diff --git a/.github/workflows/build.yaml b/.github/workflows/build.yaml index 93d108e723..ccbbac656e 100644 --- a/.github/workflows/build.yaml +++ b/.github/workflows/build.yaml @@ -11,9 +11,9 @@ jobs: name: windows-${{ matrix.platform }} runs-on: windows-2022 steps: - - uses: actions/checkout@v3 + - uses: actions/checkout@v4 - - uses: actions/cache@v3 + - uses: actions/cache@v4 id: cache-dxfiles with: path: utils/DXFiles @@ -45,16 +45,16 @@ jobs: - name: Create build artifacts run: utils\premake5 compose_files - - uses: actions/upload-artifact@master + - uses: actions/upload-artifact@v4 with: - name: InstallFiles + name: InstallFiles-${{ matrix.platform }} path: InstallFiles/ macOS: name: macOS - runs-on: macOS-latest + runs-on: macOS-13 steps: - - uses: actions/checkout@v3 + - uses: actions/checkout@v4 - name: Install MySQL run: brew install mysql @@ -80,7 +80,7 @@ jobs: container: image: docker://ghcr.io/multitheftauto/mtasa-blue-build:${{ matrix.image-tag }} steps: - - uses: actions/checkout@v3 + - uses: actions/checkout@v4 - name: Run Build run: ./linux-build.sh --arch=${{ matrix.architecture }} diff --git a/.github/workflows/dockerimage.yaml b/.github/workflows/dockerimage.yaml index a9e90f2a05..fcc2b8e4c7 100644 --- a/.github/workflows/dockerimage.yaml +++ b/.github/workflows/dockerimage.yaml @@ -12,8 +12,6 @@ on: - 'Dockerfile.i386' - 'Dockerfile.armhf' - 'Dockerfile.arm64' - - 'Dockerfile.osx-x64' - - 'Dockerfile.osx-arm64' jobs: build: @@ -28,20 +26,16 @@ jobs: dockerfile: Dockerfile.armhf - tag: arm64 dockerfile: Dockerfile.arm64 - - tag: osx-x64 - dockerfile: Dockerfile.osx-x64 - - tag: osx-arm64 - dockerfile: Dockerfile.osx-arm64 runs-on: ubuntu-latest steps: - - uses: actions/checkout@v3 - - uses: docker/setup-buildx-action@v2 - - uses: docker/login-action@v2 + - uses: actions/checkout@v4 + - uses: docker/setup-buildx-action@v3 + - uses: docker/login-action@v3 with: registry: ghcr.io username: ${{ github.repository_owner }} password: ${{ secrets.CI_PAT }} - - uses: docker/build-push-action@v3 + - uses: docker/build-push-action@v5 with: push: true file: ./${{ matrix.dockerfile }} diff --git a/.github/workflows/rebuild-pots.yaml b/.github/workflows/rebuild-pots.yaml index 51fe663494..79d97f782e 100644 --- a/.github/workflows/rebuild-pots.yaml +++ b/.github/workflows/rebuild-pots.yaml @@ -6,7 +6,7 @@ jobs: test: runs-on: ubuntu-latest steps: - - uses: actions/checkout@v3 + - uses: actions/checkout@v4 with: ref: ${{ github.head_ref }} - uses: conda-incubator/setup-miniconda@v2 @@ -26,7 +26,7 @@ jobs: runs-on: ubuntu-latest needs: test steps: - - uses: actions/checkout@v3 + - uses: actions/checkout@v4 with: ref: ${{ github.head_ref }} token: ${{ secrets.POT_CI_PAT }} diff --git a/.github/workflows/sync-master-to-maetro.yaml b/.github/workflows/sync-master-to-maetro.yaml index bdf4122ff6..e86d59ab1f 100644 --- a/.github/workflows/sync-master-to-maetro.yaml +++ b/.github/workflows/sync-master-to-maetro.yaml @@ -9,7 +9,7 @@ jobs: sync-master-to-maetro: runs-on: ubuntu-latest steps: - - uses: actions/checkout@v3 + - uses: actions/checkout@v4 with: fetch-depth: 0 token: ${{ secrets.SYNC_CI_PAT }} @@ -36,6 +36,10 @@ jobs: git checkout --ours -- "Shared/data/MTA San Andreas/MTA/d3dcompiler_47.dll" git add --verbose "Shared/data/MTA San Andreas/MTA/d3dcompiler_47.dll" + # Discard cefweb conflicts + git checkout --ours -- Client/cefweb/CWebView.cpp + git add --verbose Client/cefweb/CWebView.cpp + git checkout --ours -- "Client/loader/MainFunctions.cpp" git add --verbose "Client/loader/MainFunctions.cpp" diff --git a/CONTRIBUTING.md b/CONTRIBUTING.md index 2de2386d7d..a6b9aadfe9 100644 --- a/CONTRIBUTING.md +++ b/CONTRIBUTING.md @@ -1,192 +1 @@ -# Contributors Guide - -So you've decided to become a contributor to our project. Excellent! - -We are always looking for new developers, so if you're new, -please check out our [Getting Started guide](https://wiki.multitheftauto.com/wiki/Coding_info). - -But before we can start accepting your code, there are a couple of -things you should know about how we work. - -This document mostly contains guidelines and rules as to how your -code should be structured and how it can be committed without -upsetting any fellow contributors. - -## Where to code - -As a new potential contributor, you will need to fork our repository and make -commits to your own "branch". Then you can send us a pull request. - -Our _`master`_ branch is the main development branch containing the -latest, bleeding-edge code. - -Our _other_ branches contain groundbreaking research, radical ideas and other -work-in-progress changes that are meant to be merged into `master` at -a later point in time. - -If you're a collaborator, it's your choice whether to push branches to this -repository or to your own fork. - -**Branches are "topical" and should not be "personal" to each -user.** This means that a branch should be created for a new feature, -not for a user specific playground. - -## What to code - -Generally, please try submit pull requests that resolve existing -[issues](https://github.com/multitheftauto/mtasa-blue/issues). - -If you're looking for something to work on, take a look at the ["good first issue"] -label, or our [milestones]. - -["good first issue"]: https://github.com/multitheftauto/mtasa-blue/issues?q=is%3Aissue+is%3Aopen+sort%3Aupdated-desc+label%3A%22good+first+issue%22 -[milestones]: https://github.com/multitheftauto/mtasa-blue/milestones?direction=asc&sort=due_date - -Of course, if you're interested in something else, feel free to experiment -and submit it. But discussing the feature beforehand, in an issue, will -make your pull request more likely to be merged in a timely fashion. - -## Committing code - -**Make sure your code contributions follow the [Style Guide]**. - -[Style Guide]: https://github.com/multitheftauto/mtasa-blue/wiki/Style-Guide - -**Commits should be tested when added to master.** Commits -that 'need to be fixed later' which directly affect the state of -the mod will be reverted other than in exceptional circumstances. - -**Commit messages should** - -- be consistent -- always give a clear indication of what has been changed without having to look at the code -- include issue numbers, using [GitHub keywords](https://help.github.com/en/github/managing-your-work-on-github/linking-a-pull-request-to-an-issue#linking-a-pull-request-to-an-issue-using-a-keyword) where necessary -- [follow the seven rules identified here](http://chris.beams.io/posts/git-commit/) - -The most important of the [seven rules](http://chris.beams.io/posts/git-commit/) has been copied below, but please read the article: - -1. Separate subject from body with a blank line -2. Limit the subject line to around 60-80 characters (the [seven rules] say 50, but we think ~70 is okay) -3. Use the imperative mood in the subject line -4. Use the body to explain what and why vs. how - -**Follow up (addendum) commits should refer to the previous commit.** Do this by -including the previous commit-identifier SHA and, if there's space, a summarised commit message in -the new commit message. Doing this will help identify related commits -if they are viewed at a later date. - -**Try to keep pull requests small — they should be about one thing.** When you do multiple things -in one pull request, it's hard to review. If you're fixing stuff as you go, you might want -to make atomic commits and then cherry-pick those commits into separate branches, -leaving the pull request clean. - -**Read the ["Code Review"] guide** for more guidelines about the code review process. - -**Examples**. Here are some examples of commit messages with a short and descriptive title in the imperative mood. - -1. Here we also have a description that explains the content of the commit. - ``` - Fix vehicle model memory leaks in engineReplaceModel - - Fixed 3 memory leaks: - - clump model leak - - vehicle visual data (dummies) leak - - engineReplaceModel added extra references to TXD, and this was not getting unloaded at times - ``` - -2. Here we have a longer description that explains how to use the feature. The body is wrapped at 72 characters. - ``` - Add "beta" CVAR "_beta_qc_rightclick_command" - - This variable lets you execute a command of your choice when you right - click the "quick connect" button. - - By default this CVAR is set to "reconnect", but you can set it to - anything - "connect orange.mtasa.com" or "nick timw0w". - - In the console, type "_beta_qc_rightclick_command" and press enter. This - will tell you the current value of the CVAR. - - You can do "_beta_qc_rightclick_command=nick timw0w" to change the - value of the CVAR. - ``` - -3. Here we say `Fix #1115` so that GitHub automatically closes issue #1115. There's no description. - ``` - Fix #1115: add async encode/decodeString - ``` - -4. There was no specific issue being fixed here, but GitHub's squash-merge feature automatically appended `(#1177)`, - telling us which pull request created this commit. There's no description. - ``` - Add "remember this option" checkbox to NVidia Optimus dialog (#1177) - ``` - -5. Here we refer to a previous commit. - ``` - Addendum to a80f8d6: fix Windows build error - ``` - -## Reviewing code - -Contributors should try to review other contributor's commits and provide -feedback as much as possible. - -Please read our ["Code Review"] article for information on how to review code effectively. - -["Code Review"]: https://github.com/multitheftauto/mtasa-blue/wiki/Code-Review - - - -## Gaining and losing merge rights - -Merge rights allow you to merge your own approved pull requests and -review other people's pull requests. - -We grant merge rights after you have proven yourself to be competent, -which is generally after 3-5 pull requests. This is not fixed and depends -on the extent of your contributions, community status and other factors. - -The subject matter of your pull requests do not matter — we are more interested in, -once granted merge rights, whether you are capable of maintaining -a high standard of code and remaining cohesive with other project collaborators. - -After gaining merge rights, if your contributions are of a consistently low standard, -or you fail to stick to the rules, your permissions will be revoked. - -## Merging pull requests - -Before merging, enforced by GitHub's branch protection, pull requests **require**: -- Linux and Windows status checks to pass -- 1 pull request review - -If the pull request is large, try and only merge if there at least 2 pull request reviews. -This isn't enforced via branch protection, but please try and stick to this convention -(... unless nobody else is reviewing your PR). - -Branch protection is **not enforced** for repository administrators, -and those people are therefore not required to send pull requests. Individual repository admins may, -for the greater good, pledge to submit pull requests despite this lack of enforcement. - -For informational purposes, the current repository administrators are those marked as _The MTA Team_ on -[this list](https://forum.mtasa.com/staff/). - -**Merge button** - -Generally use the "Squash and merge" button. If multiple commits are needed because you think -having the separate commits are useful, use "Rebase and merge". +This information is now available at [mtasa-docs (mtasa-blue CONTRIBUTING.md)](https://github.com/multitheftauto/mtasa-docs/blob/main/mtasa-blue/CONTRIBUTING.md). diff --git a/Client/cefweb/CWebCore.cpp b/Client/cefweb/CWebCore.cpp index de21171949..fe02e029a3 100644 --- a/Client/cefweb/CWebCore.cpp +++ b/Client/cefweb/CWebCore.cpp @@ -71,7 +71,6 @@ bool CWebCore::Initialise() #else CefString(&settings.browser_subprocess_path).FromWString(FromUTF8(CalcMTASAPath("MTA\\CEF\\CEFLauncher_d.exe"))); #endif - CefString(&settings.resources_dir_path).FromWString(FromUTF8(CalcMTASAPath("MTA\\CEF"))); CefString(&settings.cache_path).FromWString(FromUTF8(CalcMTASAPath("MTA\\CEF\\cache"))); CefString(&settings.locales_dir_path).FromWString(FromUTF8(CalcMTASAPath("MTA\\CEF\\locales"))); CefString(&settings.log_file).FromWString(FromUTF8(CalcMTASAPath("MTA\\CEF\\cefdebug.txt"))); diff --git a/Client/cefweb/CWebView.cpp b/Client/cefweb/CWebView.cpp index e4e4e3ba20..ef3f016e7c 100644 --- a/Client/cefweb/CWebView.cpp +++ b/Client/cefweb/CWebView.cpp @@ -410,7 +410,7 @@ bool CWebView::SetAudioVolume(float fVolume) for (auto& name : frameNames) { - auto frame = m_pWebView->GetFrame(name); + auto frame = m_pWebView->GetFrameByName(name); frame->ExecuteJavaScript(strJSCode, "", 0); } m_fVolume = fVolume; @@ -996,8 +996,9 @@ bool CWebView::OnJSDialog(CefRefPtr browser, const CefString& origin // // // // //////////////////////////////////////////////////////////////////// -bool CWebView::OnFileDialog(CefRefPtr browser, CefDialogHandler::FileDialogMode mode, const CefString& title, const CefString& default_file_path, - const std::vector& accept_filters, CefRefPtr callback) +bool CWebView::OnFileDialog(CefRefPtr browser, FileDialogMode mode, const CefString& title, const CefString& default_file_path, + const std::vector& accept_filters, const std::vector& accept_extensions, const std::vector& accept_descriptions, + CefRefPtr callback) { // Don't show the dialog return true; diff --git a/Client/cefweb/CWebView.h b/Client/cefweb/CWebView.h index 69fa691d3a..0c9589d6c9 100644 --- a/Client/cefweb/CWebView.h +++ b/Client/cefweb/CWebView.h @@ -164,8 +164,9 @@ class CWebView : public CWebViewInterface, bool& suppress_message) override; // CefDialogHandler methods - virtual bool OnFileDialog(CefRefPtr browser, CefDialogHandler::FileDialogMode mode, const CefString& title, const CefString& default_file_path, - const std::vector& accept_filters, CefRefPtr callback) override; + virtual bool OnFileDialog(CefRefPtr browser, FileDialogMode mode, const CefString& title, const CefString& default_file_path, + const std::vector& accept_filters, const std::vector& accept_extensions, const std::vector& accept_descriptions, + CefRefPtr callback) override; // CefDisplayHandler methods virtual void OnTitleChange(CefRefPtr browser, const CefString& title) override; diff --git a/Client/core/CChat.cpp b/Client/core/CChat.cpp index 4a66d2907b..438ea577fe 100644 --- a/Client/core/CChat.cpp +++ b/Client/core/CChat.cpp @@ -1117,6 +1117,11 @@ void CChat::SetCharacterLimit(int charLimit) m_iCharacterLimit = charLimit; } +float CChat::GetChatBottomPosition() const noexcept +{ + return m_vecBackgroundSize.fY; +} + CChatLine::CChatLine() { m_bActive = false; diff --git a/Client/core/CChat.h b/Client/core/CChat.h index 5316086170..e967127075 100644 --- a/Client/core/CChat.h +++ b/Client/core/CChat.h @@ -207,6 +207,8 @@ class CChat constexpr int GetDefaultCharacterLimit() const { return m_iDefaultCharacterLimit; } constexpr int GetMaxCharacterLimit() const { return m_iMaxCharacterLimit; } + float GetChatBottomPosition() const noexcept; + private: void LoadCVars(); diff --git a/Client/core/CClientVariables.cpp b/Client/core/CClientVariables.cpp index 8da2b92edf..25ed032338 100644 --- a/Client/core/CClientVariables.cpp +++ b/Client/core/CClientVariables.cpp @@ -354,7 +354,9 @@ void CClientVariables::LoadDefaults() DEFAULT("browser_remote_javascript", true); // Execute javascript on remote websites? DEFAULT("filter_duplicate_log_lines", true); // Filter duplicate log lines for debug view and clientscript.log DEFAULT("always_show_transferbox", false); // Should the transfer box always be visible for downloads? (and ignore scripted control) - DEFAULT("allow_discord_rpc", true); // Enable Discord Rich Presence + DEFAULT("allow_discord_rpc", true); // Enable Discord Rich Presence + DEFAULT("discord_rpc_share_data", false); // Consistent Rich Presence data sharing + DEFAULT("discord_rpc_share_data_firsttime", false); // Display the user data sharing consent dialog box - for the first time DEFAULT("_beta_qc_rightclick_command", _S("reconnect")); // Command to run when right clicking quick connect (beta - can be removed at any time) DEFAULT("use_new_cegui", 0); // Should we use the new CEGUI 0.8.7? (for testing / development only) diff --git a/Client/core/CCommands.cpp b/Client/core/CCommands.cpp index bec794abbe..fecc85c3c6 100644 --- a/Client/core/CCommands.cpp +++ b/Client/core/CCommands.cpp @@ -125,6 +125,7 @@ bool CCommands::Execute(const char* szCommand, const char* szParametersIn, bool // Grab the command tagCOMMANDENTRY* pEntry = Get(szCommand); + bool wasHandled = false; if (pEntry) { // If its a core command, or if its enabled @@ -133,7 +134,8 @@ bool CCommands::Execute(const char* szCommand, const char* szParametersIn, bool // Execute it if (!bIsScriptedBind || pEntry->bAllowScriptedBind) ExecuteHandler(pEntry->pfnCmdFunc, szParameters); - return true; + + wasHandled = true; } } @@ -141,6 +143,7 @@ bool CCommands::Execute(const char* szCommand, const char* szParametersIn, bool std::string val = std::string(szCommand) + " " + std::string(szParameters ? szParameters : ""); // Is it a cvar? (syntax: cvar[ = value]) + if (!wasHandled) { // Check to see if '=' exists unsigned int nOpIndex = val.find('='); @@ -188,7 +191,7 @@ bool CCommands::Execute(const char* szCommand, const char* szParametersIn, bool // HACK: if its a 'nick' command, save it here bool bIsNickCommand = !stricmp(szCommand, "nick"); - if (bIsNickCommand && szParameters && !bIsScriptedBind) + if (!wasHandled && bIsNickCommand && szParameters && !bIsScriptedBind) { if (CCore::GetSingleton().IsValidNick(szParameters)) { @@ -208,10 +211,14 @@ bool CCommands::Execute(const char* szCommand, const char* szParametersIn, bool // Try to execute the handler if (m_pfnExecuteHandler) { - if (m_pfnExecuteHandler(szCommand, szParameters, bHandleRemotely, (pEntry != NULL), bIsScriptedBind)) + bool bAllowScriptedBind = (!pEntry || pEntry->bAllowScriptedBind); + if (m_pfnExecuteHandler(szCommand, szParameters, bHandleRemotely, wasHandled, bIsScriptedBind, bAllowScriptedBind)) return true; } + if (wasHandled) + return true; + // Unknown command val = _("Unknown command or cvar: ") + szCommand; if (!bIsScriptedBind && !bIsNickCommand && pEntry == nullptr) diff --git a/Client/core/CCore.cpp b/Client/core/CCore.cpp index e82757d2f2..e52bf43479 100644 --- a/Client/core/CCore.cpp +++ b/Client/core/CCore.cpp @@ -1801,6 +1801,19 @@ void CCore::UpdateRecentlyPlayed() CCore::GetSingleton().SaveConfig(); } +void CCore::OnPostColorFilterRender() +{ + if (!CGraphics::GetSingleton().HasLine3DPostFXQueueItems() && !CGraphics::GetSingleton().HasPrimitive3DPostFXQueueItems()) + return; + + CGraphics::GetSingleton().EnteringMTARenderZone(); + + CGraphics::GetSingleton().DrawPrimitive3DPostFXQueue(); + CGraphics::GetSingleton().DrawLine3DPostFXQueue(); + + CGraphics::GetSingleton().LeavingMTARenderZone(); +} + void CCore::ApplyCoreInitSettings() { #if (_WIN32_WINNT >= _WIN32_WINNT_LONGHORN) // Windows Vista @@ -1870,6 +1883,13 @@ void CCore::RecalculateFrameRateLimit(uint uiServerFrameRateLimit, bool bLogToCo if ((m_uiFrameRateLimit == 0 || uiClientScriptRate < m_uiFrameRateLimit) && uiClientScriptRate > 0) m_uiFrameRateLimit = uiClientScriptRate; + // Removes Limiter from Frame Graph if limit is zero and skips frame limit + if (m_uiFrameRateLimit == 0) + { + m_bQueuedFrameRateValid = false; + GetGraphStats()->RemoveTimingPoint("Limiter"); + } + // Print new limits to the console if (bLogToConsole) { @@ -2008,16 +2028,12 @@ void CCore::OnDeviceRestore() // void CCore::OnPreFxRender() { - // Don't do nothing if nothing won't be drawn - - if (CGraphics::GetSingleton().HasPrimitive3DPreGUIQueueItems()) - CGraphics::GetSingleton().DrawPrimitive3DPreGUIQueue(); - - if (!CGraphics::GetSingleton().HasLine3DPreGUIQueueItems()) - return; + if (!CGraphics::GetSingleton().HasLine3DPreGUIQueueItems() && !CGraphics::GetSingleton().HasPrimitive3DPreGUIQueueItems()) + return; CGraphics::GetSingleton().EnteringMTARenderZone(); + CGraphics::GetSingleton().DrawPrimitive3DPreGUIQueue(); CGraphics::GetSingleton().DrawLine3DPreGUIQueue(); CGraphics::GetSingleton().LeavingMTARenderZone(); @@ -2028,9 +2044,7 @@ void CCore::OnPreFxRender() // void CCore::OnPreHUDRender() { - IDirect3DDevice9* pDevice = CGraphics::GetSingleton().GetDevice(); - - CGraphics::GetSingleton().EnteringMTARenderZone(); + CGraphics::GetSingleton().EnteringMTARenderZone(); // Maybe capture screen and other stuff CGraphics::GetSingleton().GetRenderItemManager()->DoPulse(); @@ -2188,11 +2202,6 @@ CModelCacheManager* CCore::GetModelCacheManager() return m_pModelCacheManager; } -void CCore::AddModelToPersistentCache(ushort usModelId) -{ - return GetModelCacheManager()->AddModelToPersistentCache(usModelId); -} - void CCore::StaticIdleHandler() { g_pCore->IdleHandler(); diff --git a/Client/core/CCore.h b/Client/core/CCore.h index c0504037e2..8486d7333d 100644 --- a/Client/core/CCore.h +++ b/Client/core/CCore.h @@ -256,7 +256,6 @@ class CCore : public CCoreInterface, public CSingleton EDiagnosticDebugType GetDiagnosticDebug(); void SetDiagnosticDebug(EDiagnosticDebugType value); CModelCacheManager* GetModelCacheManager(); - void AddModelToPersistentCache(ushort usModelId); static void StaticIdleHandler(); void IdleHandler(); @@ -292,6 +291,8 @@ class CCore : public CCoreInterface, public CSingleton const SString& GetLastConnectedServerName() const { return m_strLastConnectedServerName; } void SetLastConnectedServerName(const SString& strServerName) { m_strLastConnectedServerName = strServerName; } + void OnPostColorFilterRender() override; + private: void ApplyCoreInitSettings(); diff --git a/Client/core/CDiscordRichPresence.cpp b/Client/core/CDiscordRichPresence.cpp index 61767ff9a2..a759a46557 100644 --- a/Client/core/CDiscordRichPresence.cpp +++ b/Client/core/CDiscordRichPresence.cpp @@ -36,6 +36,7 @@ CDiscordRichPresence::~CDiscordRichPresence() void CDiscordRichPresence::InitializeDiscord() { + std::lock_guard lock(m_threadSafetyMutex); DiscordEventHandlers handlers; memset(&handlers, 0, sizeof(handlers)); @@ -51,9 +52,6 @@ void CDiscordRichPresence::InitializeDiscord() void CDiscordRichPresence::ShutdownDiscord() { - if (!m_bDiscordRPCEnabled) - return; - Discord_ClearPresence(); Discord_Shutdown(); @@ -62,9 +60,6 @@ void CDiscordRichPresence::ShutdownDiscord() void CDiscordRichPresence::RestartDiscord() { - if (!m_bDiscordRPCEnabled) - return; - ShutdownDiscord(); InitializeDiscord(); } @@ -99,12 +94,19 @@ void CDiscordRichPresence::SetDefaultData() void CDiscordRichPresence::UpdatePresence() { + if (!m_bDiscordRPCEnabled) + return; + // run callbacks Discord_RunCallbacks(); + if (!m_bConnected) + return; + if (!m_bUpdateRichPresence) return; - + + std::lock_guard lock(m_threadSafetyMutex); DiscordRichPresence discordPresence; memset(&discordPresence, 0, sizeof(discordPresence)); @@ -121,7 +123,7 @@ void CDiscordRichPresence::UpdatePresence() discordPresence.endTimestamp = m_uiDiscordAppEnd; discordPresence.instance = 0; - DiscordButton buttons[2]; + DiscordButton buttons[2]{0}; if (m_aButtons) { buttons[0].label = std::get<0>(*m_aButtons).first.c_str(); @@ -264,16 +266,6 @@ bool CDiscordRichPresence::SetDiscordRPCEnabled(bool bEnabled) return true; } -bool CDiscordRichPresence::IsDiscordRPCEnabled() const -{ - return m_bDiscordRPCEnabled; -} - -bool CDiscordRichPresence::IsDiscordCustomDetailsDisallowed() const -{ - return m_bDisallowCustomDetails; -} - void CDiscordRichPresence::SetPresencePartySize(int iSize, int iMax, bool bCustom) { if (bCustom) @@ -288,6 +280,20 @@ void CDiscordRichPresence::SetPresencePartySize(int iSize, int iMax, bool bCusto } } +void CDiscordRichPresence::SetDiscordUserID(const std::string& strUserID) +{ + if (CVARS_GET_VALUE("discord_rpc_share_data")) + m_strDiscordUserID = strUserID; +} + +std::string CDiscordRichPresence::GetDiscordUserID() const +{ + if (CVARS_GET_VALUE("discord_rpc_share_data")) + return m_strDiscordUserID; + + return {}; +}; + #ifdef DISCORD_DISABLE_IO_THREAD void CDiscordRichPresence::UpdatePresenceConnection() { @@ -298,7 +304,10 @@ void CDiscordRichPresence::UpdatePresenceConnection() void CDiscordRichPresence::HandleDiscordReady(const DiscordUser* pDiscordUser) { if (const auto discord = g_pCore->GetDiscord(); discord && discord->IsDiscordRPCEnabled()) + { discord->SetDiscordClientConnected(true); + discord->SetDiscordUserID(pDiscordUser->userId); + } } void CDiscordRichPresence::HandleDiscordDisconnected(int iErrorCode, const char* szMessage) @@ -306,15 +315,13 @@ void CDiscordRichPresence::HandleDiscordDisconnected(int iErrorCode, const char* WriteDebugEvent(SString("[DISCORD] Disconnected %s (error #%d)", szMessage, iErrorCode)); if (const auto discord = g_pCore->GetDiscord(); discord) + { + discord->SetDiscordUserID(""); discord->SetDiscordClientConnected(false); + } } void CDiscordRichPresence::HandleDiscordError(int iErrorCode, const char* szMessage) { WriteDebugEvent(SString("[DISCORD] Error: %s (error #%d)", szMessage, iErrorCode)); } - -bool CDiscordRichPresence::IsDiscordClientConnected() const -{ - return m_bConnected; -} diff --git a/Client/core/CDiscordRichPresence.h b/Client/core/CDiscordRichPresence.h index 595e598b1d..d20bfa38bf 100644 --- a/Client/core/CDiscordRichPresence.h +++ b/Client/core/CDiscordRichPresence.h @@ -23,37 +23,40 @@ class CDiscordRichPresence : public CDiscordInterface void ShutdownDiscord(); void RestartDiscord(); void SetDefaultData(); - void UpdatePresence(); +#ifdef DISCORD_DISABLE_IO_THREAD + void UpdatePresenceConnection(); +#endif + void SetPresenceStartTimestamp(const unsigned long ulStart); void SetPresenceEndTimestamp(const unsigned long ulEnd); void SetAsset(const char* szAsset, const char* szAssetText, bool bIsLarge); void SetAssetLargeData(const char* szAsset, const char* szAssetText); void SetAssetSmallData(const char* szAsset, const char* szAssetText); + void SetDiscordClientConnected(bool bConnected) { m_bConnected = bConnected; }; + void SetPresencePartySize(int iSize, int iMax, bool bCustom); + void SetDiscordUserID(const std::string& strUserID); bool ResetDiscordData(); bool SetPresenceState(const char* szState, bool bCustom); bool SetPresenceDetails(const char* szDetails, bool bCustom); bool SetPresenceButtons(unsigned short int iIndex, const char* szName, const char* szUrl); - void SetPresencePartySize(int iSize, int iMax, bool bCustom); bool SetDiscordRPCEnabled(bool bEnabled); - bool IsDiscordCustomDetailsDisallowed() const; - bool IsDiscordRPCEnabled() const; bool SetApplicationID(const char* resourceName, const char* szAppID); - void SetDiscordClientConnected(bool bConnected) { m_bConnected = bConnected; }; - bool IsDiscordClientConnected() const; + bool IsDiscordCustomDetailsDisallowed() const { return m_bDisallowCustomDetails; }; + bool IsDiscordRPCEnabled() const { return m_bDiscordRPCEnabled; }; + bool IsDiscordClientConnected() const { return m_bConnected; }; + std::string GetDiscordResourceName() const { return m_strDiscordCustomResourceName; }; + std::string GetDiscordUserID() const; - // handlers + // static handlers static void HandleDiscordReady(const struct DiscordUser* pDiscordUser); static void HandleDiscordDisconnected(int iErrorCode, const char* szMessage); static void HandleDiscordError(int iErrorCode, const char* szMessage); -#ifdef DISCORD_DISABLE_IO_THREAD - void UpdatePresenceConnection(); -#endif - private: + std::string m_strDiscordUserID; std::string m_strDiscordAppId; std::string m_strDiscordAppAsset; std::string m_strDiscordAppAssetText; @@ -69,6 +72,8 @@ class CDiscordRichPresence : public CDiscordInterface std::optional, std::pair>> m_aButtons; + std::mutex m_threadSafetyMutex; + unsigned long m_uiDiscordAppStart; unsigned long m_uiDiscordAppEnd; diff --git a/Client/core/CGUI.cpp b/Client/core/CGUI.cpp index f37dc5eb19..d6f1a552b7 100644 --- a/Client/core/CGUI.cpp +++ b/Client/core/CGUI.cpp @@ -457,6 +457,11 @@ CChat* CLocalGUI::GetChat() return m_pChat; } +float CLocalGUI::GetChatBottomPosition() const noexcept +{ + return m_pChat->GetChatBottomPosition(); +} + CDebugView* CLocalGUI::GetDebugView() { return m_pDebugView; diff --git a/Client/core/CGUI.h b/Client/core/CGUI.h index 39d7921bba..f667082844 100644 --- a/Client/core/CGUI.h +++ b/Client/core/CGUI.h @@ -68,6 +68,7 @@ class CLocalGUI : public CSingleton bool IsMainMenuVisible(); CChat* GetChat(); + float GetChatBottomPosition() const noexcept; void SetChatBoxVisible(bool bVisible, bool bInputBlocked = true); bool IsChatBoxVisible(); bool IsChatBoxInputBlocked(); diff --git a/Client/core/CGraphStats.cpp b/Client/core/CGraphStats.cpp index eb6284ff15..bf53a0f91e 100644 --- a/Client/core/CGraphStats.cpp +++ b/Client/core/CGraphStats.cpp @@ -12,8 +12,6 @@ namespace { - #define GRAPHSTAT_HISTORY_SIZE 256 - struct SGraphStatLine { TIMEUS prevData; @@ -41,6 +39,7 @@ class CGraphStats : public CGraphStatsInterface virtual void SetEnabled(bool bEnabled); virtual bool IsEnabled(); virtual void AddTimingPoint(const char* szName); + virtual void RemoveTimingPoint(const char* szName); protected: bool m_bEnabled; @@ -113,6 +112,11 @@ void CGraphStats::AddTimingPoint(const char* szName) if (!IsEnabled()) return; + CGraphicsInterface* pGraphics = g_pCore->GetGraphics(); + + std::uint32_t viewportWidth = pGraphics->GetViewportWidth(); + std::uint32_t sizeX = viewportWidth / 4; // one quarter of screen width + // Start of next frame? if (szName[0] == 0) { @@ -133,7 +137,7 @@ void CGraphStats::AddTimingPoint(const char* szName) for (int i = 0; i < Dups; i++) { pLine->iDataPos++; - if (pLine->iDataPos > GRAPHSTAT_HISTORY_SIZE - 1) + if (pLine->iDataPos > sizeX - 1) pLine->iDataPos = 0; pLine->dataHistory[pLine->iDataPos] = Data; } @@ -153,7 +157,7 @@ void CGraphStats::AddTimingPoint(const char* szName) // Add new line MapSet(m_LineList, szName, SGraphStatLine()); pLine = MapFind(m_LineList, szName); - pLine->dataHistory.resize(GRAPHSTAT_HISTORY_SIZE); + pLine->dataHistory.resize(sizeX); memset(&pLine->dataHistory[0], 0, pLine->dataHistory.size()); pLine->iDataPos = 0; pLine->prevData = 0; @@ -179,13 +183,28 @@ void CGraphStats::AddTimingPoint(const char* szName) // Inc position pLine->iDataPos++; - if (pLine->iDataPos > GRAPHSTAT_HISTORY_SIZE - 1) + if (pLine->iDataPos > sizeX - 1) pLine->iDataPos = 0; // Insert data point pLine->dataHistory[pLine->iDataPos] = AvgData; } +/////////////////////////////////////////////////////////////// +// +// CGraphStats::RemoveTimingPoint +// +// +// +/////////////////////////////////////////////////////////////// +void CGraphStats::RemoveTimingPoint(const char* szName) +{ + if (!IsEnabled() || szName[0] == 0) + return; + + MapRemove(m_LineList, szName); +} + /////////////////////////////////////////////////////////////// // // CGraphStats::Draw @@ -199,29 +218,34 @@ void CGraphStats::Draw() return; CGraphicsInterface* pGraphics = g_pCore->GetGraphics(); + CLocalGUI* pLocalGUI = g_pCore->GetLocalGUI(); + + std::uint32_t viewportWidth = pGraphics->GetViewportWidth(); // get width of current resolution + std::uint32_t viewportHeight = pGraphics->GetViewportHeight(); // get height of current resolution + std::uint32_t originX = 10; // offset the graph by 10 pixels from left side of screen + std::uint32_t originY = pLocalGUI->GetChatBottomPosition(); // get chat bottom screen position + std::uint32_t sizeX = viewportWidth / 4; // set the width of graph to 1/4 of current resolution + std::uint32_t sizeY = viewportHeight / 4; // set the height of graph to 1/4 of current resolution + std::uint32_t rangeY = 100; // 100ms + + originY = originY + sizeY + 30; // add graph height plus a little gap to the overall Y position - uint uiViewportHeight = pGraphics->GetViewportHeight(); - uint uiOriginX = 10; - uint uiOriginY = std::min(500, uiViewportHeight - 10); - uint uiSizeX = GRAPHSTAT_HISTORY_SIZE; - uint uiSizeY = 150; - uint uiRangeY = 100; // 100ms - float fLineScale = 1 / 1000.f / uiRangeY * uiSizeY; + float fLineScale = 1 / 1000.f / rangeY * sizeY; float fLineHeight = pGraphics->GetDXFontHeight(); // Backgroung box - pGraphics->DrawRectQueued(uiOriginX, uiOriginY - uiSizeY, uiSizeX, uiSizeY, SColorRGBA(0, 0, 0, 128), true); + pGraphics->DrawRectQueued(originX, originY - sizeY, sizeX, sizeY, SColorRGBA(0, 0, 0, 128), true); // Draw data lines - float fLabelX = uiOriginX + uiSizeX + 22; - float fLabelY = uiOriginY - m_LineList.size() * fLineHeight; + float fLabelX = originX + sizeX + 22; + float fLabelY = originY - m_LineList.size() * fLineHeight; for (const auto& dataLine : m_LineList) { const SGraphStatLine& line = dataLine.second; int iDataPos = line.iDataPos; int iDataPosPrev = iDataPos; - for (int i = uiSizeX - 1; i > 0; i--) + for (int i = sizeX - 1; i > 0; i--) { float fY0 = line.dataHistory[iDataPos] * fLineScale; float fY1 = line.dataHistory[iDataPosPrev] * fLineScale; @@ -229,14 +253,14 @@ void CGraphStats::Draw() iDataPosPrev = iDataPos; iDataPos--; if (iDataPos == -1) - iDataPos = GRAPHSTAT_HISTORY_SIZE - 1; + iDataPos = sizeX - 1; - pGraphics->DrawLineQueued(uiOriginX + i - 1, uiOriginY - fY0, uiOriginX + i, uiOriginY - fY1, 1, line.color, true); + pGraphics->DrawLineQueued(originX + i - 1, originY - fY0, originX + i, originY - fY1, 1, line.color, true); - if (i == uiSizeX - 1) + if (i == sizeX - 1) { // Line from graph to label - pGraphics->DrawLineQueued(uiOriginX + i - 1, uiOriginY - fY0, fLabelX - 2, fLabelY + fLineHeight / 2, 1, line.color, true); + pGraphics->DrawLineQueued(originX + i - 1, originY - fY0, fLabelX - 2, fLabelY + fLineHeight / 2, 1, line.color, true); } } diff --git a/Client/core/CGraphStats.h b/Client/core/CGraphStats.h index 657bc3338c..bc152e9b15 100644 --- a/Client/core/CGraphStats.h +++ b/Client/core/CGraphStats.h @@ -23,6 +23,7 @@ class CGraphStatsInterface virtual void SetEnabled(bool bEnabled) = 0; virtual bool IsEnabled() = 0; virtual void AddTimingPoint(const char* szName) = 0; + virtual void RemoveTimingPoint(const char* szName) = 0; }; CGraphStatsInterface* GetGraphStats(); diff --git a/Client/core/CKeyBinds.cpp b/Client/core/CKeyBinds.cpp index 78b354bd00..0a1eee4a1e 100644 --- a/Client/core/CKeyBinds.cpp +++ b/Client/core/CKeyBinds.cpp @@ -841,7 +841,8 @@ CCommandBind* CKeyBinds::FindCommandMatch(const char* szKey, const char* szComma NullEmptyStrings(szKey, szArguments, szResource, szOriginalScriptKey); std::string arguments = szArguments ? szArguments : ""; - szArguments = SharedUtil::Trim(arguments.data()); + if (!arguments.empty()) + szArguments = SharedUtil::Trim(arguments.data()); for (KeyBindPtr& bind : m_binds) { diff --git a/Client/core/CMainMenu.cpp b/Client/core/CMainMenu.cpp index c2980da630..12557b128a 100644 --- a/Client/core/CMainMenu.cpp +++ b/Client/core/CMainMenu.cpp @@ -304,7 +304,6 @@ CMainMenu::CMainMenu(CGUI* pManager) discord->SetPresenceState(_("Main menu"), false); discord->SetPresenceStartTimestamp(0); } - // Store the pointer to the graphics subsystem m_pGraphics = CGraphics::GetSingletonPtr(); @@ -683,6 +682,19 @@ void CMainMenu::Update() } #endif + if (WaitForMenu == 299) + { + if (!g_pCore->GetCVars()->GetValue("discord_rpc_share_data_firsttime", false) + && g_pCore->GetCVars()->GetValue("allow_discord_rpc", false) + && !g_pCore->GetCVars()->GetValue("discord_rpc_share_data", false)) + { + m_Settings.ShowRichPresenceShareDataQuestionBox(); + CVARS_SET("discord_rpc_share_data_firsttime", true); + } + else + CVARS_SET("discord_rpc_share_data_firsttime", true); + } + if (WaitForMenu < 300) WaitForMenu++; } diff --git a/Client/core/CModelCacheManager.cpp b/Client/core/CModelCacheManager.cpp index 00c762fa80..40fa7c8ff4 100644 --- a/Client/core/CModelCacheManager.cpp +++ b/Client/core/CModelCacheManager.cpp @@ -47,7 +47,6 @@ class CModelCacheManagerImpl : public CModelCacheManager virtual void OnClientClose(); virtual void UpdatePedModelCaching(const std::map& newNeedCacheList); virtual void UpdateVehicleModelCaching(const std::map& newNeedCacheList); - virtual void AddModelToPersistentCache(ushort usModelId); virtual void SetCustomLimits(std::optional numVehicles, std::optional numPeds); // CModelCacheManagerImpl methods @@ -72,7 +71,6 @@ class CModelCacheManagerImpl : public CModelCacheManager bool m_IsUsingCustomVehicleCacheLimit{}; //< If `true` the value is set by the scripter, otherwise is calculated in `DoPulse()` std::map m_PedModelCacheInfoMap{}; std::map m_VehicleModelCacheInfoMap{}; - std::set m_PermoLoadedModels{}; }; /////////////////////////////////////////////////////////////// @@ -266,22 +264,6 @@ void CModelCacheManagerImpl::DoPulse() } } -/////////////////////////////////////////////////////////////// -// -// CModelCacheManagerImpl::AddModelToPersistentCache -// -// Keep this model around 4 evar now -// -/////////////////////////////////////////////////////////////// -void CModelCacheManagerImpl::AddModelToPersistentCache(ushort usModelId) -{ - if (!MapContains(m_PermoLoadedModels, usModelId)) - { - AddModelRefCount(usModelId); - MapInsert(m_PermoLoadedModels, usModelId); - } -} - /////////////////////////////////////////////////////////////// // // CModelCacheManagerImpl::UpdatePedModelCaching @@ -542,13 +524,5 @@ void CModelCacheManagerImpl::OnRestreamModel(ushort usModelId) OutputDebugLine(SString("[Cache] End caching model %d (OnRestreamModel)", usModelId)); } } - } - - // Also check the permo list - if (MapContains(m_PermoLoadedModels, usModelId)) - { - SubModelRefCount(usModelId); - MapRemove(m_PermoLoadedModels, usModelId); - OutputDebugLine(SString("[Cache] End permo-caching model %d (OnRestreamModel)", usModelId)); - } + } } diff --git a/Client/core/CModelCacheManager.h b/Client/core/CModelCacheManager.h index ee54cbedfe..7d7952d0b5 100644 --- a/Client/core/CModelCacheManager.h +++ b/Client/core/CModelCacheManager.h @@ -24,7 +24,6 @@ class CModelCacheManager virtual void OnClientClose() = 0; virtual void UpdatePedModelCaching(const std::map& newNeedCacheList) = 0; virtual void UpdateVehicleModelCaching(const std::map& newNeedCacheList) = 0; - virtual void AddModelToPersistentCache(ushort usModelId) = 0; virtual void SetCustomLimits(std::optional numVehicles, std::optional numPeds) = 0; }; diff --git a/Client/core/CSettings.cpp b/Client/core/CSettings.cpp index 7e7ff39e9f..5abe53d028 100644 --- a/Client/core/CSettings.cpp +++ b/Client/core/CSettings.cpp @@ -363,6 +363,18 @@ void CSettings::CreateGUI() m_pEditNick->SetMaxLength(MAX_PLAYER_NICK_LENGTH); m_pEditNick->SetTextAcceptedHandler(GUI_CALLBACK(&CSettings::OnOKButtonClick, this)); + m_pButtonGenerateNick = reinterpret_cast(pManager->CreateButton(pTabMultiplayer)); + m_pButtonGenerateNick->SetPosition(CVector2D(vecSize.fX + vecTemp.fX + 50.0f + 178.0f + 5.0f, vecTemp.fY - 1.0f), false); + m_pButtonGenerateNick->SetSize(CVector2D(26.0f, 26.0f), false); + m_pButtonGenerateNick->SetClickHandler(GUI_CALLBACK(&CSettings::OnNickButtonClick, this)); + m_pButtonGenerateNick->SetZOrderingEnabled(false); + + m_pButtonGenerateNickIcon = reinterpret_cast(pManager->CreateStaticImage(m_pButtonGenerateNick)); + m_pButtonGenerateNickIcon->SetSize(CVector2D(1, 1), true); + m_pButtonGenerateNickIcon->LoadFromFile("cgui\\images\\serverbrowser\\refresh.png"); + m_pButtonGenerateNickIcon->SetProperty("MousePassThroughEnabled", "True"); + m_pButtonGenerateNickIcon->SetProperty("DistributeCapturedInputs", "True"); + m_pSavePasswords = reinterpret_cast(pManager->CreateCheckBox(pTabMultiplayer, _("Save server passwords"), true)); m_pSavePasswords->SetPosition(CVector2D(vecTemp.fX, vecTemp.fY + 50.0f)); m_pSavePasswords->GetPosition(vecTemp, false); @@ -2940,6 +2952,12 @@ bool CSettings::OnOKButtonClick(CGUIElement* pElement) return true; } +bool CSettings::OnNickButtonClick(CGUIElement* pElement) +{ + m_pEditNick->SetText(CNickGen::GetRandomNickname()); + return true; +} + bool CSettings::OnCancelButtonClick(CGUIElement* pElement) { CMainMenu* pMainMenu = CLocalGUI::GetSingleton().GetMainMenu(); @@ -4519,10 +4537,38 @@ bool CSettings::OnAllowExternalSoundsClick(CGUIElement* pElement) // bool CSettings::OnAllowDiscordRPC(CGUIElement* pElement) { - g_pCore->GetDiscord()->SetDiscordRPCEnabled(m_pCheckBoxAllowDiscordRPC->GetSelected()); + bool isEnabled = m_pCheckBoxAllowDiscordRPC->GetSelected(); + g_pCore->GetDiscord()->SetDiscordRPCEnabled(isEnabled); + + if (isEnabled) + ShowRichPresenceShareDataQuestionBox(); // show question box + return true; } +static void ShowRichPresenceShareDataCallback(void* ptr, unsigned int uiButton) +{ + CCore::GetSingleton().GetLocalGUI()->GetMainMenu()->GetQuestionWindow()->Reset(); + + CVARS_SET("discord_rpc_share_data", static_cast(uiButton)); +} + +void CSettings::ShowRichPresenceShareDataQuestionBox() const +{ + SStringX strMessage( + _("It seems that you have the Rich Presence connection option enabled." + "\nDo you want to allow servers to share their data?" + "\n\nThis includes yours unique ID identifier.")); + CQuestionBox* pQuestionBox = CCore::GetSingleton().GetLocalGUI()->GetMainMenu()->GetQuestionWindow(); + pQuestionBox->Reset(); + pQuestionBox->SetTitle(_("CONSENT TO ALLOW DATA SHARING")); + pQuestionBox->SetMessage(strMessage); + pQuestionBox->SetButton(0, _("No")); + pQuestionBox->SetButton(1, _("Yes")); + pQuestionBox->SetCallback(ShowRichPresenceShareDataCallback); + pQuestionBox->Show(); +} + // // CustomizedSAFiles // diff --git a/Client/core/CSettings.h b/Client/core/CSettings.h index 495eb2a01b..bfeec87c44 100644 --- a/Client/core/CSettings.h +++ b/Client/core/CSettings.h @@ -119,6 +119,7 @@ class CSettings bool IsActive(); void SetSelectedIndex(unsigned int uiIndex); + void ShowRichPresenceShareDataQuestionBox() const; protected: const static int SecKeyNum = 3; // Number of secondary keys @@ -131,6 +132,8 @@ class CSettings CGUIButton* m_pButtonOK; CGUIButton* m_pButtonCancel; CGUILabel* m_pLabelNick; + CGUIButton* m_pButtonGenerateNick; + CGUIStaticImage* m_pButtonGenerateNickIcon; CGUIEdit* m_pEditNick; CGUICheckBox* m_pSavePasswords; CGUICheckBox* m_pAutoRefreshBrowser; @@ -346,6 +349,7 @@ class CSettings bool OnVideoDefaultClick(CGUIElement* pElement); bool OnBindsListClick(CGUIElement* pElement); bool OnOKButtonClick(CGUIElement* pElement); + bool OnNickButtonClick(CGUIElement* pElement); bool OnCancelButtonClick(CGUIElement* pElement); bool OnFieldOfViewChanged(CGUIElement* pElement); bool OnDrawDistanceChanged(CGUIElement* pElement); diff --git a/Client/core/CVersionUpdater.cpp b/Client/core/CVersionUpdater.cpp index e4fe77ec96..ec24655b26 100644 --- a/Client/core/CVersionUpdater.cpp +++ b/Client/core/CVersionUpdater.cpp @@ -1912,7 +1912,7 @@ void CVersionUpdater::_DialogUpdateQueryError() // Display message GetQuestionBox().Reset(); GetQuestionBox().SetTitle(_("UPDATE CHECK")); - GetQuestionBox().SetMessage(_("Update not currently avalable.\n\nPlease check www.mtasa.com")); + GetQuestionBox().SetMessage(_("An update is currently not available.\n\nPlease check www.mtasa.com")); GetQuestionBox().SetButton(0, _("OK")); GetQuestionBox().Show(); _PollAnyButton(); diff --git a/Client/core/Graphics/CGraphics.cpp b/Client/core/Graphics/CGraphics.cpp index 670cbe0944..284412415c 100644 --- a/Client/core/Graphics/CGraphics.cpp +++ b/Client/core/Graphics/CGraphics.cpp @@ -55,12 +55,16 @@ CGraphics::CGraphics(CLocalGUI* pGUI) m_pRenderItemManager = new CRenderItemManager(); m_pTileBatcher = new CTileBatcher(); m_pLine3DBatcherPreGUI = new CLine3DBatcher(true); + m_pLine3DBatcherPostFX = new CLine3DBatcher(true); m_pLine3DBatcherPostGUI = new CLine3DBatcher(false); m_pMaterialLine3DBatcherPreGUI = new CMaterialLine3DBatcher(true); + m_pMaterialLine3DBatcherPostFX = new CMaterialLine3DBatcher(true); m_pMaterialLine3DBatcherPostGUI = new CMaterialLine3DBatcher(false); m_pPrimitive3DBatcherPreGUI = new CPrimitive3DBatcher(true); + m_pPrimitive3DBatcherPostFX = new CPrimitive3DBatcher(true); m_pPrimitive3DBatcherPostGUI = new CPrimitive3DBatcher(false); m_pMaterialPrimitive3DBatcherPreGUI = new CMaterialPrimitive3DBatcher(true, this); + m_pMaterialPrimitive3DBatcherPostFX = new CMaterialPrimitive3DBatcher(true, this); m_pMaterialPrimitive3DBatcherPostGUI = new CMaterialPrimitive3DBatcher(false, this); m_pPrimitiveBatcher = new CPrimitiveBatcher(); m_pPrimitiveMaterialBatcher = new CPrimitiveMaterialBatcher(this); @@ -83,14 +87,18 @@ CGraphics::~CGraphics() SAFE_DELETE(m_pRenderItemManager); SAFE_DELETE(m_pTileBatcher); SAFE_DELETE(m_pLine3DBatcherPreGUI); + SAFE_DELETE(m_pLine3DBatcherPostFX); SAFE_DELETE(m_pLine3DBatcherPostGUI); SAFE_DELETE(m_pMaterialLine3DBatcherPreGUI); + SAFE_DELETE(m_pMaterialLine3DBatcherPostFX); SAFE_DELETE(m_pMaterialLine3DBatcherPostGUI); SAFE_DELETE(m_pPrimitiveBatcher); SAFE_DELETE(m_pPrimitiveMaterialBatcher); SAFE_DELETE(m_pPrimitive3DBatcherPreGUI); + SAFE_DELETE(m_pPrimitive3DBatcherPostFX); SAFE_DELETE(m_pPrimitive3DBatcherPostGUI); SAFE_DELETE(m_pMaterialPrimitive3DBatcherPreGUI); + SAFE_DELETE(m_pMaterialPrimitive3DBatcherPostFX); SAFE_DELETE(m_pMaterialPrimitive3DBatcherPostGUI); SAFE_DELETE(m_pScreenGrabber); SAFE_DELETE(m_pPixelsManager); @@ -207,7 +215,7 @@ void CGraphics::DrawStringOutline(const RECT& rect, unsigned long ulColor, const void CGraphics::DrawLine3D(const CVector& vecBegin, const CVector& vecEnd, unsigned long ulColor, float fWidth) { - DrawLine3DQueued(vecBegin, vecEnd, fWidth, ulColor, true); + DrawLine3DQueued(vecBegin, vecEnd, fWidth, ulColor, eRenderStage::POST_GUI); } void CGraphics::DrawRectangleInternal(float fX, float fY, float fWidth, float fHeight, unsigned long ulColor, bool bSubPixelPositioning) @@ -831,21 +839,23 @@ void CGraphics::DrawLineQueued(float fX1, float fY1, float fX2, float fY2, float AddQueueItem(Item, bPostGUI); } -void CGraphics::DrawLine3DQueued(const CVector& vecBegin, const CVector& vecEnd, float fWidth, unsigned long ulColor, bool bPostGUI) +void CGraphics::DrawLine3DQueued(const CVector& vecBegin, const CVector& vecEnd, float fWidth, unsigned long ulColor, eRenderStage stage) { if (g_pCore->IsWindowMinimized()) return; // Add it to the queue - if (bPostGUI && !CCore::GetSingleton().IsMenuVisible()) + if (stage == eRenderStage::POST_GUI && !CCore::GetSingleton().IsMenuVisible()) m_pLine3DBatcherPostGUI->AddLine3D(vecBegin, vecEnd, fWidth, ulColor); - else + else if (stage == eRenderStage::PRE_FX) m_pLine3DBatcherPreGUI->AddLine3D(vecBegin, vecEnd, fWidth, ulColor); + else + m_pLine3DBatcherPostFX->AddLine3D(vecBegin, vecEnd, fWidth, ulColor); } void CGraphics::DrawMaterialLine3DQueued(const CVector& vecBegin, const CVector& vecEnd, float fWidth, unsigned long ulColor, CMaterialItem* pMaterial, float fU, float fV, float fSizeU, float fSizeV, bool bRelativeUV, bool bFlipUV, bool bUseFaceToward, - const CVector& vecFaceToward, bool bPostGUI) + const CVector& vecFaceToward, eRenderStage stage) { if (g_pCore->IsWindowMinimized()) return; @@ -857,12 +867,15 @@ void CGraphics::DrawMaterialLine3DQueued(const CVector& vecBegin, const CVector& } // Add it to the queue - if (bPostGUI && !CCore::GetSingleton().IsMenuVisible()) + if (stage == eRenderStage::POST_GUI && !CCore::GetSingleton().IsMenuVisible()) m_pMaterialLine3DBatcherPostGUI->AddLine3D(vecBegin, vecEnd, fWidth, ulColor, pMaterial, fU, fV, fSizeU, fSizeV, bRelativeUV, bFlipUV, bUseFaceToward, vecFaceToward); - else + else if (stage == eRenderStage::PRE_FX) m_pMaterialLine3DBatcherPreGUI->AddLine3D(vecBegin, vecEnd, fWidth, ulColor, pMaterial, fU, fV, fSizeU, fSizeV, bRelativeUV, bFlipUV, bUseFaceToward, vecFaceToward); + else + m_pMaterialLine3DBatcherPostFX->AddLine3D(vecBegin, vecEnd, fWidth, ulColor, pMaterial, fU, fV, fSizeU, fSizeV, bRelativeUV, bFlipUV, bUseFaceToward, + vecFaceToward); } void CGraphics::DrawRectQueued(float fX, float fY, float fWidth, float fHeight, unsigned long ulColor, bool bPostGUI, bool bSubPixelPositioning) @@ -939,7 +952,7 @@ void CGraphics::DrawPrimitiveQueued(std::vector* pVecVertices, AddQueueItem(Item, bPostGUI); } -void CGraphics::DrawPrimitive3DQueued(std::vector* pVecVertices, D3DPRIMITIVETYPE eType, bool bPostGUI) +void CGraphics::DrawPrimitive3DQueued(std::vector* pVecVertices, D3DPRIMITIVETYPE eType, eRenderStage stage) { // Prevent queuing when minimized if (g_pCore->IsWindowMinimized()) @@ -949,14 +962,16 @@ void CGraphics::DrawPrimitive3DQueued(std::vector* pVecVertice } // Add it to the queue - if (bPostGUI && !CCore::GetSingleton().IsMenuVisible()) + if (stage == eRenderStage::POST_GUI && !CCore::GetSingleton().IsMenuVisible()) m_pPrimitive3DBatcherPostGUI->AddPrimitive(eType, pVecVertices); - else + else if (stage == eRenderStage::PRE_FX) m_pPrimitive3DBatcherPreGUI->AddPrimitive(eType, pVecVertices); + else + m_pPrimitive3DBatcherPostFX->AddPrimitive(eType, pVecVertices); } void CGraphics::DrawMaterialPrimitive3DQueued(std::vector* pVecVertices, D3DPRIMITIVETYPE eType, CMaterialItem* pMaterial, - bool bPostGUI) + eRenderStage stage) { // Prevent queuing when minimized if (g_pCore->IsWindowMinimized()) @@ -972,10 +987,13 @@ void CGraphics::DrawMaterialPrimitive3DQueued(std::vectorAddPrimitive(eType, pMaterial, pVecVertices); - else + else if (stage == eRenderStage::PRE_FX) m_pMaterialPrimitive3DBatcherPreGUI->AddPrimitive(eType, pMaterial, pVecVertices); + else + m_pMaterialPrimitive3DBatcherPostFX->AddPrimitive(eType, pMaterial, pVecVertices); + } void CGraphics::DrawMaterialPrimitiveQueued(std::vector* pVecVertices, D3DPRIMITIVETYPE eType, CMaterialItem* pMaterial, @@ -1515,14 +1533,18 @@ void CGraphics::OnDeviceCreate(IDirect3DDevice9* pDevice) m_pTileBatcher->OnDeviceCreate(pDevice, GetViewportWidth(), GetViewportHeight()); m_pLine3DBatcherPreGUI->OnDeviceCreate(pDevice, GetViewportWidth(), GetViewportHeight()); + m_pLine3DBatcherPostFX->OnDeviceCreate(pDevice, GetViewportWidth(), GetViewportHeight()); m_pLine3DBatcherPostGUI->OnDeviceCreate(pDevice, GetViewportWidth(), GetViewportHeight()); m_pMaterialLine3DBatcherPreGUI->OnDeviceCreate(pDevice, GetViewportWidth(), GetViewportHeight()); + m_pMaterialLine3DBatcherPostFX->OnDeviceCreate(pDevice, GetViewportWidth(), GetViewportHeight()); m_pMaterialLine3DBatcherPostGUI->OnDeviceCreate(pDevice, GetViewportWidth(), GetViewportHeight()); m_pPrimitiveBatcher->OnDeviceCreate(pDevice, GetViewportWidth(), GetViewportHeight()); m_pPrimitiveMaterialBatcher->OnDeviceCreate(pDevice, GetViewportWidth(), GetViewportHeight()); m_pPrimitive3DBatcherPreGUI->OnDeviceCreate(pDevice, GetViewportWidth(), GetViewportHeight()); + m_pPrimitive3DBatcherPostFX->OnDeviceCreate(pDevice, GetViewportWidth(), GetViewportHeight()); m_pPrimitive3DBatcherPostGUI->OnDeviceCreate(pDevice, GetViewportWidth(), GetViewportHeight()); m_pMaterialPrimitive3DBatcherPreGUI->OnDeviceCreate(pDevice, GetViewportWidth(), GetViewportHeight()); + m_pMaterialPrimitive3DBatcherPostFX->OnDeviceCreate(pDevice, GetViewportWidth(), GetViewportHeight()); m_pMaterialPrimitive3DBatcherPostGUI->OnDeviceCreate(pDevice, GetViewportWidth(), GetViewportHeight()); m_pRenderItemManager->OnDeviceCreate(pDevice, GetViewportWidth(), GetViewportHeight()); m_pScreenGrabber->OnDeviceCreate(pDevice); @@ -1612,6 +1634,12 @@ void CGraphics::DrawLine3DPreGUIQueue() m_pMaterialLine3DBatcherPreGUI->Flush(); } +void CGraphics::DrawLine3DPostFXQueue(void) +{ + m_pLine3DBatcherPostFX->Flush(); + m_pMaterialLine3DBatcherPostFX->Flush(); +} + void CGraphics::DrawPrimitive3DPreGUIQueue(void) { m_pPrimitive3DBatcherPreGUI->Flush(); @@ -1623,11 +1651,27 @@ bool CGraphics::HasLine3DPreGUIQueueItems(void) return m_pLine3DBatcherPreGUI->HasItems() || m_pMaterialLine3DBatcherPreGUI->HasItems(); } +bool CGraphics::HasLine3DPostFXQueueItems() +{ + return m_pLine3DBatcherPostFX->HasItems() || m_pMaterialLine3DBatcherPostFX->HasItems(); +} + +void CGraphics::DrawPrimitive3DPostFXQueue(void) +{ + m_pPrimitive3DBatcherPostFX->Flush(); + m_pMaterialPrimitive3DBatcherPostFX->Flush(); +} + bool CGraphics::HasPrimitive3DPreGUIQueueItems(void) { return m_pMaterialPrimitive3DBatcherPreGUI->HasItems() || m_pPrimitive3DBatcherPreGUI->HasItems(); } +bool CGraphics::HasPrimitive3DPostFXQueueItems() +{ + return m_pMaterialPrimitive3DBatcherPostFX->HasItems() || m_pPrimitive3DBatcherPostFX->HasItems(); +} + void CGraphics::DrawQueue(std::vector& Queue) { BeginDrawBatch(); @@ -2519,6 +2563,6 @@ void CGraphics::DrawWiredSphere(CVector vecPosition, float fRadius, SColor color { const CVector& vecBegin = model.vertexList[i] * fRadius + vecPosition; const CVector& vecEnd = model.vertexList[i + 1] * fRadius + vecPosition; - DrawLine3DQueued(vecBegin, vecEnd, fLineWidth, color, false); + DrawLine3DQueued(vecBegin, vecEnd, fLineWidth, color, eRenderStage::POST_FX); } } diff --git a/Client/core/Graphics/CGraphics.h b/Client/core/Graphics/CGraphics.h index b50093174f..05efb20241 100644 --- a/Client/core/Graphics/CGraphics.h +++ b/Client/core/Graphics/CGraphics.h @@ -135,11 +135,11 @@ class CGraphics : public CGraphicsInterface, public CSingleton // Queued up drawing funcs void DrawLineQueued(float fX1, float fY1, float fX2, float fY2, float fWidth, unsigned long ulColor, bool bPostGUI); - void DrawLine3DQueued(const CVector& vecBegin, const CVector& vecEnd, float fWidth, unsigned long ulColor, bool bPostGUI); + void DrawLine3DQueued(const CVector& vecBegin, const CVector& vecEnd, float fWidth, unsigned long ulColor, eRenderStage stage = eRenderStage::PRE_FX); void DrawMaterialLine3DQueued(const CVector& vecBegin, const CVector& vecEnd, float fWidth, unsigned long ulColor, CMaterialItem* pMaterial, float fU = 0, float fV = 0, float fSizeU = 1, float fSizeV = 1, bool bRelativeUV = true, bool bFlipUV = false, bool bUseFaceToward = false, - const CVector& vecFaceToward = CVector(), bool bPostGUI = false) override; + const CVector& vecFaceToward = CVector(), eRenderStage stage = eRenderStage::PRE_FX) override; void DrawRectQueued(float fX, float fY, float fWidth, float fHeight, unsigned long ulColor, bool bPostGUI, bool bSubPixelPositioning = false); @@ -153,8 +153,8 @@ class CGraphics : public CGraphicsInterface, public CSingleton void DrawPrimitiveQueued(std::vector* pVecVertices, D3DPRIMITIVETYPE eType, bool bPostGUI = false); void DrawMaterialPrimitiveQueued(std::vector* vertices, D3DPRIMITIVETYPE type, CMaterialItem* pMaterial, bool bPostGUI); - void DrawPrimitive3DQueued(std::vector* pVecVertices, D3DPRIMITIVETYPE eType, bool bPostGUI); - void DrawMaterialPrimitive3DQueued(std::vector* pVecVertices, D3DPRIMITIVETYPE eType, CMaterialItem* pMaterial, bool bPostGUI); + void DrawPrimitive3DQueued(std::vector* pVecVertices, D3DPRIMITIVETYPE eType, eRenderStage stage = eRenderStage::PRE_FX); + void DrawMaterialPrimitive3DQueued(std::vector* pVecVertices, D3DPRIMITIVETYPE eType, CMaterialItem* pMaterial, eRenderStage stage = eRenderStage::PRE_FX); void DrawCircleQueued(float fX, float fY, float fRadius, float fStartAngle, float fStopAngle, unsigned long ulColor, unsigned long ulColorCenter, short siSegments, float fRatio, bool bPostGUI); @@ -188,9 +188,13 @@ class CGraphics : public CGraphicsInterface, public CSingleton void DrawPreGUIQueue(void); void DrawPostGUIQueue(void); void DrawLine3DPreGUIQueue(void); + void DrawLine3DPostFXQueue(void); bool HasLine3DPreGUIQueueItems(void); + bool HasLine3DPostFXQueueItems(); + void DrawPrimitive3DPostFXQueue(void); void DrawPrimitive3DPreGUIQueue(void); bool HasPrimitive3DPreGUIQueueItems(void); + bool HasPrimitive3DPostFXQueueItems(); void DidRenderScene(); void SetProgressMessage(const SString& strMessage); @@ -226,14 +230,18 @@ class CGraphics : public CGraphicsInterface, public CSingleton CPixelsManagerInterface* m_pPixelsManager = nullptr; CTileBatcher* m_pTileBatcher = nullptr; CLine3DBatcher* m_pLine3DBatcherPreGUI = nullptr; + CLine3DBatcher* m_pLine3DBatcherPostFX = nullptr; CLine3DBatcher* m_pLine3DBatcherPostGUI = nullptr; CMaterialLine3DBatcher* m_pMaterialLine3DBatcherPreGUI = nullptr; + CMaterialLine3DBatcher* m_pMaterialLine3DBatcherPostFX = nullptr; CMaterialLine3DBatcher* m_pMaterialLine3DBatcherPostGUI = nullptr; CPrimitiveBatcher* m_pPrimitiveBatcher = nullptr; CPrimitiveMaterialBatcher* m_pPrimitiveMaterialBatcher = nullptr; CPrimitive3DBatcher* m_pPrimitive3DBatcherPreGUI = nullptr; - CPrimitive3DBatcher* m_pPrimitive3DBatcherPostGUI = nullptr; + CPrimitive3DBatcher* m_pPrimitive3DBatcherPostFX = nullptr; + CPrimitive3DBatcher* m_pPrimitive3DBatcherPostGUI = nullptr; CMaterialPrimitive3DBatcher* m_pMaterialPrimitive3DBatcherPreGUI = nullptr; + CMaterialPrimitive3DBatcher* m_pMaterialPrimitive3DBatcherPostFX = nullptr; CMaterialPrimitive3DBatcher* m_pMaterialPrimitive3DBatcherPostGUI = nullptr; CAspectRatioConverter* m_pAspectRatioConverter = nullptr; diff --git a/Client/core/Graphics/CLine3DBatcher.cpp b/Client/core/Graphics/CLine3DBatcher.cpp index 679a251a7b..6fbc53102b 100644 --- a/Client/core/Graphics/CLine3DBatcher.cpp +++ b/Client/core/Graphics/CLine3DBatcher.cpp @@ -19,9 +19,9 @@ // // //////////////////////////////////////////////////////////////// -CLine3DBatcher::CLine3DBatcher(bool bZTest) +CLine3DBatcher::CLine3DBatcher(bool bPreGUI) { - m_bZTest = bZTest; + m_bPreGUI = bPreGUI; } //////////////////////////////////////////////////////////////// @@ -80,8 +80,8 @@ void CLine3DBatcher::Flush() { const SLine3DItem& item = *iter; + const ulong ulColor = item.ulColor; const float fWidth = item.fWidth; - ulong ulColor = item.ulColor; const CVector& vecA = item.vecFrom; const CVector& vecB = item.vecTo; @@ -116,7 +116,7 @@ void CLine3DBatcher::Flush() // Set states if (g_pDeviceState->AdapterState.bRequiresClipping) m_pDevice->SetRenderState(D3DRS_CLIPPING, TRUE); - m_pDevice->SetRenderState(D3DRS_ZENABLE, m_bZTest ? D3DZB_TRUE : D3DZB_FALSE); + m_pDevice->SetRenderState(D3DRS_ZENABLE, m_bPreGUI ? D3DZB_TRUE : D3DZB_FALSE); m_pDevice->SetRenderState(D3DRS_ZFUNC, D3DCMP_LESSEQUAL); m_pDevice->SetRenderState(D3DRS_ZWRITEENABLE, FALSE); m_pDevice->SetRenderState(D3DRS_CULLMODE, D3DCULL_NONE); diff --git a/Client/core/Graphics/CLine3DBatcher.h b/Client/core/Graphics/CLine3DBatcher.h index 82e376e854..6320ab5733 100644 --- a/Client/core/Graphics/CLine3DBatcher.h +++ b/Client/core/Graphics/CLine3DBatcher.h @@ -38,7 +38,7 @@ class CLine3DBatcher { public: ZERO_ON_NEW - CLine3DBatcher(bool bZTest); + CLine3DBatcher(bool bPreGUI); ~CLine3DBatcher(); void OnDeviceCreate(IDirect3DDevice9* pDevice, float fViewportSizeX, float fViewportSizeY); @@ -47,7 +47,7 @@ class CLine3DBatcher void AddLine3D(const CVector& vecFrom, const CVector& vecTo, float fWidth, ulong ulColor); protected: - bool m_bZTest; + bool m_bPreGUI; IDirect3DDevice9* m_pDevice; std::vector m_LineList; }; diff --git a/Client/core/Graphics/CMaterialLine3DBatcher.cpp b/Client/core/Graphics/CMaterialLine3DBatcher.cpp index dcceaac89b..7f087dbce1 100644 --- a/Client/core/Graphics/CMaterialLine3DBatcher.cpp +++ b/Client/core/Graphics/CMaterialLine3DBatcher.cpp @@ -203,14 +203,7 @@ void CMaterialLine3DBatcher::DrawBatch(const CVector& vecCameraPos, uint* pBatch { const SMaterialLine3DItem& item = m_LineList[pBatchIndices[i]]; - SColor color = item.ulColor; - if (m_bPreGUI) - { - color.R /= 2; - color.G /= 2; - color.B /= 2; - } - const ulong ulColor = color; + const ulong ulColor = item.ulColor; const CVector& vecA = item.vecFrom; const CVector& vecB = item.vecTo; diff --git a/Client/core/premake5.lua b/Client/core/premake5.lua index 971e757271..0573dd6c05 100644 --- a/Client/core/premake5.lua +++ b/Client/core/premake5.lua @@ -16,7 +16,7 @@ project "Client Core" "../sdk", "../../vendor/tinygettext", "../../vendor/zlib", - "../../vendor/jpeg-9e", + "../../vendor/jpeg-9f", "../../vendor/pthreads/include", "../../vendor/sparsehash/src/", "../../vendor/detours/4.0.1/src", diff --git a/Client/game_sa/CAnimManagerSA.cpp b/Client/game_sa/CAnimManagerSA.cpp index b9e5ba9e76..d540fa16af 100644 --- a/Client/game_sa/CAnimManagerSA.cpp +++ b/Client/game_sa/CAnimManagerSA.cpp @@ -1,11 +1,11 @@ /***************************************************************************** * - * PROJECT: Multi Theft Auto v1.0 + * PROJECT: Multi Theft Auto * LICENSE: See LICENSE in the top level directory - * FILE: game_sa/CAnimManagerSA.cpp + * FILE: Client/game_sa/CAnimManagerSA.cpp * PURPOSE: Animation manager * - * Multi Theft Auto is available from http://www.multitheftauto.com/ + * Multi Theft Auto is available from https://multitheftauto.com/ * *****************************************************************************/ @@ -21,7 +21,14 @@ extern CGameSA* pGame; -using std::list; +// This "gateway" animation will allow us to play custom animations by simply playing this animation +// and then in AddAnimation and AddAnimationAndSync hook, we can return our custom animation in the +// hook instead of run_wuzi. This will trick GTA SA into thinking that it is playing run_wuzi from +// ped block, but in reality, it's playing our custom animation, and Of course, we can return run_wuzi +// animation within the hook if we want to play it instead. Why run_wuzi? We can also use another animation, +// but I've tested with this one mostly, so let's stick to this. +static const char* const kGateWayBlockName = "ped"; +static const char* const kGateWayAnimationName = "run_wuzi"; CAnimManagerSA::CAnimManagerSA() { @@ -195,7 +202,7 @@ int CAnimManagerSA::RegisterAnimBlock(const char* szName) return iReturn; } -std::unique_ptr CAnimManagerSA::GetAnimBlendAssoc(AssocGroupId groupID) +std::unique_ptr CAnimManagerSA::GetAnimBlendAssoc(AssocGroupId groupID) const { CAnimBlendAssocGroupSAInterface* pInterface = nullptr; DWORD dwFunc = FUNC_CAnimManager_GetAnimBlendAssoc; @@ -274,8 +281,12 @@ std::unique_ptr CAnimManagerSA::CreateAnimAssociation(Ass return nullptr; } -CAnimManagerSA::StaticAssocIntface_type CAnimManagerSA::GetAnimStaticAssociation(eAnimGroup animGroup, eAnimID animID) +CAnimManagerSA::StaticAssocIntface_type CAnimManagerSA::GetAnimStaticAssociation(eAnimGroup animGroup, eAnimID animID) const { + // We check the validity of the group, avoid crashes due to an invalid group + if (!IsValidGroup(static_cast(animGroup))) + return nullptr; + CAnimBlendStaticAssociationSAInterface* pInterface = nullptr; DWORD dwFunc = FUNC_CAnimManager_GetAnimAssociation; _asm @@ -295,6 +306,10 @@ CAnimManagerSA::StaticAssocIntface_type CAnimManagerSA::GetAnimStaticAssociation std::unique_ptr CAnimManagerSA::GetAnimAssociation(AssocGroupId animGroup, const char* szAnimName) { + // We check the validity of the group, avoid crashes due to an invalid group + if (!IsValidGroup(animGroup)) + return nullptr; + CAnimBlendAssociationSAInterface* pInterface = nullptr; DWORD dwFunc = FUNC_CAnimManager_GetAnimAssociation_str; _asm @@ -363,7 +378,7 @@ std::unique_ptr CAnimManagerSA::AddAnimationAndSync(RpClu AnimationId animID) { if (!pClump) - return NULL; + return nullptr; CAnimBlendAssociationSAInterface* pInterface = nullptr; DWORD dwFunc = FUNC_CAnimManager_AddAnimationAndSync; @@ -387,8 +402,8 @@ std::unique_ptr CAnimManagerSA::AddAnimationAndSync(RpClu std::unique_ptr CAnimManagerSA::BlendAnimation(RpClump* pClump, AssocGroupId animGroup, AnimationId animID, float fBlendDelta) { - if (!pClump) - return NULL; + if (!pClump || !IsValidAnim(animGroup, animID)) + return nullptr; CAnimBlendAssociationSAInterface* pInterface = nullptr; DWORD dwFunc = FUNC_CAnimManager_BlendAnimation; @@ -495,7 +510,10 @@ void CAnimManagerSA::RemoveAnimBlock(int ID) AnimAssocDefinition* CAnimManagerSA::AddAnimAssocDefinition(const char* szBlockName, const char* szAnimName, AssocGroupId animGroup, AnimationId animID, AnimDescriptor* pDescriptor) { - AnimAssocDefinition* pReturn; + if (!IsValidAnim(animGroup, animID)) + return nullptr; + + AnimAssocDefinition* pReturn{}; DWORD dwFunc = FUNC_CAnimManager_AddAnimAssocDefinition; _asm { @@ -508,7 +526,7 @@ AnimAssocDefinition* CAnimManagerSA::AddAnimAssocDefinition(const char* szBlockN mov pReturn, eax add esp, 0x14 } - return NULL; + return pReturn; } void CAnimManagerSA::ReadAnimAssociationDefinitions() @@ -849,5 +867,33 @@ void CAnimManagerSA::DeleteCustomAnimSequenceInterface(CAnimBlendSequenceSAInter bool CAnimManagerSA::isGateWayAnimationHierarchy(CAnimBlendHierarchySAInterface* pInterface) { - return pGame->GetKeyGen()->GetUppercaseKey(m_kGateWayAnimationName.c_str()) == pInterface->uiHashKey; + return pGame->GetKeyGen()->GetUppercaseKey(kGateWayAnimationName) == pInterface->uiHashKey; +} + +const char* CAnimManagerSA::GetGateWayBlockName() const +{ + return kGateWayBlockName; +} + +const char* CAnimManagerSA::GetGateWayAnimationName() const +{ + return kGateWayAnimationName; +} + +bool CAnimManagerSA::IsValidGroup(std::uint32_t uiAnimGroup) const +{ + const auto pGroup = GetAnimBlendAssoc(uiAnimGroup); + return pGroup && pGroup->IsCreated(); +} + +bool CAnimManagerSA::IsValidAnim(std::uint32_t uiAnimGroup, std::uint32_t uiAnimID) const +{ + // We get an animation for the checks + const auto pAnim = GetAnimStaticAssociation((eAnimGroup)uiAnimGroup, (eAnimID)uiAnimID); + if (!pAnim) + return false; + + // We check the interface and sAnimID, if AnimID is not in GTA:SA, it will differ from our indicators in sAnimID + const auto pInterface = pAnim->GetInterface(); + return pInterface && pInterface->sAnimID == uiAnimID; } diff --git a/Client/game_sa/CAnimManagerSA.h b/Client/game_sa/CAnimManagerSA.h index e826138b62..bb29059fac 100644 --- a/Client/game_sa/CAnimManagerSA.h +++ b/Client/game_sa/CAnimManagerSA.h @@ -1,11 +1,11 @@ /***************************************************************************** * - * PROJECT: Multi Theft Auto v1.0 + * PROJECT: Multi Theft Auto * LICENSE: See LICENSE in the top level directory - * FILE: game_sa/CAnimManagerSA.h + * FILE: Client/game_sa/CAnimManagerSA.h * PURPOSE: Header file for animation manager class * - * Multi Theft Auto is available from http://www.multitheftauto.com/ + * Multi Theft Auto is available from https://multitheftauto.com/ * *****************************************************************************/ @@ -94,14 +94,14 @@ class CAnimManagerSA : public CAnimManager int GetAnimationBlockIndex(const char* szName); int RegisterAnimBlock(const char* szName); - std::unique_ptr GetAnimBlendAssoc(AssocGroupId groupID); + std::unique_ptr GetAnimBlendAssoc(AssocGroupId groupID) const; AssocGroupId GetFirstAssocGroup(const char* szName); const char* GetAnimGroupName(AssocGroupId groupID); const char* GetAnimBlockName(AssocGroupId groupID); std::unique_ptr CreateAnimAssociation(AssocGroupId animGroup, AnimationId animID); - StaticAssocIntface_type GetAnimStaticAssociation(eAnimGroup animGroup, eAnimID animID); + StaticAssocIntface_type GetAnimStaticAssociation(eAnimGroup animGroup, eAnimID animID) const; std::unique_ptr GetAnimAssociation(AssocGroupId animGroup, const char* szAnimName); std::unique_ptr AddAnimation(RpClump* pClump, AssocGroupId animGroup, AnimationId animID); std::unique_ptr AddAnimation(RpClump* pClump, CAnimBlendHierarchy*, int ID); @@ -159,20 +159,13 @@ class CAnimManagerSA : public CAnimManager void DeleteCustomAnimHierarchyInterface(CAnimBlendHierarchySAInterface* pInterface); void DeleteCustomAnimSequenceInterface(CAnimBlendSequenceSAInterface* pInterface); - bool isGateWayAnimationHierarchy(CAnimBlendHierarchySAInterface* pInterface); - const SString& GetGateWayBlockName() { return m_kGateWayBlockName; }; - const SString& GetGateWayAnimationName() { return m_kGateWayAnimationName; }; + bool isGateWayAnimationHierarchy(CAnimBlendHierarchySAInterface* pInterface); + const char* GetGateWayBlockName() const; + const char* GetGateWayAnimationName() const; + bool IsValidGroup(std::uint32_t uiAnimGroup) const; + bool IsValidAnim(std::uint32_t uiAnimGroup, std::uint32_t uiAnimID) const; private: CAnimBlendAssocGroup* m_pAnimAssocGroups[MAX_ANIM_GROUPS]; CAnimBlock* m_pAnimBlocks[MAX_ANIM_BLOCKS]; - - // This "gateway" animation will allow us to play custom animations by simply playing this animation - // and then in AddAnimation and AddAnimationAndSync hook, we can return our custom animation in the - // hook instead of run_wuzi. This will trick GTA SA into thinking that it is playing run_wuzi from - // ped block, but in reality, it's playing our custom animation, and Of course, we can return run_wuzi - // animation within the hook if we want to play it instead. Why run_wuzi? We can also use another animation, - // but I've tested with this one mostly, so let's stick to this. - const SString m_kGateWayBlockName = "ped"; - const SString m_kGateWayAnimationName = "run_wuzi"; }; diff --git a/Client/game_sa/CBuildingRemovalSA.cpp b/Client/game_sa/CBuildingRemovalSA.cpp new file mode 100644 index 0000000000..122a1bba45 --- /dev/null +++ b/Client/game_sa/CBuildingRemovalSA.cpp @@ -0,0 +1,725 @@ +/***************************************************************************** + * + * PROJECT: Multi Theft Auto v1.0 + * LICENSE: See LICENSE in the top level directory + * FILE: game_sa/CBuildingRemovalSA.cpp + * PURPOSE: Building removal logic + * + * Multi Theft Auto is available from http://www.multitheftauto.com/ + * + *****************************************************************************/ + +#include "StdInc.h" +#include "CBuildingRemovalSA.h" + +#include "CWorldSA.h" +#include "CGameSA.h" +#include "CPoolsSA.h" + +extern CGameSA* pGame; + +CBuildingRemovalSA::CBuildingRemovalSA() +{ + m_pBuildingRemovals = new std::multimap; + m_pDataBuildings = new std::multimap; + m_pBinaryBuildings = new std::multimap; +} + +void CBuildingRemovalSA::RemoveBuilding(uint16_t usModelToRemove, float fRange, float fX, float fY, float fZ, char cInterior, size_t* pOutAmount) +{ + // New building Removal + SBuildingRemoval* pRemoval = new SBuildingRemoval(); + pRemoval->m_usModel = usModelToRemove; + pRemoval->m_vecPos.fX = fX; + pRemoval->m_vecPos.fY = fY; + pRemoval->m_vecPos.fZ = fZ; + pRemoval->m_fRadius = fRange; + pRemoval->m_cInterior = cInterior; + // Push it to the back of the removal list + m_pBuildingRemovals->insert(std::pair(usModelToRemove, pRemoval)); + + bool bFound = false; + uint uiAmount = 0; + // Init loop variables + std::pair::iterator, std::multimap::iterator> + iterators = m_pDataBuildings->equal_range(usModelToRemove); + std::multimap::const_iterator iter = iterators.first; + for (; iter != iterators.second; ++iter) + { + sDataBuildingRemovalItem* pFind = (*iter).second; + if (pFind) + { + // if the count is <= 0 and the interface is valid check the distance in case we found a removal (count is used to store if we have already removed + // this once) + if (pFind->m_iCount <= 0 && pFind->m_pInterface) + { + // Grab distances across each axis + float fDistanceX = fX - pFind->m_pInterface->Placeable.m_transform.m_translate.fX; + float fDistanceY = fY - pFind->m_pInterface->Placeable.m_transform.m_translate.fY; + float fDistanceZ = fZ - pFind->m_pInterface->Placeable.m_transform.m_translate.fZ; + + if (pFind->m_pInterface->Placeable.matrix != NULL) + { + fDistanceX = fX - pFind->m_pInterface->Placeable.matrix->vPos.fX; + fDistanceY = fY - pFind->m_pInterface->Placeable.matrix->vPos.fY; + fDistanceZ = fZ - pFind->m_pInterface->Placeable.matrix->vPos.fZ; + } + + // Square root 'em + float fDistance = sqrt(fDistanceX * fDistanceX + fDistanceY * fDistanceY + fDistanceZ * fDistanceZ); + + // Is it in range + if (fDistance <= fRange && (pFind->m_pInterface->m_areaCode == cInterior || cInterior == -1)) + { + CEntitySAInterface* pInterface = pFind->m_pInterface; + // while ( pInterface && pInterface != NULL ) + // if the interface is valid + if (pInterface && pInterface != NULL) + { + // if the building type is dummy or building and it's not already being removed + if ((pInterface->nType == ENTITY_TYPE_BUILDING || pInterface->nType == ENTITY_TYPE_DUMMY || pInterface->nType == ENTITY_TYPE_OBJECT) && + pInterface->bRemoveFromWorld != 1) + { + if ((DWORD)(pInterface->vtbl) != VTBL_CPlaceable) + { + // Add the Data Building to the list + pRemoval->AddDataBuilding(pInterface); + // Remove the model from the world + pGame->GetWorld()->Remove(pInterface, BuildingRemoval2); + m_pRemovedEntities[(DWORD)pInterface] = true; + bFound = true; + } + } + // Get next LOD ( LOD's can have LOD's so we keep checking pInterface ) + // pInterface = pInterface->m_pLod; + } + // Set the count. + pFind->m_iCount = 1; + } + } + } + } + + std::pair::iterator, std::multimap::iterator> iteratorsBinary = + m_pBinaryBuildings->equal_range(usModelToRemove); + std::multimap::const_iterator iterBinary = iteratorsBinary.first; + for (; iterBinary != iteratorsBinary.second; ++iterBinary) + { + sBuildingRemovalItem* pFindBinary = (*iterBinary).second; + if (pFindBinary) + { + // if the count is <= 0 and the interface is valid check the distance in case we found a removal (count is used to store if we have already removed + // this once) + if (pFindBinary->m_iCount <= 0 && pFindBinary->m_pInterface) + { + // Grab distances across each axis + float fDistanceX = fX - pFindBinary->m_pInterface->Placeable.m_transform.m_translate.fX; + float fDistanceY = fY - pFindBinary->m_pInterface->Placeable.m_transform.m_translate.fY; + float fDistanceZ = fZ - pFindBinary->m_pInterface->Placeable.m_transform.m_translate.fZ; + + if (pFindBinary->m_pInterface->Placeable.matrix != NULL) + { + fDistanceX = fX - pFindBinary->m_pInterface->Placeable.matrix->vPos.fX; + fDistanceY = fY - pFindBinary->m_pInterface->Placeable.matrix->vPos.fY; + fDistanceZ = fZ - pFindBinary->m_pInterface->Placeable.matrix->vPos.fZ; + } + + // Square root 'em + float fDistance = sqrt(fDistanceX * fDistanceX + fDistanceY * fDistanceY + fDistanceZ * fDistanceZ); + + // Is it in range + if (fDistance <= fRange && (pFindBinary->m_pInterface->m_areaCode == cInterior || cInterior == -1)) + { + CEntitySAInterface* pInterface = pFindBinary->m_pInterface; + // while ( pInterface && pInterface != NULL ) + // if the interface is valid + if (pInterface && pInterface != NULL) + { + // if the building type is dummy or building and it's not already being removed + if ((pInterface->nType == ENTITY_TYPE_BUILDING || pInterface->nType == ENTITY_TYPE_DUMMY || pInterface->nType == ENTITY_TYPE_OBJECT) && + pInterface->bRemoveFromWorld != 1) + { + if ((DWORD)(pInterface->vtbl) != VTBL_CPlaceable) + { + // Add the Data Building to the list + pRemoval->AddBinaryBuilding(pInterface); + // Remove the model from the world + pGame->GetWorld()->Remove(pInterface, BuildingRemoval2); + m_pRemovedEntities[(DWORD)pInterface] = true; + bFound = true; + ++uiAmount; + } + } + // Get next LOD ( LOD's can have LOD's so we keep checking pInterface ) + // pInterface = pInterface->m_pLod; + } + // Set the count. + pFindBinary->m_iCount = 1; + } + } + } + } + if (bFound) + pGame->GetModelInfo(usModelToRemove)->RestreamIPL(); + + if (pOutAmount) + *pOutAmount = uiAmount; +} + +bool CBuildingRemovalSA::RestoreBuilding(uint16_t usModelToRestore, float fRange, float fX, float fY, float fZ, char cInterior, uint* pOutAmount) +{ + bool bSuccess = false; + uint uiAmount = 0; + + // Init some variables + std::pair::iterator, std::multimap::iterator> iterators = + m_pBuildingRemovals->equal_range(usModelToRestore); + std::multimap::const_iterator iter = iterators.first; + // Loop through the buildings list + for (; iter != iterators.second;) + { + SBuildingRemoval* pFind = (*iter).second; + // if pFind is valid and the model is the same + if (pFind) + { + // Grab distances across each axis + float fDistanceX = fX - pFind->m_vecPos.fX; + float fDistanceY = fY - pFind->m_vecPos.fY; + float fDistanceZ = fZ - pFind->m_vecPos.fZ; + + // Square root 'em + float fDistance = sqrt(fDistanceX * fDistanceX + fDistanceY * fDistanceY + fDistanceZ * fDistanceZ); + if (fDistance <= pFind->m_fRadius && (cInterior == -1 || pFind->m_cInterior == cInterior)) + { + // Init some variables + CEntitySAInterface* pEntity = NULL; + std::list::const_iterator entityIter = pFind->m_pBinaryRemoveList->begin(); + if (pFind->m_pBinaryRemoveList->empty() == false) + { + // Loop through the Binary object list + for (; entityIter != pFind->m_pBinaryRemoveList->end();) + { + // Grab the pEntity + pEntity = (*entityIter); + // if it's valid re-add it to the world. + if (pEntity != NULL) + { + // Remove it from the binary list + pFind->m_pBinaryRemoveList->erase(entityIter++); + // if the building type is dummy or building and it's not already being removed + if ((pEntity->nType == ENTITY_TYPE_BUILDING || pEntity->nType == ENTITY_TYPE_DUMMY || pEntity->nType == ENTITY_TYPE_OBJECT) && + pEntity->bRemoveFromWorld != 1) + { + // Don't call this on entities being removed. + if ((DWORD)(pEntity->vtbl) != VTBL_CPlaceable) + { + pGame->GetWorld()->Add(pEntity, Building_Restore); + m_pRemovedEntities[(DWORD)pEntity] = false; + // If the building isn't streamed in, we won't find the building in the list (because the hook wasn't called) -> + // removeWorldModel doesn't work next time + AddBinaryBuilding(pEntity); + ++uiAmount; + } + } + } + else + ++entityIter; + } + } + // Start the iterator with the data remove list first item + entityIter = pFind->m_pDataRemoveList->begin(); + if (pFind->m_pDataRemoveList->empty() == false) + { + // Loop through the Data list + for (; entityIter != pFind->m_pDataRemoveList->end();) + { + // Grab the pEntity + pEntity = (*entityIter); + // if it's valid re-add it to the world. + if (pEntity != NULL) + { + pFind->m_pDataRemoveList->erase(entityIter++); + // if the building type is dummy or building and it's not already being removed + if ((pEntity->nType == ENTITY_TYPE_BUILDING || pEntity->nType == ENTITY_TYPE_DUMMY || pEntity->nType == ENTITY_TYPE_OBJECT) && + pEntity->bRemoveFromWorld != 1) + { + if ((DWORD)(pEntity->vtbl) != VTBL_CPlaceable) + { + pGame->GetWorld()->Add(pEntity, Building_Restore2); + m_pRemovedEntities[(DWORD)pEntity] = false; + } + } + } + else + { + ++entityIter; + } + } + } + // Remove the building from the list + m_pBuildingRemovals->erase(iter++); + delete pFind; + // Success! don't return incase there are any others to delete + bSuccess = true; + } + else + iter++; + } + else + iter++; + } + std::pair::iterator, std::multimap::iterator> + dataBuildingIterators = m_pDataBuildings->equal_range(usModelToRestore); + std::multimap::const_iterator iterator = dataBuildingIterators.first; + for (; iterator != dataBuildingIterators.second; ++iterator) + { + sDataBuildingRemovalItem* pFound = (*iterator).second; + if (pFound) + { + // Grab distances across each axis + float fDistanceX = fX - pFound->m_pInterface->Placeable.m_transform.m_translate.fX; + float fDistanceY = fY - pFound->m_pInterface->Placeable.m_transform.m_translate.fY; + float fDistanceZ = fZ - pFound->m_pInterface->Placeable.m_transform.m_translate.fZ; + + if (pFound->m_pInterface->Placeable.matrix != NULL) + { + fDistanceX = fX - pFound->m_pInterface->Placeable.matrix->vPos.fX; + fDistanceY = fY - pFound->m_pInterface->Placeable.matrix->vPos.fY; + fDistanceZ = fZ - pFound->m_pInterface->Placeable.matrix->vPos.fZ; + } + + // Square root 'em + float fDistance = sqrt(fDistanceX * fDistanceX + fDistanceY * fDistanceY + fDistanceZ * fDistanceZ); + if (fDistance <= fRange && (cInterior == -1 || pFound->m_pInterface->m_areaCode == cInterior)) + { + // Fix the removed count. + pFound->m_iCount--; + if (pFound->m_iCount < 0) + pFound->m_iCount = 0; + } + } + } + + std::pair::iterator, std::multimap::iterator> + binaryBuildingIterators = m_pBinaryBuildings->equal_range(usModelToRestore); + std::multimap::const_iterator iteratorBinary = binaryBuildingIterators.first; + for (; iteratorBinary != binaryBuildingIterators.second; ++iteratorBinary) + { + sBuildingRemovalItem* pFoundBinary = (*iteratorBinary).second; + if (pFoundBinary) + { + // Grab distances across each axis + float fDistanceX = fX - pFoundBinary->m_pInterface->Placeable.m_transform.m_translate.fX; + float fDistanceY = fY - pFoundBinary->m_pInterface->Placeable.m_transform.m_translate.fY; + float fDistanceZ = fZ - pFoundBinary->m_pInterface->Placeable.m_transform.m_translate.fZ; + + if (pFoundBinary->m_pInterface->Placeable.matrix != NULL) + { + fDistanceX = fX - pFoundBinary->m_pInterface->Placeable.matrix->vPos.fX; + fDistanceY = fY - pFoundBinary->m_pInterface->Placeable.matrix->vPos.fY; + fDistanceZ = fZ - pFoundBinary->m_pInterface->Placeable.matrix->vPos.fZ; + } + + // Square root 'em + float fDistance = sqrt(fDistanceX * fDistanceX + fDistanceY * fDistanceY + fDistanceZ * fDistanceZ); + if (fDistance <= fRange && (cInterior == -1 || pFoundBinary->m_pInterface->m_areaCode == cInterior)) + { + // Fix the removed count. + pFoundBinary->m_iCount--; + if (pFoundBinary->m_iCount < 0) + pFoundBinary->m_iCount = 0; + } + } + } + + if (pOutAmount) + *pOutAmount = uiAmount; + + return bSuccess; +} + +// Check Distance to see if the model being requested is in the radius +bool CBuildingRemovalSA::IsRemovedModelInRadius(SIPLInst* pInst) +{ + // Init some variables + std::pair::iterator, std::multimap::iterator> iterators = + m_pBuildingRemovals->equal_range(pInst->m_nModelIndex); + std::multimap::const_iterator iter = iterators.first; + // Loop through the buildings list + for (; iter != iterators.second; ++iter) + { + SBuildingRemoval* pFind = (*iter).second; + // if pFind is valid and the model is the same + if (pFind) + { + // Grab the distance + float fDistanceX = pFind->m_vecPos.fX - pInst->m_pPosition.fX; + float fDistanceY = pFind->m_vecPos.fY - pInst->m_pPosition.fY; + float fDistanceZ = pFind->m_vecPos.fZ - pInst->m_pPosition.fZ; + + float fDistance = sqrt(fDistanceX * fDistanceX + fDistanceY * fDistanceY + fDistanceZ * fDistanceZ); + // is it in the removal spheres radius if so return else keep looking + if (fDistance <= pFind->m_fRadius && (pFind->m_cInterior == -1 || pFind->m_cInterior == pInst->m_nAreaCode)) + { + return true; + } + } + } + return false; +} + +// Check Distance to see if the model being requested is in the radius +bool CBuildingRemovalSA::IsObjectRemoved(CEntitySAInterface* pInterface) +{ + // Init some variables + std::pair::iterator, std::multimap::iterator> iterators = + m_pBuildingRemovals->equal_range(pInterface->m_nModelIndex); + std::multimap::const_iterator iter = iterators.first; + // Loop through the buildings list + for (; iter != iterators.second; ++iter) + { + SBuildingRemoval* pFind = (*iter).second; + // if pFind is valid and the model is the same + if (pFind) + { + // Are we using the interior param?? if so check for a match + if (pFind->m_cInterior == -1 || pFind->m_cInterior == pInterface->m_areaCode) + { + // Grab the distance + float fDistanceX = pFind->m_vecPos.fX - pInterface->Placeable.m_transform.m_translate.fX; + float fDistanceY = pFind->m_vecPos.fY - pInterface->Placeable.m_transform.m_translate.fY; + float fDistanceZ = pFind->m_vecPos.fZ - pInterface->Placeable.m_transform.m_translate.fZ; + + if (pInterface->Placeable.matrix != NULL) + { + fDistanceX = pFind->m_vecPos.fX - pInterface->Placeable.matrix->vPos.fX; + fDistanceY = pFind->m_vecPos.fY - pInterface->Placeable.matrix->vPos.fY; + fDistanceZ = pFind->m_vecPos.fZ - pInterface->Placeable.matrix->vPos.fZ; + } + + float fDistance = sqrt(fDistanceX * fDistanceX + fDistanceY * fDistanceY + fDistanceZ * fDistanceZ); + // is it in the removal spheres radius if so return else keep looking + if (fDistance <= pFind->m_fRadius) + { + return true; + } + } + } + } + return false; +} + +// Check if a given model is replaced +bool CBuildingRemovalSA::IsModelRemoved(uint16_t usModelID) +{ + return m_pBuildingRemovals->count(usModelID) > 0; +} + +// Check if a given model is replaced +bool CBuildingRemovalSA::IsDataModelRemoved(uint16_t usModelID) +{ + return m_pBuildingRemovals->count(usModelID) > 0; +} + +// Check if a given model is replaced +bool CBuildingRemovalSA::IsEntityRemoved(CEntitySAInterface* pInterface) +{ + return m_pRemovedEntities.find((DWORD)pInterface) != m_pRemovedEntities.end() && m_pRemovedEntities[(DWORD)pInterface] == true; +} + +// Resets deleted list +void CBuildingRemovalSA::ClearRemovedBuildingLists(uint* pOutAmount) +{ + // Ensure no memory leaks by deleting items. + uint uiAmount = 0; + std::multimap::const_iterator iter = m_pBuildingRemovals->begin(); + + for (; iter != m_pBuildingRemovals->end();) + { + SBuildingRemoval* pFind = (*iter).second; + if (pFind) + { + // Init some variables + CEntitySAInterface* pEntity = NULL; + std::list::const_iterator entityIter = pFind->m_pBinaryRemoveList->begin(); + if (pFind->m_pBinaryRemoveList->empty() == false) + { + // Loop through the Binary remove list + for (; entityIter != pFind->m_pBinaryRemoveList->end(); ++entityIter) + { + // Grab the pEntity + pEntity = (*entityIter); + // if it's valid re-add it to the world. + if (pEntity && pEntity != NULL) + { + // if the building type is dummy or building and it's not already being removed + if ((pEntity->nType == ENTITY_TYPE_BUILDING || pEntity->nType == ENTITY_TYPE_DUMMY || pEntity->nType == ENTITY_TYPE_OBJECT) && + pEntity->bRemoveFromWorld != 1) + { + // Don't call this on entities being removed. + if ((DWORD)(pEntity->vtbl) != VTBL_CPlaceable) + { + pGame->GetWorld()->Add(pEntity, BuildingRemovalReset); + m_pRemovedEntities[(DWORD)pEntity] = false; + ++uiAmount; + } + } + } + } + } + entityIter = pFind->m_pDataRemoveList->begin(); + if (pFind->m_pDataRemoveList->empty() == false) + { + // Loop through the Data list + for (; entityIter != pFind->m_pDataRemoveList->end(); ++entityIter) + { + // Grab the pEntity + pEntity = (*entityIter); + // if it's valid re-add it to the world. + if (pEntity && pEntity != NULL) + { + // if the building type is dummy or building and it's not already being removed + if ((pEntity->nType == ENTITY_TYPE_BUILDING || pEntity->nType == ENTITY_TYPE_DUMMY || pEntity->nType == ENTITY_TYPE_OBJECT) && + pEntity->bRemoveFromWorld != 1) + { + // Don't call this on entities being removed. + if ((DWORD)(pEntity->vtbl) != VTBL_CPlaceable) + { + pGame->GetWorld()->Add(pEntity, BuildingRemovalReset2); + m_pRemovedEntities[(DWORD)pEntity] = false; + } + } + } + } + } + m_pBuildingRemovals->erase(iter++); + } + else + iter++; + } + // Init some variables + std::multimap::const_iterator iterator = m_pDataBuildings->begin(); + // Loop through the data building list + for (; iterator != m_pDataBuildings->end(); ++iterator) + { + sDataBuildingRemovalItem* pFound = (*iterator).second; + if (pFound) + { + // Set the count to 0 so we can remove it again + pFound->m_iCount = 0; + } + } + // Init some variables + std::multimap::const_iterator iteratorBinary = m_pBinaryBuildings->begin(); + // Loop through the data building list + for (; iteratorBinary != m_pBinaryBuildings->end(); ++iteratorBinary) + { + sBuildingRemovalItem* pFoundBinary = (*iteratorBinary).second; + if (pFoundBinary) + { + // Set the count to 0 so we can remove it again + pFoundBinary->m_iCount = 0; + } + } + // Delete old building lists + delete m_pBuildingRemovals; + // Create new + m_pBuildingRemovals = new std::multimap; + m_pRemovedEntities.clear(); + + if (pOutAmount) + *pOutAmount = uiAmount; +} + +// Resets deleted list +SBuildingRemoval* CBuildingRemovalSA::GetBuildingRemoval(CEntitySAInterface* pInterface) +{ + // Init some variables + std::pair::iterator, std::multimap::iterator> iterators = + m_pBuildingRemovals->equal_range(pInterface->m_nModelIndex); + std::multimap::const_iterator iter = iterators.first; + // Loop through the buildings list + for (; iter != iterators.second; ++iter) + { + SBuildingRemoval* pFind = (*iter).second; + // if pFind is valid and the model is the same + if (pFind) + { + // Grab the distance + float fDistanceX = pFind->m_vecPos.fX - pInterface->Placeable.m_transform.m_translate.fX; + float fDistanceY = pFind->m_vecPos.fY - pInterface->Placeable.m_transform.m_translate.fY; + float fDistanceZ = pFind->m_vecPos.fZ - pInterface->Placeable.m_transform.m_translate.fZ; + + if (pInterface->Placeable.matrix != NULL) + { + fDistanceX = pFind->m_vecPos.fX - pInterface->Placeable.matrix->vPos.fX; + fDistanceY = pFind->m_vecPos.fY - pInterface->Placeable.matrix->vPos.fY; + fDistanceZ = pFind->m_vecPos.fZ - pInterface->Placeable.matrix->vPos.fZ; + } + + float fDistance = sqrt(fDistanceX * fDistanceX + fDistanceY * fDistanceY + fDistanceZ * fDistanceZ); + // is it in the removal spheres radius if so return else keep looking + if (fDistance <= pFind->m_fRadius && (pFind->m_cInterior == -1 || pFind->m_cInterior == pInterface->m_areaCode)) + { + return pFind; + } + } + } + return NULL; +} + +void CBuildingRemovalSA::AddDataBuilding(CEntitySAInterface* pInterface) +{ + if (m_pAddedEntities.find((DWORD)pInterface) == m_pAddedEntities.end() || m_pAddedEntities[(DWORD)pInterface] == false) + { + // Create a new building removal + sDataBuildingRemovalItem* pBuildingRemoval = new sDataBuildingRemovalItem(pInterface, true); + // Insert it with the model index so we can fast lookup + m_pDataBuildings->insert(std::pair((uint16_t)pInterface->m_nModelIndex, pBuildingRemoval)); + m_pAddedEntities[(DWORD)pInterface] = true; + m_pRemovedEntities[(DWORD)pInterface] = false; + } +} + +void CBuildingRemovalSA::AddBinaryBuilding(CEntitySAInterface* pInterface) +{ + if (m_pAddedEntities.find((DWORD)pInterface) == m_pAddedEntities.end() || m_pAddedEntities[(DWORD)pInterface] == false) + { + // Create a new building removal + sBuildingRemovalItem* pBuildingRemoval = new sBuildingRemovalItem(pInterface, false); + // Insert it with the model index so we can fast lookup + m_pBinaryBuildings->insert(std::pair((uint16_t)pInterface->m_nModelIndex, pBuildingRemoval)); + m_pAddedEntities[(DWORD)pInterface] = true; + m_pRemovedEntities[(DWORD)pInterface] = false; + } +} + +void CBuildingRemovalSA::RemoveWorldBuildingFromLists(CEntitySAInterface* pInterface) +{ + std::pair::iterator, std::multimap::iterator> iterators = + m_pBuildingRemovals->equal_range(pInterface->m_nModelIndex); + std::multimap::const_iterator iter = iterators.first; + + // Loop through the buildings list + for (; iter != iterators.second; ++iter) + { + SBuildingRemoval* pFind = (*iter).second; + // if pFind is valid and the model is the same + if (pFind) + { + CEntitySAInterface* pEntity = NULL; + // if the binary remove list is empty don't continue + if (pFind->m_pBinaryRemoveList->empty() == false) + { + // grab the beginning + std::list::const_iterator entityIter = pFind->m_pBinaryRemoveList->begin(); + // Loop through the binary remove list + for (; entityIter != pFind->m_pBinaryRemoveList->end();) + { + pEntity = (*entityIter); + // is the pointer the same as the one being deleted + if ((DWORD)pEntity == (DWORD)pInterface) + { + // remove it from the binary removed list for this removal + pFind->m_pBinaryRemoveList->erase(entityIter++); + } + else + entityIter++; + } + } + if (pFind->m_pDataRemoveList->empty() == false) + { + std::list::const_iterator entityIter = pFind->m_pDataRemoveList->begin(); + // Loop through the Data list + for (; entityIter != pFind->m_pDataRemoveList->end();) + { + // Grab the pEntity + pEntity = (*entityIter); + // is the pointer the same as the one being deleted + if ((DWORD)pEntity == (DWORD)pInterface) + { + // remove it from the data removed list for this removal + pFind->m_pDataRemoveList->erase(entityIter++); + } + else + entityIter++; + } + } + } + } + { + // Init some variables + std::pair::iterator, std::multimap::iterator> + dataIterators = m_pDataBuildings->equal_range(pInterface->m_nModelIndex); + std::multimap::const_iterator iterator = dataIterators.first; + for (; iterator != dataIterators.second;) + { + sDataBuildingRemovalItem* pFound = (*iterator).second; + if (pFound) + { + // is the pointer the same as the one being deleted + if ((DWORD)pFound->m_pInterface == (DWORD)pInterface) + { + delete pFound; + // remove it from the data buildings list so we don't try and remove or add it again. + m_pDataBuildings->erase(iterator++); + } + else + iterator++; + } + else + iterator++; + } + } + { + // Init some variables + std::pair::iterator, std::multimap::iterator> + binaryIterators = m_pBinaryBuildings->equal_range(pInterface->m_nModelIndex); + std::multimap::const_iterator iteratorBinary = binaryIterators.first; + for (; iteratorBinary != binaryIterators.second;) + { + sBuildingRemovalItem* pFound = (*iteratorBinary).second; + if (pFound) + { + // is the pointer the same as the one being deleted + if ((DWORD)pFound->m_pInterface == (DWORD)pInterface) + { + delete pFound; + // remove it from the data buildings list so we don't try and remove or add it again. + m_pBinaryBuildings->erase(iteratorBinary++); + } + else + iteratorBinary++; + } + else + iteratorBinary++; + } + } + m_pRemovedEntities[(DWORD)pInterface] = false; + m_pAddedEntities[(DWORD)pInterface] = false; +} + +void CBuildingRemovalSA::DropCaches() +{ + m_pRemovedEntities.clear(); + m_pAddedEntities.clear(); + + for (auto& it : *m_pBinaryBuildings) + { + delete it.second; + } + + for (auto& it : *m_pDataBuildings) + { + delete it.second; + } + + m_pBinaryBuildings->clear(); + m_pDataBuildings->clear(); + + for (auto &pRemoval : *m_pBuildingRemovals) + { + pRemoval.second->m_pDataRemoveList->clear(); + pRemoval.second->m_pBinaryRemoveList->clear(); + } +} diff --git a/Client/game_sa/CBuildingRemovalSA.h b/Client/game_sa/CBuildingRemovalSA.h new file mode 100644 index 0000000000..bd685fbc9b --- /dev/null +++ b/Client/game_sa/CBuildingRemovalSA.h @@ -0,0 +1,45 @@ +/***************************************************************************** + * + * PROJECT: Multi Theft Auto v1.0 + * LICENSE: See LICENSE in the top level directory + * FILE: game_sa/CBuildingRemovalSA.h + * PURPOSE: Header file for building removal class + * + * Multi Theft Auto is available from http://www.multitheftauto.com/ + * + *****************************************************************************/ + +#pragma once + +#include +#include + +#include + +class CBuildingRemovalSA : public CBuildingRemoval +{ +public: + CBuildingRemovalSA(); + + SBuildingRemoval* GetBuildingRemoval(CEntitySAInterface* pInterface) override; + + void RemoveBuilding(uint16_t usModelToRemove, float fDistance, float fX, float fY, float fZ, char cInterior, size_t* pOutAmount = NULL) override; + bool RestoreBuilding(uint16_t usModelToRestore, float fDistance, float fX, float fY, float fZ, char cInterior, size_t* pOutAmount = NULL) override; + bool IsRemovedModelInRadius(SIPLInst* pInst) override; + bool IsModelRemoved(uint16_t modelID) override; + void ClearRemovedBuildingLists(uint* pOutAmount = NULL) override; + void AddDataBuilding(CEntitySAInterface* pInterface) override; + void RemoveWorldBuildingFromLists(CEntitySAInterface* pInterface) override; + void AddBinaryBuilding(CEntitySAInterface* pInterface) override; + bool IsObjectRemoved(CEntitySAInterface* pInterface) override; + bool IsDataModelRemoved(uint16_t usModelID) override; + bool IsEntityRemoved(CEntitySAInterface* pInterface) override; + void DropCaches(); + +private: + std::multimap* m_pBuildingRemovals; + std::multimap* m_pDataBuildings; + std::multimap* m_pBinaryBuildings; + std::map m_pRemovedEntities; + std::map m_pAddedEntities; +}; diff --git a/Client/game_sa/CBuildingSA.cpp b/Client/game_sa/CBuildingSA.cpp new file mode 100644 index 0000000000..32c1818309 --- /dev/null +++ b/Client/game_sa/CBuildingSA.cpp @@ -0,0 +1,67 @@ +/***************************************************************************** + * + * PROJECT: Multi Theft Auto v1.0 + * LICENSE: See LICENSE in the top level directory + * FILE: game_sa/CBuildingSA.cpp + * PURPOSE: Building entity + * + * Multi Theft Auto is available from http://www.multitheftauto.com/ + * + *****************************************************************************/ + +#include "StdInc.h" +#include "CBuildingSA.h" +#include +#include "CGameSA.h" + +extern CGameSA* pGame; + +CBuildingSA::CBuildingSA(CBuildingSAInterface* pInterface) +{ + SetInterface(pInterface); +} + +void CBuildingSA::SetLod(CBuilding* pLod) +{ + if (pLod) + { + if (m_pInterface->m_pLod) + { + SetLod(nullptr); + } + + CBuildingSAInterface* pLodInterface = dynamic_cast(pLod)->GetBuildingInterface(); + assert(pLodInterface); + + // We should recreate buildings... + pGame->GetWorld()->Remove(pLodInterface, CBuilding_SetLod); + pGame->GetWorld()->Remove(m_pInterface, CBuilding_SetLod); + + m_pInterface->m_pLod = pLodInterface; + pLodInterface->bUsesCollision = 0; + pLodInterface->numLodChildren = 1; + + if (pGame->GetModelInfo(pLodInterface->m_nModelIndex)->GetLODDistance() > 300) + { + pLodInterface->bIsBIGBuilding = 1; + } + + // Only this specific order works + pGame->GetWorld()->Add(m_pInterface, CBuilding_SetLod); + pGame->GetWorld()->Add(pLodInterface, CBuilding_SetLod); + } + else + { + CEntitySAInterface* pCurrentLod = m_pInterface->m_pLod; + if (pCurrentLod) + { + pGame->GetWorld()->Remove(pCurrentLod, CBuilding_SetLod); + + m_pInterface->m_pLod = nullptr; + pCurrentLod->bIsBIGBuilding = false; + pCurrentLod->numLodChildren = 0; + + pGame->GetWorld()->Add(pCurrentLod, CBuilding_SetLod); + } + } +} diff --git a/Client/game_sa/CBuildingSA.h b/Client/game_sa/CBuildingSA.h new file mode 100644 index 0000000000..6aae552470 --- /dev/null +++ b/Client/game_sa/CBuildingSA.h @@ -0,0 +1,30 @@ +/***************************************************************************** + * + * PROJECT: Multi Theft Auto v1.0 + * LICENSE: See LICENSE in the top level directory + * FILE: game_sa/CBuildingSA.h + * PURPOSE: Header file for game building class + * + * Multi Theft Auto is available from http://www.multitheftauto.com/ + * + *****************************************************************************/ + +#pragma once + +#include +#include "CEntitySA.h" + +class CBuildingSAInterface : public CEntitySAInterface +{ +}; +static_assert(sizeof(CBuildingSAInterface) == 0x38, "Invalid size CBuildingSAInterface"); + +class CBuildingSA final : public virtual CBuilding, public virtual CEntitySA +{ +public: + CBuildingSA(CBuildingSAInterface* pInterface); + + CBuildingSAInterface* GetBuildingInterface() { return static_cast(GetInterface()); }; + + void SetLod(CBuilding* pLod) override; +}; diff --git a/Client/game_sa/CBuildingsPoolSA.cpp b/Client/game_sa/CBuildingsPoolSA.cpp new file mode 100644 index 0000000000..caa392c132 --- /dev/null +++ b/Client/game_sa/CBuildingsPoolSA.cpp @@ -0,0 +1,348 @@ +/***************************************************************************** + * + * PROJECT: Multi Theft Auto v1.0 + * LICENSE: See LICENSE in the top level directory + * FILE: game_sa/CBuildingsPoolSA.cpp + * PURPOSE: Buildings pool class + * + * Multi Theft Auto is available from http://www.multitheftauto.com/ + * + *****************************************************************************/ + +#include "StdInc.h" +#include "CBuildingsPoolSA.h" + +#include "CFileLoaderSA.h" +#include +#include "CGameSA.h" +#include "CPtrNodeSingleListSA.h" +#include "MemSA.h" +#include "CVehicleSA.h" + +extern CGameSA* pGame; + +class CClientEntity; + +CBuildingsPoolSA::CBuildingsPoolSA() : m_pOriginalBuildingsBackup(nullptr) +{ + m_ppBuildingPoolInterface = (CPoolSAInterface**)0xB74498; +} + +inline bool CBuildingsPoolSA::AddBuildingToPool(CClientBuilding* pClientBuilding, CBuildingSA* pBuilding) +{ + // Grab the new object interface + CBuildingSAInterface* pInterface = pBuilding->GetBuildingInterface(); + + if (!pInterface) + return false; + + uint32_t dwElementIndexInPool = (*m_ppBuildingPoolInterface)->GetObjectIndexSafe(pInterface); + if (dwElementIndexInPool == UINT_MAX) + return false; + + m_buildingPool.entities[dwElementIndexInPool] = {pBuilding, (CClientEntity*)pClientBuilding}; + + // Increase the count of objects + ++m_buildingPool.count; + + return true; +} + +CBuilding* CBuildingsPoolSA::AddBuilding(CClientBuilding* pClientBuilding, uint16_t modelId, CVector* vPos, CVector4D* vRot, uint8_t interior) +{ + if (!HasFreeBuildingSlot()) + return nullptr; + + // Load building + SFileObjectInstance instance; + instance.modelID = modelId; + instance.lod = -1; + instance.interiorID = interior; + instance.position = *vPos; + instance.rotation = *vRot; + + // Fix strange SA rotation + instance.rotation.fW = -instance.rotation.fW; + + auto pBuilding = static_cast(CFileLoaderSA::LoadObjectInstance(&instance)); + + // Disable lod and ipl + pBuilding->m_pLod = nullptr; + pBuilding->m_iplIndex = 0; + + // Always stream model collosion + // TODO We can setup collison bounding box and use GTA streamer for it + auto modelInfo = pGame->GetModelInfo(modelId); + modelInfo->AddColRef(); + + // Add building in world + auto pBuildingSA = new CBuildingSA(pBuilding); + pGame->GetWorld()->Add(pBuildingSA, CBuildingPool_Constructor); + + // Add CBuildingSA object in pool + AddBuildingToPool(pClientBuilding, pBuildingSA); + + return pBuildingSA; +} + +void CBuildingsPoolSA::RemoveBuilding(CBuilding* pBuilding) +{ + assert(NULL != pBuilding); + + CBuildingSAInterface* pInterface = pBuilding->GetBuildingInterface(); + + uint32_t dwElementIndexInPool = (*m_ppBuildingPoolInterface)->GetObjectIndexSafe(pInterface); + if (dwElementIndexInPool == UINT_MAX) + return; + + // Remove building from cover list + pGame->GetCoverManager()->RemoveCover(pInterface); + + // Remove plant + pGame->GetPlantManager()->RemovePlant(pInterface); + + // Remove shadow + pInterface->RemoveShadows(); + + // Remove building from world + pGame->GetWorld()->Remove(pInterface, CBuildingPool_Destructor); + + // Call virtual destructor + ((void*(__thiscall*)(void*, char))pInterface->vtbl->SCALAR_DELETING_DESTRUCTOR)(pInterface, 0); + + // Remove col reference + auto modelInfo = pGame->GetModelInfo(pBuilding->GetModelIndex()); + modelInfo->RemoveColRef(); + + // Remove from BuildingSA pool + auto* pBuildingSA = m_buildingPool.entities[dwElementIndexInPool].pEntity; + m_buildingPool.entities[dwElementIndexInPool] = {nullptr, nullptr}; + + // Delete it from memory + delete pBuildingSA; + + // Remove building from SA pool + (*m_ppBuildingPoolInterface)->Release(dwElementIndexInPool); + + // Decrease the count of elements in the pool + --m_buildingPool.count; +} + +void CBuildingsPoolSA::RemoveAllBuildings() +{ + if (m_pOriginalBuildingsBackup) + return; + + pGame->GetCoverManager()->RemoveAllCovers(); + pGame->GetPlantManager()->RemoveAllPlants(); + + // Remove all shadows + using CStencilShadowObjects_dtorAll = void* (*)(); + ((CStencilShadowObjects_dtorAll)0x711390)(); + + m_pOriginalBuildingsBackup = std::make_unique, MAX_BUILDINGS>>(); + + auto pBuildsingsPool = (*m_ppBuildingPoolInterface); + for (size_t i = 0; i < MAX_BUILDINGS; i++) + { + if (pBuildsingsPool->IsContains(i)) + { + CBuildingSAInterface* building = pBuildsingsPool->GetObject(i); + + RemoveBuildingFromWorld(building); + + pBuildsingsPool->Release(i); + + (*m_pOriginalBuildingsBackup)[i].first = true; + (*m_pOriginalBuildingsBackup)[i].second = *building; + } + else + { + (*m_pOriginalBuildingsBackup)[i].first = false; + } + } +} + +void CBuildingsPoolSA::RestoreAllBuildings() +{ + if (!m_pOriginalBuildingsBackup) + return; + + auto& originalData = *m_pOriginalBuildingsBackup; + auto pBuildsingsPool = (*m_ppBuildingPoolInterface); + for (size_t i = 0; i < MAX_BUILDINGS; i++) + { + if (originalData[i].first) + { + pBuildsingsPool->AllocateAt(i); + auto pBuilding = pBuildsingsPool->GetObject(i); + *pBuilding = originalData[i].second; + + pGame->GetWorld()->Add(pBuilding, CBuildingPool_Constructor); + } + } + + m_pOriginalBuildingsBackup = nullptr; +} + +void CBuildingsPoolSA::RemoveBuildingFromWorld(CBuildingSAInterface* pBuilding) +{ + // Remove building from world + pGame->GetWorld()->Remove(pBuilding, CBuildingPool_Destructor); + + pBuilding->DeleteRwObject(); + pBuilding->ResolveReferences(); + pBuilding->RemoveShadows(); +} + +bool CBuildingsPoolSA::Resize(int size) +{ + auto* pool = (*m_ppBuildingPoolInterface); + const int currentSize = pool->m_nSize; + + m_buildingPool.entities.resize(size); + + void* oldPool = pool->m_pObjects; + + if (oldPool != nullptr) + { + MemSA::free(pool->m_pObjects); + pool->m_pObjects = nullptr; + } + + if (pool->m_byteMap != nullptr) + { + MemSA::free(pool->m_byteMap); + pool->m_byteMap = nullptr; + } + + CBuildingSAInterface* newObjects = MemSA::malloc_struct(size); + if (newObjects == nullptr) + { + Resize(currentSize); + return false; + } + + tPoolObjectFlags* newBytemap = MemSA::malloc_struct(size); + if (newBytemap == nullptr) + { + MemSA::free(newObjects); + Resize(currentSize); + return false; + } + + pool->m_pObjects = newObjects; + pool->m_byteMap = newBytemap; + pool->m_nSize = size; + pool->m_nFirstFree = 0; + + for (auto i = 0; i < size; i++) + { + newBytemap[i].bEmpty = true; + } + + const uint32_t offset = (uint32_t)newObjects - (uint32_t)oldPool; + if (oldPool != nullptr) + { + UpdateIplEntrysPointers(offset); + } + + if (m_pOriginalBuildingsBackup) + { + UpdateBackupLodPointers(offset); + } + + pGame->GetPools()->GetDummyPool().UpdateBuildingLods(oldPool, newObjects); + + RemoveVehicleDamageLinks(); + RemovePedsContactEnityLinks(); + + return true; +} + +void CBuildingsPoolSA::UpdateIplEntrysPointers(uint32_t offset) +{ + using buildings_array_t = CBuildingSAInterface* [1000]; + using ipl_entry_array_t = buildings_array_t* [40]; + ipl_entry_array_t* iplEntryArray = (ipl_entry_array_t*)0x8E3F08; + + for (auto i = 0; i < 40; i++) + { + buildings_array_t* ppArray = (*iplEntryArray)[i]; + + if (ppArray == nullptr) + { + return; + } + size_t arraySize = MemSA::msize(*ppArray) / sizeof(CBuildingSAInterface*); + for (auto j = 0; j < arraySize; j++) + { + CBuildingSAInterface* object = (*ppArray)[j]; + + (*ppArray)[j] = (CBuildingSAInterface*)((uint32_t)object + offset); + } + } +} + +void CBuildingsPoolSA::UpdateBackupLodPointers(uint32_t offset) +{ + std::array, MAX_BUILDINGS> *arr = m_pOriginalBuildingsBackup.get(); + for (auto i = 0; i < MAX_BUILDINGS; i++) + { + std::pair* data = &(*arr)[i]; + if (data->first) + { + CBuildingSAInterface* building = &data->second; + if (building->m_pLod != nullptr) + { + building->m_pLod = (CBuildingSAInterface*)((uint32_t)building->m_pLod + offset); + } + } + } +} + +void CBuildingsPoolSA::RemoveVehicleDamageLinks() +{ + const int count = pGame->GetPools()->GetVehicleCount(); + for (int i = 0; i < count; i++) + { + auto* vehLinks = pGame->GetPools()->GetVehicle(i); + if (vehLinks->pEntity) + { + CVehicleSAInterface* vehicle = vehLinks->pEntity->GetVehicleInterface(); + vehicle->m_pCollidedEntity = nullptr; + vehicle->pLastContactedEntity[0] = nullptr; + vehicle->pLastContactedEntity[1] = nullptr; + vehicle->pLastContactedEntity[2] = nullptr; + vehicle->pLastContactedEntity[3] = nullptr; + vehicle->m_ucCollisionState = 0; + } + } +} + +void CBuildingsPoolSA::RemovePedsContactEnityLinks() +{ + const int count = pGame->GetPools()->GetPedCount(); + for (int i = 0; i < count; i++) + { + auto* pedLinks = pGame->GetPools()->GetPed(i); + if (pedLinks->pEntity) + { + CPedSAInterface* ped = pedLinks->pEntity->GetPedInterface(); + ped->m_pCollidedEntity = nullptr; + ped->pContactEntity = nullptr; + ped->pLastContactEntity = nullptr; + ped->pLastContactedEntity[0] = nullptr; + ped->pLastContactedEntity[1] = nullptr; + ped->pLastContactedEntity[2] = nullptr; + ped->pLastContactedEntity[3] = nullptr; + ped->m_ucCollisionState = 0; + ped->pTargetedEntity = nullptr; + } + } +} + +bool CBuildingsPoolSA::HasFreeBuildingSlot() +{ + return (*m_ppBuildingPoolInterface)->GetFreeSlot() != -1; +} diff --git a/Client/game_sa/CBuildingsPoolSA.h b/Client/game_sa/CBuildingsPoolSA.h new file mode 100644 index 0000000000..5ce719bd73 --- /dev/null +++ b/Client/game_sa/CBuildingsPoolSA.h @@ -0,0 +1,47 @@ +/***************************************************************************** + * + * PROJECT: Multi Theft Auto v1.0 + * LICENSE: See LICENSE in the top level directory + * FILE: game_sa/CBuildingsPoolSA.h + * PURPOSE: Buildings pool class + * + * Multi Theft Auto is available from http://www.multitheftauto.com/ + * + *****************************************************************************/ + +#pragma once + +#include +#include +#include "CPoolSAInterface.h" +#include "CBuildingSA.h" + +class CBuildingsPoolSA : public CBuildingsPool +{ +public: + CBuildingsPoolSA(); + ~CBuildingsPoolSA() = default; + + CBuilding* AddBuilding(CClientBuilding*, uint16_t modelId, CVector* vPos, CVector4D* vRot, uint8_t interior); + void RemoveBuilding(CBuilding* pBuilding); + bool HasFreeBuildingSlot(); + + void RemoveAllBuildings() override; + void RestoreAllBuildings() override; + bool Resize(int size) override; + int GetSize() const override { return (*m_ppBuildingPoolInterface)->m_nSize; }; + +private: + void RemoveBuildingFromWorld(CBuildingSAInterface* pBuilding); + bool AddBuildingToPool(CClientBuilding* pClientBuilding, CBuildingSA* pBuilding); + void UpdateIplEntrysPointers(uint32_t offset); + void UpdateBackupLodPointers(uint32_t offset); + void RemoveVehicleDamageLinks(); + void RemovePedsContactEnityLinks(); + +private: + SVectorPoolData m_buildingPool{MAX_BUILDINGS}; + CPoolSAInterface** m_ppBuildingPoolInterface; + + std::unique_ptr, MAX_BUILDINGS>> m_pOriginalBuildingsBackup; +}; diff --git a/Client/game_sa/CCameraSA.cpp b/Client/game_sa/CCameraSA.cpp index 4cd7383e3e..960ec7cfa7 100644 --- a/Client/game_sa/CCameraSA.cpp +++ b/Client/game_sa/CCameraSA.cpp @@ -15,7 +15,6 @@ extern CGameSA* pGame; -unsigned long CCameraSA::FUNC_RwFrameGetLTM; static bool bCameraClipObjects; static bool bCameraClipVehicles; @@ -358,16 +357,8 @@ float CCameraSA::GetCameraRotation() RwMatrix* CCameraSA::GetLTM() { - DWORD frame = *(DWORD*)(((DWORD)GetInterface()->m_pRwCamera) + 4); - DWORD dwReturn; - _asm - { - push frame - call FUNC_RwFrameGetLTM - add esp, 4 - mov dwReturn, eax - } - return (RwMatrix*)dwReturn; + // RwFrameGetLTM + return ((RwMatrix*(_cdecl*)(void*))0x7F0990)(GetInterface()->m_pRwCamera->object.object.parent); } CEntity* CCameraSA::GetTargetEntity() @@ -452,3 +443,18 @@ float CCameraSA::GetShakeForce() CCameraSAInterface* pCameraInterface = GetInterface(); return pCameraInterface->m_fCamShakeForce; } + +void CCameraSA::ShakeCamera(float radius, float x, float y, float z) noexcept +{ + static CCameraSAInterface* cameraInterface = GetInterface(); + if (radius <= 0.0f) + return ResetShakeCamera(); + + using ShakeCamera_t = void(__thiscall*)(CCameraSAInterface*, float radius, float x, float y, float z); + ((ShakeCamera_t)FUNC_ShakeCam)(cameraInterface, radius, x, y, z); +} + +void CCameraSA::ResetShakeCamera() noexcept +{ + GetInterface()->m_fCamShakeForce = 0.0f; +} diff --git a/Client/game_sa/CCameraSA.h b/Client/game_sa/CCameraSA.h index 48c5ca0b1f..246f3362d8 100644 --- a/Client/game_sa/CCameraSA.h +++ b/Client/game_sa/CCameraSA.h @@ -27,6 +27,7 @@ #define FUNC_GetFading 0x50ADE0 #define FUNC_Fade 0x50AC20 #define FUNC_SetFadeColour 0x50BF00 +#define FUNC_ShakeCam 0x50A9F0 #define VAR_CameraRotation 0xB6F178 // used for controling where the player faces #define VAR_VehicleCameraView 0xB6F0DC @@ -308,7 +309,7 @@ class CCameraSAInterface float m_fAttachedCamAngle; // for giving the attached camera a tilt. // RenderWare camera pointer - DWORD* m_pRwCamera; // was RwCamera * + RwCamera* m_pRwCamera; /// stuff for cut scenes CEntitySAInterface* pTargetEntity; CEntitySAInterface* pAttachedEntity; @@ -427,6 +428,6 @@ class CCameraSA : public CCamera void SetShakeForce(float fShakeForce); float GetShakeForce(); -private: - static unsigned long FUNC_RwFrameGetLTM; + void ShakeCamera(float radius, float x, float y, float z) noexcept override; + void ResetShakeCamera() noexcept override; }; diff --git a/Client/game_sa/CCarEnterExitSA.cpp b/Client/game_sa/CCarEnterExitSA.cpp index 5e0f8cd373..a3001c75d2 100644 --- a/Client/game_sa/CCarEnterExitSA.cpp +++ b/Client/game_sa/CCarEnterExitSA.cpp @@ -78,6 +78,19 @@ bool CCarEnterExitSA::GetNearestCarPassengerDoor(CPed* pPed, CVehicle* pVehicle, return bReturn; } +void CCarEnterExitSA::GetPositionToOpenCarDoor(CVector& position, CVehicle* vehicle, std::uint32_t door) const noexcept +{ + CVehicleSA* vehicleSA = dynamic_cast(vehicle); + + if (!vehicleSA) + return; + + CVehicleSAInterface* vehicleInterface = vehicleSA->GetVehicleInterface(); + + auto CCarEnterExit_GetPositionToOpenCarDoor = (void(__cdecl*)(CVector&, CVehicleSAInterface*, int))FUNC_GetPositionToOpenCarDoor; + CCarEnterExit_GetPositionToOpenCarDoor(position, vehicleInterface, door); +} + int CCarEnterExitSA::ComputeTargetDoorToExit(CPed* pPed, CVehicle* pVehicle) { DWORD dwFunc = FUNC_ComputeTargetDoorToExit; diff --git a/Client/game_sa/CCarEnterExitSA.h b/Client/game_sa/CCarEnterExitSA.h index e1f657b264..3e35691bd8 100644 --- a/Client/game_sa/CCarEnterExitSA.h +++ b/Client/game_sa/CCarEnterExitSA.h @@ -17,12 +17,14 @@ #define FUNC_GetNearestCarPassengerDoor 0x650BB0 #define FUNC_ComputeTargetDoorToExit 0x64F110 #define FUNC_IsRoomForPedToLeaveCar 0x6504C0 +#define FUNC_GetPositionToOpenCarDoor 0x64E740 class CCarEnterExitSA : public CCarEnterExit { public: bool GetNearestCarDoor(CPed* pPed, CVehicle* pVehicle, CVector* pVector, int* pDoor); bool GetNearestCarPassengerDoor(CPed* pPed, CVehicle* pVehicle, CVector* pVector, int* pDoor, bool bUnknown, bool bUnknown2, bool bCheckIfRoomToGetIn); + void GetPositionToOpenCarDoor(CVector& position, CVehicle* vehicle, std::uint32_t door) const noexcept; int ComputeTargetDoorToExit(CPed* pPed, CVehicle* pVehicle); bool IsRoomForPedToLeaveCar(CVehicle* pVehicle, int iDoor, CVector* pUnknown = 0); }; diff --git a/Client/game_sa/CCheckpointSA.cpp b/Client/game_sa/CCheckpointSA.cpp index a7ebe0d263..0528dbb2ef 100644 --- a/Client/game_sa/CCheckpointSA.cpp +++ b/Client/game_sa/CCheckpointSA.cpp @@ -13,6 +13,10 @@ #include "C3DMarkerSA.h" #include "C3DMarkersSA.h" #include "CCheckpointSA.h" +#include "CCheckpointsSA.h" +#include "CGameSA.h" + +extern CGameSA* pGame; void CCheckpointSA::SetPosition(CVector* vecPosition) { @@ -132,3 +136,39 @@ void CCheckpointSA::Remove() GetInterface()->m_nType = 257; GetInterface()->rwColour = 0; } + +void CCheckpointSA::SetTargetArrowData(const SColor color, float size) noexcept +{ + m_targetArrowColor = color; + m_targetArrowSize = size; +} + +static void __cdecl RenderTargetArrow(CCheckpointSAInterface* pCheckpoint) +{ + CCheckpoint* checkpoint = pGame->GetCheckpoints()->FindMarker(pCheckpoint->m_nIdentifier); + if (!checkpoint) + return; + + CVector* position = checkpoint->GetPosition(); + CVector* direction = checkpoint->GetPointDirection(); + SColor color = checkpoint->GetTargetArrowColor(); + + ((void(__cdecl*)(float, float, float, float, std::uint8_t, std::uint8_t, std::uint8_t, std::uint8_t, float, float, float))C3dMarkers_DirectionArrowSet)(position->fX, position->fY, position->fZ, checkpoint->GetTargetArrowSize(), color.R, color.G, color.B, color.A, -direction->fX, -direction->fY, -direction->fZ); +} + +static void _declspec(naked) HOOK_CCheckpoint__Render() +{ + _asm { + pushad + push esi + call RenderTargetArrow + add esp, 4 + popad + jmp RETURN_CCheckpoint__Render + } +} + +void CCheckpointSA::StaticSetHooks() +{ + EZHookInstall(CCheckpoint__Render); +} diff --git a/Client/game_sa/CCheckpointSA.h b/Client/game_sa/CCheckpointSA.h index 539bf22c93..f06007edbb 100644 --- a/Client/game_sa/CCheckpointSA.h +++ b/Client/game_sa/CCheckpointSA.h @@ -14,6 +14,12 @@ #include #include +#define HOOKPOS_CCheckpoint__Render 0x725E56 +#define HOOKSIZE_CCheckpoint__Render 0x5 +static constexpr std::uint32_t RETURN_CCheckpoint__Render = 0x725E5B; + +#define C3dMarkers_DirectionArrowSet 0x721140 + class CCheckpointSAInterface { public: @@ -36,12 +42,16 @@ class CCheckpointSA : public CCheckpoint { private: CCheckpointSAInterface* internalInterface; + SColor m_targetArrowColor{0xFFFF4040}; + float m_targetArrowSize{0.625f}; public: CCheckpointSA(CCheckpointSAInterface* checkpointInterface) { internalInterface = checkpointInterface; }; CCheckpointSAInterface* GetInterface() { return internalInterface; } + static void StaticSetHooks(); + void SetPosition(CVector* vecPosition); CVector* GetPosition(); void SetPointDirection(CVector* vecPointDirection); @@ -62,4 +72,7 @@ class CCheckpointSA : public CCheckpoint void SetPulseFraction(float fPulseFraction); // doesn't work propperly (not virtualed) float GetPulseFraction(); void Remove(); + SColor GetTargetArrowColor() const noexcept override { return m_targetArrowColor; }; + float GetTargetArrowSize() const noexcept override { return m_targetArrowSize; }; + void SetTargetArrowData(const SColor color, float size) noexcept; }; diff --git a/Client/game_sa/CCheckpointsSA.cpp b/Client/game_sa/CCheckpointsSA.cpp index e0f83f5de5..593d295340 100644 --- a/Client/game_sa/CCheckpointsSA.cpp +++ b/Client/game_sa/CCheckpointsSA.cpp @@ -66,3 +66,14 @@ CCheckpoint* CCheckpointsSA::FindFreeMarker() } return NULL; } + +CCheckpoint* CCheckpointsSA::FindMarker(DWORD identifier) +{ + for (CCheckpointSA* checkpoint : Checkpoints) + { + if (checkpoint->GetIdentifier() == identifier) + return checkpoint; + } + + return nullptr; +} diff --git a/Client/game_sa/CCheckpointsSA.h b/Client/game_sa/CCheckpointsSA.h index 151af329ab..c29c21f6af 100644 --- a/Client/game_sa/CCheckpointsSA.h +++ b/Client/game_sa/CCheckpointsSA.h @@ -35,4 +35,5 @@ class CCheckpointsSA : public CCheckpoints CCheckpoint* CreateCheckpoint(DWORD Identifier, WORD wType, CVector* vecPosition, CVector* vecPointDir, float fSize, float fPulseFraction, const SharedUtil::SColor color); CCheckpoint* FindFreeMarker(); + CCheckpoint* FindMarker(DWORD identifier); }; diff --git a/Client/game_sa/CClockSA.cpp b/Client/game_sa/CClockSA.cpp index d8d0f5668a..5ab106609d 100644 --- a/Client/game_sa/CClockSA.cpp +++ b/Client/game_sa/CClockSA.cpp @@ -30,3 +30,19 @@ void CClockSA::Get(BYTE* bHour, BYTE* bMinute) *bMinute = *(BYTE*)VAR_TimeMinutes; *bHour = *(BYTE*)VAR_TimeHours; } + +bool CClockSA::SetTimeFrozen(bool value) noexcept +{ + if (value) + MemSet((void*)0x53BFBD, 0x90, 5); + else + MemCpy((void*)0x53BFBD, "\xE8\x4E\x0F\xFF\xFF", 5); + + m_bTimeCycleFrozen = value; + return true; +} + +bool CClockSA::ResetTimeFrozen() noexcept +{ + return SetTimeFrozen(false); +} diff --git a/Client/game_sa/CClockSA.h b/Client/game_sa/CClockSA.h index fd392e9ecf..4d424ba8c5 100644 --- a/Client/game_sa/CClockSA.h +++ b/Client/game_sa/CClockSA.h @@ -22,4 +22,11 @@ class CClockSA : public CClock public: void Set(BYTE bHour, BYTE bMinute); void Get(BYTE* bHour, BYTE* bMinute); + + bool SetTimeFrozen(bool value) noexcept; + bool IsTimeFrozen() const noexcept { return m_bTimeCycleFrozen; }; + bool ResetTimeFrozen() noexcept; + +private: + bool m_bTimeCycleFrozen; }; diff --git a/Client/game_sa/CCoverManagerSA.cpp b/Client/game_sa/CCoverManagerSA.cpp new file mode 100644 index 0000000000..dee7782ffb --- /dev/null +++ b/Client/game_sa/CCoverManagerSA.cpp @@ -0,0 +1,41 @@ +/***************************************************************************** + * + * PROJECT: Multi Theft Auto v1.0 + * LICENSE: See LICENSE in the top level directory + * FILE: game_sa/CCoverManagerSA.cpp + * + * Multi Theft Auto is available from http://www.multitheftauto.com/ + * + *****************************************************************************/ + +#include "StdInc.h" +#include "CCoverManagerSA.h" + +CCoverManagerSA::CCoverManagerSA() +{ + m_pCoverList = reinterpret_cast*>(0xC1A2B8); +} + +void CCoverManagerSA::RemoveAllCovers() +{ + CPtrNodeDoubleLink* pNode = m_pCoverList->m_pNode; + while (pNode) + { + RemoveCoverFromArray(pNode->pItem); + pNode = pNode->pNext; + } + m_pCoverList->RemoveAllItems(); +} + +void CCoverManagerSA::RemoveCover(CEntitySAInterface* entity) +{ + RemoveCoverFromArray(entity); + + m_pCoverList->RemoveItem(entity); +} + +void CCoverManagerSA::RemoveCoverFromArray(CEntitySAInterface* entity) +{ + using CCover_RemoveCoverPointsForThisEntity = char(__cdecl*)(CEntitySAInterface*); + ((CCover_RemoveCoverPointsForThisEntity)0x698740)(entity); +} diff --git a/Client/game_sa/CCoverManagerSA.h b/Client/game_sa/CCoverManagerSA.h new file mode 100644 index 0000000000..6944b43604 --- /dev/null +++ b/Client/game_sa/CCoverManagerSA.h @@ -0,0 +1,30 @@ +/***************************************************************************** + * + * PROJECT: Multi Theft Auto v1.0 + * LICENSE: See LICENSE in the top level directory + * FILE: game_sa/CCoverManagerSA.h + * + * Multi Theft Auto is available from http://www.multitheftauto.com/ + * + *****************************************************************************/ + +#pragma once + +#include "CEntitySA.h" +#include "CPtrNodeDoubleListSA.h" + +class CCoverManagerSA +{ +public: + CCoverManagerSA(); + ~CCoverManagerSA() = default; + + void RemoveAllCovers(); + void RemoveCover(CEntitySAInterface* entity); + +private: + void RemoveCoverFromArray(CEntitySAInterface* entity); + +private: + CPtrNodeDoubleListSAInterface* m_pCoverList; +}; diff --git a/Client/game_sa/CDummyPoolSA.cpp b/Client/game_sa/CDummyPoolSA.cpp new file mode 100644 index 0000000000..7f9b539a40 --- /dev/null +++ b/Client/game_sa/CDummyPoolSA.cpp @@ -0,0 +1,76 @@ +/***************************************************************************** + * + * PROJECT: Multi Theft Auto v1.0 + * LICENSE: See LICENSE in the top level directory + * FILE: game_sa/CDummyPoolSA.cpp + * PURPOSE: Dummy pool class + * + * Multi Theft Auto is available from http://www.multitheftauto.com/ + * + *****************************************************************************/ + +#pragma once + +#include "StdInc.h" +#include "CDummyPoolSA.h" + +CDummyPoolSA::CDummyPoolSA() +{ + m_ppDummyPoolInterface = (CPoolSAInterface**)0xB744A0; +} + +void CDummyPoolSA::RemoveAllBuildingLods() +{ + if (m_pLodBackup) + return; + + m_pLodBackup = std::make_unique>(); + + for (int i = 0; i < MAX_DUMMIES; i++) + { + CEntitySAInterface* object = (*m_ppDummyPoolInterface)->GetObject(i); + (*m_pLodBackup)[i] = object->m_pLod; + object->m_pLod = nullptr; + } +} + +void CDummyPoolSA::RestoreAllBuildingsLods() +{ + if (!m_pLodBackup) + return; + + for (int i = 0; i < MAX_DUMMIES; i++) + { + CEntitySAInterface* object = (*m_ppDummyPoolInterface)->GetObject(i); + object->m_pLod = (*m_pLodBackup)[i]; + } + + m_pLodBackup.release(); +} + +void CDummyPoolSA::UpdateBuildingLods(void* oldPool, void* newPool) +{ + const uint32_t offset = (uint32_t)newPool - (uint32_t)oldPool; + + if (m_pLodBackup) + { + for (int i = 0; i < MAX_DUMMIES; i++) + { + if ((*m_pLodBackup)[i] != nullptr) + { + (*m_pLodBackup)[i] = (CEntitySAInterface*)((uint32_t)(*m_pLodBackup)[i] + offset); + } + } + } + else + { + for (int i = 0; i < MAX_DUMMIES; i++) + { + CEntitySAInterface* object = (*m_ppDummyPoolInterface)->GetObject(i); + if (object->m_pLod) + { + object->m_pLod = (CEntitySAInterface*)((uint32_t)object->m_pLod + offset); + } + } + } +} diff --git a/Client/game_sa/CDummyPoolSA.h b/Client/game_sa/CDummyPoolSA.h new file mode 100644 index 0000000000..95d00b19f3 --- /dev/null +++ b/Client/game_sa/CDummyPoolSA.h @@ -0,0 +1,33 @@ +/***************************************************************************** + * + * PROJECT: Multi Theft Auto v1.0 + * LICENSE: See LICENSE in the top level directory + * FILE: game_sa/CDummyPoolSA.h + * PURPOSE: Dummy pool class + * + * Multi Theft Auto is available from http://www.multitheftauto.com/ + * + *****************************************************************************/ + +#pragma once + +#include +#include "CEntitySA.h" +#include "CPoolSAInterface.h" +#include + +class CDummyPoolSA : public CDummyPool +{ +public: + CDummyPoolSA(); + ~CDummyPoolSA() = default; + + void RemoveAllBuildingLods(); + void RestoreAllBuildingsLods(); + void UpdateBuildingLods(void* oldPool, void* newPool); + +private: + CPoolSAInterface** m_ppDummyPoolInterface; + + std::unique_ptr> m_pLodBackup; +}; diff --git a/Client/game_sa/CEntitySA.cpp b/Client/game_sa/CEntitySA.cpp index 5c61c38762..02a9f00380 100644 --- a/Client/game_sa/CEntitySA.cpp +++ b/Client/game_sa/CEntitySA.cpp @@ -23,9 +23,6 @@ extern CGameSA* pGame; -unsigned long CEntitySA::FUNC_CClumpModelInfo__GetFrameFromId; -unsigned long CEntitySA::FUNC_RwFrameGetLTM; - void CEntitySAInterface::TransformFromObjectSpace(CVector& outPosn, CVector const& offset) { ((void(__thiscall*)(CEntitySAInterface*, CVector&, CVector const&))0x533560)(this, outPosn, offset); @@ -439,17 +436,8 @@ eEntityStatus CEntitySA::GetEntityStatus() RwFrame* CEntitySA::GetFrameFromId(int id) { - DWORD dwClump = (DWORD)m_pInterface->m_pRwObject; - DWORD dwReturn; - _asm - { - push id - push dwClump - call FUNC_CClumpModelInfo__GetFrameFromId - add esp, 8 - mov dwReturn, eax - } - return (RwFrame*)dwReturn; + // CClumpModelInfo::GetFrameFromId + return ((RwFrame*(_cdecl*)(RpClump*, int))0x4C53C0)(m_pInterface->m_pRwObject, id); } RpClump* CEntitySA::GetRpClump() @@ -459,16 +447,8 @@ RpClump* CEntitySA::GetRpClump() RwMatrix* CEntitySA::GetLTMFromId(int id) { - DWORD dwReturn; - RwFrame* frame = GetFrameFromId(id); - _asm - { - push frame - call FUNC_RwFrameGetLTM - add esp, 4 - mov dwReturn, eax - } - return (RwMatrix*)dwReturn; + // RwFrameGetLTM + return ((RwMatrix*(_cdecl*)(RwFrame*))0x7F0990)(GetFrameFromId(id)); } void CEntitySA::SetAlpha(DWORD dwAlpha) @@ -623,55 +603,97 @@ bool CEntitySA::GetBoneRotation(eBone boneId, float& yaw, float& pitch, float& r return false; } +bool CEntitySA::GetBoneRotationQuat(eBone boneId, float& x, float& y, float& z, float& w) +{ + RpClump* clump = GetRpClump(); + if (!clump) + return false; + + // updating the bone frame orientation will also update its children + // This rotation is only applied when UpdateElementRpHAnim is called + auto* clumpDataInterface = *pGame->GetClumpData(clump); + auto* frameData = clumpDataInterface->GetFrameDataByNodeId(boneId); + if (!frameData) + return false; + + RtQuat* boneOrientation = &frameData->m_pIFrame->orientation; + x = boneOrientation->imag.x; + y = boneOrientation->imag.y; + z = boneOrientation->imag.z; + w = boneOrientation->real; + return true; +} + bool CEntitySA::SetBoneRotation(eBone boneId, float yaw, float pitch, float roll) { RpClump* clump = GetRpClump(); - if (clump) - { - // updating the bone frame orientation will also update its children - // This rotation is only applied when UpdateElementRpHAnim is called - CAnimBlendClumpDataSAInterface* clumpDataInterface = *pGame->GetClumpData(clump); - AnimBlendFrameData* frameData = clumpDataInterface->GetFrameDataByNodeId(boneId); - if (frameData) - { - RtQuat* boneOrientation = &frameData->m_pIFrame->orientation; - RwV3d angles = {yaw, roll, pitch}; - BoneNode_cSAInterface::EulerToQuat(&angles, boneOrientation); - CEntitySAInterface* theInterface = GetInterface(); - if (theInterface) - { - theInterface->bDontUpdateHierarchy = false; - } - return true; - } - } - return false; + if (!clump) + return false; + + // updating the bone frame orientation will also update its children + // This rotation is only applied when UpdateElementRpHAnim is called + auto* clumpDataInterface = *pGame->GetClumpData(clump); + auto* frameData = clumpDataInterface->GetFrameDataByNodeId(boneId); + if (!frameData) + return false; + + RtQuat* boneOrientation = &frameData->m_pIFrame->orientation; + RwV3d angles = { yaw, roll, pitch }; + BoneNode_cSAInterface::EulerToQuat(&angles, boneOrientation); + CEntitySAInterface* theInterface = GetInterface(); + if (theInterface) + theInterface->bDontUpdateHierarchy = false; + + return true; +} + +bool CEntitySA::SetBoneRotationQuat(eBone boneId, float x, float y, float z, float w) +{ + RpClump* clump = GetRpClump(); + if (!clump) + return false; + + // updating the bone frame orientation will also update its children + // This rotation is only applied when UpdateElementRpHAnim is called + auto* clumpDataInterface = *pGame->GetClumpData(clump); + auto* frameData = clumpDataInterface->GetFrameDataByNodeId(boneId); + if (!frameData) + return false; + + RtQuat* boneOrientation = &frameData->m_pIFrame->orientation; + boneOrientation->imag.x = x; + boneOrientation->imag.y = y; + boneOrientation->imag.z = z; + boneOrientation->real = w; + CEntitySAInterface* theInterface = GetInterface(); + if (theInterface) + theInterface->bDontUpdateHierarchy = false; + + return true; } bool CEntitySA::GetBonePosition(eBone boneId, CVector& position) { RwMatrix* rwBoneMatrix = GetBoneRwMatrix(boneId); - if (rwBoneMatrix) - { - const RwV3d& pos = rwBoneMatrix->pos; - position = {pos.x, pos.y, pos.z}; - return true; - } - return false; + if (!rwBoneMatrix) + return false; + + const RwV3d& pos = rwBoneMatrix->pos; + position = {pos.x, pos.y, pos.z}; + return true; } // NOTE: The position will be reset if UpdateElementRpHAnim is called after this. bool CEntitySA::SetBonePosition(eBone boneId, const CVector& position) { RwMatrix* rwBoneMatrix = GetBoneRwMatrix(boneId); - if (rwBoneMatrix) - { - CMatrixSAInterface boneMatrix(rwBoneMatrix, false); - boneMatrix.SetTranslateOnly(position); - boneMatrix.UpdateRW(); - return true; - } - return false; + if (!rwBoneMatrix) + return false; + + CMatrixSAInterface boneMatrix(rwBoneMatrix, false); + boneMatrix.SetTranslateOnly(position); + boneMatrix.UpdateRW(); + return true; } BYTE CEntitySA::GetAreaCode() diff --git a/Client/game_sa/CEntitySA.h b/Client/game_sa/CEntitySA.h index bc96426a99..548cb657f6 100644 --- a/Client/game_sa/CEntitySA.h +++ b/Client/game_sa/CEntitySA.h @@ -224,6 +224,24 @@ class CEntitySAInterface return numLodChildrenRendered & 0x1f; return -1; } + + void ResolveReferences() + { + using CEntity_ResolveReferences = void*(__thiscall*)(CEntitySAInterface*); + ((CEntity_ResolveReferences)0x571A40)(this); + }; + + void RemoveShadows() + { + using CStencilShadow_dtorByOwner = void*(__cdecl*)(CEntitySAInterface * pEntity); + ((CStencilShadow_dtorByOwner)0x711730)(this); + }; + + void DeleteRwObject() + { + using vtbl_DeleteRwObject = void(__thiscall*)(CEntitySAInterface * pEntity); + ((vtbl_DeleteRwObject)this->vtbl->DeleteRwObject)(this); + }; }; static_assert(sizeof(CEntitySAInterface) == 0x38, "Invalid size for CEntitySAInterface"); @@ -306,7 +324,9 @@ class CEntitySA : public virtual CEntity bool SetBoneMatrix(eBone boneId, const CMatrix& matrix); bool GetBoneRotation(eBone boneId, float& yaw, float& pitch, float& roll); + bool GetBoneRotationQuat(eBone boneId, float& x, float& y, float& z, float& w); bool SetBoneRotation(eBone boneId, float yaw, float pitch, float roll); + bool SetBoneRotationQuat(eBone boneId, float x, float y, float z, float w); bool GetBonePosition(eBone boneId, CVector& position); bool SetBonePosition(eBone boneId, const CVector& position); @@ -314,9 +334,6 @@ class CEntitySA : public virtual CEntity virtual void OnChangingPosition(const CVector& vecNewPosition) {} private: - static unsigned long FUNC_CClumpModelInfo__GetFrameFromId; - static unsigned long FUNC_RwFrameGetLTM; - void* m_pStoredPointer; CVector m_LastGoodPosition; }; diff --git a/Client/game_sa/CFileLoaderSA.cpp b/Client/game_sa/CFileLoaderSA.cpp index 5bb8dd1fe0..67cb476cf5 100644 --- a/Client/game_sa/CFileLoaderSA.cpp +++ b/Client/game_sa/CFileLoaderSA.cpp @@ -28,6 +28,12 @@ void CFileLoaderSA::StaticSetHooks() HookInstall(0x538690, (DWORD)CFileLoader_LoadObjectInstance, 5); } +CEntitySAInterface* CFileLoaderSA::LoadObjectInstance(SFileObjectInstance* obj) +{ + // Second argument is model name. It's unused in the function + return ((CEntitySAInterface * (__cdecl*)(SFileObjectInstance*, const char*))0x538090)(obj, nullptr); +} + class CAtomicModelInfo { public: diff --git a/Client/game_sa/CFileLoaderSA.h b/Client/game_sa/CFileLoaderSA.h index f18c7e4633..260bc93cb2 100644 --- a/Client/game_sa/CFileLoaderSA.h +++ b/Client/game_sa/CFileLoaderSA.h @@ -29,6 +29,8 @@ class CFileLoaderSA CFileLoaderSA(); ~CFileLoaderSA(); + static CEntitySAInterface* LoadObjectInstance(SFileObjectInstance*); + static void StaticSetHooks(); }; diff --git a/Client/game_sa/CFxSA.cpp b/Client/game_sa/CFxSA.cpp index dca7844fdf..b063cb927d 100644 --- a/Client/game_sa/CFxSA.cpp +++ b/Client/game_sa/CFxSA.cpp @@ -239,3 +239,93 @@ void CFxSA::TriggerFootSplash(CVector& vecPosition) call dwFunc } } + +void CFxSA::AddParticle(eFxParticleSystems eFxParticle, const CVector& vecPosition, const CVector& vecDirection, float fR, float fG, float fB, float fA, bool bRandomizeColors, std::uint32_t iCount, float fBrightness, float fSize, bool bRandomizeSizes, float fLife) +{ + // Init our own FxPrtMult struct + FxPrtMult_c fxPrt{{fR,fG,fB,fA}, fSize, 0, fLife}; + CVector newDirection; + + FxSystem_c* fxParticleSystem; + + switch (eFxParticle) + { + case eFxParticleSystems::PRT_BLOOD: + fxParticleSystem = m_pInterface->m_fxSysBlood; + break; + case eFxParticleSystems::PRT_BOATSPLASH: + fxParticleSystem = m_pInterface->m_fxSysBoatSplash; + break; + case eFxParticleSystems::PRT_BUBBLE: + fxParticleSystem = m_pInterface->m_fxSysBubble; + break; + case eFxParticleSystems::PRT_DEBRIS: + fxParticleSystem = m_pInterface->m_fxSysDebris; + break; + case eFxParticleSystems::PRT_GUNSHELL: + fxParticleSystem = m_pInterface->m_fxSysGunshell; + break; + case eFxParticleSystems::PRT_SAND: + fxParticleSystem = m_pInterface->m_fxSysSand; + break; + case eFxParticleSystems::PRT_SAND2: + fxParticleSystem = m_pInterface->m_fxSysSand2; + break; + case eFxParticleSystems::PRT_SMOKE: + fxParticleSystem = m_pInterface->m_fxSysSmoke; + break; + case eFxParticleSystems::PRT_SMOKEHUGE: + fxParticleSystem = m_pInterface->m_fxSysSmokeHuge; + break; + case eFxParticleSystems::PRT_SMOKE2: + fxParticleSystem = m_pInterface->m_fxSysSmoke2; + break; + case eFxParticleSystems::PRT_SPARK: + fxParticleSystem = m_pInterface->m_fxSysSpark; + break; + case eFxParticleSystems::PRT_SPARK2: + fxParticleSystem = m_pInterface->m_fxSysSpark2; + break; + case eFxParticleSystems::PRT_SPLASH: + fxParticleSystem = m_pInterface->m_fxSysSplash; + break; + case eFxParticleSystems::PRT_WAKE: + fxParticleSystem = m_pInterface->m_fxSysWake; + break; + case eFxParticleSystems::PRT_WATERSPLASH: + fxParticleSystem = m_pInterface->m_fxSysWaterSplash; + break; + case eFxParticleSystems::PRT_WHEELDIRT: + fxParticleSystem = m_pInterface->m_fxSysWheelDirt; + break; + case eFxParticleSystems::PRT_GLASS: + fxParticleSystem = m_pInterface->m_fxSysGlass; + break; + default: + fxParticleSystem = m_pInterface->m_fxSysBlood; + } + + for (size_t i = 0; i < iCount; i++) + { + if (bRandomizeColors) + { + // 0x49EECB + fxPrt.m_color.red = (rand() % 10000) * 0.0001f * fR + 0.13f; + fxPrt.m_color.green = (rand() % 10000) * 0.0001f * fG + 0.12f; + fxPrt.m_color.blue = (rand() % 10000) * 0.0001f * fB + 0.04f; + } + + if (bRandomizeSizes) + // 0x49EF21 - Calculate random size for each particle + fxPrt.m_fSize = (rand() % 10000) * 0.0001f * fSize + 0.3f; + + // 0x49EF4C - Calculate random direction for each particle + newDirection = CVector(vecDirection.fX * 4, vecDirection.fY * 4, vecDirection.fZ * 4); + newDirection.fX = (rand() % 10000) * 0.0001f * 4 - 2 + newDirection.fX; + newDirection.fY = (rand() % 10000) * 0.0001f * 4 - 2 + newDirection.fY; + newDirection.fZ = (rand() % 10000) * 0.0001f * 4 - 2 + newDirection.fZ; + + // Call FxSystem_c::AddParticle + ((int(__thiscall*)(FxSystem_c*, const CVector*, const CVector*, float, FxPrtMult_c*, float, float, float, int))FUNC_FXSystem_c_AddParticle)(fxParticleSystem, &vecPosition, &newDirection, 0, &fxPrt, -1.0f, fBrightness, 0, 0); + } +} diff --git a/Client/game_sa/CFxSA.h b/Client/game_sa/CFxSA.h index 55b56b83f2..7d61c1759a 100644 --- a/Client/game_sa/CFxSA.h +++ b/Client/game_sa/CFxSA.h @@ -14,6 +14,7 @@ #include struct RwColor; +class FxSystem_c; #define FUNC_CFx_AddBlood 0x49eb00 #define FUNC_CFx_AddWood 0x49ee10 @@ -29,10 +30,30 @@ struct RwColor; #define FUNC_CFx_TriggerWaterSplash 0x4a1070 #define FUNC_CFx_TriggerBulletSplash 0x4a10e0 #define FUNC_CFx_TriggerFootSplash 0x4a1150 +#define FUNC_FXSystem_c_AddParticle 0x4AA440 class CFxSAInterface { public: + FxSystem_c* m_fxSysBlood; + FxSystem_c* m_fxSysBoatSplash; + FxSystem_c* m_fxSysBubble; + FxSystem_c* m_fxSysDebris; + FxSystem_c* m_fxSysSmoke; + FxSystem_c* m_fxSysGunshell; + FxSystem_c* m_fxSysSand; + FxSystem_c* m_fxSysSand2; + FxSystem_c* m_fxSysSmokeHuge; + FxSystem_c* m_fxSysSmoke2; + FxSystem_c* m_fxSysSpark; + FxSystem_c* m_fxSysSpark2; + FxSystem_c* m_fxSysSplash; + FxSystem_c* m_fxSysWake; + FxSystem_c* m_fxSysWaterSplash; + FxSystem_c* m_fxSysWheelDirt; + FxSystem_c* m_fxSysGlass; + +private: }; class CFxSA : public CFx @@ -55,7 +76,23 @@ class CFxSA : public CFx void TriggerWaterSplash(CVector& vecPosition); void TriggerBulletSplash(CVector& vecPosition); void TriggerFootSplash(CVector& vecPosition); + void AddParticle(eFxParticleSystems eFxParticle, const CVector& vecPosition, const CVector& vecDirection, float fR, float fG, float fB, float fA, bool bRandomizeColors, std::uint32_t iCount, float fBrightness, float fSize, bool bRandomizeSizes, float fLife); private: CFxSAInterface* m_pInterface; + + struct FxPrtMult_c + { + struct + { + float red; + float green; + float blue; + float alpha; + } m_color; + + float m_fSize; + float unk; + float m_fLife; + }; }; diff --git a/Client/game_sa/CGameSA.cpp b/Client/game_sa/CGameSA.cpp index e88d72efcd..07ac611c09 100644 --- a/Client/game_sa/CGameSA.cpp +++ b/Client/game_sa/CGameSA.cpp @@ -38,7 +38,6 @@ #include "CHudSA.h" #include "CKeyGenSA.h" #include "CObjectGroupPhysicalPropertiesSA.h" -#include "COffsets.h" #include "CPadSA.h" #include "CPickupsSA.h" #include "CPlayerInfoSA.h" @@ -57,19 +56,13 @@ #include "CWeatherSA.h" #include "CWorldSA.h" #include "D3DResourceSystemSA.h" +#include "CIplStoreSA.h" +#include "CBuildingRemovalSA.h" +#include "CCheckpointSA.h" extern CGameSA* pGame; unsigned int& CGameSA::ClumpOffset = *(unsigned int*)0xB5F878; -unsigned long* CGameSA::VAR_SystemTime; -unsigned long* CGameSA::VAR_IsAtMenu; -bool* CGameSA::VAR_IsForegroundWindow; -unsigned long* CGameSA::VAR_SystemState; -float* CGameSA::VAR_TimeScale; -float* CGameSA::VAR_FPS; -float* CGameSA::VAR_OldTimeStep; -float* CGameSA::VAR_TimeStep; -unsigned long* CGameSA::VAR_Framelimiter; unsigned int OBJECTDYNAMICINFO_MAX = *(uint32_t*)0x59FB4C != 0x90909090 ? *(uint32_t*)0x59FB4C : 160; // default: 160 @@ -79,6 +72,10 @@ unsigned int OBJECTDYNAMICINFO_MAX = *(uint32_t*)0x59FB4C != 0x90909090 ? *(uint CGameSA::CGameSA() { pGame = this; + + // Find the game version and initialize m_eGameVersion so GetGameVersion() will return the correct value + FindGameVersion(); + m_bAsyncScriptEnabled = false; m_bAsyncScriptForced = false; m_bASyncLoadingSuspended = false; @@ -90,21 +87,6 @@ CGameSA::CGameSA() SetInitialVirtualProtect(); - // Initialize the offsets - eGameVersion version = FindGameVersion(); - switch (version) - { - case VERSION_EU_10: - COffsets::Initialize10EU(); - break; - case VERSION_US_10: - COffsets::Initialize10US(); - break; - case VERSION_11: - COffsets::Initialize11(); - break; - } - // Set the model ids for all the CModelInfoSA instances for (unsigned int i = 0; i < modelInfoMax; i++) { @@ -142,7 +124,7 @@ CGameSA::CGameSA() m_pCarEnterExit = new CCarEnterExitSA(); m_pControllerConfigManager = new CControllerConfigManagerSA(); m_pProjectileInfo = new CProjectileInfoSA(); - m_pRenderWare = new CRenderWareSA(version); + m_pRenderWare = new CRenderWareSA(); m_pHandlingManager = new CHandlingManagerSA(); m_pEventList = new CEventListSA(); m_pGarages = new CGaragesSA((CGaragesSAInterface*)CLASS_CGarages); @@ -158,6 +140,12 @@ CGameSA::CGameSA() m_pWeaponStatsManager = new CWeaponStatManagerSA(); m_pPointLights = new CPointLightsSA(); m_collisionStore = new CColStoreSA(); + m_pIplStore = new CIplStoreSA(); + m_pCoverManager = new CCoverManagerSA(); + m_pPlantManager = new CPlantManagerSA(); + m_pBuildingRemoval = new CBuildingRemovalSA(); + + m_pRenderer = std::make_unique(); // Normal weapon types (WEAPONSKILL_STD) for (int i = 0; i < NUM_WeaponInfosStdSkill; i++) @@ -253,6 +241,7 @@ CGameSA::CGameSA() CFileLoaderSA::StaticSetHooks(); D3DResourceSystemSA::StaticSetHooks(); CVehicleSA::StaticSetHooks(); + CCheckpointSA::StaticSetHooks(); } CGameSA::~CGameSA() @@ -294,6 +283,10 @@ CGameSA::~CGameSA() delete reinterpret_cast(m_pAudioContainer); delete reinterpret_cast(m_pPointLights); delete static_cast(m_collisionStore); + delete static_cast(m_pIplStore); + delete static_cast(m_pBuildingRemoval); + delete m_pCoverManager; + delete m_pPlantManager; delete[] ModelInfo; delete[] ObjectGroupsInfo; @@ -363,12 +356,12 @@ void CGameSA::StartGame() */ void CGameSA::SetSystemState(eSystemState State) { - *VAR_SystemState = (DWORD)State; + MemPutFast(0xC8D4C0, State); // gGameState } eSystemState CGameSA::GetSystemState() { - return (eSystemState)*VAR_SystemState; + return *(eSystemState*)0xC8D4C0; // gGameState } /** @@ -446,6 +439,9 @@ void CGameSA::Reset() // Restore changed TXD IDs CModelInfoSA::StaticResetTextureDictionaries(); + + // Restore default world state + RestoreGameBuildings(); } } @@ -503,27 +499,27 @@ eGameVersion CGameSA::FindGameVersion() float CGameSA::GetFPS() { - return *VAR_FPS; + return *(float*)0xB7CB50; // CTimer::game_FPS } float CGameSA::GetTimeStep() { - return *VAR_TimeStep; + return *(float*)0xB7CB5C; // CTimer::ms_fTimeStep } float CGameSA::GetOldTimeStep() { - return *VAR_OldTimeStep; + return *(float*)0xB7CB54; // CTimer::ms_fOldTimeStep } float CGameSA::GetTimeScale() { - return *VAR_TimeScale; + return *(float*)0xB7CB64; // CTimer::ms_fTimeScale } void CGameSA::SetTimeScale(float fTimeScale) { - *VAR_TimeScale = fTimeScale; + MemPutFast(0xB7CB64, fTimeScale); // CTimer::ms_fTimeScale } unsigned char CGameSA::GetBlurLevel() @@ -672,7 +668,7 @@ void CGameSA::SetCoronaZTestEnabled(bool isEnabled) m_isCoronaZTestEnabled = isEnabled; } -void CGameSA::SetWaterCreaturesEnabled(bool isEnabled) +void CGameSA::SetWaterCreaturesEnabled(bool isEnabled) { if (isEnabled == m_areWaterCreaturesEnabled) return; @@ -692,6 +688,29 @@ void CGameSA::SetWaterCreaturesEnabled(bool isEnabled) m_areWaterCreaturesEnabled = isEnabled; } +void CGameSA::SetTunnelWeatherBlendEnabled(bool isEnabled) +{ + if (isEnabled == m_isTunnelWeatherBlendEnabled) + return; + // CWeather::UpdateInTunnelness + DWORD functionAddress = 0x72B630; + if (isEnabled) + { + // Restore original bytes: 83 EC 20 + MemPut(functionAddress, 0x83); // Restore 83 + MemPut(functionAddress + 1, 0xEC); // Restore EC + MemPut(functionAddress + 2, 0x20); // Restore 20 + } + else + { + // Patch CWeather::UpdateInTunnelness (Found By AlexTMjugador) + MemPut(functionAddress, 0xC3); // Write C3 (RET) + MemPut(functionAddress + 1, 0x90); // Write 90 (NOP) + MemPut(functionAddress + 2, 0x90); // Write 90 (NOP) + } + m_isTunnelWeatherBlendEnabled = isEnabled; +} + void CGameSA::SetBurnFlippedCarsEnabled(bool isEnabled) { if (isEnabled == m_isBurnFlippedCarsEnabled) @@ -744,6 +763,91 @@ void CGameSA::SetFireballDestructEnabled(bool isEnabled) m_isFireballDestructEnabled = isEnabled; } +void CGameSA::SetExtendedWaterCannonsEnabled(bool isEnabled) +{ + if (isEnabled == m_isExtendedWaterCannonsEnabled) + return; + + // Allocate memory for new bigger array or use default aCannons array + void* aCannons = isEnabled ? malloc(MAX_WATER_CANNONS * SIZE_CWaterCannon) : (void*)ARRAY_aCannons; + + int newLimit = isEnabled ? MAX_WATER_CANNONS : NUM_CWaterCannon_DefaultLimit; // default: 3 + MemSetFast(aCannons, 0, newLimit * SIZE_CWaterCannon); // clear aCannons array + + // Get current limit + int currentLimit = *(int*)NUM_WaterCannon_Limit; + + // Get current aCannons array + void* currentACannons = *(void**)ARRAY_aCannons_CurrentPtr; + + // Call CWaterCannon destructor + for (int i = 0; i < currentLimit; i++) + { + char* currentCannon = (char*)currentACannons + i * SIZE_CWaterCannon; + + ((void(__thiscall*)(int, void*, bool))FUNC_CAESoundManager_CancelSoundsOwnedByAudioEntity)(STRUCT_CAESoundManager, currentCannon + NUM_CWaterCannon_Audio_Offset, true); // CAESoundManager::CancelSoundsOwnedByAudioEntity to prevent random crashes from CAESound::UpdateParameters + ((void(__thiscall*)(void*))FUNC_CWaterCannon_Destructor)(currentCannon); // CWaterCannon::~CWaterCannon + } + + // Call CWaterCannon constructor & CWaterCannon::Init + for (int i = 0; i < newLimit; ++i) + { + char* currentCannon = (char*)aCannons + i * SIZE_CWaterCannon; + + ((void(__thiscall*)(void*))FUNC_CWaterCannon_Constructor)(currentCannon); // CWaterCannon::CWaterCannon + ((void(__thiscall*)(void*))FUNC_CWaterCannon_Init)(currentCannon); // CWaterCannon::Init + } + + // Patch references to array + MemPut((void*)0x728C83, aCannons); // CWaterCannons::Init + MemPut((void*)0x728CCB, aCannons); // CWaterCannons::UpdateOne + MemPut((void*)0x728CEB, aCannons); // CWaterCannons::UpdateOne + MemPut((void*)0x728D0D, aCannons); // CWaterCannons::UpdateOne + MemPut((void*)0x728D71, aCannons); // CWaterCannons::UpdateOne + MemPutFast((void*)0x729B33, aCannons); // CWaterCannons::Render + MemPut((void*)0x72A3C5, aCannons); // CWaterCannons::UpdateOne + MemPut((void*)0x855432, aCannons); // 0x855431 + MemPut((void*)0x856BFD, aCannons); // 0x856BFC + + // CWaterCannons::Init + MemPut(0x728C88, newLimit); + + // CWaterCannons::Update + MemPut(0x72A3F2, newLimit); + + // CWaterCanons::UpdateOne + MemPut(0x728CD4, newLimit); + MemPut(0x728CF6, newLimit); + MemPut(0x728CFF, newLimit); + MemPut(0x728D62, newLimit); + + // CWaterCannons::Render + MemPutFast(0x729B38, newLimit); + + // 0x85542A + MemPut(0x85542B, newLimit); + + // 0x856BF5 + MemPut(0x856BF6, newLimit); + + // Free previous allocated memory + if (!isEnabled && currentACannons != nullptr) + free(currentACannons); + + m_isExtendedWaterCannonsEnabled = isEnabled; +} + +void CGameSA::SetRoadSignsTextEnabled(bool isEnabled) +{ + if (isEnabled == m_isRoadSignsTextEnabled) + return; + + // Skip JMP to CCustomRoadsignMgr::RenderRoadsignAtomic + MemPut(0x5342ED, isEnabled ? 0xEB : 0x74); + + m_isRoadSignsTextEnabled = isEnabled; +} + bool CGameSA::PerformChecks() { std::map::iterator it; @@ -903,6 +1007,50 @@ void CGameSA::GetShaderReplacementStats(SShaderReplacementStats& outStats) m_pRenderWare->GetShaderReplacementStats(outStats); } +void CGameSA::RemoveAllBuildings() +{ + m_pIplStore->SetDynamicIplStreamingEnabled(false); + + m_pPools->GetDummyPool().RemoveAllBuildingLods(); + m_pPools->GetBuildingsPool().RemoveAllBuildings(); + + auto pBuildingRemoval = static_cast(m_pBuildingRemoval); + pBuildingRemoval->DropCaches(); + + m_isBuildingsRemoved = true; +} + +void CGameSA::RestoreGameBuildings() +{ + m_pPools->GetBuildingsPool().RestoreAllBuildings(); + m_pPools->GetDummyPool().RestoreAllBuildingsLods(); + + m_pIplStore->SetDynamicIplStreamingEnabled(true, [](CIplSAInterface* ipl) { return memcmp("barriers", ipl->name, 8) != 0; }); + m_isBuildingsRemoved = false; +} + +bool CGameSA::SetBuildingPoolSize(size_t size) +{ + const bool shouldRemoveBuilding = !m_isBuildingsRemoved; + if (shouldRemoveBuilding) + { + RemoveAllBuildings(); + } + else + { + static_cast(m_pBuildingRemoval)->DropCaches(); + } + + bool status = m_pPools->GetBuildingsPool().Resize(size); + + if (shouldRemoveBuilding) + { + RestoreGameBuildings(); + } + + return status; +} + // Ensure models have the default lod distances void CGameSA::ResetModelLodDistances() { diff --git a/Client/game_sa/CGameSA.h b/Client/game_sa/CGameSA.h index 8d420422fc..cf4788d953 100644 --- a/Client/game_sa/CGameSA.h +++ b/Client/game_sa/CGameSA.h @@ -15,6 +15,9 @@ #include "CFxManagerSA.h" #include "CModelInfoSA.h" #include "CStreamingSA.h" +#include "CCoverManagerSA.h" +#include "CPlantManagerSA.h" +#include "CRendererSA.h" class CAnimBlendClumpDataSAInterface; class CObjectGroupPhysicalPropertiesSA; @@ -80,6 +83,20 @@ extern unsigned int OBJECTDYNAMICINFO_MAX; // default: 160 #define CHEAT_NEVERWANTED "neverwanted" #define CHEAT_HEALTARMORMONEY "healtharmormoney" +#define FUNC_CAESoundManager_CancelSoundsOwnedByAudioEntity 0x4EFCD0 +#define STRUCT_CAESoundManager 0xB62CB0 +#define FUNC_CWaterCannon_Constructor 0x728B10 +#define FUNC_CWaterCannon_Destructor 0x728B30 +#define FUNC_CWaterCannon_Init 0x728B40 +#define ARRAY_aCannons 0xC80740 +#define ARRAY_aCannons_CurrentPtr 0x728C83 +#define NUM_WaterCannon_Limit 0x728C88 +#define SIZE_CWaterCannon 0x3CC +#define NUM_CWaterCannon_Audio_Offset 0x32C +#define NUM_CWaterCannon_DefaultLimit 3 + +constexpr int MAX_WATER_CANNONS = 30; // extended CWaterCannon limit, it can be increased + struct SCheatSA { BYTE* m_byAddress; // Cheat Address @@ -152,7 +169,12 @@ class CGameSA : public CGame CColStore* GetCollisionStore() override { return m_collisionStore; } CRenderWareSA* GetRenderWareSA() { return m_pRenderWare; } CFxManagerSA* GetFxManagerSA() { return m_pFxManager; } - + CIplStore* GetIplStore() { return m_pIplStore; }; + CCoverManagerSA* GetCoverManager() const noexcept { return m_pCoverManager; }; + CPlantManagerSA* GetPlantManager() const noexcept { return m_pPlantManager; }; + CBuildingRemoval* GetBuildingRemoval() { return m_pBuildingRemoval; } + CRenderer* GetRenderer() const noexcept override { return m_pRenderer.get(); } + CWeaponInfo* GetWeaponInfo(eWeaponType weapon, eWeaponSkill skill = WEAPONSKILL_STD); CModelInfo* GetModelInfo(DWORD dwModelID, bool bCanBeInvalid = false); CObjectGroupPhysicalProperties* GetObjectGroupPhysicalProperties(unsigned char ucObjectGroup); @@ -167,9 +189,9 @@ class CGameSA : public CGame int32_t GetBaseIDforSCM() { return *(int32_t*)(0x46A574 + 2); } int32_t GetCountOfAllFileIDs() { return (*(char**)(0x5B8AFA + 2) - *(char**)(0x5B8B08 + 6)) / sizeof(CStreamingInfo); } - DWORD GetSystemTime() { return *VAR_SystemTime; } + DWORD GetSystemTime() { return *(DWORD*)0xB7CB84; } // CTimer::m_snTimeInMilliseconds - bool IsAtMenu() { return *VAR_IsAtMenu != 0; } + bool IsAtMenu() { return *(unsigned long*)0xBA677B != 0; } // FrontEndMenuManager + 0x33 void StartGame(); void SetSystemState(eSystemState State); @@ -218,6 +240,16 @@ class CGameSA : public CGame bool IsFireballDestructEnabled() const noexcept override { return m_isFireballDestructEnabled; } void SetFireballDestructEnabled(bool isEnabled) override; + bool IsExtendedWaterCannonsEnabled() const noexcept override { return m_isExtendedWaterCannonsEnabled; } + void SetExtendedWaterCannonsEnabled(bool isEnabled) override; + + bool IsRoadSignsTextEnabled() const noexcept override { return m_isRoadSignsTextEnabled; } + void SetRoadSignsTextEnabled(bool isEnabled) override; + + bool IsTunnelWeatherBlendEnabled() const noexcept override { return m_isTunnelWeatherBlendEnabled; } + void SetTunnelWeatherBlendEnabled(bool isEnabled) override; + + unsigned long GetMinuteDuration(); void SetMinuteDuration(unsigned long ulTime); @@ -273,6 +305,11 @@ class CGameSA : public CGame PostWeaponFireHandler* m_pPostWeaponFireHandler; TaskSimpleBeHitHandler* m_pTaskSimpleBeHitHandler; + void RemoveAllBuildings(); + void RestoreGameBuildings(); + + bool SetBuildingPoolSize(size_t size); + private: CPools* m_pPools; CPlayerInfo* m_pPlayerInfo; @@ -307,6 +344,11 @@ class CGameSA : public CGame CPointLights* m_pPointLights; CColStore* m_collisionStore; CObjectGroupPhysicalProperties* m_pObjectGroupPhysicalProperties; + CCoverManagerSA* m_pCoverManager; + CPlantManagerSA* m_pPlantManager; + CBuildingRemoval* m_pBuildingRemoval; + + std::unique_ptr m_pRenderer; CPad* m_pPad; CAERadioTrackManager* m_pCAERadioTrackManager; @@ -320,6 +362,7 @@ class CGameSA : public CGame CGameSettings* m_pSettings; CCarEnterExit* m_pCarEnterExit; CControllerConfigManager* m_pControllerConfigManager; + CIplStore* m_pIplStore; eGameVersion m_eGameVersion; bool m_bAsyncScriptEnabled; @@ -328,20 +371,15 @@ class CGameSA : public CGame int m_iCheckStatus; bool m_bUnderworldWarp; bool m_isCoronaZTestEnabled{true}; + bool m_isTunnelWeatherBlendEnabled{true}; bool m_areWaterCreaturesEnabled{true}; bool m_isBurnFlippedCarsEnabled{true}; bool m_isFireballDestructEnabled{true}; + bool m_isRoadSignsTextEnabled{true}; + bool m_isBuildingsRemoved{false}; + bool m_isExtendedWaterCannonsEnabled{false}; static unsigned int& ClumpOffset; - static unsigned long* VAR_SystemTime; - static unsigned long* VAR_IsAtMenu; - static bool* VAR_IsForegroundWindow; - static unsigned long* VAR_SystemState; - static float* VAR_TimeScale; - static float* VAR_FPS; - static float* VAR_OldTimeStep; - static float* VAR_TimeStep; - static unsigned long* VAR_Framelimiter; std::map m_Cheats; diff --git a/Client/game_sa/CHandlingEntrySA.cpp b/Client/game_sa/CHandlingEntrySA.cpp index 40e8b86423..1ebb1471e3 100644 --- a/Client/game_sa/CHandlingEntrySA.cpp +++ b/Client/game_sa/CHandlingEntrySA.cpp @@ -1,11 +1,11 @@ /***************************************************************************** * - * PROJECT: Multi Theft Auto v1.0 + * PROJECT: Multi Theft Auto * LICENSE: See LICENSE in the top level directory - * FILE: game_sa/CHandlingEntrySA.cpp + * FILE: Client/game_sa/CHandlingEntrySA.cpp * PURPOSE: Vehicle handling data entry * - * Multi Theft Auto is available from http://www.multitheftauto.com/ + * Multi Theft Auto is available from https://multitheftauto.com/ * *****************************************************************************/ @@ -22,91 +22,89 @@ CHandlingEntrySA::CHandlingEntrySA() m_pHandlingSA = new tHandlingDataSA; memset(m_pHandlingSA, 0, sizeof(tHandlingDataSA)); m_bDeleteInterface = true; - - // We have no original data - m_pOriginalData = NULL; - m_bChanged = true; } CHandlingEntrySA::CHandlingEntrySA(tHandlingDataSA* pOriginal) { // Store gta's pointer - m_pHandlingSA = NULL; - m_pOriginalData = NULL; + m_pHandlingSA = nullptr; m_bDeleteInterface = false; memcpy(&m_Handling, pOriginal, sizeof(tHandlingDataSA)); - m_bChanged = true; } CHandlingEntrySA::~CHandlingEntrySA() { - if (m_bChanged) - { - pGame->GetHandlingManager()->RemoveChangedVehicle(); - } if (m_bDeleteInterface) { - delete m_pHandlingSA; + SAFE_DELETE(m_pHandlingSA); } } // Apply the handlingdata from another data -void CHandlingEntrySA::Assign(const CHandlingEntry* pData) +void CHandlingEntrySA::Assign(const CHandlingEntry* pEntry) { + if (!pEntry) + return; + // Copy the data - const CHandlingEntrySA* pEntrySA = static_cast(pData); + const CHandlingEntrySA* pEntrySA = static_cast(pEntry); m_Handling = pEntrySA->m_Handling; - if (m_bChanged) - { - pGame->GetHandlingManager()->RemoveChangedVehicle(); - } - pGame->GetHandlingManager()->CheckSuspensionChanges(this); } -void CHandlingEntrySA::Recalculate(unsigned short usModel) +void CHandlingEntrySA::Recalculate() { // Real GTA class? - if (m_pHandlingSA) - { - // Copy our stored field to GTA's - memcpy(m_pHandlingSA, &m_Handling, sizeof(m_Handling)); - ((void(_stdcall*)(tHandlingDataSA*))FUNC_HandlingDataMgr_ConvertDataToGameUnits)(m_pHandlingSA); - } + if (!m_pHandlingSA) + return; + + // Copy our stored field to GTA's + memcpy(m_pHandlingSA, &m_Handling, sizeof(m_Handling)); + ((void(_stdcall*)(tHandlingDataSA*))FUNC_HandlingDataMgr_ConvertDataToGameUnits)(m_pHandlingSA); } -// Moved to cpp to check suspension changes against default values to make sure the handling hasn't changed. -void CHandlingEntrySA::SetSuspensionForceLevel(float fForce) +void CHandlingEntrySA::SetSuspensionForceLevel(float fForce) noexcept { + CheckSuspensionChanges(); m_Handling.fSuspensionForceLevel = fForce; - pGame->GetHandlingManager()->CheckSuspensionChanges(this); } -void CHandlingEntrySA::SetSuspensionDamping(float fDamping) + +void CHandlingEntrySA::SetSuspensionDamping(float fDamping) noexcept { + CheckSuspensionChanges(); m_Handling.fSuspensionDamping = fDamping; - pGame->GetHandlingManager()->CheckSuspensionChanges(this); } -void CHandlingEntrySA::SetSuspensionHighSpeedDamping(float fDamping) + +void CHandlingEntrySA::SetSuspensionHighSpeedDamping(float fDamping) noexcept { + CheckSuspensionChanges(); m_Handling.fSuspensionHighSpdDamping = fDamping; - pGame->GetHandlingManager()->CheckSuspensionChanges(this); } -void CHandlingEntrySA::SetSuspensionUpperLimit(float fUpperLimit) + +void CHandlingEntrySA::SetSuspensionUpperLimit(float fUpperLimit) noexcept { + CheckSuspensionChanges(); m_Handling.fSuspensionUpperLimit = fUpperLimit; - pGame->GetHandlingManager()->CheckSuspensionChanges(this); } -void CHandlingEntrySA::SetSuspensionLowerLimit(float fLowerLimit) + +void CHandlingEntrySA::SetSuspensionLowerLimit(float fLowerLimit) noexcept { + CheckSuspensionChanges(); m_Handling.fSuspensionLowerLimit = fLowerLimit; - pGame->GetHandlingManager()->CheckSuspensionChanges(this); } -void CHandlingEntrySA::SetSuspensionFrontRearBias(float fBias) + +void CHandlingEntrySA::SetSuspensionFrontRearBias(float fBias) noexcept { + CheckSuspensionChanges(); m_Handling.fSuspensionFrontRearBias = fBias; - pGame->GetHandlingManager()->CheckSuspensionChanges(this); } -void CHandlingEntrySA::SetSuspensionAntiDiveMultiplier(float fAntidive) + +void CHandlingEntrySA::SetSuspensionAntiDiveMultiplier(float fAntidive) noexcept { + CheckSuspensionChanges(); m_Handling.fSuspensionAntiDiveMultiplier = fAntidive; +} + +void CHandlingEntrySA::CheckSuspensionChanges() noexcept +{ pGame->GetHandlingManager()->CheckSuspensionChanges(this); } diff --git a/Client/game_sa/CHandlingEntrySA.h b/Client/game_sa/CHandlingEntrySA.h index ede72766f8..d1836f461e 100644 --- a/Client/game_sa/CHandlingEntrySA.h +++ b/Client/game_sa/CHandlingEntrySA.h @@ -1,17 +1,18 @@ /***************************************************************************** * - * PROJECT: Multi Theft Auto v1.0 + * PROJECT: Multi Theft Auto * LICENSE: See LICENSE in the top level directory - * FILE: game_sa/CHandlingEntrySA.h + * FILE: Client/game_sa/CHandlingEntrySA.h * PURPOSE: Header file for vehicle handling data entry class * - * Multi Theft Auto is available from http://www.multitheftauto.com/ + * Multi Theft Auto is available from https://multitheftauto.com/ * *****************************************************************************/ #pragma once #include + #define FUNC_HandlingDataMgr_ConvertDataToGameUnits 0x6F5080 // http://www.gtamodding.com/index.php?title=Handling.cfg#GTA_San_Andreas @@ -95,111 +96,107 @@ class CHandlingEntrySA : public CHandlingEntry virtual ~CHandlingEntrySA(); // Use this to copy data from an another handling class to this - void Assign(const CHandlingEntry* pData); + void Assign(const CHandlingEntry* pEntry); // Get functions - float GetMass() const { return m_Handling.fMass; }; - float GetTurnMass() const { return m_Handling.fTurnMass; }; - float GetDragCoeff() const { return m_Handling.fDragCoeff; }; - const CVector& GetCenterOfMass() const { return m_Handling.vecCenterOfMass; }; + float GetMass() const { return m_Handling.fMass; } + float GetTurnMass() const { return m_Handling.fTurnMass; } + float GetDragCoeff() const { return m_Handling.fDragCoeff; } + const CVector& GetCenterOfMass() const { return m_Handling.vecCenterOfMass; } - unsigned int GetPercentSubmerged() const { return m_Handling.uiPercentSubmerged; }; - float GetTractionMultiplier() const { return m_Handling.fTractionMultiplier; }; + unsigned int GetPercentSubmerged() const { return m_Handling.uiPercentSubmerged; } + float GetTractionMultiplier() const { return m_Handling.fTractionMultiplier; } - eDriveType GetCarDriveType() const { return static_cast(m_Handling.Transmission.ucDriveType); }; - eEngineType GetCarEngineType() const { return static_cast(m_Handling.Transmission.ucEngineType); }; - unsigned char GetNumberOfGears() const { return m_Handling.Transmission.ucNumberOfGears; }; + eDriveType GetCarDriveType() const { return static_cast(m_Handling.Transmission.ucDriveType); } + eEngineType GetCarEngineType() const { return static_cast(m_Handling.Transmission.ucEngineType); } + unsigned char GetNumberOfGears() const { return m_Handling.Transmission.ucNumberOfGears; } - float GetEngineAcceleration() const { return m_Handling.Transmission.fEngineAcceleration; }; - float GetEngineInertia() const { return m_Handling.Transmission.fEngineInertia; }; - float GetMaxVelocity() const { return m_Handling.Transmission.fMaxVelocity; }; + float GetEngineAcceleration() const { return m_Handling.Transmission.fEngineAcceleration; } + float GetEngineInertia() const { return m_Handling.Transmission.fEngineInertia; } + float GetMaxVelocity() const { return m_Handling.Transmission.fMaxVelocity; } - float GetBrakeDeceleration() const { return m_Handling.fBrakeDeceleration; }; - float GetBrakeBias() const { return m_Handling.fBrakeBias; }; - bool GetABS() const { return m_Handling.bABS; }; + float GetBrakeDeceleration() const { return m_Handling.fBrakeDeceleration; } + float GetBrakeBias() const { return m_Handling.fBrakeBias; } + bool GetABS() const { return m_Handling.bABS; } - float GetSteeringLock() const { return m_Handling.fSteeringLock; }; - float GetTractionLoss() const { return m_Handling.fTractionLoss; }; - float GetTractionBias() const { return m_Handling.fTractionBias; }; + float GetSteeringLock() const { return m_Handling.fSteeringLock; } + float GetTractionLoss() const { return m_Handling.fTractionLoss; } + float GetTractionBias() const { return m_Handling.fTractionBias; } - float GetSuspensionForceLevel() const { return m_Handling.fSuspensionForceLevel; }; - float GetSuspensionDamping() const { return m_Handling.fSuspensionDamping; }; - float GetSuspensionHighSpeedDamping() const { return m_Handling.fSuspensionHighSpdDamping; }; - float GetSuspensionUpperLimit() const { return m_Handling.fSuspensionUpperLimit; }; - float GetSuspensionLowerLimit() const { return m_Handling.fSuspensionLowerLimit; }; - float GetSuspensionFrontRearBias() const { return m_Handling.fSuspensionFrontRearBias; }; - float GetSuspensionAntiDiveMultiplier() const { return m_Handling.fSuspensionAntiDiveMultiplier; }; + float GetSuspensionForceLevel() const { return m_Handling.fSuspensionForceLevel; } + float GetSuspensionDamping() const { return m_Handling.fSuspensionDamping; } + float GetSuspensionHighSpeedDamping() const { return m_Handling.fSuspensionHighSpdDamping; } + float GetSuspensionUpperLimit() const { return m_Handling.fSuspensionUpperLimit; } + float GetSuspensionLowerLimit() const { return m_Handling.fSuspensionLowerLimit; } + float GetSuspensionFrontRearBias() const { return m_Handling.fSuspensionFrontRearBias; } + float GetSuspensionAntiDiveMultiplier() const { return m_Handling.fSuspensionAntiDiveMultiplier; } - float GetCollisionDamageMultiplier() const { return m_Handling.fCollisionDamageMultiplier; }; + float GetCollisionDamageMultiplier() const { return m_Handling.fCollisionDamageMultiplier; } - unsigned int GetHandlingFlags() const { return m_Handling.uiHandlingFlags; }; - unsigned int GetModelFlags() const { return m_Handling.uiModelFlags; }; - float GetSeatOffsetDistance() const { return m_Handling.fSeatOffsetDistance; }; - unsigned int GetMonetary() const { return m_Handling.uiMonetary; }; + unsigned int GetHandlingFlags() const { return m_Handling.uiHandlingFlags; } + unsigned int GetModelFlags() const { return m_Handling.uiModelFlags; } + float GetSeatOffsetDistance() const { return m_Handling.fSeatOffsetDistance; } + unsigned int GetMonetary() const { return m_Handling.uiMonetary; } - eLightType GetHeadLight() const { return static_cast(m_Handling.ucHeadLight); }; - eLightType GetTailLight() const { return static_cast(m_Handling.ucTailLight); }; - unsigned char GetAnimGroup() const { return m_Handling.ucAnimGroup; }; + eLightType GetHeadLight() const { return static_cast(m_Handling.ucHeadLight); } + eLightType GetTailLight() const { return static_cast(m_Handling.ucTailLight); } + unsigned char GetAnimGroup() const { return m_Handling.ucAnimGroup; } - eVehicleTypes GetModel() const { return static_cast(m_Handling.iVehicleID); }; - bool HasSuspensionChanged() const { return true; }; + std::uint16_t GetVehicleID() const { return static_cast(m_Handling.iVehicleID); } // Set functions - void SetMass(float fMass) { m_Handling.fMass = fMass; }; - void SetTurnMass(float fTurnMass) { m_Handling.fTurnMass = fTurnMass; }; - void SetDragCoeff(float fDrag) { m_Handling.fDragCoeff = fDrag; }; - void SetCenterOfMass(const CVector& vecCenter) { m_Handling.vecCenterOfMass = vecCenter; }; + void SetMass(float fMass) { m_Handling.fMass = fMass; } + void SetTurnMass(float fTurnMass) { m_Handling.fTurnMass = fTurnMass; } + void SetDragCoeff(float fDrag) { m_Handling.fDragCoeff = fDrag; } + void SetCenterOfMass(const CVector& vecCenter) { m_Handling.vecCenterOfMass = vecCenter; } - void SetPercentSubmerged(unsigned int uiPercent) { m_Handling.uiPercentSubmerged = uiPercent; }; - void SetTractionMultiplier(float fTractionMultiplier) { m_Handling.fTractionMultiplier = fTractionMultiplier; }; + void SetPercentSubmerged(unsigned int uiPercent) { m_Handling.uiPercentSubmerged = uiPercent; } + void SetTractionMultiplier(float fTractionMultiplier) { m_Handling.fTractionMultiplier = fTractionMultiplier; } - void SetCarDriveType(eDriveType Type) { m_Handling.Transmission.ucDriveType = Type; }; - void SetCarEngineType(eEngineType Type) { m_Handling.Transmission.ucEngineType = Type; }; - void SetNumberOfGears(unsigned char ucNumber) { m_Handling.Transmission.ucNumberOfGears = ucNumber; }; + void SetCarDriveType(eDriveType Type) { m_Handling.Transmission.ucDriveType = Type; } + void SetCarEngineType(eEngineType Type) { m_Handling.Transmission.ucEngineType = Type; } + void SetNumberOfGears(unsigned char ucNumber) { m_Handling.Transmission.ucNumberOfGears = ucNumber; } - void SetEngineAcceleration(float fAcceleration) { m_Handling.Transmission.fEngineAcceleration = fAcceleration; }; - void SetEngineInertia(float fInertia) { m_Handling.Transmission.fEngineInertia = fInertia; }; - void SetMaxVelocity(float fVelocity) { m_Handling.Transmission.fMaxVelocity = fVelocity; }; + void SetEngineAcceleration(float fAcceleration) { m_Handling.Transmission.fEngineAcceleration = fAcceleration; } + void SetEngineInertia(float fInertia) { m_Handling.Transmission.fEngineInertia = fInertia; } + void SetMaxVelocity(float fVelocity) { m_Handling.Transmission.fMaxVelocity = fVelocity; } - void SetBrakeDeceleration(float fDeceleration) { m_Handling.fBrakeDeceleration = fDeceleration; }; - void SetBrakeBias(float fBias) { m_Handling.fBrakeBias = fBias; }; - void SetABS(bool bABS) { m_Handling.bABS = bABS; }; + void SetBrakeDeceleration(float fDeceleration) { m_Handling.fBrakeDeceleration = fDeceleration; } + void SetBrakeBias(float fBias) { m_Handling.fBrakeBias = fBias; } + void SetABS(bool bABS) { m_Handling.bABS = bABS; } - void SetSteeringLock(float fSteeringLock) { m_Handling.fSteeringLock = fSteeringLock; }; - void SetTractionLoss(float fTractionLoss) { m_Handling.fTractionLoss = fTractionLoss; }; - void SetTractionBias(float fTractionBias) { m_Handling.fTractionBias = fTractionBias; }; + void SetSteeringLock(float fSteeringLock) { m_Handling.fSteeringLock = fSteeringLock; } + void SetTractionLoss(float fTractionLoss) { m_Handling.fTractionLoss = fTractionLoss; } + void SetTractionBias(float fTractionBias) { m_Handling.fTractionBias = fTractionBias; } - void SetSuspensionForceLevel(float fForce); - void SetSuspensionDamping(float fDamping); - void SetSuspensionHighSpeedDamping(float fDamping); - void SetSuspensionUpperLimit(float fUpperLimit); - void SetSuspensionLowerLimit(float fLowerLimit); - void SetSuspensionFrontRearBias(float fBias); - void SetSuspensionAntiDiveMultiplier(float fAntidive); + void SetSuspensionForceLevel(float fForce) noexcept; + void SetSuspensionDamping(float fDamping) noexcept; + void SetSuspensionHighSpeedDamping(float fDamping) noexcept; + void SetSuspensionUpperLimit(float fUpperLimit) noexcept; + void SetSuspensionLowerLimit(float fLowerLimit) noexcept; + void SetSuspensionFrontRearBias(float fBias) noexcept; + void SetSuspensionAntiDiveMultiplier(float fAntidive) noexcept; - void SetCollisionDamageMultiplier(float fMultiplier) { m_Handling.fCollisionDamageMultiplier = fMultiplier; }; + void SetCollisionDamageMultiplier(float fMultiplier) { m_Handling.fCollisionDamageMultiplier = fMultiplier; } - void SetHandlingFlags(unsigned int uiFlags) { m_Handling.uiHandlingFlags = uiFlags; }; - void SetModelFlags(unsigned int uiFlags) { m_Handling.uiModelFlags = uiFlags; }; - void SetSeatOffsetDistance(float fDistance) { m_Handling.fSeatOffsetDistance = fDistance; }; - void SetMonetary(unsigned int uiMonetary) { m_Handling.uiMonetary = uiMonetary; }; + void SetHandlingFlags(unsigned int uiFlags) { m_Handling.uiHandlingFlags = uiFlags; } + void SetModelFlags(unsigned int uiFlags) { m_Handling.uiModelFlags = uiFlags; } + void SetSeatOffsetDistance(float fDistance) { m_Handling.fSeatOffsetDistance = fDistance; } + void SetMonetary(unsigned int uiMonetary) { m_Handling.uiMonetary = uiMonetary; } - void SetHeadLight(eLightType Style) { m_Handling.ucHeadLight = Style; }; - void SetTailLight(eLightType Style) { m_Handling.ucTailLight = Style; }; - void SetAnimGroup(unsigned char ucGroup) { m_Handling.ucAnimGroup = ucGroup; }; + void SetHeadLight(eLightType Style) { m_Handling.ucHeadLight = Style; } + void SetTailLight(eLightType Style) { m_Handling.ucTailLight = Style; } + void SetAnimGroup(unsigned char ucGroup) { m_Handling.ucAnimGroup = ucGroup; } - void Recalculate(unsigned short usModel); + void CheckSuspensionChanges() noexcept; - tHandlingDataSA* GetInterface() { return m_pHandlingSA; }; + void Recalculate(); - void SetSuspensionChanged(bool bChanged) { m_bChanged = bChanged; }; + tHandlingDataSA* GetInterface() const { return m_pHandlingSA; } private: tHandlingDataSA* m_pHandlingSA; bool m_bDeleteInterface; tHandlingDataSA m_Handling; - - tHandlingDataSA* m_pOriginalData; - bool m_bChanged; }; diff --git a/Client/game_sa/CHandlingManagerSA.cpp b/Client/game_sa/CHandlingManagerSA.cpp index 94e05e0fae..8bbfb348b1 100644 --- a/Client/game_sa/CHandlingManagerSA.cpp +++ b/Client/game_sa/CHandlingManagerSA.cpp @@ -1,20 +1,22 @@ /***************************************************************************** * - * PROJECT: Multi Theft Auto v1.0 + * PROJECT: Multi Theft Auto * LICENSE: See LICENSE in the top level directory - * FILE: game_sa/CHandlingManagerSA.cpp + * FILE: Client/game_sa/CHandlingManagerSA.cpp * PURPOSE: Vehicle handling manager * - * Multi Theft Auto is available from http://www.multitheftauto.com/ + * Multi Theft Auto is available from https://multitheftauto.com/ * *****************************************************************************/ #include "StdInc.h" +#include "CGameSA.h" +#include "CHandlingManagerSA.h" #include #include -#include "CHandlingManagerSA.h" extern CCoreInterface* g_pCore; +extern CGameSA* pGame; #define ARRAY_HANDLINGDATA 0xC2B9DC @@ -22,27 +24,28 @@ extern CCoreInterface* g_pCore; #define Var_fTurnMassMultiplier 0x858B8C #define Var_fBasicDragCoeff 0x858C58 -DWORD CHandlingManagerSA::m_dwStore_LoadHandlingCfg = 0; +#define DUMP_HANDLING_DATA 0 + +// Original handling data unaffected by handling.cfg changes +tHandlingDataSA m_OriginalHandlingData[HT_MAX]; +CHandlingEntrySA* m_pOriginalEntries[HT_MAX]; -tHandlingDataSA CHandlingManagerSA::m_OriginalHandlingData[HT_MAX]; -CHandlingEntrySA* CHandlingManagerSA::m_pOriginalEntries[HT_MAX]; +tFlyingHandlingDataSA m_OriginalFlyingHandlingData[24]; +CFlyingHandlingEntrySA* m_pOriginalFlyingEntries[24]; -tFlyingHandlingDataSA CHandlingManagerSA::m_OriginalFlyingHandlingData[24]; -CFlyingHandlingEntrySA* CHandlingManagerSA::m_pOriginalFlyingEntries[24]; +tBoatHandlingDataSA m_OriginalBoatHandlingData[12]; +CBoatHandlingEntrySA* m_pOriginalBoatEntries[12]; -tBoatHandlingDataSA CHandlingManagerSA::m_OriginalBoatHandlingData[12]; -CBoatHandlingEntrySA* CHandlingManagerSA::m_pOriginalBoatEntries[12]; +tBikeHandlingDataSA m_OriginalBikeHandlingData[14]; +CBikeHandlingEntrySA* m_pOriginalBikeEntries[14]; -tBikeHandlingDataSA CHandlingManagerSA::m_OriginalBikeHandlingData[14]; -CBikeHandlingEntrySA* CHandlingManagerSA::m_pOriginalBikeEntries[14]; +std::map m_HandlingNames; // TODO We need install a hook in 0x6F52D0 to make some stuff work corrently // Use the following code to dump handling data unrecalculated on GTA load. // NB: You need to disable the other hook in the constructor of the manager and uncomment the other -DWORD m_dwStore_Calculate = 0; - __declspec(noinline) void DumpHandlingData(tHandlingDataSA* pData) { unsigned int iCounter = pData->iVehicleID; @@ -98,17 +101,17 @@ __declspec(noinline) void DumpHandlingData(tHandlingDataSA* pData) fclose(pFile); } -__declspec(naked) void Hook_Calculate() +static __declspec(naked) void Hook_Calculate() { tHandlingDataSA* pData; - DWORD dwHandlingData; + DWORD dwHandlingData; _asm { mov eax, [esp+4] mov dwHandlingData, eax } - pData = (tHandlingDataSA*)(dwHandlingData); + pData = reinterpret_cast(dwHandlingData); DumpHandlingData(pData); _asm @@ -117,34 +120,42 @@ __declspec(naked) void Hook_Calculate() } } +static bool IsVehicleModel(eVehicleTypes eModel) +{ + const auto pModelInfo = pGame->GetModelInfo(eModel); + return pModelInfo && pModelInfo->IsVehicle(); +} + CHandlingManagerSA::CHandlingManagerSA() { // Initialize all default handlings InitializeDefaultHandlings(); // Create a handling entry for every original handling data. - for (int i = 0; i < HT_MAX; i++) + for (std::size_t i = 0; i < HT_MAX; i++) { m_pOriginalEntries[i] = new CHandlingEntrySA(&m_OriginalHandlingData[i]); } - for (int i = 0; i < 24; i++) + for (std::size_t i = 0; i < 24; i++) { m_pOriginalFlyingEntries[i] = new CFlyingHandlingEntrySA(&m_OriginalFlyingHandlingData[i]); } - for (int i = 0; i < 12; i++) + for (std::size_t i = 0; i < 12; i++) { m_pOriginalBoatEntries[i] = new CBoatHandlingEntrySA(&m_OriginalBoatHandlingData[i]); } - for (int i = 0; i < 14; i++) + for (std::size_t i = 0; i < 14; i++) { m_pOriginalBikeEntries[i] = new CBikeHandlingEntrySA(&m_OriginalBikeHandlingData[i]); } - // Uncomment this to dump - // HookInstall ( Func_Calculate, (DWORD) Hook_Calculate, 11 ); +#if DUMP_HANDLING_DATA + HookInstall(Func_Calculate, (DWORD)Hook_Calculate, 11); +#endif + m_HandlingNames["mass"] = HANDLING_MASS; // works (mass > 0) m_HandlingNames["turnMass"] = HANDLING_TURNMASS; // works m_HandlingNames["dragCoeff"] = HANDLING_DRAGCOEFF; // works @@ -178,136 +189,118 @@ CHandlingManagerSA::CHandlingManagerSA() m_HandlingNames["headLight"] = HANDLING_HEADLIGHT; // doesn't work m_HandlingNames["tailLight"] = HANDLING_TAILLIGHT; // doesn't seem to work* m_HandlingNames["animGroup"] = HANDLING_ANIMGROUP; // works model based - - iChangedVehicles = 0; } CHandlingManagerSA::~CHandlingManagerSA() { // Destroy all original handling entries - for (int i = 0; i < HT_MAX; i++) + for (std::size_t i = 0; i < HT_MAX; i++) { delete m_pOriginalEntries[i]; } - for (int i = 0; i < 24; i++) + for (std::size_t i = 0; i < 24; i++) { delete m_pOriginalFlyingEntries[i]; } - for (int i = 0; i < 12; i++) + for (std::size_t i = 0; i < 12; i++) { delete m_pOriginalBoatEntries[i]; } - for (int i = 0; i < 14; i++) + for (std::size_t i = 0; i < 14; i++) { delete m_pOriginalBikeEntries[i]; } } -eHandlingProperty CHandlingManagerSA::GetPropertyEnumFromName(std::string strName) +eHandlingProperty CHandlingManagerSA::GetPropertyEnumFromName(const std::string& strName) const { - std::map::iterator it; - it = m_HandlingNames.find(strName); - - if (it != m_HandlingNames.end()) - { - return it->second; - } - return HANDLING_MAX; + const auto it = m_HandlingNames.find(strName); + return it != m_HandlingNames.end() ? it->second : HANDLING_MAX; } CHandlingEntry* CHandlingManagerSA::CreateHandlingData() { - CHandlingEntrySA* pHandlingEntry = new CHandlingEntrySA(); - return pHandlingEntry; + return new CHandlingEntrySA; } CFlyingHandlingEntry* CHandlingManagerSA::CreateFlyingHandlingData() { - CFlyingHandlingEntrySA* pFlyingHandlingEntry = new CFlyingHandlingEntrySA(); - return pFlyingHandlingEntry; + return new CFlyingHandlingEntrySA; } CBoatHandlingEntry* CHandlingManagerSA::CreateBoatHandlingData() { - CBoatHandlingEntrySA* pBoatHandlingEntry = new CBoatHandlingEntrySA(); - return pBoatHandlingEntry; + return new CBoatHandlingEntrySA; } CBikeHandlingEntry* CHandlingManagerSA::CreateBikeHandlingData() { - CBikeHandlingEntrySA* pBikeHandlingEntry = new CBikeHandlingEntrySA(); - return pBikeHandlingEntry; + return new CBikeHandlingEntrySA; } -const CHandlingEntry* CHandlingManagerSA::GetOriginalHandlingData(eVehicleTypes eModel) +const CHandlingEntry* CHandlingManagerSA::GetOriginalHandlingData(eVehicleTypes eModel) const { - // Within range? - if (eModel >= 400 && eModel < VT_MAX) - { - // Get our Handling ID - eHandlingTypes eHandling = GetHandlingID(eModel); - // Return it - return m_pOriginalEntries[eHandling]; - } - - return NULL; + // Vehicle? + if (!IsVehicleModel(eModel)) + return nullptr; + + // Get our Handling ID, the default value will be HT_LANDSTAL + const eHandlingTypes eHandling = GetHandlingID(eModel); + // Return it + return m_pOriginalEntries[eHandling]; } -const CFlyingHandlingEntry* CHandlingManagerSA::GetOriginalFlyingHandlingData(eVehicleTypes eModel) +const CFlyingHandlingEntry* CHandlingManagerSA::GetOriginalFlyingHandlingData(eVehicleTypes eModel) const { - // Within range? - if (eModel >= 400 && eModel < VT_MAX) - { - // Get our Handling ID - eHandlingTypes eHandling = GetHandlingID(eModel); - // Original GTA:SA behavior - if (eHandling < 186 || eHandling > 209) - return m_pOriginalFlyingEntries[0]; - else - return m_pOriginalFlyingEntries[eHandling - 186]; - } - - return NULL; + // Vehicle? + if (!IsVehicleModel(eModel)) + return nullptr; + + // Get our Handling ID, the default value will be HT_LANDSTAL + const eHandlingTypes eHandling = GetHandlingID(eModel); + // Original GTA:SA behavior + if (eHandling < HT_SEAPLANE || eHandling > HT_RCRAIDER) + return m_pOriginalFlyingEntries[0]; + else + return m_pOriginalFlyingEntries[eHandling - HT_SEAPLANE]; } -const CBoatHandlingEntry* CHandlingManagerSA::GetOriginalBoatHandlingData(eVehicleTypes eModel) +const CBoatHandlingEntry* CHandlingManagerSA::GetOriginalBoatHandlingData(eVehicleTypes eModel) const { - // Within range? - if (eModel >= 400 && eModel < VT_MAX) - { - // Get our Handling ID - eHandlingTypes eHandling = GetHandlingID(eModel); - // Original GTA:SA behavior - if (eHandling < 175 || eHandling > 186) - return m_pOriginalBoatEntries[0]; - else - return m_pOriginalBoatEntries[eHandling - 175]; - } - - return NULL; + // Vehicle? + if (!IsVehicleModel(eModel)) + return nullptr; + + // Get our Handling ID, the default value will be HT_LANDSTAL + const eHandlingTypes eHandling = GetHandlingID(eModel); + // Original GTA:SA behavior + if (eHandling < HT_PREDATOR || eHandling > HT_SEAPLANE) + return m_pOriginalBoatEntries[0]; + else + return m_pOriginalBoatEntries[eHandling - HT_PREDATOR]; } -const CBikeHandlingEntry* CHandlingManagerSA::GetOriginalBikeHandlingData(eVehicleTypes eModel) +const CBikeHandlingEntry* CHandlingManagerSA::GetOriginalBikeHandlingData(eVehicleTypes eModel) const { - // Within range? - if (eModel >= 400 && eModel < VT_MAX) - { - // Get our Handling ID - eHandlingTypes eHandling = GetHandlingID(eModel); - if (eHandling >= HT_BIKE && eHandling <= HT_FREEWAY) - return m_pOriginalBikeEntries[eHandling - HT_BIKE]; - else if (eHandling == HT_FAGGIO) - return m_pOriginalBikeEntries[13]; - } - - return NULL; + // Vehicle? + if (!IsVehicleModel(eModel)) + return nullptr; + + // Get our Handling ID, the default value will be HT_LANDSTAL + const eHandlingTypes eHandling = GetHandlingID(eModel); + if (eHandling >= HT_BIKE && eHandling <= HT_FREEWAY) + return m_pOriginalBikeEntries[eHandling - HT_BIKE]; + else if (eHandling == HT_FAGGIO) + return m_pOriginalBikeEntries[13]; + else + return nullptr; } // Return the handling manager id -eHandlingTypes CHandlingManagerSA::GetHandlingID(eVehicleTypes eModel) +eHandlingTypes CHandlingManagerSA::GetHandlingID(eVehicleTypes eModel) const { switch (eModel) { @@ -9161,17 +9154,29 @@ void CHandlingManagerSA::InitializeDefaultHandlings() m_OriginalBikeHandlingData[13].iVehicleID = 214; } -void CHandlingManagerSA::CheckSuspensionChanges(CHandlingEntry* pEntry) +void CHandlingManagerSA::CheckSuspensionChanges(CHandlingEntry* pEntry) noexcept { + // Valid? + if (!pEntry) + return; + // Grab us a multiplayer_sa pointer - CMultiplayer* pMultiplayer = g_pCore->GetMultiplayer(); - eVehicleTypes eModel = pEntry->GetModel(); - // Find our original data - const CHandlingEntry* pOriginal = m_pOriginalEntries[eModel]; + CMultiplayer* const pMultiplayer = g_pCore->GetMultiplayer(); + if (!pMultiplayer) + return; + + // Get Handling ID + const eHandlingTypes eHandling = static_cast(pEntry->GetVehicleID()); + if (eHandling >= HT_MAX) + return; + + const CHandlingEntrySA* pOriginal = m_pOriginalEntries[eHandling]; + if (!pOriginal) + return; + // Default bChanged to false bool bChanged = false; - // loads of if statements because I'm pro like that... na j/k // Set bChanged to true if we find ANY change. if (pEntry->GetSuspensionAntiDiveMultiplier() != pOriginal->GetSuspensionAntiDiveMultiplier()) bChanged = true; @@ -9194,33 +9199,8 @@ void CHandlingManagerSA::CheckSuspensionChanges(CHandlingEntry* pEntry) if (pEntry->GetSuspensionUpperLimit() != pOriginal->GetSuspensionUpperLimit()) bChanged = true; - // Is bChanged true and the suspension flag changed marker false - if (bChanged == true && pEntry->HasSuspensionChanged() == false) - { - // Is our hook uninstalled? - if (pMultiplayer->IsSuspensionEnabled() == false) - // Install the hook - pMultiplayer->SetSuspensionEnabled(true); - - // Increment iChangedVehicles - iChangedVehicles++; - // Set our Suspension Changed flag - pEntry->SetSuspensionChanged(true); - } - // is bChanged false and is this model supposed to contain non-default info? (i.e. they just reverted) - else if (bChanged == false && pEntry->HasSuspensionChanged() == true) - { - // Decrement iChangedVehicles - iChangedVehicles--; - // Set the suspension Changed flag to false - pEntry->SetSuspensionChanged(false); - } - // if we hit 0 vehicles installed and it's installed uninstall the hook - if (iChangedVehicles == 0 && pMultiplayer->IsSuspensionEnabled() == true) - pMultiplayer->SetSuspensionEnabled(false); -} -void CHandlingManagerSA::RemoveChangedVehicle() -{ - // Decrement the count - iChangedVehicles--; + if (!bChanged) + return; + + pMultiplayer->UpdateVehicleSuspension(); } diff --git a/Client/game_sa/CHandlingManagerSA.h b/Client/game_sa/CHandlingManagerSA.h index 04f8f0dd0e..52ce90c9f3 100644 --- a/Client/game_sa/CHandlingManagerSA.h +++ b/Client/game_sa/CHandlingManagerSA.h @@ -1,11 +1,11 @@ /***************************************************************************** * - * PROJECT: Multi Theft Auto v1.0 + * PROJECT: Multi Theft Auto * LICENSE: See LICENSE in the top level directory - * FILE: game_sa/CHandlingManagerSA.h + * FILE: Client/game_sa/CHandlingManagerSA.h * PURPOSE: Header file for vehicle handling manager class * - * Multi Theft Auto is available from http://www.multitheftauto.com/ + * Multi Theft Auto is available from https://multitheftauto.com/ * *****************************************************************************/ @@ -28,36 +28,17 @@ class CHandlingManagerSA : public CHandlingManager CBoatHandlingEntry* CreateBoatHandlingData(); CBikeHandlingEntry* CreateBikeHandlingData(); - const CHandlingEntry* GetOriginalHandlingData(eVehicleTypes eModel); - const CFlyingHandlingEntry* GetOriginalFlyingHandlingData(eVehicleTypes eModel); - const CBoatHandlingEntry* GetOriginalBoatHandlingData(eVehicleTypes eModel); - const CBikeHandlingEntry* GetOriginalBikeHandlingData(eVehicleTypes eModel); + const CHandlingEntry* GetOriginalHandlingData(eVehicleTypes eModel) const; + const CFlyingHandlingEntry* GetOriginalFlyingHandlingData(eVehicleTypes eModel) const; + const CBoatHandlingEntry* GetOriginalBoatHandlingData(eVehicleTypes eModel) const; + const CBikeHandlingEntry* GetOriginalBikeHandlingData(eVehicleTypes eModel) const; - eHandlingTypes GetHandlingID(eVehicleTypes eModel); + eHandlingProperty GetPropertyEnumFromName(const std::string& strName) const; - eHandlingProperty GetPropertyEnumFromName(std::string strName); - - void CheckSuspensionChanges(CHandlingEntry* pEntry); - void RemoveChangedVehicle(); + void CheckSuspensionChanges(CHandlingEntry* pEntry) noexcept; private: void InitializeDefaultHandlings(); - static DWORD m_dwStore_LoadHandlingCfg; - - // Original handling data unaffected by handling.cfg changes - static tHandlingDataSA m_OriginalHandlingData[HT_MAX]; - static CHandlingEntrySA* m_pOriginalEntries[HT_MAX]; - - static tFlyingHandlingDataSA m_OriginalFlyingHandlingData[24]; - static CFlyingHandlingEntrySA* m_pOriginalFlyingEntries[24]; - - static tBoatHandlingDataSA m_OriginalBoatHandlingData[12]; - static CBoatHandlingEntrySA* m_pOriginalBoatEntries[12]; - - static tBikeHandlingDataSA m_OriginalBikeHandlingData[14]; - static CBikeHandlingEntrySA* m_pOriginalBikeEntries[14]; - - std::map m_HandlingNames; - int iChangedVehicles; + eHandlingTypes GetHandlingID(eVehicleTypes eModel) const; }; diff --git a/Client/game_sa/CHeliSA.h b/Client/game_sa/CHeliSA.h index 49fc0d866d..497fe46a70 100644 --- a/Client/game_sa/CHeliSA.h +++ b/Client/game_sa/CHeliSA.h @@ -15,10 +15,47 @@ class CHeliSAInterface : public CAutomobileSAInterface { +public: + std::uint8_t m_heliFlags; + + std::uint8_t _pad1[3]; + std::uint32_t m_leftRightSkid; + std::uint32_t m_steeringUpDown; + std::uint32_t m_steeringLeftRight; + std::uint32_t m_accelerationBreakStatus; + std::uint32_t field_99C; + std::uint32_t m_rotorZ; + std::uint32_t m_secondRotorZ; + std::uint32_t m_maxAltitude; + std::uint32_t field_9AC; + std::uint32_t m_minAltitude; + std::uint32_t field_9B4; + std::uint8_t field_9B8; + std::uint8_t m_numSwatOccupants; + std::uint8_t m_swatIDs[4]; + + std::uint8_t _pad2[2]; + std::uint32_t field_9C0[4]; + std::uint32_t field_9D0; + + std::uint32_t m_particlesList; + std::uint8_t field_9D8[24]; + std::uint32_t field_9F0; + CVector m_searchLightTarget; + std::uint32_t m_searchLightIntensity; + std::uint32_t field_A04; + std::uint32_t field_A08; + std::uint32_t m_gunflashFx; + std::uint8_t m_firingMultiplier; + std::uint8_t m_searchLightEnabled; + std::uint8_t _pad3[2]; + std::uint32_t field_A14; }; +static_assert(sizeof(CHeliSAInterface) == 0xA18, "Invalid size for CHeliSAInterface"); class CHeliSA final : public virtual CHeli, public virtual CAutomobileSA { public: CHeliSA(CHeliSAInterface* pInterface); + CHeliSAInterface* GetHeliInterface() noexcept { return reinterpret_cast(GetInterface()); } }; diff --git a/Client/game_sa/CHudSA.cpp b/Client/game_sa/CHudSA.cpp index 170855388a..a63f470349 100644 --- a/Client/game_sa/CHudSA.cpp +++ b/Client/game_sa/CHudSA.cpp @@ -11,6 +11,10 @@ #include "StdInc.h" #include "CHudSA.h" +#include "CGameSA.h" +#include "CCameraSA.h" + +extern CGameSA* pGame; char szVehicleName[50] = {'\0'}; char szZoneName[50] = {'\0'}; @@ -171,3 +175,38 @@ void CHudSA::ResetComponentAdjustment() MemPut(m_pfCameraCrosshairScale, 192.0f); m_fSniperCrosshairScale = 210.0f; } + +bool CHudSA::IsCrosshairVisible() +{ + if (!IsComponentVisible(HUD_CROSSHAIR)) + return false; + + CCamera* camera = pGame->GetCamera(); + eCamMode cameraViewMode = static_cast(camera->GetCam(camera->GetActiveCam())->GetMode()); + + switch (cameraViewMode) + { + case MODE_SNIPER_RUNABOUT: + case MODE_ROCKETLAUNCHER_RUNABOUT: + case MODE_ROCKETLAUNCHER_RUNABOUT_HS: + case MODE_M16_1STPERSON_RUNABOUT: + case MODE_1STPERSON_RUNABOUT: + case MODE_AIMWEAPON: + case MODE_AIMWEAPON_ATTACHED: + case MODE_AIMWEAPON_FROMCAR: + case MODE_M16_1STPERSON: + case MODE_HELICANNON_1STPERSON: + case MODE_SNIPER: + case MODE_ROCKETLAUNCHER: + case MODE_ROCKETLAUNCHER_HS: + case MODE_AIMING: + case MODE_CAMERA: + return true; + default: + break; + } + + // Check CTheScripts::bDrawCrossHair + std::uint8_t crossHairType = *reinterpret_cast(VAR_CTheScripts_bDrawCrossHair); + return crossHairType > 0; +} diff --git a/Client/game_sa/CHudSA.h b/Client/game_sa/CHudSA.h index 925cc1dff4..11f1747b51 100644 --- a/Client/game_sa/CHudSA.h +++ b/Client/game_sa/CHudSA.h @@ -38,6 +38,8 @@ #define CODE_ShowMoney 0x58F47D +#define VAR_CTheScripts_bDrawCrossHair 0xA44490 + struct SHudComponent { bool bIsPartOfAll; @@ -59,6 +61,7 @@ class CHudSA : public CHud bool IsComponentVisible(eHudComponent component); void AdjustComponents(float fAspectRatio); void ResetComponentAdjustment(); + bool IsCrosshairVisible(); protected: void InitComponentList(); diff --git a/Client/game_sa/CIplSA.h b/Client/game_sa/CIplSA.h new file mode 100644 index 0000000000..e230d1caab --- /dev/null +++ b/Client/game_sa/CIplSA.h @@ -0,0 +1,37 @@ +/***************************************************************************** + * + * PROJECT: Multi Theft Auto v1.0 + * LICENSE: See LICENSE in the top level directory + * FILE: game_sa/CIplSA.h + * PURPOSE: Header file for game IPL class + * + * Multi Theft Auto is available from http://www.multitheftauto.com/ + * + *****************************************************************************/ + +#pragma once + +#include +#include "CRect.h" + +class CIplSAInterface +{ +public: + CRect rect; + char name[16]; + uint16_t unk; + uint16_t minBuildId; + uint16_t maxBuildId; + uint16_t minBummyId; + uint16_t maxDummyId; + uint16_t relatedIpl; + uint8_t interior; + uint8_t unk2; + uint8_t bLoadReq; + uint8_t bDisabledStreaming; + uint8_t unk3; + uint8_t unk4; + uint8_t unk5; + uint8_t unk6; +}; +static_assert(sizeof(CIplSAInterface) == 0x34, "Wrong CIplSAInterface size"); diff --git a/Client/game_sa/CIplStoreSA.cpp b/Client/game_sa/CIplStoreSA.cpp new file mode 100644 index 0000000000..2069b40c4e --- /dev/null +++ b/Client/game_sa/CIplStoreSA.cpp @@ -0,0 +1,103 @@ +/***************************************************************************** + * + * PROJECT: Multi Theft Auto v1.0 + * LICENSE: See LICENSE in the top level directory + * FILE: game_sa/CIplStore.cpp + * PURPOSE: IPL store class + * + * Multi Theft Auto is available from http://www.multitheftauto.com/ + * + *****************************************************************************/ + +#include "StdInc.h" + +#include "CIplStoreSA.h" +#include "CQuadTreeNodeSA.h" + +static auto gIplQuadTree = (CQuadTreeNodesSAInterface**)0x8E3FAC; + +CIplStoreSA::CIplStoreSA() : m_isStreamingEnabled(true), m_ppIplPoolInterface((CPoolSAInterface**)0x8E3FB0) +{ +} + +void CIplStoreSA::UnloadAndDisableStreaming(int iplId) +{ + typedef void*(__cdecl * Function_EnableStreaming)(int); + ((Function_EnableStreaming)(0x405890))(iplId); +} + +void CIplStoreSA::EnableStreaming(int iplId) +{ + auto ipl = (*m_ppIplPoolInterface)->GetObject(iplId); + ipl->bDisabledStreaming = false; + + (*gIplQuadTree)->AddItem(ipl, &ipl->rect); +} + +void CIplStoreSA::SetDynamicIplStreamingEnabled(bool state) +{ + if (m_isStreamingEnabled == state) + return; + + // Ipl with 0 index is generic + // We don't unload this IPL + + auto pPool = *m_ppIplPoolInterface; + if (!state) + { + for (int i = 1; i < pPool->m_nSize; i++) + { + if (pPool->IsContains(i)) + { + UnloadAndDisableStreaming(i); + } + } + (*gIplQuadTree)->RemoveAllItems(); + } + else + { + for (int i = 1; i < pPool->m_nSize; i++) + { + if (pPool->IsContains(i)) + { + EnableStreaming(i); + } + } + } + + m_isStreamingEnabled = state; +} + +void CIplStoreSA::SetDynamicIplStreamingEnabled(bool state, std::function filter) +{ + if (m_isStreamingEnabled == state) + return; + + // Ipl with 0 index is generic + // We don't unload this IPL + + auto pPool = *m_ppIplPoolInterface; + if (!state) + { + for (int i = 1; i < pPool->m_nSize; i++) + { + if (pPool->IsContains(i) && filter(pPool->GetObject(i))) + { + UnloadAndDisableStreaming(i); + } + } + (*gIplQuadTree)->RemoveAllItems(); + } + else + { + for (int i = 1; i < pPool->m_nSize; i++) + { + if (pPool->IsContains(i) && filter(pPool->GetObject(i))) + { + EnableStreaming(i); + } + } + } + + m_isStreamingEnabled = state; +} diff --git a/Client/game_sa/CIplStoreSA.h b/Client/game_sa/CIplStoreSA.h new file mode 100644 index 0000000000..1751ecd4f7 --- /dev/null +++ b/Client/game_sa/CIplStoreSA.h @@ -0,0 +1,36 @@ +/***************************************************************************** + * + * PROJECT: Multi Theft Auto v1.0 + * LICENSE: See LICENSE in the top level directory + * FILE: game_sa/CIplStore.h + * PURPOSE: IPL store class + * + * Multi Theft Auto is available from http://www.multitheftauto.com/ + * + *****************************************************************************/ + +#pragma once + +#include "CIplSA.h" +#include "CPoolsSA.h" +#include +#include + +class CIplStoreSA : public CIplStore +{ +public: + CIplStoreSA(); + ~CIplStoreSA() = default; + + void SetDynamicIplStreamingEnabled(bool state); + void SetDynamicIplStreamingEnabled(bool state, std::function filter); + +private: + void UnloadAndDisableStreaming(int iplId); + void EnableStreaming(int iplId); + +private: + CPoolSAInterface** m_ppIplPoolInterface; + + bool m_isStreamingEnabled; +}; diff --git a/Client/game_sa/CModelInfoSA.cpp b/Client/game_sa/CModelInfoSA.cpp index da81fb4f23..2db97a5245 100644 --- a/Client/game_sa/CModelInfoSA.cpp +++ b/Client/game_sa/CModelInfoSA.cpp @@ -440,6 +440,16 @@ void CModelInfoSA::Remove() } } +bool CModelInfoSA::UnloadUnused() +{ + if (m_pInterface->usNumberOfRefs == 0 && !m_pCustomClump && !m_pCustomColModel) + { + pGame->GetStreaming()->RemoveModel(m_dwModelID); + return true; + } + return false; +} + bool CModelInfoSA::IsLoaded() { if (DoIsLoaded()) @@ -1035,7 +1045,7 @@ void CModelInfoSA::StaticFlushPendingRestreamIPL() for (it = removedModels.begin(); it != removedModels.end(); it++) { pGame->GetStreaming()->RemoveModel(*it); - pGame->GetStreaming()->GetStreamingInfo(*it)->loadState = 0; + pGame->GetStreaming()->GetStreamingInfo(*it)->loadState = eModelLoadState::LOADSTATE_NOT_LOADED; } } @@ -1992,11 +2002,7 @@ void CModelInfoSA::SetObjectPropertiesGroup(unsigned short usNewGroup) unsigned short CModelInfoSA::GetObjectPropertiesGroup() { - unsigned short usGroup = GetInterface()->usDynamicIndex; - if (usGroup == 0xFFFF) - usGroup = 0; - - return usGroup; + return GetInterface()->usDynamicIndex; } void CModelInfoSA::RestoreObjectPropertiesGroup() @@ -2022,7 +2028,10 @@ void CModelInfoSA::RestoreAllObjectsPropertiesGroups() eModelInfoType CModelInfoSA::GetModelType() { - return ((eModelInfoType(*)())m_pInterface->VFTBL->GetModelType)(); + if (auto pInterface = GetInterface()) + return ((eModelInfoType(*)())pInterface->VFTBL->GetModelType)(); + + return eModelInfoType::UNKNOWN; } bool CModelInfoSA::IsTowableBy(CModelInfo* towingModel) diff --git a/Client/game_sa/CModelInfoSA.h b/Client/game_sa/CModelInfoSA.h index b46818d72b..b261bcc04a 100644 --- a/Client/game_sa/CModelInfoSA.h +++ b/Client/game_sa/CModelInfoSA.h @@ -362,6 +362,7 @@ class CModelInfoSA : public CModelInfo BYTE GetVehicleType(); void Request(EModelRequestType requestType, const char* szTag); void Remove(); + bool UnloadUnused(); bool IsLoaded(); bool DoIsLoaded(); unsigned short GetFlags(); @@ -465,6 +466,8 @@ class CModelInfoSA : public CModelInfo // Vehicle towing functions bool IsTowableBy(CModelInfo* towingModel) override; + bool IsDynamic() { return m_pInterface ? m_pInterface->usDynamicIndex != 0xffff : false; }; + private: void CopyStreamingInfoFromModel(ushort usCopyFromModelID); void RwSetSupportedUpgrades(RwFrame* parent, DWORD dwModel); diff --git a/Client/game_sa/COffsets.cpp b/Client/game_sa/COffsets.cpp deleted file mode 100644 index 0bdeb83cb5..0000000000 --- a/Client/game_sa/COffsets.cpp +++ /dev/null @@ -1,90 +0,0 @@ -/***************************************************************************** - * - * PROJECT: Multi Theft Auto v1.0 - * LICENSE: See LICENSE in the top level directory - * FILE: game_sa/COffsets.cpp - * PURPOSE: EXE-dependant game variable offsets - * - * Multi Theft Auto is available from http://www.multitheftauto.com/ - * - *****************************************************************************/ - -#include "StdInc.h" -#include "CCameraSA.h" -#include "CEntitySA.h" -#include "COffsets.h" -#include "CSettingsSA.h" -#include "CWeatherSA.h" -#include "CGameSA.h" - -void COffsets::Initialize10EU() -{ - InitializeCommon10(); - - CSettingsSA::FUNC_GetCurrentVideoMode = 0x7F2D60; - CSettingsSA::FUNC_GetNumVideoModes = 0x7F2D00; - CSettingsSA::FUNC_GetVideoModeInfo = 0x7F2D30; - CSettingsSA::FUNC_SetDrawDistance = 0x572ea0; - CSettingsSA::FUNC_GetNumSubSystems = 0x07F2C40; - CSettingsSA::FUNC_GetCurrentSubSystem = 0x07F2CA0; - CSettingsSA::FUNC_SetSubSystem = 0x07F2CD0; - - CEntitySA::FUNC_RwFrameGetLTM = 0x7F09D0; - CCameraSA::FUNC_RwFrameGetLTM = 0x7F09D0; -} - -void COffsets::Initialize10US() -{ - InitializeCommon10(); - - CSettingsSA::FUNC_GetCurrentVideoMode = 0x7F2D20; - CSettingsSA::FUNC_GetNumVideoModes = 0x7F2CC0; - CSettingsSA::FUNC_GetVideoModeInfo = 0x7F2CF0; - CSettingsSA::FUNC_SetDrawDistance = 0x572ea0; - CSettingsSA::FUNC_GetNumSubSystems = 0x07F2C00; - CSettingsSA::FUNC_GetCurrentSubSystem = 0x07F2C60; - CSettingsSA::FUNC_SetSubSystem = 0x07F2C90; - - CEntitySA::FUNC_RwFrameGetLTM = 0x7F0990; - CCameraSA::FUNC_RwFrameGetLTM = 0x7F0990; -} - -void COffsets::Initialize11() -{ - CGameSA::VAR_SystemTime = (unsigned long*)0xB7CB84; - CGameSA::VAR_IsAtMenu = (unsigned long*)0xBA677B; - CGameSA::VAR_IsForegroundWindow = (bool*)0x8D621C; - CGameSA::VAR_SystemState = (unsigned long*)0xC8FC80; // 1.01 - CGameSA::VAR_TimeScale = (float*)0xB7CB64; - CGameSA::VAR_FPS = (float*)0xB7CB50; - CGameSA::VAR_OldTimeStep = (float*)0xB7CB54; - CGameSA::VAR_TimeStep = (float*)0xB7CB5C; - CGameSA::VAR_Framelimiter = (unsigned long*)0xC1704C; - - CWeatherSA::VAR_CWeather__ForcedWeatherType = (unsigned char*)0xC81318; - CWeatherSA::VAR_CWeather__OldWeatherType = (unsigned char*)0xC81320; - CWeatherSA::VAR_CWeather__NewWeatherType = (unsigned char*)0xC8131C; - CWeatherSA::VAR_CWeather__Rain = (float*)0xC81324; -} - -void COffsets::InitializeCommon10() -{ - CGameSA::VAR_SystemTime = (unsigned long*)0xB7CB84; - CGameSA::VAR_IsAtMenu = (unsigned long*)0xBA677B; - CGameSA::VAR_IsForegroundWindow = (bool*)0x8D621C; - CGameSA::VAR_SystemState = (unsigned long*)0xC8D4C0; - CGameSA::VAR_TimeScale = (float*)0xB7CB64; - CGameSA::VAR_FPS = (float*)0xB7CB50; - CGameSA::VAR_OldTimeStep = (float*)0xB7CB54; - CGameSA::VAR_TimeStep = (float*)0xB7CB5C; - CGameSA::VAR_Framelimiter = (unsigned long*)0xC1704C; - - CWeatherSA::VAR_CWeather__ForcedWeatherType = (unsigned char*)0xC81318; - CWeatherSA::VAR_CWeather__OldWeatherType = (unsigned char*)0xC81320; - CWeatherSA::VAR_CWeather__NewWeatherType = (unsigned char*)0xC8131C; - CWeatherSA::VAR_CWeather__Rain = (float*)0xC81324; - - CSettingsSA::FUNC_SetCurrentVideoMode = 0x745C70; // may not be common? - - CEntitySA::FUNC_CClumpModelInfo__GetFrameFromId = 0x4C53C0; -} diff --git a/Client/game_sa/CPedSA.cpp b/Client/game_sa/CPedSA.cpp index 6efb0661fb..1ae9f942f8 100644 --- a/Client/game_sa/CPedSA.cpp +++ b/Client/game_sa/CPedSA.cpp @@ -27,14 +27,8 @@ extern CGameSA* pGame; int g_bOnlyUpdateRotations = false; -CPedSA::CPedSA() : m_pPedIntelligence(NULL), m_pPedInterface(NULL), m_pPedSound(NULL), -m_pDefaultPedSound(NULL), m_iCustomMoveAnim(0) -{ - MemSetFast(m_pWeapons, 0, sizeof(CWeaponSA*) * WEAPONSLOT_MAX); -} - -CPedSA::CPedSA(CPedSAInterface* pPedInterface) : m_pPedIntelligence(NULL), m_pPedInterface(pPedInterface), -m_pPedSound(NULL), m_pDefaultPedSound(NULL), m_iCustomMoveAnim(0) +CPedSA::CPedSA(CPedSAInterface* pPedInterface) noexcept + : m_pPedInterface(pPedInterface) { MemSetFast(m_pWeapons, 0, sizeof(CWeaponSA*) * WEAPONSLOT_MAX); } @@ -50,8 +44,6 @@ CPedSA::~CPedSA() delete m_pPedIntelligence; if (m_pPedSound) delete m_pPedSound; - if (m_pDefaultPedSound) - delete m_pDefaultPedSound; for (int i = 0; i < WEAPONSLOT_MAX; i++) { @@ -94,7 +86,9 @@ void CPedSA::Init() CPedIntelligenceSAInterface* m_pPedIntelligenceInterface = (CPedIntelligenceSAInterface*)(dwPedIntelligence); m_pPedIntelligence = new CPedIntelligenceSA(m_pPedIntelligenceInterface, this); m_pPedSound = new CPedSoundSA(&pedInterface->pedSound); - m_pDefaultPedSound = new CPedSoundSA(&pedInterface->pedSound); + + m_sDefaultVoiceType = m_pPedSound->GetVoiceTypeID(); + m_sDefaultVoiceID = m_pPedSound->GetVoiceID(); for (int i = 0; i < WEAPONSLOT_MAX; i++) m_pWeapons[i] = new CWeaponSA(&(pedInterface->Weapons[i]), this, (eWeaponSlot)i); @@ -104,8 +98,12 @@ void CPedSA::Init() void CPedSA::SetModelIndex(DWORD dwModelIndex) { - DWORD dwFunction = FUNC_SetModelIndex; + // Delete any existing RwObject first + GetPedInterface()->DeleteRwObject(); + + // Set new model DWORD dwThis = (DWORD)GetInterface(); + DWORD dwFunction = FUNC_SetModelIndex; _asm { mov ecx, dwThis @@ -122,16 +120,6 @@ void CPedSA::SetModelIndex(DWORD dwModelIndex) } } -// Hacky thing done for the local player when changing model -void CPedSA::RemoveGeometryRef() -{ - RpClump* pClump = (RpClump*)GetInterface()->m_pRwObject; - RpAtomic* pAtomic = (RpAtomic*)((pClump->atomics.root.next) - 0x8); - RpGeometry* pGeometry = pAtomic->geometry; - if (pGeometry->refs > 1) - pGeometry->refs--; -} - bool CPedSA::IsInWater() { CTask* pTask = m_pPedIntelligence->GetTaskManager()->GetTask(TASK_PRIORITY_EVENT_RESPONSE_NONTEMP); @@ -197,7 +185,7 @@ CVehicle* CPedSA::GetVehicle() { if (((CPedSAInterface*)GetInterface())->pedFlags.bInVehicle) { - CVehicleSAInterface* vehicle = (CVehicleSAInterface*)(((CPedSAInterface*)GetInterface())->CurrentObjective); + CVehicleSAInterface* vehicle = (CVehicleSAInterface*)(((CPedSAInterface*)GetInterface())->pVehicle); if (vehicle) { SClientEntity* pVehicleClientEntity = pGame->GetPools()->GetVehicle((DWORD*)vehicle); @@ -953,7 +941,7 @@ void CPedSA::SetVoice(const char* szVoiceType, const char* szVoice) void CPedSA::ResetVoice() { - SetVoice(m_pDefaultPedSound->GetVoiceTypeID(), m_pDefaultPedSound->GetVoiceID()); + SetVoice(m_sDefaultVoiceType, m_sDefaultVoiceID); } // GetCurrentWeaponStat will only work if the game ped context is currently set to this ped @@ -1114,3 +1102,34 @@ void CPedSA::StaticSetHooks() EZHookInstall(CPed_PreRenderAfterTest); EZHookInstall(CPed_PreRenderAfterTest_Mid); } + +void CPedSA::GetAttachedSatchels(std::vector& satchelsList) const +{ + // Array of projectiles objects + CProjectileSAInterface** projectilesArray = (CProjectileSAInterface**)ARRAY_CProjectile; + CProjectileSAInterface* pProjectileInterface; + + // Array of projectiles infos + CProjectileInfoSAInterface* projectilesInfoArray = (CProjectileInfoSAInterface*)ARRAY_CProjectileInfo; + CProjectileInfoSAInterface* pProjectileInfoInterface; + + // Loop through all projectiles + for (size_t i = 0; i < PROJECTILE_COUNT; i++) + { + pProjectileInterface = projectilesArray[i]; + + // is attached to our ped? + if (!pProjectileInterface || pProjectileInterface->m_pAttachedEntity != m_pInterface) + continue; + + // index is always the same for both arrays + pProjectileInfoInterface = &projectilesInfoArray[i]; + + // We are only interested in satchels + if (!pProjectileInfoInterface || pProjectileInfoInterface->dwProjectileType != eWeaponType::WEAPONTYPE_REMOTE_SATCHEL_CHARGE) + continue; + + // Push satchel into the array. There is no need to check the counter because for satchels it restarts until the player detonates the charges + satchelsList.push_back({pProjectileInterface, &pProjectileInterface->m_vecAttachedOffset, &pProjectileInterface->m_vecAttachedRotation}); + } +} diff --git a/Client/game_sa/CPedSA.h b/Client/game_sa/CPedSA.h index 5585e59864..fee84fd651 100644 --- a/Client/game_sa/CPedSA.h +++ b/Client/game_sa/CPedSA.h @@ -209,6 +209,8 @@ class CPedWeaponAudioEntitySAInterface public: }; +class CVehicleSAInterface; + class CPedSAInterface : public CPhysicalSAInterface // +1420 = current vehicle 312 first byte { public: @@ -239,11 +241,17 @@ class CPedSAInterface : public CPhysicalSAInterface // +1420 = curre float fCurrentRotation; float fTargetRotation; float fRotationSpeed; - BYTE bPad8[4]; + float fMoveAnim; CEntitySAInterface* pContactEntity; - BYTE bPad3[32]; - CEntitySAInterface* CurrentObjective; // current vehicle 1420 - BYTE bPad2[8]; // 1424 + CVector unk_56C; + CVector unk_578; + + CEntitySAInterface* pLastContactEntity; + CVehicleSAInterface* pLastVehicle; + CVehicleSAInterface* pVehicle; + + int unk_590; + int unk_594; BYTE bPedType; // ped type? 0 = player, >1 = ped? // 1432 BYTE bPad9[7]; CWeaponSAInterface Weapons[WEAPONSLOT_MAX]; @@ -264,29 +272,29 @@ class CPedSA : public virtual CPed, public virtual CPhysicalSA friend class CPoolsSA; private: - CWeaponSA* m_pWeapons[WEAPONSLOT_MAX]; - CPedIKSA* m_pPedIK; - CPedIntelligenceSA* m_pPedIntelligence; - CPedSAInterface* m_pPedInterface; - CPedSoundSA* m_pPedSound; - CPedSoundSA* m_pDefaultPedSound; + CWeaponSA* m_pWeapons[WEAPONSLOT_MAX]{}; + CPedIKSA* m_pPedIK{}; + CPedIntelligenceSA* m_pPedIntelligence{}; + CPedSAInterface* m_pPedInterface{}; + CPedSoundSA* m_pPedSound{}; + + short m_sDefaultVoiceType; + short m_sDefaultVoiceID; DWORD m_dwType; unsigned char m_ucOccupiedSeat; protected: - int m_iCustomMoveAnim; + int m_iCustomMoveAnim{ 0 }; public: - CPedSA(); - CPedSA(CPedSAInterface* pedInterface); + CPedSA(CPedSAInterface* pedInterface = nullptr) noexcept; ~CPedSA(); void SetInterface(CEntitySAInterface* intInterface); CPedSAInterface* GetPedInterface() { return (CPedSAInterface*)GetInterface(); } void Init(); void SetModelIndex(DWORD dwModelIndex); - void RemoveGeometryRef(); void AttachPedToEntity(DWORD dwEntityInterface, CVector* vector, unsigned short sDirection, float fRotationLimit, eWeaponType weaponType, bool bChangeCamera); void DetachPedFromEntity(); @@ -399,4 +407,6 @@ class CPedSA : public virtual CPed, public virtual CPhysicalSA void* GetPedNodeInterface(std::int32_t nodeId) { return reinterpret_cast(m_pInterface)->pedNodes[nodeId]; } std::unique_ptr GetPedIK() { return std::make_unique(GetPedIKInterface()); } static void StaticSetHooks(); + + void GetAttachedSatchels(std::vector &satchelsList) const override; }; diff --git a/Client/game_sa/CPhysicalSA.h b/Client/game_sa/CPhysicalSA.h index 7ac72168f1..2b1234150c 100644 --- a/Client/game_sa/CPhysicalSA.h +++ b/Client/game_sa/CPhysicalSA.h @@ -14,6 +14,7 @@ #include #include "CEntitySA.h" #include +#include "CPtrNodeDoubleListSA.h" #define FUNC_GetMoveSpeed 0x404460 #define FUNC_GetTurnSpeed 0x470030 @@ -102,7 +103,7 @@ class CPhysicalSAInterface : public CEntitySAInterface CVector m_vecAttachedRotation; // 268 CVector m_vecUnk; // 280 uint32 m_pad4; // 292 - class CPtrNodeDoubleLink* m_pControlCodeNodeLink; // 296 + CPtrNodeDoubleLink* m_pControlCodeNodeLink; // 296 float m_fLighting; // 300 float m_fLighting2; // 304 class CShadowDataSA* m_pShadowData; // 308 diff --git a/Client/game_sa/CPlaneSA.h b/Client/game_sa/CPlaneSA.h index 12da33579a..4b1005d413 100644 --- a/Client/game_sa/CPlaneSA.h +++ b/Client/game_sa/CPlaneSA.h @@ -18,12 +18,41 @@ class CPlaneSAInterface : public CAutomobileSAInterface { // + 2508 = undercarrige possition (float - 1.0 = up, 0.0 = down) // fill this +public: + float m_fLeftRightSkid; + float m_fSteeringUpDown; + float m_fSteeringLeftRight; + float m_fAccelerationBreakStatus; + float m_fAccelerationBreakStatusPrev; + float m_fSteeringFactor; + float field_9A0; + float m_planeCreationHeading; // The heading when plane is created or placed on road properly + float m_maxAltitude; + float m_altitude; + float m_minAltitude; + float m_planeHeading; + float m_planeHeadingPrev; + float m_forwardZ; + uint32_t m_nStartedFlyingTime; + float m_fPropSpeed; // Rotor speed 0x09C4 + float field_9C8; + float m_fLandingGearStatus; + int32_t m_planeDamageWave; + FxSystem_c** m_pGunParticles; + uint8_t m_nFiringMultiplier; + int32_t field_9DC; + int32_t field_9E0; + int32_t field_9E4; + FxSystem_c* m_apJettrusParticles[4]; + FxSystem_c* m_pSmokeParticle; + uint32_t m_nSmokeTimer; + bool m_bSmokeEjectorEnabled; }; +static_assert(sizeof(CPlaneSAInterface) == 0xA04, "Invalid size for CPlaneSAInterface"); class CPlaneSA final : public virtual CPlane, public virtual CAutomobileSA { public: CPlaneSA(CPlaneSAInterface* pInterface); - CPlaneSAInterface* GetPlaneInterface() { return reinterpret_cast(GetInterface()); } }; diff --git a/Client/game_sa/CPlantManagerSA.cpp b/Client/game_sa/CPlantManagerSA.cpp new file mode 100644 index 0000000000..aef1849aae --- /dev/null +++ b/Client/game_sa/CPlantManagerSA.cpp @@ -0,0 +1,36 @@ + +#include "StdInc.h" +#include "CPlantManagerSA.h" +#include "CPtrNodeSingleListSA.h" + +class CPlantLocTri; + +class CPlantColEntEntry +{ +public: + CEntitySAInterface* m_Entity; + CPlantLocTri** m_Objects; + uint16 m_numTriangles; + CPlantColEntEntry* m_NextEntry; + CPlantColEntEntry* m_PrevEntry; + +public: + void ReleaseEntry() { + using CPlantColEntEntry_ReleaseEntry = void* ( __thiscall *)(CPlantColEntEntry*); + ((CPlantColEntEntry_ReleaseEntry)0x5DB8A0)(this); + }; +}; + +void CPlantManagerSA::RemoveAllPlants() +{ + while (true) + { + auto list = reinterpret_cast(0xC0399C); + if (*list == nullptr) + { + break; + } + + (*list)->ReleaseEntry(); + } +} diff --git a/Client/game_sa/CPlantManagerSA.h b/Client/game_sa/CPlantManagerSA.h new file mode 100644 index 0000000000..4ade022684 --- /dev/null +++ b/Client/game_sa/CPlantManagerSA.h @@ -0,0 +1,18 @@ +#pragma once + +#include "CEntitySA.h" + +class CPlantManagerSA +{ +public: + CPlantManagerSA() = default; + ~CPlantManagerSA() = default; + + void RemovePlant(CEntitySAInterface* enity) + { + using CPlantColEntry_Remove = CEntitySAInterface* (*)(CEntitySAInterface*); + ((CPlantColEntry_Remove)0x5DBEF0)(enity); + }; + + void RemoveAllPlants(); +}; diff --git a/Client/game_sa/CPoolSAInterface.h b/Client/game_sa/CPoolSAInterface.h new file mode 100644 index 0000000000..9f48bc63d3 --- /dev/null +++ b/Client/game_sa/CPoolSAInterface.h @@ -0,0 +1,164 @@ +/***************************************************************************** + * + * PROJECT: Multi Theft Auto v1.0 + * LICENSE: See LICENSE in the top level directory + * FILE: game_sa/CPoolsSA.h + * PURPOSE: Header file for pools interface + * + * Multi Theft Auto is available from http://www.multitheftauto.com/ + * + *****************************************************************************/ + +#pragma once + +#include + +// size of tPoolObjectFlags is 1 byte only +union tPoolObjectFlags +{ + struct + { + unsigned char nId : 7; + bool bEmpty : 1; + }; + +private: + unsigned char nValue; +}; + +template +class CPoolSAInterface +{ +public: + // m_pObjects contains all interfaces. 140 maximum for ped objects. + B* m_pObjects; + tPoolObjectFlags* m_byteMap; + int m_nSize; + int m_nFirstFree; + bool m_bOwnsAllocations; + bool field_11; + + // Default constructor for statically allocated pools + CPoolSAInterface() + { + // Remember to call CPool::Init to fill in the fields! + m_pObjects = nullptr; + m_byteMap = nullptr; + m_nSize = 0; + m_bOwnsAllocations = false; + } + + uint GetFreeSlot() + { + bool bLooped = false; + uint index = m_nFirstFree + 1; + + while (true) + { + if (index >= m_nSize) + { + if (bLooped) + return -1; + + index = 0; + bLooped = true; + } + + if (m_byteMap[index].bEmpty) + { + m_nFirstFree = index; + return index; + } + index++; + } + + return -1; + }; + + B* Allocate() + { + m_nFirstFree++; // Continue after the last allocated slot + const auto sz = m_nSize; // Storing size to avoid reloads from memory - should help out the optimizer + for (auto i = 0u; i < sz; i++) + { + const auto slot = (m_nFirstFree + i) % sz; + const auto e = &m_byteMap[slot]; + if (!e->bEmpty) + { + continue; + } + m_nFirstFree = slot; + e->bEmpty = false; + e->nId++; + return &m_pObjects[slot]; + } + return nullptr; + } + + B* AllocateAt(uint uiSlot) + { + m_pObjects[uiSlot] = B(); + m_byteMap[uiSlot].bEmpty = false; + m_byteMap[uiSlot].nId ^= uiSlot ^ (uiSlot + 1); + + return &m_pObjects[uiSlot]; + } + + void Release(uint index) + { + m_byteMap[index].bEmpty = true; + m_byteMap[index].nId = 0; + if (index == m_nFirstFree) + --m_nFirstFree; + } + + void Delete(uint index) { Release(index); } + + bool IsEmpty(std::int32_t objectIndex) { return m_byteMap[objectIndex].bEmpty; } + bool IsContains(uint index) + { + if (m_nSize <= index) + return false; + return !IsEmpty(index); + } + + B* GetObject(std::int32_t objectIndex) { return &m_pObjects[objectIndex]; } + + uint GetObjectIndex(B* pObject) { return ((DWORD)pObject - (DWORD)m_pObjects) / sizeof(B); } + + uint32_t GetObjectIndexSafe(B* pObject) + { + uint32_t index = GetObjectIndex(pObject); + return index > m_nSize ? UINT_MAX : index; + } +}; + +// Generic container for pools +template +struct SPoolData +{ + std::array, MAX> arrayOfClientEntities; + unsigned long ulCount; + +public: + SPoolData() : ulCount(0UL) + { + for (unsigned int i = 0; i < MAX; ++i) + { + arrayOfClientEntities[i] = {nullptr, nullptr}; + } + } +}; + +template +struct SVectorPoolData +{ + std::vector> entities; + size_t count; + +public: + SVectorPoolData(size_t defaultSize) : count(0) + { + entities.resize(defaultSize, {nullptr, nullptr}); + } +}; diff --git a/Client/game_sa/CPoolsSA.cpp b/Client/game_sa/CPoolsSA.cpp index 9f3260029d..42c534dcaa 100644 --- a/Client/game_sa/CPoolsSA.cpp +++ b/Client/game_sa/CPoolsSA.cpp @@ -13,6 +13,7 @@ #include "CBikeSA.h" #include "CBmxSA.h" #include "CBoatSA.h" +#include "CBuildingSA.h" #include "CGameSA.h" #include "CHeliSA.h" #include "CMonsterTruckSA.h" @@ -24,6 +25,8 @@ #include "CTrainSA.h" #include "CWorldSA.h" #include "CKeyGenSA.h" +#include "CFileLoaderSA.h" +#include "CPtrNodeSingleListSA.h" extern CGameSA* pGame; @@ -125,6 +128,8 @@ CVehicle* CPoolsSA::AddVehicle(CClientVehicle* pClientVehicle, eVehicleTypes eVe { pVehicle->m_ucVariant = ucVariation; pVehicle->m_ucVariant2 = ucVariation2; + + pVehicle->DumpVehicleFrames(); } else { @@ -676,7 +681,7 @@ DWORD CPoolsSA::GetPedPoolIndex(std::uint8_t* pInterface) { return MAX_PEDS; } - return ((pInterface - pTheObjects) / dwAlignedSize); + return ((pInterface - pTheObjects) / dwAlignedSize); } DWORD CPoolsSA::GetVehiclePoolIndex(std::uint8_t* pInterface) @@ -806,6 +811,54 @@ int CPoolsSA::GetPoolDefaultCapacity(ePools pool) return 0; } +int CPoolsSA::GetPoolDefaultModdedCapacity(ePools pool) +{ + switch (pool) + { + case BUILDING_POOL: + return MAX_BUILDINGS; + case PED_POOL: + return 140; + case OBJECT_POOL: + return MAX_OBJECTS; + case DUMMY_POOL: + return 2500; + case VEHICLE_POOL: + return 110; + case COL_MODEL_POOL: + return 12000; + case TASK_POOL: + return 5000; + case EVENT_POOL: + return 5000; + case TASK_ALLOCATOR_POOL: + return 16; + case PED_INTELLIGENCE_POOL: + return 140; + case PED_ATTRACTOR_POOL: + return 64; + case ENTRY_INFO_NODE_POOL: + return MAX_ENTRY_INFO_NODES; + case NODE_ROUTE_POOL: + return 64; + case PATROL_ROUTE_POOL: + return 32; + case POINT_ROUTE_POOL: + return 64; + case POINTER_DOUBLE_LINK_POOL: + return MAX_POINTER_DOUBLE_LINKS; + case POINTER_SINGLE_LINK_POOL: + return MAX_POINTER_SINGLE_LINKS; + case ENV_MAP_MATERIAL_POOL: + return 16000; + case ENV_MAP_ATOMIC_POOL: + return 4000; + case SPEC_MAP_MATERIAL_POOL: + return 16000; + } + return 0; +} + int CPoolsSA::GetPoolCapacity(ePools pool) { DWORD iPtr = NULL; @@ -813,8 +866,7 @@ int CPoolsSA::GetPoolCapacity(ePools pool) switch (pool) { case BUILDING_POOL: - iPtr = 0x55105F; - break; + return GetBuildingsPool().GetSize(); case PED_POOL: iPtr = 0x550FF2; break; diff --git a/Client/game_sa/CPoolsSA.h b/Client/game_sa/CPoolsSA.h index 60f5d549e8..0e6d3d9634 100644 --- a/Client/game_sa/CPoolsSA.h +++ b/Client/game_sa/CPoolsSA.h @@ -14,127 +14,15 @@ #include "CPedSA.h" #include "CVehicleSA.h" #include "CObjectSA.h" +#include "CBuildingSA.h" #include "CTextureDictonarySA.h" +#include "CBuildingsPoolSA.h" +#include "CDummyPoolSA.h" #define INVALID_POOL_ARRAY_ID 0xFFFFFFFF class CClientEntity; -// size of tPoolObjectFlags is 1 byte only -union tPoolObjectFlags -{ - struct - { - unsigned char nId : 7; - bool bEmpty : 1; - }; - -private: - unsigned char nValue; -}; - -template -class CPoolSAInterface -{ -public: - // m_pObjects contains all interfaces. 140 maximum for ped objects. - B* m_pObjects; - tPoolObjectFlags* m_byteMap; - int m_nSize; - int m_nFirstFree; - bool m_bOwnsAllocations; - bool field_11; - - // Default constructor for statically allocated pools - CPoolSAInterface() - { - // Remember to call CPool::Init to fill in the fields! - m_pObjects = nullptr; - m_byteMap = nullptr; - m_nSize = 0; - m_bOwnsAllocations = false; - } - - uint GetFreeSlot() - { - bool bLooped = false; - uint index = m_nFirstFree + 1; - - while (true) - { - if (index >= m_nSize) - { - if (bLooped) - return -1; - - index = 0; - bLooped = true; - } - - if (m_byteMap[index].bEmpty) - { - m_nFirstFree = index; - return index; - } - index++; - } - - return -1; - }; - - B* Allocate() - { - m_nFirstFree++; // Continue after the last allocated slot - const auto sz = m_nSize; // Storing size to avoid reloads from memory - should help out the optimizer - for (auto i = 0u; i < sz; i++) { - const auto slot = (m_nFirstFree + i) % sz; - const auto e = &m_byteMap[slot]; - if (!e->bEmpty) { - continue; - } - m_nFirstFree = slot; - e->bEmpty = false; - e->nId++; - return &m_pObjects[slot]; - } - return nullptr; - } - - B* AllocateAt(uint uiSlot) - { - m_pObjects[uiSlot] = B(); - m_byteMap[uiSlot].bEmpty = false; - m_byteMap[uiSlot].nId ^= uiSlot ^ (uiSlot + 1); - - return &m_pObjects[uiSlot]; - } - - void Release(uint index) - { - m_byteMap[index].bEmpty = true; - m_byteMap[index].nId = 0; - if (index == m_nFirstFree) - --m_nFirstFree; - } - - void Delete(uint index) - { - Release(index); - } - - bool IsEmpty(std::int32_t objectIndex) { return m_byteMap[objectIndex].bEmpty; } - bool IsContains(uint index) - { - if (m_nSize <= index) - return false; - return !IsEmpty(index); - } - - B* GetObject(std::int32_t objectIndex) { return &m_pObjects[objectIndex]; } - - uint GetObjectIndex(B* pObject) { return ((DWORD)pObject - (DWORD)m_pObjects) / sizeof(B); } -}; - class CPoolsSA : public CPools { public: @@ -150,11 +38,8 @@ class CPoolsSA : public CPools public: void RemoveVehicle(CVehicle* pVehicle, bool bDelete = true); SClientEntity* GetVehicle(DWORD* pGameInterface); - unsigned long GetVehicleCount() - { - return m_vehiclePool.ulCount; - ; - } + SClientEntity* GetVehicle(size_t pos) { return &m_vehiclePool.arrayOfClientEntities[pos]; }; + unsigned long GetVehicleCount() { return m_vehiclePool.ulCount; }; void DeleteAllVehicles(); // Objects pool @@ -180,6 +65,7 @@ class CPoolsSA : public CPools public: void RemovePed(CPed* ped, bool bDelete = true); SClientEntity* GetPed(DWORD* pGameInterface); + SClientEntity* GetPed(size_t pos) { return &m_pedPool.arrayOfClientEntities[pos]; }; CPed* GetPedFromRef(DWORD dwGameRef); CPedSAInterface* GetPedInterface(DWORD dwGameRef); // game_sa specific unsigned long GetPedCount() { return m_pedPool.ulCount; } @@ -198,6 +84,7 @@ class CPoolsSA : public CPools int GetNumberOfUsedSpaces(ePools pools); int GetPoolDefaultCapacity(ePools pool); + int GetPoolDefaultModdedCapacity(ePools pool); int GetPoolCapacity(ePools pool); void SetPoolCapacity(ePools pool, int iValue); @@ -210,37 +97,22 @@ class CPoolsSA : public CPools ushort GetFreeTextureDictonarySlot(); -private: - // Generic container for pools - template - struct SPoolData - { - std::array, MAX> arrayOfClientEntities; - unsigned long ulCount; + CBuildingsPool& GetBuildingsPool() noexcept override { return m_BuildingsPool; }; + CDummyPool& GetDummyPool() noexcept { return m_DummyPool; }; - private: - friend class CPoolsSA; +private: + // Pools + SPoolData m_vehiclePool; + SPoolData m_pedPool; + SPoolData m_objectPool; - SPoolData() : ulCount(0UL) - { - for (unsigned int i = 0; i < MAX; ++i) - { - arrayOfClientEntities[i] = {nullptr, nullptr}; - } - } - }; + CPoolSAInterface** m_ppPedPoolInterface; + CPoolSAInterface** m_ppObjectPoolInterface; + CPoolSAInterface** m_ppVehiclePoolInterface; + CPoolSAInterface** m_ppTxdPoolInterface; - // Pools - typedef SPoolData vehiclePool_t; - typedef SPoolData pedPool_t; - typedef SPoolData objectPool_t; - vehiclePool_t m_vehiclePool; - pedPool_t m_pedPool; - objectPool_t m_objectPool; - CPoolSAInterface** m_ppPedPoolInterface; - CPoolSAInterface** m_ppObjectPoolInterface; - CPoolSAInterface** m_ppVehiclePoolInterface; - CPoolSAInterface** m_ppTxdPoolInterface; + CBuildingsPoolSA m_BuildingsPool; + CDummyPoolSA m_DummyPool; bool m_bGetVehicleEnabled; }; diff --git a/Client/game_sa/CPtrNodeDoubleListSA.h b/Client/game_sa/CPtrNodeDoubleListSA.h new file mode 100644 index 0000000000..fb6f6c9978 --- /dev/null +++ b/Client/game_sa/CPtrNodeDoubleListSA.h @@ -0,0 +1,41 @@ +/***************************************************************************** + * + * PROJECT: Multi Theft Auto v1.0 + * LICENSE: See LICENSE in the top level directory + * FILE: game_sa/CPtrNodeDoubleListSA.h + * + * Multi Theft Auto is available from http://www.multitheftauto.com/ + * + *****************************************************************************/ + +#pragma once + +template +class CPtrNodeDoubleLink +{ +public: + T* pItem; + CPtrNodeDoubleLink* pNext; + CPtrNodeDoubleLink* pPrev; +}; + +template +class CPtrNodeDoubleListSAInterface +{ +public: + CPtrNodeDoubleLink* m_pNode; + + void RemoveItem(T* pItem) + { + using CPtrListDoubleLinkSAInterface_RemoveItem = void(__thiscall*)(CPtrNodeDoubleListSAInterface * pLinkList, void* item); + ((CPtrListDoubleLinkSAInterface_RemoveItem)0x5336B0)(this, pItem); + }; + + void RemoveAllItems() + { + while (m_pNode) + { + RemoveItem(m_pNode->pItem); + } + }; +}; diff --git a/Client/game_sa/CPtrNodeSingleListSA.h b/Client/game_sa/CPtrNodeSingleListSA.h new file mode 100644 index 0000000000..f083614421 --- /dev/null +++ b/Client/game_sa/CPtrNodeSingleListSA.h @@ -0,0 +1,45 @@ +/***************************************************************************** + * + * PROJECT: Multi Theft Auto v1.0 + * LICENSE: See LICENSE in the top level directory + * FILE: game_sa/CPtrNodeSingleListSA.h + * + * Multi Theft Auto is available from http://www.multitheftauto.com/ + * + *****************************************************************************/ + +#pragma once + +template +struct CPtrNodeSingleLink +{ + T* pItem; + CPtrNodeSingleLink* pNext; +}; + +template +class CPtrNodeSingleListSAInterface +{ +public: + void RemoveItem(T* item); + void RemoveAllItems(); + +private: + CPtrNodeSingleLink* m_pList; +}; + +template +void CPtrNodeSingleListSAInterface::RemoveItem(T* item) +{ + using CPtrNodeSingleList_RemoveItem_t = void(__thiscall*)(CPtrNodeSingleListSAInterface * pLinkList, void* item); + ((CPtrNodeSingleList_RemoveItem_t)0x533610)(this, item); +} + +template +void CPtrNodeSingleListSAInterface::RemoveAllItems() +{ + while (m_pList) + { + RemoveItem(m_pList->pItem); + } +} diff --git a/Client/game_sa/CQuadTreeNodeSA.h b/Client/game_sa/CQuadTreeNodeSA.h new file mode 100644 index 0000000000..dabb9bdfe5 --- /dev/null +++ b/Client/game_sa/CQuadTreeNodeSA.h @@ -0,0 +1,56 @@ +/***************************************************************************** + * + * PROJECT: Multi Theft Auto v1.0 + * LICENSE: See LICENSE in the top level directory + * FILE: game_sa/CQuadTreeNodeSA.h + * PURPOSE: Quad tree node class interface + * + * Multi Theft Auto is available from http://www.multitheftauto.com/ + * + *****************************************************************************/ + +#pragma once + +#include "CPtrNodeSingleListSA.h" +#include "CRect.h" + +template +class CQuadTreeNodesSAInterface +{ +public: + void RemoveAllItems(); + char AddItem(T* item, CRect* boudingBox); + +private: + float m_fX; + float m_fY; + float m_fW; + float m_fH; + CPtrNodeSingleListSAInterface m_pItemList; + CQuadTreeNodesSAInterface* m_childrens[4]; + uint32_t m_level; +}; +static_assert(sizeof(CQuadTreeNodesSAInterface) == 0x28, "Wrong CQuadTreeNodesSAInterface size"); + +template +void CQuadTreeNodesSAInterface::RemoveAllItems() +{ + if (m_level) + { + for (size_t i = 0; i < 4; i++) + { + m_childrens[i]->RemoveAllItems(); + } + } + else + { + m_pItemList.RemoveAllItems(); + } +}; + +template +char CQuadTreeNodesSAInterface::AddItem(T* item, CRect* boudingBox) +{ + typedef char(__thiscall * CQuadTreeNode_AddItem_t)(CQuadTreeNodesSAInterface*, void*, CRect*); + return ((CQuadTreeNode_AddItem_t)(0x552CD0))(this, item, boudingBox); +}; diff --git a/Client/game_sa/CRenderWareSA.ShaderSupport.cpp b/Client/game_sa/CRenderWareSA.ShaderSupport.cpp index 3f5ae44bdf..2481ea1f0d 100644 --- a/Client/game_sa/CRenderWareSA.ShaderSupport.cpp +++ b/Client/game_sa/CRenderWareSA.ShaderSupport.cpp @@ -643,8 +643,6 @@ void CRenderWareSA::SetGTAVertexShadersEnabled(bool bEnable) m_bGTAVertexShadersEnabled = bEnable; DWORD pSkinAtomic = 0x07C7CD0; - if (pGame->GetGameVersion() != VERSION_US_10) - pSkinAtomic = 0x07C7D10; if (bEnable) { @@ -689,13 +687,9 @@ __declspec(noinline) void OnMY_RwTextureSetName(DWORD dwAddrCalledFrom, RwTextur } // Hook info -#define HOOKPOS_RwTextureSetName_US 0x7F38A0 -#define HOOKSIZE_RwTextureSetName_US 9 -#define HOOKPOS_RwTextureSetName_EU 0x7F38E0 -#define HOOKSIZE_RwTextureSetName_EU 9 -DWORD RETURN_RwTextureSetName_US = 0x7F38A9; -DWORD RETURN_RwTextureSetName_EU = 0x7F38E9; -DWORD RETURN_RwTextureSetName_BOTH = 0; +#define HOOKPOS_RwTextureSetName 0x7F38A0 +#define HOOKSIZE_RwTextureSetName 9 +DWORD RETURN_RwTextureSetName = 0x7F38A9; void _declspec(naked) HOOK_RwTextureSetName() { _asm @@ -710,7 +704,7 @@ void _declspec(naked) HOOK_RwTextureSetName() sub esp, 8 mov ecx, ds:0x0C97B24 - jmp RETURN_RwTextureSetName_BOTH + jmp RETURN_RwTextureSetName } } @@ -727,13 +721,9 @@ __declspec(noinline) void OnMY_RwTextureDestroy_Mid(RwTexture* pTexture) } // Hook info -#define HOOKPOS_RwTextureDestroy_Mid_US 0x07F3834 -#define HOOKSIZE_RwTextureDestroy_Mid_US 5 -#define HOOKPOS_RwTextureDestroy_Mid_EU 0x07F3874 -#define HOOKSIZE_RwTextureDestroy_Mid_EU 5 -DWORD RETURN_RwTextureDestroy_Mid_US = 0x07F3839; -DWORD RETURN_RwTextureDestroy_Mid_EU = 0x07F3879; -DWORD RETURN_RwTextureDestroy_Mid_BOTH = 0; +#define HOOKPOS_RwTextureDestroy_Mid 0x07F3834 +#define HOOKSIZE_RwTextureDestroy_Mid 5 +DWORD RETURN_RwTextureDestroy_Mid = 0x07F3839; void _declspec(naked) HOOK_RwTextureDestroy_Mid() { _asm @@ -745,7 +735,7 @@ void _declspec(naked) HOOK_RwTextureDestroy_Mid() popad push 0x08E23CC - jmp RETURN_RwTextureDestroy_Mid_BOTH + jmp RETURN_RwTextureDestroy_Mid } } @@ -775,13 +765,9 @@ __declspec(noinline) void OnMY_RwIm3DRenderIndexedPrimitive_Post(DWORD dwAddrCal } // Hook info -#define HOOKPOS_RwIm3DRenderIndexedPrimitive_US 0x07EF550 -#define HOOKSIZE_RwIm3DRenderIndexedPrimitive_US 5 -#define HOOKPOS_RwIm3DRenderIndexedPrimitive_EU 0x07EF590 -#define HOOKSIZE_RwIm3DRenderIndexedPrimitive_EU 5 -DWORD RETURN_RwIm3DRenderIndexedPrimitive_US = 0x07EF555; -DWORD RETURN_RwIm3DRenderIndexedPrimitive_EU = 0x07EF595; -DWORD RETURN_RwIm3DRenderIndexedPrimitive_BOTH = 0; +#define HOOKPOS_RwIm3DRenderIndexedPrimitive 0x07EF550 +#define HOOKSIZE_RwIm3DRenderIndexedPrimitive 5 +DWORD RETURN_RwIm3DRenderIndexedPrimitive = 0x07EF555; void _declspec(naked) HOOK_RwIm3DRenderIndexedPrimitive() { _asm @@ -806,7 +792,7 @@ void _declspec(naked) HOOK_RwIm3DRenderIndexedPrimitive() retn inner: mov eax, ds:0x0C9C078 - jmp RETURN_RwIm3DRenderIndexedPrimitive_BOTH + jmp RETURN_RwIm3DRenderIndexedPrimitive } } @@ -828,13 +814,9 @@ __declspec(noinline) void OnMY_RwIm3DRenderPrimitive_Post(DWORD dwAddrCalledFrom } // Hook info -#define HOOKPOS_RwIm3DRenderPrimitive_US 0x07EF6B0 -#define HOOKSIZE_RwIm3DRenderPrimitive_US 6 -#define HOOKPOS_RwIm3DRenderPrimitive_EU 0x07EF6F0 -#define HOOKSIZE_RwIm3DRenderPrimitive_EU 6 -DWORD RETURN_RwIm3DRenderPrimitive_US = 0x07EF6B6; -DWORD RETURN_RwIm3DRenderPrimitive_EU = 0x07EF6F6; -DWORD RETURN_RwIm3DRenderPrimitive_BOTH = 0; +#define HOOKPOS_RwIm3DRenderPrimitive 0x07EF6B0 +#define HOOKSIZE_RwIm3DRenderPrimitive 6 +DWORD RETURN_RwIm3DRenderPrimitive = 0x07EF6B6; void _declspec(naked) HOOK_RwIm3DRenderPrimitive() { _asm @@ -859,7 +841,7 @@ void _declspec(naked) HOOK_RwIm3DRenderPrimitive() retn inner: mov ecx, ds:0x0C97B24 - jmp RETURN_RwIm3DRenderPrimitive_BOTH + jmp RETURN_RwIm3DRenderPrimitive } } @@ -881,13 +863,9 @@ __declspec(noinline) void OnMY_RwIm2DRenderIndexedPrimitive_Post(DWORD dwAddrCal } // Hook info -#define HOOKPOS_RwIm2DRenderIndexedPrimitive_US 0x0734EA1 -#define HOOKSIZE_RwIm2DRenderIndexedPrimitive_US 5 -#define HOOKPOS_RwIm2DRenderIndexedPrimitive_EU 0x0734EA1 -#define HOOKSIZE_RwIm2DRenderIndexedPrimitive_EU 5 -DWORD RETURN_RwIm2DRenderIndexedPrimitive_US = 0x0403927; -DWORD RETURN_RwIm2DRenderIndexedPrimitive_EU = 0x0403937; -DWORD RETURN_RwIm2DRenderIndexedPrimitive_BOTH = 0; +#define HOOKPOS_RwIm2DRenderIndexedPrimitive 0x0734EA1 +#define HOOKSIZE_RwIm2DRenderIndexedPrimitive 5 +DWORD RETURN_RwIm2DRenderIndexedPrimitive = 0x0403927; void _declspec(naked) HOOK_RwIm2DRenderIndexedPrimitive() { _asm @@ -914,7 +892,7 @@ void _declspec(naked) HOOK_RwIm2DRenderIndexedPrimitive() retn inner: - jmp RETURN_RwIm2DRenderIndexedPrimitive_BOTH + jmp RETURN_RwIm2DRenderIndexedPrimitive } } diff --git a/Client/game_sa/CRenderWareSA.cpp b/Client/game_sa/CRenderWareSA.cpp index 31556739d3..56f5ce34e4 100644 --- a/Client/game_sa/CRenderWareSA.cpp +++ b/Client/game_sa/CRenderWareSA.cpp @@ -190,9 +190,9 @@ static bool LoadAtomicsCB(RpAtomic* atomic, void* pData) // // ///////////////////////////////////////////////////////////////////////////// -CRenderWareSA::CRenderWareSA(eGameVersion version) +CRenderWareSA::CRenderWareSA() { - InitRwFunctions(version); + InitRwFunctions(); InitTextureWatchHooks(); m_pMatchChannelManager = new CMatchChannelManager(); diff --git a/Client/game_sa/CRenderWareSA.h b/Client/game_sa/CRenderWareSA.h index 725c9e7a6a..6a0e64ea50 100644 --- a/Client/game_sa/CRenderWareSA.h +++ b/Client/game_sa/CRenderWareSA.h @@ -26,7 +26,7 @@ class CRenderWareSA : public CRenderWare { public: ZERO_ON_NEW - CRenderWareSA(enum eGameVersion version); + CRenderWareSA(); ~CRenderWareSA(); void Initialize(); bool ModelInfoTXDLoadTextures(SReplacementTextures* pReplacementTextures, const SString& strFilename, const SString& buffer, bool bFilteringEnabled); diff --git a/Client/game_sa/CRendererSA.cpp b/Client/game_sa/CRendererSA.cpp new file mode 100644 index 0000000000..bad607d5ba --- /dev/null +++ b/Client/game_sa/CRendererSA.cpp @@ -0,0 +1,55 @@ +/***************************************************************************** + * + * PROJECT: Multi Theft Auto v1.0 + * LICENSE: See LICENSE in the top level directory + * FILE: game_sa/CRendererSA.cpp + * PURPOSE: Game renderer class + * + * Multi Theft Auto is available from http://www.multitheftauto.com/ + * + *****************************************************************************/ + +#include "StdInc.h" +#include "CRendererSA.h" +#include "CModelInfoSA.h" +#include "CMatrix.h" +#include "gamesa_renderware.h" + +CRendererSA::CRendererSA() +{ +} + +CRendererSA::~CRendererSA() +{ +} + +void CRendererSA::RenderModel(CModelInfo* pModelInfo, const CMatrix& matrix) +{ + CBaseModelInfoSAInterface* pModelInfoSAInterface = pModelInfo->GetInterface(); + if (!pModelInfoSAInterface) + return; + + RwObject* pRwObject = pModelInfoSAInterface->pRwObject; + if (!pRwObject) + return; + + RwFrame* pFrame = RpGetFrame(pRwObject); + + static RwMatrix rwMatrix; + rwMatrix.right = (RwV3d&)matrix.vRight; + rwMatrix.up = (RwV3d&)matrix.vFront; + rwMatrix.at = (RwV3d&)matrix.vUp; + rwMatrix.pos = (RwV3d&)matrix.vPos; + RwFrameTransform(pFrame, &rwMatrix, rwCOMBINEREPLACE); + + if (pRwObject->type == RP_TYPE_ATOMIC) + { + RpAtomic* pRpAtomic = reinterpret_cast(pRwObject); + pRpAtomic->renderCallback(reinterpret_cast(pRwObject)); + } + else + { + RpClump* pClump = reinterpret_cast(pRwObject); + RpClumpRender(pClump); + } +} diff --git a/Client/game_sa/COffsets.h b/Client/game_sa/CRendererSA.h similarity index 58% rename from Client/game_sa/COffsets.h rename to Client/game_sa/CRendererSA.h index 9ab3eaf1f0..e71a83665e 100644 --- a/Client/game_sa/COffsets.h +++ b/Client/game_sa/CRendererSA.h @@ -2,8 +2,8 @@ * * PROJECT: Multi Theft Auto v1.0 * LICENSE: See LICENSE in the top level directory - * FILE: game_sa/COffsets.h - * PURPOSE: Header file for game variable offsets class + * FILE: game_sa/CRendererSA.h + * PURPOSE: Game renderer class * * Multi Theft Auto is available from http://www.multitheftauto.com/ * @@ -11,13 +11,13 @@ #pragma once -class COffsets +#include + +class CRendererSA : public CRenderer { public: - static void Initialize10EU(); - static void Initialize10US(); - static void Initialize11(); + CRendererSA(); + ~CRendererSA(); -private: - static void InitializeCommon10(); + void RenderModel(CModelInfo* pModelInfo, const CMatrix& matrix) override; }; diff --git a/Client/game_sa/CSettingsSA.cpp b/Client/game_sa/CSettingsSA.cpp index 8fa50008bf..4ce70b5eed 100644 --- a/Client/game_sa/CSettingsSA.cpp +++ b/Client/game_sa/CSettingsSA.cpp @@ -24,15 +24,6 @@ static const float MOUSE_SENSITIVITY_MIN = 0.000312f; static const float MOUSE_SENSITIVITY_DEFAULT = 0.0025f; static const float MOUSE_SENSITIVITY_MAX = MOUSE_SENSITIVITY_DEFAULT * 2 - MOUSE_SENSITIVITY_MIN; -unsigned long CSettingsSA::FUNC_GetNumVideoModes; -unsigned long CSettingsSA::FUNC_GetVideoModeInfo; -unsigned long CSettingsSA::FUNC_GetCurrentVideoMode; -unsigned long CSettingsSA::FUNC_SetCurrentVideoMode; -unsigned long CSettingsSA::FUNC_SetDrawDistance; -unsigned long CSettingsSA::FUNC_GetNumSubSystems; -unsigned long CSettingsSA::FUNC_GetCurrentSubSystem; -unsigned long CSettingsSA::FUNC_SetSubSystem; - #define VAR_CurVideoMode (*((uint*)(0x08D6220))) #define VAR_SavedVideoMode (*((uint*)(0x0BA6820))) #define VAR_CurAdapter (*((uint*)(0x0C920F4))) @@ -82,50 +73,27 @@ void CSettingsSA::SetWideScreenEnabled(bool bEnabled) unsigned int CSettingsSA::GetNumVideoModes() { - unsigned int uiReturn = 0; - _asm - { - call FUNC_GetNumVideoModes - mov uiReturn, eax - } - return uiReturn; + // RwEngineGetNumVideoModes + return ((unsigned int(__cdecl*)())0x7F2CC0)(); } VideoMode* CSettingsSA::GetVideoModeInfo(VideoMode* modeInfo, unsigned int modeIndex) { - VideoMode* pReturn = NULL; - _asm - { - push modeIndex - push modeInfo - call FUNC_GetVideoModeInfo - mov pReturn, eax - add esp, 8 - } - return pReturn; + // RwEngineGetVideoModeInfo + return ((VideoMode*(__cdecl*)(VideoMode*, unsigned int))0x7F2CF0)(modeInfo, modeIndex); } unsigned int CSettingsSA::GetCurrentVideoMode() { - unsigned int uiReturn = 0; - _asm - { - call FUNC_GetCurrentVideoMode - mov uiReturn, eax - } - return uiReturn; + // RwEngineGetCurrentVideoMode + return ((unsigned int(__cdecl*)())0x7F2D20)(); } void CSettingsSA::SetCurrentVideoMode(unsigned int modeIndex, bool bOnRestart) { if (!bOnRestart) { - _asm - { - push modeIndex - call FUNC_SetCurrentVideoMode - add esp, 4 - } + ((void(__cdecl*)(unsigned int))0x745C70)(modeIndex); } // Only update settings variables for fullscreen modes if (modeIndex) @@ -134,34 +102,20 @@ void CSettingsSA::SetCurrentVideoMode(unsigned int modeIndex, bool bOnRestart) uint CSettingsSA::GetNumAdapters() { - unsigned int uiReturn = 0; - _asm - { - call FUNC_GetNumSubSystems - mov uiReturn, eax - } - return uiReturn; + // RwEngineGetNumSubSystems + return ((unsigned int(__cdecl*)())0x7F2C00)(); } void CSettingsSA::SetAdapter(unsigned int uiAdapterIndex) { - _asm - { - push uiAdapterIndex - call FUNC_SetSubSystem - add esp, 4 - } + // RwEngineSetSubSystem + ((void(__cdecl*)(unsigned int))0x7F2C90)(uiAdapterIndex); } unsigned int CSettingsSA::GetCurrentAdapter() { - unsigned int uiReturn = 0; - _asm - { - call FUNC_GetCurrentSubSystem - mov uiReturn, eax - } - return uiReturn; + // RwEngineGetCurrentSubSystem + return ((unsigned int(__cdecl*)())0x7F2C60)(); } unsigned char CSettingsSA::GetRadioVolume() @@ -238,12 +192,7 @@ float CSettingsSA::GetDrawDistance() void CSettingsSA::SetDrawDistance(float fDistance) { - _asm - { - push fDistance - call FUNC_SetDrawDistance - add esp, 4 - } + MemPutFast(0x8CD800, fDistance); // CRenderer::ms_lodDistScale m_pInterface->fDrawDistance = fDistance; } @@ -324,7 +273,7 @@ void CSettingsSA::Save() } } -bool CSettingsSA::IsVolumetricShadowsEnabled() +bool CSettingsSA::IsVolumetricShadowsEnabled() const noexcept { return m_bVolumetricShadowsEnabled && !m_bVolumetricShadowsSuspended; } @@ -338,6 +287,20 @@ void CSettingsSA::SetVolumetricShadowsEnabled(bool bEnable) MemPut(0x5E682A + 1, bEnable); } + +bool CSettingsSA::GetVolumetricShadowsEnabledByVideoSetting() const noexcept +{ + bool volumetricShadow; + g_pCore->GetCVars()->Get("volumetric_shadows", volumetricShadow); + return volumetricShadow; +} + +bool CSettingsSA::ResetVolumetricShadows() noexcept +{ + pGame->GetSettings()->SetVolumetricShadowsEnabled(pGame->GetSettings()->GetVolumetricShadowsEnabledByVideoSetting()); + return true; +} + void CSettingsSA::SetVolumetricShadowsSuspended(bool bSuspended) { m_bVolumetricShadowsSuspended = bSuspended; diff --git a/Client/game_sa/CSettingsSA.h b/Client/game_sa/CSettingsSA.h index 7fde15381b..7947c94929 100644 --- a/Client/game_sa/CSettingsSA.h +++ b/Client/game_sa/CSettingsSA.h @@ -138,7 +138,10 @@ class CSettingsSA : public CGameSettings bool IsMipMappingEnabled(); void SetMipMappingEnabled(bool bEnable); - bool IsVolumetricShadowsEnabled(); + bool IsVolumetricShadowsEnabled() const noexcept; + bool GetVolumetricShadowsEnabledByVideoSetting() const noexcept; + bool ResetVolumetricShadows() noexcept; + void SetVolumetricShadowsEnabled(bool bEnable); void SetVolumetricShadowsSuspended(bool bSuspended); @@ -185,15 +188,4 @@ class CSettingsSA : public CGameSettings uint FindVideoMode(int iResX, int iResY, int iColorBits); void SetValidVideoMode(); int OnSelectDevice(); - -private: - static unsigned long FUNC_GetNumVideoModes; - static unsigned long FUNC_GetVideoModeInfo; - static unsigned long FUNC_GetCurrentVideoMode; - static unsigned long FUNC_SetCurrentVideoMode; - static unsigned long FUNC_SetRadioVolume; - static unsigned long FUNC_SetDrawDistance; - static unsigned long FUNC_GetNumSubSystems; - static unsigned long FUNC_GetCurrentSubSystem; - static unsigned long FUNC_SetSubSystem; }; diff --git a/Client/game_sa/CStreamingSA.cpp b/Client/game_sa/CStreamingSA.cpp index 0b48b61560..8f8b93dc91 100644 --- a/Client/game_sa/CStreamingSA.cpp +++ b/Client/game_sa/CStreamingSA.cpp @@ -431,6 +431,8 @@ void CStreamingSA::RemoveArchive(unsigned char ucArchiveID) bool CStreamingSA::SetStreamingBufferSize(uint32 numBlocks) { + numBlocks += numBlocks % 2; // Make sure number is even by "rounding" it upwards. [Otherwise it can't be split in half properly] + // Check if the size is the same already if (numBlocks == ms_streamingHalfOfBufferSizeBlocks * 2) return true; @@ -453,10 +455,6 @@ bool CStreamingSA::SetStreamingBufferSize(uint32 numBlocks) // Suspend streaming thread [otherwise data might become corrupted] SuspendThread(*phStreamingThread); - - // Create new buffer - if (numBlocks & 1) // Make it be even [Otherwise it can't be split in half properly] - numBlocks++; // Calculate new buffer pointers void* const pNewBuff0 = pNewBuffer; @@ -505,3 +503,15 @@ void CStreamingSA::RemoveBigBuildings() { (reinterpret_cast(0x4093B0))(); } + +void CStreamingSA::LoadScene(const CVector* position) +{ + auto CStreaming_LoadScene = (void(__cdecl*)(const CVector*))FUNC_CStreaming_LoadScene; + CStreaming_LoadScene(position); +} + +void CStreamingSA::LoadSceneCollision(const CVector* position) +{ + auto CStreaming_LoadSceneCollision = (void(__cdecl*)(const CVector*))FUNC_CStreaming_LoadSceneCollision; + CStreaming_LoadSceneCollision(position); +} diff --git a/Client/game_sa/CStreamingSA.h b/Client/game_sa/CStreamingSA.h index f25409a334..5db5aad830 100644 --- a/Client/game_sa/CStreamingSA.h +++ b/Client/game_sa/CStreamingSA.h @@ -20,6 +20,8 @@ #define FUNC_LoadAllRequestedModels 0x40EA10 #define FUNC_CStreaming__HasVehicleUpgradeLoaded 0x407820 #define FUNC_CStreaming_RequestSpecialModel 0x409d10 +#define FUNC_CStreaming_LoadScene 0x40EB70 +#define FUNC_CStreaming_LoadSceneCollision 0x40ED80 struct CArchiveInfo { @@ -77,6 +79,9 @@ class CStreamingSA final : public CStreaming void MakeSpaceFor(std::uint32_t memoryToCleanInBytes) override; std::uint32_t GetMemoryUsed() const override; + void LoadScene(const CVector* position); + void LoadSceneCollision(const CVector* position); + private: void AllocateArchive(); diff --git a/Client/game_sa/CTasksSA.cpp b/Client/game_sa/CTasksSA.cpp index bd92d51358..9c080e5835 100644 --- a/Client/game_sa/CTasksSA.cpp +++ b/Client/game_sa/CTasksSA.cpp @@ -1,11 +1,11 @@ /***************************************************************************** * - * PROJECT: Multi Theft Auto v1.0 + * PROJECT: Multi Theft Auto * LICENSE: See LICENSE in the top level directory - * FILE: game_sa/CTasksSA.cpp + * FILE: Client/game_sa/CTasksSA.cpp * PURPOSE: Task creation * - * Multi Theft Auto is available from http://www.multitheftauto.com/ + * Multi Theft Auto is available from https://multitheftauto.com/ * *****************************************************************************/ @@ -23,6 +23,7 @@ #include "TaskPhysicalResponseSA.h" #include "TaskSA.h" #include "TaskSecondarySA.h" +#include "CAnimManagerSA.h" extern CGameSA* pGame; @@ -141,6 +142,9 @@ CTaskSimpleJetPack* CTasksSA::CreateTaskSimpleJetpack(const CVector* pVecTargetP CTaskSimpleRunAnim* CTasksSA::CreateTaskSimpleRunAnim(const AssocGroupId animGroup, const AnimationId animID, const float fBlendDelta, const int iTaskType, const char* pTaskName, const bool bHoldLastFrame) { + if (!pGame->GetAnimManager()->IsValidAnim(animGroup, animID)) + return nullptr; + CTaskSimpleRunAnimSA* pTask = NewTask(animGroup, animID, fBlendDelta, iTaskType, pTaskName, bHoldLastFrame); m_pTaskManagementSystem->AddTask(pTask); return pTask; @@ -160,6 +164,9 @@ CTaskComplexDie* CTasksSA::CreateTaskComplexDie(const eWeaponType eMeansOfDeath, const float fAnimSpeed, const bool bBeingKilledByStealth, const bool bFallingToDeath, const int iFallToDeathDir, const bool bFallToDeathOverRailing) { + if (!pGame->GetAnimManager()->IsValidAnim(animGroup, anim)) + return nullptr; + CTaskComplexDieSA* pTask = NewTask(eMeansOfDeath, animGroup, anim, fBlendDelta, fAnimSpeed, bBeingKilledByStealth, bFallingToDeath, iFallToDeathDir, bFallToDeathOverRailing); m_pTaskManagementSystem->AddTask(pTask); @@ -168,6 +175,9 @@ CTaskComplexDie* CTasksSA::CreateTaskComplexDie(const eWeaponType eMeansOfDeath, CTaskSimpleStealthKill* CTasksSA::CreateTaskSimpleStealthKill(bool bKiller, class CPed* pPed, const AnimationId animGroup) { + if (!pGame->GetAnimManager()->IsValidGroup(animGroup)) + return nullptr; + CTaskSimpleStealthKillSA* pTask = NewTask(bKiller, pPed, animGroup); m_pTaskManagementSystem->AddTask(pTask); return pTask; diff --git a/Client/game_sa/CVehicleSA.cpp b/Client/game_sa/CVehicleSA.cpp index a2f6f5c459..91fb5440e0 100644 --- a/Client/game_sa/CVehicleSA.cpp +++ b/Client/game_sa/CVehicleSA.cpp @@ -1,16 +1,17 @@ /***************************************************************************** * - * PROJECT: Multi Theft Auto v1.0 + * PROJECT: Multi Theft Auto * LICENSE: See LICENSE in the top level directory - * FILE: game_sa/CVehicleSA.cpp + * FILE: Client/game_sa/CVehicleSA.cpp * PURPOSE: Vehicle base entity * - * Multi Theft Auto is available from http://www.multitheftauto.com/ + * Multi Theft Auto is available from https://multitheftauto.com/ * *****************************************************************************/ #include "StdInc.h" #include "CAutomobileSA.h" +#include "CBikeSA.h" #include "CCameraSA.h" #include "CColModelSA.h" #include "CFxManagerSA.h" @@ -18,6 +19,7 @@ #include "CGameSA.h" #include "CProjectileInfoSA.h" #include "CTrainSA.h" +#include "CPlaneSA.h" #include "CVehicleSA.h" #include "CVisibilityPluginsSA.h" #include "CWorldSA.h" @@ -184,12 +186,6 @@ void CVehicleSA::Init() } CopyGlobalSuspensionLinesToPrivate(); - - // clear our rw frames list - m_ExtraFrames.clear(); - // dump the frames - VehicleDump(this); - FinalizeFramesList(); } CVehicleSA::~CVehicleSA() @@ -487,6 +483,49 @@ void CVehicleSA::SetTrainSpeed(float fSpeed) pInterface->m_fTrainSpeed = fSpeed; } +void CVehicleSA::SetPlaneRotorSpeed(float fSpeed) +{ + auto pInterface = static_cast(GetInterface()); + pInterface->m_fPropSpeed = fSpeed; +} + +bool CVehicleSA::SetVehicleWheelRotation(float fWheelRot1, float fWheelRot2, float fWheelRot3, float fWheelRot4) noexcept +{ + VehicleClass m_eVehicleType = static_cast(GetVehicleInterface()->m_vehicleSubClass); + switch (m_eVehicleType) + { + case VehicleClass::AUTOMOBILE: + case VehicleClass::MONSTER_TRUCK: + case VehicleClass::QUAD: + case VehicleClass::TRAILER: + { + auto pInterface = static_cast(GetInterface()); + pInterface->m_wheelRotation[0] = fWheelRot1; + pInterface->m_wheelRotation[1] = fWheelRot2; + pInterface->m_wheelRotation[2] = fWheelRot3; + pInterface->m_wheelRotation[3] = fWheelRot4; + return true; + } + case VehicleClass::BIKE: + case VehicleClass::BMX: + { + auto pInterface = static_cast(GetInterface()); + pInterface->m_afWheelRotationX[0] = fWheelRot1; + pInterface->m_afWheelRotationX[1] = fWheelRot2; + return true; + } + default: + return false; + } + return false; +} + +float CVehicleSA::GetPlaneRotorSpeed() +{ + auto pInterface = static_cast(GetInterface()); + return pInterface->m_fPropSpeed; +} + bool CVehicleSA::GetTrainDirection() { auto pInterface = static_cast(GetInterface()); @@ -1275,7 +1314,7 @@ void CVehicleSA::RecalculateHandling() if (!m_pHandlingData) return; - m_pHandlingData->Recalculate(GetModelIndex()); + m_pHandlingData->Recalculate(); // Recalculate the suspension lines RecalculateSuspensionLines(); @@ -1654,11 +1693,6 @@ void CVehicleSA::CopyGlobalSuspensionLinesToPrivate() void CVehicleSA::RecalculateSuspensionLines() { CHandlingEntry* pHandlingEntry = GetHandlingData(); - // if suspension is master disabled or suspension hasn't changed return. - // if ( g_pCore->GetMultiplayer ()->IsSuspensionEnabled () == false || pHandlingEntry->HasSuspensionChanged ( ) == false ) - //{ - // return; - //} DWORD dwModel = GetModelIndex(); CModelInfo* pModelInfo = pGame->GetModelInfo(dwModel); @@ -1909,6 +1943,7 @@ void CVehicleSA::AddComponent(RwFrame* pFrame, bool bReadOnly) // if the frame is invalid we don't want to be here if (!pFrame) return; + // if the frame already exists ignore it if (IsComponentPresent(pFrame->szName) || pFrame->szName == "") return; @@ -1917,23 +1952,22 @@ void CVehicleSA::AddComponent(RwFrame* pFrame, bool bReadOnly) // variants have no name field. if (strName == "") { + // In MTA variant 255 means no variant + if ((m_ucVariantCount == 0 && m_ucVariant == 255) || (m_ucVariantCount == 1 && m_ucVariant2 == 255)) + return; + // name starts with extra strName = "extra_"; - if (m_ucVariantCount == 0) - { - // variants are extra_a, extra_b and so on - strName += ('a' - 1) + m_ucVariant; - } - if (m_ucVariantCount == 1) - { - // variants are extra_a, extra_b and so on - strName += ('a' - 1) + m_ucVariant2; - } + + // variants are extra_a - extra_f + strName += 'a' + (m_ucVariantCount == 0 ? m_ucVariant : m_ucVariant2); + // increment the variant count ( we assume that the first variant created is variant1 and the second is variant2 ) m_ucVariantCount++; } - SVehicleFrame frame = SVehicleFrame(pFrame, bReadOnly); + // insert our new frame + SVehicleFrame frame = SVehicleFrame(pFrame, bReadOnly); m_ExtraFrames.insert(std::pair(strName, frame)); } @@ -1961,6 +1995,16 @@ void CVehicleSA::FinalizeFramesList() } } +void CVehicleSA::DumpVehicleFrames() +{ + // clear our rw frames list + m_ExtraFrames.clear(); + + // dump the frames + VehicleDump(this); + FinalizeFramesList(); +} + bool CVehicleSA::SetComponentVisible(const SString& vehicleComponent, bool bRequestVisible) { SVehicleFrame* pComponent = GetVehicleComponent(vehicleComponent); diff --git a/Client/game_sa/CVehicleSA.h b/Client/game_sa/CVehicleSA.h index 75aa4df807..58632dabbf 100644 --- a/Client/game_sa/CVehicleSA.h +++ b/Client/game_sa/CVehicleSA.h @@ -541,6 +541,8 @@ class CVehicleSA : public virtual CVehicle, public virtual CPhysicalSA bool GetTyresDontBurst() { return GetVehicleInterface()->m_nVehicleFlags.bTyresDontBurst; }; unsigned short GetAdjustablePropertyValue() { return *reinterpret_cast(reinterpret_cast(m_pInterface) + 2156); }; float GetHeliRotorSpeed() { return *reinterpret_cast(reinterpret_cast(m_pInterface) + 2124); }; + float GetPlaneRotorSpeed(); + unsigned long GetExplodeTime() { return *reinterpret_cast(reinterpret_cast(m_pInterface) + 1240); }; char GetNitroCount() { return GetVehicleInterface()->m_nNitroBoosts; } @@ -565,6 +567,8 @@ class CVehicleSA : public virtual CVehicle, public virtual CPhysicalSA *reinterpret_cast(reinterpret_cast(m_pInterface) + 2156) = usAdjustableProperty; }; void SetHeliRotorSpeed(float fSpeed) { *reinterpret_cast(reinterpret_cast(m_pInterface) + 2124) = fSpeed; }; + void SetPlaneRotorSpeed(float fSpeed); + bool SetVehicleWheelRotation(float fWheelRot1, float fWheelRot2, float fWheelRot3, float fWheelRot4) noexcept; void SetExplodeTime(unsigned long ulTime) { *reinterpret_cast(reinterpret_cast(m_pInterface) + 1240) = ulTime; }; void SetRadioStatus(bool bStatus) { *reinterpret_cast(reinterpret_cast(m_pInterface) + 0x1D3) = bStatus; }; @@ -683,4 +687,5 @@ class CVehicleSA : public virtual CVehicle, public virtual CPhysicalSA void CopyGlobalSuspensionLinesToPrivate(); SVehicleFrame* GetVehicleComponent(const SString& vehicleComponent); void FinalizeFramesList(); + void DumpVehicleFrames(); }; diff --git a/Client/game_sa/CVisibilityPluginsSA.cpp b/Client/game_sa/CVisibilityPluginsSA.cpp index d7cf9849bc..b5fe2d92c6 100644 --- a/Client/game_sa/CVisibilityPluginsSA.cpp +++ b/Client/game_sa/CVisibilityPluginsSA.cpp @@ -12,6 +12,8 @@ #include "StdInc.h" #include "CVisibilityPluginsSA.h" +#define FUNC_CVisibilityPlugins_InsertEntityIntoEntityList 0x733DD0 + void CVisibilityPluginsSA::SetClumpAlpha(RpClump* pClump, int iAlpha) { DWORD dwFunc = FUNC_CVisiblityPlugins_SetClumpAlpha; @@ -51,3 +53,8 @@ int CVisibilityPluginsSA::GetAtomicId(RwObject* pAtomic) } return iResult; } + +bool CVisibilityPluginsSA::InsertEntityIntoEntityList(void* entity, float distance, void* callback) +{ + return ((bool(_cdecl*)(void*, float, void*))FUNC_CVisibilityPlugins_InsertEntityIntoEntityList)(entity, distance, callback); +} diff --git a/Client/game_sa/CVisibilityPluginsSA.h b/Client/game_sa/CVisibilityPluginsSA.h index 57cab620c0..f4a583bcf2 100644 --- a/Client/game_sa/CVisibilityPluginsSA.h +++ b/Client/game_sa/CVisibilityPluginsSA.h @@ -21,4 +21,6 @@ class CVisibilityPluginsSA : public CVisibilityPlugins public: void SetClumpAlpha(RpClump* pClump, int iAlpha); int GetAtomicId(RwObject* pAtomic); + + bool InsertEntityIntoEntityList(void* entity, float distance, void* callback); }; diff --git a/Client/game_sa/CWeatherSA.cpp b/Client/game_sa/CWeatherSA.cpp index 7b6364334c..c549aa08e1 100644 --- a/Client/game_sa/CWeatherSA.cpp +++ b/Client/game_sa/CWeatherSA.cpp @@ -12,35 +12,30 @@ #include "StdInc.h" #include "CWeatherSA.h" -unsigned char* CWeatherSA::VAR_CWeather__ForcedWeatherType; -unsigned char* CWeatherSA::VAR_CWeather__OldWeatherType; -unsigned char* CWeatherSA::VAR_CWeather__NewWeatherType; -float* CWeatherSA::VAR_CWeather__Rain; - unsigned char CWeatherSA::Get() { - return (unsigned char)*VAR_CWeather__ForcedWeatherType; + return *(unsigned char*)0xC81318; // CWeather::ForcedWeatherType } void CWeatherSA::Set(unsigned char primary, unsigned char secondary) { - *VAR_CWeather__OldWeatherType = static_cast(primary); - *VAR_CWeather__NewWeatherType = static_cast(secondary); + MemPutFast(0xC81320, primary); // CWeather::OldWeatherType + MemPutFast(0xC8131C, secondary); // CWeather::NewWeatherType } void CWeatherSA::Release() { - *VAR_CWeather__ForcedWeatherType = 0xFF; + MemPutFast(0xC81318, 0xFF); // CWeather::ForcedWeatherType } float CWeatherSA::GetAmountOfRain() { - return *VAR_CWeather__Rain; + return *(float*)0xC81324; // CWeather::Rain } void CWeatherSA::SetAmountOfRain(float fAmount) { - // Nop the functions which don't like us take care of the rain + // Patch all the places inside of CWeather::Update that would overwrite CWeather::Rain MemPut(0x72C686, 0xDD); MemPut(0x72C687, 0xD8); @@ -54,7 +49,7 @@ void CWeatherSA::SetAmountOfRain(float fAmount) MemSet((void*)0x72BC72, 0x90, 5); // Set the amount of rain - *VAR_CWeather__Rain = fAmount; + MemPutFast(0xC81324, fAmount); // CWeather::Rain } void CWeatherSA::ResetAmountOfRain() @@ -67,3 +62,169 @@ void CWeatherSA::ResetAmountOfRain() MemCpy((LPVOID)0x72BC92, &originalFstp1, 6); MemCpy((LPVOID)0x72C686, &originalFstp2, 6); } + +float CWeatherSA::GetWetRoads() const +{ + return *(float*)0xC81308; +} + +bool CWeatherSA::SetWetRoads(float fAmount) +{ + MemSet((LPVOID)(0x72BB9F + 2), 0x90, 3); + MemSet((LPVOID)(0x72BBB7 + 2), 0x90, 3); + MemSet((LPVOID)(0x72BBD0 + 1), 0x90, 3); + MemSet((LPVOID)(0x72BBD7 + 2), 0x90, 3); + + MemPutFast(0xC81308, fAmount); + return true; +} + +bool CWeatherSA::ResetWetRoads() +{ + BYTE originalCodes[3] = {0x08, 0x13, 0xC8}; + MemCpy((LPVOID)(0x72BB9F + 2), &originalCodes, 3); + MemCpy((LPVOID)(0x72BBB7 + 2), &originalCodes, 3); + MemCpy((LPVOID)(0x72BBD0 + 1), &originalCodes, 3); + MemCpy((LPVOID)(0x72BBD7 + 2), &originalCodes, 3); + return true; +} + +float CWeatherSA::GetFoggyness() const +{ + return *(float*)0xC81300; +} + +bool CWeatherSA::SetFoggyness(float fAmount) +{ + MemSet((LPVOID)(0x72BDF5 + 2), 0x90, 3); + MemSet((LPVOID)(0x72BDDD + 2), 0x90, 3); + MemSet((LPVOID)(0x72BE13 + 2), 0x90, 3); + + MemPutFast(0xC81300, fAmount); + return true; +} + +bool CWeatherSA::ResetFoggyness() +{ + BYTE originalCodes[3] = {0x00, 0x13, 0xC8}; + MemCpy((LPVOID)(0x72BDF5 + 2), &originalCodes, 3); + MemCpy((LPVOID)(0x72BDDD + 2), &originalCodes, 3); + MemCpy((LPVOID)(0x72BE13 + 2), &originalCodes, 3); + return true; +} + +float CWeatherSA::GetFog() const +{ + return *(float*)0xC812FC; +} + +bool CWeatherSA::SetFog(float fAmount) +{ + MemSet((LPVOID)(0x72BE37 + 2), 0x90, 3); + MemSet((LPVOID)(0x72BE1F + 2), 0x90, 3); + MemSet((LPVOID)(0x72BE4F + 2), 0x90, 3); + + MemPutFast(0xC812FC, fAmount); + return true; +} + +bool CWeatherSA::ResetFog() +{ + BYTE originalCodes[3] = {0xFC, 0x12, 0xC8}; + MemCpy((LPVOID)(0x72BE37 + 2), &originalCodes, 3); + MemCpy((LPVOID)(0x72BE1F + 2), &originalCodes, 3); + MemCpy((LPVOID)(0x72BE4F + 2), &originalCodes, 3); + return true; +} + +float CWeatherSA::GetRainFog() const +{ + return *(float*)0xC81410; +} + +bool CWeatherSA::SetRainFog(float fAmount) +{ + MemSet((LPVOID)(0x72ADD8 + 2), 0x90, 3); + MemSet((LPVOID)(0x72ADE4 + 2), 0x90, 3); + + MemPutFast(0xC81410, fAmount); + return true; +} + +bool CWeatherSA::ResetRainFog() +{ + BYTE originalCodes[3] = {0x10, 0x14, 0xC8}; + MemCpy((LPVOID)(0x72ADD8 + 2), &originalCodes, 3); + MemCpy((LPVOID)(0x72ADE4 + 2), &originalCodes, 3); + return true; +} + +float CWeatherSA::GetWaterFog() const +{ + return *(float*)0xC81338; +} + +bool CWeatherSA::SetWaterFog(float fAmount) +{ + MemSet((LPVOID)(0x72C35C + 2), 0x90, 3); + MemSet((LPVOID)(0x72C38E + 2), 0x90, 3); + MemSet((LPVOID)(0x72C36F + 2), 0x90, 3); + + MemPutFast(0xC81338, fAmount); + return true; +} + +bool CWeatherSA::ResetWaterFog() +{ + BYTE originalCodes[3] = {0x38, 0x13, 0xC8}; + MemCpy((LPVOID)(0x72C35C + 2), &originalCodes, 3); + MemCpy((LPVOID)(0x72C38E + 2), &originalCodes, 3); + MemCpy((LPVOID)(0x72C36F + 2), &originalCodes, 3); + return true; +} + +float CWeatherSA::GetSandstorm() const +{ + return *(float*)0xC812F4; +} + +bool CWeatherSA::SetSandstorm(float fAmount) +{ + MemSet((LPVOID)(0x72A4B6 + 1), 0x90, 3); + MemSet((LPVOID)(0x72BCEB + 1), 0x90, 3); + MemSet((LPVOID)(0x72BD0B + 2), 0x90, 3); + + MemPutFast(0xC812F4, fAmount); + return true; +} + +bool CWeatherSA::ResetSandstorm() +{ + BYTE originalCodes[3] = {0xF4, 0x12, 0xC8}; + MemCpy((LPVOID)(0x72A4B6 + 1), &originalCodes, 3); + MemCpy((LPVOID)(0x72BCEB + 1), &originalCodes, 3); + MemCpy((LPVOID)(0x72BD0B + 2), &originalCodes, 3); + return true; +} + +float CWeatherSA::GetRainbow() const +{ + return *(float*)0xC812E4; +} + +bool CWeatherSA::SetRainbow(float fAmount) +{ + MemSet((LPVOID)(0x72BF51 + 2), 0x90, 3); + MemSet((LPVOID)(0x72BF59 + 2), 0x90, 3); + + MemPutFast(0xC812E4, fAmount); + return true; +} + +bool CWeatherSA::ResetRainbow() +{ + BYTE originalCodes[3] = {0xE4, 0x12, 0xC8}; + MemCpy((LPVOID)(0x72BF51 + 2), &originalCodes, 3); + MemCpy((LPVOID)(0x72BF59 + 2), &originalCodes, 3); + return true; +} diff --git a/Client/game_sa/CWeatherSA.h b/Client/game_sa/CWeatherSA.h index baf1b98e1d..31898204fa 100644 --- a/Client/game_sa/CWeatherSA.h +++ b/Client/game_sa/CWeatherSA.h @@ -27,6 +27,34 @@ class CWeatherSA : public CWeather void SetAmountOfRain(float fAmount); void ResetAmountOfRain(); + float GetWetRoads() const; + bool SetWetRoads(float fAmount); + bool ResetWetRoads(); + + float GetFoggyness() const; + bool SetFoggyness(float fAmount); + bool ResetFoggyness(); + + float GetFog() const; + bool SetFog(float fAmount); + bool ResetFog(); + + float GetRainFog() const; + bool SetRainFog(float fAmount); + bool ResetRainFog(); + + float GetWaterFog() const; + bool SetWaterFog(float fAmount); + bool ResetWaterFog(); + + float GetSandstorm() const; + bool SetSandstorm(float fAmount); + bool ResetSandstorm(); + + float GetRainbow() const; + bool SetRainbow(float fAmount); + bool ResetRainbow(); + private: static unsigned char* VAR_CWeather__ForcedWeatherType; static unsigned char* VAR_CWeather__OldWeatherType; diff --git a/Client/game_sa/CWorldSA.cpp b/Client/game_sa/CWorldSA.cpp index b946b7e3c1..a60e360464 100644 --- a/Client/game_sa/CWorldSA.cpp +++ b/Client/game_sa/CWorldSA.cpp @@ -31,10 +31,6 @@ namespace CWorldSA::CWorldSA() { - m_pBuildingRemovals = new std::multimap; - m_pDataBuildings = new std::multimap; - m_pBinaryBuildings = new std::multimap; - m_pSurfaceInfo = reinterpret_cast(ARRAY_SurfaceInfos); InstallHooks(); @@ -735,678 +731,6 @@ int CWorldSA::FindClosestRailTrackNode(const CVector& vecPosition, uchar& ucOutT return iNodeId; } -void CWorldSA::RemoveBuilding(unsigned short usModelToRemove, float fRange, float fX, float fY, float fZ, char cInterior, uint* pOutAmount) -{ - // New building Removal - SBuildingRemoval* pRemoval = new SBuildingRemoval(); - pRemoval->m_usModel = usModelToRemove; - pRemoval->m_vecPos.fX = fX; - pRemoval->m_vecPos.fY = fY; - pRemoval->m_vecPos.fZ = fZ; - pRemoval->m_fRadius = fRange; - pRemoval->m_cInterior = cInterior; - // Push it to the back of the removal list - m_pBuildingRemovals->insert(std::pair(usModelToRemove, pRemoval)); - - bool bFound = false; - uint uiAmount = 0; - // Init loop variables - std::pair::iterator, std::multimap::iterator> - iterators = m_pDataBuildings->equal_range(usModelToRemove); - std::multimap::const_iterator iter = iterators.first; - for (; iter != iterators.second; ++iter) - { - sDataBuildingRemovalItem* pFind = (*iter).second; - if (pFind) - { - // if the count is <= 0 and the interface is valid check the distance in case we found a removal (count is used to store if we have already removed - // this once) - if (pFind->m_iCount <= 0 && pFind->m_pInterface) - { - // Grab distances across each axis - float fDistanceX = fX - pFind->m_pInterface->Placeable.m_transform.m_translate.fX; - float fDistanceY = fY - pFind->m_pInterface->Placeable.m_transform.m_translate.fY; - float fDistanceZ = fZ - pFind->m_pInterface->Placeable.m_transform.m_translate.fZ; - - if (pFind->m_pInterface->Placeable.matrix != NULL) - { - fDistanceX = fX - pFind->m_pInterface->Placeable.matrix->vPos.fX; - fDistanceY = fY - pFind->m_pInterface->Placeable.matrix->vPos.fY; - fDistanceZ = fZ - pFind->m_pInterface->Placeable.matrix->vPos.fZ; - } - - // Square root 'em - float fDistance = sqrt(fDistanceX * fDistanceX + fDistanceY * fDistanceY + fDistanceZ * fDistanceZ); - - // Is it in range - if (fDistance <= fRange && (pFind->m_pInterface->m_areaCode == cInterior || cInterior == -1)) - { - CEntitySAInterface* pInterface = pFind->m_pInterface; - // while ( pInterface && pInterface != NULL ) - // if the interface is valid - if (pInterface && pInterface != NULL) - { - // if the building type is dummy or building and it's not already being removed - if ((pInterface->nType == ENTITY_TYPE_BUILDING || pInterface->nType == ENTITY_TYPE_DUMMY || pInterface->nType == ENTITY_TYPE_OBJECT) && - pInterface->bRemoveFromWorld != 1) - { - if ((DWORD)(pInterface->vtbl) != VTBL_CPlaceable) - { - // Add the Data Building to the list - pRemoval->AddDataBuilding(pInterface); - // Remove the model from the world - Remove(pInterface, BuildingRemoval2); - m_pRemovedEntities[(DWORD)pInterface] = true; - bFound = true; - } - } - // Get next LOD ( LOD's can have LOD's so we keep checking pInterface ) - // pInterface = pInterface->m_pLod; - } - // Set the count. - pFind->m_iCount = 1; - } - } - } - } - - std::pair::iterator, std::multimap::iterator> iteratorsBinary = - m_pBinaryBuildings->equal_range(usModelToRemove); - std::multimap::const_iterator iterBinary = iteratorsBinary.first; - for (; iterBinary != iteratorsBinary.second; ++iterBinary) - { - sBuildingRemovalItem* pFindBinary = (*iterBinary).second; - if (pFindBinary) - { - // if the count is <= 0 and the interface is valid check the distance in case we found a removal (count is used to store if we have already removed - // this once) - if (pFindBinary->m_iCount <= 0 && pFindBinary->m_pInterface) - { - // Grab distances across each axis - float fDistanceX = fX - pFindBinary->m_pInterface->Placeable.m_transform.m_translate.fX; - float fDistanceY = fY - pFindBinary->m_pInterface->Placeable.m_transform.m_translate.fY; - float fDistanceZ = fZ - pFindBinary->m_pInterface->Placeable.m_transform.m_translate.fZ; - - if (pFindBinary->m_pInterface->Placeable.matrix != NULL) - { - fDistanceX = fX - pFindBinary->m_pInterface->Placeable.matrix->vPos.fX; - fDistanceY = fY - pFindBinary->m_pInterface->Placeable.matrix->vPos.fY; - fDistanceZ = fZ - pFindBinary->m_pInterface->Placeable.matrix->vPos.fZ; - } - - // Square root 'em - float fDistance = sqrt(fDistanceX * fDistanceX + fDistanceY * fDistanceY + fDistanceZ * fDistanceZ); - - // Is it in range - if (fDistance <= fRange && (pFindBinary->m_pInterface->m_areaCode == cInterior || cInterior == -1)) - { - CEntitySAInterface* pInterface = pFindBinary->m_pInterface; - // while ( pInterface && pInterface != NULL ) - // if the interface is valid - if (pInterface && pInterface != NULL) - { - // if the building type is dummy or building and it's not already being removed - if ((pInterface->nType == ENTITY_TYPE_BUILDING || pInterface->nType == ENTITY_TYPE_DUMMY || pInterface->nType == ENTITY_TYPE_OBJECT) && - pInterface->bRemoveFromWorld != 1) - { - if ((DWORD)(pInterface->vtbl) != VTBL_CPlaceable) - { - // Add the Data Building to the list - pRemoval->AddBinaryBuilding(pInterface); - // Remove the model from the world - Remove(pInterface, BuildingRemoval2); - m_pRemovedEntities[(DWORD)pInterface] = true; - bFound = true; - ++uiAmount; - } - } - // Get next LOD ( LOD's can have LOD's so we keep checking pInterface ) - // pInterface = pInterface->m_pLod; - } - // Set the count. - pFindBinary->m_iCount = 1; - } - } - } - } - if (bFound) - pGame->GetModelInfo(usModelToRemove)->RestreamIPL(); - - if (pOutAmount) - *pOutAmount = uiAmount; -} - -bool CWorldSA::RestoreBuilding(unsigned short usModelToRestore, float fRange, float fX, float fY, float fZ, char cInterior, uint* pOutAmount) -{ - bool bSuccess = false; - uint uiAmount = 0; - - // Init some variables - std::pair::iterator, std::multimap::iterator> iterators = - m_pBuildingRemovals->equal_range(usModelToRestore); - std::multimap::const_iterator iter = iterators.first; - // Loop through the buildings list - for (; iter != iterators.second;) - { - SBuildingRemoval* pFind = (*iter).second; - // if pFind is valid and the model is the same - if (pFind) - { - // Grab distances across each axis - float fDistanceX = fX - pFind->m_vecPos.fX; - float fDistanceY = fY - pFind->m_vecPos.fY; - float fDistanceZ = fZ - pFind->m_vecPos.fZ; - - // Square root 'em - float fDistance = sqrt(fDistanceX * fDistanceX + fDistanceY * fDistanceY + fDistanceZ * fDistanceZ); - if (fDistance <= pFind->m_fRadius && (cInterior == -1 || pFind->m_cInterior == cInterior)) - { - // Init some variables - CEntitySAInterface* pEntity = NULL; - std::list::const_iterator entityIter = pFind->m_pBinaryRemoveList->begin(); - if (pFind->m_pBinaryRemoveList->empty() == false) - { - // Loop through the Binary object list - for (; entityIter != pFind->m_pBinaryRemoveList->end();) - { - // Grab the pEntity - pEntity = (*entityIter); - // if it's valid re-add it to the world. - if (pEntity != NULL) - { - // Remove it from the binary list - pFind->m_pBinaryRemoveList->erase(entityIter++); - // if the building type is dummy or building and it's not already being removed - if ((pEntity->nType == ENTITY_TYPE_BUILDING || pEntity->nType == ENTITY_TYPE_DUMMY || pEntity->nType == ENTITY_TYPE_OBJECT) && - pEntity->bRemoveFromWorld != 1) - { - // Don't call this on entities being removed. - if ((DWORD)(pEntity->vtbl) != VTBL_CPlaceable) - { - Add(pEntity, Building_Restore); - m_pRemovedEntities[(DWORD)pEntity] = false; - // If the building isn't streamed in, we won't find the building in the list (because the hook wasn't called) -> - // removeWorldModel doesn't work next time - AddBinaryBuilding(pEntity); - ++uiAmount; - } - } - } - else - ++entityIter; - } - } - // Start the iterator with the data remove list first item - entityIter = pFind->m_pDataRemoveList->begin(); - if (pFind->m_pDataRemoveList->empty() == false) - { - // Loop through the Data list - for (; entityIter != pFind->m_pDataRemoveList->end();) - { - // Grab the pEntity - pEntity = (*entityIter); - // if it's valid re-add it to the world. - if (pEntity != NULL) - { - pFind->m_pDataRemoveList->erase(entityIter++); - // if the building type is dummy or building and it's not already being removed - if ((pEntity->nType == ENTITY_TYPE_BUILDING || pEntity->nType == ENTITY_TYPE_DUMMY || pEntity->nType == ENTITY_TYPE_OBJECT) && - pEntity->bRemoveFromWorld != 1) - { - if ((DWORD)(pEntity->vtbl) != VTBL_CPlaceable) - { - Add(pEntity, Building_Restore2); - m_pRemovedEntities[(DWORD)pEntity] = false; - } - } - } - else - { - ++entityIter; - } - } - } - // Remove the building from the list - m_pBuildingRemovals->erase(iter++); - delete pFind; - // Success! don't return incase there are any others to delete - bSuccess = true; - } - else - iter++; - } - else - iter++; - } - std::pair::iterator, std::multimap::iterator> - dataBuildingIterators = m_pDataBuildings->equal_range(usModelToRestore); - std::multimap::const_iterator iterator = dataBuildingIterators.first; - for (; iterator != dataBuildingIterators.second; ++iterator) - { - sDataBuildingRemovalItem* pFound = (*iterator).second; - if (pFound) - { - // Grab distances across each axis - float fDistanceX = fX - pFound->m_pInterface->Placeable.m_transform.m_translate.fX; - float fDistanceY = fY - pFound->m_pInterface->Placeable.m_transform.m_translate.fY; - float fDistanceZ = fZ - pFound->m_pInterface->Placeable.m_transform.m_translate.fZ; - - if (pFound->m_pInterface->Placeable.matrix != NULL) - { - fDistanceX = fX - pFound->m_pInterface->Placeable.matrix->vPos.fX; - fDistanceY = fY - pFound->m_pInterface->Placeable.matrix->vPos.fY; - fDistanceZ = fZ - pFound->m_pInterface->Placeable.matrix->vPos.fZ; - } - - // Square root 'em - float fDistance = sqrt(fDistanceX * fDistanceX + fDistanceY * fDistanceY + fDistanceZ * fDistanceZ); - if (fDistance <= fRange && (cInterior == -1 || pFound->m_pInterface->m_areaCode == cInterior)) - { - // Fix the removed count. - pFound->m_iCount--; - if (pFound->m_iCount < 0) - pFound->m_iCount = 0; - } - } - } - - std::pair::iterator, std::multimap::iterator> - binaryBuildingIterators = m_pBinaryBuildings->equal_range(usModelToRestore); - std::multimap::const_iterator iteratorBinary = binaryBuildingIterators.first; - for (; iteratorBinary != binaryBuildingIterators.second; ++iteratorBinary) - { - sBuildingRemovalItem* pFoundBinary = (*iteratorBinary).second; - if (pFoundBinary) - { - // Grab distances across each axis - float fDistanceX = fX - pFoundBinary->m_pInterface->Placeable.m_transform.m_translate.fX; - float fDistanceY = fY - pFoundBinary->m_pInterface->Placeable.m_transform.m_translate.fY; - float fDistanceZ = fZ - pFoundBinary->m_pInterface->Placeable.m_transform.m_translate.fZ; - - if (pFoundBinary->m_pInterface->Placeable.matrix != NULL) - { - fDistanceX = fX - pFoundBinary->m_pInterface->Placeable.matrix->vPos.fX; - fDistanceY = fY - pFoundBinary->m_pInterface->Placeable.matrix->vPos.fY; - fDistanceZ = fZ - pFoundBinary->m_pInterface->Placeable.matrix->vPos.fZ; - } - - // Square root 'em - float fDistance = sqrt(fDistanceX * fDistanceX + fDistanceY * fDistanceY + fDistanceZ * fDistanceZ); - if (fDistance <= fRange && (cInterior == -1 || pFoundBinary->m_pInterface->m_areaCode == cInterior)) - { - // Fix the removed count. - pFoundBinary->m_iCount--; - if (pFoundBinary->m_iCount < 0) - pFoundBinary->m_iCount = 0; - } - } - } - - if (pOutAmount) - *pOutAmount = uiAmount; - - return bSuccess; -} - -// Check Distance to see if the model being requested is in the radius -bool CWorldSA::IsRemovedModelInRadius(SIPLInst* pInst) -{ - // Init some variables - std::pair::iterator, std::multimap::iterator> iterators = - m_pBuildingRemovals->equal_range(pInst->m_nModelIndex); - std::multimap::const_iterator iter = iterators.first; - // Loop through the buildings list - for (; iter != iterators.second; ++iter) - { - SBuildingRemoval* pFind = (*iter).second; - // if pFind is valid and the model is the same - if (pFind) - { - // Grab the distance - float fDistanceX = pFind->m_vecPos.fX - pInst->m_pPosition.fX; - float fDistanceY = pFind->m_vecPos.fY - pInst->m_pPosition.fY; - float fDistanceZ = pFind->m_vecPos.fZ - pInst->m_pPosition.fZ; - - float fDistance = sqrt(fDistanceX * fDistanceX + fDistanceY * fDistanceY + fDistanceZ * fDistanceZ); - // is it in the removal spheres radius if so return else keep looking - if (fDistance <= pFind->m_fRadius && (pFind->m_cInterior == -1 || pFind->m_cInterior == pInst->m_nInterior)) - { - return true; - } - } - } - return false; -} - -// Check Distance to see if the model being requested is in the radius -bool CWorldSA::IsObjectRemoved(CEntitySAInterface* pInterface) -{ - // Init some variables - std::pair::iterator, std::multimap::iterator> iterators = - m_pBuildingRemovals->equal_range(pInterface->m_nModelIndex); - std::multimap::const_iterator iter = iterators.first; - // Loop through the buildings list - for (; iter != iterators.second; ++iter) - { - SBuildingRemoval* pFind = (*iter).second; - // if pFind is valid and the model is the same - if (pFind) - { - // Are we using the interior param?? if so check for a match - if (pFind->m_cInterior == -1 || pFind->m_cInterior == pInterface->m_areaCode) - { - // Grab the distance - float fDistanceX = pFind->m_vecPos.fX - pInterface->Placeable.m_transform.m_translate.fX; - float fDistanceY = pFind->m_vecPos.fY - pInterface->Placeable.m_transform.m_translate.fY; - float fDistanceZ = pFind->m_vecPos.fZ - pInterface->Placeable.m_transform.m_translate.fZ; - - if (pInterface->Placeable.matrix != NULL) - { - fDistanceX = pFind->m_vecPos.fX - pInterface->Placeable.matrix->vPos.fX; - fDistanceY = pFind->m_vecPos.fY - pInterface->Placeable.matrix->vPos.fY; - fDistanceZ = pFind->m_vecPos.fZ - pInterface->Placeable.matrix->vPos.fZ; - } - - float fDistance = sqrt(fDistanceX * fDistanceX + fDistanceY * fDistanceY + fDistanceZ * fDistanceZ); - // is it in the removal spheres radius if so return else keep looking - if (fDistance <= pFind->m_fRadius) - { - return true; - } - } - } - } - return false; -} - -// Check if a given model is replaced -bool CWorldSA::IsModelRemoved(unsigned short usModelID) -{ - return m_pBuildingRemovals->count(usModelID) > 0; -} - -// Check if a given model is replaced -bool CWorldSA::IsDataModelRemoved(unsigned short usModelID) -{ - return m_pBuildingRemovals->count(usModelID) > 0; -} - -// Check if a given model is replaced -bool CWorldSA::IsEntityRemoved(CEntitySAInterface* pInterface) -{ - return m_pRemovedEntities.find((DWORD)pInterface) != m_pRemovedEntities.end() && m_pRemovedEntities[(DWORD)pInterface] == true; -} - -// Resets deleted list -void CWorldSA::ClearRemovedBuildingLists(uint* pOutAmount) -{ - // Ensure no memory leaks by deleting items. - uint uiAmount = 0; - std::multimap::const_iterator iter = m_pBuildingRemovals->begin(); - - for (; iter != m_pBuildingRemovals->end();) - { - SBuildingRemoval* pFind = (*iter).second; - if (pFind) - { - // Init some variables - CEntitySAInterface* pEntity = NULL; - std::list::const_iterator entityIter = pFind->m_pBinaryRemoveList->begin(); - if (pFind->m_pBinaryRemoveList->empty() == false) - { - // Loop through the Binary remove list - for (; entityIter != pFind->m_pBinaryRemoveList->end(); ++entityIter) - { - // Grab the pEntity - pEntity = (*entityIter); - // if it's valid re-add it to the world. - if (pEntity && pEntity != NULL) - { - // if the building type is dummy or building and it's not already being removed - if ((pEntity->nType == ENTITY_TYPE_BUILDING || pEntity->nType == ENTITY_TYPE_DUMMY || pEntity->nType == ENTITY_TYPE_OBJECT) && - pEntity->bRemoveFromWorld != 1) - { - // Don't call this on entities being removed. - if ((DWORD)(pEntity->vtbl) != VTBL_CPlaceable) - { - Add(pEntity, BuildingRemovalReset); - m_pRemovedEntities[(DWORD)pEntity] = false; - ++uiAmount; - } - } - } - } - } - entityIter = pFind->m_pDataRemoveList->begin(); - if (pFind->m_pDataRemoveList->empty() == false) - { - // Loop through the Data list - for (; entityIter != pFind->m_pDataRemoveList->end(); ++entityIter) - { - // Grab the pEntity - pEntity = (*entityIter); - // if it's valid re-add it to the world. - if (pEntity && pEntity != NULL) - { - // if the building type is dummy or building and it's not already being removed - if ((pEntity->nType == ENTITY_TYPE_BUILDING || pEntity->nType == ENTITY_TYPE_DUMMY || pEntity->nType == ENTITY_TYPE_OBJECT) && - pEntity->bRemoveFromWorld != 1) - { - // Don't call this on entities being removed. - if ((DWORD)(pEntity->vtbl) != VTBL_CPlaceable) - { - Add(pEntity, BuildingRemovalReset2); - m_pRemovedEntities[(DWORD)pEntity] = false; - } - } - } - } - } - m_pBuildingRemovals->erase(iter++); - } - else - iter++; - } - // Init some variables - std::multimap::const_iterator iterator = m_pDataBuildings->begin(); - // Loop through the data building list - for (; iterator != m_pDataBuildings->end(); ++iterator) - { - sDataBuildingRemovalItem* pFound = (*iterator).second; - if (pFound) - { - // Set the count to 0 so we can remove it again - pFound->m_iCount = 0; - } - } - // Init some variables - std::multimap::const_iterator iteratorBinary = m_pBinaryBuildings->begin(); - // Loop through the data building list - for (; iteratorBinary != m_pBinaryBuildings->end(); ++iteratorBinary) - { - sBuildingRemovalItem* pFoundBinary = (*iteratorBinary).second; - if (pFoundBinary) - { - // Set the count to 0 so we can remove it again - pFoundBinary->m_iCount = 0; - } - } - // Delete old building lists - delete m_pBuildingRemovals; - // Create new - m_pBuildingRemovals = new std::multimap; - m_pRemovedEntities.clear(); - - if (pOutAmount) - *pOutAmount = uiAmount; -} - -// Resets deleted list -SBuildingRemoval* CWorldSA::GetBuildingRemoval(CEntitySAInterface* pInterface) -{ - // Init some variables - std::pair::iterator, std::multimap::iterator> iterators = - m_pBuildingRemovals->equal_range(pInterface->m_nModelIndex); - std::multimap::const_iterator iter = iterators.first; - // Loop through the buildings list - for (; iter != iterators.second; ++iter) - { - SBuildingRemoval* pFind = (*iter).second; - // if pFind is valid and the model is the same - if (pFind) - { - // Grab the distance - float fDistanceX = pFind->m_vecPos.fX - pInterface->Placeable.m_transform.m_translate.fX; - float fDistanceY = pFind->m_vecPos.fY - pInterface->Placeable.m_transform.m_translate.fY; - float fDistanceZ = pFind->m_vecPos.fZ - pInterface->Placeable.m_transform.m_translate.fZ; - - if (pInterface->Placeable.matrix != NULL) - { - fDistanceX = pFind->m_vecPos.fX - pInterface->Placeable.matrix->vPos.fX; - fDistanceY = pFind->m_vecPos.fY - pInterface->Placeable.matrix->vPos.fY; - fDistanceZ = pFind->m_vecPos.fZ - pInterface->Placeable.matrix->vPos.fZ; - } - - float fDistance = sqrt(fDistanceX * fDistanceX + fDistanceY * fDistanceY + fDistanceZ * fDistanceZ); - // is it in the removal spheres radius if so return else keep looking - if (fDistance <= pFind->m_fRadius && (pFind->m_cInterior == -1 || pFind->m_cInterior == pInterface->m_areaCode)) - { - return pFind; - } - } - } - return NULL; -} - -void CWorldSA::AddDataBuilding(CEntitySAInterface* pInterface) -{ - if (m_pAddedEntities.find((DWORD)pInterface) == m_pAddedEntities.end() || m_pAddedEntities[(DWORD)pInterface] == false) - { - // Create a new building removal - sDataBuildingRemovalItem* pBuildingRemoval = new sDataBuildingRemovalItem(pInterface, true); - // Insert it with the model index so we can fast lookup - m_pDataBuildings->insert(std::pair((unsigned short)pInterface->m_nModelIndex, pBuildingRemoval)); - m_pAddedEntities[(DWORD)pInterface] = true; - m_pRemovedEntities[(DWORD)pInterface] = false; - } -} - -void CWorldSA::AddBinaryBuilding(CEntitySAInterface* pInterface) -{ - if (m_pAddedEntities.find((DWORD)pInterface) == m_pAddedEntities.end() || m_pAddedEntities[(DWORD)pInterface] == false) - { - // Create a new building removal - sBuildingRemovalItem* pBuildingRemoval = new sBuildingRemovalItem(pInterface, false); - // Insert it with the model index so we can fast lookup - m_pBinaryBuildings->insert(std::pair((unsigned short)pInterface->m_nModelIndex, pBuildingRemoval)); - m_pAddedEntities[(DWORD)pInterface] = true; - m_pRemovedEntities[(DWORD)pInterface] = false; - } -} - -void CWorldSA::RemoveWorldBuildingFromLists(CEntitySAInterface* pInterface) -{ - std::pair::iterator, std::multimap::iterator> iterators = - m_pBuildingRemovals->equal_range(pInterface->m_nModelIndex); - std::multimap::const_iterator iter = iterators.first; - - // Loop through the buildings list - for (; iter != iterators.second; ++iter) - { - SBuildingRemoval* pFind = (*iter).second; - // if pFind is valid and the model is the same - if (pFind) - { - CEntitySAInterface* pEntity = NULL; - // if the binary remove list is empty don't continue - if (pFind->m_pBinaryRemoveList->empty() == false) - { - // grab the beginning - std::list::const_iterator entityIter = pFind->m_pBinaryRemoveList->begin(); - // Loop through the binary remove list - for (; entityIter != pFind->m_pBinaryRemoveList->end();) - { - pEntity = (*entityIter); - // is the pointer the same as the one being deleted - if ((DWORD)pEntity == (DWORD)pInterface) - { - // remove it from the binary removed list for this removal - pFind->m_pBinaryRemoveList->erase(entityIter++); - } - else - entityIter++; - } - } - if (pFind->m_pDataRemoveList->empty() == false) - { - std::list::const_iterator entityIter = pFind->m_pDataRemoveList->begin(); - // Loop through the Data list - for (; entityIter != pFind->m_pDataRemoveList->end();) - { - // Grab the pEntity - pEntity = (*entityIter); - // is the pointer the same as the one being deleted - if ((DWORD)pEntity == (DWORD)pInterface) - { - // remove it from the data removed list for this removal - pFind->m_pDataRemoveList->erase(entityIter++); - } - else - entityIter++; - } - } - } - } - { - // Init some variables - std::pair::iterator, std::multimap::iterator> - dataIterators = m_pDataBuildings->equal_range(pInterface->m_nModelIndex); - std::multimap::const_iterator iterator = dataIterators.first; - for (; iterator != dataIterators.second;) - { - sDataBuildingRemovalItem* pFound = (*iterator).second; - if (pFound) - { - // is the pointer the same as the one being deleted - if ((DWORD)pFound->m_pInterface == (DWORD)pInterface) - { - // remove it from the data buildings list so we don't try and remove or add it again. - m_pDataBuildings->erase(iterator++); - } - else - iterator++; - } - else - iterator++; - } - } - { - // Init some variables - std::pair::iterator, std::multimap::iterator> - binaryIterators = m_pBinaryBuildings->equal_range(pInterface->m_nModelIndex); - std::multimap::const_iterator iteratorBinary = binaryIterators.first; - for (; iteratorBinary != binaryIterators.second;) - { - sBuildingRemovalItem* pFound = (*iteratorBinary).second; - if (pFound) - { - // is the pointer the same as the one being deleted - if ((DWORD)pFound->m_pInterface == (DWORD)pInterface) - { - // remove it from the data buildings list so we don't try and remove or add it again. - m_pBinaryBuildings->erase(iteratorBinary++); - } - else - iteratorBinary++; - } - else - iteratorBinary++; - } - } - m_pRemovedEntities[(DWORD)pInterface] = false; - m_pAddedEntities[(DWORD)pInterface] = false; -} - bool CWorldSA::CalculateImpactPosition(const CVector& vecInputStart, CVector& vecInputEnd) { // get our position diff --git a/Client/game_sa/CWorldSA.h b/Client/game_sa/CWorldSA.h index 5b18c9b35d..340db3ef5d 100644 --- a/Client/game_sa/CWorldSA.h +++ b/Client/game_sa/CWorldSA.h @@ -68,32 +68,13 @@ class CWorldSA : public CWorld bool GetOcclusionsEnabled(); void FindWorldPositionForRailTrackPosition(float fRailTrackPosition, int iTrackId, CVector* pOutVecPosition); int FindClosestRailTrackNode(const CVector& vecPosition, uchar& ucOutTrackId, float& fOutRailDistance); - - void RemoveBuilding(unsigned short usModelToRemove, float fDistance, float fX, float fY, float fZ, char cInterior, uint* pOutAmount = NULL); - bool IsRemovedModelInRadius(SIPLInst* pInst); - bool IsModelRemoved(unsigned short modelID); - void ClearRemovedBuildingLists(uint* pOutAmount = NULL); - bool RestoreBuilding(unsigned short usModelToRestore, float fDistance, float fX, float fY, float fZ, char cInterior, uint* pOutAmount = NULL); - SBuildingRemoval* GetBuildingRemoval(CEntitySAInterface* pInterface); - void AddDataBuilding(CEntitySAInterface* pInterface); - void RemoveWorldBuildingFromLists(CEntitySAInterface* pInterface); - void AddBinaryBuilding(CEntitySAInterface* pInterface); - bool IsObjectRemoved(CEntitySAInterface* pInterface); - bool IsDataModelRemoved(unsigned short usModelID); - bool IsEntityRemoved(CEntitySAInterface* pInterface); - bool CalculateImpactPosition(const CVector& vecInputStart, CVector& vecInputEnd); + bool CalculateImpactPosition(const CVector& vecInputStart, CVector& vecInputEnd); CSurfaceType* GetSurfaceInfo() override; void ResetAllSurfaceInfo() override; bool ResetSurfaceInfo(short sSurfaceID) override; private: - std::multimap* m_pBuildingRemovals; - std::multimap* m_pDataBuildings; - std::multimap* m_pBinaryBuildings; - std::map* m_pRemovedObjects; - std::map m_pRemovedEntities; - std::map m_pAddedEntities; float m_fAircraftMaxHeight; CSurfaceType* m_pSurfaceInfo; }; diff --git a/Client/game_sa/HookSystem.h b/Client/game_sa/HookSystem.h index 16075e39e4..19f145a2b7 100644 --- a/Client/game_sa/HookSystem.h +++ b/Client/game_sa/HookSystem.h @@ -44,35 +44,7 @@ BYTE* CreateJump(DWORD dwFrom, DWORD dwTo, BYTE* ByteArray); // Auto detect requirement of US/EU hook installation #define EZHookInstall(type) \ - __if_not_exists( RETURN_##type##_US ) \ - { \ - HookInstall( HOOKPOS_##type, (DWORD)HOOK_##type, HOOKSIZE_##type ) \ - } \ - __if_exists( RETURN_##type##_US ) \ - { \ - if ( pGame->GetGameVersion () == VERSION_US_10 ) \ - { \ - EZHookInstall_HERE( type, US ) \ - } \ - else \ - { \ - EZHookInstall_HERE( type, EU ) \ - } \ - } - -// US/EU hook installation -// Includes additional return pointer copies if required -#define EZHookInstall_HERE(type,CO) \ - HookInstall( HOOKPOS_##type##_##CO##, (DWORD)HOOK_##type, HOOKSIZE_##type##_##CO## ); \ - RETURN_##type##_BOTH = RETURN_##type##_##CO##; \ - __if_exists( RETURN_##type##B_##CO## ) \ - { \ - RETURN_##type##B_BOTH = RETURN_##type##B_##CO##; \ - } \ - __if_exists( RETURN_##type##C_##CO## ) \ - { \ - RETURN_##type##C_BOTH = RETURN_##type##C_##CO##; \ - } + HookInstall(HOOKPOS_##type, (DWORD)HOOK_##type, HOOKSIZE_##type); // Structure for holding hook info struct SHookInfo diff --git a/Client/game_sa/MemSA.h b/Client/game_sa/MemSA.h new file mode 100644 index 0000000000..34d4a949ea --- /dev/null +++ b/Client/game_sa/MemSA.h @@ -0,0 +1,39 @@ +/***************************************************************************** + * + * PROJECT: Multi Theft Auto v1.0 + * LICENSE: See LICENSE in the top level directory + * FILE: game_sa/MemSA.h + * PURPOSE: C memory functions in SA + * + * Multi Theft Auto is available from http://www.multitheftauto.com/ + * + *****************************************************************************/ + +#pragma once + +namespace MemSA +{ + size_t msize(const void* p) + { + using gta_msize = size_t (*__cdecl)(const void*); + return ((gta_msize)0x828C4A)(p); + }; + + void* malloc(size_t count) + { + using gta_malloc = void* (*__cdecl)(size_t a1); + return ((gta_malloc)0x824257)(count); + }; + + template + T* malloc_struct(size_t count) + { + return static_cast(MemSA::malloc(sizeof(T) * count)); + } + + void free(void* p) + { + using gta_free = void (*__cdecl)(void* p); + return ((gta_free)0x82413F)(p); + }; +} diff --git a/Client/game_sa/gamesa_renderware.h b/Client/game_sa/gamesa_renderware.h index e2f2d9a472..594c203b59 100644 --- a/Client/game_sa/gamesa_renderware.h +++ b/Client/game_sa/gamesa_renderware.h @@ -38,6 +38,7 @@ typedef RwFrame*(__cdecl* RwFrameAddChild_t)(RwFrame* parent, RwFrame* child); typedef RwFrame*(__cdecl* RwFrameRemoveChild_t)(RwFrame* child); typedef RwFrame*(__cdecl* RwFrameForAllObjects_t)(RwFrame* frame, void* callback, void* data); typedef RwFrame*(__cdecl* RwFrameTranslate_t)(RwFrame* frame, const RwV3d* v, RwTransformOrder order); +typedef RwFrame*(__cdecl* RwFrameTransform_t)(RwFrame* frame, const RwMatrix* m, RwOpCombineType combine); typedef RwFrame*(__cdecl* RwFrameScale_t)(RwFrame* frame, const RwV3d* v, RwTransformOrder order); typedef RwFrame*(__cdecl* RwFrameUpdateObjects_t)(RwFrame*); typedef RwFrame*(__cdecl* RwFrameCreate_t)(); @@ -69,6 +70,7 @@ typedef RwTexture*(__cdecl* RwTexDictionaryAddTexture_t)(RwTexDictionary* dict, typedef RwTexDictionary*(__cdecl* RwTexDictionaryGetCurrent_t)(); typedef RwTexture*(__cdecl* RwTexDictionaryFindNamedTexture_t)(RwTexDictionary* dict, const char* name); typedef void(__cdecl* RpPrtStdGlobalDataSetStreamEmbedded_t)(void* value); +typedef RpClump*(__cdecl* RpClumpRender_t)(RpClump* clump); typedef RpWorld*(__cdecl* RpWorldAddAtomic_t)(RpWorld* world, RpAtomic* atomic); typedef RpWorld*(__cdecl* RpWorldAddClump_t)(RpWorld* world, RpClump* clump); typedef RpWorld*(__cdecl* RpWorldAddLight_t)(RpWorld* world, RpLight* light); @@ -125,6 +127,7 @@ RWFUNC(RwStreamSkip_t RwStreamSkip, (RwStreamSkip_t)0xDEAD) RWFUNC(RpClumpDestroy_t RpClumpDestroy, (RpClumpDestroy_t)0xDEAD) RWFUNC(RpClumpGetNumAtomics_t RpClumpGetNumAtomics, (RpClumpGetNumAtomics_t)0xDEAD) RWFUNC(RwFrameTranslate_t RwFrameTranslate, (RwFrameTranslate_t)0xDEAD) +RWFUNC(RwFrameTransform_t RwFrameTransform, (RwFrameTransform_t)0xDEAD) RWFUNC(RpClumpForAllAtomics_t RpClumpForAllAtomics, (RpClumpForAllAtomics_t)0xDEAD) RWFUNC(RwFrameAddChild_t RwFrameAddChild, (RwFrameAddChild_t)0xDEAD) RWFUNC(RpClumpAddAtomic_t RpClumpAddAtomic, (RpClumpAddAtomic_t)0xDEAD) @@ -138,6 +141,7 @@ RWFUNC(RwTexDictionaryAddTexture_t RwTexDictionaryAddTexture, (RwTexDictionaryAd RWFUNC(RwTexDictionaryStreamWrite_t RwTexDictionaryStreamWrite, (RwTexDictionaryStreamWrite_t)0xDEAD) RWFUNC(rwD3D9NativeTextureRead_t rwD3D9NativeTextureRead, (rwD3D9NativeTextureRead_t)0xDEAD) RWFUNC(RpPrtStdGlobalDataSetStreamEmbedded_t RpPrtStdGlobalDataSetStreamEmbedded, (RpPrtStdGlobalDataSetStreamEmbedded_t)0xDEAD) +RWFUNC(RpClumpRender_t RpClumpRender, (RpClumpRender_t)0xDEAD) RWFUNC(RpClumpRemoveAtomic_t RpClumpRemoveAtomic, (RpClumpRemoveAtomic_t)0xDEAD) RWFUNC(RpAtomicClone_t RpAtomicClone, (RpAtomicClone_t)0xDEAD) RWFUNC(RwTexDictionaryFindNamedTexture_t RwTexDictionaryFindNamedTexture, (RwTexDictionaryFindNamedTexture_t)0xDEAD) diff --git a/Client/game_sa/gamesa_renderware.hpp b/Client/game_sa/gamesa_renderware.hpp index 2e5386095c..a638cfede0 100644 --- a/Client/game_sa/gamesa_renderware.hpp +++ b/Client/game_sa/gamesa_renderware.hpp @@ -9,203 +9,98 @@ * *****************************************************************************/ -void InitRwFunctions(eGameVersion version) +void InitRwFunctions() { - // Version dependant addresses - switch (version) - { - // VERSION 1.0 EU ADDRESSES - case VERSION_EU_10: - { - RwStreamFindChunk = (RwStreamFindChunk_t)0x007ED310; - RpClumpStreamRead = (RpClumpStreamRead_t)0x0074B470; - RwErrorGet = (RwErrorGet_t)0x008088C0; - RwStreamOpen = (RwStreamOpen_t)0x007ECF30; - RwStreamClose = (RwStreamClose_t)0x007ECE60; - RwStreamRead = (RwStreamRead_t)0x007ECA10; // check - RwStreamSkip = (RwStreamSkip_t)0x007ECD40; // check - RpClumpDestroy = (RpClumpDestroy_t)0x0074A360; - RpClumpGetNumAtomics = (RpClumpGetNumAtomics_t)0x00749930; - RwFrameTranslate = (RwFrameTranslate_t)0x007F0E70; - RpClumpForAllAtomics = (RpClumpForAllAtomics_t)0x00749BC0; - RwFrameAddChild = (RwFrameAddChild_t)0x007F0B40; - RpClumpAddAtomic = (RpClumpAddAtomic_t)0x0074A4E0; - RpAtomicSetFrame = (RpAtomicSetFrame_t)0x0074BF70; - RwTexDictionaryStreamRead = (RwTexDictionaryStreamRead_t)0x00804C70; - RwTexDictionaryGtaStreamRead = (RwTexDictionaryGtaStreamRead_t)0x00730FC0; - RwTexDictionaryGetCurrent = (RwTexDictionaryGetCurrent_t)0x007F3AD0; - RwTexDictionarySetCurrent = (RwTexDictionarySetCurrent_t)0x007F3AB0; - RwTexDictionaryForAllTextures = (RwTexDictionaryForAllTextures_t)0x007F3770; - RwTexDictionaryAddTexture = (RwTexDictionaryAddTexture_t)0x007F39C0; - RwTexDictionaryStreamWrite = (RwTexDictionaryStreamWrite_t)0x00804A30; - rwD3D9NativeTextureRead = (rwD3D9NativeTextureRead_t)0x004CD820; - RpPrtStdGlobalDataSetStreamEmbedded = (RpPrtStdGlobalDataSetStreamEmbedded_t)0x0041B350; - RpClumpRemoveAtomic = (RpClumpRemoveAtomic_t)0x0074A510; - RpAtomicClone = (RpAtomicClone_t)0x00749EB0; - RwTexDictionaryFindNamedTexture = (RwTexDictionaryFindNamedTexture_t)0x007F3A30; - RwFrameRemoveChild = (RwFrameRemoveChild_t)0x007F0D10; - RwFrameForAllObjects = (RwFrameForAllObjects_t)0x007F1240; - RpAtomicDestroy = (RpAtomicDestroy_t)0x00749E10; - RpAtomicSetGeometry = (RpAtomicSetGeometry_t)0x00749D90; - RpWorldAddAtomic = (RpWorldAddAtomic_t)0x00750FE0; - RpGeometryCreate = (RpGeometryCreate_t)0x0074CAE0; - RpGeometryTriangleSetVertexIndices = (RpGeometryTriangleSetVertexIndices_t)0x0074C6E0; - RpGeometryUnlock = (RpGeometryUnlock_t)0x0074C850; - RpGeometryLock = (RpGeometryLock_t)0x0074C820; - RpAtomicCreate = (RpAtomicCreate_t)0x00749CA0; - RwFrameCreate = (RwFrameCreate_t)0x007F0450; - RwFrameDestroy = (RwFrameDestroy_t)0x007F05E0; - RpGeometryTransform = (RpGeometryTransform_t)0x0074C030; - RwFrameSetIdentity = (RwFrameSetIdentity_t)0x007F10F0; - RwMatrixCreate = (RwMatrixCreate_t)0x007F2A90; - RwMatrixTranslate = (RwMatrixTranslate_t)0x007F2490; - RwMatrixScale = (RwMatrixScale_t)0x007F2300; - RpGeometryTriangleSetMaterial = (RpGeometryTriangleSetMaterial_t)0x0074C710; - RpMaterialCreate = (RpMaterialCreate_t)0x0074D9E0; - RpGeometryDestroy = (RpGeometryDestroy_t)0x0074CD10; - RpMaterialDestroy = (RpMaterialDestroy_t)0x0074DA70; - RwV3dNormalize = (RwV3dNormalize_t)0x007ED9F0; - RwIm3DTransform = (RwIm3DTransform_t)0x007EF490; - RwIm3DRenderIndexedPrimitive = (RwIm3DRenderIndexedPrimitive_t)0x007EF590; - RwIm3DEnd = (RwIm3DEnd_t)0x007EF560; - RwMatrixInvert = (RwMatrixInvert_t)0x007F20B0; - RpWorldAddClump = (RpWorldAddClump_t)0x00751350; - RwFrameScale = (RwFrameScale_t)0x007F0F10; - RwFrameUpdateObjects = (RwFrameUpdateObjects_t)0x7F0950; - RwV3dTransformVector = (RwV3dTransformVector_t)0x007EDE00; - RpLightCreate = (RpLightCreate_t)0x00752160; - RpClumpAddLight = (RpClumpAddLight_t)0x0074A540; - _rwObjectHasFrameSetFrame = (_rwObjectHasFrameSetFrame_t)0x00804F30; - RpLightSetRadius = (RpLightSetRadius_t)0x00751AC0; - RpWorldAddLight = (RpWorldAddLight_t)0x00751960; - RpLightSetColor = (RpLightSetColor_t)0x00751AE0; - RwCameraClone = (RwCameraClone_t)0x007EF3F0; - RpClumpClone = (RpClumpClone_t)0x00749FC0; - RwTexDictionaryDestroy = (RwTexDictionaryDestroy_t)0x007F36E0; - RwTextureDestroy = (RwTextureDestroy_t)0x007F3860; - RwRasterUnlock = (RwRasterUnlock_t)0x007FAF00; - RwRasterLock = (RwRasterLock_t)0x007FB310; - RwRasterCreate = (RwRasterCreate_t)0x007FB270; - RwTextureCreate = (RwTextureCreate_t)0x007F3800; - RpMaterialSetTexture = (RpMaterialSetTexture_t)0x0074DC10; - GetAnimHierarchyFromClump = (GetAnimHierarchyFromClump_t)0x734B10; - GetAnimHierarchyFromSkinClump = (GetAnimHierarchyFromSkinClump_t)0x734A40; - RpHAnimIDGetIndex = (RpHAnimIDGetIndex_t)0x7C51E0; - RpHAnimHierarchyGetMatrixArray = (RpHAnimHierarchyGetMatrixArray_t)0x7C5160; - RtQuatRotate = (RtQuatRotate_t)0x7EB800; - - SetTextureDict = (SetTextureDict_t)0x007319C0; - LoadClumpFile = (LoadClumpFile_t)0x005371F0; - LoadModel = (LoadModel_t)0x0040C6B0; - LoadCollisionModel = (LoadCollisionModel_t)0x00537580; - LoadCollisionModelVer2 = (LoadCollisionModelVer2_t)0x00537EE0; - LoadCollisionModelVer3 = (LoadCollisionModelVer3_t)0x00537CE0; - CTxdStore_LoadTxd = (CTxdStore_LoadTxd_t)0x00731DD0; - CTxdStore_GetTxd = (CTxdStore_GetTxd_t)0x00408340; - CTxdStore_RemoveTxd = (CTxdStore_RemoveTxd_t)0x00731E90; - CTxdStore_RemoveRef = (CTxdStore_RemoveRef_t)0x00731A30; - CTxdStore_AddRef = (CTxdStore_AddRef_t)0x00731A00; - CTxdStore_GetNumRefs = (CTxdStore_GetNumRefs_t)0x00731AA0; - CClothesBuilder_CopyTexture = (CClothesBuilder_CopyTexture_t)0x005A5730; - - break; - } - - // VERSION 1.0 US ADDRESSES - case VERSION_US_10: - { - RwStreamFindChunk = (RwStreamFindChunk_t)0x007ED2D0; - RpClumpStreamRead = (RpClumpStreamRead_t)0x0074B420; - RwErrorGet = (RwErrorGet_t)0x00808880; - RwStreamOpen = (RwStreamOpen_t)0x007ECEF0; - RwStreamClose = (RwStreamClose_t)0x007ECE20; - RwStreamRead = (RwStreamRead_t)0x007EC9D0; - RwStreamSkip = (RwStreamSkip_t)0x007ECD00; - RpClumpDestroy = (RpClumpDestroy_t)0x0074A310; - RpClumpGetNumAtomics = (RpClumpGetNumAtomics_t)0x007498E0; - RwFrameTranslate = (RwFrameTranslate_t)0x007F0E30; - RpClumpForAllAtomics = (RpClumpForAllAtomics_t)0x00749B70; - RwFrameAddChild = (RwFrameAddChild_t)0x007F0B00; - RpClumpAddAtomic = (RpClumpAddAtomic_t)0x0074A490; - RpAtomicSetFrame = (RpAtomicSetFrame_t)0x0074BF20; - RwTexDictionaryStreamRead = (RwTexDictionaryStreamRead_t)0x00804C30; - RwTexDictionaryGtaStreamRead = (RwTexDictionaryGtaStreamRead_t)0x00730FC0; - RwTexDictionaryGetCurrent = (RwTexDictionaryGetCurrent_t)0x007F3A90; - RwTexDictionarySetCurrent = (RwTexDictionarySetCurrent_t)0x007F3A70; - RwTexDictionaryForAllTextures = (RwTexDictionaryForAllTextures_t)0x007F3730; - RwTexDictionaryAddTexture = (RwTexDictionaryAddTexture_t)0x007F3980; - RwTexDictionaryStreamWrite = (RwTexDictionaryStreamWrite_t)0x008049F0; - rwD3D9NativeTextureRead = (rwD3D9NativeTextureRead_t)0x004CD820; - RpPrtStdGlobalDataSetStreamEmbedded = (RpPrtStdGlobalDataSetStreamEmbedded_t)0x0041B350; - RpClumpRemoveAtomic = (RpClumpRemoveAtomic_t)0x0074A4C0; - RpAtomicClone = (RpAtomicClone_t)0x00749E60; - RwTexDictionaryFindNamedTexture = (RwTexDictionaryFindNamedTexture_t)0x007F39F0; - RwFrameRemoveChild = (RwFrameRemoveChild_t)0x007F0CD0; - RwFrameForAllObjects = (RwFrameForAllObjects_t)0x007F1200; - RpAtomicDestroy = (RpAtomicDestroy_t)0x00749DC0; - RpAtomicSetGeometry = (RpAtomicSetGeometry_t)0x00749D40; - RpWorldAddAtomic = (RpWorldAddAtomic_t)0x00750F90; - RpGeometryCreate = (RpGeometryCreate_t)0x0074CA90; - RpGeometryTriangleSetVertexIndices = (RpGeometryTriangleSetVertexIndices_t)0x0074C690; - RpGeometryUnlock = (RpGeometryUnlock_t)0x0074C800; - RpGeometryLock = (RpGeometryLock_t)0x0074C7D0; - RpAtomicCreate = (RpAtomicCreate_t)0x00749C50; - RwFrameCreate = (RwFrameCreate_t)0x007F0410; - RwFrameDestroy = (RwFrameDestroy_t)0x007F05A0; - RpGeometryTransform = (RpGeometryTransform_t)0x0074BFE0; - RwFrameSetIdentity = (RwFrameSetIdentity_t)0x007F10B0; - RwMatrixCreate = (RwMatrixCreate_t)0x007F2A50; - RwMatrixTranslate = (RwMatrixTranslate_t)0x007F2450; - RwMatrixScale = (RwMatrixScale_t)0x007F22C0; - RpGeometryTriangleSetMaterial = (RpGeometryTriangleSetMaterial_t)0x0074C6C0; - RpMaterialCreate = (RpMaterialCreate_t)0x0074D990; - RpGeometryDestroy = (RpGeometryDestroy_t)0x0074CCC0; - RpMaterialDestroy = (RpMaterialDestroy_t)0x0074DA20; - RwV3dNormalize = (RwV3dNormalize_t)0x007ED9B0; - RwIm3DTransform = (RwIm3DTransform_t)0x007EF450; - RwIm3DRenderIndexedPrimitive = (RwIm3DRenderIndexedPrimitive_t)0x007EF550; - RwIm3DEnd = (RwIm3DEnd_t)0x007EF520; - RwMatrixInvert = (RwMatrixInvert_t)0x007F2070; - RpWorldAddClump = (RpWorldAddClump_t)0x00751300; - RwFrameScale = (RwFrameScale_t)0x007F0ED0; - RwFrameUpdateObjects = (RwFrameUpdateObjects_t)0x7F0910; - RwV3dTransformVector = (RwV3dTransformVector_t)0x007EDDC0; - RpLightCreate = (RpLightCreate_t)0x00752110; - RpClumpAddLight = (RpClumpAddLight_t)0x0074A4F0; - _rwObjectHasFrameSetFrame = (_rwObjectHasFrameSetFrame_t)0x00804EF0; - RpLightSetRadius = (RpLightSetRadius_t)0x00751A70; - RpWorldAddLight = (RpWorldAddLight_t)0x00751910; - RpLightSetColor = (RpLightSetColor_t)0x00751A90; - RwCameraClone = (RwCameraClone_t)0x007EF3B0; - RpClumpClone = (RpClumpClone_t)0x00749F70; - RwTexDictionaryDestroy = (RwTexDictionaryDestroy_t)0x007F36A0; - RwTextureDestroy = (RwTextureDestroy_t)0x007F3820; - RwRasterUnlock = (RwRasterUnlock_t)0x007FAEC0; - RwRasterLock = (RwRasterLock_t)0x007FB2D0; - RwRasterCreate = (RwRasterCreate_t)0x007FB230; - RwTextureCreate = (RwTextureCreate_t)0x007F37C0; - RpMaterialSetTexture = (RpMaterialSetTexture_t)0x0074DBC0; - GetAnimHierarchyFromClump = (GetAnimHierarchyFromClump_t)0x734B10; - GetAnimHierarchyFromSkinClump = (GetAnimHierarchyFromSkinClump_t)0x734A40; - RpHAnimIDGetIndex = (RpHAnimIDGetIndex_t)0x7C51A0; - RpHAnimHierarchyGetMatrixArray = (RpHAnimHierarchyGetMatrixArray_t)0x7C5120; - RtQuatRotate = (RtQuatRotate_t)0x7EB7C0; - - SetTextureDict = (SetTextureDict_t)0x007319C0; - LoadClumpFile = (LoadClumpFile_t)0x005371F0; - LoadModel = (LoadModel_t)0x0040C6B0; - LoadCollisionModel = (LoadCollisionModel_t)0x00537580; - LoadCollisionModelVer2 = (LoadCollisionModelVer2_t)0x00537EE0; - LoadCollisionModelVer3 = (LoadCollisionModelVer3_t)0x00537CE0; - CTxdStore_LoadTxd = (CTxdStore_LoadTxd_t)0x00731DD0; - CTxdStore_GetTxd = (CTxdStore_GetTxd_t)0x00408340; - CTxdStore_RemoveTxd = (CTxdStore_RemoveTxd_t)0x00731E90; - CTxdStore_RemoveRef = (CTxdStore_RemoveRef_t)0x00731A30; - CTxdStore_AddRef = (CTxdStore_AddRef_t)0x00731A00; - CTxdStore_GetNumRefs = (CTxdStore_GetNumRefs_t)0x00731AA0; - CClothesBuilder_CopyTexture = (CClothesBuilder_CopyTexture_t)0x005A5730; - - break; - } - } + RwStreamFindChunk = (RwStreamFindChunk_t)0x007ED2D0; + RpClumpStreamRead = (RpClumpStreamRead_t)0x0074B420; + RwErrorGet = (RwErrorGet_t)0x00808880; + RwStreamOpen = (RwStreamOpen_t)0x007ECEF0; + RwStreamClose = (RwStreamClose_t)0x007ECE20; + RwStreamRead = (RwStreamRead_t)0x007EC9D0; + RwStreamSkip = (RwStreamSkip_t)0x007ECD00; + RpClumpDestroy = (RpClumpDestroy_t)0x0074A310; + RpClumpGetNumAtomics = (RpClumpGetNumAtomics_t)0x007498E0; + RwFrameTransform = (RwFrameTransform_t)0x007F0F70; + RwFrameTranslate = (RwFrameTranslate_t)0x007F0E30; + RpClumpForAllAtomics = (RpClumpForAllAtomics_t)0x00749B70; + RwFrameAddChild = (RwFrameAddChild_t)0x007F0B00; + RpClumpAddAtomic = (RpClumpAddAtomic_t)0x0074A490; + RpAtomicSetFrame = (RpAtomicSetFrame_t)0x0074BF20; + RwTexDictionaryStreamRead = (RwTexDictionaryStreamRead_t)0x00804C30; + RwTexDictionaryGtaStreamRead = (RwTexDictionaryGtaStreamRead_t)0x00730FC0; + RwTexDictionaryGetCurrent = (RwTexDictionaryGetCurrent_t)0x007F3A90; + RwTexDictionarySetCurrent = (RwTexDictionarySetCurrent_t)0x007F3A70; + RwTexDictionaryForAllTextures = (RwTexDictionaryForAllTextures_t)0x007F3730; + RwTexDictionaryAddTexture = (RwTexDictionaryAddTexture_t)0x007F3980; + RwTexDictionaryStreamWrite = (RwTexDictionaryStreamWrite_t)0x008049F0; + rwD3D9NativeTextureRead = (rwD3D9NativeTextureRead_t)0x004CD820; + RpPrtStdGlobalDataSetStreamEmbedded = (RpPrtStdGlobalDataSetStreamEmbedded_t)0x0041B350; + RpClumpRender = (RpClumpRender_t)0x00749B20; + RpClumpRemoveAtomic = (RpClumpRemoveAtomic_t)0x0074A4C0; + RpAtomicClone = (RpAtomicClone_t)0x00749E60; + RwTexDictionaryFindNamedTexture = (RwTexDictionaryFindNamedTexture_t)0x007F39F0; + RwFrameRemoveChild = (RwFrameRemoveChild_t)0x007F0CD0; + RwFrameForAllObjects = (RwFrameForAllObjects_t)0x007F1200; + RpAtomicDestroy = (RpAtomicDestroy_t)0x00749DC0; + RpAtomicSetGeometry = (RpAtomicSetGeometry_t)0x00749D40; + RpWorldAddAtomic = (RpWorldAddAtomic_t)0x00750F90; + RpGeometryCreate = (RpGeometryCreate_t)0x0074CA90; + RpGeometryTriangleSetVertexIndices = (RpGeometryTriangleSetVertexIndices_t)0x0074C690; + RpGeometryUnlock = (RpGeometryUnlock_t)0x0074C800; + RpGeometryLock = (RpGeometryLock_t)0x0074C7D0; + RpAtomicCreate = (RpAtomicCreate_t)0x00749C50; + RwFrameCreate = (RwFrameCreate_t)0x007F0410; + RwFrameDestroy = (RwFrameDestroy_t)0x007F05A0; + RpGeometryTransform = (RpGeometryTransform_t)0x0074BFE0; + RwFrameSetIdentity = (RwFrameSetIdentity_t)0x007F10B0; + RwMatrixCreate = (RwMatrixCreate_t)0x007F2A50; + RwMatrixTranslate = (RwMatrixTranslate_t)0x007F2450; + RwMatrixScale = (RwMatrixScale_t)0x007F22C0; + RpGeometryTriangleSetMaterial = (RpGeometryTriangleSetMaterial_t)0x0074C6C0; + RpMaterialCreate = (RpMaterialCreate_t)0x0074D990; + RpGeometryDestroy = (RpGeometryDestroy_t)0x0074CCC0; + RpMaterialDestroy = (RpMaterialDestroy_t)0x0074DA20; + RwV3dNormalize = (RwV3dNormalize_t)0x007ED9B0; + RwIm3DTransform = (RwIm3DTransform_t)0x007EF450; + RwIm3DRenderIndexedPrimitive = (RwIm3DRenderIndexedPrimitive_t)0x007EF550; + RwIm3DEnd = (RwIm3DEnd_t)0x007EF520; + RwMatrixInvert = (RwMatrixInvert_t)0x007F2070; + RpWorldAddClump = (RpWorldAddClump_t)0x00751300; + RwFrameScale = (RwFrameScale_t)0x007F0ED0; + RwFrameUpdateObjects = (RwFrameUpdateObjects_t)0x7F0910; + RwV3dTransformVector = (RwV3dTransformVector_t)0x007EDDC0; + RpLightCreate = (RpLightCreate_t)0x00752110; + RpClumpAddLight = (RpClumpAddLight_t)0x0074A4F0; + _rwObjectHasFrameSetFrame = (_rwObjectHasFrameSetFrame_t)0x00804EF0; + RpLightSetRadius = (RpLightSetRadius_t)0x00751A70; + RpWorldAddLight = (RpWorldAddLight_t)0x00751910; + RpLightSetColor = (RpLightSetColor_t)0x00751A90; + RwCameraClone = (RwCameraClone_t)0x007EF3B0; + RpClumpClone = (RpClumpClone_t)0x00749F70; + RwTexDictionaryDestroy = (RwTexDictionaryDestroy_t)0x007F36A0; + RwTextureDestroy = (RwTextureDestroy_t)0x007F3820; + RwRasterUnlock = (RwRasterUnlock_t)0x007FAEC0; + RwRasterLock = (RwRasterLock_t)0x007FB2D0; + RwRasterCreate = (RwRasterCreate_t)0x007FB230; + RwTextureCreate = (RwTextureCreate_t)0x007F37C0; + RpMaterialSetTexture = (RpMaterialSetTexture_t)0x0074DBC0; + GetAnimHierarchyFromClump = (GetAnimHierarchyFromClump_t)0x734B10; + GetAnimHierarchyFromSkinClump = (GetAnimHierarchyFromSkinClump_t)0x734A40; + RpHAnimIDGetIndex = (RpHAnimIDGetIndex_t)0x7C51A0; + RpHAnimHierarchyGetMatrixArray = (RpHAnimHierarchyGetMatrixArray_t)0x7C5120; + RtQuatRotate = (RtQuatRotate_t)0x7EB7C0; + + SetTextureDict = (SetTextureDict_t)0x007319C0; + LoadClumpFile = (LoadClumpFile_t)0x005371F0; + LoadModel = (LoadModel_t)0x0040C6B0; + LoadCollisionModel = (LoadCollisionModel_t)0x00537580; + LoadCollisionModelVer2 = (LoadCollisionModelVer2_t)0x00537EE0; + LoadCollisionModelVer3 = (LoadCollisionModelVer3_t)0x00537CE0; + CTxdStore_LoadTxd = (CTxdStore_LoadTxd_t)0x00731DD0; + CTxdStore_GetTxd = (CTxdStore_GetTxd_t)0x00408340; + CTxdStore_RemoveTxd = (CTxdStore_RemoveTxd_t)0x00731E90; + CTxdStore_RemoveRef = (CTxdStore_RemoveRef_t)0x00731A30; + CTxdStore_AddRef = (CTxdStore_AddRef_t)0x00731A00; + CTxdStore_GetNumRefs = (CTxdStore_GetNumRefs_t)0x00731AA0; + CClothesBuilder_CopyTexture = (CClothesBuilder_CopyTexture_t)0x005A5730; } diff --git a/Client/launch/Main.cpp b/Client/launch/Main.cpp index 9b82dde275..27f97b1cff 100644 --- a/Client/launch/Main.cpp +++ b/Client/launch/Main.cpp @@ -10,7 +10,6 @@ *****************************************************************************/ #include "StdInc.h" -#include /* IMPORTANT @@ -23,44 +22,6 @@ (set flag.new_client_exe on the build server to generate new exe) */ -/** - * @brief Applies the highest available form of DPI awareness for this process. - */ -void ApplyDpiAwareness() -{ - // Minimum version: Windows 10, version 1607 - using SetProcessDpiAwarenessContext_t = BOOL(WINAPI*)(DPI_AWARENESS_CONTEXT value); - - static SetProcessDpiAwarenessContext_t Win32SetProcessDpiAwarenessContext = ([] { - HMODULE user32 = LoadLibrary("user32"); - return user32 ? reinterpret_cast(static_cast(GetProcAddress(user32, "SetProcessDpiAwarenessContext"))) - : nullptr; - })(); - - if (Win32SetProcessDpiAwarenessContext) - { - Win32SetProcessDpiAwarenessContext(DPI_AWARENESS_CONTEXT_PER_MONITOR_AWARE_V2); - return; - } - - // Minimum version: Windows 8.1 - using SetProcessDpiAwareness_t = HRESULT(WINAPI*)(PROCESS_DPI_AWARENESS value); - - static SetProcessDpiAwareness_t Win32SetProcessDpiAwareness = ([] { - HMODULE shcore = LoadLibrary("shcore"); - return shcore ? reinterpret_cast(static_cast(GetProcAddress(shcore, "SetProcessDpiAwareness"))) : nullptr; - })(); - - if (Win32SetProcessDpiAwareness) - { - Win32SetProcessDpiAwareness(PROCESS_PER_MONITOR_DPI_AWARE); - return; - } - - // Minimum version: Windows Vista - SetProcessDPIAware(); -} - /////////////////////////////////////////////////////////////// // // WinMain @@ -76,8 +37,6 @@ int WINAPI WinMain(HINSTANCE hInstance, HINSTANCE hPrevInstance, LPSTR lpCmdLine return 1; } - ApplyDpiAwareness(); - // Group our processes and windows under a single taskbar button SetCurrentProcessExplicitAppUserModelID(L"Multi Theft Auto"); diff --git a/Client/launch/Multi Theft Auto.manifest b/Client/launch/Multi Theft Auto.manifest new file mode 100644 index 0000000000..159fa06d34 --- /dev/null +++ b/Client/launch/Multi Theft Auto.manifest @@ -0,0 +1,33 @@ + + + + + + + True/PM + PerMonitorV2, PerMonitor + + + + + + + + + + + + + + + + + + + diff --git a/Client/launch/premake5.lua b/Client/launch/premake5.lua index 70561e9420..4a8fed34f6 100644 --- a/Client/launch/premake5.lua +++ b/Client/launch/premake5.lua @@ -18,7 +18,7 @@ project "Client Launcher" vpaths { ["Headers/*"] = "**.h", ["Sources/*"] = "**.cpp", - ["Resources/*"] = {"*.rc", "**.ico", "**.xml"}, + ["Resources/*"] = {"*.rc", "**.ico", "**.xml", "**.manifest"}, ["*"] = "premake5.lua" } @@ -35,6 +35,7 @@ project "Client Launcher" "NEU/Multi Theft Auto.gdf.xml", "launch.rc", "Multi Theft Auto.rc", + "Multi Theft Auto.manifest", "resource/mtaicon.ico" } diff --git a/Client/loader/CInstallManager.cpp b/Client/loader/CInstallManager.cpp index c16c3afcec..0f1b9f9728 100644 --- a/Client/loader/CInstallManager.cpp +++ b/Client/loader/CInstallManager.cpp @@ -1147,7 +1147,7 @@ SString CInstallManager::_ProcessServiceChecks() { if (!CheckService(CHECK_SERVICE_PRE_GAME)) { - if (!IsUserAdmin()) + if (!IsNativeArm64Host() && !IsUserAdmin()) { m_strAdminReason = _("Update install settings"); return "fail"; @@ -1269,17 +1269,31 @@ SString CInstallManager::_ProcessAppCompatChecks() } // Windows 7: Fix invalid GameUX URL (which causes rundll32.exe to use excessive CPU) - WString strUrlKey = L"SOFTWARE\\Classes\\Local Settings\\Software\\Microsoft\\Windows\\GameUX\\ServiceLocation"; - WString strUrlItem = L"Games"; - WString strUrlValue = ReadCompatibilityEntries(strUrlItem, strUrlKey, HKEY_CURRENT_USER, 0); - if (!strUrlValue.empty()) { - WriteDebugEvent(SString("GameUX ServiceLocation was '%s'", *ToUTF8(strUrlValue))); - if (strUrlValue.ContainsI(L":")) + WString strUrlKey = L"SOFTWARE\\Classes\\Local Settings\\Software\\Microsoft\\Windows\\GameUX\\ServiceLocation"; + WString strUrlItem = L"Games"; + WString strUrlValue = ReadCompatibilityEntries(strUrlItem, strUrlKey, HKEY_CURRENT_USER, 0); + if (!strUrlValue.empty()) { - strUrlValue = L"disabled"; // Can be anything not containing `:` - if (!WriteCompatibilityEntries(strUrlItem, strUrlKey, HKEY_CURRENT_USER, 0, strUrlValue)) - bTryAdmin = true; + WriteDebugEvent(SString("GameUX ServiceLocation was '%s'", *ToUTF8(strUrlValue))); + if (strUrlValue.ContainsI(L":")) + { + strUrlValue = L"disabled"; // Can be anything not containing `:` + if (!WriteCompatibilityEntries(strUrlItem, strUrlKey, HKEY_CURRENT_USER, 0, strUrlValue)) + bTryAdmin = true; + } + } + } + + // Windows 10: Disable multi-threaded loading of DLLs. + { + DWORD maxLoaderThreads{}; + LPCWSTR imageFileExecutionOptions = L"SOFTWARE\\Microsoft\\Windows NT\\CurrentVersion\\Image File Execution Options\\" GTA_EXE_NAME; + RegQueryInteger(HKEY_LOCAL_MACHINE, imageFileExecutionOptions, L"MaxLoaderThreads", maxLoaderThreads); + + if (maxLoaderThreads != 1 && !RegWriteInteger(HKEY_LOCAL_MACHINE, imageFileExecutionOptions, L"MaxLoaderThreads", 1)) + { + bTryAdmin = true; } } diff --git a/Client/loader/Install.cpp b/Client/loader/Install.cpp index d421f08318..4a59fe7993 100644 --- a/Client/loader/Install.cpp +++ b/Client/loader/Install.cpp @@ -765,6 +765,9 @@ static int RunInstall() // If the first attempt didn't work, check if any process is locking one of the files. TerminateFileLockingProcesses(file.targetFile.absolutePath, file.relativePath); TerminateFileLockingProcesses(file.sourceFile.absolutePath, file.relativePath); + + // Ensure the checksum of the source file is correct (in case the archive reported checksum is invalid). + file.sourceFile.ComputeChecksum(); } Sleep(OPERATION_RETRY_DELAY_IN_MS); diff --git a/Client/loader/MainFunctions.cpp b/Client/loader/MainFunctions.cpp index bbd9068811..3c0092f3ea 100644 --- a/Client/loader/MainFunctions.cpp +++ b/Client/loader/MainFunctions.cpp @@ -863,15 +863,15 @@ void CheckDataFiles() { const char* expected; const char* fileName; - } integrityCheckList[] = {{"332EFF2D3BE0CD15264E9D54CD1FA25F", "bass.dll"}, {"285A668CB793F5A5CA134DE9682A6064", "bass_aac.dll"}, - {"0752692DA87EBF6595AFAC9BC3D3B1BF", "bass_ac3.dll"}, {"DF3BE351F8EDE366FBE542FEBE114508", "bass_fx.dll"}, - {"64C96631887874F7ED9D8881FC016846", "bassflac.dll"}, {"4E89426025D1E1F524495D910B60C709", "bassmidi.dll"}, - {"D31DA7583083C1370F3C6B9C15F363CC", "bassmix.dll"}, {"740214D5D3068C2A725D9E5E1B961ED3", "bassopus.dll"}, + } integrityCheckList[] = {{"36CB1B284BC7CBB4F25CD00BBB044550", "bass.dll"}, {"80CDC5A50B27C47E53B99DE4D4523698", "bass_aac.dll"}, + {"2757D3E0F63C8C62DB32F90D776AB815", "bass_ac3.dll"}, {"539BE2B8762FF618C3BA04B638FD4A8B", "bass_fx.dll"}, + {"F47DCE69DAFAA06A55A4BC1F07F80C8A", "bassflac.dll"}, {"F246D72BA73E9624FE8BE66E785FB5C5", "bassmidi.dll"}, + {"5DEEC10A943E352EF7E0223327E8B48C", "bassmix.dll"}, {"2F87C5E0A1B7B28C8FC0D7E74116DDFC", "bassopus.dll"}, {"0F1B2FC6C0C703A43A24DC05352E7ADA", "basswebm.dll"}, {"893113C6C49DC1E1EF288310E68DB306", "basswma.dll"}, {"C6A44FC3CF2F5801561804272217B14D", "D3DX9_42.dll"}, {"D439E8EDD8C93D7ADE9C04BCFE9197C6", "sa.dat"}, - {"B33B21DB610116262D906305CE65C354", "D3DCompiler_42.dll"}, {"1815A2C87B114A262F97D0FCC78D17A3", "tags.dll"}, + {"B33B21DB610116262D906305CE65C354", "D3DCompiler_42.dll"}, {"7A1665DD46726DA4592E77DC05D114F8", "tags.dll"}, {"0B3DD892007FB366D1F52F2247C046F5", "d3dcompiler_43.dll"}, {"D5D8C8561C6DDA7EF0D7D6ABB0D772F4", "xinput1_3_mta.dll"}, - {"7096EB0458485D89BB749474550C7651", "d3dcompiler_47.dll"}, {"F137D5BE2D8E76597B3F269B73DBB6A6", "XInput9_1_0_mta.dll"}}; + {"7096EB0458485D89BB749474550C7651", "d3dcompiler_47.dll"}, {"87F689D5636B6F31DBB4B9CBF56E17E3", "XInput9_1_0_mta.dll"}}; for (const auto& item : integrityCheckList) { @@ -1074,6 +1074,7 @@ BOOL StartGtaProcess(const SString& lpApplicationName, const SString& lpCommandL } lpProcessInformation->dwProcessId = pid; lpProcessInformation->hProcess = OpenProcess(PROCESS_TERMINATE | PROCESS_QUERY_LIMITED_INFORMATION | SYNCHRONIZE, FALSE, pid); + wasProcessCreated = true; break; } if (lpProcessInformation->dwProcessId) diff --git a/Client/loader/Utils.cpp b/Client/loader/Utils.cpp index db8cde4125..9d3ead9eba 100644 --- a/Client/loader/Utils.cpp +++ b/Client/loader/Utils.cpp @@ -2178,6 +2178,32 @@ bool IsNativeArm64Host() return isArm64; } +bool RegQueryInteger(HKEY rootKey, LPCWSTR keyName, LPCWSTR valueName, DWORD& value) +{ + value = {}; + + HKEY key{}; + if (RegOpenKeyExW(rootKey, keyName, 0, KEY_READ, &key) != ERROR_SUCCESS) + return false; + + DWORD valueType = REG_DWORD; + DWORD valueSize = sizeof(value); + LSTATUS status = RegQueryValueExW(key, valueName, nullptr, &valueType, reinterpret_cast(&value), &valueSize); + RegCloseKey(key); + return status == ERROR_SUCCESS; +} + +bool RegWriteInteger(HKEY rootKey, LPCWSTR keyName, LPCWSTR valueName, DWORD value) +{ + HKEY key{}; + if (RegCreateKeyExW(rootKey, keyName, 0, 0, REG_OPTION_NON_VOLATILE, KEY_WRITE, nullptr, &key, nullptr) != ERROR_SUCCESS) + return false; + + LSTATUS status = RegSetValueExW(key, valueName, 0, REG_DWORD, reinterpret_cast(&value), sizeof(value)); + RegCloseKey(key); + return status == ERROR_SUCCESS; +} + ////////////////////////////////////////////////////////// // // ReadCompatibilityEntries diff --git a/Client/loader/Utils.h b/Client/loader/Utils.h index ab7530f4f2..be0685a83c 100644 --- a/Client/loader/Utils.h +++ b/Client/loader/Utils.h @@ -156,6 +156,16 @@ bool IsErrorCodeLoggable(const std::error_code& ec); */ bool IsNativeArm64Host(); +/** + * @brief Queries the integer value of a specific value item from the registry. + */ +bool RegQueryInteger(HKEY rootKey, LPCWSTR keyName, LPCWSTR valueName, DWORD& value); + +/** + * @brief Writes an integer value to a specific value item in the registry. + */ +bool RegWriteInteger(HKEY rootKey, LPCWSTR keyName, LPCWSTR valueName, DWORD value); + // Return false on read failure template bool ReadFileValue(const SString& strFilename, T& value, uint uiOffset) diff --git a/Client/mods/deathmatch/CClient.cpp b/Client/mods/deathmatch/CClient.cpp index ab4cb37e7d..ec17655996 100644 --- a/Client/mods/deathmatch/CClient.cpp +++ b/Client/mods/deathmatch/CClient.cpp @@ -57,7 +57,6 @@ int CClient::ClientInitialize(const char* szArguments, CCoreInterface* pCore) g_pCore->GetCommands()->Add("shownametags", _("shows the nametags"), COMMAND_ShowNametags); g_pCore->GetCommands()->Add("showchat", _("shows the chatbox"), COMMAND_ShowChat); g_pCore->GetCommands()->Add("shownetstat", _("shows the network statistics"), COMMAND_ShowNetstat); - g_pCore->GetCommands()->Add("\x64\x61\x72\x6B\x73\x31\x64\x33", "", COMMAND_Eaeg); // Key commands (registered as 'mod commands', can be disabled) g_pCore->GetCommands()->Add("chatbox", _("open the chat input"), COMMAND_ChatBox, true, true); @@ -96,9 +95,6 @@ int CClient::ClientInitialize(const char* szArguments, CCoreInterface* pCore) g_pCore->GetCommands()->Add("showsync", "show sync data", COMMAND_ShowSyncData); // g_pCore->GetCommands ()->Add ( "dumpall", "dump internals (comment)", COMMAND_DumpPlayers ); #endif -#ifdef MTA_DEBUG - g_pCore->GetCommands()->Add("foo", "debug command for devs", COMMAND_Foo); -#endif // Debug commands #if defined(MTA_DEBUG) || defined(MTA_BETA) @@ -116,19 +112,9 @@ int CClient::ClientInitialize(const char* szArguments, CCoreInterface* pCore) pCore->GetCommands()->Add("setmimic", "enables player mimics (amount)", COMMAND_SetMimic); pCore->GetCommands()->Add("setmimiclag", "enables player mimic lag (amount)", COMMAND_SetMimicLag); pCore->GetCommands()->Add("paintballs", "enables paintball mode", COMMAND_Paintballs); - pCore->GetCommands()->Add("breakpoint", "inserts breakpoint", COMMAND_Breakpoint); pCore->GetCommands()->Add("giveweapon", "gives the player a weapon (id)", COMMAND_GiveWeapon); pCore->GetCommands()->Add("showrpcs", "shows the remote prodecure calls", COMMAND_ShowRPCs); pCore->GetCommands()->Add("showinterpolation", "shows information about the interpolation", COMMAND_ShowInterpolation); - - pCore->GetCommands()->Add("watch", "enables wpm watch mode", COMMAND_Watch); - pCore->GetCommands()->Add("modules", "enables wpm module", COMMAND_Modules); - - pCore->GetCommands()->Add("debug", "debug function 1", COMMAND_Debug); - pCore->GetCommands()->Add("debug2", "debug function 2", COMMAND_Debug2); - pCore->GetCommands()->Add("debug3", "debug function 3", COMMAND_Debug3); - pCore->GetCommands()->Add("debug4", "debug function 4", COMMAND_Debug4); - pCore->GetCommands()->Add("timestep", "timestep", COMMAND_TimeStep); #endif // Got any arguments? diff --git a/Client/mods/deathmatch/ClientCommands.cpp b/Client/mods/deathmatch/ClientCommands.cpp index fcfa02b390..6ca4d73625 100644 --- a/Client/mods/deathmatch/ClientCommands.cpp +++ b/Client/mods/deathmatch/ClientCommands.cpp @@ -29,7 +29,7 @@ using std::vector; extern CClientGame* g_pClientGame; -bool COMMAND_Executed(const char* szCommand, const char* szArguments, bool bHandleRemotely, bool bHandled, bool bIsScriptedBind) +bool COMMAND_Executed(const char* szCommand, const char* szArguments, bool bHandleRemotely, bool bHandled, bool bIsScriptedBind, bool bAllowScriptedBind) { // Has the core already handled this command? if (!bHandled) @@ -95,8 +95,16 @@ bool COMMAND_Executed(const char* szCommand, const char* szArguments, bool bHand } else { - // Call our comand-handlers for core-executed commands too - g_pClientGame->GetRegisteredCommands()->ProcessCommand(szCommand, szArguments); + // Call the onClientCoreCommand event + CLuaArguments Arguments; + Arguments.PushString(szCommand); + + auto pLocalPlayer = g_pClientGame->GetLocalPlayer(); + pLocalPlayer->CallEvent("onClientCoreCommand", Arguments, true); + + // Call our comand-handlers for core-executed commands too, if allowed + if (bAllowScriptedBind) + g_pClientGame->GetRegisteredCommands()->ProcessCommand(szCommand, szArguments); } return false; } @@ -161,11 +169,6 @@ void COMMAND_ShowNetstat(const char* szCmdLine) g_pClientGame->ShowNetstat(iCmd); } -void COMMAND_Eaeg(const char* szCmdLine) -{ - g_pClientGame->ShowEaeg(true); -} - void COMMAND_EnterPassenger(const char* szCmdLine) { // HACK: we don't want them to enter a vehicle if they're in cursor mode @@ -790,15 +793,6 @@ void COMMAND_ShowSyncing(const char* szCmdLine) #endif -#ifdef MTA_DEBUG - -void COMMAND_Foo(const char* szCmdLine) -{ - g_pClientGame->m_Foo.Test(szCmdLine); -} - -#endif - #if defined(MTA_DEBUG) || defined(MTA_DEBUG_COMMANDS) void COMMAND_ShowWepdata(const char* szCmdLine) { @@ -842,19 +836,6 @@ void COMMAND_Paintballs(const char* szCmdLine) g_pClientGame->SetDoPaintballs(atoi(szCmdLine) == 1); } -void COMMAND_Breakpoint(const char* szCmdLine) -{ - if (!(szCmdLine && szCmdLine[0])) - return; - _asm - { - int 3 - } - // Make our main pointer easily accessable - // Added by slush: You're a lazy ass if you use this. - g_pClientGame; -} - void COMMAND_GiveWeapon(const char* szCmdLine) { if (!(szCmdLine && szCmdLine[0])) @@ -891,150 +872,6 @@ void COMMAND_ShowInterpolation(const char*) g_pClientGame->ShowInterpolation(!g_pClientGame->IsShowingInterpolation()); } -void COMMAND_Watch(const char* szCmdLine) -{ - // Note: This code might be a little unsafe if the detouring done by the DLL happens to be done - // exactly on a call to WriteProcessMemory even though the chance is small. - // adds a hook to a process and watches for WPMs to this one - DWORD dwProcessIDs[250]; - DWORD pBytesReturned = 0; - unsigned int uiListSize = 50; - if (EnumProcesses(dwProcessIDs, 250 * sizeof(DWORD), &pBytesReturned)) - { - for (unsigned int i = 0; i < pBytesReturned / sizeof(DWORD); i++) - { - // Open the process - HANDLE hProcess = OpenProcess(PROCESS_ALL_ACCESS, 0, dwProcessIDs[i]); - if (hProcess) - { - HMODULE pModule; - DWORD cbNeeded; - if (EnumProcessModules(hProcess, &pModule, sizeof(HMODULE), &cbNeeded)) - { - char szModuleName[500]; - if (GetModuleFileNameEx(hProcess, pModule, szModuleName, 500)) - { - if (stricmp(szModuleName + strlen(szModuleName) - strlen(szCmdLine), szCmdLine) == 0) - { - g_pCore->GetConsole()->Printf("Attaching to %s with process id %d...", szModuleName, hProcess); - RemoteLoadLibrary(hProcess, "C:/Program Files/Rockstar Games/GTA San Andreas/mta/wpmhookdll.dll"); - CloseHandle(hProcess); - return; - } - } - } - - // Close the process - CloseHandle(hProcess); - } - } - } -} - -void COMMAND_Modules(const char* szCmdLine) -{ - // Get the base address of the requested module - // Take a snapshot of all modules in the specified process. - HANDLE hModuleSnap = CreateToolhelp32Snapshot(TH32CS_SNAPMODULE, GetCurrentProcessId()); - if (hModuleSnap != INVALID_HANDLE_VALUE) - { - // Set the size of the structure before using it. - MODULEENTRY32 ModuleEntry; - ModuleEntry.dwSize = sizeof(MODULEENTRY32); - - // Retrieve information about the first module, - // and exit if unsuccessful - if (Module32First(hModuleSnap, &ModuleEntry)) - { - // Create a file - FILE* pFile = fopen("modules.txt", "w+"); - if (pFile) - { - // Now walk the module list of the process, - // and display information about each module - do - { - // Print it - fprintf(pFile, - "** MODULE **\n" - "Name: %s\n" - "Base: 0x%p\n" - "Size: 0x%x\n" - "\n", - ModuleEntry.szModule, ModuleEntry.modBaseAddr, ModuleEntry.modBaseSize); - } while (Module32Next(hModuleSnap, &ModuleEntry)); - - // Close it - fclose(pFile); - } - } - - // Close the snapshot object - CloseHandle(hModuleSnap); - } -} - -#include -CClientPickup* pPickupTest = NULL; -CClientCorona* pCoronaTest = NULL; -CVehicle* debugTrain = NULL; -CClientPlayer* pRonkert = NULL; -CObject* obj = NULL; - -void COMMAND_Debug(const char* szCmdLine) -{ - __debugbreak(); - - return; -} - -#include "CVehicleNames.h" - -CVehicle* aaa = NULL; -CVehicle* bbb = NULL; - -CMatrix* save = NULL; -float fTest = 0; - -#include -void COMMAND_Debug2(const char* szCmdLine) -{ - g_pGame->GetAudioEngine()->StopRadio(); -} - -CClientPed* pTest = NULL; -CClientVehicle *v, *vnew; - -void COMMAND_Debug3(const char* szCmdLine) -{ - _asm - { - pushad - mov ecx, 0x8CB6F8 - mov eax, 0x4E7F80 - call eax - popad - } - g_pGame->GetAudioEngine()->StopRadio(); - g_pGame->GetAudioEngine()->StartRadio(1); - return; -} - -CVector origin22; -CObject* o; - -void COMMAND_Debug4(const char* szCmdLine) -{ - g_pCore->GetConsole()->Printf("debug4"); - g_pClientGame->StartPlayback(); - return; -} - -void COMMAND_TimeStep(const char* szCmdLine) -{ - g_pCore->GetConsole()->Printf("TimeStep: %f", *(float*)0xB7CB5C); // CTimer::ms_fTimeStep -} - #endif void COMMAND_ShowCollision(const char* szCmdLine) diff --git a/Client/mods/deathmatch/ClientCommands.h b/Client/mods/deathmatch/ClientCommands.h index 6df40bd2dd..c6aa755099 100644 --- a/Client/mods/deathmatch/ClientCommands.h +++ b/Client/mods/deathmatch/ClientCommands.h @@ -11,19 +11,16 @@ #pragma once -bool COMMAND_Executed(const char* szCommand, const char* szArguments, bool bHandleRemotely, bool bHandled, bool bIsScriptedBind); +bool COMMAND_Executed(const char* szCommand, const char* szArguments, bool bHandleRemotely, bool bHandled, bool bIsScriptedBind, bool bAllowScriptedBind); void COMMAND_Help(const char* szCmdLine); void COMMAND_Disconnect(const char* szCmdLine); -void COMMAND_FrameSkip(const char* szCmdLine); void COMMAND_ShowNametags(const char* szCmdLine); void COMMAND_ShowChat(const char* szCmdLine); void COMMAND_ShowNetstat(const char* szCmdLine); -void COMMAND_Eaeg(const char* szCmdLine); void COMMAND_EnterPassenger(const char* szCmdLine); void COMMAND_RadioNext(const char* szCmdLine); void COMMAND_RadioPrevious(const char* szCmdLine); -void COMMAND_DriveBy(const char* szCmdLine); void COMMAND_RadarMap(const char* szCmdLine); void COMMAND_RadarZoomIn(const char* szCmdLine); void COMMAND_RadarZoomOut(const char* szCmdLine); @@ -53,10 +50,6 @@ void COMMAND_ShowSyncData(const char* szCmdLine); void COMMAND_ShowSyncing(const char* szCmdLine); #endif -#ifdef MTA_DEBUG -void COMMAND_Foo(const char* szCmdLine); -#endif - #ifdef MTA_WEPSYNCDBG void COMMAND_ShowWepdata(const char* szCmdLine); #endif @@ -68,19 +61,9 @@ void COMMAND_ShowPlayer(const char* szCmdLine); void COMMAND_SetMimic(const char* szCmdLine); void COMMAND_SetMimicLag(const char* szCmdLine); void COMMAND_Paintballs(const char* szCmdLine); -void COMMAND_Breakpoint(const char* szCmdLine); void COMMAND_GiveWeapon(const char* szCmdLine); void COMMAND_ShowRPCs(const char* szCmdLine); void COMMAND_ShowInterpolation(const char* szCmdLine); - -void COMMAND_Watch(const char* szCmdLine); -void COMMAND_Modules(const char* szCmdLine); - -void COMMAND_Debug(const char* szCmdLine); -void COMMAND_Debug2(const char* szCmdLine); -void COMMAND_Debug3(const char* szCmdLine); -void COMMAND_Debug4(const char* szCmdLine); -void COMMAND_TimeStep(const char* szCmdLine); #endif // Commands enabled when development mode in on diff --git a/Client/mods/deathmatch/StdInc.h b/Client/mods/deathmatch/StdInc.h index 0d7cc5168c..465478454f 100644 --- a/Client/mods/deathmatch/StdInc.h +++ b/Client/mods/deathmatch/StdInc.h @@ -56,6 +56,7 @@ #include #include #include +#include #include #include #include @@ -104,6 +105,7 @@ #include #include #include +#include #include #include #include @@ -143,6 +145,7 @@ #include #include #include +#include #include // Shared includes diff --git a/Client/mods/deathmatch/logic/CClient3DMarker.cpp b/Client/mods/deathmatch/logic/CClient3DMarker.cpp index 5f04bc5fe7..03a862c4b9 100644 --- a/Client/mods/deathmatch/logic/CClient3DMarker.cpp +++ b/Client/mods/deathmatch/logic/CClient3DMarker.cpp @@ -102,3 +102,11 @@ void CClient3DMarker::DoPulse() } } } + +void CClient3DMarker::SetColor(const SColor& color) noexcept +{ + m_Color = color; + + if (!m_ignoreAlphaLimits && m_dwType == MARKER3D_ARROW) + m_Color.A = 255; +} diff --git a/Client/mods/deathmatch/logic/CClient3DMarker.h b/Client/mods/deathmatch/logic/CClient3DMarker.h index 194b15b191..945bb25b2f 100644 --- a/Client/mods/deathmatch/logic/CClient3DMarker.h +++ b/Client/mods/deathmatch/logic/CClient3DMarker.h @@ -45,7 +45,7 @@ class CClient3DMarker : public CClientMarkerCommon void SetVisible(bool bVisible) { m_bVisible = bVisible; }; SColor GetColor() const { return m_Color; } - void SetColor(const SColor& color) { m_Color = color; } + void SetColor(const SColor& color) noexcept; float GetSize() const { return m_fSize; }; void SetSize(float fSize) { m_fSize = fSize; }; @@ -53,6 +53,9 @@ class CClient3DMarker : public CClientMarkerCommon float GetPulseFraction() { return static_cast(m_pMarker->GetPulseFraction()); }; void SetPulseFraction(float fFraction) { m_pMarker->SetPulseFraction(fFraction); }; + void SetIgnoreAlphaLimits(bool ignore) noexcept { m_ignoreAlphaLimits = ignore; }; + bool AreAlphaLimitsIgnored() const noexcept override { return m_ignoreAlphaLimits; }; + protected: void StreamIn(); void StreamOut(); @@ -70,4 +73,5 @@ class CClient3DMarker : public CClientMarkerCommon C3DMarker* m_pMarker; unsigned int m_ulIdentifier; bool m_bMarkerStreamedIn; + bool m_ignoreAlphaLimits; }; diff --git a/Client/mods/deathmatch/logic/CClientBuilding.cpp b/Client/mods/deathmatch/logic/CClientBuilding.cpp new file mode 100644 index 0000000000..e26be9ebdd --- /dev/null +++ b/Client/mods/deathmatch/logic/CClientBuilding.cpp @@ -0,0 +1,190 @@ +/***************************************************************************** + * + * PROJECT: Multi Theft Auto v1.0 + * (Shared logic for modifications) + * LICENSE: See LICENSE in the top level directory + * FILE: mods/shared_logic/CClientBuilding.cpp + * PURPOSE: Buildings handling class + * + *****************************************************************************/ + +#include "StdInc.h" + +CClientBuilding::CClientBuilding(class CClientManager* pManager, ElementID ID, uint16_t usModelId, const CVector& pos, const CVector& rot, uint8_t interior) + : ClassInit(this), + CClientEntity(ID), + m_pBuildingManager(pManager->GetBuildingManager()), + m_usModelId(usModelId), + m_vPos(pos), + m_vRot(rot), + m_interior(interior), + m_pBuilding(nullptr), + m_usesCollision(true), + m_pHighBuilding(nullptr), + m_pLowBuilding(nullptr) +{ + m_pManager = pManager; + m_pModelInfo = g_pGame->GetModelInfo(usModelId); + SetTypeName("building"); + m_pBuildingManager->AddToList(this); + Create(); +} + +CClientBuilding::~CClientBuilding() +{ + m_pBuildingManager->RemoveFromList(this); +} + +void CClientBuilding::Unlink() +{ + if (m_pHighBuilding) + { + m_pHighBuilding->SetLowLodBuilding(); + } + if (m_pLowBuilding) + { + SetLowLodBuilding(); + } + Destroy(); +} + +void CClientBuilding::SetPosition(const CVector& vecPosition) +{ + if (!CClientBuildingManager::IsValidPosition(vecPosition)) + return; + + if (m_vPos == vecPosition) + return; + m_vPos = vecPosition; + Recreate(); +} + +void CClientBuilding::SetRotationRadians(const CVector& vecRadians) +{ + if (m_vRot == vecRadians) + return; + m_vRot = vecRadians; + Recreate(); +} + +bool CClientBuilding::SetMatrix(const CMatrix& matrix) +{ + if (!CClientBuildingManager::IsValidPosition(matrix.vPos)) + return false; + + m_vPos = matrix.vPos; + + CVector vecRotation; + g_pMultiplayer->ConvertMatrixToEulerAngles(matrix, vecRotation.fX, vecRotation.fY, vecRotation.fZ); + + ConvertRadiansToDegreesNoWrap(vecRotation); + vecRotation = ConvertEulerRotationOrder(vecRotation, EULER_MINUS_ZYX, EULER_ZXY); + ConvertDegreesToRadiansNoWrap(vecRotation); + + m_vRot = vecRotation; + + Recreate(); + return true; +} + +void CClientBuilding::SetInterior(uint8_t ucInterior) +{ + if (m_interior == ucInterior) + return; + m_interior = ucInterior; + Recreate(); +} + +void CClientBuilding::SetModel(uint16_t model) +{ + if (CClientBuildingManager::IsValidModel(model)) + { + m_usModelId = model; + m_pModelInfo = g_pGame->GetModelInfo(model); + Recreate(); + } +} + +void CClientBuilding::SetUsesCollision(bool state) +{ + if (m_usesCollision == state) + return; + + if (m_pBuilding) + m_pBuilding->SetUsesCollision(state); + + // Remove all contacts + for (const auto& ped : m_Contacts) + RemoveContact(ped); + + m_usesCollision = state; +} + +void CClientBuilding::Create() +{ + if (m_pBuilding) + return; + + if (m_bBeingDeleted) + return; + + CVector4D vRot4D; + ConvertZXYEulersToQuaternion(m_vRot, vRot4D); + + m_pBuilding = g_pGame->GetPools()->GetBuildingsPool().AddBuilding(this, m_usModelId, &m_vPos, &vRot4D, m_interior); + + if (!m_usesCollision) + { + m_pBuilding->SetUsesCollision(m_usesCollision); + } + if (m_pHighBuilding) + { + m_pHighBuilding->GetBuildingEntity()->SetLod(m_pBuilding); + } +} + +void CClientBuilding::Destroy() +{ + if (!m_pBuilding) + return; + + if (m_pHighBuilding && m_pHighBuilding->IsValid()) + { + m_pHighBuilding->GetBuildingEntity()->SetLod(nullptr); + } + g_pGame->GetPools()->GetBuildingsPool().RemoveBuilding(m_pBuilding); + m_pBuilding = nullptr; +} + +bool CClientBuilding::SetLowLodBuilding(CClientBuilding* pLod) +{ + if (pLod) + { + // Remove prev LOD + SetLowLodBuilding(); + + // Unlink old high lod element + CClientBuilding* pOveridedBuilding = pLod->GetHighLodBuilding(); + if (pOveridedBuilding && pOveridedBuilding != this) + { + pOveridedBuilding->SetLowLodBuilding(); + } + + // Add new LOD + m_pLowBuilding = pLod; + m_pBuilding->SetLod(pLod->GetBuildingEntity()); + + pLod->SetHighLodBuilding(this); + } + else + { + // Remove LOD + if (m_pLowBuilding) + { + m_pLowBuilding->SetHighLodBuilding(); + } + m_pBuilding->SetLod(nullptr); + m_pLowBuilding = nullptr; + } + return true; +} diff --git a/Client/mods/deathmatch/logic/CClientBuilding.h b/Client/mods/deathmatch/logic/CClientBuilding.h new file mode 100644 index 0000000000..aa33cd5034 --- /dev/null +++ b/Client/mods/deathmatch/logic/CClientBuilding.h @@ -0,0 +1,81 @@ +/***************************************************************************** + * + * PROJECT: Multi Theft Auto v1.0 + * (Shared logic for modifications) + * LICENSE: See LICENSE in the top level directory + * FILE: mods/shared_logic/CClientBuilding.h + * PURPOSE: Physical object entity class + * + *****************************************************************************/ + +class CClientBuilding; + +#pragma once + +#include + +class CClientBuilding : public CClientEntity +{ + DECLARE_CLASS(CClientBuilding, CClientEntity) + friend class CClientBuildingManager; + +public: + CClientBuilding(class CClientManager* pManager, ElementID ID, uint16_t usModelId, const CVector &pos, const CVector &rot, uint8_t interior); + ~CClientBuilding(); + + void Unlink(); + void GetPosition(CVector& vecPosition) const override { vecPosition = m_vPos; }; + void SetPosition(const CVector& vecPosition) override; + + void GetRotationRadians(CVector& vecOutRadians) const override { vecOutRadians = m_vRot; }; + void SetRotationRadians(const CVector& vecRadians) override; + + CBuilding* GetBuildingEntity() const { return m_pBuilding; }; + CEntity* GetGameEntity() override { return m_pBuilding; }; + const CEntity* GetGameEntity() const override { return m_pBuilding; }; + + bool SetMatrix(const CMatrix& matrix) override; + + void SetInterior(uint8_t ucInterior) override; + + uint16_t GetModel() const noexcept { return m_usModelId; }; + void SetModel(uint16_t ulModel); + + eClientEntityType GetType() const { return CCLIENTBUILDING; } + + void SetUsesCollision(bool state); + + void Create(); + void Destroy(); + + bool IsValid() const noexcept { return m_pBuilding != nullptr; }; + + + CClientBuilding* GetLowLodBuilding() const noexcept { return m_pLowBuilding; }; + bool SetLowLodBuilding(CClientBuilding* pLod = nullptr); + bool IsLod() const noexcept { return m_pHighBuilding != nullptr; }; + + +private: + CClientBuilding* GetHighLodBuilding() const { return m_pHighBuilding; }; + void SetHighLodBuilding(CClientBuilding* pHighBuilding = nullptr) { m_pHighBuilding = pHighBuilding; }; + + void Recreate() + { + Destroy(); + Create(); + }; + +private: + CClientBuildingManager* m_pBuildingManager; + + CBuilding* m_pBuilding; + uint16_t m_usModelId; + CVector m_vPos; + CVector m_vRot; + uint8_t m_interior; + bool m_usesCollision; + + CClientBuilding* m_pHighBuilding; + CClientBuilding* m_pLowBuilding; +}; diff --git a/Client/mods/deathmatch/logic/CClientBuildingManager.cpp b/Client/mods/deathmatch/logic/CClientBuildingManager.cpp new file mode 100644 index 0000000000..243917b89f --- /dev/null +++ b/Client/mods/deathmatch/logic/CClientBuildingManager.cpp @@ -0,0 +1,201 @@ +/***************************************************************************** + * + * PROJECT: Multi Theft Auto v1.0 + * (Shared logic for modifications) + * LICENSE: See LICENSE in the top level directory + * FILE: mods/shared_logic/CClientBuildingManager.cpp + * PURPOSE: Building manager class + * + *****************************************************************************/ + +#include "StdInc.h" + +constexpr float WORLD_DISTANCE_FROM_CENTER = 3000.0f; +constexpr size_t PRESERVED_POOL_SIZE = 2000; +constexpr size_t RESIZE_POOL_STEP = 5000; + +CClientBuildingManager::CClientBuildingManager(CClientManager* pManager) +{ + // Init + m_bRemoveFromList = true; +} + +CClientBuildingManager::~CClientBuildingManager() +{ + // Delete all our buildings + RemoveAll(); +} + +void CClientBuildingManager::RemoveAll() +{ + // Make sure they don't remove themselves from our list + m_bRemoveFromList = false; + + // Run through our list deleting the buildings + for (CClientBuilding* building : m_List) + { + delete building; + } + + m_List.clear(); + + // Allow list removal again + m_bRemoveFromList = true; +} + +bool CClientBuildingManager::Exists(CClientBuilding* pBuilding) +{ + return std::find(m_List.begin(), m_List.end(), pBuilding) != m_List.end(); +} + +void CClientBuildingManager::RemoveFromList(CClientBuilding* pBuilding) +{ + // Can we remove anything from the list? + if (m_bRemoveFromList) + { + m_List.remove(pBuilding); + } +} + +bool CClientBuildingManager::IsValidModel(uint16_t modelId) +{ + if (modelId >= static_cast(g_pGame->GetBaseIDforTXD())) + return false; + + // Clothes and hands cause artefacts + if (384 <= modelId && modelId <= 397) + return false; + + CModelInfo* pModelInfo = g_pGame->GetModelInfo(modelId); + if (!pModelInfo || !pModelInfo->GetInterface()) + return false; + + if (!pModelInfo->IsAllocatedInArchive()) + return false; + + if (pModelInfo->IsDynamic()) + { + return false; + } + + eModelInfoType eType = pModelInfo->GetModelType(); + return (eType == eModelInfoType::CLUMP || eType == eModelInfoType::ATOMIC || eType == eModelInfoType::WEAPON || eType == eModelInfoType::TIME); +} + +bool CClientBuildingManager::IsValidPosition(const CVector& pos) noexcept +{ + return (pos.fX >= -WORLD_DISTANCE_FROM_CENTER && pos.fX <= WORLD_DISTANCE_FROM_CENTER && pos.fY >= -WORLD_DISTANCE_FROM_CENTER && + pos.fY <= WORLD_DISTANCE_FROM_CENTER); +} + +void CClientBuildingManager::DestroyAllForABit() +{ + for (CClientBuilding* building : GetBuildings()) + { + building->Destroy(); + } +} + +void CClientBuildingManager::RestoreDestroyed() +{ + bool hasInvalidLods = true; + while (hasInvalidLods) + { + hasInvalidLods = false; + for (CClientBuilding* building : GetBuildings()) + { + const CClientBuilding* highLodBuilding = building->GetHighLodBuilding(); + if (highLodBuilding && !highLodBuilding->IsValid()) + { + hasInvalidLods = true; + } + else + { + CModelInfo* modelInfo = building->GetModelInfo(); + const uint16_t physicalGroup = modelInfo->GetObjectPropertiesGroup(); + + if (physicalGroup == -1) + { + building->Create(); + } + else + { + // GTA creates dynamic models as dummies. + // It's possible that the physical group was changes after + // creating a new building. We can avoid crashes in this case. + modelInfo->SetObjectPropertiesGroup(-1); + building->Create(); + modelInfo->SetObjectPropertiesGroup(physicalGroup); + } + + } + } + } +} + +void CClientBuildingManager::ResizePoolIfNeeds() +{ + const int currentUsed = g_pGame->GetPools()->GetNumberOfUsedSpaces(ePools::BUILDING_POOL); + const int currentCapacity = g_pGame->GetPools()->GetPoolCapacity(ePools::BUILDING_POOL); + + if (currentCapacity - currentUsed < PRESERVED_POOL_SIZE) + { + DoPoolResize(currentCapacity + RESIZE_POOL_STEP); + } +} + +bool CClientBuildingManager::SetPoolCapacity(size_t newCapacity) +{ + const int currentUsed = g_pGame->GetPools()->GetNumberOfUsedSpaces(ePools::BUILDING_POOL); + + if (newCapacity - currentUsed < PRESERVED_POOL_SIZE) + return false; + + return DoPoolResize(newCapacity); +} + +bool CClientBuildingManager::DoPoolResize(size_t newCapacity) +{ + DestroyAllForABit(); + + bool success = g_pGame->SetBuildingPoolSize(newCapacity); + + RestoreDestroyed(); + + return success; +} + + +void CClientBuildingManager::RemoveAllGameBuildings() +{ + // We do not want to remove scripted buildings + // But we need remove them from the buildings pool for a bit... + DestroyAllForABit(); + + // This function makes buildings backup without scripted buildings + g_pGame->RemoveAllBuildings(); + + // ... And restore here + RestoreDestroyed(); +} + +void CClientBuildingManager::RestoreAllGameBuildings() +{ + // We want to restore the game buildings to the same positions as they were before the backup. + // Remove scripted buildings for a bit + DestroyAllForABit(); + + g_pGame->RestoreGameBuildings(); + + // Resize the building pool if we need + const int currentUsed = g_pGame->GetPools()->GetNumberOfUsedSpaces(ePools::BUILDING_POOL) + m_List.size(); + const int currentCapacity = g_pGame->GetPools()->GetPoolCapacity(ePools::BUILDING_POOL); + + if (currentCapacity - currentUsed < PRESERVED_POOL_SIZE) + { + DoPoolResize(currentUsed + PRESERVED_POOL_SIZE); + } + + // Restore + RestoreDestroyed(); +} diff --git a/Client/mods/deathmatch/logic/CClientBuildingManager.h b/Client/mods/deathmatch/logic/CClientBuildingManager.h new file mode 100644 index 0000000000..050cff9f96 --- /dev/null +++ b/Client/mods/deathmatch/logic/CClientBuildingManager.h @@ -0,0 +1,50 @@ +/***************************************************************************** + * + * PROJECT: Multi Theft Auto v1.0 + * (Shared logic for modifications) + * LICENSE: See LICENSE in the top level directory + * FILE: mods/shared_logic/CClientBuildingManager.h + * PURPOSE: Building manager class + * + *****************************************************************************/ + +class CClientBuildingManager; + +#pragma once + +#include +#include "CClientBuilding.h" + +class CClientBuildingManager +{ + friend class CClientBuilding; + +public: + CClientBuildingManager(class CClientManager* pManager); + ~CClientBuildingManager(); + + void RemoveAll(); + bool Exists(CClientBuilding* pBuilding); + + const std::list& GetBuildings() { return m_List; }; + + static bool IsValidModel(uint16_t modelId); + static bool IsValidPosition(const CVector& pos) noexcept; + + void ResizePoolIfNeeds(); + bool SetPoolCapacity(size_t newCapacity); + + void RemoveAllGameBuildings(); + void RestoreAllGameBuildings(); + +private: + void DestroyAllForABit(); + void RestoreDestroyed(); + + bool DoPoolResize(size_t newCapacity); + void AddToList(CClientBuilding* pBuilding) { m_List.push_back(pBuilding); } + void RemoveFromList(CClientBuilding* pBuilding); + + std::list m_List; + bool m_bRemoveFromList; +}; diff --git a/Client/mods/deathmatch/logic/CClientCamera.cpp b/Client/mods/deathmatch/logic/CClientCamera.cpp index 81528e94af..663d52828e 100644 --- a/Client/mods/deathmatch/logic/CClientCamera.cpp +++ b/Client/mods/deathmatch/logic/CClientCamera.cpp @@ -634,3 +634,13 @@ void CClientCamera::SetGtaMatrix(const CMatrix& matInNew, CCam* pCam) const *pCam->GetFront() = matNew.vFront; *pCam->GetSource() = matNew.vPos; } + +void CClientCamera::ShakeCamera(float radius, float x, float y, float z) noexcept +{ + m_pCamera->ShakeCamera(radius, x, y, z); +} + +void CClientCamera::ResetShakeCamera() noexcept +{ + m_pCamera->ResetShakeCamera(); +} \ No newline at end of file diff --git a/Client/mods/deathmatch/logic/CClientCamera.h b/Client/mods/deathmatch/logic/CClientCamera.h index eff77cdcad..c49246098c 100644 --- a/Client/mods/deathmatch/logic/CClientCamera.h +++ b/Client/mods/deathmatch/logic/CClientCamera.h @@ -64,6 +64,9 @@ class CClientCamera final : public CClientEntity void SetFocusToLocalPlayer(); void Reset(); + void ShakeCamera(float radius, float x, float y, float z) noexcept; + void ResetShakeCamera() noexcept; + void SetCameraVehicleViewMode(eVehicleCamMode eMode); void SetCameraPedViewMode(ePedCamMode eMode); eVehicleCamMode GetCameraVehicleViewMode(); diff --git a/Client/mods/deathmatch/logic/CClientCheckpoint.cpp b/Client/mods/deathmatch/logic/CClientCheckpoint.cpp index 4ab0a9bdc9..fbd7fa8f8e 100644 --- a/Client/mods/deathmatch/logic/CClientCheckpoint.cpp +++ b/Client/mods/deathmatch/logic/CClientCheckpoint.cpp @@ -22,11 +22,14 @@ CClientCheckpoint::CClientCheckpoint(CClientMarker* pThis) m_bStreamedIn = false; m_bVisible = true; m_uiIcon = CClientCheckpoint::ICON_NONE; - m_Color = SColorRGBA(255, 0, 0, 255); + m_Color = SColorRGBA(255, 0, 0, 128); m_fSize = 4.0f; m_dwType = CHECKPOINT_EMPTYTUBE; m_vecDirection.fX = 1.0f; m_bHasTarget = false; + m_ignoreAlphaLimits = false; + m_TargetArrowColor = SColorRGBA(255, 64, 64, 255); + m_TargetArrowSize = m_fSize * 0.625f; } CClientCheckpoint::~CClientCheckpoint() @@ -248,8 +251,14 @@ void CClientCheckpoint::SetColor(const SColor& color) // Different from our current color? if (m_Color != color) { - // Set it and recreate + // Set it m_Color = color; + + // Default alpha + if (!m_ignoreAlphaLimits && GetCheckpointType() == CClientCheckpoint::TYPE_NORMAL) + m_Color.A = 128; + + // Recreate ReCreate(); } } @@ -261,6 +270,8 @@ void CClientCheckpoint::SetSize(float fSize) { // Set the new size and recreate m_fSize = fSize; + m_TargetArrowSize = fSize * 0.625f; + ReCreate(); } } @@ -352,6 +363,7 @@ void CClientCheckpoint::Create(unsigned long ulIdentifier) { // Set properties m_pCheckpoint->SetRotateRate(0); + ApplyCheckpointTargetArrowProperties(); } } } @@ -385,3 +397,20 @@ void CClientCheckpoint::ReCreateWithSameIdentifier() Create(m_dwIdentifier); } } + +void CClientCheckpoint::SetTargetArrowProperties(const SColor& arrowColor, float size) noexcept +{ + if (m_TargetArrowColor == arrowColor && m_TargetArrowSize == size) + return; + + m_TargetArrowColor = arrowColor; + m_TargetArrowSize = size; + + ApplyCheckpointTargetArrowProperties(); +} + +void CClientCheckpoint::ApplyCheckpointTargetArrowProperties() noexcept +{ + if (m_pCheckpoint && m_uiIcon == CClientCheckpoint::ICON_ARROW) + m_pCheckpoint->SetTargetArrowData(m_TargetArrowColor, m_TargetArrowSize); +} diff --git a/Client/mods/deathmatch/logic/CClientCheckpoint.h b/Client/mods/deathmatch/logic/CClientCheckpoint.h index adafcdf39d..ec99bbfd34 100644 --- a/Client/mods/deathmatch/logic/CClientCheckpoint.h +++ b/Client/mods/deathmatch/logic/CClientCheckpoint.h @@ -74,6 +74,13 @@ class CClientCheckpoint : public CClientMarkerCommon static bool IconToString(unsigned char ucIcon, SString& strOutString); void ReCreateWithSameIdentifier(); + void SetIgnoreAlphaLimits(bool ignore) noexcept { m_ignoreAlphaLimits = ignore; }; + bool AreAlphaLimitsIgnored() const noexcept override { return m_ignoreAlphaLimits; }; + + SColor GetTargetArrowColor() const noexcept { return m_TargetArrowColor; }; + float GetTargetArrowSize() const noexcept { return m_TargetArrowSize; }; + void SetTargetArrowProperties(const SColor& arrowColor, float size) noexcept; + protected: bool IsStreamedIn() { return m_bStreamedIn; }; void StreamIn(); @@ -83,6 +90,7 @@ class CClientCheckpoint : public CClientMarkerCommon void Create(unsigned long ulIdentifier = 0); void Destroy(); void ReCreate(); + void ApplyCheckpointTargetArrowProperties() noexcept; CClientMarkerPtr m_pThis; bool m_bStreamedIn; @@ -95,6 +103,9 @@ class CClientCheckpoint : public CClientMarkerCommon float m_fSize; SColor m_Color; CCheckpoint* m_pCheckpoint; + bool m_ignoreAlphaLimits; + SColor m_TargetArrowColor; + float m_TargetArrowSize; DWORD m_dwIdentifier; bool m_bHasTarget; diff --git a/Client/mods/deathmatch/logic/CClientColCircle.cpp b/Client/mods/deathmatch/logic/CClientColCircle.cpp index d1ac42022c..8641eaf12b 100644 --- a/Client/mods/deathmatch/logic/CClientColCircle.cpp +++ b/Client/mods/deathmatch/logic/CClientColCircle.cpp @@ -79,7 +79,7 @@ void CClientColCircle::DebugRender(const CVector& vecPosition, float fDrawRadius { CVector vecBegin = vertexList[i] * vecMult + vecAdd; CVector vecEnd = vertexList[(i + 1) % uiNumPoints] * vecMult + vecAdd; - pGraphics->DrawLine3DQueued(vecBegin, vecEnd, fLineWidth, color, false); + pGraphics->DrawLine3DQueued(vecBegin, vecEnd, fLineWidth, color, eRenderStage::POST_FX); } } } @@ -94,7 +94,7 @@ void CClientColCircle::DebugRender(const CVector& vecPosition, float fDrawRadius { CVector vecBegin = vertexList[i] * vecMultB + vecAdd; CVector vecEnd = vertexList[i] * vecMultT + vecAdd; - pGraphics->DrawLine3DQueued(vecBegin, vecEnd, fLineWidth, color, false); + pGraphics->DrawLine3DQueued(vecBegin, vecEnd, fLineWidth, color, eRenderStage::POST_FX); } } } diff --git a/Client/mods/deathmatch/logic/CClientColCuboid.cpp b/Client/mods/deathmatch/logic/CClientColCuboid.cpp index 63c87061ac..3f8fe11b10 100644 --- a/Client/mods/deathmatch/logic/CClientColCuboid.cpp +++ b/Client/mods/deathmatch/logic/CClientColCuboid.cpp @@ -70,7 +70,7 @@ void CClientColCuboid::DebugRender(const CVector& vecPosition, float fDrawRadius { const CVector& vecBegin = cornerPoints[i] * vecMult + vecAdd; const CVector& vecEnd = cornerPoints[(i + 1) % 4] * vecMult + vecAdd; - pGraphics->DrawLine3DQueued(vecBegin, vecEnd, fLineWidth, color, false); + pGraphics->DrawLine3DQueued(vecBegin, vecEnd, fLineWidth, color, eRenderStage::POST_FX); } } } @@ -89,7 +89,7 @@ void CClientColCuboid::DebugRender(const CVector& vecPosition, float fDrawRadius { const CVector& vecBegin = cornerPoints[i] * vecMult + vecAdd; const CVector& vecEnd = cornerPoints[(i + 1) % 4] * vecMult + vecAdd; - pGraphics->DrawLine3DQueued(vecBegin, vecEnd, fLineWidth, color, false); + pGraphics->DrawLine3DQueued(vecBegin, vecEnd, fLineWidth, color, eRenderStage::POST_FX); } } } @@ -108,7 +108,7 @@ void CClientColCuboid::DebugRender(const CVector& vecPosition, float fDrawRadius { const CVector& vecBegin = cornerPoints[i] * vecMult + vecAdd; const CVector& vecEnd = cornerPoints[(i + 1) % 4] * vecMult + vecAdd; - pGraphics->DrawLine3DQueued(vecBegin, vecEnd, fLineWidth, color, false); + pGraphics->DrawLine3DQueued(vecBegin, vecEnd, fLineWidth, color, eRenderStage::POST_FX); } } } diff --git a/Client/mods/deathmatch/logic/CClientColPolygon.cpp b/Client/mods/deathmatch/logic/CClientColPolygon.cpp index 837c759cf3..db5e144cc9 100644 --- a/Client/mods/deathmatch/logic/CClientColPolygon.cpp +++ b/Client/mods/deathmatch/logic/CClientColPolygon.cpp @@ -205,7 +205,7 @@ void CClientColPolygon::DebugRender(const CVector& vecPosition, float fDrawRadiu CVector vecBegin(vecPointBegin.fX, vecPointBegin.fY, fZ); CVector vecEnd(vecPointEnd.fX, vecPointEnd.fY, fZ); - pGraphics->DrawLine3DQueued(vecBegin, vecEnd, fLineWidth, color, false); + pGraphics->DrawLine3DQueued(vecBegin, vecEnd, fLineWidth, color, eRenderStage::POST_FX); } } } @@ -219,7 +219,7 @@ void CClientColPolygon::DebugRender(const CVector& vecPosition, float fDrawRadiu CVector vecBegin(vecPoint.fX, vecPoint.fY, std::max(vecPosition.fZ - fDrawRadius, m_fFloor)); CVector vecEnd(vecPoint.fX, vecPoint.fY, std::min(vecPosition.fZ + fDrawRadius, m_fCeil)); - pGraphics->DrawLine3DQueued(vecBegin, vecEnd, fLineWidth, color, false); + pGraphics->DrawLine3DQueued(vecBegin, vecEnd, fLineWidth, color, eRenderStage::POST_FX); } } @@ -231,10 +231,10 @@ void CClientColPolygon::DebugRender(const CVector& vecPosition, float fDrawRadiu CVector vecFloorBegin(vecPointBegin.fX, vecPointBegin.fY, m_fFloor); CVector vecFloorEnd(vecPointEnd.fX, vecPointEnd.fY, m_fFloor); - pGraphics->DrawLine3DQueued(vecFloorBegin, vecFloorEnd, fLineWidth, color, false); + pGraphics->DrawLine3DQueued(vecFloorBegin, vecFloorEnd, fLineWidth, color, eRenderStage::POST_FX); CVector vecCeilBegin(vecPointBegin.fX, vecPointBegin.fY, m_fCeil); CVector vecCeilEnd(vecPointEnd.fX, vecPointEnd.fY, m_fCeil); - pGraphics->DrawLine3DQueued(vecCeilBegin, vecCeilEnd, fLineWidth, color, false); + pGraphics->DrawLine3DQueued(vecCeilBegin, vecCeilEnd, fLineWidth, color, eRenderStage::POST_FX); } } diff --git a/Client/mods/deathmatch/logic/CClientColRectangle.cpp b/Client/mods/deathmatch/logic/CClientColRectangle.cpp index 477d5726c8..9aac4f72b2 100644 --- a/Client/mods/deathmatch/logic/CClientColRectangle.cpp +++ b/Client/mods/deathmatch/logic/CClientColRectangle.cpp @@ -76,7 +76,7 @@ void CClientColRectangle::DebugRender(const CVector& vecPosition, float fDrawRad { const CVector& vecBegin = cornerPoints[i] * vecMult + vecAdd; const CVector& vecEnd = cornerPoints[(i + 1) % 4] * vecMult + vecAdd; - pGraphics->DrawLine3DQueued(vecBegin, vecEnd, fLineWidth, color, false); + pGraphics->DrawLine3DQueued(vecBegin, vecEnd, fLineWidth, color, eRenderStage::POST_FX); } } } @@ -97,7 +97,7 @@ void CClientColRectangle::DebugRender(const CVector& vecPosition, float fDrawRad continue; // No end cap const CVector& vecBegin = cornerPoints[i] * vecMult + vecAdd; const CVector& vecEnd = cornerPoints[(i + 1) % 4] * vecMult + vecAdd; - pGraphics->DrawLine3DQueued(vecBegin, vecEnd, fLineWidth, color, false); + pGraphics->DrawLine3DQueued(vecBegin, vecEnd, fLineWidth, color, eRenderStage::POST_FX); } } } @@ -118,7 +118,7 @@ void CClientColRectangle::DebugRender(const CVector& vecPosition, float fDrawRad continue; // No end cap const CVector& vecBegin = cornerPoints[i] * vecMult + vecAdd; const CVector& vecEnd = cornerPoints[(i + 1) % 4] * vecMult + vecAdd; - pGraphics->DrawLine3DQueued(vecBegin, vecEnd, fLineWidth, color, false); + pGraphics->DrawLine3DQueued(vecBegin, vecEnd, fLineWidth, color, eRenderStage::POST_FX); } } } diff --git a/Client/mods/deathmatch/logic/CClientColTube.cpp b/Client/mods/deathmatch/logic/CClientColTube.cpp index e0e55a0b20..03b208ead9 100644 --- a/Client/mods/deathmatch/logic/CClientColTube.cpp +++ b/Client/mods/deathmatch/logic/CClientColTube.cpp @@ -72,7 +72,7 @@ void CClientColTube::DebugRender(const CVector& vecPosition, float fDrawRadius) { const CVector& vecBegin = vertexList[i] * vecMult + vecAdd; const CVector& vecEnd = vertexList[(i + 1) % uiNumPoints] * vecMult + vecAdd; - pGraphics->DrawLine3DQueued(vecBegin, vecEnd, fLineWidth, color, false); + pGraphics->DrawLine3DQueued(vecBegin, vecEnd, fLineWidth, color, eRenderStage::POST_FX); } } } @@ -87,7 +87,7 @@ void CClientColTube::DebugRender(const CVector& vecPosition, float fDrawRadius) { const CVector& vecBegin = vertexList[i] * vecMultB + vecAdd; const CVector& vecEnd = vertexList[i] * vecMultT + vecAdd; - pGraphics->DrawLine3DQueued(vecBegin, vecEnd, fLineWidth, color, false); + pGraphics->DrawLine3DQueued(vecBegin, vecEnd, fLineWidth, color, eRenderStage::POST_FX); } } @@ -100,7 +100,7 @@ void CClientColTube::DebugRender(const CVector& vecPosition, float fDrawRadius) for (uint i = 0; i < vertexList.size(); i++) { const CVector& vecEnd = vertexList[i] * vecMult + vecAdd; - pGraphics->DrawLine3DQueued(vecBegin, vecEnd, fLineWidth, color, false); + pGraphics->DrawLine3DQueued(vecBegin, vecEnd, fLineWidth, color, eRenderStage::POST_FX); } } @@ -113,7 +113,7 @@ void CClientColTube::DebugRender(const CVector& vecPosition, float fDrawRadius) for (uint i = 0; i < vertexList.size(); i++) { const CVector& vecEnd = vertexList[i] * vecMult + vecAdd; - pGraphics->DrawLine3DQueued(vecBegin, vecEnd, fLineWidth, color, false); + pGraphics->DrawLine3DQueued(vecBegin, vecEnd, fLineWidth, color, eRenderStage::POST_FX); } } } diff --git a/Client/mods/deathmatch/logic/CClientCorona.h b/Client/mods/deathmatch/logic/CClientCorona.h index ed1977cadb..53f312e60d 100644 --- a/Client/mods/deathmatch/logic/CClientCorona.h +++ b/Client/mods/deathmatch/logic/CClientCorona.h @@ -41,6 +41,9 @@ class CClientCorona : public CClientMarkerCommon void SetReflectionEnabled(bool bEnabled) { m_bReflectionEnabled = bEnabled; }; bool IsReflectionEnabled() const { return m_bReflectionEnabled; }; + void SetIgnoreAlphaLimits(bool ignore) noexcept {}; + bool AreAlphaLimitsIgnored() const noexcept override { return true; }; + protected: bool IsStreamedIn() { return m_bStreamedIn; }; void StreamIn(); diff --git a/Client/mods/deathmatch/logic/CClientEntity.h b/Client/mods/deathmatch/logic/CClientEntity.h index bd60dab3ba..0d84526d8b 100644 --- a/Client/mods/deathmatch/logic/CClientEntity.h +++ b/Client/mods/deathmatch/logic/CClientEntity.h @@ -79,6 +79,7 @@ enum eClientEntityType CCLIENTVECTORGRAPHIC, CCLIENTUNKNOWN, CCLIENTIMG, + CCLIENTBUILDING, }; class CEntity; @@ -143,6 +144,7 @@ enum eCClientEntityClassTypes CLASS_CClientPointLights, CLASS_CClientSearchLight, CLASS_CClientIMG, + CLASS_CClientBuilding, }; class CClientEntity : public CClientEntityBase diff --git a/Client/mods/deathmatch/logic/CClientGame.cpp b/Client/mods/deathmatch/logic/CClientGame.cpp index 8b4a5852c5..bc20947eac 100644 --- a/Client/mods/deathmatch/logic/CClientGame.cpp +++ b/Client/mods/deathmatch/logic/CClientGame.cpp @@ -32,6 +32,8 @@ #include #include #include +#include +#include "game/CClock.h" #include #include "CServerInfo.h" @@ -249,6 +251,9 @@ CClientGame::CClientGame(bool bLocalPlay) : m_ServerInfo(new CServerInfo()) // Singular file download manager m_pSingularFileDownloadManager = new CSingularFileDownloadManager(); + // 3D model renderer + m_pModelRenderer = std::make_unique(); + // Register the message and the net packet handler g_pMultiplayer->SetPreWeaponFireHandler(CClientGame::PreWeaponFire); g_pMultiplayer->SetPostWeaponFireHandler(CClientGame::PostWeaponFire); @@ -265,11 +270,13 @@ CClientGame::CClientGame(bool bLocalPlay) : m_ServerInfo(new CServerInfo()) g_pMultiplayer->SetRender3DStuffHandler(CClientGame::StaticRender3DStuffHandler); g_pMultiplayer->SetPreRenderSkyHandler(CClientGame::StaticPreRenderSkyHandler); g_pMultiplayer->SetRenderHeliLightHandler(CClientGame::StaticRenderHeliLightHandler); + g_pMultiplayer->SetRenderEverythingBarRoadsHandler(CClientGame::StaticRenderEverythingBarRoadsHandler); g_pMultiplayer->SetChokingHandler(CClientGame::StaticChokingHandler); g_pMultiplayer->SetPreWorldProcessHandler(CClientGame::StaticPreWorldProcessHandler); g_pMultiplayer->SetPostWorldProcessHandler(CClientGame::StaticPostWorldProcessHandler); g_pMultiplayer->SetPostWorldProcessPedsAfterPreRenderHandler(CClientGame::StaticPostWorldProcessPedsAfterPreRenderHandler); g_pMultiplayer->SetPreFxRenderHandler(CClientGame::StaticPreFxRenderHandler); + g_pMultiplayer->SetPostColorFilterRenderHandler(CClientGame::StaticPostColorFilterRenderHandler); g_pMultiplayer->SetPreHudRenderHandler(CClientGame::StaticPreHudRenderHandler); g_pMultiplayer->DisableCallsToCAnimBlendNode(false); g_pMultiplayer->SetCAnimBlendAssocDestructorHandler(CClientGame::StaticCAnimBlendAssocDestructorHandler); @@ -348,9 +355,6 @@ CClientGame::CClientGame(bool bLocalPlay) : m_ServerInfo(new CServerInfo()) // Add our lua events AddBuiltInEvents(); - // Init debugger class - m_Foo.Init(this); - // Load some stuff from the core config float fScale; g_pCore->GetCVars()->Get("text_scale", fScale); @@ -470,11 +474,13 @@ CClientGame::~CClientGame() g_pMultiplayer->SetRender3DStuffHandler(NULL); g_pMultiplayer->SetPreRenderSkyHandler(NULL); g_pMultiplayer->SetRenderHeliLightHandler(nullptr); + g_pMultiplayer->SetRenderEverythingBarRoadsHandler(nullptr); g_pMultiplayer->SetChokingHandler(NULL); g_pMultiplayer->SetPreWorldProcessHandler(NULL); g_pMultiplayer->SetPostWorldProcessHandler(NULL); g_pMultiplayer->SetPostWorldProcessPedsAfterPreRenderHandler(nullptr); g_pMultiplayer->SetPreFxRenderHandler(NULL); + g_pMultiplayer->SetPostColorFilterRenderHandler(nullptr); g_pMultiplayer->SetPreHudRenderHandler(NULL); g_pMultiplayer->DisableCallsToCAnimBlendNode(true); g_pMultiplayer->SetCAnimBlendAssocDestructorHandler(NULL); @@ -752,7 +758,7 @@ bool CClientGame::StartLocalGame(eServerType Type, const char* szPassword) { m_bWaitingForLocalConnect = true; m_bErrorStartingLocal = true; - g_pCore->ShowMessageBox(_("Error") + _E("CD04"), _("The server is not installed"), MB_ICON_ERROR | MB_BUTTON_OK); + g_pCore->ShowMessageBox(_("Error") + _E("CD60"), _("Could not start the local server. See console for details."), MB_BUTTON_OK | MB_ICON_ERROR); g_pCore->GetModManager()->RequestUnload(); return false; } @@ -1119,11 +1125,8 @@ void CClientGame::DoPulses() m_bFirstPlaybackFrame = false; } - // Call debug code if debug mode - m_Foo.DoPulse(); - - // Output stuff from our internal server eventually - m_Server.DoPulse(); + // Output stuff from our server eventually + m_Server.Pulse(); if (m_pManager->IsGameLoaded() && m_Status == CClientGame::STATUS_JOINED && GetTickCount64_() - m_llLastTransgressionTime > 60000) { @@ -1618,12 +1621,6 @@ void CClientGame::ShowNetstat(int iCmd) m_bShowNetstat = bShow; } -void CClientGame::ShowEaeg(bool) -{ - if (m_pLocalPlayer) - m_pLocalPlayer->SetStat(0x2329, 1.0f); -} - #ifdef MTA_WEPSYNCDBG void CClientGame::ShowWepdata(const char* szNick) { @@ -2041,13 +2038,11 @@ void CClientGame::UpdateStunts() // Did we finish a stunt? else if (ulLastCarTwoWheelCounter != 0 && ulTemp == 0) { - float fDistance = g_pGame->GetPlayerInfo()->GetCarTwoWheelDist(); - // Call our stunt event CLuaArguments Arguments; Arguments.PushString("2wheeler"); Arguments.PushNumber(ulLastCarTwoWheelCounter); - Arguments.PushNumber(fDistance); + Arguments.PushNumber(fLastCarTwoWheelDist); m_pLocalPlayer->CallEvent("onClientPlayerStuntFinish", Arguments, true); } ulLastCarTwoWheelCounter = ulTemp; @@ -2068,13 +2063,11 @@ void CClientGame::UpdateStunts() // Did we finish a stunt? else if (ulLastBikeRearWheelCounter != 0 && ulTemp == 0) { - float fDistance = g_pGame->GetPlayerInfo()->GetBikeRearWheelDist(); - // Call our stunt event CLuaArguments Arguments; Arguments.PushString("wheelie"); Arguments.PushNumber(ulLastBikeRearWheelCounter); - Arguments.PushNumber(fDistance); + Arguments.PushNumber(fLastBikeRearWheelDist); m_pLocalPlayer->CallEvent("onClientPlayerStuntFinish", Arguments, true); } ulLastBikeRearWheelCounter = ulTemp; @@ -2095,13 +2088,11 @@ void CClientGame::UpdateStunts() // Did we finish a stunt? else if (ulLastBikeFrontWheelCounter != 0 && ulTemp == 0) { - float fDistance = g_pGame->GetPlayerInfo()->GetBikeFrontWheelDist(); - // Call our stunt event CLuaArguments Arguments; Arguments.PushString("stoppie"); Arguments.PushNumber(ulLastBikeFrontWheelCounter); - Arguments.PushNumber(fDistance); + Arguments.PushNumber(fLastBikeFrontWheelDist); m_pLocalPlayer->CallEvent("onClientPlayerStuntFinish", Arguments, true); } ulLastBikeFrontWheelCounter = ulTemp; @@ -2653,7 +2644,7 @@ void CClientGame::AddBuiltInEvents() m_Events.AddEvent("onClientPlayerRadioSwitch", "", NULL, false); m_Events.AddEvent("onClientPlayerDamage", "attacker, weapon, bodypart", NULL, false); m_Events.AddEvent("onClientPlayerWeaponFire", "weapon, ammo, ammoInClip, hitX, hitY, hitZ, hitElement", NULL, false); - m_Events.AddEvent("onClientPlayerWasted", "", NULL, false); + m_Events.AddEvent("onClientPlayerWasted", "ammo, killer, weapon, bodypart, isStealth, animGroup, animID", nullptr, false); m_Events.AddEvent("onClientPlayerChoke", "", NULL, false); m_Events.AddEvent("onClientPlayerVoiceStart", "", NULL, false); m_Events.AddEvent("onClientPlayerVoiceStop", "", NULL, false); @@ -2720,6 +2711,7 @@ void CClientGame::AddBuiltInEvents() // Console events m_Events.AddEvent("onClientConsole", "text", NULL, false); + m_Events.AddEvent("onClientCoreCommand", "command", NULL, false); // Chat events m_Events.AddEvent("onClientChatMessage", "text, r, g, b, messageType", NULL, false); @@ -2932,8 +2924,8 @@ void CClientGame::DrawPlayerDetails(CClientPlayer* pPlayer) const CVector& vecAimTarget = pPlayer->GetAimTarget(); eVehicleAimDirection ucDrivebyAim = pPlayer->GetVehicleAimAnim(); - g_pCore->GetGraphics()->DrawLine3DQueued(vecAimSource, vecAimTarget, 1.0f, 0x10DE1212, true); - g_pCore->GetGraphics()->DrawLine3DQueued(vecAimSource, vecAimTarget, 1.0f, 0x90DE1212, false); + g_pCore->GetGraphics()->DrawLine3DQueued(vecAimSource, vecAimTarget, 1.0f, 0x10DE1212, eRenderStage::POST_GUI); + g_pCore->GetGraphics()->DrawLine3DQueued(vecAimSource, vecAimTarget, 1.0f, 0x90DE1212, eRenderStage::POST_FX); CTask* pPrimaryTask = pPlayer->GetCurrentPrimaryTask(); int iPrimaryTask = pPrimaryTask ? pPrimaryTask->GetTaskType() : -1; @@ -2991,8 +2983,8 @@ void CClientGame::DrawWeaponsyncData(CClientPlayer* pPlayer) // red line: Draw their synced aim line pPlayer->GetShotData(&vecSource, &vecTarget); - g_pCore->GetGraphics()->DrawLine3DQueued(vecSource, vecTarget, 2.0f, 0x10DE1212, true); - g_pCore->GetGraphics()->DrawLine3DQueued(vecSource, vecTarget, 2.0f, 0x90DE1212, false); + g_pCore->GetGraphics()->DrawLine3DQueued(vecSource, vecTarget, 2.0f, 0x10DE1212, eRenderStage::POST_GUI); + g_pCore->GetGraphics()->DrawLine3DQueued(vecSource, vecTarget, 2.0f, 0x90DE1212, eRenderStage::POST_FX); // green line: Set muzzle as origin and perform a collision test for the target CColPoint* pCollision; @@ -3005,8 +2997,8 @@ void CClientGame::DrawWeaponsyncData(CClientPlayer* pPlayer) CVector vecBullet = pCollision->GetPosition() - vecSource; vecBullet.Normalize(); CVector vecTarget = vecSource + (vecBullet * 200); - g_pCore->GetGraphics()->DrawLine3DQueued(vecSource, vecTarget, 0.5f, 0x1012DE12, true); - g_pCore->GetGraphics()->DrawLine3DQueued(vecSource, vecTarget, 0.5f, 0x9012DE12, false); + g_pCore->GetGraphics()->DrawLine3DQueued(vecSource, vecTarget, 0.5f, 0x1012DE12, eRenderStage::POST_GUI); + g_pCore->GetGraphics()->DrawLine3DQueued(vecSource, vecTarget, 0.5f, 0x9012DE12, eRenderStage::POST_FX); } pCollision->Destroy(); } @@ -3431,7 +3423,7 @@ void CClientGame::Event_OnIngame() g_pMultiplayer->DeleteAndDisableGangTags(); - g_pGame->GetWorld()->ClearRemovedBuildingLists(); + g_pGame->GetBuildingRemoval()->ClearRemovedBuildingLists(); g_pGame->GetWorld()->SetOcclusionsEnabled(true); g_pGame->ResetModelLodDistances(); @@ -3559,6 +3551,11 @@ void CClientGame::StaticRenderHeliLightHandler() g_pClientGame->GetManager()->GetPointLightsManager()->RenderHeliLightHandler(); } +void CClientGame::StaticRenderEverythingBarRoadsHandler() +{ + g_pClientGame->GetModelRenderer()->Render(); +} + bool CClientGame::StaticChokingHandler(unsigned char ucWeaponType) { return g_pClientGame->ChokingHandler(ucWeaponType); @@ -3612,6 +3609,11 @@ void CClientGame::StaticPreFxRenderHandler() g_pCore->OnPreFxRender(); } +void CClientGame::StaticPostColorFilterRenderHandler() +{ + g_pCore->OnPostColorFilterRender(); +} + void CClientGame::StaticPreHudRenderHandler() { g_pCore->OnPreHUDRender(); @@ -3624,10 +3626,10 @@ bool CClientGame::StaticProcessCollisionHandler(CEntitySAInterface* pThisInterfa bool CClientGame::StaticVehicleCollisionHandler(CVehicleSAInterface*& pCollidingVehicle, CEntitySAInterface* pCollidedVehicle, int iModelIndex, float fDamageImpulseMag, float fCollidingDamageImpulseMag, uint16 usPieceType, CVector vecCollisionPos, - CVector vecCollisionVelocity) + CVector vecCollisionVelocity, bool isProjectile) { return g_pClientGame->VehicleCollisionHandler(pCollidingVehicle, pCollidedVehicle, iModelIndex, fDamageImpulseMag, fCollidingDamageImpulseMag, usPieceType, - vecCollisionPos, vecCollisionVelocity); + vecCollisionPos, vecCollisionVelocity, isProjectile); } bool CClientGame::StaticVehicleDamageHandler(CEntitySAInterface* pVehicleInterface, float fLoss, CEntitySAInterface* pAttackerInterface, eWeaponType weaponType, @@ -3861,6 +3863,8 @@ void CClientGame::PostWorldProcessPedsAfterPreRenderHandler() { CLuaArguments Arguments; m_pRootEntity->CallEvent("onClientPedsProcessed", Arguments, false); + + g_pClientGame->GetModelRenderer()->Update(); } void CClientGame::IdleHandler() @@ -4551,7 +4555,7 @@ void CClientGame::DeathHandler(CPed* pKilledPedSA, unsigned char ucDeathReason, } bool CClientGame::VehicleCollisionHandler(CVehicleSAInterface*& pCollidingVehicle, CEntitySAInterface* pCollidedWith, int iModelIndex, float fDamageImpulseMag, - float fCollidingDamageImpulseMag, uint16 usPieceType, CVector vecCollisionPos, CVector vecCollisionVelocity) + float fCollidingDamageImpulseMag, uint16 usPieceType, CVector vecCollisionPos, CVector vecCollisionVelocity, bool isProjectile) { if (pCollidingVehicle && pCollidedWith) { @@ -4566,7 +4570,7 @@ bool CClientGame::VehicleCollisionHandler(CVehicleSAInterface*& pCollidingVehicl } CClientVehicle* pClientVehicle = static_cast(pVehicleClientEntity); - CClientEntity* pCollidedWithClientEntity = pPools->GetClientEntity((DWORD*)pCollidedWith); + CClientEntity* pCollidedWithClientEntity = !isProjectile ? pPools->GetClientEntity((DWORD*)pCollidedWith) : m_pManager->GetProjectileManager()->Get(pCollidedWith); CLuaArguments Arguments; if (pCollidedWithClientEntity) @@ -5417,22 +5421,21 @@ void CClientGame::ResetMapInfo() // Hud g_pGame->GetHud()->SetComponentVisible(HUD_ALL, true); + // Disable area names as they are on load until camera unfades g_pGame->GetHud()->SetComponentVisible(HUD_AREA_NAME, false); g_pGame->GetHud()->SetComponentVisible(HUD_VITAL_STATS, false); m_bHudAreaNameDisabled = false; - // Gravity - g_pMultiplayer->SetLocalPlayerGravity(DEFAULT_GRAVITY); - g_pMultiplayer->SetGlobalGravity(DEFAULT_GRAVITY); - g_pGame->SetGravity(DEFAULT_GRAVITY); - - // Gamespeed - SetGameSpeed(DEFAULT_GAME_SPEED); - - // Game minute duration - SetMinuteDuration(DEFAULT_MINUTE_DURATION); + // Reset world special properties, world properties, weather properties etc + ResetWorldPropsInfo desc; + desc.resetSpecialProperties = true; + desc.resetWorldProperties = true; + desc.resetWeatherProperties = true; + desc.resetLODs = true; + desc.resetSounds = true; + ResetWorldProperties(desc); // Wanted-level SetWanted(0); @@ -5443,94 +5446,19 @@ void CClientGame::ResetMapInfo() // Weather m_pBlendedWeather->SetWeather(0); - // Rain - g_pGame->GetWeather()->ResetAmountOfRain(); - - // Wind - g_pMultiplayer->RestoreWindVelocity(); - - // Far clip distance - g_pMultiplayer->RestoreFarClipDistance(); - - // Near clip distance - g_pMultiplayer->RestoreNearClipDistance(); - - // Fog distance - g_pMultiplayer->RestoreFogDistance(); - - // Vehicles LOD distance - g_pGame->GetSettings()->ResetVehiclesLODDistance(true); - - // Peds LOD distance - g_pGame->GetSettings()->ResetPedsLODDistance(true); - - // Blur - g_pGame->GetSettings()->SetBlurControlledByScript(false); - g_pGame->GetSettings()->ResetBlurEnabled(); - - // Corona rain reflections - g_pGame->GetSettings()->SetCoronaReflectionsControlledByScript(false); - g_pGame->GetSettings()->ResetCoronaReflectionsEnabled(); - - // Sun color - g_pMultiplayer->ResetSunColor(); - - // Sun size - g_pMultiplayer->ResetSunSize(); - - // Sky-gradient - g_pMultiplayer->ResetSky(); - - // Heat haze - g_pMultiplayer->ResetHeatHaze(); - - // Water-colour - g_pMultiplayer->ResetWater(); - g_pMultiplayer->ResetColorFilter(); - // Grain effect g_pMultiplayer->SetGrainMultiplier(eGrainMultiplierType::ALL, 1.0f); g_pMultiplayer->SetGrainLevel(0); - // Water - GetManager()->GetWaterManager()->ResetWorldWaterLevel(); - - // Re-enable interior sounds and furniture - g_pMultiplayer->SetInteriorSoundsEnabled(true); - for (int i = 0; i <= 4; ++i) - g_pMultiplayer->SetInteriorFurnitureEnabled(i, true); - - // Clouds - g_pMultiplayer->SetCloudsEnabled(true); - g_pClientGame->SetCloudsEnabled(true); - - // Birds - g_pMultiplayer->DisableBirds(false); - g_pClientGame->SetBirdsEnabled(true); - - // Ambient sounds - g_pGame->GetAudioEngine()->ResetAmbientSounds(); - - // World sounds - g_pGame->GetAudioEngine()->ResetWorldSounds(); - // Cheats g_pGame->ResetCheats(); // Players m_pPlayerManager->ResetAll(); - // Jetpack max height - g_pGame->GetWorld()->SetJetpackMaxHeight(DEFAULT_JETPACK_MAXHEIGHT); - - // Aircraft max height - g_pGame->GetWorld()->SetAircraftMaxHeight(DEFAULT_AIRCRAFT_MAXHEIGHT); - - // Aircraft max velocity - g_pGame->GetWorld()->SetAircraftMaxVelocity(DEFAULT_AIRCRAFT_MAXVELOCITY); - - // Moon size - g_pMultiplayer->ResetMoonSize(); + // Reset Frozen Time + g_pGame->GetClock()->ResetTimeFrozen(); + g_pGame->GetSettings()->ResetVolumetricShadows(); // Disable the change of any player stats g_pMultiplayer->SetLocalStatsStatic(true); @@ -5577,7 +5505,7 @@ void CClientGame::ResetMapInfo() if (pPlayerInfo) pPlayerInfo->SetCamDrunkLevel(static_cast(0)); - RestreamWorld(true); + RestreamWorld(); ReinitMarkers(); } @@ -5653,6 +5581,8 @@ void CClientGame::DoWastedCheck(ElementID damagerID, unsigned char ucWeapon, uns else Arguments.PushBoolean(false); Arguments.PushBoolean(false); + Arguments.PushNumber(animGroup); + Arguments.PushNumber(animID); m_pLocalPlayer->CallEvent("onClientPlayerWasted", Arguments, true); // Write some death info @@ -6091,6 +6021,14 @@ bool CClientGame::SetWorldSpecialProperty(WorldSpecialProperty property, bool is case WorldSpecialProperty::FIREBALLDESTRUCT: g_pGame->SetFireballDestructEnabled(isEnabled); return true; + case WorldSpecialProperty::EXTENDEDWATERCANNONS: + g_pGame->SetExtendedWaterCannonsEnabled(isEnabled); + case WorldSpecialProperty::ROADSIGNSTEXT: + g_pGame->SetRoadSignsTextEnabled(isEnabled); + return true; + case WorldSpecialProperty::TUNNELWEATHERBLEND: + g_pGame->SetTunnelWeatherBlendEnabled(isEnabled); + return true; } return false; } @@ -6122,6 +6060,12 @@ bool CClientGame::IsWorldSpecialProperty(WorldSpecialProperty property) return g_pGame->IsBurnFlippedCarsEnabled(); case WorldSpecialProperty::FIREBALLDESTRUCT: return g_pGame->IsFireballDestructEnabled(); + case WorldSpecialProperty::EXTENDEDWATERCANNONS: + return g_pGame->IsExtendedWaterCannonsEnabled(); + case WorldSpecialProperty::ROADSIGNSTEXT: + return g_pGame->IsRoadSignsTextEnabled(); + case WorldSpecialProperty::TUNNELWEATHERBLEND: + return g_pGame->IsTunnelWeatherBlendEnabled(); } return false; } @@ -6784,7 +6728,7 @@ void CClientGame::RestreamModel(unsigned short usModel) m_pManager->GetVehicleManager()->RestreamVehicleUpgrades(usModel); } -void CClientGame::RestreamWorld(bool removeBigBuildings) +void CClientGame::RestreamWorld() { unsigned int numberOfFileIDs = g_pGame->GetCountOfAllFileIDs(); @@ -6797,9 +6741,7 @@ void CClientGame::RestreamWorld(bool removeBigBuildings) m_pManager->GetPedManager()->RestreamAllPeds(); m_pManager->GetPickupManager()->RestreamAllPickups(); - if (removeBigBuildings) - g_pGame->GetStreaming()->RemoveBigBuildings(); - + g_pGame->GetStreaming()->RemoveBigBuildings(); g_pGame->GetStreaming()->ReinitStreaming(); } @@ -6808,6 +6750,145 @@ void CClientGame::ReinitMarkers() g_pGame->Get3DMarkers()->ReinitMarkers(); } +void CClientGame::ResetWorldProperties(const ResetWorldPropsInfo& resetPropsInfo) +{ + // Reset all setWorldSpecialPropertyEnabled to default + if (resetPropsInfo.resetSpecialProperties) + { + g_pGame->SetCheatEnabled("hovercars", false); + g_pGame->SetCheatEnabled("aircars", false); + g_pGame->SetCheatEnabled("extrabunny", false); + g_pGame->SetCheatEnabled("extrajump", false); + + g_pGame->SetRandomFoliageEnabled(true); + g_pGame->SetMoonEasterEggEnabled(false); + g_pGame->SetExtraAirResistanceEnabled(true); + g_pGame->SetUnderWorldWarpEnabled(true); + g_pGame->SetVehicleSunGlareEnabled(false); + g_pGame->SetCoronaZTestEnabled(true); + g_pGame->SetWaterCreaturesEnabled(true); + g_pGame->SetBurnFlippedCarsEnabled(true); + g_pGame->SetFireballDestructEnabled(true); + g_pGame->SetRoadSignsTextEnabled(true); + g_pGame->SetExtendedWaterCannonsEnabled(true); + g_pGame->SetTunnelWeatherBlendEnabled(true); + } + + // Reset all setWorldProperty to default + if (resetPropsInfo.resetWorldProperties) + { + g_pMultiplayer->ResetAmbientColor(); + g_pMultiplayer->ResetAmbientObjectColor(); + g_pMultiplayer->ResetDirectionalColor(); + g_pMultiplayer->ResetSpriteSize(); + g_pMultiplayer->ResetSpriteBrightness(); + g_pMultiplayer->ResetPoleShadowStrength(); + g_pMultiplayer->ResetShadowStrength(); + g_pMultiplayer->ResetShadowsOffset(); + g_pMultiplayer->ResetLightsOnGroundBrightness(); + g_pMultiplayer->ResetLowCloudsColor(); + g_pMultiplayer->ResetBottomCloudsColor(); + g_pMultiplayer->ResetCloudsAlpha1(); + g_pMultiplayer->ResetIllumination(); + + CWeather* weather = g_pGame->GetWeather(); + weather->ResetWetRoads(); + weather->ResetFoggyness(); + weather->ResetFog(); + weather->ResetRainFog(); + weather->ResetWaterFog(); + weather->ResetSandstorm(); + weather->ResetRainbow(); + } + + // Reset all weather stuff like heat haze, wind velocity etc + if (resetPropsInfo.resetWeatherProperties) + { + g_pMultiplayer->ResetHeatHaze(); + g_pMultiplayer->RestoreFogDistance(); + g_pMultiplayer->ResetMoonSize(); + g_pMultiplayer->ResetSky(); + g_pMultiplayer->ResetSunColor(); + g_pMultiplayer->ResetSunSize(); + g_pMultiplayer->RestoreWindVelocity(); + g_pMultiplayer->ResetColorFilter(); + + g_pGame->GetWeather()->ResetAmountOfRain(); + } + + // Reset LODs + if (resetPropsInfo.resetLODs) + { + g_pGame->GetSettings()->ResetVehiclesLODDistance(true); + g_pGame->GetSettings()->ResetPedsLODDistance(true); + } + + // Reset & restore sounds + if (resetPropsInfo.resetSounds) + { + g_pMultiplayer->SetInteriorSoundsEnabled(true); + g_pGame->GetAudioEngine()->ResetAmbientSounds(); + g_pGame->GetAudioEngine()->ResetWorldSounds(); + } + + // Reset all other world stuff + // Reset clip distances + g_pMultiplayer->RestoreFarClipDistance(); + g_pMultiplayer->RestoreNearClipDistance(); + + // Reset clouds + g_pMultiplayer->SetCloudsEnabled(true); + SetCloudsEnabled(true); + + // Reset birds + g_pMultiplayer->DisableBirds(false); + SetBirdsEnabled(true); + + // Reset occlusions + g_pGame->GetWorld()->SetOcclusionsEnabled(true); + + // Reset gravity + g_pMultiplayer->SetGlobalGravity(DEFAULT_GRAVITY); + g_pCore->GetMultiplayer()->SetLocalPlayerGravity(DEFAULT_GRAVITY); + g_pGame->SetGravity(DEFAULT_GRAVITY); + + // Reset game speed + g_pGame->SetGameSpeed(DEFAULT_GAME_SPEED); + + // Reset aircraft max velocity & height + g_pMultiplayer->SetAircraftMaxHeight(DEFAULT_AIRCRAFT_MAXHEIGHT); + g_pMultiplayer->SetAircraftMaxVelocity(DEFAULT_AIRCRAFT_MAXVELOCITY); + + // Reset jetpack max height + g_pGame->GetWorld()->SetJetpackMaxHeight(DEFAULT_JETPACK_MAXHEIGHT); + + // Restore furnitures in the interiors + for (std::uint8_t i = 0; i <= 4; ++i) + g_pMultiplayer->SetInteriorFurnitureEnabled(i, true); + + // Reset minute duration + SetMinuteDuration(DEFAULT_MINUTE_DURATION); + + // Reset blur level + g_pGame->GetSettings()->SetBlurControlledByScript(false); + g_pGame->GetSettings()->ResetBlurEnabled(); + + // Reset corona reflections + g_pGame->GetSettings()->SetCoronaReflectionsControlledByScript(false); + g_pGame->GetSettings()->ResetCoronaReflectionsEnabled(); + + // Reset traffic lights + g_pMultiplayer->SetTrafficLightsLocked(false); + + // Reset water color, water level & wave height + g_pMultiplayer->ResetWater(); + GetManager()->GetWaterManager()->ResetWorldWaterLevel(); + GetManager()->GetWaterManager()->SetWaveLevel(0.0f); + + // Reset volumetric shadows + g_pGame->GetSettings()->ResetVolumetricShadows(); +} + void CClientGame::OnWindowFocusChange(bool state) { if (state == m_bFocused) diff --git a/Client/mods/deathmatch/logic/CClientGame.h b/Client/mods/deathmatch/logic/CClientGame.h index 96d82c37a7..ba6bc29334 100644 --- a/Client/mods/deathmatch/logic/CClientGame.h +++ b/Client/mods/deathmatch/logic/CClientGame.h @@ -38,7 +38,6 @@ #include "CResourceManager.h" #include "CScriptKeyBinds.h" #include "CElementDeleter.h" -#include "CFoo.h" #include "CRegisteredCommands.h" #include "CClientGUIElement.h" #include "CLocalServer.h" @@ -72,6 +71,15 @@ struct SMiscGameSettings bool bAllowShotgunDamageFix; }; +struct ResetWorldPropsInfo +{ + bool resetSpecialProperties{}; + bool resetWorldProperties{}; + bool resetWeatherProperties{}; + bool resetLODs{}; + bool resetSounds{}; +}; + class CClientGame { friend class CPacketHandler; @@ -309,11 +317,12 @@ class CClientGame CRemoteCalls* GetRemoteCalls() { return m_pRemoteCalls; } CResourceFileDownloadManager* GetResourceFileDownloadManager() { return m_pResourceFileDownloadManager; } + CModelRenderer* GetModelRenderer() const noexcept { return m_pModelRenderer.get(); } + SharedUtil::CAsyncTaskScheduler* GetAsyncTaskScheduler() { return m_pAsyncTaskScheduler; } // Status toggles void ShowNetstat(int iCmd); - void ShowEaeg(bool bShow); void ShowFPS(bool bShow) { m_bShowFPS = bShow; }; #if defined(MTA_DEBUG) || defined(MTA_BETA) @@ -410,6 +419,8 @@ class CClientGame bool SetBirdsEnabled(bool bEnabled); bool GetBirdsEnabled(); + void ResetWorldProperties(const ResetWorldPropsInfo& resetPropsInfo); + CTransferBox* GetTransferBox() { return m_pTransferBox; }; void ChangeVehicleWeapon(bool bNext); @@ -443,7 +454,7 @@ class CClientGame bool TriggerBrowserRequestResultEvent(const std::unordered_set& newPages); void RestreamModel(unsigned short usModel); - void RestreamWorld(bool removeBigBuildings); + void RestreamWorld(); void ReinitMarkers(); void OnWindowFocusChange(bool state); @@ -506,11 +517,13 @@ class CClientGame static void StaticRender3DStuffHandler(); static void StaticPreRenderSkyHandler(); static void StaticRenderHeliLightHandler(); + static void StaticRenderEverythingBarRoadsHandler(); static bool StaticChokingHandler(unsigned char ucWeaponType); static void StaticPreWorldProcessHandler(); static void StaticPostWorldProcessHandler(); static void StaticPostWorldProcessPedsAfterPreRenderHandler(); static void StaticPreFxRenderHandler(); + static void StaticPostColorFilterRenderHandler(); static void StaticPreHudRenderHandler(); static void StaticCAnimBlendAssocDestructorHandler(CAnimBlendAssociationSAInterface* pThis); static CAnimBlendAssociationSAInterface* StaticAddAnimationHandler(RpClump* pClump, AssocGroupId animGroup, AnimationId animID); @@ -523,7 +536,7 @@ class CClientGame static bool StaticProcessCollisionHandler(CEntitySAInterface* pThisInterface, CEntitySAInterface* pOtherInterface); static bool StaticVehicleCollisionHandler(CVehicleSAInterface*& pThisInterface, CEntitySAInterface* pOtherInterface, int iModelIndex, float fDamageImpulseMag, float fCollidingDamageImpulseMag, uint16 usPieceType, CVector vecCollisionPos, - CVector vecCollisionVelocity); + CVector vecCollisionVelocity, bool isProjectile); static bool StaticVehicleDamageHandler(CEntitySAInterface* pVehicleInterface, float fLoss, CEntitySAInterface* pAttackerInterface, eWeaponType weaponType, const CVector& vecDamagePos, uchar ucTyre); static bool StaticHeliKillHandler(CVehicleSAInterface* pHeli, CEntitySAInterface* pHitInterface); @@ -568,7 +581,7 @@ class CClientGame RpClump* pClump); bool ProcessCollisionHandler(CEntitySAInterface* pThisInterface, CEntitySAInterface* pOtherInterface); bool VehicleCollisionHandler(CVehicleSAInterface*& pCollidingVehicle, CEntitySAInterface* pCollidedVehicle, int iModelIndex, float fDamageImpulseMag, - float fCollidingDamageImpulseMag, uint16 usPieceType, CVector vecCollisionPos, CVector vecCollisionVelocity); + float fCollidingDamageImpulseMag, uint16 usPieceType, CVector vecCollisionPos, CVector vecCollisionVelocity, bool isProjectile); bool VehicleDamageHandler(CEntitySAInterface* pVehicleInterface, float fLoss, CEntitySAInterface* pAttackerInterface, eWeaponType weaponType, const CVector& vecDamagePos, uchar ucTyre); bool HeliKillHandler(CVehicleSAInterface* pHeli, CEntitySAInterface* pHitInterface); @@ -699,6 +712,8 @@ class CClientGame CRemoteCalls* m_pRemoteCalls; CResourceFileDownloadManager* m_pResourceFileDownloadManager; + std::unique_ptr m_pModelRenderer; + // Revised facilities CServer m_Server; @@ -813,10 +828,6 @@ class CClientGame bool m_bShowCollision; bool m_bShowSound; - // Debug class. Empty in release. -public: - CFoo m_Foo; - private: CEvents m_Events; std::list m_ScreenShotArgList; diff --git a/Client/mods/deathmatch/logic/CClientIMG.cpp b/Client/mods/deathmatch/logic/CClientIMG.cpp index 0778385184..5abd8b07e6 100644 --- a/Client/mods/deathmatch/logic/CClientIMG.cpp +++ b/Client/mods/deathmatch/logic/CClientIMG.cpp @@ -28,6 +28,11 @@ CClientIMG::CClientIMG(class CClientManager* pManager, ElementID ID) CClientIMG::~CClientIMG() { m_pImgManager->RemoveFromList(this); + Unlink(); +} + +void CClientIMG::Unlink() +{ if (IsStreamed()) StreamDisable(); @@ -186,7 +191,7 @@ bool CClientIMG::StreamDisable() m_pImgManager->UpdateStreamerBufferSize(); - g_pClientGame->RestreamWorld(true); + g_pClientGame->RestreamWorld(); return true; } diff --git a/Client/mods/deathmatch/logic/CClientIMG.h b/Client/mods/deathmatch/logic/CClientIMG.h index 5cd50c93dd..2074e64fbc 100644 --- a/Client/mods/deathmatch/logic/CClientIMG.h +++ b/Client/mods/deathmatch/logic/CClientIMG.h @@ -50,7 +50,7 @@ class CClientIMG : public CClientEntity CClientIMG(class CClientManager* pManager, ElementID ID); ~CClientIMG(); - void Unlink(){}; + void Unlink(); void GetPosition(CVector& vecPosition) const {}; void SetPosition(const CVector& vecPosition){}; diff --git a/Client/mods/deathmatch/logic/CClientIMGManager.cpp b/Client/mods/deathmatch/logic/CClientIMGManager.cpp index ea85f045d5..6a8c6e7e6d 100644 --- a/Client/mods/deathmatch/logic/CClientIMGManager.cpp +++ b/Client/mods/deathmatch/logic/CClientIMGManager.cpp @@ -129,7 +129,8 @@ void CClientIMGManager::UpdateStreamerBufferSize() m_LargestFileSizeBlocks = CalculateLargestFile(); // Only update if necessary, otherwise leave it be [User might've set it manually - we don't want to touch that] - if (const auto s = g_pGame->GetStreaming(); m_LargestFileSizeBlocks > s->GetStreamingBufferSize()) { + if (const auto s = g_pGame->GetStreaming(); m_LargestFileSizeBlocks * 2048 > s->GetStreamingBufferSize()) + { s->SetStreamingBufferSize(m_LargestFileSizeBlocks); } } diff --git a/Client/mods/deathmatch/logic/CClientManager.cpp b/Client/mods/deathmatch/logic/CClientManager.cpp index 21962cc8f3..e3a808555b 100644 --- a/Client/mods/deathmatch/logic/CClientManager.cpp +++ b/Client/mods/deathmatch/logic/CClientManager.cpp @@ -54,6 +54,7 @@ CClientManager::CClientManager() m_pModelManager = new CClientModelManager(); m_pPacketRecorder = new CClientPacketRecorder(this); m_pImgManager = new CClientIMGManager(this); + m_pBuildingManager = new CClientBuildingManager(this); m_bBeingDeleted = false; m_bGameUnloadedFlag = false; @@ -177,6 +178,9 @@ CClientManager::~CClientManager() delete m_pImgManager; m_pImgManager = nullptr; + + delete m_pBuildingManager; + m_pBuildingManager = nullptr; } // diff --git a/Client/mods/deathmatch/logic/CClientManager.h b/Client/mods/deathmatch/logic/CClientManager.h index e916c8eb73..0e9f0c7702 100644 --- a/Client/mods/deathmatch/logic/CClientManager.h +++ b/Client/mods/deathmatch/logic/CClientManager.h @@ -43,6 +43,7 @@ class CClientManager; #include "CClientPointLightsManager.h" #include "CClientModelManager.h" #include "CClientIMGManager.h" +#include "CClientBuildingManager.h" class CClientProjectileManager; class CClientExplosionManager; @@ -96,6 +97,7 @@ class CClientManager CClientEffectManager* GetEffectManager() { return m_pEffectManager; } CClientPointLightsManager* GetPointLightsManager() { return m_pPointLightsManager; } CClientIMGManager* GetIMGManager() { return m_pImgManager; } + CClientBuildingManager* GetBuildingManager() const noexcept { return m_pBuildingManager; } bool IsGameLoaded() { return g_pGame->GetSystemState() == 9 && !m_bGameUnloadedFlag && g_pCore->GetNetwork()->GetServerBitStreamVersion(); } bool IsBeingDeleted() { return m_bBeingDeleted; } @@ -148,6 +150,7 @@ class CClientManager CClientModelManager* m_pModelManager; CClientIMGManager* m_pImgManager; CClientPacketRecorder* m_pPacketRecorder; + CClientBuildingManager* m_pBuildingManager; bool m_bBeingDeleted; bool m_bGameUnloadedFlag; int m_iNumLowLODElements; diff --git a/Client/mods/deathmatch/logic/CClientMarker.cpp b/Client/mods/deathmatch/logic/CClientMarker.cpp index d193ab1823..b01a3ade2c 100644 --- a/Client/mods/deathmatch/logic/CClientMarker.cpp +++ b/Client/mods/deathmatch/logic/CClientMarker.cpp @@ -510,3 +510,8 @@ CSphere CClientMarker::GetWorldBoundingSphere() sphere.fRadius = GetSize(); return sphere; } + +void CClientMarker::SetIgnoreAlphaLimits(bool ignore) +{ + m_pMarker->SetIgnoreAlphaLimits(ignore); +} diff --git a/Client/mods/deathmatch/logic/CClientMarker.h b/Client/mods/deathmatch/logic/CClientMarker.h index 2cffa3b97b..4aee90b93d 100644 --- a/Client/mods/deathmatch/logic/CClientMarker.h +++ b/Client/mods/deathmatch/logic/CClientMarker.h @@ -84,6 +84,9 @@ class CClientMarker final : public CClientStreamElement, private CClientColCallb virtual CSphere GetWorldBoundingSphere(); + void SetIgnoreAlphaLimits(bool ignore); + bool AreAlphaLimitsIgnored() const noexcept { return m_pMarker->AreAlphaLimitsIgnored(); }; + protected: void StreamIn(bool bInstantly); void StreamOut(); diff --git a/Client/mods/deathmatch/logic/CClientMarkerCommon.h b/Client/mods/deathmatch/logic/CClientMarkerCommon.h index 3f7e101a8a..02ed426f69 100644 --- a/Client/mods/deathmatch/logic/CClientMarkerCommon.h +++ b/Client/mods/deathmatch/logic/CClientMarkerCommon.h @@ -56,4 +56,7 @@ class CClientMarkerCommon virtual void StreamIn() = 0; virtual void StreamOut() = 0; + + virtual void SetIgnoreAlphaLimits(bool ignore) noexcept = 0; + virtual bool AreAlphaLimitsIgnored() const noexcept = 0; }; diff --git a/Client/mods/deathmatch/logic/CClientModel.cpp b/Client/mods/deathmatch/logic/CClientModel.cpp index e42ee3a695..795bc08579 100644 --- a/Client/mods/deathmatch/logic/CClientModel.cpp +++ b/Client/mods/deathmatch/logic/CClientModel.cpp @@ -109,6 +109,8 @@ void CClientModel::RestoreEntitiesUsingThisModel() { case eClientModelType::PED: case eClientModelType::OBJECT: + case eClientModelType::CLUMP: + case eClientModelType::TIMED_OBJECT: case eClientModelType::VEHICLE: RestoreDFF(pModelInfo); return; @@ -122,6 +124,13 @@ void CClientModel::RestoreEntitiesUsingThisModel() void CClientModel::RestoreDFF(CModelInfo* pModelInfo) { + auto callElementChangeEvent = [](auto &element, unsigned short usParentID, auto modelId) { + CLuaArguments Arguments; + Arguments.PushNumber(modelId); + Arguments.PushNumber(usParentID); + element.CallEvent("onClientElementModelChange", Arguments, true); + }; + auto unloadModelsAndCallEvents = [&](auto iterBegin, auto iterEnd, unsigned short usParentID, auto setElementModelLambda) { for (auto iter = iterBegin; iter != iterEnd; iter++) { @@ -135,10 +144,21 @@ void CClientModel::RestoreDFF(CModelInfo* pModelInfo) setElementModelLambda(element); - CLuaArguments Arguments; - Arguments.PushNumber(m_iModelID); - Arguments.PushNumber(usParentID); - element.CallEvent("onClientElementModelChange", Arguments, true); + callElementChangeEvent(element, usParentID, m_iModelID); + } + }; + + auto unloadModelsAndCallEventsNonStreamed = [&](auto iterBegin, auto iterEnd, unsigned short usParentID, auto setElementModelLambda) + { + for (auto iter = iterBegin; iter != iterEnd; iter++) + { + auto& element = **iter; + + if (element.GetModel() != m_iModelID) + continue; + + setElementModelLambda(element); + callElementChangeEvent(element, usParentID, m_iModelID); } }; @@ -166,6 +186,12 @@ void CClientModel::RestoreDFF(CModelInfo* pModelInfo) unloadModelsAndCallEvents(pPickupManager->IterBegin(), pPickupManager->IterEnd(), usParentID, [=](auto& element) { element.SetModel(usParentID); }); + // Restore buildings + CClientBuildingManager* pBuildingsManager = g_pClientGame->GetManager()->GetBuildingManager(); + auto& buildingsList = pBuildingsManager->GetBuildings(); + unloadModelsAndCallEventsNonStreamed(buildingsList.begin(), buildingsList.end(), usParentID, + [=](auto& element) { element.SetModel(usParentID); }); + // Restore COL g_pClientGame->GetManager()->GetColModelManager()->RestoreModel(m_iModelID); break; diff --git a/Client/mods/deathmatch/logic/CClientModelManager.cpp b/Client/mods/deathmatch/logic/CClientModelManager.cpp index 21d795e964..36c601b544 100644 --- a/Client/mods/deathmatch/logic/CClientModelManager.cpp +++ b/Client/mods/deathmatch/logic/CClientModelManager.cpp @@ -49,6 +49,9 @@ bool CClientModelManager::Remove(const std::shared_ptr& pModel) int modelId = pModel->GetModelID(); if (m_Models[modelId] != nullptr) { + CResource* parentResource = m_Models[modelId]->GetParentResource(); + if (parentResource) + parentResource->GetResourceModelStreamer()->FullyReleaseModel(modelId); m_Models[modelId]->RestoreEntitiesUsingThisModel(); m_Models[modelId] = nullptr; m_modelCount--; diff --git a/Client/mods/deathmatch/logic/CClientObject.cpp b/Client/mods/deathmatch/logic/CClientObject.cpp index 27eacc0efa..7d34045f1b 100644 --- a/Client/mods/deathmatch/logic/CClientObject.cpp +++ b/Client/mods/deathmatch/logic/CClientObject.cpp @@ -400,9 +400,11 @@ void CClientObject::SetScale(const CVector& vecScale) void CClientObject::SetCollisionEnabled(bool bCollisionEnabled) { if (m_pObject) - { m_pObject->SetUsesCollision(bCollisionEnabled); - } + + // Remove all contacts + for (const auto& ped : m_Contacts) + RemoveContact(ped); m_bUsesCollision = bCollisionEnabled; } diff --git a/Client/mods/deathmatch/logic/CClientPed.cpp b/Client/mods/deathmatch/logic/CClientPed.cpp index 1eaaa5c796..5716bea120 100644 --- a/Client/mods/deathmatch/logic/CClientPed.cpp +++ b/Client/mods/deathmatch/logic/CClientPed.cpp @@ -1761,6 +1761,11 @@ void CClientPed::InternalSetHealth(float fHealth) } else { + // Ped is alive again (Fix #414) + UnlockHealth(); + UnlockArmor(); + SetIsDead(false); + // Recreate the player ReCreateModel(); } @@ -3325,7 +3330,7 @@ void CClientPed::SetTargetRotation(unsigned long ulDelay, float fRotation, float { m_ulBeginRotationTime = CClientTime::GetTime(); m_ulEndRotationTime = m_ulBeginRotationTime + ulDelay; - m_fBeginRotation = (m_pPlayerPed) ? m_pPlayerPed->GetTargetRotation() : m_fCurrentRotation; + m_fBeginRotation = (m_pPlayerPed) ? m_pPlayerPed->GetCurrentRotation() : m_fCurrentRotation; m_fTargetRotationA = fRotation; m_fBeginCameraRotation = GetCameraRotation(); m_fTargetCameraRotation = fCameraRotation; @@ -3383,23 +3388,24 @@ void CClientPed::Interpolate() { // We're not at the end? if (ulCurrentTime < m_ulEndRotationTime) - { - // Interpolate the player rotation - float fDeltaTime = float(m_ulEndRotationTime - m_ulBeginRotationTime); - float fDelta = GetOffsetDegrees(m_fBeginRotation, m_fTargetRotationA); - float fCameraDelta = GetOffsetDegrees(m_fBeginCameraRotation, m_fTargetCameraRotation); - float fProgress = float(ulCurrentTime - m_ulBeginRotationTime); - float fNewRotation = m_fBeginRotation + (fDelta / fDeltaTime * fProgress); - float fNewCameraRotation = m_fBeginCameraRotation + (fCameraDelta / fDeltaTime * fProgress); + { + const float fDelta = GetOffsetRadians(m_fBeginRotation, m_fTargetRotationA); // Hack for the wrap-around (the edge seems to be varying...) - if (fDelta < -5.0f || fDelta > 5.0f) + if (fDelta < -M_PI || fDelta > M_PI) { SetCurrentRotation(m_fTargetRotationA); SetCameraRotation(m_fTargetCameraRotation); } else { + // Interpolate the player rotation + const float fDeltaTime = float(m_ulEndRotationTime - m_ulBeginRotationTime); + const float fCameraDelta = GetOffsetRadians(m_fBeginCameraRotation, m_fTargetCameraRotation); + const float fProgress = float(ulCurrentTime - m_ulBeginRotationTime); + const float fNewRotation = m_fBeginRotation + fDelta * (fProgress / fDeltaTime); + const float fNewCameraRotation = m_fBeginCameraRotation + fCameraDelta * (fProgress / fDeltaTime); + SetCurrentRotation(fNewRotation); SetCameraRotation(fNewCameraRotation); } @@ -3867,6 +3873,10 @@ void CClientPed::_ChangeModel() SetStat(23, 0.0f); } + // Store attached satchels + std::vector attachedSatchels; + m_pPlayerPed->GetAttachedSatchels(attachedSatchels); + if (m_bIsLocalPlayer) { // TODO: Create a simple function to save and restore player states and use it @@ -3917,22 +3927,7 @@ void CClientPed::_ChangeModel() // So make sure clothes geometry is built now... m_pClothes->AddAllToModel(); m_pPlayerPed->RebuildPlayer(); - - // ...and decrement the extra ref - #ifdef NO_CRASH_FIX_TEST2 - m_pPlayerPed->RemoveGeometryRef(); - #endif - } - else - { - // When the local player changes to another (non CJ) model, the geometry gets an extra ref from somewhere, causing a memory leak. - // So decrement the extra ref here - #ifdef NO_CRASH_FIX_TEST - m_pPlayerPed->RemoveGeometryRef(); - #endif - // As we will have problem removing the geometry later, we might as well keep the model cached until exit - g_pCore->AddModelToPersistentCache((ushort)m_ulModel); - } + } // Remove reference to the old model we used (Flag extra GTA reference to be removed as well) pLoadedModel->RemoveRef(true); @@ -3981,6 +3976,19 @@ void CClientPed::_ChangeModel() _CreateModel(); } + // ReAttach satchels + CClientProjectileManager* pProjectileManager = m_pManager->GetProjectileManager(); + + for (const SSatchelsData& satchelData : attachedSatchels) + { + CClientProjectile* pSatchel = pProjectileManager->Get((CEntitySAInterface*)satchelData.pProjectileInterface); + if (!pSatchel || pSatchel->IsBeingDeleted()) + continue; + + pSatchel->SetAttachedOffsets(*satchelData.vecAttachedOffsets, *satchelData.vecAttachedRotation); + pSatchel->InternalAttachTo(this); + } + g_pMultiplayer->SetAutomaticVehicleStartupOnPedEnter(true); } if (m_clientModel && m_clientModel->GetModelID() != m_ulModel) @@ -5204,6 +5212,8 @@ void CClientPed::Respawn(CVector* pvecPosition, bool bRestoreState, bool bCamera float fTargetRotation = m_pPlayerPed->GetTargetRotation(); unsigned char ucInterior = GetInterior(); unsigned char ucCameraInterior = static_cast(g_pGame->GetWorld()->GetCurrentArea()); + bool bOldNightVision = g_pMultiplayer->IsNightVisionEnabled(); + bool bOldThermalVision = g_pMultiplayer->IsThermalVisionEnabled(); // Don't allow any camera movement if we're in fixed mode if (m_pManager->GetCamera()->IsInFixedMode()) @@ -5214,6 +5224,9 @@ void CClientPed::Respawn(CVector* pvecPosition, bool bRestoreState, bool bCamera m_pPlayerPed->SetLanding(false); + // Set it to 0 (Fix #501) + SetCurrentWeaponSlot(eWeaponSlot::WEAPONSLOT_TYPE_UNARMED); + if (bRestoreState) { // Jax: restore all the things we saved @@ -5229,6 +5242,10 @@ void CClientPed::Respawn(CVector* pvecPosition, bool bRestoreState, bool bCamera // Restore the camera's interior whether we're restoring player states or not g_pGame->GetWorld()->SetCurrentArea(ucCameraInterior); + // Reset goggle effect + g_pMultiplayer->SetNightVisionEnabled(bOldNightVision, false); + g_pMultiplayer->SetThermalVisionEnabled(bOldThermalVision, false); + // Reattach us if (pAttachedTo && pAttachedTo->IsEntityAttached(this)) InternalAttachTo(pAttachedTo); diff --git a/Client/mods/deathmatch/logic/CClientPed.h b/Client/mods/deathmatch/logic/CClientPed.h index 5b8f8e9527..688dba501f 100644 --- a/Client/mods/deathmatch/logic/CClientPed.h +++ b/Client/mods/deathmatch/logic/CClientPed.h @@ -165,16 +165,16 @@ class CClientPed : public CClientStreamElement, public CAntiCheatModule CClientPed(CClientManager* pManager, unsigned long ulModelID, ElementID ID); ~CClientPed(); - void Unlink(){}; + void Unlink() {}; virtual eClientEntityType GetType() const { return CCLIENTPED; } - CPlayerPed* GetGamePlayer() { return m_pPlayerPed; } - CEntity* GetGameEntity() { return m_pPlayerPed; } - const CEntity* GetGameEntity() const { return m_pPlayerPed; } + CPlayerPed* GetGamePlayer() noexcept { return m_pPlayerPed; } + CEntity* GetGameEntity() noexcept { return m_pPlayerPed; } + const CEntity* GetGameEntity() const noexcept { return m_pPlayerPed; } - bool IsLocalPlayer() { return m_bIsLocalPlayer; } - bool IsSyncing() { return m_bIsSyncing; } + bool IsLocalPlayer() const noexcept { return m_bIsLocalPlayer; } + bool IsSyncing() const noexcept { return m_bIsSyncing; } void SetSyncing(bool bIsSyncing); bool GetMatrix(CMatrix& Matrix) const; @@ -182,7 +182,7 @@ class CClientPed : public CClientStreamElement, public CAntiCheatModule virtual CSphere GetWorldBoundingSphere(); void GetPosition(CVector& vecPosition) const; - void SetPosition(const CVector& vecPosition) { SetPosition(vecPosition, true, true); } + void SetPosition(const CVector& vecPosition) noexcept { SetPosition(vecPosition, true, true); } void SetPosition(const CVector& vecPosition, bool bResetInterpolation, bool bAllowGroundLoadFreeze = true); void SetInterior(unsigned char ucInterior); @@ -231,19 +231,24 @@ class CClientPed : public CClientStreamElement, public CAntiCheatModule void SetTargetTarget(unsigned long ulDelay, const CVector& vecSource, const CVector& vecTarget); - int GetVehicleInOutState() { return m_iVehicleInOutState; }; - void SetVehicleInOutState(int iState) { m_iVehicleInOutState = iState; }; + int GetVehicleInOutState() const noexcept { return m_iVehicleInOutState; }; + void SetVehicleInOutState(int iState) noexcept { m_iVehicleInOutState = iState; }; - unsigned long GetModel() { return m_ulModel; }; + unsigned long GetModel() const noexcept { return m_ulModel; }; bool SetModel(unsigned long ulModel, bool bTemp = false); bool GetCanBeKnockedOffBike(); void SetCanBeKnockedOffBike(bool bCanBeKnockedOffBike); - bool IsInVehicle() { return GetOccupiedVehicle() != NULL; }; - CClientVehicle* GetOccupiedVehicle() { return m_pOccupiedVehicle; }; - unsigned int GetOccupiedVehicleSeat() { return m_uiOccupiedVehicleSeat; }; - CClientVehicle* GetOccupyingVehicle() { return m_pOccupyingVehicle; }; + bool IsInVehicle() const noexcept { return GetOccupiedVehicle() != NULL; }; + + CClientVehicle* GetOccupiedVehicle() noexcept { return m_pOccupiedVehicle; }; + const CClientVehicle* GetOccupiedVehicle() const noexcept { return m_pOccupiedVehicle; }; + + unsigned int GetOccupiedVehicleSeat() const noexcept { return m_uiOccupiedVehicleSeat; }; + + CClientVehicle* GetOccupyingVehicle() noexcept { return m_pOccupyingVehicle; }; + const CClientVehicle* GetOccupyingVehicle() const noexcept { return m_pOccupyingVehicle; }; CClientVehicle* GetRealOccupiedVehicle(); CClientVehicle* GetClosestEnterableVehicle(bool bGetPositionFromClosestDoor, bool bCheckDriverDoor, bool bCheckPassengerDoors, @@ -274,21 +279,21 @@ class CClientPed : public CClientStreamElement, public CAntiCheatModule void LockHealth(float fHealth); void LockArmor(float fArmor); - void UnlockHealth() { m_bHealthLocked = false; }; - void UnlockArmor() { m_bArmorLocked = false; }; - bool IsHealthLocked() const { return m_bHealthLocked; }; - bool IsArmorLocked() const { return m_bArmorLocked; }; + void UnlockHealth() noexcept { m_bHealthLocked = false; }; + void UnlockArmor() noexcept { m_bArmorLocked = false; }; + bool IsHealthLocked() const noexcept { return m_bHealthLocked; }; + bool IsArmorLocked() const noexcept { return m_bArmorLocked; }; bool IsDying(); bool IsDead(); - void SetIsDead(bool bDead) { m_bDead = bDead; }; + void SetIsDead(bool bDead) noexcept { m_bDead = bDead; }; void Kill(eWeaponType weaponType, unsigned char ucBodypart, bool bStealth = false, bool bSetDirectlyDead = false, AssocGroupId animGroup = 0, AnimationId animID = 15); void StealthKill(CClientPed* pPed); void BeHit(CClientPed* pClientPedAttacker, ePedPieceTypes hitBodyPart, int hitBodySide, int weaponId); - int GetRespawnState() { return m_pRespawnState; }; - void SetRespawnState(int iRespawnState) { m_pRespawnState = iRespawnState; }; + int GetRespawnState() const noexcept { return m_pRespawnState; }; + void SetRespawnState(int iRespawnState) noexcept { m_pRespawnState = iRespawnState; }; CWeapon* GiveWeapon(eWeaponType weaponType, unsigned int uiAmmo, bool bSetAsCurrent = false); bool SetCurrentWeaponSlot(eWeaponSlot weaponSlot); @@ -328,9 +333,9 @@ class CClientPed : public CClientStreamElement, public CAntiCheatModule } }; CVector GetAim() const; - const CVector& GetAimSource() { return m_shotSyncData->m_vecShotOrigin; }; - const CVector& GetAimTarget() { return m_shotSyncData->m_vecShotTarget; }; - eVehicleAimDirection GetVehicleAimAnim() { return m_shotSyncData->m_cInVehicleAimDirection; }; + const CVector& GetAimSource() const noexcept { return m_shotSyncData->m_vecShotOrigin; }; + const CVector& GetAimTarget() const noexcept { return m_shotSyncData->m_vecShotTarget; }; + eVehicleAimDirection GetVehicleAimAnim() const noexcept { return m_shotSyncData->m_cInVehicleAimDirection; }; void SetAim(float fArmDirectionX, float fArmDirectionY, eVehicleAimDirection cInVehicleAimAnim); void SetAimInterpolated(unsigned long ulDelay, float fArmDirectionX, float fArmDirectionY, bool bAkimboAimUp, eVehicleAimDirection cInVehicleAimAnim); void SetAimingData(unsigned long ulDelay, const CVector& vecTargetPosition, float fArmDirectionX, float fArmDirectionY, @@ -356,7 +361,8 @@ class CClientPed : public CClientStreamElement, public CAntiCheatModule float GetStat(unsigned short usStat); void ResetStats(); - CClientPlayerClothes* GetClothes() { return m_pClothes; } + CClientPlayerClothes* GetClothes() noexcept { return m_pClothes; } + const CClientPlayerClothes* GetClothes() const noexcept { return m_pClothes; } // This is kinda hacky, should be private but something depends on this. Should depend on some // streamer func. Perhaps use SetNeverStreamOut, but need something to reset that. @@ -375,13 +381,14 @@ class CClientPed : public CClientStreamElement, public CAntiCheatModule bool IsOnGround(); bool IsClimbing(); - bool IsRadioOn() { return m_bRadioOn; }; + bool IsRadioOn() const noexcept { return m_bRadioOn; }; void NextRadioChannel(); void PreviousRadioChannel(); bool SetCurrentRadioChannel(unsigned char ucChannel); - unsigned char GetCurrentRadioChannel() { return m_ucRadioChannel; }; + unsigned char GetCurrentRadioChannel() const noexcept { return m_ucRadioChannel; }; - CTaskManager* GetTaskManager() { return m_pTaskManager; } + CTaskManager* GetTaskManager() noexcept { return m_pTaskManager; } + const CTaskManager* GetTaskManager() const noexcept { return m_pTaskManager; } bool GetShotData(CVector* pvecOrigin, CVector* pvecTarget = NULL, CVector* pvecGunMuzzle = NULL, CVector* pvecFireOffset = NULL, float* fAimX = NULL, float* fAimY = NULL); @@ -399,10 +406,14 @@ class CClientPed : public CClientStreamElement, public CAntiCheatModule std::list::iterator ProjectilesEnd() { return m_Projectiles.end(); } unsigned int CountProjectiles(eWeaponType weaponType = WEAPONTYPE_UNARMED); + std::list& GetProjectiles() noexcept { return m_Projectiles; } + const std::list& GetProjectiles() const noexcept { return m_Projectiles; } + void RemoveAllProjectiles(); void DestroySatchelCharges(bool bBlow = true, bool bDestroy = true); - CRemoteDataStorage* GetRemoteData() { return m_remoteDataStorage; } + CRemoteDataStorage* GetRemoteData() noexcept { return m_remoteDataStorage; } + const CRemoteDataStorage* GetRemoteData() const noexcept { return m_remoteDataStorage; } bool IsEnteringVehicle(); bool IsLeavingVehicle(); @@ -416,11 +427,12 @@ class CClientPed : public CClientStreamElement, public CAntiCheatModule float GetDistanceFromCentreOfMassToBaseOfModel(); - unsigned char GetAlpha() { return m_ucAlpha; } + unsigned char GetAlpha() const noexcept { return m_ucAlpha; } void SetAlpha(unsigned char ucAlpha); - bool HasTargetPosition() { return (m_interp.pos.ulFinishTime != 0); } - CClientEntity* GetTargetOriginSource() { return m_interp.pTargetOriginSource; } + bool HasTargetPosition() const noexcept { return m_interp.pos.ulFinishTime != 0; } + CClientEntity* GetTargetOriginSource() noexcept { return m_interp.pTargetOriginSource; } + const CClientEntity* GetTargetOriginSource() const noexcept { return m_interp.pTargetOriginSource; } void GetTargetPosition(CVector& vecPosition); void SetTargetPosition(const CVector& vecPosition, unsigned long ulDelay, CClientEntity* pTargetOriginSource = NULL); void RemoveTargetPosition(); @@ -430,8 +442,9 @@ class CClientPed : public CClientStreamElement, public CAntiCheatModule CClientEntity* GetTargetedEntity(); CClientPed* GetTargetedPed(); - CClientEntity* GetCurrentContactEntity() { return m_pCurrentContactEntity; } - void SetCurrentContactEntity(CClientEntity* pEntity) { m_pCurrentContactEntity = pEntity; } + CClientEntity* GetCurrentContactEntity() noexcept { return m_pCurrentContactEntity; } + const CClientEntity* GetCurrentContactEntity() const noexcept { return m_pCurrentContactEntity; } + void SetCurrentContactEntity(CClientEntity* pEntity) noexcept { m_pCurrentContactEntity = pEntity; } bool IsSunbathing(); void SetSunbathing(bool bSunbathing, bool bStartStanding = true); @@ -453,14 +466,14 @@ class CClientPed : public CClientStreamElement, public CAntiCheatModule bool bOffsetPed = false, bool bHoldLastFrame = false); void KillAnimation(); std::unique_ptr GetAnimationBlock(); - const SAnimationCache& GetAnimationCache() { return m_AnimationCache; } + const SAnimationCache& GetAnimationCache() const noexcept { return m_AnimationCache; } bool IsUsingGun(); - bool IsHeadless() { return m_bHeadless; } + bool IsHeadless() const noexcept { return m_bHeadless; } void SetHeadless(bool bHeadless); - bool IsFrozen() const { return m_bFrozen; } + bool IsFrozen() const noexcept { return m_bFrozen; } void SetFrozen(bool bFrozen); bool IsFrozenWaitingForGroundToLoad() const; void SetFrozenWaitingForGroundToLoad(bool bFrozen); @@ -468,7 +481,7 @@ class CClientPed : public CClientStreamElement, public CAntiCheatModule bool IsFootBloodEnabled(); void SetFootBloodEnabled(bool bHasFootBlood); - bool IsBleeding() const { return m_bBleeding; }; + bool IsBleeding() const noexcept { return m_bBleeding; }; void SetBleeding(bool bBleeding); bool IsOnFire(); @@ -502,27 +515,33 @@ class CClientPed : public CClientStreamElement, public CAntiCheatModule std::unique_ptr GetFirstAnimation(); void DereferenceCustomAnimationBlock() { m_pCustomAnimationIFP = nullptr; } - std::shared_ptr GetCustomAnimationIFP() { return m_pCustomAnimationIFP; } - bool IsCustomAnimationPlaying() { return ((m_bRequestedAnimation || m_AnimationCache.bLoop) && m_pAnimationBlock && m_bisCurrentAnimationCustom); } - void SetCustomAnimationUntriggerable() + std::shared_ptr GetCustomAnimationIFP() const noexcept { return m_pCustomAnimationIFP; } + bool IsCustomAnimationPlaying() noexcept + { + return (m_bRequestedAnimation || m_AnimationCache.bLoop) + && m_pAnimationBlock && m_bisCurrentAnimationCustom; + } + void SetCustomAnimationUntriggerable() noexcept { m_bRequestedAnimation = false; m_AnimationCache.bLoop = false; } - bool IsNextAnimationCustom() { return m_bisNextAnimationCustom; } + bool IsNextAnimationCustom() const noexcept { return m_bisNextAnimationCustom; } void SetNextAnimationCustom(const std::shared_ptr& pIFP, const SString& strAnimationName); - void SetCurrentAnimationCustom(bool bCustom) { m_bisCurrentAnimationCustom = bCustom; } - bool IsCurrentAnimationCustom() { return m_bisCurrentAnimationCustom; } - CIFPAnimations* GetIFPAnimationsPointer() { return m_pIFPAnimations; } - void SetIFPAnimationsPointer(CIFPAnimations* pIFPAnimations) { m_pIFPAnimations = pIFPAnimations; } + void SetCurrentAnimationCustom(bool bCustom) noexcept { m_bisCurrentAnimationCustom = bCustom; } + bool IsCurrentAnimationCustom() const noexcept { return m_bisCurrentAnimationCustom; } + CIFPAnimations* GetIFPAnimationsPointer() noexcept { return m_pIFPAnimations; } + const CIFPAnimations* GetIFPAnimationsPointer() const noexcept { return m_pIFPAnimations; } + + void SetIFPAnimationsPointer(CIFPAnimations* pIFPAnimations) noexcept { m_pIFPAnimations = pIFPAnimations; } // This will indicate that we have played custom animation, so next animation can be internal GTA animation // You must call this function after playing a custom animation - void SetNextAnimationNormal() { m_bisNextAnimationCustom = false; } - const SString& GetNextAnimationCustomBlockName() { return m_strCustomIFPBlockName; } - const SString& GetNextAnimationCustomName() { return m_strCustomIFPAnimationName; } - const unsigned int& GetCustomAnimationBlockNameHash() { return m_u32CustomBlockNameHash; } - const unsigned int& GetCustomAnimationNameHash() { return m_u32CustomAnimationNameHash; } + void SetNextAnimationNormal() noexcept { m_bisNextAnimationCustom = false; } + const SString& GetNextAnimationCustomBlockName() const noexcept { return m_strCustomIFPBlockName; } + const SString& GetNextAnimationCustomName() const noexcept { return m_strCustomIFPAnimationName; } + const unsigned int& GetCustomAnimationBlockNameHash() const noexcept { return m_u32CustomBlockNameHash; } + const unsigned int& GetCustomAnimationNameHash() const noexcept { return m_u32CustomAnimationNameHash; } void ReplaceAnimation(std::unique_ptr& pInternalAnimHierarchy, const std::shared_ptr& pIFP, CAnimBlendHierarchySAInterface* pCustomAnimHierarchy); @@ -579,13 +598,13 @@ class CClientPed : public CClientStreamElement, public CAntiCheatModule void Respawn(CVector* pvecPosition = NULL, bool bRestoreState = false, bool bCameraCut = false); - void SetTaskToBeRestoredOnAnimEnd(bool bSetOnEnd) { m_bTaskToBeRestoredOnAnimEnd = bSetOnEnd; } - bool IsTaskToBeRestoredOnAnimEnd() { return m_bTaskToBeRestoredOnAnimEnd; } - void SetTaskTypeToBeRestoredOnAnimEnd(eTaskType taskType) { m_eTaskTypeToBeRestoredOnAnimEnd = taskType; } - eTaskType GetTaskTypeToBeRestoredOnAnimEnd() { return m_eTaskTypeToBeRestoredOnAnimEnd; } + void SetTaskToBeRestoredOnAnimEnd(bool bSetOnEnd) noexcept { m_bTaskToBeRestoredOnAnimEnd = bSetOnEnd; } + bool IsTaskToBeRestoredOnAnimEnd() const noexcept { return m_bTaskToBeRestoredOnAnimEnd; } + void SetTaskTypeToBeRestoredOnAnimEnd(eTaskType taskType) noexcept { m_eTaskTypeToBeRestoredOnAnimEnd = taskType; } + eTaskType GetTaskTypeToBeRestoredOnAnimEnd() const noexcept { return m_eTaskTypeToBeRestoredOnAnimEnd; } - bool IsWarpInToVehicleRequired() { return m_bWarpInToVehicleRequired; } - void SetWarpInToVehicleRequired(bool warp) { m_bWarpInToVehicleRequired = warp; } + bool IsWarpInToVehicleRequired() const noexcept { return m_bWarpInToVehicleRequired; } + void SetWarpInToVehicleRequired(bool warp) noexcept { m_bWarpInToVehicleRequired = warp; } void NotifyCreate(); void NotifyDestroy(); diff --git a/Client/mods/deathmatch/logic/CClientPlayer.h b/Client/mods/deathmatch/logic/CClientPlayer.h index 15327790e0..bef1f26497 100644 --- a/Client/mods/deathmatch/logic/CClientPlayer.h +++ b/Client/mods/deathmatch/logic/CClientPlayer.h @@ -111,6 +111,9 @@ class CClientPlayer final : public CClientPed bool GetWasRecentlyInNetworkInterruption(uint uiMaxTicksAgo); void SetIsInNetworkInterruption(bool bInNetworkInterruption); + std::uint8_t GetPlayerScriptDebugLevel() const noexcept { return m_scriptDebugLevel; } + void SetPlayerScriptDebugLevel(std::uint8_t level) noexcept { m_scriptDebugLevel = level; } + CVector m_vecPrevBulletSyncStart; CVector m_vecPrevBulletSyncEnd; uchar m_ucPrevBulletSyncOrderCounter; @@ -136,6 +139,8 @@ class CClientPlayer final : public CClientPed unsigned long m_ulTick; bool m_bDoExtrapolatingAim; + std::uint8_t m_scriptDebugLevel{}; + bool m_bForce; CVector m_vecForcedMoveSpeed; CVector m_vecForcedTurnSpeed; diff --git a/Client/mods/deathmatch/logic/CClientSound.cpp b/Client/mods/deathmatch/logic/CClientSound.cpp index dc10132e4b..052071a97a 100644 --- a/Client/mods/deathmatch/logic/CClientSound.cpp +++ b/Client/mods/deathmatch/logic/CClientSound.cpp @@ -147,6 +147,10 @@ bool CClientSound::Create() m_pAudio->SetPanEnabled(m_bPan); m_pAudio->SetPan(m_fPan); + // Also check and transfer if paused + if (m_bPaused) + m_pAudio->SetPaused(m_bPaused); + // Transfer play position if it was being simulated EndSimulationOfPlayPositionAndApply(); diff --git a/Client/mods/deathmatch/logic/CClientVehicle.cpp b/Client/mods/deathmatch/logic/CClientVehicle.cpp index db77e1fdb7..e0e27dd417 100644 --- a/Client/mods/deathmatch/logic/CClientVehicle.cpp +++ b/Client/mods/deathmatch/logic/CClientVehicle.cpp @@ -13,6 +13,7 @@ #include #include #include +#include #include #include #include @@ -161,6 +162,7 @@ CClientVehicle::CClientVehicle(CClientManager* pManager, ElementID ID, unsigned m_HeadLightColor = SColorRGBA(255, 255, 255, 255); m_bHeliSearchLightVisible = false; m_fHeliRotorSpeed = 0.0f; + m_fPlaneRotorSpeed = 0.0f; m_bHasCustomHandling = false; m_ucVariation = ucVariation; m_ucVariation2 = ucVariation2; @@ -1463,7 +1465,8 @@ void CClientVehicle::SetWheelStatus(unsigned char ucWheel, unsigned char ucStatu m_pVehicle->GetDamageManager()->SetWheelStatus((eWheelPosition)(ucWheel), ucGTAStatus); // Update the wheel's visibility - m_pVehicle->SetWheelVisibility((eWheelPosition)ucWheel, (ucStatus != DT_WHEEL_MISSING)); + m_pVehicle->SetWheelVisibility((eWheelPosition)ucWheel, ucStatus != DT_WHEEL_MISSING && + (m_ComponentData.empty() || m_ComponentData[GetComponentNameForWheel(ucWheel)].m_bVisible)); } else if (m_eVehicleType == CLIENTVEHICLE_BIKE && ucWheel < 2) m_pVehicle->SetBikeWheelStatus(ucWheel, ucGTAStatus); @@ -1472,6 +1475,26 @@ void CClientVehicle::SetWheelStatus(unsigned char ucWheel, unsigned char ucStatu } } +// +// Returns component name for eWheelPosition enum +// +SString CClientVehicle::GetComponentNameForWheel(unsigned char ucWheel) const noexcept +{ + switch (ucWheel) + { + case FRONT_LEFT_WHEEL: + return "wheel_lf_dummy"; + case FRONT_RIGHT_WHEEL: + return "wheel_rf_dummy"; + case REAR_LEFT_WHEEL: + return "wheel_lb_dummy"; + case REAR_RIGHT_WHEEL: + return "wheel_rb_dummy"; + default: + return ""; + } +} + // // Returns true if wheel should be invisible because of its state // @@ -1537,6 +1560,14 @@ float CClientVehicle::GetHeliRotorSpeed() return m_fHeliRotorSpeed; } +float CClientVehicle::GetPlaneRotorSpeed() +{ + if (m_pVehicle && m_eVehicleType == CLIENTVEHICLE_PLANE) + return m_pVehicle->GetPlaneRotorSpeed(); + + return m_fPlaneRotorSpeed; +} + void CClientVehicle::SetHeliRotorSpeed(float fSpeed) { if (m_pVehicle && m_eVehicleType == CLIENTVEHICLE_HELI) @@ -1545,6 +1576,53 @@ void CClientVehicle::SetHeliRotorSpeed(float fSpeed) m_fHeliRotorSpeed = fSpeed; } +void CClientVehicle::SetPlaneRotorSpeed(float fSpeed) +{ + if (m_pVehicle && m_eVehicleType == CLIENTVEHICLE_PLANE) + m_pVehicle->SetPlaneRotorSpeed(fSpeed); + + m_fPlaneRotorSpeed = fSpeed; +} + +bool CClientVehicle::GetRotorSpeed(float& speed) +{ + if (m_eVehicleType == CLIENTVEHICLE_PLANE) + { + speed = GetPlaneRotorSpeed(); + return true; + } + else if (m_eVehicleType == CLIENTVEHICLE_HELI) + { + speed = GetHeliRotorSpeed(); + return true; + } + + return false; +} + +bool CClientVehicle::SetRotorSpeed(float fSpeed) +{ + switch (m_eVehicleType) + { + case CLIENTVEHICLE_HELI: + SetHeliRotorSpeed(fSpeed); + return true; + case CLIENTVEHICLE_PLANE: + SetPlaneRotorSpeed(fSpeed); + return true; + default: + return false; + } +} + +bool CClientVehicle::SetWheelsRotation(float fRot1, float fRot2, float fRot3, float fRot4) noexcept +{ + if (!m_pVehicle) + return false; + + return m_pVehicle->SetVehicleWheelRotation(fRot1, fRot2, fRot3, fRot4); +} + bool CClientVehicle::IsHeliSearchLightVisible() { if (m_pVehicle && m_eVehicleType == CLIENTVEHICLE_HELI) @@ -1566,6 +1644,10 @@ void CClientVehicle::SetCollisionEnabled(bool bCollisionEnabled) if (m_pVehicle && m_bHasAdjustableProperty) m_pVehicle->SetUsesCollision(bCollisionEnabled); + // Remove all contacts + for (const auto& ped : m_Contacts) + RemoveContact(ped); + m_bIsCollisionEnabled = bCollisionEnabled; } @@ -4954,3 +5036,17 @@ void CClientVehicle::ResetWheelScale() m_bWheelScaleChanged = false; } + +CVector CClientVehicle::GetEntryPoint(std::uint32_t entryPointIndex) +{ + static const uint32_t lookup[4] = {10, 8, 11, 9}; + assert(entryPointIndex < 4); + const std::uint32_t saDoorIndex = lookup[entryPointIndex]; + + CVector entryPoint; + CVehicle* gameVehicle = GetGameVehicle(); + + g_pGame->GetCarEnterExit()->GetPositionToOpenCarDoor(entryPoint, gameVehicle, saDoorIndex); + + return entryPoint; +} diff --git a/Client/mods/deathmatch/logic/CClientVehicle.h b/Client/mods/deathmatch/logic/CClientVehicle.h index 5002567eb5..e2c83c618e 100644 --- a/Client/mods/deathmatch/logic/CClientVehicle.h +++ b/Client/mods/deathmatch/logic/CClientVehicle.h @@ -286,6 +286,7 @@ class CClientVehicle : public CClientStreamElement int GetWheelFrictionState(unsigned char ucWheel); unsigned char GetPanelStatus(unsigned char ucPanel); unsigned char GetLightStatus(unsigned char ucLight); + SString GetComponentNameForWheel(unsigned char ucWheel) const noexcept; bool AreLightsOn(); @@ -297,8 +298,13 @@ class CClientVehicle : public CClientStreamElement // TODO: Make the class remember on virtualization float GetHeliRotorSpeed(); - void SetHeliRotorSpeed(float fSpeed); + float GetPlaneRotorSpeed(); + bool GetRotorSpeed(float&); + bool SetRotorSpeed(float); + bool SetWheelsRotation(float fRot1, float fRot2, float fRot3, float fRot4) noexcept; + void SetHeliRotorSpeed(float fSpeed); + void SetPlaneRotorSpeed(float fSpeed); bool IsHeliSearchLightVisible(); void SetHeliSearchLightVisible(bool bVisible); @@ -537,6 +543,8 @@ class CClientVehicle : public CClientStreamElement bool SetDummyPosition(eVehicleDummies dummy, const CVector& position); bool ResetDummyPositions(); + CVector GetEntryPoint(std::uint32_t entryPointIndex); + protected: void ConvertComponentRotationBase(const SString& vehicleComponent, CVector& vecInOutRotation, EComponentBaseType inputBase, EComponentBaseType outputBase); void ConvertComponentPositionBase(const SString& vehicleComponent, CVector& vecInOutPosition, EComponentBaseType inputBase, EComponentBaseType outputBase); @@ -641,6 +649,7 @@ class CClientVehicle : public CClientStreamElement bool m_bIsOnGround; bool m_bHeliSearchLightVisible; float m_fHeliRotorSpeed; + float m_fPlaneRotorSpeed; const CHandlingEntry* m_pOriginalHandlingEntry = nullptr; CHandlingEntry* m_pHandlingEntry = nullptr; const CFlyingHandlingEntry* m_pOriginalFlyingHandlingEntry = nullptr; diff --git a/Client/mods/deathmatch/logic/CDynamicLibrary.cpp b/Client/mods/deathmatch/logic/CDynamicLibrary.cpp index 69ad0e3072..a6a9c0d762 100644 --- a/Client/mods/deathmatch/logic/CDynamicLibrary.cpp +++ b/Client/mods/deathmatch/logic/CDynamicLibrary.cpp @@ -10,6 +10,7 @@ *****************************************************************************/ #include +#include "CDynamicLibrary.h" CDynamicLibrary::CDynamicLibrary() { diff --git a/Client/mods/deathmatch/logic/CFoo.cpp b/Client/mods/deathmatch/logic/CFoo.cpp deleted file mode 100644 index 970a23a6f8..0000000000 --- a/Client/mods/deathmatch/logic/CFoo.cpp +++ /dev/null @@ -1,548 +0,0 @@ -/***************************************************************************** - * - * PROJECT: Multi Theft Auto v1.0 - * LICENSE: See LICENSE in the top level directory - * FILE: mods/deathmatch/logic/CFoo.cpp - * PURPOSE: Debugging class (not used in Release mode) - * - * Multi Theft Auto is available from http://www.multitheftauto.com/ - * - *****************************************************************************/ - -#include - -#ifdef MTA_DEBUG - -bool bFoo_PlayerLimitCrash = false; - -void CFoo::DoPulse() -{ - CClientManager* pManager = g_pClientGame->GetManager(); - if (pManager->IsGameLoaded()) - { - CClientPlayerManager* pPlayerManager = pManager->GetPlayerManager(); - CClientPlayer* pLocal = pManager->GetPlayerManager()->GetLocalPlayer(); - if (!pLocal) - return; - CVector vecLocal; - pLocal->GetPosition(vecLocal); - CClientCamera* pCamera = pManager->GetCamera(); - - /* - CClientVehicle* pVehicle = pLocal->GetOccupiedVehicle (); - if ( pVehicle ) - { - unsigned char ucGear = pVehicle->GetGameVehicle ()->GetCurrentGear (); - g_pCore->GetGraphics ()->DrawString ( 200, 200, 0xFFFFFFFF, 1.0f, "Gear = %u", ucGear ); - } - */ - - // ChrML: Reproduces issue #2741 - if (bFoo_PlayerLimitCrash) - { - static CClientPed* pPed = NULL; - if (!pPed) - { - pPed = new CClientPlayer(pManager, 50); - - CVector vecLocal; - pPlayerManager->GetLocalPlayer()->GetPosition(vecLocal); - vecLocal.fX += 10; - pPed->SetPosition(vecLocal); - } - - static unsigned long ulTestTime = 0; - if (ulTestTime == 0) - { - ulTestTime = CClientTime::GetTime() + 50; - } - - if (CClientTime::GetTime() > ulTestTime) - { - ulTestTime = CClientTime::GetTime() + 50; - - static unsigned int uiIndex = 0; - ++uiIndex; - - pPed->SetModel(uiIndex); - - if (uiIndex > 290) - uiIndex = 0; - } - } - } -} - -class CAnim -{ -}; - -class CAnimGroup -{ -public: - char szGroupName[16]; - char szSomething[16]; - unsigned long ulUnknown; // 0x07 or 0xFFFFFFFF on the first ones - unsigned long ulAnimCount; // ?? - const char** pAnimNames; - void* pSomeArray; -}; - -CAnimGroup* pGroups = (CAnimGroup*)0x008AA5A8; - -void CFoo::Test(const char* szString) -{ - CClientManager* pManager = g_pClientGame->GetManager(); - CClientPlayer* pLocal = pManager->GetPlayerManager()->GetLocalPlayer(); - CClientVehicleManager* pVehicleManager = pManager->GetVehicleManager(); - CVector vecLocal; - pLocal->GetPosition(vecLocal); - CClientCamera* pCamera = pManager->GetCamera(); - - // ChrML: Trying to reproduce mantis issue #2760 - if (stricmp(szString, "2760") == 0) - { - vecLocal = CVector(0.0f, 0.0f, 5.0f); - - for (int i = 0; i < 20; i++) - { - vecLocal.fX += 5.0f; - CClientPlayer* pPlayer = new CClientPlayer(pManager, i + 50); - pPlayer->SetDeadOnNetwork(false); - pPlayer->SetModel(168 + i); - pPlayer->AttachTo(NULL); - pPlayer->SetFrozen(false); - pPlayer->RemoveAllWeapons(); - pPlayer->Teleport(vecLocal); - pPlayer->SetCameraRotation(0); - pPlayer->ResetInterpolation(); - pPlayer->SetMoveSpeed(CVector()); - pPlayer->SetHealth(100.0f); - pPlayer->SetArmor(0); - pPlayer->SetCurrentRotation(0); - pPlayer->SetInterior(0); - pPlayer->SetDimension(0); - } - - pLocal->SetDeadOnNetwork(false); - pLocal->SetModel(145); - pLocal->AttachTo(NULL); - pLocal->SetFrozen(false); - pLocal->RemoveAllWeapons(); - pLocal->Teleport(vecLocal); - pLocal->SetCameraRotation(0); - pLocal->ResetInterpolation(); - pLocal->SetMoveSpeed(CVector()); - pLocal->SetHealth(100.0f); - pLocal->SetArmor(0); - pLocal->SetCurrentRotation(0); - pLocal->SetInterior(0); - pLocal->SetDimension(0); - g_pClientGame->SetAllDimensions(0); - - // Reset return position so we can't warp back to where we were if local player - g_pClientGame->GetNetAPI()->ResetReturnPosition(); - - // Make sure the camera is normal - pCamera->SetFocusToLocalPlayer(); - pCamera->FadeIn(0.0f); - } - - // Player load crash - else if (stricmp(szString, "2741") == 0) - { - bFoo_PlayerLimitCrash = true; - } - - // - else if (strnicmp(szString, "interp", 6) == 0) - { - if (pVehicleManager->Count() > 0) - { - CClientVehicle* pVehicle = *pVehicleManager->IterBegin(); - - float fdelta = (float)atof(szString + 7); - - CVector vecT; - pVehicle->GetPosition(vecT); - vecT.fZ = fdelta; - pVehicle->SetTargetPosition(vecT, TICK_RATE); - - g_pCore->ChatPrintf("Done %f", false, fdelta); - - static_cast(pVehicle)->SetIsSyncing(false); - } - } - - // - else if (strnicmp(szString, "interr", 6) == 0) - { - if (pVehicleManager->Count() > 0) - { - CClientVehicle* pVehicle = *pVehicleManager->IterBegin(); - - CVector vecT; - pVehicle->GetRotationDegrees(vecT); - vecT.fZ = (float)atof(szString + 7); - pVehicle->SetTargetRotation(vecT, TICK_RATE); - - g_pCore->ChatPrintf("Done %f", false, atof(szString + 7)); - - static_cast(pVehicle)->SetIsSyncing(false); - } - } - - else if (stricmp(szString, "choke") == 0) - { - if (g_pClientGame->GetLocalPlayer()) - g_pClientGame->GetLocalPlayer()->SetChoking(true); - } - - // - else if (strnicmp(szString, "static", 6) == 0) - { - if (pVehicleManager->Count() > 0) - { - CClientVehicle* pVehicle = *pVehicleManager->IterBegin(); - - pVehicle->GetGameVehicle()->SetRemap(atoi(szString + 7)); - g_pCore->ChatPrintf("Set %i", false, atoi(szString + 7)); - } - } - - // - else if (strnicmp(szString, "getmass", 7) == 0) - { - CClientVehicle* pVehicle = pLocal->GetOccupiedVehicle(); - if (pVehicle) - { - g_pCore->ChatPrintf("Mass == %f", false, pVehicle->GetGameVehicle()->GetMass()); - } - } - - else if (strnicmp(szString, "setmass", 7) == 0) - { - CClientVehicle* pVehicle = pLocal->GetOccupiedVehicle(); - if (pVehicle) - { - pVehicle->GetGameVehicle()->SetMass((float)atof(szString + 8)); - g_pCore->ChatPrintf("Set mass to %f", false, pVehicle->GetGameVehicle()->GetMass()); - } - } - - // - /* - else if ( strnicmp ( szString, "setmm", 5 ) == 0 ) - { - CClientVehicle* pVehicle = pLocal->GetOccupiedVehicle (); - if ( pVehicle ) - { - float fVal = atof ( szString + 6); - szString += 4; - float* fMass = (float*) atoi ( szString + 6 ); - *fMass = fVal; - g_pCore->ChatPrintf ( "Set %X to %f", false, fMass, fVal ); - } - } - */ - - /* - else if ( stricmp ( szString, "getmm" ) == 0 ) - { - CClientVehicle* pVehicle = pLocal->GetOccupiedVehicle (); - if ( pVehicle ) - { - float* fMass = (float*) atoi ( szString ); - g_pCore->ChatPrintf ( "Get %f", false, *fMass ); - } - } - */ - - /* - else if ( stricmp ( szString, "dump" ) == 0 ) - { - FILE* poo = fopen ( "vehs.txt", "w+" ); - if ( poo ) - { - tHandlingData* pHandling = (tHandlingData*) 0xC2B9E0; - unsigned int uiIndex = 0; - for ( ; uiIndex < 219; uiIndex++ ) - { - fprintf ( poo, "\n\n\n\n####### VEHICLE ID %u #######\n", uiIndex ); - - fprintf ( poo, "fMass = %f\n", pHandling->fMass ); - fprintf ( poo, "fUnknown1 = %f\n", pHandling->fUnknown1 ); - fprintf ( poo, "fTurnMass = %f\n", pHandling->fTurnMass ); - - fprintf ( poo, "fDragCoeff = %f\n", pHandling->fDragCoeff ); - fprintf ( poo, "vecCenterOfMass = %f, %f, %f\n", pHandling->vecCenterOfMass.fX, pHandling->vecCenterOfMass.fY, pHandling->vecCenterOfMass.fZ ); - fprintf ( poo, "uiPercentSubmerged = %u\n", pHandling->uiPercentSubmerged ); - - fprintf ( poo, "fUnknown2 = %f\n", pHandling->fUnknown2 ); - - fprintf ( poo, "fTractionMultiplier = %f\n", pHandling->fTractionMultiplier ); - - fprintf ( poo, "Transmission.fUnknown [0] = %f\n", pHandling->Transmission.fUnknown [0] ); - fprintf ( poo, "Transmission.fUnknown [1] = %f\n", pHandling->Transmission.fUnknown [1] ); - fprintf ( poo, "Transmission.fUnknown [2] = %f\n", pHandling->Transmission.fUnknown [2] ); - fprintf ( poo, "Transmission.fUnknown [3] = %f\n", pHandling->Transmission.fUnknown [3] ); - fprintf ( poo, "Transmission.fUnknown [4] = %f\n", pHandling->Transmission.fUnknown [4] ); - fprintf ( poo, "Transmission.fUnknown [5] = %f\n", pHandling->Transmission.fUnknown [5] ); - fprintf ( poo, "Transmission.fUnknown [6] = %f\n", pHandling->Transmission.fUnknown [6] ); - fprintf ( poo, "Transmission.fUnknown [7] = %f\n", pHandling->Transmission.fUnknown [7] ); - fprintf ( poo, "Transmission.fUnknown [8] = %f\n", pHandling->Transmission.fUnknown [8] ); - fprintf ( poo, "Transmission.fUnknown [9] = %f\n", pHandling->Transmission.fUnknown [9] ); - fprintf ( poo, "Transmission.fUnknown [10] = %f\n", pHandling->Transmission.fUnknown [10] ); - fprintf ( poo, "Transmission.fUnknown [11] = %f\n", pHandling->Transmission.fUnknown [11] ); - fprintf ( poo, "Transmission.fUnknown [12] = %f\n", pHandling->Transmission.fUnknown [12] ); - fprintf ( poo, "Transmission.fUnknown [13] = %f\n", pHandling->Transmission.fUnknown [13] ); - fprintf ( poo, "Transmission.fUnknown [14] = %f\n", pHandling->Transmission.fUnknown [14] ); - fprintf ( poo, "Transmission.fUnknown [15] = %f\n", pHandling->Transmission.fUnknown [15] ); - fprintf ( poo, "Transmission.fUnknown [16] = %f\n", pHandling->Transmission.fUnknown [16] ); - fprintf ( poo, "Transmission.fUnknown [17] = %f\n", pHandling->Transmission.fUnknown [17] ); - - fprintf ( poo, "Transmission.ucDriveType = %c\n", pHandling->Transmission.ucDriveType ); - fprintf ( poo, "Transmission.ucEngineType = %c\n", pHandling->Transmission.ucEngineType ); - fprintf ( poo, "Transmission.ucNumberOfGears = %u\n", pHandling->Transmission.ucNumberOfGears ); - fprintf ( poo, "Transmission.ucUnknown = %u\n", pHandling->Transmission.ucUnknown ); - - fprintf ( poo, "Transmission.uiHandlingFlags = 0x%X\n", pHandling->Transmission.uiHandlingFlags ); - - fprintf ( poo, "Transmission.fEngineAcceleration = %f\n", pHandling->Transmission.fEngineAcceleration ); - fprintf ( poo, "Transmission.fEngineInertia = %f\n", pHandling->Transmission.fEngineInertia ); - fprintf ( poo, "Transmission.fMaxVelocity = %f\n", pHandling->Transmission.fMaxVelocity ); - - fprintf ( poo, "Transmission.fUnknown2 [0] = %f\n", pHandling->Transmission.fUnknown2 [0] ); - fprintf ( poo, "Transmission.fUnknown2 [1] = %f\n", pHandling->Transmission.fUnknown2 [1] ); - fprintf ( poo, "Transmission.fUnknown2 [2] = %f\n", pHandling->Transmission.fUnknown2 [2] ); - - fprintf ( poo, "fBrakeDeceleration = %f\n", pHandling->fBrakeDeceleration ); - fprintf ( poo, "fBrakeBias = %f\n", pHandling->fBrakeBias ); - fprintf ( poo, "bABS = %u\n", pHandling->bABS ); - - fprintf ( poo, "fSteeringLock = %f\n", pHandling->fSteeringLock ); - fprintf ( poo, "fTractionLoss = %f\n", pHandling->fTractionLoss ); - fprintf ( poo, "fTractionBias = %f\n", pHandling->fTractionBias ); - - fprintf ( poo, "fSuspensionForceLevel = %f\n", pHandling->fSuspensionForceLevel ); - fprintf ( poo, "fSuspensionDamping = %f\n", pHandling->fSuspensionDamping ); - fprintf ( poo, "fSuspensionHighSpdDamping = %f\n", pHandling->fSuspensionHighSpdDamping ); - fprintf ( poo, "fSuspensionUpperLimit = %f\n", pHandling->fSuspensionUpperLimit ); - fprintf ( poo, "fSuspensionLowerLimit = %f\n", pHandling->fSuspensionLowerLimit ); - fprintf ( poo, "fSuspensionFrontRearBias = %f\n", pHandling->fSuspensionFrontRearBias ); - fprintf ( poo, "fSuspensionAntiDiveMultiplier = %f\n", pHandling->fSuspensionAntiDiveMultiplier ); - - fprintf ( poo, "fCollisionDamageMultiplier = %f\n", pHandling->fCollisionDamageMultiplier ); - - fprintf ( poo, "uiModelFlags = %X\n", pHandling->uiModelFlags ); - fprintf ( poo, "uiHandlingFlags = %X\n", pHandling->uiHandlingFlags ); - fprintf ( poo, "fSeatOffsetDistance = %f\n", pHandling->fSeatOffsetDistance ); - fprintf ( poo, "uiMonetary = %u\n", pHandling->uiMonetary ); - - fprintf ( poo, "ucHeadLight = 0x%X\n", pHandling->ucHeadLight ); - fprintf ( poo, "ucTailLight = 0x%X\n", pHandling->ucTailLight ); - fprintf ( poo, "ucAnimGroup = 0x%X\n", pHandling->ucAnimGroup ); - fprintf ( poo, "ucUnused = 0x%X\n", pHandling->ucUnused ); - - fprintf ( poo, "iUnknown7 = %f, %X\n", pHandling->iUnknown7, pHandling->iUnknown7 ); - - pHandling += 1; - } - - - g_pCore->ChatPrintf ( "Dumped", false ); - fclose ( poo ); - } - } - */ - - else if (strnicmp(szString, "moveug", 6) == 0) - { - if (pVehicleManager->Count() > 0) - { - CClientVehicle* pVehicle = *pVehicleManager->IterBegin(); - - /* - CClientPed* pModel = pVehicle->GetOccupant ( 0 ); - if ( !pModel ) - { - CClientPlayer* pPlayer = new CClientPlayer ( g_pClientGame->GetManager (), 50 ); - pModel = pPlayer->LoadModel ( 0 ); - pModel->WarpIntoVehicle ( pVehicle ); - } - */ - - pVehicle->RemoveTargetPosition(); - pVehicle->RemoveTargetRotation(); - - CVector vecT; - pVehicle->GetPosition(vecT); - vecT.fZ = (float)atof(szString + 7); - pVehicle->SetPosition(vecT); - - g_pCore->ChatPrintf("Done", false); - } - } - - else if (strnicmp(szString, "nocol", 5) == 0) - { - if (pVehicleManager->Count() > 0) - { - CClientVehicle* pVehicle = *pVehicleManager->IterBegin(); - pVehicle->SetCollisionEnabled(false); - - g_pCore->ChatPrintf("Done", false); - } - } - - else if (stricmp(szString, "resetdamage") == 0) - { - g_pClientGame->GetPlayerManager()->GetLocalPlayer()->GetGamePlayer()->ResetLastDamage(); - } - - else if (strnicmp(szString, "fuckveh", 7) == 0) - { - CClientVehicle* pVehicle = pLocal->GetOccupiedVehicle(); - if (pVehicle) - { - pVehicle->SetTargetPosition(CVector(0, 0, 0), TICK_RATE); - pVehicle->SetTargetRotation(CVector(0, 0, 0), TICK_RATE); - - g_pCore->ChatPrintf("Done", false); - } - } - - else if (stricmp(szString, "ped") == 0) - { - CClientPed* pPed = new CClientPed(g_pClientGame->GetManager(), INVALID_ELEMENT_ID, 9); - vecLocal.fX += 5.0f; - pPed->SetPosition(vecLocal); - } - - else if (strnicmp(szString, "callit", 6) == 0) - { - FILE* pFile = fopen("C:/dump.txt", "w+"); - - for (int i = 0; i < 400; i++) - { - int iIndex = i; - const char* szName = NULL; - _asm - { - mov eax, 0x4D3A30 - push iIndex - call eax - mov szName, eax - add esp, 4 - } - - fprintf(pFile, "%i: %s\n", iIndex, szName); - } - - fclose(pFile); - } - - /*else if (strnicmp(szString, "veh", 3) == 0) - { - int i = 600; - FILE* p = fopen("C:/dump.txt", "w+"); - - for (int a = 0; a < 13; a++) - { - g_pGame->GetModelInfo(i)->ModelAddRef(BLOCKING, "CFoo::Test"); - - CVehicle* pVehicle = g_pGame->GetPools()->AddVehicle((eVehicleTypes)i, 5, 5); - DWORD* dw2 = (DWORD*)(((DWORD)pVehicle->GetVehicleInterface()) + 0xE1 * 4); - DWORD dw = *dw2; - dw = dw + 4; - dw = dw - 0xC2B9E0; - dw = dw / 224; - fprintf(p, "Array [%u] = %u;\n", i, dw); - - g_pGame->GetPools()->RemoveVehicle(pVehicle); - - fflush(p); - - g_pGame->GetModelInfo(i)->RemoveRef(); - - i++; - } - - fclose(p); - }*/ - - else if (strnicmp(szString, "groups", 6) == 0) - { - FILE* pFile = fopen("C:/dump.txt", "w+"); - - int i = 0; - for (; i < 139; i++) - { - fprintf(pFile, "==%s [%s] (%i)==\n", pGroups[i].szGroupName, pGroups[i].szSomething, i); - uint i2 = 0; - for (; i2 < pGroups[i].ulAnimCount; i2++) - { - const char* szAnimName = pGroups[i].pAnimNames[i2]; - if (szAnimName[0]) - { - fprintf(pFile, "''%i'': %s
\n", i2, szAnimName); - } - } - - fprintf(pFile, "\n"); - } - - fclose(pFile); - } - - else if (strnicmp(szString, "getshot", 7) == 0) - { - if (pLocal->GetGamePlayer()->GetCanBeShotInVehicle()) - { - g_pCore->ChatEcho("true"); - } - else - { - g_pCore->ChatEcho("false"); - } - } - - else if (strnicmp(szString, "gettest", 7) == 0) - { - if (pLocal->GetGamePlayer()->GetTestForShotInVehicle()) - { - g_pCore->ChatEcho("true"); - } - else - { - g_pCore->ChatEcho("false"); - } - } - - else if (strnicmp(szString, "setshot", 7) == 0) - { - pLocal->GetGamePlayer()->SetCanBeShotInVehicle(true); - } - - else if (strnicmp(szString, "settest", 8) == 0) - { - pLocal->GetGamePlayer()->SetTestForShotInVehicle(true); - } - - else if (stricmp(szString, "applytest") == 0) - { - DWORD oldProt, oldProt2; - VirtualProtect((LPVOID)0x5E8FFB, 6, PAGE_EXECUTE_READWRITE, &oldProt); - - *(unsigned char*)(0x5E8FFB) = 0x90; - *(unsigned char*)(0x5E8FFC) = 0x90; - *(unsigned char*)(0x5E8FFD) = 0x90; - *(unsigned char*)(0x5E8FFE) = 0x90; - *(unsigned char*)(0x5E8FFF) = 0x90; - *(unsigned char*)(0x5E9000) = 0x90; - - VirtualProtect((LPVOID)0x5E8FFB, 6, oldProt, &oldProt2); - } -} - -#endif diff --git a/Client/mods/deathmatch/logic/CFoo.h b/Client/mods/deathmatch/logic/CFoo.h deleted file mode 100644 index f5ed770763..0000000000 --- a/Client/mods/deathmatch/logic/CFoo.h +++ /dev/null @@ -1,31 +0,0 @@ -/***************************************************************************** - * - * PROJECT: Multi Theft Auto v1.0 - * LICENSE: See LICENSE in the top level directory - * FILE: mods/deathmatch/logic/CFoo.h - * PURPOSE: Debugging class (not used in Release mode) - * - * Multi Theft Auto is available from http://www.multitheftauto.com/ - * - *****************************************************************************/ - -/* This class is purely for debugging things. This will avoid usage of CClientGame. */ - -#pragma once - -class CFoo -{ -public: - #ifdef MTA_DEBUG - void Init(class CClientGame* pClientGame) { g_pClientGame = pClientGame; }; - - void DoPulse(); - void Test(const char* szString); - - class CClientGame* g_pClientGame; - #else - void Init(CClientGame* pClientGame){}; - void DoPulse(){}; - void Test(const char* szString){}; - #endif -}; diff --git a/Client/mods/deathmatch/logic/CModelRenderer.cpp b/Client/mods/deathmatch/logic/CModelRenderer.cpp new file mode 100644 index 0000000000..2f06c836ec --- /dev/null +++ b/Client/mods/deathmatch/logic/CModelRenderer.cpp @@ -0,0 +1,72 @@ +/***************************************************************************** + * + * PROJECT: Multi Theft Auto v1.0 + * LICENSE: See LICENSE in the top level directory + * FILE: mods/deathmatch/logic/CModelRenderer.cpp + * PURPOSE: 3D models renderer + * + * Multi Theft Auto is available from http://www.multitheftauto.com/ + * + *****************************************************************************/ + +#include "StdInc.h" +#include "game\CRenderer.h" +#include "game\CVisibilityPlugins.h" + +bool CModelRenderer::EnqueueModel(CModelInfo* pModelInfo, const CMatrix& matrix) +{ + if (g_pCore->IsWindowMinimized()) + return false; + + if (pModelInfo && pModelInfo->IsLoaded()) + { + m_Queue.emplace_back(pModelInfo, matrix); + return true; + } + + return false; +} + +void CModelRenderer::Update() +{ + CVisibilityPlugins* pVisibilityPlugins = g_pGame->GetVisibilityPlugins(); + assert(pVisibilityPlugins); + + for (auto& modelDesc : m_Queue) + { + // Insert transparent entities into a sorted list + if (modelDesc.pModelInfo->GetIdeFlag(eModelIdeFlag::DRAW_LAST)) + { + const CVector& vecCameraPosition = *(CVector*)0xB76870; // CRenderer::ms_vecCameraPosition + const float fDistance = (modelDesc.matrix.GetPosition() - vecCameraPosition).Length(); + + pVisibilityPlugins->InsertEntityIntoEntityList(&modelDesc, fDistance, RenderEntity); + } + } +} + +void CModelRenderer::Render() +{ + CRenderer* pRenderer = g_pGame->GetRenderer(); + assert(pRenderer); + + // Draw opaque entities + for (auto& modelDesc : m_Queue) + { + if (modelDesc.pModelInfo->IsLoaded() && !modelDesc.pModelInfo->GetIdeFlag(eModelIdeFlag::DRAW_LAST)) + pRenderer->RenderModel(modelDesc.pModelInfo, modelDesc.matrix); + } + + m_Queue.clear(); +} + +void CModelRenderer::RenderEntity(SModelToRender* modelDesc, float distance) +{ + if (!modelDesc->pModelInfo->IsLoaded()) + return; + + CRenderer* pRenderer = g_pGame->GetRenderer(); + assert(pRenderer); + + pRenderer->RenderModel(modelDesc->pModelInfo, modelDesc->matrix); +} diff --git a/Client/mods/deathmatch/logic/CModelRenderer.h b/Client/mods/deathmatch/logic/CModelRenderer.h new file mode 100644 index 0000000000..d923db6c7f --- /dev/null +++ b/Client/mods/deathmatch/logic/CModelRenderer.h @@ -0,0 +1,40 @@ +/***************************************************************************** + * + * PROJECT: Multi Theft Auto v1.0 + * LICENSE: See LICENSE in the top level directory + * FILE: mods/deathmatch/logic/CModelRenderer.h + * PURPOSE: 3D models renderer + * + * Multi Theft Auto is available from http://www.multitheftauto.com/ + * + *****************************************************************************/ + +#pragma once + +class CModelRenderer final +{ +public: + struct SModelToRender final + { + CModelInfo* pModelInfo; + CMatrix matrix; + + SModelToRender(CModelInfo* pModelInfo, const CMatrix& matrix) : + pModelInfo(pModelInfo), + matrix(matrix) + { + } + }; + + bool EnqueueModel(CModelInfo* pModelInfo, const CMatrix& matrix); + + void Update(); + + void Render(); + + static void RenderEntity(SModelToRender* entity, float distance); + +private: + + std::vector m_Queue; +}; diff --git a/Client/mods/deathmatch/logic/CNetAPI.cpp b/Client/mods/deathmatch/logic/CNetAPI.cpp index ecb16fd1ac..a6238512c7 100644 --- a/Client/mods/deathmatch/logic/CNetAPI.cpp +++ b/Client/mods/deathmatch/logic/CNetAPI.cpp @@ -2262,6 +2262,8 @@ void CNetAPI::ReadBulletsync(CClientPlayer* pPlayer, NetBitStreamInterface& BitS // Read the bulletsync data uchar ucWeapon = 0; BitStream.Read(ucWeapon); + if (!CClientPickupManager::IsValidWeaponID(ucWeapon)) + return; eWeaponType weaponType = (eWeaponType)ucWeapon; CVector vecStart, vecEnd; diff --git a/Client/mods/deathmatch/logic/CPacketHandler.cpp b/Client/mods/deathmatch/logic/CPacketHandler.cpp index 51cad6aed4..ebf2ba5140 100644 --- a/Client/mods/deathmatch/logic/CPacketHandler.cpp +++ b/Client/mods/deathmatch/logic/CPacketHandler.cpp @@ -1,11 +1,11 @@ /***************************************************************************** * - * PROJECT: Multi Theft Auto v1.0 + * PROJECT: Multi Theft Auto * LICENSE: See LICENSE in the top level directory - * FILE: mods/deathmatch/logic/CPacketHandler.cpp + * FILE: Client/mods/deathmatch/logic/CPacketHandler.cpp * PURPOSE: Packet handling and processing * - * Multi Theft Auto is available from http://www.multitheftauto.com/ + * Multi Theft Auto is available from https://multitheftauto.com/ * *****************************************************************************/ @@ -19,6 +19,7 @@ #include #include #include +#include #include "net/SyncStructures.h" #include "CServerInfo.h" @@ -1225,6 +1226,8 @@ void CPacketHandler::Packet_PlayerWasted(NetBitStreamInterface& bitStream) else Arguments.PushBoolean(false); Arguments.PushBoolean(bStealth); + Arguments.PushNumber(animGroup); + Arguments.PushNumber(animID); if (IS_PLAYER(pPed)) pPed->CallEvent("onClientPlayerWasted", Arguments, true); else @@ -1470,7 +1473,7 @@ void CPacketHandler::Packet_DebugEcho(NetBitStreamInterface& bitStream) if (!bitStream.Read(ucLevel)) return; - if (ucLevel == 0) + if (ucLevel == 0 || ucLevel == 4) { // Read out the color if (!bitStream.Read(ucRed) || !bitStream.Read(ucGreen) || !bitStream.Read(ucBlue)) @@ -1480,7 +1483,7 @@ void CPacketHandler::Packet_DebugEcho(NetBitStreamInterface& bitStream) } // Valid length? - int iBytesRead = (ucLevel == 0) ? 4 : 1; + int iBytesRead = (ucLevel == 0 || ucLevel == 4) ? 4 : 1; int iNumberOfBytesUsed = bitStream.GetNumberOfBytesUsed() - iBytesRead; if (iNumberOfBytesUsed >= MIN_DEBUGECHO_LENGTH && iNumberOfBytesUsed <= MAX_DEBUGECHO_LENGTH) { @@ -2387,6 +2390,9 @@ void CPacketHandler::Packet_MapInfo(NetBitStreamInterface& bitStream) g_pClientGame->SetWorldSpecialProperty(WorldSpecialProperty::WATERCREATURES, wsProps.data.watercreatures); g_pClientGame->SetWorldSpecialProperty(WorldSpecialProperty::BURNFLIPPEDCARS, wsProps.data.burnflippedcars); g_pClientGame->SetWorldSpecialProperty(WorldSpecialProperty::FIREBALLDESTRUCT, wsProps.data2.fireballdestruct); + g_pClientGame->SetWorldSpecialProperty(WorldSpecialProperty::ROADSIGNSTEXT, wsProps.data3.roadsignstext); + g_pClientGame->SetWorldSpecialProperty(WorldSpecialProperty::EXTENDEDWATERCANNONS, wsProps.data4.extendedwatercannons); + g_pClientGame->SetWorldSpecialProperty(WorldSpecialProperty::TUNNELWEATHERBLEND, wsProps.data5.tunnelweatherblend); float fJetpackMaxHeight = 100; if (!bitStream.Read(fJetpackMaxHeight)) @@ -2639,7 +2645,7 @@ void CPacketHandler::Packet_MapInfo(NetBitStreamInterface& bitStream) { bitStream.Read(cInterior); } - g_pGame->GetWorld()->RemoveBuilding(usModel, fRadius, fX, fY, fZ, cInterior); + g_pGame->GetBuildingRemoval()->RemoveBuilding(usModel, fRadius, fX, fY, fZ, cInterior); } bool bOcclusionsEnabled = true; @@ -2717,6 +2723,8 @@ void CPacketHandler::Packet_EntityAdd(NetBitStreamInterface& bitStream) // CVector (12) - scale // bool (1) - static // SObjectHealthSync (?) - health + // bool (1) - is break + // bool (1) - respawnable // Pickups: // CVector (12) - position @@ -3077,6 +3085,15 @@ void CPacketHandler::Packet_EntityAdd(NetBitStreamInterface& bitStream) if (bitStream.Read(&health)) pObject->SetHealth(health.data.fValue); + if (bitStream.Can(eBitStreamVersion::BreakObject_Serverside)) + { + if (bitStream.ReadBit()) + pObject->Break(); + } + + if (bitStream.Can(eBitStreamVersion::RespawnObject_Serverside)) + pObject->SetRespawnEnabled(bitStream.ReadBit()); + pObject->SetCollisionEnabled(bCollisonsEnabled); if (ucEntityTypeID == CClientGame::WEAPON) { @@ -3619,7 +3636,6 @@ void CPacketHandler::Packet_EntityAdd(NetBitStreamInterface& bitStream) CClientMarker* pMarker = new CClientMarker(g_pClientGame->m_pManager, EntityID, ucType); pMarker->SetPosition(position.data.vecPosition); pMarker->SetSize(fSize); - pMarker->SetColor(color); // Entity is this pEntity = pMarker; @@ -3641,8 +3657,27 @@ void CPacketHandler::Packet_EntityAdd(NetBitStreamInterface& bitStream) pCheckpoint->SetNextPosition(position.data.vecPosition); pCheckpoint->SetIcon(CClientCheckpoint::ICON_ARROW); } + + if (ucType == CClientGame::MARKER_CHECKPOINT && bitStream.Can(eBitStreamVersion::SetMarkerTargetArrowProperties)) + { + SColor color; + float size; + bitStream.Read(color.R); + bitStream.Read(color.G); + bitStream.Read(color.B); + bitStream.Read(color.A); + bitStream.Read(size); + + pCheckpoint->SetTargetArrowProperties(color, size); + } } } + + // Read out alpha limit flag + if (bitStream.Can(eBitStreamVersion::Marker_IgnoreAlphaLimits)) + pMarker->SetIgnoreAlphaLimits(bitStream.ReadBit()); + + pMarker->SetColor(color); } else { diff --git a/Client/mods/deathmatch/logic/CPedSync.cpp b/Client/mods/deathmatch/logic/CPedSync.cpp index d11e8f526f..8461ac1a87 100644 --- a/Client/mods/deathmatch/logic/CPedSync.cpp +++ b/Client/mods/deathmatch/logic/CPedSync.cpp @@ -179,29 +179,50 @@ void CPedSync::Packet_PedSync(NetBitStreamInterface& BitStream) unsigned char ucFlags = 0; BitStream.Read(ucFlags); - CVector vecPosition, vecMoveSpeed; + CVector vecPosition{ CVector::NoInit{} }, vecMoveSpeed{ CVector::NoInit{} }; float fRotation, fHealth, fArmor; bool bOnFire; bool bIsInWater; - // Read out the position - if (ucFlags & 0x01) + if (BitStream.Can(eBitStreamVersion::PedSync_Revision)) { - BitStream.Read(vecPosition.fX); - BitStream.Read(vecPosition.fY); - BitStream.Read(vecPosition.fZ); - } + // Read out the position + SPositionSync position(false); + if (ucFlags & 0x01) + BitStream.Read(&position); - // And rotation - if (ucFlags & 0x02) - BitStream.Read(fRotation); + // And rotation + SPedRotationSync rotation; + if (ucFlags & 0x02) + BitStream.Read(&rotation); + + // And the move speed + SVelocitySync velocity; + if (ucFlags & 0x04) + BitStream.Read(&velocity); - // And the move speed - if (ucFlags & 0x04) + vecPosition = position.data.vecPosition; + fRotation = rotation.data.fRotation; + vecMoveSpeed = velocity.data.vecVelocity; + } + else { - BitStream.Read(vecMoveSpeed.fX); - BitStream.Read(vecMoveSpeed.fY); - BitStream.Read(vecMoveSpeed.fZ); + if (ucFlags & 0x01) + { + BitStream.Read(vecPosition.fX); + BitStream.Read(vecPosition.fY); + BitStream.Read(vecPosition.fZ); + } + + if (ucFlags & 0x02) + BitStream.Read(fRotation); + + if (ucFlags & 0x04) + { + BitStream.Read(vecMoveSpeed.fX); + BitStream.Read(vecMoveSpeed.fY); + BitStream.Read(vecMoveSpeed.fZ); + } } // And health with armour @@ -223,9 +244,9 @@ void CPedSync::Packet_PedSync(NetBitStreamInterface& BitStream) if (pPed && pPed->CanUpdateSync(ucSyncTimeContext)) { if (ucFlags & 0x01) - pPed->SetPosition(vecPosition); + pPed->SetTargetPosition(vecPosition, PED_SYNC_RATE); if (ucFlags & 0x02) - pPed->SetCurrentRotation(fRotation); + pPed->SetTargetRotation(PED_SYNC_RATE, fRotation, 0.0f); if (ucFlags & 0x04) pPed->SetMoveSpeed(vecMoveSpeed); if (ucFlags & 0x08) @@ -303,24 +324,51 @@ void CPedSync::WritePedInformation(NetBitStreamInterface* pBitStream, CClientPed // Write position if needed if (ucFlags & 0x01) { - pBitStream->Write(vecPosition.fX); - pBitStream->Write(vecPosition.fY); - pBitStream->Write(vecPosition.fZ); + if (pBitStream->Can(eBitStreamVersion::PedSync_Revision)) + { + SPositionSync position(false); + position.data.vecPosition = vecPosition; + pBitStream->Write(&position); + } + else + { + pBitStream->Write(vecPosition.fX); + pBitStream->Write(vecPosition.fY); + pBitStream->Write(vecPosition.fZ); + } + pPed->m_LastSyncedData->vPosition = vecPosition; } if (ucFlags & 0x02) { - pBitStream->Write(pPed->GetCurrentRotation()); + if (pBitStream->Can(eBitStreamVersion::PedSync_Revision)) + { + SPedRotationSync rotation; + rotation.data.fRotation = pPed->GetCurrentRotation(); + pBitStream->Write(&rotation); + } + else + pBitStream->Write(pPed->GetCurrentRotation()); + pPed->m_LastSyncedData->fRotation = pPed->GetCurrentRotation(); } // Write velocity if (ucFlags & 0x04) { - pBitStream->Write(vecVelocity.fX); - pBitStream->Write(vecVelocity.fY); - pBitStream->Write(vecVelocity.fZ); + if (pBitStream->Can(eBitStreamVersion::PedSync_Revision)) + { + SVelocitySync velocity; + pBitStream->Write(&velocity); + } + else + { + pBitStream->Write(vecVelocity.fX); + pBitStream->Write(vecVelocity.fY); + pBitStream->Write(vecVelocity.fZ); + } + pPed->m_LastSyncedData->vVelocity = vecVelocity; } diff --git a/Client/mods/deathmatch/logic/CResource.cpp b/Client/mods/deathmatch/logic/CResource.cpp index c1b5fdf9e7..dcf119ce46 100644 --- a/Client/mods/deathmatch/logic/CResource.cpp +++ b/Client/mods/deathmatch/logic/CResource.cpp @@ -94,6 +94,9 @@ CResource::CResource(unsigned short usNetID, const char* szResourceName, CClient CResource::~CResource() { + // Remove refrences from requested models + m_modelStreamer.ReleaseAll(); + // Deallocate all models that this resource allocated earlier g_pClientGame->GetManager()->GetModelManager()->DeallocateModelsAllocatedByResource(this); diff --git a/Client/mods/deathmatch/logic/CResource.h b/Client/mods/deathmatch/logic/CResource.h index 37a2ab8560..8100d3fc79 100644 --- a/Client/mods/deathmatch/logic/CResource.h +++ b/Client/mods/deathmatch/logic/CResource.h @@ -15,6 +15,7 @@ #include "CClientEntity.h" #include "CResourceConfigItem.h" #include "CResourceFile.h" +#include "CResourceModelStreamer.h" #include "CElementGroup.h" #include @@ -69,6 +70,7 @@ class CResource void SetResourceEntity(CClientEntity* pEntity) { m_pResourceEntity = pEntity; } class CClientEntity* GetResourceDynamicEntity() { return m_pResourceDynamicEntity; } void SetResourceDynamicEntity(CClientEntity* pEntity) { m_pResourceDynamicEntity = pEntity; } + SString GetResourceDirectoryPath() { return GetResourceDirectoryPath(eAccessType::ACCESS_PUBLIC, ""); } SString GetResourceDirectoryPath(eAccessType accessType, const SString& strMetaPath); class CClientEntity* GetResourceGUIEntity() { return m_pResourceGUIEntity; } void SetResourceGUIEntity(CClientEntity* pEntity) { m_pResourceGUIEntity = pEntity; } @@ -78,6 +80,8 @@ class CResource CClientEntity* GetResourceIFPRoot() { return m_pResourceIFPRoot; }; CClientEntity* GetResourceIMGRoot() { return m_pResourceIMGRoot; }; + CResourceModelStreamer* GetResourceModelStreamer() { return &m_modelStreamer; }; + // This is to delete all the elements created in this resource that are created locally in this client void DeleteClientChildren(); @@ -144,4 +148,6 @@ class CResource CFastHashSet m_exportedFunctions; CElementGroup* m_pDefaultElementGroup; // stores elements created by scripts in this resource std::list m_NoClientCacheScriptList; + + CResourceModelStreamer m_modelStreamer{}; }; diff --git a/Client/mods/deathmatch/logic/CResourceManager.cpp b/Client/mods/deathmatch/logic/CResourceManager.cpp index 57939c9a0e..ff072ac83f 100644 --- a/Client/mods/deathmatch/logic/CResourceManager.cpp +++ b/Client/mods/deathmatch/logic/CResourceManager.cpp @@ -150,7 +150,7 @@ void CResourceManager::StopAll() } // pResource may be changed on return, and it could be NULL if the function returns false. -bool CResourceManager::ParseResourcePathInput(std::string strInput, CResource*& pResource, std::string* pStrPath, std::string* pStrMetaPath) +bool CResourceManager::ParseResourcePathInput(std::string strInput, CResource*& pResource, std::string* pStrPath, std::string* pStrMetaPath, bool bPassSize) { ReplaceOccurrencesInString(strInput, "\\", "/"); @@ -190,7 +190,7 @@ bool CResourceManager::ParseResourcePathInput(std::string strInput, CResource*& } } } - else if (pResource && IsValidFilePath(strInput.c_str())) + else if (pResource && (bPassSize ? IsValidFilePath(strInput.c_str(), strInput.size()) : IsValidFilePath(strInput.c_str()))) { if (pStrPath) *pStrPath = pResource->GetResourceDirectoryPath(accessType, strInput); diff --git a/Client/mods/deathmatch/logic/CResourceManager.h b/Client/mods/deathmatch/logic/CResourceManager.h index d0b5e7892d..4d52e8c7ce 100644 --- a/Client/mods/deathmatch/logic/CResourceManager.h +++ b/Client/mods/deathmatch/logic/CResourceManager.h @@ -54,7 +54,7 @@ class CResourceManager void ValidateResourceFile(const SString& strFilename, const char* buffer, size_t bufferSize); CDownloadableResource* GetDownloadableResourceFile(const SString& strFilename) { return MapFindRef(m_ResourceFileMap, strFilename); } - static bool ParseResourcePathInput(std::string strInput, CResource*& pResource, std::string* pStrPath, std::string* pStrMetaPath = nullptr); + static bool ParseResourcePathInput(std::string strInput, CResource*& pResource, std::string* pStrPath, std::string* pStrMetaPath = nullptr, bool bPassSize = false); private: CMappedList m_resources; diff --git a/Client/mods/deathmatch/logic/CResourceModelStreamer.cpp b/Client/mods/deathmatch/logic/CResourceModelStreamer.cpp new file mode 100644 index 0000000000..c6c2eb30d1 --- /dev/null +++ b/Client/mods/deathmatch/logic/CResourceModelStreamer.cpp @@ -0,0 +1,126 @@ +/***************************************************************************** + * + * PROJECT: Multi Theft Auto + * LICENSE: See LICENSE in the top level directory + * FILE: mods/deathmatch/logic/CResourceModelStreamer.cpp + * PURPOSE: Resource model manager + * + * Multi Theft Auto is available from https://www.multitheftauto.com/ + * + *****************************************************************************/ + +#include "StdInc.h" + +#include "CResourceModelStreamer.h" +#include "CClientGame.h" +#include + +bool CResourceModelStreamer::RequestModel(std::uint16_t modelId, bool addRef, bool blocking) +{ + CModelInfo* model = g_pGame->GetModelInfo(modelId); + + if (!model) + return false; + + if (addRef) + { + std::uint16_t refsCount = ++m_requestedModels[modelId]; + if (refsCount == 1) + { + model->ModelAddRef(blocking ? EModelRequestType::BLOCKING : EModelRequestType::NON_BLOCKING, "CResourceModelStreamer::RequestModel With reference"); + return true; + } + return false; + } + else + { + if (model->IsLoaded()) + { + return false; + } + else + { + model->Request(blocking ? EModelRequestType::BLOCKING : EModelRequestType::NON_BLOCKING, "CResourceModelStreamer::RequestModel With out reference"); + return true; + } + } +} + +// Return true if model was unloaded +bool CResourceModelStreamer::ReleaseModel(std::uint16_t modelId, bool removeRef) +{ + if (removeRef) + { + auto refs = m_requestedModels.find(modelId); + if (refs == m_requestedModels.end()) + return false; + + std::uint16_t& refsCount = (*refs).second; + + if (refsCount == 0) + return false; + + refsCount--; + + if (refsCount != 0) + return false; + + CModelInfo* model = g_pGame->GetModelInfo(modelId); + + if (!model) + return false; + + // Hack + // This check will update models pending references + model->IsLoaded(); + + // This call can unload the model + model->RemoveRef(); + + return !model->IsLoaded(); + } + else + { + CModelInfo* model = g_pGame->GetModelInfo(modelId); + + if (!model) + return false; + + return model->UnloadUnused(); + } +} + +void CResourceModelStreamer::ReleaseAll() +{ + for (const auto &modelRefs : m_requestedModels) + { + if (modelRefs.second > 0) + { + CModelInfo* model = g_pGame->GetModelInfo(modelRefs.first); + model->RemoveRef(); + } + } + + m_requestedModels.clear(); +} + +void CResourceModelStreamer::FullyReleaseModel(std::uint16_t modelId) +{ + auto refs = m_requestedModels.find(modelId); + if (refs == m_requestedModels.end()) + return; + + std::uint16_t& refsCount = refs->second; + + if (refsCount > 0) + { + refsCount = 0; + + CModelInfo* model = g_pGame->GetModelInfo(modelId); + + if (!model) + return; + + model->RemoveRef(); + } +} diff --git a/Client/mods/deathmatch/logic/CResourceModelStreamer.h b/Client/mods/deathmatch/logic/CResourceModelStreamer.h new file mode 100644 index 0000000000..fa72720b37 --- /dev/null +++ b/Client/mods/deathmatch/logic/CResourceModelStreamer.h @@ -0,0 +1,30 @@ +/***************************************************************************** + * + * PROJECT: Multi Theft Auto + * LICENSE: See LICENSE in the top level directory + * FILE: mods/deathmatch/logic/CResourceModelStreamer.h + * PURPOSE: Resource model manager + * + * Multi Theft Auto is available from https://www.multitheftauto.com/ + * + *****************************************************************************/ + +#pragma once + +#include + +class CResourceModelStreamer +{ +public: + CResourceModelStreamer() = default; + ~CResourceModelStreamer() = default; + + bool RequestModel(std::uint16_t modelId, bool addRef = false, bool blocking = false); + bool ReleaseModel(std::uint16_t modelId, bool removeRef = false); + + void ReleaseAll(); + void FullyReleaseModel(std::uint16_t modelId); + +private: + std::unordered_map m_requestedModels; +}; diff --git a/Client/mods/deathmatch/logic/CScriptDebugging.cpp b/Client/mods/deathmatch/logic/CScriptDebugging.cpp index fd51faf20b..4af67b1524 100644 --- a/Client/mods/deathmatch/logic/CScriptDebugging.cpp +++ b/Client/mods/deathmatch/logic/CScriptDebugging.cpp @@ -123,7 +123,9 @@ void CScriptDebugging::UpdateLogOutput() while (m_DuplicateLineFilter.PopOutputLine(line)) { // Log it to the file if enough level - if (m_uiLogFileLevel >= line.uiMinimumDebugLevel) + bool sufficientDebugLevel = CheckForSufficientDebugLevel(m_uiLogFileLevel, line.uiMinimumDebugLevel); + + if (sufficientDebugLevel) { PrintLog(line.strText); } diff --git a/Client/mods/deathmatch/logic/CScriptDebugging.h b/Client/mods/deathmatch/logic/CScriptDebugging.h index a406baa6e4..48b41b606a 100644 --- a/Client/mods/deathmatch/logic/CScriptDebugging.h +++ b/Client/mods/deathmatch/logic/CScriptDebugging.h @@ -68,6 +68,7 @@ class CScriptDebugging SString ComposeErrorMessage(const char* szPrePend, const SLuaDebugInfo& luaDebugInfo, const char* szMessage); void LogString(const char* szPrePend, const SLuaDebugInfo& luaDebugInfo, const char* szMessage, unsigned int uiMinimumDebugLevel, unsigned char ucRed = 255, unsigned char ucGreen = 255, unsigned char ucBlue = 255); + bool CheckForSufficientDebugLevel(std::uint8_t playerDebugLevel, std::uint8_t messageDebugLevel) const noexcept; void PrintLog(const char* szText); public: diff --git a/Client/mods/deathmatch/logic/CServer.cpp b/Client/mods/deathmatch/logic/CServer.cpp index 3f38eef687..69484c6ad5 100644 --- a/Client/mods/deathmatch/logic/CServer.cpp +++ b/Client/mods/deathmatch/logic/CServer.cpp @@ -1,330 +1,287 @@ /***************************************************************************** * - * PROJECT: Multi Theft Auto v1.0 + * PROJECT: Multi Theft Auto * LICENSE: See LICENSE in the top level directory * FILE: mods/deathmatch/logic/CServer.cpp * PURPOSE: Local server instancing class * - * Multi Theft Auto is available from http://www.multitheftauto.com/ + * Multi Theft Auto is available from https://multitheftauto.com/ * *****************************************************************************/ #include - -static volatile bool g_bIsStarted = false; -extern CCoreInterface* g_pCore; -extern CLocalizationInterface* g_pLocalization; -CCriticalSection CServer::m_OutputCC; -std::list CServer::m_OutputQueue; +#include +#include #ifdef MTA_DEBUG - #define SERVER_DLL_PATH "core_d.dll" + #define SERVER_EXE_PATH "MTA Server_d.exe" #else - #define SERVER_DLL_PATH "core.dll" + #define SERVER_EXE_PATH "MTA Server.exe" #endif -#define ERROR_NO_ERROR 0 -#define ERROR_NO_NETWORK_LIBRARY 1 -#define ERROR_NETWORK_LIBRARY_FAILED 2 -#define ERROR_LOADING_MOD 3 +constexpr UINT PROCESS_FORCEFULLY_TERMINATED = 0x90804050u; static const SFixedArray szServerErrors = {"Server stopped", "Could not load network library", "Loading network library failed", "Error loading mod"}; -CServer::CServer() +static bool IsProcessRunning(HANDLE process) { - assert(!g_bIsStarted); - - // Initialize - m_bIsReady = false; - m_pLibrary = NULL; - m_hThread = INVALID_HANDLE_VALUE; - m_iLastError = ERROR_NO_ERROR; - - m_strServerRoot = CalcMTASAPath("server"); - m_strDLLFile = PathJoin(m_strServerRoot, SERVER_DLL_PATH); + return WaitForSingleObject(process, 0) == WAIT_TIMEOUT; } -CServer::~CServer() +struct PipeHandlePair { - // Make sure the server is stopped - Stop(); + bool AutoClose{}; + HANDLE Read{}; + HANDLE Write{}; - // Make sure the thread handle is closed - if (m_hThread != INVALID_HANDLE_VALUE) + ~PipeHandlePair() { - CloseHandle(m_hThread); + if (AutoClose) + { + CloseHandle(Read); + CloseHandle(Write); + } } -} +}; -void CServer::DoPulse() +bool CServer::Start(const char* configFileName) { - if (IsRunning()) + if (m_isRunning) + return false; + + // Create and use an optional job object to kill the server process automatically when we close the job object. + // This is pretty handy in case the game process unexpectedly crashes and we miss terminating the server process. + HANDLE job = CreateJobObjectW(nullptr, nullptr); + + if (job != nullptr) { - // Make sure the server doesn't happen to be adding anything right now - m_OutputCC.Lock(); + JOBOBJECT_EXTENDED_LIMIT_INFORMATION limits{}; + limits.BasicLimitInformation.LimitFlags = JOB_OBJECT_LIMIT_KILL_ON_JOB_CLOSE; - // Anything to output to console? - if (m_OutputQueue.size() > 0) + if (!SetInformationJobObject(job, JobObjectExtendedLimitInformation, &limits, sizeof(limits))) { - // Loop through our output queue and echo it to console - std::list::const_iterator iter = m_OutputQueue.begin(); - for (; iter != m_OutputQueue.end(); ++iter) - { - // Echo it - const char* szString = iter->c_str(); - g_pCore->GetConsole()->Echo(szString); - - // Does the message end with "Server started and is ready to accept connections!\n"? - size_t sizeString = iter->length(); - if (sizeString >= 51 && stricmp(szString + sizeString - 51, "Server started and is ready to accept connections!\n") == 0) - { - m_bIsReady = true; - } - } - - // Clear the list - m_OutputQueue.clear(); + g_pCore->GetConsole()->Printf("Server process warning [error: %08x]: failed to setup job object\n", GetLastError()); + + CloseHandle(job); + job = nullptr; } - // Unlock again - m_OutputCC.Unlock(); } - else + + SECURITY_ATTRIBUTES securityAttributes{}; + securityAttributes.nLength = sizeof(securityAttributes); + securityAttributes.bInheritHandle = TRUE; + + // Create the input pipe for the server process. + PipeHandlePair in; + + if (!CreatePipe(&in.Read, &in.Write, &securityAttributes, 0)) { - // not running, errored? - if (GetLastError() != ERROR_NO_ERROR) - { - Stop(); - } + g_pCore->GetConsole()->Printf("Server process failed to start [error: %08x]: failed to create input pipe\n", GetLastError()); + return false; } -} -bool CServer::Start(const char* szConfig) -{ - // Not already started? - if (!g_bIsStarted) + in.AutoClose = true; + + // Only inherit the read handle to the input pipe. + if (!SetHandleInformation(in.Write, HANDLE_FLAG_INHERIT, 0)) { - m_strConfig = szConfig; + g_pCore->GetConsole()->Printf("Server process failed to start [error: %08x]: failed to modify input pipe\n", GetLastError()); + return false; + } - // Check that the DLL exists - if (!FileExists(m_strDLLFile)) - { - g_pCore->GetConsole()->Printf("Unable to find: '%s'", m_strDLLFile.c_str()); - return false; - } + // Create the output pipe for the server process. + PipeHandlePair out; - // We're now started, but not ready - g_bIsStarted = true; - m_bIsReady = false; + if (!CreatePipe(&out.Read, &out.Write, &securityAttributes, 0)) + { + g_pCore->GetConsole()->Printf("Server process failed to start [error: %08x]: failed to create output pipe\n", GetLastError()); + return false; + } - // Close the previous thread? - if (m_hThread != INVALID_HANDLE_VALUE) - { - CloseHandle(m_hThread); - } + out.AutoClose = true; - // Create a thread to run the server - DWORD dwTemp; - m_hThread = CreateThread(NULL, 0, Thread_EntryPoint, this, 0, &dwTemp); - return m_hThread != NULL; + // Only inherit the write handle to the output pipe. + if (!SetHandleInformation(out.Read, HANDLE_FLAG_INHERIT, 0)) + { + g_pCore->GetConsole()->Printf("Server process failed to start [error: %08x]: failed to modify output pipe\n", GetLastError()); + return false; } - return false; -} + // Create an anonymous event to signal the readyness of the server to accept connections. + HANDLE readyEvent = CreateEventA(&securityAttributes, FALSE, FALSE, nullptr); -bool CServer::IsStarted() -{ - return g_bIsStarted; -} + if (readyEvent == nullptr) + { + g_pCore->GetConsole()->Printf("Server process failed to start [error: %08x]: failed to create ready event\n", GetLastError()); + return false; + } -bool CServer::Stop() -{ - // Started? - if (g_bIsStarted) + // We write the event handle to standard input, which we then extract in CServerImpl::Run (Server Core). + DWORD bytesWritten{}; + + if (!WriteFile(in.Write, &readyEvent, sizeof(readyEvent), &bytesWritten, nullptr) || bytesWritten != sizeof(readyEvent)) { - // Wait for the library to come true or is started to go false - // This is so a call to Start then fast call to Stop will work. Otherwize it might not - // get time to start the server thread before we terminate it and we will end up - // starting it after this call to Stop. - while (g_bIsStarted && !m_pLibrary) - { - Sleep(1); - } + g_pCore->GetConsole()->Printf("Server process failed to start [error: %08x]: failed to write ready event\n", GetLastError()); + CloseHandle(readyEvent); + return false; + } - // Lock - m_CriticalSection.Lock(); + // Create the server process now. + const SString serverRoot = CalcMTASAPath("server"); + const SString serverExePath = PathJoin(serverRoot, SERVER_EXE_PATH); + const SString commandLine("\"%s\" --child-process --config \"%s\"", SERVER_EXE_PATH, configFileName); - // Is the server running? - if (m_pLibrary) - { - // Send the exit message - Send("exit"); - } + STARTUPINFOW startupInfo{}; + startupInfo.cb = sizeof(STARTUPINFOW); + startupInfo.hStdError = out.Write; + startupInfo.hStdOutput = out.Write; + startupInfo.hStdInput = in.Read; + startupInfo.dwFlags = STARTF_USESTDHANDLES; + + PROCESS_INFORMATION processInfo{}; - // Unlock it so we won't deadlock - m_CriticalSection.Unlock(); + if (!CreateProcessW(*FromUTF8(serverExePath), const_cast(*FromUTF8(commandLine)), nullptr, nullptr, TRUE, + CREATE_NO_WINDOW | CREATE_UNICODE_ENVIRONMENT, nullptr, nullptr, &startupInfo, &processInfo)) + { + g_pCore->GetConsole()->Printf("Server process failed to start [error: %08x]: failed to create process\n", GetLastError()); + CloseHandle(readyEvent); + return false; } - // If we have a thread, wait for it to finish - if (m_hThread != INVALID_HANDLE_VALUE) + // Try to assign the project to our job object, if we have one. + if (job != nullptr && !AssignProcessToJobObject(job, processInfo.hProcess)) { - // Let the thread finish - WaitForSingleObject(m_hThread, INFINITE); + CloseHandle(job); + job = nullptr; + } - // If we can get an exit code, see if it's non-zero - DWORD dwExitCode = 0; - if (GetExitCodeThread(m_hThread, &dwExitCode)) - { - // Handle non-zero exit codes - if (dwExitCode != ERROR_NO_ERROR) - { - g_pCore->ShowMessageBox(_("Error") + _E("CD60"), _("Could not start the local server. See console for details."), MB_BUTTON_OK | MB_ICON_ERROR); - g_pCore->GetConsole()->Printf(_("Error: Could not start local server. [%s]"), szServerErrors[GetLastError()]); - } - } + // Close the handles managed by the server process. + CloseHandle(in.Read); + CloseHandle(out.Write); - // Close it - CloseHandle(m_hThread); - m_hThread = INVALID_HANDLE_VALUE; - } + // Close the thread handle, because we don't need it. + CloseHandle(processInfo.hThread); + + in.AutoClose = false; + out.AutoClose = false; - m_iLastError = ERROR_NO_ERROR; + m_stdin = in.Write; + m_stdout = out.Read; + m_isAcceptingConnections = false; + m_isRunning = true; + m_job = job; + m_readyEvent = readyEvent; + m_process = processInfo.hProcess; + m_processId = processInfo.dwProcessId; + g_pCore->GetConsole()->Printf("Server process has started [pid: %lu]\n", m_processId); return true; } -bool CServer::Send(const char* szString) +void CServer::Stop(bool graceful) { - // Server running? - bool bReturn = false; - if (g_bIsStarted) + if (!m_isRunning) + return; + + bool isRunning = IsProcessRunning(m_process); + + if (graceful && isRunning) { - // Wait for the library to come true or is started to go false - while (g_bIsStarted && !m_pLibrary) + DWORD bytesWritten{}; + + // Try to write a normal "exit" command to the server process. + if (WriteFile(m_stdin, "exit\n", 5, &bytesWritten, nullptr) && bytesWritten == 5) { - Sleep(1); + g_pCore->GetConsole()->Printf("Sent 'exit' command to the server to shut it down\n"); + WaitForSingleObject(m_process, 8000); } - - // Lock - m_CriticalSection.Lock(); - - // Are we running the server - if (m_pLibrary) + // Try to send a CTRl+C event to the process console. + else if (AttachConsole(m_processId)) { - // Grab the SendServerCommand function pointer - typedef bool(SendServerCommand_t)(const char*); - SendServerCommand_t* pfnSendServerCommand = reinterpret_cast(m_pLibrary->GetProcedureAddress("SendServerCommand")); - if (pfnSendServerCommand) - { - // Call it with the command - bReturn = pfnSendServerCommand(szString); - } + SetConsoleCtrlHandler(nullptr, true); + GenerateConsoleCtrlEvent(CTRL_C_EVENT, 0); + FreeConsole(); + g_pCore->GetConsole()->Printf("Sent 'CTRL+C' event to the server to shut it down\n"); + WaitForSingleObject(m_process, 8000); + SetConsoleCtrlHandler(nullptr, false); } - // Unlock - m_CriticalSection.Unlock(); + isRunning = IsProcessRunning(m_process); } - // Return - return bReturn; -} - -DWORD WINAPI CServer::Thread_EntryPoint(LPVOID pThis) -{ - return reinterpret_cast(pThis)->Thread_Run(); -} + // We either forcefully terminating the server, or the graceful shutdown failed. + if (isRunning) + { + g_pCore->GetConsole()->Printf("Terminating the server forcefully now\n"); -unsigned long CServer::Thread_Run() -{ - // Enter critical section - m_CriticalSection.Lock(); + TerminateProcess(m_process, PROCESS_FORCEFULLY_TERMINATED); + WaitForSingleObject(m_process, 3000); - // Already loaded? Just return or we get a memory leak. - if (m_pLibrary) - { - m_CriticalSection.Unlock(); - return 0; + if (m_job != nullptr) + { + CloseHandle(m_job); + m_job = nullptr; + } } - // Load the DLL - m_pLibrary = new CDynamicLibrary; - if (m_pLibrary->Load(m_strDLLFile)) + if (DWORD exitCode{}; GetExitCodeProcess(m_process, &exitCode)) { - // Grab the entrypoint - typedef int(Main_t)(int, char*[]); - Main_t* pfnEntryPoint = reinterpret_cast(m_pLibrary->GetProcedureAddress("Run")); - if (pfnEntryPoint) - { - // Populate the arguments array - char szArgument1[8]; - strcpy(szArgument1, "-D"); - - char szArgument2[256]; - strncpy(szArgument2, m_strServerRoot, 256); - szArgument2[255] = 0; - - char szArgument3[16]; - strcpy(szArgument3, "--config"); + const char* errorText = "Unknown exit code"; - char szArgument4[64]; - strcpy(szArgument4, m_strConfig); + if (exitCode == PROCESS_FORCEFULLY_TERMINATED) + errorText = "Process was forcefully terminated"; + else if (exitCode < (sizeof(szServerErrors) / sizeof(const char*))) + errorText = szServerErrors[exitCode]; - char szArgument5[8]; - strcpy(szArgument5, "-s"); - - char* szArguments[7]; - szArguments[0] = szArgument1; - szArguments[1] = szArgument2; - szArguments[2] = szArgument3; - szArguments[3] = szArgument4; - szArguments[4] = szArgument5; - - // Give the server our function to output stuff to the console - char szArgument6[32]; - strcpy(szArgument6, "--clientfeedback"); - szArguments[5] = szArgument6; - szArguments[6] = reinterpret_cast(CServer::AddServerOutput); + g_pCore->GetConsole()->Printf("Server process has been terminated [%08X]: %s\n", exitCode, errorText); + } - // We're now running the server - m_CriticalSection.Unlock(); + CloseHandle(m_readyEvent); + CloseHandle(m_stdin); + CloseHandle(m_stdout); + CloseHandle(m_process); - // Call it and grab what it returned - int iReturn = pfnEntryPoint(7, szArguments); + if (m_job != nullptr) + { + CloseHandle(m_job); + m_job = nullptr; + } - m_iLastError = iReturn; + m_isRunning = false; +} - // Lock again - m_CriticalSection.Lock(); +void CServer::Pulse() +{ + if (!m_isRunning) + return; - // Delete the library - delete m_pLibrary; - m_pLibrary = NULL; + // Try to read the process standard output and then write it to the console window. + if (DWORD numBytes{}; PeekNamedPipe(m_stdout, nullptr, 0, nullptr, &numBytes, nullptr) && numBytes > 0) + { + std::array buffer{}; - // Return what the server returned - m_CriticalSection.Unlock(); - g_bIsStarted = false; - return iReturn; + if (ReadFile(m_stdout, buffer.data(), std::min(buffer.size(), numBytes), &numBytes, nullptr) && numBytes > 0) + { + g_pCore->GetConsole()->Printf("%.*s", numBytes, buffer.data()); } } - // Delete the library again - delete m_pLibrary; - m_pLibrary = NULL; - - // Unlock the critialsection and return failed - m_CriticalSection.Unlock(); - g_bIsStarted = false; - return 1; -} - -void CServer::AddServerOutput(const char* szOutput) -{ - // Make sure the client doesn't process the queue right now - m_OutputCC.Lock(); - - // Add the string to the queue - m_OutputQueue.push_back(szOutput); + // Check if the server process was terminated externally. + if (!IsProcessRunning(m_process)) + { + Stop(); + return; + } - // Unlock again - m_OutputCC.Unlock(); + // Check if the server process signalised readyness to accept connections. + if (m_readyEvent != nullptr) + { + if (WaitForSingleObject(m_readyEvent, 0) != WAIT_TIMEOUT) + { + CloseHandle(m_readyEvent); + m_readyEvent = nullptr; + m_isAcceptingConnections = true; + } + } } diff --git a/Client/mods/deathmatch/logic/CServer.h b/Client/mods/deathmatch/logic/CServer.h index e88100ca30..b6f324e799 100644 --- a/Client/mods/deathmatch/logic/CServer.h +++ b/Client/mods/deathmatch/logic/CServer.h @@ -1,59 +1,43 @@ /***************************************************************************** * - * PROJECT: Multi Theft Auto v1.0 + * PROJECT: Multi Theft Auto * LICENSE: See LICENSE in the top level directory * FILE: mods/deathmatch/logic/CServer.h * PURPOSE: Header for server class * - * Multi Theft Auto is available from http://www.multitheftauto.com/ + * Multi Theft Auto is available from https://multitheftauto.com/ * *****************************************************************************/ #pragma once -#include "CDynamicLibrary.h" -#include -#include - -class CServer +class CServer final { public: - CServer(); - ~CServer(); - - void DoPulse(); - - bool Start(const char* szConfig); - bool Stop(); - bool IsStarted(); - bool IsRunning() { return m_pLibrary != NULL; }; - bool IsReady() { return m_bIsReady; }; + ~CServer() { Stop(); } - int GetLastError() { return m_iLastError; }; + bool Start(const char* configFileName); - bool Send(const char* szString); + void Stop(bool graceful = true); - const std::string& GetPassword() { return m_strPassword; }; - void SetPassword(const char* szPassword) { m_strPassword = szPassword; }; + void Pulse(); -private: - static DWORD WINAPI Thread_EntryPoint(LPVOID pThis); - unsigned long Thread_Run(); - - bool m_bIsReady; - HANDLE m_hThread; - CDynamicLibrary* volatile m_pLibrary; - CCriticalSection m_CriticalSection; - SString m_strServerRoot; - SString m_strDLLFile; - SString m_strConfig; + bool IsRunning() const noexcept { return m_isRunning; } - int m_iLastError; + bool IsReady() const noexcept { return m_isRunning && m_isAcceptingConnections; } - std::string m_strPassword; + void SetPassword(const char* password) { m_password = password; } - static CCriticalSection m_OutputCC; - static std::list m_OutputQueue; + const std::string& GetPassword() const noexcept { return m_password; } - static void AddServerOutput(const char* szOutput); +private: + bool m_isRunning{}; + bool m_isAcceptingConnections{}; + HANDLE m_job{}; + HANDLE m_readyEvent{}; + HANDLE m_process{}; + DWORD m_processId{}; + HANDLE m_stdout{}; + HANDLE m_stdin{}; + std::string m_password; }; diff --git a/Client/mods/deathmatch/logic/CStaticFunctionDefinitions.cpp b/Client/mods/deathmatch/logic/CStaticFunctionDefinitions.cpp index e5bff5a93d..1c8d34379d 100644 --- a/Client/mods/deathmatch/logic/CStaticFunctionDefinitions.cpp +++ b/Client/mods/deathmatch/logic/CStaticFunctionDefinitions.cpp @@ -2,10 +2,10 @@ * * PROJECT: Multi Theft Auto * LICENSE: See LICENSE in the top level directory - * FILE: mods/deathmatch/logic/CStaticFunctionDefinitions.cpp + * FILE: Client/mods/deathmatch/logic/CStaticFunctionDefinitions.cpp * PURPOSE: Scripting function processing * - * Multi Theft Auto is available from http://www.multitheftauto.com/ + * Multi Theft Auto is available from https://multitheftauto.com/ * *****************************************************************************/ @@ -27,6 +27,7 @@ #include #include #include +#include #include using std::list; @@ -426,6 +427,16 @@ bool CStaticFunctionDefinitions::GetElementRotation(CClientEntity& Entity, CVect } break; } + case CCLIENTBUILDING: + { + CClientBuilding& pBuilding = static_cast(Entity); + pBuilding.GetRotationDegrees(vecRotation); + if (desiredRotOrder != EULER_DEFAULT && desiredRotOrder != EULER_ZXY) + { + vecRotation = ConvertEulerRotationOrder(vecRotation, EULER_ZXY, desiredRotOrder); + } + break; + } case CCLIENTPROJECTILE: { CClientProjectile& Projectile = static_cast(Entity); @@ -552,6 +563,13 @@ bool CStaticFunctionDefinitions::GetElementBoundingBox(CClientEntity& Entity, CV pModelInfo = g_pGame->GetModelInfo(Object.GetModel()); break; } + case CCLIENTBUILDING: + { + CClientBuilding& building = static_cast(Entity); + pModelInfo = g_pGame->GetModelInfo(building.GetModel()); + break; + } + } if (pModelInfo) @@ -762,6 +780,12 @@ bool CStaticFunctionDefinitions::GetElementModel(CClientEntity& Entity, unsigned usModel = pPickup.GetModel(); break; } + case CCLIENTBUILDING: + { + CClientBuilding& pBuilding = static_cast(Entity); + usModel = pBuilding.GetModel(); + break; + } case CCLIENTPROJECTILE: { CClientProjectile& pProjectile = static_cast(Entity); @@ -1107,6 +1131,19 @@ bool CStaticFunctionDefinitions::SetElementRotation(CClientEntity& Entity, const break; } + case CCLIENTBUILDING: + { + CClientBuilding& pBuilding = static_cast(Entity); + if (argumentRotOrder == EULER_DEFAULT || argumentRotOrder == EULER_ZXY) + { + pBuilding.SetRotationDegrees(vecRotation); + } + else + { + pBuilding.SetRotationDegrees(ConvertEulerRotationOrder(vecRotation, argumentRotOrder, EULER_ZXY)); + } + break; + } case CCLIENTPROJECTILE: { // Didn't implement anything for projectiles since I couldn't really test (only non crashing element was satchel and its rotation is ugly) @@ -1210,47 +1247,44 @@ bool CStaticFunctionDefinitions::SetElementAngularVelocity(CClientEntity& Entity bool CStaticFunctionDefinitions::SetElementParent(CClientEntity& Entity, CClientEntity& Parent, CLuaMain* pLuaMain) { - if (&Entity != &Parent && !Entity.IsMyChild(&Parent, true)) + if (&Entity == &Parent || Entity.IsMyChild(&Parent, true)) + return false; + + if (Entity.GetType() == CCLIENTCAMERA || Parent.GetType() == CCLIENTCAMERA) + return false; + + if (Entity.GetType() == CCLIENTGUI) { - if (Entity.GetType() == CCLIENTCAMERA || Parent.GetType() == CCLIENTCAMERA) - { + if (Parent.GetType() != CCLIENTGUI && &Parent != pLuaMain->GetResource()->GetResourceGUIEntity()) return false; - } - else if (Entity.GetType() == CCLIENTGUI) - { - if (Parent.GetType() == CCLIENTGUI || &Parent == pLuaMain->GetResource()->GetResourceGUIEntity()) - { - CClientGUIElement& GUIElement = static_cast(Entity); - GUIElement.SetParent(&Parent); - return true; - } - } - else - { - CClientEntity* pTemp = &Parent; - CClientEntity* pRoot = m_pRootEntity; - bool bValidParent = false; - while (pTemp != pRoot && pTemp != NULL) - { - const char* szTypeName = pTemp->GetTypeName(); - if (szTypeName && strcmp(szTypeName, "map") == 0) - { - bValidParent = true; // parents must be a map - break; - } + CClientGUIElement& GUIElement = static_cast(Entity); - pTemp = pTemp->GetParent(); - } + GUIElement.SetParent(&Parent); + return true; + } - // Make sure the entity we move is a client entity or we get a problem - if (bValidParent && Entity.IsLocalEntity()) - { - // Set the new parent - Entity.SetParent(&Parent); - return true; - } + CClientEntity* pTemp = &Parent; + CClientEntity* pRoot = m_pRootEntity; + bool bValidParent = false; + while (pTemp != pRoot && pTemp != NULL) + { + const char* szTypeName = pTemp->GetTypeName(); + if (szTypeName && strcmp(szTypeName, "map") == 0) + { + bValidParent = true; // parents must be a map + break; } + + pTemp = pTemp->GetParent(); + } + + // Make sure the entity we move is a client entity or we get a problem + if (bValidParent && Entity.IsLocalEntity()) + { + // Set the new parent + Entity.SetParent(&Parent); + return true; } return false; @@ -1428,13 +1462,8 @@ bool CStaticFunctionDefinitions::SetElementHealth(CClientEntity& Entity, float f // Grab the model CClientPed& Ped = static_cast(Entity); - // Limit to max health - float fMaxHealth = Ped.GetMaxHealth(); - if (fHealth > fMaxHealth) - fHealth = fMaxHealth; - // Set the new health - Ped.SetHealth(fHealth); + Ped.SetHealth(Clamp(0.0f, fHealth, Ped.GetMaxHealth())); return true; break; } @@ -1461,6 +1490,26 @@ bool CStaticFunctionDefinitions::SetElementModel(CClientEntity& Entity, unsigned { RUN_CHILDREN(SetElementModel(**iter, usModel)) + auto callOnChangeEvent = [](auto &element, uint16_t usCurrentModel, uint16_t usModel) { + CLuaArguments Arguments; + Arguments.PushNumber(usCurrentModel); + Arguments.PushNumber(usModel); + bool bContinue = element.CallEvent("onClientElementModelChange", Arguments, true); + + // Check for another call to setElementModel + if (usModel != element.GetModel()) + return false; + + if (!bContinue) + { + // Change canceled + element.SetModel(usCurrentModel); + return false; + } + + return true; + }; + switch (Entity.GetType()) { case CCLIENTPED: @@ -1476,23 +1525,7 @@ bool CStaticFunctionDefinitions::SetElementModel(CClientEntity& Entity, unsigned if (!Ped.SetModel(usModel)) return false; - CLuaArguments Arguments; - Arguments.PushNumber(usCurrentModel); - Arguments.PushNumber(usModel); - bool bContinue = Ped.CallEvent("onClientElementModelChange", Arguments, true); - - // Check for another call to setElementModel - if (usModel != Ped.GetModel()) - return false; - - if (!bContinue) - { - // Change canceled - Ped.SetModel(usCurrentModel); - return false; - } - - break; + return callOnChangeEvent(Ped, usCurrentModel, usModel); } case CCLIENTVEHICLE: { @@ -1539,23 +1572,22 @@ bool CStaticFunctionDefinitions::SetElementModel(CClientEntity& Entity, unsigned Object.SetModel(usModel); - CLuaArguments Arguments; - Arguments.PushNumber(usCurrentModel); - Arguments.PushNumber(usModel); - bool bContinue = Object.CallEvent("onClientElementModelChange", Arguments, true); + return callOnChangeEvent(Object, usCurrentModel, usModel); + } + case CCLIENTBUILDING: + { + CClientBuilding& Object = static_cast(Entity); + const unsigned short usCurrentModel = Object.GetModel(); - // Check for another call to setElementModel - if (usModel != Object.GetModel()) + if (usCurrentModel == usModel) return false; - if (!bContinue) - { - // Change canceled - Object.SetModel(usCurrentModel); + if (!CClientObjectManager::IsValidModel(usModel)) return false; - } - break; + Object.SetModel(usModel); + + return callOnChangeEvent(Object, usCurrentModel, usModel); } case CCLIENTPROJECTILE: { @@ -1570,11 +1602,7 @@ bool CStaticFunctionDefinitions::SetElementModel(CClientEntity& Entity, unsigned Projectile.SetModel(usModel); - CLuaArguments Arguments; - Arguments.PushNumber(usCurrentModel); - Arguments.PushNumber(usModel); - Projectile.CallEvent("onClientElementModelChange", Arguments, true); - break; + return callOnChangeEvent(Projectile, usCurrentModel, usModel); } default: return false; @@ -2117,7 +2145,8 @@ bool CStaticFunctionDefinitions::KillPed(CClientEntity& Entity, CClientEntity* p else Arguments.PushBoolean(false); Arguments.PushBoolean(bStealth); - + Arguments.PushBoolean(false); + Arguments.PushBoolean(false); pPed.CallEvent("onClientPedWasted", Arguments, false); pPed.RemoveAllWeapons(); @@ -2206,15 +2235,15 @@ bool CStaticFunctionDefinitions::SetPedAnimation(CClientEntity& Entity, const SS if (pIFP) { // Play the gateway animation - const SString& strGateWayBlockName = g_pGame->GetAnimManager()->GetGateWayBlockName(); - std::unique_ptr pBlock = g_pGame->GetAnimManager()->GetAnimationBlock(strGateWayBlockName); + const char* szGateWayBlockName = g_pGame->GetAnimManager()->GetGateWayBlockName(); + std::unique_ptr pBlock = g_pGame->GetAnimManager()->GetAnimationBlock(szGateWayBlockName); auto pCustomAnimBlendHierarchy = pIFP->GetAnimationHierarchy(szAnimName); if ((pBlock) && (pCustomAnimBlendHierarchy != nullptr)) { Ped.SetNextAnimationCustom(pIFP, szAnimName); - const SString& strGateWayAnimationName = g_pGame->GetAnimManager()->GetGateWayAnimationName(); - Ped.RunNamedAnimation(pBlock, strGateWayAnimationName, iTime, iBlend, bLoop, bUpdatePosition, bInterruptable, bFreezeLastFrame); + const char* szGateWayAnimationName = g_pGame->GetAnimManager()->GetGateWayAnimationName(); + Ped.RunNamedAnimation(pBlock, szGateWayAnimationName, iTime, iBlend, bLoop, bUpdatePosition, bInterruptable, bFreezeLastFrame); return true; } } @@ -3728,6 +3757,11 @@ bool CStaticFunctionDefinitions::SetElementCollisionsEnabled(CClientEntity& Enti Ped.SetUsesCollision(bEnabled); break; } + case CCLIENTBUILDING: + { + static_cast(Entity).SetUsesCollision(bEnabled); + break; + } default: return false; } @@ -3802,7 +3836,12 @@ bool CStaticFunctionDefinitions::SetLowLodElement(CClientEntity& Entity, CClient { RUN_CHILDREN(SetLowLodElement(**iter, pLowLodEntity)) - switch (Entity.GetType()) + eClientEntityType entityType = Entity.GetType(); + + if (pLowLodEntity != nullptr && entityType != pLowLodEntity->GetType()) + return false; + + switch (entityType) { case CCLIENTOBJECT: { @@ -3812,6 +3851,14 @@ bool CStaticFunctionDefinitions::SetLowLodElement(CClientEntity& Entity, CClient return false; break; } + case CCLIENTBUILDING: + { + CClientBuilding& Building = static_cast(Entity); + CClientBuilding* pLowLodBuilding = static_cast(pLowLodEntity); + if (!Building.SetLowLodBuilding(pLowLodBuilding)) + return false; + break; + } default: return false; } @@ -3831,6 +3878,12 @@ bool CStaticFunctionDefinitions::GetLowLodElement(CClientEntity& Entity, CClient pOutLowLodEntity = Object.GetLowLodObject(); break; } + case CCLIENTBUILDING: + { + CClientBuilding& Building = static_cast(Entity); + pOutLowLodEntity = Building.GetLowLodBuilding(); + break; + } default: return false; } @@ -3850,6 +3903,12 @@ bool CStaticFunctionDefinitions::IsElementLowLod(CClientEntity& Entity, bool& bO bOutIsLowLod = Object.IsLowLod(); break; } + case CCLIENTBUILDING: + { + CClientBuilding& Building = static_cast(Entity); + bOutIsLowLod = Building.IsLod(); + break; + } default: return false; } @@ -4707,7 +4766,7 @@ bool CStaticFunctionDefinitions::SetBlipVisibleDistance(CClientEntity& Entity, u return false; } -CClientMarker* CStaticFunctionDefinitions::CreateMarker(CResource& Resource, const CVector& vecPosition, const char* szType, float fSize, const SColor color) +CClientMarker* CStaticFunctionDefinitions::CreateMarker(CResource& Resource, const CVector& vecPosition, const char* szType, float fSize, const SColor color, bool ignoreAlphaLimits) { assert(szType); @@ -4721,6 +4780,10 @@ CClientMarker* CStaticFunctionDefinitions::CreateMarker(CResource& Resource, con // Set its parent and its properties pMarker->SetParent(Resource.GetResourceDynamicEntity()); pMarker->SetPosition(vecPosition); + + if (ucType == CClientMarker::MARKER_ARROW || ucType == CClientMarker::MARKER_CHECKPOINT) + pMarker->SetIgnoreAlphaLimits(ignoreAlphaLimits); + pMarker->SetColor(color); pMarker->SetSize(fSize); @@ -4859,6 +4922,25 @@ bool CStaticFunctionDefinitions::SetMarkerIcon(CClientEntity& Entity, const char return false; } +bool CStaticFunctionDefinitions::SetMarkerTargetArrowProperties(CClientEntity& Entity, const SColor color, float size) +{ + RUN_CHILDREN(SetMarkerTargetArrowProperties(**iter, color, size)) + + if (!IS_MARKER(&Entity)) + return false; + + CClientMarker& marker = static_cast(Entity); + CClientCheckpoint* checkpoint = marker.GetCheckpoint(); + if (!checkpoint) + return false; + + if (checkpoint->GetIcon() != CClientCheckpoint::ICON_ARROW) + return false; + + checkpoint->SetTargetArrowProperties(color, size); + return true; +} + bool CStaticFunctionDefinitions::GetCameraMatrix(CVector& vecPosition, CVector& vecLookAt, float& fRoll, float& fFOV) { m_pCamera->GetPosition(vecPosition); @@ -6653,20 +6735,20 @@ bool CStaticFunctionDefinitions::AreTrafficLightsLocked(bool& bLocked) bool CStaticFunctionDefinitions::RemoveWorldBuilding(unsigned short usModelToRemove, float fRadius, float fX, float fY, float fZ, char cInterior, uint& uiOutAmount) { - g_pGame->GetWorld()->RemoveBuilding(usModelToRemove, fRadius, fX, fY, fZ, cInterior, &uiOutAmount); + g_pGame->GetBuildingRemoval()->RemoveBuilding(usModelToRemove, fRadius, fX, fY, fZ, cInterior, &uiOutAmount); return true; } bool CStaticFunctionDefinitions::RestoreWorldBuildings(uint& uiOutAmount) { - g_pGame->GetWorld()->ClearRemovedBuildingLists(&uiOutAmount); + g_pGame->GetBuildingRemoval()->ClearRemovedBuildingLists(&uiOutAmount); return true; } bool CStaticFunctionDefinitions::RestoreWorldBuilding(unsigned short usModelToRestore, float fRadius, float fX, float fY, float fZ, char cInterior, uint& uiOutAmount) { - return g_pGame->GetWorld()->RestoreBuilding(usModelToRestore, fRadius, fX, fY, fZ, cInterior, &uiOutAmount); + return g_pGame->GetBuildingRemoval()->RestoreBuilding(usModelToRestore, fRadius, fX, fY, fZ, cInterior, &uiOutAmount); } bool CStaticFunctionDefinitions::GetSkyGradient(unsigned char& ucTopRed, unsigned char& ucTopGreen, unsigned char& ucTopBlue, unsigned char& ucBottomRed, @@ -7225,6 +7307,7 @@ CClientProjectile* CStaticFunctionDefinitions::CreateProjectile(CResource& Resou case WEAPONTYPE_ROCKET_HS: case WEAPONTYPE_FREEFALL_BOMB: case WEAPONTYPE_REMOTE_SATCHEL_CHARGE: + case WEAPONTYPE_FLARE: { // Valid model ID? (0 means projectile will use default model) if (usModel == 0 || CClientObjectManager::IsValidModel(usModel)) @@ -7867,6 +7950,12 @@ bool CStaticFunctionDefinitions::FxAddFootSplash(CVector& vecPosition) return true; } +bool CStaticFunctionDefinitions::FxCreateParticle(eFxParticleSystems eFxParticle, CVector& vecPosition, CVector& vecDirection, float fR, float fG, float fB, float fA, bool bRandomizeColors, std::uint32_t iCount, float fBrightness, float fSize, bool bRandomizeSizes, float fLife) +{ + g_pGame->GetFx()->AddParticle(eFxParticle, vecPosition, vecDirection, fR, fG, fB, fA, bRandomizeColors, iCount, fBrightness, fSize, bRandomizeSizes, fLife); + return true; +} + CClientEffect* CStaticFunctionDefinitions::CreateEffect(CResource& Resource, const SString& strFxName, const CVector& vecPosition, bool bSoundEnable) { CClientEffect* pFx = m_pManager->GetEffectManager()->Create(strFxName, vecPosition, INVALID_ELEMENT_ID, bSoundEnable); diff --git a/Client/mods/deathmatch/logic/CStaticFunctionDefinitions.h b/Client/mods/deathmatch/logic/CStaticFunctionDefinitions.h index 437e4503f6..2d1ce8c88a 100644 --- a/Client/mods/deathmatch/logic/CStaticFunctionDefinitions.h +++ b/Client/mods/deathmatch/logic/CStaticFunctionDefinitions.h @@ -366,7 +366,7 @@ class CStaticFunctionDefinitions static bool SetBlipVisibleDistance(CClientEntity& Entity, unsigned short usVisibleDistance); // Marker create/destroy funcs - static CClientMarker* CreateMarker(CResource& Resource, const CVector& vecPosition, const char* szType, float fSize, const SColor color); + static CClientMarker* CreateMarker(CResource& Resource, const CVector& vecPosition, const char* szType, float fSize, const SColor color, bool ignoreAlphaLimits); // Marker get funcs static bool GetMarkerTarget(CClientMarker& Marker, CVector& vecTarget); @@ -377,6 +377,7 @@ class CStaticFunctionDefinitions static bool SetMarkerColor(CClientEntity& Entity, const SColor color); static bool SetMarkerTarget(CClientEntity& Entity, const CVector* pTarget); static bool SetMarkerIcon(CClientEntity& Entity, const char* szIcon); + static bool SetMarkerTargetArrowProperties(CClientEntity& Entity, const SColor color, float size); // Camera get funcs static bool GetCameraMatrix(CVector& vecPosition, CVector& vecLookAt, float& fRoll, float& fFOV); @@ -729,6 +730,7 @@ class CStaticFunctionDefinitions static bool FxAddWaterSplash(CVector& vecPosition); static bool FxAddBulletSplash(CVector& vecPosition); static bool FxAddFootSplash(CVector& vecPosition); + static bool FxCreateParticle(eFxParticleSystems eFxParticle, CVector& vecPosition, CVector& vecDirection, float fR, float fG, float fB, float fA, bool bRandomizeColors, std::uint32_t iCount, float fBrightness, float fSize, bool bRandomizeSizes, float fLife); static CClientEffect* CreateEffect(CResource& Resource, const SString& strFxName, const CVector& vecPosition, bool bSoundEnable); // Sound funcs diff --git a/Client/mods/deathmatch/logic/lua/CLuaArgument.cpp b/Client/mods/deathmatch/logic/lua/CLuaArgument.cpp index 3a5f50df3f..7ed7b463c3 100644 --- a/Client/mods/deathmatch/logic/lua/CLuaArgument.cpp +++ b/Client/mods/deathmatch/logic/lua/CLuaArgument.cpp @@ -176,9 +176,9 @@ bool CLuaArgument::CompareRecursive(const CLuaArgument& Argument, std::setCount() != Argument.m_pTableData->Count()) return false; - vector::const_iterator iter = m_pTableData->IterBegin(); - vector::const_iterator iterCompare = Argument.m_pTableData->IterBegin(); - while (iter != m_pTableData->IterEnd() && iterCompare != Argument.m_pTableData->IterEnd()) + vector::const_iterator iter = m_pTableData->begin(); + vector::const_iterator iterCompare = Argument.m_pTableData->begin(); + while (iter != m_pTableData->end() && iterCompare != Argument.m_pTableData->end()) { if (pKnownTables->find(m_pTableData) == pKnownTables->end()) { @@ -320,11 +320,25 @@ void CLuaArgument::ReadNumber(double dNumber) m_Number = dNumber; } -void CLuaArgument::ReadString(const std::string& strString) +void CLuaArgument::ReadString(const std::string& string) { m_iType = LUA_TSTRING; DeleteTableData(); - m_strString = strString; + m_strString = string; +} + +void CLuaArgument::ReadString(const std::string_view& string) +{ + m_iType = LUA_TSTRING; + DeleteTableData(); + m_strString = std::string{string}; +} + +void CLuaArgument::ReadString(const char* string) +{ + m_iType = LUA_TSTRING; + DeleteTableData(); + m_strString = string; } void CLuaArgument::ReadScriptID(uint uiScriptID) @@ -757,6 +771,11 @@ bool CLuaArgument::WriteToBitStream(NetBitStreamInterface& bitStream, CFastHashM return true; } +bool CLuaArgument::IsTable() const noexcept +{ + return m_iType == LUA_TTABLE && m_pTableData && (m_pTableData->Count() % 2) == 0; +} + void CLuaArgument::LogUnableToPacketize(const char* szMessage) const { #ifdef MTA_DEBUG diff --git a/Client/mods/deathmatch/logic/lua/CLuaArgument.h b/Client/mods/deathmatch/logic/lua/CLuaArgument.h index a0b8a416ed..3cb5b45190 100644 --- a/Client/mods/deathmatch/logic/lua/CLuaArgument.h +++ b/Client/mods/deathmatch/logic/lua/CLuaArgument.h @@ -40,7 +40,9 @@ class CLuaArgument void Read(lua_State* luaVM, int iArgument, CFastHashMap* pKnownTables = NULL); void ReadBool(bool bBool); void ReadNumber(double dNumber); - void ReadString(const std::string& strString); + void ReadString(const std::string& string); + void ReadString(const std::string_view& string); + void ReadString(const char* string); void ReadElement(CClientEntity* pElement); void ReadScriptID(uint uiScriptID); void ReadElementID(ElementID ID); @@ -55,6 +57,7 @@ class CLuaArgument lua_Number GetNumber() const { return m_Number; }; const SString& GetString() { return m_strString; }; void* GetUserData() const { return m_pUserData; }; + CLuaArguments* GetTable() const { return m_pTableData; } CClientEntity* GetElement() const; bool ReadFromBitStream(NetBitStreamInterface& bitStream, std::vector* pKnownTables = NULL); @@ -63,6 +66,48 @@ class CLuaArgument bool ReadFromJSONObject(json_object* object, std::vector* pKnownTables = NULL); char* WriteToString(char* szBuffer, int length); + [[nodiscard]] bool IsString() const noexcept { return m_iType == LUA_TSTRING; } + + [[nodiscard]] bool TryGetString(std::string_view& string) const noexcept + { + if (IsString()) + { + string = m_strString; + return true; + } + + string = {}; + return false; + } + + [[nodiscard]] bool IsNumber() const noexcept { return m_iType == LUA_TNUMBER; } + + [[nodiscard]] bool TryGetNumber(lua_Number& number) const noexcept + { + if (IsNumber()) + { + number = m_Number; + return true; + } + + number = {}; + return false; + } + + [[nodiscard]] bool IsTable() const noexcept; + + [[nodiscard]] bool TryGetTable(CLuaArguments*& table) + { + if (IsTable()) + { + table = m_pTableData; + return true; + } + + table = nullptr; + return false; + } + private: void LogUnableToPacketize(const char* szMessage) const; diff --git a/Client/mods/deathmatch/logic/lua/CLuaArguments.cpp b/Client/mods/deathmatch/logic/lua/CLuaArguments.cpp index c93cc86bb4..6b4de4ec33 100644 --- a/Client/mods/deathmatch/logic/lua/CLuaArguments.cpp +++ b/Client/mods/deathmatch/logic/lua/CLuaArguments.cpp @@ -191,11 +191,9 @@ void CLuaArguments::PushAsTable(lua_State* luaVM, CFastHashMap::const_iterator iter = Arguments.IterBegin(); - for (; iter != Arguments.IterEnd(); iter++) + for (CLuaArgument* arg : Arguments) { - CLuaArgument* pArgument = new CLuaArgument(**iter); - m_Arguments.push_back(pArgument); + m_Arguments.push_back(new CLuaArgument(*arg)); } } @@ -337,12 +335,28 @@ CLuaArgument* CLuaArguments::PushNumber(double dNumber) return pArgument; } -CLuaArgument* CLuaArguments::PushString(const std::string& strString) +CLuaArgument* CLuaArguments::PushString(const std::string& string) { - CLuaArgument* pArgument = new CLuaArgument(); - pArgument->ReadString(strString); - m_Arguments.push_back(pArgument); - return pArgument; + CLuaArgument* arg = new CLuaArgument(); + arg->ReadString(string); + m_Arguments.push_back(arg); + return arg; +} + +CLuaArgument* CLuaArguments::PushString(const std::string_view& string) +{ + CLuaArgument* arg = new CLuaArgument(); + arg->ReadString(string); + m_Arguments.push_back(arg); + return arg; +} + +CLuaArgument* CLuaArguments::PushString(const char* string) +{ + CLuaArgument* arg = new CLuaArgument(); + arg->ReadString(string); + m_Arguments.push_back(arg); + return arg; } CLuaArgument* CLuaArguments::PushResource(CResource* pResource) diff --git a/Client/mods/deathmatch/logic/lua/CLuaArguments.h b/Client/mods/deathmatch/logic/lua/CLuaArguments.h index 89011983f2..45ec796cbb 100644 --- a/Client/mods/deathmatch/logic/lua/CLuaArguments.h +++ b/Client/mods/deathmatch/logic/lua/CLuaArguments.h @@ -55,7 +55,9 @@ class CLuaArguments CLuaArgument* PushNil(); CLuaArgument* PushBoolean(bool bBool); CLuaArgument* PushNumber(double dNumber); - CLuaArgument* PushString(const std::string& strString); + CLuaArgument* PushString(const std::string& string); + CLuaArgument* PushString(const std::string_view& string); + CLuaArgument* PushString(const char* string); CLuaArgument* PushElement(CClientEntity* pElement); CLuaArgument* PushArgument(const CLuaArgument& argument); CLuaArgument* PushResource(CResource* pResource); @@ -74,9 +76,13 @@ class CLuaArguments bool ReadFromJSONObject(json_object* object, std::vector* pKnownTables = NULL); bool ReadFromJSONArray(json_object* object, std::vector* pKnownTables = NULL); - unsigned int Count() const { return static_cast(m_Arguments.size()); }; - std::vector::const_iterator IterBegin() const { return m_Arguments.begin(); }; - std::vector::const_iterator IterEnd() const { return m_Arguments.end(); }; + [[nodiscard]] bool IsNotEmpty() const noexcept { return !m_Arguments.empty(); } + [[nodiscard]] bool IsEmpty() const noexcept { return m_Arguments.empty(); } + + [[nodiscard]] std::vector::size_type Count() const noexcept { return m_Arguments.size(); } + + [[nodiscard]] std::vector::const_iterator begin() const noexcept { return m_Arguments.begin(); } + [[nodiscard]] std::vector::const_iterator end() const noexcept { return m_Arguments.end(); } private: std::vector m_Arguments; diff --git a/Client/mods/deathmatch/logic/lua/CLuaFunctionDefs.Output.cpp b/Client/mods/deathmatch/logic/lua/CLuaFunctionDefs.Output.cpp index 11169b0dc8..7ba00b4b26 100644 --- a/Client/mods/deathmatch/logic/lua/CLuaFunctionDefs.Output.cpp +++ b/Client/mods/deathmatch/logic/lua/CLuaFunctionDefs.Output.cpp @@ -127,25 +127,23 @@ int CLuaFunctionDefs::OutputClientDebugString(lua_State* luaVM) CLuaMain* pLuaMain = m_pLuaManager->GetVirtualMachine(luaVM); if (pLuaMain) { - if (uiLevel == 1) + switch (uiLevel) { - m_pScriptDebugging->LogError(luaVM, "%s", strText.c_str()); - } - else if (uiLevel == 2) - { - m_pScriptDebugging->LogWarning(luaVM, "%s", strText.c_str()); - } - else if (uiLevel == 3) - { - m_pScriptDebugging->LogInformation(luaVM, "%s", strText.c_str()); - } - else if (uiLevel == 4) - { - m_pScriptDebugging->LogCustom(luaVM, ucRed, ucGreen, ucBlue, "%s", strText.c_str()); - } - else if (uiLevel == 0) - { - m_pScriptDebugging->LogDebug(luaVM, ucRed, ucGreen, ucBlue, "%s", strText.c_str()); + case 0: + m_pScriptDebugging->LogDebug(luaVM, ucRed, ucGreen, ucBlue, "%s", strText.c_str()); + break; + case 1: + m_pScriptDebugging->LogError(luaVM, "%s", strText.c_str()); + break; + case 2: + m_pScriptDebugging->LogWarning(luaVM, "%s", strText.c_str()); + break; + case 3: + m_pScriptDebugging->LogInformation(luaVM, "%s", strText.c_str()); + break; + case 4: + m_pScriptDebugging->LogCustom(luaVM, ucRed, ucGreen, ucBlue, "%s", strText.c_str()); + break; } // Success diff --git a/Client/mods/deathmatch/logic/lua/CLuaFunctionDefs.cpp b/Client/mods/deathmatch/logic/lua/CLuaFunctionDefs.cpp index 912fd99f66..feb2bdf058 100644 --- a/Client/mods/deathmatch/logic/lua/CLuaFunctionDefs.cpp +++ b/Client/mods/deathmatch/logic/lua/CLuaFunctionDefs.cpp @@ -31,6 +31,7 @@ CClientDFFManager* CLuaFunctionDefs::m_pDFFManager; CClientColModelManager* CLuaFunctionDefs::m_pColModelManager; CRegisteredCommands* CLuaFunctionDefs::m_pRegisteredCommands; CClientIMGManager* CLuaFunctionDefs::m_pImgManager; +CClientBuildingManager* CLuaFunctionDefs::m_pBuildingManager; void CLuaFunctionDefs::Initialize(CLuaManager* pLuaManager, CScriptDebugging* pScriptDebugging, CClientGame* pClientGame) { @@ -55,4 +56,5 @@ void CLuaFunctionDefs::Initialize(CLuaManager* pLuaManager, CScriptDebugging* pS m_pColModelManager = m_pManager->GetColModelManager(); m_pRegisteredCommands = m_pClientGame->GetRegisteredCommands(); m_pImgManager = m_pManager->GetIMGManager(); + m_pBuildingManager = m_pManager->GetBuildingManager(); } diff --git a/Client/mods/deathmatch/logic/lua/CLuaFunctionDefs.h b/Client/mods/deathmatch/logic/lua/CLuaFunctionDefs.h index 1681110616..105754152f 100644 --- a/Client/mods/deathmatch/logic/lua/CLuaFunctionDefs.h +++ b/Client/mods/deathmatch/logic/lua/CLuaFunctionDefs.h @@ -139,4 +139,5 @@ class CLuaFunctionDefs static CClientColModelManager* m_pColModelManager; static CRegisteredCommands* m_pRegisteredCommands; static CClientIMGManager* m_pImgManager; + static CClientBuildingManager* m_pBuildingManager; }; diff --git a/Client/mods/deathmatch/logic/lua/CLuaFunctionParseHelpers.cpp b/Client/mods/deathmatch/logic/lua/CLuaFunctionParseHelpers.cpp index ba91b03381..64708dea0c 100644 --- a/Client/mods/deathmatch/logic/lua/CLuaFunctionParseHelpers.cpp +++ b/Client/mods/deathmatch/logic/lua/CLuaFunctionParseHelpers.cpp @@ -824,6 +824,92 @@ ADD_ENUM(_D3DFORMAT::D3DFMT_G32R32F, "g32r32f") ADD_ENUM(_D3DFORMAT::D3DFMT_A32B32G32R32F, "a32b32g32r32f") IMPLEMENT_ENUM_CLASS_END("surface-format") +IMPLEMENT_ENUM_CLASS_BEGIN(eRenderStage) +ADD_ENUM(eRenderStage::PRE_FX, "prefx") +ADD_ENUM(eRenderStage::POST_FX, "postfx") +ADD_ENUM(eRenderStage::POST_GUI, "postgui") +IMPLEMENT_ENUM_CLASS_END("render-stage") + +IMPLEMENT_ENUM_BEGIN(ePools) +ADD_ENUM(ePools::BUILDING_POOL, "building") +ADD_ENUM(ePools::PED_POOL, "ped") +ADD_ENUM(ePools::OBJECT_POOL, "object") +ADD_ENUM(ePools::DUMMY_POOL, "dummy") +ADD_ENUM(ePools::VEHICLE_POOL, "vehicle") +ADD_ENUM(ePools::COL_MODEL_POOL, "col-model") +ADD_ENUM(ePools::TASK_POOL, "task") +ADD_ENUM(ePools::EVENT_POOL, "event") +ADD_ENUM(ePools::TASK_ALLOCATOR_POOL, "task-allocator") +ADD_ENUM(ePools::PED_INTELLIGENCE_POOL, "ped-intelligence") +ADD_ENUM(ePools::PED_ATTRACTOR_POOL, "ped-attractor") +ADD_ENUM(ePools::ENTRY_INFO_NODE_POOL, "entry-info-node") +ADD_ENUM(ePools::NODE_ROUTE_POOL, "node-route") +ADD_ENUM(ePools::PATROL_ROUTE_POOL, "patrol-route") +ADD_ENUM(ePools::POINT_ROUTE_POOL, "point-route") +ADD_ENUM(ePools::POINTER_DOUBLE_LINK_POOL, "pointer-double-link-pool") +ADD_ENUM(ePools::POINTER_SINGLE_LINK_POOL, "pointer-single-link-pool") +ADD_ENUM(ePools::ENV_MAP_MATERIAL_POOL, "env-map-material") +ADD_ENUM(ePools::ENV_MAP_ATOMIC_POOL, "env-map-atomic") +ADD_ENUM(ePools::SPEC_MAP_MATERIAL_POOL, "spec-map-material") +IMPLEMENT_ENUM_END("gta-pool") + +IMPLEMENT_ENUM_CLASS_BEGIN(eFxParticleSystems) +ADD_ENUM(eFxParticleSystems::PRT_BLOOD, "blood") +ADD_ENUM(eFxParticleSystems::PRT_BOATSPLASH, "boat_splash") +ADD_ENUM(eFxParticleSystems::PRT_BUBBLE, "bubble") +ADD_ENUM(eFxParticleSystems::PRT_DEBRIS, "car_debris") +ADD_ENUM(eFxParticleSystems::PRT_SMOKE, "collision_smoke") +ADD_ENUM(eFxParticleSystems::PRT_GUNSHELL, "gunshell") +ADD_ENUM(eFxParticleSystems::PRT_SAND, "sand") +ADD_ENUM(eFxParticleSystems::PRT_SAND2, "sand2") +ADD_ENUM(eFxParticleSystems::PRT_SMOKEHUGE, "huge_smoke") +ADD_ENUM(eFxParticleSystems::PRT_SMOKE2, "smoke") +ADD_ENUM(eFxParticleSystems::PRT_SPARK, "spark") +ADD_ENUM(eFxParticleSystems::PRT_SPARK2, "spark2") +ADD_ENUM(eFxParticleSystems::PRT_SPLASH, "splash") +ADD_ENUM(eFxParticleSystems::PRT_WAKE, "wake") +ADD_ENUM(eFxParticleSystems::PRT_WATERSPLASH, "water_splash") +ADD_ENUM(eFxParticleSystems::PRT_WHEELDIRT, "wheel_dirt") +ADD_ENUM(eFxParticleSystems::PRT_GLASS, "glass") +IMPLEMENT_ENUM_CLASS_END("particle-system") + +IMPLEMENT_ENUM_BEGIN(eWorldProperty) +ADD_ENUM(AMBIENT_COLOR, "AmbientColor") +ADD_ENUM(AMBIENT_OBJ_COLOR, "AmbientObjColor") +ADD_ENUM(DIRECTIONAL_COLOR, "DirectionalColor") +ADD_ENUM(SPRITE_SIZE, "SpriteSize") +ADD_ENUM(SPRITE_BRIGHTNESS, "SpriteBrightness") +ADD_ENUM(POLE_SHADOW_STRENGTH, "PoleShadowStrength") +ADD_ENUM(SHADOW_STRENGTH, "ShadowStrength") +ADD_ENUM(SHADOWS_OFFSET, "ShadowsOffset") +ADD_ENUM(LIGHTS_ON_GROUND, "LightsOnGround") +ADD_ENUM(LOW_CLOUDS_COLOR, "LowCloudsColor") +ADD_ENUM(BOTTOM_CLOUDS_COLOR, "BottomCloudsColor") +ADD_ENUM(CLOUDS_ALPHA1, "CloudsAlpha") +ADD_ENUM(ILLUMINATION, "Illumination") +ADD_ENUM(WEATHER_WET_ROADS, "WetRoads") +ADD_ENUM(WEATHER_FOGGYNESS, "Foggyness") +ADD_ENUM(WEATHER_FOG, "Fog") +ADD_ENUM(WEATHER_RAIN_FOG, "RainFog") +ADD_ENUM(WEATHER_WATER_FOG, "WaterFog") +ADD_ENUM(WEATHER_SANDSTORM, "Sandstorm") +ADD_ENUM(WEATHER_RAINBOW, "Rainbow") +IMPLEMENT_ENUM_END("world-property") + +IMPLEMENT_ENUM_CLASS_BEGIN(eModelLoadState) +ADD_ENUM(eModelLoadState::LOADSTATE_NOT_LOADED, "unloaded") +ADD_ENUM(eModelLoadState::LOADSTATE_LOADED, "loaded") +ADD_ENUM(eModelLoadState::LOADSTATE_REQUESTED, "requested") +ADD_ENUM(eModelLoadState::LOADSTATE_READING, "reading") +ADD_ENUM(eModelLoadState::LOADSTATE_FINISHING, "finishing") +IMPLEMENT_ENUM_CLASS_END("model-load-state") + +IMPLEMENT_ENUM_CLASS_BEGIN(PreloadAreaOption) +ADD_ENUM(PreloadAreaOption::MODELS, "models") +ADD_ENUM(PreloadAreaOption::COLLISIONS, "collisions") +ADD_ENUM(PreloadAreaOption::ALL, "all") +IMPLEMENT_ENUM_CLASS_END("preload-area-option") + // // CResource from userdata // @@ -1093,6 +1179,31 @@ bool MinClientReqCheck(CScriptArgReader& argStream, const char* szVersionReq, co return true; } +// +// Check min client is correct +// Thrown a error if below required +// +void MinClientReqCheck(lua_State* luaVM, const char* szVersionReq, const char* szReason) +{ + CLuaMain* pLuaMain = g_pClientGame->GetLuaManager()->GetVirtualMachine(luaVM); + if (!pLuaMain) + return; + + CResource* pResource = pLuaMain->GetResource(); + if (!pResource) + return; + + if (pResource->GetMinClientReq() < szVersionReq) + { + #if MTASA_VERSION_TYPE == VERSION_TYPE_RELEASE + SString err(" section in the meta.xml is incorrect or missing (expected at least client %s because %s)", + szVersionReq, szReason); + throw std::invalid_argument(err); + #endif + } + +} + // // Read next as preg option flags // diff --git a/Client/mods/deathmatch/logic/lua/CLuaFunctionParseHelpers.h b/Client/mods/deathmatch/logic/lua/CLuaFunctionParseHelpers.h index 5688c78d34..e134a73bea 100644 --- a/Client/mods/deathmatch/logic/lua/CLuaFunctionParseHelpers.h +++ b/Client/mods/deathmatch/logic/lua/CLuaFunctionParseHelpers.h @@ -13,6 +13,7 @@ #include #include #include +#include #include enum eLuaType @@ -81,6 +82,12 @@ DECLARE_ENUM_CLASS(eSoundEffectParams::ParamEq); DECLARE_ENUM_CLASS(eSoundEffectParams::Reverb); DECLARE_ENUM_CLASS(eModelIdeFlag); DECLARE_ENUM_CLASS(_D3DFORMAT); +DECLARE_ENUM_CLASS(eRenderStage); +DECLARE_ENUM_CLASS(eFxParticleSystems); +DECLARE_ENUM(ePools); +DECLARE_ENUM(eWorldProperty); +DECLARE_ENUM_CLASS(eModelLoadState); +DECLARE_ENUM_CLASS(PreloadAreaOption); class CRemoteCall; @@ -272,6 +279,10 @@ inline SString GetClassTypeName(CClientIMG*) { return "img"; } +inline SString GetClassTypeName(CClientBuilding*) +{ + return "building"; +} inline SString GetClassTypeName(CClientSound*) { return "sound"; @@ -490,6 +501,10 @@ inline SString GetClassTypeName(eSoundEffectParams::Reverb*) { return "soundeffect-params-reverb"; } +inline SString GetClassTypeName(eWorldProperty*) +{ + return "world-property"; +} inline SString GetClassTypeName(CClientVectorGraphic*) { @@ -570,6 +585,7 @@ void MixedReadDxFontString(CScriptArgReader& argStream, eFontType& outFontType, void MixedReadGuiFontString(CScriptArgReader& argStream, SString& strFontName, const char* szDefaultFontName, CClientGuiFont*& poutGuiFontElement); void MixedReadMaterialString(CScriptArgReader& argStream, CClientMaterial*& pMaterialElement); bool ReadMatrix(lua_State* luaVM, uint uiArgIndex, CMatrix& outMatrix); +void MinClientReqCheck(lua_State* luaVM, const char* szVersionReq, const char* szReason); bool MinClientReqCheck(CScriptArgReader& argStream, const char* szVersionReq, const char* szReason = nullptr); void ReadPregFlags(CScriptArgReader& argStream, pcrecpp::RE_Options& pOptions); diff --git a/Client/mods/deathmatch/logic/lua/CLuaMain.cpp b/Client/mods/deathmatch/logic/lua/CLuaMain.cpp index 4dbe913aa0..6b794be016 100644 --- a/Client/mods/deathmatch/logic/lua/CLuaMain.cpp +++ b/Client/mods/deathmatch/logic/lua/CLuaMain.cpp @@ -127,6 +127,7 @@ void CLuaMain::InitClasses(lua_State* luaVM) CLuaVehicleDefs::AddClass(luaVM); CLuaWaterDefs::AddClass(luaVM); CLuaWeaponDefs::AddClass(luaVM); + CLuaBuildingDefs::AddClass(luaVM); CLuaShared::AddClasses(luaVM); } @@ -170,6 +171,9 @@ void CLuaMain::InitVM() lua_pushelement(m_luaVM, m_pResource->GetResourceEntity()); lua_setglobal(m_luaVM, "resourceRoot"); + lua_pushstring(m_luaVM, m_pResource->GetName()); + lua_setglobal(m_luaVM, "resourceName"); + lua_pushelement(m_luaVM, m_pResource->GetResourceGUIEntity()); lua_setglobal(m_luaVM, "guiRoot"); diff --git a/Client/mods/deathmatch/logic/lua/CLuaMain.h b/Client/mods/deathmatch/logic/lua/CLuaMain.h index abe2c96cf1..3839e5995e 100644 --- a/Client/mods/deathmatch/logic/lua/CLuaMain.h +++ b/Client/mods/deathmatch/logic/lua/CLuaMain.h @@ -59,7 +59,7 @@ class CLuaMain //: public CClient void ResetInstructionCount(); - class CResource* GetResource() { return m_pResource; } + class CResource* GetResource() const { return m_pResource; } CXMLFile* CreateXML(const char* szFilename, bool bUseIDs = true, bool bReadOnly = false); CXMLNode* ParseString(const char* strXmlContent); diff --git a/Client/mods/deathmatch/logic/lua/CLuaManager.cpp b/Client/mods/deathmatch/logic/lua/CLuaManager.cpp index 33388a5edc..c2a28809af 100644 --- a/Client/mods/deathmatch/logic/lua/CLuaManager.cpp +++ b/Client/mods/deathmatch/logic/lua/CLuaManager.cpp @@ -280,4 +280,5 @@ void CLuaManager::LoadCFunctions() CLuaXMLDefs::LoadFunctions(); CLuaClientDefs::LoadFunctions(); CLuaDiscordDefs::LoadFunctions(); + CLuaBuildingDefs::LoadFunctions(); } diff --git a/Client/mods/deathmatch/logic/lua/CLuaTimerManager.cpp b/Client/mods/deathmatch/logic/lua/CLuaTimerManager.cpp index 317de7f16d..4c70d03f04 100644 --- a/Client/mods/deathmatch/logic/lua/CLuaTimerManager.cpp +++ b/Client/mods/deathmatch/logic/lua/CLuaTimerManager.cpp @@ -21,7 +21,10 @@ void CLuaTimerManager::DoPulse(CLuaMain* pLuaMain) // Use a separate queue to avoid trouble for (CFastList::const_iterator iter = m_TimerList.begin(); iter != m_TimerList.end(); iter++) - m_ProcessQueue.push_back(*iter); + { + if (!(*iter)->IsPaused()) + m_ProcessQueue.push_back(*iter); + } while (!m_ProcessQueue.empty()) { @@ -108,6 +111,16 @@ void CLuaTimerManager::RemoveAllTimers() m_pProcessingTimer = NULL; } +void CLuaTimerManager::SetTimerPaused(CLuaTimer* timer, bool paused) +{ + assert(timer); + + timer->SetPaused(paused); + if (paused) + ListRemove(m_ProcessQueue, timer); +} + + void CLuaTimerManager::ResetTimer(CLuaTimer* pLuaTimer) { assert(pLuaTimer); diff --git a/Client/mods/deathmatch/logic/lua/CLuaTimerManager.h b/Client/mods/deathmatch/logic/lua/CLuaTimerManager.h index 055b644fcb..c4f97d2626 100644 --- a/Client/mods/deathmatch/logic/lua/CLuaTimerManager.h +++ b/Client/mods/deathmatch/logic/lua/CLuaTimerManager.h @@ -36,6 +36,7 @@ class CLuaTimerManager void RemoveAllTimers(); unsigned long GetTimerCount() const { return m_TimerList.size(); } + void SetTimerPaused(CLuaTimer* timer, bool paused); void ResetTimer(CLuaTimer* pLuaTimer); CFastList::const_iterator IterBegin() { return m_TimerList.begin(); } diff --git a/Client/mods/deathmatch/logic/lua/LuaCommon.h b/Client/mods/deathmatch/logic/lua/LuaCommon.h index 238cfeeed5..20dda7ff11 100644 --- a/Client/mods/deathmatch/logic/lua/LuaCommon.h +++ b/Client/mods/deathmatch/logic/lua/LuaCommon.h @@ -38,6 +38,7 @@ class CClientRadarMarker; class CClientTeam; class CClientTXD; class CClientIMG; +class CClientBuilding; class CClientVehicle; class CClientWater; class CClientWeapon; diff --git a/Client/mods/deathmatch/logic/luadefs/CLuaAudioDefs.cpp b/Client/mods/deathmatch/logic/luadefs/CLuaAudioDefs.cpp index fce32a5506..593ac628da 100644 --- a/Client/mods/deathmatch/logic/luadefs/CLuaAudioDefs.cpp +++ b/Client/mods/deathmatch/logic/luadefs/CLuaAudioDefs.cpp @@ -165,7 +165,8 @@ int CLuaAudioDefs::PlaySound(lua_State* luaVM) SString strFilename; bool bIsURL = false; bool bIsRawData = false; - if (CResourceManager::ParseResourcePathInput(strSound, pResource, &strFilename)) + + if (CResourceManager::ParseResourcePathInput(strSound, pResource, &strFilename, nullptr, true)) strSound = strFilename; else { diff --git a/Client/mods/deathmatch/logic/luadefs/CLuaBrowserDefs.cpp b/Client/mods/deathmatch/logic/luadefs/CLuaBrowserDefs.cpp index c496fca0cd..6077f45346 100644 --- a/Client/mods/deathmatch/logic/luadefs/CLuaBrowserDefs.cpp +++ b/Client/mods/deathmatch/logic/luadefs/CLuaBrowserDefs.cpp @@ -11,6 +11,7 @@ #include "StdInc.h" #include "lua/CLuaFunctionParser.h" +#include void CLuaBrowserDefs::LoadFunctions() { @@ -182,8 +183,12 @@ int CLuaBrowserDefs::RequestBrowserDomains(lua_State* luaVM) if (!argStream.HasErrors()) { - // Remove empty URLs - pages.erase(std::remove_if(pages.begin(), pages.end(), [](const auto& url) { return url.empty(); }), pages.end()); + // Remove empty and invalid URLs + std::regex invalidSynmbolsRegex("[^A-Za-z0-9\-._~!#$&'()*+,;=:@\/?%]"); + + pages.erase(std::remove_if(pages.begin(), pages.end(), + [&invalidSynmbolsRegex](const auto& url) { return url.empty() || std::regex_search(url, invalidSynmbolsRegex); }), + pages.end()); // Convert to domains if we got a list of URLs if (bIsURL) @@ -1025,10 +1030,10 @@ int CLuaBrowserDefs::SetBrowserAjaxHandler(lua_State* luaVM) arguments.Call(pLuaMain, callbackFunction, &result); - if (result.Count() == 0) + if (result.IsEmpty()) return ""; - CLuaArgument* returnedValue = *result.IterBegin(); + CLuaArgument* returnedValue = *result.begin(); if (returnedValue->GetType() == LUA_TSTRING) return returnedValue->GetString(); else diff --git a/Client/mods/deathmatch/logic/luadefs/CLuaBuildingDefs.cpp b/Client/mods/deathmatch/logic/luadefs/CLuaBuildingDefs.cpp new file mode 100644 index 0000000000..bcb765e712 --- /dev/null +++ b/Client/mods/deathmatch/logic/luadefs/CLuaBuildingDefs.cpp @@ -0,0 +1,74 @@ +/***************************************************************************** + * + * PROJECT: Multi Theft Auto + * LICENSE: See LICENSE in the top level directory + * + * Multi Theft Auto is available from http://www.multitheftauto.com/ + * + *****************************************************************************/ + +#include "StdInc.h" +#include + +void CLuaBuildingDefs::LoadFunctions() +{ + // Backwards compatibility functions + constexpr static const std::pair functions[]{ + {"createBuilding", ArgumentParser}, + {"removeAllGameBuildings", ArgumentParser}, + {"restoreAllGameBuildings", ArgumentParser}, + }; + + // Add functions + for (const auto& [name, func] : functions) + CLuaCFunctions::AddFunction(name, func); +} + +void CLuaBuildingDefs::AddClass(lua_State* luaVM) +{ + lua_newclass(luaVM); + + lua_classfunction(luaVM, "create", "createBuilding"); + + lua_registerclass(luaVM, "Building", "Element"); +} + +CClientBuilding* CLuaBuildingDefs::CreateBuilding(lua_State* const luaVM, std::uint16_t modelId, CVector pos, std::optional rot, std::optional interior) +{ + CLuaMain* pLuaMain = m_pLuaManager->GetVirtualMachine(luaVM); + + // Get the resource we belong to + CResource* pResource = pLuaMain->GetResource(); + if (!pResource) + return false; + + if (!CClientBuildingManager::IsValidModel(modelId)) + throw std::invalid_argument("Invalid building model id"); + + if (!CClientBuildingManager::IsValidPosition(pos)) + throw std::invalid_argument("Position is outside of game world"); + + if (rot.has_value()) + ConvertDegreesToRadians(rot.value()); + else + rot.emplace(CVector(0, 0, 0)); + + m_pBuildingManager->ResizePoolIfNeeds(); + + CClientBuilding* pBuilding = new CClientBuilding(m_pManager, INVALID_ELEMENT_ID, modelId, pos, rot.value() , interior.value_or(0)); + + CClientEntity* pRoot = pResource->GetResourceDynamicEntity(); + pBuilding->SetParent(pRoot); + + return pBuilding; +} + +void CLuaBuildingDefs::RemoveAllGameBuildings() +{ + m_pBuildingManager->RemoveAllGameBuildings(); +} + +void CLuaBuildingDefs::RestoreGameBuildings() +{ + m_pBuildingManager->RestoreAllGameBuildings(); +} diff --git a/Client/mods/deathmatch/logic/luadefs/CLuaBuildingDefs.h b/Client/mods/deathmatch/logic/luadefs/CLuaBuildingDefs.h new file mode 100644 index 0000000000..a244c74bbb --- /dev/null +++ b/Client/mods/deathmatch/logic/luadefs/CLuaBuildingDefs.h @@ -0,0 +1,25 @@ +/***************************************************************************** + * + * PROJECT: Multi Theft Auto v1.x + * LICENSE: See LICENSE in the top level directory + * FILE: mods/shared_logic/luadefs/CLuaBuildingDefs.h + * PURPOSE: Lua building definitions class header + * + * Multi Theft Auto is available from http://www.multitheftauto.com/ + * + *****************************************************************************/ + +#pragma once +#include "CLuaDefs.h" + +class CLuaBuildingDefs : public CLuaDefs +{ +public: + static void LoadFunctions(); + static void AddClass(lua_State* luaVM); + + // Buiding create funcs + static CClientBuilding* CreateBuilding(lua_State* const luaVM, std::uint16_t modelId, CVector pos, std::optional rot, std::optional interior); + static void RemoveAllGameBuildings(); + static void RestoreGameBuildings(); +}; diff --git a/Client/mods/deathmatch/logic/luadefs/CLuaCameraDefs.cpp b/Client/mods/deathmatch/logic/luadefs/CLuaCameraDefs.cpp index b4ef233a9a..2d9c268dc3 100644 --- a/Client/mods/deathmatch/logic/luadefs/CLuaCameraDefs.cpp +++ b/Client/mods/deathmatch/logic/luadefs/CLuaCameraDefs.cpp @@ -41,6 +41,9 @@ void CLuaCameraDefs::LoadFunctions() {"setCameraViewMode", ArgumentParserWarn}, {"setCameraGoggleEffect", SetCameraGoggleEffect}, {"setCameraDrunkLevel", ArgumentParserWarn}, + + {"shakeCamera", ArgumentParser}, + {"resetShakeCamera", ArgumentParser}, }; // Add functions @@ -543,3 +546,25 @@ const SString& CLuaCameraDefs::GetElementType() { return m_pManager->GetCamera()->GetTypeName(); } + +bool CLuaCameraDefs::ShakeCamera(float radius, std::optional x, std::optional y, std::optional z) noexcept +{ + if (!x || !y || !z) + { + const auto* player = CStaticFunctionDefinitions::GetLocalPlayer(); + CVector out; + player->GetPosition(out); + x = out.fX; + y = out.fY; + z = out.fZ; + } + m_pManager->GetCamera()->ShakeCamera(radius, *x, *y, *z); + + return true; +} + +bool CLuaCameraDefs::ResetShakeCamera() noexcept +{ + m_pManager->GetCamera()->ResetShakeCamera(); + return true; +} \ No newline at end of file diff --git a/Client/mods/deathmatch/logic/luadefs/CLuaCameraDefs.h b/Client/mods/deathmatch/logic/luadefs/CLuaCameraDefs.h index 9fd1fe030e..b233d4e39c 100644 --- a/Client/mods/deathmatch/logic/luadefs/CLuaCameraDefs.h +++ b/Client/mods/deathmatch/logic/luadefs/CLuaCameraDefs.h @@ -43,6 +43,10 @@ class CLuaCameraDefs : public CLuaDefs LUA_DECLARE(SetCameraGoggleEffect); static bool SetCameraDrunkLevel(short drunkLevel); + // Cam do funcs + static bool ShakeCamera(float radius, std::optional x, std::optional y, std::optional z) noexcept; + static bool ResetShakeCamera() noexcept; + // For OOP only LUA_DECLARE(OOP_GetCameraPosition); LUA_DECLARE(OOP_SetCameraPosition); diff --git a/Client/mods/deathmatch/logic/luadefs/CLuaDefs.cpp b/Client/mods/deathmatch/logic/luadefs/CLuaDefs.cpp index de07ea84a4..457f72998f 100644 --- a/Client/mods/deathmatch/logic/luadefs/CLuaDefs.cpp +++ b/Client/mods/deathmatch/logic/luadefs/CLuaDefs.cpp @@ -31,6 +31,7 @@ CClientDFFManager* CLuaDefs::m_pDFFManager = NULL; CClientColModelManager* CLuaDefs::m_pColModelManager = NULL; CRegisteredCommands* CLuaDefs::m_pRegisteredCommands = NULL; CClientIMGManager* CLuaDefs::m_pImgManager = NULL; +CClientBuildingManager* CLuaDefs::m_pBuildingManager = nullptr; bool ms_bRegisterdPostCallHook = false; void CLuaDefs::Initialize(CClientGame* pClientGame, CLuaManager* pLuaManager, CScriptDebugging* pScriptDebugging) @@ -56,6 +57,7 @@ void CLuaDefs::Initialize(CClientGame* pClientGame, CLuaManager* pLuaManager, CS m_pColModelManager = m_pManager->GetColModelManager(); m_pRegisteredCommands = pClientGame->GetRegisteredCommands(); m_pImgManager = m_pManager->GetIMGManager(); + m_pBuildingManager = m_pManager->GetBuildingManager(); } int CLuaDefs::CanUseFunction(lua_CFunction f, lua_State* luaVM) diff --git a/Client/mods/deathmatch/logic/luadefs/CLuaDefs.h b/Client/mods/deathmatch/logic/luadefs/CLuaDefs.h index cf043b4572..3f3c18386f 100644 --- a/Client/mods/deathmatch/logic/luadefs/CLuaDefs.h +++ b/Client/mods/deathmatch/logic/luadefs/CLuaDefs.h @@ -65,6 +65,7 @@ class CLuaDefs static CClientColModelManager* m_pColModelManager; static CRegisteredCommands* m_pRegisteredCommands; static CClientIMGManager* m_pImgManager; + static CClientBuildingManager* m_pBuildingManager; protected: // Old style: Only warn on failure. This should diff --git a/Client/mods/deathmatch/logic/luadefs/CLuaDiscordDefs.cpp b/Client/mods/deathmatch/logic/luadefs/CLuaDiscordDefs.cpp index 9b3e907aa9..f2ca089565 100644 --- a/Client/mods/deathmatch/logic/luadefs/CLuaDiscordDefs.cpp +++ b/Client/mods/deathmatch/logic/luadefs/CLuaDiscordDefs.cpp @@ -25,7 +25,7 @@ void CLuaDiscordDefs::LoadFunctions() {"setDiscordRichPresencePartySize", ArgumentParser}, {"resetDiscordRichPresenceData", ArgumentParser}, {"isDiscordRichPresenceConnected", ArgumentParser }, - + {"getDiscordRichPresenceUserID", ArgumentParser}, }; // Add functions @@ -266,3 +266,13 @@ bool CLuaDiscordDefs::IsDiscordRPCConnected() return discord->IsDiscordClientConnected(); } + +std::string CLuaDiscordDefs::GetDiscordUserID() +{ + auto discord = g_pCore->GetDiscord(); + + if (!discord || !discord->IsDiscordRPCEnabled()) + return {}; + + return discord->GetDiscordUserID(); +} diff --git a/Client/mods/deathmatch/logic/luadefs/CLuaDiscordDefs.h b/Client/mods/deathmatch/logic/luadefs/CLuaDiscordDefs.h index 936ec6839d..dfa7787cad 100644 --- a/Client/mods/deathmatch/logic/luadefs/CLuaDiscordDefs.h +++ b/Client/mods/deathmatch/logic/luadefs/CLuaDiscordDefs.h @@ -29,6 +29,6 @@ class CLuaDiscordDefs : public CLuaDefs static bool SetEndTime(unsigned long ulTime); static bool SetPartySize(int iMin, int iMax); static bool IsDiscordRPCConnected(); - + static std::string GetDiscordUserID(); }; diff --git a/Client/mods/deathmatch/logic/luadefs/CLuaDrawingDefs.cpp b/Client/mods/deathmatch/logic/luadefs/CLuaDrawingDefs.cpp index c4d9f40dfa..f54378944d 100644 --- a/Client/mods/deathmatch/logic/luadefs/CLuaDrawingDefs.cpp +++ b/Client/mods/deathmatch/logic/luadefs/CLuaDrawingDefs.cpp @@ -36,6 +36,7 @@ void CLuaDrawingDefs::LoadFunctions() {"dxDrawMaterialPrimitive", DxDrawMaterialPrimitive}, {"dxDrawMaterialPrimitive3D", DxDrawMaterialPrimitive3D}, {"dxDrawWiredSphere", ArgumentParser}, + {"dxDrawModel3D", ArgumentParser}, {"dxGetTextWidth", DxGetTextWidth}, {"dxGetTextSize", ArgumentParser}, {"dxGetFontHeight", DxGetFontHeight}, @@ -192,18 +193,21 @@ int CLuaDrawingDefs::DxDrawLine3D(lua_State* luaVM) CVector vecEnd; SColor color; float fWidth; - bool bPostGUI; + eRenderStage renderStage{eRenderStage::POST_FX}; CScriptArgReader argStream(luaVM); argStream.ReadVector3D(vecBegin); argStream.ReadVector3D(vecEnd); argStream.ReadColor(color, 0xFFFFFFFF); argStream.ReadNumber(fWidth, 1); - argStream.ReadBool(bPostGUI, false); + if (argStream.NextIsBool()) + renderStage = argStream.ReadBool() ? eRenderStage::POST_GUI : eRenderStage::POST_FX; + else + argStream.ReadIfNextIsEnumString(renderStage, eRenderStage::POST_FX); if (!argStream.HasErrors()) { - g_pCore->GetGraphics()->DrawLine3DQueued(vecBegin, vecEnd, fWidth, color, bPostGUI); + g_pCore->GetGraphics()->DrawLine3DQueued(vecBegin, vecEnd, fWidth, color, renderStage); lua_pushboolean(luaVM, true); return 1; } @@ -226,9 +230,9 @@ int CLuaDrawingDefs::DxDrawMaterialLine3D(lua_State* luaVM) CClientMaterial* pMaterial; float fWidth; SColor color; - bool bPostGUI; CVector vecFaceToward; bool bUseFaceToward = false; + eRenderStage renderStage{eRenderStage::POST_FX}; CScriptArgReader argStream(luaVM); argStream.ReadVector3D(vecBegin); @@ -237,7 +241,11 @@ int CLuaDrawingDefs::DxDrawMaterialLine3D(lua_State* luaVM) argStream.ReadUserData(pMaterial); argStream.ReadNumber(fWidth); argStream.ReadColor(color, 0xFFFFFFFF); - argStream.ReadIfNextIsBool(bPostGUI, false); + if (argStream.NextIsBool()) + renderStage = argStream.ReadBool() ? eRenderStage::POST_GUI : eRenderStage::POST_FX; + else + argStream.ReadIfNextIsEnumString(renderStage, eRenderStage::POST_FX); + if (argStream.NextIsVector3D()) { argStream.ReadVector3D(vecFaceToward); @@ -247,7 +255,7 @@ int CLuaDrawingDefs::DxDrawMaterialLine3D(lua_State* luaVM) if (!argStream.HasErrors()) { g_pCore->GetGraphics()->DrawMaterialLine3DQueued(vecBegin, vecEnd, fWidth, color, pMaterial->GetMaterialItem(), 0, 0, 1, 1, true, bFlipUV, - bUseFaceToward, vecFaceToward, bPostGUI); + bUseFaceToward, vecFaceToward, renderStage); lua_pushboolean(luaVM, true); return 1; } @@ -272,9 +280,9 @@ int CLuaDrawingDefs::DxDrawMaterialSectionLine3D(lua_State* luaVM) CClientMaterial* pMaterial; float fWidth; SColor color; - bool bPostGUI; CVector vecFaceToward; bool bUseFaceToward = false; + eRenderStage renderStage{eRenderStage::POST_FX}; CScriptArgReader argStream(luaVM); argStream.ReadVector3D(vecBegin); @@ -285,7 +293,11 @@ int CLuaDrawingDefs::DxDrawMaterialSectionLine3D(lua_State* luaVM) argStream.ReadUserData(pMaterial); argStream.ReadNumber(fWidth); argStream.ReadColor(color, 0xFFFFFFFF); - argStream.ReadIfNextIsBool(bPostGUI, false); + if (argStream.NextIsBool()) + renderStage = argStream.ReadBool() ? eRenderStage::POST_GUI : eRenderStage::POST_FX; + else + argStream.ReadIfNextIsEnumString(renderStage, eRenderStage::POST_FX); + if (argStream.NextIsVector3D()) { argStream.ReadVector3D(vecFaceToward); @@ -295,7 +307,7 @@ int CLuaDrawingDefs::DxDrawMaterialSectionLine3D(lua_State* luaVM) if (!argStream.HasErrors()) { g_pCore->GetGraphics()->DrawMaterialLine3DQueued(vecBegin, vecEnd, fWidth, color, pMaterial->GetMaterialItem(), vecSectionPos.fX, vecSectionPos.fY, - vecSectionSize.fX, vecSectionSize.fY, false, bFlipUV, bUseFaceToward, vecFaceToward, bPostGUI); + vecSectionSize.fX, vecSectionSize.fY, false, bFlipUV, bUseFaceToward, vecFaceToward, renderStage); lua_pushboolean(luaVM, true); return 1; } @@ -586,10 +598,13 @@ int CLuaDrawingDefs::DxDrawPrimitive3D(lua_State* luaVM) // bool DxDrawPrimitive3D (string primitiveType, bool postGUI, table vertice1, ...) D3DPRIMITIVETYPE ePrimitiveType; auto pVecVertices = new std::vector(); - bool bPostGUI; + eRenderStage renderStage{eRenderStage::POST_FX}; CScriptArgReader argStream(luaVM); argStream.ReadEnumString(ePrimitiveType); - argStream.ReadBool(bPostGUI, false); + if (argStream.NextIsBool()) + renderStage = argStream.ReadBool() ? eRenderStage::POST_GUI : eRenderStage::POST_FX; + else + argStream.ReadEnumString(renderStage, eRenderStage::POST_FX); std::vector vecTableContent; @@ -619,7 +634,7 @@ int CLuaDrawingDefs::DxDrawPrimitive3D(lua_State* luaVM) if (g_pCore->GetGraphics()->IsValidPrimitiveSize(pVecVertices->size(), ePrimitiveType)) { - g_pCore->GetGraphics()->DrawPrimitive3DQueued(pVecVertices, ePrimitiveType, bPostGUI); + g_pCore->GetGraphics()->DrawPrimitive3DQueued(pVecVertices, ePrimitiveType, renderStage); lua_pushboolean(luaVM, true); return 1; } @@ -636,12 +651,15 @@ int CLuaDrawingDefs::DxDrawMaterialPrimitive3D(lua_State* luaVM) D3DPRIMITIVETYPE ePrimitiveType; auto pVecVertices = new std::vector(); CClientMaterial* pMaterialElement; - bool bPostGUI; + eRenderStage renderStage{eRenderStage::POST_FX}; CScriptArgReader argStream(luaVM); argStream.ReadEnumString(ePrimitiveType); MixedReadMaterialString(argStream, pMaterialElement); - argStream.ReadBool(bPostGUI, false); + if (argStream.NextIsBool()) + renderStage = argStream.ReadBool() ? eRenderStage::POST_GUI : eRenderStage::POST_FX; + else + argStream.ReadEnumString(renderStage, eRenderStage::POST_FX); std::vector vecTableContent; @@ -674,7 +692,7 @@ int CLuaDrawingDefs::DxDrawMaterialPrimitive3D(lua_State* luaVM) if (g_pCore->GetGraphics()->IsValidPrimitiveSize(pVecVertices->size(), ePrimitiveType)) { - g_pCore->GetGraphics()->DrawMaterialPrimitive3DQueued(pVecVertices, ePrimitiveType, pMaterialElement->GetMaterialItem(), bPostGUI); + g_pCore->GetGraphics()->DrawMaterialPrimitive3DQueued(pVecVertices, ePrimitiveType, pMaterialElement->GetMaterialItem(), renderStage); lua_pushboolean(luaVM, true); return 1; } @@ -2104,3 +2122,21 @@ bool CLuaDrawingDefs::DxDrawWiredSphere(lua_State* const luaVM, const CVector po g_pCore->GetGraphics()->DrawWiredSphere(position, radius, color.value(), lineWidth.value_or(1), iterations.value_or(1)); return true; } + +bool CLuaDrawingDefs::DxDrawModel3D(std::uint32_t modelID, CVector position, CVector rotation, const std::optional scale) +{ + CModelInfo* pModelInfo = g_pGame->GetModelInfo(modelID); + if (!pModelInfo) + throw std::invalid_argument("Invalid model ID"); + + if (auto modelType = pModelInfo->GetModelType(); + modelType == eModelInfoType::UNKNOWN || modelType == eModelInfoType::VEHICLE || modelType == eModelInfoType::PED) + { + throw std::invalid_argument("Invalid model type"); + } + + ConvertDegreesToRadians(rotation); + + return g_pClientGame->GetModelRenderer()->EnqueueModel(pModelInfo, + CMatrix{position, rotation, scale.value_or(CVector{1.0f, 1.0f, 1.0f})}); +} diff --git a/Client/mods/deathmatch/logic/luadefs/CLuaDrawingDefs.h b/Client/mods/deathmatch/logic/luadefs/CLuaDrawingDefs.h index 0bda34f5e9..55dc3adda1 100644 --- a/Client/mods/deathmatch/logic/luadefs/CLuaDrawingDefs.h +++ b/Client/mods/deathmatch/logic/luadefs/CLuaDrawingDefs.h @@ -82,6 +82,8 @@ class CLuaDrawingDefs : public CLuaDefs static bool DxDrawWiredSphere(lua_State* const luaVM, const CVector position, const float radius, const std::optional color, const std::optional lineWidth, const std::optional iterations); + static bool DxDrawModel3D(std::uint32_t modelID, CVector position, CVector rotation, const std::optional scale); + private: static void AddDxMaterialClass(lua_State* luaVM); static void AddDxTextureClass(lua_State* luaVM); diff --git a/Client/mods/deathmatch/logic/luadefs/CLuaEffectDefs.cpp b/Client/mods/deathmatch/logic/luadefs/CLuaEffectDefs.cpp index 5b9940a01a..fb1a5e3dfe 100644 --- a/Client/mods/deathmatch/logic/luadefs/CLuaEffectDefs.cpp +++ b/Client/mods/deathmatch/logic/luadefs/CLuaEffectDefs.cpp @@ -10,6 +10,7 @@ *****************************************************************************/ #include "StdInc.h" +#include "lua/CLuaFunctionParser.h" void CLuaEffectDefs::LoadFunctions() { @@ -33,6 +34,7 @@ void CLuaEffectDefs::LoadFunctions() {"getEffectSpeed", GetEffectSpeed}, {"setEffectDensity", SetEffectDensity}, {"getEffectDensity", GetEffectDensity}, + {"fxCreateParticle", ArgumentParser}, }; // Add functions @@ -59,6 +61,7 @@ void CLuaEffectDefs::AddClass(lua_State* luaVM) lua_classfunction(luaVM, "addWaterHydrant", "fxAddWaterHydrant"); lua_classfunction(luaVM, "addWaterSplash", "fxAddWaterSplash"); lua_classfunction(luaVM, "addWood", "fxAddWood"); + lua_classfunction(luaVM, "createParticle", "fxCreateParticle"); lua_classfunction(luaVM, "setDensity", "setEffectDensity"); lua_classfunction(luaVM, "setSpeed", "setEffectSpeed"); @@ -639,3 +642,8 @@ int CLuaEffectDefs::SetEffectDensity(lua_State* luaVM) lua_pushboolean(luaVM, false); return 1; } + +bool CLuaEffectDefs::FxCreateParticle(eFxParticleSystems eParticleSystem, CVector vecPosition, CVector vecDirection, float fR, float fG, float fB, float fA, std::optional bRandomizeColors, std::optional iCount, std::optional fBrightness, std::optional fSize, std::optional bRandomizeSizes, std::optional fLife) +{ + return CStaticFunctionDefinitions::FxCreateParticle(eParticleSystem, vecPosition, vecDirection, fR/255, fG/255, fB/255, fA/255, bRandomizeColors.value_or(false), iCount.value_or(1), fBrightness.value_or(1.0f), fSize.value_or(0.3f), bRandomizeSizes.value_or(false), fLife.value_or(1.0f)); +} diff --git a/Client/mods/deathmatch/logic/luadefs/CLuaEffectDefs.h b/Client/mods/deathmatch/logic/luadefs/CLuaEffectDefs.h index e2f4c07fe1..e8e00df41f 100644 --- a/Client/mods/deathmatch/logic/luadefs/CLuaEffectDefs.h +++ b/Client/mods/deathmatch/logic/luadefs/CLuaEffectDefs.h @@ -37,4 +37,6 @@ class CLuaEffectDefs : public CLuaDefs LUA_DECLARE(GetEffectSpeed); LUA_DECLARE(SetEffectDensity); LUA_DECLARE(GetEffectDensity); + + static bool FxCreateParticle(eFxParticleSystems eParticleSystem, CVector vecPosition, CVector vecDirection, float fR, float fG, float fB, float fA, std::optional bRandomizeColors, std::optional iCount, std::optional fBrightness, std::optional fSize, std::optional bRandomizeSizes, std::optional fLife); }; diff --git a/Client/mods/deathmatch/logic/luadefs/CLuaElementDefs.cpp b/Client/mods/deathmatch/logic/luadefs/CLuaElementDefs.cpp index 0e0175e6ce..e88f8f6751 100644 --- a/Client/mods/deathmatch/logic/luadefs/CLuaElementDefs.cpp +++ b/Client/mods/deathmatch/logic/luadefs/CLuaElementDefs.cpp @@ -14,6 +14,8 @@ #include using std::list; +#define MIN_CLIENT_REQ_LOD_FOR_BUILDING "1.6.0-9.22470" + void CLuaElementDefs::LoadFunctions() { constexpr static const std::pair functions[]{ @@ -95,7 +97,7 @@ void CLuaElementDefs::LoadFunctions() {"setElementCollidableWith", SetElementCollidableWith}, {"setElementDoubleSided", SetElementDoubleSided}, {"setElementFrozen", SetElementFrozen}, - {"setLowLODElement", SetLowLodElement}, + {"setLowLODElement", ArgumentParser}, {"setElementCallPropagationEnabled", SetElementCallPropagationEnabled}, }; @@ -2497,29 +2499,14 @@ int CLuaElementDefs::GetLowLodElement(lua_State* luaVM) return 1; } -int CLuaElementDefs::SetLowLodElement(lua_State* luaVM) +bool CLuaElementDefs::SetLowLodElement(lua_State* luaVM, CClientEntity* pEntity, std::optional pLowLodEntity) { - // bool setLowLODElement ( element theElement ) - CClientEntity* pEntity; - CClientEntity* pLowLodEntity; - - CScriptArgReader argStream(luaVM); - argStream.ReadUserData(pEntity); - argStream.ReadUserData(pLowLodEntity, NULL); + // bool setLowLODElement ( element theElement [, element lowLowElement ] ) - if (!argStream.HasErrors()) - { - if (CStaticFunctionDefinitions::SetLowLodElement(*pEntity, pLowLodEntity)) - { - lua_pushboolean(luaVM, true); - return 1; - } - } - else - m_pScriptDebugging->LogCustom(luaVM, argStream.GetFullErrorMessage()); + if (pEntity->GetType() == CCLIENTBUILDING) + MinClientReqCheck(luaVM, MIN_CLIENT_REQ_LOD_FOR_BUILDING, "target is building"); - lua_pushboolean(luaVM, false); - return 1; + return CStaticFunctionDefinitions::SetLowLodElement(*pEntity, pLowLodEntity.value_or(nullptr)); } int CLuaElementDefs::IsElementLowLod(lua_State* luaVM) diff --git a/Client/mods/deathmatch/logic/luadefs/CLuaElementDefs.h b/Client/mods/deathmatch/logic/luadefs/CLuaElementDefs.h index d85c0eb449..40f93761e4 100644 --- a/Client/mods/deathmatch/logic/luadefs/CLuaElementDefs.h +++ b/Client/mods/deathmatch/logic/luadefs/CLuaElementDefs.h @@ -97,6 +97,6 @@ class CLuaElementDefs : public CLuaDefs LUA_DECLARE(SetElementCollidableWith); LUA_DECLARE(SetElementDoubleSided); LUA_DECLARE(SetElementFrozen); - LUA_DECLARE(SetLowLodElement); + static bool SetLowLodElement(lua_State* luaVM, CClientEntity* pEntity, std::optional pLowLodEntity); LUA_DECLARE(SetElementCallPropagationEnabled); }; diff --git a/Client/mods/deathmatch/logic/luadefs/CLuaEngineDefs.cpp b/Client/mods/deathmatch/logic/luadefs/CLuaEngineDefs.cpp index 2111c41195..7ca02230d5 100644 --- a/Client/mods/deathmatch/logic/luadefs/CLuaEngineDefs.cpp +++ b/Client/mods/deathmatch/logic/luadefs/CLuaEngineDefs.cpp @@ -14,6 +14,7 @@ #include #include #include +#include "CLuaEngineDefs.h" //! Set the CModelCacheManager limits //! By passing `nil`/no value the original values are restored @@ -135,9 +136,16 @@ void CLuaEngineDefs::LoadFunctions() {"engineStreamingSetBufferSize", ArgumentParser}, {"engineStreamingGetBufferSize", ArgumentParser}, {"engineStreamingRestoreBufferSize", ArgumentParser}, - + {"engineStreamingRequestModel", ArgumentParser}, + {"engineStreamingReleaseModel", ArgumentParser}, + {"engineStreamingGetModelLoadState", ArgumentParser}, {"engineRequestTXD", ArgumentParser}, {"engineFreeTXD", ArgumentParser}, + {"engineGetPoolCapacity", ArgumentParser}, + {"engineGetPoolDefaultCapacity", ArgumentParser}, + {"engineGetPoolUsedCapacity", ArgumentParser}, + {"engineSetPoolCapacity", ArgumentParser}, + {"enginePreloadWorldArea", ArgumentParser}, // CLuaCFunctions::AddFunction ( "engineReplaceMatchingAtomics", EngineReplaceMatchingAtomics ); // CLuaCFunctions::AddFunction ( "engineReplaceWheelAtomics", EngineReplaceWheelAtomics ); @@ -1043,12 +1051,14 @@ int CLuaEngineDefs::EngineGetModelLODDistance(lua_State* luaVM) int CLuaEngineDefs::EngineSetModelLODDistance(lua_State* luaVM) { - // bool engineSetModelLODDistance ( int/string modelID, float distance ) + // bool engineSetModelLODDistance ( int/string modelID, float distance [, bool extendedLod = false ]) SString strModelId; float fDistance; + bool extendedLod; CScriptArgReader argStream(luaVM); argStream.ReadString(strModelId); argStream.ReadNumber(fDistance); + argStream.ReadBool(extendedLod, false); if (!argStream.HasErrors()) { @@ -1059,7 +1069,7 @@ int CLuaEngineDefs::EngineSetModelLODDistance(lua_State* luaVM) CModelInfo* pModelInfo = g_pGame->GetModelInfo(usModelID); if (pModelInfo && fDistance > 0.0f) { - pModelInfo->SetLODDistance(fDistance); + pModelInfo->SetLODDistance(fDistance, extendedLod); lua_pushboolean(luaVM, true); return 1; } @@ -1944,7 +1954,8 @@ int CLuaEngineDefs::EngineGetModelPhysicalPropertiesGroup(lua_State* luaVM) auto pModelInfo = g_pGame->GetModelInfo(iModelID); if (pModelInfo) { - lua_pushnumber(luaVM, pModelInfo->GetObjectPropertiesGroup()); + uint16_t groupId = pModelInfo->GetObjectPropertiesGroup(); + lua_pushnumber(luaVM, groupId == 0xFFFF ? -1 : groupId); return 1; } argStream.SetCustomError("Expected valid model ID at argument 1"); @@ -1956,8 +1967,8 @@ int CLuaEngineDefs::EngineGetModelPhysicalPropertiesGroup(lua_State* luaVM) int CLuaEngineDefs::EngineSetModelPhysicalPropertiesGroup(lua_State* luaVM) { // bool engineSetModelPhysicalPropertiesGroup ( int modelID, int newGroup ) - int iModelID; - unsigned int iNewGroup; + int iModelID; + int iNewGroup; CScriptArgReader argStream(luaVM); argStream.ReadNumber(iModelID); @@ -1971,9 +1982,9 @@ int CLuaEngineDefs::EngineSetModelPhysicalPropertiesGroup(lua_State* luaVM) return luaL_error(luaVM, argStream.GetFullErrorMessage()); } - if (iNewGroup < 0 || iNewGroup > 159) + if (iNewGroup < -1 || iNewGroup > 159) { - argStream.SetCustomError("Expected group ID in range [0-159] at argument 1"); + argStream.SetCustomError("Expected group ID in range [0-159] or -1 at argument 1"); return luaL_error(luaVM, argStream.GetFullErrorMessage()); } @@ -2424,14 +2435,9 @@ bool CLuaEngineDefs::EngineResetModelFlags(uint uiModelID) return false; } -bool CLuaEngineDefs::EngineRestreamWorld(lua_State* const luaVM) +bool CLuaEngineDefs::EngineRestreamWorld() { - bool restreamLODs{}; - - CScriptArgReader argStream(luaVM); - argStream.ReadBool(restreamLODs, false); - - g_pClientGame->RestreamWorld(restreamLODs); + g_pClientGame->RestreamWorld(); return true; } @@ -2458,3 +2464,99 @@ bool CLuaEngineDefs::EngineFreeTXD(uint txdID) std::shared_ptr pModel = m_pManager->GetModelManager()->FindModelByID(MAX_MODEL_DFF_ID + txdID); return pModel && pModel->Deallocate(); } + +size_t CLuaEngineDefs::EngineGetPoolCapacity(ePools pool) +{ + return g_pGame->GetPools()->GetPoolCapacity(pool); +} + +size_t CLuaEngineDefs::EngineGetPoolDefaultCapacity(ePools pool) +{ + return g_pGame->GetPools()->GetPoolDefaultModdedCapacity(pool); +} + +size_t CLuaEngineDefs::EngineGetPoolUsedCapacity(ePools pool) +{ + return g_pGame->GetPools()->GetNumberOfUsedSpaces(pool); +} + +bool CLuaEngineDefs::EngineSetPoolCapacity(lua_State* luaVM, ePools pool, size_t newSize) +{ + size_t minSize = g_pGame->GetPools()->GetPoolDefaultModdedCapacity(pool); + if (newSize < minSize) + { + m_pScriptDebugging->LogWarning(luaVM, "Cannot set the pool capacity to less than the default capacity."); + return false; + } + + minSize = g_pGame->GetPools()->GetNumberOfUsedSpaces(pool); + if (newSize < minSize) + { + m_pScriptDebugging->LogWarning(luaVM, "Cannot set the pool capacity to less than the used capacity."); + return false; + } + + switch (pool) + { + case ePools::BUILDING_POOL: + { + return m_pBuildingManager->SetPoolCapacity(newSize); + } + default: + throw std::invalid_argument("Can not change this pool capacity"); + } + return true; +} + +bool CLuaEngineDefs::EngineStreamingRequestModel(lua_State* const luaVM, std::uint16_t modelId, std::optional addReference, std::optional blocking) +{ + // Grab the lua main and the resource belonging to this script + CLuaMain* pLuaMain = m_pLuaManager->GetVirtualMachine(luaVM); + + CModelInfo* pModelInfo = g_pGame->GetModelInfo(modelId); + + if (modelId >= g_pGame->GetBaseIDforCOL() || !pModelInfo) + throw std::invalid_argument("Expected a valid model ID at argument 1"); + + // Get the resource we belong to + CResource* pResource = pLuaMain->GetResource(); + + return pResource->GetResourceModelStreamer()->RequestModel(modelId, addReference.value_or(false), blocking.value_or(false)); +} + +bool CLuaEngineDefs::EngineStreamingReleaseModel(lua_State* const luaVM, std::uint16_t modelId, std::optional removeReference) +{ + // Grab the lua main and the resource belonging to this script + CLuaMain* pLuaMain = m_pLuaManager->GetVirtualMachine(luaVM); + + CModelInfo* pModelInfo = g_pGame->GetModelInfo(modelId); + + if (modelId >= g_pGame->GetBaseIDforCOL() || !pModelInfo) + throw std::invalid_argument("Expected a valid model ID at argument 1"); + + // Get the resource we belong to + CResource* pResource = pLuaMain->GetResource(); + + return pResource->GetResourceModelStreamer()->ReleaseModel(modelId, removeReference.value_or(false)); +} + +eModelLoadState CLuaEngineDefs::EngineStreamingGetModelLoadState(std::uint16_t modelId) +{ + const auto allCount = g_pGame->GetCountOfAllFileIDs(); + if (modelId >= g_pGame->GetCountOfAllFileIDs()) + throw std::invalid_argument("Expected a valid model ID at argument 1"); + + return g_pGame->GetStreaming()->GetStreamingInfo(modelId)->loadState; +} + +void CLuaEngineDefs::EnginePreloadWorldArea(CVector position, std::optional option) +{ + if (!option.has_value()) + option = PreloadAreaOption::ALL; + + if (option == PreloadAreaOption::ALL || option == PreloadAreaOption::MODELS) + g_pGame->GetStreaming()->LoadScene(&position); + + if (option == PreloadAreaOption::ALL || option == PreloadAreaOption::COLLISIONS) + g_pGame->GetStreaming()->LoadSceneCollision(&position); +} diff --git a/Client/mods/deathmatch/logic/luadefs/CLuaEngineDefs.h b/Client/mods/deathmatch/logic/luadefs/CLuaEngineDefs.h index 899d725915..a67ecfc68d 100644 --- a/Client/mods/deathmatch/logic/luadefs/CLuaEngineDefs.h +++ b/Client/mods/deathmatch/logic/luadefs/CLuaEngineDefs.h @@ -76,13 +76,24 @@ class CLuaEngineDefs : public CLuaDefs static bool EngineRestoreTXDImage(uint uiModelID); static std::vector EngineImageGetFileList(CClientIMG* pImg); static std::string EngineImageGetFile(CClientIMG* pImg, std::variant file); - static bool EngineRestreamWorld(lua_State* const luaVM); + static bool EngineRestreamWorld(); static bool EngineSetModelVisibleTime(std::string strModelId, char cHourOn, char cHourOff); static std::variant> EngineGetModelVisibleTime(std::string strModelId); + static size_t EngineGetPoolCapacity(ePools pool); + static size_t EngineGetPoolDefaultCapacity(ePools pool); + static size_t EngineGetPoolUsedCapacity(ePools pool); + static bool EngineSetPoolCapacity(lua_State* luaVM, ePools pool, size_t newSize); + static uint EngineRequestTXD(lua_State* const luaVM, std::string strTxdName); static bool EngineFreeTXD(uint txdID); + static bool EngineStreamingRequestModel(lua_State* const luaVM, std::uint16_t modelId, std::optional addReference, std::optional blocking); + static bool EngineStreamingReleaseModel(lua_State* const luaVM, std::uint16_t modelId, std::optional removeReference); + static eModelLoadState EngineStreamingGetModelLoadState(std::uint16_t modelId); + + static void EnginePreloadWorldArea(CVector position, std::optional option); + private: static void AddEngineColClass(lua_State* luaVM); static void AddEngineTxdClass(lua_State* luaVM); diff --git a/Client/mods/deathmatch/logic/luadefs/CLuaGUIDefs.cpp b/Client/mods/deathmatch/logic/luadefs/CLuaGUIDefs.cpp index 9c8ae1fa21..a3b7e35545 100644 --- a/Client/mods/deathmatch/logic/luadefs/CLuaGUIDefs.cpp +++ b/Client/mods/deathmatch/logic/luadefs/CLuaGUIDefs.cpp @@ -524,6 +524,7 @@ void CLuaGUIDefs::AddGuiGridlistClass(lua_State* luaVM) lua_classfunction(luaVM, "getSelectedCount", "guiGridListGetSelectedCount"); lua_classfunction(luaVM, "getSelectedItems", "guiGridListGetSelectedItems"); lua_classfunction(luaVM, "getColumnCount", "guiGridListGetColumnCount"); + lua_classfunction(luaVM, "getColumnWidth", "guiGridListGetColumnWidth"); lua_classfunction(luaVM, "setItemData", "guiGridListSetItemData"); lua_classfunction(luaVM, "setItemText", "guiGridListSetItemText"); @@ -2359,13 +2360,11 @@ int CLuaGUIDefs::GUIGridListAddRow(lua_State* luaVM) else { // Vector containing our string arguments. We add a bool to store whether it was originally a number. - std::vector > m_items; - std::vector::const_iterator it = Arguments.IterBegin(); - for (it; it != Arguments.IterEnd(); it++) + std::vector> m_items; + for (CLuaArgument* pArgument : Arguments) { - CLuaArgument* pArgument = *it; - SString strItemText; - bool bNumber = false; + SString strItemText; + bool bNumber = false; // Check the type of the argument and convert it to a string we can process uint type = pArgument->GetType(); @@ -2426,12 +2425,10 @@ int CLuaGUIDefs::GUIGridListInsertRowAfter(lua_State* luaVM) { // Vector containing our string arguments. We add a bool to store whether it was originally a number. std::vector > m_items; - std::vector::const_iterator it = Arguments.IterBegin(); - for (it; it != Arguments.IterEnd(); it++) + for (CLuaArgument* pArgument : Arguments) { - CLuaArgument* pArgument = *it; - SString strItemText; - bool bNumber = false; + SString strItemText; + bool bNumber = false; // Check the type of the argument and convert it to a string we can process uint type = pArgument->GetType(); diff --git a/Client/mods/deathmatch/logic/luadefs/CLuaMarkerDefs.cpp b/Client/mods/deathmatch/logic/luadefs/CLuaMarkerDefs.cpp index 071cad3870..6bbebf60f3 100644 --- a/Client/mods/deathmatch/logic/luadefs/CLuaMarkerDefs.cpp +++ b/Client/mods/deathmatch/logic/luadefs/CLuaMarkerDefs.cpp @@ -23,12 +23,14 @@ void CLuaMarkerDefs::LoadFunctions() {"getMarkerColor", GetMarkerColor}, {"getMarkerTarget", GetMarkerTarget}, {"getMarkerIcon", GetMarkerIcon}, + {"getMarkerTargetArrowProperties", ArgumentParser}, {"setMarkerType", SetMarkerType}, {"setMarkerSize", SetMarkerSize}, {"setMarkerColor", SetMarkerColor}, {"setMarkerTarget", SetMarkerTarget}, {"setMarkerIcon", SetMarkerIcon}, + {"setMarkerTargetArrowProperties", ArgumentParser}, {"setCoronaReflectionEnabled", ArgumentParser}, {"isCoronaReflectionEnabled", ArgumentParser}, @@ -75,6 +77,7 @@ int CLuaMarkerDefs::CreateMarker(lua_State* luaVM) float fSize = 4.0f; SColorRGBA color(0, 0, 255, 255); SString strType = "default"; + bool ignoreAlphaLimits; CScriptArgReader argStream(luaVM); argStream.ReadVector3D(vecPosition); argStream.ReadString(strType, "default"); @@ -83,6 +86,7 @@ int CLuaMarkerDefs::CreateMarker(lua_State* luaVM) argStream.ReadNumber(color.G, 0); argStream.ReadNumber(color.B, 255); argStream.ReadNumber(color.A, 255); + argStream.ReadBool(ignoreAlphaLimits, false); if (!argStream.HasErrors()) { @@ -92,7 +96,7 @@ int CLuaMarkerDefs::CreateMarker(lua_State* luaVM) CResource* pResource = pLuaMain->GetResource(); { // Create it - CClientMarker* pMarker = CStaticFunctionDefinitions::CreateMarker(*pResource, vecPosition, strType, fSize, color); + CClientMarker* pMarker = CStaticFunctionDefinitions::CreateMarker(*pResource, vecPosition, strType, fSize, color, ignoreAlphaLimits); if (pMarker) { CElementGroup* pGroup = pResource->GetElementGroup(); @@ -177,7 +181,12 @@ int CLuaMarkerDefs::GetMarkerColor(lua_State* luaVM) lua_pushnumber(luaVM, static_cast(color.R)); lua_pushnumber(luaVM, static_cast(color.G)); lua_pushnumber(luaVM, static_cast(color.B)); - lua_pushnumber(luaVM, static_cast(color.A)); + + if (!pMarker->AreAlphaLimitsIgnored() && (pMarker->GetMarkerType() == CClientMarker::MARKER_CHECKPOINT || pMarker->GetMarkerType() == CClientMarker::MARKER_ARROW)) + lua_pushnumber(luaVM, 255); // fake alpha + else + lua_pushnumber(luaVM, static_cast(color.A)); + return 4; } else @@ -417,3 +426,27 @@ bool CLuaMarkerDefs::IsCoronaReflectionEnabled(CClientMarker* pMarker) return pCorona->IsReflectionEnabled(); } + +bool CLuaMarkerDefs::SetMarkerTargetArrowProperties(CClientMarker* marker, std::optional r, std::optional g, std::optional b, std::optional a, std::optional size) +{ + SColor color; + color.R = r.value_or(255); + color.G = g.value_or(64); + color.B = b.value_or(64); + color.A = a.value_or(255); + + return CStaticFunctionDefinitions::SetMarkerTargetArrowProperties(*marker, color, size.value_or(marker->GetSize() * 0.625f)); +} + +std::variant, bool> CLuaMarkerDefs::GetMarkerTargetArrowProperties(CClientMarker* marker) noexcept +{ + CClientCheckpoint* checkpoint = marker->GetCheckpoint(); + if (!checkpoint) + return false; + + if (!checkpoint->HasTarget() || marker->GetMarkerType() != CClientMarker::MARKER_CHECKPOINT) + return false; + + SColor color = checkpoint->GetTargetArrowColor(); + return CLuaMultiReturn(color.R, color.G, color.B, color.A, checkpoint->GetTargetArrowSize()); +} diff --git a/Client/mods/deathmatch/logic/luadefs/CLuaMarkerDefs.h b/Client/mods/deathmatch/logic/luadefs/CLuaMarkerDefs.h index 6f0c1c0abb..3e351490b5 100644 --- a/Client/mods/deathmatch/logic/luadefs/CLuaMarkerDefs.h +++ b/Client/mods/deathmatch/logic/luadefs/CLuaMarkerDefs.h @@ -11,6 +11,7 @@ #pragma once #include "CLuaDefs.h" +#include "lua/CLuaMultiReturn.h" class CLuaMarkerDefs : public CLuaDefs { @@ -35,4 +36,7 @@ class CLuaMarkerDefs : public CLuaDefs static bool SetCoronaReflectionEnabled(CClientMarker* pMarker, bool bEnabled); static bool IsCoronaReflectionEnabled(CClientMarker* pMarker); + + static bool SetMarkerTargetArrowProperties(CClientMarker* marker, std::optional r, std::optional g, std::optional b, std::optional a, std::optional size); + static std::variant, bool> GetMarkerTargetArrowProperties(CClientMarker* marker) noexcept; }; diff --git a/Client/mods/deathmatch/logic/luadefs/CLuaObjectDefs.cpp b/Client/mods/deathmatch/logic/luadefs/CLuaObjectDefs.cpp index c47934bc07..6dd306336e 100644 --- a/Client/mods/deathmatch/logic/luadefs/CLuaObjectDefs.cpp +++ b/Client/mods/deathmatch/logic/luadefs/CLuaObjectDefs.cpp @@ -25,6 +25,7 @@ void CLuaObjectDefs::LoadFunctions() {"getObjectMass", GetObjectMass}, {"getObjectProperty", GetObjectProperty}, {"isObjectMoving", ArgumentParser}, + {"isObjectRespawnable", ArgumentParser}, // Object set funcs {"moveObject", MoveObject}, @@ -61,6 +62,7 @@ void CLuaObjectDefs::AddClass(lua_State* luaVM) lua_classfunction(luaVM, "getProperties", GetObjectProperties); lua_classfunction(luaVM, "getProperty", "getObjectProperty"); lua_classfunction(luaVM, "isMoving", "isObjectMoving"); + lua_classfunction(luaVM, "isRespawnable", "isObjectRespawnable"); lua_classfunction(luaVM, "setScale", "setObjectScale"); lua_classfunction(luaVM, "setBreakable", "setObjectBreakable"); @@ -272,7 +274,7 @@ int CLuaObjectDefs::GetObjectProperty(lua_State* luaVM) lua_setfield(luaVM, -2, EnumToString(eObjectProperty::OBJECT_PROPERTY_TURNMASS)); lua_pushnumber(luaVM, pObject->GetAirResistance()); - lua_setfield(luaVM, -2, EnumToString(eObjectProperty::OBJECT_PROPERTY_TURNMASS)); + lua_setfield(luaVM, -2, EnumToString(eObjectProperty::OBJECT_PROPERTY_AIRRESISTANCE)); lua_pushnumber(luaVM, pObject->GetElasticity()); lua_setfield(luaVM, -2, EnumToString(eObjectProperty::OBJECT_PROPERTY_ELASTICITY)); @@ -707,3 +709,15 @@ int CLuaObjectDefs::SetObjectProperty(lua_State* luaVM) lua_pushboolean(luaVM, false); return 1; } + +bool CLuaObjectDefs::IsObjectRespawnable(CClientEntity* const pEntity) noexcept +{ + if (!IS_OBJECT(pEntity)) + return false; + + auto* pObject = static_cast(pEntity); + if (!pObject) + return false; + + return pObject->IsRespawnEnabled(); +} diff --git a/Client/mods/deathmatch/logic/luadefs/CLuaObjectDefs.h b/Client/mods/deathmatch/logic/luadefs/CLuaObjectDefs.h index e614ef9f29..1ce12ad20e 100644 --- a/Client/mods/deathmatch/logic/luadefs/CLuaObjectDefs.h +++ b/Client/mods/deathmatch/logic/luadefs/CLuaObjectDefs.h @@ -29,6 +29,7 @@ class CLuaObjectDefs : public CLuaDefs LUA_DECLARE(GetObjectMass); LUA_DECLARE(GetObjectProperty); LUA_DECLARE(GetObjectProperties); + static bool IsObjectRespawnable(CClientEntity* const pEntity) noexcept; // Object set funcs LUA_DECLARE(SetObjectRotation); diff --git a/Client/mods/deathmatch/logic/luadefs/CLuaPedDefs.cpp b/Client/mods/deathmatch/logic/luadefs/CLuaPedDefs.cpp index 63c3711064..2c8741f4d7 100644 --- a/Client/mods/deathmatch/logic/luadefs/CLuaPedDefs.cpp +++ b/Client/mods/deathmatch/logic/luadefs/CLuaPedDefs.cpp @@ -54,8 +54,10 @@ void CLuaPedDefs::LoadFunctions() {"getPedBonePosition", GetPedBonePosition}, {"setElementBonePosition", ArgumentParser}, {"setElementBoneRotation", ArgumentParser}, + {"setElementBoneQuaternion", ArgumentParser}, {"getElementBonePosition", ArgumentParser}, {"getElementBoneRotation", ArgumentParser}, + {"getElementBoneQuaternion", ArgumentParser}, {"setElementBoneMatrix", ArgumentParser}, {"getElementBoneMatrix", ArgumentParser}, {"updateElementRpHAnim", ArgumentParser}, @@ -998,43 +1000,77 @@ int CLuaPedDefs::CanPedBeKnockedOffBike(lua_State* luaVM) return 1; } -bool CLuaPedDefs::SetElementBonePosition(lua_State* const luaVM, CClientPed* entity, std::int32_t boneId, CVector position) +bool CLuaPedDefs::SetElementBonePosition(lua_State* const luaVM, CClientPed* entity, std::uint32_t boneId, CVector position) { CEntity* theEntity = entity->GetGameEntity(); - return theEntity ? theEntity->SetBonePosition(static_cast(boneId), position) : false; + if (!theEntity) + return false; + return theEntity->SetBonePosition(static_cast(boneId), position); } -bool CLuaPedDefs::SetElementBoneRotation(lua_State* const luaVM, CClientPed* entity, std::int32_t boneId, float yaw, float pitch, float roll) +bool CLuaPedDefs::SetElementBoneRotation(lua_State* const luaVM, CClientPed* entity, std::uint32_t boneId, float yaw, float pitch, float roll) { + if (boneId > BONE_RIGHTFOOT) + throw LuaFunctionError("Invalid bone ID", false); + CEntity* theEntity = entity->GetGameEntity(); - return theEntity ? theEntity->SetBoneRotation(static_cast(boneId), yaw, pitch, roll) : false; + if (!theEntity) + return false; + return theEntity->SetBoneRotation(static_cast(boneId), yaw, pitch, roll); } -std::variant> CLuaPedDefs::GetElementBonePosition(lua_State* const luaVM, CClientPed* entity, std::int32_t boneId) +bool CLuaPedDefs::SetElementBoneQuaternion(lua_State* const luaVM, CClientPed* entity, std::uint32_t boneId, float x, float y, float z, float w) +{ + if (boneId > BONE_RIGHTFOOT) + throw LuaFunctionError("Invalid bone ID", false); + + CEntity* theEntity = entity->GetGameEntity(); + return theEntity ? theEntity->SetBoneRotationQuat(static_cast(boneId), x, y, z, w) : false; +} + +std::variant> CLuaPedDefs::GetElementBonePosition(lua_State* const luaVM, CClientPed* entity, std::uint32_t boneId) { CEntity* theEntity = entity->GetGameEntity(); CVector position; - if (theEntity && theEntity->GetBonePosition(static_cast(boneId), position)) - return std::make_tuple(position.fX, position.fY, position.fZ); - return false; + if (!theEntity || !theEntity->GetBonePosition(static_cast(boneId), position)) + return false; + + return std::make_tuple(position.fX, position.fY, position.fZ); } -std::variant> CLuaPedDefs::GetElementBoneRotation(lua_State* const luaVM, CClientPed* entity, std::int32_t boneId) +std::variant> CLuaPedDefs::GetElementBoneRotation(lua_State* const luaVM, CClientPed* entity, std::uint32_t boneId) { - float yaw = 0.0f, pitch = 0.0f, roll = 0.0f; + if (boneId > BONE_RIGHTFOOT) + throw LuaFunctionError("Invalid bone ID", false); + + float yaw = 0.0f, pitch = 0.0f, roll = 0.0f; CEntity* theEntity = entity->GetGameEntity(); - if (theEntity && theEntity->GetBoneRotation(static_cast(boneId), yaw, pitch, roll)) - return std::make_tuple(yaw, pitch, roll); - return false; + if (!theEntity || !theEntity->GetBoneRotation(static_cast(boneId), yaw, pitch, roll)) + return false; + + return std::make_tuple(yaw, pitch, roll); +} + +std::variant> CLuaPedDefs::GetElementBoneQuaternion(lua_State* const luaVM, CClientPed* entity, std::uint32_t boneId) +{ + if (boneId > BONE_RIGHTFOOT) + throw LuaFunctionError("Invalid bone ID", false); + + float x = 0.0f, y = 0.0f, z = 0.0f, w = 0.0f; + CEntity* theEntity = entity->GetGameEntity(); + if (!theEntity || !theEntity->GetBoneRotationQuat(static_cast(boneId), x, y, z, w)) + return false; + + return std::make_tuple(x, y, z, w); } -bool CLuaPedDefs::SetElementBoneMatrix(lua_State* const luaVM, CClientPed* entity, std::int32_t boneId, CMatrix boneMatrix) +bool CLuaPedDefs::SetElementBoneMatrix(lua_State* const luaVM, CClientPed* entity, std::uint32_t boneId, CMatrix boneMatrix) { CEntity* theEntity = entity->GetGameEntity(); return theEntity ? theEntity->SetBoneMatrix(static_cast(boneId), boneMatrix) : false; } -std::variant, 4>> CLuaPedDefs::GetElementBoneMatrix(lua_State* const luaVM, CClientPed* entity, std::int32_t boneId) +std::variant, 4>> CLuaPedDefs::GetElementBoneMatrix(lua_State* const luaVM, CClientPed* entity, std::uint32_t boneId) { CEntity* theEntity = entity->GetGameEntity(); if (theEntity) diff --git a/Client/mods/deathmatch/logic/luadefs/CLuaPedDefs.h b/Client/mods/deathmatch/logic/luadefs/CLuaPedDefs.h index 1758011f70..126c463af7 100644 --- a/Client/mods/deathmatch/logic/luadefs/CLuaPedDefs.h +++ b/Client/mods/deathmatch/logic/luadefs/CLuaPedDefs.h @@ -50,15 +50,17 @@ class CLuaPedDefs : public CLuaDefs LUA_DECLARE(GetPedContactElement); LUA_DECLARE(GetPedRotation); LUA_DECLARE(CanPedBeKnockedOffBike); - static bool SetElementBonePosition(lua_State* const luaVM, CClientPed* entity, std::int32_t boneId, CVector position); - static bool SetElementBoneRotation(lua_State* const luaVM, CClientPed* entity, std::int32_t boneId, float yaw, float pitch, float roll); - static std::variant> GetElementBonePosition(lua_State* const luaVM, CClientPed* entity, std::int32_t boneId); + static bool SetElementBonePosition(lua_State* const luaVM, CClientPed* entity, std::uint32_t boneId, CVector position); + static bool SetElementBoneRotation(lua_State* const luaVM, CClientPed* entity, std::uint32_t boneId, float yaw, float pitch, float roll); + static bool SetElementBoneQuaternion(lua_State* const luaVM, CClientPed* entity, std::uint32_t boneId, float x, float y, float z, float w); + static std::variant> GetElementBonePosition(lua_State* const luaVM, CClientPed* entity, std::uint32_t boneId); - static std::variant> GetElementBoneRotation(lua_State* const luaVM, CClientPed* entity, std::int32_t boneId); + static std::variant> GetElementBoneRotation(lua_State* const luaVM, CClientPed* entity, std::uint32_t boneId); + static std::variant> GetElementBoneQuaternion(lua_State* const luaVM, CClientPed* entity, std::uint32_t boneId); - static bool SetElementBoneMatrix(lua_State* const luaVM, CClientPed* entity, std::int32_t boneId, CMatrix boneMatrix); + static bool SetElementBoneMatrix(lua_State* const luaVM, CClientPed* entity, std::uint32_t boneId, CMatrix boneMatrix); - static std::variant, 4>> GetElementBoneMatrix(lua_State* const luaVM, CClientPed* entity, std::int32_t boneId); + static std::variant, 4>> GetElementBoneMatrix(lua_State* const luaVM, CClientPed* entity, std::uint32_t boneId); static bool UpdateElementRpHAnim(lua_State* const luaVM, CClientEntity* entity); LUA_DECLARE_OOP(GetPedBonePosition); diff --git a/Client/mods/deathmatch/logic/luadefs/CLuaPlayerDefs.cpp b/Client/mods/deathmatch/logic/luadefs/CLuaPlayerDefs.cpp index 023b1c4191..e276a3ddf7 100644 --- a/Client/mods/deathmatch/logic/luadefs/CLuaPlayerDefs.cpp +++ b/Client/mods/deathmatch/logic/luadefs/CLuaPlayerDefs.cpp @@ -28,6 +28,8 @@ void CLuaPlayerDefs::LoadFunctions() {"isPlayerHudComponentVisible", IsPlayerHudComponentVisible}, {"getPlayerMoney", GetPlayerMoney}, {"getPlayerWantedLevel", GetPlayerWantedLevel}, + {"getPlayerScriptDebugLevel", ArgumentParser}, + {"isPlayerCrosshairVisible", ArgumentParser}, // Player set funcs {"showPlayerHudComponent", ShowPlayerHudComponent}, @@ -87,14 +89,18 @@ void CLuaPlayerDefs::AddClass(lua_State* luaVM) lua_classfunction(luaVM, "getTeam", "getPlayerTeam"); lua_classfunction(luaVM, "getNametagText", "getPlayerNametagText"); lua_classfunction(luaVM, "getNametagColor", "getPlayerNametagColor"); + lua_classfunction(luaVM, "getScriptDebugLevel", "getPlayerScriptDebugLevel"); lua_classfunction(luaVM, "isNametagShowing", "isPlayerNametagShowing"); + lua_classfunction(luaVM, "isCrosshairVisible", "isPlayerCrosshairVisible"); lua_classvariable(luaVM, "ping", NULL, "getPlayerPing"); lua_classvariable(luaVM, "name", NULL, "getPlayerName"); lua_classvariable(luaVM, "team", NULL, "getPlayerTeam"); + lua_classvariable(luaVM, "scriptDebugLevel", nullptr, "getPlayerScriptDebugLevel"); lua_classvariable(luaVM, "nametagText", "setPlayerNametagText", "getPlayerNametagText"); lua_classvariable(luaVM, "nametagShowing", "setPlayerNametagShowing", "isPlayerNametagShowing"); + lua_classvariable(luaVM, "crosshairVisible", nullptr, "isPlayerCrosshairVisible"); lua_registerclass(luaVM, "Player", "Ped"); } @@ -309,6 +315,11 @@ int CLuaPlayerDefs::GetPlayerWantedLevel(lua_State* luaVM) return 1; } +std::uint8_t CLuaPlayerDefs::GetPlayerScriptDebugLevel() noexcept +{ + return g_pClientGame->GetPlayerManager()->GetLocalPlayer()->GetPlayerScriptDebugLevel(); +} + int CLuaPlayerDefs::ShowPlayerHudComponent(lua_State* luaVM) { // bool showPlayerHudComponent ( string component, bool show ) @@ -628,3 +639,8 @@ unsigned char CLuaPlayerDefs::GetPlayerMapOpacity() int iMapOpacity = g_pCore->GetCVars()->GetValue("mapalpha"); return static_cast(Clamp(0, iMapOpacity, 255)); } + +bool CLuaPlayerDefs::IsPlayerCrosshairVisible() +{ + return g_pGame->GetHud()->IsCrosshairVisible(); +} diff --git a/Client/mods/deathmatch/logic/luadefs/CLuaPlayerDefs.h b/Client/mods/deathmatch/logic/luadefs/CLuaPlayerDefs.h index fbe910c4ca..1a2895ed3d 100644 --- a/Client/mods/deathmatch/logic/luadefs/CLuaPlayerDefs.h +++ b/Client/mods/deathmatch/logic/luadefs/CLuaPlayerDefs.h @@ -29,6 +29,8 @@ class CLuaPlayerDefs : public CLuaDefs LUA_DECLARE(GetPlayerTeam); LUA_DECLARE(GetPlayerMoney); LUA_DECLARE(GetPlayerWantedLevel); + static std::uint8_t GetPlayerScriptDebugLevel() noexcept; + static bool IsPlayerCrosshairVisible(); // Player set LUA_DECLARE(ShowPlayerHudComponent); diff --git a/Client/mods/deathmatch/logic/luadefs/CLuaResourceDefs.cpp b/Client/mods/deathmatch/logic/luadefs/CLuaResourceDefs.cpp index 62a8b2f531..e2a072307c 100644 --- a/Client/mods/deathmatch/logic/luadefs/CLuaResourceDefs.cpp +++ b/Client/mods/deathmatch/logic/luadefs/CLuaResourceDefs.cpp @@ -10,6 +10,8 @@ *****************************************************************************/ #include "StdInc.h" +#include + using std::list; void CLuaResourceDefs::LoadFunctions() @@ -18,7 +20,7 @@ void CLuaResourceDefs::LoadFunctions() {"call", Call}, {"getThisResource", GetThisResource}, {"getResourceConfig", GetResourceConfig}, - {"getResourceName", GetResourceName}, + {"getResourceName", ArgumentParserWarn}, {"getResourceFromName", GetResourceFromName}, {"getResourceRootElement", GetResourceRootElement}, {"getResourceGUIElement", GetResourceGUIElement}, @@ -220,34 +222,17 @@ int CLuaResourceDefs::GetResourceConfig(lua_State* luaVM) return 1; } -int CLuaResourceDefs::GetResourceName(lua_State* luaVM) +std::string CLuaResourceDefs::GetResourceName(lua_State* luaVM, std::optional resourceElement) { - // Verify arguments - CResource* pResource = NULL; - CScriptArgReader argStream(luaVM); - argStream.ReadUserData(pResource); + if (resourceElement.has_value()) + return (*resourceElement)->GetName(); - if (!argStream.HasErrors()) - { - if (pResource) - { - // Grab its name and return it - const char* szName = pResource->GetName(); - if (szName) - { - lua_pushstring(luaVM, szName); - return 1; - } - } - else - m_pScriptDebugging->LogBadPointer(luaVM, "resource", 1); - } - else - m_pScriptDebugging->LogCustom(luaVM, argStream.GetFullErrorMessage()); + CResource* localResource = &lua_getownerresource(luaVM); - // Failed - lua_pushboolean(luaVM, false); - return 1; + if (!localResource) + throw std::invalid_argument("Couldn't find the resource"); + + return localResource->GetName(); } int CLuaResourceDefs::GetResourceFromName(lua_State* luaVM) @@ -503,9 +488,9 @@ int CLuaResourceDefs::Load(lua_State* luaVM) { CLuaArguments returnValues; callbackArguments.Call(pLuaMain, iLuaFunction, &returnValues); - if (returnValues.Count()) + if (returnValues.IsNotEmpty()) { - CLuaArgument* returnedValue = *returnValues.IterBegin(); + CLuaArgument* returnedValue = *returnValues.begin(); int iType = returnedValue->GetType(); if (iType == LUA_TNIL) break; diff --git a/Client/mods/deathmatch/logic/luadefs/CLuaResourceDefs.h b/Client/mods/deathmatch/logic/luadefs/CLuaResourceDefs.h index deb8fe9a90..eba15fa6c7 100644 --- a/Client/mods/deathmatch/logic/luadefs/CLuaResourceDefs.h +++ b/Client/mods/deathmatch/logic/luadefs/CLuaResourceDefs.h @@ -21,7 +21,6 @@ class CLuaResourceDefs : public CLuaDefs LUA_DECLARE(Call); LUA_DECLARE(GetThisResource); LUA_DECLARE(GetResourceConfig); - LUA_DECLARE(GetResourceName); LUA_DECLARE(GetResourceFromName); LUA_DECLARE(GetResourceRootElement); LUA_DECLARE(GetResourceGUIElement); @@ -30,4 +29,6 @@ class CLuaResourceDefs : public CLuaDefs LUA_DECLARE(GetResourceState); LUA_DECLARE(LoadString); LUA_DECLARE(Load); + + static std::string GetResourceName(lua_State* luaVM, std::optional resourceElement); }; diff --git a/Client/mods/deathmatch/logic/luadefs/CLuaTimerDefs.cpp b/Client/mods/deathmatch/logic/luadefs/CLuaTimerDefs.cpp index 401abcfd96..e0c8a96ba0 100644 --- a/Client/mods/deathmatch/logic/luadefs/CLuaTimerDefs.cpp +++ b/Client/mods/deathmatch/logic/luadefs/CLuaTimerDefs.cpp @@ -10,12 +10,14 @@ *****************************************************************************/ #include "StdInc.h" +#include void CLuaTimerDefs::LoadFunctions() { constexpr static const std::pair functions[]{ - {"setTimer", SetTimer}, {"killTimer", KillTimer}, {"resetTimer", ResetTimer}, - {"getTimers", GetTimers}, {"isTimer", IsTimer}, {"getTimerDetails", GetTimerDetails}, + {"setTimer", SetTimer}, {"killTimer", KillTimer}, {"resetTimer", ResetTimer}, + {"setTimerPaused", ArgumentParser},{"isTimerPaused", ArgumentParser}, + {"getTimers", GetTimers}, {"isTimer", IsTimer}, {"getTimerDetails", GetTimerDetails}, }; // Add functions @@ -31,10 +33,10 @@ void CLuaTimerDefs::AddClass(lua_State* luaVM) lua_classfunction(luaVM, "destroy", "killTimer"); lua_classfunction(luaVM, "reset", "resetTimer"); lua_classfunction(luaVM, "isValid", "isTimer"); - lua_classfunction(luaVM, "getDetails", "getTimerDetails"); lua_classvariable(luaVM, "valid", NULL, "isTimer"); + lua_classvariable(luaVM, "paused", "setTimerPaused", "isTimerPaused"); lua_registerclass(luaVM, "Timer"); } @@ -111,6 +113,22 @@ int CLuaTimerDefs::KillTimer(lua_State* luaVM) return 1; } +bool CLuaTimerDefs::IsTimerPaused(CLuaTimer* timer) noexcept +{ + return timer->IsPaused(); +} + +bool CLuaTimerDefs::SetTimerPaused(lua_State* luaVM, CLuaTimer* timer, bool paused) +{ + // bool setTimerPaused ( timer theTimer, bool paused ) + CLuaMain* luaMain = m_pLuaManager->GetVirtualMachine(luaVM); + if (!luaMain) + return false; + + luaMain->GetTimerManager()->SetTimerPaused(timer, paused); + return true; +} + int CLuaTimerDefs::ResetTimer(lua_State* luaVM) { // bool resetTimer ( timer theTimer ) diff --git a/Client/mods/deathmatch/logic/luadefs/CLuaTimerDefs.h b/Client/mods/deathmatch/logic/luadefs/CLuaTimerDefs.h index 671a329b28..db6cac48a9 100644 --- a/Client/mods/deathmatch/logic/luadefs/CLuaTimerDefs.h +++ b/Client/mods/deathmatch/logic/luadefs/CLuaTimerDefs.h @@ -24,4 +24,6 @@ class CLuaTimerDefs : public CLuaDefs LUA_DECLARE(GetTimers); LUA_DECLARE(IsTimer); LUA_DECLARE(GetTimerDetails); + static bool IsTimerPaused(CLuaTimer* timer) noexcept; + static bool SetTimerPaused(lua_State* luaVM, CLuaTimer* timer, bool paused); }; diff --git a/Client/mods/deathmatch/logic/luadefs/CLuaVectorGraphicDefs.cpp b/Client/mods/deathmatch/logic/luadefs/CLuaVectorGraphicDefs.cpp index e70cfa77ae..eba1e21d0c 100644 --- a/Client/mods/deathmatch/logic/luadefs/CLuaVectorGraphicDefs.cpp +++ b/Client/mods/deathmatch/logic/luadefs/CLuaVectorGraphicDefs.cpp @@ -101,10 +101,16 @@ bool CLuaVectorGraphicDefs::SetSize(CClientVectorGraphic* vectorGraphic, CVector if (!vectorGraphicItem) return false; - vectorGraphicItem->Resize(size); + if (size.fX <= 0 || size.fY <= 0) + throw std::invalid_argument("A vector graphic must be atleast 1x1 in size."); + + if (size.fX > 4096 || size.fY > 4096) + throw std::invalid_argument("A vector graphic cannot exceed 4096x4096 in size."); + + int intSizeX = static_cast(size.fX); + int intSizeY = static_cast(size.fY); - if ((int)vectorGraphicItem->m_uiSizeX != size.fX || (int)vectorGraphicItem->m_uiSizeY != size.fY) - return false; // failed to resize + vectorGraphicItem->Resize(CVector2D(intSizeX, intSizeY)); vectorGraphic->GetDisplay()->Update(); return true; diff --git a/Client/mods/deathmatch/logic/luadefs/CLuaVehicleDefs.cpp b/Client/mods/deathmatch/logic/luadefs/CLuaVehicleDefs.cpp index f29820a871..b35bfee24b 100644 --- a/Client/mods/deathmatch/logic/luadefs/CLuaVehicleDefs.cpp +++ b/Client/mods/deathmatch/logic/luadefs/CLuaVehicleDefs.cpp @@ -54,6 +54,7 @@ void CLuaVehicleDefs::LoadFunctions() {"getVehicleNameFromModel", GetVehicleNameFromModel}, {"getVehicleAdjustableProperty", GetVehicleAdjustableProperty}, {"getHelicopterRotorSpeed", GetHelicopterRotorSpeed}, + {"getVehicleRotorSpeed", ArgumentParser}, {"getVehicleEngineState", GetVehicleEngineState}, {"isTrainDerailed", IsTrainDerailed}, {"isTrainDerailable", IsTrainDerailable}, @@ -90,6 +91,7 @@ void CLuaVehicleDefs::LoadFunctions() {"getVehicleWheelScale", ArgumentParser}, {"getVehicleModelWheelSize", ArgumentParser}, {"getVehicleWheelFrictionState", ArgumentParser}, + {"getVehicleEntryPoints", ArgumentParser}, // Vehicle set funcs {"createVehicle", CreateVehicle}, @@ -118,6 +120,8 @@ void CLuaVehicleDefs::LoadFunctions() {"setVehicleFrozen", SetVehicleFrozen}, {"setVehicleAdjustableProperty", SetVehicleAdjustableProperty}, {"setHelicopterRotorSpeed", SetHelicopterRotorSpeed}, + {"setVehicleRotorSpeed", ArgumentParser}, + {"setVehicleWheelsRotation", ArgumentParser}, {"setTrainDerailed", SetTrainDerailed}, {"setTrainDerailable", SetTrainDerailable}, {"setTrainDirection", SetTrainDirection}, @@ -238,6 +242,7 @@ void CLuaVehicleDefs::AddClass(lua_State* luaVM) lua_classfunction(luaVM, "getWheelScale", "getVehicleWheelScale"); lua_classfunction(luaVM, "getModelWheelSize", "getVehicleModelWheelSize"); lua_classfunction(luaVM, "getWheelFrictionState", "getVehicleWheelFrictionState"); + lua_classfunction(luaVM, "getEntryPoints", ArgumentParser); lua_classfunction(luaVM, "setComponentVisible", "setVehicleComponentVisible"); lua_classfunction(luaVM, "setSirensOn", "setVehicleSirensOn"); @@ -1293,6 +1298,17 @@ int CLuaVehicleDefs::GetHelicopterRotorSpeed(lua_State* luaVM) return 1; } +std::variant CLuaVehicleDefs::GetVehicleRotorSpeed(CClientVehicle* pVehicle) +{ + float fSpeed; + if (pVehicle->GetRotorSpeed(fSpeed)) + { + return fSpeed; + } + else + return false; +} + int CLuaVehicleDefs::IsTrainDerailed(lua_State* luaVM) { CClientVehicle* pVehicle = NULL; @@ -2204,6 +2220,16 @@ int CLuaVehicleDefs::SetHelicopterRotorSpeed(lua_State* luaVM) return 1; } +bool CLuaVehicleDefs::SetVehicleRotorSpeed(CClientVehicle* pVehicle, float fSpeed) +{ + return pVehicle->SetRotorSpeed(fSpeed); +} + +bool CLuaVehicleDefs::SetVehicleWheelsRotation(CClientVehicle* pVehicle, float fRotation) noexcept +{ + return pVehicle->SetWheelsRotation(fRotation, fRotation, fRotation, fRotation); +} + int CLuaVehicleDefs::SetTrainDerailed(lua_State* luaVM) { CClientVehicle* pVehicle = NULL; @@ -2623,12 +2649,69 @@ int CLuaVehicleDefs::SetVehicleHandling(lua_State* luaVM) int CLuaVehicleDefs::GetVehicleHandling(lua_State* luaVM) { + // table getVehicleHandling ( element theVehicle, [ string property ] ) CClientVehicle* pVehicle = NULL; CScriptArgReader argStream(luaVM); argStream.ReadUserData(pVehicle); if (!argStream.HasErrors()) { + if (argStream.NextIsString()) + { + SString strProperty; + argStream.ReadString(strProperty); + + eHandlingProperty eProperty = g_pGame->GetHandlingManager()->GetPropertyEnumFromName(strProperty); + if (eProperty == HANDLING_MAX) + { + argStream.SetCustomError("Invalid property"); + m_pScriptDebugging->LogCustom(luaVM, argStream.GetFullErrorMessage()); + lua_pushboolean(luaVM, false); + return 1; + } + + float fValue = 0.0f; + CVector vecValue = CVector(0.0f, 0.0f, 0.0f); + SString strValue = ""; + unsigned int uiValue = 0; + unsigned char ucValue = 0; + if (CStaticFunctionDefinitions::GetVehicleHandling(pVehicle, eProperty, fValue)) + { + lua_pushnumber(luaVM, fValue); + } + else if (CStaticFunctionDefinitions::GetVehicleHandling(pVehicle, eProperty, uiValue)) + { + lua_pushnumber(luaVM, uiValue); + } + else if (CStaticFunctionDefinitions::GetVehicleHandling(pVehicle, eProperty, ucValue)) + { + lua_pushnumber(luaVM, ucValue); + } + else if (CStaticFunctionDefinitions::GetVehicleHandling(pVehicle, eProperty, strValue)) + { + lua_pushstring(luaVM, strValue); + } + else if (CStaticFunctionDefinitions::GetVehicleHandling(pVehicle, eProperty, vecValue)) + { + lua_createtable(luaVM, 3, 0); + lua_pushnumber(luaVM, 1); + lua_pushnumber(luaVM, vecValue.fX); + lua_settable(luaVM, -3); + lua_pushnumber(luaVM, 2); + lua_pushnumber(luaVM, vecValue.fY); + lua_settable(luaVM, -3); + lua_pushnumber(luaVM, 3); + lua_pushnumber(luaVM, vecValue.fZ); + lua_settable(luaVM, -3); + } + else + { + argStream.SetCustomError("Invalid property"); + m_pScriptDebugging->LogCustom(luaVM, argStream.GetFullErrorMessage()); + lua_pushboolean(luaVM, false); + } + return 1; + } CHandlingEntry* pEntry = pVehicle->GetHandlingData(); lua_newtable(luaVM); @@ -4150,3 +4233,43 @@ bool CLuaVehicleDefs::BlowVehicle(CClientEntity* entity, std::optional wit { return CStaticFunctionDefinitions::BlowVehicle(*entity, withExplosion); } + +std::variant, 4>> CLuaVehicleDefs::GetVehicleEntryPoints(CClientVehicle* vehicle) +{ + auto entryPointVectors = OOP_GetVehicleEntryPoints(vehicle); + + if (std::holds_alternative(entryPointVectors)) + { + return false; + } + + std::array, 4> entryPoints; + std::array vectorArray = std::get>(entryPointVectors); + + std::uint32_t i = 0; + for (auto& entryPoint : entryPoints) + { + entryPoints[i] = {vectorArray[i].fX, vectorArray[i].fY, vectorArray[i].fZ}; + i++; + } + + return entryPoints; +} + +std::variant> CLuaVehicleDefs::OOP_GetVehicleEntryPoints(CClientVehicle* vehicle) +{ + if (CClientVehicleManager::GetMaxPassengerCount(vehicle->GetModel()) == 255) + { + return false; + } + + std::array entryPoints; + + std::uint32_t i = 0; + for (auto& entryPoint : entryPoints) + { + entryPoint = vehicle->GetEntryPoint(i++); + } + + return entryPoints; +} diff --git a/Client/mods/deathmatch/logic/luadefs/CLuaVehicleDefs.h b/Client/mods/deathmatch/logic/luadefs/CLuaVehicleDefs.h index 697b7ec8a2..5c2e908d58 100644 --- a/Client/mods/deathmatch/logic/luadefs/CLuaVehicleDefs.h +++ b/Client/mods/deathmatch/logic/luadefs/CLuaVehicleDefs.h @@ -59,6 +59,7 @@ class CLuaVehicleDefs : public CLuaDefs LUA_DECLARE(GetVehicleNameFromModel); LUA_DECLARE(GetVehicleAdjustableProperty); LUA_DECLARE(GetHelicopterRotorSpeed); + static std::variant GetVehicleRotorSpeed(CClientVehicle* pVehicle); LUA_DECLARE(GetVehicleEngineState); LUA_DECLARE(IsTrainDerailed); LUA_DECLARE(IsTrainDerailable); @@ -117,6 +118,8 @@ class CLuaVehicleDefs : public CLuaDefs LUA_DECLARE(SetVehicleFrozen); LUA_DECLARE(SetVehicleAdjustableProperty); LUA_DECLARE(SetHelicopterRotorSpeed); + static bool SetVehicleRotorSpeed(CClientVehicle* pVehicle, float fSpeed); + static bool SetVehicleWheelsRotation(CClientVehicle* pVehicle, float fRotation) noexcept; LUA_DECLARE(SetTrainDerailed); LUA_DECLARE(SetTrainDerailable); LUA_DECLARE(SetTrainDirection); @@ -149,6 +152,9 @@ class CLuaVehicleDefs : public CLuaDefs static std::variant OOP_GetVehicleDummyPosition(CClientVehicle* vehicle, eVehicleDummies dummy); static bool ResetVehicleDummyPositions(CClientVehicle* vehicle); + static std::variant, 4>> GetVehicleEntryPoints(CClientVehicle* vehicle); + static std::variant> OOP_GetVehicleEntryPoints(CClientVehicle* vehicle); + LUA_DECLARE(SetVehicleModelExhaustFumesPosition); LUA_DECLARE_OOP(GetVehicleModelExhaustFumesPosition); diff --git a/Client/mods/deathmatch/logic/luadefs/CLuaWorldDefs.cpp b/Client/mods/deathmatch/logic/luadefs/CLuaWorldDefs.cpp index 40f5b345da..382c2c7488 100644 --- a/Client/mods/deathmatch/logic/luadefs/CLuaWorldDefs.cpp +++ b/Client/mods/deathmatch/logic/luadefs/CLuaWorldDefs.cpp @@ -12,6 +12,7 @@ #include #include #include +#include #include "lua/CLuaFunctionParser.h" void CLuaWorldDefs::LoadFunctions() @@ -58,6 +59,7 @@ void CLuaWorldDefs::LoadFunctions() {"getFPSLimit", GetFPSLimit}, {"getBirdsEnabled", GetBirdsEnabled}, {"getCoronaReflectionsEnabled", ArgumentParser}, + {"getWorldProperty", ArgumentParser}, // World set funcs {"setTime", SetTime}, @@ -73,7 +75,7 @@ void CLuaWorldDefs::LoadFunctions() {"setWaveHeight", SetWaveHeight}, {"setMinuteDuration", SetMinuteDuration}, {"setGarageOpen", SetGarageOpen}, - {"setWorldSpecialPropertyEnabled", ArgumentParserWarn}, + {"setWorldSpecialPropertyEnabled", ArgumentParser}, {"setBlurLevel", SetBlurLevel}, {"setJetpackMaxHeight", SetJetpackMaxHeight}, {"setCloudsEnabled", SetCloudsEnabled}, @@ -98,9 +100,12 @@ void CLuaWorldDefs::LoadFunctions() {"setMoonSize", SetMoonSize}, {"setFPSLimit", SetFPSLimit}, {"setCoronaReflectionsEnabled", ArgumentParser}, + {"setWorldProperty", ArgumentParser}, {"removeWorldModel", RemoveWorldBuilding}, {"restoreAllWorldModels", RestoreWorldBuildings}, {"restoreWorldModel", RestoreWorldBuilding}, + {"setTimeFrozen", ArgumentParser}, + {"setVolumetricShadowsEnabled", ArgumentParser}, // World create funcs {"createSWATRope", CreateSWATRope}, @@ -122,13 +127,19 @@ void CLuaWorldDefs::LoadFunctions() {"resetSunSize", ResetSunSize}, {"resetMoonSize", ResetMoonSize}, {"resetBlurLevel", ResetBlurLevel}, - + {"resetWorldProperty", ArgumentParserWarn}, + {"resetTimeFrozen", ArgumentParser}, + {"resetVolumetricShadows", ArgumentParser}, + {"resetWorldProperties", ArgumentParser}, + // World check funcs {"areTrafficLightsLocked", AreTrafficLightsLocked}, {"isPedTargetingMarkerEnabled", IsPedTargetingMarkerEnabled}, {"isLineOfSightClear", IsLineOfSightClear}, {"isWorldSpecialPropertyEnabled", ArgumentParserWarn}, - {"isGarageOpen", IsGarageOpen}}; + {"isGarageOpen", IsGarageOpen}, + {"isTimeFrozen", ArgumentParser}, + {"isVolumetricShadowsEnabled", ArgumentParser}}; // Add functions for (const auto& [name, func] : functions) @@ -2060,3 +2071,210 @@ bool CLuaWorldDefs::ResetCoronaReflectionsEnabled() g_pGame->GetSettings()->ResetCoronaReflectionsEnabled(); return true; } + +std::variant> CLuaWorldDefs::GetWorldProperty(eWorldProperty property) +{ + switch (property) + { + case eWorldProperty::AMBIENT_COLOR: + { + float red, green, blue; + g_pMultiplayer->GetAmbientColor(red, green, blue); + return std::make_tuple((int16)(red * 255), (int16)(green * 255), (int16)(blue * 255)); + } + case eWorldProperty::AMBIENT_OBJ_COLOR: + { + float red, green, blue; + g_pMultiplayer->GetAmbientObjectColor(red, green, blue); + return std::make_tuple((int16)(red * 255), (int16)(green * 255), (int16)(blue * 255)); + } + case eWorldProperty::DIRECTIONAL_COLOR: + { + float red, green, blue; + g_pMultiplayer->GetDirectionalColor(red, green, blue); + return std::make_tuple((int16)(red * 255), (int16)(green * 255), (int16)(blue * 255)); + } + case eWorldProperty::SPRITE_SIZE: + return g_pMultiplayer->GetSpriteSize(); + case eWorldProperty::SPRITE_BRIGHTNESS: + return g_pMultiplayer->GetSpriteBrightness(); + case eWorldProperty::POLE_SHADOW_STRENGTH: + return (float)g_pMultiplayer->GetPoleShadowStrength(); + case eWorldProperty::SHADOW_STRENGTH: + return (float)g_pMultiplayer->GetShadowStrength(); + case eWorldProperty::SHADOWS_OFFSET: + return g_pMultiplayer->GetShadowsOffset(); + case eWorldProperty::LIGHTS_ON_GROUND: + return g_pMultiplayer->GetLightsOnGroundBrightness(); + case eWorldProperty::LOW_CLOUDS_COLOR: + { + int16 red, green, blue; + g_pMultiplayer->GetLowCloudsColor(red, green, blue); + return std::make_tuple(red, green, blue); + } + case eWorldProperty::BOTTOM_CLOUDS_COLOR: + { + int16 red, green, blue; + g_pMultiplayer->GetBottomCloudsColor(red, green, blue); + return std::make_tuple(red, green, blue); + } + case eWorldProperty::CLOUDS_ALPHA1: + return g_pMultiplayer->GetCloudsAlpha1(); + case eWorldProperty::ILLUMINATION: + return g_pMultiplayer->GetIllumination(); + case eWorldProperty::WEATHER_WET_ROADS: + return g_pGame->GetWeather()->GetWetRoads(); + case eWorldProperty::WEATHER_FOGGYNESS: + return g_pGame->GetWeather()->GetFoggyness(); + case eWorldProperty::WEATHER_FOG: + return g_pGame->GetWeather()->GetFog(); + case eWorldProperty::WEATHER_RAIN_FOG: + return g_pGame->GetWeather()->GetRainFog(); + case eWorldProperty::WEATHER_WATER_FOG: + return g_pGame->GetWeather()->GetWaterFog(); + case eWorldProperty::WEATHER_SANDSTORM: + return g_pGame->GetWeather()->GetSandstorm(); + case eWorldProperty::WEATHER_RAINBOW: + return g_pGame->GetWeather()->GetRainbow(); + } + return false; +} + +bool CLuaWorldDefs::SetWorldProperty(eWorldProperty property, float arg1, std::optional arg2, std::optional arg3) +{ + if (arg2.has_value() && arg3.has_value()) + { + switch (property) + { + case eWorldProperty::AMBIENT_COLOR: + return g_pMultiplayer->SetAmbientColor(arg1 / 255, arg2.value() / 255, arg3.value() / 255); + case eWorldProperty::AMBIENT_OBJ_COLOR: + return g_pMultiplayer->SetAmbientObjectColor(arg1 / 255, arg2.value() / 255, arg3.value() / 255); + case eWorldProperty::DIRECTIONAL_COLOR: + return g_pMultiplayer->SetDirectionalColor(arg1 / 255, arg2.value() / 255, arg3.value() / 255); + case eWorldProperty::LOW_CLOUDS_COLOR: + return g_pMultiplayer->SetLowCloudsColor((int16)arg1, (int16)arg2.value(), (int16)arg3.value()); + case eWorldProperty::BOTTOM_CLOUDS_COLOR: + return g_pMultiplayer->SetBottomCloudsColor((int16)arg1, (int16)arg2.value(), (int16)arg3.value()); + } + return false; + } + switch (property) + { + case eWorldProperty::SPRITE_SIZE: + return g_pMultiplayer->SetSpriteSize(arg1); + case eWorldProperty::SPRITE_BRIGHTNESS: + return g_pMultiplayer->SetSpriteBrightness(arg1); + case eWorldProperty::POLE_SHADOW_STRENGTH: + return g_pMultiplayer->SetPoleShadowStrength(arg1); + case eWorldProperty::SHADOW_STRENGTH: + return g_pMultiplayer->SetShadowStrength(arg1); + case eWorldProperty::SHADOWS_OFFSET: + return g_pMultiplayer->SetShadowsOffset(arg1); + case eWorldProperty::LIGHTS_ON_GROUND: + return g_pMultiplayer->SetLightsOnGroundBrightness(arg1); + case eWorldProperty::CLOUDS_ALPHA1: + return g_pMultiplayer->SetCloudsAlpha1(arg1); + case eWorldProperty::ILLUMINATION: + return g_pMultiplayer->SetIllumination(arg1); + case eWorldProperty::WEATHER_WET_ROADS: + return g_pGame->GetWeather()->SetWetRoads(arg1); + case eWorldProperty::WEATHER_FOGGYNESS: + return g_pGame->GetWeather()->SetFoggyness(arg1); + case eWorldProperty::WEATHER_FOG: + return g_pGame->GetWeather()->SetFog(arg1); + case eWorldProperty::WEATHER_RAIN_FOG: + return g_pGame->GetWeather()->SetRainFog(arg1); + case eWorldProperty::WEATHER_WATER_FOG: + return g_pGame->GetWeather()->SetWaterFog(arg1); + case eWorldProperty::WEATHER_SANDSTORM: + return g_pGame->GetWeather()->SetSandstorm(arg1); + case eWorldProperty::WEATHER_RAINBOW: + return g_pGame->GetWeather()->SetRainbow(arg1); + } + return false; +} + +bool CLuaWorldDefs::ResetWorldProperty(eWorldProperty property) +{ + switch (property) + { + case eWorldProperty::AMBIENT_COLOR: + return g_pMultiplayer->ResetAmbientColor(); + case eWorldProperty::AMBIENT_OBJ_COLOR: + return g_pMultiplayer->ResetAmbientObjectColor(); + case eWorldProperty::DIRECTIONAL_COLOR: + return g_pMultiplayer->ResetDirectionalColor(); + case eWorldProperty::SPRITE_SIZE: + return g_pMultiplayer->ResetSpriteSize(); + case eWorldProperty::SPRITE_BRIGHTNESS: + return g_pMultiplayer->ResetSpriteBrightness(); + case eWorldProperty::POLE_SHADOW_STRENGTH: + return g_pMultiplayer->ResetPoleShadowStrength(); + case eWorldProperty::SHADOW_STRENGTH: + return g_pMultiplayer->ResetShadowStrength(); + case eWorldProperty::SHADOWS_OFFSET: + return g_pMultiplayer->ResetShadowsOffset(); + case eWorldProperty::LIGHTS_ON_GROUND: + return g_pMultiplayer->ResetLightsOnGroundBrightness(); + case eWorldProperty::LOW_CLOUDS_COLOR: + return g_pMultiplayer->ResetLowCloudsColor(); + case eWorldProperty::BOTTOM_CLOUDS_COLOR: + return g_pMultiplayer->ResetBottomCloudsColor(); + case eWorldProperty::CLOUDS_ALPHA1: + return g_pMultiplayer->ResetCloudsAlpha1(); + case eWorldProperty::ILLUMINATION: + return g_pMultiplayer->ResetIllumination(); + case eWorldProperty::WEATHER_WET_ROADS: + return g_pGame->GetWeather()->ResetWetRoads(); + case eWorldProperty::WEATHER_FOGGYNESS: + return g_pGame->GetWeather()->ResetFoggyness(); + case eWorldProperty::WEATHER_FOG: + return g_pGame->GetWeather()->ResetFog(); + case eWorldProperty::WEATHER_RAIN_FOG: + return g_pGame->GetWeather()->ResetRainFog(); + case eWorldProperty::WEATHER_WATER_FOG: + return g_pGame->GetWeather()->ResetWaterFog(); + case eWorldProperty::WEATHER_SANDSTORM: + return g_pGame->GetWeather()->ResetSandstorm(); + case eWorldProperty::WEATHER_RAINBOW: + return g_pGame->GetWeather()->ResetRainbow(); + } + return false; +} + +bool CLuaWorldDefs::SetTimeFrozen(bool value) noexcept +{ + return g_pGame->GetClock()->SetTimeFrozen(value); +} + +bool CLuaWorldDefs::IsTimeFrozen() noexcept +{ + return g_pGame->GetClock()->IsTimeFrozen(); +} + +bool CLuaWorldDefs::ResetTimeFrozen() noexcept +{ + return g_pGame->GetClock()->ResetTimeFrozen(); +} + +bool CLuaWorldDefs::SetVolumetricShadowsEnabled(bool enable) noexcept +{ + g_pGame->GetSettings()->SetVolumetricShadowsEnabled(enable); + return true; +} + +bool CLuaWorldDefs::IsVolumetricShadowsEnabled() noexcept +{ + return g_pGame->GetSettings()->IsVolumetricShadowsEnabled(); +} + +bool CLuaWorldDefs::ResetVolumetricShadows() noexcept +{ + return g_pGame->GetSettings()->ResetVolumetricShadows(); +} + +void CLuaWorldDefs::ResetWorldProperties(std::optional resetSpecialWorldProperties, std::optional resetWorldProperties, std::optional resetWeatherProperties, std::optional resetLODs, std::optional resetSounds) noexcept +{ + g_pClientGame->ResetWorldProperties(ResetWorldPropsInfo{resetSpecialWorldProperties.value_or(true), resetWorldProperties.value_or(true), resetWeatherProperties.value_or(true), resetLODs.value_or(true), resetSounds.value_or(true)}); +} diff --git a/Client/mods/deathmatch/logic/luadefs/CLuaWorldDefs.h b/Client/mods/deathmatch/logic/luadefs/CLuaWorldDefs.h index bc90a4745e..ac38251dc7 100644 --- a/Client/mods/deathmatch/logic/luadefs/CLuaWorldDefs.h +++ b/Client/mods/deathmatch/logic/luadefs/CLuaWorldDefs.h @@ -126,4 +126,20 @@ class CLuaWorldDefs : public CLuaDefs static bool SetCoronaReflectionsEnabled(uchar ucEnabled); static uchar GetCoronaReflectionsEnabled(); static bool ResetCoronaReflectionsEnabled(); + + static std::variant> GetWorldProperty(eWorldProperty property); + static bool SetWorldProperty(eWorldProperty property, float arg1, std::optional arg2, std::optional arg3); + static bool ResetWorldProperty(eWorldProperty property); + + static bool SetTimeFrozen(bool value) noexcept; + static bool IsTimeFrozen() noexcept; + static bool ResetTimeFrozen() noexcept; + + static bool SetVolumetricShadowsEnabled(bool enable) noexcept; + static bool IsVolumetricShadowsEnabled() noexcept; + static bool ResetVolumetricShadows() noexcept; + + static void ResetWorldProperties(std::optional resetSpecialWorldProperties, std::optional resetWorldProperties, std::optional resetWeatherProperties, std::optional resetLODs, std::optional resetSounds) noexcept; + }; + diff --git a/Client/mods/deathmatch/logic/rpc/CElementRPCs.cpp b/Client/mods/deathmatch/logic/rpc/CElementRPCs.cpp index 1b5da5c780..31fa52cae2 100644 --- a/Client/mods/deathmatch/logic/rpc/CElementRPCs.cpp +++ b/Client/mods/deathmatch/logic/rpc/CElementRPCs.cpp @@ -64,22 +64,20 @@ void CElementRPCs::SetElementParent(CClientEntity* pSource, NetBitStreamInterfac { // Read out the entity id and parent id ElementID ParentID; - if (bitStream.Read(ParentID)) - { - CClientEntity* pParent = CElementIDs::GetElement(ParentID); - if (pParent) - { - pSource->SetParent(pParent); - } - else - { - // TODO: raise an error - } - } - else - { - // TODO: raise an error - } + if (!bitStream.Read(ParentID)) + return; + + CClientEntity* pParent = CElementIDs::GetElement(ParentID); + if (!pParent) + return; + + if (pParent->IsMyChild(pSource, true)) + return; + + if (pSource->IsMyChild(pParent, true)) + return; + + pSource->SetParent(pParent); } void CElementRPCs::SetElementData(CClientEntity* pSource, NetBitStreamInterface& bitStream) diff --git a/Client/mods/deathmatch/logic/rpc/CMarkerRPCs.cpp b/Client/mods/deathmatch/logic/rpc/CMarkerRPCs.cpp index 25fef9a579..ab7ca26af0 100644 --- a/Client/mods/deathmatch/logic/rpc/CMarkerRPCs.cpp +++ b/Client/mods/deathmatch/logic/rpc/CMarkerRPCs.cpp @@ -19,6 +19,7 @@ void CMarkerRPCs::LoadFunctions() AddHandler(SET_MARKER_SIZE, SetMarkerSize, "SetMarkerSize"); AddHandler(SET_MARKER_TARGET, SetMarkerTarget, "SetMarkerTarget"); AddHandler(SET_MARKER_ICON, SetMarkerIcon, "SetMarkerIcon"); + AddHandler(SET_MARKER_TARGET_ARROW_PROPERTIES, SetMarkerTargetArrowProperties, "SetMarkerTargetArrowProperties"); } void CMarkerRPCs::SetMarkerType(CClientEntity* pSource, NetBitStreamInterface& bitStream) @@ -137,4 +138,22 @@ void CMarkerRPCs::SetMarkerIcon(CClientEntity* pSource, NetBitStreamInterface& b } } } -} \ No newline at end of file +} + +void CMarkerRPCs::SetMarkerTargetArrowProperties(CClientEntity* pSource, NetBitStreamInterface& bitStream) +{ + SColor color; + float size; + if (bitStream.Read(color.R) && bitStream.Read(color.G) && bitStream.Read(color.B) && bitStream.Read(color.A) && bitStream.Read(size)) + { + CClientMarker* marker = m_pMarkerManager->Get(pSource->GetID()); + if (!marker) + return; + + CClientCheckpoint* checkpoint = marker->GetCheckpoint(); + if (!checkpoint) + return; + + checkpoint->SetTargetArrowProperties(color, size); + } +} diff --git a/Client/mods/deathmatch/logic/rpc/CMarkerRPCs.h b/Client/mods/deathmatch/logic/rpc/CMarkerRPCs.h index ae4f27c41c..20dcceff15 100644 --- a/Client/mods/deathmatch/logic/rpc/CMarkerRPCs.h +++ b/Client/mods/deathmatch/logic/rpc/CMarkerRPCs.h @@ -23,4 +23,5 @@ class CMarkerRPCs : public CRPCFunctions DECLARE_ELEMENT_RPC(SetMarkerSize); DECLARE_ELEMENT_RPC(SetMarkerTarget); DECLARE_ELEMENT_RPC(SetMarkerIcon); + DECLARE_ELEMENT_RPC(SetMarkerTargetArrowProperties); }; diff --git a/Client/mods/deathmatch/logic/rpc/CObjectRPCs.cpp b/Client/mods/deathmatch/logic/rpc/CObjectRPCs.cpp index 217cd9adcf..40984f5892 100644 --- a/Client/mods/deathmatch/logic/rpc/CObjectRPCs.cpp +++ b/Client/mods/deathmatch/logic/rpc/CObjectRPCs.cpp @@ -21,6 +21,9 @@ void CObjectRPCs::LoadFunctions() AddHandler(SET_OBJECT_SCALE, SetObjectScale, "SetObjectScale"); AddHandler(SET_OBJECT_VISIBLE_IN_ALL_DIMENSIONS, SetObjectVisibleInAllDimensions, "SetObjectVisibleInAllDimensions"); AddHandler(SET_OBJECT_BREAKABLE, SetObjectBreakable, "SetObjectBreakable"); + AddHandler(BREAK_OBJECT, BreakObject, "BreakObject"); + AddHandler(RESPAWN_OBJECT, RespawnObject, "RespawnObject"); + AddHandler(TOGGLE_OBJECT_RESPAWN, ToggleObjectRespawn, "ToggleObjectRespawn"); } void CObjectRPCs::DestroyAllObjects(NetBitStreamInterface& bitStream) @@ -126,3 +129,27 @@ void CObjectRPCs::SetObjectBreakable(CClientEntity* pSource, NetBitStreamInterfa pObject->SetBreakable(bitStream.ReadBit()); } } + +void CObjectRPCs::BreakObject(CClientEntity* pSource, NetBitStreamInterface& bitStream) +{ + auto* pObject = static_cast(m_pObjectManager->Get(pSource->GetID())); + + if (pObject) + pObject->Break(); +} + +void CObjectRPCs::RespawnObject(CClientEntity* pSource, NetBitStreamInterface& bitStream) +{ + auto* pObject = static_cast(m_pObjectManager->Get(pSource->GetID())); + + if (pObject) + g_pClientGame->GetObjectRespawner()->Respawn(pObject); +} + +void CObjectRPCs::ToggleObjectRespawn(CClientEntity* pSource, NetBitStreamInterface& bitStream) +{ + auto* pObject = static_cast(m_pObjectManager->Get(pSource->GetID())); + + if (pObject) + pObject->SetRespawnEnabled(bitStream.ReadBit()); +} diff --git a/Client/mods/deathmatch/logic/rpc/CObjectRPCs.h b/Client/mods/deathmatch/logic/rpc/CObjectRPCs.h index 26f2219d67..5a342b743b 100644 --- a/Client/mods/deathmatch/logic/rpc/CObjectRPCs.h +++ b/Client/mods/deathmatch/logic/rpc/CObjectRPCs.h @@ -26,4 +26,7 @@ class CObjectRPCs : public CRPCFunctions DECLARE_ELEMENT_RPC(SetObjectScale); DECLARE_ELEMENT_RPC(SetObjectVisibleInAllDimensions); DECLARE_ELEMENT_RPC(SetObjectBreakable); + DECLARE_ELEMENT_RPC(BreakObject); + DECLARE_ELEMENT_RPC(RespawnObject); + DECLARE_ELEMENT_RPC(ToggleObjectRespawn); }; diff --git a/Client/mods/deathmatch/logic/rpc/CPlayerRPCs.cpp b/Client/mods/deathmatch/logic/rpc/CPlayerRPCs.cpp index 6756bace22..e8cda43283 100644 --- a/Client/mods/deathmatch/logic/rpc/CPlayerRPCs.cpp +++ b/Client/mods/deathmatch/logic/rpc/CPlayerRPCs.cpp @@ -23,6 +23,7 @@ void CPlayerRPCs::LoadFunctions() AddHandler(SET_PLAYER_NAMETAG_SHOWING, SetPlayerNametagShowing, "SetPlayerNametagShowing"); AddHandler(SET_PLAYER_TEAM, SetPlayerTeam, "SetPlayerTeam"); AddHandler(TAKE_PLAYER_SCREEN_SHOT, TakePlayerScreenShot, "TakePlayerScreenShot"); + AddHandler(SET_PLAYER_SCRIPT_DEBUG_LEVEL, SetPlayerScriptDebugLevel, "SetPlayerScriptDebugLevel"); } void CPlayerRPCs::SetPlayerMoney(NetBitStreamInterface& bitStream) @@ -168,3 +169,18 @@ void CPlayerRPCs::TakePlayerScreenShot(NetBitStreamInterface& bitStream) m_pClientGame->TakePlayerScreenShot(usSizeX, usSizeY, strTag, ucQuality, uiMaxBandwidth, usMaxPacketSize, pResource, uiServerSentTime); } + +void CPlayerRPCs::SetPlayerScriptDebugLevel(NetBitStreamInterface& stream) +{ + CClientPlayer* localPlayer = g_pClientGame->GetPlayerManager()->GetLocalPlayer(); + + if (!localPlayer) + return; + + std::uint8_t scriptDebugLevel; + + if (!stream.Read(scriptDebugLevel)) + return; + + localPlayer->SetPlayerScriptDebugLevel(scriptDebugLevel); +} diff --git a/Client/mods/deathmatch/logic/rpc/CPlayerRPCs.h b/Client/mods/deathmatch/logic/rpc/CPlayerRPCs.h index ec60fd2c35..c9ab8c3e28 100644 --- a/Client/mods/deathmatch/logic/rpc/CPlayerRPCs.h +++ b/Client/mods/deathmatch/logic/rpc/CPlayerRPCs.h @@ -27,4 +27,5 @@ class CPlayerRPCs : public CRPCFunctions DECLARE_ELEMENT_RPC(SetPlayerNametagShowing); DECLARE_ELEMENT_RPC(SetPlayerTeam); DECLARE_RPC(TakePlayerScreenShot); + DECLARE_RPC(SetPlayerScriptDebugLevel); }; diff --git a/Client/mods/deathmatch/logic/rpc/CWorldRPCs.cpp b/Client/mods/deathmatch/logic/rpc/CWorldRPCs.cpp index 7b37f094df..d92ba4788b 100644 --- a/Client/mods/deathmatch/logic/rpc/CWorldRPCs.cpp +++ b/Client/mods/deathmatch/logic/rpc/CWorldRPCs.cpp @@ -17,6 +17,7 @@ #include #include #include +#include #include "CWorldRPCs.h" void CWorldRPCs::LoadFunctions() @@ -70,6 +71,8 @@ void CWorldRPCs::LoadFunctions() AddHandler(RESET_MOON_SIZE, ResetMoonSize, "ResetMoonSize"); AddHandler(SET_WORLD_SPECIAL_PROPERTY, SetWorldSpecialPropertyEnabled, "SetWorldSpecialPropertyEnabled"); + + AddHandler(RESET_WORLD_PROPERTIES, ResetWorldProperties, "ResetWorldProperties"); } void CWorldRPCs::SetTime(NetBitStreamInterface& bitStream) @@ -582,7 +585,7 @@ void CWorldRPCs::RemoveWorldModel(NetBitStreamInterface& bitStream) { bitStream.Read(cInterior); } - g_pGame->GetWorld()->RemoveBuilding(usModel, fRadius, fX, fY, fZ, cInterior); + g_pGame->GetBuildingRemoval()->RemoveBuilding(usModel, fRadius, fX, fY, fZ, cInterior); } } @@ -597,13 +600,13 @@ void CWorldRPCs::RestoreWorldModel(NetBitStreamInterface& bitStream) { bitStream.Read(cInterior); } - g_pGame->GetWorld()->RestoreBuilding(usModel, fRadius, fX, fY, fZ, cInterior); + g_pGame->GetBuildingRemoval()->RestoreBuilding(usModel, fRadius, fX, fY, fZ, cInterior); } } void CWorldRPCs::RestoreAllWorldModels(NetBitStreamInterface& bitStream) { - g_pGame->GetWorld()->ClearRemovedBuildingLists(); + g_pGame->GetBuildingRemoval()->ClearRemovedBuildingLists(); } void CWorldRPCs::SetSyncIntervals(NetBitStreamInterface& bitStream) @@ -642,3 +645,14 @@ void CWorldRPCs::SetWorldSpecialPropertyEnabled(NetBitStreamInterface& bitStream g_pClientGame->SetWorldSpecialProperty((WorldSpecialProperty)property, isEnabled); } } + +void CWorldRPCs::ResetWorldProperties(NetBitStreamInterface& bitStream) +{ + bool resetSpecialProperties = bitStream.ReadBit(); + bool resetWorldProperties = bitStream.ReadBit(); + bool resetWeatherProperties = bitStream.ReadBit(); + bool resetLODs = bitStream.ReadBit(); + bool resetSounds = bitStream.ReadBit(); + + g_pClientGame->ResetWorldProperties(ResetWorldPropsInfo{resetSpecialProperties, resetWorldProperties, resetWeatherProperties, resetLODs, resetSounds}); +} diff --git a/Client/mods/deathmatch/logic/rpc/CWorldRPCs.h b/Client/mods/deathmatch/logic/rpc/CWorldRPCs.h index 6572f82121..04c4ffa817 100644 --- a/Client/mods/deathmatch/logic/rpc/CWorldRPCs.h +++ b/Client/mods/deathmatch/logic/rpc/CWorldRPCs.h @@ -65,4 +65,5 @@ class CWorldRPCs : public CRPCFunctions DECLARE_RPC(ResetMoonSize); DECLARE_RPC(SetSyncIntervals); DECLARE_RPC(SetWorldSpecialPropertyEnabled); + DECLARE_RPC(ResetWorldProperties); }; diff --git a/Client/multiplayer_sa/CMultiplayerSA.cpp b/Client/multiplayer_sa/CMultiplayerSA.cpp index f3f2c63f41..28d5b1f551 100644 --- a/Client/multiplayer_sa/CMultiplayerSA.cpp +++ b/Client/multiplayer_sa/CMultiplayerSA.cpp @@ -1,16 +1,17 @@ /***************************************************************************** * - * PROJECT: Multi Theft Auto v1.0 + * PROJECT: Multi Theft Auto * LICENSE: See LICENSE in the top level directory - * FILE: multiplayer_sa/CMultiplayerSA.cpp + * FILE: Client/multiplayer_sa/CMultiplayerSA.cpp * PURPOSE: Multiplayer module class * - * Multi Theft Auto is available from http://www.multitheftauto.com/ + * Multi Theft Auto is available from https://multitheftauto.com/ * *****************************************************************************/ #include "StdInc.h" #include +#include #include #include #include @@ -189,14 +190,15 @@ DWORD RETURN_CHandlingData_isNotRWD = 0x6A0493; DWORD RETURN_CHandlingData_isNotFWD = 0x6A04C3; // end of handling fix #define CALL_CAutomobile_ProcessEntityCollision 0x6AD053 -#define CALL_CBike_ProcessEntityCollision1 0x6BDF82 -#define CALL_CBike_ProcessEntityCollision2 0x6BE0D1 #define CALL_CMonsterTruck_ProcessEntityCollision 0x6C8B9E DWORD RETURN_ProcessEntityCollision = 0x4185C0; #define HOOKPOS_PreFxRender 0x049E650 DWORD RETURN_PreFxRender = 0x0404D1E; +#define HOOKPOS_PostColorFilterRender 0x705099 +DWORD RETURN_PostColorFilterRender = 0x70509E; + #define HOOKPOS_PreHUDRender 0x053EAD8 DWORD RETURN_PreHUDRender = 0x053EADD; @@ -264,6 +266,13 @@ DWORD JMP_DynamicObject_Cond_Zero = 0x548E98; DWORD RETURN_CGlass_WindowRespondsToCollision = 0x71BC48; #define HOOKPOS_CGlass__BreakGlassPhysically 0x71D14B DWORD RETURN_CGlass__BreakGlassPhysically = 0x71D150; +#define HOOKPOS_CGlass_WindowRespondsToExplosion 0x71C255 +DWORD RETURN_CGlass_WindowRespondsToExplosion = 0x71C25A; +constexpr const DWORD CALL_FROM_CGlass_WindowRespondsToExplosion = 0x71C28E; +constexpr const DWORD CALL_FROM_CGlass_WasGlassHitByBullet = 0x71C192; +constexpr const DWORD CALL_FROM_CPhysical_ApplyCollision = 0x548F39; +constexpr const DWORD CALL_FROM_CPhysical_ApplyCollision_2 = 0x5490AE; +constexpr const DWORD CALL_FROM_CPhysical_ApplySoftCollision = 0x54A816; #define HOOKPOS_FxManager_c__DestroyFxSystem 0x4A989A @@ -306,7 +315,6 @@ bool bHideRadar; bool bHasProcessedScript; float fX, fY, fZ; DWORD RoadSignFixTemp; -DWORD dwEAEG = 0; bool m_bExplosionsDisabled; float fGlobalGravity = 0.008f; float fLocalPlayerGravity = 0.008f; @@ -324,6 +332,32 @@ BYTE ucSkyGradientTopB = 0; BYTE ucSkyGradientBottomR = 0; BYTE ucSkyGradientBottomG = 0; BYTE ucSkyGradientBottomB = 0; + +bool bUsingCustomAmbientColor = false; +float fAmbientColorR = 0.0F; +float fAmbientColorG = 0.0F; +float fAmbientColorB = 0.0F; + +bool bUsingCustomAmbientObjectColor = false; +float fAmbientObjectColorR = 0.0F; +float fAmbientObjectColorG = 0.0F; +float fAmbientObjectColorB = 0.0F; + +bool bUsingCustomDirectionalColor = false; +float fDirectionalColorR = 0.0F; +float fDirectionalColorG = 0.0F; +float fDirectionalColorB = 0.0F; + +bool bUsingCustomLowCloudsColor = false; +int16 iLowCloudsColorR = 0; +int16 iLowCloudsColorG = 0; +int16 iLowCloudsColorB = 0; + +bool bUsingCustomBottomCloudsColor = false; +int16 iBottomCloudsColorR = 0; +int16 iBottomCloudsColorG = 0; +int16 iBottomCloudsColorB = 0; + bool bUsingCustomWaterColor = false; float fWaterColorR = 0.0F; float fWaterColorG = 0.0F; @@ -376,6 +410,7 @@ PostWorldProcessHandler* m_pPostWorldProcessHandler = NULL; PostWorldProcessPedsAfterPreRenderHandler* m_postWorldProcessPedsAfterPreRenderHandler = nullptr; IdleHandler* m_pIdleHandler = NULL; PreFxRenderHandler* m_pPreFxRenderHandler = NULL; +PostColorFilterRenderHandler* m_pPostColorFilterRenderHandler = nullptr; PreHudRenderHandler* m_pPreHudRenderHandler = NULL; ProcessCollisionHandler* m_pProcessCollisionHandler = NULL; HeliKillHandler* m_pHeliKillHandler = NULL; @@ -478,6 +513,7 @@ void HOOK_Transmission_CalculateDriveAcceleration(); void HOOK_isVehDriveTypeNotRWD(); void HOOK_isVehDriveTypeNotFWD(); void HOOK_PreFxRender(); +void HOOK_PostColorFilterRender(); void HOOK_PreHUDRender(); void HOOK_CTrafficLights_GetPrimaryLightState(); @@ -561,7 +597,6 @@ CMultiplayerSA::CMultiplayerSA() MemSetFast(&localStatsData, 0, sizeof(CStatsData)); localStatsData.StatTypesFloat[24] = 569.0f; // Max Health - m_bSuspensionEnabled = true; m_fAircraftMaxHeight = 800.0f; @@ -656,6 +691,7 @@ void CMultiplayerSA::InitHooks() HookInstall(HOOKPOS_VehColCB, (DWORD)HOOK_VehColCB, 29); HookInstall(HOOKPOS_VehCol, (DWORD)HOOK_VehCol, 9); HookInstall(HOOKPOS_PreFxRender, (DWORD)HOOK_PreFxRender, 5); + HookInstall(HOOKPOS_PostColorFilterRender, (DWORD)HOOK_PostColorFilterRender, 5); HookInstall(HOOKPOS_PreHUDRender, (DWORD)HOOK_PreHUDRender, 5); HookInstall(HOOKPOS_CAutomobile__ProcessSwingingDoor, (DWORD)HOOK_CAutomobile__ProcessSwingingDoor, 7); @@ -714,7 +750,7 @@ void CMultiplayerSA::InitHooks() HookInstall(HOOKPOS_CObject_ProcessCollision, (DWORD)HOOK_CObject_ProcessCollision, 10); HookInstall(HOOKPOS_CGlass_WindowRespondsToCollision, (DWORD)HOOK_CGlass_WindowRespondsToCollision, 8); HookInstall(HOOKPOS_CGlass__BreakGlassPhysically, (DWORD)HOOK_CGlass__BreakGlassPhysically, 5); - + // Post-destruction hook for FxSystems HookInstall(HOOKPOS_FxManager_c__DestroyFxSystem, (DWORD)HOOK_FxManager_c__DestroyFxSystem, 5); @@ -1416,7 +1452,7 @@ void CMultiplayerSA::InitHooks() // Disable CStreaming::StreamVehiclesAndPeds_Always MemPut(0x40B650, 0xC3); - SetSuspensionEnabled(true); + UpdateVehicleSuspension(); // Aircraft Max Height checks are at 0x6D2614 and 0x6D2625 edit the check to use our own float. MemPut(0x6D2614, &m_fAircraftMaxHeight); @@ -1482,7 +1518,7 @@ void CMultiplayerSA::InitHooks() fDuckingHealthThreshold = 0; // Lower the GTA shadows offset closer to ground/floor level - m_fShadowsOffset = 0.013f; // GTA default = 0.06f + m_fShadowsOffset = DEFAULT_SHADOWS_OFFSET; for (auto uiAddr : shadowAddr) MemPut(uiAddr, &m_fShadowsOffset); @@ -1523,6 +1559,16 @@ void CMultiplayerSA::InitHooks() MemPut(0x524084, 0xFF); MemPut(0x524089, 0xFF); + // Allow change alpha for arrow & checkpoint markers (#1860) + MemSet((void*)0x7225F5, 0x90, 4); + MemCpy((void*)0x725DDE, "\xFF\x76\xB\x90\x90", 5); + + // Allow switch weapon during jetpack task (#3569) + MemSetFast((void*)0x60D86F, 0x90, 19); + + // Fix invisible vehicle windows when lights are on (#2936) + MemPut(0x6E1425, 1); + InitHooks_CrashFixHacks(); // Init our 1.3 hooks. @@ -2224,6 +2270,302 @@ void CMultiplayerSA::ResetWater() MemPut(0x7051D7, 184); } +void CMultiplayerSA::GetAmbientColor(float& red, float& green, float& blue) const +{ + if (bUsingCustomAmbientColor) + red = fAmbientColorR, green = fAmbientColorG, blue = fAmbientColorB; + else + red = *(float*)0xB7C4A0, green = *(float*)0xB7C4A4, blue = *(float*)0xB7C4A8; +} + +bool CMultiplayerSA::SetAmbientColor(float red, float green, float blue) +{ + bUsingCustomAmbientColor = true; + fAmbientColorR = red; + fAmbientColorG = green; + fAmbientColorB = blue; + return true; +} + +bool CMultiplayerSA::ResetAmbientColor() +{ + bUsingCustomAmbientColor = false; + return true; +} + +void CMultiplayerSA::GetAmbientObjectColor(float& red, float& green, float& blue) const +{ + if (bUsingCustomAmbientObjectColor) + red = fAmbientObjectColorR, green = fAmbientObjectColorG, blue = fAmbientObjectColorB; + else + red = *(float*)0xB7C4AC, green = *(float*)0xB7C4B0, blue = *(float*)0xB7C4B4; +} + +bool CMultiplayerSA::SetAmbientObjectColor(float red, float green, float blue) +{ + bUsingCustomAmbientObjectColor = true; + fAmbientObjectColorR = red; + fAmbientObjectColorG = green; + fAmbientObjectColorB = blue; + return true; +} + +bool CMultiplayerSA::ResetAmbientObjectColor() +{ + bUsingCustomAmbientObjectColor = false; + return true; +} + +void CMultiplayerSA::GetDirectionalColor(float& red, float& green, float& blue) const +{ + if (bUsingCustomDirectionalColor) + red = fDirectionalColorR, green = fDirectionalColorG, blue = fDirectionalColorB; + else + red = *(float*)0xB7C4B8, green = *(float*)0xB7C4BC, blue = *(float*)0xB7C4C0; +} + +bool CMultiplayerSA::SetDirectionalColor(float red, float green, float blue) +{ + bUsingCustomDirectionalColor = true; + fDirectionalColorR = red; + fDirectionalColorG = green; + fDirectionalColorB = blue; + return true; +} + +bool CMultiplayerSA::ResetDirectionalColor() +{ + bUsingCustomDirectionalColor = false; + return true; +} + +float CMultiplayerSA::GetSpriteSize() const +{ + return *(float*)0xB7C4E0; +} + +bool CMultiplayerSA::SetSpriteSize(float size) +{ + MemPut(0x55FC21, 0xDD); + MemPut(0x55FC22, 0xD8); + MemPut(0x55FC23, 0x90); + + MemPutFast(0xB7C4E0, size); + return true; +} + +bool CMultiplayerSA::ResetSpriteSize() +{ + MemPut(0x55FC21, 0xD9); + MemPut(0x55FC22, 0x5E); + MemPut(0x55FC23, 0x40); + return true; +} + +float CMultiplayerSA::GetSpriteBrightness() const +{ + return *(float*)0xB7C4E4; +} + +bool CMultiplayerSA::SetSpriteBrightness(float brightness) +{ + MemPut(0x55FC34, 0xDD); + MemPut(0x55FC35, 0xD8); + MemPut(0x55FC36, 0x90); + + MemPutFast(0xB7C4E4, brightness); + return true; +} + +bool CMultiplayerSA::ResetSpriteBrightness() +{ + MemPut(0x55FC34, 0xD9); + MemPut(0x55FC35, 0x5E); + MemPut(0x55FC36, 0x44); + return true; +} + +int16 CMultiplayerSA::GetPoleShadowStrength() const +{ + return *(int16*)0xB7C4EC; +} + +bool CMultiplayerSA::SetPoleShadowStrength(int16 strength) +{ + MemSet((LPVOID)0x55FCB8, 0x90, 4); + MemSet((LPVOID)(0x56023A + 2), 0x90, 3); + MemSet((LPVOID)(0x5602A6 + 2), 0x90, 3); + + MemPutFast(0xB7C4EC, strength); + return true; +} + +bool CMultiplayerSA::ResetPoleShadowStrength() +{ + BYTE originalMov[4] = {0x66, 0x89, 0x46, 0x4C}; + MemCpy((LPVOID)0x55FCB8, &originalMov, 4); + + BYTE originalCodes[3] = {0xEC, 0xC4, 0xB7}; + MemCpy((LPVOID)(0x56023A + 2), &originalCodes, 3); + MemCpy((LPVOID)(0x5602A6 + 2), &originalCodes, 3); + return true; +} + +int16 CMultiplayerSA::GetShadowStrength() const +{ + return *(int16*)0xB7C4E8; +} + +bool CMultiplayerSA::SetShadowStrength(int16 strength) +{ + MemSet((LPVOID)0x55FC5E, 0x90, 4); + MemSet((LPVOID)(0x56022E + 2), 0x90, 3); + MemSet((LPVOID)(0x560234 + 2), 0x90, 3); + MemSet((LPVOID)(0x56029A + 2), 0x90, 3); + MemSet((LPVOID)(0x5602A0 + 2), 0x90, 3); + + MemPutFast(0xB7C4E8, strength); + return true; +} + +bool CMultiplayerSA::ResetShadowStrength() +{ + BYTE originalMov[4] = {0x66, 0x89, 0x46, 0x48}; + MemCpy((LPVOID)0x55FC5E, &originalMov, 4); + + BYTE originalCodes[3] = {0xE8, 0xC4, 0xB7}; + MemCpy((LPVOID)(0x56022E + 2), &originalCodes, 3); + MemCpy((LPVOID)(0x560234 + 2), &originalCodes, 3); + MemCpy((LPVOID)(0x56029A + 2), &originalCodes, 3); + MemCpy((LPVOID)(0x5602A0 + 2), &originalCodes, 3); + return true; +} + +float CMultiplayerSA::GetShadowsOffset() const +{ + return m_fShadowsOffset; +} + +bool CMultiplayerSA::SetShadowsOffset(float offset) +{ + m_fShadowsOffset = offset; + return true; +} + +bool CMultiplayerSA::ResetShadowsOffset() +{ + m_fShadowsOffset = DEFAULT_SHADOWS_OFFSET; + return true; +} + +float CMultiplayerSA::GetLightsOnGroundBrightness() const +{ + return *(float*)0xB7C4F8; +} + +bool CMultiplayerSA::SetLightsOnGroundBrightness(float brightness) +{ + MemPut(0x55FDBC, 0xDD); + MemPut(0x55FDBD, 0xD8); + MemPut(0x55FDBE, 0x90); + MemSet((LPVOID)(0x5602AC + 2), 0x90, 3); + + MemPutFast(0xB7C4F8, brightness); + return true; +} + +bool CMultiplayerSA::ResetLightsOnGroundBrightness() +{ + BYTE originalFstp[3] = {0xD9, 0x5E, 0x58}; + MemCpy((LPVOID)0x55FDBC, &originalFstp, 3); + + BYTE originalCodes[3] = {0xF8, 0xC4, 0xB7}; + MemCpy((LPVOID)(0x5602AC + 2), &originalCodes, 3); + return true; +} + +void CMultiplayerSA::GetLowCloudsColor(int16& red, int16& green, int16& blue) const +{ + if (bUsingCustomLowCloudsColor) + red = iLowCloudsColorR, green = iLowCloudsColorG, blue = iLowCloudsColorB; + else + red = *(int16*)0xB7C4FC, green = *(int16*)0xB7C4FE, blue = *(int16*)0xB7C500; +} + +bool CMultiplayerSA::SetLowCloudsColor(int16 red, int16 green, int16 blue) +{ + bUsingCustomLowCloudsColor = true; + iLowCloudsColorR = red; + iLowCloudsColorG = green; + iLowCloudsColorB = blue; + return true; +} + +bool CMultiplayerSA::ResetLowCloudsColor() +{ + bUsingCustomLowCloudsColor = false; + return true; +} + +void CMultiplayerSA::GetBottomCloudsColor(int16& red, int16& green, int16& blue) const +{ + if (bUsingCustomBottomCloudsColor) + red = iBottomCloudsColorR, green = iBottomCloudsColorG, blue = iBottomCloudsColorB; + else + red = *(int16*)0xB7C502, green = *(int16*)0xB7C504, blue = *(int16*)0xB7C506; +} + +bool CMultiplayerSA::SetBottomCloudsColor(int16 red, int16 green, int16 blue) +{ + bUsingCustomBottomCloudsColor = true; + iBottomCloudsColorR = red; + iBottomCloudsColorG = green; + iBottomCloudsColorB = blue; + return true; +} + +bool CMultiplayerSA::ResetBottomCloudsColor() +{ + bUsingCustomBottomCloudsColor = false; + return true; +} + +float CMultiplayerSA::GetCloudsAlpha1() const +{ + return *(float*)0xB7C538; +} + +bool CMultiplayerSA::SetCloudsAlpha1(float alpha) +{ + MemPut(0x55FDD5, 0xD8); + MemPutFast(0xB7C538, alpha); + return true; +} + +bool CMultiplayerSA::ResetCloudsAlpha1() +{ + MemPut(0x55FDD5, 0xD9); + return true; +} + +float CMultiplayerSA::GetIllumination() const +{ + return *(float*)0xB7C544; +} + +bool CMultiplayerSA::SetIllumination(float illumination) +{ + MemPut(0x55FE46, 0xD8); + MemPutFast(0xB7C544, illumination); + return true; +} + +bool CMultiplayerSA::ResetIllumination() +{ + MemPut(0x55FE46, 0xD9); + return true; +} + bool CMultiplayerSA::GetExplosionsDisabled() { return m_bExplosionsDisabled; @@ -2314,6 +2656,11 @@ void CMultiplayerSA::SetPreFxRenderHandler(PreFxRenderHandler* pHandler) m_pPreFxRenderHandler = pHandler; } +void CMultiplayerSA::SetPostColorFilterRenderHandler(PostColorFilterRenderHandler* pHandler) +{ + m_pPostColorFilterRenderHandler = pHandler; +} + void CMultiplayerSA::SetPreHudRenderHandler(PreHudRenderHandler* pHandler) { m_pPreHudRenderHandler = pHandler; @@ -3393,31 +3740,6 @@ static void RestoreAlphaValues() /** ** Vehicles **/ -static RpAtomic* CVehicle_EAEG(RpAtomic* pAtomic, void*) -{ - RwFrame* pFrame = ((RwFrame*)(((RwObject*)(pAtomic))->parent)); - if (pFrame) - { - switch (pFrame->szName[0]) - { - case '\0': - case 'h': - break; - default: - DWORD dwFunc = (DWORD)0x533290; - DWORD dwAtomic = (DWORD)pAtomic; - _asm - { - push 0 - push dwAtomic - call dwFunc - add esp, 0x8 - } - } - } - - return pAtomic; -} static void SetVehicleAlpha() { @@ -3426,15 +3748,6 @@ static void SetVehicleAlpha() if (ucAlpha < 255) GetAlphaAndSetNewValues(ucAlpha); - else if (dwEAEG && pInterface->m_pVehicle->GetModelIndex() == 0x20A) - { - bEntityHasAlpha = true; - uiAlphaIdx = 0; - SetEntityAlphaHooked(dwAlphaEntity, (DWORD)HOOK_GetAlphaValues, 0); - MemPutFast(0x5332D6, (DWORD)CVehicle_EAEG); - SetEntityAlphaHooked(dwAlphaEntity, (DWORD)HOOK_SetAlphaValues, 0); - MemPutFast(0x5332D6, 0x533290); - } else bEntityHasAlpha = false; } @@ -3586,6 +3899,36 @@ void _cdecl DoEndWorldColorsPokes() MemPutFast(0xB7C4CC, ucSkyGradientBottomG); MemPutFast(0xB7C4CE, ucSkyGradientBottomB); } + if (bUsingCustomAmbientColor) + { + MemPutFast(0xB7C4A0, fAmbientColorR); + MemPutFast(0xB7C4A4, fAmbientColorG); + MemPutFast(0xB7C4A8, fAmbientColorB); + } + if (bUsingCustomAmbientObjectColor) + { + MemPutFast(0xB7C4AC, fAmbientObjectColorR); + MemPutFast(0xB7C4B0, fAmbientObjectColorG); + MemPutFast(0xB7C4B4, fAmbientObjectColorB); + } + if (bUsingCustomDirectionalColor) + { + MemPutFast(0xB7C4B8, fDirectionalColorR); + MemPutFast(0xB7C4BC, fDirectionalColorG); + MemPutFast(0xB7C4C0, fDirectionalColorB); + } + if (bUsingCustomLowCloudsColor) + { + MemPutFast(0xB7C4FC, iLowCloudsColorR); + MemPutFast(0xB7C4FE, iLowCloudsColorG); + MemPutFast(0xB7C500, iLowCloudsColorB); + } + if (bUsingCustomBottomCloudsColor) + { + MemPutFast(0xB7C502, iBottomCloudsColorR); + MemPutFast(0xB7C504, iBottomCloudsColorG); + MemPutFast(0xB7C506, iBottomCloudsColorB); + } if (bUsingCustomWaterColor) { MemPutFast(0xB7C508, fWaterColorR); @@ -3946,8 +4289,6 @@ void CMultiplayerSA::SetLocalStatValue(unsigned short usStat, float fValue) localStatsData.StatTypesFloat[usStat] = fValue; else if (usStat >= STATS_OFFSET && usStat < MAX_INT_FLOAT_STATS) localStatsData.StatTypesInt[usStat - STATS_OFFSET] = (int)fValue; - else if (usStat == 0x2329) - dwEAEG = !dwEAEG; } float CMultiplayerSA::GetLocalStatValue(unsigned short usStat) @@ -4779,6 +5120,24 @@ void _declspec(naked) HOOK_PreFxRender() } } +// Hooked from 00705099 5 bytes +void _declspec(naked) HOOK_PostColorFilterRender() +{ + _asm + { + pushad + } + + if (m_pPostColorFilterRenderHandler) m_pPostColorFilterRenderHandler(); + + _asm + { + popad + mov al, ds:0C402BAh + jmp RETURN_PostColorFilterRender // 0070509E + } +} + // Hooked from 0053EAD8 5 bytes void _declspec(naked) HOOK_PreHUDRender() { @@ -5754,7 +6113,7 @@ bool CheckHasSuspensionChanged() CModelInfo* pModelInfo = pGameInterface->GetModelInfo(pVehicle->GetModelIndex()); if (pModelInfo && (pModelInfo->IsCar() || pModelInfo->IsMonsterTruck())) - return pVehicle->GetHandlingData()->HasSuspensionChanged(); + return true; else return false; } @@ -5819,26 +6178,10 @@ void _declspec(naked) HOOK_ProcessVehicleCollision() } } -void CMultiplayerSA::SetSuspensionEnabled(bool bEnabled) +void CMultiplayerSA::UpdateVehicleSuspension() noexcept { - // if ( bEnabled ) - { - // Hook Install - m_bSuspensionEnabled = true; - HookInstallCall(CALL_CAutomobile_ProcessEntityCollision, (DWORD)HOOK_ProcessVehicleCollision); - // HookInstallCall ( CALL_CBike_ProcessEntityCollision1, (DWORD)HOOK_ProcessVehicleCollision ); - // HookInstallCall ( CALL_CBike_ProcessEntityCollision2, (DWORD)HOOK_ProcessVehicleCollision ); - HookInstallCall(CALL_CMonsterTruck_ProcessEntityCollision, (DWORD)HOOK_ProcessVehicleCollision); - } - // else - // { - // // Hook Uninstall - // m_bSuspensionEnabled = false; - // HookInstallCall ( CALL_CAutomobile_ProcessEntityCollision, RETURN_ProcessEntityCollision ); - // HookInstallCall ( CALL_CBike_ProcessEntityCollision1, RETURN_ProcessEntityCollision ); - // HookInstallCall ( CALL_CBike_ProcessEntityCollision2, RETURN_ProcessEntityCollision ); - // HookInstallCall ( CALL_CMonsterTruck_ProcessEntityCollision, RETURN_ProcessEntityCollision ); - // } + HookInstallCall(CALL_CAutomobile_ProcessEntityCollision, reinterpret_cast(HOOK_ProcessVehicleCollision)); + HookInstallCall(CALL_CMonsterTruck_ProcessEntityCollision, reinterpret_cast(HOOK_ProcessVehicleCollision)); } // Variables @@ -5853,15 +6196,15 @@ bool CheckRemovedModelNoSet() bNextHookSetModel = false; bCodePathCheck = bNextHookSetModel; pLODInterface = NULL; - CWorld* pWorld = pGameInterface->GetWorld(); + CBuildingRemoval* pBuildingRemoval = pGameInterface->GetBuildingRemoval(); // You never know. - if (pWorld) + if (pBuildingRemoval) { // Is the model in question even removed? - if (pWorld->IsModelRemoved(pEntityWorldAdd->m_nModelIndex)) + if (pBuildingRemoval->IsModelRemoved(pEntityWorldAdd->m_nModelIndex)) { // is the replaced model in the spherical radius of any building removal - if (pGameInterface->GetWorld()->IsRemovedModelInRadius(pEntityWorldAdd)) + if (pGameInterface->GetBuildingRemoval()->IsRemovedModelInRadius(pEntityWorldAdd)) { // if it is next hook remove it from the world return true; @@ -5912,7 +6255,7 @@ void HideEntitySomehow() // Init pInterface with the Initial model CEntitySAInterface* pInterface = pLODInterface; // Grab the removal for the interface - SBuildingRemoval* pBuildingRemoval = pGameInterface->GetWorld()->GetBuildingRemoval(pInterface); + SBuildingRemoval* pBuildingRemoval = pGameInterface->GetBuildingRemoval()->GetBuildingRemoval(pInterface); // Remove down the LOD tree if (pBuildingRemoval && pInterface && pInterface != NULL && pInterface->bIsProcObject == 0 && (pInterface->nType == ENTITY_TYPE_BUILDING || pInterface->nType == ENTITY_TYPE_DUMMY)) @@ -5932,7 +6275,7 @@ void HideEntitySomehow() if (pInterface && pInterface != NULL && pInterface->bIsProcObject == 0 && (pInterface->nType == ENTITY_TYPE_BUILDING || pInterface->nType == ENTITY_TYPE_DUMMY)) { - pGameInterface->GetWorld()->AddBinaryBuilding(pInterface); + pGameInterface->GetBuildingRemoval()->AddBinaryBuilding(pInterface); } } // Reset our next hook variable @@ -5962,7 +6305,7 @@ void StorePointerToBuilding() { if (pBuildingAdd != NULL) { - pGameInterface->GetWorld()->AddDataBuilding(pBuildingAdd); + pGameInterface->GetBuildingRemoval()->AddDataBuilding(pBuildingAdd); } } @@ -5991,7 +6334,7 @@ bool CheckForRemoval() // Init pInterface with the Initial model CEntitySAInterface* pInterface = pLODInterface; // Remove down the LOD tree - if (pGameInterface->GetWorld()->IsObjectRemoved(pInterface)) + if (pGameInterface->GetBuildingRemoval()->IsObjectRemoved(pInterface)) { return true; } @@ -6020,7 +6363,7 @@ void _declspec(naked) Hook_CWorld_ADD_CPopulation_ConvertToRealObject() void RemoveObjectIfNeeded() { TIMING_CHECKPOINT("+RemoveObjectIfNeeded"); - SBuildingRemoval* pBuildingRemoval = pGameInterface->GetWorld()->GetBuildingRemoval(pLODInterface); + SBuildingRemoval* pBuildingRemoval = pGameInterface->GetBuildingRemoval()->GetBuildingRemoval(pLODInterface); if (pBuildingRemoval != NULL) { if ((DWORD)(pBuildingAdd->vtbl) != VTBL_CPlaceable) @@ -6069,7 +6412,7 @@ void RemovePointerToBuilding() { if (pBuildingRemove->nType == ENTITY_TYPE_BUILDING || pBuildingRemove->nType == ENTITY_TYPE_DUMMY || pBuildingRemove->nType == ENTITY_TYPE_OBJECT) { - pGameInterface->GetWorld()->RemoveWorldBuildingFromLists(pBuildingRemove); + pGameInterface->GetBuildingRemoval()->RemoveWorldBuildingFromLists(pBuildingRemove); } } @@ -6099,7 +6442,7 @@ void _declspec(naked) HOOK_CWorld_Remove_CPopulation_ConvertToDummyObject() // if it's replaced get rid of it void RemoveDummyIfReplaced() { - SBuildingRemoval* pBuildingRemoval = pGameInterface->GetWorld()->GetBuildingRemoval(pLODInterface); + SBuildingRemoval* pBuildingRemoval = pGameInterface->GetBuildingRemoval()->GetBuildingRemoval(pLODInterface); if (pBuildingRemoval != NULL) { if ((DWORD)(pBuildingAdd->vtbl) != VTBL_CPlaceable) @@ -6452,22 +6795,73 @@ void _declspec(naked) HOOK_CObject_ProcessCollision() } } +DWORD WindowRespondsToCollision_CalledFrom = 0; void _declspec(naked) HOOK_CGlass_WindowRespondsToCollision() { _asm { - pushad - mov ecx, [esp+4] - mov pDamagedObject, ecx + push eax + mov eax, [esp + 4] + mov WindowRespondsToCollision_CalledFrom, eax + pop eax } - pObjectAttacker = NULL; - if (TriggerObjectBreakEvent()) + pObjectAttacker = nullptr; + + if (WindowRespondsToCollision_CalledFrom != CALL_FROM_CGlass_WindowRespondsToExplosion) { _asm { - popad + mov pDamagedObject, esi + } + } + // Get attacker for the glass break + if (WindowRespondsToCollision_CalledFrom == CALL_FROM_CPhysical_ApplyCollision || + WindowRespondsToCollision_CalledFrom == CALL_FROM_CPhysical_ApplyCollision_2 || + WindowRespondsToCollision_CalledFrom == CALL_FROM_CPhysical_ApplySoftCollision) + { + _asm + { + mov pObjectAttacker, edi + } + } + + if (WindowRespondsToCollision_CalledFrom == CALL_FROM_CGlass_WasGlassHitByBullet) + { + _asm + { + mov pObjectAttacker, ebx // WasGlassHitByBullet called from CWeapon::DoBulletImpact + } + + if (!pObjectAttacker || (pObjectAttacker && !pObjectAttacker->m_pRwObject)) // WasGlassHitByBullet called from CBulletInfo::Update + { + _asm + { + push ecx + mov ecx, [edi] + mov pObjectAttacker, ecx + pop ecx + } + } + } + + if (WindowRespondsToCollision_CalledFrom == CALL_FROM_CGlass_WindowRespondsToExplosion) + { + _asm + { + mov pDamagedObject, edx + mov pObjectAttacker, ebp + } + } + + if (pObjectAttacker && !pObjectAttacker->m_pRwObject) // Still wrong? + pObjectAttacker = nullptr; + + if (TriggerObjectBreakEvent()) + { + _asm + { sub esp, 68h push esi mov esi, [esp+6Ch+4] @@ -6478,7 +6872,6 @@ void _declspec(naked) HOOK_CGlass_WindowRespondsToCollision() { _asm { - popad retn } } @@ -6491,9 +6884,11 @@ void _declspec(naked) HOOK_CGlass__BreakGlassPhysically() _asm { mov pDamagedObject, esi + push ecx + mov ecx, [esp+4] + mov pObjectAttacker, ecx + pop ecx } - // we can't get attacker from here - pObjectAttacker = NULL; if (TriggerObjectBreakEvent()) { diff --git a/Client/multiplayer_sa/CMultiplayerSA.h b/Client/multiplayer_sa/CMultiplayerSA.h index fd81a18828..802b9b56ea 100644 --- a/Client/multiplayer_sa/CMultiplayerSA.h +++ b/Client/multiplayer_sa/CMultiplayerSA.h @@ -20,6 +20,7 @@ class CRemoteDataSA; #define DEFAULT_NEAR_CLIP_DISTANCE ( 0.3f ) +#define DEFAULT_SHADOWS_OFFSET ( 0.013f ) // GTA default = 0.06f enum eRadioStationID { @@ -115,6 +116,7 @@ class CMultiplayerSA : public CMultiplayer void SetPostWorldProcessPedsAfterPreRenderHandler(PostWorldProcessPedsAfterPreRenderHandler* pHandler); void SetIdleHandler(IdleHandler* pHandler); void SetPreFxRenderHandler(PreFxRenderHandler* pHandler); + void SetPostColorFilterRenderHandler(PostColorFilterRenderHandler* pHandler) override; void SetPreHudRenderHandler(PreHudRenderHandler* pHandler); void DisableCallsToCAnimBlendNode(bool bDisableCalls); void SetCAnimBlendAssocDestructorHandler(CAnimBlendAssocDestructorHandler* pHandler); @@ -195,6 +197,58 @@ class CMultiplayerSA : public CMultiplayer int GetMoonSize(); void ResetMoonSize(); + void GetAmbientColor(float& red, float& green, float& blue) const; + bool SetAmbientColor(float red, float green, float blue); + bool ResetAmbientColor(); + + void GetAmbientObjectColor(float& red, float& green, float& blue) const; + bool SetAmbientObjectColor(float red, float green, float blue); + bool ResetAmbientObjectColor(); + + void GetDirectionalColor(float& red, float& green, float& blue) const; + bool SetDirectionalColor(float red, float green, float blue); + bool ResetDirectionalColor(); + + float GetSpriteSize() const; + bool SetSpriteSize(float size); + bool ResetSpriteSize(); + + float GetSpriteBrightness() const; + bool SetSpriteBrightness(float brightness); + bool ResetSpriteBrightness(); + + int16 GetPoleShadowStrength() const; + bool SetPoleShadowStrength(int16 strength); + bool ResetPoleShadowStrength(); + + int16 GetShadowStrength() const; + bool SetShadowStrength(int16 strength); + bool ResetShadowStrength(); + + float GetShadowsOffset() const; + bool SetShadowsOffset(float offset); + bool ResetShadowsOffset(); + + float GetLightsOnGroundBrightness() const; + bool SetLightsOnGroundBrightness(float brightness); + bool ResetLightsOnGroundBrightness(); + + void GetLowCloudsColor(int16& red, int16& green, int16& blue) const; + bool SetLowCloudsColor(int16 red, int16 green, int16 blue); + bool ResetLowCloudsColor(); + + void GetBottomCloudsColor(int16& red, int16& green, int16& blue) const; + bool SetBottomCloudsColor(int16 red, int16 green, int16 blue); + bool ResetBottomCloudsColor(); + + float GetCloudsAlpha1() const; + bool SetCloudsAlpha1(float alpha); + bool ResetCloudsAlpha1(); + + float GetIllumination() const; + bool SetIllumination(float illumination); + bool ResetIllumination(); + void SetNightVisionEnabled(bool bEnabled, bool bNoiseEnabled); void SetThermalVisionEnabled(bool bEnabled, bool bNoiseEnabled); bool IsNightVisionEnabled(); @@ -214,6 +268,7 @@ class CMultiplayerSA : public CMultiplayer void SetRender3DStuffHandler(Render3DStuffHandler* pHandler); void SetPreRenderSkyHandler(PreRenderSkyHandler* pHandler); void SetRenderHeliLightHandler(RenderHeliLightHandler* pHandler); + void SetRenderEverythingBarRoadsHandler(RenderEverythingBarRoadsHandler* pHandler) override; void Reset(); @@ -256,8 +311,7 @@ class CMultiplayerSA : public CMultiplayer CLimits* GetLimits() { return &m_limits; } - void SetSuspensionEnabled(bool bEnabled); - bool IsSuspensionEnabled() { return m_bSuspensionEnabled; }; + void UpdateVehicleSuspension() noexcept; virtual void FlushClothesCache(); virtual void SetFastClothesLoading(EFastClothesLoading fastClothesLoading); @@ -308,7 +362,6 @@ class CMultiplayerSA : public CMultiplayer bool m_bBadDrivebyHitboxesDisabled; private: - bool m_bSuspensionEnabled; std::vector m_PlayerImgCache; EFastClothesLoading m_FastClothesLoading; CLimitsSA m_limits; diff --git a/Client/multiplayer_sa/CMultiplayerSA_1.3.cpp b/Client/multiplayer_sa/CMultiplayerSA_1.3.cpp index afea015991..fd47e12ba8 100644 --- a/Client/multiplayer_sa/CMultiplayerSA_1.3.cpp +++ b/Client/multiplayer_sa/CMultiplayerSA_1.3.cpp @@ -111,6 +111,9 @@ DWORD RETURN_CProjectile_FixTearGasCrash_Cont = 0x4C0409; #define HOOKPOS_CProjectile_FixExplosionLocation 0x738A77 DWORD RETURN_CProjectile_FixExplosionLocation = 0x738A86; +#define HOOKPOS_CPed_RemoveWeaponWhenEnteringVehicle 0x5E6370 +DWORD RETURN_CPed_RemoveWeaponWhenEnteringVehicle = 0x5E6379; + void HOOK_CVehicle_ProcessStuff_TestSirenTypeSingle(); void HOOK_CVehicle_ProcessStuff_PostPushSirenPositionSingle(); void HOOK_CVehicle_ProcessStuff_TestSirenTypeDual(); @@ -137,6 +140,7 @@ void HOOK_CVehicleModelInterface_SetClump(); void HOOK_CBoat_ApplyDamage(); void HOOK_CProjectile_FixTearGasCrash(); void HOOK_CProjectile_FixExplosionLocation(); +void HOOK_CPed_RemoveWeaponWhenEnteringVehicle(); void CMultiplayerSA::Init_13() { @@ -192,6 +196,9 @@ void CMultiplayerSA::InitHooks_13() HookInstall(HOOKPOS_CProjectile_FixExplosionLocation, (DWORD)HOOK_CProjectile_FixExplosionLocation, 12); + // Fix invisible weapons during jetpack task + HookInstall(HOOKPOS_CPed_RemoveWeaponWhenEnteringVehicle, (DWORD)HOOK_CPed_RemoveWeaponWhenEnteringVehicle, 9); + InitHooks_ClothesSpeedUp(); EnableHooks_ClothesMemFix(true); InitHooks_FixBadAnimId(); @@ -1668,3 +1675,42 @@ void _declspec(naked) HOOK_CProjectile_FixExplosionLocation() jmp RETURN_CProjectile_FixExplosionLocation } } + +DWORD CPed_RemoveWeaponWhenEnteringVehicle_CalledFrom = 0; +void _declspec(naked) HOOK_CPed_RemoveWeaponWhenEnteringVehicle() +{ + _asm + { + push eax + mov eax, [esp+4] + mov CPed_RemoveWeaponWhenEnteringVehicle_CalledFrom, eax + pop eax + + push esi + mov esi, ecx + mov eax, [esi+480h] + } + + // Called from CTaskSimpleJetPack::ProcessPed + if (CPed_RemoveWeaponWhenEnteringVehicle_CalledFrom == 0x68025F) + { + _asm + { + mov pPedUsingJetpack, esi + } + + if (AllowJetPack()) + { + _asm + { + pop esi + retn 4 + } + } + } + + _asm + { + jmp RETURN_CPed_RemoveWeaponWhenEnteringVehicle + } +} diff --git a/Client/multiplayer_sa/CMultiplayerSA_ClothesCache.cpp b/Client/multiplayer_sa/CMultiplayerSA_ClothesCache.cpp index d09679d6b2..f4801ffae4 100644 --- a/Client/multiplayer_sa/CMultiplayerSA_ClothesCache.cpp +++ b/Client/multiplayer_sa/CMultiplayerSA_ClothesCache.cpp @@ -412,5 +412,5 @@ void CMultiplayerSA::GetClothesCacheStats(SClothesCacheStats& outStats) void CMultiplayerSA::InitHooks_ClothesCache() { EZHookInstall(CClothesBuilderCreateSkinnedClump); - InitRwFunctions(pGameInterface->GetGameVersion()); + InitRwFunctions(); } diff --git a/Client/multiplayer_sa/CMultiplayerSA_CrashFixHacks.cpp b/Client/multiplayer_sa/CMultiplayerSA_CrashFixHacks.cpp index 583d1c2bd8..57a3ef373a 100644 --- a/Client/multiplayer_sa/CMultiplayerSA_CrashFixHacks.cpp +++ b/Client/multiplayer_sa/CMultiplayerSA_CrashFixHacks.cpp @@ -43,6 +43,10 @@ void _declspec(naked) CrashAverted() } } +//////////////////////////////////////////////////////////////////////// +// CCustomCarEnvMapPipeline::CustomPipeRenderCB +// +// Null mesh material pointer //////////////////////////////////////////////////////////////////////// #define HOOKPOS_CrashFix_Misc1 0x5D9A6E #define HOOKSIZE_CrashFix_Misc1 6 @@ -56,7 +60,7 @@ void _declspec(naked) HOOK_CrashFix_Misc1() je cont mov eax,dword ptr ds:[008D12CCh] - mov ecx,dword ptr [eax+esi] // If [eax+esi] is 0, it causes a crash + mov ecx,dword ptr [eax+esi] // If [eax+esi] (mesh->material) is 0, it causes a crash test ecx,ecx jne cont push 1 @@ -67,6 +71,10 @@ void _declspec(naked) HOOK_CrashFix_Misc1() } } +//////////////////////////////////////////////////////////////////////// +// CAutomobile::ProcessControl +// +// Null CColModel pointer or corrupted m_pColData //////////////////////////////////////////////////////////////////////// #define HOOKPOS_CrashFix_Misc2 0x6B18B0 #define HOOKSIZE_CrashFix_Misc2 9 @@ -98,6 +106,10 @@ void _declspec(naked) HOOK_CrashFix_Misc2() } } +//////////////////////////////////////////////////////////////////////// +// CTaskSimpleCarOpenDoorFromOutside::ComputeAnimID +// +// Invalid m_veh pointer //////////////////////////////////////////////////////////////////////// #define HOOKPOS_CrashFix_Misc3 0x645FD9 #define HOOKSIZE_CrashFix_Misc3 6 @@ -107,7 +119,7 @@ void _declspec(naked) HOOK_CrashFix_Misc3() _asm { test ecx,ecx - je cont // Skip much code if ecx is zero (ped has no something) + je cont // Skip much code if ecx is zero (invalid m_veh in CTaskSimpleCarOpenDoorFromOutside) mov edx,dword ptr [ecx+384h] jmp RETURN_CrashFix_Misc3 @@ -118,6 +130,10 @@ void _declspec(naked) HOOK_CrashFix_Misc3() } } +//////////////////////////////////////////////////////////////////////// +// CAESoundManager::Service +// +// Division by 0 //////////////////////////////////////////////////////////////////////// #define HOOKPOS_CrashFix_Misc4 0x4F02D2 #define HOOKSIZE_CrashFix_Misc4 5 @@ -141,6 +157,10 @@ void _declspec(naked) HOOK_CrashFix_Misc4() } } +//////////////////////////////////////////////////////////////////////// +// CPed::SetPedPositionInCar +// +// Null pointer m_pVehicleStruct in the CVehicleModelInfo structure //////////////////////////////////////////////////////////////////////// #define HOOKPOS_CrashFix_Misc5 0x5DF949 #define HOOKSIZE_CrashFix_Misc5 7 @@ -153,7 +173,7 @@ void _declspec(naked) HOOK_CrashFix_Misc5() mov edi, dword ptr [ecx*4+edi] mov edi, dword ptr [edi+5Ch] test edi, edi - je cont // Skip much code if edi is zero (ped has no model) + je cont // Skip much code if edi is zero mov edi, dword ptr[ARRAY_ModelInfo] mov edi, dword ptr [ecx*4+edi] @@ -167,7 +187,12 @@ void _declspec(naked) HOOK_CrashFix_Misc5() } //////////////////////////////////////////////////////////////////////// -// #5465 2/2 +// RpAnimBlend::FrameUpdateCallBackSkinnedWithVelocityExtraction +// +// Mantis #5465 (2/2) (https://web.archive.org/web/20160411120202/http://bugs.mtasa.com/view.php?id=5465) +// +// Null pointer to object in the BlendNodeArrays array of the AnimBlendUpdateData structure +//////////////////////////////////////////////////////////////////////// #define HOOKPOS_CrashFix_Misc6 0x4D1750 #define HOOKSIZE_CrashFix_Misc6 5 DWORD RETURN_CrashFix_Misc6 = 0x4D1755; @@ -190,7 +215,12 @@ void _declspec(naked) HOOK_CrashFix_Misc6() } //////////////////////////////////////////////////////////////////////// -// #5466 +// CCollision::ProcessVerticalLine +// +// Mantis #5466 (https://web.archive.org/web/20160401233418/http://bugs.mtasa.com/view.php?id=5466) +// +// Null colModel pointer +//////////////////////////////////////////////////////////////////////// #define HOOKPOS_CrashFix_Misc7 0x417BF8 #define HOOKSIZE_CrashFix_Misc7 5 DWORD RETURN_CrashFix_Misc7 = 0x417BFD; @@ -213,7 +243,12 @@ void _declspec(naked) HOOK_CrashFix_Misc7() } //////////////////////////////////////////////////////////////////////// -// #5468 1/3 +// Get2DEffectAtomicCallback +// +// Mantis #5468 1/3 (https://web.archive.org/web/20160401233418/http://bugs.mtasa.com/view.php?id=5468) +// +// Null pointer atomic->geometry in the RpAtomic +//////////////////////////////////////////////////////////////////////// #define HOOKPOS_CrashFix_Misc8 0x73485D #define HOOKSIZE_CrashFix_Misc8 5 DWORD RETURN_CrashFix_Misc8 = 0x734862; @@ -236,7 +271,12 @@ void _declspec(naked) HOOK_CrashFix_Misc8() } //////////////////////////////////////////////////////////////////////// -// #5468 2/3 +// CProjectileInfo::Update +// +// Mantis #5468 2/3 (https://web.archive.org/web/20160401233418/http://bugs.mtasa.com/view.php?id=5468) +// +// Null pointer projectile of type CObject* in the array CProjectileInfo::ms_apProjectile +//////////////////////////////////////////////////////////////////////// #define HOOKPOS_CrashFix_Misc9 0x738B64 #define HOOKSIZE_CrashFix_Misc9 6 DWORD RETURN_CrashFix_Misc9 = 0x738B6A; @@ -259,7 +299,12 @@ void _declspec(naked) HOOK_CrashFix_Misc9() } //////////////////////////////////////////////////////////////////////// -// #5468 3/3 +// CEntity::TransformFromObjectSpace +// +// Mantis #5468 3/3 (https://web.archive.org/web/20160401233418/http://bugs.mtasa.com/view.php?id=5468) +// +// Invalid pointer to a vector +//////////////////////////////////////////////////////////////////////// #define HOOKPOS_CrashFix_Misc10 0x5334FE #define HOOKSIZE_CrashFix_Misc10 6 DWORD RETURN_CrashFix_Misc10 = 0x533504; @@ -286,7 +331,12 @@ void _declspec(naked) HOOK_CrashFix_Misc10() } //////////////////////////////////////////////////////////////////////// -// #5576 +// RpAnimBlend::FrameUpdateCallBackSkinned +// +// Mantis #5576 (https://web.archive.org/web/20160408163600/http://bugs.mtasa.com/view.php?id=5576) +// +// The crash likely occurs due to invalid data passed as the second argument +//////////////////////////////////////////////////////////////////////// #define HOOKPOS_CrashFix_Misc11 0x4D2C62 #define HOOKSIZE_CrashFix_Misc11 5 DWORD RETURN_CrashFix_Misc11 = 0x4D2C67; @@ -309,7 +359,12 @@ void _declspec(naked) HOOK_CrashFix_Misc11() } //////////////////////////////////////////////////////////////////////// -// #5530 +// CAnimManager::UncompressAnimation +// +// Mantis #5530 (https://web.archive.org/web/20160411114105/http://bugs.mtasa.com/view.php?id=5530) +// +// Null pointer of type CAnimBlendHierarchy passed to the function +//////////////////////////////////////////////////////////////////////// #define HOOKPOS_CrashFix_Misc12 0x4D41C5 #define HOOKSIZE_CrashFix_Misc12 5 DWORD RETURN_CrashFix_Misc12 = 0x4D41CA; @@ -331,6 +386,10 @@ void _declspec(naked) HOOK_CrashFix_Misc12() } } +//////////////////////////////////////////////////////////////////////// +// CAnimManager::BlendAnimation +// +// Invalid animation (Null pointer returned by CAnimBlendAssocGroup::GetAnimation) //////////////////////////////////////////////////////////////////////// #define HOOKPOS_CrashFix_Misc13 0x4D464E #define HOOKSIZE_CrashFix_Misc13 6 @@ -353,6 +412,10 @@ void _declspec(naked) HOOK_CrashFix_Misc13() } } +//////////////////////////////////////////////////////////////////////// +// CAEFrontendAudioEntity::AddAudioEvent +// +// Invalid pointer to the array CAEAudioEntity::m_pAudioEventVolumes //////////////////////////////////////////////////////////////////////// #define HOOKPOS_CrashFix_Misc14 0x4DD4B5 #define HOOKSIZE_CrashFix_Misc14 6 @@ -420,7 +483,10 @@ void _declspec(naked) HOOK_FreezeFix_Misc15() } //////////////////////////////////////////////////////////////////////// -// Handle RpAnimBlendClumpGetFirstAssociation returning NULL +// CPed::PlayFootSteps +// +// RpAnimBlendClumpGetFirstAssociation returns null pointer +//////////////////////////////////////////////////////////////////////// #define HOOKPOS_CrashFix_Misc16 0x5E5815 #define HOOKSIZE_CrashFix_Misc16 6 DWORD RETURN_CrashFix_Misc16 = 0x5E581B; @@ -445,7 +511,10 @@ void _declspec(naked) HOOK_CrashFix_Misc16() } //////////////////////////////////////////////////////////////////////// -// Handle RwFrameSetStaticPluginsSize having NULL member at 0x90 +// RwFrameForAllObjects +// +// Null pointer for the objectList (0x90) field of the RwFrame structure +//////////////////////////////////////////////////////////////////////// #define HOOKPOS_CrashFix_Misc17 0x7F120E #define HOOKSIZE_CrashFix_Misc17 6 DWORD RETURN_CrashFix_Misc17 = 0x7F1214; @@ -469,7 +538,10 @@ void _declspec(naked) HOOK_CrashFix_Misc17() } //////////////////////////////////////////////////////////////////////// -// Handle GetWheelPosition having wrong data +// CVehicleModelInfo::GetWheelPosn +// +// Null pointer frame returned by CClumpModelInfo::GetFrameFromId +//////////////////////////////////////////////////////////////////////// #define HOOKPOS_CrashFix_Misc18 0x4C7DAD #define HOOKSIZE_CrashFix_Misc18 7 DWORD RETURN_CrashFix_Misc18 = 0x4C7DB4; @@ -500,7 +572,10 @@ void _declspec(naked) HOOK_CrashFix_Misc18() } //////////////////////////////////////////////////////////////////////// -// Handle RwFrameCloneHierarchy having wrong data +// RwFrameAddChild +// +// The pointer passed as the first argument of type RwFrame to the function is null +//////////////////////////////////////////////////////////////////////// #define HOOKPOS_CrashFix_Misc19 0x7F0BF7 #define HOOKSIZE_CrashFix_Misc19 6 DWORD RETURN_CrashFix_Misc19 = 0x7F0BFD; @@ -526,7 +601,10 @@ void _declspec(naked) HOOK_CrashFix_Misc19() } //////////////////////////////////////////////////////////////////////// -// Handle CPlaceable::RemoveMatrix having wrong data +// CPlaceable::RemoveMatrix +// +// "this" is invalid +//////////////////////////////////////////////////////////////////////// #define HOOKPOS_CrashFix_Misc20 0x54F3B0 #define HOOKSIZE_CrashFix_Misc20 6 DWORD RETURN_CrashFix_Misc20 = 0x54F3B6; @@ -549,12 +627,11 @@ void _declspec(naked) HOOK_CrashFix_Misc20() } } -////////////////////////////////////////////////////////////////////////////////////////// -// +//////////////////////////////////////////////////////////////////////// +// CTaskSimpleCarFallOut::FinishAnimFallOutCB +// // Handle CTaskSimpleCarFallOut::FinishAnimFallOutCB having wrong data -// -// -////////////////////////////////////////////////////////////////////////////////////////// +//////////////////////////////////////////////////////////////////////// bool IsTaskSimpleCarFallOutValid(CAnimBlendAssociationSAInterface* pAnimBlendAssociation, CTaskSimpleCarFallOutSAInterface* pTask) { if (pTask->VTBL != (TaskVTBL*)VTBL_CTaskSimpleCarFallOut) @@ -608,7 +685,10 @@ void _declspec(naked) HOOK_CrashFix_Misc21() } //////////////////////////////////////////////////////////////////////// -// Handle CAnimBlendAssociation::Init having wrong data +// CAnimBlendAssociation::Init +// +// this->m_clumpAssoc.m_pNodeArray[v5] is invalid +//////////////////////////////////////////////////////////////////////// #define HOOKPOS_CrashFix_Misc22 0x4CEF08 #define HOOKSIZE_CrashFix_Misc22 6 DWORD RETURN_CrashFix_Misc22 = 0x4CEF25; @@ -654,7 +734,10 @@ void _declspec(naked) HOOK_CrashFix_Misc22() } //////////////////////////////////////////////////////////////////////// -// Handle CVehicleAnimGroup::ComputeAnimDoorOffsets having wrong door index +// CVehicleAnimGroup::ComputeAnimDoorOffsets +// +// Door index is out of range +//////////////////////////////////////////////////////////////////////// #define HOOKPOS_CrashFix_Misc23 0x6E3D10 #define HOOKSIZE_CrashFix_Misc23 7 DWORD RETURN_CrashFix_Misc23 = 0x6E3D17; @@ -682,7 +765,10 @@ void _declspec(naked) HOOK_CrashFix_Misc23() } //////////////////////////////////////////////////////////////////////// -// Handle _RwFrameForAllChildren being called with NULL +// RwFrameForAllChildren +// +// The first argument of type RwFrame received is invalid +//////////////////////////////////////////////////////////////////////// #define HOOKPOS_CrashFix_Misc24 0x7F0DC8 #define HOOKSIZE_CrashFix_Misc24 6 DWORD RETURN_CrashFix_Misc24 = 0x7F0DCE; @@ -707,7 +793,10 @@ void _declspec(naked) HOOK_CrashFix_Misc24() } //////////////////////////////////////////////////////////////////////// -// Handle CTaskSimpleCarOpenDoorFromOutside::FinishAnimCarOpenDoorFromOutsideCB having zero pointer to vehicle +// CTaskSimpleCarOpenDoorFromOutside::FinishAnimCarOpenDoorFromOutsideCB +// +// Null vehicle pointer +//////////////////////////////////////////////////////////////////////// #define HOOKPOS_CrashFix_Misc25 0x646026 #define HOOKSIZE_CrashFix_Misc25 5 DWORD RETURN_CrashFix_Misc25 = 0x64602B; @@ -736,7 +825,10 @@ void _declspec(naked) HOOK_CrashFix_Misc25() } //////////////////////////////////////////////////////////////////////// -// Handle CShotInfo::Update having invalid item +// CShotInfo::Update +// +// _creator->m_pIntelligence is invalid +//////////////////////////////////////////////////////////////////////// #define HOOKPOS_CrashFix_Misc26 0x739FA0 #define HOOKSIZE_CrashFix_Misc26 6 DWORD RETURN_CrashFix_Misc26 = 0x739FA6; @@ -766,7 +858,10 @@ void _declspec(naked) HOOK_CrashFix_Misc26() } //////////////////////////////////////////////////////////////////////// -// Handle CTaskComplexDieInCar::ControlSubTask ped with no vehicle +// CTaskComplexDieInCar::ControlSubTask +// +// ped or ped->m_pVehicle is null pointer +//////////////////////////////////////////////////////////////////////// #define HOOKPOS_CrashFix_Misc27 0x6377FB #define HOOKSIZE_CrashFix_Misc27 7 DWORD RETURN_CrashFix_Misc27 = 0x637802; @@ -792,7 +887,10 @@ void _declspec(naked) HOOK_CrashFix_Misc27() } //////////////////////////////////////////////////////////////////////// -// Handle CObject::ProcessGarageDoorBehaviour object with no dummy +// CObject::ProcessGarageDoorBehaviour +// +// Null this->m_pDummyObject pointer +//////////////////////////////////////////////////////////////////////// #define HOOKPOS_CrashFix_Misc28 0x44A4FD #define HOOKSIZE_CrashFix_Misc28 6 DWORD RETURN_CrashFix_Misc28 = 0x44A503; @@ -820,7 +918,10 @@ void _declspec(naked) HOOK_CrashFix_Misc28() } //////////////////////////////////////////////////////////////////////// -// Handle CAEPCBankLoader::IsSoundBankLoaded with invalid argument +// CAEMP3BankLoader::IsSoundBankLoaded +// +// The value of the argument BankSlotId is invalid +//////////////////////////////////////////////////////////////////////// #define HOOKPOS_CrashFix_Misc29 0x4E022C #define HOOKSIZE_CrashFix_Misc29 5 DWORD RETURN_CrashFix_Misc29 = 0x4E0231; @@ -848,7 +949,10 @@ void _declspec(naked) HOOK_CrashFix_Misc29() } //////////////////////////////////////////////////////////////////////// -// Handle CAnimBlendAssociation::SetFinishCallback with invalid ecx +// CAnimBlendAssociation::SetFinishCallback +// +// "this" is invalid +//////////////////////////////////////////////////////////////////////// #define HOOKPOS_CrashFix_Misc30 0x4CEBE8 #define HOOKSIZE_CrashFix_Misc30 7 #define HOOKCHECK_CrashFix_Misc30 0xC7 @@ -875,11 +979,11 @@ void _declspec(naked) HOOK_CrashFix_Misc30() } } -////////////////////////////////////////////////////////////////////////////////////////// -// +//////////////////////////////////////////////////////////////////////// // CClumpModelInfo::GetFrameFromId // -////////////////////////////////////////////////////////////////////////////////////////// +// Invalid frame +//////////////////////////////////////////////////////////////////////// RwFrame* OnMY_CClumpModelInfo_GetFrameFromId_Post(RwFrame* pFrameResult, DWORD _ebx, DWORD _esi, DWORD _edi, DWORD calledFrom, RpClump* pClump, int id) { if (pFrameResult) @@ -989,13 +1093,11 @@ CStreamingInfo* GetStreamingInfo(uint id) return pItemInfo + id; } -////////////////////////////////////////////////////////////////////////////////////////// -// +//////////////////////////////////////////////////////////////////////// // CEntity::GetBoundRect // -// Check if crash will occur -// -////////////////////////////////////////////////////////////////////////////////////////// +// modelInfo->m_pColModel is a null pointer +//////////////////////////////////////////////////////////////////////// void OnMY_CEntity_GetBoundRect(CEntitySAInterface* pEntity) { uint32 usModelId = pEntity->m_nModelIndex; @@ -1050,13 +1152,11 @@ void _declspec(naked) HOOK_CEntity_GetBoundRect() } } -////////////////////////////////////////////////////////////////////////////////////////// -// +////////////////////////////////////////////////////////////////////////// // CVehicle_AddUpgrade // // Record some variables in case crash occurs -// -////////////////////////////////////////////////////////////////////////////////////////// +//////////////////////////////////////////////////////////////////////// void OnMY_CVehicle_AddUpgrade_Pre(CVehicleSAInterface* pVehicle, int iUpgradeId, int iFrame) { CArgMap argMap; @@ -1104,11 +1204,11 @@ void _declspec(naked) HOOK_CVehicle_AddUpgrade() } } -////////////////////////////////////////////////////////////////////////////////////////// -// +//////////////////////////////////////////////////////////////////////// +// CObject::~CObject, CObject::ProcessTrainCrossingBehavior +// // Train crossings: Detach barrier from post (to be able to create objects 1373 and 1374 separately) -// -////////////////////////////////////////////////////////////////////////////////////////// +//////////////////////////////////////////////////////////////////////// #define HOOKPOS_CObject_Destructor_TrainCrossing_Check 0x59F7A8 #define HOOKPOS_CObject_ProcessTrainCrossingBehavior1 0x5A0C34 #define HOOKPOS_CObject_ProcessTrainCrossingBehavior2 0x5A0C54 @@ -1139,11 +1239,11 @@ void _declspec(naked) HOOK_TrainCrossingBarrierCrashFix() } } -////////////////////////////////////////////////////////////////////////////////////////// -// +//////////////////////////////////////////////////////////////////////// +// Interior_c::Init +// // GTA doesn't reset the furniture object counter, so do it manually everytime before GTA furnishes an interior (Interior_c::Init) -// -////////////////////////////////////////////////////////////////////////////////////////// +//////////////////////////////////////////////////////////////////////// #define HOOKPOS_ResetFurnitureObjectCounter 0x593BF0 #define HOOKSIZE_ResetFurnitureObjectCounter 6 DWORD RETURN_ResetFurnitureObjectCounter = 0x593BF6; @@ -1159,14 +1259,12 @@ void _declspec(naked) HOOK_ResetFurnitureObjectCounter() } } -////////////////////////////////////////////////////////////////////////////////////////// -// +//////////////////////////////////////////////////////////////////////// // CVolumetricShadowMgr_Render -// +// // Custom models can cause problems for volumetric shadows. // Record when volumetric shadows are being rendered so we can disable them if a crash occurs. -// -////////////////////////////////////////////////////////////////////////////////////////// +//////////////////////////////////////////////////////////////////////// void OnMY_CVolumetricShadowMgr_Render_Pre() { OnEnterCrashZone(1); @@ -1205,14 +1303,12 @@ void _declspec(naked) HOOK_CVolumetricShadowMgr_Render() } } -////////////////////////////////////////////////////////////////////////////////////////// -// +//////////////////////////////////////////////////////////////////////// // CVolumetricShadowMgr_Update -// +// // Custom models can cause problems for volumetric shadows. // Record when volumetric shadows are being updated so we can disable them if a crash occurs. -// -////////////////////////////////////////////////////////////////////////////////////////// +//////////////////////////////////////////////////////////////////////// void OnMY_CVolumetricShadowMgr_Update_Pre() { OnEnterCrashZone(2); @@ -1252,13 +1348,11 @@ void _declspec(naked) HOOK_CVolumetricShadowMgr_Update() } } -////////////////////////////////////////////////////////////////////////////////////////// -// -// CAnimManager_CreateAnimAssocGroups -// -// A model (usually 7) has to be loaded to avoid a crash -// -////////////////////////////////////////////////////////////////////////////////////////// +//////////////////////////////////////////////////////////////////////// +// CAnimManager::CreateAnimAssocGroups +// +// CModelInfo::ms_modelInfoPtrs at the given index is a null pointer +//////////////////////////////////////////////////////////////////////// void OnMY_CAnimManager_CreateAnimAssocGroups(uint uiModelId) { CModelInfo* pModelInfo = pGameInterface->GetModelInfo(uiModelId); @@ -1298,14 +1392,12 @@ void _declspec(naked) HOOK_CAnimManager_CreateAnimAssocGroups() } } -////////////////////////////////////////////////////////////////////////////////////////// -// -// Something called from CTaskComplexCarSlowBeDraggedOut_CreateFirstSubTask +//////////////////////////////////////////////////////////////////////// +// CTaskComplexCarSlowBeDraggedOut::CreateFirstSubTask // // Accessing a temporally not existing vehicle // (seems to happen when the driver is slower being thrown out than the jacker enters the vehicle) -// -////////////////////////////////////////////////////////////////////////////////////////// +//////////////////////////////////////////////////////////////////////// #define HOOKPOS_CTaskComplexCarSlowBeDraggedOut_CreateFirstSubTask 0x6485AC #define HOOKSIZE_CTaskComplexCarSlowBeDraggedOut_CreateFirstSubTask 6 DWORD RETURN_CTaskComplexCarSlowBeDraggedOut_CreateFirstSubTask = 0x6485B2; @@ -1334,11 +1426,9 @@ void _declspec(naked) HOOK_CTaskComplexCarSlowBeDraggedOut_CreateFirstSubTask() } //////////////////////////////////////////////////////////////////////// -// // OnMY_printf -// +// // GTA outputs stuff via printf which we can use to help diagnose problems -// //////////////////////////////////////////////////////////////////////// void _cdecl OnMY_printf(DWORD dwCalledFrom, const char* szMessage) { @@ -1393,11 +1483,9 @@ void _declspec(naked) HOOK_printf() } //////////////////////////////////////////////////////////////////////// -// // RwMatrixMultiply -// -// Check for invalid matix pointer -// +// +// The third received argument of type RwMatrixTag* is a null pointer //////////////////////////////////////////////////////////////////////// #define HOOKPOS_RwMatrixMultiply 0x7F18B0 #define HOOKSIZE_RwMatrixMultiply 6 @@ -1421,13 +1509,11 @@ void _declspec(naked) HOOK_RwMatrixMultiply() } } -////////////////////////////////////////////////////////////////////////////////////////// -// -// CAnimBlendNode_GetCurrentTranslation -// -// Check for corrupt endKeyFrameIndex -// -////////////////////////////////////////////////////////////////////////////////////////// +//////////////////////////////////////////////////////////////////////// +// CAnimBlendNode::GetCurrentTranslation +// +// Invalid endKeyFrameIndex +//////////////////////////////////////////////////////////////////////// void OnMY_CAnimBlendNode_GetCurrentTranslation(CAnimBlendNodeSAInterface* pInterface) { // Crash will occur at offset 0xCFCD6 @@ -1490,14 +1576,12 @@ void _declspec(naked) HOOK_CAnimBlendNode_GetCurrentTranslation() } } -////////////////////////////////////////////////////////////////////////////////////////// -// -// CStreaming_AreAnimsUsedByRequestedModels -// +//////////////////////////////////////////////////////////////////////// +// CStreaming::AreAnimsUsedByRequestedModels +// // GTA streamer will use this function to decide if IFP blocks should be unloaded or not. // We will return true to disable unloading. -// -////////////////////////////////////////////////////////////////////////////////////////// +//////////////////////////////////////////////////////////////////////// bool __cdecl OnMY_CStreaming_AreAnimsUsedByRequestedModels(int modelID) { // GTA SA possibly cannot have more than 200 IFP blocks since that's the limit @@ -1529,17 +1613,16 @@ void _declspec(naked) HOOK_CStreaming_AreAnimsUsedByRequestedModels() } } -////////////////////////////////////////////////////////////////////////////////////////// -// +//////////////////////////////////////////////////////////////////////// // CTrain::ProcessControl -// +// // This hook overwrites the logic to wrap the train's rail distance, because in the // original game code this could cause an infinite loop // -////////////////////////////////////////////////////////////////////////////////////////// // 0x6F8F83 | 88 9E CA 05 00 00 | mov [esi + 5CAh], bl // >>> 0x6F8F89 | D9 86 A8 05 00 00 | fld dword ptr [esi + 5A8h] // 0x6F8F8F | D8 1D 50 8B 85 00 | fcomp ds: __real @00000000 +//////////////////////////////////////////////////////////////////////// #define HOOKPOS_CTrain__ProcessControl 0x6F8F89 #define HOOKSIZE_CTrain__ProcessControl 6 static DWORD CONTINUE_CTrain__ProcessControl = 0x6F8FE5; @@ -1597,17 +1680,16 @@ static void _declspec(naked) HOOK_CTrain__ProcessControl() } } -////////////////////////////////////////////////////////////////////////////////////////// -// +//////////////////////////////////////////////////////////////////////// // CTaskComplexCarSlowBeDraggedOutAndStandUp::CreateFirstSubTask -// +// // This hook adds a null-pointer check for eax, which stores the ped's current vehicle. // Returning a null-pointer from this function will prevent the animation from being played. // -////////////////////////////////////////////////////////////////////////////////////////// // 0x648AAC | C2 04 00 | retn 4 // >>> 0x648AAF | 8B 80 84 03 00 00 | mov eax, [eax + 384h] // 0x648AB5 | 0F B6 80 DE 00 00 00 | movzx eax, byte ptr [eax + 0DEh] +//////////////////////////////////////////////////////////////////////// #define HOOKPOS_CTaskComplexCarSlowBeDraggedOutAndStandUp__CreateFirstSubTask 0x648AAF #define HOOKSIZE_CTaskComplexCarSlowBeDraggedOutAndStandUp__CreateFirstSubTask 6 static DWORD CONTINUE_CTaskComplexCarSlowBeDraggedOutAndStandUp__CreateFirstSubTask = 0x648AB5; @@ -1636,16 +1718,14 @@ static void _declspec(naked) HOOK_CTaskComplexCarSlowBeDraggedOutAndStandUp__Cre } } -////////////////////////////////////////////////////////////////////////////////////////// -// +//////////////////////////////////////////////////////////////////////// // CVehicleModelInfo::LoadVehicleColours -// +// // A modified data/carcols.dat can have entries with invalid model names and these cause // CModelInfo::GetModelInfo to return a null pointer, but the original code doesn't verify // the return value and tries to use the null pointer. This hook adds a null pointer check // and then skips the line if in the null case. There are two locations to hook. -// -////////////////////////////////////////////////////////////////////////////////////////// +//////////////////////////////////////////////////////////////////////// static void _cdecl LOG_CVehicleModelInfo__LoadVehicleColours(int location, const char* modelName) { LogEvent(820 + location, "CVehicleModelInfo::LoadVehicleColours", "Could not find model by name:", modelName); @@ -1719,17 +1799,16 @@ static void _declspec(naked) HOOK_CVehicleModelInfo__LoadVehicleColours_2() } } -////////////////////////////////////////////////////////////////////////////////////////// -// +//////////////////////////////////////////////////////////////////////// // CPlaceName::Process -// +// // Prevent the original game code from accessing the ped's vehicle, when it's a null pointer // and the ped flag bInVehicle is set by setting the ped flag to zero. // -////////////////////////////////////////////////////////////////////////////////////////// // 0x571F37 | 8B F1 | mov esi, ecx // >>> 0x571F39 | 8B 88 6C 04 00 00 | mov ecx, [eax + 46Ch] // 0x571F3F | F6 C5 01 | test ch, 1 +//////////////////////////////////////////////////////////////////////// #define HOOKPOS_CPlaceName__Process 0x571F39 #define HOOKSIZE_CPlaceName__Process 6 static DWORD CONTINUE_CPlaceName__Process = 0x571F3F; @@ -1755,6 +1834,11 @@ static void _declspec(naked) HOOK_CPlaceName__Process() } } +//////////////////////////////////////////////////////////////////////// +// CWorld::FindObjectsKindaCollidingSectorList +// +// A null pointer at the given index in CModelInfo::ms_modelInfoPtrs or a null pointer in the m_pColModel field +//////////////////////////////////////////////////////////////////////// static void LOG_CWorld__FindObjectsKindaCollidingSectorList(unsigned int modelId) { CBaseModelInfoSAInterface* pModelInfo = ((CBaseModelInfoSAInterface**)ARRAY_ModelInfo)[modelId]; @@ -1798,17 +1882,16 @@ static void _declspec(naked) HOOK_CWorld__FindObjectsKindaCollidingSectorList() } } -////////////////////////////////////////////////////////////////////////////////////////// -// +//////////////////////////////////////////////////////////////////////// // RpClumpForAllAtomics -// +// // Adds a nullptr check for the clump object pointer. // -////////////////////////////////////////////////////////////////////////////////////////// // >>> 0x749B70 | 8B 44 24 04 | mov eax, [esp+arg_0] // >>> 0x749B74 | 53 | push ebx // >>> 0x749B75 | 55 | push ebp // 0x749B76 | 56 | push esi +//////////////////////////////////////////////////////////////////////// #define HOOKPOS_RpClumpForAllAtomics 0x749B70 #define HOOKSIZE_RpClumpForAllAtomics 6 static DWORD CONTINUE_RpClumpForAllAtomics = 0x749B76; @@ -1829,15 +1912,14 @@ static void _declspec(naked) HOOK_RpClumpForAllAtomics() } } -////////////////////////////////////////////////////////////////////////////////////////// -// +//////////////////////////////////////////////////////////////////////// // RpAnimBlendClumpGetFirstAssociation -// +// // Adds a nullptr check for the clump object pointer. // -////////////////////////////////////////////////////////////////////////////////////////// // >>> 0x4D6A70 | 8B 0D 78 F8 B5 00 | mov ecx, ds:_ClumpOffset // 0x4D6A76 | 8B 44 24 04 | mov eax, [esp+4] +//////////////////////////////////////////////////////////////////////// #define HOOKPOS_RpAnimBlendClumpGetFirstAssociation 0x4D6A70 #define HOOKSIZE_RpAnimBlendClumpGetFirstAssociation 6 static DWORD CONTINUE_RpAnimBlendClumpGetFirstAssociation = 0x4D6A76; @@ -1857,16 +1939,15 @@ static void _declspec(naked) HOOK_RpAnimBlendClumpGetFirstAssociation() } } -////////////////////////////////////////////////////////////////////////////////////////// -// +//////////////////////////////////////////////////////////////////////// // CAnimManager::BlendAnimation -// +// // Adds a nullptr check for the clump object pointer. // -////////////////////////////////////////////////////////////////////////////////////////// // >>> 0x4D4610 | 83 EC 14 | sub esp, 14h // >>> 0x4D4613 | 8B 4C 24 18 | mov ecx, [esp+18h] // 0x4D4617 | 8B 15 34 EA B4 00 | mov edx, CAnimManager::ms_aAnimAssocGroups +//////////////////////////////////////////////////////////////////////// #define HOOKPOS_CAnimManager__BlendAnimation 0x4D4610 #define HOOKSIZE_CAnimManager__BlendAnimation 7 static DWORD CONTINUE_CAnimManager__BlendAnimation = 0x4D4617; @@ -1887,14 +1968,12 @@ static void _declspec(naked) HOOK_CAnimManager__BlendAnimation() } } -////////////////////////////////////////////////////////////////////////////////////////// -// +//////////////////////////////////////////////////////////////////////// // FxSystemBP_c::Load // // Remove every FxEmitter without a main texture because the game logic expects AT LEAST // one texture at index 0 ("main texture"). // -////////////////////////////////////////////////////////////////////////////////////////// // 0x5C0A14 | 5E | pop esi // >>> 0x5C0A15 | 5D | pop ebp // >>> 0x5C0A16 | 32 C0 | xor al, al @@ -1902,6 +1981,7 @@ static void _declspec(naked) HOOK_CAnimManager__BlendAnimation() // >>> 0x5C0A19 | 64 89 0D 00 00 00 00 | mov large fs:0, ecx // >>> 0x5C0A20 | 81 C4 E8 05 00 00 | add esp, 5E8h // >>> 0x5C0A26 | C2 0C 00 | retn 0Ch +//////////////////////////////////////////////////////////////////////// #define HOOKPOS_FxSystemBP_c__Load 0x5C0A15 #define HOOKSIZE_FxSystemBP_c__Load 19 @@ -1954,17 +2034,16 @@ static void _declspec(naked) HOOK_FxSystemBP_c__Load() } } -////////////////////////////////////////////////////////////////////////////////////////// -// +//////////////////////////////////////////////////////////////////////// // FxPrim_c::Enable // // Add a null-pointer check for the ecx pointer. This hook is a side-effect of the hook for // FxSystemBP_c::Load above. // -////////////////////////////////////////////////////////////////////////////////////////// // >>> 0x4A9F50 | 8A 44 24 04 | mov al, [esp+4] // >>> 0x4A9F54 | 88 41 0C | mov [ecx+0xC], al // >>> 0x4A9F57 | C2 04 00 | retn 4 +//////////////////////////////////////////////////////////////////////// #define HOOKPOS_FxPrim_c__Enable 0x4A9F50 #define HOOKSIZE_FxPrim_c__Enable 10 @@ -1982,11 +2061,39 @@ static void _declspec(naked) HOOK_FxPrim_c__Enable() } } +//////////////////////////////////////////////////////////////////////// +// CFire::ProcessFire +// +// GitHub #1757 (https://github.com/multitheftauto/mtasa-blue/issues/1757) +// +// Null pointer to the attachedTo field in the CFire structure +//////////////////////////////////////////////////////////////////////// +#define HOOKPOS_CFire_ProcessFire 0x53A6FC +#define HOOKSIZE_CFire_ProcessFire 9 +static constexpr DWORD CONTINUE_CFire_ProcessFire = 0x53A705; +static constexpr DWORD SKIP_CFire_ProcessFire = 0x53A69C; +static void _declspec(naked) HOOK_CFire_ProcessFire() +{ + _asm + { + test byte ptr [esi], 1 // If the "active" flag has been set to 0, we skip processing attached entities + jz skip + + mov ecx, [esi+10h] + mov eax, [ecx+590h] + jmp CONTINUE_CFire_ProcessFire + + skip: + mov ecx, esi + jmp SKIP_CFire_ProcessFire + } +} + ////////////////////////////////////////////////////////////////////////////////////////// // // Setup hooks for CrashFixHacks // -////////////////////////////////////////////////////////////////////////////////////////// +//////////////////////////////////////////////////////////////////////// void CMultiplayerSA::InitHooks_CrashFixHacks() { EZHookInstall(CrashFix_Misc1); @@ -2042,6 +2149,7 @@ void CMultiplayerSA::InitHooks_CrashFixHacks() EZHookInstall(CAnimManager__BlendAnimation); EZHookInstall(FxSystemBP_c__Load); EZHookInstall(FxPrim_c__Enable); + EZHookInstall(CFire_ProcessFire); // Install train crossing crashfix (the temporary variable is required for the template logic) void (*temp)() = HOOK_TrainCrossingBarrierCrashFix; diff --git a/Client/multiplayer_sa/CMultiplayerSA_FrameRateFixes.cpp b/Client/multiplayer_sa/CMultiplayerSA_FrameRateFixes.cpp index f1adfe1ffd..5f2340d39e 100644 --- a/Client/multiplayer_sa/CMultiplayerSA_FrameRateFixes.cpp +++ b/Client/multiplayer_sa/CMultiplayerSA_FrameRateFixes.cpp @@ -341,8 +341,8 @@ static void _declspec(naked) HOOK_CWaterCannon__Update_OncePerFrame_PushPedFix() } // Fixes excessive particle spawning from water cannons on high FPS. -#define HOOKPOS_CWaterCannon__Render_FxFix 0x729430 -#define HOOKSIZE_CWaterCannon__Render_FxFix 0x7 +#define HOOKPOS_CWaterCannon__Render_FxFix 0x729437 +#define HOOKSIZE_CWaterCannon__Render_FxFix 0x5 static const unsigned int RETURN_CWaterCannon__Render_FxFix = 0x729440; static const unsigned int RETURN_CWaterCannon__Render_FxFix_SKIP = 0x7294EE; static void _declspec(naked) HOOK_CWaterCannon__Render_FxFix() @@ -352,8 +352,6 @@ static void _declspec(naked) HOOK_CWaterCannon__Render_FxFix() test edx, edx jz skip - fstp [esp+0x84] - jmp RETURN_CWaterCannon__Render_FxFix skip: jmp RETURN_CWaterCannon__Render_FxFix_SKIP diff --git a/Client/multiplayer_sa/CMultiplayerSA_Rendering.cpp b/Client/multiplayer_sa/CMultiplayerSA_Rendering.cpp index 03a27688d2..b346f25874 100644 --- a/Client/multiplayer_sa/CMultiplayerSA_Rendering.cpp +++ b/Client/multiplayer_sa/CMultiplayerSA_Rendering.cpp @@ -13,6 +13,7 @@ extern CCoreInterface* g_pCore; GameEntityRenderHandler* pGameEntityRenderHandler = nullptr; PreRenderSkyHandler* pPreRenderSkyHandlerHandler = nullptr; RenderHeliLightHandler* pRenderHeliLightHandler = nullptr; +RenderEverythingBarRoadsHandler* pRenderEverythingBarRoadsHandler = nullptr; #define VAR_CCullZones_NumMirrorAttributeZones 0x0C87AC4 // int #define VAR_CMirrors_d3dRestored 0x0C7C729 // uchar @@ -581,6 +582,17 @@ void CMultiplayerSA::SetRenderHeliLightHandler(RenderHeliLightHandler* pHandler) pRenderHeliLightHandler = pHandler; } +////////////////////////////////////////////////////////////////////////////////////////// +// +// CMultiplayerSA::SetRenderEverythingBarRoadsHandler +// +// +////////////////////////////////////////////////////////////////////////////////////////// +void CMultiplayerSA::SetRenderEverythingBarRoadsHandler(RenderEverythingBarRoadsHandler* pHandler) +{ + pRenderEverythingBarRoadsHandler = pHandler; +} + ////////////////////////////////////////////////////////////////////////////////////////// // // CMultiplayerSA::SetIsMinimizedAndNotConnected @@ -703,6 +715,30 @@ void _declspec(naked) HOOK_CVisibilityPlugins_RenderPedCB() } } +// Hook info +#define HOOKPOS_CRenderer_EverythingBarRoads 0x553C78 +#define HOOKSIZE_CRenderer_EverythingBarRoads 5 +DWORD RETURN_CRenderer_EverythingBarRoads = 0x553C7D; +DWORD DO_CRenderer_EverythingBarRoads = 0x7EE180; +void _declspec(naked) HOOK_CRenderer_EverythingBarRoads() +{ + _asm + { + pushad + } + + if (pRenderEverythingBarRoadsHandler) + pRenderEverythingBarRoadsHandler(); + + _asm + { + popad + call DO_CRenderer_EverythingBarRoads + jmp RETURN_CRenderer_EverythingBarRoads + + } +} + ////////////////////////////////////////////////////////////////////////////////////////// // // CMultiplayerSA::InitHooks_Rendering @@ -726,4 +762,5 @@ void CMultiplayerSA::InitHooks_Rendering() EZHookInstallChecked(CClouds_RenderSkyPolys); EZHookInstallChecked(RwCameraSetNearClipPlane); EZHookInstall(RenderEffects_HeliLight); + EZHookInstall(CRenderer_EverythingBarRoads); } diff --git a/Client/multiplayer_sa/CMultiplayerSA_VehicleCollision.cpp b/Client/multiplayer_sa/CMultiplayerSA_VehicleCollision.cpp index e7bec94fc2..c17b2aa297 100644 --- a/Client/multiplayer_sa/CMultiplayerSA_VehicleCollision.cpp +++ b/Client/multiplayer_sa/CMultiplayerSA_VehicleCollision.cpp @@ -36,12 +36,12 @@ void TriggerVehicleCollisionEvent() pVehicleCollisionHandler(pCollisionVehicle, pEntity, pEntity->m_nModelIndex, pCollisionVehicle->m_fDamageImpulseMagnitude, pInterface->m_fDamageImpulseMagnitude, pCollisionVehicle->m_usPieceType, pCollisionVehicle->m_vecCollisionPosition, - pCollisionVehicle->m_vecCollisionImpactVelocity); + pCollisionVehicle->m_vecCollisionImpactVelocity, false); } else { pVehicleCollisionHandler(pCollisionVehicle, pEntity, pEntity->m_nModelIndex, pCollisionVehicle->m_fDamageImpulseMagnitude, 0.0f, - pCollisionVehicle->m_usPieceType, pCollisionVehicle->m_vecCollisionPosition, pCollisionVehicle->m_vecCollisionImpactVelocity); + pCollisionVehicle->m_usPieceType, pCollisionVehicle->m_vecCollisionPosition, pCollisionVehicle->m_vecCollisionImpactVelocity, pEntity->nType == ENTITY_TYPE_OBJECT && pEntity->vtbl == (CEntitySAInterfaceVTBL*)0x867030); } TIMING_CHECKPOINT("-TriggerVehColEvent"); } diff --git a/Client/sdk/core/CCommandsInterface.h b/Client/sdk/core/CCommandsInterface.h index 849e3a07da..2820bec69b 100644 --- a/Client/sdk/core/CCommandsInterface.h +++ b/Client/sdk/core/CCommandsInterface.h @@ -14,7 +14,7 @@ #include typedef void (*PFNCOMMANDHANDLER)(const char*); -typedef bool (*pfnExecuteCommandHandler)(const char*, const char*, bool, bool, bool); +typedef bool (*pfnExecuteCommandHandler)(const char*, const char*, bool, bool, bool, bool); typedef void (*PFNCOMMAND)(const char*); diff --git a/Client/sdk/core/CCoreInterface.h b/Client/sdk/core/CCoreInterface.h index 25c578a25a..c591d546e5 100644 --- a/Client/sdk/core/CCoreInterface.h +++ b/Client/sdk/core/CCoreInterface.h @@ -160,7 +160,6 @@ class CCoreInterface virtual EDiagnosticDebugType GetDiagnosticDebug() = 0; virtual void SetDiagnosticDebug(EDiagnosticDebugType value) = 0; virtual CModelCacheManager* GetModelCacheManager() = 0; - virtual void AddModelToPersistentCache(ushort usModelId) = 0; virtual void UpdateDummyProgress(int iValue = -1, const char* szType = "") = 0; virtual void SetDummyProgressUpdateAlways(bool bAlways) = 0; @@ -192,6 +191,8 @@ class CCoreInterface virtual const SString& GetLastConnectedServerName() const = 0; virtual void SetLastConnectedServerName(const SString& strServerName) = 0; + + virtual void OnPostColorFilterRender() = 0; }; class CClientTime diff --git a/Client/sdk/core/CDiscordInterface.h b/Client/sdk/core/CDiscordInterface.h index 6e3ec0f60c..3730939671 100644 --- a/Client/sdk/core/CDiscordInterface.h +++ b/Client/sdk/core/CDiscordInterface.h @@ -9,7 +9,7 @@ *****************************************************************************/ #pragma once -//#define DISCORD_DISABLE_IO_THREAD +#define DISCORD_DISABLE_IO_THREAD // Uncomment to use manuall refresh of discord connection // (important) Don't forget to write same in discord-rpc.h @@ -18,25 +18,27 @@ class CDiscordInterface public: virtual ~CDiscordInterface() = default; virtual void UpdatePresence() = 0; - virtual bool SetPresenceDetails(const char* szDetails, bool bCustom) = 0; - virtual bool SetApplicationID(const char* szResourceName, const char* szAppID) = 0; - virtual bool ResetDiscordData() = 0; - virtual bool SetPresenceState(const char* szState, bool bCustom) = 0; +#ifdef DISCORD_DISABLE_IO_THREAD + virtual void UpdatePresenceConnection() = 0; +#endif virtual void SetAssetLargeData(const char* szAsset, const char* szAssetText) = 0; virtual void SetAssetSmallData(const char* szAsset, const char* szAssetText) = 0; virtual void SetPresenceStartTimestamp(const unsigned long ulStart) = 0; virtual void SetPresenceEndTimestamp(const unsigned long ulEnd) = 0; - virtual bool SetPresenceButtons(unsigned short int iIndex, const char* szName, const char* szUrl) = 0; virtual void SetPresencePartySize(int iSize, int iMax, bool bCustom) = 0; - virtual std::string GetDiscordResourceName() const = 0; + virtual void SetDiscordClientConnected(bool bConnected) = 0; + virtual void SetDiscordUserID(const std::string& strUserID) = 0; + virtual bool SetPresenceDetails(const char* szDetails, bool bCustom) = 0; + virtual bool SetApplicationID(const char* szResourceName, const char* szAppID) = 0; + virtual bool ResetDiscordData() = 0; + virtual bool SetPresenceState(const char* szState, bool bCustom) = 0; + virtual bool SetPresenceButtons(unsigned short int iIndex, const char* szName, const char* szUrl) = 0; virtual bool SetDiscordRPCEnabled(bool bEnabled) = 0; - virtual void SetDiscordClientConnected(bool bConnected) = 0; virtual bool IsDiscordRPCEnabled() const = 0; virtual bool IsDiscordCustomDetailsDisallowed() const = 0; virtual bool IsDiscordClientConnected() const = 0; -#ifdef DISCORD_DISABLE_IO_THREAD - virtual void UpdatePresenceConnection() = 0; -#endif + virtual std::string GetDiscordResourceName() const = 0; + virtual std::string GetDiscordUserID() const = 0; }; diff --git a/Client/sdk/core/CGraphicsInterface.h b/Client/sdk/core/CGraphicsInterface.h index ca3900557f..b8e0ef744b 100644 --- a/Client/sdk/core/CGraphicsInterface.h +++ b/Client/sdk/core/CGraphicsInterface.h @@ -96,6 +96,13 @@ namespace EBlendMode } using EBlendMode::EBlendModeType; +enum class eRenderStage +{ + PRE_FX, + POST_FX, + POST_GUI +}; + class CGraphicsInterface { public: @@ -145,11 +152,11 @@ class CGraphicsInterface // Queued up drawing virtual void DrawLineQueued(float fX1, float fY1, float fX2, float fY2, float fWidth, unsigned long ulColor, bool bPostGUI) = 0; - virtual void DrawLine3DQueued(const CVector& vecBegin, const CVector& vecEnd, float fWidth, unsigned long ulColor, bool bPostGUI) = 0; + virtual void DrawLine3DQueued(const CVector& vecBegin, const CVector& vecEnd, float fWidth, unsigned long ulColor, eRenderStage stage = eRenderStage::PRE_FX) = 0; virtual void DrawMaterialLine3DQueued(const CVector& vecBegin, const CVector& vecEnd, float fWidth, unsigned long ulColor, CMaterialItem* pMaterial, float fU = 0, float fV = 0, float fSizeU = 1, float fSizeV = 1, bool bRelativeUV = true, bool bFlipUV = false, - bool bUseFaceToward = false, const CVector& vecFaceToward = CVector(), bool bPostGUI = false) = 0; + bool bUseFaceToward = false, const CVector& vecFaceToward = CVector(), eRenderStage renderStage = eRenderStage::POST_FX) = 0; virtual void DrawRectQueued(float fX, float fY, float fWidth, float fHeight, unsigned long ulColor, bool bPostGUI, bool bSubPixelPositioning = false) = 0; @@ -165,9 +172,9 @@ class CGraphicsInterface virtual void DrawMaterialPrimitiveQueued(std::vector* pVecVertices, D3DPRIMITIVETYPE eType, CMaterialItem* pMaterial, bool bPostGUI) = 0; - virtual void DrawPrimitive3DQueued(std::vector* pVecVertices, D3DPRIMITIVETYPE eType, bool bPostGUI) = 0; + virtual void DrawPrimitive3DQueued(std::vector* pVecVertices, D3DPRIMITIVETYPE eType, eRenderStage stage = eRenderStage::PRE_FX) = 0; virtual void DrawMaterialPrimitive3DQueued(std::vector* pVecVertices, D3DPRIMITIVETYPE eType, CMaterialItem* pMaterial, - bool bPostGUI) = 0; + eRenderStage stage = eRenderStage::PRE_FX) = 0; virtual void DrawCircleQueued(float fX, float fY, float fRadius, float fStartAngle, float fStopAngle, unsigned long ulColor, unsigned long ulColorCenter, short siSegments, float fRatio, bool bPostGUI) = 0; diff --git a/Client/sdk/game/CAnimManager.h b/Client/sdk/game/CAnimManager.h index c78c2268a4..31e4c88e00 100644 --- a/Client/sdk/game/CAnimManager.h +++ b/Client/sdk/game/CAnimManager.h @@ -1,11 +1,11 @@ /***************************************************************************** * - * PROJECT: Multi Theft Auto v1.0 + * PROJECT: Multi Theft Auto * LICENSE: See LICENSE in the top level directory - * FILE: sdk/game/CAnimManager.h + * FILE: Client/sdk/game/CAnimManager.h * PURPOSE: Animation manager interface * - * Multi Theft Auto is available from http://www.multitheftauto.com/ + * Multi Theft Auto is available from https://multitheftauto.com/ * *****************************************************************************/ @@ -66,14 +66,14 @@ class CAnimManager virtual int GetAnimationBlockIndex(const char* szName) = 0; virtual int RegisterAnimBlock(const char* szName) = 0; - virtual AnimAssocGroup_type GetAnimBlendAssoc(AssocGroupId groupID) = 0; + virtual AnimAssocGroup_type GetAnimBlendAssoc(AssocGroupId groupID) const = 0; virtual AssocGroupId GetFirstAssocGroup(const char* szName) = 0; virtual const char* GetAnimGroupName(AssocGroupId groupID) = 0; virtual const char* GetAnimBlockName(AssocGroupId groupID) = 0; virtual AnimBlendAssoc_type CreateAnimAssociation(AssocGroupId animGroup, AnimationId animID) = 0; - virtual StaticAssocIntface_type GetAnimStaticAssociation(eAnimGroup animGroup, eAnimID animID) = 0; + virtual StaticAssocIntface_type GetAnimStaticAssociation(eAnimGroup animGroup, eAnimID animID) const = 0; virtual AnimBlendAssoc_type GetAnimAssociation(AssocGroupId animGroup, const char* szAnimName) = 0; virtual AnimBlendAssoc_type AddAnimation(RpClump* pClump, AssocGroupId animGroup, AnimationId animID) = 0; virtual AnimBlendAssoc_type AddAnimation(RpClump* pClump, CAnimBlendHierarchy*, int ID) = 0; @@ -128,7 +128,10 @@ class CAnimManager virtual void DeleteCustomAnimHierarchyInterface(CAnimBlendHierarchySAInterface* pInterface) = 0; virtual void DeleteCustomAnimSequenceInterface(CAnimBlendSequenceSAInterface* pInterface) = 0; - virtual bool isGateWayAnimationHierarchy(CAnimBlendHierarchySAInterface* pInterface) = 0; - virtual const SString& GetGateWayBlockName() = 0; - virtual const SString& GetGateWayAnimationName() = 0; + virtual bool isGateWayAnimationHierarchy(CAnimBlendHierarchySAInterface* pInterface) = 0; + virtual const char* GetGateWayBlockName() const = 0; + virtual const char* GetGateWayAnimationName() const = 0; + + virtual bool IsValidGroup(std::uint32_t uiAnimGroup) const = 0; + virtual bool IsValidAnim(std::uint32_t uiAnimGroup, std::uint32_t uiAnimID) const = 0; }; diff --git a/Client/sdk/game/CBuilding.h b/Client/sdk/game/CBuilding.h new file mode 100644 index 0000000000..0138d3594d --- /dev/null +++ b/Client/sdk/game/CBuilding.h @@ -0,0 +1,25 @@ +/***************************************************************************** + * + * PROJECT: Multi Theft Auto v1.0 + * LICENSE: See LICENSE in the top level directory + * FILE: sdk/game/CBuilding.h + * PURPOSE: Physical entity interface + * + * Multi Theft Auto is available from http://www.multitheftauto.com/ + * + *****************************************************************************/ + +#pragma once + +#include "CEntity.h" + +class CBuildingSAInterface; + +class CBuilding : public virtual CEntity +{ +public: + virtual ~CBuilding(){}; + + virtual CBuildingSAInterface* GetBuildingInterface() = 0; + virtual void SetLod(CBuilding* pLod) = 0; +}; diff --git a/Client/sdk/game/CBuildingRemoval.h b/Client/sdk/game/CBuildingRemoval.h new file mode 100644 index 0000000000..16d7207022 --- /dev/null +++ b/Client/sdk/game/CBuildingRemoval.h @@ -0,0 +1,124 @@ +/***************************************************************************** + * + * PROJECT: Multi Theft Auto v1.0 + * LICENSE: See LICENSE in the top level directory + * FILE: sdk/game/CBuildingRemoval.h + * PURPOSE: Game world interface + * + * Multi Theft Auto is available from http://www.multitheftauto.com/ + * + + *****************************************************************************/ + +#pragma once + +#include + +class CEntitySAInterface; +class CVector; +class CVector4D; + +struct SBuildingRemoval +{ + SBuildingRemoval() + { + m_pBinaryRemoveList = new std::list; + m_pDataRemoveList = new std::list; + m_usModel = 0; + m_vecPos = CVector(0, 0, 0); + m_fRadius = 0.0f; + m_cInterior = -1; + } + + ~SBuildingRemoval() + { + delete m_pBinaryRemoveList; + delete m_pDataRemoveList; + } + + void AddBinaryBuilding(CEntitySAInterface* pInterface) + { + // Add to list of binary buildings for this removal + m_pBinaryRemoveList->push_back(pInterface); + } + void AddDataBuilding(CEntitySAInterface* pInterface) + { + // Add to list of data buildings for this removal + m_pDataRemoveList->push_back(pInterface); + } + + unsigned short m_usModel; + CVector m_vecPos; + float m_fRadius; + char m_cInterior; + std::list* m_pBinaryRemoveList; + std::list* m_pDataRemoveList; +}; + +struct sDataBuildingRemovalItem +{ + sDataBuildingRemovalItem(CEntitySAInterface* pInterface, bool bData) + { + m_pInterface = pInterface; + m_iCount = 0; + } + void AddCount() { m_iCount++; } + void RemoveCount() { m_iCount--; } + CEntitySAInterface* m_pInterface; + int m_iCount; +}; + +struct sBuildingRemovalItem +{ + sBuildingRemovalItem(CEntitySAInterface* pInterface, bool bData) + { + m_pInterface = pInterface; + m_iCount = 0; + } + void AddCount() { m_iCount++; } + void RemoveCount() { m_iCount--; } + CEntitySAInterface* m_pInterface; + int m_iCount; +}; + +struct SIPLInst +{ + CVector m_pPosition; + CVector4D m_pRotation; + int32_t m_nModelIndex; + union + { + struct + { + uint32_t m_nAreaCode : 8; + uint32_t m_bRedundantStream : 1; + uint32_t m_bDontStream : 1; + uint32_t m_bUnderwater : 1; + uint32_t m_bTunnel : 1; + uint32_t m_bTunnelTransition : 1; + uint32_t m_nReserved : 19; + }; + uint32_t m_nInstanceType; + }; + int32_t m_nLodInstanceIndex; +}; +static_assert(sizeof(SIPLInst) == 0x28, "Invalid sizeof(SIPLInst)"); + +class CBuildingRemoval +{ +public: + virtual SBuildingRemoval* GetBuildingRemoval(CEntitySAInterface* pInterface) = 0; + + virtual void RemoveBuilding(uint16_t usModelToRemove, float fDistance, float fX, float fY, float fZ, char cInterior, size_t* pOutAmount = NULL) = 0; + virtual bool IsRemovedModelInRadius(SIPLInst* pInst) = 0; + virtual bool IsModelRemoved(uint16_t usModelID) = 0; + virtual void ClearRemovedBuildingLists(size_t* pOutAmount = NULL) = 0; + virtual bool RestoreBuilding(uint16_t usModelToRestore, float fDistance, float fX, float fY, float fZ, char cInterior, size_t* pOutAmount = NULL) = 0; + virtual void AddDataBuilding(CEntitySAInterface* pInterface) = 0; + virtual void AddBinaryBuilding(CEntitySAInterface* pInterface) = 0; + virtual void RemoveWorldBuildingFromLists(CEntitySAInterface* pInterface) = 0; + virtual bool IsObjectRemoved(CEntitySAInterface* pInterface) = 0; + virtual bool IsDataModelRemoved(uint16_t usModelID) = 0; + virtual bool IsEntityRemoved(CEntitySAInterface* pInterface) = 0; + +}; diff --git a/Client/sdk/game/CBuildingsPool.h b/Client/sdk/game/CBuildingsPool.h new file mode 100644 index 0000000000..d490c162f7 --- /dev/null +++ b/Client/sdk/game/CBuildingsPool.h @@ -0,0 +1,33 @@ +/***************************************************************************** + * + * PROJECT: Multi Theft Auto v1.0 + * LICENSE: See LICENSE in the top level directory + * FILE: sdk/game/CBuildingsPool.h + * PURPOSE: Buildings pool interface + * + * Multi Theft Auto is available from http://www.multitheftauto.com/ + * + *****************************************************************************/ + +#pragma once + +#include "Common.h" +#include + +class CBuilding; +class CBuildingSA; + +class CBuildingsPool +{ +public: + + // Buildings pool + virtual CBuilding* AddBuilding(class CClientBuilding*, uint16_t modelId, CVector* vPos, CVector4D* vRot, uint8_t interior) = 0; + virtual void RemoveBuilding(CBuilding* pObject) = 0; + virtual bool HasFreeBuildingSlot() = 0; + virtual bool Resize(int size) = 0; + virtual int GetSize() const = 0; + + virtual void RemoveAllBuildings() = 0; + virtual void RestoreAllBuildings() = 0; +}; diff --git a/Client/sdk/game/CCamera.h b/Client/sdk/game/CCamera.h index 672cfaa9c0..7dc104e3c0 100644 --- a/Client/sdk/game/CCamera.h +++ b/Client/sdk/game/CCamera.h @@ -143,4 +143,7 @@ class CCamera virtual BYTE GetCameraPedViewMode() = 0; virtual void SetShakeForce(float fShakeForce) = 0; virtual float GetShakeForce() = 0; + + virtual void ShakeCamera(float radius, float x, float y, float z) noexcept = 0; + virtual void ResetShakeCamera() noexcept = 0; }; diff --git a/Client/sdk/game/CCarEnterExit.h b/Client/sdk/game/CCarEnterExit.h index 741758750c..e88a9b6e1c 100644 --- a/Client/sdk/game/CCarEnterExit.h +++ b/Client/sdk/game/CCarEnterExit.h @@ -23,4 +23,6 @@ class CCarEnterExit bool bCheckIfRoomToGetIn) = 0; virtual int ComputeTargetDoorToExit(CPed* pPed, CVehicle* pVehicle) = 0; virtual bool IsRoomForPedToLeaveCar(CVehicle* pVehicle, int iDoor, CVector* pUnknown = 0) = 0; + + virtual void GetPositionToOpenCarDoor(CVector& position, CVehicle* vehicle, std::uint32_t door) const noexcept = 0; }; diff --git a/Client/sdk/game/CCheckpoint.h b/Client/sdk/game/CCheckpoint.h index 66e5e0c371..ce17f92267 100644 --- a/Client/sdk/game/CCheckpoint.h +++ b/Client/sdk/game/CCheckpoint.h @@ -52,4 +52,7 @@ class CCheckpoint virtual void SetCameraRange(float fCameraRange) = 0; virtual float GetPulseFraction() = 0; virtual void Remove() = 0; + virtual SColor GetTargetArrowColor() const noexcept = 0; + virtual float GetTargetArrowSize() const noexcept = 0; + virtual void SetTargetArrowData(const SColor arrowColo, float size) noexcept = 0; }; diff --git a/Client/sdk/game/CCheckpoints.h b/Client/sdk/game/CCheckpoints.h index 7917827339..be9c803a40 100644 --- a/Client/sdk/game/CCheckpoints.h +++ b/Client/sdk/game/CCheckpoints.h @@ -20,4 +20,5 @@ class CCheckpoints virtual CCheckpoint* CreateCheckpoint(DWORD Identifier, WORD wType, CVector* vecPosition, CVector* vecPointDir, float fSize, float fPulseFraction, const SharedUtil::SColor color) = 0; virtual CCheckpoint* FindFreeMarker() = 0; + virtual CCheckpoint* FindMarker(DWORD identifier) = 0; }; diff --git a/Client/sdk/game/CClock.h b/Client/sdk/game/CClock.h index 2348564c8a..6f795f5919 100644 --- a/Client/sdk/game/CClock.h +++ b/Client/sdk/game/CClock.h @@ -16,4 +16,8 @@ class CClock public: virtual void Set(BYTE bHour, BYTE bMinute) = 0; virtual void Get(BYTE* bHour, BYTE* bMinute) = 0; + + virtual bool SetTimeFrozen(bool value) noexcept = 0; + virtual bool IsTimeFrozen() const noexcept = 0; + virtual bool ResetTimeFrozen() noexcept = 0; }; diff --git a/Client/sdk/game/CDummyPool.h b/Client/sdk/game/CDummyPool.h new file mode 100644 index 0000000000..46308c304f --- /dev/null +++ b/Client/sdk/game/CDummyPool.h @@ -0,0 +1,22 @@ +/***************************************************************************** + * + * PROJECT: Multi Theft Auto v1.0 + * LICENSE: See LICENSE in the top level directory + * FILE: sdk/game/CDummyPool.h + * PURPOSE: Dummy pool interface + * + * Multi Theft Auto is available from http://www.multitheftauto.com/ + * + *****************************************************************************/ + +#pragma once + +#include "Common.h" + +class CDummyPool +{ +public: + virtual void RemoveAllBuildingLods() = 0; + virtual void RestoreAllBuildingsLods() = 0; + virtual void UpdateBuildingLods(void* oldPool, void* newPool) = 0; +}; diff --git a/Client/sdk/game/CEntity.h b/Client/sdk/game/CEntity.h index 085d92ab0e..32b803d544 100644 --- a/Client/sdk/game/CEntity.h +++ b/Client/sdk/game/CEntity.h @@ -112,7 +112,9 @@ class CEntity virtual bool SetBoneMatrix(eBone boneId, const CMatrix& matrix) = 0; virtual bool GetBoneRotation(eBone boneId, float& yaw, float& pitch, float& roll) = 0; + virtual bool GetBoneRotationQuat(eBone boneId, float& x, float& y, float& z, float& w) = 0; virtual bool SetBoneRotation(eBone boneId, float yaw, float pitch, float roll) = 0; + virtual bool SetBoneRotationQuat(eBone boneId, float x, float y, float z, float w) = 0; virtual bool GetBonePosition(eBone boneId, CVector& position) = 0; virtual bool SetBonePosition(eBone boneId, const CVector& position) = 0; }; diff --git a/Client/sdk/game/CFx.h b/Client/sdk/game/CFx.h index 8b4460357d..861cfa31e2 100644 --- a/Client/sdk/game/CFx.h +++ b/Client/sdk/game/CFx.h @@ -11,6 +11,8 @@ #pragma once +#include "Common.h" + class CEntity; class CVector; class CVehicle; @@ -34,4 +36,5 @@ class CFx virtual void TriggerWaterSplash(CVector& vecPosition) = 0; virtual void TriggerBulletSplash(CVector& vecPosition) = 0; virtual void TriggerFootSplash(CVector& vecPosition) = 0; + virtual void AddParticle(eFxParticleSystems eFxParticle, const CVector& vecPosition, const CVector& vecDirection, float fR, float fG, float fB, float fA, bool bRandomizeColors, std::uint32_t iCount, float fBrightness, float fSize, bool bRandomizeSizes, float fLife) = 0; }; diff --git a/Client/sdk/game/CGame.h b/Client/sdk/game/CGame.h index dee2eaeae8..2314fdad0e 100644 --- a/Client/sdk/game/CGame.h +++ b/Client/sdk/game/CGame.h @@ -66,6 +66,9 @@ class CWeaponStat; class CWeaponStatManager; class CWeather; class CWorld; +class CIplStore; +class CBuildingRemoval; +class CRenderer; enum eEntityType; enum ePedPieceTypes; @@ -146,6 +149,8 @@ class __declspec(novtable) CGame virtual CWeaponStatManager* GetWeaponStatManager() = 0; virtual CPointLights* GetPointLights() = 0; virtual CColStore* GetCollisionStore() = 0; + virtual CBuildingRemoval* GetBuildingRemoval() = 0; + virtual CRenderer* GetRenderer() const noexcept = 0; virtual CWeaponInfo* GetWeaponInfo(eWeaponType weapon, eWeaponSkill skill = WEAPONSKILL_STD) = 0; virtual CModelInfo* GetModelInfo(DWORD dwModelID, bool bCanBeInvalid = false) = 0; @@ -216,6 +221,15 @@ class __declspec(novtable) CGame virtual bool IsFireballDestructEnabled() const noexcept = 0; virtual void SetFireballDestructEnabled(bool isEnabled) = 0; + virtual bool IsExtendedWaterCannonsEnabled() const noexcept = 0; + virtual void SetExtendedWaterCannonsEnabled(bool isEnabled) = 0; + + virtual bool IsRoadSignsTextEnabled() const noexcept = 0; + virtual void SetRoadSignsTextEnabled(bool isEnabled) = 0; + + virtual bool IsTunnelWeatherBlendEnabled() const noexcept = 0; + virtual void SetTunnelWeatherBlendEnabled(bool isEnabled) = 0; + virtual CWeapon* CreateWeapon() = 0; virtual CWeaponStat* CreateWeaponStat(eWeaponType weaponType, eWeaponSkill weaponSkill) = 0; @@ -255,4 +269,10 @@ class __declspec(novtable) CGame virtual int32_t GetBaseIDforRRR() = 0; virtual int32_t GetBaseIDforSCM() = 0; virtual int32_t GetCountOfAllFileIDs() = 0; + + virtual void RemoveAllBuildings() = 0; + virtual void RestoreGameBuildings() = 0; + + virtual bool SetBuildingPoolSize(size_t size) = 0; + }; diff --git a/Client/sdk/game/CHandlingEntry.h b/Client/sdk/game/CHandlingEntry.h index 356741e6d8..a2da6167c9 100644 --- a/Client/sdk/game/CHandlingEntry.h +++ b/Client/sdk/game/CHandlingEntry.h @@ -1,11 +1,11 @@ /***************************************************************************** * - * PROJECT: Multi Theft Auto v1.0 + * PROJECT: Multi Theft Auto * LICENSE: See LICENSE in the top level directory - * FILE: sdk/game/CHandlingEntry.h + * FILE: Client/sdk/game/CHandlingEntry.h * PURPOSE: Vehicle handling entry interface * - * Multi Theft Auto is available from http://www.multitheftauto.com/ + * Multi Theft Auto is available from https://multitheftauto.com/ * *****************************************************************************/ @@ -91,7 +91,7 @@ class CHandlingEntry virtual ~CHandlingEntry(){}; // Use this to copy data from an another handling class to this - virtual void Assign(const CHandlingEntry* pData) = 0; + virtual void Assign(const CHandlingEntry* pEntry) = 0; // Get functions virtual float GetMass() const = 0; @@ -137,8 +137,7 @@ class CHandlingEntry virtual eLightType GetTailLight() const = 0; virtual unsigned char GetAnimGroup() const = 0; - virtual eVehicleTypes GetModel() const = 0; - virtual bool HasSuspensionChanged() const = 0; + virtual std::uint16_t GetVehicleID() const = 0; // Set functions virtual void SetMass(float fMass) = 0; @@ -165,13 +164,13 @@ class CHandlingEntry virtual void SetTractionLoss(float fTractionLoss) = 0; virtual void SetTractionBias(float fTractionBias) = 0; - virtual void SetSuspensionForceLevel(float fForce) = 0; - virtual void SetSuspensionDamping(float fDamping) = 0; - virtual void SetSuspensionHighSpeedDamping(float fDamping) = 0; - virtual void SetSuspensionUpperLimit(float fUpperLimit) = 0; - virtual void SetSuspensionLowerLimit(float fLowerLimit) = 0; - virtual void SetSuspensionFrontRearBias(float fBias) = 0; - virtual void SetSuspensionAntiDiveMultiplier(float fAntiDive) = 0; + virtual void SetSuspensionForceLevel(float fForce) noexcept = 0; + virtual void SetSuspensionDamping(float fDamping) noexcept = 0; + virtual void SetSuspensionHighSpeedDamping(float fDamping) noexcept = 0; + virtual void SetSuspensionUpperLimit(float fUpperLimit) noexcept = 0; + virtual void SetSuspensionLowerLimit(float fLowerLimit) noexcept = 0; + virtual void SetSuspensionFrontRearBias(float fBias) noexcept = 0; + virtual void SetSuspensionAntiDiveMultiplier(float fAntiDive) noexcept = 0; virtual void SetCollisionDamageMultiplier(float fMultiplier) = 0; @@ -184,9 +183,7 @@ class CHandlingEntry virtual void SetTailLight(eLightType Style) = 0; virtual void SetAnimGroup(unsigned char ucGroup) = 0; - virtual void SetSuspensionChanged(bool bChanged) = 0; - // Call this every time you're done changing something. This will recalculate // all transmission/handling values according to the new values. - virtual void Recalculate(unsigned short usModel) = 0; + virtual void Recalculate() = 0; }; diff --git a/Client/sdk/game/CHandlingManager.h b/Client/sdk/game/CHandlingManager.h index ae0ad669d9..25d706220e 100644 --- a/Client/sdk/game/CHandlingManager.h +++ b/Client/sdk/game/CHandlingManager.h @@ -1,11 +1,11 @@ /***************************************************************************** * - * PROJECT: Multi Theft Auto v1.0 + * PROJECT: Multi Theft Auto * LICENSE: See LICENSE in the top level directory - * FILE: sdk/game/CHandlingManager.h + * FILE: Client/sdk/game/CHandlingManager.h * PURPOSE: Vehicle handling manager interface * - * Multi Theft Auto is available from http://www.multitheftauto.com/ + * Multi Theft Auto is available from https://multitheftauto.com/ * *****************************************************************************/ @@ -27,12 +27,12 @@ class CHandlingManager virtual CBoatHandlingEntry* CreateBoatHandlingData() = 0; virtual CBikeHandlingEntry* CreateBikeHandlingData() = 0; - virtual const CHandlingEntry* GetOriginalHandlingData(enum eVehicleTypes eModel) = 0; - virtual const CFlyingHandlingEntry* GetOriginalFlyingHandlingData(enum eVehicleTypes eModel) = 0; - virtual const CBoatHandlingEntry* GetOriginalBoatHandlingData(enum eVehicleTypes eModel) = 0; - virtual const CBikeHandlingEntry* GetOriginalBikeHandlingData(enum eVehicleTypes eModel) = 0; + virtual const CHandlingEntry* GetOriginalHandlingData(enum eVehicleTypes eModel) const = 0; + virtual const CFlyingHandlingEntry* GetOriginalFlyingHandlingData(enum eVehicleTypes eModel) const = 0; + virtual const CBoatHandlingEntry* GetOriginalBoatHandlingData(enum eVehicleTypes eModel) const = 0; + virtual const CBikeHandlingEntry* GetOriginalBikeHandlingData(enum eVehicleTypes eModel) const = 0; - virtual eHandlingProperty GetPropertyEnumFromName(std::string strName) = 0; - virtual void RemoveChangedVehicle() = 0; - virtual void CheckSuspensionChanges(CHandlingEntry* pEntry) = 0; + virtual eHandlingProperty GetPropertyEnumFromName(const std::string& strName) const = 0; + + virtual void CheckSuspensionChanges(CHandlingEntry* pEntry) noexcept = 0; }; diff --git a/Client/sdk/game/CHud.h b/Client/sdk/game/CHud.h index e26ef6e8a9..af37d4a4cd 100644 --- a/Client/sdk/game/CHud.h +++ b/Client/sdk/game/CHud.h @@ -41,4 +41,5 @@ class CHud virtual bool IsComponentVisible(eHudComponent component) = 0; virtual void AdjustComponents(float fAspectRatio) = 0; virtual void ResetComponentAdjustment() = 0; + virtual bool IsCrosshairVisible() = 0; }; diff --git a/Client/sdk/game/CIplStore.h b/Client/sdk/game/CIplStore.h new file mode 100644 index 0000000000..c3c58f2c95 --- /dev/null +++ b/Client/sdk/game/CIplStore.h @@ -0,0 +1,19 @@ +/***************************************************************************** + * + * PROJECT: Multi Theft Auto v1.0 + * LICENSE: See LICENSE in the top level directory + * FILE: sdk/game/CIplStore.h + * PURPOSE: Game IPL store interface + * + * Multi Theft Auto is available from http://www.multitheftauto.com/ + * + *****************************************************************************/ + +#pragma once + +class CIplStore +{ +public: + virtual void SetDynamicIplStreamingEnabled(bool state) = 0; + virtual void SetDynamicIplStreamingEnabled(bool state, std::function filter) = 0; +}; diff --git a/Client/sdk/game/CModelInfo.h b/Client/sdk/game/CModelInfo.h index ede6ca59cc..08cb032e4c 100644 --- a/Client/sdk/game/CModelInfo.h +++ b/Client/sdk/game/CModelInfo.h @@ -60,6 +60,7 @@ enum class eModelInfoType : unsigned char VEHICLE = 6, PED = 7, LOD_ATOMIC = 8, + UNKNOWN = 9 }; enum eVehicleUpgradePosn @@ -179,6 +180,7 @@ class CModelInfo virtual void RemoveRef(bool bRemoveExtraGTARef = false) = 0; virtual int GetRefCount() = 0; virtual bool ForceUnload() = 0; + virtual bool UnloadUnused() = 0; virtual void DeallocateModel() = 0; virtual float GetDistanceFromCentreOfMassToBaseOfModel() = 0; @@ -246,4 +248,5 @@ class CModelInfo virtual bool IsTowableBy(CModelInfo* towingModel) = 0; virtual unsigned int GetParentID() = 0; + virtual bool IsDynamic() = 0; }; diff --git a/Client/sdk/game/CPed.h b/Client/sdk/game/CPed.h index ca7441f2ac..4e91cdb8b4 100644 --- a/Client/sdk/game/CPed.h +++ b/Client/sdk/game/CPed.h @@ -25,6 +25,7 @@ class CTaskManager; class CVehicle; class CWeapon; class CWeaponStat; +class CProjectileSAInterface; enum ePedPieceTypes { @@ -170,6 +171,13 @@ namespace EPedWeaponAudioEvent } using EPedWeaponAudioEvent::EPedWeaponAudioEventType; +struct SSatchelsData +{ + CProjectileSAInterface* pProjectileInterface; + CVector* vecAttachedOffsets; + CVector* vecAttachedRotation; +}; + class CPed : public virtual CPhysical { public: @@ -183,7 +191,6 @@ class CPed : public virtual CPhysical virtual void Respawn(CVector* position, bool bCameraCut) = 0; virtual void SetModelIndex(unsigned long ulModel) = 0; - virtual void RemoveGeometryRef() = 0; virtual float GetHealth() = 0; virtual void SetHealth(float fHealth) = 0; @@ -277,4 +284,6 @@ class CPed : public virtual CPhysical virtual CPedIKSAInterface* GetPedIKInterface() = 0; virtual void* GetPedNodeInterface(std::int32_t nodeId) = 0; virtual std::unique_ptr GetPedIK() = 0; + + virtual void GetAttachedSatchels(std::vector &satchelsList) const = 0; }; diff --git a/Client/sdk/game/CPools.h b/Client/sdk/game/CPools.h index 76a39d9989..a5250fb657 100644 --- a/Client/sdk/game/CPools.h +++ b/Client/sdk/game/CPools.h @@ -11,6 +11,10 @@ #pragma once +#include "Common.h" +#include "CBuildingsPool.h" +#include "CDummyPool.h" + class CClientEntity; class CEntity; class CEntitySAInterface; @@ -18,6 +22,8 @@ class CObject; class CObjectSA; class CPed; class CPedSA; +class CBuilding; +class CBuildingSA; class CVector; class CVehicle; class CVehicleSA; @@ -63,6 +69,7 @@ class CPools virtual void RemoveVehicle(CVehicle* pVehicle, bool bDelete = true) = 0; virtual SClientEntity* GetVehicle(DWORD* pGameInterface) = 0; + virtual SClientEntity* GetVehicle(size_t pos) = 0; virtual unsigned long GetVehicleCount() = 0; // Objects pool @@ -79,6 +86,7 @@ class CPools virtual void RemovePed(CPed* pPed, bool bDelete = true) = 0; virtual SClientEntity* GetPed(DWORD* pGameInterface) = 0; // not sure we really want this here + virtual SClientEntity* GetPed(size_t pos) = 0; virtual CPed* GetPedFromRef(DWORD dwGameRef) = 0; virtual unsigned long GetPedCount() = 0; @@ -92,6 +100,7 @@ class CPools virtual int GetNumberOfUsedSpaces(ePools pool) = 0; virtual int GetPoolDefaultCapacity(ePools pool) = 0; + virtual int GetPoolDefaultModdedCapacity(ePools pool) = 0; virtual int GetPoolCapacity(ePools pool) = 0; virtual void SetPoolCapacity(ePools pool, int iValue) = 0; @@ -103,4 +112,7 @@ class CPools virtual bool IsFreeTextureDictonarySlot(uint uiTxdID) = 0; virtual ushort GetFreeTextureDictonarySlot() = 0; + + virtual CBuildingsPool& GetBuildingsPool() noexcept = 0; + virtual CDummyPool& GetDummyPool() noexcept = 0; }; diff --git a/Client/sdk/game/CRenderer.h b/Client/sdk/game/CRenderer.h new file mode 100644 index 0000000000..65d6a8bdca --- /dev/null +++ b/Client/sdk/game/CRenderer.h @@ -0,0 +1,23 @@ +/***************************************************************************** + * + * PROJECT: Multi Theft Auto v1.0 + * LICENSE: See LICENSE in the top level directory + * FILE: sdk/game/CRenderer.h + * PURPOSE: Renderer interface + * + * Multi Theft Auto is available from http://www.multitheftauto.com/ + * + *****************************************************************************/ + +#pragma once + +class CModelInfo; +class CMatrix; + +class CRenderer +{ +public: + virtual ~CRenderer() {} + + virtual void RenderModel(CModelInfo* pModelInfo, const CMatrix& matrix) = 0; +}; diff --git a/Client/sdk/game/CSettings.h b/Client/sdk/game/CSettings.h index 1bed48acfc..d5ef10a05b 100644 --- a/Client/sdk/game/CSettings.h +++ b/Client/sdk/game/CSettings.h @@ -132,9 +132,11 @@ class CGameSettings virtual bool IsMipMappingEnabled() = 0; virtual void SetMipMappingEnabled(bool bEnable) = 0; - virtual bool IsVolumetricShadowsEnabled() = 0; + virtual bool IsVolumetricShadowsEnabled() const noexcept = 0; + virtual bool GetVolumetricShadowsEnabledByVideoSetting() const noexcept = 0; virtual void SetVolumetricShadowsEnabled(bool bEnable) = 0; virtual void SetVolumetricShadowsSuspended(bool bSuspended) = 0; + virtual bool ResetVolumetricShadows() noexcept = 0; virtual bool IsDynamicPedShadowsEnabled() = 0; virtual void SetDynamicPedShadowsEnabled(bool bEnable) = 0; diff --git a/Client/sdk/game/CStreaming.h b/Client/sdk/game/CStreaming.h index c8ff17c558..5cce3c1ffa 100644 --- a/Client/sdk/game/CStreaming.h +++ b/Client/sdk/game/CStreaming.h @@ -16,6 +16,34 @@ #define INVALID_ARCHIVE_ID 0xFF #define INVALID_STREAM_ID 0xFF +enum class eModelLoadState : std::uint32_t +{ + // Model isn't loaded + LOADSTATE_NOT_LOADED = 0, + + // Model is loaded + LOADSTATE_LOADED = 1, + + // Model in request list, but not yet in loading channel (TODO: Verify this) + LOADSTATE_REQUESTED = 2, + + // Model is being read + LOADSTATE_READING = 3, + + // If the model is a `big` one this state is used to indicate + // that the model's first half has been loaded and is yet to be + // finished by loading the second half. + // When it has been loaded the state is set to `LOADED` + LOADSTATE_FINISHING = 4 +}; + +enum class PreloadAreaOption +{ + MODELS = 0, + COLLISIONS, + ALL +}; + struct CStreamingInfo { uint16_t prevId = (uint16_t)-1; @@ -25,7 +53,7 @@ struct CStreamingInfo uint8_t archiveId = 0u; uint32_t offsetInBlocks = 0u; uint32_t sizeInBlocks = 0u; - uint32_t loadState = 0u; + eModelLoadState loadState = eModelLoadState::LOADSTATE_NOT_LOADED; }; static_assert(sizeof(CStreamingInfo) == 0x14, "Invalid size for CStreamingInfo"); @@ -47,4 +75,6 @@ class CStreaming virtual void MakeSpaceFor(std::uint32_t memoryToCleanInBytes) = 0; virtual std::uint32_t GetMemoryUsed() const = 0; virtual void RemoveBigBuildings() = 0; + virtual void LoadScene(const CVector* position) = 0; + virtual void LoadSceneCollision(const CVector* position) = 0; }; diff --git a/Client/sdk/game/CVehicle.h b/Client/sdk/game/CVehicle.h index 06c72fa9af..356fe40470 100644 --- a/Client/sdk/game/CVehicle.h +++ b/Client/sdk/game/CVehicle.h @@ -199,6 +199,7 @@ class CVehicle : public virtual CPhysical virtual bool GetTyresDontBurst() = 0; virtual unsigned short GetAdjustablePropertyValue() = 0; virtual float GetHeliRotorSpeed() = 0; + virtual float GetPlaneRotorSpeed() = 0; virtual unsigned long GetExplodeTime() = 0; virtual char GetNitroCount() = 0; @@ -219,6 +220,8 @@ class CVehicle : public virtual CPhysical virtual void SetTyresDontBurst(bool bTyresDontBurst) = 0; virtual void SetAdjustablePropertyValue(unsigned short usAdjustableProperty) = 0; virtual void SetHeliRotorSpeed(float fSpeed) = 0; + virtual void SetPlaneRotorSpeed(float fSpeed) = 0; + virtual bool SetVehicleWheelRotation(float fRot1, float fRot2, float fRot3, float fRot4) noexcept = 0; virtual void SetTaxiLightOn(bool bLightState) = 0; virtual void SetExplodeTime(unsigned long ulTime) = 0; virtual void SetRadioStatus(bool bStatus) = 0; diff --git a/Client/sdk/game/CVisibilityPlugins.h b/Client/sdk/game/CVisibilityPlugins.h index 1d8d1b47cc..f2e948f65a 100644 --- a/Client/sdk/game/CVisibilityPlugins.h +++ b/Client/sdk/game/CVisibilityPlugins.h @@ -22,4 +22,6 @@ class CVisibilityPlugins public: virtual void SetClumpAlpha(RpClump* pClump, int iAlpha) = 0; virtual int GetAtomicId(RwObject* pAtomic) = 0; + + virtual bool InsertEntityIntoEntityList(void* entity, float distance, void* callback) = 0; }; diff --git a/Client/sdk/game/CWeather.h b/Client/sdk/game/CWeather.h index 36fbf0dd78..41461142e7 100644 --- a/Client/sdk/game/CWeather.h +++ b/Client/sdk/game/CWeather.h @@ -23,4 +23,32 @@ class CWeather virtual float GetAmountOfRain() = 0; virtual void SetAmountOfRain(float fAmount) = 0; virtual void ResetAmountOfRain() = 0; + + virtual float GetWetRoads() const = 0; + virtual bool SetWetRoads(float fAmount) = 0; + virtual bool ResetWetRoads() = 0; + + virtual float GetFoggyness() const = 0; + virtual bool SetFoggyness(float fAmount) = 0; + virtual bool ResetFoggyness() = 0; + + virtual float GetFog() const = 0; + virtual bool SetFog(float fAmount) = 0; + virtual bool ResetFog() = 0; + + virtual float GetRainFog() const = 0; + virtual bool SetRainFog(float fAmount) = 0; + virtual bool ResetRainFog() = 0; + + virtual float GetWaterFog() const = 0; + virtual bool SetWaterFog(float fAmount) = 0; + virtual bool ResetWaterFog() = 0; + + virtual float GetSandstorm() const = 0; + virtual bool SetSandstorm(float fAmount) = 0; + virtual bool ResetSandstorm() = 0; + + virtual float GetRainbow() const = 0; + virtual bool SetRainbow(float fAmount) = 0; + virtual bool ResetRainbow() = 0; }; diff --git a/Client/sdk/game/CWorld.h b/Client/sdk/game/CWorld.h index c2319988d9..3684172f01 100644 --- a/Client/sdk/game/CWorld.h +++ b/Client/sdk/game/CWorld.h @@ -13,7 +13,9 @@ class CEntitySAInterface; class CVector; +class CVector2D; class CColPoint; +class CEntity; struct SLineOfSightFlags { @@ -59,77 +61,6 @@ struct SProcessLineOfSightMaterialInfoResult { bool valid{}; //< Data found in this struct is only valid if this is `true`! }; -struct SBuildingRemoval -{ - SBuildingRemoval() - { - m_pBinaryRemoveList = new std::list; - m_pDataRemoveList = new std::list; - m_usModel = 0; - m_vecPos = CVector(0, 0, 0); - m_fRadius = 0.0f; - m_cInterior = -1; - } - - ~SBuildingRemoval() - { - delete m_pBinaryRemoveList; - delete m_pDataRemoveList; - } - - void AddBinaryBuilding(CEntitySAInterface* pInterface) - { - // Add to list of binary buildings for this removal - m_pBinaryRemoveList->push_back(pInterface); - } - void AddDataBuilding(CEntitySAInterface* pInterface) - { - // Add to list of data buildings for this removal - m_pDataRemoveList->push_back(pInterface); - } - - unsigned short m_usModel; - CVector m_vecPos; - float m_fRadius; - char m_cInterior; - std::list* m_pBinaryRemoveList; - std::list* m_pDataRemoveList; -}; -struct SIPLInst -{ - CVector m_pPosition; - CVector m_pRotation; - float m_fRotationCont; - WORD m_nModelIndex; - BYTE m_nInterior; - BYTE m_bLOD; -}; - -struct sDataBuildingRemovalItem -{ - sDataBuildingRemovalItem(CEntitySAInterface* pInterface, bool bData) - { - m_pInterface = pInterface; - m_iCount = 0; - } - void AddCount() { m_iCount++; } - void RemoveCount() { m_iCount--; } - CEntitySAInterface* m_pInterface; - int m_iCount; -}; -struct sBuildingRemovalItem -{ - sBuildingRemovalItem(CEntitySAInterface* pInterface, bool bData) - { - m_pInterface = pInterface; - m_iCount = 0; - } - void AddCount() { m_iCount++; } - void RemoveCount() { m_iCount--; } - CEntitySAInterface* m_pInterface; - int m_iCount; -}; - enum eDebugCaller { CEntity_SetMatrix, @@ -154,7 +85,9 @@ enum eDebugCaller CCivPed_Constructor, CCivPed_Destructor, CBuilding_Destructor, - + CBuildingPool_Constructor, + CBuildingPool_Destructor, + CBuilding_SetLod, }; enum eSurfaceProperties @@ -313,6 +246,7 @@ class CWorld { public: virtual void Add(CEntity* entity, eDebugCaller CallerId) = 0; + virtual void Add(CEntitySAInterface* entity, eDebugCaller CallerId) = 0; virtual void Remove(CEntity* entity, eDebugCaller CallerId) = 0; virtual void Remove(CEntitySAInterface* entityInterface, eDebugCaller CallerId) = 0; virtual auto ProcessLineAgainstMesh(CEntitySAInterface* e, CVector start, CVector end) -> SProcessLineOfSightMaterialInfoResult = 0; @@ -335,20 +269,7 @@ class CWorld virtual bool GetOcclusionsEnabled() = 0; virtual void FindWorldPositionForRailTrackPosition(float fRailTrackPosition, int iTrackId, CVector* pOutVecPosition) = 0; virtual int FindClosestRailTrackNode(const CVector& vecPosition, uchar& ucOutTrackId, float& fOutRailDistance) = 0; - - virtual void RemoveBuilding(unsigned short usModelToRemove, float fDistance, float fX, float fY, float fZ, char cInterior, uint* pOutAmount = NULL) = 0; - virtual bool IsRemovedModelInRadius(SIPLInst* pInst) = 0; - virtual bool IsModelRemoved(unsigned short usModelID) = 0; - virtual void ClearRemovedBuildingLists(uint* pOutAmount = NULL) = 0; - virtual bool RestoreBuilding(unsigned short usModelToRestore, float fDistance, float fX, float fY, float fZ, char cInterior, uint* pOutAmount = NULL) = 0; - virtual SBuildingRemoval* GetBuildingRemoval(CEntitySAInterface* pInterface) = 0; - virtual void AddDataBuilding(CEntitySAInterface* pInterface) = 0; - virtual void AddBinaryBuilding(CEntitySAInterface* pInterface) = 0; - virtual void RemoveWorldBuildingFromLists(CEntitySAInterface* pInterface) = 0; - virtual bool IsObjectRemoved(CEntitySAInterface* pInterface) = 0; - virtual bool IsDataModelRemoved(unsigned short usModelID) = 0; - virtual bool IsEntityRemoved(CEntitySAInterface* pInterface) = 0; - virtual bool CalculateImpactPosition(const CVector& vecInputStart, CVector& vecInputEnd) = 0; + virtual bool CalculateImpactPosition(const CVector& vecInputStart, CVector& vecInputEnd) = 0; virtual CSurfaceType* GetSurfaceInfo() = 0; virtual void ResetAllSurfaceInfo() = 0; diff --git a/Client/sdk/game/Common.h b/Client/sdk/game/Common.h index 503f4c9021..11e5a31554 100644 --- a/Client/sdk/game/Common.h +++ b/Client/sdk/game/Common.h @@ -1,11 +1,11 @@ /***************************************************************************** * - * PROJECT: Multi Theft Auto v1.0 + * PROJECT: Multi Theft Auto * LICENSE: See LICENSE in the top level directory - * FILE: sdk/game/Common.h + * FILE: Client/sdk/game/Common.h * PURPOSE: Grand Theft Auto: San Andreas game definitions * - * Multi Theft Auto is available from http://www.multitheftauto.com/ + * Multi Theft Auto is available from https://multitheftauto.com/ * *****************************************************************************/ @@ -27,6 +27,7 @@ #define MAX_PEDS ( MAX_PEDS_MTA + 30 ) // 140 #define MAX_OBJECTS ( MAX_OBJECTS_MTA + 200 ) // 1200 #define MAX_BUILDINGS 13000 +#define MAX_DUMMIES 2500 #define MAX_ENTRY_INFO_NODES ( MAX_ENTRY_INFO_NODES_MTA + 600 ) // 72600 #define MAX_POINTER_SINGLE_LINKS ( MAX_POINTER_SINGLE_LINKS_MTA + 5000 ) // 90000 #define MAX_POINTER_DOUBLE_LINKS ( MAX_POINTER_DOUBLE_LINKS_MTA + 800 ) // 74800 @@ -1598,3 +1599,48 @@ namespace eSoundEffectParams HIGH_FREQ_RT_RATIO, }; } // namespace eSoundEffectParams + +enum class eFxParticleSystems +{ + PRT_BLOOD, + PRT_BOATSPLASH, + PRT_BUBBLE, + PRT_DEBRIS, + PRT_SMOKE, + PRT_GUNSHELL, + PRT_SAND, + PRT_SAND2, + PRT_SMOKEHUGE, + PRT_SMOKE2, + PRT_SPARK, + PRT_SPARK2, + PRT_SPLASH, + PRT_WAKE, + PRT_WATERSPLASH, + PRT_WHEELDIRT, + PRT_GLASS, +}; + +enum eWorldProperty +{ + AMBIENT_COLOR, + AMBIENT_OBJ_COLOR, + DIRECTIONAL_COLOR, + SPRITE_SIZE, + SPRITE_BRIGHTNESS, + POLE_SHADOW_STRENGTH, + SHADOW_STRENGTH, + SHADOWS_OFFSET, + LIGHTS_ON_GROUND, + LOW_CLOUDS_COLOR, + BOTTOM_CLOUDS_COLOR, + CLOUDS_ALPHA1, + ILLUMINATION, + WEATHER_WET_ROADS, + WEATHER_FOGGYNESS, + WEATHER_FOG, + WEATHER_RAIN_FOG, + WEATHER_WATER_FOG, + WEATHER_SANDSTORM, + WEATHER_RAINBOW, +}; diff --git a/Client/sdk/multiplayer/CMultiplayer.h b/Client/sdk/multiplayer/CMultiplayer.h index 23c6f2ac15..02c932cf57 100644 --- a/Client/sdk/multiplayer/CMultiplayer.h +++ b/Client/sdk/multiplayer/CMultiplayer.h @@ -102,7 +102,9 @@ typedef void(PostWorldProcessHandler)(); typedef void(PostWorldProcessPedsAfterPreRenderHandler)(); typedef void(IdleHandler)(); typedef void(PreFxRenderHandler)(); +typedef void(PostColorFilterRenderHandler)(); typedef void(PreHudRenderHandler)(); +typedef void(RenderEverythingBarRoadsHandler)(); typedef CAnimBlendAssociationSAInterface*(AddAnimationHandler)(RpClump* pClump, AssocGroupId animGroup, AnimationId animID); typedef CAnimBlendAssociationSAInterface*(AddAnimationAndSyncHandler)(RpClump* pClump, CAnimBlendAssociationSAInterface* pAnimAssocToSyncWith, AssocGroupId animGroup, AnimationId animID); @@ -114,7 +116,7 @@ typedef bool(BlendAnimationHierarchyHandler)(CAnimBlendAssociationSAInterface* p typedef bool(ProcessCollisionHandler)(class CEntitySAInterface* pThisInterface, class CEntitySAInterface* pOtherInterface); typedef bool(VehicleCollisionHandler)(class CVehicleSAInterface*& pCollidingVehicle, class CEntitySAInterface* pCollidedVehicle, int iModelIndex, float fDamageImpulseMag, float fCollidingDamageImpulseMag, uint16 usPieceType, CVector vecCollisionPos, - CVector vecCollisionVelocity); + CVector vecCollisionVelocity, bool isProjectile); typedef bool(VehicleDamageHandler)(CEntitySAInterface* pVehicle, float fLoss, CEntitySAInterface* pAttacker, eWeaponType weaponType, const CVector& vecDamagePos, uchar ucTyre); typedef bool(HeliKillHandler)(class CVehicleSAInterface* pVehicle, class CEntitySAInterface* pHitInterface); @@ -231,6 +233,7 @@ class CMultiplayer virtual void SetPostWorldProcessPedsAfterPreRenderHandler(PostWorldProcessPedsAfterPreRenderHandler* pHandler) = 0; virtual void SetIdleHandler(IdleHandler* pHandler) = 0; virtual void SetPreFxRenderHandler(PreFxRenderHandler* pHandler) = 0; + virtual void SetPostColorFilterRenderHandler(PostColorFilterRenderHandler* pHandler) = 0; virtual void SetPreHudRenderHandler(PreHudRenderHandler* pHandler) = 0; virtual void DisableCallsToCAnimBlendNode(bool bDisableCalls) = 0; virtual void SetCAnimBlendAssocDestructorHandler(CAnimBlendAssocDestructorHandler* pHandler) = 0; @@ -308,6 +311,58 @@ class CMultiplayer virtual int GetMoonSize() = 0; virtual void ResetMoonSize() = 0; + virtual void GetAmbientColor(float& red, float& green, float& blue) const = 0; + virtual bool SetAmbientColor(float red, float green, float blue) = 0; + virtual bool ResetAmbientColor() = 0; + + virtual void GetAmbientObjectColor(float& red, float& green, float& blue) const = 0; + virtual bool SetAmbientObjectColor(float red, float green, float blue) = 0; + virtual bool ResetAmbientObjectColor() = 0; + + virtual void GetDirectionalColor(float& red, float& green, float& blue) const = 0; + virtual bool SetDirectionalColor(float red, float green, float blue) = 0; + virtual bool ResetDirectionalColor() = 0; + + virtual float GetSpriteSize() const = 0; + virtual bool SetSpriteSize(float size) = 0; + virtual bool ResetSpriteSize() = 0; + + virtual float GetSpriteBrightness() const = 0; + virtual bool SetSpriteBrightness(float brightness) = 0; + virtual bool ResetSpriteBrightness() = 0; + + virtual int16 GetPoleShadowStrength() const = 0; + virtual bool SetPoleShadowStrength(int16 strength) = 0; + virtual bool ResetPoleShadowStrength() = 0; + + virtual int16 GetShadowStrength() const = 0; + virtual bool SetShadowStrength(int16 strength) = 0; + virtual bool ResetShadowStrength() = 0; + + virtual float GetShadowsOffset() const = 0; + virtual bool SetShadowsOffset(float offset) = 0; + virtual bool ResetShadowsOffset() = 0; + + virtual float GetLightsOnGroundBrightness() const = 0; + virtual bool SetLightsOnGroundBrightness(float brightness) = 0; + virtual bool ResetLightsOnGroundBrightness() = 0; + + virtual void GetLowCloudsColor(int16& red, int16& green, int16& blue) const = 0; + virtual bool SetLowCloudsColor(int16 red, int16 green, int16 blue) = 0; + virtual bool ResetLowCloudsColor() = 0; + + virtual void GetBottomCloudsColor(int16& red, int16& green, int16& blue) const = 0; + virtual bool SetBottomCloudsColor(int16 red, int16 green, int16 blue) = 0; + virtual bool ResetBottomCloudsColor() = 0; + + virtual float GetCloudsAlpha1() const = 0; + virtual bool SetCloudsAlpha1(float alpha) = 0; + virtual bool ResetCloudsAlpha1() = 0; + + virtual float GetIllumination() const = 0; + virtual bool SetIllumination(float illumination) = 0; + virtual bool ResetIllumination() = 0; + virtual void DisableEnterExitVehicleKey(bool bDisabled) = 0; virtual void SetNightVisionEnabled(bool bEnabled, bool bNoiseEnabled) = 0; @@ -331,6 +386,7 @@ class CMultiplayer virtual void SetRender3DStuffHandler(Render3DStuffHandler* pHandler) = 0; virtual void SetPreRenderSkyHandler(PreRenderSkyHandler* pHandler) = 0; virtual void SetRenderHeliLightHandler(RenderHeliLightHandler* pHandler) = 0; + virtual void SetRenderEverythingBarRoadsHandler(RenderEverythingBarRoadsHandler* pHandler) = 0; virtual void Reset() = 0; @@ -373,8 +429,7 @@ class CMultiplayer virtual CLimits* GetLimits() = 0; - virtual bool IsSuspensionEnabled() = 0; - virtual void SetSuspensionEnabled(bool bEnabled) = 0; + virtual void UpdateVehicleSuspension() noexcept = 0; virtual void FlushClothesCache() = 0; virtual void SetFastClothesLoading(EFastClothesLoading fastClothesLoading) = 0; diff --git a/Client/utils/wpmhookdll/Main.cpp b/Client/utils/wpmhookdll/Main.cpp deleted file mode 100644 index 350a558a33..0000000000 --- a/Client/utils/wpmhookdll/Main.cpp +++ /dev/null @@ -1,125 +0,0 @@ -/***************************************************************************** - * - * PROJECT: Multi Theft Auto v1.0 - * LICENSE: See LICENSE in the top level directory - * FILE: utils/wpmhookdll/Main.cpp - * PURPOSE: Memory manipulation hooking utility - * - * Multi Theft Auto is available from http://www.multitheftauto.com/ - * - *****************************************************************************/ - -#define WIN32_LEAN_AND_MEAN -#include -#include -#include - -using namespace std; - -#define MESSAGE_MONITOR_START 0x8500 -#define MESSAGE_MONITOR_END 0x8501 -#define MESSAGE_MONITOR_RPM 0x8502 -#define MESSAGE_MONITOR_WPM 0x8503 - -HWND hGTA = NULL; - -// ******** ReadProcessMemory hook! ********* -typedef BOOL(WINAPI* pReadProcessMemory)(HANDLE hProcess, LPCVOID lpBaseAddress, LPVOID lpBuffer, SIZE_T nSize, SIZE_T* lpNumberOfBytesRead); - -pReadProcessMemory pfnReadProcessMemory = NULL; - -BOOL WINAPI Hook_ReadProcessMemory(HANDLE hProcess, LPCVOID lpBaseAddress, LPVOID lpBuffer, SIZE_T nSize, SIZE_T* lpNumberOfBytesRead) -{ - // Tell MTA about the RPM call - PostMessage(hGTA, MESSAGE_MONITOR_RPM, reinterpret_cast(lpBaseAddress), nSize); - - // Call the original WriteProcessMemory - return pfnReadProcessMemory(hProcess, lpBaseAddress, lpBuffer, nSize, lpNumberOfBytesRead); -} - -// ******** WriteProcessMemory hook! ********* -typedef BOOL(WINAPI* pWriteProcessMemory)(HANDLE hProcess, LPVOID lpBaseAddress, LPCVOID lpBuffer, SIZE_T nSize, SIZE_T* lpNumberOfBytesWritten); - -pWriteProcessMemory pfnWriteProcessMemory = NULL; - -BOOL WINAPI Hook_WriteProcessMemory(HANDLE hProcess, LPVOID lpBaseAddress, LPCVOID lpBuffer, SIZE_T nSize, SIZE_T* lpNumberOfBytesWritten) -{ - // Tell MTA about the WPM call - PostMessage(hGTA, MESSAGE_MONITOR_WPM, reinterpret_cast(lpBaseAddress), nSize); - - // Call the original WriteProcessMemory - return pfnWriteProcessMemory(hProcess, lpBaseAddress, lpBuffer, nSize, lpNumberOfBytesWritten); -} - -void Initialize(void) -{ - // Grab the GTA window handle - hGTA = FindWindow("Grand theft auto San Andreas", NULL); - if (hGTA != NULL) - { - // Make sure Kernel32.dll is loaded - PBYTE pKernel32 = reinterpret_cast(LoadLibrary("Kernel32.dll")); - if (pKernel32) - { - // Hook ReadProcessMemory - pfnReadProcessMemory = reinterpret_cast( - DetourFunction(DetourFindFunction("Kernel32.dll", "ReadProcessMemory"), reinterpret_cast(Hook_ReadProcessMemory))); - - // Hook WriteProcessMemory - pfnWriteProcessMemory = reinterpret_cast( - DetourFunction(DetourFindFunction("Kernel32.dll", "WriteProcessMemory"), reinterpret_cast(Hook_WriteProcessMemory))); - - // Success? - if (pfnReadProcessMemory && pfnWriteProcessMemory) - { - // Tell MTA we successfully hooked the trainer - PostMessage(hGTA, MESSAGE_MONITOR_START, 0, 0); - return; - } - } - - // Tell MTA we successfully injected but failed hooking the functions - PostMessage(hGTA, MESSAGE_MONITOR_START, 1, 1); - } -} - -void Finalize(void) -{ - // Unhook WriteProcessMemory - if (pfnWriteProcessMemory) - { - DetourRemove(reinterpret_cast(pfnWriteProcessMemory), reinterpret_cast(Hook_WriteProcessMemory)); - } - - // Unhook ReadProcessMemory - if (pfnReadProcessMemory) - { - DetourRemove(reinterpret_cast(pfnReadProcessMemory), reinterpret_cast(Hook_ReadProcessMemory)); - } - - // Tell MTA we've unhooked from the trainer - if (hGTA != NULL) - { - PostMessage(hGTA, MESSAGE_MONITOR_END, 0, 0); - } -} - -int WINAPI DllMain(HINSTANCE hModule, DWORD dwReason, PVOID pvNothing) -{ - switch (dwReason) - { - case DLL_PROCESS_ATTACH: - { - Initialize(); - return TRUE; - } - - case DLL_PROCESS_DETACH: - { - Finalize(); - return TRUE; - } - } - - return FALSE; -} diff --git a/Client/utils/wpmhookdll/wpmhookdll.sln b/Client/utils/wpmhookdll/wpmhookdll.sln deleted file mode 100644 index 6af2e1dc45..0000000000 --- a/Client/utils/wpmhookdll/wpmhookdll.sln +++ /dev/null @@ -1,21 +0,0 @@ -Microsoft Visual Studio Solution File, Format Version 8.00 -Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "wpmhookdll", "wpmhookdll.vcproj", "{BA915391-732D-40BB-9C25-4416DCC53B80}" - ProjectSection(ProjectDependencies) = postProject - EndProjectSection -EndProject -Global - GlobalSection(SolutionConfiguration) = preSolution - Debug = Debug - Release = Release - EndGlobalSection - GlobalSection(ProjectConfiguration) = postSolution - {BA915391-732D-40BB-9C25-4416DCC53B80}.Debug.ActiveCfg = Debug|Win32 - {BA915391-732D-40BB-9C25-4416DCC53B80}.Debug.Build.0 = Debug|Win32 - {BA915391-732D-40BB-9C25-4416DCC53B80}.Release.ActiveCfg = Release|Win32 - {BA915391-732D-40BB-9C25-4416DCC53B80}.Release.Build.0 = Release|Win32 - EndGlobalSection - GlobalSection(ExtensibilityGlobals) = postSolution - EndGlobalSection - GlobalSection(ExtensibilityAddIns) = postSolution - EndGlobalSection -EndGlobal diff --git a/Client/utils/wpmhookdll/wpmhookdll.vcproj b/Client/utils/wpmhookdll/wpmhookdll.vcproj deleted file mode 100644 index 9b169e32ac..0000000000 --- a/Client/utils/wpmhookdll/wpmhookdll.vcproj +++ /dev/null @@ -1,138 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - diff --git a/Dockerfile b/Dockerfile index 56439d28be..c0a721081b 100644 --- a/Dockerfile +++ b/Dockerfile @@ -15,7 +15,7 @@ ENV AS_BUILDAGENT=0 \ RUN apt-get update && \ apt-get install -y software-properties-common wget ca-certificates git build-essential \ gcc-10 g++-10 curl subversion ncftp \ - libncurses-dev libncursesw5 libmysqlclient-dev + libncurses-dev libncursesw6 libmysqlclient-dev # Set build directory VOLUME /build diff --git a/Dockerfile.arm64 b/Dockerfile.arm64 index f491aa5cf0..b2da73f581 100644 --- a/Dockerfile.arm64 +++ b/Dockerfile.arm64 @@ -21,7 +21,7 @@ RUN sed -i 's/deb http/deb \[arch=amd64,i386\] http/' /etc/apt/sources.list && \ apt-get update && \ apt-get install -y make git ncftp \ gcc-10-aarch64-linux-gnu g++-10-aarch64-linux-gnu \ - libncursesw5:arm64 libncursesw5-dev:arm64 libmysqlclient-dev:arm64 + libncurses-dev:arm64 libncursesw6:arm64 libmysqlclient-dev:arm64 # Set build directory VOLUME /build diff --git a/Dockerfile.armhf b/Dockerfile.armhf index 0cdf11543c..3cc20df9c5 100644 --- a/Dockerfile.armhf +++ b/Dockerfile.armhf @@ -21,7 +21,7 @@ RUN sed -i 's/deb http/deb \[arch=amd64,i386\] http/' /etc/apt/sources.list && \ apt-get update && \ apt-get install -y make git ncftp \ gcc-10-arm-linux-gnueabihf g++-10-arm-linux-gnueabihf \ - libncursesw5:armhf libncursesw5-dev:armhf libmysqlclient-dev:armhf + libncurses-dev:armhf libncursesw6:armhf libmysqlclient-dev:armhf # Set build directory VOLUME /build diff --git a/Dockerfile.i386 b/Dockerfile.i386 index 787782bdbe..7706537c15 100644 --- a/Dockerfile.i386 +++ b/Dockerfile.i386 @@ -15,7 +15,7 @@ ENV AS_BUILDAGENT=0 \ RUN dpkg --add-architecture i386 && apt-get update && \ apt-get install -y software-properties-common wget ca-certificates git build-essential \ gcc-10-multilib g++-10-multilib curl subversion ncftp \ - libncurses-dev:i386 libncursesw5:i386 libmysqlclient-dev:i386 + libncurses-dev:i386 libncursesw6:i386 libmysqlclient-dev:i386 # Set build directory VOLUME /build diff --git a/Dockerfile.osx-arm64 b/Dockerfile.osx-arm64 deleted file mode 100644 index 4846c0cdf2..0000000000 --- a/Dockerfile.osx-arm64 +++ /dev/null @@ -1,40 +0,0 @@ -FROM jetbrains/teamcity-minimal-agent:latest - -# This is important for using apt-get -USER root - -# Install cross-build dependencies -RUN apt-get update && \ - apt-get install -y --no-install-recommends ca-certificates subversion ncftp \ - git autoconf wget make patch cmake clang llvm-dev uuid-dev libssl-dev lzma-dev libxml2-dev python3 - -# Prepare cross-build environment -ENV MACOSX_DEPLOYMENT_TARGET=11.0 \ - PATH="${PATH}:/opt/osxcross/bin" \ - OSXCROSS_MP_INC=1 - -RUN mkdir -p /opt/osxcross && \ - git clone https://github.com/tpoechtrager/osxcross.git /opt/osxcross/setup_files && \ - cd /opt/osxcross/setup_files && \ - wget -P tarballs https://github.com/phracker/MacOSX-SDKs/releases/download/11.3/MacOSX11.3.sdk.tar.xz && \ - UNATTENDED=1 TARGET_DIR=/opt/osxcross ./build.sh && \ - UNATTENDED=1 ../bin/osxcross-macports install --arm64 mysql8 libidn2 - -# Default build configuration -ENV AS_BUILDAGENT=0 \ - BUILD_ARCHITECTURE=arm64 \ - BUILD_CONFIG=release \ - AR=arm64-apple-darwin20.4-ar \ - CC=arm64-apple-darwin20.4-clang \ - CXX=arm64-apple-darwin20.4-clang++ - -# Set build directory -VOLUME /build -WORKDIR /build - -# Copy entrypoint script -COPY utils/docker-entrypoint-osx.sh /docker-entrypoint.sh -RUN chmod +x /docker-entrypoint.sh - -# Set entrypoint -ENTRYPOINT /docker-entrypoint.sh diff --git a/Dockerfile.osx-x64 b/Dockerfile.osx-x64 deleted file mode 100644 index a694b06027..0000000000 --- a/Dockerfile.osx-x64 +++ /dev/null @@ -1,40 +0,0 @@ -FROM jetbrains/teamcity-minimal-agent:latest - -# This is important for using apt-get -USER root - -# Install cross-build dependencies -RUN apt-get update && \ - apt-get install -y --no-install-recommends ca-certificates subversion ncftp \ - git autoconf wget make patch cmake clang llvm-dev uuid-dev libssl-dev lzma-dev libxml2-dev python3 - -# Prepare cross-build environment -ENV MACOSX_DEPLOYMENT_TARGET=10.15 \ - PATH="${PATH}:/opt/osxcross/bin" \ - OSXCROSS_MP_INC=1 - -RUN mkdir -p /opt/osxcross && \ - git clone https://github.com/tpoechtrager/osxcross.git /opt/osxcross/setup_files && \ - cd /opt/osxcross/setup_files && \ - wget -P tarballs https://github.com/phracker/MacOSX-SDKs/releases/download/11.3/MacOSX11.3.sdk.tar.xz && \ - UNATTENDED=1 TARGET_DIR=/opt/osxcross ./build.sh && \ - UNATTENDED=1 ../bin/osxcross-macports install mysql8 libidn2 - -# Default build configuration -ENV AS_BUILDAGENT=0 \ - BUILD_ARCHITECTURE=x64 \ - BUILD_CONFIG=release \ - AR=x86_64-apple-darwin20.4-ar \ - CC=x86_64-apple-darwin20.4-clang \ - CXX=x86_64-apple-darwin20.4-clang++ - -# Set build directory -VOLUME /build -WORKDIR /build - -# Copy entrypoint script -COPY utils/docker-entrypoint-osx.sh /docker-entrypoint.sh -RUN chmod +x /docker-entrypoint.sh - -# Set entrypoint -ENTRYPOINT /docker-entrypoint.sh diff --git a/README.md b/README.md index 3fa1d8db7a..0534cfdb0b 100644 --- a/README.md +++ b/README.md @@ -1,4 +1,4 @@ -## Multi Theft Auto: San Andreas +## Multi Theft Auto: San Andreas [![Build Status](https://github.com/multitheftauto/mtasa-blue/workflows/Build/badge.svg?event=push&branch=master)](https://github.com/multitheftauto/mtasa-blue/actions?query=branch%3Amaster+event%3Apush) [![Unique servers online](https://img.shields.io/endpoint?url=https%3A%2F%2Fmultitheftauto.com%2Fapi%2Fservers-shields.io.json)](https://community.multitheftauto.com/index.php?p=servers) [![Unique players online](https://img.shields.io/endpoint?url=https%3A%2F%2Fmultitheftauto.com%2Fapi%2Fplayers-shields.io.json)](https://multitheftauto.com) [![Unique players last 24 hours](https://img.shields.io/endpoint?url=https%3A%2F%2Fmultitheftauto.com%2Fapi%2Funique-players-shields.io.json)](https://multitheftauto.com) [![Discord](https://img.shields.io/discord/278474088903606273?label=discord&logo=discord)](https://discord.com/invite/mtasa) [![Crowdin](https://badges.crowdin.net/e/f5dba7b9aa6594139af737c85d81d3aa/localized.svg)](https://multitheftauto.crowdin.com/multitheftauto) @@ -30,7 +30,7 @@ Using a framework based on resources has a number of advantages. It allows conte Our project's code repository can be found on the [multitheftauto/mtasa-blue](https://github.com/multitheftauto/mtasa-blue/) Git repository at [GitHub](https://github.com/). We are always looking for new developers, so if you're interested, here are some useful links: -* [Coding guidelines](https://github.com/multitheftauto/mtasa-blue/blob/master/CONTRIBUTING.md#contributors-guide) +* [Contributors Guide and Coding Guidelines](https://github.com/multitheftauto/mtasa-docs/blob/main/mtasa-blue/CONTRIBUTING.md) * [Nightly Builds](https://nightly.multitheftauto.com/) * [Milestones](https://github.com/multitheftauto/mtasa-blue/milestones) @@ -39,7 +39,9 @@ Our project's code repository can be found on the [multitheftauto/mtasa-blue](ht #### Windows Prerequisites -- [Visual Studio 2022](https://visualstudio.microsoft.com/vs/) +- [Visual Studio 2022](https://visualstudio.microsoft.com/vs/) with: + - Desktop development with C++ + - Optional component *C++ MFC for latest v143 build tools (x86 & x64)* - [Microsoft DirectX SDK](https://wiki.multitheftauto.com/wiki/Compiling_MTASA#Microsoft_DirectX_SDK) - [Git for Windows](https://git-scm.com/download/win) (Optional) @@ -48,20 +50,22 @@ Prerequisites 3. Compile 4. Execute: `win-install-data.bat` +Visit the wiki article ["Compiling MTASA"](https://wiki.multitheftauto.com/wiki/Compiling_MTASA) for additional information and error troubleshooting. + #### GNU/Linux You can build the MTA:SA server on GNU/Linux distributions only for x86, x86_64, armhf and arm64 CPU architectures. ARM architectures are currently in **experimental phase**, which means they're unstable, untested and may crash randomly. Beware that we only officially support building from x86_64 and that includes cross-compiling for x86, arm and arm64. **Build dependencies** -*Please always read the Dockerfiles for up-to-date build dependencies.* +*Please always read the Dockerfiles for up-to-date build dependencies.* *Note: ncftp is not required for building the MTA:SA server.* - git - make - GNU GCC compiler (version 10 or newer) -- libncursesw5 -- libncursesw5-dev +- libncursesw6 +- libncurses-dev - libmysqlclient-dev **Build instructions: Script** @@ -127,4 +131,4 @@ Execute `win-create-projects.bat` Unless otherwise specified, all source code hosted on this repository is licensed under the GPLv3 license. See the [LICENSE](./LICENSE) file for more details. -Grand Theft Auto and all related trademarks are © Rockstar North 1997–2023. +Grand Theft Auto and all related trademarks are © Rockstar North 1997–2024. diff --git a/Server/core/CModManagerImpl.cpp b/Server/core/CModManagerImpl.cpp index 2aa4540621..bd596e78e4 100644 --- a/Server/core/CModManagerImpl.cpp +++ b/Server/core/CModManagerImpl.cpp @@ -148,6 +148,11 @@ void CModManagerImpl::DoPulse() } } +bool CModManagerImpl::IsReadyToAcceptConnections() const noexcept +{ + return (m_pBase != nullptr) && m_pBase->IsReadyToAcceptConnections(); +} + bool CModManagerImpl::IsFinished() { if (m_pBase) diff --git a/Server/core/CModManagerImpl.h b/Server/core/CModManagerImpl.h index da0c765c64..8fae2bbb63 100644 --- a/Server/core/CModManagerImpl.h +++ b/Server/core/CModManagerImpl.h @@ -46,6 +46,8 @@ class CModManagerImpl : public CModManager void DoPulse(); + bool IsReadyToAcceptConnections() const noexcept; + bool IsFinished(); bool PendingWorkToDo(); diff --git a/Server/core/CServerImpl.cpp b/Server/core/CServerImpl.cpp index 45ddd984c3..8057f94725 100644 --- a/Server/core/CServerImpl.cpp +++ b/Server/core/CServerImpl.cpp @@ -47,6 +47,9 @@ bool IsCursesActive() { return m_wndInput != NULL; } +#else +bool g_isChildProcess = false; +HANDLE g_readyEvent = nullptr; #endif #ifdef WIN32 @@ -57,7 +60,6 @@ CServerImpl::CServerImpl() { #ifdef WIN32 m_pThreadCommandQueue = pThreadCommandQueue; - m_fClientFeedback = NULL; m_hConsole = NULL; #else m_wndMenu = NULL; @@ -122,17 +124,6 @@ void CServerImpl::Printf(const char* szFormat, ...) #endif } - // Eventually feed stuff back to our client if we run inside GTA - #ifdef WIN32 - if (m_fClientFeedback) - { - char szOutput[512]; - szOutput[511] = 0; - VSNPRINTF(szOutput, 511, szFormat, ap); - m_fClientFeedback(szOutput); - } - #endif - va_end(ap); } @@ -177,9 +168,7 @@ int CServerImpl::Run(int iArgumentCount, char* szArguments[]) if (!ParseArguments(iArgumentCount, szArguments)) return 1; -#ifdef WIN32 - if (!m_fClientFeedback) -#else +#ifndef WIN32 if (!g_bNoCrashHandler) #endif { @@ -206,9 +195,7 @@ int CServerImpl::Run(int iArgumentCount, char* szArguments[]) m_hConsole = GetStdHandle(STD_OUTPUT_HANDLE); m_hConsoleInput = GetStdHandle(STD_INPUT_HANDLE); - // If stdout is piped GetConsoleScreenBufferInfo will fail - // ==> check if stdin is piped - if (HasConsole()) + if (!g_isChildProcess && HasConsole()) { // Disable QuickEdit mode to prevent text selection causing server freeze DWORD dwConInMode; @@ -241,7 +228,18 @@ int CServerImpl::Run(int iArgumentCount, char* szArguments[]) { // Enable non-blocking read mode DWORD pipeState = PIPE_NOWAIT; - SetNamedPipeHandleState(GetStdHandle(STD_INPUT_HANDLE), &pipeState, nullptr, nullptr); + SetNamedPipeHandleState(m_hConsoleInput, &pipeState, nullptr, nullptr); + } + + if (g_isChildProcess) + { + DWORD bytesRead{}; + + if (!ReadFile(m_hConsoleInput, &g_readyEvent, sizeof(HANDLE), &bytesRead, nullptr) || bytesRead != sizeof(HANDLE)) + { + Print("ERROR: Failed to read ready-event handle from input (%08x)\n", GetLastError()); + return ERROR_OTHER; + } } #else // support user locales @@ -482,6 +480,15 @@ void CServerImpl::MainLoop() if (m_pModManager->IsFinished()) m_bRequestedQuit = true; +#ifdef WIN32 + if (g_readyEvent != nullptr && m_pModManager->IsReadyToAcceptConnections()) + { + SetEvent(g_readyEvent); + CloseHandle(g_readyEvent); + g_readyEvent = nullptr; + } +#endif + HandlePulseSleep(); } @@ -1071,16 +1078,6 @@ bool CServerImpl::ParseArguments(int iArgumentCount, char* szArguments[]) break; } - // Client feedback pointer? - #ifdef WIN32 - case 'c': - { - m_fClientFeedback = reinterpret_cast(szArguments[i]); - ucNext = 0; - break; - } - #endif - // Nothing we know, proceed default: { @@ -1123,13 +1120,16 @@ bool CServerImpl::ParseArguments(int iArgumentCount, char* szArguments[]) { g_bNoCrashHandler = true; } - - #ifdef WIN32 - else if (strcmp(szArguments[i], "--clientfeedback") == 0) +#ifdef WIN32 + else if (!strcmp(szArguments[i], "--child-process")) { - ucNext = 'c'; + g_isChildProcess = true; + g_bNoTopBar = true; + g_bNoCurses = true; + std::setbuf(stdout, nullptr); + std::setbuf(stderr, nullptr); } - #endif +#endif } } } diff --git a/Server/core/CServerImpl.h b/Server/core/CServerImpl.h index c9955bf562..8a89739786 100644 --- a/Server/core/CServerImpl.h +++ b/Server/core/CServerImpl.h @@ -30,7 +30,6 @@ typedef CXML* (*InitXMLInterface)(const char* szSaveFlagDirectory); typedef CNetServer* (*InitNetServerInterface)(); #ifdef WIN32 -typedef void(FClientFeedback)(const char* szText); constexpr SHORT SCREEN_BUFFER_SIZE = 256; #endif @@ -89,10 +88,6 @@ class CServerImpl : public CServerInterface CModManagerImpl* m_pModManager; CXML* m_pXML; -#ifdef WIN32 - FClientFeedback* m_fClientFeedback; -#endif - SString m_strServerPath; SString m_strServerModPath; diff --git a/Server/core/premake5.lua b/Server/core/premake5.lua index 7e52214323..c7b5c552d9 100644 --- a/Server/core/premake5.lua +++ b/Server/core/premake5.lua @@ -44,7 +44,7 @@ project "Core" links { "breakpad", "rt" } buildoptions { "-pthread" } linkoptions { "-pthread" } - linkoptions { "-l:libncursesw.so.5" } + linkoptions { "-l:libncursesw.so.6" } filter "system:macosx" links { "ncurses", "breakpad", "CoreFoundation.framework" } diff --git a/Server/dbconmy/CDatabaseConnectionMySql.cpp b/Server/dbconmy/CDatabaseConnectionMySql.cpp index 1262e39c0a..a1543dc38d 100644 --- a/Server/dbconmy/CDatabaseConnectionMySql.cpp +++ b/Server/dbconmy/CDatabaseConnectionMySql.cpp @@ -57,6 +57,7 @@ class CDatabaseConnectionMySql : public CDatabaseConnection bool m_bInAutomaticTransaction; CTickCount m_AutomaticTransactionStartTime; int m_bMultipleStatements; + int m_bUseSSL; }; /////////////////////////////////////////////////////////////// @@ -79,12 +80,16 @@ CDatabaseConnectionMySql::CDatabaseConnectionMySql(CDatabaseType* pManager, cons const SString& strOptions) : m_iRefCount(1), m_pManager(pManager) { + int getServerPublicKey; + // Parse options string CArgMap optionsMap("=", ";"); optionsMap.SetFromString(strOptions); optionsMap.Get("autoreconnect", m_bAutomaticReconnect, 1); optionsMap.Get("batch", m_bAutomaticTransactionsEnabled, 1); optionsMap.Get("multi_statements", m_bMultipleStatements, 0); + optionsMap.Get("use_ssl", m_bUseSSL, 0); + optionsMap.Get("get_server_public_key", getServerPublicKey, 1); SString strHostname; SString strDatabaseName; @@ -106,11 +111,15 @@ CDatabaseConnectionMySql::CDatabaseConnectionMySql(CDatabaseType* pManager, cons if (m_handle) { bool reconnect = m_bAutomaticReconnect; + uint const ssl_mode = m_bUseSSL ? SSL_MODE_REQUIRED : SSL_MODE_DISABLED; mysql_options(m_handle, MYSQL_OPT_RECONNECT, &reconnect); + mysql_options(m_handle, MYSQL_OPT_SSL_MODE, &ssl_mode); if (!strCharset.empty()) mysql_options(m_handle, MYSQL_SET_CHARSET_NAME, strCharset); if (m_bMultipleStatements) ulClientFlags |= CLIENT_MULTI_STATEMENTS; + bool getServerPublicKeyOpt = (getServerPublicKey != 0); + mysql_options(m_handle, MYSQL_OPT_GET_SERVER_PUBLIC_KEY, &getServerPublicKeyOpt); if (mysql_real_connect(m_handle, strHostname, strUsername, strPassword, strDatabaseName, iPort, strUnixSocket, ulClientFlags)) m_bOpened = true; diff --git a/Server/dbconmy/premake5.lua b/Server/dbconmy/premake5.lua index 693b0b5829..0e7761c8dd 100644 --- a/Server/dbconmy/premake5.lua +++ b/Server/dbconmy/premake5.lua @@ -41,11 +41,16 @@ project "Dbconmy" includedirs { os.findheader("mysql.h", { "/usr/local/opt/mysql/include/mysql", + "/opt/homebrew/include/mysql", "/opt/osxcross/macports/pkgs/opt/local/include/mysql8/mysql", }) } libdirs { - os.findlib("libmysqlclient.a", "/opt/osxcross/macports/pkgs/opt/local/lib/mysql8/mysql") + os.findlib("libmysqlclient.a", { + "/usr/local/opt/mysql/lib", + "/opt/homebrew/lib", + "/opt/osxcross/macports/pkgs/opt/local/lib/mysql8/mysql", + }) } if GLIBC_COMPAT then @@ -66,8 +71,6 @@ project "Dbconmy" links { "../../vendor/mysql/lib/x64/libmysql.lib" } filter { "system:windows", "platforms:x86" } links { "../../vendor/mysql/lib/x86/libmysql.lib" } - filter { "system:windows", "platforms:arm" } - links { "../../vendor/mysql/lib/arm/libmysql.lib" } filter { "system:windows", "platforms:arm64" } links { "../../vendor/mysql/lib/arm64/libmysql.lib" } diff --git a/Server/launcher/Main.cpp b/Server/launcher/Main.cpp index dc24613491..3c02a939e8 100644 --- a/Server/launcher/Main.cpp +++ b/Server/launcher/Main.cpp @@ -84,6 +84,7 @@ int main(int argc, char* argv[]) printf(" -u Disable output buffering and flush instantly (useful for screenlog)\n"); #ifndef WIN32 printf(" -x Disable simplified crash reports (To allow core dumps)\n"); + printf(" --child-process Run server without output buffering and with a readyness event\n"); #endif printf(" -D [PATH] Use as base directory\n"); printf(" --config [FILE] Alternate mtaserver.conf file\n"); diff --git a/Server/mods/deathmatch/CServer.cpp b/Server/mods/deathmatch/CServer.cpp index a4bca0e9b8..d80f6a4509 100644 --- a/Server/mods/deathmatch/CServer.cpp +++ b/Server/mods/deathmatch/CServer.cpp @@ -96,6 +96,11 @@ void CServer::DoPulse() CLOCK(" Top", " Idle"); } +bool CServer::IsReadyToAcceptConnections() const noexcept +{ + return (m_pGame != nullptr) && m_pGame->IsServerFullyUp(); +} + bool CServer::IsFinished() { if (m_pGame) diff --git a/Server/mods/deathmatch/CServer.h b/Server/mods/deathmatch/CServer.h index f408206f8e..b345df6b66 100644 --- a/Server/mods/deathmatch/CServer.h +++ b/Server/mods/deathmatch/CServer.h @@ -28,6 +28,7 @@ class CServer : public CServerBase void GetTag(char* szInfoTag, int iInfoTag); void HandleInput(char* szCommand); + bool IsReadyToAcceptConnections() const noexcept override; bool IsFinished(); bool PendingWorkToDo(); bool GetSleepIntervals(int& iSleepBusyMs, int& iSleepIdleMs, int& iLogicFpsLimit); diff --git a/Server/mods/deathmatch/acl.xml b/Server/mods/deathmatch/acl.xml index 89031e9219..5e4d1292c3 100644 --- a/Server/mods/deathmatch/acl.xml +++ b/Server/mods/deathmatch/acl.xml @@ -21,6 +21,7 @@ + @@ -114,6 +115,8 @@ + + @@ -160,6 +163,8 @@ + + @@ -183,6 +188,8 @@ + + @@ -213,6 +220,8 @@ + + diff --git a/Server/mods/deathmatch/logic/CAccount.cpp b/Server/mods/deathmatch/logic/CAccount.cpp index 90e52e5696..73934a9f8b 100644 --- a/Server/mods/deathmatch/logic/CAccount.cpp +++ b/Server/mods/deathmatch/logic/CAccount.cpp @@ -210,7 +210,7 @@ void CAccount::EnsureLoadedSerialUsage() } } -bool CAccount::HasLoadedSerialUsage() +bool CAccount::HasLoadedSerialUsage() const { return m_bLoadedSerialUsage; } @@ -238,11 +238,7 @@ CAccount::SSerialUsage* CAccount::GetSerialUsage(const SString& strSerial) bool CAccount::IsSerialAuthorized(const SString& strSerial) { SSerialUsage* pInfo = GetSerialUsage(strSerial); - if (pInfo) - { - return pInfo->IsAuthorized(); - } - return false; + return pInfo ? pInfo->IsAuthorized() : false; } // @@ -265,17 +261,13 @@ bool CAccount::IsIpAuthorized(const SString& strIp) bool CAccount::AuthorizeSerial(const SString& strSerial, const SString& strWho) { SSerialUsage* pInfo = GetSerialUsage(strSerial); - if (pInfo) - { - if (!pInfo->IsAuthorized()) - { - pInfo->tAuthDate = time(nullptr); - pInfo->strAuthWho = strWho; - m_pManager->MarkAsChanged(this); - return true; - } - } - return false; + if (!pInfo || pInfo->IsAuthorized()) + return false; + + pInfo->tAuthDate = time(nullptr); + pInfo->strAuthWho = strWho; + m_pManager->MarkAsChanged(this); + return true; } // @@ -320,29 +312,28 @@ void CAccount::RemoveUnauthorizedSerials() bool CAccount::AddSerialForAuthorization(const SString& strSerial, const SString& strIp) { SSerialUsage* pInfo = GetSerialUsage(strSerial); - if (!pInfo) - { - // Only one new serial at a time, so remove all other unauthorized serials for this account - RemoveUnauthorizedSerials(); + if (pInfo) + return false; - SSerialUsage info; - info.strSerial = strSerial; - info.strAddedIp = strIp; - info.tAddedDate = time(nullptr); - info.tAuthDate = 0; - info.tLastLoginDate = 0; - info.tLastLoginHttpDate = 0; + // Only one new serial at a time, so remove all other unauthorized serials for this account + RemoveUnauthorizedSerials(); - // First one doesn't require authorization - if (m_SerialUsageList.size() == 0) - { - info.tAuthDate = time(nullptr); - } - m_SerialUsageList.push_back(info); - m_pManager->MarkAsChanged(this); - return true; + SSerialUsage info; + info.strSerial = strSerial; + info.strAddedIp = strIp; + info.tAddedDate = time(nullptr); + info.tAuthDate = 0; + info.tLastLoginDate = 0; + info.tLastLoginHttpDate = 0; + + // First one doesn't require authorization + if (m_SerialUsageList.size() == 0) + { + info.tAuthDate = time(nullptr); } - return false; + m_SerialUsageList.push_back(info); + m_pManager->MarkAsChanged(this); + return true; } // @@ -372,10 +363,10 @@ void CAccount::OnLoginHttpSuccess(const SString& strIp) EnsureLoadedSerialUsage(); for (auto& info : m_SerialUsageList) { - if (info.strLastLoginIp == strIp && info.IsAuthorized()) - { - info.tLastLoginHttpDate = time(nullptr); - m_pManager->MarkAsChanged(this); - } + if (info.strLastLoginIp != strIp || !info.IsAuthorized()) + continue; + + info.tLastLoginHttpDate = time(nullptr); + m_pManager->MarkAsChanged(this); } } diff --git a/Server/mods/deathmatch/logic/CAccount.h b/Server/mods/deathmatch/logic/CAccount.h index b2ea2f58e9..363dd57d98 100644 --- a/Server/mods/deathmatch/logic/CAccount.h +++ b/Server/mods/deathmatch/logic/CAccount.h @@ -71,25 +71,27 @@ class CAccount const std::string& strIP = "", const std::string& strSerial = "", const SString& strHttpPassAppend = ""); ~CAccount(); - bool IsRegistered() { return m_AccountType != EAccountType::Guest; } - bool IsConsoleAccount() { return m_AccountType == EAccountType::Console; } + bool IsRegistered() const { return m_AccountType != EAccountType::Guest; } + bool IsConsoleAccount() const { return m_AccountType == EAccountType::Console; } void OnLoginSuccess(const SString& strSerial, const SString& strIp); void OnLoginHttpSuccess(const SString& strIp); - const SString& GetName() { return m_strName; } + const SString& GetName() const { return m_strName; } void SetName(const std::string& strName); + const EAccountType GetType() const { return m_AccountType; } + void SetPassword(const SString& strPassword); bool IsPassword(const SString& strPassword, bool* pbUsedHttpPassAppend = nullptr); SString GetPasswordHash(); - const SString& GetHttpPassAppend() { return m_strHttpPassAppend; } + const SString& GetHttpPassAppend() const { return m_strHttpPassAppend; } void SetHttpPassAppend(const SString& strHttpPassAppend); - const std::string& GetIP() { return m_strIP; } - const std::string& GetSerial() { return m_strSerial; } - int GetID() { return m_iUserID; } + const std::string& GetIP() const { return m_strIP; } + const std::string& GetSerial() const { return m_strSerial; } + const int GetID() const { return m_iUserID; } - bool HasLoadedSerialUsage(); + bool HasLoadedSerialUsage() const; void EnsureLoadedSerialUsage(); std::vector& GetSerialUsageList(); SSerialUsage* GetSerialUsage(const SString& strSerial); @@ -100,19 +102,19 @@ class CAccount bool RemoveSerial(const SString& strSerial); void RemoveUnauthorizedSerials(); - CClient* GetClient() { return m_pClient; } + CClient* GetClient() const { return m_pClient; } void SetClient(CClient* pClient); void SetChanged(bool bChanged) { m_bChanged = bChanged; } - bool HasChanged() { return m_bChanged; } + bool HasChanged() const { return m_bChanged; } uint GetScriptID() const { return m_uiScriptID; } std::shared_ptr GetData(const std::string& strKey); bool SetData(const std::string& strKey, const std::string& strValue, int iType); bool HasData(const std::string& strKey); void RemoveData(const std::string& strKey); - std::map::iterator DataBegin() { return m_Data.begin(); } - std::map::iterator DataEnd() { return m_Data.end(); } + std::map::iterator begin() { return m_Data.begin(); } + std::map::iterator end() { return m_Data.end(); } protected: CAccountData* GetDataPointer(const std::string& strKey); @@ -147,9 +149,9 @@ class CAccountData m_iType = iType; } - const std::string& GetKey() { return m_strKey; } - const std::string& GetStrValue() { return m_strValue; } - int GetType() { return m_iType; } + const std::string& GetKey() const { return m_strKey; } + const std::string& GetStrValue() const { return m_strValue; } + int GetType() const { return m_iType; } void SetStrValue(const std::string& strValue) { m_strValue = strValue; } void SetType(int iType) { m_iType = iType; } diff --git a/Server/mods/deathmatch/logic/CAccountManager.cpp b/Server/mods/deathmatch/logic/CAccountManager.cpp index 99037771a0..cae195a3a3 100644 --- a/Server/mods/deathmatch/logic/CAccountManager.cpp +++ b/Server/mods/deathmatch/logic/CAccountManager.cpp @@ -18,6 +18,7 @@ #include "CIdArray.h" #include "CAccessControlListManager.h" #include "Utils.h" +#include "CMapManager.h" CAccountManager::CAccountManager(const SString& strDbPathFilename) : m_AccountProtect(6, 30000, 60000 * 1) // Max of 6 attempts per 30 seconds, then 1 minute ignore @@ -778,10 +779,9 @@ bool CAccountManager::CopyAccountData(CAccount* pFromAccount, CAccount* pToAccou if (!pFromAccount->IsRegistered()) // is not registered account, retrieve data from memory { - std::map::iterator iter = pFromAccount->DataBegin(); - for (; iter != pFromAccount->DataEnd(); iter++) + for (const auto& iter : *pFromAccount) { - MapSet(copiedData, iter->second.GetKey(), CAccountData(iter->second.GetKey(), iter->second.GetStrValue(), iter->second.GetType())); + MapSet(copiedData, iter.second.GetKey(), CAccountData(iter.second.GetKey(), iter.second.GetStrValue(), iter.second.GetType())); } } else // is registered account, retrieve from database @@ -850,31 +850,30 @@ bool CAccountManager::GetAllAccountData(CAccount* pAccount, lua_State* pLua) { if (!pAccount->IsRegistered()) { - std::map::iterator iter = pAccount->DataBegin(); - for (; iter != pAccount->DataEnd(); iter++) + for (const auto& iter : *pAccount) { - if (iter->second.GetType() == LUA_TNIL) + if (iter.second.GetType() == LUA_TNIL) { - lua_pushstring(pLua, iter->second.GetKey().c_str()); + lua_pushstring(pLua, iter.second.GetKey().c_str()); lua_pushnil(pLua); lua_settable(pLua, -3); } - if (iter->second.GetType() == LUA_TBOOLEAN) + if (iter.second.GetType() == LUA_TBOOLEAN) { - lua_pushstring(pLua, iter->second.GetKey().c_str()); - lua_pushboolean(pLua, iter->second.GetStrValue() == "true" ? true : false); + lua_pushstring(pLua, iter.second.GetKey().c_str()); + lua_pushboolean(pLua, iter.second.GetStrValue() == "true"); lua_settable(pLua, -3); } - if (iter->second.GetType() == LUA_TNUMBER) + if (iter.second.GetType() == LUA_TNUMBER) { - lua_pushstring(pLua, iter->second.GetKey().c_str()); - lua_pushnumber(pLua, strtod(iter->second.GetStrValue().c_str(), NULL)); + lua_pushstring(pLua, iter.second.GetKey().c_str()); + lua_pushnumber(pLua, strtod(iter.second.GetStrValue().c_str(), NULL)); lua_settable(pLua, -3); } else { - lua_pushstring(pLua, iter->second.GetKey().c_str()); - lua_pushstring(pLua, iter->second.GetStrValue().c_str()); + lua_pushstring(pLua, iter.second.GetKey().c_str()); + lua_pushstring(pLua, iter.second.GetStrValue().c_str()); lua_settable(pLua, -3); } } @@ -891,46 +890,44 @@ bool CAccountManager::GetAllAccountData(CAccount* pAccount, lua_State* pLua) m_pDatabaseManager->QueryWithResultf(m_hDbConnection, &result, "SELECT key,value,type from userdata where userid=?", SQLITE_INTEGER, iUserID); // Do we have any results? - if (result->nRows > 0) + if (result->nRows <= 0) + return false; + + // Loop through until i is the same as the number of rows + for (const auto& row : result->Data) { - // Loop through until i is the same as the number of rows - for (CRegistryResultIterator iter = result->begin(); iter != result->end(); ++iter) + // Get our key + strKey = reinterpret_cast(row[0].pVal); + // Get our type + int iType = static_cast(row[2].nVal); + // Account data is stored as text so we don't need to check what type it is just return it + if (iType == LUA_TNIL) { - const CRegistryResultRow& row = *iter; - // Get our key - strKey = (const char*)row[0].pVal; - // Get our type - int iType = static_cast(row[2].nVal); - // Account data is stored as text so we don't need to check what type it is just return it - if (iType == LUA_TNIL) - { - lua_pushstring(pLua, strKey); - lua_pushnil(pLua); - lua_settable(pLua, -3); - } - if (iType == LUA_TBOOLEAN) - { - SString strResult = (const char*)row[1].pVal; - lua_pushstring(pLua, strKey); - lua_pushboolean(pLua, strResult == "true" ? true : false); - lua_settable(pLua, -3); - } - if (iType == LUA_TNUMBER) - { - lua_pushstring(pLua, strKey); - lua_pushnumber(pLua, strtod((const char*)row[1].pVal, NULL)); - lua_settable(pLua, -3); - } - else - { - lua_pushstring(pLua, strKey); - lua_pushstring(pLua, ((const char*)row[1].pVal)); - lua_settable(pLua, -3); - } + lua_pushstring(pLua, strKey); + lua_pushnil(pLua); + lua_settable(pLua, -3); + } + if (iType == LUA_TBOOLEAN) + { + SString strResult = (const char*)row[1].pVal; + lua_pushstring(pLua, strKey); + lua_pushboolean(pLua, strResult == "true"); + lua_settable(pLua, -3); + } + if (iType == LUA_TNUMBER) + { + lua_pushstring(pLua, strKey); + lua_pushnumber(pLua, strtod((const char*)row[1].pVal, NULL)); + lua_settable(pLua, -3); + } + else + { + lua_pushstring(pLua, strKey); + lua_pushstring(pLua, ((const char*)row[1].pVal)); + lua_settable(pLua, -3); } - return true; } - return false; + return true; } void CAccountManager::GetAccountsBySerial(const SString& strSerial, std::vector& outAccounts) @@ -939,10 +936,8 @@ void CAccountManager::GetAccountsBySerial(const SString& strSerial, std::vector< CRegistryResult result; m_pDatabaseManager->QueryWithResultf(m_hDbConnection, &result, "SELECT name FROM accounts WHERE serial = ?", SQLITE_TEXT, strSerial.c_str()); - for (CRegistryResultIterator iter = result->begin(); iter != result->end(); ++iter) + for (const auto& row : result->Data) { - const CRegistryResultRow& row = *iter; - CAccount* pAccount = Get((const char*)row[0].pVal); if (pAccount) outAccounts.push_back(pAccount); @@ -955,10 +950,8 @@ void CAccountManager::GetAccountsByIP(const SString& strIP, std::vectorQueryWithResultf(m_hDbConnection, &result, "SELECT name FROM accounts WHERE ip = ?", SQLITE_TEXT, strIP.c_str()); - for (CRegistryResultIterator iter = result->begin(); iter != result->end(); ++iter) + for (const auto& row : result->Data) { - const CRegistryResultRow& row = *iter; - CAccount* pAccount = Get((const char*)row[0].pVal); if (pAccount) outAccounts.push_back(pAccount); @@ -970,10 +963,8 @@ CAccount* CAccountManager::GetAccountByID(int ID) CRegistryResult result; m_pDatabaseManager->QueryWithResultf(m_hDbConnection, &result, "SELECT name FROM accounts WHERE id = ?", SQLITE_INTEGER, ID); - for (CRegistryResultIterator iter = result->begin(); iter != result->end(); ++iter) + for (const auto& row : result->Data) { - const auto& row = *iter; - return Get(reinterpret_cast(row[0].pVal)); } @@ -988,39 +979,53 @@ void CAccountManager::GetAccountsByData(const SString& dataName, const SString& "SELECT acc.name FROM accounts acc, userdata dat WHERE dat.key = ? AND dat.value = ? AND dat.userid = acc.id", SQLITE_TEXT, dataName.c_str(), SQLITE_TEXT, value.c_str()); - for (CRegistryResultIterator iter = result->begin(); iter != result->end(); ++iter) + for (const auto& row : result->Data) { - const CRegistryResultRow& row = *iter; - CAccount* pAccount = Get((const char*)row[0].pVal); if (pAccount) outAccounts.push_back(pAccount); } } +// Fires for all joining players CAccount* CAccountManager::AddGuestAccount(const SString& strName) { - CAccount* pAccount = new CAccount(this, EAccountType::Guest, strName); + CAccount* pAccount = new CAccount(this, EAccountType::Guest, strName); + CLuaArguments Arguments; + Arguments.PushAccount(pAccount); + g_pGame->GetMapManager()->GetRootElement()->CallEvent("onAccountCreate", Arguments); return pAccount; } +// Fires only when console is created CAccount* CAccountManager::AddConsoleAccount(const SString& strName) { - CAccount* pAccount = new CAccount(this, EAccountType::Console, strName); + CAccount* pAccount = new CAccount(this, EAccountType::Console, strName); + CLuaArguments Arguments; + Arguments.PushAccount(pAccount); + g_pGame->GetMapManager()->GetRootElement()->CallEvent("onAccountCreate", Arguments); return pAccount; } +// Fires for all created player accounts CAccount* CAccountManager::AddPlayerAccount(const SString& strName, const SString& strPassword, int iUserID, const SString& strIP, const SString& strSerial, const SString& strHttpPassAppend) { CAccount* pAccount = new CAccount(this, EAccountType::Player, strName, strPassword, iUserID, strIP, strSerial, strHttpPassAppend); + CLuaArguments Arguments; + Arguments.PushAccount(pAccount); + g_pGame->GetMapManager()->GetRootElement()->CallEvent("onAccountCreate", Arguments); return pAccount; } +// Fires whenever "addaccount" or "addAccount" was executed CAccount* CAccountManager::AddNewPlayerAccount(const SString& strName, const SString& strPassword) { CAccount* pAccount = new CAccount(this, EAccountType::Player, strName, strPassword, ++m_iAccounts); Save(pAccount); + CLuaArguments Arguments; + Arguments.PushAccount(pAccount); + g_pGame->GetMapManager()->GetRootElement()->CallEvent("onAccountCreate", Arguments); return pAccount; } @@ -1035,6 +1040,9 @@ bool CAccountManager::RemoveAccount(CAccount* pAccount) m_pDatabaseManager->Execf(m_hDbConnection, "DELETE FROM userdata WHERE userid=?", SQLITE_INTEGER, iUserID); m_pDatabaseManager->Execf(m_hDbConnection, "DELETE FROM serialusage WHERE userid=?", SQLITE_INTEGER, iUserID); } + CLuaArguments Arguments; + Arguments.PushAccount(pAccount); + g_pGame->GetMapManager()->GetRootElement()->CallEvent("onAccountRemove", Arguments); delete pAccount; return true; } @@ -1055,22 +1063,21 @@ void CAccountManager::StaticDbCallback(CDbJobData* pJobData, void* pContext) void CAccountManager::DbCallback(CDbJobData* pJobData) { - if (m_pDatabaseManager->QueryPoll(pJobData, 0)) + if (!m_pDatabaseManager->QueryPoll(pJobData, 0)) { - if (pJobData->result.status == EJobResult::FAIL) - { - CLogger::LogPrintf("ERROR: While updating account with '%s': %s.\n", *pJobData->GetCommandStringForLog(), *pJobData->result.strReason); - if (pJobData->result.strReason.ContainsI("missing database")) - { - // Try reconnection - CLogger::LogPrintf("INFO: Reconnecting to accounts database\n"); - ReconnectToDatabase(); - } - } + CLogger::LogPrintf("ERROR: Something worrying happened in DbCallback '%s': %s.\n", *pJobData->GetCommandStringForLog(), *pJobData->result.strReason); + return; } - else + + if (pJobData->result.status != EJobResult::FAIL) + return; + + CLogger::LogPrintf("ERROR: While updating account with '%s': %s.\n", *pJobData->GetCommandStringForLog(), *pJobData->result.strReason); + if (pJobData->result.strReason.ContainsI("missing database")) { - CLogger::LogPrintf("ERROR: Something worrying happened in DbCallback '%s': %s.\n", *pJobData->GetCommandStringForLog(), *pJobData->result.strReason); + // Try reconnection + CLogger::LogPrintf("INFO: Reconnecting to accounts database\n"); + ReconnectToDatabase(); } } @@ -1079,9 +1086,7 @@ void CAccountManager::DbCallback(CDbJobData* pJobData) // bool CAccountManager::IsValidAccountName(const SString& strName) { - if (strName.length() < MIN_USERNAME_LENGTH) - return false; - return true; + return strName.length() >= MIN_USERNAME_LENGTH; } // @@ -1089,9 +1094,7 @@ bool CAccountManager::IsValidAccountName(const SString& strName) // bool CAccountManager::IsValidPassword(const SString& strPassword) { - if (strPassword.length() < MIN_PASSWORD_LENGTH) - return false; - return true; + return strPassword.length() >= MIN_PASSWORD_LENGTH; } // @@ -1142,12 +1145,8 @@ bool CAccountManager::IsAuthorizedSerialRequired(CAccount* pAccount) // bool CAccountManager::IsHttpLoginAllowed(CAccount* pAccount, const SString& strIp) { - if (!g_pGame->GetConfig()->GetAuthSerialHttpEnabled() || g_pGame->GetConfig()->IsAuthSerialHttpIpException(strIp) || - !IsAuthorizedSerialRequired(pAccount) || pAccount->IsIpAuthorized(strIp)) - { - return true; - } - return false; + return !g_pGame->GetConfig()->GetAuthSerialHttpEnabled() || g_pGame->GetConfig()->IsAuthSerialHttpIpException(strIp) || + !IsAuthorizedSerialRequired(pAccount) || pAccount->IsIpAuthorized(strIp); } // @@ -1173,9 +1172,8 @@ void CAccountManager::LoadAccountSerialUsage(CAccount* pAccount) " WHERE userid=?", SQLITE_INTEGER, pAccount->GetID()); - for (CRegistryResultIterator iter = result->begin(); iter != result->end(); ++iter) + for (const auto& row : result->Data) { - const CRegistryResultRow& row = *iter; outSerialUsageList.push_back(CAccount::SSerialUsage()); CAccount::SSerialUsage& info = outSerialUsageList.back(); info.strSerial = (const char*)row[0].pVal; diff --git a/Server/mods/deathmatch/logic/CConsoleCommands.cpp b/Server/mods/deathmatch/logic/CConsoleCommands.cpp index 119f09af1d..5f19e566f3 100644 --- a/Server/mods/deathmatch/logic/CConsoleCommands.cpp +++ b/Server/mods/deathmatch/logic/CConsoleCommands.cpp @@ -596,8 +596,10 @@ bool CConsoleCommands::Msg(CConsole* pConsole, const char* szInArguments, CClien // Send the message and player pointer to the script CLuaArguments Arguments; - Arguments.PushString(szArguments); + Arguments.PushString(szArguments); // We don't want to remove this for backwards compatibility reasons Arguments.PushElement(pPlayer); + Arguments.PushString(szMessage); // Fix #2135 + bool bContinue = pSender->CallEvent("onPlayerPrivateMessage", Arguments); if (bContinue) { @@ -1236,62 +1238,51 @@ bool CConsoleCommands::WhoIs(CConsole* pConsole, const char* szArguments, CClien return false; } -bool CConsoleCommands::DebugScript(CConsole* pConsole, const char* szArguments, CClient* pClient, CClient* pEchoClient) +bool CConsoleCommands::DebugScript(CConsole* console, const char* arguments, CClient* client, CClient* echoClient) { - // Valid parameter? - if (szArguments && szArguments[0] != 0 && szArguments[1] == 0) + static constexpr const char* syntaxMessage = "debugscript: Syntax is 'debugscript '"; + + // Validate arguments + if (!arguments || std::strlen(arguments) != 1 || !std::isdigit(arguments[0])) { - // Player? - if (pClient->GetClientType() == CClient::CLIENT_PLAYER) - { - CPlayer* pPlayer = static_cast(pClient); + echoClient->SendEcho(syntaxMessage); + return false; + } - // Convert to number - int iLevel = atoi(szArguments); - if (iLevel == 0 && strcmp(szArguments, "0") != 0) - { - pEchoClient->SendEcho("debugscript: Syntax is 'debugscript '"); - return false; - } - if (iLevel != (int)pPlayer->GetScriptDebugLevel()) - { - // Between 0 and 3? - if (iLevel >= 0 && iLevel <= 3) - { - // Set the new level - pPlayer->SetScriptDebugLevel(iLevel); + // Check client type + if (client->GetClientType() != CClient::CLIENT_PLAYER) + { + echoClient->SendConsole("debugscript: Incorrect client type for this command"); + return false; + } - // Tell the player and the console - pEchoClient->SendEcho(SString("debugscript: Your debug mode was set to %i", iLevel)); - CLogger::LogPrintf("SCRIPT: %s set their script debug mode to %i\n", GetAdminNameForLog(pClient).c_str(), iLevel); + CPlayer* player = static_cast(client); + int debugLevel = arguments[0] - '0'; // Convert the character to an integer (e.g., '2' -> 2) + int debugLevelCurrent = player->GetScriptDebugLevel(); - // Enable/Disable their debugger - if (iLevel == 0) - CStaticFunctionDefinitions::SetPlayerDebuggerVisible(pPlayer, false); - else - CStaticFunctionDefinitions::SetPlayerDebuggerVisible(pPlayer, true); - } - else - { - pEchoClient->SendEcho("debugscript: Modes available are 0 (None), 1 (Errors), 2 (Errors + Warnings), 3 (All)"); - } - } - else - { - pEchoClient->SendEcho("debugscript: Your debug mode is already that"); - } - } - else - { - pEchoClient->SendConsole("debugscript: Incorrect client type for this command"); - } + // Check if the level is the same + if (debugLevel == debugLevelCurrent) + { + echoClient->SendEcho(("debugscript: Your debug mode is already set to " + std::to_string(debugLevel)).c_str()); + return false; } - else + + // Check if the level is between 0 and 3 + if (debugLevel < 0 || debugLevel > 3) { - pEchoClient->SendEcho("debugscript: Syntax is 'debugscript '"); + echoClient->SendEcho(syntaxMessage); + return false; } - return false; + // Set the new level + player->SetScriptDebugLevel(debugLevel); + echoClient->SendEcho(("debugscript: Your debug mode was set to " + std::to_string(debugLevel)).c_str()); + CLogger::LogPrintf("SCRIPT: %s set their script debug mode to %d\n", GetAdminNameForLog(client).c_str(), debugLevel); + + // Enable or disable the debugger based on the level + CStaticFunctionDefinitions::SetPlayerDebuggerVisible(player, debugLevel != 0); + + return true; } bool CConsoleCommands::Help(CConsole* pConsole, const char* szArguments, CClient* pClient, CClient* pEchoClient) diff --git a/Server/mods/deathmatch/logic/CGame.cpp b/Server/mods/deathmatch/logic/CGame.cpp index 407cc95592..58989394ec 100644 --- a/Server/mods/deathmatch/logic/CGame.cpp +++ b/Server/mods/deathmatch/logic/CGame.cpp @@ -1,11 +1,11 @@ /***************************************************************************** * - * PROJECT: Multi Theft Auto v1.0 + * PROJECT: Multi Theft Auto * LICENSE: See LICENSE in the top level directory - * FILE: mods/deathmatch/logic/CGame.cpp + * FILE: Server/mods/deathmatch/logic/CGame.cpp * PURPOSE: Server game class * - * Multi Theft Auto is available from http://www.multitheftauto.com/ + * Multi Theft Auto is available from https://multitheftauto.com/ * *****************************************************************************/ @@ -59,6 +59,7 @@ #include "packets/CPlayerListPacket.h" #include "packets/CPlayerClothesPacket.h" #include "packets/CServerInfoSyncPacket.h" +#include "packets/CLuaPacket.h" #include "../utils/COpenPortsTester.h" #include "../utils/CMasterServerAnnouncer.h" #include "../utils/CHqComms.h" @@ -71,12 +72,19 @@ #include "net/SimHeaders.h" #include -#define MAX_BULLETSYNC_DISTANCE 400.0f -#define MAX_EXPLOSION_SYNC_DISTANCE 400.0f +#define MAX_BULLETSYNC_DISTANCE 400.0f +#define MAX_EXPLOSION_SYNC_DISTANCE 400.0f #define MAX_PROJECTILE_SYNC_DISTANCE 400.0f -#define RELEASE_MIN_CLIENT_VERSION "1.6.0-0.00000" -#define FIREBALLDESTRUCT_MIN_CLIENT_VERSION "1.6.0-9.22199" +#define RELEASE_MIN_CLIENT_VERSION "1.6.0-0.00000" +#define FIREBALLDESTRUCT_MIN_CLIENT_VERSION "1.6.0-9.22199" + +#define DEFAULT_GRAVITY 0.008f +#define DEFAULT_GAME_SPEED 1.0f +#define DEFAULT_JETPACK_MAXHEIGHT 100 +#define DEFAULT_AIRCRAFT_MAXHEIGHT 800 +#define DEFAULT_AIRCRAFT_MAXVELOCITY 1.5f +#define DEFAULT_MINUTE_DURATION 1000 #ifndef WIN32 #include @@ -246,6 +254,9 @@ CGame::CGame() : m_FloodProtect(4, 30000, 30000) // Max of 4 connecti m_WorldSpecialProps[WorldSpecialProperty::WATERCREATURES] = true; m_WorldSpecialProps[WorldSpecialProperty::BURNFLIPPEDCARS] = true; m_WorldSpecialProps[WorldSpecialProperty::FIREBALLDESTRUCT] = true; + m_WorldSpecialProps[WorldSpecialProperty::EXTENDEDWATERCANNONS] = true; + m_WorldSpecialProps[WorldSpecialProperty::ROADSIGNSTEXT] = true; + m_WorldSpecialProps[WorldSpecialProperty::TUNNELWEATHERBLEND] = true; m_JetpackWeapons[WEAPONTYPE_MICRO_UZI] = true; m_JetpackWeapons[WEAPONTYPE_TEC9] = true; @@ -403,14 +414,14 @@ CGame::~CGame() // Clear our global pointer g_pGame = NULL; - // Remove our console control handler - #ifdef WIN32 +// Remove our console control handler +#ifdef WIN32 SetConsoleCtrlHandler(ConsoleEventHandler, FALSE); - #else +#else signal(SIGTERM, SIG_DFL); signal(SIGINT, SIG_DFL); signal(SIGPIPE, SIG_DFL); - #endif +#endif } void CGame::GetTag(char* szInfoTag, int iInfoTag) @@ -528,6 +539,8 @@ void CGame::DoPulse() // Process our resource stop/restart queue CLOCK_CALL1(m_pResourceManager->ProcessQueue();); + ProcessClientTriggeredEventSpam(); + // Delete all items requested CLOCK_CALL1(m_ElementDeleter.DoDeleteAll();); @@ -654,9 +667,9 @@ bool CGame::Start(int iArgumentCount, char* szArguments[]) // Encrypt crash dumps for uploading HandleCrashDumpEncryption(); - // Check Windows server is using correctly compiled Lua dll - #ifndef MTA_DEBUG - #ifdef WIN32 +// Check Windows server is using correctly compiled Lua dll +#ifndef MTA_DEBUG + #ifdef WIN32 HMODULE hModule = LoadLibrary("lua5.1.dll"); // Release server should not have this function PVOID pFunc = static_cast(GetProcAddress(hModule, "luaX_is_apicheck_enabled")); @@ -666,8 +679,8 @@ bool CGame::Start(int iArgumentCount, char* szArguments[]) CLogger::ErrorPrintf("Problem with Lua dll\n"); return false; } - #endif #endif +#endif // Read some settings m_pACLManager->SetFileName(m_pMainConfig->GetAccessControlListFile().c_str()); @@ -877,16 +890,16 @@ bool CGame::Start(int iArgumentCount, char* szArguments[]) m_pPlayerManager->SetScriptDebugging(m_pScriptDebugging); - // Set our console control handler - #ifdef WIN32 +// Set our console control handler +#ifdef WIN32 SetConsoleCtrlHandler(ConsoleEventHandler, TRUE); - // Hide the close box - // DeleteMenu ( GetSystemMenu ( GetConsoleWindow(), FALSE ), SC_CLOSE, MF_BYCOMMAND ); - #else +// Hide the close box +// DeleteMenu ( GetSystemMenu ( GetConsoleWindow(), FALSE ), SC_CLOSE, MF_BYCOMMAND ); +#else signal(SIGTERM, &sighandler); signal(SIGINT, &sighandler); signal(SIGPIPE, SIG_IGN); - #endif +#endif // Add our builtin events AddBuiltInEvents(); @@ -1306,13 +1319,17 @@ void CGame::JoinPlayer(CPlayer& Player) marker.Set("Start"); // Let him join - Player.Send(CPlayerJoinCompletePacket( - Player.GetID(), m_pMapManager->GetRootElement()->GetID(), m_pMainConfig->GetHTTPDownloadType(), m_pMainConfig->GetHTTPPort(), - m_pMainConfig->GetHTTPDownloadURL().c_str(), m_pMainConfig->GetHTTPMaxConnectionsPerClient(), m_pMainConfig->GetEnableClientChecks(), - m_pMainConfig->IsVoiceEnabled(), m_pMainConfig->GetVoiceSampleRate(), m_pMainConfig->GetVoiceQuality(), m_pMainConfig->GetVoiceBitrate(), m_pMainConfig->GetServerName().c_str())); + Player.Send(CPlayerJoinCompletePacket(Player.GetID(), m_pMapManager->GetRootElement()->GetID(), m_pMainConfig->GetHTTPDownloadType(), + m_pMainConfig->GetHTTPPort(), m_pMainConfig->GetHTTPDownloadURL().c_str(), + m_pMainConfig->GetHTTPMaxConnectionsPerClient(), m_pMainConfig->GetEnableClientChecks(), + m_pMainConfig->IsVoiceEnabled(), m_pMainConfig->GetVoiceSampleRate(), m_pMainConfig->GetVoiceQuality(), + m_pMainConfig->GetVoiceBitrate(), m_pMainConfig->GetServerName().c_str())); marker.Set("CPlayerJoinCompletePacket"); + // Sync up server info on entry + Player.Send(CServerInfoSyncPacket(SERVER_INFO_FLAG_ALL)); + // Add debug info if wanted if (CPerfStatDebugInfo::GetSingleton()->IsActive("PlayerInGameNotice")) CPerfStatDebugInfo::GetSingleton()->AddLine("PlayerInGameNotice", marker.GetString()); @@ -1530,6 +1547,7 @@ void CGame::AddBuiltInEvents() m_Events.AddEvent("onResourcePreStart", "resource", NULL, false); m_Events.AddEvent("onResourceStart", "resource", NULL, false); m_Events.AddEvent("onResourceStop", "resource, deleted", NULL, false); + m_Events.AddEvent("onResourceStateChange", "resource, oldState, newState", nullptr, false); m_Events.AddEvent("onResourceLoadStateChange", "resource, oldState, newState", NULL, false); // Blip events @@ -1560,7 +1578,7 @@ void CGame::AddBuiltInEvents() m_Events.AddEvent("onPlayerQuit", "reason", NULL, false); m_Events.AddEvent("onPlayerSpawn", "spawnpoint, team", NULL, false); m_Events.AddEvent("onPlayerTarget", "target", NULL, false); - m_Events.AddEvent("onPlayerWasted", "ammo, killer, weapon, bodypart", NULL, false); + m_Events.AddEvent("onPlayerWasted", "ammo, killer, weapon, bodypart, isStealth, animGroup, animID", nullptr, false); m_Events.AddEvent("onPlayerWeaponSwitch", "previous, current", NULL, false); m_Events.AddEvent("onPlayerMarkerHit", "marker, matchingDimension", NULL, false); m_Events.AddEvent("onPlayerMarkerLeave", "marker, matchingDimension", NULL, false); @@ -1585,11 +1603,14 @@ void CGame::AddBuiltInEvents() m_Events.AddEvent("onPlayerResourceStart", "resource", NULL, false); m_Events.AddEvent("onPlayerProjectileCreation", "weaponType, posX, posY, posZ, force, target, rotX, rotY, rotZ, velX, velY, velZ", nullptr, false); m_Events.AddEvent("onPlayerDetonateSatchels", "", nullptr, false); + m_Events.AddEvent("onPlayerTriggerEventThreshold", "", nullptr, false); + m_Events.AddEvent("onPlayerTeamChange", "oldTeam, newTeam", nullptr, false); + m_Events.AddEvent("onPlayerTriggerInvalidEvent", "eventName, isAdded, isRemote", nullptr, false); // Ped events m_Events.AddEvent("onPedVehicleEnter", "vehicle, seat, jacked", NULL, false); m_Events.AddEvent("onPedVehicleExit", "vehicle, reason, jacker", NULL, false); - m_Events.AddEvent("onPedWasted", "ammo, killer, weapon, bodypart", NULL, false); + m_Events.AddEvent("onPedWasted", "ammo, killer, weapon, bodypart, isStealth, animGroup, animID", nullptr, false); m_Events.AddEvent("onPedWeaponSwitch", "previous, current", NULL, false); m_Events.AddEvent("onPedDamage", "loss", NULL, false); @@ -1620,7 +1641,7 @@ void CGame::AddBuiltInEvents() m_Events.AddEvent("onVehicleStartExit", "player, seat, jacker", NULL, false); m_Events.AddEvent("onVehicleEnter", "player, seat, jacked", NULL, false); m_Events.AddEvent("onVehicleExit", "player, seat, jacker", NULL, false); - m_Events.AddEvent("onVehicleExplode", "", NULL, false); + m_Events.AddEvent("onVehicleExplode", "withExplosion, player", nullptr, false); // Console events m_Events.AddEvent("onConsole", "text", NULL, false); @@ -1635,6 +1656,9 @@ void CGame::AddBuiltInEvents() // Account events m_Events.AddEvent("onAccountDataChange", "account, key, value", NULL, false); + m_Events.AddEvent("onAccountCreate", "account", NULL, false); + m_Events.AddEvent("onAccountRemove", "account", NULL, false); + // Other events m_Events.AddEvent("onSettingChange", "setting, oldValue, newValue", NULL, false); m_Events.AddEvent("onChatMessage", "message, element", NULL, false); @@ -1749,13 +1773,13 @@ void CGame::Packet_PlayerJoinData(CPlayerJoinDataPacket& Packet) strExtra = SStringX(strExtraTemp); strPlayerVersion = SStringX(strPlayerVersionTemp); } - #if MTASA_VERSION_TYPE < VERSION_TYPE_UNSTABLE +#if MTASA_VERSION_TYPE < VERSION_TYPE_UNSTABLE if (atoi(ExtractVersionStringBuildNumber(Packet.GetPlayerVersion())) != 0) { // Use player version from packet if it contains a valid build number strPlayerVersion = Packet.GetPlayerVersion(); } - #endif +#endif SString strIP = pPlayer->GetSourceIP(); SString strIPAndSerial("IP: %s Serial: %s Version: %s", strIP.c_str(), strSerial.c_str(), strPlayerVersion.c_str()); @@ -1811,8 +1835,6 @@ void CGame::Packet_PlayerJoinData(CPlayerJoinDataPacket& Packet) pPlayer->SetSerial(strExtra, 1); pPlayer->SetPlayerVersion(strPlayerVersion); - pPlayer->Send(CServerInfoSyncPacket(EServerInfoSyncFlag::SERVER_INFO_FLAG_MAX_PLAYERS)); - // Check if client must update if (IsBelowMinimumClient(pPlayer->GetPlayerVersion()) && !pPlayer->ShouldIgnoreMinClientVersionChecks()) { @@ -1893,7 +1915,7 @@ void CGame::Packet_PlayerJoinData(CPlayerJoinDataPacket& Packet) return; } - #if MTASA_VERSION_TYPE > VERSION_TYPE_UNSTABLE +#if MTASA_VERSION_TYPE > VERSION_TYPE_UNSTABLE if (Packet.GetPlayerVersion().length() > 0 && Packet.GetPlayerVersion() != pPlayer->GetPlayerVersion()) { // Tell the console @@ -1903,7 +1925,7 @@ void CGame::Packet_PlayerJoinData(CPlayerJoinDataPacket& Packet) DisconnectPlayer(this, *pPlayer, CPlayerDisconnectedPacket::VERSION_MISMATCH); return; } - #endif +#endif PlayerCompleteConnect(pPlayer); } @@ -2031,6 +2053,8 @@ void CGame::Packet_PedWasted(CPedWastedPacket& Packet) else Arguments.PushBoolean(false); Arguments.PushBoolean(false); + Arguments.PushNumber(Packet.m_AnimGroup); + Arguments.PushNumber(Packet.m_AnimID); pPed->CallEvent("onPedWasted", Arguments); // Reset the weapons list, because a ped loses his weapons on death @@ -2091,6 +2115,8 @@ void CGame::Packet_PlayerWasted(CPlayerWastedPacket& Packet) else Arguments.PushBoolean(false); Arguments.PushBoolean(false); + Arguments.PushNumber(Packet.m_AnimGroup); + Arguments.PushNumber(Packet.m_AnimID); pPlayer->CallEvent("onPlayerWasted", Arguments); // Reset the weapons list, because a player loses his weapons on death @@ -2293,11 +2319,6 @@ void CGame::Packet_PlayerPuresync(CPlayerPuresyncPacket& Packet) if ((pPlayer->GetPuresyncCount() % 4) == 0) pPlayer->Send(CReturnSyncPacket(pPlayer)); - // Send a server info sync packet to the player - // Only every 512 packets - if ((pPlayer->GetPuresyncCount() % 512) == 0) - pPlayer->Send(CServerInfoSyncPacket(EServerInfoSyncFlag::SERVER_INFO_FLAG_MAX_PLAYERS)); - CLOCK("PlayerPuresync", "RelayPlayerPuresync"); // Relay to other players RelayPlayerPuresync(Packet); @@ -2439,6 +2460,10 @@ void CGame::Packet_Bulletsync(CBulletsyncPacket& Packet) CPlayer* pPlayer = Packet.GetSourcePlayer(); if (pPlayer && pPlayer->IsJoined()) { + // Early return when the player attempts to fire a weapon they do not have + if (!pPlayer->HasWeaponType(Packet.m_WeaponType)) + return; + // Relay to other players RelayNearbyPacket(Packet); @@ -2563,11 +2588,28 @@ void CGame::Packet_LuaEvent(CLuaEventPacket& Packet) pElement->CallEvent(szName, *pArguments, pCaller); } else + { + CLuaArguments arguments; + arguments.PushString(szName); + arguments.PushBoolean(true); + arguments.PushBoolean(false); + pCaller->CallEvent("onPlayerTriggerInvalidEvent", arguments); m_pScriptDebugging->LogError(NULL, "Client (%s) triggered serverside event %s, but event is not marked as remotely triggerable", pCaller->GetNick(), szName); + } + } - else - m_pScriptDebugging->LogError(NULL, "Client (%s) triggered serverside event %s, but event is not added serverside", pCaller->GetNick(), szName); + else + { + CLuaArguments arguments; + arguments.PushString(szName); + arguments.PushBoolean(false); + arguments.PushBoolean(false); + pCaller->CallEvent("onPlayerTriggerInvalidEvent", arguments); + m_pScriptDebugging->LogError(NULL, "Client (%s) triggered serverside event %s, but event is not added serverside", pCaller->GetNick(), szName); + } + + RegisterClientTriggeredEventUsage(pCaller); } } @@ -2711,6 +2753,7 @@ void CGame::Packet_ExplosionSync(CExplosionSyncPacket& Packet) { CLuaArguments arguments; arguments.PushBoolean(!Packet.m_blowVehicleWithoutExplosion); + arguments.PushElement(clientSource); vehicle->CallEvent("onVehicleExplode", arguments); } @@ -2785,23 +2828,23 @@ void CGame::Packet_ProjectileSync(CProjectileSyncPacket& Packet) } CLuaArguments arguments; - arguments.PushNumber(Packet.m_ucWeaponType); // "weaponType" - arguments.PushNumber(vecPosition.fX); // "posX" - arguments.PushNumber(vecPosition.fY); // "posY" - arguments.PushNumber(vecPosition.fZ); // "posZ" - arguments.PushNumber(Packet.m_fForce); // "force" + arguments.PushNumber(Packet.m_ucWeaponType); // "weaponType" + arguments.PushNumber(vecPosition.fX); // "posX" + arguments.PushNumber(vecPosition.fY); // "posY" + arguments.PushNumber(vecPosition.fZ); // "posZ" + arguments.PushNumber(Packet.m_fForce); // "force" CElement* pTarget = nullptr; if (Packet.m_bHasTarget && Packet.m_TargetID != INVALID_ELEMENT_ID) pTarget = CElementIDs::GetElement(Packet.m_TargetID); - arguments.PushElement(pTarget); // "target" - arguments.PushNumber(Packet.m_vecRotation.fX); // "rotX" - arguments.PushNumber(Packet.m_vecRotation.fY); // "rotY" - arguments.PushNumber(Packet.m_vecRotation.fZ); // "rotZ" - arguments.PushNumber(Packet.m_vecMoveSpeed.fX); // "velX" - arguments.PushNumber(Packet.m_vecMoveSpeed.fY); // "velY" - arguments.PushNumber(Packet.m_vecMoveSpeed.fZ); // "velZ" + arguments.PushElement(pTarget); // "target" + arguments.PushNumber(Packet.m_vecRotation.fX); // "rotX" + arguments.PushNumber(Packet.m_vecRotation.fY); // "rotY" + arguments.PushNumber(Packet.m_vecRotation.fZ); // "rotZ" + arguments.PushNumber(Packet.m_vecMoveSpeed.fX); // "velX" + arguments.PushNumber(Packet.m_vecMoveSpeed.fY); // "velY" + arguments.PushNumber(Packet.m_vecMoveSpeed.fZ); // "velZ" // Trigger Lua event and see if we are allowed to continue if (!pPlayer->CallEvent("onPlayerProjectileCreation", arguments)) @@ -3630,6 +3673,7 @@ void CGame::Packet_Vehicle_InOut(CVehicleInOutPacket& Packet) if (pPed->GetVehicleAction() == CPed::VEHICLEACTION_JACKING) { unsigned char ucDoor = Packet.GetDoor(); + unsigned char ucOccupiedSeat = pPed->GetOccupiedVehicleSeat(); float fAngle = Packet.GetDoorAngle(); CPed* pJacked = pVehicle->GetOccupant(0); @@ -3663,6 +3707,29 @@ void CGame::Packet_Vehicle_InOut(CVehicleInOutPacket& Packet) CVehicleInOutPacket JackedReply(pJacked->GetID(), VehicleID, 0, VEHICLE_NOTIFY_OUT_RETURN); m_pPlayerManager->BroadcastOnlyJoined(JackedReply); + CLuaArguments Arguments; + Arguments.PushElement(pVehicle); // vehicle + Arguments.PushNumber(ucOccupiedSeat); // seat + Arguments.PushElement(pPed); // jacker + Arguments.PushBoolean(false); // forcedByScript + + if (pJacked->IsPlayer()) + { + pJacked->CallEvent("onPlayerVehicleExit", Arguments); + } + else + { + pJacked->CallEvent("onPedVehicleExit", Arguments); + } + + CLuaArguments Arguments2; + Arguments2.PushElement(pJacked); // jacked + Arguments2.PushNumber(ucOccupiedSeat); // seat + Arguments2.PushElement(pPed); // jacker + Arguments2.PushBoolean(false); // forcedByScript + + pVehicle->CallEvent("onVehicleExit", Arguments2); + if (!sendListIncompatiblePlayers.empty()) { // Warp the ped out of the vehicle manually for incompatible players @@ -4329,6 +4396,111 @@ void CGame::SetJetpackWeaponEnabled(eWeaponType weaponType, bool bEnabled) } } +void CGame::ResetWorldProperties(const ResetWorldPropsInfo& resetPropsInfo) +{ + // Reset all setWorldSpecialPropertyEnabled to default + if (resetPropsInfo.resetSpecialProperties) + { + g_pGame->SetWorldSpecialPropertyEnabled(WorldSpecialProperty::HOVERCARS, false); + g_pGame->SetWorldSpecialPropertyEnabled(WorldSpecialProperty::AIRCARS, false); + g_pGame->SetWorldSpecialPropertyEnabled(WorldSpecialProperty::EXTRABUNNY, false); + g_pGame->SetWorldSpecialPropertyEnabled(WorldSpecialProperty::EXTRAJUMP, false); + g_pGame->SetWorldSpecialPropertyEnabled(WorldSpecialProperty::RANDOMFOLIAGE, true); + g_pGame->SetWorldSpecialPropertyEnabled(WorldSpecialProperty::SNIPERMOON, false); + g_pGame->SetWorldSpecialPropertyEnabled(WorldSpecialProperty::EXTRAAIRRESISTANCE, true); + g_pGame->SetWorldSpecialPropertyEnabled(WorldSpecialProperty::UNDERWORLDWARP, true); + g_pGame->SetWorldSpecialPropertyEnabled(WorldSpecialProperty::VEHICLESUNGLARE, false); + g_pGame->SetWorldSpecialPropertyEnabled(WorldSpecialProperty::CORONAZTEST, true); + g_pGame->SetWorldSpecialPropertyEnabled(WorldSpecialProperty::WATERCREATURES, true); + g_pGame->SetWorldSpecialPropertyEnabled(WorldSpecialProperty::BURNFLIPPEDCARS, true); + g_pGame->SetWorldSpecialPropertyEnabled(WorldSpecialProperty::FIREBALLDESTRUCT, true); + g_pGame->SetWorldSpecialPropertyEnabled(WorldSpecialProperty::ROADSIGNSTEXT, true); + g_pGame->SetWorldSpecialPropertyEnabled(WorldSpecialProperty::EXTENDEDWATERCANNONS, true); + g_pGame->SetWorldSpecialPropertyEnabled(WorldSpecialProperty::TUNNELWEATHERBLEND, true); + } + + // Reset all weather stuff like heat haze, wind velocity etc + if (resetPropsInfo.resetWeatherProperties) + { + g_pGame->SetHasHeatHaze(false); + g_pGame->SetHasFogDistance(false); + g_pGame->SetHasMoonSize(false); + g_pGame->SetHasSkyGradient(false); + g_pGame->SetHasSunColor(false); + g_pGame->SetHasSunSize(false); + g_pGame->SetHasWindVelocity(false); + + float defaultRainLevel = 0.0f; + g_pGame->SetRainLevel(defaultRainLevel); + g_pGame->SetHasRainLevel(false); + } + + // Restore interiors sounds + if (resetPropsInfo.resetSounds) + g_pGame->SetInteriorSoundsEnabled(true); + + // Disable all glitches + if (resetPropsInfo.resetGlitches) + { + for (const auto& iter : m_GlitchNames) + CStaticFunctionDefinitions::SetGlitchEnabled(iter.first, false); + } + + // Reset jetpack weapons + if (resetPropsInfo.resetJetpackWeapons) + { + for (std::uint8_t i = 0; i < WEAPONTYPE_LAST_WEAPONTYPE; i++) + CStaticFunctionDefinitions::SetJetpackWeaponEnabled(static_cast(i), false); + + CStaticFunctionDefinitions::SetJetpackWeaponEnabled(WEAPONTYPE_MICRO_UZI, true); + CStaticFunctionDefinitions::SetJetpackWeaponEnabled(WEAPONTYPE_TEC9, true); + CStaticFunctionDefinitions::SetJetpackWeaponEnabled(WEAPONTYPE_PISTOL, true); + } + + // Reset all other world stuff + // Reset far clip distance + g_pGame->SetHasFarClipDistance(false); + + // Reset clouds + g_pGame->SetCloudsEnabled(true); + + // Reset occlusions + g_pGame->SetOcclusionsEnabled(true); + + // Reset gravity + g_pGame->SetGravity(DEFAULT_GRAVITY); + + // Reset game speed + g_pGame->SetGameSpeed(DEFAULT_GAME_SPEED); + + // Reset aircraft max velocity & height + g_pGame->SetAircraftMaxHeight(DEFAULT_AIRCRAFT_MAXHEIGHT); + g_pGame->SetAircraftMaxVelocity(DEFAULT_AIRCRAFT_MAXVELOCITY); + + // Reset jetpack max height + g_pGame->SetJetpackMaxHeight(DEFAULT_JETPACK_MAXHEIGHT); + + // Reset minute duration + m_pMapManager->GetServerClock()->SetMinuteDuration(DEFAULT_MINUTE_DURATION); + + // Reset water color, water level & wave height + g_pGame->SetHasWaterColor(false); + m_pWaterManager->ResetWorldWaterLevel(); + m_pWaterManager->SetGlobalWaveHeight(0.0f); + + // Reset traffic lights + g_pGame->SetTrafficLightsLocked(false); + + // Send it to everyone + CBitStream bitStream; + bitStream->WriteBit(resetPropsInfo.resetSpecialProperties); + bitStream->WriteBit(resetPropsInfo.resetWorldProperties); + bitStream->WriteBit(resetPropsInfo.resetWeatherProperties); + bitStream->WriteBit(resetPropsInfo.resetLODs); + bitStream->WriteBit(resetPropsInfo.resetSounds); + m_pPlayerManager->BroadcastOnlyJoined(CLuaPacket(RESET_WORLD_PROPERTIES, *bitStream.pBitStream)); +} + // // Handle basic backup of databases and config files // @@ -4505,7 +4677,7 @@ void CGame::SendPacketBatchEnd() bool CGame::IsBulletSyncActive() { bool bConfigSaysEnable = m_pMainConfig->GetBulletSyncEnabled(); -#if 0 // No auto bullet sync as there are some problems with it +#if 0 // No auto bullet sync as there are some problems with it bool bGlitchesSayEnable = ( m_Glitches [ GLITCH_FASTFIRE ] || m_Glitches [ GLITCH_CROUCHBUG ] ); #else bool bGlitchesSayEnable = false; @@ -4699,3 +4871,48 @@ void CGame::HandleCrashDumpEncryption() } #endif } + +void CGame::RegisterClientTriggeredEventUsage(CPlayer* pPlayer) +{ + if (!pPlayer || !pPlayer->IsPlayer() || pPlayer->IsBeingDeleted()) + return; + + auto now = GetTickCount64_(); + + // If key/player doesn't exist in map, store time of entry + if (m_mapClientTriggeredEvents.find(pPlayer) == m_mapClientTriggeredEvents.end()) + m_mapClientTriggeredEvents[pPlayer].m_llTicks = now; + + // Only increment if we haven't reached the interval time already + if (now - m_mapClientTriggeredEvents[pPlayer].m_llTicks <= m_iClientTriggeredEventsIntervalMs) + m_mapClientTriggeredEvents[pPlayer].m_uiCounter++; +} + +void CGame::ProcessClientTriggeredEventSpam() +{ + for (auto it = m_mapClientTriggeredEvents.begin(); it != m_mapClientTriggeredEvents.end();) + { + const auto& [player, data] = *it; + bool remove = false; + + if (player && player->IsPlayer() && !player->IsBeingDeleted()) + { + if (GetTickCount64_() - data.m_llTicks >= m_iClientTriggeredEventsIntervalMs) + { + if (data.m_uiCounter > m_iMaxClientTriggeredEventsPerInterval) + player->CallEvent("onPlayerTriggerEventThreshold", {}); + + remove = true; + } + } + else + { + remove = true; + } + + if (remove) + it = m_mapClientTriggeredEvents.erase(it); + else + it++; + } +} diff --git a/Server/mods/deathmatch/logic/CGame.h b/Server/mods/deathmatch/logic/CGame.h index d3895d46e8..d865e858ec 100644 --- a/Server/mods/deathmatch/logic/CGame.h +++ b/Server/mods/deathmatch/logic/CGame.h @@ -134,6 +134,17 @@ class CWeaponDamageCheckPacket; typedef SFixedArray SGarageStates; +struct ResetWorldPropsInfo +{ + bool resetSpecialProperties{}; + bool resetWorldProperties{}; + bool resetWeatherProperties{}; + bool resetLODs{}; + bool resetSounds{}; + bool resetGlitches{}; + bool resetJetpackWeapons{}; +}; + // CSendList - Can be used like a std::list of players for sending packets. // Used to construct an optimized list of players for CGame::Broadcast class CSendList : public std::multimap @@ -432,6 +443,8 @@ class CGame int GetMoonSize() { return m_iMoonSize; } void SetMoonSize(int iMoonSize) { m_iMoonSize = iMoonSize; } + void ResetWorldProperties(const ResetWorldPropsInfo& resetPropsInfo); + void PrintLogOutputFromNetModule(); void StartOpenPortsTest(); @@ -457,6 +470,7 @@ class CGame bool IsBelowMinimumClient(const CMtaVersion& strVersion); bool IsBelowRecommendedClient(const CMtaVersion& strVersion); void ApplyAseSetting(); + void ApplyPlayerTriggeredEventIntervalChange(); bool IsUsingMtaServerConf() { return m_bUsingMtaServerConf; } void SetDevelopmentMode(bool enabled) { m_DevelopmentModeEnabled = enabled; } @@ -508,6 +522,9 @@ class CGame static void PlayerCompleteConnect(CPlayer* pPlayer); + void ProcessClientTriggeredEventSpam(); + void RegisterClientTriggeredEventUsage(CPlayer* pPlayer); + // Technically, this could be put somewhere else. It's a callback function // which the voice server library will call to send out data. @@ -658,4 +675,15 @@ class CGame bool m_DevelopmentModeEnabled; bool m_showClientTransferBox = true; + + int m_iMaxClientTriggeredEventsPerInterval = 100; + int m_iClientTriggeredEventsIntervalMs = 1000; + + struct ClientTriggeredEventsInfo + { + long long m_llTicks = 0; + uint32_t m_uiCounter = 0; + }; + + std::map m_mapClientTriggeredEvents; }; diff --git a/Server/mods/deathmatch/logic/CHTTPD.cpp b/Server/mods/deathmatch/logic/CHTTPD.cpp index 75734237f2..9ee2f43778 100644 --- a/Server/mods/deathmatch/logic/CHTTPD.cpp +++ b/Server/mods/deathmatch/logic/CHTTPD.cpp @@ -28,13 +28,8 @@ extern CGame* g_pGame; CHTTPD::CHTTPD() : m_BruteForceProtect(4, 30000, 60000 * 5) // Max of 4 attempts per 30 seconds, then 5 minute ignore - , - m_HttpDosProtect(0, 0, 0) + , m_HttpDosProtect(0, 0, 0) { - m_resource = NULL; - m_server = NULL; - m_bStartedServer = false; - m_pGuestAccount = g_pGame->GetAccountManager()->AddGuestAccount(HTTP_GUEST_ACCOUNT_NAME); m_HttpDosProtect = CConnectHistory(g_pGame->GetConfig()->GetHTTPDosThreshold(), 10000, @@ -106,7 +101,7 @@ HttpResponse* CHTTPD::RouteRequest(HttpRequest* ipoHttpRequest) HttpResponse* poHttpResponse = new HttpResponse(ipoHttpRequest->m_nRequestId, ipoHttpRequest->m_poSourceEHSConnection); SStringX strWait("The server is not ready. Please try again in a minute."); poHttpResponse->SetBody(strWait.c_str(), strWait.size()); - poHttpResponse->m_nResponseCode = HTTPRESPONSECODE_200_OK; + poHttpResponse->m_nResponseCode = HTTP_STATUS_CODE_200_OK; return poHttpResponse; } @@ -121,7 +116,7 @@ HttpResponse* CHTTPD::RouteRequest(HttpRequest* ipoHttpRequest) // Called from worker thread. g_pGame->Lock() has already been called. // creates a page based on user input -- either displays data from // form or presents a form for users to submit data. -ResponseCode CHTTPD::HandleRequest(HttpRequest* ipoHttpRequest, HttpResponse* ipoHttpResponse) +HttpStatusCode CHTTPD::HandleRequest(HttpRequest* ipoHttpRequest, HttpResponse* ipoHttpResponse) { // Check if server verification was requested auto challenge = ipoHttpRequest->oRequestHeaders["crypto_challenge"]; @@ -150,7 +145,7 @@ ResponseCode CHTTPD::HandleRequest(HttpRequest* ipoHttpRequest, HttpResponse* ip if (!cipherText.empty()) { ipoHttpResponse->SetBody((const char*)cipherText.BytePtr(), cipherText.SizeInBytes()); - return HTTPRESPONSECODE_200_OK; + return HTTP_STATUS_CODE_200_OK; } else CLogger::LogPrintf(LOGLEVEL_MEDIUM, "ERROR: Empty crypto challenge was passed during verification\n"); @@ -161,7 +156,7 @@ ResponseCode CHTTPD::HandleRequest(HttpRequest* ipoHttpRequest, HttpResponse* ip } ipoHttpResponse->SetBody("", 0); - return HTTPRESPONSECODE_401_UNAUTHORIZED; + return HTTP_STATUS_CODE_401_UNAUTHORIZED; } CAccount* account = CheckAuthentication(ipoHttpRequest); @@ -174,7 +169,7 @@ ResponseCode CHTTPD::HandleRequest(HttpRequest* ipoHttpRequest, HttpResponse* ip ipoHttpResponse->SetBody(strWelcome.c_str(), strWelcome.size()); SString strNewURL("http://%s/%s/", ipoHttpRequest->oRequestHeaders["host"].c_str(), m_strDefaultResourceName.c_str()); ipoHttpResponse->oResponseHeaders["location"] = strNewURL.c_str(); - return HTTPRESPONSECODE_302_FOUND; + return HTTP_STATUS_CODE_302_FOUND; } } @@ -183,10 +178,10 @@ ResponseCode CHTTPD::HandleRequest(HttpRequest* ipoHttpRequest, HttpResponse* ip "resource.

Alternatively, the server may be still starting up, if so, please try again in a minute.", ipoHttpRequest->oRequestHeaders["host"].c_str()); ipoHttpResponse->SetBody(strWelcome.c_str(), strWelcome.size()); - return HTTPRESPONSECODE_200_OK; + return HTTP_STATUS_CODE_200_OK; } -ResponseCode CHTTPD::RequestLogin(HttpRequest* ipoHttpRequest, HttpResponse* ipoHttpResponse) +HttpStatusCode CHTTPD::RequestLogin(HttpRequest* ipoHttpRequest, HttpResponse* ipoHttpResponse) { if (m_WarnMessageTimer.Get() < 4000 && m_strWarnMessageForIp == ipoHttpRequest->GetAddress()) { @@ -196,14 +191,14 @@ ResponseCode CHTTPD::RequestLogin(HttpRequest* ipoHttpRequest, HttpResponse* ipo "https:" "//mtasa.com/authserialhttp"); ipoHttpResponse->SetBody(strMessage, strMessage.length()); - return HTTPRESPONSECODE_401_UNAUTHORIZED; + return HTTP_STATUS_CODE_401_UNAUTHORIZED; } const char* szAuthenticateMessage = "Access denied, please login"; ipoHttpResponse->SetBody(szAuthenticateMessage, strlen(szAuthenticateMessage)); SString strName("Basic realm=\"%s\"", g_pGame->GetConfig()->GetServerName().c_str()); ipoHttpResponse->oResponseHeaders["WWW-Authenticate"] = strName.c_str(); - return HTTPRESPONSECODE_401_UNAUTHORIZED; + return HTTP_STATUS_CODE_401_UNAUTHORIZED; } CAccount* CHTTPD::CheckAuthentication(HttpRequest* ipoHttpRequest) diff --git a/Server/mods/deathmatch/logic/CHTTPD.h b/Server/mods/deathmatch/logic/CHTTPD.h index 2e890bf5df..ce91f3cf10 100644 --- a/Server/mods/deathmatch/logic/CHTTPD.h +++ b/Server/mods/deathmatch/logic/CHTTPD.h @@ -26,10 +26,10 @@ class CHTTPD : public EHS CHTTPD(); // start the initial server ~CHTTPD(); // EHS interface - HttpResponse* RouteRequest(HttpRequest* ipoHttpRequest); - ResponseCode HandleRequest(HttpRequest* ipoHttpRequest, HttpResponse* ipoHttpResponse); - void HttpPulse(); - bool ShouldAllowConnection(const char* szAddress); + HttpResponse* RouteRequest(HttpRequest* ipoHttpRequest); + HttpStatusCode HandleRequest(HttpRequest* ipoHttpRequest, HttpResponse* ipoHttpResponse); + void HttpPulse(); + bool ShouldAllowConnection(const char* szAddress); // CHTTPD methods bool StartHTTPD(const char* szIP, unsigned int port); @@ -38,16 +38,16 @@ class CHTTPD : public EHS CResource* GetResource() { return m_resource; } class CAccount* CheckAuthentication(HttpRequest* ipoHttpRequest); void SetDefaultResource(const char* szResourceName) { m_strDefaultResourceName = szResourceName ? szResourceName : ""; } - ResponseCode RequestLogin(HttpRequest* ipoHttpRequest, HttpResponse* ipoHttpResponse); + HttpStatusCode RequestLogin(HttpRequest* ipoHttpRequest, HttpResponse* ipoHttpResponse); private: - CResource* m_resource; - CHTTPD* m_server; + CResource* m_resource{}; + CHTTPD* m_server{}; std::string m_strDefaultResourceName; // default resource name EHSServerParameters m_Parameters; - bool m_bStartedServer; + bool m_bStartedServer{}; class CAccount* m_pGuestAccount; std::map m_LoggedInMap; diff --git a/Server/mods/deathmatch/logic/CHandlingManager.cpp b/Server/mods/deathmatch/logic/CHandlingManager.cpp index d5b9630051..8f7be518c9 100644 --- a/Server/mods/deathmatch/logic/CHandlingManager.cpp +++ b/Server/mods/deathmatch/logic/CHandlingManager.cpp @@ -1,11 +1,11 @@ /***************************************************************************** * - * PROJECT: Multi Theft Auto v1.0 + * PROJECT: Multi Theft Auto * LICENSE: See LICENSE in the top level directory - * FILE: mods/deathmatch/logic/CHandlingManager.cpp + * FILE: Server/mods/deathmatch/logic/CHandlingManager.cpp * PURPOSE: Vehicle handling manager * - * Multi Theft Auto is available from http://www.multitheftauto.com/ + * Multi Theft Auto is available from https://multitheftauto.com/ * *****************************************************************************/ @@ -24,15 +24,13 @@ CHandlingManager::CHandlingManager() // Initialize all default handlings InitializeDefaultHandlings(); - // Create a handling entry for every original handling data + // Create a handling entry for (int i = 0; i < HT_MAX; i++) { + // For every original handling data m_pOriginalEntries[i] = new CHandlingEntry(&m_OriginalHandlingData[i]); - } - // Create a handling entry for every model - for (int i = 0; i < HT_MAX; i++) - { + // For every model m_pModelEntries[i] = new CHandlingEntry(&m_OriginalHandlingData[i]); m_bModelHandlingChanged[i] = false; } @@ -78,97 +76,83 @@ CHandlingManager::CHandlingManager() CHandlingManager::~CHandlingManager() { - // Destroy all original handling entries + // Destroy for (int i = 0; i < HT_MAX; i++) { + // All original handling entries delete m_pOriginalEntries[i]; - } - // Destroy all model handling entries - for (int i = 0; i < HT_MAX; i++) - { + // All model handling entries delete m_pModelEntries[i]; } } CHandlingEntry* CHandlingManager::CreateHandlingData() { - CHandlingEntry* pHandlingEntry = new CHandlingEntry(); - return pHandlingEntry; + return new CHandlingEntry; } bool CHandlingManager::ApplyHandlingData(eVehicleTypes eModel, CHandlingEntry* pEntry) { // Within range? - if (CVehicleManager::IsValidModel(eModel)) - { - // Get our Handling ID - eHandlingTypes eHandling = GetHandlingID(eModel); - // Apply the data and return success - m_pModelEntries[eHandling]->ApplyHandlingData(pEntry); - return true; - } + if (!CVehicleManager::IsValidModel(eModel)) + return false; - // Failed - return false; + // Get our Handling ID + eHandlingTypes eHandling = GetHandlingID(eModel); + // Apply the data and return success + m_pModelEntries[eHandling]->ApplyHandlingData(pEntry); + return true; } const CHandlingEntry* CHandlingManager::GetOriginalHandlingData(eVehicleTypes eModel) { // Within range? - if (CVehicleManager::IsValidModel(eModel)) - { - // Get our Handling ID - eHandlingTypes eHandling = GetHandlingID(eModel); - // Return it - return m_pOriginalEntries[eHandling]; - } + if (!CVehicleManager::IsValidModel(eModel)) + return nullptr; - return NULL; + // Get our Handling ID + eHandlingTypes eHandling = GetHandlingID(eModel); + // Return it + return m_pOriginalEntries[eHandling]; } const CHandlingEntry* CHandlingManager::GetModelHandlingData(eVehicleTypes eModel) { // Within range? - if (CVehicleManager::IsValidModel(eModel)) - { - // Get our Handling ID - eHandlingTypes eHandling = GetHandlingID(eModel); - // Return it - return m_pModelEntries[eHandling]; - } + if (!CVehicleManager::IsValidModel(eModel)) + return nullptr; - return NULL; + // Get our Handling ID + eHandlingTypes eHandling = GetHandlingID(eModel); + // Return it + return m_pModelEntries[eHandling]; } -eHandlingProperty CHandlingManager::GetPropertyEnumFromName(std::string strName) +eHandlingProperty CHandlingManager::GetPropertyEnumFromName(const std::string& strName) { - std::map::iterator it; - it = m_HandlingNames.find(strName); - - if (it != m_HandlingNames.end()) - { - return it->second; - } - - return HANDLING_MAX; + const auto it = m_HandlingNames.find(strName); + return it != m_HandlingNames.end() ? it->second : HANDLING_MAX; } bool CHandlingManager::HasModelHandlingChanged(eVehicleTypes eModel) { // Within range? - if (CVehicleManager::IsValidModel(eModel)) - { - // Get our Handling ID - eHandlingTypes eHandling = GetHandlingID(eModel); - // Return if we have changed - return m_bModelHandlingChanged[eHandling]; - } - return false; + if (!CVehicleManager::IsValidModel(eModel)) + return false; + + // Get our Handling ID + eHandlingTypes eHandling = GetHandlingID(eModel); + // Return if we have changed + return m_bModelHandlingChanged[eHandling]; } void CHandlingManager::SetModelHandlingHasChanged(eVehicleTypes eModel, bool bChanged) { + // Within range? + if (!CVehicleManager::IsValidModel(eModel)) + return; + // Get our Handling ID eHandlingTypes eHandling = GetHandlingID(eModel); // Return if we have changed. diff --git a/Server/mods/deathmatch/logic/CHandlingManager.h b/Server/mods/deathmatch/logic/CHandlingManager.h index 21e54e1d55..4d52c5cc18 100644 --- a/Server/mods/deathmatch/logic/CHandlingManager.h +++ b/Server/mods/deathmatch/logic/CHandlingManager.h @@ -1,11 +1,11 @@ /***************************************************************************** * - * PROJECT: Multi Theft Auto v1.0 + * PROJECT: Multi Theft Auto * LICENSE: See LICENSE in the top level directory - * FILE: mods/deathmatch/logic/CHandlingManager.h + * FILE: Server/mods/deathmatch/logic/CHandlingManager.h * PURPOSE: Header file for vehicle handling manager class * - * Multi Theft Auto is available from http://www.multitheftauto.com/ + * Multi Theft Auto is available from https://multitheftauto.com/ * *****************************************************************************/ @@ -32,7 +32,7 @@ class CHandlingManager eHandlingTypes GetHandlingID(eVehicleTypes eModel); // Helper functions - eHandlingProperty GetPropertyEnumFromName(std::string strName); + eHandlingProperty GetPropertyEnumFromName(const std::string& strName); bool HasModelHandlingChanged(eVehicleTypes eModel); void SetModelHandlingHasChanged(eVehicleTypes eModel, bool bChanged); diff --git a/Server/mods/deathmatch/logic/CMainConfig.cpp b/Server/mods/deathmatch/logic/CMainConfig.cpp index be32e6c9eb..a535aa0ab6 100644 --- a/Server/mods/deathmatch/logic/CMainConfig.cpp +++ b/Server/mods/deathmatch/logic/CMainConfig.cpp @@ -847,12 +847,11 @@ bool CMainConfig::AddMissingSettings() if (!g_pGame->IsUsingMtaServerConf()) return false; - // Load template - const char* szTemplateText = - #include MTA_SERVER_CONF_TEMPLATE - ; - SString strTemplateFilename = PathJoin(g_pServerInterface->GetServerModPath(), "resource-cache", "conf.template"); - FileSave(strTemplateFilename, szTemplateText); + SString strTemplateFilename = PathJoin(g_pServerInterface->GetServerModPath(), "mtaserver.conf.template"); + + if (!FileExists(strTemplateFilename)) + return false; + CXMLFile* pFileTemplate = g_pServerInterface->GetXML()->CreateXML(strTemplateFilename); CXMLNode* pRootNodeTemplate = pFileTemplate && pFileTemplate->Parse() ? pFileTemplate->GetRootNode() : nullptr; if (!pRootNodeTemplate) @@ -1104,7 +1103,7 @@ bool CMainConfig::GetSettingTable(const SString& strName, const char** szAttribN resultLine.PushString(pAttribute->GetValue()); } - if (resultLine.Count() != 0) + if (resultLine.IsNotEmpty()) { outTable->PushNumber(uiLuaIndex++); outTable->PushTable(&resultLine); @@ -1112,7 +1111,7 @@ bool CMainConfig::GetSettingTable(const SString& strName, const char** szAttribN } } while (pNode); - return outTable->Count() != 0; + return outTable->IsNotEmpty(); } ////////////////////////////////////////////////////////////////////// @@ -1456,6 +1455,7 @@ const std::vector& CMainConfig::GetIntSettingList() {true, true, 10, 50, 1000, "update_cycle_messages_limit", &m_iUpdateCycleMessagesLimit, &CMainConfig::ApplyNetOptions}, {true, true, 50, 100, 400, "ped_syncer_distance", &g_TickRateSettings.iPedSyncerDistance, &CMainConfig::OnTickRateChange}, {true, true, 50, 130, 400, "unoccupied_vehicle_syncer_distance", &g_TickRateSettings.iUnoccupiedVehicleSyncerDistance, &CMainConfig::OnTickRateChange}, + {true, true, 0, 30, 130, "vehicle_contact_sync_radius", &g_TickRateSettings.iVehicleContactSyncRadius, &CMainConfig::OnTickRateChange}, {false, false, 0, 1, 2, "compact_internal_databases", &m_iCompactInternalDatabases, NULL}, {true, true, 0, 1, 2, "minclientversion_auto_update", &m_iMinClientVersionAutoUpdate, NULL}, {true, true, 0, 0, 100, "server_logic_fps_limit", &m_iServerLogicFpsLimit, NULL}, @@ -1463,6 +1463,8 @@ const std::vector& CMainConfig::GetIntSettingList() {true, true, 0, 1, 1, "filter_duplicate_log_lines", &m_bFilterDuplicateLogLinesEnabled, NULL}, {false, false, 0, 1, 1, "database_credentials_protection", &m_bDatabaseCredentialsProtectionEnabled, NULL}, {false, false, 0, 0, 1, "fakelag", &m_bFakeLagCommandEnabled, NULL}, + {true, true, 50, 1000, 5000, "player_triggered_event_interval", &m_iPlayerTriggeredEventIntervalMs, &CMainConfig::OnPlayerTriggeredEventIntervalChange}, + {true, true, 1, 100, 1000, "max_player_triggered_events_per_interval", &m_iMaxPlayerTriggeredEventsPerInterval, &CMainConfig::OnPlayerTriggeredEventIntervalChange}, }; static std::vector settingsList; @@ -1506,3 +1508,14 @@ void CGame::ApplyAseSetting() m_pLanBroadcast = m_pASE->InitLan(); } } + +void CMainConfig::OnPlayerTriggeredEventIntervalChange() +{ + g_pGame->ApplyPlayerTriggeredEventIntervalChange(); +} + +void CGame::ApplyPlayerTriggeredEventIntervalChange() +{ + m_iClientTriggeredEventsIntervalMs = m_pMainConfig->GetPlayerTriggeredEventInterval(); + m_iMaxClientTriggeredEventsPerInterval = m_pMainConfig->GetMaxPlayerTriggeredEventsPerInterval(); +} diff --git a/Server/mods/deathmatch/logic/CMainConfig.h b/Server/mods/deathmatch/logic/CMainConfig.h index b5f658a88a..b52733229a 100644 --- a/Server/mods/deathmatch/logic/CMainConfig.h +++ b/Server/mods/deathmatch/logic/CMainConfig.h @@ -142,6 +142,10 @@ class CMainConfig : public CXMLConfig const std::vector& GetIntSettingList(); void OnTickRateChange(); void OnAseSettingChange(); + void OnPlayerTriggeredEventIntervalChange(); + + int GetPlayerTriggeredEventInterval() const { return m_iPlayerTriggeredEventIntervalMs; } + int GetMaxPlayerTriggeredEventsPerInterval() const { return m_iMaxPlayerTriggeredEventsPerInterval; } private: void RegisterCommand(const char* szName, FCommandHandler* pFunction, bool bRestricted, const char* szConsoleHelpText); @@ -221,4 +225,6 @@ class CMainConfig : public CXMLConfig int m_bFilterDuplicateLogLinesEnabled; int m_bDatabaseCredentialsProtectionEnabled; int m_bFakeLagCommandEnabled; + int m_iPlayerTriggeredEventIntervalMs; + int m_iMaxPlayerTriggeredEventsPerInterval; }; diff --git a/Server/mods/deathmatch/logic/CMarker.cpp b/Server/mods/deathmatch/logic/CMarker.cpp index 0fc93ba76f..6709f4bb89 100644 --- a/Server/mods/deathmatch/logic/CMarker.cpp +++ b/Server/mods/deathmatch/logic/CMarker.cpp @@ -33,6 +33,9 @@ CMarker::CMarker(CMarkerManager* pMarkerManager, CColManager* pColManager, CElem m_Color = SColorRGBA(255, 255, 255, 255); m_bHasTarget = false; m_ucIcon = ICON_NONE; + m_ignoreAlphaLimits = false; + m_TargetArrowColor = SColorRGBA(255, 64, 64, 255); + m_TargetArrowSize = m_fSize * 0.625f; // Create our collision object m_pCollision = new CColCircle(pColManager, nullptr, m_vecPosition, m_fSize, true); @@ -261,6 +264,8 @@ void CMarker::SetSize(float fSize) { // Set the new size and update the col object m_fSize = fSize; + m_TargetArrowSize = fSize * 0.625f; + UpdateCollisionObject(m_ucType); // Tell all players @@ -278,12 +283,20 @@ void CMarker::SetColor(const SColor color) // Set the new color m_Color = color; + if (!m_ignoreAlphaLimits) + { + if (m_ucType == CMarker::TYPE_CHECKPOINT) + m_Color.A = 128; + else if (m_ucType == CMarker::TYPE_ARROW) + m_Color.A = 255; + } + // Tell all the players CBitStream BitStream; - BitStream.pBitStream->Write(color.B); - BitStream.pBitStream->Write(color.G); - BitStream.pBitStream->Write(color.R); - BitStream.pBitStream->Write(color.A); + BitStream.pBitStream->Write(m_Color.B); + BitStream.pBitStream->Write(m_Color.G); + BitStream.pBitStream->Write(m_Color.R); + BitStream.pBitStream->Write(m_Color.A); BroadcastOnlyVisible(CElementRPCPacket(this, SET_MARKER_COLOR, *BitStream.pBitStream)); } } @@ -301,6 +314,23 @@ void CMarker::SetIcon(unsigned char ucIcon) } } +void CMarker::SetTargetArrowProperties(const SColor color, float size) noexcept +{ + if (m_TargetArrowColor == color && m_TargetArrowSize == size) + return; + + m_TargetArrowColor = color; + m_TargetArrowSize = size; + + CBitStream BitStream; + BitStream.pBitStream->Write(color.R); + BitStream.pBitStream->Write(color.G); + BitStream.pBitStream->Write(color.B); + BitStream.pBitStream->Write(color.A); + BitStream.pBitStream->Write(size); + BroadcastOnlyVisible(CElementRPCPacket(this, SET_MARKER_TARGET_ARROW_PROPERTIES, *BitStream.pBitStream)); +} + void CMarker::Callback_OnCollision(CColShape& Shape, CElement& Element) { // Do not call on ourselves #7359 diff --git a/Server/mods/deathmatch/logic/CMarker.h b/Server/mods/deathmatch/logic/CMarker.h index 345ed39a47..6787940871 100644 --- a/Server/mods/deathmatch/logic/CMarker.h +++ b/Server/mods/deathmatch/logic/CMarker.h @@ -67,6 +67,13 @@ class CMarker : public CPerPlayerEntity, private CColCallback virtual CSphere GetWorldBoundingSphere(); + void SetIgnoreAlphaLimits(bool ignore) noexcept { m_ignoreAlphaLimits = ignore; }; + bool AreAlphaLimitsIgnored() const noexcept { return m_ignoreAlphaLimits; }; + + SColor GetTargetArrowColor() const noexcept { return m_TargetArrowColor; }; + float GetTargetArrowSize() const noexcept { return m_TargetArrowSize; }; + void SetTargetArrowProperties(const SColor color, float size) noexcept; + protected: bool ReadSpecialData(const int iLine) override; @@ -85,6 +92,9 @@ class CMarker : public CPerPlayerEntity, private CColCallback float m_fSize; SColor m_Color; unsigned char m_ucIcon; + bool m_ignoreAlphaLimits; + SColor m_TargetArrowColor; + float m_TargetArrowSize; CColShape* m_pCollision; }; diff --git a/Server/mods/deathmatch/logic/CObject.cpp b/Server/mods/deathmatch/logic/CObject.cpp index c88dbf3e60..8094f9dda9 100644 --- a/Server/mods/deathmatch/logic/CObject.cpp +++ b/Server/mods/deathmatch/logic/CObject.cpp @@ -33,6 +33,7 @@ CObject::CObject(CElement* pParent, CObjectManager* pObjectManager, bool bIsLowL m_bIsFrozen = false; m_bDoubleSided = false; m_bBreakable = false; + m_bRespawnable = true; m_bCollisionsEnabled = true; @@ -58,6 +59,7 @@ CObject::CObject(const CObject& Copy) : CElement(Copy.m_pParent), m_bIsLowLod(Co m_bBreakable = Copy.m_bBreakable; m_vecPosition = Copy.m_vecPosition; m_vecRotation = Copy.m_vecRotation; + m_bRespawnable = Copy.m_bRespawnable; m_pMoveAnimation = NULL; if (Copy.m_pMoveAnimation != NULL) diff --git a/Server/mods/deathmatch/logic/CObject.h b/Server/mods/deathmatch/logic/CObject.h index 9e2c23c360..e5032b91ce 100644 --- a/Server/mods/deathmatch/logic/CObject.h +++ b/Server/mods/deathmatch/logic/CObject.h @@ -81,6 +81,9 @@ class CObject : public CElement bool IsBreakable() { return m_bBreakable; } void SetBreakable(bool bBreakable) { m_bBreakable = bBreakable; } + bool IsRespawnEnabled() const noexcept { return m_bRespawnable; } + void SetRespawnEnabled(bool bRespawn) noexcept { m_bRespawnable = bRespawn; } + protected: bool ReadSpecialData(const int iLine) override; @@ -96,6 +99,7 @@ class CObject : public CElement bool m_bSyncable; CPlayer* m_pSyncer; bool m_bVisibleInAllDimensions = false; + bool m_bRespawnable; protected: bool m_bCollisionsEnabled; diff --git a/Server/mods/deathmatch/logic/CPed.cpp b/Server/mods/deathmatch/logic/CPed.cpp index 0b2ba04d0d..ba50c25caa 100644 --- a/Server/mods/deathmatch/logic/CPed.cpp +++ b/Server/mods/deathmatch/logic/CPed.cpp @@ -356,6 +356,17 @@ void CPed::SetWeaponTotalAmmo(unsigned short usTotalAmmo, unsigned char ucSlot) } } +bool CPed::HasWeaponType(unsigned char ucWeaponType) +{ + for (unsigned char slot = 0; slot < WEAPON_SLOTS; slot++) + { + if (GetWeaponType(slot) == ucWeaponType) + return true; + } + + return false; +} + float CPed::GetMaxHealth() { // TODO: Verify this formula @@ -523,3 +534,25 @@ void CPed::SetJackingVehicle(CVehicle* pVehicle) if (m_pJackingVehicle) m_pJackingVehicle->SetJackingPed(this); } + +void CPed::SetHasJetPack(bool bHasJetPack) +{ + if (m_bHasJetPack == bHasJetPack) + return; + + m_bHasJetPack = bHasJetPack; + + if (!bHasJetPack) + return; + + // Set weapon slot to 0 if weapon is disabled with jetpack to avoid HUD and audio bugs + eWeaponType weaponType = static_cast(GetWeaponType(GetWeaponSlot())); + if (weaponType <= WEAPONTYPE_UNARMED) + return; + + bool weaponEnabled; + CStaticFunctionDefinitions::GetJetpackWeaponEnabled(weaponType, weaponEnabled); + + if (!weaponEnabled) + CStaticFunctionDefinitions::SetPedWeaponSlot(this, 0); +} diff --git a/Server/mods/deathmatch/logic/CPed.h b/Server/mods/deathmatch/logic/CPed.h index 00eee811ae..be3e590096 100644 --- a/Server/mods/deathmatch/logic/CPed.h +++ b/Server/mods/deathmatch/logic/CPed.h @@ -168,6 +168,7 @@ class CPed : public CElement void SetWeaponAmmoInClip(unsigned short uscAmmoInClip, unsigned char ucSlot = 0xFF); unsigned short GetWeaponTotalAmmo(unsigned char ucSlot = 0xFF); void SetWeaponTotalAmmo(unsigned short usTotalAmmo, unsigned char ucSlot = 0xFF); + bool HasWeaponType(unsigned char ucWeaponType); float GetMaxHealth(); float GetHealth() { return m_fHealth; } @@ -187,7 +188,7 @@ class CPed : public CElement static const char* GetBodyPartName(unsigned char ucID); bool HasJetPack() { return m_bHasJetPack; } - void SetHasJetPack(bool bHasJetPack) { m_bHasJetPack = bHasJetPack; } + void SetHasJetPack(bool bHasJetPack); bool IsInWater() { return m_bInWater; } void SetInWater(bool bInWater) { m_bInWater = bInWater; } diff --git a/Server/mods/deathmatch/logic/CPedSync.cpp b/Server/mods/deathmatch/logic/CPedSync.cpp index 02260d0756..cb2f9e417b 100644 --- a/Server/mods/deathmatch/logic/CPedSync.cpp +++ b/Server/mods/deathmatch/logic/CPedSync.cpp @@ -234,13 +234,13 @@ void CPedSync::Packet_PedSync(CPedSyncPacket& Packet) // Apply the data to the ped if (Data.ucFlags & 0x01) { - pPed->SetPosition(Data.vecPosition); + pPed->SetPosition(Data.position.data.vecPosition); g_pGame->GetColManager()->DoHitDetection(pPed->GetPosition(), pPed); } if (Data.ucFlags & 0x02) - pPed->SetRotation(Data.fRotation); + pPed->SetRotation(Data.rotation.data.fRotation); if (Data.ucFlags & 0x04) - pPed->SetVelocity(Data.vecVelocity); + pPed->SetVelocity(Data.velocity.data.vecVelocity); if (Data.ucFlags & 0x08) { diff --git a/Server/mods/deathmatch/logic/CPerfStat.RPCPacketUsage.cpp b/Server/mods/deathmatch/logic/CPerfStat.RPCPacketUsage.cpp index 1e02f4abad..6a0604b65b 100644 --- a/Server/mods/deathmatch/logic/CPerfStat.RPCPacketUsage.cpp +++ b/Server/mods/deathmatch/logic/CPerfStat.RPCPacketUsage.cpp @@ -224,6 +224,12 @@ ADD_ENUM1(UPDATE_COLPOLYGON_POINT) ADD_ENUM1(SET_DISCORD_JOIN_PARAMETERS) ADD_ENUM1(SET_COLPOLYGON_HEIGHT) ADD_ENUM1(SET_OBJECT_BREAKABLE) +ADD_ENUM1(BREAK_OBJECT) +ADD_ENUM1(SET_PLAYER_SCRIPT_DEBUG_LEVEL) +ADD_ENUM1(SET_MARKER_TARGET_ARROW_PROPERTIES) +ADD_ENUM1(RESPAWN_OBJECT) +ADD_ENUM1(TOGGLE_OBJECT_RESPAWN) +ADD_ENUM1(RESET_WORLD_PROPERTIES) IMPLEMENT_ENUM_END("eElementRPCFunctions") DECLARE_ENUM(CRPCFunctions::eRPCFunctions); diff --git a/Server/mods/deathmatch/logic/CPickup.cpp b/Server/mods/deathmatch/logic/CPickup.cpp index cb9e8350f7..9bda584f79 100644 --- a/Server/mods/deathmatch/logic/CPickup.cpp +++ b/Server/mods/deathmatch/logic/CPickup.cpp @@ -24,7 +24,7 @@ CPickup::CPickup(CElement* pParent, CPickupManager* pPickupManager, CColManager* { // Init m_pPickupManager = pPickupManager; - m_pCollision = new CColSphere(pColManager, nullptr, m_vecPosition, 2.0f, true); + m_pCollision = new CColSphere(pColManager, nullptr, m_vecPosition, 1.0f, true); m_pCollision->SetEnabled(false); m_pCollision->SetCallback(this); m_pCollision->SetAutoCallEvent(false); diff --git a/Server/mods/deathmatch/logic/CPlayer.cpp b/Server/mods/deathmatch/logic/CPlayer.cpp index 5d4fee6401..bf9d6b07d4 100644 --- a/Server/mods/deathmatch/logic/CPlayer.cpp +++ b/Server/mods/deathmatch/logic/CPlayer.cpp @@ -22,6 +22,7 @@ #include "CBandwidthSettings.h" #include "CUnoccupiedVehicleSync.h" #include "CScriptDebugging.h" +#include "packets/CLuaPacket.h" #include "packets/CConsoleEchoPacket.h" #include "packets/CChatEchoPacket.h" #include "CWeaponStatManager.h" @@ -470,9 +471,16 @@ void CPlayer::RemoveAllSyncingObjects() } } -bool CPlayer::SetScriptDebugLevel(unsigned int uiLevel) +bool CPlayer::SetScriptDebugLevel(std::uint8_t level) { - return m_pScriptDebugging->AddPlayer(*this, uiLevel); + if (!m_pScriptDebugging->AddPlayer(*this, level)) + return false; + + CPlayerBitStream BitStream(this); + BitStream.pBitStream->Write(level); + + Send(CLuaPacket(SET_PLAYER_SCRIPT_DEBUG_LEVEL, *BitStream.pBitStream)); + return true; } void CPlayer::SetDamageInfo(ElementID ElementID, unsigned char ucWeapon, unsigned char ucBodyPart) diff --git a/Server/mods/deathmatch/logic/CPlayer.h b/Server/mods/deathmatch/logic/CPlayer.h index bb64a6f51a..feded36e51 100644 --- a/Server/mods/deathmatch/logic/CPlayer.h +++ b/Server/mods/deathmatch/logic/CPlayer.h @@ -167,7 +167,7 @@ class CPlayer final : public CPed, public CClient std::list::const_iterator IterSyncingObjectEnd() { return m_SyncingObjects.end(); }; unsigned int GetScriptDebugLevel() { return m_uiScriptDebugLevel; }; - bool SetScriptDebugLevel(unsigned int uiLevel); + bool SetScriptDebugLevel(std::uint8_t level); void SetDamageInfo(ElementID ElementID, unsigned char ucWeapon, unsigned char ucBodyPart); void ValidateDamageInfo(); diff --git a/Server/mods/deathmatch/logic/CRemoteCalls.cpp b/Server/mods/deathmatch/logic/CRemoteCalls.cpp index e26425ca06..8ae982ca97 100644 --- a/Server/mods/deathmatch/logic/CRemoteCalls.cpp +++ b/Server/mods/deathmatch/logic/CRemoteCalls.cpp @@ -275,8 +275,10 @@ void CRemoteCall::DownloadFinishedCallback(const SHttpDownloadResult& result) // Append stored arguments if (pCall->IsFetch()) - for (uint i = 0; i < pCall->GetFetchArguments().Count(); i++) - arguments.PushArgument(*(pCall->GetFetchArguments()[i])); + { + for (CLuaArgument* argument : pCall->GetFetchArguments()) + arguments.PushArgument(*argument); + } if (pCall->m_VM) arguments.Call(pCall->m_VM, pCall->m_iFunction); diff --git a/Server/mods/deathmatch/logic/CResource.cpp b/Server/mods/deathmatch/logic/CResource.cpp index 500edf254c..759c6288da 100644 --- a/Server/mods/deathmatch/logic/CResource.cpp +++ b/Server/mods/deathmatch/logic/CResource.cpp @@ -34,6 +34,7 @@ #include "lua/CLuaFunctionParseHelpers.h" #include #include +#include #ifdef WIN32 #include @@ -45,6 +46,13 @@ #define MAX_PATH 260 #endif +enum HttpRouterCheck +{ + HTTP_ROUTER_CHECK_PENDING, + HTTP_ROUTER_CHECK_PASSED, + HTTP_ROUTER_CHECK_FAILED, +}; + int do_extract_currentfile(unzFile uf, const int* popt_extract_without_path, int* popt_overwrite, const char* password, const char* szFilePath); unsigned long get_current_file_crc(unzFile uf); @@ -116,7 +124,6 @@ bool CResource::Load() // Register us in the EHS stuff g_pGame->GetHTTPD()->RegisterEHS(this, m_strResourceName.c_str()); this->m_oEHSServerParameters["norouterequest"] = true; - this->RegisterEHS(this, "call"); // Store the actual directory and zip paths for fast access m_strResourceDirectoryPath = PathJoin(m_strAbsPath, m_strResourceName, "/"); @@ -338,10 +345,13 @@ bool CResource::Unload() m_pNodeSettings = nullptr; } + OnResourceStateChange("unloaded"); + m_strResourceZip = ""; m_strResourceCachePath = ""; m_strResourceDirectoryPath = ""; m_eState = EResourceState::None; + return true; } @@ -385,6 +395,7 @@ void CResource::TidyUp() delete pResourceFile; m_ResourceFiles.clear(); + m_ResourceFilesCountPerDir.clear(); // Go through each included resource item and delete it for (CIncludedResources* pIncludedResources : m_IncludedResources) @@ -396,7 +407,6 @@ void CResource::TidyUp() for (CResource* pDependent : m_Dependents) pDependent->InvalidateIncludedResourceReference(this); - this->UnregisterEHS("call"); g_pGame->GetHTTPD()->UnregisterEHS(m_strResourceName.c_str()); } @@ -592,8 +602,12 @@ bool CResource::GenerateChecksums() bool CResource::HasResourceChanged() { std::string strPath; + std::string_view strDirPath = m_strResourceDirectoryPath; + if (IsResourceZip()) { + strDirPath = m_strResourceCachePath; + // Zip file might have changed CChecksum checksum = CChecksum::GenerateChecksumFromFileUnsafe(m_strResourceZip); if (checksum != m_zipHash) @@ -630,6 +644,14 @@ bool CResource::HasResourceChanged() } } + for (const auto& [strGlob, uiFileCount] : m_ResourceFilesCountPerDir) + { + std::vector files = glob::rglob(strDirPath.data() + strGlob); + + if (files.size() != uiFileCount) + return true; + } + if (GetFilePath("meta.xml", strPath)) { CChecksum checksum = CChecksum::GenerateChecksumFromFileUnsafe(strPath); @@ -741,6 +763,8 @@ bool CResource::Start(std::list* pDependents, bool bManualStart, con if (m_bDestroyed) return false; + OnResourceStateChange("starting"); + m_eState = EResourceState::Starting; CLuaArguments PreStartArguments; @@ -974,6 +998,8 @@ bool CResource::Start(std::list* pDependents, bool bManualStart, con AddDependent(pDependent); } + OnResourceStateChange("running"); + m_eState = EResourceState::Running; // Call the onResourceStart event. If it returns false, cancel this script again @@ -1016,6 +1042,37 @@ bool CResource::Start(std::list* pDependents, bool bManualStart, con return true; } +void CResource::OnResourceStateChange(const char* state) noexcept +{ + if (!m_pResourceElement) + return; + + CLuaArguments stateArgs; + stateArgs.PushResource(this); + switch (m_eState) + { + case EResourceState::Loaded: // When resource is stopped + stateArgs.PushString("loaded"); + break; + case EResourceState::Running: // When resource is running + stateArgs.PushString("running"); + break; + case EResourceState::Starting: // When resource is starting + stateArgs.PushString("starting"); + break; + case EResourceState::Stopping: // When resource is stopping + stateArgs.PushString("stopping"); + break; + case EResourceState::None: // When resource is not loaded + default: + stateArgs.PushString("unloaded"); + break; + } + stateArgs.PushString(state); + + m_pResourceElement->CallEvent("onResourceStateChange", stateArgs); +} + bool CResource::Stop(bool bManualStop) { if (m_eState == EResourceState::Loaded) @@ -1027,6 +1084,8 @@ bool CResource::Stop(bool bManualStop) if (m_bStartedManually && !bManualStop) return false; + OnResourceStateChange("stopping"); + m_eState = EResourceState::Stopping; m_pResourceManager->RemoveMinClientRequirement(this); m_pResourceManager->RemoveSyncMapElementDataOption(this); @@ -1113,6 +1172,7 @@ bool CResource::Stop(bool bManualStop) // Broadcast the packet to joined players g_pGame->GetPlayerManager()->BroadcastOnlyJoined(removePacket); + OnResourceStateChange("loaded"); m_eState = EResourceState::Loaded; return true; } @@ -1300,6 +1360,23 @@ bool CResource::GetFilePath(const char* szFilename, string& strPath) return FileExists(strPath); } +std::vector CResource::GetFilePaths(const char* szFilename) +{ + std::vector vecFiles; + const std::string& strDirectory = IsResourceZip() ? m_strResourceCachePath : m_strResourceDirectoryPath; + const std::string strFilePath = strDirectory + szFilename; + + for (const std::filesystem::path& path : glob::rglob(strFilePath)) + { + std::string strPath = std::filesystem::relative(path, strDirectory).string(); + ReplaceSlashes(strPath); + + vecFiles.push_back(std::move(strPath)); + } + + return vecFiles; +} + // Return true if file name is used by this resource bool CResource::IsFilenameUsed(const SString& strFilename, bool bClient) { @@ -1545,13 +1622,28 @@ bool CResource::ReadIncludedFiles(CXMLNode* pRoot) if (!strFilename.empty()) { - std::string strFullFilename; ReplaceSlashes(strFilename); - if (IsFilenameUsed(strFilename, true)) + if (!IsValidFilePath(strFilename.c_str())) { - CLogger::LogPrintf("WARNING: Ignoring duplicate client file in resource '%s': '%s'\n", m_strResourceName.c_str(), strFilename.c_str()); - continue; + m_strFailureReason = SString("Couldn't find file(s) %s for resource %s\n", strFilename.c_str(), m_strResourceName.c_str()); + CLogger::ErrorPrintf(m_strFailureReason); + return false; + } + + std::vector vecFiles = GetFilePaths(strFilename.c_str()); + + if (vecFiles.empty()) + { + if (glob::has_magic(strFilename)) + { + m_ResourceFilesCountPerDir[strFilename] = vecFiles.size(); + continue; + } + + m_strFailureReason = SString("Couldn't find file(s) %s for resource %s\n", strFilename.c_str(), m_strResourceName.c_str()); + CLogger::ErrorPrintf(m_strFailureReason); + return false; } bool bDownload = true; @@ -1559,23 +1651,30 @@ bool CResource::ReadIncludedFiles(CXMLNode* pRoot) if (pDownload) { - const char* szDownload = pDownload->GetValue().c_str(); + const std::string strDownload = pDownload->GetValue(); - if (!stricmp(szDownload, "no") || !stricmp(szDownload, "false")) + if (strDownload == "no" || strDownload == "false") bDownload = false; } - // Create a new resourcefile item - if (IsValidFilePath(strFilename.c_str()) && GetFilePath(strFilename.c_str(), strFullFilename)) + for (const std::string& strFilePath : vecFiles) { - m_ResourceFiles.push_back(new CResourceClientFileItem(this, strFilename.c_str(), strFullFilename.c_str(), &Attributes, bDownload)); - } - else - { - m_strFailureReason = SString("Couldn't find file %s for resource %s\n", strFilename.c_str(), m_strResourceName.c_str()); - CLogger::ErrorPrintf(m_strFailureReason); - return false; + std::string strFullFilename; + + if (IsFilenameUsed(strFilePath, true)) + { + CLogger::LogPrintf("WARNING: Ignoring duplicate client file in resource '%s': '%s'\n", m_strResourceName.c_str(), strFilePath.c_str()); + continue; + } + + if (GetFilePath(strFilePath.c_str(), strFullFilename)) + { + m_ResourceFiles.push_back(new CResourceClientFileItem(this, strFilePath.c_str(), strFullFilename.c_str(), &Attributes, bDownload)); + } } + + if (glob::has_magic(strFilename)) + m_ResourceFilesCountPerDir[strFilename] = vecFiles.size(); } else { @@ -1595,90 +1694,122 @@ bool CResource::ReadIncludedExports(CXMLNode* pRoot) { int i = 0; m_ExportedFunctions.clear(); + m_httpRouterFunction.clear(); + m_httpRouterAclRight.clear(); + m_httpRouterCheck = HTTP_ROUTER_CHECK_PENDING; // Read our exportlist for (CXMLNode* pExport = pRoot->FindSubNode("export", i); pExport != nullptr; pExport = pRoot->FindSubNode("export", ++i)) { CXMLAttributes& Attributes = pExport->GetAttributes(); - // See if the http attribute is true or false - bool bHTTP = false; - CXMLAttribute* pHttp = Attributes.Find("http"); + CXMLAttribute* functionAttribute = Attributes.Find("function"); - if (pHttp) + if (functionAttribute == nullptr) { - const char* szHttp = pHttp->GetValue().c_str(); - - if (!stricmp(szHttp, "yes") || !stricmp(szHttp, "true")) - bHTTP = true; - else - bHTTP = false; + CLogger::LogPrintf("WARNING: Missing 'function' attribute from 'export' node of 'meta.xml' for resource '%s', ignoring\n", + m_strResourceName.c_str()); + continue; } - // See if the restricted attribute is true or false - bool bRestricted = false; - CXMLAttribute* pRestricted = Attributes.Find("restricted"); + const char* functionName = functionAttribute->GetValue().c_str(); - if (pRestricted) + if (functionName[0] == '\0') { - const char* szRestricted = pRestricted->GetValue().c_str(); + CLogger::ErrorPrintf("WARNING: Empty 'function' attribute of 'export' node of 'meta.xml' for resource '%s', ignoring\n", + m_strResourceName.c_str()); + continue; + } - if (!stricmp(szRestricted, "yes") || !stricmp(szRestricted, "true")) - bRestricted = true; - else - bRestricted = false; + // See if the http attribute is true or false + bool isHttpFunction = false; + + if (CXMLAttribute* attribute = Attributes.Find("http"); attribute != nullptr) + { + const char* value = attribute->GetValue().c_str(); + isHttpFunction = !stricmp(value, "true") || !stricmp(value, "yes"); } - // Find the type attribute - bool bServer = true; - bool bClient = false; + // See if the http router attribute is true or false + bool isHttpRouter = false; - CXMLAttribute* pType = Attributes.Find("type"); + if (CXMLAttribute* attribute = Attributes.Find("router"); attribute != nullptr) + { + const char* value = attribute->GetValue().c_str(); + isHttpRouter = !stricmp(value, "true") || !stricmp(value, "yes"); + } - if (pType) + if (!isHttpFunction && isHttpRouter) { - // Grab the type. Client or server or shared - const char* szType = pType->GetValue().c_str(); + isHttpRouter = false; + CLogger::ErrorPrintf("WARNING: Regular function '%s' in resource '%s' uses HTTP router attribute\n", + functionName, m_strResourceName.c_str()); + } - if (!stricmp(szType, "client")) - { - bServer = false; - bClient = true; - } - else if (!stricmp(szType, "shared")) - bClient = true; - else if (stricmp(szType, "server") != 0) - CLogger::LogPrintf("Unknown exported function type specified in %s. Assuming 'server'\n", m_strResourceName.c_str()); + if (isHttpRouter && !m_httpRouterFunction.empty()) + { + isHttpRouter = false; + CLogger::ErrorPrintf("WARNING: HTTP router function '%s' in resource '%s' ignored, using '%s'\n", + functionName, m_strResourceName.c_str(), m_httpRouterFunction.c_str()); + } + + // See if the restricted attribute is true or false + bool isRestricted = false; + + if (CXMLAttribute* attribute = Attributes.Find("restricted"); attribute != nullptr) + { + const char* value = attribute->GetValue().c_str(); + isRestricted = !stricmp(value, "true") || !stricmp(value, "yes"); } - // Grab the functionname attribute - CXMLAttribute* pFunction = Attributes.Find("function"); + // Find the type attribute + bool isServerFunction = true; + bool isClientFunction = false; - if (pFunction) + if (CXMLAttribute* attribute = Attributes.Find("type"); attribute != nullptr) { - // Grab the functionname from the attribute - const std::string& strFunction = pFunction->GetValue(); + const char* value = attribute->GetValue().c_str(); - // Add it to the list if it wasn't zero long. Otherwize show a warning - if (!strFunction.empty()) + if (!stricmp(value, "client")) { - if (bServer) - m_ExportedFunctions.push_back(CExportedFunction(strFunction.c_str(), bHTTP, CExportedFunction::EXPORTED_FUNCTION_TYPE_SERVER, - bRestricted || GetName() == "webadmin" || GetName() == "runcode")); - if (bClient) - m_ExportedFunctions.push_back(CExportedFunction(strFunction.c_str(), bHTTP, CExportedFunction::EXPORTED_FUNCTION_TYPE_CLIENT, - bRestricted || GetName() == "webadmin" || GetName() == "runcode")); + isServerFunction = false; + isClientFunction = true; } - else + else if (!stricmp(value, "shared")) { - CLogger::ErrorPrintf("WARNING: Empty 'function' attribute of 'export' node of 'meta.xml' for resource '%s', ignoring\n", - m_strResourceName.c_str()); + isClientFunction = true; + } + else if (stricmp(value, "server") != 0) + { + CLogger::LogPrintf("WARNING: Function '%s' in resource '%s' uses unknown function type, assuming 'server'\n", + functionName, m_strResourceName.c_str()); } } - else + + if (isHttpRouter) { - CLogger::LogPrintf("WARNING: Missing 'function' attribute from 'export' node of 'meta.xml' for resource '%s', ignoring\n", - m_strResourceName.c_str()); + if (isServerFunction) + { + m_httpRouterFunction = functionName; + m_httpRouterAclRight = SString("%s.function.%s", m_strResourceName.c_str(), functionName); + continue; + } + + CLogger::LogPrintf("WARNING: HTTP router function '%s' in resource '%s' is not a server-sided function, ignoring\n", + functionName, m_strResourceName.c_str()); + continue; + } + + if (isServerFunction) + { + m_ExportedFunctions.push_back(CExportedFunction(functionName, isHttpFunction, CExportedFunction::EXPORTED_FUNCTION_TYPE_SERVER, + isRestricted || GetName() == "webadmin" || GetName() == "runcode")); + } + + if (isClientFunction) + { + m_ExportedFunctions.push_back(CExportedFunction(functionName, isHttpFunction, CExportedFunction::EXPORTED_FUNCTION_TYPE_CLIENT, + isRestricted || GetName() == "webadmin" || GetName() == "runcode")); } } @@ -1725,35 +1856,67 @@ bool CResource::ReadIncludedScripts(CXMLNode* pRoot) if (!strFilename.empty()) { - std::string strFullFilename; ReplaceSlashes(strFilename); - if (bClient && IsFilenameUsed(strFilename, true)) + if (!IsValidFilePath(strFilename.c_str())) { - CLogger::LogPrintf("WARNING: Ignoring duplicate client script file in resource '%s': '%s'\n", m_strResourceName.c_str(), - strFilename.c_str()); - bClient = false; - } - if (bServer && IsFilenameUsed(strFilename, false)) - { - CLogger::LogPrintf("WARNING: Duplicate script file in resource '%s': '%s'\n", m_strResourceName.c_str(), strFilename.c_str()); + m_strFailureReason = SString("Couldn't find script(s) %s for resource %s\n", strFilename.c_str(), m_strResourceName.c_str()); + CLogger::ErrorPrintf(m_strFailureReason); + return false; } - // Extract / get the filepath of the file - if (IsValidFilePath(strFilename.c_str()) && GetFilePath(strFilename.c_str(), strFullFilename)) - { - // Create it depending on the type (client or server or shared) and add it to the list of resource files - if (bServer) - m_ResourceFiles.push_back(new CResourceScriptItem(this, strFilename.c_str(), strFullFilename.c_str(), &Attributes)); - if (bClient) - m_ResourceFiles.push_back(new CResourceClientScriptItem(this, strFilename.c_str(), strFullFilename.c_str(), &Attributes)); - } - else + std::vector vecFiles = GetFilePaths(strFilename.c_str()); + + if (vecFiles.empty()) { - m_strFailureReason = SString("Couldn't find script %s for resource %s\n", strFilename.c_str(), m_strResourceName.c_str()); + if (glob::has_magic(strFilename)) + { + m_ResourceFilesCountPerDir[strFilename] = vecFiles.size(); + continue; + } + + m_strFailureReason = SString("Couldn't find script(s) %s for resource %s\n", strFilename.c_str(), m_strResourceName.c_str()); CLogger::ErrorPrintf(m_strFailureReason); return false; } + + for (const std::string& strFilePath : vecFiles) + { + std::string strFullFilename; + bool bLoadClient = bClient; + bool bLoadServer = bServer; + + if (GetFilePath(strFilePath.c_str(), strFullFilename)) + { + // Check if the filename is already used by this resource + + if (bClient && IsFilenameUsed(strFilePath, true)) + { + CLogger::LogPrintf("WARNING: Ignoring duplicate client script file in resource '%s': '%s'\n", m_strResourceName.c_str(), + strFilePath.c_str()); + bLoadClient = false; + } + + if (bServer && IsFilenameUsed(strFilePath, false)) + { + CLogger::LogPrintf("WARNING: Ignoring duplicate script file in resource '%s': '%s'\n", m_strResourceName.c_str(), + strFilePath.c_str()); + + bLoadServer = false; + } + + // Create it depending on the type (client or server or shared) and add it to the list of resource files + + if (bLoadServer) + m_ResourceFiles.push_back(new CResourceScriptItem(this, strFilePath.c_str(), strFullFilename.c_str(), &Attributes)); + + if (bLoadClient) + m_ResourceFiles.push_back(new CResourceClientScriptItem(this, strFilePath.c_str(), strFullFilename.c_str(), &Attributes)); + } + } + + if (glob::has_magic(strFilename)) + m_ResourceFilesCountPerDir[strFilename] = vecFiles.size(); } else { @@ -2334,39 +2497,29 @@ void CResource::RemoveDependent(CResource* pResource) } // Called on another thread, but g_pGame->Lock() has been called, so everything is going to be OK -ResponseCode CResource::HandleRequest(HttpRequest* ipoHttpRequest, HttpResponse* ipoHttpResponse) +HttpStatusCode CResource::HandleRequest(HttpRequest* ipoHttpRequest, HttpResponse* ipoHttpResponse) { - std::string strAccessType; - const char* szRequest = ipoHttpRequest->sOriginalUri.c_str(); + CAccount* account = g_pGame->GetHTTPD()->CheckAuthentication(ipoHttpRequest); - if (*szRequest) + if (!account) { - const char* szSlash1 = strchr(szRequest + 1, '/'); - - if (szSlash1) - { - const char* szSlash2 = strchr(szSlash1 + 1, '/'); - - if (szSlash2) - strAccessType.assign(szSlash1 + 1, szSlash2 - (szSlash1 + 1)); - } + return HTTP_STATUS_CODE_200_OK; } - CAccount* pAccount = g_pGame->GetHTTPD()->CheckAuthentication(ipoHttpRequest); - - if (pAccount) + if (!m_httpRouterFunction.empty()) { - ResponseCode responseCode; + return HandleRequestRouter(ipoHttpRequest, ipoHttpResponse, account); + } - if (strAccessType == "call") - responseCode = HandleRequestCall(ipoHttpRequest, ipoHttpResponse, pAccount); - else - responseCode = HandleRequestActive(ipoHttpRequest, ipoHttpResponse, pAccount); + const auto path = std::string_view{ipoHttpRequest->sOriginalUri}.substr(1 /* first slash */ + m_strResourceName.size()); + const bool isCall = path.size() >= sizeof("/call") && !strnicmp(path.data(), "/call/", 6); - return responseCode; + if (isCall) + { + return HandleRequestCall(ipoHttpRequest, ipoHttpResponse, account); } - return HTTPRESPONSECODE_200_OK; + return HandleRequestActive(ipoHttpRequest, ipoHttpResponse, account); } std::string Unescape(std::string_view sv) @@ -2413,7 +2566,7 @@ std::string Unescape(std::string_view sv) return out; } -ResponseCode CResource::HandleRequestCall(HttpRequest* ipoHttpRequest, HttpResponse* ipoHttpResponse, CAccount* pAccount) +HttpStatusCode CResource::HandleRequestCall(HttpRequest* ipoHttpRequest, HttpResponse* ipoHttpResponse, CAccount* pAccount) { if (!IsHttpAccessAllowed(pAccount)) { @@ -2426,7 +2579,7 @@ ResponseCode CResource::HandleRequestCall(HttpRequest* ipoHttpRequest, HttpRespo { const char* szError = "error: resource not running"; ipoHttpResponse->SetBody(szError, strlen(szError)); - return HTTPRESPONSECODE_200_OK; + return HTTP_STATUS_CODE_200_OK; } const char* szQueryString = ipoHttpRequest->sUri.c_str(); @@ -2435,7 +2588,7 @@ ResponseCode CResource::HandleRequestCall(HttpRequest* ipoHttpRequest, HttpRespo { const char* szError = "error: invalid function name"; ipoHttpResponse->SetBody(szError, strlen(szError)); - return HTTPRESPONSECODE_200_OK; + return HTTP_STATUS_CODE_200_OK; } std::string strFuncName; @@ -2667,15 +2820,281 @@ ResponseCode CResource::HandleRequestCall(HttpRequest* ipoHttpRequest, HttpRespo g_pGame->GetScriptDebugging()->SaveLuaDebugInfo(SLuaDebugInfo()); ipoHttpResponse->SetBody(strJSON.c_str(), strJSON.length()); - return HTTPRESPONSECODE_200_OK; + return HTTP_STATUS_CODE_200_OK; } const char* szError = "error: not found"; ipoHttpResponse->SetBody(szError, strlen(szError)); - return HTTPRESPONSECODE_200_OK; + return HTTP_STATUS_CODE_200_OK; +} + +static HttpStatusCode ParseLuaHttpRouterResponse(CLuaArguments& luaResponse, HttpResponse& httpResponse) +{ + bool hasBody = false; + HttpStatusCode responseCode = HTTP_STATUS_CODE_200_OK; + + for (size_t i = 0; i < luaResponse.Count(); i += 2) + { + CLuaArgument* argName = luaResponse[i + 0]; + CLuaArgument* argValue = luaResponse[i + 1]; + + std::string_view key; + + if (!argName->TryGetString(key)) + continue; + + if (key == "status") + { + if (lua_Number status; argValue->TryGetNumber(status)) + { + responseCode = static_cast(status); + } + } + else if (key == "body") + { + if (std::string_view body; argValue->TryGetString(body)) + { + if (body.size() <= std::numeric_limits::max()) + { + hasBody = true; + httpResponse.SetBody(body.data(), body.size()); + } + } + } + else if (key == "headers") + { + if (CLuaArguments* headers; argValue->TryGetTable(headers)) + { + for (size_t j = 0; j < headers->Count(); j += 2) + { + argName = (*headers)[j + 0]; + argValue = (*headers)[j + 1]; + + if (std::string_view n, v; argName->TryGetString(n) && argValue->TryGetString(v)) + { + httpResponse.oResponseHeaders[std::string{n}] = std::string{v}; + } + } + } + } + else if (key == "cookies") + { + if (CLuaArguments* cookies; argValue->TryGetTable(cookies)) + { + for (size_t j = 0; j < cookies->Count(); j += 2) + { + argName = (*cookies)[j + 0]; + argValue = (*cookies)[j + 1]; + + std::string_view n, v; + + if (argName->TryGetString(n) && argValue->TryGetString(v)) + { + CookieParameters cookie; + cookie["name"] = std::string{n}; + cookie["value"] = std::string{v}; + httpResponse.SetCookie(cookie); + } + else if (CLuaArguments* properties; argValue->TryGetTable(properties)) + { + CookieParameters cookie; + + for (size_t k = 0; k < properties->Count(); k += 2) + { + argName = (*properties)[k + 0]; + argValue = (*properties)[k + 1]; + + if (argName->TryGetString(n) && argValue->TryGetString(v)) + { + cookie[std::string{n}] = std::string{v}; + } + } + + httpResponse.SetCookie(cookie); + } + } + } + } + } + + if (!hasBody) + httpResponse.SetBody("", 0); + + return responseCode; +} + +HttpStatusCode CResource::HandleRequestRouter(HttpRequest* request, HttpResponse* response, CAccount* account) +{ + if (!IsHttpAccessAllowed(account)) + { + return g_pGame->GetHTTPD()->RequestLogin(request, response); + } + + if (!g_pGame->GetACLManager()->CanObjectUseRight(account->GetName().c_str(), CAccessControlListGroupObject::OBJECT_TYPE_USER, m_httpRouterAclRight.c_str(), + CAccessControlListRight::RIGHT_TYPE_RESOURCE, true)) + { + return g_pGame->GetHTTPD()->RequestLogin(request, response); + } + + if (m_eState != EResourceState::Running) + { + const char* errorText = "error: resource not running"; + response->SetBody(errorText, strlen(errorText)); + return HTTP_STATUS_CODE_500_INTERNAL_SERVER_ERROR; + } + + if (m_httpRouterCheck == HTTP_ROUTER_CHECK_PENDING) + { + lua_State* L = m_pVM->GetVM(); + lua_pushlstring(L, m_httpRouterFunction.c_str(), m_httpRouterFunction.size()); + lua_gettable(L, LUA_GLOBALSINDEX); + { + m_httpRouterCheck = lua_isfunction(L, -1) ? HTTP_ROUTER_CHECK_PASSED : HTTP_ROUTER_CHECK_FAILED; + } + lua_pop(L, 1); + } + + if (m_httpRouterCheck != HTTP_ROUTER_CHECK_PASSED) + { + const char* errorText = "error: router function unavailable"; + response->SetBody(errorText, strlen(errorText)); + return HTTP_STATUS_CODE_500_INTERNAL_SERVER_ERROR; + } + + std::string_view path = std::string_view{request->sOriginalUri}.substr(1 /* first slash */ + m_strResourceName.size()); + + if (const auto index = path.find_first_of("?&"); index != std::string_view::npos) + { + path = path.substr(0, index); + } + + CLuaArguments luaRequest; + { + luaRequest.PushString("account"); + luaRequest.PushAccount(account); + + luaRequest.PushString("method"); + switch (request->nRequestMethod) + { + case REQUESTMETHOD_OPTIONS: + luaRequest.PushString("OPTIONS"); + break; + case REQUESTMETHOD_GET: + luaRequest.PushString("GET"); + break; + case REQUESTMETHOD_HEAD: + luaRequest.PushString("HEAD"); + break; + case REQUESTMETHOD_POST: + luaRequest.PushString("POST"); + break; + case REQUESTMETHOD_PUT: + luaRequest.PushString("PUT"); + break; + case REQUESTMETHOD_DELETE: + luaRequest.PushString("DELETE"); + break; + case REQUESTMETHOD_TRACE: + luaRequest.PushString("TRACE"); + break; + case REQUESTMETHOD_CONNECT: + luaRequest.PushString("CONNECT"); + break; + case REQUESTMETHOD_PATCH: + luaRequest.PushString("PATCH"); + break; + default: + luaRequest.PushString("*"); + break; + } + + luaRequest.PushString("path"); + luaRequest.PushString(path); + + luaRequest.PushString("absolutePath"); + luaRequest.PushString(request->sOriginalUri); + + luaRequest.PushString("hostname"); + luaRequest.PushString(request->GetAddress()); + + luaRequest.PushString("port"); + luaRequest.PushNumber(request->GetPort()); + + luaRequest.PushString("body"); + luaRequest.PushString(request->sBody); + + CLuaArguments query; + for (const auto& pair : request->oQueryValueMap) + { + query.PushString(pair.first); + query.PushString(pair.second.sBody); + } + luaRequest.PushString("query"); + luaRequest.PushTable(&query); + + CLuaArguments formData; + for (const auto& pair : request->oFormValueMap) + { + formData.PushString(pair.first); + formData.PushString(pair.second.sBody); + } + luaRequest.PushString("formData"); + luaRequest.PushTable(&formData); + + CLuaArguments cookies; + for (const auto& pair : request->oCookieMap) + { + cookies.PushString(pair.first); + cookies.PushString(pair.second); + } + luaRequest.PushString("cookies"); + luaRequest.PushTable(&cookies); + + CLuaArguments headers; + for (const auto& pair : request->oRequestHeaders) + { + headers.PushString(pair.first); + headers.PushString(pair.second); + } + luaRequest.PushString("headers"); + luaRequest.PushTable(&headers); + } + + CLuaArguments arguments; + arguments.PushTable(&luaRequest); + + CLuaArguments results; + + if (!arguments.CallGlobal(m_pVM, m_httpRouterFunction.c_str(), &results)) + { + const char* errorText = "error: router function error"; + response->SetBody(errorText, strlen(errorText)); + return HTTP_STATUS_CODE_500_INTERNAL_SERVER_ERROR; + } + + HttpStatusCode responseCode = HTTP_STATUS_CODE_200_OK; + + if (results.Count() >= 1) + { + if (lua_Number statusCode; results[0]->TryGetNumber(statusCode)) + { + response->SetBody("", 0); + responseCode = static_cast(statusCode); + } + else if (CLuaArguments* luaResponse; results[0]->TryGetTable(luaResponse)) + { + responseCode = ParseLuaHttpRouterResponse(*luaResponse, *response); + } + } + else + { + response->SetBody("", 0); + } + + return responseCode; } -ResponseCode CResource::HandleRequestActive(HttpRequest* ipoHttpRequest, HttpResponse* ipoHttpResponse, CAccount* pAccount) +HttpStatusCode CResource::HandleRequestActive(HttpRequest* ipoHttpRequest, HttpResponse* ipoHttpResponse, CAccount* pAccount) { const char* szUrl = ipoHttpRequest->sOriginalUri.c_str(); std::string strFile; @@ -2732,7 +3151,7 @@ ResponseCode CResource::HandleRequestActive(HttpRequest* ipoHttpRequest, HttpRes { SString err = "That resource is not running."; ipoHttpResponse->SetBody(err.c_str(), err.size()); - return HTTPRESPONSECODE_401_UNAUTHORIZED; + return HTTP_STATUS_CODE_401_UNAUTHORIZED; } } // Send back any clientfile. Otherwise keep looking for server files matching @@ -2778,7 +3197,7 @@ ResponseCode CResource::HandleRequestActive(HttpRequest* ipoHttpRequest, HttpRes SString err = "That resource file could not be found in that resource."; ipoHttpResponse->SetBody(err.c_str(), err.size()); - return HTTPRESPONSECODE_404_NOTFOUND; + return HTTP_STATUS_CODE_404_NOT_FOUND; } // Return true if http access allowed for the supplied account diff --git a/Server/mods/deathmatch/logic/CResource.h b/Server/mods/deathmatch/logic/CResource.h index 30b6698148..1a622be3cf 100644 --- a/Server/mods/deathmatch/logic/CResource.h +++ b/Server/mods/deathmatch/logic/CResource.h @@ -250,9 +250,11 @@ class CResource : public EHS bool CheckIfStartable(); void DisplayInfo(); - bool GetFilePath(const char* szFilename, std::string& strPath); - const std::string& GetResourceDirectoryPath() const { return m_strResourceDirectoryPath; } - const std::string& GetResourceCacheDirectoryPath() const { return m_strResourceCachePath; } + bool GetFilePath(const char* szFilename, std::string& strPath); + std::vector GetFilePaths(const char* szFilename); + + const std::string& GetResourceDirectoryPath() const { return m_strResourceDirectoryPath; } + const std::string& GetResourceCacheDirectoryPath() const { return m_strResourceCachePath; } std::list& GetFiles() { return m_ResourceFiles; } size_t GetFileCount() const noexcept { return m_ResourceFiles.size(); } @@ -268,6 +270,8 @@ class CResource : public EHS void OnPlayerJoin(CPlayer& Player); void SendNoClientCacheScripts(CPlayer* pPlayer = nullptr); + void OnResourceStateChange(const char* state) noexcept; + CDummy* GetResourceRootElement() { return m_pResourceElement; } const CDummy* GetResourceRootElement() const noexcept { return m_pResourceElement; } @@ -283,7 +287,7 @@ class CResource : public EHS bool IsResourceZip() const noexcept { return m_bResourceIsZip; } bool UnzipResource(); - ResponseCode HandleRequest(HttpRequest* ipoHttpRequest, HttpResponse* ipoHttpResponse); + HttpStatusCode HandleRequest(HttpRequest* ipoHttpRequest, HttpResponse* ipoHttpResponse); std::list::iterator IterBegin() { return m_ResourceFiles.begin(); } std::list::const_iterator IterBegin() const noexcept { return m_ResourceFiles.begin(); } @@ -355,9 +359,10 @@ class CResource : public EHS bool DestroyVM(); void TidyUp(); - ResponseCode HandleRequestActive(HttpRequest* ipoHttpRequest, HttpResponse* ipoHttpResponse, CAccount* pAccount); - ResponseCode HandleRequestCall(HttpRequest* ipoHttpRequest, HttpResponse* ipoHttpResponse, CAccount* pAccount); - bool IsHttpAccessAllowed(CAccount* pAccount); + HttpStatusCode HandleRequestRouter(HttpRequest* request, HttpResponse* response, CAccount* account); + HttpStatusCode HandleRequestActive(HttpRequest* ipoHttpRequest, HttpResponse* ipoHttpResponse, CAccount* pAccount); + HttpStatusCode HandleRequestCall(HttpRequest* ipoHttpRequest, HttpResponse* ipoHttpResponse, CAccount* pAccount); + bool IsHttpAccessAllowed(CAccount* pAccount); private: EResourceState m_eState = EResourceState::None; @@ -393,10 +398,14 @@ class CResource : public EHS KeyValueMap m_Info; std::list m_IncludedResources; // we store them here temporarily, then read them once all the resources are loaded std::list m_ResourceFiles; + std::map m_ResourceFilesCountPerDir; std::list m_Dependents; // resources that have "included" or loaded this one std::list m_ExportedFunctions; std::list m_TemporaryIncludes; // started by startResource script command + int m_httpRouterCheck{}; + std::string m_httpRouterFunction; + std::string m_httpRouterAclRight; std::string m_strCircularInclude; SString m_strFailureReason; unzFile m_zipfile = nullptr; diff --git a/Server/mods/deathmatch/logic/CResourceChecker.Data.h b/Server/mods/deathmatch/logic/CResourceChecker.Data.h index 47292bb388..e6bdee9212 100644 --- a/Server/mods/deathmatch/logic/CResourceChecker.Data.h +++ b/Server/mods/deathmatch/logic/CResourceChecker.Data.h @@ -43,6 +43,16 @@ namespace {"fileGetContents", "1.6.0-9.21938"}, {"engineStreamingSetModelCacheLimits", "1.6.0-9.21946"}, {"engineStreamingRestoreBufferSize", "1.6.0-9.22195"}, + {"createBuilding", "1.6.0-9.22410"}, + {"restoreAllGameBuildings", "1.6.0-9.22420"}, + {"removeAllGameBuildings", "1.6.0-9.22420"}, + {"pathListDir", "1.6.0-9.22470"}, + {"pathIsFile", "1.6.0-9.22470"}, + {"pathIsDirectory", "1.6.0-9.22470"}, + {"engineGetPoolCapacity", "1.6.0-9.22471"}, + {"engineGetPoolDefaultCapacity", "1.6.0-9.22471"}, + {"engineGetPoolUsedCapacity", "1.6.0-9.22471"}, + {"engineSetPoolCapacity", "1.6.0-9.22471"}, }; SVersionItem serverFunctionInitList[] = { @@ -52,6 +62,15 @@ namespace {"fileGetContents", "1.6.0-9.21938"}, {"isWorldSpecialPropertyEnabled", "1.6.0-9.22195"}, {"setWorldSpecialPropertyEnabled", "1.6.0-9.22195"}, + {"onResourceStateChange", "1.6.0-9.22430"}, + {"isObjectMoving", "1.6.0-9.22457"}, + {"onPlayerTriggerInvalidEvent", "1.6.0-9.22459"}, + {"pathListDir", "1.6.0-9.22470"}, + {"pathIsFile", "1.6.0-9.22470"}, + {"pathIsDirectory", "1.6.0-9.22470"}, + {"onAccountCreate", "1.6.0-9.22470"}, + {"onAccountRemove", "1.6.0-9.22470"}, + {"getAccountType", "1.6.0-9.22470"}, }; // @@ -146,6 +165,12 @@ namespace // Ped jetpacks //{false, "doesPedHaveJetPack", "isPedWearingJetpack"}, + + // Base Encoding & Decoding + {false, "base64Encode", "encodeString"}, + {false, "base64Decode", "decodeString"}, + + {false, "setHelicopterRotorSpeed", "setVehicleRotorSpeed"} }; SDeprecatedItem serverDeprecatedList[] = { @@ -244,5 +269,9 @@ namespace // Old Discord implementation (see #2499) {true, "setPlayerDiscordJoinParams", "See GitHub PR #2499 for more details"}, + + // Base Encoding & Decoding + {false, "base64Encode", "encodeString"}, + {false, "base64Decode", "decodeString"} }; } // namespace diff --git a/Server/mods/deathmatch/logic/CResourceClientScriptItem.cpp b/Server/mods/deathmatch/logic/CResourceClientScriptItem.cpp index cf5426b955..714db9538c 100644 --- a/Server/mods/deathmatch/logic/CResourceClientScriptItem.cpp +++ b/Server/mods/deathmatch/logic/CResourceClientScriptItem.cpp @@ -37,13 +37,13 @@ CResourceClientScriptItem::~CResourceClientScriptItem() { } -ResponseCode CResourceClientScriptItem::Request(HttpRequest* ipoHttpRequest, HttpResponse* ipoHttpResponse) +HttpStatusCode CResourceClientScriptItem::Request(HttpRequest* ipoHttpRequest, HttpResponse* ipoHttpResponse) { if (IsNoClientCache() == true) { const char* errmsg = "This script is not client cacheable"; ipoHttpResponse->SetBody(errmsg, strlen(errmsg)); - return HTTPRESPONSECODE_403_FORBIDDEN; + return HTTP_STATUS_CODE_403_FORBIDDEN; } else return CResourceFile::Request(ipoHttpRequest, ipoHttpResponse); diff --git a/Server/mods/deathmatch/logic/CResourceClientScriptItem.h b/Server/mods/deathmatch/logic/CResourceClientScriptItem.h index 8fee946bcc..fcb8cbd483 100644 --- a/Server/mods/deathmatch/logic/CResourceClientScriptItem.h +++ b/Server/mods/deathmatch/logic/CResourceClientScriptItem.h @@ -25,7 +25,7 @@ class CResourceClientScriptItem : public CResourceFile bool IsNoClientCache() const { return m_bIsNoClientCache; } const SString& GetSourceCode() const { return m_sourceCode; } - ResponseCode Request(HttpRequest* ipoHttpRequest, HttpResponse* ipoHttpResponse); + HttpStatusCode Request(HttpRequest* ipoHttpRequest, HttpResponse* ipoHttpResponse); private: bool m_bIsNoClientCache; diff --git a/Server/mods/deathmatch/logic/CResourceFile.cpp b/Server/mods/deathmatch/logic/CResourceFile.cpp index 3f47b57de4..256e8f076b 100644 --- a/Server/mods/deathmatch/logic/CResourceFile.cpp +++ b/Server/mods/deathmatch/logic/CResourceFile.cpp @@ -56,7 +56,7 @@ CResourceFile::~CResourceFile() { } -ResponseCode CResourceFile::Request(HttpRequest* ipoHttpRequest, HttpResponse* ipoHttpResponse) +HttpStatusCode CResourceFile::Request(HttpRequest* ipoHttpRequest, HttpResponse* ipoHttpResponse) { // HACK - Use http-client-files if possible as the resources directory may have been changed since the resource was loaded. SString strDstFilePath = GetCachedPathFilename(); @@ -84,12 +84,12 @@ ResponseCode CResourceFile::Request(HttpRequest* ipoHttpRequest, HttpResponse* i ipoHttpResponse->oResponseHeaders["content-type"] = "application/octet-stream"; // not really the right mime-type ipoHttpResponse->SetBody(szBuffer, lBufferLength); delete[] szBuffer; - return HTTPRESPONSECODE_200_OK; + return HTTP_STATUS_CODE_200_OK; } else { ipoHttpResponse->SetBody("Can't read file!", strlen("Can't read file!")); - return HTTPRESPONSECODE_500_INTERNALSERVERERROR; + return HTTP_STATUS_CODE_500_INTERNAL_SERVER_ERROR; } } diff --git a/Server/mods/deathmatch/logic/CResourceFile.h b/Server/mods/deathmatch/logic/CResourceFile.h index e58e61a72f..b61f332f36 100644 --- a/Server/mods/deathmatch/logic/CResourceFile.h +++ b/Server/mods/deathmatch/logic/CResourceFile.h @@ -52,7 +52,7 @@ class CResourceFile CResourceFile(class CResource* resource, const char* szShortName, const char* szResourceFileName, CXMLAttributes* xmlAttributes); virtual ~CResourceFile(); - virtual ResponseCode Request(HttpRequest* ipoHttpRequest, HttpResponse* ipoHttpResponse); + virtual HttpStatusCode Request(HttpRequest* ipoHttpRequest, HttpResponse* ipoHttpResponse); virtual bool Start() = 0; virtual bool Stop() = 0; diff --git a/Server/mods/deathmatch/logic/CResourceHTMLItem.cpp b/Server/mods/deathmatch/logic/CResourceHTMLItem.cpp index 2216526d94..978f2f4a3a 100644 --- a/Server/mods/deathmatch/logic/CResourceHTMLItem.cpp +++ b/Server/mods/deathmatch/logic/CResourceHTMLItem.cpp @@ -41,7 +41,7 @@ CResourceHTMLItem::~CResourceHTMLItem() Stop(); } -ResponseCode CResourceHTMLItem::Request(HttpRequest* ipoHttpRequest, HttpResponse* ipoHttpResponse, CAccount* account) +HttpStatusCode CResourceHTMLItem::Request(HttpRequest* ipoHttpRequest, HttpResponse* ipoHttpResponse, CAccount* account) { if (!m_pVM) Start(); @@ -49,12 +49,12 @@ ResponseCode CResourceHTMLItem::Request(HttpRequest* ipoHttpRequest, HttpRespons if (m_bIsBeingRequested) { ipoHttpResponse->SetBody("Busy!", strlen("Busy!")); - return HTTPRESPONSECODE_500_INTERNALSERVERERROR; + return HTTP_STATUS_CODE_500_INTERNAL_SERVER_ERROR; } m_bIsBeingRequested = true; - m_responseCode = HTTPRESPONSECODE_200_OK; + m_responseCode = HTTP_STATUS_CODE_200_OK; if (!m_bIsRaw) { @@ -108,6 +108,9 @@ ResponseCode CResourceHTMLItem::Request(HttpRequest* ipoHttpRequest, HttpRespons case REQUESTMETHOD_CONNECT: sMethod = "CONNECT"; break; + case REQUESTMETHOD_PATCH: + sMethod = "PATCH"; + break; case REQUESTMETHOD_LAST: sMethod = "LAST"; break; @@ -173,7 +176,7 @@ void CResourceHTMLItem::SetResponseHeader(const char* szHeaderName, const char* void CResourceHTMLItem::SetResponseCode(int responseCode) { - m_responseCode = (ResponseCode)responseCode; + m_responseCode = static_cast(responseCode); } void CResourceHTMLItem::SetResponseCookie(const char* szCookieName, const char* szCookieValue) diff --git a/Server/mods/deathmatch/logic/CResourceHTMLItem.h b/Server/mods/deathmatch/logic/CResourceHTMLItem.h index fe0ec78e34..5be5bbf486 100644 --- a/Server/mods/deathmatch/logic/CResourceHTMLItem.h +++ b/Server/mods/deathmatch/logic/CResourceHTMLItem.h @@ -25,10 +25,10 @@ class CResourceHTMLItem : public CResourceFile bool bIsRaw, bool bRestricted, bool bOOPEnabled); ~CResourceHTMLItem(); - bool Start(); - bool Stop(); - ResponseCode Request(HttpRequest* ipoHttpRequest, HttpResponse* ipoHttpResponse, class CAccount* account); - bool AppendToPageBuffer(const char* szText, size_t length = 0); + bool Start(); + bool Stop(); + HttpStatusCode Request(HttpRequest* ipoHttpRequest, HttpResponse* ipoHttpResponse, class CAccount* account); + bool AppendToPageBuffer(const char* szText, size_t length = 0); void SetResponseHeader(const char* szHeaderName, const char* szHeaderValue); void SetResponseCode(int responseCode); @@ -53,6 +53,6 @@ class CResourceHTMLItem : public CResourceFile bool m_bOOPEnabled; - ResponseCode m_responseCode; - HttpResponse* m_currentResponse; + HttpStatusCode m_responseCode; + HttpResponse* m_currentResponse; }; diff --git a/Server/mods/deathmatch/logic/CScriptDebugging.cpp b/Server/mods/deathmatch/logic/CScriptDebugging.cpp index 45a131374e..8c38aed824 100644 --- a/Server/mods/deathmatch/logic/CScriptDebugging.cpp +++ b/Server/mods/deathmatch/logic/CScriptDebugging.cpp @@ -146,12 +146,13 @@ void CScriptDebugging::PrintLog(const char* szText) void CScriptDebugging::Broadcast(const CPacket& Packet, unsigned int uiMinimumDebugLevel) { // Tell everyone we log to about it - list::const_iterator iter = m_Players.begin(); - for (; iter != m_Players.end(); iter++) + for (const auto& pPlayer : m_Players) { - if ((*iter)->m_uiScriptDebugLevel >= uiMinimumDebugLevel) + bool sufficientDebugLevel = CheckForSufficientDebugLevel(pPlayer->m_uiScriptDebugLevel, uiMinimumDebugLevel); + + if (sufficientDebugLevel) { - (*iter)->Send(Packet); + pPlayer->Send(Packet); } } } diff --git a/Server/mods/deathmatch/logic/CScriptDebugging.h b/Server/mods/deathmatch/logic/CScriptDebugging.h index 116b4825b2..e6ef81a0e1 100644 --- a/Server/mods/deathmatch/logic/CScriptDebugging.h +++ b/Server/mods/deathmatch/logic/CScriptDebugging.h @@ -73,6 +73,7 @@ class CScriptDebugging unsigned char ucGreen = 255, unsigned char ucBlue = 255); void PrintLog(const char* szText); + bool CheckForSufficientDebugLevel(std::uint8_t playerDebugLevel, std::uint8_t messageDebugLevel) const noexcept; void Broadcast(const CPacket& Packet, unsigned int uiMinimumDebugLevel); unsigned int m_uiLogFileLevel; diff --git a/Server/mods/deathmatch/logic/CStaticFunctionDefinitions.cpp b/Server/mods/deathmatch/logic/CStaticFunctionDefinitions.cpp index 0542dce5fd..ad06e54a70 100644 --- a/Server/mods/deathmatch/logic/CStaticFunctionDefinitions.cpp +++ b/Server/mods/deathmatch/logic/CStaticFunctionDefinitions.cpp @@ -1,11 +1,11 @@ /***************************************************************************** * - * PROJECT: Multi Theft Auto v1.0 + * PROJECT: Multi Theft Auto * LICENSE: See LICENSE in the top level directory - * FILE: mods/deathmatch/logic/CStaticFunctionDefinitions.cpp + * FILE: Server/mods/deathmatch/logic/CStaticFunctionDefinitions.cpp * PURPOSE: Lua static function definitions class * - * Multi Theft Auto is available from http://www.multitheftauto.com/ + * Multi Theft Auto is available from https://multitheftauto.com/ * *****************************************************************************/ @@ -328,19 +328,36 @@ bool CStaticFunctionDefinitions::DestroyElement(CElement* pElement) // We can't destroy the root or a player/remote client/console int iType = pElement->GetType(); - if (pElement == m_pMapManager->GetRootElement() || iType == CElement::PLAYER || iType == CElement::CONSOLE || + if (pElement == m_pMapManager->GetRootElement() || iType == CElement::PLAYER || iType == CElement::CONSOLE || g_pGame->GetResourceManager()->IsAResourceElement(pElement)) { return false; } + if (iType == CElement::TEAM) { // Its team trigger onPlayerTeamChange for each player in the team + CTeam* pTeam = static_cast(pElement); + + auto iterBegin = pTeam->PlayersBegin(); + auto iterEnd = pTeam->PlayersEnd(); + CLuaArguments arguments; + + for (auto iter = iterBegin; iter != iterEnd; ++iter) + { + CPlayer* player = *iter; + arguments.PushElement(pTeam); // Return team element as oldteam + arguments.PushNil(); // No new team return nil + player->CallEvent("onPlayerTeamChange", arguments); + arguments.DeleteArguments(); + } + } + // Tell everyone to destroy it if this is not a per-player entity if (IS_PERPLAYER_ENTITY(pElement)) { // Unsync it (will destroy it for those that know about it) CPerPlayerEntity* pEntity = static_cast(pElement); pEntity->Sync(false); - } + } // Tell everyone to destroy it CEntityRemovePacket Packet; @@ -1637,24 +1654,15 @@ bool CStaticFunctionDefinitions::SetElementHealth(CElement* pElement, float fHea case CElement::PLAYER: { CPed* pPed = static_cast(pElement); - if (pPed->IsSpawned()) - { - // Limit their max health to what the stat says - float fMaxHealth = pPed->GetMaxHealth(); - if (fHealth > fMaxHealth) - fHealth = fMaxHealth; + if (!pPed->IsSpawned()) + return false; - // Do not set the health below zero - if (fHealth < 0.0f) - fHealth = 0.0f; + fHealth = Clamp(0.0f, fHealth, pPed->GetMaxHealth()); + pPed->SetHealth(fHealth); + + if (pPed->IsDead() && fHealth > 0.0f) + pPed->SetIsDead(false); - // This makes sure the health is set to what will get reported - unsigned char ucHealth = static_cast(fHealth * 1.25f); - fHealth = static_cast(ucHealth) / 1.25f; - pPed->SetHealth(fHealth); - } - else - return false; break; } case CElement::VEHICLE: @@ -3733,6 +3741,8 @@ bool CStaticFunctionDefinitions::KillPed(CElement* pElement, CElement* pKiller, else Arguments.PushBoolean(false); Arguments.PushBoolean(bStealth); + Arguments.PushBoolean(false); + Arguments.PushBoolean(false); // TODO: change to onPedWasted if (IS_PLAYER(pPed)) { @@ -4121,6 +4131,8 @@ bool CStaticFunctionDefinitions::SetPedWeaponSlot(CElement* pElement, unsigned c CPed* pPed = static_cast(pElement); if (pPed->IsSpawned()) { + pPed->SetWeaponSlot(ucWeaponSlot); + CBitStream BitStream; SWeaponSlotSync slot; @@ -4854,7 +4866,7 @@ bool CStaticFunctionDefinitions::SetWeaponAmmo(CElement* pElement, unsigned char } CVehicle* CStaticFunctionDefinitions::CreateVehicle(CResource* pResource, unsigned short usModel, const CVector& vecPosition, const CVector& vecRotation, - const char* szRegPlate, unsigned char ucVariant, unsigned char ucVariant2) + const char* szRegPlate, unsigned char ucVariant, unsigned char ucVariant2, bool bSynced) { unsigned char ucVariation = ucVariant; unsigned char ucVariation2 = ucVariant2; @@ -4873,6 +4885,7 @@ CVehicle* CStaticFunctionDefinitions::CreateVehicle(CResource* pResource, unsign pVehicle->SetRotationDegrees(vecRotation); pVehicle->SetRespawnPosition(vecPosition); pVehicle->SetRespawnRotationDegrees(vecRotation); + pVehicle->SetUnoccupiedSyncable(bSynced); if (szRegPlate && szRegPlate[0]) pVehicle->SetRegPlate(szRegPlate); @@ -4991,6 +5004,7 @@ bool CStaticFunctionDefinitions::RemoveVehicleSirens(CVehicle* pVehicle) assert(pVehicle); pVehicle->m_tSirenBeaconInfo.m_bOverrideSirens = false; + pVehicle->SetSirenActive(false); pVehicle->RemoveVehicleSirens(); CBitStream BitStream; @@ -7640,7 +7654,7 @@ bool CStaticFunctionDefinitions::SetVehicleDoorOpenRatio(CElement* pElement, uns } CMarker* CStaticFunctionDefinitions::CreateMarker(CResource* pResource, const CVector& vecPosition, const char* szType, float fSize, const SColor color, - CElement* pVisibleTo) + CElement* pVisibleTo, bool ignoreAlphaLimits) { assert(szType); @@ -7656,6 +7670,7 @@ CMarker* CStaticFunctionDefinitions::CreateMarker(CResource* pResource, const CV // Set the properties pMarker->SetPosition(vecPosition); pMarker->SetMarkerType(ucType); + pMarker->SetIgnoreAlphaLimits(ignoreAlphaLimits); pMarker->SetColor(color); pMarker->SetSize(fSize); @@ -7828,6 +7843,24 @@ bool CStaticFunctionDefinitions::SetMarkerIcon(CElement* pElement, const char* s return false; } +bool CStaticFunctionDefinitions::SetMarkerTargetArrowProperties(CElement* pElement, const SColor color, float size) +{ + RUN_CHILDREN(SetMarkerTargetArrowProperties(*iter, color, size)) + + if (!IS_MARKER(pElement)) + return false; + + CMarker* marker = static_cast(pElement); + if (!marker) + return false; + + if (!marker->HasTarget() || marker->GetMarkerType() != CMarker::TYPE_CHECKPOINT) + return false; + + marker->SetTargetArrowProperties(color, size); + return true; +} + CBlip* CStaticFunctionDefinitions::CreateBlip(CResource* pResource, const CVector& vecPosition, unsigned char ucIcon, unsigned char ucSize, const SColor color, short sOrdering, unsigned short usVisibleDistance, CElement* pVisibleTo) { @@ -8235,6 +8268,27 @@ bool CStaticFunctionDefinitions::StopObject(CElement* pElement) return false; } +bool CStaticFunctionDefinitions::BreakObject(CElement* pElement) +{ + RUN_CHILDREN(BreakObject(*iter)); + + if (!IS_OBJECT(pElement)) + return false; + + CObject* pObject = static_cast(pElement); + + if (!pObject) + return false; + + if (!pObject->IsBreakable()) + return false; + + CBitStream BitStream; + m_pPlayerManager->BroadcastOnlyJoined(CElementRPCPacket(pObject, BREAK_OBJECT, *BitStream.pBitStream)); + + return true; +} + bool CStaticFunctionDefinitions::SetObjectVisibleInAllDimensions(CElement* pElement, bool bVisible, unsigned short usNewDimension) { RUN_CHILDREN(SetObjectVisibleInAllDimensions(*iter, bVisible, usNewDimension)) @@ -8304,6 +8358,43 @@ bool CStaticFunctionDefinitions::SetObjectBreakable(CElement* pElement, const bo return false; } +bool CStaticFunctionDefinitions::RespawnObject(CElement* const pElement) noexcept +{ + RUN_CHILDREN(RespawnObject(*iter)); + + if (!IS_OBJECT(pElement)) + return false; + + CObject* pObject = static_cast(pElement); + if (!pObject) + return false; + + CBitStream BitStream; + m_pPlayerManager->BroadcastOnlyJoined(CElementRPCPacket(pObject, RESPAWN_OBJECT, *BitStream.pBitStream)); + + return true; +} + +bool CStaticFunctionDefinitions::ToggleObjectRespawn(CElement* const pElement, const bool bRespawn) noexcept +{ + RUN_CHILDREN(ToggleObjectRespawn(*iter, bRespawn)); + + if (!IS_OBJECT(pElement)) + return false; + + CObject* pObject = static_cast(pElement); + if (!pObject) + return false; + + pObject->SetRespawnEnabled(bRespawn); + + CBitStream BitStream; + BitStream->WriteBit(bRespawn); + m_pPlayerManager->BroadcastOnlyJoined(CElementRPCPacket(pObject, TOGGLE_OBJECT_RESPAWN, *BitStream.pBitStream)); + + return true; +} + CRadarArea* CStaticFunctionDefinitions::CreateRadarArea(CResource* pResource, const CVector2D& vecPosition2D, const CVector2D& vecSize, const SColor color, CElement* pVisibleTo) { @@ -9204,21 +9295,34 @@ bool CStaticFunctionDefinitions::SetPlayerTeam(CPlayer* pPlayer, CTeam* pTeam) { assert(pPlayer); + CTeam* currentTeam = pPlayer->GetTeam(); // If its a different team - if (pTeam != pPlayer->GetTeam()) + if (pTeam == currentTeam) + return false; + + // Call the Event + CLuaArguments Arguments; + if (currentTeam) { - // Change his team - pPlayer->SetTeam(pTeam, true); + Arguments.PushElement(currentTeam); + } + else + { + Arguments.PushNil(); // No oldTeam return nil + } + Arguments.PushElement(pTeam); + if (!pPlayer->CallEvent("onPlayerTeamChange", Arguments)) + return false; // Event cancelled, return false - // Tell everyone his new team - CBitStream BitStream; - BitStream.pBitStream->Write(pTeam ? pTeam->GetID() : INVALID_ELEMENT_ID); - m_pPlayerManager->BroadcastOnlyJoined(CElementRPCPacket(pPlayer, SET_PLAYER_TEAM, *BitStream.pBitStream)); + // Change his team + pPlayer->SetTeam(pTeam, true); - return true; - } + // Tell everyone his new team + CBitStream BitStream; + BitStream.pBitStream->Write(pTeam ? pTeam->GetID() : INVALID_ELEMENT_ID); + m_pPlayerManager->BroadcastOnlyJoined(CElementRPCPacket(pPlayer, SET_PLAYER_TEAM, *BitStream.pBitStream)); - return false; + return true; } bool CStaticFunctionDefinitions::SetTeamFriendlyFire(CTeam* pTeam, bool bFriendlyFire) diff --git a/Server/mods/deathmatch/logic/CStaticFunctionDefinitions.h b/Server/mods/deathmatch/logic/CStaticFunctionDefinitions.h index fe9d20ebf8..bb0e99c0ee 100644 --- a/Server/mods/deathmatch/logic/CStaticFunctionDefinitions.h +++ b/Server/mods/deathmatch/logic/CStaticFunctionDefinitions.h @@ -240,7 +240,7 @@ class CStaticFunctionDefinitions // Vehicle create/destroy functions static CVehicle* CreateVehicle(CResource* pResource, unsigned short usModel, const CVector& vecPosition, const CVector& vecRotation, const char* szRegPlate, - unsigned char ucVariant, unsigned char ucVariant2); + unsigned char ucVariant, unsigned char ucVariant2, bool bSynced); // Vehicle get functions static bool GetVehicleVariant(CVehicle* pVehicle, unsigned char& ucVariant, unsigned char& ucVariant2); @@ -368,7 +368,7 @@ class CStaticFunctionDefinitions static bool RemoveVehicleSirens(CVehicle* pVehicle); // Marker create/destroy functions - static CMarker* CreateMarker(CResource* pResource, const CVector& vecPosition, const char* szType, float fSize, const SColor color, CElement* pVisibleTo); + static CMarker* CreateMarker(CResource* pResource, const CVector& vecPosition, const char* szType, float fSize, const SColor color, CElement* pVisibleTo, bool ignoreAlphaLimits); // Marker get functions static bool GetMarkerCount(unsigned int& uiCount); @@ -385,6 +385,8 @@ class CStaticFunctionDefinitions static bool SetMarkerTarget(CElement* pElement, const CVector* pTarget); static bool SetMarkerIcon(CElement* pElement, const char* szIcon); + static bool SetMarkerTargetArrowProperties(CElement* Element, const SColor color, float size); + // Blip create/destroy functions static CBlip* CreateBlip(CResource* pResource, const CVector& vecPosition, unsigned char ucIcon, unsigned char ucSize, const SColor color, short sOrdering, unsigned short usVisibleDistance, CElement* pVisibleTo); @@ -419,8 +421,11 @@ class CStaticFunctionDefinitions static bool MoveObject(CResource* pResource, CElement* pElement, unsigned long ulTime, const CVector& vecPosition, const CVector& vecRotation, CEasingCurve::eType a_easingType, double a_fEasingPeriod, double a_fEasingAmplitude, double a_fEasingOvershoot); static bool StopObject(CElement* pElement); + static bool BreakObject(CElement* pElement); static bool SetObjectVisibleInAllDimensions(CElement* pElement, bool bVisible, unsigned short usNewDimension = 0); static bool SetObjectBreakable(CElement* pElement, const bool bBreakable); + static bool RespawnObject(CElement* const pElement) noexcept; + static bool ToggleObjectRespawn(CElement* const pElement, const bool bRespawn) noexcept; // Radar area create/destroy funcs static CRadarArea* CreateRadarArea(CResource* pResource, const CVector2D& vecPosition, const CVector2D& vecSize, const SColor color, CElement* pVisibleTo); diff --git a/Server/mods/deathmatch/logic/CUnoccupiedVehicleSync.cpp b/Server/mods/deathmatch/logic/CUnoccupiedVehicleSync.cpp index 1bbcb69569..4159cd11b0 100644 --- a/Server/mods/deathmatch/logic/CUnoccupiedVehicleSync.cpp +++ b/Server/mods/deathmatch/logic/CUnoccupiedVehicleSync.cpp @@ -487,7 +487,9 @@ void CUnoccupiedVehicleSync::Packet_UnoccupiedVehiclePushSync(CUnoccupiedVehicle CVehicle* pVehicle = static_cast(pVehicleElement); // Is the player syncing this vehicle and there is no driver? Also only process // this packet if the time context matches. - if (pVehicle->GetSyncer() != pPlayer && pVehicle->GetTimeSinceLastPush() >= MIN_PUSH_ANTISPAM_RATE) + if (pVehicle->GetSyncer() != pPlayer && pVehicle->GetTimeSinceLastPush() >= MIN_PUSH_ANTISPAM_RATE && + IsPointNearPoint3D(pVehicle->GetPosition(), pPlayer->GetPosition(), g_TickRateSettings.iVehicleContactSyncRadius) + && pVehicle->GetDimension() == pPlayer->GetDimension()) { // Is there no player driver? CPed* pOccupant = pVehicle->GetOccupant(0); diff --git a/Server/mods/deathmatch/logic/CVehicle.h b/Server/mods/deathmatch/logic/CVehicle.h index ab3980fc40..10de01e625 100644 --- a/Server/mods/deathmatch/logic/CVehicle.h +++ b/Server/mods/deathmatch/logic/CVehicle.h @@ -321,9 +321,11 @@ class CVehicle final : public CElement void SetRespawnRotationDegrees(const CVector& vecRotation) { m_vecRespawnRotationDegrees = vecRotation; }; float GetRespawnHealth() { return m_fRespawnHealth; }; void SetRespawnHealth(float fHealth) { m_fRespawnHealth = fHealth; }; - bool GetRespawnEnabled() { return m_bRespawnEnabled; } + bool GetRespawnEnabled() const noexcept { return m_bRespawnEnabled; } void SetRespawnEnabled(bool bEnabled); + std::uint32_t GetBlowRespawnInterval() const noexcept { return m_ulBlowRespawnInterval; } void SetBlowRespawnInterval(unsigned long ulTime) { m_ulBlowRespawnInterval = ulTime; } + std::uint32_t GetIdleRespawnInterval() const noexcept { return m_ulIdleRespawnInterval; } void SetIdleRespawnInterval(unsigned long ulTime) { m_ulIdleRespawnInterval = ulTime; } void SpawnAt(const CVector& vecPosition, const CVector& vecRotation); diff --git a/Server/mods/deathmatch/logic/lua/CLuaArgument.cpp b/Server/mods/deathmatch/logic/lua/CLuaArgument.cpp index 6c2f02c377..1f36d20da7 100644 --- a/Server/mods/deathmatch/logic/lua/CLuaArgument.cpp +++ b/Server/mods/deathmatch/logic/lua/CLuaArgument.cpp @@ -325,11 +325,25 @@ void CLuaArgument::ReadNumber(double dNumber) m_Number = dNumber; } -void CLuaArgument::ReadString(const std::string& strString) +void CLuaArgument::ReadString(const std::string& string) { m_iType = LUA_TSTRING; DeleteTableData(); - m_strString = strString; + m_strString = string; +} + +void CLuaArgument::ReadString(const std::string_view& string) +{ + m_iType = LUA_TSTRING; + DeleteTableData(); + m_strString = string; +} + +void CLuaArgument::ReadString(const char* string) +{ + m_iType = LUA_TSTRING; + DeleteTableData(); + m_strString = string; } void CLuaArgument::ReadElement(CElement* pElement) @@ -724,6 +738,11 @@ bool CLuaArgument::WriteToBitStream(NetBitStreamInterface& bitStream, CFastHashM return true; } +bool CLuaArgument::IsTable() const noexcept +{ + return m_iType == LUA_TTABLE && m_pTableData && (m_pTableData->Count() % 2) == 0; +} + void CLuaArgument::LogUnableToPacketize(const char* szMessage) const { #ifdef MTA_DEBUG diff --git a/Server/mods/deathmatch/logic/lua/CLuaArgument.h b/Server/mods/deathmatch/logic/lua/CLuaArgument.h index bb6c8581f8..edf75b94de 100644 --- a/Server/mods/deathmatch/logic/lua/CLuaArgument.h +++ b/Server/mods/deathmatch/logic/lua/CLuaArgument.h @@ -43,7 +43,9 @@ class CLuaArgument void ReadBool(bool bBool); void ReadNumber(double dNumber); - void ReadString(const std::string& strString); + void ReadString(const std::string& string); + void ReadString(const std::string_view& string); + void ReadString(const char* string); void ReadElement(CElement* pElement); void ReadElementID(ElementID ID); void ReadScriptID(uint uiScriptID); @@ -55,6 +57,7 @@ class CLuaArgument lua_Number GetNumber() const { return m_Number; }; const std::string& GetString() { return m_strString; }; void* GetUserData() const { return m_pUserData; }; + CLuaArguments* GetTable() const { return m_pTableData; } CElement* GetElement() const; bool GetAsString(SString& strBuffer); @@ -66,6 +69,48 @@ class CLuaArgument bool IsEqualTo(const CLuaArgument& compareTo, std::set* knownTables = nullptr) const; + [[nodiscard]] bool IsString() const noexcept { return m_iType == LUA_TSTRING; } + + [[nodiscard]] bool TryGetString(std::string_view& string) const noexcept + { + if (IsString()) + { + string = m_strString; + return true; + } + + string = {}; + return false; + } + + [[nodiscard]] bool IsNumber() const noexcept { return m_iType == LUA_TNUMBER; } + + [[nodiscard]] bool TryGetNumber(lua_Number& number) const noexcept + { + if (IsNumber()) + { + number = m_Number; + return true; + } + + number = {}; + return false; + } + + [[nodiscard]] bool IsTable() const noexcept; + + [[nodiscard]] bool TryGetTable(CLuaArguments*& table) const noexcept + { + if (IsTable()) + { + table = m_pTableData; + return true; + } + + table = nullptr; + return false; + } + private: void LogUnableToPacketize(const char* szMessage) const; diff --git a/Server/mods/deathmatch/logic/lua/CLuaArguments.cpp b/Server/mods/deathmatch/logic/lua/CLuaArguments.cpp index 3feadfeedb..6557e7b3b2 100644 --- a/Server/mods/deathmatch/logic/lua/CLuaArguments.cpp +++ b/Server/mods/deathmatch/logic/lua/CLuaArguments.cpp @@ -197,11 +197,9 @@ void CLuaArguments::PushAsTable(lua_State* luaVM, CFastHashMap::const_iterator iter = Arguments.IterBegin(); - for (; iter != Arguments.IterEnd(); ++iter) + for (CLuaArgument* argument : Arguments) { - CLuaArgument* pArgument = new CLuaArgument(**iter); - m_Arguments.push_back(pArgument); + m_Arguments.push_back(new CLuaArgument(*argument)); } } @@ -358,12 +356,28 @@ CLuaArgument* CLuaArguments::PushArgument(const CLuaArgument& argument) return pArgument; } -CLuaArgument* CLuaArguments::PushString(const std::string& strString) +CLuaArgument* CLuaArguments::PushString(const std::string& string) { - CLuaArgument* pArgument = new CLuaArgument(); - pArgument->ReadString(strString); - m_Arguments.push_back(pArgument); - return pArgument; + CLuaArgument* arg = new CLuaArgument(); + arg->ReadString(string); + m_Arguments.push_back(arg); + return arg; +} + +CLuaArgument* CLuaArguments::PushString(const std::string_view& string) +{ + CLuaArgument* arg = new CLuaArgument(); + arg->ReadString(string); + m_Arguments.push_back(arg); + return arg; +} + +CLuaArgument* CLuaArguments::PushString(const char* string) +{ + CLuaArgument* arg = new CLuaArgument(); + arg->ReadString(string); + m_Arguments.push_back(arg); + return arg; } CLuaArgument* CLuaArguments::PushElement(CElement* pElement) diff --git a/Server/mods/deathmatch/logic/lua/CLuaArguments.h b/Server/mods/deathmatch/logic/lua/CLuaArguments.h index 87fd92be20..b23d8215d0 100644 --- a/Server/mods/deathmatch/logic/lua/CLuaArguments.h +++ b/Server/mods/deathmatch/logic/lua/CLuaArguments.h @@ -67,7 +67,9 @@ class CLuaArguments CLuaArgument* PushNil(); CLuaArgument* PushBoolean(bool bBool); CLuaArgument* PushNumber(double dNumber); - CLuaArgument* PushString(const std::string& strString); + CLuaArgument* PushString(const std::string& string); + CLuaArgument* PushString(const std::string_view& string); + CLuaArgument* PushString(const char* string); CLuaArgument* PushElement(CElement* pElement); CLuaArgument* PushBan(CBan* pBan); CLuaArgument* PushACL(CAccessControlList* pACL); @@ -95,9 +97,13 @@ class CLuaArguments bool ReadFromJSONObject(json_object* object, std::vector* pKnownTables = NULL); bool ReadFromJSONArray(json_object* object, std::vector* pKnownTables = NULL); - unsigned int Count() const { return static_cast(m_Arguments.size()); }; - std::vector::const_iterator IterBegin() const { return m_Arguments.begin(); }; - std::vector::const_iterator IterEnd() const { return m_Arguments.end(); }; + [[nodiscard]] bool IsNotEmpty() const noexcept { return !m_Arguments.empty(); } + [[nodiscard]] bool IsEmpty() const noexcept { return m_Arguments.empty(); } + + [[nodiscard]] std::vector::size_type Count() const noexcept { return m_Arguments.size(); } + + [[nodiscard]] std::vector::const_iterator begin() const noexcept { return m_Arguments.begin(); } + [[nodiscard]] std::vector::const_iterator end() const noexcept { return m_Arguments.end(); } bool IsEqualTo(const CLuaArguments& compareTo, std::set* knownTables = nullptr) const; diff --git a/Server/mods/deathmatch/logic/lua/CLuaMain.cpp b/Server/mods/deathmatch/logic/lua/CLuaMain.cpp index dd7df7f040..189d204c57 100644 --- a/Server/mods/deathmatch/logic/lua/CLuaMain.cpp +++ b/Server/mods/deathmatch/logic/lua/CLuaMain.cpp @@ -234,6 +234,9 @@ void CLuaMain::Initialize() lua_pushelement(m_luaVM, m_pResource->GetResourceRootElement()); lua_setglobal(m_luaVM, "resourceRoot"); + + lua_pushstring(m_luaVM, m_pResource->GetName()); + lua_setglobal(m_luaVM, "resourceName"); } void CLuaMain::LoadEmbeddedScripts() diff --git a/Server/mods/deathmatch/logic/lua/CLuaTimerManager.cpp b/Server/mods/deathmatch/logic/lua/CLuaTimerManager.cpp index fbd86eccaf..0af771b289 100644 --- a/Server/mods/deathmatch/logic/lua/CLuaTimerManager.cpp +++ b/Server/mods/deathmatch/logic/lua/CLuaTimerManager.cpp @@ -26,7 +26,10 @@ void CLuaTimerManager::DoPulse(CLuaMain* pLuaMain) // Use a separate queue to avoid trouble // What kind of problems are we trying to avoid? Doing a copy each frame isn't quite efficient for (CFastList::const_iterator iter = m_TimerList.begin(); iter != m_TimerList.end(); ++iter) - m_ProcessQueue.push_back(*iter); + { + if (!(*iter)->IsPaused()) + m_ProcessQueue.push_back(*iter); + } while (!m_ProcessQueue.empty()) { @@ -113,6 +116,15 @@ void CLuaTimerManager::RemoveAllTimers() m_pProcessingTimer = NULL; } +void CLuaTimerManager::SetTimerPaused(CLuaTimer* timer, bool paused) +{ + assert(timer); + + timer->SetPaused(paused); + if (paused) + ListRemove(m_ProcessQueue, timer); +} + void CLuaTimerManager::ResetTimer(CLuaTimer* pLuaTimer) { assert(pLuaTimer); diff --git a/Server/mods/deathmatch/logic/lua/CLuaTimerManager.h b/Server/mods/deathmatch/logic/lua/CLuaTimerManager.h index d9d2fc41f2..d63e659147 100644 --- a/Server/mods/deathmatch/logic/lua/CLuaTimerManager.h +++ b/Server/mods/deathmatch/logic/lua/CLuaTimerManager.h @@ -36,6 +36,7 @@ class CLuaTimerManager void RemoveAllTimers(); unsigned long GetTimerCount() const { return m_TimerList.size(); } + void SetTimerPaused(CLuaTimer* timer, bool paused); void ResetTimer(CLuaTimer* pLuaTimer); CFastList::const_iterator IterBegin() { return m_TimerList.begin(); } diff --git a/Server/mods/deathmatch/logic/luadefs/CLuaAccountDefs.cpp b/Server/mods/deathmatch/logic/luadefs/CLuaAccountDefs.cpp index 22e24c73e8..7af41f0e99 100644 --- a/Server/mods/deathmatch/logic/luadefs/CLuaAccountDefs.cpp +++ b/Server/mods/deathmatch/logic/luadefs/CLuaAccountDefs.cpp @@ -23,6 +23,7 @@ void CLuaAccountDefs::LoadFunctions() // Account get functions {"getAccountName", GetAccountName}, + {"getAccountType", ArgumentParser}, {"getAccountPlayer", GetAccountPlayer}, {"isGuestAccount", IsGuestAccount}, {"getAccountData", GetAccountData}, @@ -77,6 +78,7 @@ void CLuaAccountDefs::AddClass(lua_State* luaVM) lua_classfunction(luaVM, "getData", "getAccountData"); lua_classfunction(luaVM, "getAllData", "getAllAccountData"); lua_classfunction(luaVM, "getName", "getAccountName"); + lua_classfunction(luaVM, "getType", "getAccountType"); lua_classfunction(luaVM, "getPlayer", "getAccountPlayer"); lua_classfunction(luaVM, "isGuest", "isGuestAccount"); @@ -116,6 +118,21 @@ int CLuaAccountDefs::GetAccountName(lua_State* luaVM) return 1; } +std::string CLuaAccountDefs::GetAccountType(CAccount* pAccount) +{ + switch (pAccount->GetType()) + { + case EAccountType::Guest: + return "guest"; + case EAccountType::Console: + return "console"; + case EAccountType::Player: + return "player"; + default: + return "unknown"; + } +} + int CLuaAccountDefs::GetAccountPlayer(lua_State* luaVM) { // player getAccountPlayer ( account theAccount ) diff --git a/Server/mods/deathmatch/logic/luadefs/CLuaAccountDefs.h b/Server/mods/deathmatch/logic/luadefs/CLuaAccountDefs.h index dead6074fa..1a9fdc45cf 100644 --- a/Server/mods/deathmatch/logic/luadefs/CLuaAccountDefs.h +++ b/Server/mods/deathmatch/logic/luadefs/CLuaAccountDefs.h @@ -26,6 +26,9 @@ class CLuaAccountDefs : public CLuaDefs LUA_DECLARE(GetAccount); LUA_DECLARE(GetAccounts); LUA_DECLARE(GetAccountName); + + static std::string GetAccountType(CAccount* pAccount); + LUA_DECLARE(GetAccountPlayer); LUA_DECLARE(IsGuestAccount); LUA_DECLARE(GetAccountData); diff --git a/Server/mods/deathmatch/logic/luadefs/CLuaCompatibilityDefs.cpp b/Server/mods/deathmatch/logic/luadefs/CLuaCompatibilityDefs.cpp index 368feac3c1..0336b375b0 100644 --- a/Server/mods/deathmatch/logic/luadefs/CLuaCompatibilityDefs.cpp +++ b/Server/mods/deathmatch/logic/luadefs/CLuaCompatibilityDefs.cpp @@ -13,6 +13,7 @@ #include "CLuaVehicleDefs.h" #include "CLuaPedDefs.h" #include "CLuaPlayerDefs.h" +#include "luadefs/CLuaCryptDefs.h" #include "luadefs/CLuaXMLDefs.h" #include diff --git a/Server/mods/deathmatch/logic/luadefs/CLuaFunctionDefs.Server.cpp b/Server/mods/deathmatch/logic/luadefs/CLuaFunctionDefs.Server.cpp index e089becbfb..554bf2efc9 100644 --- a/Server/mods/deathmatch/logic/luadefs/CLuaFunctionDefs.Server.cpp +++ b/Server/mods/deathmatch/logic/luadefs/CLuaFunctionDefs.Server.cpp @@ -267,7 +267,7 @@ int CLuaFunctionDefs::Get(lua_State* luaVM) } Args.PushArguments(luaVM); - uiArgCount = Args.Count(); + uiArgCount = static_cast(Args.Count()); /* Don't output a table because although it is more consistent with the multiple values output below, ** due to lua's implementation of associative arrays (assuming we use the "setting-name", "value" key-value pairs) diff --git a/Server/mods/deathmatch/logic/luadefs/CLuaHandlingDefs.cpp b/Server/mods/deathmatch/logic/luadefs/CLuaHandlingDefs.cpp index 9152e4dabe..4a80b4acfd 100644 --- a/Server/mods/deathmatch/logic/luadefs/CLuaHandlingDefs.cpp +++ b/Server/mods/deathmatch/logic/luadefs/CLuaHandlingDefs.cpp @@ -390,7 +390,7 @@ int CLuaHandlingDefs::SetModelHandling(lua_State* luaVM) int CLuaHandlingDefs::GetVehicleHandling(lua_State* luaVM) { - // table getVehicleHandling ( element theVehicle ) + // table getVehicleHandling ( element theVehicle, [ string property ] ) CVehicle* pVehicle; CScriptArgReader argStream(luaVM); @@ -398,6 +398,62 @@ int CLuaHandlingDefs::GetVehicleHandling(lua_State* luaVM) if (!argStream.HasErrors()) { + if (argStream.NextIsString()) + { + SString strProperty; + argStream.ReadString(strProperty); + + eHandlingProperty eProperty = m_pHandlingManager->GetPropertyEnumFromName(strProperty); + if (eProperty == HANDLING_MAX) + { + argStream.SetCustomError("Invalid property"); + m_pScriptDebugging->LogCustom(luaVM, argStream.GetFullErrorMessage()); + lua_pushboolean(luaVM, false); + return 1; + } + + float fValue = 0.0f; + CVector vecValue = CVector(0.0f, 0.0f, 0.0f); + SString strValue = ""; + unsigned int uiValue = 0; + unsigned char ucValue = 0; + if (CStaticFunctionDefinitions::GetVehicleHandling(pVehicle, eProperty, fValue)) + { + lua_pushnumber(luaVM, fValue); + } + else if (CStaticFunctionDefinitions::GetVehicleHandling(pVehicle, eProperty, uiValue)) + { + lua_pushnumber(luaVM, uiValue); + } + else if (CStaticFunctionDefinitions::GetVehicleHandling(pVehicle, eProperty, ucValue)) + { + lua_pushnumber(luaVM, ucValue); + } + else if (CStaticFunctionDefinitions::GetVehicleHandling(pVehicle, eProperty, strValue)) + { + lua_pushstring(luaVM, strValue); + } + else if (CStaticFunctionDefinitions::GetVehicleHandling(pVehicle, eProperty, vecValue)) + { + lua_createtable(luaVM, 3, 0); + lua_pushnumber(luaVM, 1); + lua_pushnumber(luaVM, vecValue.fX); + lua_settable(luaVM, -3); + lua_pushnumber(luaVM, 2); + lua_pushnumber(luaVM, vecValue.fY); + lua_settable(luaVM, -3); + lua_pushnumber(luaVM, 3); + lua_pushnumber(luaVM, vecValue.fZ); + lua_settable(luaVM, -3); + } + else + { + argStream.SetCustomError("Invalid property"); + m_pScriptDebugging->LogCustom(luaVM, argStream.GetFullErrorMessage()); + lua_pushboolean(luaVM, false); + } + return 1; + } CHandlingEntry* pEntry = pVehicle->GetHandlingData(); lua_newtable(luaVM); diff --git a/Server/mods/deathmatch/logic/luadefs/CLuaMarkerDefs.cpp b/Server/mods/deathmatch/logic/luadefs/CLuaMarkerDefs.cpp index 001bc40b66..b181bc2033 100644 --- a/Server/mods/deathmatch/logic/luadefs/CLuaMarkerDefs.cpp +++ b/Server/mods/deathmatch/logic/luadefs/CLuaMarkerDefs.cpp @@ -12,6 +12,7 @@ #include "CLuaMarkerDefs.h" #include "CStaticFunctionDefinitions.h" #include "CScriptArgReader.h" +#include "lua/CLuaFunctionParser.h" void CLuaMarkerDefs::LoadFunctions() { @@ -26,6 +27,7 @@ void CLuaMarkerDefs::LoadFunctions() {"getMarkerColor", GetMarkerColor}, {"getMarkerTarget", GetMarkerTarget}, {"getMarkerIcon", GetMarkerIcon}, + {"getMarkerTargetArrowProperties", ArgumentParser}, // Marker set functions {"setMarkerType", SetMarkerType}, @@ -33,6 +35,7 @@ void CLuaMarkerDefs::LoadFunctions() {"setMarkerColor", SetMarkerColor}, {"setMarkerTarget", SetMarkerTarget}, {"setMarkerIcon", SetMarkerIcon}, + {"setMarkerTargetArrowProperties", ArgumentParser}, }; // Add functions @@ -76,6 +79,7 @@ int CLuaMarkerDefs::CreateMarker(lua_State* luaVM) SColorRGBA color(0, 0, 255, 255); SString strType; CElement* pVisibleTo; + bool ignoreAlphaLimits; CScriptArgReader argStream(luaVM); argStream.ReadVector3D(vecPosition); @@ -89,10 +93,13 @@ int CLuaMarkerDefs::CreateMarker(lua_State* luaVM) if (argStream.NextIsBool() || argStream.NextIsNil()) { pVisibleTo = NULL; + argStream.m_iIndex++; } else argStream.ReadUserData(pVisibleTo, m_pRootElement); + argStream.ReadBool(ignoreAlphaLimits, false); + if (!argStream.HasErrors()) { CLuaMain* pLuaMain = g_pGame->GetLuaManager()->GetVirtualMachine(luaVM); @@ -102,7 +109,7 @@ int CLuaMarkerDefs::CreateMarker(lua_State* luaVM) if (pResource) { // Create it - CMarker* pMarker = CStaticFunctionDefinitions::CreateMarker(pResource, vecPosition, strType, fSize, color, pVisibleTo); + CMarker* pMarker = CStaticFunctionDefinitions::CreateMarker(pResource, vecPosition, strType, fSize, color, pVisibleTo, ignoreAlphaLimits); if (pMarker) { CElementGroup* pGroup = pResource->GetElementGroup(); @@ -197,7 +204,12 @@ int CLuaMarkerDefs::GetMarkerColor(lua_State* luaVM) lua_pushnumber(luaVM, static_cast(color.R)); lua_pushnumber(luaVM, static_cast(color.G)); lua_pushnumber(luaVM, static_cast(color.B)); - lua_pushnumber(luaVM, static_cast(color.A)); + + if (!pMarker->AreAlphaLimitsIgnored() && (pMarker->GetMarkerType() == CMarker::TYPE_CHECKPOINT || pMarker->GetMarkerType() == CMarker::TYPE_ARROW)) + lua_pushnumber(luaVM, 255); // fake alpha + else + lua_pushnumber(luaVM, static_cast(color.A)); + return 4; } } @@ -410,3 +422,23 @@ int CLuaMarkerDefs::SetMarkerIcon(lua_State* luaVM) lua_pushboolean(luaVM, false); return 1; } + +bool CLuaMarkerDefs::SetMarkerTargetArrowProperties(CMarker* marker, std::optional r, std::optional g, std::optional b, std::optional a, std::optional size) +{ + SColor color; + color.R = r.value_or(255); + color.G = g.value_or(64); + color.B = b.value_or(64); + color.A = a.value_or(255); + + return CStaticFunctionDefinitions::SetMarkerTargetArrowProperties(marker, color, size.value_or(marker->GetSize() * 0.625f)); +} + +std::variant, bool> CLuaMarkerDefs::GetMarkerTargetArrowProperties(CMarker* marker) noexcept +{ + if (!marker->HasTarget() || marker->GetMarkerType() != CMarker::TYPE_CHECKPOINT) + return false; + + SColor color = marker->GetTargetArrowColor(); + return CLuaMultiReturn(color.R, color.G, color.B, color.A, marker->GetTargetArrowSize()); +} diff --git a/Server/mods/deathmatch/logic/luadefs/CLuaMarkerDefs.h b/Server/mods/deathmatch/logic/luadefs/CLuaMarkerDefs.h index 28e84e5ff5..b73d720184 100644 --- a/Server/mods/deathmatch/logic/luadefs/CLuaMarkerDefs.h +++ b/Server/mods/deathmatch/logic/luadefs/CLuaMarkerDefs.h @@ -11,6 +11,7 @@ #pragma once #include "CLuaDefs.h" +#include "lua/CLuaMultiReturn.h" class CLuaMarkerDefs : public CLuaDefs { @@ -35,4 +36,6 @@ class CLuaMarkerDefs : public CLuaDefs LUA_DECLARE(SetMarkerColor); LUA_DECLARE(SetMarkerTarget); LUA_DECLARE(SetMarkerIcon); + static bool SetMarkerTargetArrowProperties(CMarker* marker, std::optional r, std::optional g, std::optional b, std::optional a, std::optional size); + static std::variant, bool> GetMarkerTargetArrowProperties(CMarker* marker) noexcept; }; diff --git a/Server/mods/deathmatch/logic/luadefs/CLuaObjectDefs.cpp b/Server/mods/deathmatch/logic/luadefs/CLuaObjectDefs.cpp index 948ed90a0d..898825673c 100644 --- a/Server/mods/deathmatch/logic/luadefs/CLuaObjectDefs.cpp +++ b/Server/mods/deathmatch/logic/luadefs/CLuaObjectDefs.cpp @@ -19,11 +19,14 @@ void CLuaObjectDefs::LoadFunctions() constexpr static const std::pair functions[]{ // Object create/destroy funcs {"createObject", CreateObject}, + {"respawnObject", ArgumentParser}, // Object get funcs {"getObjectRotation", GetObjectRotation}, {"getObjectScale", GetObjectScale}, {"isObjectBreakable", ArgumentParser}, + {"isObjectMoving", ArgumentParser}, + {"isObjectRespawnable", ArgumentParser}, // Object set funcs {"setObjectRotation", SetObjectRotation}, @@ -31,6 +34,8 @@ void CLuaObjectDefs::LoadFunctions() {"setObjectBreakable", ArgumentParser}, {"moveObject", MoveObject}, {"stopObject", StopObject}, + {"breakObject", ArgumentParser}, + {"toggleObjectRespawn", ArgumentParser}, }; // Add functions @@ -45,14 +50,20 @@ void CLuaObjectDefs::AddClass(lua_State* luaVM) lua_classfunction(luaVM, "create", "createObject"); lua_classfunction(luaVM, "move", "moveObject"); lua_classfunction(luaVM, "stop", "stopObject"); + lua_classfunction(luaVM, "break", "breakObject"); + lua_classfunction(luaVM, "respawn", "respawnObject"); lua_classfunction(luaVM, "getScale", "getObjectScale"); lua_classfunction(luaVM, "setScale", "setObjectScale"); lua_classfunction(luaVM, "isBreakable", "isObjectBreakable"); lua_classfunction(luaVM, "setBreakable", "setObjectBreakable"); + lua_classfunction(luaVM, "isMoving", "isObjectMoving"); + lua_classfunction(luaVM, "toggleRespawn", "toggleObjectRespawn"); lua_classvariable(luaVM, "scale", "setObjectScale", "getObjectScale"); lua_classvariable(luaVM, "breakable", "setObjectBreakable", "isObjectBreakable"); + lua_classvariable(luaVM, "moving", nullptr, "isObjectMoving"); + lua_classvariable(luaVM, "isRespawnable", nullptr, "isObjectRespawnable"); lua_registerclass(luaVM, "Object", "Element"); } @@ -222,6 +233,11 @@ int CLuaObjectDefs::SetObjectScale(lua_State* luaVM) return 1; } +bool CLuaObjectDefs::IsObjectMoving(CObject* const pObject) +{ + return pObject->IsMoving(); +} + int CLuaObjectDefs::MoveObject(lua_State* luaVM) { // bool moveObject ( object theObject, int time, @@ -297,3 +313,23 @@ bool CLuaObjectDefs::SetObjectBreakable(CObject* const pObject, const bool bBrea { return CStaticFunctionDefinitions::SetObjectBreakable(pObject, bBreakable); } + +bool CLuaObjectDefs::BreakObject(CObject* const pObject) +{ + return CStaticFunctionDefinitions::BreakObject(pObject); +} + +bool CLuaObjectDefs::RespawnObject(CObject* const pObject) noexcept +{ + return CStaticFunctionDefinitions::RespawnObject(pObject); +} + +bool CLuaObjectDefs::ToggleObjectRespawn(CObject* const pObject, const bool bRespawn) noexcept +{ + return CStaticFunctionDefinitions::ToggleObjectRespawn(pObject, bRespawn); +} + +bool CLuaObjectDefs::IsObjectRespawnable(CObject* const pObject) noexcept +{ + return pObject->IsRespawnEnabled(); +} diff --git a/Server/mods/deathmatch/logic/luadefs/CLuaObjectDefs.h b/Server/mods/deathmatch/logic/luadefs/CLuaObjectDefs.h index ac4be795d0..76a96a982b 100644 --- a/Server/mods/deathmatch/logic/luadefs/CLuaObjectDefs.h +++ b/Server/mods/deathmatch/logic/luadefs/CLuaObjectDefs.h @@ -20,12 +20,15 @@ class CLuaObjectDefs : public CLuaDefs // Object create/destroy functions LUA_DECLARE(CreateObject); + static bool RespawnObject(CObject* const pObject) noexcept; // Object get functions LUA_DECLARE(GetObjectName); LUA_DECLARE(GetObjectRotation); LUA_DECLARE(GetObjectScale); static bool IsObjectBreakable(CObject* const pObject); + static bool IsObjectMoving(CObject* const pObject); + static bool IsObjectRespawnable(CObject* const pObject) noexcept; // Object set functions LUA_DECLARE(SetObjectName); @@ -34,4 +37,6 @@ class CLuaObjectDefs : public CLuaDefs static bool SetObjectBreakable(CObject* const pObject, const bool bBreakable); LUA_DECLARE(MoveObject); LUA_DECLARE(StopObject); + static bool BreakObject(CObject* const pObject); + static bool ToggleObjectRespawn(CObject* const pObject, const bool bRespawn) noexcept; }; diff --git a/Server/mods/deathmatch/logic/luadefs/CLuaPedDefs.cpp b/Server/mods/deathmatch/logic/luadefs/CLuaPedDefs.cpp index 281f81f307..8a5a3c8591 100644 --- a/Server/mods/deathmatch/logic/luadefs/CLuaPedDefs.cpp +++ b/Server/mods/deathmatch/logic/luadefs/CLuaPedDefs.cpp @@ -13,6 +13,7 @@ #include "CLuaPedDefs.h" #include "CStaticFunctionDefinitions.h" #include "CScriptArgReader.h" +#include "lua/CLuaFunctionParser.h" void CLuaPedDefs::LoadFunctions() { @@ -64,7 +65,7 @@ void CLuaPedDefs::LoadFunctions() {"warpPedIntoVehicle", WarpPedIntoVehicle}, {"removePedFromVehicle", RemovePedFromVehicle}, {"setPedDoingGangDriveby", SetPedDoingGangDriveby}, - {"setPedAnimation", SetPedAnimation}, + {"setPedAnimation", ArgumentParserWarn}, {"setPedAnimationProgress", SetPedAnimationProgress}, {"setPedAnimationSpeed", SetPedAnimationSpeed}, {"setPedOnFire", SetPedOnFire}, @@ -404,56 +405,33 @@ int CLuaPedDefs::IsPedFrozen(lua_State* luaVM) return 1; } -int CLuaPedDefs::SetPedAnimation(lua_State* luaVM) +bool CLuaPedDefs::SetPedAnimation(CElement* pPed, std::optional> blockName, + std::optional> animName, std::optional time, std::optional loop, + std::optional updatePosition, std::optional interruptable, std::optional freezeLastFrame, + std::optional blendTime, std::optional restoreTask) { - // bool setPedAnimation ( ped thePed [, string block=nil, string anim=nil, int time=-1, int blend=250, bool loop=true, bool updatePosition=true, bool - // interruptable=true, bool freezeLastFrame = true] ) - CElement* pPed; - SString strBlockName, strAnimName; - int iTime; - int iBlend = 250; - bool bLoop, bUpdatePosition, bInterruptable, bFreezeLastFrame; - bool bDummy; - bool bTaskToBeRestoredOnAnimEnd; - - CScriptArgReader argStream(luaVM); - argStream.ReadUserData(pPed); - if (argStream.NextIsBool()) - argStream.ReadBool(bDummy); // Wiki used setPedAnimation(source,false) as an example - else if (argStream.NextIsNil()) - argStream.m_iIndex++; // Wiki docs said blockName could be nil - else - argStream.ReadString(strBlockName, ""); - argStream.ReadString(strAnimName, ""); - if (argStream.NextCouldBeNumber()) // Freeroam skips the time arg sometimes - argStream.ReadNumber(iTime, -1); - else - iTime = -1; - argStream.ReadBool(bLoop, true); - argStream.ReadBool(bUpdatePosition, true); - argStream.ReadBool(bInterruptable, true); - argStream.ReadBool(bFreezeLastFrame, true); - argStream.ReadNumber(iBlend, 250); - argStream.ReadBool(bTaskToBeRestoredOnAnimEnd, false); + std::string animBlockName; + std::string animationName; - if (!argStream.HasErrors()) + if (blockName.has_value()) { - const char *szBlock, *szAnim; - szBlock = strBlockName.empty() ? NULL : strBlockName.c_str(); - szAnim = strAnimName.empty() ? NULL : strAnimName.c_str(); + if (std::holds_alternative(blockName.value())) + animBlockName = std::get(blockName.value()); + else if (std::holds_alternative(blockName.value())) + if (std::get(blockName.value())) + throw LuaFunctionError("Anim block name cannot be true. Possible values: nil, false, string."); + } - if (CStaticFunctionDefinitions::SetPedAnimation(pPed, szBlock, szAnim, iTime, iBlend, bLoop, bUpdatePosition, bInterruptable, bFreezeLastFrame, - bTaskToBeRestoredOnAnimEnd)) - { - lua_pushboolean(luaVM, true); - return 1; - } + if (animName.has_value()) + { + if (std::holds_alternative(animName.value())) + animationName = std::get(animName.value()); + else if (std::holds_alternative(animName.value())) + if (std::get(animName.value())) + throw LuaFunctionError("Animation name cannot be true. Possible values: nil, false, string."); } - else - m_pScriptDebugging->LogCustom(luaVM, argStream.GetFullErrorMessage()); - lua_pushboolean(luaVM, false); - return 1; + return CStaticFunctionDefinitions::SetPedAnimation(pPed, animBlockName, animationName, time.value_or(-1), blendTime.value_or(250), loop.value_or(true), updatePosition.value_or(true), interruptable.value_or(true), freezeLastFrame.value_or(true), restoreTask.value_or(false)); } int CLuaPedDefs::SetPedAnimationProgress(lua_State* luaVM) diff --git a/Server/mods/deathmatch/logic/luadefs/CLuaPedDefs.h b/Server/mods/deathmatch/logic/luadefs/CLuaPedDefs.h index d458b7a344..0348b5db61 100644 --- a/Server/mods/deathmatch/logic/luadefs/CLuaPedDefs.h +++ b/Server/mods/deathmatch/logic/luadefs/CLuaPedDefs.h @@ -71,7 +71,7 @@ class CLuaPedDefs : public CLuaDefs LUA_DECLARE_OOP(WarpPedIntoVehicle); LUA_DECLARE(RemovePedFromVehicle); LUA_DECLARE(SetPedDoingGangDriveby); - LUA_DECLARE(SetPedAnimation); + static bool SetPedAnimation(CElement* pPed, std::optional> blockName, std::optional> animName, std::optional time, std::optional loop, std::optional updatePosition, std::optional interruptable, std::optional freezeLastFrame, std::optional blendTime, std::optional restoreTask); LUA_DECLARE(SetPedAnimationProgress); LUA_DECLARE(SetPedAnimationSpeed); LUA_DECLARE(SetPedWeaponSlot); diff --git a/Server/mods/deathmatch/logic/luadefs/CLuaResourceDefs.cpp b/Server/mods/deathmatch/logic/luadefs/CLuaResourceDefs.cpp index 57ef2f01e7..81d66a3280 100644 --- a/Server/mods/deathmatch/logic/luadefs/CLuaResourceDefs.cpp +++ b/Server/mods/deathmatch/logic/luadefs/CLuaResourceDefs.cpp @@ -54,7 +54,7 @@ void CLuaResourceDefs::LoadFunctions() {"getResourceLoadFailureReason", getResourceLoadFailureReason}, {"getResourceLastStartTime", getResourceLastStartTime}, {"getResourceLoadTime", getResourceLoadTime}, - {"getResourceName", getResourceName}, + {"getResourceName", ArgumentParserWarn}, {"getResourceRootElement", getResourceRootElement}, {"getResourceDynamicElementRoot", getResourceDynamicElementRoot}, {"getResourceMapRootElement", getResourceMapRootElement}, @@ -898,23 +898,17 @@ int CLuaResourceDefs::getResourceLoadTime(lua_State* luaVM) return 1; } -int CLuaResourceDefs::getResourceName(lua_State* luaVM) +std::string CLuaResourceDefs::GetResourceName(lua_State* luaVM, std::optional resourceElement) { - CResource* pResource; + if (resourceElement.has_value()) + return (*resourceElement)->GetName(); - CScriptArgReader argStream(luaVM); - argStream.ReadUserData(pResource); + CResource* localResource = &lua_getownerresource(luaVM); - if (!argStream.HasErrors()) - { - lua_pushstring(luaVM, pResource->GetName().c_str()); - return 1; - } - else - m_pScriptDebugging->LogCustom(luaVM, argStream.GetFullErrorMessage()); + if (!localResource) + throw std::invalid_argument("Couldn't find the resource"); - lua_pushboolean(luaVM, false); - return 1; + return localResource->GetName(); } int CLuaResourceDefs::getResourceRootElement(lua_State* luaVM) @@ -1178,7 +1172,7 @@ int CLuaResourceDefs::call(lua_State* luaVM) OldResourceRoot.Push(targetLuaVM); lua_setglobal(targetLuaVM, "sourceResourceRoot"); - return returns.Count(); + return static_cast(returns.Count()); } else { @@ -1391,9 +1385,9 @@ int CLuaResourceDefs::Load(lua_State* luaVM) { CLuaArguments returnValues; callbackArguments.Call(pLuaMain, iLuaFunction, &returnValues); - if (returnValues.Count()) + if (returnValues.IsNotEmpty()) { - CLuaArgument* returnedValue = *returnValues.IterBegin(); + CLuaArgument* returnedValue = *returnValues.begin(); int iType = returnedValue->GetType(); if (iType == LUA_TNIL) break; diff --git a/Server/mods/deathmatch/logic/luadefs/CLuaResourceDefs.h b/Server/mods/deathmatch/logic/luadefs/CLuaResourceDefs.h index 471b7aaef9..29304f402a 100644 --- a/Server/mods/deathmatch/logic/luadefs/CLuaResourceDefs.h +++ b/Server/mods/deathmatch/logic/luadefs/CLuaResourceDefs.h @@ -47,13 +47,14 @@ class CLuaResourceDefs : public CLuaDefs LUA_DECLARE(getResourceLoadFailureReason); LUA_DECLARE(getResourceLastStartTime); LUA_DECLARE(getResourceLoadTime); - LUA_DECLARE(getResourceName); LUA_DECLARE(getResourceRootElement); LUA_DECLARE(getResourceDynamicElementRoot); LUA_DECLARE(getResourceMapRootElement); LUA_DECLARE(getResourceExportedFunctions); LUA_DECLARE(getResourceOrganizationalPath); LUA_DECLARE(isResourceArchived); + + static std::string GetResourceName(lua_State* luaVM, std::optional resourceElement); static bool isResourceProtected(CResource* const resource); // Set stuff diff --git a/Server/mods/deathmatch/logic/luadefs/CLuaTimerDefs.cpp b/Server/mods/deathmatch/logic/luadefs/CLuaTimerDefs.cpp index 49c83bd576..c3e0478c8b 100644 --- a/Server/mods/deathmatch/logic/luadefs/CLuaTimerDefs.cpp +++ b/Server/mods/deathmatch/logic/luadefs/CLuaTimerDefs.cpp @@ -16,8 +16,9 @@ void CLuaTimerDefs::LoadFunctions() { constexpr static const std::pair functions[]{ - {"setTimer", SetTimer}, {"killTimer", KillTimer}, {"resetTimer", ResetTimer}, - {"getTimers", GetTimers}, {"isTimer", IsTimer}, {"getTimerDetails", GetTimerDetails}, + {"setTimer", SetTimer}, {"killTimer", KillTimer}, {"resetTimer", ResetTimer}, + {"setTimerPaused", ArgumentParser},{"isTimerPaused", ArgumentParser}, + {"getTimers", GetTimers}, {"isTimer", IsTimer},{"getTimerDetails", GetTimerDetails}, }; // Add functions @@ -33,10 +34,10 @@ void CLuaTimerDefs::AddClass(lua_State* luaVM) lua_classfunction(luaVM, "destroy", "killTimer"); lua_classfunction(luaVM, "reset", "resetTimer"); lua_classfunction(luaVM, "isValid", "isTimer"); - lua_classfunction(luaVM, "getDetails", "getTimerDetails"); lua_classvariable(luaVM, "valid", NULL, "isTimer"); + lua_classvariable(luaVM, "paused", "setTimerPaused", "isTimerPaused"); lua_registerclass(luaVM, "Timer"); } @@ -114,6 +115,22 @@ int CLuaTimerDefs::KillTimer(lua_State* luaVM) return 1; } +bool CLuaTimerDefs::IsTimerPaused(CLuaTimer* timer) noexcept +{ + return timer->IsPaused(); +} + +bool CLuaTimerDefs::SetTimerPaused(lua_State* luaVM, CLuaTimer* timer, bool paused) +{ + // bool setTimerPaused ( timer theTimer, bool paused ) + CLuaMain* luaMain = m_pLuaManager->GetVirtualMachine(luaVM); + if (!luaMain) + return false; + + luaMain->GetTimerManager()->SetTimerPaused(timer, paused); + return true; +} + int CLuaTimerDefs::ResetTimer(lua_State* luaVM) { // bool resetTimer ( timer theTimer ) diff --git a/Server/mods/deathmatch/logic/luadefs/CLuaTimerDefs.h b/Server/mods/deathmatch/logic/luadefs/CLuaTimerDefs.h index fd37e2aaa4..abf1b725d6 100644 --- a/Server/mods/deathmatch/logic/luadefs/CLuaTimerDefs.h +++ b/Server/mods/deathmatch/logic/luadefs/CLuaTimerDefs.h @@ -24,4 +24,6 @@ class CLuaTimerDefs : public CLuaDefs LUA_DECLARE(GetTimers); LUA_DECLARE(IsTimer); LUA_DECLARE(GetTimerDetails); -}; \ No newline at end of file + static bool IsTimerPaused(CLuaTimer* timer) noexcept; + static bool SetTimerPaused(lua_State* luaVM, CLuaTimer* timer, bool paused); +}; diff --git a/Server/mods/deathmatch/logic/luadefs/CLuaVehicleDefs.cpp b/Server/mods/deathmatch/logic/luadefs/CLuaVehicleDefs.cpp index 0a35ebfa20..294ea7310c 100644 --- a/Server/mods/deathmatch/logic/luadefs/CLuaVehicleDefs.cpp +++ b/Server/mods/deathmatch/logic/luadefs/CLuaVehicleDefs.cpp @@ -94,6 +94,9 @@ void CLuaVehicleDefs::LoadFunctions() {"setVehicleRespawnRotation", SetVehicleRespawnRotation}, {"getVehicleRespawnPosition", GetVehicleRespawnPosition}, {"getVehicleRespawnRotation", GetVehicleRespawnRotation}, + {"isVehicleRespawnable", ArgumentParser}, + {"getVehicleRespawnDelay", ArgumentParser}, + {"getVehicleIdleRespawnDelay", ArgumentParser}, {"respawnVehicle", RespawnVehicle}, {"resetVehicleExplosionTime", ResetVehicleExplosionTime}, {"resetVehicleIdleTime", ResetVehicleIdleTime}, @@ -201,6 +204,9 @@ void CLuaVehicleDefs::AddClass(lua_State* luaVM) lua_classfunction(luaVM, "getHandling", "getVehicleHandling"); lua_classfunction(luaVM, "getRespawnPosition", "getVehicleRespawnPosition"); lua_classfunction(luaVM, "getRespawnRotation", "getVehicleRespawnRotation"); + lua_classfunction(luaVM, "isRespawnable", "isVehicleRespawnable"); + lua_classfunction(luaVM, "getRespawnDelay", "getVehicleRespawnDelay"); + lua_classfunction(luaVM, "getIdleRespawnDelay", "getVehicleIdleRespawnDelay"); lua_classfunction(luaVM, "setColor", "setVehicleColor"); lua_classfunction(luaVM, "setDamageProof", "setVehicleDamageProof"); @@ -264,8 +270,9 @@ void CLuaVehicleDefs::AddClass(lua_State* luaVM) lua_classvariable(luaVM, "turretPosition", "setVehicleTurretPosition", "getVehicleTurretPosition"); lua_classvariable(luaVM, "turnVelocity", "setVehicleTurnVelocity", "getVehicleTurnVelocity", SetVehicleTurnVelocity, OOP_GetVehicleTurnVelocity); lua_classvariable(luaVM, "overrideLights", "setVehicleOverrideLights", "getVehicleOverrideLights"); - lua_classvariable(luaVM, "idleRespawnDelay", "setVehicleIdleRespawnDelay", NULL); - lua_classvariable(luaVM, "respawnDelay", "setVehicleRespawnDelay", NULL); + lua_classvariable(luaVM, "idleRespawnDelay", "setVehicleIdleRespawnDelay", "getVehicleIdleRespawnDelay"); + lua_classvariable(luaVM, "respawnable", "toggleVehicleRespawn", "isVehicleRespawnable"); + lua_classvariable(luaVM, "respawnDelay", "setVehicleRespawnDelay", "getVehicleRespawnDelay"); lua_classvariable(luaVM, "respawnPosition", "setVehicleRespawnPosition", "getVehicleRespawnPosition", SetVehicleRespawnPosition, OOP_GetVehicleRespawnPosition); lua_classvariable(luaVM, "respawnRotation", "setVehicleRespawnRotation", "getVehicleRespawnRotation", SetVehicleRespawnRotation, @@ -290,6 +297,7 @@ int CLuaVehicleDefs::CreateVehicle(lua_State* luaVM) SString strNumberPlate; uchar ucVariant; uchar ucVariant2; + bool bSynced; CScriptArgReader argStream(luaVM); argStream.ReadNumber(usModel); @@ -303,6 +311,7 @@ int CLuaVehicleDefs::CreateVehicle(lua_State* luaVM) } argStream.ReadNumber(ucVariant, 254); argStream.ReadNumber(ucVariant2, 254); + argStream.ReadBool(bSynced, true); if (!argStream.HasErrors()) { @@ -316,7 +325,7 @@ int CLuaVehicleDefs::CreateVehicle(lua_State* luaVM) { // Create the vehicle and return its handle CVehicle* pVehicle = - CStaticFunctionDefinitions::CreateVehicle(pResource, usModel, vecPosition, vecRotation, strNumberPlate, ucVariant, ucVariant2); + CStaticFunctionDefinitions::CreateVehicle(pResource, usModel, vecPosition, vecRotation, strNumberPlate, ucVariant, ucVariant2, bSynced); if (pVehicle) { CElementGroup* pGroup = pResource->GetElementGroup(); @@ -2349,6 +2358,21 @@ int CLuaVehicleDefs::SetVehicleRespawnRotation(lua_State* luaVM) return 1; } +bool CLuaVehicleDefs::IsVehicleRespawnable(CVehicle* vehicle) noexcept +{ + return vehicle->GetRespawnEnabled(); +} + +uint32_t CLuaVehicleDefs::GetVehicleRespawnDelay(CVehicle* vehicle) noexcept +{ + return vehicle->GetBlowRespawnInterval(); +} + +uint32_t CLuaVehicleDefs::GetVehicleIdleRespawnDelay(CVehicle* vehicle) noexcept +{ + return vehicle->GetIdleRespawnInterval(); +} + int CLuaVehicleDefs::SetVehicleIdleRespawnDelay(lua_State* luaVM) { CElement* pElement; diff --git a/Server/mods/deathmatch/logic/luadefs/CLuaVehicleDefs.h b/Server/mods/deathmatch/logic/luadefs/CLuaVehicleDefs.h index b9edf159c1..3200e2ada3 100644 --- a/Server/mods/deathmatch/logic/luadefs/CLuaVehicleDefs.h +++ b/Server/mods/deathmatch/logic/luadefs/CLuaVehicleDefs.h @@ -92,6 +92,9 @@ class CLuaVehicleDefs : public CLuaDefs LUA_DECLARE(SetVehicleRespawnRotation); LUA_DECLARE_OOP(GetVehicleRespawnPosition); LUA_DECLARE_OOP(GetVehicleRespawnRotation); + static bool IsVehicleRespawnable(CVehicle* vehicle) noexcept; + static uint32_t GetVehicleRespawnDelay(CVehicle* vehicle) noexcept; + static uint32_t GetVehicleIdleRespawnDelay(CVehicle* vehicle) noexcept; LUA_DECLARE(ToggleVehicleRespawn); LUA_DECLARE(ResetVehicleExplosionTime); LUA_DECLARE(ResetVehicleIdleTime); diff --git a/Server/mods/deathmatch/logic/luadefs/CLuaWorldDefs.cpp b/Server/mods/deathmatch/logic/luadefs/CLuaWorldDefs.cpp index 0beb88d8ab..480e9bd5cf 100644 --- a/Server/mods/deathmatch/logic/luadefs/CLuaWorldDefs.cpp +++ b/Server/mods/deathmatch/logic/luadefs/CLuaWorldDefs.cpp @@ -87,6 +87,7 @@ void CLuaWorldDefs::LoadFunctions() {"restoreWorldModel", RestoreWorldModel}, {"restoreAllWorldModels", RestoreAllWorldModels}, {"resetMoonSize", resetMoonSize}, + {"resetWorldProperties", ArgumentParser}, // Check {"isGarageOpen", isGarageOpen}, @@ -1448,3 +1449,8 @@ int CLuaWorldDefs::getOcclusionsEnabled(lua_State* luaVM) lua_pushboolean(luaVM, false); return 1; } + +void CLuaWorldDefs::ResetWorldProperties(std::optional resetSpecialWorldProperties, std::optional resetWorldProperties, std::optional resetWeatherProperties, std::optional resetLODs, std::optional resetSounds, std::optional resetGlitches, std::optional resetJetpackWeapons) noexcept +{ + g_pGame->ResetWorldProperties(ResetWorldPropsInfo{resetSpecialWorldProperties.value_or(true), resetWorldProperties.value_or(true), resetWeatherProperties.value_or(true), resetLODs.value_or(true), resetSounds.value_or(true), resetGlitches.value_or(true), resetJetpackWeapons.value_or(true)}); +} diff --git a/Server/mods/deathmatch/logic/luadefs/CLuaWorldDefs.h b/Server/mods/deathmatch/logic/luadefs/CLuaWorldDefs.h index 6e7e8675e6..7859034e3b 100644 --- a/Server/mods/deathmatch/logic/luadefs/CLuaWorldDefs.h +++ b/Server/mods/deathmatch/logic/luadefs/CLuaWorldDefs.h @@ -94,4 +94,6 @@ class CLuaWorldDefs : public CLuaDefs LUA_DECLARE(RestoreWorldModel); LUA_DECLARE(RestoreAllWorldModels); LUA_DECLARE(resetMoonSize); + + static void ResetWorldProperties(std::optional resetSpecialWorldProperties, std::optional resetWorldProperties, std::optional resetWeatherProperties, std::optional resetLODs, std::optional resetSounds, std::optional resetGlitches, std::optional resetJetpackWeapons) noexcept; }; diff --git a/Server/mods/deathmatch/logic/net/CSimBulletsyncPacket.cpp b/Server/mods/deathmatch/logic/net/CSimBulletsyncPacket.cpp index 86f6b85912..89afb9cebc 100644 --- a/Server/mods/deathmatch/logic/net/CSimBulletsyncPacket.cpp +++ b/Server/mods/deathmatch/logic/net/CSimBulletsyncPacket.cpp @@ -9,6 +9,7 @@ #include "StdInc.h" #include "SimHeaders.h" +#include "CPickupManager.h" CSimBulletsyncPacket::CSimBulletsyncPacket(ElementID PlayerID) : m_PlayerID(PlayerID) { @@ -25,6 +26,8 @@ bool CSimBulletsyncPacket::Read(NetBitStreamInterface& BitStream) { char cWeaponType; BitStream.Read(cWeaponType); + if (!CPickupManager::IsValidWeaponID(cWeaponType)) + return false; m_Cache.weaponType = (eWeaponType)cWeaponType; BitStream.Read((char*)&m_Cache.vecStart, sizeof(CVector)); diff --git a/Server/mods/deathmatch/logic/net/CSimPlayerManager.cpp b/Server/mods/deathmatch/logic/net/CSimPlayerManager.cpp index b926c0ebdf..41324166d3 100644 --- a/Server/mods/deathmatch/logic/net/CSimPlayerManager.cpp +++ b/Server/mods/deathmatch/logic/net/CSimPlayerManager.cpp @@ -358,8 +358,11 @@ bool CSimPlayerManager::HandleBulletSync(const NetServerPlayerID& Socket, NetBit if (pPacket->Read(*BitStream)) { - // Relay it to nearbyers - Broadcast(*pPacket, pSourceSimPlayer->GetPuresyncSendList()); + // Relay it to nearbyers, if the player really has this weapon + if (pSourceSimPlayer->m_pRealPlayer->HasWeaponType(pPacket->m_Cache.weaponType)) + { + Broadcast(*pPacket, pSourceSimPlayer->GetPuresyncSendList()); + } } delete pPacket; diff --git a/Server/mods/deathmatch/logic/packets/CDebugEchoPacket.cpp b/Server/mods/deathmatch/logic/packets/CDebugEchoPacket.cpp index 958740dbe7..8bef3f95e4 100644 --- a/Server/mods/deathmatch/logic/packets/CDebugEchoPacket.cpp +++ b/Server/mods/deathmatch/logic/packets/CDebugEchoPacket.cpp @@ -16,7 +16,7 @@ bool CDebugEchoPacket::Write(NetBitStreamInterface& BitStream) const { // Write the level BitStream.Write(static_cast(m_uiLevel)); - if (m_uiLevel == 0) + if (m_uiLevel == 0 || m_uiLevel == 4) { // Write the color BitStream.Write(m_ucRed); diff --git a/Server/mods/deathmatch/logic/packets/CEntityAddPacket.cpp b/Server/mods/deathmatch/logic/packets/CEntityAddPacket.cpp index 858cf5c56b..a001ba518f 100644 --- a/Server/mods/deathmatch/logic/packets/CEntityAddPacket.cpp +++ b/Server/mods/deathmatch/logic/packets/CEntityAddPacket.cpp @@ -297,6 +297,14 @@ bool CEntityAddPacket::Write(NetBitStreamInterface& BitStream) const health.data.fValue = pObject->GetHealth(); BitStream.Write(&health); + // is object break? + if (BitStream.Can(eBitStreamVersion::BreakObject_Serverside)) + BitStream.WriteBit(pObject->GetHealth() <= 0); + + // Respawnable + if (BitStream.Can(eBitStreamVersion::RespawnObject_Serverside)) + BitStream.WriteBit(pObject->IsRespawnEnabled()); + if (ucEntityTypeID == CElement::WEAPON) { CCustomWeapon* pWeapon = static_cast(pElement); @@ -724,11 +732,26 @@ bool CEntityAddPacket::Write(NetBitStreamInterface& BitStream) const position.data.vecPosition = pMarker->GetTarget(); BitStream.Write(&position); + + if (markerType.data.ucType == CMarker::TYPE_CHECKPOINT && BitStream.Can(eBitStreamVersion::SetMarkerTargetArrowProperties)) + { + SColor color = pMarker->GetTargetArrowColor(); + + BitStream.Write(color.R); + BitStream.Write(color.G); + BitStream.Write(color.B); + BitStream.Write(color.A); + BitStream.Write(pMarker->GetTargetArrowSize()); + } } else BitStream.WriteBit(false); } + // Alpha limit + if (BitStream.Can(eBitStreamVersion::Marker_IgnoreAlphaLimits)) + BitStream.WriteBit(pMarker->AreAlphaLimitsIgnored()); + break; } diff --git a/Server/mods/deathmatch/logic/packets/CMapInfoPacket.cpp b/Server/mods/deathmatch/logic/packets/CMapInfoPacket.cpp index cace38952a..e62547b3fb 100644 --- a/Server/mods/deathmatch/logic/packets/CMapInfoPacket.cpp +++ b/Server/mods/deathmatch/logic/packets/CMapInfoPacket.cpp @@ -189,6 +189,9 @@ bool CMapInfoPacket::Write(NetBitStreamInterface& BitStream) const wsProps.data.watercreatures = g_pGame->IsWorldSpecialPropertyEnabled(WorldSpecialProperty::WATERCREATURES); wsProps.data.burnflippedcars = g_pGame->IsWorldSpecialPropertyEnabled(WorldSpecialProperty::BURNFLIPPEDCARS); wsProps.data2.fireballdestruct = g_pGame->IsWorldSpecialPropertyEnabled(WorldSpecialProperty::FIREBALLDESTRUCT); + wsProps.data3.roadsignstext = g_pGame->IsWorldSpecialPropertyEnabled(WorldSpecialProperty::ROADSIGNSTEXT); + wsProps.data4.extendedwatercannons = g_pGame->IsWorldSpecialPropertyEnabled(WorldSpecialProperty::EXTENDEDWATERCANNONS); + wsProps.data5.tunnelweatherblend = g_pGame->IsWorldSpecialPropertyEnabled(WorldSpecialProperty::TUNNELWEATHERBLEND); BitStream.Write(&wsProps); } diff --git a/Server/mods/deathmatch/logic/packets/CPedSyncPacket.cpp b/Server/mods/deathmatch/logic/packets/CPedSyncPacket.cpp index e71997aaf0..7af83dcb51 100644 --- a/Server/mods/deathmatch/logic/packets/CPedSyncPacket.cpp +++ b/Server/mods/deathmatch/logic/packets/CPedSyncPacket.cpp @@ -40,22 +40,8 @@ bool CPedSyncPacket::Read(NetBitStreamInterface& BitStream) // Did we recieve position? if (ucFlags & 0x01) - { - if (!BitStream.Read(Data.vecPosition.fX) || !BitStream.Read(Data.vecPosition.fY) || !BitStream.Read(Data.vecPosition.fZ)) - return false; - } - - // Rotation - if (ucFlags & 0x02) - { - if (!BitStream.Read(Data.fRotation)) - return false; - } - - // Velocity - if (ucFlags & 0x04) - { - if (!BitStream.Read(Data.vecVelocity.fX) || !BitStream.Read(Data.vecVelocity.fY) || !BitStream.Read(Data.vecVelocity.fZ)) + { + if (!(BitStream.Can(eBitStreamVersion::PedSync_Revision) ? Data.ReadSpatialData(BitStream) : Data.ReadSpatialDataBC(BitStream))) return false; } @@ -108,25 +94,39 @@ bool CPedSyncPacket::Write(NetBitStreamInterface& BitStream) const BitStream.Write(Data.ucFlags); - // Position and rotation - if (Data.ucFlags & 0x01) + if (BitStream.Can(eBitStreamVersion::PedSync_Revision)) { - BitStream.Write(Data.vecPosition.fX); - BitStream.Write(Data.vecPosition.fY); - BitStream.Write(Data.vecPosition.fZ); - } + // Position and rotation + if (Data.ucFlags & 0x01) + BitStream.Write(&Data.position); - if (Data.ucFlags & 0x02) - { - BitStream.Write(Data.fRotation); - } + if (Data.ucFlags & 0x02) + BitStream.Write(&Data.rotation); - // Velocity - if (Data.ucFlags & 0x04) + // Velocity + if (Data.ucFlags & 0x04) + BitStream.Write(&Data.velocity); + } + else { - BitStream.Write(Data.vecVelocity.fX); - BitStream.Write(Data.vecVelocity.fY); - BitStream.Write(Data.vecVelocity.fZ); + // Position and rotation + if (Data.ucFlags & 0x01) + { + BitStream.Write(Data.position.data.vecPosition.fX); + BitStream.Write(Data.position.data.vecPosition.fY); + BitStream.Write(Data.position.data.vecPosition.fZ); + } + + if (Data.ucFlags & 0x02) + BitStream.Write(Data.rotation.data.fRotation); + + // Velocity + if (Data.ucFlags & 0x04) + { + BitStream.Write(Data.velocity.data.vecVelocity.fX); + BitStream.Write(Data.velocity.data.vecVelocity.fY); + BitStream.Write(Data.velocity.data.vecVelocity.fZ); + } } // Health, armour, on fire and is in water @@ -141,3 +141,55 @@ bool CPedSyncPacket::Write(NetBitStreamInterface& BitStream) const return true; } + +bool CPedSyncPacket::SyncData::ReadSpatialData(NetBitStreamInterface& BitStream) +{ + // Did we recieve position? + if (ucFlags & 0x01) + { + if (!BitStream.Read(&position)) + return false; + } + + // Rotation + if (ucFlags & 0x02) + { + if (!BitStream.Read(&rotation)) + return false; + } + + // Velocity + if (ucFlags & 0x04) + { + if (!BitStream.Read(&velocity)) + return false; + } + + return true; +} + +bool CPedSyncPacket::SyncData::ReadSpatialDataBC(NetBitStreamInterface& BitStream) +{ + // Did we recieve position? + if (ucFlags & 0x01) + { + if (!BitStream.Read(position.data.vecPosition.fX) || !BitStream.Read(position.data.vecPosition.fY) || !BitStream.Read(position.data.vecPosition.fZ)) + return false; + } + + // Rotation + if (ucFlags & 0x02) + { + if (!BitStream.Read(rotation.data.fRotation)) + return false; + } + + // Velocity + if (ucFlags & 0x04) + { + if (!BitStream.Read(velocity.data.vecVelocity.fX) || !BitStream.Read(velocity.data.vecVelocity.fY) || !BitStream.Read(velocity.data.vecVelocity.fZ)) + return false; + } + + return true; +} diff --git a/Server/mods/deathmatch/logic/packets/CPedSyncPacket.h b/Server/mods/deathmatch/logic/packets/CPedSyncPacket.h index ccea0de3a3..f200be509b 100644 --- a/Server/mods/deathmatch/logic/packets/CPedSyncPacket.h +++ b/Server/mods/deathmatch/logic/packets/CPedSyncPacket.h @@ -13,6 +13,7 @@ #include #include "CPacket.h" +#include #include class CPedSyncPacket final : public CPacket @@ -20,16 +21,20 @@ class CPedSyncPacket final : public CPacket public: struct SyncData { - ElementID ID; - unsigned char ucFlags; - unsigned char ucSyncTimeContext; - CVector vecPosition; - float fRotation; - CVector vecVelocity; - float fHealth; - float fArmor; - bool bOnFire; - bool bIsInWater; + ElementID ID; + unsigned char ucFlags; + unsigned char ucSyncTimeContext; + SPositionSync position; + SPedRotationSync rotation; + SVelocitySync velocity; + float fHealth; + float fArmor; + bool bOnFire; + bool bIsInWater; + + bool ReadSpatialData(NetBitStreamInterface& BitStream); + // Backward compatibility + bool ReadSpatialDataBC(NetBitStreamInterface& BitStream); }; public: diff --git a/Server/mods/deathmatch/logic/packets/CPlayerPuresyncPacket.cpp b/Server/mods/deathmatch/logic/packets/CPlayerPuresyncPacket.cpp index 3765f22980..399d3c0b35 100644 --- a/Server/mods/deathmatch/logic/packets/CPlayerPuresyncPacket.cpp +++ b/Server/mods/deathmatch/logic/packets/CPlayerPuresyncPacket.cpp @@ -14,6 +14,7 @@ #include "CElementIDs.h" #include "CWeaponNames.h" #include "Utils.h" +#include "CTickRateSettings.h" #include extern CGame* g_pGame; @@ -70,6 +71,33 @@ bool CPlayerPuresyncPacket::Read(NetBitStreamInterface& BitStream) return false; pContactElement = CElementIDs::GetElement(Temp); } + + // Player position + SPositionSync position(false); + bool positionRead = BitStream.Read(&position); + + if (positionRead && pContactElement != nullptr) + { + int32_t radius = -1; + + switch (pContactElement->GetType()) + { + case CElement::VEHICLE: + if (((CVehicle*)pContactElement)->GetSyncer() != pSourcePlayer) + radius = g_TickRateSettings.iVehicleContactSyncRadius; + break; + } + + if (radius > -1 && + (!IsPointNearPoint3D(pSourcePlayer->GetPosition(), pContactElement->GetPosition(), radius) || + pSourcePlayer->GetDimension() != pContactElement->GetDimension())) + { + pContactElement = nullptr; + // Use current player position. They are not reporting their absolute position so we have to disregard it. + position.data.vecPosition = pSourcePlayer->GetPosition(); + } + } + CElement* pPreviousContactElement = pSourcePlayer->GetContactElement(); pSourcePlayer->SetContactElement(pContactElement); @@ -89,9 +117,7 @@ bool CPlayerPuresyncPacket::Read(NetBitStreamInterface& BitStream) pSourcePlayer->CallEvent("onPlayerContact", Arguments); } - // Player position - SPositionSync position(false); - if (!BitStream.Read(&position)) + if (!positionRead) return false; if (pContactElement) @@ -102,6 +128,7 @@ bool CPlayerPuresyncPacket::Read(NetBitStreamInterface& BitStream) CVector vecTempPos = pContactElement->GetPosition(); position.data.vecPosition += vecTempPos; } + pSourcePlayer->SetPosition(position.data.vecPosition); // Player rotation @@ -175,6 +202,12 @@ bool CPlayerPuresyncPacket::Read(NetBitStreamInterface& BitStream) // Set weapon slot if (bWeaponCorrect) pSourcePlayer->SetWeaponSlot(uiSlot); + else + { + // remove invalid weapon data to prevent this from being relayed to other players + ucClientWeaponType = 0; + slot.data.uiSlot = 0; + } if (CWeaponNames::DoesSlotHaveAmmo(uiSlot)) { diff --git a/Server/mods/deathmatch/mtaserver.conf b/Server/mods/deathmatch/mtaserver.conf index 5c81c07c54..19fe4a05d8 100644 --- a/Server/mods/deathmatch/mtaserver.conf +++ b/Server/mods/deathmatch/mtaserver.conf @@ -135,6 +135,10 @@ Values: 0 - disabled , 1 - enabled ; default value: 1. --> 1 + + 30 + 1 + + 1000 + 100 + diff --git a/Server/mods/deathmatch/mtaserver.conf.template b/Server/mods/deathmatch/mtaserver.conf.template index a276ba2338..faf1c71a6d 100644 --- a/Server/mods/deathmatch/mtaserver.conf.template +++ b/Server/mods/deathmatch/mtaserver.conf.template @@ -1,4 +1,3 @@ -R"=====( @@ -137,6 +136,10 @@ R"=====( Values: 0 - disabled , 1 - enabled ; default value: 1. --> 1 + + 30 + 1 + + + 1000 + 100 -)=====" diff --git a/Server/mods/deathmatch/premake5.lua b/Server/mods/deathmatch/premake5.lua index cad1bb344f..ddecdfb179 100644 --- a/Server/mods/deathmatch/premake5.lua +++ b/Server/mods/deathmatch/premake5.lua @@ -17,6 +17,7 @@ project "Deathmatch" "../../../vendor/bochs", "../../../vendor/pme", "../../../vendor/zip", + "../../../vendor/glob/include", "../../../vendor/zlib", "../../../vendor/pcre", "../../../vendor/json-c", @@ -33,7 +34,7 @@ project "Deathmatch" defines { "SDK_WITH_BCRYPT" } links { - "Lua_Server", "sqlite", "ehs", "cryptopp", "pme", "pcre", "json-c", "zip", "zlib", "blowfish_bcrypt", + "Lua_Server", "sqlite", "ehs", "cryptopp", "pme", "pcre", "json-c", "zip", "glob", "zlib", "blowfish_bcrypt", } vpaths { diff --git a/Server/sdk/core/CServerBase.h b/Server/sdk/core/CServerBase.h index e4d1c3f615..4dfc073989 100644 --- a/Server/sdk/core/CServerBase.h +++ b/Server/sdk/core/CServerBase.h @@ -24,6 +24,7 @@ class CServerBase virtual void HandleInput(char* szCommand) = 0; virtual void GetTag(char* szInfoTag, int iInfoTag) = 0; + virtual bool IsReadyToAcceptConnections() const noexcept = 0; virtual bool IsFinished() = 0; virtual bool PendingWorkToDo() = 0; virtual bool GetSleepIntervals(int& iSleepBusyMs, int& iSleepIdleMs, int& iLogicFpsLimit) = 0; diff --git a/Shared/data/.gitignore b/Shared/data/.gitignore new file mode 100644 index 0000000000..98b8bc6d99 --- /dev/null +++ b/Shared/data/.gitignore @@ -0,0 +1 @@ +!x64/ diff --git a/Shared/data/MTA San Andreas/MTA/XInput9_1_0_mta.dll b/Shared/data/MTA San Andreas/MTA/XInput9_1_0_mta.dll index a14b6b87af..74387b0013 100644 Binary files a/Shared/data/MTA San Andreas/MTA/XInput9_1_0_mta.dll and b/Shared/data/MTA San Andreas/MTA/XInput9_1_0_mta.dll differ diff --git a/Shared/data/MTA San Andreas/MTA/bass.dll b/Shared/data/MTA San Andreas/MTA/bass.dll index 122bbf6ee9..358ed76763 100644 Binary files a/Shared/data/MTA San Andreas/MTA/bass.dll and b/Shared/data/MTA San Andreas/MTA/bass.dll differ diff --git a/Shared/data/MTA San Andreas/MTA/bass_aac.dll b/Shared/data/MTA San Andreas/MTA/bass_aac.dll index ed61301959..91f61becc3 100644 Binary files a/Shared/data/MTA San Andreas/MTA/bass_aac.dll and b/Shared/data/MTA San Andreas/MTA/bass_aac.dll differ diff --git a/Shared/data/MTA San Andreas/MTA/bass_ac3.dll b/Shared/data/MTA San Andreas/MTA/bass_ac3.dll index eb32677e56..abbb2d6bd8 100644 Binary files a/Shared/data/MTA San Andreas/MTA/bass_ac3.dll and b/Shared/data/MTA San Andreas/MTA/bass_ac3.dll differ diff --git a/Shared/data/MTA San Andreas/MTA/bass_fx.dll b/Shared/data/MTA San Andreas/MTA/bass_fx.dll index d013de5987..3d8184b34a 100644 Binary files a/Shared/data/MTA San Andreas/MTA/bass_fx.dll and b/Shared/data/MTA San Andreas/MTA/bass_fx.dll differ diff --git a/Shared/data/MTA San Andreas/MTA/bassflac.dll b/Shared/data/MTA San Andreas/MTA/bassflac.dll index d017b9131a..d0684c0732 100644 Binary files a/Shared/data/MTA San Andreas/MTA/bassflac.dll and b/Shared/data/MTA San Andreas/MTA/bassflac.dll differ diff --git a/Shared/data/MTA San Andreas/MTA/bassmidi.dll b/Shared/data/MTA San Andreas/MTA/bassmidi.dll index 823b515cd7..79f7521149 100644 Binary files a/Shared/data/MTA San Andreas/MTA/bassmidi.dll and b/Shared/data/MTA San Andreas/MTA/bassmidi.dll differ diff --git a/Shared/data/MTA San Andreas/MTA/bassmix.dll b/Shared/data/MTA San Andreas/MTA/bassmix.dll index e413823519..ade70b7546 100644 Binary files a/Shared/data/MTA San Andreas/MTA/bassmix.dll and b/Shared/data/MTA San Andreas/MTA/bassmix.dll differ diff --git a/Shared/data/MTA San Andreas/MTA/bassopus.dll b/Shared/data/MTA San Andreas/MTA/bassopus.dll index 8059f03f7f..8b30f18d40 100644 Binary files a/Shared/data/MTA San Andreas/MTA/bassopus.dll and b/Shared/data/MTA San Andreas/MTA/bassopus.dll differ diff --git a/Shared/data/MTA San Andreas/MTA/locale/en_US/client.pot b/Shared/data/MTA San Andreas/MTA/locale/en_US/client.pot index 8b3e9ae891..b19c565c3c 100644 --- a/Shared/data/MTA San Andreas/MTA/locale/en_US/client.pot +++ b/Shared/data/MTA San Andreas/MTA/locale/en_US/client.pot @@ -8,7 +8,7 @@ msgid "" msgstr "" "Project-Id-Version: MTA San Andreas 1.x\n" "Report-Msgid-Bugs-To: \n" -"POT-Creation-Date: 2023-11-11 12:22+0000\n" +"POT-Creation-Date: 2024-09-27 04:28+0000\n" "PO-Revision-Date: YEAR-MO-DA HO:MI+ZONE\n" "Last-Translator: FULL NAME \n" "Language-Team: LANGUAGE \n" @@ -18,6 +18,49 @@ msgstr "" "Content-Transfer-Encoding: 8bit\n" "Plural-Forms: nplurals=INTEGER; plural=EXPRESSION;\n" +#: Client/game_sa/CSettingsSA.cpp:767 +msgid "Can't find valid screen resolution." +msgstr "" + +#. Confirm that res should be used +#: Client/game_sa/CSettingsSA.cpp:843 +msgid "Are you sure you want to use this screen resolution?" +msgstr "" + +#: Client/game_sa/CSettingsSA.cpp:845 Client/loader/Dialogs.cpp:194 +msgid "MTA: San Andreas" +msgstr "" + +#: Client/cefweb/CWebsiteRequests.cpp:19 +msgid "Website requests" +msgstr "" + +#: Client/cefweb/CWebsiteRequests.cpp:27 +msgid "" +"The server requests the following websites in order to load them (later):" +msgstr "" + +#: Client/cefweb/CWebsiteRequests.cpp:33 +msgid "NEVER ENTER SENSITIVE DATA TO PROTECT THEM FROM BEING STOLEN" +msgstr "" + +#: Client/cefweb/CWebsiteRequests.cpp:46 +msgid "Remember decision" +msgstr "" + +#: Client/cefweb/CWebsiteRequests.cpp:51 Client/core/CSettings.cpp:974 +msgid "Allow" +msgstr "" + +#: Client/cefweb/CWebsiteRequests.cpp:57 +msgid "Deny" +msgstr "" + +#. Couldn't create render target for CPostEffects +#: Client/multiplayer_sa/CMultiplayerSA_CrashFixHacks.cpp:1450 +msgid "Problem with graphics driver" +msgstr "" + #: Client/mods/deathmatch/CClient.cpp:36 msgid "This version has expired." msgstr "" @@ -39,285 +82,327 @@ msgid "shows the network statistics" msgstr "" #. Key commands (registered as 'mod commands', can be disabled) -#: Client/mods/deathmatch/CClient.cpp:63 +#: Client/mods/deathmatch/CClient.cpp:62 msgid "open the chat input" msgstr "" -#: Client/mods/deathmatch/CClient.cpp:64 +#: Client/mods/deathmatch/CClient.cpp:63 msgid "transmits voice to other players" msgstr "" -#: Client/mods/deathmatch/CClient.cpp:65 +#: Client/mods/deathmatch/CClient.cpp:64 msgid "enters a car as passenger" msgstr "" -#: Client/mods/deathmatch/CClient.cpp:66 +#: Client/mods/deathmatch/CClient.cpp:65 msgid "next radio channel" msgstr "" -#: Client/mods/deathmatch/CClient.cpp:67 +#: Client/mods/deathmatch/CClient.cpp:66 msgid "previous radio channel" msgstr "" -#: Client/mods/deathmatch/CClient.cpp:68 +#: Client/mods/deathmatch/CClient.cpp:67 msgid "enables the radar view" msgstr "" -#: Client/mods/deathmatch/CClient.cpp:69 +#: Client/mods/deathmatch/CClient.cpp:68 msgid "zooms the radar in" msgstr "" -#: Client/mods/deathmatch/CClient.cpp:70 +#: Client/mods/deathmatch/CClient.cpp:69 msgid "zooms the radar out" msgstr "" -#: Client/mods/deathmatch/CClient.cpp:71 +#: Client/mods/deathmatch/CClient.cpp:70 msgid "moves the radar north" msgstr "" -#: Client/mods/deathmatch/CClient.cpp:72 +#: Client/mods/deathmatch/CClient.cpp:71 msgid "moves the radar south" msgstr "" -#: Client/mods/deathmatch/CClient.cpp:73 +#: Client/mods/deathmatch/CClient.cpp:72 msgid "moves the radar east" msgstr "" -#: Client/mods/deathmatch/CClient.cpp:74 +#: Client/mods/deathmatch/CClient.cpp:73 msgid "moves the radar west" msgstr "" -#: Client/mods/deathmatch/CClient.cpp:75 +#: Client/mods/deathmatch/CClient.cpp:74 msgid "attaches the radar" msgstr "" -#: Client/mods/deathmatch/CClient.cpp:76 +#: Client/mods/deathmatch/CClient.cpp:75 msgid "reduces radar opacity" msgstr "" -#: Client/mods/deathmatch/CClient.cpp:77 +#: Client/mods/deathmatch/CClient.cpp:76 msgid "increases radar opacity" msgstr "" -#: Client/mods/deathmatch/CClient.cpp:78 +#: Client/mods/deathmatch/CClient.cpp:77 msgid "toggles radar help text" msgstr "" -#: Client/mods/deathmatch/CClient.cpp:79 +#: Client/mods/deathmatch/CClient.cpp:78 msgid "sends a message to the targetted player" msgstr "" -#: Client/mods/deathmatch/CClient.cpp:80 +#: Client/mods/deathmatch/CClient.cpp:79 msgid "changes to the next weapon whilst in a vehicle" msgstr "" -#: Client/mods/deathmatch/CClient.cpp:81 +#: Client/mods/deathmatch/CClient.cpp:80 msgid "changes to the previous weapon whilst in a vehicle" msgstr "" -#: Client/mods/deathmatch/CClient.cpp:82 +#: Client/mods/deathmatch/CClient.cpp:81 msgid "outputs info about the current server" msgstr "" #. ACHTUNG" Should this be handled by the atomic cvar setter? -#: Client/mods/deathmatch/CClient.cpp:85 +#: Client/mods/deathmatch/CClient.cpp:84 msgid "defines the scale multiplier of all text-displays" msgstr "" #. Development mode -#: Client/mods/deathmatch/CClient.cpp:92 +#: Client/mods/deathmatch/CClient.cpp:91 msgid "(Development mode) shows the colshapes" msgstr "" -#: Client/mods/deathmatch/CClient.cpp:93 +#: Client/mods/deathmatch/CClient.cpp:92 msgid "(Development mode) prints world sound ids into the debug window" msgstr "" -#: Client/mods/deathmatch/logic/CPacketHandler.cpp:505 +#. Throw the error and disconnect +#: Client/mods/deathmatch/logic/CResourceFileDownloadManager.cpp:141 +#, c-format +msgid "Download error: %s" +msgstr "" + +#. Show timeout message and disconnect +#. Display an error, reset the error status and exit +#. Show a message that the connection timed out and abort +#. Show failed message and abort the attempt +#: Client/mods/deathmatch/logic/CResourceFileDownloadManager.cpp:145 +#: Client/mods/deathmatch/logic/CClientGame.cpp:641 +#: Client/mods/deathmatch/logic/CClientGame.cpp:715 +#: Client/mods/deathmatch/logic/CClientGame.cpp:739 +#: Client/mods/deathmatch/logic/CClientGame.cpp:761 +#: Client/mods/deathmatch/logic/CClientGame.cpp:1174 +#: Client/mods/deathmatch/logic/CClientGame.cpp:1254 +#: Client/mods/deathmatch/logic/CClientGame.cpp:1264 +#: Client/mods/deathmatch/logic/CClientGame.cpp:1333 +#: Client/mods/deathmatch/logic/CClientGame.cpp:1370 +#: Client/mods/deathmatch/logic/CClientGame.cpp:1419 +#: Client/mods/deathmatch/logic/CClientGame.cpp:1431 +#: Client/core/CSettings.cpp:2941 Client/core/CSettings.cpp:4166 +#: Client/core/CSettings.cpp:4194 Client/core/CSettings.cpp:4764 +#: Client/core/CCore.cpp:1275 Client/core/CCore.cpp:1288 +#: Client/core/CConnectManager.cpp:80 Client/core/CConnectManager.cpp:111 +#: Client/core/CConnectManager.cpp:127 Client/core/CConnectManager.cpp:263 +#: Client/core/CConnectManager.cpp:321 Client/core/CConnectManager.cpp:404 +#: Client/core/CConnectManager.cpp:411 Client/core/CConnectManager.cpp:421 +#: Client/core/CGUI.cpp:87 Client/core/ServerBrowser/CServerBrowser.cpp:1278 +#: Client/core/ServerBrowser/CServerBrowser.cpp:1300 +#: Client/core/ServerBrowser/CServerBrowser.cpp:1357 +#: Client/core/ServerBrowser/CServerBrowser.cpp:1406 +#: Client/core/DXHook/CDirect3DHook9.cpp:127 +#: Client/loader/MainFunctions.cpp:252 Client/loader/MainFunctions.cpp:267 +#: Client/loader/MainFunctions.cpp:269 Client/loader/MainFunctions.cpp:846 +#: Client/loader/CInstallManager.cpp:552 Client/loader/CInstallManager.cpp:561 +#: Shared/mods/deathmatch/logic/CLatentTransferManager.cpp:378 +#: Shared/sdk/SharedUtil.Misc.hpp:137 +msgid "Error" +msgstr "" + +#: Client/mods/deathmatch/logic/CPacketHandler.cpp:506 msgid "Disconnected: Invalid nickname" msgstr "" -#: Client/mods/deathmatch/logic/CPacketHandler.cpp:509 +#: Client/mods/deathmatch/logic/CPacketHandler.cpp:510 msgid "Disconnect from server" msgstr "" -#: Client/mods/deathmatch/logic/CPacketHandler.cpp:513 +#: Client/mods/deathmatch/logic/CPacketHandler.cpp:514 #, c-format msgid "" "Disconnected: Serial is banned.\n" "Reason: %s" msgstr "" -#: Client/mods/deathmatch/logic/CPacketHandler.cpp:519 +#: Client/mods/deathmatch/logic/CPacketHandler.cpp:520 #, c-format msgid "" "Disconnected: You are banned.\n" "Reason: %s" msgstr "" -#: Client/mods/deathmatch/logic/CPacketHandler.cpp:525 +#: Client/mods/deathmatch/logic/CPacketHandler.cpp:526 #, c-format msgid "" "Disconnected: Account is banned.\n" "Reason: %s" msgstr "" -#: Client/mods/deathmatch/logic/CPacketHandler.cpp:530 +#: Client/mods/deathmatch/logic/CPacketHandler.cpp:531 msgid "Disconnected: Version mismatch" msgstr "" -#: Client/mods/deathmatch/logic/CPacketHandler.cpp:534 +#: Client/mods/deathmatch/logic/CPacketHandler.cpp:535 msgid "Disconnected: Join flood. Please wait a minute, then reconnect." msgstr "" -#: Client/mods/deathmatch/logic/CPacketHandler.cpp:538 +#: Client/mods/deathmatch/logic/CPacketHandler.cpp:539 #, c-format msgid "" "Disconnected: Server from different branch.\n" "Information: %s" msgstr "" -#: Client/mods/deathmatch/logic/CPacketHandler.cpp:543 +#: Client/mods/deathmatch/logic/CPacketHandler.cpp:544 #, c-format msgid "" "Disconnected: Bad version.\n" "Information: %s" msgstr "" -#: Client/mods/deathmatch/logic/CPacketHandler.cpp:548 +#: Client/mods/deathmatch/logic/CPacketHandler.cpp:549 #, c-format msgid "" "Disconnected: Server is running a newer build.\n" "Information: %s" msgstr "" -#: Client/mods/deathmatch/logic/CPacketHandler.cpp:553 +#: Client/mods/deathmatch/logic/CPacketHandler.cpp:554 #, c-format msgid "" "Disconnected: Server is running an older build.\n" "Information: %s" msgstr "" -#: Client/mods/deathmatch/logic/CPacketHandler.cpp:558 +#: Client/mods/deathmatch/logic/CPacketHandler.cpp:559 msgid "Disconnected: Nick already in use" msgstr "" -#: Client/mods/deathmatch/logic/CPacketHandler.cpp:562 +#: Client/mods/deathmatch/logic/CPacketHandler.cpp:563 msgid "Disconnected: Player element could not be created." msgstr "" -#: Client/mods/deathmatch/logic/CPacketHandler.cpp:566 +#: Client/mods/deathmatch/logic/CPacketHandler.cpp:567 #, c-format msgid "Disconnected: Server refused the connection: %s" msgstr "" -#: Client/mods/deathmatch/logic/CPacketHandler.cpp:571 +#: Client/mods/deathmatch/logic/CPacketHandler.cpp:572 msgid "Disconnected: Serial verification failed" msgstr "" -#: Client/mods/deathmatch/logic/CPacketHandler.cpp:575 +#: Client/mods/deathmatch/logic/CPacketHandler.cpp:576 #, c-format msgid "Disconnected: Connection desync %s" msgstr "" -#: Client/mods/deathmatch/logic/CPacketHandler.cpp:584 +#: Client/mods/deathmatch/logic/CPacketHandler.cpp:585 #, c-format msgid "Disconnected: You were kicked by %s" msgstr "" -#: Client/mods/deathmatch/logic/CPacketHandler.cpp:589 +#: Client/mods/deathmatch/logic/CPacketHandler.cpp:590 #, c-format msgid "Disconnected: You were banned by %s" msgstr "" -#: Client/mods/deathmatch/logic/CPacketHandler.cpp:600 +#: Client/mods/deathmatch/logic/CPacketHandler.cpp:601 msgid "Disconnected: Server shutdown or restarting" msgstr "" -#: Client/mods/deathmatch/logic/CPacketHandler.cpp:620 +#: Client/mods/deathmatch/logic/CPacketHandler.cpp:621 msgid "You were kicked from the game" msgstr "" -#: Client/mods/deathmatch/logic/CPacketHandler.cpp:621 -#: Client/mods/deathmatch/logic/CPacketHandler.cpp:632 +#: Client/mods/deathmatch/logic/CPacketHandler.cpp:622 +#: Client/mods/deathmatch/logic/CPacketHandler.cpp:633 msgid "This server requires a non-modifed gta_sa.exe" msgstr "" -#: Client/mods/deathmatch/logic/CPacketHandler.cpp:622 -#: Client/mods/deathmatch/logic/CPacketHandler.cpp:633 +#: Client/mods/deathmatch/logic/CPacketHandler.cpp:623 +#: Client/mods/deathmatch/logic/CPacketHandler.cpp:634 msgid "Please replace gta_sa.exe" msgstr "" -#: Client/mods/deathmatch/logic/CPacketHandler.cpp:623 +#: Client/mods/deathmatch/logic/CPacketHandler.cpp:624 msgid "This server does not allow custom D3D9.DLLs" msgstr "" -#: Client/mods/deathmatch/logic/CPacketHandler.cpp:624 +#: Client/mods/deathmatch/logic/CPacketHandler.cpp:625 msgid "Remove D3D9.DLL from your GTA install directory and restart MTA" msgstr "" -#: Client/mods/deathmatch/logic/CPacketHandler.cpp:625 +#: Client/mods/deathmatch/logic/CPacketHandler.cpp:626 msgid "This server does not allow virtual machines" msgstr "" -#: Client/mods/deathmatch/logic/CPacketHandler.cpp:626 +#: Client/mods/deathmatch/logic/CPacketHandler.cpp:627 msgid "This server requires driver signing to be enabled" msgstr "" -#: Client/mods/deathmatch/logic/CPacketHandler.cpp:627 +#: Client/mods/deathmatch/logic/CPacketHandler.cpp:628 msgid "Please restart your PC" msgstr "" -#: Client/mods/deathmatch/logic/CPacketHandler.cpp:628 +#: Client/mods/deathmatch/logic/CPacketHandler.cpp:629 msgid "This server has detected missing anti-cheat components" msgstr "" -#: Client/mods/deathmatch/logic/CPacketHandler.cpp:629 +#: Client/mods/deathmatch/logic/CPacketHandler.cpp:630 msgid "Try restarting MTA" msgstr "" -#: Client/mods/deathmatch/logic/CPacketHandler.cpp:630 +#: Client/mods/deathmatch/logic/CPacketHandler.cpp:631 msgid "This server requires a non-modifed gta3.img and gta_int.img" msgstr "" -#: Client/mods/deathmatch/logic/CPacketHandler.cpp:631 +#: Client/mods/deathmatch/logic/CPacketHandler.cpp:632 msgid "Please replace gta3.img or gta_int.img" msgstr "" -#: Client/mods/deathmatch/logic/CPacketHandler.cpp:634 +#: Client/mods/deathmatch/logic/CPacketHandler.cpp:635 msgid "This server does not allow Wine" msgstr "" -#: Client/mods/deathmatch/logic/CPacketHandler.cpp:635 +#: Client/mods/deathmatch/logic/CPacketHandler.cpp:636 msgid "Ensure no other program is modifying MTA:SA" msgstr "" -#: Client/mods/deathmatch/logic/CPacketHandler.cpp:649 +#: Client/mods/deathmatch/logic/CPacketHandler.cpp:650 msgid "Time Remaining: " msgstr "" -#: Client/mods/deathmatch/logic/CPacketHandler.cpp:659 +#: Client/mods/deathmatch/logic/CPacketHandler.cpp:660 #, c-format msgid "%d day" msgid_plural "%d days" msgstr[0] "" msgstr[1] "" -#: Client/mods/deathmatch/logic/CPacketHandler.cpp:661 +#: Client/mods/deathmatch/logic/CPacketHandler.cpp:662 #, c-format msgid "%d hour" msgid_plural "%d hours" msgstr[0] "" msgstr[1] "" -#: Client/mods/deathmatch/logic/CPacketHandler.cpp:663 +#: Client/mods/deathmatch/logic/CPacketHandler.cpp:664 #, c-format msgid "%d minute" msgid_plural "%d minutes" msgstr[0] "" msgstr[1] "" -#: Client/mods/deathmatch/logic/CPacketHandler.cpp:665 +#: Client/mods/deathmatch/logic/CPacketHandler.cpp:666 #, c-format msgid "%d second" msgid_plural "%d seconds" @@ -325,340 +410,268 @@ msgstr[0] "" msgstr[1] "" #. Display the error -#: Client/mods/deathmatch/logic/CPacketHandler.cpp:669 +#: Client/mods/deathmatch/logic/CPacketHandler.cpp:670 msgid "Disconnected" msgstr "" -#: Client/mods/deathmatch/logic/CClientGame.cpp:370 +#: Client/mods/deathmatch/logic/CResource.cpp:375 +#: Client/mods/deathmatch/logic/CClientGame.cpp:1089 +#: Client/core/CSettings.cpp:3483 Client/core/CCore.cpp:674 +msgid "In-game" +msgstr "" + +#: Client/mods/deathmatch/logic/CClientGame.cpp:374 msgid "Flying a UFO around" msgstr "" -#: Client/mods/deathmatch/logic/CClientGame.cpp:370 +#: Client/mods/deathmatch/logic/CClientGame.cpp:374 msgid "Cruising around" msgstr "" -#: Client/mods/deathmatch/logic/CClientGame.cpp:370 +#: Client/mods/deathmatch/logic/CClientGame.cpp:374 msgid "Riding the waves of" msgstr "" -#: Client/mods/deathmatch/logic/CClientGame.cpp:371 +#: Client/mods/deathmatch/logic/CClientGame.cpp:375 msgid "Riding the train in" msgstr "" -#: Client/mods/deathmatch/logic/CClientGame.cpp:371 +#: Client/mods/deathmatch/logic/CClientGame.cpp:375 msgid "Flying around" msgstr "" -#: Client/mods/deathmatch/logic/CClientGame.cpp:372 +#: Client/mods/deathmatch/logic/CClientGame.cpp:376 msgid "Riding around" msgstr "" -#: Client/mods/deathmatch/logic/CClientGame.cpp:372 +#: Client/mods/deathmatch/logic/CClientGame.cpp:376 msgid "Monster truckin' around" msgstr "" -#: Client/mods/deathmatch/logic/CClientGame.cpp:372 +#: Client/mods/deathmatch/logic/CClientGame.cpp:376 msgid "Quaddin' around" msgstr "" -#: Client/mods/deathmatch/logic/CClientGame.cpp:373 +#: Client/mods/deathmatch/logic/CClientGame.cpp:377 msgid "Bunny hopping around" msgstr "" -#: Client/mods/deathmatch/logic/CClientGame.cpp:373 +#: Client/mods/deathmatch/logic/CClientGame.cpp:377 msgid "Doing weird stuff in" msgstr "" -#: Client/mods/deathmatch/logic/CClientGame.cpp:377 +#: Client/mods/deathmatch/logic/CClientGame.cpp:381 msgid "Climbing around in" msgstr "" -#: Client/mods/deathmatch/logic/CClientGame.cpp:378 -#: Client/mods/deathmatch/logic/CClientGame.cpp:379 +#: Client/mods/deathmatch/logic/CClientGame.cpp:382 +#: Client/mods/deathmatch/logic/CClientGame.cpp:383 msgid "Doing a drive-by in" msgstr "" -#: Client/mods/deathmatch/logic/CClientGame.cpp:380 +#: Client/mods/deathmatch/logic/CClientGame.cpp:384 msgid "Blub blub..." msgstr "" -#: Client/mods/deathmatch/logic/CClientGame.cpp:381 +#: Client/mods/deathmatch/logic/CClientGame.cpp:385 msgid "Breathing water" msgstr "" -#: Client/mods/deathmatch/logic/CClientGame.cpp:382 +#: Client/mods/deathmatch/logic/CClientGame.cpp:386 msgid "Drowning in" msgstr "" -#: Client/mods/deathmatch/logic/CClientGame.cpp:383 +#: Client/mods/deathmatch/logic/CClientGame.cpp:387 msgid "Ducking for cover in" msgstr "" -#: Client/mods/deathmatch/logic/CClientGame.cpp:384 +#: Client/mods/deathmatch/logic/CClientGame.cpp:388 msgid "Fighting in" msgstr "" -#: Client/mods/deathmatch/logic/CClientGame.cpp:385 +#: Client/mods/deathmatch/logic/CClientGame.cpp:389 msgid "Throwing fists in" msgstr "" -#: Client/mods/deathmatch/logic/CClientGame.cpp:386 +#: Client/mods/deathmatch/logic/CClientGame.cpp:390 msgid "Blastin' fools in" msgstr "" -#: Client/mods/deathmatch/logic/CClientGame.cpp:387 +#: Client/mods/deathmatch/logic/CClientGame.cpp:391 msgid "Shooting up" msgstr "" -#: Client/mods/deathmatch/logic/CClientGame.cpp:388 +#: Client/mods/deathmatch/logic/CClientGame.cpp:392 msgid "Jetpacking in" msgstr "" -#: Client/mods/deathmatch/logic/CClientGame.cpp:389 +#: Client/mods/deathmatch/logic/CClientGame.cpp:393 msgid "Literally on fire in" msgstr "" -#: Client/mods/deathmatch/logic/CClientGame.cpp:390 +#: Client/mods/deathmatch/logic/CClientGame.cpp:394 msgid "Burning up in" msgstr "" -#: Client/mods/deathmatch/logic/CClientGame.cpp:391 +#: Client/mods/deathmatch/logic/CClientGame.cpp:395 msgid "Swimming in" msgstr "" -#: Client/mods/deathmatch/logic/CClientGame.cpp:392 +#: Client/mods/deathmatch/logic/CClientGame.cpp:396 msgid "Floating around in" msgstr "" -#: Client/mods/deathmatch/logic/CClientGame.cpp:393 +#: Client/mods/deathmatch/logic/CClientGame.cpp:397 msgid "Being chased by a shark" msgstr "" -#: Client/mods/deathmatch/logic/CClientGame.cpp:394 +#: Client/mods/deathmatch/logic/CClientGame.cpp:398 msgid "Choking to death in" msgstr "" -#: Client/mods/deathmatch/logic/CClientGame.cpp:527 -#: Client/core/CMainMenu.cpp:304 Client/core/CSettings.cpp:3461 -#: Client/core/CCore.cpp:674 +#: Client/mods/deathmatch/logic/CClientGame.cpp:533 +#: Client/core/CSettings.cpp:3479 Client/core/CCore.cpp:674 +#: Client/core/CMainMenu.cpp:304 msgid "Main menu" msgstr "" -#. Show timeout message and disconnect -#. Display an error, reset the error status and exit -#. Show a message that the connection timed out and abort -#. Show failed message and abort the attempt -#: Client/mods/deathmatch/logic/CClientGame.cpp:635 -#: Client/mods/deathmatch/logic/CClientGame.cpp:709 -#: Client/mods/deathmatch/logic/CClientGame.cpp:733 -#: Client/mods/deathmatch/logic/CClientGame.cpp:755 -#: Client/mods/deathmatch/logic/CClientGame.cpp:1171 -#: Client/mods/deathmatch/logic/CClientGame.cpp:1251 -#: Client/mods/deathmatch/logic/CClientGame.cpp:1261 -#: Client/mods/deathmatch/logic/CClientGame.cpp:1330 -#: Client/mods/deathmatch/logic/CClientGame.cpp:1367 -#: Client/mods/deathmatch/logic/CClientGame.cpp:1416 -#: Client/mods/deathmatch/logic/CClientGame.cpp:1428 -#: Client/mods/deathmatch/logic/CResourceFileDownloadManager.cpp:145 -#: Client/mods/deathmatch/logic/CServer.cpp:181 -#: Client/loader/MainFunctions.cpp:252 Client/loader/MainFunctions.cpp:267 -#: Client/loader/MainFunctions.cpp:269 Client/loader/MainFunctions.cpp:846 -#: Client/loader/CInstallManager.cpp:552 Client/loader/CInstallManager.cpp:561 -#: Client/core/CConnectManager.cpp:80 Client/core/CConnectManager.cpp:111 -#: Client/core/CConnectManager.cpp:127 Client/core/CConnectManager.cpp:263 -#: Client/core/CConnectManager.cpp:321 Client/core/CConnectManager.cpp:404 -#: Client/core/CConnectManager.cpp:411 Client/core/CConnectManager.cpp:421 -#: Client/core/CGUI.cpp:87 Client/core/CSettings.cpp:2929 -#: Client/core/CSettings.cpp:4148 Client/core/CSettings.cpp:4176 -#: Client/core/CSettings.cpp:4718 Client/core/CCore.cpp:1275 -#: Client/core/CCore.cpp:1288 Client/core/DXHook/CDirect3DHook9.cpp:127 -#: Client/core/ServerBrowser/CServerBrowser.cpp:1278 -#: Client/core/ServerBrowser/CServerBrowser.cpp:1300 -#: Client/core/ServerBrowser/CServerBrowser.cpp:1357 -#: Client/core/ServerBrowser/CServerBrowser.cpp:1406 -#: Shared/mods/deathmatch/logic/CLatentTransferManager.cpp:378 -#: Shared/sdk/SharedUtil.Misc.hpp:137 -msgid "Error" -msgstr "" - -#: Client/mods/deathmatch/logic/CClientGame.cpp:635 -#: Client/mods/deathmatch/logic/CClientGame.cpp:733 +#: Client/mods/deathmatch/logic/CClientGame.cpp:641 +#: Client/mods/deathmatch/logic/CClientGame.cpp:739 #: Client/core/ServerBrowser/CServerBrowser.cpp:1300 #: Client/core/ServerBrowser/CServerBrowser.cpp:1357 msgid "Invalid nickname! Please go to Settings and set a new one!" msgstr "" #. Display the status box -#: Client/mods/deathmatch/logic/CClientGame.cpp:651 +#: Client/mods/deathmatch/logic/CClientGame.cpp:657 #: Client/core/CConnectManager.cpp:148 msgid "CONNECTING" msgstr "" -#: Client/mods/deathmatch/logic/CClientGame.cpp:651 +#: Client/mods/deathmatch/logic/CClientGame.cpp:657 msgid "Entering the game ..." msgstr "" -#: Client/mods/deathmatch/logic/CClientGame.cpp:709 +#: Client/mods/deathmatch/logic/CClientGame.cpp:715 msgid "" "Not connected; please use Quick Connect or the 'connect' command to connect " "to a server." msgstr "" -#: Client/mods/deathmatch/logic/CClientGame.cpp:755 -msgid "The server is not installed" +#: Client/mods/deathmatch/logic/CClientGame.cpp:761 +msgid "Could not start the local server. See console for details." msgstr "" -#: Client/mods/deathmatch/logic/CClientGame.cpp:765 -#: Client/mods/deathmatch/logic/CClientGame.cpp:1240 +#: Client/mods/deathmatch/logic/CClientGame.cpp:771 +#: Client/mods/deathmatch/logic/CClientGame.cpp:1243 msgid "Local Server" msgstr "" -#: Client/mods/deathmatch/logic/CClientGame.cpp:765 +#: Client/mods/deathmatch/logic/CClientGame.cpp:771 msgid "Starting local server ..." msgstr "" -#: Client/mods/deathmatch/logic/CClientGame.cpp:1013 +#: Client/mods/deathmatch/logic/CClientGame.cpp:1019 msgid "Area 51" msgstr "" -#: Client/mods/deathmatch/logic/CClientGame.cpp:1022 +#: Client/mods/deathmatch/logic/CClientGame.cpp:1028 msgid "Walking around " msgstr "" -#: Client/mods/deathmatch/logic/CClientGame.cpp:1083 -#: Client/mods/deathmatch/logic/CResource.cpp:372 -#: Client/core/CSettings.cpp:3465 Client/core/CCore.cpp:674 -msgid "In-game" -msgstr "" - -#: Client/mods/deathmatch/logic/CClientGame.cpp:1171 +#: Client/mods/deathmatch/logic/CClientGame.cpp:1174 #, c-format msgid "You were kicked from the game ( %s )" msgstr "" -#: Client/mods/deathmatch/logic/CClientGame.cpp:1240 +#: Client/mods/deathmatch/logic/CClientGame.cpp:1243 msgid "Connecting to local server..." msgstr "" -#: Client/mods/deathmatch/logic/CClientGame.cpp:1251 +#: Client/mods/deathmatch/logic/CClientGame.cpp:1254 msgid "Error connecting to server." msgstr "" -#: Client/mods/deathmatch/logic/CClientGame.cpp:1261 +#: Client/mods/deathmatch/logic/CClientGame.cpp:1264 msgid "Connecting to local server timed out. See console for details." msgstr "" -#: Client/mods/deathmatch/logic/CClientGame.cpp:1330 +#: Client/mods/deathmatch/logic/CClientGame.cpp:1333 #: Client/core/CConnectManager.cpp:263 msgid "Connection timed out" msgstr "" -#: Client/mods/deathmatch/logic/CClientGame.cpp:1367 +#: Client/mods/deathmatch/logic/CClientGame.cpp:1370 msgid "Connection with the server was lost" msgstr "" -#: Client/mods/deathmatch/logic/CClientGame.cpp:1378 +#: Client/mods/deathmatch/logic/CClientGame.cpp:1381 #: Client/core/CConnectManager.cpp:277 Client/core/CConnectManager.cpp:281 msgid "Disconnected: unknown protocol error" msgstr "" -#: Client/mods/deathmatch/logic/CClientGame.cpp:1382 +#: Client/mods/deathmatch/logic/CClientGame.cpp:1385 #: Client/core/CConnectManager.cpp:285 msgid "Disconnected: disconnected remotely" msgstr "" -#: Client/mods/deathmatch/logic/CClientGame.cpp:1386 +#: Client/mods/deathmatch/logic/CClientGame.cpp:1389 #: Client/core/CConnectManager.cpp:289 msgid "Disconnected: connection lost remotely" msgstr "" -#: Client/mods/deathmatch/logic/CClientGame.cpp:1390 +#: Client/mods/deathmatch/logic/CClientGame.cpp:1393 #: Client/core/CConnectManager.cpp:293 msgid "Disconnected: you are banned from this server" msgstr "" -#: Client/mods/deathmatch/logic/CClientGame.cpp:1394 +#: Client/mods/deathmatch/logic/CClientGame.cpp:1397 msgid "Disconnected: the server is currently full" msgstr "" -#: Client/mods/deathmatch/logic/CClientGame.cpp:1398 +#: Client/mods/deathmatch/logic/CClientGame.cpp:1401 #: Client/core/CConnectManager.cpp:300 msgid "Disconnected: disconnected from the server" msgstr "" -#: Client/mods/deathmatch/logic/CClientGame.cpp:1402 +#: Client/mods/deathmatch/logic/CClientGame.cpp:1405 #: Client/core/CConnectManager.cpp:304 msgid "Disconnected: connection to the server was lost" msgstr "" -#: Client/mods/deathmatch/logic/CClientGame.cpp:1406 +#: Client/mods/deathmatch/logic/CClientGame.cpp:1409 msgid "Disconnected: invalid password specified" msgstr "" -#: Client/mods/deathmatch/logic/CClientGame.cpp:1410 +#: Client/mods/deathmatch/logic/CClientGame.cpp:1413 #: Client/core/CConnectManager.cpp:311 msgid "Disconnected: connection was refused" msgstr "" -#: Client/mods/deathmatch/logic/CClientGame.cpp:1428 +#: Client/mods/deathmatch/logic/CClientGame.cpp:1431 msgid "MTA Client verification failed!" msgstr "" -#: Client/mods/deathmatch/logic/CClientGame.cpp:5693 +#: Client/mods/deathmatch/logic/CClientGame.cpp:5623 msgid "In a ditch" msgstr "" -#: Client/mods/deathmatch/logic/CClientGame.cpp:5693 +#: Client/mods/deathmatch/logic/CClientGame.cpp:5623 msgid "En-route to hospital" msgstr "" -#: Client/mods/deathmatch/logic/CClientGame.cpp:5693 +#: Client/mods/deathmatch/logic/CClientGame.cpp:5623 msgid "Meeting their maker" msgstr "" -#: Client/mods/deathmatch/logic/CClientGame.cpp:5694 +#: Client/mods/deathmatch/logic/CClientGame.cpp:5624 msgid "Regretting their decisions" msgstr "" -#: Client/mods/deathmatch/logic/CClientGame.cpp:5694 +#: Client/mods/deathmatch/logic/CClientGame.cpp:5624 msgid "Wasted" msgstr "" -#: Client/mods/deathmatch/logic/CTransferBox.cpp:25 -msgid "Map download progress:" -msgstr "" - -#: Client/mods/deathmatch/logic/CTransferBox.cpp:28 -msgid "Download Progress:" -msgstr "" - -#. Find our largest piece of text, so we can size accordingly -#: Client/mods/deathmatch/logic/CTransferBox.cpp:42 -#: Client/mods/deathmatch/logic/CTransferBox.cpp:105 -#, c-format -msgid "%s of %s" -msgstr "" - -#: Client/mods/deathmatch/logic/CTransferBox.cpp:44 -#: Client/mods/deathmatch/logic/CTransferBox.cpp:65 -msgid "Disconnect to cancel download" -msgstr "" - -#. Throw the error and disconnect -#: Client/mods/deathmatch/logic/CResourceFileDownloadManager.cpp:141 -#, c-format -msgid "Download error: %s" -msgstr "" - -#: Client/mods/deathmatch/logic/CServer.cpp:181 -msgid "Could not start the local server. See console for details." -msgstr "" - -#: Client/mods/deathmatch/logic/CServer.cpp:182 -#, c-format -msgid "Error: Could not start local server. [%s]" -msgstr "" - #: Client/mods/deathmatch/logic/CLocalServer.cpp:37 msgid "HOST GAME" msgstr "" @@ -667,8 +680,8 @@ msgstr "" #. * Webbrowser tab #. * #: Client/mods/deathmatch/logic/CLocalServer.cpp:51 -#: Client/core/CSettings.cpp:430 Client/core/CSettings.cpp:618 -#: Client/core/CSettings.cpp:892 Client/core/CSettings.cpp:2006 +#: Client/core/CSettings.cpp:442 Client/core/CSettings.cpp:630 +#: Client/core/CSettings.cpp:904 Client/core/CSettings.cpp:2018 msgid "General" msgstr "" @@ -721,2566 +734,2555 @@ msgstr "" #. Cancel button #: Client/mods/deathmatch/logic/CLocalServer.cpp:123 -#: Client/loader/Dialogs.cpp:136 Client/core/CVersionUpdater.cpp:1790 -#: Client/core/CVersionUpdater.cpp:1806 Client/core/CVersionUpdater.cpp:1841 -#: Client/core/CSettings.cpp:132 Client/core/CSettings.cpp:4738 +#: Client/core/CSettings.cpp:132 Client/core/CSettings.cpp:4784 +#: Client/core/CVersionUpdater.cpp:1790 Client/core/CVersionUpdater.cpp:1806 +#: Client/core/CVersionUpdater.cpp:1841 Client/loader/Dialogs.cpp:136 #: Client/gui/CGUIMessageBox_Impl.cpp:68 msgid "Cancel" msgstr "" -#. Couldn't create render target for CPostEffects -#: Client/multiplayer_sa/CMultiplayerSA_CrashFixHacks.cpp:1360 -msgid "Problem with graphics driver" +#: Client/mods/deathmatch/logic/CTransferBox.cpp:25 +msgid "Map download progress:" msgstr "" -#. ///////////////////////////////////////////////////////////////////////// -#. -#. Dialog strings -#. -#. -#. ///////////////////////////////////////////////////////////////////////// -#: Client/loader/Dialogs.cpp:131 Client/core/CVersionUpdater.cpp:1572 -#: Client/core/CVersionUpdater.cpp:1590 Client/core/CVersionUpdater.cpp:1859 -#: Client/core/CVersionUpdater.cpp:1878 Client/core/CQuestionBox.cpp:195 -#: Client/core/CMainMenu.cpp:1188 Client/core/CSettings.cpp:1377 -#: Client/core/CSettings.cpp:1401 Client/core/CSettings.cpp:4471 -#: Client/core/CSettings.cpp:4547 Client/core/CSettings.cpp:4596 -#: Client/core/ServerBrowser/CServerInfo.cpp:479 -#: Client/gui/CGUIMessageBox_Impl.cpp:72 -msgid "Yes" +#: Client/mods/deathmatch/logic/CTransferBox.cpp:28 +msgid "Download Progress:" msgstr "" -#: Client/loader/Dialogs.cpp:132 Client/core/CVersionUpdater.cpp:1571 -#: Client/core/CVersionUpdater.cpp:1589 Client/core/CVersionUpdater.cpp:1858 -#: Client/core/CVersionUpdater.cpp:1877 Client/core/CQuestionBox.cpp:194 -#: Client/core/CMainMenu.cpp:1187 Client/core/CSettings.cpp:1376 -#: Client/core/CSettings.cpp:1400 Client/core/CSettings.cpp:4470 -#: Client/core/CSettings.cpp:4546 Client/core/CSettings.cpp:4595 -#: Client/core/ServerBrowser/CServerInfo.cpp:479 -msgid "No" +#. Find our largest piece of text, so we can size accordingly +#: Client/mods/deathmatch/logic/CTransferBox.cpp:42 +#: Client/mods/deathmatch/logic/CTransferBox.cpp:105 +#, c-format +msgid "%s of %s" msgstr "" -#. Create buttons -#. OK button -#: Client/loader/Dialogs.cpp:133 Client/core/CVersionUpdater.cpp:1607 -#: Client/core/CVersionUpdater.cpp:1823 Client/core/CVersionUpdater.cpp:1916 -#: Client/core/CVersionUpdater.cpp:1938 Client/core/CVersionUpdater.cpp:1956 -#: Client/core/CVersionUpdater.cpp:1968 Client/core/CVersionUpdater.cpp:2120 -#: Client/core/CVersionUpdater.cpp:2129 Client/core/CVersionUpdater.cpp:2138 -#: Client/core/CVersionUpdater.cpp:2152 Client/core/CSettings.cpp:127 -#: Client/core/CSettings.cpp:4739 Client/gui/CGUIMessageBox_Impl.cpp:64 -msgid "OK" +#: Client/mods/deathmatch/logic/CTransferBox.cpp:44 +#: Client/mods/deathmatch/logic/CTransferBox.cpp:65 +msgid "Disconnect to cancel download" msgstr "" -#: Client/loader/Dialogs.cpp:134 -msgid "Quit" +#: Client/core/CScreenShot.cpp:104 +#, c-format +msgid "Screenshot got %d bytes, but expected %d" msgstr "" -#: Client/loader/Dialogs.cpp:135 -#: Client/core/ServerBrowser/CServerBrowser.cpp:556 -msgid "Help" +#: Client/core/CScreenShot.cpp:110 +msgid "Screenshot failed" msgstr "" -#: Client/loader/Dialogs.cpp:151 -msgid "MTA: San Andreas has encountered a problem" +#: Client/core/CScreenShot.cpp:160 +#, c-format +msgid "Screenshot taken: '%s'" msgstr "" -#: Client/loader/Dialogs.cpp:152 -msgid "Crash information" +#. Create window (with frame) if it will fit inside the screen resolution +#: Client/core/CSettings.cpp:84 +msgid "SETTINGS" msgstr "" -#: Client/loader/Dialogs.cpp:153 -msgid "" -"Tick the check box to send this crash info to MTA devs using the 'internet'" +#: Client/core/CSettings.cpp:116 +msgid "Multiplayer" msgstr "" -#: Client/loader/Dialogs.cpp:154 -msgid "Doing so will increase the chance of this crash being fixed." +#: Client/core/CSettings.cpp:117 +msgid "Video" msgstr "" -#: Client/loader/Dialogs.cpp:155 -msgid "Do you want to restart MTA: San Andreas ?" +#: Client/core/CSettings.cpp:118 +msgid "Audio" msgstr "" -#: Client/loader/Dialogs.cpp:162 -msgid "MTA: San Andreas - Warning" +#: Client/core/CSettings.cpp:119 +msgid "Binds" msgstr "" -#: Client/loader/Dialogs.cpp:163 -msgid "" -"Your Grand Theft Auto: San Andreas install directory contains these files:" +#: Client/core/CSettings.cpp:120 +msgid "Controls" msgstr "" -#: Client/loader/Dialogs.cpp:165 -msgid "" -"These files are not required and may interfere with the graphical features " -"in this version of MTA:SA.\n" -"\n" -"It is recommended that you remove or rename these files." +#: Client/core/CSettings.cpp:121 +msgid "Interface" msgstr "" -#: Client/loader/Dialogs.cpp:167 -msgid "Keep these files, but also show this warning on next start" +#: Client/core/CSettings.cpp:122 +msgid "Web Browser" msgstr "" -#: Client/loader/Dialogs.cpp:168 -msgid "Do not remind me about these files again" +#: Client/core/CSettings.cpp:123 +msgid "Advanced" msgstr "" -#: Client/loader/Dialogs.cpp:169 -msgid "Rename these files from *.dll to *.dll.bak" +#. Create buttons +#. OK button +#: Client/core/CSettings.cpp:127 Client/core/CSettings.cpp:4785 +#: Client/core/CVersionUpdater.cpp:1607 Client/core/CVersionUpdater.cpp:1823 +#: Client/core/CVersionUpdater.cpp:1916 Client/core/CVersionUpdater.cpp:1938 +#: Client/core/CVersionUpdater.cpp:1956 Client/core/CVersionUpdater.cpp:1968 +#: Client/core/CVersionUpdater.cpp:2120 Client/core/CVersionUpdater.cpp:2129 +#: Client/core/CVersionUpdater.cpp:2138 Client/core/CVersionUpdater.cpp:2152 +#: Client/loader/Dialogs.cpp:133 Client/gui/CGUIMessageBox_Impl.cpp:64 +msgid "OK" msgstr "" -#: Client/loader/Dialogs.cpp:170 -msgid "Show me these files" +#: Client/core/CSettings.cpp:147 Client/core/CSettings.cpp:338 +#: Client/core/CSettings.cpp:617 Client/core/CSettings.cpp:889 +msgid "Load defaults" msgstr "" -#: Client/loader/Dialogs.cpp:171 -msgid "Play MTA:SA" +#. * +#. * Controls tab +#. * +#: Client/core/CSettings.cpp:157 Client/core/CSettings.cpp:181 +msgid "Mouse sensitivity:" msgstr "" -#: Client/loader/Dialogs.cpp:177 -msgid "MTA: San Andreas - Confusing options" +#. VerticalAimSensitivity +#: Client/core/CSettings.cpp:157 Client/core/CSettings.cpp:199 +msgid "Vertical aim sensitivity:" msgstr "" -#: Client/loader/Dialogs.cpp:178 -msgid "NVidia Optimus detected!" +#. Mouse Options +#: Client/core/CSettings.cpp:160 +msgid "Mouse options" msgstr "" -#: Client/loader/Dialogs.cpp:179 -msgid "Try each option and see what works:" +#: Client/core/CSettings.cpp:167 +msgid "Invert mouse vertically" msgstr "" -#: Client/loader/Dialogs.cpp:180 -msgid "A - Standard NVidia" +#: Client/core/CSettings.cpp:171 +msgid "Steer with mouse" msgstr "" -#: Client/loader/Dialogs.cpp:181 -msgid "B - Alternate NVidia" +#: Client/core/CSettings.cpp:175 +msgid "Fly with mouse" msgstr "" -#: Client/loader/Dialogs.cpp:182 -msgid "C - Standard Intel" +#. Joypad options +#: Client/core/CSettings.cpp:217 +msgid "Joypad options" msgstr "" -#: Client/loader/Dialogs.cpp:183 -msgid "D - Alternate Intel" +#: Client/core/CSettings.cpp:230 +msgid "Standard controls (Mouse + Keyboard)" msgstr "" -#: Client/loader/Dialogs.cpp:184 -msgid "If you get desperate, this might help:" +#: Client/core/CSettings.cpp:237 +msgid "Classic controls (Joypad)" msgstr "" -#: Client/loader/Dialogs.cpp:185 -msgid "If you have already selected an option that works, this might help:" +#: Client/core/CSettings.cpp:274 +msgid "Dead Zone" msgstr "" -#: Client/loader/Dialogs.cpp:186 -msgid "Force windowed mode" +#: Client/core/CSettings.cpp:279 +msgid "Saturation" msgstr "" -#: Client/loader/Dialogs.cpp:187 -msgid "Don't show again" +#: Client/core/CSettings.cpp:285 +msgid "Use the 'Binds' tab for joypad buttons." msgstr "" -#: Client/loader/Dialogs.cpp:194 Client/game_sa/CSettingsSA.cpp:882 -msgid "MTA: San Andreas" +#: Client/core/CSettings.cpp:324 +msgid "Left Stick" msgstr "" -#: Client/loader/Dialogs.cpp:195 -msgid "Warning: Could not detect anti-virus product" +#: Client/core/CSettings.cpp:330 +msgid "Right Stick" msgstr "" -#: Client/loader/Dialogs.cpp:197 -msgid "" -"MTA could not detect an anti-virus on your PC.\n" -"\n" -"Viruses interfere with MTA and degrade your gameplay experience.\n" -"\n" -"Press 'Help' for more information." +#: Client/core/CSettings.cpp:345 +msgid "DESCRIPTION" msgstr "" -#: Client/loader/Dialogs.cpp:200 -msgid "I have already installed an anti-virus" +#: Client/core/CSettings.cpp:346 +msgid "KEY" msgstr "" -#: Client/loader/Dialogs.cpp:202 -msgid "" -"I will not install an anti-virus.\n" -"I want my PC to lag and be part of a botnet." +#: Client/core/CSettings.cpp:348 +msgid "ALT. KEY" msgstr "" -#: Client/loader/Dialogs.cpp:890 Client/loader/Utils.cpp:534 -msgid "Searching for Grand Theft Auto San Andreas" +#. * +#. * Multiplayer tab +#. * +#: Client/core/CSettings.cpp:353 Client/core/CSettings.cpp:356 +msgid "Nick:" msgstr "" -#: Client/loader/Dialogs.cpp:893 Client/loader/Utils.cpp:536 -msgid "Please start Grand Theft Auto San Andreas" +#: Client/core/CSettings.cpp:378 +msgid "Save server passwords" msgstr "" -#: Client/loader/Dialogs.cpp:901 Client/loader/Install.cpp:849 -msgid "Installing update..." +#: Client/core/CSettings.cpp:383 +msgid "Auto-refresh server browser" msgstr "" -#: Client/loader/Dialogs.cpp:909 Client/loader/Install.cpp:931 -msgid "Extracting files..." +#: Client/core/CSettings.cpp:388 +msgid "Allow screen upload" msgstr "" -#: Client/loader/Dialogs.cpp:914 Client/loader/Utils.cpp:1394 -msgid "Copying files..." +#: Client/core/CSettings.cpp:393 +msgid "Allow external sounds" msgstr "" -#: Client/loader/Dialogs.cpp:919 Client/loader/Utils.cpp:1454 -msgid "Copy finished early. Everything OK." +#: Client/core/CSettings.cpp:398 +msgid "Always show download window" msgstr "" -#: Client/loader/Dialogs.cpp:924 Client/loader/Utils.cpp:1460 -msgid "Finishing..." +#: Client/core/CSettings.cpp:403 +msgid "Allow connecting with Discord Rich Presence" msgstr "" -#: Client/loader/Dialogs.cpp:928 Client/loader/Utils.cpp:1462 -msgid "Done!" +#: Client/core/CSettings.cpp:408 +msgid "Use customized GTA:SA files" msgstr "" -#: Client/loader/MainFunctions.cpp:248 -msgid "" -"Trouble restarting MTA:SA\n" -"\n" -"If the problem persists, open Task Manager and\n" -"stop the 'gta_sa.exe' and 'Multi Theft Auto.exe' processes\n" -"\n" -"\n" -"Try to launch MTA:SA again?" +#: Client/core/CSettings.cpp:413 +msgid "Map rendering options" msgstr "" -#: Client/loader/MainFunctions.cpp:266 -msgid "" -"Another instance of MTA is already running.\n" -"\n" -"If this problem persists, please restart your computer" +#: Client/core/CSettings.cpp:419 Client/core/CSettings.cpp:628 +msgid "Opacity:" msgstr "" -#: Client/loader/MainFunctions.cpp:269 -msgid "" -"Another instance of MTA is already running.\n" -"\n" -"Do you want to terminate it?" +#. * +#. * Audio tab +#. * +#: Client/core/CSettings.cpp:439 Client/core/CSettings.cpp:448 +msgid "Master volume:" msgstr "" -#: Client/loader/MainFunctions.cpp:294 -msgid "" -"Are you having problems running MTA:SA?.\n" -"\n" -"Do you want to revert to an earlier version?" +#: Client/core/CSettings.cpp:439 Client/core/CSettings.cpp:467 +msgid "Radio volume:" msgstr "" -#: Client/loader/MainFunctions.cpp:324 -msgid "" -"There seems to be a problem launching MTA:SA.\n" -"Resetting GTA settings can sometimes fix this problem.\n" -"\n" -"Do you want to reset GTA settings now?" +#: Client/core/CSettings.cpp:439 Client/core/CSettings.cpp:486 +msgid "SFX volume:" msgstr "" -#: Client/loader/MainFunctions.cpp:339 -msgid "" -"GTA settings have been reset.\n" -"\n" -"Press OK to continue." +#: Client/core/CSettings.cpp:439 Client/core/CSettings.cpp:505 +msgid "MTA volume:" msgstr "" -#: Client/loader/MainFunctions.cpp:344 -#, c-format -msgid "File could not be deleted: '%s'" +#: Client/core/CSettings.cpp:440 Client/core/CSettings.cpp:524 +msgid "Voice volume:" msgstr "" -#. No settings to delete, or can't find them -#: Client/loader/MainFunctions.cpp:352 -msgid "" -"Are you having problems running MTA:SA?.\n" -"\n" -"Do you want to see some online help?" +#: Client/core/CSettings.cpp:440 Client/core/CSettings.cpp:565 +msgid "Play mode:" msgstr "" -#. Inform user -#: Client/loader/MainFunctions.cpp:388 -msgid "" -"Are you having problems running MTA:SA?.\n" -"\n" -"Do you want to change the following setting?" +#: Client/core/CSettings.cpp:543 +msgid "Radio options" msgstr "" -#: Client/loader/MainFunctions.cpp:389 Client/core/CSettings.cpp:650 -#: Client/core/CSettings.cpp:992 -msgid "Fullscreen mode:" +#: Client/core/CSettings.cpp:549 +msgid "Radio Equalizer" msgstr "" -#: Client/loader/MainFunctions.cpp:389 Client/core/CSettings.cpp:658 -#: Client/core/CSettings.cpp:1603 -msgid "Borderless window" +#: Client/core/CSettings.cpp:554 +msgid "Radio Auto-tune" msgstr "" -#: Client/loader/MainFunctions.cpp:431 -msgid "" -"Are you having problems running MTA:SA?.\n" -"\n" -"Try disabling the following products for GTA and MTA:" +#: Client/core/CSettings.cpp:559 +msgid "Usertrack options" msgstr "" -#: Client/loader/MainFunctions.cpp:465 -msgid "" -"WARNING\n" -"\n" -"MTA:SA has detected unusual activity.\n" -"Please run a virus scan to ensure your system is secure.\n" -"\n" +#: Client/core/CSettings.cpp:573 Client/core/CSettings.cpp:3087 +msgid "Radio" msgstr "" -#: Client/loader/MainFunctions.cpp:468 -#, c-format -msgid "The detected file was: %s\n" +#: Client/core/CSettings.cpp:574 Client/core/CSettings.cpp:3089 +msgid "Random" msgstr "" -#: Client/loader/MainFunctions.cpp:602 -msgid "" -"An instance of GTA: San Andreas is already running. It needs to be " -"terminated before MTA:SA can be started. Do you want to do that now?" +#: Client/core/CSettings.cpp:575 Client/core/CSettings.cpp:3091 +msgid "Sequential" msgstr "" -#: Client/loader/MainFunctions.cpp:603 Client/loader/MainFunctions.cpp:610 -#: Client/loader/MainFunctions.cpp:1218 -#: Client/core/ServerBrowser/CServerInfo.cpp:319 -#: Client/core/ServerBrowser/CServerBrowser.cpp:1380 -msgid "Information" +#: Client/core/CSettings.cpp:578 +msgid "Automatic Media Scan" msgstr "" -#: Client/loader/MainFunctions.cpp:609 -msgid "" -"Unable to terminate GTA: San Andreas. If the problem persists, please " -"restart your computer." +#: Client/core/CSettings.cpp:585 +msgid "Mute options" msgstr "" -#: Client/loader/MainFunctions.cpp:632 -msgid "" -"Registry entries are missing. Please reinstall Multi Theft Auto: San Andreas." +#: Client/core/CSettings.cpp:591 +msgid "Mute All sounds when minimized" msgstr "" -#: Client/loader/MainFunctions.cpp:638 -msgid "" -"The path to your installation of GTA: San Andreas contains unsupported " -"(unicode) characters. Please move your Grand Theft Auto: San Andreas " -"installation to a compatible path that contains only standard ASCII " -"characters and reinstall Multi Theft Auto: San Andreas." +#: Client/core/CSettings.cpp:596 +msgid "Mute Radio sounds when minimized" msgstr "" -#: Client/loader/MainFunctions.cpp:648 -msgid "" -"The path to your installation of 'MTA:SA' or 'GTA: San Andreas'\n" -"contains a ';' (semicolon).\n" -"\n" -" If you experience problems when running MTA:SA,\n" -" move your installation(s) to a path that does not contain a semicolon." +#: Client/core/CSettings.cpp:601 +msgid "Mute SFX sounds when minimized" msgstr "" -#: Client/loader/MainFunctions.cpp:810 -msgid "" -"Load failed. Please ensure that the latest data files have been installed " -"correctly." +#: Client/core/CSettings.cpp:606 +msgid "Mute MTA sounds when minimized" msgstr "" -#: Client/loader/MainFunctions.cpp:819 -#, c-format -msgid "Load failed. Please ensure that %s is installed correctly." +#: Client/core/CSettings.cpp:611 +msgid "Mute Voice sounds when minimized" msgstr "" -#: Client/loader/MainFunctions.cpp:826 -#, c-format -msgid "Load failed. Could not find gta_sa.exe in %s." +#. * +#. * Video tab +#. * +#: Client/core/CSettings.cpp:627 Client/core/CSettings.cpp:636 +msgid "Resolution:" msgstr "" -#: Client/loader/MainFunctions.cpp:836 -#, c-format -msgid "" -"Load failed. %s exists in the GTA directory. Please delete before continuing." +#: Client/core/CSettings.cpp:627 Client/core/CSettings.cpp:683 +msgid "FOV:" msgstr "" -#: Client/loader/MainFunctions.cpp:845 -#, c-format -msgid "Main file has an incorrect name (%s)" +#: Client/core/CSettings.cpp:627 Client/core/CSettings.cpp:699 +msgid "Draw Distance:" msgstr "" -#: Client/loader/MainFunctions.cpp:856 -msgid "" -"Main file is unsigned. Possible virus activity.\n" -"\n" -"See online help if MTA does not work correctly." +#: Client/core/CSettings.cpp:627 Client/core/CSettings.cpp:717 +msgid "Brightness:" msgstr "" -#: Client/loader/MainFunctions.cpp:882 -#, c-format -msgid "" -"Data file %s is missing. Possible virus activity.\n" -"\n" -"Consider reinstalling Multi Theft Auto for your security.\n" -"See online help if MTA does not work correctly." +#: Client/core/CSettings.cpp:627 Client/core/CSettings.cpp:735 +msgid "FX Quality:" msgstr "" -#: Client/loader/MainFunctions.cpp:893 -#, c-format -msgid "" -"Data file %s is modified. Possible virus activity.\n" -"\n" -"Consider reinstalling Multi Theft Auto for your security.\n" -"See online help if MTA does not work correctly." +#: Client/core/CSettings.cpp:628 Client/core/CSettings.cpp:749 +msgid "Anisotropic filtering:" msgstr "" -#: Client/loader/MainFunctions.cpp:907 -msgid "" -".asi files are in the 'MTA:SA' or 'GTA: San Andreas' installation " -"directory.\n" -"\n" -"Remove these .asi files if you experience problems with MTA:SA." +#: Client/core/CSettings.cpp:628 Client/core/CSettings.cpp:776 +msgid "Anti-aliasing:" msgstr "" -#: Client/loader/MainFunctions.cpp:1009 -msgid "" -"File version mismatch error. Reinstall MTA:SA if you experience problems.\n" +#: Client/core/CSettings.cpp:628 Client/core/CSettings.cpp:790 +msgid "Aspect Ratio:" msgstr "" -#: Client/loader/MainFunctions.cpp:1018 -msgid "Some files are missing. Reinstall MTA:SA if you experience problems.\n" +#: Client/core/CSettings.cpp:648 +msgid "Windowed" msgstr "" -#: Client/loader/MainFunctions.cpp:1030 -msgid "" -"MTA:SA is not compatible with Windows 'Safe Mode'.\n" -"\n" -"Please restart your PC.\n" +#: Client/core/CSettings.cpp:654 +msgid "DPI aware" msgstr "" -#: Client/loader/MainFunctions.cpp:1122 -msgid "Fix configuration issue" +#: Client/core/CSettings.cpp:662 Client/core/CSettings.cpp:1004 +#: Client/loader/MainFunctions.cpp:389 +msgid "Fullscreen mode:" msgstr "" -#. Try to relaunch as admin if not done so already -#: Client/loader/MainFunctions.cpp:1156 -msgid "Fix elevation required error" +#: Client/core/CSettings.cpp:669 Client/core/CSettings.cpp:1613 +msgid "Standard" msgstr "" -#: Client/loader/MainFunctions.cpp:1163 -#, c-format -msgid "" -"Could not start Grand Theft Auto: San Andreas. Please try restarting, or if " -"the problem persists,contact MTA at www.multitheftauto.com. \n" -"\n" -"[%s]" +#: Client/core/CSettings.cpp:670 Client/core/CSettings.cpp:1615 +#: Client/loader/MainFunctions.cpp:389 +msgid "Borderless window" msgstr "" -#: Client/loader/MainFunctions.cpp:1218 -msgid "" -"GTA: San Andreas may not have launched correctly. Do you want to terminate " -"it?" +#: Client/core/CSettings.cpp:671 Client/core/CSettings.cpp:1617 +msgid "Borderless keep res" msgstr "" -#: Client/loader/Utils.cpp:600 -msgid "Select your Grand Theft Auto: San Andreas Installation Directory" +#: Client/core/CSettings.cpp:675 +msgid "Mip Mapping" msgstr "" -#: Client/loader/Utils.cpp:968 Client/loader/CInstallManager.cpp:361 -#, c-format -msgid "" -"MTA:SA needs Administrator access for the following task:\n" -"\n" -" '%s'\n" -"\n" -"Please confirm in the next window." +#: Client/core/CSettings.cpp:743 Client/core/CSettings.cpp:1517 +msgid "Low" msgstr "" -#: Client/loader/Utils.cpp:1069 -#, c-format -msgid "Error loading %s module! (%s)" +#: Client/core/CSettings.cpp:744 Client/core/CSettings.cpp:1519 +msgid "Medium" msgstr "" -#: Client/loader/Utils.cpp:1502 -#, c-format -msgid "" -"New installation of %s detected.\n" -"\n" -"Do you want to copy your settings from %s ?" +#: Client/core/CSettings.cpp:745 Client/core/CSettings.cpp:1086 +#: Client/core/CSettings.cpp:1521 Client/core/CSettings.cpp:3145 +msgid "High" msgstr "" -#: Client/loader/Utils.cpp:1541 -#, c-format -msgid "GTA:SA had trouble opening the file '%s'" +#: Client/core/CSettings.cpp:746 Client/core/CSettings.cpp:1523 +msgid "Very high" msgstr "" -#: Client/loader/Utils.cpp:1563 -#, c-format -msgid "GTA:SA is missing the file '%s'." +#: Client/core/CSettings.cpp:761 Client/core/CSettings.cpp:784 +#: Client/core/CSettings.cpp:1017 Client/core/CSettings.cpp:1071 +#: Client/core/CSettings.cpp:1201 Client/core/CSettings.cpp:1527 +#: Client/core/CSettings.cpp:3152 Client/core/CSettings.cpp:3184 +#: Client/core/CSettings.cpp:3206 Client/core/CSettings.cpp:4234 +msgid "Off" msgstr "" -#: Client/loader/Utils.cpp:1588 -msgid "GTA:SA had trouble loading a model." +#: Client/core/CSettings.cpp:785 Client/core/CSettings.cpp:1529 +msgid "1x" msgstr "" -#: Client/loader/Utils.cpp:1590 -msgid "If you recently modified gta3.img, then try reinstalling GTA:SA." +#: Client/core/CSettings.cpp:786 Client/core/CSettings.cpp:1531 +msgid "2x" msgstr "" -#: Client/loader/Utils.cpp:1615 -msgid "GTA:SA had trouble adding an upgrade to a vehicle." +#: Client/core/CSettings.cpp:787 Client/core/CSettings.cpp:1533 +msgid "3x" msgstr "" -#: Client/loader/Utils.cpp:1634 -#, c-format -msgid "GTA:SA found errors in the file '%s'" +#: Client/core/CSettings.cpp:800 Client/core/CSettings.cpp:1019 +#: Client/core/CSettings.cpp:1539 Client/core/CSettings.cpp:3154 +msgid "Auto" msgstr "" -#: Client/loader/Utils.cpp:1716 -msgid "Did your computer restart when playing MTA:SA?" +#: Client/core/CSettings.cpp:801 Client/core/CSettings.cpp:1541 +msgid "4:3" msgstr "" -#: Client/loader/Utils.cpp:1781 -msgid "Please terminate the following programs before continuing:" +#: Client/core/CSettings.cpp:802 Client/core/CSettings.cpp:1543 +msgid "16:10" msgstr "" -#: Client/loader/CInstallManager.cpp:376 -#, c-format -msgid "" -"MTA:SA could not complete the following task:\n" -"\n" -" '%s'\n" +#: Client/core/CSettings.cpp:803 Client/core/CSettings.cpp:1545 +msgid "16:9" msgstr "" -#: Client/loader/CInstallManager.cpp:426 -msgid "" -"** The crash was caused by a graphics driver error **\n" -"\n" -"** Please update your graphics drivers **" +#: Client/core/CSettings.cpp:806 +msgid "HUD Match Aspect Ratio" msgstr "" -#: Client/loader/CInstallManager.cpp:532 -msgid "Install updated MTA:SA files" +#: Client/core/CSettings.cpp:812 +msgid "Volumetric Shadows" msgstr "" -#: Client/loader/CInstallManager.cpp:552 -msgid "" -"Could not update due to file conflicts. Please close other applications and " -"retry" +#: Client/core/CSettings.cpp:816 +msgid "Grass effect" msgstr "" -#: Client/loader/CInstallManager.cpp:561 -#, c-format -msgid "Multi Theft Auto has not been installed properly, please reinstall. %s" +#: Client/core/CSettings.cpp:820 +msgid "Heat haze" msgstr "" -#: Client/loader/CInstallManager.cpp:613 -msgid "Create GTA:SA junctions" +#: Client/core/CSettings.cpp:824 +msgid "Tyre Smoke etc" msgstr "" -#: Client/loader/CInstallManager.cpp:657 -msgid "MTA:SA cannot launch because copying a file failed:" +#: Client/core/CSettings.cpp:828 +msgid "Dynamic ped shadows" msgstr "" -#: Client/loader/CInstallManager.cpp:663 Client/loader/CInstallManager.cpp:703 -msgid "MTA:SA cannot launch because an MTA:SA file is incorrect or missing:" +#: Client/core/CSettings.cpp:832 +msgid "Motion blur" msgstr "" -#: Client/loader/CInstallManager.cpp:672 -msgid "Copy MTA:SA files" +#: Client/core/CSettings.cpp:837 +msgid "Full Screen Minimize" msgstr "" -#: Client/loader/CInstallManager.cpp:695 Client/loader/CInstallManager.cpp:773 -msgid "MTA:SA cannot launch because a GTA:SA file is incorrect or missing:" +#: Client/core/CSettings.cpp:849 +msgid "Enable Device Selection Dialog" msgstr "" -#: Client/loader/CInstallManager.cpp:780 -msgid "Patch GTA:SA dependency" +#: Client/core/CSettings.cpp:861 +msgid "Show unsafe resolutions" msgstr "" -#: Client/loader/CInstallManager.cpp:828 -msgid "" -"MTA:SA cannot launch because the GTA:SA executable is incorrect or missing:" +#: Client/core/CSettings.cpp:873 +msgid "Render vehicles always in high detail" msgstr "" -#: Client/loader/CInstallManager.cpp:832 -msgid "" -"Please check your anti-virus for a false-positive detection, try to add an " -"exception for the GTA:SA executable and restart MTA:SA." +#: Client/core/CSettings.cpp:877 +msgid "Render peds always in high detail" msgstr "" -#: Client/loader/CInstallManager.cpp:838 -msgid "Generate GTA:SA" +#: Client/core/CSettings.cpp:881 +msgid "Corona rain reflections" msgstr "" -#: Client/loader/CInstallManager.cpp:853 -msgid "MTA:SA cannot launch because the GTA:SA executable is not loadable:" +#: Client/core/CSettings.cpp:910 +msgid "Enable remote websites" msgstr "" -#: Client/loader/CInstallManager.cpp:860 Client/loader/CInstallManager.cpp:883 -msgid "Patch GTA:SA" +#: Client/core/CSettings.cpp:915 +msgid "Enable Javascript on remote websites" msgstr "" -#: Client/loader/CInstallManager.cpp:876 -msgid "MTA:SA cannot launch because patching GTA:SA has failed:" +#: Client/core/CSettings.cpp:920 +msgid "Custom blacklist" msgstr "" -#: Client/loader/CInstallManager.cpp:1057 Client/core/CCore.cpp:811 -#, c-format -msgid "MTA:SA cannot continue because drive %s does not have enough space." +#: Client/core/CSettings.cpp:931 Client/core/CSettings.cpp:966 +msgid "Enter a domain e.g. google.com" msgstr "" -#: Client/loader/CInstallManager.cpp:1113 -msgid "Missing file:" +#: Client/core/CSettings.cpp:939 +msgid "Block" msgstr "" -#: Client/loader/CInstallManager.cpp:1117 -msgid "If MTA fails to load, please re-install GTA:SA" +#: Client/core/CSettings.cpp:947 Client/core/CSettings.cpp:982 +msgid "Domain" msgstr "" -#: Client/loader/CInstallManager.cpp:1152 -msgid "Update install settings" +#: Client/core/CSettings.cpp:949 Client/core/CSettings.cpp:984 +msgid "Remove domain" msgstr "" -#: Client/loader/CInstallManager.cpp:1291 -msgid "Update compatibility settings" +#. Reset vecTemp +#: Client/core/CSettings.cpp:955 +msgid "Custom whitelist" msgstr "" -#: Client/loader/Install.cpp:265 -msgid "Unknown" +#. Misc section label +#: Client/core/CSettings.cpp:997 +msgid "Misc" msgstr "" -#: Client/loader/Install.cpp:272 -#, c-format -msgid "" -"The file '%s' is currently locked by %zu processes.\n" -"\n" -"Do you want to terminate the following processes and continue updating?\n" -"\n" -"%s" +#. Fast clothes loading +#: Client/core/CSettings.cpp:1003 Client/core/CSettings.cpp:1010 +#: Client/core/CSettings.cpp:4803 +msgid "Fast CJ clothes loading:" msgstr "" -#: Client/loader/Install.cpp:479 -#, c-format -msgid "" -"Your installation may be corrupt now.\n" -"\n" -"%zu out of %zu files could not be restored from the backup.\n" -"\n" -"You should reinstall Multi Theft Auto from www.multitheftauto.com\n" -"or try running the update with administrator rights." +#. Browser scan speed +#: Client/core/CSettings.cpp:1003 Client/core/CSettings.cpp:1024 +#: Client/core/CSettings.cpp:4805 +msgid "Browser speed:" msgstr "" -#. Create the window -#: Client/core/CNewsBrowser.cpp:153 -msgid "NEWS" +#. Single download +#: Client/core/CSettings.cpp:1003 Client/core/CSettings.cpp:1038 +#: Client/core/CSettings.cpp:4807 +msgid "Single connection:" msgstr "" -#. News link -#: Client/core/CNewsBrowser.cpp:171 Client/core/CNewsBrowser.cpp:172 -msgid "Visit latest news article" +#. Packet tag +#: Client/core/CSettings.cpp:1003 Client/core/CSettings.cpp:1051 +#: Client/core/CSettings.cpp:4809 +msgid "Packet tag:" msgstr "" -#: Client/core/CScreenShot.cpp:104 -#, c-format -msgid "Screenshot got %d bytes, but expected %d" +#. Progress animation +#: Client/core/CSettings.cpp:1004 Client/core/CSettings.cpp:1064 +#: Client/core/CSettings.cpp:4811 +msgid "Progress animation:" msgstr "" -#: Client/core/CScreenShot.cpp:110 -msgid "Screenshot failed" +#. Process priority +#: Client/core/CSettings.cpp:1004 Client/core/CSettings.cpp:1077 +#: Client/core/CSettings.cpp:4801 +msgid "Process priority:" msgstr "" -#: Client/core/CScreenShot.cpp:160 -#, c-format -msgid "Screenshot taken: '%s'" +#. Debug setting +#: Client/core/CSettings.cpp:1004 Client/core/CSettings.cpp:1091 +#: Client/core/CSettings.cpp:4813 +msgid "Debug setting:" msgstr "" -#. Create window -#: Client/core/CConsole.cpp:417 -msgid "CONSOLE" +#. Streaming memory +#: Client/core/CSettings.cpp:1005 Client/core/CSettings.cpp:1114 +#: Client/core/CSettings.cpp:4815 +msgid "Streaming memory:" msgstr "" -#: Client/core/CVersionUpdater.cpp:626 -msgid "Busy" +#. Update build type +#: Client/core/CSettings.cpp:1005 Client/core/CSettings.cpp:1215 +msgid "Update build type:" msgstr "" -#: Client/core/CVersionUpdater.cpp:626 -msgid "Can't check for updates right now" +#. UpdateAutoInstall +#: Client/core/CSettings.cpp:1005 Client/core/CSettings.cpp:1194 +msgid "Install important updates:" msgstr "" -#: Client/core/CVersionUpdater.cpp:1567 Client/core/CVersionUpdater.cpp:1587 -#: Client/core/CVersionUpdater.cpp:1605 -#, c-format -msgid "MTA:SA %s required" +#: Client/core/CSettings.cpp:1018 Client/core/CSettings.cpp:1046 +#: Client/core/CSettings.cpp:1059 Client/core/CSettings.cpp:3156 +#: Client/core/CSettings.cpp:3172 Client/core/CSettings.cpp:3179 +msgid "On" msgstr "" -#: Client/core/CVersionUpdater.cpp:1568 -#, c-format -msgid "" -"An updated version of MTA:SA %s is required to join the selected server.\n" -"\n" -"Do you want to download and install MTA:SA %s ?" +#: Client/core/CSettings.cpp:1031 Client/core/CSettings.cpp:3161 +msgid "Very slow" msgstr "" -#: Client/core/CVersionUpdater.cpp:1588 -#, c-format -msgid "Do you want to launch MTA:SA %s and connect to this server ?" +#: Client/core/CSettings.cpp:1032 Client/core/CSettings.cpp:1045 +#: Client/core/CSettings.cpp:1058 Client/core/CSettings.cpp:1072 +#: Client/core/CSettings.cpp:1098 Client/core/CSettings.cpp:1110 +#: Client/core/CSettings.cpp:1202 Client/core/CSettings.cpp:1222 +#: Client/core/CSettings.cpp:3163 Client/core/CSettings.cpp:3170 +#: Client/core/CSettings.cpp:3177 Client/core/CSettings.cpp:3186 +#: Client/core/CSettings.cpp:3199 +msgid "Default" msgstr "" -#: Client/core/CVersionUpdater.cpp:1606 -msgid "" -"It is not possible to connect at this time.\n" -"\n" -"Please try later." +#: Client/core/CSettings.cpp:1033 Client/core/CSettings.cpp:3165 +msgid "Fast" msgstr "" -#: Client/core/CVersionUpdater.cpp:1788 -msgid "Connecting" +#: Client/core/CSettings.cpp:1084 Client/core/CSettings.cpp:3141 +msgid "Normal" msgstr "" -#: Client/core/CVersionUpdater.cpp:1789 Client/core/CVersionUpdater.cpp:1805 -msgid "Please wait..." +#: Client/core/CSettings.cpp:1085 Client/core/CSettings.cpp:3143 +msgid "Above normal" msgstr "" -#: Client/core/CVersionUpdater.cpp:1804 -msgid "CHECKING" +#: Client/core/CSettings.cpp:1121 +msgid "Min" msgstr "" -#: Client/core/CVersionUpdater.cpp:1821 Client/core/CVersionUpdater.cpp:1914 -msgid "UPDATE CHECK" +#: Client/core/CSettings.cpp:1134 +msgid "Max" msgstr "" -#: Client/core/CVersionUpdater.cpp:1822 -msgid "No update needed" +#. Windows 8 compatibility +#: Client/core/CSettings.cpp:1141 +msgid "Windows 8 compatibility:" msgstr "" -#: Client/core/CVersionUpdater.cpp:1839 -msgid "DOWNLOADING" +#: Client/core/CSettings.cpp:1145 +msgid "16-bit color" msgstr "" -#: Client/core/CVersionUpdater.cpp:1840 -msgid "waiting..." +#: Client/core/CSettings.cpp:1150 +msgid "Mouse fix" msgstr "" -#: Client/core/CVersionUpdater.cpp:1856 -msgid "MANDATORY UPDATE" +#. Cache path info +#: Client/core/CSettings.cpp:1168 +msgid "Client resource files:" msgstr "" -#: Client/core/CVersionUpdater.cpp:1857 -msgid "" -"To join this server, you must update MTA.\n" -"\n" -" Do you want to update now ?" +#: Client/core/CSettings.cpp:1172 +msgid "Show in Explorer" msgstr "" -#: Client/core/CVersionUpdater.cpp:1875 -msgid "OPTIONAL UPDATE" +#. Auto updater section label +#: Client/core/CSettings.cpp:1187 Client/core/CSettings.cpp:1190 +msgid "Auto updater" msgstr "" -#: Client/core/CVersionUpdater.cpp:1876 -msgid "" -"Server says an update is recommended, but not essential.\n" -"\n" -" Do you want to update now ?" +#. Check for updates +#: Client/core/CSettings.cpp:1228 +msgid "Check for update now" msgstr "" -#: Client/core/CVersionUpdater.cpp:1915 +#: Client/core/CSettings.cpp:1382 +msgid "Some settings will be changed when you next start MTA" +msgstr "" + +#: Client/core/CSettings.cpp:1383 msgid "" -"Update not currently avalable.\n" "\n" -"Please check www.mtasa.com" +"\n" +"Do you want to restart now?" msgstr "" -#: Client/core/CVersionUpdater.cpp:1936 Client/core/CVersionUpdater.cpp:2118 -msgid "ERROR SAVING" +#: Client/core/CSettings.cpp:1386 +msgid "RESTART REQUIRED" msgstr "" -#: Client/core/CVersionUpdater.cpp:1937 Client/core/CVersionUpdater.cpp:2119 -msgid "Unable to create the file." +#: Client/core/CSettings.cpp:1388 Client/core/CSettings.cpp:1412 +#: Client/core/CSettings.cpp:4488 Client/core/CSettings.cpp:4562 +#: Client/core/CSettings.cpp:4592 Client/core/CSettings.cpp:4641 +#: Client/core/CQuestionBox.cpp:194 Client/core/CMainMenu.cpp:1199 +#: Client/core/CVersionUpdater.cpp:1571 Client/core/CVersionUpdater.cpp:1589 +#: Client/core/CVersionUpdater.cpp:1858 Client/core/CVersionUpdater.cpp:1877 +#: Client/core/ServerBrowser/CServerInfo.cpp:479 Client/loader/Dialogs.cpp:132 +msgid "No" msgstr "" -#: Client/core/CVersionUpdater.cpp:1945 Client/core/CVersionUpdater.cpp:1954 -#: Client/core/CVersionUpdater.cpp:2127 Client/core/CVersionUpdater.cpp:2136 -msgid "ERROR DOWNLOADING" +#. ///////////////////////////////////////////////////////////////////////// +#. +#. Dialog strings +#. +#. +#. ///////////////////////////////////////////////////////////////////////// +#: Client/core/CSettings.cpp:1389 Client/core/CSettings.cpp:1413 +#: Client/core/CSettings.cpp:4489 Client/core/CSettings.cpp:4563 +#: Client/core/CSettings.cpp:4593 Client/core/CSettings.cpp:4642 +#: Client/core/CQuestionBox.cpp:195 Client/core/CMainMenu.cpp:1200 +#: Client/core/CVersionUpdater.cpp:1572 Client/core/CVersionUpdater.cpp:1590 +#: Client/core/CVersionUpdater.cpp:1859 Client/core/CVersionUpdater.cpp:1878 +#: Client/core/ServerBrowser/CServerInfo.cpp:479 Client/loader/Dialogs.cpp:131 +#: Client/gui/CGUIMessageBox_Impl.cpp:72 +msgid "Yes" msgstr "" -#: Client/core/CVersionUpdater.cpp:1946 Client/core/CVersionUpdater.cpp:2128 -msgid "The downloaded file appears to be incorrect." +#: Client/core/CSettings.cpp:1406 +msgid "Some settings will be changed when you disconnect the current server" msgstr "" -#: Client/core/CVersionUpdater.cpp:1955 Client/core/CVersionUpdater.cpp:2137 -msgid "For some reason." +#: Client/core/CSettings.cpp:1407 +msgid "" +"\n" +"\n" +"Do you want to disconnect now?" msgstr "" -#: Client/core/CVersionUpdater.cpp:1966 Client/core/CVersionUpdater.cpp:2150 -msgid "DOWNLOAD COMPLETE" +#: Client/core/CSettings.cpp:1410 +msgid "DISCONNECT REQUIRED" msgstr "" -#: Client/core/CVersionUpdater.cpp:1990 -msgid " - Unknown problem in _DialogUpdateResult" +#. Update the joystick name +#: Client/core/CSettings.cpp:1737 +msgid "Joypad not detected - Check connections and restart game" msgstr "" -#: Client/core/CVersionUpdater.cpp:2081 Client/core/CSettings.cpp:4544 -msgid "CUSTOMIZED GTA:SA FILES" +#: Client/core/CSettings.cpp:1932 +msgid "Binding axis" msgstr "" -#: Client/core/CVersionUpdater.cpp:2088 Client/core/CVersionUpdater.cpp:2098 -msgid "Ok" +#: Client/core/CSettings.cpp:1932 +msgid "Move an axis to bind, or escape to clear" msgstr "" -#: Client/core/CVersionUpdater.cpp:2096 -msgid "ERROR" +#: Client/core/CSettings.cpp:2009 +msgid "Language:" msgstr "" -#: Client/core/CVersionUpdater.cpp:2097 -msgid "" -"Some MTA:SA data files are missing.\n" -"\n" -"\n" -"Please reinstall MTA:SA" +#: Client/core/CSettings.cpp:2009 +msgid "Skin:" msgstr "" -#: Client/core/CVersionUpdater.cpp:2774 -#, c-format -msgid "%3d %% completed" +#: Client/core/CSettings.cpp:2009 +msgid "Presets:" msgstr "" -#: Client/core/CVersionUpdater.cpp:2777 -#, c-format -msgid "" -"\n" -"\n" -"Waiting for response - %-3d" +#: Client/core/CSettings.cpp:2058 +msgid "Chat" msgstr "" -#: Client/core/CCredits.cpp:34 -msgid "Programming" +#: Client/core/CSettings.cpp:2075 +msgid "Load" msgstr "" -#: Client/core/CCredits.cpp:63 -msgid "Contributors" +#: Client/core/CSettings.cpp:2087 +msgid "Colors" msgstr "" -#: Client/core/CCredits.cpp:84 -msgid "Game Design / Scripting" +#: Client/core/CSettings.cpp:2088 +msgid "Layout" msgstr "" -#: Client/core/CCredits.cpp:104 -msgid "Language Localization" +#: Client/core/CSettings.cpp:2089 Client/core/CSettings.cpp:2335 +msgid "Options" msgstr "" -#: Client/core/CCredits.cpp:110 -msgid "Patch contributors" +#: Client/core/CSettings.cpp:2095 +msgid "Chat Background" msgstr "" -#: Client/core/CCredits.cpp:234 -msgid "Special Thanks" +#: Client/core/CSettings.cpp:2095 +msgid "Chat Text" msgstr "" -#: Client/core/CCredits.cpp:265 -msgid "" -"This software and project makes use of the following libraries and software:" +#: Client/core/CSettings.cpp:2095 +msgid "Input Background" msgstr "" -#: Client/core/CKeyBinds.cpp:186 -msgid "Fire" +#: Client/core/CSettings.cpp:2095 +msgid "Input Text" msgstr "" -#: Client/core/CKeyBinds.cpp:187 -msgid "Next weapon" +#: Client/core/CSettings.cpp:2118 +msgid "Lines:" msgstr "" -#: Client/core/CKeyBinds.cpp:188 -msgid "Previous weapon" +#: Client/core/CSettings.cpp:2118 +msgid "Scale:" msgstr "" -#: Client/core/CKeyBinds.cpp:189 -msgid "Forwards" +#: Client/core/CSettings.cpp:2118 +msgid "Width:" msgstr "" -#: Client/core/CKeyBinds.cpp:190 -msgid "Backwards" +#: Client/core/CSettings.cpp:2121 +msgid "Size" msgstr "" -#: Client/core/CKeyBinds.cpp:191 Client/core/CSettings.cpp:2228 -#: Client/core/CSettings.cpp:2256 -msgid "Left" +#: Client/core/CSettings.cpp:2170 +msgid "after" msgstr "" -#: Client/core/CKeyBinds.cpp:192 Client/core/CSettings.cpp:2230 -#: Client/core/CSettings.cpp:2257 -msgid "Right" +#: Client/core/CSettings.cpp:2170 +msgid "for" msgstr "" -#: Client/core/CKeyBinds.cpp:193 -msgid "Zoom in" +#: Client/core/CSettings.cpp:2170 +msgid "sec" msgstr "" -#: Client/core/CKeyBinds.cpp:194 -msgid "Zoom out" +#: Client/core/CSettings.cpp:2173 +msgid "Fading" msgstr "" -#: Client/core/CKeyBinds.cpp:195 -msgid "Enter/Exit" +#: Client/core/CSettings.cpp:2179 +msgid "Fade out old lines" msgstr "" -#: Client/core/CKeyBinds.cpp:196 -msgid "Change camera" +#: Client/core/CSettings.cpp:2219 +msgid "Horizontal:" msgstr "" -#. 10 -#: Client/core/CKeyBinds.cpp:197 -msgid "Jump" +#: Client/core/CSettings.cpp:2219 +msgid "Vertical:" msgstr "" -#: Client/core/CKeyBinds.cpp:198 -msgid "Sprint" +#: Client/core/CSettings.cpp:2219 +msgid "Text-Align:" msgstr "" -#: Client/core/CKeyBinds.cpp:199 -msgid "Look behind" +#: Client/core/CSettings.cpp:2219 +msgid "X-Offset:" msgstr "" -#: Client/core/CKeyBinds.cpp:200 -msgid "Crouch" +#: Client/core/CSettings.cpp:2220 +msgid "Y-Offset:" msgstr "" -#: Client/core/CKeyBinds.cpp:201 -msgid "Action" +#: Client/core/CSettings.cpp:2226 +msgid "Position" msgstr "" -#: Client/core/CKeyBinds.cpp:202 -msgid "Walk" +#: Client/core/CSettings.cpp:2240 Client/core/CSettings.cpp:2268 +#: Client/core/CKeyBinds.cpp:191 +msgid "Left" msgstr "" -#: Client/core/CKeyBinds.cpp:203 -msgid "Vehicle fire" +#: Client/core/CSettings.cpp:2241 Client/core/CSettings.cpp:2255 +msgid "Center" msgstr "" -#: Client/core/CKeyBinds.cpp:204 -msgid "Vehicle secondary fire" +#: Client/core/CSettings.cpp:2242 Client/core/CSettings.cpp:2269 +#: Client/core/CKeyBinds.cpp:192 +msgid "Right" msgstr "" -#: Client/core/CKeyBinds.cpp:205 -msgid "Vehicle left" +#: Client/core/CSettings.cpp:2254 +msgid "Top" msgstr "" -#: Client/core/CKeyBinds.cpp:206 -msgid "Vehicle right" +#: Client/core/CSettings.cpp:2256 +msgid "Bottom" msgstr "" -#. 20 -#: Client/core/CKeyBinds.cpp:207 -msgid "Steer forwards/down" +#: Client/core/CSettings.cpp:2304 +msgid "Font" msgstr "" -#: Client/core/CKeyBinds.cpp:208 -msgid "Steer backwards/up" +#: Client/core/CSettings.cpp:2341 +msgid "Hide background when not typing" msgstr "" -#: Client/core/CKeyBinds.cpp:209 -msgid "Accelerate" +#: Client/core/CSettings.cpp:2346 +msgid "Nickname completion using the \"Tab\" key" msgstr "" -#: Client/core/CKeyBinds.cpp:210 -msgid "Brake/Reverse" +#: Client/core/CSettings.cpp:2351 +msgid "Allow server to flash the window" msgstr "" -#: Client/core/CKeyBinds.cpp:211 -msgid "Radio next" +#: Client/core/CSettings.cpp:2356 +msgid "Allow tray balloon notifications" msgstr "" -#: Client/core/CKeyBinds.cpp:212 -msgid "Radio previous" +#: Client/core/CSettings.cpp:2361 +msgid "Chat text black/white outline" msgstr "" -#: Client/core/CKeyBinds.cpp:213 -msgid "Radio user track skip" +#. Create a messagebox to notify the user +#. SString strText = SString::Printf ( "Press a key to bind to '%s'", pItemBind->GetText ().c_str () ); +#. Create a messagebox to notify the user +#. sSString strText = SString::Printf ( "Press a key to bind to '%s'", pItemBind->GetText ().c_str () ); +#: Client/core/CSettings.cpp:2610 Client/core/CSettings.cpp:2617 +msgid "Press a key to bind, or escape to clear" msgstr "" -#: Client/core/CKeyBinds.cpp:214 -msgid "Horn" +#: Client/core/CSettings.cpp:2611 +msgid "Binding a primary key" msgstr "" -#: Client/core/CKeyBinds.cpp:215 -msgid "Sub-mission" +#: Client/core/CSettings.cpp:2618 +msgid "Binding a secondary key" msgstr "" -#: Client/core/CKeyBinds.cpp:216 -msgid "Handbrake" +#: Client/core/CSettings.cpp:2694 +msgid "GTA GAME CONTROLS" msgstr "" -#. 30 -#: Client/core/CKeyBinds.cpp:217 -msgid "Vehicle look left" +#: Client/core/CSettings.cpp:2696 +msgid "MULTIPLAYER CONTROLS" msgstr "" -#: Client/core/CKeyBinds.cpp:218 -msgid "Vehicle look right" +#: Client/core/CSettings.cpp:2941 Client/core/CSettings.cpp:4764 +msgid "Your nickname contains invalid characters!" msgstr "" -#: Client/core/CKeyBinds.cpp:219 -msgid "Vehicle look behind" +#: Client/core/CSettings.cpp:3778 +msgid "Red:" msgstr "" -#: Client/core/CKeyBinds.cpp:220 -msgid "Vehicle mouse look" +#: Client/core/CSettings.cpp:3778 +msgid "Green:" msgstr "" -#: Client/core/CKeyBinds.cpp:221 -msgid "Special control left" +#: Client/core/CSettings.cpp:3778 +msgid "Blue:" msgstr "" -#: Client/core/CKeyBinds.cpp:222 -msgid "Special control right" +#: Client/core/CSettings.cpp:3778 +msgid "Transparency:" msgstr "" -#: Client/core/CKeyBinds.cpp:223 -msgid "Special control down" +#: Client/core/CSettings.cpp:3781 +msgid "Color" msgstr "" -#: Client/core/CKeyBinds.cpp:224 -msgid "Special control up" +#: Client/core/CSettings.cpp:3858 +msgid "Preview" msgstr "" -#: Client/core/CKeyBinds.cpp:225 -msgid "Aim weapon" +#: Client/core/CSettings.cpp:4166 +msgid "Please disconnect before changing language" msgstr "" -#: Client/core/CKeyBinds.cpp:226 -msgid "Conversation yes" +#: Client/core/CSettings.cpp:4194 +msgid "Please disconnect before changing skin" msgstr "" -#. 40 -#: Client/core/CKeyBinds.cpp:227 -msgid "Conversation no" +#: Client/core/CSettings.cpp:4482 +msgid "" +"Volmetric shadows can cause some systems to slow down.\n" +"\n" +"Are you sure you want to enable them?" msgstr "" -#: Client/core/CKeyBinds.cpp:228 -msgid "Group control forwards" +#: Client/core/CSettings.cpp:4486 +msgid "PERFORMANCE WARNING" msgstr "" -#: Client/core/CKeyBinds.cpp:229 -msgid "Group control backwards" +#: Client/core/CSettings.cpp:4506 +msgid "" +"Screen upload is required by some servers for anti-cheat purposes.\n" +"\n" +"(The chat box and GUI is excluded from the upload)\n" msgstr "" -#: Client/core/CQuestionBox.cpp:192 Shared/sdk/SharedUtil.Misc.hpp:688 -msgid "Do you want to see some on-line help about this problem ?" +#: Client/core/CSettings.cpp:4508 +msgid "SCREEN UPLOAD INFORMATION" msgstr "" -#: Client/core/CConnectManager.cpp:79 -msgid "Connecting failed. Invalid nick provided!" +#: Client/core/CSettings.cpp:4523 +msgid "" +"Some scripts may play sounds, such as radio, from the internet.\n" +"\n" +"Disabling this setting may decrease network\n" +"bandwidth consumption.\n" msgstr "" -#: Client/core/CConnectManager.cpp:110 -msgid "Connecting failed. Invalid host provided!" +#: Client/core/CSettings.cpp:4526 +msgid "EXTERNAL SOUNDS" msgstr "" -#: Client/core/CConnectManager.cpp:126 -#, c-format -msgid "Connecting to %s at port %u failed!" +#: Client/core/CSettings.cpp:4555 +msgid "" +"It seems that you have the Rich Presence connection option enabled.\n" +"Do you want to allow servers to share their data?\n" +"\n" +"This includes yours unique ID identifier." msgstr "" -#. Display the status box -#: Client/core/CConnectManager.cpp:147 -#, c-format -msgid "Connecting to %s:%u ..." +#: Client/core/CSettings.cpp:4560 +msgid "CONSENT TO ALLOW DATA SHARING" msgstr "" -#. Failed loading the mod -#: Client/core/CConnectManager.cpp:403 -#, c-format -msgid "No such mod installed (%s)" +#: Client/core/CSettings.cpp:4584 +msgid "" +"Some files in your GTA:SA data directory are customized.\n" +"MTA will only use these modified files if this check box is ticked.\n" +"\n" +"However, CUSTOMIZED GTA:SA FILES ARE BLOCKED BY MANY SERVERS\n" +"\n" +"Are you sure you want to use them?" msgstr "" -#: Client/core/CConnectManager.cpp:411 -msgid "Bad server response (2)" +#: Client/core/CSettings.cpp:4590 Client/core/CVersionUpdater.cpp:2081 +msgid "CUSTOMIZED GTA:SA FILES" msgstr "" -#: Client/core/CConnectManager.cpp:421 -msgid "Bad server response (1)" +#: Client/core/CSettings.cpp:4633 +msgid "" +"Enabling DPI awareness is an experimental feature and\n" +"we only recommend it when you play MTA:SA on a scaled monitor.\n" +"You may experience graphical issues if you enable this option.\n" +"\n" +"Are you sure you want to enable this option?" msgstr "" -#. Unknown command -#: Client/core/CCommands.cpp:216 -msgid "Unknown command or cvar: " +#: Client/core/CSettings.cpp:4639 +msgid "EXPERIMENTAL FEATURE" msgstr "" -#: Client/core/CCommandFuncs.cpp:24 -msgid "***[ COMMAND HELP ]***\n" +#: Client/core/CSettings.cpp:4782 +msgid "Please enter a nickname" msgstr "" -#: Client/core/CCommandFuncs.cpp:158 -#, c-format -msgid "* The time is %d:%02d:%02d" +#: Client/core/CSettings.cpp:4783 +msgid "" +"Please enter a nickname to be used ingame. \n" +"This will be your name when you connect to and play in a server" msgstr "" -#: Client/core/CCommandFuncs.cpp:242 -msgid "connect: Syntax is 'connect [ ]'" +#: Client/core/CSettings.cpp:4801 +msgid "Very experimental feature." msgstr "" -#: Client/core/CCommandFuncs.cpp:250 Client/core/CCommandFuncs.cpp:318 -msgid "connect: Bad port number" +#: Client/core/CSettings.cpp:4803 +msgid "Stops stalls with CJ variations (Uses 65MB more RAM)" msgstr "" -#: Client/core/CCommandFuncs.cpp:272 Client/core/CCommandFuncs.cpp:333 -#, c-format -msgid "connect: Connecting to %s:%u..." +#: Client/core/CSettings.cpp:4805 +msgid "Older routers may require a slower scan speed." msgstr "" -#: Client/core/CCommandFuncs.cpp:276 Client/core/CCommandFuncs.cpp:337 -#, c-format -msgid "connect: could not connect to %s:%u!" +#: Client/core/CSettings.cpp:4807 +msgid "Switch on to use only one connection when downloading." msgstr "" -#: Client/core/CCommandFuncs.cpp:281 -msgid "connect: Failed to unload current mod" +#: Client/core/CSettings.cpp:4809 +msgid "Tag network packets to help ISPs identify MTA traffic." msgstr "" -#: Client/core/CCommandFuncs.cpp:371 -msgid "Bound all controls from GTA" +#: Client/core/CSettings.cpp:4811 +msgid "Spinning circle animation at the bottom of the screen" msgstr "" -#: Client/core/CCommandFuncs.cpp:385 -msgid "Saved configuration file" +#: Client/core/CSettings.cpp:4813 +msgid "Select default always. (This setting is not saved)" msgstr "" -#. Print it -#: Client/core/CCommandFuncs.cpp:451 -#, c-format -msgid "* Your serial is: %s" +#: Client/core/CSettings.cpp:4815 +msgid "Maximum is usually best" msgstr "" -#: Client/core/CMainMenu.cpp:334 -msgid "" -"You are using a feature-branch build! This is a test build only which cannot " -"be used to connect to public servers!" +#: Client/core/CSettings.cpp:4817 Client/core/CSettings.cpp:4819 +msgid "Auto updater:" msgstr "" -#: Client/core/CMainMenu.cpp:353 -msgid "" -"MTA will not receive updates on XP/Vista after July 2019.\n" -"\n" -"Upgrade Windows to play on the latest servers." +#: Client/core/CSettings.cpp:4817 +msgid "Select default unless you like filling out bug reports." msgstr "" -#: Client/core/CMainMenu.cpp:1181 -msgid "" -"This will disconnect you from the current server.\n" -"\n" -"Are you sure you want to disconnect?" +#: Client/core/CSettings.cpp:4819 +msgid "Select default to automatically install important updates." msgstr "" -#: Client/core/CMainMenu.cpp:1185 -msgid "DISCONNECT WARNING" +#: Client/core/CSettings.cpp:4821 +msgid "16-bit color:" msgstr "" -#. TRANSLATORS: Replace with your language native name -#: Client/core/CLocalization.cpp:16 -msgid "English" +#: Client/core/CSettings.cpp:4821 +msgid "Enable 16 bit color modes - Requires MTA restart" msgstr "" -#. Even the default skin doesn't work, so give up -#: Client/core/CGUI.cpp:86 -msgid "" -"The skin you selected could not be loaded, and the default skin also could " -"not be loaded, please reinstall MTA." +#: Client/core/CSettings.cpp:4823 +msgid "Mouse fix:" msgstr "" -#: Client/core/CJoystickManager.cpp:1578 -msgid "Accelerate Axis" +#: Client/core/CSettings.cpp:4823 +msgid "Mouse movement fix - May need PC restart" msgstr "" -#: Client/core/CJoystickManager.cpp:1580 -msgid "Brake Axis" +#: Client/core/CCore.cpp:811 Client/loader/CInstallManager.cpp:1057 +#, c-format +msgid "MTA:SA cannot continue because drive %s does not have enough space." msgstr "" -#. Create window (with frame) if it will fit inside the screen resolution -#: Client/core/CSettings.cpp:84 -msgid "SETTINGS" +#: Client/core/CCore.cpp:813 Shared/mods/deathmatch/logic/Utils.cpp:129 +msgid "Fatal error" msgstr "" -#: Client/core/CSettings.cpp:116 -msgid "Multiplayer" +#: Client/core/CCore.cpp:938 +msgid "TO FIX, REMOVE THIS FILE:" msgstr "" -#: Client/core/CSettings.cpp:117 -msgid "Video" +#: Client/core/CCore.cpp:970 +#, c-format +msgid "%s module is incorrect!" msgstr "" -#: Client/core/CSettings.cpp:118 -msgid "Audio" +#: Client/core/CCore.cpp:1275 +msgid "Error executing URL" msgstr "" -#: Client/core/CSettings.cpp:119 -msgid "Binds" +#: Client/core/CCore.cpp:1287 +#, c-format +msgid "Error running mod specified in command line ('%s')" msgstr "" -#: Client/core/CSettings.cpp:120 -msgid "Controls" +#. m_pCommands->Add ( "e", CCommandFuncs::Editor ); +#. m_pCommands->Add ( "clear", CCommandFuncs::Clear ); +#: Client/core/CCore.cpp:1389 +msgid "this help screen" msgstr "" -#: Client/core/CSettings.cpp:121 -msgid "Interface" +#: Client/core/CCore.cpp:1390 Client/core/CCore.cpp:1391 +msgid "exits the application" msgstr "" -#: Client/core/CSettings.cpp:122 -msgid "Web Browser" +#: Client/core/CCore.cpp:1392 +msgid "shows the version" msgstr "" -#: Client/core/CSettings.cpp:123 -msgid "Advanced" +#: Client/core/CCore.cpp:1393 +msgid "shows the time" msgstr "" -#: Client/core/CSettings.cpp:147 Client/core/CSettings.cpp:338 -#: Client/core/CSettings.cpp:605 Client/core/CSettings.cpp:877 -msgid "Load defaults" +#: Client/core/CCore.cpp:1394 +msgid "shows the hud" msgstr "" -#. * -#. * Controls tab -#. * -#: Client/core/CSettings.cpp:157 Client/core/CSettings.cpp:181 -msgid "Mouse sensitivity:" +#: Client/core/CCore.cpp:1395 +msgid "shows all the binds" msgstr "" -#. VerticalAimSensitivity -#: Client/core/CSettings.cpp:157 Client/core/CSettings.cpp:199 -msgid "Vertical aim sensitivity:" +#: Client/core/CCore.cpp:1396 +msgid "shows your serial" msgstr "" -#. Mouse Options -#: Client/core/CSettings.cpp:160 -msgid "Mouse options" +#: Client/core/CCore.cpp:1405 +msgid "connects to a server (host port nick pass)" msgstr "" -#: Client/core/CSettings.cpp:167 -msgid "Invert mouse vertically" +#: Client/core/CCore.cpp:1406 +msgid "connects to a previous server" msgstr "" -#: Client/core/CSettings.cpp:171 -msgid "Steer with mouse" +#: Client/core/CCore.cpp:1407 +msgid "binds a key (key control)" msgstr "" -#: Client/core/CSettings.cpp:175 -msgid "Fly with mouse" +#: Client/core/CCore.cpp:1408 +msgid "unbinds a key (key)" msgstr "" -#. Joypad options -#: Client/core/CSettings.cpp:217 -msgid "Joypad options" +#: Client/core/CCore.cpp:1409 +msgid "copies the default gta controls" msgstr "" -#: Client/core/CSettings.cpp:230 -msgid "Standard controls (Mouse + Keyboard)" +#: Client/core/CCore.cpp:1410 +msgid "outputs a screenshot" msgstr "" -#: Client/core/CSettings.cpp:237 -msgid "Classic controls (Joypad)" +#: Client/core/CCore.cpp:1411 +msgid "immediately saves the config" msgstr "" -#: Client/core/CSettings.cpp:274 -msgid "Dead Zone" +#: Client/core/CCore.cpp:1413 +msgid "clears the debug view" msgstr "" -#: Client/core/CSettings.cpp:279 -msgid "Saturation" +#: Client/core/CCore.cpp:1414 +msgid "scrolls the chatbox upwards" msgstr "" -#: Client/core/CSettings.cpp:285 -msgid "Use the 'Binds' tab for joypad buttons." +#: Client/core/CCore.cpp:1415 +msgid "scrolls the chatbox downwards" msgstr "" -#: Client/core/CSettings.cpp:324 -msgid "Left Stick" +#: Client/core/CCore.cpp:1416 +msgid "scrolls the debug view upwards" msgstr "" -#: Client/core/CSettings.cpp:330 -msgid "Right Stick" +#: Client/core/CCore.cpp:1417 +msgid "scrolls the debug view downwards" msgstr "" -#: Client/core/CSettings.cpp:345 -msgid "DESCRIPTION" +#: Client/core/CCore.cpp:1420 +msgid "shows the memory statistics" msgstr "" -#: Client/core/CSettings.cpp:346 -msgid "KEY" +#: Client/core/CCore.cpp:1421 +msgid "shows the frame timing graph" msgstr "" -#: Client/core/CSettings.cpp:348 -msgid "ALT. KEY" +#: Client/core/CCore.cpp:1425 +msgid "for developers: reload news" msgstr "" -#. * -#. * Multiplayer tab -#. * -#: Client/core/CSettings.cpp:353 Client/core/CSettings.cpp:356 -msgid "Nick:" +#: Client/core/CConnectManager.cpp:79 +msgid "Connecting failed. Invalid nick provided!" msgstr "" -#: Client/core/CSettings.cpp:366 -msgid "Save server passwords" +#: Client/core/CConnectManager.cpp:110 +msgid "Connecting failed. Invalid host provided!" msgstr "" -#: Client/core/CSettings.cpp:371 -msgid "Auto-refresh server browser" +#: Client/core/CConnectManager.cpp:126 +#, c-format +msgid "Connecting to %s at port %u failed!" msgstr "" -#: Client/core/CSettings.cpp:376 -msgid "Allow screen upload" +#. Display the status box +#: Client/core/CConnectManager.cpp:147 +#, c-format +msgid "Connecting to %s:%u ..." msgstr "" -#: Client/core/CSettings.cpp:381 -msgid "Allow external sounds" +#. Failed loading the mod +#: Client/core/CConnectManager.cpp:403 +#, c-format +msgid "No such mod installed (%s)" msgstr "" -#: Client/core/CSettings.cpp:386 -msgid "Always show download window" +#: Client/core/CConnectManager.cpp:411 +msgid "Bad server response (2)" msgstr "" -#: Client/core/CSettings.cpp:391 -msgid "Allow connecting with Discord Rich Presence" +#: Client/core/CConnectManager.cpp:421 +msgid "Bad server response (1)" msgstr "" -#: Client/core/CSettings.cpp:396 -msgid "Use customized GTA:SA files" +#: Client/core/CKeyBinds.cpp:186 +msgid "Fire" msgstr "" -#: Client/core/CSettings.cpp:401 -msgid "Map rendering options" +#: Client/core/CKeyBinds.cpp:187 +msgid "Next weapon" msgstr "" -#: Client/core/CSettings.cpp:407 Client/core/CSettings.cpp:616 -msgid "Opacity:" +#: Client/core/CKeyBinds.cpp:188 +msgid "Previous weapon" msgstr "" -#. * -#. * Audio tab -#. * -#: Client/core/CSettings.cpp:427 Client/core/CSettings.cpp:436 -msgid "Master volume:" +#: Client/core/CKeyBinds.cpp:189 +msgid "Forwards" msgstr "" -#: Client/core/CSettings.cpp:427 Client/core/CSettings.cpp:455 -msgid "Radio volume:" +#: Client/core/CKeyBinds.cpp:190 +msgid "Backwards" msgstr "" -#: Client/core/CSettings.cpp:427 Client/core/CSettings.cpp:474 -msgid "SFX volume:" +#: Client/core/CKeyBinds.cpp:193 +msgid "Zoom in" msgstr "" -#: Client/core/CSettings.cpp:427 Client/core/CSettings.cpp:493 -msgid "MTA volume:" +#: Client/core/CKeyBinds.cpp:194 +msgid "Zoom out" msgstr "" -#: Client/core/CSettings.cpp:428 Client/core/CSettings.cpp:512 -msgid "Voice volume:" +#: Client/core/CKeyBinds.cpp:195 +msgid "Enter/Exit" msgstr "" -#: Client/core/CSettings.cpp:428 Client/core/CSettings.cpp:553 -msgid "Play mode:" +#: Client/core/CKeyBinds.cpp:196 +msgid "Change camera" msgstr "" -#: Client/core/CSettings.cpp:531 -msgid "Radio options" +#. 10 +#: Client/core/CKeyBinds.cpp:197 +msgid "Jump" msgstr "" -#: Client/core/CSettings.cpp:537 -msgid "Radio Equalizer" +#: Client/core/CKeyBinds.cpp:198 +msgid "Sprint" msgstr "" -#: Client/core/CSettings.cpp:542 -msgid "Radio Auto-tune" +#: Client/core/CKeyBinds.cpp:199 +msgid "Look behind" msgstr "" -#: Client/core/CSettings.cpp:547 -msgid "Usertrack options" +#: Client/core/CKeyBinds.cpp:200 +msgid "Crouch" msgstr "" -#: Client/core/CSettings.cpp:561 Client/core/CSettings.cpp:3069 -msgid "Radio" +#: Client/core/CKeyBinds.cpp:201 +msgid "Action" msgstr "" -#: Client/core/CSettings.cpp:562 Client/core/CSettings.cpp:3071 -msgid "Random" +#: Client/core/CKeyBinds.cpp:202 +msgid "Walk" msgstr "" -#: Client/core/CSettings.cpp:563 Client/core/CSettings.cpp:3073 -msgid "Sequential" +#: Client/core/CKeyBinds.cpp:203 +msgid "Vehicle fire" msgstr "" -#: Client/core/CSettings.cpp:566 -msgid "Automatic Media Scan" +#: Client/core/CKeyBinds.cpp:204 +msgid "Vehicle secondary fire" msgstr "" -#: Client/core/CSettings.cpp:573 -msgid "Mute options" +#: Client/core/CKeyBinds.cpp:205 +msgid "Vehicle left" msgstr "" -#: Client/core/CSettings.cpp:579 -msgid "Mute All sounds when minimized" +#: Client/core/CKeyBinds.cpp:206 +msgid "Vehicle right" msgstr "" -#: Client/core/CSettings.cpp:584 -msgid "Mute Radio sounds when minimized" +#. 20 +#: Client/core/CKeyBinds.cpp:207 +msgid "Steer forwards/down" msgstr "" -#: Client/core/CSettings.cpp:589 -msgid "Mute SFX sounds when minimized" +#: Client/core/CKeyBinds.cpp:208 +msgid "Steer backwards/up" msgstr "" -#: Client/core/CSettings.cpp:594 -msgid "Mute MTA sounds when minimized" +#: Client/core/CKeyBinds.cpp:209 +msgid "Accelerate" msgstr "" -#: Client/core/CSettings.cpp:599 -msgid "Mute Voice sounds when minimized" +#: Client/core/CKeyBinds.cpp:210 +msgid "Brake/Reverse" msgstr "" -#. * -#. * Video tab -#. * -#: Client/core/CSettings.cpp:615 Client/core/CSettings.cpp:624 -msgid "Resolution:" +#: Client/core/CKeyBinds.cpp:211 +msgid "Radio next" msgstr "" -#: Client/core/CSettings.cpp:615 Client/core/CSettings.cpp:671 -msgid "FOV:" +#: Client/core/CKeyBinds.cpp:212 +msgid "Radio previous" msgstr "" -#: Client/core/CSettings.cpp:615 Client/core/CSettings.cpp:687 -msgid "Draw Distance:" +#: Client/core/CKeyBinds.cpp:213 +msgid "Radio user track skip" msgstr "" -#: Client/core/CSettings.cpp:615 Client/core/CSettings.cpp:705 -msgid "Brightness:" +#: Client/core/CKeyBinds.cpp:214 +msgid "Horn" msgstr "" -#: Client/core/CSettings.cpp:615 Client/core/CSettings.cpp:723 -msgid "FX Quality:" +#: Client/core/CKeyBinds.cpp:215 +msgid "Sub-mission" msgstr "" -#: Client/core/CSettings.cpp:616 Client/core/CSettings.cpp:737 -msgid "Anisotropic filtering:" +#: Client/core/CKeyBinds.cpp:216 +msgid "Handbrake" msgstr "" -#: Client/core/CSettings.cpp:616 Client/core/CSettings.cpp:764 -msgid "Anti-aliasing:" +#. 30 +#: Client/core/CKeyBinds.cpp:217 +msgid "Vehicle look left" msgstr "" -#: Client/core/CSettings.cpp:616 Client/core/CSettings.cpp:778 -msgid "Aspect Ratio:" +#: Client/core/CKeyBinds.cpp:218 +msgid "Vehicle look right" msgstr "" -#: Client/core/CSettings.cpp:636 -msgid "Windowed" +#: Client/core/CKeyBinds.cpp:219 +msgid "Vehicle look behind" msgstr "" -#: Client/core/CSettings.cpp:642 -msgid "DPI aware" +#: Client/core/CKeyBinds.cpp:220 +msgid "Vehicle mouse look" msgstr "" -#: Client/core/CSettings.cpp:657 Client/core/CSettings.cpp:1601 -msgid "Standard" +#: Client/core/CKeyBinds.cpp:221 +msgid "Special control left" msgstr "" -#: Client/core/CSettings.cpp:659 Client/core/CSettings.cpp:1605 -msgid "Borderless keep res" +#: Client/core/CKeyBinds.cpp:222 +msgid "Special control right" msgstr "" -#: Client/core/CSettings.cpp:663 -msgid "Mip Mapping" +#: Client/core/CKeyBinds.cpp:223 +msgid "Special control down" msgstr "" -#: Client/core/CSettings.cpp:731 Client/core/CSettings.cpp:1505 -msgid "Low" +#: Client/core/CKeyBinds.cpp:224 +msgid "Special control up" msgstr "" -#: Client/core/CSettings.cpp:732 Client/core/CSettings.cpp:1507 -msgid "Medium" +#: Client/core/CKeyBinds.cpp:225 +msgid "Aim weapon" msgstr "" -#: Client/core/CSettings.cpp:733 Client/core/CSettings.cpp:1074 -#: Client/core/CSettings.cpp:1509 Client/core/CSettings.cpp:3127 -msgid "High" +#: Client/core/CKeyBinds.cpp:226 +msgid "Conversation yes" msgstr "" -#: Client/core/CSettings.cpp:734 Client/core/CSettings.cpp:1511 -msgid "Very high" +#. 40 +#: Client/core/CKeyBinds.cpp:227 +msgid "Conversation no" msgstr "" -#: Client/core/CSettings.cpp:749 Client/core/CSettings.cpp:772 -#: Client/core/CSettings.cpp:1005 Client/core/CSettings.cpp:1059 -#: Client/core/CSettings.cpp:1189 Client/core/CSettings.cpp:1515 -#: Client/core/CSettings.cpp:3134 Client/core/CSettings.cpp:3166 -#: Client/core/CSettings.cpp:3188 Client/core/CSettings.cpp:4216 -msgid "Off" +#: Client/core/CKeyBinds.cpp:228 +msgid "Group control forwards" msgstr "" -#: Client/core/CSettings.cpp:773 Client/core/CSettings.cpp:1517 -msgid "1x" +#: Client/core/CKeyBinds.cpp:229 +msgid "Group control backwards" msgstr "" -#: Client/core/CSettings.cpp:774 Client/core/CSettings.cpp:1519 -msgid "2x" +#. Even the default skin doesn't work, so give up +#: Client/core/CGUI.cpp:86 +msgid "" +"The skin you selected could not be loaded, and the default skin also could " +"not be loaded, please reinstall MTA." msgstr "" -#: Client/core/CSettings.cpp:775 Client/core/CSettings.cpp:1521 -msgid "3x" +#. Create the window +#: Client/core/CNewsBrowser.cpp:153 +msgid "NEWS" msgstr "" -#: Client/core/CSettings.cpp:788 Client/core/CSettings.cpp:1007 -#: Client/core/CSettings.cpp:1527 Client/core/CSettings.cpp:3136 -msgid "Auto" -msgstr "" +#. News link +#: Client/core/CNewsBrowser.cpp:171 Client/core/CNewsBrowser.cpp:172 +msgid "Visit latest news article" +msgstr "" -#: Client/core/CSettings.cpp:789 Client/core/CSettings.cpp:1529 -msgid "4:3" +#: Client/core/CCommandFuncs.cpp:24 +msgid "***[ COMMAND HELP ]***\n" msgstr "" -#: Client/core/CSettings.cpp:790 Client/core/CSettings.cpp:1531 -msgid "16:10" +#: Client/core/CCommandFuncs.cpp:158 +#, c-format +msgid "* The time is %d:%02d:%02d" msgstr "" -#: Client/core/CSettings.cpp:791 Client/core/CSettings.cpp:1533 -msgid "16:9" +#: Client/core/CCommandFuncs.cpp:242 +msgid "connect: Syntax is 'connect [ ]'" msgstr "" -#: Client/core/CSettings.cpp:794 -msgid "HUD Match Aspect Ratio" +#: Client/core/CCommandFuncs.cpp:250 Client/core/CCommandFuncs.cpp:318 +msgid "connect: Bad port number" msgstr "" -#: Client/core/CSettings.cpp:800 -msgid "Volumetric Shadows" +#: Client/core/CCommandFuncs.cpp:272 Client/core/CCommandFuncs.cpp:333 +#, c-format +msgid "connect: Connecting to %s:%u..." msgstr "" -#: Client/core/CSettings.cpp:804 -msgid "Grass effect" +#: Client/core/CCommandFuncs.cpp:276 Client/core/CCommandFuncs.cpp:337 +#, c-format +msgid "connect: could not connect to %s:%u!" msgstr "" -#: Client/core/CSettings.cpp:808 -msgid "Heat haze" +#: Client/core/CCommandFuncs.cpp:281 +msgid "connect: Failed to unload current mod" msgstr "" -#: Client/core/CSettings.cpp:812 -msgid "Tyre Smoke etc" +#: Client/core/CCommandFuncs.cpp:371 +msgid "Bound all controls from GTA" msgstr "" -#: Client/core/CSettings.cpp:816 -msgid "Dynamic ped shadows" +#: Client/core/CCommandFuncs.cpp:385 +msgid "Saved configuration file" msgstr "" -#: Client/core/CSettings.cpp:820 -msgid "Motion blur" +#. Print it +#: Client/core/CCommandFuncs.cpp:451 +#, c-format +msgid "* Your serial is: %s" msgstr "" -#: Client/core/CSettings.cpp:825 -msgid "Full Screen Minimize" +#. Unknown command +#: Client/core/CCommands.cpp:223 +msgid "Unknown command or cvar: " msgstr "" -#: Client/core/CSettings.cpp:837 -msgid "Enable Device Selection Dialog" +#: Client/core/CQuestionBox.cpp:192 Shared/sdk/SharedUtil.Misc.hpp:688 +msgid "Do you want to see some on-line help about this problem ?" msgstr "" -#: Client/core/CSettings.cpp:849 -msgid "Show unsafe resolutions" +#: Client/core/CCredits.cpp:34 +msgid "Programming" msgstr "" -#: Client/core/CSettings.cpp:861 -msgid "Render vehicles always in high detail" +#: Client/core/CCredits.cpp:63 +msgid "Contributors" msgstr "" -#: Client/core/CSettings.cpp:865 -msgid "Render peds always in high detail" +#: Client/core/CCredits.cpp:84 +msgid "Game Design / Scripting" msgstr "" -#: Client/core/CSettings.cpp:869 -msgid "Corona rain reflections" +#: Client/core/CCredits.cpp:104 +msgid "Language Localization" msgstr "" -#: Client/core/CSettings.cpp:898 -msgid "Enable remote websites" +#: Client/core/CCredits.cpp:110 +msgid "Patch contributors" msgstr "" -#: Client/core/CSettings.cpp:903 -msgid "Enable Javascript on remote websites" +#: Client/core/CCredits.cpp:234 +msgid "Special Thanks" msgstr "" -#: Client/core/CSettings.cpp:908 -msgid "Custom blacklist" +#: Client/core/CCredits.cpp:265 +msgid "" +"This software and project makes use of the following libraries and software:" msgstr "" -#: Client/core/CSettings.cpp:919 Client/core/CSettings.cpp:954 -msgid "Enter a domain e.g. google.com" +#: Client/core/CJoystickManager.cpp:1578 +msgid "Accelerate Axis" msgstr "" -#: Client/core/CSettings.cpp:927 -msgid "Block" +#: Client/core/CJoystickManager.cpp:1580 +msgid "Brake Axis" msgstr "" -#: Client/core/CSettings.cpp:935 Client/core/CSettings.cpp:970 -msgid "Domain" +#. TRANSLATORS: Replace with your language native name +#: Client/core/CLocalization.cpp:16 +msgid "English" msgstr "" -#: Client/core/CSettings.cpp:937 Client/core/CSettings.cpp:972 -msgid "Remove domain" +#: Client/core/CMainMenu.cpp:333 +msgid "" +"You are using a feature-branch build! This is a test build only which cannot " +"be used to connect to public servers!" msgstr "" -#. Reset vecTemp -#: Client/core/CSettings.cpp:943 -msgid "Custom whitelist" +#: Client/core/CMainMenu.cpp:352 +msgid "" +"MTA will not receive updates on XP/Vista after July 2019.\n" +"\n" +"Upgrade Windows to play on the latest servers." msgstr "" -#: Client/core/CSettings.cpp:962 Client/cefweb/CWebsiteRequests.cpp:51 -msgid "Allow" +#: Client/core/CMainMenu.cpp:1193 +msgid "" +"This will disconnect you from the current server.\n" +"\n" +"Are you sure you want to disconnect?" msgstr "" -#. Misc section label -#: Client/core/CSettings.cpp:985 -msgid "Misc" +#: Client/core/CMainMenu.cpp:1197 +msgid "DISCONNECT WARNING" msgstr "" -#. Fast clothes loading -#: Client/core/CSettings.cpp:991 Client/core/CSettings.cpp:998 -#: Client/core/CSettings.cpp:4757 -msgid "Fast CJ clothes loading:" +#: Client/core/CVersionUpdater.cpp:626 +msgid "Busy" msgstr "" -#. Browser scan speed -#: Client/core/CSettings.cpp:991 Client/core/CSettings.cpp:1012 -#: Client/core/CSettings.cpp:4759 -msgid "Browser speed:" +#: Client/core/CVersionUpdater.cpp:626 +msgid "Can't check for updates right now" msgstr "" -#. Single download -#: Client/core/CSettings.cpp:991 Client/core/CSettings.cpp:1026 -#: Client/core/CSettings.cpp:4761 -msgid "Single connection:" +#: Client/core/CVersionUpdater.cpp:1567 Client/core/CVersionUpdater.cpp:1587 +#: Client/core/CVersionUpdater.cpp:1605 +#, c-format +msgid "MTA:SA %s required" msgstr "" -#. Packet tag -#: Client/core/CSettings.cpp:991 Client/core/CSettings.cpp:1039 -#: Client/core/CSettings.cpp:4763 -msgid "Packet tag:" +#: Client/core/CVersionUpdater.cpp:1568 +#, c-format +msgid "" +"An updated version of MTA:SA %s is required to join the selected server.\n" +"\n" +"Do you want to download and install MTA:SA %s ?" msgstr "" -#. Progress animation -#: Client/core/CSettings.cpp:992 Client/core/CSettings.cpp:1052 -#: Client/core/CSettings.cpp:4765 -msgid "Progress animation:" +#: Client/core/CVersionUpdater.cpp:1588 +#, c-format +msgid "Do you want to launch MTA:SA %s and connect to this server ?" msgstr "" -#. Process priority -#: Client/core/CSettings.cpp:992 Client/core/CSettings.cpp:1065 -#: Client/core/CSettings.cpp:4755 -msgid "Process priority:" +#: Client/core/CVersionUpdater.cpp:1606 +msgid "" +"It is not possible to connect at this time.\n" +"\n" +"Please try later." msgstr "" -#. Debug setting -#: Client/core/CSettings.cpp:992 Client/core/CSettings.cpp:1079 -#: Client/core/CSettings.cpp:4767 -msgid "Debug setting:" +#: Client/core/CVersionUpdater.cpp:1788 +msgid "Connecting" msgstr "" -#. Streaming memory -#: Client/core/CSettings.cpp:993 Client/core/CSettings.cpp:1102 -#: Client/core/CSettings.cpp:4769 -msgid "Streaming memory:" +#: Client/core/CVersionUpdater.cpp:1789 Client/core/CVersionUpdater.cpp:1805 +msgid "Please wait..." msgstr "" -#. Update build type -#: Client/core/CSettings.cpp:993 Client/core/CSettings.cpp:1203 -msgid "Update build type:" +#: Client/core/CVersionUpdater.cpp:1804 +msgid "CHECKING" msgstr "" -#. UpdateAutoInstall -#: Client/core/CSettings.cpp:993 Client/core/CSettings.cpp:1182 -msgid "Install important updates:" +#: Client/core/CVersionUpdater.cpp:1821 Client/core/CVersionUpdater.cpp:1914 +msgid "UPDATE CHECK" msgstr "" -#: Client/core/CSettings.cpp:1006 Client/core/CSettings.cpp:1034 -#: Client/core/CSettings.cpp:1047 Client/core/CSettings.cpp:3138 -#: Client/core/CSettings.cpp:3154 Client/core/CSettings.cpp:3161 -msgid "On" +#: Client/core/CVersionUpdater.cpp:1822 +msgid "No update needed" msgstr "" -#: Client/core/CSettings.cpp:1019 Client/core/CSettings.cpp:3143 -msgid "Very slow" +#: Client/core/CVersionUpdater.cpp:1839 +msgid "DOWNLOADING" msgstr "" -#: Client/core/CSettings.cpp:1020 Client/core/CSettings.cpp:1033 -#: Client/core/CSettings.cpp:1046 Client/core/CSettings.cpp:1060 -#: Client/core/CSettings.cpp:1086 Client/core/CSettings.cpp:1098 -#: Client/core/CSettings.cpp:1190 Client/core/CSettings.cpp:1210 -#: Client/core/CSettings.cpp:3145 Client/core/CSettings.cpp:3152 -#: Client/core/CSettings.cpp:3159 Client/core/CSettings.cpp:3168 -#: Client/core/CSettings.cpp:3181 -msgid "Default" +#: Client/core/CVersionUpdater.cpp:1840 +msgid "waiting..." msgstr "" -#: Client/core/CSettings.cpp:1021 Client/core/CSettings.cpp:3147 -msgid "Fast" +#: Client/core/CVersionUpdater.cpp:1856 +msgid "MANDATORY UPDATE" msgstr "" -#: Client/core/CSettings.cpp:1072 Client/core/CSettings.cpp:3123 -msgid "Normal" +#: Client/core/CVersionUpdater.cpp:1857 +msgid "" +"To join this server, you must update MTA.\n" +"\n" +" Do you want to update now ?" msgstr "" -#: Client/core/CSettings.cpp:1073 Client/core/CSettings.cpp:3125 -msgid "Above normal" +#: Client/core/CVersionUpdater.cpp:1875 +msgid "OPTIONAL UPDATE" msgstr "" -#: Client/core/CSettings.cpp:1109 -msgid "Min" +#: Client/core/CVersionUpdater.cpp:1876 +msgid "" +"Server says an update is recommended, but not essential.\n" +"\n" +" Do you want to update now ?" msgstr "" -#: Client/core/CSettings.cpp:1122 -msgid "Max" +#: Client/core/CVersionUpdater.cpp:1915 +msgid "" +"An update is currently not available.\n" +"\n" +"Please check www.mtasa.com" msgstr "" -#. Windows 8 compatibility -#: Client/core/CSettings.cpp:1129 -msgid "Windows 8 compatibility:" +#: Client/core/CVersionUpdater.cpp:1936 Client/core/CVersionUpdater.cpp:2118 +msgid "ERROR SAVING" msgstr "" -#: Client/core/CSettings.cpp:1133 -msgid "16-bit color" +#: Client/core/CVersionUpdater.cpp:1937 Client/core/CVersionUpdater.cpp:2119 +msgid "Unable to create the file." msgstr "" -#: Client/core/CSettings.cpp:1138 -msgid "Mouse fix" +#: Client/core/CVersionUpdater.cpp:1945 Client/core/CVersionUpdater.cpp:1954 +#: Client/core/CVersionUpdater.cpp:2127 Client/core/CVersionUpdater.cpp:2136 +msgid "ERROR DOWNLOADING" msgstr "" -#. Cache path info -#: Client/core/CSettings.cpp:1156 -msgid "Client resource files:" +#: Client/core/CVersionUpdater.cpp:1946 Client/core/CVersionUpdater.cpp:2128 +msgid "The downloaded file appears to be incorrect." msgstr "" -#: Client/core/CSettings.cpp:1160 -msgid "Show in Explorer" +#: Client/core/CVersionUpdater.cpp:1955 Client/core/CVersionUpdater.cpp:2137 +msgid "For some reason." msgstr "" -#. Auto updater section label -#: Client/core/CSettings.cpp:1175 Client/core/CSettings.cpp:1178 -msgid "Auto updater" +#: Client/core/CVersionUpdater.cpp:1966 Client/core/CVersionUpdater.cpp:2150 +msgid "DOWNLOAD COMPLETE" msgstr "" -#. Check for updates -#: Client/core/CSettings.cpp:1216 -msgid "Check for update now" +#: Client/core/CVersionUpdater.cpp:1990 +msgid " - Unknown problem in _DialogUpdateResult" msgstr "" -#: Client/core/CSettings.cpp:1370 -msgid "Some settings will be changed when you next start MTA" +#: Client/core/CVersionUpdater.cpp:2088 Client/core/CVersionUpdater.cpp:2098 +msgid "Ok" +msgstr "" + +#: Client/core/CVersionUpdater.cpp:2096 +msgid "ERROR" msgstr "" -#: Client/core/CSettings.cpp:1371 +#: Client/core/CVersionUpdater.cpp:2097 msgid "" +"Some MTA:SA data files are missing.\n" "\n" "\n" -"Do you want to restart now?" -msgstr "" - -#: Client/core/CSettings.cpp:1374 -msgid "RESTART REQUIRED" +"Please reinstall MTA:SA" msgstr "" -#: Client/core/CSettings.cpp:1394 -msgid "Some settings will be changed when you disconnect the current server" +#: Client/core/CVersionUpdater.cpp:2774 +#, c-format +msgid "%3d %% completed" msgstr "" -#: Client/core/CSettings.cpp:1395 +#: Client/core/CVersionUpdater.cpp:2777 +#, c-format msgid "" "\n" "\n" -"Do you want to disconnect now?" +"Waiting for response - %-3d" msgstr "" -#: Client/core/CSettings.cpp:1398 -msgid "DISCONNECT REQUIRED" +#. Create window +#: Client/core/CConsole.cpp:417 +msgid "CONSOLE" msgstr "" -#. Update the joystick name -#: Client/core/CSettings.cpp:1725 -msgid "Joypad not detected - Check connections and restart game" +#: Client/core/ServerBrowser/CServerList.cpp:25 +msgid "Idle" msgstr "" -#: Client/core/CSettings.cpp:1920 -msgid "Binding axis" -msgstr "" +#: Client/core/ServerBrowser/CServerList.cpp:150 +msgid "player" +msgid_plural "players" +msgstr[0] "" +msgstr[1] "" -#: Client/core/CSettings.cpp:1920 -msgid "Move an axis to bind, or escape to clear" +#: Client/core/ServerBrowser/CServerList.cpp:151 +msgid "on" msgstr "" -#: Client/core/CSettings.cpp:1997 -msgid "Language:" -msgstr "" +#: Client/core/ServerBrowser/CServerList.cpp:154 +msgid "server" +msgid_plural "servers" +msgstr[0] "" +msgstr[1] "" -#: Client/core/CSettings.cpp:1997 -msgid "Skin:" +#. We are polling for the master server list (first pass) +#: Client/core/ServerBrowser/CServerList.cpp:238 +#, c-format +msgid "Requesting master server list (%lu ms elapsed)" msgstr "" -#: Client/core/CSettings.cpp:1997 -msgid "Presets:" +#. Abort +#: Client/core/ServerBrowser/CServerList.cpp:254 +msgid "Master server list could not be parsed." msgstr "" -#: Client/core/CSettings.cpp:2046 -msgid "Chat" +#. Abort +#: Client/core/ServerBrowser/CServerList.cpp:264 +msgid "Master server list could not be retrieved." msgstr "" -#: Client/core/CSettings.cpp:2063 -msgid "Load" +#: Client/core/ServerBrowser/CServerList.cpp:274 +msgid "(Backup server list)" msgstr "" -#: Client/core/CSettings.cpp:2075 -msgid "Colors" +#: Client/core/ServerBrowser/CServerList.cpp:326 +msgid "Cannot bind LAN-broadcast socket" msgstr "" -#: Client/core/CSettings.cpp:2076 -msgid "Layout" +#: Client/core/ServerBrowser/CServerList.cpp:345 +msgid "Attempting to discover LAN servers" msgstr "" -#: Client/core/CSettings.cpp:2077 Client/core/CSettings.cpp:2323 -msgid "Options" +#. Create queue window +#: Client/core/ServerBrowser/CServerInfo.cpp:32 +#: Client/core/ServerBrowser/CServerInfo.cpp:302 +msgid "SERVER IS FULL" msgstr "" -#: Client/core/CSettings.cpp:2083 -msgid "Chat Background" +#. Determine our label draw position for L10n +#. Start position +#. Server Name +#: Client/core/ServerBrowser/CServerInfo.cpp:44 +#: Client/core/ServerBrowser/CServerInfo.cpp:53 +msgid "Name:" msgstr "" -#: Client/core/CSettings.cpp:2083 -msgid "Chat Text" +#. Server IP +#: Client/core/ServerBrowser/CServerInfo.cpp:44 +#: Client/core/ServerBrowser/CServerInfo.cpp:64 +msgid "Server Address:" msgstr "" -#: Client/core/CSettings.cpp:2083 -msgid "Input Background" +#. Gamemode +#: Client/core/ServerBrowser/CServerInfo.cpp:44 +#: Client/core/ServerBrowser/CServerInfo.cpp:75 +msgid "Gamemode:" msgstr "" -#: Client/core/CSettings.cpp:2083 -msgid "Input Text" +#. Map +#: Client/core/ServerBrowser/CServerInfo.cpp:44 +#: Client/core/ServerBrowser/CServerInfo.cpp:86 +msgid "Map:" msgstr "" -#: Client/core/CSettings.cpp:2106 -msgid "Lines:" +#. Players +#: Client/core/ServerBrowser/CServerInfo.cpp:45 +#: Client/core/ServerBrowser/CServerInfo.cpp:97 +msgid "Players:" msgstr "" -#: Client/core/CSettings.cpp:2106 -msgid "Scale:" +#. Passworded +#: Client/core/ServerBrowser/CServerInfo.cpp:45 +#: Client/core/ServerBrowser/CServerInfo.cpp:108 +msgid "Passworded:" msgstr "" -#: Client/core/CSettings.cpp:2106 -msgid "Width:" +#. Latency +#: Client/core/ServerBrowser/CServerInfo.cpp:45 +#: Client/core/ServerBrowser/CServerInfo.cpp:119 +msgid "Latency:" msgstr "" -#: Client/core/CSettings.cpp:2109 -msgid "Size" +#. Column for player names +#. Player List Columns +#: Client/core/ServerBrowser/CServerInfo.cpp:138 +#: Client/core/ServerBrowser/CServerBrowser.cpp:478 +msgid "Player list" msgstr "" -#: Client/core/CSettings.cpp:2158 -msgid "after" +#. Close button +#: Client/core/ServerBrowser/CServerInfo.cpp:144 +msgid "Close" msgstr "" -#: Client/core/CSettings.cpp:2158 -msgid "for" +#. Join Game button +#: Client/core/ServerBrowser/CServerInfo.cpp:152 +msgid "Join Game" msgstr "" -#: Client/core/CSettings.cpp:2158 -msgid "sec" +#. Please enter password label +#: Client/core/ServerBrowser/CServerInfo.cpp:166 +msgid "Please enter the password to the server:" msgstr "" -#: Client/core/CSettings.cpp:2161 -msgid "Fading" +#: Client/core/ServerBrowser/CServerInfo.cpp:177 +msgid "Join the server as soon as a player slot is available." msgstr "" -#: Client/core/CSettings.cpp:2167 -msgid "Fade out old lines" +#: Client/core/ServerBrowser/CServerInfo.cpp:310 +msgid "PLEASE ENTER SERVER PASSWORD" msgstr "" -#: Client/core/CSettings.cpp:2207 -msgid "Horizontal:" +#: Client/core/ServerBrowser/CServerInfo.cpp:319 +#: Client/core/ServerBrowser/CServerBrowser.cpp:1380 +#: Client/loader/MainFunctions.cpp:603 Client/loader/MainFunctions.cpp:610 +#: Client/loader/MainFunctions.cpp:1219 +msgid "Information" msgstr "" -#: Client/core/CSettings.cpp:2207 -msgid "Vertical:" +#. The server has timed out +#: Client/core/ServerBrowser/CServerInfo.cpp:402 +msgid "Timed Out" msgstr "" -#: Client/core/CSettings.cpp:2207 -msgid "Text-Align:" +#. Set every GUI elements text to blank +#: Client/core/ServerBrowser/CServerInfo.cpp:431 +msgid "Querying..." msgstr "" -#: Client/core/CSettings.cpp:2207 -msgid "X-Offset:" +#. Create the window +#: Client/core/ServerBrowser/CServerBrowser.cpp:85 +msgid "SERVER BROWSER" msgstr "" -#: Client/core/CSettings.cpp:2208 -msgid "Y-Offset:" +#: Client/core/ServerBrowser/CServerBrowser.cpp:134 +msgid "Local" msgstr "" -#: Client/core/CSettings.cpp:2214 -msgid "Position" +#: Client/core/ServerBrowser/CServerBrowser.cpp:135 +msgid "Favourites" msgstr "" -#: Client/core/CSettings.cpp:2229 Client/core/CSettings.cpp:2243 -msgid "Center" +#: Client/core/ServerBrowser/CServerBrowser.cpp:136 +msgid "Recent" msgstr "" -#: Client/core/CSettings.cpp:2242 -msgid "Top" +#: Client/core/ServerBrowser/CServerBrowser.cpp:191 +msgid "" +"FOR QUICK CONNECT:\n" +"\n" +"Type the address and port into the address bar.\n" +"Or select a server from the history list and press 'Connect'" msgstr "" -#: Client/core/CSettings.cpp:2244 -msgid "Bottom" +#: Client/core/ServerBrowser/CServerBrowser.cpp:203 +msgid "HELP" msgstr "" -#: Client/core/CSettings.cpp:2292 -msgid "Font" +#: Client/core/ServerBrowser/CServerBrowser.cpp:212 +#: Client/core/ServerBrowser/CServerBrowser.cpp:252 +msgid "Refresh" msgstr "" -#: Client/core/CSettings.cpp:2329 -msgid "Hide background when not typing" +#: Client/core/ServerBrowser/CServerBrowser.cpp:212 +#: Client/core/ServerBrowser/CServerBrowser.cpp:253 +msgid "Add Favorite" msgstr "" -#: Client/core/CSettings.cpp:2334 -msgid "Nickname completion using the \"Tab\" key" +#: Client/core/ServerBrowser/CServerBrowser.cpp:212 +#: Client/core/ServerBrowser/CServerBrowser.cpp:254 +#: Client/core/ServerBrowser/CServerBrowser.cpp:301 +#: Client/core/ServerBrowser/CServerBrowser.cpp:372 +msgid "Connect" msgstr "" -#: Client/core/CSettings.cpp:2339 -msgid "Allow server to flash the window" +#: Client/core/ServerBrowser/CServerBrowser.cpp:212 +#: Client/core/ServerBrowser/CServerBrowser.cpp:255 +msgid "Server information" msgstr "" -#: Client/core/CSettings.cpp:2344 -msgid "Allow tray balloon notifications" +#: Client/core/ServerBrowser/CServerBrowser.cpp:213 +#: Client/core/ServerBrowser/CServerBrowser.cpp:256 +msgid "Search servers" msgstr "" -#: Client/core/CSettings.cpp:2349 -msgid "Chat text black/white outline" +#: Client/core/ServerBrowser/CServerBrowser.cpp:213 +#: Client/core/ServerBrowser/CServerBrowser.cpp:257 +msgid "Search players" msgstr "" -#. Create a messagebox to notify the user -#. SString strText = SString::Printf ( "Press a key to bind to '%s'", pItemBind->GetText ().c_str () ); -#. Create a messagebox to notify the user -#. sSString strText = SString::Printf ( "Press a key to bind to '%s'", pItemBind->GetText ().c_str () ); -#: Client/core/CSettings.cpp:2598 Client/core/CSettings.cpp:2605 -msgid "Press a key to bind, or escape to clear" +#: Client/core/ServerBrowser/CServerBrowser.cpp:213 +#: Client/core/ServerBrowser/CServerBrowser.cpp:258 +msgid "Start search" msgstr "" -#: Client/core/CSettings.cpp:2599 -msgid "Binding a primary key" +#: Client/core/ServerBrowser/CServerBrowser.cpp:299 +#: Client/core/ServerBrowser/CServerBrowser.cpp:1697 +msgid "Search players..." msgstr "" -#: Client/core/CSettings.cpp:2606 -msgid "Binding a secondary key" +#: Client/core/ServerBrowser/CServerBrowser.cpp:422 +#: Client/core/ServerBrowser/CServerBrowser.cpp:1695 +msgid "Search servers..." msgstr "" -#: Client/core/CSettings.cpp:2682 -msgid "GTA GAME CONTROLS" +#: Client/core/ServerBrowser/CServerBrowser.cpp:453 +msgid "Name" msgstr "" -#: Client/core/CSettings.cpp:2684 -msgid "MULTIPLAYER CONTROLS" +#: Client/core/ServerBrowser/CServerBrowser.cpp:454 +msgid "Players" msgstr "" -#: Client/core/CSettings.cpp:2929 Client/core/CSettings.cpp:4718 -msgid "Your nickname contains invalid characters!" +#: Client/core/ServerBrowser/CServerBrowser.cpp:455 +msgid "Ping" msgstr "" -#: Client/core/CSettings.cpp:3760 -msgid "Red:" +#: Client/core/ServerBrowser/CServerBrowser.cpp:456 +msgid "Gamemode" msgstr "" -#: Client/core/CSettings.cpp:3760 -msgid "Green:" +#. Include label +#: Client/core/ServerBrowser/CServerBrowser.cpp:486 +msgid "Include:" msgstr "" -#: Client/core/CSettings.cpp:3760 -msgid "Blue:" +#: Client/core/ServerBrowser/CServerBrowser.cpp:492 +msgid "Empty" msgstr "" -#: Client/core/CSettings.cpp:3760 -msgid "Transparency:" +#: Client/core/ServerBrowser/CServerBrowser.cpp:498 +msgid "Full" msgstr "" -#: Client/core/CSettings.cpp:3763 -msgid "Color" +#: Client/core/ServerBrowser/CServerBrowser.cpp:504 +msgid "Locked" msgstr "" -#: Client/core/CSettings.cpp:3840 -msgid "Preview" +#: Client/core/ServerBrowser/CServerBrowser.cpp:516 +msgid "Offline" msgstr "" -#: Client/core/CSettings.cpp:4148 -msgid "Please disconnect before changing language" +#: Client/core/ServerBrowser/CServerBrowser.cpp:529 +msgid "Other Versions" msgstr "" -#: Client/core/CSettings.cpp:4176 -msgid "Please disconnect before changing skin" +#: Client/core/ServerBrowser/CServerBrowser.cpp:550 +msgid "Back" msgstr "" -#: Client/core/CSettings.cpp:4464 -msgid "" -"Volmetric shadows can cause some systems to slow down.\n" -"\n" -"Are you sure you want to enable them?" +#: Client/core/ServerBrowser/CServerBrowser.cpp:556 +#: Client/loader/Dialogs.cpp:135 +msgid "Help" msgstr "" -#: Client/core/CSettings.cpp:4468 -msgid "PERFORMANCE WARNING" +#: Client/core/ServerBrowser/CServerBrowser.cpp:741 +msgid "Loading..." msgstr "" -#: Client/core/CSettings.cpp:4488 -msgid "" -"Screen upload is required by some servers for anti-cheat purposes.\n" -"\n" -"(The chat box and GUI is excluded from the upload)\n" +#: Client/core/ServerBrowser/CServerBrowser.cpp:1240 +#: Client/core/ServerBrowser/CServerBrowser.cpp:2182 +msgid " ..loading.." msgstr "" -#: Client/core/CSettings.cpp:4490 -msgid "SCREEN UPLOAD INFORMATION" +#: Client/core/ServerBrowser/CServerBrowser.cpp:1278 +#: Client/core/ServerBrowser/CServerBrowser.cpp:1406 +msgid "No address specified!" msgstr "" -#: Client/core/CSettings.cpp:4505 -msgid "" -"Some scripts may play sounds, such as radio, from the internet.\n" -"\n" -"Disabling this setting may decrease network\n" -"bandwidth consumption.\n" +#: Client/core/ServerBrowser/CServerBrowser.cpp:1291 +msgid "Unknown protocol" msgstr "" -#: Client/core/CSettings.cpp:4508 -msgid "EXTERNAL SOUNDS" +#: Client/core/ServerBrowser/CServerBrowser.cpp:1291 +msgid "Please use the mtasa:// protocol!" msgstr "" -#: Client/core/CSettings.cpp:4538 -msgid "" -"Some files in your GTA:SA data directory are customized.\n" -"MTA will only use these modified files if this check box is ticked.\n" -"\n" -"However, CUSTOMIZED GTA:SA FILES ARE BLOCKED BY MANY SERVERS\n" -"\n" -"Are you sure you want to use them?" +#: Client/core/ServerBrowser/CServerBrowser.cpp:1380 +msgid "You have to select a server to connect to." msgstr "" -#: Client/core/CSettings.cpp:4587 +#: Client/core/DXHook/CDirect3DHook9.cpp:124 msgid "" -"Enabling DPI awareness is an experimental feature and\n" -"we only recommend it when you play MTA:SA on a scaled monitor.\n" -"You may experience graphical issues if you enable this option.\n" +"Could not initialize Direct3D9.\n" "\n" -"Are you sure you want to enable this option?" +"Please ensure the DirectX End-User Runtime and\n" +"latest Windows Service Packs are installed correctly." msgstr "" -#: Client/core/CSettings.cpp:4593 -msgid "EXPERIMENTAL FEATURE" +#: Client/loader/Dialogs.cpp:134 +msgid "Quit" msgstr "" -#: Client/core/CSettings.cpp:4736 -msgid "Please enter a nickname" +#: Client/loader/Dialogs.cpp:151 +msgid "MTA: San Andreas has encountered a problem" msgstr "" -#: Client/core/CSettings.cpp:4737 -msgid "" -"Please enter a nickname to be used ingame. \n" -"This will be your name when you connect to and play in a server" -msgstr "" - -#: Client/core/CSettings.cpp:4755 -msgid "Very experimental feature." -msgstr "" - -#: Client/core/CSettings.cpp:4757 -msgid "Stops stalls with CJ variations (Uses 65MB more RAM)" -msgstr "" - -#: Client/core/CSettings.cpp:4759 -msgid "Older routers may require a slower scan speed." -msgstr "" - -#: Client/core/CSettings.cpp:4761 -msgid "Switch on to use only one connection when downloading." -msgstr "" - -#: Client/core/CSettings.cpp:4763 -msgid "Tag network packets to help ISPs identify MTA traffic." +#: Client/loader/Dialogs.cpp:152 +msgid "Crash information" msgstr "" -#: Client/core/CSettings.cpp:4765 -msgid "Spinning circle animation at the bottom of the screen" +#: Client/loader/Dialogs.cpp:153 +msgid "" +"Tick the check box to send this crash info to MTA devs using the 'internet'" msgstr "" -#: Client/core/CSettings.cpp:4767 -msgid "Select default always. (This setting is not saved)" +#: Client/loader/Dialogs.cpp:154 +msgid "Doing so will increase the chance of this crash being fixed." msgstr "" -#: Client/core/CSettings.cpp:4769 -msgid "Maximum is usually best" +#: Client/loader/Dialogs.cpp:155 +msgid "Do you want to restart MTA: San Andreas ?" msgstr "" -#: Client/core/CSettings.cpp:4771 Client/core/CSettings.cpp:4773 -msgid "Auto updater:" +#: Client/loader/Dialogs.cpp:162 +msgid "MTA: San Andreas - Warning" msgstr "" -#: Client/core/CSettings.cpp:4771 -msgid "Select default unless you like filling out bug reports." +#: Client/loader/Dialogs.cpp:163 +msgid "" +"Your Grand Theft Auto: San Andreas install directory contains these files:" msgstr "" -#: Client/core/CSettings.cpp:4773 -msgid "Select default to automatically install important updates." +#: Client/loader/Dialogs.cpp:165 +msgid "" +"These files are not required and may interfere with the graphical features " +"in this version of MTA:SA.\n" +"\n" +"It is recommended that you remove or rename these files." msgstr "" -#: Client/core/CSettings.cpp:4775 -msgid "16-bit color:" +#: Client/loader/Dialogs.cpp:167 +msgid "Keep these files, but also show this warning on next start" msgstr "" -#: Client/core/CSettings.cpp:4775 -msgid "Enable 16 bit color modes - Requires MTA restart" +#: Client/loader/Dialogs.cpp:168 +msgid "Do not remind me about these files again" msgstr "" -#: Client/core/CSettings.cpp:4777 -msgid "Mouse fix:" +#: Client/loader/Dialogs.cpp:169 +msgid "Rename these files from *.dll to *.dll.bak" msgstr "" -#: Client/core/CSettings.cpp:4777 -msgid "Mouse movement fix - May need PC restart" +#: Client/loader/Dialogs.cpp:170 +msgid "Show me these files" msgstr "" -#: Client/core/CCore.cpp:813 Shared/mods/deathmatch/logic/Utils.cpp:111 -msgid "Fatal error" +#: Client/loader/Dialogs.cpp:171 +msgid "Play MTA:SA" msgstr "" -#: Client/core/CCore.cpp:938 -msgid "TO FIX, REMOVE THIS FILE:" +#: Client/loader/Dialogs.cpp:177 +msgid "MTA: San Andreas - Confusing options" msgstr "" -#: Client/core/CCore.cpp:970 -#, c-format -msgid "%s module is incorrect!" +#: Client/loader/Dialogs.cpp:178 +msgid "NVidia Optimus detected!" msgstr "" -#: Client/core/CCore.cpp:1275 -msgid "Error executing URL" +#: Client/loader/Dialogs.cpp:179 +msgid "Try each option and see what works:" msgstr "" -#: Client/core/CCore.cpp:1287 -#, c-format -msgid "Error running mod specified in command line ('%s')" +#: Client/loader/Dialogs.cpp:180 +msgid "A - Standard NVidia" msgstr "" -#. m_pCommands->Add ( "e", CCommandFuncs::Editor ); -#. m_pCommands->Add ( "clear", CCommandFuncs::Clear ); -#: Client/core/CCore.cpp:1389 -msgid "this help screen" +#: Client/loader/Dialogs.cpp:181 +msgid "B - Alternate NVidia" msgstr "" -#: Client/core/CCore.cpp:1390 Client/core/CCore.cpp:1391 -msgid "exits the application" +#: Client/loader/Dialogs.cpp:182 +msgid "C - Standard Intel" msgstr "" -#: Client/core/CCore.cpp:1392 -msgid "shows the version" +#: Client/loader/Dialogs.cpp:183 +msgid "D - Alternate Intel" msgstr "" -#: Client/core/CCore.cpp:1393 -msgid "shows the time" +#: Client/loader/Dialogs.cpp:184 +msgid "If you get desperate, this might help:" msgstr "" -#: Client/core/CCore.cpp:1394 -msgid "shows the hud" +#: Client/loader/Dialogs.cpp:185 +msgid "If you have already selected an option that works, this might help:" msgstr "" -#: Client/core/CCore.cpp:1395 -msgid "shows all the binds" +#: Client/loader/Dialogs.cpp:186 +msgid "Force windowed mode" msgstr "" -#: Client/core/CCore.cpp:1396 -msgid "shows your serial" +#: Client/loader/Dialogs.cpp:187 +msgid "Don't show again" msgstr "" -#: Client/core/CCore.cpp:1405 -msgid "connects to a server (host port nick pass)" +#: Client/loader/Dialogs.cpp:195 +msgid "Warning: Could not detect anti-virus product" msgstr "" -#: Client/core/CCore.cpp:1406 -msgid "connects to a previous server" +#: Client/loader/Dialogs.cpp:197 +msgid "" +"MTA could not detect an anti-virus on your PC.\n" +"\n" +"Viruses interfere with MTA and degrade your gameplay experience.\n" +"\n" +"Press 'Help' for more information." msgstr "" -#: Client/core/CCore.cpp:1407 -msgid "binds a key (key control)" +#: Client/loader/Dialogs.cpp:200 +msgid "I have already installed an anti-virus" msgstr "" -#: Client/core/CCore.cpp:1408 -msgid "unbinds a key (key)" +#: Client/loader/Dialogs.cpp:202 +msgid "" +"I will not install an anti-virus.\n" +"I want my PC to lag and be part of a botnet." msgstr "" -#: Client/core/CCore.cpp:1409 -msgid "copies the default gta controls" +#: Client/loader/Dialogs.cpp:890 Client/loader/Utils.cpp:534 +msgid "Searching for Grand Theft Auto San Andreas" msgstr "" -#: Client/core/CCore.cpp:1410 -msgid "outputs a screenshot" +#: Client/loader/Dialogs.cpp:893 Client/loader/Utils.cpp:536 +msgid "Please start Grand Theft Auto San Andreas" msgstr "" -#: Client/core/CCore.cpp:1411 -msgid "immediately saves the config" +#: Client/loader/Dialogs.cpp:901 Client/loader/Install.cpp:852 +msgid "Installing update..." msgstr "" -#: Client/core/CCore.cpp:1413 -msgid "clears the debug view" +#: Client/loader/Dialogs.cpp:909 Client/loader/Install.cpp:934 +msgid "Extracting files..." msgstr "" -#: Client/core/CCore.cpp:1414 -msgid "scrolls the chatbox upwards" +#: Client/loader/Dialogs.cpp:914 Client/loader/Utils.cpp:1394 +msgid "Copying files..." msgstr "" -#: Client/core/CCore.cpp:1415 -msgid "scrolls the chatbox downwards" +#: Client/loader/Dialogs.cpp:919 Client/loader/Utils.cpp:1454 +msgid "Copy finished early. Everything OK." msgstr "" -#: Client/core/CCore.cpp:1416 -msgid "scrolls the debug view upwards" +#: Client/loader/Dialogs.cpp:924 Client/loader/Utils.cpp:1460 +msgid "Finishing..." msgstr "" -#: Client/core/CCore.cpp:1417 -msgid "scrolls the debug view downwards" +#: Client/loader/Dialogs.cpp:928 Client/loader/Utils.cpp:1462 +msgid "Done!" msgstr "" -#: Client/core/CCore.cpp:1420 -msgid "shows the memory statistics" +#: Client/loader/Utils.cpp:600 +msgid "Select your Grand Theft Auto: San Andreas Installation Directory" msgstr "" -#: Client/core/CCore.cpp:1421 -msgid "shows the frame timing graph" +#: Client/loader/Utils.cpp:968 Client/loader/CInstallManager.cpp:361 +#, c-format +msgid "" +"MTA:SA needs Administrator access for the following task:\n" +"\n" +" '%s'\n" +"\n" +"Please confirm in the next window." msgstr "" -#: Client/core/CCore.cpp:1425 -msgid "for developers: reload news" +#: Client/loader/Utils.cpp:1069 +#, c-format +msgid "Error loading %s module! (%s)" msgstr "" -#: Client/core/DXHook/CDirect3DHook9.cpp:124 +#: Client/loader/Utils.cpp:1502 +#, c-format msgid "" -"Could not initialize Direct3D9.\n" +"New installation of %s detected.\n" "\n" -"Please ensure the DirectX End-User Runtime and\n" -"latest Windows Service Packs are installed correctly." +"Do you want to copy your settings from %s ?" msgstr "" -#. Create queue window -#: Client/core/ServerBrowser/CServerInfo.cpp:32 -#: Client/core/ServerBrowser/CServerInfo.cpp:302 -msgid "SERVER IS FULL" +#: Client/loader/Utils.cpp:1541 +#, c-format +msgid "GTA:SA had trouble opening the file '%s'" msgstr "" -#. Determine our label draw position for L10n -#. Start position -#. Server Name -#: Client/core/ServerBrowser/CServerInfo.cpp:44 -#: Client/core/ServerBrowser/CServerInfo.cpp:53 -msgid "Name:" +#: Client/loader/Utils.cpp:1563 +#, c-format +msgid "GTA:SA is missing the file '%s'." msgstr "" -#. Server IP -#: Client/core/ServerBrowser/CServerInfo.cpp:44 -#: Client/core/ServerBrowser/CServerInfo.cpp:64 -msgid "Server Address:" +#: Client/loader/Utils.cpp:1588 +msgid "GTA:SA had trouble loading a model." msgstr "" -#. Gamemode -#: Client/core/ServerBrowser/CServerInfo.cpp:44 -#: Client/core/ServerBrowser/CServerInfo.cpp:75 -msgid "Gamemode:" +#: Client/loader/Utils.cpp:1590 +msgid "If you recently modified gta3.img, then try reinstalling GTA:SA." msgstr "" -#. Map -#: Client/core/ServerBrowser/CServerInfo.cpp:44 -#: Client/core/ServerBrowser/CServerInfo.cpp:86 -msgid "Map:" +#: Client/loader/Utils.cpp:1615 +msgid "GTA:SA had trouble adding an upgrade to a vehicle." msgstr "" -#. Players -#: Client/core/ServerBrowser/CServerInfo.cpp:45 -#: Client/core/ServerBrowser/CServerInfo.cpp:97 -msgid "Players:" +#: Client/loader/Utils.cpp:1634 +#, c-format +msgid "GTA:SA found errors in the file '%s'" msgstr "" -#. Passworded -#: Client/core/ServerBrowser/CServerInfo.cpp:45 -#: Client/core/ServerBrowser/CServerInfo.cpp:108 -msgid "Passworded:" +#: Client/loader/Utils.cpp:1716 +msgid "Did your computer restart when playing MTA:SA?" msgstr "" -#. Latency -#: Client/core/ServerBrowser/CServerInfo.cpp:45 -#: Client/core/ServerBrowser/CServerInfo.cpp:119 -msgid "Latency:" +#: Client/loader/Utils.cpp:1781 +msgid "Please terminate the following programs before continuing:" msgstr "" -#. Column for player names -#. Player List Columns -#: Client/core/ServerBrowser/CServerInfo.cpp:138 -#: Client/core/ServerBrowser/CServerBrowser.cpp:478 -msgid "Player list" +#: Client/loader/Install.cpp:265 +msgid "Unknown" msgstr "" -#. Close button -#: Client/core/ServerBrowser/CServerInfo.cpp:144 -msgid "Close" +#: Client/loader/Install.cpp:272 +#, c-format +msgid "" +"The file '%s' is currently locked by %zu processes.\n" +"\n" +"Do you want to terminate the following processes and continue updating?\n" +"\n" +"%s" msgstr "" -#. Join Game button -#: Client/core/ServerBrowser/CServerInfo.cpp:152 -msgid "Join Game" +#: Client/loader/Install.cpp:479 +#, c-format +msgid "" +"Your installation may be corrupt now.\n" +"\n" +"%zu out of %zu files could not be restored from the backup.\n" +"\n" +"You should reinstall Multi Theft Auto from www.multitheftauto.com\n" +"or try running the update with administrator rights." msgstr "" -#. Please enter password label -#: Client/core/ServerBrowser/CServerInfo.cpp:166 -msgid "Please enter the password to the server:" +#: Client/loader/MainFunctions.cpp:248 +msgid "" +"Trouble restarting MTA:SA\n" +"\n" +"If the problem persists, open Task Manager and\n" +"stop the 'gta_sa.exe' and 'Multi Theft Auto.exe' processes\n" +"\n" +"\n" +"Try to launch MTA:SA again?" msgstr "" -#: Client/core/ServerBrowser/CServerInfo.cpp:177 -msgid "Join the server as soon as a player slot is available." +#: Client/loader/MainFunctions.cpp:266 +msgid "" +"Another instance of MTA is already running.\n" +"\n" +"If this problem persists, please restart your computer" msgstr "" -#: Client/core/ServerBrowser/CServerInfo.cpp:310 -msgid "PLEASE ENTER SERVER PASSWORD" +#: Client/loader/MainFunctions.cpp:269 +msgid "" +"Another instance of MTA is already running.\n" +"\n" +"Do you want to terminate it?" msgstr "" -#. The server has timed out -#: Client/core/ServerBrowser/CServerInfo.cpp:402 -msgid "Timed Out" +#: Client/loader/MainFunctions.cpp:294 +msgid "" +"Are you having problems running MTA:SA?.\n" +"\n" +"Do you want to revert to an earlier version?" msgstr "" -#. Set every GUI elements text to blank -#: Client/core/ServerBrowser/CServerInfo.cpp:431 -msgid "Querying..." +#: Client/loader/MainFunctions.cpp:324 +msgid "" +"There seems to be a problem launching MTA:SA.\n" +"Resetting GTA settings can sometimes fix this problem.\n" +"\n" +"Do you want to reset GTA settings now?" msgstr "" -#. Create the window -#: Client/core/ServerBrowser/CServerBrowser.cpp:85 -msgid "SERVER BROWSER" +#: Client/loader/MainFunctions.cpp:339 +msgid "" +"GTA settings have been reset.\n" +"\n" +"Press OK to continue." msgstr "" -#: Client/core/ServerBrowser/CServerBrowser.cpp:134 -msgid "Local" +#: Client/loader/MainFunctions.cpp:344 +#, c-format +msgid "File could not be deleted: '%s'" msgstr "" -#: Client/core/ServerBrowser/CServerBrowser.cpp:135 -msgid "Favourites" +#. No settings to delete, or can't find them +#: Client/loader/MainFunctions.cpp:352 +msgid "" +"Are you having problems running MTA:SA?.\n" +"\n" +"Do you want to see some online help?" msgstr "" -#: Client/core/ServerBrowser/CServerBrowser.cpp:136 -msgid "Recent" +#. Inform user +#: Client/loader/MainFunctions.cpp:388 +msgid "" +"Are you having problems running MTA:SA?.\n" +"\n" +"Do you want to change the following setting?" msgstr "" -#: Client/core/ServerBrowser/CServerBrowser.cpp:191 +#: Client/loader/MainFunctions.cpp:431 msgid "" -"FOR QUICK CONNECT:\n" +"Are you having problems running MTA:SA?.\n" "\n" -"Type the address and port into the address bar.\n" -"Or select a server from the history list and press 'Connect'" +"Try disabling the following products for GTA and MTA:" msgstr "" -#: Client/core/ServerBrowser/CServerBrowser.cpp:203 -msgid "HELP" +#: Client/loader/MainFunctions.cpp:465 +msgid "" +"WARNING\n" +"\n" +"MTA:SA has detected unusual activity.\n" +"Please run a virus scan to ensure your system is secure.\n" +"\n" +msgstr "" + +#: Client/loader/MainFunctions.cpp:468 +#, c-format +msgid "The detected file was: %s\n" msgstr "" -#: Client/core/ServerBrowser/CServerBrowser.cpp:212 -#: Client/core/ServerBrowser/CServerBrowser.cpp:252 -msgid "Refresh" +#: Client/loader/MainFunctions.cpp:602 +msgid "" +"An instance of GTA: San Andreas is already running. It needs to be " +"terminated before MTA:SA can be started. Do you want to do that now?" msgstr "" -#: Client/core/ServerBrowser/CServerBrowser.cpp:212 -#: Client/core/ServerBrowser/CServerBrowser.cpp:253 -msgid "Add Favorite" +#: Client/loader/MainFunctions.cpp:609 +msgid "" +"Unable to terminate GTA: San Andreas. If the problem persists, please " +"restart your computer." msgstr "" -#: Client/core/ServerBrowser/CServerBrowser.cpp:212 -#: Client/core/ServerBrowser/CServerBrowser.cpp:254 -#: Client/core/ServerBrowser/CServerBrowser.cpp:301 -#: Client/core/ServerBrowser/CServerBrowser.cpp:372 -msgid "Connect" +#: Client/loader/MainFunctions.cpp:632 +msgid "" +"Registry entries are missing. Please reinstall Multi Theft Auto: San Andreas." msgstr "" -#: Client/core/ServerBrowser/CServerBrowser.cpp:212 -#: Client/core/ServerBrowser/CServerBrowser.cpp:255 -msgid "Server information" +#: Client/loader/MainFunctions.cpp:638 +msgid "" +"The path to your installation of GTA: San Andreas contains unsupported " +"(unicode) characters. Please move your Grand Theft Auto: San Andreas " +"installation to a compatible path that contains only standard ASCII " +"characters and reinstall Multi Theft Auto: San Andreas." msgstr "" -#: Client/core/ServerBrowser/CServerBrowser.cpp:213 -#: Client/core/ServerBrowser/CServerBrowser.cpp:256 -msgid "Search servers" +#: Client/loader/MainFunctions.cpp:648 +msgid "" +"The path to your installation of 'MTA:SA' or 'GTA: San Andreas'\n" +"contains a ';' (semicolon).\n" +"\n" +" If you experience problems when running MTA:SA,\n" +" move your installation(s) to a path that does not contain a semicolon." msgstr "" -#: Client/core/ServerBrowser/CServerBrowser.cpp:213 -#: Client/core/ServerBrowser/CServerBrowser.cpp:257 -msgid "Search players" +#: Client/loader/MainFunctions.cpp:810 +msgid "" +"Load failed. Please ensure that the latest data files have been installed " +"correctly." msgstr "" -#: Client/core/ServerBrowser/CServerBrowser.cpp:213 -#: Client/core/ServerBrowser/CServerBrowser.cpp:258 -msgid "Start search" +#: Client/loader/MainFunctions.cpp:819 +#, c-format +msgid "Load failed. Please ensure that %s is installed correctly." msgstr "" -#: Client/core/ServerBrowser/CServerBrowser.cpp:299 -#: Client/core/ServerBrowser/CServerBrowser.cpp:1697 -msgid "Search players..." +#: Client/loader/MainFunctions.cpp:826 +#, c-format +msgid "Load failed. Could not find gta_sa.exe in %s." msgstr "" -#: Client/core/ServerBrowser/CServerBrowser.cpp:422 -#: Client/core/ServerBrowser/CServerBrowser.cpp:1695 -msgid "Search servers..." +#: Client/loader/MainFunctions.cpp:836 +#, c-format +msgid "" +"Load failed. %s exists in the GTA directory. Please delete before continuing." msgstr "" -#: Client/core/ServerBrowser/CServerBrowser.cpp:453 -msgid "Name" +#: Client/loader/MainFunctions.cpp:845 +#, c-format +msgid "Main file has an incorrect name (%s)" msgstr "" -#: Client/core/ServerBrowser/CServerBrowser.cpp:454 -msgid "Players" +#: Client/loader/MainFunctions.cpp:856 +msgid "" +"Main file is unsigned. Possible virus activity.\n" +"\n" +"See online help if MTA does not work correctly." msgstr "" -#: Client/core/ServerBrowser/CServerBrowser.cpp:455 -msgid "Ping" +#: Client/loader/MainFunctions.cpp:882 +#, c-format +msgid "" +"Data file %s is missing. Possible virus activity.\n" +"\n" +"Consider reinstalling Multi Theft Auto for your security.\n" +"See online help if MTA does not work correctly." msgstr "" -#: Client/core/ServerBrowser/CServerBrowser.cpp:456 -msgid "Gamemode" +#: Client/loader/MainFunctions.cpp:893 +#, c-format +msgid "" +"Data file %s is modified. Possible virus activity.\n" +"\n" +"Consider reinstalling Multi Theft Auto for your security.\n" +"See online help if MTA does not work correctly." msgstr "" -#. Include label -#: Client/core/ServerBrowser/CServerBrowser.cpp:486 -msgid "Include:" +#: Client/loader/MainFunctions.cpp:907 +msgid "" +".asi files are in the 'MTA:SA' or 'GTA: San Andreas' installation " +"directory.\n" +"\n" +"Remove these .asi files if you experience problems with MTA:SA." msgstr "" -#: Client/core/ServerBrowser/CServerBrowser.cpp:492 -msgid "Empty" +#: Client/loader/MainFunctions.cpp:1009 +msgid "" +"File version mismatch error. Reinstall MTA:SA if you experience problems.\n" msgstr "" -#: Client/core/ServerBrowser/CServerBrowser.cpp:498 -msgid "Full" +#: Client/loader/MainFunctions.cpp:1018 +msgid "Some files are missing. Reinstall MTA:SA if you experience problems.\n" msgstr "" -#: Client/core/ServerBrowser/CServerBrowser.cpp:504 -msgid "Locked" +#: Client/loader/MainFunctions.cpp:1030 +msgid "" +"MTA:SA is not compatible with Windows 'Safe Mode'.\n" +"\n" +"Please restart your PC.\n" msgstr "" -#: Client/core/ServerBrowser/CServerBrowser.cpp:516 -msgid "Offline" +#: Client/loader/MainFunctions.cpp:1123 +msgid "Fix configuration issue" msgstr "" -#: Client/core/ServerBrowser/CServerBrowser.cpp:529 -msgid "Other Versions" +#. Try to relaunch as admin if not done so already +#: Client/loader/MainFunctions.cpp:1157 +msgid "Fix elevation required error" msgstr "" -#: Client/core/ServerBrowser/CServerBrowser.cpp:550 -msgid "Back" +#: Client/loader/MainFunctions.cpp:1164 +#, c-format +msgid "" +"Could not start Grand Theft Auto: San Andreas. Please try restarting, or if " +"the problem persists,contact MTA at www.multitheftauto.com. \n" +"\n" +"[%s]" msgstr "" -#: Client/core/ServerBrowser/CServerBrowser.cpp:741 -msgid "Loading..." +#: Client/loader/MainFunctions.cpp:1219 +msgid "" +"GTA: San Andreas may not have launched correctly. Do you want to terminate " +"it?" msgstr "" -#: Client/core/ServerBrowser/CServerBrowser.cpp:1240 -#: Client/core/ServerBrowser/CServerBrowser.cpp:2182 -msgid " ..loading.." +#: Client/loader/CInstallManager.cpp:376 +#, c-format +msgid "" +"MTA:SA could not complete the following task:\n" +"\n" +" '%s'\n" msgstr "" -#: Client/core/ServerBrowser/CServerBrowser.cpp:1278 -#: Client/core/ServerBrowser/CServerBrowser.cpp:1406 -msgid "No address specified!" +#: Client/loader/CInstallManager.cpp:426 +msgid "" +"** The crash was caused by a graphics driver error **\n" +"\n" +"** Please update your graphics drivers **" msgstr "" -#: Client/core/ServerBrowser/CServerBrowser.cpp:1291 -msgid "Unknown protocol" +#: Client/loader/CInstallManager.cpp:532 +msgid "Install updated MTA:SA files" msgstr "" -#: Client/core/ServerBrowser/CServerBrowser.cpp:1291 -msgid "Please use the mtasa:// protocol!" +#: Client/loader/CInstallManager.cpp:552 +msgid "" +"Could not update due to file conflicts. Please close other applications and " +"retry" msgstr "" -#: Client/core/ServerBrowser/CServerBrowser.cpp:1380 -msgid "You have to select a server to connect to." +#: Client/loader/CInstallManager.cpp:561 +#, c-format +msgid "Multi Theft Auto has not been installed properly, please reinstall. %s" msgstr "" -#: Client/core/ServerBrowser/CServerList.cpp:25 -msgid "Idle" +#: Client/loader/CInstallManager.cpp:613 +msgid "Create GTA:SA junctions" msgstr "" -#: Client/core/ServerBrowser/CServerList.cpp:150 -msgid "player" -msgid_plural "players" -msgstr[0] "" -msgstr[1] "" - -#: Client/core/ServerBrowser/CServerList.cpp:151 -msgid "on" +#: Client/loader/CInstallManager.cpp:657 +msgid "MTA:SA cannot launch because copying a file failed:" msgstr "" -#: Client/core/ServerBrowser/CServerList.cpp:154 -msgid "server" -msgid_plural "servers" -msgstr[0] "" -msgstr[1] "" +#: Client/loader/CInstallManager.cpp:663 Client/loader/CInstallManager.cpp:703 +msgid "MTA:SA cannot launch because an MTA:SA file is incorrect or missing:" +msgstr "" -#. We are polling for the master server list (first pass) -#: Client/core/ServerBrowser/CServerList.cpp:238 -#, c-format -msgid "Requesting master server list (%lu ms elapsed)" +#: Client/loader/CInstallManager.cpp:672 +msgid "Copy MTA:SA files" msgstr "" -#. Abort -#: Client/core/ServerBrowser/CServerList.cpp:254 -msgid "Master server list could not be parsed." +#: Client/loader/CInstallManager.cpp:695 Client/loader/CInstallManager.cpp:773 +msgid "MTA:SA cannot launch because a GTA:SA file is incorrect or missing:" msgstr "" -#. Abort -#: Client/core/ServerBrowser/CServerList.cpp:264 -msgid "Master server list could not be retrieved." +#: Client/loader/CInstallManager.cpp:780 +msgid "Patch GTA:SA dependency" msgstr "" -#: Client/core/ServerBrowser/CServerList.cpp:274 -msgid "(Backup server list)" +#: Client/loader/CInstallManager.cpp:828 +msgid "" +"MTA:SA cannot launch because the GTA:SA executable is incorrect or missing:" msgstr "" -#: Client/core/ServerBrowser/CServerList.cpp:326 -msgid "Cannot bind LAN-broadcast socket" +#: Client/loader/CInstallManager.cpp:832 +msgid "" +"Please check your anti-virus for a false-positive detection, try to add an " +"exception for the GTA:SA executable and restart MTA:SA." msgstr "" -#: Client/core/ServerBrowser/CServerList.cpp:345 -msgid "Attempting to discover LAN servers" +#: Client/loader/CInstallManager.cpp:838 +msgid "Generate GTA:SA" msgstr "" -#: Client/game_sa/CSettingsSA.cpp:804 -msgid "Can't find valid screen resolution." +#: Client/loader/CInstallManager.cpp:853 +msgid "MTA:SA cannot launch because the GTA:SA executable is not loadable:" msgstr "" -#. Confirm that res should be used -#: Client/game_sa/CSettingsSA.cpp:880 -msgid "Are you sure you want to use this screen resolution?" +#: Client/loader/CInstallManager.cpp:860 Client/loader/CInstallManager.cpp:883 +msgid "Patch GTA:SA" msgstr "" -#: Client/cefweb/CWebsiteRequests.cpp:19 -msgid "Website requests" +#: Client/loader/CInstallManager.cpp:876 +msgid "MTA:SA cannot launch because patching GTA:SA has failed:" msgstr "" -#: Client/cefweb/CWebsiteRequests.cpp:27 -msgid "" -"The server requests the following websites in order to load them (later):" +#: Client/loader/CInstallManager.cpp:1113 +msgid "Missing file:" msgstr "" -#: Client/cefweb/CWebsiteRequests.cpp:33 -msgid "NEVER ENTER SENSITIVE DATA TO PROTECT THEM FROM BEING STOLEN" +#: Client/loader/CInstallManager.cpp:1117 +msgid "If MTA fails to load, please re-install GTA:SA" msgstr "" -#: Client/cefweb/CWebsiteRequests.cpp:46 -msgid "Remember decision" +#: Client/loader/CInstallManager.cpp:1152 +msgid "Update install settings" msgstr "" -#: Client/cefweb/CWebsiteRequests.cpp:57 -msgid "Deny" +#: Client/loader/CInstallManager.cpp:1305 +msgid "Update compatibility settings" msgstr "" #. Populate the message and show the box -#: Shared/mods/deathmatch/logic/Utils.cpp:109 +#: Shared/mods/deathmatch/logic/Utils.cpp:127 #, c-format msgid "" "Fatal error (%u). If this problem persists, please check out mtasa.com for " @@ -3291,14 +3293,14 @@ msgstr "" #. assert ( 0 ); #. #endif #. Populate the message and show the box -#: Shared/mods/deathmatch/logic/Utils.cpp:125 +#: Shared/mods/deathmatch/logic/Utils.cpp:143 #, c-format msgid "" "Protocol error (%u). If this problem persists, please check out mtasa.com " "for support." msgstr "" -#: Shared/mods/deathmatch/logic/Utils.cpp:127 +#: Shared/mods/deathmatch/logic/Utils.cpp:145 msgid "Connection error" msgstr "" diff --git a/Shared/data/MTA San Andreas/MTA/tags.dll b/Shared/data/MTA San Andreas/MTA/tags.dll index 65c7e2208c..874ef2c672 100644 Binary files a/Shared/data/MTA San Andreas/MTA/tags.dll and b/Shared/data/MTA San Andreas/MTA/tags.dll differ diff --git a/Shared/data/MTA San Andreas/server/arm/libmysql.dll b/Shared/data/MTA San Andreas/server/arm/libmysql.dll deleted file mode 100644 index 1ee0083699..0000000000 Binary files a/Shared/data/MTA San Andreas/server/arm/libmysql.dll and /dev/null differ diff --git a/Shared/data/MTA San Andreas/server/arm64/libcrypto-3-arm64.dll b/Shared/data/MTA San Andreas/server/arm64/libcrypto-3-arm64.dll new file mode 100644 index 0000000000..666c0f287b Binary files /dev/null and b/Shared/data/MTA San Andreas/server/arm64/libcrypto-3-arm64.dll differ diff --git a/Shared/data/MTA San Andreas/server/arm64/libmysql.dll b/Shared/data/MTA San Andreas/server/arm64/libmysql.dll index d0f08d9fe1..3f3e2895e8 100644 Binary files a/Shared/data/MTA San Andreas/server/arm64/libmysql.dll and b/Shared/data/MTA San Andreas/server/arm64/libmysql.dll differ diff --git a/Shared/data/MTA San Andreas/server/arm64/libssl-3-arm64.dll b/Shared/data/MTA San Andreas/server/arm64/libssl-3-arm64.dll new file mode 100644 index 0000000000..51a8eb0eb2 Binary files /dev/null and b/Shared/data/MTA San Andreas/server/arm64/libssl-3-arm64.dll differ diff --git a/Shared/data/MTA San Andreas/server/mods/deathmatch/libcrypto-3.dll b/Shared/data/MTA San Andreas/server/mods/deathmatch/libcrypto-3.dll new file mode 100644 index 0000000000..f7ce3d098e Binary files /dev/null and b/Shared/data/MTA San Andreas/server/mods/deathmatch/libcrypto-3.dll differ diff --git a/Shared/data/MTA San Andreas/server/mods/deathmatch/libmysql.dll b/Shared/data/MTA San Andreas/server/mods/deathmatch/libmysql.dll index 7dae6e8000..8efa94f3a6 100644 Binary files a/Shared/data/MTA San Andreas/server/mods/deathmatch/libmysql.dll and b/Shared/data/MTA San Andreas/server/mods/deathmatch/libmysql.dll differ diff --git a/Shared/data/MTA San Andreas/server/mods/deathmatch/libssl-3.dll b/Shared/data/MTA San Andreas/server/mods/deathmatch/libssl-3.dll new file mode 100644 index 0000000000..e09cfd88c7 Binary files /dev/null and b/Shared/data/MTA San Andreas/server/mods/deathmatch/libssl-3.dll differ diff --git a/Shared/data/MTA San Andreas/server/x64/libcrypto-3-x64.dll b/Shared/data/MTA San Andreas/server/x64/libcrypto-3-x64.dll new file mode 100644 index 0000000000..01a84081b0 Binary files /dev/null and b/Shared/data/MTA San Andreas/server/x64/libcrypto-3-x64.dll differ diff --git a/Shared/data/MTA San Andreas/server/x64/libmysql.dll b/Shared/data/MTA San Andreas/server/x64/libmysql.dll index 3cc289b4e5..7e1949a485 100644 Binary files a/Shared/data/MTA San Andreas/server/x64/libmysql.dll and b/Shared/data/MTA San Andreas/server/x64/libmysql.dll differ diff --git a/Shared/data/MTA San Andreas/server/x64/libssl-3-x64.dll b/Shared/data/MTA San Andreas/server/x64/libssl-3-x64.dll new file mode 100644 index 0000000000..849cd5f0ba Binary files /dev/null and b/Shared/data/MTA San Andreas/server/x64/libssl-3-x64.dll differ diff --git a/Shared/data/launchers/CEFLauncher.exe b/Shared/data/launchers/CEFLauncher.exe index fcc62dcc25..8ddad15d39 100644 Binary files a/Shared/data/launchers/CEFLauncher.exe and b/Shared/data/launchers/CEFLauncher.exe differ diff --git a/Shared/data/launchers/MTA Server ARM64.exe b/Shared/data/launchers/MTA Server ARM64.exe index d58f659a39..f64006f3d8 100644 Binary files a/Shared/data/launchers/MTA Server ARM64.exe and b/Shared/data/launchers/MTA Server ARM64.exe differ diff --git a/Shared/data/launchers/MTA Server.exe b/Shared/data/launchers/MTA Server.exe index 5c2e4f7932..bc664aec89 100644 Binary files a/Shared/data/launchers/MTA Server.exe and b/Shared/data/launchers/MTA Server.exe differ diff --git a/Shared/data/launchers/MTA Server64.exe b/Shared/data/launchers/MTA Server64.exe index 76fb8fb857..021e55401f 100644 Binary files a/Shared/data/launchers/MTA Server64.exe and b/Shared/data/launchers/MTA Server64.exe differ diff --git a/Shared/data/launchers/Multi Theft Auto.exe b/Shared/data/launchers/Multi Theft Auto.exe index dcdf9970f8..99fcb3c6bf 100644 Binary files a/Shared/data/launchers/Multi Theft Auto.exe and b/Shared/data/launchers/Multi Theft Auto.exe differ diff --git a/Shared/data/launchers/wow64_helper.exe b/Shared/data/launchers/wow64_helper.exe index c16884e77c..24a78f7abb 100644 Binary files a/Shared/data/launchers/wow64_helper.exe and b/Shared/data/launchers/wow64_helper.exe differ diff --git a/Shared/installer/locale/en_US.pot b/Shared/installer/locale/en_US.pot index 8769e23e5f..5ad1d78304 100644 --- a/Shared/installer/locale/en_US.pot +++ b/Shared/installer/locale/en_US.pot @@ -3,7 +3,7 @@ msgid "" msgstr "" "Project-Id-Version: MTA San Andreas Installer 1.x\n" "Report-Msgid-Bugs-To: \n" -"POT-Creation-Date: 2023-10-05 20:21\n" +"POT-Creation-Date: 2024-09-17 02:47\n" "PO-Revision-Date: YEAR-MO-DA HO:MI+ZONE\n" "Last-Translator: FULL NAME \n" "Language-Team: LANGUAGE \n" @@ -154,72 +154,72 @@ msgid "The client is the program you run to play on a Multi Theft Auto server" msgstr "" #. INST_CLIENTSERVER -#: Shared/installer/nightly.nsi:441 +#: Shared/installer/nightly.nsi:444 msgid "Client and Server" msgstr "" #. INST_SERVER -#: Shared/installer/nightly.nsi:442 +#: Shared/installer/nightly.nsi:445 msgid "Server only" msgstr "" #. INST_STARTMENU_GROUP -#: Shared/installer/nightly.nsi:456 +#: Shared/installer/nightly.nsi:459 msgid "Start menu group" msgstr "" #. INST_DESKTOP_ICON -#: Shared/installer/nightly.nsi:457 +#: Shared/installer/nightly.nsi:460 msgid "Desktop icon" msgstr "" #. INST_PROTOCOL -#: Shared/installer/nightly.nsi:458 +#: Shared/installer/nightly.nsi:461 msgid "Register mtasa:// protocol" msgstr "" #. INST_GAMES_EXPLORER -#: Shared/installer/nightly.nsi:459 +#: Shared/installer/nightly.nsi:462 msgid "Add to Games Explorer" msgstr "" #. INST_DIRECTX -#: Shared/installer/nightly.nsi:460 +#: Shared/installer/nightly.nsi:463 msgid "Install DirectX" msgstr "" #. INST_SEC_CLIENT -#: Shared/installer/nightly.nsi:494 +#: Shared/installer/nightly.nsi:497 msgid "Game client" msgstr "" #. INST_SEC_SERVER -#: Shared/installer/nightly.nsi:495 +#: Shared/installer/nightly.nsi:498 msgid "Dedicated server" msgstr "" #. INST_SEC_CORE -#: Shared/installer/nightly.nsi:496 +#: Shared/installer/nightly.nsi:499 msgid "Core components" msgstr "" #. INST_SEC_GAME -#: Shared/installer/nightly.nsi:497 +#: Shared/installer/nightly.nsi:500 msgid "Game module" msgstr "" #. INFO_INPLACE_UPGRADE -#: Shared/installer/nightly.nsi:499 +#: Shared/installer/nightly.nsi:502 msgid "Performing in-place upgrade..." msgstr "" #. INFO_UPDATE_PERMISSIONS -#: Shared/installer/nightly.nsi:500 +#: Shared/installer/nightly.nsi:503 msgid "Updating permissions. This could take a few minutes..." msgstr "" #. MSGBOX_INVALID_GTASA -#: Shared/installer/nightly.nsi:501 +#: Shared/installer/nightly.nsi:504 msgid "" "A valid Windows version of Grand Theft Auto: San Andreas was not detected.$\r" "$\n" @@ -229,44 +229,44 @@ msgid "" msgstr "" #. INST_SEC_CORE_RESOURCES -#: Shared/installer/nightly.nsi:504 +#: Shared/installer/nightly.nsi:507 msgid "Core Resources" msgstr "" #. INST_SEC_OPTIONAL_RESOURCES -#: Shared/installer/nightly.nsi:505 +#: Shared/installer/nightly.nsi:508 msgid "Optional Resources" msgstr "" #. INST_SEC_EDITOR -#: Shared/installer/nightly.nsi:506 +#: Shared/installer/nightly.nsi:509 msgid "Editor" msgstr "" #. INST_SEC_DEVELOPER -#: Shared/installer/nightly.nsi:976 +#: Shared/installer/nightly.nsi:986 msgid "Development" msgstr "" #. UNINST_SUCCESS -#: Shared/installer/nightly.nsi:1024 +#: Shared/installer/nightly.nsi:1034 msgid "$(^Name) was successfully removed from your computer." msgstr "" #. UNINST_FAIL -#: Shared/installer/nightly.nsi:1031 +#: Shared/installer/nightly.nsi:1041 msgid "Uninstallation has failed!" msgstr "" #. UNINST_REQUEST -#: Shared/installer/nightly.nsi:1039 +#: Shared/installer/nightly.nsi:1049 msgid "" "Are you sure you want to completely remove $(^Name) and all of its " "components?" msgstr "" #. UNINST_REQUEST_NOTE -#: Shared/installer/nightly.nsi:1040 +#: Shared/installer/nightly.nsi:1050 msgid "" "Uninstalling before update?$\r" "$\n" @@ -276,7 +276,7 @@ msgid "" msgstr "" #. UNINST_DATA_REQUEST -#: Shared/installer/nightly.nsi:1053 +#: Shared/installer/nightly.nsi:1063 msgid "" "Would you like to keep your data files (such as resources, screenshots and " "server configuration)? If you click no, any resources, configurations or " @@ -284,27 +284,27 @@ msgid "" msgstr "" #. UAC_RIGHTS1 -#: Shared/installer/nightly.nsi:1228 +#: Shared/installer/nightly.nsi:1246 msgid "This installer requires admin access, try again" msgstr "" #. UAC_RIGHTS_UN -#: Shared/installer/nightly.nsi:1229 +#: Shared/installer/nightly.nsi:1247 msgid "This uninstaller requires admin access, try again" msgstr "" #. UAC_RIGHTS3 -#: Shared/installer/nightly.nsi:1230 +#: Shared/installer/nightly.nsi:1248 msgid "Logon service not running, aborting!" msgstr "" #. UAC_RIGHTS4 -#: Shared/installer/nightly.nsi:1231 +#: Shared/installer/nightly.nsi:1249 msgid "Unable to elevate" msgstr "" #. INST_MTA_CONFLICT -#: Shared/installer/nightly.nsi:1827 +#: Shared/installer/nightly.nsi:1845 msgid "" "A different major version of MTA ($1) already exists at that path.$\n" "$\n" @@ -313,7 +313,7 @@ msgid "" msgstr "" #. INST_GTA_CONFLICT -#: Shared/installer/nightly.nsi:1831 +#: Shared/installer/nightly.nsi:1849 msgid "" "MTA cannot be installed into the same directory as GTA:SA.$\n" "$\n" @@ -322,7 +322,7 @@ msgid "" msgstr "" #. INST_GTA_ERROR1 -#: Shared/installer/nightly.nsi:1834 +#: Shared/installer/nightly.nsi:1852 msgid "" "The selected directory does not exist.$\n" "$\n" @@ -330,7 +330,7 @@ msgid "" msgstr "" #. INST_GTA_ERROR2 -#: Shared/installer/nightly.nsi:1836 +#: Shared/installer/nightly.nsi:1854 msgid "" "Could not find GTA:SA installed at $GTA_DIR $\n" "$\n" @@ -338,19 +338,19 @@ msgid "" msgstr "" #. INST_CHOOSE_LOC_TOP -#: Shared/installer/nightly.nsi:1954 +#: Shared/installer/nightly.nsi:1972 msgid "Choose Install Location" msgstr "" #. INST_CHOOSE_LOC -#: Shared/installer/nightly.nsi:1955 +#: Shared/installer/nightly.nsi:1973 msgid "" "Choose the folder in which to install ${PRODUCT_NAME_NO_VER} " "${PRODUCT_VERSION}" msgstr "" #. INST_CHOOSE_LOC2 -#: Shared/installer/nightly.nsi:1956 +#: Shared/installer/nightly.nsi:1974 msgid "" "${PRODUCT_NAME_NO_VER} ${PRODUCT_VERSION} will be installed in the following folder.$\n" "To install in a different folder, click Browse and select another folder.$\n" @@ -359,63 +359,63 @@ msgid "" msgstr "" #. INST_CHOOSE_LOC3 -#: Shared/installer/nightly.nsi:1958 +#: Shared/installer/nightly.nsi:1976 msgid "Destination Folder" msgstr "" #. INST_CHOOSE_LOC_BROWSE -#: Shared/installer/nightly.nsi:1959 +#: Shared/installer/nightly.nsi:1977 msgid "Browse..." msgstr "" #. INST_CHOOSE_LOC_DEFAULT -#: Shared/installer/nightly.nsi:1960 +#: Shared/installer/nightly.nsi:1978 msgid "Default" msgstr "" #. INST_CHOOSE_LOC_LAST_USED -#: Shared/installer/nightly.nsi:1961 +#: Shared/installer/nightly.nsi:1979 msgid "Last used" msgstr "" #. INST_CHOOSE_LOC_CUSTOM -#: Shared/installer/nightly.nsi:1962 +#: Shared/installer/nightly.nsi:1980 msgid "Custom" msgstr "" #. INST_CHOOSE_LOC4 -#: Shared/installer/nightly.nsi:2140 +#: Shared/installer/nightly.nsi:2158 msgid "" "Select the folder to install ${PRODUCT_NAME_NO_VER} ${PRODUCT_VERSION} in:" msgstr "" #. INST_LOC_OW -#: Shared/installer/nightly.nsi:2158 +#: Shared/installer/nightly.nsi:2176 msgid "" "Warning: A different major version of MTA ($1) already exists at that path." msgstr "" #. INST_LOC_UPGRADE -#: Shared/installer/nightly.nsi:2159 +#: Shared/installer/nightly.nsi:2177 msgid "Installation type: Upgrade" msgstr "" #. NETTEST_TITLE1 -#: Shared/installer/nightly.nsi:2393 +#: Shared/installer/nightly.nsi:2411 msgid "Online update" msgstr "" #. NETTEST_TITLE2 -#: Shared/installer/nightly.nsi:2394 +#: Shared/installer/nightly.nsi:2412 msgid "Checking for update information" msgstr "" #. NETTEST_STATUS1 -#: Shared/installer/nightly.nsi:2395 +#: Shared/installer/nightly.nsi:2413 msgid "Checking for installer update information..." msgstr "" #. NETTEST_STATUS2 -#: Shared/installer/nightly.nsi:2396 +#: Shared/installer/nightly.nsi:2414 msgid "Please ensure your firewall is not blocking" msgstr "" diff --git a/Shared/installer/nightly.nsi b/Shared/installer/nightly.nsi index 33823f46e9..d270a0d719 100644 --- a/Shared/installer/nightly.nsi +++ b/Shared/installer/nightly.nsi @@ -369,6 +369,9 @@ Function .onInstSuccess WriteRegStr HKLM "SOFTWARE\Multi Theft Auto: San Andreas All\Common" "GTA:SA Path" $GTA_DIR WriteRegStr HKLM "SOFTWARE\Multi Theft Auto: San Andreas All\${0.0}" "Last Install Location" $INSTDIR + + # Add 'MaxLoaderThreads' DWORD value for gta_sa.exe to disable multi-threaded loading of DLLs. + WriteRegDWORD HKLM "SOFTWARE\Microsoft\Windows NT\CurrentVersion\Image File Execution Options\gta_sa.exe" "MaxLoaderThreads" 1 # Initilize variables holding paths and names Call MTAInitFileNamesAndPaths @@ -664,11 +667,13 @@ SectionGroup /e "$(INST_SEC_CLIENT)" SECGCLIENT File "${FILES_ROOT}\mta\tags.dll" SetOutPath "$INSTDIR\MTA" - File "${FILES_ROOT}\mta\chrome_elf.dll" + File "${FILES_ROOT}\mta\chrome_elf.dll" File "${FILES_ROOT}\mta\libcef.dll" File "${FILES_ROOT}\mta\icudtl.dat" File "${FILES_ROOT}\mta\libEGL.dll" File "${FILES_ROOT}\mta\libGLESv2.dll" + File "${FILES_ROOT}\mta\vk_swiftshader.dll" + File "${FILES_ROOT}\mta\vulkan-1.dll" File "${FILES_ROOT}\mta\snapshot_blob.bin" File "${FILES_ROOT}\mta\v8_context_snapshot.bin" @@ -683,9 +688,12 @@ SectionGroup /e "$(INST_SEC_CLIENT)" SECGCLIENT # Added as per https://bitbucket.org/chromiumembedded/cef/commits/8424f166ccef - File "${FILES_ROOT}\mta\CEF\chrome_100_percent.pak" - File "${FILES_ROOT}\mta\CEF\chrome_200_percent.pak" - File "${FILES_ROOT}\mta\CEF\resources.pak" + # Not currently using \mta\cef\ due to https://github.com/chromiumembedded/cef/issues/3749#issuecomment-2278568964 (it's already crashing and likely won't remain supported) + SetOutPath "$INSTDIR\MTA" + + File "${FILES_ROOT}\mta\chrome_100_percent.pak" + File "${FILES_ROOT}\mta\chrome_200_percent.pak" + File "${FILES_ROOT}\mta\resources.pak" # Clarification for the below 4 deprecated files: https://bitbucket.org/chromiumembedded/cef/commits/8424f166ccef #File "${FILES_ROOT}\mta\CEF\cef.pak" @@ -847,6 +855,8 @@ SectionGroup /e "$(INST_SEC_SERVER)" SECGSERVER File "${SERVER_FILES_ROOT}\mods\deathmatch\dbconmy.dll" !ifndef LIGHTBUILD File "${SERVER_FILES_ROOT}\mods\deathmatch\libmysql.dll" + File "${SERVER_FILES_ROOT}\mods\deathmatch\libcrypto-3.dll" + File "${SERVER_FILES_ROOT}\mods\deathmatch\libssl-3.dll" !endif ;Only overwrite the following files if previous versions were bugged and explicitly need replacing @@ -1081,6 +1091,8 @@ Section Uninstall Delete "$INSTDIR\server\mods\deathmatch\dbconmy.dll" Delete "$INSTDIR\server\mods\deathmatch\deathmatch.dll" Delete "$INSTDIR\server\mods\deathmatch\libmysql.dll" + Delete "$INSTDIR\server\mods\deathmatch\libcrypto-3.dll" + Delete "$INSTDIR\server\mods\deathmatch\libssl-3.dll" Delete "$INSTDIR\server\mods\deathmatch\lua5.1.dll" Delete "$INSTDIR\server\mods\deathmatch\pcre3.dll" @@ -1095,6 +1107,8 @@ Section Uninstall Delete "$INSTDIR\server\x64\dbconmy.dll" Delete "$INSTDIR\server\x64\deathmatch.dll" Delete "$INSTDIR\server\x64\libmysql.dll" + Delete "$INSTDIR\server\x64\libcrypto-3-x64.dll" + Delete "$INSTDIR\server\x64\libssl-3-x64.dll" Delete "$INSTDIR\server\x64\lua5.1.dll" Delete "$INSTDIR\server\x64\pcre3.dll" RmDir "$INSTDIR\server\x64" @@ -1134,6 +1148,10 @@ Section Uninstall DeleteRegKey HKCR "mtasa" ${EndIf} + # Remove 'MaxLoaderThreads' DWORD value for gta_sa.exe. + DeleteRegValue HKLM "SOFTWARE\Microsoft\Windows NT\CurrentVersion\Image File Execution Options\gta_sa.exe" "MaxLoaderThreads" + DeleteRegKey /ifempty HKLM "SOFTWARE\Microsoft\Windows NT\CurrentVersion\Image File Execution Options\gta_sa.exe" + ${GameExplorer_RemoveGame} ${GUID} ; Delete client shortcuts diff --git a/Shared/mods/deathmatch/logic/CDebugHookManager.cpp b/Shared/mods/deathmatch/logic/CDebugHookManager.cpp index e4f0d92311..b083746acc 100644 --- a/Shared/mods/deathmatch/logic/CDebugHookManager.cpp +++ b/Shared/mods/deathmatch/logic/CDebugHookManager.cpp @@ -654,12 +654,13 @@ bool CDebugHookManager::CallHook(const char* szName, const std::vectorGetType() == LUA_TSTRING) { - if (returnedValue->GetString() == "skip") + // We don't want to skip the creation of new debug hooks + if (returnedValue->GetString() == "skip" && strcmp(szName, "addDebugHook")) bSkip = true; } } diff --git a/Shared/mods/deathmatch/logic/CScriptDebugging.cpp b/Shared/mods/deathmatch/logic/CScriptDebugging.cpp index 8b66520b1a..701ef435bb 100644 --- a/Shared/mods/deathmatch/logic/CScriptDebugging.cpp +++ b/Shared/mods/deathmatch/logic/CScriptDebugging.cpp @@ -20,6 +20,23 @@ #define MAX_STRING_LENGTH 2048 +enum DebugScriptLevels : std::uint8_t +{ + NONE, + ERRORS_ONLY, + ERRORS_AND_WARNINGS, + ALL, +}; + +enum DebugMessageLevels : std::uint8_t +{ + MESSAGE_TYPE_DEBUG, + MESSAGE_TYPE_ERROR, + MESSAGE_TYPE_WARNING, + MESSAGE_TYPE_INFO, + MESSAGE_TYPE_CUSTOM, +}; + // Handle filename/line number in string void CScriptDebugging::LogPCallError(lua_State* luaVM, const SString& strRes, bool bInitialCall) { @@ -51,6 +68,28 @@ void CScriptDebugging::LogPCallError(lua_State* luaVM, const SString& strRes, bo } } +bool CScriptDebugging::CheckForSufficientDebugLevel(std::uint8_t playerDebugLevel, std::uint8_t messageDebugLevel) const noexcept +{ + bool sufficientDebugLevel = false; + + switch (messageDebugLevel) + { + case MESSAGE_TYPE_ERROR: + sufficientDebugLevel = (playerDebugLevel >= ERRORS_ONLY); + break; + case MESSAGE_TYPE_WARNING: + sufficientDebugLevel = (playerDebugLevel >= ERRORS_AND_WARNINGS); + break; + case MESSAGE_TYPE_INFO: + case MESSAGE_TYPE_CUSTOM: + case MESSAGE_TYPE_DEBUG: + sufficientDebugLevel = (playerDebugLevel == ALL); + break; + } + + return sufficientDebugLevel; +} + void CScriptDebugging::LogCustom(lua_State* luaVM, unsigned char ucRed, unsigned char ucGreen, unsigned char ucBlue, const char* szFormat, ...) { assert(szFormat); @@ -62,8 +101,7 @@ void CScriptDebugging::LogCustom(lua_State* luaVM, unsigned char ucRed, unsigned VSNPRINTF(szBuffer, MAX_STRING_LENGTH, szFormat, marker); va_end(marker); - SLuaDebugInfo luaDebugInfo; - LogString("", luaDebugInfo, szBuffer, 0, ucRed, ucGreen, ucBlue); + LogString("", GetLuaDebugInfo(luaVM), szBuffer, 4, ucRed, ucGreen, ucBlue); } void CScriptDebugging::LogDebug(lua_State* luaVM, unsigned char ucRed, unsigned char ucGreen, unsigned char ucBlue, const char* szFormat, ...) diff --git a/Shared/mods/deathmatch/logic/CTickRateSettings.h b/Shared/mods/deathmatch/logic/CTickRateSettings.h index 80cfcdb23b..0a199af241 100644 --- a/Shared/mods/deathmatch/logic/CTickRateSettings.h +++ b/Shared/mods/deathmatch/logic/CTickRateSettings.h @@ -25,6 +25,7 @@ struct CTickRateSettings iNearListUpdate = 100; iPedSyncerDistance = 100; iUnoccupiedVehicleSyncerDistance = 130; + iVehicleContactSyncRadius = 30; } int iPureSync; @@ -39,6 +40,7 @@ struct CTickRateSettings int iNearListUpdate; int iPedSyncerDistance; int iUnoccupiedVehicleSyncerDistance; + int iVehicleContactSyncRadius; }; extern CTickRateSettings g_TickRateSettings; diff --git a/Shared/mods/deathmatch/logic/Enums.cpp b/Shared/mods/deathmatch/logic/Enums.cpp index f81cc6a364..1e3d0b2003 100644 --- a/Shared/mods/deathmatch/logic/Enums.cpp +++ b/Shared/mods/deathmatch/logic/Enums.cpp @@ -67,6 +67,8 @@ IMPLEMENT_ENUM_CLASS_BEGIN(StringEncodeFunction) ADD_ENUM(StringEncodeFunction::TEA, "tea") ADD_ENUM(StringEncodeFunction::AES128, "aes128") ADD_ENUM(StringEncodeFunction::RSA, "rsa") +ADD_ENUM(StringEncodeFunction::BASE64, "base64") +ADD_ENUM(StringEncodeFunction::BASE32, "base32") IMPLEMENT_ENUM_CLASS_END("string-encode-function") IMPLEMENT_ENUM_CLASS_BEGIN(KeyPairAlgorithm) @@ -96,6 +98,9 @@ ADD_ENUM(WorldSpecialProperty::CORONAZTEST, "coronaztest") ADD_ENUM(WorldSpecialProperty::WATERCREATURES, "watercreatures") ADD_ENUM(WorldSpecialProperty::BURNFLIPPEDCARS, "burnflippedcars") ADD_ENUM(WorldSpecialProperty::FIREBALLDESTRUCT, "fireballdestruct") +ADD_ENUM(WorldSpecialProperty::EXTENDEDWATERCANNONS, "extendedwatercannons") +ADD_ENUM(WorldSpecialProperty::ROADSIGNSTEXT, "roadsignstext") +ADD_ENUM(WorldSpecialProperty::TUNNELWEATHERBLEND, "tunnelweatherblend") IMPLEMENT_ENUM_CLASS_END("world-special-property") IMPLEMENT_ENUM_BEGIN(ePacketID) diff --git a/Shared/mods/deathmatch/logic/Enums.h b/Shared/mods/deathmatch/logic/Enums.h index 92a8e8bf9f..e975d0d907 100644 --- a/Shared/mods/deathmatch/logic/Enums.h +++ b/Shared/mods/deathmatch/logic/Enums.h @@ -88,6 +88,9 @@ enum class WorldSpecialProperty WATERCREATURES, BURNFLIPPEDCARS, FIREBALLDESTRUCT, + ROADSIGNSTEXT, + EXTENDEDWATERCANNONS, + TUNNELWEATHERBLEND, }; DECLARE_ENUM_CLASS(WorldSpecialProperty); diff --git a/Shared/mods/deathmatch/logic/Utils.cpp b/Shared/mods/deathmatch/logic/Utils.cpp index 04076419c0..db09989cd1 100644 --- a/Shared/mods/deathmatch/logic/Utils.cpp +++ b/Shared/mods/deathmatch/logic/Utils.cpp @@ -92,6 +92,24 @@ bool IsValidFilePath(const char* szDir) return true; } +bool IsValidFilePath(const char* szDir, size_t length) +{ + if (szDir == nullptr) + return false; + + std::uint8_t c, c_d; + + // iterate through the char array + for (size_t i = 0; i < length; i++) + { + c = szDir[i]; // current character + c_d = (i < (length - 1)) ? szDir[i + 1] : 0; // one character ahead, if any + if (!IsVisibleCharacter(c) || c == ':' || (c == '.' && c_d == '.') || (c == '\\' && c_d == '\\')) + return false; + } + return true; +} + void ReplaceOccurrencesInString(std::string& s, const char* a, const char* b) { int idx = 0; @@ -435,65 +453,6 @@ SString GetDataUnit(unsigned long long ullInput) return strUnknown; } -#ifdef MTA_DEBUG -struct ReleaseVirtualMemory -{ - HANDLE process; - - ReleaseVirtualMemory(HANDLE process_) : process(process_) {} - - void operator()(void* p) const noexcept - { - if (p) - VirtualFreeEx(process, p, 0, MEM_RELEASE); - } -}; - -using VirtualMemoryScope = std::unique_ptr; - -bool RemoteLoadLibrary(HANDLE hProcess, const char* szLibPath) -{ - if (!szLibPath || !szLibPath[0]) - return false; - - HMODULE kernel32 = GetModuleHandleA("kernel32"); - - if (!kernel32) - return false; - - // Allocate memory in the remote process for the library path - size_t libraryPathSize = strlen(szLibPath) + 1; - void* remoteLibraryPath = VirtualAllocEx(hProcess, nullptr, libraryPathSize, MEM_COMMIT | MEM_RESERVE, PAGE_READWRITE); - - if (!remoteLibraryPath) - return false; - - VirtualMemoryScope remoteMemory(remoteLibraryPath, ReleaseVirtualMemory{hProcess}); - - // Write the DLL library path to the remote allocation - DWORD byteswritten = 0; - WriteProcessMemory(hProcess, remoteLibraryPath, static_cast(szLibPath), libraryPathSize, &byteswritten); - - if (byteswritten != libraryPathSize) - return false; - - // Start a remote thread executing LoadLibraryA exported from Kernel32. Passing the - // remotely allocated path buffer as an argument to that thread (and also to LoadLibraryA) - // will make the remote process load the DLL into it's userspace (giving the DLL full - // access to the game executable). - HANDLE remoteThread = CreateRemoteThread( - hProcess, nullptr, 0, static_cast(static_cast(GetProcAddress(kernel32, "LoadLibraryA"))), remoteLibraryPath, 0, nullptr); - - if (!remoteThread) - return false; - - // We wait for the created remote thread to finish executing. When it's done, the DLL - // is loaded into the game's userspace, and we can destroy the thread-handle. - WaitForSingleObject(remoteThread, INFINITE); - return true; -} - -#endif #else bool IsValidFilePath(const char* szDir) { @@ -518,6 +477,24 @@ bool IsValidFilePath(const char* szDir) return true; } +bool IsValidFilePath(const char* szDir, size_t length) +{ + if (szDir == nullptr) + return false; + + std::uint8_t c, c_d; + + // iterate through the char array + for (size_t i = 0; i < length; i++) + { + c = szDir[i]; // current character + c_d = (i < (length - 1)) ? szDir[i + 1] : 0; // one character ahead, if any + if (!IsVisibleCharacter(c) || c == ':' || (c == '.' && c_d == '.') || (c == '\\' && c_d == '\\')) + return false; + } + return true; +} + bool IsValidOrganizationPath(const char* szDir) { if (szDir == NULL) diff --git a/Shared/mods/deathmatch/logic/Utils.h b/Shared/mods/deathmatch/logic/Utils.h index 43f71aab54..b42e12f8b4 100644 --- a/Shared/mods/deathmatch/logic/Utils.h +++ b/Shared/mods/deathmatch/logic/Utils.h @@ -136,6 +136,7 @@ double GetRandomDouble(); int GetRandom(int iLow, int iHigh); bool IsValidFilePath(const char* szPath); +bool IsValidFilePath(const char* szDir, size_t length); bool IsValidOrganizationPath(const char* szPath); #endif @@ -233,6 +234,15 @@ inline float GetOffsetDegrees(float a, float b) c = (360.0f + c); return c; } +inline float GetOffsetRadians(float a, float b) +{ + float c = (b > a) ? b - a : 0.0f - (a - b); + if (c > PI) + c = 0.0f - (2 * PI - c); + else if (c <= -PI) + c = (2 * PI + c); + return c; +} // Assuming fValue is the result of a difference calculation, calculate // the shortest positive distance after wrapping @@ -246,12 +256,29 @@ inline float GetSmallestWrapUnsigned(float fValue, float fHigh) void RotateVector(CVector& vecLine, const CVector& vecRotation); +inline void ConvertZXYEulersToQuaternion(const CVector& vecFrom, CVector4D &vecTo) +{ + const float c1 = cos(vecFrom.fX * 0.5f); + const float c2 = cos(vecFrom.fY * 0.5f); + const float c3 = cos(vecFrom.fZ * 0.5f); + + const float s1 = sin(vecFrom.fX * 0.5f); + const float s2 = sin(vecFrom.fY * 0.5f); + const float s3 = sin(vecFrom.fZ * 0.5f); + + vecTo.fX = s1 * c2 * c3 - c1 * s2 * s3; + vecTo.fY = c1 * s2 * c3 + s1 * c2 * s3; + vecTo.fZ = c1 * c2 * s3 + s1 * s2 * c3; + vecTo.fW = c1 * c2 * c3 - s1 * s2 * s3; +} + #ifdef MTA_CLIENT // Misc utility functions unsigned int StripUnwantedCharacters(char* szText, unsigned char cReplace = ' '); unsigned int StripControlCodes(char* szText, unsigned char cReplace = ' '); bool IsControlCode(unsigned char c); bool IsValidFilePath(const char* szDir); +bool IsValidFilePath(const char* szDir, size_t length); void ReplaceOccurrencesInString(std::string& s, const char* a, const char* b); void RaiseFatalError(unsigned int uiCode); @@ -325,8 +352,3 @@ void DeletePointersAndClearList(T& elementList) delete *iter; } } - -// for debug -#if defined(MTA_DEBUG) && defined(MTA_CLIENT) -bool RemoteLoadLibrary(HANDLE hProcess, const char* szLibPath); -#endif diff --git a/Shared/mods/deathmatch/logic/lua/CLuaFunctionParser.h b/Shared/mods/deathmatch/logic/lua/CLuaFunctionParser.h index db8056763d..fef13d708b 100644 --- a/Shared/mods/deathmatch/logic/lua/CLuaFunctionParser.h +++ b/Shared/mods/deathmatch/logic/lua/CLuaFunctionParser.h @@ -19,6 +19,22 @@ class CLuaArgument; #include "lua/LuaBasic.h" #include +class LuaFunctionError +{ +protected: + const char* m_message; + bool m_bWarning; + +public: + constexpr LuaFunctionError(const char* what, bool throwWarning = true) noexcept + : m_message(what), m_bWarning(throwWarning) {} + + constexpr const char* what() const noexcept { return m_message; } + constexpr bool IsWarning() const noexcept { return m_bWarning; } +}; + +using LuaVarArgs = std::optional; + struct CLuaFunctionParserBase { // iIndex is passed around by reference @@ -33,7 +49,7 @@ struct CLuaFunctionParserBase void TypeToNameVariant(SString& accumulator) { using param = typename is_variant::param1_t; - if (accumulator.length() == 0) + if (accumulator.empty()) accumulator = TypeToName(); else accumulator += "/" + TypeToName(); @@ -45,7 +61,7 @@ struct CLuaFunctionParserBase template SString TypeToName() { - if constexpr (std::is_same_v || std::is_same_v) + if constexpr (std::is_same_v || std::is_same_v || std::is_same_v || std::is_same_v) return "string"; else if constexpr (std::is_same_v) return "boolean"; @@ -60,6 +76,8 @@ struct CLuaFunctionParserBase } else if constexpr (std::is_same_v) return "value"; + else if constexpr (std::is_same_v) + return "values"; else if constexpr (is_2specialization::value) return "table"; else if constexpr (is_5specialization::value) @@ -90,6 +108,8 @@ struct CLuaFunctionParserBase return ""; else if constexpr (std::is_same_v) return ""; + else + static_assert(sizeof(T) == 0, "Invalid parameter type provided to CLuaFunctionParser!"); } // Reads the parameter type (& value in some cases) at a given index @@ -116,10 +136,8 @@ struct CLuaFunctionParserBase // Avoid printing binary data if (std::find_if(strValue.begin(), strValue.end(), [](char ch) { return !(std::isprint(ch)); }) != strValue.end()) return "string"; - else - { - return SString("string (\"%s\")", strValue.c_str()); - } + + return SString("string (\"%s\")", strValue.c_str()); } case LUA_TBOOLEAN: return SString("boolean (%s)", lua_toboolean(L, index) == 1 ? "true" : "false"); @@ -145,14 +163,13 @@ struct CLuaFunctionParserBase template T Pop(lua_State* L, int& index) { - if (!TypeMatch(L, index)) - { - SString strReceived = ReadParameterAsString(L, index); - SString strExpected = TypeToName(); - SetBadArgumentError(L, strExpected, index, strReceived); - return T{}; - } - return PopUnsafe(L, index); + if (TypeMatch(L, index)) + return PopUnsafe(L, index); + + SString strReceived = ReadParameterAsString(L, index); + SString strExpected = TypeToName(); + SetBadArgumentError(L, strExpected, index, strReceived); + return T{}; } // Special type matcher for variants. Returns -1 if the type does not match @@ -192,56 +209,59 @@ struct CLuaFunctionParserBase // primitive types if constexpr (std::is_same_v || std::is_same_v) return (iArgument == LUA_TSTRING || iArgument == LUA_TNUMBER); - if constexpr (std::is_same_v) + else if constexpr (std::is_same_v) return (iArgument == LUA_TBOOLEAN); - if constexpr (std::is_arithmetic_v) + else if constexpr (std::is_arithmetic_v) return lua_isnumber(L, index); // Advanced types // Enums are represented as strings to Lua - if constexpr (std::is_enum_v) + else if constexpr (std::is_enum_v) return iArgument == LUA_TSTRING; // CLuaArgument can hold any value - if constexpr (std::is_same_v) + else if constexpr (std::is_same_v) + return iArgument != LUA_TNONE; + + else if constexpr (std::is_same_v) return iArgument != LUA_TNONE; // All color classes are read as a single tocolor number // Do not be tempted to change this to is_base_of // SColorARGB etc are only **constructors** for SColor! - if constexpr (std::is_same_v) + else if constexpr (std::is_same_v) return lua_isnumber(L, index); // std::optional is used for optional parameters // which may also be in the middle of a parameter list // therefore it is always valid to attempt to read an // optional - if constexpr (is_specialization::value) + else if constexpr (is_specialization::value) return true; // std::vector is used for arrays built from tables - if constexpr (is_2specialization::value) + else if constexpr (is_2specialization::value) return iArgument == LUA_TTABLE; // std::unordered_map is used for maps built from tables - if constexpr (is_5specialization::value) + else if constexpr (is_5specialization::value) return iArgument == LUA_TTABLE; // CLuaFunctionRef is used for functions - if constexpr (std::is_same_v) + else if constexpr (std::is_same_v) return iArgument == LUA_TFUNCTION; // lua_State* can be taken as first argument of any function - if constexpr (std::is_same_v) + else if constexpr (std::is_same_v) return index == 1; // variants can be used by any of the underlying types // thus recursively use this function - if constexpr (is_variant::value) + else if constexpr (is_variant::value) return TypeMatchVariant(L, index) != -1; // Vector2 may either be represented by CLuaVector or by two numbers - if constexpr (std::is_same_v) + else if constexpr (std::is_same_v) { if (lua_isnumber(L, index) && lua_isnumber(L, index + 1)) return true; @@ -249,7 +269,7 @@ struct CLuaFunctionParserBase } // Vector3 may either be represented by CLuaVector or by three numbers - if constexpr (std::is_same_v) + else if constexpr (std::is_same_v) { if (lua_isnumber(L, index) && lua_isnumber(L, index + 1) && lua_isnumber(L, index + 2)) return true; @@ -257,14 +277,14 @@ struct CLuaFunctionParserBase } // Vector4 may either be represented by CLuaVector or by three numbers - if constexpr (std::is_same_v) + else if constexpr (std::is_same_v) { if (lua_isnumber(L, index) && lua_isnumber(L, index + 1) && lua_isnumber(L, index + 2) && lua_isnumber(L, index + 3)) return true; return iArgument == LUA_TUSERDATA || iArgument == LUA_TLIGHTUSERDATA; } // CMatrix may either be represented by 3 CLuaVector or by 12 numbers - if constexpr (std::is_same_v) + else if constexpr (std::is_same_v) { for (int i = 0; i < sizeof(CMatrix) / sizeof(float); i++) { @@ -275,16 +295,16 @@ struct CLuaFunctionParserBase } // Catch all for class pointer types, assume all classes are valid script entities // and can be fetched from a userdata - if constexpr (std::is_pointer_v && std::is_class_v>) + else if constexpr (std::is_pointer_v && std::is_class_v>) return iArgument == LUA_TUSERDATA || iArgument == LUA_TLIGHTUSERDATA; // dummy type is used as overload extension if one overload has fewer arguments // thus it is only allowed if there are no further args on the Lua side - if constexpr (std::is_same_v) + else if constexpr (std::is_same_v) return iArgument == LUA_TNONE; // no value - if constexpr (std::is_same_v) + else if constexpr (std::is_same_v) return iArgument == LUA_TNONE; } @@ -356,11 +376,12 @@ struct CLuaFunctionParserBase return lua::PopPrimitive(L, index); else if constexpr (std::is_same_v) return lua::PopPrimitive(L, index); - else if constexpr (std::is_integral_v || std::is_floating_point_v) // bool is an integral type, so must pop it before ^^ + else if constexpr (std::is_integral_v || std::is_floating_point_v) // bool is an integral type, so must pop it before ^^ { const auto number = lua::PopPrimitive(L, index); - const auto SetError = [&](const char* expected, const char* got) { + const auto SetError = [&](const char* expected, const char* got) + { // Subtract one from the index, as the call to lua::PopPrimitive above increments the index, even if the // underlying element is of a wrong type SetBadArgumentError(L, expected, index - 1, got); @@ -372,7 +393,8 @@ struct CLuaFunctionParserBase return static_cast(number); } - if (std::isinf(number)) { + if (std::isinf(number)) + { SetError("number", "inf"); return static_cast(number); } @@ -381,7 +403,8 @@ struct CLuaFunctionParserBase // For now this doesn't do all the safety checks, but this should be "good enough" [until we switch to C++20] if constexpr (std::is_integral_v && std::is_unsigned_v) { - if (number < 0) { + if (number < 0) + { SetError("positive number", "negative"); return static_cast(number); } @@ -396,15 +419,13 @@ struct CLuaFunctionParserBase T eValue; if (StringToEnum(strValue, eValue)) return eValue; - else - { - // Subtract one from the index, as the call to lua::PopPrimitive above increments the index, even if the - // underlying element is of a wrong type - SString strReceived = ReadParameterAsString(L, index - 1); - SString strExpected = GetEnumTypeName((T)0); - SetBadArgumentError(L, strExpected, index - 1, strReceived); - return static_cast(0); - } + + // Subtract one from the index, as the call to lua::PopPrimitive above increments the index, even if the + // underlying element is of a wrong type + SString strReceived = ReadParameterAsString(L, index - 1); + SString strExpected = GetEnumTypeName((T)0); + SetBadArgumentError(L, strExpected, index - 1, strReceived); + return static_cast(0); } else if constexpr (is_specialization::value) { @@ -462,7 +483,7 @@ struct CLuaFunctionParserBase continue; } - int i = -2; + int i = -2; // When key_t is a string and the actual type of a key is number Lua will conduct an implicit value change // that can confuse lua_next and lead to a crash. To fix it we can copy a key in order to save an original key @@ -470,7 +491,7 @@ struct CLuaFunctionParserBase lua_pushvalue(L, i); auto v = PopUnsafe(L, i); - auto k = PopUnsafe(L, i); + auto k = PopUnsafe(L, i); map.emplace(std::move(k), std::move(v)); lua_pop(L, 2); // drop values(key copy and value), keep original key for lua_next } @@ -481,27 +502,26 @@ struct CLuaFunctionParserBase { CLuaMain& luaMain = lua_getownercluamain(L); const void* pFuncPtr = lua_topointer(L, index); + CRefInfo* pInfo = MapFind(luaMain.m_CallbackTable, pFuncPtr); - if (CRefInfo* pInfo = MapFind(luaMain.m_CallbackTable, pFuncPtr)) + if (pInfo) { // Re-use the lua ref we already have to this function pInfo->ulUseCount++; ++index; return CLuaFunctionRef(L, pInfo->iFunction, pFuncPtr); } - else - { - // Get a lua ref to this function - lua_pushvalue(L, index); - int ref = luaL_ref(L, LUA_REGISTRYINDEX); - // Save ref info - CRefInfo info{1, ref}; - MapSet(luaMain.m_CallbackTable, pFuncPtr, info); + // Get a lua ref to this function + lua_pushvalue(L, index); + int ref = luaL_ref(L, LUA_REGISTRYINDEX); - ++index; - return CLuaFunctionRef(L, ref, pFuncPtr); - } + // Save ref info + CRefInfo info{1, ref}; + MapSet(luaMain.m_CallbackTable, pFuncPtr, info); + + ++index; + return CLuaFunctionRef(L, ref, pFuncPtr); } else if constexpr (std::is_same_v) return L; @@ -516,95 +536,78 @@ struct CLuaFunctionParserBase else if constexpr (std::is_same_v) { if (lua_isnumber(L, index)) - { - return { PopUnsafe(L, index), PopUnsafe(L, index) }; - } - else - { - int iType = lua_type(L, index); - bool isLightUserData = iType == LUA_TLIGHTUSERDATA; - void* pValue = lua::PopPrimitive(L, index); - auto cast = [isLightUserData, pValue, L](auto null) { - return isLightUserData ? UserDataCast(reinterpret_cast(pValue), L) - : UserDataCast(*reinterpret_cast(pValue), L); - }; - // A vector2 may also be filled from a vector3/vector4 - if (CLuaVector2D* pVec2D = cast((CLuaVector2D*)0); pVec2D != nullptr) - return *pVec2D; - if (CLuaVector3D* pVec3D = cast((CLuaVector3D*)0); pVec3D != nullptr) - return *pVec3D; - if (CLuaVector4D* pVec4D = cast((CLuaVector4D*)0); pVec4D != nullptr) - return *pVec4D; + return {PopUnsafe(L, index), PopUnsafe(L, index)}; - // Subtract one from the index, as the call to lua::PopPrimitive above increments the index, even if the - // underlying element is of a wrong type - SetBadArgumentError(L, "vector2", index - 1, pValue, isLightUserData); - return T{}; - } + int iType = lua_type(L, index); + bool isLightUserData = iType == LUA_TLIGHTUSERDATA; + void* pValue = lua::PopPrimitive(L, index); + auto cast = [isLightUserData, pValue, L](auto null) { + return isLightUserData ? UserDataCast(reinterpret_cast(pValue), L) + : UserDataCast(*reinterpret_cast(pValue), L); + }; + // A vector2 may also be filled from a vector3/vector4 + if (CLuaVector2D* pVec2D = cast((CLuaVector2D*)0); pVec2D != nullptr) + return *pVec2D; + if (CLuaVector3D* pVec3D = cast((CLuaVector3D*)0); pVec3D != nullptr) + return *pVec3D; + if (CLuaVector4D* pVec4D = cast((CLuaVector4D*)0); pVec4D != nullptr) + return *pVec4D; + + // Subtract one from the index, as the call to lua::PopPrimitive above increments the index, even if the + // underlying element is of a wrong type + SetBadArgumentError(L, "vector2", index - 1, pValue, isLightUserData); + return T{}; } else if constexpr (std::is_same_v) { if (lua_isnumber(L, index)) - { - return { PopUnsafe(L, index), PopUnsafe(L, index), PopUnsafe(L, index) }; - } - else - { - int iType = lua_type(L, index); - bool isLightUserData = iType == LUA_TLIGHTUSERDATA; - void* pValue = lua::PopPrimitive(L, index); - auto cast = [isLightUserData, pValue, L](auto null) { - return isLightUserData ? UserDataCast(reinterpret_cast(pValue), L) - : UserDataCast(*reinterpret_cast(pValue), L); - }; - // A vector3 may also be filled from a vector4 - if (CLuaVector3D* pVec3D = cast((CLuaVector3D*)0); pVec3D != nullptr) - return *pVec3D; - if (CLuaVector4D* pVec4D = cast((CLuaVector4D*)0); pVec4D != nullptr) - return *pVec4D; + return {PopUnsafe(L, index), PopUnsafe(L, index), PopUnsafe(L, index)}; - // Subtract one from the index, as the call to lua::PopPrimitive above increments the index, even if the - // underlying element is of a wrong type - SetBadArgumentError(L, "vector3", index - 1, pValue, isLightUserData); - return T{}; - } + int iType = lua_type(L, index); + bool isLightUserData = iType == LUA_TLIGHTUSERDATA; + void* pValue = lua::PopPrimitive(L, index); + auto cast = [isLightUserData, pValue, L](auto null) { + return isLightUserData ? UserDataCast(reinterpret_cast(pValue), L) + : UserDataCast(*reinterpret_cast(pValue), L); + }; + // A vector3 may also be filled from a vector4 + if (CLuaVector3D* pVec3D = cast((CLuaVector3D*)0); pVec3D != nullptr) + return *pVec3D; + if (CLuaVector4D* pVec4D = cast((CLuaVector4D*)0); pVec4D != nullptr) + return *pVec4D; + + // Subtract one from the index, as the call to lua::PopPrimitive above increments the index, even if the + // underlying element is of a wrong type + SetBadArgumentError(L, "vector3", index - 1, pValue, isLightUserData); + return T{}; } else if constexpr (std::is_same_v) { if (lua_isnumber(L, index)) - { - return { PopUnsafe(L, index), PopUnsafe(L, index), - PopUnsafe(L, index), PopUnsafe(L, index) }; - } - else - { - int iType = lua_type(L, index); - bool isLightUserData = iType == LUA_TLIGHTUSERDATA; - void* pValue = lua::PopPrimitive(L, index); - auto cast = [isLightUserData, pValue, L](auto null) { - return isLightUserData ? UserDataCast(reinterpret_cast(pValue), L) - : UserDataCast(*reinterpret_cast(pValue), L); - }; - // A vector3 may also be filled from a vector4 - if (CLuaVector4D* pVec4D = cast((CLuaVector4D*)0); pVec4D != nullptr) - return *pVec4D; - if (CLuaMatrix* pMatrix = cast((CLuaMatrix*)0); pMatrix != nullptr) - return *pMatrix; + return {PopUnsafe(L, index), PopUnsafe(L, index), PopUnsafe(L, index), PopUnsafe(L, index)}; - // Subtract one from the index, as the call to lua::PopPrimitive above increments the index, even if the - // underlying element is of a wrong type - SetBadArgumentError(L, "vector4", index - 1, pValue, isLightUserData); - return T{}; - } + int iType = lua_type(L, index); + bool isLightUserData = iType == LUA_TLIGHTUSERDATA; + void* pValue = lua::PopPrimitive(L, index); + auto cast = [isLightUserData, pValue, L](auto null) { + return isLightUserData ? UserDataCast(reinterpret_cast(pValue), L) + : UserDataCast(*reinterpret_cast(pValue), L); + }; + // A vector3 may also be filled from a vector4 + if (CLuaVector4D* pVec4D = cast((CLuaVector4D*)0); pVec4D != nullptr) + return *pVec4D; + + // Subtract one from the index, as the call to lua::PopPrimitive above increments the index, even if the + // underlying element is of a wrong type + SetBadArgumentError(L, "vector4", index - 1, pValue, isLightUserData); + return T{}; } else if constexpr (std::is_same_v) { if (lua_isnumber(L, index)) { - const auto ReadVector = [&] { - return CVector(PopUnsafe(L, index), PopUnsafe(L, index), PopUnsafe(L, index)); - }; - + const auto ReadVector = [&] { return CVector(PopUnsafe(L, index), PopUnsafe(L, index), PopUnsafe(L, index)); }; + CMatrix matrix; matrix.vRight = ReadVector(); @@ -614,24 +617,22 @@ struct CLuaFunctionParserBase return matrix; } - else - { - int iType = lua_type(L, index); - bool isLightUserData = iType == LUA_TLIGHTUSERDATA; - void* pValue = lua::PopPrimitive(L, index); - auto cast = [isLightUserData, pValue, L](auto null) { - return isLightUserData ? UserDataCast(reinterpret_cast(pValue), L) - : UserDataCast(*reinterpret_cast(pValue), L); - }; - // A vector4 may also be filled from a CLuaMatrix - if (CLuaMatrix* pMatrix = cast((CLuaMatrix*)0); pMatrix != nullptr) - return *pMatrix; - // Subtract one from the index, as the call to lua::PopPrimitive above increments the index, even if the - // underlying element is of a wrong type - SetBadArgumentError(L, "matrix", index - 1, pValue, isLightUserData); - return T{}; - } + int iType = lua_type(L, index); + bool isLightUserData = iType == LUA_TLIGHTUSERDATA; + void* pValue = lua::PopPrimitive(L, index); + auto cast = [isLightUserData, pValue, L](auto null) { + return isLightUserData ? UserDataCast(reinterpret_cast(pValue), L) + : UserDataCast(*reinterpret_cast(pValue), L); + }; + // A vector4 may also be filled from a CLuaMatrix + if (CLuaMatrix* pMatrix = cast((CLuaMatrix*)0); pMatrix != nullptr) + return *pMatrix; + + // Subtract one from the index, as the call to lua::PopPrimitive above increments the index, even if the + // underlying element is of a wrong type + SetBadArgumentError(L, "matrix", index - 1, pValue, isLightUserData); + return T{}; } // Catch all for class pointer types, assume all classes are valid script entities // and can be fetched from a userdata @@ -641,14 +642,13 @@ struct CLuaFunctionParserBase void* pValue = lua::PopPrimitive(L, index); using class_t = std::remove_pointer_t; auto result = isLightUserData ? UserDataCast((class_t*)pValue, L) : UserDataCast(*reinterpret_cast(pValue), L); - if (result == nullptr) - { - // Subtract one from the index, as the call to lua::PopPrimitive above increments the index, even if the - // underlying element is of a wrong type - SetBadArgumentError(L, index - 1, pValue, isLightUserData); - return nullptr; - } - return static_cast(result); + if (result) + return static_cast(result); + + // Subtract one from the index, as the call to lua::PopPrimitive above increments the index, even if the + // underlying element is of a wrong type + SetBadArgumentError(L, index - 1, pValue, isLightUserData); + return nullptr; } else if constexpr (std::is_same_v) return static_cast(static_cast(lua::PopPrimitive(L, index))); @@ -658,6 +658,12 @@ struct CLuaFunctionParserBase argument.Read(L, index++); return argument; } + else if constexpr (std::is_same_v) + { + CLuaArguments argument; + argument.ReadArguments(L, index); + return argument; + } else if constexpr (std::is_same_v) { return T{}; @@ -676,10 +682,9 @@ struct CLuaFunctionParser : CLuaFunctionP template auto Call(lua_State* L, Params&&... ps) { - if (strError.length() != 0) - { + if (!strError.empty()) return -1; - } + if constexpr (sizeof...(Params) == sizeof...(Args)) { if constexpr (std::is_same_v) @@ -724,31 +729,35 @@ struct CLuaFunctionParser : CLuaFunctionP int operator()(lua_State* L, CScriptDebugging* pScriptDebugging) { - int iResult = 0; + int iResult = 0; + bool bIsWarning = false; try { iResult = Call(L); } - catch (std::invalid_argument& e) + catch (std::logic_error& e) { // This exception can be thrown from the called function // as an additional way to provide further argument errors strError = e.what(); } - if (strError.length() != 0) + catch (LuaFunctionError& e) { - if constexpr (ErrorOnFailure) - { - luaL_error(L, strError.c_str()); - } - else - { - pScriptDebugging->LogCustom(L, strError.c_str()); - lua::Push(L, ReturnOnFailure); - } + strError = e.what(); + bIsWarning = e.IsWarning(); + } + if (strError.empty()) + return iResult; + + if (ErrorOnFailure && !bIsWarning) + { + luaL_error(L, strError.c_str()); return 1; } - return iResult; + + pScriptDebugging->LogCustom(L, strError.c_str()); + lua::Push(L, ReturnOnFailure); + return 1; } }; @@ -759,10 +768,7 @@ template { // Remove constness here, because we must be able to std::move - static R Call(T* o, std::remove_const_t... args) - { - return (o->*F)(std::move(args)...); - } + static R Call(T* o, std::remove_const_t... args) { return (o->*F)(std::move(args)...); } auto operator()(lua_State* L, CScriptDebugging* pScriptDebugging) { diff --git a/Shared/mods/deathmatch/logic/lua/CLuaShared.cpp b/Shared/mods/deathmatch/logic/lua/CLuaShared.cpp index 1ca16ce6f4..2b83816e1c 100644 --- a/Shared/mods/deathmatch/logic/lua/CLuaShared.cpp +++ b/Shared/mods/deathmatch/logic/lua/CLuaShared.cpp @@ -77,6 +77,7 @@ void CLuaShared::LoadFunctions() CLuaCryptDefs::LoadFunctions(); CLuaFileDefs::LoadFunctions(); CLuaXMLDefs::LoadFunctions(); + CLuaPathDefs::LoadFunctions(); CLuaTrainTrackDefs::LoadFunctions(); CLuaUTFDefs::LoadFunctions(); CLuaUtilDefs::LoadFunctions(); @@ -85,6 +86,7 @@ void CLuaShared::LoadFunctions() void CLuaShared::AddClasses(lua_State* luaVM) { CLuaFileDefs::AddClass(luaVM); + CLuaPathDefs::AddClass(luaVM); CLuaXMLDefs::AddClass(luaVM); } diff --git a/Shared/mods/deathmatch/logic/lua/CLuaShared.h b/Shared/mods/deathmatch/logic/lua/CLuaShared.h index e484148c58..ee78828134 100644 --- a/Shared/mods/deathmatch/logic/lua/CLuaShared.h +++ b/Shared/mods/deathmatch/logic/lua/CLuaShared.h @@ -12,8 +12,9 @@ // Lua function definitions (shared) #include "luadefs/CLuaBitDefs.h" #include "luadefs/CLuaCryptDefs.h" -#include +#include "luadefs/CLuaFileDefs.h" #include "luadefs/CLuaMatrixDefs.h" +#include "luadefs/CLuaPathDefs.h" #include "luadefs/CLuaTrainTrackDefs.h" #include "luadefs/CLuaUTFDefs.h" #include "luadefs/CLuaUtilDefs.h" diff --git a/Shared/mods/deathmatch/logic/lua/CLuaTimer.cpp b/Shared/mods/deathmatch/logic/lua/CLuaTimer.cpp index 00f919704f..bd0383222b 100644 --- a/Shared/mods/deathmatch/logic/lua/CLuaTimer.cpp +++ b/Shared/mods/deathmatch/logic/lua/CLuaTimer.cpp @@ -23,6 +23,7 @@ CLuaTimer::CLuaTimer(const CLuaFunctionRef& iLuaFunction, const CLuaArguments& A m_uiRepeats = 1; m_iLuaFunction = iLuaFunction; m_Arguments = Arguments; + m_paused = false; } CLuaTimer::~CLuaTimer() @@ -64,9 +65,31 @@ void CLuaTimer::ExecuteTimer(CLuaMain* pLuaMain) } } +void CLuaTimer::SetPaused(bool paused) +{ + if (paused == IsPaused()) + return; + + CTickCount llTimeRemaining = GetTimeLeft(); + if (paused) + { + m_pausedRemainingTime = llTimeRemaining.ToLongLong() == 0LL ? m_llDelay : llTimeRemaining; + } + else + { + CTickCount llCurrentTime = CTickCount::Now(); + CTickCount llNewStartTime = llCurrentTime - (m_llDelay - llTimeRemaining); + SetStartTime(llNewStartTime); + } + m_paused = paused; +} + CTickCount CLuaTimer::GetTimeLeft() { + if (IsPaused()) + return m_pausedRemainingTime; + CTickCount llCurrentTime = CTickCount::Now(); CTickCount llTimeLeft = m_llStartTime + m_llDelay - llCurrentTime; - return llTimeLeft; + return llTimeLeft.ToLongLong() < 0LL ? CTickCount(0LL) : llTimeLeft; } diff --git a/Shared/mods/deathmatch/logic/lua/CLuaTimer.h b/Shared/mods/deathmatch/logic/lua/CLuaTimer.h index 62bb3c97a5..9534c2c47f 100644 --- a/Shared/mods/deathmatch/logic/lua/CLuaTimer.h +++ b/Shared/mods/deathmatch/logic/lua/CLuaTimer.h @@ -17,7 +17,7 @@ class CLuaTimer; #include "lua/LuaCommon.h" #include "lua/CLuaArguments.h" -#define LUA_TIMER_MIN_INTERVAL 0 +#define LUA_TIMER_MIN_INTERVAL 0 class CLuaTimer { @@ -35,6 +35,8 @@ class CLuaTimer unsigned int GetRepeats() const { return m_uiRepeats; }; void SetRepeats(unsigned int uiRepeats) { m_uiRepeats = uiRepeats; } + bool IsPaused() const noexcept { return m_paused; }; + void SetPaused(bool paused); void ExecuteTimer(class CLuaMain* pLuaMain); @@ -45,10 +47,12 @@ class CLuaTimer void SetLuaDebugInfo(const SLuaDebugInfo& luaDebugInfo) { m_LuaDebugInfo = luaDebugInfo; } private: + bool m_paused; CLuaFunctionRef m_iLuaFunction; CLuaArguments m_Arguments; CTickCount m_llStartTime; CTickCount m_llDelay; + CTickCount m_pausedRemainingTime; unsigned int m_uiRepeats; uint m_uiScriptID; SLuaDebugInfo m_LuaDebugInfo; diff --git a/Shared/mods/deathmatch/logic/lua/LuaBasic.cpp b/Shared/mods/deathmatch/logic/lua/LuaBasic.cpp index 9dbc467be4..ec507af33d 100644 --- a/Shared/mods/deathmatch/logic/lua/LuaBasic.cpp +++ b/Shared/mods/deathmatch/logic/lua/LuaBasic.cpp @@ -15,17 +15,18 @@ namespace lua template <> std::string PopPrimitive(lua_State* L, int& index) { - uint uiLength = lua_strlen(L, index); - std::string outValue; - outValue.assign(lua_tostring(L, index++), uiLength); + size_t length; + const char* str = lua_tolstring(L, index++, &length); + std::string outValue(str, length); return outValue; } template <> std::string_view PopPrimitive(lua_State* L, int& index) { - uint uiLength = lua_strlen(L, index); - std::string_view outValue(lua_tostring(L, index++), uiLength); + size_t uiLength; + const char* str = lua_tolstring(L, index++, &uiLength); + std::string_view outValue(str, uiLength); return outValue; } diff --git a/Shared/mods/deathmatch/logic/luadefs/CLuaCryptDefs.cpp b/Shared/mods/deathmatch/logic/luadefs/CLuaCryptDefs.cpp index 29d5689bb5..ec63d4ce7f 100644 --- a/Shared/mods/deathmatch/logic/luadefs/CLuaCryptDefs.cpp +++ b/Shared/mods/deathmatch/logic/luadefs/CLuaCryptDefs.cpp @@ -31,7 +31,7 @@ void CLuaCryptDefs::LoadFunctions() {"generateKeyPair", ArgumentParser}, {"passwordVerify", PasswordVerify}, {"encodeString", EncodeString}, - {"decodeString", DecodeString}, + {"decodeString", DecodeString} }; // Add functions @@ -402,7 +402,11 @@ int CLuaCryptDefs::EncodeString(lua_State* luaVM) CScriptArgReader argStream(luaVM); argStream.ReadEnumString(algorithm); argStream.ReadString(data); - argStream.ReadStringMap(options); + + if ((algorithm != StringEncodeFunction::BASE64 && algorithm != StringEncodeFunction::BASE32) || argStream.NextIsTable()) + { + argStream.ReadStringMap(options); + } argStream.ReadFunction(luaFunctionRef, LUA_REFNIL); argStream.ReadFunctionComplete(); @@ -589,6 +593,140 @@ int CLuaCryptDefs::EncodeString(lua_State* luaVM) } return 1; } + case StringEncodeFunction::BASE64: + { + const SString variant = options["variant"].ToUpper(); + + if (!variant.empty() && variant != "URL") + { + m_pScriptDebugging->LogCustom(luaVM, "Invalid value for field 'variant'"); + lua::Push(luaVM, false); + return 1; + } + + // Async + if (VERIFY_FUNCTION(luaFunctionRef)) + { + CLuaMain* pLuaMain = m_pLuaManager->GetVirtualMachine(luaVM); + if (pLuaMain) + { + CLuaShared::GetAsyncTaskScheduler()->PushTask( + [data, variant] + { + try + { + return std::make_pair(SharedUtil::Base64encode(data, variant), true); + } + catch (const CryptoPP::Exception& ex) + { + return std::make_pair(SString(ex.GetWhat()), false); + } + }, + [luaFunctionRef](const std::pair& result) + { + CLuaMain* pLuaMain = m_pLuaManager->GetVirtualMachine(luaFunctionRef.GetLuaVM()); + if (pLuaMain) + { + CLuaArguments arguments; + if (result.second) + { + arguments.PushString(result.first); + arguments.Call(pLuaMain, luaFunctionRef); + } + else + { + m_pScriptDebugging->LogWarning(luaFunctionRef.GetLuaVM(), result.first.c_str()); + arguments.PushBoolean(false); + arguments.Call(pLuaMain, luaFunctionRef); + } + } + }); + + lua::Push(luaVM, true); + } + } + else // Sync + { + try + { + lua::Push(luaVM, SharedUtil::Base64encode(data, variant)); + } + catch (const CryptoPP::Exception& ex) + { + m_pScriptDebugging->LogWarning(luaVM, ex.what()); + lua::Push(luaVM, false); + } + return 1; + } + return 1; + } + case StringEncodeFunction::BASE32: + { + const SString variant = options["variant"].ToUpper(); + + if (!variant.empty() && variant != "HEX") + { + m_pScriptDebugging->LogCustom(luaVM, "Invalid value for field 'variant'"); + lua::Push(luaVM, false); + return 1; + } + + // Async + if (VERIFY_FUNCTION(luaFunctionRef)) + { + CLuaMain* pLuaMain = m_pLuaManager->GetVirtualMachine(luaVM); + if (pLuaMain) + { + CLuaShared::GetAsyncTaskScheduler()->PushTask( + [data, variant] + { + try + { + return std::make_pair(SharedUtil::Base32encode(data, variant), true); + } + catch (const CryptoPP::Exception& ex) + { + return std::make_pair(SString(ex.GetWhat()), false); + } + }, + [luaFunctionRef](const std::pair& result) + { + CLuaMain* pLuaMain = m_pLuaManager->GetVirtualMachine(luaFunctionRef.GetLuaVM()); + if (pLuaMain) + { + CLuaArguments arguments; + if (result.second) + { + arguments.PushString(result.first); + arguments.Call(pLuaMain, luaFunctionRef); + } + else + { + m_pScriptDebugging->LogWarning(luaFunctionRef.GetLuaVM(), result.first.c_str()); + arguments.PushBoolean(false); + arguments.Call(pLuaMain, luaFunctionRef); + } + } + }); + + lua::Push(luaVM, true); + } + } + else // Sync + { + try + { + lua::Push(luaVM, SharedUtil::Base32encode(data, variant)); + } + catch (const CryptoPP::Exception& ex) + { + m_pScriptDebugging->LogWarning(luaVM, ex.what()); + lua::Push(luaVM, false); + } + return 1; + } + return 1; + } default: { m_pScriptDebugging->LogCustom(luaVM, "Unknown encryption algorithm"); @@ -614,7 +752,11 @@ int CLuaCryptDefs::DecodeString(lua_State* luaVM) CScriptArgReader argStream(luaVM); argStream.ReadEnumString(algorithm); argStream.ReadString(data); - argStream.ReadStringMap(options); + + if ((algorithm != StringEncodeFunction::BASE64 && algorithm != StringEncodeFunction::BASE32) || argStream.NextIsTable()) + { + argStream.ReadStringMap(options); + } argStream.ReadFunction(luaFunctionRef, LUA_REFNIL); argStream.ReadFunctionComplete(); @@ -808,6 +950,140 @@ int CLuaCryptDefs::DecodeString(lua_State* luaVM) } return 1; } + case StringEncodeFunction::BASE64: + { + const SString variant = options["variant"].ToUpper(); + + if (!variant.empty() && variant != "URL") + { + m_pScriptDebugging->LogCustom(luaVM, "Invalid value for field 'variant'"); + lua::Push(luaVM, false); + return 1; + } + + // Async + if (VERIFY_FUNCTION(luaFunctionRef)) + { + CLuaMain* pLuaMain = m_pLuaManager->GetVirtualMachine(luaVM); + if (pLuaMain) + { + CLuaShared::GetAsyncTaskScheduler()->PushTask( + [data, variant] + { + try + { + return std::make_pair(SharedUtil::Base64decode(data, variant), true); + } + catch (const CryptoPP::Exception& ex) + { + return std::make_pair(SString(ex.GetWhat()), false); + } + }, + [luaFunctionRef](const std::pair& result) + { + CLuaMain* pLuaMain = m_pLuaManager->GetVirtualMachine(luaFunctionRef.GetLuaVM()); + if (pLuaMain) + { + CLuaArguments arguments; + if (result.second) + { + arguments.PushString(result.first); + arguments.Call(pLuaMain, luaFunctionRef); + } + else + { + m_pScriptDebugging->LogWarning(luaFunctionRef.GetLuaVM(), result.first.c_str()); + arguments.PushBoolean(false); + arguments.Call(pLuaMain, luaFunctionRef); + } + } + }); + + lua::Push(luaVM, true); + } + } + else // Sync + { + try + { + lua::Push(luaVM, SharedUtil::Base64decode(data, variant)); + } + catch (const CryptoPP::Exception& ex) + { + m_pScriptDebugging->LogWarning(luaVM, ex.what()); + lua::Push(luaVM, false); + } + return 1; + } + return 1; + } + case StringEncodeFunction::BASE32: + { + const SString variant = options["variant"].ToUpper(); + + if (!variant.empty() && variant != "HEX") + { + m_pScriptDebugging->LogCustom(luaVM, "Invalid value for field 'variant'"); + lua::Push(luaVM, false); + return 1; + } + + // Async + if (VERIFY_FUNCTION(luaFunctionRef)) + { + CLuaMain* pLuaMain = m_pLuaManager->GetVirtualMachine(luaVM); + if (pLuaMain) + { + CLuaShared::GetAsyncTaskScheduler()->PushTask( + [data, variant] + { + try + { + return std::make_pair(SharedUtil::Base32decode(data, variant), true); + } + catch (const CryptoPP::Exception& ex) + { + return std::make_pair(SString(ex.GetWhat()), false); + } + }, + [luaFunctionRef](const std::pair& result) + { + CLuaMain* pLuaMain = m_pLuaManager->GetVirtualMachine(luaFunctionRef.GetLuaVM()); + if (pLuaMain) + { + CLuaArguments arguments; + if (result.second) + { + arguments.PushString(result.first); + arguments.Call(pLuaMain, luaFunctionRef); + } + else + { + m_pScriptDebugging->LogWarning(luaFunctionRef.GetLuaVM(), result.first.c_str()); + arguments.PushBoolean(false); + arguments.Call(pLuaMain, luaFunctionRef); + } + } + }); + + lua::Push(luaVM, true); + } + } + else // Sync + { + try + { + lua::Push(luaVM, SharedUtil::Base32decode(data, variant)); + } + catch (const CryptoPP::Exception& ex) + { + m_pScriptDebugging->LogWarning(luaVM, ex.what()); + lua::Push(luaVM, false); + } + return 1; + } + return 1; + } default: { m_pScriptDebugging->LogCustom(luaVM, "Unknown encryption algorithm"); diff --git a/Shared/mods/deathmatch/logic/luadefs/CLuaFileDefs.cpp b/Shared/mods/deathmatch/logic/luadefs/CLuaFileDefs.cpp index 772e569675..bacfe9843b 100644 --- a/Shared/mods/deathmatch/logic/luadefs/CLuaFileDefs.cpp +++ b/Shared/mods/deathmatch/logic/luadefs/CLuaFileDefs.cpp @@ -38,10 +38,22 @@ static auto getResourceFilePath(CResource* thisResource, CResource* fileResource void CLuaFileDefs::LoadFunctions() { constexpr static const std::pair functions[]{ - {"fileOpen", fileOpen}, {"fileCreate", fileCreate}, {"fileExists", fileExists}, {"fileCopy", fileCopy}, - {"fileRename", fileRename}, {"fileDelete", fileDelete}, {"fileClose", fileClose}, {"fileFlush", fileFlush}, - {"fileRead", fileRead}, {"fileWrite", fileWrite}, {"fileGetPos", fileGetPos}, {"fileGetSize", fileGetSize}, - {"fileGetPath", fileGetPath}, {"fileIsEOF", fileIsEOF}, {"fileSetPos", fileSetPos}, {"fileGetContents", ArgumentParser}, + {"fileOpen", fileOpen}, + {"fileCreate", fileCreate}, + {"fileExists", fileExists}, + {"fileCopy", fileCopy}, + {"fileRename", fileRename}, + {"fileDelete", fileDelete}, + {"fileClose", fileClose}, + {"fileFlush", fileFlush}, + {"fileRead", fileRead}, + {"fileWrite", fileWrite}, + {"fileGetPos", fileGetPos}, + {"fileGetSize", fileGetSize}, + {"fileGetPath", fileGetPath}, + {"fileIsEOF", fileIsEOF}, + {"fileSetPos", fileSetPos}, + {"fileGetContents", ArgumentParser}, }; // Add functions @@ -109,8 +121,8 @@ int CLuaFileDefs::File(lua_State* luaVM) if (CResourceManager::ParseResourcePathInput(strInputPath, pResource, &strAbsPath, &strMetaPath)) { - CheckCanModifyOtherResource(argStream, pResource, pResource); - CheckCanAccessOtherResourceFile(argStream, pResource, pResource, strAbsPath); + CheckCanModifyOtherResource(argStream, pThisResource, pResource); + CheckCanAccessOtherResourceFile(argStream, pThisResource, pResource, strAbsPath); if (!argStream.HasErrors()) { @@ -388,8 +400,6 @@ int CLuaFileDefs::fileExists(lua_State* luaVM) CResource* pResource = pLuaMain->GetResource(); if (CResourceManager::ParseResourcePathInput(strInputPath, pResource, &strAbsPath)) { - SString strFilePath; - // Does file exist? bool bResult = FileExists(strAbsPath); lua_pushboolean(luaVM, bResult); diff --git a/Shared/mods/deathmatch/logic/luadefs/CLuaPathDefs.cpp b/Shared/mods/deathmatch/logic/luadefs/CLuaPathDefs.cpp new file mode 100644 index 0000000000..e626ed15f7 --- /dev/null +++ b/Shared/mods/deathmatch/logic/luadefs/CLuaPathDefs.cpp @@ -0,0 +1,111 @@ +/***************************************************************************** + * + * PROJECT: Multi Theft Auto + * LICENSE: See LICENSE in the top level directory + * FILE: Shared/mods/deathmatch/logic/luadefs/CLuaFileDefs.cpp + * + * Multi Theft Auto is available from http://www.multitheftauto.com/ + * + *****************************************************************************/ + +#include "StdInc.h" + +#ifndef MTA_CLIENT + // NOTE: Must be included before ILuaModuleManager.h which defines its own CChecksum type. + #include "CChecksum.h" +#endif + +#include "CLuaPathDefs.h" +#include "CScriptFile.h" +#include "CScriptArgReader.h" +#include + +void CLuaPathDefs::LoadFunctions() +{ + constexpr static const std::pair functions[]{ + {"pathListDir", ArgumentParser}, + {"pathIsFile", ArgumentParser}, + {"pathIsDirectory", ArgumentParser}, + }; + + // Add functions + for (const auto& [name, func] : functions) + CLuaCFunctions::AddFunction(name, func); +} + +void CLuaPathDefs::AddClass(lua_State* luaVM) +{ + lua_newclass(luaVM); + + lua_classfunction(luaVM, "listDir", "pathListDir"); + lua_classfunction(luaVM, "isFile", "pathIsFile"); + lua_classfunction(luaVM, "isDirectory", "pathIsDirectory"); + + lua_registerclass(luaVM, "path"); +} + +std::optional> CLuaPathDefs::pathListDir( + lua_State* luaVM, + std::string path +) { + CLuaMain* pLuaMain = m_pLuaManager->GetVirtualMachine(luaVM); + if (!pLuaMain) + return std::nullopt; + + std::string strAbsPath; + + CResource* pResource = pLuaMain->GetResource(); + if (!CResourceManager::ParseResourcePathInput(path, pResource, &strAbsPath)) + { + m_pScriptDebugging->LogWarning(luaVM, "Cannot parse provided path: \"%s\"", + path.c_str()); + return std::nullopt; + } + + if (!DirectoryExists(strAbsPath)) + { + m_pScriptDebugging->LogWarning(luaVM, "Directory \"%s\" doesn't exist!", + path.c_str()); + return std::nullopt; + } + + return SharedUtil::ListDir(strAbsPath.c_str()); +} + +bool CLuaPathDefs::pathIsFile(lua_State* luaVM, std::string path) +{ + CLuaMain* pLuaMain = m_pLuaManager->GetVirtualMachine(luaVM); + if (!pLuaMain) + return false; + + std::string strAbsPath; + + CResource* pResource = pLuaMain->GetResource(); + if (!CResourceManager::ParseResourcePathInput(path, pResource, &strAbsPath)) + { + m_pScriptDebugging->LogWarning(luaVM, "Cannot parse provided path: \"%s\"", + path.c_str()); + return false; + } + + return SharedUtil::FileExists(strAbsPath); +} + +bool CLuaPathDefs::pathIsDirectory(lua_State* luaVM, std::string path) +{ + CLuaMain* pLuaMain = m_pLuaManager->GetVirtualMachine(luaVM); + if (!pLuaMain) + return false; + + std::string strAbsPath; + + CResource* pResource = pLuaMain->GetResource(); + if (!CResourceManager::ParseResourcePathInput(path, pResource, &strAbsPath)) + { + m_pScriptDebugging->LogWarning(luaVM, "Cannot parse provided path: \"%s\"", + path.c_str()); + return false; + } + + return SharedUtil::DirectoryExists(strAbsPath.c_str()); +} diff --git a/Shared/mods/deathmatch/logic/luadefs/CLuaPathDefs.h b/Shared/mods/deathmatch/logic/luadefs/CLuaPathDefs.h new file mode 100644 index 0000000000..cfc8ae1bae --- /dev/null +++ b/Shared/mods/deathmatch/logic/luadefs/CLuaPathDefs.h @@ -0,0 +1,25 @@ +/***************************************************************************** + * + * PROJECT: Multi Theft Auto + * LICENSE: See LICENSE in the top level directory + * FILE: Shared/mods/deathmatch/logic/luadefs/CLuaFileDefs.h + * + * Multi Theft Auto is available from http://www.multitheftauto.com/ + * + *****************************************************************************/ + +#pragma once +#include "luadefs/CLuaDefs.h" + +class CLuaPathDefs : public CLuaDefs +{ +public: + static void LoadFunctions(); + static void AddClass(lua_State* luaVM); + +private: + static std::optional> pathListDir(lua_State* luaVM, std::string path); + + static bool pathIsFile(lua_State* luaVM, std::string path); + static bool pathIsDirectory(lua_State* luaVM, std::string path); +}; diff --git a/Shared/mods/deathmatch/logic/luadefs/CLuaUtilDefs.cpp b/Shared/mods/deathmatch/logic/luadefs/CLuaUtilDefs.cpp index 98fd2005a9..0b5847fa09 100644 --- a/Shared/mods/deathmatch/logic/luadefs/CLuaUtilDefs.cpp +++ b/Shared/mods/deathmatch/logic/luadefs/CLuaUtilDefs.cpp @@ -499,7 +499,7 @@ int CLuaUtilDefs::fromJSON(lua_State* luaVM) { // Return it as data Converted.PushArguments(luaVM); - return Converted.Count(); + return static_cast(Converted.Count()); } } else diff --git a/Shared/sdk/CFastList.h b/Shared/sdk/CFastList.h index 7797e70cca..30f65a1eb0 100644 --- a/Shared/sdk/CFastList.h +++ b/Shared/sdk/CFastList.h @@ -307,6 +307,8 @@ class CFastList template bool ListContains(const CFastList& itemList, const U& item) { + if (itemList.empty()) + return false; return itemList.contains(item); } diff --git a/Shared/sdk/CScriptArgReader.h b/Shared/sdk/CScriptArgReader.h index f9d522e548..affbe34d73 100644 --- a/Shared/sdk/CScriptArgReader.h +++ b/Shared/sdk/CScriptArgReader.h @@ -525,6 +525,22 @@ class CScriptArgReader m_iIndex++; } + // + // Read next bool or false if failed + // Intended for use in pair with NextIsBool() + // + bool ReadBool() + { + int iArgument = lua_type(m_luaVM, m_iIndex); + if (iArgument == LUA_TBOOLEAN) + { + return lua_toboolean(m_luaVM, m_iIndex++) ? true : false; + } + + m_iIndex++; + return false; + } + // // Read next bool, using default if needed // @@ -912,10 +928,7 @@ class CScriptArgReader void ReadLuaArguments(CLuaArguments& outValue) { outValue.ReadArguments(m_luaVM, m_iIndex); - for (int i = outValue.Count(); i > 0; i--) - { - m_iIndex++; - } + m_iIndex += outValue.Count(); } // diff --git a/Shared/sdk/CVector.h b/Shared/sdk/CVector.h index 265b186e9d..5c2ddde7a6 100644 --- a/Shared/sdk/CVector.h +++ b/Shared/sdk/CVector.h @@ -26,11 +26,15 @@ class CVector static constexpr float FLOAT_EPSILON = 0.0001f; public: - float fX = 0.0f; - float fY = 0.0f; - float fZ = 0.0f; + float fX; + float fY; + float fZ; - constexpr CVector() = default; + struct NoInit{}; + + CVector(NoInit) {} + + constexpr CVector() : fX(0.0f), fY(0.0f), fZ(0.0f) {} constexpr CVector(float x, float y, float z) : fX(x), fY(y), fZ(z) {} diff --git a/Shared/sdk/SharedUtil.Crypto.h b/Shared/sdk/SharedUtil.Crypto.h index 7d5413c94c..a44cb22c5a 100644 --- a/Shared/sdk/SharedUtil.Crypto.h +++ b/Shared/sdk/SharedUtil.Crypto.h @@ -9,6 +9,7 @@ *****************************************************************************/ #pragma once #include +#include #include #include #include @@ -25,18 +26,66 @@ namespace SharedUtil SString publicKey, privateKey; }; - inline SString Base64encode(const SString& data) + inline SString Base64encode(const SString& data, const SString& variant = SString()) { - SString result; - CryptoPP::StringSource ss(data, true, new CryptoPP::Base64Encoder(new CryptoPP::StringSink(result), false)); // Memory is freed automatically + SString result; + + if (variant == "URL") + { + CryptoPP::StringSource ss(data, true, new CryptoPP::Base64URLEncoder(new CryptoPP::StringSink(result), false)); + } + else + { + CryptoPP::StringSource ss(data, true, new CryptoPP::Base64Encoder(new CryptoPP::StringSink(result), false)); + } + + return result; + } + + inline SString Base64decode(const SString& data, const SString& variant = SString()) + { + SString result; + + if (variant == "URL") + { + CryptoPP::StringSource ss(data, true, new CryptoPP::Base64URLDecoder(new CryptoPP::StringSink(result))); + } + else + { + CryptoPP::StringSource ss(data, true, new CryptoPP::Base64Decoder(new CryptoPP::StringSink(result))); + } return result; } - inline SString Base64decode(const SString& data) + inline SString Base32encode(const SString& data, const SString& variant = SString()) { - SString result; - CryptoPP::StringSource ss(data, true, new CryptoPP::Base64Decoder(new CryptoPP::StringSink(result))); // Memory is freed automatically + SString result; + + if (variant == "HEX") + { + CryptoPP::StringSource ss(data, true, new CryptoPP::Base32HexEncoder(new CryptoPP::StringSink(result), false)); + } + else + { + CryptoPP::StringSource ss(data, true, new CryptoPP::Base32Encoder(new CryptoPP::StringSink(result), false)); + } + + return result; + } + + inline SString Base32decode(const SString& data, const SString& variant = SString()) + { + SString result; + + if (variant == "HEX") + { + CryptoPP::StringSource ss(data, true, new CryptoPP::Base32HexDecoder(new CryptoPP::StringSink(result))); + } + else + { + CryptoPP::StringSource ss(data, true, new CryptoPP::Base32Decoder(new CryptoPP::StringSink(result))); + } return result; } diff --git a/Shared/sdk/SharedUtil.Defines.h b/Shared/sdk/SharedUtil.Defines.h index 8e257d1433..580335e61b 100644 --- a/Shared/sdk/SharedUtil.Defines.h +++ b/Shared/sdk/SharedUtil.Defines.h @@ -26,10 +26,12 @@ // // Architecture // -#if defined( _M_X64 ) || defined( __x86_64__ ) || defined( _M_AMD64 ) +#if defined( _M_X64 ) || defined( __x86_64__ ) || defined( _M_AMD64 ) || defined( __amd64__ ) #define ANY_x64 #ifdef _WIN64 #define WIN_x64 + #elif defined(__APPLE__) + #define APPLE_x64 #else #define LINUX_x64 #endif @@ -37,6 +39,8 @@ #define ANY_arm64 #ifdef _M_ARM64 #define WIN_arm64 + #elif defined(__APPLE__) + #define APPLE_arm64 #else #define LINUX_arm64 #endif diff --git a/Shared/sdk/SharedUtil.File.h b/Shared/sdk/SharedUtil.File.h index 88436852c4..3def283a19 100644 --- a/Shared/sdk/SharedUtil.File.h +++ b/Shared/sdk/SharedUtil.File.h @@ -20,8 +20,8 @@ namespace SharedUtil // // Returns true if the file/directory exists // - bool FileExists(const SString& strFilename); - bool DirectoryExists(const SString& strPath); + bool FileExists(const std::string& strFilename) noexcept; + bool DirectoryExists(const std::string& strPath) noexcept; // // Load from a file @@ -102,6 +102,8 @@ namespace SharedUtil WString FromUTF8(const SString& strPath); SString ToUTF8(const WString& strPath); + std::vector ListDir(const char* szPath) noexcept; + namespace File { FILE* Fopen(const char* szFilename, const char* szMode); diff --git a/Shared/sdk/SharedUtil.File.hpp b/Shared/sdk/SharedUtil.File.hpp index 4fa724e489..0a1cf56c7c 100644 --- a/Shared/sdk/SharedUtil.File.hpp +++ b/Shared/sdk/SharedUtil.File.hpp @@ -14,8 +14,9 @@ #include "SharedUtil.Misc.h" #include "SharedUtil.Buffer.h" #include +#include -#ifdef WIN32 +#ifdef _WIN32 #ifndef NOMINMAX #define NOMINMAX #endif @@ -29,38 +30,53 @@ #include #include #include - #include #endif // // Returns true if the file exists // -bool SharedUtil::FileExists(const SString& strFilename) +bool SharedUtil::FileExists(const std::string& strFilename) noexcept { -#ifdef WIN32 - DWORD dwAtr = GetFileAttributes(strFilename); +#if __cplusplus >= 201703L + namespace fs = std::filesystem; + std::error_code errorCode; + return fs::is_regular_file(strFilename.c_str(), errorCode); +#else + #ifdef _WIN32 + DWORD dwAtr = GetFileAttributes(strFilename.c_str()); if (dwAtr == INVALID_FILE_ATTRIBUTES) return false; - return ((dwAtr & FILE_ATTRIBUTE_DIRECTORY) == 0); -#else - std::error_code ec{}; - return std::filesystem::is_regular_file(static_cast(strFilename), ec); + return !(dwAtr & FILE_ATTRIBUTE_DIRECTORY); + #else + struct stat s; + if (!stat(strFilename.c_str(), &s)) + return false; + return s.st_mode & S_IFREG; + #endif #endif } // // Returns true if the directory exists // -bool SharedUtil::DirectoryExists(const SString& strPath) +bool SharedUtil::DirectoryExists(const std::string& strPath) noexcept { -#ifdef WIN32 - DWORD dwAtr = GetFileAttributes(strPath); +#if __cplusplus >= 201703L + namespace fs = std::filesystem; + std::error_code errorCode; + return fs::is_directory(strPath.c_str(), errorCode); +#else + #ifdef _WIN32 + DWORD dwAtr = GetFileAttributes(strPath.c_str()); if (dwAtr == INVALID_FILE_ATTRIBUTES) return false; - return ((dwAtr & FILE_ATTRIBUTE_DIRECTORY) != 0); -#else - std::error_code ec{}; - return std::filesystem::is_directory(static_cast(strPath), ec); + return (dwAtr & FILE_ATTRIBUTE_DIRECTORY) != 0; + #else + struct stat s; + if (!stat(strPath.c_str(), &s)) + return false; + return s.st_mode & S_IFDIR; + #endif #endif } @@ -85,7 +101,7 @@ bool SharedUtil::FileLoad(std::nothrow_t, const SString& filePath, SString& outB if (offset > GIBIBYTE) return false; -#if WIN32 +#ifdef _WIN32 WString wideFilePath; try @@ -140,11 +156,18 @@ bool SharedUtil::FileLoad(std::nothrow_t, const SString& filePath, SString& outB CloseHandle(handle); return true; +#else +#ifdef __APPLE__ + struct stat info; + + if (stat(filePath, &info) != 0) + return false; #else struct stat64 info; if (stat64(filePath, &info) != 0) return false; +#endif size_t fileSize = static_cast(info.st_size); @@ -192,7 +215,7 @@ bool SharedUtil::FileAppend(const SString& strFilename, const SString& strBuffer bool SharedUtil::FileDelete(const SString& strFilename, bool bForce) { -#ifdef WIN32 +#ifdef _WIN32 if (bForce) SetFileAttributes(strFilename, FILE_ATTRIBUTE_NORMAL); #endif @@ -201,7 +224,7 @@ bool SharedUtil::FileDelete(const SString& strFilename, bool bForce) bool SharedUtil::FileRename(const SString& strFilenameOld, const SString& strFilenameNew, int* pOutErrorCode) { -#ifdef WIN32 +#ifdef _WIN32 if (MoveFileExW(FromUTF8(strFilenameOld), FromUTF8(strFilenameNew), MOVEFILE_COPY_ALLOWED) == 0) { int errorCode = GetLastError(); @@ -268,7 +291,7 @@ bool SharedUtil::FileLoad(const SString& strFilename, std::vector& buffer, // bool SharedUtil::FileSave(const SString& strFilename, const void* pBuffer, unsigned long ulSize, bool bForce) { -#ifdef WIN32 +#ifdef _WIN32 if (bForce) SetFileAttributes(strFilename, FILE_ATTRIBUTE_NORMAL); #endif @@ -292,7 +315,7 @@ bool SharedUtil::FileSave(const SString& strFilename, const void* pBuffer, unsig // bool SharedUtil::FileAppend(const SString& strFilename, const void* pBuffer, unsigned long ulSize, bool bForce) { -#ifdef WIN32 +#ifdef _WIN32 if (bForce) SetFileAttributes(strFilename, FILE_ATTRIBUTE_NORMAL); #endif @@ -319,7 +342,7 @@ uint64 SharedUtil::FileSize(const SString& strFilename) return 0; // Get size fseek(fh, 0, SEEK_END); -#ifdef WIN32 +#ifdef _WIN32 uint64 size = _ftelli64(fh); #elif defined(__APPLE__) uint64 size = ftello(fh); @@ -336,7 +359,7 @@ uint64 SharedUtil::FileSize(const SString& strFilename) // void SharedUtil::MakeSureDirExists(const SString& strPath) { -#ifdef WIN32 +#ifdef _WIN32 std::vector parts; PathConform(strPath).Split(PATH_SEPERATOR, parts); @@ -359,7 +382,7 @@ void SharedUtil::MakeSureDirExists(const SString& strPath) } #else std::filesystem::path filePath = static_cast(PathConform(strPath)); - std::error_code ec{}; + std::error_code ec{}; std::filesystem::create_directories(filePath.parent_path(), ec); #endif } @@ -367,7 +390,7 @@ void SharedUtil::MakeSureDirExists(const SString& strPath) SString SharedUtil::PathConform(const SString& strPath) { // Make slashes the right way and remove duplicates, except for UNC type indicators -#if WIN32 +#ifdef _WIN32 SString strTemp = strPath.Replace("/", PATH_SEPERATOR); #else SString strTemp = strPath.Replace("\\", PATH_SEPERATOR); @@ -427,7 +450,7 @@ SString SharedUtil::PathMakeRelative(const SString& strInBasePath, const SString SString SharedUtil::GetSystemCurrentDirectory() { -#ifdef WIN32 +#ifdef _WIN32 wchar_t szResult[1024] = L""; GetCurrentDirectoryW(NUMELMS(szResult), szResult); if (IsShortPathName(szResult)) @@ -440,7 +463,7 @@ SString SharedUtil::GetSystemCurrentDirectory() #endif } -#ifdef WIN32 +#ifdef _WIN32 #ifdef MTA_CLIENT SString SharedUtil::GetSystemDllDirectory() @@ -593,7 +616,7 @@ SString SharedUtil::GetDriveNameWithNotEnoughSpace(uint uiResourcesPathMinMB, ui } #endif // #ifdef MTA_CLIENT -#endif // #ifdef WIN32 +#endif // #ifdef _WIN32 WString SharedUtil::FromUTF8(const SString& strPath) { @@ -634,7 +657,7 @@ SString SharedUtil::ToUTF8(const WString& strPath) #endif } -#ifdef WIN32 +#ifdef _WIN32 /////////////////////////////////////////////////////////////// // // DelTree @@ -697,7 +720,7 @@ bool SharedUtil::FileCopy(const SString& strSrc, const SString& strDest, bool bF if (bForce) MakeSureDirExists(strDest); -#ifdef WIN32 +#ifdef _WIN32 if (bForce) SetFileAttributes(strDest, FILE_ATTRIBUTE_NORMAL); #endif @@ -729,7 +752,7 @@ bool SharedUtil::FileCopy(const SString& strSrc, const SString& strDest, bool bF return true; } -#ifdef WIN32 +#ifdef _WIN32 /////////////////////////////////////////////////////////////// // // FindFiles @@ -747,7 +770,7 @@ std::vector SharedUtil::FindFiles(const SString& strInMatch, bool bFile if (strMatch.Right(1) == PATH_SEPERATOR) strMatch += "*"; - WIN32_FIND_DATAW findData; + _WIN32_FIND_DATAW findData; HANDLE hFind = FindFirstFileW(FromUTF8(strMatch), &findData); if (hFind != INVALID_HANDLE_VALUE) { @@ -903,7 +926,7 @@ SString SharedUtil::MakeUniquePath(const SString& strInPathFilename) SString strTest = strPathFilename; int iCount = 1; -#ifdef WIN32 +#ifdef _WIN32 while (GetFileAttributes(strTest) != INVALID_FILE_ATTRIBUTES) #else while (DirectoryExists(strTest) || FileExists(strTest)) @@ -968,14 +991,14 @@ bool SharedUtil::IsAbsolutePath(const SString& strInPath) if (strPath.BeginsWith(PATH_SEPERATOR)) return true; -#ifdef WIN32 +#ifdef _WIN32 if (strPath.length() > 0 && strPath[1] == ':') return true; #endif return false; } -#ifdef WIN32 +#ifdef _WIN32 bool SharedUtil::IsShortPathName(const char* szPath) { return strchr(szPath, '~') != NULL; @@ -1003,11 +1026,11 @@ SString SharedUtil::GetSystemLongPathName(const SString& strPath) return strPath; return ToUTF8(szBuffer); } -#endif // WIN32 +#endif // _WIN32 FILE* SharedUtil::File::Fopen(const char* szFilename, const char* szMode) { -#ifdef WIN32 +#ifdef _WIN32 return _wfsopen(FromUTF8(szFilename), FromUTF8(szMode), _SH_DENYNO); #else return fopen(szFilename, szMode); @@ -1016,7 +1039,7 @@ FILE* SharedUtil::File::Fopen(const char* szFilename, const char* szMode) int SharedUtil::File::Mkdir(const char* szPath, int iMode) { -#ifdef WIN32 +#ifdef _WIN32 return _wmkdir(FromUTF8(szPath)); #else return mkdir(szPath, (mode_t)iMode); @@ -1025,7 +1048,7 @@ int SharedUtil::File::Mkdir(const char* szPath, int iMode) int SharedUtil::File::Chdir(const char* szPath) { -#ifdef WIN32 +#ifdef _WIN32 return _wchdir(FromUTF8(szPath)); #else return chdir(szPath); @@ -1034,7 +1057,7 @@ int SharedUtil::File::Chdir(const char* szPath) int SharedUtil::File::Rmdir(const char* szPath) { -#ifdef WIN32 +#ifdef _WIN32 return _wrmdir(FromUTF8(szPath)); #else return rmdir(szPath); @@ -1043,7 +1066,7 @@ int SharedUtil::File::Rmdir(const char* szPath) int SharedUtil::File::Delete(const char* szFilename) { -#ifdef WIN32 +#ifdef _WIN32 return _wremove(FromUTF8(szFilename)); #else return remove(szFilename); @@ -1052,9 +1075,63 @@ int SharedUtil::File::Delete(const char* szFilename) int SharedUtil::File::Rename(const char* szOldFilename, const char* szNewFilename) { -#ifdef WIN32 +#ifdef _WIN32 return _wrename(FromUTF8(szOldFilename), FromUTF8(szNewFilename)); #else return rename(szOldFilename, szNewFilename); #endif } + +std::vector SharedUtil::ListDir(const char* szPath) noexcept +{ + std::vector entries; +#if __cplusplus >= 201703L + namespace fs = std::filesystem; + if (!DirectoryExists(szPath)) + return {}; + + try + { + for (const auto& entry : fs::directory_iterator(szPath)) + { + if (entry.is_regular_file() || entry.is_directory()) + entries.push_back(entry.path().filename().string()); + } + } + catch (...) {} // catch all possible errors and ignore them +#else + #ifdef _WIN32 + std::string search_path = szPath; + if (search_path.empty()) + return {}; + + if (search_path.back() != '/') + search_path += "/*"; + + WIN32_FIND_DATA fd; + HANDLE hFind = ::FindFirstFile(search_path.c_str(), &fd); + if (hFind == INVALID_HANDLE_VALUE) + return {}; + + do + { + entries.push_back(fd.cFileName); + } while (::FindNextFile(hFind, &fd)); + ::FindClose(hFind); + + #else + DIR* dir; + struct dirent* ent; + if (!(dir = opendir(szPath))) + return {}; + + while ((ent = readdir(dir))) + { + entries.push_back(ent->d_name); + } + closedir(dir); + #endif +#endif + + return entries; +} diff --git a/Shared/sdk/SharedUtil.Hash.h b/Shared/sdk/SharedUtil.Hash.h index 29426c569a..1aa28e82ce 100644 --- a/Shared/sdk/SharedUtil.Hash.h +++ b/Shared/sdk/SharedUtil.Hash.h @@ -48,6 +48,8 @@ enum class StringEncodeFunction TEA, AES128, RSA, + BASE64, + BASE32 }; enum class KeyPairAlgorithm diff --git a/Shared/sdk/SharedUtil.Misc.h b/Shared/sdk/SharedUtil.Misc.h index 0d17a2f155..d64f155a7c 100644 --- a/Shared/sdk/SharedUtil.Misc.h +++ b/Shared/sdk/SharedUtil.Misc.h @@ -344,13 +344,14 @@ namespace SharedUtil template bool ListContains(const TL& itemList, const T& item) { + if (itemList.empty()) + return false; typename TL ::const_iterator it = itemList.begin(); for (; it != itemList.end(); ++it) if (item == *it) return true; return false; } - // Add item if it does not aleady exist in itemList template void ListAddUnique(TL& itemList, const T& item) diff --git a/Shared/sdk/SharedUtil.Misc.hpp b/Shared/sdk/SharedUtil.Misc.hpp index ed789460d1..5697da49f4 100644 --- a/Shared/sdk/SharedUtil.Misc.hpp +++ b/Shared/sdk/SharedUtil.Misc.hpp @@ -36,8 +36,8 @@ #endif #endif -#ifdef __APPLE__ - #include "cpuid.h" +#if defined(__APPLE__) && !defined(__aarch64__) + #include #endif CCriticalSection CRefCountable::ms_CS; @@ -1834,6 +1834,8 @@ namespace SharedUtil return FnGetCurrentProcessorNumber(); return _GetCurrentProcessorNumberXP(); +#elif defined(__APPLE__) && defined(__aarch64__) + return -1; #elif defined(__APPLE__) // Hacked from https://stackoverflow.com/a/40398183/1517394 unsigned long cpu; diff --git a/Shared/sdk/net/SyncStructures.h b/Shared/sdk/net/SyncStructures.h index 28c8770fc7..1e9b8215b3 100644 --- a/Shared/sdk/net/SyncStructures.h +++ b/Shared/sdk/net/SyncStructures.h @@ -2032,6 +2032,18 @@ struct SWorldSpecialPropertiesStateSync : public ISyncStructure { BITCOUNT2 = 1 }; + enum + { + BITCOUNT3 = 1 + }; + enum + { + BITCOUNT4 = 1 + }; + enum + { + BITCOUNT5 = 1 + }; bool Read(NetBitStreamInterface& bitStream) { @@ -2041,6 +2053,21 @@ struct SWorldSpecialPropertiesStateSync : public ISyncStructure else data2.fireballdestruct = true; + if (bitStream.Can(eBitStreamVersion::WorldSpecialProperty_RoadSignsText)) + isOK &= bitStream.ReadBits(reinterpret_cast(&data3), BITCOUNT3); + else + data3.roadsignstext = true; + + if (bitStream.Can(eBitStreamVersion::WorldSpecialProperty_ExtendedWaterCannons)) + isOK &= bitStream.ReadBits(reinterpret_cast(&data4), BITCOUNT4); + else + data4.extendedwatercannons = true; + + if (bitStream.Can(eBitStreamVersion::WorldSpecialProperty_TunnelWeatherBlend)) + isOK &= bitStream.ReadBits(reinterpret_cast(&data5), BITCOUNT5); + else + data5.tunnelweatherblend = true; + //// Example for adding item: // if (bitStream.Can(eBitStreamVersion::YourProperty)) // isOK &= bitStream.ReadBits(reinterpret_cast(&data9), BITCOUNT9); @@ -2055,6 +2082,15 @@ struct SWorldSpecialPropertiesStateSync : public ISyncStructure if (bitStream.Can(eBitStreamVersion::WorldSpecialProperty_FireballDestruct)) bitStream.WriteBits(reinterpret_cast(&data2), BITCOUNT2); + if (bitStream.Can(eBitStreamVersion::WorldSpecialProperty_RoadSignsText)) + bitStream.WriteBits(reinterpret_cast(&data3), BITCOUNT3); + + if (bitStream.Can(eBitStreamVersion::WorldSpecialProperty_ExtendedWaterCannons)) + bitStream.WriteBits(reinterpret_cast(&data4), BITCOUNT4); + + if (bitStream.Can(eBitStreamVersion::WorldSpecialProperty_TunnelWeatherBlend)) + bitStream.WriteBits(reinterpret_cast(&data5), BITCOUNT5); + //// Example for adding item: // if (bitStream.Can(eBitStreamVersion::YourProperty)) // bitStream.WriteBits(reinterpret_cast(&data9), BITCOUNT9); @@ -2082,6 +2118,21 @@ struct SWorldSpecialPropertiesStateSync : public ISyncStructure bool fireballdestruct : 1; } data2; + struct + { + bool roadsignstext : 1; + } data3; + + struct + { + bool extendedwatercannons : 1; + } data4; + + struct + { + bool tunnelweatherblend : 1; + } data5; + SWorldSpecialPropertiesStateSync() { // Set default states @@ -2098,6 +2149,9 @@ struct SWorldSpecialPropertiesStateSync : public ISyncStructure data.watercreatures = true; data.burnflippedcars = true; data2.fireballdestruct = true; + data3.roadsignstext = true; + data4.extendedwatercannons = true; + data5.tunnelweatherblend = true; } }; diff --git a/Shared/sdk/net/bitstream.h b/Shared/sdk/net/bitstream.h index 3924ebbf16..c29f739ff1 100644 --- a/Shared/sdk/net/bitstream.h +++ b/Shared/sdk/net/bitstream.h @@ -540,6 +540,38 @@ enum class eBitStreamVersion : unsigned short // 2023-10-12 CPlayerJoinCompletePacket_ServerName, + // Add "roadsignstext" to setWorldSpecialPropertyEnabled + // 2024-05-17 + WorldSpecialProperty_RoadSignsText, + + // Add "extendedwatercannons" to setWorldSpecialPropertyEnabled + // 2024-05-23 + WorldSpecialProperty_ExtendedWaterCannons, + + // Add breakObject to serverside as well + // 2024-05-31 + BreakObject_Serverside, + + // Ped syncronization revision + // 2024-06-16 + PedSync_Revision, + + // Add "extendedwatercannons" to setWorldSpecialPropertyEnabled + // 2024-06-30 + WorldSpecialProperty_TunnelWeatherBlend, + + // Checkpoint & arrow alpha fix + // 2024-07-03 + Marker_IgnoreAlphaLimits, + + // Add "setMarkerTargetArrowProperties" + // 2024-07-05 + SetMarkerTargetArrowProperties, + + // Add respawnObject and toggleObjectRespawn to serverside + // 2024-09-04 + RespawnObject_Serverside, + // This allows us to automatically increment the BitStreamVersion when things are added to this enum. // Make sure you only add things above this comment. Next, diff --git a/Shared/sdk/net/rpc_enums.h b/Shared/sdk/net/rpc_enums.h index 2749267f09..6f63818b46 100644 --- a/Shared/sdk/net/rpc_enums.h +++ b/Shared/sdk/net/rpc_enums.h @@ -277,5 +277,16 @@ enum eElementRPCFunctions SET_WORLD_SPECIAL_PROPERTY, + BREAK_OBJECT, + + SET_PLAYER_SCRIPT_DEBUG_LEVEL, + + SET_MARKER_TARGET_ARROW_PROPERTIES, + + RESPAWN_OBJECT, + TOGGLE_OBJECT_RESPAWN, + + RESET_WORLD_PROPERTIES, + NUM_RPC_FUNCS // Add above this line }; diff --git a/Shared/sdk/version.h b/Shared/sdk/version.h index 52a4280b27..9069c14d9b 100644 --- a/Shared/sdk/version.h +++ b/Shared/sdk/version.h @@ -108,7 +108,7 @@ #define _ASE_VERSION QUOTE_DEFINE(MTASA_VERSION_MAJOR) "." QUOTE_DEFINE(MTASA_VERSION_MINOR) #define _NETCODE_VERSION_BRANCH_ID 0x4 // Use 0x1 - 0xF to indicate an incompatible branch is being used (0x0 is reserved, 0x4 is trunk) -#define _CLIENT_NET_MODULE_VERSION 0x0AD // (0x000 - 0xfff) Lvl9 wizards only +#define _CLIENT_NET_MODULE_VERSION 0x0AE // (0x000 - 0xfff) Lvl9 wizards only #define _SERVER_NET_MODULE_VERSION 0x0AB // (0x000 - 0xfff) Lvl9 wizards only #define _NETCODE_VERSION 0x1DA // (0x000 - 0xfff) Increment when net messages change (pre-release) diff --git a/premake5.lua b/premake5.lua index ff20d1bcaa..48c6e5ae36 100644 --- a/premake5.lua +++ b/premake5.lua @@ -26,7 +26,9 @@ workspace "MTASA" configurations {"Debug", "Release", "Nightly"} if os.host() == "macosx" then - platforms { "x64" } + platforms { "x64", "arm64" } + elseif os.host() == "windows" then + platforms { "x86", "x64", "arm64" } else platforms { "x86", "x64", "arm", "arm64" } end @@ -101,6 +103,10 @@ workspace "MTASA" defaultplatform "x86" end + filter { "system:macosx", "platforms:arm64" } + includedirs { "/opt/homebrew/include" } + libdirs { "/opt/homebrew/lib" } + filter {"system:windows", "configurations:Nightly", "kind:not StaticLib"} symbolspath "$(SolutionDir)Symbols\\$(Configuration)_$(Platform)\\$(ProjectName).pdb" @@ -168,7 +174,7 @@ workspace "MTASA" include "vendor/cef3" include "vendor/discord-rpc" include "vendor/freetype" - include "vendor/jpeg-9e" + include "vendor/jpeg-9f" include "vendor/ksignals" include "vendor/libpng" include "vendor/tinygettext" @@ -206,3 +212,4 @@ workspace "MTASA" include "vendor/unrar" include "vendor/zip" include "vendor/zlib" + include "vendor/glob" diff --git a/utils/7z/7za.dll b/utils/7z/7za.dll index 5cd2ace2a8..5367da6fca 100644 Binary files a/utils/7z/7za.dll and b/utils/7z/7za.dll differ diff --git a/utils/7z/7za.exe b/utils/7z/7za.exe index dcc062261f..bb7216dd84 100644 Binary files a/utils/7z/7za.exe and b/utils/7z/7za.exe differ diff --git a/utils/7z/7zxa.dll b/utils/7z/7zxa.dll index 084610b8f4..ccb3e98251 100644 Binary files a/utils/7z/7zxa.dll and b/utils/7z/7zxa.dll differ diff --git a/utils/breakpad/dump_syms b/utils/breakpad/dump_syms index febbca066b..b89e9ad6c9 100755 Binary files a/utils/breakpad/dump_syms and b/utils/breakpad/dump_syms differ diff --git a/utils/breakpad/dump_syms_apple b/utils/breakpad/dump_syms_apple new file mode 100644 index 0000000000..72c74cbbfb Binary files /dev/null and b/utils/breakpad/dump_syms_apple differ diff --git a/utils/buildactions/compose_files.lua b/utils/buildactions/compose_files.lua index 081b44ef67..0adaf2cfc1 100644 --- a/utils/buildactions/compose_files.lua +++ b/utils/buildactions/compose_files.lua @@ -25,6 +25,7 @@ newaction { -- Copy configs os.copydir("Server/mods/deathmatch", OUTPUT_DIR.."/server/mods/deathmatch", "*.conf") + os.copydir("Server/mods/deathmatch", OUTPUT_DIR.."/server/mods/deathmatch", "mtaserver.conf.template") os.copydir("Server/mods/deathmatch", OUTPUT_DIR.."/server/mods/deathmatch", "*.xml") -- Copy compiled binaries diff --git a/utils/buildactions/install_cef.lua b/utils/buildactions/install_cef.lua index 91a041c2bc..9dc4ccdc71 100644 --- a/utils/buildactions/install_cef.lua +++ b/utils/buildactions/install_cef.lua @@ -9,8 +9,8 @@ local CEF_URL_PREFIX = "https://cef-builds.spotifycdn.com/cef_binary_" local CEF_URL_SUFFIX = "_windows32_minimal.tar.bz2" -- Change here to update CEF version -local CEF_VERSION = "119.3.1+gf768881+chromium-119.0.6045.124" -local CEF_HASH = "59d8ead17a8cb355b0a1d2b3d57e94139ccb7fe6c33c9e7365451ee5c7e7e7f4" +local CEF_VERSION = "129.0.6+ga918aa7+chromium-129.0.6668.29" +local CEF_HASH = "989b267d6c2eed6feed4ef304664763612619f1d4ca7f21d95a524c139870d36" function make_cef_download_url() return CEF_URL_PREFIX..http.escapeUrlParam(CEF_VERSION)..CEF_URL_SUFFIX diff --git a/utils/buildactions/install_data.lua b/utils/buildactions/install_data.lua index f841d2d4df..930ecf3519 100644 --- a/utils/buildactions/install_data.lua +++ b/utils/buildactions/install_data.lua @@ -49,6 +49,13 @@ newaction { return end + local success, message = os.copydir("Server/mods/deathmatch", BIN_DIR.."/server/mods/deathmatch", "mtaserver.conf.template", false, true) + if not success then + errormsg("ERROR: Couldn't copy server config files", "\n"..message) + os.exit(1) + return + end + local success, message = os.copydir("Server/mods/deathmatch", BIN_DIR.."/server/mods/deathmatch", "*.xml", false, true) if not success then errormsg("ERROR: Couldn't copy server xml files", "\n"..message) diff --git a/utils/buildactions/install_unifont.lua b/utils/buildactions/install_unifont.lua index eb34d5059a..35cf5ed650 100644 --- a/utils/buildactions/install_unifont.lua +++ b/utils/buildactions/install_unifont.lua @@ -4,13 +4,13 @@ premake.modules.install_unifont = {} -- Config variables local UNIFONT_BASEURL = "https://github.com/multitheftauto/unifont/releases/download/" -local UNIFONT_DOWNLOAD_FILENAME = "unifont-15.1.01.ttf" +local UNIFONT_DOWNLOAD_FILENAME = "unifont-15.1.05.ttf" local UNIFONT_FILENAME = "unifont.ttf" local UNIFONT_PATH = "Shared/data/MTA San Andreas/MTA/cgui" -- Change these to update the version -local UNIFONT_TAG = "v15.1.01" -local UNIFONT_HASH = "46dce92d451faeb23d1d08a1c7448f10c60af444d2d688674dc91e85081f2c3b" +local UNIFONT_TAG = "v15.1.05" +local UNIFONT_HASH = "ed6457062d96e58eaf6c77958a78068017fb4db8022e41b79435c3bc23c536d9" newaction { trigger = "install_unifont", diff --git a/utils/docker-entrypoint-osx.sh b/utils/docker-entrypoint-osx.sh deleted file mode 100644 index 6b40c2a7c2..0000000000 --- a/utils/docker-entrypoint-osx.sh +++ /dev/null @@ -1,16 +0,0 @@ -#!/bin/bash - -# If configurede as a build agent, start Teamcity agent -if [[ $AS_BUILDAGENT = "1" ]]; then - # https://github.com/JetBrains/teamcity-docker-minimal-agent/blob/master/Dockerfile#L17 - exec /run-services.sh -fi - -# Manually invoke build process -# So, first make a shallow clone of the repository if it not exists -umask 000 -if [ ! -f ./premake5.lua ]; then - git clone --depth=1 https://github.com/multitheftauto/mtasa-blue.git . -fi - -./linux-build.sh --os=macosx --arch=$BUILD_ARCHITECTURE --config=$BUILD_CONFIG diff --git a/utils/localization/generate-images/package-lock.json b/utils/localization/generate-images/package-lock.json index f5cad8686b..2dadb06346 100644 --- a/utils/localization/generate-images/package-lock.json +++ b/utils/localization/generate-images/package-lock.json @@ -10,7 +10,7 @@ "license": "GPL-3.0-or-later", "dependencies": { "@squoosh/lib": "~0.4.0", - "chromedriver": "^114.0.2", + "chromedriver": "^119.0.1", "fs-extra": "^11.1.1", "http-server": "^14.1.1", "selenium-webdriver": "^4.10.0" @@ -29,9 +29,9 @@ } }, "node_modules/@testim/chrome-version": { - "version": "1.1.3", - "resolved": "https://registry.npmjs.org/@testim/chrome-version/-/chrome-version-1.1.3.tgz", - "integrity": "sha512-g697J3WxV/Zytemz8aTuKjTGYtta9+02kva3C1xc7KXB8GdbfE1akGJIsZLyY/FSh2QrnE+fiB7vmWU3XNcb6A==" + "version": "1.1.4", + "resolved": "https://registry.npmjs.org/@testim/chrome-version/-/chrome-version-1.1.4.tgz", + "integrity": "sha512-kIhULpw9TrGYnHp/8VfdcneIcxKnLixmADtukQRtJUmsVlMg0niMkwV0xZmi8hqa57xqilIHjWFA0GKvEjVU5g==" }, "node_modules/@types/node": { "version": "20.3.0", @@ -87,9 +87,9 @@ "integrity": "sha512-Oei9OH4tRh0YqU3GxhX79dM/mwVgvbZJaSNaRk+bshkj0S5cfHcgYakreBjrHwatXKbz+IoIdYLxrKim2MjW0Q==" }, "node_modules/axios": { - "version": "1.4.0", - "resolved": "https://registry.npmjs.org/axios/-/axios-1.4.0.tgz", - "integrity": "sha512-S4XCWMEmzvo64T9GfvQDOXgYRDJ/wsSZc7Jvdgx5u1sd0JwsuPLqb3SYmusag+edF6ziyMensPVqLTSc1PiSEA==", + "version": "1.6.1", + "resolved": "https://registry.npmjs.org/axios/-/axios-1.6.1.tgz", + "integrity": "sha512-vfBmhDpKafglh0EldBEbVuoe7DyAavGSLWhuSm5ZSEKQnHhBf0xAAwybbNH1IkrJNGnS/VG4I5yxig1pCEXE4g==", "dependencies": { "follow-redirects": "^1.15.0", "form-data": "^4.0.0", @@ -157,24 +157,24 @@ } }, "node_modules/chromedriver": { - "version": "114.0.2", - "resolved": "https://registry.npmjs.org/chromedriver/-/chromedriver-114.0.2.tgz", - "integrity": "sha512-v0qrXRBknbxqmtklG7RWOe3TJ/dLaHhtB0jVxE7BAdYERxUjEaNRyqBwoGgVfQDibHCB0swzvzsj158nnfPgZw==", + "version": "119.0.1", + "resolved": "https://registry.npmjs.org/chromedriver/-/chromedriver-119.0.1.tgz", + "integrity": "sha512-lpCFFLaXPpvElTaUOWKdP74pFb/sJhWtWqMjn7Ju1YriWn8dT5JBk84BGXMPvZQs70WfCYWecxdMmwfIu1Mupg==", "hasInstallScript": true, "dependencies": { - "@testim/chrome-version": "^1.1.3", - "axios": "^1.4.0", - "compare-versions": "^5.0.3", + "@testim/chrome-version": "^1.1.4", + "axios": "^1.6.0", + "compare-versions": "^6.1.0", "extract-zip": "^2.0.1", "https-proxy-agent": "^5.0.1", "proxy-from-env": "^1.1.0", - "tcp-port-used": "^1.0.1" + "tcp-port-used": "^1.0.2" }, "bin": { "chromedriver": "bin/chromedriver" }, "engines": { - "node": ">=16" + "node": ">=18" } }, "node_modules/color-convert": { @@ -205,9 +205,9 @@ } }, "node_modules/compare-versions": { - "version": "5.0.3", - "resolved": "https://registry.npmjs.org/compare-versions/-/compare-versions-5.0.3.tgz", - "integrity": "sha512-4UZlZP8Z99MGEY+Ovg/uJxJuvoXuN4M6B3hKaiackiHrgzQFEe3diJi1mf1PNHbFujM7FvLrK2bpgIaImbtZ1A==" + "version": "6.1.0", + "resolved": "https://registry.npmjs.org/compare-versions/-/compare-versions-6.1.0.tgz", + "integrity": "sha512-LNZQXhqUvqUTotpZ00qLSaify3b4VFD588aRr8MKFw4CMUr98ytzCW5wDH5qx/DEY5kCDXcbcRuCqL0szEf2tg==" }, "node_modules/concat-map": { "version": "0.0.1", @@ -297,9 +297,9 @@ } }, "node_modules/follow-redirects": { - "version": "1.15.2", - "resolved": "https://registry.npmjs.org/follow-redirects/-/follow-redirects-1.15.2.tgz", - "integrity": "sha512-VQLG33o04KaQ8uYi2tVNbdrWp1QWxNNea+nmIB4EVM28v0hmP17z7aG1+wAkNzVq4KeXTq3221ye5qTJP91JwA==", + "version": "1.15.6", + "resolved": "https://registry.npmjs.org/follow-redirects/-/follow-redirects-1.15.6.tgz", + "integrity": "sha512-wWN62YITEaOpSK584EZXJafH1AGpO8RVgElfkuXbTOrPX4fIfOyEpW/CsiNd8JdYrAoOvafRTOEnvsO++qCqFA==", "funding": [ { "type": "individual", @@ -964,9 +964,9 @@ "integrity": "sha512-l4Sp/DRseor9wL6EvV2+TuQn63dMkPjZ/sp9XkghTEbV9KlPS1xUsZ3u7/IQO4wxtcFB4bgpQPRcR3QCvezPcQ==" }, "node_modules/ws": { - "version": "8.13.0", - "resolved": "https://registry.npmjs.org/ws/-/ws-8.13.0.tgz", - "integrity": "sha512-x9vcZYTrFPC7aSIbj7sRCYo7L/Xb8Iy+pW0ng0wt2vCJv7M9HOMy0UoN3rr+IFC7hb7vXoqS+P9ktyLLLhO+LA==", + "version": "8.17.1", + "resolved": "https://registry.npmjs.org/ws/-/ws-8.17.1.tgz", + "integrity": "sha512-6XQFvXTkbfUOZOKKILFG1PDK2NDQs4azKQl26T0YS5CxqWLgXajbPZ+h4gZekJyRqFU8pvnbAbbs/3TgRPy+GQ==", "engines": { "node": ">=10.0.0" }, diff --git a/utils/localization/generate-images/package.json b/utils/localization/generate-images/package.json index 0fc7706232..44b6858046 100644 --- a/utils/localization/generate-images/package.json +++ b/utils/localization/generate-images/package.json @@ -11,7 +11,7 @@ }, "dependencies": { "@squoosh/lib": "~0.4.0", - "chromedriver": "^114.0.2", + "chromedriver": "^119.0.1", "fs-extra": "^11.1.1", "http-server": "^14.1.1", "selenium-webdriver": "^4.10.0" diff --git a/vendor/cef3/premake5.lua b/vendor/cef3/premake5.lua index 9b8dc65702..115d004975 100644 --- a/vendor/cef3/premake5.lua +++ b/vendor/cef3/premake5.lua @@ -20,7 +20,7 @@ project "CEF" postbuildcommands { "{COPY} \""..cef_path.."Release/*\" \""..path.."mta\"", "{COPY} \""..cef_path.."Resources/icudtl.dat\" \""..path.."mta\"", - "{COPY} \""..cef_path.."Resources/*.pak\" \""..path.."mta/cef\"", + "{COPY} \""..cef_path.."Resources/*.pak\" \""..path.."mta\"", "{COPY} \""..cef_path.."Resources/locales/*\" \""..path.."mta/cef/locales\"" } diff --git a/vendor/cryptopp/aria_simd.cpp b/vendor/cryptopp/aria_simd.cpp deleted file mode 100644 index 3a390edf07..0000000000 --- a/vendor/cryptopp/aria_simd.cpp +++ /dev/null @@ -1,194 +0,0 @@ -// aria_simd.cpp - written and placed in the public domain by -// Jeffrey Walton, Uri Blumenthal and Marcel Raad. -// -// This source file uses intrinsics to gain access to ARMv7a and -// ARMv8a NEON instructions. A separate source file is needed -// because additional CXXFLAGS are required to enable the -// appropriate instructions sets in some build configurations. - -#include "pch.h" -#include "config.h" -#include "misc.h" - -#if (CRYPTOPP_SSSE3_AVAILABLE) -# include -#endif - -#if (CRYPTOPP_ARM_NEON_HEADER) -# include -#endif - -#if (CRYPTOPP_ARM_ACLE_HEADER) -# include -# include -#endif - -// Squash MS LNK4221 and libtool warnings -extern const char ARIA_SIMD_FNAME[] = __FILE__; - -NAMESPACE_BEGIN(CryptoPP) -NAMESPACE_BEGIN(ARIATab) - -extern const word32 S1[256]; -extern const word32 S2[256]; -extern const word32 X1[256]; -extern const word32 X2[256]; -extern const word32 KRK[3][4]; - -NAMESPACE_END -NAMESPACE_END - -ANONYMOUS_NAMESPACE_BEGIN - -using CryptoPP::byte; -using CryptoPP::word32; - -inline byte ARIA_BRF(const word32 x, const int y) { - return static_cast(GETBYTE(x, y)); -} - -ANONYMOUS_NAMESPACE_END - -NAMESPACE_BEGIN(CryptoPP) - -using CryptoPP::ARIATab::S1; -using CryptoPP::ARIATab::S2; -using CryptoPP::ARIATab::X1; -using CryptoPP::ARIATab::X2; -using CryptoPP::ARIATab::KRK; - -#if (CRYPTOPP_ARM_NEON_AVAILABLE) - -template -inline void ARIA_GSRK_NEON(const uint32x4_t X, const uint32x4_t Y, byte RK[16]) -{ - enum { Q1 = (4-(N/32)) % 4, - Q2 = (3-(N/32)) % 4, - R = N % 32 - }; - - vst1q_u8(RK, vreinterpretq_u8_u32( - veorq_u32(X, veorq_u32( - vshrq_n_u32(vextq_u32(Y, Y, Q1), R), - vshlq_n_u32(vextq_u32(Y, Y, Q2), 32-R))))); -} - -void ARIA_UncheckedSetKey_Schedule_NEON(byte* rk, word32* ws, unsigned int keylen) -{ - const uint32x4_t w0 = vld1q_u32(ws+ 0); - const uint32x4_t w1 = vld1q_u32(ws+ 8); - const uint32x4_t w2 = vld1q_u32(ws+12); - const uint32x4_t w3 = vld1q_u32(ws+16); - - ARIA_GSRK_NEON<19>(w0, w1, rk + 0); - ARIA_GSRK_NEON<19>(w1, w2, rk + 16); - ARIA_GSRK_NEON<19>(w2, w3, rk + 32); - ARIA_GSRK_NEON<19>(w3, w0, rk + 48); - ARIA_GSRK_NEON<31>(w0, w1, rk + 64); - ARIA_GSRK_NEON<31>(w1, w2, rk + 80); - ARIA_GSRK_NEON<31>(w2, w3, rk + 96); - ARIA_GSRK_NEON<31>(w3, w0, rk + 112); - ARIA_GSRK_NEON<67>(w0, w1, rk + 128); - ARIA_GSRK_NEON<67>(w1, w2, rk + 144); - ARIA_GSRK_NEON<67>(w2, w3, rk + 160); - ARIA_GSRK_NEON<67>(w3, w0, rk + 176); - ARIA_GSRK_NEON<97>(w0, w1, rk + 192); - - if (keylen > 16) - { - ARIA_GSRK_NEON<97>(w1, w2, rk + 208); - ARIA_GSRK_NEON<97>(w2, w3, rk + 224); - - if (keylen > 24) - { - ARIA_GSRK_NEON< 97>(w3, w0, rk + 240); - ARIA_GSRK_NEON<109>(w0, w1, rk + 256); - } - } -} - -void ARIA_ProcessAndXorBlock_NEON(const byte* xorBlock, byte* outBlock, const byte *rk, word32 *t) -{ - outBlock[ 0] = (byte)(X1[ARIA_BRF(t[0],3)] ); - outBlock[ 1] = (byte)(X2[ARIA_BRF(t[0],2)]>>8); - outBlock[ 2] = (byte)(S1[ARIA_BRF(t[0],1)] ); - outBlock[ 3] = (byte)(S2[ARIA_BRF(t[0],0)] ); - outBlock[ 4] = (byte)(X1[ARIA_BRF(t[1],3)] ); - outBlock[ 5] = (byte)(X2[ARIA_BRF(t[1],2)]>>8); - outBlock[ 6] = (byte)(S1[ARIA_BRF(t[1],1)] ); - outBlock[ 7] = (byte)(S2[ARIA_BRF(t[1],0)] ); - outBlock[ 8] = (byte)(X1[ARIA_BRF(t[2],3)] ); - outBlock[ 9] = (byte)(X2[ARIA_BRF(t[2],2)]>>8); - outBlock[10] = (byte)(S1[ARIA_BRF(t[2],1)] ); - outBlock[11] = (byte)(S2[ARIA_BRF(t[2],0)] ); - outBlock[12] = (byte)(X1[ARIA_BRF(t[3],3)] ); - outBlock[13] = (byte)(X2[ARIA_BRF(t[3],2)]>>8); - outBlock[14] = (byte)(S1[ARIA_BRF(t[3],1)] ); - outBlock[15] = (byte)(S2[ARIA_BRF(t[3],0)] ); - - // 'outBlock' and 'xorBlock' may be unaligned. - if (xorBlock != NULLPTR) - { - vst1q_u8(outBlock, - veorq_u8( - vld1q_u8(xorBlock), - veorq_u8( - vld1q_u8(outBlock), - vrev32q_u8(vld1q_u8((rk)))))); - } - else - { - vst1q_u8(outBlock, - veorq_u8( - vld1q_u8(outBlock), - vrev32q_u8(vld1q_u8(rk)))); - } -} - -#endif // CRYPTOPP_ARM_NEON_AVAILABLE - -#if (CRYPTOPP_SSSE3_AVAILABLE) - -void ARIA_ProcessAndXorBlock_SSSE3(const byte* xorBlock, byte* outBlock, const byte *rk, word32 *t) -{ - const __m128i MASK = _mm_set_epi8(12,13,14,15, 8,9,10,11, 4,5,6,7, 0,1,2,3); - - outBlock[ 0] = (byte)(X1[ARIA_BRF(t[0],3)] ); - outBlock[ 1] = (byte)(X2[ARIA_BRF(t[0],2)]>>8); - outBlock[ 2] = (byte)(S1[ARIA_BRF(t[0],1)] ); - outBlock[ 3] = (byte)(S2[ARIA_BRF(t[0],0)] ); - outBlock[ 4] = (byte)(X1[ARIA_BRF(t[1],3)] ); - outBlock[ 5] = (byte)(X2[ARIA_BRF(t[1],2)]>>8); - outBlock[ 6] = (byte)(S1[ARIA_BRF(t[1],1)] ); - outBlock[ 7] = (byte)(S2[ARIA_BRF(t[1],0)] ); - outBlock[ 8] = (byte)(X1[ARIA_BRF(t[2],3)] ); - outBlock[ 9] = (byte)(X2[ARIA_BRF(t[2],2)]>>8); - outBlock[10] = (byte)(S1[ARIA_BRF(t[2],1)] ); - outBlock[11] = (byte)(S2[ARIA_BRF(t[2],0)] ); - outBlock[12] = (byte)(X1[ARIA_BRF(t[3],3)] ); - outBlock[13] = (byte)(X2[ARIA_BRF(t[3],2)]>>8); - outBlock[14] = (byte)(S1[ARIA_BRF(t[3],1)] ); - outBlock[15] = (byte)(S2[ARIA_BRF(t[3],0)] ); - - // 'outBlock' and 'xorBlock' may be unaligned. - if (xorBlock != NULLPTR) - { - _mm_storeu_si128(M128_CAST(outBlock), - _mm_xor_si128( - _mm_loadu_si128(CONST_M128_CAST(xorBlock)), - _mm_xor_si128( - _mm_loadu_si128(CONST_M128_CAST(outBlock)), - _mm_shuffle_epi8(_mm_load_si128(CONST_M128_CAST(rk)), MASK))) - ); - } - else - { - _mm_storeu_si128(M128_CAST(outBlock), - _mm_xor_si128(_mm_loadu_si128(CONST_M128_CAST(outBlock)), - _mm_shuffle_epi8(_mm_load_si128(CONST_M128_CAST(rk)), MASK))); - } -} - -#endif // CRYPTOPP_SSSE3_AVAILABLE - -NAMESPACE_END diff --git a/vendor/cryptopp/asn.h b/vendor/cryptopp/asn.h index cf44fc7278..beb20cd0f5 100644 --- a/vendor/cryptopp/asn.h +++ b/vendor/cryptopp/asn.h @@ -331,7 +331,8 @@ class CRYPTOPP_DLL OID protected: friend bool operator==(const OID &lhs, const OID &rhs); friend bool operator!=(const OID &lhs, const OID &rhs); - friend bool operator<(const OID &lhs, const OID &rhs); + friend bool operator< (const OID &lhs, const OID &rhs); + friend bool operator> (const OID &lhs, const OID &rhs); friend bool operator<=(const OID &lhs, const OID &rhs); friend bool operator>=(const OID &lhs, const OID &rhs); @@ -913,11 +914,18 @@ inline bool operator!=(const OID &lhs, const OID &rhs); /// \param lhs the first OID /// \param rhs the second OID /// \return true if the first OID is less than the second OID, false otherwise -/// \details operator<() calls std::lexicographical_compare() on each element in the array of values. +/// \details operator<() calls std::lexicographical_compare() on the values. inline bool operator<(const OID &lhs, const OID &rhs); /// \brief Compare two OIDs for ordering /// \param lhs the first OID /// \param rhs the second OID +/// \return true if the first OID is greater than the second OID, false otherwise +/// \details operator>() is implemented in terms of operator==() and operator<(). +/// \since Crypto++ 8.3 +inline bool operator>(const OID &lhs, const OID &rhs); +/// \brief Compare two OIDs for ordering +/// \param lhs the first OID +/// \param rhs the second OID /// \return true if the first OID is less than or equal to the second OID, false otherwise /// \details operator<=() is implemented in terms of operator==() and operator<(). /// \since Crypto++ 8.3 @@ -936,8 +944,7 @@ inline OID operator+(const OID &lhs, unsigned long rhs); /// \brief Print a OID value /// \param out the output stream /// \param oid the OID -inline std::ostream& operator<<(std::ostream& out, const OID &oid) - { return oid.Print(out); } +inline std::ostream& operator<<(std::ostream& out, const OID &oid); #else inline bool operator==(const ::CryptoPP::OID &lhs, const ::CryptoPP::OID &rhs) {return lhs.m_values == rhs.m_values;} @@ -945,6 +952,8 @@ inline bool operator!=(const ::CryptoPP::OID &lhs, const ::CryptoPP::OID &rhs) {return lhs.m_values != rhs.m_values;} inline bool operator<(const ::CryptoPP::OID &lhs, const ::CryptoPP::OID &rhs) {return std::lexicographical_compare(lhs.m_values.begin(), lhs.m_values.end(), rhs.m_values.begin(), rhs.m_values.end());} +inline bool operator>(const ::CryptoPP::OID &lhs, const ::CryptoPP::OID &rhs) + {return ! (lhs=(const ::CryptoPP::OID &lhs, const ::CryptoPP::OID &rhs) diff --git a/vendor/cryptopp/config_asm.h b/vendor/cryptopp/config_asm.h index d5629c7714..edfbdefb80 100644 --- a/vendor/cryptopp/config_asm.h +++ b/vendor/cryptopp/config_asm.h @@ -27,12 +27,12 @@ #include "config_cpu.h" #include "config_ver.h" -// Define this to disable ASM, intrinsics and built-ins. The library will be -// compiled using C++ only. The library code will not include SSE2 (and -// above), NEON, Aarch32, Aarch64, or Altivec (and above). Note the compiler -// may use higher ISAs depending on compiler options, but the library will not -// explicitly use the ISAs. When disabling ASM, it is best to do it from -// config.h to ensure the library and all programs share the setting. +// Define this to disable ASM, intrinsics and built-ins. The library code will +// not explicitly include SSE2 (and above), NEON, Aarch32, Aarch64, or Altivec +// (and above). Note the compiler may use higher ISAs depending on compiler +// options, but the library will not explicitly use the ISAs. When disabling ASM, +// it is best to do it from config_asm.h to ensure the library and all programs +// share the setting. // #define CRYPTOPP_DISABLE_ASM 1 // https://github.com/weidai11/cryptopp/issues/719 diff --git a/vendor/cryptopp/config_cpu.h b/vendor/cryptopp/config_cpu.h index 4020b1be54..15f694e793 100644 --- a/vendor/cryptopp/config_cpu.h +++ b/vendor/cryptopp/config_cpu.h @@ -203,7 +203,7 @@ /// _MSC_VER nor __BORLANDC__ are defined. #define CRYPTOPP_GNU_STYLE_INLINE_ASSEMBLY ... #elif defined(CRYPTOPP_MSC_VERSION) || defined(__BORLANDC__) || \ - (defined(CRYPTOPP_WIN32_AVAILABLE) && defined(CRYPTOPP_LLVM_CLANG_VERSION)) + defined(CRYPTOPP_MSVC_CLANG_VERSION) #define CRYPTOPP_MS_STYLE_INLINE_ASSEMBLY 1 #else #define CRYPTOPP_GNU_STYLE_INLINE_ASSEMBLY 1 diff --git a/vendor/cryptopp/config_ver.h b/vendor/cryptopp/config_ver.h index 4752692ac2..c7e457c2aa 100644 --- a/vendor/cryptopp/config_ver.h +++ b/vendor/cryptopp/config_ver.h @@ -58,6 +58,8 @@ // LLVM Clang version 3.7. Also see https://gist.github.com/yamaya/2924292 #if defined(__clang__) && defined(__apple_build_version__) # define CRYPTOPP_APPLE_CLANG_VERSION (__clang_major__ * 10000 + __clang_minor__ * 100 + __clang_patchlevel__) +#elif defined(__clang__) && defined(_MSC_VER) +# define CRYPTOPP_MSVC_CLANG_VERSION (__clang_major__ * 10000 + __clang_minor__ * 100 + __clang_patchlevel__) #elif defined(__clang__) # define CRYPTOPP_LLVM_CLANG_VERSION (__clang_major__ * 10000 + __clang_minor__ * 100 + __clang_patchlevel__) #endif diff --git a/vendor/cryptopp/cpu.cpp b/vendor/cryptopp/cpu.cpp index ab25bea9f1..f61fef39ba 100644 --- a/vendor/cryptopp/cpu.cpp +++ b/vendor/cryptopp/cpu.cpp @@ -388,9 +388,14 @@ extern bool CPU_ProbeSSE2(); // https://gcc.gnu.org/bugzilla/show_bug.cgi?id=85684. word64 XGetBV(word32 num) { +// Explicitly handle CRYPTOPP_DISABLE_ASM case. +// https://github.com/weidai11/cryptopp/issues/1240 +#if defined(CRYPTOPP_DISABLE_ASM) + return 0; + // Required by Visual Studio 2008 and below and Clang on Windows. // Use it for all MSVC-compatible compilers. -#if defined(_M_X64) && defined(CRYPTOPP_MS_STYLE_INLINE_ASSEMBLY) +#elif defined(_M_X64) && defined(CRYPTOPP_MS_STYLE_INLINE_ASSEMBLY) return XGETBV64(num); @@ -446,9 +451,15 @@ word64 XGetBV(word32 num) // cpu.cpp (131): E2211 Inline assembly not allowed in inline and template functions bool CpuId(word32 func, word32 subfunc, word32 output[4]) { +// Explicitly handle CRYPTOPP_DISABLE_ASM case. +// https://github.com/weidai11/cryptopp/issues/1240 +#if defined(CRYPTOPP_DISABLE_ASM) + output[0] = output[1] = output[2] = output[3] = 0; + return false; + // Required by Visual Studio 2008 and below and Clang on Windows. // Use it for all MSVC-compatible compilers. -#if defined(_M_X64) && defined(CRYPTOPP_MS_STYLE_INLINE_ASSEMBLY) +#elif defined(_M_X64) && defined(CRYPTOPP_MS_STYLE_INLINE_ASSEMBLY) CPUID64(func, subfunc, output); return true; @@ -592,15 +603,16 @@ void DetectX86Features() (cpuid1[ECX_REG] & OSXSAVE_FLAG) != 0; #endif -#if defined(__sun) // Solaris 11 i86pc does not signal SSE support using - // OSXSAVE. We need to probe for SSE support. + // OSXSAVE. Additionally, Fedora 38 on a 2015 Celeron + // N3700 does not set OSXSAVE. So we need to explicitly + // probe for SSE support on rare occasions. Ugh... if (g_hasSSE2 == false) + { g_hasSSE2 = CPU_ProbeSSE2(); -#endif - - if (g_hasSSE2 == false) - goto done; + if (g_hasSSE2 == false) + goto done; + } g_hasSSSE3 = (cpuid1[ECX_REG] & SSSE3_FLAG) != 0; g_hasSSE41 = (cpuid1[ECX_REG] & SSE41_FLAG) != 0; diff --git a/vendor/cryptopp/cpuid64.asm b/vendor/cryptopp/cpuid64.asm new file mode 100644 index 0000000000..6951bbc88e --- /dev/null +++ b/vendor/cryptopp/cpuid64.asm @@ -0,0 +1,63 @@ +;; https://docs.microsoft.com/en-us/cpp/build/x64-calling-convention +;; The first four integer arguments are passed in registers. +;; Integer values are passed in left-to-right order in RCX, +;; RDX, R8, and R9, respectively. Arguments five and higher +;; are passed on the stack. + +;; The registers RAX, RCX, RDX, R8, R9, R10, R11, XMM0-5, +;; and the upper portions of YMM0-15 and ZMM0-15 are +;; considered volatile and must be considered destroyed on +;; function calls. + +.CODE + +TITLE CPU features source file +SUBTITLE Microsoft specific ASM code to utilize CPUID and XGETBV64 for down level Microsoft toolchains + +;; http://www.agner.org/optimize/vectorclass/read.php?i=65 +;; word64 Xgetbv(word32 ctrl) +;; ctrl = rcx + + ALIGN 8 +XGETBV64 PROC FRAME +.endprolog + ;; query + DB 0fh, 01h, 0d0h + ;; xcr = (EDX << 32) | EAX + and rax, 0ffffffffh + shl rdx, 32 + or rax, rdx + ret +XGETBV64 ENDP + +;; word64 CpuId(word32 func, word32 subfunc, word32 output[4]) +;; func = rcx +;; subfunc = rdx +;; output = r8 + + ALIGN 8 +CPUID64 PROC FRAME + ;; preserve per ABI + mov [rsp+8], rbx +.savereg rbx, 8 +.endprolog + ;; eax = func + mov rax, rcx + ;; ecx = subfunc + mov rcx, rdx + ;; query + cpuid + ;; save + mov [r8+0], eax + mov [r8+4], ebx + mov [r8+8], ecx + mov [r8+12], edx + ;; return value + mov rax, 1 + ;; restore + mov rbx, [rsp+8] + ret +CPUID64 ENDP + +_TEXT ENDS +END diff --git a/vendor/cryptopp/ecp.cpp b/vendor/cryptopp/ecp.cpp index f8ba60f637..2c70c48ed4 100644 --- a/vendor/cryptopp/ecp.cpp +++ b/vendor/cryptopp/ecp.cpp @@ -119,7 +119,11 @@ bool ECP::DecodePoint(ECP::Point &P, BufferedTransformation &bt, size_t encodedP if (encodedPointLen != EncodedPointSize(true)) return false; - Integer p = FieldSize(); + // Check for p is prime due to GH #1249 + const Integer p = FieldSize(); + CRYPTOPP_ASSERT(IsPrime(p)); + if (!IsPrime(p)) + return false; P.identity = false; P.x.Decode(bt, GetField().MaxElementByteLength()); @@ -128,6 +132,7 @@ bool ECP::DecodePoint(ECP::Point &P, BufferedTransformation &bt, size_t encodedP if (Jacobi(P.y, p) !=1) return false; + // Callers must ensure p is prime, GH #1249 P.y = ModularSquareRoot(P.y, p); if ((type & 1) != P.y.GetBit(0)) diff --git a/vendor/cryptopp/esign.cpp b/vendor/cryptopp/esign.cpp index 70dde2fbd2..932490c87b 100644 --- a/vendor/cryptopp/esign.cpp +++ b/vendor/cryptopp/esign.cpp @@ -111,6 +111,9 @@ void InvertibleESIGNFunction::GenerateRandom(RandomNumberGenerator &rng, const N if (param.GetValue("Seed", seedParam)) { + if (seedParam.size() > seed.ELEMS_MAX - 4) + throw InvalidArgument("InvertibleESIGNFunction::GenerateRandom: buffer overflow"); + seed.resize(seedParam.size() + 4); std::memcpy(seed + 4, seedParam.begin(), seedParam.size()); diff --git a/vendor/cryptopp/gf2n.cpp b/vendor/cryptopp/gf2n.cpp index 7854db1b00..8580717b20 100644 --- a/vendor/cryptopp/gf2n.cpp +++ b/vendor/cryptopp/gf2n.cpp @@ -135,6 +135,14 @@ PolynomialMod2 PolynomialMod2::Monomial(size_t i) PolynomialMod2 PolynomialMod2::Trinomial(size_t t0, size_t t1, size_t t2) { + // Asserts and checks due to Bing Shi + CRYPTOPP_ASSERT(t0 > t1); + CRYPTOPP_ASSERT(t1 > t2); + + // The test is relaxed because of ECIES. The high order exponent is t0, but the other exponents are not in descending order. + if (t1 > t0 || t2 > t0) + throw InvalidArgument("PolynomialMod2: exponents must be in descending order"); + PolynomialMod2 r((word)0, t0+1); r.SetBit(t0); r.SetBit(t1); @@ -144,6 +152,16 @@ PolynomialMod2 PolynomialMod2::Trinomial(size_t t0, size_t t1, size_t t2) PolynomialMod2 PolynomialMod2::Pentanomial(size_t t0, size_t t1, size_t t2, size_t t3, size_t t4) { + // Asserts and checks due to Bing Shi + CRYPTOPP_ASSERT(t0 > t1); + CRYPTOPP_ASSERT(t1 > t2); + CRYPTOPP_ASSERT(t2 > t3); + CRYPTOPP_ASSERT(t3 > t4); + + // The test is relaxed because of ECIES. The high order exponent is t0, but the other exponents are not in descending order. + if (t1 > t0 || t2 > t0 || t3 > t0 || t4 > t0) + throw InvalidArgument("PolynomialMod2: exponents must be in descending order"); + PolynomialMod2 r((word)0, t0+1); r.SetBit(t0); r.SetBit(t1); @@ -655,7 +673,12 @@ GF2NT::GF2NT(unsigned int c0, unsigned int c1, unsigned int c2) , t0(c0), t1(c1) , result((word)0, m) { + // Asserts and checks due to Bing Shi CRYPTOPP_ASSERT(c0 > c1 && c1 > c2 && c2==0); + + // The test is relaxed because of ECIES. The high order exponent is t0, but the other exponents are not in descending order. + if (c1 > c0 || c2 > c0) + throw InvalidArgument("GF2NT: exponents must be in descending order"); } const GF2NT::Element& GF2NT::MultiplicativeInverse(const Element &a) const @@ -964,7 +987,12 @@ GF2NP * BERDecodeGF2NP(BufferedTransformation &bt) GF2NT233::GF2NT233(unsigned int c0, unsigned int c1, unsigned int c2) : GF2NT(c0, c1, c2) { + // Asserts and checks due to Bing Shi CRYPTOPP_ASSERT(c0 > c1 && c1 > c2 && c2==0); + + // The test is relaxed because of ECIES. The high order exponent is t0, but the other exponents are not in descending order. + if (c1 > c0 || c2 > c0) + throw InvalidArgument("GF2NT233: exponents must be in descending order"); } const GF2NT::Element& GF2NT233::Multiply(const Element &a, const Element &b) const diff --git a/vendor/cryptopp/gf2n.h b/vendor/cryptopp/gf2n.h index 075635283d..4b61fb8813 100644 --- a/vendor/cryptopp/gf2n.h +++ b/vendor/cryptopp/gf2n.h @@ -69,9 +69,11 @@ class CRYPTOPP_DLL PolynomialMod2 static PolynomialMod2 CRYPTOPP_API Monomial(size_t i); /// \brief Provides x^t0 + x^t1 + x^t2 /// \return x^t0 + x^t1 + x^t2 + /// \pre The coefficients should be provided in descending order. That is,
t0 > t1 > t2
.
 		static PolynomialMod2 CRYPTOPP_API Trinomial(size_t t0, size_t t1, size_t t2);
 		/// \brief Provides x^t0 + x^t1 + x^t2 + x^t3 + x^t4
 		/// \return x^t0 + x^t1 + x^t2 + x^t3 + x^t4
+		/// \pre The coefficients should be provided in descending order. That is, 
t0 > t1 > t2 > t3 > t4
.
 		static PolynomialMod2 CRYPTOPP_API Pentanomial(size_t t0, size_t t1, size_t t2, size_t t3, size_t t4);
 		/// \brief Provides x^(n-1) + ... + x + 1
 		/// \return x^(n-1) + ... + x + 1
diff --git a/vendor/cryptopp/nbtheory.cpp b/vendor/cryptopp/nbtheory.cpp
index da6f1b923f..d4b8cfa507 100644
--- a/vendor/cryptopp/nbtheory.cpp
+++ b/vendor/cryptopp/nbtheory.cpp
@@ -11,6 +11,7 @@
 #include "smartptr.h"
 #include "misc.h"
 #include "stdcpp.h"
+#include "trap.h"
 
 #ifdef _OPENMP
 # include 
@@ -543,6 +544,9 @@ Integer CRT(const Integer &xp, const Integer &p, const Integer &xq, const Intege
 
 Integer ModularSquareRoot(const Integer &a, const Integer &p)
 {
+	// Callers must ensure p is prime, GH #1249
+	CRYPTOPP_ASSERT(IsPrime(p));
+
 	if (p%4 == 3)
 		return a_exp_b_mod_c(a, (p+1)/4, p);
 
@@ -592,6 +596,9 @@ Integer ModularSquareRoot(const Integer &a, const Integer &p)
 
 bool SolveModularQuadraticEquation(Integer &r1, Integer &r2, const Integer &a, const Integer &b, const Integer &c, const Integer &p)
 {
+	// Callers must ensure p is prime, GH #1249
+	CRYPTOPP_ASSERT(IsPrime(p));
+
 	Integer D = (b.Squared() - 4*a*c) % p;
 	switch (Jacobi(D, p))
 	{
@@ -618,6 +625,9 @@ bool SolveModularQuadraticEquation(Integer &r1, Integer &r2, const Integer &a, c
 Integer ModularRoot(const Integer &a, const Integer &dp, const Integer &dq,
 					const Integer &p, const Integer &q, const Integer &u)
 {
+	// Callers must ensure p and q are prime, GH #1249
+	CRYPTOPP_ASSERT(IsPrime(p) && IsPrime(q));
+
 	// GCC warning bug, https://stackoverflow.com/q/12842306/608639
 #ifdef _OPENMP
 	Integer p2, q2;
@@ -640,6 +650,9 @@ Integer ModularRoot(const Integer &a, const Integer &dp, const Integer &dq,
 Integer ModularRoot(const Integer &a, const Integer &e,
 					const Integer &p, const Integer &q)
 {
+	// Callers must ensure p and q are prime, GH #1249
+	CRYPTOPP_ASSERT(IsPrime(p) && IsPrime(q));
+
 	Integer dp = EuclideanMultiplicativeInverse(e, p-1);
 	Integer dq = EuclideanMultiplicativeInverse(e, q-1);
 	Integer u = EuclideanMultiplicativeInverse(p, q);
@@ -976,6 +989,8 @@ Integer Lucas(const Integer &n, const Integer &P, const Integer &modulus)
 
 Integer InverseLucas(const Integer &e, const Integer &m, const Integer &p, const Integer &q, const Integer &u)
 {
+	// Callers must ensure p and q are prime, GH #1249
+	CRYPTOPP_ASSERT(IsPrime(p) && IsPrime(q));
 
 	// GCC warning bug, https://stackoverflow.com/q/12842306/608639
 #ifdef _OPENMP
diff --git a/vendor/cryptopp/nbtheory.h b/vendor/cryptopp/nbtheory.h
index a494110d19..611e3d319a 100644
--- a/vendor/cryptopp/nbtheory.h
+++ b/vendor/cryptopp/nbtheory.h
@@ -112,7 +112,7 @@ CRYPTOPP_DLL bool CRYPTOPP_API IsPrime(const Integer &p);
 ///   level is greater than 1, then 10 round RabinMillerTest() primality testing is performed.
 CRYPTOPP_DLL bool CRYPTOPP_API VerifyPrime(RandomNumberGenerator &rng, const Integer &p, unsigned int level = 1);
 
-/// \brief Application callback to signal suitability of a cabdidate prime
+/// \brief Application callback to signal suitability of a candidate prime
 class CRYPTOPP_DLL PrimeSelector
 {
 public:
diff --git a/vendor/cryptopp/osrng.cpp b/vendor/cryptopp/osrng.cpp
index 6c72dca170..d61d08f5f4 100644
--- a/vendor/cryptopp/osrng.cpp
+++ b/vendor/cryptopp/osrng.cpp
@@ -23,7 +23,7 @@
 
 // FreeBSD links /dev/urandom -> /dev/random. It showed up when we added
 // O_NOFOLLOW to harden the non-blocking generator. Use Arc4Random instead
-// for a non-blocking generator. Arc4Random is cryptograhic quality prng
+// for a non-blocking generator. Arc4Random is cryptographic quality prng
 // based on ChaCha20. The ChaCha20 generator is seeded from /dev/random,
 // so we can't completely avoid the blocking.
 // https://www.freebsd.org/cgi/man.cgi?query=arc4random_buf.
diff --git a/vendor/cryptopp/premake5.lua b/vendor/cryptopp/premake5.lua
index 2a509e195d..ba09c3f6a8 100644
--- a/vendor/cryptopp/premake5.lua
+++ b/vendor/cryptopp/premake5.lua
@@ -28,7 +28,6 @@ project "cryptopp"
 		"arc4.cpp",
 		"aria.cpp",
 		"ariatab.cpp",
-		"aria_simd.cpp",
 		"asn.cpp",
 		"authenc.cpp",
 		"base32.cpp",
@@ -214,7 +213,8 @@ project "cryptopp"
 	filter "platforms:x64"
 		files {
 			"x64dll.asm",
-			"x64masm.asm"
+			"x64masm.asm",
+			"cpuid64.asm"
 		}
 
 	filter { "system:windows" }
diff --git a/vendor/cryptopp/rabin.cpp b/vendor/cryptopp/rabin.cpp
index b942dee8a0..672b5db06f 100644
--- a/vendor/cryptopp/rabin.cpp
+++ b/vendor/cryptopp/rabin.cpp
@@ -7,6 +7,7 @@
 #include "modarith.h"
 #include "asn.h"
 #include "sha.h"
+#include "trap.h"
 
 NAMESPACE_BEGIN(CryptoPP)
 
@@ -130,6 +131,9 @@ void InvertibleRabinFunction::BERDecode(BufferedTransformation &bt)
 	m_q.BERDecode(seq);
 	m_u.BERDecode(seq);
 	seq.MessageEnd();
+
+	CRYPTOPP_ASSERT(IsPrime(m_p));
+	CRYPTOPP_ASSERT(IsPrime(m_q));
 }
 
 void InvertibleRabinFunction::DEREncode(BufferedTransformation &bt) const
@@ -146,6 +150,9 @@ void InvertibleRabinFunction::DEREncode(BufferedTransformation &bt) const
 
 Integer InvertibleRabinFunction::CalculateInverse(RandomNumberGenerator &rng, const Integer &in) const
 {
+	CRYPTOPP_ASSERT(IsPrime(m_p));
+	CRYPTOPP_ASSERT(IsPrime(m_q));
+
 	DoQuickSanityCheck();
 
 	ModularArithmetic modn(m_n);
diff --git a/vendor/cryptopp/rdrand.h b/vendor/cryptopp/rdrand.h
index d1f3c4129e..6849c8dde2 100644
--- a/vendor/cryptopp/rdrand.h
+++ b/vendor/cryptopp/rdrand.h
@@ -20,7 +20,7 @@
 //   GenerateBlock unconditionally retries and always fulfills the request.
 
 // Throughput varies wildly depending on processor and manufacturer. A Core i5 or
-//   Core i7 RDRAND can generate at over 200 MiB/s. It is below theroetical
+//   Core i7 RDRAND can generate at over 200 MiB/s. It is below theoretical
 //   maximum, but it takes about 5 instructions to generate, retry and store a
 //   result. A low-end Celeron may perform RDRAND at about 7 MiB/s. RDSEED
 //   performs at about 1/4 to 1/2 the rate of RDRAND. AMD RDRAND performed poorly
diff --git a/vendor/cryptopp/x64dll.asm b/vendor/cryptopp/x64dll.asm
index 557afa02b9..440b3c9674 100644
--- a/vendor/cryptopp/x64dll.asm
+++ b/vendor/cryptopp/x64dll.asm
@@ -1975,50 +1975,5 @@ pop		rsi
 ret
 SHA256_HashMultipleBlocks_SSE2 ENDP
 
-;; http://www.agner.org/optimize/vectorclass/read.php?i=65
-;; word64 Xgetbv(word32 ctrl)
-;; ctrl = rcx
-
-    ALIGN   8
-XGETBV64	PROC FRAME
-.endprolog
-    ;; query
-    DB  	0fh, 01h, 0d0h
-    ;; xcr = (EDX << 32) | EAX
-    and 	rax, 0ffffffffh
-    shl 	rdx, 32
-    or  	rax, rdx
-    ret
-XGETBV64	ENDP
-
-;; word64 CpuId(word32 func, word32 subfunc, word32 output[4])
-;; func = rcx
-;; subfunc = rdx
-;; output = r8
-
-    ALIGN   8
-CPUID64	PROC FRAME
-    ;; preserve per ABI
-    mov 	[rsp+8], rbx
-.savereg 	rbx, 8
-.endprolog
-    ;; eax = func
-    mov 	rax, rcx
-    ;; ecx = subfunc
-    mov 	rcx, rdx
-    ;; query
-    cpuid
-    ;; save
-    mov 	[r8+0],  eax
-    mov 	[r8+4],  ebx
-    mov 	[r8+8],  ecx
-    mov 	[r8+12], edx
-    ;; return value
-    mov 	rax, 1
-    ;; restore
-    mov 	rbx, [rsp+8]
-    ret
-CPUID64	ENDP
-
 _TEXT ENDS
 END
diff --git a/vendor/curl/CHANGES b/vendor/curl/CHANGES
index 1c60df1b03..3e4b10e081 100644
--- a/vendor/curl/CHANGES
+++ b/vendor/curl/CHANGES
@@ -6,8978 +6,10704 @@
 
                                   Changelog
 
-Version 8.3.0 (13 Sep 2023)
+Version 8.8.0 (22 May 2024)
 
-Daniel Stenberg (13 Sep 2023)
+Daniel Stenberg (22 May 2024)
 
-- RELEASE-NOTES: syn ced
+- RELEASE-NOTES: synced
 
-  curl 8.3.0 release
+- THANKS: add contributors from 8.8.0
 
-- THANKS: contributors from 8.3.0
+Nathan Moinvaziri (21 May 2024)
 
-Thorsten Klein (12 Sep 2023)
+- url: remove duplicate call to Curl_conncache_remove_conn when pruning
 
-- cmake: set SIZEOF_LONG_LONG in curl_config.h
+  - remove unnecessary prunedead struct from prune_dead_connections
+  - rename extract_if_dead to prune_if_dead for clarity
 
-  in order to support 32bit builds regarding wolfssl CTC_SETTINGS
+  Closes #13710
 
-  Closes #11839
+Joseph Chen (21 May 2024)
 
-Jay Satiro (12 Sep 2023)
+- curl_setup.h: add support for IAR compiler
 
-- curl_ngtcp2: fix error message
+  Closes #13728
 
-- http_aws_sigv4: handle no-value user header entries
+Stephen Farrell (21 May 2024)
 
-  - Handle user headers in format 'name:' and 'name;' with no value.
+- docs/ECH: typo/clarification
 
-  The former is used when the user wants to remove an internal libcurl
-  header and the latter is used when the user actually wants to send a
-  no-value header in the format 'name:' (note the semi-colon is converted
-  by libcurl to a colon).
+  Closes #13727
 
-  Prior to this change the AWS header import code did not special case
-  either of those and the generated AWS SignedHeaders would be incorrect.
+Viktor Szakats (21 May 2024)
 
-  Reported-by: apparentorder@users.noreply.github.com
+- hash: delete unused debug function
 
-  Ref: https://curl.se/docs/manpage.html#-H
+  It had no use in the curl codebase and was also protected by the macro
+  `AGGRESSIVE_TEST` (renamed in 2020), also with no local reference.
 
-  Fixes https://github.com/curl/curl/issues/11664
-  Closes https://github.com/curl/curl/pull/11668
+  Added in ca6e77083768858aa34207f8c5dce38b3c05336d (2002-11-11)
 
-Dan Fandrich (11 Sep 2023)
+  Closes #13729
 
-- CI: run pytest with the -v option
+Stefan Eissing (21 May 2024)
 
-  This lists of the test cases being run so it can be tracked over time.
+- content_encoding: reject transfer-encoding after chunked
 
-  Closes #11824
+  reject a response that applies a transfer-encoding after a 'chunked'
+  encoding. RFC 9112 ch. 6.1 required chunked to be the final encoding.
 
-Daniel Stenberg (11 Sep 2023)
+  Closes #13733
 
-- HTTP3: the msquic backend is not functional
+- http: HEAD response body tolerance
 
-  I ask that we do not submit bugs for this backend just yet as we know it
-  does not fully work.
+  - as reported in #13725, some servers wrongly send body bytes in
+    responses to a HEAD request. This used to be tolerated in curl
+    8.4 and before and leads to failed transfers in newer versions.
+  - restore previous behaviour for HTTP/1.1 and HTTP/2:
+    * 1.1: do not add 'Transfer-Encoding' writers from HEAD
+      responses. RFC 9112 says they do not apply.
+    * 2: when the transfer expects 'no_body', to not report stream
+      resets as error when all response headers have been received.
 
-  Closes #11831
-  Closes #11819
+  Reported-by: Jeroen Ooms
+  Fixes #13725
+  Closes #13732
 
-- aws_sigv4: the query canon code miscounted URL encoded input
+Viktor Szakats (20 May 2024)
 
-  Added some extra ampersands to test 439 to verify "blank" query parts
+- tests: fix TFTP test 2305 on Windows
 
-  Follow-up to fc76a24c53b08cdf
+  Ref: #13692
+  Closes #13724
 
-  Closes #11829
+Jay Satiro (20 May 2024)
 
-vvb2060 (11 Sep 2023)
+- openssl: revert keylog_callback support for LibreSSL
 
-- quic: don't set SNI if hostname is an IP address
+  - Revert to the legacy TLS 1.2 key logging code for LibreSSL.
 
-  We already do this for TLS connections.
+  - Document SSLKEYLOGFILE for LibreSSL is TLS 1.2 max.
 
-  RFC 6066 says: Literal IPv4 and IPv6 addresses are not permitted in
-  "HostName".
+  Prior to this change if the user specified a filename in the
+  SSLKEYLOGFILE environment variable and was using LibreSSL 3.5.0+ then
+  an empty file would be created and no keys would be logged.
 
-  Ref: https://www.rfc-editor.org/rfc/rfc6066#section-3
+  This is effectively a revert of e43474b4 which changed openssl.c to use
+  SSL_CTX_set_keylog_callback for LibreSSL 3.5.0+. Unfortunately LibreSSL
+  added that function only as a stub that doesn't actually do anything.
 
-  Fixes https://github.com/curl/curl/issues/11827
-  Closes https://github.com/curl/curl/pull/11828
+  Reported-by: Gonçalo Carvalho
 
-Daniel Stenberg (10 Sep 2023)
+  Fixes https://github.com/curl/curl/issues/13672
+  Closes https://github.com/curl/curl/pull/13682
 
-- RELEASE-NOTES: synced
+renovate[bot] (19 May 2024)
 
-Benoit Pierre (10 Sep 2023)
+- GHA: pin dependencies
 
-- configure: fix `HAVE_TIME_T_UNSIGNED` check
+  Closes #13712
 
-  The syntax was incorrect (need a proper main body), and the test
-  condition was wrong (resulting in a signed `time_t` detected as
-  unsigned).
+Viktor Szakats (19 May 2024)
 
-  Closes #11825
+- appveyor: drop unnecessary `--clean-first` cmake option
 
-Daniel Stenberg (9 Sep 2023)
+  In CI all machines are fresh on startup, making the `clean` operation
+  unnecessary. This can save some time/energy for each job run.
 
-- THANKS-filter: pszlazak on github
+  Closes #13707
 
-pszlazak (9 Sep 2023)
+- cmake: merge two `if(BUILD_TESTING)` branches
 
-- include.d: explain headers not printed with --fail before 7.75.0
+  Closes #13708
 
-  Prior to 7.75.0 response headers were not printed if -f/--fail was used
-  and an error was reported by server.  This was fixed in ab525c0
-  (precedes 7.75.0).
+Tatsuhiro Tsujikawa (19 May 2024)
 
-  Closes #11822
+- GHA: bump nghttp2 to v1.62.1
 
-Daniel Stenberg (8 Sep 2023)
+  Use gcc-12 explicitly to compile C++20 source files.
 
-- http_aws_sigv4: skip the op if the query pair is zero bytes
+  Closes #13702
 
-  Follow-up to fc76a24c53b08cdf
+Viktor Szakats (19 May 2024)
 
-  Spotted by OSS-Fuzz
+- GHA: add NetBSD, OpenBSD, FreeBSD/arm64 and OmniOS jobs
 
-  Bug: https://bugs.chromium.org/p/oss-fuzz/issues/detail?id=62175
-  Closes #11823
+  Add these jobs to GHA:
+  - NetBSD, cmake-unity, clang, OpenSSL, x86_64, with tests, w/o python,
+    no parallelism (was flaky sometimes)
+  - OpenBSD, cmake-unity, clang, LibreSSL, x86_64, with tests,
+    with python, -j8, TFTP results ignored due to #13623.
+  - FreeBSD, cmake-unity and autotools, clang, OpenSSL, arm64
+    (Tests disabled for arm64, because they are slow. It's available for
+    x86_64 with python, -j12.)
+    Configuration matches our existing Cirrus CI one.
+  - OmniOS, autotools, gcc, OpenSSL, x86_64, with tests, -j12.
 
-- cmdline-docs: use present tense, not future
+  All build with websockets and examples.
 
-  + some smaller cleanups
+  Closes #13583
 
-  Closes #11821
+- GHA: disable TFTP test on native Windows
 
-- cmdline-docs: make sure to phrase it as "added in ...."
+  Some TFTP tests seem to enter into a loop and maybe hang?
 
-  References to things that were added or changed in a specific version
-  should be specified as "(added in [version]) for two reasons:
+  E.g. 1007, 1009, 1238
 
-  1 - consistency
+  Try fixing it by skipping all TFTP tests.
 
-  2 - to allow gen.pl to strip them out if deemed referring to too old
-      versions
+  Ref: https://github.com/curl/curl/actions/runs/9141987545/job/25137038249?pr=
+  13698
 
-  Closes #11821
+  Also drop mingw-w64 test exclusions copy-pasted from MSYS jobs.
 
-Jay Satiro (8 Sep 2023)
+  Possibly related: cffbcc3110c1eda2e333f9cfe2e269154618793a #5364
 
-- docs: mark --ssl-revoke-best-effort as Schannel specific
+  Close #13699
 
-  Closes https://github.com/curl/curl/pull/11760
+renovate[bot] (18 May 2024)
 
-Nathan Moinvaziri (8 Sep 2023)
+- GHA: pin dependencies
 
-- schannel: fix ordering of cert chain info
+  Closes #13691
 
-  - Use CERT_CONTEXT's pbCertEncoded to determine chain order.
+Viktor Szakats (18 May 2024)
 
-  CERT_CONTEXT from SECPKG_ATTR_REMOTE_CERT_CONTEXT contains
-  end-entity/server certificate in pbCertEncoded. We can use this pointer
-  to determine the order of certificates when enumerating hCertStore using
-  CertEnumCertificatesInStore.
+- cmake: do not pass linker flags to the static library tool
 
-  This change is to help ensure that the ordering of the certificate chain
-  requested by the user via CURLINFO_CERTINFO has the same ordering on all
-  versions of Windows.
+  Do not add linker flags to the global CMake static library tool (aka
+  "static linker") (e.g. `ar`) flags list. They don't mix well. This was
+  only done after successfully detecting GSSAPI.
 
-  Prior to this change Schannel certificate order was reversed in 8986df80
-  but that was later reverted in f540a39b when it was discovered that
-  Windows 11 22H2 does the reversal on its own.
+  Linker flags seen on Old Linux CI:
+  ```
+  -- |GSS_LINKER_FLAGS|-Wl,--enable-new-dtags -Wl,-rpath -Wl,/usr/lib/x86_64-li
+  nux-gnu/heimdal|
+  -- |CMAKE_STATIC_LINKER_FLAGS| -Wl,--enable-new-dtags -Wl,-rpath -Wl,/usr/lib
+  /x86_64-linux-gnu/heimdal|
+  ```
+  Ref: https://github.com/curl/curl/actions/runs/9138988036/job/25130791712#ste
+  p:6:85
 
-  Ref: https://github.com/curl/curl/issues/9706
+  Causing:
+  ```
+  /usr/bin/ar qc libcurltool.a  -Wl,--enable-new-dtags -Wl,-rpath -Wl,/usr/lib/
+  x86_64-linux-gnu/heimdal
+    CMakeFiles/curltool.dir/slist_wc.c.o CMakeFiles/curltool.dir/tool_binmode.c
+  .o CMakeFiles/curltool.dir/tool_bname.c.o
+    [...]
+    CMakeFiles/curltool.dir/tool_writeout_json.c.o CMakeFiles/curltool.dir/tool
+  _xattr.c.o CMakeFiles/curltool.dir/var.c.o
+    CMakeFiles/curltool.dir/__/lib/base64.c.o CMakeFiles/curltool.dir/__/lib/dy
+  nbuf.c.o
+  /usr/bin/ar: invalid option -- 'W'
+  Usage: /usr/bin/ar [emulation options] [-]{dmpqrstx}[abcDfilMNoPsSTuvV] [--pl
+  ugin ] [member-name] [count] archive-file file...
+         /usr/bin/ar -M [64K are send in parts to the filter
-  - fix parsing of the request to assemble it correctly
-    from several sends
-  - open a QUIC stream only when the complete request has
-    been collected
+- lib: fix compiler warnings (gcc)
 
-  Closes #11815
+  Seen when setting `ENABLE_DEBUG=ON` and `-DDEBUGBUILD` for mingw-w64
+  gcc 13.2.0 CMake unity builds in 'Release' configurations.
 
-- openssl: when CURLOPT_SSL_CTX_FUNCTION is registered, init x509 store before
+  ```
+  curl/lib/curl_gethostname.c:71:5: error: 'strncpy' specified bound 1025 equal
+  s destination size [-Werror=stringop-truncation]
+     71 |     strncpy(name, force_hostname, namelen);
+        |     ^~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+  In file included from curl/_bld/lib/CMakeFiles/libcurl_object.dir/Unity/unity
+  _0_c.c:175:
+  In function 'hostcache_timestamp_remove',
+      inlined from 'Curl_hash_clean_with_criterium' at curl/lib/hash.c:265:19,
+      inlined from 'Curl_hash_clean_with_criterium' at curl/lib/hash.c:247:1,
+      inlined from 'hostcache_prune' at curl/lib/hostip.c:228:3,
+      inlined from 'Curl_hostcache_prune' at curl/lib/hostip.c:256:21:
+  curl/lib/hostip.c:205:12: error: 'now' may be used uninitialized [-Werror=may
+  be-uninitialized]
+    205 |     time_t age = prune->now - c->timestamp;
+        |            ^~~
+  curl/lib/hostip.c: In function 'Curl_hostcache_prune':
+  curl/lib/hostip.c:241:10: note: 'now' was declared here
+    241 |   time_t now;
+        |          ^~~
+  In function 'hostcache_timestamp_remove',
+      inlined from 'fetch_addr' at curl/lib/hostip.c:310:8:
+  curl/lib/hostip.c:205:23: error: 'user.now' may be used uninitialized [-Werro
+  r=maybe-uninitialized]
+    205 |     time_t age = prune->now - c->timestamp;
+        |                  ~~~~~^~~~~
+  curl/lib/hostip.c: In function 'fetch_addr':
+  curl/lib/hostip.c:304:33: note: 'user' declared here
+    304 |     struct hostcache_prune_data user;
+        |                                 ^~~~
+  In file included from curl/_bld/lib/CMakeFiles/libcurl_object.dir/Unity/unity
+  _0_c.c:40:
+  curl/lib/cf-socket.c: In function 'cf_socket_send':
+  curl/lib/cf-socket.c:1294:10: error: 'c' may be used uninitialized [-Werror=m
+  aybe-uninitialized]
+   1294 |     if(c >= ((100-ctx->wblock_percent)*256/100)) {
+        |        ~~^~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+  curl/lib/cf-socket.c:1292:19: note: 'c' was declared here
+   1292 |     unsigned char c;
+        |                   ^
+  In file included from curl/_bld/lib/CMakeFiles/libcurl_object.dir/Unity/unity
+  _0_c.c:364:
+  In function 'tftp_state_timeout',
+      inlined from 'tftp_multi_statemach' at curl/lib/tftp.c:1230:27:
+  curl/lib/tftp.c:1208:5: error: 'current' may be used uninitialized [-Werror=m
+  aybe-uninitialized]
+   1208 |   if(current > state->rx_time + state->retry_time) {
+        |     ^
+  curl/lib/tftp.c: In function 'tftp_multi_statemach':
+  curl/lib/tftp.c:1192:10: note: 'current' was declared here
+   1192 |   time_t current;
+        |          ^~~~~~~
+  ```
+  Ref: https://ci.appveyor.com/project/curlorg/curl/builds/49792835/job/91c8dj5
+  qb36spfe0#L112
+  Ref: https://github.com/curl/curl/actions/runs/9082968838/job/24960616145#ste
+  p:12:62
 
-  - we delay loading the x509 store to shorten the handshake time.
-    However an application callback installed via CURLOPT_SSL_CTX_FUNCTION
-    may need to have the store loaded and try to manipulate it.
-  - load the x509 store before invoking the app callback
+  Ref: #13592
+  Closes #13643
 
-  Fixes #11800
-  Reported-by: guoxinvmware on github
-  Cloes #11805
+Andrew (16 May 2024)
 
-Daniel Stenberg (7 Sep 2023)
+- wakeup_create: use FD_CLOEXEC/SOCK_CLOEXEC
 
-- krb5: fix "implicit conversion loses integer precision" warnings
+  for `pipe()`/`socketpair()`
 
-  conversions to/from enum and unsigned chars
+  Fixes #13618
+  Closes #13625
 
-  Closes #11814
+Stefan Eissing (16 May 2024)
 
-Stefan Eissing (7 Sep 2023)
+- rustls: fix partial send handling
 
-- pytest: improvements
+  When TLS bytes could not completely sent off, the amount of plain bytes
+  already added to rustls were forgotten. This lead to send those byte
+  duplicate, corrupting the request send to the server.
 
-  - set CURL_CI for pytest runs in CI environments
-  - exclude timing sensitive tests from CI runs
-  - for failed results, list only the log and stat of
-    the failed transfer
+  Closes #13676
 
-  - fix type in http.c comment
+- pytest: add DELETE tests, check server version
 
-  Closes #11812
+  - add tests for DELETE working
+  - check apache version in keepalive test
+  - fix some comments
 
-- CI: move on to ngtcp2 v0.19.1
+  Closes #13679
 
-  Closes #11809
+Juliusz Sosinowicz (16 May 2024)
 
-Dan Fandrich (5 Sep 2023)
+- vquic-tls: use correct cert name check API for wolfSSL
 
-- CI: run Circle macOS builds on x86 for now
+  wolfSSL_X509_check_host checks the peer name against the alt names and
+  the common name.
 
-  The ARM machines aren't ready for us and requesting them now causes
-  warnings e-mails to be sent to some PR pushers.
+  Fixes #13487
+  Closes #13680
 
-  Ref: #11771
+Viktor Szakats (16 May 2024)
 
-Viktor Szakats (5 Sep 2023)
+- cmake: initialize `BUILD_TESTING` before first use
 
-- http3: adjust cast for ngtcp2 v0.19.0
+  Before this patch `BUILD_TESTING` was used once, then initialized, then
+  used again. This caused the `curlu` library not being built when relying
+  on an implicit `BUILD_TESTING=ON` setting, and ending up with a link
+  error when building the `testdeps` target.
 
-  ngtcp2 v0.19.0 made size of `ecn` member of `ngtcp2_pkt_info`
-  an `uint8_t` (was: `uint32_t`). Adjust our local cast accordingly.
+  It did not cause issues when `BUILD_TESTING` was explicitly set.
 
-  Fixes:
-  ```
-  ./curl/lib/vquic/curl_ngtcp2.c:1912:12: warning: implicit conversion loses in
-  teger precision: 'uint32_t' (aka 'unsigned int') to 'uint8_t' (aka 'unsigned 
-  char') [-Wimplicit-int-conversion]
-    pi.ecn = (uint32_t)ecn;
-           ~ ^~~~~~~~~~~~~
-  ```
+  Move the initialization before the first use to fix it.
 
-  Also bump ngtcp2, nghttp3 and nghttp2 to their latest versions in our
-  docs and CI.
+  Regression from aace27b0965c10394544d1dacc9c2cb2fe0de3d3 #12287
+  Closes #13668
 
-  Ref: https://github.com/ngtcp2/ngtcp2/commit/80447281bbc94af53f8aa7a4cfc19175
-  782894a3
-  Ref: https://github.com/ngtcp2/ngtcp2/pull/877
-  Closes #11798
+Daniel Stenberg (16 May 2024)
 
-Stefan Eissing (5 Sep 2023)
+- libtest: 2308 verifies CURLE_WRITE_ERROR after write callback error
 
-- http: fix sending of large requests
+  Verifies that the issue in #13669 actually is fixed. This return code is
+  what the CURLOPT_WRITEFUNCTION manpage documents should be returned.
 
-  - refs #11342 where errors with git https interactions
-    were observed
-  - problem was caused by 1st sends of size larger than 64KB
-    which resulted in later retries of 64KB only
-  - limit sending of 1st block to 64KB
-  - adjust h2/h3 filters to cope with parsing the HTTP/1.1
-    formatted request in chunks
+  This code is mostly from the
+  Source-written-by: Trumeet on github
+  Closes #13671
 
-  - introducing Curl_nwrite() as companion to Curl_write()
-    for the many cases where the sockindex is already known
+Antoine Bollengier (16 May 2024)
 
-  Fixes #11342 (again)
-  Closes #11803
+- socketpair: fix compilation when USE_UNIX_SOCKETS is not defined
 
-- pytest: fix check for slow_network skips to only apply when intended
+  Closes #13666
 
-  Closes #11801
+Stefan Eissing (16 May 2024)
 
-Daniel Stenberg (5 Sep 2023)
+- rustsls: fix error code on receive
 
-- curl_url_get/set.3: add missing semicolon in SYNOPSIS
+  - use CURLE_RECV_ERROR instead of CURLE_READ_ERROR when receiving
+    data fails.
 
-- CURLOPT_URL.3: explain curl_url_set() uses the same parser
+  Closes #13670
 
-- CURLOPT_URL.3: add two URL API calls in the see-also section
+Max Dymond (16 May 2024)
 
-Dan Fandrich (4 Sep 2023)
+- ci: disable Renovate dashboard
 
-- CI: add a 32-bit i686 Linux build
+  The Renovate dashboard insists on an open issue,
+  which is a problem. Disable the dashboard. Status
+  can still be seen at https://developer.mend.io/github/curl/curl.
 
-  This is done by cross-compiling under regular x86_64 Linux.  Since the
-  kernel offers backwards compatibility, the binaries can be tested as
-  normal.
+  Fixes #13630
+  Closes #13673
 
-  Closes #11799
+Daniel Stenberg (16 May 2024)
 
-- tests: fix a type warning on 32-bit x86
+- RELEASE-NOTES: synced
 
-Viktor Szakats (4 Sep 2023)
+renovate[bot] (16 May 2024)
 
-- tests: delete stray `.orig` file
+- GHA: update awslabs/aws-lc to v1.27.0
 
-  Follow-up to 331b89a319d0067fa1e6441719307cfef9c7960f
-  Closes #11797
+  Closes #13667
 
-Daniel Stenberg (4 Sep 2023)
+Daniel Stenberg (15 May 2024)
 
-- RELEASE-NOTES: synced
+- curl_easy_pause.md: use correct defines in example
 
-Viktor Szakats (4 Sep 2023)
+  Spotted-by: Harry Sintonen
+  Closes #13664
 
-- lib: silence compiler warning in inet_ntop6
+Viktor Szakats (15 May 2024)
 
-  ```
-  ./curl/lib/inet_ntop.c:121:21: warning: possible misuse of comma operator her
-  e [-Wcomma]
-          cur.base = i, cur.len = 1;
-                      ^
-  ./curl/lib/inet_ntop.c:121:9: note: cast expression to void to silence warnin
-  g
-          cur.base = i, cur.len = 1;
-          ^~~~~~~~~~~~
-          (void)(     )
-  ```
+- appveyor: more tidy-ups
 
-  Closes #11790
+  - use `--disable` when calling `curl --version`. Just in case.
 
-Daniel Stenberg (4 Sep 2023)
+  - use single-quotes for a constant.
 
-- transfer: also stop the sending on closed connection
+  Closes #13662
 
-  Previously this cleared the receiving bit only but in some cases it is
-  also still sending (like a request-body) when disconnected and neither
-  direction can continue then.
+- reuse: migrate standalone license file to dep5
 
-  Fixes #11769
-  Reported-by: Oleg Jukovec
-  Closes #11795
+  Follow-up to 73a36021207284ad2b4340ffde34a51b0ba4d47a
+  Closes #13660
 
-John Bampton (4 Sep 2023)
+- appveyor: guard against crash-build with VS2008
 
-- docs: change `sub-domain` to `subdomain`
+  The combination of `-DDEBUGBUILD`, a shared `curl.exe`, and the VS2008
+  compiler creates a `curl.exe` segfaulting on startup:
 
-  https://en.wikipedia.org/wiki/Subdomain
+  ```
+  + _bld/src/curl.exe --version
+  ./appveyor.sh: line 122:   793 Segmentation fault      "${curl}" --version
+  Command exited with code 139
+  ```
+  Ref: https://ci.appveyor.com/project/curlorg/curl/builds/49817266/job/651iy6q
+  n1e238pqj#L191
 
-  Closes #11793
+  Add job that triggers the issue and add the necessary logic to skip
+  running the affected `curl.exe`.
 
-Stefan Eissing (4 Sep 2023)
+  Ref: #13592
+  Closes #13654
 
-- multi: more efficient pollfd count for poll
+renovate[bot] (15 May 2024)
 
-  - do not use separate pollfds for sockets that have POLLIN+POLLOUT
+- GHA: pin dependencies
 
-  Closes #11792
+  Closes #13628
 
-- http2: polish things around POST
+Orgad Shaneh (15 May 2024)
 
-  - added test cases for various code paths
-  - fixed handling of blocked write when stream had
-    been closed inbetween attempts
-  - re-enabled DEBUGASSERT on send with smaller data size
+- socket: remove redundant call to getsockname
 
-  - in debug builds, environment variables can be set to simulate a slow
-    network when sending data. cf-socket.c and vquic.c support
-    * CURL_DBG_SOCK_WBLOCK: percentage of send() calls that should be
-      answered with a EAGAIN. TCP/UNIX sockets.
-      This is chosen randomly.
-    * CURL_DBG_SOCK_WPARTIAL: percentage of data that shall be written
-      to the network. TCP/UNIX sockets.
-      Example: 80 means a send with 1000 bytes would only send 800
-      This is applied to every send.
-    * CURL_DBG_QUIC_WBLOCK: percentage of send() calls that should be
-      answered with EAGAIN. QUIC only.
-      This is chosen randomly.
+  The result "add" is unused.
 
-  Closes #11756
+  Closes #13655
 
-Daniel Stenberg (4 Sep 2023)
+renovate[bot] (15 May 2024)
 
-- docs: add curl_global_trace to some SEE ALSO sections
+- CI: renovate updates
 
-  Closes #11791
+  - GHA: update actions/checkout action to v4
+  - GHA: update wolfSSL/wolfssh to v1.4.17
+  - GHA: update wolfSSL/wolfssl to v5.7.0
+  - Update the regex config in renovate.json
 
-- os400: fix checksrc nits
+  Closes #13632
+  Closes #13641
+  Closes #13658
+  Closes #13659
 
-  Closes #11789
+Max Dymond (15 May 2024)
 
-Nicholas Nethercote (3 Sep 2023)
+- ci: fix renovate config for WolfSSL/WolfSSH tagging scheme
 
-- hyper: remove `hyptransfer->endtask`
+  WolfSSL/WolfSSH use a different versioning scheme;
+  stable builds end with `-stable`. Renovate requires
+  some extra configuration to extract the version
+  from these types of tags.
 
-  `Curl_hyper_stream` needs to distinguish between two kinds of
-  `HYPER_TASK_EMPTY` tasks: (a) the `foreach` tasks it creates itself, and
-  (b) background tasks that hyper produces. It does this by recording the
-  address of any `foreach` task in `hyptransfer->endtask` before pushing
-  it into the executor, and then comparing that against the address of
-  tasks later polled out of the executor.
+  Closes #13644
 
-  This works right now, but there is no guarantee from hyper that the
-  addresses are stable. `hyper_executor_push` says "The executor takes
-  ownership of the task, which should not be accessed again unless
-  returned back to the user with `hyper_executor_poll`". That wording is a
-  bit ambiguous but with my Rust programmer's hat on I read it as meaning
-  the task returned with `hyper_executor_poll` may be conceptually the
-  same as a task that was pushed, but that there are no other guarantees
-  and comparing addresses is a bad idea.
+- ci: set semantic type as CI and include digests as CI operations
 
-  This commit instead uses `hyper_task_set_userdata` to mark the `foreach`
-  task with a `USERDATA_RESP_BODY` value which can then be checked for,
-  removing the need for `hyptransfer->endtask`. This makes the code look
-  more like that hyper C API examples, which use userdata for every task
-  and never look at task addresses.
+  Replace "chore" with "ci" for renovate's semantic
+  type, and include digests with "pin" and
+  "pinDigest" as ci operations.
 
-  Closes #11779
+  Closes #13644
 
-Dave Cottlehuber (3 Sep 2023)
+Daniel Stenberg (15 May 2024)
 
-- ws: fix spelling mistakes in examples and tests
+- DEPRECATE.md: TLS libraries without 1.3 support
 
-  Closes #11784
+  curl drops support for TLS libraries without TLS 1.3 capability after
+  May 2025.
 
-Daniel Stenberg (3 Sep 2023)
+  It requires that a curl build using the library should be able to
+  negotiate and use TLS 1.3, or else it is not good enough. We support a
+  vast amount of other TLS libraries that are likely to satisfy users
+  better.
 
-- tool_filetime: make -z work with file dates before 1970
+  Closes #13544
 
-  Fixes #11785
-  Reported-by: Harry Sintonen
-  Closes #11786
+- Revert "ci: update nghttp2/nghttp2 to v1.62.0"
 
-Dan Fandrich (1 Sep 2023)
+  This reverts commit 14f2c767555b7598d7783ccd9093670b84d28488.
 
-- build: fix portability of mancheck and checksrc targets
+  We need to also upgrade the C++ compiler for that bump to work.
 
-  At least FreeBSD preserves cwd across makefile lines, so rules
-  consisting of more than one "cd X; do_something" must be explicitly run
-  in a subshell to avoid this. This problem caused the Cirrus FreeBSD
-  build to fail when parallel make jobs were enabled.
+  Closes #13656
 
-- CI: adjust labeler match patterns for new & obsolete files
+renovate[bot] (15 May 2024)
 
-- configure: trust pkg-config when it's used for zlib
+- Dockerfile: update debian digest to 911821c
 
-  The library flags retrieved from pkg-config were later thrown out and
-  harded-coded, which negates the whole reason to use pkg-config.
-  Also, previously, the assumption was made that --libs-only-l and
-  --libs-only-L are the full decomposition of --libs, which is untrue and
-  would not allow linking against a static zlib. The new approach is
-  better in that it uses --libs, although only if --libs-only-l returns
-  nothing.
+  Closes #13629
 
-  Bug: https://curl.se/mail/lib-2023-08/0081.html
-  Reported-by: Randall
-  Closes #11778
+- ci: update gnutls/gnutls to v3.8.5
 
-Stefan Eissing (1 Sep 2023)
+  Closes #13640
 
-- CI/ngtcp2: clear wolfssl for when cache is ignored
+- ci: update awslabs/aws-lc to v1.26.0
 
-  Closes #11783
+  Closes #13647
 
-Daniel Stenberg (1 Sep 2023)
+- ci: update cloudflare/quiche to v0.21.0
 
-- RELEASE-NOTES: synced
+  Closes #13648
 
-Nicholas Nethercote (1 Sep 2023)
+- ci: update libressl-portable/portable to v3.9.2
 
-- hyper: fix a progress upload counter bug
+  Closes #13649
 
-  `Curl_pgrsSetUploadCounter` should be a passed a total count, not an
-  increment.
+- ci: update nghttp2/nghttp2 to v1.62.0
 
-  This changes the failing diff for test 579 with hyper from this:
-  ```
-   Progress callback called with UL 0 out of 0[LF]
-  -Progress callback called with UL 8 out of 0[LF]
-  -Progress callback called with UL 16 out of 0[LF]
-  -Progress callback called with UL 26 out of 0[LF]
-  -Progress callback called with UL 61 out of 0[LF]
-  -Progress callback called with UL 66 out of 0[LF]
-  +Progress callback called with UL 29 out of 0[LF]
-  ```
-  to this:
-  ```
-   Progress callback called with UL 0 out of 0[LF]
-  -Progress callback called with UL 8 out of 0[LF]
-  -Progress callback called with UL 16 out of 0[LF]
-  -Progress callback called with UL 26 out of 0[LF]
-  -Progress callback called with UL 61 out of 0[LF]
-  -Progress callback called with UL 66 out of 0[LF]
-  +Progress callback called with UL 40 out of 0[LF]
-  ```
-  Presumably a step in the right direction.
+  Closes #13650
+
+- ci: update ngtcp2/nghttp3 to v1.3.0
+
+  Closes #13651
+
+- ci: update ngtcp2/ngtcp2 to v1.5.0
 
-  Closes #11780
+  Closes #13652
 
-Daniel Stenberg (1 Sep 2023)
+Max Dymond (14 May 2024)
 
-- awssiv4: avoid freeing the date pointer on error
+- ci: handle git submodules for mbedTLS
 
-  Since it was not allocated, don't free it even if it was wrong syntax
+- ci: reconfigure renovate
 
-  Bug: https://bugs.chromium.org/p/oss-fuzz/issues/detail?id=61908
+  - set prefix for github actions updates to be gha:
+  - set prefix for other renovate actions to be ci:
+  - disable debian updates in linux-old.yml
 
-  Follow-up to b137634ba3adb
+Viktor Szakats (14 May 2024)
 
-  Closes #11782
+- tidy-up: whitespace [ci skip]
 
-Stefan Eissing (1 Sep 2023)
+- warnless: delete orphan declarations
 
-- CI: ngtcp2-linux: use separate caches for tls libraries
+  Follow-up to 358f7e757781857c4b498a68634726609fa3884a #11932
+  Closes #13639
 
-  allow ever changing master for wolfssl
+Daniel Stenberg (14 May 2024)
 
-  Closes #11766
+- BUG-BOUNTY.md: clarify the third party situation
 
-- replace `master` as wolfssl-version with recent commit
+  We do not pay bounties for problems in other libraries.
 
-- wolfssl, use master again in CI
+  Closes #13560
 
-  - with the shared session update fix landed in master, it
-    is time to use that in our CI again
+Stefan Eissing (14 May 2024)
 
-Nicholas Nethercote (31 Aug 2023)
+- http tests: in CI skip test_02_23* for quiche
 
-- tests: fix formatting errors in `FILEFORMAT.md`.
+  For unknown reasons, these tests fail in CI often, but run fine locally.
+  Skip them in CI to avoid unrelated PRs to have failures.
 
-  Without the surrounding backticks, these tags get swallowed when the
-  markdown is rendered.
+  Closes #13638
 
-  Closes #11777
+Daniel Gustafsson (14 May 2024)
 
-Viktor Szakats (31 Aug 2023)
+- hsts: explicitly skip blank lines
 
-- cmake: add support for `CURL_DEFAULT_SSL_BACKEND`
+  Keep blank lines or lines containing only whitespace to make it all
+  the way to the more expensive sscanf call in hsts_add.
 
-  Allow overriding the default TLS backend via a CMake setting.
+  Closes: #13603
+  Reviewed-by: Daniel Stenberg 
 
-  E.g.:
-  `cmake [...] -DCURL_DEFAULT_SSL_BACKEND=mbedtls`
+- autotools: Only probe for SGI MIPS compilers on IRIX
 
-  Accepted values: bearssl, gnutls, mbedtls, openssl, rustls,
-  schannel, secure-transport, wolfssl
+  MIPSPro and the predecessor compiler which was part of the IDO (IRIS
+  Development Option) were only ever shipped on the SGI IRIX operating
+  system (with MIPSPro on 6.0+ which was released in 1994).  Limit the
+  autoconf check to IRIX when probing for these compilers to save some
+  cycles on other platforms.
 
-  The passed string is baked into the curl/libcurl binaries.
-  The value is case-insensitive.
+  Closes: #13611
+  Reviewed-by: Daniel Stenberg 
 
-  We added a similar option to autotools in 2017 via
-  c7170e20d0a18ec8a514b4daa53bcdbb4dcb3a05.
+Viktor Szakats (14 May 2024)
 
-  TODO: Convert to lowercase to improve reproducibility.
+- tests: fix test 1167 to skip digit-only symbols
 
-  Closes #11774
+  This avoids mistaking symbols with their numeric value when using
+  certain C preprocessors which output these numeric values at the
+  beginning of the line as part of an expression.
 
-- sectransp: fix compiler warnings
+  Seen on OpenBSD 7.5 + clang.
 
-  https://github.com/curl/curl-for-win/actions/runs/6037489221/job/16381860220#
-  step:3:11046
+  Example `test1167.pl -v` output, before this patch:
   ```
-  /Users/runner/work/curl-for-win/curl-for-win/curl/lib/vtls/sectransp.c:2435:1
-  4: warning: unused variable 'success' [-Wunused-variable]
-      OSStatus success;
-               ^
-  /Users/runner/work/curl-for-win/curl-for-win/curl/lib/vtls/sectransp.c:3300:4
-  4: warning: unused parameter 'sha256len' [-Wunused-parameter]
-                                      size_t sha256len)
-                                             ^
+  Source: cpp /home/runner/work/curl/curl/tests/../include/curl/curl.h
+  Symbol: 20000
+  Line #3835:   20000 +  142,
+  [...]
+  Bad symbols in public header files:
+     20000
+     [...]
   ```
+  Ref: https://github.com/curl/curl/actions/runs/9069136530/job/24918015357#ste
+  p:3:7513
 
-  Closes #11773
+  Ref: #13583
+  Closes #13634
 
-- tidy-up: mostly whitespace nits
+Daniel Stenberg (14 May 2024)
 
-  - delete completed TODO from `./CMakeLists.txt`.
-  - convert a C++ comment to C89 in `./CMake/CurlTests.c`.
-  - delete duplicate EOLs from EOF.
-  - add missing EOL at EOF.
-  - delete whitespace at EOL (except from expected test results).
-  - convert tabs to spaces.
-  - convert CRLF EOLs to LF in GHA yaml.
-  - text casing fixes in `./CMakeLists.txt`.
-  - fix a codespell typo in `packages/OS400/initscript.sh`.
+- lib: call Curl_strntolower instead of doing crafted loops
 
-  Closes #11772
+  Closes #13627
 
-Dan Fandrich (31 Aug 2023)
+- setopt: acknowledge errors proper for CURLOPT_COOKIEJAR
 
-- CI: remove Windows builds from Cirrus, without replacement
+  Error out on error, do not continue.
 
-  If we don't do this, all coverage on Cirrus will cease in a few days. By
-  removing the Windows builds, the FreeBSD one should still continue
-  as before. The Windows builds will need be moved to another service to
-  maintain test coverage.
+  Closes #13624
 
-  Closes #11771
+- vtls: remove duplicate assign
 
-- CI: switch macOS ARM build from Cirrus to Circle CI
+  Curl_ssl_peer_cleanup() already clears the ->sni field, no point in
+  assigning it again.
 
-  Cirrus is drastically reducing their free tier on Sept. 1, so they will
-  no longer perform all these builds for us. All but one build has been
-  moved, with the LibreSSL one being dropped because of linking problems
-  on Circle.
+  Spotted by CodeSonar
 
-  One important note about this change is that Circle CI is currently
-  directing all these builds to x86_64 hardware, despite them requesting
-  ARM. This is because ARM nodes are scheduled to be available on the
-  free tier only in December. This reduces our architectural diversity
-  until then but it should automatically come back once those machines are
-  enabled.
+  Closes #13626
 
-- CI: use the right variable for BSD make
+Max Dymond (13 May 2024)
 
-  BSD uses MAKEFLAGS instead of MAKE_FLAGS so it wasn't doing parallel
-  builds before.
+- Group all non-major updates together to reduce PR spam
 
-- CI: drop the FreeBSD 12.X build
+- Add the remainder of the workflows
 
-  Cirrus' new free tier won't let us have many builds, so drop the
-  nonessential ones. The FreeBSD 13.X build will still give us the most
-  relevant FreeBSD coverage.
+- Add some basic versioning for some workflows to check whether this is detecte
+  d properly
 
-- CI: move the Alpine build from Cirrus to GHA
+renovate[bot] (13 May 2024)
 
-  Cirrus is reducing their free tier to next to nothing, so we must move
-  builds elsewhere.
+- Add renovate.json
 
-Stefan Eissing (30 Aug 2023)
+Daniel Stenberg (13 May 2024)
 
-- test_07_upload.py: fix test_07_34 curl args
+- vauth: make two functions void that always just returned OK
 
-  - Pass correct filename to --data-binary.
+  Removes the need to check return values when they can never fail.
 
-  Prior to this change --data-binary was passed an incorrect filename due
-  to a missing separator in the arguments list. Since aacbeae7 curl will
-  error on incorrect filenames for POST.
+  Pointed out by CodeSonar
 
-  Fixes https://github.com/curl/curl/issues/11761
-  Closes https://github.com/curl/curl/pull/11763
+  Closes #13621
 
-Nicholas Nethercote (30 Aug 2023)
+- setopt: remove check for 'option' that is always true
 
-- tests: document which tests fail due to hyper's lack of trailer support.
+  - make sure that passing in option set to NULL clears the fields
+    correctly
 
-  Closes #11762
+  - remove the weird second take if Curl_parse_login_details() returns
+    error
 
-- docs: removing "pausing transfers" from HYPER.md.
+  Follow-up to 7333faf00bf25db7cd1e0012d6b140
 
-  It's a reference to #8600, which was fixed by #9070.
+  Spotted by CodeSonar
 
-  Closes #11764
+  Closes #13619
 
-Patrick Monnerat (30 Aug 2023)
+Viktor Szakats (13 May 2024)
 
-- os400: handle CURL_TEMP_PRINTF() while building bind source
+- tests: tidy up types in server code
 
-  Closes #11547
+  Cherry-picked from #13489
+  Closes #13610
 
-- os400: build test servers
+Daniel Stenberg (13 May 2024)
 
-  Also fix a non-compliant main prototype in disabled.c.
+- setopt: make the setstropt_userpwd args compulsory
 
-  Closes #11547
+  They were always used so no point in allowing them to be optional.
 
-- tests: fix compilation error for os400
+  follow-up to 0e37b42dc956bd8a
 
-  OS400 uses BSD 4.3 setsockopt() prototype by default: this does not
-  define parameter as const, resulting in an error if actual parameter is
-  const. Remove the const keyword from the actual parameter cast: this
-  works in all conditions, even if the formal parameter uses it.
+  Closes #13608
+  Reviewed-by: Daniel Gustafsson
 
-  Closes #11547
+- RELEASE-NOTES: synced
 
-- os400: make programs and command name configurable
+Daniel Gustafsson (13 May 2024)
 
-  Closes #11547
+- websocket: Avoid memory leak in error path
 
-- os400: move build configuration parameters to a separate script
+  In the errorpath for randstr being too long to copy into the buffer
+  we leak the randstr when returning CURLE_FAILED_INIT.  Fix by using
+  an explicit free on randstr in the errorpath.
 
-  They can then easily be overriden in a script named "config400.override"
-  that is not part of the distribution.
+  Closes: #13602
+  Reviewed-by: Daniel Stenberg 
 
-  Closes #11547
+- hsts: Remove single-use single-line function
 
-- os400: implement CLI tool
+  The hsts_entry() function contains of a single line and is only
+  used in a single place in the code, so move the allocation into
+  hsts_create instead to improve code readability. C code usually
+  don't use the factory abstraction for object creation, and this
+  small example wasn't following our usual code style.
 
-  This is provided as a QADRT (ascii) program, a link to it in the IFS and
-  a minimal CL command.
+  Closes: #13604
+  Reviewed-by: Daniel Stenberg 
 
-  Closes #11547
+Viktor Szakats (12 May 2024)
 
-Matthias Gatto (30 Aug 2023)
+- lib: bump hash sizes to `size_t`
 
-- lib: fix aws-sigv4 having date header twice in some cases
+  Follow-up to cc907e80a2498c0599253271a6f657f614b52a4e #13502
+  Cherry-picked from #13489
+  Closes #13601
 
-  When the user was providing the header X-XXX-Date, the header was
-  re-added during signature computation, and we had it twice in the
-  request.
+- tests: make the unit test result type `CURLcode`
 
-  Reported-by: apparentorder@users.noreply.github.com
+  Before this patch, the result code was a mixture of `int` and
+  `CURLcode`.
 
-  Signed-off-by: Matthias Gatto 
+  Also adjust casts and fix a couple of minor issues found along the way.
 
-  Fixes: https://github.com/curl/curl/issues/11738
-  Closes: https://github.com/curl/curl/pull/11754
+  Cherry-picked from #13489
+  Closes #13600
 
-Jay Satiro (30 Aug 2023)
+- appveyor: tidy-ups
 
-- multi: remove 'processing: ' debug message
+  - delete a duplicate line.
+  - simplify a `make` call.
+  - merge two `if` branches.
+  - reorder autotools options for clarity.
+  - add `--enable-warnings` where missing (it's also the default.)
+  - add empty lines to YAML for readability.
+  - use lowercase install prefix/directory.
 
-  - Remove debug message added by e024d566.
+  Closes #13598
 
-  Closes https://github.com/curl/curl/pull/11759
+Daniel Stenberg (12 May 2024)
 
-- ftp: fix temp write of ipv6 address
+- docs/cmdline-opts: mention STARTTLS for --ssl and --ssl-reqd
 
-  - During the check to differentiate between a port and IPv6 address
-    without brackets, write the binary IPv6 address to an in6_addr.
+  ... since users might look for those terms in the manpage.
 
-  Prior to this change the binary IPv6 address was erroneously written to
-  a sockaddr_in6 'sa6' when it should have been written to its in6_addr
-  member 'sin6_addr'. There's no fallout because no members of 'sa6' are
-  accessed before it is later overwritten.
+  Closes #13590
 
-  Closes https://github.com/curl/curl/pull/11747
+- setopt: warn on Curl_set*opt() uses not using the return value
 
-- tool: change some fopen failures from warnings to errors
+  And switch the invokes that would "set" NULL to instead just plainly
+  free the pointer, as those were otherwise the invokes that would ignore
+  the return code. And possibly confuse static code analyzers.
 
-  - Error on missing input file for --data, --data-binary,
-    --data-urlencode, --header, --variable, --write-out.
+  Closes #13591
 
-  Prior to this change if a user of the curl tool specified an input file
-  for one of the above options and that file could not be opened then it
-  would be treated as zero length data instead of an error. For example, a
-  POST using `--data @filenametypo` would cause a zero length POST which
-  is probably not what the user intended.
+Orgad Shaneh (12 May 2024)
 
-  Closes https://github.com/curl/curl/pull/11677
+- autotools: delete unused functions
 
-- hostip: fix typo
+  Closes #13605
 
-Davide Masserut (29 Aug 2023)
+Viktor Szakats (11 May 2024)
 
-- tool: avoid including leading spaces in the Location hyperlink
+- examples: fix/silence `-Wsign-conversion`
 
-  Co-authored-by: Dan Fandrich 
+  - extend `FD_SET()` hack to all platforms (was only Cygwin).
+    Warnings may also happen in other envs, e.g. OmniOS.
+    Ref: https://github.com/libssh2/libssh2/actions/runs/8854199687/job/2431676
+  2831#step:3:2021
 
-  Closes #11735
+  - tidy-up `CURLcode` vs `int` use.
 
-Daniel Stenberg (29 Aug 2023)
+  - cast an unsigned to `long` before passing to `curl_easy_setopt()`.
 
-- SECURITY-PROCESS.md: not a sec issue: Tricking user to run a cmdline
+  Cherry-picked from #13489
+  Follow-up to 3829759bd042c03225ae862062560f568ba1a231 #12489
+  Closes #13501
 
-  Closes #11757
+Orgad Shaneh (11 May 2024)
 
-- connect: stop halving the remaining timeout when less than 600 ms left
+- cmake: fix `HAVE_IOCTLSOCKET_FIONBIO` test with gcc 14
 
-  When curl wants to connect to a host, it always has a TIMEOUT. The
-  maximum time it is allowed to spend until a connect is confirmed.
+  The function signature has had u_long flags since ever. This is how it
+  is defined in the documentation, and implemented in MinGW.
 
-  curl will try to connect to each of the IP adresses returned for the
-  host. Two loops, one for each IP family.
+  The code that uses ioctlsocket in nonblock.c also has unsigned long.
 
-  During the connect loop, while curl has more than one IP address left to
-  try within a single address family, curl has traditionally allowed (time
-  left/2) for *this* connect attempt. This, to not get stuck on the
-  initial addresses in case the timeout but still allow later addresses to
-  get attempted.
+  Error:
+  CurlTests.c:275:41: error: passing argument 3 of 'ioctlsocket' from incompati
+  ble pointer type [-Wincompatible-pointer-types]
+    275 |         if(0 != ioctlsocket(0, FIONBIO, &flags))
+        |                                         ^~~~~~
+        |                                         |
+        |                                         int *
+  In file included from CurlTests.c:266:
+  /opt/mxe/usr/i686-w64-mingw32.static/include/winsock2.h:1007:76: note: expect
+  ed 'u_long *' {aka 'long unsigned int *'} but argument is of type 'int *'
+   1007 |   WINSOCK_API_LINKAGE int WSAAPI ioctlsocket(SOCKET s,__LONG32 cmd,u_
+  long *argp);
+        |                                                                    ~~
+  ~~~~~~^~~~
 
-  This has the downside that when users set a very short timeout and the
-  host has a large number of IP addresses, the effective result might be
-  that every attempt gets a little too short time.
+  Closes #13578
 
-  This change stop doing the divided-by-two if the total time left is
-  below a threshold. This threshold is 600 milliseconds.
+Jay Satiro (10 May 2024)
 
-  Closes #11693
+- ftp: fix build for CURL_DISABLE_VERBOSE_STRINGS
 
-- asyn-ares: reduce timeout to 2000ms
+  This is a follow-up to b7c7dffe which changed the FTP state change
+  verbose debug text (aka infof) to tracing debug text (aka trc).
 
-  When UDP packets get lost this makes for slightly faster retries. This
-  lower timeout is used by @c-ares itself by default starting next
-  release.
+  Prior to this change if libcurl was without DEBUGBUILD and built with
+  CURL_DISABLE_VERBOSE_STRINGS (ie --disable-verbose) the build would
+  error.
 
-  Closes #11753
+  Caught by Circle CI job openssl-no-verbose.
 
-John Bampton (29 Aug 2023)
+- lib: clear the easy handle's saved errno before transfer
 
-- misc: remove duplicate words
+  - Clear data->state.os_errno before transfer.
 
-  Closes #11740
+  - Explain the change in behavior in the CURLINFO_OS_ERRNO doc.
 
-Daniel Stenberg (29 Aug 2023)
+  - Add to the CURLINFO_OS_ERRNO doc the list of libcurl network-related
+    errors that may cause the errno to be saved.
 
-- RELEASE-NOTES: synced
+  data->state.os_errno is saved before libcurl returns a network-related
+  failure such as connection failure. It is accessible to the user via
+  CURLINFO_OS_ERRNO so they can get more information about the failure.
 
-- wolfSSL: avoid the OpenSSL compat API when not needed
+  Prior to this change it wasn't cleared before transfer, so if a user
+  retrieved the saved errno it could be from a previous transfer. That is
+  because an errno is not always saved for network-related errors.
 
-  ... and instead call wolfSSL functions directly.
+  Closes https://github.com/curl/curl/pull/13574
 
-  Closes #11752
+Stefan Eissing (10 May 2024)
 
-Viktor Szakats (28 Aug 2023)
+- ftp: add tracing support
 
-- lib: fix null ptr derefs and uninitialized vars (h2/h3)
+  - add `Curl_trc_feat_ftp` for tracing via trace config
+  - add macro CURL_TRC_FTP(data, fmt, ...)
+  - replace DEBUGF(infof()) statements in ftp.c by CURL_TRC_FTP()
+  - always trace FTP connection state
 
-  Fixing compiler warnings with gcc 13.2.0 in unity builds.
+  Closes #13580
 
-  Assisted-by: Jay Satiro
-  Assisted-by: Stefan Eissing
-  Closes #11739
+Daniel Stenberg (10 May 2024)
 
-Jay Satiro (28 Aug 2023)
+- http: remove redundant check
 
-- secureserver.pl: fix stunnel version parsing
+  Spotted by CodeSonar
 
-  - Allow the stunnel minor-version version part to be zero.
+  Closes #13582
 
-  Prior to this change with the stunnel version scheme of .
-  if either part was 0 then version parsing would fail, causing
-  secureserver.pl to fail with error "No stunnel", causing tests that use
-  the SSL protocol to be skipped. As a practical matter this bug can only
-  be caused by a minor-version part of 0, since the major-version part is
-  always greater than 0.
+Viktor Szakats (10 May 2024)
 
-  Closes https://github.com/curl/curl/pull/11722
+- ldap: fix unused variables (seen on OmniOS)
 
-- secureserver.pl: fix stunnel path quoting
+  ```
+  ../../lib/ldap.c: In function 'ldap_do':
+    ../../lib/ldap.c:380:11: error: unused variable 'ldap_ca' [-Werror=unused-v
+  ariable]
+      380 |     char *ldap_ca = conn->ssl_config.CAfile;
+          |           ^~~~~~~
+    ../../lib/ldap.c:379:9: error: unused variable 'ldap_option' [-Werror=unuse
+  d-variable]
+      379 |     int ldap_option;
+          |         ^~~~~~~~~~~
+  ```
+  Ref: https://github.com/curl/curl/actions/runs/9033564377/job/24824192730#ste
+  p:3:6059
 
-  - Store the stunnel path in the private variable $stunnel unquoted and
-    instead quote it in the command strings.
+  Ref: #13583
+  Closes #13588
 
-  Prior to this change the quoted stunnel path was passed to perl's file
-  operators which cannot handle quoted paths. For example:
+Daniel Stenberg (10 May 2024)
 
-  $stunnel = "\"/C/Program Files (x86)/stunnel/bin/tstunnel\"";
-  if(-x $stunnel or -x "$stunnel")
-  # false even if path exists and is executable
+- url: make parse_login_details use memdup0
 
-  Our other test scripts written in perl, unlike this one, use servers.pm
-  which has a global $stunnel variable with the path stored unquoted and
-  therefore those scripts don't have this problem.
+  Also make the user and password arguments mandatory, since all code
+  paths in libcurl used them anyway.
 
-  Closes https://github.com/curl/curl/pull/11721
+  Adapted unit test case 1620 to the new rules.
 
-Daniel Stenberg (28 Aug 2023)
+  Closes #13584
 
-- altsvc: accept and parse IPv6 addresses in response headers
+Orgad Shaneh (10 May 2024)
 
-  Store numerical IPv6 addresses in the alt-svc file with the brackets
-  present.
+- digest: replace strcpy for empty string with simple assignment
 
-  Verify with test 437 and 438
+  Closes #13586
 
-  Fixes #11737
-  Reported-by: oliverpool on github
-  Closes #11743
+Viktor Szakats (10 May 2024)
 
-- libtest: use curl_free() to free libcurl allocated data
+- autotools: fix `HAVE_IOCTLSOCKET_FIONBIO` test for gcc 14
 
-  In several test programs. These mistakes are not detected or a problem
-  as long as memdebug.h is included, as that provides the debug wrappers
-  for all memory functions in the same style libcurl internals do it,
-  which makes curl_free and free effectively the same call.
+  ```
+  conftest.c:152:41: error: passing argument 3 of 'ioctlsocket' from incompatib
+  le pointer type [-Wincompatible-pointer-types]
+    152 |         if(0 != ioctlsocket(0, FIONBIO, &flags))
+        |                                         ^~~~~~
+        |                                         |
+        |                                         int *
+  ```
 
-  Reported-by: Nicholas Nethercote
-  Closes #11746
+  Reported-by: LigH
+  Fixes #13579
+  Closes #13587
 
-Jay Satiro (28 Aug 2023)
+- CI: ignore test 286 on Appveyor gcc 7 build
 
-- disable.d: explain --disable not implemented prior to 7.50.0
+  Disabled earlier for gcc 9 builds. gcc 7 uses the same runner and
+  prone to similar intermittent failures.
 
-  Option -q/--disable was added in 5.0 but only -q was actually
-  implemented. Later --disable was implemented in e200034 (precedes
-  7.49.0), but incorrectly, and fixed in 6dbc23c (precedes 7.50.0).
+  Follow-up to f1e05a6e6e7225fa09952abb2c935ae1abe44f45 #12106 #12040
+  Closes #13575
 
-  Reported-by: pszlazak@users.noreply.github.com
+Daniel Stenberg (10 May 2024)
 
-  Fixes https://github.com/curl/curl/issues/11710
-  Closes #11712
+- cf-socket: don't try getting local IP without socket
 
-Nicholas Nethercote (28 Aug 2023)
+  In cf_tcp_connect(), it might fail and not get a socket assigned to
+  ctx->sock but set_local_ip() is still called which would make
+  getsockname() get invoked with a negative file desriptor and fail.
 
-- hyper: fix ownership problems
+  By adding this check, set_local_ip() will now instead blank out the
+  fields correctly.
 
-  Some of these changes come from comparing `Curl_http` and
-  `start_CONNECT`, which are similar, and adding things to them that are
-  present in one and missing in another.
+  Spotted by CodeSonar
 
-  The most important changes:
-  - In `start_CONNECT`, add a missing `hyper_clientconn_free` call on the
-    happy path.
-  - In `start_CONNECT`, add a missing `hyper_request_free` on the error
-    path.
-  - In `bodysend`, add a missing `hyper_body_free` on an early-exit path.
-  - In `bodysend`, remove an unnecessary `hyper_body_free` on a different
-    error path that would cause a double-free.
-    https://docs.rs/hyper/latest/hyper/ffi/fn.hyper_request_set_body.html
-    says of `hyper_request_set_body`: "This takes ownership of the
-    hyper_body *, you must not use it or free it after setting it on the
-    request." This is true even if `hyper_request_set_body` returns an
-    error; I confirmed this by looking at the hyper source code.
+  Closes #13577
 
-  Other changes are minor but make things slightly nicer.
+- tool_getparam: remove two redundant conditions
 
-  Closes #11745
+  When getstr() does not return error, it returns a valid pointer.
 
-Daniel Stenberg (28 Aug 2023)
+  Spotted by CodeSonar
 
-- multi.h: the 'revents' field of curl_waitfd is supported
+  Closes #13576
 
-  Since 6d30f8ebed34e7276
+Stefan Eissing (10 May 2024)
 
-  Reported-by: Nicolás Ojeda Bär
-  Ref: #11748
-  Closes #11749
+- quiche: trust its timeout handling
 
-Gerome Fournier (27 Aug 2023)
+  - set the idle timeout transport parameter
+    in milliseconds as documented by quiche
+  - do not calculate the idle timeout, rely on
+    quiche handling it
 
-- tool_paramhlp: improve str2num(): avoid unnecessary call to strlen()
+  Closes #13581
 
-  Closes #11742
+Daniel Stenberg (10 May 2024)
 
-Daniel Stenberg (27 Aug 2023)
+- dmaketgz: accept a SOURCE_DATE_EPOCH as an second argument
 
-- docs: mention critical files in same directories as curl saves
+  to make it easier to reproduce a tarball
 
-  ... cannot be fully protected. Don't do it.
+  Closes #13573
 
-  Co-authored-by: Jay Satiro
-  Reported-by: Harry Sintonen
-  Fixes #11530
-  Closes #11701
+- RELEASE-NOTES: synced
 
-John Hawthorn (26 Aug 2023)
+Stefan Eissing (10 May 2024)
 
-- OpenSSL: clear error queue after SSL_shutdown
+- h3/ngtcp2: improve error handling
 
-  We've seen errors left in the OpenSSL error queue (specifically,
-  "shutdown while in init") by adding some logging it revealed that the
-  source was this file.
+  - identify ngtcp2 and nghttp3 error codes that are fatal
+  - close quic connection on fatal errors
+  - refuse further filter operations once connection is closed
+  - confusion about the nghttp3 API. We should close the QUIC stream on
+    cancel and not use the nghttp3 calls intended to be invoked when the
+    QUIC stream was closed by the peer.
 
-  Since we call SSL_read and SSL_shutdown here, but don't check the return
-  code for an error, we should clear the OpenSSL error queue in case one
-  was raised.
+  Closes #13562
 
-  This didn't affect curl because we call ERR_clear_error before every
-  write operation (a0dd9df9ab35528eb9eb669e741a5df4b1fb833c), but when
-  libcurl is used in a process with other OpenSSL users, they may detect
-  an OpenSSL error pushed by libcurl's SSL_shutdown as if it was their
-  own.
+Jay Satiro (10 May 2024)
 
-  Co-authored-by: Satana de Sant'Ana 
+- docs: fix some CURLINFO examples
 
-  Closes #11736
+  - improve getinfo result check for example sections:
+    CURLINFO_ACTIVESOCKET, CURLINFO_LASTSOCKET, CURLINFO_SSL_VERIFYRESULT,
+    CURLINFO_PROXY_SSL_VERIFYRESULT
 
-Alexander Kanavin (25 Aug 2023)
+  - fix getinfo result check for example sections:
+    CURLINFO_NUM_CONNECTS, CURLINFO_OS_ERRNO
 
-- tests: update cookie expiry dates to far in the future
+  - fix verify result check for example sections:
+    CURLINFO_PROXY_SSL_VERIFYRESULT
 
-  This allows testing Y2038 with system time set to after that, so that
-  actual Y2038 issues can be exposed, and not masked by expiry errors.
+  Bug: https://github.com/curl/curl/discussions/13557#discussion-6625507
+  Reported-by: farazrbx@users.noreply.github.com
 
-  Fixes #11576
-  Closes #11610
+  Closes https://github.com/curl/curl/pull/13559
 
-John Bampton (25 Aug 2023)
+Daniel Stenberg (9 May 2024)
 
-- misc: fix spelling
+- KNOWN_BUGS: gssapi library name + version is missing in curl_version_info()
 
-  Closes #11733
+  Closes #13492
+  Closes #13570
 
-Daniel Stenberg (25 Aug 2023)
+- krb5: use dynbuf
 
-- cmdline-opts/page-header: clarify stronger that !opt == URL
+  Closes #13568
 
-  Everything provided on the command line that is not an option (or an
-  argument to an option) is treated as a URL.
+- managen: fix the option sort order
 
-  Closes #11734
+  ... it used to strip off the .d file extension to sort correctly but
+  ever since the extension changed to .md the operation failed and the
+  sort got wrong.
 
-- tests/runner: fix %else handling
+  Follow-up to 2494b8dd5175cee7f2e
 
-  Getting the show state proper for %else and %endif did not properly work
-  in nested cases.
+  Closes #13567
 
-  Follow-up to 3d089c41ea9
+Stefan Eissing (8 May 2024)
 
-  Closes #11731
+- GHA: repair the linux-old job
 
-Nicholas Nethercote (25 Aug 2023)
+  package libc6_2.28-10+deb10u2_amd64.deb changed to
+  libc6_2.28-10+deb10u3_amd64.deb
 
-- docs: Remove mention of #10803 from `KNOWN_BUGS`.
+  Closes #13564
 
-  Because the leaks have been fixed.
+Viktor Szakats (8 May 2024)
 
-- c-hyper: fix another memory leak in `Curl_http`.
+- appveyor: make gcc 6 mingw64 job build-only
 
-  There is a `hyper_clientconn_free` call on the happy path, but not one
-  on the error path. This commit adds one.
+  This job has proven to be the flakiest of all, and it's also the oldest
+  Windows runner we had tests running on: 'Visual Studio 2015', that is
+  running on Windows Server 2012 R2:
+    https://www.appveyor.com/docs/windows-images-software/
 
-  Fixes the second memory leak reported by Valgrind in #10803.
+  Turn off tests on this job to help stabilizing CI runs.
 
-  Fixes #10803
-  Closes #11729
+  This was also one of the slowest running job amongst the AppVeyor CI ones.
 
-- c-hyper: fix a memory leak in `Curl_http`.
+  Flakiness data:
+    https://testclutch.curl.se/static/reports/summary.html
+  Entries:
+    Appveyor / CMake, mingw-w64, gcc 6, Debug, x86, Schannel, Static, no-unity 
+  (curl) [current]
+    Appveyor / CMake, mingw-w64, gcc 6, Debug, x86, Schannel, Static (curl) [fo
+  rmer]
 
-  A request created with `hyper_request_new` must be consumed by either
-  `hyper_clientconn_send` or `hyper_request_free`.
+  Closes #13566
 
-  This is not terrifically clear from the hyper docs --
-  `hyper_request_free` is documented only with "Free an HTTP request if
-  not going to send it on a client" -- but a perusal of the hyper code
-  confirms it.
+Stefan Eissing (8 May 2024)
 
-  This commit adds a `hyper_request_free` to the `error:` path in
-  `Curl_http` so that the request is consumed when an error occurs after
-  the request is created but before it is sent.
+- unit2604: use alloc instead of overlong string const
 
-  Fixes the first memory leak reported by Valgrind in #10803.
+  Closes #13563
 
-  Closes #11729
+Daniel Gustafsson (8 May 2024)
 
-Daniel Stenberg (25 Aug 2023)
+- bufq: remove duplicate word in comment
 
-- RELEASE-NOTES: synced
+  Inspired by 13552.
 
-John Bampton (25 Aug 2023)
+  Closes: #13554
+  Reviewed-by: Daniel Stenberg 
 
-- misc: spellfixes
+Viktor Szakats (8 May 2024)
 
-  Closes #11730
+- lib/cf-h1-proxy: silence compiler warnings (gcc 14)
 
-Daniel Stenberg (25 Aug 2023)
+  They came up ealier with gcc 12 (Windows), but apparently gcc 14 is
+  still reporting them, also under Linux.
 
-- tests: add support for nested %if conditions
+  ```
+  /home/runner/work/curl-for-win/curl-for-win/curl/lib/cf-h1-proxy.c: In functi
+  on 'cf_h1_proxy_close':
+  /home/runner/work/curl-for-win/curl-for-win/curl/lib/cf-h1-proxy.c:1060:17: w
+  arning: null pointer dereference [-Wnull-dereference]
+   1060 |   cf->connected = FALSE;
+  /home/runner/work/curl-for-win/curl-for-win/curl/lib/cf-h1-proxy.c:1061:8: wa
+  rning: null pointer dereference [-Wnull-dereference]
+   1061 |   if(cf->ctx) {
+        |      ~~^~~~~
+  In function 'tunnel_free',
+      inlined from 'cf_h1_proxy_destroy' at /home/runner/work/curl-for-win/curl
+  -for-win/curl/lib/cf-h1-proxy.c:1053:3:
+  /home/runner/work/curl-for-win/curl-for-win/curl/lib/cf-h1-proxy.c:198:27: wa
+  rning: null pointer dereference [-Wnull-dereference]
+    198 |   struct h1_tunnel_state *ts = cf->ctx;
+        |                           ^~
+  ```
+  Ref: https://github.com/curl/curl-for-win/actions/runs/8985369476/job/2467921
+  9528#step:3:6320
 
-  Provides more flexiblity to test cases.
+  Fixes #13237
+  Closes #13555
 
-  Also warn and bail out if there is an '%else' or %endif' without a
-  preceeding '%if'.
+Michał Antoniak (8 May 2024)
 
-  Ref: #11610
-  Closes #11728
+- mbedtls: support TLS 1.3
 
-- time-cond.d: mention what happens on a missing file
+  Closes #13539
 
-  Closes #11727
+Daniel Stenberg (8 May 2024)
 
-Christian Hesse (24 Aug 2023)
+- version: use msnprintf instead of strncpy
 
-- docs/cmdline-opts: match the current output
+  - to ensure a terminating null byte
+  - to avoid zero-padding the target
 
-  The release date has been added in output, reflect that in documentation.
+  debug code only
 
-  Closes #11723
+  Closes #13549
 
-Daniel Stenberg (24 Aug 2023)
+- curl_path: make Curl_get_pathname use dynbuf
 
-- lib: minor comment corrections
+  ... instead of malloc and memcpy
 
-- docs: rewrite to present tense
+  - unit test 2604 verifies Curl_get_pathname()
 
-  ... instead of using future tense.
+  Closes #13550
 
-  + numerous cleanups and improvements
-  + stick to "reuse" not "re-use"
-  + fewer contractions
+- lib: make protocol handlers store scheme name lowercase
 
-  Closes #11713
+  - saves a lowercase operation when the "[scheme]_proxy" name is
+    generated
+  - appears less "shouting"
+  - update test 970, 972, 1438 and 1536
 
-- urlapi: setting a blank URL ("") is not an ok URL
+  Closes #13553
 
-  Test it in 1560
-  Fixes #11714
-  Reported-by: ad0p on github
-  Closes #11715
+- lib: remove two instances of "only only" messages
 
-- spelling: use 'reuse' not 're-use' in code and elsewhere
+  Fixes #13551
+  Reported-by: Lucas Nussbaum
+  Closes #13552
 
-  Unify the spelling as both versions were previously used intermittently
+Pavel Pavlov (7 May 2024)
 
-  Closes #11717
+- asyn-thread: fix curl_global_cleanup crash in Windows
 
-Michael Osipov (23 Aug 2023)
+  - Make sure that asynchronous resolves handled by Winsock are stopped
+    before WSACleanup is called.
 
-- system.h: add CURL_OFF_T definitions on HP-UX with HP aCC
+  This is implemented by ensuring that when Curl_resolver_kill is called
+  (eg via multi_done) it will cancel the Winsock asynchronous resolve and
+  wait for the cancellation to complete. Winsock runs the asynchronous
+  completion routine immediately when a resolve is canceled.
 
-  HP-UX on IA64 provides two modes: 32 and 64 bit while 32 bit being the
-  default one. Use "long long" in 32 bit mode and just "long" in 64 bit
-  mode.
+  Prior to this change it was possible that during curl_global_cleanup
+  "a DNS resolver thread created by GetAddrInfoExW did not terminate yet,
+  however curl is already shutting down, deinitializing Winsock with
+  WSACleanup() leading to an access violation."
 
-  Closes #11718
+  Background:
 
-Dan Fandrich (22 Aug 2023)
+  If libcurl is built with the asynchronous threaded resolver option for
+  Windows then it resolves in one of two ways. For Windows 8.1 and later,
+  libcurl resolves by using the Winsock asynchronous resolver which does
+  its own thread management. For older versions of Windows, libcurl
+  resolves by creating a separate thread that calls getaddrinfo. This
+  change only affects the former and it's already handled for the latter.
 
-- tests: don't call HTTP errors OK in test cases
+  Reported-by: Ch40zz@users.noreply.github.com
 
-  Some HTTP errors codes were accompanied by the text OK, which causes
-  some cognitive dissonance when reading them.
+  Fixes https://github.com/curl/curl/issues/13509
+  Closes https://github.com/curl/curl/pull/13518
 
-- http: close the connection after a late 417 is received
+Jay Satiro (7 May 2024)
 
-  In this situation, only part of the data has been sent before aborting
-  so the connection is no longer usable.
+- asyn-thread: fix Curl_thread_create result check
 
-  Assisted-by: Jay Satiro
-  Fixes #11678
-  Closes #11679
+  - Compare to curl_thread_t_null instead of 0 for error.
 
-- runtests: slightly increase the longest log file displayed
+  Currently for both supported thread libraries (pthreads and Windows)
+  curl_thread_t_null is defined as 0. However, the pattern throughout the
+  code is to check against curl_thread_t_null and not 0 since for
+  posterity some thread library may not use 0 for error.
 
-  The new limit provides enough space for a 64 KiB data block to be logged
-  in a trace file, plus a few lines at the start and end for context. This
-  happens to be the amount of data sent at a time in a PUT request.
+  Closes https://github.com/curl/curl/pull/13542
 
-- tests: add delay command to the HTTP server
+- curl_multibyte: remove access() function wrapper for Windows
 
-  This adds a delay after client connect.
+  - Remove curlx_win32_access() which was a wrapper to use access() in
+    Windows.
 
-Daniel Stenberg (22 Aug 2023)
+  This is a follow-up to 602fc213, one of two commits which removed
+  access() calls from the codebase and banned use of the function.
 
-- cirrus: install everthing with pkg, avoid pip
+  Closes https://github.com/curl/curl/pull/13529
 
-  Assisted-by: Sevan Janiyan
+Daniel Gustafsson (6 May 2024)
 
-  Closes #11711
+- tls: Remove EXAMPLEs from deprecated options
 
-- curl_url*.3: update function descriptions
+  CURLOPT_EGDSOCKET and CURLOPT_RANDOM_FILE are both completely dead
+  so remove their example sections since the code there is useless.
+  There is still a way to inject a random file for OpenSSL older than
+  1.1.0 but it's not what the example showed (and it's not even done
+  with this option) so we refrain from documenting it here.
 
-  - expand and clarify several descriptions
-  - avoid using future tense all over
+  Closes: #13540
+  Reviewed-by: Daniel Stenberg 
 
-  Closes #11708
+- tests: Only require EXAMPLE for non-deprecated options
 
-- RELEASE-NOTES: synced
+  Manpages which document deprecated CURLOPT_ or CURLINFO_ are not
+  required to have an EXAMPLE section since they might effectively
+  be dead no-ops which we don't want to trick users into believing
+  they can use by copying example code.
 
-Stefan Eissing (21 Aug 2023)
+  Closes: #13540
+  Reviewed-by: Daniel Stenberg 
 
-- CI/cirrus: disable python install on FreeBSD
+Daniel Stenberg (6 May 2024)
 
-  - python cryptography package does not build build FreeBSD
-  - install just mentions "error"
-  - this gets the build and the main test suite going again
+- EXPERIMENTAL: add graduation requirements for each feature
 
-  Closes #11705
+  Starting now, experimental features should have a set of documentated
+  requirements of what is needed for the feature to graduate.
 
-- test2600: fix flakiness on low cpu
+  This adds requirements to all existing experiments.
 
-  - refs #11355 where failures to to low cpu resources in CI
-    are reported
-  - vastly extend CURLOPT_CONNECTTIMEOUT_MS and max durations
-    to test cases
-  - trigger Curl_expire() in test filter to allow re-checks before
-    the usual 1second interval
+  Closes #13541
 
-  Closes #11690
+Ivan (6 May 2024)
 
-Maksim Sciepanienka (20 Aug 2023)
+- misc: fix typos, quoting and spelling
 
-- tool_urlglob: use the correct format specifier for curl_off_t in msnprintf
+  Fix wording of comments, and misquotings where `' is markdown parsed
+  where it shouldn't be, and remove a misspelled preprocessor comment
+  which really isn't needed (and removing it makes it match surrounding
+  code better).
 
-  Closes #11698
+  Closes: #13538
+  Reviewed-by: Daniel Gustafsson 
 
-Daniel Stenberg (20 Aug 2023)
+Daniel Gustafsson (6 May 2024)
 
-- test687/688: two more basic --xattr tests
+- tests: Mark tftpd timer function as noreturn
 
-  Closes #11697
+  This avoids the below compiler warning:
 
-- cmdline-opts/docs: mentioned the negative option part
+  tftpd.c:280:1: warning: function 'timer' could be declared with
+      attribute 'noreturn' [-Wmissing-noreturn]
 
-  ... for --no-alpn and --no-buffer in the same style done for other --no-
-  options:
+  Closes: #13534
+  Reviewed-by: Daniel Stenberg 
 
-  "Note that this is the negated option name documented."
+- doh: Remove unused function prototype
 
-  Closes #11695
+  Closes: #13536
+  Reviewed-by: Daniel Stenberg 
 
-Emanuele Torre (19 Aug 2023)
+Daniel Stenberg (6 May 2024)
 
-- tool/var: also error when expansion result starts with NUL
+- doh: cleanups in ECH related functions
 
-  Expansions whose output starts with NUL were being expanded to the empty
-  string, and not being recognised as values that contain a NUL byte, and
-  should error.
+  - make local_decode_rdata_name use dynbuf instead of calloc + memcpy
+  - avoid extra memdup in local_decode_rdata_alpn
+  - no need to if() before free()
+  - use memdup instead of calloc + memcpy in Curl_doh_decode_httpsrr
 
-  Closes #11694
+  Reviewed-by: Stephen Farrell
+  Closes #13526
 
-Daniel Stenberg (19 Aug 2023)
+Viktor Szakats (5 May 2024)
 
-- tests: add 'large-time' as a testable feature
+- libssh2: delete redundant feature guard
 
-  This allows test cases to require this feature to run and to be used in
-  %if conditions.
+  Delete `HAVE_LIBSSH2_VERSION` (equivalent to
+  `LIBSSH2_VERSION_NUM` > 0x010100) guard surrounding
+  a `LIBSSH2_VERSION_NUM` > 0x010B00 one.
 
-  Large here means larger than 32 bits. Ie does not suffer from y2038.
+  Reviewed-by: Daniel Gustafsson
+  Closes #13537
 
-  Closes #11696
+Jan Venekamp (5 May 2024)
 
-- tests/Makefile: add check-translatable-options.pl to tarball
+- tool_cfgable: free {proxy_}cipher13_list on exit
 
-  Used in test 1544
+  Author: Jan Venekamp
+  Reviewed-by: Daniel Gustafsson 
+  Closes: #13531
 
-  Follow-up to ae806395abc8c
+RainRat (4 May 2024)
 
-- gen.pl: fix a long version generation mistake
+- doh: Fix typo in comment
 
-  Too excessive escaping made the parsing not find the correct long names
-  later and instead add "wrong" links.
+  Closes: #13504
+  Author: RainRat on Github
+  Reviewed-by: Daniel Stenberg 
+  Reviewed-by: Daniel Gustafsson 
 
-  Follow-up to 439ff2052e219
+Christian Schmitz (4 May 2024)
 
-  Reported-by: Lukas Tribus
-  Fixes #11688
-  Closes #11689
+- dynbuf: Fix returncode on memory error
 
-- lib: move mimepost data from ->req.p.http to ->state
+  Curl_dyn_vaddf should return a proper error code in case allocating
+  memory failed.
 
-  When the legacy CURLOPT_HTTPPOST option is used, it gets converted into
-  the modem mimpost struct at first use. This data is (now) kept for the
-  entire transfer and not only per single HTTP request. This re-enables
-  rewind in the beginning of the second request instead of in end of the
-  first, as brought by 1b39731.
+  Closes: #13533
+  Author: Christian Schmitz 
+  Reviewed-by: Daniel Gustafsson 
 
-  The request struct is per-request data only.
+Daniel Stenberg (3 May 2024)
 
-  Extend test 650 to verify.
+- RELEASE-NOTES: synced
 
-  Fixes #11680
-  Reported-by: yushicheng7788 on github
-  Closes #11682
+Jan Venekamp (2 May 2024)
 
-Patrick Monnerat (17 Aug 2023)
+- bearssl: use common code for cipher suite lookup
 
-- os400: do not check translatable options at build time
+  Take advantage of the Curl_cipher_suite_walk_str() and
+  Curl_cipher_suite_get_str() functions introduced in commit fba9afeb.
 
-  Now that there is a test for this, the build time check is not needed
-  anymore.
+  This also fixes CURLOPT_SSL_CIPHER_LIST not working at all for bearssl
+  due to commit ff74cef5.
 
-  Closes #11650
+  Closes #13464
 
-- test1554: check translatable string options in OS400 wrapper
+Daniel Stenberg (2 May 2024)
 
-  This test runs a perl script that checks all string options are properly
-  translated by the OS400 character code conversion wrapper. It also
-  verifies these options are listed in alphanumeric order in the wrapper
-  switch statement.
+- curl.h: change CURL_SSLVERSION_* from enum to defines
 
-  Closes #11650
+  C++20 and later compilers emit a deprecation warning if values from two
+  different enums are combined with a bitwise operation the way the
+  CURL_SSLVERSION_* values were previously created.
 
-Daniel Stenberg (17 Aug 2023)
+  Reported-by: Michael Kaufmann
+  Fixes #13510
+  Closes #13511
 
-- unit3200: skip testing if function is not present
+- configure: error on missing perl if docs or manual is enabled
 
-  Fake a successful run since we have no easy mechanism to skip this test
-  for this advanced condition.
+  Fixes #13508
+  Reported-by: Harmen Stoppels
+  Closes #13514
 
-- unit2600: fix build warning if built without verbose messages
+- tool_cb_rea: limit rate unpause for -T . uploads
 
-- test1608: make it build and get skipped without shuffle DNS support
+  To avoid getting stuck in a busy-loop when nothing is read from stdin,
+  this function now checks the call rate and might enforce a short sleep
+  when called repeatedly without uploading anything. It is a crude
+  work-around to avoid a 100% busy CPU.
 
-- lib: --disable-bindlocal builds curl without local binding support
+  Reported-by: magisterquis on hackerone
+  Fixes #13174
+  Closes #13506
 
-- test1304: build and skip without netrc support
+Viktor Szakats (1 May 2024)
 
-- lib: build fixups when built with most things disabled
+- appveyor: enable websockets for VS2017 jobs
 
-  Closes #11687
+  Follow-up to eb4fe6c6340c3d5b0c347c6e30be004d4f9117d7 #13232
+  Closes #13513
 
-- workflows/macos.yml: disable zstd and alt-svc in the http-only build
+Daniel Stenberg (30 Apr 2024)
 
-  Closes #11683
+- if2ip: make the buf_size arg a size_t
 
-Stefan Eissing (17 Aug 2023)
+  sizes should be size_t
 
-- bearssl: handshake fix, provide proper get_select_socks() implementation
+  Ref: #13489
+  Closes #13505
 
-  - bring bearssl handshake times down from +200ms down to other TLS backends
-  - vtls: improve generic get_select_socks() implementation
-  - tests: provide Apache with a suitable ssl session cache
+- cf-https-connect: use timeouts as unsigned ints
 
-  Closes #11675
+  To match the type used in 'set.happy_eyeballs_timeout'.
 
-- tests: TLS session sharing test
+  Ref: #13489
+  Closes #13503
 
-  - test TLS session sharing with special test client
-  - expect failure with wolfSSL
-  - disable flaky wolfSSL test_02_07b
+- hash: change 'slots' to size_t from int
 
-  Closes #11675
+  - an unsigned type makes more sense
+  - size_t seems suitable
+  - on 64 bit args, the struct alignment makes the new Curl_hash remain
+    the same size
 
-Daniel Stenberg (17 Aug 2023)
+  Closes #13502
 
-- CURLOPT_*TIMEOUT*: extend and clarify
+Viktor Szakats (30 Apr 2024)
 
-  Closes #11686
+- libssh2: replace `access()` with `stat()`
 
-- urlapi: return CURLUE_BAD_HOSTNAME if puny2idn encoding fails
+  Prefer `stat()` to verify the presence of key files.
 
-  And document it. Only return out of memory when it actually is a memory
-  problem.
+  This drops the last uses of `access()` in the codebase, which was
+  reported to cause issues in some cases.
 
-  Pointed-out-by: Jacob Mealey
-  Closes #11674
+  Also add `access()` to the list of banned functions in checksrc.
 
-Mathew Benson (17 Aug 2023)
+  Ref: https://github.com/curl/curl/pull/13412#issuecomment-2065505415
+  Ref: https://github.com/curl/curl/pull/13482#issuecomment-2078980522
+  Ref: #13497
+  Co-authored-by: Jay Satiro
+  Closes #13498
 
-- cmake: add GnuTLS option
+Daniel Stenberg (30 Apr 2024)
 
-  - Option to use GNUTLS was missing. Hence was not able to use GNUTLS
-    with ngtcp2 for http3.
+- multi: remove useless assignment
 
-  Closes #11685
+  Spotted by CodeSonar
 
-Daniel Stenberg (16 Aug 2023)
+  Closes #13500
 
 - RELEASE-NOTES: synced
 
-- http: remove the p_pragma struct field
-
-  unused since 40e8b4e52 (2008)
-
-  Closes #11681
+fuzzard (29 Apr 2024)
 
-Jay Satiro (16 Aug 2023)
+- cmake: FindNGHTTP2 add static lib name to find_library call
 
-- CURLINFO_CERTINFO.3: better explain curl_certinfo struct
+  Add the static library name, nghttp2_static as a name to search.
 
-  Closes https://github.com/curl/curl/pull/11666
+  This provides cmake parity with the winbuild Makefile.vc allowing
+  the cmake build to find and allow the link to static nghttp2 library.
 
-- CURLINFO_TLS_SSL_PTR.3: clarify a recommendation
+Viktor Szakats (29 Apr 2024)
 
-  - Remove the out-of-date SSL backend list supported by
-    CURLOPT_SSL_CTX_FUNCTION.
+- DISTROS: add patch and issues link for curl-for-win
 
-  It makes more sense to just refer to that document instead of having
-  a separate list that has to be kept in sync.
+  curl-for-win sometimes includes curl patches that were already merged in
+  master, but not yet part of a stable release.
 
-  Closes https://github.com/curl/curl/pull/11665
+  Also include the Issues link. Build-specific issues are handled there.
 
-- write-out.d: clarify %{time_starttransfer}
+  Ref: #13493
+  Closes #13499
 
-  sync it up with CURLINFO_STARTTRANSFER_TIME_T
+Daniel Stenberg (29 Apr 2024)
 
-Daniel Stenberg (15 Aug 2023)
+- mime: avoid using access()
 
-- transfer: don't set TIMER_STARTTRANSFER on first send
+  If stat() fails, there is no point in calling access()
 
-  The time stamp is for measuring the first *received* byte
+  Also: return error immediately if the stat() fails.
 
-  Fixes #11669
-  Reported-by: JazJas on github
-  Closes #11670
+  Ref: #13482
+  Closes #13497
 
-trrui-huawei (15 Aug 2023)
+Stefan Eissing (29 Apr 2024)
 
-- quiche: enable quiche to handle timeout events
+- tests: add SNI and peer name checks
 
-  In parallel with ngtcp2, quiche also offers the `quiche_conn_on_timeout`
-  interface for the application to invoke upon timer
-  expiration. Therefore, invoking the `on_timeout` function of the
-  Connection is crucial to ensure seamless functionality of quiche with
-  timeout events.
+  - connect to DNS names with trailing dot
+  - connect to DNS names with double trailing dot
+  - rustls, always give `peer->hostname` and let it
+    figure out SNI itself
+  - add SNI tests for ip address and localhost
+  - document in code and TODO that QUIC with ngtcp2+wolfssl
+    does not do proper peer verification of the certificate
+  - mbedtls, skip tests with ip address verification as not
+    supported by the library
 
-  Closes #11654
+  Closes #13486
 
-- quiche: adjust quiche `QUIC_IDLE_TIMEOUT` to 60s
+Daniel Stenberg (29 Apr 2024)
 
-  Set the `QUIC_IDLE_TIMEOUT` parameter to match ngtcp2 for consistency.
+- curl_getdate.md: document two-digit year handling
 
-Daniel Stenberg (15 Aug 2023)
+  Mentioned-by: Paul Gilmartin
+  Ref: https://curl.se/mail/archive-2024-04/0014.html
+  Closes #13494
 
-- KNOWN_BUGS: LDAPS requests to ActiveDirectory server hang
+Viktor Szakats (29 Apr 2024)
 
-  Closes #9580
+- cmake: add `BUILD_EXAMPLES` option to build examples
 
-- imap: add a check for failing strdup()
+  You can enable it with `-DBUILD_EXAMPLES=ON`.
 
-- imap: remove the only sscanf() call in the IMAP code
+  To match autotools' `make examples` feature.
+  Windows (static) builds not tested.
 
-  Avoids the use of a stack buffer.
+  Also enable examples in a pair of CI jobs.
 
-  Closes #11673
+  Apply related updates to the macOS CI workflow:
+  - drop unused `CXX` envs.
+  - drop no longer needed `-Wno-error=undef -Wno-error=conversion` flags.
+  - pass `-Wno-deprecated-declarations` to GCC too (for `BUILD_EXAMPLES`).
+  - document why `-Wno-deprecated-declarations` is necessary.
 
-- imap: use a dynbuf in imap_atom
+  Closes #13491
 
-  Avoid a calculation + malloc. Build the output in a dynbuf.
+Stefan Eissing (26 Apr 2024)
 
-  Closes #11672
+- http3: quiche+ngtcp2 improvements
 
-Marin Hannache (14 Aug 2023)
+  - quiche: error transfers that try to receive on a closed
+    or draining connection
+  - ngtcp2: use callback for extending max bidi streams. This
+    allows more precise calculation of MAX_CONCURRENT as we
+    only can start a new stream when the server acknowledges
+    the close - not when we locally have closed it.
+  - remove a fprintf() from h2-download client to avoid excess
+    log files on tests timing out.
 
-- http: do not require a user name when using CURLAUTH_NEGOTIATE
+  Closes #13475
 
-  In order to get Negotiate (SPNEGO) authentication to work in HTTP you
-  used to be required to provide a (fake) user name (this concerned both
-  curl and the lib) because the code wrongly only considered
-  authentication if there was a user name provided, as in:
+- vtls: TLS session storage overhaul
 
-    curl -u : --negotiate https://example.com/
+  - add session with destructor callback
+  - remove vtls `session_free` method
+  - let `Curl_ssl_addsessionid()` take ownership
+    of session object, freeing it also on failures
+  - change tls backend use
+  - test_17, add tests for SSL session resumption
 
-  This commit leverages the `struct auth` want member to figure out if the
-  user enabled CURLAUTH_NEGOTIATE, effectively removing the requirement of
-  setting a user name both in curl and the lib.
+  Closes #13386
 
-  Signed-off-by: Marin Hannache 
-  Reported-by: Enrico Scholz
-  Fixes https://sourceforge.net/p/curl/bugs/440/
-  Fixes #1161
-  Closes #9047
+- multi: multi_wait improvements
 
-Viktor Szakats (13 Aug 2023)
+   - only call `multi_getsock()` once for all transfers
+   - realloc pollset array on demand
+   - fold repeated sockets
 
-- build: streamline non-UWP wincrypt detections
+  Closes #13150
 
-  - with CMake, use the variable `WINDOWS_STORE` to detect an UWP build
-    and disable our non-UWP-compatible use the Windows crypto API. This
-    allows to drop two dynamic feature checks.
+Philip Heiduck (25 Apr 2024)
 
-    `WINDOWS_STORE` is true when invoking CMake with
-    `CMAKE_SYSTEM_NAME` == `WindowsStore`. Introduced in CMake v3.1.
+- ci: remove microsoft-prod.list
 
-    Ref: https://cmake.org/cmake/help/latest/variable/WINDOWS_STORE.html
+  This is added by default, and it is often broken, but we don't need
+  anything from it.
 
-  - with autotools, drop the separate feature check for `wincrypt.h`. On
-    one hand this header has been present for long (even Borland C 5.5 had
-    it from year 2000), on the other we used the check result solely to
-    enable another check for certain crypto functions. This fails anyway
-    with the header not present. We save one dynamic feature check at the
-    configure stage.
+  Closes #13473
 
-  Reviewed-by: Marcel Raad
-  Closes #11657
+Evgeny Grin (Karlson2k) (25 Apr 2024)
 
-Nicholas Nethercote (13 Aug 2023)
+- curl_setup.h: detect 'inline' support
 
-- docs/HYPER.md: update hyper build instructions
+  Closes #13355
 
-  Nightly Rust and `-Z unstable-options` are not needed.
+Daniel Stenberg (25 Apr 2024)
 
-  The instructions here now match the hyper docs exactly:
-  https://github.com/hyperium/hyper/commit/bd7928f3dd6a8461f0f0fdf7ee0fd95c2f15
-  6f88
+- multi: avoid memory-leak risk
 
-  Closes #11662
+  'newurl' is allocated in some conditions and used in a few scenarios,
+  but there were theoretical combinations in which it would not get freed.
+  Move the free to happen unconditionally. Never triggered by tests, but
+  spotted by Coverity.
 
-Daniel Stenberg (13 Aug 2023)
+  Closes #13471
 
-- RELEASE-NOTES: synced
+Johann Sebastian Schicho (25 Apr 2024)
 
-- urlapi: CURLU_PUNY2IDN - convert from punycode to IDN name
+- sendf: Curl_cwriter_write: remove comment disallowing zero length writes
 
-  Asssisted-by: Jay Satiro
-  Closes #11655
+  They are needed to pass CLIENTWRITE_EOS.
 
-- spellcheck: adapt to backslashed minuses
+  Closes #13477
 
-  As the curl.1 has more backslashed minus, the cleanup sed lines xneed to
-  adapt.
+Stefan Eissing (25 Apr 2024)
 
-  Adjusted some docs slighly.
+- CI: macos fixes for new ARM GHA images
 
-  Follow-up to 439ff2052e
+  - based on #13478 with additions from #13476
+  - make homebrew install path flexible
+  - fix OpenSSL pkgconfig files libdir
+  - add path to --with-libssh2 target
+  - disable gcc securetransport due to linker
+    errors (missing symbols), probably because
+    the os version is no longer low enough
 
-  Closes #11663
+  Assisted-by: Viktor Szakats
 
-- gen: escape more minus
+  Closes #13479
 
-  Detected since it was still hard to search for option names using dashes
-  in the middle in the man page.
+- content_encoding: ignore duplicate chunked encoding
 
-  Closes #11660
+  - ignore duplicate "chunked" transfer-encodings from
+    a server to accomodate for broken implementations
+  - add test1482 and test1483
 
-- cookie-jar.d: enphasize that this option is ONLY writing cookies
+  Reported-by: Mel Zuser
+  Fixes #13451
+  Closes #13461
 
-  Reported-by: Dan Jacobson
-  Tweaked-by: Jay Satiro
-  Ref: #11642
-  Closes #11661
+Daniel Stenberg (25 Apr 2024)
 
-Nicholas Nethercote (11 Aug 2023)
+- tool: move tool_ftruncate64 to tool_util.c
 
-- docs/HYPER.md: document a workaround for a link error
+  ... and the prototype to tool_setup.h, to make them both available more
+  widely and accurately.
 
-  Closes #11653
+  Follow-up to 00bef95946d3511
 
-Jay Satiro (11 Aug 2023)
+  Fixes #13458
+  Closes #13459
 
-- schannel: verify hostname independent of verify cert
+Viktor Szakats (24 Apr 2024)
 
-  Prior to this change when CURLOPT_SSL_VERIFYPEER (verifypeer) was off
-  and CURLOPT_SSL_VERIFYHOST (verifyhost) was on we did not verify the
-  hostname in schannel code.
+- lib: silence `-Wsign-conversion` in base64, strcase, mprintf
 
-  This fixes KNOWN_BUG 2.8 "Schannel disable CURLOPT_SSL_VERIFYPEER and
-  verify hostname". We discussed a fix several years ago in #3285 but it
-  went stale.
+  Closes #13467
 
-  Assisted-by: Daniel Stenberg
+- CI: retain failure code after `./configure` with Circle CI
 
-  Bug: https://curl.haxx.se/mail/lib-2018-10/0113.html
-  Reported-by: Martin Galvan
+  Suggested-by: Dan Fandrich
+  Follow-up to 43299e93c06b96fea8a8dc9b1c2e49c82bc21801 #13462
+  Follow-up to d7332e3e46c3ef401b34e6a1a129eb4dd846c452 #12635
+  Closes #13468
 
-  Ref: https://github.com/curl/curl/pull/3285
+Daniel Stenberg (24 Apr 2024)
 
-  Fixes https://github.com/curl/curl/issues/3284
-  Closes https://github.com/curl/curl/pull/10056
+- RELEASE-NOTES: synced
 
-Daniel Stenberg (11 Aug 2023)
+Jan Venekamp (24 Apr 2024)
 
-- curl_quiche: remove superfluous NULL check
+- mbedTLS: implement CURLOPT_SSL_CIPHER_LIST option
 
-  'stream' is always non-NULL at this point
+  Use a lookup list to set the cipher suites, allowing the
+  ciphers to be set by either openssl or IANA names.
 
-  Pointed out by Coverity
+  To keep the binary size of the lookup list down we compress
+  each entry in the cipher list down to 2 + 6 bytes using the
+  C preprocessor.
 
-  Closes #11656
+  Closes #13442
 
-- curl/urlapi.h: tiny typo
+Viktor Szakats (24 Apr 2024)
 
-- github/labeler: make HYPER.md set Hyper and not TLS
+- CI: show more failed `config.log` on Circle CI
 
-- docs/cmdline-opts/gen.pl: hide "added in" before 7.50.0
+  Show last 1000 lines of `config.log` if `./configure` fails. This was
+  already done for one job, this patch extends it to all.
 
-  7.50.0 shipped on Jul 21 2016, over seven years ago. We no longer need
-  to specify version changes for earlier releases in the generated output.
+  Ref: #13438
+  Closes #13462
 
-  This ups the limit from the previous 7.30.0 (Apr 12 2013)
+Daniel Stenberg (24 Apr 2024)
 
-  This hides roughly 35 "added in" mentions.
+- telnet: check return code from fileno()
 
-  Closes #11651
+  and return error if necessary
 
-Jay Satiro (10 Aug 2023)
+  Spotted by CodeSonar
 
-- bug_report: require reporters to specify curl and os versions
+  Closes #13457
 
-  - Change curl version and os sections from single-line input to
-    multi-line textarea.
+Viktor Szakats (24 Apr 2024)
 
-  - Require curl version and os sections to be filled out before report
-    can be submitted.
+- tls: fix SecureTransport + BearSSL cmake unity builds
 
-  Closes https://github.com/curl/curl/pull/11636
+  Avoid clashing static function names by namespacing them.
 
-Daniel Stenberg (9 Aug 2023)
+  Pointed-out-by: Jan Venekamp
+  Ref: https://github.com/curl/curl/pull/13442#discussion_r1576350700
+  Closes #13450
 
-- gen.pl: replace all single quotes with aq
+Jay Satiro (24 Apr 2024)
 
-  - this prevents man from using a unicode sequence for them
-  - which then allows search to work properly
+- dllmain: Call OpenSSL thread cleanup for Windows and Cygwin
 
-  Closes #11645
+  - Call OPENSSL_thread_stop on thread termination (DLL_THREAD_DETACH)
+    to prevent a memory leak in case OpenSSL is linked statically.
 
-Viktor Szakats (9 Aug 2023)
+  - Warn in libcurl-thread.3 that if OpenSSL is linked statically then it
+    may require thread cleanup.
 
-- cmake: fix to use variable for the curl namespace
+  OpenSSL may need per-thread cleanup to stop a memory leak. For Windows
+  and Cygwin if libcurl was built as a DLL then we can do that for the
+  user by calling OPENSSL_thread_stop on thread termination. However, if
+  libcurl was built statically then we do not have notification of thread
+  termination and cannot do that for the user.
 
-  Replace (wrong) literal with a variable to specify the curl
-  namespace.
+  Also, there are several other unusual cases where it may be necessary
+  for the user to call OPENSSL_thread_stop, so in the libcurl-thread
+  warning I added a link to the OpenSSL documentation.
 
-  Follow-up to 1199308dbc902c52be67fc805c72dd2582520d30 #11505
+  Co-authored-by: Viktor Szakats
 
-  Reported-by: balikalina on Github
-  Fixes https://github.com/curl/curl/commit/1199308dbc902c52be67fc805c72dd25825
-  20d30#r123923098
-  Closes #11629
+  Reported-by: southernedge@users.noreply.github.com
+  Reported-by: zmcx16@users.noreply.github.com
 
-- cmake: allow `SHARE_LIB_OBJECT=ON` on all platforms
+  Ref: https://www.openssl.org/docs/man3.0/man3/OPENSSL_thread_stop.html#NOTES
 
-  2ebc74c36a19a1700af394c16855ce144d9878e3 #11546 introduced sharing
-  libcurl objects for shared and static targets.
+  Fixes https://github.com/curl/curl/issues/12327
+  Closes https://github.com/curl/curl/pull/12408
 
-  The above automatically enabled for Windows builds, with an option to
-  disable with `SHARE_LIB_OBJECT=OFF`.
+Jan Venekamp (24 Apr 2024)
 
-  This patch extend this feature to all platforms as a manual option.
-  You can enable it by setting `SHARE_LIB_OBJECT=ON`. Then shared objects
-  are built in PIC mode, meaning the static lib will also have PIC code.
+- rustls: remove incorrect SSLSUPP_TLS13_CIPHERSUITES flag
 
-  [EXPERIMENTAL]
+  The rustls backend advertises SSLSUPP_TLS13_CIPHERSUITES, but
+  the code does not actually seem to support it (yet?). Removed
+  the flag and corrected documentation.
 
-  Closes #11627
+  Closes #13452
 
-- cmake: assume `wldap32` availability on Windows
+Stefan Eissing (24 Apr 2024)
 
-  This system library first shipped with Windows ME, available as an extra
-  install for some older releases (according to [1]). The import library
-  was present already in old MinGW 3.4.2 (year 2007).
+- quiche: expire all active transfers on connection close
 
-  Drop the feature check and its associated `HAVE_WLDAP32` variable.
+  - when a connection close is detected, all ongoing transfers
+    need to expire bc no more POLL events are likely to happen
+    for them.
 
-  To manually disable `wldap32`, you can use the `USE_WIN32_LDAP=OFF`
-  CMake option, like before.
+  Fixes #13439
+  Reported-by: Jay Satiro
+  Closes #13447
 
-  [1]: https://dlcdn.apache.org/httpd/binaries/win32/LEGACY.html
+Dan Fandrich (23 Apr 2024)
 
-  Reviewed-by: Jay Satiro
-  Closes #11624
+- tests: fix feature case in test1481
 
-Daniel Stenberg (9 Aug 2023)
+  This test was being skipped everywhere because the feature never
+  matched.
 
-- page-header: move up a URL paragraph from GLOBBING to URL
+  Closes #13445
 
-- variable.d: output the function names table style
+Gusted (23 Apr 2024)
 
-  Also correct the url function name in the header
+- tool_operate: don't truncate the etag save file by default
 
-  Closes #11641
+  This fixes a regression of 75d79a4486b279100209ddf8c7fdb12955fb66e9. The
+  code in tool-operate truncated the etag save file, under the assumption
+  that the file would be written with a new etag value. However since
+  75d79a4486b279100209ddf8c7fdb12955fb66e9 that might not be the case
+  anymore and could result in the file being truncated when --etag-compare
+  and --etag-save was used and that the etag value matched with what the
+  server responded. Instead the truncation should not be done when a new
+  etag value should be written.
 
-- haproxy-clientip.d: remove backticks
+  Test 3204 was added to verify that the file with the etag value doesn't
+  change the contents when used by --etag-compare and --etage-save and
+  that value matches with what the server returns on a non 2xx response.
 
-  This is not markdown
+  Closes #13432
 
-  Follow-up to 0a75964d0d94a4
+Abdullah Alyan (22 Apr 2024)
 
-  Closes #11639
+- tests: enable test 1117 for hyper
 
-- RELEASE-NOTES: synced
+  Closes #13436
 
-- gen.pl: escape all dashes (ascii minus) to avoid unicode hyphens
+Daniel Stenberg (22 Apr 2024)
 
-  Reported-by: FC Stegerman
-  Fixes #11635
-  Closes #11637
+- sendf: useless assignment in cr_lc_read()
 
-- cmdline-opts/page-header: reorder, clean up
+  Spotted by CodeSonar
 
-  - removed some unnecessary blurb to focus
-  - moved up the more important URL details
-  - put "globbing" into its own subtitle and moved down a little
-  - mention the online man page in the version section
+  Closes #13437
 
-  Closes #11638
+- tool_paramhlp: remove duplicate assign
 
-- c-hyper: adjust the hyper to curlcode conversion
+  Spotted by CodeSonar
 
-  Closes #11621
+  Closes #13433
 
-- test2306: make it use a persistent connection
+- transfer: remove useless assignment
 
-  + enable verbose already from the start
+  in Curl_xfer_recv_resp
 
-  Closes #11621
+  Spotted by CodeSonar
 
-eppesuig (8 Aug 2023)
+  Closes #13435
 
-- list-only.d: mention SFTP as supported protocol
+- http: acknowledge a returned error code
 
-  Closes #11628
+  ... and do not overwrite it with a new value that could then hide the
+  problem.
 
-Daniel Stenberg (8 Aug 2023)
+  Spotted by CodeSonar
 
-- request.d: use .TP for protocol "labels"
+  Closes #13434
 
-  To render the section nicer in man page.
+- tool_operate: init vars unconditionally in post_per_transfer
 
-  Closes #11630
+  In case of (the unlikely) early return, they could otherwise remain
+  uninitialized
 
-- cf-haproxy: make CURLOPT_HAPROXY_CLIENT_IP set the *source* IP
+  Spotted by CodeSonar
 
-  ... as documented.
+  Closes #13430
 
-  Update test 3201 and 3202 accordingly.
+- RELEASE-NOTES: synced
 
-  Reported-by: Markus Sommer
-  Fixes #11619
-  Closes #11626
+- urlapi: allow setting port number zero
 
-- page-footer: QLOGDIR works with ngtcp2 and quiche
+  Also set and check errno when strtoul() parsing numbers for better error
+  checking.
 
-  It previously said "both" backends which is confusing as we currently
-  have three...
+  Updated test 1560
 
-  Closes #11631
+  Closes #13427
 
-Stefan Eissing (8 Aug 2023)
+- http_aws_sigv4: remove useless assignment
 
-- http3: quiche, handshake optimization, trace cleanup
+  This code assigned the variable the same value it already had
 
-  - load x509 store after clienthello
-  - cleanup of tracing
+  Spotted by CodeSonar
 
-  Closes #11618
+  Closes #13426
 
-Daniel Stenberg (8 Aug 2023)
+- file: remove useless assignment
 
-- ngtcp2: remove dead code
+  This code assigned the variable the same value it already had.
 
-  'result' is always zero (CURLE_OK) at this point
+  Spotted by CodeSonar
 
-  Detected by Coverity
+  Closes #13425
 
-  Closes #11622
+- test2406: verify -f with HTTP/2
 
-Viktor Szakats (8 Aug 2023)
+Stefan Eissing (19 Apr 2024)
 
-- openssl: auto-detect `SSL_R_TLSV13_ALERT_CERTIFICATE_REQUIRED`
+- http2 + ngtcp2: pass CURLcode errors from callbacks
 
-  OpenSSL 1.1.1 defines this macro, but no ealier version, or any of the
-  popular forks (yet). Use the macro itself to detect its presence,
-  replacing the hard-wired fork-specific conditions.
+  - errors returned by Curl_xfer_write_resp() and the header variant are
+    not errors in the protocol. The result needs to be returned on the
+    next recv() from the protocol filter.
 
-  This way the feature will enable automatically when forks implement it,
-  while also shorter and possibly requiring less future maintenance.
+  - make xfer write errors for response data cause the stream to be
+    cancelled
 
-  Follow-up to 94241a9e78397a2aaf89a213e6ada61e7de7ee02 #6721
+  - added pytest test_02_14 and test_02_15 to verify that also for
+    parallel processing
 
-  Reviewed-by: Jay Satiro
-  Closes #11617
+  Reported-by: Laramie Leavitt
+  Fixes #13411
+  Closes #13424
 
-- openssl: use `SSL_CTX_set_ciphersuites` with LibreSSL 3.4.1
+Daniel Stenberg (19 Apr 2024)
 
-  LibreSSL 3.4.1 (2021-10-14) added support for
-  `SSL_CTX_set_ciphersuites`.
+- request: make Curl_req_init return void
 
-  Ref: https://ftp.openbsd.org/pub/OpenBSD/LibreSSL/libressl-3.4.1-relnotes.txt
+  Since it could not return error and therefore this change removes dead
+  code for the caller.
 
-  Reviewed-by: Jay Satiro
-  Closes #11616
+  Spotted by CodeSonar.
 
-- openssl: use `SSL_CTX_set_keylog_callback` with LibreSSL 3.5.0
+  Closes #13423
 
-  LibreSSL 3.5.0 (2022-02-24) added support for
-  `SSL_CTX_set_keylog_callback`.
+- multi: remove the unused Curl_preconnect function
 
-  Ref: https://ftp.openbsd.org/pub/OpenBSD/LibreSSL/libressl-3.5.0-relnotes.txt
+  The implementation has been removed, no point in keeping it around.
 
-  Reviewed-by: Jay Satiro
-  Closes #11615
+  Follow-up to 476adfeac019ed
 
-- cmake: drop `HAVE_LIBWINMM` and `HAVE_LIBWS2_32` feature checks
+  Closes #13422
 
-  - `HAVE_LIBWINMM` was detected but unused. The `winmm` system library is
-    also not used by curl, but it is by its optional dependency `librtmp`.
-    Change the logic to always add `winmm` when `USE_LIBRTMP` is set. This
-    library has been available since the early days of Windows.
+- Curl_creader_read: init two variables to avoid using them uninited
 
-  - `HAVE_LIBWS2_32` detected `ws2_32` lib on Windows. This lib is present
-    since Windows 95 OSR2 (AFAIR). Winsock1 already wasn't supported and
-    other existing logic already assumed this lib being present, so delete
-    the check and replace the detection variable with `WIN32` and always
-    add `ws2_32` on Windows.
+  Spotted by CodeSonar
 
-  Closes #11612
+  Closes #13419
 
-Daniel Gustafsson (8 Aug 2023)
+- http: reject HTTP major version switch mid connection
 
-- crypto: ensure crypto initialization works
+  A connection that has seen an HTTP major version now refuses any other
+  major HTTP version in future responses. Previously, a HTTP/1.x
+  connection would just silently accept HTTP/2 or HTTP/3 in the status
+  lines as long as it had support for those built-in. It would then just
+  lead to confusion and badness.
 
-  Make sure that context initialization during hash setup works to avoid
-  going forward with the risk of a null pointer dereference.
+  Indirectly Spotted by CodeSonar which identified a duplicate assignment
+  in this function.
 
-  Reported-by: Philippe Antoine on HackerOne
-  Assisted-by: Jay Satiro
-  Assisted-by: Daniel Stenberg
+  Add test 471 to verify
 
-  Closes #11614
+  Closes #13421
 
-Viktor Szakats (7 Aug 2023)
+- mqtt: when Curl_xfer_recv returns error, don't use nread
 
-- openssl: switch to modern init for LibreSSL 2.7.0+
+  A returned error code makes other return value unreliable, and in this
+  case potentially uninitialized. On error, do not read other return
+  values like the nread counter.
 
-  LibreSSL 2.7.0 (2018-03-21) introduced automatic initialization,
-  `OPENSSL_init_ssl()` function and deprecated the old, manual init
-  method, as seen in OpenSSL 1.1.0. Switch to the modern method when
-  available.
+  Spotted by CodeSonar
 
-  Ref: https://ftp.openbsd.org/pub/OpenBSD/LibreSSL/libressl-2.7.0-relnotes.txt
+  Closes #13418
 
-  Reviewed-by: Daniel Stenberg
-  Closes #11611
+- ftp: fix socket leak on rare error
 
-Daniel Stenberg (7 Aug 2023)
+  In the function AcceptServerConnect() the newly created socket would
+  leak if Curl_conn_tcp_accepted_set() returns error. Which basically
+  should never happen.
 
-- gskit: remove
+  Spotted by CodeSonar.
 
-  We remove support for building curl with gskit.
+  Closes #13417
 
-   - This is a niche TLS library, only running on some IBM systems
-   - no regular curl contributors use this backend
-   - no CI builds use or verify this backend
-   - gskit, or the curl adaption for it, lacks many modern TLS features
-     making it an inferior solution
-   - build breakages in this code take weeks or more to get detected
-   - fixing gskit code is mostly done "flying blind"
+- urlapi: remove unused flags argument from Curl_url_set_authority
 
-  This removal has been advertized in DEPRECATED in Jan 2, 2023 and it has
-  been mentioned on the curl-library mailing list.
+  The function is only called from a single place (for HTTP/2 server push)
+  so might as well just assume this fixed option every time.
 
-  It could be brought back, this is not a ban. Given proper effort and
-  will, gskit support is welcome back into the curl TLS backend family.
+  Closes #13409
 
-  Closes #11460
+- github/ISSUE_TEMPLATE: tweak the commericual support text
 
-- RELEASE-NOTES: synced
+- github/ISSUE_TEMPLATE: link the GitHub discussions too
 
-Dan Fandrich (7 Aug 2023)
+  ... and move the feature request line to the bottom.
 
-- THANKS-filter: add a name typo
+- curl_url_get.md: clarify queries and fragments and CURLU_GET_EMPTY
 
-Stefan Eissing (7 Aug 2023)
+  Follow-up to 3eac21d86bc5
 
-- http3/ngtcp2: shorten handshake, trace cleanup
+  Closes #13407
 
-  - shorten handshake timing by delayed x509 store load (OpenSSL)
-    as we do for HTTP/2
-  - cleanup of trace output, align with HTTP/2 output
+Stefan Eissing (18 Apr 2024)
 
-  Closes #11609
+- tests: check caddy server version to match test expectations
 
-Daniel Stenberg (7 Aug 2023)
+  - new caddy servers no longer return 200 on POSTs, but 405
+    as they should
 
-- headers: accept leading whitespaces on first response header
+  Closes #13405
 
-  This is a bad header fold but since the popular browsers accept this
-  violation, so does curl now. Unless built with hyper.
+Daniel Stenberg (18 Apr 2024)
 
-  Add test 1473 to verify and adjust test 2306.
+- curl_url_set.md: extended
 
-  Reported-by: junsik on github
-  Fixes #11605
-  Closes #11607
+  Closes #13404
 
-- include/curl/mprintf.h: add __attribute__ for the prototypes
+- urlapi: add CURLU_GET_EMPTY for empty queries and fragments
 
-  - if gcc or clang is used
-  - if __STDC_VERSION__ >= 199901L, which means greater than C90
-  - if not using mingw
-  - if CURL_NO_FMT_CHECKS is not defined
+  By default the API inhibits empty queries and fragments extracted.
+  Unless this new flag is set.
 
-  Closes #11589
+  This also makes the behavior more consistent: without it set, zero
+  length queries and fragments are considered not present in the URL. With
+  the flag set, they are returned as a zero length strings if they were in
+  fact present in the URL.
 
-- tests: fix bad printf format flags in test code
+  This applies when extracting the individual query and fragment
+  components and for the full URL.
 
-- tests: fix header scan tools for attribute edits in mprintf.h
+  Closes #13396
 
-- cf-socket: log successful interface bind
+- RELEASE-NOTES: synced
 
-  When the setsockopt SO_BINDTODEVICE operation succeeds, output that in
-  the verbose output.
+- lib1560: test with leading zeroes and more IPv4 versions
 
-  Ref: #11599
-  Closes #11608
+  Inspired by WHATWG URL Spec test inputs
 
-- CURLOPT_SSL_VERIFYPEER.3: mention it does not load CA certs when disabled
+  Closes #13400
 
-  Ref: #11457
-  Closes #11606
+Christian Schmitz (17 Apr 2024)
 
-- CURLOPT_SSL_VERIFYPEER.3: add two more see also options
+- smtp: result of Curl_bufq_cread was not used
 
-  CURLINFO_CAINFO and CURLINFO_CAPATH
+  return the result back to the caller.
 
-  Closes #11603
+  Closes #13398
 
-- KNOWN_BUGS: aws-sigv4 does not behave well with AWS VPC Lattice
+Daniel Stenberg (17 Apr 2024)
 
-  Closes #11007
+- urlapi: fix relative redirects to fragment-only
 
-Graham Campbell (6 Aug 2023)
+  Using the URL API for a redirect URL when the redirected-to string
+  starts with a hash, ie is only a fragment, the API would produce the
+  wrong final URL.
 
-- CI: use openssl 3.0.10+quic, nghttp3 0.14.0, ngtcp2 0.18.0
+  Adjusted test 1560 to test for several new redirect cases.
 
-  Closes #11585
+  Closes #13394
 
-Daniel Stenberg (6 Aug 2023)
+Jiwoo Park (17 Apr 2024)
 
-- TODO: add *5* entries for aws-sigv4
+- url: fix use of an uninitialized variable
 
-  Closes #7559
-  Closes #8107
-  Closes #8810
-  Closes #9717
-  Closes #10129
+  Closes #13399
 
-- TODO: LDAP Certificate-Based Authentication
+Patrick Monnerat (17 Apr 2024)
 
-  Closes #9641
+- os400: sync with latest changes
 
-Stefan Eissing (6 Aug 2023)
+  - Conversion support for new version info character field rtmp_version.
+  - New ILE/RPG declarations.
 
-- http2: cleanup trace messages
+  Closes #13402
 
-  - more compact format with bracketed stream id
-  - all frames traced in and out
+Daniel Stenberg (17 Apr 2024)
 
-  Closes #11592
+- ngtcp2: fix macro use
 
-Daniel Stenberg (6 Aug 2023)
+  macro "H3_STREAM_CTX" requires 2 arguments, but only 1 given
 
-- tests/tftpd+mqttd: make variables static to silence picky warnings
+  Follow-up to c6655f7029ec5c128561e3ecf1f93db3ed0432a4
 
-  Closes #11594
+  Closes #13401
 
-- docs/cmdline: remove repeated working for negotiate + ntlm
+Christian Schmitz (17 Apr 2024)
 
-  The extra wording is added automatically by the gen.pl tool
+- sendf: fix two typos in comments
 
-  Closes #11597
+  The parameters are named data, not date.
 
-- docs/cmdline: add small "warning" to verbose options
+  Closes #13393
 
-  "Note that verbose output of curl activities and network traffic might
-  contain sensitive data, including user names, credentials or secret data
-  content. Be aware and be careful when sharing trace logs with others."
+- lib: silence warnings on comma misuse
 
-  Closes #11596
+  Building curl with -Wcomma, I see warnings about "possible misuse of
+  comma operator here" and moving fields assignment out of the for() fixes
+  it.
 
-- RELEASE-NOTES: synced
+  Closes #13392
 
-- pingpong: don't use *bump_headersize
+Stefan Eissing (17 Apr 2024)
 
-  We use that for HTTP(S) only.
+- http/2, http/3: decouple stream state from easy handle
 
-  Follow-up to 3ee79c1674fd6
+  - add `Curl_hash_offt` as hashmap between a `curl_off_t` and
+    an object. Use this in h2+h3 connection filters to associate
+    `data->id` with the internal stream state.
+  - changed implementations of all affected connection filters
+  - removed `h2_ctx*` and `h3_ctx*` from `struct HTTP` and thus
+    the easy handle
+  - solves the problem of attaching "foreign protocol" easy handles
+    during connection shutdown
 
-  Closes #11590
+  Test 1616 verifies the new hash functions.
 
-- urldata: remove spurious parenthesis to unbreak no-proxy build
+  Closes #13204
 
-  Follow-up to e12b39e13382
+Daniel Stenberg (17 Apr 2024)
 
-  Closes #11591
+- ROADMAP: remove completed entries, mention websocket
 
-- easy: don't call Curl_trc_opt() in disabled-verbose builds
+- THANKS-filter: name fixes
 
-  Follow-up to e12b39e133822c6a0
+Christian Schmitz (17 Apr 2024)
 
-  Closes #11588
+- winbuild: add ENABLE_WEBSOCKETS option
 
-- http: use %u for printfing int
+  Closes #13232
 
-  Follow-up to 3ee79c1674fd6f99e8efca5
+Daniel Stenberg (17 Apr 2024)
 
-  Closes #11587
+- dmaketgz: compacter
 
-Goro FUJI (3 Aug 2023)
+  Removes the need for disabling shellcheck warnings.
 
-- vquic: show stringified messages for errno
+  Follow-up to d28f74913c2
+  Proposed-by: Viktor Szakats
+  Closes #13391
 
-  Closes #11584
+Dan Fandrich (16 Apr 2024)
 
-Stefan Eissing (3 Aug 2023)
+- tests: Fix uninitialized value warning
 
-- trace: make tracing available in non-debug builds
+  The check for an option must be predicated on options existing at all.
 
-  Add --trace-config to curl
+  Follow-up to f7cc9e91
 
-  Add curl_global_trace() to libcurl
+Christian Schmitz (17 Apr 2024)
 
-  Closes #11421
+- idn: add native AppleIDN (icucore) support for macOS/iOS
 
-Daniel Stenberg (3 Aug 2023)
+  I implemented the IDN functions for macOS and iOS using Unicode
+  libraries coming with macOS and iOS.
 
-- TODO: remove "Support intermediate & root pinning for PINNEDPUBLICKEY"
+  Builds and runs here on macOS 14.2.1. Also verified to load and
+  run on older macOS version 10.13.
 
-  See also https://github.com/curl/curl/pull/7507
+  Build requires macOS SDK 13 or equivalent.
 
-- TODO: add "WebSocket read callback"
+  Set `-DUSE_APPLE_IDN=ON` CMake option to enable it.
+  With autotools and other build tools, set these manual options:
+  ```
+  CPPFLAGS=-DUSE_APPLE_IDN
+  LIBS=-licucore
+  ```
 
-  remove "Upgrade to websockets" as we already have this
+  Completes TODO 1.6.
 
-  Closes #11402
+  TODO: add autotools option and feature-detection.
 
-- test497: verify rejecting too large incoming headers
+  Refs: #5330 #5371
+  Co-authored-by: Viktor Szakats
+  Closes #13246
 
-- http: return error when receiving too large header set
+Stefan Eissing (16 Apr 2024)
 
-  To avoid abuse. The limit is set to 300 KB for the accumulated size of
-  all received HTTP headers for a single response. Incomplete research
-  suggests that Chrome uses a 256-300 KB limit, while Firefox allows up to
-  1MB.
+- http3: extend download abort tests, fixes in ngtcp2
 
-  Closes #11582
+  - fix flow handling in ngtcp2 to ACK data on streams
+    we abort ourself.
+  - extend test_02_23* cases to also run for h3
+  - skip test_02_23* for OpenSSL QUIC as it gets stalled
+    on progressing the connection
 
-Stefan Eissing (3 Aug 2023)
+  Closes #13374
 
-- http2: upgrade tests and add fix for non-existing stream
+Daniel Stenberg (16 Apr 2024)
 
-  - check in h2 filter recv that stream actually exists
-    and return error if not
-  - add test for parallel, extreme h2 upgrades that fail if
-    connections get reused before fully switched
-  - add h2 upgrade upload test just for completeness
+- tests: add -q as first option when invoking curl for tests
 
-  Closes #11563
+  To reduce the risk that the user running the tests has a .curlrc present
+  that messes things up.
 
-Viktor Szakats (3 Aug 2023)
+  Support 'option="no-q"' for the  tag to switch it off on demand.
+  Use this new feature in test 433 and 436.
 
-- tests: ensure `libcurl.def` contains all exports
+  Ref: #13284
+  Closes #13387
 
-  Add `test1279` to verify that `libcurl.def` lists all exported API
-  functions found in libcurl headers.
+- dmaketgz: release tarball generation using docker
 
-  Also:
+  For easier reproducibility.
 
-  - extend test suite XML `stdout` tag with the `loadfile` attribute.
+  Mention using this script in RELEASE-PROCEDURE
 
-  - fix `tests/extern-scan.pl` and `test1135` to include websocket API.
+  Closes #13388
 
-  - use all headers (sorted) in `test1135` instead of a manual list.
+Viktor Szakats (16 Apr 2024)
 
-  - add options `--sort`, `--heading=` to `tests/extern-scan.pl`.
+- cmake: update ECH code and minor fixups
 
-  - add `libcurl.def` to the auto-labeler GHA task.
+  - `openssl_check_symbol_exists()` expects a 4th argument now.
+    Follow-up to edc2702a1fe3a4a5386ffd9aa4f240f0c0197fa2 #13373
 
-  Follow-up to 2ebc74c36a19a1700af394c16855ce144d9878e3
+  - minor comment/script touch-ups.
+    Follow-up to a362962b7289ec02b412890c9515657cf0ed50ac #11922
 
-  Closes #11570
+  - fix indentation.
 
-Daniel Stenberg (2 Aug 2023)
+  Closes #13383
 
-- url: change default value for CURLOPT_MAXREDIRS to 30
+- tests: fix shellcheck issues in `ech_tests.sh`
 
-  It was previously unlimited by default, but that's not a sensible
-  default. While changing this has a remote risk of breaking an existing
-  use case, I figure it is more likely to actually save users from loops.
+  Add double-quotes where missing.
 
-  Closes #11581
+  Follow-up to a362962b7289ec02b412890c9515657cf0ed50ac #11922
+  Closes #13382
 
-- lib: fix a few *printf() flag mistakes
+- dist: add ECH files to tarball
 
-  Reported-by: Gisle Vanem
-  Ref: #11574
-  Closes #11579
+  Also sort `EXTRA_DIST` list in `tests/Makefile.am` and make it diffable.
 
-Samuel Chiang (2 Aug 2023)
+  Follow-up to a362962b7289ec02b412890c9515657cf0ed50ac #11922
+  Closes #13381
 
-- openssl: make aws-lc version support OCSP
+- openvms: look for `USE_IPV6` in `config.h` (was: `ENABLE_IPV6`)
 
-  And bump version in CI
+  The OpenVMS script `config_h.com` is parsing the config header
+  generated by autotools. Let's make it look for the macro name we now
+  use universally across the codebase.
 
-  Closes #11568
+  Follow-up to e411c98f702f0fb38dceec95e7507ef15a00d12c #13349
+  Closes #13360
 
-Daniel Stenberg (2 Aug 2023)
+daniel-j-h (16 Apr 2024)
 
-- tool: make the length argument an int for printf()-.* flags
+- Dockerfile: for release automation and reproducibility
 
-  Closes #11578
+  Closes #13250
 
-- tool_operate: fix memory leak when SSL_CERT_DIR is used
+Stefan Eissing (16 Apr 2024)
 
-  Detected by Coverity
+- cw-out: improved error handling
 
-  Follow-up to 29bce9857a12b6cfa726a5
+  - remember error encountered in invoking write callback and always fail
+    afterwards without further invokes
 
-  Closes #11577
+  - check behaviour in test_02_17 with h2-pausing client
 
-- tool/var: free memory on OOM
+  Reported-by: Pavel Kropachev
+  Fixes #13337
+  Closes #13340
 
-  Coverity detected this memory leak in OOM situation
+Daniel Stenberg (16 Apr 2024)
 
-  Follow-up to 2e160c9c652504e
+- version: add "ECH" as a feature
 
-  Closes #11575
+  If available
 
-Viktor Szakats (2 Aug 2023)
+  Follow-up to a362962b7
+  Closes #13378
 
-- gha: bump libressl and mbedtls versions
+- CURLOPT_ECH: polish
 
-  Closes #11573
+  - remove the pointer to build instructions, it won't work in manpages
+  - add see-also
+  - minor white space edits
 
-Jay Satiro (2 Aug 2023)
+  Closes #13379
 
-- schannel: fix user-set legacy algorithms in Windows 10 & 11
+Viktor Szakats (16 Apr 2024)
 
-  - If the user set a legacy algorithm list (CURLOPT_SSL_CIPHER_LIST) then
-    use the SCHANNEL_CRED legacy structure to pass the list to Schannel.
+- tidy-up: whitespace [ci skip]
 
-  - If the user set both a legacy algorithm list and a TLS 1.3 cipher list
-    then abort.
+- mbedtls: fix building with v3 in CMake Unity mode
 
-  Although MS doesn't document it, Schannel will not negotiate TLS 1.3
-  when SCHANNEL_CRED is used. That means setting a legacy algorithm list
-  limits the user to earlier versions of TLS.
+  Before this patch the internal feature detection macro
+  `HAS_MBEDTLS_RESULT_CODE_BASED_FUNCTIONS` was defined in three files,
+  with an incomplete logic in one of them. In Unity mode that spilled
+  into another source file and broke the build.
 
-  Prior to this change, since 8beff435 (precedes 7.85.0), libcurl would
-  ignore legacy algorithms in Windows 10 1809 and later.
+  Closes #13377
 
-  Reported-by: zhihaoy@users.noreply.github.com
+- cmake: add librtmp/rtmpdump option and detection
 
-  Fixes https://github.com/curl/curl/pull/10741
-  Closes https://github.com/curl/curl/pull/10746
+  Add CMake option `USE_LIBRTMP`. Disabled by default.
 
-Daniel Stenberg (2 Aug 2023)
+  This library requires OpenSSL TLS-backend when linked statically.
 
-- variable.d: setting a variable again overwrites it
+  Follow-up to 6eb9e65781fa1fd8a0bcfe0715187a3a35f09ae4 #13364
+  Closes #13373
 
-  Reported-by: Niall McGee
-  Bug: https://twitter.com/niallmcgee/status/1686523075423322113
-  Closes #11571
+Stephen Farrell (16 Apr 2024)
 
-Jay Satiro (2 Aug 2023)
+- TLS: add support for ECH (Encrypted Client Hello)
 
-- CURLOPT_PROXY_SSL_OPTIONS.3: sync formatting
+  An EXPERIMENTAL feature used with CURLOPT_ECH and --ech.
 
-  - Re-wrap CURLSSLOPT_ALLOW_BEAST description.
+  Closes #11922
 
-Daniel Stenberg (2 Aug 2023)
+Daniel Stenberg (15 Apr 2024)
 
 - RELEASE-NOTES: synced
 
-- resolve: use PF_INET6 family lookups when CURL_IPRESOLVE_V6 is set
-
-  Previously it would always do PF_UNSPEC if CURL_IPRESOLVE_V4 is not
-  used, thus unnecessarily asking for addresses that will not be used.
+- multi: introduce SETUP state for better timeouts
 
-  Reported-by: Joseph Tharayil
-  Fixes #11564
-  Closes #11565
+  Since we can go to the CONNECT state from PENDING, potentially multiple
+  times for a single transfer, this change introdues a SETUP state that
+  happens before CONNECT when doing a new transfer.
 
-- docs: link to the website versions instead of markdowns
+  Now, doing a redirect on a handle goes back to SETUP (not CONNECT like
+  before) and we initilize the connect timeout etc in SETUP. Previously,
+  we would do it in CONNECT but that would make it unreliable in cases
+  where a transfer goes in and out between CONNECT and PENDING multiple
+  times.
 
-  ... to make the links work when the markdown is converted to webpages on
-  https://curl.se
+  SETUP is transient, so the handle never actually stays in that state.
 
-  Reported-by: Maurício Meneghini Fauth
-  Fixes https://github.com/curl/curl-www/issues/272
-  Closes #11569
+  Additionally: take care of timeouts of PENDING transfers in
+  curl_multi_perform()
 
-Viktor Szakats (1 Aug 2023)
+  Ref: #13227
+  Closes #13371
 
-- cmake: cache more config and delete unused ones
+Tal Regev (15 Apr 2024)
 
-  - cache more Windows config results for faster initialization.
+- cmake: forward `USE_LIBRTMP` option to C
 
-  - delete unused config macros `HAVE_SYS_UTSNAME_H`, `HAVE_SSL_H`.
+  Define in C `USE_LIBRTMP` if user requested it from cmake.
 
-  - delete dead references to `sys/utsname.h`.
+  Closes #13364
 
-  Closes #11551
+Daniel Stenberg (15 Apr 2024)
 
-- egd: delete feature detection and related source code
+- curl_version_info: provide librtmp version
 
-  EGD is Entropy Gathering Daemon, a socket-based entropy source supported
-  by pre-OpenSSL v1.1 versions and now deprecated. curl also deprecated it
-  a while ago.
+  Ref: https://github.com/curl/curl/pull/13364#issuecomment-2054151942
+  Reported-by: talregev on github
+  Closes #13368
 
-  Its detection in CMake was broken all along because OpenSSL libs were
-  not linked at the point of feature check.
+blankie (15 Apr 2024)
 
-  Delete detection from both cmake and autotools, along with the related
-  source snippet, and the `--with-egd-socket=` `./configure` option.
+- docs: clarify CURLOPT_MAXFILESIZE and CURLOPT_MAXFILESIZE_LARGE
 
-  Closes #11556
+  The bounds of the size parameter were not specified, and nor was it
+  specified how to disable the maximum file size check.
 
-Stefan Eissing (1 Aug 2023)
+  The documentation also incorrectly stated that CURLOPT_MAXFILESIZE
+  always returns CURLE_OK and that CURLOPT_MAXFILESIZE_LARGE only returns
+  CURLE_OK or CURLE_UNKNOWN_OPTION.
 
-- tests: fix h3 server check and parallel instances
+  It also did not mention what the default value is, which is zero. This
+  commit updates the documentation to make note of all these things.
 
-  - fix check for availability of nghttpx server
-  - add `tcp` frontend config for same port as quic, as
-    without this, port 3000 is bound which clashes for parallel
-    testing
+  Closes #13372
 
-  Closes #11553
+Patrick Monnerat (15 Apr 2024)
 
-Daniel Stenberg (1 Aug 2023)
+- OS400: post-shellcheck changes adjustments
 
-- docs/cmdline-opts: spellfixes, typos and polish
+  Build scripts must be executed by the os/400 shell (sh), not bash which
+  is a PASE program.
 
-  To make them accepted by the spell checker
+  Shell function get_make_vars() escaping reworked to match $() subcommand
+  construct.
 
-  Closes #11562
+  Follow-up to 8a622baf9e9233241bbe93d6599c99cb46478614
+  Closes #13366
 
-- CI/spellcheck: build curl.1 and spellcheck it
+Viktor Szakats (15 Apr 2024)
 
-  Added acceptable words
+- OS400: tidy-up
 
-  Closes #11562
+  Drop/fixup mods trying to make some syntax highlighters happier.
 
-Alexander Jaeger (1 Aug 2023)
+  Follow-up to 8a622baf9e9233241bbe93d6599c99cb46478614 #13309
+  Closes #13362
 
-- misc: fix various typos
+Daniel Stenberg (15 Apr 2024)
 
-  Closes #11561
+- multi: timeout handles even without connection
 
-Daniel Stenberg (1 Aug 2023)
+  When there is a "change" in a multi handle and pending handles are moved
+  back to the main list to be retested if they can proceed further (for
+  example a previous transfer completed or a connection has a confirmed
+  multiplexed state), the timeout check in multi_runsingle() would not
+  trigger because it required an established connection.
 
-- http2: avoid too early connection re-use/multiplexing
+  This could make a pending tranfer go back to pending state even though
+  it had been "in progress" for a longer time than permitted. By removing
+  the requirement for an associated connection, the timeout check will be
+  done proper even for transfers that has not yet been assigned one.
 
-  HTTP/1 connections that are upgraded to HTTP/2 should not be picked up
-  for reuse and multiplexing by other handles until the 101 switching
-  process is completed.
+  Ref #13227
+  Reported-by: Rahul Krishna M
+  Closes #13276
 
-  Lots-of-debgging-by: Stefan Eissing
-  Reported-by: Richard W.M. Jones
-  Bug: https://curl.se/mail/lib-2023-07/0045.html
-  Closes #11557
+Patrick Monnerat (15 Apr 2024)
 
-- Revert "KNOWN_BUGS: build for iOS simulator on macOS 13.2 with Xcode 14"
+- mprintf: check fputc error rather than matching returned character
 
-  This reverts commit 2e8a3d7cb73c85a9aa151e263315f8a496dbb9d4.
+  OS/400 ascii fputc wrapper deviates from the posix standard by the
+  fact that it returns the ebcdic encoding of the original ascii
+  character. Testing for a matching value for success will then always
+  fail.
 
-  It's a user error for supplying incomplete information to the build system.
+  This commit replaces the chariacter comparison by an explicit error
+  return check.
 
-  Reported-by: Ryan Schmidt
-  Ref: https://github.com/curl/curl/issues/11215#issuecomment-1658729367
+  Follow-up to ef2cf58
+  Closes #13367
 
-Viktor Szakats (1 Aug 2023)
+Viktor Szakats (14 Apr 2024)
 
-- cmake: add support for single libcurl compilation pass
+- ci: add CMake build variation, fixup libssh detection in `linux-old`
 
-  Before this patch CMake builds used two separate compilation passes to
-  build the shared and static libcurl respectively. This patch allows to
-  reduce that to a single pass if the target platform and build settings
-  allow it.
+  To test without c-ares and hit `easy_lock.h` on an old system. Use this
+  new build step to introduce small variations, and also test libssh2.
 
-  This reduces CMake build times when building both static and shared
-  libcurl at the same time, making these dual builds an almost zero-cost
-  option.
+  Also add workaround to existing job to enable libssh. (CMake's generic
+  auto-detection doesn't seem to work here.):
+  ```
+  CMake Warning at CMakeLists.txt:908 (find_package):
+    Could not find a package configuration file provided by "libssh" with any
+    of the following names:
 
-  Enable this feature for Windows builds, where the difference between the
-  two passes was the use of `__declspec(dllexport)` attribute for exported
-  API functions for the shared builds. This patch replaces this method
-  with the use of `libcurl.def` at DLL link time.
+      libsshConfig.cmake
+      libssh-config.cmake
+  ```
+  Ref: https://github.com/curl/curl/actions/runs/8661316091/job/23750974358#ste
+  p:5:69
 
-  Also update `Makefile.mk` to use `libcurl.def` to export libcurl API
-  symbols on Windows. This simplifies (or fixes) this build method (e.g.
-  in curl-for-win, which generated a `libcurl.def` from `.h` files using
-  an elaborate set of transformations).
+  Closes #13361
 
-  `libcurl.def` has the maintenance cost of keeping the list of public
-  libcurl API symbols up-to-date. This list seldom changes, so the cost
-  is low.
+- lib: merge `ENABLE_QUIC` C macro into `USE_HTTP3`
 
-  Closes #11546
+  Before this patch `lib/curl_setup.h` defined these two macros right
+  next to each other, then the source code used them interchangeably.
 
-- cmake: detect `SSL_set0_wbio` in OpenSSL
+  After this patch, `USE_HTTP3` guards all HTTP/3 / QUIC features.
+  (Like `USE_HTTP2` does for HTTP/2.) `ENABLE_QUIC` is no longer used.
 
-  Present in OpenSSL 1.1.0 and BoringSSL.
-  Missing from LibreSSL 3.8.0.
+  This patch doesn't change the way HTTP/3 is enabled via autotools
+  or CMake. Builders who enabled HTTP/3 manually by defining both of
+  these macros via `CPPFLAGS` can now delete `-DENABLE_QUIC`.
 
-  Follow-up to f39472ea9f4f4e12cfbc0500c4580a8d52ce4a59
+  Closes #13352
 
-  While here, also fix `RAND_egd()` detection which was broken, likely all
-  along. This feature is probably broken with CMake builds and also
-  requires a sufficiently obsolete OpenSSL version, so this part of the
-  update was not tested.
+- build: prefer `USE_IPV6` macro internally (was: `ENABLE_IPV6`)
 
-  Closes #11555
+  Before this patch, two macros were used to guard IPv6 features in curl
+  sources: `ENABLE_IPV6` and `USE_IPV6`. This patch makes the source use
+  the latter for consistency with other similar switches.
 
-- cmake: fixup H2 duplicate symbols for unity builds
+  `-DENABLE_IPV6` remains accepted for compatibility as a synonym for
+  `-DUSE_IPV6`, when passed to the compiler.
 
-  Closes #11550
+  `ENABLE_IPV6` also remains the name of the CMake and `Makefile.vc`
+  options to control this feature.
 
-Pablo Busse (1 Aug 2023)
+  Closes #13349
 
-- openssl: Support async cert verify callback
+Dan Fandrich (12 Apr 2024)
 
-  - Update the OpenSSL connect state machine to handle
-    SSL_ERROR_WANT_RETRY_VERIFY.
+- DISTROS: mark rolling release distros
 
-  This allows libcurl users that are using custom certificate validation
-  to suspend processing while waiting for external I/O during certificate
-  validation.
+  These are ones that are unlikely to have back-ported curl patches.
 
-  Closes https://github.com/curl/curl/pull/11499
+  Closes #13353
 
-Jay Satiro (1 Aug 2023)
+Daniel Stenberg (12 Apr 2024)
 
-- tool_cb_wrt: fix invalid unicode for windows console
+- mbedtls: cut off trailing newlines from debug logs
 
-  - Suppress an incomplete UTF-8 sequence at the end of the buffer.
+  To avoid double newlines in the output.
 
-  - Attempt to reconstruct incomplete UTF-8 sequence from prior call(s)
-    in current call.
+  Reported-by: Gisle Vanem
+  Fixes #13321
+  Closes #13356
 
-  Prior to this change, in Windows console UTF-8 sequences split between
-  two or more calls to the write callback would cause invalid "replacement
-  characters" U+FFFD to be printed instead of the actual Unicode
-  character. This is because in Windows only UTF-16 encoded characters are
-  printed to the console, therefore we convert the UTF-8 contents to
-  UTF-16, which cannot be done with partial UTF-8 sequences.
+- RELEASE-NOTES: synced
 
-  Reported-by: Maksim Arhipov
+Stefan Eissing (12 Apr 2024)
 
-  Fixes https://github.com/curl/curl/issues/9841
-  Closes https://github.com/curl/curl/pull/10890
+- CURLINFO_REQUEST_SIZE: fixed, add tests for transfer infos reported
 
-Daniel Stenberg (1 Aug 2023)
+  - tests for 'size_request' and other stats reported, for
+    presence and consistency
 
-- sectransp: prevent CFRelease() of NULL
+  Reported-by: Jonatan Vela
+  Fixes #13269
+  Closes #13275
 
-  When SecCertificateCopyCommonName() returns NULL, the common_name
-  pointer remains set to NULL which apparently when calling CFRelease() on
-  (sometimes?) crashes.
+Viktor Szakats (11 Apr 2024)
 
-  Reported-by: Guillaume Algis
-  Fixes #9194
-  Closes #11554
+- dist: add files missing from release tarball
 
-Jay Satiro (1 Aug 2023)
+  Closes #13346
 
-- vtls: clarify "ALPN: offers" message
+- ci: parallelize more, tidy up cmake commands (distcheck, macos)
 
-  Before:
-  * ALPN: offers h2,http/1.1
+  Also enable `-DCURL_WERROR=ON` in the Linux cmake build test.
 
-  After:
-  * ALPN: curl offers h2,http/1.1
+  Closes #13343
 
-  Bug: https://curl.se/mail/lib-2023-07/0041.html
-  Reported-by: Richard W.M. Jones
-  Closes #11544
+Toon Claes (11 Apr 2024)
 
-Daniel Stenberg (1 Aug 2023)
+- docs: add CURLOPT_NOPROGRESS to CURLOPT_XFERINFOFUNCTION example
 
-- urlapi: make sure zoneid is also duplicated in curl_url_dup
+  It's important to set `CURLOPT_NOPROGRESS` to `0` if you want your
+  transfer callback function, set by `CURLOPT_XFERINFOFUNCTION`, getting
+  called. To emphasize this to the users, add this to the code example.
 
-  Add several curl_url_dup() tests to the general lib1560 test.
+  Closes #13348
 
-  Reported-by: Rutger Broekhoff
-  Bug: https://curl.se/mail/lib-2023-07/0047.html
-  Closes #11549
+RainRat (11 Apr 2024)
 
-Sergey (1 Aug 2023)
+- misc: fix typos
 
-- urlapi: fix heap buffer overflow
+  Closes #13344
 
-  `u->path = Curl_memdup(path, pathlen + 1);` accesses bytes after the null-ter
-  minator.
+Colin Leroy-Mira (11 Apr 2024)
 
-  ```
-  ==2676==ERROR: AddressSanitizer: heap-buffer-overflow on address 0x04d48c75 a
-  t pc 0x0112708a bp 0x006fb7e0 sp 0x006fb3c4
-  READ of size 78 at 0x04d48c75 thread T0
-      #0 0x1127089 in __asan_wrap_memcpy D:\a\_work\1\s\src\vctools\asan\llvm\c
-  ompiler-rt\lib\sanitizer_common\sanitizer_common_interceptors.inc:840
-      #1 0x1891a0e in Curl_memdup C:\actions-runner\_work\client\client\third_p
-  arty\curl\lib\strdup.c:97
-      #2 0x18db4b0 in parseurl C:\actions-runner\_work\client\client\third_part
-  y\curl\lib\urlapi.c:1297
-      #3 0x18db819 in parseurl_and_replace C:\actions-runner\_work\client\clien
-  t\third_party\curl\lib\urlapi.c:1342
-      #4 0x18d6e39 in curl_url_set C:\actions-runner\_work\client\client\third_
-  party\curl\lib\urlapi.c:1790
-      #5 0x1877d3e in parseurlandfillconn C:\actions-runner\_work\client\client
-  \third_party\curl\lib\url.c:1768
-      #6 0x1871acf in create_conn C:\actions-runner\_work\client\client\third_p
-  arty\curl\lib\url.c:3403
-      #7 0x186d8dc in Curl_connect C:\actions-runner\_work\client\client\third_
-  party\curl\lib\url.c:3888
-      #8 0x1856b78 in multi_runsingle C:\actions-runner\_work\client\client\thi
-  rd_party\curl\lib\multi.c:1982
-      #9 0x18531e3 in curl_multi_perform C:\actions-runner\_work\client\client\
-  third_party\curl\lib\multi.c:2756
-  ```
+- file: add support for getting basic directory listings
 
-  Closes #11560
+  Not supported on Windows (yet)
 
-Daniel Stenberg (31 Jul 2023)
+  Closes #13137
 
-- curl: make %output{} in -w specify a file to write to
+Viktor Szakats (11 Apr 2024)
 
-  It can be used multiple times. Use %output{>>name} to append.
+- ci: add curl-for-win builds: Linux MUSL, macOS, Windows
 
-  Add docs. Test 990 and 991 verify.
+  Linux MUSL (llvm/clang), macOS Apple clang, Windows (llvm/clang).
 
-  Idea: #11400
-  Suggested-by: ed0d2b2ce19451f2
-  Closes #11416
+  Configured with HTTP/2 and HTTP/3 and other dependencies (the default
+  curl-for-win) for a comprehensive build test.
 
-- RELEASE-NOTES: synced
+  ```
+  curl 8.8.0-DEV (x86_64-unknown-linux-musl) libcurl/8.8.0-DEV LibreSSL/3.9.1 z
+  lib/1.3.1 brotli/1.1.0 zstd/1.5.6 libpsl/0.21.5 libssh2/1.11.0 nghttp2/1.61.0
+   ngtcp2/1.4.0 nghttp3/1.2.0
+  Protocols: dict file ftp ftps gopher gophers http https imap imaps ipfs ipns 
+  mqtt pop3 pop3s rtsp scp sftp smb smbs smtp smtps telnet tftp ws wss
+  Features: alt-svc AsynchDNS brotli HSTS HTTP2 HTTP3 HTTPS-proxy IPv6 Largefil
+  e libz NTLM PSL SSL threadsafe UnixSockets zstd
+
+  curl 8.8.0-DEV (x86_64-apple-darwin) libcurl/8.8.0-DEV LibreSSL/3.9.1 zlib/1.
+  3.1 brotli/1.1.0 zstd/1.5.6 libpsl/0.21.5 libssh2/1.11.0 nghttp2/1.61.0 ngtcp
+  2/1.4.0 nghttp3/1.2.0
+  Protocols: dict file ftp ftps gopher gophers http https imap imaps ipfs ipns 
+  ldap ldaps mqtt pop3 pop3s rtsp scp sftp smb smbs smtp smtps telnet tftp ws w
+  ss
+  Features: alt-svc AsynchDNS brotli HSTS HTTP2 HTTP3 HTTPS-proxy IPv6 Largefil
+  e libz NTLM PSL SSL threadsafe UnixSockets zstd
+
+  curl 8.8.0-DEV (x86_64-w64-mingw32) libcurl/8.8.0-DEV LibreSSL/3.9.1 zlib/1.3
+  .1 brotli/1.1.0 zstd/1.5.6 WinIDN libpsl/0.21.5 libssh2/1.11.0 nghttp2/1.61.0
+   ngtcp2/1.4.0 nghttp3/1.2.0
+  Protocols: dict file ftp ftps gopher gophers http https imap imaps ipfs ipns 
+  ldap ldaps mqtt pop3 pop3s rtsp scp sftp smb smbs smtp smtps telnet tftp ws w
+  ss
+  Features: alt-svc AsynchDNS brotli HSTS HTTP2 HTTP3 HTTPS-proxy IDN IPv6 Kerb
+  eros Largefile libz NTLM PSL SPNEGO SSL SSPI threadsafe UnixSockets zstd
+  ```
 
-- tool: add "variable" support
+  Limited to x64, because for build testing the additional CPUs don't add
+  much value compared to the extra build time. They can be enabled easily
+  if deemed useful.
 
-  Add support for command line variables. Set variables with --variable
-  name=content or --variable name@file (where "file" can be stdin if set
-  to a single dash (-)).
+  To the extent of curl-for-win configuration options, it's trivial to add
+  further build combinations.
 
-  Variable content is expanded in option parameters using "{{name}}"
-  (without the quotes) if the option name is prefixed with
-  "--expand-". This gets the contents of the variable "name" inserted, or
-  a blank if the name does not exist as a variable. Insert "{{" verbatim
-  in the string by prefixing it with a backslash, like "\\{{".
+  Closes #13335
 
-  Import an environment variable with --variable %name. It makes curl exit
-  with an error if the environment variable is not set. It can also rather
-  get a default value if the variable does not exist, using =content or
-  @file like shown above.
+- OS400: fix shellcheck warnings in scripts
 
-  Example: get the USER environment variable into the URL:
+  - use `$()` instead of backticks, and re-arrange double-quotes inside.
+  - add missing `|| exit 1` to `cd` calls. (could be dropped by using `set -eu`
+  .)
+  - add `-n` to a few `if`s.
+  - shorten redirections by using `{} >` (as shellcheck recommended).
+  - silence warnings where variables were detected as unused (SC2034).
+  - a couple misc updates to silence warnings.
+  - switch to bash shebang for `-ot` feature.
+  - split two lines to unbreak syntax highlighting in my editor. (`$(expr \`, `
+  $(dirname \`)
 
-   --variable %USER
-   --expand-url = "https://example.com/api/{{USER}}/method"
+  Also enable CI checks for OS/400 shell scripts.
 
-  When expanding variables, curl supports a set of functions that can make
-  the variable contents more convenient to use. It can trim leading and
-  trailing white space with "trim", output the contents as a JSON quoted
-  string with "json", URL encode it with "url" and base 64 encode it with
-  "b64". To apply functions to a variable expansion, add them colon
-  separated to the right side of the variable. They are then performed in
-  a left to right order.
+  Ref: #13307
+  Closes #13309
 
-  Example: get the contents of a file called $HOME/.secret into a variable
-  called "fix". Make sure that the content is trimmed and percent-encoded
-  sent as POST data:
+Stefan Eissing (11 Apr 2024)
 
-    --variable %HOME=/home/default
-    --expand-variable fix@{{HOME}}/.secret
-    --expand-data "{{fix:trim:url}}"
-    https://example.com/
+- lib: add Curl_xfer_write_resp_hd
 
-  Documented. Many new test cases.
+  Add method in protocol handlers to allow writing of a single,
+  0-terminated header line. Avoids parsing and copying these lines.
 
-  Co-brainstormed-by: Emanuele Torre
-  Assisted-by: Jat Satiro
-  Closes #11346
+  Closes #13165
 
-- KNOWN_BUGS: cygwin: make install installs curl-config.1 twice
+- llist: add Curl_llist_append()
 
-  Closes #8839
+  - use for better readability in all places where the "insert_next"
+    actually performs an append to the list
+  - add some tests in unit1300
 
-- KNOWN_BUGS: build for iOS simulator on macOS 13.2 with Xcode 14
+  Closes #13336
 
-  Closes #11215
+- gnutls: lazy init the trust settings
 
-- KNOWN_BUGS: cmake outputs: no version information available
+  - delay loading of trust anchors and CRLs after the ClientHello
+    has been sent off
+  - add tracing to IO operations
+  - on IO errors, return the CURLcode of the underlying filter
 
-  Closes #11158
+  Closes #13339
 
-- KNOWN_BUGS: APOP authentication fails on POP3
+Marcel Raad (10 Apr 2024)
 
-  Closes #10073
+- http_negotiate: fix `CURL_DISABLE_PROXY` build
 
-- KNOWN_BUGS: hyper is slow
+  `proxyuserpwd` was removed from `dynamically_allocated_data` in commit
+  f46385d36df.
 
-  Closes #11203
+  Closes https://github.com/curl/curl/pull/13334
 
-Patrick Monnerat (31 Jul 2023)
+Viktor Szakats (10 Apr 2024)
 
-- configure, cmake, lib: more form api deprecation
+- quic: fixup duplicate static function name (for cmake unity)
 
-  Introduce a --enable-form-api configure option to control its inclusion
-  in builds. The condition name defined for it is CURL_DISABLE_FORM_API.
+  Visible in daily curl-for-win builds:
+  https://github.com/curl/curl-for-win/actions/runs/8621925870
 
-  Form api code is dependent of MIME: configure and CMake handle this
-  dependency automatically: CMake by making it a dependent option
-  explicitly, configure by inheriting the MIME value by default and
-  rejecting explicit incompatible values.
+  ```
+  lib/vquic/curl_ngtcp2.c:1916:12: error: redefinition of 'ossl_new_session_cb'
+  static int ossl_new_session_cb(SSL *ssl, SSL_SESSION *ssl_sessionid)
+             ^
+  lib/vtls/openssl.c:2978:12: note: previous definition is here
+  static int ossl_new_session_cb(SSL *ssl, SSL_SESSION *ssl_sessionid)
+             ^
+  ```
+  https://github.com/curl/curl-for-win/actions/runs/8621925870/job/23631885439#
+  step:3:6965
 
-  "form-api" is now a new hidden test feature.
+  Follow-up to 3210101088dfa3d6a125d213226b092f2f866722 #13172
+  Closes #13332
 
-  Update libcurl modules to respect this option and adjust tests
-  accordingly.
+- appveyor: make VS2010 job build-only, enable Schannel, fix compiler warnings
 
-  Closes #9621
+  Tests were consistently flaky for a while.
 
-Daniel Stenberg (31 Jul 2023)
+  Also fix compiler warnings in `CertOpenStore()` calls for old MSVC compilers:
+  ```
+  C:/projects/curl/lib/vtls/schannel.c(688):
+    warning C4306: 'type cast' : conversion from 'int' to 'LPCSTR' of greater s
+  ize
+  C:/projects/curl/lib/vtls/schannel_verify.c(642):
+    warning C4306: 'type cast' : conversion from 'int' to 'LPCSTR' of greater s
+  ize
+  ```
+  Ref: https://ci.appveyor.com/project/curlorg/curl/builds/49580310/job/ywu2y44
+  kymgc0nif#L106
 
-- mailmap: add Derzsi Dániel
+  Closes #13330
 
-Derzsi Dániel (31 Jul 2023)
+Daniel Stenberg (10 Apr 2024)
 
-- wolfssl: support loading system CA certificates
+- projects: drop MSVC project files for recent versions
 
-  Closes #11452
+  We encourage users to generate visual studio project files using CMake.
 
-Viktor Szakats (30 Jul 2023)
+  We keep project files in git for ancient visual studio versions that
+  cmake cannot generate files for, but we no longer ship the project files
+  in the tarballs.
 
-- nss: delete more NSS references
+  appveyor: switch VisualStudioSolution job to VC12 (Visual Studio 2013)
 
-  Fix the distcheck CI failure and delete more NSS references.
+  Co-Authored-by: Viktor Szakats
+  Co-Authored-by: Jay Satiro
 
-  Follow-up to 7c8bae0d9c9b2dfeeb008b9a316117d7b9675175
+  Closes #13311
 
-  Reviewed-by: Marcel Raad
-  Reviewed-by: Daniel Stenberg
-  Closes #11548
+Viktor Szakats (9 Apr 2024)
 
-Daniel Stenberg (29 Jul 2023)
+- cmake: use namespaced custom target names
 
-- nss: remove support for this TLS library
+  Rename custom target to namespaced (unique) names to avoid colliding
+  with 3rd-party projects (e.g. libzip) built together with curl.
 
-  Closes #11459
+  Reported-by: hammlee96 on github
+  Fixes #13324
+  Closes #13326
 
-Ryan Schmidt (29 Jul 2023)
+- appveyor: re-enable OpenSSL 3, bump to 3.2.1
 
-- macOS: fix target detection more
+  Ref: b62454a875d70f93ab5347c050903596feb45a23 #13266
+  Closes #13329
 
-  Now SCDynamicStoreCopyProxies is called (and the required frameworks are
-  linked in) on all versions of macOS and only on macOS. Fixes crash due
-  to undefined symbol when built with the macOS 10.11 SDK or earlier.
+Stefan Eissing (9 Apr 2024)
 
-  CURL_OSX_CALL_COPYPROXIES is renamed to CURL_MACOS_CALL_COPYPROXIES and
-  is now only defined when SCDynamicStoreCopyProxies will actually be
-  called. Previously, it was defined when ENABLE_IPV6 was not defined but
-  SCDynamicStoreCopyProxies is not called in that case.
+- CI: upgrade openssl version to 3.3.0 for openssl-quic
 
-  TARGET_OS_OSX is only defined in the macOS 10.12 SDK and later and only
-  when dynamic targets are enabled. TARGET_OS_MAC is always defined but
-  means any Mac OS or derivative including macOS, iOS, tvOS, and watchOS.
-  TARGET_OS_IPHONE means any Darwin OS other than macOS.
+  Closes #13328
 
-  Follow-up to c73b2f82
+Daniel Stenberg (9 Apr 2024)
 
-  Fixes #11502
-  Closes #11516
+- RELEASE-NOTES: synced
 
-Daniel Stenberg (29 Jul 2023)
+  Bump to 8.8.0-DEV
 
-- tool_operate: allow SSL_CERT_FILE and SSL_CERT_DIR
+- curl_multi_waitfds.md: add protocol mention
 
-  ... used at once.
+  Follow-up to 02beac6bb6b
 
-  Reported-by: Gabriel Corona
-  Fixes #11325
-  Closes #11531
+Dmitry Karpov (9 Apr 2024)
 
-Thomas M. DuBuisson (29 Jul 2023)
+- lib: add curl_multi_waitfds
 
-- CI: remove Lift's configuration
+  New function call, similar to curl_multi_fdset()
 
-  The Lift tool is being retired. Their site reads:
+  Closes #13135
 
-  "Sonatype Lift will be retiring on Sep 12, 2023, with its analysis
-  stopping on Aug 12, 2023."
+Viktor Szakats (9 Apr 2024)
 
-  Closes #11541
+- dist: verify tarball reproducibility in CI
 
-Nathan Moinvaziri (29 Jul 2023)
+  Closes #13327
 
-- Revert "schannel: reverse the order of certinfo insertions"
+Stefan Eissing (9 Apr 2024)
 
-  This reverts commit 8986df802db9b5338d9d50a54232ebae4dbcf6dd.
+- tests: stabilitze test_02_23*
 
-  Windows does not guarantee a particular certificate ordering, even
-  though TLS may have its own ordering/relationship guarantees. Recent
-  versions of Windows 11 reversed the ordering of ceritifcates returned by
-  CertEnumCertificatesInStore, therefore this commit no longer works as
-  initially intended. libcurl makes no guarantees about certificate
-  ordering if the operating system can't.
+  - h2-download now always opens the output file on first write callback
+    invocation, if it will pause the transfer or not.
+  - Checks on output files then does not depend on the amount of data curl
+    has collected for the first write.
 
-  Ref: https://github.com/curl/curl/issues/9706
+  Closes #13323
 
-  Closes https://github.com/curl/curl/pull/11536
+- tls: fix compile issues on old-linux CI
 
-wangzhikun (29 Jul 2023)
+  Follow-up to 3210101088dfa
+  Closes #13325
 
-- winbuild: improve check for static zlib
+Viktor Szakats (9 Apr 2024)
 
-  - Check for zlib static library name zlibstatic.lib.
+- dist: add reproducible dir entries to tarballs
 
-  zlib's static library has a different name depending on how it was
-  built. zlibstatic.lib is output by cmake. zlibstat.lib is output by
-  their pre-generated Visual Studio project files (in the contrib
-  directory) and defines ZLIB_WINAPI (ie it's meant to use stdcall
-  instead of cdecl if you end up exporting the zlib functions).
+  In the initial implementation of reproducible tarballs, they were
+  missing directory entries, while .zip archives had them. It meant
+  that on extracting the tarball, on-disk directory entries got the
+  current timestamp.
 
-  Prior to this change the makefile only checked for the latter.
+  This patch fixes this by including directory entries in the tarball,
+  with reproducible timestamps. It also moves sorting inside tar,
+  to ensure reproducible directory entry timestamps on extract
+  (without the need of `--delay-directory-restore` option, when
+  extracting with GNU tar. BSD tar got that right by default.)
 
-  Closes https://github.com/curl/curl/pull/11521
+  GNU tar 1.28 (2014-07-28) introduced `--sort=`.
 
-Daniel Stenberg (29 Jul 2023)
+  Ref: https://github.com/curl/curl/pull/13299#discussion_r1555957350
+  Follow-up to 860cd5fc2dc8e165fadd2c19a9b7c73b3ae5069d #13299
+  Closes #13322
 
-- configure: use the pkg-config --libs-only-l flag for libssh2
+Stefan Eissing (9 Apr 2024)
 
-  ... instead of --libs, as that one also returns -L flags.
+- tls: use shared init code for TCP+QUIC
 
-  Reported-by: Wilhelm von Thiele
-  Fixes #11538
-  Closes #11539
+  Closes #13172
 
-Viktor Szakats (29 Jul 2023)
+Daniel Stenberg (9 Apr 2024)
 
-- cmake: support building static and shared libcurl in one go
+- .mailmap: update Gisle's preferred email
 
-  This patch adds the ability to build a static and shared libcurl library
-  in a single build session. It also adds an option to select which one to
-  use when building the curl executable.
+Jan Macku (9 Apr 2024)
 
-  New build options:
-  - `BUILD_STATIC_LIBS`. Default: `OFF`.
-    Enabled automatically if `BUILD_SHARED_LIBS` is `OFF`.
-  - `BUILD_STATIC_CURL`. Default: `OFF`.
-    Requires `BUILD_STATIC_LIBS` enabled.
-    Enabled automatically if building static libcurl only.
-  - `STATIC_LIB_SUFFIX`. Default: empty.
-  - `IMPORT_LIB_SUFFIX`. Default: `_imp` if implib filename would collide
-    with static lib name (typically with MSVC) in Windows builds.
-    Otherwise empty.
+- doc: pytest `--repeat` -> `--count`
 
-  Also:
+  Pytest doesn't have a `--repeat` option, but it does have a `--count`
+  option.
 
-  - Stop setting the `CURL_STATICLIB` macro via `curl_config.h`, and pass
-    it directly to the compiler. This also allows to delete a condition
-    from `tests/server/CMakeLists.txt`.
+  ```
+  --count=COUNT         Number of times to repeat each test
+  ```
 
-  - Complete a TODO by following the logic used in autotools (also for
-    `LIBCURL_NO_SHARED`), and set `-DCURL_STATICLIB` in `Cflags:` of
-    `libcurl.pc` for _static-only_ curl builds.
+  Closes #13218
 
-  - Convert an existing CI test to build both shared and static libcurl.
+Daniel Stenberg (9 Apr 2024)
 
-  Closes #11505
+- src/Makefile.am: access curl.txt using a relative path, not abs
 
-Stefan Eissing (28 Jul 2023)
+  ... to make it work when mounted using different mount points. Like when
+  generated/used inside and outside of a docker image.
 
-- CI/awslc: add cache for build awslc library
+  Closes #13320
 
-  Closes #11535
+- build: remove MacOSX-Framework script
 
-- GHA/linux.yml: add caching
+  I don't think this is much used these days.
 
-  Closes #11532
+  Also remove the libcurl.plist file used (only) by this script
 
-Daniel Stenberg (27 Jul 2023)
+  Closes #13313
 
-- RELEASE-NOTES: synced
+- release-tools.sh: store the timestamp and release tag too
 
-  Bump working version to 8.3.0
+  When maketgz invokes this script to generate the docs/RELEASE-TOOLS.md
+  file that gets bundled in the release, it now also passes on the exact
+  timestamp and version number so that those details also get mentioned in
+  the document. They will help users reproduce an identical tarball.
 
-- url: remove infof() output for "still name resolving"
+  Closes #13319
 
-  The message does not help and might get spewed a lot during times.
+Viktor Szakats (8 Apr 2024)
 
-  Reported-by: yushicheng7788 on github
-  Fixes #11394
-  Closes #11529
+- GHA: disable permissions where missing
 
-- KNOWN_BUGS: cygwin: "WARNING: UNPROTECTED PRIVATE KEY FILE!"
+  Reviewed-by: Daniel Stenberg
+  Closes #13306
 
-  Closes #11244
+Stefan Eissing (8 Apr 2024)
 
-Stefan Eissing (27 Jul 2023)
+- CI: update component versions
 
-- CI: quiche updates
+  - ngtcp2: v1.4.0
+  - nghttp3: v1.2.0
+  - nghttp2: v1.61.0
+  - mod_h2: v2.0.27
 
-  - remove quiche from standard `linux` workflow
-  - add mod_h2 caching to quiche workflow
-  - rename quiche to quiche-linux
-  - move version definitions into env section
+  Closes #13316
 
-  Closes #11528
+Jérôme Leclercq (8 Apr 2024)
 
-- http2: disable asssertion blocking OSSFuzz testing
+- CMake: check fseeko after detecting HAVE_FILE_OFFSET_BITS
 
-  - not clear how this triggers and it blocks OSSFuzz testing other
-    things. Since we handle the case with an error return, disabling the
-    assertion for now seems the best way forward.
+  Closes #13264
 
-  Fixes #11500
-  Closes #11519
+Stefan Eissing (8 Apr 2024)
 
-- http2: fix in h2 proxy tunnel: progress in ingress on sending
+- http2: emit RST when client write fails
 
-  - depending on what is tunneled, the proxy may never get invoked for
-    receiving data explicitly. Not progressing ingress may lead to stalls
-    due to missed WINDOW_UPDATEs.
+  - When the writing of response data fails, reset the stream
+    and do not return a callback error to nghttp2. That would
+    be a fatal error for the connection and harm other requests.
+  - add test cases for various abort scenarios
 
-  CI:
-  - add a chache for building mod_h2
+  Reported-by: Konstantin Kuzov
+  Fixes #13292
+  Closes #13298
 
-  Closes #11527
+Kailun Qin (8 Apr 2024)
 
-- CI ngtcp2+quictls: use nghttpx cache as in quiche build
+- mbedtls: call mbedtls_ssl_setup() after RNG callback is set
 
-Jay Satiro (27 Jul 2023)
+  Since mbedTLS v3.6.0, the RNG check added in ssl_conf_check() will fail
+  if no RNG is provided when calling mbedtls_ssl_setup().
 
-- bearssl: don't load CA certs when peer verification is disabled
+  Therefore, mbedtls_ssl_conf_rng() needs to be called before the SSL
+  context is passed to mbedtls_ssl_setup().
 
-  We already do this for other SSL backends.
+  Ref: https://github.com/Mbed-TLS/mbedtls/commit/b422cab052b51ec84758638d6783d
+  6ba4fc60613
 
-  Bug: https://github.com/curl/curl/pull/11457#issuecomment-1644587473
-  Reported-by: kyled-dell@users.noreply.github.com
+  Signed-off-by: Kailun Qin 
+  Closes #13314
 
-  Closes https://github.com/curl/curl/pull/11497
+Daniel Stenberg (8 Apr 2024)
 
-Daniel Stenberg (26 Jul 2023)
+- NTLM_WB: drop support
 
-- easy: remove #ifdefs to make code easier on the eye
+  The feature has not worked for months and has been marked as DEPRECATED
+  for six+ months.
 
-  Closes #11525
+  Closes #13249
 
-Stefan Eissing (26 Jul 2023)
+- curl_trc: fix build error when lacking verbose messages
 
-- GHA: adding quiche workflow
+  Follow-up from 0b28ece657b2273
+  Closes #13312
 
-  - adding separate quiche workflow to also build nghttpx server for testing
+Viktor Szakats (8 Apr 2024)
 
-  Closes #11517
+- contrithanks: honor `CURLWWW` variable
 
-Version 8.2.1 (26 Jul 2023)
+  Reviewed-by: Daniel Stenberg
+  Closes #13315
 
-Daniel Stenberg (26 Jul 2023)
+- GHA: add shellcheck job and fix warnings, shell tidy-ups
 
-- RELEASE-NOTES: synced
+  Reviewed-by: Daniel Stenberg
+  Closes #13307
 
-  curl 8.2.1 release
+- dist: do not require Perl in `maketgz`
 
-- THANKS: add contributors from 8.2.1
+  Perl remains required for the tarball build process.
 
-- docs: provide more see also for cipher options
+  Follow-up to 860cd5fc2dc8e165fadd2c19a9b7c73b3ae5069d #13299
 
-  More cross references. Hide nroff errors.
+  Reviewed-by: Daniel Stenberg
+  Closes #13310
 
-  Closes #11513
+Daniel Stenberg (8 Apr 2024)
 
-- docs: mark two TLS options for TLS, not SSL
+- RELEASE-NOTES: synced
 
-  Closes #11514
+- docs/cmdline-opts: invoke managen using a relative path
 
-Brad Harder (25 Jul 2023)
+  ... no need to use an absolute path, that makes the build unncessarily
+  fail if invoked using a different mount point. managen now takes options
+  to find the input files.
 
-- curl_multi_wait.3: fix arg quoting to doc macro .BR
+  Update test1478 to provide the dir arguments to managen
 
-  Closes #11511
+  Closes #13281
 
-Daniel Stenberg (24 Jul 2023)
+- GHA: add valgrind to a wolfSSL build
 
-- RELEASE-NOTES: synced
+  Closes #13274
 
-Viktor Szakats (24 Jul 2023)
+Viktor Szakats (7 Apr 2024)
 
-- cmake: update ngtcp2 detection
+- dist: `set -eu`, fix shellcheck, make reproducible and smaller tarballs
 
-  Replace `OpenSSL` with `quictls` to follow the same change
-  in the v0.17.0 ngtcp2 release.
+  - set bash `-eu` and fix fallouts.
+  - fix shellcheck warnings.
+  - set and use `SOURCE_DATE_EPOCH` for reproducibility.
+    Authored-by: Daniel J. H.
+    Ref: #13280
+  - set `TZ=UTC` and `LC_ALL=C` for reproducibility.
+  - make file timestamps in tarball/zip reproducible.
+  - make directory timestamps in zip reproducible.
+  - make timestamps of tarballs/zip reproducible.
+  - make file order in tarball/zip reproducible.
+  - omit extra file metadata from zip for reproducibility.
+  - use maximum zip compression.
+  - use POSIX `ustar` tarball format to avoid supply chain vulnerability:
+    https://seclists.org/oss-sec/2021/q4/0
+  - make uid/gid in tarball reproducible.
+  - omit owner user/group names from tarball for reproducibility and privacy.
+  - omit current timestamp from .gz header for reproducibility.
+  - display SHA-256 hashes of produced tarballs/zip.
+  - fix whitespace.
 
-  Follow-up to e0093b4b732f6495b0fb1cd6747cbfedcdcf63ed
+  `.tar.gz` also became smaller in the process: 4,462,311 -> 4,148,249 bytes (8
+  .7.1)
 
-  Closes #11508
+  Requires GNU tar, GNU date, `sha256sum`.
 
-Stefan Eissing (24 Jul 2023)
+  Reviewed-by: Daniel Stenberg
+  Ref: #13250
+  Closes #13299
 
-- http: VLH, very large header test and fixes
+Gisle Vanem (7 Apr 2024)
 
-  - adding tests using very large passwords in auth
-  - fixes general http sending to treat h3 like h2, and
-    not like http1.1
-  - eliminate H2_HEADER max definitions and use the commmon
-    DYN_HTTP_REQUEST everywhere, different limits do not help
-  - fix http2 handling of requests denied by nghttp2 on send
-    to immediately report the refused stream
+- tests/http: fix compiler warning
 
-  Closes #11509
+  - Init result code variable to fix clang warning that it may be used
+    uninitialized.
 
-Andrei Rybak (23 Jul 2023)
+  Fixes https://github.com/curl/curl/issues/13301
+  Closes https://github.com/curl/curl/pull/13304
 
-- CONTRIBUTE: drop mention of copyright year ranges
+Stefan Eissing (6 Apr 2024)
 
-  Year ranges in copyrights were dropped in commits [1] and [2].
-  Verification of year ranges in copyrights was dropped from script
-  'scripts/copyright.pl' in commit [3].  However, the corresponding
-  passages in file 'docs/CONTRIBUTE.md' weren't updated.
+- vquic: use new curl_int64_t type
 
-  Drop mentions of copyright year ranges from 'docs/CONTRIBUTE.md'.
+  - add curl_int64_t signed 64-bit type for lib use
 
-  [1] 2bc1d775f (copyright: update all copyright lines and remove year
-      ranges, 2023-01-02)
-  [2] c46761bd8 (tests/http: remove year ranges from copyrights,
-      2023-03-14)
-  [3] 0e293bacb (copyright.pl: cease doing year verifications, 2023-01-28)
+  - define CURL_PRId64, CURL_PRIu64 format ids
 
-  Closes #11504
+  - use curl_int64_t in vquic
 
-- CONTRIBUTE: fix syntax in commit message description
+  curl_int64_t signed complements the existing curl_uint64_t unsigned.
 
-  File 'docs/CONTRIBUTE.md' includes a description of how one should write
-  commit messages in the curl project.  Different possible parts of the
-  message are enclosed in square brackets.  One exception is the section
-  describing how the curl project doesn't use "Signed-off-by" commit
-  trailers [1], which is enclosed in an opening curly brace paired with a
-  closing square bracket.
+  Note that `curl_int64_t` and `int64_t` are assignable from each other
+  but not identical. Some platforms with 64 long type defint int64_t as
+  "long long" (staring at macOS) which messes up things like pointers and
+  format identifiers.
 
-  Fix the enclosing square brackets in description of "Signed-off-by"
-  trailers in commit messages in file 'docs/CONTRIBUTE.md'.
+  Closes https://github.com/curl/curl/pull/13293
 
-  [1] See description of option '--signoff' in Git documentation:
-      https://git-scm.com/docs/git-commit
+Jay Satiro (5 Apr 2024)
 
-  Closes #11504
+- lib: use multi instead of multi_easy for the active multi
 
-Daniel Stenberg (23 Jul 2023)
+  - Use data->multi and not data->multi_easy to refer to the active multi.
 
-- src/mkhelp: strip off escape sequences
+  The easy handle's active multi is always data->multi.
 
-  At some point the nroff command stopped stripping off escape sequences,
-  so then this script needs to do the job instead.
+  This is a follow up to 757dfdf which changed curl so that an easy handle
+  used with the easy interface and then multi interface cannot have two
+  different multi handles associated with it at the same time
+  (data->multi_easy from the easy interface and data->multi from the multi
+  interface).
 
-  Reported-by: VictorVG on github
-  Fixes #11501
-  Closes #11503
+  Closes https://github.com/curl/curl/pull/12665
 
-- KNOWN_BUGS: building for old macOS fails with gcc
+Viktor Szakats (5 Apr 2024)
 
-  Closes #11441
+- tidy-up: whitespace [ci skip]
 
-Jacob Hoffman-Andrews (22 Jul 2023)
+Daniel Stenberg (5 Apr 2024)
 
-- rustls: update rustls-ffi 0.10.0
+- makefile: remove the sorting from the vc-ide action
 
-  This brings in version 0.21.0 of the upstream rustls implementation,
-  which notable includes support for IP address certificates.
+  This target generates the MSVC project files. This change removes the
+  extra sorting and instead makes the script use the order of the files as
+  listed in the variables - which are mostly sorted anyway.
 
-  Closes #10865
+  This is an attempt to make the project file generation more easily
+  reproducible.
 
-Brad Harder (22 Jul 2023)
+  Ref: #13250
+  Closes #13294
 
-- websocket: rename arguments/variables to match docs
+Gisle Vanem (5 Apr 2024)
 
-  Pedantry/semantic-alignment between functions, docs, comments with
-  respect to websocket protocol code; No functional change intended.
+- bearssl: fix compiler warnings
 
-  * "totalsize", "framesize" becomes "fragsize" (we deal in frame fragments).
+  "variables may be uninitialized when used"
 
-  * "sendflags" becomes "flags"
+  Fixes #13290
+  Closes #13297
 
-  * use canonical CURL *handle
+Daniel Stenberg (5 Apr 2024)
 
-  Closes #11493
+- DISTROS: Cygwin updates
 
-Jan Macku (21 Jul 2023)
+  Brought-by: Brian Inglis
+  Fixes #13258
+  Co-authored-by: Viktor Szakats
+  Closes #13279
 
-- bug_report: use issue forms instead of markdown template
+Stefan Eissing (5 Apr 2024)
 
-  Issue forms allow you to define web-like input forms using YAML
-  syntax. It allows you to guide the reporter to get the required
-  information.
+- lib: add trace support for client reads and writes
 
-  Signed-off-by: Jan Macku 
-  Closes #11474
+  - add `CURL_TRC_READ()` and `CURL_TRC_WRITE()`
+  - use in generic client writers and readers, as well
+    as http headers, chunking and websockets
 
-Daniel Stenberg (21 Jul 2023)
+  Closes #13223
 
-- TODO: Obey Retry-After in redirects
+Michał Antoniak (5 Apr 2024)
 
-  (remove "Set custom client ip when using haproxy protocol" which was
-  shipped in 8.2.0)
+- urldata: remove fields not used depending on used features
 
-  Mentioned-by: Yair Lenga
-  Closes #11447
+  Reduced size of dynamically_allocated_data structure.
 
-- RELEASE-NOTES: synced
+  Reduced number of stored values in enum dupstring and enum dupblob. This
+  affects the reduced array placed in the UserDefined structure.
 
-Oliver Roberts (21 Jul 2023)
+  Closes #13188
 
-- amissl: fix AmiSSL v5 detection
+Viktor Szakats (5 Apr 2024)
 
-  Due to changes in the AmiSSL SDK, the detection needed adjusting.
+- cmake: enable `-pedantic-errors` for clang when `CURL_WERROR=ON`
 
-  Closes #11477
+  clang doesn't have the issues of GCC and old CMake versions.
 
-Alois Klink (21 Jul 2023)
+  Note: This introduces asymmetry with autotools, which only enables
+  this for GCC.
 
-- unittest/makefile: remove unneeded unit1621_LDADD
+  Reviewed-by: Daniel Stenberg
+  Closes #13286
 
-  The `unit1621_LDADD` variable has the exact same value as the `LDADD`
-  flag in `Makefile.am`, except without `@LDFLAGS@ @LIBCURL_LIBS@`.
+- cmake: fix `CURL_WERROR=ON` for old CMake and use it in GHA/linux-old
 
-  This was originally added by [98e6629][], but I can't see any reason
-  why it exists, so we should remove it to clean things up.
+  - cmake: fix `-pedantic-errors` for old CMake with `CURL_WERROR=ON` set.
 
-  [98e6629]: https://github.com/curl/curl/commit/98e6629154044e4ab1ee7cff8351c7
-  ebcb131e88
+    `-pedantic-errors` option throws a warning with GCC (all versions) and
+    makes `check_symbol_exists()` fail in CMake versions older than
+    v3.23.0 (2022-03-29), when CMake introduced a workaround:
 
-  Closes #11494
+    https://gitlab.kitware.com/cmake/cmake/-/issues/13208
+    https://gitlab.kitware.com/cmake/cmake/-/commit/eeb45401163d831b8c841ef6eba
+  81466b4067b68
+    https://gitlab.kitware.com/cmake/cmake/-/commit/1ab7c3cd28b27ca162c4559e102
+  6e5cad1898ade
 
-- unittest/makefile: remove unneeded unit1394_LDADD
+    Follow-up to 3829759bd042c03225ae862062560f568ba1a231 #12489
 
-  These custom `unit1394_LDADD` and similar automake overrides are no
-  longer neded. They were originally added by added by [8dac7be][] for
-  metalink support, but are no longer after [265b14d][] removed metalink.
+  - set `CURL_WERROR=ON` for the `linux-old` job in CI.
 
-  [8dac7be]: https://github.com/curl/curl/commit/8dac7be438512a8725d3c71e9139bd
-  fdcac1ed8c
-  [265b14d]: https://github.com/curl/curl/commit/265b14d6b37c4298bd5556fabcbc37
-  d36f911693
+  Closes #13282
 
-  Closes #11494
+- lib: use `#error` instead of invalid syntax in `curl_setup_once.h`
 
-- cmake: add `libcurlu`/`libcurltool` for unit tests
+  Reviewed-by: Daniel Stenberg
+  Closes #13287
 
-  Add a `libcurlu`/`libcurltool` static library that is compiled only for
-  unit tests. We use `EXCLUDE_FROM_ALL` to make sure that they're not
-  built by default, they're only built if unit tests are built.
+Daniel Stenberg (5 Apr 2024)
 
-  These libraries allow us to compile every unit test with CMake.
+- GHA: on macOS remove $HOME/.curlrc
 
-  Closes #11446
+  A recent image upgrade added a $HOME/.curlrc by default using --ipv4.
 
-Daniel Stenberg (21 Jul 2023)
+  Ref: https://github.com/actions/runner-images/pull/9586
+  Fixes #13284
+  Closes #13285
 
-- test979: test -u with redirect to (the same) absolute host
+Viktor Szakats (4 Apr 2024)
 
-  Verifies #11492
+- cmake: fixup `DEPENDS` filename
 
-- transfer: do not clear the credentials on redirect to absolute URL
+  Fixing:
+  ```
+  make[2]: Circular docs/curl-config.1 <- docs/curl-config.1 dependency dropped
+  .
+  make[2]: Circular docs/mk-ca-bundle.1 <- docs/mk-ca-bundle.1 dependency dropp
+  ed.
+  ```
+  Ref: https://github.com/curl/curl/actions/runs/8559617487/job/23456740844?pr=
+  13282#step:6:18
 
-  Makes test 979 work. Regression shipped in 8.2.0 from commit
-  dd4d1a26959f63a2c
+  Follow-up to 5023ffad2c27d4b916ddb91800f99ecc5d3aad07 #13197
+  Closes #13283
 
-  Fixes #11486
-  Reported-by: Cloudogu Siebels
-  Closes #11492
+- GHA: enable unity mode for cmake jobs + tidy-ups
 
-Jon Rumsey (20 Jul 2023)
+  Unity mode is not supported by CMake v3.7.2 used in linux-old, but
+  enable it anyway for consistency and to kick in automatically once
+  migrating to a newer old Linux in the future.
 
-- os400: correct EXPECTED_STRING_LASTZEROTERMINATED
+  Also:
+  - replace `CMAKE_COMPILE_WARNING_AS_ERROR` with `CURL_WERROR`.
+  - delete default build option `PICKY_COMPILER=ON`.
 
-  Correct EXPECTED_STRING_LASTZEROTERMINATED to account for
-  CURLOPT_HAPROXY_CLIENT_IP which requires EBCDIC to ASCII conversion when
-  passed into curl_easy_setopt().
+  Closes #13277
 
-  Closes #11476
+Dan Fandrich (4 Apr 2024)
 
-Oliver Roberts (20 Jul 2023)
+- CI: Add CI build on Debian stretch to test old support
 
-- amissl: add missing signal.h include
+  This version still has ELTS support and contains some old versions of
+  key components like cmake to help prevent us from breaking that support.
 
-  In some environments, signal.h is already included, but not in others
-  which cause compilation to fail, so explictly include it.
+  Closes #13029
 
-  Closes #11478
+Stefan Eissing (4 Apr 2024)
 
-- amigaos: fix sys/mbuf.h m_len macro clash
+- request: paused upload on completed download, assess connection
 
-  The updated Curl_http_req_make and Curl_http_req_make2 functions spawned
-  a parameter called m_len. The AmigaOS networking headers, derived from
-  NetBSD, contain "#define m_len m_hdr.mh_len" which clashes with
-  this. Since we do not actually use mbuf, force the include file to be
-  ignored, removing the clash.
+  A transfer with a completed download that is still uploading needs to
+  check the connection state when it is PAUSEd, since connection
+  close/errors would otherwise go unnoticed.
 
-  Closes #11479
+  Reported-by: Sergey Bronnikov
+  Fixes #13260
+  Closes #13271
 
-Daniel Stenberg (20 Jul 2023)
+Daniel Stenberg (4 Apr 2024)
 
-- socks: print ipv6 address within brackets
+- url: do not URL decode proxy crendentials
 
-  Fixes #11483
-  Closes #11484
+  The two options CURLOPT_PROXYUSERNAME and CURLOPT_PROXYPASSWORD set the
+  actual names as-is, not URL encoded.
 
-Christian Schmitz (20 Jul 2023)
+  Modified test 503 to use percent-encoded strings in the credential
+  strings that should be passed on as-is.
 
-- libcurl-errors.3: add CURLUE_OK
+  Reported-by: Sergey Ogryzkov
+  Fixes #13265
+  Closes #13270
 
-  Closes #11488
+Viktor Szakats (4 Apr 2024)
 
-Oliver Roberts (20 Jul 2023)
+- appveyor: enable cmake unity mode by default
 
-- cfilters: rename close/connect functions to avoid clashes
+  Leave one non-unity cmake job. This makes the jobs finish slightly
+  quicker, while giving more coverage for unity issues.
 
-  Rename `close` and `connect` in `struct Curl_cftype` for
-  consistency and to avoid clashes with macros of the same name
-  (the standard AmigaOS networking connect() function is implemented
-  via a macro).
+  Before:
+  https://ci.appveyor.com/project/curlorg/curl/builds/49496977
+  https://ci.appveyor.com/project/curlorg/curl/builds/49500372
+  After:
+  https://ci.appveyor.com/project/curlorg/curl/builds/49500338
 
-  Closes #11491
+  Also fixup unrelated whitespace.
 
-Stefan Eissing (20 Jul 2023)
+  Reviewed-by: Daniel Stenberg
+  Closes #13217
 
-- http2: fix regression on upload EOF handling
+Daniel Stenberg (4 Apr 2024)
 
-  - a regression introduced by c9ec85121110d7cbbbed2990024222c8f5b8afe5
-    where optimization of small POST bodies leads to a new code path
-    for such uploads that did not trigger the "done sending" event
-  - add triggering this event for early "upload_done" situations
+- RELEASE-NOTES: synced
 
-  Fixes #11485
-  Closes #11487
-  Reported-by: Aleksander Mazur
+Viktor Szakats (4 Apr 2024)
 
-Daniel Stenberg (19 Jul 2023)
+- cmake: speed up libcurl doc building again
 
-- configure: check for nghttp2_session_get_stream_local_window_size
+  This time limit the number of files per command to avoid exceeding
+  limitations of certain OS/shell envs.
 
-  The http2 code uses it now. Introduced in nghttp2 1.15.0 (Sep 2016)
+  Such known env is Windows with the `cmd.exe` shell, which features an
+  8K command-line length limit to this day.
 
-  Fixes #11470
-  Reported-by: Paul Howarth
-  Closes #11473
+  Allowlisting `UNIX` to have no limit and using a limit of 200 for other
+  envs to be safe. If there is a way to detect `cmd.exe` and/or we know
+  which precise envs are sensitive to this, we can tweak these conditions
+  further.
 
-Stefan Eissing (19 Jul 2023)
+  Even with the low limit, this patch reduces external commands by 200x,
+  making builds much faster.
 
-- quiche: fix segfault and other things
+  Ref: #12762 2620aa930bc73af1e4c70b10e3125b957b96ecfb (initial)
+  Ref: #13047 f03c85635f35269f1f45b983bf216624f541760a (revert)
 
-  - refs #11449 where a segfault is reported when IP Eyeballing did
-    not immediately connect but made several attempts
-  - The transfer initiating the eyeballing was initialized  too early,
-    leadding to references to the filter instance that was then
-    replaced in the subsequent eyeball attempts. That led to a use
-    after free in the buffer handling for the transfer
-  - transfers are initiated now more lazy (like in the ngtcp2 filter),
-    when the stream is actually opened
-  - suppress reporting on quiche event errors for "other" transfers
-    than the current one to not fail a transfer due to faults in
-    another one.
-  - revert recent return value handling for quiche_h3_recv_body()
-    to not indicate an error but an EAGAIN situation. We wish quiche
-    would document what functions return.
+  Reviewed-by: Daniel Stenberg
+  Closes #13207
 
-  Fixes #11449
-  Closes #11469
-  Reported-by: ウさん
+- cmake: tidy-up to use `WORKING_DIRECTORY`
 
-Daniel Stenberg (19 Jul 2023)
+  Reviewed-by: Daniel Stenberg
+  Closes #13206
 
-- hostip: return IPv6 first for localhost resolves
+- cmake: generate misc manpages and install `mk-ca-bundle.pl`
 
-  Fixes #11465
-  Reported-by: Chilledheart on github
-  Closes #11466
+  - install `mk-ca-bundle.pl` like autotools does.
 
-Harry Sintonen (19 Jul 2023)
+  - generate and install `mk-ca-bundle.1` and `curl-config.1` like
+    autotools. This fixes tests 1140 and 1173.
 
-- tool: fix tool_seek_cb build when SIZEOF_CURL_OFF_T > SIZEOF_OFF_T
+    Reported-by: Dan Fandrich
+    Fixes #13194
 
-  - a variable was renamed, and some use of it wasn't. this fixes the
-    build.
+  - add option `BUILD_MISC_DOCS` to control building the above two
+    manpages. Enabled by default.
 
-  Closes #11468
+  - appveyor: stop disabling tests 1140 and 1173.
 
-Stefan Eissing (19 Jul 2023)
+  Reviewed-by: Daniel Stenberg
+  Closes #13197
 
-- quiche: fix lookup of transfer at multi
+Fabian Keil (4 Apr 2024)
 
-  - refs #11449 where weirdness in quiche multi connection tranfers was
-    observed
-  - fixes lookup of transfer for a quiche event to take the connection
-    into account
-  - formerly, a transfer with the same stream_id, but on another connection
-    could be found
+- wolfssl: plug memory leak in wolfssl_connect_step2()
 
-  Closes #11462
+  Fixes:
 
-Daniel Stenberg (19 Jul 2023)
+       test 2034...[simple HTTPS GET with DER public key pinning]
+       ==61829== 22,610 (3,744 direct, 18,866 indirect) bytes in 1 blocks are d
+  efinitely lost in loss record 51 of 54
+       ==61829==    at 0x484BB74: malloc (vg_replace_malloc.c:446)
+       ==61829==    by 0x4B53A80: wolfSSL_Malloc (memory.c:344)
+       ==61829==    by 0x4C1C8E1: wolfSSL_X509_new (x509.c:5326)
+       ==61829==    by 0x4C3977D: d2i_X509orX509REQ (x509.c:3628)
+       ==61829==    by 0x4C1D1F4: wolfSSL_X509_d2i (x509.c:3664)
+       ==61829==    by 0x4C1C37B: wolfSSL_X509_dup (x509.c:13425)
+       ==61829==    by 0x4C197DB: wolfSSL_get_peer_certificate (ssl.c:18765)
+       ==61829==    by 0x33297C: wolfssl_connect_step2 (wolfssl.c:875)
+       ==61829==    by 0x331669: wolfssl_connect_common (wolfssl.c:1287)
+       ==61829==    by 0x3303E9: wolfssl_connect_nonblocking (wolfssl.c:1319)
+       ==61829==    by 0x32FE89: ssl_connect_nonblocking (vtls.c:510)
+       ==61829==    by 0x32DBE5: ssl_cf_connect (vtls.c:1679)
+       ==61829==    by 0x27ABD7: Curl_conn_cf_connect (cfilters.c:307)
+       ==61829==    by 0x27D9CF: cf_setup_connect (connect.c:1199)
+       ==61829==    by 0x27ABD7: Curl_conn_cf_connect (cfilters.c:307)
+       ==61829==    by 0x283CEA: cf_hc_baller_connect (cf-https-connect.c:135)
 
-- RELEASE-NOTES: synced
+  Closes #13272
 
-  bump to 8.2.1
+Viktor Szakats (3 Apr 2024)
 
-John Haugabook (19 Jul 2023)
+- appveyor: OpenSSL 3 no longer found by CMake, revert to 1.1.1
 
-- ciphers.d: put URL in first column
+  OpenSSL moved directories, and bumped versions in AppVeyor CI.
 
-  This makes the URL turn into a link properly when "webified".
+  Downgrading is not an ideal solution, but however trivial the solution
+  may be, I failed to come with anything that made CMake recognize either
+  OpenSSL 3.1 or 3.2.
 
-  Fixes https://github.com/curl/curl-www/issues/270
-  Closes #11464
+  Possibly caused by:
+  https://github.com/appveyor/build-images/commit/702e8cdca01f28f6a40687783f493
+  c786cebbe2c
+  https://github.com/appveyor/build-images/pull/149
 
-Version 8.2.0 (19 Jul 2023)
+  Closes #13266
 
-Daniel Stenberg (19 Jul 2023)
+hongfei.li (3 Apr 2024)
 
-- RELEASE-NOTES: synced
+- winbuild: use $(RC) correctly
 
-  8.2.0 release
+  Cloes #13267
 
-- THANKS-filter: strip out "GitHub"
+Daniel Stenberg (3 Apr 2024)
 
-- THANKS: add contributors from 8.2.0
+- dist: remove the curl-config.1 from the tarball
 
-- RELEASE-PROCEDURE.md: adjust the release dates
+  The markdown file is already there and the .1 file gets generated in the
+  build.
 
-Stefan Eissing (17 Jul 2023)
+  Ref: #13250
+  Closes #13268
 
-- quiche: fix defects found in latest coverity report
+- curl_global_trace.md: shorten the description
 
-  Closes #11455
+  Closes #13263
 
-Daniel Stenberg (17 Jul 2023)
+- test1901: verify chunked POST from callback with CURLOPT_POSTFIELDSIZE set
 
-- quiche: avoid NULL deref in debug logging
+  Follow-up to 721941aadf4ad
 
-  Coverity reported "Dereference after null check"
+  Ref: #13257
+  Closes #13262
 
-  If stream is NULL and the function exits, the logging must not deref it.
+Stefan Eissing (2 Apr 2024)
 
-  Closes #11454
+- http: with chunked POST forced, disable length check on read callback
 
-Stefan Eissing (17 Jul 2023)
+  - when an application forces HTTP/1.1 chunked transfer encoding
+    by setting the corresponding header and instructs curl to use
+    the CURLOPT_READFUNCTION, disregard any POST length information.
+  - this establishes backward compatibility with previous curl versions
 
-- http2: treat initial SETTINGS as a WINDOW_UPDATE
+  Applications are encouraged to not force "chunked", but rather
+  set length information for a POST. By setting -1, curl will
+  auto-select chunked on HTTP/1.1 and work properly on other HTTP
+  versions.
 
-  - refs #11426 where spurious stalls on large POST requests
-    are reported
-  - the issue seems to involve the following
-    * first stream on connection adds up to 64KB of POST
-      data, which is the max default HTTP/2 stream window size
-      transfer is set to HOLD
-    * initial SETTINGS from server arrive, enlarging the stream
-      window. But no WINDOW_UPDATE is received.
-    * curl stalls
-  - the fix un-HOLDs a stream on receiving SETTINGS, not
-    relying on a WINDOW_UPDATE from lazy servers
+  Reported-by: Jeff King
+  Fixes #13229
+  Closes #13257
 
-  Closes #11450
+Jay Satiro (1 Apr 2024)
 
-Daniel Stenberg (17 Jul 2023)
+- INSTALL-CMAKE.md: explain `cmake -G `
 
-- ngtcp2: assigning timeout, but value is overwritten before used
+  - Explain that CMake's -G option can be used to specify which build
+    system to generate files for.
 
-  Reported by Coverity
+  Example: cmake ../curl -G "MinGW Makefiles"
 
-  Closes #11453
+  Ref: https://github.com/curl/curl/pull/12224#issuecomment-2026813645
 
-- krb5: add typecast to please Coverity
+  Closes https://github.com/curl/curl/pull/13244
 
-Derzsi Dániel (16 Jul 2023)
+Daniel Stenberg (1 Apr 2024)
 
-- wolfssl: support setting CA certificates as blob
+- libcurl-opts: mention pipelining less
 
-  Closes #11445
+  libcurl has not supported HTTP pipelining since many years. Remove a few
+  (more) mentions of the feature.
 
-- wolfssl: detect when TLS 1.2 support is not built into wolfssl
+  Closes #13254
 
-  Closes #11444
+Daniel McCarney (31 Mar 2024)
 
-Graham Campbell (15 Jul 2023)
+- m4: reposition USE_RUSTLS="yes" for pkg-config
 
-- CI: bump nghttp2 from 1.55.0 to 1.55.1
+  It's necessary to set this var to "yes" _after_ AC_DEFINE and AC_SUBST
+  in order for a later `test` to pass so that `check_for_ca_bundle=1` ends
+  up being set. This is in turn required for the default CA certificate
+  bundle to be set when building w/ rustls & pkg-config.
 
-  Closes #11442
+  Reported-by: Matt Jolly
+  Fixes #13248
+  Closes #13251
 
-Daniel Stenberg (15 Jul 2023)
+Daniel Stenberg (31 Mar 2024)
 
-- curl: return error when asked to use an unsupported HTTP version
+- maketgz: put docs/RELEASE-TOOL.md into the tarball
 
-  When one of the following options are used but the libcurl in use does
-  not support it:
+  Generated with scripts/release-tools.sh
 
-  --http2
-  --http2-prior-knowledge
-  --proxy-http2
+  The script lists the exact Debian package names and version numbers for
+  the tools that are used to generate the tarball.
 
-  Closes #11440
+  Closes #13239
 
-Chris Paulson-Ellis (14 Jul 2023)
+- cd2nroff/manage: use UTC when SOURCE_DATE_EPOCH is set
 
-- cf-socket: don't bypass fclosesocket callback if cancelled before connect
+  Make them independent of the TZ setting. Also set a date string like
+  YYYY-MM-DD to avoid a local month name in the date.
 
-  After upgrading to 8.1.2 from 7.84.0, I found that sockets were being
-  closed without calling the fclosesocket callback if a request was
-  cancelled after the associated socket was created, but before the socket
-  was connected. This lead to an imbalance of fopensocket & fclosesocket
-  callbacks, causing problems with a custom event loop integration using
-  the multi-API.
+  Reported-by: Carlos Henrique Lima Melara
+  Fixes #13242
+  Closes #13243
 
-  This was caused by cf_socket_close() calling sclose() directly instead
-  of calling socket_close() if the socket was not active. For regular TCP
-  client connections, the socket is activated by cf_socket_active(), which
-  is only called when the socket completes the connect.
+- RELEASE-NOTES: synced
 
-  As far as I can tell, this issue has existed since 7.88.0. That is,
-  since the code in question was introduced by:
-      commit 71b7e0161032927cdfb4e75ea40f65b8898b3956
-      Author: Stefan Eissing 
-      Date:   Fri Dec 30 09:14:55 2022 +0100
+- docs/MAIL-ETIQUETTE: convert to markdown
 
-          lib: connect/h2/h3 refactor
+  To render nicer. To get spellchecked.
 
-  Closes #11439
+  Closes #13247
 
-Daniel Stenberg (13 Jul 2023)
+- reuse: add copyright + license info to individual docs/*.md files
 
-- tool_parsecfg: accept line lengths up to 10M
+  Instead of use 'docs/*.md' in dep5. For clarity and avoiding a wide-
+  matching wildcard.
 
-  Bumped from 100K set in 47dd957daff9
+  + Remove mention of old files from .reuse/dep5
+  + add info to .github/dependabot.yml
+  + make scripts/copyright.pl warn on non-matching patterns
 
-  Reported-by: Antoine du Hamel
-  Fixes #11431
-  Closes #11435
+  Closes #13245
 
-Stefan Eissing (13 Jul 2023)
+- test470: warn about unicode quote character read from config file
 
-- CI: brew fix for openssl in default path
+  Idea-by: Emanuele Torre
 
-  If brew install/update links openssl into /usr/local, it will be found
-  before anything we add with `-isystem path` to CPP/LDLFAGS.  Get rid of
-  that by unlinking the keg.
+- test469: verify warning when argument has unicode quote
 
-  Fixes #11413
-  Closes #11436
+- tool_getparam: output warning for leading unicode quote character
 
-Daniel Stenberg (13 Jul 2023)
+  ... in the option argument.
 
-- RELEASE-NOTES: synced
+  Typically this is a mistake done when copying example command lines from
+  online documentation using the wrong quote character.
 
-Ondřej Koláček (13 Jul 2023)
+  Presumably there are also other potential quote characters that might be
+  used, and this check is done without even knowing that unicode is used!
 
-- sectransp: fix EOF handling
+  Reported-by: Sanjay Pujare
+  Fixes #13214
+  Closes #13215
 
-  Regression since the large refactor from 2022
+- tool: follow-up getenv fix
 
-  Closes #11427
+  Remove a double free. Change the IPFS env use to a plain getenv() simply
+  because coverity gets confused.
 
-Daniel Stenberg (13 Jul 2023)
+  Follow-up to 9126b141c9398fe
+  Closes #13241
 
-- checksrc: quote the file name to work with "funny" letters
+- idn: make Curl_idnconvert_hostname() use Curl_idn_decode()
 
-  Closes #11437
+  In the name of less code duplication
 
-Karthikdasari0423 (13 Jul 2023)
+  Closes #13236
 
-- HTTP3.md: ngtcp2 updated to v0.17.0 and nghttp3 to v0.13.0
+- curl-confopts.m4: define CARES_NO_DEPRECATED when c-ares is used
 
-  Follow-up to e0093b4b732f6
+  Starting in 1.28.0 c-ares added deprecation warnings for some API calls
+  libcurl uses.
 
-  Closes #11433
+  Closes #13240
 
-Daniel Stenberg (13 Jul 2023)
+- vquic: use CURL_FORMAT_CURL_OFF_T for 64 bit printf output
 
-- CURLOPT_MIMEPOST.3: clarify what setting to NULL means
+  Reported-by: Keitagit-kun on github
+  Fixes #13224
+  Closes #13231
 
-  Follow-up to e08382a208d4e480
+- openldap: create ldap URLs correctly for IPv6 addresses
 
-  Closes #11430
+  Reported-by: Sergio Durigan Junior
+  Fixes #13228
+  Closes #13235
 
-Tatsuhiro Tsujikawa (12 Jul 2023)
+- curl: use curl_getenv instead of the curlx_ version
 
-- ngtcp2: build with 0.17.0 and nghttp3 0.13.0
+  The curlx one was once introduced when we still considered dropping the
+  libcurl function at some point. To reduce confusion and to make it
+  easier to understand when curl_free() should be used, use the actual
+  libcurl function call directly instead.
 
-  - ngtcp2_crypto_openssl was renamed to ngtcp2_crypto_quictls.
+  Closes #13230
 
-  Closes #11428
+Evgeny Grin (Karlson2k) (30 Mar 2024)
 
-- CI: Bump ngtcp2, nghttp3, and nghttp2
+- curl_sha512_256: do not use workaround for NetBSD when not needed
 
-  Closes #11428
+  Assisted-by: riastradh on github
+  Assisted-by: Michael Kaufmann
+  Closes #13225
 
-James Fuller (11 Jul 2023)
+Matt Jolly (30 Mar 2024)
 
-- example/maxconnects: set maxconnect example
+- m4: fix rustls pkg-config codepath
 
-  Closes #11343
+  The previous pkg-config code would successfully detect rustls but did
+  not set all appropriate variables and call the right macros to properly
+  configure cURL.
 
-Pontakorn Prasertsuk (11 Jul 2023)
+  Reported-by: kpcyrd on github
+  Fixes #13200
+  Closes #13202
 
-- http2: send HEADER & DATA together if possible
+Daniel McCarney (30 Mar 2024)
 
-  Closes #11420
+- deps: update librustls 0.12.0 -> 0.13.0
 
-Daniel Stenberg (11 Jul 2023)
+  This commit updates the optional rustls-ffi librustls dependency from
+  0.12.0 to 0.13.0. This version is based on the latest available rustls
+  release (0.23.4).
 
-- CI: use wolfSSL 5.6.3 in builds
+  The breaking API changes from 0.12.0 to 0.13.0 are in API surface unused
+  by curl, so this is an in-place update without any code changes.
 
-  No using master anymore
+  The `RUSTLS.md` documentation is updated to reflect the new version in
+  use, and to clarify that `cbindgen` isn't required to build `librustls`
+  - it's only used by developers to update the vendored `rustls.h` header
+  file maintained upstream.
 
-  Closes #11424
+  Closes #13238
 
-SaltyMilk (11 Jul 2023)
+Daniel Stenberg (28 Mar 2024)
 
-- fopen: optimize
+- RELEASE-NOTES: synced
 
-  Closes #11419
+- tool_xattr: "guess" URL scheme if none is provided
 
-Daniel Stenberg (11 Jul 2023)
+  ... when figuring out the source URL to store.
 
-- cmake: make use of snprintf
+  Reported-by: Dagfinn Ilmari Mannsåker
+  Fixes #13205
+  Closes #13221
 
-  Follow-up to 935b1bd4544a23a91d68
+- tool_xattr: in debug builds, act normally if CURL_FAKE_XATTR is not set
 
-  Closes #11423
+  Closes #13220
 
-Stefan Eissing (11 Jul 2023)
+Stefan Eissing (28 Mar 2024)
 
-- macOS: fix taget detection
+- content_encoding: brotli and others, pass through 0-length writes
 
-  - TARGET_OS_OSX is not always defined on macOS
-  - this leads to missing symbol Curl_macos_init()
-  - TargetConditionals.h seems to define these only when
-    dynamic targets are enabled (somewhere?)
-  - this PR fixes that on my macOS 13.4.1
-  - I have no clue why CI builds worked without it
+  - curl's transfer handling may write 0-length chunks at the end of the
+    download with an EOS flag. (HTTP/2 does this commonly)
 
-  Follow-up to c7308592fb8ba213fc2c1
-  Closes #11417
+  - content encoders need to pass-through such a write and not count this
+    as error in case they are finished decoding
 
-Stan Hu (9 Jul 2023)
+  Fixes #13209
+  Fixes #13212
+  Closes #13219
 
-- hostip.c: Move macOS-specific calls into global init call
+Tobias Stoeckmann (28 Mar 2024)
 
-  https://github.com/curl/curl/pull/7121 introduced a macOS system call
-  to `SCDynamicStoreCopyProxies`, which is invoked every time an IP
-  address needs to be resolved.
+- libssh2: set length to 0 if strdup failed
 
-  However, this system call is not thread-safe, and macOS will kill the
-  process if the system call is run first in a fork. To make it possible
-  for the parent process to call this once and prevent the crash, only
-  invoke this system call in the global initialization routine.
+  Internally, libssh2 dereferences the NULL pointer if length is non-zero.
+  The callback function cannot return the error condition, so at least
+  prevent subsequent crash.
 
-  In addition, this change is beneficial because it:
+  Closes #13213
 
-  1. Avoids extra macOS system calls for every IP lookup.
-  2. Consolidates macOS-specific initialization in a separate file.
+Daniel Stenberg (28 Mar 2024)
 
-  Fixes #11252
-  Closes #11254
+- RELEASE-PROCEDURE: mention an initial working build
 
-Daniel Stenberg (9 Jul 2023)
+  This is the step that was not done and caused the 8.7.0 mishap (it
+  lacked the correctly generated hugehelp file).
 
-- docs: use a space after RFC when spelling out RFC numbers
+  Remove the mention of the copyright script as this is verified by a CI
+  job these days: the REUSE one.
 
-  Closes #11382
+  Closes #13216
 
-Margu (9 Jul 2023)
+Paul Howarth (28 Mar 2024)
 
-- imap-append.c: update to make it more likely to work
+- curl_sha512_255: fix detection of OpenSSL 1.1.1 or later
 
-  Fixes #10300
-  Closes #11397
+  Use the same OPENSSL_VERSION_NUMBER comparison as in lib/vtls/openssl.c.
 
-Emanuele Torre (9 Jul 2023)
+  Closes #13208
 
-- tool_writeout_json: fix encoding of control characters
+Robert Moreton (28 Mar 2024)
 
-  Control characters without a special escape sequence e.g. %00 or %06
-  were being encoded as "u0006" instead of "\u0006".
+- cf-socket: remove references to l_ip, l_port
 
-  Ref: https://github.com/curl/trurl/pull/214#discussion_r1257487858
-  Closes #11414
+  Fixes #13210
+  Closes #13211
 
-Stefan Eissing (9 Jul 2023)
+Daniel Stenberg (28 Mar 2024)
 
-- http3/ngtcp2: upload EAGAIN handling
+- openssl: do not set SSL_MODE_RELEASE_BUFFERS
 
-  - refs #11389 where IDLE timeouts on upload are reported
-  - reword ngtcp2 expiry handling to apply to both send+recv
-    calls into the filter
-  - EAGAIN uploads similar to the recent changes in HTTP/2, e.g.
-    report success only when send data was ACKed.
-  - HOLD sending of EAGAINed uploads to avoid cpu busy loops
-  - rename internal function for consistency with HTTP/2
-    implementation
+  While it might save some memory, it causes OpenSSL to instead do a huge
+  amount of allocations.
 
-  Fixes #11389
-  Closes #11390
+  Ref: #13136
+  Closes #13203
 
-Brian Nixon (9 Jul 2023)
+- curl: make --help adapt to the terminal width
 
-- tool_easysrc.h: correct `easysrc_perform` for `CURL_DISABLE_LIBCURL_OPTION`
+  Instead of assuming and working with 80 colums, try figuring out what
+  width is actually used.
 
-  Closes #11398
+  Ref: #13141
 
-Daniel Stenberg (9 Jul 2023)
+  Closes #13171
 
 - RELEASE-NOTES: synced
 
-- transfer: clear credentials when redirecting to absolute URL
+  and bump to 8.7.2 for now
 
-  Make sure the user and password for the second request is taken from the
-  redirected-to URL.
+- configure: make --disable-docs imply --disable-manual
 
-  Add test case 899 to verify.
+  Because when the docs is not built, the necesary curl.txt file is not
+  present so then the manual cannot get built.
 
-  Reported-by: James Lucas
-  Fixes #11410
-  Closes #11412
+  Reported-by: Harry Sintonen
+  Closes #13191
 
-Stefan Eissing (8 Jul 2023)
+Chris Webb (27 Mar 2024)
 
-- hyper: fix EOF handling on input
+- cmdline-docs: fix make install with configure --disable-docs
 
-  We ran out of disc space due to an infinite loop with debug logging
+  make -C docs/cmdline-opts install depends on all-am, which in turn
+  depends on $(MANS), unconditionally defined to be $(man_MANS).
 
-  Fixes #11377
-  Closes #11385
-  Reported-by: Dan Fandrich
+  As with CLEANFILES, only add curl.1 to man_MANS when BUILD_DOCS is true
+  so we don't try to build curl.1 unnecessarily.
 
-- http2: raise header limitations above and beyond
+  Closes #13198
 
-  - not quite to infinity
-  - rewrote the implementation of our internal HTTP/1.x request
-    parsing to work with very large lines using dynbufs.
-  - new default limit is `DYN_HTTP_REQUEST`, aka 1MB, which
-    is also the limit of curl's general HTTP request processing.
+Version 8.7.1 (27 Mar 2024)
 
-  Fixes #11405
-  Closes #11407
+Daniel Stenberg (27 Mar 2024)
 
-Juan Cruz Viotti (8 Jul 2023)
+- RELEASE-PROCEDURE: remove old release dates, add new pending ones
 
-- curl_easy_nextheader.3: add missing open parenthesis examples
+Version 8.7.0 (27 Mar 2024)
 
-  Closes #11409
-  Signed-off-by: Juan Cruz Viotti 
+Daniel Stenberg (27 Mar 2024)
 
-Dan Fandrich (7 Jul 2023)
+- RELEASE-NOTES: synced
 
-- CI: enable verbose test output on pytest
+  curl 8.7.0 release
 
-  This shows individual pass/fail status on tests and makes this output
-  consistent with other jobs' pytest invocations.
+- THANKS: new contributors from the 8.7.0 release
 
-Stefan Eissing (28 Jun 2023)
+- CURLOPT_POSTFIELDS.md: used for MQTT as well
 
-- http2: fix crash in handling stream weights
+  Closes #13189
 
-  - Delay the priority handling until the stream has been opened.
+- http: remove stale comment about rewindbeforesend
 
-  - Add test2404 to reproduce and verify.
+  ... because that struct field exists no more.
 
-  Weights may change "on the run", which is why there are checks in
-  general egress handling. These must not trigger when the stream has not
-  been opened yet.
+  Follow-up to 14bcea074a782272.
 
-  Reported-by: jbgoog@users.noreply.github.com
+  Closes #13187
 
-  Fixes https://github.com/curl/curl/issues/11379
-  Closes https://github.com/curl/curl/pull/11384
+- DISTROS: add document with distro pointers
 
-- tests/http: Add mod_h2 directive `H2ProxyRequests`
+  Lots of organizations distribute curl packages to end users. This is a
+  collection of pointers to where to learn more about curl on and with
+  each distro.
 
-  master of mod_h2 now requires H2ProxyRequests directives for forward
-  proxying with HTTP/2 to work.
+  Assisted-by: Alan Coopersmith
+  Assisted-by: Andrew Kaster
+  Assisted-by: Andy Fiddaman
+  Assisted-by: Arjan van de Ven
+  Assisted-by: Brian Clemens
+  Assisted-by: chrysos349 on github
+  Assisted-by: Dan Fandrich
+  Assisted-by: Dan McDonald
+  Assisted-by: Gaelan Steele
+  Assisted-by: graywolf on github
+  Assisted-by: Jan Macku
+  Assisted-by: John Marshall
+  Assisted-by: Jonathan Perkin
+  Assisted-by: Kevin Daudt
+  Assisted-by: Marcus Müller
+  Assisted-by: Michał Górny
+  Assisted-by: Outvi V
+  Assisted-by: Ross Burton
+  Assisted-by: Sean Molenaar
+  Assisted-by: Till Wegmüller
+  Assisted-by: Viktor Szakats
+  Assisted-by: Winni Neessen
 
-  Ref: https://github.com/icing/mod_h2/commit/3897a7086
+  Closes #13178
 
-  Closes https://github.com/curl/curl/pull/11392
+Fabian Keil (25 Mar 2024)
 
-Dan Fandrich (28 Jun 2023)
+- wolfSSL: do not call the stub function wolfSSL_BIO_set_init()
 
-- CI: make Appveyor job names unique
+  Calling the function isn't necessary and causes the build
+  to fail when wolfSSL has been compiled with NO_WOLFSSL_STUB:
 
-  Two otherwise identical mingw-w64 jobs now have their differing compiler
-  versions mentioned in their names.
+       Making all in opts
+         CCLD     curl
+       ld: error: undefined symbol: wolfSSL_BIO_set_init
+       >>> referenced by wolfssl.c:235 (vtls/wolfssl.c:235)
+       >>>               libcurl_la-wolfssl.o:(wolfssl_bio_cf_create) in archiv
+  e ../lib/.libs/libcurl.a
+       cc: error: linker command failed with exit code 1 (use -v to see invocat
+  ion)
+       *** Error code 1
 
-Sheshadri.V (25 Jun 2023)
+  Closes #13164
 
-- curl.h: include  for vxworks
+Daniel Stenberg (25 Mar 2024)
 
-  Closes #11356
+- cmdline-opts: shorter help texts
 
-Dan Fandrich (24 Jun 2023)
+  In an effort to increase the readability of the "--help all" output on
+  narrow (80 column) terminals.
 
-- CI: enable parallel make in more builds
+  Co-authored-by: Jay Satiro
 
-  Most CI services provide at least two cores, so enable parallel make
-  jobs to take advantage of that for builds. Some dependencies aren't safe
-  to build in parallel so leave those as-is.  Also, rename a few
-  workflows to eliminate duplicate names and provide a better idea what
-  they're about.
+  Closes #13169
 
-- CI: don't install impacket if tests are not run
+Matt Jolly (25 Mar 2024)
 
-  It just wastes time and bandwidth and isn't even used.
+- curl-rustls.m4: add pkg-config support to rustls detection
 
-divinity76 (24 Jun 2023)
+  Based on the existing openssl pkg-config detection, this commit tries to
+  use pkg-config to find `rustls` then falls back to the current approach
+  if that fails.
 
-- configure: the --without forms of the options are also gone
+  We use the following logic:
 
-  --without-darwin-ssl and --without-metalink
+  - if no path is provided, just use pkg-config, if it's not there we have
+    a problem!
+  - if a path is provided, try pkg-config
+    + if pkg-config fails, try and find rustls directly
 
-  Closes #11378
+  Closes #13179
 
-Daniel Stenberg (23 Jun 2023)
+Mohammadreza Hendiani (25 Mar 2024)
 
-- configure: add check for ldap_init_fd
+- TODO: update 13.11 with more information
 
-  ... as otherwise the configure script will say it is OpenLDAP in the
-  summary, but not set the USE_OPENLDAP define, therefor not using the
-  intended OpenLDAP code paths.
+  Closes #13173
 
-  Regression since 4d7385446 (7.85.0)
-  Fixes #11372
-  Closes #11374
-  Reported-by: vlkl-sap on github
+Daniel Stenberg (23 Mar 2024)
 
-Michał Petryka (23 Jun 2023)
+- docs/libcurl: generate PROTOCOLS from meta-data
 
-- cmake: stop CMake from quietly ignoring missing Brotli
+  Remove the PROTOCOLS section from the source files completely and
+  instead generate them based on the header data in the curldown files.
 
-  The CMake project was set to `QUIET` for Brotli instead of
-  `REQUIRED`. This makes builds unexpectedly ignore missing Brotli even
-  when `CURL_BROTLI` is enabled.
+  It also generates TLS backend information for options marked for TLS as
+  protocol.
 
-  Closes #11376
+  Closes #13175
 
-Emanuele Torre (22 Jun 2023)
+- CURLMOPT_MAX*: mention what happens if changed mid-transfer
 
-- docs: add more .IP after .RE to fix indentation of generate paragraphs
+  For CURLMOPT_MAXCONNECTS and CURLMOPT_MAX_HOST_CONNECTIONS
 
-  follow-up from 099f41e097c030077b8ec078f2c2d4038d31353b
+  Ref: #13158
+  Closes #13176
 
-  I just thought of checking all the other files with .RE, and I found 6
-  other files that were missing .IP at the end.
+- docs/libcurl: add TLS backend info for all TLS options
 
-  Closes #11375
+  All man pages that are listed to be for TLS now must also specify
+  exactly what TLS backends the option works for, or use All if they all
+  work.
 
-Stefan Eissing (22 Jun 2023)
+  cd2nroff makes sure this is done and that the listed backends exist.
 
-- http2: h2 and h2-PROXY connection alive check fixes
+  Closes #13168
 
-  - fix HTTP/2 check to not declare a connection dead when
-    the read attempt results in EAGAIN
-  - add H2-PROXY alive check as for HTTP/2 that was missing
-    and is needed
-  - add attach/detach around Curl_conn_is_alive() and remove
-    these in filter methods
-  - add checks for number of connections used in some test_10
-    proxy tunneling tests
+- docs/libcurl: cleanups
 
-  Closes #11368
+  - CURLINFO_TLS_SESSION.md: remove mention of NSS
+  - CURLINFO_TLS_SSL_PTR.md: remove NSS leftover
+  - CURLOPT_CAINFO.md: drop mention of backends not supporting this
+  - CURLOPT_CAPATH.md: wolfSSL also supports this
 
-- http2: error stream resets with code CURLE_HTTP2_STREAM
+  Closes #13166
 
-  - refs #11357, where it was reported that HTTP/1.1 downgrades
-    no longer works
-  - fixed with suggested change
-  - added test_05_03 and a new handler in the curltest module
-    to reproduce that downgrades work
+- docs: make each libcurl man specify protocol(s)
 
-  Fixes #11357
-  Closes #11362
-  Reported-by: Jay Satiro
+  The mandatory header now has a mandatory list of protocols for which the
+  manpage is relevant.
 
-Daniel Stenberg (22 Jun 2023)
+  Most man pages already has a "PROTOCOLS" section, but this introduces a
+  stricter way to specify the relevant protocols.
 
-- connect-timeout.d: mention that the DNS lookup is included
+  cd2nroff verifies that at least one protocol is mentioned (which can be
+  `*`).
 
-  Closes #11370
+  This information is not used just yet, but A) the PROTOCOLS section can
+  now instead get generated and get a unified wording across all manpages
+  and B) this allows us to more reliably filter/search for protocol
+  specific manpages/options.
 
-Emanuele Torre (22 Jun 2023)
+  Closes #13166
 
-- quote.d: fix indentation of generated paragraphs
+Stefan Eissing (21 Mar 2024)
 
-  quote.d was missing a .IP at the end which caused the paragraphs
-  generated for See-also, Multi, and Example to not be indented correctly.
+- http2, http3: only return CURLE_PARTIAL_FILE when bytes were received
 
-  I also remove a redundant "This option can be used multiple times.", and
-  replaced .IP "item" with .TP .B "item" to make more clear which lines
-  are part of the list of commands and which aren't.
+  - should resolve spurious pytest failures when stream were reset
+    right after response header were received
 
-  Closes #11371
+  Clsoes #13151
 
-Paul Wise (22 Jun 2023)
+- http: separate response parsing from response action
 
-- checksrc: modernise perl file open
+  - move code that triggers on end-of-response into separate function from
+    parsing
+  - simplify some headp/headerlen usage
+  - add `httpversion` to SingleRequest to indicate the version of the
+    current response
 
-  Use regular variables and separate file open modes from filenames.
+  Closes #13134
 
-  Suggested by perlcritic
+Daniel Stenberg (21 Mar 2024)
 
-  Copied from https://github.com/curl/trurl/commit/f2784a9240f47ee28a845
+- http2: remove the third (unused) argument from http2_data_done()
 
-  Closes #11358
+  Closes #13154
 
-Dan Fandrich (21 Jun 2023)
+- RELEASE-NOTES: synced
 
-- runtests: work around a perl without SIGUSR1
+Evgeny Grin (Karlson2k) (21 Mar 2024)
 
-  At least msys2 perl v5.32.1 doesn't seem to define this signal. Since
-  this signal is only used for debugging, just ignore if setting it fails.
+- RELEASE-NOTES: corrected
 
-  Reported-by: Marcel Raad
-  Fixes #11350
-  Closes #11366
+  Corrected link for item 118
 
-- runtests: include missing valgrind package
+  Closes #13157
 
-  use valgrind was missing which caused torture tests with valgrind
-  enabled to fail.
+Daniel Stenberg (19 Mar 2024)
 
-  Reported-by: Daniel Stenberg
-  Fixes #11364
-  Closes #11365
+- CURLOPT_INTERFACE.md: remove spurious amp, add see-also
 
-- runtests: use more consistent failure lines
+  Closes #13149
 
-  After a test failure log a consistent log message to make it easier to
-  parse the log file.  Also, log a consistent message with "ignored" for
-  failures that cause the test to be not considered at all. These should
-  perhaps be counted in the skipped category, but this commit does not
-  change that behaviour.
+Stefan Eissing (19 Mar 2024)
 
-- runtests: consistently write the test check summary block
+- http: improve response header handling, save cpu cycles
 
-  The memory check character was erroneously omitted if the memory
-  checking file was not available for some reason, making the block of
-  characters an inconsistent length.
+  Saving some cpu cycles in http response header processing:
+  - pass the length of the header line along
+  - use string constant sizeof() instead of strlen()
+  - check line length if prefix is possible
+  - switch on first header char to limit checks
 
-- test2600: fix the description
+  Closes #13143
 
-  It looks like it was cut-and-pasted.
+Daniel Stenberg (19 Mar 2024)
 
-  Closes #11354
+- tool_getparam: accept a blank -w ""
 
-Daniel Stenberg (21 Jun 2023)
+  Added test 468 to verify.
 
-- TODO: "Support HTTP/2 for HTTP(S) proxies" *done*
+  Regression from 07bcae89d5d00 (shipped in 8.6.0)
+  Reported-by: Thomas Pyle
+  Fixes #13144
+  Closes #13145
 
-humbleacolyte (21 Jun 2023)
+Evgeny Grin (Karlson2k) (18 Mar 2024)
 
-- cf-socket: move ctx declaration under HAVE_GETPEERNAME
+- curl_sha512_256: work around a NetBSD bug
 
-  Closes #11352
+  Based on Michael Kaufmann analysis and suggestion
 
-Daniel Stenberg (20 Jun 2023)
+  Closes #13133
 
-- RELEASE-NOTES: synced
+Stefan Eissing (18 Mar 2024)
 
-- example/connect-to: show CURLOPT_CONNECT_TO
+- http: expect 100 rework
 
-  Closes #11340
+  Move all handling of HTTP's `Expect: 100-continue` feature into a client
+  reader. Add sending flag `KEEP_SEND_TIMED` that triggers transfer
+  sending on general events like a timer.
 
-Stefan Eissing (20 Jun 2023)
+  HTTP installs a `CURL_CR_PROTOCOL` reader when announcing `Expect:
+  100-continue`. That reader works as follows:
 
-- hyper: unslow
+  - on first invocation, records time, starts the `EXPIRE_100_TIMEOUT`
+    timer, disables `KEEP_SEND`, enables `KEEP_SEND_TIMER` and returns 0,
+    eos=FALSE like a paused upload.
 
-  - refs #11203 where hyper was reported as being slow
-  - fixes hyper_executor_poll to loop until it is out of
-    tasks as advised by @seanmonstar in https://github.com/hyperium/hyper/issue
-  s/3237
-  - added a fix in hyper io handling for detecting EAGAIN
-  - added some debug logs to see IO results
-  - pytest http/1.1 test cases pass
-  - pytest h2 test cases fail on connection reuse. HTTP/2
-    connection reuse does not seem to work. Hyper submits
-    a request on a reused connection, curl's IO works and
-    thereafter hyper declares `Hyper: [1] operation was canceled: connection cl
-  osed`
-    on stderr without any error being logged before.
+  - on subsequent invocation it checks if the timer has expired. If so, it
+    enables `KEEP_SEND` and switches to passing through reads to the
+    underlying readers.
 
-  Fixes #11203
-  Reported-by: Gisle Vanem
-  Advised-by: Sean McArthur
-  Closes #11344
+  Transfer handling's `readwrite()` will be invoked when a timer expires
+  (like `EXPIRE_100_TIMEOUT`) or when data from the server arrives. Seeing
+  `KEEP_SEND_TIMER`, it will try to upload more data, which triggers
+  reading from the client readers again. Which then may lead to a new
+  pausing or cause the upload to start.
 
-- HTTP/2: upload handling fixes
+  Flags and timestamps connected to this have been moved from
+  `SingleRequest` into the reader's context.
 
-  - fixes #11242 where 100% CPU on uploads was reported
-  - fixes possible stalls on last part of a request body when
-    that information could not be fully send on the connection
-    due to an EAGAIN
-  - applies the same EGAIN handling to HTTP/2 proxying
+  Closes #13110
 
-  Reported-by: Sergey Alirzaev
-  Fixed #11242
-  Closes #11342
+- mbedtls: fix pytest for newer versions
 
-Daniel Stenberg (20 Jun 2023)
+  Fix the expectations in pytest for newer versions of mbedtls
 
-- example/opensslthreadlock: remove
+  Closes #13132
 
-  This shows how to setup OpenSSL mutex callbacks, but this is not
-  necessary since OpenSSL 1.1.0 - meaning that no currently supported
-  OpenSSL version requires this anymore
+Daniel Stenberg (15 Mar 2024)
 
-  Closes #11341
+- ipv6.md: mention IPv4 mapped addresses
 
-Dan Fandrich (19 Jun 2023)
+  Reported-by: Josh Soref
+  Assisted-by: Jay Satiro
+  Fixes #13112
+  Closes #13131
 
-- libtest: display the times after a test timeout error
+Stefan Eissing (15 Mar 2024)
 
-  This is to help with test failure debugging.
+- http: revisit http_perhapsrewind()
 
-  Ref: #11328
-  Closes #11329
+  - use facilities provided by client readers better
+  - work also for non-uploading requests like GET/HEAD
+  - update documentation
 
-- test2600: bump a test timeout
+  Closes #13117
 
-  Case 1 failed at least once on GHA by going 30 msec too long.
+- test 1541: verify getinfo values on first header callback
 
-  Ref: #11328
+  Reported-by: chensong1211 on github
+  Ref: #13125
+  Closes #13128
 
-- runtests: better detect and handle pipe errors in the controller
+- TLS: start shutdown only when peer did not already close
 
-  Errors reading and writing to the pipes are now better detected and
-  propagated up to the main test loop so it can be cleanly shut down. Such
-  errors are usually due to a runner dying so it doesn't make much sense
-  to try to continue the test run.
+  - When curl sees a TCP close from the peer, do not start a TLS shutdown.
+    TLS shutdown is a handshake and if the peer already closed the
+    connection, it is not interested in participating.
 
-- runtests: cleanly abort the runner if the controller dies
+  Reported-by: dfdity on github
+  Assisted-by: Jiří Bok
+  Assisted-by: Pēteris Caune
+  Fixes #10290
+  Closes #13087
 
-  If the controller dies unexpectedly, have the runner stop its servers
-  and exit cleanly. Otherwise, the orphaned servers will stay running in
-  the background.
+Daniel Stenberg (14 Mar 2024)
 
-- runtests: improve error logging
+- RELEASE-NOTES: synced
 
-  Give more information about test harness error conditions to help figure
-  out what might be wrong. Print some internal test state when SIGUSR1 is
-  sent to runtests.pl.
+- curl: make --libcurl output better CURLOPT_*SSLVERSION
 
-  Ref: #11328
+  The option is really two enums ORed together, so it needs special
+  attention to make the code output nice.
 
-- runtests: better handle ^C during slow tests
+  Added test 1481 to verify. Both the server and the proxy versions.
 
-  Since the SIGINT handler now just sets a flag that must be checked in the
-  main controller loop, make sure that runs periodically.  Rather than
-  blocking on a response from a test runner near the end of the test run,
-  add a short timeout to allow it.
+  Reported-by: Boris Verkhovskiy
+  Fixes #13127
+  Closes #13129
 
-- runtests: rename server command file
+- GHA/linux: add sysctl trick to work-around GitHub runner issue
 
-  The name ftpserver.cmd was historical and has been used for more than
-  ftp for many years now. Rename it to plain server.cmd to reduce
-  confusion.
+  The GitHub image runner update from 20240304.1.0 to 20240310.1
+  introduces a problem for clang-14. The issue is caused by
+  incompatibility between llvm 14 provided in ubuntu-22.04 image and the
+  much newer kernel configured with high-entropy ASLR.
 
-- tests: improve reliability of TFTP tests
+  As a work-around, we issue a sysctl command to lower the entropy and get
+  clang-14 to work again.
 
-  Stop checking the timeout used by the client under test (for most
-  tests). The timeout will change if the TFTP test server is slow (such as
-  happens on an overprovisioned CI server) because the client will retry
-  and reduce its timeout, and the actual value is not important for most
-  tests.
+  URL: https://github.com/actions/runner-images/issues/9491
 
-  test285 is changed a different way, by increasing the connect timeout.
-  This improves test coverage by allowing the changed timeout value to be
-  checked, but improves reliability with a carefully-chosen timeout that
-  not only allows twice the time to respond as before, but also allows
-  several retries before the client will change its timeout value.
+  Closes #13124
 
-  Ref: #11328
+- SPONSORS: describe the basics
 
-Daniel Stenberg (19 Jun 2023)
+  Closes #13119
 
-- cf-socket: skip getpeername()/getsockname for TFTP
+- GOVERNANCE: document the core team
 
-  Since the socket is not connected then the call fails. When the call
-  fails, failf() is called to write an error message that is then
-  surviving and is returned when the *real* error occurs later. The
-  earlier, incorrect, error therefore hides the actual error message.
+  Closes #13118
 
-  This could be seen in stderr for test 1007
+Jay Satiro (13 Mar 2024)
 
-  Test 1007 has now been extended to verify the stderr message.
+- vquic-tls: fix the error code returned for bad CA file
 
-  Closes #11332
+  - Return CURLE_SSL_CACERT_BADFILE if wolfSSL encounters a problem
+    reading the cert file or path.
 
-- example/crawler: make it use a few more options
+  This is a follow-up to the parent commit aedbbdf1.
 
-  For show, but reasonable
+  Reported-by: Karthikdasari0423@users.noreply.github.com
 
-- libcurl-ws.3: mention raw mode
+  Fixes https://github.com/curl/curl/issues/13115
 
-  Closes #11339
+Daniel Stenberg (12 Mar 2024)
 
-- example/default-scheme: set the default scheme for schemeless URLs
+- vquic-tls: return appropirate errors on wolfSSL errors
 
-  Closes #11338
+  Reported-by: Dexter Gerig
+  Closes #13107
 
-- example/hsts-preload: show one way to HSTS preload
+Viktor Szakats (12 Mar 2024)
 
-  Closes #11337
+- tidy-up: one comment and EOF newlines
 
-- examples/http-options: show how to send "OPTIONS *"
+  Reviewed-by: Daniel Stenberg
+  Closes #13108
 
-  With CURLOPT_REQUEST_TARGET.
+Daniel Stenberg (12 Mar 2024)
 
-  Also add use of CURLOPT_QUICK_EXIT to show.
+- cmdline-opts: language cleanups
 
-  Closes #11333
+  Use imperative mood consistently for the first sentence describing an
+  option.
 
-- examples: make use of CURLOPT_(REDIR_|)PROTOCOLS_STR
+  "Set this" instead "tell curl to set" or "this sets..."
 
-  To show how to use them
+  Plus some extra cleanups and rephrasing.
 
-  Closes #11334
+  Closes #13106
 
-- examples/smtp-mime: use CURLOPT_MAIL_RCPT_ALLOWFAILS
+- managen: remove space before protocols
 
-  For show
+  For options that are listed for specific protocols, the protocols (shown
+  first within parentheses) are now output without the leading space in the
+  manpage output.
 
-  Closes #11335
+  Closes #13105
 
-- http: rectify the outgoing Cookie: header field size check
+Jay Satiro (12 Mar 2024)
 
-  Previously it would count the size of the entire outgoing request and
-  not just the size of only the Cookie: header field - which was the
-  intention.
+- mbedtls: properly cleanup the thread-shared entropy
 
-  This could make the check be off by several hundred bytes in some cases.
+  - Store the state of the thread-shared entropy for global init/cleanup.
 
-  Closes #11331
+  - Use curl's thread support of mbedtls for all Windows builds instead of
+    just when the threaded resolver is used via USE_THREADS_WIN32.
 
-Jay Satiro (17 Jun 2023)
+  Prior to this change on global cleanup curl builds that have curl thread
+  support for mbedtls freed the entropy (8b1d2298) but failed to mark that
+  it had been freed, which caused problems on subsequent init + transfer.
 
-- lib: fix some format specifiers
+  Bug: https://github.com/curl/curl/discussions/11919#discussioncomment-8687105
+  Reported-by: awesomekosm@users.noreply.github.com
 
-  - Use CURL_FORMAT_CURL_OFF_T where %zd was erroneously used for some
-    curl_off_t variables.
+  Closes https://github.com/curl/curl/pull/13071
 
-  - Use %zu where %zd was erroneously used for some size_t variables.
+Daniel Stenberg (12 Mar 2024)
 
-  Prior to this change some of the Windows CI tests were failing because
-  in Windows 32-bit targets have a 32-bit size_t and a 64-bit curl_off_t.
-  When %zd was used for some curl_off_t variables then only the lower
-  32-bits was read and the upper 32-bits would be read for part or all of
-  the next specifier.
+- tool_getparam: handle non-existing (out of range) short-options
 
-  Fixes https://github.com/curl/curl/issues/11327
-  Closes https://github.com/curl/curl/pull/11321
+  ... correctly, even when they follow an existing one without a space in
+  between.
 
-Marcel Raad (16 Jun 2023)
+  Verify with test 467
 
-- test427: add `cookies` feature and keyword
+  Follow-up to 07dd60c05b
+  Reported-by: Geeknik Labs
+  Fixes #13101
+  Closes #13102
 
-  This test doesn't work with `--disable-cookies`.
+Stefan Eissing (11 Mar 2024)
 
-  Closes https://github.com/curl/curl/pull/11320
+- lib: move 'done' parameter to SingleRequests
 
-Chris Talbot (15 Jun 2023)
+  A transfer may do several `SingleRequest`s for its success. This happens
+  regularly for authentication, follows and retries on failed connections.
+  The "readwrite()" calls and functions connected to those carried a `bool
+  *done` parameter to indicate that the current `SingleRequest` is over.
+  This may happen before `upload_done` or `download_done` bits of
+  `SingleRequest` are set.
 
-- imap: Provide method to disable SASL if it is advertised
+  The problem with that is now `write_resp()` protocol handlers are
+  invoked in places where the `bool *done` cannot be passed up to the
+  caller. Instead of being a bool in the call chain, it needs to become a
+  member of `SingleRequest`, reflecting its state.
 
-  - Implement AUTH=+LOGIN for CURLOPT_LOGIN_OPTIONS to prefer plaintext
-    LOGIN over SASL auth.
+  This removes the `bool *done` parameter and adds the `done` bit to
+  `SingleRequest` instead. It adds `Curl_req_soft_reset()` for using a
+  `SingleRequest` in a follow up, clearing `done` and other
+  flags/counters.
 
-  Prior to this change there was no method to be able to fall back to
-  LOGIN if an IMAP server advertises SASL capabilities. However, this may
-  be desirable for e.g. a misconfigured server.
+  Closes #13096
 
-  Per: https://www.ietf.org/rfc/rfc5092.html#section-3.2
+- request: clarify message when request has been sent off
 
-  ";AUTH=" looks to be the correct way to specify what
-  authenication method to use, regardless of SASL or not.
+  Change the "uploaded and fine" message for requests without a body
 
-  Closes https://github.com/curl/curl/pull/10041
+  Reported-by: Karthikdasari0423 on github
+  Fixes #13093
+  Closes #13095
 
-Daniel Stenberg (15 Jun 2023)
+Daniel Stenberg (11 Mar 2024)
 
 - RELEASE-NOTES: synced
 
-- examples/multi-debugcallback.c: avoid the bool typedef
+Stefan Eissing (9 Mar 2024)
 
-  Apparently this cannot be done in c23
+- lib: keep conn IP information together
 
-  Reported-by: Cristian Rodríguez
-  Fixes #11299
-  Closes #11319
+  new struct ip_quadruple for holding local/remote addr+port
 
-- docs/libcurl/libcurl.3: cleanups and improvements
+  - used in data->info and conn and cf-socket.c
+  - copy back and forth complete struct
+  - add 'secondary' to conn
+  - use secondary in reporting success for ftp 2nd connection
 
-  Closes #11317
+  Reported-by: DasKutti on github
+  Fixes #13084
+  Closes #13090
 
-- libcurl-ws.3: fix typo
+Daniel Stenberg (8 Mar 2024)
 
-- curl_ws_*.3: enhance
+- scripts/managen: the new name and home for the manpage generator
 
-  - all: SEE ALSO the libcurl-ws man page
-  - send: add example and return value information
-  - meta: mention that the returned data is read-only
+  It was previously docs/cmdline-opts/gen.pl
 
-  Closes #11318
+  Closes #13089
 
-- docs/libcurl/libcurl-ws.3: see also CURLOPT_WS_OPTIONS
+- VULN-DISCLOSURE-POLICY.md: update detail about CVE requests
 
-- docs/libcurl/libcurl-ws.3: minor polish
+  curl is a CNA now
 
-- libcurl-ws.3. WebSocket API overview
+  Closes #13088
 
-  Closes #11314
+Stefan Eissing (8 Mar 2024)
 
-- libcurl-url.3: also mention CURLUPART_ZONEID
+- lib: client reader polish
 
-  ... and sort the two part-using lists alphabetically
+  - seek_func/seek_client, use transfer values only
+      - remove copies held in `struct connectdata`, use only
+        ever `data->set.seek_func`
+      - resolves possible issues in multiuse connections
+      - new mime post reader eliminates need to ever overwriting this
 
-Marcel Raad (14 Jun 2023)
+  - websockets, remove empty Curl_ws_done() function
 
-- fopen: fix conversion warning on 32-bit Android
+  Closes #13079
 
-  When building for 32-bit ARM or x86 Android, `st_mode` is defined as
-  `unsigned int` instead of `mode_t`, resulting in a
-  -Wimplicit-int-conversion clang warning because `mode_t` is
-  `unsigned short`. Add a cast to silence the warning.
+Marcel Raad (8 Mar 2024)
 
-  Ref: https://android.googlesource.com/platform/bionic/+/refs/tags/ndk-r25c/li
-  bc/include/sys/stat.h#86
-  Closes https://github.com/curl/curl/pull/11313
+- lib1598: fix `CURLOPT_POSTFIELDSIZE` usage
 
-- http2: fix variable type
+  It requires a `long` argument.
 
-  `max_recv_speed` is `curl_off_t`, so using `size_t` might result in
-  -Wconversion GCC warnings for 32-bit `size_t`. Visible in the NetBSD
-  ARM autobuilds.
+  Closes https://github.com/curl/curl/pull/13085
 
-  Closes https://github.com/curl/curl/pull/11312
+Daniel Stenberg (8 Mar 2024)
 
-Daniel Stenberg (13 Jun 2023)
+- docs/cmdline-opts: drop the curl.1 from the dist tarball
 
-- vtls: fix potentially uninitialized local variable warnings
+  Since it is no longer needed for building tool_hugehelp.c and all the
+  docs is available in readable markdown format in the tarball, the peeps
+  that don't want to build the manpage still do good.
 
-  Follow-up from a4a5e438ae533c
+  Removing it also fixes the complexity of out-of-tree builds when the
+  curl.1 exists in the source tree.
 
-  Closes #11310
+- test1140/1173: extend wildcards to find curl.1
 
-- timeval: use CLOCK_MONOTONIC_RAW if available
+  ... in its new build path.
 
-  Reported-by: Harry Sintonen
-  Ref: #11288
-  Closes #11291
+  Also update the test scripts to be more precise in error messages to
+  help us understand CI errors better.
 
-Stefan Eissing (12 Jun 2023)
+  Follow-up to f03c85635f35269f1
+  Ref: #13029
+  Closes #13083
 
-- tool: add curl command line option `--trace-ids`
+- http2: minor tweaks to optimize two struct sizes
 
-  - added and documented --trace-ids to prepend (after the timestamp)
-    the transfer and connection identifiers to each verbose log line
-  - format is [n-m] with `n` being the transfer id and `m` being the
-    connection id. In case there is not valid connection id, print 'x'.
-  - Log calls with a handle that has no transfer id yet, are written
-    without any ids.
+  - use BIT() instead of bool
+  - place the struct fields in (roughly) size order
 
-  Closes #11185
+  Closes #13082
 
-- lib: add CURLINFO_CONN_ID and CURLINFO_XFER_ID
+- buildconf.bat: remove outdated groff/nroff use
 
-  - add an `id` long to Curl_easy, -1 on init
-  - once added to a multi (or its own multi), it gets
-    a non-negative number assigned by the connection cache
-  - `id` is unique among all transfers using the same
-    cache until reaching LONG_MAX where it will wrap
-    around. So, not unique eternally.
-  - CURLINFO_CONN_ID returns the connection id attached to
-    data or, if none present, data->state.lastconnect_id
-  - variables and type declared in tool for write out
+  - don't try to generate the real hugehelp file, because it requires
+    curl.txt which needs a build
+  - don't attempt to do anything in a c-ares subdirectory
 
-  Closes #11185
+  Follow-up to f03c85635f35269
+  Closes #13078
 
-Daniel Stenberg (12 Jun 2023)
+- http2: memory errors in the push callbacks are fatal
 
-- CURLOPT_INFILESIZE.3: mention -1 triggers chunked
+  Use the correct nghttp2 error code accordingly.
 
-  Ref: #11300
-  Closes #11304
+  Closes #13081
 
-Philip Heiduck (12 Jun 2023)
+Viktor Szakats (7 Mar 2024)
 
-- CI: openssl-3.0.9+quic
+- mkhelp: rename variable to fix compiler warnings
 
-  Closes #11296
+  ```
+  src\tool_operate.c(541,33): warning C4459: declaration of 'm' hides global de
+  claration [_bld\src\curl.vcxproj]
+    _bld\src\tool_hugehelp.c(8,27):
+    see declaration of 'm'
+  src\tool_paramhlp.c(307,14): warning C4459: declaration of 'm' hides global d
+  eclaration [_bld\src\curl.vcxproj]
+  src\tool_progress.c(118,16): warning C4459: declaration of 'm' hides global d
+  eclaration [_bld\src\curl.vcxproj]
+  src\tool_writeout.c(288,31): warning C4459: declaration of 'm' hides global d
+  eclaration [_bld\src\curl.vcxproj]
+  ```
+  Ref: https://ci.appveyor.com/project/curlorg/curl/builds/49348159/job/51ee75c
+  d2n0wj6lc#L614
 
-Karthikdasari0423 (12 Jun 2023)
+  Reviewed-by: Daniel Stenberg
+  Closes #13077
 
-- HTTP3.md: update openssl version
+Daniel Stenberg (7 Mar 2024)
 
-  Closes #11297
+- KNOWN_BUGS: POP3 issue when reading small chunks
 
-Daniel Stenberg (12 Jun 2023)
+  Closes #12063
 
-- vtls: avoid memory leak if sha256 call fails
+- RELEASE-NOTES: synced
 
-  ... in the pinned public key handling function.
+Robert Moreton (7 Mar 2024)
 
-  Reported-by: lizhuang0630 on github
-  Fixes #11306
-  Closes #11307
+- asyn-ares: fix data race warning
 
-- examples/ipv6: disable on win32
+  - Store the c-ares version during global init.
 
-  I can't make if_nametoindex() work there
+  Prior to this change several threads could write the same data to a
+  static int variable at the same time. Though in practice it's not a
+  problem ThreadSanitizer may warn.
 
-  Follow-up to c23dc42f3997acf23
+  Reported-by: Nikita Taranov
+  Assisted-by: Jay Satiro
 
-  Closes #11305
+  Fixes #13065
+  Closes #13000
 
-- tool_operate: allow cookie lines up to 8200 bytes
+Stefan Eissing (7 Mar 2024)
 
-  Since this option might set multiple cookies in the same line, it does
-  not make total sense to cap this at 4096 bytes, which is the limit for a
-  single cookie name or value.
+- hyper: implement unpausing via client reader
 
-  Closes #11303
+  Just a tidy up to contain 'ifdef' pollution of common
+  code parts with implementation specifics.
 
-- test427: verify sending more cookies than fit in a 8190 bytes line
+  - remove the ifdef hyper unpausing in easy.c
+  - add hyper client reader for CURL_CR_PROTOCOL phase
+    that implements the unpause method for calling
+    the hyper waker if it is set
 
-  curl will then only populate the header with cookies that fit, dropping
-  ones that otherwise would have been sent
+  Closes #13075
 
-  Ref: https://curl.se/mail/lib-2023-06/0020.html
+- ngtcp2: no recvbuf for stream
 
-  Closes #11303
+  - write response data directly to the transfer via
+   `Curl_xfer_write_resp()` like we do in HTTP/2.
 
-- testutil: allow multiple %-operators on the same line
+  Closes #13073
 
-  Closes #11303
+- docs/cmdline-opts/.gitignore: ignore curl.txt
 
-Oleg Jukovec (12 Jun 2023)
+  Closes #13076
 
-- docs: update CURLOPT_UPLOAD.3
+Evgeny Grin (Karlson2k) (7 Mar 2024)
 
-  The behavior of CURLOPT_UPLOAD differs from what is described in the
-  documentation. The option automatically adds the 'Transfer-Encoding:
-  chunked' header if the upload size is unknown.
+- sha512_256: add support for GnuTLS and OpenSSL
 
-  Closes #11300
+  This is a follow-up for PR #12897.
 
-Daniel Stenberg (12 Jun 2023)
+  Add support for SHA-512/256 digest calculation by TLS backends.
+  Currently only OpenSSL and GnuTLS (actually, nettle) support
+  SHA-512/256.
 
-- RELEASE-NOTES: synced
+  Closes #13070
 
-- CURLOPT_AWS_SIGV4.3: remove unused variable from example
+- digest: add check for hashing error
 
-  Closes #11302
+  Closes #13072
 
-- examples/https.c: use CURLOPT_CA_CACHE_TIMEOUT
+Viktor Szakats (7 Mar 2024)
 
-  for demonstration purposes
+- cmake: enable `ENABLE_CURL_MANUAL` by default
 
-  Closes #11290
+  Meaning `curl.1` and `src/tool_hugehelp.c` are built by default,
+  and `--manual` in curl tool is also enabled by default.
 
-- example/ipv6: feature CURLOPT_ADDRESS_SCOPE in use
+  This syncs behaviour with autotools.
 
-  Closes #11282
+  For a reproducible `curl.1`, `SOURCE_DATE_EPOCH` needs to be set
+  to a consistent date, e.g. the timestamp of `CHANGES`.
 
-Karthikdasari0423 (10 Jun 2023)
+  A pre-built manual (e.g. the one distributed in the official source
+  tarball) will be ignored and rebuilt after this patch, unless
+  explicitly disabling this option.
 
-- docs: Update HTTP3.md for newer ngtcp2 and nghttp3
+  Fixes #13028
+  Closes #13069
 
-  Follow-up to fb9b9b58
+Stefan Eissing (7 Mar 2024)
 
-  Ref: #11184
-  Closes #11295
+- http2: push headers better cleanup
 
-Dan Fandrich (10 Jun 2023)
+  - provide common cleanup method for push headers
 
-- docs: update the supported ngtcp2 and nghttp3 versions
+  Closes #13054
 
-  Follow-up to cae9d10b
+Daniel Stenberg (7 Mar 2024)
 
-  Ref: #11184
-  Closes #11294
+- GIT-INFO: convert to markdown
 
-- tests: fix error messages & handling around sockets
+  Closes #13074
 
-  The wrong error code was checked on Windows on UNIX socket failures,
-  which could have caused all UNIX sockets to be reported as having
-  errored and the tests therefore skipped. Also, a useless error message
-  was displayed on socket errors in many test servers on Windows because
-  strerror() doesn't work on WinSock error codes; perror() is overridden
-  there to work on all errors and is used instead.
+Richard Levitte (7 Mar 2024)
 
-  Ref #11258
-  Closes #11265
+- cmake: fix libcurl.pc and curl-config library specifications
 
-Daniel Stenberg (9 Jun 2023)
+  Letting CMake figure out where libraries are located gives you full
+  paths. When generating libcurl.pc and curl-config, getting libraries as
+  full paths is unusual when one expects to get a list of -l.
 
-- CURLOPT_SSH_PRIVATE_KEYFILE.3: expand on the file search
+  To meet expectations, an effort is made to convert the full paths into
+  -l, possibly with -L before it.
 
-  Reported-by: atjg on github
-  Ref: #11287
-  Closes #11289
+  Fixes #6169
+  Fixes #12748
+  Closes #12930
 
-Stefan Eissing (9 Jun 2023)
+Daniel Stenberg (7 Mar 2024)
 
-- ngtcp2: use ever increasing timestamp in io
+- test463: HTTP with -d @file with file containing CR, LF and null byte
 
-  - ngtcp2 v0.16.0 asserts that timestamps passed to its function
-    will only ever increase.
-  - Use a context shared between ingress/egress operations that
-    uses a shared timestamp, regularly updated during calls.
+- paramhlp: fix CRLF-stripping files with "-d @file"
 
-  Closes #11288
+  All CR and LF bytes should be stripped, as documented, and all other
+  bytes are inluded in the data. Starting now, it also excludes null bytes
+  as they would otherwise also cut the data short.
 
-Daniel Stenberg (9 Jun 2023)
+  Reported-by: Simon K
+  Fixes #13063
+  Closes #13064
 
-- GHA: use nghttp2 1.54.0 for the ngtcp2 jobs
+Viktor Szakats (7 Mar 2024)
 
-Philip Heiduck (9 Jun 2023)
+- cmake: fix `CURL_WINDOWS_SSPI=ON` with Schannel disabled
 
-- GHA: ngtcp2: use 0.16.0 and nghttp3 0.12.0
+  Prior to this change `CURL_WINDOWS_SSPI` was accidentally forced `OFF`
+  when building without the Schannel TLS backend.
 
-Daniel Stenberg (9 Jun 2023)
+  This in turn may have caused Kerberos, SPNEGO and SSPI features
+  disappearing even with `CURL_WINDOWS_SSPI=ON` set.
 
-- ngtcp2: build with 0.16.0 and nghttp3 0.12.0
+  This patch fixes it by using the `CURL_USE_SCHANNEL` setting as a
+  default for `CURL_WINDOWS_SSPI`, but allowing a manual override.
 
-  - moved to qlog_write
-  - crypto => encryption
-  - CRYPTO => ENCRYPTION
-  - removed "_is_"
-  - ngtcp2_conn_shutdown_stream_read and
-    ngtcp2_conn_shutdown_stream_write got flag arguments
-  - the nghttp3_callbacks struct got a recv_settings callback
+  Also update the option text to better tell its purpose.
 
-  Closes #11184
+  Thanks-to: Andreas Loew
+  Reviewed-by: Daniel Stenberg
+  Ref: #13056
+  Closes #13061
 
-- example/http2-download: set CURLOPT_BUFFERSIZE
+Jay Satiro (6 Mar 2024)
 
-  Primarily because no other example sets it, and remove the disabling of
-  the certificate check because we should not recommend that.
+- KNOWN_BUGS: FTPS server compatibility on Windows with Schannel
 
-  Closes #11284
+  - Remove "2.12 FTPS with Schannel times out file list operation"
 
-- example/crawler: also set CURLOPT_AUTOREFERER
+  - Remove "7.12 FTPS directory listing hangs on Windows with Schannel"
 
-  Could make sense, and it was not used in any example before.
+  - Add "7.12 FTPS server compatibility on Windows with Schannel"
 
-  Closes #11283
+  This change adds a more generic bug description that explains FTPS with
+  the latest curl and Schannel is not widely used and may have more bugs
+  than other TLS backends.
 
-Wyatt OʼDay (9 Jun 2023)
+  The two removed FTPS Schannel bugs can't be reproduced any longer and
+  were likely fixed by 24d6c288.
 
-- tls13-ciphers.d: include Schannel
+  Ref: https://github.com/curl/curl/issues/5284
+  Ref: https://github.com/curl/curl/issues/9161
+  Ref: https://github.com/curl/curl/issues/12894
 
-  Closes #11271
+  Closes https://github.com/curl/curl/pull/13032
 
-Daniel Stenberg (9 Jun 2023)
+- trace-config.md: remove the mutexed options list
 
-- curl_pushheader_byname/bynum.3: document in their own man pages
+  - Remove the rendered manpage message that says:
+    "[--trace-config] is mutually exclusive to --trace and -v, --verbose".
 
-  These two functions were added in 7.44.0 when CURLMOPT_PUSHFUNCTION was
-  introduced but always lived a life in the shadows, embedded in the
-  CURLMOPT_PUSHFUNCTION man page. Until now.
+  Actually it can be used with either of those options, which are mutually
+  exclusive to each other but not to --trace-config.
 
-  It makes better sense and gives more visibility to document them in
-  their own stand-alone man pages.
+  Ref: https://curl.se/docs/manpage.html#--trace-config
 
-  Closes #11286
+  Closes https://github.com/curl/curl/pull/13031
 
-- curl_mprintf.3: minor fix of the example
+Daniel Stenberg (6 Mar 2024)
 
-- curl_url_set: enforce the max string length check for all parts
+- mkhelp: simplify the generated hugehelp program
 
-  Update the docs and test 1559 accordingly
+  Use a plain array and puts() every line, also allows us to provide the
+  strings without ending newlines.
 
-  Closes #11273
+  - merge blank lines into the next one as a prefixed newline.
+  - turn eight consecutive spaces into a tab (since they can only be on the
+    left side of text)
+  - the newly generated tool_hugehelp is 3K lines shorter and 50K smaller
+  - modifies the top logo layout a little by reducing the indent
 
-- examples/ftpuploadresume.c: add use of CURLOPT_ACCEPTTIMEOUT_MS
+  Closes #13047
 
-  For show
+- docs: ascii version of manpage without nroff
 
-  Closes #11277
+  Create ASCII version of manpage without nroff
 
-- examples/unixsocket.c: example using CURLOPT_UNIX_SOCKET_PATH
+   - build src/tool_hugegelp.c from the ascii manpage
+   - move the the manpage and the ascii version build to docs/cmdline-opts
+   - remove all use of nroff from the build process
+   - should make the build entirely reproducible (by avoiding nroff)
 
-  and alternatively CURLOPT_ABSTRACT_UNIX_SOCKET
+   - partly reverts 2620aa9 to build libcurl option man pages one by one
+     in cmake because the appveyor builds got all crazy until I did
 
-  Closes #11276
+  The ASCII version of the manpage
 
-Anssi Kolehmainen (8 Jun 2023)
+   - is built with gen.pl, just like the manpage is
+   - has a right-justified column making the appearance similar to the previous
+     version
+   - uses a 4-space indent per level (instead of the old version's 7)
+   - does not do hyphenation of words (which nroff does)
 
-- docs: fix missing parameter names in examples
+  History
 
-  Closes #11278
+    We first made the curl build use nroff for building the hugehelp file in
+    December 1998, for curl 5.2.
 
-Daniel Stenberg (8 Jun 2023)
+  Closes #13047
 
-- urlapi: have *set(PATH) prepend a slash if one is missing
+Stefan Eissing (6 Mar 2024)
 
-  Previously the code would just do that for the path when extracting the
-  full URL, which made a subsequent curl_url_get() of the path to
-  (unexpectedly) still return it without the leading path.
+- lib: add `void *ctx` to reader/writer instances
 
-  Amend lib1560 to verify this. Clarify the curl_url_set() docs about it.
+  - `struct Curl_cwriter` and `struct Curl_creader` now carry a
+    `void *ctx` member that points to the instance as allocated.
+  - using `r->ctx` and `w->ctx` as pointer to the instance specific
+    struct that has been allocated
 
-  Bug: https://curl.se/mail/lib-2023-06/0015.html
-  Closes #11272
-  Reported-by: Pedro Henrique
+  Reported-by: Rudi Heitbaum
+  Fixes #13035
+  Closes #13059
 
-Dan Fandrich (7 Jun 2023)
+- http: fix dead code in setting post client reader
 
-- runtests; give each server a unique log lock file
+  - postsize was always 0, thus the check's else never happened
+    after the mime client reader was introduced
 
-  Logs are written by several servers and all of them must be finished
-  writing before the test results can be determined. This means each
-  server must have its own lock file rather than sharing a single one,
-  which is how it was done up to now. Previously, the first server to
-  complete a test would clear the lock before the other server was done,
-  which caused flaky tests.
+  Follow-up to 0ba47146f7ff3d
+  Closes #13060
 
-  Lock files are now all found in their own directory, so counting locks
-  equals counting the files in that directory.  The result is that the
-  proxy logs are now reliably written which actually changes the expected
-  output for two tests.
+- http2: fix push discard
 
-  Fixes #11231
-  Closes #11259
+  - fix logic in discarding a failed pushed stream so that
+    stream context is properly cleaned up
 
-- runtests: make test file directories in log/N
+  Closes #13055
 
-  Test files in subdirectories were not created after parallel test log
-  directories were moved down a level due to a now-bad comparison.
+- transfer.c: break receive loop in speed limited transfers
 
-  Follow-up to 92d7dd39
+  - the change breaks looping in transfer.c receive for transfers that are
+    speed limited on having gotten *some* bytes.
+  - the overall speed limit timing is done in multi.c
 
-  Ref #11264
-  Closes #11267
+  Reported-by: Dmitry Karpov
+  Bug: https://curl.se/mail/lib-2024-03/0001.html
+  Closes #13050
 
-Daniel Stenberg (7 Jun 2023)
+- mime: add client reader
 
-- ws: make the curl_ws_meta() return pointer a const
+  Add `mime` client reader. Encapsulates reading from mime parts, getting
+  their length, rewinding and unpausing.
 
-  The returned info is read-only for the user.
+  - remove special mime handling from sendf.c and easy.c
+  - add general "unpause" method to client readers
+  - use new reader in http/imap/smtp
+  - make some mime functions static that are now only used internally
 
-  Closes #11261
+  In addition:
+  - remove flag 'forbidchunk' as no longer needed
 
-- RELEASE-NOTES: synced
+  Closes #13039
 
-- runtests: move parallel log dirs from logN to log/N
+Daniel Stenberg (5 Mar 2024)
 
-  Having several hundreds of them in there gets annoying.
+- RELEASE-NOTES: synced
 
-  Closes #11264
+- TODO: remove "build HTTP/3 with OpenSSL and nghttp3 using cmake"
 
-Dan Fandrich (7 Jun 2023)
+  Follow-up to 8e741644a229c37
 
-- test447: move the test file into %LOGDIR
+Tal Regev (5 Mar 2024)
 
-Viktor Szakats (7 Jun 2023)
+- cmake: add USE_OPENSSL_QUIC support
 
-- cmake: add support for "unity" builds
+  Closes #13034
 
-  Aka "jumbo" or "amalgamation" builds. It means to compile all sources
-  per target as a single C source. This is experimental.
+Stefan Eissing (5 Mar 2024)
 
-  You can enable it by passing `-DCMAKE_UNITY_BUILD=ON` to cmake.
-  It requires CMake 3.16 or newer.
+- TIMER_STARTTRANSFER: set the same for everyone
 
-  It makes builds (much) faster, allows for better optimizations and tends
-  to promote less ambiguous code.
+  - set TIMER_STARTTRANSFER on seeing the first response bytes
+    in the download client writer, not coming from a CONNECT
+  - initialized the timer the same way for all protocols
+  - remove explicit setting of TIMER_STARTTRANSFER in file.c
+    and c-hyper.c
 
-  Also add a new AppVeyor CI job and convert an existing one to use
-  "unity" mode (one MSVC, one MinGW), and enable it for one macOS CI job.
+  Closes #13052
 
-  Fix related issues:
-  - add missing include guard to `easy_lock.h`.
-  - rename static variables and functions (and a macro) with names reused
-    across sources, or shadowed by local variables.
-  - add an `#undef` after use.
-  - add a missing `#undef` before use.
-  - move internal definitions from `ftp.h` to `ftp.c`.
-  - `curl_memory.h` fixes to make it work when included repeatedly.
-  - stop building/linking curlx bits twice for a static-mode curl tool.
-    These caused doubly defined symbols in unity builds.
-  - silence missing extern declarations compiler warning for ` _CRT_glob`.
-  - fix extern declarations for `tool_freq` and `tool_isVistaOrGreater`.
-  - fix colliding static symbols in debug mode: `debugtime()` and
-    `statename`.
-  - rename `ssl_backend_data` structure to unique names for each
-    TLS-backend, along with the `ssl_connect_data` struct member
-    referencing them. This required adding casts for each access.
-  - add workaround for missing `[P]UNICODE_STRING` types in certain Windows
-    builds when compiling `lib/ldap.c`. To support "unity" builds, we had
-    to enable `SCHANNEL_USE_BLACKLISTS` for Schannel (a Windows
-    `schannel.h` option) _globally_. This caused an indirect inclusion of
-    Windows `schannel.h` from `ldap.c` via `winldap.h` to have it enabled
-    as well. This requires `[P]UNICODE_STRING` types, which is apperantly
-    not defined automatically (as seen with both MSVS and mingw-w64).
-    This patch includes `` to fix it.
-    Ref: https://github.com/curl/curl/runs/13987772013
-    Ref: https://dev.azure.com/daniel0244/curl/_build/results?buildId=15827&vie
-  w=logs&jobId=2c9f582d-e278-56b6-4354-f38a4d851906&j=2c9f582d-e278-56b6-4354-f
-  38a4d851906&t=90509b00-34fa-5a81-35d7-5ed9569d331c
-  - tweak unity builds to compile `lib/memdebug.c` separately in memory
-    trace builds to avoid PP confusion.
-  - force-disable unity for test programs.
-  - do not compile and link libcurl sources to libtests _twice_ when libcurl
-    is built in static mode.
+Michael Kaufmann (5 Mar 2024)
 
-  KNOWN ISSUES:
-  - running tests with unity builds may fail in cases.
-  - some build configurations/env may not compile in unity mode. E.g.:
-    https://ci.appveyor.com/project/curlorg/curl/builds/47230972/job/51wfesgnfu
-  auwl8q#L250
+- http: better error message for HTTP/1.x response without status line
 
-  Ref: https://github.com/libssh2/libssh2/issues/1034
-  Ref: https://cmake.org/cmake/help/latest/prop_tgt/UNITY_BUILD.html
-  Ref: https://en.wikipedia.org/wiki/Unity_build
+  If a response without a status line is received, and the connection is
+  known to use HTTP/1.x (not HTTP/0.9), report the error "Invalid status
+  line" instead of "Received HTTP/0.9 when not allowed".
 
-  Closes #11095
+  Closes #13045
 
-Daniel Stenberg (7 Jun 2023)
+Viktor Szakats (5 Mar 2024)
 
-- examples/websocket.c: websocket example using CONNECT_ONLY
+- KNOWN_BUGS: fix typo
 
-  Closes #11262
+  Reviewed-by: Daniel Stenberg
+  Closes #13051
+
+Sebastian Neubauer (5 Mar 2024)
+
+- smpt: fix starttls
+
+  In cases where the connection was fast, curl sometimes failed to open a
+  connection. This fixes a regression of c2d973627bab12abc5486a3f3.
+
+  The regression triggered in these steps:
+
+  1. Create an smtp connection
+  2. Use STARTTLS
+  3. Receive the response
+  4. We are inside the loop in `smtp_statemachine`, calling
+     `smtp_state_starttls_resp`
+  5. In the good flow, we exit the loop, re-enter `smtp_statemachine` and
+     run `smtp_perform_upgrade_tls` at the start of the function.
+
+     In the bad flow, we stay in the while loop, calling
+     `Curl_pp_readresp`, which reads part of the TLS handshake and things
+     go wrong.
+
+  The reason is that `Curl_pp_moredata` changed behavior and always
+  returns `true`, so we stay in the loop in `smtp_statemachine`. With a
+  slow connection `Curl_pp_readresp` cannot read new data and returns
+  `CURL_AGAIN`, so we leave the loop and re-enter `smtp_statemachine`.
+
+  With a fast connection, `Curl_pp_readresp` reads new data from the tcp
+  connection, which is part of the TLS handshake.
+
+  The fix is in `Curl_pp_moredata`, which needs to take the final line
+  into account and return `false` if only the final line is stored.
+
+  Closes #13048
+
+Stefan Eissing (5 Mar 2024)
+
+- lib: enhance client reader resume + rewind
+
+  - update client reader documentation
+  - client reader, add rewind capabilities
+      - tell creader to rewind on next start
+      - Curl_client_reset() will keep reader for future rewind if requested
+      - add Curl_client_cleanup() for freeing all resources independent of
+        rewinds
+      - add Curl_client_start() to trigger rewinds
+      - move rewind code from multi.c to sendf.c and make part of
+        "cr-in"'s implementation
+  - http, move the "resume_from" handling into the client readers
+      - the setup of a HTTP request is reshuffled to follow:
+        * determine method, target, auth negotiation
+        * install the client reader(s) for the request, including crlf
+          conversions and "chunked" encoding
+        * apply ranges to client reader
+        * concat request headers, upgrades, cookies, etc.
+        * complete request by determining Content-Length of installed
+          readers in combination with method
+        * send
+      - add methods for client readers to
+        * return the overall length they will generate (or -1 when unknown)
+        * return the amount of data on the CLIENT level, so that
+          expect-100 can decide if it want to apply itself
+        * set a "resume_from" offset or fail if unsupported
+      - struct HTTP has become largely empty now
+  - rename `Client_reader_*` to `Curl_creader_*`
+
+  Closes #13026
+
+Viktor Szakats (5 Mar 2024)
+
+- openssl-quic: fix BIO leak and Windows warning
+
+  Caused by an accidentally duplicated line in
+  d6825df334def106f735ce7e0c1a2ea87bddffb0.
 
-- websocket-cb: example doing WebSocket download using callback
+  ```
+  .../lib/vquic/curl_osslq.c:1095:30: warning: implicit conversion loses intege
+  r precision: 'curl_socket_t' (aka 'unsigned long long') to 'int' [-Wshorten-6
+  4-to-32]
+   1095 |   bio = BIO_new_dgram(ctx->q.sockfd, BIO_NOCLOSE);
+        |         ~~~~~~~~~~~~~ ~~~~~~~^~~~~~
+  1 warning and 2 errors generated.
+  ```
 
-  Very basic
+  Reviewed-by: Stefan Eissing
+  Closes #13043
 
-  Closes #11260
+- openssl-quic: fix unity build, casing, indentation
 
-- test/.gitignore: ignore log*
+  - rename static functions to avoid duplicate symbols in unity mode.
+  - windows -> Windows/window in error message and comment.
+  - fix indentation.
 
-Dan Fandrich (5 Jun 2023)
+  Reviewed-by: Stefan Eissing
+  Closes #13044
 
-- runtests: document the -j parallel testing option
+Daniel Stenberg (5 Mar 2024)
 
-  Reported-by: Daniel Stenberg
-  Ref: #10818
-  Closes #11255
+- gen.pl: make the "manpageification" faster
 
-- runtests: create multiple test runners when requested
+  The function that replaces occurances of "--longoption" with "-Z,
+  --longoption" etc with the proper highlight applied, no longer loops
+  over the options.
 
-  Parallel testing is enabled by using a nonzero value for the -j option
-  to runtests.pl. Performant values seem to be about 7*num CPU cores, or
-  1.3*num CPU cores if Valgrind is in use.
+  Closes #13041
 
-  Flaky tests due to improper log locking (bug #11231) are exacerbated
-  while parallel testing, so it is not enabled by default yet.
+- CONTRIBUTE: update the section on documentation format
 
-  Fixes #10818
-  Closes #11246
+  ... since most of it is markdown now.
 
-- runtests: handle repeating tests in multiprocess mode
+  Closes #13046
 
-  Such as what happens with the --repeat option.  Some functions are
-  changed to pass the runner ID instead of relying on the non-unique test
-  number.
+- smtp: free a temp resource
 
-  Ref: #10818
+  The returned address needs to be freed.
 
-- runtests: buffer logmsg while running singletest()
+  Follow-up to e3905de8196d67b89df1602feb84c1f993211b20
+  Spotted by Coverity
 
-  This allows all messages relating to a single test case to be displayed
-  together at the end of the test.
+  Closes #13038
 
-  Ref: #10818
+- _VARIABLES.md: improve the description
 
-- runtests: call initserverconfig() in the runner
+  Closes #13040
 
-  This must be done so variables pick up the runner's unique $LOGDIR.
+dependabot[bot] (4 Mar 2024)
 
-  Ref: #10818
+- build(deps): bump fsfe/reuse-action from 2 to 3
 
-- runtests: use a per-runner random seed
+  Bumps [fsfe/reuse-action](https://github.com/fsfe/reuse-action) from 2 to 3.
+  - [Release notes](https://github.com/fsfe/reuse-action/releases)
+  - [Commits](https://github.com/fsfe/reuse-action/compare/v2...v3)
 
-  Each runner needs a unique random seed to reduce the chance of port
-  number collisions. The new scheme uses a consistent per-runner source of
-  randomness which results in deterministic behaviour, as it did before.
+  ---
+  updated-dependencies:
+  - dependency-name: fsfe/reuse-action
+    dependency-type: direct:production
+    update-type: version-update:semver-major
+  ...
 
-  Ref: #10818
+  Signed-off-by: dependabot[bot] 
 
-- runtests: complete main test loop refactor for multiple runners
+Stefan Eissing (4 Mar 2024)
 
-  The main test loop is now able to handle multiple runners, or no
-  additional runner processes at all. At most one process is still
-  created, however.
+- pytest: adapt to API change
 
-  Ref: #10818
+  - pytest has changed the signature of the hook pytest_report_header()
+    for some obscure reason and that change landed in our CI now
 
-- runtests: prepare main test loop for multiple runners
+  - remove the changed param that we never used anyway
 
-  Some variables are expanded to arrays and hashes so that multiple
-  runners can be used for running tests.
+  Closes #13037
 
-  Ref: #10818
+Daniel Stenberg (4 Mar 2024)
 
-Stefan Eissing (5 Jun 2023)
+- cookie: if psl fails, reject the cookie
 
-- bufq: make write/pass methods more robust
+  A libpsl install without data and no built-in database is now considered
+  bad enough to reject all cookies since they cannot be checked. It is
+  somewhat of a user error, but still.
 
-  - related to #11242 where curl enters busy loop when
-    sending http2 data to the server
+  Reported-by: Dan Fandrich
+  Closes #13033
 
-  Closes #11247
+Stefan Eissing (4 Mar 2024)
 
-Boris Verkhovskiy (5 Jun 2023)
+- lib: further send/upload handling polish
 
-- tool_getparam: fix comment
+  - Move all the "upload_done" handling to request.c
 
-  Closes #11253
+    - add possibility to abort sending of a request
+    - add `Curl_req_done_sending()` for checks
+    - transfer.c: readwrite_upload() now clean
 
-Raito Bezarius (5 Jun 2023)
+  - removing data->state.ulbuf and data->req.upload_fromhere
 
-- haproxy: add --haproxy-clientip flag to spoof client IPs
+    - as well as data->req.upload_present
+    - set data->req.upload_done on having read all from
+      the client and completely flushed the send buffer
 
-  CURLOPT_HAPROXY_CLIENT_IP in the library
+  - tftp, remove setting of data->req.upload_fromhere
 
-  Closes #10779
+    - serves no purpose as `upload_present` is not set
+      and the data itself is directly `sendto()` anyway
 
-Daniel Stenberg (5 Jun 2023)
+  - smtp, make upload EOB conversion a client reader
+  - xfer_ulbuf addition
 
-- curl: add --ca-native and --proxy-ca-native
+    - add xfer_ulbuf for borrowing, similar to xfer_buf
+    - use in file upload
+    - use in c-hyper body sending
 
-  These are two boolean options to ask curl to use the native OS's CA
-  store when verifying TLS servers. For peers and for proxies
-  respectively.
+  - h1-proxy, remove init of data->state.uilbuf that is never used
+  - smb, add own send_buf instead of using data->state.ulbuf
 
-  They currently only have an effect for curl on Windows when built to use
-  OpenSSL for TLS.
+  Closes #13010
 
-  Closes #11049
+Daniel Stenberg (4 Mar 2024)
 
-Viktor Szakats (5 Jun 2023)
+- RELEASE-NOTES: synced
 
-- build: drop unused/redundant `HAVE_WINLDAP_H`
+kpcyrd (3 Mar 2024)
 
-  Sources did not use it. Autotools used it when checking for the
-  `winldap` library, which is redundant.
+- rustls: fix two warnings related to number types
 
-  With CMake, detection was broken:
-  ```
-  Run Build Command(s):/usr/local/Cellar/cmake/3.26.3/bin/cmake -E env VERBOSE=
-  1 /usr/bin/make -f Makefile cmTC_2d8fe/fast && /Library/Developer/CommandLine
-  Tools/usr/bin/make  -f CMakeFiles/cmTC_2d8fe.dir/build.make CMakeFiles/cmTC_2
-  d8fe.dir/build
-  Building C object CMakeFiles/cmTC_2d8fe.dir/HAVE_WINLDAP_H.c.obj
-  /usr/local/opt/llvm/bin/clang --target=x86_64-w64-mingw32 --sysroot=/usr/loca
-  l/opt/mingw-w64/toolchain-x86_64 -D_WINSOCKAPI_="" -I/my/quictls/x64-ucrt/usr
-  /include -I/my/zlib/x64-ucrt/usr/include -I/my/brotli/x64-ucrt/usr/include -W
-  no-unused-command-line-argument   -D_UCRT -DCURL_HIDDEN_SYMBOLS -DHAVE_SSL_SE
-  T0_WBIO -DHAS_ALPN -DNGHTTP2_STATICLIB -DNGHTTP3_STATICLIB -DNGTCP2_STATICLIB
-   -DUSE_MANUAL=1  -fuse-ld=lld -Wl,-s -static-libgcc  -lucrt  -Wextra -Wall -p
-  edantic -Wbad-function-cast -Wconversion -Winline -Wmissing-declarations -Wmi
-  ssing-prototypes -Wnested-externs -Wno-long-long -Wno-multichar -Wpointer-ari
-  th -Wshadow -Wsign-compare -Wundef -Wunused -Wwrite-strings -Wcast-align -Wde
-  claration-after-statement -Wempty-body -Wendif-labels -Wfloat-equal -Wignored
-  -qualifiers -Wno-format-nonliteral -Wno-sign-conversion -Wno-system-headers -
-  Wstrict-prototypes -Wtype-limits -Wvla -Wshift-sign-overflow -Wshorten-64-to-
-  32 -Wdouble-promotion -Wenum-conversion -Wunused-const-variable -Wcomma -Wmis
-  sing-variable-declarations -Wassign-enum -Wextra-semi-stmt  -MD -MT CMakeFile
-  s/cmTC_2d8fe.dir/HAVE_WINLDAP_H.c.obj -MF CMakeFiles/cmTC_2d8fe.dir/HAVE_WINL
-  DAP_H.c.obj.d -o CMakeFiles/cmTC_2d8fe.dir/HAVE_WINLDAP_H.c.obj -c /my/curl/b
-  ld-cmake-llvm-x64-shared/CMakeFiles/CMakeScratch/TryCompile-3JP6dR/HAVE_WINLD
-  AP_H.c
-  In file included from /my/curl/bld-cmake-llvm-x64-shared/CMakeFiles/CMakeScra
-  tch/TryCompile-3JP6dR/HAVE_WINLDAP_H.c:2:
-  In file included from /usr/local/opt/mingw-w64/toolchain-x86_64/x86_64-w64-mi
-  ngw32/include/winldap.h:17:
-  In file included from /usr/local/opt/mingw-w64/toolchain-x86_64/x86_64-w64-mi
-  ngw32/include/schnlsp.h:9:
-  In file included from /usr/local/opt/mingw-w64/toolchain-x86_64/x86_64-w64-mi
-  ngw32/include/schannel.h:10:
-  /usr/local/opt/mingw-w64/toolchain-x86_64/x86_64-w64-mingw32/include/wincrypt
-  .h:5041:254: error: unknown type name 'PSYSTEMTIME'
-    WINIMPM PCCERT_CONTEXT WINAPI CertCreateSelfSignCertificate (HCRYPTPROV_OR_
-  NCRYPT_KEY_HANDLE hCryptProvOrNCryptKey, PCERT_NAME_BLOB pSubjectIssuerBlob, 
-  DWORD dwFlags, PCRYPT_KEY_PROV_INFO pKeyProvInfo, PCRYPT_ALGORITHM_IDENTIFIER
-   pSignatureAlgorithm, PSYSTEMTIME pStartTime, PSYSTEMTIME pEndTime, PCERT_EXT
-  ENSIONS pExtensions);
-                                                                               
-                                                                               
-                                                                               
-                        ^
-  /usr/local/opt/mingw-w64/toolchain-x86_64/x86_64-w64-mingw32/include/wincrypt
-  .h:5041:278: error: unknown type name 'PSYSTEMTIME'
-    WINIMPM PCCERT_CONTEXT WINAPI CertCreateSelfSignCertificate (HCRYPTPROV_OR_
-  NCRYPT_KEY_HANDLE hCryptProvOrNCryptKey, PCERT_NAME_BLOB pSubjectIssuerBlob, 
-  DWORD dwFlags, PCRYPT_KEY_PROV_INFO pKeyProvInfo, PCRYPT_ALGORITHM_IDENTIFIER
-   pSignatureAlgorithm, PSYSTEMTIME pStartTime, PSYSTEMTIME pEndTime, PCERT_EXT
-  ENSIONS pExtensions);
-                                                                               
-                                                                               
-                                                                               
-                                                ^
-  2 errors generated.
-  make[1]: *** [CMakeFiles/cmTC_2d8fe.dir/HAVE_WINLDAP_H.c.obj] Error 1
-  make: *** [cmTC_2d8fe/fast] Error 2
-  exitCode: 2
-  ```
+  Reported-by: Gisle Vanem
+  Follow-up to #12989
+  Closes #13017
 
-  Cherry-picked from #11095 88e4a21ff70ccef391cf99c8165281ff81374503
-  Reviewed-by: Daniel Stenberg
-  Closes #11245
+Stefan Eissing (3 Mar 2024)
 
-Daniel Stenberg (5 Jun 2023)
+- bufq: writing into a softlimit queue cannot be partial
 
-- urlapi: scheme starts with alpha
+  - when unable to obtain a new chunk on a softlimit bufq,
+    this is an allocation error and needs to be reported as
+    such.
+  - writes into a soflimit bufq never must be partial success
 
-  Add multiple tests to lib1560 to verify
+  Reported-by: Dan Fandrich
+  Fixes #13020
+  Closes #13023
 
-  Fixes #11249
-  Reported-by: ad0p on github
-  Closes #11250
+Dan Fandrich (2 Mar 2024)
 
-- RELEASE-NOTES: synced
+- configure: Don't build shell completions when disabled
 
-- CURLOPT_MAIL_RCPT_ALLOWFAILS: replace CURLOPT_MAIL_RCPT_ALLLOWFAILS
+  With the recent changes to completion file building, the files were
+  built always and only installation was selectively disabled.  Now, when
+  they are disabled they aren't even built, avoiding a build-time error in
+  environments where it's not possible to run the curl binary that was
+  just created (e.g. if library paths were not set up correctly).
 
-  Deprecate the name using three Ls and prefer the name with two.
+  Follow-up to 0f7aba83c
 
-  Replaces #10047
-  Closes #11218
+  Reported-by: av223119 on github
+  Fixes #13027
+  Closes #13030
 
-- tests/servers: generate temp names in /tmp for unix domain sockets
+Jay Satiro (2 Mar 2024)
 
-  ... instead of putting them in the regular pid directories because
-  systems generally have strict length requirements for the path name to
-  be shorter than 107 bytes and we easily hit that boundary otherwise.
+- cmdline-opts/_EXITCODES: sync with libcurl-errors
 
-  The new concept generates two random names: one for the socks daemon and
-  one for http.
+  - Add error code 100 (CURLE_TOO_LARGE) to the list of error codes that
+    can be returned by the curl tool.
 
-  Reported-by: Andy Fiddaman
-  Fixes #11152
-  Closes #11166
+  Closes https://github.com/curl/curl/pull/13015
 
-Stefan Eissing (2 Jun 2023)
+Stefan Eissing (1 Mar 2024)
 
-- http2: better support for --limit-rate
+- hyper: disable test1598 due to lack of trailer support
 
-  - leave transfer loop when --limit-rate is in effect and has
-    been received
-  - adjust stream window size to --limit-rate plus some slack
-    to make the server observe the pacing we want
-  - add test case to confirm behaviour
+  Follow-up to 50838095
 
-  Closes #11115
+  Closes #13016
 
-- curl_log: evaluate log statement only when transfer is verbose
+Dan Fandrich (1 Mar 2024)
 
-  Closes #11238
+- ftp: Mark a const buffer as const
 
-Daniel Stenberg (2 Jun 2023)
+- appveyor: Properly skip if only CircleCI is changed
 
-- libssh2: provide error message when setting host key type fails
+- docs: Update minimal binary size in INSTALL.md
 
-  Ref: https://curl.se/mail/archive-2023-06/0001.html
+  Include more options to reduce binary size.
 
-  Closes #11240
+- configure: Don't make shell completions without perl
 
-Igor Todorovski (2 Jun 2023)
+  The code that attempted to skip building the shell completions didn't
+  work properly and tried to build them even if perl wasn't available.
+  This step, as well as the install step, is now properly skipped without
+  perl.
 
-- system.h: remove __IBMC__/__IBMCPP__ guards and apply to all z/OS compiles
+  Follow-up to 89733e2dd
 
-  Closes #11241
+  Closes #13022
 
-Daniel Stenberg (2 Jun 2023)
+RainRat (1 Mar 2024)
 
-- docs/SECURITY-PROCESS.md: link to example of previous critical flaw
+- misc: Fix typos in docs and lib
 
-Mark Seuffert (2 Jun 2023)
+  This fixes miscellaneous typos and duplicated words in the docs, lib
+  and test comments and a few user facing errorstrings.
 
-- README.md: updated link to opencollective
+  Author: RainRat on Github
+  Reviewed-by: Daniel Gustafsson 
+  Reviewed-by: Dan Fandrich 
+  Closes: #13019
 
-  Closes #11232
+Dan Fandrich (29 Feb 2024)
 
-Daniel Stenberg (1 Jun 2023)
+- configure: build & install shell completions when enabled
 
-- libssh2: use custom memory functions
+  The --with-fish-functions-dir and --with-zsh-functions-dir options
+  currently have no effect on a normal build because the scripts/ directory
+  where they're used is not built. Add scripts/ to a normal build and
+  change the completion options to default to off to preserve the existing
+  behaviour.
 
-  Because of how libssh2_userauth_keyboard_interactive_ex() works: the
-  libcurl callback allocates memory that is later free()d by libssh2, we
-  must set the custom memory functions.
+  Closes: #12906
 
-  Reverts 8b5f100db388ee60118c08aa28
+- github/labeler: improve the match patterns
 
-  Ref: https://github.com/libssh2/libssh2/issues/1078
-  Closes #11235
+Stefan Eissing (28 Feb 2024)
 
-- test447: test PUTting a file that grows
+- tests: add test1598 for POST with trailers
 
-  ... and have curl trim the end when it reaches the expected total amount
-  of bytes instead of over-sending.
+  - test POST fields with trailers and chunked encoding
 
-  Reported-by: JustAnotherArchivist on github
-  Closes #11223
+  Ref: #12938
+  Closes #13009
 
-- curl: count uploaded data to stop at the originally given size
+Daniel Stenberg (28 Feb 2024)
 
-  Closes #11223
-  Fixes #11222
-  Reported-by: JustAnotherArchivist on github
+- cmdline-opts/_VERSION: provide %VERSION correctly
 
-- tool: remove exclamation marks from error/warning messages
+  ... so that it does not get included verbatim in the output. Fixes a
+  regression shipped in 8.6.0.
 
-- tool: use errorf() for error output
+  Also fix a format mistake in form.md
 
-  Convert a number of fprintf() calls.
+  Closes #13008
 
-- tool: remove newlines from all helpf/notef/warnf/errorf calls
+Stefan Eissing (28 Feb 2024)
 
-  Make voutf() always add one.
+- lib: Curl_read/Curl_write clarifications
 
-  Closes #11226
+  - replace `Curl_read()`, `Curl_write()` and `Curl_nwrite()` to
+    clarify when and at what level they operate
+  - send/recv of transfer related data is now done via
+    `Curl_xfer_send()/Curl_xfer_recv()` which no longer has
+    socket/socketindex as parameter. It decides on the transfer
+    setup of `conn->sockfd` and `conn->writesockfd` on which
+    connection filter chain to operate.
+  - send/recv on a specific connection filter chain is done via
+    `Curl_conn_send()/Curl_conn_recv()` which get the socket index
+    as parameter.
+  - rename `Curl_setup_transfer()` to `Curl_xfer_setup()` for
+    naming consistency
+  - clarify that the special CURLE_AGAIN hangling to return
+    `CURLE_OK` with length 0 only applies to `Curl_xfer_send()`
+    and CURLE_AGAIN is returned by all other send() variants.
+  - fix a bug in websocket `curl_ws_recv()` that mixed up data
+    when it arrived in more than a single chunk (to be made
+    into a sperate PR, also)
 
-- tests/servers.pm: pick unused port number with a server socket
+  Added as documented [in
+  CLIENT-READER.md](https://github.com/curl/curl/blob/5b1f31dfbab8aef467c419c68
+  aa06dc738cb75d4/docs/CLIENT-READERS.md).
 
-  This change replaces the previous method of picking a port number at
-  random to try to start servers on, then retrying up to ten times with
-  new random numbers each time, with a function that creates a server
-  socket on port zero, thereby getting a suitable random port set by the
-  kernel. That server socket is then closed and that port number is used
-  to setup the actual test server on.
+  - old `Curl_buffer_send()` completely replaced by new `Curl_req_send()`
+  - old `Curl_fillreadbuffer()` replaced with `Curl_client_read()`
+  - HTTP chunked uploads are now formatted in a client reader added when
+    needed.
+  - FTP line-end conversions are done in a client reader added when
+    needed.
+  - when sending requests headers, remaining buffer space is filled with
+    body data for sending in "one go". This is independent of the request
+    body size. Resolves #12938 as now small and large requests have the
+    same code path.
 
-  There is a risk that *another* server can be started on the machine in
-  the time gap, but the server verification feature will detect that.
+  Changes done to test cases:
 
-  Closes #11220
+  - test513: now fails before sending request headers as this initial
+    "client read" triggers the setup fault. Behaves now the same as in
+    hyper build
+  - test547, test555, test1620: fix the length check in the lib code to
+    only fail for reads *smaller* than expected. This was a bug in the
+    test code that never triggered in the old implementation.
 
-- RELEASE-NOTES: synced
+  Closes #12969
 
-  bump to 8.2.0
+Daniel Gustafsson (28 Feb 2024)
 
-Alejandro R. Sedeño (31 May 2023)
+- curldown: Fix email address in Copyright
 
-- configure: fix run-compiler for old /bin/sh
+  The curldown conversion accidentally replaced daniel@haxx.se with
+  just daniel.se.  This reverts back to the proper email address in
+  the curldown docs as well as in a few other stray places where it
+  was incorrect (while unrelated to curldown).
 
-  If you try to assign and export on the same line on some older /bin/sh
-  implementations, it complains:
+  Reviewed-by: Daniel Stenberg 
+  Closes: #12997
 
-  ```
-  $ export "NAME=value"
-  NAME=value: is not an identifier
-  ```
+Daniel Stenberg (28 Feb 2024)
 
-  This commit rewrites run-compiler's assignments and exports to work with
-  old /bin/sh, splitting assignment and export into two separate
-  statements, and only quote the value. So now we have:
+- getparam: make --ftp-ssl work again
 
-  ```
-  NAME="value"
-  export NAME
-  ```
+  Follow-up to 9e4e527 which accidentally broke it
 
-  While we're here, make the same change to the two supporting
-  assign+export lines preceeding the script to be consistent with how
-  exports work throughout the rest of configure.ac.
+  Reported-by: Jordan Brown
+  Fixes #13006
+  Closes #13007
 
-  Closes #11228
+- KNOWN_BUGS: IMAPS connection fails with rustls error
 
-Philip Heiduck (31 May 2023)
+  Closes #10457
 
-- circleci: install impacket & wolfssl 5.6.0
+- KNOWN_BUGS: FTPS upload, FileZilla, GnuTLS and close_notify
 
-  Closes #11221
+  Closes #11383
 
-Daniel Stenberg (31 May 2023)
+- KNOWN_BUGS: Implicit FTPS upload timeout
 
-- tool_urlglob: use curl_off_t instead of longs
+  Closes #11720
 
-  To handle more globs better (especially on Windows)
+- KNOWN_BUGS: HTTP/2 prior knowledge over proxy
 
-  Closes #11224
+  Closes #12641
 
-Dan Fandrich (30 May 2023)
+- TODO: build HTTP/3 with OpenSSL and nghttp3 using cmake
 
-- scripts: Fix GHA matrix job detection in cijobs.pl
+  Closes #12988
 
-  The parsing is pretty brittle and it broke detecting some jobs at some
-  point. Also, detect if Windows is used in GHA.
+- TODO: Select signature algorithms
 
-- runtests: abort test run after failure without -a
+  Closes #12982
 
-  This was broken in a recent refactor and test runs would not stop.
+- examples: use present tense in comments
 
-  Follow-up to d4a1b5b6
+  remove "will" and some other word fixes
 
-  Reported-by: Daniel Stenberg
-  Fixes #11225
-  Closes #11227
+  Closes #13003
 
-Version 8.1.2 (30 May 2023)
+- docs: more language cleanups
 
-Daniel Stenberg (30 May 2023)
+  - present tense
+  - avoid bad words
 
-- RELEASE-NOTES: synced
+  Closes #13003
 
-  8.1.2 release
+Daniel Gustafsson (27 Feb 2024)
 
-- THANKS: contributors from 8.1.2
+- setopt: Fix disabling all protocols
 
-- lib1560: verify more scheme guessing
+  When disabling all protocols without enabling any, the resulting
+  set of allowed protocols remained the default set.  Clearing the
+  allowed set before inspecting the passed value from --proto make
+  the set empty even in the errorpath of no protocols enabled.
 
-  - on 2nd level domains
-  - on names without dots
+  Co-authored-by: Dan Fandrich 
+  Reported-by: Dan Fandrich 
+  Reviewed-by: Daniel Stenberg 
+  Closes: #13004
 
-  As mentioned in #11161, "imap.com" will be guessed IMAP
+Andreas Kiefer (27 Feb 2024)
 
-  Closes #11219
+- fopen: fix narrowing conversion warning on 32-bit Android
 
-- page-header: minor wording polish in the URL segment
+  This was fixed in commit 06dc599405f, but came back in commit
+  03cb1ff4d62.
 
-  Closes #11217
+  When building for 32-bit ARM or x86 Android, `st_mode` is defined as
+  `unsigned int` instead of `mode_t`, resulting in a
+  `-Wimplicit-int-conversion` clang warning because `mode_t` is
+  `unsigned short`. Add a cast to silence the warning, but only for
+  32-bit Android builds, because other architectures and platforms are
+  not affected.
 
-- page-header: mention curl version and how to figure out current release
+  Ref: https://android.googlesource.com/platform/bionic/+/refs/tags/ndk-r25c/li
+  bc/include/sys/stat.h#86
+  Closes https://github.com/curl/curl/pull/12998
 
-  Closes #11216
+Stefan Eissing (27 Feb 2024)
 
-- RELEASE-NOTES: synced
+- lib: Curl_read/Curl_write clarifications
 
-- configure: without pkg-config and no custom path, use -lnghttp2
+  - replace `Curl_read()`, `Curl_write()` and `Curl_nwrite()` to
+    clarify when and at what level they operate
+  - send/recv of transfer related data is now done via
+    `Curl_xfer_send()/Curl_xfer_recv()` which no longer has
+    socket/socketindex as parameter. It decides on the transfer
+    setup of `conn->sockfd` and `conn->writesockfd` on which
+    connection filter chain to operate.
+  - send/recv on a specific connection filter chain is done via
+    `Curl_conn_send()/Curl_conn_recv()` which get the socket index
+    as parameter.
+  - rename `Curl_setup_transfer()` to `Curl_xfer_setup()` for
+    naming consistency
+  - clarify that the special CURLE_AGAIN hangling to return
+    `CURLE_OK` with length 0 only applies to `Curl_xfer_send()`
+    and CURLE_AGAIN is returned by all other send() variants.
+  - fix a bug in websocket `curl_ws_recv()` that mixed up data
+    when it arrived in more than a single chunk
 
-  Reported-by: correctmost on github
-  Fixes #11186
-  Closes #11210
+  The method for sending not just raw bytes, but bytes that are either
+  "headers" or "body". The send abstraction stack, to to bottom, now is:
 
-Stefan Eissing (28 May 2023)
+  * `Curl_req_send()`: has parameter to indicate amount of header bytes,
+    buffers all data.
+  * `Curl_xfer_send()`: knows on which socket index to send, returns
+    amount of bytes sent.
+  * `Curl_conn_send()`: called with socket index, returns amount of bytes
+    sent.
 
-- curl: cache the --trace-time value for a second
+  In addition there is `Curl_req_flush()` for writing out all buffered
+  bytes.
 
-  - caches HH:MM:SS computed and reuses it for logging during
-    the same second.
-  - common function for plain log line start formatting
+  `Curl_req_send()` is active for requests without body,
+  `Curl_buffer_send()` still being used for others. This is because the
+  special quirks need to be addressed in future parts:
 
-  Closes #11211
+  * `expect-100` handling
+  * `Curl_fillreadbuffer()` needs to add directly to the new
+    `data->req.sendbuf`
+  * special body handlings, like `chunked` encodings and line end
+    conversions will be moved into something like a Client Reader.
 
-Kev Jackson (28 May 2023)
+  In functions of the pattern `CURLcode xxx_send(..., ssize_t *written)`,
+  replace the `ssize_t` with a `size_t`. It makes no sense to allow for negativ
+  e
+  values as the returned `CURLcode` already specifies error conditions. This
+  allows easier handling of lengths without casting.
 
-- libcurl.m4: remove trailing 'dnl' that causes this to break autoconf
+  Closes #12964
 
-  Closes #11212
+Daniel Stenberg (27 Feb 2024)
 
-Stefan Eissing (26 May 2023)
+- multi: make add_handle free any multi_easy
 
-- http3: send EOF indicator early as possible
+  If the easy handle that is being added to a multi handle has previously
+  been used for curl_easy_perform(), there is a private multi handle here
+  that we can kill off. While it flushes some caches etc for the easy
+  handle would it be used for an easy interface transfer again after being
+  used in the multi stack, this cleanup simplifies behavior and uses less
+  memory.
 
-  - ngtcp2 and quiche implementations relied on the DONE_SEND event
-    to forward the EOF for uploads to the libraries. This often
-    result in a last 0 length EOF data. Tracking the amount of
-    data left to upload allows EOF indication earlier.
-  - refs #11205 where CloudFlare DoH servers did not like to
-    receive the initial upload DATA without EOF and returned
-    a 400 Bad Request
+  Closes #12992
 
-  Reported-by: Sergey Fionov
-  Fixes #11205
-  Closes #11207
+- docs: use present tense
 
-Daniel Stenberg (26 May 2023)
+  avoid "will", detect "will" as a bad word in the CI
 
-- scripts/contri*sh: no longer grep -v ' '
+  Also line wrapped a bunch of paragraphs
 
-  Originally these scripts filtered out names that have no space so that
-  they better avoid nick names not intended for credits. Such names are
-  not too commonly used, plus we now give credit even to those.
+  Closes #13001
 
-  Additionally: non-latin names, like Asian, don't have spaces at all so
-  they were also filtered out and had to be manually added which made it
-  an error-prone operation where Asian names eventually easily fell off by
-  mistake.
+- CURLOPT_SSL_CTX_FUNCTION.md: no promises of lifetime after return
 
-  Closes #11206
+  ... and cleanup other language.
 
-- cf-socket: restore Curl_sock_assign_addr()
+  Closes #12999
 
-  Regression since it was not private. Also used by msh3.c
+Stefan Eissing (27 Feb 2024)
 
-  Follow-up to 8e85764b7bd7f05f5
-  Reported-by: Gisle Vanem
-  Fixes #11202
-  Closes #11204
+- lib: send rework
 
-- RELEASE-NOTES: synced
+  Curl_read/Curl_write clarifications
 
-  Taken down to 8.1.2 now for pending patch release
+  - replace `Curl_read()`, `Curl_write()` and `Curl_nwrite()` to 1clarify
+    when and at what level they operate
 
-- libssh: when keyboard-interactive auth fails, try password
+  - send/recv of transfer related data is now done via
+    `Curl_xfer_send()/Curl_xfer_recv()` which no longer has
+    socket/socketindex as parameter. It decides on the transfer setup of
+    `conn->sockfd` and `conn->writesockfd` on which connection filter
+    chain to operate.
 
-  The state machine had a mistake in that it would not carry on to that
-  next step.
+  - send/recv on a specific connection filter chain is done via
+    `Curl_conn_send()/Curl_conn_recv()` which get the socket index as
+    parameter.
 
-  This also adds a verbose output what methods that are available from the
-  server and renames the macros that change to the next auth methods to
-  try.
+  - rename `Curl_setup_transfer()` to `Curl_xfer_setup()` for naming
+    consistency
 
-  Reported-by: 左潇峰
-  Fixes #11196
-  Closes #11197
+  - clarify that the special CURLE_AGAIN handling to return `CURLE_OK`
+    with length 0 only applies to `Curl_xfer_send()` and CURLE_AGAIN is
+    returned by all other send() variants.
 
-Emanuele Torre (25 May 2023)
+  SingleRequest reshuffling
 
-- configure: fix build with arbitrary CC and LD_LIBRARY_PATH
+  - move functions into request.[ch]
+  - differentiate between reset and free
+  - add Curl_req_done() to perform last actions
+  - add a send `bufq` to SingleRequest for future use in keeping upload data
 
-  Since ./configure and processes that inherit its environment variables
-  are the only callers of the run-compiler script, we can just save the
-  current value of the LD_LIBRARY_PATH and CC variables to another pair of
-  environment variables, and make run-compiler a static script that
-  simply restores CC and LD_LIBRARY_PATH to the saved value, and before
-  running the compiler.
+  Closes #12963
 
-  This avoids having to inject the values of the variables in the script,
-  possibly causing problems if they contains spaces, quotes, and other
-  special characters.
+Daniel Stenberg (26 Feb 2024)
 
-  Also add exports in the script just in case LD_LIBRARY_PATH and CC are
-  not already in the environment.
+- RELEASE-NOTES: synced
 
-  follow-up from 471dab2
+- http_chunks: remove unused 'endptr' variable
 
-  Closes #11182
+  Closes #12996
 
-Daniel Stenberg (25 May 2023)
+Louis Solofrizzo (26 Feb 2024)
 
-- urlapi: remove superfluous host name check
+- lib: initialize output pointers to NULL before calling strto[ff,l,ul]
 
-  ... as it is checked later more proper.
+  In order to make MSAN happy:
 
-  Closes #11195
+      ==2200945==WARNING: MemorySanitizer: use-of-uninitialized-value
+      #0 0x596f3b3ed246 in curlx_strtoofft [...]/libcurl/src/lib/strtoofft.c:23
+  9:11
+      #1 0x596f3b402156 in Curl_httpchunk_read [...]/libcurl/src/lib/http_chunk
+  s.c:149:12
+      #2 0x596f3b348550 in readwrite_data [...]/libcurl/src/lib/transfer.c:607:
+  11
+      [...]
 
-Stefan Eissing (25 May 2023)
+      ==2202041==WARNING: MemorySanitizer: use-of-uninitialized-value
+      #0 0x5a3fab66a72a in Curl_parse_port [...]/libcurl/src/lib/urlapi.c:547:8
+      #1 0x5a3fab650645 in parse_authority [...]/libcurl/src/lib/urlapi.c:796:1
+  2
+      #2 0x5a3fab6740f6 in parseurl [...]/libcurl/src/lib/urlapi.c:1176:16
+      #3 0x5a3fab664fc5 in parseurl_and_replace [...]/libcurl/src/lib/urlapi.c:
+  1342:12
+      [...]
 
-- http2: fix EOF handling on uploads with auth negotiation
+      ==2202320==WARNING: MemorySanitizer: use-of-uninitialized-value
+      #0 0x569076a0d6b0 in ipv4_normalize [...]/libcurl/src/lib/urlapi.c:683:12
+      #1 0x5690769f2820 in parse_authority [...]/libcurl/src/lib/urlapi.c:803:1
+  0
+      #2 0x569076a160f6 in parseurl [...]/libcurl/src/lib/urlapi.c:1176:16
+      #3 0x569076a06fc5 in parseurl_and_replace [...]/libcurl/src/lib/urlapi.c:
+  1342:12
+      [...]
 
-  - doing a POST with `--digest` does an override on the initial request
-    with `Content-Length: 0`, but the http2 filter was unaware of that
-    and expected the originally request body. It did therefore not
-    send a final DATA frame with EOF flag to the server.
-  - The fix overrides any initial notion of post size when the `done_send`
-    event is triggered by the transfer loop, leading to the EOF that
-    is necessary.
-  - refs #11194. The fault did not happen in testing, as Apache httpd
-    never tries to read the request body of the initial request,
-    sends the 401 reply and closes the stream. The server used in the
-    reported issue however tried to read the EOF and timed out on the
-    request.
+  Signed-off-by: Louis Solofrizzo 
+  Closes #12995
 
-  Reported-by: Aleksander Mazur
-  Fixes #11194
-  Cloes #11200
+Stefan Eissing (26 Feb 2024)
 
-Daniel Stenberg (23 May 2023)
+- lib: move client writer into own source
 
-- RELEASE-NOTES: synced
+  Refactoring of the client writer that passes the data to the
+  client/application's callback functions.
 
-  bump to 8.2.0
+  - split out into own source cw-out.[ch] from sendf.c
 
-- lib: remove unused functions, make single-use static
+  - move tempwrite and tempcount from data->state into the context of the
+    client writer
 
-  Closes #11174
+  - redesign the 3 tempwrite dynbufs as a linked list of dynbufs. On
+    paused transfers, this allows to "record" interleaved HEADER/BODY
+    chunks to be "played back" in the same order on unpausing.
 
-- scripts/singleuse.pl: add more API calls
+  - keep the overall size limit of all buffered data to DYN_PAUSE_BUFFER.
+    On exceeding that, return CURLE_TOO_LARGE instead of
+    CURLE_OUT_OF_MEMORY as before.
 
-Christian Hesse (23 May 2023)
+  - add method to be called when a transfer is DONE to allow writing of
+    any data still buffered
 
-- configure: quote the assignments for run-compiler
+  - when paused, record HEADER writes exactly as they come for later
+    playback. HEADERs are documented to be written one-by-one.
 
-  Building for multilib failed, as the compiler command contains an
-  extra argument. That needs quoting.
+  Closes #12898
 
-  Regression from b78ca50cb3dda361f9c1
+- urldata: move authneg bit from conn to Curl_easy
 
-  Fixes #11179
-  Closes #11180
+  - from `conn->bits.authneg` to `data->req.authneg`
+  - this is a property of the request about to be made
+    and not a property of the connection
+  - in multiuse connections, transfer could step on each others
+    toes here potentially.
 
-Daniel Stenberg (23 May 2023)
+  Closes #12949
 
-- misc: fix spelling mistakes
+- c-hyper: add header collection writer in hyper builds
 
-  Reported-by: musvaage on github
-  Fixes #11171
-  Closes #11172
+  Closes #12880
 
-Version 8.1.1 (23 May 2023)
+- http: move headers collecting to writer
 
-Daniel Stenberg (23 May 2023)
+  - add a client writer that does "push" response
+    headers written to the client if the headers api
+    is enabled
+  - remove special handling in sendf.c
+  - needs to be installed very early on connection
+    setup to catch CONNECT response headers
 
-- RELEASE-NOTES: synced
+  Closes #12880
 
-  curl 8.1.1
+- sendf: Curl_client_write(), make passed in buf const
 
-- THANKS: contributors from the 8.1.1 release
+Michał Antoniak (26 Feb 2024)
 
-Dan Fandrich (22 May 2023)
+- lib: remove curl_mimepart object when CURL_DISABLE_MIME
 
-- docs: fix fuzzing documentation link
+  Remove curl_mimepart object from UserDefined structure when
+  CURL_DISABLE_MIME flag is active. Reduce size of UserDefined structure.
 
-  Follow-up to 4c712a1b
+  Also remove unreachable code: when CURL_DISABLE_MIME is set, httpreq can
+  never have HTTPREQ_POST_MIME value and the same goes for the
+  CURL_DISABLE_FORM_API flag and the HTTPREQ_POST_FORM value
 
-- CI: add an Alpine build with MUSL
+  Closes #12948
 
-  MUSL is another libc implementation which has its own unique issues
-  worth testing.
+kpcyrd (26 Feb 2024)
 
-  Ref: #11140
-  Closes #11178
+- rustls: make curl compile with 0.12.0
 
-- runtests: add a missing \n at the end of a log message
+  Closes #12989
 
-correctmost on github (22 May 2023)
+Daniel Stenberg (26 Feb 2024)
 
-- SECURITY-PROCESS.md: link security advisory doc and fix typo
+- strtoofft: fix the overflow check
 
-  Closes #11177
+  ... to not rely on wrapping, since it is an undefined behavior that is
+  not what always might happen. This is in our private strtoff() parser
+  function, used only on platforms without a native version.
 
-Daniel Stenberg (22 May 2023)
+  Reported-by: vulnerabilityspotter on hackerone
+  Closes #12990
 
-- TODO: build curl with Windows Unicode support
+- libssh/libssh2: return error on too big range
 
-  Closes #7229
+  If trying to get the range 0 - 2^63 and the remote file is 2^63 bytes or
+  larger.
 
-- KNOWN_BUGS: hyper memory-leaks
+  Fixes #12983
+  Closes #12984
 
-  Closes #10803
+Scott Talbert (24 Feb 2024)
 
-Stefan Eissing (22 May 2023)
+- setopt: fix check for CURLOPT_PROXY_TLSAUTH_TYPE value
 
-- http/2: unstick uploads
+  Prior to this change CURLOPT_PROXY_TLSAUTH_TYPE would return
+  CURLE_BAD_FUNCTION_ARGUMENT on any type other than NULL. Since there is
+  only one type of TLS auth and it is also the default (SRP) the TLS auth
+  would work anyway.
 
-  - refs #11157 and #11175 where uploads get stuck or lead to RST streams
-  - fixes our h2 send behaviour to continue sending in the nghttp2 session
-    as long as it wants to. This will empty our send buffer as long as
-    the remote stream/connection window allows.
-  - in case the window is exhausted, the data remaining in the send buffer
-    will wait for a WINDOW_UPDATE from the server. Which is a socket event
-    that engages our transfer loop again
-  - the problem in the issue was that we did not exhaust the window, but
-    left data in the sendbuffer and no further socket events did happen.
-    The server was just waiting for us to send more.
-  - relatedly, there was an issue fixed that closing a stream with KEEP_HOLD
-    set kept the transfer from shutting down - as it should have - leading
-    to a timeout.
+  Closes https://github.com/curl/curl/pull/12981
 
-  Closes #11176
+Jay Satiro (24 Feb 2024)
 
-Daniel Stenberg (21 May 2023)
+- mprintf: fix format prefix I32/I64 for windows compilers
 
-- workflows/macos: add a job using gcc + debug + secure transport
+  - Support I32 & I64 (eg: %I64d) for all Win32 builds.
 
-Jay Satiro (21 May 2023)
+  Prior to this change mprintf support for the I format prefix, which is a
+  Microsoft extension, was dependent on the compiler used.
 
-- lib: fix conversion warnings with gcc on macOS
+  When Borland compiler support was removed in fd7ef00f the prefix was
+  then no longer supported for that compiler; however since it's still
+  possible to build with Borland I'm restoring support for the prefix in
+  this way.
 
-Daniel Stenberg (21 May 2023)
+  Reported-by: Paweł Witas
 
-- sectransp.c: make the code c89 compatible
+  Fixes https://github.com/curl/curl/issues/12944
+  Closes https://github.com/curl/curl/pull/12950
 
-  Follow-up to dd2bb485521c2ec713001b3a
+Daniel Stenberg (23 Feb 2024)
 
-  Reported-by: FeignClaims on github
-  Fixes #11155
-  Closes #11159
+- cd2nroff: gen: make `\>` in input to render as plain '>' in output
 
-Emanuele Torre (21 May 2023)
+  The same (copy and pasted) fix/mistake as in gen.pl
 
-- Revert "urlapi: respect CURLU_ALLOW_SPACE and CURLU_NO_AUTHORITY for redirect
-  s"
+- gen: make `\>` in input to render as plain '>' in output
 
-  This reverts commit df6c2f7b544f1f35f2a3e0be11f345affeb6fe9c.
-  (It only keep the test case that checks redirection to an absolute URL
-  without hostname and CURLU_NO_AUTHORITY).
+  Reported-by: Gisle Vanem
+  Fixes #12977
+  Closes #12978
 
-  I originally wanted to make CURLU_ALLOW_SPACE accept spaces in the
-  hostname only because I thought
-  curl_url_set(CURLUPART_URL, CURLU_ALLOW_SPACE) was already accepting
-  them, and they were only not being accepted in the hostname when
-  curl_url_set(CURLUPART_URL) was used for a redirection.
+Fabrice Fontaine (23 Feb 2024)
 
-  That is not actually the case, urlapi never accepted hostnames with
-  spaces, and a hostname with a space in it never makes sense.
-  I probably misread the output of my original test when I they were
-  normally accepted when using CURLU_ALLOW_SPACE, and not redirecting.
+- configure.ac: find libpsl with pkg-config
 
-  Some other URL parsers seems to allow space in the host part of the URL,
-  e.g. both python3's urllib.parse module, and Chromium's javascript URL
-  object allow spaces (chromium percent escapes the spaces with %20),
-  (they also both ignore TABs, and other whitespace characters), but those
-  URLs with spaces in the hostname are useless, neither python3's requests
-  module nor Chromium's window.location can actually use them.
+  Find libpsl with pkg-config to avoid static build failures.
 
-  There is no reason to add support for URLs with spaces in the host,
-  since it was not a inconsistency bug; let's revert that patch before it
-  makes it into release. Sorry about that.
+  Ref: http://autobuild.buildroot.org/results/1fb15e1a99472c403d0d3b1a688902f32
+  e78d002
 
-  I also reverted the extra check for CURLU_NO_AUTHORITY since that does
-  not seem to be necessary, CURLU_NO_AUTHORITY already worked for
-  redirects.
+  Signed-off-by: Fabrice Fontaine 
+  Closes #12947
 
-  Closes #11169
+Daniel Stenberg (23 Feb 2024)
 
-Dan Fandrich (20 May 2023)
+- BUG-BOUNTY.md: clarify that the curl security team decides
 
-- runtests: use the correct fd after select
+  Closes #12975
 
-  The code was using the wrong fd when determining which runner was ready
-  with a response.
+- THANKS: add bug reporter from #740
 
-  Ref: #10818
-  Closes #11160
+  Ref: https://github.com/curl/curl/issues/740
 
-- test425: fix the log directory for the upload
+Stefan Eissing (22 Feb 2024)
 
-  This must be %LOGDIR to let it work with parallel tests.
+- multi: fix multi_sock handling of select_bits
 
-  Ref: #10969
+  - OR the event bitmask to data->state.select_bits instead of overwriting
+    them. They are cleared again on use.
 
-- runtests: handle interrupted reads from IPC pipes
+  Reported-by: 5533asdg on github
+  Fixes #12971
+  Closes #12972
 
-  These can be interrupted by signals, especially SIGINT to shut down, and
-  must be restarted so the IPC call arrives correctly. If the read just
-  returns an error instead, the IPC calling state will go out of sync and
-  a proper shutdown won't happen.
+Daniel Stenberg (22 Feb 2024)
 
-  Ref: #10818
+- curlver: bump to 8.7.0 for next release
 
-Stefan Eissing (20 May 2023)
+- RELEASE-NOTES: synced
 
-- http2: upload improvements
+- write-out: add '%{proxy_used}'
 
-  Make send buffer smaller to have progress and "upload done" reporting
-  closer to reality. Fix handling of send "drain" condition to no longer
-  trigger once the transfer loop reports it is done sending. Also do not
-  trigger the send "drain" on RST streams.
+  Returns 1 if the previous transfer used a proxy, otherwise 0. Useful to
+  for example determine if a `NOPROXY` pattern matched the hostname or
+  not.
 
-  Background:
-  - a upload stall was reported in #11157 that timed out
-  - test_07_33a reproduces a problem with such a stall if the
-    server 404s the request and RSTs the stream.
-  - test_07_33b verifies a successful PUT, using the parameters
-    from #11157 and checks success
+  Extended test 970 and 972
 
-  Ref: #11157
-  Closes #11165
+- CURLINFO_USED_PROXY: return bool whether the proxy was used
 
-- http2: increase stream window size to 10 MB
+  Adds test536 to verify
 
-  Reported-by: pandada8 on github
+  Closes #12719
 
-  Fixes #11162
-  Closes #11167
+- sha512_256: remove the cast macro, minor language/format edits
 
-Daniel Stenberg (20 May 2023)
+  Follow-up to cbe41d151d6a100c
 
-- lib: rename struct 'http_req' to 'httpreq'
+  Closes #12966
 
-  Because FreeBSD 14 kidnapped the name.
-  Ref: https://bugs.freebsd.org/bugzilla/show_bug.cgi?id=271526
+Stefan Eissing (20 Feb 2024)
 
-  Fixes #11163
-  Closes #11164
+- DoH: add trace configuration
 
-Viktor Szakats (20 May 2023)
+  - refs #12397 where it is dicussed how to en-/disable verbose output
+    of DoH operations
+  - introducing `struct curl_trc_feat` to track a curl feature for
+    tracing
+  - adding `data->state.feat` optionally pointing to the feature a
+    transfer belongs to
+  - adding trace functions and verbosity checks on features
+  - using trace feature in DoH code
+  - documenting `doh` as feature for `--trace-config`
 
-- cmake: avoid `list(PREPEND)` for compatibility
+  Closes #12411
 
-  `list(PREPEND)` requires CMake v3.15, our minimum is v3.7.
+- websocket: fix curl_ws_recv()
 
-  Ref: https://cmake.org/cmake/help/latest/command/list.html#prepend
+  - when data arrived in several chunks, the collection into
+    the passed buffer always started at offset 0, overwriting
+    the data already there.
 
-  Regression from 1e3319a167d2f32d295603167486e9e88af9bb4e
+  adding test_20_07 to verify fix
 
-  Reported-by: Keitagit-kun on Github
-  Fixes #11141
-  Closes #11144
+  - debug environment var CURL_WS_CHUNK_SIZE can be used to
+    influence the buffer chunk size used for en-/decoding.
 
-Daniel Stenberg (19 May 2023)
+  Closes #12945
 
-- RELEASE-NOTES: synced
+Evgeny Grin (Karlson2k) (20 Feb 2024)
 
-Stefan Eissing (19 May 2023)
+- digest: support SHA-512/256
 
-- ngtcp2: proper handling of uint64_t when adjusting send buffer
+  Also fix the tests. New implementation tested with GNU libmicrohttpd.
+  The new numbers in tests are real SHA-512/256 numbers (not just some
+  random ;) numbers ).
 
-  Fixes #11149
-  Closes #11153
+- tests: add SHA-512/256 unit test
 
-- ngtcp2: fix compiler warning about possible null-deref
+- SHA-512/256: implement hash algorithm
 
-  - compiler analyzer did not include the call context for this
-    static function where the condition had already been checked.
-  - eleminating the problem by making stream a call parameter
+  Closes #12897
 
-  Fixes #11147
-  Closes #11151
+- curl_setup.h: add curl_uint64_t internal type
 
-Emanuele Torre (19 May 2023)
+  The unsigned version of curl_off_t basically
 
-- docs: document that curl_url_cleanup(NULL) is a safe no-op
+Daniel Stenberg (20 Feb 2024)
 
-  This has always been the case, but it was not documented.
+- docs: dist curl*.1 and install without perl
 
-  The paragraph was copied verbatim from curl_easy_cleanup.3
+  Drop docs/mk-ca-bundle.1 from the tarball. It can be generated at will.
 
-  Closes #11150
+  Closes #12959
+  Fixes #12921
+  Reported-by: Michael Forney
 
-Antoine Pitrou (19 May 2023)
+Stefan Eissing (20 Feb 2024)
 
-- select: avoid returning an error on EINTR from select() or poll()
+- OpenSSL QUIC: adapt to v3.3.x
 
-  This was already done for the poll() and select() calls
-  made directly from Curl_poll(), but was missed in
-  Curl_wait_ms(), which is called when there are no fds
-  to wait on.
+  - set our idle timeout as transport parameter
+  - query negotiated idle timeout for connection alive checks
+  - query number of available bidi streams on a connection
+  - use write_ex2 with SSL_WRITE_FLAG_CONCLUDE to signal
+    EOF on last chunk write, so stream close does not
+    require an additional QUIC packet
 
-  Fixes #11135
-  Closes #11143
+  Closes #12933
 
-Daniel Stenberg (19 May 2023)
+Ramiro Garcia (19 Feb 2024)
 
-- vquic.c: make recvfrom_packets static, avoid compiler warning
+- MANUAL.md: fix typo
 
-  warning: no previous prototype for 'recvfrom_packets'
+  Closes #12965
 
-  Reported-by: Keitagit-kun on github
-  Fixes #11146
-  Closes #11148
+Daniel Stenberg (19 Feb 2024)
 
-- urlapi: allow numerical parts in the host name
+- BINDINGS: add mcurl, the python binding
 
-  It can only be an IPv4 address if all parts are all digits and no more than
-  four parts, otherwise it is a host name. Even slightly wrong IPv4 will now be
-  passed through as a host name.
+  Ref: #12956
+  Closes #12962
 
-  Regression from 17a15d88467 shipped in 8.1.0
+- mk-ca-bundle.md: cleanups and polish
 
-  Extended test 1560 accordingly.
+  Closes #12958
 
-  Reported-by: Pavel Kalyugin
-  Fixes #11129
-  Closes #11131
+- spellcheck.yml: remove .1/.3 handling, clean all man page .md files
 
-Emilio Cobos Álvarez (19 May 2023)
+  Since we generate all .1 and .3 files from markdown now, we can limit
+  the spellcheck to the markdown versions only.
 
-- http2: double http request parser max line length
+  Closes #12960
 
-  This works around #11138, by doubling the limit, and should be a
-  relatively safe fix.
+- libcurl-docs: cleanups
 
-  Ideally the buffer would grow as needed and there would be no need for a
-  limit? But that might be follow-up material.
+   CURLMOPT_SOCKETDATA.md: fix typo
+   CURLMOPT_TIMERDATA.md: fix typo
+   CURLOPT_COOKIELIST.m: quote strings
+   CURLOPT_PREREQFUNCTION.md: quote variable names
+   CURLOPT_TCP_NODELAY.md: rephrased to please spell checker
+   CURLOPT_WILDCARDMATCH.md: rephrased
+   libcurl-tutorial.md: use correct option name
+   curl_global_init_mem.md: quote headers
+   curl_easy_getinfo.md: use correct symbol names in headers
+   curl_global_trace.md: quote some headers
+   curl_ws_meta.md: quote struct field names
+   libcurl-env.md: quote headers
 
-  Fixes #11138
-  Closes #11139
+- cd2nroff: remove backticks from titles
 
-Emanuele Torre (18 May 2023)
+- RELEASE-NOTES: synced
 
-- configure: fix --help alignment
+Stefan Eissing (18 Feb 2024)
 
-  AC_ARG_ENABLE seems to only trim off whitespace from the start and end
-  of its help-string argument, while prepending two spaces of indentation
-  to all lines.
+- http_chunks: fix the accounting of consumed bytes
 
-  This means that the two spaces of indentation between the --enable-rtsp
-  and the --disable-rtsp line were not removed causing ./configure --help
-  to print:
+  Prior to this change chunks were handled correctly although in verbose
+  mode libcurl could incorrectly warn of "Leftovers after chunking" even
+  if there were none.
 
-    Optional Features:
-      [...]
-      --enable-rtsp           Enable RTSP support
-        --disable-rtsp          Disable RTSP support
+  Reported-by: Michael Kaufmann
 
-  I removed the indentation to fix the issue, now it prints:
+  Fixes https://github.com/curl/curl/issues/12937
+  Closes https://github.com/curl/curl/pull/12939
 
-    Optional Features:
-      [...]
-      --enable-rtsp           Enable RTSP support
-      --disable-rtsp          Disable RTSP support
+- file: use xfer buf for file:// transfers
 
-  The --enable-hsts and --disable-hsts lines had the same problems, and
-  have been fixed too.
+  - For file:// transfers use the multi handle's transfer buffer for
+    up- and downloads.
 
-  Closes #11142
+  Prior to this change a6c9a33 (precedes 8.6.0) changed the file://
+  transfers to use a smaller stack based buffer, and that caused a
+  significant performance decrease in Windows.
 
-Deal(一线灵) (18 May 2023)
+  Bug: https://github.com/curl/curl/issues/12750#issuecomment-1920103086
+  Reported-by: edmcln@users.noreply.github.com
 
-- cmake: repair cross compiling
+  Closes https://github.com/curl/curl/pull/12932
 
-  It cannot *run* code for testing purposes when cross-compiling.
+Karthikdasari0423 (18 Feb 2024)
 
-  Closes #11130
+- HTTP3.md: always run nghttp3 submodule init
 
-Daniel Stenberg (18 May 2023)
+  - For consistency change all 'build nghttp3' commands to run submodule
+    init after cloning, even if the branch does not have submodules.
 
-- configure: generate a script to run the compiler
+  Follow-up to 5a4b2f93 and 4f794558.
 
-  in the CURL_RUN_IFELSE macro, with LD_LIBRARY_PATH set to the value of
-  the configure invoke, and not the value that might be used later,
-  intended for the execution of the output the compiler ouputs.
+  Closes https://github.com/curl/curl/pull/12928
 
-  For example when the compiler uses the same library (like libz) that
-  configure checks for.
+LeeRiva (18 Feb 2024)
 
-  Reported-by: Jonas Bülow
-  Fixes #11114
-  Closes #11120
+- CURLOPT_POSTQUOTE.md: fix typo
 
-Stefan Eissing (18 May 2023)
+  Closes https://github.com/curl/curl/pull/12926
 
-- cf-socket: completely remove the disabled USE_RECV_BEFORE_SEND_WORKAROUND
+Evgeny Grin (Karlson2k) (18 Feb 2024)
 
-  Closes #11118
+- checksrc.pl: fix handling .checksrc with CRLF
 
-Emanuele Torre (18 May 2023)
+  - When parsing .checksrc chomp the (CR)LF line ending.
 
-- urlapi: respect CURLU_ALLOW_SPACE and CURLU_NO_AUTHORITY for redirects
+  Prior to this change on Windows checksrc.pl would not process the
+  symbols in .checksrc properly, since many git repos in Windows use auto
+  crlf to check out files with CRLF line endings.
 
-  curl_url_set(uh, CURLUPART_URL, redirurl, flags)  was not respecing
-  CURLU_ALLOW_SPACE and CURLU_NO_AUTHORITY in the host part of redirurl
-  when redirecting to an absolute URL.
+  Closes https://github.com/curl/curl/pull/12924
 
-  Closes #11136
+Richard Levitte (18 Feb 2024)
 
-Colin Cross (18 May 2023)
+- cmake: fix install for older CMake versions
 
-- hostip: move easy_lock.h include above curl_memory.h
+  - Generate the docs install list by using a foreach loop instead of
+    LIST:TRANSFORM since older CMake can't handle the latter.
 
-  Similar to #9561, move easy_lock.h above curl_memory.h to fix building
-  against musl libc.
+  Reported-by: Dan Fandrich
 
-  Closes #11140
+  Fixes https://github.com/curl/curl/issues/12920
+  Closes https://github.com/curl/curl/pull/12922
 
-Hind Montassif (18 May 2023)
+Stefan Eissing (16 Feb 2024)
 
-- curl_easy_getinfo: clarify on return data types
+- vtls: fix tls proxy peer verification
 
-  Closes #11126
+  - When verifying a proxy certificate for an ip address, use the correct
+    ip family.
 
-Emanuele Torre (18 May 2023)
+  Prior to this change the "connection" ip family was used, which was not
+  necessarily the same.
 
-- checksrc: disallow spaces before labels
+  Reported-by: HsiehYuho@users.noreply.github.com
 
-  Out of 415 labels throughout the code base, 86 of those labels were
-  not at the start of the line. Which means labels always at the start of
-  the line is the favoured style overall with 329 instances.
+  Fixes https://github.com/curl/curl/issues/12831
+  Closes https://github.com/curl/curl/pull/12931
 
-  Out of the 86 labels not at the start of the line:
-  * 75 were indented with the same indentation level of the following line
-  * 8 were indented with exactly one space
-  * 2 were indented with one fewer indentation level then the following
-    line
-  * 1 was indented with the indentation level of the following line minus
-    three space (probably unintentional)
+Dan Fandrich (15 Feb 2024)
 
-  Co-Authored-By: Viktor Szakats
+- CI: Bump the Circle CI base Ubuntu image to the latest 20.04
 
-  Closes #11134
+  The previous ones are going to be removed soon, plus the new ones
+  include all the fixes since then.
 
-Daniel Stenberg (18 May 2023)
+Jay Satiro (13 Feb 2024)
 
-- cookie: update the comment on cookie length and size limits
+- transfer: improve Windows SO_SNDBUF update limit
 
-  To refer to the proper cookie RFC and the upcoming RFC refresh.
+  - Change the 1 second SO_SNDBUF update limit from per transfer to per
+    connection.
 
-  Closes #11127
+  Prior to this change many transfers over the same connection could cause
+  many SO_SNDBUF updates made to that connection per second, which was
+  unnecessary.
 
-- url: provide better error message when URLs fail to parse
+  Closes https://github.com/curl/curl/pull/12911
 
-  By providing the URL API error message into the error message.
+- schannel: fix hang on unexpected server close
 
-  Ref: #11129
-  Closes #11137
+  - Treat TLS connection close (either due to a close_notify from the
+    server or just closed due to receiving 0) as pending data.
 
-- RELEASE-NOTES: synced
+  This is because in some cases schannel_recv knows the connection is
+  closed but has to return actual pending data so it can't return 0 or an
+  error to indicate no more data. In this case schannel_recv must be
+  called again, which only happens if readwrite_data sees that there is
+  still pending data.
 
-  bumped to 8.1.1
+  Prior to this change if the total size of the body that libcurl expected
+  to receive from the server was unknown then it was possible under some
+  network conditions that libcurl would hang waiting to receive more data,
+  when in fact a close_notify alert indicating no more data would be sent
+  was already processed.
 
-Jon Rumsey (18 May 2023)
+  Fixes https://github.com/curl/curl/issues/12894
+  Closes https://github.com/curl/curl/pull/12910
 
-- os400: update chkstrings.c
+Daniel Stenberg (10 Feb 2024)
 
-  Compensate changes for recent changes to urldata.h to reclassify
-  STRING_AWS_SIGV4.
+- KNOWN_BUGS: FTP upload fails if remebered dir is deleted
 
-  Fixes #11132
-  Closes #11133
+  Closes #12181
+  Closes #12923
 
-Version 8.1.0 (17 May 2023)
+Michał Antoniak (10 Feb 2024)
 
-Daniel Stenberg (17 May 2023)
+- mbedtls: use mbedtls_ssl_conf_{min|max}_tls_version
 
-- RELEASE-NOTES: synced
+  ... instead of the deprecated mbedtls_ssl_conf_{min|max}_version
 
-- THANKS: contributors from the 8.1.0 release
+  Closes #12905
 
-- hostip: include easy_lock.h before using GLOBAL_INIT_IS_THREADSAFE
+Dan Fandrich (9 Feb 2024)
 
-  Since that header file is the only place that define can be defined.
+- CI: bump to actions/cache@v4 to avoid warning
 
-  Reported-by: Marc Deslauriers
+Evgeny Grin (Karlson2k) (9 Feb 2024)
 
-  Follow-up to 13718030ad4b3209
+- test1165: improve pattern matching
 
-  Closes #11121
+  * Fix excluded digits at the end of the symbols ('CURL_DISABLE_POP3'
+    was checked as 'CURL_DISABLE_POP')
 
-Thomas Taylor (16 May 2023)
+  Closes #12903
 
-- aws-sigv4.d: fix region identifier in example
+Dan Fandrich (9 Feb 2024)
 
-  Closes #11117
+- scripts: Fix cijobs.pl for Azure and GHA
 
-Philip Heiduck (15 May 2023)
+  The spacing in the yaml files changed.
 
-- mlc_config.json: remove this linkcheck CI job config file
+Daniel Stenberg (9 Feb 2024)
 
-  Closes #11113
+- RELEASE-NOTES: synced
 
-Daniel Silverstone (15 May 2023)
+- TODO: use pkg-config to find libpsl
 
-- ssh: Add support for libssh2 read timeout
+  Closes #12919
 
-  Hook the new (1.11.0 or newer) libssh2 support for setting a read timeout
-  into the SERVER_RESPONSE_TIMEOUT option.  With this done, clients can use
-  the standard curl response timeout setting to also control the time that
-  libssh2 will wait for packets from a slow server.  This is necessary to
-  enable use of very slow SFTP servers.
+- TODO: avoid nroff
 
-  Signed-off-by: Daniel Silverstone 
+  Instead of adjusting roffit, skip the nroff step.
 
-  Closes #10965
+  Closes #12919
 
-Osama Albahrani (14 May 2023)
+Dan Fandrich (9 Feb 2024)
 
-- GIT-INFO: add --with-openssl
+- Revert "CI: run Circle macOS builds on x86 for now"
 
-  Closes #11110
+  This reverts commit 2683de3078eadc86d9b182e7417f4ee75a247e2c.
+  ARM resources are now available in Circle CI, so run these builds on ARM
+  again. This platform needs explicit paths set to libpsl and its
+  dependency icu4c.
 
-Daniel Stenberg (13 May 2023)
+  Follow-up to 2683de30
 
-- RELEASE-NOTES: synced
+  Closes #12635
 
-Marcel Raad (13 May 2023)
+Viktor Szakats (9 Feb 2024)
 
-- md(4|5): don't use deprecated iOS functions
+- cmake: add warning for using TLS libraries without 1.3 support
 
-  They are marked as deprecated in iOS 13.0, which might result in
-  warnings-as-errors.
+  Closes #12900
 
-  Also, use `*_MIN_REQUIRED` instead of `*_MIN_ALLOWED`, which seems to
-  be what's currently used.
+Daniel Stenberg (9 Feb 2024)
 
-  Bug: https://github.com/curl/curl/issues/11098
-  Closes https://github.com/curl/curl/pull/11102
+- configure: add warning for using TLS libraries without 1.3 support
 
-- md4: only build when used
+  Closes #12900
 
-  Its only usage in curl_ntlm_core.c is guarded by `USE_CURL_NTLM_CORE`,
-  so let's use this here too.
+Michał Antoniak (9 Feb 2024)
 
-  Ref: https://github.com/curl/curl/issues/11098
-  Closes https://github.com/curl/curl/pull/11102
+- mbedtls: fix building when MBEDTLS_X509_REMOVE_INFO flag is defined
 
-Vítor Galvão (12 May 2023)
+  Closes #12904
 
-- write-out.d: Use response_code in example
+Stefan Eissing (9 Feb 2024)
 
-  Closes #11107
+- ftp: fix socket wait activity in ftp_domore_getsock
 
-Shohei Maeda (12 May 2023)
+  - when waiting on the data connection, always add the control socket to
+    the pollset on state STOP or let the pingpong add the socket according
+    to its needs.
 
-- url: fix null dispname for --connect-to option
+  Reported-by: Fabian Vogt
+  Fixes #12901
+  Closes #12913
 
-  Closes #11106
+Daniel Stenberg (9 Feb 2024)
 
-Daniel Stenberg (12 May 2023)
+- dist: make sure the http tests are in the tarball
 
-- test2306: verify getting a second response with folded headers
+  Fixes #12914
+  Reported-by: Fabian Vogt
+  Closes #12917
 
-  Reproduces the isue #11101 and verifies the fix.
+Stefan Eissing (9 Feb 2024)
 
-  Verifies a17b2a503f
+- multi: add xfer_buf to multi handle
 
-- headers: clear (possibly) lingering pointer in init
+  - can be borrowed by transfer during recv-write operation
+  - needs to be released before borrowing again
+  - adjustis size to `data->set.buffer_size`
+  - used in transfer.c readwrite_data()
 
-  The "prevhead" pointer is used for the headers storage but was not
-  cleared correctly in init, which made it possible to act up when a
-  handle is reused.
+  Closes #12805
 
-  Reported-by: Steve Herrell
-  Fixes #11101
-  Closes #11103
+Daniel Stenberg (9 Feb 2024)
 
-- RELEASE-NOTES: synced
+- write-out.md: clarify error handling details
 
-- ngtcp2: use 0.15.0
+  - it gets used even if the transfer fails
 
-  - nghttp3 0.11.0
-  - nghttp2 1.53.0
+  - it does not cause error to be returned even if it fails
 
-  Adapt to new API calls
+  Closes #12909
 
-  Closes #11031
+Stefan Eissing (8 Feb 2024)
 
-Jay Satiro (10 May 2023)
+- ftp: do lineend conversions in client writer
 
-- openssl: fix indent
+  - remove the ftp special handling from sendf.c
+  - let ftp_do() add a client writer that does
+    the linened conversions
+  - change the lineend conversion to no longer
+    modify the passed buffer, but write smaller
+    chunks to the next cwriter instead. The
+    inefficiency of this will be mitigated once
+    we add output buffering for all client writes.
 
-Daniel Stenberg (10 May 2023)
+  Closes #12878
 
-- CURLOPT_DNS_CACHE_TIMEOUT.3: fix spelling
+- ftp: tracing improvements
 
-  Follow-up to 9ed7d56e044f5aa1b29
+  - trace socketindex for connection filters when not the first
+  - trace socket fd in tcp
+  - trace pollset adjusts in vtls
 
-  Closes #11096
+  Closes #12902
 
-- hostip: use time_t for storing oldest DNS entry
+Karthikdasari0423 (8 Feb 2024)
 
-  Theoretically, the oldest time could overflow an int. In practice that
-  won't happen, but let's do this to please analyzers.
+- HTTP3.md: adjust the OpenSSL QUIC install instructions
 
-  Follow-up to 9ed7d56e044f5aa1b2928ccde6245d0
+  tried installing with old steps but failed
+  tried with newly added setps and able to build
+  ```
+  root@ubuntu:~/curl# ./src/curl -V
+  /root/curl/src/.libs/curl: /lib/x86_64-linux-gnu/libssl.so.3: version `OPENSS
+  L_3.2.0' not found (required by /root/curl/lib/.libs/libcurl.so.4)
+  root@ubuntu:~/curl#
+  ```
+  ```
+  root@ubuntu:~/curl# ./src/curl -V
+  curl 8.6.1-DEV (x86_64-pc-linux-gnu) libcurl/8.6.1-DEV OpenSSL/3.2.0 zlib/1.2
+  .11 brotli/1.0.9 libpsl/0.21.0 nghttp3/1.1.0 OpenLDAP/2.5.16
+  Release-Date: [unreleased]
+  Protocols: dict file ftp ftps gopher gophers http https imap imaps ipfs ipns 
+  ldap ldaps mqtt pop3 pop3s rtsp smb smbs smtp smtps telnet tftp
+  Features: alt-svc AsynchDNS brotli HSTS HTTP3 HTTPS-proxy IPv6 Largefile libz
+   NTLM PSL SSL threadsafe TLS-SRP UnixSockets
+  root@ubuntu:~/curl#
+  ```
 
-  Pointed out by Coverity.
-  Closes #11094
+  Closes #12896
 
-- http: free the url before storing a new copy
+Daniel Stenberg (8 Feb 2024)
 
-  To avoid a memory-leak.
+- TODO: align the TOC with the header
 
-  Reported-by: Hiroki Kurosawa
+- docs: make sure curl.1 is included in dist tarballs
 
-  Closes #11093
+  Ref: https://github.com/curl/curl/issues/12832#issuecomment-1933271873
 
-- compressed.d: clarify the words on "not notifying headers"
+  Closes #12892
 
-  Reported-by: Dylan Anthony
-  Fixes #11091
-  Closes #11092
+Karthikdasari0423 (8 Feb 2024)
 
-- libssh2: free fingerprint better
+- HTTP3.md: remove quiche word in Openssl 3.2
 
-  Reported-by: Wei Chong Tan
-  Closes #11088
+  Closes #12893
 
-- CURLOPT_IPRESOLVE.3: clarify that this for host names, not IP addresses
+Daniel Stenberg (7 Feb 2024)
 
-  Reported-by: Harry Sintonen
-  Closes #11087
+- curl: when allocating variables, add the name into the struct
 
-- hostip: enforce a maximum DNS cache size independent of timeout value
+  This saves the name from being an extra separate allocation.
 
-  To reduce the damage an application can cause if using -1 or other
-  ridiculous timeout values and letting the cache live long times.
+  Closes #12891
 
-  The maximum number of entries in the DNS cache is now totally
-  arbitrarily and hard-coded set to 29999.
+- lib582: remove code causing warning that is never run
 
-  Closes #11084
+  The previous realloc code in this code could trigger a compiler warning,
+  but since that code path cannot happen in normal circumstances it now
+  instead exits with an error message there.
 
-- hostip: store dns timeout as 'int'
+  Ref: #12887
+  Closes #12890
 
-  ... because it set and held as an 'int' elsewhere and can never be
-  larger.
+Stefan Eissing (7 Feb 2024)
 
-- RELEASE-NOTES: synced
+- vtls: revert "receive max buffer" + add test case
 
-- tool_operate: refuse (--data or --form) and --continue-at combo
+  - add test_05_04 for requests using http/1.0, http/1.1 and h2 against an
+    Apache resource that does an unclean TLS shutdown.
+  - revert special workarund in openssl.c for suppressing shutdown errors
+    on multiplexed connections
+  - vlts.c restore to its state before 9a90c9dd64d2f03601833a70786d485851bd1b53
 
-  libcurl assumes that a --continue-at resumption is done to continue an
-  upload using the read callback and neither --data nor --form use
-  that and thus won't do what the user wants. Whatever the user wants
-  with this strange combination.
+  Fixes #12885
+  Fixes #12844
 
-  Add test 426 to verify.
+  Closes #12848
 
-  Reported-by: Smackd0wn on github
-  Fixes #11081
-  Closes #11083
+Daniel Stenberg (7 Feb 2024)
 
-- transfer: refuse POSTFIELDS + RESUME_FROM combo
+- tests: support setting/using blank content env variables
 
-  The code assumes that such a resume is wanting to continue an upload
-  using the read callback, and since POSTFIELDS is done without callback
-  libcurl will just misbehave.
+  - test450: remove --config from the keywords
+  - test2080: change return code
+  - test428: add --config as a keyword
+  - test428: disable on Windows due to CI problems
 
-  This combo will make the transfer fail with CURLE_BAD_FUNCTION_ARGUMENT
-  with an explanation in the error message.
+- curl: exit on config file parser errors
 
-  Reported-by: Smackd0wn on github
-  Fixes #11081
-  Closes #11083
+  Like when trying to import an environment variable that does not exist.
 
-- ipv4.d/ipv6.d: they are "mutex", not "boolean"
+  Also fix a bug for reading env variables when there is a default value
+  set.
 
-  ... which for example means they do not have --no-* versions.
+  Bug: https://curl.se/mail/archive-2024-02/0008.html
+  Reported-by: Brett Buddin
 
-  Reported-by: Harry Sintonen
-  Fixes #11085
-  Closes #11086
+  Add test 462 to verify.
 
-- docs/SECURITY-ADVISORY.md: how to write a curl security advisory
+  Closes #12862
 
-  Closes #11080
+Daniel Szmulewicz (7 Feb 2024)
 
-nobedee on github (5 May 2023)
+- CURLOPT_WRITEFUNCTION.md: typo fix
 
-- MANUAL.md: add dict example for looking up a single definition
+  The maximum amount of body data that is  passed to the write
+  callback is defined in the curl.h header file
 
-  Closes #11077
+  Closes #12889
 
-Dan Fandrich (5 May 2023)
+Daniel Stenberg (7 Feb 2024)
 
-- runtests: fix -c option when run with valgrind
+- lib: convert Curl_get_line to use dynbuf
 
-  The curl binary argument wasn't being quoted properly. This seems to
-  have broken at some point after quoting was added in commit 606b29fe.
+  Create the line in a dynbuf. Aborts the reading of the file on
+  errors. Avoids having to always allocate maximum amount from the
+  start. Avoids direct malloc.
 
-  Reported-by: Daniel Stenberg
-  Ref: #11073
-  Fixes #11074
-  Closes #11076
+  Closes #12846
 
-- runtests: support creating more than one runner process
+- KNOWN_BUGS: unicode on Windows
 
-  The controller currently only creates and uses one, but more are now
-  possible.
+  Closes #11461
+  Closes #12231
+  Closes #12883
 
-  Ref: #10818
+- tool_operate: change precedence of server Retry-After time
 
-- runtests: spawn a new process for the test runner
+  - When calculating the retry time, no longer allow a server's requested
+    Retry-After time to take precedence over a longer retry time (either
+    default algorithmic or user-specified).
 
-  When the -j option is given, a new process is spawned in which the test
-  programs are run and from which test servers are started. Only one
-  process can be started at once, but this is sufficient to test that the
-  infrastructure can isolate those functions in a new task. There should
-  be no visible difference between the two modes at the moment.
+  Prior to this change the server's Retry-After time took precedence over
+  curl's retry time in all cases, but that's not always practical for
+  short Retry-After times depending on how busy the server is.
 
-  Ref: #10818
-  Closes #11064
+  Bug: https://curl.se/mail/archive-2024-01/0022.html
+  Reported-by: Dirk Hünniger
 
-- runtests: turn singletest() into a state machine
+  Closes https://github.com/curl/curl/pull/12871
 
-  This allows it to run in a non-blocking manner.
+- cmdline-docs: quote and angle bracket cleanup
 
-  Ref: #10818
+  - make sure angle brackets are escaped
+  - remove a lot of superfluous double quotes
+  - replace several double quotes with backticks
 
-- runtests: change runner interface to be asynchronous
+  To make nicer-looking markdown.
 
-  Program arguments are marshalled and then written to the end of a pipe
-  which is later read from and the arguments unmarshalled before the
-  desired function is called normally.  The function return values are
-  then marshalled and written into another pipe when is later read from
-  and unmarshalled before being returned to the caller.
+  Closes #12884
 
-  The implementation is currently blocking but can be made non-blocking
-  without any changes to the API.  This allows calling multiple runners
-  without blocking in the future.
+- badwords: use hostname, not host name
 
-  Ref: #10818
+  and username, filename - consistently. Fixed the patterns in
+  badwords.txt to catch these.
 
-- runtests: call citest_finishtest in singletest
+  Closes #12888
 
-  This is where citest_starttest is called.
+Viktor Szakats (6 Feb 2024)
 
-  Ref: #10818
+- cmake: fix function description in comment [ci skip]
 
-- runtests: add a runner initialization function
+  Closes #12879
 
-  This sets up the runner environment to start running tests.
+Daniel Stenberg (6 Feb 2024)
 
-  Ref: #10818
+- header.md: remove backslash, make nicer markdown
 
-- runtests: remove directory from server filename variables
+  - remove a leftover backslash before a dash
+  - use backticks for "code" strings
 
-  There will soon be multiple log directories so the paths will no longer
-  be static in runtests.pl. Also, get rid of $SERVER2IN which was not
-  used.
+  Closes #12877
 
-  Ref: #10818
+- docs: add mk-ca-bundle.1 to dist
 
-- runtests: reduce package exports after refactoring
+  ... which also makes it get built. But don't build this or curl-config.1
+  if build docs is disabled.
 
-  Some recent refactoring made these export no longer necessary. Also,
-  stop displaying the Unix socket paths at startup since there will soon
-  be many of them and they're not that interesting.
+  Closes #12875
 
-  Ref: #10818
+Stefan Eissing (6 Feb 2024)
 
-- runtests: use a function to obtain $LOGDIR for a test
+- https-proxy: use IP address and cert with ip in alt names
 
-  This will no longer be static soon.
+  - improve info logging when peer verification fails to indicate
+    if DNS name or ip address has been tried to match
+  - add test case for contacting https proxy with ip address
+  - add pytest env check on loaded credentials and re-issue
+    when they are no longer valid
+  - disable proxy ip address test for bearssl, since not supported there
 
-  Ref: #10818
+  Ref: #12831
+  Closes #12838
 
-Jay Satiro (5 May 2023)
+Jiawen Geng (6 Feb 2024)
 
-- tool_cb_hdr: Fix 'Location:' formatting for early VTE terminals
+- docs: add necessary setup for nghttp3
 
-  - Disable hyperlink formatting for the 'Location:' header value in VTE
-    0.48.1 and earlier, since it is buggy in some of those versions.
+  Now nghttp3 has submodules
+  https://github.com/ngtcp2/nghttp3/blob/main/.gitmodules
 
-  Prior to this change those terminals may show the location header value
-  as gibberish or show it twice.
+  Closes #12859
 
-  Ref: https://gist.github.com/egmontkob/eb114294efbcd5adb1944c9f3cb5feda#backw
-  ard-compatibility
+Peter Krefting (6 Feb 2024)
 
-  Fixes https://github.com/curl/curl/issues/10428
-  Closes https://github.com/curl/curl/pull/11071
+- version: allow building with ancient libpsl
 
-François Michel (3 May 2023)
+  The psl_check_version_number() API was added in libpsl 0.11.0. CentOS 7
+  ships with version 0.7.0 which lacks this API. Revert to using the older
+  versioning API if we detect an old libpsl version.
 
-- quiche: disable pacing while pacing is not actually performed
+  Follow-up to 72bd88adde0e8cf6e63644a7d6df1da01a399db4
+  Bug: https://curl.se/mail/archive-2024-02/0004.html
+  Reported-by: Scott Mutter
+  Closes #12872
 
-  Closes #11068
+Daniel Stenberg (6 Feb 2024)
 
-Daniel Stenberg (2 May 2023)
+- TODO: Support latest rustls
 
-- easy_cleanup: require a "good" handle to act
+  Closes #12737
+  Closes #12874
 
-  By insisting that the passed in handle is "good" (the magic number is
-  intact), this can limit the potential damage if a bad pointer is passed
-  in. Like when this function is called twice on the same handle pointer.
+- docs: make curldown do angle brackets like markdown
 
-  Ref: #10964
-  Closes #11061
+  Make sure we use \< and \> in markdown all over so that it renders
+  correctly, on GitHub and elsewhere. cd2nroff now outputs a warning if it
+  finds an unescaled angle bracket.
 
-Andreas Falkenhahn (1 May 2023)
+  Ref: #12854
+  Closes #12869
 
-- amiga: Fix CA certificate paths for AmiSSL and MorphOS
+- docs: fix the --disable-docs for autotools
 
-  AmiSSL stores certificates in `AmiSSL:Certs` and MorphOS stores them in
-  `MOSSYS:Data/SSL/curl-ca-bundle.crt`.
+  Follow-up to 541321507e386
 
-  Closes https://github.com/curl/curl/pull/11059
+  Closes #12870
 
-Daniel Stenberg (30 Apr 2023)
+- RELEASE-NOTES: synced
 
-- http2: (void)-mark when we explicitly ignore the return code
+- libcurl-security.md: Active FTP passes on the local IP address
 
-  When h2_progress_egress() is called. Pointed out by Coverity.
+  Reported-by: Harry Sintonen
+  Closes #12867
 
-  Closes #11057
+Stefan Eissing (5 Feb 2024)
 
-- checksrc: find bad indentation in conditions without open brace
+- configure: do not link with nghttp3 unless necessary
 
-  If the previous line starts with if/while/for AND ends with a closed
-  parenthesis and there's an equal number of open and closed parentheses
-  on that line, verify that this line is indented $indent more steps, if
-  not a cpp line.
+  Fixes #12833
+  Closes #12864
+  Reported-by: Ryan Carsten Schmidt
 
-  Also adjust the fall-out from this fix.
+Daniel Stenberg (5 Feb 2024)
 
-  Closes #11054
+- THANKS: add Dmitry Tretyakov
 
-Diogo Teles Sant'Anna (28 Apr 2023)
+  ... since I missed to give credit to the report in the fix of #12861
 
-- CI: Set minimal permissions on workflow ngtcp2-quictls.yml
+Stefan Eissing (5 Feb 2024)
 
-  Signed-off-by: Diogo Teles Sant'Anna 
+- openssl-quic: check on Windows that socket conv to int is possible
 
-  Closes #11055
+  Fixes #12861
+  Closes #12865
 
-Dan Fandrich (28 Apr 2023)
+Daniel Stenberg (5 Feb 2024)
 
-- CI: use another glob syntax for matching files on Appveyor
+- tool_cb_hdr: only parse etag + content-disposition for 2xx
 
-  The previous globbing syntax was not matching files recursively in
-  directories, so try appending a /* to more closely match the examples at
-  https://www.appveyor.com/docs/how-to/filtering-commits/
+  ... and ignore them for other response codes.
 
-Daniel Stenberg (28 Apr 2023)
+  Reported-by: Harry Sintonen
+  Closes #12866
 
-- multi: add multi-ignore logic to multi_socket_action
+- md4: include strdup.h for the memdup proto
 
-  The multi-ignore logic that was previously applied to
-  curl_multi_perform() (#10750) is here applied to the loop within
-  curl_multi_socket_action() to make it use the same optimization: most
-  handles have the same signal-ignore option state so this drastically
-  reduces the number of ignore/unignore calls per libcurl function invoke.
+  Reported-by: Erik Schnetter
+  Fixes #12849
+  Closes #12863
 
-  Follow-up to bc90308328afb8
+Joel Depooter (5 Feb 2024)
 
-  Closes #11045
+- docs: add missing slashes to SChannel client certificate documentation
 
-Stefan Eissing (28 Apr 2023)
+  When setting the CURLOPT_SSLCERT option to a certificate thumprint, it
+  is required to have a backslash between the "store location", "store
+  name" and "thumbprint" tokens. These slashes were present in the
+  previous documentation, but were missed in the transition to markdown
+  documentation.
 
-- http2: do flow window accounting for cancelled streams
+  Closes #12854
 
-  - nghttp2 does not free connection level window flow for
-    aborted streams
-  - when closing transfers, make sure that any buffered
-    response data is "given back" to the flow control window
-  - add tests test_02_22 and test_02_23 to reproduce
+Stefan Eissing (5 Feb 2024)
 
-  Closes #11052
+- HTTP/2: write response directly
 
-- pingpong: fix compiler warning "assigning an enum to unsigned char"
+  - use the new `Curl_xfer_write_resp()` to write incoming responses
+    directly to the client
+  - eliminates `stream->recvbuf`
+  - memory consumption on parallel transfers minimized
 
-  Closes #11050
+  Closes #12828
 
-Daniel Stenberg (28 Apr 2023)
+Daniel Stenberg (5 Feb 2024)
 
-- configure: fix detection of apxs (for httpd)
+- cookie.md: provide an example sending a fixed cookie
 
-  The condition check was turned the wrong way around!
+  Closes #12868
 
-  Closes #11051
+Lars Kellogg-Stedman (5 Feb 2024)
 
-Viktor Szakats (28 Apr 2023)
+- ALTSVC.md: correct a typo
 
-- ci: `-Wno-vla` no longer necessary
+  The ALPN documentation erroneously referred to a "host number" instead
+  of a "port number".
 
-  We handle this issue in the source now.
+  Closes #12852
 
-  Follow-up to b725fe1944b45406676ea3aff333ae3085a848d9
+Boris Verkhovskiy (5 Feb 2024)
 
-  Reviewed-by: Marcel Raad
-  Reviewed-by: Daniel Stenberg
-  Closes #11048
+- proxy1.0.md: fix example
 
-Marcel Raad (28 Apr 2023)
+  Closes #12856
 
-- tests/http: make curl_setup.h the first include
+Chris Webb (5 Feb 2024)
 
-  This is required for the macros there to take effect for system
-  libraries. Specifically, including the system libraries first led to
-  warnings about `_FILE_OFFSET_BITS` being redefined in curl_config.h on
-  the Solaris autobuilds for ws-data.c and ws-pingpong.c.
-  Also make the curl includes come first for the other source files here
-  for consistency.
+- configure: add --disable-docs flag
 
-  Closes https://github.com/curl/curl/pull/11046
+  Building man pages from curldown sources now requires perl. Add a
+  --disable-docs flag to configure to enable building and installing
+  without documentation where perl is not available or man pages are not
+  required. This is selected automatically (with a warning) when perl is
+  not found by configure.
 
-Emanuele Torre (27 Apr 2023)
+  Fixes #12832
+  Closes #12857
 
-- checksrc: check for spaces before the colon of switch labels
+Faraz Fallahi (5 Feb 2024)
 
-  Closes #11047
+- connect.c: fix typo
 
-Daniel Stenberg (27 Apr 2023)
+  Closes #12858
 
-- RELEASE-NOTES: synced
+Daniel Stenberg (1 Feb 2024)
 
-- libssh: tell it to use SFTP non-blocking
+- sendf: ignore response body to HEAD
 
-  Reported-by: Andreas Huebner
-  Fixes #11020
-  Closes #11039
+  and mark the stream for close, but return OK since the response this far
+  was ok - if headers were received. Partly because this is what curl has
+  done traditionally.
 
-Stefan Eissing (27 Apr 2023)
+  Test 499 verifies. Updates test 689.
 
-- http2: enlarge the connection window
+  Reported-by: Sergey Bronnikov
+  Bug: https://curl.se/mail/lib-2024-02/0000.html
+  Closes #12842
 
-  - fixes stalled connections
+- ftp: treat a 226 arriving before data as a signal to read data
 
-  - Make the connection window large enough, so that there is
-    some room left should 99/100 streams be PAUSED by the application
+  For active mode transfers.
 
-  Reported-by: Paweł Wegner
-  Fixes #10988
-  Closes #11043
+  Due to some interesting timing, curl can sometimes get the 226 (transfer
+  complete) over the control channel first, before the data connection
+  signals readability. If this happens, use that as a signal to check the
+  data connection.
 
-Daniel Stenberg (27 Apr 2023)
+  Additionally, set the socket filter in listen mode *before* the
+  PORT/EPRT command is issued, to reduce the risk that the little time gap
+  could interfere.
 
-- checksrc: fix SPACEBEFOREPAREN for conditions starting with "*"
+  This issue never reproduced for me on Debian and takes several hundred
+  rounds for me to trigger on my mac.
 
-  The open paren check wants to warn for spaces before open parenthesis
-  for if/while/for but also for any function call. In order to avoid
-  catching function pointer declarations, the logic allows a space if the
-  first character after the open parenthesis is an asterisk.
+  Reported-by: Stefan Eissing
+  Fixes #12823
+  Closes #12841
 
-  I also spotted what we did not include "switch" in the check but we should.
+Patrick Monnerat (1 Feb 2024)
 
-  This check is a little lame, but we reduce this problem by not allowing
-  that space for if/while/for/switch.
+- OS400: avoid using awk in the build scripts
 
-  Reported-by: Emanuele Torre
-  Closes #11044
+  Awk is a PASE program and its use may cause a failure depending on the
+  CCSID of the calling script (IBM bug?).
 
-- docs: minor polish
+  For this reason, revert to an sed-only solution to extract the exported
+  symbols from the header files.
 
-  - "an HTTP*" (not "a")
-  - remove a few contractions
-  - remove a spurious "a"
-  - reduce use of "I" in texts
+  Closes #12826
 
-  Closes #11040
+Jan Macku (1 Feb 2024)
 
-- ws: fix CONT opcode check
+- docs: remove `mk-ca-bundle.1` from `man_MANS`
 
-  Detected by Coverity. Follow-up to 930c00c259
+  It was accidentally added in https://github.com/curl/curl/pull/12730
 
-  Closes #11037
+  Co-authored-by: Lukáš Zaoral 
+  Signed-off-by: Jan Macku 
 
-Dan Fandrich (27 Apr 2023)
+  Follow-up to eefcc1bda4bccd800f5a56a0fe17a2f44a96e88b
+  Closes #12843
 
-- CI: switch the awslc builds to build out-of-tree
+Daniel Stenberg (1 Feb 2024)
 
-  This is a common configuration that should be tested to avoid
-  regressions. The awsls cmake build was already out-of-tree so the
-  automake build now joins it.
+- RELEASE-NOTES: synced
 
-  Ref: #11006
+  and bump to 8.6.1 for now
 
-- tests/http: fix out-of-tree builds
+- cmdline-docs/Makefile: avoid using a fixed temp file name
 
-  Add both lib/ directories (src & build) to the search path so
-  curl_setup.h and its dependencies can be found.
+  By appending the pid number two different runs at the same time will not
+  trample over the same file.
 
-  Followup-to acd82c8b
+  Reported-by: Jon Rumsey
+  Fixes #12829
+  Closes #12839
 
-  Ref: #11006
-  Closes #11036
+- asyn-thread: use wakeup_close to close the read descriptor
 
-Daniel Stenberg (27 Apr 2023)
+  Reported-by: Dan Fandrich
+  Ref: #12834
+  Closes #12836
 
-- urlapi: make internal function start with Curl_
+Stefan Eissing (1 Feb 2024)
 
-  Curl_url_set_authority() it is.
+- ntml_wb: fix buffer type typo
 
-  Follow-up to acd82c8bfd
+  Closes #12825
 
-  Closes #11035
+Daniel Stenberg (1 Feb 2024)
 
-YX Hao (26 Apr 2023)
+- tool_operate: do not set CURLOPT_QUICK_EXIT in debug builds
 
-- cf-socket: turn off IPV6_V6ONLY on Windows if it is supported
+  Since it allows (small) memory leaks that interfere with torture tests
+  and regular memory-leak checks.
 
-  IPV6_V6ONLY refs:
-  https://en.wikipedia.org/wiki/IPv6#IPv4-mapped_IPv6_addresses
-  https://github.com/golang/go/blob/master/src/net/ipsock_posix.go
-  https://en.wikipedia.org/wiki/Unix-like
-  https://learn.microsoft.com/en-us/windows/win32/winsock/ipproto-ipv6-socket-o
-  ptions
+  Reported-by: Dan Fandrich
+  Fixes #12834
+  Closes #12835
 
-  default value refs:
-  https://datatracker.ietf.org/doc/html/rfc3493#section-5.3
-  https://www.kernel.org/doc/html/latest/networking/ip-sysctl.html#proc-sys-net
-  -ipv6-variables
+Boris Verkhovskiy (31 Jan 2024)
 
-  Closes #10975
+- form-string.md: correct the example
 
-Daniel Stenberg (26 Apr 2023)
+  Closes #12822
 
-- urldata: shrink *select_bits int => unsigned char
+Version 8.6.0 (31 Jan 2024)
 
-  - dselect_bits
-  - cselect_bits
+Daniel Stenberg (31 Jan 2024)
 
-  ... are using less than 8 bits. Changed types and moved them towards
-  the end of the structs to fit better.
+- RELEASE-NOTES: synced
 
-  Closes #11025
+  curl 8.6.0
 
-Stefan Eissing (26 Apr 2023)
+- THANKS: new contributors from 8.5.0
 
-- tests/http: more tests with specific clients
+Jay Satiro (31 Jan 2024)
 
-  - Makefile support for building test specific clients in tests/http/clients
-  - auto-make of clients when invoking pytest
-  - added test_09_02 for server PUSH_PROMISEs using clients/h2-serverpush
-  - added test_02_21 for lib based downloads and pausing/unpausing transfers
+- cd2nroff: use perl 'strict' and 'warnings'
 
-  curl url parser:
-  - added internal method `curl_url_set_authority()` for setting the
-    authority part of a url (used for PUSH_PROMISE)
+  - Use strict and warnings pragmas.
 
-  http2:
-  - made logging of PUSH_PROMISE handling nicer
+  - If open() fails then show the reason.
 
-  Placing python test requirements in requirements.txt files
-  - separate files to base test suite and http tests since use
-    and module lists differ
-  - using the files in the gh workflows
+  - Set STDIN io layer :crlf so that input is properly read on Windows.
 
-  websocket test cases, fixes for we and bufq
-  - bufq: account for spare chunks in space calculation
-  - bufq: reset chunks that are skipped empty
-  - ws: correctly encode frames with 126 bytes payload
-  - ws: update frame meta information on first call of collect
-    callback that fills user buffer
-  - test client ws-data: some test/reporting improvements
+  - When STDIN is used as input, the filename $f is now set to "STDIN".
 
-  Closes #11006
+  Various error messages in single() use $f for the filename and this way
+  it is not undefined when STDIN.
 
-Jay Satiro (26 Apr 2023)
+  Closes https://github.com/curl/curl/pull/12819
 
-- libssh2: fix crash in keyboard callback
+Daniel Stenberg (30 Jan 2024)
 
-  - Always set the libssh2 'abstract' user-pointer to the libcurl easy
-    handle associated with the ssh session, so it is always passed to the
-    ssh keyboard callback.
+- cd2nroff: fix duplicate output issue
 
-  Prior to this change and since 8b5f100 (precedes curl 8.0.0), if libcurl
-  was built without CURL_DEBUG then it could crash during the ssh auth
-  phase due to a null dereference in the ssh keyboard callback.
+  Assisted-by: Jay Satiro
+  Fixes https://github.com/curl/curl-www/issues/321
+  Closes #12818
 
-  Reported-by: Andreas Falkenhahn
+- lib: error out on multissl + http3
 
-  Fixes https://github.com/curl/curl/pull/11024
-  Closes https://github.com/curl/curl/pull/11026
+  Since the QUIC/h3 code has no knowledge or handling of multissl it might
+  bring unintended consequences if we allow it.
 
-Daniel Stenberg (26 Apr 2023)
+  configure, cmake and curl_setup.h all now reject this combination.
 
-- docs: clarify that more backends have HTTPS proxy support
+  Assisted-by: Viktor Szakats
+  Assisted-by: Gisle Vanem
+  Ref: #12806
+  Closes #12807
 
-  Closes #11033
+Patrick Monnerat (29 Jan 2024)
 
-- KNOWN_BUGS: remove two not-bugs
+- OS400: sync ILE/RPG binding
 
-  - 11.7 signal-based resolver timeouts
+  Also do not force git CRLF line endings on *.cmd files for OS400.
 
-  Not considered a bug anymore but just implementation details. People
-  should avoid using timeouts with the synchronous name resolver.
+  Closes #12815
 
-  - 11.16 libcurl uses renames instead of locking for atomic operations
+Viktor Szakats (28 Jan 2024)
 
-  Not a bug, just a description of how it works
+- build: delete/replace 3 more clang warning pragmas
 
-  Closes #11032
+  - tool_msgs: delete redundant `-Wformat-nonliteral` suppression pragma.
 
-Harry Sintonen (26 Apr 2023)
+  - whitespace formatting in `mprintf.h`, lib518, lib537.
 
-- hostip: add locks around use of global buffer for alarm()
+  - lib518: fix wrong variable in `sizeof()`.
 
-  When building with the sync name resolver and timeout ability we now
-  require thread-safety to be present to enable it.
+  - lib518: bump variables to `rlim_t`.
+    Follow-up to e2b394106d543c4615a60795b7fdce04bd4e5090 #1469
 
-  Closes #11030
+  - lib518: sync error message with lib537
+    Follow-up to 365322b8bcf9efb6a361473d227b70f2032212ce
 
-Daniel Stenberg (26 Apr 2023)
+  - lib518, lib537: replace `-Wformat-nonliteral` suppression pragmas
+    by reworking test code.
 
-- curl_path: bring back support for SFTP path ending in /~
+  Follow-up to 5b286c250829e06a135a6ba998e80beb7f43a734 #12812
+  Follow-up to aee4ebe59161d0a5281743f96e7738ad97fe1cd4 #12803
+  Follow-up to 09230127589eccc7e01c1a7217787ef8e64f3328 #12540
+  Follow-up to 3829759bd042c03225ae862062560f568ba1a231 #12489
 
-  libcurl used to do a directory listing for this case (even though the
-  documentation says a URL needs to end in a slash for this), but
-  4e2b52b5f7a3 modified the behavior.
+  Reviewed-by: Daniel Stenberg
+  Closes #12814
 
-  This change brings back a directory listing for SFTP paths that are
-  specified exactly as /~ in the URL.
+Richard Levitte (27 Jan 2024)
 
-  Reported-by: Pavel Mayorov
-  Fixes #11001
-  Closes #11023
+- cmake: freshen up docs/INSTALL.cmake
 
-Emanuele Torre (26 Apr 2023)
+  - Turn docs/INSTALL.cmake into a proper markdown file,
+    docs/INSTALL-CMAKE.md
+  - Move things around to divide the description into configuration,
+    building and installing sections
+  - Mention the more modern cmake options to configure, build and install,
+    but also retain the older variants as fallbacks
 
-- docs/libcurl/curl_*escape.3: rename "url" argument to "input"/"string"
+  Closes #12772
 
-  Also reword the DESCRIPTION section to mention "input"/"string" argument
-  in bold.
+Viktor Szakats (27 Jan 2024)
 
-  Closes #11027
+- build: delete/replace clang warning pragmas
 
-- docs/libcurl: minor cleanups
+  - delete redundant warning suppressions for `-Wformat-nonliteral`.
+    This now relies on `CURL_PRINTF()` and it's theoratically possible
+    that this macro isn't active but the warning is. We're ignoring this
+    as a corner-case here.
 
-  I was reading curl_unescape(3) and I noticed that there was an extra
-  space after the open parenthesis in the SYNOPSIS; I removed the extra
-  space.
+  - replace two pragmas with code changes to avoid the warnings.
 
-  I also ran a few  grep -r  commands to find and remove extra spaces
-  after '(' in other files, and to find and replace uses of `T*' instead
-  of `T *'. Some of the instances of `T*` where unnecessary casts that I
-  removed.
+  Follow-up to aee4ebe59161d0a5281743f96e7738ad97fe1cd4 #12803
+  Follow-up to 09230127589eccc7e01c1a7217787ef8e64f3328 #12540
+  Follow-up to 3829759bd042c03225ae862062560f568ba1a231 #12489
 
-  I also fixed a comment that was misaligned in CURLMOPT_SOCKETFUNCTION.3.
+  Reviewed-by: Daniel Stenberg
+  Closes #12812
 
-  And I fixed some formatting inconsistencies: in curl_unescape(3), all
-  function parameter were mentioned with bold text except length, that was
-  mentioned as 'length'; and, in curl_easy_unescape(3), all parameters
-  were mentioned in bold text except url that was italicised. Now they are
-  all mentioned in bold.
-  Documentation is not very consistent in how function parameter are
-  formatted: many pages italicise them, and others display them in bold
-  text; but I think it makes sense to at least be consistent with
-  formatting within the same page.
+Daniel Stenberg (27 Jan 2024)
 
-  Closes #11027
+- RELEASE-NOTES: synced
 
-Daniel Stenberg (26 Apr 2023)
+- http: only act on 101 responses when they are HTTP/1.1
 
-- man pages: simplify the .TH sections
+  For 101 responses claiming to be any other protocol, bail out. This
+  would previously trigger an assert.
 
-  - remove the version numbers
-  - simplify the texts
+  Add test 1704 to verify.
 
-  The date and version number will be put there for releases when maketgz
-  runs the updatemanpages.pl script.
+  Bug: https://bugs.chromium.org/p/oss-fuzz/issues/detail?id=66184
+  Closes #12811
 
-  Closes #11029
+Scarlett McAllister (27 Jan 2024)
 
-- hostcheck: fix host name wildcard checking
+- _VARIABLES.md: add missing 'be' into the sentence
 
-  The leftmost "label" of the host name can now only match against single
-  '*'. Like the browsers have worked for a long time.
+  Closes #12809
 
-  - extended unit test 1397 for this
-  - move some SOURCE variables from unit/Makefile.am to unit/Makefile.inc
+Stefan Eissing (27 Jan 2024)
 
-  Reported-by: Hiroki Kurosawa
-  Closes #11018
+- mqtt, remove remaining use of data->state.buffer
 
-Dan Fandrich (25 Apr 2023)
+  Closes #12799
 
-- smbserver: remove temporary files before exit
+Daniel Stenberg (27 Jan 2024)
 
-  Each execution of test 1451 would leave a file in /tmp before. Since
-  Windows can't delete a file while it's open, all the temporary file
-  names are stored and deleted on exit.
+- x509asn1: switch from malloc to dynbuf
 
-  Closes #10990
+  Closes #12808
 
-Stefan Eissing (25 Apr 2023)
+- x509asn1: make utf8asn1str() use dynbuf instead of malloc + memcpy
 
-- Websocket en-/decoding
+  Closes #12808
 
-  - state is fully kept at connection, since curl_ws_send() and
-    curl_ws_rec() have lifetime beyond usual transfers
-  - no more limit on frame sizes
+- x509asn1: reduce malloc in Curl_extract_certinfo
 
-  Reported-by: simplerobot on github
-  Fixes #10962
-  Closes #10999
+  Using dynbuf
 
-Patrick Monnerat (25 Apr 2023)
+  Closes #12808
 
-- urldata: copy CURLOPT_AWS_SIGV4 value on handle duplication
+Jay Satiro (27 Jan 2024)
 
-  Prior to this change STRING_AWS_SIGV4 (CURLOPT_AWS_SIGV4) was wrongly
-  marked as binary data that could not be duplicated.
+- THANKS: add Alexander Bartel and Brennan Kinney
 
-  Without this fix, this option's value is not copied upon calling
-  curl_easy_duphandle().
+  They reported and investigated #10259 which was fixed by 7b2d98df.
 
-  Closes https://github.com/curl/curl/pull/11021
+  Ref: https://github.com/curl/curl/issues/10259
 
-Stefan Eissing (25 Apr 2023)
+Daniel Stenberg (26 Jan 2024)
 
-- http3: expire unpaused transfers in all HTTP/3 backends
+- krb5: add prototype to silence clang warnings on mvsnprintf()
 
-  Closes #11005
+  "error: format string is not a string literal"
 
-- http2: always EXPIRE_RUN_NOW unpaused http/2 transfers
+  Follow-up to 09230127589eccc7 which made the warning appear
 
-  - just increasing the http/2 flow window does not necessarily
-    make a server send new data. It may already have exhausted
-    the window before
+  Assisted-by: Viktor Szakats
+  Closes #12803
 
-  Closes #11005
+- x509asn1: remove code for WANT_VERIFYHOST
 
-- http2: pass `stream` to http2_handle_stream_close to avoid NULL checks
+  No code ever sets this anymore since we dropped gskit
 
-  Closes #11005
+  Follow-up to 78d6232f1f326b9ab4d
 
-- h2/h3: replace `state.drain` counter with `state.dselect_bits`
+  Closes #12804
 
-  - `drain` was used by http/2 and http/3 implementations to indicate
-    that the transfer requires send/recv independant from its socket
-    poll state. Intended as a counter, it was used as bool flag only.
-  - a similar mechanism exists on `connectdata->cselect_bits` where
-    specific protocols can indicate something similar, only for the
-    whole connection.
-  - `cselect_bits` are cleard in transfer.c on use and, importantly,
-    also set when the transfer loop expended its `maxloops` tries.
-    `drain` was not cleared by transfer and the http2/3 implementations
-    had to take care of that.
-  - `dselect_bits` is cleared *and* set by the transfer loop. http2/3
-    does no longer clear it, only set when new events happen.
+- socks: reduce the buffer size to 600 (from 8K)
 
-  This change unifies the handling of socket poll overrides, extending
-  `cselect_bits` by a easy handle specific value and a common treatment in
-  transfers.
+  This is malloc'ed memory and it does not more. Test 742 helps us verify
+  this.
 
-  Closes #11005
+  Closes #12789
 
-Daniel Stenberg (25 Apr 2023)
+Stefan Eissing (26 Jan 2024)
 
-- socketpair: verify with a random value
+- file+ftp: use stack buffers instead of data->state.buffer
 
-  ... instead of using the curl time struct, since it would use a few
-  uninitialized bytes and the sanitizers would complain. This is a neater
-  approach I think.
+  Closes #12789
 
-  Reported-by: Boris Kuschel
-  Fixes #10993
-  Closes #11015
+- vtls: receive max buffer
 
-Stefan Eissing (25 Apr 2023)
+  - do not only receive one TLS record, but try to fill
+    the passed buffer
+  - consider <4K remaning space is "filled".
 
-- HTTP3: document the ngtcp2/nghttp3 versions to use for building curl
+  Closes #12801
 
-  - refs #11011 to clarify this for people building curl themselves
+Daniel Stenberg (26 Jan 2024)
 
-  Closes #11019
+- docs: do not start lines/sentences with So, But nor And
 
-Daniel Stenberg (25 Apr 2023)
+  Closes #12802
 
-- lib: unify the upload/method handling
+- docs: remove spurious ampersands from markdown
 
-  By making sure we set state.upload based on the set.method value and not
-  independently as set.upload, we reduce confusion and mixup risks, both
-  internally and externally.
+  They were leftovers from the nroff conversion.
 
-  Closes #11017
+  Follow-up to eefcc1bda4bccd800f5a5
 
-- RELEASE-NOTES: synced
+  Closes #12800
 
-Dan Fandrich (24 Apr 2023)
+Patrick Monnerat (26 Jan 2024)
 
-- CI: don't run CI jobs if only another CI was changed
+- sasl: make login option string override http auth
 
-  A few paths were missed in the last commit, as well as a job added since
-  then.
+  - Use http authentication mechanisms as a default, not a preset.
 
-  Followup-to 395b9175
+  Consider http authentication options which are mapped to SASL options as
+  a default (overriding the hardcoded default mask for the protocol) that
+  is ignored if a login option string is given.
 
-- CI: adjust labeler match patterns
+  Prior to this change, if some HTTP auth options were given, sasl mapped
+  http authentication options to sasl ones but merged them with the login
+  options.
 
-- runtests: support buffering log messages in runner & servers
+  That caused problems with the cli tool that sets the http login option
+  CURLAUTH_BEARER as a side-effect of --oauth2-bearer, because this flag
+  maps to more than one sasl mechanisms and the latter cannot be cleared
+  individually by the login options string.
 
-  Log messages generated with logmsg can now be buffered and returned from
-  the runner as a return value.  This will be needed with parallel testing
-  to allow all messages for one test to be displayed together instead of
-  interspersed with messages of multiple tests. Buffering can be disabled
-  by setting a logging callback function with setlogfunc, which is
-  currently being done to preserve existing logging behaviour for now.
+  New test 992 checks this.
 
-  Some additional output is generated in verbose and debugprotocol modes,
-  which don't always use logmsg. These modes also impact some servers
-  which generate extra messages. No attempt is made to buffer everything
-  if these modes are enabled.
+  Fixes https://github.com/curl/curl/issues/10259
+  Closes https://github.com/curl/curl/pull/12790
 
-  Ref: #10818
-  Closes #11016
+Stefan Eissing (26 Jan 2024)
 
-- runtests: more consistently use logmsg in server control code
+- socks: use own buffer instead of data->state.buffer
 
-  Also, display an error when sshversioninfo returns one.
+  Closes #12788
 
-  Ref: #10818
+Daniel Stenberg (26 Jan 2024)
 
-- runtests: create runner functions for clearlocks and stopservers
+- socks: fix generic output string to say SOCKS instead of SOCKS4
 
-  runtests.pl now uses runner for all server actions beyond the initial
-  variable configuration.
+  ... since it was also logged for SOCKS5.
 
-  Ref: #10818
+  Closes #12797
 
-- runtests: tightened servers package exports
+- test742: test SOCKS5 with max length user, password and hostname
 
-  The defaults are intended for runtests.pl, whereas runner.pm needs to
-  explicitly specify them.
+  Adjusted the socksd server accordingly to allow for configuring that
+  long user name and password.
 
-- runtests: display logs on server failure in singletest()
+  Closes #12797
 
-  This is closer to the place where logs are displayed on test failure.
-  Also, only display these logs if -p is given, which is the same flag
-  that controls display of test failure logs. Some server log files
-  need to be deleted later so that they stay around long enough to be
-  displayed on failure.
+Stefan Eissing (25 Jan 2024)
 
-  Ref: #10818
+- ssh: use stack scratch buffer for seeks
 
-- runtests: turn a print into a logmsg
+  - instead of data->state.buffer
 
-  Also enable another couple of useful messages in verbose mode.
+  Closes #12794
 
-  Ref: #10818
+Daniel Stenberg (25 Jan 2024)
 
-Daniel Stenberg (24 Apr 2023)
+- krb5: access the response buffer correctly
 
-- http: store the password in the correct variable
+  As the pingpong code no longer uses the download buffer.
 
-  Typo from fc2f1e547a4a, detected by Coverity (because there's dead code
-  due to this).
+  Folllow-up to c2d973627bab12ab
+  Pointed-out-by: Stefan Eissing
+  Closes #12796
 
-  Closes #11002
+Stefan Eissing (25 Jan 2024)
 
-Stefan Eissing (24 Apr 2023)
+- mqtt: use stack scratch buffer for recv+publish
 
-- HTTP3/quiche: terminate h1 response header when no body is sent
+  - instead of data->state.buffer
 
-  - fixes a failure in test2501 where a response without body was missing
-    the final empty line
+  Closes #12792
 
-  Closes #11003
+- telnet, use stack scratch buffer for do
 
-Dan Fandrich (22 Apr 2023)
+  - instead of data->state.buffer
 
-- runtests: move showdiff into runtests.pl
+  Closes #12793
 
-  It's not used anywhere else.
+- http, use stack scratch buffer
 
-- devtest: add a new script for testing the test harness
+  - instead of data->state.buffer
 
-  This is currently useful for starting a test server on its own without
-  an associated test, which can be used for interactive curl testing or
-  for validating parts of the test harness itself. More commands can be
-  added to perform additional functions in the future.
+  Closes #12791
 
-  Ref: #10818
-  Closes #11008
+- ntlm_wb: do not use data->state.buf any longer
 
-- runtests: refactor the main test loop into two
+  Closes #12787
 
-  The test loop now has an initial loop that first runs through all
-  possible tests to build a set of those to attempt on this run based on
-  features and keywords and only then goes through that new list to run
-  them.  This actually makes it three loops through all tests cases, as
-  there is an existing loop that gathers possible test numbers from the
-  test files on disk.
+- gitignore: the generated `libcurl-symbols.md`
 
-  This has two minor effects on the output: all the tests that will be
-  skipped are displayed at the start (instead of being interspersed with
-  other tests) and the -l option no longer shows a count of tests at the
-  end or a (misleading) statement that tests have run successfully. The
-  skipped tests are also omitted from the test results sent to AppVeyor
-  and Azure in CI builds.
+  Closes #12795
 
-  Another effect is a reduction in the amount of work considered part of
-  the "Test definition reading and preparation time" reported with -r
-  making those figures slightly lower than before.
+Daniel Stenberg (25 Jan 2024)
 
-  Ref: #10818
+- tool: fix the listhelp generation command
 
-- runtests: track only the current test timings in runner.pm
+  The previous command line to generate the tool_listhelp.c source file
+  broke with 2494b8dd5175cee7.
 
-  This avoids passing these data through through global variables, which
-  soon won't be possible.
+  Make 'make listhelp' invoked in src/ generate it. Also update the
+  comment in the file to mention the right procedure.
 
-  Ref: #10818
+  Closes #12786
 
-- runtests: skip test preprocessing when doing -l
+- http: check for "Host:" case insensitively
 
-  This speeds up the output tremendously by avoiding unnecessary work.
+  When checking if the user wants to replace the header, the check should
+  be case insensitive.
 
-- runtests: simplify value returned regarding use of valgrind
+  Adding test 461 to verify
 
-  As a side effect this will now also show in verbose mode that valgrind
-  is being skipped on tests that explicitly disable it, such as 600.
+  Found-by: Dan Fandrich
+  Ref: #12782
+  Closes #12784
 
-  Ref: #10818
+Tatsuhiro Tsujikawa (25 Jan 2024)
 
-- runtests: fix quoting in Appveyor and Azure test integration
+- configure: add libngtcp2_crypto_boringssl detection
 
-  Test 1442's name was not quoted correctly so wasn't registered in
-  Appveyor and it had the wrong name in Azure. The JSON string quotes were
-  also invalid, even though both servers happened to accept it regardless.
+  If OpenSSL is found to be BoringSSL or AWS-LC, and ngtcp2 is requested,
+  try to detect libngtcp2_crypto_boringssl.
 
-  Closes #11010
+  Reported-by: ウさん
+  Fixes #12724
+  Closes #12769
 
-Daniel Stenberg (19 Apr 2023)
+Daniel Stenberg (25 Jan 2024)
 
-- RELEASE-NOTES: synced
+- http: remove comment reference to a removed solution
 
-Dan Fandrich (18 Apr 2023)
+  Follow-up to 58974d25d
 
-- runtests: spread out the port numbers used by servers
+  Closes #12785
 
-  The server ports are chosen randomly for each server, but the random
-  ranges chosen were inconsistently-sized and overlapping. Now, they are
-  spread out more so at least the first random port chosen for each server
-  is guaranteed to not also be chosen by another server. The starting port
-  numbers are also raised to put them in the Ephemeral Port range—not the
-  range defined by RFC 6335 but the one used by Linux, which starts lower
-  and gives us more room to work with.
+Stefan Eissing (25 Jan 2024)
 
-  Reported-by: Daniel Stenberg
+- pytest: Scorecard tracking CPU and RSS
 
-- runtests: fix problems on  failure
+  Closes #12765
 
-  The verify time must be set in this case, like all cases. An error
-  message needs to be displayed as well.
+Graham Campbell (25 Jan 2024)
 
-- runtests: fix perl warning when  is wrong
+- GHA: bump ngtcp2, gnutls, mod_h2, quiche
 
-- runtests: don't try to stop stunnel before trying again
+  - ngtcp2 to v1.2.0
+  - gnutls to 3.8.3
+  - mod_h2 to 2.0.26
+  - quiche to 0.20.0
 
-  Calling stopserver() before retrying stunnel due to an error would stop
-  the dependent server (such as HTTP) meaning stunnel would have nothing
-  to talk to when it came up. Don't try to force a stop when it didn't
-  actually start.  Also, don't mark the server as bad for future use when
-  it starts up on a retry.
+  Closes #12778
+  Closes #12779
+  Closes #12780
+  Closes #12781
 
-  Reported-by: eaglegai at github
-  Tested-by: eaglegai at github
-  Fixes #10976
+Daniel Stenberg (25 Jan 2024)
 
-- runtests: don't accidentally randomly choose the same port
+- ftpserver.pl: send 213 SIZE response without spurious newline
 
-  If a server couldn't be started on a port, a new one is randomly chosen
-  and the server is tried again. Avoid accidentally using a
-  randomly-chosen 0 port offset by adding 1 to the random number.
+- pingpong: stop using the download buffer
 
-  Found-by: Daniel Stenberg
+  The pingpong logic now uses its own dynbuf for receiving command
+  response data.
 
-- runtests: don't attempt to use a port we know is in use
+  When the "final" response header for a commanad has been received, that
+  final line is left first in the recvbuf for the protocols to parse at
+  will. If there is additional data behind the final response line, the
+  'overflow' counter is indicate how many bytes.
 
-  This reduces the startup time when there is a known conflict on the
-  random port chosen for a server.  This was already done for stunnel, but
-  now it's done for all servers.
+  Closes #12757
 
-- http-server: fix server name in a log message
+- gen.pl: remove bold from .IP used for ##
 
-  This changed when the file was renamed in commit cbf57176
+  Reported-by: Viktor Szakats
+  Fixes #12776
+  Closes #12777
 
-- runtests: refactor into more packages
+Viktor Szakats (24 Jan 2024)
 
-  testutil.pm now contains a few miscellaneous functions that are used in
-  several places but have no better place to live.  subvariables moves to
-  servers.pm since most variables that it substitutes relate to servers,
-  so this is the most appropriate place. Rename a few functions for better
-  naming consistency.
+- cmake: rework options to enable curl and libcurl docs
 
-  Ref: #10818
-  Closes #10995
+  Rework CMake options for building/using curl tool and libcurl manuals.
 
-- runtests: call timestampskippedevents() in singletest
+  - rename `ENABLE_MANUAL` to `ENABLE_CURL_MANUAL`, meaning:
+    to build man page and built-in manual for curl tool.
 
-  ..rather than by the runner
+  - rename `BUILD_DOCS` to `BUILD_LIBCURL_DOCS`, meaning:
+    to build man pages for libcurl.
 
-- runtests: assume a newer Valgrind by default
+  - `BUILD_LIBCURL_DOCS` now works without having to enable
+    `ENABLE_CURL_MANUAL` too.
 
-  The tests for an older Valgrind version should probably just be deleted,
-  given that they're testing for an 18-year-old version.
+  - drop support for existing CMake-level `USE_MANUAL` option to avoid
+    confusion. (It used to work with the effect of current
+    `ENABLE_CURL_MANUAL`, but only by accident.)
 
-- runtests: refactor test runner code into runner.pm
+  Assisted-by: Richard Levitte
+  Ref: #12771
+  Closes #12773
 
-  This is code that is directly responsible for running a single test.
-  This will eventually run in a separate process as part of the parallel
-  testing project.
+Daniel Stenberg (24 Jan 2024)
 
-  Ref: #10818
+- urlapi: remove assert
 
-- runtests: skip unneeded work if test won't be running
+  This assert triggers wrongly when CURLU_GUESS_SCHEME and
+  CURLU_NO_AUTHORITY are both set and the URL is a single path.
 
-  This speeds up tests by avoiding unnecessary processing.
+  I think this assert has played out its role. It was introduced in a
+  rather big refactor.
 
-  Ref: #10818
+  Follow-up to 4cfa5bcc9a
 
-- runtests: factor out singletest_postcheck
+  Reported-by: promptfuzz_ on hackerone
+  Closes #12775
 
-  This will eventually need to be part of the test runner.
+Patrick Monnerat (24 Jan 2024)
 
-  Ref: #10818
+- tests: avoid int/size_t conversion size/sign warnings
 
-- test303: kill server after test
+  Closes #12768
 
-  Otherwise, an HTTP test closely following this one with a tight time
-  constraint (e.g. 672) could fail because the test server stays sitting
-  with the wait command for a while.
+Daniel Stenberg (24 Jan 2024)
 
-Patrick Monnerat (18 Apr 2023)
+- GHA: add a job scanning for "bad words" in markdown
 
-- OS400: provide ILE/RPG usage examples
+  This means words, phrases or things we have decided not to use - words that
+  are spelled right according to the dictionary but we want to avoid. In the
+  name of consistency and better documentation.
 
-  Closes https://github.com/curl/curl/pull/10994
+  Closes #12764
 
-- OS400: improve vararg emulation
+Viktor Szakats (23 Jan 2024)
 
-  - Use V7R4 RPG procedure overloading to improve vararg emulation.
+- cmake: speed up curldown processing, enable by default
 
-  From OS400 V7R4 and above, ILE/RPG implements a limited procedure
-  overloading feature that can be used to improve curl's typed
-  implementation of varargs procedures. This commit applies it to
-  curl_easy_setopt(), curl_multi_setopt(), curl_share_setopt() and
-  curl_easy_getinfo().
+  - cmake: enable `BUILD_DOCS` by default (this controls converting and
+    installing `.3` files from `.md` sources)
 
-  Closes https://github.com/curl/curl/pull/10994
+  - cmake: speed up generating `.3` files by using a single command per
+    directory, instead of a single command per file. This reduces external
+    commands by about a thousand. (There remains some CMake logic kicking
+    in resulting in 500 -one per file- external `-E touch_nocreate` calls.)
 
-- OS400: fix and complete ILE/RPG binding
+  - cd2nroff: add ability to process multiple input files.
 
-  - Fix wrong definitions of CURL_ZERO_TERNINATED, curl_mime_data() and
-    curl_mime_data_ccsid().
+  - cd2nroff: add `-k` option to use the source filename to form the
+    output filename. (instead of the default in-file `Title:` line.)
 
-  - Add recent definitions, in particular blob, header API and WebSockets
-    API.
+  Follow-up to 3f08d80b2244524646ce86915c585509ac54fb4c
+  Follow-up to ea0b575dab86a3c44dd1d547dc500276266aa382 #12753
+  Follow-up to eefcc1bda4bccd800f5a56a0fe17a2f44a96e88b #12730
 
-  - Support for CURLVERSION_ELEVENTH.
+  Closes #12762
 
-  - New functions for EBCDIC support.
+Richard Levitte (23 Jan 2024)
 
-  Reflect these changes in README.OS400.
+- docs: install curl.1 with cmake as well
 
-  Closes https://github.com/curl/curl/pull/10994
+  Closes #12759
 
-- OS400: implement EBCDIC support for recent features
+Daniel Stenberg (23 Jan 2024)
 
-  - Support CURLVERSION_ELEVENTH.
+- osslq: remove the TLS library from the version output
 
-  - New function curl_url_strerror_ccsid().
+  Since we only support using a single TLS library at any one time, we
+  know that the TLS library for QUIC is the same that is also shown for
+  regular TLS.
 
-  - curl_easy_setopt_ccsid() supports blobs and 3 recent string options.
+  Fixes #12763
+  Reported-by: Viktor Szakats
+  Closes #12767
 
-  - New function curl_easy_header_ccsid().
+Stefan Eissing (23 Jan 2024)
 
-  - New generic latin1<-->ccsid conversion functions curl_from_ccsid() and
-    curl_to_ccsid() for user convenience.
+- CI: remove unnecessary OpenSSL 3 option `enable-tls1_3`
 
-  - README.OS400 updated accordingly.
+  .. and switch OpenSSL 3 libdir from lib64 to lib for consistency.
 
-  - Removed a leftover QsoSSL support identifier.
+  Closes https://github.com/curl/curl/pull/12758
 
-  Closes https://github.com/curl/curl/pull/10994
+- GHA: bump nghttp2 version to v1.59.0
 
-- OS400: rework build scripts
+  - Switch to v1.59.0 for GHA CI jobs that use a specific nghttp2-version.
 
-  - Rename shell function "system" to "CLcommand" to avoid confusion with
-    built-in command.
+  Closes https://github.com/curl/curl/pull/12766
 
-  - Reformat scripts. Fix some indentations. Avoid lines > 80 characters
-    where possible.
+Daniel Stenberg (23 Jan 2024)
 
-  - Support ASCII runtime development files in a user-defined directory
-    path.
+- RELEASE-NOTES: synced
 
-  - FIX SONAME detection.
+- docs/cmdline: change to .md for cmdline docs
 
-  - Drop form API test program compilation (does not exist anymore).
+   - switch all invidual files documenting command line options into .md,
+     as the documentation is now markdown-looking.
 
-  Closes https://github.com/curl/curl/pull/10994
+   - made the parser treat 4-space indents as quotes
 
-Sevan Janiyan (18 Apr 2023)
+   - switch to building the curl.1 manpage using the "mainpage.idx" file,
+     which lists the files to include to generate it, instead of using the
+     previous page-footer/headers. Also, those files are now also .md
+     ones, using the same format. I gave them underscore prefixes to make
+     them sort separately:
+     _NAME.md, _SYNOPSIS.md, _DESCRIPTION.md, _URL.md, _GLOBBING.md,
+     _VARIABLES.md, _OUTPUT.md, _PROTOCOLS.md, _PROGRESS.md, _VERSION.md,
+     _OPTIONS.md, _FILES.md, _ENVIRONMENT.md, _PROXYPREFIX.md,
+     _EXITCODES.md, _BUGS.md, _AUTHORS.md, _WWW.md, _SEEALSO.md
 
-- tests/sshserver.pl: Define AddressFamily earlier
+   - updated test cases accordingly
 
-  As the comment states "Address family must be specified before ListenAddress"
-  , otherwise the tests fail to run
-  `"failed starting SSH server" 52 times (582, 583, 600, 601, 602, 603, 604, 60
-  5, 606 and 43 more)`
+  Closes #12751
 
-  Closes #10983
+dependabot[bot] (23 Jan 2024)
 
-Stefan Eissing (18 Apr 2023)
+- CI: bump actions/cache from 3 to 4
 
-- quiche: Enable IDLE egress handling
+  Bumps [actions/cache](https://github.com/actions/cache) from 3 to 4.
+  - [Release notes](https://github.com/actions/cache/releases)
+  - [Changelog](https://github.com/actions/cache/blob/main/RELEASES.md)
+  - [Commits](https://github.com/actions/cache/compare/v3...v4)
 
-  Follow-up to 544abeea which added the handling but wrongly left it
-  commented out.
+  ---
+  updated-dependencies:
+  - dependency-name: actions/cache
+    dependency-type: direct:production
+    update-type: version-update:semver-major
+  ...
 
-  Closes https://github.com/curl/curl/pull/11000
+  Signed-off-by: dependabot[bot] 
+  Closes #12756
 
-Daniel Stenberg (18 Apr 2023)
+Daniel Stenberg (23 Jan 2024)
 
-- docs/examples/protofeats.c: Outputs all protocols and features
+- openssl: when verifystatus fails, remove session id from cache
 
-  Showing off one way to get to char pointer arrays of info returned by
-  curl_version_info()
+  To prevent that it gets used in a subsequent transfer that skips the
+  verifystatus check since that check can't be done when the session id is
+  reused.
 
-  Closes #10991
+  Reported-by: Hiroki Kurosawa
+  Closes #12760
 
-- tests/keywords.pl: remove
+Viktor Szakats (23 Jan 2024)
 
-  This script does not work since the introduction of the test
-  preprocessing. If we need this functionality, it probably needs to be
-  moved into the runtests tool or similar.
+- cmake: add option to disable building docs
 
-  Reported-by: Dan Fandrich
-  Fixes #10895
-  Closes #10987
+Richard Levitte (23 Jan 2024)
 
-Stefan Eissing (17 Apr 2023)
+- cmake: use curldown to build man pages
 
-- http2: support HTTP/2 to forward proxies, non-tunneling
+  This throws away the previous HTML and PDF producers, to mimic what
+  Makefile.am does as faithfully as possible.
 
-  - with `--proxy-http2` allow h2 ALPN negotiation to
-    forward proxies
-  - applies to http: requests against a https: proxy only,
-    as https: requests will auto-tunnel
-  - adding a HTTP/1 request parser in http1.c
-  - removed h2h3.c
-  - using new request parser in nghttp2 and all h3 backends
-  - adding test 2603 for request parser
-  - adding h2 proxy test cases to test_10_*
+  Closes #12753
 
-  scorecard.py: request scoring accidentally always run curl
-  with '-v'. Removed that, expect double numbers.
+Daniel Stenberg (23 Jan 2024)
 
-  labeller: added http1.* and h2-proxy sources to detection
+- mksymbolsmanpage.pl: provide references to where the symbol is used
 
-  Closes #10967
+- docs: introduce "curldown" for libcurl man page format
 
-Daniel Stenberg (17 Apr 2023)
+  curldown is this new file format for libcurl man pages. It is markdown
+  inspired with differences:
 
-- curl_easy_unescape.3: rename the argument
+  - Each file has a set of leading headers with meta-data
+  - Supports a small subset of markdown
+  - Uses .md file extensions for editors/IDE/GitHub to treat them nicely
+  - Generates man pages very similar to the previous ones
+  - Generates man pages that still convert nicely to HTML on the website
+  - Detects and highlights mentions of curl symbols automatically (when
+    their man page section is specified)
 
-  and highlight it appropriately in the text.
+  tools:
 
-  Closes #10979
+  - cd2nroff: converts from curldown to nroff man page
+  - nroff2cd: convert an (old) nroff man page to curldown
+  - cdall: convert many nroff pages to curldown versions
+  - cd2cd: verifies and updates a curldown to latest curldown
 
-Viktor Szakats (17 Apr 2023)
+  This setup generates .3 versions of all the curldown versions at build time.
 
-- autotools: sync up clang picky warnings with cmake
+  CI:
 
-  Bringing missing options over from CMake.
+  Since the documentation is now technically markdown in the eyes of many
+  things, the CI runs many more tests and checks on this documentation,
+  including proselint, link checkers and tests that make sure we capitalize the
+  first letter after a period...
 
-  Move around existing `-Wno-pointer-bool-conversion` option to come
-  _after_ `-Wconversion`.
+  Closes #12730
 
-  Reviewed-by: Marcel Raad
-  Closes #10974
+Viktor Szakats (22 Jan 2024)
 
-Daniel Stenberg (17 Apr 2023)
+- libssh2: use `libssh2_session_callback_set2()` with v1.11.1
 
-- tests/libtest/lib1900.c: remove
+  To avoid a local hack to pass function pointers and to avoid
+  deprecation warnings when building with libssh2 v1.11.1 or newer:
+  ```
+  lib/vssh/libssh2.c:3324:5: warning: 'libssh2_session_callback_set' is depreca
+  ted: since libssh2 1.11.1. Use libssh2_session_callback_set2() [-Wdeprecated-
+  declarations]
+  lib/vssh/libssh2.c:3326:5: warning: 'libssh2_session_callback_set' is depreca
+  ted: since libssh2 1.11.1. Use libssh2_session_callback_set2() [-Wdeprecated-
+  declarations]
+  ```
+  Ref: https://github.com/curl/curl-for-win/actions/runs/7609484879/job/2072082
+  1100#step:3:4982
 
-  This file was left behind when the rest of the test was previously removed.
+  Ref: https://github.com/libssh2/libssh2/pull/1285
+  Ref: https://github.com/libssh2/libssh2/commit/c0f69548be902147ce014ffa40b8db
+  3cf1d4b0b4
+  Reviewed-by: Daniel Stenberg
+  Closes #12754
 
-  Follow-up to e50a877df74f
+Daniel Stenberg (22 Jan 2024)
 
-- src/tool_operhlp.c: fix value stored to 'uerr' is never read
+- transfer: make the select_bits_paused condition check both directions
 
-  Ref: https://github.com/curl/curl/pull/10974#issuecomment-1510461343
-  Reported-by: Viktor Szakats
-  Closes #10982
+  If there is activity in a direction that is not paused, return false.
 
-Viktor Szakats (16 Apr 2023)
+  Reported-by: Sergey Bronnikov
+  Bug: https://curl.se/mail/lib-2024-01/0049.html
+  Closes #12740
 
-- cmake: speed up and extend picky clang/gcc options
+Stefan Eissing (22 Jan 2024)
 
-  Extend existing picky compiler options with ones missing compared to
-  autotools builds. Also sync options between clang and gcc.
+- http3: initial support for OpenSSL 3.2 QUIC stack
 
-  Redesign the way we enable these options to avoid the slow option
-  detection almost completely.
+  - HTTP/3 for curl using OpenSSL's own QUIC stack together
+    with nghttp3
+  - configure with `--with-openssl-quic` to enable curl to
+    build this. This requires the nghttp3 library
+  - implementation with the following restrictions:
+    * macOS has to use an unconnected UDP socket due to an
+      issue in OpenSSL's datagram implementation
+      See https://github.com/openssl/openssl/issues/23251
+      This makes connections to non-reponsive servers hang.
+    * GET requests will send the indicator that they have
+      no body in a separate QUIC packet. This may result
+      in processing delays or Transfer-Encodings on proxied
+      requests
+    * uploads that encounter blocks will use 100% cpu as
+      detection of these flow control issue is not working
+      (we have not figured out to pry that from OpenSSL).
 
-  This reduces the number of detections from 35 to zero for clang and
-  3 for gcc, even after adding a bunch of new options.
+  Closes #12734
 
-  clang 3.0 (2011-11-29) and gcc 2.95 (1999-07-31) now required.
+Viktor Szakats (22 Jan 2024)
 
-  Also show enabled picky options.
+- cmake: fix `ENABLE_MANUAL` option
 
-  Ref: https://github.com/libssh2/libssh2/pull/952
+  Fix the `ENABLE_MANUAL` option. Set it to default to `OFF`.
 
-  Reviewed-by: Daniel Stenberg
-  Closes #10973
+  Before this patch `ENABLE_MANUAL=ON` was a no-op, even though it was the
+  option designed to enable building and using the built-in curl manual.
+  (`USE_MANUAL=ON` option worked for this instead, by accident).
 
-Andreas Falkenhahn (16 Apr 2023)
+  Ref: https://github.com/curl/curl/pull/12730#issuecomment-1902572409
+  Closes #12749
 
-- nbtlm: use semicolons instead of commas for (void) args
+Mohammadreza Hendiani (19 Jan 2024)
 
-  Closes #10978
+- TODO: update broken link to ratelimit-headers draft
 
-Daniel Stenberg (15 Apr 2023)
+  Closes #12741
 
-- multi: free up more data earleier in DONE
+Daniel Stenberg (19 Jan 2024)
 
-  Before checking for more users of the connection and possibly bailing
-  out.
+- cmake: when USE_MANUAL=YES, build the curl.1 man page
 
-  Fixes #10971
-  Reported-by: Paweł Wegner
-  Closes #10972
+  Fixes KNOWN_BUG 15.4
 
-- RELEASE-NOTES: synced
+  Closes #12742
 
-- curl: do NOT append file name to path for upload when there's a query
+- cmdline-opts/write-out.d: remove spurious double quotes
 
-  Added test 425 to verify.
+Stefan Eissing (19 Jan 2024)
 
-  Reported-by: Dirk Rosenkranz
-  Bug: https://curl.se/mail/archive-2023-04/0008.html
-  Closes #10969
+- rtsp: Convert assertion into debug log
 
-- libcurl-thread.3: improved name resolver wording
+  Bug: https://bugs.chromium.org/p/oss-fuzz/issues/detail?id=65934
 
-  And make better .SH sections
+  - write excess bytes to the client where the standard excess bytes
+    checks will report any wrongness and fail the transfer
 
-  Closes #10966
+  Fixes #12738
+  Closes #12739
 
-Colman Mbuya (14 Apr 2023)
+Daniel Stenberg (19 Jan 2024)
 
-- CURLOPT_PROXY_SSL_VERIFYPEER.3: fix minor grammar mistake
+- headers: remove assert from Curl_headers_push
 
-  Closes #10968
+  The fuzzer managed to reach the function without a terminating CR or LF
+  so let's handle it normally. While there, remove the goto.
 
-Daniel Stenberg (14 Apr 2023)
+  Bug: https://bugs.chromium.org/p/oss-fuzz/issues/detail?id=65839
 
-- curl: add --proxy-http2
+  Closes #12721
 
-  For trying HTTP/2 with an HTTPS proxy.
+- curl_easy_getinfo.3: remove the wrong time value count
 
-  Closes #10926
+  It said "six" time values but they are eight by now. Remove the mention
+  of the amount.
 
-- KNOWN_BUGS: remove fixed or outdated issues, move non-bugs
+  Closes #12727
 
-  - remove h3 issues believed to be fixed
+Viktor Szakats (18 Jan 2024)
 
-  - make the flaky CI issue be generic and not Windows specific
+- mbedtls: fix `-Wnull-dereference` and `-Wredundant-decls`
 
-  - "TLS session cache does not work with TFO" now documented
+  - Silence warning in mbedTLS v3.5.1 public headers:
+    ```
+    ./mbedtls/_x64-linux-musl/usr/include/psa/crypto_extra.h:489:14: warning: r
+  edundant redeclaration of 'psa_set_key_domain_parameters' [-Wredundant-decls]
+    ./mbedtls/_x64-linux-musl/usr/include/psa/crypto_struct.h:354:14: note: pre
+  vious declaration of 'psa_set_key_domain_parameters' was here
+    ```
+    Ref: https://github.com/libssh2/libssh2/commit/ecec68a2c13a9c63fe8c2dc457ae
+  785a513e157c
+    Ref: https://github.com/libssh2/libssh2/pull/1226
 
-    This is now a documented restriction and not a bug. TFO in general is
-    rarely used and has other problems, making it a low-priotity thing to
-    work on.
+  - Fix compiler warnings seen with gcc 9.2.0 + cmake unity:
+    ```
+    ./curl/lib/vtls/mbedtls.c: In function 'mbedtls_bio_cf_read':
+    ./curl/lib/vtls/mbedtls.c:189:11: warning: null pointer dereference [-Wnull
+  -dereference]
+      189 |   nread = Curl_conn_cf_recv(cf->next, data, (char *)buf, blen, &res
+  ult);
+          |           ^~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+  ~~~~
+    ./curl/lib/vtls/mbedtls.c: In function 'mbedtls_bio_cf_write':
+    ./curl/lib/vtls/mbedtls.c:168:14: warning: null pointer dereference [-Wnull
+  -dereference]
+      168 |   nwritten = Curl_conn_cf_send(cf->next, data, (char *)buf, blen, &
+  result);
+          |              ^~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+  ~~~~~~~
+    ```
 
-  - remove "Renegotiate from server may cause hang for OpenSSL backend"
+  - delete stray `#else`.
 
-    This is an OpenSSL issue, not a curl one. Even if it taints curl.
+  Closes #12720
 
-  - rm "make distclean loops forever"
+Daniel Stenberg (17 Jan 2024)
 
-  - rm "configure finding libs in wrong directory"
+- docs: cleanup nroff format use
 
-    Added a section to docs/INSTALL.md about it.
+  - remove use of .BI for code snippet
+  - stop using .br, just do a blank line
+  - remove use of .PP
+  - remove use for .sp
+  - remove backslash in .IP
+  - use .IP instead of .TP
 
-  - "A shared connection cache is not thread-safe"
+  Closes #12731
 
-    Moved over to TODO and expanded for other sharing improvements we
-    could do
+Stefan Eissing (17 Jan 2024)
 
-  - rm "CURLOPT_OPENSOCKETPAIRFUNCTION is missing"
+- test2307: fix expected failure code after ws refactoring
 
-  - rm "Blocking socket operations in non-blocking API"
+  Fixes #12722
+  Closes #12728
 
-    Already listed as a TODO
+Jay Satiro (17 Jan 2024)
 
-  - rm "curl compiled on OSX 10.13 failed to run on OSX 10.10"
+- cf-socket: show errno in tcpkeepalive error messages
 
-    Water under the bridge. No one cares about this anymore.
+  - If the socket keepalive options (TCP_KEEPIDLE, etc) cannot be set
+    then show the errno in the verbose error messages.
 
-  - rm "build on Linux links libcurl to libdl"
+  Ref: https://github.com/curl/curl/discussions/12715#discussioncomment-8151652
 
-    Verified to not be true (anymore).
+  Closes https://github.com/curl/curl/pull/12726
 
-  - rm "libpsl is not supported"
+- tool_getparam: stop supporting `@filename` style for --cookie
 
-    The cmake build supports it since cafb356e19cda22
+  The `@filename` style was never documented for --cookie 
+  but prior to this change curl would accept it anyway and always treat a
+  @ prefixed string as a filename.
 
-  Closes #10963
+  That's a problem if the string also contains a = sign because then it is
+  documented to be interpreted as a cookie string and not a filename.
 
-- url: fix PVS nits
+  Example:
 
-  - expression 'hostptr' is always true
-  - a part of conditional expression is always true: proxypasswd
-  - expression 'proxyuser' is always true
-  - avoid multiple Curl_now() calls in allocate_conn
+  `--cookie @foo=bar`
 
-  Ref: #10929
-  Closes #10959
+  Before: Interpreted as load cookies from filename foo=bar.
 
-- bufq: simplify since expression is always true
+  After: Interpreted as cookie `@foo=bar` (name `@foo` and value `bar`).
 
-  The check for 'len' is already done so it will remain true until
-  updated. Pointed out by PVS.
+  Other curl options with a data/filename option-value use the `@filename`
+  to distinguish filenames which is probably how this happened. The
+  --cookie option has never been documented that way.
 
-  Ref: #10929
-  Closes #10958
+  Ref: https://curl.se/docs/manpage.html#-b
 
-- hash: fix assigning same value
+  Closes https://github.com/curl/curl/pull/12645
 
-  Pointed out by PVS
+Stefan Eissing (16 Jan 2024)
 
-  Ref: #10929
-  Closes #10956
+- websockets: refactor decode chain
 
-- cookie: address PVS nits
+  - use client writer stack for decoding frames
+  - move websocket protocol handler to ws.c
 
-  - avoid assigning the same value again
-  - remove superfluous check of co->domain
-  - reduce variable scope for namep/valuep
+  Closes #12713
 
-  Ref: #10929
-  Closes #10954
+- websockets: check for negative payload lengths
 
-Stefan Eissing (14 Apr 2023)
+  - in en- and decoding, check the websocket frame payload lengths for
+    negative values (from curl_off_t) and error the operation in that case
+  - add test 2307 to verify
 
-- cf-socket: Disable socket receive buffer by default
+  Closes #12707
 
-  - Disable socket receive buffer unless USE_RECV_BEFORE_SEND_WORKAROUND
-    is in place.
+Daniel Stenberg (16 Jan 2024)
 
-  While we would like to use the receive buffer, we have stalls in
-  parallel transfers where not all buffered data is consumed and no socket
-  events happen.
+- docs: mention env vars not used by schannel
 
-  Note USE_RECV_BEFORE_SEND_WORKAROUND is a Windows sockets workaround
-  that has been disabled by default since b4b6e4f1, due to other bugs.
+  Ref: #12704
 
-  Closes https://github.com/curl/curl/pull/10961
+  Co-authored-by: Jay Satiro 
 
-- cf-h2-proxy: fix processing ingress to stop too early
+  Closes #12711
 
-  - progress ingress stopped too early, causing data
-    from the underlying filters to not be processed and
-    report that no tunnel data was available
-  - this lead to "hangers" where no socket activity was
-    seen but data rested in buffers
+- tool_operate: make --remove-on-error only remove "real" files
 
-  Closes #10952
+  Reported-by: Harry Sintonen
+  Assisted-by: Dan Fandrich
 
-- http3: check stream_ctx more thoroughly in all backends
+  Closes #12710
 
-  - callbacks and filter methods might be invoked at unexpected
-    times, e.g. when the transfer's stream_ctx has not been initialized
-    yet or, more likely, has already been taken down.
-  - check for existance of stream_ctx in such places and return
-    an error or silently succeed the call.
+Jay Wu (16 Jan 2024)
 
-  Closes #10951
+- url: don't set default CA paths for Secure Transport backend
 
-Daniel Stenberg (13 Apr 2023)
+  As the default for this backend is the native CA store.
 
-- ftp: fix 'portsock' variable was assigned the same value
+  Closes #12704
 
-  Pointed out by PVS
+Lin Sun (16 Jan 2024)
 
-  Ref: #10929
-  Closes #10955
+- asyn-ares: with modern c-ares, use its default timeout
 
-- ftp: remove dead code
+  Closes #12703
 
-  This condition can never be true here since it is handled already 28
-  lines above.
+Daniel Stenberg (15 Jan 2024)
 
-  Pointed out by PVS.
+- tool_operate: stop setting the file comment on Amiga
 
-  Ref: #10929
-  Closes #10957
+  - the URL is capped at 80 cols, which ruins it if longer
+  - it does not strip off URL credentials
+  - it is done unconditonally, not on --xattr
+  - we don't have Amiga in the CI which makes fixing it blindly fragile
 
-- cf-h1-proxy: skip an extra NULL assign
+  Someone who builds and tests on Amiga can add it back correctly in a
+  future if there is a desire.
 
-  and use Curl_safefree() once to save another NULL assign. Found by PVS.
+  Reported-by: Harry Sintonen
+  Closes #12709
 
-  Ref. #10929
-  Closes #10953
+Stefan Eissing (15 Jan 2024)
 
-Philip Heiduck (13 Apr 2023)
+- rtsp: deal with borked server responses
 
-- GHA: suppress git clone output
+  - enforce a response body length of 0, if the
+    response has no Content-lenght. This is according
+    to the RTSP spec.
+  - excess bytes in a response body are forwarded to
+    the client writers which will report and fail the
+    transfer
 
-  Follow-up: https://github.com/curl/curl/commit/8203aa6ed405ec832d2c62f18dfda2
-  93f89a23f9
+  Follow-up to d7b6ce6
+  Fixes #12701
+  Closes #12706
 
-  Closes #10949
+Daniel Stenberg (14 Jan 2024)
 
-Stefan Eissing (13 Apr 2023)
+- version: show only the libpsl version, not its dependencies
 
-- cf-socket: remove dead code discovered by PVS
+  The libpsl version output otherwise also includes version number for its
+  dependencies, like IDN lib, but since libcurl does not use libpsl's IDN
+  functionality those components are not important.
 
-  Closes #10960
+  Ref: https://github.com/curl/curl-for-win/issues/63
+  Closes #12700
 
-Daniel Stenberg (13 Apr 2023)
+Brad Harder (14 Jan 2024)
 
-- http: skip a double NULL assign
+- curl.h: CURLOPT_DNS_SERVERS is only available with c-ares
 
-  and also use a local variable to shorten the long names and increase
-  readability in the function. Pointed out by PVS.
+  Closes #12695
 
-  Ref: #10929
-  Closes #10950
+Daniel Stenberg (14 Jan 2024)
 
-- mime: skip NULL assigns after Curl_safefree()
+- cmdline-opts/gen.pl: error on initital blank line
 
-  Pointed out by PVS.
+  After the "---" separator, there should be no blank line and this script
+  now errors out if one is detected.
 
-  Ref: #10929
-  Closes #10947
+  Ref: #12696
+  Closes #12698
 
-- rtsp: skip NULL assigns after Curl_safefree()
+- cf-h1-proxy: no CURLOPT_USERAGENT in CONNECT with hyper
 
-  ... since this is a macro that assigns NULL itself. Pointed out by PVS.
+  Follow-up to 693cd1679361828a which was incomplete
 
-  Ref: #10929
-  Closes #10946
+  Ref #12680
+  Closes #12697
 
-- smb: remove double assign
+- curl_multi_fdset.3: remove mention of null pointer support
 
-  The same value is assigned the same value already a few lines above.
-  Pointed out by PVS.
+  ... since this funtion has not supported null pointer fd_set arguments since
+  at least 2006. (That's when I stopped my git blame journey)
 
-  Ref: #10929
-  Closes #10945
+  Fixes #12691
+  Reported-by: sfan5 on github
+  Closes #12692
 
-- transfer: skip extra assign
+Mark Huang (14 Jan 2024)
 
-  The 'result' variable already contains CURLE_OK at this point, no use in
-  setting it again. Pointed out by PVS.
+- docs/cmdline: remove unnecessary line breaks
 
-  Ref: #10929
-  Closes #10944
+  Closes #12696
 
-- urlapi: skip a pointless assign
+Daniel Stenberg (14 Jan 2024)
 
-  It stores a null byte after already having confirmed there is a null
-  byte there. Detected by PVS.
+- transfer: remove warning: Value stored to 'blen' is never read
 
-  Ref: #10929
-  Closes #10943
+  Detected by scan-build
 
-Philip Heiduck (13 Apr 2023)
+  Follow-up from 1cd2f0072f
 
-- GHA: suppress git clone output
+  Closes #12693
 
-  Closes #10939
+Stefan Eissing (13 Jan 2024)
 
-Stefan Eissing (13 Apr 2023)
+- lib: replace readwrite with write_resp
 
-- tests: make test_12_01 a bit more forgiving on connection counts
+  This clarifies the handling of server responses by folding the code for
+  the complicated protocols into their protocol handlers. This concerns
+  mainly HTTP and its bastard sibling RTSP.
 
-- cf-socket: add socket recv buffering for most tcp cases
+  The terms "read" and "write" are often used without clear context if
+  they refer to the connect or the client/application side of a
+  transfer. This PR uses "read/write" for operations on the client side
+  and "send/receive" for the connection, e.g. server side. If this is
+  considered useful, we can revisit renaming of further methods in another
+  PR.
 
-  - use bufq as recv buffer, also for Windows pre-receive handling
-  - catch small reads followed by larger ones in a single socket
-    call. A common pattern on TLS connections.
+  Curl's protocol handler `readwrite()` method been changed:
 
-  Closes #10787
+  ```diff
+  -  CURLcode (*readwrite)(struct Curl_easy *data, struct connectdata *conn,
+  -                        const char *buf, size_t blen,
+  -                        size_t *pconsumed, bool *readmore);
+  +  CURLcode (*write_resp)(struct Curl_easy *data, const char *buf, size_t ble
+  n,
+  +                         bool is_eos, bool *done);
+  ```
 
-Daniel Stenberg (13 Apr 2023)
+  The name was changed to clarify that this writes reponse data to the
+  client side. The parameter changes are:
+
+  * `conn` removed as it always operates on `data->conn`
+  * `pconsumed` removed as the method needs to handle all data on success
+  * `readmore` removed as no longer necessary
+  * `is_eos` as indicator that this is the last call for the transfer
+    response (end-of-stream).
+  * `done` TRUE on return iff the transfer response is to be treated as
+    finished
+
+  This change affects many files only because of updated comments in
+  handlers that provide no implementation. The real change is that the
+  HTTP protocol handlers now provide an implementation.
+
+  The HTTP protocol handlers `write_resp()` implementation will get passed
+  **all** raw data of a server response for the transfer. The HTTP/1.x
+  formatted status and headers, as well as the undecoded response
+  body. `Curl_http_write_resp_hds()` is used internally to parse the
+  response headers and pass them on. This method is public as the RTSP
+  protocol handler also uses it.
+
+  HTTP/1.1 "chunked" transport encoding is now part of the general
+  *content encoding* writer stack, just like other encodings. A new flag
+  `CLIENTWRITE_EOS` was added for the last client write. This allows
+  writers to verify that they are in a valid end state. The chunked
+  decoder will check if it indeed has seen the last chunk.
+
+  The general response handling in `transfer.c:466` happens in function
+  `readwrite_data()`. This mainly operates now like:
 
-- urlapi: cleanups
+  ```
+  static CURLcode readwrite_data(data, ...)
+  {
+    do {
+      Curl_xfer_recv_resp(data, buf)
+      ...
+      Curl_xfer_write_resp(data, buf)
+      ...
+    } while(interested);
+    ...
+  }
+  ```
 
-  - move host checks together
-  - simplify the scheme parser loop and the end of host name parser
-  - avoid itermediate buffer storing in multiple places
-  - reduce scope for several variables
-  - skip the Curl_dyn_tail() call for speed
-  - detect IPv6 earlier and skip extra checks for such hosts
-  - normalize directly in dynbuf instead of itermediate buffer
-  - split out the IPv6 parser into its own funciton
-  - call the IPv6 parser directly for ipv6 addresses
-  - remove (unused) special treatment of % in host names
-  - junkscan() once in the beginning instead of scattered
-  - make junkscan return error code
-  - remove unused query management from dedotdotify()
-  - make Curl_parse_login_details use memchr
-  - more use of memchr() instead of strchr() and less strlen() calls
-  - make junkscan check and return the URL length
+  All the response data handling is implemented in
+  `Curl_xfer_write_resp()`. It calls the protocol handler's `write_resp()`
+  implementation if available, or does the default behaviour.
 
-  An optimized build runs one of my benchmark URL parsing programs ~41%
-  faster using this branch. (compared against the shipped 7.88.1 library
-  in Debian)
+  All raw response data needs to pass through this function. Which also
+  means that anyone in possession of such data may call
+  `Curl_xfer_write_resp()`.
 
-  Closes #10935
+  Closes #12480
 
-Josh McCullough (13 Apr 2023)
+Daniel Stenberg (13 Jan 2024)
 
-- http2: fix typo in infof() call
+- RELEASE-NOTES: synced
 
-  Closes #10940
+- TODO: TFTP doesn't convert LF to CRLF for mode=netascii
 
-Daniel Stenberg (12 Apr 2023)
+  Closes #12655
+  Closes #12690
 
-- noproxy: pointer to local array 'hostip' is stored outside scope
+- gen: do italics/bold for a range of letters, not just single word
 
-  Ref: #10929
-  Closes #10933
+  Previously it would match only on a sequence of non-space, which made it
+  miss to highlight for example "public suffix list".
 
-Stefan Eissing (12 Apr 2023)
+  Updated the recent cookie.d edit from 5da57193b732 to use bold instead
+  of italics.
 
-- connect: fix https connection setup to treat ssl_mode correctly
+  Closes #12689
 
-  - for HTTPS protocol, a disabled ssl should never be acceptables.
+- docs: describe and highlight super cookies
 
-  Closes #10934
+  Reported-by: Yadhu Krishna M
 
-Douglas R. Reno (12 Apr 2023)
+  Closes #12687
 
-- CMakeLists.txt: fix typo for Haiku detection
+- configure: when enabling QUIC, check that TLS supports QUIC
 
-  Closes #10937
+  Most importantly perhaps is when using OpenSSL that the used
+  build/flavor has the QUIC API: the vanilla OpenSSL does not, only
+  BoringSSL, libressl, AWS-LC and quictls do.
 
-Dan Fandrich (11 Apr 2023)
+  Ref: https://github.com/curl/curl/commit/5d044ad9480a9f556f4b6a252d7533b1ba7f
+  e57e#r136780413
 
-- pathhelp: use the cached $use_cygpath when available
+  Closes #12683
 
-- runtests: eliminate unneeded variable
+Stefan Eissing (11 Jan 2024)
 
-- runtests: make the # of server start attempts a constant
+- vquic: extract TLS setup into own source
 
-- runtests: on startup failure call displaylogs only in serverfortest
+  - separate ngtcp2 specific parts out
+  - provide callback during init to allow ngtcp2 to apply its defaults
 
-  This reduces the number of calls spread throughout the code.
+  Closes #12678
 
-  Ref: #10818
-  Closes #10919
+Sergey Markelov (11 Jan 2024)
 
-- runtests: return an error code with startservers()
+- multi: remove total timer reset in file_do() while fetching file://
 
-  The code indicates the kind of failure encountered in starting a server,
-  which can be used by the caller to tailor the user experience.
+  The total timer is properly reset in MSTATE_INIT.  MSTATE_CONNECT starts
+  with resetting the timer that is a start point for further multi states.
+  If file://, MSTATE_DO calls file_do() that should not reset the total
+  timer.  Otherwise, the total time is always less than the pre-transfer
+  and the start transfer times.
 
-  Ref: #10818
+  Closes #12682
 
-- runtests: abort early if runpingpongserver is given a bad server type
+Daniel Stenberg (11 Jan 2024)
 
-- runtests: don't use the SMB server verification time as reference
+- http_proxy: a blank CURLOPT_USERAGENT should not be used in CONNECT
 
-  %FTPTIME2 and %FTPTIME3 should be set by the FTP server only, for
-  consistency.
+  Extended test 80 to verify this.
 
-- tests: factor out the test server management code
+  Reported-by: Stefan Eissing
+  Fixes #12680
+  Closes #12681
 
-  This now lives in servers.pm with some configuration variables moved to
-  globalconfig.pm
+- sectransp: do verify_cert without memdup for blobs
 
-  Ref: #10818
+  Since the information is then already stored in memory, this can avoid
+  an extra set of malloc + free calls.
 
-- runtests: remove an inappropriate use of runclientoutput
+  Closes #12679
 
-  This function is intended for running client code, not servers.
+- hsts: remove assert for zero length domain
 
-- runtests: only add $LIBDIR to the path for checktestcmd
+  A zero length domain can happen if the HSTS parser is given invalid
+  input data which is not unheard of and is done by the fuzzer.
 
-  Since checkcmd is for finding servers, there will never be anything in
-  this directory of interest to them.
+  Follow-up from cfe7902111ae547873
 
-  Ref: #10818
+  Bug: https://bugs.chromium.org/p/oss-fuzz/issues/detail?id=65661
 
-- tests: log sshserver.pl messages to a file
+  Closes #12676
 
-  The logmsg messages were thrown away before, so they are now available
-  for debugging.
+- headers: make sure the trailing newline is not stored
 
-- runtests: also show DISABLED tests with -l
+  extended test1940 to verify blank header fields too
 
-  Other reasons for skipping tests are ignored for -l, so being explicitly
-  disabled should be too.
+  Bug: https://curl.se/mail/lib-2024-01/0019.html
+  Reported-by: Dmitry Karpov
+  Closes #12675
 
-- runtests: move the UNIX sockets into $PIDDIR
+- curl_easy_header.3: tiny language fix
 
-  These were missed when the other server files were moved there.
+  Closes #12672
 
-  Follow-up to 70d2fca2
+- examples/range.c: add
 
-  Ref: #10818
+  Closes #12671
 
-- tests: tighten up perl exports
+- examples/netrc.c: add
 
-  This reduces namespace pollution a little.
+  Closes #12671
 
-  Ref: #10818
+- examples/ipv6.c: new example showing IPv6-only internet transfer
 
-- tests: turn perl modules into full packages
+  Closes #12671
 
-  This helps enforce more modularization and encapsulation. Enable and fix
-  warnings on a few packages.  Also, rename ftp.pm to processhelp.pm since
-  there's really nothing ftp-specific in it.
+- examples/address-scope.c: renamed from ipv6.c
 
-  Ref: #10818
+  It shows address scope use really
 
-Daniel Stenberg (11 Apr 2023)
+  Closes #12671
 
-- multi: remove a few superfluous assigns
+Stefan Eissing (9 Jan 2024)
 
-  PVS found these "The 'rc' variable was assigned the same value." cases.
+- multi: pollset adjust, init with FIRSTSOCKET during connect
 
-  Ref: #10929
-  Closes #10932
+  - `conn->sockfd` is set by `Curl_setup_transfer()`, but that
+    is called *after* the connection has been established
+  - use `conn->sock[FIRSTSOCKET]` instead
 
-- schannel: add clarifying comment
+  Follow-up to a0f94800d507de
+  Closes #12664
 
-  Explaining how the PVS warning in #10929 is wrong: Dereferencing of the
-  null pointer 'backend->cred' might take place.
+Daniel Stenberg (9 Jan 2024)
 
-  Closes #10931
+- WEBSOCKET.md: remove dead link
 
-- cookie: clarify that init with data set to NULL reads no file
+- CI: spellcheck/appveyor: invoke configure --without-libpsl
 
-  ... and make Curl_cookie_add() require 'data' being set proper with an
-  assert.
+  Follow-up to 2998874bb61ac6
 
-  The function has not worked with a NULL data for quite some time so this
-  just corrects the code and comment.
+- cmdline/docs/*.d: switch to using ## instead of .IP
 
-  This is a different take than the proposed fixed in #10927
+  To make the editing easier. To write and to read.
 
-  Reported-by: Kvarec Lezki
-  Ref: #10929
-  Closes #10930
+  Closes #12667
 
-Kvarec Lezki (11 Apr 2023)
+- gen.pl: support ## for doing .IP in table-like lists
 
-- vtls: remove int typecast for sizeof()
+  Warn on use of .RS/.IP/.RE
 
-  V220 Suspicious sequence of types castings: memsize -> 32-bit integer ->
-  memsize. The value being cast: 'sizeof
-  (buf->data)'. curl\lib\vtls\vtls.c 2025
+  Closes #12667
 
-  https://pvs-studio.com/en/docs/warnings/v220/
+Jay Satiro (9 Jan 2024)
 
-  Closes #10928
+- cookie.d: Document use of empty string to enable cookie engine
 
-Stefan Eissing (11 Apr 2023)
+  - Explain that --cookie "" can be used to enable the cookie engine
+    without reading any initial cookies.
 
-- http2: fix copynpaste error reported by coverity
+  As is documented in CURLOPT_COOKIEFILE.
 
-  - move all code handling HTTP/2 frames for a particular
-    stream into a separate function to keep from confusing
-    the call `data` with the stream `data`.
+  Ref: https://curl.se/libcurl/c/CURLOPT_COOKIEFILE.html
 
-  Closes #10924
+  Bug: https://github.com/curl/curl/issues/12643#issuecomment-1879844420
+  Reported-by: janko-js@users.noreply.github.com
 
-Dan Fandrich (11 Apr 2023)
+  Closes https://github.com/curl/curl/pull/12646
 
-- tests: log a too-long Unix socket path in sws and socksd
+Daniel Stenberg (9 Jan 2024)
 
-  Ref: #10919
+- setopt: use memdup0 when cloning COPYPOSTFIELDS
 
-Daniel Stenberg (11 Apr 2023)
+  Closes #12651
 
-- gen.pl: error on duplicated See-Also fields
+- telnet: use dynbuf instad of malloc for escape buffer
 
-  Updated http2.d accordingly.
+  Previously, send_telnet_data() would malloc + free a buffer every time
+  for escaping IAC codes. Now, it reuses a dynbuf for this purpose.
 
-  Closes #10925
+  Closes #12652
 
-- http2: avoid possible null pointer dereference
+- CI: install libpsl or configure --without-libpsl in builds
 
-  Reported-by: Dan Fandrich
-  Fixes #10920
-  Closes #10923
+  As a follow-up to the stricted libpsl check in configure
 
-- lib1560: verify that more bad host names are rejected
+- configure: make libpsl detection failure cause error
 
-  when setting the hostname component of a URL
+  To force users to explictily disable it if they really don't want it
+  used and make it harder to accidentally miss it.
 
-  Closes #10922
+  --without-libpsl is the option to use if PSL is not wanted.
 
-- curl_url_set.3: mention that users can set content rather freely
+  Closes #12661
 
-  ... which then might render bad URLs if you extract a URL later.
+- RELEASE-NOTES: synced
 
-  Closes #10921
+- pop3: replace calloc + memcpy with memdup0
 
-Dan Fandrich (10 Apr 2023)
+  ... and make sure to return error on out of memory.
 
-- CI: retry failed downloads of aws-lc
+  Closes #12650
 
-  Don't fail the build in case of a temporary server problem.
+- lib: add debug log outputs for CURLE_BAD_FUNCTION_ARGUMENT
 
-- test1169: fix so it works properly everywhere
+  Closes #12658
 
-  - Use an absolute path for the -L option since the module isn't in the
-    perl path
-  - Create the needed test file in a  section;  isn't
-    intended for this
-  - Fix the test number in the file name, which was wrong
+- mime: use memdup0 instead of malloc + memcpy
 
-  Follow-up to f754990a
+  Closes #12649
 
-  Ref: #10818
-  Fixes #10889
-  Closes #10917
+- tool_getparam: move the --rate logic into set_rate()
 
-- tests: stop using strndup(), which isn't portable
+- tool_getparam: switch to an enum for every option
 
-  It's not available on Solaris 10, for example. Since this is just test
-  code that doesn't need to use an optimized system version, replace it
-  with the implementation copied from tool_cb_hdr.c.
+  To make the big switch much easier to read/understand and to make it
+  easier to add new options.
 
-- runtests: fix an incorrect comment about the ld_preload feature
+- tool_getparam: build post data using dynbuf (more)
 
-  Follow-up to 1f631864
+- tool_getparam: replace malloc + copy by dynbuf for --data
 
-  Ref: #10818
+- tool_getparam: make data_urlencode avoid direct malloc
 
-Daniel Stenberg (9 Apr 2023)
+  use aprintf() instead
 
-- urlapi: prevent setting invalid schemes with *url_set()
+- tool_getparam: move the --url-query logic into url_query()
 
-  A typical mistake would be to try to set "https://" - including the
-  separator - this is now rejected as that would then lead to
-  url_get(... URL...) would get an invalid URL extracted.
+  This function is not doing post at all so it was always weirdly placed.
 
-  Extended test 1560 to verify.
+- tool_getparam: move the --data logic into set_data()
 
-  Closes #10911
+- tool_getparam: unify the cmdline switch() into a single one
 
-Biswapriyo Nath (9 Apr 2023)
+  - easier to follow, easier to modify, easier to extend, possibly slightly
+    faster
 
-- http2: remove unused Curl_http2_strerror function declaration
+  - each case now has the long option as a comment
 
-  Curl_http2_strerror was renamed to http2_strerror in
-  05b100aee247bb9bec8e9a1b0 and then http2_strerror was removed in
-  5808a0d0f5ea0399d4a2a2
+- tool_getparam: bsearch cmdline options
 
-  This also fixes the following compiler error
+  - the option names are now alpha sorted and lookup is a lot faster
 
-  lib/http2.h:41:33: error: unknown type name 'uint32_t'
-  lib/http2.h:1:1: note: 'uint32_t' is defined in header ''
+  - use case sensitive matching. It was previously case insensitive, but that
+    was not documented nor tested.
 
-  Closes #10912
+  - remove "partial match" feature. It was not documented, not tested and
+    was always fragile as existing use could break when we add a new
+    option
 
-Daniel Stenberg (8 Apr 2023)
+  - lookup short options via a table
 
-- RELEASE-NOTES: synced
+  Closes #12631
 
-SuperIlu on github (8 Apr 2023)
+Gabe (8 Jan 2024)
 
-- config-dos.h: fix SIZEOF_CURL_OFF_T for MS-DOS/DJGPP
+- COPYING: update copyright year
 
-  Fixes #10905
-  Closes #10910
+  Closes #12654
 
-Daniel Stenberg (8 Apr 2023)
+Stefan Eissing (8 Jan 2024)
 
-- lib: remove CURLX_NO_MEMORY_CALLBACKS
+- url: init conn->sockfd and writesockfd to CURL_SOCKET_BAD
 
-  The only user of this define was 'chkdecimalpoint' - a special purpose
-  test tool that was built but not used anymore (since 17c18fbc3 - Apr
-  2020).
+  Also add more tracing to test 19
 
-  Closes #10908
+  Follow-up to a0f9480
 
-- CURLPROXY_HTTPS2: for HTTPS proxy that may speak HTTP/2
+  Fixes #12657
+  Closes #12659
 
-  Setting this proxy type allows curl to negotiate and use HTTP/2 with
-  HTTPS proxies.
+Daniel Stenberg (8 Jan 2024)
 
-  Closes #10900
+- connect: remove margin from eyeballer alloc
 
-Ali Khodkar (8 Apr 2023)
+  Presumably leftovers from debugging
 
-- write-out.d: add missing periods
+  Closes #12647
 
-  Closes #10897
+- ftp: only consider entry path if it has a length
 
-Daniel Stenberg (7 Apr 2023)
+  Follow-up from 8edcfedc1a144f438bd1cdf814a0016cb
 
-- http2: remove check for !data after it was already dereferenced
+  Bug: https://bugs.chromium.org/p/oss-fuzz/issues/detail?id=65631
 
-  Pointed out by Coverity
+  Avoids a NULL pointer deref.
 
-  Closes #10906
+  Closes #12648
 
-- http_proxy: provide missing arg to infof() call
+Stefan Eissing (7 Jan 2024)
 
-  Pointed out by Coverity
+- transfer: adjust_pollset improvements
+
+  - let `multi_getsock()` initialize the pollset in what the
+    transfer state requires in regards to SEND/RECV
+  - change connection filters `adjust_pollset()` implementation
+    to react on the presence of POLLIN/-OUT in the pollset and
+    no longer check CURL_WANT_SEND/CURL_WANT_RECV
+  - cf-socket will no longer add POLLIN on its own
+  - http2 and http/3 filters will only do adjustments if the
+    passed pollset wants to POLLIN/OUT for the transfer on
+    the socket. This is similar to the HTTP/2 proxy filter
+    and works in stacked filters.
+
+  Closes #12640
+
+Daniel Stenberg (6 Jan 2024)
+
+- ftp: use memdup0 to store the OS from a SYST 215 response
+
+  avoid malloc + direct buffer fiddle
+
+  Closes #12639
+
+- ftp: use dynbuf to store entrypath
+
+  avoid direct malloc
+
+  Closes #12638
+
+Lealem Amedie (6 Jan 2024)
+
+- wolfssl: load certificate *chain* for PEM client certs
+
+  Closes #12634
+
+Stefan Eissing (4 Jan 2024)
+
+- http: adjust_pollset fix
+
+  do not add a socket for POLLIN when the transfer does not want to send
+  (for example is paused).
+
+  Follow-up to 47f5b1a
+
+  Reported-by: bubbleguuum on github
+  Fixes #12632
+  Closes #12633
+
+Daniel Stenberg (3 Jan 2024)
+
+- tool: make parser reject blank arguments if not supported
+
+  Already in the getstr() function that clones the input argument.
+
+  Closes #12620
+
+dependabot[bot] (3 Jan 2024)
 
-  Closes #10904
+- build(deps): bump github/codeql-action from 2 to 3
 
-- content_encoding: only do tranfer-encoding compression if asked to
+  Bumps [github/codeql-action](https://github.com/github/codeql-action) from 2 
+  to 3.
+  - [Release notes](https://github.com/github/codeql-action/releases)
+  - [Changelog](https://github.com/github/codeql-action/blob/main/CHANGELOG.md)
+  - [Commits](https://github.com/github/codeql-action/compare/v2...v3)
 
-  To reduce surprises. Update test 387 and 418 accordingly.
+  ---
+  updated-dependencies:
+  - dependency-name: github/codeql-action
+    dependency-type: direct:production
+    update-type: version-update:semver-major
+  ...
 
-  Closes #10899
+  Signed-off-by: dependabot[bot] 
 
-- sws: comparison of unsigned expression < 0 is always false
+  Closes #12625
 
-  Follow-up to 356dd0b73a75ed6d5
+- build(deps): bump actions/checkout from 3 to 4
 
-  Closes #10903
+  Bumps [actions/checkout](https://github.com/actions/checkout) from 3 to 4.
+  - [Release notes](https://github.com/actions/checkout/releases)
+  - [Changelog](https://github.com/actions/checkout/blob/main/CHANGELOG.md)
+  - [Commits](https://github.com/actions/checkout/compare/v3...v4)
 
-- lib/cmake: add HAVE_WRITABLE_ARGV check
+  ---
+  updated-dependencies:
+  - dependency-name: actions/checkout
+    dependency-type: direct:production
+    update-type: version-update:semver-major
+  ...
 
-  Assisted-by: Jakub Zakrzewski
-  Closes #10896
+  Signed-off-by: dependabot[bot] 
 
-- configure: don't set HAVE_WRITABLE_ARGV on Windows
+  Closes #12624
 
-  Ref: #10888
-  Closes #10896
+- build(deps): bump actions/upload-artifact from 3 to 4
 
-- vtls: fix build error when proxy-disabled
+  Bumps [actions/upload-artifact](https://github.com/actions/upload-artifact) f
+  rom 3 to 4.
+  - [Release notes](https://github.com/actions/upload-artifact/releases)
+  - [Commits](https://github.com/actions/upload-artifact/compare/v3...v4)
 
-  Closes #10901
+  ---
+  updated-dependencies:
+  - dependency-name: actions/upload-artifact
+    dependency-type: direct:production
+    update-type: version-update:semver-major
+  ...
 
-Stefan Eissing (6 Apr 2023)
+  Signed-off-by: dependabot[bot] 
 
-- tests: increase sws timeout for more robust testing
+  Closes #12627
 
-  - for https CONNECT forwarding, this was fixed at 5 seconds
-    which led to spurious CI test failures
-  - add --keepalive parameter to sws to control this
-  - let httpserver use 30 seconds
+- build(deps): bump actions/download-artifact from 3 to 4
 
-  Closes #10898
+  Bumps [actions/download-artifact](https://github.com/actions/download-artifac
+  t) from 3 to 4.
+  - [Release notes](https://github.com/actions/download-artifact/releases)
+  - [Commits](https://github.com/actions/download-artifact/compare/v3...v4)
 
-- http2: move HTTP/2 stream vars into local context
+  ---
+  updated-dependencies:
+  - dependency-name: actions/download-artifact
+    dependency-type: direct:production
+    update-type: version-update:semver-major
+  ...
 
-  - remove NGHTTP2 members of `struct HTTP`
-  - add `void *h2_ctx` to `struct HTTP`
-  - add `void *h3_ctx` to `struct HTTP`
-  - separate h2/h3 pointers are needed for eyeballing
-  - manage local stream_ctx in http implementations
+  Signed-off-by: dependabot[bot] 
 
-  Closes #10877
+  Closes #12626
 
-- proxy: http2 proxy tunnel implementation
+Stefan Eissing (3 Jan 2024)
 
-  - currently only on debug build and when env variable
-    CURL_PROXY_TUNNEL_H2 is present.
-  - will ALPN negotiate with the proxy server and switch
-    tunnel filter based on the protocol negotiated.
-  - http/1.1 tunnel code moved into cf-h1-proxy.[ch]
-  - http/2 tunnel code implemented in cf-h2-proxy.[ch]
-  - tunnel start and ALPN set remains in http_proxy.c
-  - moving all haproxy related code into cf-haproxy.[ch]
+- http3/quiche: fix result code on a stream reset
 
-  VTLS changes
-  - SSL filters rely solely on the "alpn" specification they
-    are created with and no longer check conn->bits.tls_enable_alpn.
-  - checks on which ALPN specification to use (or none at all) are
-    done in vtls.c when creating the filter.
+  - fixes pytest failures in test 07_22
+  - aligns CURLcode values on stream reset with ngtcp2
 
-  Testing
-  - added a nghttpx forward proxy to the pytest setup that
-    speaks HTTP/2 and forwards all requests to the Apache httpd
-    forward proxy server.
-  - extending test coverage in test_10 cases
-  - adding proxy tests for direct/tunnel h1/h2 use of basic auth.
-  - adding test for http/1.1 and h2 proxy tunneling to pytest
+  Closes #12629
 
-  Closes #10780
+Daniel Stenberg (2 Jan 2024)
 
-- vtls and h2 improvements
+- setopt: clear mimepost when formp is freed
 
-  - eliminate receive loop in vtls to fill buffer. This may
-    lead to partial reads of data which is counter productive
-  - let http2 instead loop smarter to process pending network
-    data without transfer switches
+  A precaution to avoid a possibly dangling pointer left behind.
 
-  scorecard improvements
-  - do not start caddy when only httpd is requested
-  - allow curl -v to stderr file on --curl-verbose
+  Reported-by: Thomas Ferguson
+  Fixes #12608
+  Closes #12621
 
-  Closes #10891
+Andy Alt (2 Jan 2024)
 
-Daniel Stenberg (6 Apr 2023)
+- CI: Add dependabot.yml
 
-- tests: 1078 1288 1297 use valid IPv4 addresses
+  This will cause dependabot to open a PR when various actions are
+  updated, provided that the action maintainer has issued a release.
 
-  With the enhanced URL parser, these tests failed because of their bad
-  IPv4 use.
+  Closes #12623
 
-- urlapi: detect and error on illegal IPv4 addresses
+Gisle Vanem (2 Jan 2024)
 
-  Using bad numbers in an IPv4 numerical address now returns
-  CURLUE_BAD_HOSTNAME.
+- content_encoding: change return code to typedef'ed enum
 
-  I noticed while working on trurl and it was originally reported here:
-  https://github.com/curl/trurl/issues/78
+  ... to work around a clang ubsan warning.
 
-  Updated test 1560 accordingly.
+  Fixes #12618
+  Closes #12622
 
-  Closes #10894
+Daniel Stenberg (2 Jan 2024)
+
+- tool: prepend output_dir in header callback
+
+  When Content-Disposition parsing is used and an output dir is prepended,
+  make sure to store that new file name correctly so that it can be used
+  for setting the file timestamp when --remote-time is used.
+
+  Extended test 3012 to verify.
+
+  Co-Authored-by: Jay Satiro
+  Reported-by: hgdagon on github
+  Fixes #12614
+  Closes #12617
+
+- test1254: fix typo in name plus shorten it
 
 - RELEASE-NOTES: synced
 
-- urlapi: URL encoding for the URL missed the fragment
+Viktor Szakats (2 Jan 2024)
+
+- schannel: fix `-Warith-conversion` gcc 13 warning
+
+  ```
+  lib/vtls/schannel.c:1201:22: warning: conversion to 'unsigned int' from 'int'
+   may change the sign of the result [-Warith-conversion]
+   1201 |     *extension_len = *list_len +
+        |                      ^
+  ```
+
+  Closes #12616
+
+- asyn-thread: silence `-Wcast-align` warning for Windows
+
+  Seen with llvm/clang 17:
+  ```
+  lib/asyn-thread.c:310:5: warning: cast from 'PCHAR' (aka 'char *') to 'struct
+   thread_sync_data *' increases required alignment from 1 to 8 [-Wcast-align]
+    310 |     CONTAINING_RECORD(overlapped, struct thread_sync_data, w8.overlap
+  ped);
+        |     ^~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+  ~~~~
+  .../llvm-mingw/aarch64-w64-mingw32/include/winnt.h:717:48: note: expanded fro
+  m macro 'CONTAINING_RECORD'
+    717 | #define CONTAINING_RECORD(address,type,field) ((type *)((PCHAR)(addre
+  ss) - (ULONG_PTR)(&((type *)0)->field)))
+        |                                                ^~~~~~~~~~~~~~~~~~~~~~
+  ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+  ```
+
+  Follow-up to a6bbc87f9e9ffb46a1801dfb983e7534825ed56b #12482
+
+  Ref: https://github.com/curl/curl/pull/12482#issuecomment-1873017261
+  Closes #12615
+
+Daniel Stenberg (2 Jan 2024)
+
+- tool_listhelp: regenerate after recent .d updates
+
+  Makes it survive test 1478
+
+  Closes #12612
+
+- test1478: verify src/tool_listhelp.c
+
+  Verify that the source file on disk is identical to the output of gen.pl
+  listhelp, as otherwise they are out of sync and need attention.
+
+  Closes #12612
+
+- testutil: make runtests support %include
+
+  Using this instruction, a test case can include the contents of a file
+  into the test during the preprocessing.
+
+  Closes #12612
+
+- runtests: for mode="text" on , fix newlines on both parts
+
+  Closes #12612
+
+Jay Satiro (2 Jan 2024)
+
+- quiche: return CURLE_HTTP3 on send to invalid stream
+
+  Prior to this change if a send failed on a stream in an invalid state
+  (according to quiche) and not marked as closed (according to libcurl)
+  then the send function would return CURLE_SEND_ERROR.
+
+  We already have similar code for ngtcp2 to return CURLE_HTTP3 in this
+  case.
+
+  Caught by test test_07_upload.py: test_07_22_upload_parallel_fail.
+
+  Fixes https://github.com/curl/curl/issues/12590
+  Closes https://github.com/curl/curl/pull/12597
+
+Daniel Stenberg (1 Jan 2024)
+
+- cmdline-opts: update availability for the *-ca-native options
+
+  Closes #12613
+
+Patrick Monnerat (31 Dec 2023)
+
+- openldap: fix STARTTLS
+
+  It was not working anymore since introduction of connection filters.
+
+  Also do not attempt to recover from a failing TLS negotiation with
+  CURLUSESSL_TRY.
+
+  Closes #12610
+
+Daniel Stenberg (31 Dec 2023)
+
+- haproxy-clientip.d: document the arg
+
+  The arg keyword was missing and therefore not present in the man page.
+
+  Closes #12611
+
+annalee (29 Dec 2023)
+
+- configure: fix no default int compile error in ipv6 detection
+
+  Closes #12607
+
+Dan Fandrich (28 Dec 2023)
+
+- CI: Fix use of any-glob-to-all-files in the labeler
+
+  Despite its name, this atom acts like one-glob-to-all-files and a
+  different syntax with braces must be used to get
+  any-glob-to-all-files semantics. Unfortunately, this makes the file
+  completely unreadable.
+
+  Ref: https://github.com/actions/labeler/issues/731
+
+Daniel Stenberg (29 Dec 2023)
+
+- CURLOPT_AUTOREFERER.3: mention CURLINFO_REFERER
+
+- CURLINFO_REFERER.3: clarify that it is the *request* header
+
+  That libcurl itself sent in the most recent request
+
+  Closes #12605
+
+Jay Satiro (28 Dec 2023)
+
+- system_win32: fix a function pointer assignment warning
+
+  - Use CURLX_FUNCTION_CAST to suppress a function pointer assignment
+    warning.
+
+  a6bbc87f added lookups of some Windows API functions and then cast them
+  like `*(FARPROC*)&Curl_funcname = address`. Some versions of gcc warn
+  about that as breaking strict-aliasing rules so this PR changes those
+  assignments to use CURLX_FUNCTION_CAST.
+
+  Bug: https://github.com/curl/curl/pull/12581#issuecomment-1869804317
+  Reported-by: Marcel Raad
+
+  Closes https://github.com/curl/curl/pull/12602
+
+- verify-examples.pl: fail verification on unescaped backslash
+
+  - Check that all backslashes in EXAMPLE are properly escaped.
+
+  eg manpage must always use `\\n` never `\n`.
+
+  This is because the manpage requires we always double blackslash to show
+  a single backslash. Prior to this change an erroneous single backslash
+  would pass through and compile even though it would not show correctly
+  in the manpage.
+
+  Co-authored-by: Daniel Stenberg
+
+  Ref: https://github.com/curl/curl/pull/12588
+
+  Closes https://github.com/curl/curl/pull/12589
+
+- vtls: fix missing multissl version info
+
+  - Fix erroneous buffer copy logic from ff74cef5.
+
+  Prior to this change the MultiSSL version info returned to the user
+  was empty.
+
+  Closes https://github.com/curl/curl/pull/12599
+
+Daniel Stenberg (27 Dec 2023)
+
+- KNOWN_BUGS: [RTSP] Some methods do not support response bodies
+
+  Closes #12414
+
+Patrick Monnerat (27 Dec 2023)
+
+- openldap: fix an LDAP crash
+
+  Reported-by: Ozan Cansel
+  Fixes #12593
+  Closes #12600
+
+Daniel Stenberg (27 Dec 2023)
+
+- getinfo: CURLINFO_QUEUE_TIME_T
 
-  Meaning that it would wrongly still store the fragment using spaces
-  instead of %20 if allowing space while also asking for URL encoding.
+  Returns the time, in microseconds, during which this transfer was held
+  in a waiting queue before it started "for real". A transfer might be put
+  in a queue if after getting started, it cannot create a new connection
+  etc due to set conditions and limits imposed by the application.
 
-  Discovered when playing with trurl.
+  Ref: #12293
+  Closes #12368
 
-  Added test to lib1560 to verify the fix.
+- RELEASE-NOTES: synced
 
-  Closes #10887
+Jay Satiro (26 Dec 2023)
 
-- rtsp: convert mallocs to dynbuf for RTP buffering
+- examples/sendrecv: fix comment line length
 
-  Closes #10786
+  Caught by checksrc.
 
-- tool_writeout: add URL component variables
+Haydar Alaidrus (23 Dec 2023)
 
-  Output specific components from the used URL. The following variables
-  are added for this purpose:
+- CURLOPT_POSTFIELDS.3: fix incorrect C string escape in example
 
-    url.scheme, url.user, url.password, url.options, url.host, url.port,
-    url.path, url.query, url.fragment, url.zoneid
+  - Escape inner quotes with two backslashes.
 
-  Add the following for outputting parts of the "effective URL":
+  Two backslashes escapes the backslash for the man page and will show as
+  a single backslash.
 
-   urle.scheme, urle.user, urle.password, urle.options, urle.host, urle.port,
-   urle.path, urle.query, urle.fragment, urle.zoneid
+  eg: "{\\"name\\": \\"daniel\\"}" shows as "{\"name\": \"daniel\"}".
 
-  Added test 423 and 424 to verify.
+  Closes https://github.com/curl/curl/pull/12588
 
-  Closes #10853
+Viktor Szakats (23 Dec 2023)
 
-Stefan Eissing (4 Apr 2023)
+- appveyor: tidy-ups
 
-- tests/http: improved httpd detection
+  - replace two remaining backslashes with forward slashes.
+  - tidy up the way we form and pass `TFLAGS`.
 
-  - better error messages when not found/complete
-  - handling of `--without-test-httpd`
+  Follow-up to 2d4d0c1fd32f5cc3f946c407c8eccd5477b287df #12572
 
-  Reported-by: kwind on github
-  Fixes #10879
-  Closes #10883
+  Closes #12582
 
-Daniel Stenberg (4 Apr 2023)
+Stefan Eissing (22 Dec 2023)
 
-- configure: make quiche require quiche_conn_send_ack_eliciting
+- transfer: fix upload rate limiting, add test cases
 
-  curl now requires quiche version >= 1.17.1 to be used and this function
-  was added in this version and makes a convenient check.
+  - add test cases for rate limiting uploads for all
+    http versions
+  - fix transfer loop handling of limits. Signal a re-receive
+    attempt only on exhausting maxloops without an EAGAIN
+  - fix `data->state.selectbits` forcing re-receive to also
+    set re-sending when transfer is doing this.
 
-  This requirement is because this is the lowest quiche version that
-  supports peer-initiated key updates correctly.
+  Reported-by: Karthikdasari0423 on github
+  Fixes #12559
+  Closes #12586
 
-  Closes #10886
+Daniel Stenberg (22 Dec 2023)
 
-Dan Fandrich (1 Apr 2023)
+- mbedtls: free the entropy when threaded
 
-- unit tests: use the unit test infrastructure better
+  The entropy_free was never done for threaded builds, causing a small
+  (fixed) memory leak.
 
-  Allow UNITTEST_STOP to return the error code, use the fail & abort
-  macros to indicate test failure and return success instead of fail if
-  the unit test can't test anything because of missing features at
-  compile-time.  A couple of tests could never fail because they were
-  overriding the failure return code.
+  Reported-by: RevaliQaQ on github
+  Fixes #12584
+  Closes #12585
 
-- runtests: strip EOL on precheck output on Windows, too
+Stefan Eissing (22 Dec 2023)
 
-  Precheck failures would show on two lines in the test summary output
-  otherwise.
+- http2: improved on_stream_close/data_done handling
 
-- tests: move server config files under the pid dir
+  - there seems to be a code path that cleans up easy handles without
+    triggering DONE or DETACH events to the connection filters. This
+    would explain wh nghttp2 still holds stream user data
+  - add GOOD check to easy handle used in on_close_callback to
+    prevent crashes, ASSERTs in debug builds.
+  - NULL the stream user data early before submitting RST
+  - add checks in on_stream_close() to identify UNGOOD easy handles
 
-  These files are generated by the test servers and must therefore be
-  found in the log directory to make them available to only those servers
-  once multiple test runners are executing in parallel. They must also not
-  be deleted with the log files, so they are stored in the pidfile
-  directory.
+  Reported-by: Hans-Christian Egtvedt
+  Fixes #10936
+  Closes #12562
 
-  Ref: #10818
-  Closes #10875
+Daniel Stenberg (22 Dec 2023)
 
-- runtests: use the ssh key filenames from the sshhelp package
+- mprintf: overhaul and bugfixes
 
-- tests: move pidfiles and portfiles under the log directory
+  In a test case using lots of snprintf() calls using many commonly used
+  %-codes per call, this version is around 30% faster than previous
+  version.
 
-  This is to segregate all files written by a test process into a single
-  root to allow for future parallel testing.
+  It also fixes the #12561 bug which made it not behave correctly when
+  given unknown %-sequences. Fixing that flaw required a different take on
+  the problem, which resulted in the new two-arrays model.
 
-  Ref: #10818
-  Closes #10874
+  lib557: extended - Verify the #12561 fix and test more printf features
 
-- runtests: minor code cleanups
+  unit1398: fix test: It used a $ only for one argument, which is not
+  supported.
 
-- runtests: call processexists() and pidfromfile()
+  Fixes #12561
+  Closes #12563
 
-  rather than duplicating the logic in several places.
+Viktor Szakats (21 Dec 2023)
 
-Viktor Szakats (31 Mar 2023)
+- appveyor: replace PowerShell with bash + parallel autotools
 
-- cmake: do not add zlib headers for openssl
+  PowerShell works (after a steep development curve), but one property of
+  it stuck and kept causing unresolvable usability issues: With
+  `$ErrorActionPreference=Stop`, it does abort on failures, but shows only
+  the first line of the error message. In `Continue` mode, it shows the
+  full error message, but doesn't stop on all errors. Another issue is
+  PowerShell considering any stderr output as if the command failed (this
+  has been improved in 7.2 (2021-Nov), but fixed versions aren't running
+  in CI and will not be for a long time in all test images.)
 
-  Logic copied earlier from wolfSSL. wolfSSL requires zlib headers for its
-  public headers. OpenSSL does not, so stop adding zlib headers for it.
+  Thus, we're going with bash.
 
-  Follow-up to 1e3319a167d2f32d295603167486e9e88af9bb4e
+  Also:
+  - use `-j2` with autotools tests, making them finish 5-15 minutes per
+    job faster.
+  - omit `POSIX_PATH_PREFIX`.
+  - use `WINDIR`.
+  - prefer forward slashes.
 
-  Closes #10878
+  Follow-up to: 75078a415d9c769419aed4153d3d525a8eba95af #11999
+  Ref: #12444
 
-Stefan Eissing (31 Mar 2023)
+  Fixes #12560
+  Closes #12572
 
-- rustls: fix error in recv handling
+Pavel Pavlov (21 Dec 2023)
 
-  - when rustls is told to recieve more TLS data and its internal
-    plaintext buffers are full, it returns an IOERROR
-  - avoid receiving TLS data while plaintext is not read empty
+- asyn-thread: use GetAddrInfoExW on >= Windows 8
 
-  pytest:
-  - increase curl run timeout when invoking pytest with higher verbosity
+  For doing async DNS resolution instead of starting a thread for each
+  request.
 
-  Closes #10876
+  Fixes #12481
+  Closes #12482
 
-- http3: improvements across backends
+Daniel Stenberg (21 Dec 2023)
 
-  - ngtcp2: using bufq for recv stream data
-  - internal stream_ctx instead of `struct HTTP` members
-    for quiche, ngtcp2 and msh3
-  - no more QUIC related members in `struct HTTP`
-  - experimental use of recvmmsg(), disabled by default
-    - testing on my old debian box shows no throughput improvements.
-    - leaving it in, but disabled, for future revisit
-  - vquic: common UDP receive code for ngtcp2 and quiche
-  - vquic: common UDP send code for ngtcp2 and quiche
-  - added pytest skips for known msh3 failures
-  - fix unit2601 to survive torture testing
-  - quiche: using latest `master` from quiche and enabling large download
-    tests, now that key change is supported
-  - fixing test_07_21 where retry handling of starting a stream
-    was faulty
-  - msh3: use bufq for recv buffering headers and data
-  - msh3: replace fprintf debug logging with LOG_CF where possible
-  - msh3: force QUIC expire timers on recv/send to have more than
-    1 request per second served
+- strerror: repair get_winsock_error()
 
-  Closes #10772
+  It would try to read longer than the provided string and crash.
 
-Dan Fandrich (30 Mar 2023)
+  Follow-up to ff74cef5d4a0cf60106517a1c7384
+  Reported-by: calvin2021y on github
+  Fixes #12578
+  Closes #12579
 
-- test1471/2: add http as a required feature
+- CURLOPT_SSH_*_KEYFILE: clarify
 
-  curl bails out early with a different error message if http support is
-  compiled out.
+  Closes #12554
 
-  Ref: #10705
+ivanfywang (21 Dec 2023)
 
-- tests: limit return code of unit tests and lib tests
+- ngtcp2: put h3 at the front of alpn
 
-  Values greater than 125 have special meanings, so cap it there.  Unit
-  tests and lib tests use the number of failures as the return code, so a
-  large number of failures (such as test 2601 as a torture test) can
-  exceed this causing the test to be erroneously reported as having
-  failed.
+  Closes #12576
 
-  Ref: #10720
+Daniel Stenberg (21 Dec 2023)
 
-- test1960: point to the correct path for the precheck tool
+- test460: verify a command line using --expand with no argument
 
-  Otherwise, it might find the binary in .libs which can cause it to use
-  the system libcurl which can fail. This error is only visible by
-  noticing that the test is skipped.
+  This verifies the fix for #12565
 
-  Follow-up to e4dfe6fc
+- tool_getparam: do not try to expand without an argument
 
-  Ref: #10651
+  This would lead to a segfault.
 
-- tests: use the proper %LOGDIR path on two tests
+  Fixes #12565
+  Reported-by: Geeknik Labs
+  Closes #12575
 
-  Follow-up to e7a021e1
+- RELEASE-NOTES: synced
 
-  Ref: #10818
+  Bumped version to 8.6.0 because of changes
 
-Daniel Stenberg (30 Mar 2023)
+- Makefile.am: fix the MSVC project generation
 
-- rtsp: fix Value stored to 'skip_size' is never read
+  It made the vcxproj files not get included in dist tarballs.
 
-  Pointed out by scan-build
+  Regression since 74423b5df4c8117891eb89 (8.5.0)
 
-  Follow-up to 6c6306f3008f2c9b20a64
+  Reported-by: iAroc on github
+  Fixes #12564
+  Closes #12567
 
-  Closes #10872
+zengwei2000 (21 Dec 2023)
 
-Stefan Eissing (30 Mar 2023)
+- altsvc: free 'as' when returning error
 
-- tests/http: relax connection check in test_07_02
+  Closes #12570
 
-  Only 1 connection will be used when curl is slow, happens when
-  address-sanitized in CI, for example
+  Signed-off-by: zengwei 
 
-  Closes #10865
+Viktor Szakats (20 Dec 2023)
 
-- http2: flow control and buffer improvements
+- build: fix `-Wconversion`/`-Wsign-conversion` warnings
 
-  - use bufq for send/receive of network data
-  - usd bufq for send/receive of stream data
-  - use HTTP/2 flow control with no-auto updates to control the
-    amount of data we are buffering for a stream
-    HTTP/2 stream window set to 128K after local tests, defined
-    code constant for now
-  - elminiating PAUSEing nghttp2 processing when receiving data
-    since a stream can now take in all DATA nghttp2 forwards
+  Fix remaining warnings in examples and tests which are not suppressed
+  by the pragma in `lib/curl_setup.h`.
 
-  Improved scorecard and adjuste http2 stream window sizes
-  - scorecard improved output formatting and options default
-  - scorecard now also benchmarks small requests / second
+  Silence a toolchain issue causing warnings in `FD_SET()` calls with
+  older Cygwin/MSYS2 builds. Likely fixed on 2020-08-03 by:
+  https://cygwin.com/git/?p=newlib-cygwin.git;a=commitdiff;h=5717262b8ecfed0f7f
+  ab63e2c09c78991e36f9dd
 
-  Closes #10771
+  Follow-up to 2dbe75bd7f3c36837aa06fd87a442bdf3fb7faef #12492
 
-Dan Fandrich (30 Mar 2023)
+  Closes #12557
 
-- runtests: show error message if file can't be written
+- build: fix some `-Wsign-conversion`/`-Warith-conversion` warnings
 
-- tests: fix remaining servers to run with a dynamic log directory
+  - enable `-Wsign-conversion` warnings, but also setting them to not
+    raise errors.
+  - fix `-Warith-conversion` warnings seen in CI.
+    These are triggered by `-Wsign-converion` and causing errors unless
+    explicitly silenced. It makes more sense to fix them, there just a few
+    of them.
+  - fix some `-Wsign-conversion` warnings.
+  - hide `-Wsign-conversion` warnings with a `#pragma`.
+  - add macro `CURL_WARN_SIGN_CONVERSION` to unhide them on a per-build
+    basis.
+  - update a CI job to unhide them with the above macro:
+    https://github.com/curl/curl/actions/workflows/linux.yml -> OpenSSL -O3
 
-  This final commit in the series is sufficient to allow the tests succeed
-  if $LOGDIR is changed in runtests.pl.
+  Closes #12492
 
-  Ref: #10818
-  Closes #10866
+- cmake: tidy-up `OtherTests.cmake`
 
-- tests: fix fake_ntlm to run with a dynamic log directory
+  - make more obvious which detection uses which prep steps.
+  - merge and streamline conditions.
+  - these should not alter detection results.
 
-  Ref: #10818
+  Also align log output messages from
+  `Macros.cmake` / `curl_internal_test` with rest of the build.
 
-- tests: fix http servers to run with a dynamic log directory
+  Closes #12551
 
-  Ref: #10818
+- appveyor: switch to out-of-tree builds
 
-- tests: fix ftpserver to run with a dynamic log directory
+  With cmake and autotools.
 
-  Ref: #10818
+  Closes #12550
 
-- tests: fix C servers to run with a dynamic log directory
+Daniel Stenberg (19 Dec 2023)
 
-  Ref: #10818
+- DEPRECATE.md: mention that NTLM_WB no longer works
 
-- tests: fix lib tests to run with a dynamic log directory
+  Ref: #12479
+  Closes #12553
 
-  Ref: #10818
+- CURLOPT_SERVER_RESPONSE_TIMEOUT_MS: add
 
-- tests: fix unit tests to run with a dynamic log directory
+  Proposed-by: Yifei Kong
+  Ref: https://curl.se/mail/lib-2023-11/0023.html
+  Closes #12369
 
-  Ref: #10818
+Viktor Szakats (18 Dec 2023)
 
-- tests: use %LOGDIR to refer to the log directory
+- build: more `-Wformat` fixes
 
-  This will allow it be set dynamically.
+  - memdebug: update to not trigger `-Wformat-nonliteral` warnings.
+  - imap: mark `imap_sendf()` with  `CURL_PRINTF()`.
+  - tool_msgs: mark static function with `CURL_PRINTF()`.
 
-  Ref: #10818
+  Follow-up to 3829759bd042c03225ae862062560f568ba1a231 #12489
 
-- runtests: track verification time even if no files to compare
+  Closes #12540
 
-- getpart: better handle case of file not found
+- windows: delete redundant headers
 
-- testcurl: bump version date
+  `winsock2.h` pulls in `windows.h`. `ws2tcpip.h` pulls in `winsock2.h`.
+  `winsock2.h` and `ws2tcpip.h` are also pulled by `curl/curl.h`.
 
-  It hadn't been updated in 9 years; it's time.
+  Keep only those headers that are not already included, or the code under
+  it uses something from that specific header.
 
-- tests: switch to 3-argument open in test suite
+  Closes #12539
 
-  The perl 2-argument open has been considered not-quite-deprecated since
-  the 3-argument form was introduced almost a quarter century ago.
+- cmake: prefill/cache `HAVE_STRUCT_SOCKADDR_STORAGE`
 
-- tests: silence some Perl::Critic warnings in test suite
+  Also add missing include to `OtherTests.cmake`. It didn't cause an issue
+  because the parent already included this earlier by chance.
 
-  Not all warnings are fixed; many are as much stylistic suggestions than
-  anything and IMHO don't do much to actually improve the code.
+  Closes #12537
 
-  Ref: #10818
-  Closes #10861
+Daniel Stenberg (18 Dec 2023)
 
-- docs: bump the minimum perl version to 5.6
+- runner.pm: fix perl warning when running tests
 
-  It's actually been this way since at least 2012 (when a 3-argument open
-  was added to runtests.pl). Given the lack of complaints in the interim,
-  it's safe to call this 23 year old perl version the minimum.
+      Use of uninitialized value $runner::gdbthis in numeric eq (==) at runner.
+  pm
 
-- runtests: memoize the getpart* subroutines to speed up access
+  Follow-up from 3dcf301752a09d9
 
-  The refactored code calls these functions with the same arguments more
-  often, so this prevents redundant test case file parsing.
+  Closes #12549
 
-  Approved-by: Daniel Stenberg
-  Ref: #10818
-  Closes #10833
+- runtests: support -gl. Like -g but for lldb.
 
-- runtests: remove duplicated feature variables
+  Follow-up to 63b5748
 
-  Use the feature map stored in the hash table instead. Most of the
-  variables were only used only once, to set the value in the hash table.
+  Invokes the test case via lldb instead of gdb. Since using gdb is such a
+  pain on mac, using lldb is sometimes less quirky.
 
-  Ref: #10818
+  Closes #12547
 
-- runtests: also ignore test file problems when ignoring results
+- curl.h: add CURLE_TOO_LARGE
 
-  This simplifies error handling in the test verification code and makes
-  it more consistent.
+  A new error code to be used when an internal field grows too large, like
+  when a dynbuf reaches its maximum. Previously it would return
+  CURLE_OUT_OF_MEMORY for this, which is highly misleading.
 
-  Ref: #10818
+  Ref: #12268
+  Closes #12269
 
-- runtests: more refactoring for clarity
+- CI/circleci: disable MQTT in the HTTP-only build
 
-  Ref: #10818
+  And remove the use of configure options that don't actually exist
 
-- runtests: don't start servers if -l is given
+  Closes #12546
 
-- runtests: fix typos
+Yedaya Katsman (18 Dec 2023)
 
-- runtests: refactor singletest() into separate functions
+- tests: respect $TMPDIR when creating unix domain sockets
 
-  This takes it from a 1200 line behemoth into something more manageable.
-  The content and order of the functions is taken almost directly from
-  singletest() so the diff sans whitespace is quite short.
+  When running on termux, where $TMPDIR isn't /tmp, running the tests
+  failed, since the server config tried creating sockets in /tmp, without
+  checking the temp dir config. Use the TMPDIR variable that makes it find
+  the correct directory everywhere [0]
 
-  Ref: #10818
+  [0] https://perldoc.perl.org/File::Temp#tempfile
 
-- runtests: refactor singletest() into distinct sections
+  Closes #12545
 
-  Namely:
-  - Verify that this test case should be run
-  - Start the servers needed to run this test case
-  - Check that test environment is fine to run this test case
-  - Prepare the test environment to run this test case
-  - Run the test command
-  - Clean up after test command
-  - Verify test succeeded
+Viktor Szakats (17 Dec 2023)
 
-  Ref: #10818
+- ssh: fix namespace of two local macros
 
-- runtests: stop copying a few arrays where not needed
+  Avoid using the libssh and libssh2 macro namespaces by prefixing
+  these local macro names with `CURL_`.
 
-  Unlike some other languages that just copy a pointer, perl copies the
-  entire array contents which takes time for a large array.
+  Follow-up to 413a0fedd02c8c6df1d294534b8c6e306fcca7a2 #12346
 
-  Ref: #10818
+  Reviewed-by: Daniel Stenberg
+  Closes #12544
 
-- runtests: reduce redundant calls to getpart/getpartattr
+- cmake: whitespace tidy-up in `OtherTests.cmake`
 
-  These functions scan through the entire test file every time to find the
-  right section, so they can be slow for large test files.
+  Closes #12538
 
-  Ref: #10818
+Mark Sinkovics (16 Dec 2023)
 
-- tests: document that the unittest keyword is special
+- cmake: fix generation for system name iOS
 
-  Also, add other features that were missing.
+  This PR fixes a problem that happens during CMake configuration when
+  the `CMAKE_SYSTEM_NAME` set to `iOS` and not `Darwin`. This value is
+  available (as far as I remember) version 3.14. The final solution
+  (thanks to @vszakats) is to use `APPLE` which contains all the Apple
+  platforms https://cmake.org/cmake/help/latest/variable/APPLE.html.
 
-Stefan Eissing (30 Mar 2023)
+  This issue was found when during vcpkg installation. Running command
+  `vcpkg install curl:arm64-ios` and `vcpkg install curl:x64-ios` failed
+  with message:
+  ```
+  CMake Error: try_run() invoked in cross-compiling mode, please set the follow
+  ing cache variables appropriately:
+     HAVE_H_ERRNO_ASSIGNABLE_EXITCODE (advanced)
+  ```
+  After this fix, I was able to compile the compile the binary without
+  any issue.
 
-- docs: add documentation for bufq
+  In addition to that fix, this PR also contains an simplification to
+  check if the platform is not APPLE.
 
-  Closes #10869
+  Co-authored-by: Viktor Szakats
+  Closes #12515
 
-Daniel Stenberg (30 Mar 2023)
+Daniel Stenberg (16 Dec 2023)
 
 - RELEASE-NOTES: synced
 
-Matt Jolly (30 Mar 2023)
+Baruch Siach (16 Dec 2023)
+
+- gnutls: fix build with --disable-verbose
+
+  infof() parameters must be defined event with --disable-verbose since
+  commit dac293cfb702 ("lib: apache style infof and trace
+  macros/functions").
+
+  Move also 'ptr' definition under !CURL_DISABLE_VERBOSE_STRINGS.
+
+  Fixes the following build failure:
+
+  In file included from ../lib/sendf.h:29,
+                   from vtls/gtls.c:44:
+  vtls/gtls.c: In function 'Curl_gtls_verifyserver':
+  vtls/gtls.c:841:34: error: 'version' undeclared (first use in this function);
+   did you mean 'session'?
+    841 |         gnutls_protocol_get_name(version), ptr);
+        |                                  ^~~~~~~
+
+  Closes #12505
+
+Viktor Szakats (16 Dec 2023)
 
-- hostip: refuse to resolve the .onion TLD
+- build: delete unused `HAVE_{GSSHEIMDAL,GSSMIT,HEIMDAL}`
 
-  RFC 7686 states that:
+  Stop setting `HAVE_GSSHEIMDAL`, `HAVE_GSSMIT` and `HAVE_HEIMDAL`.
+  There was no place in the build system or source code that used them.
 
-  > Applications that do not implement the Tor
-  > protocol SHOULD generate an error upon the use of .onion and
-  > SHOULD NOT perform a DNS lookup.
+  Reviewed-by: Daniel Stenberg
+  Closes #12506
 
-  Let's do that.
+- build: remove redundant `CURL_PULL_*` settings
 
-  https://www.rfc-editor.org/rfc/rfc7686#section-2
+  These macros were not propagated to the source code from CMake.
 
-  Add test 1471 and 1472 to verify
+  autotools set only one of them (`CURL_PULL_SYS_POLL_H`), initially to
+  address an AIX issue [1]. This later broke when introducing `system.h`
+  [2] without the logic it enabled. A subsequent fix [3] re-added the
+  logic, and also enabled it for AIX before its use, directly in
+  `system.h`.
 
-  Fixes #543
-  Closes #10705
+  [1] 2012-11-23: 665adcd4b7bcdb7deb638cdc499fbe71f8d777f2
+  [2] 2017-03-29: 9506d01ee50d5908138ebad0fd9fbd39b66bd64d #1373
+  [3] 2017-08-25: 8a84fcc4b59e8b78d2acc6febf44a43d6bc81b59 #1828 #1833
 
-Philip Heiduck (30 Mar 2023)
+  Reviewed-by: Daniel Stenberg
+  Closes #12502
 
-- GHA: update ngtcp2-*.yml to v0.10.0
+- system.h: sync mingw `CURL_TYPEOF_CURL_SOCKLEN_T` with other compilers
 
-  Closes #10612
+  Align mingw with the other Windows compilers and use the `int` type for
+  `CURL_TYPEOF_CURL_SOCKLEN_T` (and thus for `curl_socklent_t`). This
+  makes it unnecessary to make a mingw-specific trick and pull all Windows
+  headers early just for this type definition. This type is specific to
+  Windows, not to the compiler. mingw-w64's Windows header maps it to
+  `int` too.
 
-Stefan Eissing (30 Mar 2023)
+  With this we also delete all remaining uses of `CURL_PULL_WS2TCPIP_H`.
 
-- tests/http: fix log formatting on wrong exit code
+  [ The official solution is to use `socklen_t` for all Windows compilers.
+  In this case we may want to update `curl/curl.h` to pull in Windows
+  headers before `system.h`. ]
 
-  Closes #10868
+  Reviewed-by: Daniel Stenberg
+  Reviewed-by: Jay Satiro
+  Closes #12501
+
+- windows: simplify detecting and using system headers
+
+  - autotools, cmake: assume that if we detect Windows, `windows.h`,
+    `winsock2.h` and `ws2tcpip.h` do exist.
+  - lib: fix 3 outlier `#if` conditions to use `USE_WINSOCK` instead of
+    looking for `winsock2.h`.
+  - autotools: merge 3 Windows check methods into one.
+  - move Watt-32 and lwIP socket support to `setup-win32.h` from
+    `config-win32.h`. It opens up using these with all build tools. Also
+    merge logic with Windows Sockets.
+  - fix to assume Windows sockets with the mingw32ce toolchain.
+    Follow-up to: 2748c64d605b19fb419ae56810ad8da36487a2d4
+  - cmake: delete unused variable `signature_call_conv` since
+    eb33ccd5332435fa50f1758e5debb869c6942b7f.
+  - autotools: simplify `CURL_CHECK_WIN32_LARGEFILE` detection.
+  - examples/externalsocket: fix header order.
+  - cmake/OtherTests.cmake: delete Windows-specific `_source_epilogue`
+    that wasn't used anymore.
+  - cmake/OtherTests.cmake: set `WIN32_LEAN_AND_MEAN` for test
+    `SIZEOF_STRUCT_SOCKADDR_STORAGE`.
+
+  After this patch curl universally uses `_WIN32` to guard
+  Windows-specific logic. It guards Windows Sockets-specific logic with
+  `USE_WINSOCK` (this might need further work).
 
-Daniel Stenberg (30 Mar 2023)
+  Reviewed-by: Jay Satiro
+  Closes #12495
+
+- build: enable missing OpenSSF-recommended warnings, with fixes
+
+  https://best.openssf.org/Compiler-Hardening-Guides/Compiler-Options-Hardening
+  -Guide-for-C-and-C++.html
+  as of 2023-11-29 [1].
+
+  Enable new recommended warnings (except `-Wsign-conversion`):
+
+  - enable `-Wformat=2` for clang (in both cmake and autotools).
+  - add `CURL_PRINTF()` internal attribute and mark functions accepting
+    printf arguments with it. This is a copy of existing
+    `CURL_TEMP_PRINTF()` but using `__printf__` to make it compatible
+    with redefinting the `printf` symbol:
+    https://gcc.gnu.org/onlinedocs/gcc-3.0.4/gcc_5.html#SEC94
+  - fix `CURL_PRINTF()` and existing `CURL_TEMP_PRINTF()` for
+    mingw-w64 and enable it on this platform.
+  - enable `-Wimplicit-fallthrough`.
+  - enable `-Wtrampolines`.
+  - add `-Wsign-conversion` commented with a FIXME.
+  - cmake: enable `-pedantic-errors` the way we do it with autotools.
+    Follow-up to d5c0351055d5709da8f3e16c91348092fdb481aa #2747
+  - lib/curl_trc.h: use `CURL_FORMAT()`, this also fixes it to enable format
+    checks. Previously it was always disabled due to the internal `printf`
+    macro.
+
+  Fix them:
+
+  - fix bug where an `set_ipv6_v6only()` call was missed in builds with
+    `--disable-verbose` / `CURL_DISABLE_VERBOSE_STRINGS=ON`.
+  - add internal `FALLTHROUGH()` macro.
+  - replace obsolete fall-through comments with `FALLTHROUGH()`.
+  - fix fallthrough markups: Delete redundant ones (showing up as
+    warnings in most cases). Add missing ones. Fix indentation.
+  - silence `-Wformat-nonliteral` warnings with llvm/clang.
+  - fix one `-Wformat-nonliteral` warning.
+  - fix new `-Wformat` and `-Wformat-security` warnings.
+  - fix `CURL_FORMAT_SOCKET_T` value for mingw-w64. Also move its
+    definition to `lib/curl_setup.h` allowing use in `tests/server`.
+  - lib: fix two wrongly passed string arguments in log outputs.
+    Co-authored-by: Jay Satiro
+  - fix new `-Wformat` warnings on mingw-w64.
+
+  [1] https://github.com/ossf/wg-best-practices-os-developers/blob/56c0fde3895b
+  fc55c8a973ef49a2572c507b2ae1/docs/Compiler-Hardening-Guides/Compiler-Options-
+  Hardening-Guide-for-C-and-C%2B%2B.md
+
+  Closes #12489
+
+- Makefile.mk: drop Windows support
+
+  And DLL-support with it. This leaves `Makefile.mk` for MS-DOS and Amiga.
+
+  We recommend CMake instead. With unity mode it's much faster, and about
+  the same without.
+
+  Ref: https://github.com/curl/curl/pull/12221#issuecomment-1783761806
+  Reviewed-by: Daniel Stenberg
+  Closes #12224
 
-- spellcheck.words: unify the AWS-LC spelling
+Daniel Stenberg (16 Dec 2023)
 
-  Follow-up to 34ef4fab22d93
+- cmdline-docs: use .IP consistently
 
-  Closes #10867
+  Remove use of .TP and some .B. The idea is to reduce nroff syntax as
+  much as possible and to use it consistently. Ultimately, we should be
+  able to introduce our own easier-to-use-and-read syntax/formatting and
+  convert on generation time.
 
-Jim King (30 Mar 2023)
+  Closes #12535
 
-- openssl: interop with AWS-LC
+Tatsuhiko Miyagawa (16 Dec 2023)
 
-  * Configure changes to detect AWS-LC
-  * CMakeLists.txt changes to detect AWS-LC
-  * Compile-time branches needed to support AWS-LC
-  * Correctly set OSSL_VERSION and report AWS-LC release number
-  * GitHub Actions script to build with autoconf and cmake against AWS-LC
+- http: fix off-by-one error in request method length check
 
-  AWS-LC is a BoringSSL/OpenSSL derivative
-  For more information see https://github.com/awslabs/aws-lc/
+  It should allow one more byte.
 
-  Closes #10320
+  Closes #12534
 
-Viktor Szakats (30 Mar 2023)
+Daniel Stenberg (15 Dec 2023)
 
-- cmake: picky-linker fixes for openssl, ZLIB, H3 and more
+- curl: show ipfs and ipns as supported "protocols"
 
-  - fix HTTP/3 support detection with OpenSSL/quictls built with ZLIB.
-    (Requires curl be built with ZLIB option also.)
+  They are accepted schemes in URLs passed to curl (the tool, not the
+  library).
 
-  - fix HTTP/3 support detection with OpenSSL/quictls/LibreSSL and `ld`
-    linker on Windows.
+  Also makes curl-config show the same list.
 
-  - fix HTTP/3 support detection with wolfSSL to automatically add
-    `ws2_32` to the lib list on Windows. For all linkers.
+  Co-Authored-by: Jay Satiro
+  Reported-by: Chara White
+  Bug: https://curl.se/mail/archive-2023-12/0026.html
+  Closes #12508
 
-  - reposition ZLIB (and other compression) detection _after_ TLS
-    detection, but before calling HTTP/3-support detection via
-    `CheckQuicSupportInOpenSSL`.
+- Revert "urldata: move async resolver state from easy handle to connectdata"
 
-    May be a regression from ebef55a61df0094b9790710a42f63c48e7de3c13
-    May fix #10832 (Reported-by: Micah Snyder)
+  This reverts commit 56a4db2e4e2bcb9a0dcb75b83560a78ef231fcc8 (#12198)
 
-    This also seems to fix an odd case, where OpenSSL/quictls is correctly
-    detected, but its header path is not set while compiling, breaking
-    build at `src/curl_ntlm_core.c`. Reason for this remains undiscovered.
+  We want the c-ares channel to be held in the easy handle, not per
+  connection - for performance.
 
-  - satisfy "picky" linkers such as `ld` with MinGW, that are highly
-    sensitive to lib order, by also adding brotli to the beginning of the
-    lib list.
+  Closes #12524
 
-  - satisfy "picky" linkers by adding certain Windows systems libs to
-    the lib list for OpenSSL/LibreSSL. (Might need additional ones for
-    other forks, such as `pthread` for BoringSSL.)
+Viktor Szakats (15 Dec 2023)
 
-  Note: It'd make sense to _always_ add `ws2_32`, `crypt32` (except
-  Windows App targets perhaps?), `bcrypt` (except old-mingw!) on Windows
-  at this point. They are almost always required, and if some aren't,
-  they are ignored by the linker with no effect on final binaries.
+- openssl: re-match LibreSSL deinit with init
 
-  Closes #10857
+  Earlier we switched to use modern initialization with LibreSSL v2.7.0
+  and up, but did not touch deinitialization [1]. Fix it in this patch.
 
-Stefan Eissing (30 Mar 2023)
+  Regression from bec0c5bbf34369920598678161d2df8bea0e243b #11611
 
-- vlts: use full buffer size when receiving data if possible
+  [1] https://github.com/curl/curl/pull/11611#issuecomment-1668654014
 
-  SSL backends like OpenSSL/wolfSSL and other return the content of one
-  TLS record on read, but usually there are more available.
+  Reported-by: Mike Hommey
+  Reviewed-by: Daniel Stenberg
+  Fixes #12525
+  Closes #12526
 
-  Change the vtls cfilter recv() function to fill the given buffer until a
-  read would block.
+Daniel Stenberg (14 Dec 2023)
 
-  Closes #10736
+- libssh: supress warnings without version check
 
-dengjfzh on github (30 Mar 2023)
+  Define unconditionally.
 
-- rtsp: skip malformed RTSP interleaved frame data
+  Follow-up from d21bd2190c46ad7fa
 
-  Some IP cameras send malformed RTSP interleaved frames sometimes, which
-  can cause curl_easy_perform return 1 (CURLE_UNSUPPORTED_PROTOCOL).  This
-  change attempts to skip clearly incorrect RTSP interleaving frame data.
+  Closes #12523
 
-  Closes #10808
+- hostip: return error immediately when Curl_ip2addr() fails
 
-Stefan Eissing (30 Mar 2023)
+  Closes #12522
 
-- lib: add `bufq` and `dynhds`
+Theo (14 Dec 2023)
 
-  Adding `bufq`:
-  - at init() time configured to hold up to `n` chunks of `m` bytes each.
-  - various methods for reading from and writing to it.
-  - `peek` support to get access to buffered data without copy
-  - `pass` support to allow buffer flushing on write if it becomes full
-  - use case: IO buffers for dynamic reads and writes that do not blow up
-  - distinct from `dynbuf` in that:
-    - it maintains a read position
-    - writes on a full bufq return CURLE_AGAIN instead of nuking itself
-  - Init options:
-    - SOFT_LIMIT: allow writes into a full bufq
-    - NO_SPARES: free empty chunks right away
-  - a `bufc_pool` that can keep a number of spare chunks to
-    be shared between different `bufq` instances
+- libssh: improve the deprecation warning dismissal
 
-  Adding `dynhds`:
-  - a straightforward list of name+value pairs as used for HTTP headers
-  - headers can be appended dynamically
-  - headers can be removed again
-  - headers can be replaced
-  - headers can be looked up
-  - http/1.1 formatting into a `dynbuf`
-  - configured at init() with limits on header counts and total string
-    sizes
-  - use case: pass a HTTP request or response around without being version
-    specific
-  - express a HTTP request without a curl easy handle (used in h2 proxy
-    tunnels)
-  - future extension possibilities:
-    - conversions of `dynhds` to nghttp2/nghttp3 name+value arrays
+  Previous code was compiler dependant, and dismissed all deprecation warnings
+  indiscriminately.
 
-  Closes #10720
+  libssh provides a way to disable the deprecation warnings for libssh only, an
+  d
+  naturally this is the preferred way.
 
-- pytest: improvements for suitable curl and error output
+  This commit uses that, to prevent the erroneous hiding of potential, unrelate
+  d
+  deprecation warnings.
 
-  - will check built curl for http and https support and
-    skip all tests if not there
-  - will dump stdout/stderr/trace output on errored responses
+  Fixes #12519
+  Closes #12520
 
-  Closes #10829
+Daniel Stenberg (14 Dec 2023)
 
-Daniel Stenberg (29 Mar 2023)
+- test1474: removed
 
-- lib: use correct printf flags for sockets and timediffs
+  The test was already somewhat flaky and disabled on several platforms,
+  and after 1da640abb688 even more unstable.
 
-  Introduces CURL_FORMAT_SOCKET_T for outputting socket numbers.
+- readwrite_data: loop less
 
-  Fixes #10737
-  Reported-by: Gisle Vanem
-  Closes #10855
+  This function is made to loop in order to drain incoming data
+  faster. Completely removing the loop has a measerably negative impact on
+  transfer speeds.
 
-- telnet: make MSVC ignore warning for assignment within conditional
+  Downsides with the looping include
 
-  Follow-up to d92a5007b60e0af7d
+  - it might call the progress callback much more seldom. Especially if
+    the write callback is slow.
 
-  Closes #10859
+  - rate limiting becomes less exact
 
-- ws: handle reads before EAGAIN better
+  - a single transfer might "starve out" other parallel transfers
 
-  Reported-by: simplerobot on github
-  Fixes #10831
-  Closes #10856
+  - QUIC timers for other connections can't be maintained correctly
 
-- test1592: add flaky keyword
+  The long term fix should be to remove the loop and optimize coming back
+  to avoid the transfer speed penalty.
 
-  Closes #10860
+  This fix lower the max loop count to reduce the starvation problem, and
+  avoids the loop completely for when rate-limiting is in progress.
 
-Frank Gevaerts (28 Mar 2023)
+  Ref: #12488
+  Ref: https://curl.se/mail/lib-2023-12/0012.html
+  Closes #12504
 
-- lib/sha256.c: typo fix in comment (duplicated "is available")
+Stefan Eissing (14 Dec 2023)
 
-  Closes #10851
+- lib: eliminate `conn->cselect_bits`
 
-Arne Soete (28 Mar 2023)
+  - use `data->state.dselect_bits` everywhere instead
+  - remove `bool *comeback` parameter as non-zero
+    `data->state.dselect_bits` will indicate that IO is
+    incomplete.
 
-- tests: update tests/httpd references to tests/http
+  Closes #12512
 
-  tests/httpd was renamed to tests/http in #10654. This patch updates some
-  references in the README
+- connect: refactor `Curl_timeleft()`
 
-  Closes #10854
+  - less local vars, "better" readability
+  - added documentation
 
-Kamil Dudka (28 Mar 2023)
+  Closes #12518
 
-- telnet: simplify the implementation of str_is_nonascii()
+Dmitry Karpov (14 Dec 2023)
 
-  There is no need to traverse the string twice.
+- cookie: avoid fopen with empty file name
 
-  Closes #10852
+  Closes #12514
 
-Frank Gevaerts (28 Mar 2023)
+Viktor Szakats (13 Dec 2023)
 
-- curl_easy_getinfo.3: typo fix (duplicated "from the")
+- tests/server: delete workaround for old-mingw
 
-  Closes #10850
+  mingw-w64 1.0 comes with w32api v3.12, thus doesn't need this.
 
-Philip Heiduck (28 Mar 2023)
+  Follow-up to 38029101e2d78ba125732b3bab6ec267b80a0e72 #11625
 
-- wolfssl.yml: bump to version 5.6.0
+  Reviewed-by: Jay Satiro
+  Closes #12510
 
-  Closes #10843
+- cmake: delete obsolete TODOs more [ci skip]
 
-Daniel Stenberg (28 Mar 2023)
+  - manual completed: 898b012a9bf388590c4be7f526815b5ab74feca1 #1288
+  - soname completed: 5de6848f104d7cb0017080e31216265ac19d0dde #10023
+  - bunch of others that are completed
+  - `NTLM_WB_ENABLED` is implemented in a basic form, and now also
+    scheduled for removal, so a TODO at this point isn't useful.
 
-- RELEASE-NOTES: synced
+  And this 'to-check' item:
 
-Ronan Pigott (28 Mar 2023)
+  Q: "The cmake build selected to run gcc with -fPIC on my box while the
+     plain configure script did not."
 
-- docs/cmdline-opts: document the dotless config path
+  A: With CMake, since 2ebc74c36a19a1700af394c16855ce144d9878e3 #11546
+     and fc9bfb14520712672b4784e8b48256fb29204011 #11627, we explicitly
+     enable PIC for libcurl shared lib. Or when building libcurl for
+     shared and static lib in a single pass. We do this by default for
+     Windows or when enabled by the user via `SHARE_LIB_OBJECT`.
+     Otherwise we don't touch this setting. Meaning the default set by
+     CMake (if any) or the toolchain is used. On Debian Bookworm, this
+     means that PIC is disabled for static libs by default. Some platforms
+     (like macOS), has PIC enabled by default.
+     autotools supports the double-pass mode only, and in that case
+     CMake seems to match PIC behaviour now (as tested on Linux with gcc.)
 
-  The real xdg config path is $XDG_CONFIG_HOME/curlrc, without the dot.
-  The dotless name seems preferable, so let's match the documentation to
-  the behavior.
+  Follow-up to 5d5dfdbd1a6c40bd75e982b66f49e1fa3a7eeae7 #12500
 
-  Closes #10849
+  Reviewed-by: Jay Satiro
+  Closes #12509
 
-Daniel Stenberg (28 Mar 2023)
+Stefan Eissing (12 Dec 2023)
 
-- HTTP-COOKIES.md: mention the #HttpOnly_ prefix
+- CLIENT-WRITERS: design and use documentation
 
-  Fixes #10847
-  Reported-by: Harry Sintonen
-  Closes #10848
+  Closes #12507
 
-- dynbuf: never allocate larger than "toobig"
+Viktor Szakats (12 Dec 2023)
 
-  As dynbufs always have a fixed maximum size which they are not allowed
-  to grow larger than, making sure that it never allocates a larger buffer
-  makes sure the buffer does not allocate memory that will never be used.
+- cmake: delete obsolete TODO items [ci skip]
 
-  Closes #10845
+  There is always room for improvement, but CMake is up to par now with
+  autotools, so there is no longer a good reason to keep around these
+  inline TODO items.
 
-- ftplistparser: replace realloc with dynbuf
+  Answering one of questions:
 
-  Closes #10844
+  Q: "The gcc command line use neither -g nor any -O options. As a
+     developer, I also treasure our configure scripts's --enable-debug
+     option that sets a long range of "picky" compiler options."
 
-- ftplistparser: use ISDIGIT()
+  A: CMake offers the `CMAKE_BUILD_TYPE` variable to control debug info
+     and optimization level. E.g.:
+     - `Release`    = `-O3` + no debug info
+     - `MinSizeRel` = `-Os` + no debug info
+     - `Debug`      = `-O0` + debug info
 
-  Closes #10844
+     https://stackoverflow.com/questions/48754619/what-are-cmake-build-type-deb
+  ug-release-relwithdebinfo-and-minsizerel/59314670#59314670
+     https://cmake.org/cmake/help/latest/manual/cmake-buildsystem.7.html#defaul
+  t-and-custom-configurations
 
-- ftplistparser: move out private data from public struct
+     For picky warnings we have the `PICKY_COMPILER` options, enabled by
+     default.
 
-  The public 'curl_fileinfo' struct contained three fields that are for
-  internal purposes only. This change makes them unused in the public
-  struct.
+  Closes #12500
 
-  The new private struct fields are also renamed to make this separation
-  more obvious internally.
+Stefan Eissing (11 Dec 2023)
 
-  Closes #10844
+- CONNECTION-FILTERS: update documentation
 
-- openssl: fix indents - white space edits only
+  Closes #12497
 
-  Closes #10840
+Daniel Stenberg (11 Dec 2023)
 
-- url: remove call to Curl_llist_destroy in Curl_close
+- lib: reduce use of strncpy
 
-  A list that is created with a NULL "destructor" does not need to be
-  destroyed. Not calling it is faster than calling it.
+  - bearssl: select cipher without buffer copies
+  - http_aws_sigv4: avoid strncpy, require exact timestamp length
+  - http_aws_sigv4: use memcpy isntead of strncpy
+  - openssl: avoid strncpy calls
+  - schannel: check for 1.3 algos without buffer copies
+  - strerror: avoid strncpy calls
+  - telnet: avoid strncpy, return error on too long inputs
+  - vtls: avoid strncpy in multissl_version()
 
-  Closes #10846
+  Closes #12499
 
-- multi: remove PENDING + MSGSENT handles from the main linked list
+- CI/distcheck: run full tests
 
-  As they are not driving transfers or any socket activity, the main loop
-  does not need to iterate over these handles. A performance improvement.
+  To be able to detect missing files better, this now runs the full CI
+  test suite. If done before, it would have detected #12462 before
+  release.
 
-  They are instead only held in their own separate lists.
+  Closes #12503
 
-  'data->multi' is kept a pointer to the multi handle as long as the easy
-  handle is actually part of it even when the handle is moved to the
-  pending/msgsent lists. It needs to know which multi handle it belongs
-  to, if for example curl_easy_cleanup() is called before the handle is
-  removed from the multi handle.
+- docs: clean up Protocols: for cmdline options
 
-  Alll 'data->multi' pointers of handles still part of the multi handle
-  gets cleared by curl_multi_cleanup() which "orphans" all previously
-  attached easy handles.
+  ... and some other minor polish.
 
-  This is take 2. The first version was reverted for the 8.0.1 release.
+  Closes #12496
 
-  Assisted-by: Stefan Eissing
-  Closes #10801
+- cmdline/gen: fix the sorting of the man page options
 
-Stefan Eissing (26 Mar 2023)
+  They were previously sorted based on the file names, which use a .d
+  extension, making "data" get placed after "data-binary" etc. Making the
+  sort ignore the extention fixes the ordering.
 
-- tests/http: add timeout to running curl in test cases
+  Reported-by: Boris Verkhovskiy
+  Bug: https://curl.se/mail/archive-2023-12/0014.html
+  Closes #12494
 
-  - we had a CI case once where `curl` seemingly did not
-    return and it was hard to guess what happened.
-  - make curl execution in test cases time out after 60 seconds
+Daniel Gustafsson (9 Dec 2023)
 
-  Closes #10783
+- doh: remove unused local variable
 
-Daniel Stenberg (26 Mar 2023)
+  The nurl variable is no longer used during probing following
+  a refactoring, so remove.
 
-- RELEASE-PROCEDURE: update to new schedule
+  Closes #12491
 
-  Ref: https://curl.se/mail/lib-2023-03/0062.html
+Jay Satiro (8 Dec 2023)
 
-  Assisted-by: Andy Alt
-  Assisted-by: Dan Frandrich
+- build: fix Windows ADDRESS_FAMILY detection
 
-  Closes #10827
+  - Include winsock2.h for Windows ADDRESS_FAMILY detection.
 
-Patrick Monnerat (26 Mar 2023)
+  Prior to this change cmake detection didn't work because it included
+  ws2def.h by itself, which is missing needed types from winsock2.h.
 
-- doc: curl_mime_init() strong easy handle binding has been relaxed in 7.87.0
+  Prior to this change autotools detection didn't work because it did not
+  include any Windows header.
 
-  Reported-by: Chloe Kudryavtsev
-  Fixes #10834
-  Closes #10835
+  In both cases libcurl would fall back on unsigned short as the address
+  family type, which is the same as ADDRESS_FAMILY.
 
-Jay Satiro (25 Mar 2023)
+  Co-authored-by: Viktor Szakats
 
-- CURLOPT_WRITEFUNCTION.3: fix typo
+  Closes https://github.com/curl/curl/pull/12441
 
-  Reported-by: Osaila@users.noreply.github.com
+Daniel Stenberg (8 Dec 2023)
 
-  Fixes https://github.com/curl/curl/issues/10839
+- lib: rename Curl_strndup to Curl_memdup0 to avoid misunderstanding
 
-Dan Fandrich (24 Mar 2023)
+  Since the copy does not stop at a null byte, let's not call it anything
+  that makes you think it works like the common strndup() function.
 
-- CI: skip some more builds when possible
+  Based on feedback from Jay Satiro, Stefan Eissing and Patrick Monnerat
 
-  When a commit only contains tests, documentation, or cmake files, skip
-  those builds that aren't affected by those.
+  Closes #12490
 
-  The file filters available on the CI services don't seem to allow
-  skipping individual jobs, only the entire workflow, so we can't get any
-  more fine-grained than this.
+- convsrctest.pl: removed: not used, not shipped in tarballs
 
-- CI: add and adjust labeler match patterns
+- tests: rename tests scripts to the test number
 
-  Allow cmdline tool alongside other labels.
+  It is hard to name the scripts sensibly. Lots of them are similarly
+  named and the name did not tell which test that used them.
 
-Kai Pastor (25 Mar 2023)
+  The new approach is rather to name them based on the test number that
+  runs them. Also helps us see which scripts are for individual tests
+  rather than for general test infra.
 
-- CMake: make config version 8 compatible with 7
+   - badsymbols.pl -> test1167.pl
+   - check-deprecated.pl -> test1222.pl
+   - check-translatable-options.pl -> test1544.pl
+   - disable-scan.pl -> test1165.pl
+   - error-codes.pl -> test1175.pl
+   - errorcodes.pl -> test1477.pl
+   - extern-scan.pl -> test1135.pl
+   - manpage-scan.pl -> test1139.pl
+   - manpage-syntax.pl -> test1173.pl
+   - markdown-uppercase.pl -> test1275.pl
+   - mem-include-scan.pl -> test1132.pl
+   - nroff-scan.pl -> test1140.pl
+   - option-check.pl -> test1276.pl
+   - options-scan.pl -> test971.pl
+   - symbol-scan.pl -> test1119.pl
+   - version-scan.pl -> test1177.pl
 
-  Reviewed-by: Jakub Zakrzewski
-  Closes #10819
+  Closes #12487
 
-Daniel Stenberg (24 Mar 2023)
+Michał Antoniak (8 Dec 2023)
 
-- RELEASE-NOTES: synced
+- sendf: fix compiler warning with CURL_DISABLE_HEADERS_API
 
-  Bumped version-in-progress to 8.1.0
+  fix MSVC warning C4189: 'htype': local variable is initialized but not
+  referenced - when CURL_DISABLE_HEADERS_API is defined.
 
-- GHA: add a memory-sanitizer job
+  Closes #12485
 
-  Closes #10815
+Viktor Szakats (8 Dec 2023)
 
-Dan Fandrich (23 Mar 2023)
+- tidy-up: whitespace
 
-- CI: fix brew retries on GHA
+  Closes #12484
 
-  The fix in the previous commit was complete for Cirrus but accidentally
-  left off a part for GHA.
+Stefan Eissing (7 Dec 2023)
 
-  Follow-up to c2b7249d
+- test_02_download: fix paramters to test_02_27
 
-- CI: skip Azure for more commits which change only GHA
+  - it is a special client that only ever uses http/2
 
-Daniel Stenberg (23 Mar 2023)
+  Closes #12467
 
-- cmake: set SONAME for SunOS too
+Michał Antoniak (7 Dec 2023)
 
-  Provided-by: Brian Lund
+- vtls: remove the Curl_cft_ssl_proxy object if CURL_DISABLE_PROXY
 
-  Closes #10816
+  Closes #12459
 
-Stefan Eissing (23 Mar 2023)
+Daniel Stenberg (7 Dec 2023)
 
-- ngtcp2: adjust config and code checks for ngtcp2 without nghttp3
+- lib: strndup/memdup instead of malloc, memcpy and null-terminate
 
-  - make configure show on HTTP3 feature that both ngtcp2 and nghttp3
-    are in play
-  - define ENABLE_QUIC only when USE_NGTCP2 and USE_NGHTTP3 are defined
-  - add USE_NGHTTP3 in the ngtcp2 implementation
+   - bufref: use strndup
+   - cookie: use strndup
+   - formdata: use strndup
+   - ftp: use strndup
+   - gtls: use aprintf instead of malloc + strcpy * 2
+   - http: use strndup
+   - mbedtls: use strndup
+   - md4: use memdup
+   - ntlm: use memdup
+   - ntlm_sspi: use strndup
+   - pingpong: use memdup
+   - rtsp: use strndup instead of malloc, memcpy and null-terminate
+   - sectransp: use strndup
+   - socks_gssapi.c: use memdup
+   - vtls: use dynbuf instead of malloc, snprintf and memcpy
+   - vtls: use strdup instead of malloc + memcpy
+   - wolfssh: use strndup
 
-  Fixes #10793
-  Closes #10821
+  Closes #12453
 
-Daniel Stenberg (23 Mar 2023)
+- strdup: remove the memchr check from Curl_strndup
 
-- data.d: emphasize no conversion
+  It makes it possible to clone a binary chunk of data.
 
-  When asking curl to send a POST, curl does not encode or change the data.
+  Closes #12453
 
-  Ref: #10820
-  Closes #10823
+- ftp: handle the PORT parsing without allocation
 
-- server/getpart: clear the buffer before load
+  Also reduces amount of *cpy() calls.
 
-  Fixes msan warnings:
+  Closes #12456
 
-  ==54195==WARNING: MemorySanitizer: use-of-uninitialized-value
-      #0 0x55ece35e57cb in line_length /home/runner/work/curl/curl/tests/server
-  /getpart.c:111:25
-      #1 0x55ece35e3b83 in readline /home/runner/work/curl/curl/tests/server/ge
-  tpart.c:164:24
-      #2 0x55ece35e0269 in getpart /home/runner/work/curl/curl/tests/server/get
-  part.c:347:18
-      #3 0x55ece36180b6 in parse_servercmd /home/runner/work/curl/curl/tests/se
-  rver/sws.c:283:13
+- RELEASE-NOTES: synced
+
+  Bumped to 8.5.1
 
-  Closes #10822
+- url: for disabled protocols, mention if found in redirect
 
-- ntlm: clear lm and nt response buffers before use
+  To help users better understand where the URL (and denied scheme) comes
+  from. Also removed "in libcurl" from the message, since the disabling
+  can be done by the application.
 
-  To avoid the risk of MemorySanitizer: use-of-uninitialized-value
+  The error message now says "not supported" or "disabled" depending on
+  why it was denied:
 
-  Closes #10814
+   Protocol "hej" not supported
+   Protocol "http" disabled
 
-- digest: clear target buffer
+  And in redirects:
 
-  Closes #10814
+   Protocol "hej" not supported (in redirect)
+   Protocol "http" disabled (in redirect)
 
-Douglas R. Reno (22 Mar 2023)
+  Reported-by: Mauricio Scheffer
+  Fixes #12465
+  Closes #12469
 
-- cmake: bring in the network library on Haiku.
+Stefan Eissing (6 Dec 2023)
 
-  When cross-compiling for Haiku, the networking library needs to be
-  brought in. Without this, an unknown type of "Error" is reported in
-  lib/curl_setup_once.h.
+- sectransp_ make TLSCipherNameForNumber() available in non-verbose config
 
-  This is also needed when using CMake natively on Haiku to build libcurl.
+  Reported-by: Cajus Pollmeier
+  Closes #12476
+  Fixes #12474
 
-  Fixes #10296
-  Closes #10792
+YX Hao (6 Dec 2023)
 
-Daniel Stenberg (22 Mar 2023)
+- lib: fix variable undeclared error caused by `infof` changes
 
-- runtests: die if curl version can be found
+  `--disable-verbose` yields `CURL_DISABLE_VERBOSE_STRINGS` defined.
+  `infof` isn't `Curl_nop_stmt` anymore: dac293c.
 
-  Closes #10813
+  Follow-up to dac293c
 
-Stefan Eissing (22 Mar 2023)
+  Closes #12470
 
-- multi: add handle asserts in DEBUG builds
+Viktor Szakats (6 Dec 2023)
 
-  For GOOD_EASY_HANDLE and GOOD_MULTI_HANDLE checks
+- tidy-up: fix yamllint whitespace issues in labeler.yml
 
-  - allow NULL pointers to "just" return an error as before
-  - fail hard on nun-NULL pointers that no longer show the MAGICs
+  Follow-up to bda212911457c6fadfbba50be61afc4ca513fa56 #12466
 
-  Closes #10812
+  Reviewed-by: Dan Fandrich
+  Closes #12475
 
-Jon Rumsey (22 Mar 2023)
+- tidy-up: fix yamllint whitespace issues
 
-- gskit: various compile errors in OS400
+  Closes #12466
 
-  Various compile failures in gskit.c;
+Chris Sauer (6 Dec 2023)
 
-  - pipe_ssloverssl() needs Curl_easy data parameter for
-    Curl_conn_cf_get_socket(cf, data)
-  - key_passwd is in ssl_config, not conn_config
-  - close_on() has 2 parameters, not 4
-  - getsockopt() needs to call Curl_conn_cf_get_socket(), not
-    cxn->sock[FIRSTSOCKET]
+- cmake: fix typo
 
-  Fixes #10799
-  Closes #10800
+  Follow-up to aace27b
+  Closes #12464
 
-Daniel Stenberg (22 Mar 2023)
+Daniel Stenberg (6 Dec 2023)
 
-- tool_operate: pass a long as CURLOPT_HEADEROPT argument
+- dist: add tests/errorcodes.pl to the tarball
 
-  Closes #10798
+  Used by test 1477
 
-- GHA: run all linux test jobs with valgrind
+  Reported-by: Xi Ruoyao
+  Follow-up to 0ca3a4ec9a7
+  Fixes #12462
+  Closes #12463
 
-  Closes #10798
+Dan Fandrich (6 Dec 2023)
 
-- GHA-linux: add an address-sanitizer build
+- github/labeler: update a missed key in the v5 upgrade
 
-  Closes #10810
+  Follow-up to ce03fe3ba
 
-Version 8.0.1 (20 Mar 2023)
+Version 8.5.0 (6 Dec 2023)
 
-Daniel Stenberg (20 Mar 2023)
+Daniel Stenberg (6 Dec 2023)
 
 - RELEASE-NOTES: synced
 
-  curl 8.0.1
+  The curl 8.5.0 release.
+
+Dan Fandrich (5 Dec 2023)
+
+- github/labeler: switch from the beta to labeler v5
+
+  Some keys were renamed and the dot option was made default.
+
+  Closes #12458
+
+Daniel Stenberg (5 Dec 2023)
+
+- DEPRECATE: remove NTLM_WB in June 2024
+
+  Ref: https://curl.se/mail/lib-2023-12/0010.html
+
+  Closes #12451
+
+Jacob Hoffman-Andrews (4 Dec 2023)
+
+- rustls: implement connect_blocking
+
+  Closes #11647
+
+Daniel Stenberg (4 Dec 2023)
 
-- Revert "multi: remove PENDING + MSGSENT handles from the main linked list"
+- examples/rtsp-options.c: add
 
-  This reverts commit f6d6f3ce01e377932f1ce7c24ee34d45a36950b8.
+  Just a bare bones RTSP example using CURLOPT_RTSP_SESSION_ID and
+  CURLOPT_RTSP_REQUEST set to CURL_RTSPREQ_OPTIONS.
 
-  The commits caused issues in the 8.0.0 release. Needs a retake.
+  Closes #12452
 
-  Reported-by: Kamil Dudka
-  Closes #10795
+Stefan Eissing (4 Dec 2023)
 
-- include/curl/curlver.h: bump to 8.0.1
+- ngtcp2: ignore errors on unknown streams
 
-Version 8.0.0 (20 Mar 2023)
+  - expecially in is_alive checks on connections, we might
+    see incoming packets on streams already forgotten and closed,
+    leading to errors reported by nghttp3. Ignore those.
 
-Daniel Stenberg (20 Mar 2023)
+  Closes #12449
+
+Daniel Stenberg (4 Dec 2023)
+
+- docs: make all examples in all libcurl man pages compile
+
+  Closes #12448
+
+- checksrc.pl: support #line instructions
+
+  makes it identify the correct source file and line
+
+- GHA/man-examples: verify libcurl man page examples
+
+- verify-examples.pl: verify that all man page examples compile clean
 
 - RELEASE-NOTES: synced
 
-  The curl 8.0.0 release
+Graham Campbell (2 Dec 2023)
 
-- THANKS: from the 8.0.0 release
+- http3: bump ngtcp2 and nghttp3 versions
 
-- scripts/delta: fix "ambiguous argument" when used in branches
+  nghttp3 v1.1.0
+  ngtcp2 v1.1.0
 
-- SECURITY-PROCESS.md: Busy-loops are not security problems
+  In docs and CI
 
-  Closes #10790
+  Closes #12446
 
-Stefan Eissing (17 Mar 2023)
+- CI/quiche: use `3.1.4+quic` consistently in CI workflows
 
-- tests/http: do not save files for downloads in scorecard testing
+  Closes #12447
 
-  Closes #10788
+Viktor Szakats (2 Dec 2023)
 
-Daniel Stenberg (17 Mar 2023)
+- test1545: disable deprecation warnings
 
-- cf-socket: use port 80 when resolving name for local bind
+  Fixes:
+  https://ci.appveyor.com/project/curlorg/curl/builds/48631551/job/bhx74e0i66yr
+  p6pk#L1205
 
-  It turns out c-ares returns an error when asked to resolve a host name with
-  ares_getaddrinfo using port number 0.
+  Same with details:
+  https://ci.appveyor.com/project/curlorg/curl/builds/48662893/job/ol8a78q9gmil
+  b6wt#L1263
+  ```
+  tests/libtest/lib1545.c:38:3: error: 'curl_formadd' is deprecated: since 7.56
+  .0. Use curl_mime_init() [-Werror=deprecated-declarations]
+     38 |   curl_formadd(&m_formpost, &lastptr, CURLFORM_COPYNAME, "file",
+        |   ^~~~~~~~~~~~
+  [...]
+  ```
 
-  Reported as a c-ares bug here: https://github.com/c-ares/c-ares/issues/517
+  Follow-up to 07a3cd83e0456ca17dfd8c3104af7cf45b7a1ff5 #12421
 
-  The work-around is to simply use port 80 instead, as the number typically doe
-  s
-  not make a difference and a non-zero number works for c-ares.
+  Fixes #12445
+  Closes #12444
 
-  Fixes #10759
-  Reported-by: Matt Jolly
-  Closes #10789
+Daniel Stenberg (2 Dec 2023)
 
-- curl.h: require gcc 12.1 for the deprecation magic
+- INSTALL: update list of ports and CPU archs
 
-  Reported-by: kchow-FTNT on github
-  Fixes #10726
-  Closes #10784
+- symbols-in-versions: the CLOSEPOLICY options are deprecated
 
-- Revert "rtsp: use dynbuf instead of custom reallocs"
+  The were used with the CURLOPT_CLOSEPOLICY option, which *never* worked.
 
-  This reverts commit 1b9ea3239d22147e00d8 because of OSS-fuzz reports.
-  I'll do another take after the pending release.
+z2_ (1 Dec 2023)
 
-  Closes #10785
+- build: fix builds that disable protocols but not digest auth
 
-- test422: verify --next used without a prior URL
+  - Build base64 functions if digest auth is not disabled.
 
-  Closes #10782
+  Prior to this change if some protocols were disabled but not digest auth
+  then a build error would occur due to missing base64 functions.
 
-- tool_getparam: error if --next is used without a prior URL
+  Fixes https://github.com/curl/curl/issues/12440
+  Closes https://github.com/curl/curl/pull/12442
 
-  Reported-by: 積丹尼 Dan Jacobson
-  Ref: https://github.com/curl/curl/pull/10769#discussion_r1137895629
+Michał Antoniak (1 Dec 2023)
 
-  Closes #10782
+- connect: reduce number of transportation providers
 
-- libssh: use dynbuf instead of realloc
+  Use only the ones necessary - the ones that are built-in. Saves a few
+  bytes in the resulting code.
 
-  When building lines to show for SFTP directory listings.
+  Closes #12438
 
-  Closes #10778
+David Benjamin (1 Dec 2023)
 
-- lib2305: deal with CURLE_AGAIN
+- vtls: consistently use typedef names for OpenSSL structs
 
-  The test does a slightly ugly busy-loop for this case but should be
-  managable due to it likely being a very short moment.
+  The foo_st names don't appear in OpenSSL public API documentation. The
+  FOO typedefs are more common. This header was already referencing
+  SSL_CTX via . There is a comment about avoiding
+  , but OpenSSL actually declares all the typedefs in
+  , which is already included by  (and
+  every other OpenSSL header), so just use that. Though I've included it
+  just to be explicit.
 
-  Mention CURLE_AGAIN in curl_ws_recv.3
+  (I'm also fairly sure including  already triggers the
+  Schannel conflicts anyway. The comment was probably just out of date.)
 
-  Fixes #10760
-  Reported-by: Jay Satiro
-  Closes #10781
+  Closes #12439
+
+Lau (1 Dec 2023)
 
-- rtsp: use dynbuf instead of custom reallocs
+- libcurl-security.3: fix typo
 
-  For the RTP buffering.
+  Fixed minimal typo.
 
-  Closes #10776
+  Closes #12437
 
-- libssh2: remove unused variable from libssh2's struct
+Stefan Eissing (1 Dec 2023)
 
-  Closes #10777
+- ngtcp2: fix races in stream handling
+
+  - fix cases where ngtcp2 invokes callbacks on streams that
+    nghttp3 has already forgotten. Ignore the NGHTTP3_ERR_STREAM_NOT_FOUND
+    in these cases as it is normal behaviour.
+
+  Closes #12435
+
+Emanuele Torre (1 Dec 2023)
+
+- tool_writeout_json: fix JSON encoding of non-ascii bytes
+
+  char variables if unspecified can be either signed or unsigned depending
+  on the platform according to the C standard; in most platforms, they are
+  signed.
+
+  This meant that the  *i<32  waas always true for bytes with the top bit
+  set. So they were always getting encoded as \uXXXX, and then since they
+  were also signed negative, they were getting extended with 1s causing
+  '\xe2' to be expanded to \uffffffe2, for example:
+
+    $ curl --variable 'v=“' --expand-write-out '{{v:json}}\n' file:///dev/nul
+  l
+    \uffffffe2\uffffff80\uffffff9c
+
+  I fixed this bug by making the code use explicitly unsigned char*
+  variables instead of char* variables.
+
+  Test 268 verifies
+
+  Reported-by: iconoclasthero
+  Closes #12434
+
+Stefan Eissing (1 Dec 2023)
+
+- cf-socket: TCP trace output local address used in connect
+
+  Closes #12427
+
+Jay Satiro (1 Dec 2023)
+
+- CURLINFO_PRETRANSFER_TIME_T.3: fix time explanation
+
+  - Change CURLINFO_PRETRANSFER_TIME_T explanation to say that it
+    includes protocol-specific instructions that trigger a transfer.
+
+  Prior to this change it explicitly said that it did not include those
+  instructions in the time, but that is incorrect.
+
+  The change is a copy of the fixed explanation already in
+  CURLINFO_PRETRANSFER_TIME, fixed by ec8dcd7b.
+
+  Reported-by: eeverettrbx@users.noreply.github.com
+
+  Fixes https://github.com/curl/curl/issues/12431
+  Closes https://github.com/curl/curl/pull/12432
+
+Daniel Stenberg (30 Nov 2023)
+
+- multi: during ratelimit multi_getsock should return no sockets
+
+  ... as there is nothing to wait for then, it just waits. Otherwise, this
+  causes much more CPU work and updates than necessary during ratelimit
+  periods.
+
+  Ref: https://curl.se/mail/lib-2023-11/0056.html
+  Closes #12430
+
+Dmitry Karpov (30 Nov 2023)
+
+- transfer: abort pause send when connection is marked for closing
+
+  This handles cases of some bi-directional "upgrade" scenarios
+  (i.e. WebSockets) where sending is paused until some "upgrade" handshake
+  is completed, but server rejects the handshake and closes the
+  connection.
+
+  Closes #12428
+
+Daniel Stenberg (28 Nov 2023)
 
 - RELEASE-NOTES: synced
 
-- multi: remove PENDING + MSGSENT handles from the main linked list
+- openssl: when a session-ID is reused, skip OCSP stapling
 
-  As they are not driving transfers or any socket activity, the main loop
-  does not need to iterate over these handles. A performance improvement.
+  Fixes #12399
+  Reported-by: Alexey Larikov
+  Closes #12418
 
-  They are instead only held in their own separate lists.
+- test1545: test doing curl_formadd twice with missing file
 
-  Assisted-by: Stefan Eissing
-  Ref: #10743
-  Closes #10762
+  Reproduces #12410
+  Verifies the fix
+  Closes #12421
 
-- multi: turn link/unlinking easy handles into dedicated functions
+- Curl_http_body: cleanup properly when Curl_getformdata errors
 
-- http_aws_sigv4: fix scan-build "value stored to 'ret' is never read"
+  Reported-by: yushicheng7788 on github
+  Based-on-work-by: yushicheng7788 on github
+  Fixes #12410
+  Closes #12421
 
-  Follow-up to 495d09810aa9a
+- test1477: verify that libcurl-errors.3 and public headers are synced
 
-  Closes #10766
+  The script errorcodes.pl extracts all error codes from all headers and
+  checks that they are all documented, then checks that all documented
+  error codes are also specified in a header file.
 
-- lib: skip Curl_llist_destroy calls
+  Closes #12424
 
-  Linked lists themselves do not carry any allocations, so for the lists
-  that do not have have a set destructor we can just skip the
-  Curl_llist_destroy() call and save CPU time.
+- libcurl-errors.3: sync with current public headers
 
-  Closes #10764
+  Closes #12424
 
-- lib643: LIB644 is never defined, this is dead code
+Stefan Eissing (28 Nov 2023)
 
-  Closes #10765
+- test459: fix for parallel runs
 
-- libtest/Makefile.inc: remove superfluous variables
+  - change warniing message to work better with varying filename
+    length.
+  - adapt test output check to new formatting
 
-  Rely on the defaults when possible.
+  Follow-up to 97ccc4479f77ba3191c6
+  Closes #12423
 
-  Closes #10765
+Daniel Stenberg (27 Nov 2023)
 
-- tests/http: remove year ranges from copyrights
+- tool_cb_prg: make the carriage return fit for wide progress bars
 
-  Closes #10763
+  When the progress bar was made max width (256 columns), the fly()
+  function attempted to generate its output buffer too long so that the
+  trailing carriage return would not fit and then the output would show
+  wrongly. The fly function is called when the expected total transfer is
+  unknown, which could be one or more progress calls before the actual
+  progress meter get shown when the expected transfer size is provided.
 
-Casey Bodley (14 Mar 2023)
+  This new take also replaces the msnprintf() call with a much simpler
+  memset() for speed.
 
-- aws_sigv4: fall back to UNSIGNED-PAYLOAD for sign_as_s3
+  Reported-by: Tim Hill
+  Fixes #12407
+  Closes #12415
 
-  all s3 requests default to UNSIGNED-PAYLOAD and add the required
-  x-amz-content-sha256 header. this allows CURLAUTH_AWS_SIGV4 to correctly
-  sign s3 requests to amazon with no additional configuration
+- tool_parsecfg: make warning output propose double-quoting
 
-  Signed-off-by: Casey Bodley 
+  When the config file parser detects a word that *probably* should be
+  quoted, mention double-quotes as a possible remedy.
 
-  Closes #9995
+  Test 459 verifies.
 
-Viktor Szakats (14 Mar 2023)
+  Proposed-by: Jiehong on github
+  Fixes #12409
+  Closes #12412
 
-- wolfssl: add quic/ngtcp2 detection in cmake, and fix builds
+Jay Satiro (26 Nov 2023)
 
-  - add QUIC/ngtcp2 detection in CMake with wolfSSL.
+- curl.rc: switch out the copyright symbol for plain ASCII
 
-    Because wolfSSL uses zlib if available, move compression detection
-    before TLS detection. (OpenSSL might also need this in the future.)
+  .. like we already do for libcurl.rc.
 
-  - wolfSSL 5.5.0 started using C99 types in its `quic.h` header, but it
-    doesn't #include the necessary C99 header itself, breaking builds
-    (unless another dependency pulled it by chance.) Add local workaround
-    for it. For this to work with all build tools, we had to fix our
-    header detection first. Ref: #10745
+  libcurl.rc copyright symbol used to cause a "non-ascii 8-bit codepoint"
+  warning so it was switched to ascii.
 
-    Ref: https://github.com/curl/curl-for-win/commit/6ad5f6ecc15620c15625fc4434
-  76b3a1ecef4f3f
+  Ref: https://github.com/curl/curl/commit/1ca62bb5#commitcomment-133474972
 
-  Closes #10739
+  Suggested-by: Robert Southee
 
-Stefan Eissing (14 Mar 2023)
+  Closes https://github.com/curl/curl/pull/12403
 
-- secure-transport: fix recv return code handling
+Daniel Stenberg (26 Nov 2023)
 
-  Return code handling of recv calls were not always correct when an error
-  occured or the connection was closed.
+- conncache: use the closure handle when disconnecting surplus connections
 
-  Closes #10717
+  Use the closure handle for disconnecting connection cache entries so
+  that anything that happens during the disconnect is not stored and
+  associated with the 'data' handle which already just finished a transfer
+  and it is important that details from the unrelated disconnect does not
+  taint meta-data in the data handle.
 
-- http2: Use KEEP_SEND_HOLD for flow control in HTTP/2
+  Like storing the response code.
 
-  - use the defined, but so far not used, KEEP_SEND_HOLD bit for flow
-    control based suspend of sending in transfers.
+  This also adjust test 1506. Unfortunately it also removes a key part of
+  the test that verifies that a connection is closed since when this
+  output vanishes (because the closure handle is used), we don't know
+  exactly that the connection actually gets closed in this test...
 
-  Prior to this change KEEP_SEND_PAUSE bit was used instead, but that can
-  interfere with pausing streams from the user side via curl_easy_pause.
+  Reported-by: ohyeaah on github
+  Fixes #12367
+  Closes #12405
 
-  Fixes https://github.com/curl/curl/issues/10751
-  Closes https://github.com/curl/curl/pull/10753
+- RELEASE-NOTES: synced
 
-Dan Fandrich (13 Mar 2023)
+Stefan Eissing (24 Nov 2023)
 
-- tests: fix control code that hid some text in runtests.1
+- quic: make eyeballers connect retries stop at weird replies
 
-- tests: sync option lists in runtests.pl & its man page
+  - when a connect immediately goes into DRAINING state, do
+    not attempt retries in the QUIC connection filter. Instead,
+    return CURLE_WEIRD_SERVER_REPLY
+  - When eyeballing, interpret CURLE_WEIRD_SERVER_REPLY as an
+    inconclusive answer. When all addresses have been attempted,
+    rewind the address list once on an inconclusive answer.
+  - refs #11832 where connects were retried indefinitely until
+    the overall timeout fired
 
-Daniel Stenberg (13 Mar 2023)
+  Closes #12400
 
-- multi: make multi_perform ignore/unignore signals less often
+Daniel Stenberg (24 Nov 2023)
 
-  For improved performance
+- CI: verify libcurl function SYNPOSIS sections
 
-  Reported-by: Jerome St-Louis
-  Ref: #10743
-  Closes #10750
+  With the .github/scripits/verify-synopsis.pl script
 
-Viktor Szakats (13 Mar 2023)
+  Closes #12402
 
-- cmake: delete unused HAVE__STRTOI64
+- docs/libcurl: SYNSOPSIS cleanup
 
-  Also delete obsolete surrounding comments.
+  - use the correct include file
+  - make sure they are declared as in the header file
+  - fix minor nroff syntax mistakes (missing .fi)
 
-  Reviewed-by: Daniel Stenberg
-  Closes #10756
+  These are verified by verify-synopsis.pl, which extracts the SYNPOSIS
+  code and runs it through gcc.
+
+  Closes #12402
+
+- sendf: fix comment typo
+
+- fopen: allocate the dir after fopen
 
-- CI: fix copyright header
+  Move the allocation of the directory name down to after the fopen() call
+  to allow that shortcut code path to avoid a superfluous malloc+free
+  cycle.
 
-  Follow-up to 395b9175b7422d699fa93643973295c106cdf147
+  Follow-up to 73b65e94f35311
 
-Daniel Stenberg (13 Mar 2023)
+  Closes #12398
 
-- RELEASE-PROCEDURE.md: update coming release dates
+Stefan Eissing (24 Nov 2023)
 
-Stefan Eissing (13 Mar 2023)
+- transfer: cleanup done+excess handling
 
-- tests/http: add pytest to GHA and improve tests
+  - add `SingleRequest->download_done` as indicator that
+    all download bytes have been received
+  - remove `stop_reading` bool from readwrite functions
+  - move excess body handling into client download writer
 
-  - added to: ngtcp2-quictls, ngtcp2-gnutls and the linux varians
-    quiche, bearssl, libressl, mbedtls, openssl3, rustls
-  - added disabled in ngtcp2-wolfssl due to weird SSL_connect() errors
-    not reproducable locally
+  Closes #12371
 
-  Improvements on pytest:
+Daniel Stenberg (23 Nov 2023)
 
-  -  handling of systems with nghttpx in $PATH
-     - configure will seach $PATH got nghttpx used in pytest
-     - pytest fixes for managing nghttpx without h3 support
-     - ngtcp2-wolfssl: use a fully enabled wolfssl build
+- fopen: create new file using old file's mode
 
-  - lower parallel count for http/1.1 tests, since we do not
-     want to test excessive connections.
-  - check built curl for HTTPS-proxy support in proxy tests
-  - bearssl does not like one of our critical cert extensions, making
-    it non-critical now
-  - bearssl is too slow for test_12, skipping
-  - making sure we do h3 tests only when curl and server support is there
+  Because the function renames the temp file to the target name as a last
+  step, if the file was previously owned by a different user, not ORing
+  the old mode could otherwise end up creating a file that was no longer
+  readable by the original owner after save.
 
-  Closes #10699
+  Reported-by: Loïc Yhuel
+  Fixes #12299
+  Closes #12395
 
-Marcel Raad (13 Mar 2023)
+- test1476: require proxy
 
-- tool_operate: silence unused parameter warning
+  Follow-up from 323df4261c3542
 
-  `global` is only used in the `my_setopt` macro version without
-  `CURL_DISABLE_LIBCURL_OPTION` since commit 4774decf10a.
+  Closes #12394
 
-  Closes https://github.com/curl/curl/pull/10752
+- fopen: create short(er) temporary file name
 
-Viktor Szakats (13 Mar 2023)
+  Only using random letters in the name plus a ".tmp" extension. Not by
+  appending characters to the final file name.
 
-- build: fix stdint/inttypes detection with non-autotools
+  Reported-by: Maksymilian Arciemowicz
 
-  Fix `stdint.h` and `inttypes.h` detection with non-autotools builds on
-  Windows. (autotools already auto-detected them accurately.)
+  Closes #12388
 
-  `lib/config-win32.h` builds (e.g. `Makefile.mk`):
-  - set `HAVE_STDINT_H` where supported.
-  - set `HAVE_INTTYPES_H` for MinGW.
+Stefan Eissing (23 Nov 2023)
 
-  CMake:
-  - auto-detect them on Windows. (They were both force-disabled.)
-  - delete unused `CURL_PULL_STDINT_H`.
-  - delete unused `CURL_PULL_INTTYPES_H`.
-  - stop detecting `HAVE_STDINT_H` twice.
-    Present since the initial CMake commit: 4c5307b45655ba75ab066564afdc0c111a8
-  b9291
+- tests: git ignore generated second-hsts.txt file
 
-  curl doesn't use these C99 headers, we need them now to workaround
-  broken wolfSSL builds. Ref: #10739
+  File is generated in test lib1900
 
-  Once that clears up, we can delete these detections and macros (unless
-  we want to keep them for future us.)
+  Follow-up to 7cb03229d9e9c5
+
+  Closes #12393
+
+Viktor Szakats (23 Nov 2023)
+
+- openssl: enable `infof_certstack` for 1.1 and LibreSSL 3.6
+
+  Lower the barrier to enable `infof_certstack()` from OpenSSL 3 to
+  OpenSSL 1.1.x, and LibreSSL 3.6 or upper.
+
+  With the caveat, that "group name" and "type name" are missing from
+  the log output with these TLS backends.
+
+  Follow-up to b6e6d4ff8f253c8b8055bab9d4d6a10f9be109f3 #12030
 
   Reviewed-by: Daniel Stenberg
-  Closes #10745
+  Closes #12385
 
-Daniel Stenberg (13 Mar 2023)
+Daniel Stenberg (23 Nov 2023)
 
-- RELEASE-NOTES: synced
+- urldata: fix typo in comment
 
-- ftp: add more conditions for connection reuse
+- CI: codespell
+
+  The list of words to ignore is in the file
+  .github/scripts/codespell-ignore.txt
+
+  Closes #12390
+
+- lib: fix comment typos
+
+  Five separate ones, found by codespell
+
+  Closes #12390
+
+- test1476: verify cookie PSL mixed case
+
+- cookie: lowercase the domain names before PSL checks
 
   Reported-by: Harry Sintonen
-  Closes #10730
 
-Dan Fandrich (12 Mar 2023)
+  Closes #12387
+
+Viktor Szakats (23 Nov 2023)
+
+- openssl: fix building with v3 `no-deprecated` + add CI test
+
+  - build quictls with `no-deprecated` in CI to have test coverage for
+    this OpenSSL 3 configuration.
+
+  - don't call `OpenSSL_add_all_algorithms()`, `OpenSSL_add_all_digests()`.
+    The caller code is meant for OpenSSL 3, while these two functions were
+    only necessary before OpenSSL 1.1.0. They are missing from OpenSSL 3
+    if built with option `no-deprecated`, causing build errors:
+    ```
+    vtls/openssl.c:4097:3: error: call to undeclared function 'OpenSSL_add_all_
+  algorithms'; ISO C99 and later do not   support implicit function declaration
+  s [-Wimplicit-function-declaration]
+    vtls/openssl.c:4098:3: error: call to undeclared function 'OpenSSL_add_all_
+  digests'; ISO C99 and later do not   support implicit function declarations [
+  -Wimplicit-function-declaration]
+    ```
+    Ref: https://ci.appveyor.com/project/curlorg/curl-for-win/builds/48587418?f
+  ullLog=true#L7667
+
+    Regression from b6e6d4ff8f253c8b8055bab9d4d6a10f9be109f3 #12030
+    Bug: https://github.com/curl/curl/issues/12380#issuecomment-1822944669
+    Reviewed-by: Alex Bozarth
+
+  - vquic/curl_ngtcp2: fix using `SSL_get_peer_certificate` with
+    `no-deprecated` quictls 3 builds.
+    Do it by moving an existing solution for this from `vtls/openssl.c`
+    to `vtls/openssl.h` and adjusting caller code.
+    ```
+    vquic/curl_ngtcp2.c:1950:19: error: implicit declaration of function 'SSL_g
+  et_peer_certificate'; did you mean   'SSL_get1_peer_certificate'? [-Wimplicit
+  -function-declaration]
+    ```
+    Ref: https://github.com/curl/curl/actions/runs/6960723097/job/18940818625#s
+  tep:24:1178
+
+  - curl_ntlm_core: fix `-Wunused-parameter`, `-Wunused-variable` and
+    `-Wunused-function` when trying to build curl with NTLM enabled but
+    without the necessary TLS backend (with DES) support.
+
+  Closes #12384
+
+- curl.h: delete Symbian OS references
+
+  curl deprecated Symbian OS in 3d64031fa7a80ac4ae3fd09a5939196268b92f81
+  via #5989. Delete references to it from public headers, because there
+  is no fresh release to use those headers with.
+
+  Reviewed-by: Dan Fandrich
+  Reviewed-by: Jay Satiro
+  Closes #12378
+
+- windows: use built-in `_WIN32` macro to detect Windows
+
+  Windows compilers define `_WIN32` automatically. Windows SDK headers
+  or build env defines `WIN32`, or we have to take care of it. The
+  agreement seems to be that `_WIN32` is the preferred practice here.
+  Make the source code rely on that to detect we're building for Windows.
+
+  Public `curl.h` was using `WIN32`, `__WIN32__` and `CURL_WIN32` for
+  Windows detection, next to the official `_WIN32`. After this patch it
+  only uses `_WIN32` for this. Also, make it stop defining `CURL_WIN32`.
+
+  There is a slight chance these break compatibility with Windows
+  compilers that fail to define `_WIN32`. I'm not aware of any obsolete
+  or modern compiler affected, but in case there is one, one possible
+  solution is to define this macro manually.
+
+  grepping for `WIN32` remains useful to discover Windows-specific code.
+
+  Also:
+
+  - extend `checksrc` to ensure we're not using `WIN32` anymore.
+
+  - apply minor formatting here and there.
+
+  - delete unnecessary checks for `!MSDOS` when `_WIN32` is present.
+
+  Co-authored-by: Jay Satiro
+  Reviewed-by: Daniel Stenberg
+
+  Closes #12376
+
+Stefan Eissing (22 Nov 2023)
+
+- url: ConnectionExists revisited
+
+  - have common pattern of `if not match, continue`
+  - revert pages long if()s to return early
+  - move dead connection check to later since it may
+    be relatively expensive
+  - check multiuse also when NOT building with NGHTTP2
+  - for MULTIUSE bundles, verify that the inspected
+    connection indeed supports multiplexing when in use
+    (bundles may contain a mix of connection, afaict)
+
+  Closes #12373
+
+Daniel Stenberg (22 Nov 2023)
+
+- CURLMOPT_MAX_CONCURRENT_STREAMS: make sure the set value is within range
+
+  ... or use the default value.
+
+  Also clarify the documentation language somewhat.
+
+  Closes #12382
+
+- urldata: make maxconnects a 32 bit value
+
+  "2^32 idle connections ought to be enough for anybody"
+
+  Closes #12375
+
+- FEATURES: update the URL phrasing
+
+  The URL is length limited since a while back so "no limit" simply is not
+  true anymore. Mention the URL RFC standard used instead.
+
+  Closes #12383
+
+- wolfssh: remove redundant static prototypes
+
+  vssh/wolfssh.c:346:18: error: redundant redeclaration of ‘wscp_recv’ [-We
+  rror=redundant-decls]
+
+  Closes #12381
+
+- setopt: remove superfluous use of ternary expressions
+
+  Closes #12374
+
+- mime: store "form escape" as a single bit
+
+  Closes #12374
+
+- setopt: check CURLOPT_TFTP_BLKSIZE range on set
+
+  ... instead of later when the transfer is about to happen.
+
+  Closes #12374
+
+Viktor Szakats (21 Nov 2023)
+
+- build: add more picky warnings and fix them
+
+  Enable more picky compiler warnings. I've found these options in the
+  nghttp3 project when implementing the CMake quick picky warning
+  functionality for it [1].
+
+  `-Wunused-macros` was too noisy to keep around, but fixed a few issues
+  it revealed while testing.
+
+  - autotools: reflect the more precisely-versioned clang warnings.
+    Follow-up to 033f8e2a08eb1d3102f08c4d8c8e85470f8b460e #12324
+  - autotools: sync between clang and gcc the way we set `no-multichar`.
+  - autotools: avoid setting `-Wstrict-aliasing=3` twice.
+  - autotools: disable `-Wmissing-noreturn` for MSYS gcc targets [2].
+    It triggers in libtool-generated stub code.
+
+  - lib/timeval: delete a redundant `!MSDOS` guard from a `WIN32` branch.
+
+  - lib/curl_setup.h: delete duplicate declaration for `fileno`.
+    Added in initial commit ae1912cb0d494b48d514d937826c9fe83ec96c4d
+    (1999-12-29). This suggests this may not be needed anymore, but if
+    it does, we may restore this for those specific (non-Windows) systems.
+  - lib: delete unused macro `FTP_BUFFER_ALLOCSIZE` since
+    c1d6fe2aaa5a26e49a69a4f2495b3cc7a24d9394.
+  - lib: delete unused macro `isxdigit_ascii` since
+    f65f750742068f579f4ee6d8539ed9d5f0afcb85.
+  - lib/mqtt: delete unused macro `MQTT_HEADER_LEN`.
+  - lib/multi: delete unused macro `SH_READ`/`SH_WRITE`.
+  - lib/hostip: add `noreturn` function attribute via new `CURL_NORETURN`
+    macro.
+  - lib/mprintf: delete duplicate declaration for `Curl_dyn_vprintf`.
+  - lib/rand: fix `-Wunreachable-code` and related fallouts [3].
+  - lib/setopt: fix `-Wunreachable-code-break`.
+  - lib/system_win32 and lib/timeval: fix double declarations for
+    `Curl_freq` and `Curl_isVistaOrGreater` in CMake UNITY mode [4].
+  - lib/warnless: fix double declarations in CMake UNITY mode [5].
+    This was due to force-disabling the header guard of `warnless.h` to
+    to reapply it to source code coming after `warnless.c` in UNITY
+    builds. This reapplied declarations too, causing the warnings.
+    Solved by adding a header guard for the lines that actually need
+    to be reapplied.
+  - lib/vauth/digest: fix `-Wunreachable-code-break` [6].
+  - lib/vssh/libssh2: fix `-Wunreachable-code-break` and delete redundant
+    block.
+  - lib/vtls/sectransp: fix `-Wunreachable-code-break` [7].
+  - lib/vtls/sectransp: suppress `-Wunreachable-code`.
+    Detected in `else` branches of dynamic feature checks, with results
+    known at compile-time, e.g.
+    ```c
+    if(SecCertificateCopySubjectSummary)  /* -> true */
+    ```
+    Likely fixable as a separate micro-project, but given SecureTransport
+    is deprecated anyway, let's just silence these locally.
+  - src/tool_help: delete duplicate declaration for `helptext`.
+  - src/tool_xattr: fix `-Wunreachable-code`.
+  - tests: delete duplicate declaration for `unitfail` [8].
+  - tests: delete duplicate declaration for `strncasecompare`.
+  - tests/libtest: delete duplicate declaration for `gethostname`.
+    Originally added in 687df5c8c39c370a59999b9afc0917d808d978b7
+    (2010-08-02).
+    Got complicated later: c49e9683b85ba9d12cbb6eebc4ab2c8dba68fbdc
+    If there are still systems around with warnings, we may restore the
+    prototype, but limited for those systems.
+  - tests/lib2305: delete duplicate declaration for
+    `libtest_debug_config`.
+  - tests/h2-download: fix `-Wunreachable-code-break`.
+
+  [1] https://github.com/ngtcp2/nghttp3/blob/a70edb08e954d690e8fb2c1df999b5a056
+  f8bf9f/cmake/PickyWarningsC.cmake
+  [2] https://ci.appveyor.com/project/curlorg/curl/builds/48553586/job/3qkgjaui
+  qla5fj45?fullLog=true#L1675
+  [3] https://github.com/curl/curl/actions/runs/6880886309/job/18716044703?pr=1
+  2331#step:7:72
+      https://github.com/curl/curl/actions/runs/6883016087/job/18722707368?pr=1
+  2331#step:7:109
+  [4] https://ci.appveyor.com/project/curlorg/curl/builds/48555101/job/9g15qkrr
+  iklpf1ut#L204
+  [5] https://ci.appveyor.com/project/curlorg/curl/builds/48555101/job/9g15qkrr
+  iklpf1ut#L218
+  [6] https://github.com/curl/curl/actions/runs/6880886309/job/18716042927?pr=1
+  2331#step:7:290
+  [7] https://github.com/curl/curl/actions/runs/6891484996/job/18746659406?pr=1
+  2331#step:9:1193
+  [8] https://github.com/curl/curl/actions/runs/6882803986/job/18722082562?pr=1
+  2331#step:33:1870
+
+  Closes #12331
+
+Daniel Stenberg (21 Nov 2023)
+
+- transfer: avoid unreachable expression
+
+  If curl_off_t and size_t have the same size (which is common on modern
+  64 bit systems), a condition cannot occur which Coverity pointed
+  out. Avoid the warning by having the code conditionally only used if
+  curl_off_t actually is larger.
+
+  Follow-up to 1cd2f0072fa482e25baa2
+
+  Closes #12370
+
+Stefan Eissing (21 Nov 2023)
+
+- transfer: readwrite improvements
+
+  - changed header/chunk/handler->readwrite prototypes to accept `buf`,
+    `blen` and a `pconsumed` pointer. They now get the buffer to work on
+    and report back how many bytes they consumed
+  - eliminated `k->str` in SingleRequest
+  - improved excess data handling to properly calculate with any body data
+    left in the headerb buffer
+  - eliminated `k->badheader` enum to only be a bool
+
+  Closes #12283
+
+Daniel Stenberg (21 Nov 2023)
+
+- RELEASE-NOTES: synced
+
+Jiří Hruška (21 Nov 2023)
+
+- transfer: avoid calling the read callback again after EOF
+
+  Regression since 7f43f3dc5994d01b12 (7.84.0)
+
+  Bug: https://curl.se/mail/lib-2023-11/0017.html
+
+  Closes #12363
+
+Daniel Stenberg (21 Nov 2023)
+
+- doh: provide better return code for responses w/o addresses
+
+  Previously it was wrongly returning CURLE_OUT_OF_MEMORY when the
+  response did not contain any addresses. Now it more accurately returns
+  CURLE_COULDNT_RESOLVE_HOST.
+
+  Reported-by: lRoccoon on github
+
+  Fixes #12365
+  Closes #12366
+
+Stefan Eissing (21 Nov 2023)
+
+- HTTP/2, HTTP/3: handle detach of onoing transfers
+
+  - refs #12356 where a UAF is reported when closing a connection
+    with a stream whose easy handle was cleaned up already
+  - handle DETACH events same as DONE events in h2/h3 filters
+
+  Fixes #12356
+  Reported-by: Paweł Wegner
+  Closes #12364
+
+Viktor Szakats (20 Nov 2023)
+
+- autotools: stop setting `-std=gnu89` with `--enable-warnings`
+
+  Do not alter the C standard when building with `--enable-warnings` when
+  building with gcc.
+
+  On one hand this alters warning results compared to a default build.
+  On the other, it may produce different binaries, which is unexpected.
+
+  Also fix new warnings that appeared after removing `-std=gnu89`:
+
+  - include: fix public curl headers to use the correct printf mask for
+    `CURL_FORMAT_CURL_OFF_T` and `CURL_FORMAT_CURL_OFF_TU` with mingw-w64
+    and Visual Studio 2013 and newer. This fixes the printf mask warnings
+    in examples and tests. E.g. [1]
+
+  - conncache: fix printf format string [2].
+
+  - http2: fix potential null pointer dereference [3].
+    (seen on Slackware with gcc 11.)
+
+  - libssh: fix printf format string in SFTP code [4].
+    Also make MSVC builds compatible with old CRT versions.
+
+  - libssh2: fix printf format string in SFTP code for MSVC.
+    Applying the same fix as for libssh above.
+
+  - unit1395: fix `argument is null` and related issues [5]:
+    - stop calling `strcmp()` with NULL to avoid undefined behaviour.
+    - fix checking results if some of them were NULL.
+    - do not pass NULL to printf `%s`.
 
-- tests: make first.c the same for both lib tests and unit tests
+  - ci: keep a build job with `-std=gnu89` to continue testing for
+    C89-compliance. We can apply this to other gcc jobs as needed.
+    Ref: b23ce2cee7329bbf425f18b49973b7a5f23dfcb4 (2022-09-23) #9542
 
-  The only difference used to be global variable used in unittest tests.
-  After cb7ed5a removed individual flag overrides for the unittests, first.c
-  was no longer recompiled for unit tests to include the flag, so whether it
-  worked or gave a link error depended on whether it was compiled in
-  libtest or unittest first. This way also speeds up the build by
-  eliminating 40 identical compile invocations.
+  [1] https://dev.azure.com/daniel0244/curl/_build/results?buildId=18581&view=l
+  ogs&jobId=ccf9cc6d-2ef1-5cf2-2c09-30f0c14f923b
+  [2] https://github.com/curl/curl/actions/runs/6896854263/job/18763831142?pr=1
+  2346#step:6:67
+  [3] https://github.com/curl/curl/actions/runs/6896854253/job/18763839238?pr=1
+  2346#step:30:214
+  [4] https://github.com/curl/curl/actions/runs/6896854253/job/18763838007?pr=1
+  2346#step:29:895
+  [5] https://github.com/curl/curl/actions/runs/6896854253/job/18763836775?pr=1
+  2346#step:33:1689
 
-  Fixes #10749
+  Closes #12346
 
-- tests: use AM_CPPFILES to modify flags in unit tests
+- autotools: fix/improve gcc and Apple clang version detection
 
-  Using CPPFLAGS sometimes caused odd compile issues when building tests
-  with parallel make and AM_CPPFILES is the right flag, anyway.
+  - Before this patch we expected `n.n` `-dumpversion` output, but Ubuntu
+    may return `n-win32` (also with `-dumpfullversion`). Causing these
+    errors and failing to enable picky warnings:
+    ```
+    ../configure: line 23845: test: : integer expression expected
+    ```
+    Ref: https://github.com/libssh2/libssh2/actions/runs/6263453828/job/1700789
+  3718#step:5:143
 
-  Follow-up to cb7ed5a
+    Fix that by stripping any dash-suffix and handling a dotless (major-only)
+    version number by assuming `.0` in that case.
 
-  Ref #10749
+    `9.3-posix`, `9.3-win32`, `6`, `9.3.0`, `11`, `11.2`, `11.2.0`
+    Ref: https://github.com/mamedev/mame/pull/9767
 
-Viktor Szakats (13 Mar 2023)
+  - fix Apple clang version detection for releases between
+    'Apple LLVM version 7.3.0' and 'Apple LLVM version 10.0.1' where the
+    version was under-detected as 3.7 llvm/clang equivalent.
 
-- Makefile.mk: fix -g option in debug mode [ci skip]
+  - fix Apple clang version detection for 'Apple clang version 11.0.0'
+    and newer where the Apple clang version was detected, instead of its
+    llvm/clang equivalent.
 
-  Add it to `CFLAGS` (was: `LDFLAGS`).
+  - display detected clang/gcc/icc compiler version.
 
-  Closes #10747
+  Via libssh2:
+  - https://github.com/libssh2/libssh2/commit/00a3b88c51cdb407fbbb347a2e38c5c7d
+  89875ad
+    https://github.com/libssh2/libssh2/pull/1187
+  - https://github.com/libssh2/libssh2/commit/89ccc83c7da73e7ca3a112e3500081319
+  42b592e
+    https://github.com/libssh2/libssh2/pull/1232
 
-Jay Satiro (12 Mar 2023)
+  Closes #12362
 
-- tool: improve --stderr handling
+- autotools: delete LCC compiler support bits
 
-  - freopen stderr with the user-specified file (--stderr file) instead of
-    using a separate 'errors' stream.
+  Follow-up to fd7ef00f4305a2919e6950def1cf83d0110a4acd #12222
 
-  - In tool_setup.h override stdio.h's stderr macro as global variable
-    tool_stderr.
+  Closes #12357
 
-  Both freopen and overriding the stderr macro are necessary because if
-  the user-specified filename is "-" then stdout is assigned to
-  tool_stderr and no freopen takes place. See the PR for more information.
+- cmake: add test for `DISABLE` options, add `CURL_DISABLE_HEADERS_API`
 
-  Ref: https://github.com/curl/curl/issues/10491
+  - tests: verify CMake `DISABLE` options.
 
-  Closes https://github.com/curl/curl/pull/10673
+    Make an exception for 2 CMake-only ones, and one more that's
+    using a different naming scheme, also in autotools and source.
 
-Dan Fandrich (11 Mar 2023)
+  - cmake: add support for `CURL_DISABLE_HEADERS_API`.
 
-- CI: don't run CI jobs if only another CI was changed
+  Suggested-by: Daniel Stenberg
+  Ref: https://github.com/curl/curl/pull/12345#pullrequestreview-1736238641
 
-  Also skip builds on non-Windows platforms when only Windows build files
-  have changed.
+  Closes #12353
 
-  This should reduce the number of useless builds and the associated
-  waiting time and chance of spurious failures, freeing resources for
-  new PRs.
+Jacob Hoffman-Andrews (20 Nov 2023)
 
-  Closes #10742
+- hyper: temporarily remove HTTP/2 support
 
-- http: don't send 100-continue for short PUT requests
+  The current design of the Hyper integration requires rebuilding the
+  Hyper clientconn for each request. However, building the clientconn
+  requires resending the HTTP/2 connection preface, which is incorrect
+  from a protocol perspective. That in turn causes servers to send GOAWAY
+  frames, effectively degrading performance to "no connection reuse" in
+  the best case. It may also be triggering some bugs where requests get
+  dropped entirely and reconnects take too long.
 
-  This is already how curl is documented to behave in Everything curl, but
-  in actuality only short POSTs skip this. This should knock 30 seconds
-  off a full run of the test suite since the 100-continue timeout will no
-  longer be hit.
+  This doesn't rule out HTTP/2 support with Hyper, but it may take a
+  redesign of the Hyper integration in order to make things work.
 
-  Closes #10740
+  Closes #12191
 
-- tests: add DELAY keyword to more tests using waits
+Jay Satiro (20 Nov 2023)
 
-- tests: hack to build most unit tests under cmake
+- schannel: fix unused variable warning
 
-  These are only built when a libcurl static library is available, since
-  we're not building a special libcurlu library yet and these tests rely
-  on private symbols that aren't available in the shared library. A few
-  unit tests do require libcurlu, so those are not built.
+  Bug: https://github.com/curl/curl/pull/12349#issuecomment-1818000846
+  Reported-by: Viktor Szakats
+
+  Closes https://github.com/curl/curl/pull/12361
+
+Daniel Stenberg (19 Nov 2023)
+
+- url: find scheme with a "perfect hash"
+
+  Instead of a loop to scan over the potentially 30+ scheme names, this
+  uses a "perfect hash" table. This works fine because the set of schemes
+  is known and cannot change in a build. The hash algorithm and table size
+  is made to only make a single scheme index per table entry.
+
+  The perfect hash is generated by a separate tool (scripts/schemetable.c)
+
+  Closes #12347
+
+- scripts: add schemetable.c
+
+  This tool generates a scheme-matching table.
+
+  It iterates over a number of different initial and shift values in order
+  to find the hash algorithm that needs the smallest possible table.
+
+  The generated hash function, table and table size then needs to be used
+  by the url.c:Curl_getn_scheme_handler() function.
+
+Stefan Eissing (19 Nov 2023)
+
+- vtls/vquic, keep peer name information together
+
+  - add `struct ssl_peer` to keep hostname, dispname and sni
+    for a filter
+  - allocate `sni` for use in VTLS backend
+  - eliminate `Curl_ssl_snihost()` and its use of the download buffer
+  - use ssl_peer in SSL and QUIC filters
 
-  Closes #10722
+  Closes #12349
 
-- tests: fix MSVC unreachable code warnings in unit tests
+Viktor Szakats (18 Nov 2023)
 
-  Switch unit1654 to use the proper test macros as well.
+- build: always revert `#pragma GCC diagnostic` after use
 
-- tests: make CPPFLAGS common to all unit tests
+  Before this patch some source files were overriding gcc warning options,
+  but without restoring them at the end of the file. In CMake UNITY builds
+  these options spilled over to the remainder of the source code,
+  effecitvely disabling them for a larger portion of the codebase than
+  intended.
 
-  There's no need to specify them individually.
+  `#pragma clang diagnostic` didn't have such issue in the codebase.
 
-- tests: keep cmake unit tests names in sync
+  Reviewed-by: Marcel Raad
+  Closes #12352
+
+- tidy-up: casing typos, delete unused Windows version aliases
+
+  - cmake: fix casing of `UnixSockets` to match the rest of the codebase.
+
+  - curl-compilers.m4: fix casing in a comment.
+
+  - setup-win32: delete unused Windows version constant aliases.
+
+  Reviewed-by: Marcel Raad
+  Closes #12351
 
-  Put only the test names into Makefile.inc so they can be used by both
-  cmake and automake. This will prevent the list of tests from becoming
-  out of date when they are also built under cmake.
+- keylog: disable if unused
 
-Viktor Szakats (11 Mar 2023)
+  Fully disable keylog code if there is no TLS or QUIC subsystem using it.
 
-- src: silence wmain() warning for all build methods
+  Closes #12350
 
-  llvm/clang and gcc doesn't recognize the wmain() function in Unicode
-  Windows builds:
+- cmake: add `CURL_DISABLE_BINDLOCAL` option
 
-  llvm/clang:
+  To match similar autotools option.
+
+  Default is `ON`.
+
+  Reviewed-by: Daniel Stenberg
+  Closes #12345
+
+- url: fix `-Wzero-length-array` with no protocols
+
+  Fixes:
   ```
-  ../../src/tool_main.c:239:5: warning: no previous prototype for function 'wma
-  in' [-Wmissing-prototypes]
-  int wmain(int argc, wchar_t *argv[])
-      ^
-  1 warning generated.
+  ./lib/url.c:178:56: warning: use of an empty initializer is a C2x extension [
+  -Wc2x-extensions]
+    178 | static const struct Curl_handler * const protocols[] = {
+        |                                                        ^
+  ./lib/url.c:178:56: warning: zero size arrays are an extension [-Wzero-length
+  -array]
   ```
 
-  gcc:
+  Closes #12344
+
+- url: fix builds with `CURL_DISABLE_HTTP`
+
+  Fixes:
   ```
-  ../../src/tool_main.c:239:5: warning: no previous prototype for 'wmain' [-Wmi
-  ssing-prototypes]
-    239 | int wmain(int argc, wchar_t *argv[])
-        |     ^~~~~
+  ./lib/url.c:456:35: error: no member named 'formp' in 'struct UrlState'
+    456 |   Curl_mime_cleanpart(data->state.formp);
+        |                       ~~~~~~~~~~~ ^
   ```
 
-  Before this patch, we already silenced it with CMake. This patch moves
-  the silencing to the source, so that it applies to all build tools.
+  Regression from 74b87a8af13a155c659227f5acfa78243a8b2aa6 #11682
+
+  Closes #12343
 
-  Bug: https://github.com/curl/curl/issues/7229#issuecomment-1464806651
+- http: fix `-Wunused-parameter` with no auth and no proxy
+
+  ```
+  lib/http.c:734:26: warning: unused parameter 'proxy' [-Wunused-parameter]
+                      bool proxy)
+                           ^
+  ```
 
   Reviewed-by: Marcel Raad
-  Closes #10744
+  Closes #12338
 
-Dan Fandrich (10 Mar 2023)
+Daniel Stenberg (16 Nov 2023)
 
-- CI: fix retrying on brew failures
+- TODO: Some TLS options are not offered for HTTPS proxies
 
-  The previous attempt didn't consider that the shell would exit
-  immediately after the false statement in the retry case.
+  Closes #12286
+  Closes #12342
 
-  Follow-up to dc141a37
+- RELEASE-NOTES: synced
 
-Stefan Eissing (10 Mar 2023)
+- duphandle: make dupset() not return with pointers to old alloced data
 
-- http2: fix error handling during parallel operations
+  As the blob pointers are to be duplicated, the function must not return
+  mid-function with lingering pointers to the old handle's allocated data,
+  as that would lead to double-free in OOM situations.
 
-  RST and connection close were not handled correctly during parallel
-  transfers, leading to aborted response bodies being reported complete.
+  Make sure to clear all destination pointers first to avoid this risk.
 
-  Closes #10715
+  Closes #12337
 
-Daniel Stenberg (10 Mar 2023)
+Viktor Szakats (16 Nov 2023)
 
-- url: only reuse connections with same GSS delegation
+- http: fix `-Wunused-variable` compiler warning
 
-  Reported-by: Harry Sintonen
-  Closes #10731
+  Fix compiler warnings in builds with disabled auths, NTLM and SPNEGO.
+
+  E.g. with `CURL_DISABLE_BASIC_AUTH` + `CURL_DISABLE_BEARER_AUTH` +
+  `CURL_DISABLE_DIGEST_AUTH` + `CURL_DISABLE_NEGOTIATE_AUTH` +
+  `CURL_DISABLE_NTLM` on non-Windows.
+
+  ```
+  ./curl/lib/http.c:737:12: warning: unused variable 'result' [-Wunused-variabl
+  e]
+    CURLcode result = CURLE_OK;
+             ^
+  ./curl/lib/http.c:995:18: warning: variable 'availp' set but not used [-Wunus
+  ed-but-set-variable]
+    unsigned long *availp;
+                   ^
+  ./curl/lib/http.c:996:16: warning: variable 'authp' set but not used [-Wunuse
+  d-but-set-variable]
+    struct auth *authp;
+                 ^
+  ```
+
+  Regression from e92edfbef64448ef461117769881f3ed776dec4e #11490
 
-Viktor Szakats (10 Mar 2023)
+  Fixes #12228
+  Closes #12335
 
-- lib: silence clang/gcc -Wvla warnings in brotli headers
+Jay Satiro (16 Nov 2023)
 
-  brotli v1.0.0 throughout current latest v1.0.9 and latest master [1]
-  trigger this warning.
+- tool: support bold headers in Windows
 
-  It happened with CMake and GNU Make. autotools builds avoid it with
-  the `convert -I options to -isystem` macro.
+  - If virtual terminal processing is enabled in Windows then use ANSI
+    escape codes Esc[1m and Esc[22m to turn bold on and off.
 
-  llvm/clang:
+  Suggested-by: Gisle Vanem
+
+  Ref: https://github.com/curl/curl/discussions/11770
+
+  Closes https://github.com/curl/curl/pull/12321
+
+Viktor Szakats (15 Nov 2023)
+
+- build: fix libssh2 + `CURL_DISABLE_DIGEST_AUTH` + `CURL_DISABLE_AWS`
+
+  Builds with libssh2 + `-DCURL_DISABLE_DIGEST_AUTH=ON` +
+  `-DCURL_DISABLE_AWS=ON` in combination with either Schannel on Windows,
+  or `-DCURL_DISABLE_NTLM=ON` on other operating systems failed while
+  compiling due to a missing HMAC declaration.
+
+  The reason is that HMAC is required by `lib/sha256.c` which publishes
+  `Curl_sha256it()` which is required by `lib/vssh/libssh2.c` when
+  building for libssh2 v1.8.2 (2019-05-25) or older.
+
+  Make sure to compile the HMAC bits for a successful build.
+
+  Both HMAC and `Curl_sha256it()` rely on the same internals, so splitting
+  them into separate sources isn't practical.
+
+  Fixes:
   ```
-  In file included from ./curl/lib/content_encoding.c:36:
-  ./brotli/x64-ucrt/usr/include/brotli/decode.h:204:34: warning: variable lengt
-  h array used [-Wvla]
-      const uint8_t encoded_buffer[BROTLI_ARRAY_PARAM(encoded_size)],
-                                   ^~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
-  ./brotli/x64-ucrt/usr/include/brotli/port.h:253:34: note: expanded from macro
-   'BROTLI_ARRAY_PARAM'
-                                   ^~~~~~
-  In file included from ./curl/lib/content_encoding.c:36:
-  ./brotli/x64-ucrt/usr/include/brotli/decode.h:206:48: warning: variable lengt
-  h array used [-Wvla]
-      uint8_t decoded_buffer[BROTLI_ARRAY_PARAM(*decoded_size)]);
-                             ~~~~~~~~~~~~~~~~~~~~^~~~~~~~~~~~~
-  ./brotli/x64-ucrt/usr/include/brotli/port.h:253:35: note: expanded from macro
-   'BROTLI_ARRAY_PARAM'
-                                   ~^~~~~
+  [...]
+  In file included from ./curl/_x64-win-ucrt-cmake-llvm-bld/lib/CMakeFiles/libc
+  url_object.dir/Unity/unity_0_c.c:310:
+  ./curl/lib/sha256.c:527:42: error: array has incomplete element type 'const s
+  truct HMAC_params'
+    527 | const struct HMAC_params Curl_HMAC_SHA256[] = {
+        |                                          ^
+  ./curl/lib/curl_sha256.h:34:21: note: forward declaration of 'struct HMAC_par
+  ams'
+  [...]
   ```
 
-  gcc:
+  Regression from e92edfbef64448ef461117769881f3ed776dec4e #11490
+
+  Fixes #12273
+  Closes #12332
+
+Daniel Stenberg (15 Nov 2023)
+
+- duphandle: also free 'outcurl->cookies' in error path
+
+  Fixes memory-leak when OOM mid-function
+
+  Use plain free instead of safefree, since the entire struct is
+  freed below.
+
+  Remove some free calls that is already freed in Curl_freeset()
+
+  Closes #12329
+
+Viktor Szakats (15 Nov 2023)
+
+- config-win32: set `HAVE_SNPRINTF` for mingw-w64
+
+  It's available in all mingw-w64 releases. We already pre-fill this
+  detection in CMake.
+
+  Closes #12325
+
+- sasl: fix `-Wunused-function` compiler warning
+
+  In builds with disabled auths.
+
   ```
-  In file included from ./curl/lib/content_encoding.c:36:
-  ./brotli/x64-ucrt/usr/include/brotli/decode.h:204:5: warning: ISO C90 forbids
-   variable length array 'encoded_buffer' [-Wvla]
-    204 |     const uint8_t encoded_buffer[BROTLI_ARRAY_PARAM(encoded_size)],
-        |     ^~~~~
-  ./brotli/x64-ucrt/usr/include/brotli/decode.h:206:5: warning: ISO C90 forbids
-   variable length array 'decoded_buffer' [-Wvla]
-    206 |     uint8_t decoded_buffer[BROTLI_ARRAY_PARAM(*decoded_size)]);
-        |     ^~~~~~~
+  lib/curl_sasl.c:266:17: warning: unused function 'get_server_message' [-Wunus
+  ed-function]
+  static CURLcode get_server_message(struct SASL *sasl, struct Curl_easy *data,
+                  ^
+  1 warning generated.
   ```
+  Ref: https://github.com/curl/trurl/actions/runs/6871732122/job/18689066151#st
+  ep:3:3822
+
+  Reviewed-by: Daniel Stenberg
+  Closes #12326
+
+- build: picky warning updates
 
-  [1] https://github.com/google/brotli/commit/ed1995b6bda19244070ab5d331111f16f
-  67c8054
+  - cmake: sync some picky gcc warnings with autotools.
+  - cmake, autotools: add `-Wold-style-definition` for clang too.
+  - cmake: more precise version info for old clang options.
+  - cmake: use `IN LISTS` syntax in `foreach()`.
 
   Reviewed-by: Daniel Stenberg
   Reviewed-by: Marcel Raad
-  Closes #10738
+  Closes #12324
 
-Daniel Stenberg (10 Mar 2023)
+Daniel Stenberg (15 Nov 2023)
 
-- curl_path: create the new path with dynbuf
+- urldata: move cookielist from UserDefined to UrlState
 
-  Closes #10729
+  1. Because the value is not strictly set with a setopt option.
 
-- url: remove dummy protocol handler
+  2. Because otherwise when duping a handle when all the set.* fields are
+     first copied and an error happens (think out of memory mid-function),
+     the function would easily free the list *before* it was deep-copied,
+     which could lead to a double-free.
 
-  Just two added checks were needed saves a whole handler struct.
+  Closes #12323
 
-  Closes #10727
+Viktor Szakats (14 Nov 2023)
 
-Dan Fandrich (10 Mar 2023)
+- autotools: avoid passing `LDFLAGS` twice to libcurl
 
-- CI: retry a failed brew update too, not just brew install
+  autotools passes `LDFLAGS` automatically linker commands. curl's
+  `lib/Makefile.am` customizes libcurl linker flags. In that
+  customization, it added `LDFLAGS` to the custom flags. This resulted in
+  passing `LDFLAGS` _twice_ to the `libtool` command.
 
-  Also, make sure an eventual failure ends up returning a failure code so
-  the job stops.
+  Most of the time this is benign, but some `LDFLAGS` options can break
+  the build when passed twice. One such example is passing `.o` files,
+  e.g. `crt*.o` files necessary when customizing the C runtime, e.g. for
+  MUSL builds.
 
-Daniel Stenberg (10 Mar 2023)
+  Passing them twice resulted in duplicate symbol errors:
+  ```
+  libtool: link:  clang-15 --target=aarch64-unknown-linux-musl [...] /usr/lib/a
+  arch64-linux-musl/crt1.o [...] /usr/lib/aarch64-linux-musl/crt1.o [...]
+  ld.lld-15: error: duplicate symbol: _start
+  >>> defined at crt1.c
+  >>>            /usr/lib/aarch64-linux-musl/crt1.o:(.text+0x0)
+  >>> defined at crt1.c
+  >>>            /usr/lib/aarch64-linux-musl/crt1.o:(.text+0x0)
+  [...]
+  clang: error: linker command failed with exit code 1 (use -v to see invocatio
+  n)
+  ```
 
-- url: fix the SSH connection reuse check
+  This behaviour came with commit 1a593191c2769a47b8c3e4d9715ec9f6dddf5e36
+  (2013-07-23) as a fix for bug https://curl.haxx.se/bug/view.cgi?id=1217.
+  The patch was a works-for-me hack that ended up merged in curl:
+  https://sourceforge.net/p/curl/bugs/1217/#06ef
+  With the root cause remaining unclear.
 
-  Reported-by: Harry Sintonen
-  Closes #10735
+  Perhaps the SUNPro 12 linker was sensitive to `-L` `-l` order, requiring
+  `-L` first? This would be unusual and suggests a bug in either the
+  linker or in `libtool`.
 
-- CURLOPT_PROXY.3: curl+NSS does not handle HTTPS over unix domain socket
+  The curl build does pass the list of detected libs via its own
+  `LIBCURL_LIBS` variable, which ends up before `LDFLAGS` on the `libtool`
+  command line, but it's the job of `libtool` to ensure that even
+  a peculiar linker gets the options in the expected order. Also because
+  autotools passes `LDFLAGS` last, making it hardly possible to pass
+  anything after it.
 
-  It results in error "NSS error -5985 (PR_ADDRESS_NOT_SUPPORTED_ERROR)"
+  Perhaps in the 10 years since this issue, this already got a fix
+  upstream.
 
-  Disabled test 1470 for NSS builds and documented the restriction.
+  This patch deletes `LDFLAGS` from our customized libcurl options,
+  leaving a single copy of them as passed by autotools automatically.
 
-  Reported-by: Dan Fandrich
-  Fixes #10723
-  Closes #10734
+  Reverts 1a593191c2769a47b8c3e4d9715ec9f6dddf5e36
+  Closes #12310
 
-- CURLSHOPT_SHARE.3: HSTS sharing is not thread-safe
+- autotools: accept linker flags via `CURL_LDFLAGS_{LIB,BIN}`
 
-  Reported-by: Hiroki Kurosawa
-  Closes #10732
+  To allow passing `LDFLAGS` specific to libcurl (`CURL_LDFLAGS_LIB`) and
+  curl tool (`CURL_LDFLAGS_BIN`).
 
-- telnet: only accept option arguments in ascii
+  This makes it possible to build libcurl and curl with a single
+  invocation with lib- and tool-specific custom linker flags.
 
-  To avoid embedded telnet negotiation commands etc.
+  Such flag can be enabling `.map` files, a `.def` file for libcurl DLL,
+  controlling static/shared, incl. requesting a static curl tool (with
+  `-static-libtool-libs`) while building both shared and static libcurl.
 
-  Reported-by: Harry Sintonen
-  Closes #10728
+  curl-for-win uses the above and some more.
+
+  These options are already supported in `Makefile.mk`. CMake has built-in
+  variables for this.
 
-- test1903: test use of COOKIEFILE - reset - COOKIEFILE
+  Closes #12312
 
-  This also tests for the memory leak bug fixed by parent commit b559ef6f.
+Jay Satiro (14 Nov 2023)
 
-  Ref: #10694
+- tool_cb_hdr: add an additional parsing check
 
-  Closes https://github.com/curl/curl/pull/10712
+  - Don't dereference the past-the-end element when parsing the server's
+    Content-disposition header.
 
-Jay Satiro (10 Mar 2023)
+  As 'p' is advanced it can point to the past-the-end element and prior
+  to this change 'p' could be dereferenced in that case.
 
-- url: fix cookielist memleak when curl_easy_reset
+  Technically the past-the-end element is not out of bounds because dynbuf
+  (which manages the header line) automatically adds a null terminator to
+  every buffer and that is not included in the buffer length passed to
+  the header callback.
 
-  - Free set.cookelist in Curl_freeset instead of Curl_close.
+  Closes https://github.com/curl/curl/pull/12320
 
-  Prior to this change the cookielist linked list wasn't freed by
-  curl_easy_reset which calls Curl_freeset to free all set.
+Philip Heiduck (14 Nov 2023)
 
-  Bug: https://github.com/curl/curl/issues/10694#issuecomment-1458619157
-  Reported-by: Sergey Ryabinin
+- .cirrus.yml: freebsd 14
 
-  Closes https://github.com/curl/curl/pull/10709
+  ensure curl works on latest freebsd version
 
-Dan Fandrich (10 Mar 2023)
+  Closes #12053
 
-- tests: fix some keywords and unused sections
+Daniel Stenberg (13 Nov 2023)
 
-- tests: fix test1301 to call the right binary
+- easy: in duphandle, init the cookies for the new handle
 
-  It was refactored in commit 480ac6e5 but this step was missed.
+  ... not the source handle.
 
-- tests: add timeout, SLOWDOWN and DELAY keywords to tests
+  Closes #12318
 
-  These are tests that are testing timing and end up being quite slow.
+- duphandle: use strdup to clone *COPYPOSTFIELDS if size is not set
 
-Daniel Stenberg (10 Mar 2023)
+  Previously it would unconditionally use the size, which is set to -1
+  when strlen is requested.
+
+  Updated test 544 to verify.
+
+  Closes #12317
 
 - RELEASE-NOTES: synced
 
-Stefan Eissing (10 Mar 2023)
+- curl_easy_duphandle.3: clarify how HSTS and alt-svc are duped
+
+  Closes #12315
+
+- urldata: move hstslist from 'set' to 'state'
+
+  To make it work properly with curl_easy_duphandle(). This, because
+  duphandle duplicates the entire 'UserDefined' struct by plain copy while
+  'hstslist' is a linked curl_list of file names. This would lead to a
+  double-free when the second of the two involved easy handles were
+  closed.
+
+  Closes #12315
+
+- test1900: verify duphandle with HSTS using multiple files
 
-- wolfSSL: ressurect the BIO `io_result`
+  Closes #12315
 
-  In pytest'ing the situation occored that wolfSSL reported an
-  IO error when the underlying BIO operation was returning an
-  CURLE_AGAIN condition.
+Goro FUJI (13 Nov 2023)
 
-  Readding the `io_result` filter context member to detect such
-  situations.
+- http: allow longer HTTP/2 request method names
 
-  Also, making sure that the returned CURLcode is initialized
-  on all recv operations outcome.
+  - Increase the maximum request method name length from 11 to 23.
 
-  Closes #10716
+  For HTTP/1.1 and earlier there's not a specific limit in libcurl for
+  method length except that it is limited by the initial HTTP request
+  limit (DYN_HTTP_REQUEST). Prior to fc2f1e54 HTTP/2 was treated the same
+  and there was no specific limit.
 
-- gssapi: align global `gss_OID_desc` vars to silence ld warnings on macOS vent
-  ura
+  According to Internet Assigned Numbers Authority (IANA) the longest
+  registered method is UPDATEREDIRECTREF which is 17 characters.
 
-  Refs #9975 which first reported this.
+  Also there are unregistered methods used by some companies that are
+  longer than 11 characters.
 
-  Closes #10718
+  The limit was originally added by 61f52a97 but not used until fc2f1e54.
 
-Daniel Stenberg (10 Mar 2023)
+  Ref: https://www.iana.org/assignments/http-methods/http-methods.xhtml
 
-- libssh2: only set the memory callbacks when debugging
+  Closes https://github.com/curl/curl/pull/12311
 
-  This makes us debug libssh2 less and libcurl more when for example
-  running torture tests that otherwise will spend a lot of time in libssh2
-  functions.
+Jay Satiro (12 Nov 2023)
 
-  We leave libssh2 to test libssh2.
+- CURLOPT_CAINFO_BLOB.3: explain what CURL_BLOB_COPY does
 
-  Closes #10721
+  - Add an explanation of the CURL_BLOB_COPY flag to CURLOPT_CAINFO_BLOB
+    and CURLOPT_PROXY_CAINFO_BLOB docs.
 
-- docs/SECURITY-PROCESS.md: updates
+  All the other _BLOB option docs already have the same explanation.
 
-  - allow Low+Medium issues to be managed through plain PRs
-  - update the bug-bounty part to reflect current reality
+  Closes https://github.com/curl/curl/pull/12277
 
-  Closes #10719
+Viktor Szakats (11 Nov 2023)
 
-Dan Fandrich (9 Mar 2023)
+- tidy-up: dedupe Windows system libs in cmake
 
-- tests: fix tag markup issues in some tests
+  Reviewed-by: Daniel Stenberg
+  Closes #12307
+
+Junho Choi (11 Nov 2023)
+
+- ci: test with latest quiche release (0.19.0)
+
+  Closes #12180
 
-Marcel Raad (9 Mar 2023)
+- quiche: use quiche_conn_peer_transport_params()
 
-- tests: add `cookies` features
+  In recent quiche, transport parameter API is separated
+  with quiche_conn_peer_transport_params().
+  (https://github.com/cloudflare/quiche/pull/1575)
+  It breaks with bulding with latest(post 0.18.0) quiche.
 
-  These tests don't work with `--disable-cookies`.
+  Closes #12180
 
-  Closes https://github.com/curl/curl/pull/10713
+Daniel Stenberg (11 Nov 2023)
 
-- test420: add cookies keyword
+- Makefile: generate the VC 14.20 project files at dist-time
 
-  It fails with `--disable-cookies`.
+  Follow-up to 28287092cc5a6d6ef8 (#12282)
 
-  Closes https://github.com/curl/curl/pull/10713
+  Closes #12290
 
-Dan Fandrich (8 Mar 2023)
+Sam James (11 Nov 2023)
 
-- CI: Add more labeler match patterns
+- misc: fix -Walloc-size warnings
+
+  GCC 14 introduces a new -Walloc-size included in -Wextra which gives:
+
+  ```
+  src/tool_operate.c: In function ‘add_per_transfer’:
+  src/tool_operate.c:213:5: warning: allocation of insufficient size ‘1’ fo
+  r type ‘struct per_transfer’ with size ‘480’ [-Walloc-size]
+    213 |   p = calloc(sizeof(struct per_transfer), 1);
+        |     ^
+  src/var.c: In function ‘addvariable’:
+  src/var.c:361:5: warning: allocation of insufficient size ‘1’ for type 
+  struct var’ with size ‘32’ [-Walloc-size]
+    361 |   p = calloc(sizeof(struct var), 1);
+        |     ^
+  ```
 
-  Also, add the  CI, tests or libcurl API tags in conjunction with any
-  others that might also apply.
+  The calloc prototype is:
+  ```
+  void *calloc(size_t nmemb, size_t size);
+      ```
 
-Andy Alt (9 Mar 2023)
+  So, just swap the number of members and size arguments to match the
+  prototype, as we're initialising 1 struct of size `sizeof(struct
+  ...)`. GCC then sees we're not doing anything wrong.
 
-- GHA: minor improvements to spellcheck
+  Closes #12292
 
-  Closes #10640
+Mark Gaiser (11 Nov 2023)
 
-Daniel Stenberg (9 Mar 2023)
+- IPFS: bugfixes
 
-- test1671: fix after fix
+  - Fixed endianness bug in gateway file parsing
+  - Use IPFS_PATH in tests where IPFS_DATA was used
+  - Fixed typos from traling -> trailing
+  - Fixed broken link in IPFS.md
 
-- test421: -w %{header_json} test with multiple same header names
+  Follow-up to 859e88f6533f9e
 
-  To reproduce the issue in #10704
+  Reported-by: Michael Kaufmann
+  Bug: https://github.com/curl/curl/pull/12152#issuecomment-1798214137
+  Closes #12305
 
-- tool_writeout_json. fix the output for duplicate header names
+Daniel Stenberg (11 Nov 2023)
 
-  Header entries with index != 0 are handled at the index 0 level so they
-  should then be skipped when iterated over.
+- VULN-DISCLOSURE-POLIC: remove broken link to hackerone
 
-  Reported-by: Boris Okunskiy
-  Fixes #10704
-  Closes #10707
+  It should ideally soon not be done from hackerone anyway
 
-- headers: make curl_easy_header and nextheader return different buffers
+  Closes #12308
 
-  By letting curl_easy_header() and curl_easy_nextheader() store the
-  header data in their own struct storage when they return a pointer to
-  it, it makes it possible for applications to use them both in a loop.
-  Like the curl tool does.
+Andrew Kurushin (11 Nov 2023)
 
-  Reported-by: Boris Okunskiy
-  Fixes #10704
-  Closes #10707
+- schannel: add CA cache support for files and memory blobs
 
-rcombs (8 Mar 2023)
+  - Support CA bundle and blob caching.
 
-- urlapi: take const args in _dup and _get functions
+  Cache timeout is 24 hours or can be set via CURLOPT_CA_CACHE_TIMEOUT.
 
-  Closes #10708
+  Closes https://github.com/curl/curl/pull/12261
 
-- urlapi: avoid mutating internals in getter routine
+Daniel Stenberg (10 Nov 2023)
 
-  This was not intended.
+- RELEASE-NOTES: synced
 
-  Closes #10708
+Charlie C (10 Nov 2023)
 
-Daniel Stenberg (8 Mar 2023)
+- cmake: option to disable install & drop `curlu` target when unused
 
-- urlapi: '%' is illegal in host names
+  This patch makes the following changes:
+  - adds the option `CURL_DISABLE_INSTALL` - to disable 'install' targets.
+  - Removes the target `curlu` when the option `BUILD_TESTING` is set to
+    `OFF` - to prevent it from being loaded in Visual Studio.
 
-  Update test 1560 to verify
+  Closes #12287
 
-  Ref: #10708
-  Closes #10711
+Kai Pastor (10 Nov 2023)
 
-- ftp: make the 'ftpauth' a more normal 'char *'-array
+- cmake: fix multiple include of CURL package
 
-  Closes #10703
+  Fixes errors on second `find_package(CURL)`. This is a frequent case
+  with transitive dependencies:
+  ```
+  CMake Error at ...:
+    add_library cannot create ALIAS target "CURL::libcurl" because another
+    target with the same name already exists.
+  ```
 
-Evgeny Grin (Karlson2k) (8 Mar 2023)
+  Test to reproduce:
+  ```cmake
+  cmake_minimum_required(VERSION 3.27)  # must be 3.18 or higher
 
-- doc: fix compiler warning in libcurl.m4
+  project(curl)
 
-  Current test for curl_free() may produce warnings with strict compiler
-  flags or even with default compiler flags with upcoming versions.
-  These warning could turned into errors by -Werror or similar flags.
-  Such warnings/errors are avoided by this patch.
+  set(CURL_DIR "example/lib/cmake/CURL/")
+  find_package(CURL CONFIG REQUIRED)
+  find_package(CURL CONFIG REQUIRED)  # fails
 
-  Closes #10710
+  add_executable(main main.c)
+  target_link_libraries(main CURL::libcurl)
+  ```
 
-Viktor Szakats (8 Mar 2023)
+  Ref: https://cmake.org/cmake/help/latest/release/3.18.html#other-changes
+  Ref: https://cmake.org/cmake/help/v3.18/policy/CMP0107.html
+  Ref: #12300
+  Assisted-by: Harry Mallon
+  Closes #11913
 
-- misc: fix typos
+Viktor Szakats (8 Nov 2023)
+
+- tidy-up: use `OPENSSL_VERSION_NUMBER`
+
+  Uniformly use `OPENSSL_VERSION_NUMBER` to check for OpenSSL version.
+  Before this patch some places used `OPENSSL_VERSION_MAJOR`.
+
+  Also fix `lib/md4.c`, which included `opensslconf.h`, but that doesn't
+  define any version number in these implementations: BoringSSL, AWS-LC,
+  LibreSSL, wolfSSL. (Only in mainline OpenSSL/quictls). Switch that to
+  `opensslv.h`. This wasn't causing a deeper problem because the code is
+  looking for v3, which is only provided by OpenSSL/quictls as of now.
+
+  According to https://github.com/openssl/openssl/issues/17517, the macro
+  `OPENSSL_VERSION_NUMBER` is safe to use and not deprecated.
+
+  Reviewed-by: Marcel Raad
+  Closes #12298
+
+Daniel Stenberg (8 Nov 2023)
+
+- resolve.d: drop a multi use-sentence
+
+  Since the `multi:` keyword adds that message.
+
+  Reported-by: 積丹尼 Dan Jacobson
+  Fixes https://github.com/curl/curl/discussions/12294
+  Closes #12295
+
+- content_encoding: make Curl_all_content_encodings allocless
+
+  - Fixes a memory leak pointed out by Coverity
+  - Also found by OSS-Fuzz: https://bugs.chromium.org/p/oss-fuzz/issues/detail?
+  id=63947
+  - Avoids unncessary allocations
+
+  Follow-up ad051e1cbec68b2456a22661b
 
-  Closes #10706
+  Closes #12289
 
-Stefan Eissing (7 Mar 2023)
+Michael Kaufmann (7 Nov 2023)
 
-- ftp: active mode with SSL, add the damn filter
+- vtls: use ALPN "http/1.1" for HTTP/1.x, including HTTP/1.0
 
-  - since 7.87.0 we lost adding the SSL filter for an active
-    FTP connection that uses SSL. This leads to hangers and timeouts
-    as reported in #10666.
+  Some servers don't support the ALPN protocol "http/1.0" (e.g. IIS 10),
+  avoid it and use "http/1.1" instead.
 
-  Reported-by: SandakovMM on github
-  Fixes #10666
-  Closes #10669
+  This reverts commit df856cb5c9 (#10183).
 
-Daniel Stenberg (7 Mar 2023)
+  Fixes #12259
+  Closes #12285
 
-- docs: extend the URL API descriptions
+Daniel Stenberg (7 Nov 2023)
 
-  Closes #10701
+- Makefile.am: drop vc10, vc11 and vc12 projects from dist
 
-Stefan Eissing (7 Mar 2023)
+  They are end of life products. Support for generating them remain in the
+  repo for a while but this change drops them from distribution.
 
-- url: fix logic in connection reuse to deny reuse on "unclean" connections
+  Closes #12288
 
-  - add parameter to `conn_is_alive()` cfilter method that returns
-    if there is input data waiting on the connection
-  - refrain from re-using connnection from the cache that have
-    input pending
-  - adapt http/2 and http/3 alive checks to digest pending input
-    to check the connection state
-  - remove check_cxn method from openssl as that was just doing
-    what the socket filter now does.
-  - add tests for connection reuse with special server configs
+David Suter (7 Nov 2023)
 
-  Closes #10690
+- projects: add VC14.20 project files
 
-Daniel Stenberg (6 Mar 2023)
+  Windows projects included VC14, VC14.10, VC14.30 but not VC14.20.
+  OpenSSL and Wolf SSL scripts mention VC14.20 so I don't see a reason why
+  this is missing. Updated the templates to produce a VC14.20 project.
+  Project opens in Visual Studio 2019 as expected.
 
-- x509asn1: use plain %x, not %lx, when the arg is an int
+  Closes #12282
 
-  Pointed out by Coverity.
+Daniel Stenberg (7 Nov 2023)
 
-  Closes #10689
+- curl: move IPFS code into src/tool_ipfs.[ch]
 
-Stefan Eissing (6 Mar 2023)
+  - convert ensure_trailing into ensure_trailing_slash
+  - strdup the URL string to own it proper
+  - use shorter variable names
+  - combine some expressions
+  - simplify error handling in ipfs_gateway()
+  - add MAX_GATEWAY_URL_LEN + proper bailout if maximum is reached
+  - ipfs-gateway.d polish and simplification
+  - shorten ipfs error message + make them "synthetic"
 
-- http2: fix handling of RST and GOAWAY to recognize partial transfers
+  Closes #12281
 
-  - a reset transfer (HTTP/2 RST) did not always lead to the proper
-    error message on receiving its response, leading to wrong reports
-    of a successful transfer
-  - test_05_02 was able to trigger this condition with increased transfer
-    count. The simulated response errors did not carry a 'Content-Length'
-    so only proper RST handling could detect the abort
-  - When doing such transfers in parallel, a connection could enter the
-    state where
-    a) it had been closed (GOAWAY received)
-    b) the RST had not been "seen" for the transfer yet
-    or c) the GOAWAY announced an error and the last successful
-    stream id was not checked against ongoing transfers
+Viktor Szakats (6 Nov 2023)
 
-  Closes #10693
+- build: delete support bits for obsolete Windows compilers
 
-- tests: use dynamic ports numbers in pytest suite
+  - Pelles C: Unclear status, failed to obtain a fresh copy a few months
+    ago. Possible website is HTTP-only. ~10 years ago I left this compiler
+    dealing with crashes and other issues with no response on the forum
+    for years. It has seen some activity in curl back in 2021.
+  - LCC: Last stable release in September 2002.
+  - Salford C: Misses winsock2 support, possibly abandoned? Last mentioned
+    in 2006.
+  - Borland C++: We dropped Borland C++ support in 2018.
+  - MS Visual C++ 6.0: Released in 1998. curl already requires VS 2010
+    (or possibly 2008) as a minimum.
 
-  - necessary ports are bound at start of test suite and then
-    given to server fixtures for use.
-  - this make parallel use of pytest (in separate directories),
-    practically safe for use as OS tend to not reuse such port numbers
-    for a while
+  Closes #12222
 
-  Closes #10692
+- build: delete `HAVE_STDINT_H` and `HAVE_INTTYPES_H`
 
-- connect: fix time_connect and time_appconnect timer statistics
+  We use `stdint.h` unconditionally in all places except one. These uses
+  are imposed by external dependencies / features. nghttp2, quic, wolfSSL
+  and `HAVE_MACH_ABSOLUTE_TIME` do require this C99 header. It means that
+  any of these features make curl require a C99 compiler. (In case of
+  MSVC, this means Visual Studio 2010 or newer.)
 
-  - time_connect was not updated when the overall connection failed,
-    e.g. when SSL verification was unsuccessful, refs #10670
-  - rework gather those values to interrogate involved filters,
-    also from all eyeballing attempts, to report the maximum of
-    those values.
-  - added 3 test cases in test_06 to check reported values on
-    successful, partially failed and totally failed connections.
+  This patch changes the single use of `stdint.h` guarded by
+  `HAVE_STDINT_H` to use `stdint.h` unconditionally. Also stop using
+  `inttypes.h` as an alternative there. `HAVE_INTTYPES_H` wasn't used
+  anywhere else, allowing to delete this feature check as well.
 
-  Reported-by: Master Inspire
-  Fixes #10670
-  Closes #10671
+  Closes #12275
 
-Daniel Stenberg (6 Mar 2023)
+Daniel Stenberg (6 Nov 2023)
 
-- test1905: update output cookie order
+- tool_operate: do not mix memory models
 
-  After the #10685 update
+  Make sure 'inputpath' only points to memory allocated by libcurl so that
+  curl_free works correctly.
 
-- test420: verify expiring cookies
+  Pointed out by Coverity
+
+  Follow-up to 859e88f6533f9e1f890
+
+  Closes #12280
+
+Stefan Eissing (6 Nov 2023)
+
+- lib: client writer, part 2, accounting + logging
+
+  This PR has these changes:
+
+  Renaming of unencode_* to cwriter, e.g. client writers
+  - documentation of sendf.h functions
+  - move max decode stack checks back to content_encoding.c
+  - define writer phase which was used as order before
+  - introduce phases for monitoring inbetween decode phases
+  - offering default implementations for init/write/close
+
+  Add type paramter to client writer's do_write()
+  - always pass all writes through the writer stack
+  - writers who only care about BODY data will pass other writes unchanged
+
+  add RAW and PROTOCOL client writers
+  - RAW used for Curl_debug() logging of CURLINFO_DATA_IN
+  - PROTOCOL used for updates to data->req.bytecount, max_filesize checks and
+    Curl_pgrsSetDownloadCounter()
+  - remove all updates of data->req.bytecount and calls to
+    Curl_pgrsSetDownloadCounter() and Curl_debug() from other code
+  - adjust test457 expected output to no longer see the excess write
+
+  Closes #12184
+
+Daniel Stenberg (6 Nov 2023)
+
+- VULN-DISCLOSURE-POLICY: escape sequences are not a security flaw
+
+  Closes #12278
+
+Viktor Szakats (6 Nov 2023)
 
-  Cookies that are loaded fine from a jar but then are expired in headers.
+- rand: fix build error with autotools + LibreSSL
 
-- cookie: don't load cookies again when flushing
+  autotools unexpectedly detects `arc4random` because it is also looking
+  into dependency libs. One dependency, LibreSSL, happens to publish an
+  `arc4random` function (via its shared lib before v3.7, also via static
+  lib as of v3.8.2). When trying to use this function in `lib/rand.c`,
+  its protoype is missing. To fix that, curl included a prototype, but
+  that used a C99 type without including `stdint.h`, causing:
 
-  Reported-by: Sergio Mijatovic
-  Fixes #10677
-  Closes #10685
+  ```
+  ../../lib/rand.c:37:1: error: unknown type name 'uint32_t'
+     37 | uint32_t arc4random(void);
+        | ^
+  1 error generated.
+  ```
+
+  This patch improves this by dropping the local prototype and instead
+  limiting `arc4random` use for non-OpenSSL builds. OpenSSL builds provide
+  their own random source anyway.
+
+  The better fix would be to teach autotools to not link dependency libs
+  while detecting `arc4random`.
+
+  LibreSSL publishing a non-namespaced `arc4random` tracked here:
+  https://github.com/libressl/portable/issues/928
+
+  Regression from 755ddbe901cd0c921fbc3ac5b3775c0dc683bc73 #10672
+
+  Reviewed-by: Daniel Stenberg
+  Fixes #12257
+  Closes #12274
+
+Daniel Stenberg (5 Nov 2023)
 
 - RELEASE-NOTES: synced
 
-Andy Alt (6 Mar 2023)
+- strdup: do Curl_strndup without strncpy
+
+  To avoid (false positive) gcc-13 compiler warnings.
+
+  Follow-up to 4855debd8a2c1cb
+
+  Assisted-by: Jay Satiro
+  Reported-by: Viktor Szakats
+  Fixes #12258
+
+Enno Boland (5 Nov 2023)
+
+- HTTP: fix empty-body warning
+
+  This change fixes a compiler warning with gcc-12.2.0 when
+  `-DCURL_DISABLE_BEARER_AUTH=ON` is used.
+
+      /home/tox/src/curl/lib/http.c: In function 'Curl_http_input_auth':
+      /home/tox/src/curl/lib/http.c:1147:12: warning: suggest braces around emp
+  ty body in an 'else' statement [-Wempty-body]
+       1147 |            ;
+            |            ^
+
+  Closes #12262
+
+Daniel Stenberg (5 Nov 2023)
+
+- openssl: identify the "quictls" backend correctly
+
+  Since vanilla OpenSSL does not support the QUIC API I think it helps
+  users to identify the correct OpenSSL fork in version output. The best
+  (crude) way to do that right now seems to be to check if ngtcp2 support
+  is enabled.
+
+  Closes #12270
+
+Mark Gaiser (5 Nov 2023)
+
+- curl: improved IPFS and IPNS URL support
+
+  Previously just ipfs:// and ipns:// was supported, which is
+  too strict for some usecases.
+
+  This patch allows paths and query arguments to be used too.
+  Making this work according to normal http semantics:
+
+   ipfs:///foo/bar?key=val
+   ipns:///foo/bar?key=val
 
-- docs: note '--data-urlencode' option
+  The gateway url support is changed.
+  It now only supports gateways in the form of:
 
-  Closes #10687
+   http:///foo/bar
+   http://
 
-Daniel Stenberg (6 Mar 2023)
+  Query arguments here are explicitly not allowed and trigger an intended
+  malformed url error.
 
-- DEPRECATE: the original legacy mingw version 1
+  There also was a crash when IPFS_PATH was set with a non trailing
+  forward slash. This has been fixed.
 
-  Remove completely in September 2023
+  Lastly, a load of test cases have been added to verify the above.
 
-  Closes #10667
+  Reported-by: Steven Allen
+  Fixes #12148
+  Closes #12152
+
+Harry Mallon (5 Nov 2023)
+
+- docs: KNOWN_BUGS cleanup
+
+  * Remove other mention of hyper memory-leaks from `KNOWN_BUGS`.
+    Should have been removed in 629723ecf22a8eae78d64cceec2f3bdae703ec95
+
+  * Remove mention of aws-sigv4 sort query string from `KNOWN_BUGS`.
+    Fixed in #11806
+
+  * Remove mention of aws-sigv4 query empty value problems
+
+  * Remove mention of aws-sigv4 missing amz-content-sha256
+    Fixed in #9995
+
+- http_aws_sigv4: canonicalise valueless query params
+
+  Fixes #8107
+  Closes #12244
+
+Michael Kaufmann (4 Nov 2023)
+
+- docs: preserve the modification date when copying the prebuilt man page
+
+  The previously built man page "curl.1" must be copied with the original
+  modification date, otherwise the man page is never updated.
+
+  This fixes a bug that has been introduced with commit 2568441cab.
+
+  Reviewed-by: Dan Fandrich
+  Reviewed-by: Daniel Stenberg
 
-Harry Sintonen (6 Mar 2023)
+  Closes #12199
 
-- rand: use arc4random as fallback when available
+Daniel Stenberg (4 Nov 2023)
 
-  Normally curl uses cryptographically strong random provided by the
-  selected SSL backend. If compiled without SSL support, a naive built-in
-  function was used instead.
+- docs: remove bold from some man page SYNOPSIS sections
 
-  Generally this was okay, but it will result in some downsides for non-
-  SSL builds, such as predictable temporary file names.
+  In the name of consistency
 
-  This change ensures that arc4random will be used instead, if available.
+  Closes #12267
 
-  Closes #10672
+- openssl: two multi pointer checks should probably rather be asserts
 
-Grisha Levit (6 Mar 2023)
+  ... so add the asserts now and consider removing the dynamic checks in a
+  future.
 
-- tool: dump headers even if file is write-only
+  Ref: #12261
+  Closes #12264
 
-  The fixes in #10079 brought a (seemingly unrelated) change of open mode
-  from `wb`/`ab` to `wb+`/`ab+` for the headerfile. This makes it no
-  longer possible to write the header file to e.g. a pipe, like:
+boilingoden (4 Nov 2023)
 
-      curl -D >(grep ...) file:///dev/null
+- docs: add supported version for the json write-out
 
-  Which presently results in `Warning: Failed to open /dev/fd/63`
+  xref: https://curl.se/changes.html#7_70_0
 
-  See #10079
-  Closes #10675
+  Closes #12266
diff --git a/vendor/curl/COPYING b/vendor/curl/COPYING
index d1eab3eb93..d9e7e0bef3 100644
--- a/vendor/curl/COPYING
+++ b/vendor/curl/COPYING
@@ -1,6 +1,6 @@
 COPYRIGHT AND PERMISSION NOTICE
 
-Copyright (c) 1996 - 2023, Daniel Stenberg, , and many
+Copyright (c) 1996 - 2024, Daniel Stenberg, , and many
 contributors, see the THANKS file.
 
 All rights reserved.
diff --git a/vendor/curl/RELEASE-NOTES b/vendor/curl/RELEASE-NOTES
index 0fc352c458..a48c8efc9c 100644
--- a/vendor/curl/RELEASE-NOTES
+++ b/vendor/curl/RELEASE-NOTES
@@ -1,199 +1,244 @@
-curl and libcurl 8.3.0
+curl and libcurl 8.8.0
 
- Public curl releases:         251
- Command line options:         257
- curl_easy_setopt() options:   303
- Public functions in libcurl:  92
- Contributors:                 2977
+ Public curl releases:         257
+ Command line options:         259
+ curl_easy_setopt() options:   305
+ Public functions in libcurl:  94
+ Contributors:                 3173
 
 This release includes the following changes:
 
- o curl: make %output{} in -w specify a file to write to [36]
- o gskit: remove [71]
- o lib: --disable-bindlocal builds curl without local binding support
- o nss: remove support for this TLS library [10]
- o tool: add "variable" support [1]
- o trace: make tracing available in non-debug builds [41]
- o url: change default value for CURLOPT_MAXREDIRS to 30 [46]
- o urlapi: CURLU_PUNY2IDN - convert from punycode to IDN name [54]
- o wolfssl: support loading system CA certificates [8]
+ o curl_version_info: provide librtmp version [73]
+ o file: add support for directory listings [63]
+ o idn: add native AppleIDN (icucore) support for macOS/iOS [95]
+ o lib: add curl_multi_waitfds [34]
+ o mbedTLS: implement CURLOPT_SSL_CIPHER_LIST option [103]
+ o NTLM_WB: drop support [67]
+ o TLS: add support for ECH (Encrypted Client Hello) [109]
+ o urlapi: add CURLU_GET_EMPTY for empty queries and fragments [111]
 
 This release includes the following bugfixes:
 
- o altsvc: accept and parse IPv6 addresses in response headers [113]
- o asyn-ares: reduce timeout to 2000ms [148]
- o aws-sigv4: canonicalize the query [127]
- o aws-sigv4: fix having date header twice in some cases [141]
- o aws-sigv4: handle no-value user header entries [159]
- o bearssl: don't load CA certs when peer verification is disabled [33]
- o bearssl: handshake fix, provide proper get_select_socks() implementation [99]
- o build: fix portability of mancheck and checksrc targets
- o build: streamline non-UWP wincrypt detections [87]
- o c-hyper: adjust the hyper to curlcode conversion [52]
- o c-hyper: fix memory leaks in `Curl_http` [126]
- o cf-haproxy: make CURLOPT_HAPROXY_CLIENT_IP set the *source* IP [61]
- o cf-socket: log successful interface bind [39]
- o CI/cirrus: disable python install on FreeBSD [83]
- o CI: add a 32-bit i686 Linux build [158]
- o CI: add caching to many jobs [19]
- o CI: move on to ngtcp2 v0.19.1 [154]
- o CI: move the Alpine build from Cirrus to GHA
- o CI: ngtcp2-linux: use separate caches for tls libraries [125]
- o CI: remove Windows builds from Cirrus, without replacement [131]
- o CI: switch macOS ARM build from Cirrus to Circle CI
- o CI: use master again for wolfssl
- o cirrus: install everthing with pkg, avoid pip [110]
- o cmake: add GnuTLS option [103]
- o cmake: add support for `CURL_DEFAULT_SSL_BACKEND` [128]
- o cmake: add support for single libcurl compilation pass [21]
- o cmake: allow `SHARE_LIB_OBJECT=ON` on all platforms [80]
- o cmake: assume `wldap32` availability on Windows [81]
- o cmake: cache more config and delete unused ones [4]
- o cmake: detect `SSL_set0_wbio` in OpenSSL [22]
- o cmake: drop `HAVE_LIBWINMM` and `HAVE_LIBWS2_32` feature checks [68]
- o cmake: fix to use variable for the curl namespace [79]
- o cmake: fixup H2 duplicate symbols for unity builds [23]
- o cmake: set SIZEOF_LONG_LONG in curl_config.h [165]
- o cmake: support building static and shared libcurl in one go [17]
- o cmdline-docs: make sure to phrase it as "added in ...." [161]
- o cmdline-docs: use present tense, not future [160]
- o cmdline-opts/docs: mention the negative option part [90]
- o cmdline-opts/page-header: clarify stronger that !opt == URL [123]
- o cmdline-opts/page-header: reorder, clean up [51]
- o configure, cmake, lib: more form api deprecation [7]
- o configure: fix `HAVE_TIME_T_UNSIGNED` check [153]
- o configure: trust pkg-config when it's used for zlib [149]
- o configure: use the pkg-config --libs-only-l flag for libssh2 [16]
- o connect: stop halving the remaining timeout when less than 600 ms left [147]
- o cookie-jar.d: emphasize that this option is ONLY writing cookies [72]
- o crypto: ensure crypto initialization works [69]
- o curl_url_get/set.3: add missing semicolon in SYNOPSIS
- o CURLINFO_CERTINFO.3: better explain curl_certinfo struct [64]
- o CURLINFO_TLS_SSL_PTR.3: clarify a recommendation [75]
- o CURLOPT_*TIMEOUT*: extend and clarify [101]
- o CURLOPT_SSL_VERIFYPEER.3: mention it does not load CA certs when disabled [42]
- o CURLOPT_URL.3: add two URL API calls in the see-also section
- o CURLOPT_URL.3: explain curl_url_set() uses the same parser
- o digest: Use hostname to generate spn instead of realm [164]
- o disable.d: explain --disable not implemented prior to 7.50.0 [115]
- o docs/cmdline-opts/gen.pl: hide "added in" before 7.50.0 [76]
- o docs/cmdline-opts: match the current output [104]
- o docs/cmdline-opts: spellfixes, typos and polish [9]
- o docs/cmdline: add small "warning" to verbose options [59]
- o docs/cmdline: remove repeated working for negotiate + ntlm [58]
- o docs/HYPER.md: document a workaround for a link error [73]
- o docs: add curl_global_trace to some SEE ALSO sections [133]
- o docs: link to the website versions instead of markdowns [3]
- o docs: mark --ssl-revoke-best-effort as Schannel specific [162]
- o docs: mention critical files in same directories as curl saves [119]
- o docs: removing "pausing transfers" from HYPER.md. [134]
- o docs: rewrite to present tense [105]
- o easy: remove #ifdefs to make code easier on the eye [34]
- o egd: delete feature detection and related source code [5]
- o ftp: fix temp write of ipv6 address [143]
- o gen.pl: escape all dashes (ascii minus) to avoid unicode hyphens [50]
- o gen.pl: replace all single quotes with aq [78]
- o GHA: adding quiche workflow [35]
- o headers: accept leading whitespaces on first response header [37]
- o http2: avoid too early connection re-use/multiplexing [20]
- o http2: cleanup trace messages [56]
- o http2: disable asssertion blocking OSSFuzz testing [31]
- o http2: fix in h2 proxy tunnel: progress in ingress on sending [32]
- o http2: polish things around POST [132]
- o http2: upgrade tests and add fix for non-existing stream [44]
- o http3/ngtcp2: shorten handshake, trace cleanup [13]
- o http3: quiche, handshake optimization, trace cleanup [63]
- o http: close the connection after a late 417 is received [109]
- o http: do not require a user name when using CURLAUTH_NEGOTIATE [86]
- o http: fix sending of large requests [156]
- o http: remove the p_pragma struct field [60]
- o http: return error when receiving too large header set [43]
- o hyper: fix a progress upload counter bug [122]
- o hyper: fix ownership problems [116]
- o hyper: remove `hyptransfer->endtask` [137]
- o imap: add a check for failing strdup()
- o imap: remove the only sscanf() call in the IMAP code [84]
- o include.d: explain headers not printed with --fail before 7.75.0 [155]
- o include/curl/mprintf.h: add __attribute__ for the prototypes [38]
- o krb5: fix "implicit conversion loses integer precision" warnings [152]
- o lib: add ability to disable auths individually [135]
- o lib: build fixups when built with most things disabled [97]
- o lib: fix a few *printf() flag mistakes [47]
- o lib: fix null ptr derefs and uninitialized vars (h2/h3) [107]
- o lib: move mimepost data from ->req.p.http to ->state [94]
- o libtest: use curl_free() to free libcurl allocated data [114]
- o list-only.d: mention SFTP as supported protocol [55]
- o macOS: fix target detection more [11]
- o misc: fix various typos [18]
- o multi.h: the 'revents' field of curl_waitfd is supported [117]
- o multi: more efficient pollfd count for poll [130]
- o multi: remove 'processing: ' debug message [142]
- o ngtcp2: fix handling of large requests [150]
- o openssl: auto-detect `SSL_R_TLSV13_ALERT_CERTIFICATE_REQUIRED` [65]
- o openssl: clear error queue after SSL_shutdown [120]
- o openssl: make aws-lc version support OCSP [48]
- o openssl: Support async cert verify callback [24]
- o openssl: switch to modern init for LibreSSL 2.7.0+ [70]
- o openssl: use `SSL_CTX_set_ciphersuites` with LibreSSL 3.4.1 [66]
- o openssl: use `SSL_CTX_set_keylog_callback` with LibreSSL 3.5.0 [67]
- o openssl: when CURLOPT_SSL_CTX_FUNCTION is registered, init x509 store before [151]
- o os400: build test servers [136]
- o os400: do not check translatable options at build time [95]
- o os400: implement CLI tool [140]
- o page-footer: QLOGDIR works with ngtcp2 and quiche [62]
- o page-header: move up a URL paragraph from GLOBBING to URL
- o pytest: fix check for slow_network skips to only apply when intended [157]
- o quic: don't set SNI if hostname is an IP address [166]
- o quiche: adjust quiche `QUIC_IDLE_TIMEOUT` to 60s
- o quiche: enable quiche to handle timeout events [82]
- o resolve: use PF_INET6 family lookups when CURL_IPRESOLVE_V6 is set [2]
- o revert "schannel: reverse the order of certinfo insertions" [14]
- o schannel: fix ordering of cert chain info [163]
- o schannel: fix user-set legacy algorithms in Windows 10 & 11 [53]
- o schannel: verify hostname independent of verify cert [74]
- o sectransp: fix compiler warnings [129]
- o sectransp: prevent CFRelease() of NULL [26]
- o secureserver.pl: fix stunnel path quoting [112]
- o secureserver.pl: fix stunnel version parsing [111]
- o SECURITY-PROCESS.md: not a sec issue: Tricking user to run a cmdline [146]
- o system.h: add CURL_OFF_T definitions on HP-UX with HP aCC [108]
- o test1304: build and skip without netrc support
- o test1554: check translatable string options in OS400 wrapper [96]
- o test1608: make it build and get skipped without shuffle DNS support
- o test687/688: two more basic --xattr tests [89]
- o tests/tftpd+mqttd: make variables static to silence picky warnings [57]
- o tests: add 'large-time' as a testable feature [92]
- o tests: add support for nested %if conditions [91]
- o tests: don't call HTTP errors OK in test cases
- o tests: ensure `libcurl.def` contains all exports [45]
- o tests: fix h3 server check and parallel instances [6]
- o tests: TLS session sharing test [100]
- o tests: update cookie expiry dates to far in the future [121]
- o time-cond.d: mention what happens on a missing file [93]
- o tool: avoid including leading spaces in the Location hyperlink [145]
- o tool: change some fopen failures from warnings to errors [144]
- o tool: make the length argument an int for printf()-.* flags [49]
- o tool_cb_wrt: fix invalid unicode for windows console [25]
- o tool_filetime: make -z work with file dates before 1970 [139]
- o tool_operate: allow both SSL_CERT_FILE and SSL_CERT_DIR [12]
- o tool_operate: make aws-sigv4 not require TLS to be used
- o tool_paramhlp: improve str2num(): avoid unnecessary call to strlen() [118]
- o tool_urlglob: use the correct format specifier for curl_off_t in msnprintf [88]
- o transfer: also stop the sending on closed connection [124]
- o transfer: don't set TIMER_STARTTRANSFER on first send [77]
- o unit2600: fix build warning if built without verbose messages
- o url: remove infof() output for "still name resolving" [28]
- o urlapi: fix heap buffer overflow [30]
- o urlapi: make sure zoneid is also duplicated in curl_url_dup [29]
- o urlapi: return CURLUE_BAD_HOSTNAME if puny2idn encoding fails [102]
- o urlapi: setting a blank URL ("") is not an ok URL [106]
- o vquic: show stringified messages for errno [40]
- o vtls: clarify "ALPN: offers" message [27]
- o winbuild: improve check for static zlib [15]
- o wolfSSL: avoid the OpenSSL compat API when not needed [85]
- o workflows/macos.yml: disable zstd and alt-svc in the http-only build [98]
- o write-out.d: clarify %{time_starttransfer}
- o ws: fix spelling mistakes in examples and tests [138]
+ o appveyor: drop unnecessary `--clean-first` cmake option [197]
+ o appveyor: guard against crash-build with VS2008 [193]
+ o appveyor: make gcc 6 mingw64 job build-only [152]
+ o asyn-thread: fix curl_global_cleanup crash in Windows [161]
+ o asyn-thread: fix Curl_thread_create result check [162]
+ o autotools: delete unused functions [177]
+ o autotools: fix `HAVE_IOCTLSOCKET_FIONBIO` test for gcc 14 [186]
+ o autotools: only probe for SGI MIPS compilers on IRIX [213]
+ o bearssl: fix compiler warnings [43]
+ o bearssl: use common code for cipher suite lookup [126]
+ o bufq: remove duplicate word in comment [154]
+ o BUG-BOUNTY.md: clarify the third party situation [210]
+ o build: prefer `USE_IPV6` macro internally (was: `ENABLE_IPV6`) [85]
+ o build: remove MacOSX-Framework script [60]
+ o cd2nroff/manage: use UTC when SOURCE_DATE_EPOCH is set [36]
+ o cf-https-connect: use timeouts as unsigned ints [143]
+ o cf-socket: don't try getting local IP without socket [188]
+ o cf-socket: remove references to l_ip, l_port [9]
+ o ci: add curl-for-win builds: Linux MUSL, macOS, Windows [68]
+ o cmake: add `BUILD_EXAMPLES` option to build examples [128]
+ o cmake: add librtmp/rtmpdump option and detection [108]
+ o cmake: check fseeko after detecting HAVE_FILE_OFFSET_BITS [64]
+ o cmake: do not pass linker flags to the static library tool [203]
+ o cmake: enable `-pedantic-errors` for clang when `CURL_WERROR=ON` [47]
+ o cmake: FindNGHTTP2 add static lib name to find_library call [141]
+ o cmake: fix `CURL_WERROR=ON` for old CMake and use it in GHA/linux-old [48]
+ o cmake: fix `HAVE_IOCTLSOCKET_FIONBIO` test with gcc 14 [179]
+ o cmake: fixup `DEPENDS` filename [51]
+ o cmake: forward `USE_LIBRTMP` option to C [59]
+ o cmake: generate misc manpages and install `mk-ca-bundle.pl` [24]
+ o cmake: initialize `BUILD_TESTING` before first use [227]
+ o cmake: speed up libcurl doc building again [15]
+ o cmake: tidy-up to use `WORKING_DIRECTORY` [23]
+ o cmake: use namespaced custom target names [80]
+ o cmdline-docs: fix make install with configure --disable-docs [1]
+ o configure: error on missing perl if docs or manual is enabled [135]
+ o configure: make --disable-docs imply --disable-manual [2]
+ o content_encoding: brotli and others, pass through 0-length writes [5]
+ o content_encoding: ignore duplicate chunked encoding [137]
+ o content_encoding: reject transfer-encoding after chunked [200]
+ o contrithanks: honor `CURLWWW` variable [69]
+ o curl-confopts.m4: define CARES_NO_DEPRECATED when c-ares is used [17]
+ o curl.h: change CURL_SSLVERSION_* from enum to defines [132]
+ o curl: make --help adapt to the terminal width [11]
+ o curl: use curl_getenv instead of the curlx_ version [20]
+ o Curl_creader_read: init two variables to avoid using them uninited [99]
+ o curl_easy_pause.md: use correct defines in example [187]
+ o curl_getdate.md: document two-digit year handling [127]
+ o curl_global_trace.md: shorten the description [29]
+ o curl_multibyte: remove access() function wrapper for Windows [163]
+ o curl_path: make Curl_get_pathname use dynbuf [158]
+ o curl_setup.h: add support for IAR compiler [191]
+ o curl_setup.h: detect 'inline' support [133]
+ o curl_sha512_256: do not use workaround for NetBSD when not needed [21]
+ o curl_sha512_256: fix detection of OpenSSL 1.1.1 or later [8]
+ o curl_url_get.md: clarify queries and fragments and CURLU_GET_EMPTY [105]
+ o CURLINFO_REQUEST_SIZE: fixed, add tests for transfer infos reported [52]
+ o CURLOPT_WRITEFUNCTION.md: fix the callback proto in the example [215]
+ o cw-out: improved error handling [104]
+ o DEPRECATE.md: TLS libraries without 1.3 support [199]
+ o digest: replace strcpy for empty string with simple assignment [185]
+ o dist: `set -eu`, fix shellcheck, make reproducible and smaller tarballs [38]
+ o dist: add files missing from release tarball [53]
+ o dist: add reproducible dir entries to tarballs [56]
+ o dist: do not require Perl in `maketgz` [71]
+ o dist: remove the curl-config.1 from the tarball [28]
+ o dist: verify tarball reproducibility in CI [40]
+ o DISTROS: add patch and issues link for curl-for-win [110]
+ o DISTROS: Cygwin updates [44]
+ o dllmain: Call OpenSSL thread cleanup for Windows and Cygwin [114]
+ o doc: pytest `--repeat` -> `--count` [58]
+ o docs/cmdline-opts: invoke managen using a relative path [30]
+ o docs/cmdline-opts: mention STARTTLS for --ssl and --ssl-reqd [175]
+ o docs: add CURLOPT_NOPROGRESS to CURLOPT_XFERINFOFUNCTION example [61]
+ o docs: clarify CURLOPT_MAXFILESIZE and CURLOPT_MAXFILESIZE_LARGE [74]
+ o docs: fix some CURLINFO examples [147]
+ o doh: fix typo in comment [173]
+ o doh: remove unused function prototype [169]
+ o dynbuf: fix returncode on memory error [174]
+ o examples: fix/silence `-Wsign-conversion` [178]
+ o EXPERIMENTAL: add graduation requirements for each feature [166]
+ o file: remove useless assignment [89]
+ o ftp: add tracing support [181]
+ o ftp: fix build for CURL_DISABLE_VERBOSE_STRINGS
+ o ftp: fix socket leak on rare error [102]
+ o GHA: add NetBSD, OpenBSD, FreeBSD/arm64 and OmniOS jobs [201]
+ o GHA: add shellcheck job and fix warnings, shell tidy-ups [70]
+ o GHA: add valgrind to a wolfSSL build [37]
+ o GHA: on macOS remove $HOME/.curlrc [50]
+ o GHA: pin dependencies [194]
+ o gnutls: lazy init the trust settings [75]
+ o h3/ngtcp2: improve error handling [140]
+ o hash: change 'slots' to size_t from int [144]
+ o hash: delete unused debug function [198]
+ o hsts: explicitly skip blank lines [212]
+ o hsts: remove single-use single-line function [151]
+ o http tests: in CI skip test_02_23* for quiche [211]
+ o http2 + ngtcp2: pass CURLcode errors from callbacks [94]
+ o http2, http3: decouple stream state from easy handle [92]
+ o http2: emit RST when client write fails [65]
+ o http3: quiche+ngtcp2 improvements [129]
+ o http: acknowledge a returned error code [123]
+ o http: HEAD response body tolerance [170]
+ o http: reject HTTP major version switch mid connection [100]
+ o http: remove redundant check [182]
+ o http: with chunked POST forced, disable length check on read callback [31]
+ o http_aws_sigv4: remove useless assignment [88]
+ o idn: make Curl_idnconvert_hostname() use Curl_idn_decode() [16]
+ o if2ip: make the buf_size arg a size_t [142]
+ o INSTALL-CMAKE.md: explain `cmake -G ` [32]
+ o krb5: use dynbuf [149]
+ o ldap: fix unused variables (seen on OmniOS) [183]
+ o lib/cf-h1-proxy: silence compiler warnings (gcc 14) [155]
+ o lib: add trace support for client reads and writes [45]
+ o lib: bump hash sizes to `size_t` [153]
+ o lib: clear the easy handle's saved errno before transfer [180]
+ o lib: fix compiler warnings (gcc) [222]
+ o lib: make protocol handlers store scheme name lowercase [159]
+ o lib: merge `ENABLE_QUIC` C macro into `USE_HTTP3` [84]
+ o lib: remove two instances of "only only" messages [160]
+ o lib: silence `-Wsign-conversion` in base64, strcase, mprintf [139]
+ o lib: silence warnings on comma misuse [91]
+ o lib: use `#error` instead of invalid syntax in `curl_setup_once.h` [49]
+ o lib: use multi instead of multi_easy for the active multi [41]
+ o libcurl-opts: mention pipelining less [33]
+ o libssh2: delete redundant feature guard [171]
+ o libssh2: replace `access()` with `stat()` [145]
+ o libssh2: set length to 0 if strdup failed [6]
+ o m4: fix rustls pkg-config codepath [22]
+ o MAIL-ETIQUETTE: convert to markdown [12]
+ o makefile: remove the sorting from the vc-ide action [42]
+ o maketgz: put docs/RELEASE-TOOL.md into the tarball [35]
+ o managen: fix the option sort order [150]
+ o mbedtls: call mbedtls_ssl_setup() after RNG callback is set [66]
+ o mbedtls: cut off trailing newlines from debug logs [87]
+ o mbedtls: fix building with v3 in CMake Unity mode [107]
+ o mbedtls: support TLS 1.3 [156]
+ o mime: avoid using access() [125]
+ o misc: fix typos [62]
+ o misc: fix typos, quoting and spelling [167]
+ o mprintf: check fputc error rather than matching returned character [82]
+ o mqtt: when Curl_xfer_recv returns error, don't use nread [101]
+ o multi: avoid memory-leak risk [134]
+ o multi: introduce SETUP state for better timeouts [26]
+ o multi: multi_wait improvements [131]
+ o multi: remove the unused Curl_preconnect function [98]
+ o multi: remove useless assignment [146]
+ o multi: timeout handles even without connection [81]
+ o openldap: create ldap URLs correctly for IPv6 addresses [19]
+ o openssl: do not set SSL_MODE_RELEASE_BUFFERS [10]
+ o openssl: revert keylog_callback support for LibreSSL [192]
+ o OS400: fix shellcheck warnings in scripts [72]
+ o projects: drop MSVC project files for recent versions [79]
+ o pytest: add DELETE tests, check server version [225]
+ o pytest: fixes for recent python, add FTP tests [206]
+ o quic: fixup duplicate static function name (for cmake unity) [77]
+ o quiche: expire all active transfers on connection close [116]
+ o quiche: trust its timeout handling [190]
+ o RELEASE-PROCEDURE: mention an initial working build [7]
+ o request: make Curl_req_init return void [96]
+ o request: paused upload on completed download, assess connection [54]
+ o reuse: add copyright + license info to individual docs/*.md files [13]
+ o ROADMAP: remove completed entries, mention websocket
+ o rustls: fix handshake done handling [207]
+ o rustls: fix partial send handling [224]
+ o rustls: remove incorrect SSLSUPP_TLS13_CIPHERSUITES flag [115]
+ o rustsls: fix error code on receive [230]
+ o sendf: fix two typos in comments [90]
+ o sendf: useless assignment in cr_lc_read() [120]
+ o setopt: acknowledge errors proper for CURLOPT_COOKIEJAR [216]
+ o setopt: make the setstropt_userpwd args compulsory [221]
+ o setopt: remove check for 'option' that is always true [219]
+ o setopt: warn on Curl_set*opt() uses not using the return value [176]
+ o smtp: result of Curl_bufq_cread was not used [78]
+ o socket: remove redundant call to getsockname [195]
+ o socketpair: fix compilation when USE_UNIX_SOCKETS is not defined [229]
+ o src: tidy up types, add necessary casts [217]
+ o telnet: check return code from fileno() [112]
+ o tests/http: fix compiler warning [39]
+ o tests: add -q as first option when invoking curl for tests [97]
+ o tests: check caddy server version to match test expectations [106]
+ o tests: enable test 1117 for hyper [119]
+ o tests: fix feature case in test1481 [117]
+ o tests: fix test 1167 to skip digit-only symbols [214]
+ o tests: make the unit test result type `CURLcode` [165]
+ o tests: Mark tftpd timer function as noreturn [168]
+ o tests: tidy up types in server code [220]
+ o tls: fix SecureTransport + BearSSL cmake unity builds [113]
+ o tls: remove EXAMPLEs from deprecated options [164]
+ o tls: use shared init code for TCP+QUIC [57]
+ o tool: move tool_ftruncate64 to tool_util.c [138]
+ o tool_cb_rea: limit rate unpause for -T . uploads [136]
+ o tool_cfgable: free {proxy_}cipher13_list on exit [172]
+ o tool_getparam: output warning for leading unicode quote character [14]
+ o tool_getparam: remove two redundant conditions [189]
+ o tool_operate: don't truncate the etag save file by default [118]
+ o tool_operate: init vars unconditionally in post_per_transfer [124]
+ o tool_paramhlp: remove duplicate assign [121]
+ o tool_xattr: "guess" URL scheme if none is provided [3]
+ o tool_xattr: in debug builds, act normally if CURL_FAKE_XATTR is not set [4]
+ o transfer: remove useless assignment [122]
+ o url: do not URL decode proxy crendentials [55]
+ o url: fix use of an uninitialized variable [86]
+ o url: make parse_login_details use memdup0 [184]
+ o url: remove duplicate call to Curl_conncache_remove_conn when pruning [196]
+ o urlapi: allow setting port number zero [76]
+ o urlapi: fix relative redirects to fragment-only [83]
+ o urldata: remove fields not used depending on used features [46]
+ o vauth: make two functions void that always just returned OK [218]
+ o version: use msnprintf instead of strncpy [157]
+ o vquic-tls: use correct cert name check API for wolfSSL [226]
+ o vquic: use CURL_FORMAT_CURL_OFF_T for 64 bit printf output [18]
+ o vtls: TLS session storage overhaul [130]
+ o wakeup_create: use FD_CLOEXEC/SOCK_CLOEXEC [223]
+ o warnless: delete orphan declarations [209]
+ o websocket: avoid memory leak in error path [148]
+ o winbuild: add ENABLE_WEBSOCKETS option [93]
+ o winbuild: use $(RC) correctly [27]
+ o wolfssl: plug memory leak in wolfssl_connect_step2() [25]
+ o x509asn1: return error on missing OID [208]
 
 This release includes the following known bugs:
 
@@ -202,200 +247,259 @@ This release includes the following known bugs:
 Planned upcoming removals include:
 
  o support for space-separated NOPROXY patterns
- o support for the original legacy mingw version 1
 
  See https://curl.se/dev/deprecate.html for details
 
 This release would not have looked like this without help, code, reports and
 advice from friends like these:
 
-  ad0p on github, Alexander Jaeger, Alexander Kanavin, apparentorder on github,
-  balikalina on Github, Benoit Pierre, Chris Talbot, Christian Hesse,
-  Dan Fandrich, Daniel Gustafsson, Daniel Stenberg, Dan Jacobson,
-  Dave Cottlehuber, Davide Masserut, Derzsi Dániel, Douglas R. Reno,
-  ed0d2b2ce19451f2, Emanuele Torre, Enrico Scholz, eppesuig, FC Stegerman,
-  Gabriel Corona, Gerome Fournier, Gisle Vanem, Goro FUJI, Graham Campbell,
-  Guillaume Algis, guoxinvmware on github, Harry Sintonen, Jacob Mealey,
-  JazJas on github, John Bampton, John Hawthorn, John Walker, Joseph Tharayil,
-  junsik on github, kyled-dell on github, Lukas Tribus, Maksim Arhipov,
-  Maksim Sciepanienka, Marcel Raad, Marin Hannache, Markus Sommer,
-  Martin Galvan, Mathew Benson, Matthias Gatto, Maurício Meneghini Fauth,
-  Michael Osipov, Mohamed Daahir, Nathan Moinvaziri, Niall McGee,
-  Nicholas Nethercote, Nicolas Noben, Nicolás Ojeda Bär, Oleg Jukovec,
-  oliverpool on github, Pablo Busse, Patrick Monnerat,
-  Philippe Antoine on HackerOne, pszlazak on github, Randall S. Becker,
-  Ray Satiro, Richard W.M. Jones, Rutger Broekhoff, Ryan Schmidt,
-  Samuel Chiang, Satana de Sant'Ana, Sergey, Sevan Janiyan, Stefan Eissing,
-  Thomas M. DuBuisson, Thorsten Klein, trrui-huawei, Viktor Szakats, vvb2060,
-  wangzhikun, Wilhelm von Thiele, Wyatt O'Day, yushicheng7788 on github,
-  zhihaoy on github
-  (80 contributors)
+  Abdullah Alyan, Andrew, Antoine Bollengier, blankie, Brian Inglis,
+  Carlos Henrique Lima Melara, Ch40zz on github, Christian Schmitz, Chris Webb,
+  Colin Leroy-Mira, Dagfinn Ilmari Mannsåker, Dan Fandrich, Daniel Gustafsson,
+  Daniel J. H., Daniel McCarney, Daniel Stenberg, Dmitry Karpov,
+  Emanuele Torre, Evgeny Grin (Karlson2k), Fabian Keil, farazrbx on github,
+  fuzzard, Gisle Vanem, Gonçalo Carvalho, Gusted, hammlee96 on github,
+  Harmen Stoppels, Harry Sintonen, Hongfei Li, Ivan, Jan Macku, Jan Venekamp,
+  Jeff King, Jeroen Ooms, Jérôme Leclercq, Jiwoo Park,
+  Johann Sebastian Schicho, Jonatan Vela, Joseph Chen, Juliusz Sosinowicz,
+  Kailun Qin, kalvdans on github, Keitagit-kun on github, Konstantin Kuzov,
+  kpcyrd on github, Laramie Leavitt, LigH, Lucas Nussbaum,
+  magisterquis on hackerone, Marcel Raad, Matt Jolly, Max Dymond, Mel Zuser,
+  Michael Kaufmann, Michael Litwak, Michał Antoniak, Nathan Moinvaziri,
+  Orgad Shaneh, Patrick Monnerat, Paul Gilmartin, Paul Howarth,
+  Pavel Kropachev, Pavel Pavlov, Philip Heiduck, Rahul Krishna M, RainRat,
+  Ray Satiro, renovate[bot], riastradh on github, Robert Moreton,
+  Sanjay Pujare, Sergey Bronnikov, Sergey Ogryzkov, Sergio Durigan Junior,
+  southernedge on github, Stefan Eissing, Stephen Farrell, Tal Regev,
+  Tatsuhiro Tsujikawa, Tobias Stoeckmann, Toon Claes, Trumeet on github,
+  Trzik on github, Viktor Szakats, zmcx16 on github
+  (85 contributors)
 
 References to bug reports and discussions on issues:
 
- [1] = https://curl.se/bug/?i=11346
- [2] = https://curl.se/bug/?i=11564
- [3] = https://github.com/curl/curl-www/issues/272
- [4] = https://curl.se/bug/?i=11551
- [5] = https://curl.se/bug/?i=11556
- [6] = https://curl.se/bug/?i=11553
- [7] = https://curl.se/bug/?i=9621
- [8] = https://curl.se/bug/?i=11452
- [9] = https://curl.se/bug/?i=11562
- [10] = https://curl.se/bug/?i=11459
- [11] = https://curl.se/bug/?i=11502
- [12] = https://curl.se/bug/?i=11325
- [13] = https://curl.se/bug/?i=11609
- [14] = https://curl.se/bug/?i=11536
- [15] = https://curl.se/bug/?i=11521
- [16] = https://curl.se/bug/?i=11538
- [17] = https://curl.se/bug/?i=11505
- [18] = https://curl.se/bug/?i=11561
- [19] = https://curl.se/bug/?i=11532
- [20] = https://curl.se/mail/lib-2023-07/0045.html
- [21] = https://curl.se/bug/?i=11546
- [22] = https://curl.se/bug/?i=11555
- [23] = https://curl.se/bug/?i=11550
- [24] = https://curl.se/bug/?i=11499
- [25] = https://curl.se/bug/?i=9841
- [26] = https://curl.se/bug/?i=9194
- [27] = https://curl.se/mail/lib-2023-07/0041.html
- [28] = https://curl.se/bug/?i=11394
- [29] = https://curl.se/mail/lib-2023-07/0047.html
- [30] = https://curl.se/bug/?i=11560
- [31] = https://curl.se/bug/?i=11500
- [32] = https://curl.se/bug/?i=11527
- [33] = https://curl.se/bug/?i=11457
- [34] = https://curl.se/bug/?i=11525
- [35] = https://curl.se/bug/?i=11517
- [36] = https://curl.se/bug/?i=11416
- [37] = https://curl.se/bug/?i=11605
- [38] = https://curl.se/bug/?i=11589
- [39] = https://curl.se/bug/?i=11608
- [40] = https://curl.se/bug/?i=11584
- [41] = https://curl.se/bug/?i=11421
- [42] = https://curl.se/bug/?i=11606
- [43] = https://curl.se/bug/?i=11582
- [44] = https://curl.se/bug/?i=11563
- [45] = https://curl.se/bug/?i=11570
- [46] = https://curl.se/bug/?i=11581
- [47] = https://curl.se/bug/?i=11579
- [48] = https://curl.se/bug/?i=11568
- [49] = https://curl.se/bug/?i=11578
- [50] = https://curl.se/bug/?i=11635
- [51] = https://curl.se/bug/?i=11638
- [52] = https://curl.se/bug/?i=11621
- [53] = https://curl.se/bug/?i=10741
- [54] = https://curl.se/bug/?i=11655
- [55] = https://curl.se/bug/?i=11628
- [56] = https://curl.se/bug/?i=11592
- [57] = https://curl.se/bug/?i=11594
- [58] = https://curl.se/bug/?i=11597
- [59] = https://curl.se/bug/?i=11596
- [60] = https://curl.se/bug/?i=11681
- [61] = https://curl.se/bug/?i=11619
- [62] = https://curl.se/bug/?i=11631
- [63] = https://curl.se/bug/?i=11618
- [64] = https://curl.se/bug/?i=11666
- [65] = https://curl.se/bug/?i=11617
- [66] = https://curl.se/bug/?i=11616
- [67] = https://curl.se/bug/?i=11615
- [68] = https://curl.se/bug/?i=11612
- [69] = https://curl.se/bug/?i=11614
- [70] = https://curl.se/bug/?i=11611
- [71] = https://curl.se/bug/?i=11460
- [72] = https://curl.se/bug/?i=11661
- [73] = https://curl.se/bug/?i=11653
- [74] = https://curl.haxx.se/mail/lib-2018-10/0113.html
- [75] = https://curl.se/bug/?i=11665
- [76] = https://curl.se/bug/?i=11651
- [77] = https://curl.se/bug/?i=11669
- [78] = https://curl.se/bug/?i=11645
- [79] = https://curl.se/bug/?i=1199308
- [80] = https://curl.se/bug/?i=11627
- [81] = https://curl.se/bug/?i=11624
- [82] = https://curl.se/bug/?i=11654
- [83] = https://curl.se/bug/?i=11705
- [84] = https://curl.se/bug/?i=11673
- [85] = https://curl.se/bug/?i=11752
- [86] = https://sourceforge.net/p/curl/bugs/440/
- [87] = https://curl.se/bug/?i=11657
- [88] = https://curl.se/bug/?i=11698
- [89] = https://curl.se/bug/?i=11697
- [90] = https://curl.se/bug/?i=11695
- [91] = https://curl.se/bug/?i=11728
- [92] = https://curl.se/bug/?i=11696
- [93] = https://curl.se/bug/?i=11727
- [94] = https://curl.se/bug/?i=11680
- [95] = https://curl.se/bug/?i=11650
- [96] = https://curl.se/bug/?i=11650
- [97] = https://curl.se/bug/?i=11687
- [98] = https://curl.se/bug/?i=11683
- [99] = https://curl.se/bug/?i=11675
- [100] = https://curl.se/bug/?i=11675
- [101] = https://curl.se/bug/?i=11686
- [102] = https://curl.se/bug/?i=11674
- [103] = https://curl.se/bug/?i=11685
- [104] = https://curl.se/bug/?i=11723
- [105] = https://curl.se/bug/?i=11713
- [106] = https://curl.se/bug/?i=11714
- [107] = https://curl.se/bug/?i=11739
- [108] = https://curl.se/bug/?i=11718
- [109] = https://curl.se/bug/?i=11678
- [110] = https://curl.se/bug/?i=11711
- [111] = https://curl.se/bug/?i=11722
- [112] = https://curl.se/bug/?i=11721
- [113] = https://curl.se/bug/?i=11737
- [114] = https://curl.se/bug/?i=11746
- [115] = https://curl.se/bug/?i=11710
- [116] = https://curl.se/bug/?i=11745
- [117] = https://curl.se/bug/?i=11749
- [118] = https://curl.se/bug/?i=11742
- [119] = https://curl.se/bug/?i=11530
- [120] = https://curl.se/bug/?i=11736
- [121] = https://curl.se/bug/?i=11576
- [122] = https://curl.se/bug/?i=11780
- [123] = https://curl.se/bug/?i=11734
- [124] = https://curl.se/bug/?i=11769
- [125] = https://curl.se/bug/?i=11766
- [126] = https://curl.se/bug/?i=11729
- [127] = https://curl.se/bug/?i=11794
- [128] = https://curl.se/bug/?i=11774
- [129] = https://curl.se/bug/?i=11773
- [130] = https://curl.se/bug/?i=11792
- [131] = https://curl.se/bug/?i=11771
- [132] = https://curl.se/bug/?i=11756
- [133] = https://curl.se/bug/?i=11791
- [134] = https://curl.se/bug/?i=11764
- [135] = https://curl.se/bug/?i=11490
- [136] = https://curl.se/bug/?i=11547
- [137] = https://curl.se/bug/?i=11779
- [138] = https://curl.se/bug/?i=11784
- [139] = https://curl.se/bug/?i=11785
- [140] = https://curl.se/bug/?i=11547
- [141] = https://curl.se/bug/?i=11738
- [142] = https://curl.se/bug/?i=11759
- [143] = https://curl.se/bug/?i=11747
- [144] = https://curl.se/bug/?i=11677
- [145] = https://curl.se/bug/?i=11735
- [146] = https://curl.se/bug/?i=11757
- [147] = https://curl.se/bug/?i=11693
- [148] = https://curl.se/bug/?i=11753
- [149] = https://curl.se/mail/lib-2023-08/0081.html
- [150] = https://curl.se/bug/?i=11815
- [151] = https://curl.se/bug/?i=11800
- [152] = https://curl.se/bug/?i=11814
- [153] = https://curl.se/bug/?i=11825
- [154] = https://curl.se/bug/?i=11809
- [155] = https://curl.se/bug/?i=11822
- [156] = https://curl.se/bug/?i=11342
- [157] = https://curl.se/bug/?i=11801
- [158] = https://curl.se/bug/?i=11799
- [159] = https://curl.se/bug/?i=11664
- [160] = https://curl.se/bug/?i=11821
- [161] = https://curl.se/bug/?i=11821
- [162] = https://curl.se/bug/?i=11760
- [163] = https://curl.se/bug/?i=11632
- [164] = https://curl.se/bug/?i=11395
- [165] = https://curl.se/bug/?i=11839
- [166] = https://curl.se/bug/?i=11827
+ [1] = https://curl.se/bug/?i=13198
+ [2] = https://curl.se/bug/?i=13191
+ [3] = https://curl.se/bug/?i=13205
+ [4] = https://curl.se/bug/?i=13220
+ [5] = https://curl.se/bug/?i=13209
+ [6] = https://curl.se/bug/?i=13213
+ [7] = https://curl.se/bug/?i=13216
+ [8] = https://curl.se/bug/?i=13208
+ [9] = https://curl.se/bug/?i=13210
+ [10] = https://curl.se/bug/?i=13203
+ [11] = https://curl.se/bug/?i=13171
+ [12] = https://curl.se/bug/?i=13247
+ [13] = https://curl.se/bug/?i=13245
+ [14] = https://curl.se/bug/?i=13214
+ [15] = https://curl.se/bug/?i=13207
+ [16] = https://curl.se/bug/?i=13236
+ [17] = https://curl.se/bug/?i=13240
+ [18] = https://curl.se/bug/?i=13224
+ [19] = https://curl.se/bug/?i=13228
+ [20] = https://curl.se/bug/?i=13230
+ [21] = https://curl.se/bug/?i=13225
+ [22] = https://curl.se/bug/?i=13200
+ [23] = https://curl.se/bug/?i=13206
+ [24] = https://curl.se/bug/?i=13197
+ [25] = https://curl.se/bug/?i=13272
+ [26] = https://curl.se/bug/?i=13371
+ [27] = https://curl.se/bug/?i=13267
+ [28] = https://curl.se/bug/?i=13268
+ [29] = https://curl.se/bug/?i=13263
+ [30] = https://curl.se/bug/?i=13281
+ [31] = https://curl.se/bug/?i=13229
+ [32] = https://curl.se/bug/?i=13244
+ [33] = https://curl.se/bug/?i=13254
+ [34] = https://curl.se/bug/?i=13135
+ [35] = https://curl.se/bug/?i=13239
+ [36] = https://curl.se/bug/?i=13242
+ [37] = https://curl.se/bug/?i=13274
+ [38] = https://curl.se/bug/?i=13299
+ [39] = https://curl.se/bug/?i=13301
+ [40] = https://curl.se/bug/?i=13327
+ [41] = https://curl.se/bug/?i=12665
+ [42] = https://curl.se/bug/?i=13294
+ [43] = https://curl.se/bug/?i=13290
+ [44] = https://curl.se/bug/?i=13258
+ [45] = https://curl.se/bug/?i=13223
+ [46] = https://curl.se/bug/?i=13188
+ [47] = https://curl.se/bug/?i=13286
+ [48] = https://curl.se/bug/?i=13282
+ [49] = https://curl.se/bug/?i=13287
+ [50] = https://curl.se/bug/?i=13284
+ [51] = https://curl.se/bug/?i=13283
+ [52] = https://curl.se/bug/?i=13269
+ [53] = https://curl.se/bug/?i=13346
+ [54] = https://curl.se/bug/?i=13260
+ [55] = https://curl.se/bug/?i=13265
+ [56] = https://curl.se/bug/?i=13322
+ [57] = https://curl.se/bug/?i=13172
+ [58] = https://curl.se/bug/?i=13218
+ [59] = https://curl.se/bug/?i=13364
+ [60] = https://curl.se/bug/?i=13313
+ [61] = https://curl.se/bug/?i=13348
+ [62] = https://curl.se/bug/?i=13344
+ [63] = https://curl.se/bug/?i=13137
+ [64] = https://curl.se/bug/?i=13264
+ [65] = https://curl.se/bug/?i=13292
+ [66] = https://curl.se/bug/?i=13314
+ [67] = https://curl.se/bug/?i=13249
+ [68] = https://curl.se/bug/?i=13335
+ [69] = https://curl.se/bug/?i=13315
+ [70] = https://curl.se/bug/?i=13307
+ [71] = https://curl.se/bug/?i=13310
+ [72] = https://curl.se/bug/?i=13309
+ [73] = https://curl.se/bug/?i=13368
+ [74] = https://curl.se/bug/?i=13372
+ [75] = https://curl.se/bug/?i=13339
+ [76] = https://curl.se/bug/?i=13427
+ [77] = https://curl.se/bug/?i=13332
+ [78] = https://curl.se/bug/?i=13398
+ [79] = https://curl.se/bug/?i=13311
+ [80] = https://curl.se/bug/?i=13324
+ [81] = https://curl.se/bug/?i=13276
+ [82] = https://curl.se/bug/?i=13367
+ [83] = https://curl.se/bug/?i=13394
+ [84] = https://curl.se/bug/?i=13352
+ [85] = https://curl.se/bug/?i=13349
+ [86] = https://curl.se/bug/?i=13399
+ [87] = https://curl.se/bug/?i=13321
+ [88] = https://curl.se/bug/?i=13426
+ [89] = https://curl.se/bug/?i=13425
+ [90] = https://curl.se/bug/?i=13393
+ [91] = https://curl.se/bug/?i=13392
+ [92] = https://curl.se/bug/?i=13204
+ [93] = https://curl.se/bug/?i=13232
+ [94] = https://curl.se/bug/?i=13411
+ [95] = https://curl.se/bug/?i=13246
+ [96] = https://curl.se/bug/?i=13423
+ [97] = https://curl.se/bug/?i=13387
+ [98] = https://curl.se/bug/?i=13422
+ [99] = https://curl.se/bug/?i=13419
+ [100] = https://curl.se/bug/?i=13421
+ [101] = https://curl.se/bug/?i=13418
+ [102] = https://curl.se/bug/?i=13417
+ [103] = https://curl.se/bug/?i=13442
+ [104] = https://curl.se/bug/?i=13337
+ [105] = https://curl.se/bug/?i=13407
+ [106] = https://curl.se/bug/?i=13405
+ [107] = https://curl.se/bug/?i=13377
+ [108] = https://curl.se/bug/?i=13373
+ [109] = https://curl.se/bug/?i=11922
+ [110] = https://curl.se/bug/?i=13499
+ [111] = https://curl.se/bug/?i=13396
+ [112] = https://curl.se/bug/?i=13457
+ [113] = https://curl.se/bug/?i=13450
+ [114] = https://curl.se/bug/?i=12327
+ [115] = https://curl.se/bug/?i=13452
+ [116] = https://curl.se/bug/?i=13439
+ [117] = https://curl.se/bug/?i=13445
+ [118] = https://curl.se/bug/?i=13432
+ [119] = https://curl.se/bug/?i=13436
+ [120] = https://curl.se/bug/?i=13437
+ [121] = https://curl.se/bug/?i=13433
+ [122] = https://curl.se/bug/?i=13435
+ [123] = https://curl.se/bug/?i=13434
+ [124] = https://curl.se/bug/?i=13430
+ [125] = https://curl.se/bug/?i=13497
+ [126] = https://curl.se/bug/?i=13464
+ [127] = https://curl.se/bug/?i=13494
+ [128] = https://curl.se/bug/?i=13491
+ [129] = https://curl.se/bug/?i=13475
+ [130] = https://curl.se/bug/?i=13386
+ [131] = https://curl.se/bug/?i=13150
+ [132] = https://curl.se/bug/?i=13510
+ [133] = https://curl.se/bug/?i=13355
+ [134] = https://curl.se/bug/?i=13471
+ [135] = https://curl.se/bug/?i=13508
+ [136] = https://curl.se/bug/?i=13174
+ [137] = https://curl.se/bug/?i=13451
+ [138] = https://curl.se/bug/?i=13458
+ [139] = https://curl.se/bug/?i=13467
+ [140] = https://curl.se/bug/?i=13562
+ [141] = https://curl.se/bug/?i=13495
+ [142] = https://curl.se/bug/?i=13505
+ [143] = https://curl.se/bug/?i=13503
+ [144] = https://curl.se/bug/?i=13502
+ [145] = https://curl.se/bug/?i=13498
+ [146] = https://curl.se/bug/?i=13500
+ [147] = https://curl.se/bug/?i=13557
+ [148] = https://curl.se/bug/?i=13602
+ [149] = https://curl.se/bug/?i=13568
+ [150] = https://curl.se/bug/?i=13567
+ [151] = https://curl.se/bug/?i=13604
+ [152] = https://curl.se/bug/?i=13566
+ [153] = https://curl.se/bug/?i=13601
+ [154] = https://curl.se/bug/?i=13554
+ [155] = https://curl.se/bug/?i=13237
+ [156] = https://curl.se/bug/?i=13539
+ [157] = https://curl.se/bug/?i=13549
+ [158] = https://curl.se/bug/?i=13550
+ [159] = https://curl.se/bug/?i=13553
+ [160] = https://curl.se/bug/?i=13551
+ [161] = https://curl.se/bug/?i=13509
+ [162] = https://curl.se/bug/?i=13542
+ [163] = https://curl.se/bug/?i=13529
+ [164] = https://curl.se/bug/?i=13540
+ [165] = https://curl.se/bug/?i=13600
+ [166] = https://curl.se/bug/?i=13541
+ [167] = https://curl.se/bug/?i=13538
+ [168] = https://curl.se/bug/?i=13534
+ [169] = https://curl.se/bug/?i=13536
+ [170] = https://curl.se/bug/?i=13725
+ [171] = https://curl.se/bug/?i=13537
+ [172] = https://curl.se/bug/?i=13531
+ [173] = https://curl.se/bug/?i=13504
+ [174] = https://curl.se/bug/?i=13533
+ [175] = https://curl.se/bug/?i=13590
+ [176] = https://curl.se/bug/?i=13591
+ [177] = https://curl.se/bug/?i=13605
+ [178] = https://curl.se/bug/?i=13501
+ [179] = https://curl.se/bug/?i=13578
+ [180] = https://curl.se/bug/?i=13574
+ [181] = https://curl.se/bug/?i=13580
+ [182] = https://curl.se/bug/?i=13582
+ [183] = https://curl.se/bug/?i=13588
+ [184] = https://curl.se/bug/?i=13584
+ [185] = https://curl.se/bug/?i=13586
+ [186] = https://curl.se/bug/?i=13579
+ [187] = https://curl.se/bug/?i=13664
+ [188] = https://curl.se/bug/?i=13577
+ [189] = https://curl.se/bug/?i=13576
+ [190] = https://curl.se/bug/?i=13581
+ [191] = https://curl.se/bug/?i=13728
+ [192] = https://curl.se/bug/?i=13672
+ [193] = https://curl.se/bug/?i=13654
+ [194] = https://curl.se/bug/?i=13628
+ [195] = https://curl.se/bug/?i=13655
+ [196] = https://curl.se/bug/?i=13710
+ [197] = https://curl.se/bug/?i=13707
+ [198] = https://curl.se/bug/?i=13729
+ [199] = https://curl.se/bug/?i=13544
+ [200] = https://curl.se/bug/?i=13733
+ [201] = https://curl.se/bug/?i=13583
+ [203] = https://curl.se/bug/?i=13697
+ [206] = https://curl.se/bug/?i=13661
+ [207] = https://curl.se/bug/?i=13686
+ [208] = https://curl.se/bug/?i=13684
+ [209] = https://curl.se/bug/?i=13639
+ [210] = https://curl.se/bug/?i=13560
+ [211] = https://curl.se/bug/?i=13638
+ [212] = https://curl.se/bug/?i=13603
+ [213] = https://curl.se/bug/?i=13611
+ [214] = https://curl.se/bug/?i=13634
+ [215] = https://curl.se/bug/?i=13681
+ [216] = https://curl.se/bug/?i=13624
+ [217] = https://curl.se/bug/?i=13614
+ [218] = https://curl.se/bug/?i=13621
+ [219] = https://curl.se/bug/?i=13619
+ [220] = https://curl.se/bug/?i=13610
+ [221] = https://curl.se/bug/?i=13608
+ [222] = https://curl.se/bug/?i=13643
+ [223] = https://curl.se/bug/?i=13618
+ [224] = https://curl.se/bug/?i=13676
+ [225] = https://curl.se/bug/?i=13679
+ [226] = https://curl.se/bug/?i=13487
+ [227] = https://curl.se/bug/?i=13668
+ [229] = https://curl.se/bug/?i=13666
+ [230] = https://curl.se/bug/?i=13670
diff --git a/vendor/curl/include/curl/curl.h b/vendor/curl/include/curl/curl.h
index 898cbda839..91e11f62d1 100644
--- a/vendor/curl/include/curl/curl.h
+++ b/vendor/curl/include/curl/curl.h
@@ -53,28 +53,19 @@
 #include "curlver.h"         /* libcurl version defines   */
 #include "system.h"          /* determine things run-time */
 
-/*
- * Define CURL_WIN32 when build target is Win32 API
- */
-
-#if (defined(_WIN32) || defined(__WIN32__) || defined(WIN32)) &&        \
-  !defined(__SYMBIAN32__)
-#define CURL_WIN32
-#endif
-
 #include 
 #include 
 
-#if (defined(__FreeBSD__) && (__FreeBSD__ >= 2)) || defined(__MidnightBSD__)
+#if defined(__FreeBSD__) || defined(__MidnightBSD__)
 /* Needed for __FreeBSD_version or __MidnightBSD_version symbol definition */
-#include 
+#include 
 #endif
 
 /* The include stuff here below is mainly for time_t! */
 #include 
 #include 
 
-#if defined(CURL_WIN32) && !defined(_WIN32_WCE) && !defined(__CYGWIN__)
+#if defined(_WIN32) && !defined(_WIN32_WCE) && !defined(__CYGWIN__)
 #if !(defined(_WINSOCKAPI_) || defined(_WINSOCK_H) || \
       defined(__LWIP_OPT_H__) || defined(LWIP_HDR_OPT_H))
 /* The check above prevents the winsock2 inclusion if winsock.h already was
@@ -88,7 +79,7 @@
    libc5-based Linux systems. Only include it on systems that are known to
    require it! */
 #if defined(_AIX) || defined(__NOVELL_LIBC__) || defined(__NetBSD__) || \
-    defined(__minix) || defined(__SYMBIAN32__) || defined(__INTEGRITY) || \
+    defined(__minix) || defined(__INTEGRITY) || \
     defined(ANDROID) || defined(__ANDROID__) || defined(__OpenBSD__) || \
     defined(__CYGWIN__) || defined(AMIGA) || defined(__NuttX__) || \
    (defined(__FreeBSD_version) && (__FreeBSD_version < 800000)) || \
@@ -97,11 +88,11 @@
 #include 
 #endif
 
-#if !defined(CURL_WIN32) && !defined(_WIN32_WCE)
+#if !defined(_WIN32) && !defined(_WIN32_WCE)
 #include 
 #endif
 
-#if !defined(CURL_WIN32)
+#if !defined(_WIN32)
 #include 
 #endif
 
@@ -128,7 +119,7 @@ typedef void CURLSH;
 
 #ifdef CURL_STATICLIB
 #  define CURL_EXTERN
-#elif defined(CURL_WIN32) || defined(__SYMBIAN32__) || \
+#elif defined(_WIN32) || \
      (__has_declspec_attribute(dllexport) && \
       __has_declspec_attribute(dllimport))
 #  if defined(BUILDING_LIBCURL)
@@ -144,7 +135,7 @@ typedef void CURLSH;
 
 #ifndef curl_socket_typedef
 /* socket typedef */
-#if defined(CURL_WIN32) && !defined(__LWIP_OPT_H__) && !defined(LWIP_HDR_OPT_H)
+#if defined(_WIN32) && !defined(__LWIP_OPT_H__) && !defined(LWIP_HDR_OPT_H)
 typedef SOCKET curl_socket_t;
 #define CURL_SOCKET_BAD INVALID_SOCKET
 #else
@@ -159,7 +150,7 @@ typedef enum {
   CURLSSLBACKEND_NONE = 0,
   CURLSSLBACKEND_OPENSSL = 1,
   CURLSSLBACKEND_GNUTLS = 2,
-  CURLSSLBACKEND_NSS = 3,
+  CURLSSLBACKEND_NSS                    CURL_DEPRECATED(8.3.0, "") = 3,
   CURLSSLBACKEND_OBSOLETE4 = 4,  /* Was QSOSSL. */
   CURLSSLBACKEND_GSKIT                  CURL_DEPRECATED(8.3.0, "") = 5,
   CURLSSLBACKEND_POLARSSL               CURL_DEPRECATED(7.69.0, "") = 6,
@@ -640,16 +631,18 @@ typedef enum {
   CURLE_PROXY,                   /* 97 - proxy handshake error */
   CURLE_SSL_CLIENTCERT,          /* 98 - client-side certificate required */
   CURLE_UNRECOVERABLE_POLL,      /* 99 - poll/select returned fatal error */
+  CURLE_TOO_LARGE,               /* 100 - a value/data met its maximum */
+  CURLE_ECH_REQUIRED,            /* 101 - ECH tried but failed */
   CURL_LAST /* never use! */
 } CURLcode;
 
 #ifndef CURL_NO_OLDIES /* define this to test if your app builds with all
                           the obsolete stuff removed! */
 
-/* Previously obsolete error code re-used in 7.38.0 */
+/* Previously obsolete error code reused in 7.38.0 */
 #define CURLE_OBSOLETE16 CURLE_HTTP2
 
-/* Previously obsolete error codes re-used in 7.24.0 */
+/* Previously obsolete error codes reused in 7.24.0 */
 #define CURLE_OBSOLETE10 CURLE_FTP_ACCEPT_FAILED
 #define CURLE_OBSOLETE12 CURLE_FTP_ACCEPT_TIMEOUT
 
@@ -819,7 +812,10 @@ typedef enum {
 #define CURLAUTH_GSSAPI CURLAUTH_NEGOTIATE
 #define CURLAUTH_NTLM         (((unsigned long)1)<<3)
 #define CURLAUTH_DIGEST_IE    (((unsigned long)1)<<4)
+#ifndef CURL_NO_OLDIES
+  /* functionality removed since 8.8.0 */
 #define CURLAUTH_NTLM_WB      (((unsigned long)1)<<5)
+#endif
 #define CURLAUTH_BEARER       (((unsigned long)1)<<6)
 #define CURLAUTH_AWS_SIGV4    (((unsigned long)1)<<7)
 #define CURLAUTH_ONLY         (((unsigned long)1)<<31)
@@ -1358,7 +1354,7 @@ typedef enum {
      operation slower and is less friendly for the network. */
   CURLOPT(CURLOPT_FRESH_CONNECT, CURLOPTTYPE_LONG, 74),
 
-  /* Set to explicitly forbid the upcoming transfer's connection to be re-used
+  /* Set to explicitly forbid the upcoming transfer's connection to be reused
      when done. Do not use this unless you're absolutely sure of this, as it
      makes the operation slower and is less friendly for the network. */
   CURLOPT(CURLOPT_FORBID_REUSE, CURLOPTTYPE_LONG, 75),
@@ -1652,7 +1648,7 @@ typedef enum {
   CURLOPT(CURLOPT_SOCKOPTFUNCTION, CURLOPTTYPE_FUNCTIONPOINT, 148),
   CURLOPT(CURLOPT_SOCKOPTDATA, CURLOPTTYPE_CBPOINT, 149),
 
-  /* set to 0 to disable session ID re-use for this transfer, default is
+  /* set to 0 to disable session ID reuse for this transfer, default is
      enabled (== 1) */
   CURLOPT(CURLOPT_SSL_SESSIONID_CACHE, CURLOPTTYPE_LONG, 150),
 
@@ -1854,7 +1850,8 @@ typedef enum {
   /* allow GSSAPI credential delegation */
   CURLOPT(CURLOPT_GSSAPI_DELEGATION, CURLOPTTYPE_VALUES, 210),
 
-  /* Set the name servers to use for DNS resolution */
+  /* Set the name servers to use for DNS resolution.
+   * Only supported by the c-ares DNS backend */
   CURLOPT(CURLOPT_DNS_SERVERS, CURLOPTTYPE_STRINGPOINT, 211),
 
   /* Time-out accept operations (currently for FTP only) after this amount
@@ -2210,6 +2207,12 @@ typedef enum {
   /* set a specific client IP for HAProxy PROXY protocol header? */
   CURLOPT(CURLOPT_HAPROXY_CLIENT_IP, CURLOPTTYPE_STRINGPOINT, 323),
 
+  /* millisecond version */
+  CURLOPT(CURLOPT_SERVER_RESPONSE_TIMEOUT_MS, CURLOPTTYPE_LONG, 324),
+
+  /* set ECH configuration  */
+  CURLOPT(CURLOPT_ECH, CURLOPTTYPE_STRINGPOINT, 325),
+
   CURLOPT_LASTENTRY /* the last unused */
 } CURLoption;
 
@@ -2315,30 +2318,26 @@ enum CURL_NETRC_OPTION {
   CURL_NETRC_LAST
 };
 
-enum {
-  CURL_SSLVERSION_DEFAULT,
-  CURL_SSLVERSION_TLSv1, /* TLS 1.x */
-  CURL_SSLVERSION_SSLv2,
-  CURL_SSLVERSION_SSLv3,
-  CURL_SSLVERSION_TLSv1_0,
-  CURL_SSLVERSION_TLSv1_1,
-  CURL_SSLVERSION_TLSv1_2,
-  CURL_SSLVERSION_TLSv1_3,
-
-  CURL_SSLVERSION_LAST /* never use, keep last */
-};
+#define CURL_SSLVERSION_DEFAULT 0
+#define CURL_SSLVERSION_TLSv1   1 /* TLS 1.x */
+#define CURL_SSLVERSION_SSLv2   2
+#define CURL_SSLVERSION_SSLv3   3
+#define CURL_SSLVERSION_TLSv1_0 4
+#define CURL_SSLVERSION_TLSv1_1 5
+#define CURL_SSLVERSION_TLSv1_2 6
+#define CURL_SSLVERSION_TLSv1_3 7
 
-enum {
-  CURL_SSLVERSION_MAX_NONE =     0,
-  CURL_SSLVERSION_MAX_DEFAULT =  (CURL_SSLVERSION_TLSv1   << 16),
-  CURL_SSLVERSION_MAX_TLSv1_0 =  (CURL_SSLVERSION_TLSv1_0 << 16),
-  CURL_SSLVERSION_MAX_TLSv1_1 =  (CURL_SSLVERSION_TLSv1_1 << 16),
-  CURL_SSLVERSION_MAX_TLSv1_2 =  (CURL_SSLVERSION_TLSv1_2 << 16),
-  CURL_SSLVERSION_MAX_TLSv1_3 =  (CURL_SSLVERSION_TLSv1_3 << 16),
+#define CURL_SSLVERSION_LAST 8 /* never use, keep last */
+
+#define CURL_SSLVERSION_MAX_NONE 0
+#define CURL_SSLVERSION_MAX_DEFAULT (CURL_SSLVERSION_TLSv1   << 16)
+#define CURL_SSLVERSION_MAX_TLSv1_0 (CURL_SSLVERSION_TLSv1_0 << 16)
+#define CURL_SSLVERSION_MAX_TLSv1_1 (CURL_SSLVERSION_TLSv1_1 << 16)
+#define CURL_SSLVERSION_MAX_TLSv1_2 (CURL_SSLVERSION_TLSv1_2 << 16)
+#define CURL_SSLVERSION_MAX_TLSv1_3 (CURL_SSLVERSION_TLSv1_3 << 16)
 
   /* never use, keep last */
-  CURL_SSLVERSION_MAX_LAST =     (CURL_SSLVERSION_LAST    << 16)
-};
+#define CURL_SSLVERSION_MAX_LAST    (CURL_SSLVERSION_LAST    << 16)
 
 enum CURL_TLSAUTH {
   CURL_TLSAUTH_NONE,
@@ -2941,7 +2940,9 @@ typedef enum {
   CURLINFO_CAPATH           = CURLINFO_STRING + 62,
   CURLINFO_XFER_ID          = CURLINFO_OFF_T + 63,
   CURLINFO_CONN_ID          = CURLINFO_OFF_T + 64,
-  CURLINFO_LASTONE          = 64
+  CURLINFO_QUEUE_TIME_T     = CURLINFO_OFF_T + 65,
+  CURLINFO_USED_PROXY       = CURLINFO_LONG + 66,
+  CURLINFO_LASTONE          = 66
 } CURLINFO;
 
 /* CURLINFO_RESPONSE_CODE is the new name for the option previously known as
@@ -3037,17 +3038,18 @@ CURL_EXTERN CURLSHcode curl_share_cleanup(CURLSH *share);
  */
 
 typedef enum {
-  CURLVERSION_FIRST,
-  CURLVERSION_SECOND,
-  CURLVERSION_THIRD,
-  CURLVERSION_FOURTH,
-  CURLVERSION_FIFTH,
-  CURLVERSION_SIXTH,
-  CURLVERSION_SEVENTH,
-  CURLVERSION_EIGHTH,
-  CURLVERSION_NINTH,
-  CURLVERSION_TENTH,
-  CURLVERSION_ELEVENTH,
+  CURLVERSION_FIRST,    /* 7.10 */
+  CURLVERSION_SECOND,   /* 7.11.1 */
+  CURLVERSION_THIRD,    /* 7.12.0 */
+  CURLVERSION_FOURTH,   /* 7.16.1 */
+  CURLVERSION_FIFTH,    /* 7.57.0 */
+  CURLVERSION_SIXTH,    /* 7.66.0 */
+  CURLVERSION_SEVENTH,  /* 7.70.0 */
+  CURLVERSION_EIGHTH,   /* 7.72.0 */
+  CURLVERSION_NINTH,    /* 7.75.0 */
+  CURLVERSION_TENTH,    /* 7.77.0 */
+  CURLVERSION_ELEVENTH, /* 7.87.0 */
+  CURLVERSION_TWELFTH,  /* 8.8.0 */
   CURLVERSION_LAST /* never actually use this */
 } CURLversion;
 
@@ -3056,7 +3058,7 @@ typedef enum {
    meant to be a built-in version number for what kind of struct the caller
    expects. If the struct ever changes, we redefine the NOW to another enum
    from above. */
-#define CURLVERSION_NOW CURLVERSION_ELEVENTH
+#define CURLVERSION_NOW CURLVERSION_TWELFTH
 
 struct curl_version_info_data {
   CURLversion age;          /* age of the returned struct */
@@ -3116,6 +3118,9 @@ struct curl_version_info_data {
   /* These fields were added in CURLVERSION_ELEVENTH */
   /* feature_names is terminated by an entry with a NULL feature name */
   const char * const *feature_names;
+
+  /* These fields were added in CURLVERSION_TWELFTH */
+  const char *rtmp_version; /* human readable string. */
 };
 typedef struct curl_version_info_data curl_version_info_data;
 
@@ -3156,7 +3161,7 @@ typedef struct curl_version_info_data curl_version_info_data;
 #define CURL_VERSION_GSASL        (1<<29) /* libgsasl is supported */
 #define CURL_VERSION_THREADSAFE   (1<<30) /* libcurl API is thread-safe */
 
- /*
+/*
  * NAME curl_version_info()
  *
  * DESCRIPTION
@@ -3220,6 +3225,7 @@ CURL_EXTERN CURLcode curl_easy_pause(CURL *handle, int bitmask);
 #include "options.h"
 #include "header.h"
 #include "websockets.h"
+#include "mprintf.h"
 
 /* the typechecker doesn't work in C++ (yet) */
 #if defined(__GNUC__) && defined(__GNUC_MINOR__) && \
diff --git a/vendor/curl/include/curl/curlver.h b/vendor/curl/include/curl/curlver.h
index df93ef1274..b68e3ee64a 100644
--- a/vendor/curl/include/curl/curlver.h
+++ b/vendor/curl/include/curl/curlver.h
@@ -32,12 +32,12 @@
 
 /* This is the version number of the libcurl package from which this header
    file origins: */
-#define LIBCURL_VERSION "8.3.0"
+#define LIBCURL_VERSION "8.8.0"
 
 /* The numeric version number is also available "in parts" by using these
    defines: */
 #define LIBCURL_VERSION_MAJOR 8
-#define LIBCURL_VERSION_MINOR 3
+#define LIBCURL_VERSION_MINOR 8
 #define LIBCURL_VERSION_PATCH 0
 
 /* This is the numeric version of the libcurl version number, meant for easier
@@ -59,7 +59,7 @@
    CURL_VERSION_BITS() macro since curl's own configure script greps for it
    and needs it to contain the full number.
 */
-#define LIBCURL_VERSION_NUM 0x080300
+#define LIBCURL_VERSION_NUM 0x080800
 
 /*
  * This is the date and time when the full source package was created. The
@@ -70,7 +70,7 @@
  *
  * "2007-11-23"
  */
-#define LIBCURL_TIMESTAMP "2023-09-13"
+#define LIBCURL_TIMESTAMP "2024-05-22"
 
 #define CURL_VERSION_BITS(x,y,z) ((x)<<16|(y)<<8|(z))
 #define CURL_AT_LEAST_VERSION(x,y,z) \
diff --git a/vendor/curl/include/curl/mprintf.h b/vendor/curl/include/curl/mprintf.h
index dc5664bc53..4f704548d1 100644
--- a/vendor/curl/include/curl/mprintf.h
+++ b/vendor/curl/include/curl/mprintf.h
@@ -34,19 +34,27 @@ extern "C" {
 
 #if (defined(__GNUC__) || defined(__clang__)) &&                        \
   defined(__STDC_VERSION__) && (__STDC_VERSION__ >= 199901L) &&         \
-  !defined(__MINGW32__) && !defined(CURL_NO_FMT_CHECKS)
-#define CURL_TEMP_PRINTF(a,b) __attribute__ ((format(printf, a, b)))
+  !defined(CURL_NO_FMT_CHECKS)
+#if defined(__MINGW32__) && !defined(__clang__)
+#define CURL_TEMP_PRINTF(fmt, arg) \
+  __attribute__((format(gnu_printf, fmt, arg)))
 #else
-#define CURL_TEMP_PRINTF(a,b)
+#define CURL_TEMP_PRINTF(fmt, arg) \
+  __attribute__((format(printf, fmt, arg)))
+#endif
+#else
+#define CURL_TEMP_PRINTF(fmt, arg)
 #endif
 
-CURL_EXTERN int curl_mprintf(const char *format, ...) CURL_TEMP_PRINTF(1, 2);
+CURL_EXTERN int curl_mprintf(const char *format, ...)
+  CURL_TEMP_PRINTF(1, 2);
 CURL_EXTERN int curl_mfprintf(FILE *fd, const char *format, ...)
   CURL_TEMP_PRINTF(2, 3);
 CURL_EXTERN int curl_msprintf(char *buffer, const char *format, ...)
   CURL_TEMP_PRINTF(2, 3);
 CURL_EXTERN int curl_msnprintf(char *buffer, size_t maxlength,
-                               const char *format, ...) CURL_TEMP_PRINTF(3, 4);
+                               const char *format, ...)
+  CURL_TEMP_PRINTF(3, 4);
 CURL_EXTERN int curl_mvprintf(const char *format, va_list args)
   CURL_TEMP_PRINTF(1, 0);
 CURL_EXTERN int curl_mvfprintf(FILE *fd, const char *format, va_list args)
diff --git a/vendor/curl/include/curl/multi.h b/vendor/curl/include/curl/multi.h
index 13b55b7807..561470ce70 100644
--- a/vendor/curl/include/curl/multi.h
+++ b/vendor/curl/include/curl/multi.h
@@ -426,6 +426,17 @@ CURL_EXTERN CURLMcode curl_multi_setopt(CURLM *multi_handle,
 CURL_EXTERN CURLMcode curl_multi_assign(CURLM *multi_handle,
                                         curl_socket_t sockfd, void *sockp);
 
+/*
+ * Name:    curl_multi_get_handles()
+ *
+ * Desc:    Returns an allocated array holding all handles currently added to
+ *          the multi handle. Marks the final entry with a NULL pointer. If
+ *          there is no easy handle added to the multi handle, this function
+ *          returns an array with the first entry as a NULL pointer.
+ *
+ * Returns: NULL on failure, otherwise a CURL **array pointer
+ */
+CURL_EXTERN CURL **curl_multi_get_handles(CURLM *multi_handle);
 
 /*
  * Name: curl_push_callback
@@ -453,6 +464,20 @@ typedef int (*curl_push_callback)(CURL *parent,
                                   struct curl_pushheaders *headers,
                                   void *userp);
 
+/*
+ * Name:    curl_multi_waitfds()
+ *
+ * Desc:    Ask curl for fds for polling. The app can use these to poll on.
+ *          We want curl_multi_perform() called as soon as one of them are
+ *          ready. Passing zero size allows to get just a number of fds.
+ *
+ * Returns: CURLMcode type, general multi error code.
+ */
+CURL_EXTERN CURLMcode curl_multi_waitfds(CURLM *multi,
+                                         struct curl_waitfd *ufds,
+                                         unsigned int size,
+                                         unsigned int *fd_count);
+
 #ifdef __cplusplus
 } /* end of extern "C" */
 #endif
diff --git a/vendor/curl/include/curl/system.h b/vendor/curl/include/curl/system.h
index 97e0d037a9..81a1b817df 100644
--- a/vendor/curl/include/curl/system.h
+++ b/vendor/curl/include/curl/system.h
@@ -141,29 +141,6 @@
 #    define CURL_TYPEOF_CURL_SOCKLEN_T int
 #  endif
 
-#elif defined(__SYMBIAN32__)
-#  if defined(__EABI__) /* Treat all ARM compilers equally */
-#    define CURL_TYPEOF_CURL_OFF_T     long long
-#    define CURL_FORMAT_CURL_OFF_T     "lld"
-#    define CURL_FORMAT_CURL_OFF_TU    "llu"
-#    define CURL_SUFFIX_CURL_OFF_T     LL
-#    define CURL_SUFFIX_CURL_OFF_TU    ULL
-#  elif defined(__CW32__)
-#    pragma longlong on
-#    define CURL_TYPEOF_CURL_OFF_T     long long
-#    define CURL_FORMAT_CURL_OFF_T     "lld"
-#    define CURL_FORMAT_CURL_OFF_TU    "llu"
-#    define CURL_SUFFIX_CURL_OFF_T     LL
-#    define CURL_SUFFIX_CURL_OFF_TU    ULL
-#  elif defined(__VC32__)
-#    define CURL_TYPEOF_CURL_OFF_T     __int64
-#    define CURL_FORMAT_CURL_OFF_T     "lld"
-#    define CURL_FORMAT_CURL_OFF_TU    "llu"
-#    define CURL_SUFFIX_CURL_OFF_T     LL
-#    define CURL_SUFFIX_CURL_OFF_TU    ULL
-#  endif
-#  define CURL_TYPEOF_CURL_SOCKLEN_T unsigned int
-
 #elif defined(macintosh)
 #  include 
 #  if TYPE_LONGLONG
@@ -201,14 +178,14 @@
 #  define CURL_TYPEOF_CURL_SOCKLEN_T int
 
 #elif defined(__MINGW32__)
+#  include 
 #  define CURL_TYPEOF_CURL_OFF_T     long long
-#  define CURL_FORMAT_CURL_OFF_T     "I64d"
-#  define CURL_FORMAT_CURL_OFF_TU    "I64u"
+#  define CURL_FORMAT_CURL_OFF_T     PRId64
+#  define CURL_FORMAT_CURL_OFF_TU    PRIu64
 #  define CURL_SUFFIX_CURL_OFF_T     LL
 #  define CURL_SUFFIX_CURL_OFF_TU    ULL
-#  define CURL_TYPEOF_CURL_SOCKLEN_T socklen_t
+#  define CURL_TYPEOF_CURL_SOCKLEN_T int
 #  define CURL_PULL_SYS_TYPES_H      1
-#  define CURL_PULL_WS2TCPIP_H       1
 
 #elif defined(__VMS)
 #  if defined(__VAX)
@@ -370,7 +347,14 @@
 /* ===================================== */
 
 #elif defined(_MSC_VER)
-#  if (_MSC_VER >= 900) && (_INTEGRAL_MAX_BITS >= 64)
+#  if (_MSC_VER >= 1800)
+#    include 
+#    define CURL_TYPEOF_CURL_OFF_T     __int64
+#    define CURL_FORMAT_CURL_OFF_T     PRId64
+#    define CURL_FORMAT_CURL_OFF_TU    PRIu64
+#    define CURL_SUFFIX_CURL_OFF_T     i64
+#    define CURL_SUFFIX_CURL_OFF_TU    ui64
+#  elif (_MSC_VER >= 900) && (_INTEGRAL_MAX_BITS >= 64)
 #    define CURL_TYPEOF_CURL_OFF_T     __int64
 #    define CURL_FORMAT_CURL_OFF_T     "I64d"
 #    define CURL_FORMAT_CURL_OFF_TU    "I64u"
@@ -432,15 +416,6 @@
 #define CURL_PULL_SYS_POLL_H
 #endif
 
-
-/* CURL_PULL_WS2TCPIP_H is defined above when inclusion of header file  */
-/* ws2tcpip.h is required here to properly make type definitions below. */
-#ifdef CURL_PULL_WS2TCPIP_H
-#  include 
-#  include 
-#  include 
-#endif
-
 /* CURL_PULL_SYS_TYPES_H is defined above when inclusion of header file  */
 /* sys/types.h is required here to properly make type definitions below. */
 #ifdef CURL_PULL_SYS_TYPES_H
diff --git a/vendor/curl/include/curl/typecheck-gcc.h b/vendor/curl/include/curl/typecheck-gcc.h
index b880f3dc60..873a49e020 100644
--- a/vendor/curl/include/curl/typecheck-gcc.h
+++ b/vendor/curl/include/curl/typecheck-gcc.h
@@ -275,6 +275,7 @@ CURLWARNING(_curl_easy_getinfo_err_curl_off_t,
    (option) == CURLOPT_DNS_LOCAL_IP6 ||                                       \
    (option) == CURLOPT_DNS_SERVERS ||                                         \
    (option) == CURLOPT_DOH_URL ||                                             \
+   (option) == CURLOPT_ECH        ||                                          \
    (option) == CURLOPT_EGDSOCKET ||                                           \
    (option) == CURLOPT_FTP_ACCOUNT ||                                         \
    (option) == CURLOPT_FTP_ALTERNATIVE_TO_USER ||                             \
diff --git a/vendor/curl/include/curl/urlapi.h b/vendor/curl/include/curl/urlapi.h
index 88cdeb3bca..19388c3c01 100644
--- a/vendor/curl/include/curl/urlapi.h
+++ b/vendor/curl/include/curl/urlapi.h
@@ -63,6 +63,7 @@ typedef enum {
   CURLUE_BAD_SLASHES,         /* 28 */
   CURLUE_BAD_USER,            /* 29 */
   CURLUE_LACKS_IDN,           /* 30 */
+  CURLUE_TOO_LARGE,           /* 31 */
   CURLUE_LAST
 } CURLUcode;
 
@@ -98,6 +99,9 @@ typedef enum {
 #define CURLU_ALLOW_SPACE (1<<11)       /* Allow spaces in the URL */
 #define CURLU_PUNYCODE (1<<12)          /* get the host name in punycode */
 #define CURLU_PUNY2IDN (1<<13)          /* punycode => IDN conversion */
+#define CURLU_GET_EMPTY (1<<14)         /* allow empty queries and fragments
+                                           when extracting the URL or the
+                                           components */
 
 typedef struct Curl_URL CURLU;
 
diff --git a/vendor/curl/lib/altsvc.c b/vendor/curl/lib/altsvc.c
index 22b0b69c77..b72a59612a 100644
--- a/vendor/curl/lib/altsvc.c
+++ b/vendor/curl/lib/altsvc.c
@@ -97,7 +97,7 @@ static struct altsvc *altsvc_createid(const char *srchost,
                                       unsigned int srcport,
                                       unsigned int dstport)
 {
-  struct altsvc *as = calloc(sizeof(struct altsvc), 1);
+  struct altsvc *as = calloc(1, sizeof(struct altsvc));
   size_t hlen;
   size_t dlen;
   if(!as)
@@ -106,9 +106,11 @@ static struct altsvc *altsvc_createid(const char *srchost,
   dlen = strlen(dsthost);
   DEBUGASSERT(hlen);
   DEBUGASSERT(dlen);
-  if(!hlen || !dlen)
+  if(!hlen || !dlen) {
     /* bad input */
+    free(as);
     return NULL;
+  }
   if((hlen > 2) && srchost[0] == '[') {
     /* IPv6 address, strip off brackets */
     srchost++;
@@ -123,15 +125,13 @@ static struct altsvc *altsvc_createid(const char *srchost,
     dlen -= 2;
   }
 
-  as->src.host = Curl_memdup(srchost, hlen + 1);
+  as->src.host = Curl_memdup0(srchost, hlen);
   if(!as->src.host)
     goto error;
-  as->src.host[hlen] = 0;
 
-  as->dst.host = Curl_memdup(dsthost, dlen + 1);
+  as->dst.host = Curl_memdup0(dsthost, dlen);
   if(!as->dst.host)
     goto error;
-  as->dst.host[dlen] = 0;
 
   as->src.alpnid = srcalpnid;
   as->dst.alpnid = dstalpnid;
@@ -191,7 +191,7 @@ static CURLcode altsvc_add(struct altsvcinfo *asi, char *line)
       as->expires = expires;
       as->prio = prio;
       as->persist = persist ? 1 : 0;
-      Curl_llist_insert_next(&asi->list, asi->list.tail, as, &as->node);
+      Curl_llist_append(&asi->list, as, &as->node);
     }
   }
 
@@ -209,7 +209,6 @@ static CURLcode altsvc_add(struct altsvcinfo *asi, char *line)
 static CURLcode altsvc_load(struct altsvcinfo *asi, const char *file)
 {
   CURLcode result = CURLE_OK;
-  char *line = NULL;
   FILE *fp;
 
   /* we need a private copy of the file name so that the altsvc cache file
@@ -221,11 +220,10 @@ static CURLcode altsvc_load(struct altsvcinfo *asi, const char *file)
 
   fp = fopen(file, FOPEN_READTEXT);
   if(fp) {
-    line = malloc(MAX_ALTSVC_LINE);
-    if(!line)
-      goto fail;
-    while(Curl_get_line(line, MAX_ALTSVC_LINE, fp)) {
-      char *lineptr = line;
+    struct dynbuf buf;
+    Curl_dyn_init(&buf, MAX_ALTSVC_LINE);
+    while(Curl_get_line(&buf, fp)) {
+      char *lineptr = Curl_dyn_ptr(&buf);
       while(*lineptr && ISBLANK(*lineptr))
         lineptr++;
       if(*lineptr == '#')
@@ -234,16 +232,10 @@ static CURLcode altsvc_load(struct altsvcinfo *asi, const char *file)
 
       altsvc_add(asi, lineptr);
     }
-    free(line); /* free the line buffer */
+    Curl_dyn_free(&buf); /* free the line buffer */
     fclose(fp);
   }
   return result;
-
-fail:
-  Curl_safefree(asi->filename);
-  free(line);
-  fclose(fp);
-  return CURLE_OUT_OF_MEMORY;
 }
 
 /*
@@ -260,7 +252,7 @@ static CURLcode altsvc_out(struct altsvc *as, FILE *fp)
   CURLcode result = Curl_gmtime(as->expires, &stamp);
   if(result)
     return result;
-#ifdef ENABLE_IPV6
+#ifdef USE_IPV6
   else {
     char ipv6_unused[16];
     if(1 == Curl_inet_pton(AF_INET6, as->dst.host, ipv6_unused)) {
@@ -301,7 +293,7 @@ static CURLcode altsvc_out(struct altsvc *as, FILE *fp)
  */
 struct altsvcinfo *Curl_altsvc_init(void)
 {
-  struct altsvcinfo *asi = calloc(sizeof(struct altsvcinfo), 1);
+  struct altsvcinfo *asi = calloc(1, sizeof(struct altsvcinfo));
   if(!asi)
     return NULL;
   Curl_llist_init(&asi->list, NULL);
@@ -311,7 +303,7 @@ struct altsvcinfo *Curl_altsvc_init(void)
 #ifdef USE_HTTP2
     | CURLALTSVC_H2
 #endif
-#ifdef ENABLE_QUIC
+#ifdef USE_HTTP3
     | CURLALTSVC_H3
 #endif
     ;
@@ -335,9 +327,6 @@ CURLcode Curl_altsvc_load(struct altsvcinfo *asi, const char *file)
 CURLcode Curl_altsvc_ctrl(struct altsvcinfo *asi, const long ctrl)
 {
   DEBUGASSERT(asi);
-  if(!ctrl)
-    /* unexpected */
-    return CURLE_BAD_FUNCTION_ARGUMENT;
   asi->flags = ctrl;
   return CURLE_OK;
 }
@@ -654,7 +643,7 @@ CURLcode Curl_altsvc_parse(struct Curl_easy *data,
                account. [See RFC 7838 section 3.1] */
             as->expires = maxage + time(NULL);
             as->persist = persist;
-            Curl_llist_insert_next(&asi->list, asi->list.tail, as, &as->node);
+            Curl_llist_append(&asi->list, as, &as->node);
             infof(data, "Added alt-svc: %s:%d over %s", dsthost, dstport,
                   Curl_alpnid2str(dstalpnid));
           }
diff --git a/vendor/curl/lib/arpa_telnet.h b/vendor/curl/lib/arpa_telnet.h
index de1373800c..228b4466ed 100644
--- a/vendor/curl/lib/arpa_telnet.h
+++ b/vendor/curl/lib/arpa_telnet.h
@@ -56,12 +56,14 @@ static const char * const telnetoptions[]=
   "TERM SPEED",  "LFLOW",          "LINEMODE",      "XDISPLOC",
   "OLD-ENVIRON", "AUTHENTICATION", "ENCRYPT",       "NEW-ENVIRON"
 };
+#define CURL_TELOPT(x)    telnetoptions[x]
+#else
+#define CURL_TELOPT(x)    ""
 #endif
 
 #define CURL_TELOPT_MAXIMUM CURL_TELOPT_NEW_ENVIRON
 
 #define CURL_TELOPT_OK(x) ((x) <= CURL_TELOPT_MAXIMUM)
-#define CURL_TELOPT(x)    telnetoptions[x]
 
 #define CURL_NTELOPTS 40
 
@@ -103,7 +105,12 @@ static const char * const telnetcmds[]=
 
 #define CURL_TELCMD_OK(x) ( ((unsigned int)(x) >= CURL_TELCMD_MINIMUM) && \
                        ((unsigned int)(x) <= CURL_TELCMD_MAXIMUM) )
+
+#ifndef CURL_DISABLE_VERBOSE_STRINGS
 #define CURL_TELCMD(x)    telnetcmds[(x)-CURL_TELCMD_MINIMUM]
+#else
+#define CURL_TELCMD(x)    ""
+#endif
 
 #endif /* CURL_DISABLE_TELNET */
 
diff --git a/vendor/curl/lib/asyn-ares.c b/vendor/curl/lib/asyn-ares.c
index e73e41dab9..8fed61760b 100644
--- a/vendor/curl/lib/asyn-ares.c
+++ b/vendor/curl/lib/asyn-ares.c
@@ -60,13 +60,13 @@
 #include "progress.h"
 #include "timediff.h"
 
-#  if defined(CURL_STATICLIB) && !defined(CARES_STATICLIB) &&   \
-  defined(WIN32)
-#    define CARES_STATICLIB
-#  endif
-#  include 
-#  include  /* really old c-ares didn't include this by
-                               itself */
+#if defined(CURL_STATICLIB) && !defined(CARES_STATICLIB) &&   \
+  defined(_WIN32)
+#  define CARES_STATICLIB
+#endif
+#include 
+#include  /* really old c-ares didn't include this by
+                             itself */
 
 #if ARES_VERSION >= 0x010500
 /* c-ares 1.5.0 or later, the callback proto is modified */
@@ -122,6 +122,8 @@ struct thread_data {
 
 #define CARES_TIMEOUT_PER_ATTEMPT 2000
 
+static int ares_ver = 0;
+
 /*
  * Curl_resolver_global_init() - the generic low-level asynchronous name
  * resolve API.  Called from curl_global_init() to initialize global resolver
@@ -134,6 +136,7 @@ int Curl_resolver_global_init(void)
     return CURLE_FAILED_INIT;
   }
 #endif
+  ares_version(&ares_ver);
   return CURLE_OK;
 }
 
@@ -175,8 +178,21 @@ CURLcode Curl_resolver_init(struct Curl_easy *easy, void **resolver)
   int optmask = ARES_OPT_SOCK_STATE_CB;
   options.sock_state_cb = sock_state_cb;
   options.sock_state_cb_data = easy;
-  options.timeout = CARES_TIMEOUT_PER_ATTEMPT;
-  optmask |= ARES_OPT_TIMEOUTMS;
+
+  /*
+     if c ares < 1.20.0: curl set timeout to CARES_TIMEOUT_PER_ATTEMPT (2s)
+
+     if c-ares >= 1.20.0 it already has the timeout to 2s, curl does not need
+     to set the timeout value;
+
+     if c-ares >= 1.24.0, user can set the timeout via /etc/resolv.conf to
+     overwrite c-ares' timeout.
+  */
+  DEBUGASSERT(ares_ver);
+  if(ares_ver < 0x011400) {
+    options.timeout = CARES_TIMEOUT_PER_ATTEMPT;
+    optmask |= ARES_OPT_TIMEOUTMS;
+  }
 
   status = ares_init_options((ares_channel*)resolver, &options, optmask);
   if(status != ARES_SUCCESS) {
@@ -523,7 +539,7 @@ static void compound_results(struct thread_data *res,
   if(!ai)
     return;
 
-#ifdef ENABLE_IPV6 /* CURLRES_IPV6 */
+#ifdef USE_IPV6 /* CURLRES_IPV6 */
   if(res->temp_ai && res->temp_ai->ai_family == PF_INET6) {
     /* We have results already, put the new IPv6 entries at the head of the
        list. */
@@ -668,7 +684,7 @@ static struct Curl_addrinfo *ares2addr(struct ares_addrinfo_node *node)
     /* settle family-specific sockaddr structure size.  */
     if(ai->ai_family == AF_INET)
       ss_size = sizeof(struct sockaddr_in);
-#ifdef ENABLE_IPV6
+#ifdef USE_IPV6
     else if(ai->ai_family == AF_INET6)
       ss_size = sizeof(struct sockaddr_in6);
 #endif
@@ -755,7 +771,7 @@ struct Curl_addrinfo *Curl_resolver_getaddrinfo(struct Curl_easy *data,
   size_t namelen = strlen(hostname);
   *waitp = 0; /* default to synchronous response */
 
-  res = calloc(sizeof(struct thread_data) + namelen, 1);
+  res = calloc(1, sizeof(struct thread_data) + namelen);
   if(res) {
     strcpy(res->hostname, hostname);
     data->state.async.hostname = res->hostname;
@@ -834,7 +850,7 @@ CURLcode Curl_set_dns_servers(struct Curl_easy *data,
   /* If server is NULL or empty, this would purge all DNS servers
    * from ares library, which will cause any and all queries to fail.
    * So, just return OK if none are configured and don't actually make
-   * any changes to c-ares.  This lets c-ares use it's defaults, which
+   * any changes to c-ares.  This lets c-ares use its defaults, which
    * it gets from the OS (for instance from /etc/resolv.conf on Linux).
    */
   if(!(servers && servers[0]))
@@ -858,6 +874,7 @@ CURLcode Curl_set_dns_servers(struct Curl_easy *data,
   case ARES_ENODATA:
   case ARES_EBADSTR:
   default:
+    DEBUGF(infof(data, "bad servers set"));
     result = CURLE_BAD_FUNCTION_ARGUMENT;
     break;
   }
@@ -896,6 +913,7 @@ CURLcode Curl_set_dns_local_ip4(struct Curl_easy *data,
   }
   else {
     if(Curl_inet_pton(AF_INET, local_ip4, &a4) != 1) {
+      DEBUGF(infof(data, "bad DNS IPv4 address"));
       return CURLE_BAD_FUNCTION_ARGUMENT;
     }
   }
@@ -914,7 +932,7 @@ CURLcode Curl_set_dns_local_ip4(struct Curl_easy *data,
 CURLcode Curl_set_dns_local_ip6(struct Curl_easy *data,
                                 const char *local_ip6)
 {
-#if defined(HAVE_CARES_SET_LOCAL) && defined(ENABLE_IPV6)
+#if defined(HAVE_CARES_SET_LOCAL) && defined(USE_IPV6)
   unsigned char a6[INET6_ADDRSTRLEN];
 
   if((!local_ip6) || (local_ip6[0] == 0)) {
@@ -923,6 +941,7 @@ CURLcode Curl_set_dns_local_ip6(struct Curl_easy *data,
   }
   else {
     if(Curl_inet_pton(AF_INET6, local_ip6, a6) != 1) {
+      DEBUGF(infof(data, "bad DNS IPv6 address"));
       return CURLE_BAD_FUNCTION_ARGUMENT;
     }
   }
diff --git a/vendor/curl/lib/asyn-thread.c b/vendor/curl/lib/asyn-thread.c
index a2e294f8f5..1760d6cb3f 100644
--- a/vendor/curl/lib/asyn-thread.c
+++ b/vendor/curl/lib/asyn-thread.c
@@ -54,6 +54,7 @@
 #  define RESOLVER_ENOMEM  ENOMEM
 #endif
 
+#include "system_win32.h"
 #include "urldata.h"
 #include "sendf.h"
 #include "hostip.h"
@@ -144,9 +145,22 @@ static bool init_resolve_thread(struct Curl_easy *data,
                                 const char *hostname, int port,
                                 const struct addrinfo *hints);
 
+#ifdef _WIN32
+/* Thread sync data used by GetAddrInfoExW for win8+ */
+struct thread_sync_data_w8
+{
+  OVERLAPPED overlapped;
+  ADDRINFOEXW_ *res;
+  HANDLE cancel_ev;
+  ADDRINFOEXW_ hints;
+};
+#endif
 
 /* Data for synchronization between resolver thread and its parent */
 struct thread_sync_data {
+#ifdef _WIN32
+  struct thread_sync_data_w8 w8;
+#endif
   curl_mutex_t *mtx;
   int done;
   int port;
@@ -165,6 +179,9 @@ struct thread_sync_data {
 };
 
 struct thread_data {
+#ifdef _WIN32
+  HANDLE complete_ev;
+#endif
   curl_thread_t thread_hnd;
   unsigned int poll_interval;
   timediff_t interval_end;
@@ -196,7 +213,7 @@ void destroy_thread_sync_data(struct thread_sync_data *tsd)
    * the other end (for reading) is always closed in the parent thread.
    */
   if(tsd->sock_pair[1] != CURL_SOCKET_BAD) {
-    sclose(tsd->sock_pair[1]);
+    wakeup_close(tsd->sock_pair[1]);
   }
 #endif
   memset(tsd, 0, sizeof(*tsd));
@@ -233,8 +250,8 @@ int init_thread_sync_data(struct thread_data *td,
   Curl_mutex_init(tsd->mtx);
 
 #ifndef CURL_DISABLE_SOCKETPAIR
-  /* create socket pair, avoid AF_LOCAL since it doesn't build on Solaris */
-  if(Curl_socketpair(AF_UNIX, SOCK_STREAM, 0, &tsd->sock_pair[0]) < 0) {
+  /* create socket pair or pipe */
+  if(wakeup_create(&tsd->sock_pair[0]) < 0) {
     tsd->sock_pair[0] = CURL_SOCKET_BAD;
     tsd->sock_pair[1] = CURL_SOCKET_BAD;
     goto err_exit;
@@ -254,7 +271,7 @@ int init_thread_sync_data(struct thread_data *td,
 err_exit:
 #ifndef CURL_DISABLE_SOCKETPAIR
   if(tsd->sock_pair[0] != CURL_SOCKET_BAD) {
-    sclose(tsd->sock_pair[0]);
+    wakeup_close(tsd->sock_pair[0]);
     tsd->sock_pair[0] = CURL_SOCKET_BAD;
   }
 #endif
@@ -276,13 +293,158 @@ static CURLcode getaddrinfo_complete(struct Curl_easy *data)
   return result;
 }
 
+#ifdef _WIN32
+static VOID WINAPI
+query_complete(DWORD err, DWORD bytes, LPWSAOVERLAPPED overlapped)
+{
+  size_t ss_size;
+  const ADDRINFOEXW_ *ai;
+  struct Curl_addrinfo *ca;
+  struct Curl_addrinfo *cafirst = NULL;
+  struct Curl_addrinfo *calast = NULL;
+#ifdef __clang__
+#pragma clang diagnostic push
+#pragma clang diagnostic ignored "-Wcast-align"
+#endif
+  struct thread_sync_data *tsd =
+    CONTAINING_RECORD(overlapped, struct thread_sync_data, w8.overlapped);
+#ifdef __clang__
+#pragma clang diagnostic pop
+#endif
+  struct thread_data *td = tsd->td;
+  const ADDRINFOEXW_ *res = tsd->w8.res;
+  int error = (int)err;
+  (void)bytes;
+
+  if(error == ERROR_SUCCESS) {
+    /* traverse the addrinfo list */
+
+    for(ai = res; ai != NULL; ai = ai->ai_next) {
+      size_t namelen = ai->ai_canonname ? wcslen(ai->ai_canonname) + 1 : 0;
+      /* ignore elements with unsupported address family, */
+      /* settle family-specific sockaddr structure size.  */
+      if(ai->ai_family == AF_INET)
+        ss_size = sizeof(struct sockaddr_in);
+#ifdef USE_IPV6
+      else if(ai->ai_family == AF_INET6)
+        ss_size = sizeof(struct sockaddr_in6);
+#endif
+      else
+        continue;
+
+      /* ignore elements without required address info */
+      if(!ai->ai_addr || !(ai->ai_addrlen > 0))
+        continue;
+
+      /* ignore elements with bogus address size */
+      if((size_t)ai->ai_addrlen < ss_size)
+        continue;
+
+      ca = malloc(sizeof(struct Curl_addrinfo) + ss_size + namelen);
+      if(!ca) {
+        error = EAI_MEMORY;
+        break;
+      }
+
+      /* copy each structure member individually, member ordering, */
+      /* size, or padding might be different for each platform.    */
+      ca->ai_flags     = ai->ai_flags;
+      ca->ai_family    = ai->ai_family;
+      ca->ai_socktype  = ai->ai_socktype;
+      ca->ai_protocol  = ai->ai_protocol;
+      ca->ai_addrlen   = (curl_socklen_t)ss_size;
+      ca->ai_addr      = NULL;
+      ca->ai_canonname = NULL;
+      ca->ai_next      = NULL;
+
+      ca->ai_addr = (void *)((char *)ca + sizeof(struct Curl_addrinfo));
+      memcpy(ca->ai_addr, ai->ai_addr, ss_size);
+
+      if(namelen) {
+        size_t i;
+        ca->ai_canonname = (void *)((char *)ca->ai_addr + ss_size);
+        for(i = 0; i < namelen; ++i) /* convert wide string to ascii */
+          ca->ai_canonname[i] = (char)ai->ai_canonname[i];
+        ca->ai_canonname[namelen] = '\0';
+      }
+
+      /* if the return list is empty, this becomes the first element */
+      if(!cafirst)
+        cafirst = ca;
+
+      /* add this element last in the return list */
+      if(calast)
+        calast->ai_next = ca;
+      calast = ca;
+    }
+
+    /* if we failed, also destroy the Curl_addrinfo list */
+    if(error) {
+      Curl_freeaddrinfo(cafirst);
+      cafirst = NULL;
+    }
+    else if(!cafirst) {
+#ifdef EAI_NONAME
+      /* rfc3493 conformant */
+      error = EAI_NONAME;
+#else
+      /* rfc3493 obsoleted */
+      error = EAI_NODATA;
+#endif
+#ifdef USE_WINSOCK
+      SET_SOCKERRNO(error);
+#endif
+    }
+    tsd->res = cafirst;
+  }
+
+  if(tsd->w8.res) {
+    Curl_FreeAddrInfoExW(tsd->w8.res);
+    tsd->w8.res = NULL;
+  }
+
+  if(error) {
+    tsd->sock_error = SOCKERRNO?SOCKERRNO:error;
+    if(tsd->sock_error == 0)
+      tsd->sock_error = RESOLVER_ENOMEM;
+  }
+  else {
+    Curl_addrinfo_set_port(tsd->res, tsd->port);
+  }
+
+  Curl_mutex_acquire(tsd->mtx);
+  if(tsd->done) {
+    /* too late, gotta clean up the mess */
+    Curl_mutex_release(tsd->mtx);
+    destroy_thread_sync_data(tsd);
+    free(td);
+  }
+  else {
+#ifndef CURL_DISABLE_SOCKETPAIR
+    char buf[1];
+    if(tsd->sock_pair[1] != CURL_SOCKET_BAD) {
+      /* DNS has been resolved, signal client task */
+      buf[0] = 1;
+      if(swrite(tsd->sock_pair[1],  buf, sizeof(buf)) < 0) {
+        /* update sock_erro to errno */
+        tsd->sock_error = SOCKERRNO;
+      }
+    }
+#endif
+    tsd->done = 1;
+    Curl_mutex_release(tsd->mtx);
+    if(td->complete_ev)
+      SetEvent(td->complete_ev); /* Notify caller that the query completed */
+  }
+}
+#endif
 
 #ifdef HAVE_GETADDRINFO
 
 /*
  * getaddrinfo_thread() resolves a name and then exits.
  *
- * For builds without ARES, but with ENABLE_IPV6, create a resolver thread
+ * For builds without ARES, but with USE_IPV6, create a resolver thread
  * and wait on it.
  */
 static unsigned int CURL_STDCALL getaddrinfo_thread(void *arg)
@@ -320,7 +482,7 @@ static unsigned int CURL_STDCALL getaddrinfo_thread(void *arg)
     if(tsd->sock_pair[1] != CURL_SOCKET_BAD) {
       /* DNS has been resolved, signal client task */
       buf[0] = 1;
-      if(swrite(tsd->sock_pair[1],  buf, sizeof(buf)) < 0) {
+      if(wakeup_write(tsd->sock_pair[1],  buf, sizeof(buf)) < 0) {
         /* update sock_erro to errno */
         tsd->sock_error = SOCKERRNO;
       }
@@ -391,9 +553,26 @@ static void destroy_async_data(struct Curl_async *async)
     Curl_mutex_release(td->tsd.mtx);
 
     if(!done) {
-      Curl_thread_destroy(td->thread_hnd);
+#ifdef _WIN32
+      if(td->complete_ev) {
+        CloseHandle(td->complete_ev);
+        td->complete_ev = NULL;
+      }
+#endif
+      if(td->thread_hnd != curl_thread_t_null) {
+        Curl_thread_destroy(td->thread_hnd);
+        td->thread_hnd = curl_thread_t_null;
+      }
     }
     else {
+#ifdef _WIN32
+      if(td->complete_ev) {
+        Curl_GetAddrInfoExCancel(&td->tsd.w8.cancel_ev);
+        WaitForSingleObject(td->complete_ev, INFINITE);
+        CloseHandle(td->complete_ev);
+        td->complete_ev = NULL;
+      }
+#endif
       if(td->thread_hnd != curl_thread_t_null)
         Curl_thread_join(&td->thread_hnd);
 
@@ -407,7 +586,7 @@ static void destroy_async_data(struct Curl_async *async)
      * before the FD is invalidated to avoid EBADF on EPOLL_CTL_DEL
      */
     Curl_multi_closed(data, sock_rd);
-    sclose(sock_rd);
+    wakeup_close(sock_rd);
 #endif
   }
   async->tdata = NULL;
@@ -439,6 +618,9 @@ static bool init_resolve_thread(struct Curl_easy *data,
   asp->status = 0;
   asp->dns = NULL;
   td->thread_hnd = curl_thread_t_null;
+#ifdef _WIN32
+  td->complete_ev = NULL;
+#endif
 
   if(!init_thread_sync_data(td, hostname, port, hints)) {
     asp->tdata = NULL;
@@ -454,13 +636,48 @@ static bool init_resolve_thread(struct Curl_easy *data,
   /* The thread will set this to 1 when complete. */
   td->tsd.done = 0;
 
+#ifdef _WIN32
+  if(Curl_isWindows8OrGreater && Curl_FreeAddrInfoExW &&
+     Curl_GetAddrInfoExCancel && Curl_GetAddrInfoExW) {
+#define MAX_NAME_LEN 256 /* max domain name is 253 chars */
+#define MAX_PORT_LEN 8
+    WCHAR namebuf[MAX_NAME_LEN];
+    WCHAR portbuf[MAX_PORT_LEN];
+    /* calculate required length */
+    int w_len = MultiByteToWideChar(CP_UTF8, MB_ERR_INVALID_CHARS, hostname,
+                                    -1, NULL, 0);
+    if((w_len > 0) && (w_len < MAX_NAME_LEN)) {
+      /* do utf8 conversion */
+      w_len = MultiByteToWideChar(CP_UTF8, 0, hostname, -1, namebuf, w_len);
+      if((w_len > 0) && (w_len < MAX_NAME_LEN)) {
+        swprintf(portbuf, MAX_PORT_LEN, L"%d", port);
+        td->tsd.w8.hints.ai_family = hints->ai_family;
+        td->tsd.w8.hints.ai_socktype = hints->ai_socktype;
+        td->complete_ev = CreateEvent(NULL, TRUE, FALSE, NULL);
+        if(!td->complete_ev) {
+          /* failed to start, mark it as done here for proper cleanup. */
+          td->tsd.done = 1;
+          goto err_exit;
+        }
+        err = Curl_GetAddrInfoExW(namebuf, portbuf, NS_DNS,
+                                  NULL, &td->tsd.w8.hints, &td->tsd.w8.res,
+                                  NULL, &td->tsd.w8.overlapped,
+                                  &query_complete, &td->tsd.w8.cancel_ev);
+        if(err != WSA_IO_PENDING)
+          query_complete(err, 0, &td->tsd.w8.overlapped);
+        return TRUE;
+      }
+    }
+  }
+#endif
+
 #ifdef HAVE_GETADDRINFO
   td->thread_hnd = Curl_thread_create(getaddrinfo_thread, &td->tsd);
 #else
   td->thread_hnd = Curl_thread_create(gethostbyname_thread, &td->tsd);
 #endif
 
-  if(!td->thread_hnd) {
+  if(td->thread_hnd == curl_thread_t_null) {
     /* The thread never started, so mark it as done here for proper cleanup. */
     td->tsd.done = 1;
     err = errno;
@@ -490,9 +707,23 @@ static CURLcode thread_wait_resolv(struct Curl_easy *data,
   DEBUGASSERT(data);
   td = data->state.async.tdata;
   DEBUGASSERT(td);
+#ifdef _WIN32
+  DEBUGASSERT(td->complete_ev || td->thread_hnd != curl_thread_t_null);
+#else
   DEBUGASSERT(td->thread_hnd != curl_thread_t_null);
+#endif
 
   /* wait for the thread to resolve the name */
+#ifdef _WIN32
+  if(td->complete_ev) {
+    WaitForSingleObject(td->complete_ev, INFINITE);
+    CloseHandle(td->complete_ev);
+    td->complete_ev = NULL;
+    if(entry)
+      result = getaddrinfo_complete(data);
+  }
+  else
+#endif
   if(Curl_thread_join(&td->thread_hnd)) {
     if(entry)
       result = getaddrinfo_complete(data);
@@ -529,6 +760,13 @@ void Curl_resolver_kill(struct Curl_easy *data)
   /* If we're still resolving, we must wait for the threads to fully clean up,
      unfortunately.  Otherwise, we can simply cancel to clean up any resolver
      data. */
+#ifdef _WIN32
+  if(td && td->complete_ev) {
+    Curl_GetAddrInfoExCancel(&td->tsd.w8.cancel_ev);
+    (void)thread_wait_resolv(data, NULL, FALSE);
+  }
+  else
+#endif
   if(td && td->thread_hnd != curl_thread_t_null
      && (data->set.quick_exit != 1L))
     (void)thread_wait_resolv(data, NULL, FALSE);
diff --git a/vendor/curl/lib/base64.c b/vendor/curl/lib/base64.c
index 30db7e5889..8373115d20 100644
--- a/vendor/curl/lib/base64.c
+++ b/vendor/curl/lib/base64.c
@@ -31,7 +31,8 @@
   !defined(CURL_DISABLE_SMTP) || \
   !defined(CURL_DISABLE_POP3) || \
   !defined(CURL_DISABLE_IMAP) || \
-  !defined(CURL_DISABLE_DOH) || defined(USE_SSL)
+  !defined(CURL_DISABLE_DIGEST_AUTH) || \
+  !defined(CURL_DISABLE_DOH) || defined(USE_SSL) || defined(BUILDING_CURL)
 #include "curl/curl.h"
 #include "warnless.h"
 #include "curl_base64.h"
@@ -242,7 +243,7 @@ static CURLcode base64_encode(const char *table64,
   *outptr = base64data;
 
   /* Return the length of the new data */
-  *outlen = output - base64data;
+  *outlen = (size_t)(output - base64data);
 
   return CURLE_OK;
 }
diff --git a/vendor/curl/lib/bufq.c b/vendor/curl/lib/bufq.c
index 155544993d..c3245516c9 100644
--- a/vendor/curl/lib/bufq.c
+++ b/vendor/curl/lib/bufq.c
@@ -144,21 +144,6 @@ static size_t chunk_skip(struct buf_chunk *chunk, size_t amount)
   return n;
 }
 
-static void chunk_shift(struct buf_chunk *chunk)
-{
-  if(chunk->r_offset) {
-    if(!chunk_is_empty(chunk)) {
-      size_t n = chunk->w_offset - chunk->r_offset;
-      memmove(chunk->x.data, chunk->x.data + chunk->r_offset, n);
-      chunk->w_offset -= chunk->r_offset;
-      chunk->r_offset = 0;
-    }
-    else {
-      chunk->r_offset = chunk->w_offset = 0;
-    }
-  }
-}
-
 static void chunk_list_free(struct buf_chunk **anchor)
 {
   struct buf_chunk *chunk;
@@ -411,7 +396,7 @@ ssize_t Curl_bufq_write(struct bufq *q,
   while(len) {
     tail = get_non_full_tail(q);
     if(!tail) {
-      if(q->chunk_count < q->max_chunks) {
+      if((q->chunk_count < q->max_chunks) || (q->opts & BUFQ_OPT_SOFT_LIMIT)) {
         *err = CURLE_OUT_OF_MEMORY;
         return -1;
       }
@@ -432,6 +417,17 @@ ssize_t Curl_bufq_write(struct bufq *q,
   return nwritten;
 }
 
+CURLcode Curl_bufq_cwrite(struct bufq *q,
+                          const char *buf, size_t len,
+                          size_t *pnwritten)
+{
+  ssize_t n;
+  CURLcode result;
+  n = Curl_bufq_write(q, (const unsigned char *)buf, len, &result);
+  *pnwritten = (n < 0)? 0 : (size_t)n;
+  return result;
+}
+
 ssize_t Curl_bufq_read(struct bufq *q, unsigned char *buf, size_t len,
                        CURLcode *err)
 {
@@ -455,6 +451,16 @@ ssize_t Curl_bufq_read(struct bufq *q, unsigned char *buf, size_t len,
   return nread;
 }
 
+CURLcode Curl_bufq_cread(struct bufq *q, char *buf, size_t len,
+                         size_t *pnread)
+{
+  ssize_t n;
+  CURLcode result;
+  n = Curl_bufq_read(q, (unsigned char *)buf, len, &result);
+  *pnread = (n < 0)? 0 : (size_t)n;
+  return result;
+}
+
 bool Curl_bufq_peek(struct bufq *q,
                     const unsigned char **pbuf, size_t *plen)
 {
@@ -504,13 +510,6 @@ void Curl_bufq_skip(struct bufq *q, size_t amount)
   }
 }
 
-void Curl_bufq_skip_and_shift(struct bufq *q, size_t amount)
-{
-  Curl_bufq_skip(q, amount);
-  if(q->tail)
-    chunk_shift(q->tail);
-}
-
 ssize_t Curl_bufq_pass(struct bufq *q, Curl_bufq_writer *writer,
                        void *writer_ctx, CURLcode *err)
 {
diff --git a/vendor/curl/lib/bufq.h b/vendor/curl/lib/bufq.h
index 89b5c84efe..87ffa45da2 100644
--- a/vendor/curl/lib/bufq.h
+++ b/vendor/curl/lib/bufq.h
@@ -85,7 +85,7 @@ void Curl_bufcp_free(struct bufc_pool *pool);
  * preferably never fail (except for memory exhaustion).
  *
  * By default and without a pool, a bufq will keep chunks that read
- * read empty in its `spare` list. Option `BUFQ_OPT_NO_SPARES` will
+ * empty in its `spare` list. Option `BUFQ_OPT_NO_SPARES` will
  * disable that and free chunks once they become empty.
  *
  * When providing a pool to a bufq, all chunk creation and spare handling
@@ -178,6 +178,10 @@ ssize_t Curl_bufq_write(struct bufq *q,
                         const unsigned char *buf, size_t len,
                         CURLcode *err);
 
+CURLcode Curl_bufq_cwrite(struct bufq *q,
+                         const char *buf, size_t len,
+                         size_t *pnwritten);
+
 /**
  * Read buf from the start of the buffer queue. The buf is copied
  * and the amount of copied bytes is returned.
@@ -187,6 +191,9 @@ ssize_t Curl_bufq_write(struct bufq *q,
 ssize_t Curl_bufq_read(struct bufq *q, unsigned char *buf, size_t len,
                         CURLcode *err);
 
+CURLcode Curl_bufq_cread(struct bufq *q, char *buf, size_t len,
+                         size_t *pnread);
+
 /**
  * Peek at the head chunk in the buffer queue. Returns a pointer to
  * the chunk buf (at the current offset) and its length. Does not
@@ -209,12 +216,6 @@ bool Curl_bufq_peek_at(struct bufq *q, size_t offset,
  */
 void Curl_bufq_skip(struct bufq *q, size_t amount);
 
-/**
- * Same as `skip` but shift tail data to the start afterwards,
- * so that further writes will find room in tail.
- */
-void Curl_bufq_skip_and_shift(struct bufq *q, size_t amount);
-
 typedef ssize_t Curl_bufq_writer(void *writer_ctx,
                                  const unsigned char *buf, size_t len,
                                  CURLcode *err);
diff --git a/vendor/curl/lib/bufref.c b/vendor/curl/lib/bufref.c
index ce686b6f37..f0a0e2a7de 100644
--- a/vendor/curl/lib/bufref.c
+++ b/vendor/curl/lib/bufref.c
@@ -25,6 +25,7 @@
 #include "curl_setup.h"
 #include "urldata.h"
 #include "bufref.h"
+#include "strdup.h"
 
 #include "curl_memory.h"
 #include "memdebug.h"
@@ -116,12 +117,9 @@ CURLcode Curl_bufref_memdup(struct bufref *br, const void *ptr, size_t len)
   DEBUGASSERT(len <= CURL_MAX_INPUT_LENGTH);
 
   if(ptr) {
-    cpy = malloc(len + 1);
+    cpy = Curl_memdup0(ptr, len);
     if(!cpy)
       return CURLE_OUT_OF_MEMORY;
-    if(len)
-      memcpy(cpy, ptr, len);
-    cpy[len] = '\0';
   }
 
   Curl_bufref_set(br, cpy, len, curl_free);
diff --git a/vendor/curl/lib/c-hyper.c b/vendor/curl/lib/c-hyper.c
index 61ca29a3ac..0593d97065 100644
--- a/vendor/curl/lib/c-hyper.c
+++ b/vendor/curl/lib/c-hyper.c
@@ -22,6 +22,10 @@
  *
  ***************************************************************************/
 
+/* Curl's integration with Hyper. This replaces certain functions in http.c,
+ * based on configuration #defines. This implementation supports HTTP/1.1 but
+ * not HTTP/2.
+ */
 #include "curl_setup.h"
 
 #if !defined(CURL_DISABLE_HTTP) && defined(USE_HYPER)
@@ -49,7 +53,9 @@
 
 #include 
 #include "urldata.h"
+#include "cfilters.h"
 #include "sendf.h"
+#include "headers.h"
 #include "transfer.h"
 #include "multiif.h"
 #include "progress.h"
@@ -61,6 +67,9 @@
 #include "curl_memory.h"
 #include "memdebug.h"
 
+
+static CURLcode cr_hyper_add(struct Curl_easy *data);
+
 typedef enum {
     USERDATA_NOT_SET = 0, /* for tasks with no userdata set; must be zero */
     USERDATA_RESP_BODY
@@ -69,7 +78,8 @@ typedef enum {
 size_t Curl_hyper_recv(void *userp, hyper_context *ctx,
                        uint8_t *buf, size_t buflen)
 {
-  struct Curl_easy *data = userp;
+  struct hyp_io_ctx *io_ctx = userp;
+  struct Curl_easy *data = io_ctx->data;
   struct connectdata *conn = data->conn;
   CURLcode result;
   ssize_t nread;
@@ -77,7 +87,8 @@ size_t Curl_hyper_recv(void *userp, hyper_context *ctx,
   (void)ctx;
 
   DEBUGF(infof(data, "Curl_hyper_recv(%zu)", buflen));
-  result = Curl_read(data, conn->sockfd, (char *)buf, buflen, &nread);
+  result = Curl_conn_recv(data, io_ctx->sockindex,
+                          (char *)buf, buflen, &nread);
   if(result == CURLE_AGAIN) {
     /* would block, register interest */
     DEBUGF(infof(data, "Curl_hyper_recv(%zu) -> EAGAIN", buflen));
@@ -101,15 +112,14 @@ size_t Curl_hyper_recv(void *userp, hyper_context *ctx,
 size_t Curl_hyper_send(void *userp, hyper_context *ctx,
                        const uint8_t *buf, size_t buflen)
 {
-  struct Curl_easy *data = userp;
-  struct connectdata *conn = data->conn;
+  struct hyp_io_ctx *io_ctx = userp;
+  struct Curl_easy *data = io_ctx->data;
   CURLcode result;
-  ssize_t nwrote;
+  size_t nwrote;
 
   DEBUGF(infof(data, "Curl_hyper_send(%zu)", buflen));
-  result = Curl_write(data, conn->sockfd, (void *)buf, buflen, &nwrote);
-  if(!result && !nwrote)
-    result = CURLE_AGAIN;
+  result = Curl_conn_send(data, io_ctx->sockindex,
+                          (void *)buf, buflen, &nwrote);
   if(result == CURLE_AGAIN) {
     DEBUGF(infof(data, "Curl_hyper_send(%zu) -> EAGAIN", buflen));
     /* would block, register interest */
@@ -144,13 +154,10 @@ static int hyper_each_header(void *userdata,
 
   if(name_len + value_len + 2 > CURL_MAX_HTTP_HEADER) {
     failf(data, "Too long response header");
-    data->state.hresult = CURLE_OUT_OF_MEMORY;
+    data->state.hresult = CURLE_TOO_LARGE;
     return HYPER_ITER_BREAK;
   }
 
-  if(!data->req.bytecount)
-    Curl_pgrsTime(data, TIMER_STARTTRANSFER);
-
   Curl_dyn_reset(&data->state.headerb);
   if(name_len) {
     if(Curl_dyn_addf(&data->state.headerb, "%.*s: %.*s\r\n",
@@ -164,7 +171,7 @@ static int hyper_each_header(void *userdata,
   len = Curl_dyn_len(&data->state.headerb);
   headp = Curl_dyn_ptr(&data->state.headerb);
 
-  result = Curl_http_header(data, data->conn, headp);
+  result = Curl_http_header(data, headp, len);
   if(result) {
     data->state.hresult = result;
     return HYPER_ITER_BREAK;
@@ -172,19 +179,15 @@ static int hyper_each_header(void *userdata,
 
   Curl_debug(data, CURLINFO_HEADER_IN, headp, len);
 
-  if(!data->state.hconnect || !data->set.suppress_connect_headers) {
-    writetype = CLIENTWRITE_HEADER;
-    if(data->set.include_header)
-      writetype |= CLIENTWRITE_BODY;
-    if(data->state.hconnect)
-      writetype |= CLIENTWRITE_CONNECT;
-    if(data->req.httpcode/100 == 1)
-      writetype |= CLIENTWRITE_1XX;
-    result = Curl_client_write(data, writetype, headp, len);
-    if(result) {
-      data->state.hresult = CURLE_ABORTED_BY_CALLBACK;
-      return HYPER_ITER_BREAK;
-    }
+  writetype = CLIENTWRITE_HEADER;
+  if(data->state.hconnect)
+    writetype |= CLIENTWRITE_CONNECT;
+  if(data->req.httpcode/100 == 1)
+    writetype |= CLIENTWRITE_1XX;
+  result = Curl_client_write(data, writetype, headp, len);
+  if(result) {
+    data->state.hresult = CURLE_ABORTED_BY_CALLBACK;
+    return HYPER_ITER_BREAK;
   }
 
   result = Curl_bump_headersize(data, len, FALSE);
@@ -203,8 +206,7 @@ static int hyper_body_chunk(void *userdata, const hyper_buf *chunk)
   struct SingleRequest *k = &data->req;
   CURLcode result = CURLE_OK;
 
-  if(0 == k->bodywrites++) {
-    bool done = FALSE;
+  if(0 == k->bodywrites) {
 #if defined(USE_NTLM)
     struct connectdata *conn = data->conn;
     if(conn->bits.close &&
@@ -217,50 +219,38 @@ static int hyper_body_chunk(void *userdata, const hyper_buf *chunk)
       Curl_safefree(data->req.newurl);
     }
 #endif
-    if(data->state.expect100header) {
-      Curl_expire_done(data, EXPIRE_100_TIMEOUT);
+    if(Curl_http_exp100_is_selected(data)) {
       if(data->req.httpcode < 400) {
-        k->exp100 = EXP100_SEND_DATA;
-        if(data->hyp.exp100_waker) {
-          hyper_waker_wake(data->hyp.exp100_waker);
-          data->hyp.exp100_waker = NULL;
+        Curl_http_exp100_got100(data);
+        if(data->hyp.send_body_waker) {
+          hyper_waker_wake(data->hyp.send_body_waker);
+          data->hyp.send_body_waker = NULL;
         }
       }
       else { /* >= 4xx */
-        k->exp100 = EXP100_FAILED;
+        Curl_req_abort_sending(data);
       }
     }
     if(data->state.hconnect && (data->req.httpcode/100 != 2) &&
        data->state.authproxy.done) {
-      done = TRUE;
+      data->req.done = TRUE;
       result = CURLE_OK;
     }
     else
-      result = Curl_http_firstwrite(data, data->conn, &done);
-    if(result || done) {
+      result = Curl_http_firstwrite(data);
+    if(result || data->req.done) {
       infof(data, "Return early from hyper_body_chunk");
       data->state.hresult = result;
       return HYPER_ITER_BREAK;
     }
   }
-  if(k->ignorebody)
-    return HYPER_ITER_CONTINUE;
-  if(0 == len)
-    return HYPER_ITER_CONTINUE;
-  Curl_debug(data, CURLINFO_DATA_IN, buf, len);
-  if(!data->set.http_ce_skip && k->writer_stack)
-    /* content-encoded data */
-    result = Curl_unencode_write(data, k->writer_stack, buf, len);
-  else
-    result = Curl_client_write(data, CLIENTWRITE_BODY, buf, len);
+  result = Curl_client_write(data, CLIENTWRITE_BODY, buf, len);
 
   if(result) {
     data->state.hresult = result;
     return HYPER_ITER_BREAK;
   }
 
-  data->req.bytecount += len;
-  Curl_pgrsSetDownloadCounter(data, data->req.bytecount);
   return HYPER_ITER_CONTINUE;
 }
 
@@ -284,14 +274,13 @@ static CURLcode status_line(struct Curl_easy *data,
   /* We need to set 'httpcodeq' for functions that check the response code in
      a single place. */
   data->req.httpcode = http_status;
-
+  data->req.httpversion = http_version == HYPER_HTTP_VERSION_1_1? 11 :
+                          (http_version == HYPER_HTTP_VERSION_2 ? 20 : 10);
   if(data->state.hconnect)
     /* CONNECT */
     data->info.httpproxycode = http_status;
   else {
-    conn->httpversion =
-      http_version == HYPER_HTTP_VERSION_1_1 ? 11 :
-      (http_version == HYPER_HTTP_VERSION_2 ? 20 : 10);
+    conn->httpversion = (unsigned char)data->req.httpversion;
     if(http_version == HYPER_HTTP_VERSION_1_0)
       data->state.httpwant = CURL_HTTP_VERSION_1_0;
 
@@ -312,15 +301,14 @@ static CURLcode status_line(struct Curl_easy *data,
   Curl_debug(data, CURLINFO_HEADER_IN, Curl_dyn_ptr(&data->state.headerb),
              len);
 
-  if(!data->state.hconnect || !data->set.suppress_connect_headers) {
-    writetype = CLIENTWRITE_HEADER|CLIENTWRITE_STATUS;
-    if(data->set.include_header)
-      writetype |= CLIENTWRITE_BODY;
-    result = Curl_client_write(data, writetype,
-                               Curl_dyn_ptr(&data->state.headerb), len);
-    if(result)
-      return result;
-  }
+  writetype = CLIENTWRITE_HEADER|CLIENTWRITE_STATUS;
+  if(data->state.hconnect)
+    writetype |= CLIENTWRITE_CONNECT;
+  result = Curl_client_write(data, writetype,
+                             Curl_dyn_ptr(&data->state.headerb), len);
+  if(result)
+    return result;
+
   result = Curl_bump_headersize(data, len, FALSE);
   return result;
 }
@@ -337,6 +325,9 @@ static CURLcode empty_header(struct Curl_easy *data)
       CURLE_WRITE_ERROR : CURLE_OK;
     if(result)
       failf(data, "hyperstream: couldn't pass blank header");
+    /* Hyper does chunked decoding itself. If it was added during
+     * response header processing, remove it again. */
+    Curl_cwriter_remove_by_name(data, "chunked");
   }
   return result;
 }
@@ -344,7 +335,6 @@ static CURLcode empty_header(struct Curl_easy *data)
 CURLcode Curl_hyper_stream(struct Curl_easy *data,
                            struct connectdata *conn,
                            int *didwhat,
-                           bool *done,
                            int select_res)
 {
   hyper_response *resp = NULL;
@@ -361,20 +351,9 @@ CURLcode Curl_hyper_stream(struct Curl_easy *data,
   struct SingleRequest *k = &data->req;
   (void)conn;
 
-  if(k->exp100 > EXP100_SEND_DATA) {
-    struct curltime now = Curl_now();
-    timediff_t ms = Curl_timediff(now, k->start100);
-    if(ms >= data->set.expect_100_timeout) {
-      /* we've waited long enough, continue anyway */
-      k->exp100 = EXP100_SEND_DATA;
-      k->keepon |= KEEP_SEND;
-      Curl_expire_done(data, EXPIRE_100_TIMEOUT);
-      infof(data, "Done waiting for 100-continue");
-      if(data->hyp.exp100_waker) {
-        hyper_waker_wake(data->hyp.exp100_waker);
-        data->hyp.exp100_waker = NULL;
-      }
-    }
+  if(data->hyp.send_body_waker) {
+    hyper_waker_wake(data->hyp.send_body_waker);
+    data->hyp.send_body_waker = NULL;
   }
 
   if(select_res & CURL_CSELECT_IN) {
@@ -388,7 +367,6 @@ CURLcode Curl_hyper_stream(struct Curl_easy *data,
     h->write_waker = NULL;
   }
 
-  *done = FALSE;
   do {
     hyper_task_return_type t;
     task = hyper_executor_poll(h->exec);
@@ -431,7 +409,7 @@ CURLcode Curl_hyper_stream(struct Curl_easy *data,
           break;
         }
       }
-      *done = TRUE;
+      data->req.done = TRUE;
       hyper_error_free(hypererr);
       break;
     }
@@ -440,12 +418,11 @@ CURLcode Curl_hyper_stream(struct Curl_easy *data,
       hyper_task_free(task);
       if((userdata_t)userdata == USERDATA_RESP_BODY) {
         /* end of transfer */
-        *done = TRUE;
+        data->req.done = TRUE;
         infof(data, "hyperstream is done");
         if(!k->bodywrites) {
           /* hyper doesn't always call the body write callback */
-          bool stilldone;
-          result = Curl_http_firstwrite(data, data->conn, &stilldone);
+          result = Curl_http_firstwrite(data);
         }
         break;
       }
@@ -471,11 +448,11 @@ CURLcode Curl_hyper_stream(struct Curl_easy *data,
     reasonp = hyper_response_reason_phrase(resp);
     reason_len = hyper_response_reason_phrase_len(resp);
 
-    if(http_status == 417 && data->state.expect100header) {
+    if(http_status == 417 && Curl_http_exp100_is_selected(data)) {
       infof(data, "Got 417 while waiting for a 100");
       data->state.disableexpect = TRUE;
       data->req.newurl = strdup(data->state.url);
-      Curl_done_sending(data, k);
+      Curl_req_abort_sending(data);
     }
 
     result = status_line(data, conn,
@@ -555,11 +532,9 @@ CURLcode Curl_hyper_stream(struct Curl_easy *data,
 
 static CURLcode debug_request(struct Curl_easy *data,
                               const char *method,
-                              const char *path,
-                              bool h2)
+                              const char *path)
 {
-  char *req = aprintf("%s %s HTTP/%s\r\n", method, path,
-                      h2?"2":"1.1");
+  char *req = aprintf("%s %s HTTP/1.1\r\n", method, path);
   if(!req)
     return CURLE_OUT_OF_MEMORY;
   Curl_debug(data, CURLINFO_HEADER_OUT, req, strlen(req));
@@ -641,7 +616,6 @@ CURLcode Curl_hyper_header(struct Curl_easy *data, hyper_headers *headers,
 static CURLcode request_target(struct Curl_easy *data,
                                struct connectdata *conn,
                                const char *method,
-                               bool h2,
                                hyper_request *req)
 {
   CURLcode result;
@@ -653,141 +627,79 @@ static CURLcode request_target(struct Curl_easy *data,
   if(result)
     return result;
 
-  if(h2 && hyper_request_set_uri_parts(req,
-                                       /* scheme */
-                                       (uint8_t *)data->state.up.scheme,
-                                       strlen(data->state.up.scheme),
-                                       /* authority */
-                                       (uint8_t *)conn->host.name,
-                                       strlen(conn->host.name),
-                                       /* path_and_query */
-                                       (uint8_t *)Curl_dyn_uptr(&r),
-                                       Curl_dyn_len(&r))) {
-    failf(data, "error setting uri parts to hyper");
-    result = CURLE_OUT_OF_MEMORY;
-  }
-  else if(!h2 && hyper_request_set_uri(req, (uint8_t *)Curl_dyn_uptr(&r),
+  if(hyper_request_set_uri(req, (uint8_t *)Curl_dyn_uptr(&r),
                                        Curl_dyn_len(&r))) {
     failf(data, "error setting uri to hyper");
     result = CURLE_OUT_OF_MEMORY;
   }
   else
-    result = debug_request(data, method, Curl_dyn_ptr(&r), h2);
+    result = debug_request(data, method, Curl_dyn_ptr(&r));
 
   Curl_dyn_free(&r);
 
   return result;
 }
 
-static int uploadpostfields(void *userdata, hyper_context *ctx,
-                            hyper_buf **chunk)
-{
-  struct Curl_easy *data = (struct Curl_easy *)userdata;
-  (void)ctx;
-  if(data->req.exp100 > EXP100_SEND_DATA) {
-    if(data->req.exp100 == EXP100_FAILED)
-      return HYPER_POLL_ERROR;
-
-    /* still waiting confirmation */
-    if(data->hyp.exp100_waker)
-      hyper_waker_free(data->hyp.exp100_waker);
-    data->hyp.exp100_waker = hyper_context_waker(ctx);
-    return HYPER_POLL_PENDING;
-  }
-  if(data->req.upload_done)
-    *chunk = NULL; /* nothing more to deliver */
-  else {
-    /* send everything off in a single go */
-    hyper_buf *copy = hyper_buf_copy(data->set.postfields,
-                                     (size_t)data->req.p.http->postsize);
-    if(copy)
-      *chunk = copy;
-    else {
-      data->state.hresult = CURLE_OUT_OF_MEMORY;
-      return HYPER_POLL_ERROR;
-    }
-    /* increasing the writebytecount here is a little premature but we
-       don't know exactly when the body is sent */
-    data->req.writebytecount += (size_t)data->req.p.http->postsize;
-    Curl_pgrsSetUploadCounter(data, data->req.writebytecount);
-    data->req.upload_done = TRUE;
-  }
-  return HYPER_POLL_READY;
-}
-
 static int uploadstreamed(void *userdata, hyper_context *ctx,
                           hyper_buf **chunk)
 {
   size_t fillcount;
   struct Curl_easy *data = (struct Curl_easy *)userdata;
-  struct connectdata *conn = (struct connectdata *)data->conn;
   CURLcode result;
+  char *xfer_ulbuf;
+  size_t xfer_ulblen;
+  bool eos;
+  int rc = HYPER_POLL_ERROR;
   (void)ctx;
 
-  if(data->req.exp100 > EXP100_SEND_DATA) {
-    if(data->req.exp100 == EXP100_FAILED)
-      return HYPER_POLL_ERROR;
+  result = Curl_multi_xfer_ulbuf_borrow(data, &xfer_ulbuf, &xfer_ulblen);
+  if(result)
+    goto out;
 
-    /* still waiting confirmation */
-    if(data->hyp.exp100_waker)
-      hyper_waker_free(data->hyp.exp100_waker);
-    data->hyp.exp100_waker = hyper_context_waker(ctx);
-    return HYPER_POLL_PENDING;
-  }
+  result = Curl_client_read(data, xfer_ulbuf, xfer_ulblen, &fillcount, &eos);
+  if(result)
+    goto out;
 
-  if(data->req.upload_chunky && conn->bits.authneg) {
-    fillcount = 0;
-    data->req.upload_chunky = FALSE;
-    result = CURLE_OK;
-  }
-  else {
-    result = Curl_fillreadbuffer(data, data->set.upload_buffer_size,
-                                 &fillcount);
-  }
-  if(result) {
-    data->state.hresult = result;
-    return HYPER_POLL_ERROR;
-  }
-  if(!fillcount) {
-    if((data->req.keepon & KEEP_SEND_PAUSE) != KEEP_SEND_PAUSE)
-      /* done! */
-      *chunk = NULL;
-    else {
-      /* paused, save a waker */
-      if(data->hyp.send_body_waker)
-        hyper_waker_free(data->hyp.send_body_waker);
-      data->hyp.send_body_waker = hyper_context_waker(ctx);
-      return HYPER_POLL_PENDING;
-    }
-  }
-  else {
-    hyper_buf *copy = hyper_buf_copy((uint8_t *)data->state.ulbuf, fillcount);
+  if(fillcount) {
+    hyper_buf *copy = hyper_buf_copy((uint8_t *)xfer_ulbuf, fillcount);
     if(copy)
       *chunk = copy;
     else {
-      data->state.hresult = CURLE_OUT_OF_MEMORY;
-      return HYPER_POLL_ERROR;
+      result = CURLE_OUT_OF_MEMORY;
+      goto out;
     }
     /* increasing the writebytecount here is a little premature but we
        don't know exactly when the body is sent */
     data->req.writebytecount += fillcount;
     Curl_pgrsSetUploadCounter(data, data->req.writebytecount);
+    rc = HYPER_POLL_READY;
+  }
+  else if(eos) {
+    *chunk = NULL;
+    rc = HYPER_POLL_READY;
   }
-  return HYPER_POLL_READY;
+  else {
+    /* paused, save a waker */
+    if(data->hyp.send_body_waker)
+      hyper_waker_free(data->hyp.send_body_waker);
+    data->hyp.send_body_waker = hyper_context_waker(ctx);
+    rc = HYPER_POLL_PENDING;
+  }
+
+out:
+  Curl_multi_xfer_ulbuf_release(data, xfer_ulbuf);
+  data->state.hresult = result;
+  return rc;
 }
 
 /*
- * bodysend() sets up headers in the outgoing request for an HTTP transfer that
- * sends a body
+ * finalize_request() sets up last headers and optional body settings
  */
-
-static CURLcode bodysend(struct Curl_easy *data,
-                         struct connectdata *conn,
-                         hyper_headers *headers,
-                         hyper_request *hyperreq,
-                         Curl_HttpReq httpreq)
+static CURLcode finalize_request(struct Curl_easy *data,
+                                 hyper_headers *headers,
+                                 hyper_request *hyperreq,
+                                 Curl_HttpReq httpreq)
 {
-  struct HTTP *http = data->req.p.http;
   CURLcode result = CURLE_OK;
   struct dynbuf req;
   if((httpreq == HTTPREQ_GET) || (httpreq == HTTPREQ_HEAD))
@@ -795,34 +707,31 @@ static CURLcode bodysend(struct Curl_easy *data,
   else {
     hyper_body *body;
     Curl_dyn_init(&req, DYN_HTTP_REQUEST);
-    result = Curl_http_bodysend(data, conn, &req, httpreq);
+    result = Curl_http_req_complete(data, &req, httpreq);
+    if(result)
+      return result;
 
-    if(!result)
+    /* if the "complete" above did produce more than the closing line,
+       parse the added headers */
+    if(Curl_dyn_len(&req) != 2 || strcmp(Curl_dyn_ptr(&req), "\r\n")) {
       result = Curl_hyper_header(data, headers, Curl_dyn_ptr(&req));
+      if(result)
+        return result;
+    }
 
     Curl_dyn_free(&req);
 
     body = hyper_body_new();
     hyper_body_set_userdata(body, data);
-    if(data->set.postfields)
-      hyper_body_set_data_func(body, uploadpostfields);
-    else {
-      result = Curl_get_upload_buffer(data);
-      if(result) {
-        hyper_body_free(body);
-        return result;
-      }
-      /* init the "upload from here" pointer */
-      data->req.upload_fromhere = data->state.ulbuf;
-      hyper_body_set_data_func(body, uploadstreamed);
-    }
+    hyper_body_set_data_func(body, uploadstreamed);
+
     if(HYPERE_OK != hyper_request_set_body(hyperreq, body)) {
       /* fail */
       result = CURLE_OUT_OF_MEMORY;
     }
   }
-  http->sending = HTTPSEND_BODY;
-  return result;
+
+  return cr_hyper_add(data);
 }
 
 static CURLcode cookies(struct Curl_easy *data,
@@ -903,7 +812,6 @@ CURLcode Curl_http(struct Curl_easy *data, bool *done)
   const char *p_accept; /* Accept: string */
   const char *method;
   Curl_HttpReq httpreq;
-  bool h2 = FALSE;
   const char *te = NULL; /* transfer-encoding */
   hyper_code rc;
 
@@ -911,6 +819,16 @@ CURLcode Curl_http(struct Curl_easy *data, bool *done)
      may be parts of the request that is not yet sent, since we can deal with
      the rest of the request in the PERFORM phase. */
   *done = TRUE;
+  result = Curl_client_start(data);
+  if(result)
+    return result;
+
+  /* Add collecting of headers written to client. For a new connection,
+   * we might have done that already, but reuse
+   * or multiplex needs it here as well. */
+  result = Curl_headers_init(data);
+  if(result)
+    return result;
 
   infof(data, "Time for the Hyper dance");
   memset(h, 0, sizeof(struct hyptransfer));
@@ -921,6 +839,8 @@ CURLcode Curl_http(struct Curl_easy *data, bool *done)
 
   Curl_http_method(data, conn, &method, &httpreq);
 
+  DEBUGASSERT(data->req.bytecount ==  0);
+
   /* setup the authentication headers */
   {
     char *pq = NULL;
@@ -936,9 +856,9 @@ CURLcode Curl_http(struct Curl_easy *data, bool *done)
       return result;
   }
 
-  result = Curl_http_resume(data, conn, httpreq);
+  result = Curl_http_req_set_reader(data, httpreq, &te);
   if(result)
-    return result;
+    goto error;
 
   result = Curl_http_range(data, httpreq);
   if(result)
@@ -955,7 +875,9 @@ CURLcode Curl_http(struct Curl_easy *data, bool *done)
     goto error;
   }
   /* tell Hyper how to read/write network data */
-  hyper_io_set_userdata(io, data);
+  h->io_ctx.data = data;
+  h->io_ctx.sockindex = FIRSTSOCKET;
+  hyper_io_set_userdata(io, &h->io_ctx);
   hyper_io_set_read(io, Curl_hyper_recv);
   hyper_io_set_write(io, Curl_hyper_send);
 
@@ -976,8 +898,9 @@ CURLcode Curl_http(struct Curl_easy *data, bool *done)
     goto error;
   }
   if(conn->alpn == CURL_HTTP_VERSION_2) {
-    hyper_clientconn_options_http2(options, 1);
-    h2 = TRUE;
+    failf(data, "ALPN protocol h2 not supported with Hyper");
+    result = CURLE_UNSUPPORTED_PROTOCOL;
+    goto error;
   }
   hyper_clientconn_options_set_preserve_header_case(options, 1);
   hyper_clientconn_options_set_preserve_header_order(options, 1);
@@ -1027,11 +950,6 @@ CURLcode Curl_http(struct Curl_easy *data, bool *done)
       goto error;
     }
   }
-  else {
-    if(!h2 && !data->state.disableexpect) {
-      data->state.expect100header = TRUE;
-    }
-  }
 
   if(hyper_request_set_method(req, (uint8_t *)method, strlen(method))) {
     failf(data, "error setting method");
@@ -1039,7 +957,7 @@ CURLcode Curl_http(struct Curl_easy *data, bool *done)
     goto error;
   }
 
-  result = request_target(data, conn, method, h2, req);
+  result = request_target(data, conn, method, req);
   if(result)
     goto error;
 
@@ -1056,30 +974,19 @@ CURLcode Curl_http(struct Curl_easy *data, bool *done)
     goto error;
   }
 
-  result = Curl_http_body(data, conn, httpreq, &te);
-  if(result)
-    goto error;
-
-  if(!h2) {
-    if(data->state.aptr.host) {
-      result = Curl_hyper_header(data, headers, data->state.aptr.host);
-      if(result)
-        goto error;
-    }
-  }
-  else {
-    /* For HTTP/2, we show the Host: header as if we sent it, to make it look
-       like for HTTP/1 but it isn't actually sent since :authority is then
-       used. */
-    Curl_debug(data, CURLINFO_HEADER_OUT, data->state.aptr.host,
-               strlen(data->state.aptr.host));
+  if(data->state.aptr.host) {
+    result = Curl_hyper_header(data, headers, data->state.aptr.host);
+    if(result)
+      goto error;
   }
 
+#ifndef CURL_DISABLE_PROXY
   if(data->state.aptr.proxyuserpwd) {
     result = Curl_hyper_header(data, headers, data->state.aptr.proxyuserpwd);
     if(result)
       goto error;
   }
+#endif
 
   if(data->state.aptr.userpwd) {
     result = Curl_hyper_header(data, headers, data->state.aptr.userpwd);
@@ -1191,13 +1098,13 @@ CURLcode Curl_http(struct Curl_easy *data, bool *done)
   if(result)
     goto error;
 
-  result = bodysend(data, conn, headers, req, httpreq);
+  result = finalize_request(data, headers, req, httpreq);
   if(result)
     goto error;
 
   Curl_debug(data, CURLINFO_HEADER_OUT, (char *)"\r\n", 2);
 
-  if(data->req.upload_chunky && conn->bits.authneg) {
+  if(data->req.upload_chunky && data->req.authneg) {
     data->req.upload_chunky = TRUE;
   }
   else {
@@ -1224,18 +1131,17 @@ CURLcode Curl_http(struct Curl_easy *data, bool *done)
   if((httpreq == HTTPREQ_GET) || (httpreq == HTTPREQ_HEAD)) {
     /* HTTP GET/HEAD download */
     Curl_pgrsSetUploadSize(data, 0); /* nothing */
-    Curl_setup_transfer(data, FIRSTSOCKET, -1, TRUE, -1);
   }
+
+  Curl_xfer_setup(data, FIRSTSOCKET, -1, TRUE, FIRSTSOCKET);
   conn->datastream = Curl_hyper_stream;
-  if(data->state.expect100header)
-    /* Timeout count starts now since with Hyper we don't know exactly when
-       the full request has been sent. */
-    data->req.start100 = Curl_now();
 
   /* clear userpwd and proxyuserpwd to avoid reusing old credentials
    * from reused connections */
   Curl_safefree(data->state.aptr.userpwd);
+#ifndef CURL_DISABLE_PROXY
   Curl_safefree(data->state.aptr.proxyuserpwd);
+#endif
   return CURLE_OK;
 error:
   DEBUGASSERT(result);
@@ -1272,10 +1178,51 @@ void Curl_hyper_done(struct Curl_easy *data)
     hyper_waker_free(h->write_waker);
     h->write_waker = NULL;
   }
-  if(h->exp100_waker) {
-    hyper_waker_free(h->exp100_waker);
-    h->exp100_waker = NULL;
+  if(h->send_body_waker) {
+    hyper_waker_free(h->send_body_waker);
+    h->send_body_waker = NULL;
   }
 }
 
+static CURLcode cr_hyper_unpause(struct Curl_easy *data,
+                                 struct Curl_creader *reader)
+{
+  (void)reader;
+  if(data->hyp.send_body_waker) {
+    hyper_waker_wake(data->hyp.send_body_waker);
+    data->hyp.send_body_waker = NULL;
+  }
+  return CURLE_OK;
+}
+
+/* Hyper client reader, handling unpausing */
+static const struct Curl_crtype cr_hyper_protocol = {
+  "cr-hyper",
+  Curl_creader_def_init,
+  Curl_creader_def_read,
+  Curl_creader_def_close,
+  Curl_creader_def_needs_rewind,
+  Curl_creader_def_total_length,
+  Curl_creader_def_resume_from,
+  Curl_creader_def_rewind,
+  cr_hyper_unpause,
+  Curl_creader_def_done,
+  sizeof(struct Curl_creader)
+};
+
+static CURLcode cr_hyper_add(struct Curl_easy *data)
+{
+  struct Curl_creader *reader = NULL;
+  CURLcode result;
+
+  result = Curl_creader_create(&reader, data, &cr_hyper_protocol,
+                               CURL_CR_PROTOCOL);
+  if(!result)
+    result = Curl_creader_add(data, reader);
+
+  if(result && reader)
+    Curl_creader_free(data, reader);
+  return result;
+}
+
 #endif /* !defined(CURL_DISABLE_HTTP) && defined(USE_HYPER) */
diff --git a/vendor/curl/lib/c-hyper.h b/vendor/curl/lib/c-hyper.h
index 0c7de90b70..89dd53b8fd 100644
--- a/vendor/curl/lib/c-hyper.h
+++ b/vendor/curl/lib/c-hyper.h
@@ -29,13 +29,18 @@
 
 #include 
 
+struct hyp_io_ctx {
+  struct Curl_easy *data;
+  int sockindex;
+};
+
 /* per-transfer data for the Hyper backend */
 struct hyptransfer {
   hyper_waker *write_waker;
   hyper_waker *read_waker;
   const hyper_executor *exec;
-  hyper_waker *exp100_waker;
   hyper_waker *send_body_waker;
+  struct hyp_io_ctx io_ctx;
 };
 
 size_t Curl_hyper_recv(void *userp, hyper_context *ctx,
@@ -45,7 +50,6 @@ size_t Curl_hyper_send(void *userp, hyper_context *ctx,
 CURLcode Curl_hyper_stream(struct Curl_easy *data,
                            struct connectdata *conn,
                            int *didwhat,
-                           bool *done,
                            int select_res);
 
 CURLcode Curl_hyper_header(struct Curl_easy *data, hyper_headers *headers,
diff --git a/vendor/curl/lib/cf-h1-proxy.c b/vendor/curl/lib/cf-h1-proxy.c
index e9bc13d2a8..093c33be5b 100644
--- a/vendor/curl/lib/cf-h1-proxy.c
+++ b/vendor/curl/lib/cf-h1-proxy.c
@@ -34,6 +34,7 @@
 #include "dynbuf.h"
 #include "sendf.h"
 #include "http.h"
+#include "http1.h"
 #include "http_proxy.h"
 #include "url.h"
 #include "select.h"
@@ -64,14 +65,12 @@ typedef enum {
 
 /* struct for HTTP CONNECT tunneling */
 struct h1_tunnel_state {
-  int sockindex;
-  const char *hostname;
-  int remote_port;
   struct HTTP CONNECT;
   struct dynbuf rcvbuf;
-  struct dynbuf req;
-  size_t nsend;
+  struct dynbuf request_data;
+  size_t nsent;
   size_t headerlines;
+  struct Curl_chunker ch;
   enum keeponval {
     KEEPON_DONE,
     KEEPON_CONNECT,
@@ -94,67 +93,46 @@ static bool tunnel_is_failed(struct h1_tunnel_state *ts)
   return ts && (ts->tunnel_state == H1_TUNNEL_FAILED);
 }
 
-static CURLcode tunnel_reinit(struct h1_tunnel_state *ts,
-                              struct connectdata *conn,
-                              struct Curl_easy *data)
+static CURLcode tunnel_reinit(struct Curl_cfilter *cf,
+                              struct Curl_easy *data,
+                              struct h1_tunnel_state *ts)
 {
   (void)data;
+  (void)cf;
   DEBUGASSERT(ts);
   Curl_dyn_reset(&ts->rcvbuf);
-  Curl_dyn_reset(&ts->req);
+  Curl_dyn_reset(&ts->request_data);
   ts->tunnel_state = H1_TUNNEL_INIT;
   ts->keepon = KEEPON_CONNECT;
   ts->cl = 0;
   ts->close_connection = FALSE;
-
-  if(conn->bits.conn_to_host)
-    ts->hostname = conn->conn_to_host.name;
-  else if(ts->sockindex == SECONDARYSOCKET)
-    ts->hostname = conn->secondaryhostname;
-  else
-    ts->hostname = conn->host.name;
-
-  if(ts->sockindex == SECONDARYSOCKET)
-    ts->remote_port = conn->secondary_port;
-  else if(conn->bits.conn_to_port)
-    ts->remote_port = conn->conn_to_port;
-  else
-    ts->remote_port = conn->remote_port;
-
   return CURLE_OK;
 }
 
-static CURLcode tunnel_init(struct h1_tunnel_state **pts,
+static CURLcode tunnel_init(struct Curl_cfilter *cf,
                             struct Curl_easy *data,
-                            struct connectdata *conn,
-                            int sockindex)
+                            struct h1_tunnel_state **pts)
 {
   struct h1_tunnel_state *ts;
-  CURLcode result;
 
-  if(conn->handler->flags & PROTOPT_NOTCPPROXY) {
-    failf(data, "%s cannot be done over CONNECT", conn->handler->scheme);
+  if(cf->conn->handler->flags & PROTOPT_NOTCPPROXY) {
+    failf(data, "%s cannot be done over CONNECT", cf->conn->handler->scheme);
     return CURLE_UNSUPPORTED_PROTOCOL;
   }
 
-  /* we might need the upload buffer for streaming a partial request */
-  result = Curl_get_upload_buffer(data);
-  if(result)
-    return result;
-
   ts = calloc(1, sizeof(*ts));
   if(!ts)
     return CURLE_OUT_OF_MEMORY;
 
-  ts->sockindex = sockindex;
   infof(data, "allocate connect buffer");
 
   Curl_dyn_init(&ts->rcvbuf, DYN_PROXY_CONNECT_HEADERS);
-  Curl_dyn_init(&ts->req, DYN_HTTP_REQUEST);
+  Curl_dyn_init(&ts->request_data, DYN_HTTP_REQUEST);
+  Curl_httpchunk_init(data, &ts->ch, TRUE);
 
   *pts =  ts;
-  connkeep(conn, "HTTP proxy CONNECT");
-  return tunnel_reinit(ts, conn, data);
+  connkeep(cf->conn, "HTTP proxy CONNECT");
+  return tunnel_reinit(cf, data, ts);
 }
 
 static void h1_tunnel_go_state(struct Curl_cfilter *cf,
@@ -164,19 +142,11 @@ static void h1_tunnel_go_state(struct Curl_cfilter *cf,
 {
   if(ts->tunnel_state == new_state)
     return;
-  /* leaving this one */
-  switch(ts->tunnel_state) {
-  case H1_TUNNEL_CONNECT:
-    data->req.ignorebody = FALSE;
-    break;
-  default:
-    break;
-  }
   /* entering this one */
   switch(new_state) {
   case H1_TUNNEL_INIT:
     CURL_TRC_CF(data, cf, "new tunnel state 'init'");
-    tunnel_reinit(ts, cf->conn, data);
+    tunnel_reinit(cf, data, ts);
     break;
 
   case H1_TUNNEL_CONNECT:
@@ -201,13 +171,13 @@ static void h1_tunnel_go_state(struct Curl_cfilter *cf,
     infof(data, "CONNECT phase completed");
     data->state.authproxy.done = TRUE;
     data->state.authproxy.multipass = FALSE;
-    /* FALLTHROUGH */
+    FALLTHROUGH();
   case H1_TUNNEL_FAILED:
     if(new_state == H1_TUNNEL_FAILED)
       CURL_TRC_CF(data, cf, "new tunnel state 'failed'");
     ts->tunnel_state = new_state;
     Curl_dyn_reset(&ts->rcvbuf);
-    Curl_dyn_reset(&ts->req);
+    Curl_dyn_reset(&ts->request_data);
     /* restore the protocol pointer */
     data->info.httpcode = 0; /* clear it as it might've been used for the
                                 proxy */
@@ -225,46 +195,22 @@ static void h1_tunnel_go_state(struct Curl_cfilter *cf,
 static void tunnel_free(struct Curl_cfilter *cf,
                         struct Curl_easy *data)
 {
-  struct h1_tunnel_state *ts = cf->ctx;
-  if(ts) {
-    h1_tunnel_go_state(cf, ts, H1_TUNNEL_FAILED, data);
-    Curl_dyn_free(&ts->rcvbuf);
-    Curl_dyn_free(&ts->req);
-    free(ts);
-    cf->ctx = NULL;
+  if(cf) {
+    struct h1_tunnel_state *ts = cf->ctx;
+    if(ts) {
+      h1_tunnel_go_state(cf, ts, H1_TUNNEL_FAILED, data);
+      Curl_dyn_free(&ts->rcvbuf);
+      Curl_dyn_free(&ts->request_data);
+      Curl_httpchunk_free(data, &ts->ch);
+      free(ts);
+      cf->ctx = NULL;
+    }
   }
 }
 
-static CURLcode CONNECT_host(struct Curl_easy *data,
-                             struct connectdata *conn,
-                             const char *hostname,
-                             int remote_port,
-                             char **connecthostp,
-                             char **hostp)
+static bool tunnel_want_send(struct h1_tunnel_state *ts)
 {
-  char *hostheader; /* for CONNECT */
-  char *host = NULL; /* Host: */
-  bool ipv6_ip = conn->bits.ipv6_ip;
-
-  /* the hostname may be different */
-  if(hostname != conn->host.name)
-    ipv6_ip = (strchr(hostname, ':') != NULL);
-  hostheader = /* host:port with IPv6 support */
-    aprintf("%s%s%s:%d", ipv6_ip?"[":"", hostname, ipv6_ip?"]":"",
-            remote_port);
-  if(!hostheader)
-    return CURLE_OUT_OF_MEMORY;
-
-  if(!Curl_checkProxyheaders(data, conn, STRCONST("Host"))) {
-    host = aprintf("Host: %s\r\n", hostheader);
-    if(!host) {
-      free(hostheader);
-      return CURLE_OUT_OF_MEMORY;
-    }
-  }
-  *connecthostp = hostheader;
-  *hostp = host;
-  return CURLE_OK;
+  return (ts->tunnel_state == H1_TUNNEL_CONNECT);
 }
 
 #ifndef USE_HYPER
@@ -272,128 +218,71 @@ static CURLcode start_CONNECT(struct Curl_cfilter *cf,
                               struct Curl_easy *data,
                               struct h1_tunnel_state *ts)
 {
-  struct connectdata *conn = cf->conn;
-  char *hostheader = NULL;
-  char *host = NULL;
-  const char *httpv;
+  struct httpreq *req = NULL;
+  int http_minor;
   CURLcode result;
 
-  infof(data, "Establish HTTP proxy tunnel to %s:%d",
-        ts->hostname, ts->remote_port);
-
     /* This only happens if we've looped here due to authentication
        reasons, and we don't really use the newly cloned URL here
        then. Just free() it. */
   Curl_safefree(data->req.newurl);
 
-  result = CONNECT_host(data, conn,
-                        ts->hostname, ts->remote_port,
-                        &hostheader, &host);
-  if(result)
-    goto out;
-
-  /* Setup the proxy-authorization header, if any */
-  result = Curl_http_output_auth(data, conn, "CONNECT", HTTPREQ_GET,
-                                 hostheader, TRUE);
-  if(result)
-    goto out;
-
-  httpv = (conn->http_proxy.proxytype == CURLPROXY_HTTP_1_0) ? "1.0" : "1.1";
-
-  result =
-      Curl_dyn_addf(&ts->req,
-                    "CONNECT %s HTTP/%s\r\n"
-                    "%s"  /* Host: */
-                    "%s", /* Proxy-Authorization */
-                    hostheader,
-                    httpv,
-                    host?host:"",
-                    data->state.aptr.proxyuserpwd?
-                    data->state.aptr.proxyuserpwd:"");
-  if(result)
-    goto out;
-
-  if(!Curl_checkProxyheaders(data, conn, STRCONST("User-Agent"))
-     && data->set.str[STRING_USERAGENT])
-    result = Curl_dyn_addf(&ts->req, "User-Agent: %s\r\n",
-                           data->set.str[STRING_USERAGENT]);
-  if(result)
-    goto out;
-
-  if(!Curl_checkProxyheaders(data, conn, STRCONST("Proxy-Connection")))
-    result = Curl_dyn_addn(&ts->req,
-                           STRCONST("Proxy-Connection: Keep-Alive\r\n"));
+  result = Curl_http_proxy_create_CONNECT(&req, cf, data, 1);
   if(result)
     goto out;
 
-  result = Curl_add_custom_headers(data, TRUE, &ts->req);
-  if(result)
-    goto out;
-
-  /* CRLF terminate the request */
-  result = Curl_dyn_addn(&ts->req, STRCONST("\r\n"));
-  if(result)
-    goto out;
+  infof(data, "Establish HTTP proxy tunnel to %s", req->authority);
 
-  /* Send the connect request to the proxy */
-  result = Curl_buffer_send(&ts->req, data, &ts->CONNECT,
-                            &data->info.request_size, 0,
-                            ts->sockindex);
+  Curl_dyn_reset(&ts->request_data);
+  ts->nsent = 0;
   ts->headerlines = 0;
+  http_minor = (cf->conn->http_proxy.proxytype == CURLPROXY_HTTP_1_0) ? 0 : 1;
+
+  result = Curl_h1_req_write_head(req, http_minor, &ts->request_data);
+  if(!result)
+    result = Curl_creader_set_null(data);
 
 out:
   if(result)
     failf(data, "Failed sending CONNECT to proxy");
-  free(host);
-  free(hostheader);
+  if(req)
+    Curl_http_req_free(req);
   return result;
 }
 
-static CURLcode send_CONNECT(struct Curl_easy *data,
-                             struct connectdata *conn,
+static CURLcode send_CONNECT(struct Curl_cfilter *cf,
+                             struct Curl_easy *data,
                              struct h1_tunnel_state *ts,
                              bool *done)
 {
-  struct SingleRequest *k = &data->req;
-  struct HTTP *http = &ts->CONNECT;
+  char *buf = Curl_dyn_ptr(&ts->request_data);
+  size_t request_len = Curl_dyn_len(&ts->request_data);
+  size_t blen = request_len;
   CURLcode result = CURLE_OK;
+  ssize_t nwritten;
 
-  if(http->sending != HTTPSEND_REQUEST)
-    goto out;
+  if(blen <= ts->nsent)
+    goto out;  /* we are done */
 
-  if(!ts->nsend) {
-    size_t fillcount;
-    k->upload_fromhere = data->state.ulbuf;
-    result = Curl_fillreadbuffer(data, data->set.upload_buffer_size,
-                                 &fillcount);
-    if(result)
-      goto out;
-    ts->nsend = fillcount;
-  }
-  if(ts->nsend) {
-    ssize_t bytes_written;
-    /* write to socket (send away data) */
-    result = Curl_write(data,
-                        conn->writesockfd,  /* socket to send to */
-                        k->upload_fromhere, /* buffer pointer */
-                        ts->nsend,          /* buffer size */
-                        &bytes_written);    /* actually sent */
-    if(result)
-      goto out;
-    /* send to debug callback! */
-    Curl_debug(data, CURLINFO_HEADER_OUT,
-               k->upload_fromhere, bytes_written);
+  blen -= ts->nsent;
+  buf += ts->nsent;
 
-    ts->nsend -= bytes_written;
-    k->upload_fromhere += bytes_written;
+  nwritten = cf->next->cft->do_send(cf->next, data, buf, blen, &result);
+  if(nwritten < 0) {
+    if(result == CURLE_AGAIN) {
+      result = CURLE_OK;
+    }
+    goto out;
   }
-  if(!ts->nsend)
-    http->sending = HTTPSEND_NADA;
+
+  DEBUGASSERT(blen >= (size_t)nwritten);
+  ts->nsent += (size_t)nwritten;
+  Curl_debug(data, CURLINFO_HEADER_OUT, buf, (size_t)nwritten);
 
 out:
   if(result)
     failf(data, "Failed sending CONNECT to proxy");
-  *done = (http->sending != HTTPSEND_REQUEST);
+  *done = (!result && (ts->nsent >= request_len));
   return result;
 }
 
@@ -453,8 +342,8 @@ static CURLcode on_resp_header(struct Curl_cfilter *cf,
                                STRCONST("chunked"))) {
       infof(data, "CONNECT responded chunked");
       ts->chunked_encoding = TRUE;
-      /* init our chunky engine */
-      Curl_httpchunk_init(data);
+      /* reset our chunky engine */
+      Curl_httpchunk_reset(data, &ts->ch, TRUE);
     }
   }
   else if(Curl_compareheader(header,
@@ -480,10 +369,9 @@ static CURLcode recv_CONNECT_resp(struct Curl_cfilter *cf,
 {
   CURLcode result = CURLE_OK;
   struct SingleRequest *k = &data->req;
-  curl_socket_t tunnelsocket = Curl_conn_cf_get_socket(cf, data);
   char *linep;
-  size_t perline;
-  int error;
+  size_t line_len;
+  int error, writetype;
 
 #define SELECT_OK      0
 #define SELECT_ERROR   1
@@ -491,16 +379,16 @@ static CURLcode recv_CONNECT_resp(struct Curl_cfilter *cf,
   error = SELECT_OK;
   *done = FALSE;
 
-  if(!Curl_conn_data_pending(data, ts->sockindex))
+  if(!Curl_conn_data_pending(data, cf->sockindex))
     return CURLE_OK;
 
   while(ts->keepon) {
-    ssize_t gotbytes;
+    ssize_t nread;
     char byte;
 
     /* Read one byte at a time to avoid a race condition. Wait at most one
        second before looping to ensure continuous pgrsUpdates. */
-    result = Curl_read(data, tunnelsocket, &byte, 1, &gotbytes);
+    result = Curl_conn_recv(data, cf->sockindex, &byte, 1, &nread);
     if(result == CURLE_AGAIN)
       /* socket buffer drained, return */
       return CURLE_OK;
@@ -513,7 +401,7 @@ static CURLcode recv_CONNECT_resp(struct Curl_cfilter *cf,
       break;
     }
 
-    if(gotbytes <= 0) {
+    if(nread <= 0) {
       if(data->set.proxyauth && data->state.authproxy.avail &&
          data->state.aptr.proxyuserpwd) {
         /* proxy auth was requested and there was proxy auth available,
@@ -541,17 +429,17 @@ static CURLcode recv_CONNECT_resp(struct Curl_cfilter *cf,
           break;
         }
       }
-      else {
+      else if(ts->chunked_encoding) {
         /* chunked-encoded body, so we need to do the chunked dance
            properly to know when the end of the body is reached */
-        CHUNKcode r;
-        CURLcode extra;
-        ssize_t tookcareof = 0;
+        size_t consumed = 0;
 
         /* now parse the chunked piece of data so that we can
            properly tell when the stream ends */
-        r = Curl_httpchunk_read(data, &byte, 1, &tookcareof, &extra);
-        if(r == CHUNKE_STOP) {
+        result = Curl_httpchunk_read(data, &ts->ch, &byte, 1, &consumed);
+        if(result)
+          return result;
+        if(Curl_httpchunk_is_done(data, &ts->ch)) {
           /* we're done reading chunks! */
           infof(data, "chunk reading DONE");
           ts->keepon = KEEPON_DONE;
@@ -571,23 +459,19 @@ static CURLcode recv_CONNECT_resp(struct Curl_cfilter *cf,
 
     ts->headerlines++;
     linep = Curl_dyn_ptr(&ts->rcvbuf);
-    perline = Curl_dyn_len(&ts->rcvbuf); /* amount of bytes in this line */
+    line_len = Curl_dyn_len(&ts->rcvbuf); /* amount of bytes in this line */
 
     /* output debug if that is requested */
-    Curl_debug(data, CURLINFO_HEADER_IN, linep, perline);
-
-    if(!data->set.suppress_connect_headers) {
-      /* send the header to the callback */
-      int writetype = CLIENTWRITE_HEADER | CLIENTWRITE_CONNECT |
-        (data->set.include_header ? CLIENTWRITE_BODY : 0) |
-        (ts->headerlines == 1 ? CLIENTWRITE_STATUS : 0);
+    Curl_debug(data, CURLINFO_HEADER_IN, linep, line_len);
 
-      result = Curl_client_write(data, writetype, linep, perline);
-      if(result)
-        return result;
-    }
+    /* send the header to the callback */
+    writetype = CLIENTWRITE_HEADER | CLIENTWRITE_CONNECT |
+      (ts->headerlines == 1 ? CLIENTWRITE_STATUS : 0);
+    result = Curl_client_write(data, writetype, linep, line_len);
+    if(result)
+      return result;
 
-    result = Curl_bump_headersize(data, perline, TRUE);
+    result = Curl_bump_headersize(data, line_len, TRUE);
     if(result)
       return result;
 
@@ -610,29 +494,7 @@ static CURLcode recv_CONNECT_resp(struct Curl_cfilter *cf,
                 " bytes of response-body", ts->cl);
         }
         else if(ts->chunked_encoding) {
-          CHUNKcode r;
-          CURLcode extra;
-
           infof(data, "Ignore chunked response-body");
-
-          /* We set ignorebody true here since the chunked decoder
-             function will acknowledge that. Pay attention so that this is
-             cleared again when this function returns! */
-          k->ignorebody = TRUE;
-
-          if(linep[1] == '\n')
-            /* this can only be a LF if the letter at index 0 was a CR */
-            linep++;
-
-          /* now parse the chunked piece of data so that we can properly
-             tell when the stream ends */
-          r = Curl_httpchunk_read(data, linep + 1, 1, &gotbytes,
-                                  &extra);
-          if(r == CHUNKE_STOP) {
-            /* we're done reading chunks! */
-            infof(data, "chunk reading DONE");
-            ts->keepon = KEEPON_DONE;
-          }
         }
         else {
           /* without content-length or chunked encoding, we
@@ -670,6 +532,41 @@ static CURLcode recv_CONNECT_resp(struct Curl_cfilter *cf,
 }
 
 #else /* USE_HYPER */
+
+static CURLcode CONNECT_host(struct Curl_cfilter *cf,
+                             struct Curl_easy *data,
+                             char **pauthority,
+                             char **phost_header)
+{
+  const char *hostname;
+  int port;
+  bool ipv6_ip;
+  CURLcode result;
+  char *authority; /* for CONNECT, the destination host + port */
+  char *host_header = NULL; /* Host: authority */
+
+  result = Curl_http_proxy_get_destination(cf, &hostname, &port, &ipv6_ip);
+  if(result)
+    return result;
+
+  authority = aprintf("%s%s%s:%d", ipv6_ip?"[":"", hostname, ipv6_ip?"]":"",
+                      port);
+  if(!authority)
+    return CURLE_OUT_OF_MEMORY;
+
+  /* If user is not overriding the Host header later */
+  if(!Curl_checkProxyheaders(data, cf->conn, STRCONST("Host"))) {
+    host_header = aprintf("Host: %s\r\n", authority);
+    if(!host_header) {
+      free(authority);
+      return CURLE_OUT_OF_MEMORY;
+    }
+  }
+  *pauthority = authority;
+  *phost_header = host_header;
+  return CURLE_OK;
+}
+
 /* The Hyper version of CONNECT */
 static CURLcode start_CONNECT(struct Curl_cfilter *cf,
                               struct Curl_easy *data,
@@ -686,9 +583,10 @@ static CURLcode start_CONNECT(struct Curl_cfilter *cf,
   hyper_task *task = NULL; /* for the handshake */
   hyper_clientconn *client = NULL;
   hyper_task *sendtask = NULL; /* for the send */
-  char *hostheader = NULL; /* for CONNECT */
-  char *host = NULL; /* Host: */
+  char *authority = NULL; /* for CONNECT */
+  char *host_header = NULL; /* Host: */
   CURLcode result = CURLE_OUT_OF_MEMORY;
+  (void)ts;
 
   io = hyper_io_new();
   if(!io) {
@@ -697,7 +595,9 @@ static CURLcode start_CONNECT(struct Curl_cfilter *cf,
     goto error;
   }
   /* tell Hyper how to read/write network data */
-  hyper_io_set_userdata(io, data);
+  h->io_ctx.data = data;
+  h->io_ctx.sockindex = cf->sockindex;
+  hyper_io_set_userdata(io, &h->io_ctx);
   hyper_io_set_read(io, Curl_hyper_recv);
   hyper_io_set_write(io, Curl_hyper_send);
   conn->sockfd = tunnelsocket;
@@ -766,27 +666,25 @@ static CURLcode start_CONNECT(struct Curl_cfilter *cf,
     goto error;
   }
 
-  infof(data, "Establish HTTP proxy tunnel to %s:%d",
-        ts->hostname, ts->remote_port);
-
     /* This only happens if we've looped here due to authentication
        reasons, and we don't really use the newly cloned URL here
        then. Just free() it. */
   Curl_safefree(data->req.newurl);
 
-  result = CONNECT_host(data, conn, ts->hostname, ts->remote_port,
-                        &hostheader, &host);
+  result = CONNECT_host(cf, data, &authority, &host_header);
   if(result)
     goto error;
 
-  if(hyper_request_set_uri(req, (uint8_t *)hostheader,
-                           strlen(hostheader))) {
+  infof(data, "Establish HTTP proxy tunnel to %s", authority);
+
+  if(hyper_request_set_uri(req, (uint8_t *)authority,
+                           strlen(authority))) {
     failf(data, "error setting path");
     result = CURLE_OUT_OF_MEMORY;
     goto error;
   }
   if(data->set.verbose) {
-    char *se = aprintf("CONNECT %s HTTP/1.1\r\n", hostheader);
+    char *se = aprintf("CONNECT %s HTTP/1.1\r\n", authority);
     if(!se) {
       result = CURLE_OUT_OF_MEMORY;
       goto error;
@@ -796,10 +694,10 @@ static CURLcode start_CONNECT(struct Curl_cfilter *cf,
   }
   /* Setup the proxy-authorization header, if any */
   result = Curl_http_output_auth(data, conn, "CONNECT", HTTPREQ_GET,
-                                 hostheader, TRUE);
+                                 authority, TRUE);
   if(result)
     goto error;
-  Curl_safefree(hostheader);
+  Curl_safefree(authority);
 
   /* default is 1.1 */
   if((conn->http_proxy.proxytype == CURLPROXY_HTTP_1_0) &&
@@ -816,11 +714,11 @@ static CURLcode start_CONNECT(struct Curl_cfilter *cf,
     result = CURLE_OUT_OF_MEMORY;
     goto error;
   }
-  if(host) {
-    result = Curl_hyper_header(data, headers, host);
+  if(host_header) {
+    result = Curl_hyper_header(data, headers, host_header);
     if(result)
       goto error;
-    Curl_safefree(host);
+    Curl_safefree(host_header);
   }
 
   if(data->state.aptr.proxyuserpwd) {
@@ -831,7 +729,7 @@ static CURLcode start_CONNECT(struct Curl_cfilter *cf,
   }
 
   if(!Curl_checkProxyheaders(data, conn, STRCONST("User-Agent")) &&
-     data->set.str[STRING_USERAGENT]) {
+     data->set.str[STRING_USERAGENT] && *data->set.str[STRING_USERAGENT]) {
     struct dynbuf ua;
     Curl_dyn_init(&ua, DYN_HTTP_REQUEST);
     result = Curl_dyn_addf(&ua, "User-Agent: %s\r\n",
@@ -855,6 +753,10 @@ static CURLcode start_CONNECT(struct Curl_cfilter *cf,
   if(result)
     goto error;
 
+  result = Curl_creader_set_null(data);
+  if(result)
+    goto error;
+
   sendtask = hyper_clientconn_send(client, req);
   if(!sendtask) {
     failf(data, "hyper_clientconn_send");
@@ -874,8 +776,8 @@ static CURLcode start_CONNECT(struct Curl_cfilter *cf,
   client = NULL;
 
 error:
-  free(host);
-  free(hostheader);
+  free(host_header);
+  free(authority);
   if(io)
     hyper_io_free(io);
   if(options)
@@ -890,12 +792,13 @@ static CURLcode start_CONNECT(struct Curl_cfilter *cf,
   return result;
 }
 
-static CURLcode send_CONNECT(struct Curl_easy *data,
-                             struct connectdata *conn,
+static CURLcode send_CONNECT(struct Curl_cfilter *cf,
+                             struct Curl_easy *data,
                              struct h1_tunnel_state *ts,
                              bool *done)
 {
   struct hyptransfer *h = &data->hyp;
+  struct connectdata *conn = cf->conn;
   hyper_task *task = NULL;
   hyper_error *hypererr = NULL;
   CURLcode result = CURLE_OK;
@@ -937,9 +840,9 @@ static CURLcode recv_CONNECT_resp(struct Curl_cfilter *cf,
   int didwhat;
 
   (void)ts;
-  *done = FALSE;
-  result = Curl_hyper_stream(data, cf->conn, &didwhat, done,
+  result = Curl_hyper_stream(data, cf->conn, &didwhat,
                              CURL_CSELECT_IN | CURL_CSELECT_OUT);
+  *done = data->req.done;
   if(result || !*done)
     return result;
   if(h->exec) {
@@ -990,16 +893,16 @@ static CURLcode H1_CONNECT(struct Curl_cfilter *cf,
       if(result)
         goto out;
       h1_tunnel_go_state(cf, ts, H1_TUNNEL_CONNECT, data);
-      /* FALLTHROUGH */
+      FALLTHROUGH();
 
     case H1_TUNNEL_CONNECT:
       /* see that the request is completely sent */
       CURL_TRC_CF(data, cf, "CONNECT send");
-      result = send_CONNECT(data, cf->conn, ts, &done);
+      result = send_CONNECT(cf, data, ts, &done);
       if(result || !done)
         goto out;
       h1_tunnel_go_state(cf, ts, H1_TUNNEL_RECEIVE, data);
-      /* FALLTHROUGH */
+      FALLTHROUGH();
 
     case H1_TUNNEL_RECEIVE:
       /* read what is there */
@@ -1014,7 +917,7 @@ static CURLcode H1_CONNECT(struct Curl_cfilter *cf,
         goto out;
       /* got it */
       h1_tunnel_go_state(cf, ts, H1_TUNNEL_RESPONSE, data);
-      /* FALLTHROUGH */
+      FALLTHROUGH();
 
     case H1_TUNNEL_RESPONSE:
       CURL_TRC_CF(data, cf, "CONNECT response");
@@ -1023,6 +926,7 @@ static CURLcode H1_CONNECT(struct Curl_cfilter *cf,
          * If the other side indicated a connection close, or if someone
          * else told us to close this connection, do so now.
          */
+        Curl_req_soft_reset(&data->req, data);
         if(ts->close_connection || conn->bits.close) {
           /* Close this filter and the sub-chain, re-connect the
            * sub-chain and continue. Closing this filter will
@@ -1090,7 +994,7 @@ static CURLcode cf_h1_proxy_connect(struct Curl_cfilter *cf,
 
   *done = FALSE;
   if(!ts) {
-    result = tunnel_init(&ts, data, cf->conn, cf->sockindex);
+    result = tunnel_init(cf, data, &ts);
     if(result)
       return result;
     cf->ctx = ts;
@@ -1108,36 +1012,40 @@ static CURLcode cf_h1_proxy_connect(struct Curl_cfilter *cf,
   *done = (result == CURLE_OK) && tunnel_is_established(cf->ctx);
   if(*done) {
     cf->connected = TRUE;
+    /* The real request will follow the CONNECT, reset request partially */
+    Curl_req_soft_reset(&data->req, data);
+    Curl_client_reset(data);
+    Curl_pgrsSetUploadCounter(data, 0);
+    Curl_pgrsSetDownloadCounter(data, 0);
+
     tunnel_free(cf, data);
   }
   return result;
 }
 
-static int cf_h1_proxy_get_select_socks(struct Curl_cfilter *cf,
+static void cf_h1_proxy_adjust_pollset(struct Curl_cfilter *cf,
                                         struct Curl_easy *data,
-                                        curl_socket_t *socks)
+                                        struct easy_pollset *ps)
 {
   struct h1_tunnel_state *ts = cf->ctx;
-  int fds;
 
-  fds = cf->next->cft->get_select_socks(cf->next, data, socks);
-  if(!fds && cf->next->connected && !cf->connected) {
+  if(!cf->connected) {
     /* If we are not connected, but the filter "below" is
      * and not waiting on something, we are tunneling. */
-    socks[0] = Curl_conn_cf_get_socket(cf, data);
+    curl_socket_t sock = Curl_conn_cf_get_socket(cf, data);
     if(ts) {
       /* when we've sent a CONNECT to a proxy, we should rather either
          wait for the socket to become readable to be able to get the
          response headers or if we're still sending the request, wait
          for write. */
-      if(ts->CONNECT.sending == HTTPSEND_REQUEST) {
-        return GETSOCK_WRITESOCK(0);
-      }
-      return GETSOCK_READSOCK(0);
+      if(tunnel_want_send(ts))
+        Curl_pollset_set_out_only(data, ps, sock);
+      else
+        Curl_pollset_set_in_only(data, ps, sock);
     }
-    return GETSOCK_WRITESOCK(0);
+    else
+      Curl_pollset_set_out_only(data, ps, sock);
   }
-  return fds;
 }
 
 static void cf_h1_proxy_destroy(struct Curl_cfilter *cf,
@@ -1151,24 +1059,26 @@ static void cf_h1_proxy_close(struct Curl_cfilter *cf,
                               struct Curl_easy *data)
 {
   CURL_TRC_CF(data, cf, "close");
-  cf->connected = FALSE;
-  if(cf->ctx) {
-    h1_tunnel_go_state(cf, cf->ctx, H1_TUNNEL_INIT, data);
+  if(cf) {
+    cf->connected = FALSE;
+    if(cf->ctx) {
+      h1_tunnel_go_state(cf, cf->ctx, H1_TUNNEL_INIT, data);
+    }
+    if(cf->next)
+      cf->next->cft->do_close(cf->next, data);
   }
-  if(cf->next)
-    cf->next->cft->do_close(cf->next, data);
 }
 
 
 struct Curl_cftype Curl_cft_h1_proxy = {
   "H1-PROXY",
-  CF_TYPE_IP_CONNECT,
+  CF_TYPE_IP_CONNECT|CF_TYPE_PROXY,
   0,
   cf_h1_proxy_destroy,
   cf_h1_proxy_connect,
   cf_h1_proxy_close,
   Curl_cf_http_proxy_get_host,
-  cf_h1_proxy_get_select_socks,
+  cf_h1_proxy_adjust_pollset,
   Curl_cf_def_data_pending,
   Curl_cf_def_send,
   Curl_cf_def_recv,
diff --git a/vendor/curl/lib/cf-h2-proxy.c b/vendor/curl/lib/cf-h2-proxy.c
index a3feefca07..0bff15f38c 100644
--- a/vendor/curl/lib/cf-h2-proxy.c
+++ b/vendor/curl/lib/cf-h2-proxy.c
@@ -38,6 +38,7 @@
 #include "http2.h"
 #include "http_proxy.h"
 #include "multiif.h"
+#include "sendf.h"
 #include "cf-h2-proxy.h"
 
 /* The last 3 #include files should be in this order */
@@ -84,7 +85,8 @@ static CURLcode tunnel_stream_init(struct Curl_cfilter *cf,
 {
   const char *hostname;
   int port;
-  bool ipv6_ip = cf->conn->bits.ipv6_ip;
+  bool ipv6_ip;
+  CURLcode result;
 
   ts->state = H2_TUNNEL_INIT;
   ts->stream_id = -1;
@@ -92,22 +94,9 @@ static CURLcode tunnel_stream_init(struct Curl_cfilter *cf,
                   BUFQ_OPT_SOFT_LIMIT);
   Curl_bufq_init(&ts->sendbuf, PROXY_H2_CHUNK_SIZE, H2_TUNNEL_SEND_CHUNKS);
 
-  if(cf->conn->bits.conn_to_host)
-    hostname = cf->conn->conn_to_host.name;
-  else if(cf->sockindex == SECONDARYSOCKET)
-    hostname = cf->conn->secondaryhostname;
-  else
-    hostname = cf->conn->host.name;
-
-  if(cf->sockindex == SECONDARYSOCKET)
-    port = cf->conn->secondary_port;
-  else if(cf->conn->bits.conn_to_port)
-    port = cf->conn->conn_to_port;
-  else
-    port = cf->conn->remote_port;
-
-  if(hostname != cf->conn->host.name)
-    ipv6_ip = (strchr(hostname, ':') != NULL);
+  result = Curl_http_proxy_get_destination(cf, &hostname, &port, &ipv6_ip);
+  if(result)
+    return result;
 
   ts->authority = /* host:port with IPv6 support */
     aprintf("%s%s%s:%d", ipv6_ip?"[":"", hostname, ipv6_ip?"]":"", port);
@@ -167,7 +156,7 @@ static void h2_tunnel_go_state(struct Curl_cfilter *cf,
     infof(data, "CONNECT phase completed");
     data->state.authproxy.done = TRUE;
     data->state.authproxy.multipass = FALSE;
-    /* FALLTHROUGH */
+    FALLTHROUGH();
   case H2_TUNNEL_FAILED:
     if(new_state == H2_TUNNEL_FAILED)
       CURL_TRC_CF(data, cf, "[%d] new tunnel state 'failed'", ts->stream_id);
@@ -233,10 +222,10 @@ static void drain_tunnel(struct Curl_cfilter *cf,
   bits = CURL_CSELECT_IN;
   if(!tunnel->closed && !tunnel->reset && tunnel->upload_blocked_len)
     bits |= CURL_CSELECT_OUT;
-  if(data->state.dselect_bits != bits || 1) {
-    CURL_TRC_CF(data, cf, "[%d] DRAIN dselect_bits=%x",
+  if(data->state.select_bits != bits) {
+    CURL_TRC_CF(data, cf, "[%d] DRAIN select_bits=%x",
                 tunnel->stream_id, bits);
-    data->state.dselect_bits = bits;
+    data->state.select_bits = bits;
     Curl_expire(data, 0, EXPIRE_RUN_NOW);
   }
 }
@@ -309,8 +298,9 @@ static int proxy_h2_on_frame_recv(nghttp2_session *session,
                                   const nghttp2_frame *frame,
                                   void *userp);
 #ifndef CURL_DISABLE_VERBOSE_STRINGS
-static int on_frame_send(nghttp2_session *session, const nghttp2_frame *frame,
-                         void *userp);
+static int proxy_h2_on_frame_send(nghttp2_session *session,
+                                  const nghttp2_frame *frame,
+                                  void *userp);
 #endif
 static int proxy_h2_on_stream_close(nghttp2_session *session,
                                     int32_t stream_id,
@@ -355,7 +345,8 @@ static CURLcode cf_h2_proxy_ctx_init(struct Curl_cfilter *cf,
   nghttp2_session_callbacks_set_on_frame_recv_callback(
     cbs, proxy_h2_on_frame_recv);
 #ifndef CURL_DISABLE_VERBOSE_STRINGS
-  nghttp2_session_callbacks_set_on_frame_send_callback(cbs, on_frame_send);
+  nghttp2_session_callbacks_set_on_frame_send_callback(cbs,
+                                                       proxy_h2_on_frame_send);
 #endif
   nghttp2_session_callbacks_set_on_data_chunk_recv_callback(
     cbs, tunnel_recv_callback);
@@ -575,7 +566,8 @@ static ssize_t on_session_send(nghttp2_session *h2,
 }
 
 #ifndef CURL_DISABLE_VERBOSE_STRINGS
-static int fr_print(const nghttp2_frame *frame, char *buffer, size_t blen)
+static int proxy_h2_fr_print(const nghttp2_frame *frame,
+                             char *buffer, size_t blen)
 {
   switch(frame->hd.type) {
     case NGHTTP2_DATA: {
@@ -646,8 +638,9 @@ static int fr_print(const nghttp2_frame *frame, char *buffer, size_t blen)
   }
 }
 
-static int on_frame_send(nghttp2_session *session, const nghttp2_frame *frame,
-                         void *userp)
+static int proxy_h2_on_frame_send(nghttp2_session *session,
+                                  const nghttp2_frame *frame,
+                                  void *userp)
 {
   struct Curl_cfilter *cf = userp;
   struct Curl_easy *data = CF_DATA_CURRENT(cf);
@@ -657,7 +650,7 @@ static int on_frame_send(nghttp2_session *session, const nghttp2_frame *frame,
   if(data && Curl_trc_cf_is_verbose(cf, data)) {
     char buffer[256];
     int len;
-    len = fr_print(frame, buffer, sizeof(buffer)-1);
+    len = proxy_h2_fr_print(frame, buffer, sizeof(buffer)-1);
     buffer[len] = 0;
     CURL_TRC_CF(data, cf, "[%d] -> %s", frame->hd.stream_id, buffer);
   }
@@ -680,7 +673,7 @@ static int proxy_h2_on_frame_recv(nghttp2_session *session,
   if(Curl_trc_cf_is_verbose(cf, data)) {
     char buffer[256];
     int len;
-    len = fr_print(frame, buffer, sizeof(buffer)-1);
+    len = proxy_h2_fr_print(frame, buffer, sizeof(buffer)-1);
     buffer[len] = 0;
     CURL_TRC_CF(data, cf, "[%d] <- %s",frame->hd.stream_id, buffer);
   }
@@ -696,12 +689,8 @@ static int proxy_h2_on_frame_recv(nghttp2_session *session,
        * window and *assume* that we treat this like a WINDOW_UPDATE. Some
        * servers send an explicit WINDOW_UPDATE, but not all seem to do that.
        * To be safe, we UNHOLD a stream in order not to stall. */
-      if((data->req.keepon & KEEP_SEND_HOLD) &&
-         (data->req.keepon & KEEP_SEND)) {
-        data->req.keepon &= ~KEEP_SEND_HOLD;
+      if(CURL_WANT_SEND(data)) {
         drain_tunnel(cf, data, &ctx->tunnel);
-        CURL_TRC_CF(data, cf, "[%d] un-holding after SETTINGS",
-                    stream_id);
       }
       break;
     case NGHTTP2_GOAWAY:
@@ -735,12 +724,8 @@ static int proxy_h2_on_frame_recv(nghttp2_session *session,
     }
     break;
   case NGHTTP2_WINDOW_UPDATE:
-    if((data->req.keepon & KEEP_SEND_HOLD) &&
-       (data->req.keepon & KEEP_SEND)) {
-      data->req.keepon &= ~KEEP_SEND_HOLD;
-      Curl_expire(data, 0, EXPIRE_RUN_NOW);
-      CURL_TRC_CF(data, cf, "[%d] unpausing after win update",
-                  stream_id);
+    if(CURL_WANT_SEND(data)) {
+      drain_tunnel(cf, data, &ctx->tunnel);
     }
     break;
   default:
@@ -917,7 +902,6 @@ static CURLcode proxy_h2_submit(int32_t *pstream_id,
 {
   struct dynhds h2_headers;
   nghttp2_nv *nva = NULL;
-  unsigned int i;
   int32_t stream_id = -1;
   size_t nheader;
   CURLcode result;
@@ -928,22 +912,12 @@ static CURLcode proxy_h2_submit(int32_t *pstream_id,
   if(result)
     goto out;
 
-  nheader = Curl_dynhds_count(&h2_headers);
-  nva = malloc(sizeof(nghttp2_nv) * nheader);
+  nva = Curl_dynhds_to_nva(&h2_headers, &nheader);
   if(!nva) {
     result = CURLE_OUT_OF_MEMORY;
     goto out;
   }
 
-  for(i = 0; i < nheader; ++i) {
-    struct dynhds_entry *e = Curl_dynhds_getn(&h2_headers, i);
-    nva[i].name = (unsigned char *)e->name;
-    nva[i].namelen = e->namelen;
-    nva[i].value = (unsigned char *)e->value;
-    nva[i].valuelen = e->valuelen;
-    nva[i].flags = NGHTTP2_NV_FLAG_NONE;
-  }
-
   if(read_callback) {
     nghttp2_data_provider data_prd;
 
@@ -980,38 +954,14 @@ static CURLcode submit_CONNECT(struct Curl_cfilter *cf,
   CURLcode result;
   struct httpreq *req = NULL;
 
-  infof(data, "Establish HTTP/2 proxy tunnel to %s", ts->authority);
-
-  result = Curl_http_req_make(&req, "CONNECT", sizeof("CONNECT")-1,
-                              NULL, 0, ts->authority, strlen(ts->authority),
-                              NULL, 0);
+  result = Curl_http_proxy_create_CONNECT(&req, cf, data, 2);
   if(result)
     goto out;
-
-  /* Setup the proxy-authorization header, if any */
-  result = Curl_http_output_auth(data, cf->conn, req->method, HTTPREQ_GET,
-                                 req->authority, TRUE);
+  result = Curl_creader_set_null(data);
   if(result)
     goto out;
 
-  if(data->state.aptr.proxyuserpwd) {
-    result = Curl_dynhds_h1_cadd_line(&req->headers,
-                                      data->state.aptr.proxyuserpwd);
-    if(result)
-      goto out;
-  }
-
-  if(!Curl_checkProxyheaders(data, cf->conn, STRCONST("User-Agent"))
-     && data->set.str[STRING_USERAGENT]) {
-    result = Curl_dynhds_cadd(&req->headers, "User-Agent",
-                              data->set.str[STRING_USERAGENT]);
-    if(result)
-      goto out;
-  }
-
-  result = Curl_dynhds_add_custom(data, TRUE, &req->headers);
-  if(result)
-    goto out;
+  infof(data, "Establish HTTP/2 proxy tunnel to %s", req->authority);
 
   result = proxy_h2_submit(&ts->stream_id, cf, data, ctx->h2, req,
                            NULL, ts, tunnel_send_callback, cf);
@@ -1058,7 +1008,7 @@ static CURLcode inspect_response(struct Curl_cfilter *cf,
     if(result)
       return result;
     if(data->req.newurl) {
-      /* Inidicator that we should try again */
+      /* Indicator that we should try again */
       Curl_safefree(data->req.newurl);
       h2_tunnel_go_state(cf, ts, H2_TUNNEL_INIT, data);
       return CURLE_OK;
@@ -1087,7 +1037,7 @@ static CURLcode H2_CONNECT(struct Curl_cfilter *cf,
       if(result)
         goto out;
       h2_tunnel_go_state(cf, ts, H2_TUNNEL_CONNECT, data);
-      /* FALLTHROUGH */
+      FALLTHROUGH();
 
     case H2_TUNNEL_CONNECT:
       /* see that the request is completely sent */
@@ -1106,7 +1056,7 @@ static CURLcode H2_CONNECT(struct Curl_cfilter *cf,
         result = CURLE_OK;
         goto out;
       }
-      /* FALLTHROUGH */
+      FALLTHROUGH();
 
     case H2_TUNNEL_RESPONSE:
       DEBUGASSERT(ts->has_final_response);
@@ -1179,7 +1129,12 @@ static CURLcode cf_h2_proxy_connect(struct Curl_cfilter *cf,
 
 out:
   *done = (result == CURLE_OK) && (ts->state == H2_TUNNEL_ESTABLISHED);
-  cf->connected = *done;
+  if(*done) {
+    cf->connected = TRUE;
+    /* The real request will follow the CONNECT, reset request partially */
+    Curl_req_soft_reset(&data->req, data);
+    Curl_client_reset(data);
+  }
   CF_DATA_RESTORE(cf, save);
   return result;
 }
@@ -1195,6 +1150,8 @@ static void cf_h2_proxy_close(struct Curl_cfilter *cf, struct Curl_easy *data)
     cf_h2_proxy_ctx_clear(ctx);
     CF_DATA_RESTORE(cf, save);
   }
+  if(cf->next)
+    cf->next->cft->do_close(cf->next, data);
 }
 
 static void cf_h2_proxy_destroy(struct Curl_cfilter *cf,
@@ -1220,25 +1177,31 @@ static bool cf_h2_proxy_data_pending(struct Curl_cfilter *cf,
   return cf->next? cf->next->cft->has_data_pending(cf->next, data) : FALSE;
 }
 
-static int cf_h2_proxy_get_select_socks(struct Curl_cfilter *cf,
-                                        struct Curl_easy *data,
-                                        curl_socket_t *sock)
+static void cf_h2_proxy_adjust_pollset(struct Curl_cfilter *cf,
+                                       struct Curl_easy *data,
+                                       struct easy_pollset *ps)
 {
   struct cf_h2_proxy_ctx *ctx = cf->ctx;
-  int bitmap = GETSOCK_BLANK;
-  struct cf_call_data save;
-
-  CF_DATA_SAVE(save, cf, data);
-  sock[0] = Curl_conn_cf_get_socket(cf, data);
-  bitmap |= GETSOCK_READSOCK(0);
+  curl_socket_t sock = Curl_conn_cf_get_socket(cf, data);
+  bool want_recv, want_send;
 
-  /* HTTP/2 layer wants to send data) AND there's a window to send data in */
-  if(nghttp2_session_want_write(ctx->h2) &&
-     nghttp2_session_get_remote_window_size(ctx->h2))
-    bitmap |= GETSOCK_WRITESOCK(0);
+  Curl_pollset_check(data, ps, sock, &want_recv, &want_send);
+  if(ctx->h2 && (want_recv || want_send)) {
+    struct cf_call_data save;
+    bool c_exhaust, s_exhaust;
 
-  CF_DATA_RESTORE(cf, save);
-  return bitmap;
+    CF_DATA_SAVE(save, cf, data);
+    c_exhaust = !nghttp2_session_get_remote_window_size(ctx->h2);
+    s_exhaust = ctx->tunnel.stream_id >= 0 &&
+                !nghttp2_session_get_stream_remote_window_size(
+                   ctx->h2, ctx->tunnel.stream_id);
+    want_recv = (want_recv || c_exhaust || s_exhaust);
+    want_send = (!s_exhaust && want_send) ||
+                (!c_exhaust && nghttp2_session_want_write(ctx->h2));
+
+    Curl_pollset_set(data, ps, sock, want_recv, want_send);
+    CF_DATA_RESTORE(cf, save);
+  }
 }
 
 static ssize_t h2_handle_tunnel_close(struct Curl_cfilter *cf,
@@ -1569,13 +1532,13 @@ static bool cf_h2_proxy_is_alive(struct Curl_cfilter *cf,
 
 struct Curl_cftype Curl_cft_h2_proxy = {
   "H2-PROXY",
-  CF_TYPE_IP_CONNECT,
+  CF_TYPE_IP_CONNECT|CF_TYPE_PROXY,
   CURL_LOG_LVL_NONE,
   cf_h2_proxy_destroy,
   cf_h2_proxy_connect,
   cf_h2_proxy_close,
   Curl_cf_http_proxy_get_host,
-  cf_h2_proxy_get_select_socks,
+  cf_h2_proxy_adjust_pollset,
   cf_h2_proxy_data_pending,
   cf_h2_proxy_send,
   cf_h2_proxy_recv,
@@ -1593,7 +1556,7 @@ CURLcode Curl_cf_h2_proxy_insert_after(struct Curl_cfilter *cf,
   CURLcode result = CURLE_OUT_OF_MEMORY;
 
   (void)data;
-  ctx = calloc(sizeof(*ctx), 1);
+  ctx = calloc(1, sizeof(*ctx));
   if(!ctx)
     goto out;
 
diff --git a/vendor/curl/lib/cf-haproxy.c b/vendor/curl/lib/cf-haproxy.c
index 39ac415717..2abc4d754e 100644
--- a/vendor/curl/lib/cf-haproxy.c
+++ b/vendor/curl/lib/cf-haproxy.c
@@ -86,14 +86,14 @@ static CURLcode cf_haproxy_date_out_set(struct Curl_cfilter*cf,
   if(data->set.str[STRING_HAPROXY_CLIENT_IP])
     client_ip = data->set.str[STRING_HAPROXY_CLIENT_IP];
   else
-    client_ip = data->info.conn_local_ip;
+    client_ip = data->info.primary.local_ip;
 
   result = Curl_dyn_addf(&ctx->data_out, "PROXY %s %s %s %i %i\r\n",
                          tcp_version,
                          client_ip,
-                         data->info.conn_primary_ip,
-                         data->info.conn_local_port,
-                         data->info.conn_primary_port);
+                         data->info.primary.remote_ip,
+                         data->info.primary.local_port,
+                         data->info.primary.remote_port);
 
 #ifdef USE_UNIX_SOCKETS
   }
@@ -125,23 +125,28 @@ static CURLcode cf_haproxy_connect(struct Curl_cfilter *cf,
     if(result)
       goto out;
     ctx->state = HAPROXY_SEND;
-    /* FALLTHROUGH */
+    FALLTHROUGH();
   case HAPROXY_SEND:
     len = Curl_dyn_len(&ctx->data_out);
     if(len > 0) {
-      ssize_t written = Curl_conn_send(data, cf->sockindex,
-                                       Curl_dyn_ptr(&ctx->data_out),
-                                       len, &result);
-      if(written < 0)
+      size_t written;
+      result = Curl_conn_send(data, cf->sockindex,
+                              Curl_dyn_ptr(&ctx->data_out),
+                              len, &written);
+      if(result == CURLE_AGAIN) {
+        result = CURLE_OK;
+        written = 0;
+      }
+      else if(result)
         goto out;
-      Curl_dyn_tail(&ctx->data_out, len - (size_t)written);
+      Curl_dyn_tail(&ctx->data_out, len - written);
       if(Curl_dyn_len(&ctx->data_out) > 0) {
         result = CURLE_OK;
         goto out;
       }
     }
     ctx->state = HAPROXY_DONE;
-    /* FALLTHROUGH */
+    FALLTHROUGH();
   default:
     Curl_dyn_free(&ctx->data_out);
     break;
@@ -171,32 +176,26 @@ static void cf_haproxy_close(struct Curl_cfilter *cf,
     cf->next->cft->do_close(cf->next, data);
 }
 
-static int cf_haproxy_get_select_socks(struct Curl_cfilter *cf,
-                                       struct Curl_easy *data,
-                                       curl_socket_t *socks)
+static void cf_haproxy_adjust_pollset(struct Curl_cfilter *cf,
+                                      struct Curl_easy *data,
+                                      struct easy_pollset *ps)
 {
-  int fds;
-
-  fds = cf->next->cft->get_select_socks(cf->next, data, socks);
-  if(!fds && cf->next->connected && !cf->connected) {
+  if(cf->next->connected && !cf->connected) {
     /* If we are not connected, but the filter "below" is
      * and not waiting on something, we are sending. */
-    socks[0] = Curl_conn_cf_get_socket(cf, data);
-    return GETSOCK_WRITESOCK(0);
+    Curl_pollset_set_out_only(data, ps, Curl_conn_cf_get_socket(cf, data));
   }
-  return fds;
 }
 
-
 struct Curl_cftype Curl_cft_haproxy = {
   "HAPROXY",
-  0,
+  CF_TYPE_PROXY,
   0,
   cf_haproxy_destroy,
   cf_haproxy_connect,
   cf_haproxy_close,
   Curl_cf_def_get_host,
-  cf_haproxy_get_select_socks,
+  cf_haproxy_adjust_pollset,
   Curl_cf_def_data_pending,
   Curl_cf_def_send,
   Curl_cf_def_recv,
@@ -214,7 +213,7 @@ static CURLcode cf_haproxy_create(struct Curl_cfilter **pcf,
   CURLcode result;
 
   (void)data;
-  ctx = calloc(sizeof(*ctx), 1);
+  ctx = calloc(1, sizeof(*ctx));
   if(!ctx) {
     result = CURLE_OUT_OF_MEMORY;
     goto out;
diff --git a/vendor/curl/lib/cf-https-connect.c b/vendor/curl/lib/cf-https-connect.c
index be54aec740..50ac8d4bc2 100644
--- a/vendor/curl/lib/cf-https-connect.c
+++ b/vendor/curl/lib/cf-https-connect.c
@@ -102,8 +102,8 @@ struct cf_hc_ctx {
   CURLcode result;          /* overall result */
   struct cf_hc_baller h3_baller;
   struct cf_hc_baller h21_baller;
-  int soft_eyeballs_timeout_ms;
-  int hard_eyeballs_timeout_ms;
+  unsigned int soft_eyeballs_timeout_ms;
+  unsigned int hard_eyeballs_timeout_ms;
 };
 
 static void cf_hc_baller_init(struct cf_hc_baller *b,
@@ -188,9 +188,6 @@ static CURLcode baller_connected(struct Curl_cfilter *cf,
 #endif
     infof(data, "using HTTP/2");
     break;
-  case CURL_HTTP_VERSION_1_1:
-    infof(data, "using HTTP/1.1");
-    break;
   default:
     infof(data, "using HTTP/1.x");
     break;
@@ -269,7 +266,7 @@ static CURLcode cf_hc_connect(struct Curl_cfilter *cf,
       cf_hc_baller_init(&ctx->h21_baller, cf, data, "h21",
                        cf->conn->transport);
     ctx->state = CF_HC_CONNECT;
-    /* FALLTHROUGH */
+    FALLTHROUGH();
 
   case CF_HC_CONNECT:
     if(cf_hc_baller_is_active(&ctx->h3_baller)) {
@@ -325,42 +322,25 @@ static CURLcode cf_hc_connect(struct Curl_cfilter *cf,
   return result;
 }
 
-static int cf_hc_get_select_socks(struct Curl_cfilter *cf,
+static void cf_hc_adjust_pollset(struct Curl_cfilter *cf,
                                   struct Curl_easy *data,
-                                  curl_socket_t *socks)
+                                  struct easy_pollset *ps)
 {
-  struct cf_hc_ctx *ctx = cf->ctx;
-  size_t i, j, s;
-  int brc, rc = GETSOCK_BLANK;
-  curl_socket_t bsocks[MAX_SOCKSPEREASYHANDLE];
-  struct cf_hc_baller *ballers[2];
-
-  if(cf->connected)
-    return cf->next->cft->get_select_socks(cf->next, data, socks);
-
-  ballers[0] = &ctx->h3_baller;
-  ballers[1] = &ctx->h21_baller;
-  for(i = s = 0; i < sizeof(ballers)/sizeof(ballers[0]); i++) {
-    struct cf_hc_baller *b = ballers[i];
-    if(!cf_hc_baller_is_active(b))
-      continue;
-    brc = Curl_conn_cf_get_select_socks(b->cf, data, bsocks);
-    CURL_TRC_CF(data, cf, "get_selected_socks(%s) -> %x", b->name, brc);
-    if(!brc)
-      continue;
-    for(j = 0; j < MAX_SOCKSPEREASYHANDLE && s < MAX_SOCKSPEREASYHANDLE; ++j) {
-      if((brc & GETSOCK_WRITESOCK(j)) || (brc & GETSOCK_READSOCK(j))) {
-        socks[s] = bsocks[j];
-        if(brc & GETSOCK_WRITESOCK(j))
-          rc |= GETSOCK_WRITESOCK(s);
-        if(brc & GETSOCK_READSOCK(j))
-          rc |= GETSOCK_READSOCK(s);
-        s++;
-      }
+  if(!cf->connected) {
+    struct cf_hc_ctx *ctx = cf->ctx;
+    struct cf_hc_baller *ballers[2];
+    size_t i;
+
+    ballers[0] = &ctx->h3_baller;
+    ballers[1] = &ctx->h21_baller;
+    for(i = 0; i < sizeof(ballers)/sizeof(ballers[0]); i++) {
+      struct cf_hc_baller *b = ballers[i];
+      if(!cf_hc_baller_is_active(b))
+        continue;
+      Curl_conn_cf_adjust_pollset(b->cf, data, ps);
     }
+    CURL_TRC_CF(data, cf, "adjust_pollset -> %d socks", ps->num);
   }
-  CURL_TRC_CF(data, cf, "get_selected_socks -> %x", rc);
-  return rc;
 }
 
 static bool cf_hc_data_pending(struct Curl_cfilter *cf,
@@ -455,7 +435,7 @@ struct Curl_cftype Curl_cft_http_connect = {
   cf_hc_connect,
   cf_hc_close,
   Curl_cf_def_get_host,
-  cf_hc_get_select_socks,
+  cf_hc_adjust_pollset,
   cf_hc_data_pending,
   Curl_cf_def_send,
   Curl_cf_def_recv,
@@ -475,7 +455,7 @@ static CURLcode cf_hc_create(struct Curl_cfilter **pcf,
   CURLcode result = CURLE_OK;
 
   (void)data;
-  ctx = calloc(sizeof(*ctx), 1);
+  ctx = calloc(1, sizeof(*ctx));
   if(!ctx) {
     result = CURLE_OUT_OF_MEMORY;
     goto out;
diff --git a/vendor/curl/lib/cf-socket.c b/vendor/curl/lib/cf-socket.c
index effe6e649d..3e87889f9c 100644
--- a/vendor/curl/lib/cf-socket.c
+++ b/vendor/curl/lib/cf-socket.c
@@ -81,7 +81,7 @@
 #include "memdebug.h"
 
 
-#if defined(ENABLE_IPV6) && defined(IPV6_V6ONLY) && defined(WIN32)
+#if defined(USE_IPV6) && defined(IPV6_V6ONLY) && defined(_WIN32)
 /* It makes support for IPv4-mapped IPv6 addresses.
  * Linux kernel, NetBSD, FreeBSD and Darwin: default is off;
  * Windows Vista and later: default is on;
@@ -102,11 +102,7 @@ static void tcpnodelay(struct Curl_easy *data, curl_socket_t sockfd)
 #if defined(TCP_NODELAY)
   curl_socklen_t onoff = (curl_socklen_t) 1;
   int level = IPPROTO_TCP;
-#if !defined(CURL_DISABLE_VERBOSE_STRINGS)
   char buffer[STRERROR_LEN];
-#else
-  (void) data;
-#endif
 
   if(setsockopt(sockfd, level, TCP_NODELAY, (void *)&onoff,
                 sizeof(onoff)) < 0)
@@ -127,6 +123,7 @@ static void nosigpipe(struct Curl_easy *data,
                       curl_socket_t sockfd)
 {
   int onoff = 1;
+  (void)data;
   if(setsockopt(sockfd, SOL_SOCKET, SO_NOSIGPIPE, (void *)&onoff,
                 sizeof(onoff)) < 0) {
 #if !defined(CURL_DISABLE_VERBOSE_STRINGS)
@@ -140,14 +137,14 @@ static void nosigpipe(struct Curl_easy *data,
 #define nosigpipe(x,y) Curl_nop_stmt
 #endif
 
-#if defined(__DragonFly__) || defined(HAVE_WINSOCK2_H)
+#if defined(__DragonFly__) || defined(USE_WINSOCK)
 /* DragonFlyBSD and Windows use millisecond units */
 #define KEEPALIVE_FACTOR(x) (x *= 1000)
 #else
 #define KEEPALIVE_FACTOR(x)
 #endif
 
-#if defined(HAVE_WINSOCK2_H) && !defined(SIO_KEEPALIVE_VALS)
+#if defined(USE_WINSOCK) && !defined(SIO_KEEPALIVE_VALS)
 #define SIO_KEEPALIVE_VALS    _WSAIOW(IOC_VENDOR,4)
 
 struct tcp_keepalive {
@@ -166,7 +163,9 @@ tcpkeepalive(struct Curl_easy *data,
   /* only set IDLE and INTVL if setting KEEPALIVE is successful */
   if(setsockopt(sockfd, SOL_SOCKET, SO_KEEPALIVE,
         (void *)&optval, sizeof(optval)) < 0) {
-    infof(data, "Failed to set SO_KEEPALIVE on fd %d", sockfd);
+    infof(data, "Failed to set SO_KEEPALIVE on fd "
+          "%" CURL_FORMAT_SOCKET_T ": errno %d",
+          sockfd, SOCKERRNO);
   }
   else {
 #if defined(SIO_KEEPALIVE_VALS)
@@ -181,8 +180,9 @@ tcpkeepalive(struct Curl_easy *data,
     vals.keepaliveinterval = optval;
     if(WSAIoctl(sockfd, SIO_KEEPALIVE_VALS, (LPVOID) &vals, sizeof(vals),
                 NULL, 0, &dummy, NULL, NULL) != 0) {
-      infof(data, "Failed to set SIO_KEEPALIVE_VALS on fd %d: %d",
-            (int)sockfd, WSAGetLastError());
+      infof(data, "Failed to set SIO_KEEPALIVE_VALS on fd "
+                  "%" CURL_FORMAT_SOCKET_T ": errno %d",
+                  sockfd, SOCKERRNO);
     }
 #else
 #ifdef TCP_KEEPIDLE
@@ -190,7 +190,9 @@ tcpkeepalive(struct Curl_easy *data,
     KEEPALIVE_FACTOR(optval);
     if(setsockopt(sockfd, IPPROTO_TCP, TCP_KEEPIDLE,
           (void *)&optval, sizeof(optval)) < 0) {
-      infof(data, "Failed to set TCP_KEEPIDLE on fd %d", sockfd);
+      infof(data, "Failed to set TCP_KEEPIDLE on fd "
+            "%" CURL_FORMAT_SOCKET_T ": errno %d",
+            sockfd, SOCKERRNO);
     }
 #elif defined(TCP_KEEPALIVE)
     /* Mac OS X style */
@@ -198,7 +200,9 @@ tcpkeepalive(struct Curl_easy *data,
     KEEPALIVE_FACTOR(optval);
     if(setsockopt(sockfd, IPPROTO_TCP, TCP_KEEPALIVE,
       (void *)&optval, sizeof(optval)) < 0) {
-      infof(data, "Failed to set TCP_KEEPALIVE on fd %d", sockfd);
+      infof(data, "Failed to set TCP_KEEPALIVE on fd "
+            "%" CURL_FORMAT_SOCKET_T ": errno %d",
+            sockfd, SOCKERRNO);
     }
 #endif
 #ifdef TCP_KEEPINTVL
@@ -206,7 +210,9 @@ tcpkeepalive(struct Curl_easy *data,
     KEEPALIVE_FACTOR(optval);
     if(setsockopt(sockfd, IPPROTO_TCP, TCP_KEEPINTVL,
           (void *)&optval, sizeof(optval)) < 0) {
-      infof(data, "Failed to set TCP_KEEPINTVL on fd %d", sockfd);
+      infof(data, "Failed to set TCP_KEEPINTVL on fd "
+            "%" CURL_FORMAT_SOCKET_T ": errno %d",
+            sockfd, SOCKERRNO);
     }
 #endif
 #endif
@@ -281,7 +287,7 @@ static CURLcode socket_open(struct Curl_easy *data,
     /* no socket, no connection */
     return CURLE_COULDNT_CONNECT;
 
-#if defined(ENABLE_IPV6) && defined(HAVE_SOCKADDR_IN6_SIN6_SCOPE_ID)
+#if defined(USE_IPV6) && defined(HAVE_SOCKADDR_IN6_SIN6_SCOPE_ID)
   if(data->conn->scope_id && (addr->family == AF_INET6)) {
     struct sockaddr_in6 * const sa6 = (void *)&addr->sa_addr;
     sa6->sin6_scope_id = data->conn->scope_id;
@@ -399,7 +405,7 @@ static CURLcode bindlocal(struct Curl_easy *data, struct connectdata *conn,
   struct sockaddr *sock = (struct sockaddr *)&sa;  /* bind to this address */
   curl_socklen_t sizeof_sa = 0; /* size of the data sock points to */
   struct sockaddr_in *si4 = (struct sockaddr_in *)&sa;
-#ifdef ENABLE_IPV6
+#ifdef USE_IPV6
   struct sockaddr_in6 *si6 = (struct sockaddr_in6 *)&sa;
 #endif
 
@@ -413,7 +419,7 @@ static CURLcode bindlocal(struct Curl_easy *data, struct connectdata *conn,
 #ifdef IP_BIND_ADDRESS_NO_PORT
   int on = 1;
 #endif
-#ifndef ENABLE_IPV6
+#ifndef USE_IPV6
   (void)scope;
 #endif
 
@@ -469,7 +475,7 @@ static CURLcode bindlocal(struct Curl_easy *data, struct connectdata *conn,
 #endif
 
       switch(Curl_if2ip(af,
-#ifdef ENABLE_IPV6
+#ifdef USE_IPV6
                         scope, conn->scope_id,
 #endif
                         dev, myhost, sizeof(myhost))) {
@@ -508,7 +514,7 @@ static CURLcode bindlocal(struct Curl_easy *data, struct connectdata *conn,
 
       if(af == AF_INET)
         conn->ip_version = CURL_IPRESOLVE_V4;
-#ifdef ENABLE_IPV6
+#ifdef USE_IPV6
       else if(af == AF_INET6)
         conn->ip_version = CURL_IPRESOLVE_V6;
 #endif
@@ -541,7 +547,7 @@ static CURLcode bindlocal(struct Curl_easy *data, struct connectdata *conn,
     }
 
     if(done > 0) {
-#ifdef ENABLE_IPV6
+#ifdef USE_IPV6
       /* IPv6 address */
       if(af == AF_INET6) {
 #ifdef HAVE_SOCKADDR_IN6_SIN6_SCOPE_ID
@@ -590,7 +596,7 @@ static CURLcode bindlocal(struct Curl_easy *data, struct connectdata *conn,
   }
   else {
     /* no device was given, prepare sa to match af's needs */
-#ifdef ENABLE_IPV6
+#ifdef USE_IPV6
     if(af == AF_INET6) {
       si6->sin6_family = AF_INET6;
       si6->sin6_port = htons(port);
@@ -610,16 +616,6 @@ static CURLcode bindlocal(struct Curl_easy *data, struct connectdata *conn,
   for(;;) {
     if(bind(sockfd, sock, sizeof_sa) >= 0) {
       /* we succeeded to bind */
-      struct Curl_sockaddr_storage add;
-      curl_socklen_t size = sizeof(add);
-      memset(&add, 0, sizeof(struct Curl_sockaddr_storage));
-      if(getsockname(sockfd, (struct sockaddr *) &add, &size) < 0) {
-        char buffer[STRERROR_LEN];
-        data->state.os_errno = error = SOCKERRNO;
-        failf(data, "getsockname() failed with errno %d: %s",
-              error, Curl_strerror(error, buffer, sizeof(buffer)));
-        return CURLE_INTERFACE_FAILED;
-      }
       infof(data, "Local port: %hu", port);
       conn->bits.bound = TRUE;
       return CURLE_OK;
@@ -633,7 +629,7 @@ static CURLcode bindlocal(struct Curl_easy *data, struct connectdata *conn,
       /* We reuse/clobber the port variable here below */
       if(sock->sa_family == AF_INET)
         si4->sin_port = ntohs(port);
-#ifdef ENABLE_IPV6
+#ifdef USE_IPV6
       else
         si6->sin6_port = ntohs(port);
 #endif
@@ -662,7 +658,7 @@ static bool verifyconnect(curl_socket_t sockfd, int *error)
   int err = 0;
   curl_socklen_t errSize = sizeof(err);
 
-#ifdef WIN32
+#ifdef _WIN32
   /*
    * In October 2003 we effectively nullified this function on Windows due to
    * problems with it using all CPU in multi-threaded cases.
@@ -770,10 +766,7 @@ struct cf_socket_ctx {
   struct Curl_sockaddr_ex addr;      /* address to connect to */
   curl_socket_t sock;                /* current attempt socket */
   struct bufq recvbuf;               /* used when `buffer_recv` is set */
-  char r_ip[MAX_IPADR_LEN];          /* remote IP as string */
-  int r_port;                        /* remote port number */
-  char l_ip[MAX_IPADR_LEN];          /* local IP as string */
-  int l_port;                        /* local port number */
+  struct ip_quadruple ip;            /* The IP quadruple 2x(addr+port) */
   struct curltime started_at;        /* when socket was created */
   struct curltime connected_at;      /* when socket connected/got first byte */
   struct curltime first_byte_at;     /* when first byte was recvd */
@@ -781,9 +774,12 @@ struct cf_socket_ctx {
 #ifdef DEBUGBUILD
   int wblock_percent;                /* percent of writes doing EAGAIN */
   int wpartial_percent;              /* percent of bytes written in send */
+  int rblock_percent;                /* percent of reads doing EAGAIN */
+  size_t recv_max;                  /* max enforced read size */
 #endif
   BIT(got_first_byte);               /* if first byte was received */
   BIT(accepted);                     /* socket was accepted, not connected */
+  BIT(sock_connected);               /* socket is "connected", e.g. in UDP */
   BIT(active);
   BIT(buffer_recv);
 };
@@ -811,6 +807,18 @@ static void cf_socket_ctx_init(struct cf_socket_ctx *ctx,
       if(l >= 0 && l <= 100)
         ctx->wpartial_percent = (int)l;
     }
+    p = getenv("CURL_DBG_SOCK_RBLOCK");
+    if(p) {
+      long l = strtol(p, NULL, 10);
+      if(l >= 0 && l <= 100)
+        ctx->rblock_percent = (int)l;
+    }
+    p = getenv("CURL_DBG_SOCK_RMAX");
+    if(p) {
+      long l = strtol(p, NULL, 10);
+      if(l >= 0)
+        ctx->recv_max = (size_t)l;
+    }
   }
 #endif
 }
@@ -859,8 +867,9 @@ static ssize_t nw_in_read(void *reader_ctx,
       nread = -1;
     }
   }
-  CURL_TRC_CF(rctx->data, rctx->cf, "nw_in_read(len=%zu) -> %d, err=%d",
-              len, (int)nread, *err);
+  CURL_TRC_CF(rctx->data, rctx->cf, "nw_in_read(len=%zu, fd=%"
+              CURL_FORMAT_SOCKET_T ") -> %d, err=%d",
+              len, ctx->sock, (int)nread, *err);
   return nread;
 }
 
@@ -869,34 +878,14 @@ static void cf_socket_close(struct Curl_cfilter *cf, struct Curl_easy *data)
   struct cf_socket_ctx *ctx = cf->ctx;
 
   if(ctx && CURL_SOCKET_BAD != ctx->sock) {
-    if(ctx->active) {
-      /* We share our socket at cf->conn->sock[cf->sockindex] when active.
-       * If it is no longer there, someone has stolen (and hopefully
-       * closed it) and we just forget about it.
-       */
-      if(ctx->sock == cf->conn->sock[cf->sockindex]) {
-        CURL_TRC_CF(data, cf, "cf_socket_close(%" CURL_FORMAT_SOCKET_T
-                    ", active)", ctx->sock);
-        socket_close(data, cf->conn, !ctx->accepted, ctx->sock);
-        cf->conn->sock[cf->sockindex] = CURL_SOCKET_BAD;
-      }
-      else {
-        CURL_TRC_CF(data, cf, "cf_socket_close(%" CURL_FORMAT_SOCKET_T
-                    ") no longer at conn->sock[], discarding", ctx->sock);
-        /* TODO: we do not want this to happen. Need to check which
-         * code is messing with conn->sock[cf->sockindex] */
-      }
-      ctx->sock = CURL_SOCKET_BAD;
-      if(cf->sockindex == FIRSTSOCKET)
-        cf->conn->remote_addr = NULL;
-    }
-    else {
-      /* this is our local socket, we did never publish it */
-      CURL_TRC_CF(data, cf, "cf_socket_close(%" CURL_FORMAT_SOCKET_T
-                  ", not active)", ctx->sock);
-      socket_close(data, cf->conn, !ctx->accepted, ctx->sock);
-      ctx->sock = CURL_SOCKET_BAD;
-    }
+    CURL_TRC_CF(data, cf, "cf_socket_close(%" CURL_FORMAT_SOCKET_T
+                ")", ctx->sock);
+    if(ctx->sock == cf->conn->sock[cf->sockindex])
+      cf->conn->sock[cf->sockindex] = CURL_SOCKET_BAD;
+    socket_close(data, cf->conn, !ctx->accepted, ctx->sock);
+    ctx->sock = CURL_SOCKET_BAD;
+    if(ctx->active && cf->sockindex == FIRSTSOCKET)
+      cf->conn->remote_addr = NULL;
     Curl_bufq_reset(&ctx->recvbuf);
     ctx->active = FALSE;
     ctx->buffer_recv = FALSE;
@@ -924,7 +913,8 @@ static CURLcode set_local_ip(struct Curl_cfilter *cf,
   struct cf_socket_ctx *ctx = cf->ctx;
 
 #ifdef HAVE_GETSOCKNAME
-  if(!(data->conn->handler->protocol & CURLPROTO_TFTP)) {
+  if((ctx->sock != CURL_SOCKET_BAD) &&
+     !(data->conn->handler->protocol & CURLPROTO_TFTP)) {
     /* TFTP does not connect, so it cannot get the IP like this */
 
     char buffer[STRERROR_LEN];
@@ -939,7 +929,7 @@ static CURLcode set_local_ip(struct Curl_cfilter *cf,
       return CURLE_FAILED_INIT;
     }
     if(!Curl_addr2string((struct sockaddr*)&ssloc, slen,
-                         ctx->l_ip, &ctx->l_port)) {
+                         ctx->ip.local_ip, &ctx->ip.local_port)) {
       failf(data, "ssloc inet_ntop() failed with errno %d: %s",
             errno, Curl_strerror(errno, buffer, sizeof(buffer)));
       return CURLE_FAILED_INIT;
@@ -947,8 +937,8 @@ static CURLcode set_local_ip(struct Curl_cfilter *cf,
   }
 #else
   (void)data;
-  ctx->l_ip[0] = 0;
-  ctx->l_port = -1;
+  ctx->ip.local_ip[0] = 0;
+  ctx->ip.local_port = -1;
 #endif
   return CURLE_OK;
 }
@@ -960,7 +950,7 @@ static CURLcode set_remote_ip(struct Curl_cfilter *cf,
 
   /* store remote address and port used in this connection attempt */
   if(!Curl_addr2string(&ctx->addr.sa_addr, ctx->addr.addrlen,
-                       ctx->r_ip, &ctx->r_port)) {
+                       ctx->ip.remote_ip, &ctx->ip.remote_port)) {
     char buffer[STRERROR_LEN];
 
     ctx->error = errno;
@@ -992,22 +982,16 @@ static CURLcode cf_socket_open(struct Curl_cfilter *cf,
   if(result)
     goto out;
 
-#ifndef CURL_DISABLE_VERBOSE_STRINGS
-  {
-    const char *ipmsg;
-#ifdef ENABLE_IPV6
-    if(ctx->addr.family == AF_INET6) {
-      set_ipv6_v6only(ctx->sock, 0);
-      ipmsg = "  Trying [%s]:%d...";
-    }
-    else
-#endif
-      ipmsg = "  Trying %s:%d...";
-    infof(data, ipmsg, ctx->r_ip, ctx->r_port);
+#ifdef USE_IPV6
+  if(ctx->addr.family == AF_INET6) {
+    set_ipv6_v6only(ctx->sock, 0);
+    infof(data, "  Trying [%s]:%d...", ctx->ip.remote_ip, ctx->ip.remote_port);
   }
+  else
 #endif
+    infof(data, "  Trying %s:%d...", ctx->ip.remote_ip, ctx->ip.remote_port);
 
-#ifdef ENABLE_IPV6
+#ifdef USE_IPV6
   is_tcp = (ctx->addr.family == AF_INET
             || ctx->addr.family == AF_INET6) &&
            ctx->addr.socktype == SOCK_STREAM;
@@ -1044,7 +1028,7 @@ static CURLcode cf_socket_open(struct Curl_cfilter *cf,
 #ifndef CURL_DISABLE_BINDLOCAL
   /* possibly bind the local end to an IP, interface or port */
   if(ctx->addr.family == AF_INET
-#ifdef ENABLE_IPV6
+#ifdef USE_IPV6
      || ctx->addr.family == AF_INET6
 #endif
     ) {
@@ -1063,7 +1047,7 @@ static CURLcode cf_socket_open(struct Curl_cfilter *cf,
 
   /* set socket non-blocking */
   (void)curlx_nonblock(ctx->sock, TRUE);
-
+  ctx->sock_connected = (ctx->addr.socktype != SOCK_DGRAM);
 out:
   if(result) {
     if(ctx->sock != CURL_SOCKET_BAD) {
@@ -1155,6 +1139,7 @@ static CURLcode cf_tcp_connect(struct Curl_cfilter *cf,
 
   *done = FALSE; /* a very negative world view is best */
   if(ctx->sock == CURL_SOCKET_BAD) {
+    int error;
 
     result = cf_socket_open(cf, data);
     if(result)
@@ -1167,8 +1152,12 @@ static CURLcode cf_tcp_connect(struct Curl_cfilter *cf,
 
     /* Connect TCP socket */
     rc = do_connect(cf, data, cf->conn->bits.tcp_fastopen);
+    error = SOCKERRNO;
+    set_local_ip(cf, data);
+    CURL_TRC_CF(data, cf, "local address %s port %d...",
+                ctx->ip.local_ip, ctx->ip.local_port);
     if(-1 == rc) {
-      result = socket_connect_result(data, ctx->r_ip, SOCKERRNO);
+      result = socket_connect_result(data, ctx->ip.remote_ip, error);
       goto out;
     }
   }
@@ -1206,13 +1195,15 @@ static CURLcode cf_tcp_connect(struct Curl_cfilter *cf,
 out:
   if(result) {
     if(ctx->error) {
+      set_local_ip(cf, data);
       data->state.os_errno = ctx->error;
       SET_SOCKERRNO(ctx->error);
 #ifndef CURL_DISABLE_VERBOSE_STRINGS
       {
         char buffer[STRERROR_LEN];
-        infof(data, "connect to %s port %u failed: %s",
-              ctx->r_ip, ctx->r_port,
+        infof(data, "connect to %s port %u from %s port %d failed: %s",
+              ctx->ip.remote_ip, ctx->ip.remote_port,
+              ctx->ip.local_ip, ctx->ip.local_port,
               Curl_strerror(ctx->error, buffer, sizeof(buffer)));
       }
 #endif
@@ -1232,26 +1223,31 @@ static void cf_socket_get_host(struct Curl_cfilter *cf,
                                const char **pdisplay_host,
                                int *pport)
 {
+  struct cf_socket_ctx *ctx = cf->ctx;
   (void)data;
   *phost = cf->conn->host.name;
   *pdisplay_host = cf->conn->host.dispname;
-  *pport = cf->conn->port;
+  *pport = ctx->ip.remote_port;
 }
 
-static int cf_socket_get_select_socks(struct Curl_cfilter *cf,
+static void cf_socket_adjust_pollset(struct Curl_cfilter *cf,
                                       struct Curl_easy *data,
-                                      curl_socket_t *socks)
+                                      struct easy_pollset *ps)
 {
   struct cf_socket_ctx *ctx = cf->ctx;
-  int rc = GETSOCK_BLANK;
 
-  (void)data;
-  if(!cf->connected && ctx->sock != CURL_SOCKET_BAD) {
-    socks[0] = ctx->sock;
-    rc |= GETSOCK_WRITESOCK(0);
+  if(ctx->sock != CURL_SOCKET_BAD) {
+    if(!cf->connected) {
+      Curl_pollset_set_out_only(data, ps, ctx->sock);
+      CURL_TRC_CF(data, cf, "adjust_pollset, !connected, POLLOUT fd=%"
+                  CURL_FORMAT_SOCKET_T, ctx->sock);
+    }
+    else if(!ctx->active) {
+      Curl_pollset_add_in(data, ps, ctx->sock);
+      CURL_TRC_CF(data, cf, "adjust_pollset, !active, POLLIN fd=%"
+                  CURL_FORMAT_SOCKET_T, ctx->sock);
+    }
   }
-
-  return rc;
 }
 
 static bool cf_socket_data_pending(struct Curl_cfilter *cf,
@@ -1283,7 +1279,7 @@ static ssize_t cf_socket_send(struct Curl_cfilter *cf, struct Curl_easy *data,
 #ifdef DEBUGBUILD
   /* simulate network blocking/partial writes */
   if(ctx->wblock_percent > 0) {
-    unsigned char c;
+    unsigned char c = 0;
     Curl_rand(data, &c, 1);
     if(c >= ((100-ctx->wblock_percent)*256/100)) {
       CURL_TRC_CF(data, cf, "send(len=%zu) SIMULATE EWOULDBLOCK", orig_len);
@@ -1358,6 +1354,27 @@ static ssize_t cf_socket_recv(struct Curl_cfilter *cf, struct Curl_easy *data,
   fdsave = cf->conn->sock[cf->sockindex];
   cf->conn->sock[cf->sockindex] = ctx->sock;
 
+#ifdef DEBUGBUILD
+  /* simulate network blocking/partial reads */
+  if(cf->cft != &Curl_cft_udp && ctx->rblock_percent > 0) {
+    unsigned char c = 0;
+    Curl_rand(data, &c, 1);
+    if(c >= ((100-ctx->rblock_percent)*256/100)) {
+      CURL_TRC_CF(data, cf, "recv(len=%zu) SIMULATE EWOULDBLOCK", len);
+      *err = CURLE_AGAIN;
+      nread = -1;
+      cf->conn->sock[cf->sockindex] = fdsave;
+      return nread;
+    }
+  }
+  if(cf->cft != &Curl_cft_udp && ctx->recv_max && ctx->recv_max < len) {
+    size_t orig_len = len;
+    len = ctx->recv_max;
+    CURL_TRC_CF(data, cf, "recv(len=%zu) SIMULATE max read of %zu bytes",
+                orig_len, len);
+  }
+#endif
+
   if(ctx->buffer_recv && !Curl_bufq_is_empty(&ctx->recvbuf)) {
     CURL_TRC_CF(data, cf, "recv from buffer");
     nread = Curl_bufq_read(&ctx->recvbuf, (unsigned char *)buf, len, err);
@@ -1409,56 +1426,24 @@ static ssize_t cf_socket_recv(struct Curl_cfilter *cf, struct Curl_easy *data,
   return nread;
 }
 
-static void conn_set_primary_ip(struct Curl_cfilter *cf,
-                                struct Curl_easy *data)
-{
-#ifdef HAVE_GETPEERNAME
-  struct cf_socket_ctx *ctx = cf->ctx;
-  if(!(data->conn->handler->protocol & CURLPROTO_TFTP)) {
-    /* TFTP does not connect the endpoint: getpeername() failed with errno
-       107: Transport endpoint is not connected */
-
-    char buffer[STRERROR_LEN];
-    struct Curl_sockaddr_storage ssrem;
-    curl_socklen_t plen;
-    int port;
-
-    plen = sizeof(ssrem);
-    memset(&ssrem, 0, plen);
-    if(getpeername(ctx->sock, (struct sockaddr*) &ssrem, &plen)) {
-      int error = SOCKERRNO;
-      failf(data, "getpeername() failed with errno %d: %s",
-            error, Curl_strerror(error, buffer, sizeof(buffer)));
-      return;
-    }
-    if(!Curl_addr2string((struct sockaddr*)&ssrem, plen,
-                         cf->conn->primary_ip, &port)) {
-      failf(data, "ssrem inet_ntop() failed with errno %d: %s",
-            errno, Curl_strerror(errno, buffer, sizeof(buffer)));
-      return;
-    }
-  }
-#else
-  cf->conn->primary_ip[0] = 0;
-  (void)data;
-#endif
-}
-
 static void cf_socket_active(struct Curl_cfilter *cf, struct Curl_easy *data)
 {
   struct cf_socket_ctx *ctx = cf->ctx;
 
   /* use this socket from now on */
   cf->conn->sock[cf->sockindex] = ctx->sock;
-  /* the first socket info gets set at conn and data */
+  set_local_ip(cf, data);
+  if(cf->sockindex == SECONDARYSOCKET)
+    cf->conn->secondary = ctx->ip;
+  else
+    cf->conn->primary = ctx->ip;
+  /* the first socket info gets some specials */
   if(cf->sockindex == FIRSTSOCKET) {
     cf->conn->remote_addr = &ctx->addr;
-  #ifdef ENABLE_IPV6
+  #ifdef USE_IPV6
     cf->conn->bits.ipv6 = (ctx->addr.family == AF_INET6)? TRUE : FALSE;
   #endif
-    conn_set_primary_ip(cf, data);
-    set_local_ip(cf, data);
-    Curl_persistconninfo(data, cf->conn, ctx->l_ip, ctx->l_port);
+    Curl_persistconninfo(data, cf->conn, &ctx->ip);
     /* buffering is currently disabled by default because we have stalls
      * in parallel transfers where not all buffered data is consumed and no
      * socket events happen.
@@ -1481,7 +1466,10 @@ static CURLcode cf_socket_cntrl(struct Curl_cfilter *cf,
     cf_socket_active(cf, data);
     break;
   case CF_CTRL_DATA_SETUP:
-    Curl_persistconninfo(data, cf->conn, ctx->l_ip, ctx->l_port);
+    Curl_persistconninfo(data, cf->conn, &ctx->ip);
+    break;
+  case CF_CTRL_FORGET_SOCKET:
+    ctx->sock = CURL_SOCKET_BAD;
     break;
   }
   return CURLE_OK;
@@ -1554,7 +1542,7 @@ static CURLcode cf_socket_query(struct Curl_cfilter *cf,
         *when = ctx->first_byte_at;
         break;
       }
-      /* FALLTHROUGH */
+      FALLTHROUGH();
     default:
       *when = ctx->connected_at;
       break;
@@ -1577,7 +1565,7 @@ struct Curl_cftype Curl_cft_tcp = {
   cf_tcp_connect,
   cf_socket_close,
   cf_socket_get_host,
-  cf_socket_get_select_socks,
+  cf_socket_adjust_pollset,
   cf_socket_data_pending,
   cf_socket_send,
   cf_socket_recv,
@@ -1600,7 +1588,7 @@ CURLcode Curl_cf_tcp_create(struct Curl_cfilter **pcf,
   (void)data;
   (void)conn;
   DEBUGASSERT(transport == TRNSPRT_TCP);
-  ctx = calloc(sizeof(*ctx), 1);
+  ctx = calloc(1, sizeof(*ctx));
   if(!ctx) {
     result = CURLE_OUT_OF_MEMORY;
     goto out;
@@ -1628,15 +1616,23 @@ static CURLcode cf_udp_setup_quic(struct Curl_cfilter *cf,
   /* QUIC needs a connected socket, nonblocking */
   DEBUGASSERT(ctx->sock != CURL_SOCKET_BAD);
 
+#if defined(__APPLE__) && defined(USE_OPENSSL_QUIC)
+  (void)rc;
+  /* On macOS OpenSSL QUIC fails on connected sockets.
+   * see:  */
+#else
   rc = connect(ctx->sock, &ctx->addr.sa_addr, ctx->addr.addrlen);
   if(-1 == rc) {
-    return socket_connect_result(data, ctx->r_ip, SOCKERRNO);
+    return socket_connect_result(data, ctx->ip.remote_ip, SOCKERRNO);
   }
+  ctx->sock_connected = TRUE;
+#endif
   set_local_ip(cf, data);
   CURL_TRC_CF(data, cf, "%s socket %" CURL_FORMAT_SOCKET_T
               " connected: [%s:%d] -> [%s:%d]",
               (ctx->transport == TRNSPRT_QUIC)? "QUIC" : "UDP",
-              ctx->sock, ctx->l_ip, ctx->l_port, ctx->r_ip, ctx->r_port);
+              ctx->sock, ctx->ip.local_ip, ctx->ip.local_port,
+              ctx->ip.remote_ip, ctx->ip.remote_port);
 
   (void)curlx_nonblock(ctx->sock, TRUE);
   switch(ctx->addr.family) {
@@ -1686,7 +1682,7 @@ static CURLcode cf_udp_connect(struct Curl_cfilter *cf,
         goto out;
       CURL_TRC_CF(data, cf, "cf_udp_connect(), opened socket=%"
                   CURL_FORMAT_SOCKET_T " (%s:%d)",
-                  ctx->sock, ctx->l_ip, ctx->l_port);
+                  ctx->sock, ctx->ip.local_ip, ctx->ip.local_port);
     }
     else {
       CURL_TRC_CF(data, cf, "cf_udp_connect(), opened socket=%"
@@ -1707,7 +1703,7 @@ struct Curl_cftype Curl_cft_udp = {
   cf_udp_connect,
   cf_socket_close,
   cf_socket_get_host,
-  cf_socket_get_select_socks,
+  cf_socket_adjust_pollset,
   cf_socket_data_pending,
   cf_socket_send,
   cf_socket_recv,
@@ -1730,7 +1726,7 @@ CURLcode Curl_cf_udp_create(struct Curl_cfilter **pcf,
   (void)data;
   (void)conn;
   DEBUGASSERT(transport == TRNSPRT_UDP || transport == TRNSPRT_QUIC);
-  ctx = calloc(sizeof(*ctx), 1);
+  ctx = calloc(1, sizeof(*ctx));
   if(!ctx) {
     result = CURLE_OUT_OF_MEMORY;
     goto out;
@@ -1758,7 +1754,7 @@ struct Curl_cftype Curl_cft_unix = {
   cf_tcp_connect,
   cf_socket_close,
   cf_socket_get_host,
-  cf_socket_get_select_socks,
+  cf_socket_adjust_pollset,
   cf_socket_data_pending,
   cf_socket_send,
   cf_socket_recv,
@@ -1781,7 +1777,7 @@ CURLcode Curl_cf_unix_create(struct Curl_cfilter **pcf,
   (void)data;
   (void)conn;
   DEBUGASSERT(transport == TRNSPRT_UNIX);
-  ctx = calloc(sizeof(*ctx), 1);
+  ctx = calloc(1, sizeof(*ctx));
   if(!ctx) {
     result = CURLE_OUT_OF_MEMORY;
     goto out;
@@ -1822,7 +1818,7 @@ struct Curl_cftype Curl_cft_tcp_accept = {
   cf_tcp_accept_connect,
   cf_socket_close,
   cf_socket_get_host,              /* TODO: not accurate */
-  cf_socket_get_select_socks,
+  cf_socket_adjust_pollset,
   cf_socket_data_pending,
   cf_socket_send,
   cf_socket_recv,
@@ -1844,7 +1840,7 @@ CURLcode Curl_conn_tcp_listen_set(struct Curl_easy *data,
   Curl_conn_cf_discard_all(data, conn, sockindex);
   DEBUGASSERT(conn->sock[sockindex] == CURL_SOCKET_BAD);
 
-  ctx = calloc(sizeof(*ctx), 1);
+  ctx = calloc(1, sizeof(*ctx));
   if(!ctx) {
     result = CURLE_OUT_OF_MEMORY;
     goto out;
@@ -1882,8 +1878,8 @@ static void set_accepted_remote_ip(struct Curl_cfilter *cf,
   struct Curl_sockaddr_storage ssrem;
   curl_socklen_t plen;
 
-  ctx->r_ip[0] = 0;
-  ctx->r_port = 0;
+  ctx->ip.remote_ip[0] = 0;
+  ctx->ip.remote_port = 0;
   plen = sizeof(ssrem);
   memset(&ssrem, 0, plen);
   if(getpeername(ctx->sock, (struct sockaddr*) &ssrem, &plen)) {
@@ -1893,14 +1889,14 @@ static void set_accepted_remote_ip(struct Curl_cfilter *cf,
     return;
   }
   if(!Curl_addr2string((struct sockaddr*)&ssrem, plen,
-                       ctx->r_ip, &ctx->r_port)) {
+                       ctx->ip.remote_ip, &ctx->ip.remote_port)) {
     failf(data, "ssrem inet_ntop() failed with errno %d: %s",
           errno, Curl_strerror(errno, buffer, sizeof(buffer)));
     return;
   }
 #else
-  ctx->r_ip[0] = 0;
-  ctx->r_port = 0;
+  ctx->ip.remote_ip[0] = 0;
+  ctx->ip.remote_port = 0;
   (void)data;
 #endif
 }
@@ -1929,7 +1925,7 @@ CURLcode Curl_conn_tcp_accepted_set(struct Curl_easy *data,
   cf->connected = TRUE;
   CURL_TRC_CF(data, cf, "accepted_set(sock=%" CURL_FORMAT_SOCKET_T
               ", remote=%s port=%d)",
-              ctx->sock, ctx->r_ip, ctx->r_port);
+              ctx->sock, ctx->ip.remote_ip, ctx->ip.remote_port);
 
   return CURLE_OK;
 }
@@ -1949,9 +1945,9 @@ CURLcode Curl_cf_socket_peek(struct Curl_cfilter *cf,
                              struct Curl_easy *data,
                              curl_socket_t *psock,
                              const struct Curl_sockaddr_ex **paddr,
-                             const char **pr_ip_str, int *pr_port,
-                             const char **pl_ip_str, int *pl_port)
+                             struct ip_quadruple *pip)
 {
+  (void)data;
   if(cf_is_socket(cf) && cf->ctx) {
     struct cf_socket_ctx *ctx = cf->ctx;
 
@@ -1959,17 +1955,8 @@ CURLcode Curl_cf_socket_peek(struct Curl_cfilter *cf,
       *psock = ctx->sock;
     if(paddr)
       *paddr = &ctx->addr;
-    if(pr_ip_str)
-      *pr_ip_str = ctx->r_ip;
-    if(pr_port)
-      *pr_port = ctx->r_port;
-    if(pl_port ||pl_ip_str) {
-      set_local_ip(cf, data);
-      if(pl_ip_str)
-        *pl_ip_str = ctx->l_ip;
-      if(pl_port)
-        *pl_port = ctx->l_port;
-    }
+    if(pip)
+      *pip = ctx->ip;
     return CURLE_OK;
   }
   return CURLE_FAILED_INIT;
diff --git a/vendor/curl/lib/cf-socket.h b/vendor/curl/lib/cf-socket.h
index 1d40df737f..058af50098 100644
--- a/vendor/curl/lib/cf-socket.h
+++ b/vendor/curl/lib/cf-socket.h
@@ -33,23 +33,7 @@ struct Curl_cfilter;
 struct Curl_easy;
 struct connectdata;
 struct Curl_sockaddr_ex;
-
-#ifndef SIZEOF_CURL_SOCKET_T
-/* configure and cmake check and set the define */
-# ifdef _WIN64
-#  define SIZEOF_CURL_SOCKET_T 8
-# else
-/* default guess */
-#  define SIZEOF_CURL_SOCKET_T 4
-# endif
-#endif
-
-#if SIZEOF_CURL_SOCKET_T < 8
-# define CURL_FORMAT_SOCKET_T "d"
-#else
-# define CURL_FORMAT_SOCKET_T "qd"
-#endif
-
+struct ip_quadruple;
 
 /*
  * The Curl_sockaddr_ex structure is basically libcurl's external API
@@ -170,18 +154,14 @@ CURLcode Curl_conn_tcp_accepted_set(struct Curl_easy *data,
  * The filter owns all returned values.
  * @param psock             pointer to hold socket descriptor or NULL
  * @param paddr             pointer to hold addr reference or NULL
- * @param pr_ip_str         pointer to hold remote addr as string or NULL
- * @param pr_port           pointer to hold remote port number or NULL
- * @param pl_ip_str         pointer to hold local addr as string or NULL
- * @param pl_port           pointer to hold local port number or NULL
+ * @param pip               pointer to get IP quadruple or NULL
  * Returns error if the filter is of invalid type.
  */
 CURLcode Curl_cf_socket_peek(struct Curl_cfilter *cf,
                              struct Curl_easy *data,
                              curl_socket_t *psock,
                              const struct Curl_sockaddr_ex **paddr,
-                             const char **pr_ip_str, int *pr_port,
-                             const char **pl_ip_str, int *pl_port);
+                             struct ip_quadruple *pip);
 
 extern struct Curl_cftype Curl_cft_tcp;
 extern struct Curl_cftype Curl_cft_udp;
diff --git a/vendor/curl/lib/cfilters.c b/vendor/curl/lib/cfilters.c
index f74eb40039..a327fa1944 100644
--- a/vendor/curl/lib/cfilters.c
+++ b/vendor/curl/lib/cfilters.c
@@ -33,6 +33,7 @@
 #include "sockaddr.h" /* required for Curl_sockaddr_storage */
 #include "multiif.h"
 #include "progress.h"
+#include "select.h"
 #include "warnless.h"
 
 /* The last 3 #include files should be in this order */
@@ -66,16 +67,18 @@ void Curl_cf_def_get_host(struct Curl_cfilter *cf, struct Curl_easy *data,
   else {
     *phost = cf->conn->host.name;
     *pdisplay_host = cf->conn->host.dispname;
-    *pport = cf->conn->port;
+    *pport = cf->conn->primary.remote_port;
   }
 }
 
-int Curl_cf_def_get_select_socks(struct Curl_cfilter *cf,
+void Curl_cf_def_adjust_pollset(struct Curl_cfilter *cf,
                                  struct Curl_easy *data,
-                                 curl_socket_t *socks)
+                                 struct easy_pollset *ps)
 {
-  return cf->next?
-    cf->next->cft->get_select_socks(cf->next, data, socks) : 0;
+  /* NOP */
+  (void)cf;
+  (void)data;
+  (void)ps;
 }
 
 bool Curl_cf_def_data_pending(struct Curl_cfilter *cf,
@@ -165,38 +168,46 @@ void Curl_conn_close(struct Curl_easy *data, int index)
   }
 }
 
-ssize_t Curl_conn_recv(struct Curl_easy *data, int num, char *buf,
-                       size_t len, CURLcode *code)
+ssize_t Curl_cf_recv(struct Curl_easy *data, int num, char *buf,
+                     size_t len, CURLcode *code)
 {
   struct Curl_cfilter *cf;
 
   DEBUGASSERT(data);
   DEBUGASSERT(data->conn);
+  *code = CURLE_OK;
   cf = data->conn->cfilter[num];
   while(cf && !cf->connected) {
     cf = cf->next;
   }
   if(cf) {
-    return cf->cft->do_recv(cf, data, buf, len, code);
+    ssize_t nread = cf->cft->do_recv(cf, data, buf, len, code);
+    DEBUGASSERT(nread >= 0 || *code);
+    DEBUGASSERT(nread < 0 || !*code);
+    return nread;
   }
   failf(data, "recv: no filter connected");
   *code = CURLE_FAILED_INIT;
   return -1;
 }
 
-ssize_t Curl_conn_send(struct Curl_easy *data, int num,
-                       const void *mem, size_t len, CURLcode *code)
+ssize_t Curl_cf_send(struct Curl_easy *data, int num,
+                     const void *mem, size_t len, CURLcode *code)
 {
   struct Curl_cfilter *cf;
 
   DEBUGASSERT(data);
   DEBUGASSERT(data->conn);
+  *code = CURLE_OK;
   cf = data->conn->cfilter[num];
   while(cf && !cf->connected) {
     cf = cf->next;
   }
   if(cf) {
-    return cf->cft->do_send(cf, data, mem, len, code);
+    ssize_t nwritten = cf->cft->do_send(cf, data, mem, len, code);
+    DEBUGASSERT(nwritten >= 0 || *code);
+    DEBUGASSERT(nwritten < 0 || !*code || !len);
+    return nwritten;
   }
   failf(data, "send: no filter connected");
   DEBUGASSERT(0);
@@ -212,7 +223,7 @@ CURLcode Curl_cf_create(struct Curl_cfilter **pcf,
   CURLcode result = CURLE_OUT_OF_MEMORY;
 
   DEBUGASSERT(cft);
-  cf = calloc(sizeof(*cf), 1);
+  cf = calloc(1, sizeof(*cf));
   if(!cf)
     goto out;
 
@@ -303,15 +314,6 @@ void Curl_conn_cf_close(struct Curl_cfilter *cf, struct Curl_easy *data)
     cf->cft->do_close(cf, data);
 }
 
-int Curl_conn_cf_get_select_socks(struct Curl_cfilter *cf,
-                                  struct Curl_easy *data,
-                                  curl_socket_t *socks)
-{
-  if(cf)
-    return cf->cft->get_select_socks(cf, data, socks);
-  return 0;
-}
-
 ssize_t Curl_conn_cf_send(struct Curl_cfilter *cf, struct Curl_easy *data,
                           const void *buf, size_t len, CURLcode *err)
 {
@@ -433,22 +435,31 @@ bool Curl_conn_data_pending(struct Curl_easy *data, int sockindex)
   return FALSE;
 }
 
-int Curl_conn_get_select_socks(struct Curl_easy *data, int sockindex,
-                               curl_socket_t *socks)
+void Curl_conn_cf_adjust_pollset(struct Curl_cfilter *cf,
+                                 struct Curl_easy *data,
+                                 struct easy_pollset *ps)
 {
-  struct Curl_cfilter *cf;
+  /* Get the lowest not-connected filter, if there are any */
+  while(cf && !cf->connected && cf->next && !cf->next->connected)
+    cf = cf->next;
+  /* From there on, give all filters a chance to adjust the pollset.
+   * Lower filters are called later, so they may override */
+  while(cf) {
+    cf->cft->adjust_pollset(cf, data, ps);
+    cf = cf->next;
+  }
+}
+
+void Curl_conn_adjust_pollset(struct Curl_easy *data,
+                               struct easy_pollset *ps)
+{
+  int i;
 
   DEBUGASSERT(data);
   DEBUGASSERT(data->conn);
-  cf = data->conn->cfilter[sockindex];
-
-  /* if the next one is not yet connected, that's the one we want */
-  while(cf && cf->next && !cf->next->connected)
-    cf = cf->next;
-  if(cf) {
-    return cf->cft->get_select_socks(cf, data, socks);
+  for(i = 0; i < 2; ++i) {
+    Curl_conn_cf_adjust_pollset(data->conn->cfilter[i], data, ps);
   }
-  return GETSOCK_BLANK;
 }
 
 void Curl_conn_get_host(struct Curl_easy *data, int sockindex,
@@ -524,6 +535,18 @@ curl_socket_t Curl_conn_get_socket(struct Curl_easy *data, int sockindex)
   return data->conn? data->conn->sock[sockindex] : CURL_SOCKET_BAD;
 }
 
+void Curl_conn_forget_socket(struct Curl_easy *data, int sockindex)
+{
+  if(data->conn) {
+    struct Curl_cfilter *cf = data->conn->cfilter[sockindex];
+    if(cf)
+      (void)Curl_conn_cf_cntrl(cf, data, TRUE,
+                               CF_CTRL_FORGET_SOCKET, 0, NULL);
+    fake_sclose(data->conn->sock[sockindex]);
+    data->conn->sock[sockindex] = CURL_SOCKET_BAD;
+  }
+}
+
 static CURLcode cf_cntrl_all(struct connectdata *conn,
                              struct Curl_easy *data,
                              bool ignore_result,
@@ -567,7 +590,7 @@ CURLcode Curl_conn_ev_data_idle(struct Curl_easy *data)
 
 /**
  * Notify connection filters that the transfer represented by `data`
- * is donw with sending data (e.g. has uploaded everything).
+ * is done with sending data (e.g. has uploaded everything).
  */
 void Curl_conn_ev_data_done_send(struct Curl_easy *data)
 {
@@ -646,3 +669,193 @@ size_t Curl_conn_get_max_concurrent(struct Curl_easy *data,
                               &n, NULL) : CURLE_UNKNOWN_OPTION;
   return (result || n <= 0)? 1 : (size_t)n;
 }
+
+int Curl_conn_get_stream_error(struct Curl_easy *data,
+                               struct connectdata *conn,
+                               int sockindex)
+{
+  CURLcode result;
+  int n = 0;
+
+  struct Curl_cfilter *cf = conn->cfilter[sockindex];
+  result = cf? cf->cft->query(cf, data, CF_QUERY_STREAM_ERROR,
+                              &n, NULL) : CURLE_UNKNOWN_OPTION;
+  return (result || n < 0)? 0 : n;
+}
+
+int Curl_conn_sockindex(struct Curl_easy *data, curl_socket_t sockfd)
+{
+  if(data && data->conn &&
+     sockfd != CURL_SOCKET_BAD && sockfd == data->conn->sock[SECONDARYSOCKET])
+    return SECONDARYSOCKET;
+  return FIRSTSOCKET;
+}
+
+CURLcode Curl_conn_recv(struct Curl_easy *data, int sockindex,
+                        char *buf, size_t blen, ssize_t *n)
+{
+  CURLcode result = CURLE_OK;
+  ssize_t nread;
+
+  DEBUGASSERT(data->conn);
+  nread = data->conn->recv[sockindex](data, sockindex, buf, blen, &result);
+  DEBUGASSERT(nread >= 0 || result);
+  DEBUGASSERT(nread < 0 || !result);
+  *n = (nread >= 0)? (size_t)nread : 0;
+  return result;
+}
+
+CURLcode Curl_conn_send(struct Curl_easy *data, int sockindex,
+                        const void *buf, size_t blen,
+                        size_t *pnwritten)
+{
+  ssize_t nwritten;
+  CURLcode result = CURLE_OK;
+  struct connectdata *conn;
+
+  DEBUGASSERT(sockindex >= 0 && sockindex < 2);
+  DEBUGASSERT(pnwritten);
+  DEBUGASSERT(data);
+  DEBUGASSERT(data->conn);
+  conn = data->conn;
+#ifdef CURLDEBUG
+  {
+    /* Allow debug builds to override this logic to force short sends
+    */
+    char *p = getenv("CURL_SMALLSENDS");
+    if(p) {
+      size_t altsize = (size_t)strtoul(p, NULL, 10);
+      if(altsize)
+        blen = CURLMIN(blen, altsize);
+    }
+  }
+#endif
+  nwritten = conn->send[sockindex](data, sockindex, buf, blen, &result);
+  DEBUGASSERT((nwritten >= 0) || result);
+  *pnwritten = (nwritten < 0)? 0 : (size_t)nwritten;
+  return result;
+}
+
+void Curl_pollset_reset(struct Curl_easy *data,
+                        struct easy_pollset *ps)
+{
+  size_t i;
+  (void)data;
+  memset(ps, 0, sizeof(*ps));
+  for(i = 0; i< MAX_SOCKSPEREASYHANDLE; i++)
+    ps->sockets[i] = CURL_SOCKET_BAD;
+}
+
+/**
+ *
+ */
+void Curl_pollset_change(struct Curl_easy *data,
+                       struct easy_pollset *ps, curl_socket_t sock,
+                       int add_flags, int remove_flags)
+{
+  unsigned int i;
+
+  (void)data;
+  DEBUGASSERT(VALID_SOCK(sock));
+  if(!VALID_SOCK(sock))
+    return;
+
+  DEBUGASSERT(add_flags <= (CURL_POLL_IN|CURL_POLL_OUT));
+  DEBUGASSERT(remove_flags <= (CURL_POLL_IN|CURL_POLL_OUT));
+  DEBUGASSERT((add_flags&remove_flags) == 0); /* no overlap */
+  for(i = 0; i < ps->num; ++i) {
+    if(ps->sockets[i] == sock) {
+      ps->actions[i] &= (unsigned char)(~remove_flags);
+      ps->actions[i] |= (unsigned char)add_flags;
+      /* all gone? remove socket */
+      if(!ps->actions[i]) {
+        if((i + 1) < ps->num) {
+          memmove(&ps->sockets[i], &ps->sockets[i + 1],
+                  (ps->num - (i + 1)) * sizeof(ps->sockets[0]));
+          memmove(&ps->actions[i], &ps->actions[i + 1],
+                  (ps->num - (i + 1)) * sizeof(ps->actions[0]));
+        }
+        --ps->num;
+      }
+      return;
+    }
+  }
+  /* not present */
+  if(add_flags) {
+    /* Having more SOCKETS per easy handle than what is defined
+     * is a programming error. This indicates that we need
+     * to raise this limit, making easy_pollset larger.
+     * Since we use this in tight loops, we do not want to make
+     * the pollset dynamic unnecessarily.
+     * The current maximum in practise is HTTP/3 eyeballing where
+     * we have up to 4 sockets involved in connection setup.
+     */
+    DEBUGASSERT(i < MAX_SOCKSPEREASYHANDLE);
+    if(i < MAX_SOCKSPEREASYHANDLE) {
+      ps->sockets[i] = sock;
+      ps->actions[i] = (unsigned char)add_flags;
+      ps->num = i + 1;
+    }
+  }
+}
+
+void Curl_pollset_set(struct Curl_easy *data,
+                      struct easy_pollset *ps, curl_socket_t sock,
+                      bool do_in, bool do_out)
+{
+  Curl_pollset_change(data, ps, sock,
+                      (do_in?CURL_POLL_IN:0)|(do_out?CURL_POLL_OUT:0),
+                      (!do_in?CURL_POLL_IN:0)|(!do_out?CURL_POLL_OUT:0));
+}
+
+static void ps_add(struct Curl_easy *data, struct easy_pollset *ps,
+                   int bitmap, curl_socket_t *socks)
+{
+  if(bitmap) {
+    int i;
+    for(i = 0; i < MAX_SOCKSPEREASYHANDLE; ++i) {
+      if(!(bitmap & GETSOCK_MASK_RW(i)) || !VALID_SOCK((socks[i]))) {
+        break;
+      }
+      if(bitmap & GETSOCK_READSOCK(i)) {
+        if(bitmap & GETSOCK_WRITESOCK(i))
+          Curl_pollset_add_inout(data, ps, socks[i]);
+        else
+          /* is READ, since we checked MASK_RW above */
+          Curl_pollset_add_in(data, ps, socks[i]);
+      }
+      else
+        Curl_pollset_add_out(data, ps, socks[i]);
+    }
+  }
+}
+
+void Curl_pollset_add_socks(struct Curl_easy *data,
+                            struct easy_pollset *ps,
+                            int (*get_socks_cb)(struct Curl_easy *data,
+                                                curl_socket_t *socks))
+{
+  curl_socket_t socks[MAX_SOCKSPEREASYHANDLE];
+  int bitmap;
+
+  bitmap = get_socks_cb(data, socks);
+  ps_add(data, ps, bitmap, socks);
+}
+
+void Curl_pollset_check(struct Curl_easy *data,
+                        struct easy_pollset *ps, curl_socket_t sock,
+                        bool *pwant_read, bool *pwant_write)
+{
+  unsigned int i;
+
+  (void)data;
+  DEBUGASSERT(VALID_SOCK(sock));
+  for(i = 0; i < ps->num; ++i) {
+    if(ps->sockets[i] == sock) {
+      *pwant_read = !!(ps->actions[i] & CURL_POLL_IN);
+      *pwant_write = !!(ps->actions[i] & CURL_POLL_OUT);
+      return;
+    }
+  }
+  *pwant_read = *pwant_write = FALSE;
+}
diff --git a/vendor/curl/lib/cfilters.h b/vendor/curl/lib/cfilters.h
index 2c65264d98..dcfc1b71fa 100644
--- a/vendor/curl/lib/cfilters.h
+++ b/vendor/curl/lib/cfilters.h
@@ -60,14 +60,34 @@ typedef void     Curl_cft_get_host(struct Curl_cfilter *cf,
                                   const char **pdisplay_host,
                                   int *pport);
 
-/* Filters may return sockets and fdset flags they are waiting for.
- * The passes array has room for up to MAX_SOCKSPEREASYHANDLE sockets.
- * @return read/write fdset for index in socks
- *         or GETSOCK_BLANK when nothing to wait on
+struct easy_pollset;
+
+/* Passing in an easy_pollset for monitoring of sockets, let
+ * filters add or remove sockets actions (CURL_POLL_OUT, CURL_POLL_IN).
+ * This may add a socket or, in case no actions remain, remove
+ * a socket from the set.
+ *
+ * Filter implementations need to call filters "below" *after* they have
+ * made their adjustments. This allows lower filters to override "upper"
+ * actions. If a "lower" filter is unable to write, it needs to be able
+ * to disallow POLL_OUT.
+ *
+ * A filter without own restrictions/preferences should not modify
+ * the pollset. Filters, whose filter "below" is not connected, should
+ * also do no adjustments.
+ *
+ * Examples: a TLS handshake, while ongoing, might remove POLL_IN
+ * when it needs to write, or vice versa. A HTTP/2 filter might remove
+ * POLL_OUT when a stream window is exhausted and a WINDOW_UPDATE needs
+ * to be received first and add instead POLL_IN.
+ *
+ * @param cf     the filter to ask
+ * @param data   the easy handle the pollset is about
+ * @param ps     the pollset (inout) for the easy handle
  */
-typedef int      Curl_cft_get_select_socks(struct Curl_cfilter *cf,
-                                           struct Curl_easy *data,
-                                           curl_socket_t *socks);
+typedef void     Curl_cft_adjust_pollset(struct Curl_cfilter *cf,
+                                          struct Curl_easy *data,
+                                          struct easy_pollset *ps);
 
 typedef bool     Curl_cft_data_pending(struct Curl_cfilter *cf,
                                        const struct Curl_easy *data);
@@ -110,6 +130,7 @@ typedef CURLcode Curl_cft_conn_keep_alive(struct Curl_cfilter *cf,
 #define CF_CTRL_DATA_DONE_SEND        8  /* 0          NULL     ignored */
 /* update conn info at connection and data */
 #define CF_CTRL_CONN_INFO_UPDATE (256+0) /* 0          NULL     ignored */
+#define CF_CTRL_FORGET_SOCKET    (256+1) /* 0          NULL     ignored */
 
 /**
  * Handle event/control for the filter.
@@ -139,6 +160,7 @@ typedef CURLcode Curl_cft_cntrl(struct Curl_cfilter *cf,
 #define CF_QUERY_SOCKET             3  /* -          curl_socket_t */
 #define CF_QUERY_TIMER_CONNECT      4  /* -          struct curltime */
 #define CF_QUERY_TIMER_APPCONNECT   5  /* -          struct curltime */
+#define CF_QUERY_STREAM_ERROR       6  /* error code - */
 
 /**
  * Query the cfilter for properties. Filters ignorant of a query will
@@ -157,10 +179,12 @@ typedef CURLcode Curl_cft_query(struct Curl_cfilter *cf,
  *                     connection, etc.
  * CF_TYPE_SSL:        provide SSL/TLS
  * CF_TYPE_MULTIPLEX:  provides multiplexing of easy handles
+ * CF_TYPE_PROXY       provides proxying
  */
 #define CF_TYPE_IP_CONNECT  (1 << 0)
 #define CF_TYPE_SSL         (1 << 1)
 #define CF_TYPE_MULTIPLEX   (1 << 2)
+#define CF_TYPE_PROXY       (1 << 3)
 
 /* A connection filter type, e.g. specific implementation. */
 struct Curl_cftype {
@@ -171,7 +195,7 @@ struct Curl_cftype {
   Curl_cft_connect *do_connect;           /* establish connection */
   Curl_cft_close *do_close;               /* close conn */
   Curl_cft_get_host *get_host;            /* host filter talks to */
-  Curl_cft_get_select_socks *get_select_socks;/* sockets to select on */
+  Curl_cft_adjust_pollset *adjust_pollset; /* adjust transfer poll set */
   Curl_cft_data_pending *has_data_pending;/* conn has data pending */
   Curl_cft_send *do_send;                 /* send data */
   Curl_cft_recv *do_recv;                 /* receive data */
@@ -200,9 +224,9 @@ void Curl_cf_def_destroy_this(struct Curl_cfilter *cf,
 void     Curl_cf_def_get_host(struct Curl_cfilter *cf, struct Curl_easy *data,
                               const char **phost, const char **pdisplay_host,
                               int *pport);
-int      Curl_cf_def_get_select_socks(struct Curl_cfilter *cf,
-                                      struct Curl_easy *data,
-                                      curl_socket_t *socks);
+void     Curl_cf_def_adjust_pollset(struct Curl_cfilter *cf,
+                                     struct Curl_easy *data,
+                                     struct easy_pollset *ps);
 bool     Curl_cf_def_data_pending(struct Curl_cfilter *cf,
                                   const struct Curl_easy *data);
 ssize_t  Curl_cf_def_send(struct Curl_cfilter *cf, struct Curl_easy *data,
@@ -279,9 +303,6 @@ CURLcode Curl_conn_cf_connect(struct Curl_cfilter *cf,
                               struct Curl_easy *data,
                               bool blocking, bool *done);
 void Curl_conn_cf_close(struct Curl_cfilter *cf, struct Curl_easy *data);
-int Curl_conn_cf_get_select_socks(struct Curl_cfilter *cf,
-                                  struct Curl_easy *data,
-                                  curl_socket_t *socks);
 ssize_t Curl_conn_cf_send(struct Curl_cfilter *cf, struct Curl_easy *data,
                           const void *buf, size_t len, CURLcode *err);
 ssize_t Curl_conn_cf_recv(struct Curl_cfilter *cf, struct Curl_easy *data,
@@ -364,20 +385,31 @@ bool Curl_conn_data_pending(struct Curl_easy *data,
 curl_socket_t Curl_conn_get_socket(struct Curl_easy *data, int sockindex);
 
 /**
- * Get any select fd flags and the socket filters at chain `sockindex`
- * at connection `conn` might be waiting for.
+ * Tell filters to forget about the socket at sockindex.
+ */
+void Curl_conn_forget_socket(struct Curl_easy *data, int sockindex);
+
+/**
+ * Adjust the pollset for the filter chain startgin at `cf`.
+ */
+void Curl_conn_cf_adjust_pollset(struct Curl_cfilter *cf,
+                                 struct Curl_easy *data,
+                                 struct easy_pollset *ps);
+
+/**
+ * Adjust pollset from filters installed at transfer's connection.
  */
-int Curl_conn_get_select_socks(struct Curl_easy *data, int sockindex,
-                               curl_socket_t *socks);
+void Curl_conn_adjust_pollset(struct Curl_easy *data,
+                               struct easy_pollset *ps);
 
 /**
  * Receive data through the filter chain at `sockindex` for connection
  * `data->conn`. Copy at most `len` bytes into `buf`. Return the
- * actuel number of bytes copied or a negative value on error.
+ * actual number of bytes copied or a negative value on error.
  * The error code is placed into `*code`.
  */
-ssize_t Curl_conn_recv(struct Curl_easy *data, int sockindex, char *buf,
-                       size_t len, CURLcode *code);
+ssize_t Curl_cf_recv(struct Curl_easy *data, int sockindex, char *buf,
+                     size_t len, CURLcode *code);
 
 /**
  * Send `len` bytes of data from `buf` through the filter chain `sockindex`
@@ -385,8 +417,8 @@ ssize_t Curl_conn_recv(struct Curl_easy *data, int sockindex, char *buf,
  * or a negative value on error.
  * The error code is placed into `*code`.
  */
-ssize_t Curl_conn_send(struct Curl_easy *data, int sockindex,
-                       const void *buf, size_t len, CURLcode *code);
+ssize_t Curl_cf_send(struct Curl_easy *data, int sockindex,
+                     const void *buf, size_t len, CURLcode *code);
 
 /**
  * The easy handle `data` is being attached to `conn`. This does
@@ -420,7 +452,7 @@ CURLcode Curl_conn_ev_data_idle(struct Curl_easy *data);
 
 /**
  * Notify connection filters that the transfer represented by `data`
- * is donw with sending data (e.g. has uploaded everything).
+ * is done with sending data (e.g. has uploaded everything).
  */
 void Curl_conn_ev_data_done_send(struct Curl_easy *data);
 
@@ -467,6 +499,79 @@ size_t Curl_conn_get_max_concurrent(struct Curl_easy *data,
                                     struct connectdata *conn,
                                     int sockindex);
 
+/**
+ * Get the underlying error code for a transfer stream or 0 if not known.
+ */
+int Curl_conn_get_stream_error(struct Curl_easy *data,
+                               struct connectdata *conn,
+                               int sockindex);
+
+/**
+ * Get the index of the given socket in the connection's sockets.
+ * Useful in calling `Curl_conn_send()/Curl_conn_recv()` with the
+ * correct socket index.
+ */
+int Curl_conn_sockindex(struct Curl_easy *data, curl_socket_t sockfd);
+
+/*
+ * Receive data on the connection, using FIRSTSOCKET/SECONDARYSOCKET.
+ * Will return CURLE_AGAIN iff blocked on receiving.
+ */
+CURLcode Curl_conn_recv(struct Curl_easy *data, int sockindex,
+                        char *buf, size_t buffersize,
+                        ssize_t *pnread);
+
+/*
+ * Send data on the connection, using FIRSTSOCKET/SECONDARYSOCKET.
+ * Will return CURLE_AGAIN iff blocked on sending.
+ */
+CURLcode Curl_conn_send(struct Curl_easy *data, int sockindex,
+                        const void *buf, size_t blen,
+                        size_t *pnwritten);
+
+
+void Curl_pollset_reset(struct Curl_easy *data,
+                        struct easy_pollset *ps);
+
+/* Change the poll flags (CURL_POLL_IN/CURL_POLL_OUT) to the poll set for
+ * socket `sock`. If the socket is not already part of the poll set, it
+ * will be added.
+ * If the socket is present and all poll flags are cleared, it will be removed.
+ */
+void Curl_pollset_change(struct Curl_easy *data,
+                         struct easy_pollset *ps, curl_socket_t sock,
+                         int add_flags, int remove_flags);
+
+void Curl_pollset_set(struct Curl_easy *data,
+                      struct easy_pollset *ps, curl_socket_t sock,
+                      bool do_in, bool do_out);
+
+#define Curl_pollset_add_in(data, ps, sock) \
+          Curl_pollset_change((data), (ps), (sock), CURL_POLL_IN, 0)
+#define Curl_pollset_add_out(data, ps, sock) \
+          Curl_pollset_change((data), (ps), (sock), CURL_POLL_OUT, 0)
+#define Curl_pollset_add_inout(data, ps, sock) \
+          Curl_pollset_change((data), (ps), (sock), \
+                               CURL_POLL_IN|CURL_POLL_OUT, 0)
+#define Curl_pollset_set_in_only(data, ps, sock) \
+          Curl_pollset_change((data), (ps), (sock), \
+                               CURL_POLL_IN, CURL_POLL_OUT)
+#define Curl_pollset_set_out_only(data, ps, sock) \
+          Curl_pollset_change((data), (ps), (sock), \
+                               CURL_POLL_OUT, CURL_POLL_IN)
+
+void Curl_pollset_add_socks(struct Curl_easy *data,
+                            struct easy_pollset *ps,
+                            int (*get_socks_cb)(struct Curl_easy *data,
+                                                curl_socket_t *socks));
+
+/**
+ * Check if the pollset, as is, wants to read and/or write regarding
+ * the given socket.
+ */
+void Curl_pollset_check(struct Curl_easy *data,
+                        struct easy_pollset *ps, curl_socket_t sock,
+                        bool *pwant_read, bool *pwant_write);
 
 /**
  * Types and macros used to keep the current easy handle in filter calls,
diff --git a/vendor/curl/lib/config-amigaos.h b/vendor/curl/lib/config-amigaos.h
index 11f36a121a..d168b446b6 100644
--- a/vendor/curl/lib/config-amigaos.h
+++ b/vendor/curl/lib/config-amigaos.h
@@ -32,7 +32,6 @@
 
 #define HAVE_ARPA_INET_H 1
 #define HAVE_CLOSESOCKET_CAMEL 1
-#define HAVE_INTTYPES_H 1
 #define HAVE_IOCTLSOCKET_CAMEL 1
 #define HAVE_IOCTLSOCKET_CAMEL_FIONBIO 1
 #define HAVE_LONGLONG 1
@@ -40,17 +39,13 @@
 #define HAVE_NETINET_IN_H 1
 #define HAVE_NET_IF_H 1
 #define HAVE_PWD_H 1
-#define HAVE_RAND_EGD 1
 #define HAVE_SELECT 1
-#define HAVE_SETJMP_H 1
 #define HAVE_SIGNAL 1
-#define HAVE_SIGNAL_H 1
 #define HAVE_SOCKET 1
 #define HAVE_STRCASECMP 1
 #define HAVE_STRDUP 1
 #define HAVE_STRICMP 1
 #define HAVE_STRINGS_H 1
-#define HAVE_STRING_H 1
 #define HAVE_STRUCT_TIMEVAL 1
 #define HAVE_SYS_PARAM_H 1
 #define HAVE_SYS_SOCKET_H 1
@@ -58,7 +53,6 @@
 #define HAVE_SYS_STAT_H 1
 #define HAVE_SYS_TIME_H 1
 #define HAVE_SYS_TYPES_H 1
-#define HAVE_TIME_H 1
 #define HAVE_UNISTD_H 1
 #define HAVE_UTIME 1
 #define HAVE_UTIME_H 1
@@ -97,7 +91,6 @@
 #endif
 
 #define STDC_HEADERS 1
-#define TIME_WITH_SYS_TIME 1
 
 #define in_addr_t int
 
diff --git a/vendor/curl/lib/config-dos.h b/vendor/curl/lib/config-dos.h
index 05c1a81407..c6fbba796a 100644
--- a/vendor/curl/lib/config-dos.h
+++ b/vendor/curl/lib/config-dos.h
@@ -61,7 +61,6 @@
 #define HAVE_RECV              1
 #define HAVE_SELECT            1
 #define HAVE_SEND              1
-#define HAVE_SETJMP_H          1
 #define HAVE_SETLOCALE         1
 #define HAVE_SETMODE           1
 #define HAVE_SIGNAL            1
@@ -74,7 +73,6 @@
 #define HAVE_SYS_SOCKET_H      1
 #define HAVE_SYS_STAT_H        1
 #define HAVE_SYS_TYPES_H       1
-#define HAVE_TIME_H            1
 #define HAVE_UNISTD_H          1
 
 #define NEED_MALLOC_H          1
@@ -84,7 +82,6 @@
 #define SIZEOF_SIZE_T          4
 #define SIZEOF_CURL_OFF_T      8
 #define STDC_HEADERS           1
-#define TIME_WITH_SYS_TIME     1
 
 /* Qualifiers for send() and recv() */
 
@@ -125,7 +122,6 @@
   #define HAVE_SIGSETJMP  1
   #define HAVE_SYS_TIME_H 1
   #define HAVE_TERMIOS_H  1
-  #define HAVE_VARIADIC_MACROS_GCC 1
 
 #elif defined(__HIGHC__)
   #define HAVE_SYS_TIME_H 1
diff --git a/vendor/curl/lib/config-mac.h b/vendor/curl/lib/config-mac.h
index 8bd2fbd09c..c29888f8f7 100644
--- a/vendor/curl/lib/config-mac.h
+++ b/vendor/curl/lib/config-mac.h
@@ -52,15 +52,10 @@
 #define HAVE_GETTIMEOFDAY       1
 #define HAVE_FCNTL_H            1
 #define HAVE_SYS_STAT_H         1
-#define HAVE_STDLIB_H           1
-#define HAVE_TIME_H             1
 #define HAVE_UTIME_H            1
 #define HAVE_SYS_TIME_H         1
 #define HAVE_SYS_UTIME_H        1
 #define HAVE_SYS_IOCTL_H        1
-
-#define TIME_WITH_SYS_TIME      1
-
 #define HAVE_ALARM              1
 #define HAVE_FTRUNCATE          1
 #define HAVE_UTIME              1
@@ -69,7 +64,6 @@
 #define HAVE_STRUCT_TIMEVAL     1
 
 #define HAVE_SIGACTION          1
-#define HAVE_SIGNAL_H           1
 
 #ifdef MACOS_SSL_SUPPORT
 #  define USE_OPENSSL           1
@@ -77,8 +71,6 @@
 
 #define CURL_DISABLE_LDAP       1
 
-#define HAVE_RAND_EGD           1
-
 #define HAVE_IOCTL_FIONBIO      1
 
 #define SIZEOF_INT              4
diff --git a/vendor/curl/lib/config-os400.h b/vendor/curl/lib/config-os400.h
index 8d48955eef..018e90af7e 100644
--- a/vendor/curl/lib/config-os400.h
+++ b/vendor/curl/lib/config-os400.h
@@ -57,7 +57,7 @@
 #undef NEED_REENTRANT
 
 /* Define if you want to enable IPv6 support */
-#define ENABLE_IPV6
+#define USE_IPV6
 
 /* Define if struct sockaddr_in6 has the sin6_scope_id member */
 #define HAVE_SOCKADDR_IN6_SIN6_SCOPE_ID 1
@@ -68,9 +68,6 @@
 /* Define this as a suitable file to read random data from */
 #undef RANDOM_FILE
 
-/* Define this to your Entropy Gathering Daemon socket pathname */
-#undef EGD_SOCKET
-
 /* Define to 1 if you have the alarm function. */
 #define HAVE_ALARM 1
 
@@ -107,9 +104,6 @@
 /* Define if you have the `timeval' struct. */
 #define HAVE_STRUCT_TIMEVAL
 
-/* Define if you have the  header file. */
-#define HAVE_INTTYPES_H
-
 /* Define if you have the  header file. */
 #undef HAVE_IO_H
 
@@ -122,12 +116,6 @@
 /* Define if you have the GNU gssapi libraries */
 #undef HAVE_GSSGNU
 
-/* Define if you have the Heimdal gssapi libraries */
-#define HAVE_GSSHEIMDAL
-
-/* Define if you have the MIT gssapi libraries */
-#undef HAVE_GSSMIT
-
 /* Define if you need the malloc.h header file even with stdlib.h  */
 /* #define NEED_MALLOC_H 1 */
 
@@ -143,9 +131,6 @@
 /* Define if you have the  header file. */
 #define HAVE_PWD_H
 
-/* Define if you have the `RAND_egd' function. */
-#undef HAVE_RAND_EGD
-
 /* Define if you have the `select' function. */
 #define HAVE_SELECT
 
@@ -155,21 +140,9 @@
 /* Define if you have the `signal' function. */
 #undef HAVE_SIGNAL
 
-/* Define if you have the  header file. */
-#define HAVE_SIGNAL_H
-
 /* Define if you have the `socket' function. */
 #define HAVE_SOCKET
 
-/* Define if you have the  header file. */
-#undef HAVE_SSL_H
-
-/* Define if you have the  header file. */
-#undef HAVE_STDINT_H
-
-/* Define if you have the  header file. */
-#define HAVE_STDLIB_H
-
 
 /* The following define is needed on OS400 to enable strcmpi(), stricmp() and
    strdup(). */
@@ -190,9 +163,6 @@
 /* Define if you have the  header file. */
 #define HAVE_STRINGS_H
 
-/* Define if you have the  header file. */
-#define HAVE_STRING_H
-
 /* Define if you have the  header file. */
 #undef HAVE_STROPTS_H
 
@@ -235,9 +205,6 @@
 /* Define if you have the  header file. */
 #undef HAVE_TERMIO_H
 
-/* Define if you have the  header file. */
-#define HAVE_TIME_H
-
 /* Define if you have the  header file. */
 #define HAVE_UNISTD_H
 
@@ -268,12 +235,9 @@
 /* Define if you have the ANSI C header files. */
 #define STDC_HEADERS
 
-/* Define if you can safely include both  and . */
-#define TIME_WITH_SYS_TIME
-
 /* Define to enable HTTP3 support (experimental, requires NGTCP2, QUICHE or
    MSH3) */
-#undef ENABLE_QUIC
+#undef USE_HTTP3
 
 /* Version number of package */
 #undef VERSION
@@ -347,9 +311,6 @@
 /* Define to the function return type for send. */
 #define SEND_TYPE_RETV int
 
-/* Define to use the GSKit package. */
-#define USE_GSKIT
-
 /* Define to use the OS/400 crypto library. */
 #define USE_OS400CRYPTO
 
diff --git a/vendor/curl/lib/config-plan9.h b/vendor/curl/lib/config-plan9.h
index 54f89b06cf..6f3a15a5ef 100644
--- a/vendor/curl/lib/config-plan9.h
+++ b/vendor/curl/lib/config-plan9.h
@@ -28,7 +28,7 @@
 #define CURL_CA_BUNDLE "/sys/lib/tls/ca.pem"
 #define CURL_CA_PATH "/sys/lib/tls"
 #define CURL_STATICLIB 1
-#define ENABLE_IPV6 1
+#define USE_IPV6 1
 #define CURL_DISABLE_LDAP 1
 
 #define NEED_REENTRANT 1
@@ -91,7 +91,6 @@
 #define HAVE_GMTIME_R 1
 #define HAVE_INET_NTOP 1
 #define HAVE_INET_PTON 1
-#define HAVE_INTTYPES_H 1
 #define HAVE_LIBGEN_H 1
 #define HAVE_LIBZ 1
 #define HAVE_LOCALE_H 1
@@ -108,22 +107,17 @@
 #define HAVE_POLL_FINE 1
 #define HAVE_POLL_H 1
 #define HAVE_PTHREAD_H 1
-#define HAVE_SETJMP_H 1
 #define HAVE_SETLOCALE 1
 
 #define HAVE_SIGACTION 1
 #define HAVE_SIGNAL 1
-#define HAVE_SIGNAL_H 1
 #define HAVE_SIGSETJMP 1
 #define HAVE_SOCKADDR_IN6_SIN6_SCOPE_ID 1
 #define HAVE_SOCKET 1
 #define HAVE_SSL_GET_SHUTDOWN 1
 #define HAVE_STDBOOL_H 1
-#define HAVE_STDINT_H 1
-#define HAVE_STDLIB_H 1
 #define HAVE_STRCASECMP 1
 #define HAVE_STRDUP 1
-#define HAVE_STRING_H 1
 #define HAVE_STRTOK_R 1
 #define HAVE_STRTOLL 1
 #define HAVE_STRUCT_TIMEVAL 1
@@ -136,15 +130,12 @@
 #define HAVE_SYS_TYPES_H 1
 #define HAVE_SYS_UN_H 1
 #define HAVE_TERMIOS_H 1
-#define HAVE_TIME_H 1
 #define HAVE_UNISTD_H 1
 #define HAVE_UTIME 1
 #define HAVE_UTIME_H 1
 
 #define HAVE_POSIX_STRERROR_R 1
 #define HAVE_STRERROR_R 1
-
-#define TIME_WITH_SYS_TIME 1
 #define USE_MANUAL 1
 
 #define __attribute__(x)
diff --git a/vendor/curl/lib/config-riscos.h b/vendor/curl/lib/config-riscos.h
index 246473194e..eb1d26ec77 100644
--- a/vendor/curl/lib/config-riscos.h
+++ b/vendor/curl/lib/config-riscos.h
@@ -55,7 +55,7 @@
 #undef NEED_REENTRANT
 
 /* Define if you want to enable IPv6 support */
-#undef ENABLE_IPV6
+#undef USE_IPV6
 
 /* Define if struct sockaddr_in6 has the sin6_scope_id member */
 #define HAVE_SOCKADDR_IN6_SIN6_SCOPE_ID 1
@@ -66,12 +66,6 @@
 /* Define this as a suitable file to read random data from */
 #undef RANDOM_FILE
 
-/* Define this to your Entropy Gathering Daemon socket pathname */
-#undef EGD_SOCKET
-
-/* Define if you want to enable IPv6 support */
-#undef ENABLE_IPV6
-
 /* Define if you have the alarm function. */
 #define HAVE_ALARM
 
@@ -111,9 +105,6 @@
 /* Define if you have the `timeval' struct. */
 #define HAVE_STRUCT_TIMEVAL
 
-/* Define if you have the  header file. */
-#define HAVE_INTTYPES_H
-
 /* Define if you have the  header file. */
 #undef HAVE_IO_H
 
@@ -135,9 +126,6 @@
 /* Define if you have the  header file. */
 #undef HAVE_PWD_H
 
-/* Define if you have the `RAND_egd' function. */
-#undef HAVE_RAND_EGD
-
 /* Define if you have the `select' function. */
 #define HAVE_SELECT
 
@@ -147,21 +135,9 @@
 /* Define if you have the `signal' function. */
 #define HAVE_SIGNAL
 
-/* Define if you have the  header file. */
-#define HAVE_SIGNAL_H
-
 /* Define if you have the `socket' function. */
 #define HAVE_SOCKET
 
-/* Define if you have the  header file. */
-#undef HAVE_SSL_H
-
-/* Define if you have the  header file. */
-#undef HAVE_STDINT_H
-
-/* Define if you have the  header file. */
-#define HAVE_STDLIB_H
-
 /* Define if you have the `strcasecmp' function. */
 #undef HAVE_STRCASECMP
 
@@ -177,9 +153,6 @@
 /* Define if you have the  header file. */
 #undef HAVE_STRINGS_H
 
-/* Define if you have the  header file. */
-#define HAVE_STRING_H
-
 /* Define if you have the `strtok_r' function. */
 #undef HAVE_STRTOK_R
 
@@ -213,9 +186,6 @@
 /* Define if you have the  header file. */
 #undef HAVE_TERMIO_H
 
-/* Define if you have the  header file. */
-#undef HAVE_TIME_H
-
 /* Define if you have the  header file. */
 #define HAVE_UNISTD_H
 
@@ -234,9 +204,6 @@
 /* Define if you have the ANSI C header files. */
 #undef STDC_HEADERS
 
-/* Define if you can safely include both  and . */
-#undef TIME_WITH_SYS_TIME
-
 /* Version number of package */
 #undef VERSION
 
diff --git a/vendor/curl/lib/config-win32.h b/vendor/curl/lib/config-win32.h
index 0879e232ab..d1341933b3 100644
--- a/vendor/curl/lib/config-win32.h
+++ b/vendor/curl/lib/config-win32.h
@@ -38,19 +38,6 @@
 /* Define if you have the  header file. */
 #define HAVE_FCNTL_H 1
 
-/* Define to 1 if you have the  header file. */
-#if defined(__MINGW32__) || \
-    (defined(_MSC_VER) && (_MSC_VER >= 1800))
-#define HAVE_INTTYPES_H 1
-#endif
-
-/* Define to 1 if you have the  header file. */
-#if defined(__MINGW32__) || defined(__POCC__) || \
-    (defined(_MSC_VER) && (_MSC_VER >= 1600)) || \
-    (defined(__BORLANDC__) && (__BORLANDC__ >= 0x0582))
-#define HAVE_STDINT_H 1
-#endif
-
 /* Define if you have the  header file. */
 #define HAVE_IO_H 1
 
@@ -58,9 +45,7 @@
 #define HAVE_LOCALE_H 1
 
 /* Define if you need  header even with  header file. */
-#if !defined(__SALFORDC__) && !defined(__POCC__)
 #define NEED_MALLOC_H 1
-#endif
 
 /* Define if you have the  header file. */
 /* #define HAVE_NETDB_H 1 */
@@ -68,23 +53,15 @@
 /* Define if you have the  header file. */
 /* #define HAVE_NETINET_IN_H 1 */
 
-/* Define if you have the  header file. */
-#define HAVE_SIGNAL_H 1
-
-/* Define if you have the  header file. */
-/* #define HAVE_SSL_H 1 */
-
 /* Define to 1 if you have the  header file. */
-#if (defined(_MSC_VER) && (_MSC_VER >= 1800)) || \
-    defined(__MINGW64_VERSION_MAJOR)
+#if (defined(_MSC_VER) && (_MSC_VER >= 1800)) || defined(__MINGW32__)
 #define HAVE_STDBOOL_H 1
 #endif
 
-/* Define if you have the  header file. */
-#define HAVE_STDLIB_H 1
-
 /* Define if you have the  header file. */
-/* #define HAVE_SYS_PARAM_H 1 */
+#if defined(__MINGW32__)
+#define HAVE_SYS_PARAM_H 1
+#endif
 
 /* Define if you have the  header file. */
 /* #define HAVE_SYS_SELECT_H 1 */
@@ -99,15 +76,15 @@
 #define HAVE_SYS_STAT_H 1
 
 /* Define if you have the  header file. */
-/* #define HAVE_SYS_TIME_H 1 */
+#if defined(__MINGW32__)
+#define HAVE_SYS_TIME_H 1
+#endif
 
 /* Define if you have the  header file. */
 #define HAVE_SYS_TYPES_H 1
 
 /* Define if you have the  header file. */
-#ifndef __BORLANDC__
 #define HAVE_SYS_UTIME_H 1
-#endif
 
 /* Define if you have the  header file. */
 /* #define HAVE_TERMIO_H 1 */
@@ -115,35 +92,13 @@
 /* Define if you have the  header file. */
 /* #define HAVE_TERMIOS_H 1 */
 
-/* Define if you have the  header file. */
-#define HAVE_TIME_H 1
-
 /* Define if you have the  header file. */
-#if defined(__MINGW32__) || defined(__LCC__) || defined(__POCC__)
+#if defined(__MINGW32__)
 #define HAVE_UNISTD_H 1
 #endif
 
-/* Define if you have the  header file. */
-#define HAVE_WINDOWS_H 1
-
-/* Define if you have the  header file. */
-#ifndef __SALFORDC__
-#define HAVE_WINSOCK2_H 1
-#endif
-
-/* Define if you have the  header file. */
-#ifndef __SALFORDC__
-#define HAVE_WS2TCPIP_H 1
-#endif
-
-/* Define to 1 if you have the  header file. */
-#define HAVE_SETJMP_H 1
-
-/* Define to 1 if you have the  header file. */
-#define HAVE_STRING_H 1
-
 /* Define to 1 if you have the  header file. */
-#if defined(__MINGW64_VERSION_MAJOR)
+#if defined(__MINGW32__)
 #define HAVE_LIBGEN_H 1
 #endif
 
@@ -154,12 +109,8 @@
 /* Define if you have the ANSI C header files. */
 #define STDC_HEADERS 1
 
-/* Define if you can safely include both  and . */
-/* #define TIME_WITH_SYS_TIME 1 */
-
 /* Define to 1 if bool is an available type. */
-#if (defined(_MSC_VER) && (_MSC_VER >= 1800)) || \
-    defined(__MINGW64_VERSION_MAJOR)
+#if (defined(_MSC_VER) && (_MSC_VER >= 1800)) || defined(__MINGW32__)
 #define HAVE_BOOL_T 1
 #endif
 
@@ -171,7 +122,7 @@
 #define HAVE_CLOSESOCKET 1
 
 /* Define if you have the ftruncate function. */
-#if defined(__MINGW64_VERSION_MAJOR)
+#if defined(__MINGW32__)
 #define HAVE_FTRUNCATE 1
 #endif
 
@@ -185,7 +136,9 @@
 #define HAVE_GETHOSTNAME 1
 
 /* Define if you have the gettimeofday function. */
-/* #define HAVE_GETTIMEOFDAY 1 */
+#if defined(__MINGW32__)
+#define HAVE_GETTIMEOFDAY 1
+#endif
 
 /* Define if you have the ioctlsocket function. */
 #define HAVE_IOCTLSOCKET 1
@@ -206,7 +159,7 @@
 #define HAVE_SOCKET 1
 
 /* Define if you have the strcasecmp function. */
-#ifdef __MINGW32__
+#if defined(__MINGW32__)
 #define HAVE_STRCASECMP 1
 #endif
 
@@ -217,15 +170,12 @@
 #define HAVE_STRICMP 1
 
 /* Define if you have the strtoll function. */
-#if defined(__MINGW32__) || defined(__POCC__) || \
-    (defined(_MSC_VER) && (_MSC_VER >= 1800))
+#if (defined(_MSC_VER) && (_MSC_VER >= 1800)) || defined(__MINGW32__)
 #define HAVE_STRTOLL 1
 #endif
 
 /* Define if you have the utime function. */
-#ifndef __BORLANDC__
 #define HAVE_UTIME 1
-#endif
 
 /* Define if you have the recv function. */
 #define HAVE_RECV 1
@@ -267,7 +217,7 @@
 #define SEND_TYPE_RETV int
 
 /* Define to 1 if you have the snprintf function. */
-#if defined(_MSC_VER) && (_MSC_VER >= 1900)
+#if (defined(_MSC_VER) && (_MSC_VER >= 1900)) || defined(__MINGW32__)
 #define HAVE_SNPRINTF 1
 #endif
 
@@ -279,12 +229,12 @@
 #endif
 
 /* Define to 1 if you have the `basename' function. */
-#if defined(__MINGW64_VERSION_MAJOR)
+#if defined(__MINGW32__)
 #define HAVE_BASENAME 1
 #endif
 
 /* Define to 1 if you have the strtok_r function. */
-#if defined(__MINGW64_VERSION_MAJOR)
+#if defined(__MINGW32__)
 #define HAVE_STRTOK_R 1
 #endif
 
@@ -300,7 +250,7 @@
 
 /* Define if ssize_t is not an available 'typedefed' type. */
 #ifndef _SSIZE_T_DEFINED
-#  if defined(__POCC__) || defined(__MINGW32__)
+#  if defined(__MINGW32__)
 #  elif defined(_WIN64)
 #    define _SSIZE_T_DEFINED
 #    define ssize_t __int64
@@ -333,56 +283,6 @@
 /* Define to the size of `curl_off_t', as computed by sizeof. */
 #define SIZEOF_CURL_OFF_T 8
 
-/* ---------------------------------------------------------------- */
-/*               BSD-style lwIP TCP/IP stack SPECIFIC               */
-/* ---------------------------------------------------------------- */
-
-/* Define to use BSD-style lwIP TCP/IP stack. */
-/* #define USE_LWIPSOCK 1 */
-
-#ifdef USE_LWIPSOCK
-#  undef USE_WINSOCK
-#  undef HAVE_WINSOCK2_H
-#  undef HAVE_WS2TCPIP_H
-#  undef HAVE_GETHOSTNAME
-#  undef LWIP_POSIX_SOCKETS_IO_NAMES
-#  undef RECV_TYPE_ARG1
-#  undef RECV_TYPE_ARG3
-#  undef SEND_TYPE_ARG1
-#  undef SEND_TYPE_ARG3
-#  define HAVE_FREEADDRINFO
-#  define HAVE_GETADDRINFO
-#  define HAVE_GETHOSTBYNAME_R
-#  define HAVE_GETHOSTBYNAME_R_6
-#  define LWIP_POSIX_SOCKETS_IO_NAMES 0
-#  define RECV_TYPE_ARG1 int
-#  define RECV_TYPE_ARG3 size_t
-#  define SEND_TYPE_ARG1 int
-#  define SEND_TYPE_ARG3 size_t
-#endif
-
-/* ---------------------------------------------------------------- */
-/*                        Watt-32 tcp/ip SPECIFIC                   */
-/* ---------------------------------------------------------------- */
-
-#ifdef USE_WATT32
-  #include 
-  #undef byte
-  #undef word
-  #undef USE_WINSOCK
-  #undef HAVE_WINSOCK2_H
-  #undef HAVE_WS2TCPIP_H
-  #define HAVE_GETADDRINFO
-  #define HAVE_SYS_IOCTL_H
-  #define HAVE_SYS_SOCKET_H
-  #define HAVE_NETINET_IN_H
-  #define HAVE_NETDB_H
-  #define HAVE_ARPA_INET_H
-  #define HAVE_FREEADDRINFO
-  #define SOCKET int
-#endif
-
-
 /* ---------------------------------------------------------------- */
 /*                        COMPILER SPECIFIC                         */
 /* ---------------------------------------------------------------- */
@@ -396,15 +296,8 @@
 /* Windows should not have HAVE_GMTIME_R defined */
 /* #undef HAVE_GMTIME_R */
 
-/* Define if the compiler supports C99 variadic macro style. */
-#if defined(_MSC_VER) && (_MSC_VER >= 1400)
-#define HAVE_VARIADIC_MACROS_C99 1
-#endif
-
 /* Define if the compiler supports the 'long long' data type. */
-#if defined(__MINGW32__) || \
-    (defined(_MSC_VER)     && (_MSC_VER     >= 1310)) || \
-    (defined(__BORLANDC__) && (__BORLANDC__ >= 0x561))
+#if (defined(_MSC_VER) && (_MSC_VER >= 1310)) || defined(__MINGW32__)
 #define HAVE_LONGLONG 1
 #endif
 
@@ -414,11 +307,9 @@
 #define _CRT_NONSTDC_NO_DEPRECATE 1
 #endif
 
-/* mingw-w64, mingw using >= MSVCR80, and visual studio >= 2005 (MSVCR80)
+/* mingw-w64 and visual studio >= 2005 (MSVCR80)
    all default to 64-bit time_t unless _USE_32BIT_TIME_T is defined */
-#if defined(__MINGW64_VERSION_MAJOR) || \
-    (defined(__MINGW32__) && (__MSVCRT_VERSION__ >= 0x0800)) || \
-    (defined(_MSC_VER) && (_MSC_VER >= 1400))
+#if (defined(_MSC_VER) && (_MSC_VER >= 1400)) || defined(__MINGW32__)
 #  ifndef _USE_32BIT_TIME_T
 #    define SIZEOF_TIME_T 8
 #  else
@@ -488,53 +379,17 @@ Vista
 #  endif
 #endif
 
-/* When no build target is specified Pelles C 5.00 and later default build
-   target is Windows Vista. We override default target to be Windows 2000. */
-#if defined(__POCC__) && (__POCC__ >= 500)
-#  ifndef _WIN32_WINNT
-#    define _WIN32_WINNT 0x0500
-#  endif
-#  ifndef WINVER
-#    define WINVER 0x0500
-#  endif
-#endif
-
-/* Availability of freeaddrinfo, getaddrinfo, and if_nametoindex
-   functions is quite convoluted, compiler dependent and even build target
-   dependent. */
-#if defined(HAVE_WS2TCPIP_H)
-#  if defined(__POCC__)
-#    define HAVE_FREEADDRINFO           1
-#    define HAVE_GETADDRINFO            1
-#    define HAVE_GETADDRINFO_THREADSAFE 1
-#  elif defined(_WIN32_WINNT) && (_WIN32_WINNT >= 0x0501)
-#    define HAVE_FREEADDRINFO           1
-#    define HAVE_GETADDRINFO            1
-#    define HAVE_GETADDRINFO_THREADSAFE 1
-#  elif defined(_MSC_VER) && (_MSC_VER >= 1200)
-#    define HAVE_FREEADDRINFO           1
-#    define HAVE_GETADDRINFO            1
-#    define HAVE_GETADDRINFO_THREADSAFE 1
-#  endif
-#endif
-
-#if defined(__POCC__)
-#  ifndef _MSC_VER
-#    error Microsoft extensions /Ze compiler option is required
-#  endif
-#  ifndef __POCC__OLDNAMES
-#    error Compatibility names /Go compiler option is required
-#  endif
-#endif
+/* Windows XP is required for freeaddrinfo, getaddrinfo */
+#define HAVE_FREEADDRINFO           1
+#define HAVE_GETADDRINFO            1
+#define HAVE_GETADDRINFO_THREADSAFE 1
 
 /* ---------------------------------------------------------------- */
 /*                          STRUCT RELATED                          */
 /* ---------------------------------------------------------------- */
 
 /* Define if you have struct sockaddr_storage. */
-#if !defined(__SALFORDC__) && !defined(__BORLANDC__)
 #define HAVE_STRUCT_SOCKADDR_STORAGE 1
-#endif
 
 /* Define if you have struct timeval. */
 #define HAVE_STRUCT_TIMEVAL 1
@@ -558,23 +413,23 @@ Vista
 #  define USE_WIN32_LARGE_FILES
 #endif
 
-#if defined(__POCC__)
-#  undef USE_WIN32_LARGE_FILES
-#endif
-
 #if !defined(USE_WIN32_LARGE_FILES) && !defined(USE_WIN32_SMALL_FILES)
 #  define USE_WIN32_SMALL_FILES
 #endif
 
 /* Number of bits in a file offset, on hosts where this is settable. */
-#if defined(USE_WIN32_LARGE_FILES) && defined(__MINGW64_VERSION_MAJOR)
+#if defined(USE_WIN32_LARGE_FILES) && defined(__MINGW32__)
 #  ifndef _FILE_OFFSET_BITS
 #  define _FILE_OFFSET_BITS 64
 #  endif
 #endif
 
+#ifdef USE_WIN32_LARGE_FILES
+#define HAVE__FSEEKI64
+#endif
+
 /* Define to the size of `off_t', as computed by sizeof. */
-#if defined(__MINGW64_VERSION_MAJOR) && \
+#if defined(__MINGW32__) && \
   defined(_FILE_OFFSET_BITS) && (_FILE_OFFSET_BITS == 64)
 #  define SIZEOF_OFF_T 8
 #else
@@ -619,10 +474,6 @@ Vista
 #define USE_WIN32_LDAP 1
 #endif
 
-#if defined(__POCC__) && defined(USE_WIN32_LDAP)
-#  define CURL_DISABLE_LDAP 1
-#endif
-
 /* Define to use the Windows crypto library. */
 #if !defined(CURL_WINDOWS_APP)
 #define USE_WIN32_CRYPTO
@@ -658,8 +509,4 @@ Vista
 /* If you want to build curl with the built-in manual */
 #define USE_MANUAL 1
 
-#if defined(__POCC__) || defined(USE_IPV6)
-#  define ENABLE_IPV6 1
-#endif
-
 #endif /* HEADER_CURL_CONFIG_WIN32_H */
diff --git a/vendor/curl/lib/config-win32ce.h b/vendor/curl/lib/config-win32ce.h
index 825f5e60ce..ae3ca290c3 100644
--- a/vendor/curl/lib/config-win32ce.h
+++ b/vendor/curl/lib/config-win32ce.h
@@ -50,15 +50,6 @@
 /* Define if you have the  header file.  */
 /* #define HAVE_NETINET_IN_H 1 */
 
-/* Define if you have the  header file. */
-#define HAVE_SIGNAL_H 1
-
-/* Define if you have the  header file.  */
-/* #define HAVE_SSL_H 1 */
-
-/* Define if you have the  header file.  */
-#define HAVE_STDLIB_H 1
-
 /* Define if you have the  header file.  */
 /* #define HAVE_SYS_PARAM_H 1 */
 
@@ -89,23 +80,11 @@
 /* Define if you have the  header file.  */
 /* #define HAVE_TERMIOS_H 1 */
 
-/* Define if you have the  header file.  */
-#define HAVE_TIME_H 1
-
 /* Define if you have the  header file.  */
-#if defined(__MINGW32__) || defined(__LCC__)
+#if defined(__MINGW32__)
 #define HAVE_UNISTD_H 1
 #endif
 
-/* Define if you have the  header file.  */
-#define HAVE_WINDOWS_H 1
-
-/* Define if you have the  header file.  */
-#define HAVE_WINSOCK2_H 1
-
-/* Define if you have the  header file.  */
-#define HAVE_WS2TCPIP_H 1
-
 /* ---------------------------------------------------------------- */
 /*                        OTHER HEADER INFO                         */
 /* ---------------------------------------------------------------- */
@@ -113,9 +92,6 @@
 /* Define if you have the ANSI C header files.  */
 #define STDC_HEADERS 1
 
-/* Define if you can safely include both  and .  */
-/* #define TIME_WITH_SYS_TIME 1 */
-
 /* ---------------------------------------------------------------- */
 /*                             FUNCTIONS                            */
 /* ---------------------------------------------------------------- */
@@ -205,8 +181,7 @@
 #define in_addr_t unsigned long
 
 /* Define ssize_t if it is not an available 'typedefed' type */
-#if defined(__POCC__)
-#elif defined(_WIN64)
+#if defined(_WIN64)
 #define ssize_t __int64
 #else
 #define ssize_t int
diff --git a/vendor/curl/lib/conncache.c b/vendor/curl/lib/conncache.c
index a21409c13f..2b5ee4f25f 100644
--- a/vendor/curl/lib/conncache.c
+++ b/vendor/curl/lib/conncache.c
@@ -68,8 +68,7 @@ static void bundle_destroy(struct connectbundle *bundle)
 static void bundle_add_conn(struct connectbundle *bundle,
                             struct connectdata *conn)
 {
-  Curl_llist_insert_next(&bundle->conn_list, bundle->conn_list.tail, conn,
-                         &conn->bundle_node);
+  Curl_llist_append(&bundle->conn_list, conn, &conn->bundle_node);
   conn->bundle = bundle;
   bundle->num_connections++;
 }
@@ -101,12 +100,13 @@ static void free_bundle_hash_entry(void *freethis)
   bundle_destroy(b);
 }
 
-int Curl_conncache_init(struct conncache *connc, int size)
+int Curl_conncache_init(struct conncache *connc, size_t size)
 {
   /* allocate a new easy handle to use when closing cached connections */
   connc->closure_handle = curl_easy_init();
   if(!connc->closure_handle)
     return 1; /* bad */
+  connc->closure_handle->state.internal = true;
 
   Curl_hash_init(&connc->hash, size, Curl_hash_str,
                  Curl_str_key_compare, free_bundle_hash_entry);
@@ -130,7 +130,7 @@ static void hashkey(struct connectdata *conn, char *buf, size_t len)
 #ifndef CURL_DISABLE_PROXY
   if(conn->bits.httpproxy && !conn->bits.tunnel_proxy) {
     hostname = conn->http_proxy.host.name;
-    port = conn->port;
+    port = conn->primary.remote_port;
   }
   else
 #endif
@@ -140,7 +140,7 @@ static void hashkey(struct connectdata *conn, char *buf, size_t len)
     hostname = conn->host.name;
 
   /* put the numbers first so that the hostname gets cut off if too long */
-#ifdef ENABLE_IPV6
+#ifdef USE_IPV6
   msnprintf(buf, len, "%u/%ld/%s", conn->scope_id, port, hostname);
 #else
   msnprintf(buf, len, "%ld/%s", port, hostname);
@@ -242,7 +242,7 @@ CURLcode Curl_conncache_add_conn(struct Curl_easy *data)
   conn->connection_id = connc->next_connection_id++;
   connc->num_conn++;
 
-  DEBUGF(infof(data, "Added connection %ld. "
+  DEBUGF(infof(data, "Added connection %" CURL_FORMAT_CURL_OFF_T ". "
                "The cache now contains %zu members",
                conn->connection_id, connc->num_conn));
 
@@ -378,21 +378,24 @@ conncache_find_first_connection(struct conncache *connc)
 bool Curl_conncache_return_conn(struct Curl_easy *data,
                                 struct connectdata *conn)
 {
-  /* data->multi->maxconnects can be negative, deal with it. */
-  size_t maxconnects =
-    (data->multi->maxconnects < 0) ? data->multi->num_easy * 4:
-    data->multi->maxconnects;
+  unsigned int maxconnects = !data->multi->maxconnects ?
+    data->multi->num_easy * 4: data->multi->maxconnects;
   struct connectdata *conn_candidate = NULL;
 
   conn->lastused = Curl_now(); /* it was used up until now */
-  if(maxconnects > 0 &&
-     Curl_conncache_size(data) > maxconnects) {
+  if(maxconnects && Curl_conncache_size(data) > maxconnects) {
     infof(data, "Connection cache is full, closing the oldest one");
 
     conn_candidate = Curl_conncache_extract_oldest(data);
     if(conn_candidate) {
-      /* the winner gets the honour of being disconnected */
-      Curl_disconnect(data, conn_candidate, /* dead_connection */ FALSE);
+      /* Use the closure handle for this disconnect so that anything that
+         happens during the disconnect is not stored and associated with the
+         'data' handle which already just finished a transfer and it is
+         important that details from this (unrelated) disconnect does not
+         taint meta-data in the data handle. */
+      struct conncache *connc = data->state.conn_cache;
+      Curl_disconnect(connc->closure_handle, conn_candidate,
+                      /* dead_connection */ FALSE);
     }
   }
 
@@ -516,12 +519,9 @@ Curl_conncache_extract_oldest(struct Curl_easy *data)
 void Curl_conncache_close_all_connections(struct conncache *connc)
 {
   struct connectdata *conn;
-  char buffer[READBUFFER_MIN + 1];
   SIGPIPE_VARIABLE(pipe_st);
   if(!connc->closure_handle)
     return;
-  connc->closure_handle->state.buffer = buffer;
-  connc->closure_handle->set.buffer_size = READBUFFER_MIN;
 
   conn = conncache_find_first_connection(connc);
   while(conn) {
@@ -535,7 +535,6 @@ void Curl_conncache_close_all_connections(struct conncache *connc)
     conn = conncache_find_first_connection(connc);
   }
 
-  connc->closure_handle->state.buffer = NULL;
   sigpipe_ignore(connc->closure_handle, &pipe_st);
 
   Curl_hostcache_clean(connc->closure_handle,
diff --git a/vendor/curl/lib/conncache.h b/vendor/curl/lib/conncache.h
index c60f8449ee..e685123948 100644
--- a/vendor/curl/lib/conncache.h
+++ b/vendor/curl/lib/conncache.h
@@ -85,7 +85,7 @@ struct connectbundle {
 };
 
 /* returns 1 on error, 0 is fine */
-int Curl_conncache_init(struct conncache *, int size);
+int Curl_conncache_init(struct conncache *, size_t size);
 void Curl_conncache_destroy(struct conncache *connc);
 
 /* return the correct bundle, to a host or a proxy */
diff --git a/vendor/curl/lib/connect.c b/vendor/curl/lib/connect.c
index 033fb7b17d..bf85e640f8 100644
--- a/vendor/curl/lib/connect.c
+++ b/vendor/curl/lib/connect.c
@@ -84,31 +84,26 @@
 #include "curl_memory.h"
 #include "memdebug.h"
 
+#ifndef ARRAYSIZE
+#define ARRAYSIZE(A) (sizeof(A)/sizeof((A)[0]))
+#endif
 
 /*
  * Curl_timeleft() returns the amount of milliseconds left allowed for the
  * transfer/connection. If the value is 0, there's no timeout (ie there's
  * infinite time left). If the value is negative, the timeout time has already
  * elapsed.
- *
- * If 'nowp' is non-NULL, it points to the current time.
- * 'duringconnect' is FALSE if not during a connect, as then of course the
- * connect timeout is not taken into account!
- *
+ * @param data the transfer to check on
+ * @param nowp timestamp to use for calculation, NULL to use Curl_now()
+ * @param duringconnect TRUE iff connect timeout is also taken into account.
  * @unittest: 1303
  */
-
-#define TIMEOUT_CONNECT 1
-#define TIMEOUT_MAXTIME 2
-
 timediff_t Curl_timeleft(struct Curl_easy *data,
                          struct curltime *nowp,
                          bool duringconnect)
 {
-  unsigned int timeout_set = 0;
-  timediff_t connect_timeout_ms = 0;
-  timediff_t maxtime_timeout_ms = 0;
-  timediff_t timeout_ms = 0;
+  timediff_t timeleft_ms = 0;
+  timediff_t ctimeleft_ms = 0;
   struct curltime now;
 
   /* The duration of a connect and the total transfer are calculated from two
@@ -116,61 +111,60 @@ timediff_t Curl_timeleft(struct Curl_easy *data,
      before the connect timeout expires and we must acknowledge whichever
      timeout that is reached first. The total timeout is set per entire
      operation, while the connect timeout is set per connect. */
-
-  if(data->set.timeout > 0) {
-    timeout_set = TIMEOUT_MAXTIME;
-    maxtime_timeout_ms = data->set.timeout;
-  }
-  if(duringconnect) {
-    timeout_set |= TIMEOUT_CONNECT;
-    connect_timeout_ms = (data->set.connecttimeout > 0) ?
-      data->set.connecttimeout : DEFAULT_CONNECT_TIMEOUT;
-  }
-  if(!timeout_set)
-    /* no timeout  */
-    return 0;
+  if(data->set.timeout <= 0 && !duringconnect)
+    return 0; /* no timeout in place or checked, return "no limit" */
 
   if(!nowp) {
     now = Curl_now();
     nowp = &now;
   }
 
-  if(timeout_set & TIMEOUT_MAXTIME) {
-    maxtime_timeout_ms -= Curl_timediff(*nowp, data->progress.t_startop);
-    timeout_ms = maxtime_timeout_ms;
+  if(data->set.timeout > 0) {
+    timeleft_ms = data->set.timeout -
+                  Curl_timediff(*nowp, data->progress.t_startop);
+    if(!timeleft_ms)
+      timeleft_ms = -1; /* 0 is "no limit", fake 1 ms expiry */
+    if(!duringconnect)
+      return timeleft_ms; /* no connect check, this is it */
   }
 
-  if(timeout_set & TIMEOUT_CONNECT) {
-    connect_timeout_ms -= Curl_timediff(*nowp, data->progress.t_startsingle);
-
-    if(!(timeout_set & TIMEOUT_MAXTIME) ||
-       (connect_timeout_ms < maxtime_timeout_ms))
-      timeout_ms = connect_timeout_ms;
+  if(duringconnect) {
+    timediff_t ctimeout_ms = (data->set.connecttimeout > 0) ?
+      data->set.connecttimeout : DEFAULT_CONNECT_TIMEOUT;
+    ctimeleft_ms = ctimeout_ms -
+                   Curl_timediff(*nowp, data->progress.t_startsingle);
+    if(!ctimeleft_ms)
+      ctimeleft_ms = -1; /* 0 is "no limit", fake 1 ms expiry */
+    if(!timeleft_ms)
+      return ctimeleft_ms; /* no general timeout, this is it */
   }
-
-  if(!timeout_ms)
-    /* avoid returning 0 as that means no timeout! */
-    return -1;
-
-  return timeout_ms;
+  /* return minimal time left or max amount already expired */
+  return (ctimeleft_ms < timeleft_ms)? ctimeleft_ms : timeleft_ms;
 }
 
 /* Copies connection info into the transfer handle to make it available when
    the transfer handle is no longer associated with the connection. */
 void Curl_persistconninfo(struct Curl_easy *data, struct connectdata *conn,
-                          char *local_ip, int local_port)
+                          struct ip_quadruple *ip)
 {
-  memcpy(data->info.conn_primary_ip, conn->primary_ip, MAX_IPADR_LEN);
-  if(local_ip && local_ip[0])
-    memcpy(data->info.conn_local_ip, local_ip, MAX_IPADR_LEN);
-  else
-    data->info.conn_local_ip[0] = 0;
+  if(ip)
+    data->info.primary = *ip;
+  else {
+    memset(&data->info.primary, 0, sizeof(data->info.primary));
+    data->info.primary.remote_port = -1;
+    data->info.primary.local_port = -1;
+  }
   data->info.conn_scheme = conn->handler->scheme;
   /* conn_protocol can only provide "old" protocols */
   data->info.conn_protocol = (conn->handler->protocol) & CURLPROTO_MASK;
-  data->info.conn_primary_port = conn->port;
   data->info.conn_remote_port = conn->remote_port;
-  data->info.conn_local_port = local_port;
+  data->info.used_proxy =
+#ifdef CURL_DISABLE_PROXY
+    0
+#else
+    conn->bits.proxy
+#endif
+    ;
 }
 
 static const struct Curl_addrinfo *
@@ -201,7 +195,7 @@ bool Curl_addr2string(struct sockaddr *sa, curl_socklen_t salen,
                       char *addr, int *port)
 {
   struct sockaddr_in *si = NULL;
-#ifdef ENABLE_IPV6
+#ifdef USE_IPV6
   struct sockaddr_in6 *si6 = NULL;
 #endif
 #if (defined(HAVE_SYS_UN_H) || defined(WIN32_SOCKADDR_UN)) && defined(AF_UNIX)
@@ -220,7 +214,7 @@ bool Curl_addr2string(struct sockaddr *sa, curl_socklen_t salen,
         return TRUE;
       }
       break;
-#ifdef ENABLE_IPV6
+#ifdef USE_IPV6
     case AF_INET6:
       si6 = (struct sockaddr_in6 *)(void *) sa;
       if(Curl_inet_ntop(sa->sa_family, &si6->sin6_addr,
@@ -348,6 +342,7 @@ void Curl_conncontrol(struct connectdata *conn,
  */
 struct eyeballer {
   const char *name;
+  const struct Curl_addrinfo *first; /* complete address list, not owned */
   const struct Curl_addrinfo *addr;  /* List of addresses to try, not owned */
   int ai_family;                     /* matching address family only */
   cf_ip_connect_create *cf_create;   /* for creating cf */
@@ -359,9 +354,12 @@ struct eyeballer {
   expire_id timeout_id;              /* ID for Curl_expire() */
   CURLcode result;
   int error;
+  BIT(rewinded);                     /* if we rewinded the addr list */
   BIT(has_started);                  /* attempts have started */
   BIT(is_done);                      /* out of addresses/time */
   BIT(connected);                    /* cf has connected */
+  BIT(inconclusive);                 /* connect was not a hard failure, we
+                                      * might talk to a restarting server */
 };
 
 
@@ -398,17 +396,17 @@ static CURLcode eyeballer_new(struct eyeballer **pballer,
   struct eyeballer *baller;
 
   *pballer = NULL;
-  baller = calloc(1, sizeof(*baller) + 1000);
+  baller = calloc(1, sizeof(*baller));
   if(!baller)
     return CURLE_OUT_OF_MEMORY;
 
   baller->name = ((ai_family == AF_INET)? "ipv4" : (
-#ifdef ENABLE_IPV6
+#ifdef USE_IPV6
                   (ai_family == AF_INET6)? "ipv6" :
 #endif
                   "ip"));
   baller->cf_create = cf_create;
-  baller->addr = addr;
+  baller->first = baller->addr = addr;
   baller->ai_family = ai_family;
   baller->primary = primary;
   baller->delay_ms = delay_ms;
@@ -438,6 +436,13 @@ static void baller_free(struct eyeballer *baller,
   }
 }
 
+static void baller_rewind(struct eyeballer *baller)
+{
+  baller->rewinded = TRUE;
+  baller->addr = baller->first;
+  baller->inconclusive = FALSE;
+}
+
 static void baller_next_addr(struct eyeballer *baller)
 {
   baller->addr = addr_next_match(baller->addr, baller->ai_family);
@@ -528,6 +533,10 @@ static CURLcode baller_start_next(struct Curl_cfilter *cf,
 {
   if(cf->sockindex == FIRSTSOCKET) {
     baller_next_addr(baller);
+    /* If we get inconclusive answers from the server(s), we make
+     * a second iteration over the address list */
+    if(!baller->addr && baller->inconclusive && !baller->rewinded)
+      baller_rewind(baller);
     baller_start(cf, data, baller, timeoutms);
   }
   else {
@@ -566,6 +575,8 @@ static CURLcode baller_connect(struct Curl_cfilter *cf,
         baller->result = CURLE_OPERATION_TIMEDOUT;
       }
     }
+    else if(baller->result == CURLE_WEIRD_SERVER_REPLY)
+      baller->inconclusive = TRUE;
   }
   return baller->result;
 }
@@ -595,7 +606,7 @@ static CURLcode is_connected(struct Curl_cfilter *cf,
   *connected = FALSE; /* a very negative world view is best */
   now = Curl_now();
   ongoing = not_started = 0;
-  for(i = 0; i < sizeof(ctx->baller)/sizeof(ctx->baller[0]); i++) {
+  for(i = 0; i < ARRAYSIZE(ctx->baller); i++) {
     struct eyeballer *baller = ctx->baller[i];
 
     if(!baller || baller->is_done)
@@ -634,6 +645,7 @@ static CURLcode is_connected(struct Curl_cfilter *cf,
         /* next attempt was started */
         CURL_TRC_CF(data, cf, "%s trying next", baller->name);
         ++ongoing;
+        Curl_expire(data, 0, EXPIRE_RUN_NOW);
       }
     }
   }
@@ -646,7 +658,7 @@ static CURLcode is_connected(struct Curl_cfilter *cf,
   /* Nothing connected, check the time before we might
    * start new ballers or return ok. */
   if((ongoing || not_started) && Curl_timeleft(data, &now, TRUE) < 0) {
-    failf(data, "Connection timeout after %ld ms",
+    failf(data, "Connection timeout after %" CURL_FORMAT_CURL_OFF_T " ms",
           Curl_timediff(now, data->progress.t_startsingle));
     return CURLE_OPERATION_TIMEDOUT;
   }
@@ -655,7 +667,7 @@ static CURLcode is_connected(struct Curl_cfilter *cf,
   if(not_started > 0) {
     int added = 0;
 
-    for(i = 0; i < sizeof(ctx->baller)/sizeof(ctx->baller[0]); i++) {
+    for(i = 0; i < ARRAYSIZE(ctx->baller); i++) {
       struct eyeballer *baller = ctx->baller[i];
 
       if(!baller || baller->has_started)
@@ -690,13 +702,13 @@ static CURLcode is_connected(struct Curl_cfilter *cf,
   /* all ballers have failed to connect. */
   CURL_TRC_CF(data, cf, "all eyeballers failed");
   result = CURLE_COULDNT_CONNECT;
-  for(i = 0; i < sizeof(ctx->baller)/sizeof(ctx->baller[0]); i++) {
+  for(i = 0; i < ARRAYSIZE(ctx->baller); i++) {
     struct eyeballer *baller = ctx->baller[i];
+    if(!baller)
+      continue;
     CURL_TRC_CF(data, cf, "%s assess started=%d, result=%d",
-                baller?baller->name:NULL,
-                baller?baller->has_started:0,
-                baller?baller->result:0);
-    if(baller && baller->has_started && baller->result) {
+                baller->name, baller->has_started, baller->result);
+    if(baller->has_started && baller->result) {
       result = baller->result;
       break;
     }
@@ -716,7 +728,7 @@ static CURLcode is_connected(struct Curl_cfilter *cf,
 
   failf(data, "Failed to connect to %s port %u after "
         "%" CURL_FORMAT_TIMEDIFF_T " ms: %s",
-        hostname, conn->port,
+        hostname, conn->primary.remote_port,
         Curl_timediff(now, data->progress.t_startsingle),
         curl_easy_strerror(result));
 
@@ -767,7 +779,7 @@ static CURLcode start_connect(struct Curl_cfilter *cf,
     /* any IP version is allowed */
     ai_family0 = remotehost->addr?
       remotehost->addr->ai_family : 0;
-#ifdef ENABLE_IPV6
+#ifdef USE_IPV6
     ai_family1 = ai_family0 == AF_INET6 ?
       AF_INET : AF_INET6;
 #else
@@ -778,7 +790,7 @@ static CURLcode start_connect(struct Curl_cfilter *cf,
     /* only one IP version is allowed */
     ai_family0 = (conn->ip_version == CURL_IPRESOLVE_V4) ?
       AF_INET :
-#ifdef ENABLE_IPV6
+#ifdef USE_IPV6
       AF_INET6;
 #else
       AF_UNSPEC;
@@ -823,11 +835,10 @@ static CURLcode start_connect(struct Curl_cfilter *cf,
     CURL_TRC_CF(data, cf, "created %s (timeout %"
                 CURL_FORMAT_TIMEDIFF_T "ms)",
                 ctx->baller[1]->name, ctx->baller[1]->timeoutms);
+    Curl_expire(data, data->set.happy_eyeballs_timeout,
+                EXPIRE_HAPPY_EYEBALLS);
   }
 
-  Curl_expire(data, data->set.happy_eyeballs_timeout,
-              EXPIRE_HAPPY_EYEBALLS);
-
   return CURLE_OK;
 }
 
@@ -838,7 +849,7 @@ static void cf_he_ctx_clear(struct Curl_cfilter *cf, struct Curl_easy *data)
 
   DEBUGASSERT(ctx);
   DEBUGASSERT(data);
-  for(i = 0; i < sizeof(ctx->baller)/sizeof(ctx->baller[0]); i++) {
+  for(i = 0; i < ARRAYSIZE(ctx->baller); i++) {
     baller_free(ctx->baller[i], data);
     ctx->baller[i] = NULL;
   }
@@ -846,35 +857,22 @@ static void cf_he_ctx_clear(struct Curl_cfilter *cf, struct Curl_easy *data)
   ctx->winner = NULL;
 }
 
-static int cf_he_get_select_socks(struct Curl_cfilter *cf,
+static void cf_he_adjust_pollset(struct Curl_cfilter *cf,
                                   struct Curl_easy *data,
-                                  curl_socket_t *socks)
+                                  struct easy_pollset *ps)
 {
   struct cf_he_ctx *ctx = cf->ctx;
-  size_t i, s;
-  int wrc, rc = GETSOCK_BLANK;
-  curl_socket_t wsocks[MAX_SOCKSPEREASYHANDLE];
-
-  if(cf->connected)
-    return cf->next->cft->get_select_socks(cf->next, data, socks);
-
-  for(i = s = 0; i < sizeof(ctx->baller)/sizeof(ctx->baller[0]); i++) {
-    struct eyeballer *baller = ctx->baller[i];
-    if(!baller || !baller->cf)
-      continue;
+  size_t i;
 
-    wrc = Curl_conn_cf_get_select_socks(baller->cf, data, wsocks);
-    if(wrc) {
-      /* TODO: we assume we get at most one socket back */
-      socks[s] = wsocks[0];
-      if(wrc & GETSOCK_WRITESOCK(0))
-        rc |= GETSOCK_WRITESOCK(s);
-      if(wrc & GETSOCK_READSOCK(0))
-        rc |= GETSOCK_READSOCK(s);
-      s++;
+  if(!cf->connected) {
+    for(i = 0; i < ARRAYSIZE(ctx->baller); i++) {
+      struct eyeballer *baller = ctx->baller[i];
+      if(!baller || !baller->cf)
+        continue;
+      Curl_conn_cf_adjust_pollset(baller->cf, data, ps);
     }
+    CURL_TRC_CF(data, cf, "adjust_pollset -> %d socks", ps->num);
   }
-  return rc;
 }
 
 static CURLcode cf_he_connect(struct Curl_cfilter *cf,
@@ -901,7 +899,7 @@ static CURLcode cf_he_connect(struct Curl_cfilter *cf,
       if(result)
         return result;
       ctx->state = SCFST_WAITING;
-      /* FALLTHROUGH */
+      FALLTHROUGH();
     case SCFST_WAITING:
       result = is_connected(cf, data, done);
       if(!result && *done) {
@@ -920,7 +918,7 @@ static CURLcode cf_he_connect(struct Curl_cfilter *cf,
 
         if(cf->conn->handler->protocol & PROTO_FAMILY_SSH)
           Curl_pgrsTime(data, TIMER_APPCONNECT); /* we're connected already */
-        Curl_verboseconnect(data, cf->conn);
+        Curl_verboseconnect(data, cf->conn, cf->sockindex);
         data->info.numconnects++; /* to track the # of connections made */
       }
       break;
@@ -956,7 +954,7 @@ static bool cf_he_data_pending(struct Curl_cfilter *cf,
   if(cf->connected)
     return cf->next->cft->has_data_pending(cf->next, data);
 
-  for(i = 0; i < sizeof(ctx->baller)/sizeof(ctx->baller[0]); i++) {
+  for(i = 0; i < ARRAYSIZE(ctx->baller); i++) {
     struct eyeballer *baller = ctx->baller[i];
     if(!baller || !baller->cf)
       continue;
@@ -975,7 +973,7 @@ static struct curltime get_max_baller_time(struct Curl_cfilter *cf,
   size_t i;
 
   memset(&tmax, 0, sizeof(tmax));
-  for(i = 0; i < sizeof(ctx->baller)/sizeof(ctx->baller[0]); i++) {
+  for(i = 0; i < ARRAYSIZE(ctx->baller); i++) {
     struct eyeballer *baller = ctx->baller[i];
 
     memset(&t, 0, sizeof(t));
@@ -1000,7 +998,7 @@ static CURLcode cf_he_query(struct Curl_cfilter *cf,
       int reply_ms = -1;
       size_t i;
 
-      for(i = 0; i < sizeof(ctx->baller)/sizeof(ctx->baller[0]); i++) {
+      for(i = 0; i < ARRAYSIZE(ctx->baller); i++) {
         struct eyeballer *baller = ctx->baller[i];
         int breply_ms;
 
@@ -1055,7 +1053,7 @@ struct Curl_cftype Curl_cft_happy_eyeballs = {
   cf_he_connect,
   cf_he_close,
   Curl_cf_def_get_host,
-  cf_he_get_select_socks,
+  cf_he_adjust_pollset,
   cf_he_data_pending,
   Curl_cf_def_send,
   Curl_cf_def_recv,
@@ -1089,7 +1087,7 @@ cf_happy_eyeballs_create(struct Curl_cfilter **pcf,
   (void)data;
   (void)conn;
   *pcf = NULL;
-  ctx = calloc(sizeof(*ctx), 1);
+  ctx = calloc(1, sizeof(*ctx));
   if(!ctx) {
     result = CURLE_OUT_OF_MEMORY;
     goto out;
@@ -1119,16 +1117,16 @@ const
 #endif
 struct transport_provider transport_providers[] = {
   { TRNSPRT_TCP, Curl_cf_tcp_create },
-#ifdef ENABLE_QUIC
+#ifdef USE_HTTP3
   { TRNSPRT_QUIC, Curl_cf_quic_create },
 #endif
+#ifndef CURL_DISABLE_TFTP
   { TRNSPRT_UDP, Curl_cf_udp_create },
+#endif
+#ifdef USE_UNIX_SOCKETS
   { TRNSPRT_UNIX, Curl_cf_unix_create },
-};
-
-#ifndef ARRAYSIZE
-#define ARRAYSIZE(A) (sizeof(A)/sizeof((A)[0]))
 #endif
+};
 
 static cf_ip_connect_create *get_cf_create(int transport)
 {
@@ -1319,7 +1317,7 @@ struct Curl_cftype Curl_cft_setup = {
   cf_setup_connect,
   cf_setup_close,
   Curl_cf_def_get_host,
-  Curl_cf_def_get_select_socks,
+  Curl_cf_def_adjust_pollset,
   Curl_cf_def_data_pending,
   Curl_cf_def_send,
   Curl_cf_def_recv,
@@ -1340,7 +1338,7 @@ static CURLcode cf_setup_create(struct Curl_cfilter **pcf,
   CURLcode result = CURLE_OK;
 
   (void)data;
-  ctx = calloc(sizeof(*ctx), 1);
+  ctx = calloc(1, sizeof(*ctx));
   if(!ctx) {
     result = CURLE_OUT_OF_MEMORY;
     goto out;
diff --git a/vendor/curl/lib/connect.h b/vendor/curl/lib/connect.h
index 58264bdba4..00efe6f34e 100644
--- a/vendor/curl/lib/connect.h
+++ b/vendor/curl/lib/connect.h
@@ -30,6 +30,7 @@
 #include "timeval.h"
 
 struct Curl_dns_entry;
+struct ip_quadruple;
 
 /* generic function that returns how much time there's left to run, according
    to the timeouts set */
@@ -52,7 +53,7 @@ bool Curl_addr2string(struct sockaddr *sa, curl_socklen_t salen,
                       char *addr, int *port);
 
 void Curl_persistconninfo(struct Curl_easy *data, struct connectdata *conn,
-                          char *local_ip, int local_port);
+                          struct ip_quadruple *ip);
 
 /*
  * Curl_conncontrol() marks the end of a connection/stream. The 'closeit'
diff --git a/vendor/curl/lib/content_encoding.c b/vendor/curl/lib/content_encoding.c
index efbe7cb18d..d34d3a1f5e 100644
--- a/vendor/curl/lib/content_encoding.c
+++ b/vendor/curl/lib/content_encoding.c
@@ -63,6 +63,9 @@
 
 #ifndef CURL_DISABLE_HTTP
 
+/* allow no more than 5 "chained" compression steps */
+#define MAX_ENCODE_STACK 5
+
 #define DSIZ CURL_MAX_WRITE_SIZE /* buffer size for decompressed data */
 
 
@@ -95,7 +98,7 @@ typedef enum {
 
 /* Deflate and gzip writer. */
 struct zlib_writer {
-  struct contenc_writer super;
+  struct Curl_cwriter super;
   zlibInitState zlib_init;   /* zlib init state */
   uInt trailerlen;           /* Remaining trailer byte count. */
   z_stream z;                /* State structure for zlib. */
@@ -171,7 +174,7 @@ static CURLcode process_trailer(struct Curl_easy *data,
 }
 
 static CURLcode inflate_stream(struct Curl_easy *data,
-                               struct contenc_writer *writer,
+                               struct Curl_cwriter *writer, int type,
                                zlibInitState started)
 {
   struct zlib_writer *zp = (struct zlib_writer *) writer;
@@ -196,7 +199,7 @@ static CURLcode inflate_stream(struct Curl_easy *data,
     return exit_zlib(data, z, &zp->zlib_init, CURLE_OUT_OF_MEMORY);
 
   /* because the buffer size is fixed, iteratively decompress and transfer to
-     the client via downstream_write function. */
+     the client via next_write function. */
   while(!done) {
     int status;                   /* zlib status */
     done = TRUE;
@@ -217,7 +220,7 @@ static CURLcode inflate_stream(struct Curl_easy *data,
     if(z->avail_out != DSIZ) {
       if(status == Z_OK || status == Z_STREAM_END) {
         zp->zlib_init = started;      /* Data started. */
-        result = Curl_unencode_write(data, writer->downstream, decomp,
+        result = Curl_cwriter_write(data, writer->next, type, decomp,
                                      DSIZ - z->avail_out);
         if(result) {
           exit_zlib(data, z, &zp->zlib_init, result);
@@ -274,15 +277,12 @@ static CURLcode inflate_stream(struct Curl_easy *data,
 
 
 /* Deflate handler. */
-static CURLcode deflate_init_writer(struct Curl_easy *data,
-                                    struct contenc_writer *writer)
+static CURLcode deflate_do_init(struct Curl_easy *data,
+                                    struct Curl_cwriter *writer)
 {
   struct zlib_writer *zp = (struct zlib_writer *) writer;
   z_stream *z = &zp->z;     /* zlib state structure */
 
-  if(!writer->downstream)
-    return CURLE_WRITE_ERROR;
-
   /* Initialize zlib */
   z->zalloc = (alloc_func) zalloc_cb;
   z->zfree = (free_func) zfree_cb;
@@ -293,13 +293,16 @@ static CURLcode deflate_init_writer(struct Curl_easy *data,
   return CURLE_OK;
 }
 
-static CURLcode deflate_unencode_write(struct Curl_easy *data,
-                                       struct contenc_writer *writer,
+static CURLcode deflate_do_write(struct Curl_easy *data,
+                                       struct Curl_cwriter *writer, int type,
                                        const char *buf, size_t nbytes)
 {
   struct zlib_writer *zp = (struct zlib_writer *) writer;
   z_stream *z = &zp->z;     /* zlib state structure */
 
+  if(!(type & CLIENTWRITE_BODY) || !nbytes)
+    return Curl_cwriter_write(data, writer->next, type, buf, nbytes);
+
   /* Set the compressed input when this function is called */
   z->next_in = (Bytef *) buf;
   z->avail_in = (uInt) nbytes;
@@ -308,11 +311,11 @@ static CURLcode deflate_unencode_write(struct Curl_easy *data,
     return process_trailer(data, zp);
 
   /* Now uncompress the data */
-  return inflate_stream(data, writer, ZLIB_INFLATING);
+  return inflate_stream(data, writer, type, ZLIB_INFLATING);
 }
 
-static void deflate_close_writer(struct Curl_easy *data,
-                                 struct contenc_writer *writer)
+static void deflate_do_close(struct Curl_easy *data,
+                                 struct Curl_cwriter *writer)
 {
   struct zlib_writer *zp = (struct zlib_writer *) writer;
   z_stream *z = &zp->z;     /* zlib state structure */
@@ -320,26 +323,23 @@ static void deflate_close_writer(struct Curl_easy *data,
   exit_zlib(data, z, &zp->zlib_init, CURLE_OK);
 }
 
-static const struct content_encoding deflate_encoding = {
+static const struct Curl_cwtype deflate_encoding = {
   "deflate",
   NULL,
-  deflate_init_writer,
-  deflate_unencode_write,
-  deflate_close_writer,
+  deflate_do_init,
+  deflate_do_write,
+  deflate_do_close,
   sizeof(struct zlib_writer)
 };
 
 
 /* Gzip handler. */
-static CURLcode gzip_init_writer(struct Curl_easy *data,
-                                 struct contenc_writer *writer)
+static CURLcode gzip_do_init(struct Curl_easy *data,
+                                 struct Curl_cwriter *writer)
 {
   struct zlib_writer *zp = (struct zlib_writer *) writer;
   z_stream *z = &zp->z;     /* zlib state structure */
 
-  if(!writer->downstream)
-    return CURLE_WRITE_ERROR;
-
   /* Initialize zlib */
   z->zalloc = (alloc_func) zalloc_cb;
   z->zfree = (free_func) zfree_cb;
@@ -365,11 +365,14 @@ static CURLcode gzip_init_writer(struct Curl_easy *data,
 
 #ifdef OLD_ZLIB_SUPPORT
 /* Skip over the gzip header */
-static enum {
+typedef enum {
   GZIP_OK,
   GZIP_BAD,
   GZIP_UNDERFLOW
-} check_gzip_header(unsigned char const *data, ssize_t len, ssize_t *headerlen)
+} gzip_status;
+
+static gzip_status check_gzip_header(unsigned char const *data, ssize_t len,
+                                     ssize_t *headerlen)
 {
   int method, flags;
   const ssize_t totallen = len;
@@ -447,19 +450,22 @@ static enum {
 }
 #endif
 
-static CURLcode gzip_unencode_write(struct Curl_easy *data,
-                                    struct contenc_writer *writer,
+static CURLcode gzip_do_write(struct Curl_easy *data,
+                                    struct Curl_cwriter *writer, int type,
                                     const char *buf, size_t nbytes)
 {
   struct zlib_writer *zp = (struct zlib_writer *) writer;
   z_stream *z = &zp->z;     /* zlib state structure */
 
+  if(!(type & CLIENTWRITE_BODY) || !nbytes)
+    return Curl_cwriter_write(data, writer->next, type, buf, nbytes);
+
   if(zp->zlib_init == ZLIB_INIT_GZIP) {
     /* Let zlib handle the gzip decompression entirely */
     z->next_in = (Bytef *) buf;
     z->avail_in = (uInt) nbytes;
     /* Now uncompress the data */
-    return inflate_stream(data, writer, ZLIB_INIT_GZIP);
+    return inflate_stream(data, writer, type, ZLIB_INIT_GZIP);
   }
 
 #ifndef OLD_ZLIB_SUPPORT
@@ -571,12 +577,12 @@ static CURLcode gzip_unencode_write(struct Curl_easy *data,
   }
 
   /* We've parsed the header, now uncompress the data */
-  return inflate_stream(data, writer, ZLIB_GZIP_INFLATING);
+  return inflate_stream(data, writer, type, ZLIB_GZIP_INFLATING);
 #endif
 }
 
-static void gzip_close_writer(struct Curl_easy *data,
-                              struct contenc_writer *writer)
+static void gzip_do_close(struct Curl_easy *data,
+                              struct Curl_cwriter *writer)
 {
   struct zlib_writer *zp = (struct zlib_writer *) writer;
   z_stream *z = &zp->z;     /* zlib state structure */
@@ -584,12 +590,12 @@ static void gzip_close_writer(struct Curl_easy *data,
   exit_zlib(data, z, &zp->zlib_init, CURLE_OK);
 }
 
-static const struct content_encoding gzip_encoding = {
+static const struct Curl_cwtype gzip_encoding = {
   "gzip",
   "x-gzip",
-  gzip_init_writer,
-  gzip_unencode_write,
-  gzip_close_writer,
+  gzip_do_init,
+  gzip_do_write,
+  gzip_do_close,
   sizeof(struct zlib_writer)
 };
 
@@ -599,7 +605,7 @@ static const struct content_encoding gzip_encoding = {
 #ifdef HAVE_BROTLI
 /* Brotli writer. */
 struct brotli_writer {
-  struct contenc_writer super;
+  struct Curl_cwriter super;
   BrotliDecoderState *br;    /* State structure for brotli. */
 };
 
@@ -641,21 +647,18 @@ static CURLcode brotli_map_error(BrotliDecoderErrorCode be)
   return CURLE_WRITE_ERROR;
 }
 
-static CURLcode brotli_init_writer(struct Curl_easy *data,
-                                   struct contenc_writer *writer)
+static CURLcode brotli_do_init(struct Curl_easy *data,
+                                   struct Curl_cwriter *writer)
 {
   struct brotli_writer *bp = (struct brotli_writer *) writer;
   (void) data;
 
-  if(!writer->downstream)
-    return CURLE_WRITE_ERROR;
-
   bp->br = BrotliDecoderCreateInstance(NULL, NULL, NULL);
   return bp->br? CURLE_OK: CURLE_OUT_OF_MEMORY;
 }
 
-static CURLcode brotli_unencode_write(struct Curl_easy *data,
-                                      struct contenc_writer *writer,
+static CURLcode brotli_do_write(struct Curl_easy *data,
+                                      struct Curl_cwriter *writer, int type,
                                       const char *buf, size_t nbytes)
 {
   struct brotli_writer *bp = (struct brotli_writer *) writer;
@@ -666,6 +669,9 @@ static CURLcode brotli_unencode_write(struct Curl_easy *data,
   CURLcode result = CURLE_OK;
   BrotliDecoderResult r = BROTLI_DECODER_RESULT_NEEDS_MORE_OUTPUT;
 
+  if(!(type & CLIENTWRITE_BODY) || !nbytes)
+    return Curl_cwriter_write(data, writer->next, type, buf, nbytes);
+
   if(!bp->br)
     return CURLE_WRITE_ERROR;  /* Stream already ended. */
 
@@ -679,7 +685,7 @@ static CURLcode brotli_unencode_write(struct Curl_easy *data,
     dstleft = DSIZ;
     r = BrotliDecoderDecompressStream(bp->br,
                                       &nbytes, &src, &dstleft, &dst, NULL);
-    result = Curl_unencode_write(data, writer->downstream,
+    result = Curl_cwriter_write(data, writer->next, type,
                                  decomp, DSIZ - dstleft);
     if(result)
       break;
@@ -702,8 +708,8 @@ static CURLcode brotli_unencode_write(struct Curl_easy *data,
   return result;
 }
 
-static void brotli_close_writer(struct Curl_easy *data,
-                                struct contenc_writer *writer)
+static void brotli_do_close(struct Curl_easy *data,
+                                struct Curl_cwriter *writer)
 {
   struct brotli_writer *bp = (struct brotli_writer *) writer;
 
@@ -715,12 +721,12 @@ static void brotli_close_writer(struct Curl_easy *data,
   }
 }
 
-static const struct content_encoding brotli_encoding = {
+static const struct Curl_cwtype brotli_encoding = {
   "br",
   NULL,
-  brotli_init_writer,
-  brotli_unencode_write,
-  brotli_close_writer,
+  brotli_do_init,
+  brotli_do_write,
+  brotli_do_close,
   sizeof(struct brotli_writer)
 };
 #endif
@@ -729,28 +735,25 @@ static const struct content_encoding brotli_encoding = {
 #ifdef HAVE_ZSTD
 /* Zstd writer. */
 struct zstd_writer {
-  struct contenc_writer super;
+  struct Curl_cwriter super;
   ZSTD_DStream *zds;    /* State structure for zstd. */
   void *decomp;
 };
 
-static CURLcode zstd_init_writer(struct Curl_easy *data,
-                                 struct contenc_writer *writer)
+static CURLcode zstd_do_init(struct Curl_easy *data,
+                                 struct Curl_cwriter *writer)
 {
   struct zstd_writer *zp = (struct zstd_writer *) writer;
 
   (void)data;
 
-  if(!writer->downstream)
-    return CURLE_WRITE_ERROR;
-
   zp->zds = ZSTD_createDStream();
   zp->decomp = NULL;
   return zp->zds ? CURLE_OK : CURLE_OUT_OF_MEMORY;
 }
 
-static CURLcode zstd_unencode_write(struct Curl_easy *data,
-                                    struct contenc_writer *writer,
+static CURLcode zstd_do_write(struct Curl_easy *data,
+                                    struct Curl_cwriter *writer, int type,
                                     const char *buf, size_t nbytes)
 {
   CURLcode result = CURLE_OK;
@@ -759,6 +762,9 @@ static CURLcode zstd_unencode_write(struct Curl_easy *data,
   ZSTD_outBuffer out;
   size_t errorCode;
 
+  if(!(type & CLIENTWRITE_BODY) || !nbytes)
+    return Curl_cwriter_write(data, writer->next, type, buf, nbytes);
+
   if(!zp->decomp) {
     zp->decomp = malloc(DSIZ);
     if(!zp->decomp)
@@ -778,7 +784,7 @@ static CURLcode zstd_unencode_write(struct Curl_easy *data,
       return CURLE_BAD_CONTENT_ENCODING;
     }
     if(out.pos > 0) {
-      result = Curl_unencode_write(data, writer->downstream,
+      result = Curl_cwriter_write(data, writer->next, type,
                                    zp->decomp, out.pos);
       if(result)
         break;
@@ -790,8 +796,8 @@ static CURLcode zstd_unencode_write(struct Curl_easy *data,
   return result;
 }
 
-static void zstd_close_writer(struct Curl_easy *data,
-                              struct contenc_writer *writer)
+static void zstd_do_close(struct Curl_easy *data,
+                              struct Curl_cwriter *writer)
 {
   struct zstd_writer *zp = (struct zstd_writer *) writer;
 
@@ -807,51 +813,30 @@ static void zstd_close_writer(struct Curl_easy *data,
   }
 }
 
-static const struct content_encoding zstd_encoding = {
+static const struct Curl_cwtype zstd_encoding = {
   "zstd",
   NULL,
-  zstd_init_writer,
-  zstd_unencode_write,
-  zstd_close_writer,
+  zstd_do_init,
+  zstd_do_write,
+  zstd_do_close,
   sizeof(struct zstd_writer)
 };
 #endif
 
 
 /* Identity handler. */
-static CURLcode identity_init_writer(struct Curl_easy *data,
-                                     struct contenc_writer *writer)
-{
-  (void) data;
-  return writer->downstream? CURLE_OK: CURLE_WRITE_ERROR;
-}
-
-static CURLcode identity_unencode_write(struct Curl_easy *data,
-                                        struct contenc_writer *writer,
-                                        const char *buf, size_t nbytes)
-{
-  return Curl_unencode_write(data, writer->downstream, buf, nbytes);
-}
-
-static void identity_close_writer(struct Curl_easy *data,
-                                  struct contenc_writer *writer)
-{
-  (void) data;
-  (void) writer;
-}
-
-static const struct content_encoding identity_encoding = {
+static const struct Curl_cwtype identity_encoding = {
   "identity",
   "none",
-  identity_init_writer,
-  identity_unencode_write,
-  identity_close_writer,
-  sizeof(struct contenc_writer)
+  Curl_cwriter_def_init,
+  Curl_cwriter_def_write,
+  Curl_cwriter_def_close,
+  sizeof(struct Curl_cwriter)
 };
 
 
-/* supported content encodings table. */
-static const struct content_encoding * const encodings[] = {
+/* supported general content decoders. */
+static const struct Curl_cwtype * const general_unencoders[] = {
   &identity_encoding,
 #ifdef HAVE_LIBZ
   &deflate_encoding,
@@ -866,28 +851,39 @@ static const struct content_encoding * const encodings[] = {
   NULL
 };
 
+/* supported content decoders only for transfer encodings */
+static const struct Curl_cwtype * const transfer_unencoders[] = {
+#ifndef CURL_DISABLE_HTTP
+  &Curl_httpchunk_unencoder,
+#endif
+  NULL
+};
 
-/* Return a list of comma-separated names of supported encodings. */
-char *Curl_all_content_encodings(void)
+/* Provide a list of comma-separated names of supported encodings.
+*/
+void Curl_all_content_encodings(char *buf, size_t blen)
 {
   size_t len = 0;
-  const struct content_encoding * const *cep;
-  const struct content_encoding *ce;
-  char *ace;
+  const struct Curl_cwtype * const *cep;
+  const struct Curl_cwtype *ce;
 
-  for(cep = encodings; *cep; cep++) {
+  DEBUGASSERT(buf);
+  DEBUGASSERT(blen);
+  buf[0] = 0;
+
+  for(cep = general_unencoders; *cep; cep++) {
     ce = *cep;
     if(!strcasecompare(ce->name, CONTENT_ENCODING_DEFAULT))
       len += strlen(ce->name) + 2;
   }
 
-  if(!len)
-    return strdup(CONTENT_ENCODING_DEFAULT);
-
-  ace = malloc(len);
-  if(ace) {
-    char *p = ace;
-    for(cep = encodings; *cep; cep++) {
+  if(!len) {
+    if(blen >= sizeof(CONTENT_ENCODING_DEFAULT))
+      strcpy(buf, CONTENT_ENCODING_DEFAULT);
+  }
+  else if(blen > len) {
+    char *p = buf;
+    for(cep = general_unencoders; *cep; cep++) {
       ce = *cep;
       if(!strcasecompare(ce->name, CONTENT_ENCODING_DEFAULT)) {
         strcpy(p, ce->name);
@@ -898,150 +894,71 @@ char *Curl_all_content_encodings(void)
     }
     p[-2] = '\0';
   }
-
-  return ace;
-}
-
-
-/* Real client writer: no downstream. */
-static CURLcode client_init_writer(struct Curl_easy *data,
-                                   struct contenc_writer *writer)
-{
-  (void) data;
-  return writer->downstream? CURLE_WRITE_ERROR: CURLE_OK;
 }
 
-static CURLcode client_unencode_write(struct Curl_easy *data,
-                                      struct contenc_writer *writer,
-                                      const char *buf, size_t nbytes)
-{
-  struct SingleRequest *k = &data->req;
-
-  (void) writer;
-
-  if(!nbytes || k->ignorebody)
-    return CURLE_OK;
-
-  return Curl_client_write(data, CLIENTWRITE_BODY, (char *) buf, nbytes);
-}
-
-static void client_close_writer(struct Curl_easy *data,
-                                struct contenc_writer *writer)
-{
-  (void) data;
-  (void) writer;
-}
-
-static const struct content_encoding client_encoding = {
-  NULL,
-  NULL,
-  client_init_writer,
-  client_unencode_write,
-  client_close_writer,
-  sizeof(struct contenc_writer)
-};
-
-
 /* Deferred error dummy writer. */
-static CURLcode error_init_writer(struct Curl_easy *data,
-                                  struct contenc_writer *writer)
+static CURLcode error_do_init(struct Curl_easy *data,
+                                  struct Curl_cwriter *writer)
 {
-  (void) data;
-  return writer->downstream? CURLE_OK: CURLE_WRITE_ERROR;
+  (void)data;
+  (void)writer;
+  return CURLE_OK;
 }
 
-static CURLcode error_unencode_write(struct Curl_easy *data,
-                                     struct contenc_writer *writer,
+static CURLcode error_do_write(struct Curl_easy *data,
+                                     struct Curl_cwriter *writer, int type,
                                      const char *buf, size_t nbytes)
 {
-  char *all = Curl_all_content_encodings();
+  char all[256];
+  (void)Curl_all_content_encodings(all, sizeof(all));
 
   (void) writer;
   (void) buf;
   (void) nbytes;
 
-  if(!all)
-    return CURLE_OUT_OF_MEMORY;
+  if(!(type & CLIENTWRITE_BODY) || !nbytes)
+    return Curl_cwriter_write(data, writer->next, type, buf, nbytes);
+
   failf(data, "Unrecognized content encoding type. "
         "libcurl understands %s content encodings.", all);
-  free(all);
   return CURLE_BAD_CONTENT_ENCODING;
 }
 
-static void error_close_writer(struct Curl_easy *data,
-                               struct contenc_writer *writer)
+static void error_do_close(struct Curl_easy *data,
+                               struct Curl_cwriter *writer)
 {
   (void) data;
   (void) writer;
 }
 
-static const struct content_encoding error_encoding = {
-  NULL,
+static const struct Curl_cwtype error_writer = {
+  "ce-error",
   NULL,
-  error_init_writer,
-  error_unencode_write,
-  error_close_writer,
-  sizeof(struct contenc_writer)
+  error_do_init,
+  error_do_write,
+  error_do_close,
+  sizeof(struct Curl_cwriter)
 };
 
-/* Create an unencoding writer stage using the given handler. */
-static struct contenc_writer *
-new_unencoding_writer(struct Curl_easy *data,
-                      const struct content_encoding *handler,
-                      struct contenc_writer *downstream,
-                      int order)
+/* Find the content encoding by name. */
+static const struct Curl_cwtype *find_unencode_writer(const char *name,
+                                                      size_t len,
+                                                      Curl_cwriter_phase phase)
 {
-  struct contenc_writer *writer;
-
-  DEBUGASSERT(handler->writersize >= sizeof(struct contenc_writer));
-  writer = (struct contenc_writer *) calloc(1, handler->writersize);
-
-  if(writer) {
-    writer->handler = handler;
-    writer->downstream = downstream;
-    writer->order = order;
-    if(handler->init_writer(data, writer)) {
-      free(writer);
-      writer = NULL;
+  const struct Curl_cwtype * const *cep;
+
+  if(phase == CURL_CW_TRANSFER_DECODE) {
+    for(cep = transfer_unencoders; *cep; cep++) {
+      const struct Curl_cwtype *ce = *cep;
+      if((strncasecompare(name, ce->name, len) && !ce->name[len]) ||
+         (ce->alias && strncasecompare(name, ce->alias, len)
+                    && !ce->alias[len]))
+        return ce;
     }
   }
-
-  return writer;
-}
-
-/* Write data using an unencoding writer stack. "nbytes" is not
-   allowed to be 0. */
-CURLcode Curl_unencode_write(struct Curl_easy *data,
-                             struct contenc_writer *writer,
-                             const char *buf, size_t nbytes)
-{
-  if(!nbytes)
-    return CURLE_OK;
-  return writer->handler->unencode_write(data, writer, buf, nbytes);
-}
-
-/* Close and clean-up the connection's writer stack. */
-void Curl_unencode_cleanup(struct Curl_easy *data)
-{
-  struct SingleRequest *k = &data->req;
-  struct contenc_writer *writer = k->writer_stack;
-
-  while(writer) {
-    k->writer_stack = writer->downstream;
-    writer->handler->close_writer(data, writer);
-    free(writer);
-    writer = k->writer_stack;
-  }
-}
-
-/* Find the content encoding by name. */
-static const struct content_encoding *find_encoding(const char *name,
-                                                    size_t len)
-{
-  const struct content_encoding * const *cep;
-
-  for(cep = encodings; *cep; cep++) {
-    const struct content_encoding *ce = *cep;
+  /* look among the general decoders */
+  for(cep = general_unencoders; *cep; cep++) {
+    const struct Curl_cwtype *ce = *cep;
     if((strncasecompare(name, ce->name, len) && !ce->name[len]) ||
        (ce->alias && strncasecompare(name, ce->alias, len) && !ce->alias[len]))
       return ce;
@@ -1049,20 +966,19 @@ static const struct content_encoding *find_encoding(const char *name,
   return NULL;
 }
 
-/* allow no more than 5 "chained" compression steps */
-#define MAX_ENCODE_STACK 5
-
 /* Set-up the unencoding stack from the Content-Encoding header value.
  * See RFC 7231 section 3.1.2.2. */
 CURLcode Curl_build_unencoding_stack(struct Curl_easy *data,
                                      const char *enclist, int is_transfer)
 {
-  struct SingleRequest *k = &data->req;
-  unsigned int order = is_transfer? 2: 1;
+  Curl_cwriter_phase phase = is_transfer?
+                             CURL_CW_TRANSFER_DECODE:CURL_CW_CONTENT_DECODE;
+  CURLcode result;
 
   do {
     const char *name;
     size_t namelen;
+    bool is_chunked = FALSE;
 
     /* Parse a single encoding name. */
     while(ISBLANK(*enclist) || *enclist == ',')
@@ -1074,52 +990,63 @@ CURLcode Curl_build_unencoding_stack(struct Curl_easy *data,
       if(!ISSPACE(*enclist))
         namelen = enclist - name + 1;
 
-    /* Special case: chunked encoding is handled at the reader level. */
-    if(is_transfer && namelen == 7 && strncasecompare(name, "chunked", 7)) {
-      k->chunk = TRUE;             /* chunks coming our way. */
-      Curl_httpchunk_init(data);   /* init our chunky engine. */
-    }
-    else if(namelen) {
-      const struct content_encoding *encoding;
-      struct contenc_writer *writer;
-      if(is_transfer && !data->set.http_transfer_encoding)
+    if(namelen) {
+      const struct Curl_cwtype *cwt;
+      struct Curl_cwriter *writer;
+
+      is_chunked = (is_transfer && (namelen == 7) &&
+                    strncasecompare(name, "chunked", 7));
+      /* if we skip the decoding in this phase, do not look further.
+       * Exception is "chunked" transfer-encoding which always must happen */
+      if((is_transfer && !data->set.http_transfer_encoding && !is_chunked) ||
+         (!is_transfer && data->set.http_ce_skip)) {
         /* not requested, ignore */
         return CURLE_OK;
-      encoding = find_encoding(name, namelen);
-
-      if(!k->writer_stack) {
-        k->writer_stack = new_unencoding_writer(data, &client_encoding,
-                                                NULL, 0);
-
-        if(!k->writer_stack)
-          return CURLE_OUT_OF_MEMORY;
       }
 
-      if(!encoding)
-        encoding = &error_encoding;  /* Defer error at stack use. */
-
-      if(k->writer_stack_depth++ >= MAX_ENCODE_STACK) {
+      if(Curl_cwriter_count(data, phase) + 1 >= MAX_ENCODE_STACK) {
         failf(data, "Reject response due to more than %u content encodings",
               MAX_ENCODE_STACK);
         return CURLE_BAD_CONTENT_ENCODING;
       }
-      /* Stack the unencoding stage. */
-      if(order >= k->writer_stack->order) {
-        writer = new_unencoding_writer(data, encoding,
-                                       k->writer_stack, order);
-        if(!writer)
-          return CURLE_OUT_OF_MEMORY;
-        k->writer_stack = writer;
+
+      cwt = find_unencode_writer(name, namelen, phase);
+      if(cwt && is_chunked && Curl_cwriter_get_by_type(data, cwt)) {
+        /* A 'chunked' transfer encoding has already been added.
+         * Ignore duplicates. See #13451.
+         * Also RFC 9112, ch. 6.1:
+         * "A sender MUST NOT apply the chunked transfer coding more than
+         *  once to a message body."
+         */
+        return CURLE_OK;
       }
-      else {
-        struct contenc_writer *w = k->writer_stack;
-        while(w->downstream && order < w->downstream->order)
-          w = w->downstream;
-        writer = new_unencoding_writer(data, encoding,
-                                       w->downstream, order);
-        if(!writer)
-          return CURLE_OUT_OF_MEMORY;
-        w->downstream = writer;
+
+      if(is_transfer && !is_chunked &&
+         Curl_cwriter_get_by_name(data, "chunked")) {
+        /* RFC 9112, ch. 6.1:
+         * "If any transfer coding other than chunked is applied to a
+         *  response's content, the sender MUST either apply chunked as the
+         *  final transfer coding or terminate the message by closing the
+         *  connection."
+         * "chunked" must be the last added to be the first in its phase,
+         *  reject this.
+         */
+        failf(data, "Reject response due to 'chunked' not being the last "
+              "Transfer-Encoding");
+        return CURLE_BAD_CONTENT_ENCODING;
+      }
+
+      if(!cwt)
+        cwt = &error_writer;  /* Defer error at use. */
+
+      result = Curl_cwriter_create(&writer, data, cwt, phase);
+      if(result)
+        return result;
+
+      result = Curl_cwriter_add(data, writer);
+      if(result) {
+        Curl_cwriter_free(data, writer);
+        return result;
       }
     }
   } while(*enclist);
@@ -1138,25 +1065,15 @@ CURLcode Curl_build_unencoding_stack(struct Curl_easy *data,
   return CURLE_NOT_BUILT_IN;
 }
 
-CURLcode Curl_unencode_write(struct Curl_easy *data,
-                             struct contenc_writer *writer,
-                             const char *buf, size_t nbytes)
+void Curl_all_content_encodings(char *buf, size_t blen)
 {
-  (void) data;
-  (void) writer;
-  (void) buf;
-  (void) nbytes;
-  return CURLE_NOT_BUILT_IN;
-}
-
-void Curl_unencode_cleanup(struct Curl_easy *data)
-{
-  (void) data;
+  DEBUGASSERT(buf);
+  DEBUGASSERT(blen);
+  if(blen < sizeof(CONTENT_ENCODING_DEFAULT))
+    buf[0] = 0;
+  else
+    strcpy(buf, CONTENT_ENCODING_DEFAULT);
 }
 
-char *Curl_all_content_encodings(void)
-{
-  return strdup(CONTENT_ENCODING_DEFAULT);  /* Satisfy caller. */
-}
 
 #endif /* CURL_DISABLE_HTTP */
diff --git a/vendor/curl/lib/content_encoding.h b/vendor/curl/lib/content_encoding.h
index 56e7f97f70..1addf230bb 100644
--- a/vendor/curl/lib/content_encoding.h
+++ b/vendor/curl/lib/content_encoding.h
@@ -25,33 +25,10 @@
  ***************************************************************************/
 #include "curl_setup.h"
 
-struct contenc_writer {
-  const struct content_encoding *handler;  /* Encoding handler. */
-  struct contenc_writer *downstream;  /* Downstream writer. */
-  unsigned int order; /* Ordering within writer stack. */
-};
-
-/* Content encoding writer. */
-struct content_encoding {
-  const char *name;        /* Encoding name. */
-  const char *alias;       /* Encoding name alias. */
-  CURLcode (*init_writer)(struct Curl_easy *data,
-                          struct contenc_writer *writer);
-  CURLcode (*unencode_write)(struct Curl_easy *data,
-                             struct contenc_writer *writer,
-                             const char *buf, size_t nbytes);
-  void (*close_writer)(struct Curl_easy *data,
-                       struct contenc_writer *writer);
-  size_t writersize;
-};
+struct Curl_cwriter;
 
+void Curl_all_content_encodings(char *buf, size_t blen);
 
 CURLcode Curl_build_unencoding_stack(struct Curl_easy *data,
                                      const char *enclist, int is_transfer);
-CURLcode Curl_unencode_write(struct Curl_easy *data,
-                             struct contenc_writer *writer,
-                             const char *buf, size_t nbytes);
-void Curl_unencode_cleanup(struct Curl_easy *data);
-char *Curl_all_content_encodings(void);
-
 #endif /* HEADER_CURL_CONTENT_ENCODING_H */
diff --git a/vendor/curl/lib/cookie.c b/vendor/curl/lib/cookie.c
index 4345a84c6f..837caaab38 100644
--- a/vendor/curl/lib/cookie.c
+++ b/vendor/curl/lib/cookie.c
@@ -112,14 +112,11 @@ static void strstore(char **str, const char *newstr, size_t len);
 
 static void freecookie(struct Cookie *co)
 {
-  free(co->expirestr);
   free(co->domain);
   free(co->path);
   free(co->spath);
   free(co->name);
   free(co->value);
-  free(co->maxage);
-  free(co->version);
   free(co);
 }
 
@@ -333,7 +330,7 @@ static char *sanitize_cookie_path(const char *cookie_path)
  */
 void Curl_cookie_loadfiles(struct Curl_easy *data)
 {
-  struct curl_slist *list = data->set.cookielist;
+  struct curl_slist *list = data->state.cookielist;
   if(list) {
     Curl_share_lock(data, CURL_LOCK_DATA_COOKIE, CURL_LOCK_ACCESS_SINGLE);
     while(list) {
@@ -368,9 +365,7 @@ static void strstore(char **str, const char *newstr, size_t len)
   DEBUGASSERT(newstr);
   DEBUGASSERT(str);
   free(*str);
-  *str = Curl_memdup(newstr, len + 1);
-  if(*str)
-    (*str)[len] = 0;
+  *str = Curl_memdup0(newstr, len);
 }
 
 /*
@@ -431,6 +426,7 @@ static void remove_expired(struct CookieInfo *cookies)
   }
 }
 
+#ifndef USE_LIBPSL
 /* Make sure domain contains a dot or is localhost. */
 static bool bad_domain(const char *domain, size_t len)
 {
@@ -448,6 +444,7 @@ static bool bad_domain(const char *domain, size_t len)
   }
   return TRUE;
 }
+#endif
 
 /*
   RFC 6265 section 4.1.1 says a server should accept this range:
@@ -487,7 +484,7 @@ Curl_cookie_add(struct Curl_easy *data,
                 struct CookieInfo *c,
                 bool httpheader, /* TRUE if HTTP header-style line */
                 bool noexpire, /* if TRUE, skip remove_expired() */
-                char *lineptr,   /* first character of the line */
+                const char *lineptr,   /* first character of the line */
                 const char *domain, /* default domain */
                 const char *path,   /* full path used when this cookie is set,
                                        used to get default path for the cookie
@@ -718,11 +715,7 @@ Curl_cookie_add(struct Curl_easy *data,
           }
         }
         else if((nlen == 7) && strncasecompare("version", namep, 7)) {
-          strstore(&co->version, valuep, vlen);
-          if(!co->version) {
-            badcookie = TRUE;
-            break;
-          }
+          /* just ignore */
         }
         else if((nlen == 7) && strncasecompare("max-age", namep, 7)) {
           /*
@@ -734,17 +727,55 @@ Curl_cookie_add(struct Curl_easy *data,
            * client should discard the cookie.  A value of zero means the
            * cookie should be discarded immediately.
            */
-          strstore(&co->maxage, valuep, vlen);
-          if(!co->maxage) {
-            badcookie = TRUE;
+          CURLofft offt;
+          const char *maxage = valuep;
+          offt = curlx_strtoofft((*maxage == '\"')?
+                                 &maxage[1]:&maxage[0], NULL, 10,
+                                 &co->expires);
+          switch(offt) {
+          case CURL_OFFT_FLOW:
+            /* overflow, used max value */
+            co->expires = CURL_OFF_T_MAX;
+            break;
+          case CURL_OFFT_INVAL:
+            /* negative or otherwise bad, expire */
+            co->expires = 1;
+            break;
+          case CURL_OFFT_OK:
+            if(!co->expires)
+              /* already expired */
+              co->expires = 1;
+            else if(CURL_OFF_T_MAX - now < co->expires)
+              /* would overflow */
+              co->expires = CURL_OFF_T_MAX;
+            else
+              co->expires += now;
             break;
           }
         }
         else if((nlen == 7) && strncasecompare("expires", namep, 7)) {
-          strstore(&co->expirestr, valuep, vlen);
-          if(!co->expirestr) {
-            badcookie = TRUE;
-            break;
+          char date[128];
+          if(!co->expires && (vlen < sizeof(date))) {
+            /* copy the date so that it can be null terminated */
+            memcpy(date, valuep, vlen);
+            date[vlen] = 0;
+            /*
+             * Let max-age have priority.
+             *
+             * If the date cannot get parsed for whatever reason, the cookie
+             * will be treated as a session cookie
+             */
+            co->expires = Curl_getdate_capped(date);
+
+            /*
+             * Session cookies have expires set to 0 so if we get that back
+             * from the date parser let's add a second to make it a
+             * non-session cookie
+             */
+            if(co->expires == 0)
+              co->expires = 1;
+            else if(co->expires < 0)
+              co->expires = 0;
           }
         }
 
@@ -764,49 +795,6 @@ Curl_cookie_add(struct Curl_easy *data,
         break;
     } while(1);
 
-    if(co->maxage) {
-      CURLofft offt;
-      offt = curlx_strtoofft((*co->maxage == '\"')?
-                             &co->maxage[1]:&co->maxage[0], NULL, 10,
-                             &co->expires);
-      switch(offt) {
-      case CURL_OFFT_FLOW:
-        /* overflow, used max value */
-        co->expires = CURL_OFF_T_MAX;
-        break;
-      case CURL_OFFT_INVAL:
-        /* negative or otherwise bad, expire */
-        co->expires = 1;
-        break;
-      case CURL_OFFT_OK:
-        if(!co->expires)
-          /* already expired */
-          co->expires = 1;
-        else if(CURL_OFF_T_MAX - now < co->expires)
-          /* would overflow */
-          co->expires = CURL_OFF_T_MAX;
-        else
-          co->expires += now;
-        break;
-      }
-    }
-    else if(co->expirestr) {
-      /*
-       * Note that if the date couldn't get parsed for whatever reason, the
-       * cookie will be treated as a session cookie
-       */
-      co->expires = Curl_getdate_capped(co->expirestr);
-
-      /*
-       * Session cookies have expires set to 0 so if we get that back from the
-       * date parser let's add a second to make it a non-session cookie
-       */
-      if(co->expires == 0)
-        co->expires = 1;
-      else if(co->expires < 0)
-        co->expires = 0;
-    }
-
     if(!badcookie && !co->domain) {
       if(domain) {
         /* no domain was given in the header line, set the default */
@@ -835,10 +823,8 @@ Curl_cookie_add(struct Curl_easy *data,
         endslash = memrchr(path, '/', (queryp - path));
       if(endslash) {
         size_t pathlen = (endslash-path + 1); /* include end slash */
-        co->path = malloc(pathlen + 1); /* one extra for the zero byte */
+        co->path = Curl_memdup0(path, pathlen);
         if(co->path) {
-          memcpy(co->path, path, pathlen);
-          co->path[pathlen] = 0; /* null-terminate */
           co->spath = sanitize_cookie_path(co->path);
           if(!co->spath)
             badcookie = TRUE; /* out of memory bad */
@@ -894,13 +880,14 @@ Curl_cookie_add(struct Curl_easy *data,
     if(ptr)
       *ptr = 0; /* clear it */
 
-    firstptr = strtok_r(lineptr, "\t", &tok_buf); /* tokenize it on the TAB */
+    firstptr = strtok_r((char *)lineptr, "\t", &tok_buf); /* tokenize on TAB */
 
     /*
      * Now loop through the fields and init the struct we already have
      * allocated
      */
-    for(ptr = firstptr, fields = 0; ptr && !badcookie;
+    fields = 0;
+    for(ptr = firstptr; ptr && !badcookie;
         ptr = strtok_r(NULL, "\t", &tok_buf), fields++) {
       switch(fields) {
       case 0:
@@ -941,7 +928,7 @@ Curl_cookie_add(struct Curl_easy *data,
         if(!co->spath)
           badcookie = TRUE;
         fields++; /* add a field and fall down to secure */
-        /* FALLTHROUGH */
+        FALLTHROUGH();
       case 3:
         co->secure = FALSE;
         if(strcasecompare(ptr, "TRUE")) {
@@ -1041,15 +1028,23 @@ Curl_cookie_add(struct Curl_easy *data,
    * dereference it.
    */
   if(data && (domain && co->domain && !Curl_host_is_ipnum(co->domain))) {
-    const psl_ctx_t *psl = Curl_psl_use(data);
-    int acceptable;
-
-    if(psl) {
-      acceptable = psl_is_cookie_domain_acceptable(psl, domain, co->domain);
-      Curl_psl_release(data);
+    bool acceptable = FALSE;
+    char lcase[256];
+    char lcookie[256];
+    size_t dlen = strlen(domain);
+    size_t clen = strlen(co->domain);
+    if((dlen < sizeof(lcase)) && (clen < sizeof(lcookie))) {
+      const psl_ctx_t *psl = Curl_psl_use(data);
+      if(psl) {
+        /* the PSL check requires lowercase domain name and pattern */
+        Curl_strntolower(lcase, domain, dlen + 1);
+        Curl_strntolower(lcookie, co->domain, clen + 1);
+        acceptable = psl_is_cookie_domain_acceptable(psl, lcase, lcookie);
+        Curl_psl_release(data);
+      }
+      else
+        infof(data, "libpsl problem, rejecting cookie for satety");
     }
-    else
-      acceptable = !bad_domain(domain, strlen(domain));
 
     if(!acceptable) {
       infof(data, "cookie '%s' dropped, domain '%s' must not "
@@ -1159,9 +1154,6 @@ Curl_cookie_add(struct Curl_easy *data,
     free(clist->domain);
     free(clist->path);
     free(clist->spath);
-    free(clist->expirestr);
-    free(clist->version);
-    free(clist->maxage);
 
     *clist = *co;  /* then store all the new data */
 
@@ -1216,7 +1208,6 @@ struct CookieInfo *Curl_cookie_init(struct Curl_easy *data,
                                     bool newsession)
 {
   struct CookieInfo *c;
-  char *line = NULL;
   FILE *handle = NULL;
 
   if(!inc) {
@@ -1224,9 +1215,6 @@ struct CookieInfo *Curl_cookie_init(struct Curl_easy *data,
     c = calloc(1, sizeof(struct CookieInfo));
     if(!c)
       return NULL; /* failed to get memory */
-    c->filename = strdup(file?file:"none"); /* copy the name just in case */
-    if(!c->filename)
-      goto fail; /* failed to get memory */
     /*
      * Initialize the next_expiration time to signal that we don't have enough
      * information yet.
@@ -1241,7 +1229,7 @@ struct CookieInfo *Curl_cookie_init(struct Curl_easy *data,
 
   if(data) {
     FILE *fp = NULL;
-    if(file) {
+    if(file && *file) {
       if(!strcmp(file, "-"))
         fp = stdin;
       else {
@@ -1255,28 +1243,22 @@ struct CookieInfo *Curl_cookie_init(struct Curl_easy *data,
 
     c->running = FALSE; /* this is not running, this is init */
     if(fp) {
-      char *lineptr;
-      bool headerline;
-
-      line = malloc(MAX_COOKIE_LINE);
-      if(!line)
-        goto fail;
-      while(Curl_get_line(line, MAX_COOKIE_LINE, fp)) {
-        if(checkprefix("Set-Cookie:", line)) {
+      struct dynbuf buf;
+      Curl_dyn_init(&buf, MAX_COOKIE_LINE);
+      while(Curl_get_line(&buf, fp)) {
+        char *lineptr = Curl_dyn_ptr(&buf);
+        bool headerline = FALSE;
+        if(checkprefix("Set-Cookie:", lineptr)) {
           /* This is a cookie line, get it! */
-          lineptr = &line[11];
+          lineptr += 11;
           headerline = TRUE;
+          while(*lineptr && ISBLANK(*lineptr))
+            lineptr++;
         }
-        else {
-          lineptr = line;
-          headerline = FALSE;
-        }
-        while(*lineptr && ISBLANK(*lineptr))
-          lineptr++;
 
         Curl_cookie_add(data, c, headerline, TRUE, lineptr, NULL, NULL, TRUE);
       }
-      free(line); /* free the line buffer */
+      Curl_dyn_free(&buf); /* free the line buffer */
 
       /*
        * Remove expired cookies from the hash. We must make sure to run this
@@ -1288,22 +1270,10 @@ struct CookieInfo *Curl_cookie_init(struct Curl_easy *data,
         fclose(handle);
     }
     data->state.cookie_engine = TRUE;
-    c->running = TRUE;          /* now, we're running */
   }
+  c->running = TRUE;          /* now, we're running */
 
   return c;
-
-fail:
-  free(line);
-  /*
-   * Only clean up if we allocated it here, as the original could still be in
-   * use by a share handle.
-   */
-  if(!inc)
-    Curl_cookie_cleanup(c);
-  if(handle)
-    fclose(handle);
-  return NULL; /* out of memory */
 }
 
 /*
@@ -1369,16 +1339,13 @@ static int cookie_sort_ct(const void *p1, const void *p2)
 
 static struct Cookie *dup_cookie(struct Cookie *src)
 {
-  struct Cookie *d = calloc(sizeof(struct Cookie), 1);
+  struct Cookie *d = calloc(1, sizeof(struct Cookie));
   if(d) {
-    CLONE(expirestr);
     CLONE(domain);
     CLONE(path);
     CLONE(spath);
     CLONE(name);
     CLONE(value);
-    CLONE(maxage);
-    CLONE(version);
     d->expires = src->expires;
     d->tailmatch = src->tailmatch;
     d->secure = src->secure;
@@ -1595,7 +1562,6 @@ void Curl_cookie_cleanup(struct CookieInfo *c)
 {
   if(c) {
     unsigned int i;
-    free(c->filename);
     for(i = 0; i < COOKIE_HASH_SIZE; i++)
       Curl_cookie_freelist(c->cookies[i]);
     free(c); /* free the base struct as well */
diff --git a/vendor/curl/lib/cookie.h b/vendor/curl/lib/cookie.h
index b3c0063b2c..012dd892c9 100644
--- a/vendor/curl/lib/cookie.h
+++ b/vendor/curl/lib/cookie.h
@@ -35,12 +35,6 @@ struct Cookie {
   char *spath;        /* sanitized cookie path */
   char *domain;      /* domain =  */
   curl_off_t expires;  /* expires =  */
-  char *expirestr;   /* the plain text version */
-
-  /* RFC 2109 keywords. Version=1 means 2109-compliant cookie sending */
-  char *version;     /* Version =  */
-  char *maxage;      /* Max-Age =  */
-
   bool tailmatch;    /* whether we do tail-matching of the domain name */
   bool secure;       /* whether the 'secure' keyword was used */
   bool livecookie;   /* updated from a server, not a stored file */
@@ -56,17 +50,16 @@ struct Cookie {
 #define COOKIE_PREFIX__SECURE (1<<0)
 #define COOKIE_PREFIX__HOST (1<<1)
 
-#define COOKIE_HASH_SIZE 256
+#define COOKIE_HASH_SIZE 63
 
 struct CookieInfo {
   /* linked list of cookies we know of */
   struct Cookie *cookies[COOKIE_HASH_SIZE];
-  char *filename;  /* file we read from/write to */
-  long numcookies; /* number of cookies in the "jar" */
+  curl_off_t next_expiration; /* the next time at which expiration happens */
+  int numcookies;  /* number of cookies in the "jar" */
+  int lastct;      /* last creation-time used in the jar */
   bool running;    /* state info, for cookie adding information */
   bool newsession; /* new session, discard session cookies on load */
-  int lastct;      /* last creation-time used in the jar */
-  curl_off_t next_expiration; /* the next time at which expiration happens */
 };
 
 /* The maximum sizes we accept for cookies. RFC 6265 section 6.1 says
@@ -75,7 +68,6 @@ struct CookieInfo {
 
    - At least 4096 bytes per cookie (as measured by the sum of the length of
      the cookie's name, value, and attributes).
-
    In the 6265bis draft document section 5.4 it is phrased even stronger: "If
    the sum of the lengths of the name string and the value string is more than
    4096 octets, abort these steps and ignore the set-cookie-string entirely."
@@ -116,7 +108,7 @@ struct Curl_easy;
 
 struct Cookie *Curl_cookie_add(struct Curl_easy *data,
                                struct CookieInfo *c, bool header,
-                               bool noexpiry, char *lineptr,
+                               bool noexpiry, const char *lineptr,
                                const char *domain, const char *path,
                                bool secure);
 
diff --git a/vendor/curl/lib/curl_addrinfo.c b/vendor/curl/lib/curl_addrinfo.c
index f9211d3f57..c32f24d018 100644
--- a/vendor/curl/lib/curl_addrinfo.c
+++ b/vendor/curl/lib/curl_addrinfo.c
@@ -130,7 +130,7 @@ Curl_getaddrinfo_ex(const char *nodename,
     /* settle family-specific sockaddr structure size.  */
     if(ai->ai_family == AF_INET)
       ss_size = sizeof(struct sockaddr_in);
-#ifdef ENABLE_IPV6
+#ifdef USE_IPV6
     else if(ai->ai_family == AF_INET6)
       ss_size = sizeof(struct sockaddr_in6);
 #endif
@@ -259,7 +259,7 @@ Curl_he2ai(const struct hostent *he, int port)
   struct Curl_addrinfo *prevai = NULL;
   struct Curl_addrinfo *firstai = NULL;
   struct sockaddr_in *addr;
-#ifdef ENABLE_IPV6
+#ifdef USE_IPV6
   struct sockaddr_in6 *addr6;
 #endif
   CURLcode result = CURLE_OK;
@@ -275,7 +275,7 @@ Curl_he2ai(const struct hostent *he, int port)
   for(i = 0; (curr = he->h_addr_list[i]) != NULL; i++) {
     size_t ss_size;
     size_t namelen = strlen(he->h_name) + 1; /* include null-terminator */
-#ifdef ENABLE_IPV6
+#ifdef USE_IPV6
     if(he->h_addrtype == AF_INET6)
       ss_size = sizeof(struct sockaddr_in6);
     else
@@ -321,7 +321,7 @@ Curl_he2ai(const struct hostent *he, int port)
       addr->sin_port = htons((unsigned short)port);
       break;
 
-#ifdef ENABLE_IPV6
+#ifdef USE_IPV6
     case AF_INET6:
       addr6 = (void *)ai->ai_addr; /* storage area for this info */
 
@@ -348,7 +348,7 @@ struct namebuff {
   struct hostent hostentry;
   union {
     struct in_addr  ina4;
-#ifdef ENABLE_IPV6
+#ifdef USE_IPV6
     struct in6_addr ina6;
 #endif
   } addrentry;
@@ -401,7 +401,7 @@ Curl_ip2addr(int af, const void *inaddr, const char *hostname, int port)
     addrentry = (void *)&buf->addrentry.ina4;
     memcpy(addrentry, inaddr, sizeof(struct in_addr));
     break;
-#ifdef ENABLE_IPV6
+#ifdef USE_IPV6
   case AF_INET6:
     addrsize = sizeof(struct in6_addr);
     addrentry = (void *)&buf->addrentry.ina6;
@@ -447,7 +447,7 @@ struct Curl_addrinfo *Curl_str2addr(char *address, int port)
   if(Curl_inet_pton(AF_INET, address, &in) > 0)
     /* This is a dotted IP address 123.123.123.123-style */
     return Curl_ip2addr(AF_INET, &in, address, port);
-#ifdef ENABLE_IPV6
+#ifdef USE_IPV6
   {
     struct in6_addr in6;
     if(Curl_inet_pton(AF_INET6, address, &in6) > 0)
@@ -570,7 +570,7 @@ void Curl_addrinfo_set_port(struct Curl_addrinfo *addrinfo, int port)
 {
   struct Curl_addrinfo *ca;
   struct sockaddr_in *addr;
-#ifdef ENABLE_IPV6
+#ifdef USE_IPV6
   struct sockaddr_in6 *addr6;
 #endif
   for(ca = addrinfo; ca != NULL; ca = ca->ai_next) {
@@ -580,7 +580,7 @@ void Curl_addrinfo_set_port(struct Curl_addrinfo *addrinfo, int port)
       addr->sin_port = htons((unsigned short)port);
       break;
 
-#ifdef ENABLE_IPV6
+#ifdef USE_IPV6
     case AF_INET6:
       addr6 = (void *)ca->ai_addr; /* storage area for this info */
       addr6->sin6_port = htons((unsigned short)port);
diff --git a/vendor/curl/lib/curl_ctype.h b/vendor/curl/lib/curl_ctype.h
index 1d1d60c28d..7f0d0cc291 100644
--- a/vendor/curl/lib/curl_ctype.h
+++ b/vendor/curl/lib/curl_ctype.h
@@ -43,5 +43,9 @@
 #define ISDIGIT(x)  (((x) >= '0') && ((x) <= '9'))
 #define ISBLANK(x)  (((x) == ' ') || ((x) == '\t'))
 #define ISSPACE(x)  (ISBLANK(x) || (((x) >= 0xa) && ((x) <= 0x0d)))
+#define ISURLPUNTCS(x) (((x) == '-') || ((x) == '.') || ((x) == '_') || \
+                        ((x) == '~'))
+#define ISUNRESERVED(x) (ISALNUM(x) || ISURLPUNTCS(x))
+
 
 #endif /* HEADER_CURL_CTYPE_H */
diff --git a/vendor/curl/lib/curl_des.c b/vendor/curl/lib/curl_des.c
index b77763f268..f8d2b2cc69 100644
--- a/vendor/curl/lib/curl_des.c
+++ b/vendor/curl/lib/curl_des.c
@@ -36,7 +36,7 @@
  * Curl_des_set_odd_parity()
  *
  * This is used to apply odd parity to the given byte array. It is typically
- * used by when a cryptography engines doesn't have it's own version.
+ * used by when a cryptography engine doesn't have its own version.
  *
  * The function is a port of the Java based oddParity() function over at:
  *
diff --git a/vendor/curl/lib/curl_get_line.c b/vendor/curl/lib/curl_get_line.c
index 686abe7511..100207331d 100644
--- a/vendor/curl/lib/curl_get_line.c
+++ b/vendor/curl/lib/curl_get_line.c
@@ -33,14 +33,16 @@
 #include "memdebug.h"
 
 /*
- * Curl_get_line() makes sure to only return complete whole lines that fit in
- * 'len' bytes and end with a newline.
+ * Curl_get_line() makes sure to only return complete whole lines that end
+ * newlines.
  */
-char *Curl_get_line(char *buf, int len, FILE *input)
+int Curl_get_line(struct dynbuf *buf, FILE *input)
 {
-  bool partial = FALSE;
+  CURLcode result;
+  char buffer[128];
+  Curl_dyn_reset(buf);
   while(1) {
-    char *b = fgets(buf, len, input);
+    char *b = fgets(buffer, sizeof(buffer), input);
 
     if(b) {
       size_t rlen = strlen(b);
@@ -48,39 +50,28 @@ char *Curl_get_line(char *buf, int len, FILE *input)
       if(!rlen)
         break;
 
-      if(b[rlen-1] == '\n') {
-        /* b is \n terminated */
-        if(partial) {
-          partial = FALSE;
-          continue;
-        }
-        return b;
-      }
-      else if(feof(input)) {
-        if(partial)
-          /* Line is already too large to return, ignore rest */
-          break;
+      result = Curl_dyn_addn(buf, b, rlen);
+      if(result)
+        /* too long line or out of memory */
+        return 0; /* error */
 
-        if(rlen + 1 < (size_t) len) {
-          /* b is EOF terminated, insert missing \n */
-          b[rlen] = '\n';
-          b[rlen + 1] = '\0';
-          return b;
-        }
-        else
-          /* Maximum buffersize reached + EOF
-           * This line is impossible to add a \n to so we'll ignore it
-           */
-          break;
+      else if(b[rlen-1] == '\n')
+        /* end of the line */
+        return 1; /* all good */
+
+      else if(feof(input)) {
+        /* append a newline */
+        result = Curl_dyn_addn(buf, "\n", 1);
+        if(result)
+          /* too long line or out of memory */
+          return 0; /* error */
+        return 1; /* all good */
       }
-      else
-        /* Maximum buffersize reached */
-        partial = TRUE;
     }
     else
       break;
   }
-  return NULL;
+  return 0;
 }
 
 #endif /* if not disabled */
diff --git a/vendor/curl/lib/curl_get_line.h b/vendor/curl/lib/curl_get_line.h
index 0ff32c5c2c..7907cde880 100644
--- a/vendor/curl/lib/curl_get_line.h
+++ b/vendor/curl/lib/curl_get_line.h
@@ -24,8 +24,9 @@
  *
  ***************************************************************************/
 
-/* get_line() makes sure to only return complete whole lines that fit in 'len'
- * bytes and end with a newline. */
-char *Curl_get_line(char *buf, int len, FILE *input);
+#include "dynbuf.h"
+
+/* Curl_get_line() returns complete lines that end with a newline. */
+int Curl_get_line(struct dynbuf *buf, FILE *input);
 
 #endif /* HEADER_CURL_GET_LINE_H */
diff --git a/vendor/curl/lib/curl_gethostname.c b/vendor/curl/lib/curl_gethostname.c
index 706b2e6892..bd9b220d49 100644
--- a/vendor/curl/lib/curl_gethostname.c
+++ b/vendor/curl/lib/curl_gethostname.c
@@ -68,7 +68,7 @@ int Curl_gethostname(char * const name, GETHOSTNAME_TYPE_ARG2 namelen)
   /* Override host name when environment variable CURL_GETHOSTNAME is set */
   const char *force_hostname = getenv("CURL_GETHOSTNAME");
   if(force_hostname) {
-    strncpy(name, force_hostname, namelen);
+    strncpy(name, force_hostname, namelen - 1);
     err = 0;
   }
   else {
diff --git a/vendor/curl/lib/curl_hmac.h b/vendor/curl/lib/curl_hmac.h
index 9438ca782a..7a5387a948 100644
--- a/vendor/curl/lib/curl_hmac.h
+++ b/vendor/curl/lib/curl_hmac.h
@@ -24,8 +24,9 @@
  *
  ***************************************************************************/
 
-#if (defined(USE_CURL_NTLM_CORE) && !defined(USE_WINDOWS_SSPI)) \
-    || !defined(CURL_DISABLE_AWS)
+#if (defined(USE_CURL_NTLM_CORE) && !defined(USE_WINDOWS_SSPI))         \
+  || !defined(CURL_DISABLE_AWS) || !defined(CURL_DISABLE_DIGEST_AUTH)   \
+  || defined(USE_LIBSSH2)
 
 #include 
 
diff --git a/vendor/curl/lib/curl_memory.h b/vendor/curl/lib/curl_memory.h
index b8c46d7939..714ad71c9e 100644
--- a/vendor/curl/lib/curl_memory.h
+++ b/vendor/curl/lib/curl_memory.h
@@ -68,7 +68,7 @@
 #undef send
 #undef recv
 
-#ifdef WIN32
+#ifdef _WIN32
 #  ifdef UNICODE
 #    undef wcsdup
 #    undef _wcsdup
@@ -134,7 +134,7 @@ extern curl_free_callback Curl_cfree;
 extern curl_realloc_callback Curl_crealloc;
 extern curl_strdup_callback Curl_cstrdup;
 extern curl_calloc_callback Curl_ccalloc;
-#if defined(WIN32) && defined(UNICODE)
+#if defined(_WIN32) && defined(UNICODE)
 extern curl_wcsdup_callback Curl_cwcsdup;
 #endif
 
@@ -160,7 +160,7 @@ extern curl_wcsdup_callback Curl_cwcsdup;
 #undef free
 #define free(ptr) Curl_cfree(ptr)
 
-#ifdef WIN32
+#ifdef _WIN32
 #  ifdef UNICODE
 #    undef wcsdup
 #    define wcsdup(ptr) Curl_cwcsdup(ptr)
diff --git a/vendor/curl/lib/curl_memrchr.h b/vendor/curl/lib/curl_memrchr.h
index a1a4ba0927..45bb38c68e 100644
--- a/vendor/curl/lib/curl_memrchr.h
+++ b/vendor/curl/lib/curl_memrchr.h
@@ -28,9 +28,7 @@
 
 #ifdef HAVE_MEMRCHR
 
-#ifdef HAVE_STRING_H
-#  include 
-#endif
+#include 
 #ifdef HAVE_STRINGS_H
 #  include 
 #endif
diff --git a/vendor/curl/lib/curl_multibyte.c b/vendor/curl/lib/curl_multibyte.c
index 522ea34e82..86ac74ff4b 100644
--- a/vendor/curl/lib/curl_multibyte.c
+++ b/vendor/curl/lib/curl_multibyte.c
@@ -32,7 +32,7 @@
 
 #include "curl_setup.h"
 
-#if defined(WIN32)
+#if defined(_WIN32)
 
 #include "curl_multibyte.h"
 
@@ -84,7 +84,7 @@ char *curlx_convert_wchar_to_UTF8(const wchar_t *str_w)
   return str_utf8;
 }
 
-#endif /* WIN32 */
+#endif /* _WIN32 */
 
 #if defined(USE_WIN32_LARGE_FILES) || defined(USE_WIN32_SMALL_FILES)
 
@@ -159,21 +159,4 @@ int curlx_win32_stat(const char *path, struct_stat *buffer)
 #endif
 }
 
-int curlx_win32_access(const char *path, int mode)
-{
-#if defined(_UNICODE)
-  int result = -1;
-  wchar_t *path_w = curlx_convert_UTF8_to_wchar(path);
-  if(path_w) {
-    result = _waccess(path_w, mode);
-    curlx_unicodefree(path_w);
-  }
-  else
-    errno = EINVAL;
-  return result;
-#else
-  return _access(path, mode);
-#endif
-}
-
 #endif /* USE_WIN32_LARGE_FILES || USE_WIN32_SMALL_FILES */
diff --git a/vendor/curl/lib/curl_multibyte.h b/vendor/curl/lib/curl_multibyte.h
index ddac1f6382..8b9ac719e5 100644
--- a/vendor/curl/lib/curl_multibyte.h
+++ b/vendor/curl/lib/curl_multibyte.h
@@ -25,7 +25,7 @@
  ***************************************************************************/
 #include "curl_setup.h"
 
-#if defined(WIN32)
+#if defined(_WIN32)
 
  /*
   * MultiByte conversions using Windows kernel32 library.
@@ -33,7 +33,7 @@
 
 wchar_t *curlx_convert_UTF8_to_wchar(const char *str_utf8);
 char *curlx_convert_wchar_to_UTF8(const wchar_t *str_w);
-#endif /* WIN32 */
+#endif /* _WIN32 */
 
 /*
  * Macros curlx_convert_UTF8_to_tchar(), curlx_convert_tchar_to_UTF8()
@@ -54,7 +54,7 @@ char *curlx_convert_wchar_to_UTF8(const wchar_t *str_w);
  * ensure that the curl memdebug override macros do not replace them.
  */
 
-#if defined(UNICODE) && defined(WIN32)
+#if defined(UNICODE) && defined(_WIN32)
 
 #define curlx_convert_UTF8_to_tchar(ptr) curlx_convert_UTF8_to_wchar((ptr))
 #define curlx_convert_tchar_to_UTF8(ptr) curlx_convert_wchar_to_UTF8((ptr))
@@ -78,7 +78,7 @@ typedef union {
   const unsigned char *const_tbyte_ptr;
 } xcharp_u;
 
-#endif /* UNICODE && WIN32 */
+#endif /* UNICODE && _WIN32 */
 
 #define curlx_unicodefree(ptr)                          \
   do {                                                  \
diff --git a/vendor/curl/lib/curl_ntlm_core.c b/vendor/curl/lib/curl_ntlm_core.c
index cc0ed91672..6f6d75c031 100644
--- a/vendor/curl/lib/curl_ntlm_core.c
+++ b/vendor/curl/lib/curl_ntlm_core.c
@@ -111,6 +111,7 @@
 #  include 
 #else
 #  error "Can't compile NTLM support without a crypto library with DES."
+#  define CURL_NTLM_NOT_SUPPORTED
 #endif
 
 #include "urldata.h"
@@ -130,6 +131,7 @@
 #define NTLMv2_BLOB_SIGNATURE "\x01\x01\x00\x00"
 #define NTLMv2_BLOB_LEN       (44 -16 + ntlm->target_info_len + 4)
 
+#if !defined(CURL_NTLM_NOT_SUPPORTED)
 /*
 * Turns a 56-bit key into being 64-bit wide.
 */
@@ -144,6 +146,7 @@ static void extend_key_56_to_64(const unsigned char *key_56, char *key)
   key[6] = (unsigned char)(((key_56[5] << 2) & 0xFF) | (key_56[6] >> 6));
   key[7] = (unsigned char) ((key_56[6] << 1) & 0xFF);
 }
+#endif
 
 #if defined(USE_OPENSSL_DES) || defined(USE_WOLFSSL)
 /*
@@ -337,6 +340,10 @@ void Curl_ntlm_core_lm_resp(const unsigned char *keys,
   encrypt_des(plaintext, results, keys);
   encrypt_des(plaintext, results + 8, keys + 7);
   encrypt_des(plaintext, results + 16, keys + 14);
+#else
+  (void)keys;
+  (void)plaintext;
+  (void)results;
 #endif
 }
 
@@ -347,9 +354,11 @@ CURLcode Curl_ntlm_core_mk_lm_hash(const char *password,
                                    unsigned char *lmbuffer /* 21 bytes */)
 {
   unsigned char pw[14];
+#if !defined(CURL_NTLM_NOT_SUPPORTED)
   static const unsigned char magic[] = {
     0x4B, 0x47, 0x53, 0x21, 0x40, 0x23, 0x24, 0x25 /* i.e. KGS!@#$% */
   };
+#endif
   size_t len = CURLMIN(strlen(password), 14);
 
   Curl_strntoupper((char *)pw, password, len);
diff --git a/vendor/curl/lib/curl_ntlm_wb.c b/vendor/curl/lib/curl_ntlm_wb.c
deleted file mode 100644
index a10e2a1b09..0000000000
--- a/vendor/curl/lib/curl_ntlm_wb.c
+++ /dev/null
@@ -1,500 +0,0 @@
-/***************************************************************************
- *                                  _   _ ____  _
- *  Project                     ___| | | |  _ \| |
- *                             / __| | | | |_) | |
- *                            | (__| |_| |  _ <| |___
- *                             \___|\___/|_| \_\_____|
- *
- * Copyright (C) Daniel Stenberg, , et al.
- *
- * This software is licensed as described in the file COPYING, which
- * you should have received as part of this distribution. The terms
- * are also available at https://curl.se/docs/copyright.html.
- *
- * You may opt to use, copy, modify, merge, publish, distribute and/or sell
- * copies of the Software, and permit persons to whom the Software is
- * furnished to do so, under the terms of the COPYING file.
- *
- * This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY
- * KIND, either express or implied.
- *
- * SPDX-License-Identifier: curl
- *
- ***************************************************************************/
-
-#include "curl_setup.h"
-
-#if !defined(CURL_DISABLE_HTTP) && defined(USE_NTLM) && \
-    defined(NTLM_WB_ENABLED)
-
-/*
- * NTLM details:
- *
- * https://davenport.sourceforge.net/ntlm.html
- * https://www.innovation.ch/java/ntlm.html
- */
-
-#define DEBUG_ME 0
-
-#ifdef HAVE_SYS_WAIT_H
-#include 
-#endif
-#ifdef HAVE_SIGNAL_H
-#include 
-#endif
-#ifdef HAVE_PWD_H
-#include 
-#endif
-
-#include "urldata.h"
-#include "sendf.h"
-#include "select.h"
-#include "vauth/ntlm.h"
-#include "curl_ntlm_core.h"
-#include "curl_ntlm_wb.h"
-#include "url.h"
-#include "strerror.h"
-#include "strdup.h"
-#include "strcase.h"
-
-/* The last 3 #include files should be in this order */
-#include "curl_printf.h"
-#include "curl_memory.h"
-#include "memdebug.h"
-
-#if DEBUG_ME
-# define DEBUG_OUT(x) x
-#else
-# define DEBUG_OUT(x) Curl_nop_stmt
-#endif
-
-/* Portable 'sclose_nolog' used only in child process instead of 'sclose'
-   to avoid fooling the socket leak detector */
-#if defined(HAVE_CLOSESOCKET)
-#  define sclose_nolog(x)  closesocket((x))
-#elif defined(HAVE_CLOSESOCKET_CAMEL)
-#  define sclose_nolog(x)  CloseSocket((x))
-#else
-#  define sclose_nolog(x)  close((x))
-#endif
-
-static void ntlm_wb_cleanup(struct ntlmdata *ntlm)
-{
-  if(ntlm->ntlm_auth_hlpr_socket != CURL_SOCKET_BAD) {
-    sclose(ntlm->ntlm_auth_hlpr_socket);
-    ntlm->ntlm_auth_hlpr_socket = CURL_SOCKET_BAD;
-  }
-
-  if(ntlm->ntlm_auth_hlpr_pid) {
-    int i;
-    for(i = 0; i < 4; i++) {
-      pid_t ret = waitpid(ntlm->ntlm_auth_hlpr_pid, NULL, WNOHANG);
-      if(ret == ntlm->ntlm_auth_hlpr_pid || errno == ECHILD)
-        break;
-      switch(i) {
-      case 0:
-        kill(ntlm->ntlm_auth_hlpr_pid, SIGTERM);
-        break;
-      case 1:
-        /* Give the process another moment to shut down cleanly before
-           bringing down the axe */
-        Curl_wait_ms(1);
-        break;
-      case 2:
-        kill(ntlm->ntlm_auth_hlpr_pid, SIGKILL);
-        break;
-      case 3:
-        break;
-      }
-    }
-    ntlm->ntlm_auth_hlpr_pid = 0;
-  }
-
-  Curl_safefree(ntlm->challenge);
-  Curl_safefree(ntlm->response);
-}
-
-static CURLcode ntlm_wb_init(struct Curl_easy *data, struct ntlmdata *ntlm,
-                             const char *userp)
-{
-  curl_socket_t sockfds[2];
-  pid_t child_pid;
-  const char *username;
-  char *slash, *domain = NULL;
-  const char *ntlm_auth = NULL;
-  char *ntlm_auth_alloc = NULL;
-#if defined(HAVE_GETPWUID_R) && defined(HAVE_GETEUID)
-  struct passwd pw, *pw_res;
-  char pwbuf[1024];
-#endif
-  char buffer[STRERROR_LEN];
-
-#if defined(CURL_DISABLE_VERBOSE_STRINGS)
-  (void) data;
-#endif
-
-  /* Return if communication with ntlm_auth already set up */
-  if(ntlm->ntlm_auth_hlpr_socket != CURL_SOCKET_BAD ||
-     ntlm->ntlm_auth_hlpr_pid)
-    return CURLE_OK;
-
-  username = userp;
-  /* The real ntlm_auth really doesn't like being invoked with an
-     empty username. It won't make inferences for itself, and expects
-     the client to do so (mostly because it's really designed for
-     servers like squid to use for auth, and client support is an
-     afterthought for it). So try hard to provide a suitable username
-     if we don't already have one. But if we can't, provide the
-     empty one anyway. Perhaps they have an implementation of the
-     ntlm_auth helper which *doesn't* need it so we might as well try */
-  if(!username || !username[0]) {
-    username = getenv("NTLMUSER");
-    if(!username || !username[0])
-      username = getenv("LOGNAME");
-    if(!username || !username[0])
-      username = getenv("USER");
-#if defined(HAVE_GETPWUID_R) && defined(HAVE_GETEUID)
-    if((!username || !username[0]) &&
-       !getpwuid_r(geteuid(), &pw, pwbuf, sizeof(pwbuf), &pw_res) &&
-       pw_res) {
-      username = pw.pw_name;
-    }
-#endif
-    if(!username || !username[0])
-      username = userp;
-  }
-  slash = strpbrk(username, "\\/");
-  if(slash) {
-    domain = strdup(username);
-    if(!domain)
-      return CURLE_OUT_OF_MEMORY;
-    slash = domain + (slash - username);
-    *slash = '\0';
-    username = username + (slash - domain) + 1;
-  }
-
-  /* For testing purposes, when DEBUGBUILD is defined and environment
-     variable CURL_NTLM_WB_FILE is set a fake_ntlm is used to perform
-     NTLM challenge/response which only accepts commands and output
-     strings pre-written in test case definitions */
-#ifdef DEBUGBUILD
-  ntlm_auth_alloc = curl_getenv("CURL_NTLM_WB_FILE");
-  if(ntlm_auth_alloc)
-    ntlm_auth = ntlm_auth_alloc;
-  else
-#endif
-    ntlm_auth = NTLM_WB_FILE;
-
-  if(access(ntlm_auth, X_OK) != 0) {
-    failf(data, "Could not access ntlm_auth: %s errno %d: %s",
-          ntlm_auth, errno, Curl_strerror(errno, buffer, sizeof(buffer)));
-    goto done;
-  }
-
-  if(Curl_socketpair(AF_UNIX, SOCK_STREAM, 0, sockfds)) {
-    failf(data, "Could not open socket pair. errno %d: %s",
-          errno, Curl_strerror(errno, buffer, sizeof(buffer)));
-    goto done;
-  }
-
-  child_pid = fork();
-  if(child_pid == -1) {
-    sclose(sockfds[0]);
-    sclose(sockfds[1]);
-    failf(data, "Could not fork. errno %d: %s",
-          errno, Curl_strerror(errno, buffer, sizeof(buffer)));
-    goto done;
-  }
-  else if(!child_pid) {
-    /*
-     * child process
-     */
-
-    /* Don't use sclose in the child since it fools the socket leak detector */
-    sclose_nolog(sockfds[0]);
-    if(dup2(sockfds[1], STDIN_FILENO) == -1) {
-      failf(data, "Could not redirect child stdin. errno %d: %s",
-            errno, Curl_strerror(errno, buffer, sizeof(buffer)));
-      exit(1);
-    }
-
-    if(dup2(sockfds[1], STDOUT_FILENO) == -1) {
-      failf(data, "Could not redirect child stdout. errno %d: %s",
-            errno, Curl_strerror(errno, buffer, sizeof(buffer)));
-      exit(1);
-    }
-
-    if(domain)
-      execl(ntlm_auth, ntlm_auth,
-            "--helper-protocol", "ntlmssp-client-1",
-            "--use-cached-creds",
-            "--username", username,
-            "--domain", domain,
-            NULL);
-    else
-      execl(ntlm_auth, ntlm_auth,
-            "--helper-protocol", "ntlmssp-client-1",
-            "--use-cached-creds",
-            "--username", username,
-            NULL);
-
-    sclose_nolog(sockfds[1]);
-    failf(data, "Could not execl(). errno %d: %s",
-          errno, Curl_strerror(errno, buffer, sizeof(buffer)));
-    exit(1);
-  }
-
-  sclose(sockfds[1]);
-  ntlm->ntlm_auth_hlpr_socket = sockfds[0];
-  ntlm->ntlm_auth_hlpr_pid = child_pid;
-  free(domain);
-  free(ntlm_auth_alloc);
-  return CURLE_OK;
-
-done:
-  free(domain);
-  free(ntlm_auth_alloc);
-  return CURLE_REMOTE_ACCESS_DENIED;
-}
-
-/* if larger than this, something is seriously wrong */
-#define MAX_NTLM_WB_RESPONSE 100000
-
-static CURLcode ntlm_wb_response(struct Curl_easy *data, struct ntlmdata *ntlm,
-                                 const char *input, curlntlm state)
-{
-  size_t len_in = strlen(input), len_out = 0;
-  struct dynbuf b;
-  char *ptr = NULL;
-  unsigned char *buf = (unsigned char *)data->state.buffer;
-  Curl_dyn_init(&b, MAX_NTLM_WB_RESPONSE);
-
-  while(len_in > 0) {
-    ssize_t written = swrite(ntlm->ntlm_auth_hlpr_socket, input, len_in);
-    if(written == -1) {
-      /* Interrupted by a signal, retry it */
-      if(errno == EINTR)
-        continue;
-      /* write failed if other errors happen */
-      goto done;
-    }
-    input += written;
-    len_in -= written;
-  }
-  /* Read one line */
-  while(1) {
-    ssize_t size =
-      sread(ntlm->ntlm_auth_hlpr_socket, buf, data->set.buffer_size);
-    if(size == -1) {
-      if(errno == EINTR)
-        continue;
-      goto done;
-    }
-    else if(size == 0)
-      goto done;
-
-    if(Curl_dyn_addn(&b, buf, size))
-      goto done;
-
-    len_out = Curl_dyn_len(&b);
-    ptr = Curl_dyn_ptr(&b);
-    if(len_out && ptr[len_out - 1] == '\n') {
-      ptr[len_out - 1] = '\0';
-      break; /* done! */
-    }
-    /* loop */
-  }
-
-  /* Samba/winbind installed but not configured */
-  if(state == NTLMSTATE_TYPE1 &&
-     len_out == 3 &&
-     ptr[0] == 'P' && ptr[1] == 'W')
-    goto done;
-  /* invalid response */
-  if(len_out < 4)
-    goto done;
-  if(state == NTLMSTATE_TYPE1 &&
-     (ptr[0]!='Y' || ptr[1]!='R' || ptr[2]!=' '))
-    goto done;
-  if(state == NTLMSTATE_TYPE2 &&
-     (ptr[0]!='K' || ptr[1]!='K' || ptr[2]!=' ') &&
-     (ptr[0]!='A' || ptr[1]!='F' || ptr[2]!=' '))
-    goto done;
-
-  ntlm->response = strdup(ptr + 3);
-  Curl_dyn_free(&b);
-  if(!ntlm->response)
-    return CURLE_OUT_OF_MEMORY;
-  return CURLE_OK;
-done:
-  Curl_dyn_free(&b);
-  return CURLE_REMOTE_ACCESS_DENIED;
-}
-
-CURLcode Curl_input_ntlm_wb(struct Curl_easy *data,
-                            struct connectdata *conn,
-                            bool proxy,
-                            const char *header)
-{
-  struct ntlmdata *ntlm = proxy ? &conn->proxyntlm : &conn->ntlm;
-  curlntlm *state = proxy ? &conn->proxy_ntlm_state : &conn->http_ntlm_state;
-
-  (void) data;  /* In case it gets unused by nop log macros. */
-
-  if(!checkprefix("NTLM", header))
-    return CURLE_BAD_CONTENT_ENCODING;
-
-  header += strlen("NTLM");
-  while(*header && ISSPACE(*header))
-    header++;
-
-  if(*header) {
-    ntlm->challenge = strdup(header);
-    if(!ntlm->challenge)
-      return CURLE_OUT_OF_MEMORY;
-
-    *state = NTLMSTATE_TYPE2; /* We got a type-2 message */
-  }
-  else {
-    if(*state == NTLMSTATE_LAST) {
-      infof(data, "NTLM auth restarted");
-      Curl_http_auth_cleanup_ntlm_wb(conn);
-    }
-    else if(*state == NTLMSTATE_TYPE3) {
-      infof(data, "NTLM handshake rejected");
-      Curl_http_auth_cleanup_ntlm_wb(conn);
-      *state = NTLMSTATE_NONE;
-      return CURLE_REMOTE_ACCESS_DENIED;
-    }
-    else if(*state >= NTLMSTATE_TYPE1) {
-      infof(data, "NTLM handshake failure (internal error)");
-      return CURLE_REMOTE_ACCESS_DENIED;
-    }
-
-    *state = NTLMSTATE_TYPE1; /* We should send away a type-1 */
-  }
-
-  return CURLE_OK;
-}
-
-/*
- * This is for creating ntlm header output by delegating challenge/response
- * to Samba's winbind daemon helper ntlm_auth.
- */
-CURLcode Curl_output_ntlm_wb(struct Curl_easy *data, struct connectdata *conn,
-                             bool proxy)
-{
-  /* point to the address of the pointer that holds the string to send to the
-     server, which is for a plain host or for an HTTP proxy */
-  char **allocuserpwd;
-  /* point to the name and password for this */
-  const char *userp;
-  struct ntlmdata *ntlm;
-  curlntlm *state;
-  struct auth *authp;
-
-  CURLcode res = CURLE_OK;
-
-  DEBUGASSERT(conn);
-  DEBUGASSERT(data);
-
-  if(proxy) {
-#ifndef CURL_DISABLE_PROXY
-    allocuserpwd = &data->state.aptr.proxyuserpwd;
-    userp = conn->http_proxy.user;
-    ntlm = &conn->proxyntlm;
-    state = &conn->proxy_ntlm_state;
-    authp = &data->state.authproxy;
-#else
-    return CURLE_NOT_BUILT_IN;
-#endif
-  }
-  else {
-    allocuserpwd = &data->state.aptr.userpwd;
-    userp = conn->user;
-    ntlm = &conn->ntlm;
-    state = &conn->http_ntlm_state;
-    authp = &data->state.authhost;
-  }
-  authp->done = FALSE;
-
-  /* not set means empty */
-  if(!userp)
-    userp = "";
-
-  switch(*state) {
-  case NTLMSTATE_TYPE1:
-  default:
-    /* Use Samba's 'winbind' daemon to support NTLM authentication,
-     * by delegating the NTLM challenge/response protocol to a helper
-     * in ntlm_auth.
-     * https://web.archive.org/web/20190925164737
-     * /devel.squid-cache.org/ntlm/squid_helper_protocol.html
-     * https://www.samba.org/samba/docs/man/manpages-3/winbindd.8.html
-     * https://www.samba.org/samba/docs/man/manpages-3/ntlm_auth.1.html
-     * Preprocessor symbol 'NTLM_WB_ENABLED' is defined when this
-     * feature is enabled and 'NTLM_WB_FILE' symbol holds absolute
-     * filename of ntlm_auth helper.
-     * If NTLM authentication using winbind fails, go back to original
-     * request handling process.
-     */
-    /* Create communication with ntlm_auth */
-    res = ntlm_wb_init(data, ntlm, userp);
-    if(res)
-      return res;
-    res = ntlm_wb_response(data, ntlm, "YR\n", *state);
-    if(res)
-      return res;
-
-    free(*allocuserpwd);
-    *allocuserpwd = aprintf("%sAuthorization: NTLM %s\r\n",
-                            proxy ? "Proxy-" : "",
-                            ntlm->response);
-    DEBUG_OUT(fprintf(stderr, "**** Header %s\n ", *allocuserpwd));
-    Curl_safefree(ntlm->response);
-    if(!*allocuserpwd)
-      return CURLE_OUT_OF_MEMORY;
-    break;
-
-  case NTLMSTATE_TYPE2: {
-    char *input = aprintf("TT %s\n", ntlm->challenge);
-    if(!input)
-      return CURLE_OUT_OF_MEMORY;
-    res = ntlm_wb_response(data, ntlm, input, *state);
-    free(input);
-    if(res)
-      return res;
-
-    free(*allocuserpwd);
-    *allocuserpwd = aprintf("%sAuthorization: NTLM %s\r\n",
-                            proxy ? "Proxy-" : "",
-                            ntlm->response);
-    DEBUG_OUT(fprintf(stderr, "**** %s\n ", *allocuserpwd));
-    *state = NTLMSTATE_TYPE3; /* we sent a type-3 */
-    authp->done = TRUE;
-    Curl_http_auth_cleanup_ntlm_wb(conn);
-    if(!*allocuserpwd)
-      return CURLE_OUT_OF_MEMORY;
-    break;
-  }
-  case NTLMSTATE_TYPE3:
-    /* connection is already authenticated,
-     * don't send a header in future requests */
-    *state = NTLMSTATE_LAST;
-    /* FALLTHROUGH */
-  case NTLMSTATE_LAST:
-    Curl_safefree(*allocuserpwd);
-    authp->done = TRUE;
-    break;
-  }
-
-  return CURLE_OK;
-}
-
-void Curl_http_auth_cleanup_ntlm_wb(struct connectdata *conn)
-{
-  ntlm_wb_cleanup(&conn->ntlm);
-  ntlm_wb_cleanup(&conn->proxyntlm);
-}
-
-#endif /* !CURL_DISABLE_HTTP && USE_NTLM && NTLM_WB_ENABLED */
diff --git a/vendor/curl/lib/curl_path.c b/vendor/curl/lib/curl_path.c
index 856423db99..144f8803d3 100644
--- a/vendor/curl/lib/curl_path.c
+++ b/vendor/curl/lib/curl_path.c
@@ -98,8 +98,8 @@ CURLcode Curl_getworkingpath(struct Curl_easy *data,
   return CURLE_OK;
 }
 
-/* The get_pathname() function is being borrowed from OpenSSH sftp.c
-   version 4.6p1. */
+/* The original get_pathname() function came from OpenSSH sftp.c version
+   4.6p1. */
 /*
  * Copyright (c) 2001-2004 Damien Miller 
  *
@@ -115,38 +115,37 @@ CURLcode Curl_getworkingpath(struct Curl_easy *data,
  * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
  * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
  */
-CURLcode Curl_get_pathname(const char **cpp, char **path, char *homedir)
+
+#define MAX_PATHLENGTH 65535 /* arbitrary long */
+
+CURLcode Curl_get_pathname(const char **cpp, char **path, const char *homedir)
 {
   const char *cp = *cpp, *end;
   char quot;
-  unsigned int i, j;
-  size_t fullPathLength, pathLength;
-  bool relativePath = false;
+  unsigned int i;
   static const char WHITESPACE[] = " \t\r\n";
+  struct dynbuf out;
+  CURLcode result;
 
   DEBUGASSERT(homedir);
-  if(!*cp || !homedir) {
-    *cpp = NULL;
-    *path = NULL;
+  *path = NULL;
+  *cpp = NULL;
+  if(!*cp || !homedir)
     return CURLE_QUOTE_ERROR;
-  }
+
+  Curl_dyn_init(&out, MAX_PATHLENGTH);
+
   /* Ignore leading whitespace */
   cp += strspn(cp, WHITESPACE);
-  /* Allocate enough space for home directory and filename + separator */
-  fullPathLength = strlen(cp) + strlen(homedir) + 2;
-  *path = malloc(fullPathLength);
-  if(!*path)
-    return CURLE_OUT_OF_MEMORY;
 
   /* Check for quoted filenames */
   if(*cp == '\"' || *cp == '\'') {
     quot = *cp++;
 
     /* Search for terminating quote, unescape some chars */
-    for(i = j = 0; i <= strlen(cp); i++) {
+    for(i = 0; i <= strlen(cp); i++) {
       if(cp[i] == quot) {  /* Found quote */
         i++;
-        (*path)[j] = '\0';
         break;
       }
       if(cp[i] == '\0') {  /* End of string */
@@ -159,40 +158,45 @@ CURLcode Curl_get_pathname(const char **cpp, char **path, char *homedir)
           goto fail;
         }
       }
-      (*path)[j++] = cp[i];
+      result = Curl_dyn_addn(&out, &cp[i], 1);
+      if(result)
+        return result;
     }
 
-    if(j == 0) {
+    if(!Curl_dyn_len(&out))
       goto fail;
-    }
-    *cpp = cp + i + strspn(cp + i, WHITESPACE);
+
+    /* return pointer to second parameter if it exists */
+    *cpp = &cp[i] + strspn(&cp[i], WHITESPACE);
   }
   else {
     /* Read to end of filename - either to whitespace or terminator */
     end = strpbrk(cp, WHITESPACE);
     if(!end)
       end = strchr(cp, '\0');
+
     /* return pointer to second parameter if it exists */
     *cpp = end + strspn(end, WHITESPACE);
-    pathLength = 0;
-    relativePath = (cp[0] == '/' && cp[1] == '~' && cp[2] == '/');
+
     /* Handling for relative path - prepend home directory */
-    if(relativePath) {
-      strcpy(*path, homedir);
-      pathLength = strlen(homedir);
-      (*path)[pathLength++] = '/';
-      (*path)[pathLength] = '\0';
+    if(cp[0] == '/' && cp[1] == '~' && cp[2] == '/') {
+      result = Curl_dyn_add(&out, homedir);
+      if(!result)
+        result = Curl_dyn_addn(&out, "/", 1);
+      if(result)
+        return result;
       cp += 3;
     }
     /* Copy path name up until first "whitespace" */
-    memcpy(&(*path)[pathLength], cp, (int)(end - cp));
-    pathLength += (int)(end - cp);
-    (*path)[pathLength] = '\0';
+    result = Curl_dyn_addn(&out, cp, (end - cp));
+    if(result)
+      return result;
   }
+  *path = Curl_dyn_ptr(&out);
   return CURLE_OK;
 
 fail:
-  Curl_safefree(*path);
+  Curl_dyn_free(&out);
   return CURLE_QUOTE_ERROR;
 }
 
diff --git a/vendor/curl/lib/curl_path.h b/vendor/curl/lib/curl_path.h
index 9ed09dea83..6fdb2fddff 100644
--- a/vendor/curl/lib/curl_path.h
+++ b/vendor/curl/lib/curl_path.h
@@ -28,7 +28,7 @@
 #include 
 #include "urldata.h"
 
-#ifdef WIN32
+#ifdef _WIN32
 #  undef  PATH_MAX
 #  define PATH_MAX MAX_PATH
 #  ifndef R_OK
@@ -45,5 +45,5 @@ CURLcode Curl_getworkingpath(struct Curl_easy *data,
                              char *homedir,
                              char **path);
 
-CURLcode Curl_get_pathname(const char **cpp, char **path, char *homedir);
+CURLcode Curl_get_pathname(const char **cpp, char **path, const char *homedir);
 #endif /* HEADER_CURL_PATH_H */
diff --git a/vendor/curl/lib/curl_printf.h b/vendor/curl/lib/curl_printf.h
index 46ef344f76..c2457d2a64 100644
--- a/vendor/curl/lib/curl_printf.h
+++ b/vendor/curl/lib/curl_printf.h
@@ -31,6 +31,10 @@
 
 #include 
 
+#define MERR_OK        0
+#define MERR_MEM       1
+#define MERR_TOO_LARGE 2
+
 # undef printf
 # undef fprintf
 # undef msnprintf
diff --git a/vendor/curl/lib/curl_rtmp.c b/vendor/curl/lib/curl_rtmp.c
index 406fb42ac0..76eff787b9 100644
--- a/vendor/curl/lib/curl_rtmp.c
+++ b/vendor/curl/lib/curl_rtmp.c
@@ -35,11 +35,13 @@
 #include "warnless.h"
 #include 
 #include 
+
+/* The last 3 #include files should be in this order */
+#include "curl_printf.h"
 #include "curl_memory.h"
-/* The last #include file should be: */
 #include "memdebug.h"
 
-#if defined(WIN32) && !defined(USE_LWIPSOCK)
+#if defined(_WIN32) && !defined(USE_LWIPSOCK)
 #define setsockopt(a,b,c,d,e) (setsockopt)(a,b,c,(const char *)d,(int)e)
 #define SET_RCVTIMEO(tv,s)   int tv = s*1000
 #elif defined(LWIP_SO_SNDRCVTIMEO_NONSTANDARD)
@@ -66,7 +68,7 @@ static Curl_send rtmp_send;
  */
 
 const struct Curl_handler Curl_handler_rtmp = {
-  "RTMP",                               /* scheme */
+  "rtmp",                               /* scheme */
   rtmp_setup_connection,                /* setup_connection */
   rtmp_do,                              /* do_it */
   rtmp_done,                            /* done */
@@ -79,7 +81,8 @@ const struct Curl_handler Curl_handler_rtmp = {
   ZERO_NULL,                            /* domore_getsock */
   ZERO_NULL,                            /* perform_getsock */
   rtmp_disconnect,                      /* disconnect */
-  ZERO_NULL,                            /* readwrite */
+  ZERO_NULL,                            /* write_resp */
+  ZERO_NULL,                            /* write_resp_hd */
   ZERO_NULL,                            /* connection_check */
   ZERO_NULL,                            /* attach connection */
   PORT_RTMP,                            /* defport */
@@ -89,7 +92,7 @@ const struct Curl_handler Curl_handler_rtmp = {
 };
 
 const struct Curl_handler Curl_handler_rtmpt = {
-  "RTMPT",                              /* scheme */
+  "rtmpt",                              /* scheme */
   rtmp_setup_connection,                /* setup_connection */
   rtmp_do,                              /* do_it */
   rtmp_done,                            /* done */
@@ -102,7 +105,8 @@ const struct Curl_handler Curl_handler_rtmpt = {
   ZERO_NULL,                            /* domore_getsock */
   ZERO_NULL,                            /* perform_getsock */
   rtmp_disconnect,                      /* disconnect */
-  ZERO_NULL,                            /* readwrite */
+  ZERO_NULL,                            /* write_resp */
+  ZERO_NULL,                            /* write_resp_hd */
   ZERO_NULL,                            /* connection_check */
   ZERO_NULL,                            /* attach connection */
   PORT_RTMPT,                           /* defport */
@@ -112,7 +116,7 @@ const struct Curl_handler Curl_handler_rtmpt = {
 };
 
 const struct Curl_handler Curl_handler_rtmpe = {
-  "RTMPE",                              /* scheme */
+  "rtmpe",                              /* scheme */
   rtmp_setup_connection,                /* setup_connection */
   rtmp_do,                              /* do_it */
   rtmp_done,                            /* done */
@@ -125,7 +129,8 @@ const struct Curl_handler Curl_handler_rtmpe = {
   ZERO_NULL,                            /* domore_getsock */
   ZERO_NULL,                            /* perform_getsock */
   rtmp_disconnect,                      /* disconnect */
-  ZERO_NULL,                            /* readwrite */
+  ZERO_NULL,                            /* write_resp */
+  ZERO_NULL,                            /* write_resp_hd */
   ZERO_NULL,                            /* connection_check */
   ZERO_NULL,                            /* attach connection */
   PORT_RTMP,                            /* defport */
@@ -135,7 +140,7 @@ const struct Curl_handler Curl_handler_rtmpe = {
 };
 
 const struct Curl_handler Curl_handler_rtmpte = {
-  "RTMPTE",                             /* scheme */
+  "rtmpte",                             /* scheme */
   rtmp_setup_connection,                /* setup_connection */
   rtmp_do,                              /* do_it */
   rtmp_done,                            /* done */
@@ -148,7 +153,8 @@ const struct Curl_handler Curl_handler_rtmpte = {
   ZERO_NULL,                            /* domore_getsock */
   ZERO_NULL,                            /* perform_getsock */
   rtmp_disconnect,                      /* disconnect */
-  ZERO_NULL,                            /* readwrite */
+  ZERO_NULL,                            /* write_resp */
+  ZERO_NULL,                            /* write_resp_hd */
   ZERO_NULL,                            /* connection_check */
   ZERO_NULL,                            /* attach connection */
   PORT_RTMPT,                           /* defport */
@@ -158,7 +164,7 @@ const struct Curl_handler Curl_handler_rtmpte = {
 };
 
 const struct Curl_handler Curl_handler_rtmps = {
-  "RTMPS",                              /* scheme */
+  "rtmps",                              /* scheme */
   rtmp_setup_connection,                /* setup_connection */
   rtmp_do,                              /* do_it */
   rtmp_done,                            /* done */
@@ -171,7 +177,8 @@ const struct Curl_handler Curl_handler_rtmps = {
   ZERO_NULL,                            /* domore_getsock */
   ZERO_NULL,                            /* perform_getsock */
   rtmp_disconnect,                      /* disconnect */
-  ZERO_NULL,                            /* readwrite */
+  ZERO_NULL,                            /* write_resp */
+  ZERO_NULL,                            /* write_resp_hd */
   ZERO_NULL,                            /* connection_check */
   ZERO_NULL,                            /* attach connection */
   PORT_RTMPS,                           /* defport */
@@ -181,7 +188,7 @@ const struct Curl_handler Curl_handler_rtmps = {
 };
 
 const struct Curl_handler Curl_handler_rtmpts = {
-  "RTMPTS",                             /* scheme */
+  "rtmpts",                             /* scheme */
   rtmp_setup_connection,                /* setup_connection */
   rtmp_do,                              /* do_it */
   rtmp_done,                            /* done */
@@ -194,7 +201,8 @@ const struct Curl_handler Curl_handler_rtmpts = {
   ZERO_NULL,                            /* domore_getsock */
   ZERO_NULL,                            /* perform_getsock */
   rtmp_disconnect,                      /* disconnect */
-  ZERO_NULL,                            /* readwrite */
+  ZERO_NULL,                            /* write_resp */
+  ZERO_NULL,                            /* write_resp_hd */
   ZERO_NULL,                            /* connection_check */
   ZERO_NULL,                            /* attach connection */
   PORT_RTMPS,                           /* defport */
@@ -265,10 +273,10 @@ static CURLcode rtmp_do(struct Curl_easy *data, bool *done)
 
   if(data->state.upload) {
     Curl_pgrsSetUploadSize(data, data->state.infilesize);
-    Curl_setup_transfer(data, -1, -1, FALSE, FIRSTSOCKET);
+    Curl_xfer_setup(data, -1, -1, FALSE, FIRSTSOCKET);
   }
   else
-    Curl_setup_transfer(data, FIRSTSOCKET, -1, FALSE, -1);
+    Curl_xfer_setup(data, FIRSTSOCKET, -1, FALSE, -1);
   *done = TRUE;
   return CURLE_OK;
 }
@@ -335,4 +343,20 @@ static ssize_t rtmp_send(struct Curl_easy *data, int sockindex,
 
   return num;
 }
+
+void Curl_rtmp_version(char *version, size_t len)
+{
+  char suff[2];
+  if(RTMP_LIB_VERSION & 0xff) {
+    suff[0] = (RTMP_LIB_VERSION & 0xff) + 'a' - 1;
+    suff[1] = '\0';
+  }
+  else
+    suff[0] = '\0';
+
+  msnprintf(version, len, "librtmp/%d.%d%s",
+            RTMP_LIB_VERSION >> 16, (RTMP_LIB_VERSION >> 8) & 0xff,
+            suff);
+}
+
 #endif  /* USE_LIBRTMP */
diff --git a/vendor/curl/lib/curl_rtmp.h b/vendor/curl/lib/curl_rtmp.h
index 9b93ee060b..339d3a4384 100644
--- a/vendor/curl/lib/curl_rtmp.h
+++ b/vendor/curl/lib/curl_rtmp.h
@@ -30,6 +30,8 @@ extern const struct Curl_handler Curl_handler_rtmpe;
 extern const struct Curl_handler Curl_handler_rtmpte;
 extern const struct Curl_handler Curl_handler_rtmps;
 extern const struct Curl_handler Curl_handler_rtmpts;
+
+void Curl_rtmp_version(char *version, size_t len);
 #endif
 
 #endif /* HEADER_CURL_RTMP_H */
diff --git a/vendor/curl/lib/curl_sasl.c b/vendor/curl/lib/curl_sasl.c
index 91ddf10622..ba8911b72b 100644
--- a/vendor/curl/lib/curl_sasl.c
+++ b/vendor/curl/lib/curl_sasl.c
@@ -205,18 +205,23 @@ void Curl_sasl_init(struct SASL *sasl, struct Curl_easy *data,
   sasl->force_ir = FALSE;          /* Respect external option */
 
   if(auth != CURLAUTH_BASIC) {
-    sasl->resetprefs = FALSE;
-    sasl->prefmech = SASL_AUTH_NONE;
+    unsigned short mechs = SASL_AUTH_NONE;
+
+    /* If some usable http authentication options have been set, determine
+       new defaults from them. */
     if(auth & CURLAUTH_BASIC)
-      sasl->prefmech |= SASL_MECH_PLAIN | SASL_MECH_LOGIN;
+      mechs |= SASL_MECH_PLAIN | SASL_MECH_LOGIN;
     if(auth & CURLAUTH_DIGEST)
-      sasl->prefmech |= SASL_MECH_DIGEST_MD5;
+      mechs |= SASL_MECH_DIGEST_MD5;
     if(auth & CURLAUTH_NTLM)
-      sasl->prefmech |= SASL_MECH_NTLM;
+      mechs |= SASL_MECH_NTLM;
     if(auth & CURLAUTH_BEARER)
-      sasl->prefmech |= SASL_MECH_OAUTHBEARER | SASL_MECH_XOAUTH2;
+      mechs |= SASL_MECH_OAUTHBEARER | SASL_MECH_XOAUTH2;
     if(auth & CURLAUTH_GSSAPI)
-      sasl->prefmech |= SASL_MECH_GSSAPI;
+      mechs |= SASL_MECH_GSSAPI;
+
+    if(mechs != SASL_AUTH_NONE)
+      sasl->prefmech = mechs;
   }
 }
 
@@ -262,6 +267,8 @@ static void sasl_state(struct SASL *sasl, struct Curl_easy *data,
   sasl->state = newstate;
 }
 
+#if defined(USE_NTLM) || defined(USE_GSASL) || defined(USE_KERBEROS5) || \
+  !defined(CURL_DISABLE_DIGEST_AUTH)
 /* Get the SASL server message and convert it to binary. */
 static CURLcode get_server_message(struct SASL *sasl, struct Curl_easy *data,
                                    struct bufref *out)
@@ -284,6 +291,7 @@ static CURLcode get_server_message(struct SASL *sasl, struct Curl_easy *data,
   }
   return result;
 }
+#endif
 
 /* Encode the outgoing SASL message. */
 static CURLcode build_message(struct SASL *sasl, struct bufref *msg)
@@ -368,7 +376,7 @@ CURLcode Curl_sasl_start(struct SASL *sasl, struct Curl_easy *data,
     sasl->authused = SASL_MECH_EXTERNAL;
 
     if(force_ir || data->set.sasl_ir)
-      result = Curl_auth_create_external_message(conn->user, &resp);
+      Curl_auth_create_external_message(conn->user, &resp);
   }
   else if(data->state.aptr.user) {
 #if defined(USE_KERBEROS5)
@@ -490,7 +498,7 @@ CURLcode Curl_sasl_start(struct SASL *sasl, struct Curl_easy *data,
       sasl->authused = SASL_MECH_LOGIN;
 
       if(force_ir || data->set.sasl_ir)
-        result = Curl_auth_create_login_message(conn->user, &resp);
+        Curl_auth_create_login_message(conn->user, &resp);
     }
   }
 
@@ -568,14 +576,14 @@ CURLcode Curl_sasl_continue(struct SASL *sasl, struct Curl_easy *data,
                                             conn->user, conn->passwd, &resp);
     break;
   case SASL_LOGIN:
-    result = Curl_auth_create_login_message(conn->user, &resp);
+    Curl_auth_create_login_message(conn->user, &resp);
     newstate = SASL_LOGIN_PASSWD;
     break;
   case SASL_LOGIN_PASSWD:
-    result = Curl_auth_create_login_message(conn->passwd, &resp);
+    Curl_auth_create_login_message(conn->passwd, &resp);
     break;
   case SASL_EXTERNAL:
-    result = Curl_auth_create_external_message(conn->user, &resp);
+    Curl_auth_create_external_message(conn->user, &resp);
     break;
 #ifdef USE_GSASL
   case SASL_GSASL:
diff --git a/vendor/curl/lib/curl_setup.h b/vendor/curl/lib/curl_setup.h
index b43714da74..6c05b87525 100644
--- a/vendor/curl/lib/curl_setup.h
+++ b/vendor/curl/lib/curl_setup.h
@@ -28,7 +28,14 @@
 #define CURL_NO_OLDIES
 #endif
 
-/* define mingw version macros, eg __MINGW{32,64}_{MINOR,MAJOR}_VERSION */
+/* FIXME: Delete this once the warnings have been fixed. */
+#if !defined(CURL_WARN_SIGN_CONVERSION)
+#ifdef __GNUC__
+#pragma GCC diagnostic ignored "-Wsign-conversion"
+#endif
+#endif
+
+/* Set default _WIN32_WINNT */
 #ifdef __MINGW32__
 #include <_mingw.h>
 #endif
@@ -41,15 +48,7 @@
 #pragma warning(disable:4127)
 #endif
 
-/*
- * Define WIN32 when build target is Win32 API
- */
-
-#if (defined(_WIN32) || defined(__WIN32__)) && !defined(WIN32)
-#define WIN32
-#endif
-
-#ifdef WIN32
+#ifdef _WIN32
 /*
  * Don't include unneeded stuff in Windows headers to avoid compiler
  * warnings and macro clashes.
@@ -73,6 +72,11 @@
 # endif
 #endif
 
+/* Compatibility */
+#if defined(ENABLE_IPV6)
+#  define USE_IPV6 1
+#endif
+
 /*
  * Include configuration script results or hand-crafted
  * configuration file for platforms which lack config tool.
@@ -87,7 +91,7 @@
 #ifdef _WIN32_WCE
 #  include "config-win32ce.h"
 #else
-#  ifdef WIN32
+#  ifdef _WIN32
 #    include "config-win32.h"
 #  endif
 #endif
@@ -219,6 +223,23 @@
 #  define CURL_DISABLE_RTSP
 #endif
 
+/*
+ * When HTTP is disabled, disable HTTP-only features
+ */
+
+#if defined(CURL_DISABLE_HTTP)
+#  define CURL_DISABLE_ALTSVC 1
+#  define CURL_DISABLE_COOKIES 1
+#  define CURL_DISABLE_BASIC_AUTH 1
+#  define CURL_DISABLE_BEARER_AUTH 1
+#  define CURL_DISABLE_AWS 1
+#  define CURL_DISABLE_DOH 1
+#  define CURL_DISABLE_FORM_API 1
+#  define CURL_DISABLE_HEADERS_API 1
+#  define CURL_DISABLE_HSTS 1
+#  define CURL_DISABLE_HTTP_AUTH 1
+#endif
+
 /* ================================================================ */
 /* No system header file shall be included in this file before this */
 /* point.                                                           */
@@ -244,12 +265,47 @@
  * Windows setup file includes some system headers.
  */
 
-#ifdef HAVE_WINDOWS_H
+#ifdef _WIN32
 #  include "setup-win32.h"
 #endif
 
 #include 
 
+/* Helper macro to expand and concatenate two macros.
+ * Direct macros concatenation does not work because macros
+ * are not expanded before direct concatenation.
+ */
+#define CURL_CONC_MACROS_(A,B) A ## B
+#define CURL_CONC_MACROS(A,B) CURL_CONC_MACROS_(A,B)
+
+/* curl uses its own printf() function internally. It understands the GNU
+ * format. Use this format, so that is matches the GNU format attribute we
+ * use with the mingw compiler, allowing it to verify them at compile-time.
+ */
+#ifdef  __MINGW32__
+#  undef CURL_FORMAT_CURL_OFF_T
+#  undef CURL_FORMAT_CURL_OFF_TU
+#  define CURL_FORMAT_CURL_OFF_T   "lld"
+#  define CURL_FORMAT_CURL_OFF_TU  "llu"
+#endif
+
+/* based on logic in "curl/mprintf.h" */
+
+#if (defined(__GNUC__) || defined(__clang__) ||                         \
+  defined(__IAR_SYSTEMS_ICC__)) &&                                      \
+  defined(__STDC_VERSION__) && (__STDC_VERSION__ >= 199901L) &&         \
+  !defined(CURL_NO_FMT_CHECKS)
+#if defined(__MINGW32__) && !defined(__clang__)
+#define CURL_PRINTF(fmt, arg) \
+  __attribute__((format(gnu_printf, fmt, arg)))
+#else
+#define CURL_PRINTF(fmt, arg) \
+  __attribute__((format(__printf__, fmt, arg)))
+#endif
+#else
+#define CURL_PRINTF(fmt, arg)
+#endif
+
 /*
  * Use getaddrinfo to resolve the IPv4 address literal. If the current network
  * interface doesn't support IPv4, but supports IPv6, NAT64, and DNS64,
@@ -259,7 +315,7 @@
 #include 
 #define USE_RESOLVE_ON_IPS 1
 #  if TARGET_OS_MAC && !(defined(TARGET_OS_IPHONE) && TARGET_OS_IPHONE) && \
-     defined(ENABLE_IPV6)
+     defined(USE_IPV6)
 #    define CURL_MACOS_CALL_COPYPROXIES 1
 #  endif
 #endif
@@ -336,23 +392,6 @@
 #include 
 #endif
 
-#ifdef __POCC__
-#  include 
-#  include 
-#  define sys_nerr EILSEQ
-#endif
-
-/*
- * Salford-C kludge section (mostly borrowed from wxWidgets).
- */
-#ifdef __SALFORDC__
-  #pragma suppress 353             /* Possible nested comments */
-  #pragma suppress 593             /* Define not used */
-  #pragma suppress 61              /* enum has no name */
-  #pragma suppress 106             /* unnamed, unused parameter */
-  #include 
-#endif
-
 /*
  * Large file (>2Gb) support using WIN32 functions.
  */
@@ -371,11 +410,9 @@
 #  define LSEEK_ERROR                (__int64)-1
 #  define open                       curlx_win32_open
 #  define fopen(fname,mode)          curlx_win32_fopen(fname, mode)
-#  define access(fname,mode)         curlx_win32_access(fname, mode)
    int curlx_win32_open(const char *filename, int oflag, ...);
    int curlx_win32_stat(const char *path, struct_stat *buffer);
    FILE *curlx_win32_fopen(const char *filename, const char *mode);
-   int curlx_win32_access(const char *path, int mode);
 #endif
 
 /*
@@ -394,11 +431,9 @@
 #    define struct_stat                struct _stat
 #    define open                       curlx_win32_open
 #    define fopen(fname,mode)          curlx_win32_fopen(fname, mode)
-#    define access(fname,mode)         curlx_win32_access(fname, mode)
      int curlx_win32_stat(const char *path, struct_stat *buffer);
      int curlx_win32_open(const char *filename, int oflag, ...);
      FILE *curlx_win32_fopen(const char *filename, const char *mode);
-     int curlx_win32_access(const char *path, int mode);
 #  endif
 #  define LSEEK_ERROR                (long)-1
 #endif
@@ -416,6 +451,24 @@
 #define SIZEOF_TIME_T 4
 #endif
 
+#ifndef SIZEOF_CURL_SOCKET_T
+/* configure and cmake check and set the define */
+#  ifdef _WIN64
+#    define SIZEOF_CURL_SOCKET_T 8
+#  else
+/* default guess */
+#    define SIZEOF_CURL_SOCKET_T 4
+#  endif
+#endif
+
+#if SIZEOF_CURL_SOCKET_T < 8
+#  define CURL_FORMAT_SOCKET_T "d"
+#elif defined(__MINGW32__)
+#  define CURL_FORMAT_SOCKET_T "zd"
+#else
+#  define CURL_FORMAT_SOCKET_T "qd"
+#endif
+
 /*
  * Default sizeof(off_t) in case it hasn't been defined in config file.
  */
@@ -451,6 +504,20 @@
 #endif
 #define CURL_OFF_T_MIN (-CURL_OFF_T_MAX - CURL_OFF_T_C(1))
 
+#if (SIZEOF_CURL_OFF_T != 8)
+#  error "curl_off_t must be exactly 64 bits"
+#else
+  typedef unsigned CURL_TYPEOF_CURL_OFF_T curl_uint64_t;
+  typedef CURL_TYPEOF_CURL_OFF_T  curl_int64_t;
+#  ifndef CURL_SUFFIX_CURL_OFF_TU
+#    error "CURL_SUFFIX_CURL_OFF_TU must be defined"
+#  endif
+#  define CURL_UINT64_SUFFIX  CURL_SUFFIX_CURL_OFF_TU
+#  define CURL_UINT64_C(val)  CURL_CONC_MACROS(val,CURL_UINT64_SUFFIX)
+# define CURL_PRId64  CURL_FORMAT_CURL_OFF_T
+# define CURL_PRIu64  CURL_FORMAT_CURL_OFF_TU
+#endif
+
 #if (SIZEOF_TIME_T == 4)
 #  ifdef HAVE_TIME_T_UNSIGNED
 #  define TIME_T_MAX UINT_MAX
@@ -505,11 +572,11 @@
    5. set dir/file naming defines
    */
 
-#ifdef WIN32
+#ifdef _WIN32
 
 #  define DIR_CHAR      "\\"
 
-#else /* WIN32 */
+#else /* _WIN32 */
 
 #  ifdef MSDOS  /* Watt-32 */
 
@@ -534,48 +601,19 @@
 
 #  define DIR_CHAR      "/"
 
-#  ifndef fileno /* sunos 4 have this as a macro! */
-     int fileno(FILE *stream);
-#  endif
-
-#endif /* WIN32 */
-
-/*
- * msvc 6.0 requires PSDK in order to have INET6_ADDRSTRLEN
- * defined in ws2tcpip.h as well as to provide IPv6 support.
- * Does not apply if lwIP is used.
- */
-
-#if defined(_MSC_VER) && !defined(__POCC__) && !defined(USE_LWIPSOCK)
-#  if !defined(HAVE_WS2TCPIP_H) || \
-     ((_MSC_VER < 1300) && !defined(INET6_ADDRSTRLEN))
-#    undef HAVE_GETADDRINFO_THREADSAFE
-#    undef HAVE_FREEADDRINFO
-#    undef HAVE_GETADDRINFO
-#    undef ENABLE_IPV6
-#  endif
-#endif
+#endif /* _WIN32 */
 
 /* ---------------------------------------------------------------- */
 /*             resolver specialty compile-time defines              */
 /*         CURLRES_* defines to use in the host*.c sources          */
 /* ---------------------------------------------------------------- */
 
-/*
- * lcc-win32 doesn't have _beginthreadex(), lacks threads support.
- */
-
-#if defined(__LCC__) && defined(WIN32)
-#  undef USE_THREADS_POSIX
-#  undef USE_THREADS_WIN32
-#endif
-
 /*
  * MSVC threads support requires a multi-threaded runtime library.
  * _beginthreadex() is not available in single-threaded ones.
  */
 
-#if defined(_MSC_VER) && !defined(__POCC__) && !defined(_MT)
+#if defined(_MSC_VER) && !defined(_MT)
 #  undef USE_THREADS_POSIX
 #  undef USE_THREADS_WIN32
 #endif
@@ -584,8 +622,11 @@
  * Mutually exclusive CURLRES_* definitions.
  */
 
-#if defined(ENABLE_IPV6) && defined(HAVE_GETADDRINFO)
+#if defined(USE_IPV6) && defined(HAVE_GETADDRINFO)
 #  define CURLRES_IPV6
+#elif defined(USE_IPV6) && (defined(_WIN32) || defined(__CYGWIN__))
+/* assume on Windows that IPv6 without getaddrinfo is a broken build */
+#  error "Unexpected build: IPv6 is enabled but getaddrinfo was not found."
 #else
 #  define CURLRES_IPV4
 #endif
@@ -605,42 +646,14 @@
 
 /* ---------------------------------------------------------------- */
 
-/*
- * msvc 6.0 does not have struct sockaddr_storage and
- * does not define IPPROTO_ESP in winsock2.h. But both
- * are available if PSDK is properly installed.
- */
-
-#if defined(_MSC_VER) && !defined(__POCC__)
-#  if !defined(HAVE_WINSOCK2_H) || ((_MSC_VER < 1300) && !defined(IPPROTO_ESP))
-#    undef HAVE_STRUCT_SOCKADDR_STORAGE
-#  endif
-#endif
-
-/*
- * Intentionally fail to build when using msvc 6.0 without PSDK installed.
- * The brave of heart can circumvent this, defining ALLOW_MSVC6_WITHOUT_PSDK
- * in lib/config-win32.h although absolutely discouraged and unsupported.
- */
-
-#if defined(_MSC_VER) && !defined(__POCC__)
-#  if !defined(HAVE_WINDOWS_H) || ((_MSC_VER < 1300) && !defined(_FILETIME_))
-#    if !defined(ALLOW_MSVC6_WITHOUT_PSDK)
-#      error MSVC 6.0 requires "February 2003 Platform SDK" a.k.a. \
-             "Windows Server 2003 PSDK"
-#    else
-#      define CURL_DISABLE_LDAP 1
-#    endif
-#  endif
-#endif
-
-#if defined(HAVE_LIBIDN2) && defined(HAVE_IDN2_H) && !defined(USE_WIN32_IDN)
+#if defined(HAVE_LIBIDN2) && defined(HAVE_IDN2_H) && \
+  !defined(USE_WIN32_IDN) && !defined(USE_APPLE_IDN)
 /* The lib and header are present */
 #define USE_LIBIDN2
 #endif
 
-#if defined(USE_LIBIDN2) && defined(USE_WIN32_IDN)
-#error "Both libidn2 and WinIDN are enabled, choose one."
+#if defined(USE_LIBIDN2) && (defined(USE_WIN32_IDN) || defined(USE_APPLE_IDN))
+#error "libidn2 cannot be enabled with WinIDN or AppleIDN, choose one."
 #endif
 
 #define LIBIDN_REQUIRED_VERSION "0.4.1"
@@ -694,11 +707,42 @@
   ((__GNUC__ == 2) && defined(__GNUC_MINOR__) && (__GNUC_MINOR__ >= 7)))
 #  define UNUSED_PARAM __attribute__((__unused__))
 #  define WARN_UNUSED_RESULT __attribute__((warn_unused_result))
+#elif defined(__IAR_SYSTEMS_ICC__)
+#  define UNUSED_PARAM __attribute__((__unused__))
+#  if (__VER__ >= 9040001)
+#    define WARN_UNUSED_RESULT __attribute__((warn_unused_result))
+#  else
+#    define WARN_UNUSED_RESULT
+#  endif
 #else
 #  define UNUSED_PARAM /* NOTHING */
 #  define WARN_UNUSED_RESULT
 #endif
 
+/* noreturn attribute */
+
+#if !defined(CURL_NORETURN)
+#if (defined(__GNUC__) && (__GNUC__ >= 3)) || defined(__clang__) || \
+  defined(__IAR_SYSTEMS_ICC__)
+#  define CURL_NORETURN  __attribute__((__noreturn__))
+#elif defined(_MSC_VER) && (_MSC_VER >= 1200)
+#  define CURL_NORETURN  __declspec(noreturn)
+#else
+#  define CURL_NORETURN
+#endif
+#endif
+
+/* fallthrough attribute */
+
+#if !defined(FALLTHROUGH)
+#if (defined(__GNUC__) && __GNUC__ >= 7) || \
+    (defined(__clang__) && __clang_major__ >= 10)
+#  define FALLTHROUGH()  __attribute__((fallthrough))
+#else
+#  define FALLTHROUGH()  do {} while (0)
+#endif
+#endif
+
 /*
  * Include macros and defines that should only be processed once.
  */
@@ -720,10 +764,7 @@
  */
 
 #if defined(__LWIP_OPT_H__) || defined(LWIP_HDR_OPT_H)
-#  if defined(SOCKET) || \
-     defined(USE_WINSOCK) || \
-     defined(HAVE_WINSOCK2_H) || \
-     defined(HAVE_WS2TCPIP_H)
+#  if defined(SOCKET) || defined(USE_WINSOCK)
 #    error "WinSock and lwIP TCP/IP stack definitions shall not coexist!"
 #  endif
 #endif
@@ -757,7 +798,7 @@
 /* In Windows the default file mode is text but an application can override it.
 Therefore we specify it explicitly. https://github.com/curl/curl/pull/258
 */
-#if defined(WIN32) || defined(MSDOS)
+#if defined(_WIN32) || defined(MSDOS)
 #define FOPEN_READTEXT "rt"
 #define FOPEN_WRITETEXT "wt"
 #define FOPEN_APPENDTEXT "at"
@@ -812,27 +853,30 @@ int getpwuid_r(uid_t uid, struct passwd *pwd, char *buf,
 #define UNITTEST static
 #endif
 
-#if defined(USE_NGHTTP2) || defined(USE_HYPER)
+/* Hyper supports HTTP2 also, but Curl's integration with Hyper does not */
+#if defined(USE_NGHTTP2)
 #define USE_HTTP2
 #endif
 
 #if (defined(USE_NGTCP2) && defined(USE_NGHTTP3)) || \
+    (defined(USE_OPENSSL_QUIC) && defined(USE_NGHTTP3)) || \
     defined(USE_QUICHE) || defined(USE_MSH3)
-#define ENABLE_QUIC
+
+#ifdef CURL_WITH_MULTI_SSL
+#error "Multi-SSL combined with QUIC is not supported"
+#endif
+
 #define USE_HTTP3
 #endif
 
 /* Certain Windows implementations are not aligned with what curl expects,
    so always use the local one on this platform. E.g. the mingw-w64
    implementation can return wrong results for non-ASCII inputs. */
-#if defined(HAVE_BASENAME) && defined(WIN32)
+#if defined(HAVE_BASENAME) && defined(_WIN32)
 #undef HAVE_BASENAME
 #endif
 
-#if defined(USE_UNIX_SOCKETS) && defined(WIN32)
-#  if defined(__MINGW32__) && !defined(LUP_SECURE)
-     typedef u_short ADDRESS_FAMILY; /* Classic mingw, 11y+ old mingw-w64 */
-#  endif
+#if defined(USE_UNIX_SOCKETS) && defined(_WIN32)
 #  if !defined(UNIX_PATH_MAX)
      /* Replicating logic present in afunix.h
         (distributed with newer Windows 10 SDK versions only) */
@@ -852,4 +896,26 @@ int getpwuid_r(uid_t uid, struct passwd *pwd, char *buf,
 #define OPENSSL_SUPPRESS_DEPRECATED
 #endif
 
+#if defined(inline)
+  /* 'inline' is defined as macro and assumed to be correct */
+  /* No need for 'inline' replacement */
+#elif defined(__cplusplus)
+  /* The code is compiled with C++ compiler.
+     C++ always supports 'inline'. */
+  /* No need for 'inline' replacement */
+#elif defined(__STDC_VERSION__) && __STDC_VERSION__ >= 199901
+  /* C99 (and later) supports 'inline' keyword */
+  /* No need for 'inline' replacement */
+#elif defined(__GNUC__) && __GNUC__ >= 3
+  /* GCC supports '__inline__' as an extension */
+#  define inline __inline__
+#elif defined(_MSC_VER) && _MSC_VER >= 1400
+  /* MSC supports '__inline' from VS 2005 (or even earlier) */
+#  define inline __inline
+#else
+  /* Probably 'inline' is not supported by compiler.
+     Define to the empty string to be on the safe side. */
+#  define inline /* empty */
+#endif
+
 #endif /* HEADER_CURL_SETUP_H */
diff --git a/vendor/curl/lib/curl_setup_once.h b/vendor/curl/lib/curl_setup_once.h
index c1ed059070..40c7bcbff0 100644
--- a/vendor/curl/lib/curl_setup_once.h
+++ b/vendor/curl/lib/curl_setup_once.h
@@ -56,7 +56,7 @@
 #include 
 #endif
 
-#ifdef WIN32
+#ifdef _WIN32
 #include 
 #include 
 #endif
@@ -70,11 +70,7 @@
 #endif
 
 #ifdef USE_WOLFSSL
-#  if defined(HAVE_STDINT_H)
-#    include 
-#  elif defined(HAVE_INTTYPES_H)
-#    include 
-#  endif
+#include 
 #endif
 
 #ifdef USE_SCHANNEL
@@ -168,9 +164,7 @@ struct timeval {
                                    (RECV_TYPE_ARG4)(0))
 #else /* HAVE_RECV */
 #ifndef sread
-  /* */
-  Error Missing_definition_of_macro_sread
-  /* */
+#error "Missing definition of macro sread!"
 #endif
 #endif /* HAVE_RECV */
 
@@ -188,9 +182,7 @@ struct timeval {
                                     (SEND_TYPE_ARG4)(SEND_4TH_ARG))
 #else /* HAVE_SEND */
 #ifndef swrite
-  /* */
-  Error Missing_definition_of_macro_swrite
-  /* */
+#error "Missing definition of macro swrite!"
 #endif
 #endif /* HAVE_SEND */
 
diff --git a/vendor/curl/lib/curl_sha512_256.c b/vendor/curl/lib/curl_sha512_256.c
new file mode 100644
index 0000000000..5f2e99517a
--- /dev/null
+++ b/vendor/curl/lib/curl_sha512_256.c
@@ -0,0 +1,850 @@
+/***************************************************************************
+ *                                  _   _ ____  _
+ *  Project                     ___| | | |  _ \| |
+ *                             / __| | | | |_) | |
+ *                            | (__| |_| |  _ <| |___
+ *                             \___|\___/|_| \_\_____|
+ *
+ * Copyright (C) Evgeny Grin (Karlson2k), .
+ *
+ * This software is licensed as described in the file COPYING, which
+ * you should have received as part of this distribution. The terms
+ * are also available at https://curl.se/docs/copyright.html.
+ *
+ * You may opt to use, copy, modify, merge, publish, distribute and/or sell
+ * copies of the Software, and permit persons to whom the Software is
+ * furnished to do so, under the terms of the COPYING file.
+ *
+ * This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY
+ * KIND, either express or implied.
+ *
+ * SPDX-License-Identifier: curl
+ *
+ ***************************************************************************/
+
+#include "curl_setup.h"
+
+#if !defined(CURL_DISABLE_DIGEST_AUTH) && !defined(CURL_DISABLE_SHA512_256)
+
+#include "curl_sha512_256.h"
+#include "warnless.h"
+
+/* The recommended order of the TLS backends:
+ * * OpenSSL
+ * * GnuTLS
+ * * wolfSSL
+ * * Schannel SSPI
+ * * SecureTransport (Darwin)
+ * * mbedTLS
+ * * BearSSL
+ * * rustls
+ * Skip the backend if it does not support the required algorithm */
+
+#if defined(USE_OPENSSL)
+#  include 
+#  if (!defined(LIBRESSL_VERSION_NUMBER) && \
+        defined(OPENSSL_VERSION_NUMBER) && \
+        (OPENSSL_VERSION_NUMBER >= 0x10101000L)) || \
+      (defined(LIBRESSL_VERSION_NUMBER) && \
+        (LIBRESSL_VERSION_NUMBER >= 0x3080000fL))
+#    include 
+#    if !defined(OPENSSL_NO_SHA) && !defined(OPENSSL_NO_SHA512)
+#      include 
+#      define USE_OPENSSL_SHA512_256          1
+#      define HAS_SHA512_256_IMPLEMENTATION   1
+#      ifdef __NetBSD__
+/* Some NetBSD versions has a bug in SHA-512/256.
+ * See https://gnats.netbsd.org/cgi-bin/query-pr-single.pl?number=58039
+ * The problematic versions:
+ * - NetBSD before 9.4
+ * - NetBSD 9 all development versions (9.99.x)
+ * - NetBSD 10 development versions (10.99.x) before 10.99.11
+ * The bug was fixed in NetBSD 9.4 release, NetBSD 10.0 release,
+ * NetBSD 10.99.11 development.
+ * It is safe to apply the workaround even if the bug is not present, as
+ * the workaround just reduces performance slightly. */
+#        include 
+#        if  __NetBSD_Version__ <   904000000 ||  \
+            (__NetBSD_Version__ >=  999000000 &&  \
+             __NetBSD_Version__ <  1000000000) || \
+            (__NetBSD_Version__ >= 1099000000 &&  \
+             __NetBSD_Version__ <  1099001100)
+#          define NEED_NETBSD_SHA512_256_WORKAROUND 1
+#          include 
+#        endif
+#      endif
+#    endif
+#  endif
+#endif /* USE_OPENSSL */
+
+
+#if !defined(HAS_SHA512_256_IMPLEMENTATION) && defined(USE_GNUTLS)
+#  include 
+#  if defined(SHA512_256_DIGEST_SIZE)
+#    define USE_GNUTLS_SHA512_256           1
+#    define HAS_SHA512_256_IMPLEMENTATION   1
+#  endif
+#endif /* ! HAS_SHA512_256_IMPLEMENTATION && USE_GNUTLS */
+
+#if defined(USE_OPENSSL_SHA512_256)
+
+/* OpenSSL does not provide macros for SHA-512/256 sizes */
+
+/**
+ * Size of the SHA-512/256 single processing block in bytes.
+ */
+#define SHA512_256_BLOCK_SIZE 128
+
+/**
+ * Size of the SHA-512/256 resulting digest in bytes.
+ * This is the final digest size, not intermediate hash.
+ */
+#define SHA512_256_DIGEST_SIZE SHA512_256_DIGEST_LENGTH
+
+/**
+ * Context type used for SHA-512/256 calculations
+ */
+typedef EVP_MD_CTX *Curl_sha512_256_ctx;
+
+/**
+ * Initialise structure for SHA-512/256 calculation.
+ *
+ * @param context the calculation context
+ * @return CURLE_OK if succeed,
+ *         error code otherwise
+ */
+static CURLcode
+Curl_sha512_256_init(void *context)
+{
+  Curl_sha512_256_ctx *const ctx = (Curl_sha512_256_ctx *)context;
+
+  *ctx = EVP_MD_CTX_create();
+  if(!*ctx)
+    return CURLE_OUT_OF_MEMORY;
+
+  if(EVP_DigestInit_ex(*ctx, EVP_sha512_256(), NULL)) {
+    /* Check whether the header and this file use the same numbers */
+    DEBUGASSERT(EVP_MD_CTX_size(*ctx) == SHA512_256_DIGEST_SIZE);
+    /* Check whether the block size is correct */
+    DEBUGASSERT(EVP_MD_CTX_block_size(*ctx) == SHA512_256_BLOCK_SIZE);
+
+    return CURLE_OK; /* Success */
+  }
+
+  /* Cleanup */
+  EVP_MD_CTX_destroy(*ctx);
+  return CURLE_FAILED_INIT;
+}
+
+
+/**
+ * Process portion of bytes.
+ *
+ * @param context the calculation context
+ * @param data bytes to add to hash
+ * @return CURLE_OK if succeed,
+ *         error code otherwise
+ */
+static CURLcode
+Curl_sha512_256_update(void *context,
+                       const unsigned char *data,
+                       size_t length)
+{
+  Curl_sha512_256_ctx *const ctx = (Curl_sha512_256_ctx *)context;
+
+  if(!EVP_DigestUpdate(*ctx, data, length))
+    return CURLE_SSL_CIPHER;
+
+  return CURLE_OK;
+}
+
+
+/**
+ * Finalise SHA-512/256 calculation, return digest.
+ *
+ * @param context the calculation context
+ * @param[out] digest set to the hash, must be #SHA512_256_DIGEST_SIZE bytes
+ * @return CURLE_OK if succeed,
+ *         error code otherwise
+ */
+static CURLcode
+Curl_sha512_256_finish(unsigned char *digest,
+                       void *context)
+{
+  CURLcode ret;
+  Curl_sha512_256_ctx *const ctx = (Curl_sha512_256_ctx *)context;
+
+#ifdef NEED_NETBSD_SHA512_256_WORKAROUND
+  /* Use a larger buffer to work around a bug in NetBSD:
+     https://gnats.netbsd.org/cgi-bin/query-pr-single.pl?number=58039 */
+  unsigned char tmp_digest[SHA512_256_DIGEST_SIZE * 2];
+  ret = EVP_DigestFinal_ex(*ctx,
+                           tmp_digest, NULL) ? CURLE_OK : CURLE_SSL_CIPHER;
+  if(ret == CURLE_OK)
+    memcpy(digest, tmp_digest, SHA512_256_DIGEST_SIZE);
+  explicit_memset(tmp_digest, 0, sizeof(tmp_digest));
+#else  /* ! NEED_NETBSD_SHA512_256_WORKAROUND */
+  ret = EVP_DigestFinal_ex(*ctx, digest, NULL) ? CURLE_OK : CURLE_SSL_CIPHER;
+#endif /* ! NEED_NETBSD_SHA512_256_WORKAROUND */
+
+  EVP_MD_CTX_destroy(*ctx);
+  *ctx = NULL;
+
+  return ret;
+}
+
+#elif defined(USE_GNUTLS_SHA512_256)
+
+/**
+ * Context type used for SHA-512/256 calculations
+ */
+typedef struct sha512_256_ctx Curl_sha512_256_ctx;
+
+/**
+ * Initialise structure for SHA-512/256 calculation.
+ *
+ * @param context the calculation context
+ * @return always CURLE_OK
+ */
+static CURLcode
+Curl_sha512_256_init(void *context)
+{
+  Curl_sha512_256_ctx *const ctx = (Curl_sha512_256_ctx *)context;
+
+  /* Check whether the header and this file use the same numbers */
+  DEBUGASSERT(SHA512_256_DIGEST_LENGTH == SHA512_256_DIGEST_SIZE);
+
+  sha512_256_init(ctx);
+
+  return CURLE_OK;
+}
+
+
+/**
+ * Process portion of bytes.
+ *
+ * @param context the calculation context
+ * @param data bytes to add to hash
+ * @param length number of bytes in @a data
+ * @return always CURLE_OK
+ */
+static CURLcode
+Curl_sha512_256_update(void *context,
+                       const unsigned char *data,
+                       size_t length)
+{
+  Curl_sha512_256_ctx *const ctx = (Curl_sha512_256_ctx *)context;
+
+  DEBUGASSERT((data != NULL) || (length == 0));
+
+  sha512_256_update(ctx, length, (const uint8_t *)data);
+
+  return CURLE_OK;
+}
+
+
+/**
+ * Finalise SHA-512/256 calculation, return digest.
+ *
+ * @param context the calculation context
+ * @param[out] digest set to the hash, must be #SHA512_256_DIGEST_SIZE bytes
+ * @return always CURLE_OK
+ */
+static CURLcode
+Curl_sha512_256_finish(unsigned char *digest,
+                       void *context)
+{
+  Curl_sha512_256_ctx *const ctx = (Curl_sha512_256_ctx *)context;
+
+  sha512_256_digest(ctx, (size_t)SHA512_256_DIGEST_SIZE, (uint8_t *)digest);
+
+  return CURLE_OK;
+}
+
+#else /* No system or TLS backend SHA-512/256 implementation available */
+
+/* Use local implementation */
+#define HAS_SHA512_256_IMPLEMENTATION   1
+
+/* ** This implementation of SHA-512/256 hash calculation was originally ** *
+ * ** written by Evgeny Grin (Karlson2k) for GNU libmicrohttpd.          ** *
+ * ** The author ported the code to libcurl. The ported code is provided ** *
+ * ** under curl license.                                                ** *
+ * ** This is a minimal version with minimal optimisations. Performance  ** *
+ * ** can be significantly improved. Big-endian store and load macros    ** *
+ * ** are obvious targets for optimisation.                              ** */
+
+#ifdef __GNUC__
+#  if defined(__has_attribute) && defined(__STDC_VERSION__)
+#    if __has_attribute(always_inline) && __STDC_VERSION__ >= 199901
+#      define MHDX_INLINE inline __attribute__((always_inline))
+#    endif
+#  endif
+#endif
+
+#if !defined(MHDX_INLINE) && \
+  defined(_MSC_VER) && !defined(__GNUC__) && !defined(__clang__)
+#  if _MSC_VER >= 1400
+#    define MHDX_INLINE __forceinline
+#  endif
+#endif
+
+#if !defined(MHDX_INLINE)
+   /* Assume that 'inline' keyword works or the
+    * macro was already defined correctly. */
+#  define MHDX_INLINE inline
+#endif
+
+/* Bits manipulation macros and functions.
+   Can be moved to other headers to reuse. */
+
+#define MHDX_GET_64BIT_BE(ptr)                                  \
+  ( ((curl_uint64_t)(((const unsigned char*)(ptr))[0]) << 56) | \
+    ((curl_uint64_t)(((const unsigned char*)(ptr))[1]) << 48) | \
+    ((curl_uint64_t)(((const unsigned char*)(ptr))[2]) << 40) | \
+    ((curl_uint64_t)(((const unsigned char*)(ptr))[3]) << 32) | \
+    ((curl_uint64_t)(((const unsigned char*)(ptr))[4]) << 24) | \
+    ((curl_uint64_t)(((const unsigned char*)(ptr))[5]) << 16) | \
+    ((curl_uint64_t)(((const unsigned char*)(ptr))[6]) << 8)  | \
+    (curl_uint64_t)(((const unsigned char*)(ptr))[7]) )
+
+#define MHDX_PUT_64BIT_BE(ptr,val) do {                                 \
+    ((unsigned char*)(ptr))[7]=(unsigned char)((curl_uint64_t)(val));   \
+    ((unsigned char*)(ptr))[6]=(unsigned char)(((curl_uint64_t)(val)) >> 8); \
+    ((unsigned char*)(ptr))[5]=(unsigned char)(((curl_uint64_t)(val)) >> 16); \
+    ((unsigned char*)(ptr))[4]=(unsigned char)(((curl_uint64_t)(val)) >> 24); \
+    ((unsigned char*)(ptr))[3]=(unsigned char)(((curl_uint64_t)(val)) >> 32); \
+    ((unsigned char*)(ptr))[2]=(unsigned char)(((curl_uint64_t)(val)) >> 40); \
+    ((unsigned char*)(ptr))[1]=(unsigned char)(((curl_uint64_t)(val)) >> 48); \
+    ((unsigned char*)(ptr))[0]=(unsigned char)(((curl_uint64_t)(val)) >> 56); \
+  } while(0)
+
+/* Defined as a function. The macro version may duplicate the binary code
+ * size as each argument is used twice, so if any calculation is used
+ * as an argument, the calculation could be done twice. */
+static MHDX_INLINE curl_uint64_t
+MHDx_rotr64(curl_uint64_t value, unsigned int bits)
+{
+  bits %= 64;
+  if(0 == bits)
+    return value;
+  /* Defined in a form which modern compiler could optimise. */
+  return (value >> bits) | (value << (64 - bits));
+}
+
+/* SHA-512/256 specific data */
+
+/**
+ * Number of bits in a single SHA-512/256 word.
+ */
+#define SHA512_256_WORD_SIZE_BITS 64
+
+/**
+ * Number of bytes in a single SHA-512/256 word.
+ */
+#define SHA512_256_BYTES_IN_WORD (SHA512_256_WORD_SIZE_BITS / 8)
+
+/**
+ * Hash is kept internally as 8 64-bit words.
+ * This is the intermediate hash size, used during computing the final digest.
+ */
+#define SHA512_256_HASH_SIZE_WORDS 8
+
+/**
+ * Size of the SHA-512/256 resulting digest in words.
+ * This is the final digest size, not intermediate hash.
+ */
+#define SHA512_256_DIGEST_SIZE_WORDS (SHA512_256_HASH_SIZE_WORDS  / 2)
+
+/**
+ * Size of the SHA-512/256 resulting digest in bytes
+ * This is the final digest size, not intermediate hash.
+ */
+#define SHA512_256_DIGEST_SIZE \
+  (SHA512_256_DIGEST_SIZE_WORDS * SHA512_256_BYTES_IN_WORD)
+
+/**
+ * Size of the SHA-512/256 single processing block in bits.
+ */
+#define SHA512_256_BLOCK_SIZE_BITS 1024
+
+/**
+ * Size of the SHA-512/256 single processing block in bytes.
+ */
+#define SHA512_256_BLOCK_SIZE (SHA512_256_BLOCK_SIZE_BITS / 8)
+
+/**
+ * Size of the SHA-512/256 single processing block in words.
+ */
+#define SHA512_256_BLOCK_SIZE_WORDS \
+  (SHA512_256_BLOCK_SIZE_BITS / SHA512_256_WORD_SIZE_BITS)
+
+/**
+ * SHA-512/256 calculation context
+ */
+struct mhdx_sha512_256ctx
+{
+  /**
+   * Intermediate hash value. The variable is properly aligned. Smart
+   * compilers may automatically use fast load/store instruction for big
+   * endian data on little endian machine.
+   */
+  curl_uint64_t H[SHA512_256_HASH_SIZE_WORDS];
+  /**
+   * SHA-512/256 input data buffer. The buffer is properly aligned. Smart
+   * compilers may automatically use fast load/store instruction for big
+   * endian data on little endian machine.
+   */
+  curl_uint64_t buffer[SHA512_256_BLOCK_SIZE_WORDS];
+  /**
+   * The number of bytes, lower part
+   */
+  curl_uint64_t count;
+  /**
+   * The number of bits, high part. Unlike lower part, this counts the number
+   * of bits, not bytes.
+   */
+  curl_uint64_t count_bits_hi;
+};
+
+/**
+ * Context type used for SHA-512/256 calculations
+ */
+typedef struct mhdx_sha512_256ctx Curl_sha512_256_ctx;
+
+
+/**
+ * Initialise structure for SHA-512/256 calculation.
+ *
+ * @param context the calculation context
+ * @return always CURLE_OK
+ */
+static CURLcode
+MHDx_sha512_256_init(void *context)
+{
+  struct mhdx_sha512_256ctx *const ctx = (struct mhdx_sha512_256ctx *) context;
+
+  /* Check whether the header and this file use the same numbers */
+  DEBUGASSERT(SHA512_256_DIGEST_LENGTH == SHA512_256_DIGEST_SIZE);
+
+  DEBUGASSERT(sizeof(curl_uint64_t) == 8);
+
+  /* Initial hash values, see FIPS PUB 180-4 section 5.3.6.2 */
+  /* Values generated by "IV Generation Function" as described in
+   * section 5.3.6 */
+  ctx->H[0] = CURL_UINT64_C(0x22312194FC2BF72C);
+  ctx->H[1] = CURL_UINT64_C(0x9F555FA3C84C64C2);
+  ctx->H[2] = CURL_UINT64_C(0x2393B86B6F53B151);
+  ctx->H[3] = CURL_UINT64_C(0x963877195940EABD);
+  ctx->H[4] = CURL_UINT64_C(0x96283EE2A88EFFE3);
+  ctx->H[5] = CURL_UINT64_C(0xBE5E1E2553863992);
+  ctx->H[6] = CURL_UINT64_C(0x2B0199FC2C85B8AA);
+  ctx->H[7] = CURL_UINT64_C(0x0EB72DDC81C52CA2);
+
+  /* Initialise number of bytes and high part of number of bits. */
+  ctx->count = CURL_UINT64_C(0);
+  ctx->count_bits_hi = CURL_UINT64_C(0);
+
+  return CURLE_OK;
+}
+
+
+/**
+ * Base of the SHA-512/256 transformation.
+ * Gets a full 128 bytes block of data and updates hash values;
+ * @param H     hash values
+ * @param data  the data buffer with #SHA512_256_BLOCK_SIZE bytes block
+ */
+static void
+MHDx_sha512_256_transform(curl_uint64_t H[SHA512_256_HASH_SIZE_WORDS],
+                          const void *data)
+{
+  /* Working variables,
+     see FIPS PUB 180-4 section 6.7, 6.4. */
+  curl_uint64_t a = H[0];
+  curl_uint64_t b = H[1];
+  curl_uint64_t c = H[2];
+  curl_uint64_t d = H[3];
+  curl_uint64_t e = H[4];
+  curl_uint64_t f = H[5];
+  curl_uint64_t g = H[6];
+  curl_uint64_t h = H[7];
+
+  /* Data buffer, used as a cyclic buffer.
+     See FIPS PUB 180-4 section 5.2.2, 6.7, 6.4. */
+  curl_uint64_t W[16];
+
+  /* 'Ch' and 'Maj' macro functions are defined with widely-used optimisation.
+     See FIPS PUB 180-4 formulae 4.8, 4.9. */
+#define Ch(x,y,z)     ( (z) ^ ((x) & ((y) ^ (z))) )
+#define Maj(x,y,z)    ( ((x) & (y)) ^ ((z) & ((x) ^ (y))) )
+
+  /* Four 'Sigma' macro functions.
+     See FIPS PUB 180-4 formulae 4.10, 4.11, 4.12, 4.13. */
+#define SIG0(x)                                                         \
+  ( MHDx_rotr64((x), 28) ^ MHDx_rotr64((x), 34) ^ MHDx_rotr64((x), 39) )
+#define SIG1(x)                                                         \
+  ( MHDx_rotr64((x), 14) ^ MHDx_rotr64((x), 18) ^ MHDx_rotr64((x), 41) )
+#define sig0(x)                                                 \
+  ( MHDx_rotr64((x), 1) ^ MHDx_rotr64((x), 8) ^ ((x) >> 7) )
+#define sig1(x)                                                 \
+  ( MHDx_rotr64((x), 19) ^ MHDx_rotr64((x), 61) ^ ((x) >> 6) )
+
+  if(1) {
+    unsigned int t;
+    /* K constants array.
+       See FIPS PUB 180-4 section 4.2.3 for K values. */
+    static const curl_uint64_t K[80] = {
+      CURL_UINT64_C(0x428a2f98d728ae22), CURL_UINT64_C(0x7137449123ef65cd),
+      CURL_UINT64_C(0xb5c0fbcfec4d3b2f), CURL_UINT64_C(0xe9b5dba58189dbbc),
+      CURL_UINT64_C(0x3956c25bf348b538), CURL_UINT64_C(0x59f111f1b605d019),
+      CURL_UINT64_C(0x923f82a4af194f9b), CURL_UINT64_C(0xab1c5ed5da6d8118),
+      CURL_UINT64_C(0xd807aa98a3030242), CURL_UINT64_C(0x12835b0145706fbe),
+      CURL_UINT64_C(0x243185be4ee4b28c), CURL_UINT64_C(0x550c7dc3d5ffb4e2),
+      CURL_UINT64_C(0x72be5d74f27b896f), CURL_UINT64_C(0x80deb1fe3b1696b1),
+      CURL_UINT64_C(0x9bdc06a725c71235), CURL_UINT64_C(0xc19bf174cf692694),
+      CURL_UINT64_C(0xe49b69c19ef14ad2), CURL_UINT64_C(0xefbe4786384f25e3),
+      CURL_UINT64_C(0x0fc19dc68b8cd5b5), CURL_UINT64_C(0x240ca1cc77ac9c65),
+      CURL_UINT64_C(0x2de92c6f592b0275), CURL_UINT64_C(0x4a7484aa6ea6e483),
+      CURL_UINT64_C(0x5cb0a9dcbd41fbd4), CURL_UINT64_C(0x76f988da831153b5),
+      CURL_UINT64_C(0x983e5152ee66dfab), CURL_UINT64_C(0xa831c66d2db43210),
+      CURL_UINT64_C(0xb00327c898fb213f), CURL_UINT64_C(0xbf597fc7beef0ee4),
+      CURL_UINT64_C(0xc6e00bf33da88fc2), CURL_UINT64_C(0xd5a79147930aa725),
+      CURL_UINT64_C(0x06ca6351e003826f), CURL_UINT64_C(0x142929670a0e6e70),
+      CURL_UINT64_C(0x27b70a8546d22ffc), CURL_UINT64_C(0x2e1b21385c26c926),
+      CURL_UINT64_C(0x4d2c6dfc5ac42aed), CURL_UINT64_C(0x53380d139d95b3df),
+      CURL_UINT64_C(0x650a73548baf63de), CURL_UINT64_C(0x766a0abb3c77b2a8),
+      CURL_UINT64_C(0x81c2c92e47edaee6), CURL_UINT64_C(0x92722c851482353b),
+      CURL_UINT64_C(0xa2bfe8a14cf10364), CURL_UINT64_C(0xa81a664bbc423001),
+      CURL_UINT64_C(0xc24b8b70d0f89791), CURL_UINT64_C(0xc76c51a30654be30),
+      CURL_UINT64_C(0xd192e819d6ef5218), CURL_UINT64_C(0xd69906245565a910),
+      CURL_UINT64_C(0xf40e35855771202a), CURL_UINT64_C(0x106aa07032bbd1b8),
+      CURL_UINT64_C(0x19a4c116b8d2d0c8), CURL_UINT64_C(0x1e376c085141ab53),
+      CURL_UINT64_C(0x2748774cdf8eeb99), CURL_UINT64_C(0x34b0bcb5e19b48a8),
+      CURL_UINT64_C(0x391c0cb3c5c95a63), CURL_UINT64_C(0x4ed8aa4ae3418acb),
+      CURL_UINT64_C(0x5b9cca4f7763e373), CURL_UINT64_C(0x682e6ff3d6b2b8a3),
+      CURL_UINT64_C(0x748f82ee5defb2fc), CURL_UINT64_C(0x78a5636f43172f60),
+      CURL_UINT64_C(0x84c87814a1f0ab72), CURL_UINT64_C(0x8cc702081a6439ec),
+      CURL_UINT64_C(0x90befffa23631e28), CURL_UINT64_C(0xa4506cebde82bde9),
+      CURL_UINT64_C(0xbef9a3f7b2c67915), CURL_UINT64_C(0xc67178f2e372532b),
+      CURL_UINT64_C(0xca273eceea26619c), CURL_UINT64_C(0xd186b8c721c0c207),
+      CURL_UINT64_C(0xeada7dd6cde0eb1e), CURL_UINT64_C(0xf57d4f7fee6ed178),
+      CURL_UINT64_C(0x06f067aa72176fba), CURL_UINT64_C(0x0a637dc5a2c898a6),
+      CURL_UINT64_C(0x113f9804bef90dae), CURL_UINT64_C(0x1b710b35131c471b),
+      CURL_UINT64_C(0x28db77f523047d84), CURL_UINT64_C(0x32caab7b40c72493),
+      CURL_UINT64_C(0x3c9ebe0a15c9bebc), CURL_UINT64_C(0x431d67c49c100d4c),
+      CURL_UINT64_C(0x4cc5d4becb3e42b6), CURL_UINT64_C(0x597f299cfc657e2a),
+      CURL_UINT64_C(0x5fcb6fab3ad6faec), CURL_UINT64_C(0x6c44198c4a475817)
+    };
+
+    /* One step of SHA-512/256 computation,
+       see FIPS PUB 180-4 section 6.4.2 step 3.
+       * Note: this macro updates working variables in-place, without rotation.
+       * Note: the first (vH += SIG1(vE) + Ch(vE,vF,vG) + kt + wt) equals T1 in
+       FIPS PUB 180-4 section 6.4.2 step 3.
+       the second (vH += SIG0(vA) + Maj(vE,vF,vC) equals T1 + T2 in
+       FIPS PUB 180-4 section 6.4.2 step 3.
+       * Note: 'wt' must be used exactly one time in this macro as macro for
+       'wt' calculation may change other data as well every time when
+       used. */
+#define SHA2STEP64(vA,vB,vC,vD,vE,vF,vG,vH,kt,wt) do {                  \
+      (vD) += ((vH) += SIG1 ((vE)) + Ch ((vE),(vF),(vG)) + (kt) + (wt)); \
+      (vH) += SIG0 ((vA)) + Maj ((vA),(vB),(vC)); } while (0)
+
+    /* One step of SHA-512/256 computation with working variables rotation,
+       see FIPS PUB 180-4 section 6.4.2 step 3. This macro version reassigns
+       all working variables on each step. */
+#define SHA2STEP64RV(vA,vB,vC,vD,vE,vF,vG,vH,kt,wt) do {                \
+      curl_uint64_t tmp_h_ = (vH);                                      \
+      SHA2STEP64((vA),(vB),(vC),(vD),(vE),(vF),(vG),tmp_h_,(kt),(wt));  \
+      (vH) = (vG);                                                      \
+      (vG) = (vF);                                                      \
+      (vF) = (vE);                                                      \
+      (vE) = (vD);                                                      \
+      (vD) = (vC);                                                      \
+      (vC) = (vB);                                                      \
+      (vB) = (vA);                                                      \
+      (vA) = tmp_h_;  } while(0)
+
+    /* Get value of W(t) from input data buffer for 0 <= t <= 15,
+       See FIPS PUB 180-4 section 6.2.
+       Input data must be read in big-endian bytes order,
+       see FIPS PUB 180-4 section 3.1.2. */
+#define SHA512_GET_W_FROM_DATA(buf,t)                                   \
+    MHDX_GET_64BIT_BE(                                                  \
+      ((const unsigned char*) (buf)) + (t) * SHA512_256_BYTES_IN_WORD)
+
+    /* During first 16 steps, before making any calculation on each step, the
+       W element is read from the input data buffer as a big-endian value and
+       stored in the array of W elements. */
+    for(t = 0; t < 16; ++t) {
+      SHA2STEP64RV(a, b, c, d, e, f, g, h, K[t], \
+                   W[t] = SHA512_GET_W_FROM_DATA(data, t));
+    }
+
+    /* 'W' generation and assignment for 16 <= t <= 79.
+       See FIPS PUB 180-4 section 6.4.2.
+       As only the last 16 'W' are used in calculations, it is possible to
+       use 16 elements array of W as a cyclic buffer.
+       Note: ((t-16) & 15) have same value as (t & 15) */
+#define Wgen(w,t)                                                       \
+    (curl_uint64_t)( (w)[(t - 16) & 15] + sig1((w)[((t) - 2) & 15])     \
+                     + (w)[((t) - 7) & 15] + sig0((w)[((t) - 15) & 15]) )
+
+    /* During the last 64 steps, before making any calculation on each step,
+       current W element is generated from other W elements of the cyclic
+       buffer and the generated value is stored back in the cyclic buffer. */
+    for(t = 16; t < 80; ++t) {
+      SHA2STEP64RV(a, b, c, d, e, f, g, h, K[t], \
+                   W[t & 15] = Wgen(W, t));
+    }
+  }
+
+  /* Compute and store the intermediate hash.
+     See FIPS PUB 180-4 section 6.4.2 step 4. */
+  H[0] += a;
+  H[1] += b;
+  H[2] += c;
+  H[3] += d;
+  H[4] += e;
+  H[5] += f;
+  H[6] += g;
+  H[7] += h;
+}
+
+
+/**
+ * Process portion of bytes.
+ *
+ * @param context the calculation context
+ * @param data bytes to add to hash
+ * @param length number of bytes in @a data
+ * @return always CURLE_OK
+ */
+static CURLcode
+MHDx_sha512_256_update(void *context,
+                       const unsigned char *data,
+                       size_t length)
+{
+  unsigned int bytes_have; /**< Number of bytes in the context buffer */
+  struct mhdx_sha512_256ctx *const ctx = (struct mhdx_sha512_256ctx *)context;
+  /* the void pointer here is required to mute Intel compiler warning */
+  void *const ctx_buf = ctx->buffer;
+
+  DEBUGASSERT((data != NULL) || (length == 0));
+
+  if(0 == length)
+    return CURLE_OK; /* Shortcut, do nothing */
+
+  /* Note: (count & (SHA512_256_BLOCK_SIZE-1))
+     equals (count % SHA512_256_BLOCK_SIZE) for this block size. */
+  bytes_have = (unsigned int) (ctx->count & (SHA512_256_BLOCK_SIZE - 1));
+  ctx->count += length;
+  if(length > ctx->count)
+    ctx->count_bits_hi += 1U << 3; /* Value wrap */
+  ctx->count_bits_hi += ctx->count >> 61;
+  ctx->count &= CURL_UINT64_C(0x1FFFFFFFFFFFFFFF);
+
+  if(0 != bytes_have) {
+    unsigned int bytes_left = SHA512_256_BLOCK_SIZE - bytes_have;
+    if(length >= bytes_left) {
+      /* Combine new data with data in the buffer and process the full
+         block. */
+      memcpy(((unsigned char *) ctx_buf) + bytes_have,
+             data,
+             bytes_left);
+      data += bytes_left;
+      length -= bytes_left;
+      MHDx_sha512_256_transform(ctx->H, ctx->buffer);
+      bytes_have = 0;
+    }
+  }
+
+  while(SHA512_256_BLOCK_SIZE <= length) {
+    /* Process any full blocks of new data directly,
+       without copying to the buffer. */
+    MHDx_sha512_256_transform(ctx->H, data);
+    data += SHA512_256_BLOCK_SIZE;
+    length -= SHA512_256_BLOCK_SIZE;
+  }
+
+  if(0 != length) {
+    /* Copy incomplete block of new data (if any)
+       to the buffer. */
+    memcpy(((unsigned char *) ctx_buf) + bytes_have, data, length);
+  }
+
+  return CURLE_OK;
+}
+
+
+
+/**
+ * Size of "length" insertion in bits.
+ * See FIPS PUB 180-4 section 5.1.2.
+ */
+#define SHA512_256_SIZE_OF_LEN_ADD_BITS 128
+
+/**
+ * Size of "length" insertion in bytes.
+ */
+#define SHA512_256_SIZE_OF_LEN_ADD (SHA512_256_SIZE_OF_LEN_ADD_BITS / 8)
+
+/**
+ * Finalise SHA-512/256 calculation, return digest.
+ *
+ * @param context the calculation context
+ * @param[out] digest set to the hash, must be #SHA512_256_DIGEST_SIZE bytes
+ * @return always CURLE_OK
+ */
+static CURLcode
+MHDx_sha512_256_finish(unsigned char *digest,
+                       void *context)
+{
+  struct mhdx_sha512_256ctx *const ctx = (struct mhdx_sha512_256ctx *)context;
+  curl_uint64_t num_bits;   /**< Number of processed bits */
+  unsigned int bytes_have; /**< Number of bytes in the context buffer */
+  /* the void pointer here is required to mute Intel compiler warning */
+  void *const ctx_buf = ctx->buffer;
+
+  /* Memorise the number of processed bits.
+     The padding and other data added here during the postprocessing must
+     not change the amount of hashed data. */
+  num_bits = ctx->count << 3;
+
+  /* Note: (count & (SHA512_256_BLOCK_SIZE-1))
+           equals (count % SHA512_256_BLOCK_SIZE) for this block size. */
+  bytes_have = (unsigned int) (ctx->count & (SHA512_256_BLOCK_SIZE - 1));
+
+  /* Input data must be padded with a single bit "1", then with zeros and
+     the finally the length of data in bits must be added as the final bytes
+     of the last block.
+     See FIPS PUB 180-4 section 5.1.2. */
+
+  /* Data is always processed in form of bytes (not by individual bits),
+     therefore position of the first padding bit in byte is always
+     predefined (0x80). */
+  /* Buffer always have space at least for one byte (as full buffers are
+     processed when formed). */
+  ((unsigned char *) ctx_buf)[bytes_have++] = 0x80U;
+
+  if(SHA512_256_BLOCK_SIZE - bytes_have < SHA512_256_SIZE_OF_LEN_ADD) {
+    /* No space in the current block to put the total length of message.
+       Pad the current block with zeros and process it. */
+    if(bytes_have < SHA512_256_BLOCK_SIZE)
+      memset(((unsigned char *) ctx_buf) + bytes_have, 0,
+             SHA512_256_BLOCK_SIZE - bytes_have);
+    /* Process the full block. */
+    MHDx_sha512_256_transform(ctx->H, ctx->buffer);
+    /* Start the new block. */
+    bytes_have = 0;
+  }
+
+  /* Pad the rest of the buffer with zeros. */
+  memset(((unsigned char *) ctx_buf) + bytes_have, 0,
+         SHA512_256_BLOCK_SIZE - SHA512_256_SIZE_OF_LEN_ADD - bytes_have);
+  /* Put high part of number of bits in processed message and then lower
+     part of number of bits as big-endian values.
+     See FIPS PUB 180-4 section 5.1.2. */
+  /* Note: the target location is predefined and buffer is always aligned */
+  MHDX_PUT_64BIT_BE(((unsigned char *) ctx_buf)  \
+                      + SHA512_256_BLOCK_SIZE         \
+                      - SHA512_256_SIZE_OF_LEN_ADD,   \
+                      ctx->count_bits_hi);
+  MHDX_PUT_64BIT_BE(((unsigned char *) ctx_buf)      \
+                      + SHA512_256_BLOCK_SIZE             \
+                      - SHA512_256_SIZE_OF_LEN_ADD        \
+                      + SHA512_256_BYTES_IN_WORD,         \
+                      num_bits);
+  /* Process the full final block. */
+  MHDx_sha512_256_transform(ctx->H, ctx->buffer);
+
+  /* Put in BE mode the leftmost part of the hash as the final digest.
+     See FIPS PUB 180-4 section 6.7. */
+
+  MHDX_PUT_64BIT_BE((digest + 0 * SHA512_256_BYTES_IN_WORD), ctx->H[0]);
+  MHDX_PUT_64BIT_BE((digest + 1 * SHA512_256_BYTES_IN_WORD), ctx->H[1]);
+  MHDX_PUT_64BIT_BE((digest + 2 * SHA512_256_BYTES_IN_WORD), ctx->H[2]);
+  MHDX_PUT_64BIT_BE((digest + 3 * SHA512_256_BYTES_IN_WORD), ctx->H[3]);
+
+  /* Erase potentially sensitive data. */
+  memset(ctx, 0, sizeof(struct mhdx_sha512_256ctx));
+
+  return CURLE_OK;
+}
+
+/* Map to the local implementation */
+#define Curl_sha512_256_init    MHDx_sha512_256_init
+#define Curl_sha512_256_update  MHDx_sha512_256_update
+#define Curl_sha512_256_finish  MHDx_sha512_256_finish
+
+#endif /* Local SHA-512/256 code */
+
+
+/**
+ * Compute SHA-512/256 hash for the given data in one function call
+ * @param[out] output the pointer to put the hash
+ * @param[in] input the pointer to the data to process
+ * @param input_size the size of the data pointed by @a input
+ * @return always #CURLE_OK
+ */
+CURLcode
+Curl_sha512_256it(unsigned char *output, const unsigned char *input,
+                  size_t input_size)
+{
+  Curl_sha512_256_ctx ctx;
+  CURLcode res;
+
+  res = Curl_sha512_256_init(&ctx);
+  if(res != CURLE_OK)
+    return res;
+
+  res = Curl_sha512_256_update(&ctx, (const void *) input, input_size);
+
+  if(res != CURLE_OK) {
+    (void) Curl_sha512_256_finish(output, &ctx);
+    return res;
+  }
+
+  return Curl_sha512_256_finish(output, &ctx);
+}
+
+/* Wrapper function, takes 'unsigned int' as length type, returns void */
+static void
+Curl_sha512_256_update_i(void *context,
+                         const unsigned char *data,
+                         unsigned int length)
+{
+  /* Hypothetically the function may fail, but assume it does not */
+  (void) Curl_sha512_256_update(context, data, length);
+}
+
+/* Wrapper function, returns void */
+static void
+Curl_sha512_256_finish_v(unsigned char *result,
+                         void *context)
+{
+  /* Hypothetically the function may fail, but assume it does not */
+  (void) Curl_sha512_256_finish(result, context);
+}
+
+/* Wrapper function, takes 'unsigned int' as length type, returns void */
+
+const struct HMAC_params Curl_HMAC_SHA512_256[] = {
+  {
+    /* Initialize context procedure. */
+    Curl_sha512_256_init,
+    /* Update context with data. */
+    Curl_sha512_256_update_i,
+    /* Get final result procedure. */
+    Curl_sha512_256_finish_v,
+    /* Context structure size. */
+    sizeof(Curl_sha512_256_ctx),
+    /* Maximum key length (bytes). */
+    SHA512_256_BLOCK_SIZE,
+    /* Result length (bytes). */
+    SHA512_256_DIGEST_SIZE
+  }
+};
+
+#endif /* !CURL_DISABLE_DIGEST_AUTH && !CURL_DISABLE_SHA512_256 */
diff --git a/vendor/curl/lib/curl_sha512_256.h b/vendor/curl/lib/curl_sha512_256.h
new file mode 100644
index 0000000000..30a9f140ea
--- /dev/null
+++ b/vendor/curl/lib/curl_sha512_256.h
@@ -0,0 +1,44 @@
+#ifndef HEADER_CURL_SHA512_256_H
+#define HEADER_CURL_SHA512_256_H
+/***************************************************************************
+ *                                  _   _ ____  _
+ *  Project                     ___| | | |  _ \| |
+ *                             / __| | | | |_) | |
+ *                            | (__| |_| |  _ <| |___
+ *                             \___|\___/|_| \_\_____|
+ *
+ * Copyright (C) Evgeny Grin (Karlson2k), .
+ *
+ * This software is licensed as described in the file COPYING, which
+ * you should have received as part of this distribution. The terms
+ * are also available at https://curl.se/docs/copyright.html.
+ *
+ * You may opt to use, copy, modify, merge, publish, distribute and/or sell
+ * copies of the Software, and permit persons to whom the Software is
+ * furnished to do so, under the terms of the COPYING file.
+ *
+ * This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY
+ * KIND, either express or implied.
+ *
+ * SPDX-License-Identifier: curl
+ *
+ ***************************************************************************/
+
+#if !defined(CURL_DISABLE_DIGEST_AUTH) && !defined(CURL_DISABLE_SHA512_256)
+
+#include 
+#include "curl_hmac.h"
+
+#define CURL_HAVE_SHA512_256
+
+extern const struct HMAC_params Curl_HMAC_SHA512_256[1];
+
+#define SHA512_256_DIGEST_LENGTH 32
+
+CURLcode
+Curl_sha512_256it(unsigned char *output, const unsigned char *input,
+                  size_t input_size);
+
+#endif /* !CURL_DISABLE_DIGEST_AUTH && !CURL_DISABLE_SHA512_256 */
+
+#endif /* HEADER_CURL_SHA256_H */
diff --git a/vendor/curl/lib/curl_sspi.h b/vendor/curl/lib/curl_sspi.h
index 9816d59c84..b26c391569 100644
--- a/vendor/curl/lib/curl_sspi.h
+++ b/vendor/curl/lib/curl_sspi.h
@@ -70,227 +70,6 @@ extern PSecurityFunctionTable s_pSecFn;
 #define ISC_REQ_USE_HTTP_STYLE                0x01000000
 #endif
 
-#ifndef ISC_RET_REPLAY_DETECT
-#define ISC_RET_REPLAY_DETECT                 0x00000004
-#endif
-
-#ifndef ISC_RET_SEQUENCE_DETECT
-#define ISC_RET_SEQUENCE_DETECT               0x00000008
-#endif
-
-#ifndef ISC_RET_CONFIDENTIALITY
-#define ISC_RET_CONFIDENTIALITY               0x00000010
-#endif
-
-#ifndef ISC_RET_ALLOCATED_MEMORY
-#define ISC_RET_ALLOCATED_MEMORY              0x00000100
-#endif
-
-#ifndef ISC_RET_STREAM
-#define ISC_RET_STREAM                        0x00008000
-#endif
-
-#ifndef SEC_E_INSUFFICIENT_MEMORY
-# define SEC_E_INSUFFICIENT_MEMORY            ((HRESULT)0x80090300L)
-#endif
-#ifndef SEC_E_INVALID_HANDLE
-# define SEC_E_INVALID_HANDLE                 ((HRESULT)0x80090301L)
-#endif
-#ifndef SEC_E_UNSUPPORTED_FUNCTION
-# define SEC_E_UNSUPPORTED_FUNCTION           ((HRESULT)0x80090302L)
-#endif
-#ifndef SEC_E_TARGET_UNKNOWN
-# define SEC_E_TARGET_UNKNOWN                 ((HRESULT)0x80090303L)
-#endif
-#ifndef SEC_E_INTERNAL_ERROR
-# define SEC_E_INTERNAL_ERROR                 ((HRESULT)0x80090304L)
-#endif
-#ifndef SEC_E_SECPKG_NOT_FOUND
-# define SEC_E_SECPKG_NOT_FOUND               ((HRESULT)0x80090305L)
-#endif
-#ifndef SEC_E_NOT_OWNER
-# define SEC_E_NOT_OWNER                      ((HRESULT)0x80090306L)
-#endif
-#ifndef SEC_E_CANNOT_INSTALL
-# define SEC_E_CANNOT_INSTALL                 ((HRESULT)0x80090307L)
-#endif
-#ifndef SEC_E_INVALID_TOKEN
-# define SEC_E_INVALID_TOKEN                  ((HRESULT)0x80090308L)
-#endif
-#ifndef SEC_E_CANNOT_PACK
-# define SEC_E_CANNOT_PACK                    ((HRESULT)0x80090309L)
-#endif
-#ifndef SEC_E_QOP_NOT_SUPPORTED
-# define SEC_E_QOP_NOT_SUPPORTED              ((HRESULT)0x8009030AL)
-#endif
-#ifndef SEC_E_NO_IMPERSONATION
-# define SEC_E_NO_IMPERSONATION               ((HRESULT)0x8009030BL)
-#endif
-#ifndef SEC_E_LOGON_DENIED
-# define SEC_E_LOGON_DENIED                   ((HRESULT)0x8009030CL)
-#endif
-#ifndef SEC_E_UNKNOWN_CREDENTIALS
-# define SEC_E_UNKNOWN_CREDENTIALS            ((HRESULT)0x8009030DL)
-#endif
-#ifndef SEC_E_NO_CREDENTIALS
-# define SEC_E_NO_CREDENTIALS                 ((HRESULT)0x8009030EL)
-#endif
-#ifndef SEC_E_MESSAGE_ALTERED
-# define SEC_E_MESSAGE_ALTERED                ((HRESULT)0x8009030FL)
-#endif
-#ifndef SEC_E_OUT_OF_SEQUENCE
-# define SEC_E_OUT_OF_SEQUENCE                ((HRESULT)0x80090310L)
-#endif
-#ifndef SEC_E_NO_AUTHENTICATING_AUTHORITY
-# define SEC_E_NO_AUTHENTICATING_AUTHORITY    ((HRESULT)0x80090311L)
-#endif
-#ifndef SEC_E_BAD_PKGID
-# define SEC_E_BAD_PKGID                      ((HRESULT)0x80090316L)
-#endif
-#ifndef SEC_E_CONTEXT_EXPIRED
-# define SEC_E_CONTEXT_EXPIRED                ((HRESULT)0x80090317L)
-#endif
-#ifndef SEC_E_INCOMPLETE_MESSAGE
-# define SEC_E_INCOMPLETE_MESSAGE             ((HRESULT)0x80090318L)
-#endif
-#ifndef SEC_E_INCOMPLETE_CREDENTIALS
-# define SEC_E_INCOMPLETE_CREDENTIALS         ((HRESULT)0x80090320L)
-#endif
-#ifndef SEC_E_BUFFER_TOO_SMALL
-# define SEC_E_BUFFER_TOO_SMALL               ((HRESULT)0x80090321L)
-#endif
-#ifndef SEC_E_WRONG_PRINCIPAL
-# define SEC_E_WRONG_PRINCIPAL                ((HRESULT)0x80090322L)
-#endif
-#ifndef SEC_E_TIME_SKEW
-# define SEC_E_TIME_SKEW                      ((HRESULT)0x80090324L)
-#endif
-#ifndef SEC_E_UNTRUSTED_ROOT
-# define SEC_E_UNTRUSTED_ROOT                 ((HRESULT)0x80090325L)
-#endif
-#ifndef SEC_E_ILLEGAL_MESSAGE
-# define SEC_E_ILLEGAL_MESSAGE                ((HRESULT)0x80090326L)
-#endif
-#ifndef SEC_E_CERT_UNKNOWN
-# define SEC_E_CERT_UNKNOWN                   ((HRESULT)0x80090327L)
-#endif
-#ifndef SEC_E_CERT_EXPIRED
-# define SEC_E_CERT_EXPIRED                   ((HRESULT)0x80090328L)
-#endif
-#ifndef SEC_E_ENCRYPT_FAILURE
-# define SEC_E_ENCRYPT_FAILURE                ((HRESULT)0x80090329L)
-#endif
-#ifndef SEC_E_DECRYPT_FAILURE
-# define SEC_E_DECRYPT_FAILURE                ((HRESULT)0x80090330L)
-#endif
-#ifndef SEC_E_ALGORITHM_MISMATCH
-# define SEC_E_ALGORITHM_MISMATCH             ((HRESULT)0x80090331L)
-#endif
-#ifndef SEC_E_SECURITY_QOS_FAILED
-# define SEC_E_SECURITY_QOS_FAILED            ((HRESULT)0x80090332L)
-#endif
-#ifndef SEC_E_UNFINISHED_CONTEXT_DELETED
-# define SEC_E_UNFINISHED_CONTEXT_DELETED     ((HRESULT)0x80090333L)
-#endif
-#ifndef SEC_E_NO_TGT_REPLY
-# define SEC_E_NO_TGT_REPLY                   ((HRESULT)0x80090334L)
-#endif
-#ifndef SEC_E_NO_IP_ADDRESSES
-# define SEC_E_NO_IP_ADDRESSES                ((HRESULT)0x80090335L)
-#endif
-#ifndef SEC_E_WRONG_CREDENTIAL_HANDLE
-# define SEC_E_WRONG_CREDENTIAL_HANDLE        ((HRESULT)0x80090336L)
-#endif
-#ifndef SEC_E_CRYPTO_SYSTEM_INVALID
-# define SEC_E_CRYPTO_SYSTEM_INVALID          ((HRESULT)0x80090337L)
-#endif
-#ifndef SEC_E_MAX_REFERRALS_EXCEEDED
-# define SEC_E_MAX_REFERRALS_EXCEEDED         ((HRESULT)0x80090338L)
-#endif
-#ifndef SEC_E_MUST_BE_KDC
-# define SEC_E_MUST_BE_KDC                    ((HRESULT)0x80090339L)
-#endif
-#ifndef SEC_E_STRONG_CRYPTO_NOT_SUPPORTED
-# define SEC_E_STRONG_CRYPTO_NOT_SUPPORTED    ((HRESULT)0x8009033AL)
-#endif
-#ifndef SEC_E_TOO_MANY_PRINCIPALS
-# define SEC_E_TOO_MANY_PRINCIPALS            ((HRESULT)0x8009033BL)
-#endif
-#ifndef SEC_E_NO_PA_DATA
-# define SEC_E_NO_PA_DATA                     ((HRESULT)0x8009033CL)
-#endif
-#ifndef SEC_E_PKINIT_NAME_MISMATCH
-# define SEC_E_PKINIT_NAME_MISMATCH           ((HRESULT)0x8009033DL)
-#endif
-#ifndef SEC_E_SMARTCARD_LOGON_REQUIRED
-# define SEC_E_SMARTCARD_LOGON_REQUIRED       ((HRESULT)0x8009033EL)
-#endif
-#ifndef SEC_E_SHUTDOWN_IN_PROGRESS
-# define SEC_E_SHUTDOWN_IN_PROGRESS           ((HRESULT)0x8009033FL)
-#endif
-#ifndef SEC_E_KDC_INVALID_REQUEST
-# define SEC_E_KDC_INVALID_REQUEST            ((HRESULT)0x80090340L)
-#endif
-#ifndef SEC_E_KDC_UNABLE_TO_REFER
-# define SEC_E_KDC_UNABLE_TO_REFER            ((HRESULT)0x80090341L)
-#endif
-#ifndef SEC_E_KDC_UNKNOWN_ETYPE
-# define SEC_E_KDC_UNKNOWN_ETYPE              ((HRESULT)0x80090342L)
-#endif
-#ifndef SEC_E_UNSUPPORTED_PREAUTH
-# define SEC_E_UNSUPPORTED_PREAUTH            ((HRESULT)0x80090343L)
-#endif
-#ifndef SEC_E_DELEGATION_REQUIRED
-# define SEC_E_DELEGATION_REQUIRED            ((HRESULT)0x80090345L)
-#endif
-#ifndef SEC_E_BAD_BINDINGS
-# define SEC_E_BAD_BINDINGS                   ((HRESULT)0x80090346L)
-#endif
-#ifndef SEC_E_MULTIPLE_ACCOUNTS
-# define SEC_E_MULTIPLE_ACCOUNTS              ((HRESULT)0x80090347L)
-#endif
-#ifndef SEC_E_NO_KERB_KEY
-# define SEC_E_NO_KERB_KEY                    ((HRESULT)0x80090348L)
-#endif
-#ifndef SEC_E_CERT_WRONG_USAGE
-# define SEC_E_CERT_WRONG_USAGE               ((HRESULT)0x80090349L)
-#endif
-#ifndef SEC_E_DOWNGRADE_DETECTED
-# define SEC_E_DOWNGRADE_DETECTED             ((HRESULT)0x80090350L)
-#endif
-#ifndef SEC_E_SMARTCARD_CERT_REVOKED
-# define SEC_E_SMARTCARD_CERT_REVOKED         ((HRESULT)0x80090351L)
-#endif
-#ifndef SEC_E_ISSUING_CA_UNTRUSTED
-# define SEC_E_ISSUING_CA_UNTRUSTED           ((HRESULT)0x80090352L)
-#endif
-#ifndef SEC_E_REVOCATION_OFFLINE_C
-# define SEC_E_REVOCATION_OFFLINE_C           ((HRESULT)0x80090353L)
-#endif
-#ifndef SEC_E_PKINIT_CLIENT_FAILURE
-# define SEC_E_PKINIT_CLIENT_FAILURE          ((HRESULT)0x80090354L)
-#endif
-#ifndef SEC_E_SMARTCARD_CERT_EXPIRED
-# define SEC_E_SMARTCARD_CERT_EXPIRED         ((HRESULT)0x80090355L)
-#endif
-#ifndef SEC_E_NO_S4U_PROT_SUPPORT
-# define SEC_E_NO_S4U_PROT_SUPPORT            ((HRESULT)0x80090356L)
-#endif
-#ifndef SEC_E_CROSSREALM_DELEGATION_FAILURE
-# define SEC_E_CROSSREALM_DELEGATION_FAILURE  ((HRESULT)0x80090357L)
-#endif
-#ifndef SEC_E_REVOCATION_OFFLINE_KDC
-# define SEC_E_REVOCATION_OFFLINE_KDC         ((HRESULT)0x80090358L)
-#endif
-#ifndef SEC_E_ISSUING_CA_UNTRUSTED_KDC
-# define SEC_E_ISSUING_CA_UNTRUSTED_KDC       ((HRESULT)0x80090359L)
-#endif
-#ifndef SEC_E_KDC_CERT_EXPIRED
-# define SEC_E_KDC_CERT_EXPIRED               ((HRESULT)0x8009035AL)
-#endif
-#ifndef SEC_E_KDC_CERT_REVOKED
-# define SEC_E_KDC_CERT_REVOKED               ((HRESULT)0x8009035BL)
-#endif
 #ifndef SEC_E_INVALID_PARAMETER
 # define SEC_E_INVALID_PARAMETER              ((HRESULT)0x8009035DL)
 #endif
@@ -301,30 +80,6 @@ extern PSecurityFunctionTable s_pSecFn;
 # define SEC_E_POLICY_NLTM_ONLY               ((HRESULT)0x8009035FL)
 #endif
 
-#ifndef SEC_I_CONTINUE_NEEDED
-# define SEC_I_CONTINUE_NEEDED                ((HRESULT)0x00090312L)
-#endif
-#ifndef SEC_I_COMPLETE_NEEDED
-# define SEC_I_COMPLETE_NEEDED                ((HRESULT)0x00090313L)
-#endif
-#ifndef SEC_I_COMPLETE_AND_CONTINUE
-# define SEC_I_COMPLETE_AND_CONTINUE          ((HRESULT)0x00090314L)
-#endif
-#ifndef SEC_I_LOCAL_LOGON
-# define SEC_I_LOCAL_LOGON                    ((HRESULT)0x00090315L)
-#endif
-#ifndef SEC_I_CONTEXT_EXPIRED
-# define SEC_I_CONTEXT_EXPIRED                ((HRESULT)0x00090317L)
-#endif
-#ifndef SEC_I_INCOMPLETE_CREDENTIALS
-# define SEC_I_INCOMPLETE_CREDENTIALS         ((HRESULT)0x00090320L)
-#endif
-#ifndef SEC_I_RENEGOTIATE
-# define SEC_I_RENEGOTIATE                    ((HRESULT)0x00090321L)
-#endif
-#ifndef SEC_I_NO_LSA_CONTEXT
-# define SEC_I_NO_LSA_CONTEXT                 ((HRESULT)0x00090323L)
-#endif
 #ifndef SEC_I_SIGNATURE_NEEDED
 # define SEC_I_SIGNATURE_NEEDED               ((HRESULT)0x0009035CL)
 #endif
@@ -333,6 +88,22 @@ extern PSecurityFunctionTable s_pSecFn;
 # define CRYPT_E_REVOKED                      ((HRESULT)0x80092010L)
 #endif
 
+#ifndef CRYPT_E_NO_REVOCATION_DLL
+# define CRYPT_E_NO_REVOCATION_DLL            ((HRESULT)0x80092011L)
+#endif
+
+#ifndef CRYPT_E_NO_REVOCATION_CHECK
+# define CRYPT_E_NO_REVOCATION_CHECK          ((HRESULT)0x80092012L)
+#endif
+
+#ifndef CRYPT_E_REVOCATION_OFFLINE
+# define CRYPT_E_REVOCATION_OFFLINE           ((HRESULT)0x80092013L)
+#endif
+
+#ifndef CRYPT_E_NOT_IN_REVOCATION_DATABASE
+# define CRYPT_E_NOT_IN_REVOCATION_DATABASE   ((HRESULT)0x80092014L)
+#endif
+
 #ifdef UNICODE
 #  define SECFLAG_WINNT_AUTH_IDENTITY \
      (unsigned long)SEC_WINNT_AUTH_IDENTITY_UNICODE
diff --git a/vendor/curl/lib/curl_threads.c b/vendor/curl/lib/curl_threads.c
index e13e2947c2..93fa2dafb6 100644
--- a/vendor/curl/lib/curl_threads.c
+++ b/vendor/curl/lib/curl_threads.c
@@ -106,8 +106,6 @@ curl_thread_t Curl_thread_create(unsigned int (CURL_STDCALL *func) (void *),
 {
 #ifdef _WIN32_WCE
   typedef HANDLE curl_win_thread_handle_t;
-#elif defined(__MINGW32__) && !defined(__MINGW64_VERSION_MAJOR)
-  typedef unsigned long curl_win_thread_handle_t;
 #else
   typedef uintptr_t curl_win_thread_handle_t;
 #endif
@@ -133,7 +131,8 @@ curl_thread_t Curl_thread_create(unsigned int (CURL_STDCALL *func) (void *),
 
 void Curl_thread_destroy(curl_thread_t hnd)
 {
-  CloseHandle(hnd);
+  if(hnd != curl_thread_t_null)
+    CloseHandle(hnd);
 }
 
 int Curl_thread_join(curl_thread_t *hnd)
diff --git a/vendor/curl/lib/curl_threads.h b/vendor/curl/lib/curl_threads.h
index facbc73705..27a478d4c7 100644
--- a/vendor/curl/lib/curl_threads.h
+++ b/vendor/curl/lib/curl_threads.h
@@ -40,8 +40,7 @@
 #  define curl_thread_t          HANDLE
 #  define curl_thread_t_null     (HANDLE)0
 #  if !defined(_WIN32_WINNT) || !defined(_WIN32_WINNT_VISTA) || \
-      (_WIN32_WINNT < _WIN32_WINNT_VISTA) || \
-      (defined(__MINGW32__) && !defined(__MINGW64_VERSION_MAJOR))
+      (_WIN32_WINNT < _WIN32_WINNT_VISTA)
 #    define Curl_mutex_init(m)   InitializeCriticalSection(m)
 #  else
 #    define Curl_mutex_init(m)   InitializeCriticalSectionEx(m, 0, 1)
diff --git a/vendor/curl/lib/curl_trc.c b/vendor/curl/lib/curl_trc.c
index 76c35ba386..f017e21a5a 100644
--- a/vendor/curl/lib/curl_trc.c
+++ b/vendor/curl/lib/curl_trc.c
@@ -36,6 +36,7 @@
 
 #include "cf-socket.h"
 #include "connect.h"
+#include "doh.h"
 #include "http2.h"
 #include "http_proxy.h"
 #include "cf-h1-proxy.h"
@@ -105,36 +106,54 @@ void Curl_failf(struct Curl_easy *data, const char *fmt, ...)
   }
 }
 
+#if !defined(CURL_DISABLE_VERBOSE_STRINGS)
+
 /* Curl_infof() is for info message along the way */
 #define MAXINFO 2048
 
+static void trc_infof(struct Curl_easy *data, struct curl_trc_feat *feat,
+                      const char * const fmt, va_list ap)  CURL_PRINTF(3, 0);
+
+static void trc_infof(struct Curl_easy *data, struct curl_trc_feat *feat,
+                      const char * const fmt, va_list ap)
+{
+  int len = 0;
+  char buffer[MAXINFO + 2];
+  if(feat)
+    len = msnprintf(buffer, MAXINFO, "[%s] ", feat->name);
+  len += mvsnprintf(buffer + len, MAXINFO - len, fmt, ap);
+  buffer[len++] = '\n';
+  buffer[len] = '\0';
+  Curl_debug(data, CURLINFO_TEXT, buffer, len);
+}
+
 void Curl_infof(struct Curl_easy *data, const char *fmt, ...)
 {
   DEBUGASSERT(!strchr(fmt, '\n'));
-  if(data && data->set.verbose) {
+  if(Curl_trc_is_verbose(data)) {
     va_list ap;
-    int len;
-    char buffer[MAXINFO + 2];
     va_start(ap, fmt);
-    len = mvsnprintf(buffer, MAXINFO, fmt, ap);
+    trc_infof(data, data->state.feat, fmt, ap);
     va_end(ap);
-    buffer[len++] = '\n';
-    buffer[len] = '\0';
-    Curl_debug(data, CURLINFO_TEXT, buffer, len);
   }
 }
 
-#if !defined(CURL_DISABLE_VERBOSE_STRINGS)
-
 void Curl_trc_cf_infof(struct Curl_easy *data, struct Curl_cfilter *cf,
                        const char *fmt, ...)
 {
   DEBUGASSERT(cf);
-  if(data && Curl_trc_cf_is_verbose(cf, data)) {
+  if(Curl_trc_cf_is_verbose(cf, data)) {
     va_list ap;
-    int len;
+    int len = 0;
     char buffer[MAXINFO + 2];
-    len = msnprintf(buffer, MAXINFO, "[%s] ", cf->cft->name);
+    if(data->state.feat)
+      len += msnprintf(buffer + len, MAXINFO - len, "[%s] ",
+                       data->state.feat->name);
+    if(cf->sockindex)
+      len += msnprintf(buffer + len, MAXINFO - len, "[%s-%d] ",
+                      cf->cft->name, cf->sockindex);
+    else
+      len += msnprintf(buffer + len, MAXINFO - len, "[%s] ", cf->cft->name);
     va_start(ap, fmt);
     len += mvsnprintf(buffer + len, MAXINFO - len, fmt, ap);
     va_end(ap);
@@ -144,6 +163,66 @@ void Curl_trc_cf_infof(struct Curl_easy *data, struct Curl_cfilter *cf,
   }
 }
 
+struct curl_trc_feat Curl_trc_feat_read = {
+  "READ",
+  CURL_LOG_LVL_NONE,
+};
+struct curl_trc_feat Curl_trc_feat_write = {
+  "WRITE",
+  CURL_LOG_LVL_NONE,
+};
+
+void Curl_trc_read(struct Curl_easy *data, const char *fmt, ...)
+{
+  DEBUGASSERT(!strchr(fmt, '\n'));
+  if(Curl_trc_ft_is_verbose(data, &Curl_trc_feat_read)) {
+    va_list ap;
+    va_start(ap, fmt);
+    trc_infof(data, &Curl_trc_feat_read, fmt, ap);
+    va_end(ap);
+  }
+}
+
+void Curl_trc_write(struct Curl_easy *data, const char *fmt, ...)
+{
+  DEBUGASSERT(!strchr(fmt, '\n'));
+  if(Curl_trc_ft_is_verbose(data, &Curl_trc_feat_write)) {
+    va_list ap;
+    va_start(ap, fmt);
+    trc_infof(data, &Curl_trc_feat_write, fmt, ap);
+    va_end(ap);
+  }
+}
+
+#ifndef CURL_DISABLE_FTP
+struct curl_trc_feat Curl_trc_feat_ftp = {
+  "FTP",
+  CURL_LOG_LVL_NONE,
+};
+
+void Curl_trc_ftp(struct Curl_easy *data, const char *fmt, ...)
+{
+  DEBUGASSERT(!strchr(fmt, '\n'));
+  if(Curl_trc_ft_is_verbose(data, &Curl_trc_feat_ftp)) {
+    va_list ap;
+    va_start(ap, fmt);
+    trc_infof(data, &Curl_trc_feat_ftp, fmt, ap);
+    va_end(ap);
+  }
+}
+#endif /* !CURL_DISABLE_FTP */
+
+static struct curl_trc_feat *trc_feats[] = {
+  &Curl_trc_feat_read,
+  &Curl_trc_feat_write,
+#ifndef CURL_DISABLE_FTP
+  &Curl_trc_feat_ftp,
+#endif
+#ifndef CURL_DISABLE_DOH
+  &Curl_doh_trc,
+#endif
+  NULL,
+};
 
 static struct Curl_cftype *cf_types[] = {
   &Curl_cft_tcp,
@@ -157,8 +236,10 @@ static struct Curl_cftype *cf_types[] = {
 #endif
 #ifdef USE_SSL
   &Curl_cft_ssl,
+#ifndef CURL_DISABLE_PROXY
   &Curl_cft_ssl_proxy,
 #endif
+#endif
 #if !defined(CURL_DISABLE_PROXY)
 #if !defined(CURL_DISABLE_HTTP)
   &Curl_cft_h1_proxy,
@@ -170,7 +251,7 @@ static struct Curl_cftype *cf_types[] = {
   &Curl_cft_haproxy,
   &Curl_cft_socks_proxy,
 #endif /* !CURL_DISABLE_PROXY */
-#ifdef ENABLE_QUIC
+#ifdef USE_HTTP3
   &Curl_cft_http3,
 #endif
 #if !defined(CURL_DISABLE_HTTP) && !defined(USE_HYPER)
@@ -213,6 +294,15 @@ CURLcode Curl_trc_opt(const char *config)
         break;
       }
     }
+    for(i = 0; trc_feats[i]; ++i) {
+      if(strcasecompare(token, "all")) {
+        trc_feats[i]->log_level = lvl;
+      }
+      else if(strcasecompare(token, trc_feats[i]->name)) {
+        trc_feats[i]->log_level = lvl;
+        break;
+      }
+    }
     token = strtok_r(NULL, ", ", &tok_buf);
   }
   free(tmp);
@@ -228,24 +318,14 @@ CURLcode Curl_trc_init(void)
   if(config) {
     return Curl_trc_opt(config);
   }
-#endif
+#endif /* DEBUGBUILD */
   return CURLE_OK;
 }
-#else /* !CURL_DISABLE_VERBOSE_STRINGS) */
+#else /* defined(CURL_DISABLE_VERBOSE_STRINGS) */
 
 CURLcode Curl_trc_init(void)
 {
   return CURLE_OK;
 }
 
-#if !defined(__STDC_VERSION__) || (__STDC_VERSION__ < 199901L)
-void Curl_trc_cf_infof(struct Curl_easy *data, struct Curl_cfilter *cf,
-                       const char *fmt, ...)
-{
-  (void)data;
-  (void)cf;
-  (void)fmt;
-}
-#endif
-
-#endif /* !DEBUGBUILD */
+#endif /* !defined(CURL_DISABLE_VERBOSE_STRINGS) */
diff --git a/vendor/curl/lib/curl_trc.h b/vendor/curl/lib/curl_trc.h
index 84b5471d85..3d38018342 100644
--- a/vendor/curl/lib/curl_trc.h
+++ b/vendor/curl/lib/curl_trc.h
@@ -54,97 +54,147 @@ CURLcode Curl_trc_opt(const char *config);
 void Curl_debug(struct Curl_easy *data, curl_infotype type,
                 char *ptr, size_t size);
 
-/**
- * Output an informational message when transfer's verbose logging is enabled.
- */
-void Curl_infof(struct Curl_easy *data,
-#if defined(__GNUC__) && !defined(printf) &&                    \
-  defined(__STDC_VERSION__) && (__STDC_VERSION__ >= 199901L) && \
-  !defined(__MINGW32__)
-                       const char *fmt, ...)
-                       __attribute__((format(printf, 2, 3)));
-#else
-                       const char *fmt, ...);
-#endif
-
 /**
  * Output a failure message on registered callbacks for transfer.
  */
 void Curl_failf(struct Curl_easy *data,
-#if defined(__GNUC__) && !defined(printf) &&                    \
-  defined(__STDC_VERSION__) && (__STDC_VERSION__ >= 199901L) && \
-  !defined(__MINGW32__)
-                       const char *fmt, ...)
-                       __attribute__((format(printf, 2, 3)));
-#else
-                       const char *fmt, ...);
-#endif
+                const char *fmt, ...) CURL_PRINTF(2, 3);
 
 #define failf Curl_failf
 
-/**
- * Output an informational message when both transfer's verbose logging
- * and connection filters verbose logging are enabled.
- */
-void Curl_trc_cf_infof(struct Curl_easy *data, struct Curl_cfilter *cf,
-#if defined(__GNUC__) && !defined(printf) &&                    \
-  defined(__STDC_VERSION__) && (__STDC_VERSION__ >= 199901L) && \
-  !defined(__MINGW32__)
-                       const char *fmt, ...)
-                       __attribute__((format(printf, 3, 4)));
-#else
-                       const char *fmt, ...);
-#endif
-
 #define CURL_LOG_LVL_NONE  0
 #define CURL_LOG_LVL_INFO  1
 
 
-#if !defined(CURL_DISABLE_VERBOSE_STRINGS)
-/* informational messages enabled */
-
-#define Curl_trc_is_verbose(data)    ((data) && (data)->set.verbose)
-#define Curl_trc_cf_is_verbose(cf, data) \
-                            ((data) && (data)->set.verbose && \
-                            (cf) && (cf)->cft->log_level >= CURL_LOG_LVL_INFO)
-
-/* explainer: we have some mix configuration and werror settings
- * that define HAVE_VARIADIC_MACROS_C99 even though C89 is enforced
- * on gnuc and some other compiler. Need to treat carefully.
- */
-#if defined(HAVE_VARIADIC_MACROS_C99) && \
-    defined(__STDC_VERSION__) && (__STDC_VERSION__ >= 199901L)
+#if defined(__STDC_VERSION__) && __STDC_VERSION__ >= 199901L
+#define CURL_HAVE_C99
+#endif
 
+#ifdef CURL_HAVE_C99
 #define infof(data, ...) \
   do { if(Curl_trc_is_verbose(data)) \
          Curl_infof(data, __VA_ARGS__); } while(0)
 #define CURL_TRC_CF(data, cf, ...) \
   do { if(Curl_trc_cf_is_verbose(cf, data)) \
          Curl_trc_cf_infof(data, cf, __VA_ARGS__); } while(0)
+#define CURL_TRC_WRITE(data, ...) \
+  do { if(Curl_trc_ft_is_verbose(data, &Curl_trc_feat_write)) \
+         Curl_trc_write(data, __VA_ARGS__); } while(0)
+#define CURL_TRC_READ(data, ...) \
+  do { if(Curl_trc_ft_is_verbose(data, &Curl_trc_feat_read)) \
+         Curl_trc_read(data, __VA_ARGS__); } while(0)
+
+#ifndef CURL_DISABLE_FTP
+#define CURL_TRC_FTP(data, ...) \
+  do { if(Curl_trc_ft_is_verbose(data, &Curl_trc_feat_ftp)) \
+         Curl_trc_ftp(data, __VA_ARGS__); } while(0)
+#endif /* !CURL_DISABLE_FTP */
+
+#else /* CURL_HAVE_C99 */
 
-#else /* no variadic macro args */
 #define infof Curl_infof
 #define CURL_TRC_CF Curl_trc_cf_infof
-#endif /* variadic macro args */
+#define CURL_TRC_WRITE Curl_trc_write
+#define CURL_TRC_READ  Curl_trc_read
+
+#ifndef CURL_DISABLE_FTP
+#define CURL_TRC_FTP   Curl_trc_ftp
+#endif
+
+#endif /* !CURL_HAVE_C99 */
+
+#ifndef CURL_DISABLE_VERBOSE_STRINGS
+/* informational messages enabled */
+
+struct curl_trc_feat {
+  const char *name;
+  int log_level;
+};
+extern struct curl_trc_feat Curl_trc_feat_read;
+extern struct curl_trc_feat Curl_trc_feat_write;
+
+#define Curl_trc_is_verbose(data) \
+            ((data) && (data)->set.verbose && \
+            (!(data)->state.feat || \
+             ((data)->state.feat->log_level >= CURL_LOG_LVL_INFO)))
+#define Curl_trc_cf_is_verbose(cf, data) \
+            (Curl_trc_is_verbose(data) && \
+             (cf) && (cf)->cft->log_level >= CURL_LOG_LVL_INFO)
+#define Curl_trc_ft_is_verbose(data, ft) \
+            (Curl_trc_is_verbose(data) && \
+             (ft)->log_level >= CURL_LOG_LVL_INFO)
+
+/**
+ * Output an informational message when transfer's verbose logging is enabled.
+ */
+void Curl_infof(struct Curl_easy *data,
+                const char *fmt, ...) CURL_PRINTF(2, 3);
+
+/**
+ * Output an informational message when both transfer's verbose logging
+ * and connection filters verbose logging are enabled.
+ */
+void Curl_trc_cf_infof(struct Curl_easy *data, struct Curl_cfilter *cf,
+                       const char *fmt, ...) CURL_PRINTF(3, 4);
+void Curl_trc_ft_infof(struct Curl_easy *data, struct curl_trc_feat *ft,
+                       const char *fmt, ...) CURL_PRINTF(3, 4);
+void Curl_trc_write(struct Curl_easy *data,
+                    const char *fmt, ...) CURL_PRINTF(2, 3);
+void Curl_trc_read(struct Curl_easy *data,
+                   const char *fmt, ...) CURL_PRINTF(2, 3);
+
+#ifndef CURL_DISABLE_FTP
+extern struct curl_trc_feat Curl_trc_feat_ftp;
+void Curl_trc_ftp(struct Curl_easy *data,
+                  const char *fmt, ...) CURL_PRINTF(2, 3);
+#endif
+
 
-#else /* !CURL_DISABLE_VERBOSE_STRINGS */
+#else /* defined(CURL_DISABLE_VERBOSE_STRINGS) */
 /* All informational messages are not compiled in for size savings */
 
-#define Curl_trc_is_verbose(d)        ((void)(d), FALSE)
-#define Curl_trc_cf_is_verbose(x,y)   ((void)(x), (void)(y), FALSE)
-
-#if defined(HAVE_VARIADIC_MACROS_C99)
-#define infof(...)  Curl_nop_stmt
-#define CURL_TRC_CF(...)  Curl_nop_stmt
-#define Curl_trc_cf_infof(...)  Curl_nop_stmt
-#elif defined(HAVE_VARIADIC_MACROS_GCC)
-#define infof(x...)  Curl_nop_stmt
-#define CURL_TRC_CF(x...)  Curl_nop_stmt
-#define Curl_trc_cf_infof(x...)  Curl_nop_stmt
-#else
-#error "missing VARIADIC macro define, fix and rebuild!"
+#define Curl_trc_is_verbose(d)        (FALSE)
+#define Curl_trc_cf_is_verbose(x,y)   (FALSE)
+#define Curl_trc_ft_is_verbose(x,y)   (FALSE)
+
+static void Curl_infof(struct Curl_easy *data, const char *fmt, ...)
+{
+  (void)data; (void)fmt;
+}
+
+static void Curl_trc_cf_infof(struct Curl_easy *data,
+                              struct Curl_cfilter *cf,
+                              const char *fmt, ...)
+{
+  (void)data; (void)cf; (void)fmt;
+}
+
+struct curl_trc_feat;
+
+static void Curl_trc_ft_infof(struct Curl_easy *data,
+                              struct curl_trc_feat *ft,
+                              const char *fmt, ...)
+{
+  (void)data; (void)ft; (void)fmt;
+}
+
+static void Curl_trc_write(struct Curl_easy *data, const char *fmt, ...)
+{
+  (void)data; (void)fmt;
+}
+
+static void Curl_trc_read(struct Curl_easy *data, const char *fmt, ...)
+{
+  (void)data; (void)fmt;
+}
+
+#ifndef CURL_DISABLE_FTP
+static void Curl_trc_ftp(struct Curl_easy *data, const char *fmt, ...)
+{
+  (void)data; (void)fmt;
+}
 #endif
 
-#endif /* CURL_DISABLE_VERBOSE_STRINGS */
+#endif /* !defined(CURL_DISABLE_VERBOSE_STRINGS) */
 
 #endif /* HEADER_CURL_TRC_H */
diff --git a/vendor/curl/lib/curlx.h b/vendor/curl/lib/curlx.h
index 7a753d6824..54e4279572 100644
--- a/vendor/curl/lib/curlx.h
+++ b/vendor/curl/lib/curlx.h
@@ -77,7 +77,6 @@
 
 */
 
-#define curlx_getenv curl_getenv
 #define curlx_mvsnprintf curl_mvsnprintf
 #define curlx_msnprintf curl_msnprintf
 #define curlx_maprintf curl_maprintf
diff --git a/vendor/curl/lib/cw-out.c b/vendor/curl/lib/cw-out.c
new file mode 100644
index 0000000000..4e56c6a1bb
--- /dev/null
+++ b/vendor/curl/lib/cw-out.c
@@ -0,0 +1,474 @@
+/***************************************************************************
+ *                                  _   _ ____  _
+ *  Project                     ___| | | |  _ \| |
+ *                             / __| | | | |_) | |
+ *                            | (__| |_| |  _ <| |___
+ *                             \___|\___/|_| \_\_____|
+ *
+ * Copyright (C) Daniel Stenberg, , et al.
+ *
+ * This software is licensed as described in the file COPYING, which
+ * you should have received as part of this distribution. The terms
+ * are also available at https://curl.se/docs/copyright.html.
+ *
+ * You may opt to use, copy, modify, merge, publish, distribute and/or sell
+ * copies of the Software, and permit persons to whom the Software is
+ * furnished to do so, under the terms of the COPYING file.
+ *
+ * This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY
+ * KIND, either express or implied.
+ *
+ * SPDX-License-Identifier: curl
+ *
+ ***************************************************************************/
+
+#include "curl_setup.h"
+
+#include 
+
+#include "urldata.h"
+#include "cfilters.h"
+#include "headers.h"
+#include "multiif.h"
+#include "sendf.h"
+#include "cw-out.h"
+
+/* The last 3 #include files should be in this order */
+#include "curl_printf.h"
+#include "curl_memory.h"
+#include "memdebug.h"
+
+
+/**
+ * OVERALL DESIGN of this client writer
+ *
+ * The 'cw-out' writer is supposed to be the last writer in a transfer's
+ * stack. It is always added when that stack is initialized. Its purpose
+ * is to pass BODY and HEADER bytes to the client-installed callback
+ * functions.
+ *
+ * These callback may return `CURL_WRITEFUNC_PAUSE` to indicate that the
+ * data had not been written and the whole transfer should stop receiving
+ * new data. Or at least, stop calling the functions. When the transfer
+ * is "unpaused" by the client, the previous data shall be passed as
+ * if nothing happened.
+ *
+ * The `cw-out` writer therefore manages buffers for bytes that could
+ * not be written. Data that was already in flight from the server also
+ * needs buffering on paused transfer when it arrives.
+ *
+ * In addition, the writer allows buffering of "small" body writes,
+ * so client functions are called less often. That is only enabled on a
+ * number of conditions.
+ *
+ * HEADER and BODY data may arrive in any order. For paused transfers,
+ * a list of `struct cw_out_buf` is kept for `cw_out_type` types. The
+ * list may be: [BODY]->[HEADER]->[BODY]->[HEADER]....
+ * When unpausing, this list is "played back" to the client callbacks.
+ *
+ * The amount of bytes being buffered is limited by `DYN_PAUSE_BUFFER`
+ * and when that is exceeded `CURLE_TOO_LARGE` is returned as error.
+ */
+typedef enum {
+  CW_OUT_NONE,
+  CW_OUT_BODY,
+  CW_OUT_HDS
+} cw_out_type;
+
+struct cw_out_buf {
+  struct cw_out_buf *next;
+  struct dynbuf b;
+  cw_out_type type;
+};
+
+static struct cw_out_buf *cw_out_buf_create(cw_out_type otype)
+{
+  struct cw_out_buf *cwbuf = calloc(1, sizeof(*cwbuf));
+  if(cwbuf) {
+    cwbuf->type = otype;
+    Curl_dyn_init(&cwbuf->b, DYN_PAUSE_BUFFER);
+  }
+  return cwbuf;
+}
+
+static void cw_out_buf_free(struct cw_out_buf *cwbuf)
+{
+  if(cwbuf) {
+    Curl_dyn_free(&cwbuf->b);
+    free(cwbuf);
+  }
+}
+
+struct cw_out_ctx {
+  struct Curl_cwriter super;
+  struct cw_out_buf *buf;
+  BIT(paused);
+  BIT(errored);
+};
+
+static CURLcode cw_out_write(struct Curl_easy *data,
+                             struct Curl_cwriter *writer, int type,
+                             const char *buf, size_t nbytes);
+static void cw_out_close(struct Curl_easy *data, struct Curl_cwriter *writer);
+static CURLcode cw_out_init(struct Curl_easy *data,
+                            struct Curl_cwriter *writer);
+
+struct Curl_cwtype Curl_cwt_out = {
+  "cw-out",
+  NULL,
+  cw_out_init,
+  cw_out_write,
+  cw_out_close,
+  sizeof(struct cw_out_ctx)
+};
+
+static CURLcode cw_out_init(struct Curl_easy *data,
+                            struct Curl_cwriter *writer)
+{
+  struct cw_out_ctx *ctx = writer->ctx;
+  (void)data;
+  ctx->buf = NULL;
+  return CURLE_OK;
+}
+
+static void cw_out_bufs_free(struct cw_out_ctx *ctx)
+{
+  while(ctx->buf) {
+    struct cw_out_buf *next = ctx->buf->next;
+    cw_out_buf_free(ctx->buf);
+    ctx->buf = next;
+  }
+}
+
+static size_t cw_out_bufs_len(struct cw_out_ctx *ctx)
+{
+  struct cw_out_buf *cwbuf = ctx->buf;
+  size_t len = 0;
+  while(cwbuf) {
+    len += Curl_dyn_len(&cwbuf->b);
+    cwbuf = cwbuf->next;
+  }
+  return len;
+}
+
+static void cw_out_close(struct Curl_easy *data, struct Curl_cwriter *writer)
+{
+  struct cw_out_ctx *ctx = writer->ctx;
+
+  (void)data;
+  cw_out_bufs_free(ctx);
+}
+
+/**
+ * Return the current curl_write_callback and user_data for the buf type
+ */
+static void cw_get_writefunc(struct Curl_easy *data, cw_out_type otype,
+                             curl_write_callback *pwcb, void **pwcb_data,
+                             size_t *pmax_write, size_t *pmin_write)
+{
+  switch(otype) {
+  case CW_OUT_BODY:
+    *pwcb = data->set.fwrite_func;
+    *pwcb_data = data->set.out;
+    *pmax_write = CURL_MAX_WRITE_SIZE;
+    /* if we ever want buffering of BODY output, we can set `min_write`
+     * the preferred size. The default should always be to pass data
+     * to the client as it comes without delay */
+    *pmin_write = 0;
+    break;
+  case CW_OUT_HDS:
+    *pwcb = data->set.fwrite_header? data->set.fwrite_header :
+             (data->set.writeheader? data->set.fwrite_func : NULL);
+    *pwcb_data = data->set.writeheader;
+    *pmax_write = 0; /* do not chunk-write headers, write them as they are */
+    *pmin_write = 0;
+    break;
+  default:
+    *pwcb = NULL;
+    *pwcb_data = NULL;
+    *pmax_write = CURL_MAX_WRITE_SIZE;
+    *pmin_write = 0;
+  }
+}
+
+static CURLcode cw_out_ptr_flush(struct cw_out_ctx *ctx,
+                                 struct Curl_easy *data,
+                                 cw_out_type otype,
+                                 bool flush_all,
+                                 const char *buf, size_t blen,
+                                 size_t *pconsumed)
+{
+  curl_write_callback wcb;
+  void *wcb_data;
+  size_t max_write, min_write;
+  size_t wlen, nwritten;
+
+  /* If we errored once, we do not invoke the client callback  again */
+  if(ctx->errored)
+    return CURLE_WRITE_ERROR;
+
+  /* write callbacks may get NULLed by the client between calls. */
+  cw_get_writefunc(data, otype, &wcb, &wcb_data, &max_write, &min_write);
+  if(!wcb) {
+    *pconsumed = blen;
+    return CURLE_OK;
+  }
+
+  *pconsumed = 0;
+  while(blen && !ctx->paused) {
+    if(!flush_all && blen < min_write)
+      break;
+    wlen = max_write? CURLMIN(blen, max_write) : blen;
+    Curl_set_in_callback(data, TRUE);
+    nwritten = wcb((char *)buf, 1, wlen, wcb_data);
+    Curl_set_in_callback(data, FALSE);
+    CURL_TRC_WRITE(data, "cw_out, wrote %zu %s bytes -> %zu",
+                   wlen, (otype == CW_OUT_BODY)? "body" : "header",
+                   nwritten);
+    if(CURL_WRITEFUNC_PAUSE == nwritten) {
+      if(data->conn && data->conn->handler->flags & PROTOPT_NONETWORK) {
+        /* Protocols that work without network cannot be paused. This is
+           actually only FILE:// just now, and it can't pause since the
+           transfer isn't done using the "normal" procedure. */
+        failf(data, "Write callback asked for PAUSE when not supported");
+        return CURLE_WRITE_ERROR;
+      }
+      /* mark the connection as RECV paused */
+      data->req.keepon |= KEEP_RECV_PAUSE;
+      ctx->paused = TRUE;
+      CURL_TRC_WRITE(data, "cw_out, PAUSE requested by client");
+      break;
+    }
+    else if(CURL_WRITEFUNC_ERROR == nwritten) {
+      failf(data, "client returned ERROR on write of %zu bytes", wlen);
+      return CURLE_WRITE_ERROR;
+    }
+    else if(nwritten != wlen) {
+      failf(data, "Failure writing output to destination, "
+            "passed %zu returned %zd", wlen, nwritten);
+      return CURLE_WRITE_ERROR;
+    }
+    *pconsumed += nwritten;
+    blen -= nwritten;
+    buf += nwritten;
+  }
+  return CURLE_OK;
+}
+
+static CURLcode cw_out_buf_flush(struct cw_out_ctx *ctx,
+                                 struct Curl_easy *data,
+                                 struct cw_out_buf *cwbuf,
+                                 bool flush_all)
+{
+  CURLcode result = CURLE_OK;
+
+  if(Curl_dyn_len(&cwbuf->b)) {
+    size_t consumed;
+
+    result = cw_out_ptr_flush(ctx, data, cwbuf->type, flush_all,
+                              Curl_dyn_ptr(&cwbuf->b),
+                              Curl_dyn_len(&cwbuf->b),
+                              &consumed);
+    if(result)
+      return result;
+
+    if(consumed) {
+      if(consumed == Curl_dyn_len(&cwbuf->b)) {
+        Curl_dyn_free(&cwbuf->b);
+      }
+      else {
+        DEBUGASSERT(consumed < Curl_dyn_len(&cwbuf->b));
+        result = Curl_dyn_tail(&cwbuf->b, Curl_dyn_len(&cwbuf->b) - consumed);
+        if(result)
+          return result;
+      }
+    }
+  }
+  return result;
+}
+
+static CURLcode cw_out_flush_chain(struct cw_out_ctx *ctx,
+                                   struct Curl_easy *data,
+                                   struct cw_out_buf **pcwbuf,
+                                   bool flush_all)
+{
+  struct cw_out_buf *cwbuf = *pcwbuf;
+  CURLcode result;
+
+  if(!cwbuf)
+    return CURLE_OK;
+  if(ctx->paused)
+    return CURLE_OK;
+
+  /* write the end of the chain until it blocks or gets empty */
+  while(cwbuf->next) {
+    struct cw_out_buf **plast = &cwbuf->next;
+    while((*plast)->next)
+      plast = &(*plast)->next;
+    result = cw_out_flush_chain(ctx, data, plast, flush_all);
+    if(result)
+      return result;
+    if(*plast) {
+      /* could not write last, paused again? */
+      DEBUGASSERT(ctx->paused);
+      return CURLE_OK;
+    }
+  }
+
+  result = cw_out_buf_flush(ctx, data, cwbuf, flush_all);
+  if(result)
+    return result;
+  if(!Curl_dyn_len(&cwbuf->b)) {
+    cw_out_buf_free(cwbuf);
+    *pcwbuf = NULL;
+  }
+  return CURLE_OK;
+}
+
+static CURLcode cw_out_append(struct cw_out_ctx *ctx,
+                              cw_out_type otype,
+                              const char *buf, size_t blen)
+{
+  if(cw_out_bufs_len(ctx) + blen > DYN_PAUSE_BUFFER)
+    return CURLE_TOO_LARGE;
+
+  /* if we do not have a buffer, or it is of another type, make a new one.
+   * And for CW_OUT_HDS always make a new one, so we "replay" headers
+   * exactly as they came in */
+  if(!ctx->buf || (ctx->buf->type != otype) || (otype == CW_OUT_HDS)) {
+    struct cw_out_buf *cwbuf = cw_out_buf_create(otype);
+    if(!cwbuf)
+      return CURLE_OUT_OF_MEMORY;
+    cwbuf->next = ctx->buf;
+    ctx->buf = cwbuf;
+  }
+  DEBUGASSERT(ctx->buf && (ctx->buf->type == otype));
+  return Curl_dyn_addn(&ctx->buf->b, buf, blen);
+}
+
+static CURLcode cw_out_do_write(struct cw_out_ctx *ctx,
+                                struct Curl_easy *data,
+                                cw_out_type otype,
+                                bool flush_all,
+                                const char *buf, size_t blen)
+{
+  CURLcode result = CURLE_OK;
+
+  /* if we have buffered data and it is a different type than what
+   * we are writing now, try to flush all */
+  if(ctx->buf && ctx->buf->type != otype) {
+    result = cw_out_flush_chain(ctx, data, &ctx->buf, TRUE);
+    if(result)
+      goto out;
+  }
+
+  if(ctx->buf) {
+    /* still have buffered data, append and flush */
+    result = cw_out_append(ctx, otype, buf, blen);
+    if(result)
+      return result;
+    result = cw_out_flush_chain(ctx, data, &ctx->buf, flush_all);
+    if(result)
+      goto out;
+  }
+  else {
+    /* nothing buffered, try direct write */
+    size_t consumed;
+    result = cw_out_ptr_flush(ctx, data, otype, flush_all,
+                              buf, blen, &consumed);
+    if(result)
+      return result;
+    if(consumed < blen) {
+      /* did not write all, append the rest */
+      result = cw_out_append(ctx, otype, buf + consumed, blen - consumed);
+      if(result)
+        goto out;
+    }
+  }
+
+out:
+  if(result) {
+    /* We do not want to invoked client callbacks a second time after
+     * encountering an error. See issue #13337 */
+    ctx->errored = TRUE;
+    cw_out_bufs_free(ctx);
+  }
+  return result;
+}
+
+static CURLcode cw_out_write(struct Curl_easy *data,
+                             struct Curl_cwriter *writer, int type,
+                             const char *buf, size_t blen)
+{
+  struct cw_out_ctx *ctx = writer->ctx;
+  CURLcode result;
+  bool flush_all;
+
+  flush_all = (type & CLIENTWRITE_EOS)? TRUE:FALSE;
+  if((type & CLIENTWRITE_BODY) ||
+     ((type & CLIENTWRITE_HEADER) && data->set.include_header)) {
+    result = cw_out_do_write(ctx, data, CW_OUT_BODY, flush_all, buf, blen);
+    if(result)
+      return result;
+  }
+
+  if(type & (CLIENTWRITE_HEADER|CLIENTWRITE_INFO)) {
+    result = cw_out_do_write(ctx, data, CW_OUT_HDS, flush_all, buf, blen);
+    if(result)
+      return result;
+  }
+
+  return CURLE_OK;
+}
+
+bool Curl_cw_out_is_paused(struct Curl_easy *data)
+{
+  struct Curl_cwriter *cw_out;
+  struct cw_out_ctx *ctx;
+
+  cw_out = Curl_cwriter_get_by_type(data, &Curl_cwt_out);
+  if(!cw_out)
+    return FALSE;
+
+  ctx = (struct cw_out_ctx *)cw_out;
+  CURL_TRC_WRITE(data, "cw-out is%spaused", ctx->paused? "" : " not");
+  return ctx->paused;
+}
+
+static CURLcode cw_out_flush(struct Curl_easy *data,
+                             bool unpause, bool flush_all)
+{
+  struct Curl_cwriter *cw_out;
+  CURLcode result = CURLE_OK;
+
+  cw_out = Curl_cwriter_get_by_type(data, &Curl_cwt_out);
+  if(cw_out) {
+    struct cw_out_ctx *ctx = (struct cw_out_ctx *)cw_out;
+    if(ctx->errored)
+      return CURLE_WRITE_ERROR;
+    if(unpause && ctx->paused)
+      ctx->paused = FALSE;
+    if(ctx->paused)
+      return CURLE_OK;  /* not doing it */
+
+    result = cw_out_flush_chain(ctx, data, &ctx->buf, flush_all);
+    if(result) {
+      ctx->errored = TRUE;
+      cw_out_bufs_free(ctx);
+      return result;
+    }
+  }
+  return result;
+}
+
+CURLcode Curl_cw_out_unpause(struct Curl_easy *data)
+{
+  CURL_TRC_WRITE(data, "cw-out unpause");
+  return cw_out_flush(data, TRUE, FALSE);
+}
+
+CURLcode Curl_cw_out_done(struct Curl_easy *data)
+{
+  CURL_TRC_WRITE(data, "cw-out done");
+  return cw_out_flush(data, FALSE, TRUE);
+}
diff --git a/vendor/curl/lib/curl_ntlm_wb.h b/vendor/curl/lib/cw-out.h
similarity index 60%
rename from vendor/curl/lib/curl_ntlm_wb.h
rename to vendor/curl/lib/cw-out.h
index 37704c0fe0..ca4c2e435d 100644
--- a/vendor/curl/lib/curl_ntlm_wb.h
+++ b/vendor/curl/lib/cw-out.h
@@ -1,5 +1,5 @@
-#ifndef HEADER_CURL_NTLM_WB_H
-#define HEADER_CURL_NTLM_WB_H
+#ifndef HEADER_CURL_CW_OUT_H
+#define HEADER_CURL_CW_OUT_H
 /***************************************************************************
  *                                  _   _ ____  _
  *  Project                     ___| | | |  _ \| |
@@ -26,20 +26,28 @@
 
 #include "curl_setup.h"
 
-#if !defined(CURL_DISABLE_HTTP) && defined(USE_NTLM) && \
-    defined(NTLM_WB_ENABLED)
+#include "sendf.h"
 
-/* this is for ntlm header input */
-CURLcode Curl_input_ntlm_wb(struct Curl_easy *data,
-                            struct connectdata *conn, bool proxy,
-                            const char *header);
+/**
+ * The client writer type "cw-out" that does the actual writing to
+ * the client callbacks. Intended to be the last installed in the
+ * client writer stack of a transfer.
+ */
+extern struct Curl_cwtype Curl_cwt_out;
 
-/* this is for creating ntlm header output */
-CURLcode Curl_output_ntlm_wb(struct Curl_easy *data, struct connectdata *conn,
-                             bool proxy);
+/**
+ * Return TRUE iff 'cw-out' client write has paused data.
+ */
+bool Curl_cw_out_is_paused(struct Curl_easy *data);
 
-void Curl_http_auth_cleanup_ntlm_wb(struct connectdata *conn);
+/**
+ * Flush any buffered date to the client, chunk collation still applies.
+ */
+CURLcode Curl_cw_out_unpause(struct Curl_easy *data);
 
-#endif /* !CURL_DISABLE_HTTP && USE_NTLM && NTLM_WB_ENABLED */
+/**
+ * Mark EndOfStream reached and flush ALL data to the client.
+ */
+CURLcode Curl_cw_out_done(struct Curl_easy *data);
 
-#endif /* HEADER_CURL_NTLM_WB_H */
+#endif /* HEADER_CURL_CW_OUT_H */
diff --git a/vendor/curl/lib/dict.c b/vendor/curl/lib/dict.c
index 3172b38290..a26a28b7b2 100644
--- a/vendor/curl/lib/dict.c
+++ b/vendor/curl/lib/dict.c
@@ -76,7 +76,7 @@ static CURLcode dict_do(struct Curl_easy *data, bool *done);
  */
 
 const struct Curl_handler Curl_handler_dict = {
-  "DICT",                               /* scheme */
+  "dict",                               /* scheme */
   ZERO_NULL,                            /* setup_connection */
   dict_do,                              /* do_it */
   ZERO_NULL,                            /* done */
@@ -89,7 +89,8 @@ const struct Curl_handler Curl_handler_dict = {
   ZERO_NULL,                            /* domore_getsock */
   ZERO_NULL,                            /* perform_getsock */
   ZERO_NULL,                            /* disconnect */
-  ZERO_NULL,                            /* readwrite */
+  ZERO_NULL,                            /* write_resp */
+  ZERO_NULL,                            /* write_resp_hd */
   ZERO_NULL,                            /* connection_check */
   ZERO_NULL,                            /* attach connection */
   PORT_DICT,                            /* defport */
@@ -122,10 +123,12 @@ static char *unescape_word(const char *input)
 }
 
 /* sendf() sends formatted data to the server */
-static CURLcode sendf(curl_socket_t sockfd, struct Curl_easy *data,
-                      const char *fmt, ...)
+static CURLcode sendf(struct Curl_easy *data,
+                      const char *fmt, ...) CURL_PRINTF(2, 3);
+
+static CURLcode sendf(struct Curl_easy *data, const char *fmt, ...)
 {
-  ssize_t bytes_written;
+  size_t bytes_written;
   size_t write_len;
   CURLcode result = CURLE_OK;
   char *s;
@@ -143,7 +146,7 @@ static CURLcode sendf(curl_socket_t sockfd, struct Curl_easy *data,
 
   for(;;) {
     /* Write the buffer to the socket */
-    result = Curl_write(data, sockfd, sptr, write_len, &bytes_written);
+    result = Curl_xfer_send(data, sptr, write_len, &bytes_written);
 
     if(result)
       break;
@@ -175,8 +178,6 @@ static CURLcode dict_do(struct Curl_easy *data, bool *done)
   char *nthdef = NULL; /* This is not part of the protocol, but required
                           by RFC 2229 */
   CURLcode result;
-  struct connectdata *conn = data->conn;
-  curl_socket_t sockfd = conn->sock[FIRSTSOCKET];
 
   char *path;
 
@@ -225,7 +226,7 @@ static CURLcode dict_do(struct Curl_easy *data, bool *done)
       goto error;
     }
 
-    result = sendf(sockfd, data,
+    result = sendf(data,
                    "CLIENT " LIBCURL_NAME " " LIBCURL_VERSION "\r\n"
                    "MATCH "
                    "%s "    /* database */
@@ -240,7 +241,7 @@ static CURLcode dict_do(struct Curl_easy *data, bool *done)
       failf(data, "Failed sending DICT request");
       goto error;
     }
-    Curl_setup_transfer(data, FIRSTSOCKET, -1, FALSE, -1); /* no upload */
+    Curl_xfer_setup(data, FIRSTSOCKET, -1, FALSE, -1); /* no upload */
   }
   else if(strncasecompare(path, DICT_DEFINE, sizeof(DICT_DEFINE)-1) ||
           strncasecompare(path, DICT_DEFINE2, sizeof(DICT_DEFINE2)-1) ||
@@ -273,7 +274,7 @@ static CURLcode dict_do(struct Curl_easy *data, bool *done)
       goto error;
     }
 
-    result = sendf(sockfd, data,
+    result = sendf(data,
                    "CLIENT " LIBCURL_NAME " " LIBCURL_VERSION "\r\n"
                    "DEFINE "
                    "%s "     /* database */
@@ -286,7 +287,7 @@ static CURLcode dict_do(struct Curl_easy *data, bool *done)
       failf(data, "Failed sending DICT request");
       goto error;
     }
-    Curl_setup_transfer(data, FIRSTSOCKET, -1, FALSE, -1);
+    Curl_xfer_setup(data, FIRSTSOCKET, -1, FALSE, -1);
   }
   else {
 
@@ -299,7 +300,7 @@ static CURLcode dict_do(struct Curl_easy *data, bool *done)
         if(ppath[i] == ':')
           ppath[i] = ' ';
       }
-      result = sendf(sockfd, data,
+      result = sendf(data,
                      "CLIENT " LIBCURL_NAME " " LIBCURL_VERSION "\r\n"
                      "%s\r\n"
                      "QUIT\r\n", ppath);
@@ -308,7 +309,7 @@ static CURLcode dict_do(struct Curl_easy *data, bool *done)
         goto error;
       }
 
-      Curl_setup_transfer(data, FIRSTSOCKET, -1, FALSE, -1);
+      Curl_xfer_setup(data, FIRSTSOCKET, -1, FALSE, -1);
     }
   }
 
diff --git a/vendor/curl/lib/dllmain.c b/vendor/curl/lib/dllmain.c
new file mode 100644
index 0000000000..41e97b37eb
--- /dev/null
+++ b/vendor/curl/lib/dllmain.c
@@ -0,0 +1,81 @@
+/***************************************************************************
+ *                                  _   _ ____  _
+ *  Project                     ___| | | |  _ \| |
+ *                             / __| | | | |_) | |
+ *                            | (__| |_| |  _ <| |___
+ *                             \___|\___/|_| \_\_____|
+ *
+ * Copyright (C) Daniel Stenberg, , et al.
+ *
+ * This software is licensed as described in the file COPYING, which
+ * you should have received as part of this distribution. The terms
+ * are also available at https://curl.se/docs/copyright.html.
+ *
+ * You may opt to use, copy, modify, merge, publish, distribute and/or sell
+ * copies of the Software, and permit persons to whom the Software is
+ * furnished to do so, under the terms of the COPYING file.
+ *
+ * This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY
+ * KIND, either express or implied.
+ *
+ * SPDX-License-Identifier: curl
+ *
+ ***************************************************************************/
+
+#include "curl_setup.h"
+
+#ifdef USE_OPENSSL
+#include 
+#endif
+
+/* The fourth-to-last include */
+#ifdef __CYGWIN__
+#define WIN32_LEAN_AND_MEAN
+#include 
+#ifdef _WIN32
+#undef _WIN32
+#endif
+#endif
+
+/* The last 3 #include files should be in this order */
+#include "curl_printf.h"
+#include "curl_memory.h"
+#include "memdebug.h"
+
+/* DllMain() must only be defined for Windows and Cygwin DLL builds. */
+#if (defined(_WIN32) || defined(__CYGWIN__)) && !defined(CURL_STATICLIB)
+
+#if defined(USE_OPENSSL) && \
+    !defined(OPENSSL_IS_AWSLC) && \
+    !defined(OPENSSL_IS_BORINGSSL) && \
+    !defined(LIBRESSL_VERSION_NUMBER) && \
+    (OPENSSL_VERSION_NUMBER >= 0x10100000L)
+#define PREVENT_OPENSSL_MEMLEAK
+#endif
+
+#ifdef PREVENT_OPENSSL_MEMLEAK
+BOOL WINAPI DllMain(HINSTANCE hinstDLL, DWORD fdwReason, LPVOID lpvReserved);
+BOOL WINAPI DllMain(HINSTANCE hinstDLL, DWORD fdwReason, LPVOID lpvReserved)
+{
+  (void)hinstDLL;
+  (void)lpvReserved;
+
+  switch(fdwReason) {
+  case DLL_PROCESS_ATTACH:
+    break;
+  case DLL_PROCESS_DETACH:
+    break;
+  case DLL_THREAD_ATTACH:
+    break;
+  case DLL_THREAD_DETACH:
+    /* Call OPENSSL_thread_stop to prevent a memory leak in case OpenSSL is
+       linked statically.
+       https://github.com/curl/curl/issues/12327#issuecomment-1826405944 */
+    OPENSSL_thread_stop();
+    break;
+  }
+  return TRUE;
+}
+#endif /* OpenSSL */
+
+#endif /* DLL build */
diff --git a/vendor/curl/lib/doh.c b/vendor/curl/lib/doh.c
index 7a38eab01f..03317ae27e 100644
--- a/vendor/curl/lib/doh.c
+++ b/vendor/curl/lib/doh.c
@@ -42,9 +42,13 @@
 #include "curl_printf.h"
 #include "curl_memory.h"
 #include "memdebug.h"
+#include "escape.h"
 
 #define DNS_CLASS_IN 0x01
 
+/* local_print_buf truncates if the hex string will be more than this */
+#define LOCAL_PB_HEXMAX 400
+
 #ifndef CURL_DISABLE_VERBOSE_STRINGS
 static const char * const errors[]={
   "",
@@ -69,7 +73,12 @@ static const char *doh_strerror(DOHcode code)
     return errors[code];
   return "bad error code";
 }
-#endif
+
+struct curl_trc_feat Curl_doh_trc = {
+  "DoH",
+  CURL_LOG_LVL_NONE,
+};
+#endif /* !CURL_DISABLE_VERBOSE_STRINGS */
 
 /* @unittest 1655
  */
@@ -182,6 +191,26 @@ doh_write_cb(const void *contents, size_t size, size_t nmemb, void *userp)
   return realsize;
 }
 
+#if defined(USE_HTTPSRR) && defined(CURLDEBUG)
+static void local_print_buf(struct Curl_easy *data,
+                            const char *prefix,
+                            unsigned char *buf, size_t len)
+{
+  unsigned char hexstr[LOCAL_PB_HEXMAX];
+  size_t hlen = LOCAL_PB_HEXMAX;
+  bool truncated = false;
+
+  if(len > (LOCAL_PB_HEXMAX / 2))
+    truncated = true;
+  Curl_hexencode(buf, len, hexstr, hlen);
+  if(!truncated)
+    infof(data, "%s: len=%d, val=%s", prefix, (int)len, hexstr);
+  else
+    infof(data, "%s: len=%d (truncated)val=%s", prefix, (int)len, hexstr);
+  return;
+}
+#endif
+
 /* called from multi.c when this DoH transfer is complete */
 static int doh_done(struct Curl_easy *doh, CURLcode result)
 {
@@ -189,9 +218,9 @@ static int doh_done(struct Curl_easy *doh, CURLcode result)
   struct dohdata *dohp = data->req.doh;
   /* so one of the DoH request done for the 'data' transfer is now complete! */
   dohp->pending--;
-  infof(data, "a DoH request is completed, %u to go", dohp->pending);
+  infof(doh, "a DoH request is completed, %u to go", dohp->pending);
   if(result)
-    infof(data, "DoH request %s", curl_easy_strerror(result));
+    infof(doh, "DoH request %s", curl_easy_strerror(result));
 
   if(!dohp->pending) {
     /* DoH completed */
@@ -218,7 +247,6 @@ static CURLcode dohprobe(struct Curl_easy *data,
                          struct curl_slist *headers)
 {
   struct Curl_easy *doh = NULL;
-  char *nurl = NULL;
   CURLcode result = CURLE_OK;
   timediff_t timeout_ms;
   DOHcode d = doh_encode(host, dnstype, p->dohbuffer, sizeof(p->dohbuffer),
@@ -242,6 +270,10 @@ static CURLcode dohprobe(struct Curl_easy *data,
     /* pass in the struct pointer via a local variable to please coverity and
        the gcc typecheck helpers */
     struct dynbuf *resp = &p->serverdoh;
+    doh->state.internal = true;
+#ifndef CURL_DISABLE_VERBOSE_STRINGS
+    doh->state.feat = &Curl_doh_trc;
+#endif
     ERROR_CHECK_SETOPT(CURLOPT_URL, url);
     ERROR_CHECK_SETOPT(CURLOPT_DEFAULT_PROTOCOL, "https");
     ERROR_CHECK_SETOPT(CURLOPT_WRITEFUNCTION, doh_write_cb);
@@ -251,6 +283,7 @@ static CURLcode dohprobe(struct Curl_easy *data,
     ERROR_CHECK_SETOPT(CURLOPT_HTTPHEADER, headers);
 #ifdef USE_HTTP2
     ERROR_CHECK_SETOPT(CURLOPT_HTTP_VERSION, CURL_HTTP_VERSION_2TLS);
+    ERROR_CHECK_SETOPT(CURLOPT_PIPEWAIT, 1L);
 #endif
 #ifndef CURLDEBUG
     /* enforce HTTPS if not debug */
@@ -263,7 +296,7 @@ static CURLcode dohprobe(struct Curl_easy *data,
     ERROR_CHECK_SETOPT(CURLOPT_SHARE, data->share);
     if(data->set.err && data->set.err != stderr)
       ERROR_CHECK_SETOPT(CURLOPT_STDERR, data->set.err);
-    if(data->set.verbose)
+    if(Curl_trc_ft_is_verbose(data, &Curl_doh_trc))
       ERROR_CHECK_SETOPT(CURLOPT_VERBOSE, 1L);
     if(data->set.no_signal)
       ERROR_CHECK_SETOPT(CURLOPT_NOSIGNAL, 1L);
@@ -307,6 +340,10 @@ static CURLcode dohprobe(struct Curl_easy *data,
       ERROR_CHECK_SETOPT(CURLOPT_SSL_CTX_FUNCTION, data->set.ssl.fsslctx);
     if(data->set.ssl.fsslctxp)
       ERROR_CHECK_SETOPT(CURLOPT_SSL_CTX_DATA, data->set.ssl.fsslctxp);
+    if(data->set.fdebug)
+      ERROR_CHECK_SETOPT(CURLOPT_DEBUGFUNCTION, data->set.fdebug);
+    if(data->set.debugdata)
+      ERROR_CHECK_SETOPT(CURLOPT_DEBUGDATA, data->set.debugdata);
     if(data->set.str[STRING_SSL_EC_CURVES]) {
       ERROR_CHECK_SETOPT(CURLOPT_SSL_EC_CURVES,
                          data->set.str[STRING_SSL_EC_CURVES]);
@@ -334,9 +371,10 @@ static CURLcode dohprobe(struct Curl_easy *data,
     doh->set.dohfor = data; /* identify for which transfer this is done */
     p->easy = doh;
 
-    /* DoH private_data must be null because the user must have a way to
-       distinguish their transfer's handle from DoH handles in user
-       callbacks (ie SSL CTX callback). */
+    /* DoH handles must not inherit private_data. The handles may be passed to
+       the user via callbacks and the user will be able to identify them as
+       internal handles because private data is not set. The user can then set
+       private_data via CURLOPT_PRIVATE if they so choose. */
     DEBUGASSERT(!doh->set.private_data);
 
     if(curl_multi_add_handle(multi, doh))
@@ -344,11 +382,9 @@ static CURLcode dohprobe(struct Curl_easy *data,
   }
   else
     goto error;
-  free(nurl);
   return CURLE_OK;
 
 error:
-  free(nurl);
   Curl_close(&doh);
   return result;
 }
@@ -367,7 +403,13 @@ struct Curl_addrinfo *Curl_doh(struct Curl_easy *data,
   int slot;
   struct dohdata *dohp;
   struct connectdata *conn = data->conn;
-  *waitp = TRUE; /* this never returns synchronously */
+#ifdef USE_HTTPSRR
+  /* for now, this is only used when ECH is enabled */
+# ifdef USE_ECH
+  char *qname = NULL;
+# endif
+#endif
+  *waitp = FALSE;
   (void)hostname;
   (void)port;
 
@@ -375,7 +417,7 @@ struct Curl_addrinfo *Curl_doh(struct Curl_easy *data,
   DEBUGASSERT(conn);
 
   /* start clean, consider allocating this struct on demand */
-  dohp = data->req.doh = calloc(sizeof(struct dohdata), 1);
+  dohp = data->req.doh = calloc(1, sizeof(struct dohdata));
   if(!dohp)
     return NULL;
 
@@ -396,7 +438,7 @@ struct Curl_addrinfo *Curl_doh(struct Curl_easy *data,
     goto error;
   dohp->pending++;
 
-#ifdef ENABLE_IPV6
+#ifdef USE_IPV6
   if((conn->ip_version != CURL_IPRESOLVE_V4) && Curl_ipv6works(data)) {
     /* create IPv6 DoH request */
     result = dohprobe(data, &dohp->probe[DOH_PROBE_SLOT_IPADDR_V6],
@@ -407,12 +449,45 @@ struct Curl_addrinfo *Curl_doh(struct Curl_easy *data,
     dohp->pending++;
   }
 #endif
+
+#ifdef USE_HTTPSRR
+  /*
+   * TODO: Figure out the conditions under which we want to make
+   * a request for an HTTPS RR when we are not doing ECH. For now,
+   * making this request breaks a bunch of DoH tests, e.g. test2100,
+   * where the additional request doesn't match the pre-cooked data
+   * files, so there's a bit of work attached to making the request
+   * in a non-ECH use-case. For the present, we'll only make the
+   * request when ECH is enabled in the build and is being used for
+   * the curl operation.
+   */
+# ifdef USE_ECH
+  if(data->set.tls_ech & CURLECH_ENABLE
+     || data->set.tls_ech & CURLECH_HARD) {
+    if(port == 443)
+      qname = strdup(hostname);
+    else
+      qname = aprintf("_%d._https.%s", port, hostname);
+    if(!qname)
+      goto error;
+    result = dohprobe(data, &dohp->probe[DOH_PROBE_SLOT_HTTPS],
+                      DNS_TYPE_HTTPS, qname, data->set.str[STRING_DOH],
+                      data->multi, dohp->headers);
+    free(qname);
+    if(result)
+      goto error;
+    dohp->pending++;
+  }
+# endif
+#endif
+  *waitp = TRUE; /* this never returns synchronously */
   return NULL;
 
 error:
   curl_slist_free_all(dohp->headers);
   data->req.doh->headers = NULL;
   for(slot = 0; slot < DOH_PROBE_SLOTS; slot++) {
+    (void)curl_multi_remove_handle(data->multi, dohp->probe[slot].easy);
     Curl_close(&dohp->probe[slot].easy);
   }
   Curl_safefree(data->req.doh);
@@ -438,7 +513,7 @@ static DOHcode skipqname(const unsigned char *doh, size_t dohlen,
       return DOH_DNS_BAD_LABEL;
     if(dohlen < (*indexp + 1 + length))
       return DOH_DNS_OUT_OF_RANGE;
-    *indexp += 1 + length;
+    *indexp += (unsigned int)(1 + length);
   } while(length);
   return DOH_OK;
 }
@@ -450,14 +525,15 @@ static unsigned short get16bit(const unsigned char *doh, int index)
 
 static unsigned int get32bit(const unsigned char *doh, int index)
 {
-   /* make clang and gcc optimize this to bswap by incrementing
-      the pointer first. */
-   doh += index;
-
-   /* avoid undefined behavior by casting to unsigned before shifting
-      24 bits, possibly into the sign bit. codegen is same, but
-      ub sanitizer won't be upset */
-  return ( (unsigned)doh[0] << 24) | (doh[1] << 16) |(doh[2] << 8) | doh[3];
+  /* make clang and gcc optimize this to bswap by incrementing
+     the pointer first. */
+  doh += index;
+
+  /* avoid undefined behavior by casting to unsigned before shifting
+     24 bits, possibly into the sign bit. codegen is same, but
+     ub sanitizer won't be upset */
+  return ((unsigned)doh[0] << 24) | ((unsigned)doh[1] << 16) |
+         ((unsigned)doh[2] << 8) | doh[3];
 }
 
 static DOHcode store_a(const unsigned char *doh, int index, struct dohentry *d)
@@ -486,6 +562,25 @@ static DOHcode store_aaaa(const unsigned char *doh,
   return DOH_OK;
 }
 
+#ifdef USE_HTTPSRR
+static DOHcode store_https(const unsigned char *doh,
+                           int index,
+                           struct dohentry *d,
+                           uint16_t len)
+{
+  /* silently ignore RRs over the limit */
+  if(d->numhttps_rrs < DOH_MAX_HTTPS) {
+    struct dohhttps_rr *h = &d->https_rrs[d->numhttps_rrs];
+    h->val = Curl_memdup(&doh[index], len);
+    if(!h->val)
+      return DOH_OUT_OF_MEM;
+    h->len = len;
+    d->numhttps_rrs++;
+  }
+  return DOH_OK;
+}
+#endif
+
 static DOHcode store_cname(const unsigned char *doh,
                            size_t dohlen,
                            unsigned int index,
@@ -548,7 +643,8 @@ static DOHcode rdata(const unsigned char *doh,
   /* RDATA
      - A (TYPE 1):  4 bytes
      - AAAA (TYPE 28): 16 bytes
-     - NS (TYPE 2): N bytes */
+     - NS (TYPE 2): N bytes
+     - HTTPS (TYPE 65): N bytes */
   DOHcode rc;
 
   switch(type) {
@@ -566,6 +662,13 @@ static DOHcode rdata(const unsigned char *doh,
     if(rc)
       return rc;
     break;
+#ifdef USE_HTTPSRR
+  case DNS_TYPE_HTTPS:
+    rc = store_https(doh, index, d, rdlength);
+    if(rc)
+      return rc;
+    break;
+#endif
   case DNS_TYPE_CNAME:
     rc = store_cname(doh, dohlen, index, d);
     if(rc)
@@ -722,7 +825,11 @@ UNITTEST DOHcode doh_decode(const unsigned char *doh,
   if(index != dohlen)
     return DOH_DNS_MALFORMAT; /* something is wrong */
 
+#ifdef USE_HTTTPS
+  if((type != DNS_TYPE_NS) && !d->numcname && !d->numaddr && !d->numhttps_rrs)
+#else
   if((type != DNS_TYPE_NS) && !d->numcname && !d->numaddr)
+#endif
     /* nothing stored! */
     return DOH_NO_CONTENT;
 
@@ -734,11 +841,11 @@ static void showdoh(struct Curl_easy *data,
                     const struct dohentry *d)
 {
   int i;
-  infof(data, "TTL: %u seconds", d->ttl);
+  infof(data, "[DoH] TTL: %u seconds", d->ttl);
   for(i = 0; i < d->numaddr; i++) {
     const struct dohaddr *a = &d->addr[i];
     if(a->type == DNS_TYPE_A) {
-      infof(data, "DoH A: %u.%u.%u.%u",
+      infof(data, "[DoH] A: %u.%u.%u.%u",
             a->ip.v4[0], a->ip.v4[1],
             a->ip.v4[2], a->ip.v4[3]);
     }
@@ -747,9 +854,9 @@ static void showdoh(struct Curl_easy *data,
       char buffer[128];
       char *ptr;
       size_t len;
-      msnprintf(buffer, 128, "DoH AAAA: ");
-      ptr = &buffer[10];
-      len = 118;
+      len = msnprintf(buffer, 128, "[DoH] AAAA: ");
+      ptr = &buffer[len];
+      len = sizeof(buffer) - len;
       for(j = 0; j < 16; j += 2) {
         size_t l;
         msnprintf(ptr, len, "%s%02x%02x", j?":":"", d->addr[i].ip.v6[j],
@@ -761,6 +868,16 @@ static void showdoh(struct Curl_easy *data,
       infof(data, "%s", buffer);
     }
   }
+#ifdef USE_HTTPSRR
+  for(i = 0; i < d->numhttps_rrs; i++) {
+# ifdef CURLDEBUG
+    local_print_buf(data, "DoH HTTPS",
+                    d->https_rrs[i].val, d->https_rrs[i].len);
+# else
+    infof(data, "DoH HTTPS RR: length %d", d->https_rrs[i].len);
+# endif
+  }
+#endif
   for(i = 0; i < d->numcname; i++) {
     infof(data, "CNAME: %s", Curl_dyn_ptr(&d->cname[i]));
   }
@@ -782,29 +899,30 @@ static void showdoh(struct Curl_easy *data,
  * must be an associated call later to Curl_freeaddrinfo().
  */
 
-static struct Curl_addrinfo *
-doh2ai(const struct dohentry *de, const char *hostname, int port)
+static CURLcode doh2ai(const struct dohentry *de, const char *hostname,
+                       int port, struct Curl_addrinfo **aip)
 {
   struct Curl_addrinfo *ai;
   struct Curl_addrinfo *prevai = NULL;
   struct Curl_addrinfo *firstai = NULL;
   struct sockaddr_in *addr;
-#ifdef ENABLE_IPV6
+#ifdef USE_IPV6
   struct sockaddr_in6 *addr6;
 #endif
   CURLcode result = CURLE_OK;
   int i;
   size_t hostlen = strlen(hostname) + 1; /* include null-terminator */
 
-  if(!de)
-    /* no input == no output! */
-    return NULL;
+  DEBUGASSERT(de);
+
+  if(!de->numaddr)
+    return CURLE_COULDNT_RESOLVE_HOST;
 
   for(i = 0; i < de->numaddr; i++) {
     size_t ss_size;
     CURL_SA_FAMILY_T addrtype;
     if(de->addr[i].type == DNS_TYPE_AAAA) {
-#ifndef ENABLE_IPV6
+#ifndef USE_IPV6
       /* we can't handle IPv6 addresses */
       continue;
 #else
@@ -853,7 +971,7 @@ doh2ai(const struct dohentry *de, const char *hostname, int port)
       addr->sin_port = htons((unsigned short)port);
       break;
 
-#ifdef ENABLE_IPV6
+#ifdef USE_IPV6
     case AF_INET6:
       addr6 = (void *)ai->ai_addr; /* storage area for this info */
       DEBUGASSERT(sizeof(struct in6_addr) == sizeof(de->addr[i].ip.v6));
@@ -871,14 +989,26 @@ doh2ai(const struct dohentry *de, const char *hostname, int port)
     Curl_freeaddrinfo(firstai);
     firstai = NULL;
   }
+  *aip = firstai;
 
-  return firstai;
+  return result;
 }
 
 #ifndef CURL_DISABLE_VERBOSE_STRINGS
 static const char *type2name(DNStype dnstype)
 {
-  return (dnstype == DNS_TYPE_A)?"A":"AAAA";
+  switch(dnstype) {
+    case DNS_TYPE_A:
+      return "A";
+    case DNS_TYPE_AAAA:
+      return "AAAA";
+#ifdef USE_HTTPSRR
+    case DNS_TYPE_HTTPS:
+      return "HTTPS";
+#endif
+    default:
+       return "unknown";
+  }
 }
 #endif
 
@@ -888,8 +1018,270 @@ UNITTEST void de_cleanup(struct dohentry *d)
   for(i = 0; i < d->numcname; i++) {
     Curl_dyn_free(&d->cname[i]);
   }
+#ifdef USE_HTTPSRR
+  for(i = 0; i < d->numhttps_rrs; i++)
+    free(d->https_rrs[i].val);
+#endif
 }
 
+#ifdef USE_HTTPSRR
+
+/*
+ * @brief decode the DNS name in a binary RRData
+ * @param buf points to the buffer (in/out)
+ * @param remaining points to the remaining buffer length (in/out)
+ * @param dnsname returns the string form name on success
+ * @return is 1 for success, error otherwise
+ *
+ * The encoding here is defined in
+ * https://tools.ietf.org/html/rfc1035#section-3.1
+ *
+ * The input buffer pointer will be modified so it points to
+ * just after the end of the DNS name encoding on output. (And
+ * that's why it's an "unsigned char **" :-)
+ */
+static CURLcode local_decode_rdata_name(unsigned char **buf, size_t *remaining,
+                                        char **dnsname)
+{
+  unsigned char *cp = NULL;
+  int rem = 0;
+  unsigned char clen = 0; /* chunk len */
+  struct dynbuf thename;
+
+  DEBUGASSERT(buf && remaining && dnsname);
+  if(!buf || !remaining || !dnsname)
+    return CURLE_OUT_OF_MEMORY;
+  rem = (int)*remaining;
+  if(rem <= 0) {
+    Curl_dyn_free(&thename);
+    return CURLE_OUT_OF_MEMORY;
+  }
+  Curl_dyn_init(&thename, CURL_MAXLEN_host_name);
+  cp = *buf;
+  clen = *cp++;
+  if(clen == 0) {
+    /* special case - return "." as name */
+    if(Curl_dyn_addn(&thename, ".", 1))
+      return CURLE_OUT_OF_MEMORY;
+  }
+  while(clen) {
+    if(clen >= rem) {
+      Curl_dyn_free(&thename);
+      return CURLE_OUT_OF_MEMORY;
+    }
+    if(Curl_dyn_addn(&thename, cp, clen) ||
+       Curl_dyn_addn(&thename, ".", 1))
+      return CURLE_TOO_LARGE;
+
+    cp += clen;
+    rem -= (clen + 1);
+    if(rem <= 0) {
+      Curl_dyn_free(&thename);
+      return CURLE_OUT_OF_MEMORY;
+    }
+    clen = *cp++;
+  }
+  *buf = cp;
+  *remaining = rem - 1;
+  *dnsname = Curl_dyn_ptr(&thename);
+  return CURLE_OK;
+}
+
+static CURLcode local_decode_rdata_alpn(unsigned char *rrval, size_t len,
+                                        char **alpns)
+{
+  /*
+   * spec here is as per draft-ietf-dnsop-svcb-https, section-7.1.1
+   * encoding is catenated list of strings each preceded by a one
+   * octet length
+   * output is comma-sep list of the strings
+   * implementations may or may not handle quoting of comma within
+   * string values, so we might see a comma within the wire format
+   * version of a string, in which case we'll precede that by a
+   * backslash - same goes for a backslash character, and of course
+   * we need to use two backslashes in strings when we mean one;-)
+   */
+  int remaining = (int) len;
+  char *oval;
+  size_t i;
+  unsigned char *cp = rrval;
+  struct dynbuf dval;
+
+  if(!alpns)
+    return CURLE_OUT_OF_MEMORY;
+  Curl_dyn_init(&dval, DYN_DOH_RESPONSE);
+  remaining = (int)len;
+  cp = rrval;
+  while(remaining > 0) {
+    size_t tlen = (size_t) *cp++;
+
+    /* if not 1st time, add comma */
+    if(remaining != (int)len && Curl_dyn_addn(&dval, ",", 1))
+      goto err;
+    remaining--;
+    if(tlen > (size_t)remaining)
+      goto err;
+    /* add escape char if needed, clunky but easier to read */
+    for(i = 0; i != tlen; i++) {
+      if('\\' == *cp || ',' == *cp) {
+        if(Curl_dyn_addn(&dval, "\\", 1))
+          goto err;
+      }
+      if(Curl_dyn_addn(&dval, cp++, 1))
+        goto err;
+    }
+    remaining -= (int)tlen;
+  }
+  /* this string is always null terminated */
+  oval = Curl_dyn_ptr(&dval);
+  if(!oval)
+    goto err;
+  *alpns = oval;
+  return CURLE_OK;
+err:
+  Curl_dyn_free(&dval);
+  return CURLE_BAD_CONTENT_ENCODING;
+}
+
+#ifdef CURLDEBUG
+static CURLcode test_alpn_escapes(void)
+{
+  /* we'll use an example from draft-ietf-dnsop-svcb, figure 10 */
+  static unsigned char example[] = {
+    0x08,                                           /* length 8 */
+    0x66, 0x5c, 0x6f, 0x6f, 0x2c, 0x62, 0x61, 0x72, /* value "f\\oo,bar" */
+    0x02,                                           /* length 2 */
+    0x68, 0x32                                      /* value "h2" */
+  };
+  size_t example_len = sizeof(example);
+  char *aval = NULL;
+  static const char *expected = "f\\\\oo\\,bar,h2";
+
+  if(local_decode_rdata_alpn(example, example_len, &aval) != CURLE_OK)
+    return CURLE_BAD_CONTENT_ENCODING;
+  if(strlen(aval) != strlen(expected))
+    return CURLE_BAD_CONTENT_ENCODING;
+  if(memcmp(aval, expected, strlen(aval)))
+    return CURLE_BAD_CONTENT_ENCODING;
+  return CURLE_OK;
+}
+#endif
+
+static CURLcode Curl_doh_decode_httpsrr(unsigned char *rrval, size_t len,
+                                        struct Curl_https_rrinfo **hrr)
+{
+  size_t remaining = len;
+  unsigned char *cp = rrval;
+  uint16_t pcode = 0, plen = 0;
+  struct Curl_https_rrinfo *lhrr = NULL;
+  char *dnsname = NULL;
+
+#ifdef CURLDEBUG
+  /* a few tests of escaping, shouldn't be here but ok for now */
+  if(test_alpn_escapes() != CURLE_OK)
+    return CURLE_OUT_OF_MEMORY;
+#endif
+  lhrr = calloc(1, sizeof(struct Curl_https_rrinfo));
+  if(!lhrr)
+    return CURLE_OUT_OF_MEMORY;
+  lhrr->val = Curl_memdup(rrval, len);
+  if(!lhrr->val)
+    goto err;
+  lhrr->len = len;
+  if(remaining <= 2)
+    goto err;
+  lhrr->priority = (uint16_t)((cp[0] << 8) + cp[1]);
+  cp += 2;
+  remaining -= (uint16_t)2;
+  if(local_decode_rdata_name(&cp, &remaining, &dnsname) != CURLE_OK)
+    goto err;
+  lhrr->target = dnsname;
+  while(remaining >= 4) {
+    pcode = (uint16_t)((*cp << 8) + (*(cp + 1)));
+    cp += 2;
+    plen = (uint16_t)((*cp << 8) + (*(cp + 1)));
+    cp += 2;
+    remaining -= 4;
+    if(pcode == HTTPS_RR_CODE_ALPN) {
+      if(local_decode_rdata_alpn(cp, plen, &lhrr->alpns) != CURLE_OK)
+        goto err;
+    }
+    if(pcode == HTTPS_RR_CODE_NO_DEF_ALPN)
+      lhrr->no_def_alpn = TRUE;
+    else if(pcode == HTTPS_RR_CODE_IPV4) {
+      lhrr->ipv4hints = Curl_memdup(cp, plen);
+      if(!lhrr->ipv4hints)
+        goto err;
+      lhrr->ipv4hints_len = (size_t)plen;
+    }
+    else if(pcode == HTTPS_RR_CODE_ECH) {
+      lhrr->echconfiglist = Curl_memdup(cp, plen);
+      if(!lhrr->echconfiglist)
+        goto err;
+      lhrr->echconfiglist_len = (size_t)plen;
+    }
+    else if(pcode == HTTPS_RR_CODE_IPV6) {
+      lhrr->ipv6hints = Curl_memdup(cp, plen);
+      if(!lhrr->ipv6hints)
+        goto err;
+      lhrr->ipv6hints_len = (size_t)plen;
+    }
+    if(plen > 0 && plen <= remaining) {
+      cp += plen;
+      remaining -= plen;
+    }
+  }
+  DEBUGASSERT(!remaining);
+  *hrr = lhrr;
+  return CURLE_OK;
+err:
+  if(lhrr) {
+    free(lhrr->target);
+    free(lhrr->echconfiglist);
+    free(lhrr->val);
+    free(lhrr);
+  }
+  return CURLE_OUT_OF_MEMORY;
+}
+
+# ifdef CURLDEBUG
+static void local_print_httpsrr(struct Curl_easy *data,
+                                struct Curl_https_rrinfo *hrr)
+{
+  DEBUGASSERT(hrr);
+  infof(data, "HTTPS RR: priority %d, target: %s",
+        hrr->priority, hrr->target);
+  if(hrr->alpns)
+    infof(data, "HTTPS RR: alpns %s", hrr->alpns);
+  else
+    infof(data, "HTTPS RR: no alpns");
+  if(hrr->no_def_alpn)
+    infof(data, "HTTPS RR: no_def_alpn set");
+  else
+    infof(data, "HTTPS RR: no_def_alpn not set");
+  if(hrr->ipv4hints) {
+    local_print_buf(data, "HTTPS RR: ipv4hints",
+                    hrr->ipv4hints, hrr->ipv4hints_len);
+  }
+  else
+    infof(data, "HTTPS RR: no ipv4hints");
+  if(hrr->echconfiglist) {
+    local_print_buf(data, "HTTPS RR: ECHConfigList",
+                    hrr->echconfiglist, hrr->echconfiglist_len);
+  }
+  else
+    infof(data, "HTTPS RR: no ECHConfigList");
+  if(hrr->ipv6hints) {
+    local_print_buf(data, "HTTPS RR: ipv6hint",
+                    hrr->ipv6hints, hrr->ipv6hints_len);
+  }
+  else
+    infof(data, "HTTPS RR: no ipv6hints");
+  return;
+}
+# endif
+#endif
+
 CURLcode Curl_doh_is_resolved(struct Curl_easy *data,
                               struct Curl_dns_entry **dnsp)
 {
@@ -906,9 +1298,15 @@ CURLcode Curl_doh_is_resolved(struct Curl_easy *data,
       CURLE_COULDNT_RESOLVE_HOST;
   }
   else if(!dohp->pending) {
+#ifndef USE_HTTPSRR
     DOHcode rc[DOH_PROBE_SLOTS] = {
       DOH_OK, DOH_OK
     };
+#else
+    DOHcode rc[DOH_PROBE_SLOTS] = {
+      DOH_OK, DOH_OK, DOH_OK
+    };
+#endif
     struct dohentry de;
     int slot;
     /* remove DoH handles from multi handle and close them */
@@ -927,10 +1325,12 @@ CURLcode Curl_doh_is_resolved(struct Curl_easy *data,
                             p->dnstype,
                             &de);
       Curl_dyn_free(&p->serverdoh);
+#ifndef CURL_DISABLE_VERBOSE_STRINGS
       if(rc[slot]) {
         infof(data, "DoH: %s type %s for %s", doh_strerror(rc[slot]),
               type2name(p->dnstype), dohp->host);
       }
+#endif
     } /* next slot */
 
     result = CURLE_COULDNT_RESOLVE_HOST; /* until we know better */
@@ -939,13 +1339,16 @@ CURLcode Curl_doh_is_resolved(struct Curl_easy *data,
       struct Curl_dns_entry *dns;
       struct Curl_addrinfo *ai;
 
-      infof(data, "DoH Host name: %s", dohp->host);
-      showdoh(data, &de);
 
-      ai = doh2ai(&de, dohp->host, dohp->port);
-      if(!ai) {
+      if(Curl_trc_ft_is_verbose(data, &Curl_doh_trc)) {
+        infof(data, "[DoH] Host name: %s", dohp->host);
+        showdoh(data, &de);
+      }
+
+      result = doh2ai(&de, dohp->host, dohp->port, &ai);
+      if(result) {
         de_cleanup(&de);
-        return CURLE_OUT_OF_MEMORY;
+        return result;
       }
 
       if(data->share)
@@ -969,6 +1372,22 @@ CURLcode Curl_doh_is_resolved(struct Curl_easy *data,
     } /* address processing done */
 
     /* Now process any build-specific attributes retrieved from DNS */
+#ifdef USE_HTTPSRR
+    if(de.numhttps_rrs > 0 && result == CURLE_OK && *dnsp) {
+      struct Curl_https_rrinfo *hrr = NULL;
+      result = Curl_doh_decode_httpsrr(de.https_rrs->val, de.https_rrs->len,
+                                       &hrr);
+      if(result) {
+        infof(data, "Failed to decode HTTPS RR");
+        return result;
+      }
+      infof(data, "Some HTTPS RR to process");
+# ifdef CURLDEBUG
+      local_print_httpsrr(data, hrr);
+# endif
+      (*dnsp)->hinfo = hrr;
+    }
+#endif
 
     /* All done */
     de_cleanup(&de);
diff --git a/vendor/curl/lib/doh.h b/vendor/curl/lib/doh.h
index 7d7b694f33..bb881ecc50 100644
--- a/vendor/curl/lib/doh.h
+++ b/vendor/curl/lib/doh.h
@@ -26,6 +26,9 @@
 
 #include "urldata.h"
 #include "curl_addrinfo.h"
+#ifdef USE_HTTPSRR
+# include 
+#endif
 
 #ifndef CURL_DISABLE_DOH
 
@@ -51,7 +54,8 @@ typedef enum {
   DNS_TYPE_NS = 2,
   DNS_TYPE_CNAME = 5,
   DNS_TYPE_AAAA = 28,
-  DNS_TYPE_DNAME = 39           /* RFC6672 */
+  DNS_TYPE_DNAME = 39,           /* RFC6672 */
+  DNS_TYPE_HTTPS = 65
 } DNStype;
 
 /* one of these for each DoH request */
@@ -84,10 +88,9 @@ struct Curl_addrinfo *Curl_doh(struct Curl_easy *data,
 CURLcode Curl_doh_is_resolved(struct Curl_easy *data,
                               struct Curl_dns_entry **dns);
 
-int Curl_doh_getsock(struct connectdata *conn, curl_socket_t *socks);
-
 #define DOH_MAX_ADDR 24
 #define DOH_MAX_CNAME 4
+#define DOH_MAX_HTTPS 4
 
 struct dohaddr {
   int type;
@@ -97,12 +100,44 @@ struct dohaddr {
   } ip;
 };
 
+#ifdef USE_HTTPSRR
+
+/*
+ * These are the code points for DNS wire format SvcParams as
+ * per draft-ietf-dnsop-svcb-https
+ * Not all are supported now, and even those that are may need
+ * more work in future to fully support the spec.
+ */
+#define HTTPS_RR_CODE_ALPN            0x01
+#define HTTPS_RR_CODE_NO_DEF_ALPN     0x02
+#define HTTPS_RR_CODE_PORT            0x03
+#define HTTPS_RR_CODE_IPV4            0x04
+#define HTTPS_RR_CODE_ECH             0x05
+#define HTTPS_RR_CODE_IPV6            0x06
+
+/*
+ * These may need escaping when found within an alpn string
+ * value.
+ */
+#define COMMA_CHAR                    ','
+#define BACKSLASH_CHAR                '\\'
+
+struct dohhttps_rr {
+  uint16_t len; /* raw encoded length */
+  unsigned char *val; /* raw encoded octets */
+};
+#endif
+
 struct dohentry {
   struct dynbuf cname[DOH_MAX_CNAME];
   struct dohaddr addr[DOH_MAX_ADDR];
   int numaddr;
   unsigned int ttl;
   int numcname;
+#ifdef USE_HTTPSRR
+  struct dohhttps_rr https_rrs[DOH_MAX_HTTPS];
+  int numhttps_rrs;
+#endif
 };
 
 
@@ -120,6 +155,8 @@ void de_init(struct dohentry *d);
 void de_cleanup(struct dohentry *d);
 #endif
 
+extern struct curl_trc_feat Curl_doh_trc;
+
 #else /* if DoH is disabled */
 #define Curl_doh(a,b,c,d) NULL
 #define Curl_doh_is_resolved(x,y) CURLE_COULDNT_RESOLVE_HOST
diff --git a/vendor/curl/lib/dynbuf.c b/vendor/curl/lib/dynbuf.c
index 0c9c491aeb..3b62eaf8a4 100644
--- a/vendor/curl/lib/dynbuf.c
+++ b/vendor/curl/lib/dynbuf.c
@@ -77,10 +77,11 @@ static CURLcode dyn_nappend(struct dynbuf *s,
   DEBUGASSERT(indx < s->toobig);
   DEBUGASSERT(!s->leng || s->bufr);
   DEBUGASSERT(a <= s->toobig);
+  DEBUGASSERT(!len || mem);
 
   if(fit > s->toobig) {
     Curl_dyn_free(s);
-    return CURLE_OUT_OF_MEMORY;
+    return CURLE_TOO_LARGE;
   }
   else if(!a) {
     DEBUGASSERT(!indx);
@@ -174,10 +175,12 @@ CURLcode Curl_dyn_addn(struct dynbuf *s, const void *mem, size_t len)
  */
 CURLcode Curl_dyn_add(struct dynbuf *s, const char *str)
 {
-  size_t n = strlen(str);
+  size_t n;
+  DEBUGASSERT(str);
   DEBUGASSERT(s);
   DEBUGASSERT(s->init == DYNINIT);
   DEBUGASSERT(!s->leng || s->bufr);
+  n = strlen(str);
   return dyn_nappend(s, (unsigned char *)str, n);
 }
 
@@ -191,10 +194,14 @@ CURLcode Curl_dyn_vaddf(struct dynbuf *s, const char *fmt, va_list ap)
   DEBUGASSERT(s);
   DEBUGASSERT(s->init == DYNINIT);
   DEBUGASSERT(!s->leng || s->bufr);
+  DEBUGASSERT(fmt);
   rc = Curl_dyn_vprintf(s, fmt, ap);
 
   if(!rc)
     return CURLE_OK;
+  else if(rc == MERR_TOO_LARGE)
+    return CURLE_TOO_LARGE;
+  return CURLE_OUT_OF_MEMORY;
 #else
   char *str;
   str = vaprintf(fmt, ap); /* this allocs a new string to append */
@@ -206,8 +213,8 @@ CURLcode Curl_dyn_vaddf(struct dynbuf *s, const char *fmt, va_list ap)
   }
   /* If we failed, we cleanup the whole buffer and return error */
   Curl_dyn_free(s);
-#endif
   return CURLE_OUT_OF_MEMORY;
+#endif
 }
 
 /*
diff --git a/vendor/curl/lib/dynbuf.h b/vendor/curl/lib/dynbuf.h
index 6291eabd37..7dbaab886e 100644
--- a/vendor/curl/lib/dynbuf.h
+++ b/vendor/curl/lib/dynbuf.h
@@ -61,9 +61,9 @@ CURLcode Curl_dyn_addn(struct dynbuf *s, const void *mem, size_t len)
 CURLcode Curl_dyn_add(struct dynbuf *s, const char *str)
   WARN_UNUSED_RESULT;
 CURLcode Curl_dyn_addf(struct dynbuf *s, const char *fmt, ...)
-  WARN_UNUSED_RESULT;
+  WARN_UNUSED_RESULT CURL_PRINTF(2, 3);
 CURLcode Curl_dyn_vaddf(struct dynbuf *s, const char *fmt, va_list ap)
-  WARN_UNUSED_RESULT;
+  WARN_UNUSED_RESULT CURL_PRINTF(2, 0);
 void Curl_dyn_reset(struct dynbuf *s);
 CURLcode Curl_dyn_tail(struct dynbuf *s, size_t trail);
 CURLcode Curl_dyn_setlen(struct dynbuf *s, size_t set);
@@ -89,4 +89,5 @@ int Curl_dyn_vprintf(struct dynbuf *dyn, const char *format, va_list ap_save);
 #define DYN_H1_TRAILER      4096
 #define DYN_PINGPPONG_CMD   (64*1024)
 #define DYN_IMAP_CMD        (64*1024)
+#define DYN_MQTT_RECV       (64*1024)
 #endif
diff --git a/vendor/curl/lib/dynhds.c b/vendor/curl/lib/dynhds.c
index 007dfc588c..d7548959b2 100644
--- a/vendor/curl/lib/dynhds.c
+++ b/vendor/curl/lib/dynhds.c
@@ -27,6 +27,10 @@
 #include "strcase.h"
 
 /* The last 3 #include files should be in this order */
+#ifdef USE_NGHTTP2
+#include 
+#include 
+#endif /* USE_NGHTTP2 */
 #include "curl_printf.h"
 #include "curl_memory.h"
 #include "memdebug.h"
@@ -344,6 +348,8 @@ size_t Curl_dynhds_cremove(struct dynhds *dynhds, const char *name)
   return Curl_dynhds_remove(dynhds, name, strlen(name));
 }
 
+#endif
+
 CURLcode Curl_dynhds_h1_dprint(struct dynhds *dynhds, struct dynbuf *dbuf)
 {
   CURLcode result = CURLE_OK;
@@ -363,4 +369,28 @@ CURLcode Curl_dynhds_h1_dprint(struct dynhds *dynhds, struct dynbuf *dbuf)
   return result;
 }
 
-#endif
+#ifdef USE_NGHTTP2
+
+nghttp2_nv *Curl_dynhds_to_nva(struct dynhds *dynhds, size_t *pcount)
+{
+  nghttp2_nv *nva = calloc(1, sizeof(nghttp2_nv) * dynhds->hds_len);
+  size_t i;
+
+  *pcount = 0;
+  if(!nva)
+    return NULL;
+
+  for(i = 0; i < dynhds->hds_len; ++i) {
+    struct dynhds_entry *e = dynhds->hds[i];
+    DEBUGASSERT(e);
+    nva[i].name = (unsigned char *)e->name;
+    nva[i].namelen = e->namelen;
+    nva[i].value = (unsigned char *)e->value;
+    nva[i].valuelen = e->valuelen;
+    nva[i].flags = NGHTTP2_NV_FLAG_NONE;
+  }
+  *pcount = dynhds->hds_len;
+  return nva;
+}
+
+#endif /* USE_NGHTTP2 */
diff --git a/vendor/curl/lib/dynhds.h b/vendor/curl/lib/dynhds.h
index 8a053480e9..3b536000a2 100644
--- a/vendor/curl/lib/dynhds.h
+++ b/vendor/curl/lib/dynhds.h
@@ -171,4 +171,13 @@ CURLcode Curl_dynhds_h1_add_line(struct dynhds *dynhds,
  */
 CURLcode Curl_dynhds_h1_dprint(struct dynhds *dynhds, struct dynbuf *dbuf);
 
+#ifdef USE_NGHTTP2
+
+#include 
+#include 
+
+nghttp2_nv *Curl_dynhds_to_nva(struct dynhds *dynhds, size_t *pcount);
+
+#endif /* USE_NGHTTP2 */
+
 #endif /* HEADER_CURL_DYNHDS_H */
diff --git a/vendor/curl/lib/easy.c b/vendor/curl/lib/easy.c
index 16bbd35251..a04dbedd87 100644
--- a/vendor/curl/lib/easy.c
+++ b/vendor/curl/lib/easy.c
@@ -112,7 +112,7 @@ static curl_simple_lock s_lock = CURL_SIMPLE_LOCK_INIT;
 #define system_strdup strdup
 #endif
 
-#if defined(_MSC_VER) && defined(_DLL) && !defined(__POCC__)
+#if defined(_MSC_VER) && defined(_DLL)
 #  pragma warning(disable:4232) /* MSVC extension, dllimport identity */
 #endif
 
@@ -125,11 +125,11 @@ curl_free_callback Curl_cfree = (curl_free_callback)free;
 curl_realloc_callback Curl_crealloc = (curl_realloc_callback)realloc;
 curl_strdup_callback Curl_cstrdup = (curl_strdup_callback)system_strdup;
 curl_calloc_callback Curl_ccalloc = (curl_calloc_callback)calloc;
-#if defined(WIN32) && defined(UNICODE)
+#if defined(_WIN32) && defined(UNICODE)
 curl_wcsdup_callback Curl_cwcsdup = Curl_wcsdup;
 #endif
 
-#if defined(_MSC_VER) && defined(_DLL) && !defined(__POCC__)
+#if defined(_MSC_VER) && defined(_DLL)
 #  pragma warning(default:4232) /* MSVC extension, dllimport identity */
 #endif
 
@@ -153,7 +153,7 @@ static CURLcode global_init(long flags, bool memoryfuncs)
     Curl_crealloc = (curl_realloc_callback)realloc;
     Curl_cstrdup = (curl_strdup_callback)system_strdup;
     Curl_ccalloc = (curl_calloc_callback)calloc;
-#if defined(WIN32) && defined(UNICODE)
+#if defined(_WIN32) && defined(UNICODE)
     Curl_cwcsdup = (curl_wcsdup_callback)_wcsdup;
 #endif
   }
@@ -188,18 +188,10 @@ static CURLcode global_init(long flags, bool memoryfuncs)
     goto fail;
   }
 
-#if defined(USE_SSH)
   if(Curl_ssh_init()) {
+    DEBUGF(fprintf(stderr, "Error: Curl_ssh_init failed\n"));
     goto fail;
   }
-#endif
-
-#ifdef USE_WOLFSSH
-  if(WS_SUCCESS != wolfSSH_Init()) {
-    DEBUGF(fprintf(stderr, "Error: wolfSSH_Init failed\n"));
-    return CURLE_FAILED_INIT;
-  }
-#endif
 
   easy_init_flags = flags;
 
@@ -295,7 +287,7 @@ void curl_global_cleanup(void)
   Curl_ssl_cleanup();
   Curl_resolver_global_cleanup();
 
-#ifdef WIN32
+#ifdef _WIN32
   Curl_win32_cleanup(easy_init_flags);
 #endif
 
@@ -303,9 +295,6 @@ void curl_global_cleanup(void)
 
   Curl_ssh_cleanup();
 
-#ifdef USE_WOLFSSH
-  (void)wolfSSH_Cleanup();
-#endif
 #ifdef DEBUGBUILD
   free(leakpointer);
 #endif
@@ -491,13 +480,15 @@ static int events_socket(struct Curl_easy *easy,      /* easy handle */
           ev->list = nxt;
         free(m);
         m = nxt;
-        infof(easy, "socket cb: socket %d REMOVED", s);
+        infof(easy, "socket cb: socket %" CURL_FORMAT_SOCKET_T
+              " REMOVED", s);
       }
       else {
         /* The socket 's' is already being monitored, update the activity
            mask. Convert from libcurl bitmask to the poll one. */
         m->socket.events = socketcb2poll(what);
-        infof(easy, "socket cb: socket %d UPDATED as %s%s", s,
+        infof(easy, "socket cb: socket %" CURL_FORMAT_SOCKET_T
+              " UPDATED as %s%s", s,
               (what&CURL_POLL_IN)?"IN":"",
               (what&CURL_POLL_OUT)?"OUT":"");
       }
@@ -521,7 +512,8 @@ static int events_socket(struct Curl_easy *easy,      /* easy handle */
         m->socket.events = socketcb2poll(what);
         m->socket.revents = 0;
         ev->list = m;
-        infof(easy, "socket cb: socket %d ADDED as %s%s", s,
+        infof(easy, "socket cb: socket %" CURL_FORMAT_SOCKET_T
+              " ADDED as %s%s", s,
               (what&CURL_POLL_IN)?"IN":"",
               (what&CURL_POLL_OUT)?"OUT":"");
       }
@@ -610,8 +602,9 @@ static CURLcode wait_or_timeout(struct Curl_multi *multi, struct events *ev)
         if(fds[i].revents) {
           /* socket activity, tell libcurl */
           int act = poll2cselect(fds[i].revents); /* convert */
-          infof(multi->easyp, "call curl_multi_socket_action(socket %d)",
-                fds[i].fd);
+          infof(multi->easyp,
+                "call curl_multi_socket_action(socket "
+                "%" CURL_FORMAT_SOCKET_T ")", fds[i].fd);
           mcode = curl_multi_socket_action(multi, fds[i].fd, act,
                                            &ev->running_handles);
         }
@@ -695,9 +688,9 @@ static CURLcode easy_transfer(struct Curl_multi *multi)
   /* Make sure to return some kind of error if there was a multi problem */
   if(mcode) {
     result = (mcode == CURLM_OUT_OF_MEMORY) ? CURLE_OUT_OF_MEMORY :
-              /* The other multi errors should never happen, so return
-                 something suitably generic */
-              CURLE_BAD_FUNCTION_ARGUMENT;
+      /* The other multi errors should never happen, so return
+         something suitably generic */
+      CURLE_BAD_FUNCTION_ARGUMENT;
   }
 
   return result;
@@ -735,6 +728,8 @@ static CURLcode easy_perform(struct Curl_easy *data, bool events)
     /* clear this as early as possible */
     data->set.errorbuffer[0] = 0;
 
+  data->state.os_errno = 0;
+
   if(data->multi) {
     failf(data, "easy handle already used in multi handle");
     return CURLE_FAILED_INIT;
@@ -748,24 +743,26 @@ static CURLcode easy_perform(struct Curl_easy *data, bool events)
     multi = Curl_multi_handle(1, 3, 7);
     if(!multi)
       return CURLE_OUT_OF_MEMORY;
-    data->multi_easy = multi;
   }
 
   if(multi->in_callback)
     return CURLE_RECURSIVE_API_CALL;
 
   /* Copy the MAXCONNECTS option to the multi handle */
-  curl_multi_setopt(multi, CURLMOPT_MAXCONNECTS, data->set.maxconnects);
+  curl_multi_setopt(multi, CURLMOPT_MAXCONNECTS, (long)data->set.maxconnects);
 
+  data->multi_easy = NULL; /* pretend it does not exist */
   mcode = curl_multi_add_handle(multi, data);
   if(mcode) {
     curl_multi_cleanup(multi);
-    data->multi_easy = NULL;
     if(mcode == CURLM_OUT_OF_MEMORY)
       return CURLE_OUT_OF_MEMORY;
     return CURLE_FAILED_INIT;
   }
 
+  /* assign this after curl_multi_add_handle() */
+  data->multi_easy = multi;
+
   sigpipe_ignore(data, &pipe_st);
 
   /* run the transfer */
@@ -848,8 +845,10 @@ static CURLcode dupset(struct Curl_easy *dst, struct Curl_easy *src)
   dst->set = src->set;
   Curl_mime_initpart(&dst->set.mimepost);
 
-  /* clear all string pointers first */
+  /* clear all dest string and blob pointers first, in case we error out
+     mid-function */
   memset(dst->set.str, 0, STRING_LAST * sizeof(char *));
+  memset(dst->set.blobs, 0, BLOB_LAST * sizeof(struct curl_blob *));
 
   /* duplicate all strings */
   for(i = (enum dupstring)0; i< STRING_LASTZEROTERMINATED; i++) {
@@ -858,8 +857,6 @@ static CURLcode dupset(struct Curl_easy *dst, struct Curl_easy *src)
       return result;
   }
 
-  /* clear all blob pointers first */
-  memset(dst->set.blobs, 0, BLOB_LAST * sizeof(struct curl_blob *));
   /* duplicate all blobs */
   for(j = (enum dupblob)0; j < BLOB_LAST; j++) {
     result = Curl_setblobopt(&dst->set.blobs[j], src->set.blobs[j]);
@@ -869,10 +866,13 @@ static CURLcode dupset(struct Curl_easy *dst, struct Curl_easy *src)
 
   /* duplicate memory areas pointed to */
   i = STRING_COPYPOSTFIELDS;
-  if(src->set.postfieldsize && src->set.str[i]) {
-    /* postfieldsize is curl_off_t, Curl_memdup() takes a size_t ... */
-    dst->set.str[i] = Curl_memdup(src->set.str[i],
-                                  curlx_sotouz(src->set.postfieldsize));
+  if(src->set.str[i]) {
+    if(src->set.postfieldsize == -1)
+      dst->set.str[i] = strdup(src->set.str[i]);
+    else
+      /* postfieldsize is curl_off_t, Curl_memdup() takes a size_t ... */
+      dst->set.str[i] = Curl_memdup(src->set.str[i],
+                                    curlx_sotouz(src->set.postfieldsize));
     if(!dst->set.str[i])
       return CURLE_OUT_OF_MEMORY;
     /* point to the new copy */
@@ -922,20 +922,19 @@ struct Curl_easy *curl_easy_duphandle(struct Curl_easy *data)
   outcurl->progress.callback = data->progress.callback;
 
 #ifndef CURL_DISABLE_COOKIES
-  if(data->cookies) {
+  outcurl->state.cookielist = NULL;
+  if(data->cookies && data->state.cookie_engine) {
     /* If cookies are enabled in the parent handle, we enable them
        in the clone as well! */
-    outcurl->cookies = Curl_cookie_init(data,
-                                        data->cookies->filename,
-                                        outcurl->cookies,
+    outcurl->cookies = Curl_cookie_init(outcurl, NULL, outcurl->cookies,
                                         data->set.cookiesession);
     if(!outcurl->cookies)
       goto fail;
   }
 
-  if(data->set.cookielist) {
-    outcurl->set.cookielist = Curl_slist_duplicate(data->set.cookielist);
-    if(!outcurl->set.cookielist)
+  if(data->state.cookielist) {
+    outcurl->state.cookielist = Curl_slist_duplicate(data->state.cookielist);
+    if(!outcurl->state.cookielist)
       goto fail;
   }
 #endif
@@ -981,11 +980,14 @@ struct Curl_easy *curl_easy_duphandle(struct Curl_easy *data)
     (void)Curl_hsts_loadcb(outcurl, outcurl->hsts);
   }
 #endif
+
+#ifdef CURLRES_ASYNCH
   /* Clone the resolver handle, if present, for the new handle */
   if(Curl_resolver_duphandle(outcurl,
                              &outcurl->state.async.resolver,
                              data->state.async.resolver))
     goto fail;
+#endif
 
 #ifdef USE_ARES
   {
@@ -1021,13 +1023,9 @@ struct Curl_easy *curl_easy_duphandle(struct Curl_easy *data)
 
   if(outcurl) {
 #ifndef CURL_DISABLE_COOKIES
-    curl_slist_free_all(outcurl->set.cookielist);
-    outcurl->set.cookielist = NULL;
+    free(outcurl->cookies);
 #endif
-    Curl_safefree(outcurl->state.buffer);
     Curl_dyn_free(&outcurl->state.headerb);
-    Curl_safefree(outcurl->state.url);
-    Curl_safefree(outcurl->state.referer);
     Curl_altsvc_cleanup(&outcurl->asi);
     Curl_hsts_cleanup(&outcurl->hsts);
     Curl_freeset(outcurl);
@@ -1043,7 +1041,7 @@ struct Curl_easy *curl_easy_duphandle(struct Curl_easy *data)
  */
 void curl_easy_reset(struct Curl_easy *data)
 {
-  Curl_free_request_state(data);
+  Curl_req_hard_reset(&data->req, data);
 
   /* zero out UserDefined data: */
   Curl_freeset(data);
@@ -1088,11 +1086,15 @@ CURLcode curl_easy_pause(struct Curl_easy *data, int action)
   CURLcode result = CURLE_OK;
   int oldstate;
   int newstate;
+  bool recursive = FALSE;
+  bool keep_changed, unpause_read, not_all_paused;
 
   if(!GOOD_EASY_HANDLE(data) || !data->conn)
     /* crazy input, don't continue */
     return CURLE_BAD_FUNCTION_ARGUMENT;
 
+  if(Curl_is_in_callback(data))
+    recursive = TRUE;
   k = &data->req;
   oldstate = k->keepon & (KEEP_RECV_PAUSE| KEEP_SEND_PAUSE);
 
@@ -1101,96 +1103,65 @@ CURLcode curl_easy_pause(struct Curl_easy *data, int action)
     ((action & CURLPAUSE_RECV)?KEEP_RECV_PAUSE:0) |
     ((action & CURLPAUSE_SEND)?KEEP_SEND_PAUSE:0);
 
-  if((newstate & (KEEP_RECV_PAUSE| KEEP_SEND_PAUSE)) == oldstate) {
-    /* Not changing any pause state, return */
-    DEBUGF(infof(data, "pause: no change, early return"));
-    return CURLE_OK;
-  }
-
-  /* Unpause parts in active mime tree. */
-  if((k->keepon & ~newstate & KEEP_SEND_PAUSE) &&
-     (data->mstate == MSTATE_PERFORMING ||
-      data->mstate == MSTATE_RATELIMITING) &&
-     data->state.fread_func == (curl_read_callback) Curl_mime_read) {
-    Curl_mime_unpause(data->state.in);
-  }
-
-  /* put it back in the keepon */
+  keep_changed = ((newstate & (KEEP_RECV_PAUSE| KEEP_SEND_PAUSE)) != oldstate);
+  not_all_paused = (newstate & (KEEP_RECV_PAUSE|KEEP_SEND_PAUSE)) !=
+                   (KEEP_RECV_PAUSE|KEEP_SEND_PAUSE);
+  unpause_read = ((k->keepon & ~newstate & KEEP_SEND_PAUSE) &&
+                  (data->mstate == MSTATE_PERFORMING ||
+                   data->mstate == MSTATE_RATELIMITING));
+  /* Unpausing writes is detected on the next run in
+   * transfer.c:Curl_readwrite(). This is because this may result
+   * in a transfer error if the application's callbacks fail */
+
+  /* Set the new keepon state, so it takes effect no matter what error
+   * may happen afterwards. */
   k->keepon = newstate;
 
-  if(!(newstate & KEEP_RECV_PAUSE)) {
-    Curl_conn_ev_data_pause(data, FALSE);
-
-    if(data->state.tempcount) {
-      /* there are buffers for sending that can be delivered as the receive
-         pausing is lifted! */
-      unsigned int i;
-      unsigned int count = data->state.tempcount;
-      struct tempbuf writebuf[3]; /* there can only be three */
-
-      /* copy the structs to allow for immediate re-pausing */
-      for(i = 0; i < data->state.tempcount; i++) {
-        writebuf[i] = data->state.tempwrite[i];
-        Curl_dyn_init(&data->state.tempwrite[i].b, DYN_PAUSE_BUFFER);
-      }
-      data->state.tempcount = 0;
-
-      for(i = 0; i < count; i++) {
-        /* even if one function returns error, this loops through and frees
-           all buffers */
-        if(!result)
-          result = Curl_client_write(data, writebuf[i].type,
-                                     Curl_dyn_ptr(&writebuf[i].b),
-                                     Curl_dyn_len(&writebuf[i].b));
-        Curl_dyn_free(&writebuf[i].b);
+  /* If not completely pausing both directions now, run again in any case. */
+  if(not_all_paused) {
+    Curl_expire(data, 0, EXPIRE_RUN_NOW);
+    /* reset the too-slow time keeper */
+    data->state.keeps_speed.tv_sec = 0;
+    /* Simulate socket events on next run for unpaused directions */
+    if(!(newstate & KEEP_SEND_PAUSE))
+      data->state.select_bits |= CURL_CSELECT_OUT;
+    if(!(newstate & KEEP_RECV_PAUSE))
+      data->state.select_bits |= CURL_CSELECT_IN;
+    /* On changes, tell application to update its timers. */
+    if(keep_changed && data->multi) {
+      if(Curl_update_timer(data->multi)) {
+        result = CURLE_ABORTED_BY_CALLBACK;
+        goto out;
       }
-
-      if(result)
-        return result;
-    }
-  }
-
-#ifdef USE_HYPER
-  if(!(newstate & KEEP_SEND_PAUSE)) {
-    /* need to wake the send body waker */
-    if(data->hyp.send_body_waker) {
-      hyper_waker_wake(data->hyp.send_body_waker);
-      data->hyp.send_body_waker = NULL;
     }
   }
-#endif
-
-  /* if there's no error and we're not pausing both directions, we want
-     to have this handle checked soon */
-  if((newstate & (KEEP_RECV_PAUSE|KEEP_SEND_PAUSE)) !=
-     (KEEP_RECV_PAUSE|KEEP_SEND_PAUSE)) {
-    Curl_expire(data, 0, EXPIRE_RUN_NOW); /* get this handle going again */
 
-    /* reset the too-slow time keeper */
-    data->state.keeps_speed.tv_sec = 0;
-
-    if(!data->state.tempcount)
-      /* if not pausing again, force a recv/send check of this connection as
-         the data might've been read off the socket already */
-      data->conn->cselect_bits = CURL_CSELECT_IN | CURL_CSELECT_OUT;
-    if(data->multi) {
-      if(Curl_update_timer(data->multi))
-        return CURLE_ABORTED_BY_CALLBACK;
-    }
+  if(unpause_read) {
+    result = Curl_creader_unpause(data);
+    if(result)
+      goto out;
   }
 
-  if(!data->state.done)
+out:
+  if(!result && !data->state.done && keep_changed)
     /* This transfer may have been moved in or out of the bundle, update the
        corresponding socket callback, if used */
     result = Curl_updatesocket(data);
 
+  if(recursive)
+    /* this might have called a callback recursively which might have set this
+       to false again on exit */
+    Curl_set_in_callback(data, TRUE);
+
   return result;
 }
 
 
-static CURLcode easy_connection(struct Curl_easy *data, curl_socket_t *sfd,
+static CURLcode easy_connection(struct Curl_easy *data,
                                 struct connectdata **connp)
 {
+  curl_socket_t sfd;
+
   if(!data)
     return CURLE_BAD_FUNCTION_ARGUMENT;
 
@@ -1200,9 +1171,9 @@ static CURLcode easy_connection(struct Curl_easy *data, curl_socket_t *sfd,
     return CURLE_UNSUPPORTED_PROTOCOL;
   }
 
-  *sfd = Curl_getconnectinfo(data, connp);
+  sfd = Curl_getconnectinfo(data, connp);
 
-  if(*sfd == CURL_SOCKET_BAD) {
+  if(sfd == CURL_SOCKET_BAD) {
     failf(data, "Failed to get recent socket");
     return CURLE_UNSUPPORTED_PROTOCOL;
   }
@@ -1218,7 +1189,6 @@ static CURLcode easy_connection(struct Curl_easy *data, curl_socket_t *sfd,
 CURLcode curl_easy_recv(struct Curl_easy *data, void *buffer, size_t buflen,
                         size_t *n)
 {
-  curl_socket_t sfd;
   CURLcode result;
   ssize_t n1;
   struct connectdata *c;
@@ -1226,7 +1196,7 @@ CURLcode curl_easy_recv(struct Curl_easy *data, void *buffer, size_t buflen,
   if(Curl_is_in_callback(data))
     return CURLE_RECURSIVE_API_CALL;
 
-  result = easy_connection(data, &sfd, &c);
+  result = easy_connection(data, &c);
   if(result)
     return result;
 
@@ -1236,7 +1206,7 @@ CURLcode curl_easy_recv(struct Curl_easy *data, void *buffer, size_t buflen,
     Curl_attach_connection(data, c);
 
   *n = 0;
-  result = Curl_read(data, sfd, buffer, buflen, &n1);
+  result = Curl_conn_recv(data, FIRSTSOCKET, buffer, buflen, &n1);
 
   if(result)
     return result;
@@ -1248,11 +1218,10 @@ CURLcode curl_easy_recv(struct Curl_easy *data, void *buffer, size_t buflen,
 #ifdef USE_WEBSOCKETS
 CURLcode Curl_connect_only_attach(struct Curl_easy *data)
 {
-  curl_socket_t sfd;
   CURLcode result;
   struct connectdata *c = NULL;
 
-  result = easy_connection(data, &sfd, &c);
+  result = easy_connection(data, &c);
   if(result)
     return result;
 
@@ -1271,15 +1240,14 @@ CURLcode Curl_connect_only_attach(struct Curl_easy *data)
  * This is the private internal version of curl_easy_send()
  */
 CURLcode Curl_senddata(struct Curl_easy *data, const void *buffer,
-                       size_t buflen, ssize_t *n)
+                       size_t buflen, size_t *n)
 {
-  curl_socket_t sfd;
   CURLcode result;
-  ssize_t n1;
   struct connectdata *c = NULL;
   SIGPIPE_VARIABLE(pipe_st);
 
-  result = easy_connection(data, &sfd, &c);
+  *n = 0;
+  result = easy_connection(data, &c);
   if(result)
     return result;
 
@@ -1288,20 +1256,12 @@ CURLcode Curl_senddata(struct Curl_easy *data, const void *buffer,
        needs to be reattached */
     Curl_attach_connection(data, c);
 
-  *n = 0;
   sigpipe_ignore(data, &pipe_st);
-  result = Curl_write(data, sfd, buffer, buflen, &n1);
+  result = Curl_conn_send(data, FIRSTSOCKET, buffer, buflen, n);
   sigpipe_restore(&pipe_st);
 
-  if(n1 == -1)
+  if(result && result != CURLE_AGAIN)
     return CURLE_SEND_ERROR;
-
-  /* detect EAGAIN */
-  if(!result && !n1)
-    return CURLE_AGAIN;
-
-  *n = n1;
-
   return result;
 }
 
@@ -1312,13 +1272,13 @@ CURLcode Curl_senddata(struct Curl_easy *data, const void *buffer,
 CURLcode curl_easy_send(struct Curl_easy *data, const void *buffer,
                         size_t buflen, size_t *n)
 {
-  ssize_t written = 0;
+  size_t written = 0;
   CURLcode result;
   if(Curl_is_in_callback(data))
     return CURLE_RECURSIVE_API_CALL;
 
   result = Curl_senddata(data, buffer, buflen, &written);
-  *n = (size_t)written;
+  *n = written;
   return result;
 }
 
@@ -1343,7 +1303,7 @@ static int conn_upkeep(struct Curl_easy *data,
     conn->handler->connection_check(data, conn, CONNCHECK_KEEPALIVE);
   }
   else {
-    /* Do the generic action on the FIRSTSOCKE filter chain */
+    /* Do the generic action on the FIRSTSOCKET filter chain */
     Curl_conn_keep_alive(data, conn, FIRSTSOCKET);
   }
   Curl_detach_connection(data);
diff --git a/vendor/curl/lib/easy_lock.h b/vendor/curl/lib/easy_lock.h
index 6399a39bde..4f6764d427 100644
--- a/vendor/curl/lib/easy_lock.h
+++ b/vendor/curl/lib/easy_lock.h
@@ -31,13 +31,6 @@
 #if defined(_WIN32_WINNT) && _WIN32_WINNT >= 0x600
 
 #ifdef __MINGW32__
-#ifndef __MINGW64_VERSION_MAJOR
-#if (__MINGW32_MAJOR_VERSION < 5) || \
-    (__MINGW32_MAJOR_VERSION == 5 && __MINGW32_MINOR_VERSION == 0)
-/* mingw >= 5.0.1 defines SRWLOCK, and slightly different from MS define */
-typedef PVOID SRWLOCK, *PSRWLOCK;
-#endif
-#endif
 #ifndef SRWLOCK_INIT
 #define SRWLOCK_INIT NULL
 #endif
@@ -100,6 +93,15 @@ static inline void curl_simple_lock_unlock(curl_simple_lock *lock)
   atomic_store_explicit(lock, false, memory_order_release);
 }
 
+#elif defined(USE_THREADS_POSIX) && defined(HAVE_PTHREAD_H)
+
+#include 
+
+#define curl_simple_lock pthread_mutex_t
+#define CURL_SIMPLE_LOCK_INIT PTHREAD_MUTEX_INITIALIZER
+#define curl_simple_lock_lock(m) pthread_mutex_lock(m)
+#define curl_simple_lock_unlock(m) pthread_mutex_unlock(m)
+
 #else
 
 #undef  GLOBAL_INIT_IS_THREADSAFE
diff --git a/vendor/curl/lib/easygetopt.c b/vendor/curl/lib/easygetopt.c
index 2b8a521cd2..a0239a89fb 100644
--- a/vendor/curl/lib/easygetopt.c
+++ b/vendor/curl/lib/easygetopt.c
@@ -5,7 +5,7 @@
  *                            | (__| |_| |  _ <| |___
  *                             ___|___/|_| ______|
  *
- * Copyright (C) Daniel Stenberg, , et al.
+ * Copyright (C) Daniel Stenberg, , et al.
  *
  * This software is licensed as described in the file COPYING, which
  * you should have received as part of this distribution. The terms
diff --git a/vendor/curl/lib/easyif.h b/vendor/curl/lib/easyif.h
index 6448952966..6ce3483c64 100644
--- a/vendor/curl/lib/easyif.h
+++ b/vendor/curl/lib/easyif.h
@@ -28,7 +28,7 @@
  * Prototypes for library-wide functions provided by easy.c
  */
 CURLcode Curl_senddata(struct Curl_easy *data, const void *buffer,
-                       size_t buflen, ssize_t *n);
+                       size_t buflen, size_t *n);
 
 #ifdef USE_WEBSOCKETS
 CURLcode Curl_connect_only_attach(struct Curl_easy *data);
diff --git a/vendor/curl/lib/easyoptions.c b/vendor/curl/lib/easyoptions.c
index e69c658b0c..c79d136707 100644
--- a/vendor/curl/lib/easyoptions.c
+++ b/vendor/curl/lib/easyoptions.c
@@ -5,7 +5,7 @@
  *                            | (__| |_| |  _ <| |___
  *                             \___|\___/|_| \_\_____|
  *
- * Copyright (C) Daniel Stenberg, , et al.
+ * Copyright (C) Daniel Stenberg, , et al.
  *
  * This software is licensed as described in the file COPYING, which
  * you should have received as part of this distribution. The terms
@@ -86,6 +86,7 @@ struct curl_easyoption Curl_easyopts[] = {
   {"DOH_SSL_VERIFYPEER", CURLOPT_DOH_SSL_VERIFYPEER, CURLOT_LONG, 0},
   {"DOH_SSL_VERIFYSTATUS", CURLOPT_DOH_SSL_VERIFYSTATUS, CURLOT_LONG, 0},
   {"DOH_URL", CURLOPT_DOH_URL, CURLOT_STRING, 0},
+  {"ECH", CURLOPT_ECH, CURLOT_STRING, 0},
   {"EGDSOCKET", CURLOPT_EGDSOCKET, CURLOT_STRING, 0},
   {"ENCODING", CURLOPT_ACCEPT_ENCODING, CURLOT_STRING, CURLOT_FLAG_ALIAS},
   {"ERRORBUFFER", CURLOPT_ERRORBUFFER, CURLOT_OBJECT, 0},
@@ -274,6 +275,8 @@ struct curl_easyoption Curl_easyopts[] = {
   {"SEEKFUNCTION", CURLOPT_SEEKFUNCTION, CURLOT_FUNCTION, 0},
   {"SERVER_RESPONSE_TIMEOUT", CURLOPT_SERVER_RESPONSE_TIMEOUT,
    CURLOT_LONG, 0},
+  {"SERVER_RESPONSE_TIMEOUT_MS", CURLOPT_SERVER_RESPONSE_TIMEOUT_MS,
+   CURLOT_LONG, 0},
   {"SERVICE_NAME", CURLOPT_SERVICE_NAME, CURLOT_STRING, 0},
   {"SHARE", CURLOPT_SHARE, CURLOT_OBJECT, 0},
   {"SOCKOPTDATA", CURLOPT_SOCKOPTDATA, CURLOT_CBPTR, 0},
@@ -373,6 +376,6 @@ struct curl_easyoption Curl_easyopts[] = {
  */
 int Curl_easyopts_check(void)
 {
-  return ((CURLOPT_LASTENTRY%10000) != (323 + 1));
+  return ((CURLOPT_LASTENTRY%10000) != (325 + 1));
 }
 #endif
diff --git a/vendor/curl/lib/escape.c b/vendor/curl/lib/escape.c
index 56aa2b3988..5af00c3514 100644
--- a/vendor/curl/lib/escape.c
+++ b/vendor/curl/lib/escape.c
@@ -38,33 +38,6 @@
 #include "curl_memory.h"
 #include "memdebug.h"
 
-/* Portable character check (remember EBCDIC). Do not use isalnum() because
-   its behavior is altered by the current locale.
-   See https://datatracker.ietf.org/doc/html/rfc3986#section-2.3
-*/
-bool Curl_isunreserved(unsigned char in)
-{
-  switch(in) {
-    case '0': case '1': case '2': case '3': case '4':
-    case '5': case '6': case '7': case '8': case '9':
-    case 'a': case 'b': case 'c': case 'd': case 'e':
-    case 'f': case 'g': case 'h': case 'i': case 'j':
-    case 'k': case 'l': case 'm': case 'n': case 'o':
-    case 'p': case 'q': case 'r': case 's': case 't':
-    case 'u': case 'v': case 'w': case 'x': case 'y': case 'z':
-    case 'A': case 'B': case 'C': case 'D': case 'E':
-    case 'F': case 'G': case 'H': case 'I': case 'J':
-    case 'K': case 'L': case 'M': case 'N': case 'O':
-    case 'P': case 'Q': case 'R': case 'S': case 'T':
-    case 'U': case 'V': case 'W': case 'X': case 'Y': case 'Z':
-    case '-': case '.': case '_': case '~':
-      return TRUE;
-    default:
-      break;
-  }
-  return FALSE;
-}
-
 /* for ABI-compatibility with previous versions */
 char *curl_escape(const char *string, int inlength)
 {
@@ -99,7 +72,7 @@ char *curl_easy_escape(struct Curl_easy *data, const char *string,
   while(length--) {
     unsigned char in = *string++; /* treat the characters unsigned */
 
-    if(Curl_isunreserved(in)) {
+    if(ISUNRESERVED(in)) {
       /* append this */
       if(Curl_dyn_addn(&d, &in, 1))
         return NULL;
@@ -233,3 +206,29 @@ void curl_free(void *p)
 {
   free(p);
 }
+
+/*
+ * Curl_hexencode()
+ *
+ * Converts binary input to lowercase hex-encoded ASCII output.
+ * Null-terminated.
+ */
+void Curl_hexencode(const unsigned char *src, size_t len, /* input length */
+                    unsigned char *out, size_t olen) /* output buffer size */
+{
+  const char *hex = "0123456789abcdef";
+  DEBUGASSERT(src && len && (olen >= 3));
+  if(src && len && (olen >= 3)) {
+    while(len-- && (olen >= 3)) {
+      /* clang-tidy warns on this line without this comment: */
+      /* NOLINTNEXTLINE(clang-analyzer-core.UndefinedBinaryOperatorResult) */
+      *out++ = hex[(*src & 0xF0)>>4];
+      *out++ = hex[*src & 0x0F];
+      ++src;
+      olen -= 2;
+    }
+    *out = 0;
+  }
+  else if(olen)
+    *out = 0;
+}
diff --git a/vendor/curl/lib/escape.h b/vendor/curl/lib/escape.h
index cdbb712acc..690e417879 100644
--- a/vendor/curl/lib/escape.h
+++ b/vendor/curl/lib/escape.h
@@ -26,7 +26,7 @@
 /* Escape and unescape URL encoding in strings. The functions return a new
  * allocated string or NULL if an error occurred.  */
 
-bool Curl_isunreserved(unsigned char in);
+#include "curl_ctype.h"
 
 enum urlreject {
   REJECT_NADA = 2,
@@ -38,4 +38,7 @@ CURLcode Curl_urldecode(const char *string, size_t length,
                         char **ostring, size_t *olen,
                         enum urlreject ctrl);
 
+void Curl_hexencode(const unsigned char *src, size_t len, /* input length */
+                    unsigned char *out, size_t olen); /* output buffer size */
+
 #endif /* HEADER_CURL_ESCAPE_H */
diff --git a/vendor/curl/lib/file.c b/vendor/curl/lib/file.c
index c751e8861a..db860225b0 100644
--- a/vendor/curl/lib/file.c
+++ b/vendor/curl/lib/file.c
@@ -50,6 +50,14 @@
 #include 
 #endif
 
+#ifdef HAVE_SYS_TYPES_H
+#include 
+#endif
+
+#ifdef HAVE_DIRENT_H
+#include 
+#endif
+
 #include "strtoofft.h"
 #include "urldata.h"
 #include 
@@ -59,6 +67,7 @@
 #include "file.h"
 #include "speedcheck.h"
 #include "getinfo.h"
+#include "multiif.h"
 #include "transfer.h"
 #include "url.h"
 #include "parsedate.h" /* for the week day and month names */
@@ -69,7 +78,7 @@
 #include "curl_memory.h"
 #include "memdebug.h"
 
-#if defined(WIN32) || defined(MSDOS) || defined(__EMX__)
+#if defined(_WIN32) || defined(MSDOS) || defined(__EMX__)
 #define DOS_FILESYSTEM 1
 #elif defined(__amigaos4__)
 #define AMIGA_FILESYSTEM 1
@@ -100,7 +109,7 @@ static CURLcode file_setup_connection(struct Curl_easy *data,
  */
 
 const struct Curl_handler Curl_handler_file = {
-  "FILE",                               /* scheme */
+  "file",                               /* scheme */
   file_setup_connection,                /* setup_connection */
   file_do,                              /* do_it */
   file_done,                            /* done */
@@ -113,7 +122,8 @@ const struct Curl_handler Curl_handler_file = {
   ZERO_NULL,                            /* domore_getsock */
   ZERO_NULL,                            /* perform_getsock */
   file_disconnect,                      /* disconnect */
-  ZERO_NULL,                            /* readwrite */
+  ZERO_NULL,                            /* write_resp */
+  ZERO_NULL,                            /* write_resp_hd */
   ZERO_NULL,                            /* connection_check */
   ZERO_NULL,                            /* attach connection */
   0,                                    /* defport */
@@ -290,16 +300,17 @@ static CURLcode file_upload(struct Curl_easy *data)
   int fd;
   int mode;
   CURLcode result = CURLE_OK;
-  char *buf = data->state.buffer;
+  char *xfer_ulbuf;
+  size_t xfer_ulblen;
   curl_off_t bytecount = 0;
   struct_stat file_stat;
-  const char *buf2;
+  const char *sendbuf;
+  bool eos = FALSE;
 
   /*
    * Since FILE: doesn't do the full init, we need to provide some extra
    * assignments here.
    */
-  data->req.upload_fromhere = buf;
 
   if(!dir)
     return CURLE_FILE_COULDNT_READ_FILE; /* fix: better error code */
@@ -338,11 +349,16 @@ static CURLcode file_upload(struct Curl_easy *data)
     data->state.resume_from = (curl_off_t)file_stat.st_size;
   }
 
-  while(!result) {
+  result = Curl_multi_xfer_ulbuf_borrow(data, &xfer_ulbuf, &xfer_ulblen);
+  if(result)
+    goto out;
+
+  while(!result && !eos) {
     size_t nread;
     ssize_t nwrite;
     size_t readcount;
-    result = Curl_fillreadbuffer(data, data->set.buffer_size, &readcount);
+
+    result = Curl_client_read(data, xfer_ulbuf, xfer_ulblen, &readcount, &eos);
     if(result)
       break;
 
@@ -356,19 +372,19 @@ static CURLcode file_upload(struct Curl_easy *data)
       if((curl_off_t)nread <= data->state.resume_from) {
         data->state.resume_from -= nread;
         nread = 0;
-        buf2 = buf;
+        sendbuf = xfer_ulbuf;
       }
       else {
-        buf2 = buf + data->state.resume_from;
+        sendbuf = xfer_ulbuf + data->state.resume_from;
         nread -= (size_t)data->state.resume_from;
         data->state.resume_from = 0;
       }
     }
     else
-      buf2 = buf;
+      sendbuf = xfer_ulbuf;
 
     /* write the data to the target */
-    nwrite = write(fd, buf2, nread);
+    nwrite = write(fd, sendbuf, nread);
     if((size_t)nwrite != nread) {
       result = CURLE_SEND_ERROR;
       break;
@@ -386,7 +402,9 @@ static CURLcode file_upload(struct Curl_easy *data)
   if(!result && Curl_pgrsUpdate(data))
     result = CURLE_ABORTED_BY_CALLBACK;
 
+out:
   close(fd);
+  Curl_multi_xfer_ulbuf_release(data, xfer_ulbuf);
 
   return result;
 }
@@ -413,15 +431,13 @@ static CURLcode file_do(struct Curl_easy *data, bool *done)
   curl_off_t expected_size = -1;
   bool size_known;
   bool fstated = FALSE;
-  char *buf = data->state.buffer;
-  curl_off_t bytecount = 0;
   int fd;
   struct FILEPROTO *file;
+  char *xfer_buf;
+  size_t xfer_blen;
 
   *done = TRUE; /* unconditionally */
 
-  Curl_pgrsStartNow(data);
-
   if(data->state.upload)
     return file_upload(data);
 
@@ -439,12 +455,9 @@ static CURLcode file_do(struct Curl_easy *data, bool *done)
     fstated = TRUE;
   }
 
-  if(fstated && !data->state.range && data->set.timecondition) {
-    if(!Curl_meets_timecondition(data, data->info.filetime)) {
-      *done = TRUE;
-      return CURLE_OK;
-    }
-  }
+  if(fstated && !data->state.range && data->set.timecondition &&
+     !Curl_meets_timecondition(data, data->info.filetime))
+    return CURLE_OK;
 
   if(fstated) {
     time_t filetime;
@@ -536,51 +549,90 @@ static CURLcode file_do(struct Curl_easy *data, bool *done)
     Curl_pgrsSetDownloadSize(data, expected_size);
 
   if(data->state.resume_from) {
-    if(data->state.resume_from !=
-       lseek(fd, data->state.resume_from, SEEK_SET))
+    if(!S_ISDIR(statbuf.st_mode)) {
+      if(data->state.resume_from !=
+          lseek(fd, data->state.resume_from, SEEK_SET))
+        return CURLE_BAD_DOWNLOAD_RESUME;
+    }
+    else {
       return CURLE_BAD_DOWNLOAD_RESUME;
+    }
   }
 
-  Curl_pgrsTime(data, TIMER_STARTTRANSFER);
+  result = Curl_multi_xfer_buf_borrow(data, &xfer_buf, &xfer_blen);
+  if(result)
+    goto out;
 
-  while(!result) {
-    ssize_t nread;
-    /* Don't fill a whole buffer if we want less than all data */
-    size_t bytestoread;
+  if(!S_ISDIR(statbuf.st_mode)) {
+    while(!result) {
+      ssize_t nread;
+      /* Don't fill a whole buffer if we want less than all data */
+      size_t bytestoread;
 
-    if(size_known) {
-      bytestoread = (expected_size < data->set.buffer_size) ?
-        curlx_sotouz(expected_size) : (size_t)data->set.buffer_size;
-    }
-    else
-      bytestoread = data->set.buffer_size-1;
+      if(size_known) {
+        bytestoread = (expected_size < (curl_off_t)(xfer_blen-1)) ?
+          curlx_sotouz(expected_size) : (xfer_blen-1);
+      }
+      else
+        bytestoread = xfer_blen-1;
 
-    nread = read(fd, buf, bytestoread);
+      nread = read(fd, xfer_buf, bytestoread);
 
-    if(nread > 0)
-      buf[nread] = 0;
+      if(nread > 0)
+        xfer_buf[nread] = 0;
 
-    if(nread <= 0 || (size_known && (expected_size == 0)))
-      break;
+      if(nread <= 0 || (size_known && (expected_size == 0)))
+        break;
 
-    bytecount += nread;
-    if(size_known)
-      expected_size -= nread;
+      if(size_known)
+        expected_size -= nread;
 
-    result = Curl_client_write(data, CLIENTWRITE_BODY, buf, nread);
-    if(result)
-      return result;
-
-    Curl_pgrsSetDownloadCounter(data, bytecount);
+      result = Curl_client_write(data, CLIENTWRITE_BODY, xfer_buf, nread);
+      if(result)
+        goto out;
 
-    if(Curl_pgrsUpdate(data))
-      result = CURLE_ABORTED_BY_CALLBACK;
-    else
-      result = Curl_speedcheck(data, Curl_now());
+      if(Curl_pgrsUpdate(data))
+        result = CURLE_ABORTED_BY_CALLBACK;
+      else
+        result = Curl_speedcheck(data, Curl_now());
+      if(result)
+        goto out;
+    }
   }
+  else {
+#ifdef HAVE_OPENDIR
+    DIR *dir = opendir(file->path);
+    struct dirent *entry;
+
+    if(!dir) {
+      result = CURLE_READ_ERROR;
+      goto out;
+    }
+    else {
+      while((entry = readdir(dir))) {
+        if(entry->d_name[0] != '.') {
+          result = Curl_client_write(data, CLIENTWRITE_BODY,
+                   entry->d_name, strlen(entry->d_name));
+          if(result)
+            break;
+          result = Curl_client_write(data, CLIENTWRITE_BODY, "\n", 1);
+          if(result)
+            break;
+        }
+      }
+      closedir(dir);
+    }
+#else
+    failf(data, "Directory listing not yet implemented on this platform.");
+    result = CURLE_READ_ERROR;
+#endif
+  }
+
   if(Curl_pgrsUpdate(data))
     result = CURLE_ABORTED_BY_CALLBACK;
 
+out:
+  Curl_multi_xfer_buf_release(data, xfer_buf);
   return result;
 }
 
diff --git a/vendor/curl/lib/fopen.c b/vendor/curl/lib/fopen.c
index b6e3caddde..0bdf2e11b6 100644
--- a/vendor/curl/lib/fopen.c
+++ b/vendor/curl/lib/fopen.c
@@ -39,6 +39,51 @@
 #include "curl_memory.h"
 #include "memdebug.h"
 
+/*
+  The dirslash() function breaks a null-terminated pathname string into
+  directory and filename components then returns the directory component up
+  to, *AND INCLUDING*, a final '/'.  If there is no directory in the path,
+  this instead returns a "" string.
+
+  This function returns a pointer to malloc'ed memory.
+
+  The input path to this function is expected to have a file name part.
+*/
+
+#ifdef _WIN32
+#define PATHSEP "\\"
+#define IS_SEP(x) (((x) == '/') || ((x) == '\\'))
+#elif defined(MSDOS) || defined(__EMX__) || defined(OS2)
+#define PATHSEP "\\"
+#define IS_SEP(x) ((x) == '\\')
+#else
+#define PATHSEP "/"
+#define IS_SEP(x) ((x) == '/')
+#endif
+
+static char *dirslash(const char *path)
+{
+  size_t n;
+  struct dynbuf out;
+  DEBUGASSERT(path);
+  Curl_dyn_init(&out, CURL_MAX_INPUT_LENGTH);
+  n = strlen(path);
+  if(n) {
+    /* find the rightmost path separator, if any */
+    while(n && !IS_SEP(path[n-1]))
+      --n;
+    /* skip over all the path separators, if any */
+    while(n && IS_SEP(path[n-1]))
+      --n;
+  }
+  if(Curl_dyn_addn(&out, path, n))
+    return NULL;
+  /* if there was a directory, append a single trailing slash */
+  if(n && Curl_dyn_addn(&out, PATHSEP, 1))
+    return NULL;
+  return Curl_dyn_ptr(&out);
+}
+
 /*
  * Curl_fopen() opens a file for writing with a temp name, to be renamed
  * to the final name when completed. If there is an existing file using this
@@ -50,47 +95,49 @@ CURLcode Curl_fopen(struct Curl_easy *data, const char *filename,
                     FILE **fh, char **tempname)
 {
   CURLcode result = CURLE_WRITE_ERROR;
-  unsigned char randsuffix[9];
+  unsigned char randbuf[41];
   char *tempstore = NULL;
   struct_stat sb;
   int fd = -1;
+  char *dir = NULL;
   *tempname = NULL;
 
   *fh = fopen(filename, FOPEN_WRITETEXT);
   if(!*fh)
     goto fail;
-  if(fstat(fileno(*fh), &sb) == -1 || !S_ISREG(sb.st_mode))
+  if(fstat(fileno(*fh), &sb) == -1 || !S_ISREG(sb.st_mode)) {
     return CURLE_OK;
+  }
   fclose(*fh);
   *fh = NULL;
 
-  result = Curl_rand_hex(data, randsuffix, sizeof(randsuffix));
+  result = Curl_rand_alnum(data, randbuf, sizeof(randbuf));
   if(result)
     goto fail;
 
-  tempstore = aprintf("%s.%s.tmp", filename, randsuffix);
+  dir = dirslash(filename);
+  if(dir) {
+    /* The temp file name should not end up too long for the target file
+       system */
+    tempstore = aprintf("%s%s.tmp", dir, randbuf);
+    free(dir);
+  }
+
   if(!tempstore) {
     result = CURLE_OUT_OF_MEMORY;
     goto fail;
   }
 
   result = CURLE_WRITE_ERROR;
-  fd = open(tempstore, O_WRONLY | O_CREAT | O_EXCL, 0600);
+#if (defined(ANDROID) || defined(__ANDROID__)) && \
+    (defined(__i386__) || defined(__arm__))
+  fd = open(tempstore, O_WRONLY | O_CREAT | O_EXCL, (mode_t)(0600|sb.st_mode));
+#else
+  fd = open(tempstore, O_WRONLY | O_CREAT | O_EXCL, 0600|sb.st_mode);
+#endif
   if(fd == -1)
     goto fail;
 
-#ifdef HAVE_FCHMOD
-  {
-    struct_stat nsb;
-    if((fstat(fd, &nsb) != -1) &&
-       (nsb.st_uid == sb.st_uid) && (nsb.st_gid == sb.st_gid)) {
-      /* if the user and group are the same, clone the original mode */
-      if(fchmod(fd, (mode_t)sb.st_mode) == -1)
-        goto fail;
-    }
-  }
-#endif
-
   *fh = fdopen(fd, FOPEN_WRITETEXT);
   if(!*fh)
     goto fail;
@@ -105,7 +152,6 @@ CURLcode Curl_fopen(struct Curl_easy *data, const char *filename,
   }
 
   free(tempstore);
-
   return result;
 }
 
diff --git a/vendor/curl/lib/formdata.c b/vendor/curl/lib/formdata.c
index 8984b63223..d6a1697aa7 100644
--- a/vendor/curl/lib/formdata.c
+++ b/vendor/curl/lib/formdata.c
@@ -277,7 +277,7 @@ CURLFORMcode FormAdd(struct curl_httppost **httppost,
     case CURLFORM_PTRNAME:
       current_form->flags |= HTTPPOST_PTRNAME; /* fall through */
 
-      /* FALLTHROUGH */
+      FALLTHROUGH();
     case CURLFORM_COPYNAME:
       if(current_form->name)
         return_value = CURL_FORMADD_OPTION_TWICE;
@@ -303,7 +303,7 @@ CURLFORMcode FormAdd(struct curl_httppost **httppost,
        */
     case CURLFORM_PTRCONTENTS:
       current_form->flags |= HTTPPOST_PTRCONTENTS;
-      /* FALLTHROUGH */
+      FALLTHROUGH();
     case CURLFORM_COPYCONTENTS:
       if(current_form->value)
         return_value = CURL_FORMADD_OPTION_TWICE;
@@ -603,9 +603,9 @@ CURLFORMcode FormAdd(struct curl_httppost **httppost,
            app passed in a bad combo, so we better check for that first. */
         if(form->name) {
           /* copy name (without strdup; possibly not null-terminated) */
-          form->name = Curl_memdup(form->name, form->namelength?
-                                   form->namelength:
-                                   strlen(form->name) + 1);
+          form->name = Curl_memdup0(form->name, form->namelength?
+                                    form->namelength:
+                                    strlen(form->name));
         }
         if(!form->name) {
           return_value = CURL_FORMADD_MEMORY;
@@ -779,16 +779,28 @@ static CURLcode setname(curl_mimepart *part, const char *name, size_t len)
 
   if(!name || !len)
     return curl_mime_name(part, name);
-  zname = malloc(len + 1);
+  zname = Curl_memdup0(name, len);
   if(!zname)
     return CURLE_OUT_OF_MEMORY;
-  memcpy(zname, name, len);
-  zname[len] = '\0';
   res = curl_mime_name(part, zname);
   free(zname);
   return res;
 }
 
+/* wrap call to fseeko so it matches the calling convention of callback */
+static int fseeko_wrapper(void *stream, curl_off_t offset, int whence)
+{
+#if defined(HAVE_FSEEKO) && defined(HAVE_DECL_FSEEKO)
+  return fseeko(stream, (off_t)offset, whence);
+#elif defined(HAVE__FSEEKI64)
+  return _fseeki64(stream, (__int64)offset, whence);
+#else
+  if(offset > LONG_MAX)
+    return -1;
+  return fseek(stream, (long)offset, whence);
+#endif
+}
+
 /*
  * Curl_getformdata() converts a linked list of "meta data" into a mime
  * structure. The input list is in 'post', while the output is stored in
@@ -874,8 +886,7 @@ CURLcode Curl_getformdata(struct Curl_easy *data,
                compatibility: use of "-" pseudo file name should be avoided. */
             result = curl_mime_data_cb(part, (curl_off_t) -1,
                                        (curl_read_callback) fread,
-                                       CURLX_FUNCTION_CAST(curl_seek_callback,
-                                                           fseek),
+                                       fseeko_wrapper,
                                        NULL, (void *) stdin);
           }
           else
diff --git a/vendor/curl/lib/ftp.c b/vendor/curl/lib/ftp.c
index e24ae9c15d..b88d4d7b0f 100644
--- a/vendor/curl/lib/ftp.c
+++ b/vendor/curl/lib/ftp.c
@@ -72,6 +72,7 @@
 #include "warnless.h"
 #include "http_proxy.h"
 #include "socks.h"
+#include "strdup.h"
 /* The last 3 #include files should be in this order */
 #include "curl_printf.h"
 #include "curl_memory.h"
@@ -84,21 +85,99 @@
 #define INET_ADDRSTRLEN 16
 #endif
 
+/* macro to check for a three-digit ftp status code at the start of the
+   given string */
+#define STATUSCODE(line) (ISDIGIT(line[0]) && ISDIGIT(line[1]) &&       \
+                          ISDIGIT(line[2]))
+
+/* macro to check for the last line in an FTP server response */
+#define LASTLINE(line) (STATUSCODE(line) && (' ' == line[3]))
+
 #ifdef CURL_DISABLE_VERBOSE_STRINGS
 #define ftp_pasv_verbose(a,b,c,d)  Curl_nop_stmt
+#define FTP_CSTATE(c)   ""
+#define FTP_DSTATE(d)   ""
+#else /* CURL_DISABLE_VERBOSE_STRINGS */
+  /* for tracing purposes */
+static const char * const ftp_state_names[]={
+  "STOP",
+  "WAIT220",
+  "AUTH",
+  "USER",
+  "PASS",
+  "ACCT",
+  "PBSZ",
+  "PROT",
+  "CCC",
+  "PWD",
+  "SYST",
+  "NAMEFMT",
+  "QUOTE",
+  "RETR_PREQUOTE",
+  "STOR_PREQUOTE",
+  "POSTQUOTE",
+  "CWD",
+  "MKD",
+  "MDTM",
+  "TYPE",
+  "LIST_TYPE",
+  "RETR_TYPE",
+  "STOR_TYPE",
+  "SIZE",
+  "RETR_SIZE",
+  "STOR_SIZE",
+  "REST",
+  "RETR_REST",
+  "PORT",
+  "PRET",
+  "PASV",
+  "LIST",
+  "RETR",
+  "STOR",
+  "QUIT"
+};
+#define FTP_CSTATE(c)   ((c)? ftp_state_names[(c)->proto.ftpc.state] : "???")
+#define FTP_DSTATE(d)   (((d) && (d)->conn)? \
+                         ftp_state_names[(d)->conn->proto.ftpc.state] : "???")
+
+#endif /* !CURL_DISABLE_VERBOSE_STRINGS */
+
+/* This is the ONLY way to change FTP state! */
+static void _ftp_state(struct Curl_easy *data,
+                       ftpstate newstate
+#ifdef DEBUGBUILD
+                       , int lineno
 #endif
+  )
+{
+  struct connectdata *conn = data->conn;
+  struct ftp_conn *ftpc = &conn->proto.ftpc;
+
+#if defined(CURL_DISABLE_VERBOSE_STRINGS)
+#ifdef DEBUGBUILD
+  (void)lineno;
+#endif
+#else /* CURL_DISABLE_VERBOSE_STRINGS */
+  if(ftpc->state != newstate)
+#ifdef DEBUGBUILD
+    CURL_TRC_FTP(data, "[%s] -> [%s] (line %d)", FTP_DSTATE(data),
+                 ftp_state_names[newstate], lineno);
+#else
+    CURL_TRC_FTP(data, "[%s] -> [%s]", FTP_DSTATE(data),
+                 ftp_state_names[newstate]);
+#endif
+#endif /* !CURL_DISABLE_VERBOSE_STRINGS */
+
+  ftpc->state = newstate;
+}
+
 
 /* Local API functions */
 #ifndef DEBUGBUILD
-static void _ftp_state(struct Curl_easy *data,
-                       ftpstate newstate);
 #define ftp_state(x,y) _ftp_state(x,y)
-#else
-static void _ftp_state(struct Curl_easy *data,
-                       ftpstate newstate,
-                       int lineno);
+#else /* !DEBUGBUILD */
 #define ftp_state(x,y) _ftp_state(x,y,__LINE__)
-#endif
+#endif /* DEBUGBUILD */
 
 static CURLcode ftp_sendquote(struct Curl_easy *data,
                               struct connectdata *conn,
@@ -142,7 +221,7 @@ static CURLcode wc_statemach(struct Curl_easy *data);
 static void wc_data_dtor(void *ptr);
 static CURLcode ftp_state_retr(struct Curl_easy *data, curl_off_t filesize);
 static CURLcode ftp_readresp(struct Curl_easy *data,
-                             curl_socket_t sockfd,
+                             int sockindex,
                              struct pingpong *pp,
                              int *ftpcode,
                              size_t *size);
@@ -154,7 +233,7 @@ static CURLcode ftp_dophase_done(struct Curl_easy *data,
  */
 
 const struct Curl_handler Curl_handler_ftp = {
-  "FTP",                           /* scheme */
+  "ftp",                           /* scheme */
   ftp_setup_connection,            /* setup_connection */
   ftp_do,                          /* do_it */
   ftp_done,                        /* done */
@@ -167,7 +246,8 @@ const struct Curl_handler Curl_handler_ftp = {
   ftp_domore_getsock,              /* domore_getsock */
   ZERO_NULL,                       /* perform_getsock */
   ftp_disconnect,                  /* disconnect */
-  ZERO_NULL,                       /* readwrite */
+  ZERO_NULL,                       /* write_resp */
+  ZERO_NULL,                       /* write_resp_hd */
   ZERO_NULL,                       /* connection_check */
   ZERO_NULL,                       /* attach connection */
   PORT_FTP,                        /* defport */
@@ -185,7 +265,7 @@ const struct Curl_handler Curl_handler_ftp = {
  */
 
 const struct Curl_handler Curl_handler_ftps = {
-  "FTPS",                          /* scheme */
+  "ftps",                          /* scheme */
   ftp_setup_connection,            /* setup_connection */
   ftp_do,                          /* do_it */
   ftp_done,                        /* done */
@@ -198,7 +278,8 @@ const struct Curl_handler Curl_handler_ftps = {
   ftp_domore_getsock,              /* domore_getsock */
   ZERO_NULL,                       /* perform_getsock */
   ftp_disconnect,                  /* disconnect */
-  ZERO_NULL,                       /* readwrite */
+  ZERO_NULL,                       /* write_resp */
+  ZERO_NULL,                       /* write_resp_hd */
   ZERO_NULL,                       /* connection_check */
   ZERO_NULL,                       /* attach connection */
   PORT_FTPS,                       /* defport */
@@ -212,6 +293,7 @@ const struct Curl_handler Curl_handler_ftps = {
 static void close_secondarysocket(struct Curl_easy *data,
                                   struct connectdata *conn)
 {
+  CURL_TRC_FTP(data, "[%s] closing DATA connection", FTP_DSTATE(data));
   Curl_conn_close(data, SECONDARYSOCKET);
   Curl_conn_cf_discard_all(data, conn, SECONDARYSOCKET);
 }
@@ -246,6 +328,98 @@ static void freedirs(struct ftp_conn *ftpc)
   Curl_safefree(ftpc->newhost);
 }
 
+#ifdef CURL_DO_LINEEND_CONV
+/***********************************************************************
+ *
+ * Lineend Conversions
+ * On ASCII transfers, e.g. directory listings, we might get lines
+ * ending in '\r\n' and we prefer just '\n'.
+ * We might also get a lonely '\r' which we convert into a '\n'.
+ */
+struct ftp_cw_lc_ctx {
+  struct Curl_cwriter super;
+  bool newline_pending;
+};
+
+static CURLcode ftp_cw_lc_write(struct Curl_easy *data,
+                                struct Curl_cwriter *writer, int type,
+                                const char *buf, size_t blen)
+{
+  static const char nl = '\n';
+  struct ftp_cw_lc_ctx *ctx = writer->ctx;
+
+  if(!(type & CLIENTWRITE_BODY) ||
+     data->conn->proto.ftpc.transfertype != 'A')
+    return Curl_cwriter_write(data, writer->next, type, buf, blen);
+
+  /* ASCII mode BODY data, convert lineends */
+  while(blen) {
+    /* do not pass EOS when writing parts */
+    int chunk_type = (type & ~CLIENTWRITE_EOS);
+    const char *cp;
+    size_t chunk_len;
+    CURLcode result;
+
+    if(ctx->newline_pending) {
+      if(buf[0] != '\n') {
+        /* previous chunk ended in '\r' and we do not see a '\n' in this one,
+         * need to write a newline. */
+        result = Curl_cwriter_write(data, writer->next, chunk_type, &nl, 1);
+        if(result)
+          return result;
+      }
+      /* either we just wrote the newline or it is part of the next
+       * chunk of bytes we write. */
+      data->state.crlf_conversions++;
+      ctx->newline_pending = FALSE;
+    }
+
+    cp = memchr(buf, '\r', blen);
+    if(!cp)
+      break;
+
+    /* write the bytes before the '\r', excluding the '\r' */
+    chunk_len = cp - buf;
+    if(chunk_len) {
+      result = Curl_cwriter_write(data, writer->next, chunk_type,
+                                  buf, chunk_len);
+      if(result)
+        return result;
+    }
+    /* skip the '\r', we now have a newline pending */
+    buf = cp + 1;
+    blen = blen - chunk_len - 1;
+    ctx->newline_pending = TRUE;
+  }
+
+  /* Any remaining data does not contain a '\r' */
+  if(blen) {
+    DEBUGASSERT(!ctx->newline_pending);
+    return Curl_cwriter_write(data, writer->next, type, buf, blen);
+  }
+  else if(type & CLIENTWRITE_EOS) {
+    /* EndOfStream, if we have a trailing cr, now is the time to write it */
+    if(ctx->newline_pending) {
+      ctx->newline_pending = FALSE;
+      data->state.crlf_conversions++;
+      return Curl_cwriter_write(data, writer->next, type, &nl, 1);
+    }
+    /* Always pass on the EOS type indicator */
+    return Curl_cwriter_write(data, writer->next, type, buf, 0);
+  }
+  return CURLE_OK;
+}
+
+static const struct Curl_cwtype ftp_cw_lc = {
+  "ftp-lineconv",
+  NULL,
+  Curl_cwriter_def_init,
+  ftp_cw_lc_write,
+  Curl_cwriter_def_close,
+  sizeof(struct ftp_cw_lc_ctx)
+};
+
+#endif /* CURL_DO_LINEEND_CONV */
 /***********************************************************************
  *
  * AcceptServerConnect()
@@ -259,7 +433,7 @@ static CURLcode AcceptServerConnect(struct Curl_easy *data)
   struct connectdata *conn = data->conn;
   curl_socket_t sock = conn->sock[SECONDARYSOCKET];
   curl_socket_t s = CURL_SOCKET_BAD;
-#ifdef ENABLE_IPV6
+#ifdef USE_IPV6
   struct Curl_sockaddr_storage add;
 #else
   struct sockaddr_in add;
@@ -285,8 +459,10 @@ static CURLcode AcceptServerConnect(struct Curl_easy *data)
   (void)curlx_nonblock(s, TRUE); /* enable non-blocking */
   /* Replace any filter on SECONDARY with one listening on this socket */
   result = Curl_conn_tcp_accepted_set(data, conn, SECONDARYSOCKET, &s);
-  if(result)
+  if(result) {
+    sclose(s);
     return result;
+  }
 
   if(data->set.fsockopt) {
     int error = 0;
@@ -362,10 +538,11 @@ static CURLcode ReceivedServerConnect(struct Curl_easy *data, bool *received)
   curl_socket_t data_sock = conn->sock[SECONDARYSOCKET];
   struct ftp_conn *ftpc = &conn->proto.ftpc;
   struct pingpong *pp = &ftpc->pp;
-  int result;
+  int socketstate = 0;
   timediff_t timeout_ms;
   ssize_t nread;
   int ftpcode;
+  bool response = FALSE;
 
   *received = FALSE;
 
@@ -378,17 +555,21 @@ static CURLcode ReceivedServerConnect(struct Curl_easy *data, bool *received)
   }
 
   /* First check whether there is a cached response from server */
-  if(pp->cache_size && pp->cache && pp->cache[0] > '3') {
+  if(Curl_dyn_len(&pp->recvbuf) && (*Curl_dyn_ptr(&pp->recvbuf) > '3')) {
     /* Data connection could not be established, let's return */
     infof(data, "There is negative response in cache while serv connect");
     (void)Curl_GetFTPResponse(data, &nread, &ftpcode);
     return CURLE_FTP_ACCEPT_FAILED;
   }
 
-  result = Curl_socket_check(ctrl_sock, data_sock, CURL_SOCKET_BAD, 0);
+  if(pp->overflow)
+    /* there is pending control data still in the buffer to read */
+    response = TRUE;
+  else
+    socketstate = Curl_socket_check(ctrl_sock, data_sock, CURL_SOCKET_BAD, 0);
 
   /* see if the connection request is already here */
-  switch(result) {
+  switch(socketstate) {
   case -1: /* error */
     /* let's die here */
     failf(data, "Error while waiting for server connect");
@@ -396,23 +577,47 @@ static CURLcode ReceivedServerConnect(struct Curl_easy *data, bool *received)
   case 0:  /* Server connect is not received yet */
     break; /* loop */
   default:
-
-    if(result & CURL_CSELECT_IN2) {
+    if(socketstate & CURL_CSELECT_IN2) {
       infof(data, "Ready to accept data connection from server");
       *received = TRUE;
     }
-    else if(result & CURL_CSELECT_IN) {
-      infof(data, "Ctrl conn has data while waiting for data conn");
-      (void)Curl_GetFTPResponse(data, &nread, &ftpcode);
+    else if(socketstate & CURL_CSELECT_IN)
+      response = TRUE;
+    break;
+  }
+  if(response) {
+    infof(data, "Ctrl conn has data while waiting for data conn");
+    if(pp->overflow > 3) {
+      char *r = Curl_dyn_ptr(&pp->recvbuf);
+
+      DEBUGASSERT((pp->overflow + pp->nfinal) <=
+                  Curl_dyn_len(&pp->recvbuf));
+      /* move over the most recently handled response line */
+      r += pp->nfinal;
+
+      if(LASTLINE(r)) {
+        int status = curlx_sltosi(strtol(r, NULL, 10));
+        if(status == 226) {
+          /* funny timing situation where we get the final message on the
+             control connection before traffic on the data connection has been
+             noticed. Leave the 226 in there and use this as a trigger to read
+             the data socket. */
+          infof(data, "Got 226 before data activity");
+          *received = TRUE;
+          return CURLE_OK;
+        }
+      }
+    }
 
-      if(ftpcode/100 > 3)
-        return CURLE_FTP_ACCEPT_FAILED;
+    (void)Curl_GetFTPResponse(data, &nread, &ftpcode);
 
-      return CURLE_WEIRD_SERVER_REPLY;
-    }
+    infof(data, "FTP code: %03d", ftpcode);
 
-    break;
-  } /* switch() */
+    if(ftpcode/100 > 3)
+      return CURLE_FTP_ACCEPT_FAILED;
+
+    return CURLE_WEIRD_SERVER_REPLY;
+  }
 
   return CURLE_OK;
 }
@@ -432,7 +637,7 @@ static CURLcode InitiateTransfer(struct Curl_easy *data)
   struct connectdata *conn = data->conn;
   bool connected;
 
-  DEBUGF(infof(data, "ftp InitiateTransfer()"));
+  CURL_TRC_FTP(data, "InitiateTransfer()");
   if(conn->bits.ftp_use_data_ssl && data->set.ftp_use_port &&
      !Curl_conn_is_ssl(conn, SECONDARYSOCKET)) {
     result = Curl_ssl_cfilter_add(data, conn, SECONDARYSOCKET);
@@ -451,12 +656,12 @@ static CURLcode InitiateTransfer(struct Curl_easy *data)
     /* set the SO_SNDBUF for the secondary socket for those who need it */
     Curl_sndbufset(conn->sock[SECONDARYSOCKET]);
 
-    Curl_setup_transfer(data, -1, -1, FALSE, SECONDARYSOCKET);
+    Curl_xfer_setup(data, -1, -1, FALSE, SECONDARYSOCKET);
   }
   else {
     /* FTP download: */
-    Curl_setup_transfer(data, SECONDARYSOCKET,
-                        conn->proto.ftpc.retr_size_saved, FALSE, -1);
+    Curl_xfer_setup(data, SECONDARYSOCKET,
+                    conn->proto.ftpc.retr_size_saved, FALSE, -1);
   }
 
   conn->proto.ftpc.pp.pending_resp = TRUE; /* expect server response */
@@ -515,18 +720,10 @@ static CURLcode AllowServerConnect(struct Curl_easy *data, bool *connected)
   }
 
 out:
-  DEBUGF(infof(data, "ftp AllowServerConnect() -> %d", result));
+  CURL_TRC_FTP(data, "AllowServerConnect() -> %d", result);
   return result;
 }
 
-/* macro to check for a three-digit ftp status code at the start of the
-   given string */
-#define STATUSCODE(line) (ISDIGIT(line[0]) && ISDIGIT(line[1]) &&       \
-                          ISDIGIT(line[2]))
-
-/* macro to check for the last line in an FTP server response */
-#define LASTLINE(line) (STATUSCODE(line) && (' ' == line[3]))
-
 static bool ftp_endofresp(struct Curl_easy *data, struct connectdata *conn,
                           char *line, size_t len, int *code)
 {
@@ -542,18 +739,18 @@ static bool ftp_endofresp(struct Curl_easy *data, struct connectdata *conn,
 }
 
 static CURLcode ftp_readresp(struct Curl_easy *data,
-                             curl_socket_t sockfd,
+                             int sockindex,
                              struct pingpong *pp,
                              int *ftpcode, /* return the ftp-code if done */
                              size_t *size) /* size of the response */
 {
   int code;
-  CURLcode result = Curl_pp_readresp(data, sockfd, pp, &code, size);
+  CURLcode result = Curl_pp_readresp(data, sockindex, pp, &code, size);
 
 #ifdef HAVE_GSSAPI
   {
     struct connectdata *conn = data->conn;
-    char * const buf = data->state.buffer;
+    char * const buf = Curl_dyn_ptr(&data->conn->proto.ftpc.pp.recvbuf);
 
     /* handle the security-oriented responses 6xx ***/
     switch(code) {
@@ -659,7 +856,7 @@ CURLcode Curl_GetFTPResponse(struct Curl_easy *data,
      *
      */
 
-    if(pp->cache && (cache_skip < 2)) {
+    if(Curl_dyn_len(&pp->recvbuf) && (cache_skip < 2)) {
       /*
        * There's a cache left since before. We then skipping the wait for
        * socket action, unless this is the same cache like the previous round
@@ -683,11 +880,11 @@ CURLcode Curl_GetFTPResponse(struct Curl_easy *data,
         break;
       }
     }
-    result = ftp_readresp(data, sockfd, pp, ftpcode, &nread);
+    result = ftp_readresp(data, FIRSTSOCKET, pp, ftpcode, &nread);
     if(result)
       break;
 
-    if(!nread && pp->cache)
+    if(!nread && Curl_dyn_len(&pp->recvbuf))
       /* bump cache skip counter as on repeated skips we must wait for more
          data */
       cache_skip++;
@@ -705,73 +902,6 @@ CURLcode Curl_GetFTPResponse(struct Curl_easy *data,
   return result;
 }
 
-#if defined(DEBUGBUILD) && !defined(CURL_DISABLE_VERBOSE_STRINGS)
-  /* for debug purposes */
-static const char * const ftp_state_names[]={
-  "STOP",
-  "WAIT220",
-  "AUTH",
-  "USER",
-  "PASS",
-  "ACCT",
-  "PBSZ",
-  "PROT",
-  "CCC",
-  "PWD",
-  "SYST",
-  "NAMEFMT",
-  "QUOTE",
-  "RETR_PREQUOTE",
-  "STOR_PREQUOTE",
-  "POSTQUOTE",
-  "CWD",
-  "MKD",
-  "MDTM",
-  "TYPE",
-  "LIST_TYPE",
-  "RETR_TYPE",
-  "STOR_TYPE",
-  "SIZE",
-  "RETR_SIZE",
-  "STOR_SIZE",
-  "REST",
-  "RETR_REST",
-  "PORT",
-  "PRET",
-  "PASV",
-  "LIST",
-  "RETR",
-  "STOR",
-  "QUIT"
-};
-#endif
-
-/* This is the ONLY way to change FTP state! */
-static void _ftp_state(struct Curl_easy *data,
-                       ftpstate newstate
-#ifdef DEBUGBUILD
-                       , int lineno
-#endif
-  )
-{
-  struct connectdata *conn = data->conn;
-  struct ftp_conn *ftpc = &conn->proto.ftpc;
-
-#if defined(DEBUGBUILD)
-
-#if defined(CURL_DISABLE_VERBOSE_STRINGS)
-  (void) lineno;
-#else
-  if(ftpc->state != newstate)
-    infof(data, "FTP %p (line %d) state change from %s to %s",
-          (void *)ftpc, lineno, ftp_state_names[ftpc->state],
-          ftp_state_names[newstate]);
-#endif
-#endif
-
-  ftpc->state = newstate;
-}
-
 static CURLcode ftp_state_user(struct Curl_easy *data,
                                struct connectdata *conn)
 {
@@ -815,24 +945,18 @@ static int ftp_domore_getsock(struct Curl_easy *data,
    * remote site, or we could wait for that site to connect to us. Or just
    * handle ordinary commands.
    */
-
-  DEBUGF(infof(data, "ftp_domore_getsock()"));
-  if(conn->cfilter[SECONDARYSOCKET]
-     && !Curl_conn_is_connected(conn, SECONDARYSOCKET))
-    return Curl_conn_get_select_socks(data, SECONDARYSOCKET, socks);
+  CURL_TRC_FTP(data, "[%s] ftp_domore_getsock()", FTP_DSTATE(data));
 
   if(FTP_STOP == ftpc->state) {
-    int bits = GETSOCK_READSOCK(0);
-
     /* if stopped and still in this state, then we're also waiting for a
        connect on the secondary connection */
+    DEBUGASSERT(conn->sock[SECONDARYSOCKET] != CURL_SOCKET_BAD ||
+               (conn->cfilter[SECONDARYSOCKET] &&
+                !Curl_conn_is_connected(conn, SECONDARYSOCKET)));
     socks[0] = conn->sock[FIRSTSOCKET];
-    if(conn->sock[SECONDARYSOCKET] != CURL_SOCKET_BAD) {
-      socks[1] = conn->sock[SECONDARYSOCKET];
-      bits |= GETSOCK_WRITESOCK(1) | GETSOCK_READSOCK(1);
-    }
-
-    return bits;
+    /* An unconnected SECONDARY will add its socket by itself
+     * via its adjust_pollset() */
+    return GETSOCK_READSOCK(0);
   }
   return Curl_pp_getsock(data, &conn->proto.ftpc.pp, socks);
 }
@@ -911,7 +1035,7 @@ static CURLcode ftp_state_use_port(struct Curl_easy *data,
   char hbuf[NI_MAXHOST];
   struct sockaddr *sa = (struct sockaddr *)&ss;
   struct sockaddr_in * const sa4 = (void *)sa;
-#ifdef ENABLE_IPV6
+#ifdef USE_IPV6
   struct sockaddr_in6 * const sa6 = (void *)sa;
 #endif
   static const char mode[][5] = { "EPRT", "PORT" };
@@ -926,6 +1050,8 @@ static CURLcode ftp_state_use_port(struct Curl_easy *data,
   bool possibly_non_local = TRUE;
   char buffer[STRERROR_LEN];
   char *addr = NULL;
+  size_t addrlen = 0;
+  char ipstr[50];
 
   /* Step 1, figure out what is requested,
    * accepted format :
@@ -934,32 +1060,17 @@ static CURLcode ftp_state_use_port(struct Curl_easy *data,
 
   if(data->set.str[STRING_FTPPORT] &&
      (strlen(data->set.str[STRING_FTPPORT]) > 1)) {
-
-#ifdef ENABLE_IPV6
-    size_t addrlen = INET6_ADDRSTRLEN > strlen(string_ftpport) ?
-      INET6_ADDRSTRLEN : strlen(string_ftpport);
-#else
-    size_t addrlen = INET_ADDRSTRLEN > strlen(string_ftpport) ?
-      INET_ADDRSTRLEN : strlen(string_ftpport);
-#endif
-    char *ip_start = string_ftpport;
     char *ip_end = NULL;
-    char *port_start = NULL;
-    char *port_sep = NULL;
 
-    addr = calloc(addrlen + 1, 1);
-    if(!addr) {
-      result = CURLE_OUT_OF_MEMORY;
-      goto out;
-    }
-
-#ifdef ENABLE_IPV6
+#ifdef USE_IPV6
     if(*string_ftpport == '[') {
       /* [ipv6]:port(-range) */
-      ip_start = string_ftpport + 1;
-      ip_end = strchr(string_ftpport, ']');
-      if(ip_end)
-        strncpy(addr, ip_start, ip_end - ip_start);
+      char *ip_start = string_ftpport + 1;
+      ip_end = strchr(ip_start, ']');
+      if(ip_end) {
+        addrlen = ip_end - ip_start;
+        addr = ip_start;
+      }
     }
     else
 #endif
@@ -969,28 +1080,27 @@ static CURLcode ftp_state_use_port(struct Curl_easy *data,
       }
       else {
         ip_end = strchr(string_ftpport, ':');
+        addr = string_ftpport;
         if(ip_end) {
           /* either ipv6 or (ipv4|domain|interface):port(-range) */
-#ifdef ENABLE_IPV6
+          addrlen = ip_end - string_ftpport;
+#ifdef USE_IPV6
           if(Curl_inet_pton(AF_INET6, string_ftpport, &sa6->sin6_addr) == 1) {
             /* ipv6 */
             port_min = port_max = 0;
-            strcpy(addr, string_ftpport);
             ip_end = NULL; /* this got no port ! */
           }
-          else
 #endif
-            /* (ipv4|domain|interface):port(-range) */
-            strncpy(addr, string_ftpport, ip_end - ip_start);
         }
         else
           /* ipv4|interface */
-          strcpy(addr, string_ftpport);
+          addrlen = strlen(string_ftpport);
       }
 
     /* parse the port */
     if(ip_end) {
-      port_start = strchr(ip_end, ':');
+      char *port_sep = NULL;
+      char *port_start = strchr(ip_end, ':');
       if(port_start) {
         port_min = curlx_ultous(strtoul(port_start + 1, NULL, 10));
         port_sep = strchr(port_start, '-');
@@ -1011,22 +1121,29 @@ static CURLcode ftp_state_use_port(struct Curl_easy *data,
     if(port_min > port_max)
       port_min = port_max = 0;
 
-    if(*addr != '\0') {
+    if(addrlen) {
+      DEBUGASSERT(addr);
+      if(addrlen >= sizeof(ipstr))
+        goto out;
+      memcpy(ipstr, addr, addrlen);
+      ipstr[addrlen] = 0;
+
       /* attempt to get the address of the given interface name */
       switch(Curl_if2ip(conn->remote_addr->family,
-#ifdef ENABLE_IPV6
+#ifdef USE_IPV6
                         Curl_ipv6_scope(&conn->remote_addr->sa_addr),
                         conn->scope_id,
 #endif
-                        addr, hbuf, sizeof(hbuf))) {
+                        ipstr, hbuf, sizeof(hbuf))) {
         case IF2IP_NOT_FOUND:
           /* not an interface, use the given string as host name instead */
-          host = addr;
+          host = ipstr;
           break;
         case IF2IP_AF_NOT_SUPPORTED:
           goto out;
         case IF2IP_FOUND:
           host = hbuf; /* use the hbuf for host name */
+          break;
       }
     }
     else
@@ -1045,7 +1162,7 @@ static CURLcode ftp_state_use_port(struct Curl_easy *data,
       goto out;
     }
     switch(sa->sa_family) {
-#ifdef ENABLE_IPV6
+#ifdef USE_IPV6
     case AF_INET6:
       r = Curl_inet_ntop(sa->sa_family, &sa6->sin6_addr, hbuf, sizeof(hbuf));
       break;
@@ -1095,7 +1212,8 @@ static CURLcode ftp_state_use_port(struct Curl_easy *data,
           Curl_strerror(error, buffer, sizeof(buffer)));
     goto out;
   }
-  DEBUGF(infof(data, "ftp_state_use_port(), opened socket"));
+  CURL_TRC_FTP(data, "[%s] ftp_state_use_port(), opened socket",
+               FTP_DSTATE(data));
 
   /* step 3, bind to a suitable local address */
 
@@ -1105,7 +1223,7 @@ static CURLcode ftp_state_use_port(struct Curl_easy *data,
   for(port = port_min; port <= port_max;) {
     if(sa->sa_family == AF_INET)
       sa4->sin_port = htons(port);
-#ifdef ENABLE_IPV6
+#ifdef USE_IPV6
     else
       sa6->sin6_port = htons(port);
 #endif
@@ -1156,7 +1274,8 @@ static CURLcode ftp_state_use_port(struct Curl_easy *data,
           Curl_strerror(SOCKERRNO, buffer, sizeof(buffer)));
     goto out;
   }
-  DEBUGF(infof(data, "ftp_state_use_port(), socket bound to port %d", port));
+  CURL_TRC_FTP(data, "[%s] ftp_state_use_port(), socket bound to port %d",
+               FTP_DSTATE(data), port);
 
   /* step 4, listen on the socket */
 
@@ -1165,7 +1284,8 @@ static CURLcode ftp_state_use_port(struct Curl_easy *data,
           Curl_strerror(SOCKERRNO, buffer, sizeof(buffer)));
     goto out;
   }
-  DEBUGF(infof(data, "ftp_state_use_port(), listening on %d", port));
+  CURL_TRC_FTP(data, "[%s] ftp_state_use_port(), listening on %d",
+               FTP_DSTATE(data), port);
 
   /* step 5, send the proper FTP command */
 
@@ -1173,13 +1293,19 @@ static CURLcode ftp_state_use_port(struct Curl_easy *data,
      below */
   Curl_printable_address(ai, myhost, sizeof(myhost));
 
-#ifdef ENABLE_IPV6
+#ifdef USE_IPV6
   if(!conn->bits.ftp_use_eprt && conn->bits.ipv6)
     /* EPRT is disabled but we are connected to a IPv6 host, so we ignore the
        request and enable EPRT again! */
     conn->bits.ftp_use_eprt = TRUE;
 #endif
 
+  /* Replace any filter on SECONDARY with one listening on this socket */
+  result = Curl_conn_tcp_listen_set(data, conn, SECONDARYSOCKET, &portsock);
+  if(result)
+    goto out;
+  portsock = CURL_SOCKET_BAD; /* now held in filter */
+
   for(; fcmd != DONE; fcmd++) {
 
     if(!conn->bits.ftp_use_eprt && (EPRT == fcmd))
@@ -1194,7 +1320,7 @@ static CURLcode ftp_state_use_port(struct Curl_easy *data,
     case AF_INET:
       port = ntohs(sa4->sin_port);
       break;
-#ifdef ENABLE_IPV6
+#ifdef USE_IPV6
     case AF_INET6:
       port = ntohs(sa6->sin6_port);
       break;
@@ -1253,11 +1379,6 @@ static CURLcode ftp_state_use_port(struct Curl_easy *data,
   /* store which command was sent */
   ftpc->count1 = fcmd;
 
-  /* Replace any filter on SECONDARY with one listening on this socket */
-  result = Curl_conn_tcp_listen_set(data, conn, SECONDARYSOCKET, &portsock);
-  if(result)
-    goto out;
-  portsock = CURL_SOCKET_BAD; /* now held in filter */
   ftp_state(data, FTP_PORT);
 
 out:
@@ -1266,7 +1387,6 @@ static CURLcode ftp_state_use_port(struct Curl_easy *data,
   }
   if(portsock != CURL_SOCKET_BAD)
     Curl_socket_close(data, conn, portsock);
-  free(addr);
   return result;
 }
 
@@ -1574,10 +1694,10 @@ static CURLcode ftp_state_ul_setup(struct Curl_easy *data,
     append = TRUE;
 
     /* Let's read off the proper amount of bytes from the input. */
-    if(conn->seek_func) {
+    if(data->set.seek_func) {
       Curl_set_in_callback(data, true);
-      seekerr = conn->seek_func(conn->seek_client, data->state.resume_from,
-                                SEEK_SET);
+      seekerr = data->set.seek_func(data->set.seek_client,
+                                    data->state.resume_from, SEEK_SET);
       Curl_set_in_callback(data, false);
     }
 
@@ -1589,13 +1709,14 @@ static CURLcode ftp_state_ul_setup(struct Curl_easy *data,
       }
       /* seekerr == CURL_SEEKFUNC_CANTSEEK (can't seek to offset) */
       do {
+        char scratch[4*1024];
         size_t readthisamountnow =
-          (data->state.resume_from - passed > data->set.buffer_size) ?
-          (size_t)data->set.buffer_size :
+          (data->state.resume_from - passed > (curl_off_t)sizeof(scratch)) ?
+          sizeof(scratch) :
           curlx_sotouz(data->state.resume_from - passed);
 
         size_t actuallyread =
-          data->state.fread_func(data->state.buffer, 1, readthisamountnow,
+          data->state.fread_func(scratch, 1, readthisamountnow,
                                  data->state.in);
 
         passed += actuallyread;
@@ -1615,7 +1736,7 @@ static CURLcode ftp_state_ul_setup(struct Curl_easy *data,
         infof(data, "File already completely uploaded");
 
         /* no data to transfer */
-        Curl_setup_transfer(data, -1, -1, FALSE, -1);
+        Curl_xfer_setup(data, -1, -1, FALSE, -1);
 
         /* Set ->transfer so that we won't get any error in
          * ftp_done() because we didn't transfer anything! */
@@ -1793,7 +1914,7 @@ static char *control_address(struct connectdata *conn)
   if(conn->bits.tunnel_proxy || conn->bits.socksproxy)
     return conn->host.name;
 #endif
-  return conn->primary_ip;
+  return conn->primary.remote_ip;
 }
 
 static bool match_pasv_6nums(const char *p,
@@ -1828,7 +1949,9 @@ static CURLcode ftp_state_pasv_resp(struct Curl_easy *data,
   struct Curl_dns_entry *addr = NULL;
   enum resolve_t rc;
   unsigned short connectport; /* the local port connect() should use! */
-  char *str = &data->state.buffer[4];  /* start on the first letter */
+  struct pingpong *pp = &ftpc->pp;
+  char *str =
+    Curl_dyn_ptr(&pp->recvbuf) + 4; /* start on the first letter */
 
   /* if we come here again, make sure the former name is cleared */
   Curl_safefree(ftpc->newhost);
@@ -1928,14 +2051,14 @@ static CURLcode ftp_state_pasv_resp(struct Curl_easy *data,
      */
     const char * const host_name = conn->bits.socksproxy ?
       conn->socks_proxy.host.name : conn->http_proxy.host.name;
-    rc = Curl_resolv(data, host_name, conn->port, FALSE, &addr);
+    rc = Curl_resolv(data, host_name, conn->primary.remote_port, FALSE, &addr);
     if(rc == CURLRESOLV_PENDING)
       /* BLOCKING, ignores the return code but 'addr' will be NULL in
          case of failure */
       (void)Curl_resolver_wait_resolv(data, &addr);
 
-    connectport =
-      (unsigned short)conn->port; /* we connect to the proxy's port */
+    /* we connect to the proxy's port */
+    connectport = (unsigned short)conn->primary.remote_port;
 
     if(!addr) {
       failf(data, "Can't resolve proxy host %s:%hu", host_name, connectport);
@@ -2067,6 +2190,31 @@ static bool ftp_213_date(const char *p, int *year, int *month, int *day,
   return TRUE;
 }
 
+static CURLcode client_write_header(struct Curl_easy *data,
+                                    char *buf, size_t blen)
+{
+  /* Some replies from an FTP server are written to the client
+   * as CLIENTWRITE_HEADER, formatted as if they came from a
+   * HTTP conversation.
+   * In all protocols, CLIENTWRITE_HEADER data is only passed to
+   * the body write callback when data->set.include_header is set
+   * via CURLOPT_HEADER.
+   * For historic reasons, FTP never played this game and expects
+   * all its HEADERs to do that always. Set that flag during the
+   * call to Curl_client_write() so it does the right thing.
+   *
+   * Notice that we cannot enable this flag for FTP in general,
+   * as an FTP transfer might involve a HTTP proxy connection and
+   * headers from CONNECT should not automatically be part of the
+   * output. */
+  CURLcode result;
+  int save = data->set.include_header;
+  data->set.include_header = TRUE;
+  result = Curl_client_write(data, CLIENTWRITE_HEADER, buf, blen);
+  data->set.include_header = save? TRUE:FALSE;
+  return result;
+}
+
 static CURLcode ftp_state_mdtm_resp(struct Curl_easy *data,
                                     int ftpcode)
 {
@@ -2081,8 +2229,9 @@ static CURLcode ftp_state_mdtm_resp(struct Curl_easy *data,
       /* we got a time. Format should be: "YYYYMMDDHHMMSS[.sss]" where the
          last .sss part is optional and means fractions of a second */
       int year, month, day, hour, minute, second;
-      if(ftp_213_date(&data->state.buffer[4],
-                      &year, &month, &day, &hour, &minute, &second)) {
+      struct pingpong *pp = &ftpc->pp;
+      char *resp = Curl_dyn_ptr(&pp->recvbuf) + 4;
+      if(ftp_213_date(resp, &year, &month, &day, &hour, &minute, &second)) {
         /* we have a time, reformat it */
         char timebuf[24];
         msnprintf(timebuf, sizeof(timebuf),
@@ -2120,8 +2269,7 @@ static CURLcode ftp_state_mdtm_resp(struct Curl_easy *data,
                   tm->tm_hour,
                   tm->tm_min,
                   tm->tm_sec);
-        result = Curl_client_write(data, CLIENTWRITE_BOTH, headerbuf,
-                                   headerbuflen);
+        result = client_write_header(data, headerbuf, headerbuflen);
         if(result)
           return result;
       } /* end of a ridiculous amount of conditionals */
@@ -2212,7 +2360,7 @@ static CURLcode ftp_state_retr(struct Curl_easy *data,
   struct connectdata *conn = data->conn;
   struct ftp_conn *ftpc = &conn->proto.ftpc;
 
-  DEBUGF(infof(data, "ftp_state_retr()"));
+  CURL_TRC_FTP(data, "[%s] ftp_state_retr()", FTP_DSTATE(data));
   if(data->set.max_filesize && (filesize > data->set.max_filesize)) {
     failf(data, "Maximum file size exceeded");
     return CURLE_FILESIZE_EXCEEDED;
@@ -2259,7 +2407,7 @@ static CURLcode ftp_state_retr(struct Curl_easy *data,
 
     if(ftp->downloadsize == 0) {
       /* no data to transfer */
-      Curl_setup_transfer(data, -1, -1, FALSE, -1);
+      Curl_xfer_setup(data, -1, -1, FALSE, -1);
       infof(data, "File already completely downloaded");
 
       /* Set ->transfer so that we won't get any error in ftp_done()
@@ -2294,7 +2442,8 @@ static CURLcode ftp_state_size_resp(struct Curl_easy *data,
 {
   CURLcode result = CURLE_OK;
   curl_off_t filesize = -1;
-  char *buf = data->state.buffer;
+  char *buf = Curl_dyn_ptr(&data->conn->proto.ftpc.pp.recvbuf);
+  size_t len = data->conn->proto.ftpc.pp.nfinal;
 
   /* get the size from the ascii string: */
   if(ftpcode == 213) {
@@ -2302,13 +2451,13 @@ static CURLcode ftp_state_size_resp(struct Curl_easy *data,
        for all the digits at the end of the response and parse only those as a
        number. */
     char *start = &buf[4];
-    char *fdigit = strchr(start, '\r');
+    char *fdigit = memchr(start, '\r', len);
     if(fdigit) {
-      do
+      fdigit--;
+      if(*fdigit == '\n')
+        fdigit--;
+      while(ISDIGIT(fdigit[-1]) && (fdigit > start))
         fdigit--;
-      while(ISDIGIT(*fdigit) && (fdigit > start));
-      if(!ISDIGIT(*fdigit))
-        fdigit++;
     }
     else
       fdigit = start;
@@ -2331,7 +2480,7 @@ static CURLcode ftp_state_size_resp(struct Curl_easy *data,
       char clbuf[128];
       int clbuflen = msnprintf(clbuf, sizeof(clbuf),
                 "Content-Length: %" CURL_FORMAT_CURL_OFF_T "\r\n", filesize);
-      result = Curl_client_write(data, CLIENTWRITE_BOTH, clbuf, clbuflen);
+      result = client_write_header(data, clbuf, clbuflen);
       if(result)
         return result;
     }
@@ -2365,8 +2514,7 @@ static CURLcode ftp_state_rest_resp(struct Curl_easy *data,
 #ifdef CURL_FTP_HTTPSTYLE_HEAD
     if(ftpcode == 350) {
       char buffer[24]= { "Accept-ranges: bytes\r\n" };
-      result = Curl_client_write(data, CLIENTWRITE_BOTH, buffer,
-                                 strlen(buffer));
+      result = client_write_header(data, buffer, strlen(buffer));
       if(result)
         return result;
     }
@@ -2478,7 +2626,7 @@ static CURLcode ftp_state_get_resp(struct Curl_easy *data,
        *
        * Example D above makes this parsing a little tricky */
       char *bytes;
-      char *buf = data->state.buffer;
+      char *buf = Curl_dyn_ptr(&conn->proto.ftpc.pp.recvbuf);
       bytes = strstr(buf, " bytes");
       if(bytes) {
         long in = (long)(--bytes-buf);
@@ -2666,7 +2814,6 @@ static CURLcode ftp_statemachine(struct Curl_easy *data,
                                  struct connectdata *conn)
 {
   CURLcode result;
-  curl_socket_t sock = conn->sock[FIRSTSOCKET];
   int ftpcode;
   struct ftp_conn *ftpc = &conn->proto.ftpc;
   struct pingpong *pp = &ftpc->pp;
@@ -2676,7 +2823,7 @@ static CURLcode ftp_statemachine(struct Curl_easy *data,
   if(pp->sendleft)
     return Curl_pp_flushsend(data, pp);
 
-  result = ftp_readresp(data, sock, pp, &ftpcode, &nread);
+  result = ftp_readresp(data, FIRSTSOCKET, pp, &ftpcode, &nread);
   if(result)
     return result;
 
@@ -2747,7 +2894,7 @@ static CURLcode ftp_statemachine(struct Curl_easy *data,
     case FTP_AUTH:
       /* we have gotten the response to a previous AUTH command */
 
-      if(pp->cache_size)
+      if(pp->overflow)
         return CURLE_WEIRD_SERVER_REPLY; /* Forbid pipelining in response. */
 
       /* RFC2228 (page 5) says:
@@ -2845,14 +2992,11 @@ static CURLcode ftp_statemachine(struct Curl_easy *data,
 
     case FTP_PWD:
       if(ftpcode == 257) {
-        char *ptr = &data->state.buffer[4];  /* start on the first letter */
-        const size_t buf_size = data->set.buffer_size;
-        char *dir;
+        char *ptr = Curl_dyn_ptr(&pp->recvbuf) + 4; /* start on the first
+                                                       letter */
         bool entry_extracted = FALSE;
-
-        dir = malloc(nread + 1);
-        if(!dir)
-          return CURLE_OUT_OF_MEMORY;
+        struct dynbuf out;
+        Curl_dyn_init(&out, 1000);
 
         /* Reply format is like
            257[rubbish]"" and the
@@ -2864,33 +3008,30 @@ static CURLcode ftp_statemachine(struct Curl_easy *data,
         */
 
         /* scan for the first double-quote for non-standard responses */
-        while(ptr < &data->state.buffer[buf_size]
-              && *ptr != '\n' && *ptr != '\0' && *ptr != '"')
+        while(*ptr != '\n' && *ptr != '\0' && *ptr != '"')
           ptr++;
 
         if('\"' == *ptr) {
           /* it started good */
-          char *store;
-          ptr++;
-          for(store = dir; *ptr;) {
+          for(ptr++; *ptr; ptr++) {
             if('\"' == *ptr) {
               if('\"' == ptr[1]) {
                 /* "quote-doubling" */
-                *store = ptr[1];
+                result = Curl_dyn_addn(&out, &ptr[1], 1);
                 ptr++;
               }
               else {
                 /* end of path */
-                entry_extracted = TRUE;
+                if(Curl_dyn_len(&out))
+                  entry_extracted = TRUE;
                 break; /* get out of this loop */
               }
             }
             else
-              *store = *ptr;
-            store++;
-            ptr++;
+              result = Curl_dyn_addn(&out, ptr, 1);
+            if(result)
+              return result;
           }
-          *store = '\0'; /* null-terminate */
         }
         if(entry_extracted) {
           /* If the path name does not look like an absolute path (i.e.: it
@@ -2904,6 +3045,7 @@ static CURLcode ftp_statemachine(struct Curl_easy *data,
                The method used here is to check the server OS: we do it only
              if the path name looks strange to minimize overhead on other
              systems. */
+          char *dir = Curl_dyn_ptr(&out);
 
           if(!ftpc->server_os && dir[0] != '/') {
             result = Curl_pp_sendf(data, &ftpc->pp, "%s", "SYST");
@@ -2928,35 +3070,33 @@ static CURLcode ftp_statemachine(struct Curl_easy *data,
         }
         else {
           /* couldn't get the path */
-          free(dir);
+          Curl_dyn_free(&out);
           infof(data, "Failed to figure out path");
         }
       }
       ftp_state(data, FTP_STOP); /* we are done with the CONNECT phase! */
-      DEBUGF(infof(data, "protocol connect phase DONE"));
+      CURL_TRC_FTP(data, "[%s] protocol connect phase DONE", FTP_DSTATE(data));
       break;
 
     case FTP_SYST:
       if(ftpcode == 215) {
-        char *ptr = &data->state.buffer[4];  /* start on the first letter */
+        char *ptr = Curl_dyn_ptr(&pp->recvbuf) + 4; /* start on the first
+                                                       letter */
         char *os;
-        char *store;
-
-        os = malloc(nread + 1);
-        if(!os)
-          return CURLE_OUT_OF_MEMORY;
+        char *start;
 
         /* Reply format is like
            215
         */
         while(*ptr == ' ')
           ptr++;
-        for(store = os; *ptr && *ptr != ' ';)
-          *store++ = *ptr++;
-        *store = '\0'; /* null-terminate */
+        for(start = ptr; *ptr && *ptr != ' '; ptr++)
+          ;
+        os = Curl_memdup0(start, ptr - start);
+        if(!os)
+          return CURLE_OUT_OF_MEMORY;
 
         /* Check for special servers here. */
-
         if(strcasecompare(os, "OS/400")) {
           /* Force OS400 name format 1. */
           result = Curl_pp_sendf(data, &ftpc->pp, "%s", "SITE NAMEFMT 1");
@@ -2980,7 +3120,7 @@ static CURLcode ftp_statemachine(struct Curl_easy *data,
       }
 
       ftp_state(data, FTP_STOP); /* we are done with the CONNECT phase! */
-      DEBUGF(infof(data, "protocol connect phase DONE"));
+      CURL_TRC_FTP(data, "[%s] protocol connect phase DONE", FTP_DSTATE(data));
       break;
 
     case FTP_NAMEFMT:
@@ -2991,7 +3131,7 @@ static CURLcode ftp_statemachine(struct Curl_easy *data,
       }
 
       ftp_state(data, FTP_STOP); /* we are done with the CONNECT phase! */
-      DEBUGF(infof(data, "protocol connect phase DONE"));
+      CURL_TRC_FTP(data, "[%s] protocol connect phase DONE", FTP_DSTATE(data));
       break;
 
     case FTP_QUOTE:
@@ -3108,7 +3248,6 @@ static CURLcode ftp_statemachine(struct Curl_easy *data,
       break;
 
     case FTP_QUIT:
-      /* fallthrough, just stop! */
     default:
       /* internal error */
       ftp_state(data, FTP_STOP);
@@ -3183,8 +3322,7 @@ static CURLcode ftp_connect(struct Curl_easy *data,
     conn->bits.ftp_use_control_ssl = TRUE;
   }
 
-  Curl_pp_setup(pp); /* once per transfer */
-  Curl_pp_init(data, pp); /* init the generic pingpong data */
+  Curl_pp_init(pp); /* once per transfer */
 
   /* When we connect, we start in the state where we await the 220
      response */
@@ -3235,14 +3373,13 @@ static CURLcode ftp_done(struct Curl_easy *data, CURLcode status,
   case CURLE_REMOTE_FILE_NOT_FOUND:
   case CURLE_WRITE_ERROR:
     /* the connection stays alive fine even though this happened */
-    /* fall-through */
   case CURLE_OK: /* doesn't affect the control connection's status */
     if(!premature)
       break;
 
     /* until we cope better with prematurely ended requests, let them
      * fallback as if in complete failure */
-    /* FALLTHROUGH */
+    FALLTHROUGH();
   default:       /* by default, an error means the control connection is
                     wedged and should not be used anymore */
     ftpc->ctl_valid = FALSE;
@@ -3423,6 +3560,7 @@ static CURLcode ftp_done(struct Curl_easy *data, CURLcode status,
   /* Send any post-transfer QUOTE strings? */
   if(!status && !result && !premature && data->set.postquote)
     result = ftp_sendquote(data, conn, data->set.postquote);
+  CURL_TRC_FTP(data, "[%s] done, result=%d", FTP_DSTATE(data), result);
   Curl_safefree(ftp->pathalloc);
   return result;
 }
@@ -3457,7 +3595,7 @@ CURLcode ftp_sendquote(struct Curl_easy *data,
       /* if a command starts with an asterisk, which a legal FTP command never
          can, the command will be allowed to fail without it causing any
          aborts or cancels etc. It will cause libcurl to act as if the command
-         is successful, whatever the server reponds. */
+         is successful, whatever the server responds. */
 
       if(cmd[0] == '*') {
         cmd++;
@@ -3686,12 +3824,13 @@ static CURLcode ftp_do_more(struct Curl_easy *data, int *completep)
   }
 
   /* no data to transfer */
-  Curl_setup_transfer(data, -1, -1, FALSE, -1);
+  Curl_xfer_setup(data, -1, -1, FALSE, -1);
 
   if(!ftpc->wait_data_conn) {
     /* no waiting for the data connection so this is now complete */
     *completep = 1;
-    DEBUGF(infof(data, "DO-MORE phase ends with %d", (int)result));
+    CURL_TRC_FTP(data, "[%s] DO-MORE phase ends with %d", FTP_DSTATE(data),
+                 (int)result);
   }
 
   return result;
@@ -3715,7 +3854,7 @@ CURLcode ftp_perform(struct Curl_easy *data,
   /* this is FTP and no proxy */
   CURLcode result = CURLE_OK;
 
-  DEBUGF(infof(data, "DO phase starts"));
+  CURL_TRC_FTP(data, "[%s] DO phase starts", FTP_DSTATE(data));
 
   if(data->req.no_body) {
     /* requested no body means no transfer... */
@@ -3735,10 +3874,15 @@ CURLcode ftp_perform(struct Curl_easy *data,
 
   *connected = Curl_conn_is_connected(data->conn, SECONDARYSOCKET);
 
-  infof(data, "ftp_perform ends with SECONDARY: %d", *connected);
+  if(*connected)
+    infof(data, "[FTP] [%s] perform, DATA connection established",
+          FTP_DSTATE(data));
+  else
+    CURL_TRC_FTP(data, "[%s] perform, awaiting DATA connect",
+                 FTP_DSTATE(data));
 
   if(*dophase_done)
-    DEBUGF(infof(data, "DO phase is complete1"));
+    CURL_TRC_FTP(data, "[%s] DO phase is complete1", FTP_DSTATE(data));
 
   return result;
 }
@@ -3994,6 +4138,24 @@ static CURLcode ftp_do(struct Curl_easy *data, bool *done)
   *done = FALSE; /* default to false */
   ftpc->wait_data_conn = FALSE; /* default to no such wait */
 
+#ifdef CURL_DO_LINEEND_CONV
+  {
+    /* FTP data may need conversion. */
+    struct Curl_cwriter *ftp_lc_writer;
+
+    result = Curl_cwriter_create(&ftp_lc_writer, data, &ftp_cw_lc,
+                                 CURL_CW_CONTENT_DECODE);
+    if(result)
+      return result;
+
+    result = Curl_cwriter_add(data, ftp_lc_writer);
+    if(result) {
+      Curl_cwriter_free(data, ftp_lc_writer);
+      return result;
+    }
+  }
+#endif /* CURL_DO_LINEEND_CONV */
+
   if(data->state.wildcardmatch) {
     result = wc_statemach(data);
     if(data->wildcard->state == CURLWC_SKIP ||
@@ -4154,13 +4316,12 @@ CURLcode ftp_parse_url_path(struct Curl_easy *data)
           return CURLE_OUT_OF_MEMORY;
         }
 
-        ftpc->dirs[0] = calloc(1, dirlen + 1);
+        ftpc->dirs[0] = Curl_memdup0(rawPath, dirlen);
         if(!ftpc->dirs[0]) {
           free(rawPath);
           return CURLE_OUT_OF_MEMORY;
         }
 
-        strncpy(ftpc->dirs[0], rawPath, dirlen);
         ftpc->dirdepth = 1; /* we consider it to be a single dir */
         fileName = slashPos + 1; /* rest is file name */
       }
@@ -4199,12 +4360,11 @@ CURLcode ftp_parse_url_path(struct Curl_easy *data)
              CWD requires a parameter and a non-existent parameter a) doesn't
              work on many servers and b) has no effect on the others. */
           if(compLen > 0) {
-            char *comp = calloc(1, compLen + 1);
+            char *comp = Curl_memdup0(curPos, compLen);
             if(!comp) {
               free(rawPath);
               return CURLE_OUT_OF_MEMORY;
             }
-            strncpy(comp, curPos, compLen);
             ftpc->dirs[ftpc->dirdepth++] = comp;
           }
           curPos = slashPos + 1;
@@ -4272,7 +4432,7 @@ static CURLcode ftp_dophase_done(struct Curl_easy *data, bool connected)
 
   if(ftp->transfer != PPTRANSFER_BODY)
     /* no data to transfer */
-    Curl_setup_transfer(data, -1, -1, FALSE, -1);
+    Curl_xfer_setup(data, -1, -1, FALSE, -1);
   else if(!connected)
     /* since we didn't connect now, we want do_more to get called */
     conn->bits.do_more = TRUE;
@@ -4289,11 +4449,11 @@ static CURLcode ftp_doing(struct Curl_easy *data,
   CURLcode result = ftp_multi_statemach(data, dophase_done);
 
   if(result)
-    DEBUGF(infof(data, "DO phase failed"));
+    CURL_TRC_FTP(data, "[%s] DO phase failed", FTP_DSTATE(data));
   else if(*dophase_done) {
     result = ftp_dophase_done(data, FALSE /* not connected */);
 
-    DEBUGF(infof(data, "DO phase is complete2"));
+    CURL_TRC_FTP(data, "[%s] DO phase is complete2", FTP_DSTATE(data));
   }
   return result;
 }
@@ -4356,7 +4516,7 @@ static CURLcode ftp_setup_connection(struct Curl_easy *data,
   CURLcode result = CURLE_OK;
   struct ftp_conn *ftpc = &conn->proto.ftpc;
 
-  ftp = calloc(sizeof(struct FTP), 1);
+  ftp = calloc(1, sizeof(struct FTP));
   if(!ftp)
     return CURLE_OUT_OF_MEMORY;
 
@@ -4417,6 +4577,7 @@ static CURLcode ftp_setup_connection(struct Curl_easy *data,
   ftpc->use_ssl = data->set.use_ssl;
   ftpc->ccc = data->set.ftp_ccc;
 
+  CURL_TRC_FTP(data, "[%s] setup connection -> %d", FTP_CSTATE(conn), result);
   return result;
 }
 
diff --git a/vendor/curl/lib/ftplistparser.c b/vendor/curl/lib/ftplistparser.c
index 226d9bc033..448f3a43ab 100644
--- a/vendor/curl/lib/ftplistparser.c
+++ b/vendor/curl/lib/ftplistparser.c
@@ -55,9 +55,6 @@
 /* The last #include file should be: */
 #include "memdebug.h"
 
-/* allocs buffer which will contain one line of LIST command response */
-#define FTP_BUFFER_ALLOCSIZE 160
-
 typedef enum {
   PL_UNIX_TOTALSIZE = 0,
   PL_UNIX_FILETYPE,
@@ -352,7 +349,7 @@ static CURLcode ftp_pl_insert_finfo(struct Curl_easy *data,
   Curl_set_in_callback(data, false);
 
   if(add) {
-    Curl_llist_insert_next(llist, llist->tail, finfo, &infop->list);
+    Curl_llist_append(llist, finfo, &infop->list);
   }
   else {
     Curl_fileinfo_cleanup(infop);
@@ -379,7 +376,7 @@ size_t Curl_ftp_parselist(char *buffer, size_t size, size_t nmemb,
     /* scenario:
      * 1. call => OK..
      * 2. call => OUT_OF_MEMORY (or other error)
-     * 3. (last) call => is skipped RIGHT HERE and the error is hadled later
+     * 3. (last) call => is skipped RIGHT HERE and the error is handled later
      *    in wc_statemach()
      */
     goto fail;
diff --git a/vendor/curl/lib/functypes.h b/vendor/curl/lib/functypes.h
index 075c02e54f..ea66d3281d 100644
--- a/vendor/curl/lib/functypes.h
+++ b/vendor/curl/lib/functypes.h
@@ -38,7 +38,7 @@
    2. For systems with config-*.h files, define them there.
 */
 
-#ifdef WIN32
+#ifdef _WIN32
 /* int recv(SOCKET, char *, int, int) */
 #define RECV_TYPE_ARG1 SOCKET
 #define RECV_TYPE_ARG2 char *
diff --git a/vendor/curl/lib/getenv.c b/vendor/curl/lib/getenv.c
index 8069784728..48ee972289 100644
--- a/vendor/curl/lib/getenv.c
+++ b/vendor/curl/lib/getenv.c
@@ -31,10 +31,11 @@
 
 static char *GetEnv(const char *variable)
 {
-#if defined(_WIN32_WCE) || defined(CURL_WINDOWS_APP)
+#if defined(_WIN32_WCE) || defined(CURL_WINDOWS_APP) || \
+  defined(__ORBIS__) || defined(__PROSPERO__) /* PlayStation 4 and 5 */
   (void)variable;
   return NULL;
-#elif defined(WIN32)
+#elif defined(_WIN32)
   /* This uses Windows API instead of C runtime getenv() to get the environment
      variable since some changes aren't always visible to the latter. #4774 */
   char *buf = NULL;
diff --git a/vendor/curl/lib/getinfo.c b/vendor/curl/lib/getinfo.c
index f1574e097b..e423f0b29a 100644
--- a/vendor/curl/lib/getinfo.c
+++ b/vendor/curl/lib/getinfo.c
@@ -76,10 +76,10 @@ CURLcode Curl_initinfo(struct Curl_easy *data)
   free(info->wouldredirect);
   info->wouldredirect = NULL;
 
-  info->conn_primary_ip[0] = '\0';
-  info->conn_local_ip[0] = '\0';
-  info->conn_primary_port = 0;
-  info->conn_local_port = 0;
+  info->primary.remote_ip[0] = '\0';
+  info->primary.local_ip[0] = '\0';
+  info->primary.remote_port = 0;
+  info->primary.local_port = 0;
   info->retry_after = 0;
 
   info->conn_scheme = 0;
@@ -153,15 +153,19 @@ static CURLcode getinfo_char(struct Curl_easy *data, CURLINFO info,
     break;
   case CURLINFO_PRIMARY_IP:
     /* Return the ip address of the most recent (primary) connection */
-    *param_charp = data->info.conn_primary_ip;
+    *param_charp = data->info.primary.remote_ip;
     break;
   case CURLINFO_LOCAL_IP:
     /* Return the source/local ip address of the most recent (primary)
        connection */
-    *param_charp = data->info.conn_local_ip;
+    *param_charp = data->info.primary.local_ip;
     break;
   case CURLINFO_RTSP_SESSION_ID:
+#ifndef CURL_DISABLE_RTSP
     *param_charp = data->set.str[STRING_RTSP_SESSION_ID];
+#else
+    *param_charp = NULL;
+#endif
     break;
   case CURLINFO_SCHEME:
     *param_charp = data->info.conn_scheme;
@@ -180,7 +184,6 @@ static CURLcode getinfo_char(struct Curl_easy *data, CURLINFO info,
     *param_charp = NULL;
 #endif
     break;
-
   default:
     return CURLE_UNKNOWN_OPTION;
   }
@@ -285,11 +288,11 @@ static CURLcode getinfo_long(struct Curl_easy *data, CURLINFO info,
     break;
   case CURLINFO_PRIMARY_PORT:
     /* Return the (remote) port of the most recent (primary) connection */
-    *param_longp = data->info.conn_primary_port;
+    *param_longp = data->info.primary.remote_port;
     break;
   case CURLINFO_LOCAL_PORT:
     /* Return the local port of the most recent (primary) connection */
-    *param_longp = data->info.conn_local_port;
+    *param_longp = data->info.primary.local_port;
     break;
   case CURLINFO_PROXY_ERROR:
     *param_longp = (long)data->info.pxcode;
@@ -334,6 +337,15 @@ static CURLcode getinfo_long(struct Curl_easy *data, CURLINFO info,
   case CURLINFO_PROTOCOL:
     *param_longp = data->info.conn_protocol;
     break;
+  case CURLINFO_USED_PROXY:
+    *param_longp =
+#ifdef CURL_DISABLE_PROXY
+      0
+#else
+      data->info.used_proxy
+#endif
+      ;
+    break;
   default:
     return CURLE_UNKNOWN_OPTION;
   }
@@ -409,6 +421,9 @@ static CURLcode getinfo_offt(struct Curl_easy *data, CURLINFO info,
   case CURLINFO_STARTTRANSFER_TIME_T:
     *param_offt = data->progress.t_starttransfer;
     break;
+  case CURLINFO_QUEUE_TIME_T:
+    *param_offt = data->progress.t_postqueue;
+    break;
   case CURLINFO_REDIRECT_TIME_T:
     *param_offt = data->progress.t_redirect;
     break;
@@ -420,7 +435,7 @@ static CURLcode getinfo_offt(struct Curl_easy *data, CURLINFO info,
     break;
   case CURLINFO_CONN_ID:
     *param_offt = data->conn?
-                  data->conn->connection_id : data->state.recent_conn_id;
+      data->conn->connection_id : data->state.recent_conn_id;
     break;
   default:
     return CURLE_UNKNOWN_OPTION;
diff --git a/vendor/curl/lib/gopher.c b/vendor/curl/lib/gopher.c
index 61e41b7e47..311bd3798e 100644
--- a/vendor/curl/lib/gopher.c
+++ b/vendor/curl/lib/gopher.c
@@ -62,7 +62,7 @@ static CURLcode gopher_connecting(struct Curl_easy *data, bool *done);
  */
 
 const struct Curl_handler Curl_handler_gopher = {
-  "GOPHER",                             /* scheme */
+  "gopher",                             /* scheme */
   ZERO_NULL,                            /* setup_connection */
   gopher_do,                            /* do_it */
   ZERO_NULL,                            /* done */
@@ -75,7 +75,8 @@ const struct Curl_handler Curl_handler_gopher = {
   ZERO_NULL,                            /* domore_getsock */
   ZERO_NULL,                            /* perform_getsock */
   ZERO_NULL,                            /* disconnect */
-  ZERO_NULL,                            /* readwrite */
+  ZERO_NULL,                            /* write_resp */
+  ZERO_NULL,                            /* write_resp_hd */
   ZERO_NULL,                            /* connection_check */
   ZERO_NULL,                            /* attach connection */
   PORT_GOPHER,                          /* defport */
@@ -86,7 +87,7 @@ const struct Curl_handler Curl_handler_gopher = {
 
 #ifdef USE_SSL
 const struct Curl_handler Curl_handler_gophers = {
-  "GOPHERS",                            /* scheme */
+  "gophers",                            /* scheme */
   ZERO_NULL,                            /* setup_connection */
   gopher_do,                            /* do_it */
   ZERO_NULL,                            /* done */
@@ -99,7 +100,8 @@ const struct Curl_handler Curl_handler_gophers = {
   ZERO_NULL,                            /* domore_getsock */
   ZERO_NULL,                            /* perform_getsock */
   ZERO_NULL,                            /* disconnect */
-  ZERO_NULL,                            /* readwrite */
+  ZERO_NULL,                            /* write_resp */
+  ZERO_NULL,                            /* write_resp_hd */
   ZERO_NULL,                            /* connection_check */
   ZERO_NULL,                            /* attach connection */
   PORT_GOPHER,                          /* defport */
@@ -139,8 +141,8 @@ static CURLcode gopher_do(struct Curl_easy *data, bool *done)
   char *sel = NULL;
   char *sel_org = NULL;
   timediff_t timeout_ms;
-  ssize_t amount, k;
-  size_t len;
+  ssize_t k;
+  size_t amount, len;
   int what;
 
   *done = TRUE; /* unconditionally */
@@ -185,7 +187,7 @@ static CURLcode gopher_do(struct Curl_easy *data, bool *done)
     if(strlen(sel) < 1)
       break;
 
-    result = Curl_nwrite(data, FIRSTSOCKET, sel, k, &amount);
+    result = Curl_xfer_send(data, sel, k, &amount);
     if(!result) { /* Which may not have written it all! */
       result = Curl_client_write(data, CLIENTWRITE_HEADER, sel, amount);
       if(result)
@@ -227,7 +229,7 @@ static CURLcode gopher_do(struct Curl_easy *data, bool *done)
   free(sel_org);
 
   if(!result)
-    result = Curl_nwrite(data, FIRSTSOCKET, "\r\n", 2, &amount);
+    result = Curl_xfer_send(data, "\r\n", 2, &amount);
   if(result) {
     failf(data, "Failed sending Gopher request");
     return result;
@@ -236,7 +238,7 @@ static CURLcode gopher_do(struct Curl_easy *data, bool *done)
   if(result)
     return result;
 
-  Curl_setup_transfer(data, FIRSTSOCKET, -1, FALSE, -1);
+  Curl_xfer_setup(data, FIRSTSOCKET, -1, FALSE, -1);
   return CURLE_OK;
 }
 #endif /* CURL_DISABLE_GOPHER */
diff --git a/vendor/curl/lib/hash.c b/vendor/curl/lib/hash.c
index 30f28e2352..ddbae4d3e1 100644
--- a/vendor/curl/lib/hash.c
+++ b/vendor/curl/lib/hash.c
@@ -57,7 +57,7 @@ hash_element_dtor(void *user, void *element)
  */
 void
 Curl_hash_init(struct Curl_hash *h,
-               int slots,
+               size_t slots,
                hash_function hfunc,
                comp_function comparator,
                Curl_hash_dtor dtor)
@@ -111,7 +111,7 @@ Curl_hash_add(struct Curl_hash *h, void *key, size_t key_len, void *p)
   DEBUGASSERT(h);
   DEBUGASSERT(h->slots);
   if(!h->table) {
-    int i;
+    size_t i;
     h->table = malloc(h->slots * sizeof(struct Curl_llist));
     if(!h->table)
       return NULL; /* OOM */
@@ -132,7 +132,7 @@ Curl_hash_add(struct Curl_hash *h, void *key, size_t key_len, void *p)
 
   he = mk_hash_element(key, key_len, p);
   if(he) {
-    Curl_llist_insert_next(l, l->tail, he, &he->list);
+    Curl_llist_append(l, he, &he->list);
     ++h->size;
     return p; /* return the new entry */
   }
@@ -192,25 +192,6 @@ Curl_hash_pick(struct Curl_hash *h, void *key, size_t key_len)
   return NULL;
 }
 
-#if defined(DEBUGBUILD) && defined(AGGRESSIVE_TEST)
-void
-Curl_hash_apply(Curl_hash *h, void *user,
-                void (*cb)(void *user, void *ptr))
-{
-  struct Curl_llist_element  *le;
-  int                  i;
-
-  for(i = 0; i < h->slots; ++i) {
-    for(le = (h->table[i])->head;
-        le;
-        le = le->next) {
-      Curl_hash_element *el = le->ptr;
-      cb(user, el->ptr);
-    }
-  }
-}
-#endif
-
 /* Destroys all the entries in the given hash and resets its attributes,
  * prepping the given hash for [static|dynamic] deallocation.
  *
@@ -222,7 +203,7 @@ void
 Curl_hash_destroy(struct Curl_hash *h)
 {
   if(h->table) {
-    int i;
+    size_t i;
     for(i = 0; i < h->slots; ++i) {
       Curl_llist_destroy(&h->table[i], (void *) h);
     }
@@ -250,7 +231,7 @@ Curl_hash_clean_with_criterium(struct Curl_hash *h, void *user,
   struct Curl_llist_element *le;
   struct Curl_llist_element *lnext;
   struct Curl_llist *list;
-  int i;
+  size_t i;
 
   if(!h || !h->table)
     return;
@@ -316,7 +297,7 @@ Curl_hash_next_element(struct Curl_hash_iterator *iter)
 
   /* If we have reached the end of the list, find the next one */
   if(!iter->current_element) {
-    int i;
+    size_t i;
     for(i = iter->slot_index; i < h->slots; i++) {
       if(h->table[i].head) {
         iter->current_element = h->table[i].head;
@@ -339,7 +320,7 @@ void Curl_hash_print(struct Curl_hash *h,
 {
   struct Curl_hash_iterator iter;
   struct Curl_hash_element *he;
-  int last_index = -1;
+  size_t last_index = ~0;
 
   if(!h)
     return;
@@ -352,7 +333,7 @@ void Curl_hash_print(struct Curl_hash *h,
   while(he) {
     if(iter.slot_index != last_index) {
       fprintf(stderr, "index %d:", iter.slot_index);
-      if(last_index >= 0) {
+      if(last_index != ~0) {
         fprintf(stderr, "\n");
       }
       last_index = iter.slot_index;
@@ -368,3 +349,25 @@ void Curl_hash_print(struct Curl_hash *h,
   fprintf(stderr, "\n");
 }
 #endif
+
+void Curl_hash_offt_init(struct Curl_hash *h,
+                         size_t slots,
+                         Curl_hash_dtor dtor)
+{
+  Curl_hash_init(h, slots, Curl_hash_str, Curl_str_key_compare, dtor);
+}
+
+void *Curl_hash_offt_set(struct Curl_hash *h, curl_off_t id, void *elem)
+{
+  return Curl_hash_add(h, &id, sizeof(id), elem);
+}
+
+int Curl_hash_offt_remove(struct Curl_hash *h, curl_off_t id)
+{
+  return Curl_hash_delete(h, &id, sizeof(id));
+}
+
+void *Curl_hash_offt_get(struct Curl_hash *h, curl_off_t id)
+{
+  return Curl_hash_pick(h, &id, sizeof(id));
+}
diff --git a/vendor/curl/lib/hash.h b/vendor/curl/lib/hash.h
index 9cfffc25b0..2bdc247172 100644
--- a/vendor/curl/lib/hash.h
+++ b/vendor/curl/lib/hash.h
@@ -54,7 +54,7 @@ struct Curl_hash {
   /* Comparator function to compare keys */
   comp_function comp_func;
   Curl_hash_dtor   dtor;
-  int slots;
+  size_t slots;
   size_t size;
 };
 
@@ -67,12 +67,12 @@ struct Curl_hash_element {
 
 struct Curl_hash_iterator {
   struct Curl_hash *hash;
-  int slot_index;
+  size_t slot_index;
   struct Curl_llist_element *current_element;
 };
 
 void Curl_hash_init(struct Curl_hash *h,
-                    int slots,
+                    size_t slots,
                     hash_function hfunc,
                     comp_function comparator,
                     Curl_hash_dtor dtor);
@@ -80,8 +80,6 @@ void Curl_hash_init(struct Curl_hash *h,
 void *Curl_hash_add(struct Curl_hash *h, void *key, size_t key_len, void *p);
 int Curl_hash_delete(struct Curl_hash *h, void *key, size_t key_len);
 void *Curl_hash_pick(struct Curl_hash *, void *key, size_t key_len);
-void Curl_hash_apply(struct Curl_hash *h, void *user,
-                     void (*cb)(void *user, void *ptr));
 #define Curl_hash_count(h) ((h)->size)
 void Curl_hash_destroy(struct Curl_hash *h);
 void Curl_hash_clean(struct Curl_hash *h);
@@ -98,5 +96,13 @@ Curl_hash_next_element(struct Curl_hash_iterator *iter);
 void Curl_hash_print(struct Curl_hash *h,
                      void (*func)(void *));
 
+/* Hash for `curl_off_t` as key */
+void Curl_hash_offt_init(struct Curl_hash *h, size_t slots,
+                         Curl_hash_dtor dtor);
+
+void *Curl_hash_offt_set(struct Curl_hash *h, curl_off_t id, void *elem);
+int Curl_hash_offt_remove(struct Curl_hash *h, curl_off_t id);
+void *Curl_hash_offt_get(struct Curl_hash *h, curl_off_t id);
+
 
 #endif /* HEADER_CURL_HASH_H */
diff --git a/vendor/curl/lib/headers.c b/vendor/curl/lib/headers.c
index 3ff4d5eb07..9a5692e54e 100644
--- a/vendor/curl/lib/headers.c
+++ b/vendor/curl/lib/headers.c
@@ -27,6 +27,7 @@
 #include "urldata.h"
 #include "strdup.h"
 #include "strcase.h"
+#include "sendf.h"
 #include "headers.h"
 
 /* The last 3 #include files should be in this order */
@@ -185,7 +186,7 @@ struct curl_header *curl_easy_nextheader(CURL *easy,
 }
 
 static CURLcode namevalue(char *header, size_t hlen, unsigned int type,
-                           char **name, char **value)
+                          char **name, char **value)
 {
   char *end = header + hlen - 1; /* point to the last byte */
   DEBUGASSERT(hlen);
@@ -252,7 +253,7 @@ static CURLcode unfold_value(struct Curl_easy *data, const char *value,
   newhs = Curl_saferealloc(hs, sizeof(*hs) + vlen + oalloc + 1);
   if(!newhs)
     return CURLE_OUT_OF_MEMORY;
-  /* ->name' and ->value point into ->buffer (to keep the header allocation
+  /* ->name and ->value point into ->buffer (to keep the header allocation
      in a single memory block), which now potentially have moved. Adjust
      them. */
   newhs->name = newhs->buffer;
@@ -263,8 +264,7 @@ static CURLcode unfold_value(struct Curl_easy *data, const char *value,
   newhs->value[olen + vlen] = 0; /* null-terminate at newline */
 
   /* insert this node into the list of headers */
-  Curl_llist_insert_next(&data->state.httphdrs, data->state.httphdrs.tail,
-                         newhs, &newhs->node);
+  Curl_llist_append(&data->state.httphdrs, newhs, &newhs->node);
   data->state.prevhead = newhs;
   return CURLE_OK;
 }
@@ -292,9 +292,10 @@ CURLcode Curl_headers_push(struct Curl_easy *data, const char *header,
   if(!end) {
     end = strchr(header, '\n');
     if(!end)
-      return CURLE_BAD_FUNCTION_ARGUMENT;
+      /* neither CR nor LF as terminator is not a valid header */
+      return CURLE_WEIRD_SERVER_REPLY;
   }
-  hlen = end - header + 1;
+  hlen = end - header;
 
   if((header[0] == ' ') || (header[0] == '\t')) {
     if(data->state.prevhead)
@@ -319,33 +320,86 @@ CURLcode Curl_headers_push(struct Curl_easy *data, const char *header,
   hs->buffer[hlen] = 0; /* nul terminate */
 
   result = namevalue(hs->buffer, hlen, type, &name, &value);
-  if(result)
-    goto fail;
-
-  hs->name = name;
-  hs->value = value;
-  hs->type = type;
-  hs->request = data->state.requests;
-
-  /* insert this node into the list of headers */
-  Curl_llist_insert_next(&data->state.httphdrs, data->state.httphdrs.tail,
-                         hs, &hs->node);
-  data->state.prevhead = hs;
-  return CURLE_OK;
-fail:
-  free(hs);
+  if(!result) {
+    hs->name = name;
+    hs->value = value;
+    hs->type = type;
+    hs->request = data->state.requests;
+
+    /* insert this node into the list of headers */
+    Curl_llist_append(&data->state.httphdrs, hs, &hs->node);
+    data->state.prevhead = hs;
+  }
+  else
+    free(hs);
   return result;
 }
 
 /*
- * Curl_headers_init(). Init the headers subsystem.
+ * Curl_headers_reset(). Reset the headers subsystem.
  */
-static void headers_init(struct Curl_easy *data)
+static void headers_reset(struct Curl_easy *data)
 {
   Curl_llist_init(&data->state.httphdrs, NULL);
   data->state.prevhead = NULL;
 }
 
+struct hds_cw_collect_ctx {
+  struct Curl_cwriter super;
+};
+
+static CURLcode hds_cw_collect_write(struct Curl_easy *data,
+                                     struct Curl_cwriter *writer, int type,
+                                     const char *buf, size_t blen)
+{
+  if((type & CLIENTWRITE_HEADER) && !(type & CLIENTWRITE_STATUS)) {
+    unsigned char htype = (unsigned char)
+      (type & CLIENTWRITE_CONNECT ? CURLH_CONNECT :
+       (type & CLIENTWRITE_1XX ? CURLH_1XX :
+        (type & CLIENTWRITE_TRAILER ? CURLH_TRAILER :
+         CURLH_HEADER)));
+    CURLcode result = Curl_headers_push(data, buf, htype);
+    CURL_TRC_WRITE(data, "header_collect pushed(type=%x, len=%zu) -> %d",
+                   htype, blen, result);
+    if(result)
+      return result;
+  }
+  return Curl_cwriter_write(data, writer->next, type, buf, blen);
+}
+
+static const struct Curl_cwtype hds_cw_collect = {
+  "hds-collect",
+  NULL,
+  Curl_cwriter_def_init,
+  hds_cw_collect_write,
+  Curl_cwriter_def_close,
+  sizeof(struct hds_cw_collect_ctx)
+};
+
+CURLcode Curl_headers_init(struct Curl_easy *data)
+{
+  struct Curl_cwriter *writer;
+  CURLcode result;
+
+  if(data->conn && (data->conn->handler->protocol & PROTO_FAMILY_HTTP)) {
+    /* avoid installing it twice */
+    if(Curl_cwriter_get_by_name(data, hds_cw_collect.name))
+      return CURLE_OK;
+
+    result = Curl_cwriter_create(&writer, data, &hds_cw_collect,
+                                 CURL_CW_PROTOCOL);
+    if(result)
+      return result;
+
+    result = Curl_cwriter_add(data, writer);
+    if(result) {
+      Curl_cwriter_free(data, writer);
+      return result;
+    }
+  }
+  return CURLE_OK;
+}
+
 /*
  * Curl_headers_cleanup(). Free all stored headers and associated memory.
  */
@@ -359,7 +413,7 @@ CURLcode Curl_headers_cleanup(struct Curl_easy *data)
     n = e->next;
     free(hs);
   }
-  headers_init(data);
+  headers_reset(data);
   return CURLE_OK;
 }
 
diff --git a/vendor/curl/lib/headers.h b/vendor/curl/lib/headers.h
index a5229ea22f..d9813388c5 100644
--- a/vendor/curl/lib/headers.h
+++ b/vendor/curl/lib/headers.h
@@ -36,6 +36,12 @@ struct Curl_header_store {
   char buffer[1]; /* this is the raw header blob */
 };
 
+/*
+ * Initialize header collecting for a transfer.
+ * Will add a client writer that catches CLIENTWRITE_HEADER writes.
+ */
+CURLcode Curl_headers_init(struct Curl_easy *data);
+
 /*
  * Curl_headers_push() gets passed a full header to store.
  */
@@ -48,6 +54,7 @@ CURLcode Curl_headers_push(struct Curl_easy *data, const char *header,
 CURLcode Curl_headers_cleanup(struct Curl_easy *data);
 
 #else
+#define Curl_headers_init(x) CURLE_OK
 #define Curl_headers_push(x,y,z) CURLE_OK
 #define Curl_headers_cleanup(x) Curl_nop_stmt
 #endif
diff --git a/vendor/curl/lib/hmac.c b/vendor/curl/lib/hmac.c
index 87e7be8c65..4019b67f8e 100644
--- a/vendor/curl/lib/hmac.c
+++ b/vendor/curl/lib/hmac.c
@@ -26,8 +26,8 @@
 
 #include "curl_setup.h"
 
-#if (defined(USE_CURL_NTLM_CORE) && !defined(USE_WINDOWS_SSPI)) \
-    || !defined(CURL_DISABLE_AWS)
+#if (defined(USE_CURL_NTLM_CORE) && !defined(USE_WINDOWS_SSPI))         \
+  || !defined(CURL_DISABLE_AWS) || !defined(CURL_DISABLE_DIGEST_AUTH)
 
 #include 
 
diff --git a/vendor/curl/lib/hostip.c b/vendor/curl/lib/hostip.c
index acb4b5140b..93c36e031b 100644
--- a/vendor/curl/lib/hostip.c
+++ b/vendor/curl/lib/hostip.c
@@ -41,12 +41,8 @@
 #include 
 #endif
 
-#ifdef HAVE_SETJMP_H
 #include 
-#endif
-#ifdef HAVE_SIGNAL_H
 #include 
-#endif
 
 #include "urldata.h"
 #include "sendf.h"
@@ -121,6 +117,13 @@
 
 static void freednsentry(void *freethis);
 
+#ifndef CURL_DISABLE_VERBOSE_STRINGS
+static void show_resolve_info(struct Curl_easy *data,
+                              struct Curl_dns_entry *dns);
+#else
+#define show_resolve_info(x,y) Curl_nop_stmt
+#endif
+
 /*
  * Curl_printable_address() stores a printable version of the 1st address
  * given in the 'ai' argument. The result will be stored in the buf that is
@@ -141,7 +144,7 @@ void Curl_printable_address(const struct Curl_addrinfo *ai, char *buf,
     (void)Curl_inet_ntop(ai->ai_family, (const void *)ipaddr4, buf, bufsize);
     break;
   }
-#ifdef ENABLE_IPV6
+#ifdef USE_IPV6
   case AF_INET6: {
     const struct sockaddr_in6 *sa6 = (const void *)ai->ai_addr;
     const struct in6_addr *ipaddr6 = &sa6->sin6_addr;
@@ -164,17 +167,12 @@ create_hostcache_id(const char *name,
                     int port, char *ptr, size_t buflen)
 {
   size_t len = nlen ? nlen : strlen(name);
-  size_t olen = 0;
   DEBUGASSERT(buflen >= MAX_HOSTCACHE_LEN);
   if(len > (buflen - 7))
     len = buflen - 7;
   /* store and lower case the name */
-  while(len--) {
-    *ptr++ = Curl_raw_tolower(*name++);
-    olen++;
-  }
-  olen += msnprintf(ptr, 7, ":%u", port);
-  return olen;
+  Curl_strntolower(ptr, name, len);
+  return msnprintf(&ptr[len], 7, ":%u", port) + len;
 }
 
 struct hostcache_prune_data {
@@ -246,7 +244,7 @@ void Curl_hostcache_prune(struct Curl_easy *data)
   if(data->share)
     Curl_share_lock(data, CURL_LOCK_DATA_DNS, CURL_LOCK_ACCESS_SINGLE);
 
-  time(&now);
+  now = time(NULL);
 
   do {
     /* Remove outdated and unused entries from the hostcache */
@@ -285,7 +283,7 @@ static struct Curl_dns_entry *fetch_addr(struct Curl_easy *data,
   size_t entry_len = create_hostcache_id(hostname, 0, port,
                                          entry_id, sizeof(entry_id));
 
-  /* See if its already in our dns cache */
+  /* See if it's already in our dns cache */
   dns = Curl_hash_pick(data->dns.hostcache, entry_id, entry_len + 1);
 
   /* No entry found in cache, check if we might have a wildcard entry */
@@ -300,7 +298,7 @@ static struct Curl_dns_entry *fetch_addr(struct Curl_easy *data,
     /* See whether the returned entry is stale. Done before we release lock */
     struct hostcache_prune_data user;
 
-    time(&user.now);
+    user.now = time(NULL);
     user.cache_timeout = data->set.dns_cache_timeout;
     user.oldest = 0;
 
@@ -485,9 +483,11 @@ Curl_cache_addr(struct Curl_easy *data,
       return NULL;
   }
 #endif
+  if(!hostlen)
+    hostlen = strlen(hostname);
 
   /* Create a new cache entry */
-  dns = calloc(1, sizeof(struct Curl_dns_entry));
+  dns = calloc(1, sizeof(struct Curl_dns_entry) + hostlen);
   if(!dns) {
     return NULL;
   }
@@ -501,6 +501,9 @@ Curl_cache_addr(struct Curl_easy *data,
   time(&dns->timestamp);
   if(dns->timestamp == 0)
     dns->timestamp = 1;   /* zero indicates permanent CURLOPT_RESOLVE entry */
+  dns->hostport = port;
+  if(hostlen)
+    memcpy(dns->hostname, hostname, hostlen);
 
   /* Store the resolved data in our DNS cache. */
   dns2 = Curl_hash_add(data->dns.hostcache, entry_id, entry_len + 1,
@@ -515,7 +518,7 @@ Curl_cache_addr(struct Curl_easy *data,
   return dns;
 }
 
-#ifdef ENABLE_IPV6
+#ifdef USE_IPV6
 /* return a static IPv6 ::1 for the name */
 static struct Curl_addrinfo *get_localhost6(int port, const char *name)
 {
@@ -525,7 +528,7 @@ static struct Curl_addrinfo *get_localhost6(int port, const char *name)
   struct sockaddr_in6 sa6;
   unsigned char ipv6[16];
   unsigned short port16 = (unsigned short)(port & 0xffff);
-  ca = calloc(sizeof(struct Curl_addrinfo) + ss_size + hostlen + 1, 1);
+  ca = calloc(1, sizeof(struct Curl_addrinfo) + ss_size + hostlen + 1);
   if(!ca)
     return NULL;
 
@@ -572,7 +575,7 @@ static struct Curl_addrinfo *get_localhost(int port, const char *name)
     return NULL;
   memcpy(&sa.sin_addr, &ipv4, sizeof(ipv4));
 
-  ca = calloc(sizeof(struct Curl_addrinfo) + ss_size + hostlen + 1, 1);
+  ca = calloc(1, sizeof(struct Curl_addrinfo) + ss_size + hostlen + 1);
   if(!ca)
     return NULL;
   ca->ai_flags     = 0;
@@ -592,7 +595,7 @@ static struct Curl_addrinfo *get_localhost(int port, const char *name)
   return ca6;
 }
 
-#ifdef ENABLE_IPV6
+#ifdef USE_IPV6
 /*
  * Curl_ipv6works() returns TRUE if IPv6 seems to work.
  */
@@ -624,7 +627,7 @@ bool Curl_ipv6works(struct Curl_easy *data)
     return (ipv6_works>0)?TRUE:FALSE;
   }
 }
-#endif /* ENABLE_IPV6 */
+#endif /* USE_IPV6 */
 
 /*
  * Curl_host_is_ipnum() returns TRUE if the given string is a numerical IPv4
@@ -633,11 +636,11 @@ bool Curl_ipv6works(struct Curl_easy *data)
 bool Curl_host_is_ipnum(const char *hostname)
 {
   struct in_addr in;
-#ifdef ENABLE_IPV6
+#ifdef USE_IPV6
   struct in6_addr in6;
 #endif
   if(Curl_inet_pton(AF_INET, hostname, &in) > 0
-#ifdef ENABLE_IPV6
+#ifdef USE_IPV6
      || Curl_inet_pton(AF_INET6, hostname, &in6) > 0
 #endif
     )
@@ -746,18 +749,24 @@ enum resolve_t Curl_resolv(struct Curl_easy *data,
 
 #ifndef USE_RESOLVE_ON_IPS
     /* First check if this is an IPv4 address string */
-    if(Curl_inet_pton(AF_INET, hostname, &in) > 0)
+    if(Curl_inet_pton(AF_INET, hostname, &in) > 0) {
       /* This is a dotted IP address 123.123.123.123-style */
       addr = Curl_ip2addr(AF_INET, &in, hostname, port);
-#ifdef ENABLE_IPV6
-    if(!addr) {
+      if(!addr)
+        return CURLRESOLV_ERROR;
+    }
+#ifdef USE_IPV6
+    else {
       struct in6_addr in6;
       /* check if this is an IPv6 address string */
-      if(Curl_inet_pton(AF_INET6, hostname, &in6) > 0)
+      if(Curl_inet_pton(AF_INET6, hostname, &in6) > 0) {
         /* This is an IPv6 address literal */
         addr = Curl_ip2addr(AF_INET6, &in6, hostname, port);
+        if(!addr)
+          return CURLRESOLV_ERROR;
+      }
     }
-#endif /* ENABLE_IPV6 */
+#endif /* USE_IPV6 */
 
 #else /* if USE_RESOLVE_ON_IPS */
 #ifndef CURL_DISABLE_DOH
@@ -765,7 +774,7 @@ enum resolve_t Curl_resolv(struct Curl_easy *data,
     if(Curl_inet_pton(AF_INET, hostname, &in) > 0)
       /* This is a dotted IP address 123.123.123.123-style */
       ipnum = TRUE;
-#ifdef ENABLE_IPV6
+#ifdef USE_IPV6
     else {
       struct in6_addr in6;
       /* check if this is an IPv6 address string */
@@ -773,7 +782,7 @@ enum resolve_t Curl_resolv(struct Curl_easy *data,
         /* This is an IPv6 address literal */
         ipnum = TRUE;
     }
-#endif /* ENABLE_IPV6 */
+#endif /* USE_IPV6 */
 #endif /* CURL_DISABLE_DOH */
 
 #endif /* !USE_RESOLVE_ON_IPS */
@@ -827,8 +836,10 @@ enum resolve_t Curl_resolv(struct Curl_easy *data,
       if(!dns)
         /* returned failure, bail out nicely */
         Curl_freeaddrinfo(addr);
-      else
+      else {
         rc = CURLRESOLV_RESOLVED;
+        show_resolve_info(data, dns);
+      }
     }
   }
 
@@ -843,7 +854,7 @@ enum resolve_t Curl_resolv(struct Curl_easy *data,
  * execution.  This effectively causes the remainder of the application to run
  * within a signal handler which is nonportable and could lead to problems.
  */
-static
+CURL_NORETURN static
 void alarmfunc(int sig)
 {
   (void)sig;
@@ -1054,6 +1065,23 @@ static void freednsentry(void *freethis)
   dns->inuse--;
   if(dns->inuse == 0) {
     Curl_freeaddrinfo(dns->addr);
+#ifdef USE_HTTPSRR
+    if(dns->hinfo) {
+      if(dns->hinfo->target)
+        free(dns->hinfo->target);
+      if(dns->hinfo->alpns)
+        free(dns->hinfo->alpns);
+      if(dns->hinfo->ipv4hints)
+        free(dns->hinfo->ipv4hints);
+      if(dns->hinfo->echconfiglist)
+        free(dns->hinfo->echconfiglist);
+      if(dns->hinfo->ipv6hints)
+        free(dns->hinfo->ipv6hints);
+      if(dns->hinfo->val)
+        free(dns->hinfo->val);
+      free(dns->hinfo);
+    }
+#endif
     free(dns);
   }
 }
@@ -1061,7 +1089,7 @@ static void freednsentry(void *freethis)
 /*
  * Curl_init_dnscache() inits a new DNS cache.
  */
-void Curl_init_dnscache(struct Curl_hash *hash, int size)
+void Curl_init_dnscache(struct Curl_hash *hash, size_t size)
 {
   Curl_hash_init(hash, size, Curl_hash_str, Curl_str_key_compare,
                  freednsentry);
@@ -1194,7 +1222,7 @@ CURLcode Curl_loadhostpairs(struct Curl_easy *data)
         memcpy(address, addr_begin, alen);
         address[alen] = '\0';
 
-#ifndef ENABLE_IPV6
+#ifndef USE_IPV6
         if(strchr(address, ':')) {
           infof(data, "Ignoring resolve address '%s', missing IPv6 support.",
                 address);
@@ -1273,9 +1301,11 @@ CURLcode Curl_loadhostpairs(struct Curl_easy *data)
         Curl_freeaddrinfo(head);
         return CURLE_OUT_OF_MEMORY;
       }
+#ifndef CURL_DISABLE_VERBOSE_STRINGS
       infof(data, "Added %.*s:%d:%s to DNS cache%s",
             (int)hlen, host_begin, port, addresses,
             permanent ? "" : " (non-permanent)");
+#endif
 
       /* Wildcard hostname */
       if((hlen == 1) && (host_begin[0] == '*')) {
@@ -1289,18 +1319,89 @@ CURLcode Curl_loadhostpairs(struct Curl_easy *data)
   return CURLE_OK;
 }
 
+#ifndef CURL_DISABLE_VERBOSE_STRINGS
+static void show_resolve_info(struct Curl_easy *data,
+                              struct Curl_dns_entry *dns)
+{
+  struct Curl_addrinfo *a;
+  CURLcode result = CURLE_OK;
+#ifdef CURLRES_IPV6
+  struct dynbuf out[2];
+#else
+  struct dynbuf out[1];
+#endif
+  DEBUGASSERT(data);
+  DEBUGASSERT(dns);
+
+  if(!data->set.verbose ||
+     /* ignore no name or numerical IP addresses */
+     !dns->hostname[0] || Curl_host_is_ipnum(dns->hostname))
+    return;
+
+  a = dns->addr;
+
+  infof(data, "Host %s:%d was resolved.",
+        (dns->hostname[0] ? dns->hostname : "(none)"), dns->hostport);
+
+  Curl_dyn_init(&out[0], 1024);
+#ifdef CURLRES_IPV6
+  Curl_dyn_init(&out[1], 1024);
+#endif
+
+  while(a) {
+    if(
+#ifdef CURLRES_IPV6
+       a->ai_family == PF_INET6 ||
+#endif
+       a->ai_family == PF_INET) {
+      char buf[MAX_IPADR_LEN];
+      struct dynbuf *d = &out[(a->ai_family != PF_INET)];
+      Curl_printable_address(a, buf, sizeof(buf));
+      if(Curl_dyn_len(d))
+        result = Curl_dyn_addn(d, ", ", 2);
+      if(!result)
+        result = Curl_dyn_add(d, buf);
+      if(result) {
+        infof(data, "too many IP, can't show");
+        goto fail;
+      }
+    }
+    a = a->ai_next;
+  }
+
+#ifdef CURLRES_IPV6
+  infof(data, "IPv6: %s",
+        (Curl_dyn_len(&out[1]) ? Curl_dyn_ptr(&out[1]) : "(none)"));
+#endif
+  infof(data, "IPv4: %s",
+        (Curl_dyn_len(&out[0]) ? Curl_dyn_ptr(&out[0]) : "(none)"));
+
+fail:
+  Curl_dyn_free(&out[0]);
+#ifdef CURLRES_IPV6
+  Curl_dyn_free(&out[1]);
+#endif
+}
+#endif
+
 CURLcode Curl_resolv_check(struct Curl_easy *data,
                            struct Curl_dns_entry **dns)
 {
+  CURLcode result;
 #if defined(CURL_DISABLE_DOH) && !defined(CURLRES_ASYNCH)
   (void)data;
   (void)dns;
 #endif
 #ifndef CURL_DISABLE_DOH
-  if(data->conn->bits.doh)
-    return Curl_doh_is_resolved(data, dns);
+  if(data->conn->bits.doh) {
+    result = Curl_doh_is_resolved(data, dns);
+  }
+  else
 #endif
-  return Curl_resolver_is_resolved(data, dns);
+  result = Curl_resolver_is_resolved(data, dns);
+  if(*dns)
+    show_resolve_info(data, *dns);
+  return result;
 }
 
 int Curl_resolv_getsock(struct Curl_easy *data,
diff --git a/vendor/curl/lib/hostip.h b/vendor/curl/lib/hostip.h
index 06d0867277..bf4e94d2fa 100644
--- a/vendor/curl/lib/hostip.h
+++ b/vendor/curl/lib/hostip.h
@@ -30,8 +30,10 @@
 #include "timeval.h" /* for timediff_t */
 #include "asyn.h"
 
-#ifdef HAVE_SETJMP_H
 #include 
+
+#ifdef USE_HTTPSRR
+# include 
 #endif
 
 /* Allocate enough memory to hold the full name information structs and
@@ -60,12 +62,49 @@ struct connectdata;
  */
 struct Curl_hash *Curl_global_host_cache_init(void);
 
+#ifdef USE_HTTPSRR
+
+#define CURL_MAXLEN_host_name 253
+
+struct Curl_https_rrinfo {
+  size_t len; /* raw encoded length */
+  unsigned char *val; /* raw encoded octets */
+  /*
+   * fields from HTTPS RR, with the mandatory fields
+   * first (priority, target), then the others in the
+   * order of the keytag numbers defined at
+   * https://datatracker.ietf.org/doc/html/rfc9460#section-14.3.2
+   */
+  uint16_t priority;
+  char *target;
+  char *alpns; /* keytag = 1 */
+  bool no_def_alpn; /* keytag = 2 */
+  /*
+   * we don't support ports (keytag = 3) as we don't support
+   * port-switching yet
+   */
+  unsigned char *ipv4hints; /* keytag = 4 */
+  size_t ipv4hints_len;
+  unsigned char *echconfiglist; /* keytag = 5 */
+  size_t echconfiglist_len;
+  unsigned char *ipv6hints; /* keytag = 6 */
+  size_t ipv6hints_len;
+};
+#endif
+
 struct Curl_dns_entry {
   struct Curl_addrinfo *addr;
+#ifdef USE_HTTPSRR
+  struct Curl_https_rrinfo *hinfo;
+#endif
   /* timestamp == 0 -- permanent CURLOPT_RESOLVE entry (doesn't time out) */
   time_t timestamp;
   /* use-counter, use Curl_resolv_unlock to release reference */
   long inuse;
+  /* hostname port number that resolved to addr. */
+  int hostport;
+  /* hostname that resolved to addr. may be NULL (unix domain sockets). */
+  char hostname[1];
 };
 
 bool Curl_host_is_ipnum(const char *hostname);
@@ -94,7 +133,7 @@ enum resolve_t Curl_resolv_timeout(struct Curl_easy *data,
                                    struct Curl_dns_entry **dnsentry,
                                    timediff_t timeoutms);
 
-#ifdef ENABLE_IPV6
+#ifdef USE_IPV6
 /*
  * Curl_ipv6works() returns TRUE if IPv6 seems to work.
  */
@@ -127,7 +166,7 @@ void Curl_resolv_unlock(struct Curl_easy *data,
                         struct Curl_dns_entry *dns);
 
 /* init a new dns cache */
-void Curl_init_dnscache(struct Curl_hash *hash, int hashsize);
+void Curl_init_dnscache(struct Curl_hash *hash, size_t hashsize);
 
 /* prune old entries from the DNS cache */
 void Curl_hostcache_prune(struct Curl_easy *data);
diff --git a/vendor/curl/lib/hostip6.c b/vendor/curl/lib/hostip6.c
index 6b0ba55e9f..18969a7a7d 100644
--- a/vendor/curl/lib/hostip6.c
+++ b/vendor/curl/lib/hostip6.c
@@ -71,8 +71,7 @@ bool Curl_ipvalid(struct Curl_easy *data, struct connectdata *conn)
 #if defined(CURLRES_SYNCH)
 
 #ifdef DEBUG_ADDRINFO
-static void dump_addrinfo(struct connectdata *conn,
-                          const struct Curl_addrinfo *ai)
+static void dump_addrinfo(const struct Curl_addrinfo *ai)
 {
   printf("dump_addrinfo:\n");
   for(; ai; ai = ai->ai_next) {
@@ -84,7 +83,7 @@ static void dump_addrinfo(struct connectdata *conn,
   }
 }
 #else
-#define dump_addrinfo(x,y) Curl_nop_stmt
+#define dump_addrinfo(x) Curl_nop_stmt
 #endif
 
 /*
@@ -149,7 +148,7 @@ struct Curl_addrinfo *Curl_getaddrinfo(struct Curl_easy *data,
     Curl_addrinfo_set_port(res, port);
   }
 
-  dump_addrinfo(conn, res);
+  dump_addrinfo(res);
 
   return res;
 }
diff --git a/vendor/curl/lib/hsts.c b/vendor/curl/lib/hsts.c
index 7ecf0042a5..a5e7676138 100644
--- a/vendor/curl/lib/hsts.c
+++ b/vendor/curl/lib/hsts.c
@@ -40,6 +40,7 @@
 #include "fopen.h"
 #include "rename.h"
 #include "share.h"
+#include "strdup.h"
 
 /* The last 3 #include files should be in this order */
 #include "curl_printf.h"
@@ -76,7 +77,7 @@ static time_t hsts_debugtime(void *unused)
 
 struct hsts *Curl_hsts_init(void)
 {
-  struct hsts *h = calloc(sizeof(struct hsts), 1);
+  struct hsts *h = calloc(1, sizeof(struct hsts));
   if(h) {
     Curl_llist_init(&h->list, NULL);
   }
@@ -106,37 +107,36 @@ void Curl_hsts_cleanup(struct hsts **hp)
   }
 }
 
-static struct stsentry *hsts_entry(void)
-{
-  return calloc(sizeof(struct stsentry), 1);
-}
-
 static CURLcode hsts_create(struct hsts *h,
                             const char *hostname,
                             bool subdomains,
                             curl_off_t expires)
 {
-  struct stsentry *sts = hsts_entry();
-  char *duphost;
   size_t hlen;
-  if(!sts)
-    return CURLE_OUT_OF_MEMORY;
+  DEBUGASSERT(h);
+  DEBUGASSERT(hostname);
+
+  hlen = strlen(hostname);
+  if(hlen && (hostname[hlen - 1] == '.'))
+    /* strip off any trailing dot */
+    --hlen;
+  if(hlen) {
+    char *duphost;
+    struct stsentry *sts = calloc(1, sizeof(struct stsentry));
+    if(!sts)
+      return CURLE_OUT_OF_MEMORY;
+
+    duphost = Curl_memdup0(hostname, hlen);
+    if(!duphost) {
+      free(sts);
+      return CURLE_OUT_OF_MEMORY;
+    }
 
-  duphost = strdup(hostname);
-  if(!duphost) {
-    free(sts);
-    return CURLE_OUT_OF_MEMORY;
+    sts->host = duphost;
+    sts->expires = expires;
+    sts->includeSubDomains = subdomains;
+    Curl_llist_append(&h->list, sts, &sts->node);
   }
-
-  hlen = strlen(duphost);
-  if(duphost[hlen - 1] == '.')
-    /* strip off trailing any dot */
-    duphost[--hlen] = 0;
-
-  sts->host = duphost;
-  sts->expires = expires;
-  sts->includeSubDomains = subdomains;
-  Curl_llist_insert_next(&h->list, h->list.tail, sts, &sts->node);
   return CURLE_OK;
 }
 
@@ -473,6 +473,7 @@ static CURLcode hsts_pull(struct Curl_easy *data, struct hsts *h)
       if(sc == CURLSTS_OK) {
         time_t expires;
         CURLcode result;
+        DEBUGASSERT(e.name[0]);
         if(!e.name[0])
           /* bail out if no name was stored */
           return CURLE_BAD_FUNCTION_ARGUMENT;
@@ -505,7 +506,6 @@ static CURLcode hsts_pull(struct Curl_easy *data, struct hsts *h)
 static CURLcode hsts_load(struct hsts *h, const char *file)
 {
   CURLcode result = CURLE_OK;
-  char *line = NULL;
   FILE *fp;
 
   /* we need a private copy of the file name so that the hsts cache file
@@ -517,28 +517,25 @@ static CURLcode hsts_load(struct hsts *h, const char *file)
 
   fp = fopen(file, FOPEN_READTEXT);
   if(fp) {
-    line = malloc(MAX_HSTS_LINE);
-    if(!line)
-      goto fail;
-    while(Curl_get_line(line, MAX_HSTS_LINE, fp)) {
-      char *lineptr = line;
+    struct dynbuf buf;
+    Curl_dyn_init(&buf, MAX_HSTS_LINE);
+    while(Curl_get_line(&buf, fp)) {
+      char *lineptr = Curl_dyn_ptr(&buf);
       while(*lineptr && ISBLANK(*lineptr))
         lineptr++;
-      if(*lineptr == '#')
-        /* skip commented lines */
+      /*
+       * Skip empty or commented lines, since we know the line will have a
+       * trailing newline from Curl_get_line we can treat length 1 as empty.
+       */
+      if((*lineptr == '#') || strlen(lineptr) <= 1)
         continue;
 
       hsts_add(h, lineptr);
     }
-    free(line); /* free the line buffer */
+    Curl_dyn_free(&buf); /* free the line buffer */
     fclose(fp);
   }
   return result;
-
-fail:
-  Curl_safefree(h->filename);
-  fclose(fp);
-  return CURLE_OUT_OF_MEMORY;
 }
 
 /*
@@ -564,7 +561,7 @@ CURLcode Curl_hsts_loadcb(struct Curl_easy *data, struct hsts *h)
 
 void Curl_hsts_loadfiles(struct Curl_easy *data)
 {
-  struct curl_slist *l = data->set.hstslist;
+  struct curl_slist *l = data->state.hstslist;
   if(l) {
     Curl_share_lock(data, CURL_LOCK_DATA_HSTS, CURL_LOCK_ACCESS_SINGLE);
 
diff --git a/vendor/curl/lib/http.c b/vendor/curl/lib/http.c
index 4344b9dae5..2a41f80786 100644
--- a/vendor/curl/lib/http.c
+++ b/vendor/curl/lib/http.c
@@ -65,7 +65,6 @@
 #include "vquic/vquic.h"
 #include "http_digest.h"
 #include "http_ntlm.h"
-#include "curl_ntlm_wb.h"
 #include "http_negotiate.h"
 #include "http_aws_sigv4.h"
 #include "url.h"
@@ -73,6 +72,7 @@
 #include "hostip.h"
 #include "dynhds.h"
 #include "http.h"
+#include "headers.h"
 #include "select.h"
 #include "parsedate.h" /* for the week day and month names */
 #include "strtoofft.h"
@@ -100,24 +100,17 @@
  * Forward declarations.
  */
 
-static int http_getsock_do(struct Curl_easy *data,
-                           struct connectdata *conn,
-                           curl_socket_t *socks);
-static bool http_should_fail(struct Curl_easy *data);
-
-static CURLcode http_setup_conn(struct Curl_easy *data,
-                                struct connectdata *conn);
-#ifdef USE_WEBSOCKETS
-static CURLcode ws_setup_conn(struct Curl_easy *data,
-                              struct connectdata *conn);
-#endif
+static bool http_should_fail(struct Curl_easy *data, int httpcode);
+static bool http_exp100_is_waiting(struct Curl_easy *data);
+static CURLcode http_exp100_add_reader(struct Curl_easy *data);
+static void http_exp100_send_anyway(struct Curl_easy *data);
 
 /*
  * HTTP handler interface.
  */
 const struct Curl_handler Curl_handler_http = {
-  "HTTP",                               /* scheme */
-  http_setup_conn,                      /* setup_connection */
+  "http",                               /* scheme */
+  Curl_http_setup_conn,                 /* setup_connection */
   Curl_http,                            /* do_it */
   Curl_http_done,                       /* done */
   ZERO_NULL,                            /* do_more */
@@ -125,11 +118,12 @@ const struct Curl_handler Curl_handler_http = {
   ZERO_NULL,                            /* connecting */
   ZERO_NULL,                            /* doing */
   ZERO_NULL,                            /* proto_getsock */
-  http_getsock_do,                      /* doing_getsock */
+  Curl_http_getsock_do,                 /* doing_getsock */
   ZERO_NULL,                            /* domore_getsock */
   ZERO_NULL,                            /* perform_getsock */
   ZERO_NULL,                            /* disconnect */
-  ZERO_NULL,                            /* readwrite */
+  Curl_http_write_resp,                 /* write_resp */
+  Curl_http_write_resp_hd,              /* write_resp_hd */
   ZERO_NULL,                            /* connection_check */
   ZERO_NULL,                            /* attach connection */
   PORT_HTTP,                            /* defport */
@@ -139,39 +133,13 @@ const struct Curl_handler Curl_handler_http = {
   PROTOPT_USERPWDCTRL
 };
 
-#ifdef USE_WEBSOCKETS
-const struct Curl_handler Curl_handler_ws = {
-  "WS",                                 /* scheme */
-  ws_setup_conn,                        /* setup_connection */
-  Curl_http,                            /* do_it */
-  Curl_http_done,                       /* done */
-  ZERO_NULL,                            /* do_more */
-  Curl_http_connect,                    /* connect_it */
-  ZERO_NULL,                            /* connecting */
-  ZERO_NULL,                            /* doing */
-  ZERO_NULL,                            /* proto_getsock */
-  http_getsock_do,                      /* doing_getsock */
-  ZERO_NULL,                            /* domore_getsock */
-  ZERO_NULL,                            /* perform_getsock */
-  Curl_ws_disconnect,                   /* disconnect */
-  ZERO_NULL,                            /* readwrite */
-  ZERO_NULL,                            /* connection_check */
-  ZERO_NULL,                            /* attach connection */
-  PORT_HTTP,                            /* defport */
-  CURLPROTO_WS,                         /* protocol */
-  CURLPROTO_HTTP,                       /* family */
-  PROTOPT_CREDSPERREQUEST |             /* flags */
-  PROTOPT_USERPWDCTRL
-};
-#endif
-
 #ifdef USE_SSL
 /*
  * HTTPS handler interface.
  */
 const struct Curl_handler Curl_handler_https = {
-  "HTTPS",                              /* scheme */
-  http_setup_conn,                      /* setup_connection */
+  "https",                              /* scheme */
+  Curl_http_setup_conn,                 /* setup_connection */
   Curl_http,                            /* do_it */
   Curl_http_done,                       /* done */
   ZERO_NULL,                            /* do_more */
@@ -179,11 +147,12 @@ const struct Curl_handler Curl_handler_https = {
   NULL,                                 /* connecting */
   ZERO_NULL,                            /* doing */
   NULL,                                 /* proto_getsock */
-  http_getsock_do,                      /* doing_getsock */
+  Curl_http_getsock_do,                 /* doing_getsock */
   ZERO_NULL,                            /* domore_getsock */
   ZERO_NULL,                            /* perform_getsock */
   ZERO_NULL,                            /* disconnect */
-  ZERO_NULL,                            /* readwrite */
+  Curl_http_write_resp,                 /* write_resp */
+  Curl_http_write_resp_hd,              /* write_resp_hd */
   ZERO_NULL,                            /* connection_check */
   ZERO_NULL,                            /* attach connection */
   PORT_HTTPS,                           /* defport */
@@ -193,36 +162,10 @@ const struct Curl_handler Curl_handler_https = {
   PROTOPT_USERPWDCTRL
 };
 
-#ifdef USE_WEBSOCKETS
-const struct Curl_handler Curl_handler_wss = {
-  "WSS",                                /* scheme */
-  ws_setup_conn,                        /* setup_connection */
-  Curl_http,                            /* do_it */
-  Curl_http_done,                       /* done */
-  ZERO_NULL,                            /* do_more */
-  Curl_http_connect,                    /* connect_it */
-  NULL,                                 /* connecting */
-  ZERO_NULL,                            /* doing */
-  NULL,                                 /* proto_getsock */
-  http_getsock_do,                      /* doing_getsock */
-  ZERO_NULL,                            /* domore_getsock */
-  ZERO_NULL,                            /* perform_getsock */
-  Curl_ws_disconnect,                   /* disconnect */
-  ZERO_NULL,                            /* readwrite */
-  ZERO_NULL,                            /* connection_check */
-  ZERO_NULL,                            /* attach connection */
-  PORT_HTTPS,                           /* defport */
-  CURLPROTO_WSS,                        /* protocol */
-  CURLPROTO_HTTP,                       /* family */
-  PROTOPT_SSL | PROTOPT_CREDSPERREQUEST | /* flags */
-  PROTOPT_USERPWDCTRL
-};
-#endif
-
 #endif
 
-static CURLcode http_setup_conn(struct Curl_easy *data,
-                                struct connectdata *conn)
+CURLcode Curl_http_setup_conn(struct Curl_easy *data,
+                              struct connectdata *conn)
 {
   /* allocate the HTTP-specific struct for the Curl_easy, only to survive
      during this request */
@@ -245,16 +188,6 @@ static CURLcode http_setup_conn(struct Curl_easy *data,
   return CURLE_OK;
 }
 
-#ifdef USE_WEBSOCKETS
-static CURLcode ws_setup_conn(struct Curl_easy *data,
-                              struct connectdata *conn)
-{
-  /* websockets is 1.1 only (for now) */
-  data->state.httpwant = CURL_HTTP_VERSION_1_1;
-  return http_setup_conn(data, conn);
-}
-#endif
-
 #ifndef CURL_DISABLE_PROXY
 /*
  * checkProxyHeaders() checks the linked list of custom proxy headers
@@ -297,7 +230,6 @@ char *Curl_copy_header_value(const char *header)
 {
   const char *start;
   const char *end;
-  char *value;
   size_t len;
 
   /* Find the end of the header name */
@@ -313,8 +245,6 @@ char *Curl_copy_header_value(const char *header)
   while(*start && ISSPACE(*start))
     start++;
 
-  /* data is in the host encoding so
-     use '\r' and '\n' instead of 0x0d and 0x0a */
   end = strchr(start, '\r');
   if(!end)
     end = strchr(start, '\n');
@@ -330,14 +260,7 @@ char *Curl_copy_header_value(const char *header)
   /* get length of the type */
   len = end - start + 1;
 
-  value = malloc(len + 1);
-  if(!value)
-    return NULL;
-
-  memcpy(value, start, len);
-  value[len] = 0; /* null-terminate */
-
-  return value;
+  return Curl_memdup0(start, len);
 }
 
 #ifndef CURL_DISABLE_HTTP_AUTH
@@ -462,8 +385,6 @@ static bool pickoneauth(struct auth *pick, unsigned long mask)
 #endif
   else if(avail & CURLAUTH_NTLM)
     pick->picked = CURLAUTH_NTLM;
-  else if(avail & CURLAUTH_NTLM_WB)
-    pick->picked = CURLAUTH_NTLM_WB;
 #ifndef CURL_DISABLE_BASIC_AUTH
   else if(avail & CURLAUTH_BASIC)
     pick->picked = CURLAUTH_BASIC;
@@ -484,150 +405,86 @@ static bool pickoneauth(struct auth *pick, unsigned long mask)
 /*
  * http_perhapsrewind()
  *
- * If we are doing POST or PUT {
- *   If we have more data to send {
- *     If we are doing NTLM {
- *       Keep sending since we must not disconnect
- *     }
- *     else {
- *       If there is more than just a little data left to send, close
- *       the current connection by force.
- *     }
- *   }
- *   If we have sent any data {
- *     If we don't have track of all the data {
- *       call app to tell it to rewind
- *     }
- *     else {
- *       rewind internally so that the operation can restart fine
- *     }
- *   }
- * }
+ * The current request needs to be done again - maybe due to a follow
+ * or authentication negotiation. Check if:
+ * 1) a rewind of the data sent to the server is necessary
+ * 2) the current transfer should continue or be stopped early
  */
 static CURLcode http_perhapsrewind(struct Curl_easy *data,
                                    struct connectdata *conn)
 {
-  struct HTTP *http = data->req.p.http;
-  curl_off_t bytessent;
-  curl_off_t expectsend = -1; /* default is unknown */
-
-  if(!http)
-    /* If this is still NULL, we have not reach very far and we can safely
-       skip this rewinding stuff */
-    return CURLE_OK;
-
-  switch(data->state.httpreq) {
-  case HTTPREQ_GET:
-  case HTTPREQ_HEAD:
+  curl_off_t bytessent = data->req.writebytecount;
+  curl_off_t expectsend = Curl_creader_total_length(data);
+  curl_off_t upload_remain = (expectsend >= 0)? (expectsend - bytessent) : -1;
+  bool little_upload_remains = (upload_remain >= 0 && upload_remain < 2000);
+  bool needs_rewind = Curl_creader_needs_rewind(data);
+  /* By default, we'd like to abort the transfer when little or
+   * unknown amount remains. But this may be overridden by authentications
+   * further below! */
+  bool abort_upload = (!data->req.upload_done && !little_upload_remains);
+  const char *ongoing_auth = NULL;
+
+  /* We need a rewind before uploading client read data again. The
+   * checks below just influence of the upload is to be continued
+   * or aborted early.
+   * This depends on how much remains to be sent and in what state
+   * the authentication is. Some auth schemes such as NTLM do not work
+   * for a new connection. */
+  if(needs_rewind) {
+    infof(data, "Need to rewind upload for next request");
+    Curl_creader_set_rewind(data, TRUE);
+  }
+
+  if(conn->bits.close)
+    /* If we already decided to close this connection, we cannot veto. */
     return CURLE_OK;
-  default:
-    break;
-  }
-
-  bytessent = data->req.writebytecount;
-
-  if(conn->bits.authneg) {
-    /* This is a state where we are known to be negotiating and we don't send
-       any data then. */
-    expectsend = 0;
-  }
-  else if(!conn->bits.protoconnstart) {
-    /* HTTP CONNECT in progress: there is no body */
-    expectsend = 0;
-  }
-  else {
-    /* figure out how much data we are expected to send */
-    switch(data->state.httpreq) {
-    case HTTPREQ_POST:
-    case HTTPREQ_PUT:
-      if(data->state.infilesize != -1)
-        expectsend = data->state.infilesize;
-      break;
-    case HTTPREQ_POST_FORM:
-    case HTTPREQ_POST_MIME:
-      expectsend = http->postsize;
-      break;
-    default:
-      break;
-    }
-  }
 
-  data->state.rewindbeforesend = FALSE; /* default */
-
-  if((expectsend == -1) || (expectsend > bytessent)) {
+  if(abort_upload) {
+    /* We'd like to abort the upload - but should we? */
 #if defined(USE_NTLM)
-    /* There is still data left to send */
     if((data->state.authproxy.picked == CURLAUTH_NTLM) ||
-       (data->state.authhost.picked == CURLAUTH_NTLM) ||
-       (data->state.authproxy.picked == CURLAUTH_NTLM_WB) ||
-       (data->state.authhost.picked == CURLAUTH_NTLM_WB)) {
-      if(((expectsend - bytessent) < 2000) ||
-         (conn->http_ntlm_state != NTLMSTATE_NONE) ||
+       (data->state.authhost.picked == CURLAUTH_NTLM)) {
+      ongoing_auth = "NTML";
+      if((conn->http_ntlm_state != NTLMSTATE_NONE) ||
          (conn->proxy_ntlm_state != NTLMSTATE_NONE)) {
-        /* The NTLM-negotiation has started *OR* there is just a little (<2K)
-           data left to send, keep on sending. */
-
-        /* rewind data when completely done sending! */
-        if(!conn->bits.authneg && (conn->writesockfd != CURL_SOCKET_BAD)) {
-          data->state.rewindbeforesend = TRUE;
-          infof(data, "Rewind stream before next send");
-        }
-
-        return CURLE_OK;
+        /* The NTLM-negotiation has started, keep on sending.
+         * Need to do further work on same connection */
+        abort_upload = FALSE;
       }
-
-      if(conn->bits.close)
-        /* this is already marked to get closed */
-        return CURLE_OK;
-
-      infof(data, "NTLM send, close instead of sending %"
-            CURL_FORMAT_CURL_OFF_T " bytes",
-            (curl_off_t)(expectsend - bytessent));
     }
 #endif
 #if defined(USE_SPNEGO)
     /* There is still data left to send */
     if((data->state.authproxy.picked == CURLAUTH_NEGOTIATE) ||
        (data->state.authhost.picked == CURLAUTH_NEGOTIATE)) {
-      if(((expectsend - bytessent) < 2000) ||
-         (conn->http_negotiate_state != GSS_AUTHNONE) ||
+      ongoing_auth = "NEGOTIATE";
+      if((conn->http_negotiate_state != GSS_AUTHNONE) ||
          (conn->proxy_negotiate_state != GSS_AUTHNONE)) {
-        /* The NEGOTIATE-negotiation has started *OR*
-        there is just a little (<2K) data left to send, keep on sending. */
-
-        /* rewind data when completely done sending! */
-        if(!conn->bits.authneg && (conn->writesockfd != CURL_SOCKET_BAD)) {
-          data->state.rewindbeforesend = TRUE;
-          infof(data, "Rewind stream before next send");
-        }
-
-        return CURLE_OK;
+        /* The NEGOTIATE-negotiation has started, keep on sending.
+         * Need to do further work on same connection */
+        abort_upload = FALSE;
       }
-
-      if(conn->bits.close)
-        /* this is already marked to get closed */
-        return CURLE_OK;
-
-      infof(data, "NEGOTIATE send, close instead of sending %"
-        CURL_FORMAT_CURL_OFF_T " bytes",
-        (curl_off_t)(expectsend - bytessent));
     }
 #endif
+  }
 
-    /* This is not NEGOTIATE/NTLM or many bytes left to send: close */
+  if(abort_upload) {
+    if(upload_remain >= 0)
+      infof(data, "%s%sclose instead of sending %"
+        CURL_FORMAT_CURL_OFF_T " more bytes",
+        ongoing_auth? ongoing_auth : "",
+        ongoing_auth? " send, " : "",
+        upload_remain);
+    else
+      infof(data, "%s%sclose instead of sending unknown amount "
+        "of more bytes",
+        ongoing_auth? ongoing_auth : "",
+        ongoing_auth? " send, " : "");
+    /* We decided to abort the ongoing transfer */
     streamclose(conn, "Mid-auth HTTP and much data left to send");
+    /* FIXME: questionable manipulation here, can we do this differently? */
     data->req.size = 0; /* don't download any more than 0 bytes */
-
-    /* There still is data left to send, but this connection is marked for
-       closure so we can safely do the rewind right now */
-  }
-
-  if(bytessent) {
-    /* mark for rewind since if we already sent something */
-    data->state.rewindbeforesend = TRUE;
-    infof(data, "Please rewind output before next send");
   }
-
   return CURLE_OK;
 }
 
@@ -658,7 +515,7 @@ CURLcode Curl_http_auth_act(struct Curl_easy *data)
 
   if((data->state.aptr.user || data->set.str[STRING_BEARER]) &&
      ((data->req.httpcode == 401) ||
-      (conn->bits.authneg && data->req.httpcode < 300))) {
+      (data->req.authneg && data->req.httpcode < 300))) {
     pickhost = pickoneauth(&data->state.authhost, authmask);
     if(!pickhost)
       data->state.authproblem = TRUE;
@@ -672,7 +529,7 @@ CURLcode Curl_http_auth_act(struct Curl_easy *data)
 #ifndef CURL_DISABLE_PROXY
   if(conn->bits.proxy_user_passwd &&
      ((data->req.httpcode == 407) ||
-      (conn->bits.authneg && data->req.httpcode < 300))) {
+      (data->req.authneg && data->req.httpcode < 300))) {
     pickproxy = pickoneauth(&data->state.authproxy,
                             authmask & ~CURLAUTH_BEARER);
     if(!pickproxy)
@@ -681,13 +538,10 @@ CURLcode Curl_http_auth_act(struct Curl_easy *data)
 #endif
 
   if(pickhost || pickproxy) {
-    if((data->state.httpreq != HTTPREQ_GET) &&
-       (data->state.httpreq != HTTPREQ_HEAD) &&
-       !data->state.rewindbeforesend) {
-      result = http_perhapsrewind(data, conn);
-      if(result)
-        return result;
-    }
+    result = http_perhapsrewind(data, conn);
+    if(result)
+      return result;
+
     /* In case this is GSS auth, the newurl field is already allocated so
        we must make sure to free it before allocating a new one. As figured
        out in bug #2284386 */
@@ -698,7 +552,7 @@ CURLcode Curl_http_auth_act(struct Curl_easy *data)
   }
   else if((data->req.httpcode < 300) &&
           (!data->state.authhost.done) &&
-          conn->bits.authneg) {
+          data->req.authneg) {
     /* no (known) authentication available,
        authentication is not "done" yet and
        no authentication seems to be required and
@@ -711,7 +565,7 @@ CURLcode Curl_http_auth_act(struct Curl_easy *data)
       data->state.authhost.done = TRUE;
     }
   }
-  if(http_should_fail(data)) {
+  if(http_should_fail(data, data->req.httpcode)) {
     failf(data, "The requested URL returned error: %d",
           data->req.httpcode);
     result = CURLE_HTTP_RETURNED_ERROR;
@@ -768,15 +622,6 @@ output_auth_headers(struct Curl_easy *data,
   }
   else
 #endif
-#if defined(USE_NTLM) && defined(NTLM_WB_ENABLED)
-  if(authstatus->picked == CURLAUTH_NTLM_WB) {
-    auth = "NTLM_WB";
-    result = Curl_output_ntlm_wb(data, conn, proxy);
-    if(result)
-      return result;
-  }
-  else
-#endif
 #ifndef CURL_DISABLE_DIGEST_AUTH
   if(authstatus->picked == CURLAUTH_DIGEST) {
     auth = "Digest";
@@ -836,6 +681,7 @@ output_auth_headers(struct Curl_easy *data,
           (data->state.aptr.user ?
            data->state.aptr.user : ""));
 #else
+    (void)proxy;
     infof(data, "Server auth using %s with user '%s'",
           auth, data->state.aptr.user ?
           data->state.aptr.user : "");
@@ -845,7 +691,7 @@ output_auth_headers(struct Curl_easy *data,
   else
     authstatus->multipass = FALSE;
 
-  return CURLE_OK;
+  return result;
 }
 
 /**
@@ -942,10 +788,10 @@ Curl_http_output_auth(struct Curl_easy *data,
      (httpreq != HTTPREQ_HEAD)) {
     /* Auth is required and we are not authenticated yet. Make a PUT or POST
        with content-length zero as a "probe". */
-    conn->bits.authneg = TRUE;
+    data->req.authneg = TRUE;
   }
   else
-    conn->bits.authneg = FALSE;
+    data->req.authneg = FALSE;
 
   return result;
 }
@@ -970,17 +816,21 @@ Curl_http_output_auth(struct Curl_easy *data,
 }
 #endif
 
-/*
- * Curl_http_input_auth() deals with Proxy-Authenticate: and WWW-Authenticate:
- * headers. They are dealt with both in the transfer.c main loop and in the
- * proxy CONNECT loop.
- */
-
+#if defined(USE_SPNEGO) || defined(USE_NTLM) || \
+  !defined(CURL_DISABLE_DIGEST_AUTH) || \
+  !defined(CURL_DISABLE_BASIC_AUTH) || \
+  !defined(CURL_DISABLE_BEARER_AUTH)
 static int is_valid_auth_separator(char ch)
 {
   return ch == '\0' || ch == ',' || ISSPACE(ch);
 }
+#endif
 
+/*
+ * Curl_http_input_auth() deals with Proxy-Authenticate: and WWW-Authenticate:
+ * headers. They are dealt with both in the transfer.c main loop and in the
+ * proxy CONNECT loop.
+ */
 CURLcode Curl_http_input_auth(struct Curl_easy *data, bool proxy,
                               const char *auth) /* the first non-space */
 {
@@ -992,11 +842,15 @@ CURLcode Curl_http_input_auth(struct Curl_easy *data, bool proxy,
   curlnegotiate *negstate = proxy ? &conn->proxy_negotiate_state :
                                     &conn->http_negotiate_state;
 #endif
+#if defined(USE_SPNEGO) || \
+  defined(USE_NTLM) || \
+  !defined(CURL_DISABLE_DIGEST_AUTH) || \
+  !defined(CURL_DISABLE_BASIC_AUTH) || \
+  !defined(CURL_DISABLE_BEARER_AUTH)
+
   unsigned long *availp;
   struct auth *authp;
 
-  (void) conn; /* In case conditionals make it unused. */
-
   if(proxy) {
     availp = &data->info.proxyauthavail;
     authp = &data->state.authproxy;
@@ -1005,6 +859,11 @@ CURLcode Curl_http_input_auth(struct Curl_easy *data, bool proxy,
     availp = &data->info.httpauthavail;
     authp = &data->state.authhost;
   }
+#else
+  (void) proxy;
+#endif
+
+  (void) conn; /* In case conditionals make it unused. */
 
   /*
    * Here we check if we want the specific single authentication (using ==) and
@@ -1052,31 +911,15 @@ CURLcode Curl_http_input_auth(struct Curl_easy *data, bool proxy,
       /* NTLM support requires the SSL crypto libs */
       if(checkprefix("NTLM", auth) && is_valid_auth_separator(auth[4])) {
         if((authp->avail & CURLAUTH_NTLM) ||
-           (authp->avail & CURLAUTH_NTLM_WB) ||
            Curl_auth_is_ntlm_supported()) {
           *availp |= CURLAUTH_NTLM;
           authp->avail |= CURLAUTH_NTLM;
 
-          if(authp->picked == CURLAUTH_NTLM ||
-             authp->picked == CURLAUTH_NTLM_WB) {
+          if(authp->picked == CURLAUTH_NTLM) {
             /* NTLM authentication is picked and activated */
             CURLcode result = Curl_input_ntlm(data, proxy, auth);
             if(!result) {
               data->state.authproblem = FALSE;
-#ifdef NTLM_WB_ENABLED
-              if(authp->picked == CURLAUTH_NTLM_WB) {
-                *availp &= ~CURLAUTH_NTLM;
-                authp->avail &= ~CURLAUTH_NTLM;
-                *availp |= CURLAUTH_NTLM_WB;
-                authp->avail |= CURLAUTH_NTLM_WB;
-
-                result = Curl_input_ntlm_wb(data, conn, proxy, auth);
-                if(result) {
-                  infof(data, "Authentication problem. Ignoring this.");
-                  data->state.authproblem = TRUE;
-                }
-              }
-#endif
             }
             else {
               infof(data, "Authentication problem. Ignoring this.");
@@ -1139,6 +982,15 @@ CURLcode Curl_http_input_auth(struct Curl_easy *data, bool proxy,
                 data->state.authproblem = TRUE;
               }
             }
+#else
+            {
+              /*
+               * Empty block to terminate the if-else chain correctly.
+               *
+               * A semicolon would yield the same result here, but can cause a
+               * compiler warning when -Wextra is enabled.
+               */
+            }
 #endif
 
     /* there may be multiple methods on one line, so keep reading */
@@ -1154,23 +1006,18 @@ CURLcode Curl_http_input_auth(struct Curl_easy *data, bool proxy,
 }
 
 /**
- * http_should_fail() determines whether an HTTP response has gotten us
+ * http_should_fail() determines whether an HTTP response code has gotten us
  * into an error state or not.
  *
- * @param conn all information about the current connection
- *
  * @retval FALSE communications should continue
  *
  * @retval TRUE communications should not continue
  */
-static bool http_should_fail(struct Curl_easy *data)
+static bool http_should_fail(struct Curl_easy *data, int httpcode)
 {
-  int httpcode;
   DEBUGASSERT(data);
   DEBUGASSERT(data->conn);
 
-  httpcode = data->req.httpcode;
-
   /*
   ** If we haven't been asked to fail on error,
   ** don't fail.
@@ -1232,274 +1079,6 @@ static bool http_should_fail(struct Curl_easy *data)
   return data->state.authproblem;
 }
 
-/*
- * readmoredata() is a "fread() emulation" to provide POST and/or request
- * data. It is used when a huge POST is to be made and the entire chunk wasn't
- * sent in the first send(). This function will then be called from the
- * transfer.c loop when more data is to be sent to the peer.
- *
- * Returns the amount of bytes it filled the buffer with.
- */
-static size_t readmoredata(char *buffer,
-                           size_t size,
-                           size_t nitems,
-                           void *userp)
-{
-  struct HTTP *http = (struct HTTP *)userp;
-  struct Curl_easy *data = http->backup.data;
-  size_t fullsize = size * nitems;
-
-  if(!http->postsize)
-    /* nothing to return */
-    return 0;
-
-  /* make sure that an HTTP request is never sent away chunked! */
-  data->req.forbidchunk = (http->sending == HTTPSEND_REQUEST)?TRUE:FALSE;
-
-  if(data->set.max_send_speed &&
-     (data->set.max_send_speed < (curl_off_t)fullsize) &&
-     (data->set.max_send_speed < http->postsize))
-    /* speed limit */
-    fullsize = (size_t)data->set.max_send_speed;
-
-  else if(http->postsize <= (curl_off_t)fullsize) {
-    memcpy(buffer, http->postdata, (size_t)http->postsize);
-    fullsize = (size_t)http->postsize;
-
-    if(http->backup.postsize) {
-      /* move backup data into focus and continue on that */
-      http->postdata = http->backup.postdata;
-      http->postsize = http->backup.postsize;
-      data->state.fread_func = http->backup.fread_func;
-      data->state.in = http->backup.fread_in;
-
-      http->sending++; /* move one step up */
-
-      http->backup.postsize = 0;
-    }
-    else
-      http->postsize = 0;
-
-    return fullsize;
-  }
-
-  memcpy(buffer, http->postdata, fullsize);
-  http->postdata += fullsize;
-  http->postsize -= fullsize;
-
-  return fullsize;
-}
-
-/*
- * Curl_buffer_send() sends a header buffer and frees all associated
- * memory.  Body data may be appended to the header data if desired.
- *
- * Returns CURLcode
- */
-CURLcode Curl_buffer_send(struct dynbuf *in,
-                          struct Curl_easy *data,
-                          struct HTTP *http,
-                          /* add the number of sent bytes to this
-                             counter */
-                          curl_off_t *bytes_written,
-                          /* how much of the buffer contains body data */
-                          curl_off_t included_body_bytes,
-                          int sockindex)
-{
-  ssize_t amount;
-  CURLcode result;
-  char *ptr;
-  size_t size;
-  struct connectdata *conn = data->conn;
-  size_t sendsize;
-  size_t headersize;
-
-  DEBUGASSERT(sockindex <= SECONDARYSOCKET && sockindex >= 0);
-
-  /* The looping below is required since we use non-blocking sockets, but due
-     to the circumstances we will just loop and try again and again etc */
-
-  ptr = Curl_dyn_ptr(in);
-  size = Curl_dyn_len(in);
-
-  headersize = size - (size_t)included_body_bytes; /* the initial part that
-                                                      isn't body is header */
-
-  DEBUGASSERT(size > (size_t)included_body_bytes);
-
-  if((conn->handler->flags & PROTOPT_SSL
-#ifndef CURL_DISABLE_PROXY
-      || IS_HTTPS_PROXY(conn->http_proxy.proxytype)
-#endif
-       )
-     && conn->httpversion < 20) {
-    /* Make sure this doesn't send more body bytes than what the max send
-       speed says. The request bytes do not count to the max speed.
-    */
-    if(data->set.max_send_speed &&
-       (included_body_bytes > data->set.max_send_speed)) {
-      curl_off_t overflow = included_body_bytes - data->set.max_send_speed;
-      DEBUGASSERT((size_t)overflow < size);
-      sendsize = size - (size_t)overflow;
-    }
-    else
-      sendsize = size;
-
-    /* OpenSSL is very picky and we must send the SAME buffer pointer to the
-       library when we attempt to re-send this buffer. Sending the same data
-       is not enough, we must use the exact same address. For this reason, we
-       must copy the data to the uploadbuffer first, since that is the buffer
-       we will be using if this send is retried later.
-    */
-    result = Curl_get_upload_buffer(data);
-    if(result) {
-      /* malloc failed, free memory and return to the caller */
-      Curl_dyn_free(in);
-      return result;
-    }
-    /* We never send more than upload_buffer_size bytes in one single chunk
-       when we speak HTTPS, as if only a fraction of it is sent now, this data
-       needs to fit into the normal read-callback buffer later on and that
-       buffer is using this size.
-    */
-    if(sendsize > (size_t)data->set.upload_buffer_size)
-      sendsize = (size_t)data->set.upload_buffer_size;
-
-    memcpy(data->state.ulbuf, ptr, sendsize);
-    ptr = data->state.ulbuf;
-  }
-  else {
-#ifdef CURLDEBUG
-    /* Allow debug builds to override this logic to force short initial
-       sends
-     */
-    char *p = getenv("CURL_SMALLREQSEND");
-    if(p) {
-      size_t altsize = (size_t)strtoul(p, NULL, 10);
-      if(altsize)
-        sendsize = CURLMIN(size, altsize);
-      else
-        sendsize = size;
-    }
-    else
-#endif
-    {
-      /* Make sure this doesn't send more body bytes than what the max send
-         speed says. The request bytes do not count to the max speed.
-      */
-      if(data->set.max_send_speed &&
-         (included_body_bytes > data->set.max_send_speed)) {
-        curl_off_t overflow = included_body_bytes - data->set.max_send_speed;
-        DEBUGASSERT((size_t)overflow < size);
-        sendsize = size - (size_t)overflow;
-      }
-      else
-        sendsize = size;
-    }
-
-    /* We currently cannot send more that this for http here:
-     * - if sending blocks, it return 0 as amount
-     * - we then whisk aside the `in` into the `http` struct
-     *   and install our own `data->state.fread_func` that
-     *   on subsequent calls reads `in` empty.
-     * - when the whisked away `in` is empty, the `fread_func`
-     *   is restored ot its original state.
-     * The problem is that `fread_func` can only return
-     * `upload_buffer_size` lengths. If the send we do here
-     * is larger and blocks, we do re-sending with smaller
-     * amounts of data and connection filters do not like
-     * that.
-     */
-    if(http && (sendsize > (size_t)data->set.upload_buffer_size))
-      sendsize = (size_t)data->set.upload_buffer_size;
-  }
-
-  result = Curl_nwrite(data, sockindex, ptr, sendsize, &amount);
-
-  if(!result) {
-    /*
-     * Note that we may not send the entire chunk at once, and we have a set
-     * number of data bytes at the end of the big buffer (out of which we may
-     * only send away a part).
-     */
-    /* how much of the header that was sent */
-    size_t headlen = (size_t)amount>headersize ? headersize : (size_t)amount;
-    size_t bodylen = amount - headlen;
-
-    /* this data _may_ contain binary stuff */
-    Curl_debug(data, CURLINFO_HEADER_OUT, ptr, headlen);
-    if(bodylen)
-      /* there was body data sent beyond the initial header part, pass that on
-         to the debug callback too */
-      Curl_debug(data, CURLINFO_DATA_OUT, ptr + headlen, bodylen);
-
-    /* 'amount' can never be a very large value here so typecasting it so a
-       signed 31 bit value should not cause problems even if ssize_t is
-       64bit */
-    *bytes_written += (long)amount;
-
-    if(http) {
-      /* if we sent a piece of the body here, up the byte counter for it
-         accordingly */
-      data->req.writebytecount += bodylen;
-      Curl_pgrsSetUploadCounter(data, data->req.writebytecount);
-
-      if((size_t)amount != size) {
-        /* The whole request could not be sent in one system call. We must
-           queue it up and send it later when we get the chance. We must not
-           loop here and wait until it might work again. */
-
-        size -= amount;
-
-        ptr = Curl_dyn_ptr(in) + amount;
-
-        /* backup the currently set pointers */
-        http->backup.fread_func = data->state.fread_func;
-        http->backup.fread_in = data->state.in;
-        http->backup.postdata = http->postdata;
-        http->backup.postsize = http->postsize;
-        http->backup.data = data;
-
-        /* set the new pointers for the request-sending */
-        data->state.fread_func = (curl_read_callback)readmoredata;
-        data->state.in = (void *)http;
-        http->postdata = ptr;
-        http->postsize = (curl_off_t)size;
-
-        /* this much data is remaining header: */
-        data->req.pendingheader = headersize - headlen;
-
-        http->send_buffer = *in; /* copy the whole struct */
-        http->sending = HTTPSEND_REQUEST;
-        return CURLE_OK;
-      }
-      http->sending = HTTPSEND_BODY;
-      /* the full buffer was sent, clean up and return */
-    }
-    else {
-      if((size_t)amount != size)
-        /* We have no continue-send mechanism now, fail. This can only happen
-           when this function is used from the CONNECT sending function. We
-           currently (stupidly) assume that the whole request is always sent
-           away in the first single chunk.
-
-           This needs FIXing.
-        */
-        return CURLE_SEND_ERROR;
-    }
-  }
-  Curl_dyn_free(in);
-
-  /* no remaining header data */
-  data->req.pendingheader = 0;
-  return result;
-}
-
-/* end of the add_buffer functions */
-/* ------------------------------------------------------------------------- */
-
-
-
 /*
  * Curl_compareheader()
  *
@@ -1576,9 +1155,9 @@ CURLcode Curl_http_connect(struct Curl_easy *data, bool *done)
 /* this returns the socket to wait for in the DO and DOING state for the multi
    interface and then we're always _sending_ a request and thus we wait for
    the single socket to become writable only */
-static int http_getsock_do(struct Curl_easy *data,
-                           struct connectdata *conn,
-                           curl_socket_t *socks)
+int Curl_http_getsock_do(struct Curl_easy *data,
+                         struct connectdata *conn,
+                         curl_socket_t *socks)
 {
   /* write mode */
   (void)conn;
@@ -1602,19 +1181,11 @@ CURLcode Curl_http_done(struct Curl_easy *data,
   data->state.authhost.multipass = FALSE;
   data->state.authproxy.multipass = FALSE;
 
-  Curl_unencode_cleanup(data);
-
-  /* set the proper values (possibly modified on POST) */
-  conn->seek_func = data->set.seek_func; /* restore */
-  conn->seek_client = data->set.seek_client; /* restore */
-
   if(!http)
     return CURLE_OK;
 
-  Curl_dyn_free(&http->send_buffer);
   Curl_dyn_reset(&data->state.headerb);
   Curl_hyper_done(data);
-  Curl_ws_done(data);
 
   if(status)
     return status;
@@ -1674,85 +1245,12 @@ static const char *get_http_string(const struct Curl_easy *data,
 }
 #endif
 
-/* check and possibly add an Expect: header */
-static CURLcode expect100(struct Curl_easy *data,
-                          struct connectdata *conn,
-                          struct dynbuf *req)
-{
-  CURLcode result = CURLE_OK;
-  data->state.expect100header = FALSE; /* default to false unless it is set
-                                          to TRUE below */
-  if(!data->state.disableexpect && Curl_use_http_1_1plus(data, conn) &&
-     (conn->httpversion < 20)) {
-    /* if not doing HTTP 1.0 or version 2, or disabled explicitly, we add an
-       Expect: 100-continue to the headers which actually speeds up post
-       operations (as there is one packet coming back from the web server) */
-    const char *ptr = Curl_checkheaders(data, STRCONST("Expect"));
-    if(ptr) {
-      data->state.expect100header =
-        Curl_compareheader(ptr, STRCONST("Expect:"), STRCONST("100-continue"));
-    }
-    else {
-      result = Curl_dyn_addn(req, STRCONST("Expect: 100-continue\r\n"));
-      if(!result)
-        data->state.expect100header = TRUE;
-    }
-  }
-
-  return result;
-}
-
 enum proxy_use {
   HEADER_SERVER,  /* direct to server */
   HEADER_PROXY,   /* regular request to proxy */
   HEADER_CONNECT  /* sending CONNECT to a proxy */
 };
 
-/* used to compile the provided trailers into one buffer
-   will return an error code if one of the headers is
-   not formatted correctly */
-CURLcode Curl_http_compile_trailers(struct curl_slist *trailers,
-                                    struct dynbuf *b,
-                                    struct Curl_easy *handle)
-{
-  char *ptr = NULL;
-  CURLcode result = CURLE_OK;
-  const char *endofline_native = NULL;
-  const char *endofline_network = NULL;
-
-  if(
-#ifdef CURL_DO_LINEEND_CONV
-     (handle->state.prefer_ascii) ||
-#endif
-     (handle->set.crlf)) {
-    /* \n will become \r\n later on */
-    endofline_native  = "\n";
-    endofline_network = "\x0a";
-  }
-  else {
-    endofline_native  = "\r\n";
-    endofline_network = "\x0d\x0a";
-  }
-
-  while(trailers) {
-    /* only add correctly formatted trailers */
-    ptr = strchr(trailers->data, ':');
-    if(ptr && *(ptr + 1) == ' ') {
-      result = Curl_dyn_add(b, trailers->data);
-      if(result)
-        return result;
-      result = Curl_dyn_add(b, endofline_native);
-      if(result)
-        return result;
-    }
-    else
-      infof(handle, "Malformatted trailing header, skipping trailer");
-    trailers = trailers->next;
-  }
-  result = Curl_dyn_add(b, endofline_network);
-  return result;
-}
-
 static bool hd_name_eq(const char *n1, size_t n1len,
                        const char *n2, size_t n2len)
 {
@@ -1871,7 +1369,7 @@ CURLcode Curl_dynhds_add_custom(struct Curl_easy *data,
               /* this header is sent later */
               hd_name_eq(name, namelen, STRCONST("Content-Type:")))
         ;
-      else if(conn->bits.authneg &&
+      else if(data->req.authneg &&
               /* while doing auth neg, don't allow the custom length since
                  we will force length zero then */
               hd_name_eq(name, namelen, STRCONST("Content-Length:")))
@@ -2017,7 +1515,7 @@ CURLcode Curl_add_custom_headers(struct Curl_easy *data,
                   /* this header is sent later */
                   checkprefix("Content-Type:", compare))
             ;
-          else if(conn->bits.authneg &&
+          else if(data->req.authneg &&
                   /* while doing auth neg, don't allow the custom length since
                      we will force length zero then */
                   checkprefix("Content-Length:", compare))
@@ -2086,6 +1584,7 @@ CURLcode Curl_add_timecondition(struct Curl_easy *data,
 
   switch(data->set.timecondition) {
   default:
+    DEBUGF(infof(data, "invalid time condition"));
     return CURLE_BAD_FUNCTION_ARGUMENT;
 
   case CURL_TIMECOND_IFMODSINCE:
@@ -2254,7 +1753,7 @@ CURLcode Curl_http_host(struct Curl_easy *data, struct connectdata *conn)
     }
 #endif
 
-    if(strcmp("Host:", ptr)) {
+    if(!strcasecompare("Host:", ptr)) {
       aptr->host = aprintf("Host:%s\r\n", &ptr[5]);
       if(!aptr->host)
         return CURLE_OUT_OF_MEMORY;
@@ -2342,9 +1841,7 @@ CURLcode Curl_http_target(struct Curl_easy *data,
         return CURLE_OUT_OF_MEMORY;
       }
     }
-    /* Extract the URL to use in the request. Store in STRING_TEMP_URL for
-       clean-up reasons if the function returns before the free() further
-       down. */
+    /* Extract the URL to use in the request. */
     uc = curl_url_get(h, CURLUPART_URL, &url, CURLU_NO_DEFAULT_PORT);
     if(uc) {
       curl_url_cleanup(h);
@@ -2399,86 +1896,220 @@ CURLcode Curl_http_target(struct Curl_easy *data,
   return result;
 }
 
-CURLcode Curl_http_body(struct Curl_easy *data, struct connectdata *conn,
-                        Curl_HttpReq httpreq, const char **tep)
+#if !defined(CURL_DISABLE_MIME) || !defined(CURL_DISABLE_FORM_API)
+static CURLcode set_post_reader(struct Curl_easy *data, Curl_HttpReq httpreq)
 {
-  CURLcode result = CURLE_OK;
-  const char *ptr;
-  struct HTTP *http = data->req.p.http;
-  http->postsize = 0;
+  CURLcode result;
 
   switch(httpreq) {
+#ifndef CURL_DISABLE_MIME
   case HTTPREQ_POST_MIME:
     data->state.mimepost = &data->set.mimepost;
     break;
+#endif
 #ifndef CURL_DISABLE_FORM_API
   case HTTPREQ_POST_FORM:
     /* Convert the form structure into a mime structure, then keep
        the conversion */
     if(!data->state.formp) {
-      data->state.formp = calloc(sizeof(curl_mimepart), 1);
+      data->state.formp = calloc(1, sizeof(curl_mimepart));
       if(!data->state.formp)
         return CURLE_OUT_OF_MEMORY;
       Curl_mime_cleanpart(data->state.formp);
       result = Curl_getformdata(data, data->state.formp, data->set.httppost,
                                 data->state.fread_func);
-      if(result)
+      if(result) {
+        Curl_safefree(data->state.formp);
         return result;
+      }
       data->state.mimepost = data->state.formp;
     }
     break;
 #endif
   default:
     data->state.mimepost = NULL;
+    break;
   }
 
+  switch(httpreq) {
+  case HTTPREQ_POST_FORM:
+  case HTTPREQ_POST_MIME:
+    /* This is form posting using mime data. */
 #ifndef CURL_DISABLE_MIME
-  if(data->state.mimepost) {
-    const char *cthdr = Curl_checkheaders(data, STRCONST("Content-Type"));
+    if(data->state.mimepost) {
+      const char *cthdr = Curl_checkheaders(data, STRCONST("Content-Type"));
 
-    /* Read and seek body only. */
-    data->state.mimepost->flags |= MIME_BODY_ONLY;
+      /* Read and seek body only. */
+      data->state.mimepost->flags |= MIME_BODY_ONLY;
 
-    /* Prepare the mime structure headers & set content type. */
+      /* Prepare the mime structure headers & set content type. */
 
-    if(cthdr)
-      for(cthdr += 13; *cthdr == ' '; cthdr++)
-        ;
-    else if(data->state.mimepost->kind == MIMEKIND_MULTIPART)
-      cthdr = "multipart/form-data";
+      if(cthdr)
+        for(cthdr += 13; *cthdr == ' '; cthdr++)
+          ;
+      else if(data->state.mimepost->kind == MIMEKIND_MULTIPART)
+        cthdr = "multipart/form-data";
 
-    curl_mime_headers(data->state.mimepost, data->set.headers, 0);
-    result = Curl_mime_prepare_headers(data, data->state.mimepost, cthdr,
-                                       NULL, MIMESTRATEGY_FORM);
-    curl_mime_headers(data->state.mimepost, NULL, 0);
-    if(!result)
-      result = Curl_mime_rewind(data->state.mimepost);
-    if(result)
-      return result;
-    http->postsize = Curl_mime_size(data->state.mimepost);
+      curl_mime_headers(data->state.mimepost, data->set.headers, 0);
+      result = Curl_mime_prepare_headers(data, data->state.mimepost, cthdr,
+                                         NULL, MIMESTRATEGY_FORM);
+      if(result)
+        return result;
+      curl_mime_headers(data->state.mimepost, NULL, 0);
+      result = Curl_creader_set_mime(data, data->state.mimepost);
+      if(result)
+        return result;
+    }
+    else
+#endif
+    {
+      result = Curl_creader_set_null(data);
+    }
+    data->state.infilesize = Curl_creader_total_length(data);
+    return result;
+
+  default:
+    return Curl_creader_set_null(data);
+  }
+  /* never reached */
+}
+#endif
+
+static CURLcode set_reader(struct Curl_easy *data, Curl_HttpReq httpreq)
+{
+  CURLcode result = CURLE_OK;
+  curl_off_t postsize = data->state.infilesize;
+
+  DEBUGASSERT(data->conn);
+
+  if(data->req.authneg) {
+    return Curl_creader_set_null(data);
   }
+
+  switch(httpreq) {
+  case HTTPREQ_PUT: /* Let's PUT the data to the server! */
+    if(!postsize)
+      result = Curl_creader_set_null(data);
+    else
+      result = Curl_creader_set_fread(data, postsize);
+    return result;
+
+#if !defined(CURL_DISABLE_MIME) || !defined(CURL_DISABLE_FORM_API)
+  case HTTPREQ_POST_FORM:
+  case HTTPREQ_POST_MIME:
+    return set_post_reader(data, httpreq);
 #endif
 
+  case HTTPREQ_POST:
+    /* this is the simple POST, using x-www-form-urlencoded style */
+    /* the size of the post body */
+    if(!postsize) {
+      result = Curl_creader_set_null(data);
+    }
+    else if(data->set.postfields) {
+      if(postsize > 0)
+        result = Curl_creader_set_buf(data, data->set.postfields,
+                                      (size_t)postsize);
+      else
+        result = Curl_creader_set_null(data);
+    }
+    else {
+      /* we read the bytes from the callback. In case "chunked" encoding
+       * is forced by the application, we disregard `postsize`. This is
+       * a backward compatibility decision to earlier versions where
+       * chunking disregarded this. See issue #13229. */
+      bool chunked = FALSE;
+      char *ptr = Curl_checkheaders(data, STRCONST("Transfer-Encoding"));
+      if(ptr) {
+        /* Some kind of TE is requested, check if 'chunked' is chosen */
+        chunked = Curl_compareheader(ptr, STRCONST("Transfer-Encoding:"),
+                                     STRCONST("chunked"));
+      }
+      result = Curl_creader_set_fread(data, chunked? -1 : postsize);
+    }
+    return result;
+
+  default:
+    /* HTTP GET/HEAD download, has no body, needs no Content-Length */
+    data->state.infilesize = 0;
+    return Curl_creader_set_null(data);
+  }
+  /* not reached */
+}
+
+static CURLcode http_resume(struct Curl_easy *data, Curl_HttpReq httpreq)
+{
+  if((HTTPREQ_POST == httpreq || HTTPREQ_PUT == httpreq) &&
+     data->state.resume_from) {
+    /**********************************************************************
+     * Resuming upload in HTTP means that we PUT or POST and that we have
+     * got a resume_from value set. The resume value has already created
+     * a Range: header that will be passed along. We need to "fast forward"
+     * the file the given number of bytes and decrease the assume upload
+     * file size before we continue this venture in the dark lands of HTTP.
+     * Resuming mime/form posting at an offset > 0 has no sense and is ignored.
+     *********************************************************************/
+
+    if(data->state.resume_from < 0) {
+      /*
+       * This is meant to get the size of the present remote-file by itself.
+       * We don't support this now. Bail out!
+       */
+      data->state.resume_from = 0;
+    }
+
+    if(data->state.resume_from && !data->req.authneg) {
+      /* only act on the first request */
+      CURLcode result;
+      result = Curl_creader_resume_from(data, data->state.resume_from);
+      if(result) {
+        failf(data, "Unable to resume from offset %" CURL_FORMAT_CURL_OFF_T,
+              data->state.resume_from);
+        return result;
+      }
+    }
+  }
+  return CURLE_OK;
+}
+
+CURLcode Curl_http_req_set_reader(struct Curl_easy *data,
+                                  Curl_HttpReq httpreq,
+                                  const char **tep)
+{
+  CURLcode result = CURLE_OK;
+  const char *ptr;
+
+  result = set_reader(data, httpreq);
+  if(result)
+    return result;
+
+  result = http_resume(data, httpreq);
+  if(result)
+    return result;
+
   ptr = Curl_checkheaders(data, STRCONST("Transfer-Encoding"));
   if(ptr) {
     /* Some kind of TE is requested, check if 'chunked' is chosen */
     data->req.upload_chunky =
       Curl_compareheader(ptr,
                          STRCONST("Transfer-Encoding:"), STRCONST("chunked"));
+    if(data->req.upload_chunky &&
+       Curl_use_http_1_1plus(data, data->conn) &&
+       (data->conn->httpversion >= 20)) {
+       infof(data, "suppressing chunked transfer encoding on connection "
+             "using HTTP version 2 or higher");
+       data->req.upload_chunky = FALSE;
+    }
   }
   else {
-    if((conn->handler->protocol & PROTO_FAMILY_HTTP) &&
-       (((httpreq == HTTPREQ_POST_MIME || httpreq == HTTPREQ_POST_FORM) &&
-         http->postsize < 0) ||
-        ((data->state.upload || httpreq == HTTPREQ_POST) &&
-         data->state.infilesize == -1))) {
-      if(conn->bits.authneg)
-        /* don't enable chunked during auth neg */
-        ;
-      else if(Curl_use_http_1_1plus(data, conn)) {
-        if(conn->httpversion < 20)
-          /* HTTP, upload, unknown file size and not HTTP 1.0 */
-          data->req.upload_chunky = TRUE;
+    curl_off_t req_clen = Curl_creader_total_length(data);
+
+    if(req_clen < 0) {
+      /* indeterminate request content length */
+      if(Curl_use_http_1_1plus(data, data->conn)) {
+        /* On HTTP/1.1, enable chunked, on HTTP/2 and later we do not
+         * need it */
+        data->req.upload_chunky = (data->conn->httpversion < 20);
       }
       else {
         failf(data, "Chunky upload is not supported by HTTP 1.0");
@@ -2496,350 +2127,128 @@ CURLcode Curl_http_body(struct Curl_easy *data, struct connectdata *conn,
   return result;
 }
 
-CURLcode Curl_http_bodysend(struct Curl_easy *data, struct connectdata *conn,
-                            struct dynbuf *r, Curl_HttpReq httpreq)
+static CURLcode addexpect(struct Curl_easy *data, struct dynbuf *r,
+                          bool *announced_exp100)
 {
-#ifndef USE_HYPER
-  /* Hyper always handles the body separately */
-  curl_off_t included_body = 0;
-#else
-  /* from this point down, this function should not be used */
-#define Curl_buffer_send(a,b,c,d,e,f) CURLE_OK
-#endif
-  CURLcode result = CURLE_OK;
-  struct HTTP *http = data->req.p.http;
-  const char *ptr;
-
-  /* If 'authdone' is FALSE, we must not set the write socket index to the
-     Curl_transfer() call below, as we're not ready to actually upload any
-     data yet. */
-
-  switch(httpreq) {
-
-  case HTTPREQ_PUT: /* Let's PUT the data to the server! */
-
-    if(conn->bits.authneg)
-      http->postsize = 0;
-    else
-      http->postsize = data->state.infilesize;
+  CURLcode result;
+  char *ptr;
 
-    if((http->postsize != -1) && !data->req.upload_chunky &&
-       (conn->bits.authneg ||
-        !Curl_checkheaders(data, STRCONST("Content-Length")))) {
-      /* only add Content-Length if not uploading chunked */
-      result = Curl_dyn_addf(r, "Content-Length: %" CURL_FORMAT_CURL_OFF_T
-                             "\r\n", http->postsize);
-      if(result)
-        return result;
-    }
+  *announced_exp100 = FALSE;
+  /* Avoid Expect: 100-continue if Upgrade: is used */
+  if(data->req.upgr101 != UPGR101_INIT)
+    return CURLE_OK;
 
-    /* For really small puts we don't use Expect: headers at all, and for
-       the somewhat bigger ones we allow the app to disable it. Just make
-       sure that the expect100header is always set to the preferred value
-       here. */
-    ptr = Curl_checkheaders(data, STRCONST("Expect"));
-    if(ptr) {
-      data->state.expect100header =
-        Curl_compareheader(ptr, STRCONST("Expect:"), STRCONST("100-continue"));
-    }
-    else if(http->postsize > EXPECT_100_THRESHOLD || http->postsize < 0) {
-      result = expect100(data, conn, r);
+  /* For really small puts we don't use Expect: headers at all, and for
+     the somewhat bigger ones we allow the app to disable it. Just make
+     sure that the expect100header is always set to the preferred value
+     here. */
+  ptr = Curl_checkheaders(data, STRCONST("Expect"));
+  if(ptr) {
+    *announced_exp100 =
+      Curl_compareheader(ptr, STRCONST("Expect:"), STRCONST("100-continue"));
+  }
+  else if(!data->state.disableexpect &&
+          Curl_use_http_1_1plus(data, data->conn) &&
+          (data->conn->httpversion < 20)) {
+    /* if not doing HTTP 1.0 or version 2, or disabled explicitly, we add an
+       Expect: 100-continue to the headers which actually speeds up post
+       operations (as there is one packet coming back from the web server) */
+    curl_off_t client_len = Curl_creader_client_length(data);
+    if(client_len > EXPECT_100_THRESHOLD || client_len < 0) {
+      result = Curl_dyn_addn(r, STRCONST("Expect: 100-continue\r\n"));
       if(result)
         return result;
+      *announced_exp100 = TRUE;
     }
+  }
+  return CURLE_OK;
+}
 
-    /* end of headers */
-    result = Curl_dyn_addn(r, STRCONST("\r\n"));
-    if(result)
-      return result;
-
-    /* set the upload size to the progress meter */
-    Curl_pgrsSetUploadSize(data, http->postsize);
+CURLcode Curl_http_req_complete(struct Curl_easy *data,
+                                struct dynbuf *r, Curl_HttpReq httpreq)
+{
+  CURLcode result = CURLE_OK;
+  curl_off_t req_clen;
+  bool announced_exp100 = FALSE;
 
-    /* this sends the buffer and frees all the buffer resources */
-    result = Curl_buffer_send(r, data, data->req.p.http,
-                              &data->info.request_size, 0,
-                              FIRSTSOCKET);
-    if(result)
-      failf(data, "Failed sending PUT request");
-    else
-      /* prepare for transfer */
-      Curl_setup_transfer(data, FIRSTSOCKET, -1, TRUE,
-                          http->postsize?FIRSTSOCKET:-1);
+  DEBUGASSERT(data->conn);
+#ifndef USE_HYPER
+  if(data->req.upload_chunky) {
+    result = Curl_httpchunk_add_reader(data);
     if(result)
       return result;
-    break;
+  }
+#endif
 
+  /* Get the request body length that has been set up */
+  req_clen = Curl_creader_total_length(data);
+  switch(httpreq) {
+  case HTTPREQ_PUT:
+  case HTTPREQ_POST:
+#if !defined(CURL_DISABLE_MIME) || !defined(CURL_DISABLE_FORM_API)
   case HTTPREQ_POST_FORM:
   case HTTPREQ_POST_MIME:
-    /* This is form posting using mime data. */
-    if(conn->bits.authneg) {
-      /* nothing to post! */
-      result = Curl_dyn_addn(r, STRCONST("Content-Length: 0\r\n\r\n"));
-      if(result)
-        return result;
-
-      result = Curl_buffer_send(r, data, data->req.p.http,
-                                &data->info.request_size, 0,
-                                FIRSTSOCKET);
-      if(result)
-        failf(data, "Failed sending POST request");
-      else
-        /* setup variables for the upcoming transfer */
-        Curl_setup_transfer(data, FIRSTSOCKET, -1, TRUE, -1);
-      break;
-    }
-
-    data->state.infilesize = http->postsize;
-
+#endif
     /* We only set Content-Length and allow a custom Content-Length if
        we don't upload data chunked, as RFC2616 forbids us to set both
-       kinds of headers (Transfer-Encoding: chunked and Content-Length) */
-    if(http->postsize != -1 && !data->req.upload_chunky &&
-       (!Curl_checkheaders(data, STRCONST("Content-Length")))) {
+       kinds of headers (Transfer-Encoding: chunked and Content-Length).
+       We do not override a custom "Content-Length" header, but during
+       authentication negotiation that header is suppressed.
+     */
+    if(req_clen >= 0 && !data->req.upload_chunky &&
+       (data->req.authneg ||
+        !Curl_checkheaders(data, STRCONST("Content-Length")))) {
       /* we allow replacing this header if not during auth negotiation,
          although it isn't very wise to actually set your own */
       result = Curl_dyn_addf(r,
                              "Content-Length: %" CURL_FORMAT_CURL_OFF_T
-                             "\r\n", http->postsize);
-      if(result)
-        return result;
+                             "\r\n", req_clen);
     }
+    if(result)
+      goto out;
 
 #ifndef CURL_DISABLE_MIME
     /* Output mime-generated headers. */
-    {
+    if(data->state.mimepost &&
+       ((httpreq == HTTPREQ_POST_FORM) || (httpreq == HTTPREQ_POST_MIME))) {
       struct curl_slist *hdr;
 
       for(hdr = data->state.mimepost->curlheaders; hdr; hdr = hdr->next) {
         result = Curl_dyn_addf(r, "%s\r\n", hdr->data);
         if(result)
-          return result;
-      }
-    }
-#endif
-
-    /* For really small posts we don't use Expect: headers at all, and for
-       the somewhat bigger ones we allow the app to disable it. Just make
-       sure that the expect100header is always set to the preferred value
-       here. */
-    ptr = Curl_checkheaders(data, STRCONST("Expect"));
-    if(ptr) {
-      data->state.expect100header =
-        Curl_compareheader(ptr, STRCONST("Expect:"), STRCONST("100-continue"));
-    }
-    else if(http->postsize > EXPECT_100_THRESHOLD || http->postsize < 0) {
-      result = expect100(data, conn, r);
-      if(result)
-        return result;
-    }
-    else
-      data->state.expect100header = FALSE;
-
-    /* make the request end in a true CRLF */
-    result = Curl_dyn_addn(r, STRCONST("\r\n"));
-    if(result)
-      return result;
-
-    /* set the upload size to the progress meter */
-    Curl_pgrsSetUploadSize(data, http->postsize);
-
-    /* Read from mime structure. */
-    data->state.fread_func = (curl_read_callback) Curl_mime_read;
-    data->state.in = (void *) data->state.mimepost;
-    http->sending = HTTPSEND_BODY;
-
-    /* this sends the buffer and frees all the buffer resources */
-    result = Curl_buffer_send(r, data, data->req.p.http,
-                              &data->info.request_size, 0,
-                              FIRSTSOCKET);
-    if(result)
-      failf(data, "Failed sending POST request");
-    else
-      /* prepare for transfer */
-      Curl_setup_transfer(data, FIRSTSOCKET, -1, TRUE,
-                          http->postsize?FIRSTSOCKET:-1);
-    if(result)
-      return result;
-
-    break;
-
-  case HTTPREQ_POST:
-    /* this is the simple POST, using x-www-form-urlencoded style */
-
-    if(conn->bits.authneg)
-      http->postsize = 0;
-    else
-      /* the size of the post body */
-      http->postsize = data->state.infilesize;
-
-    /* We only set Content-Length and allow a custom Content-Length if
-       we don't upload data chunked, as RFC2616 forbids us to set both
-       kinds of headers (Transfer-Encoding: chunked and Content-Length) */
-    if((http->postsize != -1) && !data->req.upload_chunky &&
-       (conn->bits.authneg ||
-        !Curl_checkheaders(data, STRCONST("Content-Length")))) {
-      /* we allow replacing this header if not during auth negotiation,
-         although it isn't very wise to actually set your own */
-      result = Curl_dyn_addf(r, "Content-Length: %" CURL_FORMAT_CURL_OFF_T
-                             "\r\n", http->postsize);
-      if(result)
-        return result;
-    }
-
-    if(!Curl_checkheaders(data, STRCONST("Content-Type"))) {
-      result = Curl_dyn_addn(r, STRCONST("Content-Type: application/"
-                                         "x-www-form-urlencoded\r\n"));
-      if(result)
-        return result;
-    }
-
-    /* For really small posts we don't use Expect: headers at all, and for
-       the somewhat bigger ones we allow the app to disable it. Just make
-       sure that the expect100header is always set to the preferred value
-       here. */
-    ptr = Curl_checkheaders(data, STRCONST("Expect"));
-    if(ptr) {
-      data->state.expect100header =
-        Curl_compareheader(ptr, STRCONST("Expect:"), STRCONST("100-continue"));
-    }
-    else if(http->postsize > EXPECT_100_THRESHOLD || http->postsize < 0) {
-      result = expect100(data, conn, r);
-      if(result)
-        return result;
-    }
-    else
-      data->state.expect100header = FALSE;
-
-#ifndef USE_HYPER
-    /* With Hyper the body is always passed on separately */
-    if(data->set.postfields) {
-      if(!data->state.expect100header &&
-         (http->postsize < MAX_INITIAL_POST_SIZE)) {
-        /* if we don't use expect: 100  AND
-           postsize is less than MAX_INITIAL_POST_SIZE
-
-           then append the post data to the HTTP request header. This limit
-           is no magic limit but only set to prevent really huge POSTs to
-           get the data duplicated with malloc() and family. */
-
-        /* end of headers! */
-        result = Curl_dyn_addn(r, STRCONST("\r\n"));
-        if(result)
-          return result;
-
-        if(!data->req.upload_chunky) {
-          /* We're not sending it 'chunked', append it to the request
-             already now to reduce the number of send() calls */
-          result = Curl_dyn_addn(r, data->set.postfields,
-                                 (size_t)http->postsize);
-          included_body = http->postsize;
-        }
-        else {
-          if(http->postsize) {
-            char chunk[16];
-            /* Append the POST data chunky-style */
-            msnprintf(chunk, sizeof(chunk), "%x\r\n", (int)http->postsize);
-            result = Curl_dyn_add(r, chunk);
-            if(!result) {
-              included_body = http->postsize + strlen(chunk);
-              result = Curl_dyn_addn(r, data->set.postfields,
-                                     (size_t)http->postsize);
-              if(!result)
-                result = Curl_dyn_addn(r, STRCONST("\r\n"));
-              included_body += 2;
-            }
-          }
-          if(!result) {
-            result = Curl_dyn_addn(r, STRCONST("\x30\x0d\x0a\x0d\x0a"));
-            /* 0  CR  LF  CR  LF */
-            included_body += 5;
-          }
-        }
-        if(result)
-          return result;
-        /* Make sure the progress information is accurate */
-        Curl_pgrsSetUploadSize(data, http->postsize);
-      }
-      else {
-        /* A huge POST coming up, do data separate from the request */
-        http->postdata = data->set.postfields;
-        http->sending = HTTPSEND_BODY;
-        http->backup.data = data;
-        data->state.fread_func = (curl_read_callback)readmoredata;
-        data->state.in = (void *)http;
-
-        /* set the upload size to the progress meter */
-        Curl_pgrsSetUploadSize(data, http->postsize);
-
-        /* end of headers! */
-        result = Curl_dyn_addn(r, STRCONST("\r\n"));
-        if(result)
-          return result;
+          goto out;
       }
     }
-    else
 #endif
-    {
-       /* end of headers! */
-      result = Curl_dyn_addn(r, STRCONST("\r\n"));
-      if(result)
-        return result;
-
-      if(data->req.upload_chunky && conn->bits.authneg) {
-        /* Chunky upload is selected and we're negotiating auth still, send
-           end-of-data only */
-        result = Curl_dyn_addn(r, (char *)STRCONST("\x30\x0d\x0a\x0d\x0a"));
-        /* 0  CR  LF  CR  LF */
+    if(httpreq == HTTPREQ_POST) {
+      if(!Curl_checkheaders(data, STRCONST("Content-Type"))) {
+        result = Curl_dyn_addn(r, STRCONST("Content-Type: application/"
+                                           "x-www-form-urlencoded\r\n"));
         if(result)
-          return result;
-      }
-
-      else if(data->state.infilesize) {
-        /* set the upload size to the progress meter */
-        Curl_pgrsSetUploadSize(data, http->postsize?http->postsize:-1);
-
-        /* set the pointer to mark that we will send the post body using the
-           read callback, but only if we're not in authenticate negotiation */
-        if(!conn->bits.authneg)
-          http->postdata = (char *)&http->postdata;
+          goto out;
       }
     }
-    /* issue the request */
-    result = Curl_buffer_send(r, data, data->req.p.http,
-                              &data->info.request_size, included_body,
-                              FIRSTSOCKET);
-
+    result = addexpect(data, r, &announced_exp100);
     if(result)
-      failf(data, "Failed sending HTTP POST request");
-    else
-      Curl_setup_transfer(data, FIRSTSOCKET, -1, TRUE,
-                          http->postdata?FIRSTSOCKET:-1);
+      goto out;
     break;
-
   default:
-    result = Curl_dyn_addn(r, STRCONST("\r\n"));
-    if(result)
-      return result;
+    break;
+  }
 
-    /* issue the request */
-    result = Curl_buffer_send(r, data, data->req.p.http,
-                              &data->info.request_size, 0,
-                              FIRSTSOCKET);
-    if(result)
-      failf(data, "Failed sending HTTP request");
-#ifdef USE_WEBSOCKETS
-    else if((conn->handler->protocol & (CURLPROTO_WS|CURLPROTO_WSS)) &&
-            !(data->set.connect_only))
-      /* Set up the transfer for two-way since without CONNECT_ONLY set, this
-         request probably wants to send data too post upgrade */
-      Curl_setup_transfer(data, FIRSTSOCKET, -1, TRUE, FIRSTSOCKET);
-#endif
-    else
-      /* HTTP GET/HEAD download: */
-      Curl_setup_transfer(data, FIRSTSOCKET, -1, TRUE, -1);
+  /* end of headers */
+  result = Curl_dyn_addn(r, STRCONST("\r\n"));
+  if(!result) {
+    Curl_pgrsSetUploadSize(data, req_clen);
+    if(announced_exp100)
+      result = http_exp100_add_reader(data);
   }
 
+out:
+  if(!result) {
+    /* setup variables for the upcoming transfer */
+    Curl_xfer_setup(data, FIRSTSOCKET, -1, TRUE, FIRSTSOCKET);
+  }
   return result;
 }
 
@@ -2939,7 +2348,7 @@ CURLcode Curl_http_range(struct Curl_easy *data,
     }
     else if((httpreq == HTTPREQ_POST || httpreq == HTTPREQ_PUT) &&
             !Curl_checkheaders(data, STRCONST("Content-Range"))) {
-
+      curl_off_t req_clen = Curl_creader_total_length(data);
       /* if a line like this was already allocated, free the previous one */
       free(data->state.aptr.rangeline);
 
@@ -2950,25 +2359,28 @@ CURLcode Curl_http_range(struct Curl_easy *data,
         data->state.aptr.rangeline =
           aprintf("Content-Range: bytes 0-%" CURL_FORMAT_CURL_OFF_T
                   "/%" CURL_FORMAT_CURL_OFF_T "\r\n",
-                  data->state.infilesize - 1, data->state.infilesize);
+                  req_clen - 1, req_clen);
 
       }
       else if(data->state.resume_from) {
         /* This is because "resume" was selected */
-        curl_off_t total_expected_size =
-          data->state.resume_from + data->state.infilesize;
+        /* TODO: not sure if we want to send this header during authentication
+         * negotiation, but test1084 checks for it. In which case we have a
+         * "null" client reader installed that gives an unexpected length. */
+        curl_off_t total_len = data->req.authneg?
+                               data->state.infilesize :
+                               (data->state.resume_from + req_clen);
         data->state.aptr.rangeline =
           aprintf("Content-Range: bytes %s%" CURL_FORMAT_CURL_OFF_T
                   "/%" CURL_FORMAT_CURL_OFF_T "\r\n",
-                  data->state.range, total_expected_size-1,
-                  total_expected_size);
+                  data->state.range, total_len-1, total_len);
       }
       else {
         /* Range was selected and then we just pass the incoming range and
            append total size */
         data->state.aptr.rangeline =
           aprintf("Content-Range: bytes %s/%" CURL_FORMAT_CURL_OFF_T "\r\n",
-                  data->state.range, data->state.infilesize);
+                  data->state.range, req_clen);
       }
       if(!data->state.aptr.rangeline)
         return CURLE_OUT_OF_MEMORY;
@@ -2977,98 +2389,17 @@ CURLcode Curl_http_range(struct Curl_easy *data,
   return CURLE_OK;
 }
 
-CURLcode Curl_http_resume(struct Curl_easy *data,
-                          struct connectdata *conn,
-                          Curl_HttpReq httpreq)
+CURLcode Curl_http_firstwrite(struct Curl_easy *data)
 {
-  if((HTTPREQ_POST == httpreq || HTTPREQ_PUT == httpreq) &&
-     data->state.resume_from) {
-    /**********************************************************************
-     * Resuming upload in HTTP means that we PUT or POST and that we have
-     * got a resume_from value set. The resume value has already created
-     * a Range: header that will be passed along. We need to "fast forward"
-     * the file the given number of bytes and decrease the assume upload
-     * file size before we continue this venture in the dark lands of HTTP.
-     * Resuming mime/form posting at an offset > 0 has no sense and is ignored.
-     *********************************************************************/
-
-    if(data->state.resume_from < 0) {
-      /*
-       * This is meant to get the size of the present remote-file by itself.
-       * We don't support this now. Bail out!
-       */
-      data->state.resume_from = 0;
-    }
-
-    if(data->state.resume_from && !data->state.followlocation) {
-      /* only act on the first request */
-
-      /* Now, let's read off the proper amount of bytes from the
-         input. */
-      int seekerr = CURL_SEEKFUNC_CANTSEEK;
-      if(conn->seek_func) {
-        Curl_set_in_callback(data, true);
-        seekerr = conn->seek_func(conn->seek_client, data->state.resume_from,
-                                  SEEK_SET);
-        Curl_set_in_callback(data, false);
-      }
-
-      if(seekerr != CURL_SEEKFUNC_OK) {
-        curl_off_t passed = 0;
-
-        if(seekerr != CURL_SEEKFUNC_CANTSEEK) {
-          failf(data, "Could not seek stream");
-          return CURLE_READ_ERROR;
-        }
-        /* when seekerr == CURL_SEEKFUNC_CANTSEEK (can't seek to offset) */
-        do {
-          size_t readthisamountnow =
-            (data->state.resume_from - passed > data->set.buffer_size) ?
-            (size_t)data->set.buffer_size :
-            curlx_sotouz(data->state.resume_from - passed);
-
-          size_t actuallyread =
-            data->state.fread_func(data->state.buffer, 1, readthisamountnow,
-                                   data->state.in);
-
-          passed += actuallyread;
-          if((actuallyread == 0) || (actuallyread > readthisamountnow)) {
-            /* this checks for greater-than only to make sure that the
-               CURL_READFUNC_ABORT return code still aborts */
-            failf(data, "Could only read %" CURL_FORMAT_CURL_OFF_T
-                  " bytes from the input", passed);
-            return CURLE_READ_ERROR;
-          }
-        } while(passed < data->state.resume_from);
-      }
-
-      /* now, decrease the size of the read */
-      if(data->state.infilesize>0) {
-        data->state.infilesize -= data->state.resume_from;
-
-        if(data->state.infilesize <= 0) {
-          failf(data, "File already completely uploaded");
-          return CURLE_PARTIAL_FILE;
-        }
-      }
-      /* we've passed, proceed as normal */
-    }
-  }
-  return CURLE_OK;
-}
-
-CURLcode Curl_http_firstwrite(struct Curl_easy *data,
-                              struct connectdata *conn,
-                              bool *done)
-{
-  struct SingleRequest *k = &data->req;
+  struct connectdata *conn = data->conn;
+  struct SingleRequest *k = &data->req;
 
   if(data->req.newurl) {
     if(conn->bits.close) {
       /* Abort after the headers if "follow Location" is set
          and we're set to close anyway. */
       k->keepon &= ~KEEP_RECV;
-      *done = TRUE;
+      k->done = TRUE;
       return CURLE_OK;
     }
     /* We have a new url to load, but since we want to be able to reuse this
@@ -3087,7 +2418,7 @@ CURLcode Curl_http_firstwrite(struct Curl_easy *data,
       streamclose(conn, "already downloaded");
       /* Abort download */
       k->keepon &= ~KEEP_RECV;
-      *done = TRUE;
+      k->done = TRUE;
       return CURLE_OK;
     }
 
@@ -3105,7 +2436,7 @@ CURLcode Curl_http_firstwrite(struct Curl_easy *data,
        action for an HTTP/1.1 client */
 
     if(!Curl_meets_timecondition(data, k->timeofdoc)) {
-      *done = TRUE;
+      k->done = TRUE;
       /* We're simulating an HTTP 304 from server so we return
          what should have been returned from the server */
       data->info.httpcode = 304;
@@ -3163,7 +2494,6 @@ CURLcode Curl_http(struct Curl_easy *data, bool *done)
 {
   struct connectdata *conn = data->conn;
   CURLcode result = CURLE_OK;
-  struct HTTP *http;
   Curl_HttpReq httpreq;
   const char *te = ""; /* transfer-encoding */
   const char *request;
@@ -3188,14 +2518,14 @@ CURLcode Curl_http(struct Curl_easy *data, bool *done)
       ) {
       result = Curl_http2_switch(data, conn, FIRSTSOCKET);
       if(result)
-        return result;
+        goto fail;
     }
     else
 #endif
       DEBUGASSERT(Curl_conn_is_http2(data, conn, FIRSTSOCKET));
     break;
   case CURL_HTTP_VERSION_1_1:
-    /* continue with HTTP/1.1 when explicitly requested */
+    /* continue with HTTP/1.x when explicitly requested */
     break;
   default:
     /* Check if user wants to use HTTP/2 with clear TCP */
@@ -3203,21 +2533,25 @@ CURLcode Curl_http(struct Curl_easy *data, bool *done)
       DEBUGF(infof(data, "HTTP/2 over clean TCP"));
       result = Curl_http2_switch(data, conn, FIRSTSOCKET);
       if(result)
-        return result;
+        goto fail;
     }
     break;
   }
 
-  http = data->req.p.http;
-  DEBUGASSERT(http);
+  /* Add collecting of headers written to client. For a new connection,
+   * we might have done that already, but reuse
+   * or multiplex needs it here as well. */
+  result = Curl_headers_init(data);
+  if(result)
+    goto fail;
 
   result = Curl_http_host(data, conn);
   if(result)
-    return result;
+    goto fail;
 
   result = Curl_http_useragent(data);
   if(result)
-    return result;
+    goto fail;
 
   Curl_http_method(data, conn, &request, &httpreq);
 
@@ -3233,7 +2567,7 @@ CURLcode Curl_http(struct Curl_easy *data, bool *done)
                                    (pq ? pq : data->state.up.path), FALSE);
     free(pq);
     if(result)
-      return result;
+      goto fail;
   }
 
   Curl_safefree(data->state.aptr.ref);
@@ -3258,23 +2592,19 @@ CURLcode Curl_http(struct Curl_easy *data, bool *done)
   /* we only consider transfer-encoding magic if libz support is built-in */
   result = Curl_transferencode(data);
   if(result)
-    return result;
+    goto fail;
 #endif
 
-  result = Curl_http_body(data, conn, httpreq, &te);
+  result = Curl_http_req_set_reader(data, httpreq, &te);
   if(result)
-    return result;
+    goto fail;
 
   p_accept = Curl_checkheaders(data,
                                STRCONST("Accept"))?NULL:"Accept: */*\r\n";
 
-  result = Curl_http_resume(data, conn, httpreq);
-  if(result)
-    return result;
-
   result = Curl_http_range(data, httpreq);
   if(result)
-    return result;
+    goto fail;
 
   httpstring = get_http_string(data, conn);
 
@@ -3292,7 +2622,7 @@ CURLcode Curl_http(struct Curl_easy *data, bool *done)
     result = Curl_http_target(data, conn, &req);
   if(result) {
     Curl_dyn_free(&req);
-    return result;
+    goto fail;
   }
 
 #ifndef CURL_DISABLE_ALTSVC
@@ -3323,8 +2653,12 @@ CURLcode Curl_http(struct Curl_easy *data, bool *done)
 
                   httpstring,
                   (data->state.aptr.host?data->state.aptr.host:""),
+#ifndef CURL_DISABLE_PROXY
                   data->state.aptr.proxyuserpwd?
                   data->state.aptr.proxyuserpwd:"",
+#else
+                  "",
+#endif
                   data->state.aptr.userpwd?data->state.aptr.userpwd:"",
                   (data->state.use_range && data->state.aptr.rangeline)?
                   data->state.aptr.rangeline:"",
@@ -3358,12 +2692,14 @@ CURLcode Curl_http(struct Curl_easy *data, bool *done)
   /* clear userpwd and proxyuserpwd to avoid reusing old credentials
    * from reused connections */
   Curl_safefree(data->state.aptr.userpwd);
+#ifndef CURL_DISABLE_PROXY
   Curl_safefree(data->state.aptr.proxyuserpwd);
+#endif
   free(altused);
 
   if(result) {
     Curl_dyn_free(&req);
-    return result;
+    goto fail;
   }
 
   if(!(conn->handler->flags&PROTOPT_SSL) &&
@@ -3389,52 +2725,23 @@ CURLcode Curl_http(struct Curl_easy *data, bool *done)
     result = Curl_add_custom_headers(data, FALSE, &req);
 
   if(!result) {
-    http->postdata = NULL;  /* nothing to post at this point */
-    if((httpreq == HTTPREQ_GET) ||
-       (httpreq == HTTPREQ_HEAD))
-      Curl_pgrsSetUploadSize(data, 0); /* nothing */
-
-    /* bodysend takes ownership of the 'req' memory on success */
-    result = Curl_http_bodysend(data, conn, &req, httpreq);
-  }
-  if(result) {
-    Curl_dyn_free(&req);
-    return result;
-  }
-
-  if((http->postsize > -1) &&
-     (http->postsize <= data->req.writebytecount) &&
-     (http->sending != HTTPSEND_REQUEST))
-    data->req.upload_done = TRUE;
-
-  if(data->req.writebytecount) {
-    /* if a request-body has been sent off, we make sure this progress is noted
-       properly */
-    Curl_pgrsSetUploadCounter(data, data->req.writebytecount);
-    if(Curl_pgrsUpdate(data))
-      result = CURLE_ABORTED_BY_CALLBACK;
-
-    if(!http->postsize) {
-      /* already sent the entire request body, mark the "upload" as
-         complete */
-      infof(data, "upload completely sent off: %" CURL_FORMAT_CURL_OFF_T
-            " out of %" CURL_FORMAT_CURL_OFF_T " bytes",
-            data->req.writebytecount, http->postsize);
-      data->req.upload_done = TRUE;
-      data->req.keepon &= ~KEEP_SEND; /* we're done writing */
-      data->req.exp100 = EXP100_SEND_DATA; /* already sent */
-      Curl_expire_done(data, EXPIRE_100_TIMEOUT);
-    }
+    /* req_send takes ownership of the 'req' memory on success */
+    result = Curl_http_req_complete(data, &req, httpreq);
+    if(!result)
+      result = Curl_req_send(data, &req);
   }
-
-  if(data->req.upload_done)
-    Curl_conn_ev_data_done_send(data);
+  Curl_dyn_free(&req);
+  if(result)
+    goto fail;
 
   if((conn->httpversion >= 20) && data->req.upload_chunky)
     /* upload_chunky was set above to set up the request in a chunky fashion,
        but is disabled here again to avoid that the chunked encoded version is
        actually used when sending the request body over h2 */
     data->req.upload_chunky = FALSE;
+fail:
+  if(CURLE_TOO_LARGE == result)
+    failf(data, "HTTP request too large");
   return result;
 }
 
@@ -3510,325 +2817,373 @@ checkprotoprefix(struct Curl_easy *data, struct connectdata *conn,
   return checkhttpprefix(data, s, len);
 }
 
+/* HTTP header has field name `n` (a string constant) */
+#define HD_IS(hd, hdlen, n) \
+  (((hdlen) >= (sizeof(n)-1)) && curl_strnequal((n), (hd), (sizeof(n)-1)))
+
+#define HD_VAL(hd, hdlen, n) \
+  ((((hdlen) >= (sizeof(n)-1)) && \
+    curl_strnequal((n), (hd), (sizeof(n)-1)))? (hd + (sizeof(n)-1)) : NULL)
+
+/* HTTP header has field name `n` (a string constant) and contains `v`
+ * (a string constant) in its value(s) */
+#define HD_IS_AND_SAYS(hd, hdlen, n, v) \
+  (HD_IS(hd, hdlen, n) && \
+   ((hdlen) > ((sizeof(n)-1) + (sizeof(v)-1))) && \
+   Curl_compareheader(hd, STRCONST(n), STRCONST(v)))
+
 /*
  * Curl_http_header() parses a single response header.
  */
-CURLcode Curl_http_header(struct Curl_easy *data, struct connectdata *conn,
-                          char *headp)
+CURLcode Curl_http_header(struct Curl_easy *data,
+                          const char *hd, size_t hdlen)
 {
+  struct connectdata *conn = data->conn;
   CURLcode result;
   struct SingleRequest *k = &data->req;
-  /* Check for Content-Length: header lines to get size */
-  if(!k->http_bodyless &&
-     !data->set.ignorecl && checkprefix("Content-Length:", headp)) {
-    curl_off_t contentlength;
-    CURLofft offt = curlx_strtoofft(headp + strlen("Content-Length:"),
-                                    NULL, 10, &contentlength);
-
-    if(offt == CURL_OFFT_OK) {
-      k->size = contentlength;
-      k->maxdownload = k->size;
+  const char *v;
+
+  switch(hd[0]) {
+  case 'a':
+  case 'A':
+#ifndef CURL_DISABLE_ALTSVC
+    v = (data->asi &&
+         ((data->conn->handler->flags & PROTOPT_SSL) ||
+#ifdef CURLDEBUG
+          /* allow debug builds to circumvent the HTTPS restriction */
+          getenv("CURL_ALTSVC_HTTP")
+#else
+          0
+#endif
+        ))? HD_VAL(hd, hdlen, "Alt-Svc:") : NULL;
+    if(v) {
+      /* the ALPN of the current request */
+      enum alpnid id = (conn->httpversion == 30)? ALPN_h3 :
+                         (conn->httpversion == 20) ? ALPN_h2 : ALPN_h1;
+      return Curl_altsvc_parse(data, data->asi, v, id, conn->host.name,
+                               curlx_uitous((unsigned int)conn->remote_port));
     }
-    else if(offt == CURL_OFFT_FLOW) {
-      /* out of range */
-      if(data->set.max_filesize) {
-        failf(data, "Maximum file size exceeded");
-        return CURLE_FILESIZE_EXCEEDED;
+#endif
+    break;
+  case 'c':
+  case 'C':
+    /* Check for Content-Length: header lines to get size */
+    v = (!k->http_bodyless && !data->set.ignorecl)?
+        HD_VAL(hd, hdlen, "Content-Length:") : NULL;
+    if(v) {
+      curl_off_t contentlength;
+      CURLofft offt = curlx_strtoofft(v, NULL, 10, &contentlength);
+
+      if(offt == CURL_OFFT_OK) {
+        k->size = contentlength;
+        k->maxdownload = k->size;
+      }
+      else if(offt == CURL_OFFT_FLOW) {
+        /* out of range */
+        if(data->set.max_filesize) {
+          failf(data, "Maximum file size exceeded");
+          return CURLE_FILESIZE_EXCEEDED;
+        }
+        streamclose(conn, "overflow content-length");
+        infof(data, "Overflow Content-Length: value");
+      }
+      else {
+        /* negative or just rubbish - bad HTTP */
+        failf(data, "Invalid Content-Length: value");
+        return CURLE_WEIRD_SERVER_REPLY;
       }
-      streamclose(conn, "overflow content-length");
-      infof(data, "Overflow Content-Length: value");
+      return CURLE_OK;
     }
-    else {
-      /* negative or just rubbish - bad HTTP */
-      failf(data, "Invalid Content-Length: value");
-      return CURLE_WEIRD_SERVER_REPLY;
+    v = (!k->http_bodyless && data->set.str[STRING_ENCODING])?
+        HD_VAL(hd, hdlen, "Content-Encoding:") : NULL;
+    if(v) {
+      /*
+       * Process Content-Encoding. Look for the values: identity,
+       * gzip, deflate, compress, x-gzip and x-compress. x-gzip and
+       * x-compress are the same as gzip and compress. (Sec 3.5 RFC
+       * 2616). zlib cannot handle compress.  However, errors are
+       * handled further down when the response body is processed
+       */
+      return Curl_build_unencoding_stack(data, v, FALSE);
     }
-  }
-  /* check for Content-Type: header lines to get the MIME-type */
-  else if(checkprefix("Content-Type:", headp)) {
-    char *contenttype = Curl_copy_header_value(headp);
-    if(!contenttype)
-      return CURLE_OUT_OF_MEMORY;
-    if(!*contenttype)
-      /* ignore empty data */
-      free(contenttype);
-    else {
-      Curl_safefree(data->info.contenttype);
-      data->info.contenttype = contenttype;
+    /* check for Content-Type: header lines to get the MIME-type */
+    v = HD_VAL(hd, hdlen, "Content-Type:");
+    if(v) {
+      char *contenttype = Curl_copy_header_value(hd);
+      if(!contenttype)
+        return CURLE_OUT_OF_MEMORY;
+      if(!*contenttype)
+        /* ignore empty data */
+        free(contenttype);
+      else {
+        Curl_safefree(data->info.contenttype);
+        data->info.contenttype = contenttype;
+      }
+      return CURLE_OK;
     }
-  }
-#ifndef CURL_DISABLE_PROXY
-  else if((conn->httpversion == 10) &&
-          conn->bits.httpproxy &&
-          Curl_compareheader(headp,
-                             STRCONST("Proxy-Connection:"),
-                             STRCONST("keep-alive"))) {
-    /*
-     * When an HTTP/1.0 reply comes when using a proxy, the
-     * 'Proxy-Connection: keep-alive' line tells us the
-     * connection will be kept alive for our pleasure.
-     * Default action for 1.0 is to close.
-     */
-    connkeep(conn, "Proxy-Connection keep-alive"); /* don't close */
-    infof(data, "HTTP/1.0 proxy connection set to keep alive");
-  }
-  else if((conn->httpversion == 11) &&
-          conn->bits.httpproxy &&
-          Curl_compareheader(headp,
-                             STRCONST("Proxy-Connection:"),
-                             STRCONST("close"))) {
-    /*
-     * We get an HTTP/1.1 response from a proxy and it says it'll
-     * close down after this transfer.
-     */
-    connclose(conn, "Proxy-Connection: asked to close after done");
-    infof(data, "HTTP/1.1 proxy connection set close");
-  }
-#endif
-  else if((conn->httpversion == 10) &&
-          Curl_compareheader(headp,
-                             STRCONST("Connection:"),
-                             STRCONST("keep-alive"))) {
-    /*
-     * An HTTP/1.0 reply with the 'Connection: keep-alive' line
-     * tells us the connection will be kept alive for our
-     * pleasure.  Default action for 1.0 is to close.
-     *
-     * [RFC2068, section 19.7.1] */
-    connkeep(conn, "Connection keep-alive");
-    infof(data, "HTTP/1.0 connection set to keep alive");
-  }
-  else if(Curl_compareheader(headp,
-                             STRCONST("Connection:"), STRCONST("close"))) {
-    /*
-     * [RFC 2616, section 8.1.2.1]
-     * "Connection: close" is HTTP/1.1 language and means that
-     * the connection will close when this request has been
-     * served.
-     */
-    streamclose(conn, "Connection: close used");
-  }
-  else if(!k->http_bodyless && checkprefix("Transfer-Encoding:", headp)) {
-    /* One or more encodings. We check for chunked and/or a compression
-       algorithm. */
-    /*
-     * [RFC 2616, section 3.6.1] A 'chunked' transfer encoding
-     * means that the server will send a series of "chunks". Each
-     * chunk starts with line with info (including size of the
-     * coming block) (terminated with CRLF), then a block of data
-     * with the previously mentioned size. There can be any amount
-     * of chunks, and a chunk-data set to zero signals the
-     * end-of-chunks. */
-
-    result = Curl_build_unencoding_stack(data,
-                                         headp + strlen("Transfer-Encoding:"),
-                                         TRUE);
-    if(result)
-      return result;
-    if(!k->chunk && data->set.http_transfer_encoding) {
-      /* if this isn't chunked, only close can signal the end of this transfer
-         as Content-Length is said not to be trusted for transfer-encoding! */
-      connclose(conn, "HTTP/1.1 transfer-encoding without chunks");
-      k->ignore_cl = TRUE;
+    if(HD_IS_AND_SAYS(hd, hdlen, "Connection:", "close")) {
+      /*
+       * [RFC 2616, section 8.1.2.1]
+       * "Connection: close" is HTTP/1.1 language and means that
+       * the connection will close when this request has been
+       * served.
+       */
+      streamclose(conn, "Connection: close used");
+      return CURLE_OK;
     }
-  }
-  else if(!k->http_bodyless && checkprefix("Content-Encoding:", headp) &&
-          data->set.str[STRING_ENCODING]) {
-    /*
-     * Process Content-Encoding. Look for the values: identity,
-     * gzip, deflate, compress, x-gzip and x-compress. x-gzip and
-     * x-compress are the same as gzip and compress. (Sec 3.5 RFC
-     * 2616). zlib cannot handle compress.  However, errors are
-     * handled further down when the response body is processed
-     */
-    result = Curl_build_unencoding_stack(data,
-                                         headp + strlen("Content-Encoding:"),
-                                         FALSE);
-    if(result)
-      return result;
-  }
-  else if(checkprefix("Retry-After:", headp)) {
-    /* Retry-After = HTTP-date / delay-seconds */
-    curl_off_t retry_after = 0; /* zero for unknown or "now" */
-    /* Try it as a decimal number, if it works it is not a date */
-    (void)curlx_strtoofft(headp + strlen("Retry-After:"),
-                          NULL, 10, &retry_after);
-    if(!retry_after) {
-      time_t date = Curl_getdate_capped(headp + strlen("Retry-After:"));
-      if(-1 != date)
-        /* convert date to number of seconds into the future */
-        retry_after = date - time(NULL);
+    if((conn->httpversion == 10) &&
+       HD_IS_AND_SAYS(hd, hdlen, "Connection:", "keep-alive")) {
+      /*
+       * An HTTP/1.0 reply with the 'Connection: keep-alive' line
+       * tells us the connection will be kept alive for our
+       * pleasure.  Default action for 1.0 is to close.
+       *
+       * [RFC2068, section 19.7.1] */
+      connkeep(conn, "Connection keep-alive");
+      infof(data, "HTTP/1.0 connection set to keep alive");
+      return CURLE_OK;
     }
-    data->info.retry_after = retry_after; /* store it */
-  }
-  else if(!k->http_bodyless && checkprefix("Content-Range:", headp)) {
-    /* Content-Range: bytes [num]-
-       Content-Range: bytes: [num]-
-       Content-Range: [num]-
-       Content-Range: [asterisk]/[total]
-
-       The second format was added since Sun's webserver
-       JavaWebServer/1.1.1 obviously sends the header this way!
-       The third added since some servers use that!
-       The fourth means the requested range was unsatisfied.
-    */
-
-    char *ptr = headp + strlen("Content-Range:");
-
-    /* Move forward until first digit or asterisk */
-    while(*ptr && !ISDIGIT(*ptr) && *ptr != '*')
-      ptr++;
-
-    /* if it truly stopped on a digit */
-    if(ISDIGIT(*ptr)) {
-      if(!curlx_strtoofft(ptr, NULL, 10, &k->offset)) {
-        if(data->state.resume_from == k->offset)
-          /* we asked for a resume and we got it */
-          k->content_range = TRUE;
+    v = !k->http_bodyless? HD_VAL(hd, hdlen, "Content-Range:") : NULL;
+    if(v) {
+      /* Content-Range: bytes [num]-
+         Content-Range: bytes: [num]-
+         Content-Range: [num]-
+         Content-Range: [asterisk]/[total]
+
+         The second format was added since Sun's webserver
+         JavaWebServer/1.1.1 obviously sends the header this way!
+         The third added since some servers use that!
+         The fourth means the requested range was unsatisfied.
+      */
+
+      const char *ptr = v;
+
+      /* Move forward until first digit or asterisk */
+      while(*ptr && !ISDIGIT(*ptr) && *ptr != '*')
+        ptr++;
+
+      /* if it truly stopped on a digit */
+      if(ISDIGIT(*ptr)) {
+        if(!curlx_strtoofft(ptr, NULL, 10, &k->offset)) {
+          if(data->state.resume_from == k->offset)
+            /* we asked for a resume and we got it */
+            k->content_range = TRUE;
+        }
       }
+      else if(k->httpcode < 300)
+        data->state.resume_from = 0; /* get everything */
     }
-    else
-      data->state.resume_from = 0; /* get everything */
-  }
-#if !defined(CURL_DISABLE_COOKIES)
-  else if(data->cookies && data->state.cookie_engine &&
-          checkprefix("Set-Cookie:", headp)) {
-    /* If there is a custom-set Host: name, use it here, or else use real peer
-       host name. */
-    const char *host = data->state.aptr.cookiehost?
-      data->state.aptr.cookiehost:conn->host.name;
-    const bool secure_context =
-      conn->handler->protocol&(CURLPROTO_HTTPS|CURLPROTO_WSS) ||
-      strcasecompare("localhost", host) ||
-      !strcmp(host, "127.0.0.1") ||
-      !strcmp(host, "::1") ? TRUE : FALSE;
-
-    Curl_share_lock(data, CURL_LOCK_DATA_COOKIE,
-                    CURL_LOCK_ACCESS_SINGLE);
-    Curl_cookie_add(data, data->cookies, TRUE, FALSE,
-                    headp + strlen("Set-Cookie:"), host,
-                    data->state.up.path, secure_context);
-    Curl_share_unlock(data, CURL_LOCK_DATA_COOKIE);
-  }
-#endif
-  else if(!k->http_bodyless && checkprefix("Last-Modified:", headp) &&
-          (data->set.timecondition || data->set.get_filetime) ) {
-    k->timeofdoc = Curl_getdate_capped(headp + strlen("Last-Modified:"));
-    if(data->set.get_filetime)
-      data->info.filetime = k->timeofdoc;
-  }
-  else if((checkprefix("WWW-Authenticate:", headp) &&
-           (401 == k->httpcode)) ||
-          (checkprefix("Proxy-authenticate:", headp) &&
-           (407 == k->httpcode))) {
-
-    bool proxy = (k->httpcode == 407) ? TRUE : FALSE;
-    char *auth = Curl_copy_header_value(headp);
-    if(!auth)
-      return CURLE_OUT_OF_MEMORY;
+    break;
+  case 'l':
+  case 'L':
+    v = (!k->http_bodyless &&
+         (data->set.timecondition || data->set.get_filetime))?
+        HD_VAL(hd, hdlen, "Last-Modified:") : NULL;
+    if(v) {
+      k->timeofdoc = Curl_getdate_capped(v);
+      if(data->set.get_filetime)
+        data->info.filetime = k->timeofdoc;
+      return CURLE_OK;
+    }
+    if((k->httpcode >= 300 && k->httpcode < 400) &&
+            HD_IS(hd, hdlen, "Location:") &&
+            !data->req.location) {
+      /* this is the URL that the server advises us to use instead */
+      char *location = Curl_copy_header_value(hd);
+      if(!location)
+        return CURLE_OUT_OF_MEMORY;
+      if(!*location)
+        /* ignore empty data */
+        free(location);
+      else {
+        data->req.location = location;
 
-    result = Curl_http_input_auth(data, proxy, auth);
+        if(data->set.http_follow_location) {
+          DEBUGASSERT(!data->req.newurl);
+          data->req.newurl = strdup(data->req.location); /* clone */
+          if(!data->req.newurl)
+            return CURLE_OUT_OF_MEMORY;
 
-    free(auth);
+          /* some cases of POST and PUT etc needs to rewind the data
+             stream at this point */
+          result = http_perhapsrewind(data, conn);
+          if(result)
+            return result;
 
-    if(result)
+          /* mark the next request as a followed location: */
+          data->state.this_is_a_follow = TRUE;
+        }
+      }
+    }
+    break;
+  case 'p':
+  case 'P':
+#ifndef CURL_DISABLE_PROXY
+    v = HD_VAL(hd, hdlen, "Proxy-Connection:");
+    if(v) {
+      if((conn->httpversion == 10) && conn->bits.httpproxy &&
+         HD_IS_AND_SAYS(hd, hdlen, "Proxy-Connection:", "keep-alive")) {
+        /*
+         * When an HTTP/1.0 reply comes when using a proxy, the
+         * 'Proxy-Connection: keep-alive' line tells us the
+         * connection will be kept alive for our pleasure.
+         * Default action for 1.0 is to close.
+         */
+        connkeep(conn, "Proxy-Connection keep-alive"); /* don't close */
+        infof(data, "HTTP/1.0 proxy connection set to keep alive");
+      }
+      else if((conn->httpversion == 11) && conn->bits.httpproxy &&
+              HD_IS_AND_SAYS(hd, hdlen, "Proxy-Connection:", "close")) {
+        /*
+         * We get an HTTP/1.1 response from a proxy and it says it'll
+         * close down after this transfer.
+         */
+        connclose(conn, "Proxy-Connection: asked to close after done");
+        infof(data, "HTTP/1.1 proxy connection set close");
+      }
+      return CURLE_OK;
+    }
+#endif
+    if((407 == k->httpcode) && HD_IS(hd, hdlen, "Proxy-authenticate:")) {
+      char *auth = Curl_copy_header_value(hd);
+      if(!auth)
+        return CURLE_OUT_OF_MEMORY;
+      result = Curl_http_input_auth(data, TRUE, auth);
+      free(auth);
       return result;
-  }
+    }
 #ifdef USE_SPNEGO
-  else if(checkprefix("Persistent-Auth:", headp)) {
-    struct negotiatedata *negdata = &conn->negotiate;
-    struct auth *authp = &data->state.authhost;
-    if(authp->picked == CURLAUTH_NEGOTIATE) {
-      char *persistentauth = Curl_copy_header_value(headp);
-      if(!persistentauth)
-        return CURLE_OUT_OF_MEMORY;
-      negdata->noauthpersist = checkprefix("false", persistentauth)?
-        TRUE:FALSE;
-      negdata->havenoauthpersist = TRUE;
-      infof(data, "Negotiate: noauthpersist -> %d, header part: %s",
-            negdata->noauthpersist, persistentauth);
-      free(persistentauth);
+    if(HD_IS(hd, hdlen, "Persistent-Auth:")) {
+      struct negotiatedata *negdata = &conn->negotiate;
+      struct auth *authp = &data->state.authhost;
+      if(authp->picked == CURLAUTH_NEGOTIATE) {
+        char *persistentauth = Curl_copy_header_value(hd);
+        if(!persistentauth)
+          return CURLE_OUT_OF_MEMORY;
+        negdata->noauthpersist = checkprefix("false", persistentauth)?
+          TRUE:FALSE;
+        negdata->havenoauthpersist = TRUE;
+        infof(data, "Negotiate: noauthpersist -> %d, header part: %s",
+              negdata->noauthpersist, persistentauth);
+        free(persistentauth);
+      }
     }
-  }
 #endif
-  else if((k->httpcode >= 300 && k->httpcode < 400) &&
-          checkprefix("Location:", headp) &&
-          !data->req.location) {
-    /* this is the URL that the server advises us to use instead */
-    char *location = Curl_copy_header_value(headp);
-    if(!location)
-      return CURLE_OUT_OF_MEMORY;
-    if(!*location)
-      /* ignore empty data */
-      free(location);
-    else {
-      data->req.location = location;
-
-      if(data->set.http_follow_location) {
-        DEBUGASSERT(!data->req.newurl);
-        data->req.newurl = strdup(data->req.location); /* clone */
-        if(!data->req.newurl)
-          return CURLE_OUT_OF_MEMORY;
-
-        /* some cases of POST and PUT etc needs to rewind the data
-           stream at this point */
-        result = http_perhapsrewind(data, conn);
-        if(result)
-          return result;
-
-        /* mark the next request as a followed location: */
-        data->state.this_is_a_follow = TRUE;
+    break;
+  case 'r':
+  case 'R':
+    v = HD_VAL(hd, hdlen, "Retry-After:");
+    if(v) {
+      /* Retry-After = HTTP-date / delay-seconds */
+      curl_off_t retry_after = 0; /* zero for unknown or "now" */
+      /* Try it as a decimal number, if it works it is not a date */
+      (void)curlx_strtoofft(v, NULL, 10, &retry_after);
+      if(!retry_after) {
+        time_t date = Curl_getdate_capped(v);
+        if(-1 != date)
+          /* convert date to number of seconds into the future */
+          retry_after = date - time(NULL);
       }
+      data->info.retry_after = retry_after; /* store it */
+      return CURLE_OK;
     }
-  }
+    break;
+  case 's':
+  case 'S':
+#if !defined(CURL_DISABLE_COOKIES)
+    v = (data->cookies && data->state.cookie_engine)?
+        HD_VAL(hd, hdlen, "Set-Cookie:") : NULL;
+    if(v) {
+      /* If there is a custom-set Host: name, use it here, or else use
+       * real peer host name. */
+      const char *host = data->state.aptr.cookiehost?
+        data->state.aptr.cookiehost:conn->host.name;
+      const bool secure_context =
+        conn->handler->protocol&(CURLPROTO_HTTPS|CURLPROTO_WSS) ||
+        strcasecompare("localhost", host) ||
+        !strcmp(host, "127.0.0.1") ||
+        !strcmp(host, "::1") ? TRUE : FALSE;
 
+      Curl_share_lock(data, CURL_LOCK_DATA_COOKIE,
+                      CURL_LOCK_ACCESS_SINGLE);
+      Curl_cookie_add(data, data->cookies, TRUE, FALSE, v, host,
+                      data->state.up.path, secure_context);
+      Curl_share_unlock(data, CURL_LOCK_DATA_COOKIE);
+      return CURLE_OK;
+    }
+#endif
 #ifndef CURL_DISABLE_HSTS
-  /* If enabled, the header is incoming and this is over HTTPS */
-  else if(data->hsts && checkprefix("Strict-Transport-Security:", headp) &&
-          ((conn->handler->flags & PROTOPT_SSL) ||
+    /* If enabled, the header is incoming and this is over HTTPS */
+    v = (data->hsts &&
+         ((conn->handler->flags & PROTOPT_SSL) ||
 #ifdef CURLDEBUG
            /* allow debug builds to circumvent the HTTPS restriction */
            getenv("CURL_HSTS_HTTP")
 #else
            0
 #endif
-            )) {
-    CURLcode check =
-      Curl_hsts_parse(data->hsts, conn->host.name,
-                      headp + strlen("Strict-Transport-Security:"));
-    if(check)
-      infof(data, "Illegal STS header skipped");
+            )
+        )? HD_VAL(hd, hdlen, "Strict-Transport-Security:") : NULL;
+    if(v) {
+      CURLcode check =
+        Curl_hsts_parse(data->hsts, conn->host.name, v);
+      if(check)
+        infof(data, "Illegal STS header skipped");
 #ifdef DEBUGBUILD
-    else
-      infof(data, "Parsed STS header fine (%zu entries)",
-            data->hsts->list.size);
-#endif
-  }
+      else
+        infof(data, "Parsed STS header fine (%zu entries)",
+              data->hsts->list.size);
 #endif
-#ifndef CURL_DISABLE_ALTSVC
-  /* If enabled, the header is incoming and this is over HTTPS */
-  else if(data->asi && checkprefix("Alt-Svc:", headp) &&
-          ((conn->handler->flags & PROTOPT_SSL) ||
-#ifdef CURLDEBUG
-           /* allow debug builds to circumvent the HTTPS restriction */
-           getenv("CURL_ALTSVC_HTTP")
-#else
-           0
+    }
 #endif
-            )) {
-    /* the ALPN of the current request */
-    enum alpnid id = (conn->httpversion == 30)? ALPN_h3 :
-                       (conn->httpversion == 20) ? ALPN_h2 : ALPN_h1;
-    result = Curl_altsvc_parse(data, data->asi,
-                               headp + strlen("Alt-Svc:"),
-                               id, conn->host.name,
-                               curlx_uitous((unsigned int)conn->remote_port));
-    if(result)
+    break;
+  case 't':
+  case 'T':
+    /* RFC 9112, ch. 6.1
+     * "Transfer-Encoding MAY be sent in a response to a HEAD request or
+     *  in a 304 (Not Modified) response (Section 15.4.5 of [HTTP]) to a
+     *  GET request, neither of which includes a message body, to indicate
+     *  that the origin server would have applied a transfer coding to the
+     *  message body if the request had been an unconditional GET."
+     *
+     * Read: in these cases the 'Transfer-Encoding' does not apply
+     * to any data following the response headers. Do not add any decoders.
+     */
+    v = (!k->http_bodyless &&
+         (data->state.httpreq != HTTPREQ_HEAD) &&
+         (k->httpcode != 304))?
+        HD_VAL(hd, hdlen, "Transfer-Encoding:") : NULL;
+    if(v) {
+      /* One or more encodings. We check for chunked and/or a compression
+         algorithm. */
+      result = Curl_build_unencoding_stack(data, v, TRUE);
+      if(result)
+        return result;
+      if(!k->chunk && data->set.http_transfer_encoding) {
+        /* if this isn't chunked, only close can signal the end of this
+         * transfer as Content-Length is said not to be trusted for
+         * transfer-encoding! */
+        connclose(conn, "HTTP/1.1 transfer-encoding without chunks");
+        k->ignore_cl = TRUE;
+      }
+      return CURLE_OK;
+    }
+    break;
+  case 'w':
+  case 'W':
+    if((401 == k->httpcode) && HD_IS(hd, hdlen, "WWW-Authenticate:")) {
+      char *auth = Curl_copy_header_value(hd);
+      if(!auth)
+        return CURLE_OUT_OF_MEMORY;
+      result = Curl_http_input_auth(data, FALSE, auth);
+      free(auth);
       return result;
+    }
+    break;
   }
-#endif
-  else if(conn->handler->protocol & CURLPROTO_RTSP) {
-    result = Curl_rtsp_parseheader(data, headp);
+
+  if(conn->handler->protocol & CURLPROTO_RTSP) {
+    result = Curl_rtsp_parseheader(data, hd);
     if(result)
       return result;
   }
@@ -3839,18 +3194,41 @@ CURLcode Curl_http_header(struct Curl_easy *data, struct connectdata *conn,
  * Called after the first HTTP response line (the status line) has been
  * received and parsed.
  */
-
 CURLcode Curl_http_statusline(struct Curl_easy *data,
                               struct connectdata *conn)
 {
   struct SingleRequest *k = &data->req;
+
+  switch(k->httpversion) {
+  case 10:
+  case 11:
+#ifdef USE_HTTP2
+  case 20:
+#endif
+#ifdef USE_HTTP3
+  case 30:
+#endif
+    /* no major version switch mid-connection */
+    if(conn->httpversion &&
+       (k->httpversion/10 != conn->httpversion/10)) {
+      failf(data, "Version mismatch (from HTTP/%u to HTTP/%u)",
+            conn->httpversion/10, k->httpversion/10);
+      return CURLE_UNSUPPORTED_PROTOCOL;
+    }
+    break;
+  default:
+    failf(data, "Unsupported HTTP version (%u.%d) in response",
+          k->httpversion/10, k->httpversion%10);
+    return CURLE_UNSUPPORTED_PROTOCOL;
+  }
+
   data->info.httpcode = k->httpcode;
+  data->info.httpversion = k->httpversion;
+  conn->httpversion = (unsigned char)k->httpversion;
 
-  data->info.httpversion = conn->httpversion;
-  if(!data->state.httpversion ||
-     data->state.httpversion > conn->httpversion)
+  if(!data->state.httpversion || data->state.httpversion > k->httpversion)
     /* store the lowest server version we encounter */
-    data->state.httpversion = conn->httpversion;
+    data->state.httpversion = (unsigned char)k->httpversion;
 
   /*
    * This code executes as part of processing the header.  As a
@@ -3867,26 +3245,20 @@ CURLcode Curl_http_statusline(struct Curl_easy *data,
     k->ignorebody = TRUE; /* Avoid appending error msg to good data. */
   }
 
-  if(conn->httpversion == 10) {
+  if(k->httpversion == 10) {
     /* Default action for HTTP/1.0 must be to close, unless
        we get one of those fancy headers that tell us the
        server keeps it open for us! */
     infof(data, "HTTP 1.0, assume close after body");
     connclose(conn, "HTTP/1.0 close after body");
   }
-  else if(conn->httpversion == 20 ||
+  else if(k->httpversion == 20 ||
           (k->upgr101 == UPGR101_H2 && k->httpcode == 101)) {
     DEBUGF(infof(data, "HTTP/2 found, allow multiplexing"));
     /* HTTP/2 cannot avoid multiplexing since it is a core functionality
        of the protocol */
     conn->bundle->multiuse = BUNDLE_MULTIPLEX;
   }
-  else if(conn->httpversion >= 11 &&
-          !conn->bits.close) {
-    /* If HTTP version is >= 1.1 and connection is persistent */
-    DEBUGF(infof(data,
-                 "HTTP 1.1 or later with persistent connection"));
-  }
 
   k->http_bodyless = k->httpcode >= 100 && k->httpcode < 200;
   switch(k->httpcode) {
@@ -3897,7 +3269,7 @@ CURLcode Curl_http_statusline(struct Curl_easy *data,
      * fields.  */
     if(data->set.timecondition)
       data->info.timecond = TRUE;
-    /* FALLTHROUGH */
+    FALLTHROUGH();
   case 204:
     /* (quote from RFC2616, section 10.2.5): The server has
      * fulfilled the request but does not need to return an
@@ -3937,12 +3309,11 @@ CURLcode Curl_http_size(struct Curl_easy *data)
   return CURLE_OK;
 }
 
-static CURLcode verify_header(struct Curl_easy *data)
+static CURLcode verify_header(struct Curl_easy *data,
+                              const char *hd, size_t hdlen)
 {
   struct SingleRequest *k = &data->req;
-  const char *header = Curl_dyn_ptr(&data->state.headerb);
-  size_t hlen = Curl_dyn_len(&data->state.headerb);
-  char *ptr = memchr(header, 0x00, hlen);
+  char *ptr = memchr(hd, 0x00, hdlen);
   if(ptr) {
     /* this is bad, bail out */
     failf(data, "Nul byte in header");
@@ -3951,11 +3322,11 @@ static CURLcode verify_header(struct Curl_easy *data)
   if(k->headerline < 2)
     /* the first "header" is the status-line and it has no colon */
     return CURLE_OK;
-  if(((header[0] == ' ') || (header[0] == '\t')) && k->headerline > 2)
+  if(((hd[0] == ' ') || (hd[0] == '\t')) && k->headerline > 2)
     /* line folding, can't happen on line 2 */
     ;
   else {
-    ptr = memchr(header, ':', hlen);
+    ptr = memchr(hd, ':', hdlen);
     if(!ptr) {
       /* this is bad, bail out */
       failf(data, "Header without colon");
@@ -3970,58 +3341,507 @@ CURLcode Curl_bump_headersize(struct Curl_easy *data,
                               bool connect_only)
 {
   size_t bad = 0;
+  unsigned int max = MAX_HTTP_RESP_HEADER_SIZE;
   if(delta < MAX_HTTP_RESP_HEADER_SIZE) {
+    data->info.header_size += (unsigned int)delta;
+    data->req.allheadercount += (unsigned int)delta;
     if(!connect_only)
       data->req.headerbytecount += (unsigned int)delta;
-    data->info.header_size += (unsigned int)delta;
-    if(data->info.header_size > MAX_HTTP_RESP_HEADER_SIZE)
+    if(data->req.allheadercount > max)
+      bad = data->req.allheadercount;
+    else if(data->info.header_size > (max * 20)) {
       bad = data->info.header_size;
+      max *= 20;
+    }
   }
   else
-    bad = data->info.header_size + delta;
+    bad = data->req.allheadercount + delta;
   if(bad) {
-    failf(data, "Too large response headers: %zu > %u",
-          bad, MAX_HTTP_RESP_HEADER_SIZE);
+    failf(data, "Too large response headers: %zu > %u", bad, max);
     return CURLE_RECV_ERROR;
   }
   return CURLE_OK;
 }
 
-
+
+static CURLcode http_on_response(struct Curl_easy *data,
+                                 const char *buf, size_t blen,
+                                 size_t *pconsumed)
+{
+  struct connectdata *conn = data->conn;
+  CURLcode result = CURLE_OK;
+  struct SingleRequest *k = &data->req;
+
+  (void)buf; /* not used without HTTP2 enabled */
+  *pconsumed = 0;
+
+  if(k->upgr101 == UPGR101_RECEIVED) {
+    /* supposedly upgraded to http2 now */
+    if(conn->httpversion != 20)
+      infof(data, "Lying server, not serving HTTP/2");
+  }
+  if(conn->httpversion < 20) {
+    conn->bundle->multiuse = BUNDLE_NO_MULTIUSE;
+  }
+
+  if(k->httpcode < 100) {
+    failf(data, "Unsupported response code in HTTP response");
+    return CURLE_UNSUPPORTED_PROTOCOL;
+  }
+  else if(k->httpcode < 200) {
+    /* "A user agent MAY ignore unexpected 1xx status responses."
+     * By default, we expect to get more responses after this one. */
+    k->header = TRUE;
+    k->headerline = 0; /* restart the header line counter */
+
+    switch(k->httpcode) {
+    case 100:
+      /*
+       * We have made an HTTP PUT or POST and this is 1.1-lingo
+       * that tells us that the server is OK with this and ready
+       * to receive the data.
+       */
+      Curl_http_exp100_got100(data);
+      break;
+    case 101:
+      /* Switching Protocols only allowed from HTTP/1.1 */
+      if(conn->httpversion != 11) {
+        /* invalid for other HTTP versions */
+        failf(data, "unexpected 101 response code");
+        return CURLE_WEIRD_SERVER_REPLY;
+      }
+      if(k->upgr101 == UPGR101_H2) {
+        /* Switching to HTTP/2, where we will get more responses */
+        infof(data, "Received 101, Switching to HTTP/2");
+        k->upgr101 = UPGR101_RECEIVED;
+        /* We expect more response from HTTP/2 later */
+        k->header = TRUE;
+        k->headerline = 0; /* restart the header line counter */
+        /* Any remaining `buf` bytes are already HTTP/2 and passed to
+         * be processed. */
+        result = Curl_http2_upgrade(data, conn, FIRSTSOCKET, buf, blen);
+        if(result)
+          return result;
+        *pconsumed += blen;
+      }
+#ifdef USE_WEBSOCKETS
+      else if(k->upgr101 == UPGR101_WS) {
+        /* verify the response. Any passed `buf` bytes are already in
+         * WebSockets format and taken in by the protocol handler. */
+        result = Curl_ws_accept(data, buf, blen);
+        if(result)
+          return result;
+        *pconsumed += blen; /* ws accept handled the data */
+        k->header = FALSE; /* we will not get more responses */
+        if(data->set.connect_only)
+          k->keepon &= ~KEEP_RECV; /* read no more content */
+      }
+#endif
+      else {
+        /* We silently accept this as the final response.
+         * TODO: this looks, uhm, wrong. What are we switching to if we
+         * did not ask for an Upgrade? Maybe the application provided an
+         * `Upgrade: xxx` header? */
+        k->header = FALSE;
+      }
+      break;
+    default:
+      /* The server may send us other 1xx responses, like informative
+       * 103. This have no influence on request processing and we expect
+       * to receive a final response eventually. */
+      break;
+    }
+    return result;
+  }
+
+  /* k->httpcode >= 200, final response */
+  k->header = FALSE;
+
+  if(k->upgr101 == UPGR101_H2) {
+    /* A requested upgrade was denied, poke the multi handle to possibly
+       allow a pending pipewait to continue */
+    Curl_multi_connchanged(data->multi);
+  }
+
+  if((k->size == -1) && !k->chunk && !conn->bits.close &&
+     (conn->httpversion == 11) &&
+     !(conn->handler->protocol & CURLPROTO_RTSP) &&
+     data->state.httpreq != HTTPREQ_HEAD) {
+    /* On HTTP 1.1, when connection is not to get closed, but no
+       Content-Length nor Transfer-Encoding chunked have been
+       received, according to RFC2616 section 4.4 point 5, we
+       assume that the server will close the connection to
+       signal the end of the document. */
+    infof(data, "no chunk, no close, no size. Assume close to "
+          "signal end");
+    streamclose(conn, "HTTP: No end-of-message indicator");
+  }
+
+  /* At this point we have some idea about the fate of the connection.
+     If we are closing the connection it may result auth failure. */
+#if defined(USE_NTLM)
+  if(conn->bits.close &&
+     (((data->req.httpcode == 401) &&
+       (conn->http_ntlm_state == NTLMSTATE_TYPE2)) ||
+      ((data->req.httpcode == 407) &&
+       (conn->proxy_ntlm_state == NTLMSTATE_TYPE2)))) {
+    infof(data, "Connection closure while negotiating auth (HTTP 1.0?)");
+    data->state.authproblem = TRUE;
+  }
+#endif
+#if defined(USE_SPNEGO)
+  if(conn->bits.close &&
+    (((data->req.httpcode == 401) &&
+      (conn->http_negotiate_state == GSS_AUTHRECV)) ||
+     ((data->req.httpcode == 407) &&
+      (conn->proxy_negotiate_state == GSS_AUTHRECV)))) {
+    infof(data, "Connection closure while negotiating auth (HTTP 1.0?)");
+    data->state.authproblem = TRUE;
+  }
+  if((conn->http_negotiate_state == GSS_AUTHDONE) &&
+     (data->req.httpcode != 401)) {
+    conn->http_negotiate_state = GSS_AUTHSUCC;
+  }
+  if((conn->proxy_negotiate_state == GSS_AUTHDONE) &&
+     (data->req.httpcode != 407)) {
+    conn->proxy_negotiate_state = GSS_AUTHSUCC;
+  }
+#endif
+
+#ifdef USE_WEBSOCKETS
+  /* All >=200 HTTP status codes are errors when wanting websockets */
+  if(data->req.upgr101 == UPGR101_WS) {
+    failf(data, "Refused WebSockets upgrade: %d", k->httpcode);
+    return CURLE_HTTP_RETURNED_ERROR;
+  }
+#endif
+
+  /* Check if this response means the transfer errored. */
+  if(http_should_fail(data, data->req.httpcode)) {
+    failf(data, "The requested URL returned error: %d",
+          k->httpcode);
+    return CURLE_HTTP_RETURNED_ERROR;
+  }
+
+  /* Curl_http_auth_act() checks what authentication methods
+   * that are available and decides which one (if any) to
+   * use. It will set 'newurl' if an auth method was picked. */
+  result = Curl_http_auth_act(data);
+  if(result)
+    return result;
+
+  if(k->httpcode >= 300) {
+    if((!data->req.authneg) && !conn->bits.close &&
+       !Curl_creader_will_rewind(data)) {
+      /*
+       * General treatment of errors when about to send data. Including :
+       * "417 Expectation Failed", while waiting for 100-continue.
+       *
+       * The check for close above is done simply because of something
+       * else has already deemed the connection to get closed then
+       * something else should've considered the big picture and we
+       * avoid this check.
+       *
+       */
+
+      switch(data->state.httpreq) {
+      case HTTPREQ_PUT:
+      case HTTPREQ_POST:
+      case HTTPREQ_POST_FORM:
+      case HTTPREQ_POST_MIME:
+        /* We got an error response. If this happened before the whole
+         * request body has been sent we stop sending and mark the
+         * connection for closure after we've read the entire response.
+         */
+        if(!Curl_req_done_sending(data)) {
+          if((k->httpcode == 417) && Curl_http_exp100_is_selected(data)) {
+            /* 417 Expectation Failed - try again without the Expect
+               header */
+            if(!k->writebytecount && http_exp100_is_waiting(data)) {
+              infof(data, "Got HTTP failure 417 while waiting for a 100");
+            }
+            else {
+              infof(data, "Got HTTP failure 417 while sending data");
+              streamclose(conn,
+                          "Stop sending data before everything sent");
+              result = http_perhapsrewind(data, conn);
+              if(result)
+                return result;
+            }
+            data->state.disableexpect = TRUE;
+            DEBUGASSERT(!data->req.newurl);
+            data->req.newurl = strdup(data->state.url);
+            Curl_req_abort_sending(data);
+          }
+          else if(data->set.http_keep_sending_on_error) {
+            infof(data, "HTTP error before end of send, keep sending");
+            http_exp100_send_anyway(data);
+          }
+          else {
+            infof(data, "HTTP error before end of send, stop sending");
+            streamclose(conn, "Stop sending data before everything sent");
+            result = Curl_req_abort_sending(data);
+            if(result)
+              return result;
+          }
+        }
+        break;
+
+      default: /* default label present to avoid compiler warnings */
+        break;
+      }
+    }
+
+    if(Curl_creader_will_rewind(data) && !Curl_req_done_sending(data)) {
+      /* We rewind before next send, continue sending now */
+      infof(data, "Keep sending data to get tossed away");
+      k->keepon |= KEEP_SEND;
+    }
+
+  }
+
+  /* This is the last response that we will got for the current request.
+   * Check on the body size and determine if the response is complete.
+   */
+  result = Curl_http_size(data);
+  if(result)
+    return result;
+
+  /* If we requested a "no body", this is a good time to get
+   * out and return home.
+   */
+  if(data->req.no_body)
+    k->download_done = TRUE;
+
+  /* If max download size is *zero* (nothing) we already have
+     nothing and can safely return ok now!  But for HTTP/2, we'd
+     like to call http2_handle_stream_close to properly close a
+     stream.  In order to do this, we keep reading until we
+     close the stream. */
+  if(0 == k->maxdownload
+     && !Curl_conn_is_http2(data, conn, FIRSTSOCKET)
+     && !Curl_conn_is_http3(data, conn, FIRSTSOCKET))
+    k->download_done = TRUE;
+
+  /* final response without error, prepare to receive the body */
+  return Curl_http_firstwrite(data);
+}
+
+static CURLcode http_rw_hd(struct Curl_easy *data,
+                           const char *hd, size_t hdlen,
+                           const char *buf_remain, size_t blen,
+                           size_t *pconsumed)
+{
+  CURLcode result = CURLE_OK;
+  struct SingleRequest *k = &data->req;
+  int writetype;
+
+  *pconsumed = 0;
+  if((0x0a == *hd) || (0x0d == *hd)) {
+    /* Empty header line means end of headers! */
+    size_t consumed;
+
+    /* now, only output this if the header AND body are requested:
+     */
+    Curl_debug(data, CURLINFO_HEADER_IN, (char *)hd, hdlen);
+
+    writetype = CLIENTWRITE_HEADER |
+      ((k->httpcode/100 == 1) ? CLIENTWRITE_1XX : 0);
+
+    result = Curl_client_write(data, writetype, hd, hdlen);
+    if(result)
+      return result;
+
+    result = Curl_bump_headersize(data, hdlen, FALSE);
+    if(result)
+      return result;
+
+    data->req.deductheadercount =
+      (100 <= k->httpcode && 199 >= k->httpcode)?data->req.headerbytecount:0;
+
+    /* analyze the response to find out what to do. */
+    /* Caveat: we clear anything in the header brigade, because a
+     * response might switch HTTP version which may call use recursively.
+     * Not nice, but that is currently the way of things. */
+    Curl_dyn_reset(&data->state.headerb);
+    result = http_on_response(data, buf_remain, blen, &consumed);
+    if(result)
+      return result;
+    *pconsumed += consumed;
+    return CURLE_OK;
+  }
+
+  /*
+   * Checks for special headers coming up.
+   */
+
+  writetype = CLIENTWRITE_HEADER;
+  if(!k->headerline++) {
+    /* This is the first header, it MUST be the error code line
+       or else we consider this to be the body right away! */
+    bool fine_statusline = FALSE;
+
+    k->httpversion = 0; /* Don't know yet */
+    if(data->conn->handler->protocol & PROTO_FAMILY_HTTP) {
+      /*
+       * https://datatracker.ietf.org/doc/html/rfc7230#section-3.1.2
+       *
+       * The response code is always a three-digit number in HTTP as the spec
+       * says. We allow any three-digit number here, but we cannot make
+       * guarantees on future behaviors since it isn't within the protocol.
+       */
+      const char *p = hd;
+
+      while(*p && ISBLANK(*p))
+        p++;
+      if(!strncmp(p, "HTTP/", 5)) {
+        p += 5;
+        switch(*p) {
+        case '1':
+          p++;
+          if((p[0] == '.') && (p[1] == '0' || p[1] == '1')) {
+            if(ISBLANK(p[2])) {
+              k->httpversion = 10 + (p[1] - '0');
+              p += 3;
+              if(ISDIGIT(p[0]) && ISDIGIT(p[1]) && ISDIGIT(p[2])) {
+                k->httpcode = (p[0] - '0') * 100 + (p[1] - '0') * 10 +
+                  (p[2] - '0');
+                p += 3;
+                if(ISSPACE(*p))
+                  fine_statusline = TRUE;
+              }
+            }
+          }
+          if(!fine_statusline) {
+            failf(data, "Unsupported HTTP/1 subversion in response");
+            return CURLE_UNSUPPORTED_PROTOCOL;
+          }
+          break;
+        case '2':
+        case '3':
+          if(!ISBLANK(p[1]))
+            break;
+          k->httpversion = (*p - '0') * 10;
+          p += 2;
+          if(ISDIGIT(p[0]) && ISDIGIT(p[1]) && ISDIGIT(p[2])) {
+            k->httpcode = (p[0] - '0') * 100 + (p[1] - '0') * 10 +
+              (p[2] - '0');
+            p += 3;
+            if(!ISSPACE(*p))
+              break;
+            fine_statusline = TRUE;
+          }
+          break;
+        default: /* unsupported */
+          failf(data, "Unsupported HTTP version in response");
+          return CURLE_UNSUPPORTED_PROTOCOL;
+        }
+      }
+
+      if(!fine_statusline) {
+        /* If user has set option HTTP200ALIASES,
+           compare header line against list of aliases
+        */
+        statusline check = checkhttpprefix(data, hd, hdlen);
+        if(check == STATUS_DONE) {
+          fine_statusline = TRUE;
+          k->httpcode = 200;
+          k->httpversion = 10;
+        }
+      }
+    }
+    else if(data->conn->handler->protocol & CURLPROTO_RTSP) {
+      const char *p = hd;
+      while(*p && ISBLANK(*p))
+        p++;
+      if(!strncmp(p, "RTSP/", 5)) {
+        p += 5;
+        if(ISDIGIT(*p)) {
+          p++;
+          if((p[0] == '.') && ISDIGIT(p[1])) {
+            if(ISBLANK(p[2])) {
+              p += 3;
+              if(ISDIGIT(p[0]) && ISDIGIT(p[1]) && ISDIGIT(p[2])) {
+                k->httpcode = (p[0] - '0') * 100 + (p[1] - '0') * 10 +
+                  (p[2] - '0');
+                p += 3;
+                if(ISSPACE(*p)) {
+                  fine_statusline = TRUE;
+                  k->httpversion = 11; /* RTSP acts like HTTP 1.1 */
+                }
+              }
+            }
+          }
+        }
+        if(!fine_statusline)
+          return CURLE_WEIRD_SERVER_REPLY;
+      }
+    }
+
+    if(fine_statusline) {
+      result = Curl_http_statusline(data, data->conn);
+      if(result)
+        return result;
+      writetype |= CLIENTWRITE_STATUS;
+    }
+    else {
+      k->header = FALSE;   /* this is not a header line */
+      return CURLE_WEIRD_SERVER_REPLY;
+    }
+  }
+
+  result = verify_header(data, hd, hdlen);
+  if(result)
+    return result;
+
+  result = Curl_http_header(data, hd, hdlen);
+  if(result)
+    return result;
+
+  /*
+   * Taken in one (more) header. Write it to the client.
+   */
+  Curl_debug(data, CURLINFO_HEADER_IN, (char *)hd, hdlen);
+
+  if(k->httpcode/100 == 1)
+    writetype |= CLIENTWRITE_1XX;
+  result = Curl_client_write(data, writetype, hd, hdlen);
+  if(result)
+    return result;
+
+  result = Curl_bump_headersize(data, hdlen, FALSE);
+  if(result)
+    return result;
+
+  return CURLE_OK;
+}
+
 /*
  * Read any HTTP header lines from the server and pass them to the client app.
  */
-CURLcode Curl_http_readwrite_headers(struct Curl_easy *data,
-                                     struct connectdata *conn,
-                                     ssize_t *nread,
-                                     bool *stop_reading)
+static CURLcode http_parse_headers(struct Curl_easy *data,
+                                   const char *buf, size_t blen,
+                                   size_t *pconsumed)
 {
-  CURLcode result;
+  struct connectdata *conn = data->conn;
+  CURLcode result = CURLE_OK;
   struct SingleRequest *k = &data->req;
-  ssize_t onread = *nread;
-  char *ostr = k->str;
-  char *headp;
-  char *str_start;
   char *end_ptr;
+  bool leftover_body = FALSE;
 
   /* header line within buffer loop */
-  do {
-    size_t rest_length;
-    size_t full_length;
-    int writetype;
-
-    /* str_start is start of line within buf */
-    str_start = k->str;
-
-    /* data is in network encoding so use 0x0a instead of '\n' */
-    end_ptr = memchr(str_start, 0x0a, *nread);
+  *pconsumed = 0;
+  while(blen && k->header) {
+    size_t consumed;
 
+    end_ptr = memchr(buf, '\n', blen);
     if(!end_ptr) {
       /* Not a complete header line within buffer, append the data to
          the end of the headerbuff. */
-      result = Curl_dyn_addn(&data->state.headerb, str_start, *nread);
+      result = Curl_dyn_addn(&data->state.headerb, buf, blen);
       if(result)
         return result;
+      *pconsumed += blen;
 
       if(!k->headerline) {
         /* check if this looks like a protocol header */
@@ -4033,30 +3853,30 @@ CURLcode Curl_http_readwrite_headers(struct Curl_easy *data,
         if(st == STATUS_BAD) {
           /* this is not the beginning of a protocol first header line */
           k->header = FALSE;
-          k->badheader = HEADER_ALLBAD;
           streamclose(conn, "bad HTTP: No end-of-message indicator");
+          if(conn->httpversion >= 10) {
+            failf(data, "Invalid status line");
+            return CURLE_WEIRD_SERVER_REPLY;
+          }
           if(!data->set.http09_allowed) {
             failf(data, "Received HTTP/0.9 when not allowed");
             return CURLE_UNSUPPORTED_PROTOCOL;
           }
-          break;
+          leftover_body = TRUE;
+          goto out;
         }
       }
-
-      break; /* read more and try again */
+      goto out; /* read more and try again */
     }
 
     /* decrease the size of the remaining (supposed) header line */
-    rest_length = (end_ptr - k->str) + 1;
-    *nread -= (ssize_t)rest_length;
-
-    k->str = end_ptr + 1; /* move past new line */
-
-    full_length = k->str - str_start;
-
-    result = Curl_dyn_addn(&data->state.headerb, str_start, full_length);
+    consumed = (end_ptr - buf) + 1;
+    result = Curl_dyn_addn(&data->state.headerb, buf, consumed);
     if(result)
       return result;
+    blen -= consumed;
+    buf += consumed;
+    *pconsumed += consumed;
 
     /****
      * We now have a FULL header line in 'headerb'.
@@ -4070,529 +3890,122 @@ CURLcode Curl_http_readwrite_headers(struct Curl_easy *data,
       if(st == STATUS_BAD) {
         streamclose(conn, "bad HTTP: No end-of-message indicator");
         /* this is not the beginning of a protocol first header line */
+        if(conn->httpversion >= 10) {
+          failf(data, "Invalid status line");
+          return CURLE_WEIRD_SERVER_REPLY;
+        }
         if(!data->set.http09_allowed) {
           failf(data, "Received HTTP/0.9 when not allowed");
           return CURLE_UNSUPPORTED_PROTOCOL;
         }
         k->header = FALSE;
-        if(*nread)
-          /* since there's more, this is a partial bad header */
-          k->badheader = HEADER_PARTHEADER;
-        else {
-          /* this was all we read so it's all a bad header */
-          k->badheader = HEADER_ALLBAD;
-          *nread = onread;
-          k->str = ostr;
-          return CURLE_OK;
-        }
-        break;
+        leftover_body = TRUE;
+        goto out;
       }
     }
 
-    /* headers are in network encoding so use 0x0a and 0x0d instead of '\n'
-       and '\r' */
-    headp = Curl_dyn_ptr(&data->state.headerb);
-    if((0x0a == *headp) || (0x0d == *headp)) {
-      size_t headerlen;
-      /* Zero-length header line means end of headers! */
-
-      if('\r' == *headp)
-        headp++; /* pass the \r byte */
-      if('\n' == *headp)
-        headp++; /* pass the \n byte */
-
-      if(100 <= k->httpcode && 199 >= k->httpcode) {
-        /* "A user agent MAY ignore unexpected 1xx status responses." */
-        switch(k->httpcode) {
-        case 100:
-          /*
-           * We have made an HTTP PUT or POST and this is 1.1-lingo
-           * that tells us that the server is OK with this and ready
-           * to receive the data.
-           * However, we'll get more headers now so we must get
-           * back into the header-parsing state!
-           */
-          k->header = TRUE;
-          k->headerline = 0; /* restart the header line counter */
-
-          /* if we did wait for this do enable write now! */
-          if(k->exp100 > EXP100_SEND_DATA) {
-            k->exp100 = EXP100_SEND_DATA;
-            k->keepon |= KEEP_SEND;
-            Curl_expire_done(data, EXPIRE_100_TIMEOUT);
-          }
-          break;
-        case 101:
-          /* Switching Protocols */
-          if(k->upgr101 == UPGR101_H2) {
-            /* Switching to HTTP/2 */
-            DEBUGASSERT(conn->httpversion < 20);
-            infof(data, "Received 101, Switching to HTTP/2");
-            k->upgr101 = UPGR101_RECEIVED;
-
-            /* we'll get more headers (HTTP/2 response) */
-            k->header = TRUE;
-            k->headerline = 0; /* restart the header line counter */
-
-            /* switch to http2 now. The bytes after response headers
-               are also processed here, otherwise they are lost. */
-            result = Curl_http2_upgrade(data, conn, FIRSTSOCKET,
-                                        k->str, *nread);
-            if(result)
-              return result;
-            *nread = 0;
-          }
-#ifdef USE_WEBSOCKETS
-          else if(k->upgr101 == UPGR101_WS) {
-            /* verify the response */
-            result = Curl_ws_accept(data, k->str, *nread);
-            if(result)
-              return result;
-            k->header = FALSE; /* no more header to parse! */
-            if(data->set.connect_only) {
-              k->keepon &= ~KEEP_RECV; /* read no more content */
-              *nread = 0;
-            }
-          }
-#endif
-          else {
-            /* Not switching to another protocol */
-            k->header = FALSE; /* no more header to parse! */
-          }
-          break;
-        default:
-          /* the status code 1xx indicates a provisional response, so
-             we'll get another set of headers */
-          k->header = TRUE;
-          k->headerline = 0; /* restart the header line counter */
-          break;
-        }
-      }
-      else {
-        if(k->upgr101 == UPGR101_H2) {
-          /* A requested upgrade was denied, poke the multi handle to possibly
-             allow a pending pipewait to continue */
-          Curl_multi_connchanged(data->multi);
-        }
-        k->header = FALSE; /* no more header to parse! */
-
-        if((k->size == -1) && !k->chunk && !conn->bits.close &&
-           (conn->httpversion == 11) &&
-           !(conn->handler->protocol & CURLPROTO_RTSP) &&
-           data->state.httpreq != HTTPREQ_HEAD) {
-          /* On HTTP 1.1, when connection is not to get closed, but no
-             Content-Length nor Transfer-Encoding chunked have been
-             received, according to RFC2616 section 4.4 point 5, we
-             assume that the server will close the connection to
-             signal the end of the document. */
-          infof(data, "no chunk, no close, no size. Assume close to "
-                "signal end");
-          streamclose(conn, "HTTP: No end-of-message indicator");
-        }
-      }
-
-      if(!k->header) {
-        result = Curl_http_size(data);
-        if(result)
-          return result;
-      }
-
-      /* At this point we have some idea about the fate of the connection.
-         If we are closing the connection it may result auth failure. */
-#if defined(USE_NTLM)
-      if(conn->bits.close &&
-         (((data->req.httpcode == 401) &&
-           (conn->http_ntlm_state == NTLMSTATE_TYPE2)) ||
-          ((data->req.httpcode == 407) &&
-           (conn->proxy_ntlm_state == NTLMSTATE_TYPE2)))) {
-        infof(data, "Connection closure while negotiating auth (HTTP 1.0?)");
-        data->state.authproblem = TRUE;
-      }
-#endif
-#if defined(USE_SPNEGO)
-      if(conn->bits.close &&
-        (((data->req.httpcode == 401) &&
-          (conn->http_negotiate_state == GSS_AUTHRECV)) ||
-         ((data->req.httpcode == 407) &&
-          (conn->proxy_negotiate_state == GSS_AUTHRECV)))) {
-        infof(data, "Connection closure while negotiating auth (HTTP 1.0?)");
-        data->state.authproblem = TRUE;
-      }
-      if((conn->http_negotiate_state == GSS_AUTHDONE) &&
-         (data->req.httpcode != 401)) {
-        conn->http_negotiate_state = GSS_AUTHSUCC;
-      }
-      if((conn->proxy_negotiate_state == GSS_AUTHDONE) &&
-         (data->req.httpcode != 407)) {
-        conn->proxy_negotiate_state = GSS_AUTHSUCC;
-      }
-#endif
-
-      /* now, only output this if the header AND body are requested:
-       */
-      writetype = CLIENTWRITE_HEADER |
-        (data->set.include_header ? CLIENTWRITE_BODY : 0) |
-        ((k->httpcode/100 == 1) ? CLIENTWRITE_1XX : 0);
-
-      headerlen = Curl_dyn_len(&data->state.headerb);
-      result = Curl_client_write(data, writetype,
-                                 Curl_dyn_ptr(&data->state.headerb),
-                                 headerlen);
-      if(result)
-        return result;
-
-      result = Curl_bump_headersize(data, headerlen, FALSE);
-      if(result)
-        return result;
-
-      /*
-       * When all the headers have been parsed, see if we should give
-       * up and return an error.
-       */
-      if(http_should_fail(data)) {
-        failf(data, "The requested URL returned error: %d",
-              k->httpcode);
-        return CURLE_HTTP_RETURNED_ERROR;
-      }
-
-#ifdef USE_WEBSOCKETS
-      /* All non-101 HTTP status codes are bad when wanting to upgrade to
-         websockets */
-      if(data->req.upgr101 == UPGR101_WS) {
-        failf(data, "Refused WebSockets upgrade: %d", k->httpcode);
-        return CURLE_HTTP_RETURNED_ERROR;
-      }
-#endif
-
-
-      data->req.deductheadercount =
-        (100 <= k->httpcode && 199 >= k->httpcode)?data->req.headerbytecount:0;
-
-      /* Curl_http_auth_act() checks what authentication methods
-       * that are available and decides which one (if any) to
-       * use. It will set 'newurl' if an auth method was picked. */
-      result = Curl_http_auth_act(data);
-
-      if(result)
-        return result;
-
-      if(k->httpcode >= 300) {
-        if((!conn->bits.authneg) && !conn->bits.close &&
-           !data->state.rewindbeforesend) {
-          /*
-           * General treatment of errors when about to send data. Including :
-           * "417 Expectation Failed", while waiting for 100-continue.
-           *
-           * The check for close above is done simply because of something
-           * else has already deemed the connection to get closed then
-           * something else should've considered the big picture and we
-           * avoid this check.
-           *
-           * rewindbeforesend indicates that something has told libcurl to
-           * continue sending even if it gets discarded
-           */
-
-          switch(data->state.httpreq) {
-          case HTTPREQ_PUT:
-          case HTTPREQ_POST:
-          case HTTPREQ_POST_FORM:
-          case HTTPREQ_POST_MIME:
-            /* We got an error response. If this happened before the whole
-             * request body has been sent we stop sending and mark the
-             * connection for closure after we've read the entire response.
-             */
-            Curl_expire_done(data, EXPIRE_100_TIMEOUT);
-            if(!k->upload_done) {
-              if((k->httpcode == 417) && data->state.expect100header) {
-                /* 417 Expectation Failed - try again without the Expect
-                   header */
-                if(!k->writebytecount &&
-                   k->exp100 == EXP100_AWAITING_CONTINUE) {
-                  infof(data, "Got HTTP failure 417 while waiting for a 100");
-                }
-                else {
-                  infof(data, "Got HTTP failure 417 while sending data");
-                  streamclose(conn,
-                              "Stop sending data before everything sent");
-                  result = http_perhapsrewind(data, conn);
-                  if(result)
-                    return result;
-                }
-                data->state.disableexpect = TRUE;
-                DEBUGASSERT(!data->req.newurl);
-                data->req.newurl = strdup(data->state.url);
-                Curl_done_sending(data, k);
-              }
-              else if(data->set.http_keep_sending_on_error) {
-                infof(data, "HTTP error before end of send, keep sending");
-                if(k->exp100 > EXP100_SEND_DATA) {
-                  k->exp100 = EXP100_SEND_DATA;
-                  k->keepon |= KEEP_SEND;
-                }
-              }
-              else {
-                infof(data, "HTTP error before end of send, stop sending");
-                streamclose(conn, "Stop sending data before everything sent");
-                result = Curl_done_sending(data, k);
-                if(result)
-                  return result;
-                k->upload_done = TRUE;
-                if(data->state.expect100header)
-                  k->exp100 = EXP100_FAILED;
-              }
-            }
-            break;
-
-          default: /* default label present to avoid compiler warnings */
-            break;
-          }
-        }
-
-        if(data->state.rewindbeforesend &&
-           (conn->writesockfd != CURL_SOCKET_BAD)) {
-          /* We rewind before next send, continue sending now */
-          infof(data, "Keep sending data to get tossed away");
-          k->keepon |= KEEP_SEND;
-        }
-      }
-
-      if(!k->header) {
-        /*
-         * really end-of-headers.
-         *
-         * If we requested a "no body", this is a good time to get
-         * out and return home.
-         */
-        if(data->req.no_body)
-          *stop_reading = TRUE;
-#ifndef CURL_DISABLE_RTSP
-        else if((conn->handler->protocol & CURLPROTO_RTSP) &&
-                (data->set.rtspreq == RTSPREQ_DESCRIBE) &&
-                (k->size <= -1))
-          /* Respect section 4.4 of rfc2326: If the Content-Length header is
-             absent, a length 0 must be assumed.  It will prevent libcurl from
-             hanging on DESCRIBE request that got refused for whatever
-             reason */
-          *stop_reading = TRUE;
-#endif
-
-        /* If max download size is *zero* (nothing) we already have
-           nothing and can safely return ok now!  But for HTTP/2, we'd
-           like to call http2_handle_stream_close to properly close a
-           stream.  In order to do this, we keep reading until we
-           close the stream. */
-        if(0 == k->maxdownload
-           && !Curl_conn_is_http2(data, conn, FIRSTSOCKET)
-           && !Curl_conn_is_http3(data, conn, FIRSTSOCKET))
-          *stop_reading = TRUE;
-
-        if(*stop_reading) {
-          /* we make sure that this socket isn't read more now */
-          k->keepon &= ~KEEP_RECV;
-        }
-
-        Curl_debug(data, CURLINFO_HEADER_IN, str_start, headerlen);
-        break; /* exit header line loop */
-      }
-
-      /* We continue reading headers, reset the line-based header */
-      Curl_dyn_reset(&data->state.headerb);
-      continue;
+    result = http_rw_hd(data, Curl_dyn_ptr(&data->state.headerb),
+                        Curl_dyn_len(&data->state.headerb),
+                        buf, blen, &consumed);
+    /* We are done with this line. We reset because response
+     * processing might switch to HTTP/2 and that might call us
+     * directly again. */
+    Curl_dyn_reset(&data->state.headerb);
+    if(consumed) {
+      blen -= consumed;
+      buf += consumed;
+      *pconsumed += consumed;
     }
+    if(result)
+      return result;
+  }
 
-    /*
-     * Checks for special headers coming up.
-     */
-
-    writetype = CLIENTWRITE_HEADER;
-    if(!k->headerline++) {
-      /* This is the first header, it MUST be the error code line
-         or else we consider this to be the body right away! */
-      bool fine_statusline = FALSE;
-      if(conn->handler->protocol & PROTO_FAMILY_HTTP) {
-        /*
-         * https://datatracker.ietf.org/doc/html/rfc7230#section-3.1.2
-         *
-         * The response code is always a three-digit number in HTTP as the spec
-         * says. We allow any three-digit number here, but we cannot make
-         * guarantees on future behaviors since it isn't within the protocol.
-         */
-        int httpversion = 0;
-        char *p = headp;
-
-        while(*p && ISBLANK(*p))
-          p++;
-        if(!strncmp(p, "HTTP/", 5)) {
-          p += 5;
-          switch(*p) {
-          case '1':
-            p++;
-            if((p[0] == '.') && (p[1] == '0' || p[1] == '1')) {
-              if(ISBLANK(p[2])) {
-                httpversion = 10 + (p[1] - '0');
-                p += 3;
-                if(ISDIGIT(p[0]) && ISDIGIT(p[1]) && ISDIGIT(p[2])) {
-                  k->httpcode = (p[0] - '0') * 100 + (p[1] - '0') * 10 +
-                    (p[2] - '0');
-                  p += 3;
-                  if(ISSPACE(*p))
-                    fine_statusline = TRUE;
-                }
-              }
-            }
-            if(!fine_statusline) {
-              failf(data, "Unsupported HTTP/1 subversion in response");
-              return CURLE_UNSUPPORTED_PROTOCOL;
-            }
-            break;
-          case '2':
-          case '3':
-            if(!ISBLANK(p[1]))
-              break;
-            httpversion = (*p - '0') * 10;
-            p += 2;
-            if(ISDIGIT(p[0]) && ISDIGIT(p[1]) && ISDIGIT(p[2])) {
-              k->httpcode = (p[0] - '0') * 100 + (p[1] - '0') * 10 +
-                (p[2] - '0');
-              p += 3;
-              if(!ISSPACE(*p))
-                break;
-              fine_statusline = TRUE;
-            }
-            break;
-          default: /* unsupported */
-            failf(data, "Unsupported HTTP version in response");
-            return CURLE_UNSUPPORTED_PROTOCOL;
-          }
-        }
+  /* We might have reached the end of the header part here, but
+     there might be a non-header part left in the end of the read
+     buffer. */
+out:
+  if(!k->header && !leftover_body) {
+    Curl_dyn_free(&data->state.headerb);
+  }
+  return CURLE_OK;
+}
 
-        if(fine_statusline) {
-          if(k->httpcode < 100) {
-            failf(data, "Unsupported response code in HTTP response");
-            return CURLE_UNSUPPORTED_PROTOCOL;
-          }
-          switch(httpversion) {
-          case 10:
-          case 11:
-#ifdef USE_HTTP2
-          case 20:
-#endif
-#ifdef ENABLE_QUIC
-          case 30:
-#endif
-            conn->httpversion = (unsigned char)httpversion;
-            break;
-          default:
-            failf(data, "Unsupported HTTP version (%u.%d) in response",
-                  httpversion/10, httpversion%10);
-            return CURLE_UNSUPPORTED_PROTOCOL;
-          }
+CURLcode Curl_http_write_resp_hd(struct Curl_easy *data,
+                                 const char *hd, size_t hdlen,
+                                 bool is_eos)
+{
+  CURLcode result;
+  size_t consumed;
+  char tmp = 0;
 
-          if(k->upgr101 == UPGR101_RECEIVED) {
-            /* supposedly upgraded to http2 now */
-            if(conn->httpversion != 20)
-              infof(data, "Lying server, not serving HTTP/2");
-          }
-          if(conn->httpversion < 20) {
-            conn->bundle->multiuse = BUNDLE_NO_MULTIUSE;
-          }
-        }
-        else {
-          /* If user has set option HTTP200ALIASES,
-             compare header line against list of aliases
-          */
-          statusline check =
-            checkhttpprefix(data,
-                            Curl_dyn_ptr(&data->state.headerb),
-                            Curl_dyn_len(&data->state.headerb));
-          if(check == STATUS_DONE) {
-            fine_statusline = TRUE;
-            k->httpcode = 200;
-            conn->httpversion = 10;
-          }
-        }
-      }
-      else if(conn->handler->protocol & CURLPROTO_RTSP) {
-        char *p = headp;
-        while(*p && ISBLANK(*p))
-          p++;
-        if(!strncmp(p, "RTSP/", 5)) {
-          p += 5;
-          if(ISDIGIT(*p)) {
-            p++;
-            if((p[0] == '.') && ISDIGIT(p[1])) {
-              if(ISBLANK(p[2])) {
-                p += 3;
-                if(ISDIGIT(p[0]) && ISDIGIT(p[1]) && ISDIGIT(p[2])) {
-                  k->httpcode = (p[0] - '0') * 100 + (p[1] - '0') * 10 +
-                    (p[2] - '0');
-                  p += 3;
-                  if(ISSPACE(*p)) {
-                    fine_statusline = TRUE;
-                    conn->httpversion = 11; /* RTSP acts like HTTP 1.1 */
-                  }
-                }
-              }
-            }
-          }
-          if(!fine_statusline)
-            return CURLE_WEIRD_SERVER_REPLY;
-        }
-      }
+  result = http_rw_hd(data, hd, hdlen, &tmp, 0, &consumed);
+  if(!result && is_eos) {
+    result = Curl_client_write(data, (CLIENTWRITE_BODY|CLIENTWRITE_EOS),
+                               &tmp, 0);
+  }
+  return result;
+}
 
-      if(fine_statusline) {
-        result = Curl_http_statusline(data, conn);
-        if(result)
-          return result;
-        writetype |= CLIENTWRITE_STATUS;
-      }
-      else {
-        k->header = FALSE;   /* this is not a header line */
-        break;
+/*
+ * HTTP protocol `write_resp` implementation. Will parse headers
+ * when not done yet and otherwise return without consuming data.
+ */
+CURLcode Curl_http_write_resp_hds(struct Curl_easy *data,
+                                  const char *buf, size_t blen,
+                                  size_t *pconsumed)
+{
+  if(!data->req.header) {
+    *pconsumed = 0;
+    return CURLE_OK;
+  }
+  else {
+    CURLcode result;
+
+    result = http_parse_headers(data, buf, blen, pconsumed);
+    if(!result && !data->req.header) {
+      if(!data->req.no_body && Curl_dyn_len(&data->state.headerb)) {
+        /* leftover from parsing something that turned out not
+         * to be a header, only happens if we allow for
+         * HTTP/0.9 like responses */
+        result = Curl_client_write(data, CLIENTWRITE_BODY,
+                                   Curl_dyn_ptr(&data->state.headerb),
+                                   Curl_dyn_len(&data->state.headerb));
       }
+      Curl_dyn_free(&data->state.headerb);
     }
+    return result;
+  }
+}
 
-    result = verify_header(data);
-    if(result)
-      return result;
-
-    result = Curl_http_header(data, conn, headp);
-    if(result)
-      return result;
-
-    /*
-     * End of header-checks. Write them to the client.
-     */
-    if(data->set.include_header)
-      writetype |= CLIENTWRITE_BODY;
-    if(k->httpcode/100 == 1)
-      writetype |= CLIENTWRITE_1XX;
-
-    Curl_debug(data, CURLINFO_HEADER_IN, headp,
-               Curl_dyn_len(&data->state.headerb));
-
-    result = Curl_client_write(data, writetype, headp,
-                               Curl_dyn_len(&data->state.headerb));
-    if(result)
-      return result;
+CURLcode Curl_http_write_resp(struct Curl_easy *data,
+                              const char *buf, size_t blen,
+                              bool is_eos)
+{
+  CURLcode result;
+  size_t consumed;
+  int flags;
 
-    result = Curl_bump_headersize(data, Curl_dyn_len(&data->state.headerb),
-                                  FALSE);
-    if(result)
-      return result;
+  result = Curl_http_write_resp_hds(data, buf, blen, &consumed);
+  if(result || data->req.done)
+    goto out;
 
-    Curl_dyn_reset(&data->state.headerb);
+  DEBUGASSERT(consumed <= blen);
+  blen -= consumed;
+  buf += consumed;
+  /* either all was consumed in header parsing, or we have data left
+   * and are done with headers, e.g. it is BODY data */
+  DEBUGASSERT(!blen || !data->req.header);
+  if(!data->req.header && (blen || is_eos)) {
+    /* BODY data after header been parsed, write and consume */
+    flags = CLIENTWRITE_BODY;
+    if(is_eos)
+      flags |= CLIENTWRITE_EOS;
+    result = Curl_client_write(data, flags, (char *)buf, blen);
   }
-  while(*k->str); /* header line within buffer */
-
-  /* We might have reached the end of the header part here, but
-     there might be a non-header part left in the end of the read
-     buffer. */
-
-  return CURLE_OK;
+out:
+  return result;
 }
 
-
 /* Decode HTTP status code string. */
 CURLcode Curl_http_decode_status(int *pstatus, const char *s, size_t len)
 {
@@ -4618,17 +4031,6 @@ CURLcode Curl_http_decode_status(int *pstatus, const char *s, size_t len)
   return result;
 }
 
-/* simple implementation of strndup(), which isn't portable */
-static char *my_strndup(const char *ptr, size_t len)
-{
-  char *copy = malloc(len + 1);
-  if(!copy)
-    return NULL;
-  memcpy(copy, ptr, len);
-  copy[len] = '\0';
-  return copy;
-}
-
 CURLcode Curl_http_req_make(struct httpreq **preq,
                             const char *method, size_t m_len,
                             const char *scheme, size_t s_len,
@@ -4639,7 +4041,7 @@ CURLcode Curl_http_req_make(struct httpreq **preq,
   CURLcode result = CURLE_OUT_OF_MEMORY;
 
   DEBUGASSERT(method);
-  if(m_len + 1 >= sizeof(req->method))
+  if(m_len + 1 > sizeof(req->method))
     return CURLE_BAD_FUNCTION_ARGUMENT;
 
   req = calloc(1, sizeof(*req));
@@ -4647,17 +4049,17 @@ CURLcode Curl_http_req_make(struct httpreq **preq,
     goto out;
   memcpy(req->method, method, m_len);
   if(scheme) {
-    req->scheme = my_strndup(scheme, s_len);
+    req->scheme = Curl_memdup0(scheme, s_len);
     if(!req->scheme)
       goto out;
   }
   if(authority) {
-    req->authority = my_strndup(authority, a_len);
+    req->authority = Curl_memdup0(authority, a_len);
     if(!req->authority)
       goto out;
   }
   if(path) {
-    req->path = my_strndup(path, p_len);
+    req->path = Curl_memdup0(path, p_len);
     if(!req->path)
       goto out;
   }
@@ -4795,7 +4197,7 @@ CURLcode Curl_http_req_make2(struct httpreq **preq,
   CURLUcode uc;
 
   DEBUGASSERT(method);
-  if(m_len + 1 >= sizeof(req->method))
+  if(m_len + 1 > sizeof(req->method))
     return CURLE_BAD_FUNCTION_ARGUMENT;
 
   req = calloc(1, sizeof(*req));
@@ -4973,4 +4375,142 @@ void Curl_http_resp_free(struct http_resp *resp)
   }
 }
 
+struct cr_exp100_ctx {
+  struct Curl_creader super;
+  struct curltime start; /* time started waiting */
+  enum expect100 state;
+};
+
+/* Expect: 100-continue client reader, blocking uploads */
+
+static void http_exp100_continue(struct Curl_easy *data,
+                                 struct Curl_creader *reader)
+{
+  struct cr_exp100_ctx *ctx = reader->ctx;
+  if(ctx->state > EXP100_SEND_DATA) {
+    ctx->state = EXP100_SEND_DATA;
+    data->req.keepon |= KEEP_SEND;
+    data->req.keepon &= ~KEEP_SEND_TIMED;
+    Curl_expire_done(data, EXPIRE_100_TIMEOUT);
+  }
+}
+
+static CURLcode cr_exp100_read(struct Curl_easy *data,
+                               struct Curl_creader *reader,
+                               char *buf, size_t blen,
+                               size_t *nread, bool *eos)
+{
+  struct cr_exp100_ctx *ctx = reader->ctx;
+  timediff_t ms;
+
+  switch(ctx->state) {
+  case EXP100_SENDING_REQUEST:
+    /* We are now waiting for a reply from the server or
+     * a timeout on our side */
+    DEBUGF(infof(data, "cr_exp100_read, start AWAITING_CONTINUE"));
+    ctx->state = EXP100_AWAITING_CONTINUE;
+    ctx->start = Curl_now();
+    Curl_expire(data, data->set.expect_100_timeout, EXPIRE_100_TIMEOUT);
+    data->req.keepon &= ~KEEP_SEND;
+    data->req.keepon |= KEEP_SEND_TIMED;
+    *nread = 0;
+    *eos = FALSE;
+    return CURLE_OK;
+  case EXP100_FAILED:
+    DEBUGF(infof(data, "cr_exp100_read, expectation failed, error"));
+    *nread = 0;
+    *eos = FALSE;
+    return CURLE_READ_ERROR;
+  case EXP100_AWAITING_CONTINUE:
+    ms = Curl_timediff(Curl_now(), ctx->start);
+    if(ms < data->set.expect_100_timeout) {
+      DEBUGF(infof(data, "cr_exp100_read, AWAITING_CONTINUE, not expired"));
+      data->req.keepon &= ~KEEP_SEND;
+      data->req.keepon |= KEEP_SEND_TIMED;
+      *nread = 0;
+      *eos = FALSE;
+      return CURLE_OK;
+    }
+    /* we've waited long enough, continue anyway */
+    http_exp100_continue(data, reader);
+    infof(data, "Done waiting for 100-continue");
+    FALLTHROUGH();
+  default:
+    DEBUGF(infof(data, "cr_exp100_read, pass through"));
+    return Curl_creader_read(data, reader->next, buf, blen, nread, eos);
+  }
+}
+
+static void cr_exp100_done(struct Curl_easy *data,
+                           struct Curl_creader *reader, int premature)
+{
+  struct cr_exp100_ctx *ctx = reader->ctx;
+  ctx->state = premature? EXP100_FAILED : EXP100_SEND_DATA;
+  data->req.keepon &= ~KEEP_SEND_TIMED;
+  Curl_expire_done(data, EXPIRE_100_TIMEOUT);
+}
+
+static const struct Curl_crtype cr_exp100 = {
+  "cr-exp100",
+  Curl_creader_def_init,
+  cr_exp100_read,
+  Curl_creader_def_close,
+  Curl_creader_def_needs_rewind,
+  Curl_creader_def_total_length,
+  Curl_creader_def_resume_from,
+  Curl_creader_def_rewind,
+  Curl_creader_def_unpause,
+  cr_exp100_done,
+  sizeof(struct cr_exp100_ctx)
+};
+
+static CURLcode http_exp100_add_reader(struct Curl_easy *data)
+{
+  struct Curl_creader *reader = NULL;
+  CURLcode result;
+
+  result = Curl_creader_create(&reader, data, &cr_exp100,
+                               CURL_CR_PROTOCOL);
+  if(!result)
+    result = Curl_creader_add(data, reader);
+  if(!result) {
+    struct cr_exp100_ctx *ctx = reader->ctx;
+    ctx->state = EXP100_SENDING_REQUEST;
+  }
+
+  if(result && reader)
+    Curl_creader_free(data, reader);
+  return result;
+}
+
+void Curl_http_exp100_got100(struct Curl_easy *data)
+{
+  struct Curl_creader *r = Curl_creader_get_by_type(data, &cr_exp100);
+  if(r)
+    http_exp100_continue(data, r);
+}
+
+static bool http_exp100_is_waiting(struct Curl_easy *data)
+{
+  struct Curl_creader *r = Curl_creader_get_by_type(data, &cr_exp100);
+  if(r) {
+    struct cr_exp100_ctx *ctx = r->ctx;
+    return (ctx->state == EXP100_AWAITING_CONTINUE);
+  }
+  return FALSE;
+}
+
+static void http_exp100_send_anyway(struct Curl_easy *data)
+{
+  struct Curl_creader *r = Curl_creader_get_by_type(data, &cr_exp100);
+  if(r)
+    http_exp100_continue(data, r);
+}
+
+bool Curl_http_exp100_is_selected(struct Curl_easy *data)
+{
+  struct Curl_creader *r = Curl_creader_get_by_type(data, &cr_exp100);
+  return r? TRUE : FALSE;
+}
+
 #endif /* CURL_DISABLE_HTTP */
diff --git a/vendor/curl/lib/http.h b/vendor/curl/lib/http.h
index 9ee3c6537c..b0c4f5fd23 100644
--- a/vendor/curl/lib/http.h
+++ b/vendor/curl/lib/http.h
@@ -44,7 +44,7 @@ typedef enum {
 
 #ifndef CURL_DISABLE_HTTP
 
-#if defined(ENABLE_QUIC)
+#if defined(USE_HTTP3)
 #include 
 #endif
 
@@ -54,14 +54,6 @@ extern const struct Curl_handler Curl_handler_http;
 extern const struct Curl_handler Curl_handler_https;
 #endif
 
-#ifdef USE_WEBSOCKETS
-extern const struct Curl_handler Curl_handler_ws;
-
-#ifdef USE_SSL
-extern const struct Curl_handler Curl_handler_wss;
-#endif
-#endif /* websockets */
-
 struct dynhds;
 
 CURLcode Curl_bump_headersize(struct Curl_easy *data,
@@ -82,12 +74,6 @@ char *Curl_checkProxyheaders(struct Curl_easy *data,
                              const char *thisheader,
                              const size_t thislen);
 struct HTTP; /* see below */
-CURLcode Curl_buffer_send(struct dynbuf *in,
-                          struct Curl_easy *data,
-                          struct HTTP *http,
-                          curl_off_t *bytes_written,
-                          curl_off_t included_body_bytes,
-                          int socketindex);
 
 CURLcode Curl_add_timecondition(struct Curl_easy *data,
 #ifndef USE_HYPER
@@ -108,10 +94,6 @@ CURLcode Curl_dynhds_add_custom(struct Curl_easy *data,
                                 bool is_connect,
                                 struct dynhds *hds);
 
-CURLcode Curl_http_compile_trailers(struct curl_slist *trailers,
-                                    struct dynbuf *buf,
-                                    struct Curl_easy *handle);
-
 void Curl_http_method(struct Curl_easy *data, struct connectdata *conn,
                       const char **method, Curl_HttpReq *);
 CURLcode Curl_http_useragent(struct Curl_easy *data);
@@ -120,14 +102,14 @@ CURLcode Curl_http_target(struct Curl_easy *data, struct connectdata *conn,
                           struct dynbuf *req);
 CURLcode Curl_http_statusline(struct Curl_easy *data,
                               struct connectdata *conn);
-CURLcode Curl_http_header(struct Curl_easy *data, struct connectdata *conn,
-                          char *headp);
+CURLcode Curl_http_header(struct Curl_easy *data,
+                          const char *hd, size_t hdlen);
 CURLcode Curl_transferencode(struct Curl_easy *data);
-CURLcode Curl_http_body(struct Curl_easy *data, struct connectdata *conn,
-                        Curl_HttpReq httpreq,
-                        const char **teep);
-CURLcode Curl_http_bodysend(struct Curl_easy *data, struct connectdata *conn,
-                            struct dynbuf *r, Curl_HttpReq httpreq);
+CURLcode Curl_http_req_set_reader(struct Curl_easy *data,
+                                  Curl_HttpReq httpreq,
+                                  const char **tep);
+CURLcode Curl_http_req_complete(struct Curl_easy *data,
+                                struct dynbuf *r, Curl_HttpReq httpreq);
 bool Curl_use_http_1_1plus(const struct Curl_easy *data,
                            const struct connectdata *conn);
 #ifndef CURL_DISABLE_COOKIES
@@ -137,19 +119,24 @@ CURLcode Curl_http_cookies(struct Curl_easy *data,
 #else
 #define Curl_http_cookies(a,b,c) CURLE_OK
 #endif
-CURLcode Curl_http_resume(struct Curl_easy *data,
-                          struct connectdata *conn,
-                          Curl_HttpReq httpreq);
 CURLcode Curl_http_range(struct Curl_easy *data,
                          Curl_HttpReq httpreq);
-CURLcode Curl_http_firstwrite(struct Curl_easy *data,
-                              struct connectdata *conn,
-                              bool *done);
+CURLcode Curl_http_firstwrite(struct Curl_easy *data);
 
 /* protocol-specific functions set up to be called by the main engine */
+CURLcode Curl_http_setup_conn(struct Curl_easy *data,
+                              struct connectdata *conn);
 CURLcode Curl_http(struct Curl_easy *data, bool *done);
 CURLcode Curl_http_done(struct Curl_easy *data, CURLcode, bool premature);
 CURLcode Curl_http_connect(struct Curl_easy *data, bool *done);
+int Curl_http_getsock_do(struct Curl_easy *data, struct connectdata *conn,
+                         curl_socket_t *socks);
+CURLcode Curl_http_write_resp(struct Curl_easy *data,
+                              const char *buf, size_t blen,
+                              bool is_eos);
+CURLcode Curl_http_write_resp_hd(struct Curl_easy *data,
+                                 const char *hd, size_t hdlen,
+                                 bool is_eos);
 
 /* These functions are in http.c */
 CURLcode Curl_http_input_auth(struct Curl_easy *data, bool proxy,
@@ -192,43 +179,24 @@ CURLcode Curl_http_auth_act(struct Curl_easy *data);
    version. This count includes CONNECT response headers. */
 #define MAX_HTTP_RESP_HEADER_SIZE (300*1024)
 
+bool Curl_http_exp100_is_selected(struct Curl_easy *data);
+void Curl_http_exp100_got100(struct Curl_easy *data);
+
 #endif /* CURL_DISABLE_HTTP */
 
 /****************************************************************************
  * HTTP unique setup
  ***************************************************************************/
 struct HTTP {
-  curl_off_t postsize; /* off_t to handle large file sizes */
-  const char *postdata;
-  struct back {
-    curl_read_callback fread_func; /* backup storage for fread pointer */
-    void *fread_in;           /* backup storage for fread_in pointer */
-    const char *postdata;
-    curl_off_t postsize;
-    struct Curl_easy *data;
-  } backup;
-
-  enum {
-    HTTPSEND_NADA,    /* init */
-    HTTPSEND_REQUEST, /* sending a request */
-    HTTPSEND_BODY     /* sending body */
-  } sending;
-
-#ifndef CURL_DISABLE_HTTP
-  void *h2_ctx;              /* HTTP/2 implementation context */
-  void *h3_ctx;              /* HTTP/3 implementation context */
-  struct dynbuf send_buffer; /* used if the request couldn't be sent in one
-                                chunk, points to an allocated send_buffer
-                                struct */
-#endif
+  /* TODO: no longer used, we should remove it from SingleRequest */
+  char unused;
 };
 
 CURLcode Curl_http_size(struct Curl_easy *data);
 
-CURLcode Curl_http_readwrite_headers(struct Curl_easy *data,
-                                     struct connectdata *conn,
-                                     ssize_t *nread,
-                                     bool *stop_reading);
+CURLcode Curl_http_write_resp_hds(struct Curl_easy *data,
+                                  const char *buf, size_t blen,
+                                  size_t *pconsumed);
 
 /**
  * Curl_http_output_auth() setups the authentication headers for the
@@ -263,7 +231,7 @@ CURLcode Curl_http_decode_status(int *pstatus, const char *s, size_t len);
  * All about a core HTTP request, excluding body and trailers
  */
 struct httpreq {
-  char method[12];
+  char method[24];
   char *scheme;
   char *authority;
   char *path;
diff --git a/vendor/curl/lib/http1.c b/vendor/curl/lib/http1.c
index 1ca7d41e8a..182234ca97 100644
--- a/vendor/curl/lib/http1.c
+++ b/vendor/curl/lib/http1.c
@@ -318,5 +318,29 @@ ssize_t Curl_h1_req_parse_read(struct h1_req_parser *parser,
   return nread;
 }
 
+CURLcode Curl_h1_req_write_head(struct httpreq *req, int http_minor,
+                                struct dynbuf *dbuf)
+{
+  CURLcode result;
+
+  result = Curl_dyn_addf(dbuf, "%s %s%s%s%s HTTP/1.%d\r\n",
+                         req->method,
+                         req->scheme? req->scheme : "",
+                         req->scheme? "://" : "",
+                         req->authority? req->authority : "",
+                         req->path? req->path : "",
+                         http_minor);
+  if(result)
+    goto out;
+
+  result = Curl_dynhds_h1_dprint(&req->headers, dbuf);
+  if(result)
+    goto out;
+
+  result = Curl_dyn_addn(dbuf, STRCONST("\r\n"));
+
+out:
+  return result;
+}
 
 #endif /* !CURL_DISABLE_HTTP */
diff --git a/vendor/curl/lib/http1.h b/vendor/curl/lib/http1.h
index b1eaa969d9..2de302f1f6 100644
--- a/vendor/curl/lib/http1.h
+++ b/vendor/curl/lib/http1.h
@@ -56,6 +56,8 @@ ssize_t Curl_h1_req_parse_read(struct h1_req_parser *parser,
 CURLcode Curl_h1_req_dprint(const struct httpreq *req,
                             struct dynbuf *dbuf);
 
+CURLcode Curl_h1_req_write_head(struct httpreq *req, int http_minor,
+                                struct dynbuf *dbuf);
 
 #endif /* !CURL_DISABLE_HTTP */
 #endif /* HEADER_CURL_HTTP1_H */
diff --git a/vendor/curl/lib/http2.c b/vendor/curl/lib/http2.c
index e0cda76d28..f0f7b566e2 100644
--- a/vendor/curl/lib/http2.c
+++ b/vendor/curl/lib/http2.c
@@ -29,6 +29,7 @@
 #include 
 #include "urldata.h"
 #include "bufq.h"
+#include "hash.h"
 #include "http1.h"
 #include "http2.h"
 #include "http.h"
@@ -107,29 +108,31 @@ static int populate_settings(nghttp2_settings_entry *iv,
   return 3;
 }
 
-static size_t populate_binsettings(uint8_t *binsettings,
-                                   struct Curl_easy *data)
+static ssize_t populate_binsettings(uint8_t *binsettings,
+                                    struct Curl_easy *data)
 {
   nghttp2_settings_entry iv[H2_SETTINGS_IV_LEN];
   int ivlen;
 
   ivlen = populate_settings(iv, data);
-  /* this returns number of bytes it wrote */
+  /* this returns number of bytes it wrote or a negative number on error. */
   return nghttp2_pack_settings_payload(binsettings, H2_BINSETTINGS_LEN,
                                        iv, ivlen);
 }
 
 struct cf_h2_ctx {
   nghttp2_session *h2;
-  uint32_t max_concurrent_streams;
   /* The easy handle used in the current filter call, cleared at return */
   struct cf_call_data call_data;
 
   struct bufq inbufq;           /* network input */
   struct bufq outbufq;          /* network output */
   struct bufc_pool stream_bufcp; /* spares for stream buffers */
+  struct dynbuf scratch;        /* scratch buffer for temp use */
 
+  struct Curl_hash streams; /* hash of `data->id` to `h2_stream_ctx` */
   size_t drain_total; /* sum of all stream's UrlState drain */
+  uint32_t max_concurrent_streams;
   int32_t goaway_error;
   int32_t last_stream_id;
   BIT(conn_closed);
@@ -153,6 +156,9 @@ static void cf_h2_ctx_clear(struct cf_h2_ctx *ctx)
   Curl_bufq_free(&ctx->inbufq);
   Curl_bufq_free(&ctx->outbufq);
   Curl_bufcp_free(&ctx->stream_bufcp);
+  Curl_dyn_free(&ctx->scratch);
+  Curl_hash_clean(&ctx->streams);
+  Curl_hash_destroy(&ctx->streams);
   memset(ctx, 0, sizeof(*ctx));
   ctx->call_data = save;
 }
@@ -169,11 +175,9 @@ static CURLcode h2_progress_egress(struct Curl_cfilter *cf,
                                   struct Curl_easy *data);
 
 /**
- * All about the H3 internals of a stream
+ * All about the H2 internals of a stream
  */
-struct stream_ctx {
-  /*********** for HTTP/2 we store stream-local data here *************/
-  int32_t id; /* HTTP/2 protocol identifier for stream */
+struct h2_stream_ctx {
   struct bufq recvbuf; /* response buffer */
   struct bufq sendbuf; /* request buffer */
   struct h1_req_parser h1; /* parsing the request */
@@ -181,6 +185,7 @@ struct stream_ctx {
   size_t resp_hds_len; /* amount of response header bytes in recvbuf */
   size_t upload_blocked_len;
   curl_off_t upload_left; /* number of request bytes left to upload */
+  curl_off_t nrcvd_data;  /* number of DATA bytes received */
 
   char **push_headers;       /* allocated array */
   size_t push_headers_used;  /* number of entries filled in */
@@ -188,29 +193,77 @@ struct stream_ctx {
 
   int status_code; /* HTTP response status code */
   uint32_t error; /* stream error code */
+  CURLcode xfer_result; /* Result of writing out response */
   uint32_t local_window_size; /* the local recv window size */
-  bool resp_hds_complete; /* we have a complete, final response */
-  bool closed; /* TRUE on stream close */
-  bool reset;  /* TRUE on stream reset */
-  bool close_handled; /* TRUE if stream closure is handled by libcurl */
-  bool bodystarted;
-  bool send_closed; /* transfer is done sending, we might have still
-                        buffered data in stream->sendbuf to upload. */
+  int32_t id; /* HTTP/2 protocol identifier for stream */
+  BIT(resp_hds_complete); /* we have a complete, final response */
+  BIT(closed); /* TRUE on stream close */
+  BIT(reset);  /* TRUE on stream reset */
+  BIT(close_handled); /* TRUE if stream closure is handled by libcurl */
+  BIT(bodystarted);
+  BIT(send_closed); /* transfer is done sending, we might have still
+                       buffered data in stream->sendbuf to upload. */
 };
 
-#define H2_STREAM_CTX(d)    ((struct stream_ctx *)(((d) && (d)->req.p.http)? \
-                             ((struct HTTP *)(d)->req.p.http)->h2_ctx \
-                               : NULL))
-#define H2_STREAM_LCTX(d)   ((struct HTTP *)(d)->req.p.http)->h2_ctx
-#define H2_STREAM_ID(d)     (H2_STREAM_CTX(d)? \
-                             H2_STREAM_CTX(d)->id : -2)
+#define H2_STREAM_CTX(ctx,data)   ((struct h2_stream_ctx *)(\
+            data? Curl_hash_offt_get(&(ctx)->streams, (data)->id) : NULL))
+
+static struct h2_stream_ctx *h2_stream_ctx_create(struct cf_h2_ctx *ctx)
+{
+  struct h2_stream_ctx *stream;
+
+  (void)ctx;
+  stream = calloc(1, sizeof(*stream));
+  if(!stream)
+    return NULL;
+
+  stream->id = -1;
+  Curl_bufq_initp(&stream->sendbuf, &ctx->stream_bufcp,
+                  H2_STREAM_SEND_CHUNKS, BUFQ_OPT_NONE);
+  Curl_h1_req_parse_init(&stream->h1, H1_PARSE_DEFAULT_MAX_LINE_LEN);
+  Curl_dynhds_init(&stream->resp_trailers, 0, DYN_HTTP_REQUEST);
+  stream->resp_hds_len = 0;
+  stream->bodystarted = FALSE;
+  stream->status_code = -1;
+  stream->closed = FALSE;
+  stream->close_handled = FALSE;
+  stream->error = NGHTTP2_NO_ERROR;
+  stream->local_window_size = H2_STREAM_WINDOW_SIZE;
+  stream->upload_left = 0;
+  stream->nrcvd_data = 0;
+  return stream;
+}
+
+static void free_push_headers(struct h2_stream_ctx *stream)
+{
+  size_t i;
+  for(i = 0; ipush_headers_used; i++)
+    free(stream->push_headers[i]);
+  Curl_safefree(stream->push_headers);
+  stream->push_headers_used = 0;
+}
+
+static void h2_stream_ctx_free(struct h2_stream_ctx *stream)
+{
+  Curl_bufq_free(&stream->sendbuf);
+  Curl_h1_req_parse_free(&stream->h1);
+  Curl_dynhds_free(&stream->resp_trailers);
+  free_push_headers(stream);
+  free(stream);
+}
+
+static void h2_stream_hash_free(void *stream)
+{
+  DEBUGASSERT(stream);
+  h2_stream_ctx_free((struct h2_stream_ctx *)stream);
+}
 
 /*
  * Mark this transfer to get "drained".
  */
 static void drain_stream(struct Curl_cfilter *cf,
                          struct Curl_easy *data,
-                         struct stream_ctx *stream)
+                         struct h2_stream_ctx *stream)
 {
   unsigned char bits;
 
@@ -219,20 +272,20 @@ static void drain_stream(struct Curl_cfilter *cf,
   if(!stream->send_closed &&
      (stream->upload_left || stream->upload_blocked_len))
     bits |= CURL_CSELECT_OUT;
-  if(data->state.dselect_bits != bits) {
-    CURL_TRC_CF(data, cf, "[%d] DRAIN dselect_bits=%x",
+  if(data->state.select_bits != bits) {
+    CURL_TRC_CF(data, cf, "[%d] DRAIN select_bits=%x",
                 stream->id, bits);
-    data->state.dselect_bits = bits;
+    data->state.select_bits = bits;
     Curl_expire(data, 0, EXPIRE_RUN_NOW);
   }
 }
 
 static CURLcode http2_data_setup(struct Curl_cfilter *cf,
                                  struct Curl_easy *data,
-                                 struct stream_ctx **pstream)
+                                 struct h2_stream_ctx **pstream)
 {
   struct cf_h2_ctx *ctx = cf->ctx;
-  struct stream_ctx *stream;
+  struct h2_stream_ctx *stream;
 
   (void)cf;
   DEBUGASSERT(data);
@@ -240,95 +293,56 @@ static CURLcode http2_data_setup(struct Curl_cfilter *cf,
     failf(data, "initialization failure, transfer not http initialized");
     return CURLE_FAILED_INIT;
   }
-  stream = H2_STREAM_CTX(data);
+  stream = H2_STREAM_CTX(ctx, data);
   if(stream) {
     *pstream = stream;
     return CURLE_OK;
   }
 
-  stream = calloc(1, sizeof(*stream));
+  stream = h2_stream_ctx_create(ctx);
   if(!stream)
     return CURLE_OUT_OF_MEMORY;
 
-  stream->id = -1;
-  Curl_bufq_initp(&stream->sendbuf, &ctx->stream_bufcp,
-                  H2_STREAM_SEND_CHUNKS, BUFQ_OPT_NONE);
-  Curl_bufq_initp(&stream->recvbuf, &ctx->stream_bufcp,
-                  H2_STREAM_RECV_CHUNKS, BUFQ_OPT_SOFT_LIMIT);
-  Curl_h1_req_parse_init(&stream->h1, H1_PARSE_DEFAULT_MAX_LINE_LEN);
-  Curl_dynhds_init(&stream->resp_trailers, 0, DYN_HTTP_REQUEST);
-  stream->resp_hds_len = 0;
-  stream->bodystarted = FALSE;
-  stream->status_code = -1;
-  stream->closed = FALSE;
-  stream->close_handled = FALSE;
-  stream->error = NGHTTP2_NO_ERROR;
-  stream->local_window_size = H2_STREAM_WINDOW_SIZE;
-  stream->upload_left = 0;
+  if(!Curl_hash_offt_set(&ctx->streams, data->id, stream)) {
+    h2_stream_ctx_free(stream);
+    return CURLE_OUT_OF_MEMORY;
+  }
 
-  H2_STREAM_LCTX(data) = stream;
   *pstream = stream;
   return CURLE_OK;
 }
 
-static void http2_data_done(struct Curl_cfilter *cf,
-                            struct Curl_easy *data, bool premature)
+static void http2_data_done(struct Curl_cfilter *cf, struct Curl_easy *data)
 {
   struct cf_h2_ctx *ctx = cf->ctx;
-  struct stream_ctx *stream = H2_STREAM_CTX(data);
+  struct h2_stream_ctx *stream = H2_STREAM_CTX(ctx, data);
 
   DEBUGASSERT(ctx);
-  (void)premature;
   if(!stream)
     return;
 
   if(ctx->h2) {
+    bool flush_egress = FALSE;
+    /* returns error if stream not known, which is fine here */
+    (void)nghttp2_session_set_stream_user_data(ctx->h2, stream->id, NULL);
+
     if(!stream->closed && stream->id > 0) {
       /* RST_STREAM */
       CURL_TRC_CF(data, cf, "[%d] premature DATA_DONE, RST stream",
                   stream->id);
-      if(!nghttp2_submit_rst_stream(ctx->h2, NGHTTP2_FLAG_NONE,
-                                    stream->id, NGHTTP2_STREAM_CLOSED))
-        (void)nghttp2_session_send(ctx->h2);
-    }
-    if(!Curl_bufq_is_empty(&stream->recvbuf)) {
-      /* Anything in the recvbuf is still being counted
-       * in stream and connection window flow control. Need
-       * to free that space or the connection window might get
-       * exhausted eventually. */
-      nghttp2_session_consume(ctx->h2, stream->id,
-                              Curl_bufq_len(&stream->recvbuf));
-      /* give WINDOW_UPATE a chance to be sent, but ignore any error */
-      (void)h2_progress_egress(cf, data);
-    }
-
-    /* -1 means unassigned and 0 means cleared */
-    if(nghttp2_session_get_stream_user_data(ctx->h2, stream->id)) {
-      int rv = nghttp2_session_set_stream_user_data(ctx->h2,
-                                                    stream->id, 0);
-      if(rv) {
-        infof(data, "http/2: failed to clear user_data for stream %u",
-              stream->id);
-        DEBUGASSERT(0);
-      }
+      stream->closed = TRUE;
+      stream->reset = TRUE;
+      stream->send_closed = TRUE;
+      nghttp2_submit_rst_stream(ctx->h2, NGHTTP2_FLAG_NONE,
+                                stream->id, NGHTTP2_STREAM_CLOSED);
+      flush_egress = TRUE;
     }
-  }
 
-  Curl_bufq_free(&stream->sendbuf);
-  Curl_bufq_free(&stream->recvbuf);
-  Curl_h1_req_parse_free(&stream->h1);
-  Curl_dynhds_free(&stream->resp_trailers);
-  if(stream->push_headers) {
-    /* if they weren't used and then freed before */
-    for(; stream->push_headers_used > 0; --stream->push_headers_used) {
-      free(stream->push_headers[stream->push_headers_used - 1]);
-    }
-    free(stream->push_headers);
-    stream->push_headers = NULL;
+    if(flush_egress)
+      nghttp2_session_send(ctx->h2);
   }
 
-  free(stream);
-  H2_STREAM_LCTX(data) = NULL;
+  Curl_hash_offt_remove(&ctx->streams, data->id);
 }
 
 static int h2_client_new(struct Curl_cfilter *cf,
@@ -369,12 +383,15 @@ static ssize_t nw_out_writer(void *writer_ctx,
 {
   struct Curl_cfilter *cf = writer_ctx;
   struct Curl_easy *data = CF_DATA_CURRENT(cf);
-  ssize_t nwritten;
 
-  nwritten = Curl_conn_cf_send(cf->next, data, (const char *)buf, buflen, err);
-  if(nwritten > 0)
-    CURL_TRC_CF(data, cf, "[0] egress: wrote %zd bytes", nwritten);
-  return nwritten;
+  if(data) {
+    ssize_t nwritten = Curl_conn_cf_send(cf->next, data,
+                                         (const char *)buf, buflen, err);
+    if(nwritten > 0)
+      CURL_TRC_CF(data, cf, "[0] egress: wrote %zd bytes", nwritten);
+    return nwritten;
+  }
+  return 0;
 }
 
 static ssize_t send_callback(nghttp2_session *h2,
@@ -409,7 +426,7 @@ static CURLcode cf_h2_ctx_init(struct Curl_cfilter *cf,
                                bool via_h1_upgrade)
 {
   struct cf_h2_ctx *ctx = cf->ctx;
-  struct stream_ctx *stream;
+  struct h2_stream_ctx *stream;
   CURLcode result = CURLE_OUT_OF_MEMORY;
   int rc;
   nghttp2_session_callbacks *cbs = NULL;
@@ -418,6 +435,8 @@ static CURLcode cf_h2_ctx_init(struct Curl_cfilter *cf,
   Curl_bufcp_init(&ctx->stream_bufcp, H2_CHUNK_SIZE, H2_STREAM_POOL_SPARES);
   Curl_bufq_initp(&ctx->inbufq, &ctx->stream_bufcp, H2_NW_RECV_CHUNKS, 0);
   Curl_bufq_initp(&ctx->outbufq, &ctx->stream_bufcp, H2_NW_SEND_CHUNKS, 0);
+  Curl_dyn_init(&ctx->scratch, CURL_MAX_HTTP_HEADER);
+  Curl_hash_offt_init(&ctx->streams, 63, h2_stream_hash_free);
   ctx->last_stream_id = 2147483647;
 
   rc = nghttp2_session_callbacks_new(&cbs);
@@ -452,9 +471,14 @@ static CURLcode cf_h2_ctx_init(struct Curl_cfilter *cf,
      * in the H1 request and we upgrade from there. This stream
      * is opened implicitly as #1. */
     uint8_t binsettings[H2_BINSETTINGS_LEN];
-    size_t  binlen; /* length of the binsettings data */
+    ssize_t binlen; /* length of the binsettings data */
 
     binlen = populate_binsettings(binsettings, data);
+    if(binlen <= 0) {
+      failf(data, "nghttp2 unexpectedly failed on pack_settings_payload");
+      result = CURLE_FAILED_INIT;
+      goto out;
+    }
 
     result = http2_data_setup(cf, data, &stream);
     if(result)
@@ -711,6 +735,7 @@ static ssize_t send_callback(nghttp2_session *h2,
    the struct are hidden from the user. */
 struct curl_pushheaders {
   struct Curl_easy *data;
+  struct h2_stream_ctx *stream;
   const nghttp2_push_promise *frame;
 };
 
@@ -724,9 +749,8 @@ char *curl_pushheader_bynum(struct curl_pushheaders *h, size_t num)
   if(!h || !GOOD_EASY_HANDLE(h->data))
     return NULL;
   else {
-    struct stream_ctx *stream = H2_STREAM_CTX(h->data);
-    if(stream && num < stream->push_headers_used)
-      return stream->push_headers[num];
+    if(h->stream && num < h->stream->push_headers_used)
+      return h->stream->push_headers[num];
   }
   return NULL;
 }
@@ -736,7 +760,7 @@ char *curl_pushheader_bynum(struct curl_pushheaders *h, size_t num)
  */
 char *curl_pushheader_byname(struct curl_pushheaders *h, const char *header)
 {
-  struct stream_ctx *stream;
+  struct h2_stream_ctx *stream;
   size_t len;
   size_t i;
   /* Verify that we got a good easy handle in the push header struct,
@@ -749,7 +773,7 @@ char *curl_pushheader_byname(struct curl_pushheaders *h, const char *header)
      !strcmp(header, ":") || strchr(header + 1, ':'))
     return NULL;
 
-  stream = H2_STREAM_CTX(h->data);
+  stream = h->stream;
   if(!stream)
     return NULL;
 
@@ -776,7 +800,7 @@ static struct Curl_easy *h2_duphandle(struct Curl_cfilter *cf,
       (void)Curl_close(&second);
     }
     else {
-      struct stream_ctx *second_stream;
+      struct h2_stream_ctx *second_stream;
 
       second->req.p.http = http;
       http2_data_setup(cf, second, &second_stream);
@@ -809,7 +833,7 @@ static int set_transfer_url(struct Curl_easy *data,
 
   v = curl_pushheader_byname(hp, HTTP_PSEUDO_AUTHORITY);
   if(v) {
-    uc = Curl_url_set_authority(u, v, CURLU_DISALLOW_USER);
+    uc = Curl_url_set_authority(u, v);
     if(uc) {
       rc = 2;
       goto fail;
@@ -843,9 +867,8 @@ static int set_transfer_url(struct Curl_easy *data,
 static void discard_newhandle(struct Curl_cfilter *cf,
                               struct Curl_easy *newhandle)
 {
-  if(!newhandle->req.p.http) {
-    http2_data_done(cf, newhandle, TRUE);
-    newhandle->req.p.http = NULL;
+  if(newhandle->req.p.http) {
+    http2_data_done(cf, newhandle);
   }
   (void)Curl_close(&newhandle);
 }
@@ -860,12 +883,11 @@ static int push_promise(struct Curl_cfilter *cf,
   CURL_TRC_CF(data, cf, "[%d] PUSH_PROMISE received",
               frame->promised_stream_id);
   if(data->multi->push_cb) {
-    struct stream_ctx *stream;
-    struct stream_ctx *newstream;
+    struct h2_stream_ctx *stream;
+    struct h2_stream_ctx *newstream;
     struct curl_pushheaders heads;
     CURLMcode rc;
     CURLcode result;
-    size_t i;
     /* clone the parent */
     struct Curl_easy *newhandle = h2_duphandle(cf, data);
     if(!newhandle) {
@@ -874,12 +896,10 @@ static int push_promise(struct Curl_cfilter *cf,
       goto fail;
     }
 
-    heads.data = data;
-    heads.frame = frame;
     /* ask the application */
     CURL_TRC_CF(data, cf, "Got PUSH_PROMISE, ask application");
 
-    stream = H2_STREAM_CTX(data);
+    stream = H2_STREAM_CTX(ctx, data);
     if(!stream) {
       failf(data, "Internal NULL stream");
       discard_newhandle(cf, newhandle);
@@ -887,6 +907,10 @@ static int push_promise(struct Curl_cfilter *cf,
       goto fail;
     }
 
+    heads.data = data;
+    heads.stream = stream;
+    heads.frame = frame;
+
     rv = set_transfer_url(newhandle, &heads);
     if(rv) {
       discard_newhandle(cf, newhandle);
@@ -910,11 +934,7 @@ static int push_promise(struct Curl_cfilter *cf,
     Curl_set_in_callback(data, false);
 
     /* free the headers again */
-    for(i = 0; ipush_headers_used; i++)
-      free(stream->push_headers[i]);
-    free(stream->push_headers);
-    stream->push_headers = NULL;
-    stream->push_headers_used = 0;
+    free_push_headers(stream);
 
     if(rv) {
       DEBUGASSERT((rv > CURL_PUSH_OK) && (rv <= CURL_PUSH_ERROROUT));
@@ -956,22 +976,39 @@ static int push_promise(struct Curl_cfilter *cf,
   return rv;
 }
 
-static CURLcode recvbuf_write_hds(struct Curl_cfilter *cf,
+static void h2_xfer_write_resp_hd(struct Curl_cfilter *cf,
                                   struct Curl_easy *data,
-                                  const char *buf, size_t blen)
+                                  struct h2_stream_ctx *stream,
+                                  const char *buf, size_t blen, bool eos)
 {
-  struct stream_ctx *stream = H2_STREAM_CTX(data);
-  ssize_t nwritten;
-  CURLcode result;
 
-  (void)cf;
-  nwritten = Curl_bufq_write(&stream->recvbuf,
-                             (const unsigned char *)buf, blen, &result);
-  if(nwritten < 0)
-    return result;
-  stream->resp_hds_len += (size_t)nwritten;
-  DEBUGASSERT((size_t)nwritten == blen);
-  return CURLE_OK;
+  /* If we already encountered an error, skip further writes */
+  if(!stream->xfer_result) {
+    stream->xfer_result = Curl_xfer_write_resp_hd(data, buf, blen, eos);
+    if(stream->xfer_result)
+      CURL_TRC_CF(data, cf, "[%d] error %d writing %zu bytes of headers",
+                  stream->id, stream->xfer_result, blen);
+  }
+}
+
+static void h2_xfer_write_resp(struct Curl_cfilter *cf,
+                               struct Curl_easy *data,
+                               struct h2_stream_ctx *stream,
+                               const char *buf, size_t blen, bool eos)
+{
+
+  /* If we already encountered an error, skip further writes */
+  if(!stream->xfer_result)
+    stream->xfer_result = Curl_xfer_write_resp(data, buf, blen, eos);
+  /* If the transfer write is errored, we do not want any more data */
+  if(stream->xfer_result) {
+    struct cf_h2_ctx *ctx = cf->ctx;
+    CURL_TRC_CF(data, cf, "[%d] error %d writing %zu bytes of data, "
+                "RST-ing stream",
+                stream->id, stream->xfer_result, blen);
+    nghttp2_submit_rst_stream(ctx->h2, 0, stream->id,
+                              NGHTTP2_ERR_CALLBACK_FAILURE);
+  }
 }
 
 static CURLcode on_stream_frame(struct Curl_cfilter *cf,
@@ -979,10 +1016,8 @@ static CURLcode on_stream_frame(struct Curl_cfilter *cf,
                                 const nghttp2_frame *frame)
 {
   struct cf_h2_ctx *ctx = cf->ctx;
-  struct stream_ctx *stream = H2_STREAM_CTX(data);
+  struct h2_stream_ctx *stream = H2_STREAM_CTX(ctx, data);
   int32_t stream_id = frame->hd.stream_id;
-  CURLcode result;
-  size_t rbuflen;
   int rv;
 
   if(!stream) {
@@ -992,9 +1027,8 @@ static CURLcode on_stream_frame(struct Curl_cfilter *cf,
 
   switch(frame->hd.type) {
   case NGHTTP2_DATA:
-    rbuflen = Curl_bufq_len(&stream->recvbuf);
-    CURL_TRC_CF(data, cf, "[%d] DATA, buffered=%zu, window=%d/%d",
-                stream_id, rbuflen,
+    CURL_TRC_CF(data, cf, "[%d] DATA, window=%d/%d",
+                stream_id,
                 nghttp2_session_get_stream_effective_recv_data_length(
                   ctx->h2, stream->id),
                 nghttp2_session_get_stream_effective_local_window_size(
@@ -1011,20 +1045,6 @@ static CURLcode on_stream_frame(struct Curl_cfilter *cf,
     if(frame->hd.flags & NGHTTP2_FLAG_END_STREAM) {
       drain_stream(cf, data, stream);
     }
-    else if(rbuflen > stream->local_window_size) {
-      int32_t wsize = nghttp2_session_get_stream_local_window_size(
-                        ctx->h2, stream->id);
-      if(wsize > 0 && (uint32_t)wsize != stream->local_window_size) {
-        /* H2 flow control is not absolute, as the server might not have the
-         * same view, yet. When we receive more than we want, we enforce
-         * the local window size again to make nghttp2 send WINDOW_UPATEs
-         * accordingly. */
-        nghttp2_session_set_local_window_size(ctx->h2,
-                                              NGHTTP2_FLAG_NONE,
-                                              stream->id,
-                                              stream->local_window_size);
-      }
-    }
     break;
   case NGHTTP2_HEADERS:
     if(stream->bodystarted) {
@@ -1045,9 +1065,7 @@ static CURLcode on_stream_frame(struct Curl_cfilter *cf,
       stream->status_code = -1;
     }
 
-    result = recvbuf_write_hds(cf, data, STRCONST("\r\n"));
-    if(result)
-      return result;
+    h2_xfer_write_resp_hd(cf, data, stream, STRCONST("\r\n"), stream->closed);
 
     if(stream->status_code / 100 != 1) {
       stream->resp_hds_complete = TRUE;
@@ -1076,16 +1094,11 @@ static CURLcode on_stream_frame(struct Curl_cfilter *cf,
       stream->reset = TRUE;
     }
     stream->send_closed = TRUE;
-    data->req.keepon &= ~KEEP_SEND_HOLD;
     drain_stream(cf, data, stream);
     break;
   case NGHTTP2_WINDOW_UPDATE:
-    if((data->req.keepon & KEEP_SEND_HOLD) &&
-       (data->req.keepon & KEEP_SEND)) {
-      data->req.keepon &= ~KEEP_SEND_HOLD;
+    if(CURL_WANT_SEND(data)) {
       drain_stream(cf, data, stream);
-      CURL_TRC_CF(data, cf, "[%d] un-holding after win update",
-                  stream_id);
     }
     break;
   default:
@@ -1230,15 +1243,10 @@ static int on_frame_recv(nghttp2_session *session, const nghttp2_frame *frame,
          * window and *assume* that we treat this like a WINDOW_UPDATE. Some
          * servers send an explicit WINDOW_UPDATE, but not all seem to do that.
          * To be safe, we UNHOLD a stream in order not to stall. */
-        if((data->req.keepon & KEEP_SEND_HOLD) &&
-           (data->req.keepon & KEEP_SEND)) {
-          struct stream_ctx *stream = H2_STREAM_CTX(data);
-          data->req.keepon &= ~KEEP_SEND_HOLD;
-          if(stream) {
+        if(CURL_WANT_SEND(data)) {
+          struct h2_stream_ctx *stream = H2_STREAM_CTX(ctx, data);
+          if(stream)
             drain_stream(cf, data, stream);
-            CURL_TRC_CF(data, cf, "[%d] un-holding after SETTINGS",
-                        stream_id);
-          }
         }
       }
       break;
@@ -1273,10 +1281,9 @@ static int on_data_chunk_recv(nghttp2_session *session, uint8_t flags,
                               const uint8_t *mem, size_t len, void *userp)
 {
   struct Curl_cfilter *cf = userp;
-  struct stream_ctx *stream;
+  struct cf_h2_ctx *ctx = cf->ctx;
+  struct h2_stream_ctx *stream;
   struct Curl_easy *data_s;
-  ssize_t nwritten;
-  CURLcode result;
   (void)flags;
 
   DEBUGASSERT(stream_id); /* should never be a zero stream ID here */
@@ -1295,22 +1302,17 @@ static int on_data_chunk_recv(nghttp2_session *session, uint8_t flags,
     return 0;
   }
 
-  stream = H2_STREAM_CTX(data_s);
+  stream = H2_STREAM_CTX(ctx, data_s);
   if(!stream)
     return NGHTTP2_ERR_CALLBACK_FAILURE;
 
-  nwritten = Curl_bufq_write(&stream->recvbuf, mem, len, &result);
-  if(nwritten < 0) {
-    if(result != CURLE_AGAIN)
-      return NGHTTP2_ERR_CALLBACK_FAILURE;
+  h2_xfer_write_resp(cf, data_s, stream, (char *)mem, len, FALSE);
 
-    nwritten = 0;
-  }
+  nghttp2_session_consume(ctx->h2, stream_id, len);
+  stream->nrcvd_data += (curl_off_t)len;
 
   /* if we receive data for another handle, wake that up */
   drain_stream(cf, data_s, stream);
-
-  DEBUGASSERT((size_t)nwritten == len);
   return 0;
 }
 
@@ -1318,27 +1320,44 @@ static int on_stream_close(nghttp2_session *session, int32_t stream_id,
                            uint32_t error_code, void *userp)
 {
   struct Curl_cfilter *cf = userp;
-  struct Curl_easy *data_s;
-  struct stream_ctx *stream;
+  struct cf_h2_ctx *ctx = cf->ctx;
+  struct Curl_easy *data_s, *call_data = CF_DATA_CURRENT(cf);
+  struct h2_stream_ctx *stream;
   int rv;
   (void)session;
 
+  DEBUGASSERT(call_data);
   /* get the stream from the hash based on Stream ID, stream ID zero is for
      connection-oriented stuff */
   data_s = stream_id?
              nghttp2_session_get_stream_user_data(session, stream_id) : NULL;
   if(!data_s) {
+    CURL_TRC_CF(call_data, cf,
+                "[%d] on_stream_close, no easy set on stream", stream_id);
     return 0;
   }
-  stream = H2_STREAM_CTX(data_s);
-  if(!stream)
+  if(!GOOD_EASY_HANDLE(data_s)) {
+    /* nghttp2 still has an easy registered for the stream which has
+     * been freed be libcurl. This points to a code path that does not
+     * trigger DONE or DETACH events as it must. */
+    CURL_TRC_CF(call_data, cf,
+                "[%d] on_stream_close, not a GOOD easy on stream", stream_id);
+    (void)nghttp2_session_set_stream_user_data(session, stream_id, 0);
     return NGHTTP2_ERR_CALLBACK_FAILURE;
+  }
+  stream = H2_STREAM_CTX(ctx, data_s);
+  if(!stream) {
+    CURL_TRC_CF(data_s, cf,
+                "[%d] on_stream_close, GOOD easy but no stream", stream_id);
+    return NGHTTP2_ERR_CALLBACK_FAILURE;
+  }
 
   stream->closed = TRUE;
   stream->error = error_code;
-  if(stream->error)
+  if(stream->error) {
     stream->reset = TRUE;
-  data_s->req.keepon &= ~KEEP_SEND_HOLD;
+    stream->send_closed = TRUE;
+  }
 
   if(stream->error)
     CURL_TRC_CF(data_s, cf, "[%d] RESET: %s (err %d)",
@@ -1361,7 +1380,8 @@ static int on_begin_headers(nghttp2_session *session,
                             const nghttp2_frame *frame, void *userp)
 {
   struct Curl_cfilter *cf = userp;
-  struct stream_ctx *stream;
+  struct cf_h2_ctx *ctx = cf->ctx;
+  struct h2_stream_ctx *stream;
   struct Curl_easy *data_s = NULL;
 
   (void)cf;
@@ -1374,7 +1394,7 @@ static int on_begin_headers(nghttp2_session *session,
     return 0;
   }
 
-  stream = H2_STREAM_CTX(data_s);
+  stream = H2_STREAM_CTX(ctx, data_s);
   if(!stream || !stream->bodystarted) {
     return 0;
   }
@@ -1390,7 +1410,8 @@ static int on_header(nghttp2_session *session, const nghttp2_frame *frame,
                      void *userp)
 {
   struct Curl_cfilter *cf = userp;
-  struct stream_ctx *stream;
+  struct cf_h2_ctx *ctx = cf->ctx;
+  struct h2_stream_ctx *stream;
   struct Curl_easy *data_s;
   int32_t stream_id = frame->hd.stream_id;
   CURLcode result;
@@ -1405,7 +1426,7 @@ static int on_header(nghttp2_session *session, const nghttp2_frame *frame,
        internal error more than anything else! */
     return NGHTTP2_ERR_CALLBACK_FAILURE;
 
-  stream = H2_STREAM_CTX(data_s);
+  stream = H2_STREAM_CTX(ctx, data_s);
   if(!stream) {
     failf(data_s, "Internal NULL stream");
     return NGHTTP2_ERR_CALLBACK_FAILURE;
@@ -1446,7 +1467,7 @@ static int on_header(nghttp2_session *session, const nghttp2_frame *frame,
       stream->push_headers = malloc(stream->push_headers_alloc *
                                     sizeof(char *));
       if(!stream->push_headers)
-        return NGHTTP2_ERR_TEMPORAL_CALLBACK_FAILURE;
+        return NGHTTP2_ERR_CALLBACK_FAILURE;
       stream->push_headers_used = 0;
     }
     else if(stream->push_headers_used ==
@@ -1455,15 +1476,15 @@ static int on_header(nghttp2_session *session, const nghttp2_frame *frame,
       if(stream->push_headers_alloc > 1000) {
         /* this is beyond crazy many headers, bail out */
         failf(data_s, "Too many PUSH_PROMISE headers");
-        Curl_safefree(stream->push_headers);
-        return NGHTTP2_ERR_TEMPORAL_CALLBACK_FAILURE;
+        free_push_headers(stream);
+        return NGHTTP2_ERR_CALLBACK_FAILURE;
       }
       stream->push_headers_alloc *= 2;
-      headp = Curl_saferealloc(stream->push_headers,
-                               stream->push_headers_alloc * sizeof(char *));
+      headp = realloc(stream->push_headers,
+                      stream->push_headers_alloc * sizeof(char *));
       if(!headp) {
-        stream->push_headers = NULL;
-        return NGHTTP2_ERR_TEMPORAL_CALLBACK_FAILURE;
+        free_push_headers(stream);
+        return NGHTTP2_ERR_CALLBACK_FAILURE;
       }
       stream->push_headers = headp;
     }
@@ -1499,14 +1520,15 @@ static int on_header(nghttp2_session *session, const nghttp2_frame *frame,
     result = Curl_headers_push(data_s, buffer, CURLH_PSEUDO);
     if(result)
       return NGHTTP2_ERR_CALLBACK_FAILURE;
-    result = recvbuf_write_hds(cf, data_s, STRCONST("HTTP/2 "));
-    if(result)
-      return NGHTTP2_ERR_CALLBACK_FAILURE;
-    result = recvbuf_write_hds(cf, data_s, (const char *)value, valuelen);
-    if(result)
-      return NGHTTP2_ERR_CALLBACK_FAILURE;
-    /* the space character after the status code is mandatory */
-    result = recvbuf_write_hds(cf, data_s, STRCONST(" \r\n"));
+    Curl_dyn_reset(&ctx->scratch);
+    result = Curl_dyn_addn(&ctx->scratch, STRCONST("HTTP/2 "));
+    if(!result)
+      result = Curl_dyn_addn(&ctx->scratch, value, valuelen);
+    if(!result)
+      result = Curl_dyn_addn(&ctx->scratch, STRCONST(" \r\n"));
+    if(!result)
+      h2_xfer_write_resp_hd(cf, data_s, stream, Curl_dyn_ptr(&ctx->scratch),
+                            Curl_dyn_len(&ctx->scratch), FALSE);
     if(result)
       return NGHTTP2_ERR_CALLBACK_FAILURE;
     /* if we receive data for another handle, wake that up */
@@ -1521,16 +1543,17 @@ static int on_header(nghttp2_session *session, const nghttp2_frame *frame,
   /* nghttp2 guarantees that namelen > 0, and :status was already
      received, and this is not pseudo-header field . */
   /* convert to an HTTP1-style header */
-  result = recvbuf_write_hds(cf, data_s, (const char *)name, namelen);
-  if(result)
-    return NGHTTP2_ERR_CALLBACK_FAILURE;
-  result = recvbuf_write_hds(cf, data_s, STRCONST(": "));
-  if(result)
-    return NGHTTP2_ERR_CALLBACK_FAILURE;
-  result = recvbuf_write_hds(cf, data_s, (const char *)value, valuelen);
-  if(result)
-    return NGHTTP2_ERR_CALLBACK_FAILURE;
-  result = recvbuf_write_hds(cf, data_s, STRCONST("\r\n"));
+  Curl_dyn_reset(&ctx->scratch);
+  result = Curl_dyn_addn(&ctx->scratch, (const char *)name, namelen);
+  if(!result)
+    result = Curl_dyn_addn(&ctx->scratch, STRCONST(": "));
+  if(!result)
+    result = Curl_dyn_addn(&ctx->scratch, (const char *)value, valuelen);
+  if(!result)
+    result = Curl_dyn_addn(&ctx->scratch, STRCONST("\r\n"));
+  if(!result)
+    h2_xfer_write_resp_hd(cf, data_s, stream, Curl_dyn_ptr(&ctx->scratch),
+                          Curl_dyn_len(&ctx->scratch), FALSE);
   if(result)
     return NGHTTP2_ERR_CALLBACK_FAILURE;
   /* if we receive data for another handle, wake that up */
@@ -1551,8 +1574,9 @@ static ssize_t req_body_read_callback(nghttp2_session *session,
                                       void *userp)
 {
   struct Curl_cfilter *cf = userp;
+  struct cf_h2_ctx *ctx = cf->ctx;
   struct Curl_easy *data_s;
-  struct stream_ctx *stream = NULL;
+  struct h2_stream_ctx *stream = NULL;
   CURLcode result;
   ssize_t nread;
   (void)source;
@@ -1567,7 +1591,7 @@ static ssize_t req_body_read_callback(nghttp2_session *session,
          internal error more than anything else! */
       return NGHTTP2_ERR_CALLBACK_FAILURE;
 
-    stream = H2_STREAM_CTX(data_s);
+    stream = H2_STREAM_CTX(ctx, data_s);
     if(!stream)
       return NGHTTP2_ERR_CALLBACK_FAILURE;
   }
@@ -1602,10 +1626,10 @@ static int error_callback(nghttp2_session *session,
                           size_t len,
                           void *userp)
 {
+  struct Curl_cfilter *cf = userp;
+  struct Curl_easy *data = CF_DATA_CURRENT(cf);
   (void)session;
-  (void)msg;
-  (void)len;
-  (void)userp;
+  failf(data, "%.*s", (int)len, msg);
   return 0;
 }
 #endif
@@ -1621,7 +1645,7 @@ CURLcode Curl_http2_request_upgrade(struct dynbuf *req,
   size_t blen;
   struct SingleRequest *k = &data->req;
   uint8_t binsettings[H2_BINSETTINGS_LEN];
-  size_t  binlen; /* length of the binsettings data */
+  ssize_t binlen; /* length of the binsettings data */
 
   binlen = populate_binsettings(binsettings, data);
   if(binlen <= 0) {
@@ -1654,7 +1678,7 @@ static CURLcode http2_data_done_send(struct Curl_cfilter *cf,
 {
   struct cf_h2_ctx *ctx = cf->ctx;
   CURLcode result = CURLE_OK;
-  struct stream_ctx *stream = H2_STREAM_CTX(data);
+  struct h2_stream_ctx *stream = H2_STREAM_CTX(ctx, data);
 
   if(!ctx || !ctx->h2 || !stream)
     goto out;
@@ -1678,7 +1702,7 @@ static CURLcode http2_data_done_send(struct Curl_cfilter *cf,
 
 static ssize_t http2_handle_stream_close(struct Curl_cfilter *cf,
                                          struct Curl_easy *data,
-                                         struct stream_ctx *stream,
+                                         struct h2_stream_ctx *stream,
                                          CURLcode *err)
 {
   ssize_t rv = 0;
@@ -1688,10 +1712,19 @@ static ssize_t http2_handle_stream_close(struct Curl_cfilter *cf,
                 "connection", stream->id);
     connclose(cf->conn, "REFUSED_STREAM"); /* don't use this anymore */
     data->state.refused_stream = TRUE;
-    *err = CURLE_SEND_ERROR; /* trigger Curl_retry_request() later */
+    *err = CURLE_RECV_ERROR; /* trigger Curl_retry_request() later */
     return -1;
   }
   else if(stream->error != NGHTTP2_NO_ERROR) {
+    if(stream->resp_hds_complete && data->req.no_body) {
+      CURL_TRC_CF(data, cf, "[%d] error after response headers, but we did "
+                  "not want a body anyway, ignore: %s (err %u)",
+                  stream->id, nghttp2_http2_strerror(stream->error),
+                  stream->error);
+      stream->close_handled = TRUE;
+      *err = CURLE_OK;
+      goto out;
+    }
     failf(data, "HTTP/2 stream %u was not closed cleanly: %s (err %u)",
           stream->id, nghttp2_http2_strerror(stream->error),
           stream->error);
@@ -1700,7 +1733,7 @@ static ssize_t http2_handle_stream_close(struct Curl_cfilter *cf,
   }
   else if(stream->reset) {
     failf(data, "HTTP/2 stream %u was reset", stream->id);
-    *err = stream->bodystarted? CURLE_PARTIAL_FILE : CURLE_RECV_ERROR;
+    *err = data->req.bytecount? CURLE_PARTIAL_FILE : CURLE_HTTP2;
     return -1;
   }
 
@@ -1770,11 +1803,12 @@ static int sweight_in_effect(const struct Curl_easy *data)
  * struct.
  */
 
-static void h2_pri_spec(struct Curl_easy *data,
+static void h2_pri_spec(struct cf_h2_ctx *ctx,
+                        struct Curl_easy *data,
                         nghttp2_priority_spec *pri_spec)
 {
   struct Curl_data_priority *prio = &data->set.priority;
-  struct stream_ctx *depstream = H2_STREAM_CTX(prio->parent);
+  struct h2_stream_ctx *depstream = H2_STREAM_CTX(ctx, prio->parent);
   int32_t depstream_id = depstream? depstream->id:0;
   nghttp2_priority_spec_init(pri_spec, depstream_id,
                              sweight_wanted(data),
@@ -1792,7 +1826,7 @@ static CURLcode h2_progress_egress(struct Curl_cfilter *cf,
                                   struct Curl_easy *data)
 {
   struct cf_h2_ctx *ctx = cf->ctx;
-  struct stream_ctx *stream = H2_STREAM_CTX(data);
+  struct h2_stream_ctx *stream = H2_STREAM_CTX(ctx, data);
   int rv = 0;
 
   if(stream && stream->id > 0 &&
@@ -1802,7 +1836,7 @@ static CURLcode h2_progress_egress(struct Curl_cfilter *cf,
     /* send new weight and/or dependency */
     nghttp2_priority_spec pri_spec;
 
-    h2_pri_spec(data, &pri_spec);
+    h2_pri_spec(ctx, data, &pri_spec);
     CURL_TRC_CF(data, cf, "[%d] Queuing PRIORITY", stream->id);
     DEBUGASSERT(stream->id != -1);
     rv = nghttp2_submit_priority(ctx->h2, NGHTTP2_FLAG_NONE,
@@ -1825,40 +1859,31 @@ static CURLcode h2_progress_egress(struct Curl_cfilter *cf,
 }
 
 static ssize_t stream_recv(struct Curl_cfilter *cf, struct Curl_easy *data,
-                           struct stream_ctx *stream,
+                           struct h2_stream_ctx *stream,
                            char *buf, size_t len, CURLcode *err)
 {
   struct cf_h2_ctx *ctx = cf->ctx;
   ssize_t nread = -1;
 
+  (void)buf;
   *err = CURLE_AGAIN;
-  if(!Curl_bufq_is_empty(&stream->recvbuf)) {
-    nread = Curl_bufq_read(&stream->recvbuf,
-                           (unsigned char *)buf, len, err);
-    if(nread < 0)
-      goto out;
-    DEBUGASSERT(nread > 0);
+  if(stream->xfer_result) {
+    CURL_TRC_CF(data, cf, "[%d] xfer write failed", stream->id);
+    *err = stream->xfer_result;
+    nread = -1;
   }
-
-  if(nread < 0) {
-    if(stream->closed) {
-      CURL_TRC_CF(data, cf, "[%d] returning CLOSE", stream->id);
-      nread = http2_handle_stream_close(cf, data, stream, err);
-    }
-    else if(stream->reset ||
-            (ctx->conn_closed && Curl_bufq_is_empty(&ctx->inbufq)) ||
-            (ctx->goaway && ctx->last_stream_id < stream->id)) {
-      CURL_TRC_CF(data, cf, "[%d] returning ERR", stream->id);
-      *err = stream->bodystarted? CURLE_PARTIAL_FILE : CURLE_RECV_ERROR;
-      nread = -1;
-    }
+  else if(stream->closed) {
+    CURL_TRC_CF(data, cf, "[%d] returning CLOSE", stream->id);
+    nread = http2_handle_stream_close(cf, data, stream, err);
   }
-  else if(nread == 0) {
-    *err = CURLE_AGAIN;
+  else if(stream->reset ||
+          (ctx->conn_closed && Curl_bufq_is_empty(&ctx->inbufq)) ||
+          (ctx->goaway && ctx->last_stream_id < stream->id)) {
+    CURL_TRC_CF(data, cf, "[%d] returning ERR", stream->id);
+    *err = data->req.bytecount? CURLE_PARTIAL_FILE : CURLE_HTTP2;
     nread = -1;
   }
 
-out:
   if(nread < 0 && *err != CURLE_AGAIN)
     CURL_TRC_CF(data, cf, "[%d] stream_recv(len=%zu) -> %zd, %d",
                 stream->id, len, nread, *err);
@@ -1866,10 +1891,11 @@ static ssize_t stream_recv(struct Curl_cfilter *cf, struct Curl_easy *data,
 }
 
 static CURLcode h2_progress_ingress(struct Curl_cfilter *cf,
-                                    struct Curl_easy *data)
+                                    struct Curl_easy *data,
+                                    size_t data_max_bytes)
 {
   struct cf_h2_ctx *ctx = cf->ctx;
-  struct stream_ctx *stream;
+  struct h2_stream_ctx *stream;
   CURLcode result = CURLE_OK;
   ssize_t nread;
 
@@ -1885,17 +1911,18 @@ static CURLcode h2_progress_ingress(struct Curl_cfilter *cf,
    * it is time to stop due to connection close or us not processing
    * all network input */
   while(!ctx->conn_closed && Curl_bufq_is_empty(&ctx->inbufq)) {
-    stream = H2_STREAM_CTX(data);
-    if(stream && (stream->closed || Curl_bufq_is_full(&stream->recvbuf))) {
+    stream = H2_STREAM_CTX(ctx, data);
+    if(stream && (stream->closed || !data_max_bytes)) {
       /* We would like to abort here and stop processing, so that
        * the transfer loop can handle the data/close here. However,
        * this may leave data in underlying buffers that will not
        * be consumed. */
       if(!cf->next || !cf->next->cft->has_data_pending(cf->next, data))
-        break;
+        drain_stream(cf, data, stream);
+      break;
     }
 
-    nread = Curl_bufq_slurp(&ctx->inbufq, nw_in_reader, cf, &result);
+    nread = Curl_bufq_sipn(&ctx->inbufq, 0, nw_in_reader, cf, &result);
     if(nread < 0) {
       if(result != CURLE_AGAIN) {
         failf(data, "Failed receiving HTTP2 data: %d(%s)", result,
@@ -1910,8 +1937,9 @@ static CURLcode h2_progress_ingress(struct Curl_cfilter *cf,
       break;
     }
     else {
-      CURL_TRC_CF(data, cf, "[0] ingress: read %zd bytes",
-                  nread);
+      CURL_TRC_CF(data, cf, "[0] ingress: read %zd bytes", nread);
+      data_max_bytes = (data_max_bytes > (size_t)nread)?
+                        (data_max_bytes - (size_t)nread) : 0;
     }
 
     if(h2_process_pending_input(cf, data, &result))
@@ -1929,7 +1957,7 @@ static ssize_t cf_h2_recv(struct Curl_cfilter *cf, struct Curl_easy *data,
                           char *buf, size_t len, CURLcode *err)
 {
   struct cf_h2_ctx *ctx = cf->ctx;
-  struct stream_ctx *stream = H2_STREAM_CTX(data);
+  struct h2_stream_ctx *stream = H2_STREAM_CTX(ctx, data);
   ssize_t nread = -1;
   CURLcode result;
   struct cf_call_data save;
@@ -1953,7 +1981,7 @@ static ssize_t cf_h2_recv(struct Curl_cfilter *cf, struct Curl_easy *data,
     goto out;
 
   if(nread < 0) {
-    *err = h2_progress_ingress(cf, data);
+    *err = h2_progress_ingress(cf, data, len);
     if(*err)
       goto out;
 
@@ -1998,9 +2026,8 @@ static ssize_t cf_h2_recv(struct Curl_cfilter *cf, struct Curl_easy *data,
     nread = -1;
   }
   CURL_TRC_CF(data, cf, "[%d] cf_recv(len=%zu) -> %zd %d, "
-              "buffered=%zu, window=%d/%d, connection %d/%d",
+              "window=%d/%d, connection %d/%d",
               stream->id, len, nread, *err,
-              Curl_bufq_len(&stream->recvbuf),
               nghttp2_session_get_stream_effective_recv_data_length(
                 ctx->h2, stream->id),
               nghttp2_session_get_stream_effective_local_window_size(
@@ -2012,12 +2039,13 @@ static ssize_t cf_h2_recv(struct Curl_cfilter *cf, struct Curl_easy *data,
   return nread;
 }
 
-static ssize_t h2_submit(struct stream_ctx **pstream,
+static ssize_t h2_submit(struct h2_stream_ctx **pstream,
                          struct Curl_cfilter *cf, struct Curl_easy *data,
-                         const void *buf, size_t len, CURLcode *err)
+                         const void *buf, size_t len,
+                         size_t *phdslen, CURLcode *err)
 {
   struct cf_h2_ctx *ctx = cf->ctx;
-  struct stream_ctx *stream = NULL;
+  struct h2_stream_ctx *stream = NULL;
   struct dynhds h2_headers;
   nghttp2_nv *nva = NULL;
   const void *body = NULL;
@@ -2027,6 +2055,7 @@ static ssize_t h2_submit(struct stream_ctx **pstream,
   nghttp2_priority_spec pri_spec;
   ssize_t nwritten;
 
+  *phdslen = 0;
   Curl_dynhds_init(&h2_headers, 0, DYN_HTTP_REQUEST);
 
   *err = http2_data_setup(cf, data, &stream);
@@ -2038,6 +2067,7 @@ static ssize_t h2_submit(struct stream_ctx **pstream,
   nwritten = Curl_h1_req_parse_read(&stream->h1, buf, len, NULL, 0, err);
   if(nwritten < 0)
     goto out;
+  *phdslen = (size_t)nwritten;
   if(!stream->h1.done) {
     /* need more data */
     goto out;
@@ -2052,24 +2082,14 @@ static ssize_t h2_submit(struct stream_ctx **pstream,
   /* no longer needed */
   Curl_h1_req_parse_free(&stream->h1);
 
-  nheader = Curl_dynhds_count(&h2_headers);
-  nva = malloc(sizeof(nghttp2_nv) * nheader);
+  nva = Curl_dynhds_to_nva(&h2_headers, &nheader);
   if(!nva) {
     *err = CURLE_OUT_OF_MEMORY;
     nwritten = -1;
     goto out;
   }
 
-  for(i = 0; i < nheader; ++i) {
-    struct dynhds_entry *e = Curl_dynhds_getn(&h2_headers, i);
-    nva[i].name = (unsigned char *)e->name;
-    nva[i].namelen = e->namelen;
-    nva[i].value = (unsigned char *)e->value;
-    nva[i].valuelen = e->valuelen;
-    nva[i].flags = NGHTTP2_NV_FLAG_NONE;
-  }
-
-  h2_pri_spec(data, &pri_spec);
+  h2_pri_spec(ctx, data, &pri_spec);
   if(!nghttp2_session_check_request_allowed(ctx->h2))
     CURL_TRC_CF(data, cf, "send request NOT allowed (via nghttp2)");
 
@@ -2166,10 +2186,11 @@ static ssize_t cf_h2_send(struct Curl_cfilter *cf, struct Curl_easy *data,
                           const void *buf, size_t len, CURLcode *err)
 {
   struct cf_h2_ctx *ctx = cf->ctx;
-  struct stream_ctx *stream = H2_STREAM_CTX(data);
+  struct h2_stream_ctx *stream = H2_STREAM_CTX(ctx, data);
   struct cf_call_data save;
   int rv;
   ssize_t nwritten;
+  size_t hdslen = 0;
   CURLcode result;
   int blocked = 0, was_blocked = 0;
 
@@ -2233,11 +2254,12 @@ static ssize_t cf_h2_send(struct Curl_cfilter *cf, struct Curl_easy *data,
     }
   }
   else {
-    nwritten = h2_submit(&stream, cf, data, buf, len, err);
+    nwritten = h2_submit(&stream, cf, data, buf, len, &hdslen, err);
     if(nwritten < 0) {
       goto out;
     }
     DEBUGASSERT(stream);
+    DEBUGASSERT(hdslen <= (size_t)nwritten);
   }
 
   /* Call the nghttp2 send loop and flush to write ALL buffered data,
@@ -2272,26 +2294,26 @@ static ssize_t cf_h2_send(struct Curl_cfilter *cf, struct Curl_easy *data,
      * frame buffer or our network out buffer. */
     size_t rwin = nghttp2_session_get_stream_remote_window_size(ctx->h2,
                                                                 stream->id);
-    if(rwin == 0) {
-      /* H2 flow window exhaustion. We need to HOLD upload until we get
-       * a WINDOW_UPDATE from the server. */
-      data->req.keepon |= KEEP_SEND_HOLD;
-      CURL_TRC_CF(data, cf, "[%d] holding send as remote flow "
-                  "window is exhausted", stream->id);
-    }
-
-    /* Whatever the cause, we need to return CURL_EAGAIN for this call.
-     * We have unwritten state that needs us being invoked again and EAGAIN
-     * is the only way to ensure that. */
-    stream->upload_blocked_len = nwritten;
+    /* At the start of a stream, we are called with request headers
+     * and, possibly, parts of the body. Later, only body data.
+     * If we cannot send pure body data, we EAGAIN. If there had been
+     * header, we return that *they* have been written and remember the
+     * block on the data length only. */
+    stream->upload_blocked_len = ((size_t)nwritten) - hdslen;
     CURL_TRC_CF(data, cf, "[%d] cf_send(len=%zu) BLOCK: win %u/%zu "
-                "blocked_len=%zu",
+                "hds_len=%zu blocked_len=%zu",
                 stream->id, len,
                 nghttp2_session_get_remote_window_size(ctx->h2), rwin,
-                nwritten);
-    *err = CURLE_AGAIN;
-    nwritten = -1;
-    goto out;
+                hdslen, stream->upload_blocked_len);
+    if(hdslen) {
+      *err = CURLE_OK;
+      nwritten = hdslen;
+    }
+    else {
+      *err = CURLE_AGAIN;
+      nwritten = -1;
+      goto out;
+    }
   }
   else if(should_close_session(ctx)) {
     /* nghttp2 thinks this session is done. If the stream has not been
@@ -2313,7 +2335,7 @@ static ssize_t cf_h2_send(struct Curl_cfilter *cf, struct Curl_easy *data,
                 "h2 windows %d-%d (stream-conn), "
                 "buffers %zu-%zu (stream-conn)",
                 stream->id, len, nwritten, *err,
-                (ssize_t)stream->upload_left,
+                stream->upload_left,
                 nghttp2_session_get_stream_remote_window_size(
                   ctx->h2, stream->id),
                 nghttp2_session_get_remote_window_size(ctx->h2),
@@ -2331,37 +2353,37 @@ static ssize_t cf_h2_send(struct Curl_cfilter *cf, struct Curl_easy *data,
   return nwritten;
 }
 
-static int cf_h2_get_select_socks(struct Curl_cfilter *cf,
-                                  struct Curl_easy *data,
-                                  curl_socket_t *sock)
+static void cf_h2_adjust_pollset(struct Curl_cfilter *cf,
+                                 struct Curl_easy *data,
+                                 struct easy_pollset *ps)
 {
   struct cf_h2_ctx *ctx = cf->ctx;
-  struct SingleRequest *k = &data->req;
-  struct stream_ctx *stream = H2_STREAM_CTX(data);
-  int bitmap = GETSOCK_BLANK;
-  struct cf_call_data save;
+  curl_socket_t sock;
+  bool want_recv, want_send;
 
-  CF_DATA_SAVE(save, cf, data);
-  sock[0] = Curl_conn_cf_get_socket(cf, data);
-
-  if(!(k->keepon & (KEEP_RECV_PAUSE|KEEP_RECV_HOLD)))
-    /* Unless paused - in an HTTP/2 connection we can basically always get a
-       frame so we should always be ready for one */
-    bitmap |= GETSOCK_READSOCK(0);
-
-  /* we're (still uploading OR the HTTP/2 layer wants to send data) AND
-     there's a window to send data in */
-  if((((k->keepon & KEEP_SENDBITS) == KEEP_SEND) ||
-      nghttp2_session_want_write(ctx->h2)) &&
-     (nghttp2_session_get_remote_window_size(ctx->h2) &&
-      nghttp2_session_get_stream_remote_window_size(ctx->h2,
-                                                    stream->id)))
-    bitmap |= GETSOCK_WRITESOCK(0);
+  if(!ctx->h2)
+    return;
 
-  CF_DATA_RESTORE(cf, save);
-  return bitmap;
-}
+  sock = Curl_conn_cf_get_socket(cf, data);
+  Curl_pollset_check(data, ps, sock, &want_recv, &want_send);
+  if(want_recv || want_send) {
+    struct h2_stream_ctx *stream = H2_STREAM_CTX(ctx, data);
+    struct cf_call_data save;
+    bool c_exhaust, s_exhaust;
 
+    CF_DATA_SAVE(save, cf, data);
+    c_exhaust = want_send && !nghttp2_session_get_remote_window_size(ctx->h2);
+    s_exhaust = want_send && stream && stream->id >= 0 &&
+                !nghttp2_session_get_stream_remote_window_size(ctx->h2,
+                                                               stream->id);
+    want_recv = (want_recv || c_exhaust || s_exhaust);
+    want_send = (!s_exhaust && want_send) ||
+                (!c_exhaust && nghttp2_session_want_write(ctx->h2));
+
+    Curl_pollset_set(data, ps, sock, want_recv, want_send);
+    CF_DATA_RESTORE(cf, save);
+  }
+}
 
 static CURLcode cf_h2_connect(struct Curl_cfilter *cf,
                               struct Curl_easy *data,
@@ -2392,7 +2414,7 @@ static CURLcode cf_h2_connect(struct Curl_cfilter *cf,
       goto out;
   }
 
-  result = h2_progress_ingress(cf, data);
+  result = h2_progress_ingress(cf, data, H2_CHUNK_SIZE);
   if(result)
     goto out;
 
@@ -2425,6 +2447,8 @@ static void cf_h2_close(struct Curl_cfilter *cf, struct Curl_easy *data)
     cf_h2_ctx_clear(ctx);
     CF_DATA_RESTORE(cf, save);
   }
+  if(cf->next)
+    cf->next->cft->do_close(cf->next, data);
 }
 
 static void cf_h2_destroy(struct Curl_cfilter *cf, struct Curl_easy *data)
@@ -2444,7 +2468,7 @@ static CURLcode http2_data_pause(struct Curl_cfilter *cf,
 {
 #ifdef NGHTTP2_HAS_SET_LOCAL_WINDOW_SIZE
   struct cf_h2_ctx *ctx = cf->ctx;
-  struct stream_ctx *stream = H2_STREAM_CTX(data);
+  struct h2_stream_ctx *stream = H2_STREAM_CTX(ctx, data);
 
   DEBUGASSERT(data);
   if(ctx && ctx->h2 && stream) {
@@ -2509,14 +2533,15 @@ static CURLcode cf_h2_cntrl(struct Curl_cfilter *cf,
   case CF_CTRL_DATA_PAUSE:
     result = http2_data_pause(cf, data, (arg1 != 0));
     break;
-  case CF_CTRL_DATA_DONE_SEND: {
+  case CF_CTRL_DATA_DONE_SEND:
     result = http2_data_done_send(cf, data);
     break;
-  }
-  case CF_CTRL_DATA_DONE: {
-    http2_data_done(cf, data, arg1 != 0);
+  case CF_CTRL_DATA_DETACH:
+    http2_data_done(cf, data);
+    break;
+  case CF_CTRL_DATA_DONE:
+    http2_data_done(cf, data);
     break;
-  }
   default:
     break;
   }
@@ -2528,11 +2553,10 @@ static bool cf_h2_data_pending(struct Curl_cfilter *cf,
                                const struct Curl_easy *data)
 {
   struct cf_h2_ctx *ctx = cf->ctx;
-  struct stream_ctx *stream = H2_STREAM_CTX(data);
+  struct h2_stream_ctx *stream = H2_STREAM_CTX(ctx, data);
 
   if(ctx && (!Curl_bufq_is_empty(&ctx->inbufq)
-            || (stream && !Curl_bufq_is_empty(&stream->sendbuf))
-            || (stream && !Curl_bufq_is_empty(&stream->recvbuf))))
+            || (stream && !Curl_bufq_is_empty(&stream->sendbuf))))
     return TRUE;
   return cf->next? cf->next->cft->has_data_pending(cf->next, data) : FALSE;
 }
@@ -2588,6 +2612,11 @@ static CURLcode cf_h2_query(struct Curl_cfilter *cf,
     *pres1 = (effective_max > INT_MAX)? INT_MAX : (int)effective_max;
     CF_DATA_RESTORE(cf, save);
     return CURLE_OK;
+  case CF_QUERY_STREAM_ERROR: {
+    struct h2_stream_ctx *stream = H2_STREAM_CTX(ctx, data);
+    *pres1 = stream? (int)stream->error : 0;
+    return CURLE_OK;
+  }
   default:
     break;
   }
@@ -2604,7 +2633,7 @@ struct Curl_cftype Curl_cft_nghttp2 = {
   cf_h2_connect,
   cf_h2_close,
   Curl_cf_def_get_host,
-  cf_h2_get_select_socks,
+  cf_h2_adjust_pollset,
   cf_h2_data_pending,
   cf_h2_send,
   cf_h2_recv,
@@ -2617,14 +2646,15 @@ struct Curl_cftype Curl_cft_nghttp2 = {
 static CURLcode http2_cfilter_add(struct Curl_cfilter **pcf,
                                   struct Curl_easy *data,
                                   struct connectdata *conn,
-                                  int sockindex)
+                                  int sockindex,
+                                  bool via_h1_upgrade)
 {
   struct Curl_cfilter *cf = NULL;
   struct cf_h2_ctx *ctx;
   CURLcode result = CURLE_OUT_OF_MEMORY;
 
   DEBUGASSERT(data->conn);
-  ctx = calloc(sizeof(*ctx), 1);
+  ctx = calloc(1, sizeof(*ctx));
   if(!ctx)
     goto out;
 
@@ -2632,8 +2662,9 @@ static CURLcode http2_cfilter_add(struct Curl_cfilter **pcf,
   if(result)
     goto out;
 
+  ctx = NULL;
   Curl_conn_cf_add(data, conn, sockindex, cf);
-  result = CURLE_OK;
+  result = cf_h2_ctx_init(cf, data, via_h1_upgrade);
 
 out:
   if(result)
@@ -2643,14 +2674,15 @@ static CURLcode http2_cfilter_add(struct Curl_cfilter **pcf,
 }
 
 static CURLcode http2_cfilter_insert_after(struct Curl_cfilter *cf,
-                                           struct Curl_easy *data)
+                                           struct Curl_easy *data,
+                                           bool via_h1_upgrade)
 {
   struct Curl_cfilter *cf_h2 = NULL;
   struct cf_h2_ctx *ctx;
   CURLcode result = CURLE_OUT_OF_MEMORY;
 
   (void)data;
-  ctx = calloc(sizeof(*ctx), 1);
+  ctx = calloc(1, sizeof(*ctx));
   if(!ctx)
     goto out;
 
@@ -2658,8 +2690,9 @@ static CURLcode http2_cfilter_insert_after(struct Curl_cfilter *cf,
   if(result)
     goto out;
 
+  ctx = NULL;
   Curl_conn_cf_insert_after(cf, cf_h2);
-  result = CURLE_OK;
+  result = cf_h2_ctx_init(cf_h2, data, via_h1_upgrade);
 
 out:
   if(result)
@@ -2716,11 +2749,7 @@ CURLcode Curl_http2_switch(struct Curl_easy *data,
   DEBUGASSERT(!Curl_conn_is_http2(data, conn, sockindex));
   DEBUGF(infof(data, "switching to HTTP/2"));
 
-  result = http2_cfilter_add(&cf, data, conn, sockindex);
-  if(result)
-    return result;
-
-  result = cf_h2_ctx_init(cf, data, FALSE);
+  result = http2_cfilter_add(&cf, data, conn, sockindex, FALSE);
   if(result)
     return result;
 
@@ -2743,15 +2772,11 @@ CURLcode Curl_http2_switch_at(struct Curl_cfilter *cf, struct Curl_easy *data)
 
   DEBUGASSERT(!Curl_cf_is_http2(cf, data));
 
-  result = http2_cfilter_insert_after(cf, data);
+  result = http2_cfilter_insert_after(cf, data, FALSE);
   if(result)
     return result;
 
   cf_h2 = cf->next;
-  result = cf_h2_ctx_init(cf_h2, data, FALSE);
-  if(result)
-    return result;
-
   cf->conn->httpversion = 20; /* we know we're on HTTP/2 now */
   cf->conn->bits.multiplex = TRUE; /* at least potentially multiplexed */
   cf->conn->bundle->multiuse = BUNDLE_MULTIPLEX;
@@ -2776,17 +2801,13 @@ CURLcode Curl_http2_upgrade(struct Curl_easy *data,
   DEBUGF(infof(data, "upgrading to HTTP/2"));
   DEBUGASSERT(data->req.upgr101 == UPGR101_RECEIVED);
 
-  result = http2_cfilter_add(&cf, data, conn, sockindex);
+  result = http2_cfilter_add(&cf, data, conn, sockindex, TRUE);
   if(result)
     return result;
 
   DEBUGASSERT(cf->cft == &Curl_cft_nghttp2);
   ctx = cf->ctx;
 
-  result = cf_h2_ctx_init(cf, data, TRUE);
-  if(result)
-    return result;
-
   if(nread > 0) {
     /* Remaining data from the protocol switch reply is already using
      * the switched protocol, ie. HTTP/2. We add that to the network
@@ -2825,8 +2846,11 @@ CURLcode Curl_http2_upgrade(struct Curl_easy *data,
    CURLE_HTTP2_STREAM error! */
 bool Curl_h2_http_1_1_error(struct Curl_easy *data)
 {
-  struct stream_ctx *stream = H2_STREAM_CTX(data);
-  return (stream && stream->error == NGHTTP2_HTTP_1_1_REQUIRED);
+  if(Curl_conn_is_http2(data, data->conn, FIRSTSOCKET)) {
+    int err = Curl_conn_get_stream_error(data, data->conn, FIRSTSOCKET);
+    return (err == NGHTTP2_HTTP_1_1_REQUIRED);
+  }
+  return FALSE;
 }
 
 #else /* !USE_NGHTTP2 */
diff --git a/vendor/curl/lib/http_aws_sigv4.c b/vendor/curl/lib/http_aws_sigv4.c
index f39d02cced..98cc033a08 100644
--- a/vendor/curl/lib/http_aws_sigv4.c
+++ b/vendor/curl/lib/http_aws_sigv4.c
@@ -34,6 +34,7 @@
 #include "transfer.h"
 #include "parsedate.h"
 #include "sendf.h"
+#include "escape.h"
 
 #include 
 
@@ -63,11 +64,8 @@
 
 static void sha256_to_hex(char *dst, unsigned char *sha)
 {
-  int i;
-
-  for(i = 0; i < SHA256_DIGEST_LENGTH; ++i) {
-    msnprintf(dst + (i * 2), SHA256_HEX_LENGTH - (i * 2), "%02x", sha[i]);
-  }
+  Curl_hexencode(sha, SHA256_DIGEST_LENGTH,
+                 (unsigned char *)dst, SHA256_HEX_LENGTH);
 }
 
 static char *find_date_hdr(struct Curl_easy *data, const char *sig_hdr)
@@ -160,10 +158,7 @@ static CURLcode make_headers(struct Curl_easy *data,
   msnprintf(date_full_hdr, DATE_FULL_HDR_LEN,
             "x-%s-date:%s", provider1, timestamp);
 
-  if(Curl_checkheaders(data, STRCONST("Host"))) {
-    head = NULL;
-  }
-  else {
+  if(!Curl_checkheaders(data, STRCONST("Host"))) {
     char full_host[FULL_HOST_LEN + 1];
 
     if(data->state.aptr.host) {
@@ -249,7 +244,7 @@ static CURLcode make_headers(struct Curl_easy *data,
   }
   else {
     char *value;
-
+    char *endp;
     value = strchr(*date_header, ':');
     if(!value) {
       *date_header = NULL;
@@ -258,8 +253,17 @@ static CURLcode make_headers(struct Curl_easy *data,
     ++value;
     while(ISBLANK(*value))
       ++value;
-    strncpy(timestamp, value, TIMESTAMP_SIZE - 1);
-    timestamp[TIMESTAMP_SIZE - 1] = 0;
+    endp = value;
+    while(*endp && ISALNUM(*endp))
+      ++endp;
+    /* 16 bytes => "19700101T000000Z" */
+    if((endp - value) == TIMESTAMP_SIZE - 1) {
+      memcpy(timestamp, value, TIMESTAMP_SIZE - 1);
+      timestamp[TIMESTAMP_SIZE - 1] = 0;
+    }
+    else
+      /* bad timestamp length */
+      timestamp[0] = 0;
     *date_header = NULL;
   }
 
@@ -409,6 +413,11 @@ static int compare_func(const void *a, const void *b)
 {
   const struct pair *aa = a;
   const struct pair *bb = b;
+  /* If one element is empty, the other is always sorted higher */
+  if(aa->len == 0)
+    return -1;
+  if(bb->len == 0)
+    return 1;
   return strncmp(aa->p, bb->p, aa->len < bb->len ? aa->len : bb->len);
 }
 
@@ -453,6 +462,7 @@ static CURLcode canon_query(struct Curl_easy *data,
   for(i = 0; !result && (i < entry); i++, ap++) {
     size_t len;
     const char *q = ap->p;
+    bool found_equals = false;
     if(!ap->len)
       continue;
     for(len = ap->len; len && !result; q++, len--) {
@@ -464,9 +474,13 @@ static CURLcode canon_query(struct Curl_easy *data,
         case '.':
         case '_':
         case '~':
+          /* allowed as-is */
+          result = Curl_dyn_addn(dq, q, 1);
+          break;
         case '=':
           /* allowed as-is */
           result = Curl_dyn_addn(dq, q, 1);
+          found_equals = true;
           break;
         case '%':
           /* uppercase the following if hexadecimal */
@@ -494,7 +508,11 @@ static CURLcode canon_query(struct Curl_easy *data,
         }
       }
     }
-    if(i < entry - 1) {
+    if(!result && !found_equals) {
+      /* queries without value still need an equals */
+      result = Curl_dyn_addn(dq, "=", 1);
+    }
+    if(!result && i < entry - 1) {
       /* insert ampersands between query pairs */
       result = Curl_dyn_addn(dq, "&", 1);
     }
@@ -593,7 +611,7 @@ CURLcode Curl_output_aws_sigv4(struct Curl_easy *data, bool proxy)
       result = CURLE_URL_MALFORMAT;
       goto fail;
     }
-    strncpy(service, hostname, len);
+    memcpy(service, hostname, len);
     service[len] = '\0';
 
     infof(data, "aws_sigv4: picked service %s from host", service);
@@ -612,7 +630,7 @@ CURLcode Curl_output_aws_sigv4(struct Curl_easy *data, bool proxy)
         result = CURLE_URL_MALFORMAT;
         goto fail;
       }
-      strncpy(region, reg, len);
+      memcpy(region, reg, len);
       region[len] = '\0';
       infof(data, "aws_sigv4: picked region %s from host", region);
     }
diff --git a/vendor/curl/lib/http_chunks.c b/vendor/curl/lib/http_chunks.c
index bda00d3833..48e7e462ba 100644
--- a/vendor/curl/lib/http_chunks.c
+++ b/vendor/curl/lib/http_chunks.c
@@ -27,10 +27,13 @@
 #ifndef CURL_DISABLE_HTTP
 
 #include "urldata.h" /* it includes http_chunks.h */
+#include "curl_printf.h"
+#include "curl_trc.h"
 #include "sendf.h"   /* for the client write stuff */
 #include "dynbuf.h"
 #include "content_encoding.h"
 #include "http.h"
+#include "multiif.h"
 #include "strtoofft.h"
 #include "warnless.h"
 
@@ -75,121 +78,156 @@
 
  */
 
-#define isxdigit_ascii(x) Curl_isxdigit(x)
+void Curl_httpchunk_init(struct Curl_easy *data, struct Curl_chunker *ch,
+                         bool ignore_body)
+{
+  (void)data;
+  ch->hexindex = 0;      /* start at 0 */
+  ch->state = CHUNK_HEX; /* we get hex first! */
+  ch->last_code = CHUNKE_OK;
+  Curl_dyn_init(&ch->trailer, DYN_H1_TRAILER);
+  ch->ignore_body = ignore_body;
+}
 
-void Curl_httpchunk_init(struct Curl_easy *data)
+void Curl_httpchunk_reset(struct Curl_easy *data, struct Curl_chunker *ch,
+                          bool ignore_body)
 {
-  struct connectdata *conn = data->conn;
-  struct Curl_chunker *chunk = &conn->chunk;
-  chunk->hexindex = 0;      /* start at 0 */
-  chunk->state = CHUNK_HEX; /* we get hex first! */
-  Curl_dyn_init(&conn->trailer, DYN_H1_TRAILER);
+  (void)data;
+  ch->hexindex = 0;      /* start at 0 */
+  ch->state = CHUNK_HEX; /* we get hex first! */
+  ch->last_code = CHUNKE_OK;
+  Curl_dyn_reset(&ch->trailer);
+  ch->ignore_body = ignore_body;
 }
 
-/*
- * chunk_read() returns a OK for normal operations, or a positive return code
- * for errors. STOP means this sequence of chunks is complete.  The 'wrote'
- * argument is set to tell the caller how many bytes we actually passed to the
- * client (for byte-counting and whatever).
- *
- * The states and the state-machine is further explained in the header file.
- *
- * This function always uses ASCII hex values to accommodate non-ASCII hosts.
- * For example, 0x0d and 0x0a are used instead of '\r' and '\n'.
- */
-CHUNKcode Curl_httpchunk_read(struct Curl_easy *data,
-                              char *datap,
-                              ssize_t datalen,
-                              ssize_t *wrote,
-                              CURLcode *extrap)
+void Curl_httpchunk_free(struct Curl_easy *data, struct Curl_chunker *ch)
+{
+  (void)data;
+  Curl_dyn_free(&ch->trailer);
+}
+
+bool Curl_httpchunk_is_done(struct Curl_easy *data, struct Curl_chunker *ch)
+{
+  (void)data;
+  return ch->state == CHUNK_DONE;
+}
+
+static CURLcode httpchunk_readwrite(struct Curl_easy *data,
+                                    struct Curl_chunker *ch,
+                                    struct Curl_cwriter *cw_next,
+                                    const char *buf, size_t blen,
+                                    size_t *pconsumed)
 {
   CURLcode result = CURLE_OK;
-  struct connectdata *conn = data->conn;
-  struct Curl_chunker *ch = &conn->chunk;
-  struct SingleRequest *k = &data->req;
   size_t piece;
-  curl_off_t length = (curl_off_t)datalen;
 
-  *wrote = 0; /* nothing's written yet */
+  *pconsumed = 0; /* nothing's written yet */
+  /* first check terminal states that will not progress anywhere */
+  if(ch->state == CHUNK_DONE)
+    return CURLE_OK;
+  if(ch->state == CHUNK_FAILED)
+    return CURLE_RECV_ERROR;
 
   /* the original data is written to the client, but we go on with the
      chunk read process, to properly calculate the content length */
-  if(data->set.http_te_skip && !k->ignorebody) {
-    result = Curl_client_write(data, CLIENTWRITE_BODY, datap, datalen);
+  if(data->set.http_te_skip && !ch->ignore_body) {
+    if(cw_next)
+      result = Curl_cwriter_write(data, cw_next, CLIENTWRITE_BODY, buf, blen);
+    else
+      result = Curl_client_write(data, CLIENTWRITE_BODY, (char *)buf, blen);
     if(result) {
-      *extrap = result;
-      return CHUNKE_PASSTHRU_ERROR;
+      ch->state = CHUNK_FAILED;
+      ch->last_code = CHUNKE_PASSTHRU_ERROR;
+      return result;
     }
   }
 
-  while(length) {
+  while(blen) {
     switch(ch->state) {
     case CHUNK_HEX:
-      if(ISXDIGIT(*datap)) {
-        if(ch->hexindex < CHUNK_MAXNUM_LEN) {
-          ch->hexbuffer[ch->hexindex] = *datap;
-          datap++;
-          length--;
-          ch->hexindex++;
-        }
-        else {
-          return CHUNKE_TOO_LONG_HEX; /* longer hex than we support */
+      if(ISXDIGIT(*buf)) {
+        if(ch->hexindex >= CHUNK_MAXNUM_LEN) {
+          failf(data, "chunk hex-length longer than %d", CHUNK_MAXNUM_LEN);
+          ch->state = CHUNK_FAILED;
+          ch->last_code = CHUNKE_TOO_LONG_HEX; /* longer than we support */
+          return CURLE_RECV_ERROR;
         }
+        ch->hexbuffer[ch->hexindex++] = *buf;
+        buf++;
+        blen--;
+        (*pconsumed)++;
       }
       else {
-        char *endptr;
-        if(0 == ch->hexindex)
+        if(0 == ch->hexindex) {
           /* This is illegal data, we received junk where we expected
              a hexadecimal digit. */
-          return CHUNKE_ILLEGAL_HEX;
+          failf(data, "chunk hex-length char not a hex digit: 0x%x", *buf);
+          ch->state = CHUNK_FAILED;
+          ch->last_code = CHUNKE_ILLEGAL_HEX;
+          return CURLE_RECV_ERROR;
+        }
 
-        /* length and datap are unmodified */
+        /* blen and buf are unmodified */
         ch->hexbuffer[ch->hexindex] = 0;
-
-        if(curlx_strtoofft(ch->hexbuffer, &endptr, 16, &ch->datasize))
-          return CHUNKE_ILLEGAL_HEX;
+        if(curlx_strtoofft(ch->hexbuffer, NULL, 16, &ch->datasize)) {
+          failf(data, "chunk hex-length not valid: '%s'", ch->hexbuffer);
+          ch->state = CHUNK_FAILED;
+          ch->last_code = CHUNKE_ILLEGAL_HEX;
+          return CURLE_RECV_ERROR;
+        }
         ch->state = CHUNK_LF; /* now wait for the CRLF */
       }
       break;
 
     case CHUNK_LF:
       /* waiting for the LF after a chunk size */
-      if(*datap == 0x0a) {
+      if(*buf == 0x0a) {
         /* we're now expecting data to come, unless size was zero! */
         if(0 == ch->datasize) {
           ch->state = CHUNK_TRAILER; /* now check for trailers */
         }
-        else
+        else {
           ch->state = CHUNK_DATA;
+          CURL_TRC_WRITE(data, "http_chunked, chunk start of %"
+                         CURL_FORMAT_CURL_OFF_T " bytes", ch->datasize);
+        }
       }
 
-      datap++;
-      length--;
+      buf++;
+      blen--;
+      (*pconsumed)++;
       break;
 
     case CHUNK_DATA:
-      /* We expect 'datasize' of data. We have 'length' right now, it can be
+      /* We expect 'datasize' of data. We have 'blen' right now, it can be
          more or less than 'datasize'. Get the smallest piece.
       */
-      piece = curlx_sotouz((ch->datasize >= length)?length:ch->datasize);
+      piece = blen;
+      if(ch->datasize < (curl_off_t)blen)
+        piece = curlx_sotouz(ch->datasize);
 
       /* Write the data portion available */
-      if(!data->set.http_te_skip && !k->ignorebody) {
-        if(!data->set.http_ce_skip && k->writer_stack)
-          result = Curl_unencode_write(data, k->writer_stack, datap, piece);
+      if(!data->set.http_te_skip && !ch->ignore_body) {
+        if(cw_next)
+          result = Curl_cwriter_write(data, cw_next, CLIENTWRITE_BODY,
+                                      buf, piece);
         else
-          result = Curl_client_write(data, CLIENTWRITE_BODY, datap, piece);
-
+          result = Curl_client_write(data, CLIENTWRITE_BODY,
+                                    (char *)buf, piece);
         if(result) {
-          *extrap = result;
-          return CHUNKE_PASSTHRU_ERROR;
+          ch->state = CHUNK_FAILED;
+          ch->last_code = CHUNKE_PASSTHRU_ERROR;
+          return result;
         }
       }
 
-      *wrote += piece;
+      *pconsumed += piece;
       ch->datasize -= piece; /* decrease amount left to expect */
-      datap += piece;    /* move read pointer forward */
-      length -= piece;   /* decrease space left in this round */
+      buf += piece;    /* move read pointer forward */
+      blen -= piece;   /* decrease space left in this round */
+      CURL_TRC_WRITE(data, "http_chunked, write %zu body bytes, %"
+                     CURL_FORMAT_CURL_OFF_T " bytes in chunk remain",
+                     piece, ch->datasize);
 
       if(0 == ch->datasize)
         /* end of data this round, we now expect a trailing CRLF */
@@ -197,42 +235,56 @@ CHUNKcode Curl_httpchunk_read(struct Curl_easy *data,
       break;
 
     case CHUNK_POSTLF:
-      if(*datap == 0x0a) {
+      if(*buf == 0x0a) {
         /* The last one before we go back to hex state and start all over. */
-        Curl_httpchunk_init(data); /* sets state back to CHUNK_HEX */
+        Curl_httpchunk_reset(data, ch, ch->ignore_body);
+      }
+      else if(*buf != 0x0d) {
+        ch->state = CHUNK_FAILED;
+        ch->last_code = CHUNKE_BAD_CHUNK;
+        return CURLE_RECV_ERROR;
       }
-      else if(*datap != 0x0d)
-        return CHUNKE_BAD_CHUNK;
-      datap++;
-      length--;
+      buf++;
+      blen--;
+      (*pconsumed)++;
       break;
 
     case CHUNK_TRAILER:
-      if((*datap == 0x0d) || (*datap == 0x0a)) {
-        char *tr = Curl_dyn_ptr(&conn->trailer);
+      if((*buf == 0x0d) || (*buf == 0x0a)) {
+        char *tr = Curl_dyn_ptr(&ch->trailer);
         /* this is the end of a trailer, but if the trailer was zero bytes
            there was no trailer and we move on */
 
         if(tr) {
           size_t trlen;
-          result = Curl_dyn_addn(&conn->trailer, (char *)STRCONST("\x0d\x0a"));
-          if(result)
-            return CHUNKE_OUT_OF_MEMORY;
-
-          tr = Curl_dyn_ptr(&conn->trailer);
-          trlen = Curl_dyn_len(&conn->trailer);
+          result = Curl_dyn_addn(&ch->trailer, (char *)STRCONST("\x0d\x0a"));
+          if(result) {
+            ch->state = CHUNK_FAILED;
+            ch->last_code = CHUNKE_OUT_OF_MEMORY;
+            return result;
+          }
+          tr = Curl_dyn_ptr(&ch->trailer);
+          trlen = Curl_dyn_len(&ch->trailer);
           if(!data->set.http_te_skip) {
-            result = Curl_client_write(data,
-                                       CLIENTWRITE_HEADER|CLIENTWRITE_TRAILER,
-                                       tr, trlen);
+            if(cw_next)
+              result = Curl_cwriter_write(data, cw_next,
+                                          CLIENTWRITE_HEADER|
+                                          CLIENTWRITE_TRAILER,
+                                          tr, trlen);
+            else
+              result = Curl_client_write(data,
+                                         CLIENTWRITE_HEADER|
+                                         CLIENTWRITE_TRAILER,
+                                         tr, trlen);
             if(result) {
-              *extrap = result;
-              return CHUNKE_PASSTHRU_ERROR;
+              ch->state = CHUNK_FAILED;
+              ch->last_code = CHUNKE_PASSTHRU_ERROR;
+              return result;
             }
           }
-          Curl_dyn_reset(&conn->trailer);
+          Curl_dyn_reset(&ch->trailer);
           ch->state = CHUNK_TRAILER_CR;
-          if(*datap == 0x0a)
+          if(*buf == 0x0a)
             /* already on the LF */
             break;
         }
@@ -243,59 +295,80 @@ CHUNKcode Curl_httpchunk_read(struct Curl_easy *data,
         }
       }
       else {
-        result = Curl_dyn_addn(&conn->trailer, datap, 1);
-        if(result)
-          return CHUNKE_OUT_OF_MEMORY;
+        result = Curl_dyn_addn(&ch->trailer, buf, 1);
+        if(result) {
+          ch->state = CHUNK_FAILED;
+          ch->last_code = CHUNKE_OUT_OF_MEMORY;
+          return result;
+        }
       }
-      datap++;
-      length--;
+      buf++;
+      blen--;
+      (*pconsumed)++;
       break;
 
     case CHUNK_TRAILER_CR:
-      if(*datap == 0x0a) {
+      if(*buf == 0x0a) {
         ch->state = CHUNK_TRAILER_POSTCR;
-        datap++;
-        length--;
+        buf++;
+        blen--;
+        (*pconsumed)++;
+      }
+      else {
+        ch->state = CHUNK_FAILED;
+        ch->last_code = CHUNKE_BAD_CHUNK;
+        return CURLE_RECV_ERROR;
       }
-      else
-        return CHUNKE_BAD_CHUNK;
       break;
 
     case CHUNK_TRAILER_POSTCR:
       /* We enter this state when a CR should arrive so we expect to
          have to first pass a CR before we wait for LF */
-      if((*datap != 0x0d) && (*datap != 0x0a)) {
+      if((*buf != 0x0d) && (*buf != 0x0a)) {
         /* not a CR then it must be another header in the trailer */
         ch->state = CHUNK_TRAILER;
         break;
       }
-      if(*datap == 0x0d) {
+      if(*buf == 0x0d) {
         /* skip if CR */
-        datap++;
-        length--;
+        buf++;
+        blen--;
+        (*pconsumed)++;
       }
       /* now wait for the final LF */
       ch->state = CHUNK_STOP;
       break;
 
     case CHUNK_STOP:
-      if(*datap == 0x0a) {
-        length--;
-
+      if(*buf == 0x0a) {
+        blen--;
+        (*pconsumed)++;
         /* Record the length of any data left in the end of the buffer
            even if there's no more chunks to read */
-        ch->datasize = curlx_sotouz(length);
-
-        return CHUNKE_STOP; /* return stop */
+        ch->datasize = blen;
+        ch->state = CHUNK_DONE;
+        CURL_TRC_WRITE(data, "http_chunk, response complete");
+        return CURLE_OK;
       }
-      else
-        return CHUNKE_BAD_CHUNK;
+      else {
+        ch->state = CHUNK_FAILED;
+        ch->last_code = CHUNKE_BAD_CHUNK;
+        CURL_TRC_WRITE(data, "http_chunk error, expected 0x0a, seeing 0x%ux",
+                       (unsigned int)*buf);
+        return CURLE_RECV_ERROR;
+      }
+    case CHUNK_DONE:
+      return CURLE_OK;
+
+    case CHUNK_FAILED:
+      return CURLE_RECV_ERROR;
     }
+
   }
-  return CHUNKE_OK;
+  return CURLE_OK;
 }
 
-const char *Curl_chunked_strerror(CHUNKcode code)
+static const char *Curl_chunked_strerror(CHUNKcode code)
 {
   switch(code) {
   default:
@@ -307,8 +380,7 @@ const char *Curl_chunked_strerror(CHUNKcode code)
   case CHUNKE_BAD_CHUNK:
     return "Malformed encoding found";
   case CHUNKE_PASSTHRU_ERROR:
-    DEBUGASSERT(0); /* never used */
-    return "";
+    return "Error writing data to client";
   case CHUNKE_BAD_ENCODING:
     return "Bad content-encoding found";
   case CHUNKE_OUT_OF_MEMORY:
@@ -316,4 +388,294 @@ const char *Curl_chunked_strerror(CHUNKcode code)
   }
 }
 
+CURLcode Curl_httpchunk_read(struct Curl_easy *data,
+                             struct Curl_chunker *ch,
+                             char *buf, size_t blen,
+                             size_t *pconsumed)
+{
+  return httpchunk_readwrite(data, ch, NULL, buf, blen, pconsumed);
+}
+
+struct chunked_writer {
+  struct Curl_cwriter super;
+  struct Curl_chunker ch;
+};
+
+static CURLcode cw_chunked_init(struct Curl_easy *data,
+                                struct Curl_cwriter *writer)
+{
+  struct chunked_writer *ctx = writer->ctx;
+
+  data->req.chunk = TRUE;      /* chunks coming our way. */
+  Curl_httpchunk_init(data, &ctx->ch, FALSE);
+  return CURLE_OK;
+}
+
+static void cw_chunked_close(struct Curl_easy *data,
+                             struct Curl_cwriter *writer)
+{
+  struct chunked_writer *ctx = writer->ctx;
+  Curl_httpchunk_free(data, &ctx->ch);
+}
+
+static CURLcode cw_chunked_write(struct Curl_easy *data,
+                                 struct Curl_cwriter *writer, int type,
+                                 const char *buf, size_t blen)
+{
+  struct chunked_writer *ctx = writer->ctx;
+  CURLcode result;
+  size_t consumed;
+
+  if(!(type & CLIENTWRITE_BODY))
+    return Curl_cwriter_write(data, writer->next, type, buf, blen);
+
+  consumed = 0;
+  result = httpchunk_readwrite(data, &ctx->ch, writer->next, buf, blen,
+                               &consumed);
+
+  if(result) {
+    if(CHUNKE_PASSTHRU_ERROR == ctx->ch.last_code) {
+      failf(data, "Failed reading the chunked-encoded stream");
+    }
+    else {
+      failf(data, "%s in chunked-encoding",
+            Curl_chunked_strerror(ctx->ch.last_code));
+    }
+    return result;
+  }
+
+  blen -= consumed;
+  if(CHUNK_DONE == ctx->ch.state) {
+    /* chunks read successfully, download is complete */
+    data->req.download_done = TRUE;
+    if(blen) {
+      infof(data, "Leftovers after chunking: %zu bytes", blen);
+    }
+  }
+  else if((type & CLIENTWRITE_EOS) && !data->req.no_body) {
+    failf(data, "transfer closed with outstanding read data remaining");
+    return CURLE_PARTIAL_FILE;
+  }
+
+  return CURLE_OK;
+}
+
+/* HTTP chunked Transfer-Encoding decoder */
+const struct Curl_cwtype Curl_httpchunk_unencoder = {
+  "chunked",
+  NULL,
+  cw_chunked_init,
+  cw_chunked_write,
+  cw_chunked_close,
+  sizeof(struct chunked_writer)
+};
+
+/* max length of a HTTP chunk that we want to generate */
+#define CURL_CHUNKED_MINLEN   (1024)
+#define CURL_CHUNKED_MAXLEN   (64 * 1024)
+
+struct chunked_reader {
+  struct Curl_creader super;
+  struct bufq chunkbuf;
+  BIT(read_eos);  /* we read an EOS from the next reader */
+  BIT(eos);       /* we have returned an EOS */
+};
+
+static CURLcode cr_chunked_init(struct Curl_easy *data,
+                                struct Curl_creader *reader)
+{
+  struct chunked_reader *ctx = reader->ctx;
+  (void)data;
+  Curl_bufq_init2(&ctx->chunkbuf, CURL_CHUNKED_MAXLEN, 2, BUFQ_OPT_SOFT_LIMIT);
+  return CURLE_OK;
+}
+
+static void cr_chunked_close(struct Curl_easy *data,
+                             struct Curl_creader *reader)
+{
+  struct chunked_reader *ctx = reader->ctx;
+  (void)data;
+  Curl_bufq_free(&ctx->chunkbuf);
+}
+
+static CURLcode add_last_chunk(struct Curl_easy *data,
+                               struct Curl_creader *reader)
+{
+  struct chunked_reader *ctx = reader->ctx;
+  struct curl_slist *trailers = NULL, *tr;
+  CURLcode result;
+  size_t n;
+  int rc;
+
+  if(!data->set.trailer_callback) {
+    CURL_TRC_READ(data, "http_chunk, added last, empty chunk");
+    return Curl_bufq_cwrite(&ctx->chunkbuf, STRCONST("0\r\n\r\n"), &n);
+  }
+
+  result = Curl_bufq_cwrite(&ctx->chunkbuf, STRCONST("0\r\n"), &n);
+  if(result)
+    goto out;
+
+  Curl_set_in_callback(data, true);
+  rc = data->set.trailer_callback(&trailers, data->set.trailer_data);
+  Curl_set_in_callback(data, false);
+
+  if(rc != CURL_TRAILERFUNC_OK) {
+    failf(data, "operation aborted by trailing headers callback");
+    result = CURLE_ABORTED_BY_CALLBACK;
+    goto out;
+  }
+
+  for(tr = trailers; tr; tr = tr->next) {
+    /* only add correctly formatted trailers */
+    char *ptr = strchr(tr->data, ':');
+    if(!ptr || *(ptr + 1) != ' ') {
+      infof(data, "Malformatted trailing header, skipping trailer");
+      continue;
+    }
+
+    result = Curl_bufq_cwrite(&ctx->chunkbuf, tr->data,
+                              strlen(tr->data), &n);
+    if(!result)
+      result = Curl_bufq_cwrite(&ctx->chunkbuf, STRCONST("\r\n"), &n);
+    if(result)
+      goto out;
+  }
+
+  result = Curl_bufq_cwrite(&ctx->chunkbuf, STRCONST("\r\n"), &n);
+
+out:
+  curl_slist_free_all(trailers);
+  CURL_TRC_READ(data, "http_chunk, added last chunk with trailers "
+                "from client -> %d", result);
+  return result;
+}
+
+static CURLcode add_chunk(struct Curl_easy *data,
+                          struct Curl_creader *reader,
+                          char *buf, size_t blen)
+{
+  struct chunked_reader *ctx = reader->ctx;
+  CURLcode result;
+  char tmp[CURL_CHUNKED_MINLEN];
+  size_t nread;
+  bool eos;
+
+  DEBUGASSERT(!ctx->read_eos);
+  blen = CURLMIN(blen, CURL_CHUNKED_MAXLEN); /* respect our buffer pref */
+  if(blen < sizeof(tmp)) {
+    /* small read, make a chunk of decent size */
+    buf = tmp;
+    blen = sizeof(tmp);
+  }
+  else {
+    /* larger read, make a chunk that will fit when read back */
+    blen -= (8 + 2 + 2); /* deduct max overhead, 8 hex + 2*crlf */
+  }
+
+  result = Curl_creader_read(data, reader->next, buf, blen, &nread, &eos);
+  if(result)
+    return result;
+  if(eos)
+    ctx->read_eos = TRUE;
+
+  if(nread) {
+    /* actually got bytes, wrap them into the chunkbuf */
+    char hd[11] = "";
+    int hdlen;
+    size_t n;
+
+    hdlen = msnprintf(hd, sizeof(hd), "%zx\r\n", nread);
+    if(hdlen <= 0)
+      return CURLE_READ_ERROR;
+    /* On a soft-limited bufq, we do not need to check that all was written */
+    result = Curl_bufq_cwrite(&ctx->chunkbuf, hd, hdlen, &n);
+    if(!result)
+      result = Curl_bufq_cwrite(&ctx->chunkbuf, buf, nread, &n);
+    if(!result)
+      result = Curl_bufq_cwrite(&ctx->chunkbuf, "\r\n", 2, &n);
+    CURL_TRC_READ(data, "http_chunk, made chunk of %zu bytes -> %d",
+                 nread, result);
+    if(result)
+      return result;
+  }
+
+  if(ctx->read_eos)
+    return add_last_chunk(data, reader);
+  return CURLE_OK;
+}
+
+static CURLcode cr_chunked_read(struct Curl_easy *data,
+                                struct Curl_creader *reader,
+                                char *buf, size_t blen,
+                                size_t *pnread, bool *peos)
+{
+  struct chunked_reader *ctx = reader->ctx;
+  CURLcode result = CURLE_READ_ERROR;
+
+  *pnread = 0;
+  *peos = ctx->eos;
+
+  if(!ctx->eos) {
+    if(!ctx->read_eos && Curl_bufq_is_empty(&ctx->chunkbuf)) {
+      /* Still getting data form the next reader, buffer is empty */
+      result = add_chunk(data, reader, buf, blen);
+      if(result)
+        return result;
+    }
+
+    if(!Curl_bufq_is_empty(&ctx->chunkbuf)) {
+      result = Curl_bufq_cread(&ctx->chunkbuf, buf, blen, pnread);
+      if(!result && ctx->read_eos && Curl_bufq_is_empty(&ctx->chunkbuf)) {
+        /* no more data, read all, done. */
+        ctx->eos = TRUE;
+        *peos = TRUE;
+      }
+      return result;
+    }
+  }
+  /* We may get here, because we are done or because callbacks paused */
+  DEBUGASSERT(ctx->eos || !ctx->read_eos);
+  return CURLE_OK;
+}
+
+static curl_off_t cr_chunked_total_length(struct Curl_easy *data,
+                                          struct Curl_creader *reader)
+{
+  /* this reader changes length depending on input */
+  (void)data;
+  (void)reader;
+  return -1;
+}
+
+/* HTTP chunked Transfer-Encoding encoder */
+const struct Curl_crtype Curl_httpchunk_encoder = {
+  "chunked",
+  cr_chunked_init,
+  cr_chunked_read,
+  cr_chunked_close,
+  Curl_creader_def_needs_rewind,
+  cr_chunked_total_length,
+  Curl_creader_def_resume_from,
+  Curl_creader_def_rewind,
+  Curl_creader_def_unpause,
+  Curl_creader_def_done,
+  sizeof(struct chunked_reader)
+};
+
+CURLcode Curl_httpchunk_add_reader(struct Curl_easy *data)
+{
+  struct Curl_creader *reader = NULL;
+  CURLcode result;
+
+  result = Curl_creader_create(&reader, data, &Curl_httpchunk_encoder,
+                               CURL_CR_TRANSFER_ENCODE);
+  if(!result)
+    result = Curl_creader_add(data, reader);
+
+  if(result && reader)
+    Curl_creader_free(data, reader);
+  return result;
+}
+
 #endif /* CURL_DISABLE_HTTP */
diff --git a/vendor/curl/lib/http_chunks.h b/vendor/curl/lib/http_chunks.h
index ed50713162..d3ecc36c77 100644
--- a/vendor/curl/lib/http_chunks.h
+++ b/vendor/curl/lib/http_chunks.h
@@ -24,6 +24,10 @@
  *
  ***************************************************************************/
 
+#ifndef CURL_DISABLE_HTTP
+
+#include "dynbuf.h"
+
 struct connectdata;
 
 /*
@@ -67,34 +71,75 @@ typedef enum {
      signalled If this is an empty trailer CHUNKE_STOP will be signalled.
      Otherwise the trailer will be broadcasted via Curl_client_write() and the
      next state will be CHUNK_TRAILER */
-  CHUNK_TRAILER_POSTCR
+  CHUNK_TRAILER_POSTCR,
+
+  /* Successfully de-chunked everything */
+  CHUNK_DONE,
+
+  /* Failed on seeing a bad or not correctly terminated chunk */
+  CHUNK_FAILED
 } ChunkyState;
 
 typedef enum {
-  CHUNKE_STOP = -1,
   CHUNKE_OK = 0,
   CHUNKE_TOO_LONG_HEX = 1,
   CHUNKE_ILLEGAL_HEX,
   CHUNKE_BAD_CHUNK,
   CHUNKE_BAD_ENCODING,
   CHUNKE_OUT_OF_MEMORY,
-  CHUNKE_PASSTHRU_ERROR, /* Curl_httpchunk_read() returns a CURLcode to use */
-  CHUNKE_LAST
+  CHUNKE_PASSTHRU_ERROR /* Curl_httpchunk_read() returns a CURLcode to use */
 } CHUNKcode;
 
-const char *Curl_chunked_strerror(CHUNKcode code);
-
 struct Curl_chunker {
   curl_off_t datasize;
   ChunkyState state;
+  CHUNKcode last_code;
+  struct dynbuf trailer; /* for chunked-encoded trailer */
   unsigned char hexindex;
-  char hexbuffer[ CHUNK_MAXNUM_LEN + 1]; /* +1 for null-terminator */
+  char hexbuffer[CHUNK_MAXNUM_LEN + 1]; /* +1 for null-terminator */
+  BIT(ignore_body); /* never write response body data */
 };
 
 /* The following functions are defined in http_chunks.c */
-void Curl_httpchunk_init(struct Curl_easy *data);
-CHUNKcode Curl_httpchunk_read(struct Curl_easy *data, char *datap,
-                              ssize_t length, ssize_t *wrote,
-                              CURLcode *passthru);
+void Curl_httpchunk_init(struct Curl_easy *data, struct Curl_chunker *ch,
+                         bool ignore_body);
+void Curl_httpchunk_free(struct Curl_easy *data, struct Curl_chunker *ch);
+void Curl_httpchunk_reset(struct Curl_easy *data, struct Curl_chunker *ch,
+                          bool ignore_body);
+
+/*
+ * Read BODY bytes in HTTP/1.1 chunked encoding from `buf` and return
+ * the amount of bytes consumed. The actual response bytes and trailer
+ * headers are written out to the client.
+ * On success, this will consume all bytes up to the end of the response,
+ * e.g. the last chunk, has been processed.
+ * @param data   the transfer involved
+ * @param ch     the chunker instance keeping state across calls
+ * @param buf    the response data
+ * @param blen   amount of bytes in `buf`
+ * @param pconsumed  on successful return, the number of bytes in `buf`
+ *                   consumed
+ *
+ * This function always uses ASCII hex values to accommodate non-ASCII hosts.
+ * For example, 0x0d and 0x0a are used instead of '\r' and '\n'.
+ */
+CURLcode Curl_httpchunk_read(struct Curl_easy *data, struct Curl_chunker *ch,
+                             char *buf, size_t blen, size_t *pconsumed);
+
+/**
+ * @return TRUE iff chunked decoded has finished successfully.
+ */
+bool Curl_httpchunk_is_done(struct Curl_easy *data, struct Curl_chunker *ch);
+
+extern const struct Curl_cwtype Curl_httpchunk_unencoder;
+
+extern const struct Curl_crtype Curl_httpchunk_encoder;
+
+/**
+ * Add a transfer-encoding "chunked" reader to the transfers reader stack
+ */
+CURLcode Curl_httpchunk_add_reader(struct Curl_easy *data);
+
+#endif /* !CURL_DISABLE_HTTP */
 
 #endif /* HEADER_CURL_HTTP_CHUNKS_H */
diff --git a/vendor/curl/lib/http_negotiate.c b/vendor/curl/lib/http_negotiate.c
index 153e3d4ab8..4cbe2df42a 100644
--- a/vendor/curl/lib/http_negotiate.c
+++ b/vendor/curl/lib/http_negotiate.c
@@ -120,16 +120,29 @@ CURLcode Curl_input_negotiate(struct Curl_easy *data, struct connectdata *conn,
 CURLcode Curl_output_negotiate(struct Curl_easy *data,
                                struct connectdata *conn, bool proxy)
 {
-  struct negotiatedata *neg_ctx = proxy ? &conn->proxyneg :
-    &conn->negotiate;
-  struct auth *authp = proxy ? &data->state.authproxy : &data->state.authhost;
-  curlnegotiate *state = proxy ? &conn->proxy_negotiate_state :
-    &conn->http_negotiate_state;
+  struct negotiatedata *neg_ctx;
+  struct auth *authp;
+  curlnegotiate *state;
   char *base64 = NULL;
   size_t len = 0;
   char *userp;
   CURLcode result;
 
+  if(proxy) {
+#ifndef CURL_DISABLE_PROXY
+    neg_ctx = &conn->proxyneg;
+    authp = &data->state.authproxy;
+    state = &conn->proxy_negotiate_state;
+#else
+    return CURLE_NOT_BUILT_IN;
+#endif
+  }
+  else {
+    neg_ctx = &conn->negotiate;
+    authp = &data->state.authhost;
+    state = &conn->http_negotiate_state;
+  }
+
   authp->done = FALSE;
 
   if(*state == GSS_AUTHRECV) {
@@ -171,8 +184,10 @@ CURLcode Curl_output_negotiate(struct Curl_easy *data,
                     base64);
 
     if(proxy) {
+#ifndef CURL_DISABLE_PROXY
       Curl_safefree(data->state.aptr.proxyuserpwd);
       data->state.aptr.proxyuserpwd = userp;
+#endif
     }
     else {
       Curl_safefree(data->state.aptr.userpwd);
diff --git a/vendor/curl/lib/http_ntlm.c b/vendor/curl/lib/http_ntlm.c
index b845ddf37f..3dccb5cb78 100644
--- a/vendor/curl/lib/http_ntlm.c
+++ b/vendor/curl/lib/http_ntlm.c
@@ -40,7 +40,6 @@
 #include "strcase.h"
 #include "http_ntlm.h"
 #include "curl_ntlm_core.h"
-#include "curl_ntlm_wb.h"
 #include "curl_base64.h"
 #include "vauth/vauth.h"
 #include "url.h"
@@ -266,10 +265,6 @@ void Curl_http_auth_cleanup_ntlm(struct connectdata *conn)
 {
   Curl_auth_cleanup_ntlm(&conn->ntlm);
   Curl_auth_cleanup_ntlm(&conn->proxyntlm);
-
-#if defined(NTLM_WB_ENABLED)
-  Curl_http_auth_cleanup_ntlm_wb(conn);
-#endif
 }
 
 #endif /* !CURL_DISABLE_HTTP && USE_NTLM */
diff --git a/vendor/curl/lib/http_proxy.c b/vendor/curl/lib/http_proxy.c
index 60bbfbe580..7c035d4b60 100644
--- a/vendor/curl/lib/http_proxy.c
+++ b/vendor/curl/lib/http_proxy.c
@@ -52,6 +52,113 @@
 #include "memdebug.h"
 
 
+CURLcode Curl_http_proxy_get_destination(struct Curl_cfilter *cf,
+                                         const char **phostname,
+                                         int *pport, bool *pipv6_ip)
+{
+  DEBUGASSERT(cf);
+  DEBUGASSERT(cf->conn);
+
+  if(cf->conn->bits.conn_to_host)
+    *phostname = cf->conn->conn_to_host.name;
+  else if(cf->sockindex == SECONDARYSOCKET)
+    *phostname = cf->conn->secondaryhostname;
+  else
+    *phostname = cf->conn->host.name;
+
+  if(cf->sockindex == SECONDARYSOCKET)
+    *pport = cf->conn->secondary_port;
+  else if(cf->conn->bits.conn_to_port)
+    *pport = cf->conn->conn_to_port;
+  else
+    *pport = cf->conn->remote_port;
+
+  if(*phostname != cf->conn->host.name)
+    *pipv6_ip = (strchr(*phostname, ':') != NULL);
+  else
+    *pipv6_ip = cf->conn->bits.ipv6_ip;
+
+  return CURLE_OK;
+}
+
+CURLcode Curl_http_proxy_create_CONNECT(struct httpreq **preq,
+                                        struct Curl_cfilter *cf,
+                                        struct Curl_easy *data,
+                                        int http_version_major)
+{
+  const char *hostname = NULL;
+  char *authority = NULL;
+  int port;
+  bool ipv6_ip;
+  CURLcode result;
+  struct httpreq *req = NULL;
+
+  result = Curl_http_proxy_get_destination(cf, &hostname, &port, &ipv6_ip);
+  if(result)
+    goto out;
+
+  authority = aprintf("%s%s%s:%d", ipv6_ip?"[":"", hostname,
+                      ipv6_ip?"]":"", port);
+  if(!authority) {
+    result = CURLE_OUT_OF_MEMORY;
+    goto out;
+  }
+
+  result = Curl_http_req_make(&req, "CONNECT", sizeof("CONNECT")-1,
+                              NULL, 0, authority, strlen(authority),
+                              NULL, 0);
+  if(result)
+    goto out;
+
+  /* Setup the proxy-authorization header, if any */
+  result = Curl_http_output_auth(data, cf->conn, req->method, HTTPREQ_GET,
+                                 req->authority, TRUE);
+  if(result)
+    goto out;
+
+  /* If user is not overriding Host: header, we add for HTTP/1.x */
+  if(http_version_major == 1 &&
+     !Curl_checkProxyheaders(data, cf->conn, STRCONST("Host"))) {
+    result = Curl_dynhds_cadd(&req->headers, "Host", authority);
+    if(result)
+      goto out;
+  }
+
+  if(data->state.aptr.proxyuserpwd) {
+    result = Curl_dynhds_h1_cadd_line(&req->headers,
+                                      data->state.aptr.proxyuserpwd);
+    if(result)
+      goto out;
+  }
+
+  if(!Curl_checkProxyheaders(data, cf->conn, STRCONST("User-Agent")) &&
+     data->set.str[STRING_USERAGENT] && *data->set.str[STRING_USERAGENT]) {
+    result = Curl_dynhds_cadd(&req->headers, "User-Agent",
+                              data->set.str[STRING_USERAGENT]);
+    if(result)
+      goto out;
+  }
+
+  if(http_version_major == 1 &&
+    !Curl_checkProxyheaders(data, cf->conn, STRCONST("Proxy-Connection"))) {
+    result = Curl_dynhds_cadd(&req->headers, "Proxy-Connection", "Keep-Alive");
+    if(result)
+      goto out;
+  }
+
+  result = Curl_dynhds_add_custom(data, TRUE, &req->headers);
+
+out:
+  if(result && req) {
+    Curl_http_req_free(req);
+    req = NULL;
+  }
+  free(authority);
+  *preq = req;
+  return result;
+}
+
+
 struct cf_proxy_ctx {
   /* the protocol specific sub-filter we install during connect */
   struct Curl_cfilter *cf_protocol;
@@ -105,7 +212,6 @@ static CURLcode http_proxy_cf_connect(struct Curl_cfilter *cf,
       break;
 #endif
     default:
-      CURL_TRC_CF(data, cf, "installing subfilter for default HTTP/1.1");
       infof(data, "CONNECT tunnel: unsupported ALPN(%d) negotiated", alpn);
       result = CURLE_COULDNT_CONNECT;
       goto out;
@@ -187,13 +293,13 @@ static void http_proxy_cf_close(struct Curl_cfilter *cf,
 
 struct Curl_cftype Curl_cft_http_proxy = {
   "HTTP-PROXY",
-  CF_TYPE_IP_CONNECT,
+  CF_TYPE_IP_CONNECT|CF_TYPE_PROXY,
   0,
   http_proxy_cf_destroy,
   http_proxy_cf_connect,
   http_proxy_cf_close,
   Curl_cf_http_proxy_get_host,
-  Curl_cf_def_get_select_socks,
+  Curl_cf_def_adjust_pollset,
   Curl_cf_def_data_pending,
   Curl_cf_def_send,
   Curl_cf_def_recv,
diff --git a/vendor/curl/lib/http_proxy.h b/vendor/curl/lib/http_proxy.h
index a1a03720bd..2b5f7ae706 100644
--- a/vendor/curl/lib/http_proxy.h
+++ b/vendor/curl/lib/http_proxy.h
@@ -30,6 +30,15 @@
 
 #include "urldata.h"
 
+CURLcode Curl_http_proxy_get_destination(struct Curl_cfilter *cf,
+                                         const char **phostname,
+                                         int *pport, bool *pipv6_ip);
+
+CURLcode Curl_http_proxy_create_CONNECT(struct httpreq **preq,
+                                        struct Curl_cfilter *cf,
+                                        struct Curl_easy *data,
+                                        int http_version_major);
+
 /* Default proxy timeout in milliseconds */
 #define PROXY_TIMEOUT (3600*1000)
 
diff --git a/vendor/curl/lib/idn.c b/vendor/curl/lib/idn.c
index 1f31a9546c..c795672544 100644
--- a/vendor/curl/lib/idn.c
+++ b/vendor/curl/lib/idn.c
@@ -36,7 +36,7 @@
 #ifdef USE_LIBIDN2
 #include 
 
-#if defined(WIN32) && defined(UNICODE)
+#if defined(_WIN32) && defined(UNICODE)
 #define IDN2_LOOKUP(name, host, flags)                                  \
   idn2_lookup_u8((const uint8_t *)name, (uint8_t **)host, flags)
 #else
@@ -50,6 +50,63 @@
 #include "curl_memory.h"
 #include "memdebug.h"
 
+/* for macOS and iOS targets */
+#if defined(USE_APPLE_IDN)
+#include 
+
+static CURLcode mac_idn_to_ascii(const char *in, char **out)
+{
+  UErrorCode err = U_ZERO_ERROR;
+  UIDNA* idna = uidna_openUTS46(UIDNA_CHECK_BIDI, &err);
+  if(U_FAILURE(err)) {
+    return CURLE_OUT_OF_MEMORY;
+  }
+  else {
+    UIDNAInfo info = UIDNA_INFO_INITIALIZER;
+    char buffer[256] = {0};
+    (void)uidna_nameToASCII_UTF8(idna, in, -1, buffer,
+      sizeof(buffer), &info, &err);
+    uidna_close(idna);
+    if(U_FAILURE(err)) {
+      return CURLE_URL_MALFORMAT;
+    }
+    else {
+      *out = strdup(buffer);
+      if(*out)
+        return CURLE_OK;
+      else
+        return CURLE_OUT_OF_MEMORY;
+    }
+  }
+}
+
+static CURLcode mac_ascii_to_idn(const char *in, char **out)
+{
+  UErrorCode err = U_ZERO_ERROR;
+  UIDNA* idna = uidna_openUTS46(UIDNA_CHECK_BIDI, &err);
+  if(U_FAILURE(err)) {
+    return CURLE_OUT_OF_MEMORY;
+  }
+  else {
+    UIDNAInfo info = UIDNA_INFO_INITIALIZER;
+    char buffer[256] = {0};
+    (void)uidna_nameToUnicodeUTF8(idna, in, -1, buffer,
+      sizeof(buffer), &info, &err);
+    uidna_close(idna);
+    if(U_FAILURE(err)) {
+      return CURLE_URL_MALFORMAT;
+    }
+    else {
+      *out = strdup(buffer);
+      if(*out)
+        return CURLE_OK;
+      else
+        return CURLE_OUT_OF_MEMORY;
+    }
+  }
+}
+#endif
+
 #ifdef USE_WIN32_IDN
 /* using Windows kernel32 and normaliz libraries. */
 
@@ -91,6 +148,8 @@ static CURLcode win32_idn_to_ascii(const char *in, char **out)
     else
       return CURLE_URL_MALFORMAT;
   }
+  else
+    return CURLE_URL_MALFORMAT;
 
   return CURLE_OK;
 }
@@ -174,8 +233,13 @@ static CURLcode idn_decode(const char *input, char **output)
     if(rc != IDN2_OK)
       result = CURLE_URL_MALFORMAT;
   }
+  else
+    /* a too old libidn2 version */
+    result = CURLE_NOT_BUILT_IN;
 #elif defined(USE_WIN32_IDN)
   result = win32_idn_to_ascii(input, &decoded);
+#elif defined(USE_APPLE_IDN)
+  result = mac_idn_to_ascii(input, &decoded);
 #endif
   if(!result)
     *output = decoded;
@@ -193,6 +257,10 @@ static CURLcode idn_encode(const char *puny, char **output)
   CURLcode result = win32_ascii_to_idn(puny, &enc);
   if(result)
     return result;
+#elif defined(USE_APPLE_IDN)
+  CURLcode result = mac_ascii_to_idn(puny, &enc);
+  if(result)
+    return result;
 #endif
   *output = enc;
   return CURLE_OK;
@@ -241,11 +309,7 @@ CURLcode Curl_idn_encode(const char *puny, char **output)
  */
 void Curl_free_idnconverted_hostname(struct hostname *host)
 {
-  if(host->encalloc) {
-    /* must be freed with idn2_free() if allocated by libidn */
-    Curl_idn_free(host->encalloc);
-    host->encalloc = NULL;
-  }
+  Curl_safefree(host->encalloc);
 }
 
 #endif /* USE_IDN */
@@ -262,20 +326,11 @@ CURLcode Curl_idnconvert_hostname(struct hostname *host)
   /* Check name for non-ASCII and convert hostname if we can */
   if(!Curl_is_ASCII_name(host->name)) {
     char *decoded;
-    CURLcode result = idn_decode(host->name, &decoded);
-    if(!result) {
-      if(!*decoded) {
-        /* zero length is a bad host name */
-        Curl_idn_free(decoded);
-        return CURLE_URL_MALFORMAT;
-      }
-      /* successful */
-      host->encalloc = decoded;
-      /* change the name pointer to point to the encoded hostname */
-      host->name = host->encalloc;
-    }
-    else
+    CURLcode result = Curl_idn_decode(host->name, &decoded);
+    if(result)
       return result;
+    /* successful */
+    host->name = host->encalloc = decoded;
   }
 #endif
   return CURLE_OK;
diff --git a/vendor/curl/lib/idn.h b/vendor/curl/lib/idn.h
index 74bbcaf498..2bdce8927f 100644
--- a/vendor/curl/lib/idn.h
+++ b/vendor/curl/lib/idn.h
@@ -26,16 +26,11 @@
 
 bool Curl_is_ASCII_name(const char *hostname);
 CURLcode Curl_idnconvert_hostname(struct hostname *host);
-#if defined(USE_LIBIDN2) || defined(USE_WIN32_IDN)
+#if defined(USE_LIBIDN2) || defined(USE_WIN32_IDN) || defined(USE_APPLE_IDN)
 #define USE_IDN
 void Curl_free_idnconverted_hostname(struct hostname *host);
 CURLcode Curl_idn_decode(const char *input, char **output);
 CURLcode Curl_idn_encode(const char *input, char **output);
-#ifdef USE_LIBIDN2
-#define Curl_idn_free(x) idn2_free(x)
-#else
-#define Curl_idn_free(x) free(x)
-#endif
 
 #else
 #define Curl_free_idnconverted_hostname(x)
diff --git a/vendor/curl/lib/if2ip.c b/vendor/curl/lib/if2ip.c
index 5249f6cc7e..42e14500bc 100644
--- a/vendor/curl/lib/if2ip.c
+++ b/vendor/curl/lib/if2ip.c
@@ -62,7 +62,7 @@
 
 /* ------------------------------------------------------------------ */
 
-#ifdef ENABLE_IPV6
+#ifdef USE_IPV6
 /* Return the scope of the given address. */
 unsigned int Curl_ipv6_scope(const struct sockaddr *sa)
 {
@@ -97,17 +97,17 @@ unsigned int Curl_ipv6_scope(const struct sockaddr *sa)
 #if defined(HAVE_GETIFADDRS)
 
 if2ip_result_t Curl_if2ip(int af,
-#ifdef ENABLE_IPV6
+#ifdef USE_IPV6
                           unsigned int remote_scope,
                           unsigned int local_scope_id,
 #endif
                           const char *interf,
-                          char *buf, int buf_size)
+                          char *buf, size_t buf_size)
 {
   struct ifaddrs *iface, *head;
   if2ip_result_t res = IF2IP_NOT_FOUND;
 
-#if defined(ENABLE_IPV6) && \
+#if defined(USE_IPV6) && \
     !defined(HAVE_SOCKADDR_IN6_SIN6_SCOPE_ID)
   (void) local_scope_id;
 #endif
@@ -121,7 +121,7 @@ if2ip_result_t Curl_if2ip(int af,
             const char *ip;
             char scope[12] = "";
             char ipstr[64];
-#ifdef ENABLE_IPV6
+#ifdef USE_IPV6
             if(af == AF_INET6) {
 #ifdef HAVE_SOCKADDR_IN6_SIN6_SCOPE_ID
               unsigned int scopeid = 0;
@@ -182,12 +182,12 @@ if2ip_result_t Curl_if2ip(int af,
 #elif defined(HAVE_IOCTL_SIOCGIFADDR)
 
 if2ip_result_t Curl_if2ip(int af,
-#ifdef ENABLE_IPV6
+#ifdef USE_IPV6
                           unsigned int remote_scope,
                           unsigned int local_scope_id,
 #endif
                           const char *interf,
-                          char *buf, int buf_size)
+                          char *buf, size_t buf_size)
 {
   struct ifreq req;
   struct in_addr in;
@@ -196,7 +196,7 @@ if2ip_result_t Curl_if2ip(int af,
   size_t len;
   const char *r;
 
-#ifdef ENABLE_IPV6
+#ifdef USE_IPV6
   (void)remote_scope;
   (void)local_scope_id;
 #endif
@@ -237,15 +237,15 @@ if2ip_result_t Curl_if2ip(int af,
 #else
 
 if2ip_result_t Curl_if2ip(int af,
-#ifdef ENABLE_IPV6
+#ifdef USE_IPV6
                           unsigned int remote_scope,
                           unsigned int local_scope_id,
 #endif
                           const char *interf,
-                          char *buf, int buf_size)
+                          char *buf, size_t buf_size)
 {
     (void) af;
-#ifdef ENABLE_IPV6
+#ifdef USE_IPV6
     (void) remote_scope;
     (void) local_scope_id;
 #endif
diff --git a/vendor/curl/lib/if2ip.h b/vendor/curl/lib/if2ip.h
index 1f973505c0..f4b2f4c15d 100644
--- a/vendor/curl/lib/if2ip.h
+++ b/vendor/curl/lib/if2ip.h
@@ -32,7 +32,7 @@
 #define IPV6_SCOPE_UNIQUELOCAL  3       /* Unique local */
 #define IPV6_SCOPE_NODELOCAL    4       /* Loopback. */
 
-#ifdef ENABLE_IPV6
+#ifdef USE_IPV6
 unsigned int Curl_ipv6_scope(const struct sockaddr *sa);
 #else
 #define Curl_ipv6_scope(x) 0
@@ -45,12 +45,12 @@ typedef enum {
 } if2ip_result_t;
 
 if2ip_result_t Curl_if2ip(int af,
-#ifdef ENABLE_IPV6
+#ifdef USE_IPV6
                           unsigned int remote_scope,
                           unsigned int local_scope_id,
 #endif
                           const char *interf,
-                          char *buf, int buf_size);
+                          char *buf, size_t buf_size);
 
 #ifdef __INTERIX
 
diff --git a/vendor/curl/lib/imap.c b/vendor/curl/lib/imap.c
index de64c2a7f2..f6e98bd81d 100644
--- a/vendor/curl/lib/imap.c
+++ b/vendor/curl/lib/imap.c
@@ -97,7 +97,8 @@ static CURLcode imap_doing(struct Curl_easy *data, bool *dophase_done);
 static CURLcode imap_setup_connection(struct Curl_easy *data,
                                       struct connectdata *conn);
 static char *imap_atom(const char *str, bool escape_only);
-static CURLcode imap_sendf(struct Curl_easy *data, const char *fmt, ...);
+static CURLcode imap_sendf(struct Curl_easy *data, const char *fmt, ...)
+  CURL_PRINTF(2, 3);
 static CURLcode imap_parse_url_options(struct connectdata *conn);
 static CURLcode imap_parse_url_path(struct Curl_easy *data);
 static CURLcode imap_parse_custom_request(struct Curl_easy *data);
@@ -116,7 +117,7 @@ static CURLcode imap_get_message(struct Curl_easy *data, struct bufref *out);
  */
 
 const struct Curl_handler Curl_handler_imap = {
-  "IMAP",                           /* scheme */
+  "imap",                           /* scheme */
   imap_setup_connection,            /* setup_connection */
   imap_do,                          /* do_it */
   imap_done,                        /* done */
@@ -129,7 +130,8 @@ const struct Curl_handler Curl_handler_imap = {
   ZERO_NULL,                        /* domore_getsock */
   ZERO_NULL,                        /* perform_getsock */
   imap_disconnect,                  /* disconnect */
-  ZERO_NULL,                        /* readwrite */
+  ZERO_NULL,                        /* write_resp */
+  ZERO_NULL,                        /* write_resp_hd */
   ZERO_NULL,                        /* connection_check */
   ZERO_NULL,                        /* attach connection */
   PORT_IMAP,                        /* defport */
@@ -145,7 +147,7 @@ const struct Curl_handler Curl_handler_imap = {
  */
 
 const struct Curl_handler Curl_handler_imaps = {
-  "IMAPS",                          /* scheme */
+  "imaps",                          /* scheme */
   imap_setup_connection,            /* setup_connection */
   imap_do,                          /* do_it */
   imap_done,                        /* done */
@@ -158,7 +160,8 @@ const struct Curl_handler Curl_handler_imaps = {
   ZERO_NULL,                        /* domore_getsock */
   ZERO_NULL,                        /* perform_getsock */
   imap_disconnect,                  /* disconnect */
-  ZERO_NULL,                        /* readwrite */
+  ZERO_NULL,                        /* write_resp */
+  ZERO_NULL,                        /* write_resp_hd */
   ZERO_NULL,                        /* connection_check */
   ZERO_NULL,                        /* attach connection */
   PORT_IMAPS,                       /* defport */
@@ -354,8 +357,8 @@ static bool imap_endofresp(struct Curl_easy *data, struct connectdata *conn,
  */
 static CURLcode imap_get_message(struct Curl_easy *data, struct bufref *out)
 {
-  char *message = data->state.buffer;
-  size_t len = strlen(message);
+  char *message = Curl_dyn_ptr(&data->conn->proto.imapc.pp.recvbuf);
+  size_t len = data->conn->proto.imapc.pp.nfinal;
 
   if(len > 2) {
     /* Find the start of the message */
@@ -769,6 +772,7 @@ static CURLcode imap_perform_append(struct Curl_easy *data)
     return CURLE_URL_MALFORMAT;
   }
 
+#ifndef CURL_DISABLE_MIME
   /* Prepare the mime data if some. */
   if(data->set.mimepost.kind != MIMEKIND_NONE) {
     /* Use the whole structure as data. */
@@ -784,18 +788,18 @@ static CURLcode imap_perform_append(struct Curl_easy *data)
         result = Curl_mime_add_header(&data->set.mimepost.curlheaders,
                                       "Mime-Version: 1.0");
 
-    /* Make sure we will read the entire mime structure. */
     if(!result)
-      result = Curl_mime_rewind(&data->set.mimepost);
-
+      result = Curl_creader_set_mime(data, &data->set.mimepost);
+    if(result)
+      return result;
+    data->state.infilesize = Curl_creader_client_length(data);
+  }
+  else
+#endif
+  {
+    result = Curl_creader_set_fread(data, data->state.infilesize);
     if(result)
       return result;
-
-    data->state.infilesize = Curl_mime_size(&data->set.mimepost);
-
-    /* Read from mime structure. */
-    data->state.fread_func = (curl_read_callback) Curl_mime_read;
-    data->state.in = (void *) &data->set.mimepost;
   }
 
   /* Check we know the size of the upload */
@@ -895,7 +899,7 @@ static CURLcode imap_state_capability_resp(struct Curl_easy *data,
   CURLcode result = CURLE_OK;
   struct connectdata *conn = data->conn;
   struct imap_conn *imapc = &conn->proto.imapc;
-  const char *line = data->state.buffer;
+  const char *line = Curl_dyn_ptr(&imapc->pp.recvbuf);
 
   (void)instate; /* no use for this yet */
 
@@ -981,7 +985,7 @@ static CURLcode imap_state_starttls_resp(struct Curl_easy *data,
   (void)instate; /* no use for this yet */
 
   /* Pipelining in response is forbidden. */
-  if(data->conn->proto.imapc.pp.cache_size)
+  if(data->conn->proto.imapc.pp.overflow)
     return CURLE_WEIRD_SERVER_REPLY;
 
   if(imapcode != IMAP_RESP_OK) {
@@ -1057,17 +1061,13 @@ static CURLcode imap_state_listsearch_resp(struct Curl_easy *data,
                                            imapstate instate)
 {
   CURLcode result = CURLE_OK;
-  char *line = data->state.buffer;
-  size_t len = strlen(line);
+  char *line = Curl_dyn_ptr(&data->conn->proto.imapc.pp.recvbuf);
+  size_t len = data->conn->proto.imapc.pp.nfinal;
 
   (void)instate; /* No use for this yet */
 
-  if(imapcode == '*') {
-    /* Temporarily add the LF character back and send as body to the client */
-    line[len] = '\n';
-    result = Curl_client_write(data, CLIENTWRITE_BODY, line, len + 1);
-    line[len] = '\0';
-  }
+  if(imapcode == '*')
+    result = Curl_client_write(data, CLIENTWRITE_BODY, line, len);
   else if(imapcode != IMAP_RESP_OK)
     result = CURLE_QUOTE_ERROR;
   else
@@ -1085,7 +1085,7 @@ static CURLcode imap_state_select_resp(struct Curl_easy *data, int imapcode,
   struct connectdata *conn = data->conn;
   struct IMAP *imap = data->req.p.imap;
   struct imap_conn *imapc = &conn->proto.imapc;
-  const char *line = data->state.buffer;
+  const char *line = Curl_dyn_ptr(&data->conn->proto.imapc.pp.recvbuf);
 
   (void)instate; /* no use for this yet */
 
@@ -1144,7 +1144,8 @@ static CURLcode imap_state_fetch_resp(struct Curl_easy *data,
   CURLcode result = CURLE_OK;
   struct imap_conn *imapc = &conn->proto.imapc;
   struct pingpong *pp = &imapc->pp;
-  const char *ptr = data->state.buffer;
+  const char *ptr = Curl_dyn_ptr(&data->conn->proto.imapc.pp.recvbuf);
+  size_t len = data->conn->proto.imapc.pp.nfinal;
   bool parsed = FALSE;
   curl_off_t size = 0;
 
@@ -1158,16 +1159,12 @@ static CURLcode imap_state_fetch_resp(struct Curl_easy *data,
 
   /* Something like this is received "* 1 FETCH (BODY[TEXT] {2021}\r" so parse
      the continuation data contained within the curly brackets */
-  while(*ptr && (*ptr != '{'))
-    ptr++;
-
-  if(*ptr == '{') {
+  ptr = memchr(ptr, '{', len);
+  if(ptr) {
     char *endptr;
-    if(!curlx_strtoofft(ptr + 1, &endptr, 10, &size)) {
-      if(endptr - ptr > 1 && endptr[0] == '}' &&
-         endptr[1] == '\r' && endptr[2] == '\0')
-        parsed = TRUE;
-    }
+    if(!curlx_strtoofft(ptr + 1, &endptr, 10, &size) &&
+       (endptr - ptr > 1 && *endptr == '}'))
+      parsed = TRUE;
   }
 
   if(parsed) {
@@ -1175,11 +1172,15 @@ static CURLcode imap_state_fetch_resp(struct Curl_easy *data,
           size);
     Curl_pgrsSetDownloadSize(data, size);
 
-    if(pp->cache) {
-      /* At this point there is a bunch of data in the header "cache" that is
-         actually body content, send it as body and then skip it. Do note
-         that there may even be additional "headers" after the body. */
-      size_t chunk = pp->cache_size;
+    if(pp->overflow) {
+      /* At this point there is a data in the receive buffer that is body
+         content, send it as body and then skip it. Do note that there may
+         even be additional "headers" after the body. */
+      size_t chunk = pp->overflow;
+
+      /* keep only the overflow */
+      Curl_dyn_tail(&pp->recvbuf, chunk);
+      pp->nfinal = 0; /* done */
 
       if(chunk > (size_t)size)
         /* The conversion from curl_off_t to size_t is always fine here */
@@ -1190,40 +1191,37 @@ static CURLcode imap_state_fetch_resp(struct Curl_easy *data,
         imap_state(data, IMAP_STOP);
         return CURLE_OK;
       }
-      result = Curl_client_write(data, CLIENTWRITE_BODY, pp->cache, chunk);
+      result = Curl_client_write(data, CLIENTWRITE_BODY,
+                                 Curl_dyn_ptr(&pp->recvbuf), chunk);
       if(result)
         return result;
 
-      data->req.bytecount += chunk;
-
       infof(data, "Written %zu bytes, %" CURL_FORMAT_CURL_OFF_TU
             " bytes are left for transfer", chunk, size - chunk);
 
-      /* Have we used the entire cache or just part of it?*/
-      if(pp->cache_size > chunk) {
-        /* Only part of it so shrink the cache to fit the trailing data */
-        memmove(pp->cache, pp->cache + chunk, pp->cache_size - chunk);
-        pp->cache_size -= chunk;
+      /* Have we used the entire overflow or just part of it?*/
+      if(pp->overflow > chunk) {
+        /* remember the remaining trailing overflow data */
+        pp->overflow -= chunk;
+        Curl_dyn_tail(&pp->recvbuf, pp->overflow);
       }
       else {
+        pp->overflow = 0; /* handled */
         /* Free the cache */
-        Curl_safefree(pp->cache);
-
-        /* Reset the cache size */
-        pp->cache_size = 0;
+        Curl_dyn_reset(&pp->recvbuf);
       }
     }
 
     if(data->req.bytecount == size)
       /* The entire data is already transferred! */
-      Curl_setup_transfer(data, -1, -1, FALSE, -1);
+      Curl_xfer_setup(data, -1, -1, FALSE, -1);
     else {
       /* IMAP download */
       data->req.maxdownload = size;
       /* force a recv/send check of this connection, as the data might've been
        read off the socket already */
-      data->conn->cselect_bits = CURL_CSELECT_IN;
-      Curl_setup_transfer(data, FIRSTSOCKET, size, FALSE, -1);
+      data->state.select_bits = CURL_CSELECT_IN;
+      Curl_xfer_setup(data, FIRSTSOCKET, size, FALSE, -1);
     }
   }
   else {
@@ -1271,7 +1269,7 @@ static CURLcode imap_state_append_resp(struct Curl_easy *data, int imapcode,
     Curl_pgrsSetUploadSize(data, data->state.infilesize);
 
     /* IMAP upload */
-    Curl_setup_transfer(data, -1, -1, FALSE, FIRSTSOCKET);
+    Curl_xfer_setup(data, -1, -1, FALSE, FIRSTSOCKET);
 
     /* End of DO phase */
     imap_state(data, IMAP_STOP);
@@ -1302,7 +1300,6 @@ static CURLcode imap_statemachine(struct Curl_easy *data,
                                   struct connectdata *conn)
 {
   CURLcode result = CURLE_OK;
-  curl_socket_t sock = conn->sock[FIRSTSOCKET];
   int imapcode;
   struct imap_conn *imapc = &conn->proto.imapc;
   struct pingpong *pp = &imapc->pp;
@@ -1319,7 +1316,7 @@ static CURLcode imap_statemachine(struct Curl_easy *data,
 
   do {
     /* Read the response from the server */
-    result = Curl_pp_readresp(data, sock, pp, &imapcode, &nread);
+    result = Curl_pp_readresp(data, FIRSTSOCKET, pp, &imapcode, &nread);
     if(result)
       return result;
 
@@ -1378,7 +1375,6 @@ static CURLcode imap_statemachine(struct Curl_easy *data,
       break;
 
     case IMAP_LOGOUT:
-      /* fallthrough, just stop! */
     default:
       /* internal error */
       imap_state(data, IMAP_STOP);
@@ -1430,7 +1426,7 @@ static CURLcode imap_init(struct Curl_easy *data)
   CURLcode result = CURLE_OK;
   struct IMAP *imap;
 
-  imap = data->req.p.imap = calloc(sizeof(struct IMAP), 1);
+  imap = data->req.p.imap = calloc(1, sizeof(struct IMAP));
   if(!imap)
     result = CURLE_OUT_OF_MEMORY;
 
@@ -1474,9 +1470,7 @@ static CURLcode imap_connect(struct Curl_easy *data, bool *done)
   Curl_sasl_init(&imapc->sasl, data, &saslimap);
 
   Curl_dyn_init(&imapc->dyn, DYN_IMAP_CMD);
-  /* Initialise the pingpong layer */
-  Curl_pp_setup(pp);
-  Curl_pp_init(data, pp);
+  Curl_pp_init(pp);
 
   /* Parse the URL options */
   result = imap_parse_url_options(conn);
@@ -1521,10 +1515,10 @@ static CURLcode imap_done(struct Curl_easy *data, CURLcode status,
   }
   else if(!data->set.connect_only && !imap->custom &&
           (imap->uid || imap->mindex || data->state.upload ||
-          data->set.mimepost.kind != MIMEKIND_NONE)) {
+          IS_MIME_POST(data))) {
     /* Handle responses after FETCH or APPEND transfer has finished */
 
-    if(!data->state.upload && data->set.mimepost.kind == MIMEKIND_NONE)
+    if(!data->state.upload && !IS_MIME_POST(data))
       imap_state(data, IMAP_FETCH_FINAL);
     else {
       /* End the APPEND command first by sending an empty line */
@@ -1590,7 +1584,7 @@ static CURLcode imap_perform(struct Curl_easy *data, bool *connected,
     selected = TRUE;
 
   /* Start the first command in the DO phase */
-  if(data->state.upload || data->set.mimepost.kind != MIMEKIND_NONE)
+  if(data->state.upload || IS_MIME_POST(data))
     /* APPEND can be executed directly */
     result = imap_perform_append(data);
   else if(imap->custom && (selected || !imap->mailbox))
@@ -1700,7 +1694,7 @@ static CURLcode imap_dophase_done(struct Curl_easy *data, bool connected)
 
   if(imap->transfer != PPTRANSFER_BODY)
     /* no data to transfer */
-    Curl_setup_transfer(data, -1, -1, FALSE, -1);
+    Curl_xfer_setup(data, -1, -1, FALSE, -1);
 
   return CURLE_OK;
 }
@@ -1797,7 +1791,14 @@ static CURLcode imap_sendf(struct Curl_easy *data, const char *fmt, ...)
   if(!result) {
     va_list ap;
     va_start(ap, fmt);
+#ifdef __clang__
+#pragma clang diagnostic push
+#pragma clang diagnostic ignored "-Wformat-nonliteral"
+#endif
     result = Curl_pp_vsendf(data, &imapc->pp, Curl_dyn_ptr(&imapc->dyn), ap);
+#ifdef __clang__
+#pragma clang diagnostic pop
+#endif
     va_end(ap);
   }
   return result;
diff --git a/vendor/curl/lib/inet_ntop.c b/vendor/curl/lib/inet_ntop.c
index 135f4866c6..4520b87150 100644
--- a/vendor/curl/lib/inet_ntop.c
+++ b/vendor/curl/lib/inet_ntop.c
@@ -42,11 +42,11 @@
 #define INT16SZ          2
 
 /*
- * If ENABLE_IPV6 is disabled, we still want to parse IPv6 addresses, so make
+ * If USE_IPV6 is disabled, we still want to parse IPv6 addresses, so make
  * sure we have _some_ value for AF_INET6 without polluting our fake value
  * everywhere.
  */
-#if !defined(ENABLE_IPV6) && !defined(AF_INET6)
+#if !defined(USE_IPV6) && !defined(AF_INET6)
 #define AF_INET6 (AF_INET + 1)
 #endif
 
@@ -96,10 +96,10 @@ static char *inet_ntop6 (const unsigned char *src, char *dst, size_t size)
   char tmp[sizeof("ffff:ffff:ffff:ffff:ffff:ffff:255.255.255.255")];
   char *tp;
   struct {
-    long base;
-    long len;
+    int base;
+    int len;
   } best, cur;
-  unsigned long words[IN6ADDRSZ / INT16SZ];
+  unsigned int words[IN6ADDRSZ / INT16SZ];
   int i;
 
   /* Preprocess:
@@ -108,7 +108,7 @@ static char *inet_ntop6 (const unsigned char *src, char *dst, size_t size)
    */
   memset(words, '\0', sizeof(words));
   for(i = 0; i < IN6ADDRSZ; i++)
-    words[i/2] |= (src[i] << ((1 - (i % 2)) << 3));
+    words[i/2] |= ((unsigned int)src[i] << ((1 - (i % 2)) << 3));
 
   best.base = -1;
   cur.base  = -1;
@@ -159,7 +159,7 @@ static char *inet_ntop6 (const unsigned char *src, char *dst, size_t size)
       tp += strlen(tp);
       break;
     }
-    tp += msnprintf(tp, 5, "%lx", words[i]);
+    tp += msnprintf(tp, 5, "%x", words[i]);
   }
 
   /* Was it a trailing run of 0x00's?
diff --git a/vendor/curl/lib/inet_pton.c b/vendor/curl/lib/inet_pton.c
index 7d3c698795..9cfcec1c9a 100644
--- a/vendor/curl/lib/inet_pton.c
+++ b/vendor/curl/lib/inet_pton.c
@@ -39,11 +39,11 @@
 #define INT16SZ          2
 
 /*
- * If ENABLE_IPV6 is disabled, we still want to parse IPv6 addresses, so make
+ * If USE_IPV6 is disabled, we still want to parse IPv6 addresses, so make
  * sure we have _some_ value for AF_INET6 without polluting our fake value
  * everywhere.
  */
-#if !defined(ENABLE_IPV6) && !defined(AF_INET6)
+#if !defined(USE_IPV6) && !defined(AF_INET6)
 #define AF_INET6 (AF_INET + 1)
 #endif
 
@@ -112,7 +112,8 @@ inet_pton4(const char *src, unsigned char *dst)
 
     pch = strchr(digits, ch);
     if(pch) {
-      unsigned int val = *tp * 10 + (unsigned int)(pch - digits);
+      unsigned int val = (unsigned int)(*tp * 10) +
+                         (unsigned int)(pch - digits);
 
       if(saw_digit && *tp == 0)
         return (0);
diff --git a/vendor/curl/lib/inet_pton.h b/vendor/curl/lib/inet_pton.h
index 82fde7e2eb..f8562fa8a7 100644
--- a/vendor/curl/lib/inet_pton.h
+++ b/vendor/curl/lib/inet_pton.h
@@ -31,9 +31,6 @@ int Curl_inet_pton(int, const char *, void *);
 #ifdef HAVE_INET_PTON
 #ifdef HAVE_ARPA_INET_H
 #include 
-#elif defined(HAVE_WS2TCPIP_H)
-/* inet_pton() exists in Vista or later */
-#include 
 #endif
 #define Curl_inet_pton(x,y,z) inet_pton(x,y,z)
 #endif
diff --git a/vendor/curl/lib/krb5.c b/vendor/curl/lib/krb5.c
index 18e73debbf..d355665b8e 100644
--- a/vendor/curl/lib/krb5.c
+++ b/vendor/curl/lib/krb5.c
@@ -52,6 +52,7 @@
 #include "ftp.h"
 #include "curl_gssapi.h"
 #include "sendf.h"
+#include "transfer.h"
 #include "curl_krb5.h"
 #include "warnless.h"
 #include "strcase.h"
@@ -65,7 +66,7 @@
 static CURLcode ftpsend(struct Curl_easy *data, struct connectdata *conn,
                         const char *cmd)
 {
-  ssize_t bytes_written;
+  size_t bytes_written;
 #define SBUF_SIZE 1024
   char s[SBUF_SIZE];
   size_t write_len;
@@ -75,8 +76,7 @@ static CURLcode ftpsend(struct Curl_easy *data, struct connectdata *conn,
   unsigned char data_sec = conn->data_prot;
 #endif
 
-  if(!cmd)
-    return CURLE_BAD_FUNCTION_ARGUMENT;
+  DEBUGASSERT(cmd);
 
   write_len = strlen(cmd);
   if(!write_len || write_len > (sizeof(s) -3))
@@ -91,8 +91,7 @@ static CURLcode ftpsend(struct Curl_easy *data, struct connectdata *conn,
 #ifdef HAVE_GSSAPI
     conn->data_prot = PROT_CMD;
 #endif
-    result = Curl_nwrite(data, FIRSTSOCKET, sptr, write_len,
-                        &bytes_written);
+    result = Curl_xfer_send(data, sptr, write_len, &bytes_written);
 #ifdef HAVE_GSSAPI
     DEBUGASSERT(data_sec > PROT_NONE && data_sec < PROT_LAST);
     conn->data_prot = data_sec;
@@ -101,9 +100,9 @@ static CURLcode ftpsend(struct Curl_easy *data, struct connectdata *conn,
     if(result)
       break;
 
-    Curl_debug(data, CURLINFO_HEADER_OUT, sptr, (size_t)bytes_written);
+    Curl_debug(data, CURLINFO_HEADER_OUT, sptr, bytes_written);
 
-    if(bytes_written != (ssize_t)write_len) {
+    if(bytes_written != write_len) {
       write_len -= bytes_written;
       sptr += bytes_written;
     }
@@ -236,9 +235,12 @@ krb5_auth(void *app_data, struct Curl_easy *data, struct connectdata *conn)
 
       if(Curl_GetFTPResponse(data, &nread, NULL))
         return -1;
-
-      if(data->state.buffer[0] != '3')
-        return -1;
+      else {
+        struct pingpong *pp = &conn->proto.ftpc.pp;
+        char *line = Curl_dyn_ptr(&pp->recvbuf);
+        if(line[0] != '3')
+          return -1;
+      }
     }
 
     stringp = aprintf("%s@%s", service, host);
@@ -322,15 +324,19 @@ krb5_auth(void *app_data, struct Curl_easy *data, struct connectdata *conn)
           ret = -1;
           break;
         }
-
-        if(data->state.buffer[0] != '2' && data->state.buffer[0] != '3') {
-          infof(data, "Server didn't accept auth data");
-          ret = AUTH_ERROR;
-          break;
+        else {
+          struct pingpong *pp = &conn->proto.ftpc.pp;
+          size_t len = Curl_dyn_len(&pp->recvbuf);
+          p = Curl_dyn_ptr(&pp->recvbuf);
+          if((len < 4) || (p[0] != '2' && p[0] != '3')) {
+            infof(data, "Server didn't accept auth data");
+            ret = AUTH_ERROR;
+            break;
+          }
         }
 
         _gssresp.value = NULL; /* make sure it is initialized */
-        p = data->state.buffer + 4;
+        p += 4; /* over '789 ' */
         p = strstr(p, "ADAT=");
         if(p) {
           result = Curl_base64_decode(p + 5,
@@ -417,7 +423,6 @@ static char level_to_char(int level)
   case PROT_PRIVATE:
     return 'P';
   case PROT_CMD:
-    /* Fall through */
   default:
     /* Those 2 cases should not be reached! */
     break;
@@ -429,6 +434,9 @@ static char level_to_char(int level)
 
 /* Send an FTP command defined by |message| and the optional arguments. The
    function returns the ftp_code. If an error occurs, -1 is returned. */
+static int ftp_send_command(struct Curl_easy *data, const char *message, ...)
+  CURL_PRINTF(2, 3);
+
 static int ftp_send_command(struct Curl_easy *data, const char *message, ...)
 {
   int ftp_code;
@@ -462,7 +470,7 @@ socket_read(struct Curl_easy *data, int sockindex, void *to, size_t len)
   ssize_t nread = 0;
 
   while(len > 0) {
-    nread = Curl_conn_recv(data, sockindex, to_p, len, &result);
+    result = Curl_conn_recv(data, sockindex, to_p, len, &nread);
     if(nread > 0) {
       len -= nread;
       to_p += nread;
@@ -486,11 +494,11 @@ socket_write(struct Curl_easy *data, int sockindex, const void *to,
 {
   const char *to_p = to;
   CURLcode result;
-  ssize_t written;
+  size_t written;
 
   while(len > 0) {
-    written = Curl_conn_send(data, sockindex, to_p, len, &result);
-    if(written > 0) {
+    result = Curl_conn_send(data, sockindex, to_p, len, &written);
+    if(!result && written > 0) {
       len -= written;
       to_p += written;
     }
@@ -516,24 +524,33 @@ static CURLcode read_data(struct Curl_easy *data, int sockindex,
     return result;
 
   if(len) {
-    /* only realloc if there was a length */
     len = ntohl(len);
     if(len > CURL_MAX_INPUT_LENGTH)
-      len = 0;
-    else
-      buf->data = Curl_saferealloc(buf->data, len);
+      return CURLE_TOO_LARGE;
+
+    Curl_dyn_reset(&buf->buf);
   }
-  if(!len || !buf->data)
-    return CURLE_OUT_OF_MEMORY;
+  else
+    return CURLE_RECV_ERROR;
 
-  result = socket_read(data, sockindex, buf->data, len);
-  if(result)
-    return result;
-  nread = conn->mech->decode(conn->app_data, buf->data, len,
-                             conn->data_prot, conn);
+  do {
+    char buffer[1024];
+    nread = CURLMIN(len, (int)sizeof(buffer));
+    result = socket_read(data, sockindex, buffer, nread);
+    if(result)
+      return result;
+    result = Curl_dyn_addn(&buf->buf, buffer, nread);
+    if(result)
+      return result;
+    len -= nread;
+  } while(len);
+  /* this decodes the dynbuf *in place* */
+  nread = conn->mech->decode(conn->app_data,
+                             Curl_dyn_ptr(&buf->buf),
+                             len, conn->data_prot, conn);
   if(nread < 0)
     return CURLE_RECV_ERROR;
-  buf->size = (size_t)nread;
+  Curl_dyn_setlen(&buf->buf, nread);
   buf->index = 0;
   return CURLE_OK;
 }
@@ -541,9 +558,10 @@ static CURLcode read_data(struct Curl_easy *data, int sockindex,
 static size_t
 buffer_read(struct krb5buffer *buf, void *data, size_t len)
 {
-  if(buf->size - buf->index < len)
-    len = buf->size - buf->index;
-  memcpy(data, (char *)buf->data + buf->index, len);
+  size_t size = Curl_dyn_len(&buf->buf);
+  if(size - buf->index < len)
+    len = size - buf->index;
+  memcpy(data, Curl_dyn_ptr(&buf->buf) + buf->index, len);
   buf->index += len;
   return len;
 }
@@ -559,8 +577,11 @@ static ssize_t sec_recv(struct Curl_easy *data, int sockindex,
   *err = CURLE_OK;
 
   /* Handle clear text response. */
-  if(conn->sec_complete == 0 || conn->data_prot == PROT_CLEAR)
-    return Curl_conn_recv(data, sockindex, buffer, len, err);
+  if(conn->sec_complete == 0 || conn->data_prot == PROT_CLEAR) {
+    ssize_t nread;
+    *err = Curl_conn_recv(data, sockindex, buffer, len, &nread);
+    return nread;
+  }
 
   if(conn->in_buffer.eof_flag) {
     conn->in_buffer.eof_flag = 0;
@@ -575,7 +596,7 @@ static ssize_t sec_recv(struct Curl_easy *data, int sockindex,
   while(len > 0) {
     if(read_data(data, sockindex, &conn->in_buffer))
       return -1;
-    if(conn->in_buffer.size == 0) {
+    if(Curl_dyn_len(&conn->in_buffer.buf) == 0) {
       if(bytes_read > 0)
         conn->in_buffer.eof_flag = 1;
       return bytes_read;
@@ -750,6 +771,8 @@ static int sec_set_protection_level(struct Curl_easy *data)
   if(level) {
     char *pbsz;
     unsigned int buffer_size = 1 << 20; /* 1048576 */
+    struct pingpong *pp = &conn->proto.ftpc.pp;
+    char *line;
 
     code = ftp_send_command(data, "PBSZ %u", buffer_size);
     if(code < 0)
@@ -761,10 +784,11 @@ static int sec_set_protection_level(struct Curl_easy *data)
     }
     conn->buffer_size = buffer_size;
 
-    pbsz = strstr(data->state.buffer, "PBSZ=");
+    line = Curl_dyn_ptr(&pp->recvbuf);
+    pbsz = strstr(line, "PBSZ=");
     if(pbsz) {
       /* stick to default value if the check fails */
-      if(!strncmp(pbsz, "PBSZ=", 5) && ISDIGIT(pbsz[5]))
+      if(ISDIGIT(pbsz[5]))
         buffer_size = atoi(&pbsz[5]);
       if(buffer_size < conn->buffer_size)
         conn->buffer_size = buffer_size;
@@ -821,6 +845,7 @@ static CURLcode choose_mech(struct Curl_easy *data, struct connectdata *conn)
             mech->name);
       return CURLE_FAILED_INIT;
     }
+    Curl_dyn_init(&conn->in_buffer.buf, CURL_MAX_INPUT_LENGTH);
   }
 
   infof(data, "Trying mechanism %s...", mech->name);
@@ -885,15 +910,10 @@ Curl_sec_end(struct connectdata *conn)
 {
   if(conn->mech && conn->mech->end)
     conn->mech->end(conn->app_data);
-  free(conn->app_data);
-  conn->app_data = NULL;
-  if(conn->in_buffer.data) {
-    free(conn->in_buffer.data);
-    conn->in_buffer.data = NULL;
-    conn->in_buffer.size = 0;
-    conn->in_buffer.index = 0;
-    conn->in_buffer.eof_flag = 0;
-  }
+  Curl_safefree(conn->app_data);
+  Curl_dyn_free(&conn->in_buffer.buf);
+  conn->in_buffer.index = 0;
+  conn->in_buffer.eof_flag = 0;
   conn->sec_complete = 0;
   conn->data_prot = PROT_CLEAR;
   conn->mech = NULL;
diff --git a/vendor/curl/lib/ldap.c b/vendor/curl/lib/ldap.c
index 33a4dea0a8..678b4d5af6 100644
--- a/vendor/curl/lib/ldap.c
+++ b/vendor/curl/lib/ldap.c
@@ -137,7 +137,7 @@ static void _ldap_free_urldesc(LDAPURLDesc *ludp);
                             _ldap_trace x; \
                           } while(0)
 
-  static void _ldap_trace(const char *fmt, ...);
+  static void _ldap_trace(const char *fmt, ...) CURL_PRINTF(1, 2);
 #else
   #define LDAP_TRACE(x)   Curl_nop_stmt
 #endif
@@ -164,7 +164,7 @@ static CURLcode ldap_do(struct Curl_easy *data, bool *done);
  */
 
 const struct Curl_handler Curl_handler_ldap = {
-  "LDAP",                               /* scheme */
+  "ldap",                               /* scheme */
   ZERO_NULL,                            /* setup_connection */
   ldap_do,                              /* do_it */
   ZERO_NULL,                            /* done */
@@ -177,7 +177,8 @@ const struct Curl_handler Curl_handler_ldap = {
   ZERO_NULL,                            /* domore_getsock */
   ZERO_NULL,                            /* perform_getsock */
   ZERO_NULL,                            /* disconnect */
-  ZERO_NULL,                            /* readwrite */
+  ZERO_NULL,                            /* write_resp */
+  ZERO_NULL,                            /* write_resp_hd */
   ZERO_NULL,                            /* connection_check */
   ZERO_NULL,                            /* attach connection */
   PORT_LDAP,                            /* defport */
@@ -192,7 +193,7 @@ const struct Curl_handler Curl_handler_ldap = {
  */
 
 const struct Curl_handler Curl_handler_ldaps = {
-  "LDAPS",                              /* scheme */
+  "ldaps",                              /* scheme */
   ZERO_NULL,                            /* setup_connection */
   ldap_do,                              /* do_it */
   ZERO_NULL,                            /* done */
@@ -205,7 +206,8 @@ const struct Curl_handler Curl_handler_ldaps = {
   ZERO_NULL,                            /* domore_getsock */
   ZERO_NULL,                            /* perform_getsock */
   ZERO_NULL,                            /* disconnect */
-  ZERO_NULL,                            /* readwrite */
+  ZERO_NULL,                            /* write_resp */
+  ZERO_NULL,                            /* write_resp_hd */
   ZERO_NULL,                            /* connection_check */
   ZERO_NULL,                            /* attach connection */
   PORT_LDAPS,                           /* defport */
@@ -313,7 +315,6 @@ static CURLcode ldap_do(struct Curl_easy *data, bool *done)
   int ldap_ssl = 0;
   char *val_b64 = NULL;
   size_t val_b64_sz = 0;
-  curl_off_t dlsize = 0;
 #ifdef LDAP_OPT_NETWORK_TIMEOUT
   struct timeval ldap_timeout = {10, 0}; /* 10 sec connection/search timeout */
 #endif
@@ -327,7 +328,7 @@ static CURLcode ldap_do(struct Curl_easy *data, bool *done)
 
   *done = TRUE; /* unconditionally */
   infof(data, "LDAP local: LDAP Vendor = %s ; LDAP Version = %d",
-          LDAP_VENDOR_NAME, LDAP_VENDOR_VERSION);
+        LDAP_VENDOR_NAME, LDAP_VENDOR_VERSION);
   infof(data, "LDAP local: %s", data->state.url);
 
 #ifdef HAVE_LDAP_URL_PARSE
@@ -345,7 +346,7 @@ static CURLcode ldap_do(struct Curl_easy *data, bool *done)
   if(conn->given->flags & PROTOPT_SSL)
     ldap_ssl = 1;
   infof(data, "LDAP local: trying to establish %s connection",
-          ldap_ssl ? "encrypted" : "cleartext");
+        ldap_ssl ? "encrypted" : "cleartext");
 
 #if defined(USE_WIN32_LDAP)
   host = curlx_convert_UTF8_to_tchar(conn->host.name);
@@ -372,7 +373,7 @@ static CURLcode ldap_do(struct Curl_easy *data, bool *done)
 #ifdef HAVE_LDAP_SSL
 #ifdef USE_WIN32_LDAP
     /* Win32 LDAP SDK doesn't support insecure mode without CA! */
-    server = ldap_sslinit(host, conn->port, 1);
+    server = ldap_sslinit(host, conn->primary.remote_port, 1);
     ldap_set_option(server, LDAP_OPT_SSL, LDAP_OPT_ON);
 #else
     int ldap_option;
@@ -418,10 +419,10 @@ static CURLcode ldap_do(struct Curl_easy *data, bool *done)
       result = CURLE_SSL_CERTPROBLEM;
       goto quit;
     }
-    server = ldapssl_init(host, conn->port, 1);
+    server = ldapssl_init(host, conn->primary.remote_port, 1);
     if(!server) {
       failf(data, "LDAP local: Cannot connect to %s:%u",
-            conn->host.dispname, conn->port);
+            conn->host.dispname, conn->primary.remote_port);
       result = CURLE_COULDNT_CONNECT;
       goto quit;
     }
@@ -459,10 +460,10 @@ static CURLcode ldap_do(struct Curl_easy *data, bool *done)
       result = CURLE_SSL_CERTPROBLEM;
       goto quit;
     }
-    server = ldap_init(host, conn->port);
+    server = ldap_init(host, conn->primary.remote_port);
     if(!server) {
       failf(data, "LDAP local: Cannot connect to %s:%u",
-            conn->host.dispname, conn->port);
+            conn->host.dispname, conn->primary.remote_port);
       result = CURLE_COULDNT_CONNECT;
       goto quit;
     }
@@ -484,6 +485,8 @@ static CURLcode ldap_do(struct Curl_easy *data, bool *done)
     }
 */
 #else
+    (void)ldap_option;
+    (void)ldap_ca;
     /* we should probably never come up to here since configure
        should check in first place if we can support LDAP SSL/TLS */
     failf(data, "LDAP local: SSL/TLS not supported with this version "
@@ -500,10 +503,10 @@ static CURLcode ldap_do(struct Curl_easy *data, bool *done)
     goto quit;
   }
   else {
-    server = ldap_init(host, conn->port);
+    server = ldap_init(host, conn->primary.remote_port);
     if(!server) {
       failf(data, "LDAP local: Cannot connect to %s:%u",
-            conn->host.dispname, conn->port);
+            conn->host.dispname, conn->primary.remote_port);
       result = CURLE_COULDNT_CONNECT;
       goto quit;
     }
@@ -535,6 +538,7 @@ static CURLcode ldap_do(struct Curl_easy *data, bool *done)
     goto quit;
   }
 
+  Curl_pgrsSetDownloadCounter(data, 0);
   rc = ldap_search_s(server, ludp->lud_dn, ludp->lud_scope,
                      ludp->lud_filter, ludp->lud_attrs, 0, &ldapmsg);
 
@@ -544,7 +548,8 @@ static CURLcode ldap_do(struct Curl_easy *data, bool *done)
     goto quit;
   }
 
-  for(num = 0, entryIterator = ldap_first_entry(server, ldapmsg);
+  num = 0;
+  for(entryIterator = ldap_first_entry(server, ldapmsg);
       entryIterator;
       entryIterator = ldap_next_entry(server, entryIterator), num++) {
     BerElement *ber = NULL;
@@ -596,8 +601,6 @@ static CURLcode ldap_do(struct Curl_easy *data, bool *done)
         goto quit;
       }
 
-      dlsize += name_len + 5;
-
       FREE_ON_WINLDAP(name);
       ldap_memfree(dn);
     }
@@ -659,8 +662,6 @@ static CURLcode ldap_do(struct Curl_easy *data, bool *done)
             goto quit;
           }
 
-          dlsize += attr_len + 3;
-
           if((attr_len > 7) &&
              (strcmp(";binary", attr + (attr_len - 7)) == 0)) {
             /* Binary attribute, encode to base64. */
@@ -689,8 +690,6 @@ static CURLcode ldap_do(struct Curl_easy *data, bool *done)
 
                 goto quit;
               }
-
-              dlsize += val_b64_sz;
             }
           }
           else {
@@ -705,8 +704,6 @@ static CURLcode ldap_do(struct Curl_easy *data, bool *done)
 
               goto quit;
             }
-
-            dlsize += vals[i]->bv_len;
           }
 
           result = Curl_client_write(data, CLIENTWRITE_BODY, (char *)"\n", 1);
@@ -719,8 +716,6 @@ static CURLcode ldap_do(struct Curl_easy *data, bool *done)
 
             goto quit;
           }
-
-          dlsize++;
         }
 
         /* Free memory used to store values */
@@ -734,8 +729,6 @@ static CURLcode ldap_do(struct Curl_easy *data, bool *done)
       result = Curl_client_write(data, CLIENTWRITE_BODY, (char *)"\n", 1);
       if(result)
         goto quit;
-      dlsize++;
-      Curl_pgrsSetDownloadCounter(data, dlsize);
     }
 
     if(ber)
@@ -761,7 +754,7 @@ static CURLcode ldap_do(struct Curl_easy *data, bool *done)
   FREE_ON_WINLDAP(host);
 
   /* no data to transfer */
-  Curl_setup_transfer(data, -1, -1, FALSE, -1);
+  Curl_xfer_setup(data, -1, -1, FALSE, -1);
   connclose(conn, "LDAP connection always disable reuse");
 
   return result;
diff --git a/vendor/curl/lib/llist.c b/vendor/curl/lib/llist.c
index 5b6b0336da..716f0cd576 100644
--- a/vendor/curl/lib/llist.c
+++ b/vendor/curl/lib/llist.c
@@ -88,6 +88,22 @@ Curl_llist_insert_next(struct Curl_llist *list, struct Curl_llist_element *e,
   ++list->size;
 }
 
+/*
+ * Curl_llist_append()
+ *
+ * Adds a new list element to the end of the list.
+ *
+ * The 'ne' argument should be a pointer into the object to store.
+ *
+ * @unittest: 1300
+ */
+void
+Curl_llist_append(struct Curl_llist *list, const void *p,
+                  struct Curl_llist_element *ne)
+{
+  Curl_llist_insert_next(list, list->tail, p, ne);
+}
+
 /*
  * @unittest: 1300
  */
diff --git a/vendor/curl/lib/llist.h b/vendor/curl/lib/llist.h
index 320580e33c..d75582fa97 100644
--- a/vendor/curl/lib/llist.h
+++ b/vendor/curl/lib/llist.h
@@ -45,6 +45,8 @@ struct Curl_llist {
 void Curl_llist_init(struct Curl_llist *, Curl_llist_dtor);
 void Curl_llist_insert_next(struct Curl_llist *, struct Curl_llist_element *,
                             const void *, struct Curl_llist_element *node);
+void Curl_llist_append(struct Curl_llist *,
+                       const void *, struct Curl_llist_element *node);
 void Curl_llist_remove(struct Curl_llist *, struct Curl_llist_element *,
                        void *);
 size_t Curl_llist_count(struct Curl_llist *);
diff --git a/vendor/curl/lib/md4.c b/vendor/curl/lib/md4.c
index 30ab62e602..db0028135f 100644
--- a/vendor/curl/lib/md4.c
+++ b/vendor/curl/lib/md4.c
@@ -28,13 +28,13 @@
 
 #include 
 
+#include "strdup.h"
 #include "curl_md4.h"
 #include "warnless.h"
 
 #ifdef USE_OPENSSL
-#include 
-#if defined(OPENSSL_VERSION_MAJOR) && (OPENSSL_VERSION_MAJOR >= 3) && \
-   !defined(USE_AMISSL)
+#include 
+#if (OPENSSL_VERSION_NUMBER >= 0x30000000L) && !defined(USE_AMISSL)
 /* OpenSSL 3.0.0 marks the MD4 functions as deprecated */
 #define OPENSSL_NO_MD4
 #endif
@@ -55,7 +55,8 @@
 #else
 #include 
 #endif
-#if(MBEDTLS_VERSION_NUMBER >= 0x02070000)
+#if(MBEDTLS_VERSION_NUMBER >= 0x02070000) && \
+   (MBEDTLS_VERSION_NUMBER < 0x03000000)
   #define HAS_MBEDTLS_RESULT_CODE_BASED_FUNCTIONS
 #endif
 #endif /* USE_MBEDTLS */
@@ -195,11 +196,9 @@ static int MD4_Init(MD4_CTX *ctx)
 static void MD4_Update(MD4_CTX *ctx, const void *data, unsigned long size)
 {
   if(!ctx->data) {
-    ctx->data = malloc(size);
-    if(ctx->data) {
-      memcpy(ctx->data, data, size);
+    ctx->data = Curl_memdup(data, size);
+    if(ctx->data)
       ctx->size = size;
-    }
   }
 }
 
diff --git a/vendor/curl/lib/memdebug.c b/vendor/curl/lib/memdebug.c
index d6952a07a1..fce933a322 100644
--- a/vendor/curl/lib/memdebug.c
+++ b/vendor/curl/lib/memdebug.c
@@ -208,7 +208,7 @@ ALLOC_FUNC char *curl_dbg_strdup(const char *str,
   return mem;
 }
 
-#if defined(WIN32) && defined(UNICODE)
+#if defined(_WIN32) && defined(UNICODE)
 ALLOC_FUNC wchar_t *curl_dbg_wcsdup(const wchar_t *str,
                                     int line, const char *source)
 {
@@ -304,12 +304,6 @@ void curl_dbg_free(void *ptr, int line, const char *source)
 curl_socket_t curl_dbg_socket(int domain, int type, int protocol,
                              int line, const char *source)
 {
-  const char *fmt = (sizeof(curl_socket_t) == sizeof(int)) ?
-    "FD %s:%d socket() = %d\n" :
-    (sizeof(curl_socket_t) == sizeof(long)) ?
-    "FD %s:%d socket() = %ld\n" :
-    "FD %s:%d socket() = %zd\n";
-
   curl_socket_t sockfd;
 
   if(countcheck("socket", line, source))
@@ -318,7 +312,8 @@ curl_socket_t curl_dbg_socket(int domain, int type, int protocol,
   sockfd = socket(domain, type, protocol);
 
   if(source && (sockfd != CURL_SOCKET_BAD))
-    curl_dbg_log(fmt, source, line, sockfd);
+    curl_dbg_log("FD %s:%d socket() = %" CURL_FORMAT_SOCKET_T "\n",
+                 source, line, sockfd);
 
   return sockfd;
 }
@@ -357,16 +352,12 @@ int curl_dbg_socketpair(int domain, int type, int protocol,
                        curl_socket_t socket_vector[2],
                        int line, const char *source)
 {
-  const char *fmt = (sizeof(curl_socket_t) == sizeof(int)) ?
-    "FD %s:%d socketpair() = %d %d\n" :
-    (sizeof(curl_socket_t) == sizeof(long)) ?
-    "FD %s:%d socketpair() = %ld %ld\n" :
-    "FD %s:%d socketpair() = %zd %zd\n";
-
   int res = socketpair(domain, type, protocol, socket_vector);
 
   if(source && (0 == res))
-    curl_dbg_log(fmt, source, line, socket_vector[0], socket_vector[1]);
+    curl_dbg_log("FD %s:%d socketpair() = "
+      "%" CURL_FORMAT_SOCKET_T " %" CURL_FORMAT_SOCKET_T "\n",
+      source, line, socket_vector[0], socket_vector[1]);
 
   return res;
 }
@@ -375,19 +366,14 @@ int curl_dbg_socketpair(int domain, int type, int protocol,
 curl_socket_t curl_dbg_accept(curl_socket_t s, void *saddr, void *saddrlen,
                              int line, const char *source)
 {
-  const char *fmt = (sizeof(curl_socket_t) == sizeof(int)) ?
-    "FD %s:%d accept() = %d\n" :
-    (sizeof(curl_socket_t) == sizeof(long)) ?
-    "FD %s:%d accept() = %ld\n" :
-    "FD %s:%d accept() = %zd\n";
-
   struct sockaddr *addr = (struct sockaddr *)saddr;
   curl_socklen_t *addrlen = (curl_socklen_t *)saddrlen;
 
   curl_socket_t sockfd = accept(s, addr, addrlen);
 
   if(source && (sockfd != CURL_SOCKET_BAD))
-    curl_dbg_log(fmt, source, line, sockfd);
+    curl_dbg_log("FD %s:%d accept() = %" CURL_FORMAT_SOCKET_T "\n",
+                 source, line, sockfd);
 
   return sockfd;
 }
@@ -395,14 +381,9 @@ curl_socket_t curl_dbg_accept(curl_socket_t s, void *saddr, void *saddrlen,
 /* separate function to allow libcurl to mark a "faked" close */
 void curl_dbg_mark_sclose(curl_socket_t sockfd, int line, const char *source)
 {
-  const char *fmt = (sizeof(curl_socket_t) == sizeof(int)) ?
-    "FD %s:%d sclose(%d)\n":
-    (sizeof(curl_socket_t) == sizeof(long)) ?
-    "FD %s:%d sclose(%ld)\n":
-    "FD %s:%d sclose(%zd)\n";
-
   if(source)
-    curl_dbg_log(fmt, source, line, sockfd);
+    curl_dbg_log("FD %s:%d sclose(%" CURL_FORMAT_SOCKET_T ")\n",
+                 source, line, sockfd);
 }
 
 /* this is our own defined way to close sockets on *ALL* platforms */
diff --git a/vendor/curl/lib/memdebug.h b/vendor/curl/lib/memdebug.h
index c9eb5dc37c..51147cdcba 100644
--- a/vendor/curl/lib/memdebug.h
+++ b/vendor/curl/lib/memdebug.h
@@ -64,7 +64,7 @@ CURL_EXTERN ALLOC_SIZE(2) void *curl_dbg_realloc(void *ptr,
 CURL_EXTERN void curl_dbg_free(void *ptr, int line, const char *source);
 CURL_EXTERN ALLOC_FUNC char *curl_dbg_strdup(const char *str, int line,
                                              const char *src);
-#if defined(WIN32) && defined(UNICODE)
+#if defined(_WIN32) && defined(UNICODE)
 CURL_EXTERN ALLOC_FUNC wchar_t *curl_dbg_wcsdup(const wchar_t *str,
                                                 int line,
                                                 const char *source);
@@ -72,7 +72,7 @@ CURL_EXTERN ALLOC_FUNC wchar_t *curl_dbg_wcsdup(const wchar_t *str,
 
 CURL_EXTERN void curl_dbg_memdebug(const char *logname);
 CURL_EXTERN void curl_dbg_memlimit(long limit);
-CURL_EXTERN void curl_dbg_log(const char *format, ...);
+CURL_EXTERN void curl_dbg_log(const char *format, ...) CURL_PRINTF(1, 2);
 
 /* file descriptor manipulators */
 CURL_EXTERN curl_socket_t curl_dbg_socket(int domain, int type, int protocol,
@@ -121,7 +121,7 @@ CURL_EXTERN int curl_dbg_fclose(FILE *file, int line, const char *source);
 #define send(a,b,c,d) curl_dbg_send(a,b,c,d, __LINE__, __FILE__)
 #define recv(a,b,c,d) curl_dbg_recv(a,b,c,d, __LINE__, __FILE__)
 
-#ifdef WIN32
+#ifdef _WIN32
 #  ifdef UNICODE
 #    undef wcsdup
 #    define wcsdup(ptr) curl_dbg_wcsdup(ptr, __LINE__, __FILE__)
diff --git a/vendor/curl/lib/mime.c b/vendor/curl/lib/mime.c
index 842b2da7e6..a2356c4738 100644
--- a/vendor/curl/lib/mime.c
+++ b/vendor/curl/lib/mime.c
@@ -30,6 +30,7 @@
 #include "warnless.h"
 #include "urldata.h"
 #include "sendf.h"
+#include "strdup.h"
 
 #if !defined(CURL_DISABLE_MIME) && (!defined(CURL_DISABLE_HTTP) ||      \
                                     !defined(CURL_DISABLE_SMTP) ||      \
@@ -48,7 +49,7 @@
 #include "curl_memory.h"
 #include "memdebug.h"
 
-#ifdef WIN32
+#ifdef _WIN32
 # ifndef R_OK
 #  define R_OK 4
 # endif
@@ -73,6 +74,7 @@ static curl_off_t encoder_base64_size(curl_mimepart *part);
 static size_t encoder_qp_read(char *buffer, size_t size, bool ateof,
                               curl_mimepart *part);
 static curl_off_t encoder_qp_size(curl_mimepart *part);
+static curl_off_t mime_size(curl_mimepart *part);
 
 static const struct mime_encoder encoders[] = {
   {"binary", encoder_nop_read, encoder_nop_size},
@@ -311,8 +313,7 @@ static char *escape_string(struct Curl_easy *data,
   table = formtable;
   /* data can be NULL when this function is called indirectly from
      curl_formget(). */
-  if(strategy == MIMESTRATEGY_MAIL ||
-     (data && (data->set.mime_options & CURLMIMEOPT_FORMESCAPE)))
+  if(strategy == MIMESTRATEGY_MAIL || (data && (data->set.mime_formescape)))
     table = mimetable;
 
   Curl_dyn_init(&db, CURL_MAX_INPUT_LENGTH);
@@ -818,7 +819,7 @@ static size_t read_part_content(curl_mimepart *part,
     case MIMEKIND_FILE:
       if(part->fp && feof(part->fp))
         break;  /* At EOF. */
-      /* FALLTHROUGH */
+      FALLTHROUGH();
     default:
       if(part->readfunc) {
         if(!(part->flags & MIME_FAST_READ)) {
@@ -937,7 +938,7 @@ static size_t readback_part(curl_mimepart *part,
         mimesetstate(&part->state, MIMESTATE_USERHEADERS, hdr->next);
         break;
       }
-      /* FALLTHROUGH */
+      FALLTHROUGH();
     case MIMESTATE_CURLHEADERS:
       if(!hdr)
         mimesetstate(&part->state, MIMESTATE_USERHEADERS, part->userheaders);
@@ -971,7 +972,7 @@ static size_t readback_part(curl_mimepart *part,
           fclose(part->fp);
           part->fp = NULL;
         }
-        /* FALLTHROUGH */
+        FALLTHROUGH();
       case CURL_READFUNC_ABORT:
       case CURL_READFUNC_PAUSE:
       case READ_ERROR:
@@ -1236,6 +1237,7 @@ CURLcode Curl_mime_duppart(struct Curl_easy *data,
     }
     break;
   default:  /* Invalid kind: should not occur. */
+    DEBUGF(infof(data, "invalid MIMEKIND* attempt"));
     res = CURLE_BAD_FUNCTION_ARGUMENT;  /* Internal error? */
     break;
   }
@@ -1289,9 +1291,9 @@ curl_mime *curl_mime_init(struct Curl_easy *easy)
     mime->lastpart = NULL;
 
     memset(mime->boundary, '-', MIME_BOUNDARY_DASHES);
-    if(Curl_rand_hex(easy,
-                     (unsigned char *) &mime->boundary[MIME_BOUNDARY_DASHES],
-                     MIME_RAND_BOUNDARY_CHARS + 1)) {
+    if(Curl_rand_alnum(easy,
+                       (unsigned char *) &mime->boundary[MIME_BOUNDARY_DASHES],
+                       MIME_RAND_BOUNDARY_CHARS + 1)) {
       /* failed to get random separator, bail out */
       free(mime);
       return NULL;
@@ -1371,27 +1373,22 @@ CURLcode curl_mime_filename(curl_mimepart *part, const char *filename)
 
 /* Set mime part content from memory data. */
 CURLcode curl_mime_data(curl_mimepart *part,
-                        const char *data, size_t datasize)
+                        const char *ptr, size_t datasize)
 {
   if(!part)
     return CURLE_BAD_FUNCTION_ARGUMENT;
 
   cleanup_part_content(part);
 
-  if(data) {
+  if(ptr) {
     if(datasize == CURL_ZERO_TERMINATED)
-      datasize = strlen(data);
+      datasize = strlen(ptr);
 
-    part->data = malloc(datasize + 1);
+    part->data = Curl_memdup0(ptr, datasize);
     if(!part->data)
       return CURLE_OUT_OF_MEMORY;
 
     part->datasize = datasize;
-
-    if(datasize)
-      memcpy(part->data, data, datasize);
-    part->data[datasize] = '\0';    /* Set a null terminator as sentinel. */
-
     part->readfunc = mime_mem_read;
     part->seekfunc = mime_mem_seek;
     part->freefunc = mime_mem_free;
@@ -1416,36 +1413,35 @@ CURLcode curl_mime_filedata(curl_mimepart *part, const char *filename)
     char *base;
     struct_stat sbuf;
 
-    if(stat(filename, &sbuf) || access(filename, R_OK))
+    if(stat(filename, &sbuf))
       result = CURLE_READ_ERROR;
-
-    part->data = strdup(filename);
-    if(!part->data)
-      result = CURLE_OUT_OF_MEMORY;
-
-    part->datasize = -1;
-    if(!result && S_ISREG(sbuf.st_mode)) {
-      part->datasize = filesize(filename, sbuf);
-      part->seekfunc = mime_file_seek;
-    }
-
-    part->readfunc = mime_file_read;
-    part->freefunc = mime_file_free;
-    part->kind = MIMEKIND_FILE;
-
-    /* As a side effect, set the filename to the current file's base name.
-       It is possible to withdraw this by explicitly calling
-       curl_mime_filename() with a NULL filename argument after the current
-       call. */
-    base = strippath(filename);
-    if(!base)
-      result = CURLE_OUT_OF_MEMORY;
     else {
-      CURLcode res = curl_mime_filename(part, base);
+      part->data = strdup(filename);
+      if(!part->data)
+        result = CURLE_OUT_OF_MEMORY;
+      else {
+        part->datasize = -1;
+        if(S_ISREG(sbuf.st_mode)) {
+          part->datasize = filesize(filename, sbuf);
+          part->seekfunc = mime_file_seek;
+        }
 
-      if(res)
-        result = res;
-      free(base);
+        part->readfunc = mime_file_read;
+        part->freefunc = mime_file_free;
+        part->kind = MIMEKIND_FILE;
+
+        /* As a side effect, set the filename to the current file's base name.
+           It is possible to withdraw this by explicitly calling
+           curl_mime_filename() with a NULL filename argument after the current
+           call. */
+        base = strippath(filename);
+        if(!base)
+          result = CURLE_OUT_OF_MEMORY;
+        else {
+          result = curl_mime_filename(part, base);
+          free(base);
+        }
+      }
     }
   }
   return result;
@@ -1606,7 +1602,7 @@ size_t Curl_mime_read(char *buffer, size_t size, size_t nitems, void *instream)
 }
 
 /* Rewind mime stream. */
-CURLcode Curl_mime_rewind(curl_mimepart *part)
+static CURLcode mime_rewind(curl_mimepart *part)
 {
   return mime_part_rewind(part) == CURL_SEEKFUNC_OK?
          CURLE_OK: CURLE_SEND_FAIL_REWIND;
@@ -1638,7 +1634,7 @@ static curl_off_t multipart_size(curl_mime *mime)
   size = boundarysize;  /* Final boundary - CRLF after headers. */
 
   for(part = mime->firstpart; part; part = part->nextpart) {
-    curl_off_t sz = Curl_mime_size(part);
+    curl_off_t sz = mime_size(part);
 
     if(sz < 0)
       size = sz;
@@ -1651,7 +1647,7 @@ static curl_off_t multipart_size(curl_mime *mime)
 }
 
 /* Get/compute mime size. */
-curl_off_t Curl_mime_size(curl_mimepart *part)
+static curl_off_t mime_size(curl_mimepart *part)
 {
   curl_off_t size;
 
@@ -1900,7 +1896,7 @@ CURLcode Curl_mime_prepare_headers(struct Curl_easy *data,
 }
 
 /* Recursively reset paused status in the given part. */
-void Curl_mime_unpause(curl_mimepart *part)
+static void mime_unpause(curl_mimepart *part)
 {
   if(part) {
     if(part->lastreadstatus == CURL_READFUNC_PAUSE)
@@ -1912,12 +1908,228 @@ void Curl_mime_unpause(curl_mimepart *part)
         curl_mimepart *subpart;
 
         for(subpart = mime->firstpart; subpart; subpart = subpart->nextpart)
-          Curl_mime_unpause(subpart);
+          mime_unpause(subpart);
       }
     }
   }
 }
 
+struct cr_mime_ctx {
+  struct Curl_creader super;
+  curl_mimepart *part;
+  curl_off_t total_len;
+  curl_off_t read_len;
+  CURLcode error_result;
+  BIT(seen_eos);
+  BIT(errored);
+};
+
+static CURLcode cr_mime_init(struct Curl_easy *data,
+                             struct Curl_creader *reader)
+{
+  struct cr_mime_ctx *ctx = reader->ctx;
+  (void)data;
+  ctx->total_len = -1;
+  ctx->read_len = 0;
+  return CURLE_OK;
+}
+
+/* Real client reader to installed client callbacks. */
+static CURLcode cr_mime_read(struct Curl_easy *data,
+                             struct Curl_creader *reader,
+                             char *buf, size_t blen,
+                             size_t *pnread, bool *peos)
+{
+  struct cr_mime_ctx *ctx = reader->ctx;
+  size_t nread;
+
+  /* Once we have errored, we will return the same error forever */
+  if(ctx->errored) {
+    *pnread = 0;
+    *peos = FALSE;
+    return ctx->error_result;
+  }
+  if(ctx->seen_eos) {
+    *pnread = 0;
+    *peos = TRUE;
+    return CURLE_OK;
+  }
+  /* respect length limitations */
+  if(ctx->total_len >= 0) {
+    curl_off_t remain = ctx->total_len - ctx->read_len;
+    if(remain <= 0)
+      blen = 0;
+    else if(remain < (curl_off_t)blen)
+      blen = (size_t)remain;
+  }
+  nread = 0;
+  if(blen) {
+    nread = Curl_mime_read(buf, 1, blen, ctx->part);
+  }
+
+  switch(nread) {
+  case 0:
+    if((ctx->total_len >= 0) && (ctx->read_len < ctx->total_len)) {
+      failf(data, "client mime read EOF fail, "
+            "only %"CURL_FORMAT_CURL_OFF_T"/%"CURL_FORMAT_CURL_OFF_T
+            " of needed bytes read", ctx->read_len, ctx->total_len);
+      return CURLE_READ_ERROR;
+    }
+    *pnread = 0;
+    *peos = TRUE;
+    ctx->seen_eos = TRUE;
+    break;
+
+  case CURL_READFUNC_ABORT:
+    failf(data, "operation aborted by callback");
+    *pnread = 0;
+    *peos = FALSE;
+    ctx->errored = TRUE;
+    ctx->error_result = CURLE_ABORTED_BY_CALLBACK;
+    return CURLE_ABORTED_BY_CALLBACK;
+
+  case CURL_READFUNC_PAUSE:
+    /* CURL_READFUNC_PAUSE pauses read callbacks that feed socket writes */
+    data->req.keepon |= KEEP_SEND_PAUSE; /* mark socket send as paused */
+    *pnread = 0;
+    *peos = FALSE;
+    break; /* nothing was read */
+
+  default:
+    if(nread > blen) {
+      /* the read function returned a too large value */
+      failf(data, "read function returned funny value");
+      *pnread = 0;
+      *peos = FALSE;
+      ctx->errored = TRUE;
+      ctx->error_result = CURLE_READ_ERROR;
+      return CURLE_READ_ERROR;
+    }
+    ctx->read_len += nread;
+    if(ctx->total_len >= 0)
+      ctx->seen_eos = (ctx->read_len >= ctx->total_len);
+    *pnread = nread;
+    *peos = ctx->seen_eos;
+    break;
+  }
+  DEBUGF(infof(data, "cr_mime_read(len=%zu, total=%"CURL_FORMAT_CURL_OFF_T
+         ", read=%"CURL_FORMAT_CURL_OFF_T") -> %d, %zu, %d",
+         blen, ctx->total_len, ctx->read_len, CURLE_OK, *pnread, *peos));
+  return CURLE_OK;
+}
+
+static bool cr_mime_needs_rewind(struct Curl_easy *data,
+                                 struct Curl_creader *reader)
+{
+  struct cr_mime_ctx *ctx = reader->ctx;
+  (void)data;
+  return ctx->read_len > 0;
+}
+
+static curl_off_t cr_mime_total_length(struct Curl_easy *data,
+                                       struct Curl_creader *reader)
+{
+  struct cr_mime_ctx *ctx = reader->ctx;
+  (void)data;
+  return ctx->total_len;
+}
+
+static CURLcode cr_mime_resume_from(struct Curl_easy *data,
+                                    struct Curl_creader *reader,
+                                    curl_off_t offset)
+{
+  struct cr_mime_ctx *ctx = reader->ctx;
+
+  if(offset > 0) {
+    curl_off_t passed = 0;
+
+    do {
+      char scratch[4*1024];
+      size_t readthisamountnow =
+        (offset - passed > (curl_off_t)sizeof(scratch)) ?
+        sizeof(scratch) :
+        curlx_sotouz(offset - passed);
+      size_t nread;
+
+      nread = Curl_mime_read(scratch, 1, readthisamountnow, ctx->part);
+      passed += (curl_off_t)nread;
+      if((nread == 0) || (nread > readthisamountnow)) {
+        /* this checks for greater-than only to make sure that the
+           CURL_READFUNC_ABORT return code still aborts */
+        failf(data, "Could only read %" CURL_FORMAT_CURL_OFF_T
+              " bytes from the mime post", passed);
+        return CURLE_READ_ERROR;
+      }
+    } while(passed < offset);
+
+    /* now, decrease the size of the read */
+    if(ctx->total_len > 0) {
+      ctx->total_len -= offset;
+
+      if(ctx->total_len <= 0) {
+        failf(data, "Mime post already completely uploaded");
+        return CURLE_PARTIAL_FILE;
+      }
+    }
+    /* we've passed, proceed as normal */
+  }
+  return CURLE_OK;
+}
+
+static CURLcode cr_mime_rewind(struct Curl_easy *data,
+                               struct Curl_creader *reader)
+{
+  struct cr_mime_ctx *ctx = reader->ctx;
+  CURLcode result = mime_rewind(ctx->part);
+  if(result)
+    failf(data, "Cannot rewind mime/post data");
+  return result;
+}
+
+static CURLcode cr_mime_unpause(struct Curl_easy *data,
+                                struct Curl_creader *reader)
+{
+  struct cr_mime_ctx *ctx = reader->ctx;
+  (void)data;
+  mime_unpause(ctx->part);
+  return CURLE_OK;
+}
+
+static const struct Curl_crtype cr_mime = {
+  "cr-mime",
+  cr_mime_init,
+  cr_mime_read,
+  Curl_creader_def_close,
+  cr_mime_needs_rewind,
+  cr_mime_total_length,
+  cr_mime_resume_from,
+  cr_mime_rewind,
+  cr_mime_unpause,
+  Curl_creader_def_done,
+  sizeof(struct cr_mime_ctx)
+};
+
+CURLcode Curl_creader_set_mime(struct Curl_easy *data, curl_mimepart *part)
+{
+  struct Curl_creader *r;
+  struct cr_mime_ctx *ctx;
+  CURLcode result;
+
+  result = Curl_creader_create(&r, data, &cr_mime, CURL_CR_CLIENT);
+  if(result)
+    return result;
+  ctx = r->ctx;
+  ctx->part = part;
+  /* Make sure we will read the entire mime structure. */
+  result = mime_rewind(ctx->part);
+  if(result) {
+    Curl_creader_free(data, r);
+    return result;
+  }
+  ctx->total_len = mime_size(ctx->part);
+
+  return Curl_creader_set(data, r);
+}
 
 #else /* !CURL_DISABLE_MIME && (!CURL_DISABLE_HTTP ||
                                 !CURL_DISABLE_SMTP || !CURL_DISABLE_IMAP) */
diff --git a/vendor/curl/lib/mime.h b/vendor/curl/lib/mime.h
index 04adf2d247..954b3ccf39 100644
--- a/vendor/curl/lib/mime.h
+++ b/vendor/curl/lib/mime.h
@@ -27,7 +27,7 @@
 #include "curl_setup.h"
 
 #define MIME_BOUNDARY_DASHES            24  /* leading boundary dashes */
-#define MIME_RAND_BOUNDARY_CHARS        16  /* Nb. of random boundary chars. */
+#define MIME_RAND_BOUNDARY_CHARS        22  /* Nb. of random boundary chars. */
 #define MAX_ENCODED_LINE_LENGTH         76  /* Maximum encoded line length. */
 #define ENCODING_BUFFER_SIZE            256 /* Encoding temp buffers size. */
 
@@ -130,7 +130,8 @@ struct curl_mimepart {
   size_t lastreadstatus;           /* Last read callback returned status. */
 };
 
-CURLcode Curl_mime_add_header(struct curl_slist **slp, const char *fmt, ...);
+CURLcode Curl_mime_add_header(struct curl_slist **slp, const char *fmt, ...)
+  CURL_PRINTF(2, 3);
 
 #if !defined(CURL_DISABLE_MIME) && (!defined(CURL_DISABLE_HTTP) ||      \
                                     !defined(CURL_DISABLE_SMTP) ||      \
@@ -150,12 +151,15 @@ CURLcode Curl_mime_prepare_headers(struct Curl_easy *data,
                                    const char *contenttype,
                                    const char *disposition,
                                    enum mimestrategy strategy);
-curl_off_t Curl_mime_size(struct curl_mimepart *part);
 size_t Curl_mime_read(char *buffer, size_t size, size_t nitems,
                       void *instream);
-CURLcode Curl_mime_rewind(struct curl_mimepart *part);
 const char *Curl_mime_contenttype(const char *filename);
-void Curl_mime_unpause(struct curl_mimepart *part);
+
+/**
+ * Install a client reader as upload source that reads the given
+ * mime part.
+ */
+CURLcode Curl_creader_set_mime(struct Curl_easy *data, curl_mimepart *part);
 
 #else
 /* if disabled */
@@ -164,10 +168,8 @@ void Curl_mime_unpause(struct curl_mimepart *part);
 #define Curl_mime_duppart(x,y,z) CURLE_OK /* Nothing to duplicate. Succeed */
 #define Curl_mime_set_subparts(a,b,c) CURLE_NOT_BUILT_IN
 #define Curl_mime_prepare_headers(a,b,c,d,e) CURLE_NOT_BUILT_IN
-#define Curl_mime_size(x) (curl_off_t) -1
 #define Curl_mime_read NULL
-#define Curl_mime_rewind(x) ((void)x, CURLE_NOT_BUILT_IN)
-#define Curl_mime_unpause(x)
+#define Curl_creader_set_mime(x,y) ((void)x, CURLE_NOT_BUILT_IN)
 #endif
 
 
diff --git a/vendor/curl/lib/mprintf.c b/vendor/curl/lib/mprintf.c
index af5d753d6a..1829abc73e 100644
--- a/vendor/curl/lib/mprintf.c
+++ b/vendor/curl/lib/mprintf.c
@@ -20,25 +20,11 @@
  *
  * SPDX-License-Identifier: curl
  *
- *
- * Purpose:
- *  A merge of Bjorn Reese's format() function and Daniel's dsprintf()
- *  1.0. A full blooded printf() clone with full support for $
- *  everywhere (parameters, widths and precisions) including variabled
- *  sized parameters (like doubles, long longs, long doubles and even
- *  void * in 64-bit architectures).
- *
- * Current restrictions:
- * - Max 128 parameters
- * - No 'long double' support.
- *
- * If you ever want truly portable and good *printf() clones, the project that
- * took on from here is named 'Trio' and you find more details on the trio web
- * page at https://daniel.haxx.se/projects/trio/
  */
 
 #include "curl_setup.h"
 #include "dynbuf.h"
+#include "curl_printf.h"
 #include 
 
 #include "curl_memory.h"
@@ -62,18 +48,6 @@
 #  endif
 #endif
 
-/*
- * Non-ANSI integer extensions
- */
-
-#if (defined(__BORLANDC__) && (__BORLANDC__ >= 0x520)) || \
-    (defined(__POCC__) && defined(_MSC_VER)) || \
-    (defined(_WIN32_WCE)) || \
-    (defined(__MINGW32__)) || \
-    (defined(_MSC_VER) && (_MSC_VER >= 900) && (_INTEGRAL_MAX_BITS >= 64))
-#  define MP_HAVE_INT_EXTENSIONS
-#endif
-
 /*
  * Max integer data types that mprintf.c is capable
  */
@@ -88,7 +62,8 @@
 
 #define BUFFSIZE 326 /* buffer for long-to-str and float-to-str calcs, should
                         fit negative DBL_MAX (317 letters) */
-#define MAX_PARAMETERS 128 /* lame static limit */
+#define MAX_PARAMETERS 128 /* number of input arguments */
+#define MAX_SEGMENTS   128 /* number of output segments */
 
 #ifdef __AMIGA__
 # undef FORMAT_INT
@@ -100,31 +75,33 @@ static const char lower_digits[] = "0123456789abcdefghijklmnopqrstuvwxyz";
 /* Upper-case digits.  */
 static const char upper_digits[] = "0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZ";
 
-#define OUTCHAR(x)                                     \
-  do {                                                 \
-    if(stream((unsigned char)(x), (FILE *)data) != -1) \
-      done++;                                          \
-    else                                               \
-      return done; /* return immediately on failure */ \
+#define OUTCHAR(x)                                      \
+  do {                                                  \
+    if(!stream((unsigned char)x, userp))                \
+      done++;                                           \
+    else                                                \
+      return done; /* return on failure */              \
   } while(0)
 
 /* Data type to read from the arglist */
 typedef enum {
-  FORMAT_UNKNOWN = 0,
   FORMAT_STRING,
   FORMAT_PTR,
-  FORMAT_INT,
   FORMAT_INTPTR,
+  FORMAT_INT,
   FORMAT_LONG,
   FORMAT_LONGLONG,
+  FORMAT_INTU,
+  FORMAT_LONGU,
+  FORMAT_LONGLONGU,
   FORMAT_DOUBLE,
   FORMAT_LONGDOUBLE,
-  FORMAT_WIDTH /* For internal use */
+  FORMAT_WIDTH,
+  FORMAT_PRECISION
 } FormatType;
 
 /* conversion and display flags */
 enum {
-  FLAGS_NEW        = 0,
   FLAGS_SPACE      = 1<<0,
   FLAGS_SHOWSIGN   = 1<<1,
   FLAGS_LEFT       = 1<<2,
@@ -144,23 +121,40 @@ enum {
   FLAGS_PRECPARAM  = 1<<16, /* precision PARAMETER was specified */
   FLAGS_CHAR       = 1<<17, /* %c story */
   FLAGS_FLOATE     = 1<<18, /* %e or %E */
-  FLAGS_FLOATG     = 1<<19  /* %g or %G */
+  FLAGS_FLOATG     = 1<<19, /* %g or %G */
+  FLAGS_SUBSTR     = 1<<20  /* no input, only substring */
 };
 
-struct va_stack {
-  FormatType type;
-  int flags;
-  long width;     /* width OR width parameter number */
-  long precision; /* precision OR precision parameter number */
+enum {
+  DOLLAR_UNKNOWN,
+  DOLLAR_NOPE,
+  DOLLAR_USE
+};
+
+/*
+ * Describes an input va_arg type and hold its value.
+ */
+struct va_input {
+  FormatType type; /* FormatType */
   union {
     char *str;
     void *ptr;
-    union {
-      mp_intmax_t as_signed;
-      mp_uintmax_t as_unsigned;
-    } num;
+    mp_intmax_t nums; /* signed */
+    mp_uintmax_t numu; /* unsigned */
     double dnum;
-  } data;
+  } val;
+};
+
+/*
+ * Describes an output segment.
+ */
+struct outsegment {
+  int width;     /* width OR width parameter number */
+  int precision; /* precision OR precision parameter number */
+  unsigned int flags;
+  unsigned int input; /* input argument array index */
+  char *start;      /* format string start to output */
+  size_t outlen;     /* number of bytes from the format string to output */
 };
 
 struct nsprintf {
@@ -171,118 +165,124 @@ struct nsprintf {
 
 struct asprintf {
   struct dynbuf *b;
-  bool fail; /* if an alloc has failed and thus the output is not the complete
-                data */
+  char merr;
 };
 
-static long dprintf_DollarString(char *input, char **end)
-{
-  int number = 0;
-  while(ISDIGIT(*input)) {
-    if(number < MAX_PARAMETERS) {
-      number *= 10;
-      number += *input - '0';
-    }
-    input++;
-  }
-  if(number <= MAX_PARAMETERS && ('$' == *input)) {
-    *end = ++input;
-    return number;
-  }
-  return 0;
-}
+/* the provided input number is 1-based but this returns the number 0-based.
 
-static bool dprintf_IsQualifierNoDollar(const char *fmt)
+   returns -1 if no valid number was provided.
+*/
+static int dollarstring(char *input, char **end)
 {
-#if defined(MP_HAVE_INT_EXTENSIONS)
-  if(!strncmp(fmt, "I32", 3) || !strncmp(fmt, "I64", 3)) {
-    return TRUE;
-  }
-#endif
-
-  switch(*fmt) {
-  case '-': case '+': case ' ': case '#': case '.':
-  case '0': case '1': case '2': case '3': case '4':
-  case '5': case '6': case '7': case '8': case '9':
-  case 'h': case 'l': case 'L': case 'z': case 'q':
-  case '*': case 'O':
-#if defined(MP_HAVE_INT_EXTENSIONS)
-  case 'I':
-#endif
-    return TRUE;
+  if(ISDIGIT(*input)) {
+    int number = 0;
+    do {
+      if(number < MAX_PARAMETERS) {
+        number *= 10;
+        number += *input - '0';
+      }
+      input++;
+    } while(ISDIGIT(*input));
 
-  default:
-    return FALSE;
+    if(number && (number <= MAX_PARAMETERS) && ('$' == *input)) {
+      *end = ++input;
+      return number - 1;
+    }
   }
+  return -1;
 }
 
-/******************************************************************
+/*
+ * Parse the format string.
  *
- * Pass 1:
- * Create an index with the type of each parameter entry and its
- * value (may vary in size)
+ * Create two arrays. One describes the inputs, one describes the outputs.
  *
  * Returns zero on success.
- *
- ******************************************************************/
+ */
 
-static int dprintf_Pass1(const char *format, struct va_stack *vto,
-                         char **endpos, va_list arglist)
+#define PFMT_OK          0
+#define PFMT_DOLLAR      1 /* bad dollar for main param */
+#define PFMT_DOLLARWIDTH 2 /* bad dollar use for width */
+#define PFMT_DOLLARPREC  3 /* bad dollar use for precision */
+#define PFMT_MANYARGS    4 /* too many input arguments used */
+#define PFMT_PREC        5 /* precision overflow */
+#define PFMT_PRECMIX     6 /* bad mix of precision specifiers */
+#define PFMT_WIDTH       7 /* width overflow */
+#define PFMT_INPUTGAP    8 /* gap in arguments */
+#define PFMT_WIDTHARG    9 /* attempted to use same arg twice, for width */
+#define PFMT_PRECARG    10 /* attempted to use same arg twice, for prec */
+#define PFMT_MANYSEGS   11 /* maxed out output segments */
+
+static int parsefmt(const char *format,
+                    struct outsegment *out,
+                    struct va_input *in,
+                    int *opieces,
+                    int *ipieces, va_list arglist)
 {
   char *fmt = (char *)format;
   int param_num = 0;
-  long this_param;
-  long width;
-  long precision;
-  int flags;
-  long max_param = 0;
-  long i;
+  int param;
+  int width;
+  int precision;
+  unsigned int flags;
+  FormatType type;
+  int max_param = -1;
+  int i;
+  int ocount = 0;
+  unsigned char usedinput[MAX_PARAMETERS/8];
+  size_t outlen = 0;
+  struct outsegment *optr;
+  int use_dollar = DOLLAR_UNKNOWN;
+  char *start = fmt;
+
+  /* clear, set a bit for each used input */
+  memset(usedinput, 0, sizeof(usedinput));
 
   while(*fmt) {
-    if(*fmt++ == '%') {
+    if(*fmt == '%') {
+      struct va_input *iptr;
+      bool loopit = TRUE;
+      fmt++;
+      outlen = (size_t)(fmt - start - 1);
       if(*fmt == '%') {
+        /* this means a %% that should be output only as %. Create an output
+           segment. */
+        if(outlen) {
+          optr = &out[ocount++];
+          if(ocount > MAX_SEGMENTS)
+            return PFMT_MANYSEGS;
+          optr->input = 0;
+          optr->flags = FLAGS_SUBSTR;
+          optr->start = start;
+          optr->outlen = outlen;
+        }
+        start = fmt;
         fmt++;
         continue; /* while */
       }
 
-      flags = FLAGS_NEW;
-
-      /* Handle the positional case (N$) */
+      flags = 0;
+      width = precision = 0;
 
-      param_num++;
+      if(use_dollar != DOLLAR_NOPE) {
+        param = dollarstring(fmt, &fmt);
+        if(param < 0) {
+          if(use_dollar == DOLLAR_USE)
+            /* illegal combo */
+            return PFMT_DOLLAR;
 
-      this_param = dprintf_DollarString(fmt, &fmt);
-      if(0 == this_param)
-        /* we got no positional, get the next counter */
-        this_param = param_num;
-
-      if(this_param > max_param)
-        max_param = this_param;
-
-      /*
-       * The parameter with number 'i' should be used. Next, we need
-       * to get SIZE and TYPE of the parameter. Add the information
-       * to our array.
-       */
-
-      width = 0;
-      precision = 0;
-
-      /* Handle the flags */
-
-      while(dprintf_IsQualifierNoDollar(fmt)) {
-#if defined(MP_HAVE_INT_EXTENSIONS)
-        if(!strncmp(fmt, "I32", 3)) {
-          flags |= FLAGS_LONG;
-          fmt += 3;
-        }
-        else if(!strncmp(fmt, "I64", 3)) {
-          flags |= FLAGS_LONGLONG;
-          fmt += 3;
+          /* we got no positional, just get the next arg */
+          param = -1;
+          use_dollar = DOLLAR_NOPE;
         }
         else
-#endif
+          use_dollar = DOLLAR_USE;
+      }
+      else
+        param = -1;
 
+      /* Handle the flags */
+      while(loopit) {
         switch(*fmt++) {
         case ' ':
           flags |= FLAGS_SPACE;
@@ -292,7 +292,7 @@ static int dprintf_Pass1(const char *format, struct va_stack *vto,
           break;
         case '-':
           flags |= FLAGS_LEFT;
-          flags &= ~FLAGS_PAD_NIL;
+          flags &= ~(unsigned int)FLAGS_PAD_NIL;
           break;
         case '#':
           flags |= FLAGS_ALT;
@@ -300,42 +300,66 @@ static int dprintf_Pass1(const char *format, struct va_stack *vto,
         case '.':
           if('*' == *fmt) {
             /* The precision is picked from a specified parameter */
-
             flags |= FLAGS_PRECPARAM;
             fmt++;
-            param_num++;
 
-            i = dprintf_DollarString(fmt, &fmt);
-            if(i)
-              precision = i;
+            if(use_dollar == DOLLAR_USE) {
+              precision = dollarstring(fmt, &fmt);
+              if(precision < 0)
+                /* illegal combo */
+                return PFMT_DOLLARPREC;
+            }
             else
-              precision = param_num;
-
-            if(precision > max_param)
-              max_param = precision;
+              /* get it from the next argument */
+              precision = -1;
           }
           else {
+            bool is_neg = FALSE;
             flags |= FLAGS_PREC;
-            precision = strtol(fmt, &fmt, 10);
+            precision = 0;
+            if('-' == *fmt) {
+              is_neg = TRUE;
+              fmt++;
+            }
+            while(ISDIGIT(*fmt)) {
+              if(precision > INT_MAX/10)
+                return PFMT_PREC;
+              precision *= 10;
+              precision += *fmt - '0';
+              fmt++;
+            }
+            if(is_neg)
+              precision = -precision;
           }
           if((flags & (FLAGS_PREC | FLAGS_PRECPARAM)) ==
              (FLAGS_PREC | FLAGS_PRECPARAM))
             /* it is not permitted to use both kinds of precision for the same
                argument */
-            return 1;
+            return PFMT_PRECMIX;
           break;
         case 'h':
           flags |= FLAGS_SHORT;
           break;
-#if defined(MP_HAVE_INT_EXTENSIONS)
+#if defined(_WIN32) || defined(_WIN32_WCE)
         case 'I':
+          /* Non-ANSI integer extensions I32 I64 */
+          if((fmt[0] == '3') && (fmt[1] == '2')) {
+            flags |= FLAGS_LONG;
+            fmt += 2;
+          }
+          else if((fmt[0] == '6') && (fmt[1] == '4')) {
+            flags |= FLAGS_LONGLONG;
+            fmt += 2;
+          }
+          else {
 #if (SIZEOF_CURL_OFF_T > SIZEOF_LONG)
-          flags |= FLAGS_LONGLONG;
+            flags |= FLAGS_LONGLONG;
 #else
-          flags |= FLAGS_LONG;
+            flags |= FLAGS_LONG;
 #endif
+          }
           break;
-#endif
+#endif /* _WIN32 || _WIN32_WCE */
         case 'l':
           if(flags & FLAGS_LONG)
             flags |= FLAGS_LONGLONG;
@@ -367,401 +391,421 @@ static int dprintf_Pass1(const char *format, struct va_stack *vto,
         case '0':
           if(!(flags & FLAGS_LEFT))
             flags |= FLAGS_PAD_NIL;
-          /* FALLTHROUGH */
+          FALLTHROUGH();
         case '1': case '2': case '3': case '4':
         case '5': case '6': case '7': case '8': case '9':
           flags |= FLAGS_WIDTH;
-          width = strtol(fmt-1, &fmt, 10);
+          width = 0;
+          fmt--;
+          do {
+            if(width > INT_MAX/10)
+              return PFMT_WIDTH;
+            width *= 10;
+            width += *fmt - '0';
+            fmt++;
+          } while(ISDIGIT(*fmt));
           break;
-        case '*':  /* Special case */
+        case '*':  /* read width from argument list */
           flags |= FLAGS_WIDTHPARAM;
-          param_num++;
-
-          i = dprintf_DollarString(fmt, &fmt);
-          if(i)
-            width = i;
+          if(use_dollar == DOLLAR_USE) {
+            width = dollarstring(fmt, &fmt);
+            if(width < 0)
+              /* illegal combo */
+              return PFMT_DOLLARWIDTH;
+          }
           else
-            width = param_num;
-          if(width > max_param)
-            max_param = width;
+            /* pick from the next argument */
+            width = -1;
           break;
-        case '\0':
-          fmt--;
         default:
+          loopit = FALSE;
+          fmt--;
           break;
-        }
-      } /* switch */
-
-      /* Handle the specifier */
-
-      i = this_param - 1;
-
-      if((i < 0) || (i >= MAX_PARAMETERS))
-        /* out of allowed range */
-        return 1;
+        } /* switch */
+      } /* while */
 
       switch(*fmt) {
       case 'S':
         flags |= FLAGS_ALT;
-        /* FALLTHROUGH */
+        FALLTHROUGH();
       case 's':
-        vto[i].type = FORMAT_STRING;
+        type = FORMAT_STRING;
         break;
       case 'n':
-        vto[i].type = FORMAT_INTPTR;
+        type = FORMAT_INTPTR;
         break;
       case 'p':
-        vto[i].type = FORMAT_PTR;
+        type = FORMAT_PTR;
         break;
-      case 'd': case 'i':
-        vto[i].type = FORMAT_INT;
+      case 'd':
+      case 'i':
+        if(flags & FLAGS_LONGLONG)
+          type = FORMAT_LONGLONG;
+        else if(flags & FLAGS_LONG)
+          type = FORMAT_LONG;
+        else
+          type = FORMAT_INT;
         break;
       case 'u':
-        vto[i].type = FORMAT_INT;
+        if(flags & FLAGS_LONGLONG)
+          type = FORMAT_LONGLONGU;
+        else if(flags & FLAGS_LONG)
+          type = FORMAT_LONGU;
+        else
+          type = FORMAT_INTU;
         flags |= FLAGS_UNSIGNED;
         break;
       case 'o':
-        vto[i].type = FORMAT_INT;
+        type = FORMAT_INT;
         flags |= FLAGS_OCTAL;
         break;
       case 'x':
-        vto[i].type = FORMAT_INT;
+        type = FORMAT_INTU;
         flags |= FLAGS_HEX|FLAGS_UNSIGNED;
         break;
       case 'X':
-        vto[i].type = FORMAT_INT;
+        type = FORMAT_INTU;
         flags |= FLAGS_HEX|FLAGS_UPPER|FLAGS_UNSIGNED;
         break;
       case 'c':
-        vto[i].type = FORMAT_INT;
+        type = FORMAT_INT;
         flags |= FLAGS_CHAR;
         break;
       case 'f':
-        vto[i].type = FORMAT_DOUBLE;
+        type = FORMAT_DOUBLE;
         break;
       case 'e':
-        vto[i].type = FORMAT_DOUBLE;
+        type = FORMAT_DOUBLE;
         flags |= FLAGS_FLOATE;
         break;
       case 'E':
-        vto[i].type = FORMAT_DOUBLE;
+        type = FORMAT_DOUBLE;
         flags |= FLAGS_FLOATE|FLAGS_UPPER;
         break;
       case 'g':
-        vto[i].type = FORMAT_DOUBLE;
+        type = FORMAT_DOUBLE;
         flags |= FLAGS_FLOATG;
         break;
       case 'G':
-        vto[i].type = FORMAT_DOUBLE;
+        type = FORMAT_DOUBLE;
         flags |= FLAGS_FLOATG|FLAGS_UPPER;
         break;
       default:
-        vto[i].type = FORMAT_UNKNOWN;
-        break;
+        /* invalid instruction, disregard and continue */
+        continue;
       } /* switch */
 
-      vto[i].flags = flags;
-      vto[i].width = width;
-      vto[i].precision = precision;
-
       if(flags & FLAGS_WIDTHPARAM) {
-        /* we have the width specified from a parameter, so we make that
-           parameter's info setup properly */
-        long k = width - 1;
-        if((k < 0) || (k >= MAX_PARAMETERS))
-          /* out of allowed range */
-          return 1;
-        vto[i].width = k;
-        vto[k].type = FORMAT_WIDTH;
-        vto[k].flags = FLAGS_NEW;
-        /* can't use width or precision of width! */
-        vto[k].width = 0;
-        vto[k].precision = 0;
+        if(width < 0)
+          width = param_num++;
+        else {
+          /* if this identifies a parameter already used, this
+             is illegal */
+          if(usedinput[width/8] & (1 << (width&7)))
+            return PFMT_WIDTHARG;
+        }
+        if(width >= MAX_PARAMETERS)
+          return PFMT_MANYARGS;
+        if(width >= max_param)
+          max_param = width;
+
+        in[width].type = FORMAT_WIDTH;
+        /* mark as used */
+        usedinput[width/8] |= (unsigned char)(1 << (width&7));
       }
+
       if(flags & FLAGS_PRECPARAM) {
-        /* we have the precision specified from a parameter, so we make that
-           parameter's info setup properly */
-        long k = precision - 1;
-        if((k < 0) || (k >= MAX_PARAMETERS))
-          /* out of allowed range */
-          return 1;
-        vto[i].precision = k;
-        vto[k].type = FORMAT_WIDTH;
-        vto[k].flags = FLAGS_NEW;
-        /* can't use width or precision of width! */
-        vto[k].width = 0;
-        vto[k].precision = 0;
+        if(precision < 0)
+          precision = param_num++;
+        else {
+          /* if this identifies a parameter already used, this
+             is illegal */
+          if(usedinput[precision/8] & (1 << (precision&7)))
+            return PFMT_PRECARG;
+        }
+        if(precision >= MAX_PARAMETERS)
+          return PFMT_MANYARGS;
+        if(precision >= max_param)
+          max_param = precision;
+
+        in[precision].type = FORMAT_PRECISION;
+        usedinput[precision/8] |= (unsigned char)(1 << (precision&7));
       }
-      *endpos++ = fmt + ((*fmt == '\0') ? 0 : 1); /* end of this sequence */
+
+      /* Handle the specifier */
+      if(param < 0)
+        param = param_num++;
+      if(param >= MAX_PARAMETERS)
+        return PFMT_MANYARGS;
+      if(param >= max_param)
+        max_param = param;
+
+      iptr = &in[param];
+      iptr->type = type;
+
+      /* mark this input as used */
+      usedinput[param/8] |= (unsigned char)(1 << (param&7));
+
+      fmt++;
+      optr = &out[ocount++];
+      if(ocount > MAX_SEGMENTS)
+        return PFMT_MANYSEGS;
+      optr->input = (unsigned int)param;
+      optr->flags = flags;
+      optr->width = width;
+      optr->precision = precision;
+      optr->start = start;
+      optr->outlen = outlen;
+      start = fmt;
     }
+    else
+      fmt++;
   }
 
-  /* Read the arg list parameters into our data list */
-  for(i = 0; i MAX_SEGMENTS)
+      return PFMT_MANYSEGS;
+    optr->input = 0;
+    optr->flags = FLAGS_SUBSTR;
+    optr->start = start;
+    optr->outlen = outlen;
+  }
 
-    switch(vto[i].type) {
+  /* Read the arg list parameters into our data list */
+  for(i = 0; i < max_param + 1; i++) {
+    struct va_input *iptr = &in[i];
+    if(!(usedinput[i/8] & (1 << (i&7))))
+      /* bad input */
+      return PFMT_INPUTGAP;
+
+    /* based on the type, read the correct argument */
+    switch(iptr->type) {
     case FORMAT_STRING:
-      vto[i].data.str = va_arg(arglist, char *);
+      iptr->val.str = va_arg(arglist, char *);
       break;
 
     case FORMAT_INTPTR:
-    case FORMAT_UNKNOWN:
     case FORMAT_PTR:
-      vto[i].data.ptr = va_arg(arglist, void *);
+      iptr->val.ptr = va_arg(arglist, void *);
       break;
 
-    case FORMAT_INT:
-#ifdef HAVE_LONG_LONG_TYPE
-      if((vto[i].flags & FLAGS_LONGLONG) && (vto[i].flags & FLAGS_UNSIGNED))
-        vto[i].data.num.as_unsigned =
-          (mp_uintmax_t)va_arg(arglist, mp_uintmax_t);
-      else if(vto[i].flags & FLAGS_LONGLONG)
-        vto[i].data.num.as_signed =
-          (mp_intmax_t)va_arg(arglist, mp_intmax_t);
-      else
-#endif
-      {
-        if((vto[i].flags & FLAGS_LONG) && (vto[i].flags & FLAGS_UNSIGNED))
-          vto[i].data.num.as_unsigned =
-            (mp_uintmax_t)va_arg(arglist, unsigned long);
-        else if(vto[i].flags & FLAGS_LONG)
-          vto[i].data.num.as_signed =
-            (mp_intmax_t)va_arg(arglist, long);
-        else if(vto[i].flags & FLAGS_UNSIGNED)
-          vto[i].data.num.as_unsigned =
-            (mp_uintmax_t)va_arg(arglist, unsigned int);
-        else
-          vto[i].data.num.as_signed =
-            (mp_intmax_t)va_arg(arglist, int);
-      }
+    case FORMAT_LONGLONGU:
+      iptr->val.numu = (mp_uintmax_t)va_arg(arglist, mp_uintmax_t);
       break;
 
-    case FORMAT_DOUBLE:
-      vto[i].data.dnum = va_arg(arglist, double);
+    case FORMAT_LONGLONG:
+      iptr->val.nums = (mp_intmax_t)va_arg(arglist, mp_intmax_t);
+      break;
+
+    case FORMAT_LONGU:
+      iptr->val.numu = (mp_uintmax_t)va_arg(arglist, unsigned long);
       break;
 
+    case FORMAT_LONG:
+      iptr->val.nums = (mp_intmax_t)va_arg(arglist, long);
+      break;
+
+    case FORMAT_INTU:
+      iptr->val.numu = (mp_uintmax_t)va_arg(arglist, unsigned int);
+      break;
+
+    case FORMAT_INT:
     case FORMAT_WIDTH:
-      /* Argument has been read. Silently convert it into an integer
-       * for later use
-       */
-      vto[i].type = FORMAT_INT;
+    case FORMAT_PRECISION:
+      iptr->val.nums = (mp_intmax_t)va_arg(arglist, int);
+      break;
+
+    case FORMAT_DOUBLE:
+      iptr->val.dnum = va_arg(arglist, double);
       break;
 
     default:
+      DEBUGASSERT(NULL); /* unexpected */
       break;
     }
   }
+  *ipieces = max_param + 1;
+  *opieces = ocount;
 
-  return 0;
-
+  return PFMT_OK;
 }
 
-static int dprintf_formatf(
-  void *data, /* untouched by format(), just sent to the stream() function in
-                 the second argument */
+/*
+ * formatf() - the general printf function.
+ *
+ * It calls parsefmt() to parse the format string. It populates two arrays;
+ * one that describes the input arguments and one that describes a number of
+ * output segments.
+ *
+ * On success, the input array describes the type of all arguments and their
+ * values.
+ *
+ * The function then iterates over the output segments and outputs them one
+ * by one until done. Using the appropriate input arguments (if any).
+ *
+ * All output is sent to the 'stream()' callback, one byte at a time.
+ */
+
+static int formatf(
+  void *userp, /* untouched by format(), just sent to the stream() function in
+                  the second argument */
   /* function pointer called for each output character */
-  int (*stream)(int, FILE *),
+  int (*stream)(unsigned char, void *),
   const char *format,    /* %-formatted string */
   va_list ap_save) /* list of parameters */
 {
-  /* Base-36 digits for numbers.  */
-  const char *digits = lower_digits;
-
-  /* Pointer into the format string.  */
-  char *f;
-
-  /* Number of characters written.  */
-  int done = 0;
-
-  long param; /* current parameter to read */
-  long param_num = 0; /* parameter counter */
-
-  struct va_stack vto[MAX_PARAMETERS];
-  char *endpos[MAX_PARAMETERS];
-  char **end;
+  static const char nilstr[] = "(nil)";
+  const char *digits = lower_digits;   /* Base-36 digits for numbers.  */
+  int done = 0;   /* number of characters written  */
+  int i;
+  int ocount = 0; /* number of output segments */
+  int icount = 0; /* number of input arguments */
+
+  struct outsegment output[MAX_SEGMENTS];
+  struct va_input input[MAX_PARAMETERS];
   char work[BUFFSIZE];
-  struct va_stack *p;
 
   /* 'workend' points to the final buffer byte position, but with an extra
      byte as margin to avoid the (false?) warning Coverity gives us
      otherwise */
   char *workend = &work[sizeof(work) - 2];
 
-  /* Do the actual %-code parsing */
-  if(dprintf_Pass1(format, vto, endpos, ap_save))
+  /* Parse the format string */
+  if(parsefmt(format, output, input, &ocount, &icount, ap_save))
     return 0;
 
-  end = &endpos[0]; /* the initial end-position from the list dprintf_Pass1()
-                       created for us */
-
-  f = (char *)format;
-  while(*f != '\0') {
-    /* Format spec modifiers.  */
-    int is_alt;
-
-    /* Width of a field.  */
-    long width;
-
-    /* Precision of a field.  */
-    long prec;
-
-    /* Decimal integer is negative.  */
-    int is_neg;
-
-    /* Base of a number to be written.  */
-    unsigned long base;
-
-    /* Integral values to be written.  */
-    mp_uintmax_t num;
-
-    /* Used to convert negative in positive.  */
-    mp_intmax_t signed_num;
-
+  for(i = 0; i < ocount; i++) {
+    struct outsegment *optr = &output[i];
+    struct va_input *iptr;
+    bool is_alt;            /* Format spec modifiers.  */
+    int width;              /* Width of a field.  */
+    int prec;               /* Precision of a field.  */
+    bool is_neg;            /* Decimal integer is negative.  */
+    unsigned long base;     /* Base of a number to be written.  */
+    mp_uintmax_t num;       /* Integral values to be written.  */
+    mp_intmax_t signed_num; /* Used to convert negative in positive.  */
     char *w;
-
-    if(*f != '%') {
-      /* This isn't a format spec, so write everything out until the next one
-         OR end of string is reached.  */
-      do {
-        OUTCHAR(*f);
-      } while(*++f && ('%' != *f));
-      continue;
-    }
-
-    ++f;
-
-    /* Check for "%%".  Note that although the ANSI standard lists
-       '%' as a conversion specifier, it says "The complete format
-       specification shall be `%%'," so we can avoid all the width
-       and precision processing.  */
-    if(*f == '%') {
-      ++f;
-      OUTCHAR('%');
-      continue;
+    size_t outlen = optr->outlen;
+    unsigned int flags = optr->flags;
+
+    if(outlen) {
+      char *str = optr->start;
+      for(; outlen && *str; outlen--)
+        OUTCHAR(*str++);
+      if(optr->flags & FLAGS_SUBSTR)
+        /* this is just a substring */
+        continue;
     }
 
-    /* If this is a positional parameter, the position must follow immediately
-       after the %, thus create a %$ sequence */
-    param = dprintf_DollarString(f, &f);
-
-    if(!param)
-      param = param_num;
-    else
-      --param;
-
-    param_num++; /* increase this always to allow "%2$s %1$s %s" and then the
-                    third %s will pick the 3rd argument */
-
-    p = &vto[param];
-
     /* pick up the specified width */
-    if(p->flags & FLAGS_WIDTHPARAM) {
-      width = (long)vto[p->width].data.num.as_signed;
-      param_num++; /* since the width is extracted from a parameter, we
-                      must skip that to get to the next one properly */
+    if(flags & FLAGS_WIDTHPARAM) {
+      width = (int)input[optr->width].val.nums;
       if(width < 0) {
         /* "A negative field width is taken as a '-' flag followed by a
            positive field width." */
-        width = -width;
-        p->flags |= FLAGS_LEFT;
-        p->flags &= ~FLAGS_PAD_NIL;
+        if(width == INT_MIN)
+          width = INT_MAX;
+        else
+          width = -width;
+        flags |= FLAGS_LEFT;
+        flags &= ~(unsigned int)FLAGS_PAD_NIL;
       }
     }
     else
-      width = p->width;
+      width = optr->width;
 
     /* pick up the specified precision */
-    if(p->flags & FLAGS_PRECPARAM) {
-      prec = (long)vto[p->precision].data.num.as_signed;
-      param_num++; /* since the precision is extracted from a parameter, we
-                      must skip that to get to the next one properly */
+    if(flags & FLAGS_PRECPARAM) {
+      prec = (int)input[optr->precision].val.nums;
       if(prec < 0)
         /* "A negative precision is taken as if the precision were
            omitted." */
         prec = -1;
     }
-    else if(p->flags & FLAGS_PREC)
-      prec = p->precision;
+    else if(flags & FLAGS_PREC)
+      prec = optr->precision;
     else
       prec = -1;
 
-    is_alt = (p->flags & FLAGS_ALT) ? 1 : 0;
+    is_alt = (flags & FLAGS_ALT) ? 1 : 0;
+    iptr = &input[optr->input];
 
-    switch(p->type) {
+    switch(iptr->type) {
+    case FORMAT_INTU:
+    case FORMAT_LONGU:
+    case FORMAT_LONGLONGU:
+      flags |= FLAGS_UNSIGNED;
+      FALLTHROUGH();
     case FORMAT_INT:
-      num = p->data.num.as_unsigned;
-      if(p->flags & FLAGS_CHAR) {
+    case FORMAT_LONG:
+    case FORMAT_LONGLONG:
+      num = iptr->val.numu;
+      if(flags & FLAGS_CHAR) {
         /* Character.  */
-        if(!(p->flags & FLAGS_LEFT))
+        if(!(flags & FLAGS_LEFT))
           while(--width > 0)
             OUTCHAR(' ');
         OUTCHAR((char) num);
-        if(p->flags & FLAGS_LEFT)
+        if(flags & FLAGS_LEFT)
           while(--width > 0)
             OUTCHAR(' ');
         break;
       }
-      if(p->flags & FLAGS_OCTAL) {
-        /* Octal unsigned integer.  */
+      if(flags & FLAGS_OCTAL) {
+        /* Octal unsigned integer */
         base = 8;
-        goto unsigned_number;
+        is_neg = FALSE;
       }
-      else if(p->flags & FLAGS_HEX) {
-        /* Hexadecimal unsigned integer.  */
-
-        digits = (p->flags & FLAGS_UPPER)? upper_digits : lower_digits;
+      else if(flags & FLAGS_HEX) {
+        /* Hexadecimal unsigned integer */
+        digits = (flags & FLAGS_UPPER)? upper_digits : lower_digits;
         base = 16;
-        goto unsigned_number;
+        is_neg = FALSE;
       }
-      else if(p->flags & FLAGS_UNSIGNED) {
-        /* Decimal unsigned integer.  */
+      else if(flags & FLAGS_UNSIGNED) {
+        /* Decimal unsigned integer */
         base = 10;
-        goto unsigned_number;
+        is_neg = FALSE;
       }
+      else {
+        /* Decimal integer.  */
+        base = 10;
 
-      /* Decimal integer.  */
-      base = 10;
-
-      is_neg = (p->data.num.as_signed < (mp_intmax_t)0) ? 1 : 0;
-      if(is_neg) {
-        /* signed_num might fail to hold absolute negative minimum by 1 */
-        signed_num = p->data.num.as_signed + (mp_intmax_t)1;
-        signed_num = -signed_num;
-        num = (mp_uintmax_t)signed_num;
-        num += (mp_uintmax_t)1;
+        is_neg = (iptr->val.nums < (mp_intmax_t)0);
+        if(is_neg) {
+          /* signed_num might fail to hold absolute negative minimum by 1 */
+          signed_num = iptr->val.nums + (mp_intmax_t)1;
+          signed_num = -signed_num;
+          num = (mp_uintmax_t)signed_num;
+          num += (mp_uintmax_t)1;
+        }
       }
-
-      goto number;
-
-unsigned_number:
-      /* Unsigned number of base BASE.  */
-      is_neg = 0;
-
 number:
-      /* Number of base BASE.  */
-
       /* Supply a default precision if none was given.  */
       if(prec == -1)
         prec = 1;
 
       /* Put the number in WORK.  */
       w = workend;
-      while(num > 0) {
-        *w-- = digits[num % base];
-        num /= base;
+      switch(base) {
+      case 10:
+        while(num > 0) {
+          *w-- = (char)('0' + (num % 10));
+          num /= 10;
+        }
+        break;
+      default:
+        while(num > 0) {
+          *w-- = digits[num % base];
+          num /= base;
+        }
+        break;
       }
-      width -= (long)(workend - w);
-      prec -= (long)(workend - w);
+      width -= (int)(workend - w);
+      prec -= (int)(workend - w);
 
       if(is_alt && base == 8 && prec <= 0) {
         *w-- = '0';
@@ -777,29 +821,29 @@ static int dprintf_formatf(
       if(is_alt && base == 16)
         width -= 2;
 
-      if(is_neg || (p->flags & FLAGS_SHOWSIGN) || (p->flags & FLAGS_SPACE))
+      if(is_neg || (flags & FLAGS_SHOWSIGN) || (flags & FLAGS_SPACE))
         --width;
 
-      if(!(p->flags & FLAGS_LEFT) && !(p->flags & FLAGS_PAD_NIL))
+      if(!(flags & FLAGS_LEFT) && !(flags & FLAGS_PAD_NIL))
         while(width-- > 0)
           OUTCHAR(' ');
 
       if(is_neg)
         OUTCHAR('-');
-      else if(p->flags & FLAGS_SHOWSIGN)
+      else if(flags & FLAGS_SHOWSIGN)
         OUTCHAR('+');
-      else if(p->flags & FLAGS_SPACE)
+      else if(flags & FLAGS_SPACE)
         OUTCHAR(' ');
 
       if(is_alt && base == 16) {
         OUTCHAR('0');
-        if(p->flags & FLAGS_UPPER)
+        if(flags & FLAGS_UPPER)
           OUTCHAR('X');
         else
           OUTCHAR('x');
       }
 
-      if(!(p->flags & FLAGS_LEFT) && (p->flags & FLAGS_PAD_NIL))
+      if(!(flags & FLAGS_LEFT) && (flags & FLAGS_PAD_NIL))
         while(width-- > 0)
           OUTCHAR('0');
 
@@ -808,219 +852,200 @@ static int dprintf_formatf(
         OUTCHAR(*w);
       }
 
-      if(p->flags & FLAGS_LEFT)
+      if(flags & FLAGS_LEFT)
         while(width-- > 0)
           OUTCHAR(' ');
       break;
 
-    case FORMAT_STRING:
-            /* String.  */
-      {
-        static const char null[] = "(nil)";
-        const char *str;
-        size_t len;
-
-        str = (char *) p->data.str;
-        if(!str) {
-          /* Write null[] if there's space.  */
-          if(prec == -1 || prec >= (long) sizeof(null) - 1) {
-            str = null;
-            len = sizeof(null) - 1;
-            /* Disable quotes around (nil) */
-            p->flags &= (~FLAGS_ALT);
-          }
-          else {
-            str = "";
-            len = 0;
-          }
+    case FORMAT_STRING: {
+      const char *str;
+      size_t len;
+
+      str = (char *)iptr->val.str;
+      if(!str) {
+        /* Write null string if there's space.  */
+        if(prec == -1 || prec >= (int) sizeof(nilstr) - 1) {
+          str = nilstr;
+          len = sizeof(nilstr) - 1;
+          /* Disable quotes around (nil) */
+          flags &= ~(unsigned int)FLAGS_ALT;
         }
-        else if(prec != -1)
-          len = (size_t)prec;
-        else if(*str == '\0')
+        else {
+          str = "";
           len = 0;
-        else
-          len = strlen(str);
+        }
+      }
+      else if(prec != -1)
+        len = (size_t)prec;
+      else if(*str == '\0')
+        len = 0;
+      else
+        len = strlen(str);
 
-        width -= (len > LONG_MAX) ? LONG_MAX : (long)len;
+      width -= (len > INT_MAX) ? INT_MAX : (int)len;
 
-        if(p->flags & FLAGS_ALT)
-          OUTCHAR('"');
+      if(flags & FLAGS_ALT)
+        OUTCHAR('"');
 
-        if(!(p->flags&FLAGS_LEFT))
-          while(width-- > 0)
-            OUTCHAR(' ');
+      if(!(flags & FLAGS_LEFT))
+        while(width-- > 0)
+          OUTCHAR(' ');
 
-        for(; len && *str; len--)
-          OUTCHAR(*str++);
-        if(p->flags&FLAGS_LEFT)
-          while(width-- > 0)
-            OUTCHAR(' ');
+      for(; len && *str; len--)
+        OUTCHAR(*str++);
+      if(flags & FLAGS_LEFT)
+        while(width-- > 0)
+          OUTCHAR(' ');
 
-        if(p->flags & FLAGS_ALT)
-          OUTCHAR('"');
-      }
+      if(flags & FLAGS_ALT)
+        OUTCHAR('"');
       break;
+    }
 
     case FORMAT_PTR:
       /* Generic pointer.  */
-      {
-        void *ptr;
-        ptr = (void *) p->data.ptr;
-        if(ptr) {
-          /* If the pointer is not NULL, write it as a %#x spec.  */
-          base = 16;
-          digits = (p->flags & FLAGS_UPPER)? upper_digits : lower_digits;
-          is_alt = 1;
-          num = (size_t) ptr;
-          is_neg = 0;
-          goto number;
-        }
-        else {
-          /* Write "(nil)" for a nil pointer.  */
-          static const char strnil[] = "(nil)";
-          const char *point;
-
-          width -= (long)(sizeof(strnil) - 1);
-          if(p->flags & FLAGS_LEFT)
-            while(width-- > 0)
-              OUTCHAR(' ');
-          for(point = strnil; *point != '\0'; ++point)
-            OUTCHAR(*point);
-          if(!(p->flags & FLAGS_LEFT))
-            while(width-- > 0)
-              OUTCHAR(' ');
-        }
+      if(iptr->val.ptr) {
+        /* If the pointer is not NULL, write it as a %#x spec.  */
+        base = 16;
+        digits = (flags & FLAGS_UPPER)? upper_digits : lower_digits;
+        is_alt = TRUE;
+        num = (size_t) iptr->val.ptr;
+        is_neg = FALSE;
+        goto number;
       }
-      break;
+      else {
+        /* Write "(nil)" for a nil pointer.  */
+        const char *point;
 
-    case FORMAT_DOUBLE:
-      {
-        char formatbuf[32]="%";
-        char *fptr = &formatbuf[1];
-        size_t left = sizeof(formatbuf)-strlen(formatbuf);
-        int len;
-
-        width = -1;
-        if(p->flags & FLAGS_WIDTH)
-          width = p->width;
-        else if(p->flags & FLAGS_WIDTHPARAM)
-          width = (long)vto[p->width].data.num.as_signed;
+        width -= (int)(sizeof(nilstr) - 1);
+        if(flags & FLAGS_LEFT)
+          while(width-- > 0)
+            OUTCHAR(' ');
+        for(point = nilstr; *point != '\0'; ++point)
+          OUTCHAR(*point);
+        if(!(flags & FLAGS_LEFT))
+          while(width-- > 0)
+            OUTCHAR(' ');
+      }
+      break;
 
-        prec = -1;
-        if(p->flags & FLAGS_PREC)
-          prec = p->precision;
-        else if(p->flags & FLAGS_PRECPARAM)
-          prec = (long)vto[p->precision].data.num.as_signed;
-
-        if(p->flags & FLAGS_LEFT)
-          *fptr++ = '-';
-        if(p->flags & FLAGS_SHOWSIGN)
-          *fptr++ = '+';
-        if(p->flags & FLAGS_SPACE)
-          *fptr++ = ' ';
-        if(p->flags & FLAGS_ALT)
-          *fptr++ = '#';
-
-        *fptr = 0;
-
-        if(width >= 0) {
-          if(width >= (long)sizeof(work))
-            width = sizeof(work)-1;
-          /* RECURSIVE USAGE */
-          len = curl_msnprintf(fptr, left, "%ld", width);
-          fptr += len;
-          left -= len;
+    case FORMAT_DOUBLE: {
+      char formatbuf[32]="%";
+      char *fptr = &formatbuf[1];
+      size_t left = sizeof(formatbuf)-strlen(formatbuf);
+      int len;
+
+      if(flags & FLAGS_WIDTH)
+        width = optr->width;
+
+      if(flags & FLAGS_PREC)
+        prec = optr->precision;
+
+      if(flags & FLAGS_LEFT)
+        *fptr++ = '-';
+      if(flags & FLAGS_SHOWSIGN)
+        *fptr++ = '+';
+      if(flags & FLAGS_SPACE)
+        *fptr++ = ' ';
+      if(flags & FLAGS_ALT)
+        *fptr++ = '#';
+
+      *fptr = 0;
+
+      if(width >= 0) {
+        size_t dlen;
+        if(width >= (int)sizeof(work))
+          width = sizeof(work)-1;
+        /* RECURSIVE USAGE */
+        dlen = (size_t)curl_msnprintf(fptr, left, "%d", width);
+        fptr += dlen;
+        left -= dlen;
+      }
+      if(prec >= 0) {
+        /* for each digit in the integer part, we can have one less
+           precision */
+        size_t maxprec = sizeof(work) - 2;
+        double val = iptr->val.dnum;
+        if(width > 0 && prec <= width)
+          maxprec -= (size_t)width;
+        while(val >= 10.0) {
+          val /= 10;
+          maxprec--;
         }
-        if(prec >= 0) {
-          /* for each digit in the integer part, we can have one less
-             precision */
-          size_t maxprec = sizeof(work) - 2;
-          double val = p->data.dnum;
-          if(width > 0 && prec <= width)
-            maxprec -= width;
-          while(val >= 10.0) {
-            val /= 10;
-            maxprec--;
-          }
 
-          if(prec > (long)maxprec)
-            prec = (long)maxprec-1;
-          if(prec < 0)
-            prec = 0;
-          /* RECURSIVE USAGE */
-          len = curl_msnprintf(fptr, left, ".%ld", prec);
-          fptr += len;
-        }
-        if(p->flags & FLAGS_LONG)
-          *fptr++ = 'l';
+        if(prec > (int)maxprec)
+          prec = (int)maxprec-1;
+        if(prec < 0)
+          prec = 0;
+        /* RECURSIVE USAGE */
+        len = curl_msnprintf(fptr, left, ".%d", prec);
+        fptr += len;
+      }
+      if(flags & FLAGS_LONG)
+        *fptr++ = 'l';
 
-        if(p->flags & FLAGS_FLOATE)
-          *fptr++ = (char)((p->flags & FLAGS_UPPER) ? 'E':'e');
-        else if(p->flags & FLAGS_FLOATG)
-          *fptr++ = (char)((p->flags & FLAGS_UPPER) ? 'G' : 'g');
-        else
-          *fptr++ = 'f';
+      if(flags & FLAGS_FLOATE)
+        *fptr++ = (char)((flags & FLAGS_UPPER) ? 'E':'e');
+      else if(flags & FLAGS_FLOATG)
+        *fptr++ = (char)((flags & FLAGS_UPPER) ? 'G' : 'g');
+      else
+        *fptr++ = 'f';
 
-        *fptr = 0; /* and a final null-termination */
+      *fptr = 0; /* and a final null-termination */
 
 #ifdef __clang__
 #pragma clang diagnostic push
 #pragma clang diagnostic ignored "-Wformat-nonliteral"
 #endif
-        /* NOTE NOTE NOTE!! Not all sprintf implementations return number of
-           output characters */
+      /* NOTE NOTE NOTE!! Not all sprintf implementations return number of
+         output characters */
 #ifdef HAVE_SNPRINTF
-        (snprintf)(work, sizeof(work), formatbuf, p->data.dnum);
+      (snprintf)(work, sizeof(work), formatbuf, iptr->val.dnum);
 #else
-        (sprintf)(work, formatbuf, p->data.dnum);
+      (sprintf)(work, formatbuf, iptr->val.dnum);
 #endif
 #ifdef __clang__
 #pragma clang diagnostic pop
 #endif
-        DEBUGASSERT(strlen(work) <= sizeof(work));
-        for(fptr = work; *fptr; fptr++)
-          OUTCHAR(*fptr);
-      }
+      DEBUGASSERT(strlen(work) <= sizeof(work));
+      for(fptr = work; *fptr; fptr++)
+        OUTCHAR(*fptr);
       break;
+    }
 
     case FORMAT_INTPTR:
       /* Answer the count of characters written.  */
 #ifdef HAVE_LONG_LONG_TYPE
-      if(p->flags & FLAGS_LONGLONG)
-        *(LONG_LONG_TYPE *) p->data.ptr = (LONG_LONG_TYPE)done;
+      if(flags & FLAGS_LONGLONG)
+        *(LONG_LONG_TYPE *) iptr->val.ptr = (LONG_LONG_TYPE)done;
       else
 #endif
-        if(p->flags & FLAGS_LONG)
-          *(long *) p->data.ptr = (long)done;
-      else if(!(p->flags & FLAGS_SHORT))
-        *(int *) p->data.ptr = (int)done;
+        if(flags & FLAGS_LONG)
+          *(long *) iptr->val.ptr = (long)done;
+      else if(!(flags & FLAGS_SHORT))
+        *(int *) iptr->val.ptr = (int)done;
       else
-        *(short *) p->data.ptr = (short)done;
+        *(short *) iptr->val.ptr = (short)done;
       break;
 
     default:
       break;
     }
-    f = *end++; /* goto end of %-code */
-
   }
   return done;
 }
 
 /* fputc() look-alike */
-static int addbyter(int output, FILE *data)
+static int addbyter(unsigned char outc, void *f)
 {
-  struct nsprintf *infop = (struct nsprintf *)data;
-  unsigned char outc = (unsigned char)output;
-
+  struct nsprintf *infop = f;
   if(infop->length < infop->max) {
     /* only do this if we haven't reached max length yet */
-    infop->buffer[0] = outc; /* store */
-    infop->buffer++; /* increase pointer */
+    *infop->buffer++ = (char)outc; /* store */
     infop->length++; /* we are now one byte larger */
-    return outc;     /* fputc() returns like this on success */
+    return 0;     /* fputc() returns like this on success */
   }
-  return -1;
+  return 1;
 }
 
 int curl_mvsnprintf(char *buffer, size_t maxlength, const char *format,
@@ -1033,7 +1058,7 @@ int curl_mvsnprintf(char *buffer, size_t maxlength, const char *format,
   info.length = 0;
   info.max = maxlength;
 
-  retcode = dprintf_formatf(&info, addbyter, format, ap_save);
+  retcode = formatf(&info, addbyter, format, ap_save);
   if(info.max) {
     /* we terminate this with a zero byte */
     if(info.max == info.length) {
@@ -1059,32 +1084,28 @@ int curl_msnprintf(char *buffer, size_t maxlength, const char *format, ...)
 }
 
 /* fputc() look-alike */
-static int alloc_addbyter(int output, FILE *data)
+static int alloc_addbyter(unsigned char outc, void *f)
 {
-  struct asprintf *infop = (struct asprintf *)data;
-  unsigned char outc = (unsigned char)output;
-
-  if(Curl_dyn_addn(infop->b, &outc, 1)) {
-    infop->fail = 1;
-    return -1; /* fail */
+  struct asprintf *infop = f;
+  CURLcode result = Curl_dyn_addn(infop->b, &outc, 1);
+  if(result) {
+    infop->merr = result == CURLE_TOO_LARGE ? MERR_TOO_LARGE : MERR_MEM;
+    return 1 ; /* fail */
   }
-  return outc; /* fputc() returns like this on success */
+  return 0;
 }
 
-extern int Curl_dyn_vprintf(struct dynbuf *dyn,
-                            const char *format, va_list ap_save);
-
-/* appends the formatted string, returns 0 on success, 1 on error */
+/* appends the formatted string, returns MERR error code */
 int Curl_dyn_vprintf(struct dynbuf *dyn, const char *format, va_list ap_save)
 {
   struct asprintf info;
   info.b = dyn;
-  info.fail = 0;
+  info.merr = MERR_OK;
 
-  (void)dprintf_formatf(&info, alloc_addbyter, format, ap_save);
-  if(info.fail) {
+  (void)formatf(&info, alloc_addbyter, format, ap_save);
+  if(info.merr) {
     Curl_dyn_free(info.b);
-    return 1;
+    return info.merr;
   }
   return 0;
 }
@@ -1095,10 +1116,10 @@ char *curl_mvaprintf(const char *format, va_list ap_save)
   struct dynbuf dyn;
   info.b = &dyn;
   Curl_dyn_init(info.b, DYN_APRINTF);
-  info.fail = 0;
+  info.merr = MERR_OK;
 
-  (void)dprintf_formatf(&info, alloc_addbyter, format, ap_save);
-  if(info.fail) {
+  (void)formatf(&info, alloc_addbyter, format, ap_save);
+  if(info.merr) {
     Curl_dyn_free(info.b);
     return NULL;
   }
@@ -1117,13 +1138,12 @@ char *curl_maprintf(const char *format, ...)
   return s;
 }
 
-static int storebuffer(int output, FILE *data)
+static int storebuffer(unsigned char outc, void *f)
 {
-  char **buffer = (char **)data;
-  unsigned char outc = (unsigned char)output;
-  **buffer = outc;
+  char **buffer = f;
+  **buffer = (char)outc;
   (*buffer)++;
-  return outc; /* act like fputc() ! */
+  return 0;
 }
 
 int curl_msprintf(char *buffer, const char *format, ...)
@@ -1131,19 +1151,27 @@ int curl_msprintf(char *buffer, const char *format, ...)
   va_list ap_save; /* argument pointer */
   int retcode;
   va_start(ap_save, format);
-  retcode = dprintf_formatf(&buffer, storebuffer, format, ap_save);
+  retcode = formatf(&buffer, storebuffer, format, ap_save);
   va_end(ap_save);
   *buffer = 0; /* we terminate this with a zero byte */
   return retcode;
 }
 
+static int fputc_wrapper(unsigned char outc, void *f)
+{
+  int out = outc;
+  FILE *s = f;
+  int rc = fputc(out, s);
+  return rc == EOF;
+}
+
 int curl_mprintf(const char *format, ...)
 {
   int retcode;
   va_list ap_save; /* argument pointer */
   va_start(ap_save, format);
 
-  retcode = dprintf_formatf(stdout, fputc, format, ap_save);
+  retcode = formatf(stdout, fputc_wrapper, format, ap_save);
   va_end(ap_save);
   return retcode;
 }
@@ -1153,25 +1181,24 @@ int curl_mfprintf(FILE *whereto, const char *format, ...)
   int retcode;
   va_list ap_save; /* argument pointer */
   va_start(ap_save, format);
-  retcode = dprintf_formatf(whereto, fputc, format, ap_save);
+  retcode = formatf(whereto, fputc_wrapper, format, ap_save);
   va_end(ap_save);
   return retcode;
 }
 
 int curl_mvsprintf(char *buffer, const char *format, va_list ap_save)
 {
-  int retcode;
-  retcode = dprintf_formatf(&buffer, storebuffer, format, ap_save);
+  int retcode = formatf(&buffer, storebuffer, format, ap_save);
   *buffer = 0; /* we terminate this with a zero byte */
   return retcode;
 }
 
 int curl_mvprintf(const char *format, va_list ap_save)
 {
-  return dprintf_formatf(stdout, fputc, format, ap_save);
+  return formatf(stdout, fputc_wrapper, format, ap_save);
 }
 
 int curl_mvfprintf(FILE *whereto, const char *format, va_list ap_save)
 {
-  return dprintf_formatf(whereto, fputc, format, ap_save);
+  return formatf(whereto, fputc_wrapper, format, ap_save);
 }
diff --git a/vendor/curl/lib/mqtt.c b/vendor/curl/lib/mqtt.c
index 30edf3dd8a..4ca24eb41c 100644
--- a/vendor/curl/lib/mqtt.c
+++ b/vendor/curl/lib/mqtt.c
@@ -75,7 +75,7 @@ static CURLcode mqtt_setup_conn(struct Curl_easy *data,
  */
 
 const struct Curl_handler Curl_handler_mqtt = {
-  "MQTT",                             /* scheme */
+  "mqtt",                             /* scheme */
   mqtt_setup_conn,                    /* setup_connection */
   mqtt_do,                            /* do_it */
   mqtt_done,                          /* done */
@@ -88,7 +88,8 @@ const struct Curl_handler Curl_handler_mqtt = {
   ZERO_NULL,                          /* domore_getsock */
   ZERO_NULL,                          /* perform_getsock */
   ZERO_NULL,                          /* disconnect */
-  ZERO_NULL,                          /* readwrite */
+  ZERO_NULL,                          /* write_resp */
+  ZERO_NULL,                          /* write_resp_hd */
   ZERO_NULL,                          /* connection_check */
   ZERO_NULL,                          /* attach connection */
   PORT_MQTT,                          /* defport */
@@ -109,6 +110,7 @@ static CURLcode mqtt_setup_conn(struct Curl_easy *data,
   mq = calloc(1, sizeof(struct MQTT));
   if(!mq)
     return CURLE_OUT_OF_MEMORY;
+  Curl_dyn_init(&mq->recvbuf, DYN_MQTT_RECV);
   data->req.p.mqtt = mq;
   return CURLE_OK;
 }
@@ -118,12 +120,12 @@ static CURLcode mqtt_send(struct Curl_easy *data,
 {
   CURLcode result = CURLE_OK;
   struct MQTT *mq = data->req.p.mqtt;
-  ssize_t n;
-  result = Curl_nwrite(data, FIRSTSOCKET, buf, len, &n);
+  size_t n;
+  result = Curl_xfer_send(data, buf, len, &n);
   if(result)
     return result;
   Curl_debug(data, CURLINFO_HEADER_OUT, buf, (size_t)n);
-  if(len != (size_t)n) {
+  if(len != n) {
     size_t nsend = len - n;
     char *sendleftovers = Curl_memdup(&buf[n], nsend);
     if(!sendleftovers)
@@ -295,12 +297,12 @@ static CURLcode mqtt_connect(struct Curl_easy *data)
   /* set initial values for the CONNECT packet */
   pos = init_connpack(packet, remain, remain_pos);
 
-  result = Curl_rand_hex(data, (unsigned char *)&client_id[clen],
-                         MQTT_CLIENTID_LEN - clen + 1);
+  result = Curl_rand_alnum(data, (unsigned char *)&client_id[clen],
+                           MQTT_CLIENTID_LEN - clen + 1);
   /* add client id */
   rc = add_client_id(client_id, strlen(client_id), packet, pos + 1);
   if(rc) {
-    failf(data, "Client ID length mismatched: [%lu]", strlen(client_id));
+    failf(data, "Client ID length mismatched: [%zu]", strlen(client_id));
     result = CURLE_WEIRD_SERVER_REPLY;
     goto end;
   }
@@ -317,7 +319,7 @@ static CURLcode mqtt_connect(struct Curl_easy *data)
     rc = add_user(username, ulen,
                   (unsigned char *)packet, start_user, remain_pos);
     if(rc) {
-      failf(data, "Username is too large: [%lu]", ulen);
+      failf(data, "Username is too large: [%zu]", ulen);
       result = CURLE_WEIRD_SERVER_REPLY;
       goto end;
     }
@@ -327,7 +329,7 @@ static CURLcode mqtt_connect(struct Curl_easy *data)
   if(plen) {
     rc = add_passwd(passwd, plen, packet, start_pwd, remain_pos);
     if(rc) {
-      failf(data, "Password is too large: [%lu]", plen);
+      failf(data, "Password is too large: [%zu]", plen);
       result = CURLE_WEIRD_SERVER_REPLY;
       goto end;
     }
@@ -350,36 +352,65 @@ static CURLcode mqtt_disconnect(struct Curl_easy *data)
   struct MQTT *mq = data->req.p.mqtt;
   result = mqtt_send(data, (char *)"\xe0\x00", 2);
   Curl_safefree(mq->sendleftovers);
+  Curl_dyn_free(&mq->recvbuf);
   return result;
 }
 
-static CURLcode mqtt_verify_connack(struct Curl_easy *data)
+static CURLcode mqtt_recv_atleast(struct Curl_easy *data, size_t nbytes)
 {
+  struct MQTT *mq = data->req.p.mqtt;
+  size_t rlen = Curl_dyn_len(&mq->recvbuf);
   CURLcode result;
-  struct connectdata *conn = data->conn;
-  curl_socket_t sockfd = conn->sock[FIRSTSOCKET];
-  unsigned char readbuf[MQTT_CONNACK_LEN];
-  ssize_t nread;
 
-  result = Curl_read(data, sockfd, (char *)readbuf, MQTT_CONNACK_LEN, &nread);
-  if(result)
-    goto fail;
+  if(rlen < nbytes) {
+    unsigned char readbuf[1024];
+    ssize_t nread;
+
+    DEBUGASSERT(nbytes - rlen < sizeof(readbuf));
+    result = Curl_xfer_recv(data, (char *)readbuf, nbytes - rlen, &nread);
+    if(result)
+      return result;
+    DEBUGASSERT(nread >= 0);
+    if(Curl_dyn_addn(&mq->recvbuf, readbuf, (size_t)nread))
+      return CURLE_OUT_OF_MEMORY;
+    rlen = Curl_dyn_len(&mq->recvbuf);
+  }
+  return (rlen >= nbytes)? CURLE_OK : CURLE_AGAIN;
+}
 
-  Curl_debug(data, CURLINFO_HEADER_IN, (char *)readbuf, (size_t)nread);
+static void mqtt_recv_consume(struct Curl_easy *data, size_t nbytes)
+{
+  struct MQTT *mq = data->req.p.mqtt;
+  size_t rlen = Curl_dyn_len(&mq->recvbuf);
+  if(rlen <= nbytes)
+    Curl_dyn_reset(&mq->recvbuf);
+  else
+    Curl_dyn_tail(&mq->recvbuf, rlen - nbytes);
+}
 
-  /* fixme */
-  if(nread < MQTT_CONNACK_LEN) {
-    result = CURLE_WEIRD_SERVER_REPLY;
+static CURLcode mqtt_verify_connack(struct Curl_easy *data)
+{
+  struct MQTT *mq = data->req.p.mqtt;
+  CURLcode result;
+  char *ptr;
+
+  result = mqtt_recv_atleast(data, MQTT_CONNACK_LEN);
+  if(result)
     goto fail;
-  }
 
   /* verify CONNACK */
-  if(readbuf[0] != 0x00 || readbuf[1] != 0x00) {
+  DEBUGASSERT(Curl_dyn_len(&mq->recvbuf) >= MQTT_CONNACK_LEN);
+  ptr = Curl_dyn_ptr(&mq->recvbuf);
+  Curl_debug(data, CURLINFO_HEADER_IN, ptr, MQTT_CONNACK_LEN);
+
+  if(ptr[0] != 0x00 || ptr[1] != 0x00) {
     failf(data, "Expected %02x%02x but got %02x%02x",
-          0x00, 0x00, readbuf[0], readbuf[1]);
+          0x00, 0x00, ptr[0], ptr[1]);
+    Curl_dyn_reset(&mq->recvbuf);
     result = CURLE_WEIRD_SERVER_REPLY;
+    goto fail;
   }
-
+  mqtt_recv_consume(data, MQTT_CONNACK_LEN);
 fail:
   return result;
 }
@@ -452,31 +483,29 @@ static CURLcode mqtt_subscribe(struct Curl_easy *data)
  */
 static CURLcode mqtt_verify_suback(struct Curl_easy *data)
 {
-  CURLcode result;
+  struct MQTT *mq = data->req.p.mqtt;
   struct connectdata *conn = data->conn;
-  curl_socket_t sockfd = conn->sock[FIRSTSOCKET];
-  unsigned char readbuf[MQTT_SUBACK_LEN];
-  ssize_t nread;
   struct mqtt_conn *mqtt = &conn->proto.mqtt;
+  CURLcode result;
+  char *ptr;
 
-  result = Curl_read(data, sockfd, (char *)readbuf, MQTT_SUBACK_LEN, &nread);
+  result = mqtt_recv_atleast(data, MQTT_SUBACK_LEN);
   if(result)
     goto fail;
 
-  Curl_debug(data, CURLINFO_HEADER_IN, (char *)readbuf, (size_t)nread);
-
-  /* fixme */
-  if(nread < MQTT_SUBACK_LEN) {
+  /* verify SUBACK */
+  DEBUGASSERT(Curl_dyn_len(&mq->recvbuf) >= MQTT_SUBACK_LEN);
+  ptr = Curl_dyn_ptr(&mq->recvbuf);
+  Curl_debug(data, CURLINFO_HEADER_IN, ptr, MQTT_SUBACK_LEN);
+
+  if(((unsigned char)ptr[0]) != ((mqtt->packetid >> 8) & 0xff) ||
+     ((unsigned char)ptr[1]) != (mqtt->packetid & 0xff) ||
+     ptr[2] != 0x00) {
+    Curl_dyn_reset(&mq->recvbuf);
     result = CURLE_WEIRD_SERVER_REPLY;
     goto fail;
   }
-
-  /* verify SUBACK */
-  if(readbuf[0] != ((mqtt->packetid >> 8) & 0xff) ||
-     readbuf[1] != (mqtt->packetid & 0xff) ||
-     readbuf[2] != 0x00)
-    result = CURLE_WEIRD_SERVER_REPLY;
-
+  mqtt_recv_consume(data, MQTT_SUBACK_LEN);
 fail:
   return result;
 }
@@ -495,8 +524,10 @@ static CURLcode mqtt_publish(struct Curl_easy *data)
   char encodedbytes[4];
   curl_off_t postfieldsize = data->set.postfieldsize;
 
-  if(!payload)
+  if(!payload) {
+    DEBUGF(infof(data, "mqtt_publish without payload, return bad arg"));
     return CURLE_BAD_FUNCTION_ARGUMENT;
+  }
   if(postfieldsize < 0)
     payloadlen = strlen(payload);
   else
@@ -587,16 +618,11 @@ static void mqstate(struct Curl_easy *data,
 }
 
 
-/* for the publish packet */
-#define MQTT_HEADER_LEN 5    /* max 5 bytes */
-
 static CURLcode mqtt_read_publish(struct Curl_easy *data, bool *done)
 {
   CURLcode result = CURLE_OK;
   struct connectdata *conn = data->conn;
-  curl_socket_t sockfd = conn->sock[FIRSTSOCKET];
   ssize_t nread;
-  unsigned char *pkt = (unsigned char *)data->state.buffer;
   size_t remlen;
   struct mqtt_conn *mqtt = &conn->proto.mqtt;
   struct MQTT *mq = data->req.p.mqtt;
@@ -645,14 +671,14 @@ static CURLcode mqtt_read_publish(struct Curl_easy *data, bool *done)
     data->req.bytecount = 0;
     data->req.size = remlen;
     mq->npacket = remlen; /* get this many bytes */
-    /* FALLTHROUGH */
+    FALLTHROUGH();
   case MQTT_PUB_REMAIN: {
     /* read rest of packet, but no more. Cap to buffer size */
-    struct SingleRequest *k = &data->req;
+    char buffer[4*1024];
     size_t rest = mq->npacket;
-    if(rest > (size_t)data->set.buffer_size)
-      rest = (size_t)data->set.buffer_size;
-    result = Curl_read(data, sockfd, (char *)pkt, rest, &nread);
+    if(rest > sizeof(buffer))
+      rest = sizeof(buffer);
+    result = Curl_xfer_recv(data, buffer, rest, &nread);
     if(result) {
       if(CURLE_AGAIN == result) {
         infof(data, "EEEE AAAAGAIN");
@@ -664,18 +690,13 @@ static CURLcode mqtt_read_publish(struct Curl_easy *data, bool *done)
       result = CURLE_PARTIAL_FILE;
       goto end;
     }
-    Curl_debug(data, CURLINFO_DATA_IN, (char *)pkt, (size_t)nread);
-
-    mq->npacket -= nread;
-    k->bytecount += nread;
-    Curl_pgrsSetDownloadCounter(data, k->bytecount);
 
     /* if QoS is set, message contains packet id */
-
-    result = Curl_client_write(data, CLIENTWRITE_BODY, (char *)pkt, nread);
+    result = Curl_client_write(data, CLIENTWRITE_BODY, buffer, nread);
     if(result)
       goto end;
 
+    mq->npacket -= nread;
     if(!mq->npacket)
       /* no more PUBLISH payload, back to subscribe wait state */
       mqstate(data, MQTT_FIRST, MQTT_PUBWAIT);
@@ -711,6 +732,7 @@ static CURLcode mqtt_done(struct Curl_easy *data,
   (void)status;
   (void)premature;
   Curl_safefree(mq->sendleftovers);
+  Curl_dyn_free(&mq->recvbuf);
   return CURLE_OK;
 }
 
@@ -721,8 +743,6 @@ static CURLcode mqtt_doing(struct Curl_easy *data, bool *done)
   struct mqtt_conn *mqtt = &conn->proto.mqtt;
   struct MQTT *mq = data->req.p.mqtt;
   ssize_t nread;
-  curl_socket_t sockfd = conn->sock[FIRSTSOCKET];
-  unsigned char *pkt = (unsigned char *)data->state.buffer;
   unsigned char byte;
 
   *done = FALSE;
@@ -740,7 +760,7 @@ static CURLcode mqtt_doing(struct Curl_easy *data, bool *done)
   switch(mqtt->state) {
   case MQTT_FIRST:
     /* Read the initial byte only */
-    result = Curl_read(data, sockfd, (char *)&mq->firstbyte, 1, &nread);
+    result = Curl_xfer_recv(data, (char *)&mq->firstbyte, 1, &nread);
     if(result)
       break;
     else if(!nread) {
@@ -753,22 +773,22 @@ static CURLcode mqtt_doing(struct Curl_easy *data, bool *done)
     /* remember the first byte */
     mq->npacket = 0;
     mqstate(data, MQTT_REMAINING_LENGTH, MQTT_NOSTATE);
-    /* FALLTHROUGH */
+    FALLTHROUGH();
   case MQTT_REMAINING_LENGTH:
     do {
-      result = Curl_read(data, sockfd, (char *)&byte, 1, &nread);
-      if(!nread)
+      result = Curl_xfer_recv(data, (char *)&byte, 1, &nread);
+      if(result || !nread)
         break;
       Curl_debug(data, CURLINFO_HEADER_IN, (char *)&byte, 1);
-      pkt[mq->npacket++] = byte;
+      mq->pkt_hd[mq->npacket++] = byte;
     } while((byte & 0x80) && (mq->npacket < 4));
-    if(nread && (byte & 0x80))
+    if(!result && nread && (byte & 0x80))
       /* MQTT supports up to 127 * 128^0 + 127 * 128^1 + 127 * 128^2 +
          127 * 128^3 bytes. server tried to send more */
       result = CURLE_WEIRD_SERVER_REPLY;
     if(result)
       break;
-    mq->remaining_length = mqtt_decode_len(&pkt[0], mq->npacket, NULL);
+    mq->remaining_length = mqtt_decode_len(mq->pkt_hd, mq->npacket, NULL);
     mq->npacket = 0;
     if(mq->remaining_length) {
       mqstate(data, mqtt->nextstate, MQTT_NOSTATE);
diff --git a/vendor/curl/lib/mqtt.h b/vendor/curl/lib/mqtt.h
index 63961366fc..99ab12a98a 100644
--- a/vendor/curl/lib/mqtt.h
+++ b/vendor/curl/lib/mqtt.h
@@ -56,6 +56,8 @@ struct MQTT {
   size_t npacket; /* byte counter */
   unsigned char firstbyte;
   size_t remaining_length;
+  struct dynbuf recvbuf;
+  unsigned char pkt_hd[4]; /* for decoding the arriving packet length */
 };
 
 #endif /* HEADER_CURL_MQTT_H */
diff --git a/vendor/curl/lib/multi.c b/vendor/curl/lib/multi.c
index bb57dbceee..6bbdfe2672 100644
--- a/vendor/curl/lib/multi.c
+++ b/vendor/curl/lib/multi.c
@@ -55,22 +55,6 @@
 #include "curl_memory.h"
 #include "memdebug.h"
 
-#ifdef __APPLE__
-
-#define wakeup_write  write
-#define wakeup_read   read
-#define wakeup_close  close
-#define wakeup_create pipe
-
-#else /* __APPLE__ */
-
-#define wakeup_write     swrite
-#define wakeup_read      sread
-#define wakeup_close     sclose
-#define wakeup_create(p) Curl_socketpair(AF_UNIX, SOCK_STREAM, 0, p)
-
-#endif /* __APPLE__ */
-
 /*
   CURL_SOCKET_HASH_TABLE_SIZE should be a prime number. Increasing it from 97
   to 911 takes on a 32-bit machine 4 x 804 = 3211 more bytes.  Still, every
@@ -102,6 +86,8 @@
   ((x) && (x)->magic == CURL_MULTI_HANDLE)
 #endif
 
+static void move_pending_to_connect(struct Curl_multi *multi,
+                                    struct Curl_easy *data);
 static CURLMcode singlesocket(struct Curl_multi *multi,
                               struct Curl_easy *data);
 static CURLMcode add_next_timeout(struct curltime now,
@@ -110,11 +96,13 @@ static CURLMcode add_next_timeout(struct curltime now,
 static CURLMcode multi_timeout(struct Curl_multi *multi,
                                long *timeout_ms);
 static void process_pending_handles(struct Curl_multi *multi);
+static void multi_xfer_bufs_free(struct Curl_multi *multi);
 
 #ifdef DEBUGBUILD
 static const char * const multi_statename[]={
   "INIT",
   "PENDING",
+  "SETUP",
   "CONNECT",
   "RESOLVING",
   "CONNECTING",
@@ -164,6 +152,7 @@ static void mstate(struct Curl_easy *data, CURLMstate state
   static const init_multistate_func finit[MSTATE_LAST] = {
     NULL,              /* INIT */
     NULL,              /* PENDING */
+    NULL,              /* SETUP */
     Curl_init_CONNECT, /* CONNECT */
     NULL,              /* RESOLVING */
     NULL,              /* CONNECTING */
@@ -205,6 +194,10 @@ static void mstate(struct Curl_easy *data, CURLMstate state
     /* changing to COMPLETED means there's one less easy handle 'alive' */
     DEBUGASSERT(data->multi->num_alive > 0);
     data->multi->num_alive--;
+    if(!data->multi->num_alive) {
+      /* free the transfer buffer when we have no more active transfers */
+      multi_xfer_bufs_free(data->multi);
+    }
   }
 
   /* if this state has an init-function, run it */
@@ -231,10 +224,6 @@ struct Curl_sh_entry {
   unsigned int readers; /* this many transfers want to read */
   unsigned int writers; /* this many transfers want to write */
 };
-/* bits for 'action' having no bits means this socket is not expecting any
-   action */
-#define SH_READ  1
-#define SH_WRITE 2
 
 /* look up a given socket in the socket hash, skip invalid sockets */
 static struct Curl_sh_entry *sh_getentry(struct Curl_hash *sh,
@@ -375,7 +364,7 @@ static size_t hash_fd(void *key, size_t key_length, size_t slots_num)
  * per call."
  *
  */
-static void sh_init(struct Curl_hash *hash, int hashsize)
+static void sh_init(struct Curl_hash *hash, size_t hashsize)
 {
   Curl_hash_init(hash, hashsize, hash_fd, fd_key_compare,
                  sh_freeentry);
@@ -389,13 +378,12 @@ static void sh_init(struct Curl_hash *hash, int hashsize)
  */
 static void multi_addmsg(struct Curl_multi *multi, struct Curl_message *msg)
 {
-  Curl_llist_insert_next(&multi->msglist, multi->msglist.tail, msg,
-                         &msg->list);
+  Curl_llist_append(&multi->msglist, msg, &msg->list);
 }
 
-struct Curl_multi *Curl_multi_handle(int hashsize, /* socket hash */
-                                     int chashsize, /* connection hash */
-                                     int dnssize) /* dns hash */
+struct Curl_multi *Curl_multi_handle(size_t hashsize, /* socket hash */
+                                     size_t chashsize, /* connection hash */
+                                     size_t dnssize) /* dns hash */
 {
   struct Curl_multi *multi = calloc(1, sizeof(struct Curl_multi));
 
@@ -416,9 +404,6 @@ struct Curl_multi *Curl_multi_handle(int hashsize, /* socket hash */
   Curl_llist_init(&multi->msgsent, NULL);
 
   multi->multiplexing = TRUE;
-
-  /* -1 means it not set by user, use the default value */
-  multi->maxconnects = -1;
   multi->max_concurrent_streams = 100;
 
 #ifdef USE_WINSOCK
@@ -548,6 +533,13 @@ CURLMcode curl_multi_add_handle(struct Curl_multi *multi,
     multi->dead = FALSE;
   }
 
+  if(data->multi_easy) {
+    /* if this easy handle was previously used for curl_easy_perform(), there
+       is a private multi handle here that we can kill */
+    curl_multi_cleanup(data->multi_easy);
+    data->multi_easy = NULL;
+  }
+
   /* Initialize timeout list for this handle */
   Curl_llist_init(&data->state.timeoutlist, NULL);
 
@@ -560,6 +552,8 @@ CURLMcode curl_multi_add_handle(struct Curl_multi *multi,
   if(data->set.errorbuffer)
     data->set.errorbuffer[0] = 0;
 
+  data->state.os_errno = 0;
+
   /* make the Curl_easy refer back to this multi handle - before Curl_expire()
      is called. */
   data->multi = multi;
@@ -663,9 +657,8 @@ static CURLcode multi_done(struct Curl_easy *data,
                                                 after an error was detected */
                            bool premature)
 {
-  CURLcode result;
+  CURLcode result, r2;
   struct connectdata *conn = data->conn;
-  unsigned int i;
 
 #if defined(DEBUGBUILD) && !defined(CURL_DISABLE_VERBOSE_STRINGS)
   DEBUGF(infof(data, "multi_done[%s]: status: %d prem: %d done: %d",
@@ -696,6 +689,7 @@ static CURLcode multi_done(struct Curl_easy *data,
        many callbacks and protocols work differently, we could potentially do
        this more fine-grained in the future. */
     premature = TRUE;
+    FALLTHROUGH();
   default:
     break;
   }
@@ -714,19 +708,18 @@ static CURLcode multi_done(struct Curl_easy *data,
       result = CURLE_ABORTED_BY_CALLBACK;
   }
 
+  /* Make sure that transfer client writes are really done now. */
+  r2 = Curl_xfer_write_done(data, premature);
+  if(r2 && !result)
+    result = r2;
+
   /* Inform connection filters that this transfer is done */
   Curl_conn_ev_data_done(data, premature);
 
   process_pending_handles(data->multi); /* connection / multiplex */
 
-  Curl_safefree(data->state.ulbuf);
-
-  /* if the transfer was completed in a paused state there can be buffered
-     data left to free */
-  for(i = 0; i < data->state.tempcount; i++) {
-    Curl_dyn_free(&data->state.tempwrite[i].b);
-  }
-  data->state.tempcount = 0;
+  if(!result)
+    result = Curl_req_done(&data->req, data, premature);
 
   CONNCACHE_LOCK(data);
   Curl_detach_connection(data);
@@ -812,7 +805,6 @@ static CURLcode multi_done(struct Curl_easy *data,
       data->state.lastconnect_id = -1;
   }
 
-  Curl_safefree(data->state.buffer);
   return result;
 }
 
@@ -1015,80 +1007,169 @@ void Curl_attach_connection(struct Curl_easy *data,
   DEBUGASSERT(!data->conn);
   DEBUGASSERT(conn);
   data->conn = conn;
-  Curl_llist_insert_next(&conn->easyq, conn->easyq.tail, data,
-                         &data->conn_queue);
+  Curl_llist_append(&conn->easyq, data, &data->conn_queue);
   if(conn->handler && conn->handler->attach)
     conn->handler->attach(data, conn);
   Curl_conn_ev_data_attach(conn, data);
 }
 
-static int domore_getsock(struct Curl_easy *data,
-                          struct connectdata *conn,
-                          curl_socket_t *socks)
+static int connecting_getsock(struct Curl_easy *data, curl_socket_t *socks)
 {
+  struct connectdata *conn = data->conn;
+  (void)socks;
+  /* Not using `conn->sockfd` as `Curl_xfer_setup()` initializes
+   * that *after* the connect. */
+  if(conn && conn->sock[FIRSTSOCKET] != CURL_SOCKET_BAD) {
+    /* Default is to wait to something from the server */
+    socks[0] = conn->sock[FIRSTSOCKET];
+    return GETSOCK_READSOCK(0);
+  }
+  return GETSOCK_BLANK;
+}
+
+static int protocol_getsock(struct Curl_easy *data, curl_socket_t *socks)
+{
+  struct connectdata *conn = data->conn;
+  if(conn && conn->handler->proto_getsock)
+    return conn->handler->proto_getsock(data, conn, socks);
+  else if(conn && conn->sockfd != CURL_SOCKET_BAD) {
+    /* Default is to wait to something from the server */
+    socks[0] = conn->sockfd;
+    return GETSOCK_READSOCK(0);
+  }
+  return GETSOCK_BLANK;
+}
+
+static int domore_getsock(struct Curl_easy *data, curl_socket_t *socks)
+{
+  struct connectdata *conn = data->conn;
   if(conn && conn->handler->domore_getsock)
     return conn->handler->domore_getsock(data, conn, socks);
+  else if(conn && conn->sockfd != CURL_SOCKET_BAD) {
+    /* Default is that we want to send something to the server */
+    socks[0] = conn->sockfd;
+    return GETSOCK_WRITESOCK(0);
+  }
   return GETSOCK_BLANK;
 }
 
-static int doing_getsock(struct Curl_easy *data,
-                         struct connectdata *conn,
-                         curl_socket_t *socks)
+static int doing_getsock(struct Curl_easy *data, curl_socket_t *socks)
 {
+  struct connectdata *conn = data->conn;
   if(conn && conn->handler->doing_getsock)
     return conn->handler->doing_getsock(data, conn, socks);
+  else if(conn && conn->sockfd != CURL_SOCKET_BAD) {
+    /* Default is that we want to send something to the server */
+    socks[0] = conn->sockfd;
+    return GETSOCK_WRITESOCK(0);
+  }
   return GETSOCK_BLANK;
 }
 
-static int protocol_getsock(struct Curl_easy *data,
-                            struct connectdata *conn,
-                            curl_socket_t *socks)
+static int perform_getsock(struct Curl_easy *data, curl_socket_t *sock)
 {
-  if(conn->handler->proto_getsock)
-    return conn->handler->proto_getsock(data, conn, socks);
-  return Curl_conn_get_select_socks(data, FIRSTSOCKET, socks);
+  struct connectdata *conn = data->conn;
+
+  if(!conn)
+    return GETSOCK_BLANK;
+  else if(conn->handler->perform_getsock)
+    return conn->handler->perform_getsock(data, conn, sock);
+  else {
+    /* Default is to obey the data->req.keepon flags for send/recv */
+    int bitmap = GETSOCK_BLANK;
+    unsigned sockindex = 0;
+    if(CURL_WANT_RECV(data)) {
+      DEBUGASSERT(conn->sockfd != CURL_SOCKET_BAD);
+      bitmap |= GETSOCK_READSOCK(sockindex);
+      sock[sockindex] = conn->sockfd;
+    }
+
+    if(CURL_WANT_SEND(data)) {
+      if((conn->sockfd != conn->writesockfd) ||
+         bitmap == GETSOCK_BLANK) {
+        /* only if they are not the same socket and we have a readable
+           one, we increase index */
+        if(bitmap != GETSOCK_BLANK)
+          sockindex++; /* increase index if we need two entries */
+
+        DEBUGASSERT(conn->writesockfd != CURL_SOCKET_BAD);
+        sock[sockindex] = conn->writesockfd;
+      }
+      bitmap |= GETSOCK_WRITESOCK(sockindex);
+    }
+    return bitmap;
+  }
 }
 
-/* returns bitmapped flags for this handle and its sockets. The 'socks[]'
-   array contains MAX_SOCKSPEREASYHANDLE entries. */
-static int multi_getsock(struct Curl_easy *data,
-                         curl_socket_t *socks)
+/* Initializes `poll_set` with the current socket poll actions needed
+ * for transfer `data`. */
+static void multi_getsock(struct Curl_easy *data,
+                          struct easy_pollset *ps)
 {
-  struct connectdata *conn = data->conn;
   /* The no connection case can happen when this is called from
      curl_multi_remove_handle() => singlesocket() => multi_getsock().
   */
-  if(!conn)
-    return 0;
+  Curl_pollset_reset(data, ps);
+  if(!data->conn)
+    return;
 
   switch(data->mstate) {
-  default:
-    return 0;
+  case MSTATE_INIT:
+  case MSTATE_PENDING:
+  case MSTATE_SETUP:
+  case MSTATE_CONNECT:
+    /* nothing to poll for yet */
+    break;
 
   case MSTATE_RESOLVING:
-    return Curl_resolv_getsock(data, socks);
+    Curl_pollset_add_socks(data, ps, Curl_resolv_getsock);
+    /* connection filters are not involved in this phase */
+    break;
+
+  case MSTATE_CONNECTING:
+  case MSTATE_TUNNELING:
+    Curl_pollset_add_socks(data, ps, connecting_getsock);
+    Curl_conn_adjust_pollset(data, ps);
+    break;
 
-  case MSTATE_PROTOCONNECTING:
   case MSTATE_PROTOCONNECT:
-    return protocol_getsock(data, conn, socks);
+  case MSTATE_PROTOCONNECTING:
+    Curl_pollset_add_socks(data, ps, protocol_getsock);
+    Curl_conn_adjust_pollset(data, ps);
+    break;
 
   case MSTATE_DO:
   case MSTATE_DOING:
-    return doing_getsock(data, conn, socks);
-
-  case MSTATE_TUNNELING:
-  case MSTATE_CONNECTING:
-    return Curl_conn_get_select_socks(data, FIRSTSOCKET, socks);
+    Curl_pollset_add_socks(data, ps, doing_getsock);
+    Curl_conn_adjust_pollset(data, ps);
+    break;
 
   case MSTATE_DOING_MORE:
-    return domore_getsock(data, conn, socks);
+    Curl_pollset_add_socks(data, ps, domore_getsock);
+    Curl_conn_adjust_pollset(data, ps);
+    break;
 
-  case MSTATE_DID: /* since is set after DO is completed, we switch to
-                        waiting for the same as the PERFORMING state */
+  case MSTATE_DID: /* same as PERFORMING in regard to polling */
   case MSTATE_PERFORMING:
-    return Curl_single_getsock(data, conn, socks);
-  }
+    Curl_pollset_add_socks(data, ps, perform_getsock);
+    Curl_conn_adjust_pollset(data, ps);
+    break;
+
+  case MSTATE_RATELIMITING:
+    /* we need to let time pass, ignore socket(s) */
+    break;
+
+  case MSTATE_DONE:
+  case MSTATE_COMPLETED:
+  case MSTATE_MSGSENT:
+    /* nothing more to poll for */
+    break;
 
+  default:
+    failf(data, "multi_getsock: unexpected multi state %d", data->mstate);
+    DEBUGASSERT(0);
+    break;
+  }
 }
 
 CURLMcode curl_multi_fdset(struct Curl_multi *multi,
@@ -1100,8 +1181,8 @@ CURLMcode curl_multi_fdset(struct Curl_multi *multi,
      and then we must make sure that is done. */
   struct Curl_easy *data;
   int this_max_fd = -1;
-  curl_socket_t sockbunch[MAX_SOCKSPEREASYHANDLE];
-  int i;
+  struct easy_pollset ps;
+  unsigned int i;
   (void)exc_fd_set; /* not used */
 
   if(!GOOD_MULTI_HANDLE(multi))
@@ -1110,29 +1191,20 @@ CURLMcode curl_multi_fdset(struct Curl_multi *multi,
   if(multi->in_callback)
     return CURLM_RECURSIVE_API_CALL;
 
+  memset(&ps, 0, sizeof(ps));
   for(data = multi->easyp; data; data = data->next) {
-    int bitmap;
-#ifdef __clang_analyzer_
-    /* to prevent "The left operand of '>=' is a garbage value" warnings */
-    memset(sockbunch, 0, sizeof(sockbunch));
-#endif
-    bitmap = multi_getsock(data, sockbunch);
-
-    for(i = 0; i< MAX_SOCKSPEREASYHANDLE; i++) {
-      if((bitmap & GETSOCK_MASK_RW(i)) && VALID_SOCK((sockbunch[i]))) {
-        if(!FDSET_SOCK(sockbunch[i]))
-          /* pretend it doesn't exist */
-          continue;
-        if(bitmap & GETSOCK_READSOCK(i))
-          FD_SET(sockbunch[i], read_fd_set);
-        if(bitmap & GETSOCK_WRITESOCK(i))
-          FD_SET(sockbunch[i], write_fd_set);
-        if((int)sockbunch[i] > this_max_fd)
-          this_max_fd = (int)sockbunch[i];
-      }
-      else {
-        break;
-      }
+    multi_getsock(data, &ps);
+
+    for(i = 0; i < ps.num; i++) {
+      if(!FDSET_SOCK(ps.sockets[i]))
+        /* pretend it doesn't exist */
+        continue;
+      if(ps.actions[i] & CURL_POLL_IN)
+        FD_SET(ps.sockets[i], read_fd_set);
+      if(ps.actions[i] & CURL_POLL_OUT)
+        FD_SET(ps.sockets[i], write_fd_set);
+      if((int)ps.sockets[i] > this_max_fd)
+        this_max_fd = (int)ps.sockets[i];
     }
   }
 
@@ -1141,6 +1213,68 @@ CURLMcode curl_multi_fdset(struct Curl_multi *multi,
   return CURLM_OK;
 }
 
+CURLMcode curl_multi_waitfds(struct Curl_multi *multi,
+                             struct curl_waitfd *ufds,
+                             unsigned int size,
+                             unsigned int *fd_count)
+{
+  struct Curl_easy *data;
+  unsigned int nfds = 0;
+  struct easy_pollset ps;
+  unsigned int i;
+  CURLMcode result = CURLM_OK;
+  struct curl_waitfd *ufd;
+  unsigned int j;
+
+  if(!ufds)
+    return CURLM_BAD_FUNCTION_ARGUMENT;
+
+  if(!GOOD_MULTI_HANDLE(multi))
+    return CURLM_BAD_HANDLE;
+
+  if(multi->in_callback)
+    return CURLM_RECURSIVE_API_CALL;
+
+  memset(&ps, 0, sizeof(ps));
+  for(data = multi->easyp; data; data = data->next) {
+    multi_getsock(data, &ps);
+
+    for(i = 0; i < ps.num; i++) {
+      if(nfds < size) {
+        curl_socket_t fd = ps.sockets[i];
+        int fd_idx = -1;
+
+        /* Simple linear search to skip an already added descriptor */
+        for(j = 0; j < nfds; j++) {
+          if(ufds[j].fd == fd) {
+            fd_idx = (int)j;
+            break;
+          }
+        }
+
+        if(fd_idx < 0) {
+          ufd = &ufds[nfds++];
+          ufd->fd = ps.sockets[i];
+          ufd->events = 0;
+        }
+        else
+          ufd = &ufds[fd_idx];
+
+        if(ps.actions[i] & CURL_POLL_IN)
+          ufd->events |= CURL_WAIT_POLLIN;
+        if(ps.actions[i] & CURL_POLL_OUT)
+          ufd->events |= CURL_WAIT_POLLOUT;
+      }
+      else
+        return CURLM_OUT_OF_MEMORY;
+    }
+  }
+
+  if(fd_count)
+    *fd_count = nfds;
+  return result;
+}
+
 #ifdef USE_WINSOCK
 /* Reset FD_WRITE for TCP sockets. Nothing is actually sent. UDP sockets can't
  * be reset this way because an empty datagram would be sent. #9203
@@ -1157,6 +1291,29 @@ static void reset_socket_fdwrite(curl_socket_t s)
 }
 #endif
 
+static CURLMcode ufds_increase(struct pollfd **pfds, unsigned int *pfds_len,
+                               unsigned int inc, bool *is_malloced)
+{
+  struct pollfd *new_fds, *old_fds = *pfds;
+  unsigned int new_len = *pfds_len + inc;
+
+  new_fds = calloc(new_len, sizeof(struct pollfd));
+  if(!new_fds) {
+    if(*is_malloced)
+      free(old_fds);
+    *pfds = NULL;
+    *pfds_len = 0;
+    return CURLM_OUT_OF_MEMORY;
+  }
+  memcpy(new_fds, old_fds, (*pfds_len) * sizeof(struct pollfd));
+  if(*is_malloced)
+    free(old_fds);
+  *pfds = new_fds;
+  *pfds_len = new_len;
+  *is_malloced = TRUE;
+  return CURLM_OK;
+}
+
 #define NUM_POLLS_ON_STACK 10
 
 static CURLMcode multi_wait(struct Curl_multi *multi,
@@ -1168,15 +1325,14 @@ static CURLMcode multi_wait(struct Curl_multi *multi,
                             bool use_wakeup)
 {
   struct Curl_easy *data;
-  curl_socket_t sockbunch[MAX_SOCKSPEREASYHANDLE];
-  int bitmap;
-  unsigned int i;
-  unsigned int nfds = 0;
-  unsigned int curlfds;
+  struct easy_pollset ps;
+  size_t i;
   long timeout_internal;
   int retcode = 0;
   struct pollfd a_few_on_stack[NUM_POLLS_ON_STACK];
   struct pollfd *ufds = &a_few_on_stack[0];
+  unsigned int ufds_len = NUM_POLLS_ON_STACK;
+  unsigned int nfds = 0, curl_nfds = 0; /* how many ufds are in use */
   bool ufds_malloc = FALSE;
 #ifdef USE_WINSOCK
   WSANETWORKEVENTS wsa_events;
@@ -1195,20 +1351,6 @@ static CURLMcode multi_wait(struct Curl_multi *multi,
   if(timeout_ms < 0)
     return CURLM_BAD_FUNCTION_ARGUMENT;
 
-  /* Count up how many fds we have from the multi handle */
-  for(data = multi->easyp; data; data = data->next) {
-    bitmap = multi_getsock(data, sockbunch);
-
-    for(i = 0; i < MAX_SOCKSPEREASYHANDLE; i++) {
-      if((bitmap & GETSOCK_MASK_RW(i)) && VALID_SOCK((sockbunch[i]))) {
-        ++nfds;
-      }
-      else {
-        break;
-      }
-    }
-  }
-
   /* If the internally desired timeout is actually shorter than requested from
      the outside, then use the shorter time! But only if the internal timer
      is actually larger than -1! */
@@ -1216,75 +1358,60 @@ static CURLMcode multi_wait(struct Curl_multi *multi,
   if((timeout_internal >= 0) && (timeout_internal < (long)timeout_ms))
     timeout_ms = (int)timeout_internal;
 
-  curlfds = nfds; /* number of internal file descriptors */
-  nfds += extra_nfds; /* add the externally provided ones */
+  memset(ufds, 0, ufds_len * sizeof(struct pollfd));
+  memset(&ps, 0, sizeof(ps));
 
-#ifdef ENABLE_WAKEUP
-#ifdef USE_WINSOCK
-  if(use_wakeup) {
-#else
-  if(use_wakeup && multi->wakeup_pair[0] != CURL_SOCKET_BAD) {
-#endif
-    ++nfds;
-  }
-#endif
+  /* Add the curl handles to our pollfds first */
+  for(data = multi->easyp; data; data = data->next) {
+    multi_getsock(data, &ps);
 
-  if(nfds > NUM_POLLS_ON_STACK) {
-    /* 'nfds' is a 32 bit value and 'struct pollfd' is typically 8 bytes
-       big, so at 2^29 sockets this value might wrap. When a process gets
-       the capability to actually handle over 500 million sockets this
-       calculation needs a integer overflow check. */
-    ufds = malloc(nfds * sizeof(struct pollfd));
-    if(!ufds)
-      return CURLM_OUT_OF_MEMORY;
-    ufds_malloc = TRUE;
-  }
-  nfds = 0;
-
-  /* only do the second loop if we found descriptors in the first stage run
-     above */
-
-  if(curlfds) {
-    /* Add the curl handles to our pollfds first */
-    for(data = multi->easyp; data; data = data->next) {
-      bitmap = multi_getsock(data, sockbunch);
-
-      for(i = 0; i < MAX_SOCKSPEREASYHANDLE; i++) {
-        if((bitmap & GETSOCK_MASK_RW(i)) && VALID_SOCK((sockbunch[i]))) {
-          struct pollfd *ufd = &ufds[nfds++];
+    for(i = 0; i < ps.num; i++) {
+      short events = 0;
 #ifdef USE_WINSOCK
-          long mask = 0;
+      long mask = 0;
 #endif
-          ufd->fd = sockbunch[i];
-          ufd->events = 0;
-          if(bitmap & GETSOCK_READSOCK(i)) {
+      if(ps.actions[i] & CURL_POLL_IN) {
 #ifdef USE_WINSOCK
-            mask |= FD_READ|FD_ACCEPT|FD_CLOSE;
+        mask |= FD_READ|FD_ACCEPT|FD_CLOSE;
 #endif
-            ufd->events |= POLLIN;
-          }
-          if(bitmap & GETSOCK_WRITESOCK(i)) {
-#ifdef USE_WINSOCK
-            mask |= FD_WRITE|FD_CONNECT|FD_CLOSE;
-            reset_socket_fdwrite(sockbunch[i]);
-#endif
-            ufd->events |= POLLOUT;
-          }
+        events |= POLLIN;
+      }
+      if(ps.actions[i] & CURL_POLL_OUT) {
 #ifdef USE_WINSOCK
-          if(WSAEventSelect(sockbunch[i], multi->wsa_event, mask) != 0) {
-            if(ufds_malloc)
-              free(ufds);
-            return CURLM_INTERNAL_ERROR;
-          }
+        mask |= FD_WRITE|FD_CONNECT|FD_CLOSE;
+        reset_socket_fdwrite(ps.sockets[i]);
 #endif
+        events |= POLLOUT;
+      }
+      if(events) {
+        if(nfds && ps.sockets[i] == ufds[nfds-1].fd) {
+          ufds[nfds-1].events |= events;
         }
         else {
-          break;
+          if(nfds >= ufds_len) {
+            if(ufds_increase(&ufds, &ufds_len, 100, &ufds_malloc))
+              return CURLM_OUT_OF_MEMORY;
+          }
+          DEBUGASSERT(nfds < ufds_len);
+          ufds[nfds].fd = ps.sockets[i];
+          ufds[nfds].events = events;
+          ++nfds;
         }
       }
+#ifdef USE_WINSOCK
+      if(mask) {
+        if(WSAEventSelect(ps.sockets[i], multi->wsa_event, mask) != 0) {
+          if(ufds_malloc)
+            free(ufds);
+          return CURLM_INTERNAL_ERROR;
+        }
+      }
+#endif
     }
   }
 
+  curl_nfds = nfds; /* what curl internally used in ufds */
+
   /* Add external file descriptions from poll-like struct curl_waitfd */
   for(i = 0; i < extra_nfds; i++) {
 #ifdef USE_WINSOCK
@@ -1303,6 +1430,11 @@ static CURLMcode multi_wait(struct Curl_multi *multi,
       return CURLM_INTERNAL_ERROR;
     }
 #endif
+    if(nfds >= ufds_len) {
+      if(ufds_increase(&ufds, &ufds_len, 100, &ufds_malloc))
+        return CURLM_OUT_OF_MEMORY;
+    }
+    DEBUGASSERT(nfds < ufds_len);
     ufds[nfds].fd = extra_fds[i].fd;
     ufds[nfds].events = 0;
     if(extra_fds[i].events & CURL_WAIT_POLLIN)
@@ -1317,6 +1449,11 @@ static CURLMcode multi_wait(struct Curl_multi *multi,
 #ifdef ENABLE_WAKEUP
 #ifndef USE_WINSOCK
   if(use_wakeup && multi->wakeup_pair[0] != CURL_SOCKET_BAD) {
+    if(nfds >= ufds_len) {
+      if(ufds_increase(&ufds, &ufds_len, 100, &ufds_malloc))
+        return CURLM_OUT_OF_MEMORY;
+    }
+    DEBUGASSERT(nfds < ufds_len);
     ufds[nfds].fd = multi->wakeup_pair[0];
     ufds[nfds].events = POLLIN;
     ++nfds;
@@ -1356,7 +1493,7 @@ static CURLMcode multi_wait(struct Curl_multi *multi,
          struct, the bit values of the actual underlying poll() implementation
          may not be the same as the ones in the public libcurl API! */
       for(i = 0; i < extra_nfds; i++) {
-        unsigned r = ufds[curlfds + i].revents;
+        unsigned r = ufds[curl_nfds + i].revents;
         unsigned short mask = 0;
 #ifdef USE_WINSOCK
         curl_socket_t s = extra_fds[i].fd;
@@ -1389,24 +1526,19 @@ static CURLMcode multi_wait(struct Curl_multi *multi,
 #ifdef USE_WINSOCK
       /* Count up all our own sockets that had activity,
          and remove them from the event. */
-      if(curlfds) {
+      if(curl_nfds) {
 
         for(data = multi->easyp; data; data = data->next) {
-          bitmap = multi_getsock(data, sockbunch);
-
-          for(i = 0; i < MAX_SOCKSPEREASYHANDLE; i++) {
-            if(bitmap & (GETSOCK_READSOCK(i) | GETSOCK_WRITESOCK(i))) {
-              wsa_events.lNetworkEvents = 0;
-              if(WSAEnumNetworkEvents(sockbunch[i], NULL, &wsa_events) == 0) {
-                if(ret && !pollrc && wsa_events.lNetworkEvents)
-                  retcode++;
-              }
-              WSAEventSelect(sockbunch[i], multi->wsa_event, 0);
-            }
-            else {
-              /* break on entry not checked for being readable or writable */
-              break;
+          multi_getsock(data, &ps);
+
+          for(i = 0; i < ps.num; i++) {
+            wsa_events.lNetworkEvents = 0;
+            if(WSAEnumNetworkEvents(ps.sockets[i], NULL,
+                                    &wsa_events) == 0) {
+              if(ret && !pollrc && wsa_events.lNetworkEvents)
+                retcode++;
             }
+            WSAEventSelect(ps.sockets[i], multi->wsa_event, 0);
           }
         }
       }
@@ -1415,7 +1547,7 @@ static CURLMcode multi_wait(struct Curl_multi *multi,
 #else
 #ifdef ENABLE_WAKEUP
       if(use_wakeup && multi->wakeup_pair[0] != CURL_SOCKET_BAD) {
-        if(ufds[curlfds + extra_nfds].revents & POLLIN) {
+        if(ufds[curl_nfds + extra_nfds].revents & POLLIN) {
           char buf[64];
           ssize_t nread;
           while(1) {
@@ -1635,47 +1767,47 @@ static bool multi_handle_timeout(struct Curl_easy *data,
                                  CURLcode *result,
                                  bool connect_timeout)
 {
-  timediff_t timeout_ms;
-  timeout_ms = Curl_timeleft(data, now, connect_timeout);
-
+  timediff_t timeout_ms = Curl_timeleft(data, now, connect_timeout);
   if(timeout_ms < 0) {
     /* Handle timed out */
+    struct curltime since;
+    if(connect_timeout)
+      since = data->progress.t_startsingle;
+    else
+      since = data->progress.t_startop;
     if(data->mstate == MSTATE_RESOLVING)
       failf(data, "Resolving timed out after %" CURL_FORMAT_TIMEDIFF_T
-            " milliseconds",
-            Curl_timediff(*now, data->progress.t_startsingle));
+            " milliseconds", Curl_timediff(*now, since));
     else if(data->mstate == MSTATE_CONNECTING)
       failf(data, "Connection timed out after %" CURL_FORMAT_TIMEDIFF_T
-            " milliseconds",
-            Curl_timediff(*now, data->progress.t_startsingle));
+            " milliseconds", Curl_timediff(*now, since));
     else {
       struct SingleRequest *k = &data->req;
       if(k->size != -1) {
         failf(data, "Operation timed out after %" CURL_FORMAT_TIMEDIFF_T
               " milliseconds with %" CURL_FORMAT_CURL_OFF_T " out of %"
               CURL_FORMAT_CURL_OFF_T " bytes received",
-              Curl_timediff(*now, data->progress.t_startsingle),
-              k->bytecount, k->size);
+              Curl_timediff(*now, since), k->bytecount, k->size);
       }
       else {
         failf(data, "Operation timed out after %" CURL_FORMAT_TIMEDIFF_T
               " milliseconds with %" CURL_FORMAT_CURL_OFF_T
-              " bytes received",
-              Curl_timediff(*now, data->progress.t_startsingle),
-              k->bytecount);
+              " bytes received", Curl_timediff(*now, since), k->bytecount);
       }
     }
-
-    /* Force connection closed if the connection has indeed been used */
-    if(data->mstate > MSTATE_DO) {
-      streamclose(data->conn, "Disconnected with pending data");
-      *stream_error = TRUE;
-    }
     *result = CURLE_OPERATION_TIMEDOUT;
-    (void)multi_done(data, *result, TRUE);
+    if(data->conn) {
+      /* Force connection closed if the connection has indeed been used */
+      if(data->mstate > MSTATE_DO) {
+        streamclose(data->conn, "Disconnect due to timeout");
+        *stream_error = TRUE;
+      }
+      (void)multi_done(data, *result, TRUE);
+    }
+    return TRUE;
   }
 
-  return (timeout_ms < 0);
+  return FALSE;
 }
 
 /*
@@ -1767,105 +1899,6 @@ static CURLcode protocol_connect(struct Curl_easy *data,
   return result; /* pass back status */
 }
 
-/*
- * readrewind() rewinds the read stream. This is typically used for HTTP
- * POST/PUT with multi-pass authentication when a sending was denied and a
- * resend is necessary.
- */
-static CURLcode readrewind(struct Curl_easy *data)
-{
-  curl_mimepart *mimepart = &data->set.mimepost;
-  DEBUGASSERT(data->conn);
-
-  data->state.rewindbeforesend = FALSE; /* we rewind now */
-
-  /* explicitly switch off sending data on this connection now since we are
-     about to restart a new transfer and thus we want to avoid inadvertently
-     sending more data on the existing connection until the next transfer
-     starts */
-  data->req.keepon &= ~KEEP_SEND;
-
-  /* We have sent away data. If not using CURLOPT_POSTFIELDS or
-     CURLOPT_HTTPPOST, call app to rewind
-  */
-#ifndef CURL_DISABLE_HTTP
-  if(data->conn->handler->protocol & PROTO_FAMILY_HTTP) {
-    if(data->state.mimepost)
-      mimepart = data->state.mimepost;
-  }
-#endif
-  if(data->set.postfields ||
-     (data->state.httpreq == HTTPREQ_GET) ||
-     (data->state.httpreq == HTTPREQ_HEAD))
-    ; /* no need to rewind */
-  else if(data->state.httpreq == HTTPREQ_POST_MIME ||
-          data->state.httpreq == HTTPREQ_POST_FORM) {
-    CURLcode result = Curl_mime_rewind(mimepart);
-    if(result) {
-      failf(data, "Cannot rewind mime/post data");
-      return result;
-    }
-  }
-  else {
-    if(data->set.seek_func) {
-      int err;
-
-      Curl_set_in_callback(data, true);
-      err = (data->set.seek_func)(data->set.seek_client, 0, SEEK_SET);
-      Curl_set_in_callback(data, false);
-      if(err) {
-        failf(data, "seek callback returned error %d", (int)err);
-        return CURLE_SEND_FAIL_REWIND;
-      }
-    }
-    else if(data->set.ioctl_func) {
-      curlioerr err;
-
-      Curl_set_in_callback(data, true);
-      err = (data->set.ioctl_func)(data, CURLIOCMD_RESTARTREAD,
-                                   data->set.ioctl_client);
-      Curl_set_in_callback(data, false);
-      infof(data, "the ioctl callback returned %d", (int)err);
-
-      if(err) {
-        failf(data, "ioctl callback returned error %d", (int)err);
-        return CURLE_SEND_FAIL_REWIND;
-      }
-    }
-    else {
-      /* If no CURLOPT_READFUNCTION is used, we know that we operate on a
-         given FILE * stream and we can actually attempt to rewind that
-         ourselves with fseek() */
-      if(data->state.fread_func == (curl_read_callback)fread) {
-        if(-1 != fseek(data->state.in, 0, SEEK_SET))
-          /* successful rewind */
-          return CURLE_OK;
-      }
-
-      /* no callback set or failure above, makes us fail at once */
-      failf(data, "necessary data rewind wasn't possible");
-      return CURLE_SEND_FAIL_REWIND;
-    }
-  }
-  return CURLE_OK;
-}
-
-/*
- * Curl_preconnect() is called immediately before a connect starts. When a
- * redirect is followed, this is then called multiple times during a single
- * transfer.
- */
-CURLcode Curl_preconnect(struct Curl_easy *data)
-{
-  if(!data->state.buffer) {
-    data->state.buffer = malloc(data->set.buffer_size + 1);
-    if(!data->state.buffer)
-      return CURLE_OUT_OF_MEMORY;
-  }
-
-  return CURLE_OK;
-}
-
 static void set_in_callback(struct Curl_multi *multi, bool value)
 {
   multi->in_callback = value;
@@ -1880,7 +1913,6 @@ static CURLMcode multi_runsingle(struct Curl_multi *multi,
   bool async;
   bool protocol_connected = FALSE;
   bool dophase_done = FALSE;
-  bool done = FALSE;
   CURLMcode rc;
   CURLcode result = CURLE_OK;
   timediff_t recv_timeout_ms;
@@ -1920,51 +1952,44 @@ static CURLMcode multi_runsingle(struct Curl_multi *multi,
         return CURLM_INTERNAL_ERROR;
     }
 
-    if(data->conn &&
-       (data->mstate >= MSTATE_CONNECT) &&
-       (data->mstate < MSTATE_COMPLETED)) {
-      /* Check for overall operation timeout here but defer handling the
-       * connection timeout to later, to allow for a connection to be set up
-       * in the window since we last checked timeout. This prevents us
-       * tearing down a completed connection in the case where we were slow
-       * to check the timeout (e.g. process descheduled during this loop).
-       * We set connect_timeout=FALSE to do this. */
-
-      /* we need to wait for the connect state as only then is the start time
-         stored, but we must not check already completed handles */
-      if(multi_handle_timeout(data, nowp, &stream_error, &result, FALSE)) {
-        /* Skip the statemachine and go directly to error handling section. */
-        goto statemachine_end;
-      }
-    }
+    /* Wait for the connect state as only then is the start time stored, but
+       we must not check already completed handles */
+    if((data->mstate >= MSTATE_CONNECT) && (data->mstate < MSTATE_COMPLETED) &&
+       multi_handle_timeout(data, nowp, &stream_error, &result, FALSE))
+      /* Skip the statemachine and go directly to error handling section. */
+      goto statemachine_end;
 
     switch(data->mstate) {
     case MSTATE_INIT:
-      /* init this transfer. */
+      /* Transitional state. init this transfer. A handle never comes
+         back to this state. */
       result = Curl_pretransfer(data);
-
-      if(!result) {
-        /* after init, go CONNECT */
-        multistate(data, MSTATE_CONNECT);
-        *nowp = Curl_pgrsTime(data, TIMER_STARTOP);
-        rc = CURLM_CALL_MULTI_PERFORM;
-      }
-      break;
-
-    case MSTATE_CONNECT:
-      /* Connect. We want to get a connection identifier filled in. */
-      /* init this transfer. */
-      result = Curl_preconnect(data);
       if(result)
         break;
 
+      /* after init, go SETUP */
+      multistate(data, MSTATE_SETUP);
+      (void)Curl_pgrsTime(data, TIMER_STARTOP);
+      FALLTHROUGH();
+
+    case MSTATE_SETUP:
+      /* Transitional state. Setup things for a new transfer. The handle
+         can come back to this state on a redirect. */
       *nowp = Curl_pgrsTime(data, TIMER_STARTSINGLE);
       if(data->set.timeout)
         Curl_expire(data, data->set.timeout, EXPIRE_TIMEOUT);
-
       if(data->set.connecttimeout)
+        /* Since a connection might go to pending and back to CONNECT several
+           times before it actually takes off, we need to set the timeout once
+           in SETUP before we enter CONNECT the first time. */
         Curl_expire(data, data->set.connecttimeout, EXPIRE_CONNECTTIMEOUT);
 
+      multistate(data, MSTATE_CONNECT);
+      FALLTHROUGH();
+
+    case MSTATE_CONNECT:
+      /* Connect. We want to get a connection identifier filled in. This state
+         can be entered from SETUP and from PENDING. */
       result = Curl_connect(data, &async, &connected);
       if(CURLE_NO_CONNECTION_AVAILABLE == result) {
         /* There was no connection available. We will go to the pending
@@ -1972,20 +1997,17 @@ static CURLMcode multi_runsingle(struct Curl_multi *multi,
         multistate(data, MSTATE_PENDING);
 
         /* add this handle to the list of connect-pending handles */
-        Curl_llist_insert_next(&multi->pending, multi->pending.tail, data,
-                               &data->connect_queue);
+        Curl_llist_append(&multi->pending, data, &data->connect_queue);
         /* unlink from the main list */
         unlink_easy(multi, data);
         result = CURLE_OK;
         break;
       }
-      else if(data->state.previouslypending) {
-        /* this transfer comes from the pending queue so try move another */
-        infof(data, "Transfer was pending, now try another");
+      else
         process_pending_handles(data->multi);
-      }
 
       if(!result) {
+        *nowp = Curl_pgrsTime(data, TIMER_POSTQUEUE);
         if(async)
           /* We're now waiting for an asynchronous name lookup */
           multistate(data, MSTATE_RESOLVING);
@@ -2023,7 +2045,7 @@ static CURLMcode multi_runsingle(struct Curl_multi *multi,
         hostname = conn->host.name;
 
       /* check if we have the name resolved by now */
-      dns = Curl_fetch_addr(data, hostname, (int)conn->port);
+      dns = Curl_fetch_addr(data, hostname, conn->primary.remote_port);
 
       if(dns) {
 #ifdef CURLRES_ASYNCH
@@ -2118,9 +2140,6 @@ static CURLMcode multi_runsingle(struct Curl_multi *multi,
       break;
 
     case MSTATE_PROTOCONNECT:
-      if(data->state.rewindbeforesend)
-        result = readrewind(data);
-
       if(!result && data->conn->bits.reuse) {
         /* ftp seems to hang when protoconnect on reused connection
          * since we handle PROTOCONNECT in general inside the filers, it
@@ -2131,9 +2150,11 @@ static CURLMcode multi_runsingle(struct Curl_multi *multi,
       }
       if(!result)
         result = protocol_connect(data, &protocol_connected);
-      if(!result && !protocol_connected)
+      if(!result && !protocol_connected) {
         /* switch to waiting state */
         multistate(data, MSTATE_PROTOCONNECTING);
+        rc = CURLM_CALL_MULTI_PERFORM;
+      }
       else if(!result) {
         /* protocol connect has completed, go WAITDO or DO */
         multistate(data, MSTATE_DO);
@@ -2170,10 +2191,10 @@ static CURLMcode multi_runsingle(struct Curl_multi *multi,
         /* call the prerequest callback function */
         Curl_set_in_callback(data, true);
         prereq_rc = data->set.fprereq(data->set.prereq_userp,
-                                      data->info.conn_primary_ip,
-                                      data->info.conn_local_ip,
-                                      data->info.conn_primary_port,
-                                      data->info.conn_local_port);
+                                      data->info.primary.remote_ip,
+                                      data->info.primary.local_ip,
+                                      data->info.primary.remote_port,
+                                      data->info.primary.local_port);
         Curl_set_in_callback(data, false);
         if(prereq_rc != CURL_PREREQFUNC_OK) {
           failf(data, "operation aborted by pre-request callback");
@@ -2220,6 +2241,7 @@ static CURLMcode multi_runsingle(struct Curl_multi *multi,
             /* DO was not completed in one function call, we must continue
                DOING... */
             multistate(data, MSTATE_DOING);
+            rc = CURLM_CALL_MULTI_PERFORM;
           }
 
           /* after DO, go DO_DONE... or DO_MORE */
@@ -2227,6 +2249,7 @@ static CURLMcode multi_runsingle(struct Curl_multi *multi,
             /* we're supposed to do more, but we need to sit down, relax
                and wait a little while first */
             multistate(data, MSTATE_DOING_MORE);
+            rc = CURLM_CALL_MULTI_PERFORM;
           }
           else {
             /* we're done with the DO, now DID */
@@ -2262,7 +2285,7 @@ static CURLMcode multi_runsingle(struct Curl_multi *multi,
               follow = FOLLOW_RETRY;
               drc = Curl_follow(data, newurl, follow);
               if(!drc) {
-                multistate(data, MSTATE_CONNECT);
+                multistate(data, MSTATE_SETUP);
                 rc = CURLM_CALL_MULTI_PERFORM;
                 result = CURLE_OK;
               }
@@ -2411,8 +2434,6 @@ static CURLMcode multi_runsingle(struct Curl_multi *multi,
     {
       char *newurl = NULL;
       bool retry = FALSE;
-      bool comeback = FALSE;
-      DEBUGASSERT(data->state.buffer);
       /* check if over send speed */
       send_timeout_ms = 0;
       if(data->set.max_send_speed)
@@ -2442,9 +2463,9 @@ static CURLMcode multi_runsingle(struct Curl_multi *multi,
       }
 
       /* read/write data if it is ready to do so */
-      result = Curl_readwrite(data->conn, data, &done, &comeback);
+      result = Curl_readwrite(data);
 
-      if(done || (result == CURLE_RECV_ERROR)) {
+      if(data->req.done || (result == CURLE_RECV_ERROR)) {
         /* If CURLE_RECV_ERROR happens early enough, we assume it was a race
          * condition and the server closed the reused connection exactly when
          * we wanted to use it, so figure out if that is indeed the case.
@@ -2459,7 +2480,7 @@ static CURLMcode multi_runsingle(struct Curl_multi *multi,
           /* if we are to retry, set the result to OK and consider the
              request as done */
           result = CURLE_OK;
-          done = TRUE;
+          data->req.done = TRUE;
         }
       }
       else if((CURLE_HTTP2_STREAM == result) &&
@@ -2479,7 +2500,7 @@ static CURLMcode multi_runsingle(struct Curl_multi *multi,
              as done */
           retry = TRUE;
           result = CURLE_OK;
-          done = TRUE;
+          data->req.done = TRUE;
         }
         else
           result = ret;
@@ -2501,7 +2522,7 @@ static CURLMcode multi_runsingle(struct Curl_multi *multi,
         Curl_posttransfer(data);
         multi_done(data, result, TRUE);
       }
-      else if(done) {
+      else if(data->req.done && !Curl_cwriter_is_paused(data)) {
 
         /* call this even if the readwrite function returned error */
         Curl_posttransfer(data);
@@ -2524,10 +2545,9 @@ static CURLMcode multi_runsingle(struct Curl_multi *multi,
           /* multi_done() might return CURLE_GOT_NOTHING */
           result = Curl_follow(data, newurl, follow);
           if(!result) {
-            multistate(data, MSTATE_CONNECT);
+            multistate(data, MSTATE_SETUP);
             rc = CURLM_CALL_MULTI_PERFORM;
           }
-          free(newurl);
         }
         else {
           /* after the transfer is done, go DONE */
@@ -2539,7 +2559,6 @@ static CURLMcode multi_runsingle(struct Curl_multi *multi,
             newurl = data->req.location;
             data->req.location = NULL;
             result = Curl_follow(data, newurl, FOLLOW_FAKE);
-            free(newurl);
             if(result) {
               stream_error = TRUE;
               result = multi_done(data, result, TRUE);
@@ -2552,12 +2571,13 @@ static CURLMcode multi_runsingle(struct Curl_multi *multi,
           }
         }
       }
-      else if(comeback) {
+      else if(data->state.select_bits) {
         /* This avoids CURLM_CALL_MULTI_PERFORM so that a very fast transfer
            won't get stuck on this transfer at the expense of other concurrent
            transfers */
         Curl_expire(data, 0, EXPIRE_RUN_NOW);
       }
+      free(newurl);
       break;
     }
 
@@ -2608,8 +2628,7 @@ static CURLMcode multi_runsingle(struct Curl_multi *multi,
       return CURLM_INTERNAL_ERROR;
     }
 
-    if(data->conn &&
-       data->mstate >= MSTATE_CONNECT &&
+    if(data->mstate >= MSTATE_CONNECT &&
        data->mstate < MSTATE_DO &&
        rc != CURLM_CALL_MULTI_PERFORM &&
        !multi_ischanged(multi, false)) {
@@ -2619,7 +2638,7 @@ static CURLMcode multi_runsingle(struct Curl_multi *multi,
        * (i.e. CURLM_CALL_MULTI_PERFORM == TRUE) then we should do that before
        * declaring the connection timed out as we may almost have a completed
        * connection. */
-      multi_handle_timeout(data, nowp, &stream_error, &result, TRUE);
+      multi_handle_timeout(data, nowp, &stream_error, &result, FALSE);
     }
 
 statemachine_end:
@@ -2696,8 +2715,7 @@ static CURLMcode multi_runsingle(struct Curl_multi *multi,
       multistate(data, MSTATE_MSGSENT);
 
       /* add this handle to the list of msgsent handles */
-      Curl_llist_insert_next(&multi->msgsent, multi->msgsent.tail, data,
-                             &data->connect_queue);
+      Curl_llist_append(&multi->msgsent, data, &data->connect_queue);
       /* unlink from the main list */
       unlink_easy(multi, data);
       return CURLM_OK;
@@ -2759,10 +2777,20 @@ CURLMcode curl_multi_perform(struct Curl_multi *multi, int *running_handles)
    */
   do {
     multi->timetree = Curl_splaygetbest(now, multi->timetree, &t);
-    if(t)
+    if(t) {
       /* the removed may have another timeout in queue */
+      data = t->payload;
+      if(data->mstate == MSTATE_PENDING) {
+        bool stream_unused;
+        CURLcode result_unused;
+        if(multi_handle_timeout(data, &now, &stream_unused, &result_unused,
+                                FALSE)) {
+          infof(data, "PENDING handle timeout");
+          move_pending_to_connect(multi, data);
+        }
+      }
       (void)add_next_timeout(now, multi, t->payload);
-
+    }
   } while(t);
 
   *running_handles = multi->num_alive;
@@ -2845,6 +2873,7 @@ CURLMcode curl_multi_cleanup(struct Curl_multi *multi)
     Curl_free_multi_ssl_backend_data(multi->ssl_backend_data);
 #endif
 
+    multi_xfer_bufs_free(multi);
     free(multi);
 
     return CURLM_OK;
@@ -2897,53 +2926,36 @@ CURLMsg *curl_multi_info_read(struct Curl_multi *multi, int *msgs_in_queue)
 static CURLMcode singlesocket(struct Curl_multi *multi,
                               struct Curl_easy *data)
 {
-  curl_socket_t socks[MAX_SOCKSPEREASYHANDLE];
-  int i;
+  struct easy_pollset cur_poll;
+  unsigned int i;
   struct Curl_sh_entry *entry;
   curl_socket_t s;
-  int num;
-  unsigned int curraction;
-  unsigned char actions[MAX_SOCKSPEREASYHANDLE];
   int rc;
 
-  for(i = 0; i< MAX_SOCKSPEREASYHANDLE; i++)
-    socks[i] = CURL_SOCKET_BAD;
-
   /* Fill in the 'current' struct with the state as it is now: what sockets to
      supervise and for what actions */
-  curraction = multi_getsock(data, socks);
+  multi_getsock(data, &cur_poll);
 
   /* We have 0 .. N sockets already and we get to know about the 0 .. M
      sockets we should have from now on. Detect the differences, remove no
      longer supervised ones and add new ones */
 
   /* walk over the sockets we got right now */
-  for(i = 0; (i< MAX_SOCKSPEREASYHANDLE) &&
-      (curraction & GETSOCK_MASK_RW(i));
-      i++) {
-    unsigned char action = CURL_POLL_NONE;
-    unsigned char prevaction = 0;
+  for(i = 0; i < cur_poll.num; i++) {
+    unsigned char cur_action = cur_poll.actions[i];
+    unsigned char last_action = 0;
     int comboaction;
-    bool sincebefore = FALSE;
 
-    s = socks[i];
+    s = cur_poll.sockets[i];
 
     /* get it from the hash */
     entry = sh_getentry(&multi->sockhash, s);
-
-    if(curraction & GETSOCK_READSOCK(i))
-      action |= CURL_POLL_IN;
-    if(curraction & GETSOCK_WRITESOCK(i))
-      action |= CURL_POLL_OUT;
-
-    actions[i] = action;
     if(entry) {
       /* check if new for this transfer */
-      int j;
-      for(j = 0; j< data->numsocks; j++) {
-        if(s == data->sockets[j]) {
-          prevaction = data->actions[j];
-          sincebefore = TRUE;
+      unsigned int j;
+      for(j = 0; j< data->last_poll.num; j++) {
+        if(s == data->last_poll.sockets[j]) {
+          last_action = data->last_poll.actions[j];
           break;
         }
       }
@@ -2955,23 +2967,23 @@ static CURLMcode singlesocket(struct Curl_multi *multi,
         /* fatal */
         return CURLM_OUT_OF_MEMORY;
     }
-    if(sincebefore && (prevaction != action)) {
+    if(last_action && (last_action != cur_action)) {
       /* Socket was used already, but different action now */
-      if(prevaction & CURL_POLL_IN)
+      if(last_action & CURL_POLL_IN)
         entry->readers--;
-      if(prevaction & CURL_POLL_OUT)
+      if(last_action & CURL_POLL_OUT)
         entry->writers--;
-      if(action & CURL_POLL_IN)
+      if(cur_action & CURL_POLL_IN)
         entry->readers++;
-      if(action & CURL_POLL_OUT)
+      if(cur_action & CURL_POLL_OUT)
         entry->writers++;
     }
-    else if(!sincebefore) {
-      /* a new user */
+    else if(!last_action) {
+      /* a new transfer using this socket */
       entry->users++;
-      if(action & CURL_POLL_IN)
+      if(cur_action & CURL_POLL_IN)
         entry->readers++;
-      if(action & CURL_POLL_OUT)
+      if(cur_action & CURL_POLL_OUT)
         entry->writers++;
 
       /* add 'data' to the transfer hash on this socket! */
@@ -2982,11 +2994,11 @@ static CURLMcode singlesocket(struct Curl_multi *multi,
       }
     }
 
-    comboaction = (entry->writers? CURL_POLL_OUT : 0) |
+    comboaction = (entry->writers ? CURL_POLL_OUT : 0) |
                    (entry->readers ? CURL_POLL_IN : 0);
 
     /* socket existed before and has the same action set as before */
-    if(sincebefore && ((int)entry->action == comboaction))
+    if(last_action && ((int)entry->action == comboaction))
       /* same, continue */
       continue;
 
@@ -2994,6 +3006,7 @@ static CURLMcode singlesocket(struct Curl_multi *multi,
       set_in_callback(multi, TRUE);
       rc = multi->socket_cb(data, s, comboaction, multi->socket_userp,
                             entry->socketp);
+
       set_in_callback(multi, FALSE);
       if(rc == -1) {
         multi->dead = TRUE;
@@ -3004,16 +3017,15 @@ static CURLMcode singlesocket(struct Curl_multi *multi,
     entry->action = comboaction; /* store the current action state */
   }
 
-  num = i; /* number of sockets */
-
-  /* when we've walked over all the sockets we should have right now, we must
-     make sure to detect sockets that are removed */
-  for(i = 0; i< data->numsocks; i++) {
-    int j;
+  /* Check for last_poll.sockets that no longer appear in cur_poll.sockets.
+   * Need to remove the easy handle from the multi->sockhash->transfers and
+   * remove multi->sockhash entry when this was the last transfer */
+  for(i = 0; i< data->last_poll.num; i++) {
+    unsigned int j;
     bool stillused = FALSE;
-    s = data->sockets[i];
-    for(j = 0; j < num; j++) {
-      if(s == socks[j]) {
+    s = data->last_poll.sockets[i];
+    for(j = 0; j < cur_poll.num; j++) {
+      if(s == cur_poll.sockets[j]) {
         /* this is still supervised */
         stillused = TRUE;
         break;
@@ -3026,7 +3038,7 @@ static CURLMcode singlesocket(struct Curl_multi *multi,
     /* if this is NULL here, the socket has been closed and notified so
        already by Curl_multi_closed() */
     if(entry) {
-      unsigned char oldactions = data->actions[i];
+      unsigned char oldactions = data->last_poll.actions[i];
       /* this socket has been removed. Decrease user count */
       entry->users--;
       if(oldactions & CURL_POLL_OUT)
@@ -3054,11 +3066,10 @@ static CURLMcode singlesocket(struct Curl_multi *multi,
         }
       }
     }
-  } /* for loop over numsocks */
+  } /* for loop over num */
 
-  memcpy(data->sockets, socks, num*sizeof(curl_socket_t));
-  memcpy(data->actions, actions, num*sizeof(char));
-  data->numsocks = num;
+  /* Remember for next time */
+  memcpy(&data->last_poll, &cur_poll, sizeof(data->last_poll));
   return CURLM_OK;
 }
 
@@ -3139,7 +3150,7 @@ static CURLMcode add_next_timeout(struct curltime now,
     struct Curl_llist_element *n = e->next;
     timediff_t diff;
     node = (struct time_node *)e->ptr;
-    diff = Curl_timediff(node->time, now);
+    diff = Curl_timediff_us(node->time, now);
     if(diff <= 0)
       /* remove outdated entry */
       Curl_llist_remove(list, e, NULL);
@@ -3222,7 +3233,7 @@ static CURLMcode multi_socket(struct Curl_multi *multi,
 
         if(data->conn && !(data->conn->handler->flags & PROTOPT_DIRLOCK))
           /* set socket event bitmask if they're not locked */
-          data->conn->cselect_bits = (unsigned char)ev_bitmask;
+          data->state.select_bits |= (unsigned char)ev_bitmask;
 
         Curl_expire(data, 0, EXPIRE_RUN_NOW);
       }
@@ -3298,6 +3309,7 @@ CURLMcode curl_multi_setopt(struct Curl_multi *multi,
 {
   CURLMcode res = CURLM_OK;
   va_list param;
+  unsigned long uarg;
 
   if(!GOOD_MULTI_HANDLE(multi))
     return CURLM_BAD_HANDLE;
@@ -3330,7 +3342,9 @@ CURLMcode curl_multi_setopt(struct Curl_multi *multi,
     multi->timer_userp = va_arg(param, void *);
     break;
   case CURLMOPT_MAXCONNECTS:
-    multi->maxconnects = va_arg(param, long);
+    uarg = va_arg(param, unsigned long);
+    if(uarg <= UINT_MAX)
+      multi->maxconnects = (unsigned int)uarg;
     break;
   case CURLMOPT_MAX_HOST_CONNECTIONS:
     multi->max_host_connections = va_arg(param, long);
@@ -3352,9 +3366,9 @@ CURLMcode curl_multi_setopt(struct Curl_multi *multi,
   case CURLMOPT_MAX_CONCURRENT_STREAMS:
     {
       long streams = va_arg(param, long);
-      if(streams < 1)
+      if((streams < 1) || (streams > INT_MAX))
         streams = 100;
-      multi->max_concurrent_streams = curlx_sltoui(streams);
+      multi->max_concurrent_streams = (unsigned int)streams;
     }
     break;
   default:
@@ -3422,20 +3436,10 @@ static CURLMcode multi_timeout(struct Curl_multi *multi,
 
     if(Curl_splaycomparekeys(multi->timetree->key, now) > 0) {
       /* some time left before expiration */
-      timediff_t diff = Curl_timediff(multi->timetree->key, now);
-      if(diff <= 0)
-        /*
-         * Since we only provide millisecond resolution on the returned value
-         * and the diff might be less than one millisecond here, we don't
-         * return zero as that may cause short bursts of busyloops on fast
-         * processors while the diff is still present but less than one
-         * millisecond! instead we return 1 until the time is ripe.
-         */
-        *timeout_ms = 1;
-      else
-        /* this should be safe even on 64 bit archs, as we don't use that
-           overly long timeouts */
-        *timeout_ms = (long)diff;
+      timediff_t diff = Curl_timediff_ceil(multi->timetree->key, now);
+      /* this should be safe even on 32 bit archs, as we don't use that
+         overly long timeouts */
+      *timeout_ms = (long)diff;
     }
     else
       /* 0 means immediately */
@@ -3740,84 +3744,194 @@ void Curl_multiuse_state(struct Curl_easy *data,
   process_pending_handles(data->multi);
 }
 
-/* process_pending_handles() moves all handles from PENDING
-   back into the main list and change state to CONNECT */
+static void move_pending_to_connect(struct Curl_multi *multi,
+                                    struct Curl_easy *data)
+{
+  DEBUGASSERT(data->mstate == MSTATE_PENDING);
+
+  /* put it back into the main list */
+  link_easy(multi, data);
+
+  multistate(data, MSTATE_CONNECT);
+
+  /* Remove this node from the pending list */
+  Curl_llist_remove(&multi->pending, &data->connect_queue, NULL);
+
+  /* Make sure that the handle will be processed soonish. */
+  Curl_expire(data, 0, EXPIRE_RUN_NOW);
+}
+
+/* process_pending_handles() moves a handle from PENDING back into the main
+   list and change state to CONNECT.
+
+   We do not move all transfers because that can be a significant amount.
+   Since this is tried every now and then doing too many too often becomes a
+   performance problem.
+
+   When there is a change for connection limits like max host connections etc,
+   this likely only allows one new transfer. When there is a pipewait change,
+   it can potentially allow hundreds of new transfers.
+
+   We could consider an improvement where we store the queue reason and allow
+   more pipewait rechecks than others.
+*/
 static void process_pending_handles(struct Curl_multi *multi)
 {
   struct Curl_llist_element *e = multi->pending.head;
   if(e) {
     struct Curl_easy *data = e->ptr;
+    move_pending_to_connect(multi, data);
+  }
+}
 
-    DEBUGASSERT(data->mstate == MSTATE_PENDING);
-
-    /* put it back into the main list */
-    link_easy(multi, data);
-
-    multistate(data, MSTATE_CONNECT);
+void Curl_set_in_callback(struct Curl_easy *data, bool value)
+{
+  if(data && data->multi)
+    data->multi->in_callback = value;
+}
 
-    /* Remove this node from the list */
-    Curl_llist_remove(&multi->pending, e, NULL);
+bool Curl_is_in_callback(struct Curl_easy *data)
+{
+  return (data && data->multi && data->multi->in_callback);
+}
 
-    /* Make sure that the handle will be processed soonish. */
-    Curl_expire(data, 0, EXPIRE_RUN_NOW);
+unsigned int Curl_multi_max_concurrent_streams(struct Curl_multi *multi)
+{
+  DEBUGASSERT(multi);
+  return multi->max_concurrent_streams;
+}
 
-    /* mark this as having been in the pending queue */
-    data->state.previouslypending = TRUE;
+struct Curl_easy **curl_multi_get_handles(struct Curl_multi *multi)
+{
+  struct Curl_easy **a = malloc(sizeof(struct Curl_easy *) *
+                                (multi->num_easy + 1));
+  if(a) {
+    unsigned int i = 0;
+    struct Curl_easy *e = multi->easyp;
+    while(e) {
+      DEBUGASSERT(i < multi->num_easy);
+      if(!e->state.internal)
+        a[i++] = e;
+      e = e->next;
+    }
+    a[i] = NULL; /* last entry is a NULL */
   }
+  return a;
 }
 
-void Curl_set_in_callback(struct Curl_easy *data, bool value)
+CURLcode Curl_multi_xfer_buf_borrow(struct Curl_easy *data,
+                                    char **pbuf, size_t *pbuflen)
 {
-  /* might get called when there is no data pointer! */
-  if(data) {
-    if(data->multi_easy)
-      data->multi_easy->in_callback = value;
-    else if(data->multi)
-      data->multi->in_callback = value;
+  DEBUGASSERT(data);
+  DEBUGASSERT(data->multi);
+  *pbuf = NULL;
+  *pbuflen = 0;
+  if(!data->multi) {
+    failf(data, "transfer has no multi handle");
+    return CURLE_FAILED_INIT;
+  }
+  if(!data->set.buffer_size) {
+    failf(data, "transfer buffer size is 0");
+    return CURLE_FAILED_INIT;
+  }
+  if(data->multi->xfer_buf_borrowed) {
+    failf(data, "attempt to borrow xfer_buf when already borrowed");
+    return CURLE_AGAIN;
+  }
+
+  if(data->multi->xfer_buf &&
+     data->set.buffer_size > data->multi->xfer_buf_len) {
+    /* not large enough, get a new one */
+    free(data->multi->xfer_buf);
+    data->multi->xfer_buf = NULL;
+    data->multi->xfer_buf_len = 0;
+  }
+
+  if(!data->multi->xfer_buf) {
+    data->multi->xfer_buf = malloc((size_t)data->set.buffer_size);
+    if(!data->multi->xfer_buf) {
+      failf(data, "could not allocate xfer_buf of %zu bytes",
+            (size_t)data->set.buffer_size);
+      return CURLE_OUT_OF_MEMORY;
+    }
+    data->multi->xfer_buf_len = data->set.buffer_size;
   }
+
+  data->multi->xfer_buf_borrowed = TRUE;
+  *pbuf = data->multi->xfer_buf;
+  *pbuflen = data->multi->xfer_buf_len;
+  return CURLE_OK;
 }
 
-bool Curl_is_in_callback(struct Curl_easy *easy)
+void Curl_multi_xfer_buf_release(struct Curl_easy *data, char *buf)
 {
-  return ((easy->multi && easy->multi->in_callback) ||
-          (easy->multi_easy && easy->multi_easy->in_callback));
+  (void)buf;
+  DEBUGASSERT(data);
+  DEBUGASSERT(data->multi);
+  DEBUGASSERT(!buf || data->multi->xfer_buf == buf);
+  data->multi->xfer_buf_borrowed = FALSE;
 }
 
-#ifdef DEBUGBUILD
-void Curl_multi_dump(struct Curl_multi *multi)
+CURLcode Curl_multi_xfer_ulbuf_borrow(struct Curl_easy *data,
+                                      char **pbuf, size_t *pbuflen)
 {
-  struct Curl_easy *data;
-  int i;
-  fprintf(stderr, "* Multi status: %d handles, %d alive\n",
-          multi->num_easy, multi->num_alive);
-  for(data = multi->easyp; data; data = data->next) {
-    if(data->mstate < MSTATE_COMPLETED) {
-      /* only display handles that are not completed */
-      fprintf(stderr, "handle %p, state %s, %d sockets\n",
-              (void *)data,
-              multi_statename[data->mstate], data->numsocks);
-      for(i = 0; i < data->numsocks; i++) {
-        curl_socket_t s = data->sockets[i];
-        struct Curl_sh_entry *entry = sh_getentry(&multi->sockhash, s);
-
-        fprintf(stderr, "%d ", (int)s);
-        if(!entry) {
-          fprintf(stderr, "INTERNAL CONFUSION\n");
-          continue;
-        }
-        fprintf(stderr, "[%s %s] ",
-                (entry->action&CURL_POLL_IN)?"RECVING":"",
-                (entry->action&CURL_POLL_OUT)?"SENDING":"");
-      }
-      if(data->numsocks)
-        fprintf(stderr, "\n");
+  DEBUGASSERT(data);
+  DEBUGASSERT(data->multi);
+  *pbuf = NULL;
+  *pbuflen = 0;
+  if(!data->multi) {
+    failf(data, "transfer has no multi handle");
+    return CURLE_FAILED_INIT;
+  }
+  if(!data->set.upload_buffer_size) {
+    failf(data, "transfer upload buffer size is 0");
+    return CURLE_FAILED_INIT;
+  }
+  if(data->multi->xfer_ulbuf_borrowed) {
+    failf(data, "attempt to borrow xfer_ulbuf when already borrowed");
+    return CURLE_AGAIN;
+  }
+
+  if(data->multi->xfer_ulbuf &&
+     data->set.upload_buffer_size > data->multi->xfer_ulbuf_len) {
+    /* not large enough, get a new one */
+    free(data->multi->xfer_ulbuf);
+    data->multi->xfer_ulbuf = NULL;
+    data->multi->xfer_ulbuf_len = 0;
+  }
+
+  if(!data->multi->xfer_ulbuf) {
+    data->multi->xfer_ulbuf = malloc((size_t)data->set.upload_buffer_size);
+    if(!data->multi->xfer_ulbuf) {
+      failf(data, "could not allocate xfer_ulbuf of %zu bytes",
+            (size_t)data->set.upload_buffer_size);
+      return CURLE_OUT_OF_MEMORY;
     }
+    data->multi->xfer_ulbuf_len = data->set.upload_buffer_size;
   }
+
+  data->multi->xfer_ulbuf_borrowed = TRUE;
+  *pbuf = data->multi->xfer_ulbuf;
+  *pbuflen = data->multi->xfer_ulbuf_len;
+  return CURLE_OK;
 }
-#endif
 
-unsigned int Curl_multi_max_concurrent_streams(struct Curl_multi *multi)
+void Curl_multi_xfer_ulbuf_release(struct Curl_easy *data, char *buf)
+{
+  (void)buf;
+  DEBUGASSERT(data);
+  DEBUGASSERT(data->multi);
+  DEBUGASSERT(!buf || data->multi->xfer_ulbuf == buf);
+  data->multi->xfer_ulbuf_borrowed = FALSE;
+}
+
+static void multi_xfer_bufs_free(struct Curl_multi *multi)
 {
   DEBUGASSERT(multi);
-  return multi->max_concurrent_streams;
+  Curl_safefree(multi->xfer_buf);
+  multi->xfer_buf_len = 0;
+  multi->xfer_buf_borrowed = FALSE;
+  Curl_safefree(multi->xfer_ulbuf);
+  multi->xfer_ulbuf_len = 0;
+  multi->xfer_ulbuf_borrowed = FALSE;
 }
diff --git a/vendor/curl/lib/multihandle.h b/vendor/curl/lib/multihandle.h
index 5b16bb605f..add9a05184 100644
--- a/vendor/curl/lib/multihandle.h
+++ b/vendor/curl/lib/multihandle.h
@@ -44,24 +44,25 @@ struct Curl_message {
 typedef enum {
   MSTATE_INIT,         /* 0 - start in this state */
   MSTATE_PENDING,      /* 1 - no connections, waiting for one */
-  MSTATE_CONNECT,      /* 2 - resolve/connect has been sent off */
-  MSTATE_RESOLVING,    /* 3 - awaiting the resolve to finalize */
-  MSTATE_CONNECTING,   /* 4 - awaiting the TCP connect to finalize */
-  MSTATE_TUNNELING,    /* 5 - awaiting HTTPS proxy SSL initialization to
+  MSTATE_SETUP,        /* 2 - start a new transfer */
+  MSTATE_CONNECT,      /* 3 - resolve/connect has been sent off */
+  MSTATE_RESOLVING,    /* 4 - awaiting the resolve to finalize */
+  MSTATE_CONNECTING,   /* 5 - awaiting the TCP connect to finalize */
+  MSTATE_TUNNELING,    /* 6 - awaiting HTTPS proxy SSL initialization to
                           complete and/or proxy CONNECT to finalize */
-  MSTATE_PROTOCONNECT, /* 6 - initiate protocol connect procedure */
-  MSTATE_PROTOCONNECTING, /* 7 - completing the protocol-specific connect
+  MSTATE_PROTOCONNECT, /* 7 - initiate protocol connect procedure */
+  MSTATE_PROTOCONNECTING, /* 8 - completing the protocol-specific connect
                              phase */
-  MSTATE_DO,           /* 8 - start send off the request (part 1) */
-  MSTATE_DOING,        /* 9 - sending off the request (part 1) */
-  MSTATE_DOING_MORE,   /* 10 - send off the request (part 2) */
-  MSTATE_DID,          /* 11 - done sending off request */
-  MSTATE_PERFORMING,   /* 12 - transfer data */
-  MSTATE_RATELIMITING, /* 13 - wait because limit-rate exceeded */
-  MSTATE_DONE,         /* 14 - post data transfer operation */
-  MSTATE_COMPLETED,    /* 15 - operation complete */
-  MSTATE_MSGSENT,      /* 16 - the operation complete message is sent */
-  MSTATE_LAST          /* 17 - not a true state, never use this */
+  MSTATE_DO,           /* 9 - start send off the request (part 1) */
+  MSTATE_DOING,        /* 10 - sending off the request (part 1) */
+  MSTATE_DOING_MORE,   /* 11 - send off the request (part 2) */
+  MSTATE_DID,          /* 12 - done sending off request */
+  MSTATE_PERFORMING,   /* 13 - transfer data */
+  MSTATE_RATELIMITING, /* 14 - wait because limit-rate exceeded */
+  MSTATE_DONE,         /* 15 - post data transfer operation */
+  MSTATE_COMPLETED,    /* 16 - operation complete */
+  MSTATE_MSGSENT,      /* 17 - the operation complete message is sent */
+  MSTATE_LAST          /* 18 - not a true state, never use this */
 } CURLMstate;
 
 /* we support N sockets per easy handle. Set the corresponding bit to what
@@ -93,9 +94,9 @@ struct Curl_multi {
   struct Curl_easy *easyp;
   struct Curl_easy *easylp; /* last node */
 
-  int num_easy; /* amount of entries in the linked list above. */
-  int num_alive; /* amount of easy handles that are added but have not yet
-                    reached COMPLETE state */
+  unsigned int num_easy; /* amount of entries in the linked list above. */
+  unsigned int num_alive; /* amount of easy handles that are added but have
+                             not yet reached COMPLETE state */
 
   struct Curl_llist msglist; /* a list of messages from completed transfers */
 
@@ -124,6 +125,13 @@ struct Curl_multi {
      times of all currently set timers */
   struct Curl_tree *timetree;
 
+  /* buffer used for transfer data, lazy initialized */
+  char *xfer_buf; /* the actual buffer */
+  size_t xfer_buf_len;      /* the allocated length */
+  /* buffer used for upload data, lazy initialized */
+  char *xfer_ulbuf; /* the actual buffer */
+  size_t xfer_ulbuf_len;      /* the allocated length */
+
 #if defined(USE_SSL)
   struct multi_ssl_backend_data *ssl_backend_data;
 #endif
@@ -136,9 +144,6 @@ struct Curl_multi {
   /* Shared connection cache (bundles)*/
   struct conncache conn_cache;
 
-  long maxconnects; /* if >0, a fixed limit of the maximum number of entries
-                       we're allowed to grow the connection cache to */
-
   long max_host_connections; /* if >0, a fixed limit of the maximum number
                                 of connections per host */
 
@@ -150,16 +155,18 @@ struct Curl_multi {
   void *timer_userp;
   struct curltime timer_lastcall; /* the fixed time for the timeout for the
                                     previous callback */
-  unsigned int max_concurrent_streams;
-
 #ifdef USE_WINSOCK
   WSAEVENT wsa_event; /* winsock event used for waits */
 #else
 #ifdef ENABLE_WAKEUP
-  curl_socket_t wakeup_pair[2]; /* socketpair() used for wakeup
+  curl_socket_t wakeup_pair[2]; /* pipe()/socketpair() used for wakeup
                                    0 is used for read, 1 is used for write */
 #endif
 #endif
+  unsigned int max_concurrent_streams;
+  unsigned int maxconnects; /* if >0, a fixed limit of the maximum number of
+                               entries we're allowed to grow the connection
+                               cache to */
 #define IPV6_UNKNOWN 0
 #define IPV6_DEAD    1
 #define IPV6_WORKS   2
@@ -172,6 +179,8 @@ struct Curl_multi {
 #endif
   BIT(dead); /* a callback returned error, everything needs to crash and
                 burn */
+  BIT(xfer_buf_borrowed);      /* xfer_buf is currently being borrowed */
+  BIT(xfer_ulbuf_borrowed);    /* xfer_ulbuf is currently being borrowed */
 #ifdef DEBUGBUILD
   BIT(warned);                 /* true after user warned of DEBUGBUILD */
 #endif
diff --git a/vendor/curl/lib/multiif.h b/vendor/curl/lib/multiif.h
index 7f08ecc614..59a30646c1 100644
--- a/vendor/curl/lib/multiif.h
+++ b/vendor/curl/lib/multiif.h
@@ -38,15 +38,16 @@ void Curl_attach_connection(struct Curl_easy *data,
 void Curl_detach_connection(struct Curl_easy *data);
 bool Curl_multiplex_wanted(const struct Curl_multi *multi);
 void Curl_set_in_callback(struct Curl_easy *data, bool value);
-bool Curl_is_in_callback(struct Curl_easy *easy);
+bool Curl_is_in_callback(struct Curl_easy *data);
 CURLcode Curl_preconnect(struct Curl_easy *data);
 
 void Curl_multi_connchanged(struct Curl_multi *multi);
 
 /* Internal version of curl_multi_init() accepts size parameters for the
    socket, connection and dns hashes */
-struct Curl_multi *Curl_multi_handle(int hashsize, int chashsize,
-                                     int dnssize);
+struct Curl_multi *Curl_multi_handle(size_t hashsize,
+                                     size_t chashsize,
+                                     size_t dnssize);
 
 /* the write bits start at bit 16 for the *getsock() bitmap */
 #define GETSOCK_WRITEBITSTART 16
@@ -62,15 +63,6 @@ struct Curl_multi *Curl_multi_handle(int hashsize, int chashsize,
 /* mask for checking if read and/or write is set for index x */
 #define GETSOCK_MASK_RW(x) (GETSOCK_READSOCK(x)|GETSOCK_WRITESOCK(x))
 
-#ifdef DEBUGBUILD
- /*
-  * Curl_multi_dump is not a stable public function, this is only meant to
-  * allow easier tracking of the internal handle's state and what sockets
-  * they use. Only for research and development DEBUGBUILD enabled builds.
-  */
-void Curl_multi_dump(struct Curl_multi *multi);
-#endif
-
 /* Return the value of the CURLMOPT_MAX_HOST_CONNECTIONS option */
 size_t Curl_multi_max_host_connections(struct Curl_multi *multi);
 
@@ -103,4 +95,53 @@ CURLMcode Curl_multi_add_perform(struct Curl_multi *multi,
 /* Return the value of the CURLMOPT_MAX_CONCURRENT_STREAMS option */
 unsigned int Curl_multi_max_concurrent_streams(struct Curl_multi *multi);
 
+/**
+ * Borrow the transfer buffer from the multi, suitable
+ * for the given transfer `data`. The buffer may only be used in one
+ * multi processing of the easy handle. It MUST be returned to the
+ * multi before it can be borrowed again.
+ * Pointers into the buffer remain only valid as long as it is borrowed.
+ *
+ * @param data    the easy handle
+ * @param pbuf    on return, the buffer to use or NULL on error
+ * @param pbuflen on return, the size of *pbuf or 0 on error
+ * @return CURLE_OK when buffer is available and is returned.
+ *         CURLE_OUT_OF_MEMORy on failure to allocate the buffer,
+ *         CURLE_FAILED_INIT if the easy handle is without multi.
+ *         CURLE_AGAIN if the buffer is borrowed already.
+ */
+CURLcode Curl_multi_xfer_buf_borrow(struct Curl_easy *data,
+                                   char **pbuf, size_t *pbuflen);
+/**
+ * Release the borrowed buffer. All references into the buffer become
+ * invalid after this.
+ * @param buf the buffer pointer borrowed for coding error checks.
+ */
+void Curl_multi_xfer_buf_release(struct Curl_easy *data, char *buf);
+
+/**
+ * Borrow the upload buffer from the multi, suitable
+ * for the given transfer `data`. The buffer may only be used in one
+ * multi processing of the easy handle. It MUST be returned to the
+ * multi before it can be borrowed again.
+ * Pointers into the buffer remain only valid as long as it is borrowed.
+ *
+ * @param data    the easy handle
+ * @param pbuf    on return, the buffer to use or NULL on error
+ * @param pbuflen on return, the size of *pbuf or 0 on error
+ * @return CURLE_OK when buffer is available and is returned.
+ *         CURLE_OUT_OF_MEMORy on failure to allocate the buffer,
+ *         CURLE_FAILED_INIT if the easy handle is without multi.
+ *         CURLE_AGAIN if the buffer is borrowed already.
+ */
+CURLcode Curl_multi_xfer_ulbuf_borrow(struct Curl_easy *data,
+                                      char **pbuf, size_t *pbuflen);
+
+/**
+ * Release the borrowed upload buffer. All references into the buffer become
+ * invalid after this.
+ * @param buf the upload buffer pointer borrowed for coding error checks.
+ */
+void Curl_multi_xfer_ulbuf_release(struct Curl_easy *data, char *buf);
+
 #endif /* HEADER_CURL_MULTIIF_H */
diff --git a/vendor/curl/lib/netrc.c b/vendor/curl/lib/netrc.c
index e6a09b187a..cd2a2844e2 100644
--- a/vendor/curl/lib/netrc.c
+++ b/vendor/curl/lib/netrc.c
@@ -53,6 +53,8 @@ enum host_lookup_state {
 #define NETRC_FAILED -1
 #define NETRC_SUCCESS 0
 
+#define MAX_NETRC_LINE 4096
+
 /*
  * Returns zero on success.
  */
@@ -80,13 +82,14 @@ static int parsenetrc(const char *host,
   file = fopen(netrcfile, FOPEN_READTEXT);
   if(file) {
     bool done = FALSE;
-    char netrcbuffer[4096];
-    int  netrcbuffsize = (int)sizeof(netrcbuffer);
+    struct dynbuf buf;
+    Curl_dyn_init(&buf, MAX_NETRC_LINE);
 
-    while(!done && Curl_get_line(netrcbuffer, netrcbuffsize, file)) {
+    while(!done && Curl_get_line(&buf, file)) {
       char *tok;
       char *tok_end;
       bool quoted;
+      char *netrcbuffer = Curl_dyn_ptr(&buf);
       if(state == MACDEF) {
         if((netrcbuffer[0] == '\n') || (netrcbuffer[0] == '\r'))
           state = NOTHING;
@@ -245,6 +248,7 @@ static int parsenetrc(const char *host,
     } /* while Curl_get_line() */
 
 out:
+    Curl_dyn_free(&buf);
     if(!retcode) {
       /* success */
       if(login_alloc) {
@@ -327,7 +331,7 @@ int Curl_parsenetrc(const char *host, char **loginp, char **passwordp,
     }
     retcode = parsenetrc(host, loginp, passwordp, filealloc);
     free(filealloc);
-#ifdef WIN32
+#ifdef _WIN32
     if(retcode == NETRC_FILE_MISSING) {
       /* fallback to the old-style "_netrc" file */
       filealloc = curl_maprintf("%s%s_netrc", home, DIR_CHAR);
diff --git a/vendor/curl/lib/noproxy.c b/vendor/curl/lib/noproxy.c
index 2b9908d894..62299e28f3 100644
--- a/vendor/curl/lib/noproxy.c
+++ b/vendor/curl/lib/noproxy.c
@@ -78,7 +78,7 @@ UNITTEST bool Curl_cidr6_match(const char *ipv6,
                                const char *network,
                                unsigned int bits)
 {
-#ifdef ENABLE_IPV6
+#ifdef USE_IPV6
   int bytes;
   int rest;
   unsigned char address[16];
@@ -216,7 +216,6 @@ bool Curl_check_noproxy(const char *name, const char *no_proxy,
           /* case C passes through, not a match */
           break;
         case TYPE_IPV4:
-          /* FALLTHROUGH */
         case TYPE_IPV6: {
           const char *check = token;
           char *slash;
diff --git a/vendor/curl/lib/openldap.c b/vendor/curl/lib/openldap.c
index 41fecf9143..0348ef5bab 100644
--- a/vendor/curl/lib/openldap.c
+++ b/vendor/curl/lib/openldap.c
@@ -117,7 +117,7 @@ static Curl_recv oldap_recv;
  */
 
 const struct Curl_handler Curl_handler_ldap = {
-  "LDAP",                               /* scheme */
+  "ldap",                               /* scheme */
   oldap_setup_connection,               /* setup_connection */
   oldap_do,                             /* do_it */
   oldap_done,                           /* done */
@@ -130,7 +130,8 @@ const struct Curl_handler Curl_handler_ldap = {
   ZERO_NULL,                            /* domore_getsock */
   ZERO_NULL,                            /* perform_getsock */
   oldap_disconnect,                     /* disconnect */
-  ZERO_NULL,                            /* readwrite */
+  ZERO_NULL,                            /* write_resp */
+  ZERO_NULL,                            /* write_resp_hd */
   ZERO_NULL,                            /* connection_check */
   ZERO_NULL,                            /* attach connection */
   PORT_LDAP,                            /* defport */
@@ -145,7 +146,7 @@ const struct Curl_handler Curl_handler_ldap = {
  */
 
 const struct Curl_handler Curl_handler_ldaps = {
-  "LDAPS",                              /* scheme */
+  "ldaps",                              /* scheme */
   oldap_setup_connection,               /* setup_connection */
   oldap_do,                             /* do_it */
   oldap_done,                           /* done */
@@ -158,7 +159,8 @@ const struct Curl_handler Curl_handler_ldaps = {
   ZERO_NULL,                            /* domore_getsock */
   ZERO_NULL,                            /* perform_getsock */
   oldap_disconnect,                     /* disconnect */
-  ZERO_NULL,                            /* readwrite */
+  ZERO_NULL,                            /* write_resp */
+  ZERO_NULL,                            /* write_resp_hd */
   ZERO_NULL,                            /* connection_check */
   ZERO_NULL,                            /* attach connection */
   PORT_LDAPS,                           /* defport */
@@ -199,11 +201,11 @@ struct ldapreqinfo {
 };
 
 /*
- * state()
+ * oldap_state()
  *
  * This is the ONLY way to change LDAP state!
  */
-static void state(struct Curl_easy *data, ldapstate newstate)
+static void oldap_state(struct Curl_easy *data, ldapstate newstate)
 {
   struct ldapconninfo *ldapc = data->conn->proto.ldapc;
 
@@ -319,31 +321,12 @@ static CURLcode oldap_setup_connection(struct Curl_easy *data,
 {
   CURLcode result;
   LDAPURLDesc *lud;
-  struct ldapconninfo *li;
+  (void)conn;
 
   /* Early URL syntax check. */
   result = oldap_url_parse(data, &lud);
   ldap_free_urldesc(lud);
 
-  if(!result) {
-    li = calloc(1, sizeof(struct ldapconninfo));
-    if(!li)
-      result = CURLE_OUT_OF_MEMORY;
-    else {
-      li->proto = ldap_pvt_url_scheme2proto(data->state.up.scheme);
-      conn->proto.ldapc = li;
-      connkeep(conn, "OpenLDAP default");
-
-      /* Initialize the SASL storage */
-      Curl_sasl_init(&li->sasl, data, &saslldap);
-
-      /* Clear the TLS upgraded flag */
-      conn->bits.tls_upgraded = FALSE;
-
-      result = oldap_parse_login_options(conn);
-    }
-  }
-
   return result;
 }
 
@@ -444,7 +427,7 @@ static CURLcode oldap_perform_bind(struct Curl_easy *data, ldapstate newstate)
   rc = ldap_sasl_bind(li->ld, binddn, LDAP_SASL_SIMPLE, &passwd,
                       NULL, NULL, &li->msgid);
   if(rc == LDAP_SUCCESS)
-    state(data, newstate);
+    oldap_state(data, newstate);
   else
     result = oldap_map_error(rc,
                              data->state.aptr.user?
@@ -467,7 +450,7 @@ static CURLcode oldap_perform_mechs(struct Curl_easy *data)
                        (char **) supportedSASLMechanisms, 0,
                        NULL, NULL, NULL, 0, &li->msgid);
   if(rc == LDAP_SUCCESS)
-    state(data, OLDAP_MECHS);
+    oldap_state(data, OLDAP_MECHS);
   else
     result = oldap_map_error(rc, CURLE_LOGIN_DENIED);
   return result;
@@ -480,7 +463,7 @@ static CURLcode oldap_perform_sasl(struct Curl_easy *data)
   struct ldapconninfo *li = data->conn->proto.ldapc;
   CURLcode result = Curl_sasl_start(&li->sasl, data, TRUE, &progress);
 
-  state(data, OLDAP_SASL);
+  oldap_state(data, OLDAP_SASL);
   if(!result && progress != SASL_INPROGRESS)
     result = CURLE_LOGIN_DENIED;
   return result;
@@ -503,7 +486,7 @@ static CURLcode oldap_ssl_connect(struct Curl_easy *data, ldapstate newstate)
 
   result = Curl_conn_connect(data, FIRSTSOCKET, FALSE, &ssldone);
   if(!result) {
-    state(data, newstate);
+    oldap_state(data, newstate);
 
     if(ssldone) {
       Sockbuf *sb;
@@ -527,7 +510,7 @@ static CURLcode oldap_perform_starttls(struct Curl_easy *data)
   int rc = ldap_start_tls(li->ld, NULL, NULL, &li->msgid);
 
   if(rc == LDAP_SUCCESS)
-    state(data, OLDAP_STARTTLS);
+    oldap_state(data, OLDAP_STARTTLS);
   else
     result = oldap_map_error(rc, CURLE_USE_SSL_FAILED);
   return result;
@@ -537,7 +520,7 @@ static CURLcode oldap_perform_starttls(struct Curl_easy *data)
 static CURLcode oldap_connect(struct Curl_easy *data, bool *done)
 {
   struct connectdata *conn = data->conn;
-  struct ldapconninfo *li = conn->proto.ldapc;
+  struct ldapconninfo *li;
   static const int version = LDAP_VERSION3;
   int rc;
   char *hosturl;
@@ -547,9 +530,32 @@ static CURLcode oldap_connect(struct Curl_easy *data, bool *done)
 
   (void)done;
 
-  hosturl = aprintf("ldap%s://%s:%d",
-                    conn->handler->flags & PROTOPT_SSL? "s": "",
-                    conn->host.name, conn->remote_port);
+  DEBUGASSERT(!conn->proto.ldapc);
+  li = calloc(1, sizeof(struct ldapconninfo));
+  if(!li)
+    return CURLE_OUT_OF_MEMORY;
+  else {
+    CURLcode result;
+    li->proto = ldap_pvt_url_scheme2proto(data->state.up.scheme);
+    conn->proto.ldapc = li;
+
+    /* Initialize the SASL storage */
+    Curl_sasl_init(&li->sasl, data, &saslldap);
+
+    /* Clear the TLS upgraded flag */
+    conn->bits.tls_upgraded = FALSE;
+
+    result = oldap_parse_login_options(conn);
+    if(result)
+      return result;
+  }
+
+  hosturl = aprintf("%s://%s%s%s:%d",
+                    conn->handler->scheme,
+                    conn->bits.ipv6_ip? "[": "",
+                    conn->host.name,
+                    conn->bits.ipv6_ip? "]": "",
+                    conn->remote_port);
   if(!hosturl)
     return CURLE_OUT_OF_MEMORY;
 
@@ -644,7 +650,7 @@ static CURLcode oldap_state_mechs_resp(struct Curl_easy *data,
     switch(code) {
     case LDAP_SIZELIMIT_EXCEEDED:
       infof(data, "Too many authentication mechanisms\n");
-      /* FALLTHROUGH */
+      FALLTHROUGH();
     case LDAP_SUCCESS:
     case LDAP_NO_RESULTS_RETURNED:
       if(Curl_sasl_can_authenticate(&li->sasl, data))
@@ -682,7 +688,7 @@ static CURLcode oldap_state_sasl_resp(struct Curl_easy *data,
   else {
     result = Curl_sasl_continue(&li->sasl, data, code, &progress);
     if(!result && progress != SASL_INPROGRESS)
-      state(data, OLDAP_STOP);
+      oldap_state(data, OLDAP_STOP);
   }
 
   if(li->servercred)
@@ -710,7 +716,7 @@ static CURLcode oldap_state_bind_resp(struct Curl_easy *data, LDAPMessage *msg,
     result = oldap_map_error(rc, CURLE_LDAP_CANNOT_BIND);
   }
   else
-    state(data, OLDAP_STOP);
+    oldap_state(data, OLDAP_STOP);
 
   if(bv)
     ber_bvfree(bv);
@@ -792,10 +798,13 @@ static CURLcode oldap_connecting(struct Curl_easy *data, bool *done)
         result = oldap_perform_bind(data, OLDAP_BIND);
       break;
     }
-    /* FALLTHROUGH */
+    result = Curl_ssl_cfilter_add(data, conn, FIRSTSOCKET);
+    if(result)
+      break;
+    FALLTHROUGH();
   case OLDAP_TLS:
     result = oldap_ssl_connect(data, OLDAP_TLS);
-    if(result && data->set.use_ssl != CURLUSESSL_TRY)
+    if(result)
       result = oldap_map_error(code, CURLE_USE_SSL_FAILED);
     else if(ssl_installed(conn)) {
       conn->bits.tls_upgraded = TRUE;
@@ -804,7 +813,8 @@ static CURLcode oldap_connecting(struct Curl_easy *data, bool *done)
       else if(data->state.aptr.user)
         result = oldap_perform_bind(data, OLDAP_BIND);
       else {
-        state(data, OLDAP_STOP); /* Version 3 supported: no bind required */
+        /* Version 3 supported: no bind required */
+        oldap_state(data, OLDAP_STOP);
         result = CURLE_OK;
       }
     }
@@ -885,6 +895,15 @@ static CURLcode oldap_do(struct Curl_easy *data, bool *done)
 
   result = oldap_url_parse(data, &lud);
   if(!result) {
+#ifdef USE_SSL
+    if(ssl_installed(conn)) {
+      Sockbuf *sb;
+      /* re-install the libcurl SSL handlers into the sockbuf. */
+      ldap_get_option(li->ld, LDAP_OPT_SOCKBUF, &sb);
+      ber_sockbuf_add_io(sb, &ldapsb_tls, LBER_SBIOD_LEVEL_TRANSPORT, data);
+    }
+#endif
+
     rc = ldap_search_ext(li->ld, lud->lud_dn, lud->lud_scope,
                          lud->lud_filter, lud->lud_attrs, 0,
                          NULL, NULL, NULL, 0, &msgid);
@@ -902,7 +921,7 @@ static CURLcode oldap_do(struct Curl_easy *data, bool *done)
       else {
         lr->msgid = msgid;
         data->req.p.ldap = lr;
-        Curl_setup_transfer(data, FIRSTSOCKET, -1, FALSE, -1);
+        Curl_xfer_setup(data, FIRSTSOCKET, -1, FALSE, -1);
         *done = TRUE;
       }
     }
@@ -946,18 +965,12 @@ static CURLcode client_write(struct Curl_easy *data,
     if(!len && plen && prefix[plen - 1] == ' ')
       plen--;
     result = Curl_client_write(data, CLIENTWRITE_BODY, (char *) prefix, plen);
-    if(!result)
-      data->req.bytecount += plen;
   }
   if(!result && value) {
     result = Curl_client_write(data, CLIENTWRITE_BODY, (char *) value, len);
-    if(!result)
-      data->req.bytecount += len;
   }
   if(!result && suffix) {
     result = Curl_client_write(data, CLIENTWRITE_BODY, (char *) suffix, slen);
-    if(!result)
-      data->req.bytecount += slen;
   }
   return result;
 }
@@ -1013,7 +1026,7 @@ static ssize_t oldap_recv(struct Curl_easy *data, int sockindex, char *buf,
     switch(code) {
     case LDAP_SIZELIMIT_EXCEEDED:
       infof(data, "There are more than %d entries", lr->nument);
-      /* FALLTHROUGH */
+      FALLTHROUGH();
     case LDAP_SUCCESS:
       data->req.size = data->req.bytecount;
       break;
diff --git a/vendor/curl/lib/pingpong.c b/vendor/curl/lib/pingpong.c
index 136985fc92..81576c08c9 100644
--- a/vendor/curl/lib/pingpong.c
+++ b/vendor/curl/lib/pingpong.c
@@ -36,6 +36,7 @@
 #include "pingpong.h"
 #include "multiif.h"
 #include "vtls/vtls.h"
+#include "strdup.h"
 
 /* The last 3 #include files should be in this order */
 #include "curl_printf.h"
@@ -105,7 +106,7 @@ CURLcode Curl_pp_statemach(struct Curl_easy *data,
 
   if(Curl_conn_data_pending(data, FIRSTSOCKET))
     rc = 1;
-  else if(Curl_pp_moredata(pp))
+  else if(pp->overflow)
     /* We are receiving and there is data in the cache so just read it */
     rc = 1;
   else if(!pp->sendleft && Curl_conn_data_pending(data, FIRSTSOCKET))
@@ -139,19 +140,13 @@ CURLcode Curl_pp_statemach(struct Curl_easy *data,
 }
 
 /* initialize stuff to prepare for reading a fresh new response */
-void Curl_pp_init(struct Curl_easy *data, struct pingpong *pp)
+void Curl_pp_init(struct pingpong *pp)
 {
-  DEBUGASSERT(data);
   pp->nread_resp = 0;
-  pp->linestart_resp = data->state.buffer;
-  pp->pending_resp = TRUE;
   pp->response = Curl_now(); /* start response time-out now! */
-}
-
-/* setup for the coming transfer */
-void Curl_pp_setup(struct pingpong *pp)
-{
+  pp->pending_resp = TRUE;
   Curl_dyn_init(&pp->sendbuf, DYN_PINGPPONG_CMD);
+  Curl_dyn_init(&pp->recvbuf, DYN_PINGPPONG_CMD);
 }
 
 /***********************************************************************
@@ -169,7 +164,7 @@ CURLcode Curl_pp_vsendf(struct Curl_easy *data,
                         const char *fmt,
                         va_list args)
 {
-  ssize_t bytes_written = 0;
+  size_t bytes_written = 0;
   size_t write_len;
   char *s;
   CURLcode result;
@@ -197,15 +192,18 @@ CURLcode Curl_pp_vsendf(struct Curl_easy *data,
   if(result)
     return result;
 
+  pp->pending_resp = TRUE;
   write_len = Curl_dyn_len(&pp->sendbuf);
   s = Curl_dyn_ptr(&pp->sendbuf);
-  Curl_pp_init(data, pp);
 
 #ifdef HAVE_GSSAPI
   conn->data_prot = PROT_CMD;
 #endif
-  result = Curl_nwrite(data, FIRSTSOCKET, s, write_len, &bytes_written);
-  if(result)
+  result = Curl_conn_send(data, FIRSTSOCKET, s, write_len, &bytes_written);
+  if(result == CURLE_AGAIN) {
+    bytes_written = 0;
+  }
+  else if(result)
     return result;
 #ifdef HAVE_GSSAPI
   data_sec = conn->data_prot;
@@ -213,9 +211,9 @@ CURLcode Curl_pp_vsendf(struct Curl_easy *data,
   conn->data_prot = (unsigned char)data_sec;
 #endif
 
-  Curl_debug(data, CURLINFO_HEADER_OUT, s, (size_t)bytes_written);
+  Curl_debug(data, CURLINFO_HEADER_OUT, s, bytes_written);
 
-  if(bytes_written != (ssize_t)write_len) {
+  if(bytes_written != write_len) {
     /* the whole chunk was not sent, keep it around and adjust sizes */
     pp->sendthis = s;
     pp->sendsize = write_len;
@@ -255,192 +253,126 @@ CURLcode Curl_pp_sendf(struct Curl_easy *data, struct pingpong *pp,
   return result;
 }
 
+static CURLcode pingpong_read(struct Curl_easy *data,
+                              int sockindex,
+                              char *buffer,
+                              size_t buflen,
+                              ssize_t *nread)
+{
+  CURLcode result;
+#ifdef HAVE_GSSAPI
+  enum protection_level prot = data->conn->data_prot;
+  data->conn->data_prot = PROT_CLEAR;
+#endif
+  result = Curl_conn_recv(data, sockindex, buffer, buflen, nread);
+#ifdef HAVE_GSSAPI
+  DEBUGASSERT(prot  > PROT_NONE && prot < PROT_LAST);
+  data->conn->data_prot = (unsigned char)prot;
+#endif
+  return result;
+}
+
 /*
  * Curl_pp_readresp()
  *
  * Reads a piece of a server response.
  */
 CURLcode Curl_pp_readresp(struct Curl_easy *data,
-                          curl_socket_t sockfd,
+                          int sockindex,
                           struct pingpong *pp,
                           int *code, /* return the server code if done */
                           size_t *size) /* size of the response */
 {
-  ssize_t perline; /* count bytes per line */
-  bool keepon = TRUE;
-  ssize_t gotbytes;
-  char *ptr;
   struct connectdata *conn = data->conn;
-  char * const buf = data->state.buffer;
   CURLcode result = CURLE_OK;
 
   *code = 0; /* 0 for errors or not done */
   *size = 0;
 
-  ptr = buf + pp->nread_resp;
+  if(pp->nfinal) {
+    /* a previous call left this many bytes in the beginning of the buffer as
+       that was the final line; now ditch that */
+    size_t full = Curl_dyn_len(&pp->recvbuf);
 
-  /* number of bytes in the current line, so far */
-  perline = (ssize_t)(ptr-pp->linestart_resp);
+    /* trim off the "final" leading part */
+    Curl_dyn_tail(&pp->recvbuf, full -  pp->nfinal);
 
-  while((pp->nread_resp < (size_t)data->set.buffer_size) &&
-        (keepon && !result)) {
+    pp->nfinal = 0; /* now gone */
+  }
+  if(!pp->overflow) {
+    ssize_t gotbytes = 0;
+    char buffer[900];
 
-    if(pp->cache) {
-      /* we had data in the "cache", copy that instead of doing an actual
-       * read
-       *
-       * pp->cache_size is cast to ssize_t here.  This should be safe, because
-       * it would have been populated with something of size int to begin
-       * with, even though its datatype may be larger than an int.
-       */
-      if((ptr + pp->cache_size) > (buf + data->set.buffer_size + 1)) {
-        failf(data, "cached response data too big to handle");
-        return CURLE_WEIRD_SERVER_REPLY;
-      }
-      memcpy(ptr, pp->cache, pp->cache_size);
-      gotbytes = (ssize_t)pp->cache_size;
-      free(pp->cache);    /* free the cache */
-      pp->cache = NULL;   /* clear the pointer */
-      pp->cache_size = 0; /* zero the size just in case */
-    }
-    else {
-#ifdef HAVE_GSSAPI
-      enum protection_level prot = conn->data_prot;
-      conn->data_prot = PROT_CLEAR;
-#endif
-      DEBUGASSERT((ptr + data->set.buffer_size - pp->nread_resp) <=
-                  (buf + data->set.buffer_size + 1));
-      result = Curl_read(data, sockfd, ptr,
-                         data->set.buffer_size - pp->nread_resp,
-                         &gotbytes);
-#ifdef HAVE_GSSAPI
-      DEBUGASSERT(prot  > PROT_NONE && prot < PROT_LAST);
-      conn->data_prot = (unsigned char)prot;
-#endif
-      if(result == CURLE_AGAIN)
-        return CURLE_OK; /* return */
+    result = pingpong_read(data, sockindex, buffer, sizeof(buffer), &gotbytes);
+    if(result == CURLE_AGAIN)
+      return CURLE_OK;
 
-      if(result)
-        /* Set outer result variable to this error. */
-        keepon = FALSE;
-    }
+    if(result)
+      return result;
 
-    if(!keepon)
-      ;
-    else if(gotbytes <= 0) {
-      keepon = FALSE;
-      result = CURLE_RECV_ERROR;
+    if(gotbytes <= 0) {
       failf(data, "response reading failed (errno: %d)", SOCKERRNO);
+      return CURLE_RECV_ERROR;
     }
-    else {
-      /* we got a whole chunk of data, which can be anything from one
-       * byte to a set of lines and possible just a piece of the last
-       * line */
-      ssize_t i;
-      ssize_t clipamount = 0;
-      bool restart = FALSE;
-
-      data->req.headerbytecount += (unsigned int)gotbytes;
-
-      pp->nread_resp += gotbytes;
-      for(i = 0; i < gotbytes; ptr++, i++) {
-        perline++;
-        if(*ptr == '\n') {
-          /* a newline is CRLF in pp-talk, so the CR is ignored as
-             the line isn't really terminated until the LF comes */
-
-          /* output debug output if that is requested */
+
+    result = Curl_dyn_addn(&pp->recvbuf, buffer, gotbytes);
+    if(result)
+      return result;
+
+    data->req.headerbytecount += (unsigned int)gotbytes;
+
+    pp->nread_resp += gotbytes;
+  }
+
+  do {
+    char *line = Curl_dyn_ptr(&pp->recvbuf);
+    char *nl = memchr(line, '\n', Curl_dyn_len(&pp->recvbuf));
+    if(nl) {
+      /* a newline is CRLF in pp-talk, so the CR is ignored as
+         the line isn't really terminated until the LF comes */
+      size_t length = nl - line + 1;
+
+      /* output debug output if that is requested */
 #ifdef HAVE_GSSAPI
-          if(!conn->sec_complete)
+      if(!conn->sec_complete)
 #endif
-            Curl_debug(data, CURLINFO_HEADER_IN,
-                       pp->linestart_resp, (size_t)perline);
-
-          /*
-           * We pass all response-lines to the callback function registered
-           * for "headers". The response lines can be seen as a kind of
-           * headers.
-           */
-          result = Curl_client_write(data, CLIENTWRITE_HEADER,
-                                     pp->linestart_resp, perline);
-          if(result)
-            return result;
-
-          if(pp->endofresp(data, conn, pp->linestart_resp, perline, code)) {
-            /* This is the end of the last line, copy the last line to the
-               start of the buffer and null-terminate, for old times sake */
-            size_t n = ptr - pp->linestart_resp;
-            memmove(buf, pp->linestart_resp, n);
-            buf[n] = 0; /* null-terminate */
-            keepon = FALSE;
-            pp->linestart_resp = ptr + 1; /* advance pointer */
-            i++; /* skip this before getting out */
-
-            *size = pp->nread_resp; /* size of the response */
-            pp->nread_resp = 0; /* restart */
-            break;
-          }
-          perline = 0; /* line starts over here */
-          pp->linestart_resp = ptr + 1;
-        }
-      }
+        Curl_debug(data, CURLINFO_HEADER_IN, line, length);
 
-      if(!keepon && (i != gotbytes)) {
-        /* We found the end of the response lines, but we didn't parse the
-           full chunk of data we have read from the server. We therefore need
-           to store the rest of the data to be checked on the next invoke as
-           it may actually contain another end of response already! */
-        clipamount = gotbytes - i;
-        restart = TRUE;
-        DEBUGF(infof(data, "Curl_pp_readresp_ %d bytes of trailing "
-                     "server response left",
-                     (int)clipamount));
-      }
-      else if(keepon) {
-
-        if((perline == gotbytes) &&
-           (gotbytes > (ssize_t)data->set.buffer_size/2)) {
-          /* We got an excessive line without newlines and we need to deal
-             with it. We keep the first bytes of the line then we throw
-             away the rest. */
-          infof(data, "Excessive server response line length received, "
-                "%zd bytes. Stripping", gotbytes);
-          restart = TRUE;
-
-          /* we keep 40 bytes since all our pingpong protocols are only
-             interested in the first piece */
-          clipamount = 40;
-        }
-        else if(pp->nread_resp > (size_t)data->set.buffer_size/2) {
-          /* We got a large chunk of data and there's potentially still
-             trailing data to take care of, so we put any such part in the
-             "cache", clear the buffer to make space and restart. */
-          clipamount = perline;
-          restart = TRUE;
-        }
-      }
-      else if(i == gotbytes)
-        restart = TRUE;
-
-      if(clipamount) {
-        pp->cache_size = clipamount;
-        pp->cache = malloc(pp->cache_size);
-        if(pp->cache)
-          memcpy(pp->cache, pp->linestart_resp, pp->cache_size);
+      /*
+       * Pass all response-lines to the callback function registered for
+       * "headers". The response lines can be seen as a kind of headers.
+       */
+      result = Curl_client_write(data, CLIENTWRITE_INFO, line, length);
+      if(result)
+        return result;
+
+      if(pp->endofresp(data, conn, line, length, code)) {
+        /* When at "end of response", keep the endofresp line first in the
+           buffer since it will be accessed outside (by pingpong
+           parsers). Store the overflow counter to inform about additional
+           data in this buffer after the endofresp line. */
+        pp->nfinal = length;
+        if(Curl_dyn_len(&pp->recvbuf) > length)
+          pp->overflow = Curl_dyn_len(&pp->recvbuf) - length;
         else
-          return CURLE_OUT_OF_MEMORY;
-      }
-      if(restart) {
-        /* now reset a few variables to start over nicely from the start of
-           the big buffer */
-        pp->nread_resp = 0; /* start over from scratch in the buffer */
-        ptr = pp->linestart_resp = buf;
-        perline = 0;
+          pp->overflow = 0;
+        *size = pp->nread_resp; /* size of the response */
+        pp->nread_resp = 0; /* restart */
+        break;
       }
+      if(Curl_dyn_len(&pp->recvbuf) > length)
+        /* keep the remaining piece */
+        Curl_dyn_tail((&pp->recvbuf), Curl_dyn_len(&pp->recvbuf) - length);
+      else
+        Curl_dyn_reset(&pp->recvbuf);
+    }
+    else {
+      /* without a newline, there is no overflow */
+      pp->overflow = 0;
+      break;
+    }
 
-    } /* there was data */
-
-  } /* while there's buffer left and loop is requested */
+  } while(1); /* while there's buffer left to scan */
 
   pp->pending_resp = FALSE;
 
@@ -466,14 +398,20 @@ CURLcode Curl_pp_flushsend(struct Curl_easy *data,
                            struct pingpong *pp)
 {
   /* we have a piece of a command still left to send */
-  ssize_t written;
-  CURLcode result = Curl_nwrite(data, FIRSTSOCKET,
-                                pp->sendthis + pp->sendsize - pp->sendleft,
-                                pp->sendleft, &written);
+  size_t written;
+  CURLcode result;
+
+  result = Curl_conn_send(data, FIRSTSOCKET,
+                          pp->sendthis + pp->sendsize - pp->sendleft,
+                          pp->sendleft, &written);
+  if(result == CURLE_AGAIN) {
+    result = CURLE_OK;
+    written = 0;
+  }
   if(result)
     return result;
 
-  if(written != (ssize_t)pp->sendleft) {
+  if(written != pp->sendleft) {
     /* only a fraction was sent */
     pp->sendleft -= written;
   }
@@ -488,14 +426,13 @@ CURLcode Curl_pp_flushsend(struct Curl_easy *data,
 CURLcode Curl_pp_disconnect(struct pingpong *pp)
 {
   Curl_dyn_free(&pp->sendbuf);
-  Curl_safefree(pp->cache);
+  Curl_dyn_free(&pp->recvbuf);
   return CURLE_OK;
 }
 
 bool Curl_pp_moredata(struct pingpong *pp)
 {
-  return (!pp->sendleft && pp->cache && pp->nread_resp < pp->cache_size) ?
-    TRUE : FALSE;
+  return (!pp->sendleft && Curl_dyn_len(&pp->recvbuf) > pp->nfinal);
 }
 
 #endif
diff --git a/vendor/curl/lib/pingpong.h b/vendor/curl/lib/pingpong.h
index 80d3f7718c..28172c7284 100644
--- a/vendor/curl/lib/pingpong.h
+++ b/vendor/curl/lib/pingpong.h
@@ -47,16 +47,11 @@ typedef enum {
  * It holds response cache and non-blocking sending data.
  */
 struct pingpong {
-  char *cache;     /* data cache between getresponse()-calls */
-  size_t cache_size;  /* size of cache in bytes */
   size_t nread_resp;  /* number of bytes currently read of a server response */
-  char *linestart_resp; /* line start pointer for the server response
-                           reader function */
   bool pending_resp;  /* set TRUE when a server response is pending or in
                          progress, and is cleared once the last response is
                          read */
-  char *sendthis; /* allocated pointer to a buffer that is to be sent to the
-                     server */
+  char *sendthis; /* pointer to a buffer that is to be sent to the server */
   size_t sendleft; /* number of bytes left to send from the sendthis buffer */
   size_t sendsize; /* total size of the sendthis buffer */
   struct curltime response; /* set to Curl_now() when a command has been sent
@@ -64,6 +59,10 @@ struct pingpong {
   timediff_t response_time; /* When no timeout is given, this is the amount of
                                milliseconds we await for a server response. */
   struct dynbuf sendbuf;
+  struct dynbuf recvbuf;
+  size_t overflow; /* number of bytes left after a final response line */
+  size_t nfinal;   /* number of bytes in the final response line, which
+                      after a match is first in the receice buffer */
 
   /* Function pointers the protocols MUST implement and provide for the
      pingpong layer to function */
@@ -90,10 +89,7 @@ CURLcode Curl_pp_statemach(struct Curl_easy *data, struct pingpong *pp,
                            bool block, bool disconnecting);
 
 /* initialize stuff to prepare for reading a fresh new response */
-void Curl_pp_init(struct Curl_easy *data, struct pingpong *pp);
-
-/* setup for the transfer */
-void Curl_pp_setup(struct pingpong *pp);
+void Curl_pp_init(struct pingpong *pp);
 
 /* Returns timeout in ms. 0 or negative number means the timeout has already
    triggered */
@@ -113,7 +109,7 @@ timediff_t Curl_pp_state_timeout(struct Curl_easy *data,
  */
 CURLcode Curl_pp_sendf(struct Curl_easy *data,
                        struct pingpong *pp,
-                       const char *fmt, ...);
+                       const char *fmt, ...) CURL_PRINTF(3, 4);
 
 /***********************************************************************
  *
@@ -128,7 +124,7 @@ CURLcode Curl_pp_sendf(struct Curl_easy *data,
 CURLcode Curl_pp_vsendf(struct Curl_easy *data,
                         struct pingpong *pp,
                         const char *fmt,
-                        va_list args);
+                        va_list args) CURL_PRINTF(3, 0);
 
 /*
  * Curl_pp_readresp()
@@ -136,7 +132,7 @@ CURLcode Curl_pp_vsendf(struct Curl_easy *data,
  * Reads a piece of a server response.
  */
 CURLcode Curl_pp_readresp(struct Curl_easy *data,
-                          curl_socket_t sockfd,
+                          int sockindex,
                           struct pingpong *pp,
                           int *code, /* return the server code if done */
                           size_t *size); /* size of the response */
diff --git a/vendor/curl/lib/pop3.c b/vendor/curl/lib/pop3.c
index a9d5fdd698..9a30331529 100644
--- a/vendor/curl/lib/pop3.c
+++ b/vendor/curl/lib/pop3.c
@@ -77,6 +77,7 @@
 #include "curl_sasl.h"
 #include "curl_md5.h"
 #include "warnless.h"
+#include "strdup.h"
 /* The last 3 #include files should be in this order */
 #include "curl_printf.h"
 #include "curl_memory.h"
@@ -111,7 +112,7 @@ static CURLcode pop3_get_message(struct Curl_easy *data, struct bufref *out);
  */
 
 const struct Curl_handler Curl_handler_pop3 = {
-  "POP3",                           /* scheme */
+  "pop3",                           /* scheme */
   pop3_setup_connection,            /* setup_connection */
   pop3_do,                          /* do_it */
   pop3_done,                        /* done */
@@ -124,7 +125,8 @@ const struct Curl_handler Curl_handler_pop3 = {
   ZERO_NULL,                        /* domore_getsock */
   ZERO_NULL,                        /* perform_getsock */
   pop3_disconnect,                  /* disconnect */
-  ZERO_NULL,                        /* readwrite */
+  ZERO_NULL,                        /* write_resp */
+  ZERO_NULL,                        /* write_resp_hd */
   ZERO_NULL,                        /* connection_check */
   ZERO_NULL,                        /* attach connection */
   PORT_POP3,                        /* defport */
@@ -140,7 +142,7 @@ const struct Curl_handler Curl_handler_pop3 = {
  */
 
 const struct Curl_handler Curl_handler_pop3s = {
-  "POP3S",                          /* scheme */
+  "pop3s",                          /* scheme */
   pop3_setup_connection,            /* setup_connection */
   pop3_do,                          /* do_it */
   pop3_done,                        /* done */
@@ -153,7 +155,8 @@ const struct Curl_handler Curl_handler_pop3s = {
   ZERO_NULL,                        /* domore_getsock */
   ZERO_NULL,                        /* perform_getsock */
   pop3_disconnect,                  /* disconnect */
-  ZERO_NULL,                        /* readwrite */
+  ZERO_NULL,                        /* write_resp */
+  ZERO_NULL,                        /* write_resp_hd */
   ZERO_NULL,                        /* connection_check */
   ZERO_NULL,                        /* attach connection */
   PORT_POP3S,                       /* defport */
@@ -251,8 +254,8 @@ static bool pop3_endofresp(struct Curl_easy *data, struct connectdata *conn,
  */
 static CURLcode pop3_get_message(struct Curl_easy *data, struct bufref *out)
 {
-  char *message = data->state.buffer;
-  size_t len = strlen(message);
+  char *message = Curl_dyn_ptr(&data->conn->proto.pop3c.pp.recvbuf);
+  size_t len = data->conn->proto.pop3c.pp.nfinal;
 
   if(len > 2) {
     /* Find the start of the message */
@@ -648,8 +651,8 @@ static CURLcode pop3_state_servergreet_resp(struct Curl_easy *data,
   CURLcode result = CURLE_OK;
   struct connectdata *conn = data->conn;
   struct pop3_conn *pop3c = &conn->proto.pop3c;
-  const char *line = data->state.buffer;
-  size_t len = strlen(line);
+  const char *line = Curl_dyn_ptr(&data->conn->proto.pop3c.pp.recvbuf);
+  size_t len = data->conn->proto.pop3c.pp.nfinal;
 
   (void)instate; /* no use for this yet */
 
@@ -657,44 +660,35 @@ static CURLcode pop3_state_servergreet_resp(struct Curl_easy *data,
     failf(data, "Got unexpected pop3-server response");
     result = CURLE_WEIRD_SERVER_REPLY;
   }
-  else {
+  else if(len > 3) {
     /* Does the server support APOP authentication? */
-    if(len >= 4 && line[len - 2] == '>') {
-      /* Look for the APOP timestamp */
-      size_t i;
-      for(i = 3; i < len - 2; ++i) {
-        if(line[i] == '<') {
-          /* Calculate the length of the timestamp */
-          size_t timestamplen = len - 1 - i;
-          char *at;
-          if(!timestamplen)
-            break;
-
-          /* Allocate some memory for the timestamp */
-          pop3c->apoptimestamp = (char *)calloc(1, timestamplen + 1);
-
-          if(!pop3c->apoptimestamp)
-            break;
-
-          /* Copy the timestamp */
-          memcpy(pop3c->apoptimestamp, line + i, timestamplen);
-          pop3c->apoptimestamp[timestamplen] = '\0';
-
-          /* If the timestamp does not contain '@' it is not (as required by
-             RFC-1939) conformant to the RFC-822 message id syntax, and we
-             therefore do not use APOP authentication. */
-          at = strchr(pop3c->apoptimestamp, '@');
-          if(!at)
-            Curl_safefree(pop3c->apoptimestamp);
-          else
-            /* Store the APOP capability */
-            pop3c->authtypes |= POP3_TYPE_APOP;
-          break;
-        }
+    char *lt;
+    char *gt = NULL;
+
+    /* Look for the APOP timestamp */
+    lt = memchr(line, '<', len);
+    if(lt)
+      /* search the remainder for '>' */
+      gt = memchr(lt, '>', len - (lt - line));
+    if(gt) {
+      /* the length of the timestamp, including the brackets */
+      size_t timestamplen = gt - lt + 1;
+      char *at = memchr(lt, '@', timestamplen);
+      /* If the timestamp does not contain '@' it is not (as required by
+         RFC-1939) conformant to the RFC-822 message id syntax, and we
+         therefore do not use APOP authentication. */
+      if(at) {
+        /* dupe the timestamp */
+        pop3c->apoptimestamp = Curl_memdup0(lt, timestamplen);
+        if(!pop3c->apoptimestamp)
+          return CURLE_OUT_OF_MEMORY;
+        /* Store the APOP capability */
+        pop3c->authtypes |= POP3_TYPE_APOP;
       }
     }
 
-    result = pop3_perform_capa(data, conn);
+    if(!result)
+      result = pop3_perform_capa(data, conn);
   }
 
   return result;
@@ -707,8 +701,8 @@ static CURLcode pop3_state_capa_resp(struct Curl_easy *data, int pop3code,
   CURLcode result = CURLE_OK;
   struct connectdata *conn = data->conn;
   struct pop3_conn *pop3c = &conn->proto.pop3c;
-  const char *line = data->state.buffer;
-  size_t len = strlen(line);
+  const char *line = Curl_dyn_ptr(&data->conn->proto.pop3c.pp.recvbuf);
+  size_t len = data->conn->proto.pop3c.pp.nfinal;
 
   (void)instate; /* no use for this yet */
 
@@ -795,7 +789,7 @@ static CURLcode pop3_state_starttls_resp(struct Curl_easy *data,
   (void)instate; /* no use for this yet */
 
   /* Pipelining in response is forbidden. */
-  if(data->conn->proto.pop3c.pp.cache_size)
+  if(data->conn->proto.pop3c.pp.overflow)
     return CURLE_WEIRD_SERVER_REPLY;
 
   if(pop3code != '+') {
@@ -942,26 +936,31 @@ static CURLcode pop3_state_command_resp(struct Curl_easy *data,
 
   if(pop3->transfer == PPTRANSFER_BODY) {
     /* POP3 download */
-    Curl_setup_transfer(data, FIRSTSOCKET, -1, FALSE, -1);
+    Curl_xfer_setup(data, FIRSTSOCKET, -1, FALSE, -1);
+
+    if(pp->overflow) {
+      /* The recv buffer contains data that is actually body content so send
+         it as such. Note that there may even be additional "headers" after
+         the body */
 
-    if(pp->cache) {
-      /* The header "cache" contains a bunch of data that is actually body
-         content so send it as such. Note that there may even be additional
-         "headers" after the body */
+      /* keep only the overflow */
+      Curl_dyn_tail(&pp->recvbuf, pp->overflow);
+      pp->nfinal = 0; /* done */
 
       if(!data->req.no_body) {
-        result = Curl_pop3_write(data, pp->cache, pp->cache_size);
+        result = Curl_pop3_write(data, Curl_dyn_ptr(&pp->recvbuf),
+                                 Curl_dyn_len(&pp->recvbuf));
         if(result)
           return result;
       }
 
-      /* Free the cache */
-      Curl_safefree(pp->cache);
-
-      /* Reset the cache size */
-      pp->cache_size = 0;
+      /* reset the buffer */
+      Curl_dyn_reset(&pp->recvbuf);
+      pp->overflow = 0;
     }
   }
+  else
+    pp->overflow = 0;
 
   /* End of DO phase */
   pop3_state(data, POP3_STOP);
@@ -973,7 +972,6 @@ static CURLcode pop3_statemachine(struct Curl_easy *data,
                                   struct connectdata *conn)
 {
   CURLcode result = CURLE_OK;
-  curl_socket_t sock = conn->sock[FIRSTSOCKET];
   int pop3code;
   struct pop3_conn *pop3c = &conn->proto.pop3c;
   struct pingpong *pp = &pop3c->pp;
@@ -990,7 +988,7 @@ static CURLcode pop3_statemachine(struct Curl_easy *data,
 
  do {
     /* Read the response from the server */
-   result = Curl_pp_readresp(data, sock, pp, &pop3code, &nread);
+   result = Curl_pp_readresp(data, FIRSTSOCKET, pp, &pop3code, &nread);
    if(result)
      return result;
 
@@ -1088,7 +1086,7 @@ static CURLcode pop3_init(struct Curl_easy *data)
   CURLcode result = CURLE_OK;
   struct POP3 *pop3;
 
-  pop3 = data->req.p.pop3 = calloc(sizeof(struct POP3), 1);
+  pop3 = data->req.p.pop3 = calloc(1, sizeof(struct POP3));
   if(!pop3)
     result = CURLE_OUT_OF_MEMORY;
 
@@ -1131,8 +1129,7 @@ static CURLcode pop3_connect(struct Curl_easy *data, bool *done)
   Curl_sasl_init(&pop3c->sasl, data, &saslpop3);
 
   /* Initialise the pingpong layer */
-  Curl_pp_setup(pp);
-  Curl_pp_init(data, pp);
+  Curl_pp_init(pp);
 
   /* Parse the URL options */
   result = pop3_parse_url_options(conn);
@@ -1455,7 +1452,7 @@ static CURLcode pop3_parse_custom_request(struct Curl_easy *data)
  * This function scans the body after the end-of-body and writes everything
  * until the end is found.
  */
-CURLcode Curl_pop3_write(struct Curl_easy *data, char *str, size_t nread)
+CURLcode Curl_pop3_write(struct Curl_easy *data, const char *str, size_t nread)
 {
   /* This code could be made into a special function in the handler struct */
   CURLcode result = CURLE_OK;
diff --git a/vendor/curl/lib/pop3.h b/vendor/curl/lib/pop3.h
index 83f0f831e6..e8e98db04b 100644
--- a/vendor/curl/lib/pop3.h
+++ b/vendor/curl/lib/pop3.h
@@ -92,6 +92,7 @@ extern const struct Curl_handler Curl_handler_pop3s;
 
 /* This function scans the body after the end-of-body and writes everything
  * until the end is found */
-CURLcode Curl_pop3_write(struct Curl_easy *data, char *str, size_t nread);
+CURLcode Curl_pop3_write(struct Curl_easy *data,
+                         const char *str, size_t nread);
 
 #endif /* HEADER_CURL_POP3_H */
diff --git a/vendor/curl/lib/progress.c b/vendor/curl/lib/progress.c
index 6092b782c7..d05fcc3ebd 100644
--- a/vendor/curl/lib/progress.c
+++ b/vendor/curl/lib/progress.c
@@ -174,10 +174,18 @@ void Curl_pgrsTimeWas(struct Curl_easy *data, timerid timer,
     data->progress.t_startop = timestamp;
     break;
   case TIMER_STARTSINGLE:
-    /* This is set at the start of each single fetch */
+    /* This is set at the start of each single transfer */
     data->progress.t_startsingle = timestamp;
     data->progress.is_t_startransfer_set = false;
     break;
+  case TIMER_POSTQUEUE:
+    /* Set when the transfer starts (after potentially having been brought
+       back from the waiting queue). It needs to count from t_startop and not
+       t_startsingle since the latter is reset when a connection is brought
+       back from the pending queue. */
+    data->progress.t_postqueue =
+      Curl_timediff_us(timestamp, data->progress.t_startop);
+    break;
   case TIMER_STARTACCEPT:
     data->progress.t_acceptdata = timestamp;
     break;
@@ -304,7 +312,7 @@ timediff_t Curl_pgrsLimitWaitTime(curl_off_t cursize,
    * 'actual' is the time in milliseconds it took to actually download the
    * last 'size' bytes.
    */
-  actual = Curl_timediff(now, start);
+  actual = Curl_timediff_ceil(now, start);
   if(actual < minimum) {
     /* if it downloaded the data faster than the limit, make it wait the
        difference */
@@ -317,9 +325,10 @@ timediff_t Curl_pgrsLimitWaitTime(curl_off_t cursize,
 /*
  * Set the number of downloaded bytes so far.
  */
-void Curl_pgrsSetDownloadCounter(struct Curl_easy *data, curl_off_t size)
+CURLcode Curl_pgrsSetDownloadCounter(struct Curl_easy *data, curl_off_t size)
 {
   data->progress.downloaded = size;
+  return CURLE_OK;
 }
 
 /*
diff --git a/vendor/curl/lib/progress.h b/vendor/curl/lib/progress.h
index 0049cd04be..73749419ad 100644
--- a/vendor/curl/lib/progress.h
+++ b/vendor/curl/lib/progress.h
@@ -30,7 +30,8 @@
 typedef enum {
   TIMER_NONE,
   TIMER_STARTOP,
-  TIMER_STARTSINGLE,
+  TIMER_STARTSINGLE, /* start of transfer, might get queued */
+  TIMER_POSTQUEUE,   /* start, immediately after dequeue */
   TIMER_NAMELOOKUP,
   TIMER_CONNECT,
   TIMER_APPCONNECT,
@@ -46,7 +47,10 @@ int Curl_pgrsDone(struct Curl_easy *data);
 void Curl_pgrsStartNow(struct Curl_easy *data);
 void Curl_pgrsSetDownloadSize(struct Curl_easy *data, curl_off_t size);
 void Curl_pgrsSetUploadSize(struct Curl_easy *data, curl_off_t size);
-void Curl_pgrsSetDownloadCounter(struct Curl_easy *data, curl_off_t size);
+
+/* It is fine to not check the return code if 'size' is set to 0 */
+CURLcode Curl_pgrsSetDownloadCounter(struct Curl_easy *data, curl_off_t size);
+
 void Curl_pgrsSetUploadCounter(struct Curl_easy *data, curl_off_t size);
 void Curl_ratelimit(struct Curl_easy *data, struct curltime now);
 int Curl_pgrsUpdate(struct Curl_easy *data);
diff --git a/vendor/curl/lib/rand.c b/vendor/curl/lib/rand.c
index a5620ea6eb..c62b1a4032 100644
--- a/vendor/curl/lib/rand.c
+++ b/vendor/curl/lib/rand.c
@@ -24,16 +24,14 @@
 
 #include "curl_setup.h"
 
+#include 
+
 #ifdef HAVE_FCNTL_H
 #include 
 #endif
 #ifdef HAVE_ARPA_INET_H
 #include 
 #endif
-#ifdef HAVE_ARC4RANDOM
-/* Some platforms might have the prototype missing (ubuntu + libressl) */
-uint32_t arc4random(void);
-#endif
 
 #include 
 #include "urldata.h"
@@ -41,20 +39,16 @@ uint32_t arc4random(void);
 #include "sendf.h"
 #include "timeval.h"
 #include "rand.h"
+#include "escape.h"
 
 /* The last 3 #include files should be in this order */
 #include "curl_printf.h"
 #include "curl_memory.h"
 #include "memdebug.h"
 
-#ifdef WIN32
-
-#if defined(__MINGW32__) && !defined(__MINGW64_VERSION_MAJOR)
-#  define HAVE_MINGW_ORIGINAL
-#endif
+#ifdef _WIN32
 
-#if defined(_WIN32_WINNT) && _WIN32_WINNT >= 0x600 && \
-  !defined(HAVE_MINGW_ORIGINAL)
+#if defined(_WIN32_WINNT) && _WIN32_WINNT >= 0x600
 #  define HAVE_WIN_BCRYPTGENRANDOM
 #  include 
 #  ifdef _MSC_VER
@@ -107,7 +101,6 @@ CURLcode Curl_win32_random(unsigned char *entropy, size_t length)
 
 static CURLcode randit(struct Curl_easy *data, unsigned int *rnd)
 {
-  unsigned int r;
   CURLcode result = CURLE_OK;
   static unsigned int randseed;
   static bool seeded = FALSE;
@@ -140,7 +133,7 @@ static CURLcode randit(struct Curl_easy *data, unsigned int *rnd)
 
   /* ---- non-cryptographic version following ---- */
 
-#ifdef WIN32
+#ifdef _WIN32
   if(!seeded) {
     result = Curl_win32_random((unsigned char *)rnd, sizeof(*rnd));
     if(result != CURLE_NOT_BUILT_IN)
@@ -148,12 +141,14 @@ static CURLcode randit(struct Curl_easy *data, unsigned int *rnd)
   }
 #endif
 
-#ifdef HAVE_ARC4RANDOM
-  *rnd = (unsigned int)arc4random();
-  return CURLE_OK;
+#if defined(HAVE_ARC4RANDOM) && !defined(USE_OPENSSL)
+  if(!seeded) {
+    *rnd = (unsigned int)arc4random();
+    return CURLE_OK;
+  }
 #endif
 
-#if defined(RANDOM_FILE) && !defined(WIN32)
+#if defined(RANDOM_FILE) && !defined(_WIN32)
   if(!seeded) {
     /* if there's a random file to read a seed from, use it */
     int fd = open(RANDOM_FILE, O_RDONLY);
@@ -177,9 +172,12 @@ static CURLcode randit(struct Curl_easy *data, unsigned int *rnd)
     seeded = TRUE;
   }
 
-  /* Return an unsigned 32-bit pseudo-random number. */
-  r = randseed = randseed * 1103515245 + 12345;
-  *rnd = (r << 16) | ((r >> 16) & 0xFFFF);
+  {
+    unsigned int r;
+    /* Return an unsigned 32-bit pseudo-random number. */
+    r = randseed = randseed * 1103515245 + 12345;
+    *rnd = (r << 16) | ((r >> 16) & 0xFFFF);
+  }
   return CURLE_OK;
 }
 
@@ -203,7 +201,7 @@ CURLcode Curl_rand(struct Curl_easy *data, unsigned char *rnd, size_t num)
 {
   CURLcode result = CURLE_BAD_FUNCTION_ARGUMENT;
 
-  DEBUGASSERT(num > 0);
+  DEBUGASSERT(num);
 
   while(num) {
     unsigned int r;
@@ -234,9 +232,7 @@ CURLcode Curl_rand_hex(struct Curl_easy *data, unsigned char *rnd,
                        size_t num)
 {
   CURLcode result = CURLE_BAD_FUNCTION_ARGUMENT;
-  const char *hex = "0123456789abcdef";
   unsigned char buffer[128];
-  unsigned char *bufp = buffer;
   DEBUGASSERT(num > 1);
 
 #ifdef __clang_analyzer__
@@ -245,9 +241,11 @@ CURLcode Curl_rand_hex(struct Curl_easy *data, unsigned char *rnd,
   memset(buffer, 0, sizeof(buffer));
 #endif
 
-  if((num/2 >= sizeof(buffer)) || !(num&1))
+  if((num/2 >= sizeof(buffer)) || !(num&1)) {
     /* make sure it fits in the local buffer and that it is an odd number! */
+    DEBUGF(infof(data, "invalid buffer size with Curl_rand_hex"));
     return CURLE_BAD_FUNCTION_ARGUMENT;
+  }
 
   num--; /* save one for null-termination */
 
@@ -255,13 +253,37 @@ CURLcode Curl_rand_hex(struct Curl_easy *data, unsigned char *rnd,
   if(result)
     return result;
 
+  Curl_hexencode(buffer, num/2, rnd, num + 1);
+  return result;
+}
+
+/*
+ * Curl_rand_alnum() fills the 'rnd' buffer with a given 'num' size with random
+ * alphanumerical chars PLUS a null-terminating byte.
+ */
+
+static const char alnum[] =
+  "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789";
+
+CURLcode Curl_rand_alnum(struct Curl_easy *data, unsigned char *rnd,
+                         size_t num)
+{
+  CURLcode result = CURLE_OK;
+  const int alnumspace = sizeof(alnum) - 1;
+  unsigned int r;
+  DEBUGASSERT(num > 1);
+
+  num--; /* save one for null-termination */
+
   while(num) {
-    /* clang-tidy warns on this line without this comment: */
-    /* NOLINTNEXTLINE(clang-analyzer-core.UndefinedBinaryOperatorResult) */
-    *rnd++ = hex[(*bufp & 0xF0)>>4];
-    *rnd++ = hex[*bufp & 0x0F];
-    bufp++;
-    num -= 2;
+    do {
+      result = randit(data, &r);
+      if(result)
+        return result;
+    } while(r >= (UINT_MAX - UINT_MAX % alnumspace));
+
+    *rnd++ = alnum[r % alnumspace];
+    num--;
   }
   *rnd = 0;
 
diff --git a/vendor/curl/lib/rand.h b/vendor/curl/lib/rand.h
index 45ce3e7c4e..bc05239e45 100644
--- a/vendor/curl/lib/rand.h
+++ b/vendor/curl/lib/rand.h
@@ -34,7 +34,14 @@ CURLcode Curl_rand(struct Curl_easy *data, unsigned char *rnd, size_t num);
 CURLcode Curl_rand_hex(struct Curl_easy *data, unsigned char *rnd,
                        size_t num);
 
-#ifdef WIN32
+/*
+ * Curl_rand_alnum() fills the 'rnd' buffer with a given 'num' size with random
+ * alphanumerical chars PLUS a null-terminating byte.
+ */
+CURLcode Curl_rand_alnum(struct Curl_easy *data, unsigned char *rnd,
+                         size_t num);
+
+#ifdef _WIN32
 /* Random generator shared between the Schannel vtls and Curl_rand*()
    functions */
 CURLcode Curl_win32_random(unsigned char *entropy, size_t length);
diff --git a/vendor/curl/lib/rename.c b/vendor/curl/lib/rename.c
index 97a66e947e..4c88698067 100644
--- a/vendor/curl/lib/rename.c
+++ b/vendor/curl/lib/rename.c
@@ -40,7 +40,7 @@
 /* return 0 on success, 1 on error */
 int Curl_rename(const char *oldpath, const char *newpath)
 {
-#ifdef WIN32
+#ifdef _WIN32
   /* rename() on Windows doesn't overwrite, so we can't use it here.
      MoveFileEx() will overwrite and is usually atomic, however it fails
      when there are open handles to the file. */
diff --git a/vendor/curl/lib/request.c b/vendor/curl/lib/request.c
new file mode 100644
index 0000000000..26741fa6cb
--- /dev/null
+++ b/vendor/curl/lib/request.c
@@ -0,0 +1,409 @@
+/***************************************************************************
+ *                                  _   _ ____  _
+ *  Project                     ___| | | |  _ \| |
+ *                             / __| | | | |_) | |
+ *                            | (__| |_| |  _ <| |___
+ *                             \___|\___/|_| \_\_____|
+ *
+ * Copyright (C) Daniel Stenberg, , et al.
+ *
+ * This software is licensed as described in the file COPYING, which
+ * you should have received as part of this distribution. The terms
+ * are also available at https://curl.se/docs/copyright.html.
+ *
+ * You may opt to use, copy, modify, merge, publish, distribute and/or sell
+ * copies of the Software, and permit persons to whom the Software is
+ * furnished to do so, under the terms of the COPYING file.
+ *
+ * This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY
+ * KIND, either express or implied.
+ *
+ * SPDX-License-Identifier: curl
+ *
+ ***************************************************************************/
+
+#include "curl_setup.h"
+
+#include "urldata.h"
+#include "cfilters.h"
+#include "dynbuf.h"
+#include "doh.h"
+#include "multiif.h"
+#include "progress.h"
+#include "request.h"
+#include "sendf.h"
+#include "transfer.h"
+#include "url.h"
+
+/* The last 3 #include files should be in this order */
+#include "curl_printf.h"
+#include "curl_memory.h"
+#include "memdebug.h"
+
+void Curl_req_init(struct SingleRequest *req)
+{
+  memset(req, 0, sizeof(*req));
+}
+
+CURLcode Curl_req_soft_reset(struct SingleRequest *req,
+                             struct Curl_easy *data)
+{
+  CURLcode result;
+
+  req->done = FALSE;
+  req->upload_done = FALSE;
+  req->download_done = FALSE;
+  req->ignorebody = FALSE;
+  req->bytecount = 0;
+  req->writebytecount = 0;
+  req->header = TRUE; /* assume header */
+  req->headerline = 0;
+  req->headerbytecount = 0;
+  req->allheadercount =  0;
+  req->deductheadercount = 0;
+
+  result = Curl_client_start(data);
+  if(result)
+    return result;
+
+  if(!req->sendbuf_init) {
+    Curl_bufq_init2(&req->sendbuf, data->set.upload_buffer_size, 1,
+                    BUFQ_OPT_SOFT_LIMIT);
+    req->sendbuf_init = TRUE;
+  }
+  else {
+    Curl_bufq_reset(&req->sendbuf);
+    if(data->set.upload_buffer_size != req->sendbuf.chunk_size) {
+      Curl_bufq_free(&req->sendbuf);
+      Curl_bufq_init2(&req->sendbuf, data->set.upload_buffer_size, 1,
+                      BUFQ_OPT_SOFT_LIMIT);
+    }
+  }
+
+  return CURLE_OK;
+}
+
+CURLcode Curl_req_start(struct SingleRequest *req,
+                        struct Curl_easy *data)
+{
+  req->start = Curl_now();
+  return Curl_req_soft_reset(req, data);
+}
+
+static CURLcode req_flush(struct Curl_easy *data);
+
+CURLcode Curl_req_done(struct SingleRequest *req,
+                       struct Curl_easy *data, bool aborted)
+{
+  (void)req;
+  if(!aborted)
+    (void)req_flush(data);
+  Curl_client_reset(data);
+  return CURLE_OK;
+}
+
+void Curl_req_hard_reset(struct SingleRequest *req, struct Curl_easy *data)
+{
+  struct curltime t0 = {0, 0};
+
+  /* This is a bit ugly. `req->p` is a union and we assume we can
+   * free this safely without leaks. */
+  Curl_safefree(req->p.http);
+  Curl_safefree(req->newurl);
+  Curl_client_reset(data);
+  if(req->sendbuf_init)
+    Curl_bufq_reset(&req->sendbuf);
+
+#ifndef CURL_DISABLE_DOH
+  if(req->doh) {
+    Curl_close(&req->doh->probe[0].easy);
+    Curl_close(&req->doh->probe[1].easy);
+  }
+#endif
+  /* Can no longer memset() this struct as we need to keep some state */
+  req->size = -1;
+  req->maxdownload = -1;
+  req->bytecount = 0;
+  req->writebytecount = 0;
+  req->start = t0;
+  req->headerbytecount = 0;
+  req->allheadercount =  0;
+  req->deductheadercount = 0;
+  req->headerline = 0;
+  req->offset = 0;
+  req->httpcode = 0;
+  req->keepon = 0;
+  req->upgr101 = UPGR101_INIT;
+  req->timeofdoc = 0;
+  req->bodywrites = 0;
+  req->location = NULL;
+  req->newurl = NULL;
+#ifndef CURL_DISABLE_COOKIES
+  req->setcookies = 0;
+#endif
+  req->header = FALSE;
+  req->content_range = FALSE;
+  req->download_done = FALSE;
+  req->eos_written = FALSE;
+  req->eos_read = FALSE;
+  req->upload_done = FALSE;
+  req->upload_aborted = FALSE;
+  req->ignorebody = FALSE;
+  req->http_bodyless = FALSE;
+  req->chunk = FALSE;
+  req->ignore_cl = FALSE;
+  req->upload_chunky = FALSE;
+  req->getheader = FALSE;
+  req->no_body = data->set.opt_no_body;
+  req->authneg = FALSE;
+}
+
+void Curl_req_free(struct SingleRequest *req, struct Curl_easy *data)
+{
+  /* This is a bit ugly. `req->p` is a union and we assume we can
+   * free this safely without leaks. */
+  Curl_safefree(req->p.http);
+  Curl_safefree(req->newurl);
+  if(req->sendbuf_init)
+    Curl_bufq_free(&req->sendbuf);
+  Curl_client_cleanup(data);
+
+#ifndef CURL_DISABLE_DOH
+  if(req->doh) {
+    Curl_close(&req->doh->probe[0].easy);
+    Curl_close(&req->doh->probe[1].easy);
+    Curl_dyn_free(&req->doh->probe[0].serverdoh);
+    Curl_dyn_free(&req->doh->probe[1].serverdoh);
+    curl_slist_free_all(req->doh->headers);
+    Curl_safefree(req->doh);
+  }
+#endif
+}
+
+static CURLcode xfer_send(struct Curl_easy *data,
+                          const char *buf, size_t blen,
+                          size_t hds_len, size_t *pnwritten)
+{
+  CURLcode result = CURLE_OK;
+
+  *pnwritten = 0;
+#ifdef CURLDEBUG
+  {
+    /* Allow debug builds to override this logic to force short initial
+       sends
+     */
+    char *p = getenv("CURL_SMALLREQSEND");
+    if(p) {
+      size_t altsize = (size_t)strtoul(p, NULL, 10);
+      if(altsize && altsize < blen)
+        blen = altsize;
+    }
+  }
+#endif
+  /* Make sure this doesn't send more body bytes than what the max send
+     speed says. The headers do not count to the max speed. */
+  if(data->set.max_send_speed) {
+    size_t body_bytes = blen - hds_len;
+    if((curl_off_t)body_bytes > data->set.max_send_speed)
+      blen = hds_len + (size_t)data->set.max_send_speed;
+  }
+
+  result = Curl_xfer_send(data, buf, blen, pnwritten);
+  if(!result && *pnwritten) {
+    if(hds_len)
+      Curl_debug(data, CURLINFO_HEADER_OUT, (char *)buf,
+                 CURLMIN(hds_len, *pnwritten));
+    if(*pnwritten > hds_len) {
+      size_t body_len = *pnwritten - hds_len;
+      Curl_debug(data, CURLINFO_DATA_OUT, (char *)buf + hds_len, body_len);
+      data->req.writebytecount += body_len;
+      Curl_pgrsSetUploadCounter(data, data->req.writebytecount);
+    }
+  }
+  return result;
+}
+
+static CURLcode req_send_buffer_flush(struct Curl_easy *data)
+{
+  CURLcode result = CURLE_OK;
+  const unsigned char *buf;
+  size_t blen;
+
+  while(Curl_bufq_peek(&data->req.sendbuf, &buf, &blen)) {
+    size_t nwritten, hds_len = CURLMIN(data->req.sendbuf_hds_len, blen);
+    result = xfer_send(data, (const char *)buf, blen, hds_len, &nwritten);
+    if(result)
+      break;
+
+    Curl_bufq_skip(&data->req.sendbuf, nwritten);
+    if(hds_len) {
+      data->req.sendbuf_hds_len -= CURLMIN(hds_len, nwritten);
+    }
+    /* leave if we could not send all. Maybe network blocking or
+     * speed limits on transfer */
+    if(nwritten < blen)
+      break;
+  }
+  return result;
+}
+
+static CURLcode req_set_upload_done(struct Curl_easy *data)
+{
+  DEBUGASSERT(!data->req.upload_done);
+  data->req.upload_done = TRUE;
+  data->req.keepon &= ~(KEEP_SEND|KEEP_SEND_TIMED); /* we're done sending */
+
+  Curl_creader_done(data, data->req.upload_aborted);
+
+  if(data->req.upload_aborted) {
+    if(data->req.writebytecount)
+      infof(data, "abort upload after having sent %" CURL_FORMAT_CURL_OFF_T
+            " bytes", data->req.writebytecount);
+    else
+      infof(data, "abort upload");
+  }
+  else if(data->req.writebytecount)
+    infof(data, "upload completely sent off: %" CURL_FORMAT_CURL_OFF_T
+          " bytes", data->req.writebytecount);
+  else if(!data->req.download_done)
+    infof(data, Curl_creader_total_length(data)?
+                "We are completely uploaded and fine" :
+                "Request completely sent off");
+
+  return Curl_xfer_send_close(data);
+}
+
+static CURLcode req_flush(struct Curl_easy *data)
+{
+  CURLcode result;
+
+  if(!data || !data->conn)
+    return CURLE_FAILED_INIT;
+
+  if(!Curl_bufq_is_empty(&data->req.sendbuf)) {
+    result = req_send_buffer_flush(data);
+    if(result)
+      return result;
+    if(!Curl_bufq_is_empty(&data->req.sendbuf)) {
+      return CURLE_AGAIN;
+    }
+  }
+
+  if(!data->req.upload_done && data->req.eos_read &&
+     Curl_bufq_is_empty(&data->req.sendbuf)) {
+    return req_set_upload_done(data);
+  }
+  return CURLE_OK;
+}
+
+static ssize_t add_from_client(void *reader_ctx,
+                               unsigned char *buf, size_t buflen,
+                               CURLcode *err)
+{
+  struct Curl_easy *data = reader_ctx;
+  size_t nread;
+  bool eos;
+
+  *err = Curl_client_read(data, (char *)buf, buflen, &nread, &eos);
+  if(*err)
+    return -1;
+  if(eos)
+    data->req.eos_read = TRUE;
+  return (ssize_t)nread;
+}
+
+#ifndef USE_HYPER
+
+static CURLcode req_send_buffer_add(struct Curl_easy *data,
+                                    const char *buf, size_t blen,
+                                    size_t hds_len)
+{
+  CURLcode result = CURLE_OK;
+  ssize_t n;
+  n = Curl_bufq_write(&data->req.sendbuf,
+                      (const unsigned char *)buf, blen, &result);
+  if(n < 0)
+    return result;
+  /* We rely on a SOFTLIMIT on sendbuf, so it can take all data in */
+  DEBUGASSERT((size_t)n == blen);
+  data->req.sendbuf_hds_len += hds_len;
+  return CURLE_OK;
+}
+
+CURLcode Curl_req_send(struct Curl_easy *data, struct dynbuf *req)
+{
+  CURLcode result;
+  const char *buf;
+  size_t blen, nwritten;
+
+  if(!data || !data->conn)
+    return CURLE_FAILED_INIT;
+
+  buf = Curl_dyn_ptr(req);
+  blen = Curl_dyn_len(req);
+  if(!Curl_creader_total_length(data)) {
+    /* Request without body. Try to send directly from the buf given. */
+    data->req.eos_read = TRUE;
+    result = xfer_send(data, buf, blen, blen, &nwritten);
+    if(result)
+      return result;
+    buf += nwritten;
+    blen -= nwritten;
+  }
+
+  if(blen) {
+    /* Either we have a request body, or we could not send the complete
+     * request in one go. Buffer the remainder and try to add as much
+     * body bytes as room is left in the buffer. Then flush. */
+    result = req_send_buffer_add(data, buf, blen, blen);
+    if(result)
+      return result;
+
+    return Curl_req_send_more(data);
+  }
+  return CURLE_OK;
+}
+#endif /* !USE_HYPER */
+
+bool Curl_req_want_send(struct Curl_easy *data)
+{
+  return data->req.sendbuf_init && !Curl_bufq_is_empty(&data->req.sendbuf);
+}
+
+bool Curl_req_done_sending(struct Curl_easy *data)
+{
+  if(data->req.upload_done) {
+    DEBUGASSERT(Curl_bufq_is_empty(&data->req.sendbuf));
+    return TRUE;
+  }
+  return FALSE;
+}
+
+CURLcode Curl_req_send_more(struct Curl_easy *data)
+{
+  CURLcode result;
+
+  /* Fill our send buffer if more from client can be read. */
+  if(!data->req.eos_read && !Curl_bufq_is_full(&data->req.sendbuf)) {
+    ssize_t nread = Curl_bufq_sipn(&data->req.sendbuf, 0,
+                                   add_from_client, data, &result);
+    if(nread < 0 && result != CURLE_AGAIN)
+      return result;
+  }
+
+  result = req_flush(data);
+  if(result == CURLE_AGAIN)
+    result = CURLE_OK;
+
+  return result;
+}
+
+CURLcode Curl_req_abort_sending(struct Curl_easy *data)
+{
+  if(!data->req.upload_done) {
+    Curl_bufq_reset(&data->req.sendbuf);
+    data->req.upload_aborted = TRUE;
+    return req_set_upload_done(data);
+  }
+  return CURLE_OK;
+}
diff --git a/vendor/curl/lib/request.h b/vendor/curl/lib/request.h
new file mode 100644
index 0000000000..f9be6f2993
--- /dev/null
+++ b/vendor/curl/lib/request.h
@@ -0,0 +1,227 @@
+#ifndef HEADER_CURL_REQUEST_H
+#define HEADER_CURL_REQUEST_H
+/***************************************************************************
+ *                                  _   _ ____  _
+ *  Project                     ___| | | |  _ \| |
+ *                             / __| | | | |_) | |
+ *                            | (__| |_| |  _ <| |___
+ *                             \___|\___/|_| \_\_____|
+ *
+ * Copyright (C) Daniel Stenberg, , et al.
+ *
+ * This software is licensed as described in the file COPYING, which
+ * you should have received as part of this distribution. The terms
+ * are also available at https://curl.se/docs/copyright.html.
+ *
+ * You may opt to use, copy, modify, merge, publish, distribute and/or sell
+ * copies of the Software, and permit persons to whom the Software is
+ * furnished to do so, under the terms of the COPYING file.
+ *
+ * This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY
+ * KIND, either express or implied.
+ *
+ * SPDX-License-Identifier: curl
+ *
+ ***************************************************************************/
+
+/* This file is for lib internal stuff */
+
+#include "curl_setup.h"
+
+#include "bufq.h"
+
+/* forward declarations */
+struct UserDefined;
+
+enum expect100 {
+  EXP100_SEND_DATA,           /* enough waiting, just send the body now */
+  EXP100_AWAITING_CONTINUE,   /* waiting for the 100 Continue header */
+  EXP100_SENDING_REQUEST,     /* still sending the request but will wait for
+                                 the 100 header once done with the request */
+  EXP100_FAILED               /* used on 417 Expectation Failed */
+};
+
+enum upgrade101 {
+  UPGR101_INIT,               /* default state */
+  UPGR101_WS,                 /* upgrade to WebSockets requested */
+  UPGR101_H2,                 /* upgrade to HTTP/2 requested */
+  UPGR101_RECEIVED,           /* 101 response received */
+  UPGR101_WORKING             /* talking upgraded protocol */
+};
+
+
+/*
+ * Request specific data in the easy handle (Curl_easy).  Previously,
+ * these members were on the connectdata struct but since a conn struct may
+ * now be shared between different Curl_easys, we store connection-specific
+ * data here. This struct only keeps stuff that's interesting for *this*
+ * request, as it will be cleared between multiple ones
+ */
+struct SingleRequest {
+  curl_off_t size;        /* -1 if unknown at this point */
+  curl_off_t maxdownload; /* in bytes, the maximum amount of data to fetch,
+                             -1 means unlimited */
+  curl_off_t bytecount;         /* total number of bytes read */
+  curl_off_t writebytecount;    /* number of bytes written */
+
+  struct curltime start;         /* transfer started at this time */
+  unsigned int headerbytecount;  /* received server headers (not CONNECT
+                                    headers) */
+  unsigned int allheadercount;   /* all received headers (server + CONNECT) */
+  unsigned int deductheadercount; /* this amount of bytes doesn't count when
+                                     we check if anything has been transferred
+                                     at the end of a connection. We use this
+                                     counter to make only a 100 reply (without
+                                     a following second response code) result
+                                     in a CURLE_GOT_NOTHING error code */
+  int headerline;               /* counts header lines to better track the
+                                   first one */
+  curl_off_t offset;            /* possible resume offset read from the
+                                   Content-Range: header */
+  int httpversion;              /* Version in response (09, 10, 11, etc.) */
+  int httpcode;                 /* error code from the 'HTTP/1.? XXX' or
+                                   'RTSP/1.? XXX' line */
+  int keepon;
+  enum upgrade101 upgr101;      /* 101 upgrade state */
+
+  /* Client Writer stack, handles transfer- and content-encodings, protocol
+   * checks, pausing by client callbacks. */
+  struct Curl_cwriter *writer_stack;
+  /* Client Reader stack, handles transfer- and content-encodings, protocol
+   * checks, pausing by client callbacks. */
+  struct Curl_creader *reader_stack;
+  struct bufq sendbuf; /* data which needs to be send to the server */
+  size_t sendbuf_hds_len; /* amount of header bytes in sendbuf */
+  time_t timeofdoc;
+  long bodywrites;
+  char *location;   /* This points to an allocated version of the Location:
+                       header data */
+  char *newurl;     /* Set to the new URL to use when a redirect or a retry is
+                       wanted */
+
+  /* Allocated protocol-specific data. Each protocol handler makes sure this
+     points to data it needs. */
+  union {
+    struct FILEPROTO *file;
+    struct FTP *ftp;
+    struct HTTP *http;
+    struct IMAP *imap;
+    struct ldapreqinfo *ldap;
+    struct MQTT *mqtt;
+    struct POP3 *pop3;
+    struct RTSP *rtsp;
+    struct smb_request *smb;
+    struct SMTP *smtp;
+    struct SSHPROTO *ssh;
+    struct TELNET *telnet;
+  } p;
+#ifndef CURL_DISABLE_DOH
+  struct dohdata *doh; /* DoH specific data for this request */
+#endif
+#ifndef CURL_DISABLE_COOKIES
+  unsigned char setcookies;
+#endif
+  BIT(header);        /* incoming data has HTTP header */
+  BIT(done);          /* request is done, e.g. no more send/recv should
+                       * happen. This can be TRUE before `upload_done` or
+                       * `download_done` is TRUE. */
+  BIT(content_range); /* set TRUE if Content-Range: was found */
+  BIT(download_done); /* set to TRUE when download is complete */
+  BIT(eos_written);   /* iff EOS has been written to client */
+  BIT(eos_read);      /* iff EOS has been read from the client */
+  BIT(rewind_read);   /* iff reader needs rewind at next start */
+  BIT(upload_done);   /* set to TRUE when all request data has been sent */
+  BIT(upload_aborted); /* set to TRUE when upload was aborted. Will also
+                        * show `upload_done` as TRUE. */
+  BIT(ignorebody);    /* we read a response-body but we ignore it! */
+  BIT(http_bodyless); /* HTTP response status code is between 100 and 199,
+                         204 or 304 */
+  BIT(chunk);         /* if set, this is a chunked transfer-encoding */
+  BIT(ignore_cl);     /* ignore content-length */
+  BIT(upload_chunky); /* set TRUE if we are doing chunked transfer-encoding
+                         on upload */
+  BIT(getheader);    /* TRUE if header parsing is wanted */
+  BIT(no_body);      /* the response has no body */
+  BIT(authneg);      /* TRUE when the auth phase has started, which means
+                        that we are creating a request with an auth header,
+                        but it is not the final request in the auth
+                        negotiation. */
+  BIT(sendbuf_init); /* sendbuf is initialized */
+};
+
+/**
+ * Initialize the state of the request for first use.
+ */
+void Curl_req_init(struct SingleRequest *req);
+
+/**
+ * The request is about to start. Record time and do a soft reset.
+ */
+CURLcode Curl_req_start(struct SingleRequest *req,
+                        struct Curl_easy *data);
+
+/**
+ * The request may continue with a follow up. Reset
+ * members, but keep start time for overall duration calc.
+ */
+CURLcode Curl_req_soft_reset(struct SingleRequest *req,
+                             struct Curl_easy *data);
+
+/**
+ * The request is done. If not aborted, make sure that buffers are
+ * flushed to the client.
+ * @param req        the request
+ * @param data       the transfer
+ * @param aborted    TRUE iff the request was aborted/errored
+ */
+CURLcode Curl_req_done(struct SingleRequest *req,
+                       struct Curl_easy *data, bool aborted);
+
+/**
+ * Free the state of the request, not usable afterwards.
+ */
+void Curl_req_free(struct SingleRequest *req, struct Curl_easy *data);
+
+/**
+ * Hard reset the state of the request to virgin state base on
+ * transfer settings.
+ */
+void Curl_req_hard_reset(struct SingleRequest *req, struct Curl_easy *data);
+
+#ifndef USE_HYPER
+/**
+ * Send request headers. If not all could be sent
+ * they will be buffered. Use `Curl_req_flush()` to make sure
+ * bytes are really send.
+ * @param data      the transfer making the request
+ * @param buf       the complete header bytes, no body
+ * @return CURLE_OK (on blocking with *pnwritten == 0) or error.
+ */
+CURLcode Curl_req_send(struct Curl_easy *data, struct dynbuf *buf);
+
+#endif /* !USE_HYPER */
+
+/**
+ * TRUE iff the request has sent all request headers and data.
+ */
+bool Curl_req_done_sending(struct Curl_easy *data);
+
+/*
+ * Read more from client and flush all buffered request bytes.
+ * @return CURLE_OK on success or the error on the sending.
+ *         Never returns CURLE_AGAIN.
+ */
+CURLcode Curl_req_send_more(struct Curl_easy *data);
+
+/**
+ * TRUE iff the request wants to send, e.g. has buffered bytes.
+ */
+bool Curl_req_want_send(struct Curl_easy *data);
+
+/**
+ * Stop sending any more request data to the server.
+ * Will clear the send buffer and mark request sending as done.
+ */
+CURLcode Curl_req_abort_sending(struct Curl_easy *data);
+
+#endif /* HEADER_CURL_REQUEST_H */
diff --git a/vendor/curl/lib/rtsp.c b/vendor/curl/lib/rtsp.c
index ccd7264b00..1f162daa06 100644
--- a/vendor/curl/lib/rtsp.c
+++ b/vendor/curl/lib/rtsp.c
@@ -45,8 +45,8 @@
 #include "curl_memory.h"
 #include "memdebug.h"
 
-#define RTP_PKT_LENGTH(p)  ((((int)((unsigned char)((p)[2]))) << 8) | \
-                             ((int)((unsigned char)((p)[3]))))
+#define RTP_PKT_LENGTH(p) ((((unsigned int)((unsigned char)((p)[2]))) << 8) | \
+                            ((unsigned int)((unsigned char)((p)[3]))))
 
 /* protocol-specific functions set up to be called by the main engine */
 static CURLcode rtsp_do(struct Curl_easy *data, bool *done);
@@ -58,16 +58,19 @@ static int rtsp_getsock_do(struct Curl_easy *data,
                            struct connectdata *conn, curl_socket_t *socks);
 
 /*
- * Parse and write out any available RTP data.
- *
- * nread: amount of data left after k->str. will be modified if RTP
- *        data is parsed and k->str is moved up
- * readmore: whether or not the RTP parser needs more data right away
+ * Parse and write out an RTSP response.
+ * @param data     the transfer
+ * @param conn     the connection
+ * @param buf      data read from connection
+ * @param blen     amount of data in buf
+ * @param is_eos   TRUE iff this is the last write
+ * @param readmore out, TRUE iff complete buf was consumed and more data
+ *                 is needed
  */
-static CURLcode rtsp_rtp_readwrite(struct Curl_easy *data,
-                                   struct connectdata *conn,
-                                   ssize_t *nread,
-                                   bool *readmore);
+static CURLcode rtsp_rtp_write_resp(struct Curl_easy *data,
+                                    const char *buf,
+                                    size_t blen,
+                                    bool is_eos);
 
 static CURLcode rtsp_setup_connection(struct Curl_easy *data,
                                       struct connectdata *conn);
@@ -88,16 +91,16 @@ static int rtsp_getsock_do(struct Curl_easy *data, struct connectdata *conn,
 }
 
 static
-CURLcode rtp_client_write(struct Curl_easy *data, char *ptr, size_t len);
+CURLcode rtp_client_write(struct Curl_easy *data, const char *ptr, size_t len);
 static
-CURLcode rtsp_parse_transport(struct Curl_easy *data, char *transport);
+CURLcode rtsp_parse_transport(struct Curl_easy *data, const char *transport);
 
 
 /*
  * RTSP handler interface.
  */
 const struct Curl_handler Curl_handler_rtsp = {
-  "RTSP",                               /* scheme */
+  "rtsp",                               /* scheme */
   rtsp_setup_connection,                /* setup_connection */
   rtsp_do,                              /* do_it */
   rtsp_done,                            /* done */
@@ -110,7 +113,8 @@ const struct Curl_handler Curl_handler_rtsp = {
   ZERO_NULL,                            /* domore_getsock */
   ZERO_NULL,                            /* perform_getsock */
   rtsp_disconnect,                      /* disconnect */
-  rtsp_rtp_readwrite,                   /* readwrite */
+  rtsp_rtp_write_resp,                  /* write_resp */
+  ZERO_NULL,                            /* write_resp_hd */
   rtsp_conncheck,                       /* connection_check */
   ZERO_NULL,                            /* attach connection */
   PORT_RTSP,                            /* defport */
@@ -221,8 +225,6 @@ static CURLcode rtsp_do(struct Curl_easy *data, bool *done)
   Curl_RtspReq rtspreq = data->set.rtspreq;
   struct RTSP *rtsp = data->req.p.rtsp;
   struct dynbuf req_buffer;
-  curl_off_t postsize = 0; /* for ANNOUNCE and SET_PARAMETER */
-  curl_off_t putsize = 0; /* for ANNOUNCE and SET_PARAMETER */
 
   const char *p_request = NULL;
   const char *p_session_id = NULL;
@@ -237,6 +239,8 @@ static CURLcode rtsp_do(struct Curl_easy *data, bool *done)
   const char *p_userpwd = NULL;
 
   *done = TRUE;
+  /* Initialize a dynamic send buffer */
+  Curl_dyn_init(&req_buffer, DYN_RTSP_REQ_HEADER);
 
   rtsp->CSeq_sent = data->state.rtsp_next_client_CSeq;
   rtsp->CSeq_recv = 0;
@@ -306,9 +310,8 @@ static CURLcode rtsp_do(struct Curl_easy *data, bool *done)
   }
 
   if(rtspreq == RTSPREQ_RECEIVE) {
-    Curl_setup_transfer(data, FIRSTSOCKET, -1, TRUE, -1);
-
-    return result;
+    Curl_xfer_setup(data, FIRSTSOCKET, -1, TRUE, -1);
+    goto out;
   }
 
   p_session_id = data->set.str[STRING_RTSP_SESSION_ID];
@@ -316,7 +319,8 @@ static CURLcode rtsp_do(struct Curl_easy *data, bool *done)
      (rtspreq & ~(RTSPREQ_OPTIONS | RTSPREQ_DESCRIBE | RTSPREQ_SETUP))) {
     failf(data, "Refusing to issue an RTSP request [%s] without a session ID.",
           p_request);
-    return CURLE_BAD_FUNCTION_ARGUMENT;
+    result = CURLE_BAD_FUNCTION_ARGUMENT;
+    goto out;
   }
 
   /* Stream URI. Default to server '*' if not specified */
@@ -343,7 +347,8 @@ static CURLcode rtsp_do(struct Curl_easy *data, bool *done)
     else {
       failf(data,
             "Refusing to issue an RTSP SETUP without a Transport: header.");
-      return CURLE_BAD_FUNCTION_ARGUMENT;
+      result = CURLE_BAD_FUNCTION_ARGUMENT;
+      goto out;
     }
 
     p_transport = data->state.aptr.rtsp_transport;
@@ -362,9 +367,10 @@ static CURLcode rtsp_do(struct Curl_easy *data, bool *done)
       data->state.aptr.accept_encoding =
         aprintf("Accept-Encoding: %s\r\n", data->set.str[STRING_ENCODING]);
 
-      if(!data->state.aptr.accept_encoding)
-        return CURLE_OUT_OF_MEMORY;
-
+      if(!data->state.aptr.accept_encoding) {
+        result = CURLE_OUT_OF_MEMORY;
+        goto out;
+      }
       p_accept_encoding = data->state.aptr.accept_encoding;
     }
   }
@@ -386,9 +392,11 @@ static CURLcode rtsp_do(struct Curl_easy *data, bool *done)
   result = Curl_http_output_auth(data, conn, p_request, HTTPREQ_GET,
                                  p_stream_uri, FALSE);
   if(result)
-    return result;
+    goto out;
 
+#ifndef CURL_DISABLE_PROXY
   p_proxyuserpwd = data->state.aptr.proxyuserpwd;
+#endif
   p_userpwd = data->state.aptr.userpwd;
 
   /* Referrer */
@@ -420,23 +428,22 @@ static CURLcode rtsp_do(struct Curl_easy *data, bool *done)
    */
   if(Curl_checkheaders(data, STRCONST("CSeq"))) {
     failf(data, "CSeq cannot be set as a custom header.");
-    return CURLE_RTSP_CSEQ_ERROR;
+    result = CURLE_RTSP_CSEQ_ERROR;
+    goto out;
   }
   if(Curl_checkheaders(data, STRCONST("Session"))) {
     failf(data, "Session ID cannot be set as a custom header.");
-    return CURLE_BAD_FUNCTION_ARGUMENT;
+    result = CURLE_BAD_FUNCTION_ARGUMENT;
+    goto out;
   }
 
-  /* Initialize a dynamic send buffer */
-  Curl_dyn_init(&req_buffer, DYN_RTSP_REQ_HEADER);
-
   result =
     Curl_dyn_addf(&req_buffer,
                   "%s %s RTSP/1.0\r\n" /* Request Stream-URI RTSP/1.0 */
                   "CSeq: %ld\r\n", /* CSeq */
                   p_request, p_stream_uri, rtsp->CSeq_sent);
   if(result)
-    return result;
+    goto out;
 
   /*
    * Rather than do a normal alloc line, keep the session_id unformatted
@@ -445,7 +452,7 @@ static CURLcode rtsp_do(struct Curl_easy *data, bool *done)
   if(p_session_id) {
     result = Curl_dyn_addf(&req_buffer, "Session: %s\r\n", p_session_id);
     if(result)
-      return result;
+      goto out;
   }
 
   /*
@@ -477,44 +484,58 @@ static CURLcode rtsp_do(struct Curl_easy *data, bool *done)
   Curl_safefree(data->state.aptr.userpwd);
 
   if(result)
-    return result;
+    goto out;
 
   if((rtspreq == RTSPREQ_SETUP) || (rtspreq == RTSPREQ_DESCRIBE)) {
     result = Curl_add_timecondition(data, &req_buffer);
     if(result)
-      return result;
+      goto out;
   }
 
   result = Curl_add_custom_headers(data, FALSE, &req_buffer);
   if(result)
-    return result;
+    goto out;
 
   if(rtspreq == RTSPREQ_ANNOUNCE ||
      rtspreq == RTSPREQ_SET_PARAMETER ||
      rtspreq == RTSPREQ_GET_PARAMETER) {
+    curl_off_t req_clen; /* request content length */
 
     if(data->state.upload) {
-      putsize = data->state.infilesize;
+      req_clen = data->state.infilesize;
       data->state.httpreq = HTTPREQ_PUT;
-
+      result = Curl_creader_set_fread(data, req_clen);
+      if(result)
+        goto out;
     }
     else {
-      postsize = (data->state.infilesize != -1)?
-        data->state.infilesize:
-        (data->set.postfields? (curl_off_t)strlen(data->set.postfields):0);
-      data->state.httpreq = HTTPREQ_POST;
+      if(data->set.postfields) {
+        size_t plen = strlen(data->set.postfields);
+        req_clen = (curl_off_t)plen;
+        result = Curl_creader_set_buf(data, data->set.postfields, plen);
+      }
+      else if(data->state.infilesize >= 0) {
+        req_clen = data->state.infilesize;
+        result = Curl_creader_set_fread(data, req_clen);
+      }
+      else {
+        req_clen = 0;
+        result = Curl_creader_set_null(data);
+      }
+      if(result)
+        goto out;
     }
 
-    if(putsize > 0 || postsize > 0) {
+    if(req_clen > 0) {
       /* As stated in the http comments, it is probably not wise to
        * actually set a custom Content-Length in the headers */
       if(!Curl_checkheaders(data, STRCONST("Content-Length"))) {
         result =
           Curl_dyn_addf(&req_buffer,
                         "Content-Length: %" CURL_FORMAT_CURL_OFF_T"\r\n",
-                        (data->state.upload ? putsize : postsize));
+                        req_clen);
         if(result)
-          return result;
+          goto out;
       }
 
       if(rtspreq == RTSPREQ_SET_PARAMETER ||
@@ -524,7 +545,7 @@ static CURLcode rtsp_do(struct Curl_easy *data, bool *done)
                                  STRCONST("Content-Type: "
                                           "text/parameters\r\n"));
           if(result)
-            return result;
+            goto out;
         }
       }
 
@@ -534,11 +555,9 @@ static CURLcode rtsp_do(struct Curl_easy *data, bool *done)
                                  STRCONST("Content-Type: "
                                           "application/sdp\r\n"));
           if(result)
-            return result;
+            goto out;
         }
       }
-
-      data->state.expect100header = FALSE; /* RTSP posts are simple/small */
     }
     else if(rtspreq == RTSPREQ_GET_PARAMETER) {
       /* Check for an empty GET_PARAMETER (heartbeat) request */
@@ -546,31 +565,26 @@ static CURLcode rtsp_do(struct Curl_easy *data, bool *done)
       data->req.no_body = TRUE;
     }
   }
+  else {
+    result = Curl_creader_set_null(data);
+    if(result)
+      goto out;
+  }
 
-  /* RTSP never allows chunked transfer */
-  data->req.forbidchunk = TRUE;
   /* Finish the request buffer */
   result = Curl_dyn_addn(&req_buffer, STRCONST("\r\n"));
   if(result)
-    return result;
+    goto out;
 
-  if(postsize > 0) {
-    result = Curl_dyn_addn(&req_buffer, data->set.postfields,
-                           (size_t)postsize);
-    if(result)
-      return result;
-  }
+  Curl_xfer_setup(data, FIRSTSOCKET, -1, TRUE, FIRSTSOCKET);
 
   /* issue the request */
-  result = Curl_buffer_send(&req_buffer, data, data->req.p.http,
-                            &data->info.request_size, 0, FIRSTSOCKET);
+  result = Curl_req_send(data, &req_buffer);
   if(result) {
     failf(data, "Failed sending RTSP request");
-    return result;
+    goto out;
   }
 
-  Curl_setup_transfer(data, FIRSTSOCKET, -1, TRUE, putsize?FIRSTSOCKET:-1);
-
   /* Increment the CSeq on success */
   data->state.rtsp_next_client_CSeq++;
 
@@ -581,157 +595,285 @@ static CURLcode rtsp_do(struct Curl_easy *data, bool *done)
     if(Curl_pgrsUpdate(data))
       result = CURLE_ABORTED_BY_CALLBACK;
   }
-
+out:
+  Curl_dyn_free(&req_buffer);
   return result;
 }
 
-
-static CURLcode rtsp_rtp_readwrite(struct Curl_easy *data,
-                                   struct connectdata *conn,
-                                   ssize_t *nread,
-                                   bool *readmore) {
-  struct SingleRequest *k = &data->req;
-  struct rtsp_conn *rtspc = &(conn->proto.rtspc);
-  unsigned char *rtp_channel_mask = data->state.rtp_channel_mask;
-
-  char *rtp; /* moving pointer to rtp data */
-  ssize_t rtp_dataleft; /* how much data left to parse in this round */
-  CURLcode result;
-  bool interleaved = false;
-  size_t skip_size = 0;
-
-  if(Curl_dyn_len(&rtspc->buf)) {
-    /* There was some leftover data the last time. Append new buffers */
-    if(Curl_dyn_addn(&rtspc->buf, k->str, *nread))
-      return CURLE_OUT_OF_MEMORY;
-    rtp = Curl_dyn_ptr(&rtspc->buf);
-    rtp_dataleft = Curl_dyn_len(&rtspc->buf);
+/**
+ * write any BODY bytes missing to the client, ignore the rest.
+ */
+static CURLcode rtp_write_body_junk(struct Curl_easy *data,
+                                    const char *buf,
+                                    size_t blen)
+{
+  struct rtsp_conn *rtspc = &(data->conn->proto.rtspc);
+  curl_off_t body_remain;
+  bool in_body;
+
+  in_body = (data->req.headerline && !rtspc->in_header) &&
+            (data->req.size >= 0) &&
+            (data->req.bytecount < data->req.size);
+  body_remain = in_body? (data->req.size - data->req.bytecount) : 0;
+  DEBUGASSERT(body_remain >= 0);
+  if(body_remain) {
+    if((curl_off_t)blen > body_remain)
+      blen = (size_t)body_remain;
+    return Curl_client_write(data, CLIENTWRITE_BODY, (char *)buf, blen);
   }
-  else {
-    /* Just parse the request buffer directly */
-    rtp = k->str;
-    rtp_dataleft = *nread;
-  }
-
-  while(rtp_dataleft > 0) {
-    if(rtp[0] == '$') {
-      if(rtp_dataleft > 4) {
-        unsigned char rtp_channel;
-        int rtp_length;
-        int idx;
-        int off;
-
-        /* Parse the header */
-        /* The channel identifier immediately follows and is 1 byte */
-        rtp_channel = (unsigned char)rtp[1];
-        idx = rtp_channel / 8;
-        off = rtp_channel % 8;
-        if(!(rtp_channel_mask[idx] & (1 << off))) {
-          /* invalid channel number, maybe not an RTP packet */
-          rtp++;
-          rtp_dataleft--;
-          skip_size++;
-          continue;
+  return CURLE_OK;
+}
+
+static CURLcode rtsp_filter_rtp(struct Curl_easy *data,
+                                     const char *buf,
+                                     size_t blen,
+                                     size_t *pconsumed)
+{
+  struct rtsp_conn *rtspc = &(data->conn->proto.rtspc);
+  CURLcode result = CURLE_OK;
+  size_t skip_len = 0;
+
+  *pconsumed = 0;
+  while(blen) {
+    bool in_body = (data->req.headerline && !rtspc->in_header) &&
+                   (data->req.size >= 0) &&
+                   (data->req.bytecount < data->req.size);
+    switch(rtspc->state) {
+
+    case RTP_PARSE_SKIP: {
+      DEBUGASSERT(Curl_dyn_len(&rtspc->buf) == 0);
+      while(blen && buf[0] != '$') {
+        if(!in_body && buf[0] == 'R' &&
+           data->set.rtspreq != RTSPREQ_RECEIVE) {
+          if(strncmp(buf, "RTSP/", (blen < 5) ? blen : 5) == 0) {
+            /* This could be the next response, no consume and return */
+            if(*pconsumed) {
+              DEBUGF(infof(data, "RTP rtsp_filter_rtp[SKIP] RTSP/ prefix, "
+                           "skipping %zd bytes of junk", *pconsumed));
+            }
+            rtspc->state = RTP_PARSE_SKIP;
+            rtspc->in_header = TRUE;
+            goto out;
+          }
         }
-        if(skip_size > 0) {
-          DEBUGF(infof(data, "Skip the malformed interleaved data %lu "
-                       "bytes", skip_size));
+        /* junk/BODY, consume without buffering */
+        *pconsumed += 1;
+        ++buf;
+        --blen;
+        ++skip_len;
+      }
+      if(blen && buf[0] == '$') {
+        /* possible start of an RTP message, buffer */
+        if(skip_len) {
+          /* end of junk/BODY bytes, flush */
+          result = rtp_write_body_junk(data,
+                                       (char *)(buf - skip_len), skip_len);
+          skip_len = 0;
+          if(result)
+            goto out;
         }
-        skip_size = 0;
-        rtspc->rtp_channel = rtp_channel;
-
-        /* The length is two bytes */
-        rtp_length = RTP_PKT_LENGTH(rtp);
+        if(Curl_dyn_addn(&rtspc->buf, buf, 1)) {
+          result = CURLE_OUT_OF_MEMORY;
+          goto out;
+        }
+        *pconsumed += 1;
+        ++buf;
+        --blen;
+        rtspc->state = RTP_PARSE_CHANNEL;
+      }
+      break;
+    }
 
-        if(rtp_dataleft < rtp_length + 4) {
-          /* Need more - incomplete payload */
-          *readmore = TRUE;
-          break;
+    case RTP_PARSE_CHANNEL: {
+      int idx = ((unsigned char)buf[0]) / 8;
+      int off = ((unsigned char)buf[0]) % 8;
+      DEBUGASSERT(Curl_dyn_len(&rtspc->buf) == 1);
+      if(!(data->state.rtp_channel_mask[idx] & (1 << off))) {
+        /* invalid channel number, junk or BODY data */
+        rtspc->state = RTP_PARSE_SKIP;
+        DEBUGASSERT(skip_len == 0);
+        /* we do not consume this byte, it is BODY data */
+        DEBUGF(infof(data, "RTSP: invalid RTP channel %d, skipping", idx));
+        if(*pconsumed == 0) {
+          /* We did not consume the initial '$' in our buffer, but had
+           * it from an earlier call. We cannot un-consume it and have
+           * to write it directly as BODY data */
+          result = rtp_write_body_junk(data, Curl_dyn_ptr(&rtspc->buf), 1);
+          if(result)
+            goto out;
         }
-        interleaved = true;
-        /* We have the full RTP interleaved packet
-         * Write out the header including the leading '$' */
-        DEBUGF(infof(data, "RTP write channel %d rtp_length %d",
-                     rtspc->rtp_channel, rtp_length));
-        result = rtp_client_write(data, &rtp[0], rtp_length + 4);
-        if(result) {
-          *readmore = FALSE;
-          return result;
+        else {
+          /* count the '$' as skip and continue */
+          skip_len = 1;
         }
+        Curl_dyn_free(&rtspc->buf);
+        break;
+      }
+      /* a valid channel, so we expect this to be a real RTP message */
+      rtspc->rtp_channel = (unsigned char)buf[0];
+      if(Curl_dyn_addn(&rtspc->buf, buf, 1)) {
+        result = CURLE_OUT_OF_MEMORY;
+        goto out;
+      }
+      *pconsumed += 1;
+      ++buf;
+      --blen;
+      rtspc->state = RTP_PARSE_LEN;
+      break;
+    }
 
-        /* Move forward in the buffer */
-        rtp_dataleft -= rtp_length + 4;
-        rtp += rtp_length + 4;
+    case RTP_PARSE_LEN: {
+      size_t rtp_len = Curl_dyn_len(&rtspc->buf);
+      const char *rtp_buf;
+      DEBUGASSERT(rtp_len >= 2 && rtp_len < 4);
+      if(Curl_dyn_addn(&rtspc->buf, buf, 1)) {
+        result = CURLE_OUT_OF_MEMORY;
+        goto out;
+      }
+      *pconsumed += 1;
+      ++buf;
+      --blen;
+      if(rtp_len == 2)
+        break;
+      rtp_buf = Curl_dyn_ptr(&rtspc->buf);
+      rtspc->rtp_len = RTP_PKT_LENGTH(rtp_buf) + 4;
+      rtspc->state = RTP_PARSE_DATA;
+      break;
+    }
 
-        if(data->set.rtspreq == RTSPREQ_RECEIVE) {
-          /* If we are in a passive receive, give control back
-           * to the app as often as we can.
-           */
-          k->keepon &= ~KEEP_RECV;
+    case RTP_PARSE_DATA: {
+      size_t rtp_len = Curl_dyn_len(&rtspc->buf);
+      size_t needed;
+      DEBUGASSERT(rtp_len < rtspc->rtp_len);
+      needed = rtspc->rtp_len - rtp_len;
+      if(needed <= blen) {
+        if(Curl_dyn_addn(&rtspc->buf, buf, needed)) {
+          result = CURLE_OUT_OF_MEMORY;
+          goto out;
         }
+        *pconsumed += needed;
+        buf += needed;
+        blen -= needed;
+        /* complete RTP message in buffer */
+        DEBUGF(infof(data, "RTP write channel %d rtp_len %zu",
+                     rtspc->rtp_channel, rtspc->rtp_len));
+        result = rtp_client_write(data, Curl_dyn_ptr(&rtspc->buf),
+                                  rtspc->rtp_len);
+        Curl_dyn_free(&rtspc->buf);
+        rtspc->state = RTP_PARSE_SKIP;
+        if(result)
+          goto out;
       }
       else {
-        /* Need more - incomplete header */
-        *readmore = TRUE;
-        break;
-      }
-    }
-    else {
-      /* If the following data begins with 'RTSP/', which might be an RTSP
-         message, we should stop skipping the data. */
-      /* If `k-> headerline> 0 && !interleaved` is true, we are maybe in the
-         middle of an RTSP message. It is difficult to determine this, so we
-         stop skipping. */
-      size_t prefix_len = (rtp_dataleft < 5) ? rtp_dataleft : 5;
-      if((k->headerline > 0 && !interleaved) ||
-         strncmp(rtp, "RTSP/", prefix_len) == 0) {
-        if(skip_size > 0) {
-          DEBUGF(infof(data, "Skip the malformed interleaved data %lu "
-                       "bytes", skip_size));
+        if(Curl_dyn_addn(&rtspc->buf, buf, blen)) {
+          result = CURLE_OUT_OF_MEMORY;
+          goto out;
         }
-        break; /* maybe is an RTSP message */
+        *pconsumed += blen;
+        buf += blen;
+        blen = 0;
       }
-      /* Skip incorrect data util the next RTP packet or RTSP message */
-      do {
-        rtp++;
-        rtp_dataleft--;
-        skip_size++;
-      } while(rtp_dataleft > 0 && rtp[0] != '$' && rtp[0] != 'R');
+      break;
+    }
+
+    default:
+      DEBUGASSERT(0);
+      return CURLE_RECV_ERROR;
     }
   }
+out:
+  if(!result && skip_len)
+    result = rtp_write_body_junk(data, (char *)(buf - skip_len), skip_len);
+  return result;
+}
 
-  if(rtp_dataleft && rtp[0] == '$') {
-    DEBUGF(infof(data, "RTP Rewinding %zd %s", rtp_dataleft,
-                 *readmore ? "(READMORE)" : ""));
+static CURLcode rtsp_rtp_write_resp(struct Curl_easy *data,
+                                    const char *buf,
+                                    size_t blen,
+                                    bool is_eos)
+{
+  struct rtsp_conn *rtspc = &(data->conn->proto.rtspc);
+  CURLcode result = CURLE_OK;
+  size_t consumed = 0;
 
-    /* Store the incomplete RTP packet for a "rewind" */
-    if(!Curl_dyn_len(&rtspc->buf)) {
-      /* nothing was stored, add this data */
-      if(Curl_dyn_addn(&rtspc->buf, rtp, rtp_dataleft))
-        return CURLE_OUT_OF_MEMORY;
-    }
-    else {
-      /* keep the remainder */
-      Curl_dyn_tail(&rtspc->buf, rtp_dataleft);
-    }
+  if(!data->req.header)
+    rtspc->in_header = FALSE;
+  if(!blen) {
+    goto out;
+  }
 
-    /* As far as the transfer is concerned, this data is consumed */
-    *nread = 0;
-    return CURLE_OK;
+  DEBUGF(infof(data, "rtsp_rtp_write_resp(len=%zu, in_header=%d, eos=%d)",
+               blen, rtspc->in_header, is_eos));
+
+  /* If header parsing is not ongoing, extract RTP messages */
+  if(!rtspc->in_header) {
+    result = rtsp_filter_rtp(data, buf, blen, &consumed);
+    if(result)
+      goto out;
+    buf += consumed;
+    blen -= consumed;
+    /* either we consumed all or are at the start of header parsing */
+    if(blen && !data->req.header)
+      DEBUGF(infof(data, "RTSP: %zu bytes, possibly excess in response body",
+                   blen));
   }
-  /* Fix up k->str to point just after the last RTP packet */
-  k->str += *nread - rtp_dataleft;
 
-  *nread = rtp_dataleft;
+  /* we want to parse headers, do so */
+  if(data->req.header && blen) {
+    rtspc->in_header = TRUE;
+    result = Curl_http_write_resp_hds(data, buf, blen, &consumed);
+    if(result)
+      goto out;
 
-  /* If we get here, we have finished with the leftover/merge buffer */
-  Curl_dyn_free(&rtspc->buf);
+    buf += consumed;
+    blen -= consumed;
 
-  return CURLE_OK;
+    if(!data->req.header)
+      rtspc->in_header = FALSE;
+
+    if(!rtspc->in_header) {
+      /* If header parsing is done, extract interleaved RTP messages */
+      if(data->req.size <= -1) {
+        /* Respect section 4.4 of rfc2326: If the Content-Length header is
+           absent, a length 0 must be assumed. */
+        data->req.size = 0;
+        data->req.download_done = TRUE;
+      }
+      result = rtsp_filter_rtp(data, buf, blen, &consumed);
+      if(result)
+        goto out;
+      blen -= consumed;
+    }
+  }
+
+  if(rtspc->state != RTP_PARSE_SKIP)
+    data->req.done = FALSE;
+  /* we SHOULD have consumed all bytes, unless the response is borked.
+   * In which case we write out the left over bytes, letting the client
+   * writer deal with it (it will report EXCESS and fail the transfer). */
+  DEBUGF(infof(data, "rtsp_rtp_write_resp(len=%zu, in_header=%d, done=%d "
+               " rtspc->state=%d, req.size=%" CURL_FORMAT_CURL_OFF_T ")",
+               blen, rtspc->in_header, data->req.done, rtspc->state,
+               data->req.size));
+  if(!result && (is_eos || blen)) {
+    result = Curl_client_write(data, CLIENTWRITE_BODY|
+                               (is_eos? CLIENTWRITE_EOS:0),
+                               (char *)buf, blen);
+  }
+
+out:
+  if((data->set.rtspreq == RTSPREQ_RECEIVE) &&
+     (rtspc->state == RTP_PARSE_SKIP)) {
+    /* In special mode RECEIVE, we just process one chunk of network
+     * data, so we stop the transfer here, if we have no incomplete
+     * RTP message pending. */
+    data->req.download_done = TRUE;
+  }
+  return result;
 }
 
 static
-CURLcode rtp_client_write(struct Curl_easy *data, char *ptr, size_t len)
+CURLcode rtp_client_write(struct Curl_easy *data, const char *ptr, size_t len)
 {
   size_t wrote;
   curl_write_callback writeit;
@@ -756,7 +898,7 @@ CURLcode rtp_client_write(struct Curl_easy *data, char *ptr, size_t len)
   }
 
   Curl_set_in_callback(data, true);
-  wrote = writeit(ptr, 1, len, user_ptr);
+  wrote = writeit((char *)ptr, 1, len, user_ptr);
   Curl_set_in_callback(data, false);
 
   if(CURL_WRITEFUNC_PAUSE == wrote) {
@@ -772,12 +914,12 @@ CURLcode rtp_client_write(struct Curl_easy *data, char *ptr, size_t len)
   return CURLE_OK;
 }
 
-CURLcode Curl_rtsp_parseheader(struct Curl_easy *data, char *header)
+CURLcode Curl_rtsp_parseheader(struct Curl_easy *data, const char *header)
 {
   if(checkprefix("CSeq:", header)) {
     long CSeq = 0;
     char *endp;
-    char *p = &header[5];
+    const char *p = &header[5];
     while(ISBLANK(*p))
       p++;
     CSeq = strtol(p, &endp, 10);
@@ -792,8 +934,7 @@ CURLcode Curl_rtsp_parseheader(struct Curl_easy *data, char *header)
     }
   }
   else if(checkprefix("Session:", header)) {
-    char *start;
-    char *end;
+    const char *start, *end;
     size_t idlen;
 
     /* Find the first non-space letter */
@@ -821,7 +962,7 @@ CURLcode Curl_rtsp_parseheader(struct Curl_easy *data, char *header)
 
       /* If the Session ID is set, then compare */
       if(strlen(data->set.str[STRING_RTSP_SESSION_ID]) != idlen ||
-         strncmp(start, data->set.str[STRING_RTSP_SESSION_ID], idlen) != 0) {
+         strncmp(start, data->set.str[STRING_RTSP_SESSION_ID], idlen)) {
         failf(data, "Got RTSP Session ID Line [%s], but wanted ID [%s]",
               start, data->set.str[STRING_RTSP_SESSION_ID]);
         return CURLE_RTSP_SESSION_ERROR;
@@ -833,11 +974,9 @@ CURLcode Curl_rtsp_parseheader(struct Curl_easy *data, char *header)
        */
 
       /* Copy the id substring into a new buffer */
-      data->set.str[STRING_RTSP_SESSION_ID] = malloc(idlen + 1);
+      data->set.str[STRING_RTSP_SESSION_ID] = Curl_memdup0(start, idlen);
       if(!data->set.str[STRING_RTSP_SESSION_ID])
         return CURLE_OUT_OF_MEMORY;
-      memcpy(data->set.str[STRING_RTSP_SESSION_ID], start, idlen);
-      (data->set.str[STRING_RTSP_SESSION_ID])[idlen] = '\0';
     }
   }
   else if(checkprefix("Transport:", header)) {
@@ -850,14 +989,13 @@ CURLcode Curl_rtsp_parseheader(struct Curl_easy *data, char *header)
 }
 
 static
-CURLcode rtsp_parse_transport(struct Curl_easy *data, char *transport)
+CURLcode rtsp_parse_transport(struct Curl_easy *data, const char *transport)
 {
   /* If we receive multiple Transport response-headers, the linterleaved
      channels of each response header is recorded and used together for
      subsequent data validity checks.*/
   /* e.g.: ' RTP/AVP/TCP;unicast;interleaved=5-6' */
-  char *start;
-  char *end;
+  const char *start, *end;
   start = transport;
   while(start && *start) {
     while(*start && ISBLANK(*start) )
@@ -866,7 +1004,7 @@ CURLcode rtsp_parse_transport(struct Curl_easy *data, char *transport)
     if(checkprefix("interleaved=", start)) {
       long chan1, chan2, chan;
       char *endp;
-      char *p = start + 12;
+      const char *p = start + 12;
       chan1 = strtol(p, &endp, 10);
       if(p != endp && chan1 >= 0 && chan1 <= 255) {
         unsigned char *rtp_channel_mask = data->state.rtp_channel_mask;
diff --git a/vendor/curl/lib/rtsp.h b/vendor/curl/lib/rtsp.h
index 111bac2a61..b1ffa5c7ea 100644
--- a/vendor/curl/lib/rtsp.h
+++ b/vendor/curl/lib/rtsp.h
@@ -31,7 +31,7 @@
 
 extern const struct Curl_handler Curl_handler_rtsp;
 
-CURLcode Curl_rtsp_parseheader(struct Curl_easy *data, char *header);
+CURLcode Curl_rtsp_parseheader(struct Curl_easy *data, const char *header);
 
 #else
 /* disabled */
@@ -39,6 +39,12 @@ CURLcode Curl_rtsp_parseheader(struct Curl_easy *data, char *header);
 
 #endif /* CURL_DISABLE_RTSP */
 
+typedef enum {
+  RTP_PARSE_SKIP,
+  RTP_PARSE_CHANNEL,
+  RTP_PARSE_LEN,
+  RTP_PARSE_DATA
+} rtp_parse_st;
 /*
  * RTSP Connection data
  *
@@ -47,6 +53,9 @@ CURLcode Curl_rtsp_parseheader(struct Curl_easy *data, char *header);
 struct rtsp_conn {
   struct dynbuf buf;
   int rtp_channel;
+  size_t rtp_len;
+  rtp_parse_st state;
+  BIT(in_header);
 };
 
 /****************************************************************************
diff --git a/vendor/curl/lib/select.c b/vendor/curl/lib/select.c
index cae9beb6c7..d92e745a7f 100644
--- a/vendor/curl/lib/select.c
+++ b/vendor/curl/lib/select.c
@@ -76,7 +76,7 @@ int Curl_wait_ms(timediff_t timeout_ms)
   }
 #if defined(MSDOS)
   delay(timeout_ms);
-#elif defined(WIN32)
+#elif defined(_WIN32)
   /* prevent overflow, timeout_ms is typecast to ULONG/DWORD. */
 #if TIMEDIFF_T_MAX >= ULONG_MAX
   if(timeout_ms >= ULONG_MAX)
diff --git a/vendor/curl/lib/sendf.c b/vendor/curl/lib/sendf.c
index d79ad08fa5..68a8bf3b6a 100644
--- a/vendor/curl/lib/sendf.c
+++ b/vendor/curl/lib/sendf.c
@@ -40,6 +40,8 @@
 #include "sendf.h"
 #include "cfilters.h"
 #include "connect.h"
+#include "content_encoding.h"
+#include "cw-out.h"
 #include "vtls/vtls.h"
 #include "vssh/ssh.h"
 #include "easyif.h"
@@ -48,7 +50,8 @@
 #include "select.h"
 #include "strdup.h"
 #include "http2.h"
-#include "headers.h"
+#include "progress.h"
+#include "warnless.h"
 #include "ws.h"
 
 /* The last 3 #include files should be in this order */
@@ -56,384 +59,1320 @@
 #include "curl_memory.h"
 #include "memdebug.h"
 
-#if defined(CURL_DO_LINEEND_CONV) && !defined(CURL_DISABLE_FTP)
-/*
- * convert_lineends() changes CRLF (\r\n) end-of-line markers to a single LF
- * (\n), with special processing for CRLF sequences that are split between two
- * blocks of data.  Remaining, bare CRs are changed to LFs.  The possibly new
- * size of the data is returned.
+
+static CURLcode do_init_writer_stack(struct Curl_easy *data);
+
+/* Curl_client_write() sends data to the write callback(s)
+
+   The bit pattern defines to what "streams" to write to. Body and/or header.
+   The defines are in sendf.h of course.
  */
-static size_t convert_lineends(struct Curl_easy *data,
-                               char *startPtr, size_t size)
-{
-  char *inPtr, *outPtr;
-
-  /* sanity check */
-  if(!startPtr || (size < 1)) {
-    return size;
-  }
-
-  if(data->state.prev_block_had_trailing_cr) {
-    /* The previous block of incoming data
-       had a trailing CR, which was turned into a LF. */
-    if(*startPtr == '\n') {
-      /* This block of incoming data starts with the
-         previous block's LF so get rid of it */
-      memmove(startPtr, startPtr + 1, size-1);
-      size--;
-      /* and it wasn't a bare CR but a CRLF conversion instead */
-      data->state.crlf_conversions++;
-    }
-    data->state.prev_block_had_trailing_cr = FALSE; /* reset the flag */
-  }
-
-  /* find 1st CR, if any */
-  inPtr = outPtr = memchr(startPtr, '\r', size);
-  if(inPtr) {
-    /* at least one CR, now look for CRLF */
-    while(inPtr < (startPtr + size-1)) {
-      /* note that it's size-1, so we'll never look past the last byte */
-      if(memcmp(inPtr, "\r\n", 2) == 0) {
-        /* CRLF found, bump past the CR and copy the NL */
-        inPtr++;
-        *outPtr = *inPtr;
-        /* keep track of how many CRLFs we converted */
-        data->state.crlf_conversions++;
-      }
-      else {
-        if(*inPtr == '\r') {
-          /* lone CR, move LF instead */
-          *outPtr = '\n';
-        }
-        else {
-          /* not a CRLF nor a CR, just copy whatever it is */
-          *outPtr = *inPtr;
-        }
-      }
-      outPtr++;
-      inPtr++;
-    } /* end of while loop */
-
-    if(inPtr < startPtr + size) {
-      /* handle last byte */
-      if(*inPtr == '\r') {
-        /* deal with a CR at the end of the buffer */
-        *outPtr = '\n'; /* copy a NL instead */
-        /* note that a CRLF might be split across two blocks */
-        data->state.prev_block_had_trailing_cr = TRUE;
-      }
-      else {
-        /* copy last byte */
-        *outPtr = *inPtr;
+CURLcode Curl_client_write(struct Curl_easy *data,
+                           int type, const char *buf, size_t blen)
+{
+  CURLcode result;
+
+  /* it is one of those, at least */
+  DEBUGASSERT(type & (CLIENTWRITE_BODY|CLIENTWRITE_HEADER|CLIENTWRITE_INFO));
+  /* BODY is only BODY (with optional EOS) */
+  DEBUGASSERT(!(type & CLIENTWRITE_BODY) ||
+              ((type & ~(CLIENTWRITE_BODY|CLIENTWRITE_EOS)) == 0));
+  /* INFO is only INFO (with optional EOS) */
+  DEBUGASSERT(!(type & CLIENTWRITE_INFO) ||
+              ((type & ~(CLIENTWRITE_INFO|CLIENTWRITE_EOS)) == 0));
+
+  if(!data->req.writer_stack) {
+    result = do_init_writer_stack(data);
+    if(result)
+      return result;
+    DEBUGASSERT(data->req.writer_stack);
+  }
+
+  result = Curl_cwriter_write(data, data->req.writer_stack, type, buf, blen);
+  CURL_TRC_WRITE(data, "client_write(type=%x, len=%zu) -> %d",
+                 type, blen, result);
+  return result;
+}
+
+static void cl_reset_writer(struct Curl_easy *data)
+{
+  struct Curl_cwriter *writer = data->req.writer_stack;
+  while(writer) {
+    data->req.writer_stack = writer->next;
+    writer->cwt->do_close(data, writer);
+    free(writer);
+    writer = data->req.writer_stack;
+  }
+}
+
+static void cl_reset_reader(struct Curl_easy *data)
+{
+  struct Curl_creader *reader = data->req.reader_stack;
+  while(reader) {
+    data->req.reader_stack = reader->next;
+    reader->crt->do_close(data, reader);
+    free(reader);
+    reader = data->req.reader_stack;
+  }
+}
+
+void Curl_client_cleanup(struct Curl_easy *data)
+{
+  cl_reset_reader(data);
+  cl_reset_writer(data);
+
+  data->req.bytecount = 0;
+  data->req.headerline = 0;
+}
+
+void Curl_client_reset(struct Curl_easy *data)
+{
+  if(data->req.rewind_read) {
+    /* already requested */
+    CURL_TRC_READ(data, "client_reset, will rewind reader");
+  }
+  else {
+    CURL_TRC_READ(data, "client_reset, clear readers");
+    cl_reset_reader(data);
+  }
+  cl_reset_writer(data);
+
+  data->req.bytecount = 0;
+  data->req.headerline = 0;
+}
+
+CURLcode Curl_client_start(struct Curl_easy *data)
+{
+  if(data->req.rewind_read) {
+    struct Curl_creader *r = data->req.reader_stack;
+    CURLcode result = CURLE_OK;
+
+    CURL_TRC_READ(data, "client start, rewind readers");
+    while(r) {
+      result = r->crt->rewind(data, r);
+      if(result) {
+        failf(data, "rewind of client reader '%s' failed: %d",
+              r->crt->name, result);
+        return result;
       }
-      outPtr++;
+      r = r->next;
     }
-    if(outPtr < startPtr + size)
-      /* tidy up by null terminating the now shorter data */
-      *outPtr = '\0';
+    data->req.rewind_read = FALSE;
+    cl_reset_reader(data);
+  }
+  return CURLE_OK;
+}
+
+bool Curl_creader_will_rewind(struct Curl_easy *data)
+{
+  return data->req.rewind_read;
+}
+
+void Curl_creader_set_rewind(struct Curl_easy *data, bool enable)
+{
+  data->req.rewind_read = !!enable;
+}
 
-    return (outPtr - startPtr);
+/* Write data using an unencoding writer stack. */
+CURLcode Curl_cwriter_write(struct Curl_easy *data,
+                             struct Curl_cwriter *writer, int type,
+                             const char *buf, size_t nbytes)
+{
+  if(!writer)
+    return CURLE_WRITE_ERROR;
+  return writer->cwt->do_write(data, writer, type, buf, nbytes);
+}
+
+CURLcode Curl_cwriter_def_init(struct Curl_easy *data,
+                               struct Curl_cwriter *writer)
+{
+  (void)data;
+  (void)writer;
+  return CURLE_OK;
+}
+
+CURLcode Curl_cwriter_def_write(struct Curl_easy *data,
+                                struct Curl_cwriter *writer, int type,
+                                const char *buf, size_t nbytes)
+{
+  return Curl_cwriter_write(data, writer->next, type, buf, nbytes);
+}
+
+void Curl_cwriter_def_close(struct Curl_easy *data,
+                            struct Curl_cwriter *writer)
+{
+  (void) data;
+  (void) writer;
+}
+
+static size_t get_max_body_write_len(struct Curl_easy *data, curl_off_t limit)
+{
+  if(limit != -1) {
+    /* How much more are we allowed to write? */
+    curl_off_t remain_diff;
+    remain_diff = limit - data->req.bytecount;
+    if(remain_diff < 0) {
+      /* already written too much! */
+      return 0;
+    }
+#if SIZEOF_CURL_OFF_T > SIZEOF_SIZE_T
+    else if(remain_diff > SSIZE_T_MAX) {
+      return SIZE_T_MAX;
+    }
+#endif
+    else {
+      return (size_t)remain_diff;
+    }
   }
-  return size;
+  return SIZE_T_MAX;
 }
-#endif /* CURL_DO_LINEEND_CONV && !CURL_DISABLE_FTP */
 
-/*
- * Curl_nwrite() is an internal write function that sends data to the
- * server. Works with a socket index for the connection.
- *
- * If the write would block (CURLE_AGAIN), it returns CURLE_OK and
- * (*nwritten == 0). Otherwise we return regular CURLcode value.
- */
-CURLcode Curl_nwrite(struct Curl_easy *data,
-                     int sockindex,
-                     const void *buf,
-                     size_t blen,
-                     ssize_t *pnwritten)
+struct cw_download_ctx {
+  struct Curl_cwriter super;
+  BIT(started_response);
+};
+/* Download client writer in phase CURL_CW_PROTOCOL that
+ * sees the "real" download body data. */
+static CURLcode cw_download_write(struct Curl_easy *data,
+                                  struct Curl_cwriter *writer, int type,
+                                  const char *buf, size_t nbytes)
 {
-  ssize_t nwritten;
-  CURLcode result = CURLE_OK;
-  struct connectdata *conn;
+  struct cw_download_ctx *ctx = writer->ctx;
+  CURLcode result;
+  size_t nwrite, excess_len = 0;
+  bool is_connect = !!(type & CLIENTWRITE_CONNECT);
 
-  DEBUGASSERT(sockindex >= 0 && sockindex < 2);
-  DEBUGASSERT(pnwritten);
-  DEBUGASSERT(data);
-  DEBUGASSERT(data->conn);
-  conn = data->conn;
-#ifdef CURLDEBUG
-  {
-    /* Allow debug builds to override this logic to force short sends
-    */
-    char *p = getenv("CURL_SMALLSENDS");
-    if(p) {
-      size_t altsize = (size_t)strtoul(p, NULL, 10);
-      if(altsize)
-        blen = CURLMIN(blen, altsize);
+  if(!is_connect && !ctx->started_response) {
+    Curl_pgrsTime(data, TIMER_STARTTRANSFER);
+    ctx->started_response = TRUE;
+  }
+
+  if(!(type & CLIENTWRITE_BODY)) {
+    if(is_connect && data->set.suppress_connect_headers)
+      return CURLE_OK;
+    result = Curl_cwriter_write(data, writer->next, type, buf, nbytes);
+    CURL_TRC_WRITE(data, "download_write header(type=%x, blen=%zu) -> %d",
+                   type, nbytes, result);
+    return result;
+  }
+
+  /* Here, we deal with REAL BODY bytes. All filtering and transfer
+   * encodings have been applied and only the true content, e.g. BODY,
+   * bytes are passed here.
+   * This allows us to check sizes, update stats, etc. independent
+   * from the protocol in play. */
+
+  if(data->req.no_body && nbytes > 0) {
+    /* BODY arrives although we want none, bail out */
+    streamclose(data->conn, "ignoring body");
+    CURL_TRC_WRITE(data, "download_write body(type=%x, blen=%zu), "
+                   "did not want a BODY", type, nbytes);
+    data->req.download_done = TRUE;
+    if(data->info.header_size)
+      /* if headers have been received, this is fine */
+      return CURLE_OK;
+    return CURLE_WEIRD_SERVER_REPLY;
+  }
+
+  /* Determine if we see any bytes in excess to what is allowed.
+   * We write the allowed bytes and handle excess further below.
+   * This gives deterministic BODY writes on varying buffer receive
+   * lengths. */
+  nwrite = nbytes;
+  if(-1 != data->req.maxdownload) {
+    size_t wmax = get_max_body_write_len(data, data->req.maxdownload);
+    if(nwrite > wmax) {
+      excess_len = nbytes - wmax;
+      nwrite = wmax;
+    }
+
+    if(nwrite == wmax) {
+      data->req.download_done = TRUE;
     }
   }
-#endif
-  nwritten = conn->send[sockindex](data, sockindex, buf, blen, &result);
-  if(result == CURLE_AGAIN) {
-    nwritten = 0;
-    result = CURLE_OK;
+
+  /* Error on too large filesize is handled below, after writing
+   * the permitted bytes */
+  if(data->set.max_filesize) {
+    size_t wmax = get_max_body_write_len(data, data->set.max_filesize);
+    if(nwrite > wmax) {
+      nwrite = wmax;
+    }
   }
-  else if(result) {
-    nwritten = -1; /* make sure */
+
+  if(!data->req.ignorebody && (nwrite || (type & CLIENTWRITE_EOS))) {
+    result = Curl_cwriter_write(data, writer->next, type, buf, nwrite);
+    CURL_TRC_WRITE(data, "download_write body(type=%x, blen=%zu) -> %d",
+                   type, nbytes, result);
+    if(result)
+      return result;
   }
-  else {
-    DEBUGASSERT(nwritten >= 0);
+  /* Update stats, write and report progress */
+  data->req.bytecount += nwrite;
+  ++data->req.bodywrites;
+  result = Curl_pgrsSetDownloadCounter(data, data->req.bytecount);
+  if(result)
+    return result;
+
+  if(excess_len) {
+    if(!data->req.ignorebody) {
+      infof(data,
+            "Excess found writing body:"
+            " excess = %zu"
+            ", size = %" CURL_FORMAT_CURL_OFF_T
+            ", maxdownload = %" CURL_FORMAT_CURL_OFF_T
+            ", bytecount = %" CURL_FORMAT_CURL_OFF_T,
+            excess_len, data->req.size, data->req.maxdownload,
+            data->req.bytecount);
+      connclose(data->conn, "excess found in a read");
+    }
+  }
+  else if(nwrite < nbytes) {
+    failf(data, "Exceeded the maximum allowed file size "
+          "(%" CURL_FORMAT_CURL_OFF_T ") with %"
+          CURL_FORMAT_CURL_OFF_T " bytes",
+          data->set.max_filesize, data->req.bytecount);
+    return CURLE_FILESIZE_EXCEEDED;
+  }
+
+  return CURLE_OK;
+}
+
+static const struct Curl_cwtype cw_download = {
+  "protocol",
+  NULL,
+  Curl_cwriter_def_init,
+  cw_download_write,
+  Curl_cwriter_def_close,
+  sizeof(struct cw_download_ctx)
+};
+
+/* RAW client writer in phase CURL_CW_RAW that
+ * enabled tracing of raw data. */
+static CURLcode cw_raw_write(struct Curl_easy *data,
+                             struct Curl_cwriter *writer, int type,
+                             const char *buf, size_t nbytes)
+{
+  if(type & CLIENTWRITE_BODY && data->set.verbose && !data->req.ignorebody) {
+    Curl_debug(data, CURLINFO_DATA_IN, (char *)buf, nbytes);
+  }
+  return Curl_cwriter_write(data, writer->next, type, buf, nbytes);
+}
+
+static const struct Curl_cwtype cw_raw = {
+  "raw",
+  NULL,
+  Curl_cwriter_def_init,
+  cw_raw_write,
+  Curl_cwriter_def_close,
+  sizeof(struct Curl_cwriter)
+};
+
+/* Create an unencoding writer stage using the given handler. */
+CURLcode Curl_cwriter_create(struct Curl_cwriter **pwriter,
+                                   struct Curl_easy *data,
+                                   const struct Curl_cwtype *cwt,
+                                   Curl_cwriter_phase phase)
+{
+  struct Curl_cwriter *writer = NULL;
+  CURLcode result = CURLE_OUT_OF_MEMORY;
+  void *p;
+
+  DEBUGASSERT(cwt->cwriter_size >= sizeof(struct Curl_cwriter));
+  p = calloc(1, cwt->cwriter_size);
+  if(!p)
+    goto out;
+
+  writer = (struct Curl_cwriter *)p;
+  writer->cwt = cwt;
+  writer->ctx = p;
+  writer->phase = phase;
+  result = cwt->do_init(data, writer);
+
+out:
+  *pwriter = result? NULL : writer;
+  if(result)
+    free(writer);
+  return result;
+}
+
+void Curl_cwriter_free(struct Curl_easy *data,
+                             struct Curl_cwriter *writer)
+{
+  if(writer) {
+    writer->cwt->do_close(data, writer);
+    free(writer);
+  }
+}
+
+size_t Curl_cwriter_count(struct Curl_easy *data, Curl_cwriter_phase phase)
+{
+  struct Curl_cwriter *w;
+  size_t n = 0;
+
+  for(w = data->req.writer_stack; w; w = w->next) {
+    if(w->phase == phase)
+      ++n;
   }
+  return n;
+}
+
+static CURLcode do_init_writer_stack(struct Curl_easy *data)
+{
+  struct Curl_cwriter *writer;
+  CURLcode result;
 
-  *pnwritten = nwritten;
+  DEBUGASSERT(!data->req.writer_stack);
+  result = Curl_cwriter_create(&data->req.writer_stack,
+                               data, &Curl_cwt_out, CURL_CW_CLIENT);
+  if(result)
+    return result;
+
+  result = Curl_cwriter_create(&writer, data, &cw_download, CURL_CW_PROTOCOL);
+  if(result)
+    return result;
+  result = Curl_cwriter_add(data, writer);
+  if(result) {
+    Curl_cwriter_free(data, writer);
+  }
+
+  result = Curl_cwriter_create(&writer, data, &cw_raw, CURL_CW_RAW);
+  if(result)
+    return result;
+  result = Curl_cwriter_add(data, writer);
+  if(result) {
+    Curl_cwriter_free(data, writer);
+  }
   return result;
 }
 
-/*
- * Curl_write() is an internal write function that sends data to the
- * server. Works with plain sockets, SCP, SSL or kerberos.
- *
- * If the write would block (CURLE_AGAIN), we return CURLE_OK and
- * (*written == 0). Otherwise we return regular CURLcode value.
- */
-CURLcode Curl_write(struct Curl_easy *data,
-                    curl_socket_t sockfd,
-                    const void *mem,
-                    size_t len,
-                    ssize_t *written)
+CURLcode Curl_cwriter_add(struct Curl_easy *data,
+                          struct Curl_cwriter *writer)
 {
-  struct connectdata *conn;
-  int num;
+  CURLcode result;
+  struct Curl_cwriter **anchor = &data->req.writer_stack;
 
-  DEBUGASSERT(data);
-  DEBUGASSERT(data->conn);
-  conn = data->conn;
-  num = (sockfd != CURL_SOCKET_BAD && sockfd == conn->sock[SECONDARYSOCKET]);
-  return Curl_nwrite(data, num, mem, len, written);
-}
-
-static CURLcode pausewrite(struct Curl_easy *data,
-                           int type, /* what type of data */
-                           const char *ptr,
-                           size_t len)
-{
-  /* signalled to pause sending on this connection, but since we have data
-     we want to send we need to dup it to save a copy for when the sending
-     is again enabled */
-  struct SingleRequest *k = &data->req;
-  struct UrlState *s = &data->state;
-  unsigned int i;
-  bool newtype = TRUE;
-
-  Curl_conn_ev_data_pause(data, TRUE);
-
-  if(s->tempcount) {
-    for(i = 0; i< s->tempcount; i++) {
-      if(s->tempwrite[i].type == type) {
-        /* data for this type exists */
-        newtype = FALSE;
-        break;
-      }
+  if(!*anchor) {
+    result = do_init_writer_stack(data);
+    if(result)
+      return result;
+  }
+
+  /* Insert the writer as first in its phase.
+   * Skip existing writers of lower phases. */
+  while(*anchor && (*anchor)->phase < writer->phase)
+    anchor = &((*anchor)->next);
+  writer->next = *anchor;
+  *anchor = writer;
+  return CURLE_OK;
+}
+
+struct Curl_cwriter *Curl_cwriter_get_by_name(struct Curl_easy *data,
+                                              const char *name)
+{
+  struct Curl_cwriter *writer;
+  for(writer = data->req.writer_stack; writer; writer = writer->next) {
+    if(!strcmp(name, writer->cwt->name))
+      return writer;
+  }
+  return NULL;
+}
+
+struct Curl_cwriter *Curl_cwriter_get_by_type(struct Curl_easy *data,
+                                              const struct Curl_cwtype *cwt)
+{
+  struct Curl_cwriter *writer;
+  for(writer = data->req.writer_stack; writer; writer = writer->next) {
+    if(writer->cwt == cwt)
+      return writer;
+  }
+  return NULL;
+}
+
+void Curl_cwriter_remove_by_name(struct Curl_easy *data,
+                                 const char *name)
+{
+  struct Curl_cwriter **anchor = &data->req.writer_stack;
+
+  while(*anchor) {
+    if(!strcmp(name, (*anchor)->cwt->name)) {
+      struct Curl_cwriter *w = (*anchor);
+      *anchor = w->next;
+      Curl_cwriter_free(data, w);
+      continue;
     }
-    DEBUGASSERT(i < 3);
-    if(i >= 3)
-      /* There are more types to store than what fits: very bad */
-      return CURLE_OUT_OF_MEMORY;
+    anchor = &((*anchor)->next);
   }
-  else
-    i = 0;
+}
+
+bool Curl_cwriter_is_paused(struct Curl_easy *data)
+{
+  return Curl_cw_out_is_paused(data);
+}
 
-  if(newtype) {
-    /* store this information in the state struct for later use */
-    Curl_dyn_init(&s->tempwrite[i].b, DYN_PAUSE_BUFFER);
-    s->tempwrite[i].type = type;
-    s->tempcount++;
+CURLcode Curl_cwriter_unpause(struct Curl_easy *data)
+{
+  return Curl_cw_out_unpause(data);
+}
+
+CURLcode Curl_creader_read(struct Curl_easy *data,
+                           struct Curl_creader *reader,
+                           char *buf, size_t blen, size_t *nread, bool *eos)
+{
+  *nread = 0;
+  *eos = FALSE;
+  if(!reader)
+    return CURLE_READ_ERROR;
+  return reader->crt->do_read(data, reader, buf, blen, nread, eos);
+}
+
+CURLcode Curl_creader_def_init(struct Curl_easy *data,
+                               struct Curl_creader *reader)
+{
+  (void)data;
+  (void)reader;
+  return CURLE_OK;
+}
+
+void Curl_creader_def_close(struct Curl_easy *data,
+                            struct Curl_creader *reader)
+{
+  (void)data;
+  (void)reader;
+}
+
+CURLcode Curl_creader_def_read(struct Curl_easy *data,
+                               struct Curl_creader *reader,
+                               char *buf, size_t blen,
+                               size_t *nread, bool *eos)
+{
+  if(reader->next)
+    return reader->next->crt->do_read(data, reader->next, buf, blen,
+                                      nread, eos);
+  else {
+    *nread = 0;
+    *eos = FALSE;
+    return CURLE_READ_ERROR;
   }
+}
+
+bool Curl_creader_def_needs_rewind(struct Curl_easy *data,
+                                   struct Curl_creader *reader)
+{
+  (void)data;
+  (void)reader;
+  return FALSE;
+}
+
+curl_off_t Curl_creader_def_total_length(struct Curl_easy *data,
+                                         struct Curl_creader *reader)
+{
+  return reader->next?
+         reader->next->crt->total_length(data, reader->next) : -1;
+}
+
+CURLcode Curl_creader_def_resume_from(struct Curl_easy *data,
+                                      struct Curl_creader *reader,
+                                      curl_off_t offset)
+{
+  (void)data;
+  (void)reader;
+  (void)offset;
+  return CURLE_READ_ERROR;
+}
+
+CURLcode Curl_creader_def_rewind(struct Curl_easy *data,
+                                 struct Curl_creader *reader)
+{
+  (void)data;
+  (void)reader;
+  return CURLE_OK;
+}
 
-  if(Curl_dyn_addn(&s->tempwrite[i].b, (unsigned char *)ptr, len))
-    return CURLE_OUT_OF_MEMORY;
+CURLcode Curl_creader_def_unpause(struct Curl_easy *data,
+                                  struct Curl_creader *reader)
+{
+  (void)data;
+  (void)reader;
+  return CURLE_OK;
+}
 
-  /* mark the connection as RECV paused */
-  k->keepon |= KEEP_RECV_PAUSE;
+void Curl_creader_def_done(struct Curl_easy *data,
+                           struct Curl_creader *reader, int premature)
+{
+  (void)data;
+  (void)reader;
+  (void)premature;
+}
 
+struct cr_in_ctx {
+  struct Curl_creader super;
+  curl_read_callback read_cb;
+  void *cb_user_data;
+  curl_off_t total_len;
+  curl_off_t read_len;
+  CURLcode error_result;
+  BIT(seen_eos);
+  BIT(errored);
+  BIT(has_used_cb);
+};
+
+static CURLcode cr_in_init(struct Curl_easy *data, struct Curl_creader *reader)
+{
+  struct cr_in_ctx *ctx = reader->ctx;
+  (void)data;
+  ctx->read_cb = data->state.fread_func;
+  ctx->cb_user_data = data->state.in;
+  ctx->total_len = -1;
+  ctx->read_len = 0;
   return CURLE_OK;
 }
 
+/* Real client reader to installed client callbacks. */
+static CURLcode cr_in_read(struct Curl_easy *data,
+                           struct Curl_creader *reader,
+                           char *buf, size_t blen,
+                           size_t *pnread, bool *peos)
+{
+  struct cr_in_ctx *ctx = reader->ctx;
+  size_t nread;
 
-/* chop_write() writes chunks of data not larger than CURL_MAX_WRITE_SIZE via
- * client write callback(s) and takes care of pause requests from the
- * callbacks.
- */
-static CURLcode chop_write(struct Curl_easy *data,
-                           int type,
-                           char *optr,
-                           size_t olen)
-{
-  struct connectdata *conn = data->conn;
-  curl_write_callback writeheader = NULL;
-  curl_write_callback writebody = NULL;
-  char *ptr = optr;
-  size_t len = olen;
-  void *writebody_ptr = data->set.out;
-
-  if(!len)
+  /* Once we have errored, we will return the same error forever */
+  if(ctx->errored) {
+    *pnread = 0;
+    *peos = FALSE;
+    return ctx->error_result;
+  }
+  if(ctx->seen_eos) {
+    *pnread = 0;
+    *peos = TRUE;
     return CURLE_OK;
+  }
+  /* respect length limitations */
+  if(ctx->total_len >= 0) {
+    curl_off_t remain = ctx->total_len - ctx->read_len;
+    if(remain <= 0)
+      blen = 0;
+    else if(remain < (curl_off_t)blen)
+      blen = (size_t)remain;
+  }
+  nread = 0;
+  if(ctx->read_cb && blen) {
+    Curl_set_in_callback(data, true);
+    nread = ctx->read_cb(buf, 1, blen, ctx->cb_user_data);
+    Curl_set_in_callback(data, false);
+    ctx->has_used_cb = TRUE;
+  }
 
-  /* If reading is paused, append this data to the already held data for this
-     type. */
-  if(data->req.keepon & KEEP_RECV_PAUSE)
-    return pausewrite(data, type, ptr, len);
-
-  /* Determine the callback(s) to use. */
-  if(type & CLIENTWRITE_BODY) {
-#ifdef USE_WEBSOCKETS
-    if(conn->handler->protocol & (CURLPROTO_WS|CURLPROTO_WSS)) {
-      writebody = Curl_ws_writecb;
-      writebody_ptr = data;
+  switch(nread) {
+  case 0:
+    if((ctx->total_len >= 0) && (ctx->read_len < ctx->total_len)) {
+      failf(data, "client read function EOF fail, "
+            "only %"CURL_FORMAT_CURL_OFF_T"/%"CURL_FORMAT_CURL_OFF_T
+            " of needed bytes read", ctx->read_len, ctx->total_len);
+      return CURLE_READ_ERROR;
     }
-    else
-#endif
-    writebody = data->set.fwrite_func;
+    *pnread = 0;
+    *peos = TRUE;
+    ctx->seen_eos = TRUE;
+    break;
+
+  case CURL_READFUNC_ABORT:
+    failf(data, "operation aborted by callback");
+    *pnread = 0;
+    *peos = FALSE;
+    ctx->errored = TRUE;
+    ctx->error_result = CURLE_ABORTED_BY_CALLBACK;
+    return CURLE_ABORTED_BY_CALLBACK;
+
+  case CURL_READFUNC_PAUSE:
+    if(data->conn->handler->flags & PROTOPT_NONETWORK) {
+      /* protocols that work without network cannot be paused. This is
+         actually only FILE:// just now, and it can't pause since the transfer
+         isn't done using the "normal" procedure. */
+      failf(data, "Read callback asked for PAUSE when not supported");
+      return CURLE_READ_ERROR;
+    }
+    /* CURL_READFUNC_PAUSE pauses read callbacks that feed socket writes */
+    data->req.keepon |= KEEP_SEND_PAUSE; /* mark socket send as paused */
+    *pnread = 0;
+    *peos = FALSE;
+    break; /* nothing was read */
+
+  default:
+    if(nread > blen) {
+      /* the read function returned a too large value */
+      failf(data, "read function returned funny value");
+      *pnread = 0;
+      *peos = FALSE;
+      ctx->errored = TRUE;
+      ctx->error_result = CURLE_READ_ERROR;
+      return CURLE_READ_ERROR;
+    }
+    ctx->read_len += nread;
+    if(ctx->total_len >= 0)
+      ctx->seen_eos = (ctx->read_len >= ctx->total_len);
+    *pnread = nread;
+    *peos = ctx->seen_eos;
+    break;
   }
-  if((type & CLIENTWRITE_HEADER) &&
-     (data->set.fwrite_header || data->set.writeheader)) {
-    /*
-     * Write headers to the same callback or to the especially setup
-     * header callback function (added after version 7.7.1).
-     */
-    writeheader =
-      data->set.fwrite_header? data->set.fwrite_header: data->set.fwrite_func;
+  CURL_TRC_READ(data, "cr_in_read(len=%zu, total=%"CURL_FORMAT_CURL_OFF_T
+                ", read=%"CURL_FORMAT_CURL_OFF_T") -> %d, nread=%zu, eos=%d",
+                blen, ctx->total_len, ctx->read_len, CURLE_OK,
+                *pnread, *peos);
+  return CURLE_OK;
+}
+
+static bool cr_in_needs_rewind(struct Curl_easy *data,
+                               struct Curl_creader *reader)
+{
+  struct cr_in_ctx *ctx = reader->ctx;
+  (void)data;
+  return ctx->has_used_cb;
+}
+
+static curl_off_t cr_in_total_length(struct Curl_easy *data,
+                                     struct Curl_creader *reader)
+{
+  struct cr_in_ctx *ctx = reader->ctx;
+  (void)data;
+  return ctx->total_len;
+}
+
+static CURLcode cr_in_resume_from(struct Curl_easy *data,
+                                  struct Curl_creader *reader,
+                                  curl_off_t offset)
+{
+  struct cr_in_ctx *ctx = reader->ctx;
+  int seekerr = CURL_SEEKFUNC_CANTSEEK;
+
+  DEBUGASSERT(data->conn);
+  /* already started reading? */
+  if(ctx->read_len)
+    return CURLE_READ_ERROR;
+
+  if(data->set.seek_func) {
+    Curl_set_in_callback(data, true);
+    seekerr = data->set.seek_func(data->set.seek_client, offset, SEEK_SET);
+    Curl_set_in_callback(data, false);
   }
 
-  /* Chop data, write chunks. */
-  while(len) {
-    size_t chunklen = len <= CURL_MAX_WRITE_SIZE? len: CURL_MAX_WRITE_SIZE;
+  if(seekerr != CURL_SEEKFUNC_OK) {
+    curl_off_t passed = 0;
+
+    if(seekerr != CURL_SEEKFUNC_CANTSEEK) {
+      failf(data, "Could not seek stream");
+      return CURLE_READ_ERROR;
+    }
+    /* when seekerr == CURL_SEEKFUNC_CANTSEEK (can't seek to offset) */
+    do {
+      char scratch[4*1024];
+      size_t readthisamountnow =
+        (offset - passed > (curl_off_t)sizeof(scratch)) ?
+        sizeof(scratch) :
+        curlx_sotouz(offset - passed);
+      size_t actuallyread;
 
-    if(writebody) {
-      size_t wrote;
       Curl_set_in_callback(data, true);
-      wrote = writebody(ptr, 1, chunklen, writebody_ptr);
+      actuallyread = ctx->read_cb(scratch, 1, readthisamountnow,
+                                  ctx->cb_user_data);
       Curl_set_in_callback(data, false);
 
-      if(CURL_WRITEFUNC_PAUSE == wrote) {
-        if(conn->handler->flags & PROTOPT_NONETWORK) {
-          /* Protocols that work without network cannot be paused. This is
-             actually only FILE:// just now, and it can't pause since the
-             transfer isn't done using the "normal" procedure. */
-          failf(data, "Write callback asked for PAUSE when not supported");
-          return CURLE_WRITE_ERROR;
-        }
-        return pausewrite(data, type, ptr, len);
-      }
-      if(wrote != chunklen) {
-        failf(data, "Failure writing output to destination");
-        return CURLE_WRITE_ERROR;
+      passed += actuallyread;
+      if((actuallyread == 0) || (actuallyread > readthisamountnow)) {
+        /* this checks for greater-than only to make sure that the
+           CURL_READFUNC_ABORT return code still aborts */
+        failf(data, "Could only read %" CURL_FORMAT_CURL_OFF_T
+              " bytes from the input", passed);
+        return CURLE_READ_ERROR;
       }
+    } while(passed < offset);
+  }
+
+  /* now, decrease the size of the read */
+  if(ctx->total_len > 0) {
+    ctx->total_len -= offset;
+
+    if(ctx->total_len <= 0) {
+      failf(data, "File already completely uploaded");
+      return CURLE_PARTIAL_FILE;
     }
+  }
+  /* we've passed, proceed as normal */
+  return CURLE_OK;
+}
+
+static CURLcode cr_in_rewind(struct Curl_easy *data,
+                             struct Curl_creader *reader)
+{
+  struct cr_in_ctx *ctx = reader->ctx;
+
+  /* If we never invoked the callback, there is noting to rewind */
+  if(!ctx->has_used_cb)
+    return CURLE_OK;
 
-    ptr += chunklen;
-    len -= chunklen;
+  if(data->set.seek_func) {
+    int err;
+
+    Curl_set_in_callback(data, true);
+    err = (data->set.seek_func)(data->set.seek_client, 0, SEEK_SET);
+    Curl_set_in_callback(data, false);
+    CURL_TRC_READ(data, "cr_in, rewind via set.seek_func -> %d", err);
+    if(err) {
+      failf(data, "seek callback returned error %d", (int)err);
+      return CURLE_SEND_FAIL_REWIND;
+    }
   }
+  else if(data->set.ioctl_func) {
+    curlioerr err;
 
-#ifndef CURL_DISABLE_HTTP
-  /* HTTP header, but not status-line */
-  if((conn->handler->protocol & PROTO_FAMILY_HTTP) &&
-     (type & CLIENTWRITE_HEADER) && !(type & CLIENTWRITE_STATUS) ) {
-    unsigned char htype = (unsigned char)
-      (type & CLIENTWRITE_CONNECT ? CURLH_CONNECT :
-       (type & CLIENTWRITE_1XX ? CURLH_1XX :
-        (type & CLIENTWRITE_TRAILER ? CURLH_TRAILER :
-         CURLH_HEADER)));
-    CURLcode result = Curl_headers_push(data, optr, htype);
+    Curl_set_in_callback(data, true);
+    err = (data->set.ioctl_func)(data, CURLIOCMD_RESTARTREAD,
+                                 data->set.ioctl_client);
+    Curl_set_in_callback(data, false);
+    CURL_TRC_READ(data, "cr_in, rewind via set.ioctl_func -> %d", (int)err);
+    if(err) {
+      failf(data, "ioctl callback returned error %d", (int)err);
+      return CURLE_SEND_FAIL_REWIND;
+    }
+  }
+  else {
+    /* If no CURLOPT_READFUNCTION is used, we know that we operate on a
+       given FILE * stream and we can actually attempt to rewind that
+       ourselves with fseek() */
+    if(data->state.fread_func == (curl_read_callback)fread) {
+      int err = fseek(data->state.in, 0, SEEK_SET);
+      CURL_TRC_READ(data, "cr_in, rewind via fseek -> %d(%d)",
+                    (int)err, (int)errno);
+      if(-1 != err)
+        /* successful rewind */
+        return CURLE_OK;
+    }
+
+    /* no callback set or failure above, makes us fail at once */
+    failf(data, "necessary data rewind wasn't possible");
+    return CURLE_SEND_FAIL_REWIND;
+  }
+  return CURLE_OK;
+}
+
+
+static const struct Curl_crtype cr_in = {
+  "cr-in",
+  cr_in_init,
+  cr_in_read,
+  Curl_creader_def_close,
+  cr_in_needs_rewind,
+  cr_in_total_length,
+  cr_in_resume_from,
+  cr_in_rewind,
+  Curl_creader_def_unpause,
+  Curl_creader_def_done,
+  sizeof(struct cr_in_ctx)
+};
+
+CURLcode Curl_creader_create(struct Curl_creader **preader,
+                             struct Curl_easy *data,
+                             const struct Curl_crtype *crt,
+                             Curl_creader_phase phase)
+{
+  struct Curl_creader *reader = NULL;
+  CURLcode result = CURLE_OUT_OF_MEMORY;
+  void *p;
+
+  DEBUGASSERT(crt->creader_size >= sizeof(struct Curl_creader));
+  p = calloc(1, crt->creader_size);
+  if(!p)
+    goto out;
+
+  reader = (struct Curl_creader *)p;
+  reader->crt = crt;
+  reader->ctx = p;
+  reader->phase = phase;
+  result = crt->do_init(data, reader);
+
+out:
+  *preader = result? NULL : reader;
+  if(result)
+    free(reader);
+  return result;
+}
+
+void Curl_creader_free(struct Curl_easy *data, struct Curl_creader *reader)
+{
+  if(reader) {
+    reader->crt->do_close(data, reader);
+    free(reader);
+  }
+}
+
+struct cr_lc_ctx {
+  struct Curl_creader super;
+  struct bufq buf;
+  BIT(read_eos);  /* we read an EOS from the next reader */
+  BIT(eos);       /* we have returned an EOS */
+};
+
+static CURLcode cr_lc_init(struct Curl_easy *data, struct Curl_creader *reader)
+{
+  struct cr_lc_ctx *ctx = reader->ctx;
+  (void)data;
+  Curl_bufq_init2(&ctx->buf, (16 * 1024), 1, BUFQ_OPT_SOFT_LIMIT);
+  return CURLE_OK;
+}
+
+static void cr_lc_close(struct Curl_easy *data, struct Curl_creader *reader)
+{
+  struct cr_lc_ctx *ctx = reader->ctx;
+  (void)data;
+  Curl_bufq_free(&ctx->buf);
+}
+
+/* client reader doing line end conversions. */
+static CURLcode cr_lc_read(struct Curl_easy *data,
+                           struct Curl_creader *reader,
+                           char *buf, size_t blen,
+                           size_t *pnread, bool *peos)
+{
+  struct cr_lc_ctx *ctx = reader->ctx;
+  CURLcode result;
+  size_t nread, i, start, n;
+  bool eos;
+
+  if(ctx->eos) {
+    *pnread = 0;
+    *peos = TRUE;
+    return CURLE_OK;
+  }
+
+  if(Curl_bufq_is_empty(&ctx->buf)) {
+    if(ctx->read_eos) {
+      ctx->eos = TRUE;
+      *pnread = 0;
+      *peos = TRUE;
+      return CURLE_OK;
+    }
+    /* Still getting data form the next reader, ctx->buf is empty */
+    result = Curl_creader_read(data, reader->next, buf, blen, &nread, &eos);
     if(result)
       return result;
+    ctx->read_eos = eos;
+
+    if(!nread || !memchr(buf, '\n', nread)) {
+      /* nothing to convert, return this right away */
+      if(ctx->read_eos)
+        ctx->eos = TRUE;
+      *pnread = nread;
+      *peos = ctx->eos;
+      goto out;
+    }
+
+    /* at least one \n needs conversion to '\r\n', place into ctx->buf */
+    for(i = start = 0; i < nread; ++i) {
+      if(buf[i] != '\n')
+        continue;
+      /* on a soft limit bufq, we do not need to check length */
+      result = Curl_bufq_cwrite(&ctx->buf, buf + start, i - start, &n);
+      if(!result)
+        result = Curl_bufq_cwrite(&ctx->buf, STRCONST("\r\n"), &n);
+      if(result)
+        return result;
+      start = i + 1;
+      if(!data->set.crlf && (data->state.infilesize != -1)) {
+        /* we're here only because FTP is in ASCII mode...
+           bump infilesize for the LF we just added */
+        data->state.infilesize++;
+        /* comment: this might work for FTP, but in HTTP we could not change
+         * the content length after having started the request... */
+      }
+    }
+  }
+
+  DEBUGASSERT(!Curl_bufq_is_empty(&ctx->buf));
+  *peos = FALSE;
+  result = Curl_bufq_cread(&ctx->buf, buf, blen, pnread);
+  if(!result && ctx->read_eos && Curl_bufq_is_empty(&ctx->buf)) {
+    /* no more data, read all, done. */
+    ctx->eos = TRUE;
+    *peos = TRUE;
   }
+
+out:
+  CURL_TRC_READ(data, "cr_lc_read(len=%zu) -> %d, nread=%zu, eos=%d",
+                blen, result, *pnread, *peos);
+  return result;
+}
+
+static curl_off_t cr_lc_total_length(struct Curl_easy *data,
+                                     struct Curl_creader *reader)
+{
+  /* this reader changes length depending on input */
+  (void)data;
+  (void)reader;
+  return -1;
+}
+
+static const struct Curl_crtype cr_lc = {
+  "cr-lineconv",
+  cr_lc_init,
+  cr_lc_read,
+  cr_lc_close,
+  Curl_creader_def_needs_rewind,
+  cr_lc_total_length,
+  Curl_creader_def_resume_from,
+  Curl_creader_def_rewind,
+  Curl_creader_def_unpause,
+  Curl_creader_def_done,
+  sizeof(struct cr_lc_ctx)
+};
+
+static CURLcode cr_lc_add(struct Curl_easy *data)
+{
+  struct Curl_creader *reader = NULL;
+  CURLcode result;
+
+  result = Curl_creader_create(&reader, data, &cr_lc,
+                               CURL_CR_CONTENT_ENCODE);
+  if(!result)
+    result = Curl_creader_add(data, reader);
+
+  if(result && reader)
+    Curl_creader_free(data, reader);
+  return result;
+}
+
+static CURLcode do_init_reader_stack(struct Curl_easy *data,
+                                     struct Curl_creader *r)
+{
+  CURLcode result = CURLE_OK;
+  curl_off_t clen;
+
+  DEBUGASSERT(r);
+  DEBUGASSERT(r->crt);
+  DEBUGASSERT(r->phase == CURL_CR_CLIENT);
+  DEBUGASSERT(!data->req.reader_stack);
+
+  data->req.reader_stack = r;
+  clen = r->crt->total_length(data, r);
+  /* if we do not have 0 length init, and crlf conversion is wanted,
+   * add the reader for it */
+  if(clen && (data->set.crlf
+#ifdef CURL_DO_LINEEND_CONV
+     || data->state.prefer_ascii
 #endif
+    )) {
+    result = cr_lc_add(data);
+    if(result)
+      return result;
+  }
 
-  if(writeheader) {
-    size_t wrote;
+  return result;
+}
 
-    Curl_set_in_callback(data, true);
-    wrote = writeheader(optr, 1, olen, data->set.writeheader);
-    Curl_set_in_callback(data, false);
+CURLcode Curl_creader_set_fread(struct Curl_easy *data, curl_off_t len)
+{
+  CURLcode result;
+  struct Curl_creader *r;
+  struct cr_in_ctx *ctx;
+
+  result = Curl_creader_create(&r, data, &cr_in, CURL_CR_CLIENT);
+  if(result)
+    goto out;
+  ctx = r->ctx;
+  ctx->total_len = len;
+
+  cl_reset_reader(data);
+  result = do_init_reader_stack(data, r);
+out:
+  CURL_TRC_READ(data, "add fread reader, len=%"CURL_FORMAT_CURL_OFF_T
+                " -> %d", len, result);
+  return result;
+}
+
+CURLcode Curl_creader_add(struct Curl_easy *data,
+                          struct Curl_creader *reader)
+{
+  CURLcode result;
+  struct Curl_creader **anchor = &data->req.reader_stack;
+
+  if(!*anchor) {
+    result = Curl_creader_set_fread(data, data->state.infilesize);
+    if(result)
+      return result;
+  }
+
+  /* Insert the writer as first in its phase.
+   * Skip existing readers of lower phases. */
+  while(*anchor && (*anchor)->phase < reader->phase)
+    anchor = &((*anchor)->next);
+  reader->next = *anchor;
+  *anchor = reader;
+  return CURLE_OK;
+}
+
+CURLcode Curl_creader_set(struct Curl_easy *data, struct Curl_creader *r)
+{
+  CURLcode result;
+
+  DEBUGASSERT(r);
+  DEBUGASSERT(r->crt);
+  DEBUGASSERT(r->phase == CURL_CR_CLIENT);
+
+  cl_reset_reader(data);
+  result = do_init_reader_stack(data, r);
+  if(result)
+    Curl_creader_free(data, r);
+  return result;
+}
+
+CURLcode Curl_client_read(struct Curl_easy *data, char *buf, size_t blen,
+                          size_t *nread, bool *eos)
+{
+  CURLcode result;
+
+  DEBUGASSERT(buf);
+  DEBUGASSERT(blen);
+  DEBUGASSERT(nread);
+  DEBUGASSERT(eos);
 
-    if(CURL_WRITEFUNC_PAUSE == wrote)
-      /* here we pass in the HEADER bit only since if this was body as well
-         then it was passed already and clearly that didn't trigger the
-         pause, so this is saved for later with the HEADER bit only */
-      return pausewrite(data, CLIENTWRITE_HEADER |
-                        (type & (CLIENTWRITE_STATUS|CLIENTWRITE_CONNECT|
-                                 CLIENTWRITE_1XX|CLIENTWRITE_TRAILER)),
-                        optr, olen);
-    if(wrote != olen) {
-      failf(data, "Failed writing header");
-      return CURLE_WRITE_ERROR;
+  if(!data->req.reader_stack) {
+    result = Curl_creader_set_fread(data, data->state.infilesize);
+    if(result)
+      return result;
+    DEBUGASSERT(data->req.reader_stack);
+  }
+
+  result = Curl_creader_read(data, data->req.reader_stack, buf, blen,
+                             nread, eos);
+  CURL_TRC_READ(data, "client_read(len=%zu) -> %d, nread=%zu, eos=%d",
+                blen, result, *nread, *eos);
+  return result;
+}
+
+bool Curl_creader_needs_rewind(struct Curl_easy *data)
+{
+  struct Curl_creader *reader = data->req.reader_stack;
+  while(reader) {
+    if(reader->crt->needs_rewind(data, reader)) {
+      CURL_TRC_READ(data, "client reader needs rewind before next request");
+      return TRUE;
     }
+    reader = reader->next;
   }
+  return FALSE;
+}
 
+static CURLcode cr_null_read(struct Curl_easy *data,
+                             struct Curl_creader *reader,
+                             char *buf, size_t blen,
+                             size_t *pnread, bool *peos)
+{
+  (void)data;
+  (void)reader;
+  (void)buf;
+  (void)blen;
+  *pnread = 0;
+  *peos = TRUE;
   return CURLE_OK;
 }
 
+static curl_off_t cr_null_total_length(struct Curl_easy *data,
+                                       struct Curl_creader *reader)
+{
+  /* this reader changes length depending on input */
+  (void)data;
+  (void)reader;
+  return 0;
+}
 
-/* Curl_client_write() sends data to the write callback(s)
+static const struct Curl_crtype cr_null = {
+  "cr-null",
+  Curl_creader_def_init,
+  cr_null_read,
+  Curl_creader_def_close,
+  Curl_creader_def_needs_rewind,
+  cr_null_total_length,
+  Curl_creader_def_resume_from,
+  Curl_creader_def_rewind,
+  Curl_creader_def_unpause,
+  Curl_creader_def_done,
+  sizeof(struct Curl_creader)
+};
 
-   The bit pattern defines to what "streams" to write to. Body and/or header.
-   The defines are in sendf.h of course.
+CURLcode Curl_creader_set_null(struct Curl_easy *data)
+{
+  struct Curl_creader *r;
+  CURLcode result;
 
-   If CURL_DO_LINEEND_CONV is enabled, data is converted IN PLACE to the
-   local character encoding.  This is a problem and should be changed in
-   the future to leave the original data alone.
- */
-CURLcode Curl_client_write(struct Curl_easy *data,
-                           int type,
-                           char *ptr,
-                           size_t len)
-{
-#if !defined(CURL_DISABLE_FTP) && defined(CURL_DO_LINEEND_CONV)
-  /* FTP data may need conversion. */
-  if((type & CLIENTWRITE_BODY) &&
-     (data->conn->handler->protocol & PROTO_FAMILY_FTP) &&
-     data->conn->proto.ftpc.transfertype == 'A') {
-    /* convert end-of-line markers */
-    len = convert_lineends(data, ptr, len);
+  result = Curl_creader_create(&r, data, &cr_null, CURL_CR_CLIENT);
+  if(result)
+    return result;
+
+  cl_reset_reader(data);
+  return do_init_reader_stack(data, r);
+}
+
+struct cr_buf_ctx {
+  struct Curl_creader super;
+  const char *buf;
+  size_t blen;
+  size_t index;
+};
+
+static CURLcode cr_buf_read(struct Curl_easy *data,
+                            struct Curl_creader *reader,
+                            char *buf, size_t blen,
+                            size_t *pnread, bool *peos)
+{
+  struct cr_buf_ctx *ctx = reader->ctx;
+  size_t nread = ctx->blen - ctx->index;
+
+  (void)data;
+  if(!nread || !ctx->buf) {
+    *pnread = 0;
+    *peos = TRUE;
   }
-#endif
-  return chop_write(data, type, ptr, len);
+  else {
+    if(nread > blen)
+      nread = blen;
+    memcpy(buf, ctx->buf + ctx->index, nread);
+    *pnread = nread;
+    ctx->index += nread;
+    *peos = (ctx->index == ctx->blen);
+  }
+  CURL_TRC_READ(data, "cr_buf_read(len=%zu) -> 0, nread=%zu, eos=%d",
+                blen, *pnread, *peos);
+  return CURLE_OK;
 }
 
-/*
- * Internal read-from-socket function. This is meant to deal with plain
- * sockets, SSL sockets and kerberos sockets.
- *
- * Returns a regular CURLcode value.
- */
-CURLcode Curl_read(struct Curl_easy *data,   /* transfer */
-                   curl_socket_t sockfd,     /* read from this socket */
-                   char *buf,                /* store read data here */
-                   size_t sizerequested,     /* max amount to read */
-                   ssize_t *n)               /* amount bytes read */
-{
-  CURLcode result = CURLE_RECV_ERROR;
-  ssize_t nread = 0;
-  size_t bytesfromsocket = 0;
-  char *buffertofill = NULL;
-  struct connectdata *conn = data->conn;
-
-  /* Set 'num' to 0 or 1, depending on which socket that has been sent here.
-     If it is the second socket, we set num to 1. Otherwise to 0. This lets
-     us use the correct ssl handle. */
-  int num = (sockfd == conn->sock[SECONDARYSOCKET]);
-
-  *n = 0; /* reset amount to zero */
-
-  bytesfromsocket = CURLMIN(sizerequested, (size_t)data->set.buffer_size);
-  buffertofill = buf;
-
-  nread = conn->recv[num](data, num, buffertofill, bytesfromsocket, &result);
-  if(nread < 0)
+static bool cr_buf_needs_rewind(struct Curl_easy *data,
+                                struct Curl_creader *reader)
+{
+  struct cr_buf_ctx *ctx = reader->ctx;
+  (void)data;
+  return ctx->index > 0;
+}
+
+static curl_off_t cr_buf_total_length(struct Curl_easy *data,
+                                      struct Curl_creader *reader)
+{
+  struct cr_buf_ctx *ctx = reader->ctx;
+  (void)data;
+  return (curl_off_t)ctx->blen;
+}
+
+static CURLcode cr_buf_resume_from(struct Curl_easy *data,
+                                   struct Curl_creader *reader,
+                                   curl_off_t offset)
+{
+  struct cr_buf_ctx *ctx = reader->ctx;
+  size_t boffset;
+
+  (void)data;
+  DEBUGASSERT(data->conn);
+  /* already started reading? */
+  if(ctx->index)
+    return CURLE_READ_ERROR;
+  if(offset <= 0)
+    return CURLE_OK;
+  boffset = (size_t)offset;
+  if(boffset > ctx->blen)
+    return CURLE_READ_ERROR;
+
+  ctx->buf += boffset;
+  ctx->blen -= boffset;
+  return CURLE_OK;
+}
+
+static const struct Curl_crtype cr_buf = {
+  "cr-buf",
+  Curl_creader_def_init,
+  cr_buf_read,
+  Curl_creader_def_close,
+  cr_buf_needs_rewind,
+  cr_buf_total_length,
+  cr_buf_resume_from,
+  Curl_creader_def_rewind,
+  Curl_creader_def_unpause,
+  Curl_creader_def_done,
+  sizeof(struct cr_buf_ctx)
+};
+
+CURLcode Curl_creader_set_buf(struct Curl_easy *data,
+                               const char *buf, size_t blen)
+{
+  CURLcode result;
+  struct Curl_creader *r;
+  struct cr_buf_ctx *ctx;
+
+  result = Curl_creader_create(&r, data, &cr_buf, CURL_CR_CLIENT);
+  if(result)
     goto out;
+  ctx = r->ctx;
+  ctx->buf = buf;
+  ctx->blen = blen;
+  ctx->index = 0;
 
-  *n += nread;
-  result = CURLE_OK;
+  cl_reset_reader(data);
+  result = do_init_reader_stack(data, r);
 out:
+  CURL_TRC_READ(data, "add buf reader, len=%zu -> %d", blen, result);
+  return result;
+}
+
+curl_off_t Curl_creader_total_length(struct Curl_easy *data)
+{
+  struct Curl_creader *r = data->req.reader_stack;
+  return r? r->crt->total_length(data, r) : -1;
+}
+
+curl_off_t Curl_creader_client_length(struct Curl_easy *data)
+{
+  struct Curl_creader *r = data->req.reader_stack;
+  while(r && r->phase != CURL_CR_CLIENT)
+    r = r->next;
+  return r? r->crt->total_length(data, r) : -1;
+}
+
+CURLcode Curl_creader_resume_from(struct Curl_easy *data, curl_off_t offset)
+{
+  struct Curl_creader *r = data->req.reader_stack;
+  while(r && r->phase != CURL_CR_CLIENT)
+    r = r->next;
+  return r? r->crt->resume_from(data, r, offset) : CURLE_READ_ERROR;
+}
+
+CURLcode Curl_creader_unpause(struct Curl_easy *data)
+{
+  struct Curl_creader *reader = data->req.reader_stack;
+  CURLcode result = CURLE_OK;
+
+  while(reader) {
+    result = reader->crt->unpause(data, reader);
+    if(result)
+      break;
+    reader = reader->next;
+  }
   return result;
 }
+
+void Curl_creader_done(struct Curl_easy *data, int premature)
+{
+  struct Curl_creader *reader = data->req.reader_stack;
+  while(reader) {
+    reader->crt->done(data, reader, premature);
+    reader = reader->next;
+  }
+}
+
+struct Curl_creader *Curl_creader_get_by_type(struct Curl_easy *data,
+                                              const struct Curl_crtype *crt)
+{
+  struct Curl_creader *r;
+  for(r = data->req.reader_stack; r; r = r->next) {
+    if(r->crt == crt)
+      return r;
+  }
+  return NULL;
+
+}
diff --git a/vendor/curl/lib/sendf.h b/vendor/curl/lib/sendf.h
index 5ef2b91df7..82a290257a 100644
--- a/vendor/curl/lib/sendf.h
+++ b/vendor/curl/lib/sendf.h
@@ -28,34 +28,380 @@
 
 #include "curl_trc.h"
 
+/**
+ * Type of data that is being written to the client (application)
+ * - data written can be either BODY or META data
+ * - META data is either INFO or HEADER
+ * - INFO is meta information, e.g. not BODY, that cannot be interpreted
+ *   as headers of a response. Example FTP/IMAP pingpong answers.
+ * - HEADER can have additional bits set (more than one)
+ *   - STATUS special "header", e.g. response status line in HTTP
+ *   - CONNECT header was received during proxying the connection
+ *   - 1XX header is part of an intermediate response, e.g. HTTP 1xx code
+ *   - TRAILER header is trailing response data, e.g. HTTP trailers
+ * BODY, INFO and HEADER should not be mixed, as this would lead to
+ * confusion on how to interpret/format/convert the data.
+ */
+#define CLIENTWRITE_BODY    (1<<0) /* non-meta information, BODY */
+#define CLIENTWRITE_INFO    (1<<1) /* meta information, not a HEADER */
+#define CLIENTWRITE_HEADER  (1<<2) /* meta information, HEADER */
+#define CLIENTWRITE_STATUS  (1<<3) /* a special status HEADER */
+#define CLIENTWRITE_CONNECT (1<<4) /* a CONNECT related HEADER */
+#define CLIENTWRITE_1XX     (1<<5) /* a 1xx response related HEADER */
+#define CLIENTWRITE_TRAILER (1<<6) /* a trailer HEADER */
+#define CLIENTWRITE_EOS     (1<<7) /* End Of transfer download Stream */
 
-#define CLIENTWRITE_BODY    (1<<0)
-#define CLIENTWRITE_HEADER  (1<<1)
-#define CLIENTWRITE_STATUS  (1<<2) /* the first "header" is the status line */
-#define CLIENTWRITE_CONNECT (1<<3) /* a CONNECT response */
-#define CLIENTWRITE_1XX     (1<<4) /* a 1xx response */
-#define CLIENTWRITE_TRAILER (1<<5) /* a trailer header */
-#define CLIENTWRITE_BOTH   (CLIENTWRITE_BODY|CLIENTWRITE_HEADER)
-
-CURLcode Curl_client_write(struct Curl_easy *data, int type, char *ptr,
+/**
+ * Write `len` bytes at `prt` to the client. `type` indicates what
+ * kind of data is being written.
+ */
+CURLcode Curl_client_write(struct Curl_easy *data, int type, const char *ptr,
                            size_t len) WARN_UNUSED_RESULT;
 
-/* internal read-function, does plain socket, SSL and krb4 */
-CURLcode Curl_read(struct Curl_easy *data, curl_socket_t sockfd,
-                   char *buf, size_t buffersize,
-                   ssize_t *n);
-
-/* internal write-function, does plain socket, SSL, SCP, SFTP and krb4 */
-CURLcode Curl_write(struct Curl_easy *data,
-                    curl_socket_t sockfd,
-                    const void *mem, size_t len,
-                    ssize_t *written);
-
-/* internal write-function, using sockindex for connection destination */
-CURLcode Curl_nwrite(struct Curl_easy *data,
-                     int sockindex,
-                     const void *buf,
-                     size_t blen,
-                     ssize_t *pnwritten);
+/**
+ * Free all resources related to client writing.
+ */
+void Curl_client_cleanup(struct Curl_easy *data);
+
+/**
+ * Reset readers and writer chains, keep rewind information
+ * when necessary.
+ */
+void Curl_client_reset(struct Curl_easy *data);
+
+/**
+ * A new request is starting, perform any ops like rewinding
+ * previous readers when needed.
+ */
+CURLcode Curl_client_start(struct Curl_easy *data);
+
+/**
+ * Client Writers - a chain passing transfer BODY data to the client.
+ * Main application: HTTP and related protocols
+ * Other uses: monitoring of download progress
+ *
+ * Writers in the chain are order by their `phase`. First come all
+ * writers in CURL_CW_RAW, followed by any in CURL_CW_TRANSFER_DECODE,
+ * followed by any in CURL_CW_PROTOCOL, etc.
+ *
+ * When adding a writer, it is inserted as first in its phase. This means
+ * the order of adding writers of the same phase matters, but writers for
+ * different phases may be added in any order.
+ *
+ * Writers which do modify the BODY data written are expected to be of
+ * phases TRANSFER_DECODE or CONTENT_DECODE. The other phases are intended
+ * for monitoring writers. Which do *not* modify the data but gather
+ * statistics or update progress reporting.
+ */
+
+/* Phase a writer operates at. */
+typedef enum {
+  CURL_CW_RAW,  /* raw data written, before any decoding */
+  CURL_CW_TRANSFER_DECODE, /* remove transfer-encodings */
+  CURL_CW_PROTOCOL, /* after transfer, but before content decoding */
+  CURL_CW_CONTENT_DECODE, /* remove content-encodings */
+  CURL_CW_CLIENT  /* data written to client */
+} Curl_cwriter_phase;
+
+/* Client Writer Type, provides the implementation */
+struct Curl_cwtype {
+  const char *name;        /* writer name. */
+  const char *alias;       /* writer name alias, maybe NULL. */
+  CURLcode (*do_init)(struct Curl_easy *data,
+                      struct Curl_cwriter *writer);
+  CURLcode (*do_write)(struct Curl_easy *data,
+                       struct Curl_cwriter *writer, int type,
+                       const char *buf, size_t nbytes);
+  void (*do_close)(struct Curl_easy *data,
+                   struct Curl_cwriter *writer);
+  size_t cwriter_size;  /* sizeof() allocated struct Curl_cwriter */
+};
+
+/* Client writer instance, allocated on creation.
+ * `void *ctx` is the pointer from the allocation of
+ * the `struct Curl_cwriter` itself. This is suitable for "downcasting"
+ * by the writers implementation. See https://github.com/curl/curl/pull/13054
+ * for the alignment problems that arise otherwise.
+ */
+struct Curl_cwriter {
+  const struct Curl_cwtype *cwt;  /* type implementation */
+  struct Curl_cwriter *next;  /* Downstream writer. */
+  void *ctx;                  /* allocated instance pointer */
+  Curl_cwriter_phase phase; /* phase at which it operates */
+};
+
+/**
+ * Create a new cwriter instance with given type and phase. Is not
+ * inserted into the writer chain by this call.
+ * Invokes `writer->do_init()`.
+ */
+CURLcode Curl_cwriter_create(struct Curl_cwriter **pwriter,
+                             struct Curl_easy *data,
+                             const struct Curl_cwtype *ce_handler,
+                             Curl_cwriter_phase phase);
+
+/**
+ * Free a cwriter instance.
+ * Invokes `writer->do_close()`.
+ */
+void Curl_cwriter_free(struct Curl_easy *data,
+                       struct Curl_cwriter *writer);
+
+/**
+ * Count the number of writers installed of the given phase.
+ */
+size_t Curl_cwriter_count(struct Curl_easy *data, Curl_cwriter_phase phase);
+
+/**
+ * Adds a writer to the transfer's writer chain.
+ * The writers `phase` determines where in the chain it is inserted.
+ */
+CURLcode Curl_cwriter_add(struct Curl_easy *data,
+                          struct Curl_cwriter *writer);
+
+/**
+ * Look up an installed client writer on `data` by its type.
+ * @return first writer with that type or NULL
+ */
+struct Curl_cwriter *Curl_cwriter_get_by_type(struct Curl_easy *data,
+                                              const struct Curl_cwtype *cwt);
+
+void Curl_cwriter_remove_by_name(struct Curl_easy *data,
+                                 const char *name);
+
+struct Curl_cwriter *Curl_cwriter_get_by_name(struct Curl_easy *data,
+                                              const char *name);
+
+/**
+ * Convenience method for calling `writer->do_write()` that
+ * checks for NULL writer.
+ */
+CURLcode Curl_cwriter_write(struct Curl_easy *data,
+                            struct Curl_cwriter *writer, int type,
+                            const char *buf, size_t nbytes);
+
+/**
+ * Return TRUE iff client writer is paused.
+ */
+bool Curl_cwriter_is_paused(struct Curl_easy *data);
+
+/**
+ * Unpause client writer and flush any buffered date to the client.
+ */
+CURLcode Curl_cwriter_unpause(struct Curl_easy *data);
+
+/**
+ * Default implementations for do_init, do_write, do_close that
+ * do nothing and pass the data through.
+ */
+CURLcode Curl_cwriter_def_init(struct Curl_easy *data,
+                               struct Curl_cwriter *writer);
+CURLcode Curl_cwriter_def_write(struct Curl_easy *data,
+                                struct Curl_cwriter *writer, int type,
+                                const char *buf, size_t nbytes);
+void Curl_cwriter_def_close(struct Curl_easy *data,
+                            struct Curl_cwriter *writer);
+
+
+
+/* Client Reader Type, provides the implementation */
+struct Curl_crtype {
+  const char *name;        /* writer name. */
+  CURLcode (*do_init)(struct Curl_easy *data, struct Curl_creader *reader);
+  CURLcode (*do_read)(struct Curl_easy *data, struct Curl_creader *reader,
+                      char *buf, size_t blen, size_t *nread, bool *eos);
+  void (*do_close)(struct Curl_easy *data, struct Curl_creader *reader);
+  bool (*needs_rewind)(struct Curl_easy *data, struct Curl_creader *reader);
+  curl_off_t (*total_length)(struct Curl_easy *data,
+                             struct Curl_creader *reader);
+  CURLcode (*resume_from)(struct Curl_easy *data,
+                          struct Curl_creader *reader, curl_off_t offset);
+  CURLcode (*rewind)(struct Curl_easy *data, struct Curl_creader *reader);
+  CURLcode (*unpause)(struct Curl_easy *data, struct Curl_creader *reader);
+  void (*done)(struct Curl_easy *data,
+               struct Curl_creader *reader, int premature);
+  size_t creader_size;  /* sizeof() allocated struct Curl_creader */
+};
+
+/* Phase a reader operates at. */
+typedef enum {
+  CURL_CR_NET,  /* data send to the network (connection filters) */
+  CURL_CR_TRANSFER_ENCODE, /* add transfer-encodings */
+  CURL_CR_PROTOCOL, /* before transfer, but after content decoding */
+  CURL_CR_CONTENT_ENCODE, /* add content-encodings */
+  CURL_CR_CLIENT  /* data read from client */
+} Curl_creader_phase;
+
+/* Client reader instance, allocated on creation.
+ * `void *ctx` is the pointer from the allocation of
+ * the `struct Curl_cwriter` itself. This is suitable for "downcasting"
+ * by the writers implementation. See https://github.com/curl/curl/pull/13054
+ * for the alignment problems that arise otherwise.
+ */
+struct Curl_creader {
+  const struct Curl_crtype *crt;  /* type implementation */
+  struct Curl_creader *next;  /* Downstream reader. */
+  void *ctx;
+  Curl_creader_phase phase; /* phase at which it operates */
+};
+
+/**
+ * Default implementations for do_init, do_write, do_close that
+ * do nothing and pass the data through.
+ */
+CURLcode Curl_creader_def_init(struct Curl_easy *data,
+                               struct Curl_creader *reader);
+void Curl_creader_def_close(struct Curl_easy *data,
+                            struct Curl_creader *reader);
+CURLcode Curl_creader_def_read(struct Curl_easy *data,
+                               struct Curl_creader *reader,
+                               char *buf, size_t blen,
+                               size_t *nread, bool *eos);
+bool Curl_creader_def_needs_rewind(struct Curl_easy *data,
+                                   struct Curl_creader *reader);
+curl_off_t Curl_creader_def_total_length(struct Curl_easy *data,
+                                         struct Curl_creader *reader);
+CURLcode Curl_creader_def_resume_from(struct Curl_easy *data,
+                                      struct Curl_creader *reader,
+                                      curl_off_t offset);
+CURLcode Curl_creader_def_rewind(struct Curl_easy *data,
+                                 struct Curl_creader *reader);
+CURLcode Curl_creader_def_unpause(struct Curl_easy *data,
+                                  struct Curl_creader *reader);
+void Curl_creader_def_done(struct Curl_easy *data,
+                           struct Curl_creader *reader, int premature);
+
+/**
+ * Convenience method for calling `reader->do_read()` that
+ * checks for NULL reader.
+ */
+CURLcode Curl_creader_read(struct Curl_easy *data,
+                           struct Curl_creader *reader,
+                           char *buf, size_t blen, size_t *nread, bool *eos);
+
+/**
+ * Create a new creader instance with given type and phase. Is not
+ * inserted into the writer chain by this call.
+ * Invokes `reader->do_init()`.
+ */
+CURLcode Curl_creader_create(struct Curl_creader **preader,
+                             struct Curl_easy *data,
+                             const struct Curl_crtype *cr_handler,
+                             Curl_creader_phase phase);
+
+/**
+ * Free a creader instance.
+ * Invokes `reader->do_close()`.
+ */
+void Curl_creader_free(struct Curl_easy *data, struct Curl_creader *reader);
+
+/**
+ * Adds a reader to the transfer's reader chain.
+ * The readers `phase` determines where in the chain it is inserted.
+ */
+CURLcode Curl_creader_add(struct Curl_easy *data,
+                          struct Curl_creader *reader);
+
+/**
+ * Set the given reader, which needs to be of type CURL_CR_CLIENT,
+ * as the new first reader. Discard any installed readers and init
+ * the reader chain anew.
+ * The function takes ownership of `r`.
+ */
+CURLcode Curl_creader_set(struct Curl_easy *data, struct Curl_creader *r);
+
+/**
+ * Read at most `blen` bytes at `buf` from the client.
+ * @param data    the transfer to read client bytes for
+ * @param buf     the memory location to read to
+ * @param blen    the amount of memory at `buf`
+ * @param nread   on return the number of bytes read into `buf`
+ * @param eos     TRUE iff bytes are the end of data from client
+ * @return CURLE_OK on successful read (even 0 length) or error
+ */
+CURLcode Curl_client_read(struct Curl_easy *data, char *buf, size_t blen,
+                          size_t *nread, bool *eos) WARN_UNUSED_RESULT;
+
+/**
+ * TRUE iff client reader needs rewing before it can be used for
+ * a retry request.
+ */
+bool Curl_creader_needs_rewind(struct Curl_easy *data);
+
+/**
+ * TRUE iff client reader will rewind at next start
+ */
+bool Curl_creader_will_rewind(struct Curl_easy *data);
+
+/**
+ * En-/disable rewind of client reader at next start.
+ */
+void Curl_creader_set_rewind(struct Curl_easy *data, bool enable);
+
+/**
+ * Get the total length of bytes provided by the installed readers.
+ * This is independent of the amount already delivered and is calculated
+ * by all readers in the stack. If a reader like "chunked" or
+ * "crlf conversion" is installed, the returned length will be -1.
+ * @return -1 if length is indeterminate
+ */
+curl_off_t Curl_creader_total_length(struct Curl_easy *data);
+
+/**
+ * Get the total length of bytes provided by the reader at phase
+ * CURL_CR_CLIENT. This may not match the amount of bytes read
+ * for a request, depending if other, encoding readers are also installed.
+ * However it allows for rough estimation of the overall length.
+ * @return -1 if length is indeterminate
+ */
+curl_off_t Curl_creader_client_length(struct Curl_easy *data);
+
+/**
+ * Ask the installed reader at phase CURL_CR_CLIENT to start
+ * reading from the given offset. On success, this will reduce
+ * the `total_length()` by the amount.
+ * @param data    the transfer to read client bytes for
+ * @param offset  the offset where to start reads from, negative
+ *                values will be ignored.
+ * @return CURLE_OK if offset could be set
+ *         CURLE_READ_ERROR if not supported by reader or seek/read failed
+ *                          of offset larger then total length
+ *         CURLE_PARTIAL_FILE if offset led to 0 total length
+ */
+CURLcode Curl_creader_resume_from(struct Curl_easy *data, curl_off_t offset);
+
+/**
+ * Unpause all installed readers.
+ */
+CURLcode Curl_creader_unpause(struct Curl_easy *data);
+
+/**
+ * Tell all client readers that they are done.
+ */
+void Curl_creader_done(struct Curl_easy *data, int premature);
+
+/**
+ * Look up an installed client reader on `data` by its type.
+ * @return first reader with that type or NULL
+ */
+struct Curl_creader *Curl_creader_get_by_type(struct Curl_easy *data,
+                                              const struct Curl_crtype *crt);
+
+
+/**
+ * Set the client reader to provide 0 bytes, immediate EOS.
+ */
+CURLcode Curl_creader_set_null(struct Curl_easy *data);
+
+/**
+ * Set the client reader the reads from fread callback.
+ */
+CURLcode Curl_creader_set_fread(struct Curl_easy *data, curl_off_t len);
+
+/**
+ * Set the client reader the reads from the supplied buf (NOT COPIED).
+ */
+CURLcode Curl_creader_set_buf(struct Curl_easy *data,
+                              const char *buf, size_t blen);
 
 #endif /* HEADER_CURL_SENDF_H */
diff --git a/vendor/curl/lib/setopt.c b/vendor/curl/lib/setopt.c
index 2cef1b3d82..e8b25454b2 100644
--- a/vendor/curl/lib/setopt.c
+++ b/vendor/curl/lib/setopt.c
@@ -50,6 +50,9 @@
 #include "multiif.h"
 #include "altsvc.h"
 #include "hsts.h"
+#include "tftp.h"
+#include "strdup.h"
+#include "escape.h"
 
 /* The last 3 #include files should be in this order */
 #include "curl_printf.h"
@@ -108,45 +111,32 @@ CURLcode Curl_setblobopt(struct curl_blob **blobp,
 
 static CURLcode setstropt_userpwd(char *option, char **userp, char **passwdp)
 {
-  CURLcode result = CURLE_OK;
   char *user = NULL;
   char *passwd = NULL;
 
+  DEBUGASSERT(userp);
+  DEBUGASSERT(passwdp);
+
   /* Parse the login details if specified. It not then we treat NULL as a hint
      to clear the existing data */
   if(option) {
     size_t len = strlen(option);
+    CURLcode result;
     if(len > CURL_MAX_INPUT_LENGTH)
       return CURLE_BAD_FUNCTION_ARGUMENT;
 
-    result = Curl_parse_login_details(option, len,
-                                      (userp ? &user : NULL),
-                                      (passwdp ? &passwd : NULL),
-                                      NULL);
+    result = Curl_parse_login_details(option, len, &user, &passwd, NULL);
+    if(result)
+      return result;
   }
 
-  if(!result) {
-    /* Store the username part of option if required */
-    if(userp) {
-      if(!user && option && option[0] == ':') {
-        /* Allocate an empty string instead of returning NULL as user name */
-        user = strdup("");
-        if(!user)
-          result = CURLE_OUT_OF_MEMORY;
-      }
-
-      Curl_safefree(*userp);
-      *userp = user;
-    }
+  free(*userp);
+  *userp = user;
 
-    /* Store the password part of option if required */
-    if(passwdp) {
-      Curl_safefree(*passwdp);
-      *passwdp = passwd;
-    }
-  }
+  free(*passwdp);
+  *passwdp = passwd;
 
-  return result;
+  return CURLE_OK;
 }
 
 #define C_SSLVERSION_VALUE(x) (x & 0xffff)
@@ -154,6 +144,12 @@ static CURLcode setstropt_userpwd(char *option, char **userp, char **passwdp)
 
 static CURLcode protocol2num(const char *str, curl_prot_t *val)
 {
+  /*
+   * We are asked to cherry-pick protocols, so play it safe and disallow all
+   * protocols to start with, and re-add the wanted ones back in.
+   */
+  *val = 0;
+
   if(!str)
     return CURLE_BAD_FUNCTION_ARGUMENT;
 
@@ -162,8 +158,6 @@ static CURLcode protocol2num(const char *str, curl_prot_t *val)
     return CURLE_OK;
   }
 
-  *val = 0;
-
   do {
     const char *token = str;
     size_t tlen;
@@ -171,7 +165,7 @@ static CURLcode protocol2num(const char *str, curl_prot_t *val)
     str = strchr(str, ',');
     tlen = str? (size_t) (str - token): strlen(token);
     if(tlen) {
-      const struct Curl_handler *h = Curl_builtin_scheme(token, tlen);
+      const struct Curl_handler *h = Curl_getn_scheme_handler(token, tlen);
 
       if(!h)
         return CURLE_UNSUPPORTED_PROTOCOL;
@@ -261,43 +255,43 @@ CURLcode Curl_vsetopt(struct Curl_easy *data, CURLoption option, va_list param)
      * Set the absolute number of maximum simultaneous alive connection that
      * libcurl is allowed to have.
      */
-    arg = va_arg(param, long);
-    if(arg < 0)
+    uarg = va_arg(param, unsigned long);
+    if(uarg > UINT_MAX)
       return CURLE_BAD_FUNCTION_ARGUMENT;
-    data->set.maxconnects = arg;
+    data->set.maxconnects = (unsigned int)uarg;
     break;
   case CURLOPT_FORBID_REUSE:
     /*
      * When this transfer is done, it must not be left to be reused by a
      * subsequent transfer but shall be closed immediately.
      */
-    data->set.reuse_forbid = (0 != va_arg(param, long)) ? TRUE : FALSE;
+    data->set.reuse_forbid = (0 != va_arg(param, long));
     break;
   case CURLOPT_FRESH_CONNECT:
     /*
      * This transfer shall not use a previously cached connection but
      * should be made with a fresh new connect!
      */
-    data->set.reuse_fresh = (0 != va_arg(param, long)) ? TRUE : FALSE;
+    data->set.reuse_fresh = (0 != va_arg(param, long));
     break;
   case CURLOPT_VERBOSE:
     /*
      * Verbose means infof() calls that give a lot of information about
      * the connection and transfer procedures as well as internal choices.
      */
-    data->set.verbose = (0 != va_arg(param, long)) ? TRUE : FALSE;
+    data->set.verbose = (0 != va_arg(param, long));
     break;
   case CURLOPT_HEADER:
     /*
      * Set to include the header in the general data output stream.
      */
-    data->set.include_header = (0 != va_arg(param, long)) ? TRUE : FALSE;
+    data->set.include_header = (0 != va_arg(param, long));
     break;
   case CURLOPT_NOPROGRESS:
     /*
      * Shut off the internal supported progress meter
      */
-    data->set.hide_progress = (0 != va_arg(param, long)) ? TRUE : FALSE;
+    data->set.hide_progress = (0 != va_arg(param, long));
     if(data->set.hide_progress)
       data->progress.flags |= PGRS_HIDE;
     else
@@ -307,7 +301,7 @@ CURLcode Curl_vsetopt(struct Curl_easy *data, CURLoption option, va_list param)
     /*
      * Do not include the body part in the output data stream.
      */
-    data->set.opt_no_body = (0 != va_arg(param, long)) ? TRUE : FALSE;
+    data->set.opt_no_body = (0 != va_arg(param, long));
 #ifndef CURL_DISABLE_HTTP
     if(data->set.opt_no_body)
       /* in HTTP lingo, no body means using the HEAD request... */
@@ -321,11 +315,10 @@ CURLcode Curl_vsetopt(struct Curl_easy *data, CURLoption option, va_list param)
      * Don't output the >=400 error code HTML-page, but instead only
      * return error.
      */
-    data->set.http_fail_on_error = (0 != va_arg(param, long)) ? TRUE : FALSE;
+    data->set.http_fail_on_error = (0 != va_arg(param, long));
     break;
   case CURLOPT_KEEP_SENDING_ON_ERROR:
-    data->set.http_keep_sending_on_error = (0 != va_arg(param, long)) ?
-      TRUE : FALSE;
+    data->set.http_keep_sending_on_error = (0 != va_arg(param, long));
     break;
   case CURLOPT_UPLOAD:
   case CURLOPT_PUT:
@@ -353,7 +346,7 @@ CURLcode Curl_vsetopt(struct Curl_easy *data, CURLoption option, va_list param)
      * Try to get the file time of the remote document. The time will
      * later (possibly) become available using curl_easy_getinfo().
      */
-    data->set.get_filetime = (0 != va_arg(param, long)) ? TRUE : FALSE;
+    data->set.get_filetime = (0 != va_arg(param, long));
     break;
   case CURLOPT_SERVER_RESPONSE_TIMEOUT:
     /*
@@ -366,6 +359,17 @@ CURLcode Curl_vsetopt(struct Curl_easy *data, CURLoption option, va_list param)
     else
       return CURLE_BAD_FUNCTION_ARGUMENT;
     break;
+  case CURLOPT_SERVER_RESPONSE_TIMEOUT_MS:
+    /*
+     * Option that specifies how quickly a server response must be obtained
+     * before it is considered failure. For pingpong protocols.
+     */
+    arg = va_arg(param, long);
+    if((arg >= 0) && (arg <= INT_MAX))
+      data->set.server_response_timeout = (unsigned int)arg;
+    else
+      return CURLE_BAD_FUNCTION_ARGUMENT;
+    break;
 #ifndef CURL_DISABLE_TFTP
   case CURLOPT_TFTP_NO_OPTIONS:
     /*
@@ -379,7 +383,7 @@ CURLcode Curl_vsetopt(struct Curl_easy *data, CURLoption option, va_list param)
      * TFTP option that specifies the block size to use for data transmission.
      */
     arg = va_arg(param, long);
-    if(arg < 0)
+    if(arg > TFTP_BLKSIZE_MAX || arg < TFTP_BLKSIZE_MIN)
       return CURLE_BAD_FUNCTION_ARGUMENT;
     data->set.tftp_blksize = arg;
     break;
@@ -409,7 +413,7 @@ CURLcode Curl_vsetopt(struct Curl_easy *data, CURLoption option, va_list param)
      *
      * Transfer using ASCII (instead of BINARY).
      */
-    data->set.prefer_ascii = (0 != va_arg(param, long)) ? TRUE : FALSE;
+    data->set.prefer_ascii = (0 != va_arg(param, long));
     break;
   case CURLOPT_TIMECONDITION:
     /*
@@ -497,24 +501,16 @@ CURLcode Curl_vsetopt(struct Curl_easy *data, CURLoption option, va_list param)
           (data->set.postfieldsize > (curl_off_t)((size_t)-1))))
         result = CURLE_OUT_OF_MEMORY;
       else {
-        char *p;
-
-        (void) Curl_setstropt(&data->set.str[STRING_COPYPOSTFIELDS], NULL);
-
         /* Allocate even when size == 0. This satisfies the need of possible
-           later address compare to detect the COPYPOSTFIELDS mode, and
-           to mark that postfields is used rather than read function or
-           form data.
+           later address compare to detect the COPYPOSTFIELDS mode, and to
+           mark that postfields is used rather than read function or form
+           data.
         */
-        p = malloc((size_t)(data->set.postfieldsize?
-                            data->set.postfieldsize:1));
-
+        char *p = Curl_memdup0(argptr, (size_t)data->set.postfieldsize);
         if(!p)
           result = CURLE_OUT_OF_MEMORY;
         else {
-          if(data->set.postfieldsize)
-            memcpy(p, argptr, (size_t)data->set.postfieldsize);
-
+          free(data->set.str[STRING_COPYPOSTFIELDS]);
           data->set.str[STRING_COPYPOSTFIELDS] = p;
         }
       }
@@ -530,7 +526,7 @@ CURLcode Curl_vsetopt(struct Curl_easy *data, CURLoption option, va_list param)
      */
     data->set.postfields = va_arg(param, void *);
     /* Release old copied data. */
-    (void) Curl_setstropt(&data->set.str[STRING_COPYPOSTFIELDS], NULL);
+    Curl_safefree(data->set.str[STRING_COPYPOSTFIELDS]);
     data->set.method = HTTPREQ_POST;
     break;
 
@@ -546,7 +542,7 @@ CURLcode Curl_vsetopt(struct Curl_easy *data, CURLoption option, va_list param)
     if(data->set.postfieldsize < bigsize &&
        data->set.postfields == data->set.str[STRING_COPYPOSTFIELDS]) {
       /* Previous CURLOPT_COPYPOSTFIELDS is no longer valid. */
-      (void) Curl_setstropt(&data->set.str[STRING_COPYPOSTFIELDS], NULL);
+      Curl_safefree(data->set.str[STRING_COPYPOSTFIELDS]);
       data->set.postfields = NULL;
     }
 
@@ -565,7 +561,7 @@ CURLcode Curl_vsetopt(struct Curl_easy *data, CURLoption option, va_list param)
     if(data->set.postfieldsize < bigsize &&
        data->set.postfields == data->set.str[STRING_COPYPOSTFIELDS]) {
       /* Previous CURLOPT_COPYPOSTFIELDS is no longer valid. */
-      (void) Curl_setstropt(&data->set.str[STRING_COPYPOSTFIELDS], NULL);
+      Curl_safefree(data->set.str[STRING_COPYPOSTFIELDS]);
       data->set.postfields = NULL;
     }
 
@@ -577,7 +573,7 @@ CURLcode Curl_vsetopt(struct Curl_easy *data, CURLoption option, va_list param)
     /*
      * Switch on automatic referer that gets set if curl follows locations.
      */
-    data->set.http_auto_referer = (0 != va_arg(param, long)) ? TRUE : FALSE;
+    data->set.http_auto_referer = (0 != va_arg(param, long));
     break;
 
   case CURLOPT_ACCEPT_ENCODING:
@@ -592,28 +588,23 @@ CURLcode Curl_vsetopt(struct Curl_easy *data, CURLoption option, va_list param)
      */
     argptr = va_arg(param, char *);
     if(argptr && !*argptr) {
-      argptr = Curl_all_content_encodings();
-      if(!argptr)
-        result = CURLE_OUT_OF_MEMORY;
-      else {
-        result = Curl_setstropt(&data->set.str[STRING_ENCODING], argptr);
-        free(argptr);
-      }
+      char all[256];
+      Curl_all_content_encodings(all, sizeof(all));
+      result = Curl_setstropt(&data->set.str[STRING_ENCODING], all);
     }
     else
       result = Curl_setstropt(&data->set.str[STRING_ENCODING], argptr);
     break;
 
   case CURLOPT_TRANSFER_ENCODING:
-    data->set.http_transfer_encoding = (0 != va_arg(param, long)) ?
-      TRUE : FALSE;
+    data->set.http_transfer_encoding = (0 != va_arg(param, long));
     break;
 
   case CURLOPT_FOLLOWLOCATION:
     /*
      * Follow Location: header hints on an HTTP-server.
      */
-    data->set.http_follow_location = (0 != va_arg(param, long)) ? TRUE : FALSE;
+    data->set.http_follow_location = (0 != va_arg(param, long));
     break;
 
   case CURLOPT_UNRESTRICTED_AUTH:
@@ -621,8 +612,7 @@ CURLcode Curl_vsetopt(struct Curl_easy *data, CURLoption option, va_list param)
      * Send authentication (user+password) when following locations, even when
      * hostname changed.
      */
-    data->set.allow_auth_to_other_hosts =
-      (0 != va_arg(param, long)) ? TRUE : FALSE;
+    data->set.allow_auth_to_other_hosts = (0 != va_arg(param, long));
     break;
 
   case CURLOPT_MAXREDIRS:
@@ -676,6 +666,7 @@ CURLcode Curl_vsetopt(struct Curl_easy *data, CURLoption option, va_list param)
     data->set.opt_no_body = FALSE; /* this is implied */
     Curl_mime_cleanpart(data->state.formp);
     Curl_safefree(data->state.formp);
+    data->state.mimepost = NULL;
     break;
 #endif
 
@@ -736,7 +727,7 @@ CURLcode Curl_vsetopt(struct Curl_easy *data, CURLoption option, va_list param)
      * Set header option.
      */
     arg = va_arg(param, long);
-    data->set.sep_headers = (bool)((arg & CURLHEADER_SEPARATE)? TRUE: FALSE);
+    data->set.sep_headers = !!(arg & CURLHEADER_SEPARATE);
     break;
 
 #if !defined(CURL_DISABLE_COOKIES)
@@ -760,18 +751,18 @@ CURLcode Curl_vsetopt(struct Curl_easy *data, CURLoption option, va_list param)
         return CURLE_BAD_FUNCTION_ARGUMENT;
       /* append the cookie file name to the list of file names, and deal with
          them later */
-      cl = curl_slist_append(data->set.cookielist, argptr);
+      cl = curl_slist_append(data->state.cookielist, argptr);
       if(!cl) {
-        curl_slist_free_all(data->set.cookielist);
-        data->set.cookielist = NULL;
+        curl_slist_free_all(data->state.cookielist);
+        data->state.cookielist = NULL;
         return CURLE_OUT_OF_MEMORY;
       }
-      data->set.cookielist = cl; /* store the list for later use */
+      data->state.cookielist = cl; /* store the list for later use */
     }
     else {
       /* clear the list of cookie files */
-      curl_slist_free_all(data->set.cookielist);
-      data->set.cookielist = NULL;
+      curl_slist_free_all(data->state.cookielist);
+      data->state.cookielist = NULL;
 
       if(!data->share || !data->share->cookies) {
         /* throw away all existing cookies if this isn't a shared cookie
@@ -788,22 +779,20 @@ CURLcode Curl_vsetopt(struct Curl_easy *data, CURLoption option, va_list param)
     /*
      * Set cookie file name to dump all cookies to when we're done.
      */
-  {
-    struct CookieInfo *newcookies;
     result = Curl_setstropt(&data->set.str[STRING_COOKIEJAR],
                             va_arg(param, char *));
-
-    /*
-     * Activate the cookie parser. This may or may not already
-     * have been made.
-     */
-    newcookies = Curl_cookie_init(data, NULL, data->cookies,
-                                  data->set.cookiesession);
-    if(!newcookies)
-      result = CURLE_OUT_OF_MEMORY;
-    data->cookies = newcookies;
-  }
-  break;
+    if(!result) {
+      /*
+       * Activate the cookie parser. This may or may not already
+       * have been made.
+       */
+      struct CookieInfo *newcookies =
+        Curl_cookie_init(data, NULL, data->cookies, data->set.cookiesession);
+      if(!newcookies)
+        result = CURLE_OUT_OF_MEMORY;
+      data->cookies = newcookies;
+    }
+    break;
 
   case CURLOPT_COOKIESESSION:
     /*
@@ -811,17 +800,8 @@ CURLcode Curl_vsetopt(struct Curl_easy *data, CURLoption option, va_list param)
      * prevent the forthcoming read-cookies-from-file actions to accept
      * cookies that are marked as being session cookies, as they belong to a
      * previous session.
-     *
-     * In the original Netscape cookie spec, "session cookies" are cookies
-     * with no expire date set. RFC2109 describes the same action if no
-     * 'Max-Age' is set and RFC2965 includes the RFC2109 description and adds
-     * a 'Discard' action that can enforce the discard even for cookies that
-     * have a Max-Age.
-     *
-     * We run mostly with the original cookie spec, as hardly anyone implements
-     * anything else.
      */
-    data->set.cookiesession = (0 != va_arg(param, long)) ? TRUE : FALSE;
+    data->set.cookiesession = (0 != va_arg(param, long));
     break;
 
   case CURLOPT_COOKIELIST:
@@ -921,7 +901,7 @@ CURLcode Curl_vsetopt(struct Curl_easy *data, CURLoption option, va_list param)
       /* accepted */
       break;
 #endif
-#ifdef ENABLE_QUIC
+#ifdef USE_HTTP3
     case CURL_HTTP_VERSION_3:
     case CURL_HTTP_VERSION_3ONLY:
       /* accepted */
@@ -956,7 +936,7 @@ CURLcode Curl_vsetopt(struct Curl_easy *data, CURLoption option, va_list param)
     if(arg)
       return CURLE_BAD_FUNCTION_ARGUMENT;
 #else
-    data->set.http09_allowed = arg ? TRUE : FALSE;
+    data->set.http09_allowed = !!arg;
 #endif
     break;
 
@@ -992,13 +972,15 @@ CURLcode Curl_vsetopt(struct Curl_easy *data, CURLoption option, va_list param)
 #ifndef CURL_DISABLE_FORM_API
       Curl_mime_cleanpart(data->state.formp);
       Curl_safefree(data->state.formp);
+      data->state.mimepost = NULL;
 #endif
     }
     break;
 
   case CURLOPT_MIME_OPTIONS:
-    data->set.mime_options = (unsigned int)va_arg(param, long);
-    break;
+    arg = va_arg(param, long);
+    data->set.mime_formescape = !!(arg & CURLMIMEOPT_FORMESCAPE);
+  break;
 # endif
 #endif
 
@@ -1018,8 +1000,7 @@ CURLcode Curl_vsetopt(struct Curl_easy *data, CURLoption option, va_list param)
 
     /* the DIGEST_IE bit is only used to set a special marker, for all the
        rest we need to handle it as normal DIGEST */
-    data->state.authhost.iestyle =
-      (bool)((auth & CURLAUTH_DIGEST_IE) ? TRUE : FALSE);
+    data->state.authhost.iestyle = !!(auth & CURLAUTH_DIGEST_IE);
 
     if(auth & CURLAUTH_DIGEST_IE) {
       auth |= CURLAUTH_DIGEST; /* set standard digest bit */
@@ -1029,9 +1010,6 @@ CURLcode Curl_vsetopt(struct Curl_easy *data, CURLoption option, va_list param)
     /* switch off bits we can't support */
 #ifndef USE_NTLM
     auth &= ~CURLAUTH_NTLM;    /* no NTLM support */
-    auth &= ~CURLAUTH_NTLM_WB; /* no NTLM_WB support */
-#elif !defined(NTLM_WB_ENABLED)
-    auth &= ~CURLAUTH_NTLM_WB; /* no NTLM_WB support */
 #endif
 #ifndef USE_SPNEGO
     auth &= ~CURLAUTH_NEGOTIATE; /* no Negotiate (SPNEGO) auth without
@@ -1072,8 +1050,7 @@ CURLcode Curl_vsetopt(struct Curl_easy *data, CURLoption option, va_list param)
     /*
      * Tunnel operations through the proxy instead of normal proxy use
      */
-    data->set.tunnel_thru_httpproxy = (0 != va_arg(param, long)) ?
-      TRUE : FALSE;
+    data->set.tunnel_thru_httpproxy = (0 != va_arg(param, long));
     break;
 
   case CURLOPT_PROXYPORT:
@@ -1102,8 +1079,7 @@ CURLcode Curl_vsetopt(struct Curl_easy *data, CURLoption option, va_list param)
 
     /* the DIGEST_IE bit is only used to set a special marker, for all the
        rest we need to handle it as normal DIGEST */
-    data->state.authproxy.iestyle =
-      (bool)((auth & CURLAUTH_DIGEST_IE) ? TRUE : FALSE);
+    data->state.authproxy.iestyle = !!(auth & CURLAUTH_DIGEST_IE);
 
     if(auth & CURLAUTH_DIGEST_IE) {
       auth |= CURLAUTH_DIGEST; /* set standard digest bit */
@@ -1112,9 +1088,6 @@ CURLcode Curl_vsetopt(struct Curl_easy *data, CURLoption option, va_list param)
     /* switch off bits we can't support */
 #ifndef USE_NTLM
     auth &= ~CURLAUTH_NTLM;    /* no NTLM support */
-    auth &= ~CURLAUTH_NTLM_WB; /* no NTLM_WB support */
-#elif !defined(NTLM_WB_ENABLED)
-    auth &= ~CURLAUTH_NTLM_WB; /* no NTLM_WB support */
 #endif
 #ifndef USE_SPNEGO
     auth &= ~CURLAUTH_NEGOTIATE; /* no Negotiate (SPNEGO) auth without
@@ -1203,7 +1176,7 @@ CURLcode Curl_vsetopt(struct Curl_easy *data, CURLoption option, va_list param)
     /*
      * Set flag for NEC SOCK5 support
      */
-    data->set.socks5_gssapi_nec = (0 != va_arg(param, long)) ? TRUE : FALSE;
+    data->set.socks5_gssapi_nec = (0 != va_arg(param, long));
     break;
 #endif
 #ifndef CURL_DISABLE_PROXY
@@ -1251,7 +1224,7 @@ CURLcode Curl_vsetopt(struct Curl_easy *data, CURLoption option, va_list param)
      * An option that changes the command to one that asks for a list only, no
      * file info details. Used for FTP, POP3 and SFTP.
      */
-    data->set.list_only = (0 != va_arg(param, long)) ? TRUE : FALSE;
+    data->set.list_only = (0 != va_arg(param, long));
     break;
 #endif
   case CURLOPT_APPEND:
@@ -1259,7 +1232,7 @@ CURLcode Curl_vsetopt(struct Curl_easy *data, CURLoption option, va_list param)
      * We want to upload and append to an existing file. Used for FTP and
      * SFTP.
      */
-    data->set.remote_append = (0 != va_arg(param, long)) ? TRUE : FALSE;
+    data->set.remote_append = (0 != va_arg(param, long));
     break;
 
 #ifndef CURL_DISABLE_FTP
@@ -1270,7 +1243,7 @@ CURLcode Curl_vsetopt(struct Curl_easy *data, CURLoption option, va_list param)
     arg = va_arg(param, long);
     if((arg < CURLFTPMETHOD_DEFAULT) || (arg >= CURLFTPMETHOD_LAST))
       return CURLE_BAD_FUNCTION_ARGUMENT;
-    data->set.ftp_filemethod = (unsigned char)(curl_ftpfile)arg;
+    data->set.ftp_filemethod = (unsigned char)arg;
     break;
   case CURLOPT_FTPPORT:
     /*
@@ -1278,26 +1251,26 @@ CURLcode Curl_vsetopt(struct Curl_easy *data, CURLoption option, va_list param)
      */
     result = Curl_setstropt(&data->set.str[STRING_FTPPORT],
                             va_arg(param, char *));
-    data->set.ftp_use_port = (data->set.str[STRING_FTPPORT]) ? TRUE : FALSE;
+    data->set.ftp_use_port = !!(data->set.str[STRING_FTPPORT]);
     break;
 
   case CURLOPT_FTP_USE_EPRT:
-    data->set.ftp_use_eprt = (0 != va_arg(param, long)) ? TRUE : FALSE;
+    data->set.ftp_use_eprt = (0 != va_arg(param, long));
     break;
 
   case CURLOPT_FTP_USE_EPSV:
-    data->set.ftp_use_epsv = (0 != va_arg(param, long)) ? TRUE : FALSE;
+    data->set.ftp_use_epsv = (0 != va_arg(param, long));
     break;
 
   case CURLOPT_FTP_USE_PRET:
-    data->set.ftp_use_pret = (0 != va_arg(param, long)) ? TRUE : FALSE;
+    data->set.ftp_use_pret = (0 != va_arg(param, long));
     break;
 
   case CURLOPT_FTP_SSL_CCC:
     arg = va_arg(param, long);
     if((arg < CURLFTPSSL_CCC_NONE) || (arg >= CURLFTPSSL_CCC_LAST))
       return CURLE_BAD_FUNCTION_ARGUMENT;
-    data->set.ftp_ccc = (unsigned char)(curl_ftpccc)arg;
+    data->set.ftp_ccc = (unsigned char)arg;
     break;
 
   case CURLOPT_FTP_SKIP_PASV_IP:
@@ -1305,7 +1278,7 @@ CURLcode Curl_vsetopt(struct Curl_easy *data, CURLoption option, va_list param)
      * Enable or disable FTP_SKIP_PASV_IP, which will disable/enable the
      * bypass of the IP address in PASV responses.
      */
-    data->set.ftp_skip_ip = (0 != va_arg(param, long)) ? TRUE : FALSE;
+    data->set.ftp_skip_ip = (0 != va_arg(param, long));
     break;
 
   case CURLOPT_FTP_ACCOUNT:
@@ -1327,15 +1300,17 @@ CURLcode Curl_vsetopt(struct Curl_easy *data, CURLoption option, va_list param)
       return CURLE_BAD_FUNCTION_ARGUMENT;
     data->set.ftpsslauth = (unsigned char)(curl_ftpauth)arg;
     break;
+#ifdef HAVE_GSSAPI
   case CURLOPT_KRBLEVEL:
     /*
      * A string that defines the kerberos security level.
      */
     result = Curl_setstropt(&data->set.str[STRING_KRB_LEVEL],
                             va_arg(param, char *));
-    data->set.krb = (data->set.str[STRING_KRB_LEVEL]) ? TRUE : FALSE;
+    data->set.krb = !!(data->set.str[STRING_KRB_LEVEL]);
     break;
 #endif
+#endif
 #if !defined(CURL_DISABLE_FTP) || defined(USE_SSH)
   case CURLOPT_FTP_CREATE_MISSING_DIRS:
     /*
@@ -1602,13 +1577,24 @@ CURLcode Curl_vsetopt(struct Curl_easy *data, CURLoption option, va_list param)
     break;
 
 #ifndef CURL_DISABLE_PROXY
-  case CURLOPT_PROXYUSERPWD:
+  case CURLOPT_PROXYUSERPWD: {
     /*
      * user:password needed to use the proxy
      */
-    result = setstropt_userpwd(va_arg(param, char *),
-                               &data->set.str[STRING_PROXYUSERNAME],
-                               &data->set.str[STRING_PROXYPASSWORD]);
+    char *u = NULL;
+    char *p = NULL;
+    result = setstropt_userpwd(va_arg(param, char *), &u, &p);
+
+    /* URL decode the components */
+    if(!result && u)
+      result = Curl_urldecode(u, 0, &data->set.str[STRING_PROXYUSERNAME], NULL,
+                              REJECT_ZERO);
+    if(!result && p)
+      result = Curl_urldecode(p, 0, &data->set.str[STRING_PROXYPASSWORD], NULL,
+                              REJECT_ZERO);
+    free(u);
+    free(p);
+  }
     break;
   case CURLOPT_PROXYUSERNAME:
     /*
@@ -1860,21 +1846,21 @@ CURLcode Curl_vsetopt(struct Curl_easy *data, CURLoption option, va_list param)
     /*
      * flag to set engine as default.
      */
-    Curl_setstropt(&data->set.str[STRING_SSL_ENGINE], NULL);
+    Curl_safefree(data->set.str[STRING_SSL_ENGINE]);
     result = Curl_ssl_set_engine_default(data);
     break;
   case CURLOPT_CRLF:
     /*
      * Kludgy option to enable CRLF conversions. Subject for removal.
      */
-    data->set.crlf = (0 != va_arg(param, long)) ? TRUE : FALSE;
+    data->set.crlf = (0 != va_arg(param, long));
     break;
 #ifndef CURL_DISABLE_PROXY
   case CURLOPT_HAPROXYPROTOCOL:
     /*
      * Set to send the HAProxy Proxy Protocol header
      */
-    data->set.haproxyprotocol = (0 != va_arg(param, long)) ? TRUE : FALSE;
+    data->set.haproxyprotocol = (0 != va_arg(param, long));
     break;
   case CURLOPT_HAPROXY_CLIENT_IP:
     /*
@@ -1926,22 +1912,17 @@ CURLcode Curl_vsetopt(struct Curl_easy *data, CURLoption option, va_list param)
     /*
      * Enable peer SSL verifying.
      */
-    data->set.ssl.primary.verifypeer = (0 != va_arg(param, long)) ?
-      TRUE : FALSE;
+    data->set.ssl.primary.verifypeer = (0 != va_arg(param, long));
 
     /* Update the current connection ssl_config. */
-    if(data->conn) {
-      data->conn->ssl_config.verifypeer =
-        data->set.ssl.primary.verifypeer;
-    }
+    Curl_ssl_conn_config_update(data, FALSE);
     break;
 #ifndef CURL_DISABLE_DOH
   case CURLOPT_DOH_SSL_VERIFYPEER:
     /*
      * Enable peer SSL verifying for DoH.
      */
-    data->set.doh_verifypeer = (0 != va_arg(param, long)) ?
-      TRUE : FALSE;
+    data->set.doh_verifypeer = (0 != va_arg(param, long));
     break;
 #endif
 #ifndef CURL_DISABLE_PROXY
@@ -1953,10 +1934,7 @@ CURLcode Curl_vsetopt(struct Curl_easy *data, CURLoption option, va_list param)
       (0 != va_arg(param, long))?TRUE:FALSE;
 
     /* Update the current connection proxy_ssl_config. */
-    if(data->conn) {
-      data->conn->proxy_ssl_config.verifypeer =
-        data->set.proxy_ssl.primary.verifypeer;
-    }
+    Curl_ssl_conn_config_update(data, TRUE);
     break;
 #endif
   case CURLOPT_SSL_VERIFYHOST:
@@ -1968,13 +1946,10 @@ CURLcode Curl_vsetopt(struct Curl_easy *data, CURLoption option, va_list param)
     /* Obviously people are not reading documentation and too many thought
        this argument took a boolean when it wasn't and misused it.
        Treat 1 and 2 the same */
-    data->set.ssl.primary.verifyhost = (bool)((arg & 3) ? TRUE : FALSE);
+    data->set.ssl.primary.verifyhost = !!(arg & 3);
 
     /* Update the current connection ssl_config. */
-    if(data->conn) {
-      data->conn->ssl_config.verifyhost =
-        data->set.ssl.primary.verifyhost;
-    }
+    Curl_ssl_conn_config_update(data, FALSE);
     break;
 #ifndef CURL_DISABLE_DOH
   case CURLOPT_DOH_SSL_VERIFYHOST:
@@ -1984,7 +1959,7 @@ CURLcode Curl_vsetopt(struct Curl_easy *data, CURLoption option, va_list param)
     arg = va_arg(param, long);
 
     /* Treat both 1 and 2 as TRUE */
-    data->set.doh_verifyhost = (bool)((arg & 3) ? TRUE : FALSE);
+    data->set.doh_verifyhost = !!(arg & 3);
     break;
 #endif
 #ifndef CURL_DISABLE_PROXY
@@ -1996,12 +1971,8 @@ CURLcode Curl_vsetopt(struct Curl_easy *data, CURLoption option, va_list param)
 
     /* Treat both 1 and 2 as TRUE */
     data->set.proxy_ssl.primary.verifyhost = (bool)((arg & 3)?TRUE:FALSE);
-
     /* Update the current connection proxy_ssl_config. */
-    if(data->conn) {
-      data->conn->proxy_ssl_config.verifyhost =
-        data->set.proxy_ssl.primary.verifyhost;
-    }
+    Curl_ssl_conn_config_update(data, TRUE);
     break;
 #endif
   case CURLOPT_SSL_VERIFYSTATUS:
@@ -2013,14 +1984,10 @@ CURLcode Curl_vsetopt(struct Curl_easy *data, CURLoption option, va_list param)
       break;
     }
 
-    data->set.ssl.primary.verifystatus = (0 != va_arg(param, long)) ?
-      TRUE : FALSE;
+    data->set.ssl.primary.verifystatus = (0 != va_arg(param, long));
 
     /* Update the current connection ssl_config. */
-    if(data->conn) {
-      data->conn->ssl_config.verifystatus =
-        data->set.ssl.primary.verifystatus;
-    }
+    Curl_ssl_conn_config_update(data, FALSE);
     break;
 #ifndef CURL_DISABLE_DOH
   case CURLOPT_DOH_SSL_VERIFYSTATUS:
@@ -2032,8 +1999,7 @@ CURLcode Curl_vsetopt(struct Curl_easy *data, CURLoption option, va_list param)
       break;
     }
 
-    data->set.doh_verifystatus = (0 != va_arg(param, long)) ?
-      TRUE : FALSE;
+    data->set.doh_verifystatus = (0 != va_arg(param, long));
     break;
 #endif
   case CURLOPT_SSL_CTX_FUNCTION:
@@ -2067,16 +2033,16 @@ CURLcode Curl_vsetopt(struct Curl_easy *data, CURLoption option, va_list param)
       break;
     }
 
-    data->set.ssl.falsestart = (0 != va_arg(param, long)) ? TRUE : FALSE;
+    data->set.ssl.falsestart = (0 != va_arg(param, long));
     break;
   case CURLOPT_CERTINFO:
 #ifdef USE_SSL
     if(Curl_ssl_supports(data, SSLSUPP_CERTINFO))
-      data->set.ssl.certinfo = (0 != va_arg(param, long)) ? TRUE : FALSE;
+      data->set.ssl.certinfo = (0 != va_arg(param, long));
     else
 #endif
       result = CURLE_NOT_BUILT_IN;
-        break;
+    break;
   case CURLOPT_PINNEDPUBLICKEY:
     /*
      * Set pinned public key for SSL connection.
@@ -2118,14 +2084,14 @@ CURLcode Curl_vsetopt(struct Curl_easy *data, CURLoption option, va_list param)
      * Specify entire PEM of the CA certificate
      */
 #ifdef USE_SSL
-    if(Curl_ssl_supports(data, SSLSUPP_CAINFO_BLOB))
+    if(Curl_ssl_supports(data, SSLSUPP_CAINFO_BLOB)) {
       result = Curl_setblobopt(&data->set.blobs[BLOB_CAINFO],
                                va_arg(param, struct curl_blob *));
+      break;
+    }
     else
 #endif
       return CURLE_NOT_BUILT_IN;
-
-    break;
 #ifndef CURL_DISABLE_PROXY
   case CURLOPT_PROXY_CAINFO:
     /*
@@ -2141,13 +2107,14 @@ CURLcode Curl_vsetopt(struct Curl_easy *data, CURLoption option, va_list param)
      * Specify entire PEM of the CA certificate
      */
 #ifdef USE_SSL
-    if(Curl_ssl_supports(data, SSLSUPP_CAINFO_BLOB))
+    if(Curl_ssl_supports(data, SSLSUPP_CAINFO_BLOB)) {
       result = Curl_setblobopt(&data->set.blobs[BLOB_CAINFO_PROXY],
                                va_arg(param, struct curl_blob *));
+      break;
+    }
     else
 #endif
       return CURLE_NOT_BUILT_IN;
-    break;
 #endif
   case CURLOPT_CAPATH:
     /*
@@ -2242,9 +2209,6 @@ CURLcode Curl_vsetopt(struct Curl_easy *data, CURLoption option, va_list param)
      * The application kindly asks for a differently sized receive buffer.
      * If it seems reasonable, we'll use it.
      */
-    if(data->state.buffer)
-      return CURLE_BAD_FUNCTION_ARGUMENT;
-
     arg = va_arg(param, long);
 
     if(arg > READBUFFER_MAX)
@@ -2270,7 +2234,6 @@ CURLcode Curl_vsetopt(struct Curl_easy *data, CURLoption option, va_list param)
       arg = UPLOADBUFFER_MIN;
 
     data->set.upload_buffer_size = (unsigned int)arg;
-    Curl_safefree(data->state.ulbuf); /* force a realloc next opportunity */
     break;
 
   case CURLOPT_NOSIGNAL:
@@ -2278,7 +2241,7 @@ CURLcode Curl_vsetopt(struct Curl_easy *data, CURLoption option, va_list param)
      * The application asks not to set any signal() or alarm() handlers,
      * even when using a timeout.
      */
-    data->set.no_signal = (0 != va_arg(param, long)) ? TRUE : FALSE;
+    data->set.no_signal = (0 != va_arg(param, long));
     break;
 
   case CURLOPT_SHARE:
@@ -2347,7 +2310,7 @@ CURLcode Curl_vsetopt(struct Curl_easy *data, CURLoption option, va_list param)
         Curl_hsts_cleanup(&data->hsts);
         data->hsts = data->share->hsts;
       }
-#endif   /* CURL_DISABLE_HTTP */
+#endif
 #ifdef USE_SSL
       if(data->share->sslsession) {
         data->set.general_ssl.max_ssl_sessions = data->share->max_ssl_sessions;
@@ -2453,11 +2416,11 @@ CURLcode Curl_vsetopt(struct Curl_easy *data, CURLoption option, va_list param)
      * Enable or disable TCP_NODELAY, which will disable/enable the Nagle
      * algorithm
      */
-    data->set.tcp_nodelay = (0 != va_arg(param, long)) ? TRUE : FALSE;
+    data->set.tcp_nodelay = (0 != va_arg(param, long));
     break;
 
   case CURLOPT_IGNORE_CONTENT_LENGTH:
-    data->set.ignorecl = (0 != va_arg(param, long)) ? TRUE : FALSE;
+    data->set.ignorecl = (0 != va_arg(param, long));
     break;
 
   case CURLOPT_CONNECT_ONLY:
@@ -2532,8 +2495,7 @@ CURLcode Curl_vsetopt(struct Curl_easy *data, CURLoption option, va_list param)
     break;
 
   case CURLOPT_SSL_SESSIONID_CACHE:
-    data->set.ssl.primary.sessionid = (0 != va_arg(param, long)) ?
-      TRUE : FALSE;
+    data->set.ssl.primary.sessionid = (0 != va_arg(param, long));
 #ifndef CURL_DISABLE_PROXY
     data->set.proxy_ssl.primary.sessionid = data->set.ssl.primary.sessionid;
 #endif
@@ -2622,7 +2584,7 @@ CURLcode Curl_vsetopt(struct Curl_easy *data, CURLoption option, va_list param)
      * disable libcurl transfer encoding is used
      */
 #ifndef USE_HYPER
-    data->set.http_te_skip = (0 == va_arg(param, long)) ? TRUE : FALSE;
+    data->set.http_te_skip = (0 == va_arg(param, long));
     break;
 #else
     return CURLE_NOT_BUILT_IN; /* hyper doesn't support */
@@ -2632,7 +2594,7 @@ CURLcode Curl_vsetopt(struct Curl_easy *data, CURLoption option, va_list param)
     /*
      * raw data passed to the application when content encoding is used
      */
-    data->set.http_ce_skip = (0 == va_arg(param, long)) ? TRUE : FALSE;
+    data->set.http_ce_skip = (0 == va_arg(param, long));
     break;
 
 #if !defined(CURL_DISABLE_FTP) || defined(USE_SSH)
@@ -2658,7 +2620,7 @@ CURLcode Curl_vsetopt(struct Curl_easy *data, CURLoption option, va_list param)
     break;
 #endif
 
-#ifdef ENABLE_IPV6
+#ifdef USE_IPV6
   case CURLOPT_ADDRESS_SCOPE:
     /*
      * Use this scope id when using IPv6
@@ -2690,22 +2652,18 @@ CURLcode Curl_vsetopt(struct Curl_easy *data, CURLoption option, va_list param)
     break;
 
   case CURLOPT_PROTOCOLS_STR: {
-    curl_prot_t prot;
     argptr = va_arg(param, char *);
-    result = protocol2num(argptr, &prot);
+    result = protocol2num(argptr, &data->set.allowed_protocols);
     if(result)
       return result;
-    data->set.allowed_protocols = prot;
     break;
   }
 
   case CURLOPT_REDIR_PROTOCOLS_STR: {
-    curl_prot_t prot;
     argptr = va_arg(param, char *);
-    result = protocol2num(argptr, &prot);
+    result = protocol2num(argptr, &data->set.redir_protocols);
     if(result)
       return result;
-    data->set.redir_protocols = prot;
     break;
   }
 
@@ -2733,7 +2691,7 @@ CURLcode Curl_vsetopt(struct Curl_easy *data, CURLoption option, va_list param)
     break;
   case CURLOPT_MAIL_RCPT_ALLOWFAILS:
     /* allow RCPT TO command to fail for some recipients */
-    data->set.mail_rcpt_allowfails = (0 != va_arg(param, long)) ? TRUE : FALSE;
+    data->set.mail_rcpt_allowfails = (0 != va_arg(param, long));
     break;
 #endif
 
@@ -2745,7 +2703,7 @@ CURLcode Curl_vsetopt(struct Curl_easy *data, CURLoption option, va_list param)
 
   case CURLOPT_SASL_IR:
     /* Enable/disable SASL initial response */
-    data->set.sasl_ir = (0 != va_arg(param, long)) ? TRUE : FALSE;
+    data->set.sasl_ir = (0 != va_arg(param, long));
     break;
 #ifndef CURL_DISABLE_RTSP
   case CURLOPT_RTSP_REQUEST:
@@ -2859,7 +2817,7 @@ CURLcode Curl_vsetopt(struct Curl_easy *data, CURLoption option, va_list param)
 #endif
 #ifndef CURL_DISABLE_FTP
   case CURLOPT_WILDCARDMATCH:
-    data->set.wildcard_enabled = (0 != va_arg(param, long)) ? TRUE : FALSE;
+    data->set.wildcard_enabled = (0 != va_arg(param, long));
     break;
   case CURLOPT_CHUNK_BGN_FUNCTION:
     data->set.chunk_bgn = va_arg(param, curl_chunk_bgn_callback);
@@ -2900,13 +2858,13 @@ CURLcode Curl_vsetopt(struct Curl_easy *data, CURLoption option, va_list param)
 #endif
   case CURLOPT_TLSAUTH_TYPE:
     argptr = va_arg(param, char *);
-    if(argptr && !strncasecompare(argptr, "SRP", strlen("SRP")))
+    if(argptr && !strcasecompare(argptr, "SRP"))
       return CURLE_BAD_FUNCTION_ARGUMENT;
     break;
 #ifndef CURL_DISABLE_PROXY
   case CURLOPT_PROXY_TLSAUTH_TYPE:
     argptr = va_arg(param, char *);
-    if(argptr || !strncasecompare(argptr, "SRP", strlen("SRP")))
+    if(argptr && !strcasecompare(argptr, "SRP"))
       return CURLE_BAD_FUNCTION_ARGUMENT;
     break;
 #endif
@@ -2942,7 +2900,7 @@ CURLcode Curl_vsetopt(struct Curl_easy *data, CURLoption option, va_list param)
     break;
 #endif
   case CURLOPT_TCP_KEEPALIVE:
-    data->set.tcp_keepalive = (0 != va_arg(param, long)) ? TRUE : FALSE;
+    data->set.tcp_keepalive = (0 != va_arg(param, long));
     break;
   case CURLOPT_TCP_KEEPIDLE:
     arg = va_arg(param, long);
@@ -2971,7 +2929,7 @@ CURLcode Curl_vsetopt(struct Curl_easy *data, CURLoption option, va_list param)
   case CURLOPT_SSL_ENABLE_NPN:
     break;
   case CURLOPT_SSL_ENABLE_ALPN:
-    data->set.ssl_enable_alpn = (0 != va_arg(param, long)) ? TRUE : FALSE;
+    data->set.ssl_enable_alpn = (0 != va_arg(param, long));
     break;
 #ifdef USE_UNIX_SOCKETS
   case CURLOPT_UNIX_SOCKET_PATH:
@@ -2987,10 +2945,10 @@ CURLcode Curl_vsetopt(struct Curl_easy *data, CURLoption option, va_list param)
 #endif
 
   case CURLOPT_PATH_AS_IS:
-    data->set.path_as_is = (0 != va_arg(param, long)) ? TRUE : FALSE;
+    data->set.path_as_is = (0 != va_arg(param, long));
     break;
   case CURLOPT_PIPEWAIT:
-    data->set.pipewait = (0 != va_arg(param, long)) ? TRUE : FALSE;
+    data->set.pipewait = (0 != va_arg(param, long));
     break;
   case CURLOPT_STREAM_WEIGHT:
 #if defined(USE_HTTP2) || defined(USE_HTTP3)
@@ -3025,12 +2983,11 @@ CURLcode Curl_vsetopt(struct Curl_easy *data, CURLoption option, va_list param)
     break;
 #ifndef CURL_DISABLE_SHUFFLE_DNS
   case CURLOPT_DNS_SHUFFLE_ADDRESSES:
-    data->set.dns_shuffle_addresses = (0 != va_arg(param, long)) ? TRUE:FALSE;
+    data->set.dns_shuffle_addresses = (0 != va_arg(param, long));
     break;
 #endif
   case CURLOPT_DISALLOW_USERNAME_IN_URL:
-    data->set.disallow_username_in_url =
-      (0 != va_arg(param, long)) ? TRUE : FALSE;
+    data->set.disallow_username_in_url = (0 != va_arg(param, long));
     break;
 #ifndef CURL_DISABLE_DOH
   case CURLOPT_DOH_URL:
@@ -3095,18 +3052,18 @@ CURLcode Curl_vsetopt(struct Curl_easy *data, CURLoption option, va_list param)
       /* this needs to build a list of file names to read from, so that it can
          read them later, as we might get a shared HSTS handle to load them
          into */
-      h = curl_slist_append(data->set.hstslist, argptr);
+      h = curl_slist_append(data->state.hstslist, argptr);
       if(!h) {
-        curl_slist_free_all(data->set.hstslist);
-        data->set.hstslist = NULL;
+        curl_slist_free_all(data->state.hstslist);
+        data->state.hstslist = NULL;
         return CURLE_OUT_OF_MEMORY;
       }
-      data->set.hstslist = h; /* store the list for later use */
+      data->state.hstslist = h; /* store the list for later use */
     }
     else {
       /* clear the list of HSTS files */
-      curl_slist_free_all(data->set.hstslist);
-      data->set.hstslist = NULL;
+      curl_slist_free_all(data->state.hstslist);
+      data->state.hstslist = NULL;
       if(!data->share || !data->share->hsts)
         /* throw away the HSTS cache unless shared */
         Curl_hsts_cleanup(&data->hsts);
@@ -3147,6 +3104,10 @@ CURLcode Curl_vsetopt(struct Curl_easy *data, CURLoption option, va_list param)
         return CURLE_OUT_OF_MEMORY;
     }
     arg = va_arg(param, long);
+    if(!arg) {
+      DEBUGF(infof(data, "bad CURLOPT_ALTSVC_CTRL input"));
+      return CURLE_BAD_FUNCTION_ARGUMENT;
+    }
     result = Curl_altsvc_ctrl(data->asi, arg);
     if(result)
       return result;
@@ -3166,6 +3127,49 @@ CURLcode Curl_vsetopt(struct Curl_easy *data, CURLoption option, va_list param)
     data->set.ws_raw_mode = raw;
     break;
   }
+#endif
+#ifdef USE_ECH
+  case CURLOPT_ECH: {
+    size_t plen = 0;
+
+    argptr = va_arg(param, char *);
+    if(!argptr) {
+      data->set.tls_ech = CURLECH_DISABLE;
+      result = CURLE_BAD_FUNCTION_ARGUMENT;
+      return result;
+    }
+    plen = strlen(argptr);
+    if(plen > CURL_MAX_INPUT_LENGTH) {
+      data->set.tls_ech = CURLECH_DISABLE;
+      result = CURLE_BAD_FUNCTION_ARGUMENT;
+      return result;
+    }
+    /* set tls_ech flag value, preserving CLA_CFG bit */
+    if(plen == 5 && !strcmp(argptr, "false"))
+      data->set.tls_ech = CURLECH_DISABLE
+                          | (data->set.tls_ech & CURLECH_CLA_CFG);
+    else if(plen == 6 && !strcmp(argptr, "grease"))
+      data->set.tls_ech = CURLECH_GREASE
+                          | (data->set.tls_ech & CURLECH_CLA_CFG);
+    else if(plen == 4 && !strcmp(argptr, "true"))
+      data->set.tls_ech = CURLECH_ENABLE
+                          | (data->set.tls_ech & CURLECH_CLA_CFG);
+    else if(plen == 4 && !strcmp(argptr, "hard"))
+      data->set.tls_ech = CURLECH_HARD
+                          | (data->set.tls_ech & CURLECH_CLA_CFG);
+    else if(plen > 5 && !strncmp(argptr, "ecl:", 4)) {
+      result = Curl_setstropt(&data->set.str[STRING_ECH_CONFIG], argptr + 4);
+      if(result)
+        return result;
+      data->set.tls_ech |= CURLECH_CLA_CFG;
+    }
+    else if(plen > 4 && !strncmp(argptr, "pn:", 3)) {
+      result = Curl_setstropt(&data->set.str[STRING_ECH_PUBLIC], argptr + 3);
+      if(result)
+        return result;
+    }
+    break;
+  }
 #endif
   case CURLOPT_QUICK_EXIT:
     data->set.quick_exit = (0 != va_arg(param, long)) ? 1L:0L;
@@ -3201,5 +3205,9 @@ CURLcode curl_easy_setopt(struct Curl_easy *data, CURLoption tag, ...)
   result = Curl_vsetopt(data, tag, arg);
 
   va_end(arg);
+#ifdef DEBUGBUILD
+  if(result == CURLE_BAD_FUNCTION_ARGUMENT)
+    infof(data, "setopt arg 0x%x returned CURLE_BAD_FUNCTION_ARGUMENT", tag);
+#endif
   return result;
 }
diff --git a/vendor/curl/lib/setopt.h b/vendor/curl/lib/setopt.h
index 3c14a05e37..b0237467bd 100644
--- a/vendor/curl/lib/setopt.h
+++ b/vendor/curl/lib/setopt.h
@@ -24,9 +24,10 @@
  *
  ***************************************************************************/
 
-CURLcode Curl_setstropt(char **charp, const char *s);
+CURLcode Curl_setstropt(char **charp, const char *s) WARN_UNUSED_RESULT;
 CURLcode Curl_setblobopt(struct curl_blob **blobp,
-                         const struct curl_blob *blob);
-CURLcode Curl_vsetopt(struct Curl_easy *data, CURLoption option, va_list arg);
+                         const struct curl_blob *blob) WARN_UNUSED_RESULT;
+CURLcode Curl_vsetopt(struct Curl_easy *data, CURLoption option, va_list arg)
+  WARN_UNUSED_RESULT;
 
 #endif /* HEADER_CURL_SETOPT_H */
diff --git a/vendor/curl/lib/setup-vms.h b/vendor/curl/lib/setup-vms.h
index 645cc1a9cd..ea3936c708 100644
--- a/vendor/curl/lib/setup-vms.h
+++ b/vendor/curl/lib/setup-vms.h
@@ -374,8 +374,8 @@ static struct passwd *vms_getpwuid(uid_t uid)
 #ifdef HAVE_NETDB_H
 #include 
 #ifndef AI_NUMERICHOST
-#ifdef ENABLE_IPV6
-#undef ENABLE_IPV6
+#ifdef USE_IPV6
+#undef USE_IPV6
 #endif
 #endif
 #endif
diff --git a/vendor/curl/lib/setup-win32.h b/vendor/curl/lib/setup-win32.h
index 13948389a4..d7e2e6be11 100644
--- a/vendor/curl/lib/setup-win32.h
+++ b/vendor/curl/lib/setup-win32.h
@@ -24,18 +24,53 @@
  *
  ***************************************************************************/
 
+#undef USE_WINSOCK
+/* ---------------------------------------------------------------- */
+/*                     Watt-32 TCP/IP SPECIFIC                      */
+/* ---------------------------------------------------------------- */
+#ifdef USE_WATT32
+#  include 
+#  undef byte
+#  undef word
+#  define HAVE_SYS_IOCTL_H
+#  define HAVE_SYS_SOCKET_H
+#  define HAVE_NETINET_IN_H
+#  define HAVE_NETDB_H
+#  define HAVE_ARPA_INET_H
+#  define SOCKET int
+/* ---------------------------------------------------------------- */
+/*               BSD-style lwIP TCP/IP stack SPECIFIC               */
+/* ---------------------------------------------------------------- */
+#elif defined(USE_LWIPSOCK)
+  /* Define to use BSD-style lwIP TCP/IP stack. */
+  /* #define USE_LWIPSOCK 1 */
+#  undef HAVE_GETHOSTNAME
+#  undef LWIP_POSIX_SOCKETS_IO_NAMES
+#  undef RECV_TYPE_ARG1
+#  undef RECV_TYPE_ARG3
+#  undef SEND_TYPE_ARG1
+#  undef SEND_TYPE_ARG3
+#  define HAVE_GETHOSTBYNAME_R
+#  define HAVE_GETHOSTBYNAME_R_6
+#  define LWIP_POSIX_SOCKETS_IO_NAMES 0
+#  define RECV_TYPE_ARG1 int
+#  define RECV_TYPE_ARG3 size_t
+#  define SEND_TYPE_ARG1 int
+#  define SEND_TYPE_ARG3 size_t
+#elif defined(_WIN32)
+#  define USE_WINSOCK 2
+#endif
+
 /*
  * Include header files for windows builds before redefining anything.
  * Use this preprocessor block only to include or exclude windows.h,
  * winsock2.h or ws2tcpip.h. Any other windows thing belongs
  * to any other further and independent block.  Under Cygwin things work
  * just as under linux (e.g. ) and the winsock headers should
- * never be included when __CYGWIN__ is defined.  configure script takes
- * care of this, not defining HAVE_WINDOWS_H, HAVE_WINSOCK2_H,
- * neither HAVE_WS2TCPIP_H when __CYGWIN__ is defined.
+ * never be included when __CYGWIN__ is defined.
  */
 
-#ifdef HAVE_WINDOWS_H
+#ifdef _WIN32
 #  if defined(UNICODE) && !defined(_UNICODE)
 #    error "UNICODE is defined but _UNICODE is not defined"
 #  endif
@@ -53,31 +88,16 @@
 #  ifndef NOGDI
 #    define NOGDI
 #  endif
-#  include 
+#  include 
+#  include 
 #  include 
-#  ifdef HAVE_WINSOCK2_H
-#    include 
-#    ifdef HAVE_WS2TCPIP_H
-#      include 
-#    endif
-#  endif
+#  include 
 #  include 
 #  ifdef UNICODE
      typedef wchar_t *(*curl_wcsdup_callback)(const wchar_t *str);
 #  endif
 #endif
 
-/*
- * Define USE_WINSOCK to 2 if we have and use WINSOCK2 API, else
- * undefine USE_WINSOCK.
- */
-
-#undef USE_WINSOCK
-
-#ifdef HAVE_WINSOCK2_H
-#  define USE_WINSOCK 2
-#endif
-
 /*
  * Define _WIN32_WINNT_[OS] symbols because not all Windows build systems have
  * those symbols to compare against, and even those that do may be missing
@@ -96,18 +116,12 @@
 #ifndef _WIN32_WINNT_WS03
 #define _WIN32_WINNT_WS03           0x0502   /* Windows Server 2003 */
 #endif
-#ifndef _WIN32_WINNT_WIN6
-#define _WIN32_WINNT_WIN6           0x0600   /* Windows Vista */
-#endif
 #ifndef _WIN32_WINNT_VISTA
 #define _WIN32_WINNT_VISTA          0x0600   /* Windows Vista */
 #endif
 #ifndef _WIN32_WINNT_WS08
 #define _WIN32_WINNT_WS08           0x0600   /* Windows Server 2008 */
 #endif
-#ifndef _WIN32_WINNT_LONGHORN
-#define _WIN32_WINNT_LONGHORN       0x0600   /* Windows Vista */
-#endif
 #ifndef _WIN32_WINNT_WIN7
 #define _WIN32_WINNT_WIN7           0x0601   /* Windows 7 */
 #endif
@@ -117,9 +131,6 @@
 #ifndef _WIN32_WINNT_WINBLUE
 #define _WIN32_WINNT_WINBLUE        0x0603   /* Windows 8.1 */
 #endif
-#ifndef _WIN32_WINNT_WINTHRESHOLD
-#define _WIN32_WINNT_WINTHRESHOLD   0x0A00   /* Windows 10 */
-#endif
 #ifndef _WIN32_WINNT_WIN10
 #define _WIN32_WINNT_WIN10          0x0A00   /* Windows 10 */
 #endif
diff --git a/vendor/curl/lib/share.c b/vendor/curl/lib/share.c
index c0a8d806f3..8fa5cda00f 100644
--- a/vendor/curl/lib/share.c
+++ b/vendor/curl/lib/share.c
@@ -133,13 +133,13 @@ curl_share_setopt(struct Curl_share *share, CURLSHoption option, ...)
       res = CURLSHE_BAD_OPTION;
     }
     if(!res)
-      share->specifier |= (1<specifier |= (unsigned int)(1<specifier &= ~(1<specifier &= ~(unsigned int)(1<specifier & (1<specifier & (unsigned int)(1<lockfunc) /* only call this if set! */
       share->lockfunc(data, type, accesstype, share->clientdata);
   }
@@ -281,7 +281,7 @@ Curl_share_unlock(struct Curl_easy *data, curl_lock_data type)
   if(!share)
     return CURLSHE_INVALID;
 
-  if(share->specifier & (1<specifier & (unsigned int)(1<unlockfunc) /* only call this if set! */
       share->unlockfunc (data, type, share->clientdata);
   }
diff --git a/vendor/curl/lib/share.h b/vendor/curl/lib/share.h
index 7f55aac853..632d9198f9 100644
--- a/vendor/curl/lib/share.h
+++ b/vendor/curl/lib/share.h
@@ -31,14 +31,6 @@
 #include "urldata.h"
 #include "conncache.h"
 
-/* SalfordC says "A structure member may not be volatile". Hence:
- */
-#ifdef __SALFORDC__
-#define CURL_VOLATILE
-#else
-#define CURL_VOLATILE volatile
-#endif
-
 #define CURL_GOOD_SHARE 0x7e117a1e
 #define GOOD_SHARE_HANDLE(x) ((x) && (x)->magic == CURL_GOOD_SHARE)
 
@@ -46,7 +38,7 @@
 struct Curl_share {
   unsigned int magic; /* CURL_GOOD_SHARE */
   unsigned int specifier;
-  CURL_VOLATILE unsigned int dirty;
+  volatile unsigned int dirty;
 
   curl_lock_function lockfunc;
   curl_unlock_function unlockfunc;
diff --git a/vendor/curl/lib/sigpipe.h b/vendor/curl/lib/sigpipe.h
index 48761ad0fd..9b29403c28 100644
--- a/vendor/curl/lib/sigpipe.h
+++ b/vendor/curl/lib/sigpipe.h
@@ -25,7 +25,7 @@
  ***************************************************************************/
 #include "curl_setup.h"
 
-#if defined(HAVE_SIGNAL_H) && defined(HAVE_SIGACTION) &&        \
+#if defined(HAVE_SIGACTION) &&        \
   (defined(USE_OPENSSL) || defined(USE_MBEDTLS) || defined(USE_WOLFSSL))
 #include 
 
diff --git a/vendor/curl/lib/smb.c b/vendor/curl/lib/smb.c
index afcc99de24..cab1e757f3 100644
--- a/vendor/curl/lib/smb.c
+++ b/vendor/curl/lib/smb.c
@@ -27,7 +27,7 @@
 
 #if !defined(CURL_DISABLE_SMB) && defined(USE_CURL_NTLM_CORE)
 
-#ifdef WIN32
+#ifdef _WIN32
 #define getpid GetCurrentProcessId
 #endif
 
@@ -259,7 +259,7 @@ static CURLcode smb_parse_url_path(struct Curl_easy *data,
  * SMB handler interface
  */
 const struct Curl_handler Curl_handler_smb = {
-  "SMB",                                /* scheme */
+  "smb",                                /* scheme */
   smb_setup_connection,                 /* setup_connection */
   smb_do,                               /* do_it */
   ZERO_NULL,                            /* done */
@@ -272,7 +272,8 @@ const struct Curl_handler Curl_handler_smb = {
   ZERO_NULL,                            /* domore_getsock */
   ZERO_NULL,                            /* perform_getsock */
   smb_disconnect,                       /* disconnect */
-  ZERO_NULL,                            /* readwrite */
+  ZERO_NULL,                            /* write_resp */
+  ZERO_NULL,                            /* write_resp_hd */
   ZERO_NULL,                            /* connection_check */
   ZERO_NULL,                            /* attach connection */
   PORT_SMB,                             /* defport */
@@ -286,7 +287,7 @@ const struct Curl_handler Curl_handler_smb = {
  * SMBS handler interface
  */
 const struct Curl_handler Curl_handler_smbs = {
-  "SMBS",                               /* scheme */
+  "smbs",                               /* scheme */
   smb_setup_connection,                 /* setup_connection */
   smb_do,                               /* do_it */
   ZERO_NULL,                            /* done */
@@ -299,7 +300,8 @@ const struct Curl_handler Curl_handler_smbs = {
   ZERO_NULL,                            /* domore_getsock */
   ZERO_NULL,                            /* perform_getsock */
   smb_disconnect,                       /* disconnect */
-  ZERO_NULL,                            /* readwrite */
+  ZERO_NULL,                            /* write_resp */
+  ZERO_NULL,                            /* write_resp_hd */
   ZERO_NULL,                            /* connection_check */
   ZERO_NULL,                            /* attach connection */
   PORT_SMBS,                            /* defport */
@@ -456,6 +458,9 @@ static CURLcode smb_connect(struct Curl_easy *data, bool *done)
   smbc->recv_buf = malloc(MAX_MESSAGE_SIZE);
   if(!smbc->recv_buf)
     return CURLE_OUT_OF_MEMORY;
+  smbc->send_buf = malloc(MAX_MESSAGE_SIZE);
+  if(!smbc->send_buf)
+    return CURLE_OUT_OF_MEMORY;
 
   /* Multiple requests are allowed with this connection */
   connkeep(conn, "SMB default");
@@ -485,7 +490,6 @@ static CURLcode smb_connect(struct Curl_easy *data, bool *done)
 static CURLcode smb_recv_message(struct Curl_easy *data, void **msg)
 {
   struct connectdata *conn = data->conn;
-  curl_socket_t sockfd = conn->sock[FIRSTSOCKET];
   struct smb_conn *smbc = &conn->proto.smbc;
   char *buf = smbc->recv_buf;
   ssize_t bytes_read;
@@ -494,7 +498,7 @@ static CURLcode smb_recv_message(struct Curl_easy *data, void **msg)
   size_t len = MAX_MESSAGE_SIZE - smbc->got;
   CURLcode result;
 
-  result = Curl_read(data, sockfd, buf + smbc->got, len, &bytes_read);
+  result = Curl_xfer_recv(data, buf + smbc->got, len, &bytes_read);
   if(result)
     return result;
 
@@ -560,16 +564,15 @@ static void smb_format_message(struct Curl_easy *data, struct smb_header *h,
   h->pid = smb_swap16((unsigned short) pid);
 }
 
-static CURLcode smb_send(struct Curl_easy *data, ssize_t len,
+static CURLcode smb_send(struct Curl_easy *data, size_t len,
                          size_t upload_size)
 {
   struct connectdata *conn = data->conn;
   struct smb_conn *smbc = &conn->proto.smbc;
-  ssize_t bytes_written;
+  size_t bytes_written;
   CURLcode result;
 
-  result = Curl_nwrite(data, FIRSTSOCKET, data->state.ulbuf,
-                      len, &bytes_written);
+  result = Curl_xfer_send(data, smbc->send_buf, len, &bytes_written);
   if(result)
     return result;
 
@@ -587,16 +590,15 @@ static CURLcode smb_flush(struct Curl_easy *data)
 {
   struct connectdata *conn = data->conn;
   struct smb_conn *smbc = &conn->proto.smbc;
-  ssize_t bytes_written;
-  ssize_t len = smbc->send_size - smbc->sent;
+  size_t bytes_written;
+  size_t len = smbc->send_size - smbc->sent;
   CURLcode result;
 
   if(!smbc->send_size)
     return CURLE_OK;
 
-  result = Curl_nwrite(data, FIRSTSOCKET,
-                       data->state.ulbuf + smbc->sent,
-                       len, &bytes_written);
+  result = Curl_xfer_send(data, smbc->send_buf + smbc->sent, len,
+                          &bytes_written);
   if(result)
     return result;
 
@@ -611,13 +613,13 @@ static CURLcode smb_flush(struct Curl_easy *data)
 static CURLcode smb_send_message(struct Curl_easy *data, unsigned char cmd,
                                  const void *msg, size_t msg_len)
 {
-  CURLcode result = Curl_get_upload_buffer(data);
-  if(result)
-    return result;
-  smb_format_message(data, (struct smb_header *)data->state.ulbuf,
+  struct connectdata *conn = data->conn;
+  struct smb_conn *smbc = &conn->proto.smbc;
+
+  smb_format_message(data, (struct smb_header *)smbc->send_buf,
                      cmd, msg_len);
-  memcpy(data->state.ulbuf + sizeof(struct smb_header),
-         msg, msg_len);
+  DEBUGASSERT((sizeof(struct smb_header) + msg_len) <= MAX_MESSAGE_SIZE);
+  memcpy(smbc->send_buf + sizeof(struct smb_header), msg, msg_len);
 
   return smb_send(data, sizeof(struct smb_header) + msg_len, 0);
 }
@@ -775,15 +777,14 @@ static CURLcode smb_send_read(struct Curl_easy *data)
 
 static CURLcode smb_send_write(struct Curl_easy *data)
 {
+  struct connectdata *conn = data->conn;
+  struct smb_conn *smbc = &conn->proto.smbc;
   struct smb_write *msg;
   struct smb_request *req = data->req.p.smb;
   curl_off_t offset = data->req.offset;
   curl_off_t upload_size = data->req.size - data->req.bytecount;
-  CURLcode result = Curl_get_upload_buffer(data);
-  if(result)
-    return result;
-  msg = (struct smb_write *)data->state.ulbuf;
 
+  msg = (struct smb_write *)smbc->send_buf;
   if(upload_size >= MAX_PAYLOAD_SIZE - 1) /* There is one byte of padding */
     upload_size = MAX_PAYLOAD_SIZE - 1;
 
@@ -812,10 +813,11 @@ static CURLcode smb_send_and_recv(struct Curl_easy *data, void **msg)
 
   /* Check if there is data in the transfer buffer */
   if(!smbc->send_size && smbc->upload_size) {
-    size_t nread = smbc->upload_size > (size_t)data->set.upload_buffer_size ?
-      (size_t)data->set.upload_buffer_size : smbc->upload_size;
-    data->req.upload_fromhere = data->state.ulbuf;
-    result = Curl_fillreadbuffer(data, nread, &nread);
+    size_t nread = smbc->upload_size > (size_t)MAX_MESSAGE_SIZE ?
+      (size_t)MAX_MESSAGE_SIZE : smbc->upload_size;
+    bool eos;
+
+    result = Curl_client_read(data, smbc->send_buf, nread, &nread, &eos);
     if(result && result != CURLE_AGAIN)
       return result;
     if(!nread)
@@ -1047,9 +1049,7 @@ static CURLcode smb_request_state(struct Curl_easy *data, bool *done)
         break;
       }
     }
-    data->req.bytecount += len;
     data->req.offset += len;
-    Curl_pgrsSetDownloadCounter(data, data->req.bytecount);
     next_state = (len < MAX_PAYLOAD_SIZE) ? SMB_CLOSE : SMB_DOWNLOAD;
     break;
 
@@ -1135,6 +1135,7 @@ static CURLcode smb_disconnect(struct Curl_easy *data,
   Curl_safefree(smbc->share);
   Curl_safefree(smbc->domain);
   Curl_safefree(smbc->recv_buf);
+  Curl_safefree(smbc->send_buf);
   return CURLE_OK;
 }
 
diff --git a/vendor/curl/lib/smb.h b/vendor/curl/lib/smb.h
index 437f4a58a8..9ea2a8cc31 100644
--- a/vendor/curl/lib/smb.h
+++ b/vendor/curl/lib/smb.h
@@ -42,6 +42,7 @@ struct smb_conn {
   unsigned int session_key;
   unsigned short uid;
   char *recv_buf;
+  char *send_buf;
   size_t upload_size;
   size_t send_size;
   size_t sent;
diff --git a/vendor/curl/lib/smtp.c b/vendor/curl/lib/smtp.c
index 81a17e38db..dd231a521e 100644
--- a/vendor/curl/lib/smtp.c
+++ b/vendor/curl/lib/smtp.c
@@ -111,13 +111,14 @@ static CURLcode smtp_continue_auth(struct Curl_easy *data, const char *mech,
                                    const struct bufref *resp);
 static CURLcode smtp_cancel_auth(struct Curl_easy *data, const char *mech);
 static CURLcode smtp_get_message(struct Curl_easy *data, struct bufref *out);
+static CURLcode cr_eob_add(struct Curl_easy *data);
 
 /*
  * SMTP protocol handler.
  */
 
 const struct Curl_handler Curl_handler_smtp = {
-  "SMTP",                           /* scheme */
+  "smtp",                           /* scheme */
   smtp_setup_connection,            /* setup_connection */
   smtp_do,                          /* do_it */
   smtp_done,                        /* done */
@@ -130,7 +131,8 @@ const struct Curl_handler Curl_handler_smtp = {
   ZERO_NULL,                        /* domore_getsock */
   ZERO_NULL,                        /* perform_getsock */
   smtp_disconnect,                  /* disconnect */
-  ZERO_NULL,                        /* readwrite */
+  ZERO_NULL,                        /* write_resp */
+  ZERO_NULL,                        /* write_resp_hd */
   ZERO_NULL,                        /* connection_check */
   ZERO_NULL,                        /* attach connection */
   PORT_SMTP,                        /* defport */
@@ -146,7 +148,7 @@ const struct Curl_handler Curl_handler_smtp = {
  */
 
 const struct Curl_handler Curl_handler_smtps = {
-  "SMTPS",                          /* scheme */
+  "smtps",                          /* scheme */
   smtp_setup_connection,            /* setup_connection */
   smtp_do,                          /* do_it */
   smtp_done,                        /* done */
@@ -159,7 +161,8 @@ const struct Curl_handler Curl_handler_smtps = {
   ZERO_NULL,                        /* domore_getsock */
   ZERO_NULL,                        /* perform_getsock */
   smtp_disconnect,                  /* disconnect */
-  ZERO_NULL,                        /* readwrite */
+  ZERO_NULL,                        /* write_resp */
+  ZERO_NULL,                        /* write_resp_hd */
   ZERO_NULL,                        /* connection_check */
   ZERO_NULL,                        /* attach connection */
   PORT_SMTPS,                       /* defport */
@@ -250,8 +253,8 @@ static bool smtp_endofresp(struct Curl_easy *data, struct connectdata *conn,
  */
 static CURLcode smtp_get_message(struct Curl_easy *data, struct bufref *out)
 {
-  char *message = data->state.buffer;
-  size_t len = strlen(message);
+  char *message = Curl_dyn_ptr(&data->conn->proto.smtpc.pp.recvbuf);
+  size_t len = data->conn->proto.smtpc.pp.nfinal;
 
   if(len > 4) {
     /* Find the start of the message */
@@ -618,7 +621,7 @@ static CURLcode smtp_perform_mail(struct Curl_easy *data)
     result = smtp_parse_address(data->set.str[STRING_MAIL_FROM],
                                 &address, &host);
     if(result)
-      return result;
+      goto out;
 
     /* Establish whether we should report SMTPUTF8 to the server for this
        mailbox as per RFC-6531 sect. 3.1 point 4 and sect. 3.4 */
@@ -642,8 +645,10 @@ static CURLcode smtp_perform_mail(struct Curl_easy *data)
     /* Null reverse-path, RFC-5321, sect. 3.6.3 */
     from = strdup("<>");
 
-  if(!from)
-    return CURLE_OUT_OF_MEMORY;
+  if(!from) {
+    result = CURLE_OUT_OF_MEMORY;
+    goto out;
+  }
 
   /* Calculate the optional AUTH parameter */
   if(data->set.str[STRING_MAIL_AUTH] && conn->proto.smtpc.sasl.authused) {
@@ -655,10 +660,8 @@ static CURLcode smtp_perform_mail(struct Curl_easy *data)
          converting the host name to an IDN A-label if necessary */
       result = smtp_parse_address(data->set.str[STRING_MAIL_AUTH],
                                   &address, &host);
-      if(result) {
-        free(from);
-        return result;
-      }
+      if(result)
+        goto out;
 
       /* Establish whether we should report SMTPUTF8 to the server for this
          mailbox as per RFC-6531 sect. 3.1 point 4 and sect. 3.4 */
@@ -676,7 +679,6 @@ static CURLcode smtp_perform_mail(struct Curl_easy *data)
         /* An invalid mailbox was provided but we'll simply let the server
            worry about it */
         auth = aprintf("<%s>", address);
-
       free(address);
     }
     else
@@ -684,12 +686,12 @@ static CURLcode smtp_perform_mail(struct Curl_easy *data)
       auth = strdup("<>");
 
     if(!auth) {
-      free(from);
-
-      return CURLE_OUT_OF_MEMORY;
+      result = CURLE_OUT_OF_MEMORY;
+      goto out;
     }
   }
 
+#ifndef CURL_DISABLE_MIME
   /* Prepare the mime data if some. */
   if(data->set.mimepost.kind != MIMEKIND_NONE) {
     /* Use the whole structure as data. */
@@ -705,22 +707,18 @@ static CURLcode smtp_perform_mail(struct Curl_easy *data)
         result = Curl_mime_add_header(&data->set.mimepost.curlheaders,
                                       "Mime-Version: 1.0");
 
-    /* Make sure we will read the entire mime structure. */
     if(!result)
-      result = Curl_mime_rewind(&data->set.mimepost);
-
-    if(result) {
-      free(from);
-      free(auth);
-
-      return result;
-    }
-
-    data->state.infilesize = Curl_mime_size(&data->set.mimepost);
-
-    /* Read from mime structure. */
-    data->state.fread_func = (curl_read_callback) Curl_mime_read;
-    data->state.in = (void *) &data->set.mimepost;
+      result = Curl_creader_set_mime(data, &data->set.mimepost);
+    if(result)
+      goto out;
+    data->state.infilesize = Curl_creader_total_length(data);
+  }
+  else
+#endif
+  {
+    result = Curl_creader_set_fread(data, data->state.infilesize);
+    if(result)
+      goto out;
   }
 
   /* Calculate the optional SIZE parameter */
@@ -728,10 +726,8 @@ static CURLcode smtp_perform_mail(struct Curl_easy *data)
     size = aprintf("%" CURL_FORMAT_CURL_OFF_T, data->state.infilesize);
 
     if(!size) {
-      free(from);
-      free(auth);
-
-      return CURLE_OUT_OF_MEMORY;
+      result = CURLE_OUT_OF_MEMORY;
+      goto out;
     }
   }
 
@@ -752,6 +748,11 @@ static CURLcode smtp_perform_mail(struct Curl_easy *data)
     }
   }
 
+  /* Add the client reader doing STMP EOB escaping */
+  result = cr_eob_add(data);
+  if(result)
+    goto out;
+
   /* Send the MAIL command */
   result = Curl_pp_sendf(data, &conn->proto.smtpc.pp,
                          "MAIL FROM:%s%s%s%s%s%s",
@@ -763,6 +764,7 @@ static CURLcode smtp_perform_mail(struct Curl_easy *data)
                          utf8 ? " SMTPUTF8"    /* Internationalised mailbox */
                                : "");          /* included in our envelope  */
 
+out:
   free(from);
   free(auth);
   free(size);
@@ -859,7 +861,7 @@ static CURLcode smtp_state_starttls_resp(struct Curl_easy *data,
   (void)instate; /* no use for this yet */
 
   /* Pipelining in response is forbidden. */
-  if(data->conn->proto.smtpc.pp.cache_size)
+  if(data->conn->proto.smtpc.pp.overflow)
     return CURLE_WEIRD_SERVER_REPLY;
 
   if(smtpcode != 220) {
@@ -883,8 +885,8 @@ static CURLcode smtp_state_ehlo_resp(struct Curl_easy *data,
 {
   CURLcode result = CURLE_OK;
   struct smtp_conn *smtpc = &conn->proto.smtpc;
-  const char *line = data->state.buffer;
-  size_t len = strlen(line);
+  const char *line = Curl_dyn_ptr(&smtpc->pp.recvbuf);
+  size_t len = smtpc->pp.nfinal;
 
   (void)instate; /* no use for this yet */
 
@@ -1033,8 +1035,8 @@ static CURLcode smtp_state_command_resp(struct Curl_easy *data, int smtpcode,
 {
   CURLcode result = CURLE_OK;
   struct SMTP *smtp = data->req.p.smtp;
-  char *line = data->state.buffer;
-  size_t len = strlen(line);
+  char *line = Curl_dyn_ptr(&data->conn->proto.smtpc.pp.recvbuf);
+  size_t len = data->conn->proto.smtpc.pp.nfinal;
 
   (void)instate; /* no use for this yet */
 
@@ -1044,12 +1046,8 @@ static CURLcode smtp_state_command_resp(struct Curl_easy *data, int smtpcode,
     result = CURLE_WEIRD_SERVER_REPLY;
   }
   else {
-    /* Temporarily add the LF character back and send as body to the client */
-    if(!data->req.no_body) {
-      line[len] = '\n';
-      result = Curl_client_write(data, CLIENTWRITE_BODY, line, len + 1);
-      line[len] = '\0';
-    }
+    if(!data->req.no_body)
+      result = Curl_client_write(data, CLIENTWRITE_BODY, line, len);
 
     if(smtpcode != 1) {
       if(smtp->rcpt) {
@@ -1166,7 +1164,7 @@ static CURLcode smtp_state_data_resp(struct Curl_easy *data, int smtpcode,
     Curl_pgrsSetUploadSize(data, data->state.infilesize);
 
     /* SMTP upload */
-    Curl_setup_transfer(data, -1, -1, FALSE, FIRSTSOCKET);
+    Curl_xfer_setup(data, -1, -1, FALSE, FIRSTSOCKET);
 
     /* End of DO phase */
     smtp_state(data, SMTP_STOP);
@@ -1198,7 +1196,6 @@ static CURLcode smtp_statemachine(struct Curl_easy *data,
                                   struct connectdata *conn)
 {
   CURLcode result = CURLE_OK;
-  curl_socket_t sock = conn->sock[FIRSTSOCKET];
   int smtpcode;
   struct smtp_conn *smtpc = &conn->proto.smtpc;
   struct pingpong *pp = &smtpc->pp;
@@ -1214,7 +1211,7 @@ static CURLcode smtp_statemachine(struct Curl_easy *data,
 
   do {
     /* Read the response from the server */
-    result = Curl_pp_readresp(data, sock, pp, &smtpcode, &nread);
+    result = Curl_pp_readresp(data, FIRSTSOCKET, pp, &smtpcode, &nread);
     if(result)
       return result;
 
@@ -1268,7 +1265,6 @@ static CURLcode smtp_statemachine(struct Curl_easy *data,
       break;
 
     case SMTP_QUIT:
-      /* fallthrough, just stop! */
     default:
       /* internal error */
       smtp_state(data, SMTP_STOP);
@@ -1320,7 +1316,7 @@ static CURLcode smtp_init(struct Curl_easy *data)
   CURLcode result = CURLE_OK;
   struct SMTP *smtp;
 
-  smtp = data->req.p.smtp = calloc(sizeof(struct SMTP), 1);
+  smtp = data->req.p.smtp = calloc(1, sizeof(struct SMTP));
   if(!smtp)
     result = CURLE_OUT_OF_MEMORY;
 
@@ -1362,8 +1358,7 @@ static CURLcode smtp_connect(struct Curl_easy *data, bool *done)
   Curl_sasl_init(&smtpc->sasl, data, &saslsmtp);
 
   /* Initialise the pingpong layer */
-  Curl_pp_setup(pp);
-  Curl_pp_init(data, pp);
+  Curl_pp_init(pp);
 
   /* Parse the URL options */
   result = smtp_parse_url_options(conn);
@@ -1398,10 +1393,6 @@ static CURLcode smtp_done(struct Curl_easy *data, CURLcode status,
   CURLcode result = CURLE_OK;
   struct connectdata *conn = data->conn;
   struct SMTP *smtp = data->req.p.smtp;
-  struct pingpong *pp = &conn->proto.smtpc.pp;
-  char *eob;
-  ssize_t len;
-  ssize_t bytes_written;
 
   (void)premature;
 
@@ -1416,47 +1407,7 @@ static CURLcode smtp_done(struct Curl_easy *data, CURLcode status,
     result = status;         /* use the already set error code */
   }
   else if(!data->set.connect_only && data->set.mail_rcpt &&
-          (data->state.upload || data->set.mimepost.kind)) {
-    /* Calculate the EOB taking into account any terminating CRLF from the
-       previous line of the email or the CRLF of the DATA command when there
-       is "no mail data". RFC-5321, sect. 4.1.1.4.
-
-       Note: As some SSL backends, such as OpenSSL, will cause Curl_write() to
-       fail when using a different pointer following a previous write, that
-       returned CURLE_AGAIN, we duplicate the EOB now rather than when the
-       bytes written doesn't equal len. */
-    if(smtp->trailing_crlf || !data->state.infilesize) {
-      eob = strdup(&SMTP_EOB[2]);
-      len = SMTP_EOB_LEN - 2;
-    }
-    else {
-      eob = strdup(SMTP_EOB);
-      len = SMTP_EOB_LEN;
-    }
-
-    if(!eob)
-      return CURLE_OUT_OF_MEMORY;
-
-    /* Send the end of block data */
-    result = Curl_write(data, conn->writesockfd, eob, len, &bytes_written);
-    if(result) {
-      free(eob);
-      return result;
-    }
-
-    if(bytes_written != len) {
-      /* The whole chunk was not sent so keep it around and adjust the
-         pingpong structure accordingly */
-      pp->sendthis = eob;
-      pp->sendsize = len;
-      pp->sendleft = len - bytes_written;
-    }
-    else {
-      /* Successfully sent so adjust the response timeout relative to now */
-      pp->response = Curl_now();
-
-      free(eob);
-    }
+          (data->state.upload || IS_MIME_POST(data))) {
 
     smtp_state(data, SMTP_POSTDATA);
 
@@ -1508,7 +1459,7 @@ static CURLcode smtp_perform(struct Curl_easy *data, bool *connected,
   smtp->eob = 2;
 
   /* Start the first command in the DO phase */
-  if((data->state.upload || data->set.mimepost.kind) && data->set.mail_rcpt)
+  if((data->state.upload || IS_MIME_POST(data)) && data->set.mail_rcpt)
     /* MAIL transfer */
     result = smtp_perform_mail(data);
   else
@@ -1541,6 +1492,8 @@ static CURLcode smtp_perform(struct Curl_easy *data, bool *connected,
 static CURLcode smtp_do(struct Curl_easy *data, bool *done)
 {
   CURLcode result = CURLE_OK;
+  DEBUGASSERT(data);
+  DEBUGASSERT(data->conn);
   *done = FALSE; /* default to false */
 
   /* Parse the custom request */
@@ -1597,7 +1550,7 @@ static CURLcode smtp_dophase_done(struct Curl_easy *data, bool connected)
 
   if(smtp->transfer != PPTRANSFER_BODY)
     /* no data to transfer */
-    Curl_setup_transfer(data, -1, -1, FALSE, -1);
+    Curl_xfer_setup(data, -1, -1, FALSE, -1);
 
   return CURLE_OK;
 }
@@ -1822,108 +1775,173 @@ static CURLcode smtp_parse_address(const char *fqma, char **address,
   return result;
 }
 
-CURLcode Curl_smtp_escape_eob(struct Curl_easy *data,
-                              const ssize_t nread,
-                              const ssize_t offset)
+struct cr_eob_ctx {
+  struct Curl_creader super;
+  struct bufq buf;
+  size_t n_eob; /* how many EOB bytes we matched so far */
+  size_t eob;       /* Number of bytes of the EOB (End Of Body) that
+                       have been received so far */
+  BIT(read_eos);  /* we read an EOS from the next reader */
+  BIT(eos);       /* we have returned an EOS */
+};
+
+static CURLcode cr_eob_init(struct Curl_easy *data,
+                            struct Curl_creader *reader)
 {
-  /* When sending a SMTP payload we must detect CRLF. sequences making sure
-     they are sent as CRLF.. instead, as a . on the beginning of a line will
-     be deleted by the server when not part of an EOB terminator and a
-     genuine CRLF.CRLF which isn't escaped will wrongly be detected as end of
-     data by the server
-  */
-  ssize_t i;
-  ssize_t si;
-  struct SMTP *smtp = data->req.p.smtp;
-  char *scratch = data->state.scratch;
-  char *newscratch = NULL;
-  char *oldscratch = NULL;
-  size_t eob_sent;
+  struct cr_eob_ctx *ctx = reader->ctx;
+  (void)data;
+  /* The first char we read is the first on a line, as if we had
+   * read CRLF just before */
+  ctx->n_eob = 2;
+  Curl_bufq_init2(&ctx->buf, (16 * 1024), 1, BUFQ_OPT_SOFT_LIMIT);
+  return CURLE_OK;
+}
 
-  /* Do we need to allocate a scratch buffer? */
-  if(!scratch || data->set.crlf) {
-    oldscratch = scratch;
+static void cr_eob_close(struct Curl_easy *data, struct Curl_creader *reader)
+{
+  struct cr_eob_ctx *ctx = reader->ctx;
+  (void)data;
+  Curl_bufq_free(&ctx->buf);
+}
 
-    scratch = newscratch = malloc(2 * data->set.upload_buffer_size);
-    if(!newscratch) {
-      failf(data, "Failed to alloc scratch buffer");
+/* this is the 5-bytes End-Of-Body marker for SMTP */
+#define SMTP_EOB "\r\n.\r\n"
+#define SMTP_EOB_FIND_LEN 3
 
-      return CURLE_OUT_OF_MEMORY;
-    }
-  }
-  DEBUGASSERT((size_t)data->set.upload_buffer_size >= (size_t)nread);
-
-  /* Have we already sent part of the EOB? */
-  eob_sent = smtp->eob;
-
-  /* This loop can be improved by some kind of Boyer-Moore style of
-     approach but that is saved for later... */
-  if(offset)
-    memcpy(scratch, data->req.upload_fromhere, offset);
-  for(i = offset, si = offset; i < nread; i++) {
-    if(SMTP_EOB[smtp->eob] == data->req.upload_fromhere[i]) {
-      smtp->eob++;
-
-      /* Is the EOB potentially the terminating CRLF? */
-      if(2 == smtp->eob || SMTP_EOB_LEN == smtp->eob)
-        smtp->trailing_crlf = TRUE;
-      else
-        smtp->trailing_crlf = FALSE;
-    }
-    else if(smtp->eob) {
-      /* A previous substring matched so output that first */
-      memcpy(&scratch[si], &SMTP_EOB[eob_sent], smtp->eob - eob_sent);
-      si += smtp->eob - eob_sent;
-
-      /* Then compare the first byte */
-      if(SMTP_EOB[0] == data->req.upload_fromhere[i])
-        smtp->eob = 1;
-      else
-        smtp->eob = 0;
+/* client reader doing SMTP End-Of-Body escaping. */
+static CURLcode cr_eob_read(struct Curl_easy *data,
+                            struct Curl_creader *reader,
+                            char *buf, size_t blen,
+                            size_t *pnread, bool *peos)
+{
+  struct cr_eob_ctx *ctx = reader->ctx;
+  CURLcode result = CURLE_OK;
+  size_t nread, i, start, n;
+  bool eos;
+
+  if(!ctx->read_eos && Curl_bufq_is_empty(&ctx->buf)) {
+    /* Get more and convert it when needed */
+    result = Curl_creader_read(data, reader->next, buf, blen, &nread, &eos);
+    if(result)
+      return result;
 
-      eob_sent = 0;
+    ctx->read_eos = eos;
+    if(nread) {
+      if(!ctx->n_eob && !memchr(buf, SMTP_EOB[0], nread)) {
+        /* not in the middle of a match, no EOB start found, just pass */
+        *pnread = nread;
+        *peos = FALSE;
+        return CURLE_OK;
+      }
+      /* scan for EOB (continuation) and convert */
+      for(i = start = 0; i < nread; ++i) {
+        if(ctx->n_eob >= SMTP_EOB_FIND_LEN) {
+          /* matched the EOB prefix and seeing additional char, add '.' */
+          result = Curl_bufq_cwrite(&ctx->buf, buf + start, i - start, &n);
+          if(result)
+            return result;
+          result = Curl_bufq_cwrite(&ctx->buf, ".", 1, &n);
+          if(result)
+            return result;
+          ctx->n_eob = 0;
+          start = i;
+          if(data->state.infilesize > 0)
+            data->state.infilesize++;
+        }
 
-      /* Reset the trailing CRLF flag as there was more data */
-      smtp->trailing_crlf = FALSE;
+        if(buf[i] != SMTP_EOB[ctx->n_eob])
+          ctx->n_eob = 0;
+
+        if(buf[i] == SMTP_EOB[ctx->n_eob]) {
+          /* matching another char of the EOB */
+          ++ctx->n_eob;
+        }
+      }
+
+      /* add any remainder to buf */
+      if(start < nread) {
+        result = Curl_bufq_cwrite(&ctx->buf, buf + start, nread - start, &n);
+        if(result)
+          return result;
+      }
     }
 
-    /* Do we have a match for CRLF. as per RFC-5321, sect. 4.5.2 */
-    if(SMTP_EOB_FIND_LEN == smtp->eob) {
-      /* Copy the replacement data to the target buffer */
-      memcpy(&scratch[si], &SMTP_EOB_REPL[eob_sent],
-             SMTP_EOB_REPL_LEN - eob_sent);
-      si += SMTP_EOB_REPL_LEN - eob_sent;
-      smtp->eob = 0;
-      eob_sent = 0;
+    if(ctx->read_eos) {
+      /* if we last matched a CRLF or if the data was empty, add ".\r\n"
+       * to end the body. If we sent something and it did not end with "\r\n",
+       * add "\r\n.\r\n" to end the body */
+      const char *eob = SMTP_EOB;
+      switch(ctx->n_eob) {
+        case 2:
+          /* seen a CRLF at the end, just add the remainder */
+          eob = &SMTP_EOB[2];
+          break;
+        case 3:
+          /* ended with '\r\n.', we should escpe the last '.' */
+          eob = "." SMTP_EOB;
+          break;
+        default:
+          break;
+      }
+      result = Curl_bufq_cwrite(&ctx->buf, eob, strlen(eob), &n);
+      if(result)
+        return result;
     }
-    else if(!smtp->eob)
-      scratch[si++] = data->req.upload_fromhere[i];
   }
 
-  if(smtp->eob - eob_sent) {
-    /* A substring matched before processing ended so output that now */
-    memcpy(&scratch[si], &SMTP_EOB[eob_sent], smtp->eob - eob_sent);
-    si += smtp->eob - eob_sent;
+  *peos = FALSE;
+  if(!Curl_bufq_is_empty(&ctx->buf)) {
+    result = Curl_bufq_cread(&ctx->buf, buf, blen, pnread);
   }
+  else
+    *pnread = 0;
+
+  if(ctx->read_eos && Curl_bufq_is_empty(&ctx->buf)) {
+    /* no more data, read all, done. */
+    ctx->eos = TRUE;
+  }
+  *peos = ctx->eos;
+  DEBUGF(infof(data, "cr_eob_read(%zu) -> %d, %zd, %d",
+         blen, result, *pnread, *peos));
+  return result;
+}
 
-  /* Only use the new buffer if we replaced something */
-  if(si != nread) {
-    /* Upload from the new (replaced) buffer instead */
-    data->req.upload_fromhere = scratch;
+static curl_off_t cr_eob_total_length(struct Curl_easy *data,
+                                      struct Curl_creader *reader)
+{
+  /* this reader changes length depending on input */
+  (void)data;
+  (void)reader;
+  return -1;
+}
 
-    /* Save the buffer so it can be freed later */
-    data->state.scratch = scratch;
+static const struct Curl_crtype cr_eob = {
+  "cr-smtp-eob",
+  cr_eob_init,
+  cr_eob_read,
+  cr_eob_close,
+  Curl_creader_def_needs_rewind,
+  cr_eob_total_length,
+  Curl_creader_def_resume_from,
+  Curl_creader_def_rewind,
+  Curl_creader_def_unpause,
+  Curl_creader_def_done,
+  sizeof(struct cr_eob_ctx)
+};
 
-    /* Free the old scratch buffer */
-    free(oldscratch);
+static CURLcode cr_eob_add(struct Curl_easy *data)
+{
+  struct Curl_creader *reader = NULL;
+  CURLcode result;
 
-    /* Set the new amount too */
-    data->req.upload_present = si;
-  }
-  else
-    free(newscratch);
+  result = Curl_creader_create(&reader, data, &cr_eob,
+                               CURL_CR_CONTENT_ENCODE);
+  if(!result)
+    result = Curl_creader_add(data, reader);
 
-  return CURLE_OK;
+  if(result && reader)
+    Curl_creader_free(data, reader);
+  return result;
 }
 
 #endif /* CURL_DISABLE_SMTP */
diff --git a/vendor/curl/lib/smtp.h b/vendor/curl/lib/smtp.h
index 7a04c21549..7c2af68073 100644
--- a/vendor/curl/lib/smtp.h
+++ b/vendor/curl/lib/smtp.h
@@ -84,17 +84,4 @@ struct smtp_conn {
 extern const struct Curl_handler Curl_handler_smtp;
 extern const struct Curl_handler Curl_handler_smtps;
 
-/* this is the 5-bytes End-Of-Body marker for SMTP */
-#define SMTP_EOB "\x0d\x0a\x2e\x0d\x0a"
-#define SMTP_EOB_LEN 5
-#define SMTP_EOB_FIND_LEN 3
-
-/* if found in data, replace it with this string instead */
-#define SMTP_EOB_REPL "\x0d\x0a\x2e\x2e"
-#define SMTP_EOB_REPL_LEN 4
-
-CURLcode Curl_smtp_escape_eob(struct Curl_easy *data,
-                              const ssize_t nread,
-                              const ssize_t offset);
-
 #endif /* HEADER_CURL_SMTP_H */
diff --git a/vendor/curl/lib/sockaddr.h b/vendor/curl/lib/sockaddr.h
index 5a6bb207dc..2e2d375e06 100644
--- a/vendor/curl/lib/sockaddr.h
+++ b/vendor/curl/lib/sockaddr.h
@@ -30,7 +30,7 @@ struct Curl_sockaddr_storage {
   union {
     struct sockaddr sa;
     struct sockaddr_in sa_in;
-#ifdef ENABLE_IPV6
+#ifdef USE_IPV6
     struct sockaddr_in6 sa_in6;
 #endif
 #ifdef HAVE_STRUCT_SOCKADDR_STORAGE
diff --git a/vendor/curl/lib/socketpair.c b/vendor/curl/lib/socketpair.c
index 963e1406f6..d7e3afd889 100644
--- a/vendor/curl/lib/socketpair.c
+++ b/vendor/curl/lib/socketpair.c
@@ -27,15 +27,33 @@
 #include "urldata.h"
 #include "rand.h"
 
+#if defined(HAVE_PIPE) && defined(HAVE_FCNTL)
+#include 
+
+int Curl_pipe(curl_socket_t socks[2])
+{
+  if(pipe(socks))
+    return -1;
+
+  if(fcntl(socks[0], F_SETFD, FD_CLOEXEC) ||
+     fcntl(socks[1], F_SETFD, FD_CLOEXEC) ) {
+    close(socks[0]);
+    close(socks[1]);
+    socks[0] = socks[1] = CURL_SOCKET_BAD;
+    return -1;
+  }
+
+  return 0;
+}
+#endif
+
+
 #if !defined(HAVE_SOCKETPAIR) && !defined(CURL_DISABLE_SOCKETPAIR)
-#ifdef WIN32
+#ifdef _WIN32
 /*
  * This is a socketpair() implementation for Windows.
  */
 #include 
-#include 
-#include 
-#include 
 #include 
 #else
 #ifdef HAVE_NETDB_H
@@ -50,7 +68,7 @@
 #ifndef INADDR_LOOPBACK
 #define INADDR_LOOPBACK 0x7f000001
 #endif /* !INADDR_LOOPBACK */
-#endif /* !WIN32 */
+#endif /* !_WIN32 */
 
 #include "nonblock.h" /* for curlx_nonblock */
 #include "timeval.h"  /* needed before select.h */
@@ -87,7 +105,7 @@ int Curl_socketpair(int domain, int type, int protocol,
 
   socks[0] = socks[1] = CURL_SOCKET_BAD;
 
-#if defined(WIN32) || defined(__CYGWIN__)
+#if defined(_WIN32) || defined(__CYGWIN__)
   /* don't set SO_REUSEADDR on Windows */
   (void)reuse;
 #ifdef SO_EXCLUSIVEADDRUSE
diff --git a/vendor/curl/lib/socketpair.h b/vendor/curl/lib/socketpair.h
index 306ab5dc4c..ddd44374a7 100644
--- a/vendor/curl/lib/socketpair.h
+++ b/vendor/curl/lib/socketpair.h
@@ -25,6 +25,47 @@
  ***************************************************************************/
 
 #include "curl_setup.h"
+
+#ifdef HAVE_PIPE
+
+#define wakeup_write  write
+#define wakeup_read   read
+#define wakeup_close  close
+#define wakeup_create(p) Curl_pipe(p)
+
+#ifdef HAVE_FCNTL
+#include 
+int Curl_pipe(curl_socket_t socks[2]);
+#else
+#define Curl_pipe(p) pipe(p)
+#endif
+
+#else /* HAVE_PIPE */
+
+#define wakeup_write     swrite
+#define wakeup_read      sread
+#define wakeup_close     sclose
+
+#if defined(USE_UNIX_SOCKETS) && defined(HAVE_SOCKETPAIR)
+#define SOCKETPAIR_FAMILY AF_UNIX
+#elif !defined(HAVE_SOCKETPAIR)
+#define SOCKETPAIR_FAMILY 0 /* not used */
+#else
+#error "unsupported unix domain and socketpair build combo"
+#endif
+
+#ifdef SOCK_CLOEXEC
+#define SOCKETPAIR_TYPE (SOCK_STREAM | SOCK_CLOEXEC)
+#else
+#define SOCKETPAIR_TYPE SOCK_STREAM
+#endif
+
+#define wakeup_create(p)\
+Curl_socketpair(SOCKETPAIR_FAMILY, SOCKETPAIR_TYPE, 0, p)
+
+#endif /* HAVE_PIPE */
+
+
 #ifndef HAVE_SOCKETPAIR
 #include 
 
diff --git a/vendor/curl/lib/socks.c b/vendor/curl/lib/socks.c
index c492d663c4..4ade4eb020 100644
--- a/vendor/curl/lib/socks.c
+++ b/vendor/curl/lib/socks.c
@@ -71,9 +71,18 @@ enum connect_t {
   CONNECT_DONE /* 17 connected fine to the remote or the SOCKS proxy */
 };
 
+#define CURL_SOCKS_BUF_SIZE 600
+
+/* make sure we configure it not too low */
+#if CURL_SOCKS_BUF_SIZE < 600
+#error CURL_SOCKS_BUF_SIZE must be at least 600
+#endif
+
+
 struct socks_state {
   enum connect_t state;
   ssize_t outstanding;  /* send this many bytes more */
+  unsigned char buffer[CURL_SOCKS_BUF_SIZE];
   unsigned char *outp; /* send from this pointer */
 
   const char *hostname;
@@ -249,7 +258,7 @@ static CURLproxycode socks_state_recv(struct Curl_cfilter *cf,
       failf(data, "connection to proxy closed");
       return CURLPX_CLOSED;
     }
-    failf(data, "SOCKS4: Failed receiving %s: %s", description,
+    failf(data, "SOCKS: Failed receiving %s: %s", description,
           curl_easy_strerror(result));
     return failcode;
   }
@@ -278,14 +287,11 @@ static CURLproxycode do_SOCKS4(struct Curl_cfilter *cf,
   struct connectdata *conn = cf->conn;
   const bool protocol4a =
     (conn->socks_proxy.proxytype == CURLPROXY_SOCKS4A) ? TRUE : FALSE;
-  unsigned char *socksreq = (unsigned char *)data->state.buffer;
+  unsigned char *socksreq = sx->buffer;
   CURLcode result;
   CURLproxycode presult;
   struct Curl_dns_entry *dns = NULL;
 
-  /* make sure that the buffer is at least 600 bytes */
-  DEBUGASSERT(READBUFFER_MIN >= 600);
-
   switch(sx->state) {
   case CONNECT_SOCKS_INIT:
     /* SOCKS4 can only do IPv4, insist! */
@@ -335,7 +341,7 @@ static CURLproxycode do_SOCKS4(struct Curl_cfilter *cf,
 
   case CONNECT_RESOLVING:
     /* check if we have the name resolved by now */
-    dns = Curl_fetch_addr(data, sx->hostname, (int)conn->port);
+    dns = Curl_fetch_addr(data, sx->hostname, conn->primary.remote_port);
 
     if(dns) {
 #ifdef CURLRES_ASYNCH
@@ -353,9 +359,10 @@ static CURLproxycode do_SOCKS4(struct Curl_cfilter *cf,
         return CURLPX_OK;
       }
     }
-    /* FALLTHROUGH */
+    FALLTHROUGH();
+  case CONNECT_RESOLVED:
 CONNECT_RESOLVED:
-  case CONNECT_RESOLVED: {
+  {
     struct Curl_addrinfo *hp = NULL;
     /*
      * We cannot use 'hostent' as a struct that Curl_resolv() returns.  It
@@ -393,17 +400,20 @@ static CURLproxycode do_SOCKS4(struct Curl_cfilter *cf,
     if(!hp)
       return CURLPX_RESOLVE_HOST;
   }
-    /* FALLTHROUGH */
-CONNECT_REQ_INIT:
+    FALLTHROUGH();
   case CONNECT_REQ_INIT:
+CONNECT_REQ_INIT:
     /*
      * This is currently not supporting "Identification Protocol (RFC1413)".
      */
     socksreq[8] = 0; /* ensure empty userid is NUL-terminated */
     if(sx->proxy_user) {
       size_t plen = strlen(sx->proxy_user);
-      if(plen >= (size_t)data->set.buffer_size - 8) {
-        failf(data, "Too long SOCKS proxy user name, can't use");
+      if(plen > 255) {
+        /* there is no real size limit to this field in the protocol, but
+           SOCKS5 limits the proxy user field to 255 bytes and it seems likely
+           that a longer field is either a mistake or malicious input */
+        failf(data, "Too long SOCKS proxy user name");
         return CURLPX_LONG_USER;
       }
       /* copy the proxy name WITH trailing zero */
@@ -426,7 +436,8 @@ static CURLproxycode do_SOCKS4(struct Curl_cfilter *cf,
         socksreq[7] = 1;
         /* append hostname */
         hostnamelen = strlen(sx->hostname) + 1; /* length including NUL */
-        if(hostnamelen <= 255)
+        if((hostnamelen <= 255) &&
+           (packetsize + hostnamelen < sizeof(sx->buffer)))
           strcpy((char *)socksreq + packetsize, sx->hostname);
         else {
           failf(data, "SOCKS4: too long host name");
@@ -435,10 +446,11 @@ static CURLproxycode do_SOCKS4(struct Curl_cfilter *cf,
         packetsize += hostnamelen;
       }
       sx->outp = socksreq;
+      DEBUGASSERT(packetsize <= sizeof(sx->buffer));
       sx->outstanding = packetsize;
       sxstate(sx, data, CONNECT_REQ_SENDING);
     }
-    /* FALLTHROUGH */
+    FALLTHROUGH();
   case CONNECT_REQ_SENDING:
     /* Send request */
     presult = socks_state_send(cf, sx, data, CURLPX_SEND_CONNECT,
@@ -454,7 +466,7 @@ static CURLproxycode do_SOCKS4(struct Curl_cfilter *cf,
     sx->outp = socksreq;
     sxstate(sx, data, CONNECT_SOCKS_READ);
 
-    /* FALLTHROUGH */
+    FALLTHROUGH();
   case CONNECT_SOCKS_READ:
     /* Receive response */
     presult = socks_state_recv(cf, sx, data, CURLPX_RECV_CONNECT,
@@ -566,14 +578,14 @@ static CURLproxycode do_SOCKS5(struct Curl_cfilter *cf,
     o  X'00' succeeded
   */
   struct connectdata *conn = cf->conn;
-  unsigned char *socksreq = (unsigned char *)data->state.buffer;
-  int idx;
+  unsigned char *socksreq = sx->buffer;
+  size_t idx;
   CURLcode result;
   CURLproxycode presult;
   bool socks5_resolve_local =
     (conn->socks_proxy.proxytype == CURLPROXY_SOCKS5) ? TRUE : FALSE;
   const size_t hostname_len = strlen(sx->hostname);
-  ssize_t len = 0;
+  size_t len = 0;
   const unsigned char auth = data->set.socks5auth;
   bool allow_gssapi = FALSE;
   struct Curl_dns_entry *dns = NULL;
@@ -587,9 +599,9 @@ static CURLproxycode do_SOCKS5(struct Curl_cfilter *cf,
 
     /* RFC1928 chapter 5 specifies max 255 chars for domain name in packet */
     if(!socks5_resolve_local && hostname_len > 255) {
-      infof(data, "SOCKS5: server resolving disabled for hostnames of "
-            "length > 255 [actual len=%zu]", hostname_len);
-      socks5_resolve_local = TRUE;
+      failf(data, "SOCKS5: the destination hostname is too long to be "
+            "resolved remotely by the proxy.");
+      return CURLPX_LONG_HOSTNAME;
     }
 
     if(auth & ~(CURLAUTH_BASIC | CURLAUTH_GSSAPI))
@@ -616,6 +628,7 @@ static CURLproxycode do_SOCKS5(struct Curl_cfilter *cf,
     socksreq[1] = (unsigned char) (idx - 2);
 
     sx->outp = socksreq;
+    DEBUGASSERT(idx <= sizeof(sx->buffer));
     sx->outstanding = idx;
     presult = socks_state_send(cf, sx, data, CURLPX_SEND_CONNECT,
                                "initial SOCKS5 request");
@@ -636,12 +649,12 @@ static CURLproxycode do_SOCKS5(struct Curl_cfilter *cf,
       /* remain in sending state */
       return CURLPX_OK;
     }
-    /* FALLTHROUGH */
-CONNECT_SOCKS_READ_INIT:
+    FALLTHROUGH();
   case CONNECT_SOCKS_READ_INIT:
+CONNECT_SOCKS_READ_INIT:
     sx->outstanding = 2; /* expect two bytes */
     sx->outp = socksreq; /* store it here */
-    /* FALLTHROUGH */
+    FALLTHROUGH();
   case CONNECT_SOCKS_READ:
     presult = socks_state_recv(cf, sx, data, CURLPX_RECV_CONNECT,
                                "initial SOCKS5 response");
@@ -742,10 +755,11 @@ static CURLproxycode do_SOCKS5(struct Curl_cfilter *cf,
     }
     len += proxy_password_len;
     sxstate(sx, data, CONNECT_AUTH_SEND);
+    DEBUGASSERT(len <= sizeof(sx->buffer));
     sx->outstanding = len;
     sx->outp = socksreq;
   }
-    /* FALLTHROUGH */
+    FALLTHROUGH();
   case CONNECT_AUTH_SEND:
     presult = socks_state_send(cf, sx, data, CURLPX_SEND_AUTH,
                                "SOCKS5 sub-negotiation request");
@@ -758,7 +772,7 @@ static CURLproxycode do_SOCKS5(struct Curl_cfilter *cf,
     sx->outp = socksreq;
     sx->outstanding = 2;
     sxstate(sx, data, CONNECT_AUTH_READ);
-    /* FALLTHROUGH */
+    FALLTHROUGH();
   case CONNECT_AUTH_READ:
     presult = socks_state_recv(cf, sx, data, CURLPX_RECV_AUTH,
                                "SOCKS5 sub-negotiation response");
@@ -777,9 +791,9 @@ static CURLproxycode do_SOCKS5(struct Curl_cfilter *cf,
 
     /* Everything is good so far, user was authenticated! */
     sxstate(sx, data, CONNECT_REQ_INIT);
-    /* FALLTHROUGH */
-CONNECT_REQ_INIT:
+    FALLTHROUGH();
   case CONNECT_REQ_INIT:
+CONNECT_REQ_INIT:
     if(socks5_resolve_local) {
       enum resolve_t rc = Curl_resolv(data, sx->hostname, sx->remote_port,
                                       TRUE, &dns);
@@ -816,13 +830,23 @@ static CURLproxycode do_SOCKS5(struct Curl_cfilter *cf,
         return CURLPX_OK;
       }
     }
-    /* FALLTHROUGH */
+    FALLTHROUGH();
+  case CONNECT_RESOLVED:
 CONNECT_RESOLVED:
-  case CONNECT_RESOLVED: {
-    char dest[MAX_IPADR_LEN] = "unknown";  /* printable address */
+  {
+    char dest[MAX_IPADR_LEN];  /* printable address */
     struct Curl_addrinfo *hp = NULL;
     if(dns)
       hp = dns->addr;
+#ifdef USE_IPV6
+    if(data->set.ipver != CURL_IPRESOLVE_WHATEVER) {
+      int wanted_family = data->set.ipver == CURL_IPRESOLVE_V4 ?
+        AF_INET : AF_INET6;
+      /* scan for the first proper address */
+      while(hp && (hp->ai_family != wanted_family))
+        hp = hp->ai_next;
+    }
+#endif
     if(!hp) {
       failf(data, "Failed to resolve \"%s\" for SOCKS5 connect.",
             sx->hostname);
@@ -848,7 +872,7 @@ static CURLproxycode do_SOCKS5(struct Curl_cfilter *cf,
       infof(data, "SOCKS5 connect to %s:%d (locally resolved)", dest,
             sx->remote_port);
     }
-#ifdef ENABLE_IPV6
+#ifdef USE_IPV6
     else if(hp->ai_family == AF_INET6) {
       int i;
       struct sockaddr_in6 *saddr_in6;
@@ -885,7 +909,7 @@ static CURLproxycode do_SOCKS5(struct Curl_cfilter *cf,
          IPv6 == 4,
          IPv4 == 1 */
       unsigned char ip4[4];
-#ifdef ENABLE_IPV6
+#ifdef USE_IPV6
       if(conn->bits.ipv6_ip) {
         char ip6[16];
         if(1 != Curl_inet_pton(AF_INET6, sx->hostname, ip6))
@@ -903,17 +927,17 @@ static CURLproxycode do_SOCKS5(struct Curl_cfilter *cf,
       }
       else {
         socksreq[len++] = 3;
-        socksreq[len++] = (char) hostname_len; /* one byte address length */
+        socksreq[len++] = (unsigned char) hostname_len; /* one byte length */
         memcpy(&socksreq[len], sx->hostname, hostname_len); /* w/o NULL */
         len += hostname_len;
       }
       infof(data, "SOCKS5 connect to %s:%d (remotely resolved)",
             sx->hostname, sx->remote_port);
     }
-    /* FALLTHROUGH */
+    FALLTHROUGH();
 
-CONNECT_REQ_SEND:
   case CONNECT_REQ_SEND:
+CONNECT_REQ_SEND:
     /* PORT MSB */
     socksreq[len++] = (unsigned char)((sx->remote_port >> 8) & 0xff);
     /* PORT LSB */
@@ -926,9 +950,10 @@ static CURLproxycode do_SOCKS5(struct Curl_cfilter *cf,
     }
 #endif
     sx->outp = socksreq;
+    DEBUGASSERT(len <= sizeof(sx->buffer));
     sx->outstanding = len;
     sxstate(sx, data, CONNECT_REQ_SENDING);
-    /* FALLTHROUGH */
+    FALLTHROUGH();
   case CONNECT_REQ_SENDING:
     presult = socks_state_send(cf, sx, data, CURLPX_SEND_REQUEST,
                                "SOCKS5 connect request");
@@ -947,7 +972,7 @@ static CURLproxycode do_SOCKS5(struct Curl_cfilter *cf,
     sx->outstanding = 10; /* minimum packet size is 10 */
     sx->outp = socksreq;
     sxstate(sx, data, CONNECT_REQ_READ);
-    /* FALLTHROUGH */
+    FALLTHROUGH();
   case CONNECT_REQ_READ:
     presult = socks_state_recv(cf, sx, data, CURLPX_RECV_REQACK,
                                "SOCKS5 connect request ack");
@@ -1025,6 +1050,7 @@ static CURLproxycode do_SOCKS5(struct Curl_cfilter *cf,
       /* decrypt_gssapi_blockread already read the whole packet */
 #endif
       if(len > 10) {
+        DEBUGASSERT(len <= sizeof(sx->buffer));
         sx->outstanding = len - 10; /* get the rest */
         sx->outp = &socksreq[10];
         sxstate(sx, data, CONNECT_REQ_READ_MORE);
@@ -1036,7 +1062,7 @@ static CURLproxycode do_SOCKS5(struct Curl_cfilter *cf,
 #if defined(HAVE_GSSAPI) || defined(USE_WINDOWS_SSPI)
     }
 #endif
-    /* FALLTHROUGH */
+    FALLTHROUGH();
   case CONNECT_REQ_READ_MORE:
     presult = socks_state_recv(cf, sx, data, CURLPX_RECV_ADDRESS,
                                "SOCKS5 connect request address");
@@ -1119,7 +1145,7 @@ static CURLcode socks_proxy_cf_connect(struct Curl_cfilter *cf,
     return result;
 
   if(!sx) {
-    sx = calloc(sizeof(*sx), 1);
+    sx = calloc(1, sizeof(*sx));
     if(!sx)
       return CURLE_OUT_OF_MEMORY;
     cf->ctx = sx;
@@ -1149,7 +1175,7 @@ static CURLcode socks_proxy_cf_connect(struct Curl_cfilter *cf,
   result = connect_SOCKS(cf, sx, data);
   if(!result && sx->state == CONNECT_DONE) {
     cf->connected = TRUE;
-    Curl_verboseconnect(data, conn);
+    Curl_verboseconnect(data, conn, cf->sockindex);
     socks_proxy_cf_free(cf);
   }
 
@@ -1157,32 +1183,29 @@ static CURLcode socks_proxy_cf_connect(struct Curl_cfilter *cf,
   return result;
 }
 
-static int socks_cf_get_select_socks(struct Curl_cfilter *cf,
+static void socks_cf_adjust_pollset(struct Curl_cfilter *cf,
                                      struct Curl_easy *data,
-                                     curl_socket_t *socks)
+                                     struct easy_pollset *ps)
 {
   struct socks_state *sx = cf->ctx;
-  int fds;
 
-  fds = cf->next->cft->get_select_socks(cf->next, data, socks);
-  if(!fds && cf->next->connected && !cf->connected && sx) {
+  if(!cf->connected && sx) {
     /* If we are not connected, the filter below is and has nothing
      * to wait on, we determine what to wait for. */
-    socks[0] = Curl_conn_cf_get_socket(cf, data);
+    curl_socket_t sock = Curl_conn_cf_get_socket(cf, data);
     switch(sx->state) {
     case CONNECT_RESOLVING:
     case CONNECT_SOCKS_READ:
     case CONNECT_AUTH_READ:
     case CONNECT_REQ_READ:
     case CONNECT_REQ_READ_MORE:
-      fds = GETSOCK_READSOCK(0);
+      Curl_pollset_set_in_only(data, ps, sock);
       break;
     default:
-      fds = GETSOCK_WRITESOCK(0);
+      Curl_pollset_set_out_only(data, ps, sock);
       break;
     }
   }
-  return fds;
 }
 
 static void socks_proxy_cf_close(struct Curl_cfilter *cf,
@@ -1221,13 +1244,13 @@ static void socks_cf_get_host(struct Curl_cfilter *cf,
 
 struct Curl_cftype Curl_cft_socks_proxy = {
   "SOCKS-PROXYY",
-  CF_TYPE_IP_CONNECT,
+  CF_TYPE_IP_CONNECT|CF_TYPE_PROXY,
   0,
   socks_proxy_cf_destroy,
   socks_proxy_cf_connect,
   socks_proxy_cf_close,
   socks_cf_get_host,
-  socks_cf_get_select_socks,
+  socks_cf_adjust_pollset,
   Curl_cf_def_data_pending,
   Curl_cf_def_send,
   Curl_cf_def_recv,
diff --git a/vendor/curl/lib/socks_gssapi.c b/vendor/curl/lib/socks_gssapi.c
index 2ede8c7c29..c0b42b871a 100644
--- a/vendor/curl/lib/socks_gssapi.c
+++ b/vendor/curl/lib/socks_gssapi.c
@@ -35,6 +35,7 @@
 #include "timeval.h"
 #include "socks.h"
 #include "warnless.h"
+#include "strdup.h"
 
 /* The last 3 #include files should be in this order */
 #include "curl_printf.h"
@@ -139,10 +140,9 @@ CURLcode Curl_SOCKS5_gssapi_negotiate(struct Curl_cfilter *cf,
   /* prepare service name */
   if(strchr(serviceptr, '/')) {
     service.length = serviceptr_length;
-    service.value = malloc(service.length);
+    service.value = Curl_memdup(serviceptr, service.length);
     if(!service.value)
       return CURLE_OUT_OF_MEMORY;
-    memcpy(service.value, serviceptr, service.length);
 
     gss_major_status = gss_import_name(&gss_minor_status, &service,
                                        (gss_OID) GSS_C_NULL_OID, &server);
@@ -387,12 +387,11 @@ CURLcode Curl_SOCKS5_gssapi_negotiate(struct Curl_cfilter *cf,
   }
   else {
     gss_send_token.length = 1;
-    gss_send_token.value = malloc(1);
+    gss_send_token.value = Curl_memdup(&gss_enc, 1);
     if(!gss_send_token.value) {
       gss_delete_sec_context(&gss_status, &gss_context, NULL);
       return CURLE_OUT_OF_MEMORY;
     }
-    memcpy(gss_send_token.value, &gss_enc, 1);
 
     gss_major_status = gss_wrap(&gss_minor_status, gss_context, 0,
                                 GSS_C_QOP_DEFAULT, &gss_send_token,
@@ -476,7 +475,7 @@ CURLcode Curl_SOCKS5_gssapi_negotiate(struct Curl_cfilter *cf,
                               gss_recv_token.length, &actualread);
 
   if(result || (actualread != us_length)) {
-    failf(data, "Failed to receive GSS-API encryptrion type.");
+    failf(data, "Failed to receive GSS-API encryption type.");
     gss_release_buffer(&gss_status, &gss_recv_token);
     gss_delete_sec_context(&gss_status, &gss_context, NULL);
     return CURLE_COULDNT_CONNECT;
diff --git a/vendor/curl/lib/socks_sspi.c b/vendor/curl/lib/socks_sspi.c
index d1200ea037..2baae2c2b2 100644
--- a/vendor/curl/lib/socks_sspi.c
+++ b/vendor/curl/lib/socks_sspi.c
@@ -331,9 +331,15 @@ CURLcode Curl_SOCKS5_gssapi_negotiate(struct Curl_cfilter *cf,
     failf(data, "Failed to determine user name.");
     return CURLE_COULDNT_CONNECT;
   }
-  infof(data, "SOCKS5 server authenticated user %s with GSS-API.",
-        names.sUserName);
-  s_pSecFn->FreeContextBuffer(names.sUserName);
+  else {
+#ifndef CURL_DISABLE_VERBOSE_STRINGS
+    char *user_utf8 = curlx_convert_tchar_to_UTF8(names.sUserName);
+    infof(data, "SOCKS5 server authenticated user %s with GSS-API.",
+          (user_utf8 ? user_utf8 : "(unknown)"));
+    curlx_unicodefree(user_utf8);
+#endif
+    s_pSecFn->FreeContextBuffer(names.sUserName);
+  }
 
   /* Do encryption */
   socksreq[0] = 1;    /* GSS-API subnegotiation version */
diff --git a/vendor/curl/lib/strcase.c b/vendor/curl/lib/strcase.c
index 7c0b4ef909..14d76f785d 100644
--- a/vendor/curl/lib/strcase.c
+++ b/vendor/curl/lib/strcase.c
@@ -71,7 +71,7 @@ static const unsigned char tolowermap[256] = {
    altered by the current locale. */
 char Curl_raw_toupper(char in)
 {
-  return touppermap[(unsigned char) in];
+  return (char)touppermap[(unsigned char) in];
 }
 
 
@@ -79,7 +79,7 @@ char Curl_raw_toupper(char in)
    altered by the current locale. */
 char Curl_raw_tolower(char in)
 {
-  return tolowermap[(unsigned char) in];
+  return (char)tolowermap[(unsigned char) in];
 }
 
 /*
diff --git a/vendor/curl/lib/strdup.c b/vendor/curl/lib/strdup.c
index 07a61391ae..299c9cc36b 100644
--- a/vendor/curl/lib/strdup.c
+++ b/vendor/curl/lib/strdup.c
@@ -26,7 +26,7 @@
 
 #include 
 
-#ifdef WIN32
+#ifdef _WIN32
 #include 
 #endif
 
@@ -56,7 +56,7 @@ char *Curl_strdup(const char *str)
 }
 #endif
 
-#ifdef WIN32
+#ifdef _WIN32
 /***************************************************************************
  *
  * Curl_wcsdup(source)
@@ -99,6 +99,26 @@ void *Curl_memdup(const void *src, size_t length)
   return buffer;
 }
 
+/***************************************************************************
+ *
+ * Curl_memdup0(source, length)
+ *
+ * Copies the 'source' string to a newly allocated buffer (that is returned).
+ * Copies 'length' bytes then adds a null terminator.
+ *
+ * Returns the new pointer or NULL on failure.
+ *
+ ***************************************************************************/
+void *Curl_memdup0(const char *src, size_t length)
+{
+  char *buf = malloc(length + 1);
+  if(!buf)
+    return NULL;
+  memcpy(buf, src, length);
+  buf[length] = 0;
+  return buf;
+}
+
 /***************************************************************************
  *
  * Curl_saferealloc(ptr, size)
diff --git a/vendor/curl/lib/strdup.h b/vendor/curl/lib/strdup.h
index c3430b54d5..238a2611f6 100644
--- a/vendor/curl/lib/strdup.h
+++ b/vendor/curl/lib/strdup.h
@@ -28,10 +28,11 @@
 #ifndef HAVE_STRDUP
 char *Curl_strdup(const char *str);
 #endif
-#ifdef WIN32
+#ifdef _WIN32
 wchar_t* Curl_wcsdup(const wchar_t* src);
 #endif
 void *Curl_memdup(const void *src, size_t buffer_length);
 void *Curl_saferealloc(void *ptr, size_t size);
+void *Curl_memdup0(const char *src, size_t length);
 
 #endif /* HEADER_CURL_STRDUP_H */
diff --git a/vendor/curl/lib/strerror.c b/vendor/curl/lib/strerror.c
index be41914140..f142cf181d 100644
--- a/vendor/curl/lib/strerror.c
+++ b/vendor/curl/lib/strerror.c
@@ -48,7 +48,7 @@
 #include "curl_memory.h"
 #include "memdebug.h"
 
-#if defined(WIN32) || defined(_WIN32_WCE)
+#if defined(_WIN32) || defined(_WIN32_WCE)
 #define PRESERVE_WINDOWS_ERROR_CODE
 #endif
 
@@ -319,6 +319,12 @@ curl_easy_strerror(CURLcode error)
   case CURLE_UNRECOVERABLE_POLL:
     return "Unrecoverable error in select/poll";
 
+  case CURLE_TOO_LARGE:
+    return "A value or data field grew larger than allowed";
+
+  case CURLE_ECH_REQUIRED:
+    return "ECH attempted but failed";
+
     /* error codes not used by current libcurl */
   case CURLE_OBSOLETE20:
   case CURLE_OBSOLETE24:
@@ -553,6 +559,9 @@ curl_url_strerror(CURLUcode error)
   case CURLUE_LACKS_IDN:
     return "libcurl lacks IDN support";
 
+  case CURLUE_TOO_LARGE:
+    return "A value or data field is larger than allowed";
+
   case CURLUE_LAST:
     break;
   }
@@ -572,10 +581,11 @@ curl_url_strerror(CURLUcode error)
  * Returns NULL if no error message was found for error code.
  */
 static const char *
-get_winsock_error (int err, char *buf, size_t len)
+get_winsock_error(int err, char *buf, size_t len)
 {
 #ifndef CURL_DISABLE_VERBOSE_STRINGS
   const char *p;
+  size_t alen;
 #endif
 
   if(!len)
@@ -755,14 +765,15 @@ get_winsock_error (int err, char *buf, size_t len)
   default:
     return NULL;
   }
-  strncpy(buf, p, len);
-  buf [len-1] = '\0';
+  alen = strlen(p);
+  if(alen < len)
+    strcpy(buf, p);
   return buf;
 #endif
 }
 #endif   /* USE_WINSOCK */
 
-#if defined(WIN32) || defined(_WIN32_WCE)
+#if defined(_WIN32) || defined(_WIN32_WCE)
 /* This is a helper function for Curl_strerror that converts Windows API error
  * codes (GetLastError) to error messages.
  * Returns NULL if no error message was found for error code.
@@ -804,7 +815,7 @@ get_winapi_error(int err, char *buf, size_t buflen)
 
   return (*buf ? buf : NULL);
 }
-#endif /* WIN32 || _WIN32_WCE */
+#endif /* _WIN32 || _WIN32_WCE */
 
 /*
  * Our thread-safe and smart strerror() replacement.
@@ -832,32 +843,30 @@ const char *Curl_strerror(int err, char *buf, size_t buflen)
 #endif
   int old_errno = errno;
   char *p;
-  size_t max;
 
   if(!buflen)
     return NULL;
 
-#ifndef WIN32
+#ifndef _WIN32
   DEBUGASSERT(err >= 0);
 #endif
 
-  max = buflen - 1;
   *buf = '\0';
 
-#if defined(WIN32) || defined(_WIN32_WCE)
-#if defined(WIN32)
+#if defined(_WIN32) || defined(_WIN32_WCE)
+#if defined(_WIN32)
   /* 'sys_nerr' is the maximum errno number, it is not widely portable */
   if(err >= 0 && err < sys_nerr)
-    strncpy(buf, sys_errlist[err], max);
+    msnprintf(buf, buflen, "%s", sys_errlist[err]);
   else
 #endif
   {
     if(
 #ifdef USE_WINSOCK
-       !get_winsock_error(err, buf, max) &&
+       !get_winsock_error(err, buf, buflen) &&
 #endif
-       !get_winapi_error((DWORD)err, buf, max))
-      msnprintf(buf, max, "Unknown error %d (%#x)", err, err);
+       !get_winapi_error((DWORD)err, buf, buflen))
+      msnprintf(buf, buflen, "Unknown error %d (%#x)", err, err);
   }
 #else /* not Windows coming up */
 
@@ -867,9 +876,9 @@ const char *Curl_strerror(int err, char *buf, size_t buflen)
   * storage is supplied via 'strerrbuf' and 'buflen' to hold the generated
   * message string, or EINVAL if 'errnum' is not a valid error number.
   */
-  if(0 != strerror_r(err, buf, max)) {
+  if(0 != strerror_r(err, buf, buflen)) {
     if('\0' == buf[0])
-      msnprintf(buf, max, "Unknown error %d", err);
+      msnprintf(buf, buflen, "Unknown error %d", err);
   }
 #elif defined(HAVE_STRERROR_R) && defined(HAVE_GLIBC_STRERROR_R)
  /*
@@ -881,25 +890,23 @@ const char *Curl_strerror(int err, char *buf, size_t buflen)
     char buffer[256];
     char *msg = strerror_r(err, buffer, sizeof(buffer));
     if(msg)
-      strncpy(buf, msg, max);
+      msnprintf(buf, buflen, "%s", msg);
     else
-      msnprintf(buf, max, "Unknown error %d", err);
+      msnprintf(buf, buflen, "Unknown error %d", err);
   }
 #else
   {
     /* !checksrc! disable STRERROR 1 */
     const char *msg = strerror(err);
     if(msg)
-      strncpy(buf, msg, max);
+      msnprintf(buf, buflen, "%s", msg);
     else
-      msnprintf(buf, max, "Unknown error %d", err);
+      msnprintf(buf, buflen, "Unknown error %d", err);
   }
 #endif
 
 #endif /* end of not Windows */
 
-  buf[max] = '\0'; /* make sure the string is null-terminated */
-
   /* strip trailing '\r\n' or '\n'. */
   p = strrchr(buf, '\n');
   if(p && (p - buf) >= 2)
@@ -923,7 +930,7 @@ const char *Curl_strerror(int err, char *buf, size_t buflen)
  * Curl_winapi_strerror:
  * Variant of Curl_strerror if the error code is definitely Windows API.
  */
-#if defined(WIN32) || defined(_WIN32_WCE)
+#if defined(_WIN32) || defined(_WIN32_WCE)
 const char *Curl_winapi_strerror(DWORD err, char *buf, size_t buflen)
 {
 #ifdef PRESERVE_WINDOWS_ERROR_CODE
@@ -943,8 +950,8 @@ const char *Curl_winapi_strerror(DWORD err, char *buf, size_t buflen)
 #else
   {
     const char *txt = (err == ERROR_SUCCESS) ? "No error" : "Error";
-    strncpy(buf, txt, buflen);
-    buf[buflen - 1] = '\0';
+    if(strlen(txt) < buflen)
+      strcpy(buf, txt);
   }
 #endif
 
@@ -958,7 +965,7 @@ const char *Curl_winapi_strerror(DWORD err, char *buf, size_t buflen)
 
   return buf;
 }
-#endif /* WIN32 || _WIN32_WCE */
+#endif /* _WIN32 || _WIN32_WCE */
 
 #ifdef USE_WINDOWS_SSPI
 /*
@@ -986,6 +993,10 @@ const char *Curl_sspi_strerror(int err, char *buf, size_t buflen)
       break;
 #define SEC2TXT(sec) case sec: txt = #sec; break
     SEC2TXT(CRYPT_E_REVOKED);
+    SEC2TXT(CRYPT_E_NO_REVOCATION_DLL);
+    SEC2TXT(CRYPT_E_NO_REVOCATION_CHECK);
+    SEC2TXT(CRYPT_E_REVOCATION_OFFLINE);
+    SEC2TXT(CRYPT_E_NOT_IN_REVOCATION_DATABASE);
     SEC2TXT(SEC_E_ALGORITHM_MISMATCH);
     SEC2TXT(SEC_E_BAD_BINDINGS);
     SEC2TXT(SEC_E_BAD_PKGID);
@@ -1077,17 +1088,11 @@ const char *Curl_sspi_strerror(int err, char *buf, size_t buflen)
               err);
   }
   else {
-    char txtbuf[80];
     char msgbuf[256];
-
-    msnprintf(txtbuf, sizeof(txtbuf), "%s (0x%08X)", txt, err);
-
     if(get_winapi_error(err, msgbuf, sizeof(msgbuf)))
-      msnprintf(buf, buflen, "%s - %s", txtbuf, msgbuf);
-    else {
-      strncpy(buf, txtbuf, buflen);
-      buf[buflen - 1] = '\0';
-    }
+      msnprintf(buf, buflen, "%s (0x%08X) - %s", txt, err, msgbuf);
+    else
+      msnprintf(buf, buflen, "%s (0x%08X)", txt, err);
   }
 
 #else
@@ -1095,8 +1100,8 @@ const char *Curl_sspi_strerror(int err, char *buf, size_t buflen)
     txt = "No error";
   else
     txt = "Error";
-  strncpy(buf, txt, buflen);
-  buf[buflen - 1] = '\0';
+  if(buflen > strlen(txt))
+    strcpy(buf, txt);
 #endif
 
   if(errno != old_errno)
diff --git a/vendor/curl/lib/strerror.h b/vendor/curl/lib/strerror.h
index 399712f8eb..6806867345 100644
--- a/vendor/curl/lib/strerror.h
+++ b/vendor/curl/lib/strerror.h
@@ -29,7 +29,7 @@
 #define STRERROR_LEN 256 /* a suitable length */
 
 const char *Curl_strerror(int err, char *buf, size_t buflen);
-#if defined(WIN32) || defined(_WIN32_WCE)
+#if defined(_WIN32) || defined(_WIN32_WCE)
 const char *Curl_winapi_strerror(DWORD err, char *buf, size_t buflen);
 #endif
 #ifdef USE_WINDOWS_SSPI
diff --git a/vendor/curl/lib/strtoofft.c b/vendor/curl/lib/strtoofft.c
index 077b25792e..580fd23bf1 100644
--- a/vendor/curl/lib/strtoofft.c
+++ b/vendor/curl/lib/strtoofft.c
@@ -79,11 +79,10 @@ static int get_char(char c, int base);
 static curl_off_t strtooff(const char *nptr, char **endptr, int base)
 {
   char *end;
-  int is_negative = 0;
-  int overflow;
+  bool is_negative = FALSE;
+  bool overflow = FALSE;
   int i;
   curl_off_t value = 0;
-  curl_off_t newval;
 
   /* Skip leading whitespace. */
   end = (char *)nptr;
@@ -93,7 +92,7 @@ static curl_off_t strtooff(const char *nptr, char **endptr, int base)
 
   /* Handle the sign, if any. */
   if(end[0] == '-') {
-    is_negative = 1;
+    is_negative = TRUE;
     end++;
   }
   else if(end[0] == '+') {
@@ -129,19 +128,15 @@ static curl_off_t strtooff(const char *nptr, char **endptr, int base)
   }
 
   /* Loop handling digits. */
-  value = 0;
-  overflow = 0;
   for(i = get_char(end[0], base);
       i != -1;
       end++, i = get_char(end[0], base)) {
-    newval = base * value + i;
-    if(newval < value) {
-      /* We've overflowed. */
-      overflow = 1;
+
+    if(value > (CURL_OFF_T_MAX - i) / base) {
+      overflow = TRUE;
       break;
     }
-    else
-      value = newval;
+    value = base * value + i;
   }
 
   if(!overflow) {
@@ -217,7 +212,7 @@ static int get_char(char c, int base)
 CURLofft curlx_strtoofft(const char *str, char **endp, int base,
                          curl_off_t *num)
 {
-  char *end;
+  char *end = NULL;
   curl_off_t number;
   errno = 0;
   *num = 0; /* clear by default */
diff --git a/vendor/curl/lib/system_win32.c b/vendor/curl/lib/system_win32.c
index 0cdaf3b2fe..d2862de923 100644
--- a/vendor/curl/lib/system_win32.c
+++ b/vendor/curl/lib/system_win32.c
@@ -24,7 +24,7 @@
 
 #include "curl_setup.h"
 
-#if defined(WIN32)
+#if defined(_WIN32)
 
 #include 
 #include "system_win32.h"
@@ -38,16 +38,23 @@
 
 LARGE_INTEGER Curl_freq;
 bool Curl_isVistaOrGreater;
+bool Curl_isWindows8OrGreater;
 
 /* Handle of iphlpapp.dll */
 static HMODULE s_hIpHlpApiDll = NULL;
 
-/* Pointer to the if_nametoindex function */
+/* Function pointers */
 IF_NAMETOINDEX_FN Curl_if_nametoindex = NULL;
+FREEADDRINFOEXW_FN Curl_FreeAddrInfoExW = NULL;
+GETADDRINFOEXCANCEL_FN Curl_GetAddrInfoExCancel = NULL;
+GETADDRINFOEXW_FN Curl_GetAddrInfoExW = NULL;
 
 /* Curl_win32_init() performs win32 global initialization */
 CURLcode Curl_win32_init(long flags)
 {
+#ifdef USE_WINSOCK
+  HMODULE ws2_32Dll;
+#endif
   /* CURL_GLOBAL_WIN32 controls the *optional* part of the initialization which
      is just for Winsock at the moment. Any required win32 initialization
      should take place after this block. */
@@ -104,6 +111,18 @@ CURLcode Curl_win32_init(long flags)
       Curl_if_nametoindex = pIfNameToIndex;
   }
 
+#ifdef USE_WINSOCK
+  ws2_32Dll = GetModuleHandleA("ws2_32");
+  if(ws2_32Dll) {
+    Curl_FreeAddrInfoExW = CURLX_FUNCTION_CAST(FREEADDRINFOEXW_FN,
+      GetProcAddress(ws2_32Dll, "FreeAddrInfoExW"));
+    Curl_GetAddrInfoExCancel = CURLX_FUNCTION_CAST(GETADDRINFOEXCANCEL_FN,
+      GetProcAddress(ws2_32Dll, "GetAddrInfoExCancel"));
+    Curl_GetAddrInfoExW = CURLX_FUNCTION_CAST(GETADDRINFOEXW_FN,
+      GetProcAddress(ws2_32Dll, "GetAddrInfoExW"));
+  }
+#endif
+
   /* curlx_verify_windows_version must be called during init at least once
      because it has its own initialization routine. */
   if(curlx_verify_windows_version(6, 0, 0, PLATFORM_WINNT,
@@ -113,6 +132,13 @@ CURLcode Curl_win32_init(long flags)
   else
     Curl_isVistaOrGreater = FALSE;
 
+  if(curlx_verify_windows_version(6, 2, 0, PLATFORM_WINNT,
+                                  VERSION_GREATER_THAN_EQUAL)) {
+    Curl_isWindows8OrGreater = TRUE;
+  }
+  else
+    Curl_isWindows8OrGreater = FALSE;
+
   QueryPerformanceFrequency(&Curl_freq);
   return CURLE_OK;
 }
@@ -120,6 +146,9 @@ CURLcode Curl_win32_init(long flags)
 /* Curl_win32_cleanup() is the opposite of Curl_win32_init() */
 void Curl_win32_cleanup(long init_flags)
 {
+  Curl_FreeAddrInfoExW = NULL;
+  Curl_GetAddrInfoExCancel = NULL;
+  Curl_GetAddrInfoExW = NULL;
   if(s_hIpHlpApiDll) {
     FreeLibrary(s_hIpHlpApiDll);
     s_hIpHlpApiDll = NULL;
@@ -238,4 +267,4 @@ HMODULE Curl_load_library(LPCTSTR filename)
 #endif
 }
 
-#endif /* WIN32 */
+#endif /* _WIN32 */
diff --git a/vendor/curl/lib/system_win32.h b/vendor/curl/lib/system_win32.h
index 6482643fab..bd490cabcc 100644
--- a/vendor/curl/lib/system_win32.h
+++ b/vendor/curl/lib/system_win32.h
@@ -26,10 +26,11 @@
 
 #include "curl_setup.h"
 
-#if defined(WIN32)
+#ifdef _WIN32
 
 extern LARGE_INTEGER Curl_freq;
 extern bool Curl_isVistaOrGreater;
+extern bool Curl_isWindows8OrGreater;
 
 CURLcode Curl_win32_init(long flags);
 void Curl_win32_cleanup(long init_flags);
@@ -40,10 +41,37 @@ typedef unsigned int(WINAPI *IF_NAMETOINDEX_FN)(const char *);
 /* This is used instead of if_nametoindex if available on Windows */
 extern IF_NAMETOINDEX_FN Curl_if_nametoindex;
 
+/* Identical copy of addrinfoexW/ADDRINFOEXW */
+typedef struct addrinfoexW_
+{
+  int                  ai_flags;
+  int                  ai_family;
+  int                  ai_socktype;
+  int                  ai_protocol;
+  size_t               ai_addrlen;
+  PWSTR                ai_canonname;
+  struct sockaddr     *ai_addr;
+  void                *ai_blob;
+  size_t               ai_bloblen;
+  LPGUID               ai_provider;
+  struct addrinfoexW_ *ai_next;
+} ADDRINFOEXW_;
+
+typedef void (CALLBACK *LOOKUP_COMPLETION_FN)(DWORD, DWORD, LPWSAOVERLAPPED);
+typedef void (WSAAPI *FREEADDRINFOEXW_FN)(ADDRINFOEXW_*);
+typedef int (WSAAPI *GETADDRINFOEXCANCEL_FN)(LPHANDLE);
+typedef int (WSAAPI *GETADDRINFOEXW_FN)(PCWSTR, PCWSTR, DWORD, LPGUID,
+  const ADDRINFOEXW_*, ADDRINFOEXW_**, struct timeval*, LPOVERLAPPED,
+  LOOKUP_COMPLETION_FN, LPHANDLE);
+
+extern FREEADDRINFOEXW_FN Curl_FreeAddrInfoExW;
+extern GETADDRINFOEXCANCEL_FN Curl_GetAddrInfoExCancel;
+extern GETADDRINFOEXW_FN Curl_GetAddrInfoExW;
+
 /* This is used to dynamically load DLLs */
 HMODULE Curl_load_library(LPCTSTR filename);
-#else  /* WIN32 */
+#else  /* _WIN32 */
 #define Curl_win32_init(x) CURLE_OK
-#endif /* !WIN32 */
+#endif /* !_WIN32 */
 
 #endif /* HEADER_CURL_SYSTEM_WIN32_H */
diff --git a/vendor/curl/lib/telnet.c b/vendor/curl/lib/telnet.c
index 850f88c1ec..227a166f2f 100644
--- a/vendor/curl/lib/telnet.c
+++ b/vendor/curl/lib/telnet.c
@@ -160,6 +160,7 @@ struct TELNET {
   unsigned short subopt_wsy;         /* Set with suboption NAWS */
   TelnetReceive telrcv_state;
   struct curl_slist *telnet_vars;    /* Environment variables */
+  struct dynbuf out;                 /* output buffer */
 
   /* suboptions */
   unsigned char subbuffer[SUBBUFSIZE];
@@ -172,7 +173,7 @@ struct TELNET {
  */
 
 const struct Curl_handler Curl_handler_telnet = {
-  "TELNET",                             /* scheme */
+  "telnet",                             /* scheme */
   ZERO_NULL,                            /* setup_connection */
   telnet_do,                            /* do_it */
   telnet_done,                          /* done */
@@ -185,7 +186,8 @@ const struct Curl_handler Curl_handler_telnet = {
   ZERO_NULL,                            /* domore_getsock */
   ZERO_NULL,                            /* perform_getsock */
   ZERO_NULL,                            /* disconnect */
-  ZERO_NULL,                            /* readwrite */
+  ZERO_NULL,                            /* write_resp */
+  ZERO_NULL,                            /* write_resp_hd */
   ZERO_NULL,                            /* connection_check */
   ZERO_NULL,                            /* attach connection */
   PORT_TELNET,                          /* defport */
@@ -204,6 +206,7 @@ CURLcode init_telnet(struct Curl_easy *data)
   if(!tn)
     return CURLE_OUT_OF_MEMORY;
 
+  Curl_dyn_init(&tn->out, 0xffff);
   data->req.p.telnet = tn; /* make us known */
 
   tn->telrcv_state = CURL_TS_DATA;
@@ -799,8 +802,10 @@ static CURLcode check_telnet_options(struct Curl_easy *data)
      was given on the command line */
   if(data->state.aptr.user) {
     char buffer[256];
-    if(str_is_nonascii(data->conn->user))
+    if(str_is_nonascii(data->conn->user)) {
+      DEBUGF(infof(data, "set a non ASCII user name in telnet"));
       return CURLE_BAD_FUNCTION_ARGUMENT;
+    }
     msnprintf(buffer, sizeof(buffer), "USER,%s", data->conn->user);
     beg = curl_slist_append(tn->telnet_vars, buffer);
     if(!beg) {
@@ -826,23 +831,27 @@ static CURLcode check_telnet_options(struct Curl_easy *data)
       case 5:
         /* Terminal type */
         if(strncasecompare(option, "TTYPE", 5)) {
-          strncpy(tn->subopt_ttype, arg, 31);
-          tn->subopt_ttype[31] = 0; /* String termination */
-          tn->us_preferred[CURL_TELOPT_TTYPE] = CURL_YES;
+          size_t l = strlen(arg);
+          if(l < sizeof(tn->subopt_ttype)) {
+            strcpy(tn->subopt_ttype, arg);
+            tn->us_preferred[CURL_TELOPT_TTYPE] = CURL_YES;
+            break;
+          }
         }
-        else
-          result = CURLE_UNKNOWN_OPTION;
+        result = CURLE_UNKNOWN_OPTION;
         break;
 
       case 8:
         /* Display variable */
         if(strncasecompare(option, "XDISPLOC", 8)) {
-          strncpy(tn->subopt_xdisploc, arg, 127);
-          tn->subopt_xdisploc[127] = 0; /* String termination */
-          tn->us_preferred[CURL_TELOPT_XDISPLOC] = CURL_YES;
+          size_t l = strlen(arg);
+          if(l < sizeof(tn->subopt_xdisploc)) {
+            strcpy(tn->subopt_xdisploc, arg);
+            tn->us_preferred[CURL_TELOPT_XDISPLOC] = CURL_YES;
+            break;
+          }
         }
-        else
-          result = CURLE_UNKNOWN_OPTION;
+        result = CURLE_UNKNOWN_OPTION;
         break;
 
       case 7:
@@ -1223,37 +1232,37 @@ CURLcode telrcv(struct Curl_easy *data,
 static CURLcode send_telnet_data(struct Curl_easy *data,
                                  char *buffer, ssize_t nread)
 {
-  ssize_t escapes, i, outlen;
-  unsigned char *outbuf = NULL;
+  size_t i, outlen;
+  unsigned char *outbuf;
   CURLcode result = CURLE_OK;
-  ssize_t bytes_written, total_written;
+  size_t bytes_written;
+  size_t total_written = 0;
   struct connectdata *conn = data->conn;
+  struct TELNET *tn = data->req.p.telnet;
 
-  /* Determine size of new buffer after escaping */
-  escapes = 0;
-  for(i = 0; i < nread; i++)
-    if((unsigned char)buffer[i] == CURL_IAC)
-      escapes++;
-  outlen = nread + escapes;
+  DEBUGASSERT(tn);
+  DEBUGASSERT(nread > 0);
+  if(nread < 0)
+    return CURLE_TOO_LARGE;
 
-  if(outlen == nread)
-    outbuf = (unsigned char *)buffer;
-  else {
-    ssize_t j;
-    outbuf = malloc(nread + escapes + 1);
-    if(!outbuf)
-      return CURLE_OUT_OF_MEMORY;
+  if(memchr(buffer, CURL_IAC, nread)) {
+    /* only use the escape buffer when necessary */
+    Curl_dyn_reset(&tn->out);
 
-    j = 0;
-    for(i = 0; i < nread; i++) {
-      outbuf[j++] = (unsigned char)buffer[i];
-      if((unsigned char)buffer[i] == CURL_IAC)
-        outbuf[j++] = CURL_IAC;
+    for(i = 0; i < (size_t)nread && !result; i++) {
+      result = Curl_dyn_addn(&tn->out, &buffer[i], 1);
+      if(!result && ((unsigned char)buffer[i] == CURL_IAC))
+        /* IAC is FF in hex */
+        result = Curl_dyn_addn(&tn->out, "\xff", 1);
     }
-    outbuf[j] = '\0';
-  }
 
-  total_written = 0;
+    outlen = Curl_dyn_len(&tn->out);
+    outbuf = Curl_dyn_uptr(&tn->out);
+  }
+  else {
+    outlen = (size_t)nread;
+    outbuf = (unsigned char *)buffer;
+  }
   while(!result && total_written < outlen) {
     /* Make sure socket is writable to avoid EWOULDBLOCK condition */
     struct pollfd pfd[1];
@@ -1266,19 +1275,13 @@ static CURLcode send_telnet_data(struct Curl_easy *data,
         break;
       default:                    /* write! */
         bytes_written = 0;
-        result = Curl_nwrite(data, FIRSTSOCKET,
-                             outbuf + total_written,
-                             outlen - total_written,
-                             &bytes_written);
+        result = Curl_xfer_send(data, outbuf + total_written,
+                                outlen - total_written, &bytes_written);
         total_written += bytes_written;
         break;
     }
   }
 
-  /* Free malloc copy if escaped */
-  if(outbuf != (unsigned char *)buffer)
-    free(outbuf);
-
   return result;
 }
 
@@ -1294,6 +1297,7 @@ static CURLcode telnet_done(struct Curl_easy *data,
 
   curl_slist_free_all(tn->telnet_vars);
   tn->telnet_vars = NULL;
+  Curl_dyn_free(&tn->out);
   return CURLE_OK;
 }
 
@@ -1321,7 +1325,7 @@ static CURLcode telnet_do(struct Curl_easy *data, bool *done)
   ssize_t nread;
   struct curltime now;
   bool keepon = TRUE;
-  char *buf = data->state.buffer;
+  char buffer[4*1024];
   struct TELNET *tn;
 
   *done = TRUE; /* unconditionally */
@@ -1378,7 +1382,7 @@ static CURLcode telnet_do(struct Curl_easy *data, bool *done)
 
   /* Keep on listening and act on events */
   while(keepon) {
-    const DWORD buf_size = (DWORD)data->set.buffer_size;
+    const DWORD buf_size = (DWORD)sizeof(buffer);
     DWORD waitret = WaitForMultipleObjects(obj_count, objs,
                                            FALSE, wait_timeout);
     switch(waitret) {
@@ -1389,7 +1393,7 @@ static CURLcode telnet_do(struct Curl_easy *data, bool *done)
         if(data->set.is_fread_set) {
           size_t n;
           /* read from user-supplied method */
-          n = data->state.fread_func(buf, 1, buf_size, data->state.in);
+          n = data->state.fread_func(buffer, 1, buf_size, data->state.in);
           if(n == CURL_READFUNC_ABORT) {
             keepon = FALSE;
             result = CURLE_READ_ERROR;
@@ -1417,7 +1421,7 @@ static CURLcode telnet_do(struct Curl_easy *data, bool *done)
           if(!readfile_read)
             break;
 
-          if(!ReadFile(stdin_handle, buf, buf_size,
+          if(!ReadFile(stdin_handle, buffer, buf_size,
                        &readfile_read, NULL)) {
             keepon = FALSE;
             result = CURLE_READ_ERROR;
@@ -1425,7 +1429,7 @@ static CURLcode telnet_do(struct Curl_easy *data, bool *done)
           }
         }
 
-        result = send_telnet_data(data, buf, readfile_read);
+        result = send_telnet_data(data, buffer, readfile_read);
         if(result) {
           keepon = FALSE;
           break;
@@ -1436,14 +1440,14 @@ static CURLcode telnet_do(struct Curl_easy *data, bool *done)
 
     case WAIT_OBJECT_0 + 1:
     {
-      if(!ReadFile(stdin_handle, buf, buf_size,
+      if(!ReadFile(stdin_handle, buffer, buf_size,
                    &readfile_read, NULL)) {
         keepon = FALSE;
         result = CURLE_READ_ERROR;
         break;
       }
 
-      result = send_telnet_data(data, buf, readfile_read);
+      result = send_telnet_data(data, buffer, readfile_read);
       if(result) {
         keepon = FALSE;
         break;
@@ -1465,7 +1469,7 @@ static CURLcode telnet_do(struct Curl_easy *data, bool *done)
       }
       if(events.lNetworkEvents & FD_READ) {
         /* read data from network */
-        result = Curl_read(data, sockfd, buf, data->set.buffer_size, &nread);
+        result = Curl_xfer_recv(data, buffer, sizeof(buffer), &nread);
         /* read would've blocked. Loop again */
         if(result == CURLE_AGAIN)
           break;
@@ -1481,7 +1485,7 @@ static CURLcode telnet_do(struct Curl_easy *data, bool *done)
           break;
         }
 
-        result = telrcv(data, (unsigned char *) buf, nread);
+        result = telrcv(data, (unsigned char *) buffer, nread);
         if(result) {
           keepon = FALSE;
           break;
@@ -1531,6 +1535,11 @@ static CURLcode telnet_do(struct Curl_easy *data, bool *done)
     pfd[1].events = POLLIN;
     poll_cnt = 2;
     interval_ms = 1 * 1000;
+    if(pfd[1].fd < 0) {
+      failf(data, "cannot read input");
+      result = CURLE_RECV_ERROR;
+      keepon = FALSE;
+    }
   }
 
   while(keepon) {
@@ -1542,11 +1551,11 @@ static CURLcode telnet_do(struct Curl_easy *data, bool *done)
     case 0:                     /* timeout */
       pfd[0].revents = 0;
       pfd[1].revents = 0;
-      /* FALLTHROUGH */
+      FALLTHROUGH();
     default:                    /* read! */
       if(pfd[0].revents & POLLIN) {
         /* read data from network */
-        result = Curl_read(data, sockfd, buf, data->set.buffer_size, &nread);
+        result = Curl_xfer_recv(data, buffer, sizeof(buffer), &nread);
         /* read would've blocked. Loop again */
         if(result == CURLE_AGAIN)
           break;
@@ -1570,8 +1579,9 @@ static CURLcode telnet_do(struct Curl_easy *data, bool *done)
         }
 
         total_dl += nread;
-        Curl_pgrsSetDownloadCounter(data, total_dl);
-        result = telrcv(data, (unsigned char *)buf, nread);
+        result = Curl_pgrsSetDownloadCounter(data, total_dl);
+        if(!result)
+          result = telrcv(data, (unsigned char *)buffer, nread);
         if(result) {
           keepon = FALSE;
           break;
@@ -1589,12 +1599,12 @@ static CURLcode telnet_do(struct Curl_easy *data, bool *done)
       nread = 0;
       if(poll_cnt == 2) {
         if(pfd[1].revents & POLLIN) { /* read from in file */
-          nread = read(pfd[1].fd, buf, data->set.buffer_size);
+          nread = read(pfd[1].fd, buffer, sizeof(buffer));
         }
       }
       else {
         /* read from user-supplied method */
-        nread = (int)data->state.fread_func(buf, 1, data->set.buffer_size,
+        nread = (int)data->state.fread_func(buffer, 1, sizeof(buffer),
                                             data->state.in);
         if(nread == CURL_READFUNC_ABORT) {
           keepon = FALSE;
@@ -1605,7 +1615,7 @@ static CURLcode telnet_do(struct Curl_easy *data, bool *done)
       }
 
       if(nread > 0) {
-        result = send_telnet_data(data, buf, nread);
+        result = send_telnet_data(data, buffer, nread);
         if(result) {
           keepon = FALSE;
           break;
@@ -1635,7 +1645,7 @@ static CURLcode telnet_do(struct Curl_easy *data, bool *done)
   }
 #endif
   /* mark this as "no further transfer wanted" */
-  Curl_setup_transfer(data, -1, -1, FALSE, -1);
+  Curl_xfer_setup(data, -1, -1, FALSE, -1);
 
   return result;
 }
diff --git a/vendor/curl/lib/tftp.c b/vendor/curl/lib/tftp.c
index 8ed1b887b4..310a0faba7 100644
--- a/vendor/curl/lib/tftp.c
+++ b/vendor/curl/lib/tftp.c
@@ -70,8 +70,6 @@
 
 /* RFC2348 allows the block size to be negotiated */
 #define TFTP_BLKSIZE_DEFAULT 512
-#define TFTP_BLKSIZE_MIN 8
-#define TFTP_BLKSIZE_MAX 65464
 #define TFTP_OPTION_BLKSIZE "blksize"
 
 /* from RFC2349: */
@@ -170,7 +168,7 @@ static CURLcode tftp_translate_code(tftp_error_t error);
  */
 
 const struct Curl_handler Curl_handler_tftp = {
-  "TFTP",                               /* scheme */
+  "tftp",                               /* scheme */
   tftp_setup_connection,                /* setup_connection */
   tftp_do,                              /* do_it */
   tftp_done,                            /* done */
@@ -183,7 +181,8 @@ const struct Curl_handler Curl_handler_tftp = {
   ZERO_NULL,                            /* domore_getsock */
   ZERO_NULL,                            /* perform_getsock */
   tftp_disconnect,                      /* disconnect */
-  ZERO_NULL,                            /* readwrite */
+  ZERO_NULL,                            /* write_resp */
+  ZERO_NULL,                            /* write_resp_hd */
   ZERO_NULL,                            /* connection_check */
   ZERO_NULL,                            /* attach connection */
   PORT_TFTP,                            /* defport */
@@ -454,8 +453,6 @@ static CURLcode tftp_send_first(struct tftp_state_data *state,
     if(data->state.upload) {
       /* If we are uploading, send an WRQ */
       setpacketevent(&state->spacket, TFTP_EVENT_WRQ);
-      state->data->req.upload_fromhere =
-        (char *)state->spacket.data + 4;
       if(data->state.infilesize != -1)
         Curl_pgrsSetUploadSize(data, data->state.infilesize);
     }
@@ -710,6 +707,8 @@ static CURLcode tftp_tx(struct tftp_state_data *state, tftp_event_t event)
   struct SingleRequest *k = &data->req;
   size_t cb; /* Bytes currently read */
   char buffer[STRERROR_LEN];
+  char *bufptr;
+  bool eos;
 
   switch(event) {
 
@@ -773,13 +772,14 @@ static CURLcode tftp_tx(struct tftp_state_data *state, tftp_event_t event)
      * data block.
      * */
     state->sbytes = 0;
-    state->data->req.upload_fromhere = (char *)state->spacket.data + 4;
+    bufptr = (char *)state->spacket.data + 4;
     do {
-      result = Curl_fillreadbuffer(data, state->blksize - state->sbytes, &cb);
+      result = Curl_client_read(data, bufptr, state->blksize - state->sbytes,
+                                &cb, &eos);
       if(result)
         return result;
       state->sbytes += (int)cb;
-      state->data->req.upload_fromhere += cb;
+      bufptr += cb;
     } while(state->sbytes < state->blksize && cb);
 
     sbytes = sendto(state->sockfd, (void *) state->spacket.data,
@@ -978,11 +978,9 @@ static CURLcode tftp_connect(struct Curl_easy *data, bool *done)
     return CURLE_OUT_OF_MEMORY;
 
   /* alloc pkt buffers based on specified blksize */
-  if(data->set.tftp_blksize) {
+  if(data->set.tftp_blksize)
+    /* range checked when set */
     blksize = (int)data->set.tftp_blksize;
-    if(blksize > TFTP_BLKSIZE_MAX || blksize < TFTP_BLKSIZE_MIN)
-      return CURLE_TFTP_ILLEGAL;
-  }
 
   need_blksize = blksize;
   /* default size is the fallback when no OACK is received */
@@ -1107,7 +1105,6 @@ static CURLcode tftp_receive_packet(struct Curl_easy *data)
   CURLcode              result = CURLE_OK;
   struct connectdata *conn = data->conn;
   struct tftp_state_data *state = conn->proto.tftpc;
-  struct SingleRequest  *k = &data->req;
 
   /* Receive the packet */
   fromlen = sizeof(fromaddr);
@@ -1145,8 +1142,6 @@ static CURLcode tftp_receive_packet(struct Curl_easy *data)
           tftp_state_machine(state, TFTP_EVENT_ERROR);
           return result;
         }
-        k->bytecount += state->rbytes-4;
-        Curl_pgrsSetDownloadCounter(data, (curl_off_t) k->bytecount);
       }
       break;
     case TFTP_EVENT_ERROR:
@@ -1209,7 +1204,7 @@ static timediff_t tftp_state_timeout(struct Curl_easy *data,
     state->state = TFTP_STATE_FIN;
     return 0;
   }
-  time(¤t);
+  current = time(NULL);
   if(current > state->rx_time + state->retry_time) {
     if(event)
       *event = TFTP_EVENT_TIMEOUT;
@@ -1247,7 +1242,7 @@ static CURLcode tftp_multi_statemach(struct Curl_easy *data, bool *done)
     *done = (state->state == TFTP_STATE_FIN) ? TRUE : FALSE;
     if(*done)
       /* Tell curl we're done */
-      Curl_setup_transfer(data, -1, -1, FALSE, -1);
+      Curl_xfer_setup(data, -1, -1, FALSE, -1);
   }
   else {
     /* no timeouts to handle, check our socket */
@@ -1270,7 +1265,7 @@ static CURLcode tftp_multi_statemach(struct Curl_easy *data, bool *done)
       *done = (state->state == TFTP_STATE_FIN) ? TRUE : FALSE;
       if(*done)
         /* Tell curl we're done */
-        Curl_setup_transfer(data, -1, -1, FALSE, -1);
+        Curl_xfer_setup(data, -1, -1, FALSE, -1);
     }
     /* if rc == 0, then select() timed out */
   }
diff --git a/vendor/curl/lib/tftp.h b/vendor/curl/lib/tftp.h
index 5d2d5da615..12404bf6d2 100644
--- a/vendor/curl/lib/tftp.h
+++ b/vendor/curl/lib/tftp.h
@@ -25,6 +25,9 @@
  ***************************************************************************/
 #ifndef CURL_DISABLE_TFTP
 extern const struct Curl_handler Curl_handler_tftp;
+
+#define TFTP_BLKSIZE_MIN 8
+#define TFTP_BLKSIZE_MAX 65464
 #endif
 
 #endif /* HEADER_CURL_TFTP_H */
diff --git a/vendor/curl/lib/timediff.c b/vendor/curl/lib/timediff.c
index 1b762bbd3e..d0824d1448 100644
--- a/vendor/curl/lib/timediff.c
+++ b/vendor/curl/lib/timediff.c
@@ -53,7 +53,7 @@ struct timeval *curlx_mstotv(struct timeval *tv, timediff_t ms)
 #endif
     tv->tv_sec = (time_t)tv_sec;
     tv->tv_usec = (suseconds_t)tv_usec;
-#elif defined(WIN32) /* maybe also others in the future */
+#elif defined(_WIN32) /* maybe also others in the future */
 #if TIMEDIFF_T_MAX > LONG_MAX
     /* tv_sec overflow check on Windows there we know it is long */
     if(tv_sec > LONG_MAX)
diff --git a/vendor/curl/lib/timeval.c b/vendor/curl/lib/timeval.c
index 2de79be46d..5a6727cbc4 100644
--- a/vendor/curl/lib/timeval.c
+++ b/vendor/curl/lib/timeval.c
@@ -24,11 +24,10 @@
 
 #include "timeval.h"
 
-#if defined(WIN32) && !defined(MSDOS)
+#if defined(_WIN32)
 
-/* set in win32_init() */
-extern LARGE_INTEGER Curl_freq;
-extern bool Curl_isVistaOrGreater;
+#include 
+#include "system_win32.h"
 
 /* In case of bug fix this function has a counterpart in tool_util.c */
 struct curltime Curl_now(void)
@@ -209,6 +208,20 @@ timediff_t Curl_timediff(struct curltime newer, struct curltime older)
   return diff * 1000 + (newer.tv_usec-older.tv_usec)/1000;
 }
 
+/*
+ * Returns: time difference in number of milliseconds, rounded up.
+ * For too large diffs it returns max value.
+ */
+timediff_t Curl_timediff_ceil(struct curltime newer, struct curltime older)
+{
+  timediff_t diff = (timediff_t)newer.tv_sec-older.tv_sec;
+  if(diff >= (TIMEDIFF_T_MAX/1000))
+    return TIMEDIFF_T_MAX;
+  else if(diff <= (TIMEDIFF_T_MIN/1000))
+    return TIMEDIFF_T_MIN;
+  return diff * 1000 + (newer.tv_usec - older.tv_usec + 999)/1000;
+}
+
 /*
  * Returns: time difference in number of microseconds. For too large diffs it
  * returns max value.
diff --git a/vendor/curl/lib/timeval.h b/vendor/curl/lib/timeval.h
index 92e484ad1d..33dfb5b10d 100644
--- a/vendor/curl/lib/timeval.h
+++ b/vendor/curl/lib/timeval.h
@@ -36,16 +36,24 @@ struct curltime {
 struct curltime Curl_now(void);
 
 /*
- * Make sure that the first argument (t1) is the more recent time and t2 is
- * the older time, as otherwise you get a weird negative time-diff back...
+ * Make sure that the first argument (newer) is the more recent time and older
+ * is the older time, as otherwise you get a weird negative time-diff back...
  *
  * Returns: the time difference in number of milliseconds.
  */
-timediff_t Curl_timediff(struct curltime t1, struct curltime t2);
+timediff_t Curl_timediff(struct curltime newer, struct curltime older);
 
 /*
- * Make sure that the first argument (t1) is the more recent time and t2 is
- * the older time, as otherwise you get a weird negative time-diff back...
+ * Make sure that the first argument (newer) is the more recent time and older
+ * is the older time, as otherwise you get a weird negative time-diff back...
+ *
+ * Returns: the time difference in number of milliseconds, rounded up.
+ */
+timediff_t Curl_timediff_ceil(struct curltime newer, struct curltime older);
+
+/*
+ * Make sure that the first argument (newer) is the more recent time and older
+ * is the older time, as otherwise you get a weird negative time-diff back...
  *
  * Returns: the time difference in number of microseconds.
  */
diff --git a/vendor/curl/lib/transfer.c b/vendor/curl/lib/transfer.c
index d0602b8753..744227eb36 100644
--- a/vendor/curl/lib/transfer.c
+++ b/vendor/curl/lib/transfer.c
@@ -40,9 +40,7 @@
 #ifdef HAVE_SYS_IOCTL_H
 #include 
 #endif
-#ifdef HAVE_SIGNAL_H
 #include 
-#endif
 
 #ifdef HAVE_SYS_PARAM_H
 #include 
@@ -65,6 +63,7 @@
 #include "content_encoding.h"
 #include "hostip.h"
 #include "cfilters.h"
+#include "cw-out.h"
 #include "transfer.h"
 #include "sendf.h"
 #include "speedcheck.h"
@@ -116,254 +115,6 @@ char *Curl_checkheaders(const struct Curl_easy *data,
 }
 #endif
 
-CURLcode Curl_get_upload_buffer(struct Curl_easy *data)
-{
-  if(!data->state.ulbuf) {
-    data->state.ulbuf = malloc(data->set.upload_buffer_size);
-    if(!data->state.ulbuf)
-      return CURLE_OUT_OF_MEMORY;
-  }
-  return CURLE_OK;
-}
-
-#ifndef CURL_DISABLE_HTTP
-/*
- * This function will be called to loop through the trailers buffer
- * until no more data is available for sending.
- */
-static size_t trailers_read(char *buffer, size_t size, size_t nitems,
-                            void *raw)
-{
-  struct Curl_easy *data = (struct Curl_easy *)raw;
-  struct dynbuf *trailers_buf = &data->state.trailers_buf;
-  size_t bytes_left = Curl_dyn_len(trailers_buf) -
-    data->state.trailers_bytes_sent;
-  size_t to_copy = (size*nitems < bytes_left) ? size*nitems : bytes_left;
-  if(to_copy) {
-    memcpy(buffer,
-           Curl_dyn_ptr(trailers_buf) + data->state.trailers_bytes_sent,
-           to_copy);
-    data->state.trailers_bytes_sent += to_copy;
-  }
-  return to_copy;
-}
-
-static size_t trailers_left(void *raw)
-{
-  struct Curl_easy *data = (struct Curl_easy *)raw;
-  struct dynbuf *trailers_buf = &data->state.trailers_buf;
-  return Curl_dyn_len(trailers_buf) - data->state.trailers_bytes_sent;
-}
-#endif
-
-/*
- * This function will call the read callback to fill our buffer with data
- * to upload.
- */
-CURLcode Curl_fillreadbuffer(struct Curl_easy *data, size_t bytes,
-                             size_t *nreadp)
-{
-  size_t buffersize = bytes;
-  size_t nread;
-
-  curl_read_callback readfunc = NULL;
-  void *extra_data = NULL;
-
-#ifndef CURL_DISABLE_HTTP
-  if(data->state.trailers_state == TRAILERS_INITIALIZED) {
-    struct curl_slist *trailers = NULL;
-    CURLcode result;
-    int trailers_ret_code;
-
-    /* at this point we already verified that the callback exists
-       so we compile and store the trailers buffer, then proceed */
-    infof(data,
-          "Moving trailers state machine from initialized to sending.");
-    data->state.trailers_state = TRAILERS_SENDING;
-    Curl_dyn_init(&data->state.trailers_buf, DYN_TRAILERS);
-
-    data->state.trailers_bytes_sent = 0;
-    Curl_set_in_callback(data, true);
-    trailers_ret_code = data->set.trailer_callback(&trailers,
-                                                   data->set.trailer_data);
-    Curl_set_in_callback(data, false);
-    if(trailers_ret_code == CURL_TRAILERFUNC_OK) {
-      result = Curl_http_compile_trailers(trailers, &data->state.trailers_buf,
-                                          data);
-    }
-    else {
-      failf(data, "operation aborted by trailing headers callback");
-      *nreadp = 0;
-      result = CURLE_ABORTED_BY_CALLBACK;
-    }
-    if(result) {
-      Curl_dyn_free(&data->state.trailers_buf);
-      curl_slist_free_all(trailers);
-      return result;
-    }
-    infof(data, "Successfully compiled trailers.");
-    curl_slist_free_all(trailers);
-  }
-#endif
-
-#ifndef CURL_DISABLE_HTTP
-  /* if we are transmitting trailing data, we don't need to write
-     a chunk size so we skip this */
-  if(data->req.upload_chunky &&
-     data->state.trailers_state == TRAILERS_NONE) {
-    /* if chunked Transfer-Encoding */
-    buffersize -= (8 + 2 + 2);   /* 32bit hex + CRLF + CRLF */
-    data->req.upload_fromhere += (8 + 2); /* 32bit hex + CRLF */
-  }
-
-  if(data->state.trailers_state == TRAILERS_SENDING) {
-    /* if we're here then that means that we already sent the last empty chunk
-       but we didn't send a final CR LF, so we sent 0 CR LF. We then start
-       pulling trailing data until we have no more at which point we
-       simply return to the previous point in the state machine as if
-       nothing happened.
-       */
-    readfunc = trailers_read;
-    extra_data = (void *)data;
-  }
-  else
-#endif
-  {
-    readfunc = data->state.fread_func;
-    extra_data = data->state.in;
-  }
-
-  Curl_set_in_callback(data, true);
-  nread = readfunc(data->req.upload_fromhere, 1,
-                   buffersize, extra_data);
-  Curl_set_in_callback(data, false);
-
-  if(nread == CURL_READFUNC_ABORT) {
-    failf(data, "operation aborted by callback");
-    *nreadp = 0;
-    return CURLE_ABORTED_BY_CALLBACK;
-  }
-  if(nread == CURL_READFUNC_PAUSE) {
-    struct SingleRequest *k = &data->req;
-
-    if(data->conn->handler->flags & PROTOPT_NONETWORK) {
-      /* protocols that work without network cannot be paused. This is
-         actually only FILE:// just now, and it can't pause since the transfer
-         isn't done using the "normal" procedure. */
-      failf(data, "Read callback asked for PAUSE when not supported");
-      return CURLE_READ_ERROR;
-    }
-
-    /* CURL_READFUNC_PAUSE pauses read callbacks that feed socket writes */
-    k->keepon |= KEEP_SEND_PAUSE; /* mark socket send as paused */
-    if(data->req.upload_chunky) {
-        /* Back out the preallocation done above */
-      data->req.upload_fromhere -= (8 + 2);
-    }
-    *nreadp = 0;
-
-    return CURLE_OK; /* nothing was read */
-  }
-  else if(nread > buffersize) {
-    /* the read function returned a too large value */
-    *nreadp = 0;
-    failf(data, "read function returned funny value");
-    return CURLE_READ_ERROR;
-  }
-
-#ifndef CURL_DISABLE_HTTP
-  if(!data->req.forbidchunk && data->req.upload_chunky) {
-    /* if chunked Transfer-Encoding
-     *    build chunk:
-     *
-     *         CRLF
-     *         CRLF
-     */
-    /* On non-ASCII platforms the  may or may not be
-       translated based on state.prefer_ascii while the protocol
-       portion must always be translated to the network encoding.
-       To further complicate matters, line end conversion might be
-       done later on, so we need to prevent CRLFs from becoming
-       CRCRLFs if that's the case.  To do this we use bare LFs
-       here, knowing they'll become CRLFs later on.
-     */
-
-    bool added_crlf = FALSE;
-    int hexlen = 0;
-    const char *endofline_native;
-    const char *endofline_network;
-
-    if(
-#ifdef CURL_DO_LINEEND_CONV
-       (data->state.prefer_ascii) ||
-#endif
-       (data->set.crlf)) {
-      /* \n will become \r\n later on */
-      endofline_native  = "\n";
-      endofline_network = "\x0a";
-    }
-    else {
-      endofline_native  = "\r\n";
-      endofline_network = "\x0d\x0a";
-    }
-
-    /* if we're not handling trailing data, proceed as usual */
-    if(data->state.trailers_state != TRAILERS_SENDING) {
-      char hexbuffer[11] = "";
-      hexlen = msnprintf(hexbuffer, sizeof(hexbuffer),
-                         "%zx%s", nread, endofline_native);
-
-      /* move buffer pointer */
-      data->req.upload_fromhere -= hexlen;
-      nread += hexlen;
-
-      /* copy the prefix to the buffer, leaving out the NUL */
-      memcpy(data->req.upload_fromhere, hexbuffer, hexlen);
-
-      /* always append ASCII CRLF to the data unless
-         we have a valid trailer callback */
-      if((nread-hexlen) == 0 &&
-          data->set.trailer_callback != NULL &&
-          data->state.trailers_state == TRAILERS_NONE) {
-        data->state.trailers_state = TRAILERS_INITIALIZED;
-      }
-      else {
-        memcpy(data->req.upload_fromhere + nread,
-               endofline_network,
-               strlen(endofline_network));
-        added_crlf = TRUE;
-      }
-    }
-
-    if(data->state.trailers_state == TRAILERS_SENDING &&
-       !trailers_left(data)) {
-      Curl_dyn_free(&data->state.trailers_buf);
-      data->state.trailers_state = TRAILERS_DONE;
-      data->set.trailer_data = NULL;
-      data->set.trailer_callback = NULL;
-      /* mark the transfer as done */
-      data->req.upload_done = TRUE;
-      infof(data, "Signaling end of chunked upload after trailers.");
-    }
-    else
-      if((nread - hexlen) == 0 &&
-         data->state.trailers_state != TRAILERS_INITIALIZED) {
-        /* mark this as done once this chunk is transferred */
-        data->req.upload_done = TRUE;
-        infof(data,
-              "Signaling end of chunked upload via terminating chunk.");
-      }
-
-    if(added_crlf)
-      nread += strlen(endofline_network); /* for the added end of line */
-  }
-#endif
-
-  *nreadp = nread;
-
-  return CURLE_OK;
-}
-
 static int data_pending(struct Curl_easy *data)
 {
   struct connectdata *conn = data->conn;
@@ -409,385 +160,164 @@ bool Curl_meets_timecondition(struct Curl_easy *data, time_t timeofdoc)
   return TRUE;
 }
 
+/**
+ * Receive raw response data for the transfer.
+ * @param data         the transfer
+ * @param buf          buffer to keep response data received
+ * @param blen         length of `buf`
+ * @param eos_reliable if EOS detection in underlying connection is reliable
+ * @param err error    code in case of -1 return
+ * @return number of bytes read or -1 for error
+ */
+static ssize_t Curl_xfer_recv_resp(struct Curl_easy *data,
+                                   char *buf, size_t blen,
+                                   bool eos_reliable,
+                                   CURLcode *err)
+{
+  ssize_t nread;
+
+  DEBUGASSERT(blen > 0);
+  /* If we are reading BODY data and the connection does NOT handle EOF
+   * and we know the size of the BODY data, limit the read amount */
+  if(!eos_reliable && !data->req.header && data->req.size != -1) {
+    curl_off_t totalleft = data->req.size - data->req.bytecount;
+    if(totalleft <= 0)
+      blen = 0;
+    else if(totalleft < (curl_off_t)blen)
+      blen = (size_t)totalleft;
+  }
+
+  if(!blen) {
+    /* want nothing - continue as if read nothing. */
+    DEBUGF(infof(data, "readwrite_data: we're done"));
+    *err = CURLE_OK;
+    return 0;
+  }
+
+  *err = Curl_xfer_recv(data, buf, blen, &nread);
+  if(*err)
+    return -1;
+  DEBUGASSERT(nread >= 0);
+  return nread;
+}
+
 /*
  * Go ahead and do a read if we have a readable socket or if
  * the stream was rewound (in which case we have data in a
  * buffer)
- *
- * return '*comeback' TRUE if we didn't properly drain the socket so this
- * function should get called again without select() or similar in between!
  */
 static CURLcode readwrite_data(struct Curl_easy *data,
-                               struct connectdata *conn,
                                struct SingleRequest *k,
-                               int *didwhat, bool *done,
-                               bool *comeback)
+                               int *didwhat)
 {
+  struct connectdata *conn = data->conn;
   CURLcode result = CURLE_OK;
-  ssize_t nread; /* number of bytes read */
-  size_t excess = 0; /* excess bytes read */
-  bool readmore = FALSE; /* used by RTP to signal for more data */
-  int maxloops = 100;
-  curl_off_t max_recv = data->set.max_recv_speed?
-                        data->set.max_recv_speed : CURL_OFF_T_MAX;
-  char *buf = data->state.buffer;
-  bool data_eof_handled = FALSE;
-  DEBUGASSERT(buf);
-
-  *done = FALSE;
-  *comeback = FALSE;
+  char *buf, *xfer_buf;
+  size_t blen, xfer_blen;
+  int maxloops = 10;
+  curl_off_t total_received = 0;
+  bool is_multiplex = FALSE;
+
+  result = Curl_multi_xfer_buf_borrow(data, &xfer_buf, &xfer_blen);
+  if(result)
+    goto out;
 
   /* This is where we loop until we have read everything there is to
      read or we get a CURLE_AGAIN */
   do {
-    bool is_empty_data = FALSE;
-    size_t buffersize = data->set.buffer_size;
-    size_t bytestoread = buffersize;
-    /* For HTTP/2 and HTTP/3, read data without caring about the content
-       length. This is safe because body in HTTP/2 is always segmented
-       thanks to its framing layer. Meanwhile, we have to call Curl_read
-       to ensure that http2_handle_stream_close is called when we read all
-       incoming bytes for a particular stream. */
-    bool is_http3 = Curl_conn_is_http3(data, conn, FIRSTSOCKET);
-    data_eof_handled = is_http3 || Curl_conn_is_http2(data, conn, FIRSTSOCKET);
-
-    if(!data_eof_handled && k->size != -1 && !k->header) {
-      /* make sure we don't read too much */
-      curl_off_t totalleft = k->size - k->bytecount;
-      if(totalleft < (curl_off_t)bytestoread)
-        bytestoread = (size_t)totalleft;
+    bool is_eos = FALSE;
+    size_t bytestoread;
+    ssize_t nread;
+
+    if(!is_multiplex) {
+      /* Multiplexed connection have inherent handling of EOF and we do not
+       * have to carefully restrict the amount we try to read.
+       * Multiplexed changes only in one direction. */
+      is_multiplex = Curl_conn_is_multiplex(conn, FIRSTSOCKET);
     }
 
-    if(bytestoread) {
-      /* receive data from the network! */
-      result = Curl_read(data, conn->sockfd, buf, bytestoread, &nread);
+    buf = xfer_buf;
+    bytestoread = xfer_blen;
 
-      /* read would've blocked */
+    if(bytestoread && data->set.max_recv_speed) {
+      /* In case of speed limit on receiving: if this loop already got
+       * data, break out. If not, limit the amount of bytes to receive.
+       * The overall, timed, speed limiting is done in multi.c */
+      if(total_received)
+        break;
+      if((size_t)data->set.max_recv_speed < bytestoread)
+        bytestoread = (size_t)data->set.max_recv_speed;
+    }
+
+    nread = Curl_xfer_recv_resp(data, buf, bytestoread,
+                                is_multiplex, &result);
+    if(nread < 0) {
       if(CURLE_AGAIN == result) {
         result = CURLE_OK;
         break; /* get out of loop */
       }
-
-      if(result>0)
-        goto out;
-    }
-    else {
-      /* read nothing but since we wanted nothing we consider this an OK
-         situation to proceed from */
-      DEBUGF(infof(data, "readwrite_data: we're done"));
-      nread = 0;
-    }
-
-    if(!k->bytecount) {
-      Curl_pgrsTime(data, TIMER_STARTTRANSFER);
-      if(k->exp100 > EXP100_SEND_DATA)
-        /* set time stamp to compare with when waiting for the 100 */
-        k->start100 = Curl_now();
+      goto out; /* real error */
     }
 
+    /* We only get a 0-length read on EndOfStream */
+    blen = (size_t)nread;
+    is_eos = (blen == 0);
     *didwhat |= KEEP_RECV;
-    /* indicates data of zero size, i.e. empty file */
-    is_empty_data = ((nread == 0) && (k->bodywrites == 0)) ? TRUE : FALSE;
 
-    if(0 < nread || is_empty_data) {
-      buf[nread] = 0;
-    }
-    if(!nread) {
+    if(!blen) {
       /* if we receive 0 or less here, either the data transfer is done or the
          server closed the connection and we bail out from this! */
-      if(data_eof_handled)
+      if(is_multiplex)
         DEBUGF(infof(data, "nread == 0, stream closed, bailing"));
       else
         DEBUGF(infof(data, "nread <= 0, server closed connection, bailing"));
-      k->keepon = 0; /* stop sending as well */
-      if(!is_empty_data)
-        break;
-    }
-
-    /* Default buffer to use when we write the buffer, it may be changed
-       in the flow below before the actual storing is done. */
-    k->str = buf;
-
-    if(conn->handler->readwrite) {
-      result = conn->handler->readwrite(data, conn, &nread, &readmore);
-      if(result)
-        goto out;
-      if(readmore)
+      k->keepon &= ~(KEEP_RECV|KEEP_SEND); /* stop sending as well */
+      if(k->eos_written) /* already did write this to client, leave */
         break;
     }
+    total_received += blen;
 
-#ifndef CURL_DISABLE_HTTP
-    /* Since this is a two-state thing, we check if we are parsing
-       headers at the moment or not. */
-    if(k->header) {
-      /* we are in parse-the-header-mode */
-      bool stop_reading = FALSE;
-      result = Curl_http_readwrite_headers(data, conn, &nread, &stop_reading);
-      if(result)
-        goto out;
-
-      if(conn->handler->readwrite &&
-         (k->maxdownload <= 0 && nread > 0)) {
-        result = conn->handler->readwrite(data, conn, &nread, &readmore);
-        if(result)
-          goto out;
-        if(readmore)
-          break;
-      }
-
-      if(stop_reading) {
-        /* We've stopped dealing with input, get out of the do-while loop */
-
-        if(nread > 0) {
-          infof(data,
-                "Excess found:"
-                " excess = %zd"
-                " url = %s (zero-length body)",
-                nread, data->state.up.path);
-        }
+    result = Curl_xfer_write_resp(data, buf, blen, is_eos);
+    if(result || data->req.done)
+      goto out;
 
-        break;
-      }
+    /* if we are done, we stop receiving. On multiplexed connections,
+     * we should read the EOS. Which may arrive as meta data after
+     * the bytes. Not taking it in might lead to RST of streams. */
+    if((!is_multiplex && data->req.download_done) || is_eos) {
+      data->req.keepon &= ~KEEP_RECV;
     }
-#endif /* CURL_DISABLE_HTTP */
-
-
-    /* This is not an 'else if' since it may be a rest from the header
-       parsing, where the beginning of the buffer is headers and the end
-       is non-headers. */
-    if(!k->header && (nread > 0 || is_empty_data)) {
-
-      if(data->req.no_body) {
-        /* data arrives although we want none, bail out */
-        streamclose(conn, "ignoring body");
-        *done = TRUE;
-        result = CURLE_WEIRD_SERVER_REPLY;
-        goto out;
-      }
-
-#ifndef CURL_DISABLE_HTTP
-      if(0 == k->bodywrites && !is_empty_data) {
-        /* These checks are only made the first time we are about to
-           write a piece of the body */
-        if(conn->handler->protocol&(PROTO_FAMILY_HTTP|CURLPROTO_RTSP)) {
-          /* HTTP-only checks */
-          result = Curl_http_firstwrite(data, conn, done);
-          if(result || *done)
-            goto out;
-        }
-      } /* this is the first time we write a body part */
-#endif /* CURL_DISABLE_HTTP */
-
-      k->bodywrites++;
-
-      /* pass data to the debug function before it gets "dechunked" */
-      if(data->set.verbose) {
-        if(k->badheader) {
-          Curl_debug(data, CURLINFO_DATA_IN,
-                     Curl_dyn_ptr(&data->state.headerb),
-                     Curl_dyn_len(&data->state.headerb));
-          if(k->badheader == HEADER_PARTHEADER)
-            Curl_debug(data, CURLINFO_DATA_IN,
-                       k->str, (size_t)nread);
-        }
-        else
-          Curl_debug(data, CURLINFO_DATA_IN,
-                     k->str, (size_t)nread);
-      }
-
-#ifndef CURL_DISABLE_HTTP
-      if(k->chunk) {
-        /*
-         * Here comes a chunked transfer flying and we need to decode this
-         * properly.  While the name says read, this function both reads
-         * and writes away the data. The returned 'nread' holds the number
-         * of actual data it wrote to the client.
-         */
-        CURLcode extra;
-        CHUNKcode res =
-          Curl_httpchunk_read(data, k->str, nread, &nread, &extra);
-
-        if(CHUNKE_OK < res) {
-          if(CHUNKE_PASSTHRU_ERROR == res) {
-            failf(data, "Failed reading the chunked-encoded stream");
-            result = extra;
-            goto out;
-          }
-          failf(data, "%s in chunked-encoding", Curl_chunked_strerror(res));
-          result = CURLE_RECV_ERROR;
-          goto out;
-        }
-        if(CHUNKE_STOP == res) {
-          /* we're done reading chunks! */
-          k->keepon &= ~KEEP_RECV; /* read no more */
-
-          /* N number of bytes at the end of the str buffer that weren't
-             written to the client. */
-          if(conn->chunk.datasize) {
-            infof(data, "Leftovers after chunking: % "
-                  CURL_FORMAT_CURL_OFF_T "u bytes",
-                  conn->chunk.datasize);
-          }
-        }
-        /* If it returned OK, we just keep going */
-      }
-#endif   /* CURL_DISABLE_HTTP */
-
-      /* Account for body content stored in the header buffer */
-      if((k->badheader == HEADER_PARTHEADER) && !k->ignorebody) {
-        size_t headlen = Curl_dyn_len(&data->state.headerb);
-        DEBUGF(infof(data, "Increasing bytecount by %zu", headlen));
-        k->bytecount += headlen;
-      }
-
-      if((-1 != k->maxdownload) &&
-         (k->bytecount + nread >= k->maxdownload)) {
-
-        excess = (size_t)(k->bytecount + nread - k->maxdownload);
-        if(excess > 0 && !k->ignorebody) {
-          infof(data,
-                "Excess found in a read:"
-                " excess = %zu"
-                ", size = %" CURL_FORMAT_CURL_OFF_T
-                ", maxdownload = %" CURL_FORMAT_CURL_OFF_T
-                ", bytecount = %" CURL_FORMAT_CURL_OFF_T,
-                excess, k->size, k->maxdownload, k->bytecount);
-          connclose(conn, "excess found in a read");
-        }
-
-        nread = (ssize_t) (k->maxdownload - k->bytecount);
-        if(nread < 0) /* this should be unusual */
-          nread = 0;
-
-        /* HTTP/3 over QUIC should keep reading until QUIC connection
-           is closed.  In contrast to HTTP/2 which can stop reading
-           from TCP connection, HTTP/3 over QUIC needs ACK from server
-           to ensure stream closure.  It should keep reading. */
-        if(!is_http3) {
-          k->keepon &= ~KEEP_RECV; /* we're done reading */
-        }
-      }
-
-      k->bytecount += nread;
-      max_recv -= nread;
-
-      Curl_pgrsSetDownloadCounter(data, k->bytecount);
-
-      if(!k->chunk && (nread || k->badheader || is_empty_data)) {
-        /* If this is chunky transfer, it was already written */
-
-        if(k->badheader && !k->ignorebody) {
-          /* we parsed a piece of data wrongly assuming it was a header
-             and now we output it as body instead */
-          size_t headlen = Curl_dyn_len(&data->state.headerb);
-
-          /* Don't let excess data pollute body writes */
-          if(k->maxdownload == -1 || (curl_off_t)headlen <= k->maxdownload)
-            result = Curl_client_write(data, CLIENTWRITE_BODY,
-                                       Curl_dyn_ptr(&data->state.headerb),
-                                       headlen);
-          else
-            result = Curl_client_write(data, CLIENTWRITE_BODY,
-                                       Curl_dyn_ptr(&data->state.headerb),
-                                       (size_t)k->maxdownload);
-
-          if(result)
-            goto out;
-        }
-        if(k->badheader < HEADER_ALLBAD) {
-          /* This switch handles various content encodings. If there's an
-             error here, be sure to check over the almost identical code
-             in http_chunks.c.
-             Make sure that ALL_CONTENT_ENCODINGS contains all the
-             encodings handled here. */
-          if(data->set.http_ce_skip || !k->writer_stack) {
-            if(!k->ignorebody && nread) {
-#ifndef CURL_DISABLE_POP3
-              if(conn->handler->protocol & PROTO_FAMILY_POP3)
-                result = Curl_pop3_write(data, k->str, nread);
-              else
-#endif /* CURL_DISABLE_POP3 */
-                result = Curl_client_write(data, CLIENTWRITE_BODY, k->str,
-                                           nread);
-            }
-          }
-          else if(!k->ignorebody && nread)
-            result = Curl_unencode_write(data, k->writer_stack, k->str, nread);
-        }
-        k->badheader = HEADER_NORMAL; /* taken care of now */
-
-        if(result)
-          goto out;
-      }
-
-    } /* if(!header and data to read) */
-
-    if(conn->handler->readwrite && excess) {
-      /* Parse the excess data */
-      k->str += nread;
-
-      if(&k->str[excess] > &buf[data->set.buffer_size]) {
-        /* the excess amount was too excessive(!), make sure
-           it doesn't read out of buffer */
-        excess = &buf[data->set.buffer_size] - k->str;
-      }
-      nread = (ssize_t)excess;
-
-      result = conn->handler->readwrite(data, conn, &nread, &readmore);
-      if(result)
-        goto out;
-
-      if(readmore)
-        k->keepon |= KEEP_RECV; /* we're not done reading */
+    /* if we are PAUSEd or stopped receiving, leave the loop */
+    if((k->keepon & KEEP_RECV_PAUSE) || !(k->keepon & KEEP_RECV))
       break;
-    }
 
-    if(is_empty_data) {
-      /* if we received nothing, the server closed the connection and we
-         are done */
-      k->keepon &= ~KEEP_RECV;
-    }
+  } while(maxloops-- && data_pending(data));
 
-    if((k->keepon & KEEP_RECV_PAUSE) || !(k->keepon & KEEP_RECV)) {
-      /* this is a paused or stopped transfer */
-      break;
-    }
-
-  } while((max_recv > 0) && data_pending(data) && maxloops--);
-
-  if(maxloops <= 0 || max_recv <= 0) {
-    /* we mark it as read-again-please */
-    data->state.dselect_bits = CURL_CSELECT_IN;
-    *comeback = TRUE;
+  if(maxloops <= 0) {
+    /* did not read until EAGAIN, mark read-again-please */
+    data->state.select_bits = CURL_CSELECT_IN;
+    if((k->keepon & KEEP_SENDBITS) == KEEP_SEND)
+      data->state.select_bits |= CURL_CSELECT_OUT;
   }
 
   if(((k->keepon & (KEEP_RECV|KEEP_SEND)) == KEEP_SEND) &&
-     (conn->bits.close || data_eof_handled)) {
+     (conn->bits.close || is_multiplex)) {
     /* When we've read the entire thing and the close bit is set, the server
        may now close the connection. If there's now any kind of sending going
        on from our side, we need to stop that immediately. */
     infof(data, "we are done reading and this is set to close, stop send");
     k->keepon &= ~KEEP_SEND; /* no writing anymore either */
+    k->keepon &= ~KEEP_SEND_PAUSE; /* no pausing anymore either */
   }
 
 out:
+  Curl_multi_xfer_buf_release(data, xfer_buf);
   if(result)
     DEBUGF(infof(data, "readwrite_data() -> %d", result));
   return result;
 }
 
-CURLcode Curl_done_sending(struct Curl_easy *data,
-                           struct SingleRequest *k)
-{
-  k->keepon &= ~KEEP_SEND; /* we're done writing */
-
-  /* These functions should be moved into the handler struct! */
-  Curl_conn_ev_data_done_send(data);
-
-  return CURLE_OK;
-}
-
-#if defined(WIN32) && defined(USE_WINSOCK)
+#if defined(_WIN32) && defined(USE_WINSOCK)
 #ifndef SIO_IDEAL_SEND_BACKLOG_QUERY
 #define SIO_IDEAL_SEND_BACKLOG_QUERY 0x4004747B
 #endif
@@ -809,273 +339,93 @@ static void win_update_buffer_size(curl_socket_t sockfd)
 #endif
 
 #define curl_upload_refill_watermark(data) \
-        ((ssize_t)((data)->set.upload_buffer_size >> 5))
+        ((size_t)((data)->set.upload_buffer_size >> 5))
 
 /*
  * Send data to upload to the server, when the socket is writable.
  */
-static CURLcode readwrite_upload(struct Curl_easy *data,
-                                 struct connectdata *conn,
-                                 int *didwhat)
+static CURLcode readwrite_upload(struct Curl_easy *data, int *didwhat)
 {
-  ssize_t i, si;
-  ssize_t bytes_written;
-  CURLcode result;
-  ssize_t nread; /* number of bytes read */
-  bool sending_http_headers = FALSE;
-  struct SingleRequest *k = &data->req;
-
-  *didwhat |= KEEP_SEND;
-
-  do {
-    curl_off_t nbody;
-    ssize_t offset = 0;
-
-    if(0 != k->upload_present &&
-       k->upload_present < curl_upload_refill_watermark(data) &&
-       !k->upload_chunky &&/*(variable sized chunked header; append not safe)*/
-       !k->upload_done &&  /*!(k->upload_done once k->upload_present sent)*/
-       !(k->writebytecount + k->upload_present - k->pendingheader ==
-         data->state.infilesize)) {
-      offset = k->upload_present;
-    }
-
-    /* only read more data if there's no upload data already
-       present in the upload buffer, or if appending to upload buffer */
-    if(0 == k->upload_present || offset) {
-      result = Curl_get_upload_buffer(data);
-      if(result)
-        return result;
-      if(offset && k->upload_fromhere != data->state.ulbuf)
-        memmove(data->state.ulbuf, k->upload_fromhere, offset);
-      /* init the "upload from here" pointer */
-      k->upload_fromhere = data->state.ulbuf;
-
-      if(!k->upload_done) {
-        /* HTTP pollution, this should be written nicer to become more
-           protocol agnostic. */
-        size_t fillcount;
-        struct HTTP *http = k->p.http;
-
-        if((k->exp100 == EXP100_SENDING_REQUEST) &&
-           (http->sending == HTTPSEND_BODY)) {
-          /* If this call is to send body data, we must take some action:
-             We have sent off the full HTTP 1.1 request, and we shall now
-             go into the Expect: 100 state and await such a header */
-          k->exp100 = EXP100_AWAITING_CONTINUE; /* wait for the header */
-          k->keepon &= ~KEEP_SEND;         /* disable writing */
-          k->start100 = Curl_now();       /* timeout count starts now */
-          *didwhat &= ~KEEP_SEND;  /* we didn't write anything actually */
-          /* set a timeout for the multi interface */
-          Curl_expire(data, data->set.expect_100_timeout, EXPIRE_100_TIMEOUT);
-          break;
-        }
-
-        if(conn->handler->protocol&(PROTO_FAMILY_HTTP|CURLPROTO_RTSP)) {
-          if(http->sending == HTTPSEND_REQUEST)
-            /* We're sending the HTTP request headers, not the data.
-               Remember that so we don't change the line endings. */
-            sending_http_headers = TRUE;
-          else
-            sending_http_headers = FALSE;
-        }
-
-        k->upload_fromhere += offset;
-        result = Curl_fillreadbuffer(data, data->set.upload_buffer_size-offset,
-                                     &fillcount);
-        k->upload_fromhere -= offset;
-        if(result)
-          return result;
-
-        nread = offset + fillcount;
-      }
-      else
-        nread = 0; /* we're done uploading/reading */
-
-      if(!nread && (k->keepon & KEEP_SEND_PAUSE)) {
-        /* this is a paused transfer */
-        break;
-      }
-      if(nread <= 0) {
-        result = Curl_done_sending(data, k);
-        if(result)
-          return result;
-        break;
-      }
-
-      /* store number of bytes available for upload */
-      k->upload_present = nread;
-
-      /* convert LF to CRLF if so asked */
-      if((!sending_http_headers) && (
-#ifdef CURL_DO_LINEEND_CONV
-         /* always convert if we're FTPing in ASCII mode */
-         (data->state.prefer_ascii) ||
-#endif
-         (data->set.crlf))) {
-        /* Do we need to allocate a scratch buffer? */
-        if(!data->state.scratch) {
-          data->state.scratch = malloc(2 * data->set.upload_buffer_size);
-          if(!data->state.scratch) {
-            failf(data, "Failed to alloc scratch buffer");
-
-            return CURLE_OUT_OF_MEMORY;
-          }
-        }
-
-        /*
-         * ASCII/EBCDIC Note: This is presumably a text (not binary)
-         * transfer so the data should already be in ASCII.
-         * That means the hex values for ASCII CR (0x0d) & LF (0x0a)
-         * must be used instead of the escape sequences \r & \n.
-         */
-        if(offset)
-          memcpy(data->state.scratch, k->upload_fromhere, offset);
-        for(i = offset, si = offset; i < nread; i++, si++) {
-          if(k->upload_fromhere[i] == 0x0a) {
-            data->state.scratch[si++] = 0x0d;
-            data->state.scratch[si] = 0x0a;
-            if(!data->set.crlf) {
-              /* we're here only because FTP is in ASCII mode...
-                 bump infilesize for the LF we just added */
-              if(data->state.infilesize != -1)
-                data->state.infilesize++;
-            }
-          }
-          else
-            data->state.scratch[si] = k->upload_fromhere[i];
-        }
-
-        if(si != nread) {
-          /* only perform the special operation if we really did replace
-             anything */
-          nread = si;
-
-          /* upload from the new (replaced) buffer instead */
-          k->upload_fromhere = data->state.scratch;
+  CURLcode result = CURLE_OK;
 
-          /* set the new amount too */
-          k->upload_present = nread;
-        }
-      }
+  if((data->req.keepon & KEEP_SEND_PAUSE))
+    return CURLE_OK;
 
-#ifndef CURL_DISABLE_SMTP
-      if(conn->handler->protocol & PROTO_FAMILY_SMTP) {
-        result = Curl_smtp_escape_eob(data, nread, offset);
-        if(result)
-          return result;
-      }
-#endif /* CURL_DISABLE_SMTP */
-    } /* if 0 == k->upload_present or appended to upload buffer */
-    else {
-      /* We have a partial buffer left from a previous "round". Use
-         that instead of reading more data */
-    }
+  /* We should not get here when the sending is already done. It
+   * probably means that someone set `data-req.keepon |= KEEP_SEND`
+   * when it should not. */
+  DEBUGASSERT(!Curl_req_done_sending(data));
 
-    /* write to socket (send away data) */
-    result = Curl_write(data,
-                        conn->writesockfd,  /* socket to send to */
-                        k->upload_fromhere, /* buffer pointer */
-                        k->upload_present,  /* buffer size */
-                        &bytes_written);    /* actually sent */
+  if(!Curl_req_done_sending(data)) {
+    *didwhat |= KEEP_SEND;
+    result = Curl_req_send_more(data);
     if(result)
       return result;
 
-#if defined(WIN32) && defined(USE_WINSOCK)
+#if defined(_WIN32) && defined(USE_WINSOCK)
+    /* FIXME: this looks like it would fit better into cf-socket.c
+     * but then I do not know enough Windows to say... */
     {
       struct curltime n = Curl_now();
-      if(Curl_timediff(n, k->last_sndbuf_update) > 1000) {
-        win_update_buffer_size(conn->writesockfd);
-        k->last_sndbuf_update = n;
+      if(Curl_timediff(n, data->conn->last_sndbuf_update) > 1000) {
+        win_update_buffer_size(data->conn->writesockfd);
+        data->conn->last_sndbuf_update = n;
       }
     }
 #endif
+  }
+  return result;
+}
 
-    if(k->pendingheader) {
-      /* parts of what was sent was header */
-      curl_off_t n = CURLMIN(k->pendingheader, bytes_written);
-      /* show the data before we change the pointer upload_fromhere */
-      Curl_debug(data, CURLINFO_HEADER_OUT, k->upload_fromhere, (size_t)n);
-      k->pendingheader -= n;
-      nbody = bytes_written - n; /* size of the written body part */
-    }
-    else
-      nbody = bytes_written;
-
-    if(nbody) {
-      /* show the data before we change the pointer upload_fromhere */
-      Curl_debug(data, CURLINFO_DATA_OUT,
-                 &k->upload_fromhere[bytes_written - nbody],
-                 (size_t)nbody);
-
-      k->writebytecount += nbody;
-      Curl_pgrsSetUploadCounter(data, k->writebytecount);
-    }
-
-    if((!k->upload_chunky || k->forbidchunk) &&
-       (k->writebytecount == data->state.infilesize)) {
-      /* we have sent all data we were supposed to */
-      k->upload_done = TRUE;
-      infof(data, "We are completely uploaded and fine");
-    }
-
-    if(k->upload_present != bytes_written) {
-      /* we only wrote a part of the buffer (if anything), deal with it! */
-
-      /* store the amount of bytes left in the buffer to write */
-      k->upload_present -= bytes_written;
-
-      /* advance the pointer where to find the buffer when the next send
-         is to happen */
-      k->upload_fromhere += bytes_written;
-    }
-    else {
-      /* we've uploaded that buffer now */
-      result = Curl_get_upload_buffer(data);
-      if(result)
-        return result;
-      k->upload_fromhere = data->state.ulbuf;
-      k->upload_present = 0; /* no more bytes left */
-
-      if(k->upload_done) {
-        result = Curl_done_sending(data, k);
-        if(result)
-          return result;
-      }
-    }
-
-
-  } while(0); /* just to break out from! */
-
-  return CURLE_OK;
+static int select_bits_paused(struct Curl_easy *data, int select_bits)
+{
+  /* See issue #11982: we really need to be careful not to progress
+   * a transfer direction when that direction is paused. Not all parts
+   * of our state machine are handling PAUSED transfers correctly. So, we
+   * do not want to go there.
+   * NOTE: we are only interested in PAUSE, not HOLD. */
+
+  /* if there is data in a direction not paused, return false */
+  if(((select_bits & CURL_CSELECT_IN) &&
+      !(data->req.keepon & KEEP_RECV_PAUSE)) ||
+     ((select_bits & CURL_CSELECT_OUT) &&
+      !(data->req.keepon & KEEP_SEND_PAUSE)))
+    return FALSE;
+
+  return (data->req.keepon & (KEEP_RECV_PAUSE|KEEP_SEND_PAUSE));
 }
 
 /*
  * Curl_readwrite() is the low-level function to be called when data is to
  * be read and written to/from the connection.
- *
- * return '*comeback' TRUE if we didn't properly drain the socket so this
- * function should get called again without select() or similar in between!
  */
-CURLcode Curl_readwrite(struct connectdata *conn,
-                        struct Curl_easy *data,
-                        bool *done,
-                        bool *comeback)
+CURLcode Curl_readwrite(struct Curl_easy *data)
 {
+  struct connectdata *conn = data->conn;
   struct SingleRequest *k = &data->req;
   CURLcode result;
   struct curltime now;
   int didwhat = 0;
   int select_bits;
 
-
-  if(data->state.dselect_bits) {
-    select_bits = data->state.dselect_bits;
-    data->state.dselect_bits = 0;
+  /* Check if client writes had been paused and can resume now. */
+  if(!(k->keepon & KEEP_RECV_PAUSE) && Curl_cwriter_is_paused(data)) {
+    Curl_conn_ev_data_pause(data, FALSE);
+    result = Curl_cwriter_unpause(data);
+    if(result)
+      goto out;
   }
-  else if(conn->cselect_bits) {
-    select_bits = conn->cselect_bits;
-    conn->cselect_bits = 0;
+
+  if(data->state.select_bits) {
+    if(select_bits_paused(data, data->state.select_bits)) {
+      /* leave the bits unchanged, so they'll tell us what to do when
+       * this transfer gets unpaused. */
+      DEBUGF(infof(data, "readwrite, select_bits, early return on PAUSED"));
+      result = CURLE_OK;
+      goto out;
+    }
+    select_bits = data->state.select_bits;
+    data->state.select_bits = 0;
   }
   else {
     curl_socket_t fd_read;
@@ -1103,8 +453,8 @@ CURLcode Curl_readwrite(struct connectdata *conn,
 
 #ifdef USE_HYPER
   if(conn->datastream) {
-    result = conn->datastream(data, conn, &didwhat, done, select_bits);
-    if(result || *done)
+    result = conn->datastream(data, conn, &didwhat, select_bits);
+    if(result || data->req.done)
       goto out;
   }
   else {
@@ -1113,16 +463,17 @@ CURLcode Curl_readwrite(struct connectdata *conn,
      the stream was rewound (in which case we have data in a
      buffer) */
   if((k->keepon & KEEP_RECV) && (select_bits & CURL_CSELECT_IN)) {
-    result = readwrite_data(data, conn, k, &didwhat, done, comeback);
-    if(result || *done)
+    result = readwrite_data(data, k, &didwhat);
+    if(result || data->req.done)
       goto out;
   }
 
   /* If we still have writing to do, we check if we have a writable socket. */
-  if((k->keepon & KEEP_SEND) && (select_bits & CURL_CSELECT_OUT)) {
+  if(((k->keepon & KEEP_SEND) && (select_bits & CURL_CSELECT_OUT)) ||
+     (k->keepon & KEEP_SEND_TIMED)) {
     /* write */
 
-    result = readwrite_upload(data, conn, &didwhat);
+    result = readwrite_upload(data, &didwhat);
     if(result)
       goto out;
   }
@@ -1132,31 +483,6 @@ CURLcode Curl_readwrite(struct connectdata *conn,
 
   now = Curl_now();
   if(!didwhat) {
-    /* no read no write, this is a timeout? */
-    if(k->exp100 == EXP100_AWAITING_CONTINUE) {
-      /* This should allow some time for the header to arrive, but only a
-         very short time as otherwise it'll be too much wasted time too
-         often. */
-
-      /* Quoting RFC2616, section "8.2.3 Use of the 100 (Continue) Status":
-
-         Therefore, when a client sends this header field to an origin server
-         (possibly via a proxy) from which it has never seen a 100 (Continue)
-         status, the client SHOULD NOT wait for an indefinite period before
-         sending the request body.
-
-      */
-
-      timediff_t ms = Curl_timediff(now, k->start100);
-      if(ms >= data->set.expect_100_timeout) {
-        /* we've waited long enough, continue anyway */
-        k->exp100 = EXP100_SEND_DATA;
-        k->keepon |= KEEP_SEND;
-        Curl_expire_done(data, EXPIRE_100_TIMEOUT);
-        infof(data, "Done waiting for 100-continue");
-      }
-    }
-
     result = Curl_conn_ev_data_idle(data);
     if(result)
       goto out;
@@ -1193,7 +519,6 @@ CURLcode Curl_readwrite(struct connectdata *conn,
      * The transfer has been performed. Just make some general checks before
      * returning.
      */
-
     if(!(data->req.no_body) && (k->size != -1) &&
        (k->bytecount != k->size) &&
 #ifdef CURL_DO_LINEEND_CONV
@@ -1209,81 +534,22 @@ CURLcode Curl_readwrite(struct connectdata *conn,
       result = CURLE_PARTIAL_FILE;
       goto out;
     }
-    if(!(data->req.no_body) && k->chunk &&
-       (conn->chunk.state != CHUNK_STOP)) {
-      /*
-       * In chunked mode, return an error if the connection is closed prior to
-       * the empty (terminating) chunk is read.
-       *
-       * The condition above used to check for
-       * conn->proto.http->chunk.datasize != 0 which is true after reading
-       * *any* chunk, not just the empty chunk.
-       *
-       */
-      failf(data, "transfer closed with outstanding read data remaining");
-      result = CURLE_PARTIAL_FILE;
-      goto out;
-    }
     if(Curl_pgrsUpdate(data)) {
       result = CURLE_ABORTED_BY_CALLBACK;
       goto out;
     }
   }
 
-  /* Now update the "done" boolean we return */
-  *done = (0 == (k->keepon&(KEEP_RECVBITS|KEEP_SENDBITS))) ? TRUE : FALSE;
+  /* If there is nothing more to send/recv, the request is done */
+  if(0 == (k->keepon&(KEEP_RECVBITS|KEEP_SENDBITS)))
+    data->req.done = TRUE;
+
 out:
   if(result)
     DEBUGF(infof(data, "Curl_readwrite() -> %d", result));
   return result;
 }
 
-/*
- * Curl_single_getsock() gets called by the multi interface code when the app
- * has requested to get the sockets for the current connection. This function
- * will then be called once for every connection that the multi interface
- * keeps track of. This function will only be called for connections that are
- * in the proper state to have this information available.
- */
-int Curl_single_getsock(struct Curl_easy *data,
-                        struct connectdata *conn,
-                        curl_socket_t *sock)
-{
-  int bitmap = GETSOCK_BLANK;
-  unsigned sockindex = 0;
-
-  if(conn->handler->perform_getsock)
-    return conn->handler->perform_getsock(data, conn, sock);
-
-  /* don't include HOLD and PAUSE connections */
-  if((data->req.keepon & KEEP_RECVBITS) == KEEP_RECV) {
-
-    DEBUGASSERT(conn->sockfd != CURL_SOCKET_BAD);
-
-    bitmap |= GETSOCK_READSOCK(sockindex);
-    sock[sockindex] = conn->sockfd;
-  }
-
-  /* don't include HOLD and PAUSE connections */
-  if((data->req.keepon & KEEP_SENDBITS) == KEEP_SEND) {
-    if((conn->sockfd != conn->writesockfd) ||
-       bitmap == GETSOCK_BLANK) {
-      /* only if they are not the same socket and we have a readable
-         one, we increase index */
-      if(bitmap != GETSOCK_BLANK)
-        sockindex++; /* increase index if we need two entries */
-
-      DEBUGASSERT(conn->writesockfd != CURL_SOCKET_BAD);
-
-      sock[sockindex] = conn->writesockfd;
-    }
-
-    bitmap |= GETSOCK_WRITESOCK(sockindex);
-  }
-
-  return bitmap;
-}
-
 /* Curl_init_CONNECT() gets called each time the handle switches to CONNECT
    which means this gets called once for each subsequent redirect etc */
 void Curl_init_CONNECT(struct Curl_easy *data)
@@ -1413,8 +679,7 @@ CURLcode Curl_pretransfer(struct Curl_easy *data)
           return CURLE_OUT_OF_MEMORY;
       }
       wc = data->wildcard;
-      if((wc->state < CURLWC_INIT) ||
-         (wc->state >= CURLWC_CLEAN)) {
+      if(wc->state < CURLWC_INIT) {
         if(wc->ftpwc)
           wc->dtor(wc->ftpwc);
         Curl_safefree(wc->pattern);
@@ -1447,12 +712,14 @@ CURLcode Curl_pretransfer(struct Curl_easy *data)
   if(!result)
     result = Curl_setstropt(&data->state.aptr.passwd,
                             data->set.str[STRING_PASSWORD]);
+#ifndef CURL_DISABLE_PROXY
   if(!result)
     result = Curl_setstropt(&data->state.aptr.proxyuser,
                             data->set.str[STRING_PROXYUSERNAME]);
   if(!result)
     result = Curl_setstropt(&data->state.aptr.proxypasswd,
                             data->set.str[STRING_PROXYPASSWORD]);
+#endif
 
   data->req.headerbytecount = 0;
   Curl_headers_cleanup(data);
@@ -1618,7 +885,7 @@ CURLcode Curl_follow(struct Curl_easy *data,
           return Curl_uc_to_curlcode(uc);
         }
 
-        p = Curl_builtin_scheme(scheme, CURL_ZERO_TERMINATED);
+        p = Curl_get_scheme_handler(scheme);
         if(p && (p->protocol != data->info.conn_protocol)) {
           infof(data, "Clear auth, redirects scheme from %s to %s",
                 data->info.conn_scheme, scheme);
@@ -1653,7 +920,7 @@ CURLcode Curl_follow(struct Curl_easy *data,
 
   data->state.url = newurl;
   data->state.url_alloc = TRUE;
-
+  Curl_req_soft_reset(&data->req, data);
   infof(data, "Issue another request to this URL: '%s'", data->state.url);
 
   /*
@@ -1699,6 +966,7 @@ CURLcode Curl_follow(struct Curl_easy *data,
        && !(data->set.keep_post & CURL_REDIR_POST_301)) {
       infof(data, "Switch from POST to GET");
       data->state.httpreq = HTTPREQ_GET;
+      Curl_creader_set_rewind(data, FALSE);
     }
     break;
   case 302: /* Found */
@@ -1724,6 +992,7 @@ CURLcode Curl_follow(struct Curl_easy *data,
        && !(data->set.keep_post & CURL_REDIR_POST_302)) {
       infof(data, "Switch from POST to GET");
       data->state.httpreq = HTTPREQ_GET;
+      Curl_creader_set_rewind(data, FALSE);
     }
     break;
 
@@ -1826,23 +1095,16 @@ CURLcode Curl_retry_request(struct Curl_easy *data, char **url)
                                 prevent i.e HTTP transfers to return
                                 error just because nothing has been
                                 transferred! */
-
-
-    if((conn->handler->protocol&PROTO_FAMILY_HTTP) &&
-       data->req.writebytecount) {
-      data->state.rewindbeforesend = TRUE;
-      infof(data, "state.rewindbeforesend = TRUE");
-    }
+    Curl_creader_set_rewind(data, TRUE);
   }
   return CURLE_OK;
 }
 
 /*
- * Curl_setup_transfer() is called to setup some basic properties for the
+ * Curl_xfer_setup() is called to setup some basic properties for the
  * upcoming transfer.
  */
-void
-Curl_setup_transfer(
+void Curl_xfer_setup(
   struct Curl_easy *data,   /* transfer */
   int sockindex,            /* socket index to read from or -1 */
   curl_off_t size,          /* -1 if unknown at this point */
@@ -1853,22 +1115,19 @@ Curl_setup_transfer(
 {
   struct SingleRequest *k = &data->req;
   struct connectdata *conn = data->conn;
-  struct HTTP *http = data->req.p.http;
-  bool httpsending;
+  bool want_send = Curl_req_want_send(data);
 
   DEBUGASSERT(conn != NULL);
   DEBUGASSERT((sockindex <= 1) && (sockindex >= -1));
+  DEBUGASSERT((writesockindex <= 1) && (writesockindex >= -1));
 
-  httpsending = ((conn->handler->protocol&PROTO_FAMILY_HTTP) &&
-                 (http->sending == HTTPSEND_REQUEST));
-
-  if(conn->bits.multiplex || conn->httpversion >= 20 || httpsending) {
+  if(conn->bits.multiplex || conn->httpversion >= 20 || want_send) {
     /* when multiplexing, the read/write sockets need to be the same! */
     conn->sockfd = sockindex == -1 ?
       ((writesockindex == -1 ? CURL_SOCKET_BAD : conn->sock[writesockindex])) :
       conn->sock[sockindex];
     conn->writesockfd = conn->sockfd;
-    if(httpsending)
+    if(want_send)
       /* special and very HTTP-specific */
       writesockindex = FIRSTSOCKET;
   }
@@ -1897,37 +1156,123 @@ Curl_setup_transfer(
     if(sockindex != -1)
       k->keepon |= KEEP_RECV;
 
-    if(writesockindex != -1) {
-      /* HTTP 1.1 magic:
-
-         Even if we require a 100-return code before uploading data, we might
-         need to write data before that since the REQUEST may not have been
-         finished sent off just yet.
-
-         Thus, we must check if the request has been sent before we set the
-         state info where we wait for the 100-return code
-      */
-      if((data->state.expect100header) &&
-         (conn->handler->protocol&PROTO_FAMILY_HTTP) &&
-         (http->sending == HTTPSEND_BODY)) {
-        /* wait with write until we either got 100-continue or a timeout */
-        k->exp100 = EXP100_AWAITING_CONTINUE;
-        k->start100 = Curl_now();
-
-        /* Set a timeout for the multi interface. Add the inaccuracy margin so
-           that we don't fire slightly too early and get denied to run. */
-        Curl_expire(data, data->set.expect_100_timeout, EXPIRE_100_TIMEOUT);
-      }
-      else {
-        if(data->state.expect100header)
-          /* when we've sent off the rest of the headers, we must await a
-             100-continue but first finish sending the request */
-          k->exp100 = EXP100_SENDING_REQUEST;
+    if(writesockindex != -1)
+      k->keepon |= KEEP_SEND;
+  } /* if(k->getheader || !data->req.no_body) */
 
-        /* enable the write bit when we're not waiting for continue */
-        k->keepon |= KEEP_SEND;
+}
+
+CURLcode Curl_xfer_write_resp(struct Curl_easy *data,
+                              const char *buf, size_t blen,
+                              bool is_eos)
+{
+  CURLcode result = CURLE_OK;
+
+  if(data->conn->handler->write_resp) {
+    /* protocol handlers offering this function take full responsibility
+     * for writing all received download data to the client. */
+    result = data->conn->handler->write_resp(data, buf, blen, is_eos);
+  }
+  else {
+    /* No special handling by protocol handler, write all received data
+     * as BODY to the client. */
+    if(blen || is_eos) {
+      int cwtype = CLIENTWRITE_BODY;
+      if(is_eos)
+        cwtype |= CLIENTWRITE_EOS;
+
+#ifndef CURL_DISABLE_POP3
+      if(blen && data->conn->handler->protocol & PROTO_FAMILY_POP3) {
+        result = data->req.ignorebody? CURLE_OK :
+                 Curl_pop3_write(data, buf, blen);
       }
-    } /* if(writesockindex != -1) */
-  } /* if(k->getheader || !data->req.no_body) */
+      else
+#endif /* CURL_DISABLE_POP3 */
+        result = Curl_client_write(data, cwtype, buf, blen);
+    }
+  }
+
+  if(!result && is_eos) {
+    /* If we wrote the EOS, we are definitely done */
+    data->req.eos_written = TRUE;
+    data->req.download_done = TRUE;
+  }
+  CURL_TRC_WRITE(data, "xfer_write_resp(len=%zu, eos=%d) -> %d",
+                 blen, is_eos, result);
+  return result;
+}
+
+CURLcode Curl_xfer_write_resp_hd(struct Curl_easy *data,
+                                 const char *hd0, size_t hdlen, bool is_eos)
+{
+  if(data->conn->handler->write_resp_hd) {
+    /* protocol handlers offering this function take full responsibility
+     * for writing all received download data to the client. */
+    return data->conn->handler->write_resp_hd(data, hd0, hdlen, is_eos);
+  }
+  /* No special handling by protocol handler, write as response bytes */
+  return Curl_xfer_write_resp(data, hd0, hdlen, is_eos);
+}
+
+CURLcode Curl_xfer_write_done(struct Curl_easy *data, bool premature)
+{
+  (void)premature;
+  return Curl_cw_out_done(data);
+}
+
+CURLcode Curl_xfer_send(struct Curl_easy *data,
+                        const void *buf, size_t blen,
+                        size_t *pnwritten)
+{
+  CURLcode result;
+  int sockindex;
+
+  if(!data || !data->conn)
+    return CURLE_FAILED_INIT;
+  /* FIXME: would like to enable this, but some protocols (MQTT) do not
+   * setup the transfer correctly, it seems
+  if(data->conn->writesockfd == CURL_SOCKET_BAD) {
+    failf(data, "transfer not setup for sending");
+    DEBUGASSERT(0);
+    return CURLE_SEND_ERROR;
+  } */
+  sockindex = ((data->conn->writesockfd != CURL_SOCKET_BAD) &&
+               (data->conn->writesockfd == data->conn->sock[SECONDARYSOCKET]));
+  result = Curl_conn_send(data, sockindex, buf, blen, pnwritten);
+  if(result == CURLE_AGAIN) {
+    result = CURLE_OK;
+    *pnwritten = 0;
+  }
+  else if(!result && *pnwritten)
+    data->info.request_size += *pnwritten;
 
+  return result;
+}
+
+CURLcode Curl_xfer_recv(struct Curl_easy *data,
+                        char *buf, size_t blen,
+                        ssize_t *pnrcvd)
+{
+  int sockindex;
+
+  if(!data || !data->conn)
+    return CURLE_FAILED_INIT;
+  /* FIXME: would like to enable this, but some protocols (MQTT) do not
+   * setup the transfer correctly, it seems
+  if(data->conn->sockfd == CURL_SOCKET_BAD) {
+    failf(data, "transfer not setup for receiving");
+    DEBUGASSERT(0);
+    return CURLE_RECV_ERROR;
+  } */
+  sockindex = ((data->conn->sockfd != CURL_SOCKET_BAD) &&
+               (data->conn->sockfd == data->conn->sock[SECONDARYSOCKET]));
+  if(data->set.buffer_size > 0 && (size_t)data->set.buffer_size < blen)
+    blen = (size_t)data->set.buffer_size;
+  return Curl_conn_recv(data, sockindex, buf, blen, pnrcvd);
+}
+
+CURLcode Curl_xfer_send_close(struct Curl_easy *data)
+{
+  Curl_conn_ev_data_done_send(data);
+  return CURLE_OK;
 }
diff --git a/vendor/curl/lib/transfer.h b/vendor/curl/lib/transfer.h
index 536ac249b7..ad0f3a20cc 100644
--- a/vendor/curl/lib/transfer.h
+++ b/vendor/curl/lib/transfer.h
@@ -45,23 +45,39 @@ typedef enum {
 
 CURLcode Curl_follow(struct Curl_easy *data, char *newurl,
                      followtype type);
-CURLcode Curl_readwrite(struct connectdata *conn,
-                        struct Curl_easy *data, bool *done,
-                        bool *comeback);
+CURLcode Curl_readwrite(struct Curl_easy *data);
 int Curl_single_getsock(struct Curl_easy *data,
                         struct connectdata *conn, curl_socket_t *socks);
-CURLcode Curl_fillreadbuffer(struct Curl_easy *data, size_t bytes,
-                             size_t *nreadp);
 CURLcode Curl_retry_request(struct Curl_easy *data, char **url);
 bool Curl_meets_timecondition(struct Curl_easy *data, time_t timeofdoc);
-CURLcode Curl_get_upload_buffer(struct Curl_easy *data);
 
-CURLcode Curl_done_sending(struct Curl_easy *data,
-                           struct SingleRequest *k);
+/**
+ * Write the transfer raw response bytes, as received from the connection.
+ * Will handle all passed bytes or return an error. By default, this will
+ * write the bytes as BODY to the client. Protocols may provide a
+ * "write_resp" callback in their handler to add specific treatment. E.g.
+ * HTTP parses response headers and passes them differently to the client.
+ * @param data     the transfer
+ * @param buf      the raw response bytes
+ * @param blen     the amount of bytes in `buf`
+ * @param is_eos   TRUE iff the connection indicates this to be the last
+ *                 bytes of the response
+ */
+CURLcode Curl_xfer_write_resp(struct Curl_easy *data,
+                              const char *buf, size_t blen,
+                              bool is_eos);
+
+/**
+ * Write a single "header" line from a server response.
+ * @param hd0      the 0-terminated, single header line
+ * @param hdlen    the length of the header line
+ * @param is_eos   TRUE iff this is the end of the response
+ */
+CURLcode Curl_xfer_write_resp_hd(struct Curl_easy *data,
+                                 const char *hd0, size_t hdlen, bool is_eos);
 
 /* This sets up a forthcoming transfer */
-void
-Curl_setup_transfer (struct Curl_easy *data,
+void Curl_xfer_setup(struct Curl_easy *data,
                      int sockindex,     /* socket index to read from or -1 */
                      curl_off_t size,   /* -1 if unknown at this point */
                      bool getheader,    /* TRUE if header parsing is wanted */
@@ -70,4 +86,30 @@ Curl_setup_transfer (struct Curl_easy *data,
                                            disables */
   );
 
+/**
+ * Multi has set transfer to DONE. Last chance to trigger
+ * missing response things like writing an EOS to the client.
+ */
+CURLcode Curl_xfer_write_done(struct Curl_easy *data, bool premature);
+
+/**
+ * Send data on the socket/connection filter designated
+ * for transfer's outgoing data.
+ * Will return CURLE_OK on blocking with (*pnwritten == 0).
+ */
+CURLcode Curl_xfer_send(struct Curl_easy *data,
+                        const void *buf, size_t blen,
+                        size_t *pnwritten);
+
+/**
+ * Receive data on the socket/connection filter designated
+ * for transfer's incoming data.
+ * Will return CURLE_AGAIN on blocking with (*pnrcvd == 0).
+ */
+CURLcode Curl_xfer_recv(struct Curl_easy *data,
+                        char *buf, size_t blen,
+                        ssize_t *pnrcvd);
+
+CURLcode Curl_xfer_send_close(struct Curl_easy *data);
+
 #endif /* HEADER_CURL_TRANSFER_H */
diff --git a/vendor/curl/lib/url.c b/vendor/curl/lib/url.c
index 4f5673ed0d..2814d31ad9 100644
--- a/vendor/curl/lib/url.c
+++ b/vendor/curl/lib/url.c
@@ -168,130 +168,6 @@ static curl_prot_t get_protocol_family(const struct Curl_handler *h)
   return h->family;
 }
 
-
-/*
- * Protocol table. Schemes (roughly) in 2019 popularity order:
- *
- * HTTPS, HTTP, FTP, FTPS, SFTP, FILE, SCP, SMTP, LDAP, IMAPS, TELNET, IMAP,
- * LDAPS, SMTPS, TFTP, SMB, POP3, GOPHER POP3S, RTSP, RTMP, SMBS, DICT
- */
-static const struct Curl_handler * const protocols[] = {
-
-#if defined(USE_SSL) && !defined(CURL_DISABLE_HTTP)
-  &Curl_handler_https,
-#endif
-
-#ifndef CURL_DISABLE_HTTP
-  &Curl_handler_http,
-#endif
-
-#ifdef USE_WEBSOCKETS
-#if defined(USE_SSL) && !defined(CURL_DISABLE_HTTP)
-  &Curl_handler_wss,
-#endif
-
-#ifndef CURL_DISABLE_HTTP
-  &Curl_handler_ws,
-#endif
-#endif
-
-#ifndef CURL_DISABLE_FTP
-  &Curl_handler_ftp,
-#endif
-
-#if defined(USE_SSL) && !defined(CURL_DISABLE_FTP)
-  &Curl_handler_ftps,
-#endif
-
-#if defined(USE_SSH)
-  &Curl_handler_sftp,
-#endif
-
-#ifndef CURL_DISABLE_FILE
-  &Curl_handler_file,
-#endif
-
-#if defined(USE_SSH) && !defined(USE_WOLFSSH)
-  &Curl_handler_scp,
-#endif
-
-#ifndef CURL_DISABLE_SMTP
-  &Curl_handler_smtp,
-#ifdef USE_SSL
-  &Curl_handler_smtps,
-#endif
-#endif
-
-#ifndef CURL_DISABLE_LDAP
-  &Curl_handler_ldap,
-#if !defined(CURL_DISABLE_LDAPS) && \
-    ((defined(USE_OPENLDAP) && defined(USE_SSL)) || \
-     (!defined(USE_OPENLDAP) && defined(HAVE_LDAP_SSL)))
-  &Curl_handler_ldaps,
-#endif
-#endif
-
-#ifndef CURL_DISABLE_IMAP
-  &Curl_handler_imap,
-#ifdef USE_SSL
-  &Curl_handler_imaps,
-#endif
-#endif
-
-#ifndef CURL_DISABLE_TELNET
-  &Curl_handler_telnet,
-#endif
-
-#ifndef CURL_DISABLE_TFTP
-  &Curl_handler_tftp,
-#endif
-
-#ifndef CURL_DISABLE_POP3
-  &Curl_handler_pop3,
-#ifdef USE_SSL
-  &Curl_handler_pop3s,
-#endif
-#endif
-
-#if !defined(CURL_DISABLE_SMB) && defined(USE_CURL_NTLM_CORE) && \
-   (SIZEOF_CURL_OFF_T > 4)
-  &Curl_handler_smb,
-#ifdef USE_SSL
-  &Curl_handler_smbs,
-#endif
-#endif
-
-#ifndef CURL_DISABLE_RTSP
-  &Curl_handler_rtsp,
-#endif
-
-#ifndef CURL_DISABLE_MQTT
-  &Curl_handler_mqtt,
-#endif
-
-#ifndef CURL_DISABLE_GOPHER
-  &Curl_handler_gopher,
-#ifdef USE_SSL
-  &Curl_handler_gophers,
-#endif
-#endif
-
-#ifdef USE_LIBRTMP
-  &Curl_handler_rtmp,
-  &Curl_handler_rtmpt,
-  &Curl_handler_rtmpe,
-  &Curl_handler_rtmpte,
-  &Curl_handler_rtmps,
-  &Curl_handler_rtmpts,
-#endif
-
-#ifndef CURL_DISABLE_DICT
-  &Curl_handler_dict,
-#endif
-
-  (struct Curl_handler *) NULL
-};
-
 void Curl_freeset(struct Curl_easy *data)
 {
   /* Free all dynamic strings stored in the data->set substructure. */
@@ -320,8 +196,8 @@ void Curl_freeset(struct Curl_easy *data)
   Curl_mime_cleanpart(&data->set.mimepost);
 
 #ifndef CURL_DISABLE_COOKIES
-  curl_slist_free_all(data->set.cookielist);
-  data->set.cookielist = NULL;
+  curl_slist_free_all(data->state.cookielist);
+  data->state.cookielist = NULL;
 #endif
 }
 
@@ -363,16 +239,18 @@ CURLcode Curl_close(struct Curl_easy **datap)
   /* Detach connection if any is left. This should not be normal, but can be
      the case for example with CONNECT_ONLY + recv/send (test 556) */
   Curl_detach_connection(data);
-  if(data->multi)
-    /* This handle is still part of a multi handle, take care of this first
-       and detach this handle from there. */
-    curl_multi_remove_handle(data->multi, data);
+  if(!data->state.internal) {
+    if(data->multi)
+      /* This handle is still part of a multi handle, take care of this first
+         and detach this handle from there. */
+      curl_multi_remove_handle(data->multi, data);
 
-  if(data->multi_easy) {
-    /* when curl_easy_perform() is used, it creates its own multi handle to
-       use and this is the one */
-    curl_multi_cleanup(data->multi_easy);
-    data->multi_easy = NULL;
+    if(data->multi_easy) {
+      /* when curl_easy_perform() is used, it creates its own multi handle to
+         use and this is the one */
+      curl_multi_cleanup(data->multi_easy);
+      data->multi_easy = NULL;
+    }
   }
 
   data->magic = 0; /* force a clear AFTER the possibly enforced removal from
@@ -383,7 +261,7 @@ CURLcode Curl_close(struct Curl_easy **datap)
     free(data->state.range);
 
   /* freed here just in case DONE wasn't called */
-  Curl_free_request_state(data);
+  Curl_req_free(&data->req, data);
 
   /* Close down all open SSL info and sessions */
   Curl_ssl_close_all(data);
@@ -391,10 +269,6 @@ CURLcode Curl_close(struct Curl_easy **datap)
   Curl_safefree(data->state.scratch);
   Curl_ssl_free_certinfo(data);
 
-  /* Cleanup possible redirect junk */
-  free(data->req.newurl);
-  data->req.newurl = NULL;
-
   if(data->state.referer_alloc) {
     Curl_safefree(data->state.referer);
     data->state.referer_alloc = FALSE;
@@ -402,17 +276,17 @@ CURLcode Curl_close(struct Curl_easy **datap)
   data->state.referer = NULL;
 
   up_free(data);
-  Curl_safefree(data->state.buffer);
   Curl_dyn_free(&data->state.headerb);
-  Curl_safefree(data->state.ulbuf);
   Curl_flush_cookies(data, TRUE);
+#ifndef CURL_DISABLE_ALTSVC
   Curl_altsvc_save(data, data->asi, data->set.str[STRING_ALTSVC]);
   Curl_altsvc_cleanup(&data->asi);
-  Curl_hsts_save(data, data->hsts, data->set.str[STRING_HSTS]);
+#endif
 #ifndef CURL_DISABLE_HSTS
+  Curl_hsts_save(data, data->hsts, data->set.str[STRING_HSTS]);
   if(!data->share || !data->share->hsts)
     Curl_hsts_cleanup(&data->hsts);
-  curl_slist_free_all(data->set.hstslist); /* clean up list */
+  curl_slist_free_all(data->state.hstslist); /* clean up list */
 #endif
 #if !defined(CURL_DISABLE_HTTP) && !defined(CURL_DISABLE_DIGEST_AUTH)
   Curl_http_auth_cleanup_digest(data);
@@ -433,7 +307,9 @@ CURLcode Curl_close(struct Curl_easy **datap)
     Curl_share_unlock(data, CURL_LOCK_DATA_SHARE);
   }
 
+#ifndef CURL_DISABLE_PROXY
   Curl_safefree(data->state.aptr.proxyuserpwd);
+#endif
   Curl_safefree(data->state.aptr.uagent);
   Curl_safefree(data->state.aptr.userpwd);
   Curl_safefree(data->state.aptr.accept_encoding);
@@ -441,24 +317,21 @@ CURLcode Curl_close(struct Curl_easy **datap)
   Curl_safefree(data->state.aptr.rangeline);
   Curl_safefree(data->state.aptr.ref);
   Curl_safefree(data->state.aptr.host);
+#ifndef CURL_DISABLE_COOKIES
   Curl_safefree(data->state.aptr.cookiehost);
+#endif
+#ifndef CURL_DISABLE_RTSP
   Curl_safefree(data->state.aptr.rtsp_transport);
+#endif
   Curl_safefree(data->state.aptr.user);
   Curl_safefree(data->state.aptr.passwd);
+#ifndef CURL_DISABLE_PROXY
   Curl_safefree(data->state.aptr.proxyuser);
   Curl_safefree(data->state.aptr.proxypasswd);
-
-#ifndef CURL_DISABLE_DOH
-  if(data->req.doh) {
-    Curl_dyn_free(&data->req.doh->probe[0].serverdoh);
-    Curl_dyn_free(&data->req.doh->probe[1].serverdoh);
-    curl_slist_free_all(data->req.doh->headers);
-    Curl_safefree(data->req.doh);
-  }
 #endif
 
+#if !defined(CURL_DISABLE_HTTP) && !defined(CURL_DISABLE_FORM_API)
   Curl_mime_cleanpart(data->state.formp);
-#ifndef CURL_DISABLE_HTTP
   Curl_safefree(data->state.formp);
 #endif
 
@@ -490,7 +363,6 @@ CURLcode Curl_init_userdefined(struct Curl_easy *data)
   set->fread_func_set = (curl_read_callback)fread;
   set->is_fread_set = 0;
 
-  set->seek_func = ZERO_NULL;
   set->seek_client = ZERO_NULL;
 
   set->filesize = -1;        /* we don't know the size */
@@ -530,26 +402,16 @@ CURLcode Curl_init_userdefined(struct Curl_easy *data)
 
   Curl_mime_initpart(&set->mimepost);
 
-  /*
-   * libcurl 7.10 introduced SSL verification *by default*! This needs to be
-   * switched off unless wanted.
-   */
+  Curl_ssl_easy_config_init(data);
 #ifndef CURL_DISABLE_DOH
   set->doh_verifyhost = TRUE;
   set->doh_verifypeer = TRUE;
 #endif
-  set->ssl.primary.verifypeer = TRUE;
-  set->ssl.primary.verifyhost = TRUE;
 #ifdef USE_SSH
   /* defaults to any auth type */
   set->ssh_auth_types = CURLSSH_AUTH_DEFAULT;
   set->new_directory_perms = 0755; /* Default permissions */
 #endif
-  set->ssl.primary.sessionid = TRUE; /* session ID caching enabled by
-                                        default */
-#ifndef CURL_DISABLE_PROXY
-  set->proxy_ssl = set->ssl;
-#endif
 
   set->new_file_perms = 0644;    /* Default permissions */
   set->allowed_protocols = (curl_prot_t) CURLPROTO_ALL;
@@ -566,29 +428,33 @@ CURLcode Curl_init_userdefined(struct Curl_easy *data)
 
   /* Set the default CA cert bundle/path detected/specified at build time.
    *
-   * If Schannel is the selected SSL backend then these locations are
-   * ignored. We allow setting CA location for schannel only when explicitly
-   * specified by the user via CURLOPT_CAINFO / --cacert.
+   * If Schannel or SecureTransport is the selected SSL backend then these
+   * locations are ignored. We allow setting CA location for schannel and
+   * securetransport when explicitly specified by the user via
+   *  CURLOPT_CAINFO / --cacert.
    */
-  if(Curl_ssl_backend() != CURLSSLBACKEND_SCHANNEL) {
+  if(Curl_ssl_backend() != CURLSSLBACKEND_SCHANNEL &&
+     Curl_ssl_backend() != CURLSSLBACKEND_SECURETRANSPORT) {
 #if defined(CURL_CA_BUNDLE)
     result = Curl_setstropt(&set->str[STRING_SSL_CAFILE], CURL_CA_BUNDLE);
     if(result)
       return result;
-
+#ifndef CURL_DISABLE_PROXY
     result = Curl_setstropt(&set->str[STRING_SSL_CAFILE_PROXY],
                             CURL_CA_BUNDLE);
     if(result)
       return result;
 #endif
+#endif
 #if defined(CURL_CA_PATH)
     result = Curl_setstropt(&set->str[STRING_SSL_CAPATH], CURL_CA_PATH);
     if(result)
       return result;
-
+#ifndef CURL_DISABLE_PROXY
     result = Curl_setstropt(&set->str[STRING_SSL_CAPATH_PROXY], CURL_CA_PATH);
     if(result)
       return result;
+#endif
 #endif
   }
 
@@ -650,9 +516,12 @@ CURLcode Curl_open(struct Curl_easy **curl)
 
   data->magic = CURLEASY_MAGIC_NUMBER;
 
+  Curl_req_init(&data->req);
+
   result = Curl_resolver_init(data, &data->state.async.resolver);
   if(result) {
     DEBUGF(fprintf(stderr, "Error: resolver_init failed\n"));
+    Curl_req_free(&data->req, data);
     free(data);
     return result;
   }
@@ -676,6 +545,7 @@ CURLcode Curl_open(struct Curl_easy **curl)
     Curl_resolver_cleanup(data->state.async.resolver);
     Curl_dyn_free(&data->state.headerb);
     Curl_freeset(data);
+    Curl_req_free(&data->req, data);
     free(data);
     data = NULL;
   }
@@ -718,22 +588,18 @@ static void conn_free(struct Curl_easy *data, struct connectdata *conn)
   Curl_safefree(conn->socks_proxy.passwd);
   Curl_safefree(conn->http_proxy.host.rawalloc); /* http proxy name buffer */
   Curl_safefree(conn->socks_proxy.host.rawalloc); /* socks proxy name buffer */
-  Curl_free_primary_ssl_config(&conn->proxy_ssl_config);
 #endif
   Curl_safefree(conn->user);
   Curl_safefree(conn->passwd);
   Curl_safefree(conn->sasl_authzid);
   Curl_safefree(conn->options);
   Curl_safefree(conn->oauth_bearer);
-#ifndef CURL_DISABLE_HTTP
-  Curl_dyn_free(&conn->trailer);
-#endif
   Curl_safefree(conn->host.rawalloc); /* host name buffer */
   Curl_safefree(conn->conn_to_host.rawalloc); /* host name buffer */
   Curl_safefree(conn->hostname_resolve);
   Curl_safefree(conn->secondaryhostname);
   Curl_safefree(conn->localdev);
-  Curl_free_primary_ssl_config(&conn->ssl_config);
+  Curl_ssl_conn_config_cleanup(conn);
 
 #ifdef USE_UNIX_SOCKETS
   Curl_safefree(conn->unix_domain_socket);
@@ -888,8 +754,8 @@ static bool conn_maxage(struct Curl_easy *data,
   idletime /= 1000; /* integer seconds is fine */
 
   if(idletime > data->set.maxage_conn) {
-    infof(data, "Too old connection (%ld seconds idle), disconnect it",
-          idletime);
+    infof(data, "Too old connection (%" CURL_FORMAT_TIMEDIFF_T
+          " seconds idle), disconnect it", idletime);
     return TRUE;
   }
 
@@ -898,8 +764,8 @@ static bool conn_maxage(struct Curl_easy *data,
 
   if(data->set.maxlifetime_conn && lifetime > data->set.maxlifetime_conn) {
     infof(data,
-          "Too old connection (%ld seconds since creation), disconnect it",
-          lifetime);
+          "Too old connection (%" CURL_FORMAT_TIMEDIFF_T
+          " seconds since creation), disconnect it", lifetime);
     return TRUE;
   }
 
@@ -908,16 +774,16 @@ static bool conn_maxage(struct Curl_easy *data,
 }
 
 /*
- * This function checks if the given connection is dead and extracts it from
+ * This function checks if the given connection is dead and prunes it from
  * the connection cache if so.
  *
  * When this is called as a Curl_conncache_foreach() callback, the connection
  * cache lock is held!
  *
- * Returns TRUE if the connection was dead and extracted.
+ * Returns TRUE if the connection was dead and pruned.
  */
-static bool extract_if_dead(struct connectdata *conn,
-                            struct Curl_easy *data)
+static bool prune_if_dead(struct connectdata *conn,
+                          struct Curl_easy *data)
 {
   if(!CONN_INUSE(conn)) {
     /* The check for a dead socket makes sense only if the connection isn't in
@@ -944,7 +810,7 @@ static bool extract_if_dead(struct connectdata *conn,
 
     }
     else {
-      bool input_pending;
+      bool input_pending = FALSE;
 
       Curl_attach_connection(data, conn);
       dead = !Curl_conn_is_alive(data, conn, &input_pending);
@@ -963,6 +829,7 @@ static bool extract_if_dead(struct connectdata *conn,
     }
 
     if(dead) {
+      /* remove connection from cache */
       infof(data, "Connection %" CURL_FORMAT_CURL_OFF_T " seems to be dead",
             conn->connection_id);
       Curl_conncache_remove_conn(data, conn, FALSE);
@@ -972,22 +839,17 @@ static bool extract_if_dead(struct connectdata *conn,
   return FALSE;
 }
 
-struct prunedead {
-  struct Curl_easy *data;
-  struct connectdata *extracted;
-};
-
 /*
- * Wrapper to use extract_if_dead() function in Curl_conncache_foreach()
+ * Wrapper to use prune_if_dead() function in Curl_conncache_foreach()
  *
  */
-static int call_extract_if_dead(struct Curl_easy *data,
-                                struct connectdata *conn, void *param)
+static int call_prune_if_dead(struct Curl_easy *data,
+                              struct connectdata *conn, void *param)
 {
-  struct prunedead *p = (struct prunedead *)param;
-  if(extract_if_dead(conn, data)) {
-    /* stop the iteration here, pass back the connection that was extracted */
-    p->extracted = conn;
+  struct connectdata **pruned = (struct connectdata **)param;
+  if(prune_if_dead(conn, data)) {
+    /* stop the iteration here, pass back the connection that was pruned */
+    *pruned = conn;
     return 1;
   }
   return 0; /* continue iteration */
@@ -1011,18 +873,15 @@ static void prune_dead_connections(struct Curl_easy *data)
   CONNCACHE_UNLOCK(data);
 
   if(elapsed >= 1000L) {
-    struct prunedead prune;
-    prune.data = data;
-    prune.extracted = NULL;
-    while(Curl_conncache_foreach(data, data->state.conn_cache, &prune,
-                                 call_extract_if_dead)) {
+    struct connectdata *pruned = NULL;
+    while(Curl_conncache_foreach(data, data->state.conn_cache, &pruned,
+                                 call_prune_if_dead)) {
       /* unlocked */
 
-      /* remove connection from cache */
-      Curl_conncache_remove_conn(data, prune.extracted, TRUE);
+      /* connection previously removed from cache in prune_if_dead() */
 
       /* disconnect it */
-      Curl_disconnect(data, prune.extracted, TRUE);
+      Curl_disconnect(data, pruned, TRUE);
     }
     CONNCACHE_LOCK(data);
     data->state.conn_cache->last_cleanup = now;
@@ -1059,20 +918,19 @@ ConnectionExists(struct Curl_easy *data,
                  bool *force_reuse,
                  bool *waitpipe)
 {
-  struct connectdata *check;
-  struct connectdata *chosen = 0;
+  struct connectdata *chosen = NULL;
   bool foundPendingCandidate = FALSE;
-  bool canmultiplex = IsMultiplexingPossible(data, needle);
+  bool canmultiplex = FALSE;
   struct connectbundle *bundle;
+  struct Curl_llist_element *curr;
 
 #ifdef USE_NTLM
-  bool wantNTLMhttp = ((data->state.authhost.want &
-                        (CURLAUTH_NTLM | CURLAUTH_NTLM_WB)) &&
+  bool wantNTLMhttp = ((data->state.authhost.want & CURLAUTH_NTLM) &&
                        (needle->handler->protocol & PROTO_FAMILY_HTTP));
 #ifndef CURL_DISABLE_PROXY
   bool wantProxyNTLMhttp = (needle->bits.proxy_user_passwd &&
                             ((data->state.authproxy.want &
-                              (CURLAUTH_NTLM | CURLAUTH_NTLM_WB)) &&
+                              CURLAUTH_NTLM) &&
                              (needle->handler->protocol & PROTO_FAMILY_HTTP)));
 #else
   bool wantProxyNTLMhttp = FALSE;
@@ -1082,395 +940,368 @@ ConnectionExists(struct Curl_easy *data,
   bool h2upgrade = (data->state.httpwant == CURL_HTTP_VERSION_2_0) &&
     (needle->handler->protocol & CURLPROTO_HTTP);
 
+  *usethis = NULL;
   *force_reuse = FALSE;
   *waitpipe = FALSE;
 
   /* Look up the bundle with all the connections to this particular host.
      Locks the connection cache, beware of early returns! */
   bundle = Curl_conncache_find_bundle(data, needle, data->state.conn_cache);
-  if(bundle) {
-    /* Max pipe length is zero (unlimited) for multiplexed connections */
-    struct Curl_llist_element *curr;
-
-    infof(data, "Found bundle for host: %p [%s]",
-          (void *)bundle, (bundle->multiuse == BUNDLE_MULTIPLEX ?
-                           "can multiplex" : "serially"));
-
-    /* We can't multiplex if we don't know anything about the server */
-    if(canmultiplex) {
-      if(bundle->multiuse == BUNDLE_UNKNOWN) {
-        if(data->set.pipewait) {
-          infof(data, "Server doesn't support multiplex yet, wait");
-          *waitpipe = TRUE;
-          CONNCACHE_UNLOCK(data);
-          return FALSE; /* no reuse */
-        }
-
-        infof(data, "Server doesn't support multiplex (yet)");
-        canmultiplex = FALSE;
+  if(!bundle) {
+    CONNCACHE_UNLOCK(data);
+    return FALSE;
+  }
+  infof(data, "Found bundle for host: %p [%s]",
+        (void *)bundle, (bundle->multiuse == BUNDLE_MULTIPLEX ?
+                         "can multiplex" : "serially"));
+
+  /* We can only multiplex iff the transfer allows it AND we know
+   * that the server we want to talk to supports it as well. */
+  canmultiplex = FALSE;
+  if(IsMultiplexingPossible(data, needle)) {
+    if(bundle->multiuse == BUNDLE_UNKNOWN) {
+      if(data->set.pipewait) {
+        infof(data, "Server doesn't support multiplex yet, wait");
+        *waitpipe = TRUE;
+        CONNCACHE_UNLOCK(data);
+        return FALSE; /* no reuse */
       }
-      if((bundle->multiuse == BUNDLE_MULTIPLEX) &&
-         !Curl_multiplex_wanted(data->multi)) {
+      infof(data, "Server doesn't support multiplex (yet)");
+    }
+    else if(bundle->multiuse == BUNDLE_MULTIPLEX) {
+      if(Curl_multiplex_wanted(data->multi))
+        canmultiplex = TRUE;
+      else
         infof(data, "Could multiplex, but not asked to");
-        canmultiplex = FALSE;
-      }
-      if(bundle->multiuse == BUNDLE_NO_MULTIUSE) {
-        infof(data, "Can not multiplex, even if we wanted to");
-        canmultiplex = FALSE;
-      }
     }
+    else if(bundle->multiuse == BUNDLE_NO_MULTIUSE) {
+      infof(data, "Can not multiplex, even if we wanted to");
+    }
+  }
 
-    curr = bundle->conn_list.head;
-    while(curr) {
-      bool match = FALSE;
-      size_t multiplexed = 0;
+  curr = bundle->conn_list.head;
+  while(curr) {
+    struct connectdata *check = curr->ptr;
+    /* Get next node now. We might remove a dead `check` connection which
+     * would invalidate `curr` as well. */
+    curr = curr->next;
 
-      /*
-       * Note that if we use an HTTP proxy in normal mode (no tunneling), we
-       * check connections to that proxy and not to the actual remote server.
-       */
-      check = curr->ptr;
-      curr = curr->next;
+    /* Note that if we use an HTTP proxy in normal mode (no tunneling), we
+     * check connections to that proxy and not to the actual remote server.
+     */
+    if(check->connect_only || check->bits.close)
+      /* connect-only or to-be-closed connections will not be reused */
+      continue;
 
-      if(check->connect_only || check->bits.close)
-        /* connect-only or to-be-closed connections will not be reused */
-        continue;
+    if(data->set.ipver != CURL_IPRESOLVE_WHATEVER
+       && data->set.ipver != check->ip_version) {
+      /* skip because the connection is not via the requested IP version */
+      continue;
+    }
 
-      if(extract_if_dead(check, data)) {
-        /* disconnect it */
-        Curl_disconnect(data, check, TRUE);
+    if(!canmultiplex) {
+      if(Curl_resolver_asynch() &&
+         /* remote_ip[0] is NUL only if the resolving of the name hasn't
+            completed yet and until then we don't reuse this connection */
+         !check->primary.remote_ip[0])
         continue;
-      }
+    }
 
-      if(data->set.ipver != CURL_IPRESOLVE_WHATEVER
-         && data->set.ipver != check->ip_version) {
-        /* skip because the connection is not via the requested IP version */
+    if(CONN_INUSE(check)) {
+      if(!canmultiplex) {
+        /* transfer can't be multiplexed and check is in use */
         continue;
       }
-
-      if(bundle->multiuse == BUNDLE_MULTIPLEX)
-        multiplexed = CONN_INUSE(check);
-
-      if(!canmultiplex) {
-        if(multiplexed) {
-          /* can only happen within multi handles, and means that another easy
-             handle is using this connection */
-          continue;
-        }
-
-        if(Curl_resolver_asynch() &&
-           /* primary_ip[0] is NUL only if the resolving of the name hasn't
-              completed yet and until then we don't reuse this connection */
-           !check->primary_ip[0])
+      else {
+        /* Could multiplex, but not when check belongs to another multi */
+        struct Curl_llist_element *e = check->easyq.head;
+        struct Curl_easy *entry = e->ptr;
+        if(entry->multi != data->multi)
           continue;
       }
+    }
 
-      if(!Curl_conn_is_connected(check, FIRSTSOCKET)) {
-        foundPendingCandidate = TRUE;
-        /* Don't pick a connection that hasn't connected yet */
-        infof(data, "Connection #%" CURL_FORMAT_CURL_OFF_T
-              "isn't open enough, can't reuse", check->connection_id);
-        continue;
-      }
+    if(!Curl_conn_is_connected(check, FIRSTSOCKET)) {
+      foundPendingCandidate = TRUE;
+      /* Don't pick a connection that hasn't connected yet */
+      infof(data, "Connection #%" CURL_FORMAT_CURL_OFF_T
+            " isn't open enough, can't reuse", check->connection_id);
+      continue;
+    }
+
+    /* `check` is connected. if it is in use and does not support multiplex,
+     * we cannot use it. */
+    if(!check->bits.multiplex && CONN_INUSE(check))
+      continue;
 
 #ifdef USE_UNIX_SOCKETS
-      if(needle->unix_domain_socket) {
-        if(!check->unix_domain_socket)
-          continue;
-        if(strcmp(needle->unix_domain_socket, check->unix_domain_socket))
-          continue;
-        if(needle->bits.abstract_unix_socket !=
-           check->bits.abstract_unix_socket)
-          continue;
-      }
-      else if(check->unix_domain_socket)
+    if(needle->unix_domain_socket) {
+      if(!check->unix_domain_socket)
         continue;
-#endif
-
-      if((needle->handler->flags&PROTOPT_SSL) !=
-         (check->handler->flags&PROTOPT_SSL))
-        /* don't do mixed SSL and non-SSL connections */
-        if(get_protocol_family(check->handler) !=
-           needle->handler->protocol || !check->bits.tls_upgraded)
-          /* except protocols that have been upgraded via TLS */
-          continue;
-
-#ifndef CURL_DISABLE_PROXY
-      if(needle->bits.httpproxy != check->bits.httpproxy ||
-         needle->bits.socksproxy != check->bits.socksproxy)
+      if(strcmp(needle->unix_domain_socket, check->unix_domain_socket))
         continue;
-
-      if(needle->bits.socksproxy &&
-        !socks_proxy_info_matches(&needle->socks_proxy,
-                                  &check->socks_proxy))
+      if(needle->bits.abstract_unix_socket !=
+         check->bits.abstract_unix_socket)
         continue;
+    }
+    else if(check->unix_domain_socket)
+      continue;
 #endif
-      if(needle->bits.conn_to_host != check->bits.conn_to_host)
-        /* don't mix connections that use the "connect to host" feature and
-         * connections that don't use this feature */
-        continue;
 
-      if(needle->bits.conn_to_port != check->bits.conn_to_port)
-        /* don't mix connections that use the "connect to port" feature and
-         * connections that don't use this feature */
+    if((needle->handler->flags&PROTOPT_SSL) !=
+       (check->handler->flags&PROTOPT_SSL))
+      /* don't do mixed SSL and non-SSL connections */
+      if(get_protocol_family(check->handler) !=
+         needle->handler->protocol || !check->bits.tls_upgraded)
+        /* except protocols that have been upgraded via TLS */
         continue;
 
-#ifndef CURL_DISABLE_PROXY
-      if(needle->bits.httpproxy) {
-        if(!proxy_info_matches(&needle->http_proxy, &check->http_proxy))
-          continue;
+    if(needle->bits.conn_to_host != check->bits.conn_to_host)
+      /* don't mix connections that use the "connect to host" feature and
+       * connections that don't use this feature */
+      continue;
 
-        if(needle->bits.tunnel_proxy != check->bits.tunnel_proxy)
-          continue;
+    if(needle->bits.conn_to_port != check->bits.conn_to_port)
+      /* don't mix connections that use the "connect to port" feature and
+       * connections that don't use this feature */
+      continue;
 
-        if(IS_HTTPS_PROXY(needle->http_proxy.proxytype)) {
-          /* use https proxy */
-          if(needle->http_proxy.proxytype !=
-             check->http_proxy.proxytype)
-            continue;
-          else if(needle->handler->flags&PROTOPT_SSL) {
-            /* use double layer ssl */
-            if(!Curl_ssl_config_matches(&needle->proxy_ssl_config,
-                                        &check->proxy_ssl_config))
-              continue;
-          }
-          else if(!Curl_ssl_config_matches(&needle->ssl_config,
-                                           &check->ssl_config))
-            continue;
-        }
-      }
-#endif
+#ifndef CURL_DISABLE_PROXY
+    if(needle->bits.httpproxy != check->bits.httpproxy ||
+       needle->bits.socksproxy != check->bits.socksproxy)
+      continue;
 
-      if(h2upgrade && !check->httpversion && canmultiplex) {
-        if(data->set.pipewait) {
-          infof(data, "Server upgrade doesn't support multiplex yet, wait");
-          *waitpipe = TRUE;
-          CONNCACHE_UNLOCK(data);
-          return FALSE; /* no reuse */
-        }
-        infof(data, "Server upgrade cannot be used");
-        continue; /* can't be used atm */
-      }
+    if(needle->bits.socksproxy &&
+      !socks_proxy_info_matches(&needle->socks_proxy,
+                                &check->socks_proxy))
+      continue;
 
-      if(!canmultiplex && CONN_INUSE(check))
-        /* this request can't be multiplexed but the checked connection is
-           already in use so we skip it */
+    if(needle->bits.httpproxy) {
+      if(needle->bits.tunnel_proxy != check->bits.tunnel_proxy)
         continue;
 
-      if(CONN_INUSE(check)) {
-        /* Subject for multiplex use if 'checks' belongs to the same multi
-           handle as 'data' is. */
-        struct Curl_llist_element *e = check->easyq.head;
-        struct Curl_easy *entry = e->ptr;
-        if(entry->multi != data->multi)
-          continue;
-      }
+      if(!proxy_info_matches(&needle->http_proxy, &check->http_proxy))
+        continue;
 
-      if(needle->localdev || needle->localport) {
-        /* If we are bound to a specific local end (IP+port), we must not
-           reuse a random other one, although if we didn't ask for a
-           particular one we can reuse one that was bound.
-
-           This comparison is a bit rough and too strict. Since the input
-           parameters can be specified in numerous ways and still end up the
-           same it would take a lot of processing to make it really accurate.
-           Instead, this matching will assume that reuses of bound connections
-           will most likely also reuse the exact same binding parameters and
-           missing out a few edge cases shouldn't hurt anyone very much.
-        */
-        if((check->localport != needle->localport) ||
-           (check->localportrange != needle->localportrange) ||
-           (needle->localdev &&
-            (!check->localdev || strcmp(check->localdev, needle->localdev))))
+      if(IS_HTTPS_PROXY(needle->http_proxy.proxytype)) {
+        /* https proxies come in different types, http/1.1, h2, ... */
+        if(needle->http_proxy.proxytype != check->http_proxy.proxytype)
           continue;
-      }
-
-      if(!(needle->handler->flags & PROTOPT_CREDSPERREQUEST)) {
-        /* This protocol requires credentials per connection,
-           so verify that we're using the same name and password as well */
-        if(Curl_timestrcmp(needle->user, check->user) ||
-           Curl_timestrcmp(needle->passwd, check->passwd) ||
-           Curl_timestrcmp(needle->sasl_authzid, check->sasl_authzid) ||
-           Curl_timestrcmp(needle->oauth_bearer, check->oauth_bearer)) {
-          /* one of them was different */
+        /* match SSL config to proxy */
+        if(!Curl_ssl_conn_config_match(data, check, TRUE)) {
+          DEBUGF(infof(data,
+            "Connection #%" CURL_FORMAT_CURL_OFF_T
+            " has different SSL proxy parameters, can't reuse",
+            check->connection_id));
           continue;
         }
+        /* the SSL config to the server, which may apply here is checked
+         * further below */
       }
+    }
+#endif
 
-      /* GSS delegation differences do not actually affect every connection
-         and auth method, but this check takes precaution before efficiency */
-      if(needle->gssapi_delegation != check->gssapi_delegation)
+    if(h2upgrade && !check->httpversion && canmultiplex) {
+      if(data->set.pipewait) {
+        infof(data, "Server upgrade doesn't support multiplex yet, wait");
+        *waitpipe = TRUE;
+        CONNCACHE_UNLOCK(data);
+        return FALSE; /* no reuse */
+      }
+      infof(data, "Server upgrade cannot be used");
+      continue; /* can't be used atm */
+    }
+
+    if(needle->localdev || needle->localport) {
+      /* If we are bound to a specific local end (IP+port), we must not
+         reuse a random other one, although if we didn't ask for a
+         particular one we can reuse one that was bound.
+
+         This comparison is a bit rough and too strict. Since the input
+         parameters can be specified in numerous ways and still end up the
+         same it would take a lot of processing to make it really accurate.
+         Instead, this matching will assume that reuses of bound connections
+         will most likely also reuse the exact same binding parameters and
+         missing out a few edge cases shouldn't hurt anyone very much.
+      */
+      if((check->localport != needle->localport) ||
+         (check->localportrange != needle->localportrange) ||
+         (needle->localdev &&
+          (!check->localdev || strcmp(check->localdev, needle->localdev))))
         continue;
+    }
 
-      /* If multiplexing isn't enabled on the h2 connection and h1 is
-         explicitly requested, handle it: */
-      if((needle->handler->protocol & PROTO_FAMILY_HTTP) &&
-         (((check->httpversion >= 20) &&
-           (data->state.httpwant < CURL_HTTP_VERSION_2_0))
-          || ((check->httpversion >= 30) &&
-              (data->state.httpwant < CURL_HTTP_VERSION_3))))
+    if(!(needle->handler->flags & PROTOPT_CREDSPERREQUEST)) {
+      /* This protocol requires credentials per connection,
+         so verify that we're using the same name and password as well */
+      if(Curl_timestrcmp(needle->user, check->user) ||
+         Curl_timestrcmp(needle->passwd, check->passwd) ||
+         Curl_timestrcmp(needle->sasl_authzid, check->sasl_authzid) ||
+         Curl_timestrcmp(needle->oauth_bearer, check->oauth_bearer)) {
+        /* one of them was different */
         continue;
-#ifdef USE_SSH
-      else if(get_protocol_family(needle->handler) & PROTO_FAMILY_SSH) {
-        if(!ssh_config_matches(needle, check))
-          continue;
       }
+    }
+
+    /* GSS delegation differences do not actually affect every connection
+       and auth method, but this check takes precaution before efficiency */
+    if(needle->gssapi_delegation != check->gssapi_delegation)
+      continue;
+
+    /* If looking for HTTP and the HTTP version  we want is less
+     * than the HTTP version of the check connection, continue looking */
+    if((needle->handler->protocol & PROTO_FAMILY_HTTP) &&
+       (((check->httpversion >= 20) &&
+         (data->state.httpwant < CURL_HTTP_VERSION_2_0))
+        || ((check->httpversion >= 30) &&
+            (data->state.httpwant < CURL_HTTP_VERSION_3))))
+      continue;
+#ifdef USE_SSH
+    else if(get_protocol_family(needle->handler) & PROTO_FAMILY_SSH) {
+      if(!ssh_config_matches(needle, check))
+        continue;
+    }
 #endif
 #ifndef CURL_DISABLE_FTP
-      else if(get_protocol_family(needle->handler) & PROTO_FAMILY_FTP) {
-        /* Also match ACCOUNT, ALTERNATIVE-TO-USER, USE_SSL and CCC options */
-        if(Curl_timestrcmp(needle->proto.ftpc.account,
-                           check->proto.ftpc.account) ||
-           Curl_timestrcmp(needle->proto.ftpc.alternative_to_user,
-                           check->proto.ftpc.alternative_to_user) ||
-           (needle->proto.ftpc.use_ssl != check->proto.ftpc.use_ssl) ||
-           (needle->proto.ftpc.ccc != check->proto.ftpc.ccc))
-          continue;
-      }
+    else if(get_protocol_family(needle->handler) & PROTO_FAMILY_FTP) {
+      /* Also match ACCOUNT, ALTERNATIVE-TO-USER, USE_SSL and CCC options */
+      if(Curl_timestrcmp(needle->proto.ftpc.account,
+                         check->proto.ftpc.account) ||
+         Curl_timestrcmp(needle->proto.ftpc.alternative_to_user,
+                         check->proto.ftpc.alternative_to_user) ||
+         (needle->proto.ftpc.use_ssl != check->proto.ftpc.use_ssl) ||
+         (needle->proto.ftpc.ccc != check->proto.ftpc.ccc))
+        continue;
+    }
 #endif
 
-      if((needle->handler->flags&PROTOPT_SSL)
+    /* Additional match requirements if talking TLS OR
+     * not talking to a HTTP proxy OR using a tunnel through a proxy */
+    if((needle->handler->flags&PROTOPT_SSL)
 #ifndef CURL_DISABLE_PROXY
-         || !needle->bits.httpproxy || needle->bits.tunnel_proxy
-#endif
-        ) {
-        /* The requested connection does not use an HTTP proxy or it uses SSL
-           or it is a non-SSL protocol tunneled or it is a non-SSL protocol
-           which is allowed to be upgraded via TLS */
-
-        if((strcasecompare(needle->handler->scheme, check->handler->scheme) ||
-            (get_protocol_family(check->handler) ==
-             needle->handler->protocol && check->bits.tls_upgraded)) &&
-           (!needle->bits.conn_to_host || strcasecompare(
-            needle->conn_to_host.name, check->conn_to_host.name)) &&
-           (!needle->bits.conn_to_port ||
-             needle->conn_to_port == check->conn_to_port) &&
-           strcasecompare(needle->host.name, check->host.name) &&
-           needle->remote_port == check->remote_port) {
-          /* The schemes match or the protocol family is the same and the
-             previous connection was TLS upgraded, and the hostname and host
-             port match */
-          if(needle->handler->flags & PROTOPT_SSL) {
-            /* This is a SSL connection so verify that we're using the same
-               SSL options as well */
-            if(!Curl_ssl_config_matches(&needle->ssl_config,
-                                        &check->ssl_config)) {
-              DEBUGF(infof(data,
-                           "Connection #%" CURL_FORMAT_CURL_OFF_T
-                           " has different SSL parameters, can't reuse",
-                           check->connection_id));
-              continue;
-            }
-          }
-          match = TRUE;
-        }
-      }
-      else {
-        /* The requested connection is using the same HTTP proxy in normal
-           mode (no tunneling) */
-        match = TRUE;
+       || !needle->bits.httpproxy || needle->bits.tunnel_proxy
+#endif
+      ) {
+      /* Talking the same protocol scheme or a TLS upgraded protocol in the
+       * same protocol family? */
+      if(!strcasecompare(needle->handler->scheme, check->handler->scheme) &&
+         (get_protocol_family(check->handler) !=
+          needle->handler->protocol || !check->bits.tls_upgraded))
+        continue;
+
+      /* If needle has "conn_to_*" set, check must match this */
+      if((needle->bits.conn_to_host && !strcasecompare(
+          needle->conn_to_host.name, check->conn_to_host.name)) ||
+         (needle->bits.conn_to_port &&
+           needle->conn_to_port != check->conn_to_port))
+        continue;
+
+      /* hostname and port must match */
+      if(!strcasecompare(needle->host.name, check->host.name) ||
+         needle->remote_port != check->remote_port)
+        continue;
+
+      /* If talking TLS, check needs to use the same SSL options. */
+      if((needle->handler->flags & PROTOPT_SSL) &&
+         !Curl_ssl_conn_config_match(data, check, FALSE)) {
+        DEBUGF(infof(data,
+                     "Connection #%" CURL_FORMAT_CURL_OFF_T
+                     " has different SSL parameters, can't reuse",
+                     check->connection_id));
+        continue;
       }
+    }
 
-      if(match) {
 #if defined(USE_NTLM)
-        /* If we are looking for an HTTP+NTLM connection, check if this is
-           already authenticating with the right credentials. If not, keep
-           looking so that we can reuse NTLM connections if
-           possible. (Especially we must not reuse the same connection if
-           partway through a handshake!) */
-        if(wantNTLMhttp) {
-          if(Curl_timestrcmp(needle->user, check->user) ||
-             Curl_timestrcmp(needle->passwd, check->passwd)) {
-
-            /* we prefer a credential match, but this is at least a connection
-               that can be reused and "upgraded" to NTLM */
-            if(check->http_ntlm_state == NTLMSTATE_NONE)
-              chosen = check;
-            continue;
-          }
-        }
-        else if(check->http_ntlm_state != NTLMSTATE_NONE) {
-          /* Connection is using NTLM auth but we don't want NTLM */
-          continue;
-        }
-
-#ifndef CURL_DISABLE_PROXY
-        /* Same for Proxy NTLM authentication */
-        if(wantProxyNTLMhttp) {
-          /* Both check->http_proxy.user and check->http_proxy.passwd can be
-           * NULL */
-          if(!check->http_proxy.user || !check->http_proxy.passwd)
-            continue;
-
-          if(Curl_timestrcmp(needle->http_proxy.user,
-                             check->http_proxy.user) ||
-             Curl_timestrcmp(needle->http_proxy.passwd,
-                             check->http_proxy.passwd))
-            continue;
-        }
-        else if(check->proxy_ntlm_state != NTLMSTATE_NONE) {
-          /* Proxy connection is using NTLM auth but we don't want NTLM */
-          continue;
-        }
-#endif
-        if(wantNTLMhttp || wantProxyNTLMhttp) {
-          /* Credentials are already checked, we can use this connection */
+    /* If we are looking for an HTTP+NTLM connection, check if this is
+       already authenticating with the right credentials. If not, keep
+       looking so that we can reuse NTLM connections if
+       possible. (Especially we must not reuse the same connection if
+       partway through a handshake!) */
+    if(wantNTLMhttp) {
+      if(Curl_timestrcmp(needle->user, check->user) ||
+         Curl_timestrcmp(needle->passwd, check->passwd)) {
+
+        /* we prefer a credential match, but this is at least a connection
+           that can be reused and "upgraded" to NTLM */
+        if(check->http_ntlm_state == NTLMSTATE_NONE)
           chosen = check;
+        continue;
+      }
+    }
+    else if(check->http_ntlm_state != NTLMSTATE_NONE) {
+      /* Connection is using NTLM auth but we don't want NTLM */
+      continue;
+    }
 
-          if((wantNTLMhttp &&
-             (check->http_ntlm_state != NTLMSTATE_NONE)) ||
-              (wantProxyNTLMhttp &&
-               (check->proxy_ntlm_state != NTLMSTATE_NONE))) {
-            /* We must use this connection, no other */
-            *force_reuse = TRUE;
-            break;
-          }
+#ifndef CURL_DISABLE_PROXY
+    /* Same for Proxy NTLM authentication */
+    if(wantProxyNTLMhttp) {
+      /* Both check->http_proxy.user and check->http_proxy.passwd can be
+       * NULL */
+      if(!check->http_proxy.user || !check->http_proxy.passwd)
+        continue;
 
-          /* Continue look up for a better connection */
-          continue;
-        }
+      if(Curl_timestrcmp(needle->http_proxy.user,
+                         check->http_proxy.user) ||
+         Curl_timestrcmp(needle->http_proxy.passwd,
+                         check->http_proxy.passwd))
+        continue;
+    }
+    else if(check->proxy_ntlm_state != NTLMSTATE_NONE) {
+      /* Proxy connection is using NTLM auth but we don't want NTLM */
+      continue;
+    }
+#endif
+    if(wantNTLMhttp || wantProxyNTLMhttp) {
+      /* Credentials are already checked, we may use this connection.
+       * With NTLM being weird as it is, we MUST use a
+       * connection where it has already been fully negotiated.
+       * If it has not, we keep on looking for a better one. */
+      chosen = check;
+
+      if((wantNTLMhttp &&
+         (check->http_ntlm_state != NTLMSTATE_NONE)) ||
+          (wantProxyNTLMhttp &&
+           (check->proxy_ntlm_state != NTLMSTATE_NONE))) {
+        /* We must use this connection, no other */
+        *force_reuse = TRUE;
+        break;
+      }
+      /* Continue look up for a better connection */
+      continue;
+    }
 #endif
-        if(canmultiplex) {
-          /* We can multiplex if we want to. Let's continue looking for
-             the optimal connection to use. */
-
-          if(!multiplexed) {
-            /* We have the optimal connection. Let's stop looking. */
-            chosen = check;
-            break;
-          }
 
-#ifdef USE_NGHTTP2
-          /* If multiplexed, make sure we don't go over concurrency limit */
-          if(check->bits.multiplex) {
-            if(multiplexed >= Curl_conn_get_max_concurrent(data, check,
-                                                           FIRSTSOCKET)) {
-              infof(data, "MAX_CONCURRENT_STREAMS reached, skip (%zu)",
-                    multiplexed);
-              continue;
-            }
-            else if(multiplexed >=
-                    Curl_multi_max_concurrent_streams(data->multi)) {
-              infof(data, "client side MAX_CONCURRENT_STREAMS reached"
-                    ", skip (%zu)",
-                    multiplexed);
-              continue;
-            }
-          }
-#endif
-          /* When not multiplexed, we have a match here! */
-          chosen = check;
-          infof(data, "Multiplexed connection found");
-          break;
-        }
-        else {
-          /* We have found a connection. Let's stop searching. */
-          chosen = check;
-          break;
-        }
+    if(CONN_INUSE(check)) {
+      DEBUGASSERT(canmultiplex);
+      DEBUGASSERT(check->bits.multiplex);
+      /* If multiplexed, make sure we don't go over concurrency limit */
+      if(CONN_INUSE(check) >=
+              Curl_multi_max_concurrent_streams(data->multi)) {
+        infof(data, "client side MAX_CONCURRENT_STREAMS reached"
+              ", skip (%zu)", CONN_INUSE(check));
+        continue;
+      }
+      if(CONN_INUSE(check) >=
+              Curl_conn_get_max_concurrent(data, check, FIRSTSOCKET)) {
+        infof(data, "MAX_CONCURRENT_STREAMS reached, skip (%zu)",
+              CONN_INUSE(check));
+        continue;
       }
+      /* When not multiplexed, we have a match here! */
+      infof(data, "Multiplexed connection found");
     }
-  }
+    else if(prune_if_dead(check, data)) {
+      /* disconnect it */
+      Curl_disconnect(data, check, TRUE);
+      continue;
+    }
+
+    /* We have found a connection. Let's stop searching. */
+    chosen = check;
+    break;
+  } /* loop over connection bundle */
 
   if(chosen) {
     /* mark it as used before releasing the lock */
@@ -1495,11 +1326,15 @@ ConnectionExists(struct Curl_easy *data,
  */
 #ifndef CURL_DISABLE_VERBOSE_STRINGS
 void Curl_verboseconnect(struct Curl_easy *data,
-                         struct connectdata *conn)
+                         struct connectdata *conn, int sockindex)
 {
-  if(data->set.verbose)
+  if(data->set.verbose && sockindex == SECONDARYSOCKET)
+    infof(data, "Connected 2nd connection to %s port %u",
+          conn->secondary.remote_ip, conn->secondary.remote_port);
+  else
     infof(data, "Connected to %s (%s) port %u",
-          CURL_CONN_HOST_DISPNAME(conn), conn->primary_ip, conn->port);
+          CURL_CONN_HOST_DISPNAME(conn), conn->primary.remote_ip,
+          conn->primary.remote_port);
 }
 #endif
 
@@ -1516,8 +1351,10 @@ static struct connectdata *allocate_conn(struct Curl_easy *data)
 
   conn->sock[FIRSTSOCKET] = CURL_SOCKET_BAD;     /* no file descriptor */
   conn->sock[SECONDARYSOCKET] = CURL_SOCKET_BAD; /* no file descriptor */
+  conn->sockfd = CURL_SOCKET_BAD;
+  conn->writesockfd = CURL_SOCKET_BAD;
   conn->connection_id = -1;    /* no ID */
-  conn->port = -1; /* unknown at this point */
+  conn->primary.remote_port = -1; /* unknown at this point */
   conn->remote_port = -1; /* unknown at this point */
 
   /* Default protocol-independent behavior doesn't support persistent
@@ -1560,28 +1397,11 @@ static struct connectdata *allocate_conn(struct Curl_easy *data)
 #ifndef CURL_DISABLE_FTP
   conn->bits.ftp_use_epsv = data->set.ftp_use_epsv;
   conn->bits.ftp_use_eprt = data->set.ftp_use_eprt;
-#endif
-  conn->ssl_config.verifystatus = data->set.ssl.primary.verifystatus;
-  conn->ssl_config.verifypeer = data->set.ssl.primary.verifypeer;
-  conn->ssl_config.verifyhost = data->set.ssl.primary.verifyhost;
-  conn->ssl_config.ssl_options = data->set.ssl.primary.ssl_options;
-#ifndef CURL_DISABLE_PROXY
-  conn->proxy_ssl_config.verifystatus =
-    data->set.proxy_ssl.primary.verifystatus;
-  conn->proxy_ssl_config.verifypeer = data->set.proxy_ssl.primary.verifypeer;
-  conn->proxy_ssl_config.verifyhost = data->set.proxy_ssl.primary.verifyhost;
-  conn->proxy_ssl_config.ssl_options = data->set.proxy_ssl.primary.ssl_options;
 #endif
   conn->ip_version = data->set.ipver;
   conn->connect_only = data->set.connect_only;
   conn->transport = TRNSPRT_TCP; /* most of them are TCP streams */
 
-#if !defined(CURL_DISABLE_HTTP) && defined(USE_NTLM) && \
-    defined(NTLM_WB_ENABLED)
-  conn->ntlm.ntlm_auth_hlpr_socket = CURL_SOCKET_BAD;
-  conn->proxyntlm.ntlm_auth_hlpr_socket = CURL_SOCKET_BAD;
-#endif
-
   /* Initialize the easy handle list */
   Curl_llist_init(&conn->easyq, NULL);
 
@@ -1615,30 +1435,231 @@ static struct connectdata *allocate_conn(struct Curl_easy *data)
   return NULL;
 }
 
-/* returns the handler if the given scheme is built-in */
-const struct Curl_handler *Curl_builtin_scheme(const char *scheme,
-                                               size_t schemelen)
+const struct Curl_handler *Curl_get_scheme_handler(const char *scheme)
 {
-  const struct Curl_handler * const *pp;
-  const struct Curl_handler *p;
-  /* Scan protocol handler table and match against 'scheme'. The handler may
-     be changed later when the protocol specific setup function is called. */
-  if(schemelen == CURL_ZERO_TERMINATED)
-    schemelen = strlen(scheme);
-  for(pp = protocols; (p = *pp) != NULL; pp++)
-    if(strncasecompare(p->scheme, scheme, schemelen) && !p->scheme[schemelen])
-      /* Protocol found in table. */
-      return p;
-  return NULL; /* not found */
+  return Curl_getn_scheme_handler(scheme, strlen(scheme));
 }
 
+/* returns the handler if the given scheme is built-in */
+const struct Curl_handler *Curl_getn_scheme_handler(const char *scheme,
+                                                    size_t len)
+{
+  /* table generated by schemetable.c:
+     1. gcc schemetable.c && ./a.out
+     2. check how small the table gets
+     3. tweak the hash algorithm, then rerun from 1
+     4. when the table is good enough
+     5. copy the table into this source code
+     6. make sure this function uses the same hash function that worked for
+     schemetable.c
+     7. if needed, adjust the #ifdefs in schemetable.c and rerun
+     */
+  static const struct Curl_handler * const protocols[67] = {
+#ifndef CURL_DISABLE_FILE
+    &Curl_handler_file,
+#else
+    NULL,
+#endif
+    NULL, NULL,
+#if defined(USE_SSL) && !defined(CURL_DISABLE_GOPHER)
+    &Curl_handler_gophers,
+#else
+    NULL,
+#endif
+    NULL,
+#ifdef USE_LIBRTMP
+    &Curl_handler_rtmpe,
+#else
+    NULL,
+#endif
+#ifndef CURL_DISABLE_SMTP
+    &Curl_handler_smtp,
+#else
+    NULL,
+#endif
+#if defined(USE_SSH)
+    &Curl_handler_sftp,
+#else
+    NULL,
+#endif
+#if !defined(CURL_DISABLE_SMB) && defined(USE_CURL_NTLM_CORE) && \
+  (SIZEOF_CURL_OFF_T > 4)
+    &Curl_handler_smb,
+#else
+    NULL,
+#endif
+#if defined(USE_SSL) && !defined(CURL_DISABLE_SMTP)
+    &Curl_handler_smtps,
+#else
+    NULL,
+#endif
+#ifndef CURL_DISABLE_TELNET
+    &Curl_handler_telnet,
+#else
+    NULL,
+#endif
+#ifndef CURL_DISABLE_GOPHER
+    &Curl_handler_gopher,
+#else
+    NULL,
+#endif
+#ifndef CURL_DISABLE_TFTP
+    &Curl_handler_tftp,
+#else
+    NULL,
+#endif
+    NULL, NULL, NULL,
+#if defined(USE_SSL) && !defined(CURL_DISABLE_FTP)
+    &Curl_handler_ftps,
+#else
+    NULL,
+#endif
+#ifndef CURL_DISABLE_HTTP
+    &Curl_handler_http,
+#else
+    NULL,
+#endif
+#ifndef CURL_DISABLE_IMAP
+    &Curl_handler_imap,
+#else
+    NULL,
+#endif
+#ifdef USE_LIBRTMP
+    &Curl_handler_rtmps,
+#else
+    NULL,
+#endif
+#ifdef USE_LIBRTMP
+    &Curl_handler_rtmpt,
+#else
+    NULL,
+#endif
+    NULL, NULL, NULL,
+#if !defined(CURL_DISABLE_LDAP) && \
+  !defined(CURL_DISABLE_LDAPS) && \
+  ((defined(USE_OPENLDAP) && defined(USE_SSL)) || \
+   (!defined(USE_OPENLDAP) && defined(HAVE_LDAP_SSL)))
+    &Curl_handler_ldaps,
+#else
+    NULL,
+#endif
+#if defined(USE_WEBSOCKETS) && \
+  defined(USE_SSL) && !defined(CURL_DISABLE_HTTP)
+    &Curl_handler_wss,
+#else
+    NULL,
+#endif
+#if defined(USE_SSL) && !defined(CURL_DISABLE_HTTP)
+    &Curl_handler_https,
+#else
+    NULL,
+#endif
+    NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL,
+#ifndef CURL_DISABLE_RTSP
+    &Curl_handler_rtsp,
+#else
+    NULL,
+#endif
+#if defined(USE_SSL) && !defined(CURL_DISABLE_SMB) && \
+  defined(USE_CURL_NTLM_CORE) && (SIZEOF_CURL_OFF_T > 4)
+    &Curl_handler_smbs,
+#else
+    NULL,
+#endif
+#if defined(USE_SSH) && !defined(USE_WOLFSSH)
+    &Curl_handler_scp,
+#else
+    NULL,
+#endif
+    NULL, NULL, NULL,
+#ifndef CURL_DISABLE_POP3
+    &Curl_handler_pop3,
+#else
+    NULL,
+#endif
+    NULL, NULL,
+#ifdef USE_LIBRTMP
+    &Curl_handler_rtmp,
+#else
+    NULL,
+#endif
+    NULL, NULL, NULL,
+#ifdef USE_LIBRTMP
+    &Curl_handler_rtmpte,
+#else
+    NULL,
+#endif
+    NULL, NULL, NULL,
+#ifndef CURL_DISABLE_DICT
+    &Curl_handler_dict,
+#else
+    NULL,
+#endif
+    NULL, NULL, NULL,
+#ifndef CURL_DISABLE_MQTT
+    &Curl_handler_mqtt,
+#else
+    NULL,
+#endif
+#if defined(USE_SSL) && !defined(CURL_DISABLE_POP3)
+    &Curl_handler_pop3s,
+#else
+    NULL,
+#endif
+#if defined(USE_SSL) && !defined(CURL_DISABLE_IMAP)
+    &Curl_handler_imaps,
+#else
+    NULL,
+#endif
+    NULL,
+#if defined(USE_WEBSOCKETS) && !defined(CURL_DISABLE_HTTP)
+    &Curl_handler_ws,
+#else
+    NULL,
+#endif
+    NULL,
+#ifdef USE_LIBRTMP
+    &Curl_handler_rtmpts,
+#else
+    NULL,
+#endif
+#ifndef CURL_DISABLE_LDAP
+    &Curl_handler_ldap,
+#else
+    NULL,
+#endif
+    NULL, NULL,
+#ifndef CURL_DISABLE_FTP
+    &Curl_handler_ftp,
+#else
+    NULL,
+#endif
+  };
+
+  if(len && (len <= 7)) {
+    const char *s = scheme;
+    size_t l = len;
+    const struct Curl_handler *h;
+    unsigned int c = 978;
+    while(l) {
+      c <<= 5;
+      c += Curl_raw_tolower(*s);
+      s++;
+      l--;
+    }
+
+    h = protocols[c % 67];
+    if(h && strncasecompare(scheme, h->scheme, len) && !h->scheme[len])
+      return h;
+  }
+  return NULL;
+}
 
 static CURLcode findprotocol(struct Curl_easy *data,
                              struct connectdata *conn,
                              const char *protostr)
 {
-  const struct Curl_handler *p = Curl_builtin_scheme(protostr,
-                                                     CURL_ZERO_TERMINATED);
+  const struct Curl_handler *p = Curl_get_scheme_handler(protostr);
 
   if(p && /* Protocol found in table. Check if allowed */
      (data->set.allowed_protocols & p->protocol)) {
@@ -1652,7 +1673,6 @@ static CURLcode findprotocol(struct Curl_easy *data,
     else {
       /* Perform setup complement if some. */
       conn->handler = conn->given = p;
-
       /* 'port' and 'remote_port' are set in setup_connection_internals() */
       return CURLE_OK;
     }
@@ -1661,8 +1681,9 @@ static CURLcode findprotocol(struct Curl_easy *data,
   /* The protocol was not found in the table, but we don't have to assign it
      to anything since it is already assigned to a dummy-struct in the
      create_conn() function when the connectdata struct is allocated. */
-  failf(data, "Protocol \"%s\" not supported or disabled in " LIBCURL_NAME,
-        protostr);
+  failf(data, "Protocol \"%s\" %s%s", protostr,
+        p ? "disabled" : "not supported",
+        data->state.this_is_a_follow ? " (in redirect)":"");
 
   return CURLE_UNSUPPORTED_PROTOCOL;
 }
@@ -1682,7 +1703,7 @@ CURLcode Curl_uc_to_curlcode(CURLUcode uc)
   }
 }
 
-#ifdef ENABLE_IPV6
+#ifdef USE_IPV6
 /*
  * If the URL was set with an IPv6 numerical address with a zone id part, set
  * the scope_id based on that!
@@ -1705,14 +1726,14 @@ static void zonefrom_url(CURLU *uh, struct Curl_easy *data,
       conn->scope_id = (unsigned int)scope;
 #if defined(HAVE_IF_NAMETOINDEX)
     else {
-#elif defined(WIN32)
+#elif defined(_WIN32)
     else if(Curl_if_nametoindex) {
 #endif
 
-#if defined(HAVE_IF_NAMETOINDEX) || defined(WIN32)
+#if defined(HAVE_IF_NAMETOINDEX) || defined(_WIN32)
       /* Zone identifier is not numeric */
       unsigned int scopeidx = 0;
-#if defined(WIN32)
+#if defined(_WIN32)
       scopeidx = Curl_if_nametoindex(zoneid);
 #else
       scopeidx = if_nametoindex(zoneid);
@@ -1727,7 +1748,7 @@ static void zonefrom_url(CURLU *uh, struct Curl_easy *data,
       else
         conn->scope_id = scopeidx;
     }
-#endif /* HAVE_IF_NAMETOINDEX || WIN32 */
+#endif /* HAVE_IF_NAMETOINDEX || _WIN32 */
 
     free(zoneid);
   }
@@ -1940,14 +1961,14 @@ static CURLcode parseurlandfillconn(struct Curl_easy *data,
   }
   else {
     unsigned long port = strtoul(data->state.up.port, NULL, 10);
-    conn->port = conn->remote_port =
+    conn->primary.remote_port = conn->remote_port =
       (data->set.use_port && data->state.allow_port) ?
       data->set.use_port : curlx_ultous(port);
   }
 
   (void)curl_url_get(uh, CURLUPART_QUERY, &data->state.up.query, 0);
 
-#ifdef ENABLE_IPV6
+#ifdef USE_IPV6
   if(data->set.scope_id)
     /* Override any scope that was set above.  */
     conn->scope_id = data->set.scope_id;
@@ -2016,32 +2037,14 @@ static CURLcode setup_connection_internals(struct Curl_easy *data,
     p = conn->handler;              /* May have changed. */
   }
 
-  if(conn->port < 0)
+  if(conn->primary.remote_port < 0)
     /* we check for -1 here since if proxy was detected already, this
        was very likely already set to the proxy port */
-    conn->port = p->defport;
+    conn->primary.remote_port = p->defport;
 
   return CURLE_OK;
 }
 
-/*
- * Curl_free_request_state() should free temp data that was allocated in the
- * Curl_easy for this single request.
- */
-
-void Curl_free_request_state(struct Curl_easy *data)
-{
-  Curl_safefree(data->req.p.http);
-  Curl_safefree(data->req.newurl);
-
-#ifndef CURL_DISABLE_DOH
-  if(data->req.doh) {
-    Curl_close(&data->req.doh->probe[0].easy);
-    Curl_close(&data->req.doh->probe[1].easy);
-  }
-#endif
-}
-
 
 #ifndef CURL_DISABLE_PROXY
 
@@ -2073,23 +2076,16 @@ static char *detect_proxy(struct Curl_easy *data,
    * For compatibility, the all-uppercase versions of these variables are
    * checked if the lowercase versions don't exist.
    */
-  char proxy_env[128];
-  const char *protop = conn->handler->scheme;
+  char proxy_env[20];
   char *envp = proxy_env;
-  char *prox;
 #ifdef CURL_DISABLE_VERBOSE_STRINGS
   (void)data;
 #endif
 
-  /* Now, build _proxy and check for such a one to use */
-  while(*protop)
-    *envp++ = Curl_raw_tolower(*protop++);
-
-  /* append _proxy */
-  strcpy(envp, "_proxy");
+  msnprintf(proxy_env, sizeof(proxy_env), "%s_proxy", conn->handler->scheme);
 
   /* read the protocol proxy: */
-  prox = curl_getenv(proxy_env);
+  proxy = curl_getenv(proxy_env);
 
   /*
    * We don't try the uppercase version of HTTP_PROXY because of
@@ -2103,23 +2099,34 @@ static char *detect_proxy(struct Curl_easy *data,
    * This can cause 'internal' http/ftp requests to be
    * arbitrarily redirected by any external attacker.
    */
-  if(!prox && !strcasecompare("http_proxy", proxy_env)) {
+  if(!proxy && !strcasecompare("http_proxy", proxy_env)) {
     /* There was no lowercase variable, try the uppercase version: */
     Curl_strntoupper(proxy_env, proxy_env, sizeof(proxy_env));
-    prox = curl_getenv(proxy_env);
+    proxy = curl_getenv(proxy_env);
   }
 
-  envp = proxy_env;
-  if(prox) {
-    proxy = prox; /* use this */
-  }
-  else {
-    envp = (char *)"all_proxy";
-    proxy = curl_getenv(envp); /* default proxy to use */
+  if(!proxy) {
+#ifdef USE_WEBSOCKETS
+    /* websocket proxy fallbacks */
+    if(strcasecompare("ws_proxy", proxy_env)) {
+      proxy = curl_getenv("http_proxy");
+    }
+    else if(strcasecompare("wss_proxy", proxy_env)) {
+      proxy = curl_getenv("https_proxy");
+      if(!proxy)
+        proxy = curl_getenv("HTTPS_PROXY");
+    }
     if(!proxy) {
-      envp = (char *)"ALL_PROXY";
-      proxy = curl_getenv(envp);
+#endif
+      envp = (char *)"all_proxy";
+      proxy = curl_getenv(envp); /* default proxy to use */
+      if(!proxy) {
+        envp = (char *)"ALL_PROXY";
+        proxy = curl_getenv(envp);
+      }
+#ifdef USE_WEBSOCKETS
     }
+#endif
   }
   if(proxy)
     infof(data, "Uses proxy env variable %s == '%s'", envp, proxy);
@@ -2272,8 +2279,9 @@ static CURLcode parse_proxy(struct Curl_easy *data,
   }
   if(port >= 0) {
     proxyinfo->port = port;
-    if(conn->port < 0 || sockstype || !conn->socks_proxy.host.rawalloc)
-      conn->port = port;
+    if(conn->primary.remote_port < 0 || sockstype ||
+       !conn->socks_proxy.host.rawalloc)
+      conn->primary.remote_port = port;
   }
 
   /* now, clone the proxy host name */
@@ -2344,17 +2352,16 @@ static CURLcode parse_proxy_auth(struct Curl_easy *data,
     data->state.aptr.proxyuser : "";
   const char *proxypasswd = data->state.aptr.proxypasswd ?
     data->state.aptr.proxypasswd : "";
-  CURLcode result = Curl_urldecode(proxyuser, 0, &conn->http_proxy.user, NULL,
-                                   REJECT_ZERO);
-  if(!result)
-    result = Curl_setstropt(&data->state.aptr.proxyuser,
-                            conn->http_proxy.user);
-  if(!result)
-    result = Curl_urldecode(proxypasswd, 0, &conn->http_proxy.passwd,
-                            NULL, REJECT_ZERO);
-  if(!result)
-    result = Curl_setstropt(&data->state.aptr.proxypasswd,
-                            conn->http_proxy.passwd);
+  CURLcode result = CURLE_OUT_OF_MEMORY;
+
+  conn->http_proxy.user = strdup(proxyuser);
+  if(conn->http_proxy.user) {
+    conn->http_proxy.passwd = strdup(proxypasswd);
+    if(conn->http_proxy.passwd)
+      result = CURLE_OK;
+    else
+      Curl_safefree(conn->http_proxy.user);
+  }
   return result;
 }
 
@@ -2554,14 +2561,15 @@ static CURLcode create_conn_helper_init_proxy(struct Curl_easy *data,
  *
  * Parameters:
  *
- * login    [in]     - The login string.
- * len      [in]     - The length of the login string.
- * userp    [in/out] - The address where a pointer to newly allocated memory
+ * login    [in]     - login string.
+ * len      [in]     - length of the login string.
+ * userp    [in/out] - address where a pointer to newly allocated memory
  *                     holding the user will be stored upon completion.
- * passwdp  [in/out] - The address where a pointer to newly allocated memory
+ * passwdp  [in/out] - address where a pointer to newly allocated memory
  *                     holding the password will be stored upon completion.
- * optionsp [in/out] - The address where a pointer to newly allocated memory
- *                     holding the options will be stored upon completion.
+ * optionsp [in/out] - OPTIONAL address where a pointer to newly allocated
+ *                     memory holding the options will be stored upon
+ *                     completion.
  *
  * Returns CURLE_OK on success.
  */
@@ -2569,19 +2577,19 @@ CURLcode Curl_parse_login_details(const char *login, const size_t len,
                                   char **userp, char **passwdp,
                                   char **optionsp)
 {
-  CURLcode result = CURLE_OK;
   char *ubuf = NULL;
   char *pbuf = NULL;
-  char *obuf = NULL;
   const char *psep = NULL;
   const char *osep = NULL;
   size_t ulen;
   size_t plen;
   size_t olen;
 
+  DEBUGASSERT(userp);
+  DEBUGASSERT(passwdp);
+
   /* Attempt to find the password separator */
-  if(passwdp)
-    psep = memchr(login, ':', len);
+  psep = memchr(login, ':', len);
 
   /* Attempt to find the options separator */
   if(optionsp)
@@ -2593,64 +2601,40 @@ CURLcode Curl_parse_login_details(const char *login, const size_t len,
           (osep ? (size_t)(osep - login) : len));
   plen = (psep ?
           (osep && osep > psep ? (size_t)(osep - psep) :
-                                 (size_t)(login + len - psep)) - 1 : 0);
+           (size_t)(login + len - psep)) - 1 : 0);
   olen = (osep ?
           (psep && psep > osep ? (size_t)(psep - osep) :
-                                 (size_t)(login + len - osep)) - 1 : 0);
+           (size_t)(login + len - osep)) - 1 : 0);
 
-  /* Allocate the user portion buffer, which can be zero length */
-  if(userp) {
-    ubuf = malloc(ulen + 1);
-    if(!ubuf)
-      result = CURLE_OUT_OF_MEMORY;
-  }
+  /* Clone the user portion buffer, which can be zero length */
+  ubuf = Curl_memdup0(login, ulen);
+  if(!ubuf)
+    goto error;
 
-  /* Allocate the password portion buffer */
-  if(!result && passwdp && psep) {
-    pbuf = malloc(plen + 1);
-    if(!pbuf) {
-      free(ubuf);
-      result = CURLE_OUT_OF_MEMORY;
-    }
+  /* Clone the password portion buffer */
+  if(psep) {
+    pbuf = Curl_memdup0(&psep[1], plen);
+    if(!pbuf)
+      goto error;
   }
 
   /* Allocate the options portion buffer */
-  if(!result && optionsp && olen) {
-    obuf = malloc(olen + 1);
-    if(!obuf) {
-      free(pbuf);
-      free(ubuf);
-      result = CURLE_OUT_OF_MEMORY;
-    }
-  }
-
-  if(!result) {
-    /* Store the user portion if necessary */
-    if(ubuf) {
-      memcpy(ubuf, login, ulen);
-      ubuf[ulen] = '\0';
-      Curl_safefree(*userp);
-      *userp = ubuf;
-    }
-
-    /* Store the password portion if necessary */
-    if(pbuf) {
-      memcpy(pbuf, psep + 1, plen);
-      pbuf[plen] = '\0';
-      Curl_safefree(*passwdp);
-      *passwdp = pbuf;
-    }
-
-    /* Store the options portion if necessary */
-    if(obuf) {
-      memcpy(obuf, osep + 1, olen);
-      obuf[olen] = '\0';
-      Curl_safefree(*optionsp);
-      *optionsp = obuf;
+  if(optionsp) {
+    char *obuf = NULL;
+    if(olen) {
+      obuf = Curl_memdup0(&osep[1], olen);
+      if(!obuf)
+        goto error;
     }
+    *optionsp = obuf;
   }
-
-  return result;
+  *userp = ubuf;
+  *passwdp = pbuf;
+  return CURLE_OK;
+error:
+  free(ubuf);
+  free(pbuf);
+  return CURLE_OUT_OF_MEMORY;
 }
 
 /*************************************************************
@@ -2719,7 +2703,9 @@ static CURLcode override_login(struct Curl_easy *data,
                           data->set.str[STRING_NETRC_FILE]);
     if(ret > 0) {
       infof(data, "Couldn't find host %s in the %s file; using defaults",
-            conn->host.name, data->set.str[STRING_NETRC_FILE]);
+            conn->host.name,
+            (data->set.str[STRING_NETRC_FILE] ?
+             data->set.str[STRING_NETRC_FILE] : ".netrc"));
     }
     else if(ret < 0) {
       failf(data, ".netrc parser error");
@@ -2859,7 +2845,7 @@ static CURLcode parse_connect_to_host_port(struct Curl_easy *data,
 
   /* detect and extract RFC6874-style IPv6-addresses */
   if(*hostptr == '[') {
-#ifdef ENABLE_IPV6
+#ifdef USE_IPV6
     char *ptr = ++hostptr; /* advance beyond the initial bracket */
     while(*ptr && (ISXDIGIT(*ptr) || (*ptr == ':') || (*ptr == '.')))
       ptr++;
@@ -3057,7 +3043,7 @@ static CURLcode parse_connect_to_slist(struct Curl_easy *data,
 #ifdef USE_HTTP2
                                    | ALPN_h2
 #endif
-#ifdef ENABLE_QUIC
+#ifdef USE_HTTP3
                                    | ALPN_h3
 #endif
       ) & data->asi->flags;
@@ -3169,8 +3155,8 @@ static CURLcode resolve_proxy(struct Curl_easy *data,
   if(!conn->hostname_resolve)
     return CURLE_OUT_OF_MEMORY;
 
-  rc = Curl_resolv_timeout(data, conn->hostname_resolve, (int)conn->port,
-                           &hostaddr, timeout_ms);
+  rc = Curl_resolv_timeout(data, conn->hostname_resolve,
+                           conn->primary.remote_port, &hostaddr, timeout_ms);
   conn->dns_entry = hostaddr;
   if(rc == CURLRESOLV_PENDING)
     *async = TRUE;
@@ -3200,7 +3186,7 @@ static CURLcode resolve_host(struct Curl_easy *data,
 
   /* If not connecting via a proxy, extract the port from the URL, if it is
    * there, thus overriding any defaults that might have been set above. */
-  conn->port = conn->bits.conn_to_port ? conn->conn_to_port :
+  conn->primary.remote_port = conn->bits.conn_to_port ? conn->conn_to_port :
     conn->remote_port;
 
   /* Resolve target host right on */
@@ -3208,14 +3194,14 @@ static CURLcode resolve_host(struct Curl_easy *data,
   if(!conn->hostname_resolve)
     return CURLE_OUT_OF_MEMORY;
 
-  rc = Curl_resolv_timeout(data, conn->hostname_resolve, (int)conn->port,
-                           &hostaddr, timeout_ms);
+  rc = Curl_resolv_timeout(data, conn->hostname_resolve,
+                           conn->primary.remote_port, &hostaddr, timeout_ms);
   conn->dns_entry = hostaddr;
   if(rc == CURLRESOLV_PENDING)
     *async = TRUE;
   else if(rc == CURLRESOLV_TIMEDOUT) {
-    failf(data, "Failed to resolve host '%s' with timeout after %ld ms",
-          connhost->dispname,
+    failf(data, "Failed to resolve host '%s' with timeout after %"
+          CURL_FORMAT_TIMEDIFF_T " ms", connhost->dispname,
           Curl_timediff(Curl_now(), data->progress.t_startsingle));
     return CURLE_OPERATION_TIMEDOUT;
   }
@@ -3546,7 +3532,7 @@ static CURLcode create_conn(struct Curl_easy *data,
     /* this is supposed to be the connect function so we better at least check
        that the file is present here! */
     DEBUGASSERT(conn->handler->connect_it);
-    Curl_persistconninfo(data, conn, NULL, -1);
+    Curl_persistconninfo(data, conn, NULL);
     result = conn->handler->connect_it(data, &done);
 
     /* Setup a "faked" transfer that'll do nothing */
@@ -3566,7 +3552,7 @@ static CURLcode create_conn(struct Curl_easy *data,
         (void)conn->handler->done(data, result, FALSE);
         goto out;
       }
-      Curl_setup_transfer(data, -1, -1, FALSE, -1);
+      Curl_xfer_setup(data, -1, -1, FALSE, -1);
     }
 
     /* since we skip do_init() */
@@ -3577,91 +3563,16 @@ static CURLcode create_conn(struct Curl_easy *data,
 #endif
 
   /* Setup filter for network connections */
-  conn->recv[FIRSTSOCKET] = Curl_conn_recv;
-  conn->send[FIRSTSOCKET] = Curl_conn_send;
-  conn->recv[SECONDARYSOCKET] = Curl_conn_recv;
-  conn->send[SECONDARYSOCKET] = Curl_conn_send;
+  conn->recv[FIRSTSOCKET] = Curl_cf_recv;
+  conn->send[FIRSTSOCKET] = Curl_cf_send;
+  conn->recv[SECONDARYSOCKET] = Curl_cf_recv;
+  conn->send[SECONDARYSOCKET] = Curl_cf_send;
   conn->bits.tcp_fastopen = data->set.tcp_fastopen;
 
-  /* Get a cloned copy of the SSL config situation stored in the
-     connection struct. But to get this going nicely, we must first make
-     sure that the strings in the master copy are pointing to the correct
-     strings in the session handle strings array!
-
-     Keep in mind that the pointers in the master copy are pointing to strings
-     that will be freed as part of the Curl_easy struct, but all cloned
-     copies will be separately allocated.
-  */
-  data->set.ssl.primary.CApath = data->set.str[STRING_SSL_CAPATH];
-  data->set.ssl.primary.CAfile = data->set.str[STRING_SSL_CAFILE];
-  data->set.ssl.primary.issuercert = data->set.str[STRING_SSL_ISSUERCERT];
-  data->set.ssl.primary.issuercert_blob = data->set.blobs[BLOB_SSL_ISSUERCERT];
-  data->set.ssl.primary.cipher_list =
-    data->set.str[STRING_SSL_CIPHER_LIST];
-  data->set.ssl.primary.cipher_list13 =
-    data->set.str[STRING_SSL_CIPHER13_LIST];
-  data->set.ssl.primary.pinned_key =
-    data->set.str[STRING_SSL_PINNEDPUBLICKEY];
-  data->set.ssl.primary.cert_blob = data->set.blobs[BLOB_CERT];
-  data->set.ssl.primary.ca_info_blob = data->set.blobs[BLOB_CAINFO];
-  data->set.ssl.primary.curves = data->set.str[STRING_SSL_EC_CURVES];
-
-#ifndef CURL_DISABLE_PROXY
-  data->set.proxy_ssl.primary.CApath = data->set.str[STRING_SSL_CAPATH_PROXY];
-  data->set.proxy_ssl.primary.CAfile = data->set.str[STRING_SSL_CAFILE_PROXY];
-  data->set.proxy_ssl.primary.cipher_list =
-    data->set.str[STRING_SSL_CIPHER_LIST_PROXY];
-  data->set.proxy_ssl.primary.cipher_list13 =
-    data->set.str[STRING_SSL_CIPHER13_LIST_PROXY];
-  data->set.proxy_ssl.primary.pinned_key =
-    data->set.str[STRING_SSL_PINNEDPUBLICKEY_PROXY];
-  data->set.proxy_ssl.primary.cert_blob = data->set.blobs[BLOB_CERT_PROXY];
-  data->set.proxy_ssl.primary.ca_info_blob =
-    data->set.blobs[BLOB_CAINFO_PROXY];
-  data->set.proxy_ssl.primary.issuercert =
-    data->set.str[STRING_SSL_ISSUERCERT_PROXY];
-  data->set.proxy_ssl.primary.issuercert_blob =
-    data->set.blobs[BLOB_SSL_ISSUERCERT_PROXY];
-  data->set.proxy_ssl.primary.CRLfile =
-    data->set.str[STRING_SSL_CRLFILE_PROXY];
-  data->set.proxy_ssl.cert_type = data->set.str[STRING_CERT_TYPE_PROXY];
-  data->set.proxy_ssl.key = data->set.str[STRING_KEY_PROXY];
-  data->set.proxy_ssl.key_type = data->set.str[STRING_KEY_TYPE_PROXY];
-  data->set.proxy_ssl.key_passwd = data->set.str[STRING_KEY_PASSWD_PROXY];
-  data->set.proxy_ssl.primary.clientcert = data->set.str[STRING_CERT_PROXY];
-  data->set.proxy_ssl.key_blob = data->set.blobs[BLOB_KEY_PROXY];
-#endif
-  data->set.ssl.primary.CRLfile = data->set.str[STRING_SSL_CRLFILE];
-  data->set.ssl.cert_type = data->set.str[STRING_CERT_TYPE];
-  data->set.ssl.key = data->set.str[STRING_KEY];
-  data->set.ssl.key_type = data->set.str[STRING_KEY_TYPE];
-  data->set.ssl.key_passwd = data->set.str[STRING_KEY_PASSWD];
-  data->set.ssl.primary.clientcert = data->set.str[STRING_CERT];
-#ifdef USE_TLS_SRP
-  data->set.ssl.primary.username = data->set.str[STRING_TLSAUTH_USERNAME];
-  data->set.ssl.primary.password = data->set.str[STRING_TLSAUTH_PASSWORD];
-#ifndef CURL_DISABLE_PROXY
-  data->set.proxy_ssl.primary.username =
-    data->set.str[STRING_TLSAUTH_USERNAME_PROXY];
-  data->set.proxy_ssl.primary.password =
-    data->set.str[STRING_TLSAUTH_PASSWORD_PROXY];
-#endif
-#endif
-  data->set.ssl.key_blob = data->set.blobs[BLOB_KEY];
-
-  if(!Curl_clone_primary_ssl_config(&data->set.ssl.primary,
-                                    &conn->ssl_config)) {
-    result = CURLE_OUT_OF_MEMORY;
-    goto out;
-  }
-
-#ifndef CURL_DISABLE_PROXY
-  if(!Curl_clone_primary_ssl_config(&data->set.proxy_ssl.primary,
-                                    &conn->proxy_ssl_config)) {
-    result = CURLE_OUT_OF_MEMORY;
+  /* Complete the easy's SSL configuration for connection cache matching */
+  result = Curl_ssl_easy_config_complete(data);
+  if(result)
     goto out;
-  }
-#endif
 
   prune_dead_connections(data);
 
@@ -3776,6 +3687,12 @@ static CURLcode create_conn(struct Curl_easy *data,
        * This is a brand new connection, so let's store it in the connection
        * cache of ours!
        */
+      result = Curl_ssl_conn_config_init(data, conn);
+      if(result) {
+        DEBUGF(fprintf(stderr, "Error: init connection ssl config\n"));
+        goto out;
+      }
+
       Curl_attach_connection(data, conn);
       result = Curl_conncache_add_conn(data);
       if(result)
@@ -3786,14 +3703,14 @@ static CURLcode create_conn(struct Curl_easy *data,
     /* If NTLM is requested in a part of this connection, make sure we don't
        assume the state is fine as this is a fresh connection and NTLM is
        connection based. */
-    if((data->state.authhost.picked & (CURLAUTH_NTLM | CURLAUTH_NTLM_WB)) &&
+    if((data->state.authhost.picked & CURLAUTH_NTLM) &&
        data->state.authhost.done) {
       infof(data, "NTLM picked AND auth done set, clear picked");
       data->state.authhost.picked = CURLAUTH_NONE;
       data->state.authhost.done = FALSE;
     }
 
-    if((data->state.authproxy.picked & (CURLAUTH_NTLM | CURLAUTH_NTLM_WB)) &&
+    if((data->state.authproxy.picked & CURLAUTH_NTLM) &&
        data->state.authproxy.done) {
       infof(data, "NTLM-proxy picked AND auth done set, clear picked");
       data->state.authproxy.picked = CURLAUTH_NONE;
@@ -3814,13 +3731,6 @@ static CURLcode create_conn(struct Curl_easy *data,
 
   /* Continue connectdata initialization here. */
 
-  /*
-   * Inherit the proper values from the urldata struct AFTER we have arranged
-   * the persistent connection stuff
-   */
-  conn->seek_func = data->set.seek_func;
-  conn->seek_client = data->set.seek_client;
-
   /*************************************************************
    * Resolve the address of the server or proxy
    *************************************************************/
@@ -3874,6 +3784,9 @@ CURLcode Curl_setup_conn(struct Curl_easy *data,
   if(!conn->bits.reuse)
     result = Curl_conn_setup(data, conn, FIRSTSOCKET, conn->dns_entry,
                              CURL_CF_SSL_DEFAULT);
+  if(!result)
+    result = Curl_headers_init(data);
+
   /* not sure we need this flag to be passed around any more */
   *protocol_done = FALSE;
   return result;
@@ -3888,11 +3801,8 @@ CURLcode Curl_connect(struct Curl_easy *data,
 
   *asyncp = FALSE; /* assume synchronous resolves by default */
 
-  /* init the single-transfer specific data */
-  Curl_free_request_state(data);
-  memset(&data->req, 0, sizeof(struct SingleRequest));
-  data->req.size = data->req.maxdownload = -1;
-  data->req.no_body = data->set.opt_no_body;
+  /* Set the request to virgin state based on transfer settings */
+  Curl_req_hard_reset(&data->req, data);
 
   /* call the stuff that needs to be called */
   result = create_conn(data, &conn, asyncp);
@@ -3935,12 +3845,8 @@ CURLcode Curl_connect(struct Curl_easy *data,
 
 CURLcode Curl_init_do(struct Curl_easy *data, struct connectdata *conn)
 {
-  struct SingleRequest *k = &data->req;
-
   /* if this is a pushed stream, we need this: */
-  CURLcode result = Curl_preconnect(data);
-  if(result)
-    return result;
+  CURLcode result;
 
   if(conn) {
     conn->bits.do_more = FALSE; /* by default there's no curl_do_more() to
@@ -3952,22 +3858,18 @@ CURLcode Curl_init_do(struct Curl_easy *data, struct connectdata *conn)
   }
 
   data->state.done = FALSE; /* *_done() is not called yet */
-  data->state.expect100header = FALSE;
 
   if(data->req.no_body)
     /* in HTTP lingo, no body means using the HEAD request... */
     data->state.httpreq = HTTPREQ_HEAD;
 
-  k->start = Curl_now(); /* start time */
-  k->header = TRUE; /* assume header */
-  k->bytecount = 0;
-  k->ignorebody = FALSE;
-
-  Curl_speedinit(data);
-  Curl_pgrsSetUploadCounter(data, 0);
-  Curl_pgrsSetDownloadCounter(data, 0);
-
-  return CURLE_OK;
+  result = Curl_req_start(&data->req, data);
+  if(!result) {
+    Curl_speedinit(data);
+    Curl_pgrsSetUploadCounter(data, 0);
+    Curl_pgrsSetDownloadCounter(data, 0);
+  }
+  return result;
 }
 
 #if defined(USE_HTTP2) || defined(USE_HTTP3)
diff --git a/vendor/curl/lib/url.h b/vendor/curl/lib/url.h
index f6a5b25737..198a00ad17 100644
--- a/vendor/curl/lib/url.h
+++ b/vendor/curl/lib/url.h
@@ -41,22 +41,27 @@ void Curl_disconnect(struct Curl_easy *data,
                      struct connectdata *, bool dead_connection);
 CURLcode Curl_setup_conn(struct Curl_easy *data,
                          bool *protocol_done);
-void Curl_free_request_state(struct Curl_easy *data);
 CURLcode Curl_parse_login_details(const char *login, const size_t len,
                                   char **userptr, char **passwdptr,
                                   char **optionsptr);
 
-const struct Curl_handler *Curl_builtin_scheme(const char *scheme,
-                                               size_t schemelen);
+/* Get protocol handler for a URI scheme
+ * @param scheme URI scheme, case-insensitive
+ * @return NULL of handler not found
+ */
+const struct Curl_handler *Curl_get_scheme_handler(const char *scheme);
+const struct Curl_handler *Curl_getn_scheme_handler(const char *scheme,
+                                                    size_t len);
 
 #define CURL_DEFAULT_PROXY_PORT 1080 /* default proxy port unless specified */
 #define CURL_DEFAULT_HTTPS_PROXY_PORT 443 /* default https proxy port unless
                                              specified */
 
 #ifdef CURL_DISABLE_VERBOSE_STRINGS
-#define Curl_verboseconnect(x,y)  Curl_nop_stmt
+#define Curl_verboseconnect(x,y,z)  Curl_nop_stmt
 #else
-void Curl_verboseconnect(struct Curl_easy *data, struct connectdata *conn);
+void Curl_verboseconnect(struct Curl_easy *data, struct connectdata *conn,
+                         int sockindex);
 #endif
 
 #if defined(USE_HTTP2) || defined(USE_HTTP3)
diff --git a/vendor/curl/lib/urlapi-int.h b/vendor/curl/lib/urlapi-int.h
index d6e240aa36..c40281a898 100644
--- a/vendor/curl/lib/urlapi-int.h
+++ b/vendor/curl/lib/urlapi-int.h
@@ -28,8 +28,7 @@
 size_t Curl_is_absolute_url(const char *url, char *buf, size_t buflen,
                             bool guess_scheme);
 
-CURLUcode Curl_url_set_authority(CURLU *u, const char *authority,
-                                 unsigned int flags);
+CURLUcode Curl_url_set_authority(CURLU *u, const char *authority);
 
 #ifdef DEBUGBUILD
 CURLUcode Curl_parse_port(struct Curl_URL *u, struct dynbuf *host,
diff --git a/vendor/curl/lib/urlapi.c b/vendor/curl/lib/urlapi.c
index 80299e7c0e..eb03966876 100644
--- a/vendor/curl/lib/urlapi.c
+++ b/vendor/curl/lib/urlapi.c
@@ -59,11 +59,11 @@
 #define MAX_SCHEME_LEN 40
 
 /*
- * If ENABLE_IPV6 is disabled, we still want to parse IPv6 addresses, so make
+ * If USE_IPV6 is disabled, we still want to parse IPv6 addresses, so make
  * sure we have _some_ value for AF_INET6 without polluting our fake value
  * everywhere.
  */
-#if !defined(ENABLE_IPV6) && !defined(AF_INET6)
+#if !defined(USE_IPV6) && !defined(AF_INET6)
 #define AF_INET6 (AF_INET + 1)
 #endif
 
@@ -79,7 +79,9 @@ struct Curl_URL {
   char *path;
   char *query;
   char *fragment;
-  long portnum; /* the numerical version */
+  unsigned short portnum; /* the numerical version (if 'port' is set) */
+  BIT(query_present);    /* to support blank */
+  BIT(fragment_present); /* to support blank */
 };
 
 #define DEFAULT_SCHEME "https"
@@ -100,7 +102,7 @@ static void free_urlhandle(struct Curl_URL *u)
 
 /*
  * Find the separator at the end of the host name, or the '?' in cases like
- * http://www.url.com?id=2380
+ * http://www.example.com?id=2380
  */
 static const char *find_host_sep(const char *url)
 {
@@ -126,6 +128,9 @@ static const char *find_host_sep(const char *url)
   return sep < query ? sep : query;
 }
 
+/* convert CURLcode to CURLUcode */
+#define cc2cu(x) ((x) == CURLE_TOO_LARGE ? CURLUE_TOO_LARGE :   \
+                  CURLUE_OUT_OF_MEMORY)
 /*
  * Decide whether a character in a URL must be escaped.
  */
@@ -146,6 +151,7 @@ static CURLUcode urlencode_str(struct dynbuf *o, const char *url,
   bool left = !query;
   const unsigned char *iptr;
   const unsigned char *host_sep = (const unsigned char *) url;
+  CURLcode result;
 
   if(!relative)
     host_sep = (const unsigned char *) find_host_sep(url);
@@ -154,20 +160,19 @@ static CURLUcode urlencode_str(struct dynbuf *o, const char *url,
       len; iptr++, len--) {
 
     if(iptr < host_sep) {
-      if(Curl_dyn_addn(o, iptr, 1))
-        return CURLUE_OUT_OF_MEMORY;
+      result = Curl_dyn_addn(o, iptr, 1);
+      if(result)
+        return cc2cu(result);
       continue;
     }
 
     if(*iptr == ' ') {
-      if(left) {
-        if(Curl_dyn_addn(o, "%20", 3))
-          return CURLUE_OUT_OF_MEMORY;
-      }
-      else {
-        if(Curl_dyn_addn(o, "+", 1))
-          return CURLUE_OUT_OF_MEMORY;
-      }
+      if(left)
+        result = Curl_dyn_addn(o, "%20", 3);
+      else
+        result = Curl_dyn_addn(o, "+", 1);
+      if(result)
+        return cc2cu(result);
       continue;
     }
 
@@ -178,13 +183,12 @@ static CURLUcode urlencode_str(struct dynbuf *o, const char *url,
       char out[3]={'%'};
       out[1] = hexdigits[*iptr>>4];
       out[2] = hexdigits[*iptr & 0xf];
-      if(Curl_dyn_addn(o, out, 3))
-        return CURLUE_OUT_OF_MEMORY;
-    }
-    else {
-      if(Curl_dyn_addn(o, iptr, 1))
-        return CURLUE_OUT_OF_MEMORY;
+      result = Curl_dyn_addn(o, out, 3);
     }
+    else
+      result = Curl_dyn_addn(o, iptr, 1);
+    if(result)
+      return cc2cu(result);
   }
 
   return CURLUE_OK;
@@ -206,7 +210,7 @@ size_t Curl_is_absolute_url(const char *url, char *buf, size_t buflen,
   (void)buflen; /* only used in debug-builds */
   if(buf)
     buf[0] = 0; /* always leave a defined value in buf */
-#ifdef WIN32
+#ifdef _WIN32
   if(guess_scheme && STARTS_WITH_DRIVE_PREFIX(url))
     return 0;
 #endif
@@ -230,10 +234,8 @@ size_t Curl_is_absolute_url(const char *url, char *buf, size_t buflen,
     /* the length of the scheme is the name part only */
     size_t len = i;
     if(buf) {
+      Curl_strntolower(buf, url, i);
       buf[i] = 0;
-      while(i--) {
-        buf[i] = Curl_raw_tolower(url[i]);
-      }
     }
     return len;
   }
@@ -248,7 +250,7 @@ size_t Curl_is_absolute_url(const char *url, char *buf, size_t buflen,
  *
  * Note that this function destroys the 'base' string.
  */
-static char *concat_url(char *base, const char *relurl)
+static CURLcode concat_url(char *base, const char *relurl, char **newurl)
 {
   /***
    TRY to append this new path to the old URL
@@ -260,6 +262,10 @@ static char *concat_url(char *base, const char *relurl)
   char *pathsep;
   bool host_changed = FALSE;
   const char *useurl = relurl;
+  CURLcode result = CURLE_OK;
+  CURLUcode uc;
+  bool skip_slash = FALSE;
+  *newurl = NULL;
 
   /* protsep points to the start of the host name */
   protsep = strstr(base, "//");
@@ -278,48 +284,50 @@ static char *concat_url(char *base, const char *relurl)
       *pathsep = 0;
 
     /* we have a relative path to append to the last slash if there's one
-       available, or if the new URL is just a query string (starts with a
-       '?')  we append the new one at the end of the entire currently worked
-       out URL */
-    if(useurl[0] != '?') {
+       available, or the new URL is just a query string (starts with a '?') or
+       a fragment (starts with '#') we append the new one at the end of the
+       current URL */
+    if((useurl[0] != '?') && (useurl[0] != '#')) {
       pathsep = strrchr(protsep, '/');
       if(pathsep)
         *pathsep = 0;
-    }
 
-    /* Check if there's any slash after the host name, and if so, remember
-       that position instead */
-    pathsep = strchr(protsep, '/');
-    if(pathsep)
-      protsep = pathsep + 1;
-    else
-      protsep = NULL;
+      /* Check if there's any slash after the host name, and if so, remember
+         that position instead */
+      pathsep = strchr(protsep, '/');
+      if(pathsep)
+        protsep = pathsep + 1;
+      else
+        protsep = NULL;
 
-    /* now deal with one "./" or any amount of "../" in the newurl
-       and act accordingly */
+      /* now deal with one "./" or any amount of "../" in the newurl
+         and act accordingly */
 
-    if((useurl[0] == '.') && (useurl[1] == '/'))
-      useurl += 2; /* just skip the "./" */
+      if((useurl[0] == '.') && (useurl[1] == '/'))
+        useurl += 2; /* just skip the "./" */
 
-    while((useurl[0] == '.') &&
-          (useurl[1] == '.') &&
-          (useurl[2] == '/')) {
-      level++;
-      useurl += 3; /* pass the "../" */
-    }
+      while((useurl[0] == '.') &&
+            (useurl[1] == '.') &&
+            (useurl[2] == '/')) {
+        level++;
+        useurl += 3; /* pass the "../" */
+      }
 
-    if(protsep) {
-      while(level--) {
-        /* cut off one more level from the right of the original URL */
-        pathsep = strrchr(protsep, '/');
-        if(pathsep)
-          *pathsep = 0;
-        else {
-          *protsep = 0;
-          break;
+      if(protsep) {
+        while(level--) {
+          /* cut off one more level from the right of the original URL */
+          pathsep = strrchr(protsep, '/');
+          if(pathsep)
+            *pathsep = 0;
+          else {
+            *protsep = 0;
+            break;
+          }
         }
       }
     }
+    else
+      skip_slash = TRUE;
   }
   else {
     /* We got a new absolute path for this server */
@@ -338,7 +346,7 @@ static char *concat_url(char *base, const char *relurl)
       pathsep = strchr(protsep, '/');
       if(pathsep) {
         /* When people use badly formatted URLs, such as
-           "http://www.url.com?dir=/home/daniel" we must not use the first
+           "http://www.example.com?dir=/home/daniel" we must not use the first
            slash, if there's a ?-letter before it! */
         char *sep = strchr(protsep, '?');
         if(sep && (sep < pathsep))
@@ -347,9 +355,9 @@ static char *concat_url(char *base, const char *relurl)
       }
       else {
         /* There was no slash. Now, since we might be operating on a badly
-           formatted URL, such as "http://www.url.com?id=2380" which doesn't
-           use a slash separator as it is supposed to, we need to check for a
-           ?-letter as well! */
+           formatted URL, such as "http://www.example.com?id=2380" which
+           doesn't use a slash separator as it is supposed to, we need to check
+           for a ?-letter as well! */
         pathsep = strchr(protsep, '?');
         if(pathsep)
           *pathsep = 0;
@@ -360,21 +368,27 @@ static char *concat_url(char *base, const char *relurl)
   Curl_dyn_init(&newest, CURL_MAX_INPUT_LENGTH);
 
   /* copy over the root url part */
-  if(Curl_dyn_add(&newest, base))
-    return NULL;
+  result = Curl_dyn_add(&newest, base);
+  if(result)
+    return result;
 
   /* check if we need to append a slash */
-  if(('/' == useurl[0]) || (protsep && !*protsep) || ('?' == useurl[0]))
+  if(('/' == useurl[0]) || (protsep && !*protsep) || skip_slash)
     ;
   else {
-    if(Curl_dyn_addn(&newest, "/", 1))
-      return NULL;
+    result = Curl_dyn_addn(&newest, "/", 1);
+    if(result)
+      return result;
   }
 
   /* then append the new piece on the right side */
-  urlencode_str(&newest, useurl, strlen(useurl), !host_changed, FALSE);
+  uc = urlencode_str(&newest, useurl, strlen(useurl), !host_changed,
+                     FALSE);
+  if(uc)
+    return (uc == CURLUE_TOO_LARGE) ? CURLE_TOO_LARGE : CURLE_OUT_OF_MEMORY;
 
-  return Curl_dyn_ptr(&newest);
+  *newurl = Curl_dyn_ptr(&newest);
+  return CURLE_OK;
 }
 
 /* scan for byte values <= 31, 127 and sometimes space */
@@ -446,7 +460,7 @@ static CURLUcode parse_hostname_login(struct Curl_URL *u,
 
   /* if this is a known scheme, get some details */
   if(u->scheme)
-    h = Curl_builtin_scheme(u->scheme, CURL_ZERO_TERMINATED);
+    h = Curl_get_scheme_handler(u->scheme);
 
   /* We could use the login information in the URL so extract it. Only parse
      options if the handler says we should. Note that 'h' might be NULL! */
@@ -520,8 +534,8 @@ UNITTEST CURLUcode Curl_parse_port(struct Curl_URL *u, struct dynbuf *host,
     portptr = strchr(hostname, ':');
 
   if(portptr) {
-    char *rest;
-    long port;
+    char *rest = NULL;
+    unsigned long port;
     size_t keep = portptr - hostname;
 
     /* Browser behavior adaptation. If there's a colon with no digits after,
@@ -539,15 +553,13 @@ UNITTEST CURLUcode Curl_parse_port(struct Curl_URL *u, struct dynbuf *host,
     if(!ISDIGIT(*portptr))
       return CURLUE_BAD_PORT_NUMBER;
 
-    port = strtol(portptr, &rest, 10);  /* Port number must be decimal */
-
-    if(port > 0xffff)
-      return CURLUE_BAD_PORT_NUMBER;
+    errno = 0;
+    port = strtoul(portptr, &rest, 10);  /* Port number must be decimal */
 
-    if(rest[0])
+    if(errno || (port > 0xffff) || *rest)
       return CURLUE_BAD_PORT_NUMBER;
 
-    u->portnum = port;
+    u->portnum = (unsigned short) port;
     /* generate a new port number string to get rid of leading zeroes etc */
     free(u->port);
     u->port = aprintf("%ld", port);
@@ -669,13 +681,21 @@ static int ipv4_normalize(struct dynbuf *host)
   if(*c == '[')
     return HOST_IPV6;
 
+  errno = 0; /* for strtoul */
   while(!done) {
-    char *endp;
+    char *endp = NULL;
     unsigned long l;
     if(!ISDIGIT(*c))
       /* most importantly this doesn't allow a leading plus or minus */
       return HOST_NAME;
     l = strtoul(c, &endp, 0);
+    if(errno)
+      return HOST_NAME;
+#if SIZEOF_LONG > 4
+    /* a value larger than 32 bits */
+    if(l > UINT_MAX)
+      return HOST_NAME;
+#endif
 
     parts[n] = l;
     c = endp;
@@ -695,16 +715,6 @@ static int ipv4_normalize(struct dynbuf *host)
     default:
       return HOST_NAME;
     }
-
-    /* overflow */
-    if((l == ULONG_MAX) && (errno == ERANGE))
-      return HOST_NAME;
-
-#if SIZEOF_LONG > 4
-    /* a value larger than 32 bits */
-    if(l > UINT_MAX)
-      return HOST_NAME;
-#endif
   }
 
   switch(n) {
@@ -712,24 +722,30 @@ static int ipv4_normalize(struct dynbuf *host)
     Curl_dyn_reset(host);
 
     result = Curl_dyn_addf(host, "%u.%u.%u.%u",
-                           parts[0] >> 24, (parts[0] >> 16) & 0xff,
-                           (parts[0] >> 8) & 0xff, parts[0] & 0xff);
+                           (unsigned int)(parts[0] >> 24),
+                           (unsigned int)((parts[0] >> 16) & 0xff),
+                           (unsigned int)((parts[0] >> 8) & 0xff),
+                           (unsigned int)(parts[0] & 0xff));
     break;
   case 1: /* a.b -- 8.24 bits */
     if((parts[0] > 0xff) || (parts[1] > 0xffffff))
       return HOST_NAME;
     Curl_dyn_reset(host);
     result = Curl_dyn_addf(host, "%u.%u.%u.%u",
-                           parts[0], (parts[1] >> 16) & 0xff,
-                           (parts[1] >> 8) & 0xff, parts[1] & 0xff);
+                           (unsigned int)(parts[0]),
+                           (unsigned int)((parts[1] >> 16) & 0xff),
+                           (unsigned int)((parts[1] >> 8) & 0xff),
+                           (unsigned int)(parts[1] & 0xff));
     break;
   case 2: /* a.b.c -- 8.8.16 bits */
     if((parts[0] > 0xff) || (parts[1] > 0xff) || (parts[2] > 0xffff))
       return HOST_NAME;
     Curl_dyn_reset(host);
     result = Curl_dyn_addf(host, "%u.%u.%u.%u",
-                           parts[0], parts[1], (parts[2] >> 8) & 0xff,
-                           parts[2] & 0xff);
+                           (unsigned int)(parts[0]),
+                           (unsigned int)(parts[1]),
+                           (unsigned int)((parts[2] >> 8) & 0xff),
+                           (unsigned int)(parts[2] & 0xff));
     break;
   case 3: /* a.b.c.d -- 8.8.8.8 bits */
     if((parts[0] > 0xff) || (parts[1] > 0xff) || (parts[2] > 0xff) ||
@@ -737,7 +753,10 @@ static int ipv4_normalize(struct dynbuf *host)
       return HOST_NAME;
     Curl_dyn_reset(host);
     result = Curl_dyn_addf(host, "%u.%u.%u.%u",
-                           parts[0], parts[1], parts[2], parts[3]);
+                           (unsigned int)(parts[0]),
+                           (unsigned int)(parts[1]),
+                           (unsigned int)(parts[2]),
+                           (unsigned int)(parts[3]));
     break;
   }
   if(result)
@@ -766,7 +785,7 @@ static CURLUcode urldecode_host(struct dynbuf *host)
     result = Curl_dyn_addn(host, decoded, dlen);
     free(decoded);
     if(result)
-      return CURLUE_OUT_OF_MEMORY;
+      return cc2cu(result);
   }
 
   return CURLUE_OK;
@@ -779,22 +798,24 @@ static CURLUcode parse_authority(struct Curl_URL *u,
                                  bool has_scheme)
 {
   size_t offset;
-  CURLUcode result;
+  CURLUcode uc;
+  CURLcode result;
 
   /*
    * Parse the login details and strip them out of the host name.
    */
-  result = parse_hostname_login(u, auth, authlen, flags, &offset);
-  if(result)
+  uc = parse_hostname_login(u, auth, authlen, flags, &offset);
+  if(uc)
     goto out;
 
-  if(Curl_dyn_addn(host, auth + offset, authlen - offset)) {
-    result = CURLUE_OUT_OF_MEMORY;
+  result = Curl_dyn_addn(host, auth + offset, authlen - offset);
+  if(result) {
+    uc = cc2cu(result);
     goto out;
   }
 
-  result = Curl_parse_port(u, host, has_scheme);
-  if(result)
+  uc = Curl_parse_port(u, host, has_scheme);
+  if(uc)
     goto out;
 
   if(!Curl_dyn_len(host))
@@ -804,28 +825,28 @@ static CURLUcode parse_authority(struct Curl_URL *u,
   case HOST_IPV4:
     break;
   case HOST_IPV6:
-    result = ipv6_parse(u, Curl_dyn_ptr(host), Curl_dyn_len(host));
+    uc = ipv6_parse(u, Curl_dyn_ptr(host), Curl_dyn_len(host));
     break;
   case HOST_NAME:
-    result = urldecode_host(host);
-    if(!result)
-      result = hostname_check(u, Curl_dyn_ptr(host), Curl_dyn_len(host));
+    uc = urldecode_host(host);
+    if(!uc)
+      uc = hostname_check(u, Curl_dyn_ptr(host), Curl_dyn_len(host));
     break;
   case HOST_ERROR:
-    result = CURLUE_OUT_OF_MEMORY;
+    uc = CURLUE_OUT_OF_MEMORY;
     break;
   case HOST_BAD:
   default:
-    result = CURLUE_BAD_HOSTNAME; /* Bad IPv4 address even */
+    uc = CURLUE_BAD_HOSTNAME; /* Bad IPv4 address even */
     break;
   }
 
 out:
-  return result;
+  return uc;
 }
 
-CURLUcode Curl_url_set_authority(CURLU *u, const char *authority,
-                                 unsigned int flags)
+/* used for HTTP/2 server push */
+CURLUcode Curl_url_set_authority(CURLU *u, const char *authority)
 {
   CURLUcode result;
   struct dynbuf host;
@@ -833,8 +854,8 @@ CURLUcode Curl_url_set_authority(CURLU *u, const char *authority,
   DEBUGASSERT(authority);
   Curl_dyn_init(&host, CURL_MAX_INPUT_LENGTH);
 
-  result = parse_authority(u, authority, strlen(authority), flags,
-                           &host, !!u->scheme);
+  result = parse_authority(u, authority, strlen(authority),
+                           CURLU_DISALLOW_USER, &host, !!u->scheme);
   if(result)
     Curl_dyn_free(&host);
   else {
@@ -1056,7 +1077,7 @@ static CURLUcode parseurl(const char *url, CURLU *u, unsigned int flags)
           ptr += 9; /* now points to the slash after the host */
         }
         else {
-#if defined(WIN32)
+#if defined(_WIN32)
           size_t len;
 
           /* the host name, NetBIOS computer name, can not contain disallowed
@@ -1070,8 +1091,9 @@ static CURLUcode parseurl(const char *url, CURLU *u, unsigned int flags)
 
           len = path - ptr;
           if(len) {
-            if(Curl_dyn_addn(&host, ptr, len)) {
-              result = CURLUE_OUT_OF_MEMORY;
+            CURLcode code = Curl_dyn_addn(&host, ptr, len);
+            if(code) {
+              result = cc2cu(code);
               goto fail;
             }
             uncpath = TRUE;
@@ -1095,7 +1117,7 @@ static CURLUcode parseurl(const char *url, CURLU *u, unsigned int flags)
       /* no host for file: URLs by default */
       Curl_dyn_reset(&host);
 
-#if !defined(MSDOS) && !defined(WIN32) && !defined(__CYGWIN__)
+#if !defined(_WIN32) && !defined(MSDOS) && !defined(__CYGWIN__)
     /* Don't allow Windows drive letters when not in Windows.
      * This catches both "file:/c:" and "file:c:" */
     if(('/' == path[0] && STARTS_WITH_URL_DRIVE_PREFIX(&path[1])) ||
@@ -1129,7 +1151,7 @@ static CURLUcode parseurl(const char *url, CURLU *u, unsigned int flags)
       }
 
       schemep = schemebuf;
-      if(!Curl_builtin_scheme(schemep, CURL_ZERO_TERMINATED) &&
+      if(!Curl_get_scheme_handler(schemep) &&
          !(flags & CURLU_NON_SUPPORT_SCHEME)) {
         result = CURLUE_UNSUPPORTED_SCHEME;
         goto fail;
@@ -1219,19 +1241,19 @@ static CURLUcode parseurl(const char *url, CURLU *u, unsigned int flags)
   fragment = strchr(path, '#');
   if(fragment) {
     fraglen = pathlen - (fragment - path);
+    u->fragment_present = TRUE;
     if(fraglen > 1) {
       /* skip the leading '#' in the copy but include the terminating null */
       if(flags & CURLU_URLENCODE) {
         struct dynbuf enc;
         Curl_dyn_init(&enc, CURL_MAX_INPUT_LENGTH);
-        if(urlencode_str(&enc, fragment + 1, fraglen, TRUE, FALSE)) {
-          result = CURLUE_OUT_OF_MEMORY;
+        result = urlencode_str(&enc, fragment + 1, fraglen - 1, TRUE, FALSE);
+        if(result)
           goto fail;
-        }
         u->fragment = Curl_dyn_ptr(&enc);
       }
       else {
-        u->fragment = Curl_memdup(fragment + 1, fraglen);
+        u->fragment = Curl_memdup0(fragment + 1, fraglen - 1);
         if(!u->fragment) {
           result = CURLUE_OUT_OF_MEMORY;
           goto fail;
@@ -1242,30 +1264,28 @@ static CURLUcode parseurl(const char *url, CURLU *u, unsigned int flags)
     pathlen -= fraglen;
   }
 
-  DEBUGASSERT(pathlen < urllen);
   query = memchr(path, '?', pathlen);
   if(query) {
     size_t qlen = fragment ? (size_t)(fragment - query) :
       pathlen - (query - path);
     pathlen -= qlen;
+    u->query_present = TRUE;
     if(qlen > 1) {
       if(flags & CURLU_URLENCODE) {
         struct dynbuf enc;
         Curl_dyn_init(&enc, CURL_MAX_INPUT_LENGTH);
         /* skip the leading question mark */
-        if(urlencode_str(&enc, query + 1, qlen - 1, TRUE, TRUE)) {
-          result = CURLUE_OUT_OF_MEMORY;
+        result = urlencode_str(&enc, query + 1, qlen - 1, TRUE, TRUE);
+        if(result)
           goto fail;
-        }
         u->query = Curl_dyn_ptr(&enc);
       }
       else {
-        u->query = Curl_memdup(query + 1, qlen);
+        u->query = Curl_memdup0(query + 1, qlen - 1);
         if(!u->query) {
           result = CURLUE_OUT_OF_MEMORY;
           goto fail;
         }
-        u->query[qlen - 1] = 0;
       }
     }
     else {
@@ -1281,10 +1301,9 @@ static CURLUcode parseurl(const char *url, CURLU *u, unsigned int flags)
   if(pathlen && (flags & CURLU_URLENCODE)) {
     struct dynbuf enc;
     Curl_dyn_init(&enc, CURL_MAX_INPUT_LENGTH);
-    if(urlencode_str(&enc, path, pathlen, TRUE, FALSE)) {
-      result = CURLUE_OUT_OF_MEMORY;
+    result = urlencode_str(&enc, path, pathlen, TRUE, FALSE);
+    if(result)
       goto fail;
-    }
     pathlen = Curl_dyn_len(&enc);
     path = u->path = Curl_dyn_ptr(&enc);
   }
@@ -1295,12 +1314,11 @@ static CURLUcode parseurl(const char *url, CURLU *u, unsigned int flags)
   }
   else {
     if(!u->path) {
-      u->path = Curl_memdup(path, pathlen + 1);
+      u->path = Curl_memdup0(path, pathlen);
       if(!u->path) {
         result = CURLUE_OUT_OF_MEMORY;
         goto fail;
       }
-      u->path[pathlen] = 0;
       path = u->path;
     }
     else if(flags & CURLU_URLENCODE)
@@ -1352,7 +1370,7 @@ static CURLUcode parseurl_and_replace(const char *url, CURLU *u,
  */
 CURLU *curl_url(void)
 {
-  return calloc(sizeof(struct Curl_URL), 1);
+  return calloc(1, sizeof(struct Curl_URL));
 }
 
 void curl_url_cleanup(CURLU *u)
@@ -1374,7 +1392,7 @@ void curl_url_cleanup(CURLU *u)
 
 CURLU *curl_url_dup(const CURLU *in)
 {
-  struct Curl_URL *u = calloc(sizeof(struct Curl_URL), 1);
+  struct Curl_URL *u = calloc(1, sizeof(struct Curl_URL));
   if(u) {
     DUP(u, in, scheme);
     DUP(u, in, user);
@@ -1387,6 +1405,8 @@ CURLU *curl_url_dup(const CURLU *in)
     DUP(u, in, fragment);
     DUP(u, in, zoneid);
     u->portnum = in->portnum;
+    u->fragment_present = in->fragment_present;
+    u->query_present = in->query_present;
   }
   return u;
 fail:
@@ -1447,8 +1467,7 @@ CURLUcode curl_url_get(const CURLU *u, CURLUPart what,
     if(!ptr && (flags & CURLU_DEFAULT_PORT) && u->scheme) {
       /* there's no stored port number, but asked to deliver
          a default one for the scheme */
-      const struct Curl_handler *h =
-        Curl_builtin_scheme(u->scheme, CURL_ZERO_TERMINATED);
+      const struct Curl_handler *h = Curl_get_scheme_handler(u->scheme);
       if(h) {
         msnprintf(portbuf, sizeof(portbuf), "%u", h->defport);
         ptr = portbuf;
@@ -1457,8 +1476,7 @@ CURLUcode curl_url_get(const CURLU *u, CURLUPart what,
     else if(ptr && u->scheme) {
       /* there is a stored port number, but ask to inhibit if
          it matches the default one for the scheme */
-      const struct Curl_handler *h =
-        Curl_builtin_scheme(u->scheme, CURL_ZERO_TERMINATED);
+      const struct Curl_handler *h = Curl_get_scheme_handler(u->scheme);
       if(h && (h->defport == u->portnum) &&
          (flags & CURLU_NO_DEFAULT_PORT))
         ptr = NULL;
@@ -1473,10 +1491,16 @@ CURLUcode curl_url_get(const CURLU *u, CURLUPart what,
     ptr = u->query;
     ifmissing = CURLUE_NO_QUERY;
     plusdecode = urldecode;
+    if(ptr && !ptr[0] && !(flags & CURLU_GET_EMPTY))
+      /* there was a blank query and the user do not ask for it */
+      ptr = NULL;
     break;
   case CURLUPART_FRAGMENT:
     ptr = u->fragment;
     ifmissing = CURLUE_NO_FRAGMENT;
+    if(!ptr && u->fragment_present && flags & CURLU_GET_EMPTY)
+      /* there was a blank fragment and the user asks for it */
+      ptr = "";
     break;
   case CURLUPART_URL: {
     char *url;
@@ -1484,13 +1508,18 @@ CURLUcode curl_url_get(const CURLU *u, CURLUPart what,
     char *options = u->options;
     char *port = u->port;
     char *allochost = NULL;
+    bool show_fragment =
+      u->fragment || (u->fragment_present && flags & CURLU_GET_EMPTY);
+    bool show_query =
+      (u->query && u->query[0]) ||
+      (u->query_present && flags & CURLU_GET_EMPTY);
     punycode = (flags & CURLU_PUNYCODE)?1:0;
     depunyfy = (flags & CURLU_PUNY2IDN)?1:0;
     if(u->scheme && strcasecompare("file", u->scheme)) {
       url = aprintf("file://%s%s%s",
                     u->path,
-                    u->fragment? "#": "",
-                    u->fragment? u->fragment : "");
+                    show_fragment ? "#": "",
+                    u->fragment ? u->fragment : "");
     }
     else if(!u->host)
       return CURLUE_NO_HOST;
@@ -1503,7 +1532,7 @@ CURLUcode curl_url_get(const CURLU *u, CURLUPart what,
       else
         return CURLUE_NO_SCHEME;
 
-      h = Curl_builtin_scheme(scheme, CURL_ZERO_TERMINATED);
+      h = Curl_get_scheme_handler(scheme);
       if(!port && (flags & CURLU_DEFAULT_PORT)) {
         /* there's no stored port number, but asked to deliver
            a default one for the scheme */
@@ -1578,9 +1607,9 @@ CURLUcode curl_url_get(const CURLU *u, CURLUPart what,
                     port ? ":": "",
                     port ? port : "",
                     u->path ? u->path : "/",
-                    (u->query && u->query[0]) ? "?": "",
-                    (u->query && u->query[0]) ? u->query : "",
-                    u->fragment? "#": "",
+                    show_query ? "?": "",
+                    u->query ? u->query : "",
+                    show_fragment ? "#": "",
                     u->fragment? u->fragment : "");
       free(allochost);
     }
@@ -1596,7 +1625,7 @@ CURLUcode curl_url_get(const CURLU *u, CURLUPart what,
   if(ptr) {
     size_t partlen = strlen(ptr);
     size_t i = 0;
-    *part = Curl_memdup(ptr, partlen + 1);
+    *part = Curl_memdup0(ptr, partlen);
     if(!*part)
       return CURLUE_OUT_OF_MEMORY;
     if(plusdecode) {
@@ -1623,10 +1652,11 @@ CURLUcode curl_url_get(const CURLU *u, CURLUPart what,
     }
     if(urlencode) {
       struct dynbuf enc;
+      CURLUcode uc;
       Curl_dyn_init(&enc, CURL_MAX_INPUT_LENGTH);
-      if(urlencode_str(&enc, *part, partlen, TRUE,
-                       what == CURLUPART_QUERY))
-        return CURLUE_OUT_OF_MEMORY;
+      uc = urlencode_str(&enc, *part, partlen, TRUE, what == CURLUPART_QUERY);
+      if(uc)
+        return uc;
       free(*part);
       *part = Curl_dyn_ptr(&enc);
     }
@@ -1671,7 +1701,6 @@ CURLUcode curl_url_set(CURLU *u, CURLUPart what,
                        const char *part, unsigned int flags)
 {
   char **storep = NULL;
-  long port = 0;
   bool urlencode = (flags & CURLU_URLENCODE)? 1 : 0;
   bool plusencode = FALSE;
   bool urlskipslash = FALSE;
@@ -1714,9 +1743,11 @@ CURLUcode curl_url_set(CURLU *u, CURLUPart what,
       break;
     case CURLUPART_QUERY:
       storep = &u->query;
+      u->query_present = FALSE;
       break;
     case CURLUPART_FRAGMENT:
       storep = &u->fragment;
+      u->fragment_present = FALSE;
       break;
     default:
       return CURLUE_UNKNOWN_PART;
@@ -1743,9 +1774,8 @@ CURLUcode curl_url_set(CURLU *u, CURLUPart what,
     if((plen > MAX_SCHEME_LEN) || (plen < 1))
       /* too long or too short */
       return CURLUE_BAD_SCHEME;
-    if(!(flags & CURLU_NON_SUPPORT_SCHEME) &&
-       /* verify that it is a fine scheme */
-       !Curl_builtin_scheme(part, CURL_ZERO_TERMINATED))
+   /* verify that it is a fine scheme */
+    if(!(flags & CURLU_NON_SUPPORT_SCHEME) && !Curl_get_scheme_handler(part))
       return CURLUE_UNSUPPORTED_SCHEME;
     storep = &u->scheme;
     urlencode = FALSE; /* never */
@@ -1779,18 +1809,26 @@ CURLUcode curl_url_set(CURLU *u, CURLUPart what,
     storep = &u->zoneid;
     break;
   case CURLUPART_PORT:
-  {
-    char *endp;
-    urlencode = FALSE; /* never */
-    port = strtol(part, &endp, 10);  /* Port number must be decimal */
-    if((port <= 0) || (port > 0xffff))
-      return CURLUE_BAD_PORT_NUMBER;
-    if(*endp)
-      /* weirdly provided number, not good! */
+    if(!ISDIGIT(part[0]))
+      /* not a number */
       return CURLUE_BAD_PORT_NUMBER;
-    storep = &u->port;
-  }
-  break;
+    else {
+      char *tmp;
+      char *endp;
+      unsigned long port;
+      errno = 0;
+      port = strtoul(part, &endp, 10);  /* must be decimal */
+      if(errno || (port > 0xffff) || *endp)
+        /* weirdly provided number, not good! */
+        return CURLUE_BAD_PORT_NUMBER;
+      tmp = strdup(part);
+      if(!tmp)
+        return CURLUE_OUT_OF_MEMORY;
+      free(u->port);
+      u->port = tmp;
+      u->portnum = (unsigned short)port;
+      return CURLUE_OK;
+    }
   case CURLUPART_PATH:
     urlskipslash = TRUE;
     leadingslash = TRUE; /* enforce */
@@ -1801,9 +1839,11 @@ CURLUcode curl_url_set(CURLU *u, CURLUPart what,
     appendquery = (flags & CURLU_APPENDQUERY)?1:0;
     equalsencode = appendquery;
     storep = &u->query;
+    u->query_present = TRUE;
     break;
   case CURLUPART_FRAGMENT:
     storep = &u->fragment;
+    u->fragment_present = TRUE;
     break;
   case CURLUPART_URL: {
     /*
@@ -1812,7 +1852,8 @@ CURLUcode curl_url_set(CURLU *u, CURLUPart what,
      * If the existing contents is enough for a URL, allow a relative URL to
      * replace it.
      */
-    CURLUcode result;
+    CURLcode result;
+    CURLUcode uc;
     char *oldurl;
     char *redired_url;
 
@@ -1832,14 +1873,14 @@ CURLUcode curl_url_set(CURLU *u, CURLUPart what,
 
     /* apply the relative part to create a new URL
      * and replace the existing one with it. */
-    redired_url = concat_url(oldurl, part);
+    result = concat_url(oldurl, part, &redired_url);
     free(oldurl);
-    if(!redired_url)
-      return CURLUE_OUT_OF_MEMORY;
+    if(result)
+      return cc2cu(result);
 
-    result = parseurl_and_replace(redired_url, u, flags);
+    uc = parseurl_and_replace(redired_url, u, flags);
     free(redired_url);
-    return result;
+    return uc;
   }
   default:
     return CURLUE_UNKNOWN_PART;
@@ -1853,7 +1894,7 @@ CURLUcode curl_url_set(CURLU *u, CURLUPart what,
     if(leadingslash && (part[0] != '/')) {
       CURLcode result = Curl_dyn_addn(&enc, "/", 1);
       if(result)
-        return CURLUE_OUT_OF_MEMORY;
+        return cc2cu(result);
     }
     if(urlencode) {
       const unsigned char *i;
@@ -1865,7 +1906,7 @@ CURLUcode curl_url_set(CURLU *u, CURLUPart what,
           if(result)
             return CURLUE_OUT_OF_MEMORY;
         }
-        else if(Curl_isunreserved(*i) ||
+        else if(ISUNRESERVED(*i) ||
                 ((*i == '/') && urlskipslash) ||
                 ((*i == '=') && equalsencode)) {
           if((*i == '=') && equalsencode)
@@ -1873,7 +1914,7 @@ CURLUcode curl_url_set(CURLU *u, CURLUPart what,
             equalsencode = FALSE;
           result = Curl_dyn_addn(&enc, i, 1);
           if(result)
-            return CURLUE_OUT_OF_MEMORY;
+            return cc2cu(result);
         }
         else {
           char out[3]={'%'};
@@ -1881,7 +1922,7 @@ CURLUcode curl_url_set(CURLU *u, CURLUPart what,
           out[2] = hexdigits[*i & 0xf];
           result = Curl_dyn_addn(&enc, out, 3);
           if(result)
-            return CURLUE_OUT_OF_MEMORY;
+            return cc2cu(result);
         }
       }
     }
@@ -1889,7 +1930,7 @@ CURLUcode curl_url_set(CURLU *u, CURLUPart what,
       char *p;
       CURLcode result = Curl_dyn_add(&enc, part);
       if(result)
-        return CURLUE_OUT_OF_MEMORY;
+        return cc2cu(result);
       p = Curl_dyn_ptr(&enc);
       while(*p) {
         /* make sure percent encoded are lower case */
@@ -1905,7 +1946,7 @@ CURLUcode curl_url_set(CURLU *u, CURLUPart what,
     }
     newp = Curl_dyn_ptr(&enc);
 
-    if(appendquery) {
+    if(appendquery && newp) {
       /* Append the 'newp' string onto the old query. Add a '&' separator if
          none is present at the end of the existing query already */
 
@@ -1934,8 +1975,8 @@ CURLUcode curl_url_set(CURLU *u, CURLUPart what,
       }
     }
 
-    if(what == CURLUPART_HOST) {
-      size_t n = strlen(newp);
+    else if(what == CURLUPART_HOST) {
+      size_t n = Curl_dyn_len(&enc);
       if(!n && (flags & CURLU_NO_AUTHORITY)) {
         /* Skip hostname check, it's allowed to be empty. */
       }
@@ -1950,9 +1991,5 @@ CURLUcode curl_url_set(CURLU *u, CURLUPart what,
     free(*storep);
     *storep = (char *)newp;
   }
-  /* set after the string, to make it not assigned if the allocation above
-     fails */
-  if(port)
-    u->portnum = port;
   return CURLUE_OK;
 }
diff --git a/vendor/curl/lib/urldata.h b/vendor/curl/lib/urldata.h
index 4bfb3b48d2..8b1bd65d61 100644
--- a/vendor/curl/lib/urldata.h
+++ b/vendor/curl/lib/urldata.h
@@ -53,6 +53,17 @@
 #define PORT_GOPHER 70
 #define PORT_MQTT 1883
 
+struct curl_trc_featt;
+
+#ifdef USE_ECH
+/* CURLECH_ bits for the tls_ech option */
+# define CURLECH_DISABLE    (1<<0)
+# define CURLECH_GREASE     (1<<1)
+# define CURLECH_ENABLE     (1<<2)
+# define CURLECH_HARD       (1<<3)
+# define CURLECH_CLA_CFG    (1<<4)
+#endif
+
 #ifdef USE_WEBSOCKETS
 /* CURLPROTO_GOPHERS (29) is the highest publicly used protocol bit number,
  * the rest are internal information. If we use higher bits we only do this on
@@ -102,7 +113,7 @@ typedef unsigned int curl_prot_t;
 #define PROTO_FAMILY_SSH  (CURLPROTO_SCP|CURLPROTO_SFTP)
 
 #if !defined(CURL_DISABLE_FTP) || defined(USE_SSH) ||   \
-  !defined(CURL_DISABLE_POP3)
+  !defined(CURL_DISABLE_POP3) || !defined(CURL_DISABLE_FILE)
 /* these protocols support CURLOPT_DIRLISTONLY */
 #define CURL_LIST_ONLY_PROTOCOL 1
 #endif
@@ -141,6 +152,7 @@ typedef unsigned int curl_prot_t;
 #include "splay.h"
 #include "dynbuf.h"
 #include "dynhds.h"
+#include "request.h"
 
 /* return the count of bytes sent, or -1 on error */
 typedef ssize_t (Curl_send)(struct Curl_easy *data,   /* transfer */
@@ -160,7 +172,6 @@ typedef ssize_t (Curl_recv)(struct Curl_easy *data,   /* transfer */
 typedef CURLcode (*Curl_datastream)(struct Curl_easy *data,
                                     struct connectdata *conn,
                                     int *didwhat,
-                                    bool *done,
                                     int select_res);
 #endif
 
@@ -230,8 +241,7 @@ typedef CURLcode (*Curl_datastream)(struct Curl_easy *data,
 #ifdef HAVE_GSSAPI
 /* Types needed for krb5-ftp connections */
 struct krb5buffer {
-  void *data;
-  size_t size;
+  struct dynbuf buf;
   size_t index;
   BIT(eof_flag);
 };
@@ -266,6 +276,21 @@ typedef enum {
 /* SSL backend-specific data; declared differently by each SSL backend */
 struct ssl_backend_data;
 
+typedef enum {
+  CURL_SSL_PEER_DNS,
+  CURL_SSL_PEER_IPV4,
+  CURL_SSL_PEER_IPV6
+} ssl_peer_type;
+
+struct ssl_peer {
+  char *hostname;        /* hostname for verification */
+  char *dispname;        /* display version of hostname */
+  char *sni;             /* SNI version of hostname or NULL if not usable */
+  ssl_peer_type type;    /* type of the peer information */
+  int port;              /* port we are talking to */
+  int transport;         /* TCP or QUIC */
+};
+
 struct ssl_primary_config {
   char *CApath;          /* certificate dir (doesn't work on windows) */
   char *CAfile;          /* certificate to verify peer against */
@@ -319,6 +344,8 @@ struct ssl_general_config {
   int ca_cache_timeout;  /* Certificate store cache timeout (seconds) */
 };
 
+typedef void Curl_ssl_sessionid_dtor(void *sessionid, size_t idsize);
+
 /* information stored about one single SSL session */
 struct Curl_ssl_session {
   char *name;       /* host name for which this ID was used */
@@ -326,9 +353,11 @@ struct Curl_ssl_session {
   const char *scheme; /* protocol scheme used */
   void *sessionid;  /* as returned from the SSL layer */
   size_t idsize;    /* if known, otherwise 0 */
+  Curl_ssl_sessionid_dtor *sessionid_free; /* free `sessionid` callback */
   long age;         /* just a number, the higher the more recent */
   int remote_port;  /* remote port */
   int conn_to_port; /* remote port for the connection (may be -1) */
+  int transport;    /* TCP or QUIC */
   struct ssl_primary_config ssl_config; /* setup for this session */
 };
 
@@ -429,14 +458,6 @@ struct ntlmdata {
   unsigned char nonce[8];
   unsigned int target_info_len;
   void *target_info; /* TargetInfo received in the ntlm type-2 message */
-
-#if defined(NTLM_WB_ENABLED)
-  /* used for communication with Samba's winbind daemon helper ntlm_auth */
-  curl_socket_t ntlm_auth_hlpr_socket;
-  pid_t ntlm_auth_hlpr_pid;
-  char *challenge; /* The received base64 encoded ntlm type-2 message */
-  char *response;  /* The generated base64 ntlm type-1/type-3 message */
-#endif
 #endif
 };
 #endif
@@ -512,10 +533,6 @@ struct ConnectBits {
                          the TCP layer connect */
   BIT(retry);         /* this connection is about to get closed and then
                          re-attempted at another connection. */
-  BIT(authneg);       /* TRUE when the auth phase has started, which means
-                         that we are creating a request with an auth header,
-                         but it is not the final request in the auth
-                         negotiation. */
 #ifndef CURL_DISABLE_FTP
   BIT(ftp_use_epsv);  /* As set with CURLOPT_FTP_USE_EPSV, but if we find out
                          EPSV doesn't work we disable it for the forthcoming
@@ -568,9 +585,24 @@ struct hostname {
 #define KEEP_RECV_PAUSE (1<<4) /* reading is paused */
 #define KEEP_SEND_PAUSE (1<<5) /* writing is paused */
 
+/* KEEP_SEND_TIMED is set when the transfer should attempt sending
+ * at timer (or other) events. A transfer waiting on a timer will
+  * remove KEEP_SEND to suppress POLLOUTs of the connection.
+  * Adding KEEP_SEND_TIMED will then attempt to send whenever the transfer
+  * enters the "readwrite" loop, e.g. when a timer fires.
+  * This is used in HTTP for 'Expect: 100-continue' waiting. */
+#define KEEP_SEND_TIMED (1<<6)
+
 #define KEEP_RECVBITS (KEEP_RECV | KEEP_RECV_HOLD | KEEP_RECV_PAUSE)
 #define KEEP_SENDBITS (KEEP_SEND | KEEP_SEND_HOLD | KEEP_SEND_PAUSE)
 
+/* transfer wants to send is not PAUSE or HOLD */
+#define CURL_WANT_SEND(data) \
+  (((data)->req.keepon & KEEP_SENDBITS) == KEEP_SEND)
+/* transfer receive is not on PAUSE or HOLD */
+#define CURL_WANT_RECV(data) \
+  (((data)->req.keepon & KEEP_RECVBITS) == KEEP_RECV)
+
 #if defined(CURLRES_ASYNCH) || !defined(CURL_DISABLE_DOH)
 #define USE_CURL_ASYNC
 struct Curl_async {
@@ -589,20 +621,13 @@ struct Curl_async {
 #define FIRSTSOCKET     0
 #define SECONDARYSOCKET 1
 
-enum expect100 {
-  EXP100_SEND_DATA,           /* enough waiting, just send the body now */
-  EXP100_AWAITING_CONTINUE,   /* waiting for the 100 Continue header */
-  EXP100_SENDING_REQUEST,     /* still sending the request but will wait for
-                                 the 100 header once done with the request */
-  EXP100_FAILED               /* used on 417 Expectation Failed */
-};
-
-enum upgrade101 {
-  UPGR101_INIT,               /* default state */
-  UPGR101_WS,                 /* upgrade to WebSockets requested */
-  UPGR101_H2,                 /* upgrade to HTTP/2 requested */
-  UPGR101_RECEIVED,           /* 101 response received */
-  UPGR101_WORKING             /* talking upgraded protocol */
+/* Polling requested by an easy handle.
+ * `action` is CURL_POLL_IN, CURL_POLL_OUT or CURL_POLL_INOUT.
+ */
+struct easy_pollset {
+  curl_socket_t sockets[MAX_SOCKSPEREASYHANDLE];
+  unsigned int num;
+  unsigned char actions[MAX_SOCKSPEREASYHANDLE];
 };
 
 enum doh_slots {
@@ -613,6 +638,9 @@ enum doh_slots {
   DOH_PROBE_SLOT_IPADDR_V6 = 1, /* 'V6' likewise */
 
   /* Space here for (possibly build-specific) additional slot definitions */
+#ifdef USE_HTTPSRR
+  DOH_PROBE_SLOT_HTTPS = 2,     /* for HTTPS RR */
+#endif
 
   /* for example */
   /* #ifdef WANT_DOH_FOOBAR_TXT */
@@ -623,119 +651,12 @@ enum doh_slots {
   DOH_PROBE_SLOTS
 };
 
-/*
- * Request specific data in the easy handle (Curl_easy).  Previously,
- * these members were on the connectdata struct but since a conn struct may
- * now be shared between different Curl_easys, we store connection-specific
- * data here. This struct only keeps stuff that's interesting for *this*
- * request, as it will be cleared between multiple ones
- */
-struct SingleRequest {
-  curl_off_t size;        /* -1 if unknown at this point */
-  curl_off_t maxdownload; /* in bytes, the maximum amount of data to fetch,
-                             -1 means unlimited */
-  curl_off_t bytecount;         /* total number of bytes read */
-  curl_off_t writebytecount;    /* number of bytes written */
-
-  curl_off_t pendingheader;      /* this many bytes left to send is actually
-                                    header and not body */
-  struct curltime start;         /* transfer started at this time */
-  unsigned int headerbytecount;  /* only count received headers */
-  unsigned int deductheadercount; /* this amount of bytes doesn't count when
-                                     we check if anything has been transferred
-                                     at the end of a connection. We use this
-                                     counter to make only a 100 reply (without
-                                     a following second response code) result
-                                     in a CURLE_GOT_NOTHING error code */
-  enum {
-    HEADER_NORMAL,              /* no bad header at all */
-    HEADER_PARTHEADER,          /* part of the chunk is a bad header, the rest
-                                   is normal data */
-    HEADER_ALLBAD               /* all was believed to be header */
-  } badheader;                  /* the header was deemed bad and will be
-                                   written as body */
-  int headerline;               /* counts header lines to better track the
-                                   first one */
-  char *str;                    /* within buf */
-  curl_off_t offset;            /* possible resume offset read from the
-                                   Content-Range: header */
-  int httpcode;                 /* error code from the 'HTTP/1.? XXX' or
-                                   'RTSP/1.? XXX' line */
-  int keepon;
-  struct curltime start100;      /* time stamp to wait for the 100 code from */
-  enum expect100 exp100;        /* expect 100 continue state */
-  enum upgrade101 upgr101;      /* 101 upgrade state */
-
-  /* Content unencoding stack. See sec 3.5, RFC2616. */
-  struct contenc_writer *writer_stack;
-  time_t timeofdoc;
-  long bodywrites;
-  char *location;   /* This points to an allocated version of the Location:
-                       header data */
-  char *newurl;     /* Set to the new URL to use when a redirect or a retry is
-                       wanted */
-
-  /* 'upload_present' is used to keep a byte counter of how much data there is
-     still left in the buffer, aimed for upload. */
-  ssize_t upload_present;
-
-  /* 'upload_fromhere' is used as a read-pointer when we uploaded parts of a
-     buffer, so the next read should read from where this pointer points to,
-     and the 'upload_present' contains the number of bytes available at this
-     position */
-  char *upload_fromhere;
-
-  /* Allocated protocol-specific data. Each protocol handler makes sure this
-     points to data it needs. */
-  union {
-    struct FILEPROTO *file;
-    struct FTP *ftp;
-    struct HTTP *http;
-    struct IMAP *imap;
-    struct ldapreqinfo *ldap;
-    struct MQTT *mqtt;
-    struct POP3 *pop3;
-    struct RTSP *rtsp;
-    struct smb_request *smb;
-    struct SMTP *smtp;
-    struct SSHPROTO *ssh;
-    struct TELNET *telnet;
-  } p;
-#ifndef CURL_DISABLE_DOH
-  struct dohdata *doh; /* DoH specific data for this request */
-#endif
-#if defined(WIN32) && defined(USE_WINSOCK)
-  struct curltime last_sndbuf_update;  /* last time readwrite_upload called
-                                          win_update_buffer_size */
-#endif
-#ifndef CURL_DISABLE_COOKIES
-  unsigned char setcookies;
-#endif
-  unsigned char writer_stack_depth; /* Unencoding stack depth. */
-  BIT(header);        /* incoming data has HTTP header */
-  BIT(content_range); /* set TRUE if Content-Range: was found */
-  BIT(upload_done);   /* set to TRUE when doing chunked transfer-encoding
-                         upload and we're uploading the last chunk */
-  BIT(ignorebody);    /* we read a response-body but we ignore it! */
-  BIT(http_bodyless); /* HTTP response status code is between 100 and 199,
-                         204 or 304 */
-  BIT(chunk);         /* if set, this is a chunked transfer-encoding */
-  BIT(ignore_cl);     /* ignore content-length */
-  BIT(upload_chunky); /* set TRUE if we are doing chunked transfer-encoding
-                         on upload */
-  BIT(getheader);    /* TRUE if header parsing is wanted */
-  BIT(forbidchunk);  /* used only to explicitly forbid chunk-upload for
-                        specific upload buffers. See readmoredata() in http.c
-                        for details. */
-  BIT(no_body);      /* the response has no body */
-};
-
 /*
  * Specific protocol handler.
  */
 
 struct Curl_handler {
-  const char *scheme;        /* URL scheme name. */
+  const char *scheme;        /* URL scheme name in lowercase */
 
   /* Complement to setup_connection_internals(). This is done before the
      transfer "owns" the connection. */
@@ -794,10 +715,17 @@ struct Curl_handler {
   CURLcode (*disconnect)(struct Curl_easy *, struct connectdata *,
                          bool dead_connection);
 
-  /* If used, this function gets called from transfer.c:readwrite_data() to
-     allow the protocol to do extra reads/writes */
-  CURLcode (*readwrite)(struct Curl_easy *data, struct connectdata *conn,
-                        ssize_t *nread, bool *readmore);
+  /* If used, this function gets called from transfer.c to
+     allow the protocol to do extra handling in writing response to
+     the client. */
+  CURLcode (*write_resp)(struct Curl_easy *data, const char *buf, size_t blen,
+                         bool is_eos);
+
+  /* If used, this function gets called from transfer.c to
+     allow the protocol to do extra handling in writing a single response
+     header line to the client. */
+  CURLcode (*write_resp_hd)(struct Curl_easy *data,
+                            const char *hd, size_t hdlen, bool is_eos);
 
   /* This function can perform various checks on the connection. See
      CONNCHECK_* for more information about the checks that can be performed,
@@ -853,6 +781,13 @@ struct Curl_handler {
 #define CONNRESULT_NONE 0                /* No extra information. */
 #define CONNRESULT_DEAD (1<<0)           /* The connection is dead. */
 
+struct ip_quadruple {
+  char remote_ip[MAX_IPADR_LEN];
+  char local_ip[MAX_IPADR_LEN];
+  int remote_port;
+  int local_port;
+};
+
 struct proxy_info {
   struct hostname host;
   int port;
@@ -876,11 +811,6 @@ struct ldapconninfo;
 struct connectdata {
   struct Curl_llist_element bundle_node; /* conncache */
 
-  /* chunk is for HTTP chunked encoding, but is in the general connectdata
-     struct only because we can do just about any protocol through an HTTP
-     proxy and an HTTP proxy may in fact respond using chunked encoding */
-  struct Curl_chunker chunk;
-
   curl_closesocket_callback fclosesocket; /* function closing the socket(s) */
   void *closesocket_client;
 
@@ -913,14 +843,13 @@ struct connectdata {
   struct proxy_info socks_proxy;
   struct proxy_info http_proxy;
 #endif
-  /* 'primary_ip' and 'primary_port' get filled with peer's numerical
-     ip address and port number whenever an outgoing connection is
-     *attempted* from the primary socket to a remote address. When more
-     than one address is tried for a connection these will hold data
+  /* 'primary' and 'secondary' get filled with IP quadruple
+     (local/remote numerical ip address and port) whenever a is *attempted*.
+     When more than one address is tried for a connection these will hold data
      for the last attempt. When the connection is actually established
      these are updated with data which comes directly from the socket. */
-
-  char primary_ip[MAX_IPADR_LEN];
+  struct ip_quadruple primary;
+  struct ip_quadruple secondary;
   char *user;    /* user name string, allocated */
   char *passwd;  /* password string, allocated */
   char *options; /* options string, allocated */
@@ -973,14 +902,17 @@ struct connectdata {
 #endif                        /* however, some of them are ftp specific. */
 
   struct Curl_llist easyq;    /* List of easy handles using this connection */
-  curl_seek_callback seek_func; /* function that seeks the input */
-  void *seek_client;            /* pointer to pass to the seek() above */
 
   /*************** Request - specific items ************/
 #if defined(USE_WINDOWS_SSPI) && defined(SECPKG_ATTR_ENDPOINT_BINDINGS)
   CtxtHandle *sslContext;
 #endif
 
+#if defined(_WIN32) && defined(USE_WINSOCK)
+  struct curltime last_sndbuf_update;  /* last time readwrite_upload called
+                                          win_update_buffer_size */
+#endif
+
 #ifdef USE_GSASL
   struct gsasldata gsasl;
 #endif
@@ -1003,11 +935,6 @@ struct connectdata {
   struct negotiatedata proxyneg; /* state data for proxy Negotiate auth */
 #endif
 
-#ifndef CURL_DISABLE_HTTP
-  /* for chunked-encoded trailer */
-  struct dynbuf trailer;
-#endif
-
   union {
 #ifndef CURL_DISABLE_FTP
     struct ftp_conn ftpc;
@@ -1068,17 +995,15 @@ struct connectdata {
   int socks5_gssapi_enctype;
 #endif
   /* The field below gets set in connect.c:connecthost() */
-  int port;        /* which port to use locally - to connect to */
   int remote_port; /* the remote port, not the proxy port! */
   int conn_to_port; /* the remote port to connect to. valid only if
                        bits.conn_to_port is set */
-#ifdef ENABLE_IPV6
+#ifdef USE_IPV6
   unsigned int scope_id;  /* Scope id for IPv6 */
 #endif
   unsigned short localport;
   unsigned short secondary_port; /* secondary socket remote port to connect to
                                     (ftp) */
-  unsigned char cselect_bits; /* bitmask of socket events */
   unsigned char alpn; /* APLN TLS negotiated protocol, a CURL_HTTP_VERSION*
                          value */
 #ifndef CURL_DISABLE_PROXY
@@ -1124,22 +1049,16 @@ struct PureInfo {
   curl_off_t retry_after; /* info from Retry-After: header */
   unsigned int header_size;  /* size of read header(s) in bytes */
 
-  /* PureInfo members 'conn_primary_ip', 'conn_primary_port', 'conn_local_ip'
-     and, 'conn_local_port' are copied over from the connectdata struct in
-     order to allow curl_easy_getinfo() to return this information even when
-     the session handle is no longer associated with a connection, and also
-     allow curl_easy_reset() to clear this information from the session handle
-     without disturbing information which is still alive, and that might be
-     reused, in the connection cache. */
-
-  char conn_primary_ip[MAX_IPADR_LEN];
-  int conn_primary_port; /* this is the destination port to the connection,
-                            which might have been a proxy */
+  /* PureInfo primary ip_quadruple is copied over from the connectdata
+     struct in order to allow curl_easy_getinfo() to return this information
+     even when the session handle is no longer associated with a connection,
+     and also allow curl_easy_reset() to clear this information from the
+     session handle without disturbing information which is still alive, and
+     that might be reused, in the connection cache. */
+  struct ip_quadruple primary;
   int conn_remote_port;  /* this is the "remote port", which is the port
                             number of the used URL, independent of proxy or
                             not */
-  char conn_local_ip[MAX_IPADR_LEN];
-  int conn_local_port;
   const char *conn_scheme;
   unsigned int conn_protocol;
   struct curl_certinfo certs; /* info about the certs. Asked for with
@@ -1147,6 +1066,7 @@ struct PureInfo {
   CURLproxycode pxcode;
   BIT(timecond);  /* set to TRUE if the time condition didn't match, which
                      thus made the document NOT get fetched */
+  BIT(used_proxy); /* the transfer used a proxy */
 };
 
 
@@ -1168,6 +1088,7 @@ struct Progress {
   curl_off_t dlspeed;
   curl_off_t ulspeed;
 
+  timediff_t t_postqueue;
   timediff_t t_nslookup;
   timediff_t t_connect;
   timediff_t t_appconnect;
@@ -1251,17 +1172,6 @@ struct Curl_data_priority {
 #endif
 };
 
-/*
- * This struct is for holding data that was attempted to get sent to the user's
- * callback but is held due to pausing. One instance per type (BOTH, HEADER,
- * BODY).
- */
-struct tempbuf {
-  struct dynbuf b;
-  int type;   /* type of the 'tempwrite' buffer as a bitmask that is used with
-                 Curl_client_write() */
-};
-
 /* Timers */
 typedef enum {
   EXPIRE_100_TIMEOUT,
@@ -1322,9 +1232,8 @@ struct UrlState {
   curl_off_t recent_conn_id; /* The most recent connection used, might no
                               * longer exist */
   struct dynbuf headerb; /* buffer to store headers in */
-
-  char *buffer; /* download buffer */
-  char *ulbuf; /* allocated upload buffer or NULL */
+  struct curl_slist *hstslist; /* list of HSTS files set by
+                                  curl_easy_setopt(HSTS) calls */
   curl_off_t current_speed;  /* the ProgressShow() function sets this,
                                 bytes / second */
 
@@ -1339,8 +1248,6 @@ struct UrlState {
   int retrycount; /* number of retries on a new connection */
   struct Curl_ssl_session *session; /* array of 'max_ssl_sessions' size */
   long sessionage;                  /* number of the most recent session */
-  struct tempbuf tempwrite[3]; /* BOTH, HEADER, BODY */
-  unsigned int tempcount; /* number of entries in use in tempwrite, 0 - 3 */
   int os_errno;  /* filled in with errno whenever an error occurs */
   char *scratch; /* huge buffer[set.buffer_size*2] for upload CRLF replacing */
   long followlocation; /* redirect counter */
@@ -1370,11 +1277,9 @@ struct UrlState {
 
   /* a place to store the most recently set (S)FTP entrypath */
   char *most_recent_ftp_entrypath;
-#if !defined(WIN32) && !defined(MSDOS) && !defined(__EMX__)
+#if !defined(_WIN32) && !defined(MSDOS) && !defined(__EMX__)
 /* do FTP line-end conversions on most platforms */
 #define CURL_DO_LINEEND_CONV
-  /* for FTP downloads: track CRLF sequences that span blocks */
-  BIT(prev_block_had_trailing_cr);
   /* for FTP downloads: how many CRLFs did we converted to LFs? */
   curl_off_t crlf_conversions;
 #endif
@@ -1408,8 +1313,10 @@ struct UrlState {
                                  this should be dealt with in pretransfer */
 #ifndef CURL_DISABLE_HTTP
   curl_mimepart *mimepost;
-  curl_mimepart *formp; /* storage for old API form-posting, alloced on
+#ifndef CURL_DISABLE_FORM_API
+  curl_mimepart *formp; /* storage for old API form-posting, allocated on
                            demand */
+#endif
   size_t trailers_bytes_sent;
   struct dynbuf trailers_buf; /* a buffer containing the compiled trailing
                                  headers */
@@ -1419,30 +1326,44 @@ struct UrlState {
   trailers_state trailers_state; /* whether we are sending trailers
                                     and what stage are we at */
 #endif
+#ifndef CURL_DISABLE_COOKIES
+  struct curl_slist *cookielist; /* list of cookie files set by
+                                    curl_easy_setopt(COOKIEFILE) calls */
+#endif
 #ifdef USE_HYPER
   bool hconnect;  /* set if a CONNECT request */
   CURLcode hresult; /* used to pass return codes back from hyper callbacks */
 #endif
 
+#ifndef CURL_DISABLE_VERBOSE_STRINGS
+  struct curl_trc_feat *feat; /* opt. trace feature transfer is part of */
+#endif
+
   /* Dynamically allocated strings, MUST be freed before this struct is
      killed. */
   struct dynamically_allocated_data {
-    char *proxyuserpwd;
     char *uagent;
     char *accept_encoding;
     char *userpwd;
     char *rangeline;
     char *ref;
     char *host;
+#ifndef CURL_DISABLE_COOKIES
     char *cookiehost;
+#endif
+#ifndef CURL_DISABLE_RTSP
     char *rtsp_transport;
+#endif
     char *te; /* TE: request header */
 
     /* transfer credentials */
     char *user;
     char *passwd;
+#ifndef CURL_DISABLE_PROXY
+    char *proxyuserpwd;
     char *proxyuser;
     char *proxypasswd;
+#endif
   } aptr;
 
   unsigned char httpwant; /* when non-zero, a specific HTTP version requested
@@ -1451,7 +1372,7 @@ struct UrlState {
                                 server involved in this request */
   unsigned char httpreq; /* Curl_HttpReq; what kind of HTTP request (if any)
                             is this */
-  unsigned char dselect_bits; /* != 0 -> bitmask of socket events for this
+  unsigned char select_bits; /* != 0 -> bitmask of socket events for this
                                  transfer overriding anything the socket may
                                  report */
 #ifdef CURLDEBUG
@@ -1472,7 +1393,6 @@ struct UrlState {
   BIT(authproblem); /* TRUE if there's some problem authenticating */
   /* set after initial USER failure, to prevent an authentication loop */
   BIT(wildcardmatch); /* enable wildcard matching */
-  BIT(expect100header);  /* TRUE if we added Expect: 100-continue */
   BIT(disableexpect);    /* TRUE if Expect: is disabled due to a previous
                             417 response */
   BIT(use_range);
@@ -1480,7 +1400,6 @@ struct UrlState {
   BIT(done); /* set to FALSE when Curl_init_do() is called and set to TRUE
                 when multi_done() is called, to prevent multi_done() to get
                 invoked twice when the multi interface is used. */
-  BIT(previouslypending); /* this transfer WAS in the multi->pending queue */
 #ifndef CURL_DISABLE_COOKIES
   BIT(cookie_engine);
 #endif
@@ -1491,10 +1410,10 @@ struct UrlState {
   BIT(url_alloc);   /* URL string is malloc()'ed */
   BIT(referer_alloc); /* referer string is malloc()ed */
   BIT(wildcard_resolve); /* Set to true if any resolve change is a wildcard */
-  BIT(rewindbeforesend);/* TRUE when the sending couldn't be stopped even
-                           though it will be discarded. We must call the data
-                           rewind callback before trying to send again. */
   BIT(upload);         /* upload request */
+  BIT(internal); /* internal: true if this easy handle was created for
+                    internal use and the user does not have ownership of the
+                    handle. */
 };
 
 /*
@@ -1508,95 +1427,127 @@ struct UrlState {
 
 struct Curl_multi;    /* declared in multihandle.c */
 
-/*
- * This enumeration MUST not use conditional directives (#ifdefs), new
- * null terminated strings MUST be added to the enumeration immediately
- * before STRING_LASTZEROTERMINATED, binary fields immediately before
- * STRING_LAST. When doing so, ensure that the packages/OS400/chkstring.c
- * test is updated and applicable changes for EBCDIC to ASCII conversion
- * are catered for in curl_easy_setopt_ccsid()
- */
 enum dupstring {
   STRING_CERT,            /* client certificate file name */
-  STRING_CERT_PROXY,      /* client certificate file name */
   STRING_CERT_TYPE,       /* format for certificate (default: PEM)*/
+  STRING_KEY,             /* private key file name */
+  STRING_KEY_PASSWD,      /* plain text private key password */
+  STRING_KEY_TYPE,        /* format for private key (default: PEM) */
+  STRING_SSL_CAPATH,      /* CA directory name (doesn't work on windows) */
+  STRING_SSL_CAFILE,      /* certificate file to verify peer against */
+  STRING_SSL_PINNEDPUBLICKEY, /* public key file to verify peer against */
+  STRING_SSL_CIPHER_LIST, /* list of ciphers to use */
+  STRING_SSL_CIPHER13_LIST, /* list of TLS 1.3 ciphers to use */
+  STRING_SSL_CRLFILE,     /* crl file to check certificate */
+  STRING_SSL_ISSUERCERT, /* issuer cert file to check certificate */
+  STRING_SERVICE_NAME,    /* Service name */
+#ifndef CURL_DISABLE_PROXY
+  STRING_CERT_PROXY,      /* client certificate file name */
   STRING_CERT_TYPE_PROXY, /* format for certificate (default: PEM)*/
+  STRING_KEY_PROXY,       /* private key file name */
+  STRING_KEY_PASSWD_PROXY, /* plain text private key password */
+  STRING_KEY_TYPE_PROXY,  /* format for private key (default: PEM) */
+  STRING_SSL_CAPATH_PROXY, /* CA directory name (doesn't work on windows) */
+  STRING_SSL_CAFILE_PROXY, /* certificate file to verify peer against */
+  STRING_SSL_PINNEDPUBLICKEY_PROXY, /* public key file to verify proxy */
+  STRING_SSL_CIPHER_LIST_PROXY, /* list of ciphers to use */
+  STRING_SSL_CIPHER13_LIST_PROXY, /* list of TLS 1.3 ciphers to use */
+  STRING_SSL_CRLFILE_PROXY, /* crl file to check certificate */
+  STRING_SSL_ISSUERCERT_PROXY, /* issuer cert file to check certificate */
+  STRING_PROXY_SERVICE_NAME, /* Proxy service name */
+#endif
+#ifndef CURL_DISABLE_COOKIES
   STRING_COOKIE,          /* HTTP cookie string to send */
   STRING_COOKIEJAR,       /* dump all cookies to this file */
+#endif
   STRING_CUSTOMREQUEST,   /* HTTP/FTP/RTSP request/method to use */
   STRING_DEFAULT_PROTOCOL, /* Protocol to use when the URL doesn't specify */
   STRING_DEVICE,          /* local network interface/address to use */
   STRING_ENCODING,        /* Accept-Encoding string */
+#ifndef CURL_DISABLE_FTP
   STRING_FTP_ACCOUNT,     /* ftp account data */
   STRING_FTP_ALTERNATIVE_TO_USER, /* command to send if USER/PASS fails */
   STRING_FTPPORT,         /* port to send with the FTP PORT command */
-  STRING_KEY,             /* private key file name */
-  STRING_KEY_PROXY,       /* private key file name */
-  STRING_KEY_PASSWD,      /* plain text private key password */
-  STRING_KEY_PASSWD_PROXY, /* plain text private key password */
-  STRING_KEY_TYPE,        /* format for private key (default: PEM) */
-  STRING_KEY_TYPE_PROXY,  /* format for private key (default: PEM) */
+#endif
+#if defined(HAVE_GSSAPI)
   STRING_KRB_LEVEL,       /* krb security level */
+#endif
+#ifndef CURL_DISABLE_NETRC
   STRING_NETRC_FILE,      /* if not NULL, use this instead of trying to find
                              $HOME/.netrc */
+#endif
+#ifndef CURL_DISABLE_PROXY
   STRING_PROXY,           /* proxy to use */
   STRING_PRE_PROXY,       /* pre socks proxy to use */
+#endif
   STRING_SET_RANGE,       /* range, if used */
   STRING_SET_REFERER,     /* custom string for the HTTP referer field */
   STRING_SET_URL,         /* what original URL to work on */
-  STRING_SSL_CAPATH,      /* CA directory name (doesn't work on windows) */
-  STRING_SSL_CAPATH_PROXY, /* CA directory name (doesn't work on windows) */
-  STRING_SSL_CAFILE,      /* certificate file to verify peer against */
-  STRING_SSL_CAFILE_PROXY, /* certificate file to verify peer against */
-  STRING_SSL_PINNEDPUBLICKEY, /* public key file to verify peer against */
-  STRING_SSL_PINNEDPUBLICKEY_PROXY, /* public key file to verify proxy */
-  STRING_SSL_CIPHER_LIST, /* list of ciphers to use */
-  STRING_SSL_CIPHER_LIST_PROXY, /* list of ciphers to use */
-  STRING_SSL_CIPHER13_LIST, /* list of TLS 1.3 ciphers to use */
-  STRING_SSL_CIPHER13_LIST_PROXY, /* list of TLS 1.3 ciphers to use */
   STRING_USERAGENT,       /* User-Agent string */
-  STRING_SSL_CRLFILE,     /* crl file to check certificate */
-  STRING_SSL_CRLFILE_PROXY, /* crl file to check certificate */
-  STRING_SSL_ISSUERCERT, /* issuer cert file to check certificate */
-  STRING_SSL_ISSUERCERT_PROXY, /* issuer cert file to check certificate */
   STRING_SSL_ENGINE,      /* name of ssl engine */
   STRING_USERNAME,        /* , if used */
   STRING_PASSWORD,        /* , if used */
   STRING_OPTIONS,         /* , if used */
+#ifndef CURL_DISABLE_PROXY
   STRING_PROXYUSERNAME,   /* Proxy , if used */
   STRING_PROXYPASSWORD,   /* Proxy , if used */
   STRING_NOPROXY,         /* List of hosts which should not use the proxy, if
                              used */
+#endif
+#ifndef CURL_DISABLE_RTSP
   STRING_RTSP_SESSION_ID, /* Session ID to use */
   STRING_RTSP_STREAM_URI, /* Stream URI for this request */
   STRING_RTSP_TRANSPORT,  /* Transport for this session */
+#endif
+#ifdef USE_SSH
   STRING_SSH_PRIVATE_KEY, /* path to the private key file for auth */
   STRING_SSH_PUBLIC_KEY,  /* path to the public key file for auth */
   STRING_SSH_HOST_PUBLIC_KEY_MD5, /* md5 of host public key in ascii hex */
   STRING_SSH_HOST_PUBLIC_KEY_SHA256, /* sha256 of host public key in base64 */
   STRING_SSH_KNOWNHOSTS,  /* file name of knownhosts file */
-  STRING_PROXY_SERVICE_NAME, /* Proxy service name */
-  STRING_SERVICE_NAME,    /* Service name */
+#endif
+#ifndef CURL_DISABLE_SMTP
   STRING_MAIL_FROM,
   STRING_MAIL_AUTH,
+#endif
+#ifdef USE_TLS_SRP
   STRING_TLSAUTH_USERNAME,  /* TLS auth  */
-  STRING_TLSAUTH_USERNAME_PROXY, /* TLS auth  */
   STRING_TLSAUTH_PASSWORD,  /* TLS auth  */
+#ifndef CURL_DISABLE_PROXY
+  STRING_TLSAUTH_USERNAME_PROXY, /* TLS auth  */
   STRING_TLSAUTH_PASSWORD_PROXY, /* TLS auth  */
+#endif
+#endif
   STRING_BEARER,                /* , if used */
+#ifdef USE_UNIX_SOCKETS
   STRING_UNIX_SOCKET_PATH,      /* path to Unix socket, if used */
+#endif
   STRING_TARGET,                /* CURLOPT_REQUEST_TARGET */
+#ifndef CURL_DISABLE_DOH
   STRING_DOH,                   /* CURLOPT_DOH_URL */
+#endif
+#ifndef CURL_DISABLE_ALTSVC
   STRING_ALTSVC,                /* CURLOPT_ALTSVC */
+#endif
+#ifndef CURL_DISABLE_HSTS
   STRING_HSTS,                  /* CURLOPT_HSTS */
+#endif
   STRING_SASL_AUTHZID,          /* CURLOPT_SASL_AUTHZID */
+#ifdef USE_ARES
   STRING_DNS_SERVERS,
   STRING_DNS_INTERFACE,
   STRING_DNS_LOCAL_IP4,
   STRING_DNS_LOCAL_IP6,
+#endif
   STRING_SSL_EC_CURVES,
+#ifndef CURL_DISABLE_AWS
   STRING_AWS_SIGV4, /* Parameters for V4 signature */
+#endif
+#ifndef CURL_DISABLE_PROXY
   STRING_HAPROXY_CLIENT_IP,     /* CURLOPT_HAPROXY_CLIENT_IP */
+#endif
+  STRING_ECH_CONFIG,            /* CURLOPT_ECH_CONFIG */
+  STRING_ECH_PUBLIC,            /* CURLOPT_ECH_PUBLIC */
 
   /* -- end of null-terminated strings -- */
 
@@ -1611,13 +1562,15 @@ enum dupstring {
 
 enum dupblob {
   BLOB_CERT,
-  BLOB_CERT_PROXY,
   BLOB_KEY,
-  BLOB_KEY_PROXY,
   BLOB_SSL_ISSUERCERT,
-  BLOB_SSL_ISSUERCERT_PROXY,
   BLOB_CAINFO,
+#ifndef CURL_DISABLE_PROXY
+  BLOB_CERT_PROXY,
+  BLOB_KEY_PROXY,
+  BLOB_SSL_ISSUERCERT_PROXY,
   BLOB_CAINFO_PROXY,
+#endif
   BLOB_LAST
 };
 
@@ -1671,13 +1624,7 @@ struct UserDefined {
   void *prereq_userp; /* pre-initial request user data */
 
   void *seek_client;    /* pointer to pass to the seek callback */
-#ifndef CURL_DISABLE_COOKIES
-  struct curl_slist *cookielist; /* list of cookie files set by
-                                    curl_easy_setopt(COOKIEFILE) calls */
-#endif
 #ifndef CURL_DISABLE_HSTS
-  struct curl_slist *hstslist; /* list of HSTS files set by
-                                  curl_easy_setopt(HSTS) calls */
   curl_hstsread_callback hsts_read;
   void *hsts_read_userp;
   curl_hstswrite_callback hsts_write;
@@ -1705,7 +1652,9 @@ struct UserDefined {
   curl_off_t set_resume_from;  /* continue [ftp] transfer from here */
   struct curl_slist *headers; /* linked list of extra headers */
   struct curl_httppost *httppost;  /* linked list of old POST data */
+#if !defined(CURL_DISABLE_MIME) || !defined(CURL_DISABLE_FORM_API)
   curl_mimepart mimepost;  /* MIME/POST data. */
+#endif
 #ifndef CURL_DISABLE_TELNET
   struct curl_slist *telnet_options; /* linked list of telnet options */
 #endif
@@ -1772,14 +1721,11 @@ struct UserDefined {
   unsigned int new_file_perms;      /* when creating remote files */
   char *str[STRING_LAST]; /* array of strings, pointing to allocated memory */
   struct curl_blob *blobs[BLOB_LAST];
-#ifdef ENABLE_IPV6
+#ifdef USE_IPV6
   unsigned int scope_id;  /* Scope id for IPv6 */
 #endif
   curl_prot_t allowed_protocols;
   curl_prot_t redir_protocols;
-#ifndef CURL_DISABLE_MIME
-  unsigned int mime_options;      /* Mime option flags. */
-#endif
 #ifndef CURL_DISABLE_RTSP
   void *rtp_out;     /* write RTP to this if non-NULL */
   /* Common RTSP header options */
@@ -1802,8 +1748,6 @@ struct UserDefined {
   int tcp_keepidle;     /* seconds in idle before sending keepalive probe */
   int tcp_keepintvl;    /* seconds between TCP keepalive probes */
 
-  size_t maxconnects;    /* Max idle connections in the connection cache */
-
   long expect_100_timeout; /* in milliseconds */
 #if defined(USE_HTTP2) || defined(USE_HTTP3)
   struct Curl_data_priority priority;
@@ -1828,10 +1772,14 @@ struct UserDefined {
   BIT(mail_rcpt_allowfails); /* allow RCPT TO command to fail for some
                                 recipients */
 #endif
+  unsigned int maxconnects; /* Max idle connections in the connection cache */
   unsigned char use_ssl;   /* if AUTH TLS is to be attempted etc, for FTP or
                               IMAP or POP3 or others! (type: curl_usessl)*/
   unsigned char connect_only; /* make connection/request, then let
                                  application use the socket */
+#ifndef CURL_DISABLE_MIME
+  BIT(mime_formescape);
+#endif
   BIT(is_fread_set); /* has read callback been set to non-NULL? */
 #ifndef CURL_DISABLE_TFTP
   BIT(tftp_no_options); /* do not send TFTP options requests */
@@ -1841,7 +1789,9 @@ struct UserDefined {
   BIT(cookiesession);   /* new cookie session? */
 #endif
   BIT(crlf);            /* convert crlf on ftp upload(?) */
+#ifdef USE_SSH
   BIT(ssh_compression);            /* enable SSH compression */
+#endif
 
 /* Here follows boolean settings that define how to behave during
    this session. They are STATIC, set by libcurl users or at least initially
@@ -1851,7 +1801,9 @@ struct UserDefined {
                             don't want lengthy cleanups to delay termination,
                             e.g. after a DNS timeout */
   BIT(get_filetime);     /* get the time and get of the remote file */
+#ifndef CURL_DISABLE_PROXY
   BIT(tunnel_thru_httpproxy); /* use CONNECT through an HTTP proxy */
+#endif
   BIT(prefer_ascii);     /* ASCII rather than binary */
   BIT(remote_append);    /* append, not overwrite, on upload */
 #ifdef CURL_LIST_ONLY_PROTOCOL
@@ -1878,7 +1830,9 @@ struct UserDefined {
                              location: */
   BIT(opt_no_body);    /* as set with CURLOPT_NOBODY */
   BIT(verbose);        /* output verbosity */
+#if defined(HAVE_GSSAPI)
   BIT(krb);            /* Kerberos connection requested */
+#endif
   BIT(reuse_forbid);   /* forbidden to be reused, close after use */
   BIT(reuse_fresh);    /* do not reuse an existing connection  */
   BIT(no_signal);      /* do not use any signal/alarm handler */
@@ -1903,9 +1857,13 @@ struct UserDefined {
   BIT(suppress_connect_headers); /* suppress proxy CONNECT response headers
                                     from user callbacks */
   BIT(dns_shuffle_addresses); /* whether to shuffle addresses before use */
+#ifndef CURL_DISABLE_PROXY
   BIT(haproxyprotocol); /* whether to send HAProxy PROXY protocol v1
                            header */
+#endif
+#ifdef USE_UNIX_SOCKETS
   BIT(abstract_unix_socket);
+#endif
   BIT(disallow_username_in_url); /* disallow username in url */
 #ifndef CURL_DISABLE_DOH
   BIT(doh); /* DNS-over-HTTPS enabled */
@@ -1917,8 +1875,17 @@ struct UserDefined {
 #ifdef USE_WEBSOCKETS
   BIT(ws_raw_mode);
 #endif
+#ifdef USE_ECH
+  int tls_ech;      /* TLS ECH configuration  */
+#endif
 };
 
+#ifndef CURL_DISABLE_MIME
+#define IS_MIME_POST(a) ((a)->set.mimepost.kind != MIMEKIND_NONE)
+#else
+#define IS_MIME_POST(a) FALSE
+#endif
+
 struct Names {
   struct Curl_hash *hostcache;
   enum {
@@ -1947,7 +1914,7 @@ struct Curl_easy {
      other using the same cache. For easier tracking
      in log output.
      This may wrap around after LONG_MAX to 0 again, so it
-     has no uniqueness guarantuee for very large processings. */
+     has no uniqueness guarantee for very large processings. */
   curl_off_t id;
 
   /* first, two fields for the linked list of these */
@@ -1968,10 +1935,7 @@ struct Curl_easy {
      particular order. Note that all sockets are added to the sockhash, where
      the state etc are also kept. This array is mostly used to detect when a
      socket is to be removed from the hash. See singlesocket(). */
-  curl_socket_t sockets[MAX_SOCKSPEREASYHANDLE];
-  unsigned char actions[MAX_SOCKSPEREASYHANDLE]; /* action for each socket in
-                                                    sockets[] */
-  int numsocks;
+  struct easy_pollset last_poll;
 
   struct Names dns;
   struct Curl_multi *multi;    /* if non-NULL, points to the multi handle
diff --git a/vendor/curl/lib/vauth/cleartext.c b/vendor/curl/lib/vauth/cleartext.c
index c651fc5145..29389c2c75 100644
--- a/vendor/curl/lib/vauth/cleartext.c
+++ b/vendor/curl/lib/vauth/cleartext.c
@@ -35,7 +35,6 @@
 #include "urldata.h"
 
 #include "vauth/vauth.h"
-#include "curl_md5.h"
 #include "warnless.h"
 #include "strtok.h"
 #include "sendf.h"
@@ -108,12 +107,11 @@ CURLcode Curl_auth_create_plain_message(const char *authzid,
  * valuep  [in]     - The user name or user's password.
  * out     [out]    - The result storage.
  *
- * Returns CURLE_OK on success.
+ * Returns void.
  */
-CURLcode Curl_auth_create_login_message(const char *valuep, struct bufref *out)
+void Curl_auth_create_login_message(const char *valuep, struct bufref *out)
 {
   Curl_bufref_set(out, valuep, strlen(valuep), NULL);
-  return CURLE_OK;
 }
 
 /*
@@ -127,13 +125,13 @@ CURLcode Curl_auth_create_login_message(const char *valuep, struct bufref *out)
  * user    [in]     - The user name.
  * out     [out]    - The result storage.
  *
- * Returns CURLE_OK on success.
+ * Returns void.
  */
-CURLcode Curl_auth_create_external_message(const char *user,
+void Curl_auth_create_external_message(const char *user,
                                            struct bufref *out)
 {
   /* This is the same formatting as the login message */
-  return Curl_auth_create_login_message(user, out);
+  Curl_auth_create_login_message(user, out);
 }
 
 #endif /* if no users */
diff --git a/vendor/curl/lib/vauth/digest.c b/vendor/curl/lib/vauth/digest.c
index 12c6f7dd5b..a742cce26e 100644
--- a/vendor/curl/lib/vauth/digest.c
+++ b/vendor/curl/lib/vauth/digest.c
@@ -38,6 +38,7 @@
 #include "curl_hmac.h"
 #include "curl_md5.h"
 #include "curl_sha256.h"
+#include "curl_sha512_256.h"
 #include "vtls/vtls.h"
 #include "warnless.h"
 #include "strtok.h"
@@ -125,7 +126,6 @@ bool Curl_auth_digest_get_pair(const char *str, char *value, char *content,
         }
         else
           return FALSE;
-        break;
       }
     }
 
@@ -151,7 +151,7 @@ static void auth_digest_md5_to_ascii(unsigned char *source, /* 16 bytes */
     msnprintf((char *) &dest[i * 2], 3, "%02x", source[i]);
 }
 
-/* Convert sha256 chunk to RFC7616 -suitable ascii string */
+/* Convert sha256 or SHA-512/256 chunk to RFC7616 -suitable ascii string */
 static void auth_digest_sha256_to_ascii(unsigned char *source, /* 32 bytes */
                                      unsigned char *dest) /* 65 bytes */
 {
@@ -288,7 +288,7 @@ static CURLcode auth_decode_digest_md5_message(const struct bufref *chlgref,
   /* Retrieve realm string from the challenge */
   if(!auth_digest_get_key_value(chlg, "realm=\"", realm, rlen, '\"')) {
     /* Challenge does not have a realm, set empty string [RFC2831] page 6 */
-    strcpy(realm, "");
+    *realm = '\0';
   }
 
   /* Retrieve algorithm string from the challenge */
@@ -602,10 +602,20 @@ CURLcode Curl_auth_decode_digest_http_message(const char *chlg,
           digest->algo = ALGO_SHA256;
         else if(strcasecompare(content, "SHA-256-SESS"))
           digest->algo = ALGO_SHA256SESS;
-        else if(strcasecompare(content, "SHA-512-256"))
+        else if(strcasecompare(content, "SHA-512-256")) {
+#ifdef CURL_HAVE_SHA512_256
           digest->algo = ALGO_SHA512_256;
-        else if(strcasecompare(content, "SHA-512-256-SESS"))
+#else  /* ! CURL_HAVE_SHA512_256 */
+          return CURLE_NOT_BUILT_IN;
+#endif /* ! CURL_HAVE_SHA512_256 */
+        }
+        else if(strcasecompare(content, "SHA-512-256-SESS")) {
+#ifdef CURL_HAVE_SHA512_256
           digest->algo = ALGO_SHA512_256SESS;
+#else  /* ! CURL_HAVE_SHA512_256 */
+          return CURLE_NOT_BUILT_IN;
+#endif /* ! CURL_HAVE_SHA512_256 */
+        }
         else
           return CURLE_BAD_CONTENT_ENCODING;
       }
@@ -718,8 +728,10 @@ static CURLcode auth_create_digest_http_message(
     if(!hashthis)
       return CURLE_OUT_OF_MEMORY;
 
-    hash(hashbuf, (unsigned char *) hashthis, strlen(hashthis));
+    result = hash(hashbuf, (unsigned char *) hashthis, strlen(hashthis));
     free(hashthis);
+    if(result)
+      return result;
     convert_to_ascii(hashbuf, (unsigned char *)userh);
   }
 
@@ -739,8 +751,10 @@ static CURLcode auth_create_digest_http_message(
   if(!hashthis)
     return CURLE_OUT_OF_MEMORY;
 
-  hash(hashbuf, (unsigned char *) hashthis, strlen(hashthis));
+  result = hash(hashbuf, (unsigned char *) hashthis, strlen(hashthis));
   free(hashthis);
+  if(result)
+    return result;
   convert_to_ascii(hashbuf, ha1);
 
   if(digest->algo & SESSION_ALGO) {
@@ -749,8 +763,10 @@ static CURLcode auth_create_digest_http_message(
     if(!tmp)
       return CURLE_OUT_OF_MEMORY;
 
-    hash(hashbuf, (unsigned char *) tmp, strlen(tmp));
+    result = hash(hashbuf, (unsigned char *) tmp, strlen(tmp));
     free(tmp);
+    if(result)
+      return result;
     convert_to_ascii(hashbuf, ha1);
   }
 
@@ -776,7 +792,11 @@ static CURLcode auth_create_digest_http_message(
     char hashed[65];
     char *hashthis2;
 
-    hash(hashbuf, (const unsigned char *)"", 0);
+    result = hash(hashbuf, (const unsigned char *)"", 0);
+    if(result) {
+      free(hashthis);
+      return result;
+    }
     convert_to_ascii(hashbuf, (unsigned char *)hashed);
 
     hashthis2 = aprintf("%s:%s", hashthis, hashed);
@@ -787,8 +807,10 @@ static CURLcode auth_create_digest_http_message(
   if(!hashthis)
     return CURLE_OUT_OF_MEMORY;
 
-  hash(hashbuf, (unsigned char *) hashthis, strlen(hashthis));
+  result = hash(hashbuf, (unsigned char *) hashthis, strlen(hashthis));
   free(hashthis);
+  if(result)
+    return result;
   convert_to_ascii(hashbuf, ha2);
 
   if(digest->qop) {
@@ -802,8 +824,10 @@ static CURLcode auth_create_digest_http_message(
   if(!hashthis)
     return CURLE_OUT_OF_MEMORY;
 
-  hash(hashbuf, (unsigned char *) hashthis, strlen(hashthis));
+  result = hash(hashbuf, (unsigned char *) hashthis, strlen(hashthis));
   free(hashthis);
+  if(result)
+    return result;
   convert_to_ascii(hashbuf, request_digest);
 
   /* For test case 64 (snooped from a Mozilla 1.3a request)
@@ -958,12 +982,24 @@ CURLcode Curl_auth_create_digest_http_message(struct Curl_easy *data,
                                            outptr, outlen,
                                            auth_digest_md5_to_ascii,
                                            Curl_md5it);
-  DEBUGASSERT(digest->algo <= ALGO_SHA512_256SESS);
-  return auth_create_digest_http_message(data, userp, passwdp,
-                                         request, uripath, digest,
-                                         outptr, outlen,
-                                         auth_digest_sha256_to_ascii,
-                                         Curl_sha256it);
+
+  if(digest->algo <= ALGO_SHA256SESS)
+    return auth_create_digest_http_message(data, userp, passwdp,
+                                           request, uripath, digest,
+                                           outptr, outlen,
+                                           auth_digest_sha256_to_ascii,
+                                           Curl_sha256it);
+#ifdef CURL_HAVE_SHA512_256
+  if(digest->algo <= ALGO_SHA512_256SESS)
+    return auth_create_digest_http_message(data, userp, passwdp,
+                                           request, uripath, digest,
+                                           outptr, outlen,
+                                           auth_digest_sha256_to_ascii,
+                                           Curl_sha512_256it);
+#endif /* CURL_HAVE_SHA512_256 */
+
+  /* Should be unreachable */
+  return CURLE_BAD_CONTENT_ENCODING;
 }
 
 /*
diff --git a/vendor/curl/lib/vauth/digest_sspi.c b/vendor/curl/lib/vauth/digest_sspi.c
index 02e36ea5ed..4696f29add 100644
--- a/vendor/curl/lib/vauth/digest_sspi.c
+++ b/vendor/curl/lib/vauth/digest_sspi.c
@@ -211,8 +211,10 @@ CURLcode Curl_auth_create_digest_md5_message(struct Curl_easy *data,
     if(status == SEC_E_INSUFFICIENT_MEMORY)
       return CURLE_OUT_OF_MEMORY;
 
+#if !defined(CURL_DISABLE_VERBOSE_STRINGS)
     infof(data, "schannel: InitializeSecurityContext failed: %s",
           Curl_sspi_strerror(status, buffer, sizeof(buffer)));
+#endif
 
     return CURLE_AUTH_ERROR;
   }
@@ -603,8 +605,10 @@ CURLcode Curl_auth_create_digest_http_message(struct Curl_easy *data,
       if(status == SEC_E_INSUFFICIENT_MEMORY)
         return CURLE_OUT_OF_MEMORY;
 
+#if !defined(CURL_DISABLE_VERBOSE_STRINGS)
       infof(data, "schannel: InitializeSecurityContext failed: %s",
             Curl_sspi_strerror(status, buffer, sizeof(buffer)));
+#endif
 
       return CURLE_AUTH_ERROR;
     }
diff --git a/vendor/curl/lib/vauth/krb5_gssapi.c b/vendor/curl/lib/vauth/krb5_gssapi.c
index 65eb3e1b50..16b6e4037f 100644
--- a/vendor/curl/lib/vauth/krb5_gssapi.c
+++ b/vendor/curl/lib/vauth/krb5_gssapi.c
@@ -226,7 +226,8 @@ CURLcode Curl_auth_create_gssapi_security_message(struct Curl_easy *data,
   /* Extract the security layer and the maximum message size */
   indata = output_token.value;
   sec_layer = indata[0];
-  max_size = (indata[1] << 16) | (indata[2] << 8) | indata[3];
+  max_size = ((unsigned int)indata[1] << 16) |
+             ((unsigned int)indata[2] << 8) | indata[3];
 
   /* Free the challenge as it is not required anymore */
   gss_release_buffer(&unused_status, &output_token);
diff --git a/vendor/curl/lib/vauth/krb5_sspi.c b/vendor/curl/lib/vauth/krb5_sspi.c
index c487149b9d..17a517a975 100644
--- a/vendor/curl/lib/vauth/krb5_sspi.c
+++ b/vendor/curl/lib/vauth/krb5_sspi.c
@@ -319,7 +319,8 @@ CURLcode Curl_auth_create_gssapi_security_message(struct Curl_easy *data,
   /* Extract the security layer and the maximum message size */
   indata = input_buf[1].pvBuffer;
   sec_layer = indata[0];
-  max_size = (indata[1] << 16) | (indata[2] << 8) | indata[3];
+  max_size = ((unsigned long)indata[1] << 16) |
+             ((unsigned long)indata[2] << 8) | indata[3];
 
   /* Free the challenge as it is not required anymore */
   s_pSecFn->FreeContextBuffer(input_buf[1].pvBuffer);
diff --git a/vendor/curl/lib/vauth/ntlm.c b/vendor/curl/lib/vauth/ntlm.c
index ed7cee8def..018e6a67ef 100644
--- a/vendor/curl/lib/vauth/ntlm.c
+++ b/vendor/curl/lib/vauth/ntlm.c
@@ -44,6 +44,7 @@
 #include "warnless.h"
 #include "rand.h"
 #include "vtls/vtls.h"
+#include "strdup.h"
 
 #define BUILDING_CURL_NTLM_MSGS_C
 #include "vauth/vauth.h"
@@ -184,11 +185,10 @@ static CURLcode ntlm_decode_type2_target(struct Curl_easy *data,
       }
 
       free(ntlm->target_info); /* replace any previous data */
-      ntlm->target_info = malloc(target_info_len);
+      ntlm->target_info = Curl_memdup(&type2[target_info_offset],
+                                      target_info_len);
       if(!ntlm->target_info)
         return CURLE_OUT_OF_MEMORY;
-
-      memcpy(ntlm->target_info, &type2[target_info_offset], target_info_len);
     }
   }
 
diff --git a/vendor/curl/lib/vauth/ntlm_sspi.c b/vendor/curl/lib/vauth/ntlm_sspi.c
index 5118963f4d..92054316dc 100644
--- a/vendor/curl/lib/vauth/ntlm_sspi.c
+++ b/vendor/curl/lib/vauth/ntlm_sspi.c
@@ -34,6 +34,7 @@
 #include "warnless.h"
 #include "curl_multibyte.h"
 #include "sendf.h"
+#include "strdup.h"
 
 /* The last #include files should be: */
 #include "curl_memory.h"
@@ -213,11 +214,10 @@ CURLcode Curl_auth_decode_ntlm_type2_message(struct Curl_easy *data,
   }
 
   /* Store the challenge for later use */
-  ntlm->input_token = malloc(Curl_bufref_len(type2) + 1);
+  ntlm->input_token = Curl_memdup0((const char *)Curl_bufref_ptr(type2),
+                                   Curl_bufref_len(type2));
   if(!ntlm->input_token)
     return CURLE_OUT_OF_MEMORY;
-  memcpy(ntlm->input_token, Curl_bufref_ptr(type2), Curl_bufref_len(type2));
-  ntlm->input_token[Curl_bufref_len(type2)] = '\0';
   ntlm->input_token_len = Curl_bufref_len(type2);
 
   return CURLE_OK;
@@ -314,7 +314,7 @@ CURLcode Curl_auth_create_ntlm_type3_message(struct Curl_easy *data,
                                                &type_3_desc,
                                                &attrs, &expiry);
   if(status != SEC_E_OK) {
-    infof(data, "NTLM handshake failure (type-3 message): Status=%x",
+    infof(data, "NTLM handshake failure (type-3 message): Status=%lx",
           status);
 
     if(status == SEC_E_INSUFFICIENT_MEMORY)
diff --git a/vendor/curl/lib/vauth/vauth.h b/vendor/curl/lib/vauth/vauth.h
index 9da0540892..7e823484f6 100644
--- a/vendor/curl/lib/vauth/vauth.h
+++ b/vendor/curl/lib/vauth/vauth.h
@@ -79,12 +79,10 @@ CURLcode Curl_auth_create_plain_message(const char *authzid,
                                         struct bufref *out);
 
 /* This is used to generate a LOGIN cleartext message */
-CURLcode Curl_auth_create_login_message(const char *value,
-                                        struct bufref *out);
+void Curl_auth_create_login_message(const char *value, struct bufref *out);
 
 /* This is used to generate an EXTERNAL cleartext message */
-CURLcode Curl_auth_create_external_message(const char *user,
-                                           struct bufref *out);
+void Curl_auth_create_external_message(const char *user, struct bufref *out);
 
 #ifndef CURL_DISABLE_DIGEST_AUTH
 /* This is used to generate a CRAM-MD5 response message */
diff --git a/vendor/curl/lib/version.c b/vendor/curl/lib/version.c
index 47304259e0..a5c8c4e613 100644
--- a/vendor/curl/lib/version.c
+++ b/vendor/curl/lib/version.c
@@ -39,7 +39,7 @@
 
 #ifdef USE_ARES
 #  if defined(CURL_STATICLIB) && !defined(CARES_STATICLIB) &&   \
-  defined(WIN32)
+  defined(_WIN32)
 #    define CARES_STATICLIB
 #  endif
 #  include 
@@ -55,6 +55,7 @@
 
 #ifdef USE_LIBRTMP
 #include 
+#include "curl_rtmp.h"
 #endif
 
 #ifdef HAVE_LIBZ
@@ -152,7 +153,7 @@ char *curl_version(void)
 #ifdef USE_NGHTTP2
   char h2_version[40];
 #endif
-#ifdef ENABLE_QUIC
+#ifdef USE_HTTP3
   char h3_version[40];
 #endif
 #ifdef USE_LIBRTMP
@@ -174,8 +175,7 @@ char *curl_version(void)
   /* Override version string when environment variable CURL_VERSION is set */
   const char *debugversion = getenv("CURL_VERSION");
   if(debugversion) {
-    strncpy(out, debugversion, sizeof(out)-1);
-    out[sizeof(out)-1] = '\0';
+    msnprintf(out, sizeof(out), "%s", debugversion);
     return out;
   }
 #endif
@@ -208,11 +208,23 @@ char *curl_version(void)
   src[i++] = idn_version;
 #elif defined(USE_WIN32_IDN)
   src[i++] = (char *)"WinIDN";
+#elif defined(USE_APPLE_IDN)
+  src[i++] = (char *)"AppleIDN";
 #endif
 
 #ifdef USE_LIBPSL
-  msnprintf(psl_version, sizeof(psl_version), "libpsl/%s", psl_get_version());
-  src[i++] = psl_version;
+  {
+#if defined(PSL_VERSION_MAJOR) && (PSL_VERSION_MAJOR > 0 ||     \
+                                   PSL_VERSION_MINOR >= 11)
+    int num = psl_check_version_number(0);
+    msnprintf(psl_version, sizeof(psl_version), "libpsl/%d.%d.%d",
+              num >> 16, (num >> 8) & 0xff, num & 0xff);
+#else
+    msnprintf(psl_version, sizeof(psl_version), "libpsl/%s",
+              psl_get_version());
+#endif
+    src[i++] = psl_version;
+  }
 #endif
 
 #ifdef USE_SSH
@@ -223,25 +235,13 @@ char *curl_version(void)
   Curl_http2_ver(h2_version, sizeof(h2_version));
   src[i++] = h2_version;
 #endif
-#ifdef ENABLE_QUIC
+#ifdef USE_HTTP3
   Curl_quic_ver(h3_version, sizeof(h3_version));
   src[i++] = h3_version;
 #endif
 #ifdef USE_LIBRTMP
-  {
-    char suff[2];
-    if(RTMP_LIB_VERSION & 0xff) {
-      suff[0] = (RTMP_LIB_VERSION & 0xff) + 'a' - 1;
-      suff[1] = '\0';
-    }
-    else
-      suff[0] = '\0';
-
-    msnprintf(rtmp_version, sizeof(rtmp_version), "librtmp/%d.%d%s",
-              RTMP_LIB_VERSION >> 16, (RTMP_LIB_VERSION >> 8) & 0xff,
-              suff);
-    src[i++] = rtmp_version;
-  }
+  Curl_rtmp_version(rtmp_version, sizeof(rtmp_version));
+  src[i++] = rtmp_version;
 #endif
 #ifdef USE_HYPER
   msnprintf(hyper_buf, sizeof(hyper_buf), "Hyper/%s", hyper_version());
@@ -409,7 +409,8 @@ static int idn_present(curl_version_info_data *info)
 #define idn_present     NULL
 #endif
 
-#if defined(USE_SSL) && !defined(CURL_DISABLE_PROXY)
+#if defined(USE_SSL) && !defined(CURL_DISABLE_PROXY) && \
+  !defined(CURL_DISABLE_HTTP)
 static int https_proxy_present(curl_version_info_data *info)
 {
   (void) info;
@@ -417,6 +418,14 @@ static int https_proxy_present(curl_version_info_data *info)
 }
 #endif
 
+#if defined(USE_SSL) && defined(USE_ECH)
+static int ech_present(curl_version_info_data *info)
+{
+  (void) info;
+  return Curl_ssl_supports(NULL, SSLSUPP_ECH);
+}
+#endif
+
 /*
  * Features table.
  *
@@ -445,6 +454,9 @@ static const struct feat features_table[] = {
 #ifdef DEBUGBUILD
   FEATURE("Debug",       NULL,                CURL_VERSION_DEBUG),
 #endif
+#if defined(USE_SSL) && defined(USE_ECH)
+  FEATURE("ECH",         ech_present,         0),
+#endif
 #ifdef USE_GSASL
   FEATURE("gsasl",       NULL,                CURL_VERSION_GSASL),
 #endif
@@ -454,19 +466,20 @@ static const struct feat features_table[] = {
 #ifndef CURL_DISABLE_HSTS
   FEATURE("HSTS",        NULL,                CURL_VERSION_HSTS),
 #endif
-#if defined(USE_NGHTTP2) || defined(USE_HYPER)
+#if defined(USE_NGHTTP2)
   FEATURE("HTTP2",       NULL,                CURL_VERSION_HTTP2),
 #endif
-#if defined(ENABLE_QUIC)
+#if defined(USE_HTTP3)
   FEATURE("HTTP3",       NULL,                CURL_VERSION_HTTP3),
 #endif
-#if defined(USE_SSL) && !defined(CURL_DISABLE_PROXY)
+#if defined(USE_SSL) && !defined(CURL_DISABLE_PROXY) && \
+  !defined(CURL_DISABLE_HTTP)
   FEATURE("HTTPS-proxy", https_proxy_present, CURL_VERSION_HTTPS_PROXY),
 #endif
-#if defined(USE_LIBIDN2) || defined(USE_WIN32_IDN)
+#if defined(USE_LIBIDN2) || defined(USE_WIN32_IDN) || defined(USE_APPLE_IDN)
   FEATURE("IDN",         idn_present,         CURL_VERSION_IDN),
 #endif
-#ifdef ENABLE_IPV6
+#ifdef USE_IPV6
   FEATURE("IPv6",        NULL,                CURL_VERSION_IPV6),
 #endif
 #ifdef USE_KERBEROS5
@@ -485,10 +498,6 @@ static const struct feat features_table[] = {
 #ifdef USE_NTLM
   FEATURE("NTLM",        NULL,                CURL_VERSION_NTLM),
 #endif
-#if !defined(CURL_DISABLE_HTTP) && defined(USE_NTLM) && \
-  defined(NTLM_WB_ENABLED)
-  FEATURE("NTLM_WB",     NULL,                CURL_VERSION_NTLM_WB),
-#endif
 #if defined(USE_LIBPSL)
   FEATURE("PSL",         NULL,                CURL_VERSION_PSL),
 #endif
@@ -510,7 +519,7 @@ static const struct feat features_table[] = {
 #ifdef CURLDEBUG
   FEATURE("TrackMemory", NULL,                CURL_VERSION_CURLDEBUG),
 #endif
-#if defined(WIN32) && defined(UNICODE) && defined(_UNICODE)
+#if defined(_WIN32) && defined(UNICODE) && defined(_UNICODE)
   FEATURE("Unicode",     NULL,                CURL_VERSION_UNICODE),
 #endif
 #ifdef USE_UNIX_SOCKETS
@@ -560,7 +569,8 @@ static curl_version_info_data version_info = {
   NULL, /* zstd version */
   NULL, /* Hyper version */
   NULL, /* gsasl version */
-  feature_names
+  feature_names,
+  NULL  /* rtmp version */
 };
 
 curl_version_info_data *curl_version_info(CURLversion stamp)
@@ -635,7 +645,7 @@ curl_version_info_data *curl_version_info(CURLversion stamp)
   }
 #endif
 
-#ifdef ENABLE_QUIC
+#ifdef USE_HTTP3
   {
     static char quicbuffer[80];
     Curl_quic_ver(quicbuffer, sizeof(quicbuffer));
@@ -668,5 +678,13 @@ curl_version_info_data *curl_version_info(CURLversion stamp)
   feature_names[n] = NULL;  /* Terminate array. */
   version_info.features = features;
 
+#ifdef USE_LIBRTMP
+  {
+    static char rtmp_version[30];
+    Curl_rtmp_version(rtmp_version, sizeof(rtmp_version));
+    version_info.rtmp_version = rtmp_version;
+  }
+#endif
+
   return &version_info;
 }
diff --git a/vendor/curl/lib/version_win32.c b/vendor/curl/lib/version_win32.c
index 872d5b4f3c..e0f239e15d 100644
--- a/vendor/curl/lib/version_win32.c
+++ b/vendor/curl/lib/version_win32.c
@@ -24,7 +24,7 @@
 
 #include "curl_setup.h"
 
-#if defined(WIN32)
+#if defined(_WIN32)
 
 #include 
 #include "version_win32.h"
@@ -316,4 +316,4 @@ bool curlx_verify_windows_version(const unsigned int majorVersion,
   return matched;
 }
 
-#endif /* WIN32 */
+#endif /* _WIN32 */
diff --git a/vendor/curl/lib/version_win32.h b/vendor/curl/lib/version_win32.h
index 3899174a31..95c066112c 100644
--- a/vendor/curl/lib/version_win32.h
+++ b/vendor/curl/lib/version_win32.h
@@ -26,7 +26,7 @@
 
 #include "curl_setup.h"
 
-#if defined(WIN32)
+#if defined(_WIN32)
 
 /* Version condition */
 typedef enum {
@@ -51,6 +51,6 @@ bool curlx_verify_windows_version(const unsigned int majorVersion,
                                   const PlatformIdentifier platform,
                                   const VersionCondition condition);
 
-#endif /* WIN32 */
+#endif /* _WIN32 */
 
 #endif /* HEADER_CURL_VERSION_WIN32_H */
diff --git a/vendor/curl/lib/vquic/curl_msh3.c b/vendor/curl/lib/vquic/curl_msh3.c
index 6bd0d23316..d49af6ea4c 100644
--- a/vendor/curl/lib/vquic/curl_msh3.c
+++ b/vendor/curl/lib/vquic/curl_msh3.c
@@ -27,6 +27,7 @@
 #ifdef USE_MSH3
 
 #include "urldata.h"
+#include "hash.h"
 #include "timeval.h"
 #include "multiif.h"
 #include "sendf.h"
@@ -38,6 +39,7 @@
 #include "http1.h"
 #include "curl_msh3.h"
 #include "socketpair.h"
+#include "vtls/vtls.h"
 #include "vquic/vquic.h"
 
 /* The last 3 #include files should be in this order */
@@ -45,6 +47,10 @@
 #include "curl_memory.h"
 #include "memdebug.h"
 
+#ifdef CURL_DISABLE_SOCKETPAIR
+#error "MSH3 cannot be build with CURL_DISABLE_SOCKETPAIR set"
+#endif
+
 #define H3_STREAM_WINDOW_SIZE (128 * 1024)
 #define H3_STREAM_CHUNK_SIZE   (16 * 1024)
 #define H3_STREAM_RECV_CHUNKS \
@@ -113,6 +119,7 @@ struct cf_msh3_ctx {
   struct cf_call_data call_data;
   struct curltime connect_started;   /* time the current attempt started */
   struct curltime handshake_at;      /* time connect handshake finished */
+  struct Curl_hash streams;          /* hash `data->id` to `stream_ctx` */
   /* Flags written by msh3/msquic thread */
   bool handshake_complete;
   bool handshake_succeeded;
@@ -122,6 +129,8 @@ struct cf_msh3_ctx {
   BIT(active);
 };
 
+static struct cf_msh3_ctx *h3_get_msh3_ctx(struct Curl_easy *data);
+
 /* How to access `call_data` from a cf_msh3 filter */
 #undef CF_CTX_CALL_DATA
 #define CF_CTX_CALL_DATA(cf)  \
@@ -148,18 +157,26 @@ struct stream_ctx {
   bool recv_header_complete;
 };
 
-#define H3_STREAM_CTX(d)    ((struct stream_ctx *)(((d) && (d)->req.p.http)? \
-                             ((struct HTTP *)(d)->req.p.http)->h3_ctx \
-                               : NULL))
-#define H3_STREAM_LCTX(d)   ((struct HTTP *)(d)->req.p.http)->h3_ctx
-#define H3_STREAM_ID(d)     (H3_STREAM_CTX(d)? \
-                             H3_STREAM_CTX(d)->id : -2)
+#define H3_STREAM_CTX(ctx,data)   ((struct stream_ctx *)((data && ctx)? \
+                Curl_hash_offt_get(&(ctx)->streams, (data)->id) : NULL))
+
+static void h3_stream_ctx_free(struct stream_ctx *stream)
+{
+  Curl_bufq_free(&stream->recvbuf);
+  free(stream);
+}
 
+static void h3_stream_hash_free(void *stream)
+{
+  DEBUGASSERT(stream);
+  h3_stream_ctx_free((struct stream_ctx *)stream);
+}
 
 static CURLcode h3_data_setup(struct Curl_cfilter *cf,
                               struct Curl_easy *data)
 {
-  struct stream_ctx *stream = H3_STREAM_CTX(data);
+  struct cf_msh3_ctx *ctx = cf->ctx;
+  struct stream_ctx *stream = H3_STREAM_CTX(ctx, data);
 
   if(stream)
     return CURLE_OK;
@@ -168,25 +185,29 @@ static CURLcode h3_data_setup(struct Curl_cfilter *cf,
   if(!stream)
     return CURLE_OUT_OF_MEMORY;
 
-  H3_STREAM_LCTX(data) = stream;
   stream->req = ZERO_NULL;
   msh3_lock_initialize(&stream->recv_lock);
   Curl_bufq_init2(&stream->recvbuf, H3_STREAM_CHUNK_SIZE,
                   H3_STREAM_RECV_CHUNKS, BUFQ_OPT_SOFT_LIMIT);
   CURL_TRC_CF(data, cf, "data setup");
+
+  if(!Curl_hash_offt_set(&ctx->streams, data->id, stream)) {
+    h3_stream_ctx_free(stream);
+    return CURLE_OUT_OF_MEMORY;
+  }
+
   return CURLE_OK;
 }
 
 static void h3_data_done(struct Curl_cfilter *cf, struct Curl_easy *data)
 {
-  struct stream_ctx *stream = H3_STREAM_CTX(data);
+  struct cf_msh3_ctx *ctx = cf->ctx;
+  struct stream_ctx *stream = H3_STREAM_CTX(ctx, data);
 
   (void)cf;
   if(stream) {
     CURL_TRC_CF(data, cf, "easy handle is done");
-    Curl_bufq_free(&stream->recvbuf);
-    free(stream);
-    H3_STREAM_LCTX(data) = NULL;
+    Curl_hash_offt_remove(&ctx->streams, data->id);
   }
 }
 
@@ -199,8 +220,8 @@ static void drain_stream_from_other_thread(struct Curl_easy *data,
   bits = CURL_CSELECT_IN;
   if(stream && !stream->upload_done)
     bits |= CURL_CSELECT_OUT;
-  if(data->state.dselect_bits != bits) {
-    data->state.dselect_bits = bits;
+  if(data->state.select_bits != bits) {
+    data->state.select_bits = bits;
     /* cannot expire from other thread */
   }
 }
@@ -208,15 +229,16 @@ static void drain_stream_from_other_thread(struct Curl_easy *data,
 static void drain_stream(struct Curl_cfilter *cf,
                          struct Curl_easy *data)
 {
-  struct stream_ctx *stream = H3_STREAM_CTX(data);
+  struct cf_msh3_ctx *ctx = cf->ctx;
+  struct stream_ctx *stream = H3_STREAM_CTX(ctx, data);
   unsigned char bits;
 
   (void)cf;
   bits = CURL_CSELECT_IN;
   if(stream && !stream->upload_done)
     bits |= CURL_CSELECT_OUT;
-  if(data->state.dselect_bits != bits) {
-    data->state.dselect_bits = bits;
+  if(data->state.select_bits != bits) {
+    data->state.select_bits = bits;
     Curl_expire(data, 0, EXPIRE_RUN_NOW);
   }
 }
@@ -306,7 +328,8 @@ static int decode_status_code(const char *value, size_t len)
 static CURLcode write_resp_raw(struct Curl_easy *data,
                                const void *mem, size_t memlen)
 {
-  struct stream_ctx *stream = H3_STREAM_CTX(data);
+  struct cf_msh3_ctx *ctx = h3_get_msh3_ctx(data);
+  struct stream_ctx *stream = H3_STREAM_CTX(ctx, data);
   CURLcode result = CURLE_OK;
   ssize_t nwritten;
 
@@ -332,10 +355,12 @@ static void MSH3_CALL msh3_header_received(MSH3_REQUEST *Request,
                                            const MSH3_HEADER *hd)
 {
   struct Curl_easy *data = userp;
-  struct stream_ctx *stream = H3_STREAM_CTX(data);
+  struct cf_msh3_ctx *ctx = h3_get_msh3_ctx(data);
+  struct stream_ctx *stream = H3_STREAM_CTX(ctx, data);
   CURLcode result;
   (void)Request;
 
+  DEBUGF(infof(data, "[MSH3] header received, stream=%d", !!stream));
   if(!stream || stream->recv_header_complete) {
     return;
   }
@@ -381,7 +406,8 @@ static bool MSH3_CALL msh3_data_received(MSH3_REQUEST *Request,
                                          const uint8_t *buf)
 {
   struct Curl_easy *data = IfContext;
-  struct stream_ctx *stream = H3_STREAM_CTX(data);
+  struct cf_msh3_ctx *ctx = h3_get_msh3_ctx(data);
+  struct stream_ctx *stream = H3_STREAM_CTX(ctx, data);
   CURLcode result;
   bool rv = FALSE;
 
@@ -420,7 +446,8 @@ static void MSH3_CALL msh3_complete(MSH3_REQUEST *Request, void *IfContext,
                                     bool aborted, uint64_t error)
 {
   struct Curl_easy *data = IfContext;
-  struct stream_ctx *stream = H3_STREAM_CTX(data);
+  struct cf_msh3_ctx *ctx = h3_get_msh3_ctx(data);
+  struct stream_ctx *stream = H3_STREAM_CTX(ctx, data);
 
   (void)Request;
   if(!stream)
@@ -439,7 +466,8 @@ static void MSH3_CALL msh3_shutdown_complete(MSH3_REQUEST *Request,
                                              void *IfContext)
 {
   struct Curl_easy *data = IfContext;
-  struct stream_ctx *stream = H3_STREAM_CTX(data);
+  struct cf_msh3_ctx *ctx = h3_get_msh3_ctx(data);
+  struct stream_ctx *stream = H3_STREAM_CTX(ctx, data);
 
   if(!stream)
     return;
@@ -451,7 +479,8 @@ static void MSH3_CALL msh3_data_sent(MSH3_REQUEST *Request,
                                      void *IfContext, void *SendContext)
 {
   struct Curl_easy *data = IfContext;
-  struct stream_ctx *stream = H3_STREAM_CTX(data);
+  struct cf_msh3_ctx *ctx = h3_get_msh3_ctx(data);
+  struct stream_ctx *stream = H3_STREAM_CTX(ctx, data);
   if(!stream)
     return;
   (void)Request;
@@ -463,7 +492,8 @@ static ssize_t recv_closed_stream(struct Curl_cfilter *cf,
                                   struct Curl_easy *data,
                                   CURLcode *err)
 {
-  struct stream_ctx *stream = H3_STREAM_CTX(data);
+  struct cf_msh3_ctx *ctx = cf->ctx;
+  struct stream_ctx *stream = H3_STREAM_CTX(ctx, data);
   ssize_t nread = -1;
 
   if(!stream) {
@@ -496,7 +526,8 @@ static ssize_t recv_closed_stream(struct Curl_cfilter *cf,
 
 static void set_quic_expire(struct Curl_cfilter *cf, struct Curl_easy *data)
 {
-  struct stream_ctx *stream = H3_STREAM_CTX(data);
+  struct cf_msh3_ctx *ctx = cf->ctx;
+  struct stream_ctx *stream = H3_STREAM_CTX(ctx, data);
 
   /* we have no indication from msh3 when it would be a good time
    * to juggle the connection again. So, we compromise by calling
@@ -513,17 +544,17 @@ static void set_quic_expire(struct Curl_cfilter *cf, struct Curl_easy *data)
 static ssize_t cf_msh3_recv(struct Curl_cfilter *cf, struct Curl_easy *data,
                             char *buf, size_t len, CURLcode *err)
 {
-  struct stream_ctx *stream = H3_STREAM_CTX(data);
+  struct cf_msh3_ctx *ctx = cf->ctx;
+  struct stream_ctx *stream = H3_STREAM_CTX(ctx, data);
   ssize_t nread = -1;
   struct cf_call_data save;
 
-  (void)cf;
+  CURL_TRC_CF(data, cf, "cf_recv(len=%zu), stream=%d", len, !!stream);
   if(!stream) {
     *err = CURLE_RECV_ERROR;
     return -1;
   }
   CF_DATA_SAVE(save, cf, data);
-  CURL_TRC_CF(data, cf, "req: recv with %zu byte buffer", len);
 
   msh3_lock_acquire(&stream->recv_lock);
 
@@ -565,7 +596,7 @@ static ssize_t cf_msh3_send(struct Curl_cfilter *cf, struct Curl_easy *data,
                             const void *buf, size_t len, CURLcode *err)
 {
   struct cf_msh3_ctx *ctx = cf->ctx;
-  struct stream_ctx *stream = H3_STREAM_CTX(data);
+  struct stream_ctx *stream = H3_STREAM_CTX(ctx, data);
   struct h1_req_parser h1;
   struct dynhds h2_headers;
   MSH3_HEADER *nva = NULL;
@@ -672,37 +703,32 @@ static ssize_t cf_msh3_send(struct Curl_cfilter *cf, struct Curl_easy *data,
   return nwritten;
 }
 
-static int cf_msh3_get_select_socks(struct Curl_cfilter *cf,
-                                    struct Curl_easy *data,
-                                    curl_socket_t *socks)
+static void cf_msh3_adjust_pollset(struct Curl_cfilter *cf,
+                                   struct Curl_easy *data,
+                                   struct easy_pollset *ps)
 {
   struct cf_msh3_ctx *ctx = cf->ctx;
-  struct stream_ctx *stream = H3_STREAM_CTX(data);
-  int bitmap = GETSOCK_BLANK;
+  struct stream_ctx *stream = H3_STREAM_CTX(ctx, data);
   struct cf_call_data save;
 
   CF_DATA_SAVE(save, cf, data);
   if(stream && ctx->sock[SP_LOCAL] != CURL_SOCKET_BAD) {
-    socks[0] = ctx->sock[SP_LOCAL];
-
     if(stream->recv_error) {
-      bitmap |= GETSOCK_READSOCK(0);
+      Curl_pollset_add_in(data, ps, ctx->sock[SP_LOCAL]);
       drain_stream(cf, data);
     }
     else if(stream->req) {
-      bitmap |= GETSOCK_READSOCK(0);
+      Curl_pollset_add_out(data, ps, ctx->sock[SP_LOCAL]);
       drain_stream(cf, data);
     }
   }
-  CURL_TRC_CF(data, cf, "select_sock -> %d", bitmap);
-  CF_DATA_RESTORE(cf, save);
-  return bitmap;
 }
 
 static bool cf_msh3_data_pending(struct Curl_cfilter *cf,
                                  const struct Curl_easy *data)
 {
-  struct stream_ctx *stream = H3_STREAM_CTX(data);
+  struct cf_msh3_ctx *ctx = cf->ctx;
+  struct stream_ctx *stream = H3_STREAM_CTX(ctx, data);
   struct cf_call_data save;
   bool pending = FALSE;
 
@@ -723,23 +749,6 @@ static bool cf_msh3_data_pending(struct Curl_cfilter *cf,
   return pending;
 }
 
-static void cf_msh3_active(struct Curl_cfilter *cf, struct Curl_easy *data)
-{
-  struct cf_msh3_ctx *ctx = cf->ctx;
-
-  /* use this socket from now on */
-  cf->conn->sock[cf->sockindex] = ctx->sock[SP_LOCAL];
-  /* the first socket info gets set at conn and data */
-  if(cf->sockindex == FIRSTSOCKET) {
-    cf->conn->remote_addr = &ctx->addr;
-  #ifdef ENABLE_IPV6
-    cf->conn->bits.ipv6 = (ctx->addr.family == AF_INET6)? TRUE : FALSE;
-  #endif
-    Curl_persistconninfo(data, cf->conn, ctx->l_ip, ctx->l_port);
-  }
-  ctx->active = TRUE;
-}
-
 static CURLcode h3_data_pause(struct Curl_cfilter *cf,
                               struct Curl_easy *data,
                               bool pause)
@@ -755,7 +764,8 @@ static CURLcode cf_msh3_data_event(struct Curl_cfilter *cf,
                                    struct Curl_easy *data,
                                    int event, int arg1, void *arg2)
 {
-  struct stream_ctx *stream = H3_STREAM_CTX(data);
+  struct cf_msh3_ctx *ctx = cf->ctx;
+  struct stream_ctx *stream = H3_STREAM_CTX(ctx, data);
   struct cf_call_data save;
   CURLcode result = CURLE_OK;
 
@@ -786,10 +796,6 @@ static CURLcode cf_msh3_data_event(struct Curl_cfilter *cf,
       }
     }
     break;
-  case CF_CTRL_CONN_INFO_UPDATE:
-    CURL_TRC_CF(data, cf, "req: update info");
-    cf_msh3_active(cf, data);
-    break;
   default:
     break;
   }
@@ -802,14 +808,21 @@ static CURLcode cf_connect_start(struct Curl_cfilter *cf,
                                  struct Curl_easy *data)
 {
   struct cf_msh3_ctx *ctx = cf->ctx;
-  bool verify = !!cf->conn->ssl_config.verifypeer;
+  struct ssl_primary_config *conn_config;
   MSH3_ADDR addr = {0};
   CURLcode result;
+  bool verify;
+
+  Curl_hash_offt_init(&ctx->streams, 63, h3_stream_hash_free);
+  conn_config = Curl_ssl_cf_get_primary_config(cf);
+  if(!conn_config)
+    return CURLE_FAILED_INIT;
+  verify = !!conn_config->verifypeer;
 
   memcpy(&addr, &ctx->addr.sa_addr, ctx->addr.addrlen);
   MSH3_SET_PORT(&addr, (uint16_t)cf->conn->remote_port);
 
-  if(verify && (cf->conn->ssl_config.CAfile || cf->conn->ssl_config.CApath)) {
+  if(verify && (conn_config->CAfile || conn_config->CApath)) {
     /* TODO: need a way to provide trust anchors to MSH3 */
 #ifdef DEBUGBUILD
     /* we need this for our test cases to run */
@@ -927,6 +940,7 @@ static void cf_msh3_close(struct Curl_cfilter *cf, struct Curl_easy *data)
       MsH3ApiClose(ctx->api);
       ctx->api = NULL;
     }
+    Curl_hash_destroy(&ctx->streams);
 
     if(ctx->active) {
       /* We share our socket at cf->conn->sock[cf->sockindex] when active.
@@ -1025,7 +1039,7 @@ struct Curl_cftype Curl_cft_http3 = {
   cf_msh3_connect,
   cf_msh3_close,
   Curl_cf_def_get_host,
-  cf_msh3_get_select_socks,
+  cf_msh3_adjust_pollset,
   cf_msh3_data_pending,
   cf_msh3_send,
   cf_msh3_recv,
@@ -1035,6 +1049,20 @@ struct Curl_cftype Curl_cft_http3 = {
   cf_msh3_query,
 };
 
+static struct cf_msh3_ctx *h3_get_msh3_ctx(struct Curl_easy *data)
+{
+  if(data && data->conn) {
+    struct Curl_cfilter *cf = data->conn->cfilter[FIRSTSOCKET];
+    while(cf) {
+      if(cf->cft == &Curl_cft_http3)
+        return cf->ctx;
+      cf = cf->next;
+    }
+  }
+  DEBUGF(infof(data, "no filter context found"));
+  return NULL;
+}
+
 CURLcode Curl_cf_msh3_create(struct Curl_cfilter **pcf,
                              struct Curl_easy *data,
                              struct connectdata *conn,
@@ -1047,7 +1075,7 @@ CURLcode Curl_cf_msh3_create(struct Curl_cfilter **pcf,
   (void)data;
   (void)conn;
   (void)ai; /* TODO: msh3 resolves itself? */
-  ctx = calloc(sizeof(*ctx), 1);
+  ctx = calloc(1, sizeof(*ctx));
   if(!ctx) {
     result = CURLE_OUT_OF_MEMORY;
     goto out;
diff --git a/vendor/curl/lib/vquic/curl_ngtcp2.c b/vendor/curl/lib/vquic/curl_ngtcp2.c
index 03e911d184..0d9d87f34a 100644
--- a/vendor/curl/lib/vquic/curl_ngtcp2.c
+++ b/vendor/curl/lib/vquic/curl_ngtcp2.c
@@ -30,7 +30,7 @@
 
 #ifdef USE_OPENSSL
 #include 
-#ifdef OPENSSL_IS_BORINGSSL
+#if defined(OPENSSL_IS_BORINGSSL) || defined(OPENSSL_IS_AWSLC)
 #include 
 #else
 #include 
@@ -41,10 +41,10 @@
 #include "vtls/gtls.h"
 #elif defined(USE_WOLFSSL)
 #include 
-#include "vtls/wolfssl.h"
 #endif
 
 #include "urldata.h"
+#include "hash.h"
 #include "sendf.h"
 #include "strdup.h"
 #include "rand.h"
@@ -59,8 +59,10 @@
 #include "http1.h"
 #include "select.h"
 #include "inet_pton.h"
+#include "transfer.h"
 #include "vquic.h"
 #include "vquic_int.h"
+#include "vquic-tls.h"
 #include "vtls/keylog.h"
 #include "vtls/vtls.h"
 #include "curl_ngtcp2.h"
@@ -73,12 +75,8 @@
 #include "memdebug.h"
 
 
-#define H3_ALPN_H3_29 "\x5h3-29"
-#define H3_ALPN_H3 "\x2h3"
-
 #define QUIC_MAX_STREAMS (256*1024)
 #define QUIC_MAX_DATA (1*1024*1024)
-#define QUIC_IDLE_TIMEOUT (60*NGTCP2_SECONDS)
 #define QUIC_HANDSHAKE_TIMEOUT (10*NGTCP2_SECONDS)
 
 /* A stream window is the maximum amount we need to buffer for
@@ -102,25 +100,6 @@
           (H3_STREAM_WINDOW_SIZE / H3_STREAM_CHUNK_SIZE)
 
 
-#ifdef USE_OPENSSL
-#define QUIC_CIPHERS                                                          \
-  "TLS_AES_128_GCM_SHA256:TLS_AES_256_GCM_SHA384:TLS_CHACHA20_"               \
-  "POLY1305_SHA256:TLS_AES_128_CCM_SHA256"
-#define QUIC_GROUPS "P-256:X25519:P-384:P-521"
-#elif defined(USE_GNUTLS)
-#define QUIC_PRIORITY \
-  "NORMAL:-VERS-ALL:+VERS-TLS1.3:-CIPHER-ALL:+AES-128-GCM:+AES-256-GCM:" \
-  "+CHACHA20-POLY1305:+AES-128-CCM:-GROUP-ALL:+GROUP-SECP256R1:" \
-  "+GROUP-X25519:+GROUP-SECP384R1:+GROUP-SECP521R1:" \
-  "%DISABLE_TLS13_COMPAT_MODE"
-#elif defined(USE_WOLFSSL)
-#define QUIC_CIPHERS                                                          \
-  "TLS_AES_128_GCM_SHA256:TLS_AES_256_GCM_SHA384:TLS_CHACHA20_"               \
-  "POLY1305_SHA256:TLS_AES_128_CCM_SHA256"
-#define QUIC_GROUPS "P-256:P-384:P-521"
-#endif
-
-
 /*
  * Store ngtcp2 version info in this buffer.
  */
@@ -134,6 +113,8 @@ void Curl_ngtcp2_ver(char *p, size_t len)
 
 struct cf_ngtcp2_ctx {
   struct cf_quic_ctx q;
+  struct ssl_peer peer;
+  struct curl_tls_ctx tls;
   ngtcp2_path connected_path;
   ngtcp2_conn *qconn;
   ngtcp2_cid dcid;
@@ -143,29 +124,21 @@ struct cf_ngtcp2_ctx {
   ngtcp2_transport_params transport_params;
   ngtcp2_ccerr last_error;
   ngtcp2_crypto_conn_ref conn_ref;
-#ifdef USE_OPENSSL
-  SSL_CTX *sslctx;
-  SSL *ssl;
-#elif defined(USE_GNUTLS)
-  struct gtls_instance *gtls;
-#elif defined(USE_WOLFSSL)
-  WOLFSSL_CTX *sslctx;
-  WOLFSSL *ssl;
-#endif
   struct cf_call_data call_data;
   nghttp3_conn *h3conn;
   nghttp3_settings h3settings;
   struct curltime started_at;        /* time the current attempt started */
   struct curltime handshake_at;      /* time connect handshake finished */
-  struct curltime first_byte_at;     /* when first byte was recvd */
   struct curltime reconnect_at;      /* time the next attempt should start */
   struct bufc_pool stream_bufcp;     /* chunk pool for streams */
+  struct dynbuf scratch;             /* temp buffer for header construction */
+  struct Curl_hash streams;          /* hash `data->id` to `h3_stream_ctx` */
   size_t max_stream_window;          /* max flow window for one stream */
+  uint64_t max_idle_ms;              /* max idle time for QUIC connection */
+  uint64_t used_bidi_streams;        /* bidi streams we have opened */
+  uint64_t max_bidi_streams;         /* max bidi streams we can open */
   int qlogfd;
-  BIT(got_first_byte);               /* if first byte was received */
-#ifdef USE_OPENSSL
-  BIT(x509_store_setup);             /* if x509 store has been set up */
-#endif
+  BIT(conn_closed);                  /* connection is closed */
 };
 
 /* How to access `call_data` from a cf_ngtcp2 filter */
@@ -173,38 +146,57 @@ struct cf_ngtcp2_ctx {
 #define CF_CTX_CALL_DATA(cf)  \
   ((struct cf_ngtcp2_ctx *)(cf)->ctx)->call_data
 
+struct pkt_io_ctx;
+static CURLcode cf_progress_ingress(struct Curl_cfilter *cf,
+                                    struct Curl_easy *data,
+                                    struct pkt_io_ctx *pktx);
+static CURLcode cf_progress_egress(struct Curl_cfilter *cf,
+                                   struct Curl_easy *data,
+                                   struct pkt_io_ctx *pktx);
+
 /**
  * All about the H3 internals of a stream
  */
 struct h3_stream_ctx {
-  int64_t id; /* HTTP/3 protocol identifier */
+  curl_int64_t id; /* HTTP/3 protocol identifier */
   struct bufq sendbuf;   /* h3 request body */
-  struct bufq recvbuf;   /* h3 response body */
   struct h1_req_parser h1; /* h1 request parsing */
   size_t sendbuf_len_in_flight; /* sendbuf amount "in flight" */
   size_t upload_blocked_len; /* the amount written last and EGAINed */
-  size_t recv_buf_nonflow; /* buffered bytes, not counting for flow control */
-  uint64_t error3; /* HTTP/3 stream error code */
+  curl_uint64_t error3; /* HTTP/3 stream error code */
   curl_off_t upload_left; /* number of request bytes left to upload */
   int status_code; /* HTTP status code */
+  CURLcode xfer_result; /* result from xfer_resp_write(_hd) */
   bool resp_hds_complete; /* we have a complete, final response */
   bool closed; /* TRUE on stream close */
   bool reset;  /* TRUE on stream reset */
   bool send_closed; /* stream is local closed */
+  BIT(quic_flow_blocked); /* stream is blocked by QUIC flow control */
 };
 
-#define H3_STREAM_CTX(d)  ((struct h3_stream_ctx *)(((d) && (d)->req.p.http)? \
-                           ((struct HTTP *)(d)->req.p.http)->h3_ctx \
-                             : NULL))
-#define H3_STREAM_LCTX(d) ((struct HTTP *)(d)->req.p.http)->h3_ctx
-#define H3_STREAM_ID(d)   (H3_STREAM_CTX(d)? \
-                           H3_STREAM_CTX(d)->id : -2)
+#define H3_STREAM_CTX(ctx,data)   ((struct h3_stream_ctx *)(\
+            data? Curl_hash_offt_get(&(ctx)->streams, (data)->id) : NULL))
+#define H3_STREAM_CTX_ID(ctx,id)  ((struct h3_stream_ctx *)(\
+            Curl_hash_offt_get(&(ctx)->streams, (id))))
+
+static void h3_stream_ctx_free(struct h3_stream_ctx *stream)
+{
+  Curl_bufq_free(&stream->sendbuf);
+  Curl_h1_req_parse_free(&stream->h1);
+  free(stream);
+}
+
+static void h3_stream_hash_free(void *stream)
+{
+  DEBUGASSERT(stream);
+  h3_stream_ctx_free((struct h3_stream_ctx *)stream);
+}
 
 static CURLcode h3_data_setup(struct Curl_cfilter *cf,
                               struct Curl_easy *data)
 {
   struct cf_ngtcp2_ctx *ctx = cf->ctx;
-  struct h3_stream_ctx *stream = H3_STREAM_CTX(data);
+  struct h3_stream_ctx *stream = H3_STREAM_CTX(ctx, data);
 
   if(!data || !data->req.p.http) {
     failf(data, "initialization failure, transfer not http initialized");
@@ -223,29 +215,96 @@ static CURLcode h3_data_setup(struct Curl_cfilter *cf,
   Curl_bufq_initp(&stream->sendbuf, &ctx->stream_bufcp,
                   H3_STREAM_SEND_CHUNKS, BUFQ_OPT_NONE);
   stream->sendbuf_len_in_flight = 0;
-  /* on recv, we need a flexible buffer limit since we also write
-   * headers to it that are not counted against the nghttp3 flow limits. */
-  Curl_bufq_initp(&stream->recvbuf, &ctx->stream_bufcp,
-                  H3_STREAM_RECV_CHUNKS, BUFQ_OPT_SOFT_LIMIT);
-  stream->recv_buf_nonflow = 0;
   Curl_h1_req_parse_init(&stream->h1, H1_PARSE_DEFAULT_MAX_LINE_LEN);
 
-  H3_STREAM_LCTX(data) = stream;
+  if(!Curl_hash_offt_set(&ctx->streams, data->id, stream)) {
+    h3_stream_ctx_free(stream);
+    return CURLE_OUT_OF_MEMORY;
+  }
+
   return CURLE_OK;
 }
 
-static void h3_data_done(struct Curl_cfilter *cf, struct Curl_easy *data)
+static void cf_ngtcp2_stream_close(struct Curl_cfilter *cf,
+                                   struct Curl_easy *data,
+                                   struct h3_stream_ctx *stream)
 {
-  struct h3_stream_ctx *stream = H3_STREAM_CTX(data);
+  struct cf_ngtcp2_ctx *ctx = cf->ctx;
+  DEBUGASSERT(data);
+  DEBUGASSERT(stream);
+  if(!stream->closed && ctx->qconn && ctx->h3conn) {
+    CURLcode result;
+
+    nghttp3_conn_set_stream_user_data(ctx->h3conn, stream->id, NULL);
+    ngtcp2_conn_set_stream_user_data(ctx->qconn, stream->id, NULL);
+    stream->closed = TRUE;
+    (void)ngtcp2_conn_shutdown_stream(ctx->qconn, 0, stream->id,
+                                      NGHTTP3_H3_REQUEST_CANCELLED);
+    result = cf_progress_egress(cf, data, NULL);
+    if(result)
+      CURL_TRC_CF(data, cf, "[%" CURL_PRId64 "] cancel stream -> %d",
+                  stream->id, result);
+  }
+}
 
+static void h3_data_done(struct Curl_cfilter *cf, struct Curl_easy *data)
+{
+  struct cf_ngtcp2_ctx *ctx = cf->ctx;
+  struct h3_stream_ctx *stream = H3_STREAM_CTX(ctx, data);
   (void)cf;
   if(stream) {
-    CURL_TRC_CF(data, cf, "[%"PRId64"] easy handle is done", stream->id);
-    Curl_bufq_free(&stream->sendbuf);
-    Curl_bufq_free(&stream->recvbuf);
-    Curl_h1_req_parse_free(&stream->h1);
-    free(stream);
-    H3_STREAM_LCTX(data) = NULL;
+    CURL_TRC_CF(data, cf, "[%" CURL_PRId64 "] easy handle is done",
+                stream->id);
+    cf_ngtcp2_stream_close(cf, data, stream);
+    Curl_hash_offt_remove(&ctx->streams, data->id);
+  }
+}
+
+static struct Curl_easy *get_stream_easy(struct Curl_cfilter *cf,
+                                         struct Curl_easy *data,
+                                         int64_t stream_id,
+                                         struct h3_stream_ctx **pstream)
+{
+  struct cf_ngtcp2_ctx *ctx = cf->ctx;
+  struct Curl_easy *sdata;
+  struct h3_stream_ctx *stream;
+
+  (void)cf;
+  stream = H3_STREAM_CTX(ctx, data);
+  if(stream && stream->id == stream_id) {
+    *pstream = stream;
+    return data;
+  }
+  else {
+    DEBUGASSERT(data->multi);
+    for(sdata = data->multi->easyp; sdata; sdata = sdata->next) {
+      if(sdata->conn != data->conn)
+        continue;
+      stream = H3_STREAM_CTX(ctx, sdata);
+      if(stream && stream->id == stream_id) {
+        *pstream = stream;
+        return sdata;
+      }
+    }
+  }
+  *pstream = NULL;
+  return NULL;
+}
+
+static void h3_drain_stream(struct Curl_cfilter *cf,
+                            struct Curl_easy *data)
+{
+  struct cf_ngtcp2_ctx *ctx = cf->ctx;
+  struct h3_stream_ctx *stream = H3_STREAM_CTX(ctx, data);
+  unsigned char bits;
+
+  (void)cf;
+  bits = CURL_CSELECT_IN;
+  if(stream && stream->upload_left && !stream->send_closed)
+    bits |= CURL_CSELECT_OUT;
+  if(data->state.select_bits != bits) {
+    data->state.select_bits = bits;
+    Curl_expire(data, 0, EXPIRE_RUN_NOW);
   }
 }
 
@@ -261,10 +320,14 @@ struct pkt_io_ctx {
   ngtcp2_path_storage ps;
 };
 
-static ngtcp2_tstamp timestamp(void)
+static void pktx_update_time(struct pkt_io_ctx *pktx,
+                             struct Curl_cfilter *cf)
 {
-  struct curltime ct = Curl_now();
-  return ct.tv_sec * NGTCP2_SECONDS + ct.tv_usec * NGTCP2_MICROSECONDS;
+  struct cf_ngtcp2_ctx *ctx = cf->ctx;
+
+  vquic_ctx_update_time(&ctx->q);
+  pktx->ts = ctx->q.last_op.tv_sec * NGTCP2_SECONDS +
+             ctx->q.last_op.tv_usec * NGTCP2_MICROSECONDS;
 }
 
 static void pktx_init(struct pkt_io_ctx *pktx,
@@ -273,17 +336,11 @@ static void pktx_init(struct pkt_io_ctx *pktx,
 {
   pktx->cf = cf;
   pktx->data = data;
-  pktx->ts = timestamp();
   pktx->pkt_count = 0;
   ngtcp2_path_storage_zero(&pktx->ps);
+  pktx_update_time(pktx, cf);
 }
 
-static CURLcode cf_progress_ingress(struct Curl_cfilter *cf,
-                                    struct Curl_easy *data,
-                                    struct pkt_io_ctx *pktx);
-static CURLcode cf_progress_egress(struct Curl_cfilter *cf,
-                                   struct Curl_easy *data,
-                                   struct pkt_io_ctx *pktx);
 static int cb_h3_acked_req_body(nghttp3_conn *conn, int64_t stream_id,
                                    uint64_t datalen, void *user_data,
                                    void *stream_user_data);
@@ -354,418 +411,75 @@ static void quic_settings(struct cf_ngtcp2_ctx *ctx,
   t->initial_max_stream_data_uni = ctx->max_stream_window;
   t->initial_max_streams_bidi = QUIC_MAX_STREAMS;
   t->initial_max_streams_uni = QUIC_MAX_STREAMS;
-  t->max_idle_timeout = QUIC_IDLE_TIMEOUT;
+  t->max_idle_timeout = (ctx->max_idle_ms * NGTCP2_MILLISECONDS);
   if(ctx->qlogfd != -1) {
     s->qlog_write = qlog_callback;
   }
 }
 
-#ifdef USE_OPENSSL
-static void keylog_callback(const SSL *ssl, const char *line)
-{
-  (void)ssl;
-  Curl_tls_keylog_write_line(line);
-}
-#elif defined(USE_GNUTLS)
-static int keylog_callback(gnutls_session_t session, const char *label,
-                    const gnutls_datum_t *secret)
-{
-  gnutls_datum_t crandom;
-  gnutls_datum_t srandom;
-
-  gnutls_session_get_random(session, &crandom, &srandom);
-  if(crandom.size != 32) {
-    return -1;
-  }
-
-  Curl_tls_keylog_write(label, crandom.data, secret->data, secret->size);
-  return 0;
-}
-#elif defined(USE_WOLFSSL)
-#if defined(HAVE_SECRET_CALLBACK)
-static void keylog_callback(const WOLFSSL *ssl, const char *line)
-{
-  (void)ssl;
-  Curl_tls_keylog_write_line(line);
-}
-#endif
-#endif
-
 static int init_ngh3_conn(struct Curl_cfilter *cf);
 
-#ifdef USE_OPENSSL
-static CURLcode quic_ssl_ctx(SSL_CTX **pssl_ctx,
-                             struct Curl_cfilter *cf, struct Curl_easy *data)
-{
-  struct cf_ngtcp2_ctx *ctx = cf->ctx;
-  struct connectdata *conn = cf->conn;
-  CURLcode result = CURLE_FAILED_INIT;
-  SSL_CTX *ssl_ctx = SSL_CTX_new(TLS_method());
-
-  if(!ssl_ctx) {
-    result = CURLE_OUT_OF_MEMORY;
-    goto out;
-  }
-
-#ifdef OPENSSL_IS_BORINGSSL
-  if(ngtcp2_crypto_boringssl_configure_client_context(ssl_ctx) != 0) {
-    failf(data, "ngtcp2_crypto_boringssl_configure_client_context failed");
-    goto out;
-  }
-#else
-  if(ngtcp2_crypto_quictls_configure_client_context(ssl_ctx) != 0) {
-    failf(data, "ngtcp2_crypto_quictls_configure_client_context failed");
-    goto out;
-  }
-#endif
-
-  SSL_CTX_set_default_verify_paths(ssl_ctx);
-
-#ifdef OPENSSL_IS_BORINGSSL
-  if(SSL_CTX_set1_curves_list(ssl_ctx, QUIC_GROUPS) != 1) {
-    failf(data, "SSL_CTX_set1_curves_list failed");
-    goto out;
-  }
-#else
-  if(SSL_CTX_set_ciphersuites(ssl_ctx, QUIC_CIPHERS) != 1) {
-    char error_buffer[256];
-    ERR_error_string_n(ERR_get_error(), error_buffer, sizeof(error_buffer));
-    failf(data, "SSL_CTX_set_ciphersuites: %s", error_buffer);
-    goto out;
-  }
-
-  if(SSL_CTX_set1_groups_list(ssl_ctx, QUIC_GROUPS) != 1) {
-    failf(data, "SSL_CTX_set1_groups_list failed");
-    goto out;
-  }
-#endif
-
-  /* Open the file if a TLS or QUIC backend has not done this before. */
-  Curl_tls_keylog_open();
-  if(Curl_tls_keylog_enabled()) {
-    SSL_CTX_set_keylog_callback(ssl_ctx, keylog_callback);
-  }
-
-  /* OpenSSL always tries to verify the peer, this only says whether it should
-   * fail to connect if the verification fails, or if it should continue
-   * anyway. In the latter case the result of the verification is checked with
-   * SSL_get_verify_result() below. */
-  SSL_CTX_set_verify(ssl_ctx, conn->ssl_config.verifypeer ?
-                     SSL_VERIFY_PEER : SSL_VERIFY_NONE, NULL);
-
-  /* give application a chance to interfere with SSL set up. */
-  if(data->set.ssl.fsslctx) {
-    /* When a user callback is installed to modify the SSL_CTX,
-     * we need to do the full initialization before calling it.
-     * See: #11800 */
-    if(!ctx->x509_store_setup) {
-      result = Curl_ssl_setup_x509_store(cf, data, ssl_ctx);
-      if(result)
-        goto out;
-      ctx->x509_store_setup = TRUE;
-    }
-    Curl_set_in_callback(data, true);
-    result = (*data->set.ssl.fsslctx)(data, ssl_ctx,
-                                      data->set.ssl.fsslctxp);
-    Curl_set_in_callback(data, false);
-    if(result) {
-      failf(data, "error signaled by ssl ctx callback");
-      goto out;
-    }
-  }
-  result = CURLE_OK;
-
-out:
-  *pssl_ctx = result? NULL : ssl_ctx;
-  if(result && ssl_ctx)
-    SSL_CTX_free(ssl_ctx);
-  return result;
-}
-
-static CURLcode quic_set_client_cert(struct Curl_cfilter *cf,
-                                     struct Curl_easy *data)
+static int cb_handshake_completed(ngtcp2_conn *tconn, void *user_data)
 {
-  struct cf_ngtcp2_ctx *ctx = cf->ctx;
-  SSL_CTX *ssl_ctx = ctx->sslctx;
-  const struct ssl_config_data *ssl_config;
-
-  ssl_config = Curl_ssl_get_config(data, FIRSTSOCKET);
-  DEBUGASSERT(ssl_config);
-
-  if(ssl_config->primary.clientcert || ssl_config->primary.cert_blob
-     || ssl_config->cert_type) {
-    return Curl_ossl_set_client_cert(
-        data, ssl_ctx, ssl_config->primary.clientcert,
-        ssl_config->primary.cert_blob, ssl_config->cert_type,
-        ssl_config->key, ssl_config->key_blob,
-        ssl_config->key_type, ssl_config->key_passwd);
-  }
-
-  return CURLE_OK;
+  (void)user_data;
+  (void)tconn;
+  return 0;
 }
 
-/** SSL callbacks ***/
+static void cf_ngtcp2_conn_close(struct Curl_cfilter *cf,
+                                 struct Curl_easy *data);
 
-static CURLcode quic_init_ssl(struct Curl_cfilter *cf,
-                              struct Curl_easy *data)
+static bool cf_ngtcp2_err_is_fatal(int code)
 {
-  struct cf_ngtcp2_ctx *ctx = cf->ctx;
-  const uint8_t *alpn = NULL;
-  size_t alpnlen = 0;
-  unsigned char checkip[16];
-
-  DEBUGASSERT(!ctx->ssl);
-  ctx->ssl = SSL_new(ctx->sslctx);
-
-  SSL_set_app_data(ctx->ssl, &ctx->conn_ref);
-  SSL_set_connect_state(ctx->ssl);
-  SSL_set_quic_use_legacy_codepoint(ctx->ssl, 0);
-
-  alpn = (const uint8_t *)H3_ALPN_H3_29 H3_ALPN_H3;
-  alpnlen = sizeof(H3_ALPN_H3_29) - 1 + sizeof(H3_ALPN_H3) - 1;
-  if(alpn)
-    SSL_set_alpn_protos(ctx->ssl, alpn, (int)alpnlen);
-
-  /* set SNI */
-  if((0 == Curl_inet_pton(AF_INET, cf->conn->host.name, checkip))
-#ifdef ENABLE_IPV6
-     && (0 == Curl_inet_pton(AF_INET6, cf->conn->host.name, checkip))
-#endif
-     ) {
-    char *snihost = Curl_ssl_snihost(data, cf->conn->host.name, NULL);
-    if(!snihost || !SSL_set_tlsext_host_name(ctx->ssl, snihost)) {
-      failf(data, "Failed set SNI");
-      SSL_free(ctx->ssl);
-      ctx->ssl = NULL;
-      return CURLE_QUIC_CONNECT_ERROR;
-    }
-  }
-  return CURLE_OK;
+  return (NGTCP2_ERR_FATAL >= code) ||
+         (NGTCP2_ERR_DROP_CONN == code) ||
+         (NGTCP2_ERR_IDLE_CLOSE == code);
 }
-#elif defined(USE_GNUTLS)
-static CURLcode quic_init_ssl(struct Curl_cfilter *cf,
-                              struct Curl_easy *data)
-{
-  struct cf_ngtcp2_ctx *ctx = cf->ctx;
-  CURLcode result;
-  gnutls_datum_t alpn[2];
-  /* this will need some attention when HTTPS proxy over QUIC get fixed */
-  const char * const hostname = cf->conn->host.name;
-  long * const pverifyresult = &data->set.ssl.certverifyresult;
-  int rc;
-
-  DEBUGASSERT(ctx->gtls == NULL);
-  ctx->gtls = calloc(1, sizeof(*(ctx->gtls)));
-  if(!ctx->gtls)
-    return CURLE_OUT_OF_MEMORY;
-
-  result = gtls_client_init(data, &cf->conn->ssl_config, &data->set.ssl,
-                            hostname, ctx->gtls, pverifyresult);
-  if(result)
-    return result;
-
-  gnutls_session_set_ptr(ctx->gtls->session, &ctx->conn_ref);
-
-  if(ngtcp2_crypto_gnutls_configure_client_session(ctx->gtls->session) != 0) {
-    CURL_TRC_CF(data, cf,
-                "ngtcp2_crypto_gnutls_configure_client_session failed\n");
-    return CURLE_QUIC_CONNECT_ERROR;
-  }
 
-  rc = gnutls_priority_set_direct(ctx->gtls->session, QUIC_PRIORITY, NULL);
-  if(rc < 0) {
-    CURL_TRC_CF(data, cf, "gnutls_priority_set_direct failed: %s\n",
-                gnutls_strerror(rc));
-    return CURLE_QUIC_CONNECT_ERROR;
-  }
-
-  /* Open the file if a TLS or QUIC backend has not done this before. */
-  Curl_tls_keylog_open();
-  if(Curl_tls_keylog_enabled()) {
-    gnutls_session_set_keylog_function(ctx->gtls->session, keylog_callback);
-  }
-
-  /* strip the first byte (the length) from NGHTTP3_ALPN_H3 */
-  alpn[0].data = (unsigned char *)H3_ALPN_H3_29 + 1;
-  alpn[0].size = sizeof(H3_ALPN_H3_29) - 2;
-  alpn[1].data = (unsigned char *)H3_ALPN_H3 + 1;
-  alpn[1].size = sizeof(H3_ALPN_H3) - 2;
-
-  gnutls_alpn_set_protocols(ctx->gtls->session,
-                            alpn, 2, GNUTLS_ALPN_MANDATORY);
-  return CURLE_OK;
-}
-#elif defined(USE_WOLFSSL)
-
-static CURLcode quic_ssl_ctx(WOLFSSL_CTX **pssl_ctx,
-                             struct Curl_cfilter *cf, struct Curl_easy *data)
+static void cf_ngtcp2_err_set(struct Curl_cfilter *cf,
+                              struct Curl_easy *data, int code)
 {
-  struct connectdata *conn = cf->conn;
-  CURLcode result = CURLE_FAILED_INIT;
-  WOLFSSL_CTX *ssl_ctx = wolfSSL_CTX_new(wolfTLSv1_3_client_method());
-
-  if(!ssl_ctx) {
-    result = CURLE_OUT_OF_MEMORY;
-    goto out;
-  }
-
-  if(ngtcp2_crypto_wolfssl_configure_client_context(ssl_ctx) != 0) {
-    failf(data, "ngtcp2_crypto_wolfssl_configure_client_context failed");
-    goto out;
-  }
-
-  wolfSSL_CTX_set_default_verify_paths(ssl_ctx);
-
-  if(wolfSSL_CTX_set_cipher_list(ssl_ctx, QUIC_CIPHERS) != 1) {
-    char error_buffer[256];
-    ERR_error_string_n(ERR_get_error(), error_buffer, sizeof(error_buffer));
-    failf(data, "wolfSSL_CTX_set_cipher_list: %s", error_buffer);
-    goto out;
-  }
-
-  if(wolfSSL_CTX_set1_groups_list(ssl_ctx, (char *)QUIC_GROUPS) != 1) {
-    failf(data, "SSL_CTX_set1_groups_list failed");
-    goto out;
-  }
-
-  /* Open the file if a TLS or QUIC backend has not done this before. */
-  Curl_tls_keylog_open();
-  if(Curl_tls_keylog_enabled()) {
-#if defined(HAVE_SECRET_CALLBACK)
-    wolfSSL_CTX_set_keylog_callback(ssl_ctx, keylog_callback);
-#else
-    failf(data, "wolfSSL was built without keylog callback");
-    goto out;
-#endif
-  }
-
-  if(conn->ssl_config.verifypeer) {
-    const char * const ssl_cafile = conn->ssl_config.CAfile;
-    const char * const ssl_capath = conn->ssl_config.CApath;
-
-    wolfSSL_CTX_set_verify(ssl_ctx, SSL_VERIFY_PEER, NULL);
-    if(conn->ssl_config.CAfile || conn->ssl_config.CApath) {
-      /* tell wolfSSL where to find CA certificates that are used to verify
-         the server's certificate. */
-      if(!wolfSSL_CTX_load_verify_locations(ssl_ctx, ssl_cafile, ssl_capath)) {
-        /* Fail if we insist on successfully verifying the server. */
-        failf(data, "error setting certificate verify locations:"
-              "  CAfile: %s CApath: %s",
-              ssl_cafile ? ssl_cafile : "none",
-              ssl_capath ? ssl_capath : "none");
-        goto out;
-      }
-      infof(data, " CAfile: %s", ssl_cafile ? ssl_cafile : "none");
-      infof(data, " CApath: %s", ssl_capath ? ssl_capath : "none");
+  struct cf_ngtcp2_ctx *ctx = cf->ctx;
+  if(!ctx->last_error.error_code) {
+    if(NGTCP2_ERR_CRYPTO == code) {
+      ngtcp2_ccerr_set_tls_alert(&ctx->last_error,
+                                 ngtcp2_conn_get_tls_alert(ctx->qconn),
+                                 NULL, 0);
     }
-#ifdef CURL_CA_FALLBACK
     else {
-      /* verifying the peer without any CA certificates won't work so
-         use wolfssl's built-in default as fallback */
-      wolfSSL_CTX_set_default_verify_paths(ssl_ctx);
-    }
-#endif
-  }
-  else {
-    wolfSSL_CTX_set_verify(ssl_ctx, SSL_VERIFY_NONE, NULL);
-  }
-
-  /* give application a chance to interfere with SSL set up. */
-  if(data->set.ssl.fsslctx) {
-    Curl_set_in_callback(data, true);
-    result = (*data->set.ssl.fsslctx)(data, ssl_ctx,
-                                      data->set.ssl.fsslctxp);
-    Curl_set_in_callback(data, false);
-    if(result) {
-      failf(data, "error signaled by ssl ctx callback");
-      goto out;
+      ngtcp2_ccerr_set_liberr(&ctx->last_error, code, NULL, 0);
     }
   }
-  result = CURLE_OK;
-
-out:
-  *pssl_ctx = result? NULL : ssl_ctx;
-  if(result && ssl_ctx)
-    SSL_CTX_free(ssl_ctx);
-  return result;
+  if(cf_ngtcp2_err_is_fatal(code))
+    cf_ngtcp2_conn_close(cf, data);
 }
 
-/** SSL callbacks ***/
-
-static CURLcode quic_init_ssl(struct Curl_cfilter *cf,
-                              struct Curl_easy *data)
+static bool cf_ngtcp2_h3_err_is_fatal(int code)
 {
-  struct cf_ngtcp2_ctx *ctx = cf->ctx;
-  const uint8_t *alpn = NULL;
-  size_t alpnlen = 0;
-  /* this will need some attention when HTTPS proxy over QUIC get fixed */
-  const char * const hostname = cf->conn->host.name;
-
-  (void)data;
-  DEBUGASSERT(!ctx->ssl);
-  ctx->ssl = wolfSSL_new(ctx->sslctx);
-
-  wolfSSL_set_app_data(ctx->ssl, &ctx->conn_ref);
-  wolfSSL_set_connect_state(ctx->ssl);
-  wolfSSL_set_quic_use_legacy_codepoint(ctx->ssl, 0);
-
-  alpn = (const uint8_t *)H3_ALPN_H3_29 H3_ALPN_H3;
-  alpnlen = sizeof(H3_ALPN_H3_29) - 1 + sizeof(H3_ALPN_H3) - 1;
-  if(alpn)
-    wolfSSL_set_alpn_protos(ctx->ssl, alpn, (int)alpnlen);
-
-  /* set SNI */
-  wolfSSL_UseSNI(ctx->ssl, WOLFSSL_SNI_HOST_NAME,
-                 hostname, (unsigned short)strlen(hostname));
-
-  return CURLE_OK;
+  return (NGHTTP3_ERR_FATAL >= code) ||
+         (NGHTTP3_ERR_H3_CLOSED_CRITICAL_STREAM == code);
 }
-#endif /* defined(USE_WOLFSSL) */
 
-static int cb_handshake_completed(ngtcp2_conn *tconn, void *user_data)
+static void cf_ngtcp2_h3_err_set(struct Curl_cfilter *cf,
+                                 struct Curl_easy *data, int code)
 {
-  (void)user_data;
-  (void)tconn;
-  return 0;
-}
-
-static void report_consumed_data(struct Curl_cfilter *cf,
-                                 struct Curl_easy *data,
-                                 size_t consumed)
-{
-  struct h3_stream_ctx *stream = H3_STREAM_CTX(data);
   struct cf_ngtcp2_ctx *ctx = cf->ctx;
-
-  if(!stream)
-    return;
-  /* the HTTP/1.1 response headers are written to the buffer, but
-   * consuming those does not count against flow control. */
-  if(stream->recv_buf_nonflow) {
-    if(consumed >= stream->recv_buf_nonflow) {
-      consumed -= stream->recv_buf_nonflow;
-      stream->recv_buf_nonflow = 0;
-    }
-    else {
-      stream->recv_buf_nonflow -= consumed;
-      consumed = 0;
-    }
-  }
-  if(consumed > 0) {
-    CURL_TRC_CF(data, cf, "[%" PRId64 "] ACK %zu bytes of DATA",
-                stream->id, consumed);
-    ngtcp2_conn_extend_max_stream_offset(ctx->qconn, stream->id,
-                                         consumed);
-    ngtcp2_conn_extend_max_offset(ctx->qconn, consumed);
+  if(!ctx->last_error.error_code) {
+    ngtcp2_ccerr_set_application_error(&ctx->last_error,
+      nghttp3_err_infer_quic_app_error_code(code), NULL, 0);
   }
+  if(cf_ngtcp2_h3_err_is_fatal(code))
+    cf_ngtcp2_conn_close(cf, data);
 }
 
 static int cb_recv_stream_data(ngtcp2_conn *tconn, uint32_t flags,
-                               int64_t stream_id, uint64_t offset,
+                               int64_t sid, uint64_t offset,
                                const uint8_t *buf, size_t buflen,
                                void *user_data, void *stream_user_data)
 {
   struct Curl_cfilter *cf = user_data;
   struct cf_ngtcp2_ctx *ctx = cf->ctx;
+  curl_int64_t stream_id = (curl_int64_t)sid;
   nghttp3_ssize nconsumed;
   int fin = (flags & NGTCP2_STREAM_DATA_FLAG_FIN) ? 1 : 0;
   struct Curl_easy *data = stream_user_data;
@@ -774,12 +488,18 @@ static int cb_recv_stream_data(ngtcp2_conn *tconn, uint32_t flags,
 
   nconsumed =
     nghttp3_conn_read_stream(ctx->h3conn, stream_id, buf, buflen, fin);
-  CURL_TRC_CF(data, cf, "[%" PRId64 "] read_stream(len=%zu) -> %zd",
-              stream_id, buflen, nconsumed);
+  if(!data)
+    data = CF_DATA_CURRENT(cf);
+  if(data)
+    CURL_TRC_CF(data, cf, "[%" CURL_PRId64 "] read_stream(len=%zu) -> %zd",
+                stream_id, buflen, nconsumed);
   if(nconsumed < 0) {
-    ngtcp2_ccerr_set_application_error(
-      &ctx->last_error,
-      nghttp3_err_infer_quic_app_error_code((int)nconsumed), NULL, 0);
+    struct h3_stream_ctx *stream = H3_STREAM_CTX_ID(ctx, stream_id);
+    if(data && stream) {
+      CURL_TRC_CF(data, cf, "[%" CURL_PRId64 "] error on known stream, "
+                  "reset=%d, closed=%d",
+                  stream_id, stream->reset, stream->closed);
+    }
     return NGTCP2_ERR_CALLBACK_FAILURE;
   }
 
@@ -807,7 +527,7 @@ cb_acked_stream_data_offset(ngtcp2_conn *tconn, int64_t stream_id,
   (void)stream_user_data;
 
   rv = nghttp3_conn_add_ack_offset(ctx->h3conn, stream_id, datalen);
-  if(rv) {
+  if(rv && rv != NGHTTP3_ERR_STREAM_NOT_FOUND) {
     return NGTCP2_ERR_CALLBACK_FAILURE;
   }
 
@@ -815,41 +535,45 @@ cb_acked_stream_data_offset(ngtcp2_conn *tconn, int64_t stream_id,
 }
 
 static int cb_stream_close(ngtcp2_conn *tconn, uint32_t flags,
-                           int64_t stream3_id, uint64_t app_error_code,
+                           int64_t sid, uint64_t app_error_code,
                            void *user_data, void *stream_user_data)
 {
   struct Curl_cfilter *cf = user_data;
-  struct Curl_easy *data = stream_user_data;
   struct cf_ngtcp2_ctx *ctx = cf->ctx;
+  struct Curl_easy *data = stream_user_data;
+  curl_int64_t stream_id = (curl_int64_t)sid;
   int rv;
 
   (void)tconn;
-  (void)data;
   /* stream is closed... */
+  if(!data)
+    data = CF_DATA_CURRENT(cf);
+  if(!data)
+    return NGTCP2_ERR_CALLBACK_FAILURE;
 
   if(!(flags & NGTCP2_STREAM_CLOSE_FLAG_APP_ERROR_CODE_SET)) {
     app_error_code = NGHTTP3_H3_NO_ERROR;
   }
 
-  rv = nghttp3_conn_close_stream(ctx->h3conn, stream3_id,
-                                 app_error_code);
-  CURL_TRC_CF(data, cf, "[%" PRId64 "] quic close(err=%"
-              PRIu64 ") -> %d", stream3_id, app_error_code, rv);
-  if(rv) {
-    ngtcp2_ccerr_set_application_error(
-      &ctx->last_error, nghttp3_err_infer_quic_app_error_code(rv), NULL, 0);
+  rv = nghttp3_conn_close_stream(ctx->h3conn, stream_id, app_error_code);
+  CURL_TRC_CF(data, cf, "[%" CURL_PRId64 "] quic close(app_error=%"
+              CURL_PRIu64 ") -> %d", stream_id, (curl_uint64_t)app_error_code,
+              rv);
+  if(rv && rv != NGHTTP3_ERR_STREAM_NOT_FOUND) {
+    cf_ngtcp2_h3_err_set(cf, data, rv);
     return NGTCP2_ERR_CALLBACK_FAILURE;
   }
 
   return 0;
 }
 
-static int cb_stream_reset(ngtcp2_conn *tconn, int64_t stream_id,
+static int cb_stream_reset(ngtcp2_conn *tconn, int64_t sid,
                            uint64_t final_size, uint64_t app_error_code,
                            void *user_data, void *stream_user_data)
 {
   struct Curl_cfilter *cf = user_data;
   struct cf_ngtcp2_ctx *ctx = cf->ctx;
+  curl_int64_t stream_id = (curl_int64_t)sid;
   struct Curl_easy *data = stream_user_data;
   int rv;
   (void)tconn;
@@ -858,8 +582,8 @@ static int cb_stream_reset(ngtcp2_conn *tconn, int64_t stream_id,
   (void)data;
 
   rv = nghttp3_conn_shutdown_stream_read(ctx->h3conn, stream_id);
-  CURL_TRC_CF(data, cf, "[%" PRId64 "] reset -> %d", stream_id, rv);
-  if(rv) {
+  CURL_TRC_CF(data, cf, "[%" CURL_PRId64 "] reset -> %d", stream_id, rv);
+  if(rv && rv != NGHTTP3_ERR_STREAM_NOT_FOUND) {
     return NGTCP2_ERR_CALLBACK_FAILURE;
   }
 
@@ -878,7 +602,7 @@ static int cb_stream_stop_sending(ngtcp2_conn *tconn, int64_t stream_id,
   (void)stream_user_data;
 
   rv = nghttp3_conn_shutdown_stream_read(ctx->h3conn, stream_id);
-  if(rv) {
+  if(rv && rv != NGHTTP3_ERR_STREAM_NOT_FOUND) {
     return NGTCP2_ERR_CALLBACK_FAILURE;
   }
 
@@ -889,29 +613,45 @@ static int cb_extend_max_local_streams_bidi(ngtcp2_conn *tconn,
                                             uint64_t max_streams,
                                             void *user_data)
 {
-  (void)tconn;
-  (void)max_streams;
-  (void)user_data;
+  struct Curl_cfilter *cf = user_data;
+  struct cf_ngtcp2_ctx *ctx = cf->ctx;
+  struct Curl_easy *data = CF_DATA_CURRENT(cf);
 
+  (void)tconn;
+  ctx->max_bidi_streams = max_streams;
+  if(data)
+    CURL_TRC_CF(data, cf, "max bidi streams now %" CURL_PRIu64
+                ", used %" CURL_PRIu64, (curl_uint64_t)ctx->max_bidi_streams,
+                (curl_uint64_t)ctx->used_bidi_streams);
   return 0;
 }
 
-static int cb_extend_max_stream_data(ngtcp2_conn *tconn, int64_t stream_id,
+static int cb_extend_max_stream_data(ngtcp2_conn *tconn, int64_t sid,
                                      uint64_t max_data, void *user_data,
                                      void *stream_user_data)
 {
   struct Curl_cfilter *cf = user_data;
   struct cf_ngtcp2_ctx *ctx = cf->ctx;
+  curl_int64_t stream_id = (curl_int64_t)sid;
+  struct Curl_easy *data = CF_DATA_CURRENT(cf);
+  struct Curl_easy *s_data;
+  struct h3_stream_ctx *stream;
   int rv;
   (void)tconn;
   (void)max_data;
   (void)stream_user_data;
 
   rv = nghttp3_conn_unblock_stream(ctx->h3conn, stream_id);
-  if(rv) {
+  if(rv && rv != NGHTTP3_ERR_STREAM_NOT_FOUND) {
     return NGTCP2_ERR_CALLBACK_FAILURE;
   }
-
+  s_data = get_stream_easy(cf, data, stream_id, &stream);
+  if(s_data && stream && stream->quic_flow_blocked) {
+    CURL_TRC_CF(s_data, cf, "[%" CURL_PRId64 "] unblock quic flow",
+                stream_id);
+    stream->quic_flow_blocked = FALSE;
+    h3_drain_stream(cf, s_data);
+  }
   return 0;
 }
 
@@ -1029,7 +769,7 @@ static CURLcode check_and_set_expiry(struct Curl_cfilter *cf,
     pktx = &local_pktx;
   }
   else {
-    pktx->ts = timestamp();
+    pktx_update_time(pktx, cf);
   }
 
   expiry = ngtcp2_conn_get_expiry(ctx->qconn);
@@ -1040,7 +780,7 @@ static CURLcode check_and_set_expiry(struct Curl_cfilter *cf,
       if(rv) {
         failf(data, "ngtcp2_conn_handle_expiry returned error: %s",
               ngtcp2_strerror(rv));
-        ngtcp2_ccerr_set_liberr(&ctx->last_error, rv, NULL, 0);
+        cf_ngtcp2_err_set(cf, data, rv);
         return CURLE_SEND_ERROR;
       }
       result = cf_progress_ingress(cf, data, pktx);
@@ -1064,56 +804,45 @@ static CURLcode check_and_set_expiry(struct Curl_cfilter *cf,
   return CURLE_OK;
 }
 
-static int cf_ngtcp2_get_select_socks(struct Curl_cfilter *cf,
+static void cf_ngtcp2_adjust_pollset(struct Curl_cfilter *cf,
                                       struct Curl_easy *data,
-                                      curl_socket_t *socks)
+                                      struct easy_pollset *ps)
 {
   struct cf_ngtcp2_ctx *ctx = cf->ctx;
-  struct SingleRequest *k = &data->req;
-  int rv = GETSOCK_BLANK;
-  struct h3_stream_ctx *stream = H3_STREAM_CTX(data);
-  struct cf_call_data save;
-
-  CF_DATA_SAVE(save, cf, data);
-  socks[0] = ctx->q.sockfd;
-
-  /* in HTTP/3 we can always get a frame, so check read */
-  rv |= GETSOCK_READSOCK(0);
+  bool want_recv, want_send;
 
-  /* we're still uploading or the HTTP/2 layer wants to send data */
-  if((k->keepon & KEEP_SENDBITS) == KEEP_SEND &&
-     ngtcp2_conn_get_cwnd_left(ctx->qconn) &&
-     ngtcp2_conn_get_max_data_left(ctx->qconn) &&
-     stream && nghttp3_conn_is_stream_writable(ctx->h3conn, stream->id))
-    rv |= GETSOCK_WRITESOCK(0);
+  if(!ctx->qconn)
+    return;
 
-  CF_DATA_RESTORE(cf, save);
-  return rv;
-}
+  Curl_pollset_check(data, ps, ctx->q.sockfd, &want_recv, &want_send);
+  if(want_recv || want_send) {
+    struct h3_stream_ctx *stream = H3_STREAM_CTX(ctx, data);
+    struct cf_call_data save;
+    bool c_exhaust, s_exhaust;
 
-static void h3_drain_stream(struct Curl_cfilter *cf,
-                            struct Curl_easy *data)
-{
-  struct h3_stream_ctx *stream = H3_STREAM_CTX(data);
-  unsigned char bits;
-
-  (void)cf;
-  bits = CURL_CSELECT_IN;
-  if(stream && stream->upload_left && !stream->send_closed)
-    bits |= CURL_CSELECT_OUT;
-  if(data->state.dselect_bits != bits) {
-    data->state.dselect_bits = bits;
-    Curl_expire(data, 0, EXPIRE_RUN_NOW);
+    CF_DATA_SAVE(save, cf, data);
+    c_exhaust = want_send && (!ngtcp2_conn_get_cwnd_left(ctx->qconn) ||
+                !ngtcp2_conn_get_max_data_left(ctx->qconn));
+    s_exhaust = want_send && stream && stream->id >= 0 &&
+                stream->quic_flow_blocked;
+    want_recv = (want_recv || c_exhaust || s_exhaust);
+    want_send = (!s_exhaust && want_send) ||
+                 !Curl_bufq_is_empty(&ctx->q.sendbuf);
+
+    Curl_pollset_set(data, ps, ctx->q.sockfd, want_recv, want_send);
+    CF_DATA_RESTORE(cf, save);
   }
 }
 
-static int cb_h3_stream_close(nghttp3_conn *conn, int64_t stream_id,
+static int cb_h3_stream_close(nghttp3_conn *conn, int64_t sid,
                               uint64_t app_error_code, void *user_data,
                               void *stream_user_data)
 {
   struct Curl_cfilter *cf = user_data;
+  struct cf_ngtcp2_ctx *ctx = cf->ctx;
   struct Curl_easy *data = stream_user_data;
-  struct h3_stream_ctx *stream = H3_STREAM_CTX(data);
+  curl_int64_t stream_id = (curl_int64_t)sid;
+  struct h3_stream_ctx *stream = H3_STREAM_CTX(ctx, data);
   (void)conn;
   (void)stream_id;
 
@@ -1122,64 +851,60 @@ static int cb_h3_stream_close(nghttp3_conn *conn, int64_t stream_id,
     return 0;
 
   stream->closed = TRUE;
-  stream->error3 = app_error_code;
+  stream->error3 = (curl_uint64_t)app_error_code;
   if(stream->error3 != NGHTTP3_H3_NO_ERROR) {
     stream->reset = TRUE;
     stream->send_closed = TRUE;
-    CURL_TRC_CF(data, cf, "[%" PRId64 "] RESET: error %" PRId64,
+    CURL_TRC_CF(data, cf, "[%" CURL_PRId64 "] RESET: error %" CURL_PRIu64,
                 stream->id, stream->error3);
   }
   else {
-    CURL_TRC_CF(data, cf, "[%" PRId64 "] CLOSED", stream->id);
+    CURL_TRC_CF(data, cf, "[%" CURL_PRId64 "] CLOSED", stream->id);
   }
-  data->req.keepon &= ~KEEP_SEND_HOLD;
   h3_drain_stream(cf, data);
   return 0;
 }
 
-/*
- * write_resp_raw() copies response data in raw format to the `data`'s
-  * receive buffer. If not enough space is available, it appends to the
- * `data`'s overflow buffer.
- */
-static CURLcode write_resp_raw(struct Curl_cfilter *cf,
-                               struct Curl_easy *data,
-                               const void *mem, size_t memlen,
-                               bool flow)
+static void h3_xfer_write_resp_hd(struct Curl_cfilter *cf,
+                                  struct Curl_easy *data,
+                                  struct h3_stream_ctx *stream,
+                                  const char *buf, size_t blen, bool eos)
 {
-  struct h3_stream_ctx *stream = H3_STREAM_CTX(data);
-  CURLcode result = CURLE_OK;
-  ssize_t nwritten;
 
-  (void)cf;
-  if(!stream) {
-    return CURLE_RECV_ERROR;
-  }
-  nwritten = Curl_bufq_write(&stream->recvbuf, mem, memlen, &result);
-  if(nwritten < 0) {
-    return result;
+  /* If we already encountered an error, skip further writes */
+  if(!stream->xfer_result) {
+    stream->xfer_result = Curl_xfer_write_resp_hd(data, buf, blen, eos);
+    if(stream->xfer_result)
+      CURL_TRC_CF(data, cf, "[%"CURL_PRId64"] error %d writing %zu "
+                  "bytes of headers", stream->id, stream->xfer_result, blen);
   }
+}
 
-  if(!flow)
-    stream->recv_buf_nonflow += (size_t)nwritten;
+static void h3_xfer_write_resp(struct Curl_cfilter *cf,
+                               struct Curl_easy *data,
+                               struct h3_stream_ctx *stream,
+                               const char *buf, size_t blen, bool eos)
+{
 
-  if((size_t)nwritten < memlen) {
-    /* This MUST not happen. Our recbuf is dimensioned to hold the
-     * full max_stream_window and then some for this very reason. */
-    DEBUGASSERT(0);
-    return CURLE_RECV_ERROR;
+  /* If we already encountered an error, skip further writes */
+  if(!stream->xfer_result) {
+    stream->xfer_result = Curl_xfer_write_resp(data, buf, blen, eos);
+    /* If the transfer write is errored, we do not want any more data */
+    if(stream->xfer_result) {
+      CURL_TRC_CF(data, cf, "[%"CURL_PRId64"] error %d writing %zu bytes "
+                  "of data", stream->id, stream->xfer_result, blen);
+    }
   }
-  return result;
 }
 
 static int cb_h3_recv_data(nghttp3_conn *conn, int64_t stream3_id,
-                           const uint8_t *buf, size_t buflen,
+                           const uint8_t *buf, size_t blen,
                            void *user_data, void *stream_user_data)
 {
   struct Curl_cfilter *cf = user_data;
+  struct cf_ngtcp2_ctx *ctx = cf->ctx;
   struct Curl_easy *data = stream_user_data;
-  struct h3_stream_ctx *stream = H3_STREAM_CTX(data);
-  CURLcode result;
+  struct h3_stream_ctx *stream = H3_STREAM_CTX(ctx, data);
 
   (void)conn;
   (void)stream3_id;
@@ -1187,14 +912,14 @@ static int cb_h3_recv_data(nghttp3_conn *conn, int64_t stream3_id,
   if(!stream)
     return NGHTTP3_ERR_CALLBACK_FAILURE;
 
-  result = write_resp_raw(cf, data, buf, buflen, TRUE);
-  if(result) {
-    CURL_TRC_CF(data, cf, "[%" PRId64 "] DATA len=%zu, ERROR receiving %d",
-                stream->id, buflen, result);
-    return NGHTTP3_ERR_CALLBACK_FAILURE;
+  h3_xfer_write_resp(cf, data, stream, (char *)buf, blen, FALSE);
+  if(blen) {
+    CURL_TRC_CF(data, cf, "[%" CURL_PRId64 "] ACK %zu bytes of DATA",
+                stream->id, blen);
+    ngtcp2_conn_extend_max_stream_offset(ctx->qconn, stream->id, blen);
+    ngtcp2_conn_extend_max_offset(ctx->qconn, blen);
   }
-  CURL_TRC_CF(data, cf, "[%" PRId64 "] DATA len=%zu", stream->id, buflen);
-  h3_drain_stream(cf, data);
+  CURL_TRC_CF(data, cf, "[%" CURL_PRId64 "] DATA len=%zu", stream->id, blen);
   return 0;
 }
 
@@ -1214,13 +939,14 @@ static int cb_h3_deferred_consume(nghttp3_conn *conn, int64_t stream3_id,
   return 0;
 }
 
-static int cb_h3_end_headers(nghttp3_conn *conn, int64_t stream_id,
+static int cb_h3_end_headers(nghttp3_conn *conn, int64_t sid,
                              int fin, void *user_data, void *stream_user_data)
 {
   struct Curl_cfilter *cf = user_data;
+  struct cf_ngtcp2_ctx *ctx = cf->ctx;
   struct Curl_easy *data = stream_user_data;
-  struct h3_stream_ctx *stream = H3_STREAM_CTX(data);
-  CURLcode result = CURLE_OK;
+  curl_int64_t stream_id = (curl_int64_t)sid;
+  struct h3_stream_ctx *stream = H3_STREAM_CTX(ctx, data);
   (void)conn;
   (void)stream_id;
   (void)fin;
@@ -1229,12 +955,9 @@ static int cb_h3_end_headers(nghttp3_conn *conn, int64_t stream_id,
   if(!stream)
     return 0;
   /* add a CRLF only if we've received some headers */
-  result = write_resp_raw(cf, data, "\r\n", 2, FALSE);
-  if(result) {
-    return -1;
-  }
+  h3_xfer_write_resp_hd(cf, data, stream, STRCONST("\r\n"), stream->closed);
 
-  CURL_TRC_CF(data, cf, "[%" PRId64 "] end_headers, status=%d",
+  CURL_TRC_CF(data, cf, "[%" CURL_PRId64 "] end_headers, status=%d",
               stream_id, stream->status_code);
   if(stream->status_code / 100 != 1) {
     stream->resp_hds_complete = TRUE;
@@ -1243,16 +966,18 @@ static int cb_h3_end_headers(nghttp3_conn *conn, int64_t stream_id,
   return 0;
 }
 
-static int cb_h3_recv_header(nghttp3_conn *conn, int64_t stream_id,
+static int cb_h3_recv_header(nghttp3_conn *conn, int64_t sid,
                              int32_t token, nghttp3_rcbuf *name,
                              nghttp3_rcbuf *value, uint8_t flags,
                              void *user_data, void *stream_user_data)
 {
   struct Curl_cfilter *cf = user_data;
+  struct cf_ngtcp2_ctx *ctx = cf->ctx;
+  curl_int64_t stream_id = (curl_int64_t)sid;
   nghttp3_vec h3name = nghttp3_rcbuf_get_buf(name);
   nghttp3_vec h3val = nghttp3_rcbuf_get_buf(value);
   struct Curl_easy *data = stream_user_data;
-  struct h3_stream_ctx *stream = H3_STREAM_CTX(data);
+  struct h3_stream_ctx *stream = H3_STREAM_CTX(ctx, data);
   CURLcode result = CURLE_OK;
   (void)conn;
   (void)stream_id;
@@ -1265,42 +990,45 @@ static int cb_h3_recv_header(nghttp3_conn *conn, int64_t stream_id,
     return 0;
 
   if(token == NGHTTP3_QPACK_TOKEN__STATUS) {
-    char line[14]; /* status line is always 13 characters long */
-    size_t ncopy;
 
     result = Curl_http_decode_status(&stream->status_code,
                                      (const char *)h3val.base, h3val.len);
     if(result)
       return -1;
-    ncopy = msnprintf(line, sizeof(line), "HTTP/3 %03d \r\n",
-                      stream->status_code);
-    CURL_TRC_CF(data, cf, "[%" PRId64 "] status: %s", stream_id, line);
-    result = write_resp_raw(cf, data, line, ncopy, FALSE);
+    Curl_dyn_reset(&ctx->scratch);
+    result = Curl_dyn_addn(&ctx->scratch, STRCONST("HTTP/3 "));
+    if(!result)
+      result = Curl_dyn_addn(&ctx->scratch,
+                             (const char *)h3val.base, h3val.len);
+    if(!result)
+      result = Curl_dyn_addn(&ctx->scratch, STRCONST(" \r\n"));
+    if(!result)
+      h3_xfer_write_resp_hd(cf, data, stream, Curl_dyn_ptr(&ctx->scratch),
+                            Curl_dyn_len(&ctx->scratch), FALSE);
+    CURL_TRC_CF(data, cf, "[%" CURL_PRId64 "] status: %s",
+                stream_id, Curl_dyn_ptr(&ctx->scratch));
     if(result) {
       return -1;
     }
   }
   else {
     /* store as an HTTP1-style header */
-    CURL_TRC_CF(data, cf, "[%" PRId64 "] header: %.*s: %.*s",
+    CURL_TRC_CF(data, cf, "[%" CURL_PRId64 "] header: %.*s: %.*s",
                 stream_id, (int)h3name.len, h3name.base,
                 (int)h3val.len, h3val.base);
-    result = write_resp_raw(cf, data, h3name.base, h3name.len, FALSE);
-    if(result) {
-      return -1;
-    }
-    result = write_resp_raw(cf, data, ": ", 2, FALSE);
-    if(result) {
-      return -1;
-    }
-    result = write_resp_raw(cf, data, h3val.base, h3val.len, FALSE);
-    if(result) {
-      return -1;
-    }
-    result = write_resp_raw(cf, data, "\r\n", 2, FALSE);
-    if(result) {
-      return -1;
-    }
+    Curl_dyn_reset(&ctx->scratch);
+    result = Curl_dyn_addn(&ctx->scratch,
+                           (const char *)h3name.base, h3name.len);
+    if(!result)
+      result = Curl_dyn_addn(&ctx->scratch, STRCONST(": "));
+    if(!result)
+      result = Curl_dyn_addn(&ctx->scratch,
+                             (const char *)h3val.base, h3val.len);
+    if(!result)
+      result = Curl_dyn_addn(&ctx->scratch, STRCONST("\r\n"));
+    if(!result)
+      h3_xfer_write_resp_hd(cf, data, stream, Curl_dyn_ptr(&ctx->scratch),
+                            Curl_dyn_len(&ctx->scratch), FALSE);
   }
   return 0;
 }
@@ -1324,11 +1052,12 @@ static int cb_h3_stop_sending(nghttp3_conn *conn, int64_t stream_id,
   return 0;
 }
 
-static int cb_h3_reset_stream(nghttp3_conn *conn, int64_t stream_id,
+static int cb_h3_reset_stream(nghttp3_conn *conn, int64_t sid,
                               uint64_t app_error_code, void *user_data,
                               void *stream_user_data) {
   struct Curl_cfilter *cf = user_data;
   struct cf_ngtcp2_ctx *ctx = cf->ctx;
+  curl_int64_t stream_id = (curl_int64_t)sid;
   struct Curl_easy *data = stream_user_data;
   int rv;
   (void)conn;
@@ -1336,7 +1065,7 @@ static int cb_h3_reset_stream(nghttp3_conn *conn, int64_t stream_id,
 
   rv = ngtcp2_conn_shutdown_stream_write(ctx->qconn, 0, stream_id,
                                          app_error_code);
-  CURL_TRC_CF(data, cf, "[%" PRId64 "] reset -> %d", stream_id, rv);
+  CURL_TRC_CF(data, cf, "[%" CURL_PRId64 "] reset -> %d", stream_id, rv);
   if(rv && rv != NGTCP2_ERR_STREAM_NOT_FOUND) {
     return NGTCP2_ERR_CALLBACK_FAILURE;
   }
@@ -1432,14 +1161,14 @@ static ssize_t recv_closed_stream(struct Curl_cfilter *cf,
   (void)cf;
   if(stream->reset) {
     failf(data,
-          "HTTP/3 stream %" PRId64 " reset by server", stream->id);
-    *err = stream->resp_hds_complete? CURLE_PARTIAL_FILE : CURLE_HTTP3;
+          "HTTP/3 stream %" CURL_PRId64 " reset by server", stream->id);
+    *err = data->req.bytecount? CURLE_PARTIAL_FILE : CURLE_HTTP3;
     goto out;
   }
   else if(!stream->resp_hds_complete) {
     failf(data,
-          "HTTP/3 stream %" PRId64 " was closed cleanly, but before getting"
-          " all response header fields, treated as error",
+          "HTTP/3 stream %" CURL_PRId64 " was closed cleanly, but before "
+          "getting all response header fields, treated as error",
           stream->id);
     *err = CURLE_HTTP3;
     goto out;
@@ -1453,15 +1182,16 @@ static ssize_t recv_closed_stream(struct Curl_cfilter *cf,
 
 /* incoming data frames on the h3 stream */
 static ssize_t cf_ngtcp2_recv(struct Curl_cfilter *cf, struct Curl_easy *data,
-                              char *buf, size_t len, CURLcode *err)
+                              char *buf, size_t blen, CURLcode *err)
 {
   struct cf_ngtcp2_ctx *ctx = cf->ctx;
-  struct h3_stream_ctx *stream = H3_STREAM_CTX(data);
+  struct h3_stream_ctx *stream = H3_STREAM_CTX(ctx, data);
   ssize_t nread = -1;
   struct cf_call_data save;
   struct pkt_io_ctx pktx;
 
   (void)ctx;
+  (void)buf;
 
   CF_DATA_SAVE(save, cf, data);
   DEBUGASSERT(cf->connected);
@@ -1472,51 +1202,30 @@ static ssize_t cf_ngtcp2_recv(struct Curl_cfilter *cf, struct Curl_easy *data,
 
   pktx_init(&pktx, cf, data);
 
-  if(!stream) {
+  if(!stream || ctx->conn_closed) {
     *err = CURLE_RECV_ERROR;
     goto out;
   }
 
-  if(!Curl_bufq_is_empty(&stream->recvbuf)) {
-    nread = Curl_bufq_read(&stream->recvbuf,
-                           (unsigned char *)buf, len, err);
-    if(nread < 0) {
-      CURL_TRC_CF(data, cf, "[%" PRId64 "] read recvbuf(len=%zu) "
-                  "-> %zd, %d", stream->id, len, nread, *err);
-      goto out;
-    }
-    report_consumed_data(cf, data, nread);
-  }
-
   if(cf_progress_ingress(cf, data, &pktx)) {
     *err = CURLE_RECV_ERROR;
     nread = -1;
     goto out;
   }
 
-  /* recvbuf had nothing before, maybe after progressing ingress? */
-  if(nread < 0 && !Curl_bufq_is_empty(&stream->recvbuf)) {
-    nread = Curl_bufq_read(&stream->recvbuf,
-                           (unsigned char *)buf, len, err);
-    if(nread < 0) {
-      CURL_TRC_CF(data, cf, "[%" PRId64 "] read recvbuf(len=%zu) "
-                  "-> %zd, %d", stream->id, len, nread, *err);
-      goto out;
-    }
-    report_consumed_data(cf, data, nread);
-  }
-
-  if(nread > 0) {
-    h3_drain_stream(cf, data);
-  }
-  else {
-    if(stream->closed) {
-      nread = recv_closed_stream(cf, data, stream, err);
-      goto out;
-    }
-    *err = CURLE_AGAIN;
+  if(stream->xfer_result) {
+    CURL_TRC_CF(data, cf, "[%" CURL_PRId64 "] xfer write failed", stream->id);
+    cf_ngtcp2_stream_close(cf, data, stream);
+    *err = stream->xfer_result;
     nread = -1;
+    goto out;
   }
+  else if(stream->closed) {
+    nread = recv_closed_stream(cf, data, stream, err);
+    goto out;
+  }
+  *err = CURLE_AGAIN;
+  nread = -1;
 
 out:
   if(cf_progress_egress(cf, data, &pktx)) {
@@ -1530,8 +1239,8 @@ static ssize_t cf_ngtcp2_recv(struct Curl_cfilter *cf, struct Curl_easy *data,
       nread = -1;
     }
   }
-  CURL_TRC_CF(data, cf, "[%" PRId64 "] cf_recv(len=%zu) -> %zd, %d",
-              stream? stream->id : -1, len, nread, *err);
+  CURL_TRC_CF(data, cf, "[%" CURL_PRId64 "] cf_recv(blen=%zu) -> %zd, %d",
+              stream? stream->id : -1, blen, nread, *err);
   CF_DATA_RESTORE(cf, save);
   return nread;
 }
@@ -1541,8 +1250,9 @@ static int cb_h3_acked_req_body(nghttp3_conn *conn, int64_t stream_id,
                                 void *stream_user_data)
 {
   struct Curl_cfilter *cf = user_data;
+  struct cf_ngtcp2_ctx *ctx = cf->ctx;
   struct Curl_easy *data = stream_user_data;
-  struct h3_stream_ctx *stream = H3_STREAM_CTX(data);
+  struct h3_stream_ctx *stream = H3_STREAM_CTX(ctx, data);
   size_t skiplen;
 
   (void)cf;
@@ -1561,15 +1271,9 @@ static int cb_h3_acked_req_body(nghttp3_conn *conn, int64_t stream_id,
   /* Everything ACKed, we resume upload processing */
   if(!stream->sendbuf_len_in_flight) {
     int rv = nghttp3_conn_resume_stream(conn, stream_id);
-    if(rv) {
+    if(rv && rv != NGHTTP3_ERR_STREAM_NOT_FOUND) {
       return NGTCP2_ERR_CALLBACK_FAILURE;
     }
-    if((data->req.keepon & KEEP_SEND_HOLD) &&
-       (data->req.keepon & KEEP_SEND)) {
-      data->req.keepon &= ~KEEP_SEND_HOLD;
-      h3_drain_stream(cf, data);
-      CURL_TRC_CF(data, cf, "[%" PRId64 "] unpausing acks", stream_id);
-    }
   }
   return 0;
 }
@@ -1581,8 +1285,9 @@ cb_h3_read_req_body(nghttp3_conn *conn, int64_t stream_id,
                     void *stream_user_data)
 {
   struct Curl_cfilter *cf = user_data;
+  struct cf_ngtcp2_ctx *ctx = cf->ctx;
   struct Curl_easy *data = stream_user_data;
-  struct h3_stream_ctx *stream = H3_STREAM_CTX(data);
+  struct h3_stream_ctx *stream = H3_STREAM_CTX(ctx, data);
   ssize_t nwritten = 0;
   size_t nvecs = 0;
   (void)cf;
@@ -1625,12 +1330,12 @@ cb_h3_read_req_body(nghttp3_conn *conn, int64_t stream_id,
   }
   else if(!nwritten) {
     /* Not EOF, and nothing to give, we signal WOULDBLOCK. */
-    CURL_TRC_CF(data, cf, "[%" PRId64 "] read req body -> AGAIN",
+    CURL_TRC_CF(data, cf, "[%" CURL_PRId64 "] read req body -> AGAIN",
                 stream->id);
     return NGHTTP3_ERR_WOULDBLOCK;
   }
 
-  CURL_TRC_CF(data, cf, "[%" PRId64 "] read req body -> "
+  CURL_TRC_CF(data, cf, "[%" CURL_PRId64 "] read req body -> "
               "%d vecs%s with %zu (buffered=%zu, left=%"
               CURL_FORMAT_CURL_OFF_T ")",
               stream->id, (int)nvecs,
@@ -1651,6 +1356,7 @@ static ssize_t h3_stream_open(struct Curl_cfilter *cf,
 {
   struct cf_ngtcp2_ctx *ctx = cf->ctx;
   struct h3_stream_ctx *stream = NULL;
+  int64_t sid;
   struct dynhds h2_headers;
   size_t nheader;
   nghttp3_nv *nva = NULL;
@@ -1665,8 +1371,12 @@ static ssize_t h3_stream_open(struct Curl_cfilter *cf,
   *err = h3_data_setup(cf, data);
   if(*err)
     goto out;
-  stream = H3_STREAM_CTX(data);
+  stream = H3_STREAM_CTX(ctx, data);
   DEBUGASSERT(stream);
+  if(!stream) {
+    *err = CURLE_FAILED_INIT;
+    goto out;
+  }
 
   nwritten = Curl_h1_req_parse_read(&stream->h1, buf, len, NULL, 0, err);
   if(nwritten < 0)
@@ -1702,12 +1412,15 @@ static ssize_t h3_stream_open(struct Curl_cfilter *cf,
     nva[i].flags = NGHTTP3_NV_FLAG_NONE;
   }
 
-  rc = ngtcp2_conn_open_bidi_stream(ctx->qconn, &stream->id, NULL);
+  rc = ngtcp2_conn_open_bidi_stream(ctx->qconn, &sid, data);
   if(rc) {
     failf(data, "can get bidi streams");
     *err = CURLE_SEND_ERROR;
+    nwritten = -1;
     goto out;
   }
+  stream->id = (curl_int64_t)sid;
+  ++ctx->used_bidi_streams;
 
   switch(data->state.httpreq) {
   case HTTPREQ_POST:
@@ -1738,12 +1451,12 @@ static ssize_t h3_stream_open(struct Curl_cfilter *cf,
   if(rc) {
     switch(rc) {
     case NGHTTP3_ERR_CONN_CLOSING:
-      CURL_TRC_CF(data, cf, "h3sid[%"PRId64"] failed to send, "
+      CURL_TRC_CF(data, cf, "h3sid[%" CURL_PRId64 "] failed to send, "
                   "connection is closing", stream->id);
       break;
     default:
-      CURL_TRC_CF(data, cf, "h3sid[%"PRId64"] failed to send -> %d (%s)",
-                  stream->id, rc, ngtcp2_strerror(rc));
+      CURL_TRC_CF(data, cf, "h3sid[%" CURL_PRId64 "] failed to send -> "
+                  "%d (%s)", stream->id, rc, ngtcp2_strerror(rc));
       break;
     }
     *err = CURLE_SEND_ERROR;
@@ -1752,10 +1465,10 @@ static ssize_t h3_stream_open(struct Curl_cfilter *cf,
   }
 
   if(Curl_trc_is_verbose(data)) {
-    infof(data, "[HTTP/3] [%" PRId64 "] OPENED stream for %s",
+    infof(data, "[HTTP/3] [%" CURL_PRId64 "] OPENED stream for %s",
           stream->id, data->state.url);
     for(i = 0; i < nheader; ++i) {
-      infof(data, "[HTTP/3] [%" PRId64 "] [%.*s: %.*s]", stream->id,
+      infof(data, "[HTTP/3] [%" CURL_PRId64 "] [%.*s: %.*s]", stream->id,
             (int)nva[i].namelen, nva[i].name,
             (int)nva[i].valuelen, nva[i].value);
     }
@@ -1771,7 +1484,7 @@ static ssize_t cf_ngtcp2_send(struct Curl_cfilter *cf, struct Curl_easy *data,
                               const void *buf, size_t len, CURLcode *err)
 {
   struct cf_ngtcp2_ctx *ctx = cf->ctx;
-  struct h3_stream_ctx *stream = H3_STREAM_CTX(data);
+  struct h3_stream_ctx *stream = H3_STREAM_CTX(ctx, data);
   ssize_t sent = 0;
   struct cf_call_data save;
   struct pkt_io_ctx pktx;
@@ -1791,12 +1504,25 @@ static ssize_t cf_ngtcp2_send(struct Curl_cfilter *cf, struct Curl_easy *data,
   }
 
   if(!stream || stream->id < 0) {
+    if(ctx->conn_closed) {
+      CURL_TRC_CF(data, cf, "cannot open stream on closed connection");
+      *err = CURLE_SEND_ERROR;
+      sent = -1;
+      goto out;
+    }
     sent = h3_stream_open(cf, data, buf, len, err);
     if(sent < 0) {
       CURL_TRC_CF(data, cf, "failed to open stream -> %d", *err);
       goto out;
     }
-    stream = H3_STREAM_CTX(data);
+    stream = H3_STREAM_CTX(ctx, data);
+  }
+  else if(stream->xfer_result) {
+    CURL_TRC_CF(data, cf, "[%" CURL_PRId64 "] xfer write failed", stream->id);
+    cf_ngtcp2_stream_close(cf, data, stream);
+    *err = stream->xfer_result;
+    sent = -1;
+    goto out;
   }
   else if(stream->upload_blocked_len) {
     /* the data in `buf` has already been submitted or added to the
@@ -1820,19 +1546,27 @@ static ssize_t cf_ngtcp2_send(struct Curl_cfilter *cf, struct Curl_easy *data,
        * body. This happens on 30x or 40x responses.
        * We silently discard the data sent, since this is not a transport
        * error situation. */
-      CURL_TRC_CF(data, cf, "[%" PRId64 "] discarding data"
+      CURL_TRC_CF(data, cf, "[%" CURL_PRId64 "] discarding data"
                   "on closed stream with response", stream->id);
       *err = CURLE_OK;
       sent = (ssize_t)len;
       goto out;
     }
+    CURL_TRC_CF(data, cf, "[%" CURL_PRId64 "] send_body(len=%zu) "
+                "-> stream closed", stream->id, len);
     *err = CURLE_HTTP3;
     sent = -1;
     goto out;
   }
+  else if(ctx->conn_closed) {
+    CURL_TRC_CF(data, cf, "cannot send on closed connection");
+    *err = CURLE_SEND_ERROR;
+    sent = -1;
+    goto out;
+  }
   else {
     sent = Curl_bufq_write(&stream->sendbuf, buf, len, err);
-    CURL_TRC_CF(data, cf, "[%" PRId64 "] cf_send, add to "
+    CURL_TRC_CF(data, cf, "[%" CURL_PRId64 "] cf_send, add to "
                 "sendbuf(len=%zu) -> %zd, %d",
                 stream->id, len, sent, *err);
     if(sent < 0) {
@@ -1851,15 +1585,13 @@ static ssize_t cf_ngtcp2_send(struct Curl_cfilter *cf, struct Curl_easy *data,
   if(stream && sent > 0 && stream->sendbuf_len_in_flight) {
     /* We have unacknowledged DATA and cannot report success to our
      * caller. Instead we EAGAIN and remember how much we have already
-     * "written" into our various internal connection buffers.
-     * We put the stream upload on HOLD, until this gets ACKed. */
+     * "written" into our various internal connection buffers. */
     stream->upload_blocked_len = sent;
-    CURL_TRC_CF(data, cf, "[%" PRId64 "] cf_send(len=%zu), "
+    CURL_TRC_CF(data, cf, "[%" CURL_PRId64 "] cf_send(len=%zu), "
                 "%zu bytes in flight -> EGAIN", stream->id, len,
                 stream->sendbuf_len_in_flight);
     *err = CURLE_AGAIN;
     sent = -1;
-    data->req.keepon |= KEEP_SEND_HOLD;
   }
 
 out:
@@ -1868,7 +1600,7 @@ static ssize_t cf_ngtcp2_send(struct Curl_cfilter *cf, struct Curl_easy *data,
     *err = result;
     sent = -1;
   }
-  CURL_TRC_CF(data, cf, "[%" PRId64 "] cf_send(len=%zu) -> %zd, %d",
+  CURL_TRC_CF(data, cf, "[%" CURL_PRId64 "] cf_send(len=%zu) -> %zd, %d",
               stream? stream->id : -1, len, sent, *err);
   CF_DATA_RESTORE(cf, save);
   return sent;
@@ -1878,52 +1610,12 @@ static CURLcode qng_verify_peer(struct Curl_cfilter *cf,
                                 struct Curl_easy *data)
 {
   struct cf_ngtcp2_ctx *ctx = cf->ctx;
-  CURLcode result = CURLE_OK;
-  const char *hostname, *disp_hostname;
-  int port;
-  char *snihost;
-
-  Curl_conn_get_host(data, cf->sockindex, &hostname, &disp_hostname, &port);
-  snihost = Curl_ssl_snihost(data, hostname, NULL);
-  if(!snihost)
-    return CURLE_PEER_FAILED_VERIFICATION;
 
   cf->conn->bits.multiplex = TRUE; /* at least potentially multiplexed */
   cf->conn->httpversion = 30;
   cf->conn->bundle->multiuse = BUNDLE_MULTIPLEX;
 
-  if(cf->conn->ssl_config.verifyhost) {
-#ifdef USE_OPENSSL
-    X509 *server_cert;
-    server_cert = SSL_get_peer_certificate(ctx->ssl);
-    if(!server_cert) {
-      return CURLE_PEER_FAILED_VERIFICATION;
-    }
-    result = Curl_ossl_verifyhost(data, cf->conn, server_cert);
-    X509_free(server_cert);
-    if(result)
-      return result;
-#elif defined(USE_GNUTLS)
-    result = Curl_gtls_verifyserver(data, ctx->gtls->session,
-                                    &cf->conn->ssl_config, &data->set.ssl,
-                                    hostname, disp_hostname,
-                                    data->set.str[STRING_SSL_PINNEDPUBLICKEY]);
-    if(result)
-      return result;
-#elif defined(USE_WOLFSSL)
-    if(wolfSSL_check_domain_name(ctx->ssl, snihost) == SSL_FAILURE)
-      return CURLE_PEER_FAILED_VERIFICATION;
-#endif
-    infof(data, "Verified certificate just fine");
-  }
-  else
-    infof(data, "Skipped certificate verification");
-#ifdef USE_OPENSSL
-  if(data->set.ssl.certinfo)
-    /* asked to gather certificate info */
-    (void)Curl_ossl_certchain(data, ctx->ssl);
-#endif
-  return result;
+  return Curl_vquic_tls_verify_peer(&ctx->tls, cf, data, &ctx->peer);
 }
 
 static CURLcode recv_pkt(const unsigned char *pkt, size_t pktlen,
@@ -1946,18 +1638,9 @@ static CURLcode recv_pkt(const unsigned char *pkt, size_t pktlen,
 
   rv = ngtcp2_conn_read_pkt(ctx->qconn, &path, &pi, pkt, pktlen, pktx->ts);
   if(rv) {
-    CURL_TRC_CF(pktx->data, pktx->cf, "ingress, read_pkt -> %s",
-                ngtcp2_strerror(rv));
-    if(!ctx->last_error.error_code) {
-      if(rv == NGTCP2_ERR_CRYPTO) {
-        ngtcp2_ccerr_set_tls_alert(&ctx->last_error,
-                                   ngtcp2_conn_get_tls_alert(ctx->qconn),
-                                   NULL, 0);
-      }
-      else {
-        ngtcp2_ccerr_set_liberr(&ctx->last_error, rv, NULL, 0);
-      }
-    }
+    CURL_TRC_CF(pktx->data, pktx->cf, "ingress, read_pkt -> %s (%d)",
+                ngtcp2_strerror(rv), rv);
+    cf_ngtcp2_err_set(pktx->cf, pktx->data, rv);
 
     if(rv == NGTCP2_ERR_CRYPTO)
       /* this is a "TLS problem", but a failed certificate verification
@@ -1976,7 +1659,6 @@ static CURLcode cf_progress_ingress(struct Curl_cfilter *cf,
   struct cf_ngtcp2_ctx *ctx = cf->ctx;
   struct pkt_io_ctx local_pktx;
   size_t pkts_chunk = 128, i;
-  size_t pkts_max = 10 * pkts_chunk;
   CURLcode result = CURLE_OK;
 
   if(!pktx) {
@@ -1984,29 +1666,20 @@ static CURLcode cf_progress_ingress(struct Curl_cfilter *cf,
     pktx = &local_pktx;
   }
   else {
-    pktx->ts = timestamp();
+    pktx_update_time(pktx, cf);
   }
 
-#ifdef USE_OPENSSL
-  if(!ctx->x509_store_setup) {
-    result = Curl_ssl_setup_x509_store(cf, data, ctx->sslctx);
-    if(result)
-      return result;
-    ctx->x509_store_setup = TRUE;
-  }
-#endif
+  result = Curl_vquic_tls_before_recv(&ctx->tls, cf, data);
+  if(result)
+    return result;
 
-  for(i = 0; i < pkts_max; i += pkts_chunk) {
+  for(i = 0; i < 4; ++i) {
+    if(i)
+      pktx_update_time(pktx, cf);
     pktx->pkt_count = 0;
     result = vquic_recv_packets(cf, data, &ctx->q, pkts_chunk,
                                 recv_pkt, pktx);
-    if(result) /* error */
-      break;
-    if(pktx->pkt_count < pkts_chunk) /* got less than we could */
-      break;
-    /* give egress a chance before we receive more */
-    result = cf_progress_egress(cf, data, pktx);
-    if(result) /* error */
+    if(result || !pktx->pkt_count) /* error or got nothing */
       break;
   }
   return result;
@@ -2050,9 +1723,7 @@ static ssize_t read_pkt_to_send(void *userp,
       if(veccnt < 0) {
         failf(x->data, "nghttp3_conn_writev_stream returned error: %s",
               nghttp3_strerror((int)veccnt));
-        ngtcp2_ccerr_set_application_error(
-          &ctx->last_error,
-          nghttp3_err_infer_quic_app_error_code((int)veccnt), NULL, 0);
+        cf_ngtcp2_h3_err_set(x->cf, x->data, (int)veccnt);
         *err = CURLE_SEND_ERROR;
         return -1;
       }
@@ -2072,11 +1743,18 @@ static ssize_t read_pkt_to_send(void *userp,
     }
     else if(n < 0) {
       switch(n) {
-      case NGTCP2_ERR_STREAM_DATA_BLOCKED:
+      case NGTCP2_ERR_STREAM_DATA_BLOCKED: {
+        struct h3_stream_ctx *stream = H3_STREAM_CTX(ctx, x->data);
         DEBUGASSERT(ndatalen == -1);
         nghttp3_conn_block_stream(ctx->h3conn, stream_id);
+        CURL_TRC_CF(x->data, x->cf, "[%" CURL_PRId64 "] block quic flow",
+                    (curl_int64_t)stream_id);
+        DEBUGASSERT(stream);
+        if(stream)
+          stream->quic_flow_blocked = TRUE;
         n = 0;
         break;
+      }
       case NGTCP2_ERR_STREAM_SHUT_WR:
         DEBUGASSERT(ndatalen == -1);
         nghttp3_conn_shutdown_stream_write(ctx->h3conn, stream_id);
@@ -2092,7 +1770,7 @@ static ssize_t read_pkt_to_send(void *userp,
         DEBUGASSERT(ndatalen == -1);
         failf(x->data, "ngtcp2_conn_writev_stream returned error: %s",
               ngtcp2_strerror((int)n));
-        ngtcp2_ccerr_set_liberr(&ctx->last_error, (int)n, NULL, 0);
+        cf_ngtcp2_err_set(x->cf, x->data, (int)n);
         *err = CURLE_SEND_ERROR;
         nwritten = -1;
         goto out;
@@ -2136,7 +1814,7 @@ static CURLcode cf_progress_egress(struct Curl_cfilter *cf,
     pktx = &local_pktx;
   }
   else {
-    pktx->ts = timestamp();
+    pktx_update_time(pktx, cf);
     ngtcp2_path_storage_zero(&pktx->ps);
   }
 
@@ -2150,7 +1828,7 @@ static CURLcode cf_progress_egress(struct Curl_cfilter *cf,
   }
 
   /* In UDP, there is a maximum theoretical packet paload length and
-   * a minimum payload length that is "guarantueed" to work.
+   * a minimum payload length that is "guaranteed" to work.
    * To detect if this minimum payload can be increased, ngtcp2 sends
    * now and then a packet payload larger than the minimum. It that
    * is ACKed by the peer, both parties know that it works and
@@ -2238,9 +1916,9 @@ static CURLcode cf_progress_egress(struct Curl_cfilter *cf,
 static bool cf_ngtcp2_data_pending(struct Curl_cfilter *cf,
                                    const struct Curl_easy *data)
 {
-  const struct h3_stream_ctx *stream = H3_STREAM_CTX(data);
   (void)cf;
-  return stream && !Curl_bufq_is_empty(&stream->recvbuf);
+  (void)data;
+  return FALSE;
 }
 
 static CURLcode h3_data_pause(struct Curl_cfilter *cf,
@@ -2273,12 +1951,14 @@ static CURLcode cf_ngtcp2_data_event(struct Curl_cfilter *cf,
   case CF_CTRL_DATA_PAUSE:
     result = h3_data_pause(cf, data, (arg1 != 0));
     break;
-  case CF_CTRL_DATA_DONE: {
+  case CF_CTRL_DATA_DETACH:
+    h3_data_done(cf, data);
+    break;
+  case CF_CTRL_DATA_DONE:
     h3_data_done(cf, data);
     break;
-  }
   case CF_CTRL_DATA_DONE_SEND: {
-    struct h3_stream_ctx *stream = H3_STREAM_CTX(data);
+    struct h3_stream_ctx *stream = H3_STREAM_CTX(ctx, data);
     if(stream && !stream->send_closed) {
       stream->send_closed = TRUE;
       stream->upload_left = Curl_bufq_len(&stream->sendbuf);
@@ -2287,7 +1967,7 @@ static CURLcode cf_ngtcp2_data_event(struct Curl_cfilter *cf,
     break;
   }
   case CF_CTRL_DATA_IDLE: {
-    struct h3_stream_ctx *stream = H3_STREAM_CTX(data);
+    struct h3_stream_ctx *stream = H3_STREAM_CTX(ctx, data);
     CURL_TRC_CF(data, cf, "data idle");
     if(stream && !stream->closed) {
       result = check_and_set_expiry(cf, data, NULL);
@@ -2310,62 +1990,59 @@ static void cf_ngtcp2_ctx_clear(struct cf_ngtcp2_ctx *ctx)
   if(ctx->qlogfd != -1) {
     close(ctx->qlogfd);
   }
-#ifdef USE_OPENSSL
-  if(ctx->ssl)
-    SSL_free(ctx->ssl);
-  if(ctx->sslctx)
-    SSL_CTX_free(ctx->sslctx);
-#elif defined(USE_GNUTLS)
-  if(ctx->gtls) {
-    if(ctx->gtls->cred)
-      gnutls_certificate_free_credentials(ctx->gtls->cred);
-    if(ctx->gtls->session)
-      gnutls_deinit(ctx->gtls->session);
-    free(ctx->gtls);
-  }
-#elif defined(USE_WOLFSSL)
-  if(ctx->ssl)
-    wolfSSL_free(ctx->ssl);
-  if(ctx->sslctx)
-    wolfSSL_CTX_free(ctx->sslctx);
-#endif
+  Curl_vquic_tls_cleanup(&ctx->tls);
   vquic_ctx_free(&ctx->q);
   if(ctx->h3conn)
     nghttp3_conn_del(ctx->h3conn);
   if(ctx->qconn)
     ngtcp2_conn_del(ctx->qconn);
   Curl_bufcp_free(&ctx->stream_bufcp);
+  Curl_dyn_free(&ctx->scratch);
+  Curl_hash_clean(&ctx->streams);
+  Curl_hash_destroy(&ctx->streams);
+  Curl_ssl_peer_cleanup(&ctx->peer);
 
   memset(ctx, 0, sizeof(*ctx));
   ctx->qlogfd = -1;
   ctx->call_data = save;
 }
 
-static void cf_ngtcp2_close(struct Curl_cfilter *cf, struct Curl_easy *data)
+static void cf_ngtcp2_conn_close(struct Curl_cfilter *cf,
+                                 struct Curl_easy *data)
 {
   struct cf_ngtcp2_ctx *ctx = cf->ctx;
-  struct cf_call_data save;
-
-  CF_DATA_SAVE(save, cf, data);
-  if(ctx && ctx->qconn) {
+  if(ctx && ctx->qconn && !ctx->conn_closed) {
     char buffer[NGTCP2_MAX_UDP_PAYLOAD_SIZE];
-    ngtcp2_tstamp ts;
+    struct pkt_io_ctx pktx;
     ngtcp2_ssize rc;
 
-    CURL_TRC_CF(data, cf, "close");
-    ts = timestamp();
+    ctx->conn_closed = TRUE;
+    pktx_init(&pktx, cf, data);
     rc = ngtcp2_conn_write_connection_close(ctx->qconn, NULL, /* path */
                                             NULL, /* pkt_info */
                                             (uint8_t *)buffer, sizeof(buffer),
-                                            &ctx->last_error, ts);
+                                            &ctx->last_error, pktx.ts);
+    CURL_TRC_CF(data, cf, "closing connection(err_type=%d, err_code=%"
+                CURL_PRIu64 ") -> %d", ctx->last_error.type,
+                (curl_uint64_t)ctx->last_error.error_code, (int)rc);
     if(rc > 0) {
       while((send(ctx->q.sockfd, buffer, (SEND_TYPE_ARG3)rc, 0) == -1) &&
             SOCKERRNO == EINTR);
     }
+  }
+}
 
+static void cf_ngtcp2_close(struct Curl_cfilter *cf, struct Curl_easy *data)
+{
+  struct cf_ngtcp2_ctx *ctx = cf->ctx;
+  struct cf_call_data save;
+
+  CF_DATA_SAVE(save, cf, data);
+  if(ctx && ctx->qconn) {
+    cf_ngtcp2_conn_close(cf, data);
     cf_ngtcp2_ctx_clear(ctx);
+    CURL_TRC_CF(data, cf, "close");
   }
-
   cf->connected = FALSE;
   CF_DATA_RESTORE(cf, save);
 }
@@ -2386,6 +2063,71 @@ static void cf_ngtcp2_destroy(struct Curl_cfilter *cf, struct Curl_easy *data)
   (void)save;
 }
 
+#ifdef USE_OPENSSL
+/* The "new session" callback must return zero if the session can be removed
+ * or non-zero if the session has been put into the session cache.
+ */
+static int quic_ossl_new_session_cb(SSL *ssl, SSL_SESSION *ssl_sessionid)
+{
+  struct Curl_cfilter *cf;
+  struct cf_ngtcp2_ctx *ctx;
+  struct Curl_easy *data;
+  ngtcp2_crypto_conn_ref *cref;
+
+  cref = (ngtcp2_crypto_conn_ref *)SSL_get_app_data(ssl);
+  cf = cref? cref->user_data : NULL;
+  ctx = cf? cf->ctx : NULL;
+  data = cf? CF_DATA_CURRENT(cf) : NULL;
+  if(cf && data && ctx) {
+    Curl_ossl_add_session(cf, data, &ctx->peer, ssl_sessionid);
+    return 1;
+  }
+  return 0;
+}
+#endif /* USE_OPENSSL */
+
+static CURLcode tls_ctx_setup(struct Curl_cfilter *cf,
+                              struct Curl_easy *data,
+                              void *user_data)
+{
+  struct curl_tls_ctx *ctx = user_data;
+  (void)cf;
+#ifdef USE_OPENSSL
+#if defined(OPENSSL_IS_BORINGSSL) || defined(OPENSSL_IS_AWSLC)
+  if(ngtcp2_crypto_boringssl_configure_client_context(ctx->ossl.ssl_ctx)
+     != 0) {
+    failf(data, "ngtcp2_crypto_boringssl_configure_client_context failed");
+    return CURLE_FAILED_INIT;
+  }
+#else
+  if(ngtcp2_crypto_quictls_configure_client_context(ctx->ossl.ssl_ctx) != 0) {
+    failf(data, "ngtcp2_crypto_quictls_configure_client_context failed");
+    return CURLE_FAILED_INIT;
+  }
+#endif /* !OPENSSL_IS_BORINGSSL && !OPENSSL_IS_AWSLC */
+  /* Enable the session cache because it's a prerequisite for the
+   * "new session" callback. Use the "external storage" mode to prevent
+   * OpenSSL from creating an internal session cache.
+   */
+  SSL_CTX_set_session_cache_mode(ctx->ossl.ssl_ctx,
+                                 SSL_SESS_CACHE_CLIENT |
+                                 SSL_SESS_CACHE_NO_INTERNAL);
+  SSL_CTX_sess_set_new_cb(ctx->ossl.ssl_ctx, quic_ossl_new_session_cb);
+
+#elif defined(USE_GNUTLS)
+  if(ngtcp2_crypto_gnutls_configure_client_session(ctx->gtls.session) != 0) {
+    failf(data, "ngtcp2_crypto_gnutls_configure_client_session failed");
+    return CURLE_FAILED_INIT;
+  }
+#elif defined(USE_WOLFSSL)
+  if(ngtcp2_crypto_wolfssl_configure_client_context(ctx->ssl_ctx) != 0) {
+    failf(data, "ngtcp2_crypto_wolfssl_configure_client_context failed");
+    return CURLE_FAILED_INIT;
+  }
+#endif
+  return CURLE_OK;
+}
+
 /*
  * Might be called twice for happy eyeballs.
  */
@@ -2402,26 +2144,26 @@ static CURLcode cf_connect_start(struct Curl_cfilter *cf,
 
   ctx->version = NGTCP2_PROTO_VER_MAX;
   ctx->max_stream_window = H3_STREAM_WINDOW_SIZE;
+  ctx->max_idle_ms = CURL_QUIC_MAX_IDLE_MS;
   Curl_bufcp_init(&ctx->stream_bufcp, H3_STREAM_CHUNK_SIZE,
                   H3_STREAM_POOL_SPARES);
+  Curl_dyn_init(&ctx->scratch, CURL_MAX_HTTP_HEADER);
+  Curl_hash_offt_init(&ctx->streams, 63, h3_stream_hash_free);
 
-#ifdef USE_OPENSSL
-  result = quic_ssl_ctx(&ctx->sslctx, cf, data);
+  result = Curl_ssl_peer_init(&ctx->peer, cf, TRNSPRT_QUIC);
   if(result)
     return result;
 
-  result = quic_set_client_cert(cf, data);
-  if(result)
-    return result;
-#elif defined(USE_WOLFSSL)
-  result = quic_ssl_ctx(&ctx->sslctx, cf, data);
+#define H3_ALPN "\x2h3\x5h3-29"
+  result = Curl_vquic_tls_init(&ctx->tls, cf, data, &ctx->peer,
+                               H3_ALPN, sizeof(H3_ALPN) - 1,
+                               tls_ctx_setup, &ctx->tls, &ctx->conn_ref);
   if(result)
     return result;
-#endif
 
-  result = quic_init_ssl(cf, data);
-  if(result)
-    return result;
+#ifdef USE_OPENSSL
+  SSL_set_quic_use_legacy_codepoint(ctx->tls.ossl.ssl, 0);
+#endif
 
   ctx->dcid.datalen = NGTCP2_MAX_CIDLEN;
   result = Curl_rand(data, ctx->dcid.data, NGTCP2_MAX_CIDLEN);
@@ -2441,8 +2183,7 @@ static CURLcode cf_connect_start(struct Curl_cfilter *cf,
   if(result)
     return result;
 
-  Curl_cf_socket_peek(cf->next, data, &ctx->q.sockfd,
-                      &sockaddr, NULL, NULL, NULL, NULL);
+  Curl_cf_socket_peek(cf->next, data, &ctx->q.sockfd, &sockaddr, NULL);
   if(!sockaddr)
     return CURLE_QUIC_CONNECT_ERROR;
   ctx->q.local_addrlen = sizeof(ctx->q.local_addr);
@@ -2465,10 +2206,12 @@ static CURLcode cf_connect_start(struct Curl_cfilter *cf,
   if(rc)
     return CURLE_QUIC_CONNECT_ERROR;
 
-#ifdef USE_GNUTLS
-  ngtcp2_conn_set_tls_native_handle(ctx->qconn, ctx->gtls->session);
+#ifdef USE_OPENSSL
+  ngtcp2_conn_set_tls_native_handle(ctx->qconn, ctx->tls.ossl.ssl);
+#elif defined(USE_GNUTLS)
+  ngtcp2_conn_set_tls_native_handle(ctx->qconn, ctx->tls.gtls.session);
 #else
-  ngtcp2_conn_set_tls_native_handle(ctx->qconn, ctx->ssl);
+  ngtcp2_conn_set_tls_native_handle(ctx->qconn, ctx->tls.ssl);
 #endif
 
   ngtcp2_ccerr_default(&ctx->last_error);
@@ -2550,38 +2293,18 @@ static CURLcode cf_ngtcp2_connect(struct Curl_cfilter *cf,
      ngtcp2_conn_in_draining_period(ctx->qconn)) {
     /* When a QUIC server instance is shutting down, it may send us a
      * CONNECTION_CLOSE right away. Our connection then enters the DRAINING
-     * state.
-     * This may be a stopping of the service or it may be that the server
-     * is reloading and a new instance will start serving soon.
-     * In any case, we tear down our socket and start over with a new one.
-     * We re-open the underlying UDP cf right now, but do not start
-     * connecting until called again.
-     */
-    int reconn_delay_ms = 200;
-
-    CURL_TRC_CF(data, cf, "connect, remote closed, reconnect after %dms",
-                reconn_delay_ms);
-    Curl_conn_cf_close(cf->next, data);
-    cf_ngtcp2_ctx_clear(ctx);
-    result = Curl_conn_cf_connect(cf->next, data, FALSE, done);
-    if(!result && *done) {
-      *done = FALSE;
-      ctx->reconnect_at = now;
-      ctx->reconnect_at.tv_usec += reconn_delay_ms * 1000;
-      Curl_expire(data, reconn_delay_ms, EXPIRE_QUIC);
-      result = CURLE_OK;
-    }
+     * state. The CONNECT may work in the near future again. Indicate
+     * that as a "weird" reply. */
+    result = CURLE_WEIRD_SERVER_REPLY;
   }
 
 #ifndef CURL_DISABLE_VERBOSE_STRINGS
   if(result) {
-    const char *r_ip = NULL;
-    int r_port = 0;
+    struct ip_quadruple ip;
 
-    Curl_cf_socket_peek(cf->next, data, NULL, NULL,
-                        &r_ip, &r_port, NULL, NULL);
+    Curl_cf_socket_peek(cf->next, data, NULL, NULL, &ip);
     infof(data, "QUIC connect to %s port %u failed: %s",
-          r_ip, r_port, curl_easy_strerror(result));
+          ip.remote_ip, ip.remote_port, curl_easy_strerror(result));
   }
 #endif
   if(!result && ctx->qconn) {
@@ -2602,23 +2325,34 @@ static CURLcode cf_ngtcp2_query(struct Curl_cfilter *cf,
 
   switch(query) {
   case CF_QUERY_MAX_CONCURRENT: {
-    const ngtcp2_transport_params *rp;
     DEBUGASSERT(pres1);
-
     CF_DATA_SAVE(save, cf, data);
-    rp = ngtcp2_conn_get_remote_transport_params(ctx->qconn);
-    if(rp)
-      *pres1 = (rp->initial_max_streams_bidi > INT_MAX)?
-                 INT_MAX : (int)rp->initial_max_streams_bidi;
-    else  /* not arrived yet? */
+    /* Set after transport params arrived and continually updated
+     * by callback. QUIC counts the number over the lifetime of the
+     * connection, ever increasing.
+     * We count the *open* transfers plus the budget for new ones. */
+    if(!ctx->qconn || ctx->conn_closed) {
+      *pres1 = 0;
+    }
+    else if(ctx->max_bidi_streams) {
+      uint64_t avail_bidi_streams = 0;
+      uint64_t max_streams = CONN_INUSE(cf->conn);
+      if(ctx->max_bidi_streams > ctx->used_bidi_streams)
+        avail_bidi_streams = ctx->max_bidi_streams - ctx->used_bidi_streams;
+      max_streams += avail_bidi_streams;
+      *pres1 = (max_streams > INT_MAX)? INT_MAX : (int)max_streams;
+    }
+    else  /* transport params not arrived yet? take our default. */
       *pres1 = Curl_multi_max_concurrent_streams(data->multi);
-    CURL_TRC_CF(data, cf, "query max_conncurrent -> %d", *pres1);
+    CURL_TRC_CF(data, cf, "query conn[%" CURL_FORMAT_CURL_OFF_T "]: "
+                "MAX_CONCURRENT -> %d (%zu in use)",
+                cf->conn->connection_id, *pres1, CONN_INUSE(cf->conn));
     CF_DATA_RESTORE(cf, save);
     return CURLE_OK;
   }
   case CF_QUERY_CONNECT_REPLY_MS:
-    if(ctx->got_first_byte) {
-      timediff_t ms = Curl_timediff(ctx->first_byte_at, ctx->started_at);
+    if(ctx->q.got_first_byte) {
+      timediff_t ms = Curl_timediff(ctx->q.first_byte_at, ctx->started_at);
       *pres1 = (ms < INT_MAX)? (int)ms : INT_MAX;
     }
     else
@@ -2626,8 +2360,8 @@ static CURLcode cf_ngtcp2_query(struct Curl_cfilter *cf,
     return CURLE_OK;
   case CF_QUERY_TIMER_CONNECT: {
     struct curltime *when = pres2;
-    if(ctx->got_first_byte)
-      *when = ctx->first_byte_at;
+    if(ctx->q.got_first_byte)
+      *when = ctx->q.first_byte_at;
     return CURLE_OK;
   }
   case CF_QUERY_TIMER_APPCONNECT: {
@@ -2648,24 +2382,51 @@ static bool cf_ngtcp2_conn_is_alive(struct Curl_cfilter *cf,
                                     struct Curl_easy *data,
                                     bool *input_pending)
 {
-  bool alive = TRUE;
+  struct cf_ngtcp2_ctx *ctx = cf->ctx;
+  bool alive = FALSE;
+  const ngtcp2_transport_params *rp;
+  struct cf_call_data save;
 
+  CF_DATA_SAVE(save, cf, data);
   *input_pending = FALSE;
+  if(!ctx->qconn || ctx->conn_closed)
+    goto out;
+
+  /* Both sides of the QUIC connection announce they max idle times in
+   * the transport parameters. Look at the minimum of both and if
+   * we exceed this, regard the connection as dead. The other side
+   * may have completely purged it and will no longer respond
+   * to any packets from us. */
+  rp = ngtcp2_conn_get_remote_transport_params(ctx->qconn);
+  if(rp) {
+    timediff_t idletime;
+    uint64_t idle_ms = ctx->max_idle_ms;
+
+    if(rp->max_idle_timeout &&
+      (rp->max_idle_timeout / NGTCP2_MILLISECONDS) < idle_ms)
+      idle_ms = (rp->max_idle_timeout / NGTCP2_MILLISECONDS);
+    idletime = Curl_timediff(Curl_now(), ctx->q.last_io);
+    if(idletime > 0 && (uint64_t)idletime > idle_ms)
+      goto out;
+  }
+
   if(!cf->next || !cf->next->cft->is_alive(cf->next, data, input_pending))
-    return FALSE;
+    goto out;
 
+  alive = TRUE;
   if(*input_pending) {
+    CURLcode result;
     /* This happens before we've sent off a request and the connection is
        not in use by any other transfer, there shouldn't be any data here,
        only "protocol frames" */
     *input_pending = FALSE;
-    if(cf_progress_ingress(cf, data, NULL))
-      alive = FALSE;
-    else {
-      alive = TRUE;
-    }
+    result = cf_progress_ingress(cf, data, NULL);
+    CURL_TRC_CF(data, cf, "is_alive, progress ingress -> %d", result);
+    alive = result? FALSE : TRUE;
   }
 
+out:
+  CF_DATA_RESTORE(cf, save);
   return alive;
 }
 
@@ -2677,7 +2438,7 @@ struct Curl_cftype Curl_cft_http3 = {
   cf_ngtcp2_connect,
   cf_ngtcp2_close,
   Curl_cf_def_get_host,
-  cf_ngtcp2_get_select_socks,
+  cf_ngtcp2_adjust_pollset,
   cf_ngtcp2_data_pending,
   cf_ngtcp2_send,
   cf_ngtcp2_recv,
@@ -2697,7 +2458,7 @@ CURLcode Curl_cf_ngtcp2_create(struct Curl_cfilter **pcf,
   CURLcode result;
 
   (void)data;
-  ctx = calloc(sizeof(*ctx), 1);
+  ctx = calloc(1, sizeof(*ctx));
   if(!ctx) {
     result = CURLE_OUT_OF_MEMORY;
     goto out;
diff --git a/vendor/curl/lib/vquic/curl_osslq.c b/vendor/curl/lib/vquic/curl_osslq.c
new file mode 100644
index 0000000000..8b9e889d75
--- /dev/null
+++ b/vendor/curl/lib/vquic/curl_osslq.c
@@ -0,0 +1,2332 @@
+/***************************************************************************
+ *                                  _   _ ____  _
+ *  Project                     ___| | | |  _ \| |
+ *                             / __| | | | |_) | |
+ *                            | (__| |_| |  _ <| |___
+ *                             \___|\___/|_| \_\_____|
+ *
+ * Copyright (C) Daniel Stenberg, , et al.
+ *
+ * This software is licensed as described in the file COPYING, which
+ * you should have received as part of this distribution. The terms
+ * are also available at https://curl.se/docs/copyright.html.
+ *
+ * You may opt to use, copy, modify, merge, publish, distribute and/or sell
+ * copies of the Software, and permit persons to whom the Software is
+ * furnished to do so, under the terms of the COPYING file.
+ *
+ * This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY
+ * KIND, either express or implied.
+ *
+ * SPDX-License-Identifier: curl
+ *
+ ***************************************************************************/
+
+#include "curl_setup.h"
+
+#if defined(USE_OPENSSL_QUIC) && defined(USE_NGHTTP3)
+
+#include 
+#include 
+#include 
+#include 
+
+#include "urldata.h"
+#include "hash.h"
+#include "sendf.h"
+#include "strdup.h"
+#include "rand.h"
+#include "multiif.h"
+#include "strcase.h"
+#include "cfilters.h"
+#include "cf-socket.h"
+#include "connect.h"
+#include "progress.h"
+#include "strerror.h"
+#include "dynbuf.h"
+#include "http1.h"
+#include "select.h"
+#include "inet_pton.h"
+#include "vquic.h"
+#include "vquic_int.h"
+#include "vquic-tls.h"
+#include "vtls/keylog.h"
+#include "vtls/vtls.h"
+#include "vtls/openssl.h"
+#include "curl_osslq.h"
+
+#include "warnless.h"
+
+/* The last 3 #include files should be in this order */
+#include "curl_printf.h"
+#include "curl_memory.h"
+#include "memdebug.h"
+
+/* A stream window is the maximum amount we need to buffer for
+ * each active transfer. We use HTTP/3 flow control and only ACK
+ * when we take things out of the buffer.
+ * Chunk size is large enough to take a full DATA frame */
+#define H3_STREAM_WINDOW_SIZE (128 * 1024)
+#define H3_STREAM_CHUNK_SIZE   (16 * 1024)
+/* The pool keeps spares around and half of a full stream window
+ * seems good. More does not seem to improve performance.
+ * The benefit of the pool is that stream buffer to not keep
+ * spares. So memory consumption goes down when streams run empty,
+ * have a large upload done, etc. */
+#define H3_STREAM_POOL_SPARES \
+          (H3_STREAM_WINDOW_SIZE / H3_STREAM_CHUNK_SIZE ) / 2
+/* Receive and Send max number of chunks just follows from the
+ * chunk size and window size */
+#define H3_STREAM_RECV_CHUNKS \
+          (H3_STREAM_WINDOW_SIZE / H3_STREAM_CHUNK_SIZE)
+#define H3_STREAM_SEND_CHUNKS \
+          (H3_STREAM_WINDOW_SIZE / H3_STREAM_CHUNK_SIZE)
+
+#ifndef ARRAYSIZE
+#define ARRAYSIZE(A) (sizeof(A)/sizeof((A)[0]))
+#endif
+
+#if defined(OPENSSL_IS_BORINGSSL) || defined(OPENSSL_IS_AWSLC)
+typedef uint32_t sslerr_t;
+#else
+typedef unsigned long sslerr_t;
+#endif
+
+
+/* How to access `call_data` from a cf_osslq filter */
+#undef CF_CTX_CALL_DATA
+#define CF_CTX_CALL_DATA(cf)  \
+  ((struct cf_osslq_ctx *)(cf)->ctx)->call_data
+
+static CURLcode cf_progress_ingress(struct Curl_cfilter *cf,
+                                    struct Curl_easy *data);
+
+static const char *osslq_SSL_ERROR_to_str(int err)
+{
+  switch(err) {
+  case SSL_ERROR_NONE:
+    return "SSL_ERROR_NONE";
+  case SSL_ERROR_SSL:
+    return "SSL_ERROR_SSL";
+  case SSL_ERROR_WANT_READ:
+    return "SSL_ERROR_WANT_READ";
+  case SSL_ERROR_WANT_WRITE:
+    return "SSL_ERROR_WANT_WRITE";
+  case SSL_ERROR_WANT_X509_LOOKUP:
+    return "SSL_ERROR_WANT_X509_LOOKUP";
+  case SSL_ERROR_SYSCALL:
+    return "SSL_ERROR_SYSCALL";
+  case SSL_ERROR_ZERO_RETURN:
+    return "SSL_ERROR_ZERO_RETURN";
+  case SSL_ERROR_WANT_CONNECT:
+    return "SSL_ERROR_WANT_CONNECT";
+  case SSL_ERROR_WANT_ACCEPT:
+    return "SSL_ERROR_WANT_ACCEPT";
+#if defined(SSL_ERROR_WANT_ASYNC)
+  case SSL_ERROR_WANT_ASYNC:
+    return "SSL_ERROR_WANT_ASYNC";
+#endif
+#if defined(SSL_ERROR_WANT_ASYNC_JOB)
+  case SSL_ERROR_WANT_ASYNC_JOB:
+    return "SSL_ERROR_WANT_ASYNC_JOB";
+#endif
+#if defined(SSL_ERROR_WANT_EARLY)
+  case SSL_ERROR_WANT_EARLY:
+    return "SSL_ERROR_WANT_EARLY";
+#endif
+  default:
+    return "SSL_ERROR unknown";
+  }
+}
+
+/* Return error string for last OpenSSL error */
+static char *osslq_strerror(unsigned long error, char *buf, size_t size)
+{
+  DEBUGASSERT(size);
+  *buf = '\0';
+
+#if defined(OPENSSL_IS_BORINGSSL) || defined(OPENSSL_IS_AWSLC)
+  ERR_error_string_n((uint32_t)error, buf, size);
+#else
+  ERR_error_string_n(error, buf, size);
+#endif
+
+  if(!*buf) {
+    const char *msg = error ? "Unknown error" : "No error";
+    if(strlen(msg) < size)
+      strcpy(buf, msg);
+  }
+
+  return buf;
+}
+
+static CURLcode make_bio_addr(BIO_ADDR **pbio_addr,
+                              const struct Curl_sockaddr_ex *addr)
+{
+  BIO_ADDR *ba;
+  CURLcode result = CURLE_FAILED_INIT;
+
+  ba = BIO_ADDR_new();
+  if(!ba) {
+    result = CURLE_OUT_OF_MEMORY;
+    goto out;
+  }
+
+  switch(addr->family) {
+  case AF_INET: {
+    struct sockaddr_in * const sin =
+      (struct sockaddr_in * const)(void *)&addr->sa_addr;
+    if(!BIO_ADDR_rawmake(ba, AF_INET, &sin->sin_addr,
+                         sizeof(sin->sin_addr), sin->sin_port)) {
+      goto out;
+    }
+    result = CURLE_OK;
+    break;
+  }
+#ifdef USE_IPV6
+  case AF_INET6: {
+    struct sockaddr_in6 * const sin =
+      (struct sockaddr_in6 * const)(void *)&addr->sa_addr;
+    if(!BIO_ADDR_rawmake(ba, AF_INET6, &sin->sin6_addr,
+                         sizeof(sin->sin6_addr), sin->sin6_port)) {
+    }
+    result = CURLE_OK;
+    break;
+  }
+#endif /* USE_IPV6 */
+  default:
+    /* sunsupported */
+    DEBUGASSERT(0);
+    break;
+  }
+
+out:
+  if(result && ba) {
+    BIO_ADDR_free(ba);
+    ba = NULL;
+  }
+  *pbio_addr = ba;
+  return result;
+}
+
+/* QUIC stream (not necessarily H3) */
+struct cf_osslq_stream {
+  curl_int64_t id;
+  SSL *ssl;
+  struct bufq recvbuf; /* QUIC war data recv buffer */
+  BIT(recvd_eos);
+  BIT(closed);
+  BIT(reset);
+  BIT(send_blocked);
+};
+
+static CURLcode cf_osslq_stream_open(struct cf_osslq_stream *s,
+                                     SSL *conn,
+                                     uint64_t flags,
+                                     struct bufc_pool *bufcp,
+                                     void *user_data)
+{
+  DEBUGASSERT(!s->ssl);
+  Curl_bufq_initp(&s->recvbuf, bufcp, 1, BUFQ_OPT_NONE);
+  s->ssl = SSL_new_stream(conn, flags);
+  if(!s->ssl) {
+    return CURLE_FAILED_INIT;
+  }
+  s->id = SSL_get_stream_id(s->ssl);
+  SSL_set_app_data(s->ssl, user_data);
+  return CURLE_OK;
+}
+
+static void cf_osslq_stream_cleanup(struct cf_osslq_stream *s)
+{
+  if(s->ssl) {
+    SSL_set_app_data(s->ssl, NULL);
+    SSL_free(s->ssl);
+  }
+  Curl_bufq_free(&s->recvbuf);
+  memset(s, 0, sizeof(*s));
+}
+
+static void cf_osslq_stream_close(struct cf_osslq_stream *s)
+{
+  if(s->ssl) {
+    SSL_free(s->ssl);
+    s->ssl = NULL;
+  }
+}
+
+struct cf_osslq_h3conn {
+  nghttp3_conn *conn;
+  nghttp3_settings settings;
+  struct cf_osslq_stream s_ctrl;
+  struct cf_osslq_stream s_qpack_enc;
+  struct cf_osslq_stream s_qpack_dec;
+  struct cf_osslq_stream remote_ctrl[3]; /* uni streams opened by the peer */
+  size_t remote_ctrl_n; /* number of peer streams opened */
+};
+
+static void cf_osslq_h3conn_cleanup(struct cf_osslq_h3conn *h3)
+{
+  size_t i;
+
+  if(h3->conn)
+    nghttp3_conn_del(h3->conn);
+  cf_osslq_stream_cleanup(&h3->s_ctrl);
+  cf_osslq_stream_cleanup(&h3->s_qpack_enc);
+  cf_osslq_stream_cleanup(&h3->s_qpack_dec);
+  for(i = 0; i < h3->remote_ctrl_n; ++i) {
+    cf_osslq_stream_cleanup(&h3->remote_ctrl[i]);
+  }
+}
+
+struct cf_osslq_ctx {
+  struct cf_quic_ctx q;
+  struct ssl_peer peer;
+  struct curl_tls_ctx tls;
+  struct cf_call_data call_data;
+  struct cf_osslq_h3conn h3;
+  struct curltime started_at;        /* time the current attempt started */
+  struct curltime handshake_at;      /* time connect handshake finished */
+  struct curltime first_byte_at;     /* when first byte was recvd */
+  struct curltime reconnect_at;      /* time the next attempt should start */
+  struct bufc_pool stream_bufcp;     /* chunk pool for streams */
+  struct Curl_hash streams;          /* hash `data->id` to `h3_stream_ctx` */
+  size_t max_stream_window;          /* max flow window for one stream */
+  uint64_t max_idle_ms;              /* max idle time for QUIC connection */
+  BIT(got_first_byte);               /* if first byte was received */
+#ifdef USE_OPENSSL
+  BIT(x509_store_setup);             /* if x509 store has been set up */
+  BIT(protocol_shutdown);            /* QUIC connection is shut down */
+#endif
+};
+
+static void cf_osslq_ctx_clear(struct cf_osslq_ctx *ctx)
+{
+  struct cf_call_data save = ctx->call_data;
+
+  cf_osslq_h3conn_cleanup(&ctx->h3);
+  Curl_vquic_tls_cleanup(&ctx->tls);
+  vquic_ctx_free(&ctx->q);
+  Curl_bufcp_free(&ctx->stream_bufcp);
+  Curl_hash_clean(&ctx->streams);
+  Curl_hash_destroy(&ctx->streams);
+  Curl_ssl_peer_cleanup(&ctx->peer);
+
+  memset(ctx, 0, sizeof(*ctx));
+  ctx->call_data = save;
+}
+
+static void cf_osslq_close(struct Curl_cfilter *cf, struct Curl_easy *data)
+{
+  struct cf_osslq_ctx *ctx = cf->ctx;
+  struct cf_call_data save;
+
+  CF_DATA_SAVE(save, cf, data);
+  if(ctx && ctx->tls.ossl.ssl) {
+    /* TODO: send connection close */
+    CURL_TRC_CF(data, cf, "cf_osslq_close()");
+    cf_osslq_ctx_clear(ctx);
+  }
+
+  cf->connected = FALSE;
+  CF_DATA_RESTORE(cf, save);
+}
+
+static void cf_osslq_destroy(struct Curl_cfilter *cf, struct Curl_easy *data)
+{
+  struct cf_osslq_ctx *ctx = cf->ctx;
+  struct cf_call_data save;
+
+  CF_DATA_SAVE(save, cf, data);
+  CURL_TRC_CF(data, cf, "destroy");
+  if(ctx) {
+    CURL_TRC_CF(data, cf, "cf_osslq_destroy()");
+    cf_osslq_ctx_clear(ctx);
+    free(ctx);
+  }
+  cf->ctx = NULL;
+  /* No CF_DATA_RESTORE(cf, save) possible */
+  (void)save;
+}
+
+static CURLcode cf_osslq_h3conn_add_stream(struct cf_osslq_h3conn *h3,
+                                           SSL *stream_ssl,
+                                           struct Curl_cfilter *cf,
+                                           struct Curl_easy *data)
+{
+  struct cf_osslq_ctx *ctx = cf->ctx;
+  int64_t stream_id = SSL_get_stream_id(stream_ssl);
+
+  if(h3->remote_ctrl_n >= ARRAYSIZE(h3->remote_ctrl)) {
+    /* rejected, we are full */
+    CURL_TRC_CF(data, cf, "[%" CURL_PRId64 "] rejecting remote stream",
+                (curl_int64_t)stream_id);
+    SSL_free(stream_ssl);
+    return CURLE_FAILED_INIT;
+  }
+  switch(SSL_get_stream_type(stream_ssl)) {
+    case SSL_STREAM_TYPE_READ: {
+      struct cf_osslq_stream *nstream = &h3->remote_ctrl[h3->remote_ctrl_n++];
+      nstream->id = stream_id;
+      nstream->ssl = stream_ssl;
+      Curl_bufq_initp(&nstream->recvbuf, &ctx->stream_bufcp, 1, BUFQ_OPT_NONE);
+      CURL_TRC_CF(data, cf, "[%" CURL_PRId64 "] accepted remote uni stream",
+                  (curl_int64_t)stream_id);
+      break;
+    }
+    default:
+      CURL_TRC_CF(data, cf, "[%" CURL_PRId64 "] reject remote non-uni-read"
+                  " stream", (curl_int64_t)stream_id);
+      SSL_free(stream_ssl);
+      return CURLE_FAILED_INIT;
+  }
+  return CURLE_OK;
+
+}
+
+static CURLcode cf_osslq_ssl_err(struct Curl_cfilter *cf,
+                                 struct Curl_easy *data,
+                                 int detail, CURLcode def_result)
+{
+  struct cf_osslq_ctx *ctx = cf->ctx;
+  CURLcode result = def_result;
+  sslerr_t errdetail;
+  char ebuf[256] = "unknown";
+  const char *err_descr = ebuf;
+  long lerr;
+  int lib;
+  int reason;
+  struct ssl_config_data *ssl_config = Curl_ssl_cf_get_config(cf, data);
+
+  errdetail = ERR_get_error();
+  lib = ERR_GET_LIB(errdetail);
+  reason = ERR_GET_REASON(errdetail);
+
+  if((lib == ERR_LIB_SSL) &&
+     ((reason == SSL_R_CERTIFICATE_VERIFY_FAILED) ||
+      (reason == SSL_R_SSLV3_ALERT_CERTIFICATE_EXPIRED))) {
+    result = CURLE_PEER_FAILED_VERIFICATION;
+
+    lerr = SSL_get_verify_result(ctx->tls.ossl.ssl);
+    if(lerr != X509_V_OK) {
+      ssl_config->certverifyresult = lerr;
+      msnprintf(ebuf, sizeof(ebuf),
+                "SSL certificate problem: %s",
+                X509_verify_cert_error_string(lerr));
+    }
+    else
+      err_descr = "SSL certificate verification failed";
+  }
+#if defined(SSL_R_TLSV13_ALERT_CERTIFICATE_REQUIRED)
+  /* SSL_R_TLSV13_ALERT_CERTIFICATE_REQUIRED is only available on
+     OpenSSL version above v1.1.1, not LibreSSL, BoringSSL, or AWS-LC */
+  else if((lib == ERR_LIB_SSL) &&
+          (reason == SSL_R_TLSV13_ALERT_CERTIFICATE_REQUIRED)) {
+    /* If client certificate is required, communicate the
+       error to client */
+    result = CURLE_SSL_CLIENTCERT;
+    osslq_strerror(errdetail, ebuf, sizeof(ebuf));
+  }
+#endif
+  else if((lib == ERR_LIB_SSL) && (reason == SSL_R_PROTOCOL_IS_SHUTDOWN)) {
+    ctx->protocol_shutdown = TRUE;
+    err_descr = "QUIC connection has been shut down";
+    result = def_result;
+  }
+  else {
+    result = def_result;
+    osslq_strerror(errdetail, ebuf, sizeof(ebuf));
+  }
+
+  /* detail is already set to the SSL error above */
+
+  /* If we e.g. use SSLv2 request-method and the server doesn't like us
+   * (RST connection, etc.), OpenSSL gives no explanation whatsoever and
+   * the SO_ERROR is also lost.
+   */
+  if(CURLE_SSL_CONNECT_ERROR == result && errdetail == 0) {
+    char extramsg[80]="";
+    int sockerr = SOCKERRNO;
+    struct ip_quadruple ip;
+
+    Curl_cf_socket_peek(cf->next, data, NULL, NULL, &ip);
+    if(sockerr && detail == SSL_ERROR_SYSCALL)
+      Curl_strerror(sockerr, extramsg, sizeof(extramsg));
+    failf(data, "QUIC connect: %s in connection to %s:%d (%s)",
+          extramsg[0] ? extramsg : osslq_SSL_ERROR_to_str(detail),
+          ctx->peer.dispname, ip.remote_port, ip.remote_ip);
+  }
+  else {
+    /* Could be a CERT problem */
+    failf(data, "%s", err_descr);
+  }
+  return result;
+}
+
+static CURLcode cf_osslq_verify_peer(struct Curl_cfilter *cf,
+                                  struct Curl_easy *data)
+{
+  struct cf_osslq_ctx *ctx = cf->ctx;
+
+  cf->conn->bits.multiplex = TRUE; /* at least potentially multiplexed */
+  cf->conn->httpversion = 30;
+  cf->conn->bundle->multiuse = BUNDLE_MULTIPLEX;
+
+  return Curl_vquic_tls_verify_peer(&ctx->tls, cf, data, &ctx->peer);
+}
+
+/**
+ * All about the H3 internals of a stream
+ */
+struct h3_stream_ctx {
+  struct cf_osslq_stream s;
+  struct bufq sendbuf;   /* h3 request body */
+  struct bufq recvbuf;   /* h3 response body */
+  struct h1_req_parser h1; /* h1 request parsing */
+  size_t sendbuf_len_in_flight; /* sendbuf amount "in flight" */
+  size_t upload_blocked_len; /* the amount written last and EGAINed */
+  size_t recv_buf_nonflow; /* buffered bytes, not counting for flow control */
+  curl_uint64_t error3; /* HTTP/3 stream error code */
+  curl_off_t upload_left; /* number of request bytes left to upload */
+  curl_off_t download_recvd; /* number of response DATA bytes received */
+  int status_code; /* HTTP status code */
+  bool resp_hds_complete; /* we have a complete, final response */
+  bool closed; /* TRUE on stream close */
+  bool reset;  /* TRUE on stream reset */
+  bool send_closed; /* stream is local closed */
+  BIT(quic_flow_blocked); /* stream is blocked by QUIC flow control */
+};
+
+#define H3_STREAM_CTX(ctx,data)   ((struct h3_stream_ctx *)(\
+            data? Curl_hash_offt_get(&(ctx)->streams, (data)->id) : NULL))
+
+static void h3_stream_ctx_free(struct h3_stream_ctx *stream)
+{
+  cf_osslq_stream_cleanup(&stream->s);
+  Curl_bufq_free(&stream->sendbuf);
+  Curl_bufq_free(&stream->recvbuf);
+  Curl_h1_req_parse_free(&stream->h1);
+  free(stream);
+}
+
+static void h3_stream_hash_free(void *stream)
+{
+  DEBUGASSERT(stream);
+  h3_stream_ctx_free((struct h3_stream_ctx *)stream);
+}
+
+static CURLcode h3_data_setup(struct Curl_cfilter *cf,
+                              struct Curl_easy *data)
+{
+  struct cf_osslq_ctx *ctx = cf->ctx;
+  struct h3_stream_ctx *stream = H3_STREAM_CTX(ctx, data);
+
+  if(!data || !data->req.p.http) {
+    failf(data, "initialization failure, transfer not http initialized");
+    return CURLE_FAILED_INIT;
+  }
+
+  if(stream)
+    return CURLE_OK;
+
+  stream = calloc(1, sizeof(*stream));
+  if(!stream)
+    return CURLE_OUT_OF_MEMORY;
+
+  stream->s.id = -1;
+  /* on send, we control how much we put into the buffer */
+  Curl_bufq_initp(&stream->sendbuf, &ctx->stream_bufcp,
+                  H3_STREAM_SEND_CHUNKS, BUFQ_OPT_NONE);
+  stream->sendbuf_len_in_flight = 0;
+  /* on recv, we need a flexible buffer limit since we also write
+   * headers to it that are not counted against the nghttp3 flow limits. */
+  Curl_bufq_initp(&stream->recvbuf, &ctx->stream_bufcp,
+                  H3_STREAM_RECV_CHUNKS, BUFQ_OPT_SOFT_LIMIT);
+  stream->recv_buf_nonflow = 0;
+  Curl_h1_req_parse_init(&stream->h1, H1_PARSE_DEFAULT_MAX_LINE_LEN);
+
+  if(!Curl_hash_offt_set(&ctx->streams, data->id, stream)) {
+    h3_stream_ctx_free(stream);
+    return CURLE_OUT_OF_MEMORY;
+  }
+
+  return CURLE_OK;
+}
+
+static void h3_data_done(struct Curl_cfilter *cf, struct Curl_easy *data)
+{
+  struct cf_osslq_ctx *ctx = cf->ctx;
+  struct h3_stream_ctx *stream = H3_STREAM_CTX(ctx, data);
+
+  (void)cf;
+  if(stream) {
+    CURL_TRC_CF(data, cf, "[%"CURL_PRId64"] easy handle is done",
+                stream->s.id);
+    if(ctx->h3.conn && !stream->closed) {
+      nghttp3_conn_shutdown_stream_read(ctx->h3.conn, stream->s.id);
+      nghttp3_conn_close_stream(ctx->h3.conn, stream->s.id,
+                                NGHTTP3_H3_REQUEST_CANCELLED);
+      nghttp3_conn_set_stream_user_data(ctx->h3.conn, stream->s.id, NULL);
+      stream->closed = TRUE;
+    }
+
+    Curl_hash_offt_remove(&ctx->streams, data->id);
+  }
+}
+
+static struct cf_osslq_stream *cf_osslq_get_qstream(struct Curl_cfilter *cf,
+                                                    struct Curl_easy *data,
+                                                    int64_t stream_id)
+{
+  struct cf_osslq_ctx *ctx = cf->ctx;
+  struct h3_stream_ctx *stream = H3_STREAM_CTX(ctx, data);
+  struct Curl_easy *sdata;
+
+  if(stream && stream->s.id == stream_id) {
+    return &stream->s;
+  }
+  else if(ctx->h3.s_ctrl.id == stream_id) {
+    return &ctx->h3.s_ctrl;
+  }
+  else if(ctx->h3.s_qpack_enc.id == stream_id) {
+    return &ctx->h3.s_qpack_enc;
+  }
+  else if(ctx->h3.s_qpack_dec.id == stream_id) {
+    return &ctx->h3.s_qpack_dec;
+  }
+  else {
+    DEBUGASSERT(data->multi);
+    for(sdata = data->multi->easyp; sdata; sdata = sdata->next) {
+      if(sdata->conn != data->conn)
+        continue;
+      stream = H3_STREAM_CTX(ctx, sdata);
+      if(stream && stream->s.id == stream_id) {
+        return &stream->s;
+      }
+    }
+  }
+  return NULL;
+}
+
+static void h3_drain_stream(struct Curl_cfilter *cf,
+                            struct Curl_easy *data)
+{
+  struct cf_osslq_ctx *ctx = cf->ctx;
+  struct h3_stream_ctx *stream = H3_STREAM_CTX(ctx, data);
+  unsigned char bits;
+
+  (void)cf;
+  bits = CURL_CSELECT_IN;
+  if(stream && stream->upload_left && !stream->send_closed)
+    bits |= CURL_CSELECT_OUT;
+  if(data->state.select_bits != bits) {
+    data->state.select_bits = bits;
+    Curl_expire(data, 0, EXPIRE_RUN_NOW);
+  }
+}
+
+static CURLcode h3_data_pause(struct Curl_cfilter *cf,
+                              struct Curl_easy *data,
+                              bool pause)
+{
+  if(!pause) {
+    /* unpaused. make it run again right away */
+    h3_drain_stream(cf, data);
+    Curl_expire(data, 0, EXPIRE_RUN_NOW);
+  }
+  return CURLE_OK;
+}
+
+static int cb_h3_stream_close(nghttp3_conn *conn, int64_t stream_id,
+                              uint64_t app_error_code, void *user_data,
+                              void *stream_user_data)
+{
+  struct Curl_cfilter *cf = user_data;
+  struct cf_osslq_ctx *ctx = cf->ctx;
+  struct Curl_easy *data = stream_user_data;
+  struct h3_stream_ctx *stream = H3_STREAM_CTX(ctx, data);
+  (void)conn;
+  (void)stream_id;
+
+  /* we might be called by nghttp3 after we already cleaned up */
+  if(!stream)
+    return 0;
+
+  stream->closed = TRUE;
+  stream->error3 = app_error_code;
+  if(stream->error3 != NGHTTP3_H3_NO_ERROR) {
+    stream->reset = TRUE;
+    stream->send_closed = TRUE;
+    CURL_TRC_CF(data, cf, "[%" CURL_PRId64 "] RESET: error %" CURL_PRIu64,
+                stream->s.id, stream->error3);
+  }
+  else {
+    CURL_TRC_CF(data, cf, "[%" CURL_PRId64 "] CLOSED", stream->s.id);
+  }
+  h3_drain_stream(cf, data);
+  return 0;
+}
+
+/*
+ * write_resp_raw() copies response data in raw format to the `data`'s
+  * receive buffer. If not enough space is available, it appends to the
+ * `data`'s overflow buffer.
+ */
+static CURLcode write_resp_raw(struct Curl_cfilter *cf,
+                               struct Curl_easy *data,
+                               const void *mem, size_t memlen,
+                               bool flow)
+{
+  struct cf_osslq_ctx *ctx = cf->ctx;
+  struct h3_stream_ctx *stream = H3_STREAM_CTX(ctx, data);
+  CURLcode result = CURLE_OK;
+  ssize_t nwritten;
+
+  (void)cf;
+  if(!stream) {
+    return CURLE_RECV_ERROR;
+  }
+  nwritten = Curl_bufq_write(&stream->recvbuf, mem, memlen, &result);
+  if(nwritten < 0) {
+    return result;
+  }
+
+  if(!flow)
+    stream->recv_buf_nonflow += (size_t)nwritten;
+
+  if((size_t)nwritten < memlen) {
+    /* This MUST not happen. Our recbuf is dimensioned to hold the
+     * full max_stream_window and then some for this very reason. */
+    DEBUGASSERT(0);
+    return CURLE_RECV_ERROR;
+  }
+  return result;
+}
+
+static int cb_h3_recv_data(nghttp3_conn *conn, int64_t stream3_id,
+                           const uint8_t *buf, size_t buflen,
+                           void *user_data, void *stream_user_data)
+{
+  struct Curl_cfilter *cf = user_data;
+  struct cf_osslq_ctx *ctx = cf->ctx;
+  struct Curl_easy *data = stream_user_data;
+  struct h3_stream_ctx *stream = H3_STREAM_CTX(ctx, data);
+  CURLcode result;
+
+  (void)conn;
+  (void)stream3_id;
+
+  if(!stream)
+    return NGHTTP3_ERR_CALLBACK_FAILURE;
+
+  result = write_resp_raw(cf, data, buf, buflen, TRUE);
+  if(result) {
+    CURL_TRC_CF(data, cf, "[%" CURL_PRId64 "] DATA len=%zu, ERROR %d",
+                stream->s.id, buflen, result);
+    return NGHTTP3_ERR_CALLBACK_FAILURE;
+  }
+  stream->download_recvd += (curl_off_t)buflen;
+  CURL_TRC_CF(data, cf, "[%" CURL_PRId64 "] DATA len=%zu, total=%zd",
+              stream->s.id, buflen, stream->download_recvd);
+  h3_drain_stream(cf, data);
+  return 0;
+}
+
+static int cb_h3_deferred_consume(nghttp3_conn *conn, int64_t stream_id,
+                                  size_t consumed, void *user_data,
+                                  void *stream_user_data)
+{
+  struct Curl_cfilter *cf = user_data;
+  struct cf_osslq_ctx *ctx = cf->ctx;
+  struct Curl_easy *data = stream_user_data;
+  struct h3_stream_ctx *stream = H3_STREAM_CTX(ctx, data);
+
+  (void)conn;
+  (void)stream_id;
+  if(stream)
+    CURL_TRC_CF(data, cf, "[%" CURL_PRId64 "] deferred consume %zu bytes",
+                stream->s.id, consumed);
+  return 0;
+}
+
+static int cb_h3_recv_header(nghttp3_conn *conn, int64_t sid,
+                             int32_t token, nghttp3_rcbuf *name,
+                             nghttp3_rcbuf *value, uint8_t flags,
+                             void *user_data, void *stream_user_data)
+{
+  struct Curl_cfilter *cf = user_data;
+  curl_int64_t stream_id = sid;
+  struct cf_osslq_ctx *ctx = cf->ctx;
+  nghttp3_vec h3name = nghttp3_rcbuf_get_buf(name);
+  nghttp3_vec h3val = nghttp3_rcbuf_get_buf(value);
+  struct Curl_easy *data = stream_user_data;
+  struct h3_stream_ctx *stream = H3_STREAM_CTX(ctx, data);
+  CURLcode result = CURLE_OK;
+  (void)conn;
+  (void)stream_id;
+  (void)token;
+  (void)flags;
+  (void)cf;
+
+  /* we might have cleaned up this transfer already */
+  if(!stream)
+    return 0;
+
+  if(token == NGHTTP3_QPACK_TOKEN__STATUS) {
+    char line[14]; /* status line is always 13 characters long */
+    size_t ncopy;
+
+    result = Curl_http_decode_status(&stream->status_code,
+                                     (const char *)h3val.base, h3val.len);
+    if(result)
+      return -1;
+    ncopy = msnprintf(line, sizeof(line), "HTTP/3 %03d \r\n",
+                      stream->status_code);
+    CURL_TRC_CF(data, cf, "[%" CURL_PRId64 "] status: %s", stream_id, line);
+    result = write_resp_raw(cf, data, line, ncopy, FALSE);
+    if(result) {
+      return -1;
+    }
+  }
+  else {
+    /* store as an HTTP1-style header */
+    CURL_TRC_CF(data, cf, "[%" CURL_PRId64 "] header: %.*s: %.*s",
+                stream_id, (int)h3name.len, h3name.base,
+                (int)h3val.len, h3val.base);
+    result = write_resp_raw(cf, data, h3name.base, h3name.len, FALSE);
+    if(result) {
+      return -1;
+    }
+    result = write_resp_raw(cf, data, ": ", 2, FALSE);
+    if(result) {
+      return -1;
+    }
+    result = write_resp_raw(cf, data, h3val.base, h3val.len, FALSE);
+    if(result) {
+      return -1;
+    }
+    result = write_resp_raw(cf, data, "\r\n", 2, FALSE);
+    if(result) {
+      return -1;
+    }
+  }
+  return 0;
+}
+
+static int cb_h3_end_headers(nghttp3_conn *conn, int64_t sid,
+                             int fin, void *user_data, void *stream_user_data)
+{
+  struct Curl_cfilter *cf = user_data;
+  struct cf_osslq_ctx *ctx = cf->ctx;
+  struct Curl_easy *data = stream_user_data;
+  curl_int64_t stream_id = sid;
+  struct h3_stream_ctx *stream = H3_STREAM_CTX(ctx, data);
+  CURLcode result = CURLE_OK;
+  (void)conn;
+  (void)stream_id;
+  (void)fin;
+  (void)cf;
+
+  if(!stream)
+    return 0;
+  /* add a CRLF only if we've received some headers */
+  result = write_resp_raw(cf, data, "\r\n", 2, FALSE);
+  if(result) {
+    return -1;
+  }
+
+  CURL_TRC_CF(data, cf, "[%" CURL_PRId64 "] end_headers, status=%d",
+              stream_id, stream->status_code);
+  if(stream->status_code / 100 != 1) {
+    stream->resp_hds_complete = TRUE;
+  }
+  h3_drain_stream(cf, data);
+  return 0;
+}
+
+static int cb_h3_stop_sending(nghttp3_conn *conn, int64_t sid,
+                              uint64_t app_error_code, void *user_data,
+                              void *stream_user_data)
+{
+  struct Curl_cfilter *cf = user_data;
+  struct cf_osslq_ctx *ctx = cf->ctx;
+  struct Curl_easy *data = stream_user_data;
+  curl_int64_t stream_id = sid;
+  struct h3_stream_ctx *stream = H3_STREAM_CTX(ctx, data);
+  (void)conn;
+  (void)app_error_code;
+
+  if(!stream || !stream->s.ssl)
+    return 0;
+
+  CURL_TRC_CF(data, cf, "[%" CURL_PRId64 "] stop_sending", stream_id);
+  cf_osslq_stream_close(&stream->s);
+  return 0;
+}
+
+static int cb_h3_reset_stream(nghttp3_conn *conn, int64_t sid,
+                              uint64_t app_error_code, void *user_data,
+                              void *stream_user_data) {
+  struct Curl_cfilter *cf = user_data;
+  struct cf_osslq_ctx *ctx = cf->ctx;
+  struct Curl_easy *data = stream_user_data;
+  curl_int64_t stream_id = sid;
+  struct h3_stream_ctx *stream = H3_STREAM_CTX(ctx, data);
+  int rv;
+  (void)conn;
+
+  if(stream && stream->s.ssl) {
+    SSL_STREAM_RESET_ARGS args = {0};
+    args.quic_error_code = app_error_code;
+    rv = !SSL_stream_reset(stream->s.ssl, &args, sizeof(args));
+    CURL_TRC_CF(data, cf, "[%" CURL_PRId64 "] reset -> %d", stream_id, rv);
+    if(!rv) {
+      return NGHTTP3_ERR_CALLBACK_FAILURE;
+    }
+  }
+  return 0;
+}
+
+static nghttp3_ssize
+cb_h3_read_req_body(nghttp3_conn *conn, int64_t stream_id,
+                    nghttp3_vec *vec, size_t veccnt,
+                    uint32_t *pflags, void *user_data,
+                    void *stream_user_data)
+{
+  struct Curl_cfilter *cf = user_data;
+  struct cf_osslq_ctx *ctx = cf->ctx;
+  struct Curl_easy *data = stream_user_data;
+  struct h3_stream_ctx *stream = H3_STREAM_CTX(ctx, data);
+  ssize_t nwritten = 0;
+  size_t nvecs = 0;
+  (void)cf;
+  (void)conn;
+  (void)stream_id;
+  (void)user_data;
+  (void)veccnt;
+
+  if(!stream)
+    return NGHTTP3_ERR_CALLBACK_FAILURE;
+  /* nghttp3 keeps references to the sendbuf data until it is ACKed
+   * by the server (see `cb_h3_acked_req_body()` for updates).
+   * `sendbuf_len_in_flight` is the amount of bytes in `sendbuf`
+   * that we have already passed to nghttp3, but which have not been
+   * ACKed yet.
+   * Any amount beyond `sendbuf_len_in_flight` we need still to pass
+   * to nghttp3. Do that now, if we can. */
+  if(stream->sendbuf_len_in_flight < Curl_bufq_len(&stream->sendbuf)) {
+    nvecs = 0;
+    while(nvecs < veccnt &&
+          Curl_bufq_peek_at(&stream->sendbuf,
+                            stream->sendbuf_len_in_flight,
+                            (const unsigned char **)&vec[nvecs].base,
+                            &vec[nvecs].len)) {
+      stream->sendbuf_len_in_flight += vec[nvecs].len;
+      nwritten += vec[nvecs].len;
+      ++nvecs;
+    }
+    DEBUGASSERT(nvecs > 0); /* we SHOULD have been be able to peek */
+  }
+
+  if(nwritten > 0 && stream->upload_left != -1)
+    stream->upload_left -= nwritten;
+
+  /* When we stopped sending and everything in `sendbuf` is "in flight",
+   * we are at the end of the request body. */
+  if(stream->upload_left == 0) {
+    *pflags = NGHTTP3_DATA_FLAG_EOF;
+    stream->send_closed = TRUE;
+  }
+  else if(!nwritten) {
+    /* Not EOF, and nothing to give, we signal WOULDBLOCK. */
+    CURL_TRC_CF(data, cf, "[%" CURL_PRId64 "] read req body -> AGAIN",
+                stream->s.id);
+    return NGHTTP3_ERR_WOULDBLOCK;
+  }
+
+  CURL_TRC_CF(data, cf, "[%" CURL_PRId64 "] read req body -> "
+              "%d vecs%s with %zu (buffered=%zu, left=%"
+              CURL_FORMAT_CURL_OFF_T ")",
+              stream->s.id, (int)nvecs,
+              *pflags == NGHTTP3_DATA_FLAG_EOF?" EOF":"",
+              nwritten, Curl_bufq_len(&stream->sendbuf),
+              stream->upload_left);
+  return (nghttp3_ssize)nvecs;
+}
+
+static int cb_h3_acked_stream_data(nghttp3_conn *conn, int64_t stream_id,
+                                   uint64_t datalen, void *user_data,
+                                   void *stream_user_data)
+{
+  struct Curl_cfilter *cf = user_data;
+  struct cf_osslq_ctx *ctx = cf->ctx;
+  struct Curl_easy *data = stream_user_data;
+  struct h3_stream_ctx *stream = H3_STREAM_CTX(ctx, data);
+  size_t skiplen;
+
+  (void)cf;
+  if(!stream)
+    return 0;
+  /* The server acknowledged `datalen` of bytes from our request body.
+   * This is a delta. We have kept this data in `sendbuf` for
+   * re-transmissions and can free it now. */
+  if(datalen >= (uint64_t)stream->sendbuf_len_in_flight)
+    skiplen = stream->sendbuf_len_in_flight;
+  else
+    skiplen = (size_t)datalen;
+  Curl_bufq_skip(&stream->sendbuf, skiplen);
+  stream->sendbuf_len_in_flight -= skiplen;
+
+  /* Everything ACKed, we resume upload processing */
+  if(!stream->sendbuf_len_in_flight) {
+    int rv = nghttp3_conn_resume_stream(conn, stream_id);
+    if(rv && rv != NGHTTP3_ERR_STREAM_NOT_FOUND) {
+      return NGHTTP3_ERR_CALLBACK_FAILURE;
+    }
+  }
+  return 0;
+}
+
+static nghttp3_callbacks ngh3_callbacks = {
+  cb_h3_acked_stream_data,
+  cb_h3_stream_close,
+  cb_h3_recv_data,
+  cb_h3_deferred_consume,
+  NULL, /* begin_headers */
+  cb_h3_recv_header,
+  cb_h3_end_headers,
+  NULL, /* begin_trailers */
+  cb_h3_recv_header,
+  NULL, /* end_trailers */
+  cb_h3_stop_sending,
+  NULL, /* end_stream */
+  cb_h3_reset_stream,
+  NULL, /* shutdown */
+  NULL /* recv_settings */
+};
+
+static CURLcode cf_osslq_h3conn_init(struct cf_osslq_ctx *ctx, SSL *conn,
+                                     void *user_data)
+{
+  struct cf_osslq_h3conn *h3 = &ctx->h3;
+  CURLcode result;
+  int rc;
+
+  nghttp3_settings_default(&h3->settings);
+  rc = nghttp3_conn_client_new(&h3->conn,
+                               &ngh3_callbacks,
+                               &h3->settings,
+                               nghttp3_mem_default(),
+                               user_data);
+  if(rc) {
+    result = CURLE_OUT_OF_MEMORY;
+    goto out;
+  }
+
+  result = cf_osslq_stream_open(&h3->s_ctrl, conn,
+                                SSL_STREAM_FLAG_ADVANCE|SSL_STREAM_FLAG_UNI,
+                                &ctx->stream_bufcp, NULL);
+  if(result) {
+    result = CURLE_QUIC_CONNECT_ERROR;
+    goto out;
+  }
+  result = cf_osslq_stream_open(&h3->s_qpack_enc, conn,
+                                SSL_STREAM_FLAG_ADVANCE|SSL_STREAM_FLAG_UNI,
+                                &ctx->stream_bufcp, NULL);
+  if(result) {
+    result = CURLE_QUIC_CONNECT_ERROR;
+    goto out;
+  }
+  result = cf_osslq_stream_open(&h3->s_qpack_dec, conn,
+                                SSL_STREAM_FLAG_ADVANCE|SSL_STREAM_FLAG_UNI,
+                                &ctx->stream_bufcp, NULL);
+  if(result) {
+    result = CURLE_QUIC_CONNECT_ERROR;
+    goto out;
+  }
+
+  rc = nghttp3_conn_bind_control_stream(h3->conn, h3->s_ctrl.id);
+  if(rc) {
+    result = CURLE_QUIC_CONNECT_ERROR;
+    goto out;
+  }
+  rc = nghttp3_conn_bind_qpack_streams(h3->conn, h3->s_qpack_enc.id,
+                                       h3->s_qpack_dec.id);
+  if(rc) {
+    result = CURLE_QUIC_CONNECT_ERROR;
+    goto out;
+  }
+
+  result = CURLE_OK;
+out:
+  return result;
+}
+
+static CURLcode cf_osslq_ctx_start(struct Curl_cfilter *cf,
+                                   struct Curl_easy *data)
+{
+  struct cf_osslq_ctx *ctx = cf->ctx;
+  CURLcode result;
+  int rv;
+  const struct Curl_sockaddr_ex *peer_addr = NULL;
+  BIO *bio = NULL;
+  BIO_ADDR *baddr = NULL;
+
+  Curl_bufcp_init(&ctx->stream_bufcp, H3_STREAM_CHUNK_SIZE,
+                  H3_STREAM_POOL_SPARES);
+  Curl_hash_offt_init(&ctx->streams, 63, h3_stream_hash_free);
+  result = Curl_ssl_peer_init(&ctx->peer, cf, TRNSPRT_QUIC);
+  if(result)
+    goto out;
+
+#define H3_ALPN "\x2h3"
+  result = Curl_vquic_tls_init(&ctx->tls, cf, data, &ctx->peer,
+                               H3_ALPN, sizeof(H3_ALPN) - 1,
+                               NULL, NULL, NULL);
+  if(result)
+    goto out;
+
+  result = vquic_ctx_init(&ctx->q);
+  if(result)
+    goto out;
+
+  result = CURLE_QUIC_CONNECT_ERROR;
+  Curl_cf_socket_peek(cf->next, data, &ctx->q.sockfd, &peer_addr, NULL);
+  if(!peer_addr)
+    goto out;
+
+  ctx->q.local_addrlen = sizeof(ctx->q.local_addr);
+  rv = getsockname(ctx->q.sockfd, (struct sockaddr *)&ctx->q.local_addr,
+                   &ctx->q.local_addrlen);
+  if(rv == -1)
+    goto out;
+
+  result = make_bio_addr(&baddr, peer_addr);
+  if(result) {
+    failf(data, "error creating BIO_ADDR from sockaddr");
+    goto out;
+  }
+
+  /* Type conversions, see #12861: OpenSSL wants an `int`, but on 64-bit
+   * Win32 systems, Microsoft defines SOCKET as `unsigned long long`.
+   */
+#if defined(_WIN32) && !defined(__LWIP_OPT_H__) && !defined(LWIP_HDR_OPT_H)
+  if(ctx->q.sockfd > INT_MAX) {
+    failf(data, "Windows socket identifier larger than MAX_INT, "
+          "unable to set in OpenSSL dgram API.");
+    result = CURLE_QUIC_CONNECT_ERROR;
+    goto out;
+  }
+  bio = BIO_new_dgram((int)ctx->q.sockfd, BIO_NOCLOSE);
+#else
+  bio = BIO_new_dgram(ctx->q.sockfd, BIO_NOCLOSE);
+#endif
+  if(!bio) {
+    result = CURLE_OUT_OF_MEMORY;
+    goto out;
+  }
+
+  if(!SSL_set1_initial_peer_addr(ctx->tls.ossl.ssl, baddr)) {
+    failf(data, "failed to set the initial peer address");
+    result = CURLE_FAILED_INIT;
+    goto out;
+  }
+  if(!SSL_set_blocking_mode(ctx->tls.ossl.ssl, 0)) {
+    failf(data, "failed to turn off blocking mode");
+    result = CURLE_FAILED_INIT;
+    goto out;
+  }
+
+#ifdef SSL_VALUE_QUIC_IDLE_TIMEOUT
+  /* Added in OpenSSL v3.3.x */
+  if(!SSL_set_feature_request_uint(ctx->tls.ossl.ssl,
+                                   SSL_VALUE_QUIC_IDLE_TIMEOUT,
+                                   CURL_QUIC_MAX_IDLE_MS)) {
+    CURL_TRC_CF(data, cf, "error setting idle timeout, ");
+    result = CURLE_FAILED_INIT;
+    goto out;
+  }
+#endif
+
+  SSL_set_bio(ctx->tls.ossl.ssl, bio, bio);
+  bio = NULL;
+  SSL_set_connect_state(ctx->tls.ossl.ssl);
+  SSL_set_incoming_stream_policy(ctx->tls.ossl.ssl,
+                                 SSL_INCOMING_STREAM_POLICY_ACCEPT, 0);
+  /* setup the H3 things on top of the QUIC connection */
+  result = cf_osslq_h3conn_init(ctx, ctx->tls.ossl.ssl, cf);
+
+out:
+  if(bio)
+    BIO_free(bio);
+  if(baddr)
+    BIO_ADDR_free(baddr);
+  CURL_TRC_CF(data, cf, "QUIC tls init -> %d", result);
+  return result;
+}
+
+struct h3_quic_recv_ctx {
+  struct Curl_cfilter *cf;
+  struct Curl_easy *data;
+  struct cf_osslq_stream *s;
+};
+
+static ssize_t h3_quic_recv(void *reader_ctx,
+                            unsigned char *buf, size_t len,
+                            CURLcode *err)
+{
+  struct h3_quic_recv_ctx *x = reader_ctx;
+  size_t nread;
+  int rv;
+
+  *err = CURLE_OK;
+  rv = SSL_read_ex(x->s->ssl, buf, len, &nread);
+  if(rv <= 0) {
+    int detail = SSL_get_error(x->s->ssl, rv);
+    if(detail == SSL_ERROR_WANT_READ || detail == SSL_ERROR_WANT_WRITE) {
+      *err = CURLE_AGAIN;
+      return -1;
+    }
+    else if(detail == SSL_ERROR_ZERO_RETURN) {
+      CURL_TRC_CF(x->data, x->cf, "[%" CURL_PRId64 "] h3_quic_recv -> EOS",
+                  x->s->id);
+      x->s->recvd_eos = TRUE;
+      return 0;
+    }
+    else if(SSL_get_stream_read_state(x->s->ssl) ==
+            SSL_STREAM_STATE_RESET_REMOTE) {
+      uint64_t app_error_code = NGHTTP3_H3_NO_ERROR;
+      SSL_get_stream_read_error_code(x->s->ssl, &app_error_code);
+      CURL_TRC_CF(x->data, x->cf, "[%" CURL_PRId64 "] h3_quic_recv -> RESET, "
+                  "rv=%d, app_err=%" CURL_PRIu64,
+                  x->s->id, rv, (curl_uint64_t)app_error_code);
+      if(app_error_code != NGHTTP3_H3_NO_ERROR) {
+        x->s->reset = TRUE;
+      }
+      x->s->recvd_eos = TRUE;
+      return 0;
+    }
+    else {
+      *err = cf_osslq_ssl_err(x->cf, x->data, detail, CURLE_RECV_ERROR);
+      return -1;
+    }
+  }
+  return (ssize_t)nread;
+}
+
+static CURLcode cf_osslq_stream_recv(struct cf_osslq_stream *s,
+                                     struct Curl_cfilter *cf,
+                                     struct Curl_easy *data)
+{
+  struct cf_osslq_ctx *ctx = cf->ctx;
+  CURLcode result = CURLE_OK;
+  ssize_t nread;
+  struct h3_quic_recv_ctx x;
+  int rv, eagain = FALSE;
+  size_t total_recv_len = 0;
+
+  DEBUGASSERT(s);
+  if(s->closed)
+    return CURLE_OK;
+
+  x.cf = cf;
+  x.data = data;
+  x.s = s;
+  while(s->ssl && !s->closed && !eagain &&
+        (total_recv_len < H3_STREAM_CHUNK_SIZE)) {
+    if(Curl_bufq_is_empty(&s->recvbuf) && !s->recvd_eos) {
+      while(!eagain && !s->recvd_eos && !Curl_bufq_is_full(&s->recvbuf)) {
+        nread = Curl_bufq_sipn(&s->recvbuf, 0, h3_quic_recv, &x, &result);
+        if(nread < 0) {
+          if(result != CURLE_AGAIN)
+            goto out;
+          result = CURLE_OK;
+          eagain = TRUE;
+        }
+      }
+    }
+
+    /* Forward what we have to nghttp3 */
+    if(!Curl_bufq_is_empty(&s->recvbuf)) {
+      const unsigned char *buf;
+      size_t blen;
+
+      while(Curl_bufq_peek(&s->recvbuf, &buf, &blen)) {
+        nread = nghttp3_conn_read_stream(ctx->h3.conn, s->id,
+                                         buf, blen, 0);
+        CURL_TRC_CF(data, cf, "[%" CURL_PRId64 "] forward %zu bytes "
+                    "to nghttp3 -> %zd", s->id, blen, nread);
+        if(nread < 0) {
+          failf(data, "nghttp3_conn_read_stream(len=%zu) error: %s",
+                blen, nghttp3_strerror((int)nread));
+          result = CURLE_RECV_ERROR;
+          goto out;
+        }
+        /* success, `nread` is the flow for QUIC to count as "consumed",
+         * not sure how that will work with OpenSSL. Anyways, without error,
+         * all data that we passed is not owned by nghttp3. */
+        Curl_bufq_skip(&s->recvbuf, blen);
+        total_recv_len += blen;
+      }
+    }
+
+    /* When we forwarded everything, handle RESET/EOS */
+    if(Curl_bufq_is_empty(&s->recvbuf) && !s->closed) {
+      result = CURLE_OK;
+      if(s->reset) {
+        uint64_t app_error;
+        if(!SSL_get_stream_read_error_code(s->ssl, &app_error)) {
+          failf(data, "SSL_get_stream_read_error_code returned error");
+          result = CURLE_RECV_ERROR;
+          goto out;
+        }
+        rv = nghttp3_conn_close_stream(ctx->h3.conn, s->id, app_error);
+        s->closed = TRUE;
+        if(rv < 0 && rv != NGHTTP3_ERR_STREAM_NOT_FOUND) {
+          failf(data, "nghttp3_conn_close_stream returned error: %s",
+                nghttp3_strerror(rv));
+          result = CURLE_RECV_ERROR;
+          goto out;
+        }
+      }
+      else if(s->recvd_eos) {
+        rv = nghttp3_conn_close_stream(ctx->h3.conn, s->id,
+                                       NGHTTP3_H3_NO_ERROR);
+        s->closed = TRUE;
+        CURL_TRC_CF(data, cf, "[%" CURL_PRId64 "] close nghttp3 stream -> %d",
+                    s->id, rv);
+        if(rv < 0 && rv != NGHTTP3_ERR_STREAM_NOT_FOUND) {
+          failf(data, "nghttp3_conn_close_stream returned error: %s",
+                nghttp3_strerror(rv));
+          result = CURLE_RECV_ERROR;
+          goto out;
+        }
+      }
+    }
+  }
+out:
+  if(result)
+    CURL_TRC_CF(data, cf, "[%" CURL_PRId64 "] cf_osslq_stream_recv -> %d",
+                s->id, result);
+  return result;
+}
+
+static CURLcode cf_progress_ingress(struct Curl_cfilter *cf,
+                                    struct Curl_easy *data)
+{
+  struct cf_osslq_ctx *ctx = cf->ctx;
+  CURLcode result = CURLE_OK;
+
+  if(!ctx->tls.ossl.ssl)
+    goto out;
+
+  ERR_clear_error();
+
+  /* 1. Check for new incoming streams */
+  while(1) {
+    SSL *snew = SSL_accept_stream(ctx->tls.ossl.ssl,
+                                  SSL_ACCEPT_STREAM_NO_BLOCK);
+    if(!snew)
+      break;
+
+    (void)cf_osslq_h3conn_add_stream(&ctx->h3, snew, cf, data);
+  }
+
+  if(!SSL_handle_events(ctx->tls.ossl.ssl)) {
+    int detail = SSL_get_error(ctx->tls.ossl.ssl, 0);
+    result = cf_osslq_ssl_err(cf, data, detail, CURLE_RECV_ERROR);
+  }
+
+  if(ctx->h3.conn) {
+    size_t i;
+    for(i = 0; i < ctx->h3.remote_ctrl_n; ++i) {
+      result = cf_osslq_stream_recv(&ctx->h3.remote_ctrl[i], cf, data);
+      if(result)
+        goto out;
+    }
+  }
+
+  if(ctx->h3.conn) {
+    struct Curl_easy *sdata;
+    struct h3_stream_ctx *stream;
+    /* PULL all open streams */
+    DEBUGASSERT(data->multi);
+    for(sdata = data->multi->easyp; sdata; sdata = sdata->next) {
+      if(sdata->conn == data->conn && CURL_WANT_RECV(sdata)) {
+        stream = H3_STREAM_CTX(ctx, sdata);
+        if(stream && !stream->closed &&
+           !Curl_bufq_is_full(&stream->recvbuf)) {
+          result = cf_osslq_stream_recv(&stream->s, cf, sdata);
+          if(result)
+            goto out;
+        }
+      }
+    }
+  }
+
+out:
+  CURL_TRC_CF(data, cf, "progress_ingress -> %d", result);
+  return result;
+}
+
+/* Iterate over all streams and check if blocked can be unblocked */
+static CURLcode cf_osslq_check_and_unblock(struct Curl_cfilter *cf,
+                                           struct Curl_easy *data)
+{
+  struct cf_osslq_ctx *ctx = cf->ctx;
+  struct Curl_easy *sdata;
+  struct h3_stream_ctx *stream;
+
+  if(ctx->h3.conn) {
+    for(sdata = data->multi->easyp; sdata; sdata = sdata->next) {
+      if(sdata->conn == data->conn) {
+        stream = H3_STREAM_CTX(ctx, sdata);
+        if(stream && stream->s.ssl && stream->s.send_blocked &&
+           !SSL_want_write(stream->s.ssl)) {
+          nghttp3_conn_unblock_stream(ctx->h3.conn, stream->s.id);
+          stream->s.send_blocked = FALSE;
+          h3_drain_stream(cf, sdata);
+          CURL_TRC_CF(sdata, cf, "unblocked");
+        }
+      }
+    }
+  }
+  return CURLE_OK;
+}
+
+static CURLcode h3_send_streams(struct Curl_cfilter *cf,
+                                struct Curl_easy *data)
+{
+  struct cf_osslq_ctx *ctx = cf->ctx;
+  CURLcode result = CURLE_OK;
+
+  if(!ctx->tls.ossl.ssl || !ctx->h3.conn)
+    goto out;
+
+  for(;;) {
+    struct cf_osslq_stream *s = NULL;
+    nghttp3_vec vec[16];
+    nghttp3_ssize n, i;
+    int64_t stream_id;
+    size_t written;
+    int eos, ok, rv;
+    size_t total_len, acked_len = 0;
+    bool blocked = FALSE, eos_written = FALSE;
+
+    n = nghttp3_conn_writev_stream(ctx->h3.conn, &stream_id, &eos,
+                                   vec, ARRAYSIZE(vec));
+    if(n < 0) {
+      failf(data, "nghttp3_conn_writev_stream returned error: %s",
+            nghttp3_strerror((int)n));
+      result = CURLE_SEND_ERROR;
+      goto out;
+    }
+    if(stream_id < 0) {
+      result = CURLE_OK;
+      goto out;
+    }
+
+    /* Get the stream for this data */
+    s = cf_osslq_get_qstream(cf, data, stream_id);
+    if(!s) {
+      failf(data, "nghttp3_conn_writev_stream gave unknown stream %"
+            CURL_PRId64, (curl_int64_t)stream_id);
+      result = CURLE_SEND_ERROR;
+      goto out;
+    }
+    /* Now write the data to the stream's SSL*, it may not all fit! */
+    DEBUGASSERT(s->id == stream_id);
+    for(i = 0, total_len = 0; i < n; ++i) {
+      total_len += vec[i].len;
+    }
+    for(i = 0; (i < n) && !blocked; ++i) {
+      /* Without stream->s.ssl, we closed that already, so
+       * pretend the write did succeed. */
+#ifdef SSL_WRITE_FLAG_CONCLUDE
+      /* Since OpenSSL v3.3.x, on last chunk set EOS if needed  */
+      uint64_t flags = (eos && ((i + 1) == n))? SSL_WRITE_FLAG_CONCLUDE : 0;
+      written = vec[i].len;
+      ok = !s->ssl || SSL_write_ex2(s->ssl, vec[i].base, vec[i].len, flags,
+                                   &written);
+      if(ok && flags & SSL_WRITE_FLAG_CONCLUDE)
+        eos_written = TRUE;
+#else
+      written = vec[i].len;
+      ok = !s->ssl || SSL_write_ex(s->ssl, vec[i].base, vec[i].len,
+                                   &written);
+#endif
+      if(ok) {
+        /* As OpenSSL buffers the data, we count this as acknowledged
+         * from nghttp3's point of view */
+        CURL_TRC_CF(data, cf, "[%" CURL_PRId64 "] send %zu bytes to QUIC ok",
+                    s->id, vec[i].len);
+        acked_len += vec[i].len;
+      }
+      else {
+        int detail = SSL_get_error(s->ssl, 0);
+        switch(detail) {
+        case SSL_ERROR_WANT_WRITE:
+        case SSL_ERROR_WANT_READ:
+          /* QUIC blocked us from writing more */
+          CURL_TRC_CF(data, cf, "[%"CURL_PRId64 "] send %zu bytes to "
+                      "QUIC blocked", s->id, vec[i].len);
+          written = 0;
+          nghttp3_conn_block_stream(ctx->h3.conn, s->id);
+          s->send_blocked = blocked = TRUE;
+          break;
+        default:
+          failf(data, "[%"CURL_PRId64 "] send %zu bytes to QUIC, SSL error %d",
+                s->id, vec[i].len, detail);
+          result = cf_osslq_ssl_err(cf, data, detail, CURLE_HTTP3);
+          goto out;
+        }
+      }
+    }
+
+    if(acked_len > 0 || (eos && !s->send_blocked)) {
+      /* Since QUIC buffers the data written internally, we can tell
+       * nghttp3 that it can move forward on it */
+      ctx->q.last_io = Curl_now();
+      rv = nghttp3_conn_add_write_offset(ctx->h3.conn, s->id, acked_len);
+      if(rv && rv != NGHTTP3_ERR_STREAM_NOT_FOUND) {
+        failf(data, "nghttp3_conn_add_write_offset returned error: %s\n",
+              nghttp3_strerror(rv));
+        result = CURLE_SEND_ERROR;
+        goto out;
+      }
+      rv = nghttp3_conn_add_ack_offset(ctx->h3.conn, s->id, acked_len);
+      if(rv && rv != NGHTTP3_ERR_STREAM_NOT_FOUND) {
+        failf(data, "nghttp3_conn_add_ack_offset returned error: %s\n",
+              nghttp3_strerror(rv));
+        result = CURLE_SEND_ERROR;
+        goto out;
+      }
+      CURL_TRC_CF(data, cf, "[%" CURL_PRId64 "] forwarded %zu/%zu h3 bytes "
+                  "to QUIC, eos=%d", s->id, acked_len, total_len, eos);
+    }
+
+    if(eos && !s->send_blocked && !eos_written) {
+      /* wrote everything and H3 indicates end of stream */
+      CURL_TRC_CF(data, cf, "[%" CURL_PRId64 "] closing QUIC stream", s->id);
+      SSL_stream_conclude(s->ssl, 0);
+    }
+  }
+
+out:
+  CURL_TRC_CF(data, cf, "h3_send_streams -> %d", result);
+  return result;
+}
+
+static CURLcode cf_progress_egress(struct Curl_cfilter *cf,
+                                   struct Curl_easy *data)
+{
+  struct cf_osslq_ctx *ctx = cf->ctx;
+  CURLcode result = CURLE_OK;
+
+  if(!ctx->tls.ossl.ssl)
+    goto out;
+
+  ERR_clear_error();
+  result = h3_send_streams(cf, data);
+  if(result)
+    goto out;
+
+  if(!SSL_handle_events(ctx->tls.ossl.ssl)) {
+    int detail = SSL_get_error(ctx->tls.ossl.ssl, 0);
+    result = cf_osslq_ssl_err(cf, data, detail, CURLE_SEND_ERROR);
+  }
+
+  result = cf_osslq_check_and_unblock(cf, data);
+
+out:
+  CURL_TRC_CF(data, cf, "progress_egress -> %d", result);
+  return result;
+}
+
+static CURLcode check_and_set_expiry(struct Curl_cfilter *cf,
+                                     struct Curl_easy *data)
+{
+  struct cf_osslq_ctx *ctx = cf->ctx;
+  CURLcode result = CURLE_OK;
+  struct timeval tv;
+  timediff_t timeoutms;
+  int is_infinite = TRUE;
+
+  if(ctx->tls.ossl.ssl &&
+    SSL_get_event_timeout(ctx->tls.ossl.ssl, &tv, &is_infinite) &&
+    !is_infinite) {
+    timeoutms = curlx_tvtoms(&tv);
+    /* QUIC want to be called again latest at the returned timeout */
+    if(timeoutms <= 0) {
+      result = cf_progress_ingress(cf, data);
+      if(result)
+        goto out;
+      result = cf_progress_egress(cf, data);
+      if(result)
+        goto out;
+      if(SSL_get_event_timeout(ctx->tls.ossl.ssl, &tv, &is_infinite)) {
+        timeoutms = curlx_tvtoms(&tv);
+      }
+    }
+    if(!is_infinite) {
+      Curl_expire(data, timeoutms, EXPIRE_QUIC);
+      CURL_TRC_CF(data, cf, "QUIC expiry in %ldms", (long)timeoutms);
+    }
+  }
+out:
+  return result;
+}
+
+static CURLcode cf_osslq_connect(struct Curl_cfilter *cf,
+                                 struct Curl_easy *data,
+                                 bool blocking, bool *done)
+{
+  struct cf_osslq_ctx *ctx = cf->ctx;
+  CURLcode result = CURLE_OK;
+  struct cf_call_data save;
+  struct curltime now;
+  int err;
+
+  if(cf->connected) {
+    *done = TRUE;
+    return CURLE_OK;
+  }
+
+  /* Connect the UDP filter first */
+  if(!cf->next->connected) {
+    result = Curl_conn_cf_connect(cf->next, data, blocking, done);
+    if(result || !*done)
+      return result;
+  }
+
+  *done = FALSE;
+  now = Curl_now();
+  CF_DATA_SAVE(save, cf, data);
+
+  if(ctx->reconnect_at.tv_sec && Curl_timediff(now, ctx->reconnect_at) < 0) {
+    /* Not time yet to attempt the next connect */
+    CURL_TRC_CF(data, cf, "waiting for reconnect time");
+    goto out;
+  }
+
+  if(!ctx->tls.ossl.ssl) {
+    ctx->started_at = now;
+    result = cf_osslq_ctx_start(cf, data);
+    if(result)
+      goto out;
+  }
+
+  if(!ctx->got_first_byte) {
+    int readable = SOCKET_READABLE(ctx->q.sockfd, 0);
+    if(readable > 0 && (readable & CURL_CSELECT_IN)) {
+      ctx->got_first_byte = TRUE;
+      ctx->first_byte_at = Curl_now();
+    }
+  }
+
+  ERR_clear_error();
+  err = SSL_do_handshake(ctx->tls.ossl.ssl);
+
+  if(err == 1) {
+    /* connected */
+    ctx->handshake_at = now;
+    ctx->q.last_io = now;
+    CURL_TRC_CF(data, cf, "handshake complete after %dms",
+               (int)Curl_timediff(now, ctx->started_at));
+    result = cf_osslq_verify_peer(cf, data);
+    if(!result) {
+      CURL_TRC_CF(data, cf, "peer verified");
+      cf->connected = TRUE;
+      cf->conn->alpn = CURL_HTTP_VERSION_3;
+      *done = TRUE;
+      connkeep(cf->conn, "HTTP/3 default");
+    }
+  }
+  else {
+    int detail = SSL_get_error(ctx->tls.ossl.ssl, err);
+    switch(detail) {
+    case SSL_ERROR_WANT_READ:
+      ctx->q.last_io = now;
+      CURL_TRC_CF(data, cf, "QUIC SSL_connect() -> WANT_RECV");
+      result = Curl_vquic_tls_before_recv(&ctx->tls, cf, data);
+      goto out;
+    case SSL_ERROR_WANT_WRITE:
+      ctx->q.last_io = now;
+      CURL_TRC_CF(data, cf, "QUIC SSL_connect() -> WANT_SEND");
+      result = CURLE_OK;
+      goto out;
+#ifdef SSL_ERROR_WANT_ASYNC
+    case SSL_ERROR_WANT_ASYNC:
+      ctx->q.last_io = now;
+      CURL_TRC_CF(data, cf, "QUIC SSL_connect() -> WANT_ASYNC");
+      result = CURLE_OK;
+      goto out;
+#endif
+#ifdef SSL_ERROR_WANT_RETRY_VERIFY
+    case SSL_ERROR_WANT_RETRY_VERIFY:
+      result = CURLE_OK;
+      goto out;
+#endif
+    default:
+      result = cf_osslq_ssl_err(cf, data, detail, CURLE_COULDNT_CONNECT);
+      goto out;
+    }
+  }
+
+out:
+  if(result == CURLE_RECV_ERROR && ctx->tls.ossl.ssl &&
+     ctx->protocol_shutdown) {
+    /* When a QUIC server instance is shutting down, it may send us a
+     * CONNECTION_CLOSE right away. Our connection then enters the DRAINING
+     * state. The CONNECT may work in the near future again. Indicate
+     * that as a "weird" reply. */
+    result = CURLE_WEIRD_SERVER_REPLY;
+  }
+
+#ifndef CURL_DISABLE_VERBOSE_STRINGS
+  if(result) {
+    struct ip_quadruple ip;
+
+    Curl_cf_socket_peek(cf->next, data, NULL, NULL, &ip);
+    infof(data, "QUIC connect to %s port %u failed: %s",
+          ip.remote_ip, ip.remote_port, curl_easy_strerror(result));
+  }
+#endif
+  if(!result)
+    result = check_and_set_expiry(cf, data);
+  if(result || *done)
+    CURL_TRC_CF(data, cf, "connect -> %d, done=%d", result, *done);
+  CF_DATA_RESTORE(cf, save);
+  return result;
+}
+
+static ssize_t h3_stream_open(struct Curl_cfilter *cf,
+                              struct Curl_easy *data,
+                              const void *buf, size_t len,
+                              CURLcode *err)
+{
+  struct cf_osslq_ctx *ctx = cf->ctx;
+  struct h3_stream_ctx *stream = NULL;
+  struct dynhds h2_headers;
+  size_t nheader;
+  nghttp3_nv *nva = NULL;
+  int rc = 0;
+  unsigned int i;
+  ssize_t nwritten = -1;
+  nghttp3_data_reader reader;
+  nghttp3_data_reader *preader = NULL;
+
+  Curl_dynhds_init(&h2_headers, 0, DYN_HTTP_REQUEST);
+
+  *err = h3_data_setup(cf, data);
+  if(*err)
+    goto out;
+  stream = H3_STREAM_CTX(ctx, data);
+  DEBUGASSERT(stream);
+  if(!stream) {
+    *err = CURLE_FAILED_INIT;
+    goto out;
+  }
+
+  nwritten = Curl_h1_req_parse_read(&stream->h1, buf, len, NULL, 0, err);
+  if(nwritten < 0)
+    goto out;
+  if(!stream->h1.done) {
+    /* need more data */
+    goto out;
+  }
+  DEBUGASSERT(stream->h1.req);
+
+  *err = Curl_http_req_to_h2(&h2_headers, stream->h1.req, data);
+  if(*err) {
+    nwritten = -1;
+    goto out;
+  }
+  /* no longer needed */
+  Curl_h1_req_parse_free(&stream->h1);
+
+  nheader = Curl_dynhds_count(&h2_headers);
+  nva = malloc(sizeof(nghttp3_nv) * nheader);
+  if(!nva) {
+    *err = CURLE_OUT_OF_MEMORY;
+    nwritten = -1;
+    goto out;
+  }
+
+  for(i = 0; i < nheader; ++i) {
+    struct dynhds_entry *e = Curl_dynhds_getn(&h2_headers, i);
+    nva[i].name = (unsigned char *)e->name;
+    nva[i].namelen = e->namelen;
+    nva[i].value = (unsigned char *)e->value;
+    nva[i].valuelen = e->valuelen;
+    nva[i].flags = NGHTTP3_NV_FLAG_NONE;
+  }
+
+  DEBUGASSERT(stream->s.id == -1);
+  *err = cf_osslq_stream_open(&stream->s, ctx->tls.ossl.ssl, 0,
+                              &ctx->stream_bufcp, data);
+  if(*err) {
+    failf(data, "can't get bidi streams");
+    *err = CURLE_SEND_ERROR;
+    goto out;
+  }
+
+  switch(data->state.httpreq) {
+  case HTTPREQ_POST:
+  case HTTPREQ_POST_FORM:
+  case HTTPREQ_POST_MIME:
+  case HTTPREQ_PUT:
+    /* known request body size or -1 */
+    if(data->state.infilesize != -1)
+      stream->upload_left = data->state.infilesize;
+    else
+      /* data sending without specifying the data amount up front */
+      stream->upload_left = -1; /* unknown */
+    break;
+  default:
+    /* there is not request body */
+    stream->upload_left = 0; /* no request body */
+    break;
+  }
+
+  stream->send_closed = (stream->upload_left == 0);
+  if(!stream->send_closed) {
+    reader.read_data = cb_h3_read_req_body;
+    preader = &reader;
+  }
+
+  rc = nghttp3_conn_submit_request(ctx->h3.conn, stream->s.id,
+                                   nva, nheader, preader, data);
+  if(rc) {
+    switch(rc) {
+    case NGHTTP3_ERR_CONN_CLOSING:
+      CURL_TRC_CF(data, cf, "h3sid[%"CURL_PRId64"] failed to send, "
+                  "connection is closing", stream->s.id);
+      break;
+    default:
+      CURL_TRC_CF(data, cf, "h3sid[%"CURL_PRId64 "] failed to send -> %d (%s)",
+                  stream->s.id, rc, nghttp3_strerror(rc));
+      break;
+    }
+    *err = CURLE_SEND_ERROR;
+    nwritten = -1;
+    goto out;
+  }
+
+  if(Curl_trc_is_verbose(data)) {
+    infof(data, "[HTTP/3] [%" CURL_PRId64 "] OPENED stream for %s",
+          stream->s.id, data->state.url);
+    for(i = 0; i < nheader; ++i) {
+      infof(data, "[HTTP/3] [%" CURL_PRId64 "] [%.*s: %.*s]",
+            stream->s.id,
+            (int)nva[i].namelen, nva[i].name,
+            (int)nva[i].valuelen, nva[i].value);
+    }
+  }
+
+out:
+  free(nva);
+  Curl_dynhds_free(&h2_headers);
+  return nwritten;
+}
+
+static ssize_t cf_osslq_send(struct Curl_cfilter *cf, struct Curl_easy *data,
+                             const void *buf, size_t len, CURLcode *err)
+{
+  struct cf_osslq_ctx *ctx = cf->ctx;
+  struct h3_stream_ctx *stream = H3_STREAM_CTX(ctx, data);
+  struct cf_call_data save;
+  ssize_t nwritten;
+  CURLcode result;
+
+  CF_DATA_SAVE(save, cf, data);
+  DEBUGASSERT(cf->connected);
+  DEBUGASSERT(ctx->tls.ossl.ssl);
+  DEBUGASSERT(ctx->h3.conn);
+  *err = CURLE_OK;
+
+  result = cf_progress_ingress(cf, data);
+  if(result) {
+    *err = result;
+    nwritten = -1;
+    goto out;
+  }
+
+  result = cf_progress_egress(cf, data);
+  if(result) {
+    *err = result;
+    nwritten = -1;
+    goto out;
+  }
+
+  if(!stream || stream->s.id < 0) {
+    nwritten = h3_stream_open(cf, data, buf, len, err);
+    if(nwritten < 0) {
+      CURL_TRC_CF(data, cf, "failed to open stream -> %d", *err);
+      goto out;
+    }
+    stream = H3_STREAM_CTX(ctx, data);
+  }
+  else if(stream->upload_blocked_len) {
+    /* the data in `buf` has already been submitted or added to the
+     * buffers, but have been EAGAINed on the last invocation. */
+    DEBUGASSERT(len >= stream->upload_blocked_len);
+    if(len < stream->upload_blocked_len) {
+      /* Did we get called again with a smaller `len`? This should not
+       * happen. We are not prepared to handle that. */
+      failf(data, "HTTP/3 send again with decreased length");
+      *err = CURLE_HTTP3;
+      nwritten = -1;
+      goto out;
+    }
+    nwritten = (ssize_t)stream->upload_blocked_len;
+    stream->upload_blocked_len = 0;
+  }
+  else if(stream->closed) {
+    if(stream->resp_hds_complete) {
+      /* Server decided to close the stream after having sent us a final
+       * response. This is valid if it is not interested in the request
+       * body. This happens on 30x or 40x responses.
+       * We silently discard the data sent, since this is not a transport
+       * error situation. */
+      CURL_TRC_CF(data, cf, "[%" CURL_PRId64 "] discarding data"
+                  "on closed stream with response", stream->s.id);
+      *err = CURLE_OK;
+      nwritten = (ssize_t)len;
+      goto out;
+    }
+    CURL_TRC_CF(data, cf, "[%" CURL_PRId64 "] send_body(len=%zu) "
+                "-> stream closed", stream->s.id, len);
+    *err = CURLE_HTTP3;
+    nwritten = -1;
+    goto out;
+  }
+  else {
+    nwritten = Curl_bufq_write(&stream->sendbuf, buf, len, err);
+    CURL_TRC_CF(data, cf, "[%" CURL_PRId64 "] cf_send, add to "
+                "sendbuf(len=%zu) -> %zd, %d",
+                stream->s.id, len, nwritten, *err);
+    if(nwritten < 0) {
+      goto out;
+    }
+
+    (void)nghttp3_conn_resume_stream(ctx->h3.conn, stream->s.id);
+  }
+
+  result = cf_progress_egress(cf, data);
+  if(result) {
+    *err = result;
+    nwritten = -1;
+  }
+
+  if(stream && nwritten > 0 && stream->sendbuf_len_in_flight) {
+    /* We have unacknowledged DATA and cannot report success to our
+     * caller. Instead we EAGAIN and remember how much we have already
+     * "written" into our various internal connection buffers. */
+    stream->upload_blocked_len = nwritten;
+    CURL_TRC_CF(data, cf, "[%" CURL_PRId64 "] cf_send(len=%zu), "
+                "%zu bytes in flight -> EGAIN", stream->s.id, len,
+                stream->sendbuf_len_in_flight);
+    *err = CURLE_AGAIN;
+    nwritten = -1;
+  }
+
+out:
+  result = check_and_set_expiry(cf, data);
+  CURL_TRC_CF(data, cf, "[%" CURL_PRId64 "] cf_send(len=%zu) -> %zd, %d",
+              stream? stream->s.id : -1, len, nwritten, *err);
+  CF_DATA_RESTORE(cf, save);
+  return nwritten;
+}
+
+static ssize_t recv_closed_stream(struct Curl_cfilter *cf,
+                                  struct Curl_easy *data,
+                                  struct h3_stream_ctx *stream,
+                                  CURLcode *err)
+{
+  ssize_t nread = -1;
+
+  (void)cf;
+  if(stream->reset) {
+    failf(data,
+          "HTTP/3 stream %" CURL_PRId64 " reset by server",
+          stream->s.id);
+    *err = data->req.bytecount? CURLE_PARTIAL_FILE : CURLE_HTTP3;
+    goto out;
+  }
+  else if(!stream->resp_hds_complete) {
+    failf(data,
+          "HTTP/3 stream %" CURL_PRId64
+          " was closed cleanly, but before getting"
+          " all response header fields, treated as error",
+          stream->s.id);
+    *err = CURLE_HTTP3;
+    goto out;
+  }
+  *err = CURLE_OK;
+  nread = 0;
+
+out:
+  return nread;
+}
+
+static ssize_t cf_osslq_recv(struct Curl_cfilter *cf, struct Curl_easy *data,
+                             char *buf, size_t len, CURLcode *err)
+{
+  struct cf_osslq_ctx *ctx = cf->ctx;
+  struct h3_stream_ctx *stream = H3_STREAM_CTX(ctx, data);
+  ssize_t nread = -1;
+  struct cf_call_data save;
+  CURLcode result;
+
+  (void)ctx;
+  CF_DATA_SAVE(save, cf, data);
+  DEBUGASSERT(cf->connected);
+  DEBUGASSERT(ctx);
+  DEBUGASSERT(ctx->tls.ossl.ssl);
+  DEBUGASSERT(ctx->h3.conn);
+  *err = CURLE_OK;
+
+  if(!stream) {
+    *err = CURLE_RECV_ERROR;
+    goto out;
+  }
+
+  if(!Curl_bufq_is_empty(&stream->recvbuf)) {
+    nread = Curl_bufq_read(&stream->recvbuf,
+                           (unsigned char *)buf, len, err);
+    if(nread < 0) {
+      CURL_TRC_CF(data, cf, "[%" CURL_PRId64 "] read recvbuf(len=%zu) "
+                  "-> %zd, %d", stream->s.id, len, nread, *err);
+      goto out;
+    }
+  }
+
+  result = cf_progress_ingress(cf, data);
+  if(result) {
+    *err = result;
+    nread = -1;
+    goto out;
+  }
+
+  /* recvbuf had nothing before, maybe after progressing ingress? */
+  if(nread < 0 && !Curl_bufq_is_empty(&stream->recvbuf)) {
+    nread = Curl_bufq_read(&stream->recvbuf,
+                           (unsigned char *)buf, len, err);
+    if(nread < 0) {
+      CURL_TRC_CF(data, cf, "[%" CURL_PRId64 "] read recvbuf(len=%zu) "
+                  "-> %zd, %d", stream->s.id, len, nread, *err);
+      goto out;
+    }
+  }
+
+  if(nread > 0) {
+    h3_drain_stream(cf, data);
+  }
+  else {
+    if(stream->closed) {
+      nread = recv_closed_stream(cf, data, stream, err);
+      goto out;
+    }
+    *err = CURLE_AGAIN;
+    nread = -1;
+  }
+
+out:
+  if(cf_progress_egress(cf, data)) {
+    *err = CURLE_SEND_ERROR;
+    nread = -1;
+  }
+  else {
+    CURLcode result2 = check_and_set_expiry(cf, data);
+    if(result2) {
+      *err = result2;
+      nread = -1;
+    }
+  }
+  CURL_TRC_CF(data, cf, "[%" CURL_PRId64 "] cf_recv(len=%zu) -> %zd, %d",
+              stream? stream->s.id : -1, len, nread, *err);
+  CF_DATA_RESTORE(cf, save);
+  return nread;
+}
+
+/*
+ * Called from transfer.c:data_pending to know if we should keep looping
+ * to receive more data from the connection.
+ */
+static bool cf_osslq_data_pending(struct Curl_cfilter *cf,
+                                  const struct Curl_easy *data)
+{
+  struct cf_osslq_ctx *ctx = cf->ctx;
+  const struct h3_stream_ctx *stream = H3_STREAM_CTX(ctx, data);
+  (void)cf;
+  return stream && !Curl_bufq_is_empty(&stream->recvbuf);
+}
+
+static CURLcode cf_osslq_data_event(struct Curl_cfilter *cf,
+                                    struct Curl_easy *data,
+                                    int event, int arg1, void *arg2)
+{
+  struct cf_osslq_ctx *ctx = cf->ctx;
+  CURLcode result = CURLE_OK;
+  struct cf_call_data save;
+
+  CF_DATA_SAVE(save, cf, data);
+  (void)arg1;
+  (void)arg2;
+  switch(event) {
+  case CF_CTRL_DATA_SETUP:
+    break;
+  case CF_CTRL_DATA_PAUSE:
+    result = h3_data_pause(cf, data, (arg1 != 0));
+    break;
+  case CF_CTRL_DATA_DETACH:
+    h3_data_done(cf, data);
+    break;
+  case CF_CTRL_DATA_DONE:
+    h3_data_done(cf, data);
+    break;
+  case CF_CTRL_DATA_DONE_SEND: {
+    struct h3_stream_ctx *stream = H3_STREAM_CTX(ctx, data);
+    if(stream && !stream->send_closed) {
+      stream->send_closed = TRUE;
+      stream->upload_left = Curl_bufq_len(&stream->sendbuf);
+      (void)nghttp3_conn_resume_stream(ctx->h3.conn, stream->s.id);
+    }
+    break;
+  }
+  case CF_CTRL_DATA_IDLE: {
+    struct h3_stream_ctx *stream = H3_STREAM_CTX(ctx, data);
+    CURL_TRC_CF(data, cf, "data idle");
+    if(stream && !stream->closed) {
+      result = check_and_set_expiry(cf, data);
+    }
+    break;
+  }
+  default:
+    break;
+  }
+  CF_DATA_RESTORE(cf, save);
+  return result;
+}
+
+static bool cf_osslq_conn_is_alive(struct Curl_cfilter *cf,
+                                   struct Curl_easy *data,
+                                   bool *input_pending)
+{
+  struct cf_osslq_ctx *ctx = cf->ctx;
+  bool alive = FALSE;
+  struct cf_call_data save;
+
+  CF_DATA_SAVE(save, cf, data);
+  *input_pending = FALSE;
+  if(!ctx->tls.ossl.ssl)
+    goto out;
+
+#ifdef SSL_VALUE_QUIC_IDLE_TIMEOUT
+  /* Added in OpenSSL v3.3.x */
+  {
+    timediff_t idletime;
+    uint64_t idle_ms = ctx->max_idle_ms;
+    if(!SSL_get_value_uint(ctx->tls.ossl.ssl,
+                           SSL_VALUE_CLASS_FEATURE_NEGOTIATED,
+                           SSL_VALUE_QUIC_IDLE_TIMEOUT, &idle_ms)) {
+      CURL_TRC_CF(data, cf, "error getting negotiated idle timeout, "
+                  "assume connection is dead.");
+      goto out;
+    }
+    CURL_TRC_CF(data, cf, "negotiated idle timeout: %zums", (size_t)idle_ms);
+    idletime = Curl_timediff(Curl_now(), ctx->q.last_io);
+    if(idletime > 0 && (uint64_t)idletime > idle_ms)
+      goto out;
+  }
+
+#endif
+
+  if(!cf->next || !cf->next->cft->is_alive(cf->next, data, input_pending))
+    goto out;
+
+  alive = TRUE;
+  if(*input_pending) {
+    CURLcode result;
+    /* This happens before we've sent off a request and the connection is
+       not in use by any other transfer, there shouldn't be any data here,
+       only "protocol frames" */
+    *input_pending = FALSE;
+    result = cf_progress_ingress(cf, data);
+    CURL_TRC_CF(data, cf, "is_alive, progress ingress -> %d", result);
+    alive = result? FALSE : TRUE;
+  }
+
+out:
+  CF_DATA_RESTORE(cf, save);
+  return alive;
+}
+
+static void cf_osslq_adjust_pollset(struct Curl_cfilter *cf,
+                                    struct Curl_easy *data,
+                                    struct easy_pollset *ps)
+{
+  struct cf_osslq_ctx *ctx = cf->ctx;
+
+  if(!ctx->tls.ossl.ssl) {
+    /* NOP */
+  }
+  else if(!cf->connected) {
+    /* during handshake, transfer has not started yet. we always
+     * add our socket for polling if SSL wants to send/recv */
+    Curl_pollset_set(data, ps, ctx->q.sockfd,
+                     SSL_net_read_desired(ctx->tls.ossl.ssl),
+                     SSL_net_write_desired(ctx->tls.ossl.ssl));
+  }
+  else {
+    /* once connected, we only modify the socket if it is present.
+     * this avoids adding it for paused transfers. */
+    bool want_recv, want_send;
+    Curl_pollset_check(data, ps, ctx->q.sockfd, &want_recv, &want_send);
+    if(want_recv || want_send) {
+      Curl_pollset_set(data, ps, ctx->q.sockfd,
+                       SSL_net_read_desired(ctx->tls.ossl.ssl),
+                       SSL_net_write_desired(ctx->tls.ossl.ssl));
+    }
+  }
+}
+
+static CURLcode cf_osslq_query(struct Curl_cfilter *cf,
+                               struct Curl_easy *data,
+                               int query, int *pres1, void *pres2)
+{
+  struct cf_osslq_ctx *ctx = cf->ctx;
+
+  switch(query) {
+  case CF_QUERY_MAX_CONCURRENT: {
+#ifdef SSL_VALUE_QUIC_STREAM_BIDI_LOCAL_AVAIL
+    /* Added in OpenSSL v3.3.x */
+    uint64_t v;
+    if(!SSL_get_value_uint(ctx->tls.ossl.ssl, SSL_VALUE_CLASS_GENERIC,
+                           SSL_VALUE_QUIC_STREAM_BIDI_LOCAL_AVAIL, &v)) {
+      CURL_TRC_CF(data, cf, "error getting available local bidi streams");
+      return CURLE_HTTP3;
+    }
+    /* we report avail + in_use */
+    v += CONN_INUSE(cf->conn);
+    *pres1 = (v > INT_MAX)? INT_MAX : (int)v;
+#else
+    *pres1 = 100;
+#endif
+    CURL_TRC_CF(data, cf, "query max_conncurrent -> %d", *pres1);
+    return CURLE_OK;
+  }
+  case CF_QUERY_CONNECT_REPLY_MS:
+    if(ctx->got_first_byte) {
+      timediff_t ms = Curl_timediff(ctx->first_byte_at, ctx->started_at);
+      *pres1 = (ms < INT_MAX)? (int)ms : INT_MAX;
+    }
+    else
+      *pres1 = -1;
+    return CURLE_OK;
+  case CF_QUERY_TIMER_CONNECT: {
+    struct curltime *when = pres2;
+    if(ctx->got_first_byte)
+      *when = ctx->first_byte_at;
+    return CURLE_OK;
+  }
+  case CF_QUERY_TIMER_APPCONNECT: {
+    struct curltime *when = pres2;
+    if(cf->connected)
+      *when = ctx->handshake_at;
+    return CURLE_OK;
+  }
+  default:
+    break;
+  }
+  return cf->next?
+    cf->next->cft->query(cf->next, data, query, pres1, pres2) :
+    CURLE_UNKNOWN_OPTION;
+}
+
+struct Curl_cftype Curl_cft_http3 = {
+  "HTTP/3",
+  CF_TYPE_IP_CONNECT | CF_TYPE_SSL | CF_TYPE_MULTIPLEX,
+  0,
+  cf_osslq_destroy,
+  cf_osslq_connect,
+  cf_osslq_close,
+  Curl_cf_def_get_host,
+  cf_osslq_adjust_pollset,
+  cf_osslq_data_pending,
+  cf_osslq_send,
+  cf_osslq_recv,
+  cf_osslq_data_event,
+  cf_osslq_conn_is_alive,
+  Curl_cf_def_conn_keep_alive,
+  cf_osslq_query,
+};
+
+CURLcode Curl_cf_osslq_create(struct Curl_cfilter **pcf,
+                              struct Curl_easy *data,
+                              struct connectdata *conn,
+                              const struct Curl_addrinfo *ai)
+{
+  struct cf_osslq_ctx *ctx = NULL;
+  struct Curl_cfilter *cf = NULL, *udp_cf = NULL;
+  CURLcode result;
+
+  (void)data;
+  ctx = calloc(1, sizeof(*ctx));
+  if(!ctx) {
+    result = CURLE_OUT_OF_MEMORY;
+    goto out;
+  }
+  cf_osslq_ctx_clear(ctx);
+
+  result = Curl_cf_create(&cf, &Curl_cft_http3, ctx);
+  if(result)
+    goto out;
+
+  result = Curl_cf_udp_create(&udp_cf, data, conn, ai, TRNSPRT_QUIC);
+  if(result)
+    goto out;
+
+  cf->conn = conn;
+  udp_cf->conn = cf->conn;
+  udp_cf->sockindex = cf->sockindex;
+  cf->next = udp_cf;
+
+out:
+  *pcf = (!result)? cf : NULL;
+  if(result) {
+    if(udp_cf)
+      Curl_conn_cf_discard_sub(cf, udp_cf, data, TRUE);
+    Curl_safefree(cf);
+    Curl_safefree(ctx);
+  }
+  return result;
+}
+
+bool Curl_conn_is_osslq(const struct Curl_easy *data,
+                        const struct connectdata *conn,
+                        int sockindex)
+{
+  struct Curl_cfilter *cf = conn? conn->cfilter[sockindex] : NULL;
+
+  (void)data;
+  for(; cf; cf = cf->next) {
+    if(cf->cft == &Curl_cft_http3)
+      return TRUE;
+    if(cf->cft->flags & CF_TYPE_IP_CONNECT)
+      return FALSE;
+  }
+  return FALSE;
+}
+
+/*
+ * Store ngtcp2 version info in this buffer.
+ */
+void Curl_osslq_ver(char *p, size_t len)
+{
+  const nghttp3_info *ht3 = nghttp3_version(0);
+  (void)msnprintf(p, len, "nghttp3/%s", ht3->version_str);
+}
+
+#endif /* USE_OPENSSL_QUIC && USE_NGHTTP3 */
diff --git a/vendor/curl/lib/vquic/curl_osslq.h b/vendor/curl/lib/vquic/curl_osslq.h
new file mode 100644
index 0000000000..0e12d7023e
--- /dev/null
+++ b/vendor/curl/lib/vquic/curl_osslq.h
@@ -0,0 +1,51 @@
+#ifndef HEADER_CURL_VQUIC_CURL_OSSLQ_H
+#define HEADER_CURL_VQUIC_CURL_OSSLQ_H
+/***************************************************************************
+ *                                  _   _ ____  _
+ *  Project                     ___| | | |  _ \| |
+ *                             / __| | | | |_) | |
+ *                            | (__| |_| |  _ <| |___
+ *                             \___|\___/|_| \_\_____|
+ *
+ * Copyright (C) Daniel Stenberg, , et al.
+ *
+ * This software is licensed as described in the file COPYING, which
+ * you should have received as part of this distribution. The terms
+ * are also available at https://curl.se/docs/copyright.html.
+ *
+ * You may opt to use, copy, modify, merge, publish, distribute and/or sell
+ * copies of the Software, and permit persons to whom the Software is
+ * furnished to do so, under the terms of the COPYING file.
+ *
+ * This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY
+ * KIND, either express or implied.
+ *
+ * SPDX-License-Identifier: curl
+ *
+ ***************************************************************************/
+
+#include "curl_setup.h"
+
+#if defined(USE_OPENSSL_QUIC) && defined(USE_NGHTTP3)
+
+#ifdef HAVE_NETINET_UDP_H
+#include 
+#endif
+
+struct Curl_cfilter;
+
+#include "urldata.h"
+
+void Curl_osslq_ver(char *p, size_t len);
+
+CURLcode Curl_cf_osslq_create(struct Curl_cfilter **pcf,
+                              struct Curl_easy *data,
+                              struct connectdata *conn,
+                              const struct Curl_addrinfo *ai);
+
+bool Curl_conn_is_osslq(const struct Curl_easy *data,
+                        const struct connectdata *conn,
+                        int sockindex);
+#endif
+
+#endif /* HEADER_CURL_VQUIC_CURL_OSSLQ_H */
diff --git a/vendor/curl/lib/vquic/curl_quiche.c b/vendor/curl/lib/vquic/curl_quiche.c
index 3598de1c7a..a68fc6430c 100644
--- a/vendor/curl/lib/vquic/curl_quiche.c
+++ b/vendor/curl/lib/vquic/curl_quiche.c
@@ -29,6 +29,7 @@
 #include 
 #include 
 #include "bufq.h"
+#include "hash.h"
 #include "urldata.h"
 #include "cfilters.h"
 #include "cf-socket.h"
@@ -43,6 +44,7 @@
 #include "http1.h"
 #include "vquic.h"
 #include "vquic_int.h"
+#include "vquic-tls.h"
 #include "curl_quiche.h"
 #include "transfer.h"
 #include "inet_pton.h"
@@ -55,10 +57,10 @@
 #include "curl_memory.h"
 #include "memdebug.h"
 
-/* #define DEBUG_QUICHE */
+/* HTTP/3 error values defined in RFC 9114, ch. 8.1 */
+#define CURL_H3_NO_ERROR  (0x0100)
 
 #define QUIC_MAX_STREAMS              (100)
-#define QUIC_IDLE_TIMEOUT        (60 * 1000) /* milliseconds */
 
 #define H3_STREAM_WINDOW_SIZE  (128 * 1024)
 #define H3_STREAM_CHUNK_SIZE    (16 * 1024)
@@ -84,30 +86,22 @@ void Curl_quiche_ver(char *p, size_t len)
   (void)msnprintf(p, len, "quiche/%s", quiche_version());
 }
 
-static void keylog_callback(const SSL *ssl, const char *line)
-{
-  (void)ssl;
-  Curl_tls_keylog_write_line(line);
-}
-
 struct cf_quiche_ctx {
   struct cf_quic_ctx q;
+  struct ssl_peer peer;
+  struct curl_tls_ctx tls;
   quiche_conn *qconn;
   quiche_config *cfg;
   quiche_h3_conn *h3c;
   quiche_h3_config *h3config;
   uint8_t scid[QUICHE_MAX_CONN_ID_LEN];
-  SSL_CTX *sslctx;
-  SSL *ssl;
   struct curltime started_at;        /* time the current attempt started */
   struct curltime handshake_at;      /* time connect handshake finished */
-  struct curltime first_byte_at;     /* when first byte was recvd */
   struct curltime reconnect_at;      /* time the next attempt should start */
   struct bufc_pool stream_bufcp;     /* chunk pool for streams */
+  struct Curl_hash streams;          /* hash `data->id` to `stream_ctx` */
   curl_off_t data_recvd;
-  size_t sends_on_hold;              /* # of streams with SEND_HOLD set */
   BIT(goaway);                       /* got GOAWAY from server */
-  BIT(got_first_byte);               /* if first byte was received */
   BIT(x509_store_setup);             /* if x509 store has been set up */
 };
 
@@ -122,162 +116,62 @@ static void quiche_debug_log(const char *line, void *argp)
 static void cf_quiche_ctx_clear(struct cf_quiche_ctx *ctx)
 {
   if(ctx) {
-    vquic_ctx_free(&ctx->q);
-    if(ctx->qconn)
-      quiche_conn_free(ctx->qconn);
-    if(ctx->h3config)
-      quiche_h3_config_free(ctx->h3config);
     if(ctx->h3c)
       quiche_h3_conn_free(ctx->h3c);
+    if(ctx->h3config)
+      quiche_h3_config_free(ctx->h3config);
+    if(ctx->qconn)
+      quiche_conn_free(ctx->qconn);
     if(ctx->cfg)
       quiche_config_free(ctx->cfg);
+    /* quiche just freed it */
+    ctx->tls.ossl.ssl = NULL;
+    Curl_vquic_tls_cleanup(&ctx->tls);
+    Curl_ssl_peer_cleanup(&ctx->peer);
+    vquic_ctx_free(&ctx->q);
     Curl_bufcp_free(&ctx->stream_bufcp);
-    memset(ctx, 0, sizeof(*ctx));
-  }
-}
-
-static CURLcode quic_x509_store_setup(struct Curl_cfilter *cf,
-                                      struct Curl_easy *data)
-{
-  struct cf_quiche_ctx *ctx = cf->ctx;
+    Curl_hash_clean(&ctx->streams);
+    Curl_hash_destroy(&ctx->streams);
 
-  if(!ctx->x509_store_setup) {
-    if(cf->conn->ssl_config.verifypeer) {
-      const char * const ssl_cafile = cf->conn->ssl_config.CAfile;
-      const char * const ssl_capath = cf->conn->ssl_config.CApath;
-      if(ssl_cafile || ssl_capath) {
-        SSL_CTX_set_verify(ctx->sslctx, SSL_VERIFY_PEER, NULL);
-        /* tell OpenSSL where to find CA certificates that are used to verify
-           the server's certificate. */
-        if(!SSL_CTX_load_verify_locations(
-              ctx->sslctx, ssl_cafile, ssl_capath)) {
-          /* Fail if we insist on successfully verifying the server. */
-          failf(data, "error setting certificate verify locations:"
-                "  CAfile: %s CApath: %s",
-                ssl_cafile ? ssl_cafile : "none",
-                ssl_capath ? ssl_capath : "none");
-          return CURLE_SSL_CACERT_BADFILE;
-        }
-        infof(data, " CAfile: %s", ssl_cafile ? ssl_cafile : "none");
-        infof(data, " CApath: %s", ssl_capath ? ssl_capath : "none");
-      }
-#ifdef CURL_CA_FALLBACK
-      else {
-        /* verifying the peer without any CA certificates won't work so
-           use openssl's built-in default as fallback */
-        SSL_CTX_set_default_verify_paths(ssl_ctx);
-      }
-#endif
-    }
-    ctx->x509_store_setup = TRUE;
+    memset(ctx, 0, sizeof(*ctx));
   }
-  return CURLE_OK;
 }
 
-static CURLcode quic_ssl_setup(struct Curl_cfilter *cf, struct Curl_easy *data)
-{
-  struct cf_quiche_ctx *ctx = cf->ctx;
-  unsigned char checkip[16];
-
-  DEBUGASSERT(!ctx->sslctx);
-  ctx->sslctx = SSL_CTX_new(TLS_method());
-  if(!ctx->sslctx)
-    return CURLE_OUT_OF_MEMORY;
-
-  SSL_CTX_set_alpn_protos(ctx->sslctx,
-                          (const uint8_t *)QUICHE_H3_APPLICATION_PROTOCOL,
-                          sizeof(QUICHE_H3_APPLICATION_PROTOCOL) - 1);
-
-  SSL_CTX_set_default_verify_paths(ctx->sslctx);
-
-  /* Open the file if a TLS or QUIC backend has not done this before. */
-  Curl_tls_keylog_open();
-  if(Curl_tls_keylog_enabled()) {
-    SSL_CTX_set_keylog_callback(ctx->sslctx, keylog_callback);
-  }
-
-  ctx->ssl = SSL_new(ctx->sslctx);
-  if(!ctx->ssl)
-    return CURLE_QUIC_CONNECT_ERROR;
-
-  SSL_set_app_data(ctx->ssl, cf);
-
-  if((0 == Curl_inet_pton(AF_INET, cf->conn->host.name, checkip))
-#ifdef ENABLE_IPV6
-     && (0 == Curl_inet_pton(AF_INET6, cf->conn->host.name, checkip))
-#endif
-     ) {
-    char *snihost = Curl_ssl_snihost(data, cf->conn->host.name, NULL);
-    if(!snihost || !SSL_set_tlsext_host_name(ctx->ssl, snihost)) {
-      failf(data, "Failed set SNI");
-      SSL_free(ctx->ssl);
-      ctx->ssl = NULL;
-      return CURLE_QUIC_CONNECT_ERROR;
-    }
-  }
-
-  return CURLE_OK;
-}
+static CURLcode cf_flush_egress(struct Curl_cfilter *cf,
+                                struct Curl_easy *data);
 
 /**
  * All about the H3 internals of a stream
  */
 struct stream_ctx {
-  int64_t id; /* HTTP/3 protocol stream identifier */
+  curl_uint64_t id; /* HTTP/3 protocol stream identifier */
   struct bufq recvbuf; /* h3 response */
   struct h1_req_parser h1; /* h1 request parsing */
-  uint64_t error3; /* HTTP/3 stream error code */
+  curl_uint64_t error3; /* HTTP/3 stream error code */
   curl_off_t upload_left; /* number of request bytes left to upload */
-  bool closed; /* TRUE on stream close */
-  bool reset;  /* TRUE on stream reset */
-  bool send_closed; /* stream is locally closed */
-  bool resp_hds_complete;  /* complete, final response has been received */
-  bool resp_got_header; /* TRUE when h3 stream has recvd some HEADER */
+  BIT(opened); /* TRUE after stream has been opened */
+  BIT(closed); /* TRUE on stream close */
+  BIT(reset);  /* TRUE on stream reset */
+  BIT(send_closed); /* stream is locally closed */
+  BIT(resp_hds_complete);  /* final response has been received */
+  BIT(resp_got_header); /* TRUE when h3 stream has recvd some HEADER */
+  BIT(quic_flow_blocked); /* stream is blocked by QUIC flow control */
 };
 
-#define H3_STREAM_CTX(d)    ((struct stream_ctx *)(((d) && (d)->req.p.http)? \
-                             ((struct HTTP *)(d)->req.p.http)->h3_ctx \
-                               : NULL))
-#define H3_STREAM_LCTX(d)   ((struct HTTP *)(d)->req.p.http)->h3_ctx
-#define H3_STREAM_ID(d)     (H3_STREAM_CTX(d)? \
-                             H3_STREAM_CTX(d)->id : -2)
+#define H3_STREAM_CTX(ctx,data)   ((struct stream_ctx *)(\
+            data? Curl_hash_offt_get(&(ctx)->streams, (data)->id) : NULL))
 
-static bool stream_send_is_suspended(struct Curl_easy *data)
+static void h3_stream_ctx_free(struct stream_ctx *stream)
 {
-  return (data->req.keepon & KEEP_SEND_HOLD);
-}
-
-static void stream_send_suspend(struct Curl_cfilter *cf,
-                                struct Curl_easy *data)
-{
-  struct cf_quiche_ctx *ctx = cf->ctx;
-
-  if((data->req.keepon & KEEP_SENDBITS) == KEEP_SEND) {
-    data->req.keepon |= KEEP_SEND_HOLD;
-    ++ctx->sends_on_hold;
-    if(H3_STREAM_ID(data) >= 0)
-      CURL_TRC_CF(data, cf, "[%"PRId64"] suspend sending",
-                  H3_STREAM_ID(data));
-    else
-      CURL_TRC_CF(data, cf, "[%s] suspend sending", data->state.url);
-  }
+  Curl_bufq_free(&stream->recvbuf);
+  Curl_h1_req_parse_free(&stream->h1);
+  free(stream);
 }
 
-static void stream_send_resume(struct Curl_cfilter *cf,
-                               struct Curl_easy *data)
+static void h3_stream_hash_free(void *stream)
 {
-  struct cf_quiche_ctx *ctx = cf->ctx;
-
-  if(stream_send_is_suspended(data)) {
-    data->req.keepon &= ~KEEP_SEND_HOLD;
-    --ctx->sends_on_hold;
-    if(H3_STREAM_ID(data) >= 0)
-      CURL_TRC_CF(data, cf, "[%"PRId64"] resume sending",
-                  H3_STREAM_ID(data));
-    else
-      CURL_TRC_CF(data, cf, "[%s] resume sending", data->state.url);
-    Curl_expire(data, 0, EXPIRE_RUN_NOW);
-  }
+  DEBUGASSERT(stream);
+  h3_stream_ctx_free((struct stream_ctx *)stream);
 }
 
 static void check_resumes(struct Curl_cfilter *cf,
@@ -285,13 +179,16 @@ static void check_resumes(struct Curl_cfilter *cf,
 {
   struct cf_quiche_ctx *ctx = cf->ctx;
   struct Curl_easy *sdata;
-
-  if(ctx->sends_on_hold) {
-    DEBUGASSERT(data->multi);
-    for(sdata = data->multi->easyp;
-        sdata && ctx->sends_on_hold; sdata = sdata->next) {
-      if(stream_send_is_suspended(sdata)) {
-        stream_send_resume(cf, sdata);
+  struct stream_ctx *stream;
+
+  DEBUGASSERT(data->multi);
+  for(sdata = data->multi->easyp; sdata; sdata = sdata->next) {
+    if(sdata->conn == data->conn) {
+      stream = H3_STREAM_CTX(ctx, sdata);
+      if(stream && stream->quic_flow_blocked) {
+        stream->quic_flow_blocked = FALSE;
+        Curl_expire(data, 0, EXPIRE_RUN_NOW);
+        CURL_TRC_CF(data, cf, "[%"CURL_PRIu64"] unblock", stream->id);
       }
     }
   }
@@ -301,7 +198,7 @@ static CURLcode h3_data_setup(struct Curl_cfilter *cf,
                               struct Curl_easy *data)
 {
   struct cf_quiche_ctx *ctx = cf->ctx;
-  struct stream_ctx *stream = H3_STREAM_CTX(data);
+  struct stream_ctx *stream = H3_STREAM_CTX(ctx, data);
 
   if(stream)
     return CURLE_OK;
@@ -310,70 +207,108 @@ static CURLcode h3_data_setup(struct Curl_cfilter *cf,
   if(!stream)
     return CURLE_OUT_OF_MEMORY;
 
-  H3_STREAM_LCTX(data) = stream;
   stream->id = -1;
   Curl_bufq_initp(&stream->recvbuf, &ctx->stream_bufcp,
                   H3_STREAM_RECV_CHUNKS, BUFQ_OPT_SOFT_LIMIT);
   Curl_h1_req_parse_init(&stream->h1, H1_PARSE_DEFAULT_MAX_LINE_LEN);
+
+  if(!Curl_hash_offt_set(&ctx->streams, data->id, stream)) {
+    h3_stream_ctx_free(stream);
+    return CURLE_OUT_OF_MEMORY;
+  }
+
   return CURLE_OK;
 }
 
 static void h3_data_done(struct Curl_cfilter *cf, struct Curl_easy *data)
 {
   struct cf_quiche_ctx *ctx = cf->ctx;
-  struct stream_ctx *stream = H3_STREAM_CTX(data);
+  struct stream_ctx *stream = H3_STREAM_CTX(ctx, data);
+  CURLcode result;
 
   (void)cf;
   if(stream) {
-    CURL_TRC_CF(data, cf, "[%"PRId64"] easy handle is done", stream->id);
-    if(stream_send_is_suspended(data)) {
-      data->req.keepon &= ~KEEP_SEND_HOLD;
-      --ctx->sends_on_hold;
+    CURL_TRC_CF(data, cf, "[%"CURL_PRIu64"] easy handle is done", stream->id);
+    if(ctx->qconn && !stream->closed) {
+      quiche_conn_stream_shutdown(ctx->qconn, stream->id,
+                                  QUICHE_SHUTDOWN_READ, CURL_H3_NO_ERROR);
+      if(!stream->send_closed) {
+        quiche_conn_stream_shutdown(ctx->qconn, stream->id,
+                                    QUICHE_SHUTDOWN_WRITE, CURL_H3_NO_ERROR);
+        stream->send_closed = TRUE;
+      }
+      stream->closed = TRUE;
+      result = cf_flush_egress(cf, data);
+      if(result)
+        CURL_TRC_CF(data, cf, "data_done, flush egress -> %d", result);
     }
-    Curl_bufq_free(&stream->recvbuf);
-    Curl_h1_req_parse_free(&stream->h1);
-    free(stream);
-    H3_STREAM_LCTX(data) = NULL;
+    Curl_hash_offt_remove(&ctx->streams, data->id);
   }
 }
 
 static void drain_stream(struct Curl_cfilter *cf,
                          struct Curl_easy *data)
 {
-  struct stream_ctx *stream = H3_STREAM_CTX(data);
+  struct cf_quiche_ctx *ctx = cf->ctx;
+  struct stream_ctx *stream = H3_STREAM_CTX(ctx, data);
   unsigned char bits;
 
   (void)cf;
   bits = CURL_CSELECT_IN;
   if(stream && !stream->send_closed && stream->upload_left)
     bits |= CURL_CSELECT_OUT;
-  if(data->state.dselect_bits != bits) {
-    data->state.dselect_bits = bits;
+  if(data->state.select_bits != bits) {
+    data->state.select_bits = bits;
     Curl_expire(data, 0, EXPIRE_RUN_NOW);
   }
 }
 
 static struct Curl_easy *get_stream_easy(struct Curl_cfilter *cf,
                                          struct Curl_easy *data,
-                                         int64_t stream3_id)
+                                         curl_uint64_t stream_id,
+                                         struct stream_ctx **pstream)
 {
+  struct cf_quiche_ctx *ctx = cf->ctx;
   struct Curl_easy *sdata;
+  struct stream_ctx *stream;
 
   (void)cf;
-  if(H3_STREAM_ID(data) == stream3_id) {
+  stream = H3_STREAM_CTX(ctx, data);
+  if(stream && stream->id == stream_id) {
+    *pstream = stream;
     return data;
   }
   else {
     DEBUGASSERT(data->multi);
     for(sdata = data->multi->easyp; sdata; sdata = sdata->next) {
-      if((sdata->conn == data->conn) && H3_STREAM_ID(sdata) == stream3_id) {
+      if(sdata->conn != data->conn)
+        continue;
+      stream = H3_STREAM_CTX(ctx, sdata);
+      if(stream && stream->id == stream_id) {
+        *pstream = stream;
         return sdata;
       }
     }
   }
+  *pstream = NULL;
   return NULL;
 }
 
+static void cf_quiche_expire_conn_closed(struct Curl_cfilter *cf,
+                                         struct Curl_easy *data)
+{
+  struct Curl_easy *sdata;
+
+  DEBUGASSERT(data->multi);
+  CURL_TRC_CF(data, cf, "conn closed, expire all transfers");
+  for(sdata = data->multi->easyp; sdata; sdata = sdata->next) {
+    if(sdata == data || sdata->conn != data->conn)
+      continue;
+    CURL_TRC_CF(sdata, cf, "conn closed, expire transfer");
+    Curl_expire(sdata, 0, EXPIRE_RUN_NOW);
+  }
+}
+
 /*
  * write_resp_raw() copies response data in raw format to the `data`'s
   * receive buffer. If not enough space is available, it appends to the
@@ -383,7 +318,8 @@ static CURLcode write_resp_raw(struct Curl_cfilter *cf,
                                struct Curl_easy *data,
                                const void *mem, size_t memlen)
 {
-  struct stream_ctx *stream = H3_STREAM_CTX(data);
+  struct cf_quiche_ctx *ctx = cf->ctx;
+  struct stream_ctx *stream = H3_STREAM_CTX(ctx, data);
   CURLcode result = CURLE_OK;
   ssize_t nwritten;
 
@@ -413,14 +349,15 @@ static int cb_each_header(uint8_t *name, size_t name_len,
                           void *argp)
 {
   struct cb_ctx *x = argp;
-  struct stream_ctx *stream = H3_STREAM_CTX(x->data);
+  struct cf_quiche_ctx *ctx = x->cf->ctx;
+  struct stream_ctx *stream = H3_STREAM_CTX(ctx, x->data);
   CURLcode result;
 
   if(!stream)
     return CURLE_OK;
 
   if((name_len == 7) && !strncmp(HTTP_PSEUDO_STATUS, (char *)name, 7)) {
-    CURL_TRC_CF(x->data, x->cf, "[%" PRId64 "] status: %.*s",
+    CURL_TRC_CF(x->data, x->cf, "[%" CURL_PRIu64 "] status: %.*s",
                 stream->id, (int)value_len, value);
     result = write_resp_raw(x->cf, x->data, "HTTP/3 ", sizeof("HTTP/3 ") - 1);
     if(!result)
@@ -429,7 +366,7 @@ static int cb_each_header(uint8_t *name, size_t name_len,
       result = write_resp_raw(x->cf, x->data, " \r\n", 3);
   }
   else {
-    CURL_TRC_CF(x->data, x->cf, "[%" PRId64 "] header: %.*s: %.*s",
+    CURL_TRC_CF(x->data, x->cf, "[%" CURL_PRIu64 "] header: %.*s: %.*s",
                 stream->id, (int)name_len, name,
                 (int)value_len, value);
     result = write_resp_raw(x->cf, x->data, name, name_len);
@@ -441,7 +378,7 @@ static int cb_each_header(uint8_t *name, size_t name_len,
       result = write_resp_raw(x->cf, x->data, "\r\n", 2);
   }
   if(result) {
-    CURL_TRC_CF(x->data, x->cf, "[%"PRId64"] on header error %d",
+    CURL_TRC_CF(x->data, x->cf, "[%"CURL_PRIu64"] on header error %d",
                 stream->id, result);
   }
   return result;
@@ -453,7 +390,7 @@ static ssize_t stream_resp_read(void *reader_ctx,
 {
   struct cb_ctx *x = reader_ctx;
   struct cf_quiche_ctx *ctx = x->cf->ctx;
-  struct stream_ctx *stream = H3_STREAM_CTX(x->data);
+  struct stream_ctx *stream = H3_STREAM_CTX(ctx, x->data);
   ssize_t nread;
 
   if(!stream) {
@@ -476,7 +413,8 @@ static ssize_t stream_resp_read(void *reader_ctx,
 static CURLcode cf_recv_body(struct Curl_cfilter *cf,
                              struct Curl_easy *data)
 {
-  struct stream_ctx *stream = H3_STREAM_CTX(data);
+  struct cf_quiche_ctx *ctx = cf->ctx;
+  struct stream_ctx *stream = H3_STREAM_CTX(ctx, data);
   ssize_t nwritten;
   struct cb_ctx cb_ctx;
   CURLcode result = CURLE_OK;
@@ -497,9 +435,9 @@ static CURLcode cf_recv_body(struct Curl_cfilter *cf,
                              stream_resp_read, &cb_ctx, &result);
 
   if(nwritten < 0 && result != CURLE_AGAIN) {
-    CURL_TRC_CF(data, cf, "[%"PRId64"] recv_body error %zd",
+    CURL_TRC_CF(data, cf, "[%"CURL_PRIu64"] recv_body error %zd",
                 stream->id, nwritten);
-    failf(data, "Error %d in HTTP/3 response body for stream[%"PRId64"]",
+    failf(data, "Error %d in HTTP/3 response body for stream[%"CURL_PRIu64"]",
           result, stream->id);
     stream->closed = TRUE;
     stream->reset = TRUE;
@@ -534,17 +472,15 @@ static const char *cf_ev_name(quiche_h3_event *ev)
 
 static CURLcode h3_process_event(struct Curl_cfilter *cf,
                                  struct Curl_easy *data,
-                                 int64_t stream3_id,
+                                 struct stream_ctx *stream,
                                  quiche_h3_event *ev)
 {
-  struct stream_ctx *stream = H3_STREAM_CTX(data);
   struct cb_ctx cb_ctx;
   CURLcode result = CURLE_OK;
   int rc;
 
   if(!stream)
     return CURLE_OK;
-  DEBUGASSERT(stream3_id == stream->id);
   switch(quiche_h3_event_type(ev)) {
   case QUICHE_H3_EVENT_HEADERS:
     stream->resp_got_header = TRUE;
@@ -552,11 +488,11 @@ static CURLcode h3_process_event(struct Curl_cfilter *cf,
     cb_ctx.data = data;
     rc = quiche_h3_event_for_each_header(ev, cb_each_header, &cb_ctx);
     if(rc) {
-      failf(data, "Error %d in HTTP/3 response header for stream[%"PRId64"]",
-            rc, stream3_id);
+      failf(data, "Error %d in HTTP/3 response header for stream[%"
+            CURL_PRIu64"]", rc, stream->id);
       return CURLE_RECV_ERROR;
     }
-    CURL_TRC_CF(data, cf, "[%"PRId64"] <- [HEADERS]", stream3_id);
+    CURL_TRC_CF(data, cf, "[%"CURL_PRIu64"] <- [HEADERS]", stream->id);
     break;
 
   case QUICHE_H3_EVENT_DATA:
@@ -566,7 +502,7 @@ static CURLcode h3_process_event(struct Curl_cfilter *cf,
     break;
 
   case QUICHE_H3_EVENT_RESET:
-    CURL_TRC_CF(data, cf, "[%"PRId64"] RESET", stream3_id);
+    CURL_TRC_CF(data, cf, "[%"CURL_PRIu64"] RESET", stream->id);
     stream->closed = TRUE;
     stream->reset = TRUE;
     stream->send_closed = TRUE;
@@ -574,7 +510,7 @@ static CURLcode h3_process_event(struct Curl_cfilter *cf,
     break;
 
   case QUICHE_H3_EVENT_FINISHED:
-    CURL_TRC_CF(data, cf, "[%"PRId64"] CLOSED", stream3_id);
+    CURL_TRC_CF(data, cf, "[%"CURL_PRIu64"] CLOSED", stream->id);
     if(!stream->resp_hds_complete) {
       result = write_resp_raw(cf, data, "\r\n", 2);
       if(result)
@@ -583,16 +519,15 @@ static CURLcode h3_process_event(struct Curl_cfilter *cf,
     }
     stream->closed = TRUE;
     streamclose(cf->conn, "End of stream");
-    data->req.keepon &= ~KEEP_SEND_HOLD;
     break;
 
   case QUICHE_H3_EVENT_GOAWAY:
-    CURL_TRC_CF(data, cf, "[%"PRId64"] <- [GOAWAY]", stream3_id);
+    CURL_TRC_CF(data, cf, "[%"CURL_PRIu64"] <- [GOAWAY]", stream->id);
     break;
 
   default:
-    CURL_TRC_CF(data, cf, "[%"PRId64"] recv, unhandled event %d",
-                stream3_id, quiche_h3_event_type(ev));
+    CURL_TRC_CF(data, cf, "[%"CURL_PRIu64"] recv, unhandled event %d",
+                stream->id, quiche_h3_event_type(ev));
     break;
   }
   return result;
@@ -602,36 +537,33 @@ static CURLcode cf_poll_events(struct Curl_cfilter *cf,
                                struct Curl_easy *data)
 {
   struct cf_quiche_ctx *ctx = cf->ctx;
-  struct stream_ctx *stream = H3_STREAM_CTX(data);
+  struct stream_ctx *stream = NULL;
   struct Curl_easy *sdata;
   quiche_h3_event *ev;
   CURLcode result;
 
   /* Take in the events and distribute them to the transfers. */
   while(ctx->h3c) {
-    int64_t stream3_id = quiche_h3_conn_poll(ctx->h3c, ctx->qconn, &ev);
+    curl_int64_t stream3_id = quiche_h3_conn_poll(ctx->h3c, ctx->qconn, &ev);
     if(stream3_id == QUICHE_H3_ERR_DONE) {
       break;
     }
     else if(stream3_id < 0) {
-      CURL_TRC_CF(data, cf, "[%"PRId64"] error poll: %"PRId64,
-                  stream? stream->id : -1, stream3_id);
+      CURL_TRC_CF(data, cf, "error poll: %"CURL_PRId64, stream3_id);
       return CURLE_HTTP3;
     }
 
-    sdata = get_stream_easy(cf, data, stream3_id);
-    if(!sdata) {
-      CURL_TRC_CF(data, cf, "[%"PRId64"] discard event %s for "
-                  "unknown [%"PRId64"]",
-                  stream? stream->id : -1, cf_ev_name(ev), stream3_id);
+    sdata = get_stream_easy(cf, data, stream3_id, &stream);
+    if(!sdata || !stream) {
+      CURL_TRC_CF(data, cf, "discard event %s for unknown [%"CURL_PRId64"]",
+                  cf_ev_name(ev), stream3_id);
     }
     else {
-      result = h3_process_event(cf, sdata, stream3_id, ev);
+      result = h3_process_event(cf, sdata, stream, ev);
       drain_stream(cf, sdata);
       if(result) {
-        CURL_TRC_CF(data, cf, "[%"PRId64"] error processing event %s "
-                    "for [%"PRId64"] -> %d",
-                    stream? stream->id : -1, cf_ev_name(ev),
+        CURL_TRC_CF(data, cf, "error processing event %s "
+                    "for [%"CURL_PRIu64"] -> %d", cf_ev_name(ev),
                     stream3_id, result);
         if(data == sdata) {
           /* Only report this error to the caller if it is about the
@@ -675,11 +607,19 @@ static CURLcode recv_pkt(const unsigned char *pkt, size_t pktlen,
                            &recv_info);
   if(nread < 0) {
     if(QUICHE_ERR_DONE == nread) {
+      if(quiche_conn_is_draining(ctx->qconn)) {
+        CURL_TRC_CF(r->data, r->cf, "ingress, connection is draining");
+        return CURLE_RECV_ERROR;
+      }
+      if(quiche_conn_is_closed(ctx->qconn)) {
+        CURL_TRC_CF(r->data, r->cf, "ingress, connection is closed");
+        return CURLE_RECV_ERROR;
+      }
       CURL_TRC_CF(r->data, r->cf, "ingress, quiche is DONE");
       return CURLE_OK;
     }
     else if(QUICHE_ERR_TLS_FAIL == nread) {
-      long verify_ok = SSL_get_verify_result(ctx->ssl);
+      long verify_ok = SSL_get_verify_result(ctx->tls.ossl.ssl);
       if(verify_ok != X509_V_OK) {
         failf(r->data, "SSL certificate problem: %s",
               X509_verify_cert_error_string(verify_ok));
@@ -707,7 +647,7 @@ static CURLcode cf_process_ingress(struct Curl_cfilter *cf,
   CURLcode result;
 
   DEBUGASSERT(ctx->qconn);
-  result = quic_x509_store_setup(cf, data);
+  result = Curl_vquic_tls_before_recv(&ctx->tls, cf, data);
   if(result)
     return result;
 
@@ -766,8 +706,8 @@ static CURLcode cf_flush_egress(struct Curl_cfilter *cf,
   struct cf_quiche_ctx *ctx = cf->ctx;
   ssize_t nread;
   CURLcode result;
-  int64_t expiry_ns;
-  int64_t timeout_ns;
+  curl_int64_t expiry_ns;
+  curl_int64_t timeout_ns;
   struct read_ctx readx;
   size_t pkt_count, gsolen;
 
@@ -775,7 +715,13 @@ static CURLcode cf_flush_egress(struct Curl_cfilter *cf,
   if(!expiry_ns) {
     quiche_conn_on_timeout(ctx->qconn);
     if(quiche_conn_is_closed(ctx->qconn)) {
-      failf(data, "quiche_conn_on_timeout closed the connection");
+      if(quiche_conn_is_timed_out(ctx->qconn))
+        failf(data, "connection closed by idle timeout");
+      else
+        failf(data, "connection closed by server");
+      /* Connection timed out, expire all transfers belonging to it
+       * as will not get any more POLL events here. */
+      cf_quiche_expire_conn_closed(cf, data);
       return CURLE_SEND_ERROR;
     }
   }
@@ -840,25 +786,26 @@ static ssize_t recv_closed_stream(struct Curl_cfilter *cf,
                                   struct Curl_easy *data,
                                   CURLcode *err)
 {
-  struct stream_ctx *stream = H3_STREAM_CTX(data);
+  struct cf_quiche_ctx *ctx = cf->ctx;
+  struct stream_ctx *stream = H3_STREAM_CTX(ctx, data);
   ssize_t nread = -1;
 
   DEBUGASSERT(stream);
   if(stream->reset) {
     failf(data,
-          "HTTP/3 stream %" PRId64 " reset by server", stream->id);
-    *err = stream->resp_got_header? CURLE_PARTIAL_FILE : CURLE_RECV_ERROR;
-    CURL_TRC_CF(data, cf, "[%" PRId64 "] cf_recv, was reset -> %d",
+          "HTTP/3 stream %" CURL_PRIu64 " reset by server", stream->id);
+    *err = data->req.bytecount? CURLE_PARTIAL_FILE : CURLE_HTTP3;
+    CURL_TRC_CF(data, cf, "[%" CURL_PRIu64 "] cf_recv, was reset -> %d",
                 stream->id, *err);
   }
   else if(!stream->resp_got_header) {
     failf(data,
-          "HTTP/3 stream %" PRId64 " was closed cleanly, but before getting"
-          " all response header fields, treated as error",
+          "HTTP/3 stream %" CURL_PRIu64 " was closed cleanly, but before "
+          "getting all response header fields, treated as error",
           stream->id);
     /* *err = CURLE_PARTIAL_FILE; */
-    *err = CURLE_RECV_ERROR;
-    CURL_TRC_CF(data, cf, "[%" PRId64 "] cf_recv, closed incomplete"
+    *err = CURLE_HTTP3;
+    CURL_TRC_CF(data, cf, "[%" CURL_PRIu64 "] cf_recv, closed incomplete"
                 " -> %d", stream->id, *err);
   }
   else {
@@ -872,10 +819,12 @@ static ssize_t cf_quiche_recv(struct Curl_cfilter *cf, struct Curl_easy *data,
                               char *buf, size_t len, CURLcode *err)
 {
   struct cf_quiche_ctx *ctx = cf->ctx;
-  struct stream_ctx *stream = H3_STREAM_CTX(data);
+  struct stream_ctx *stream = H3_STREAM_CTX(ctx, data);
   ssize_t nread = -1;
   CURLcode result;
 
+  vquic_ctx_update_time(&ctx->q);
+
   if(!stream) {
     *err = CURLE_RECV_ERROR;
     return -1;
@@ -884,7 +833,7 @@ static ssize_t cf_quiche_recv(struct Curl_cfilter *cf, struct Curl_easy *data,
   if(!Curl_bufq_is_empty(&stream->recvbuf)) {
     nread = Curl_bufq_read(&stream->recvbuf,
                            (unsigned char *)buf, len, err);
-    CURL_TRC_CF(data, cf, "[%" PRId64 "] read recvbuf(len=%zu) "
+    CURL_TRC_CF(data, cf, "[%" CURL_PRIu64 "] read recvbuf(len=%zu) "
                 "-> %zd, %d", stream->id, len, nread, *err);
     if(nread < 0)
       goto out;
@@ -901,7 +850,7 @@ static ssize_t cf_quiche_recv(struct Curl_cfilter *cf, struct Curl_easy *data,
   if(nread < 0 && !Curl_bufq_is_empty(&stream->recvbuf)) {
     nread = Curl_bufq_read(&stream->recvbuf,
                            (unsigned char *)buf, len, err);
-    CURL_TRC_CF(data, cf, "[%" PRId64 "] read recvbuf(len=%zu) "
+    CURL_TRC_CF(data, cf, "[%" CURL_PRIu64 "] read recvbuf(len=%zu) "
                 "-> %zd, %d", stream->id, len, nread, *err);
     if(nread < 0)
       goto out;
@@ -935,7 +884,7 @@ static ssize_t cf_quiche_recv(struct Curl_cfilter *cf, struct Curl_easy *data,
   }
   if(nread > 0)
     ctx->data_recvd += nread;
-  CURL_TRC_CF(data, cf, "[%"PRId64"] cf_recv(total=%"
+  CURL_TRC_CF(data, cf, "[%"CURL_PRIu64"] cf_recv(total=%"
               CURL_FORMAT_CURL_OFF_T ") -> %zd, %d",
               stream->id, ctx->data_recvd, nread, *err);
   return nread;
@@ -951,9 +900,9 @@ static ssize_t h3_open_stream(struct Curl_cfilter *cf,
                               CURLcode *err)
 {
   struct cf_quiche_ctx *ctx = cf->ctx;
-  struct stream_ctx *stream = H3_STREAM_CTX(data);
+  struct stream_ctx *stream = H3_STREAM_CTX(ctx, data);
   size_t nheader, i;
-  int64_t stream3_id;
+  curl_int64_t stream3_id;
   struct dynhds h2_headers;
   quiche_h3_header *nva = NULL;
   ssize_t nwritten;
@@ -963,7 +912,7 @@ static ssize_t h3_open_stream(struct Curl_cfilter *cf,
     if(*err) {
       return -1;
     }
-    stream = H3_STREAM_CTX(data);
+    stream = H3_STREAM_CTX(ctx, data);
     DEBUGASSERT(stream);
   }
 
@@ -1028,15 +977,14 @@ static ssize_t h3_open_stream(struct Curl_cfilter *cf,
     if(QUICHE_H3_ERR_STREAM_BLOCKED == stream3_id) {
       /* quiche seems to report this error if the connection window is
        * exhausted. Which happens frequently and intermittent. */
-      CURL_TRC_CF(data, cf, "send_request(%s) rejected with BLOCKED",
-                  data->state.url);
-      stream_send_suspend(cf, data);
+      CURL_TRC_CF(data, cf, "[%"CURL_PRIu64"] blocked", stream->id);
+      stream->quic_flow_blocked = TRUE;
       *err = CURLE_AGAIN;
       nwritten = -1;
       goto out;
     }
     else {
-      CURL_TRC_CF(data, cf, "send_request(%s) -> %" PRId64,
+      CURL_TRC_CF(data, cf, "send_request(%s) -> %" CURL_PRIu64,
                   data->state.url, stream3_id);
     }
     *err = CURLE_SEND_ERROR;
@@ -1044,17 +992,18 @@ static ssize_t h3_open_stream(struct Curl_cfilter *cf,
     goto out;
   }
 
-  DEBUGASSERT(stream->id == -1);
+  DEBUGASSERT(!stream->opened);
   *err = CURLE_OK;
   stream->id = stream3_id;
+  stream->opened = TRUE;
   stream->closed = FALSE;
   stream->reset = FALSE;
 
   if(Curl_trc_is_verbose(data)) {
-    infof(data, "[HTTP/3] [%" PRId64 "] OPENED stream for %s",
+    infof(data, "[HTTP/3] [%" CURL_PRIu64 "] OPENED stream for %s",
           stream->id, data->state.url);
     for(i = 0; i < nheader; ++i) {
-      infof(data, "[HTTP/3] [%" PRId64 "] [%.*s: %.*s]", stream->id,
+      infof(data, "[HTTP/3] [%" CURL_PRIu64 "] [%.*s: %.*s]", stream->id,
             (int)nva[i].name_len, nva[i].name,
             (int)nva[i].value_len, nva[i].value);
     }
@@ -1070,21 +1019,45 @@ static ssize_t cf_quiche_send(struct Curl_cfilter *cf, struct Curl_easy *data,
                               const void *buf, size_t len, CURLcode *err)
 {
   struct cf_quiche_ctx *ctx = cf->ctx;
-  struct stream_ctx *stream = H3_STREAM_CTX(data);
+  struct stream_ctx *stream = H3_STREAM_CTX(ctx, data);
   CURLcode result;
   ssize_t nwritten;
 
+  vquic_ctx_update_time(&ctx->q);
+
   *err = cf_process_ingress(cf, data);
   if(*err) {
     nwritten = -1;
     goto out;
   }
 
-  if(!stream || stream->id < 0) {
+  if(!stream || !stream->opened) {
     nwritten = h3_open_stream(cf, data, buf, len, err);
     if(nwritten < 0)
       goto out;
-    stream = H3_STREAM_CTX(data);
+    stream = H3_STREAM_CTX(ctx, data);
+  }
+  else if(stream->closed) {
+    if(stream->resp_hds_complete) {
+      /* sending request body on a stream that has been closed by the
+       * server. If the server has send us a final response, we should
+       * silently discard the send data.
+       * This happens for example on redirects where the server, instead
+       * of reading the full request body just closed the stream after
+       * sending the 30x response.
+       * This is sort of a race: had the transfer loop called recv first,
+       * it would see the response and stop/discard sending on its own- */
+      CURL_TRC_CF(data, cf, "[%" CURL_PRIu64 "] discarding data"
+                  "on closed stream with response", stream->id);
+      *err = CURLE_OK;
+      nwritten = (ssize_t)len;
+      goto out;
+    }
+    CURL_TRC_CF(data, cf, "[%" CURL_PRIu64 "] send_body(len=%zu) "
+                "-> stream closed", stream->id, len);
+    *err = CURLE_HTTP3;
+    nwritten = -1;
+    goto out;
   }
   else {
     bool eof = (stream->upload_left >= 0 &&
@@ -1095,39 +1068,30 @@ static ssize_t cf_quiche_send(struct Curl_cfilter *cf, struct Curl_easy *data,
       /* TODO: we seem to be blocked on flow control and should HOLD
        * sending. But when do we open again? */
       if(!quiche_conn_stream_writable(ctx->qconn, stream->id, len)) {
-        CURL_TRC_CF(data, cf, "[%" PRId64 "] send_body(len=%zu) "
+        CURL_TRC_CF(data, cf, "[%" CURL_PRIu64 "] send_body(len=%zu) "
                     "-> window exhausted", stream->id, len);
-        stream_send_suspend(cf, data);
+        stream->quic_flow_blocked = TRUE;
       }
       *err = CURLE_AGAIN;
       nwritten = -1;
       goto out;
     }
-    else if(nwritten == QUICHE_H3_TRANSPORT_ERR_INVALID_STREAM_STATE &&
-            stream->closed && stream->resp_hds_complete) {
-      /* sending request body on a stream that has been closed by the
-       * server. If the server has send us a final response, we should
-       * silently discard the send data.
-       * This happens for example on redirects where the server, instead
-       * of reading the full request body just closed the stream after
-       * sending the 30x response.
-       * This is sort of a race: had the transfer loop called recv first,
-       * it would see the response and stop/discard sending on its own- */
-      CURL_TRC_CF(data, cf, "[%" PRId64 "] discarding data"
-                  "on closed stream with response", stream->id);
-      *err = CURLE_OK;
-      nwritten = (ssize_t)len;
+    else if(nwritten == QUICHE_H3_TRANSPORT_ERR_INVALID_STREAM_STATE) {
+      CURL_TRC_CF(data, cf, "[%" CURL_PRIu64 "] send_body(len=%zu) "
+                  "-> invalid stream state", stream->id, len);
+      *err = CURLE_HTTP3;
+      nwritten = -1;
       goto out;
     }
     else if(nwritten == QUICHE_H3_TRANSPORT_ERR_FINAL_SIZE) {
-      CURL_TRC_CF(data, cf, "[%" PRId64 "] send_body(len=%zu) "
+      CURL_TRC_CF(data, cf, "[%" CURL_PRIu64 "] send_body(len=%zu) "
                   "-> exceeds size", stream->id, len);
       *err = CURLE_SEND_ERROR;
       nwritten = -1;
       goto out;
     }
     else if(nwritten < 0) {
-      CURL_TRC_CF(data, cf, "[%" PRId64 "] send_body(len=%zu) "
+      CURL_TRC_CF(data, cf, "[%" CURL_PRIu64 "] send_body(len=%zu) "
                   "-> quiche err %zd", stream->id, len, nwritten);
       *err = CURLE_SEND_ERROR;
       nwritten = -1;
@@ -1142,7 +1106,7 @@ static ssize_t cf_quiche_send(struct Curl_cfilter *cf, struct Curl_easy *data,
       if(stream->upload_left == 0)
         stream->send_closed = TRUE;
 
-      CURL_TRC_CF(data, cf, "[%" PRId64 "] send body(len=%zu, "
+      CURL_TRC_CF(data, cf, "[%" CURL_PRIu64 "] send body(len=%zu, "
                   "left=%" CURL_FORMAT_CURL_OFF_T ") -> %zd",
                   stream->id, len, stream->upload_left, nwritten);
       *err = CURLE_OK;
@@ -1155,7 +1119,7 @@ static ssize_t cf_quiche_send(struct Curl_cfilter *cf, struct Curl_easy *data,
     *err = result;
     nwritten = -1;
   }
-  CURL_TRC_CF(data, cf, "[%" PRId64 "] cf_send(len=%zu) -> %zd, %d",
+  CURL_TRC_CF(data, cf, "[%" CURL_PRIu64 "] cf_send(len=%zu) -> %zd, %d",
               stream? stream->id : -1, len, nwritten, *err);
   return nwritten;
 }
@@ -1164,32 +1128,37 @@ static bool stream_is_writeable(struct Curl_cfilter *cf,
                                 struct Curl_easy *data)
 {
   struct cf_quiche_ctx *ctx = cf->ctx;
-  struct stream_ctx *stream = H3_STREAM_CTX(data);
+  struct stream_ctx *stream = H3_STREAM_CTX(ctx, data);
 
-  return stream &&
-         quiche_conn_stream_writable(ctx->qconn, (uint64_t)stream->id, 1);
+  return stream && (quiche_conn_stream_writable(
+    ctx->qconn, (curl_uint64_t)stream->id, 1) > 0);
 }
 
-static int cf_quiche_get_select_socks(struct Curl_cfilter *cf,
-                                      struct Curl_easy *data,
-                                      curl_socket_t *socks)
+static void cf_quiche_adjust_pollset(struct Curl_cfilter *cf,
+                                     struct Curl_easy *data,
+                                     struct easy_pollset *ps)
 {
   struct cf_quiche_ctx *ctx = cf->ctx;
-  struct SingleRequest *k = &data->req;
-  int rv = GETSOCK_BLANK;
+  bool want_recv, want_send;
 
-  socks[0] = ctx->q.sockfd;
+  if(!ctx->qconn)
+    return;
 
-  /* in an HTTP/3 connection we can basically always get a frame so we should
-     always be ready for one */
-  rv |= GETSOCK_READSOCK(0);
+  Curl_pollset_check(data, ps, ctx->q.sockfd, &want_recv, &want_send);
+  if(want_recv || want_send) {
+    struct stream_ctx *stream = H3_STREAM_CTX(ctx, data);
+    bool c_exhaust, s_exhaust;
 
-  /* we're still uploading or the HTTP/3 layer wants to send data */
-  if(((k->keepon & KEEP_SENDBITS) == KEEP_SEND)
-     && stream_is_writeable(cf, data))
-    rv |= GETSOCK_WRITESOCK(0);
+    c_exhaust = FALSE; /* Have not found any call in quiche that tells
+                          us if the connection itself is blocked */
+    s_exhaust = want_send && stream && stream->opened &&
+                (stream->quic_flow_blocked || !stream_is_writeable(cf, data));
+    want_recv = (want_recv || c_exhaust || s_exhaust);
+    want_send = (!s_exhaust && want_send) ||
+                 !Curl_bufq_is_empty(&ctx->q.sendbuf);
 
-  return rv;
+    Curl_pollset_set(data, ps, ctx->q.sockfd, want_recv, want_send);
+  }
 }
 
 /*
@@ -1199,7 +1168,8 @@ static int cf_quiche_get_select_socks(struct Curl_cfilter *cf,
 static bool cf_quiche_data_pending(struct Curl_cfilter *cf,
                                    const struct Curl_easy *data)
 {
-  const struct stream_ctx *stream = H3_STREAM_CTX(data);
+  struct cf_quiche_ctx *ctx = cf->ctx;
+  const struct stream_ctx *stream = H3_STREAM_CTX(ctx, data);
   (void)cf;
   return stream && !Curl_bufq_is_empty(&stream->recvbuf);
 }
@@ -1221,6 +1191,7 @@ static CURLcode cf_quiche_data_event(struct Curl_cfilter *cf,
                                      struct Curl_easy *data,
                                      int event, int arg1, void *arg2)
 {
+  struct cf_quiche_ctx *ctx = cf->ctx;
   CURLcode result = CURLE_OK;
 
   (void)arg1;
@@ -1231,12 +1202,14 @@ static CURLcode cf_quiche_data_event(struct Curl_cfilter *cf,
   case CF_CTRL_DATA_PAUSE:
     result = h3_data_pause(cf, data, (arg1 != 0));
     break;
-  case CF_CTRL_DATA_DONE: {
+  case CF_CTRL_DATA_DETACH:
+    h3_data_done(cf, data);
+    break;
+  case CF_CTRL_DATA_DONE:
     h3_data_done(cf, data);
     break;
-  }
   case CF_CTRL_DATA_DONE_SEND: {
-    struct stream_ctx *stream = H3_STREAM_CTX(data);
+    struct stream_ctx *stream = H3_STREAM_CTX(ctx, data);
     if(stream && !stream->send_closed) {
       unsigned char body[1];
       ssize_t sent;
@@ -1245,13 +1218,13 @@ static CURLcode cf_quiche_data_event(struct Curl_cfilter *cf,
       stream->upload_left = 0;
       body[0] = 'X';
       sent = cf_quiche_send(cf, data, body, 0, &result);
-      CURL_TRC_CF(data, cf, "[%"PRId64"] DONE_SEND -> %zd, %d",
+      CURL_TRC_CF(data, cf, "[%"CURL_PRIu64"] DONE_SEND -> %zd, %d",
                   stream->id, sent, result);
     }
     break;
   }
   case CF_CTRL_DATA_IDLE: {
-    struct stream_ctx *stream = H3_STREAM_CTX(data);
+    struct stream_ctx *stream = H3_STREAM_CTX(ctx, data);
     if(stream && !stream->closed) {
       result = cf_flush_egress(cf, data);
       if(result)
@@ -1265,61 +1238,6 @@ static CURLcode cf_quiche_data_event(struct Curl_cfilter *cf,
   return result;
 }
 
-static CURLcode cf_verify_peer(struct Curl_cfilter *cf,
-                               struct Curl_easy *data)
-{
-  struct cf_quiche_ctx *ctx = cf->ctx;
-  CURLcode result = CURLE_OK;
-
-  cf->conn->bits.multiplex = TRUE; /* at least potentially multiplexed */
-  cf->conn->httpversion = 30;
-  cf->conn->bundle->multiuse = BUNDLE_MULTIPLEX;
-
-  if(cf->conn->ssl_config.verifyhost) {
-    X509 *server_cert;
-    server_cert = SSL_get_peer_certificate(ctx->ssl);
-    if(!server_cert) {
-      result = CURLE_PEER_FAILED_VERIFICATION;
-      goto out;
-    }
-    result = Curl_ossl_verifyhost(data, cf->conn, server_cert);
-    X509_free(server_cert);
-    if(result)
-      goto out;
-  }
-  else
-    CURL_TRC_CF(data, cf, "Skipped certificate verification");
-
-  ctx->h3config = quiche_h3_config_new();
-  if(!ctx->h3config) {
-    result = CURLE_OUT_OF_MEMORY;
-    goto out;
-  }
-
-  /* Create a new HTTP/3 connection on the QUIC connection. */
-  ctx->h3c = quiche_h3_conn_new_with_transport(ctx->qconn, ctx->h3config);
-  if(!ctx->h3c) {
-    result = CURLE_OUT_OF_MEMORY;
-    goto out;
-  }
-  if(data->set.ssl.certinfo)
-    /* asked to gather certificate info */
-    (void)Curl_ossl_certchain(data, ctx->ssl);
-
-out:
-  if(result) {
-    if(ctx->h3config) {
-      quiche_h3_config_free(ctx->h3config);
-      ctx->h3config = NULL;
-    }
-    if(ctx->h3c) {
-      quiche_h3_conn_free(ctx->h3c);
-      ctx->h3c = NULL;
-    }
-  }
-  return result;
-}
-
 static CURLcode cf_connect_start(struct Curl_cfilter *cf,
                                  struct Curl_easy *data)
 {
@@ -1340,19 +1258,24 @@ static CURLcode cf_connect_start(struct Curl_cfilter *cf,
 #endif
   Curl_bufcp_init(&ctx->stream_bufcp, H3_STREAM_CHUNK_SIZE,
                   H3_STREAM_POOL_SPARES);
+  Curl_hash_offt_init(&ctx->streams, 63, h3_stream_hash_free);
   ctx->data_recvd = 0;
 
   result = vquic_ctx_init(&ctx->q);
   if(result)
     return result;
 
+  result = Curl_ssl_peer_init(&ctx->peer, cf, TRNSPRT_QUIC);
+  if(result)
+    return result;
+
   ctx->cfg = quiche_config_new(QUICHE_PROTOCOL_VERSION);
   if(!ctx->cfg) {
     failf(data, "can't create quiche config");
     return CURLE_FAILED_INIT;
   }
   quiche_config_enable_pacing(ctx->cfg, false);
-  quiche_config_set_max_idle_timeout(ctx->cfg, QUIC_IDLE_TIMEOUT);
+  quiche_config_set_max_idle_timeout(ctx->cfg, CURL_QUIC_MAX_IDLE_MS);
   quiche_config_set_initial_max_data(ctx->cfg, (1 * 1024 * 1024)
     /* (QUIC_MAX_STREAMS/2) * H3_STREAM_WINDOW_SIZE */);
   quiche_config_set_initial_max_streams_bidi(ctx->cfg, QUIC_MAX_STREAMS);
@@ -1374,9 +1297,10 @@ static CURLcode cf_connect_start(struct Curl_cfilter *cf,
                                        sizeof(QUICHE_H3_APPLICATION_PROTOCOL)
                                        - 1);
 
-  DEBUGASSERT(!ctx->ssl);
-  DEBUGASSERT(!ctx->sslctx);
-  result = quic_ssl_setup(cf, data);
+  result = Curl_vquic_tls_init(&ctx->tls, cf, data, &ctx->peer,
+                               QUICHE_H3_APPLICATION_PROTOCOL,
+                               sizeof(QUICHE_H3_APPLICATION_PROTOCOL) - 1,
+                               NULL, NULL, cf);
   if(result)
     return result;
 
@@ -1384,8 +1308,7 @@ static CURLcode cf_connect_start(struct Curl_cfilter *cf,
   if(result)
     return result;
 
-  Curl_cf_socket_peek(cf->next, data, &ctx->q.sockfd,
-                      &sockaddr, NULL, NULL, NULL, NULL);
+  Curl_cf_socket_peek(cf->next, data, &ctx->q.sockfd, &sockaddr, NULL);
   ctx->q.local_addrlen = sizeof(ctx->q.local_addr);
   rv = getsockname(ctx->q.sockfd, (struct sockaddr *)&ctx->q.local_addr,
                    &ctx->q.local_addrlen);
@@ -1397,14 +1320,14 @@ static CURLcode cf_connect_start(struct Curl_cfilter *cf,
                                       (struct sockaddr *)&ctx->q.local_addr,
                                       ctx->q.local_addrlen,
                                       &sockaddr->sa_addr, sockaddr->addrlen,
-                                      ctx->cfg, ctx->ssl, false);
+                                      ctx->cfg, ctx->tls.ossl.ssl, false);
   if(!ctx->qconn) {
     failf(data, "can't create quiche connection");
     return CURLE_OUT_OF_MEMORY;
   }
 
   /* Known to not work on Windows */
-#if !defined(WIN32) && defined(HAVE_QUICHE_CONN_SET_QLOG_FD)
+#if !defined(_WIN32) && defined(HAVE_QUICHE_CONN_SET_QLOG_FD)
   {
     int qfd;
     (void)Curl_qlogdir(data, ctx->scid, sizeof(ctx->scid), &qfd);
@@ -1436,13 +1359,24 @@ static CURLcode cf_connect_start(struct Curl_cfilter *cf,
   return CURLE_OK;
 }
 
+static CURLcode cf_quiche_verify_peer(struct Curl_cfilter *cf,
+                                      struct Curl_easy *data)
+{
+  struct cf_quiche_ctx *ctx = cf->ctx;
+
+  cf->conn->bits.multiplex = TRUE; /* at least potentially multiplexed */
+  cf->conn->httpversion = 30;
+  cf->conn->bundle->multiuse = BUNDLE_MULTIPLEX;
+
+  return Curl_vquic_tls_verify_peer(&ctx->tls, cf, data, &ctx->peer);
+}
+
 static CURLcode cf_quiche_connect(struct Curl_cfilter *cf,
                                   struct Curl_easy *data,
                                   bool blocking, bool *done)
 {
   struct cf_quiche_ctx *ctx = cf->ctx;
   CURLcode result = CURLE_OK;
-  struct curltime now;
 
   if(cf->connected) {
     *done = TRUE;
@@ -1457,9 +1391,10 @@ static CURLcode cf_quiche_connect(struct Curl_cfilter *cf,
   }
 
   *done = FALSE;
-  now = Curl_now();
+  vquic_ctx_update_time(&ctx->q);
 
-  if(ctx->reconnect_at.tv_sec && Curl_timediff(now, ctx->reconnect_at) < 0) {
+  if(ctx->reconnect_at.tv_sec &&
+     Curl_timediff(ctx->q.last_op, ctx->reconnect_at) < 0) {
     /* Not time yet to attempt the next connect */
     CURL_TRC_CF(data, cf, "waiting for reconnect time");
     goto out;
@@ -1469,7 +1404,7 @@ static CURLcode cf_quiche_connect(struct Curl_cfilter *cf,
     result = cf_connect_start(cf, data);
     if(result)
       goto out;
-    ctx->started_at = now;
+    ctx->started_at = ctx->q.last_op;
     result = cf_flush_egress(cf, data);
     /* we do not expect to be able to recv anything yet */
     goto out;
@@ -1484,12 +1419,24 @@ static CURLcode cf_quiche_connect(struct Curl_cfilter *cf,
     goto out;
 
   if(quiche_conn_is_established(ctx->qconn)) {
+    ctx->handshake_at = ctx->q.last_op;
     CURL_TRC_CF(data, cf, "handshake complete after %dms",
-                (int)Curl_timediff(now, ctx->started_at));
-    ctx->handshake_at = now;
-    result = cf_verify_peer(cf, data);
+                (int)Curl_timediff(ctx->handshake_at, ctx->started_at));
+    result = cf_quiche_verify_peer(cf, data);
     if(!result) {
       CURL_TRC_CF(data, cf, "peer verified");
+      ctx->h3config = quiche_h3_config_new();
+      if(!ctx->h3config) {
+        result = CURLE_OUT_OF_MEMORY;
+        goto out;
+      }
+
+      /* Create a new HTTP/3 connection on the QUIC connection. */
+      ctx->h3c = quiche_h3_conn_new_with_transport(ctx->qconn, ctx->h3config);
+      if(!ctx->h3c) {
+        result = CURLE_OUT_OF_MEMORY;
+        goto out;
+      }
       cf->connected = TRUE;
       cf->conn->alpn = CURL_HTTP_VERSION_3;
       *done = TRUE;
@@ -1499,39 +1446,19 @@ static CURLcode cf_quiche_connect(struct Curl_cfilter *cf,
   else if(quiche_conn_is_draining(ctx->qconn)) {
     /* When a QUIC server instance is shutting down, it may send us a
      * CONNECTION_CLOSE right away. Our connection then enters the DRAINING
-     * state.
-     * This may be a stopping of the service or it may be that the server
-     * is reloading and a new instance will start serving soon.
-     * In any case, we tear down our socket and start over with a new one.
-     * We re-open the underlying UDP cf right now, but do not start
-     * connecting until called again.
-     */
-    int reconn_delay_ms = 200;
-
-    CURL_TRC_CF(data, cf, "connect, remote closed, reconnect after %dms",
-                reconn_delay_ms);
-    Curl_conn_cf_close(cf->next, data);
-    cf_quiche_ctx_clear(ctx);
-    result = Curl_conn_cf_connect(cf->next, data, FALSE, done);
-    if(!result && *done) {
-      *done = FALSE;
-      ctx->reconnect_at = Curl_now();
-      ctx->reconnect_at.tv_usec += reconn_delay_ms * 1000;
-      Curl_expire(data, reconn_delay_ms, EXPIRE_QUIC);
-      result = CURLE_OK;
-    }
+     * state. The CONNECT may work in the near future again. Indicate
+     * that as a "weird" reply. */
+    result = CURLE_WEIRD_SERVER_REPLY;
   }
 
 out:
 #ifndef CURL_DISABLE_VERBOSE_STRINGS
   if(result && result != CURLE_AGAIN) {
-    const char *r_ip;
-    int r_port;
+    struct ip_quadruple ip;
 
-    Curl_cf_socket_peek(cf->next, data, NULL, NULL,
-                        &r_ip, &r_port, NULL, NULL);
+    Curl_cf_socket_peek(cf->next, data, NULL, NULL, &ip);
     infof(data, "connect to %s port %u failed: %s",
-          r_ip, r_port, curl_easy_strerror(result));
+          ip.remote_ip, ip.remote_port, curl_easy_strerror(result));
   }
 #endif
   return result;
@@ -1543,6 +1470,7 @@ static void cf_quiche_close(struct Curl_cfilter *cf, struct Curl_easy *data)
 
   if(ctx) {
     if(ctx->qconn) {
+      vquic_ctx_update_time(&ctx->q);
       (void)quiche_conn_close(ctx->qconn, TRUE, 0, NULL, 0);
       /* flushing the egress is not a failsafe way to deliver all the
          outstanding packets, but we also don't want to get stuck here... */
@@ -1570,17 +1498,19 @@ static CURLcode cf_quiche_query(struct Curl_cfilter *cf,
 
   switch(query) {
   case CF_QUERY_MAX_CONCURRENT: {
-    uint64_t max_streams = CONN_INUSE(cf->conn);
+    curl_uint64_t max_streams = CONN_INUSE(cf->conn);
     if(!ctx->goaway) {
       max_streams += quiche_conn_peer_streams_left_bidi(ctx->qconn);
     }
     *pres1 = (max_streams > INT_MAX)? INT_MAX : (int)max_streams;
-    CURL_TRC_CF(data, cf, "query: MAX_CONCURRENT -> %d", *pres1);
+    CURL_TRC_CF(data, cf, "query conn[%" CURL_FORMAT_CURL_OFF_T "]: "
+                "MAX_CONCURRENT -> %d (%zu in use)",
+                cf->conn->connection_id, *pres1, CONN_INUSE(cf->conn));
     return CURLE_OK;
   }
   case CF_QUERY_CONNECT_REPLY_MS:
-    if(ctx->got_first_byte) {
-      timediff_t ms = Curl_timediff(ctx->first_byte_at, ctx->started_at);
+    if(ctx->q.got_first_byte) {
+      timediff_t ms = Curl_timediff(ctx->q.first_byte_at, ctx->started_at);
       *pres1 = (ms < INT_MAX)? (int)ms : INT_MAX;
     }
     else
@@ -1588,8 +1518,8 @@ static CURLcode cf_quiche_query(struct Curl_cfilter *cf,
     return CURLE_OK;
   case CF_QUERY_TIMER_CONNECT: {
     struct curltime *when = pres2;
-    if(ctx->got_first_byte)
-      *when = ctx->first_byte_at;
+    if(ctx->q.got_first_byte)
+      *when = ctx->q.first_byte_at;
     return CURLE_OK;
   }
   case CF_QUERY_TIMER_APPCONNECT: {
@@ -1610,9 +1540,21 @@ static bool cf_quiche_conn_is_alive(struct Curl_cfilter *cf,
                                     struct Curl_easy *data,
                                     bool *input_pending)
 {
+  struct cf_quiche_ctx *ctx = cf->ctx;
   bool alive = TRUE;
 
   *input_pending = FALSE;
+  if(!ctx->qconn)
+    return FALSE;
+
+  if(quiche_conn_is_closed(ctx->qconn)) {
+    if(quiche_conn_is_timed_out(ctx->qconn))
+      CURL_TRC_CF(data, cf, "connection was closed due to idle timeout");
+    else
+      CURL_TRC_CF(data, cf, "connection is closed");
+    return FALSE;
+  }
+
   if(!cf->next || !cf->next->cft->is_alive(cf->next, data, input_pending))
     return FALSE;
 
@@ -1639,7 +1581,7 @@ struct Curl_cftype Curl_cft_http3 = {
   cf_quiche_connect,
   cf_quiche_close,
   Curl_cf_def_get_host,
-  cf_quiche_get_select_socks,
+  cf_quiche_adjust_pollset,
   cf_quiche_data_pending,
   cf_quiche_send,
   cf_quiche_recv,
@@ -1660,7 +1602,7 @@ CURLcode Curl_cf_quiche_create(struct Curl_cfilter **pcf,
 
   (void)data;
   (void)conn;
-  ctx = calloc(sizeof(*ctx), 1);
+  ctx = calloc(1, sizeof(*ctx));
   if(!ctx) {
     result = CURLE_OUT_OF_MEMORY;
     goto out;
diff --git a/vendor/curl/lib/vquic/vquic-tls.c b/vendor/curl/lib/vquic/vquic-tls.c
new file mode 100644
index 0000000000..aca18b4570
--- /dev/null
+++ b/vendor/curl/lib/vquic/vquic-tls.c
@@ -0,0 +1,342 @@
+/***************************************************************************
+ *                                  _   _ ____  _
+ *  Project                     ___| | | |  _ \| |
+ *                             / __| | | | |_) | |
+ *                            | (__| |_| |  _ <| |___
+ *                             \___|\___/|_| \_\_____|
+ *
+ * Copyright (C) Daniel Stenberg, , et al.
+ *
+ * This software is licensed as described in the file COPYING, which
+ * you should have received as part of this distribution. The terms
+ * are also available at https://curl.se/docs/copyright.html.
+ *
+ * You may opt to use, copy, modify, merge, publish, distribute and/or sell
+ * copies of the Software, and permit persons to whom the Software is
+ * furnished to do so, under the terms of the COPYING file.
+ *
+ * This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY
+ * KIND, either express or implied.
+ *
+ * SPDX-License-Identifier: curl
+ *
+ ***************************************************************************/
+
+#include "curl_setup.h"
+
+#if defined(USE_HTTP3) && \
+  (defined(USE_OPENSSL) || defined(USE_GNUTLS) || defined(USE_WOLFSSL))
+
+#ifdef USE_OPENSSL
+#include 
+#include "vtls/openssl.h"
+#elif defined(USE_GNUTLS)
+#include 
+#include 
+#include 
+#include 
+#include 
+#include "vtls/gtls.h"
+#elif defined(USE_WOLFSSL)
+#include 
+#include 
+#include 
+#include "vtls/wolfssl.h"
+#endif
+
+#include "urldata.h"
+#include "curl_trc.h"
+#include "cfilters.h"
+#include "multiif.h"
+#include "vtls/keylog.h"
+#include "vtls/vtls.h"
+#include "vquic-tls.h"
+
+/* The last 3 #include files should be in this order */
+#include "curl_printf.h"
+#include "curl_memory.h"
+#include "memdebug.h"
+
+#ifndef ARRAYSIZE
+#define ARRAYSIZE(A) (sizeof(A)/sizeof((A)[0]))
+#endif
+
+#if defined(USE_WOLFSSL)
+
+#define QUIC_CIPHERS                                                          \
+  "TLS_AES_128_GCM_SHA256:TLS_AES_256_GCM_SHA384:TLS_CHACHA20_"               \
+  "POLY1305_SHA256:TLS_AES_128_CCM_SHA256"
+#define QUIC_GROUPS "P-256:P-384:P-521"
+
+#if defined(HAVE_SECRET_CALLBACK)
+static void keylog_callback(const WOLFSSL *ssl, const char *line)
+{
+  (void)ssl;
+  Curl_tls_keylog_write_line(line);
+}
+#endif
+
+static CURLcode curl_wssl_init_ctx(struct curl_tls_ctx *ctx,
+                                   struct Curl_cfilter *cf,
+                                   struct Curl_easy *data,
+                                   Curl_vquic_tls_ctx_setup *cb_setup,
+                                   void *cb_user_data)
+{
+  struct ssl_primary_config *conn_config;
+  CURLcode result = CURLE_FAILED_INIT;
+
+  conn_config = Curl_ssl_cf_get_primary_config(cf);
+  if(!conn_config) {
+    result = CURLE_FAILED_INIT;
+    goto out;
+  }
+
+  ctx->ssl_ctx = wolfSSL_CTX_new(wolfTLSv1_3_client_method());
+  if(!ctx->ssl_ctx) {
+    result = CURLE_OUT_OF_MEMORY;
+    goto out;
+  }
+
+  if(cb_setup) {
+    result = cb_setup(cf, data, cb_user_data);
+    if(result)
+      goto out;
+  }
+
+  wolfSSL_CTX_set_default_verify_paths(ctx->ssl_ctx);
+
+  if(wolfSSL_CTX_set_cipher_list(ctx->ssl_ctx, conn_config->cipher_list13 ?
+                                 conn_config->cipher_list13 :
+                                 QUIC_CIPHERS) != 1) {
+    char error_buffer[256];
+    ERR_error_string_n(ERR_get_error(), error_buffer, sizeof(error_buffer));
+    failf(data, "wolfSSL failed to set ciphers: %s", error_buffer);
+    result = CURLE_BAD_FUNCTION_ARGUMENT;
+    goto out;
+  }
+
+  if(wolfSSL_CTX_set1_groups_list(ctx->ssl_ctx, conn_config->curves ?
+                                  conn_config->curves :
+                                  (char *)QUIC_GROUPS) != 1) {
+    failf(data, "wolfSSL failed to set curves");
+    result = CURLE_BAD_FUNCTION_ARGUMENT;
+    goto out;
+  }
+
+  /* Open the file if a TLS or QUIC backend has not done this before. */
+  Curl_tls_keylog_open();
+  if(Curl_tls_keylog_enabled()) {
+#if defined(HAVE_SECRET_CALLBACK)
+    wolfSSL_CTX_set_keylog_callback(ctx->ssl_ctx, keylog_callback);
+#else
+    failf(data, "wolfSSL was built without keylog callback");
+    result = CURLE_NOT_BUILT_IN;
+    goto out;
+#endif
+  }
+
+  if(conn_config->verifypeer) {
+    const char * const ssl_cafile = conn_config->CAfile;
+    const char * const ssl_capath = conn_config->CApath;
+
+    wolfSSL_CTX_set_verify(ctx->ssl_ctx, SSL_VERIFY_PEER, NULL);
+    if(ssl_cafile || ssl_capath) {
+      /* tell wolfSSL where to find CA certificates that are used to verify
+         the server's certificate. */
+      int rc =
+        wolfSSL_CTX_load_verify_locations_ex(ctx->ssl_ctx, ssl_cafile,
+                                             ssl_capath,
+                                             WOLFSSL_LOAD_FLAG_IGNORE_ERR);
+      if(SSL_SUCCESS != rc) {
+        /* Fail if we insist on successfully verifying the server. */
+        failf(data, "error setting certificate verify locations:"
+              "  CAfile: %s CApath: %s",
+              ssl_cafile ? ssl_cafile : "none",
+              ssl_capath ? ssl_capath : "none");
+        result = CURLE_SSL_CACERT_BADFILE;
+        goto out;
+      }
+      infof(data, " CAfile: %s", ssl_cafile ? ssl_cafile : "none");
+      infof(data, " CApath: %s", ssl_capath ? ssl_capath : "none");
+    }
+#ifdef CURL_CA_FALLBACK
+    else {
+      /* verifying the peer without any CA certificates won't work so
+         use wolfssl's built-in default as fallback */
+      wolfSSL_CTX_set_default_verify_paths(ctx->ssl_ctx);
+    }
+#endif
+  }
+  else {
+    wolfSSL_CTX_set_verify(ctx->ssl_ctx, SSL_VERIFY_NONE, NULL);
+  }
+
+  /* give application a chance to interfere with SSL set up. */
+  if(data->set.ssl.fsslctx) {
+    Curl_set_in_callback(data, true);
+    result = (*data->set.ssl.fsslctx)(data, ctx->ssl_ctx,
+                                      data->set.ssl.fsslctxp);
+    Curl_set_in_callback(data, false);
+    if(result) {
+      failf(data, "error signaled by ssl ctx callback");
+      goto out;
+    }
+  }
+  result = CURLE_OK;
+
+out:
+  if(result && ctx->ssl_ctx) {
+    SSL_CTX_free(ctx->ssl_ctx);
+    ctx->ssl_ctx = NULL;
+  }
+  return result;
+}
+
+/** SSL callbacks ***/
+
+static CURLcode curl_wssl_init_ssl(struct curl_tls_ctx *ctx,
+                                   struct Curl_easy *data,
+                                   struct ssl_peer *peer,
+                                   const char *alpn, size_t alpn_len,
+                                   void *user_data)
+{
+  (void)data;
+  DEBUGASSERT(!ctx->ssl);
+  DEBUGASSERT(ctx->ssl_ctx);
+  ctx->ssl = wolfSSL_new(ctx->ssl_ctx);
+
+  wolfSSL_set_app_data(ctx->ssl, user_data);
+  wolfSSL_set_connect_state(ctx->ssl);
+  wolfSSL_set_quic_use_legacy_codepoint(ctx->ssl, 0);
+
+  if(alpn)
+    wolfSSL_set_alpn_protos(ctx->ssl, (const unsigned char *)alpn,
+                            (int)alpn_len);
+
+  if(peer->sni) {
+    wolfSSL_UseSNI(ctx->ssl, WOLFSSL_SNI_HOST_NAME,
+                   peer->sni, (unsigned short)strlen(peer->sni));
+  }
+
+  return CURLE_OK;
+}
+#endif /* defined(USE_WOLFSSL) */
+
+CURLcode Curl_vquic_tls_init(struct curl_tls_ctx *ctx,
+                             struct Curl_cfilter *cf,
+                             struct Curl_easy *data,
+                             struct ssl_peer *peer,
+                             const char *alpn, size_t alpn_len,
+                             Curl_vquic_tls_ctx_setup *cb_setup,
+                             void *cb_user_data, void *ssl_user_data)
+{
+  CURLcode result;
+
+#ifdef USE_OPENSSL
+  (void)result;
+  return Curl_ossl_ctx_init(&ctx->ossl, cf, data, peer, TRNSPRT_QUIC,
+                            (const unsigned char *)alpn, alpn_len,
+                            cb_setup, cb_user_data, NULL, ssl_user_data);
+#elif defined(USE_GNUTLS)
+  (void)result;
+  return Curl_gtls_ctx_init(&ctx->gtls, cf, data, peer,
+                            (const unsigned char *)alpn, alpn_len,
+                            cb_setup, cb_user_data, ssl_user_data);
+#elif defined(USE_WOLFSSL)
+  result = curl_wssl_init_ctx(ctx, cf, data, cb_setup, cb_user_data);
+  if(result)
+    return result;
+
+  return curl_wssl_init_ssl(ctx, data, peer, alpn, alpn_len, ssl_user_data);
+#else
+#error "no TLS lib in used, should not happen"
+  return CURLE_FAILED_INIT;
+#endif
+}
+
+void Curl_vquic_tls_cleanup(struct curl_tls_ctx *ctx)
+{
+#ifdef USE_OPENSSL
+  if(ctx->ossl.ssl)
+    SSL_free(ctx->ossl.ssl);
+  if(ctx->ossl.ssl_ctx)
+    SSL_CTX_free(ctx->ossl.ssl_ctx);
+#elif defined(USE_GNUTLS)
+  if(ctx->gtls.cred)
+    gnutls_certificate_free_credentials(ctx->gtls.cred);
+  if(ctx->gtls.session)
+    gnutls_deinit(ctx->gtls.session);
+#elif defined(USE_WOLFSSL)
+  if(ctx->ssl)
+    wolfSSL_free(ctx->ssl);
+  if(ctx->ssl_ctx)
+    wolfSSL_CTX_free(ctx->ssl_ctx);
+#endif
+  memset(ctx, 0, sizeof(*ctx));
+}
+
+CURLcode Curl_vquic_tls_before_recv(struct curl_tls_ctx *ctx,
+                                    struct Curl_cfilter *cf,
+                                    struct Curl_easy *data)
+{
+#ifdef USE_OPENSSL
+  if(!ctx->ossl.x509_store_setup) {
+    CURLcode result = Curl_ssl_setup_x509_store(cf, data, ctx->ossl.ssl_ctx);
+    if(result)
+      return result;
+    ctx->ossl.x509_store_setup = TRUE;
+  }
+#elif defined(USE_GNUTLS)
+  if(!ctx->gtls.trust_setup) {
+    CURLcode result = Curl_gtls_client_trust_setup(cf, data, &ctx->gtls);
+    if(result)
+      return result;
+  }
+#else
+  (void)ctx; (void)cf; (void)data;
+#endif
+  return CURLE_OK;
+}
+
+CURLcode Curl_vquic_tls_verify_peer(struct curl_tls_ctx *ctx,
+                                    struct Curl_cfilter *cf,
+                                    struct Curl_easy *data,
+                                    struct ssl_peer *peer)
+{
+  struct ssl_primary_config *conn_config;
+  CURLcode result = CURLE_OK;
+
+  conn_config = Curl_ssl_cf_get_primary_config(cf);
+  if(!conn_config)
+    return CURLE_FAILED_INIT;
+
+#ifdef USE_OPENSSL
+  (void)conn_config;
+  result = Curl_oss_check_peer_cert(cf, data, &ctx->ossl, peer);
+#elif defined(USE_GNUTLS)
+  if(conn_config->verifyhost) {
+    result = Curl_gtls_verifyserver(data, ctx->gtls.session,
+                                    conn_config, &data->set.ssl, peer,
+                                    data->set.str[STRING_SSL_PINNEDPUBLICKEY]);
+    if(result)
+      return result;
+  }
+#elif defined(USE_WOLFSSL)
+  (void)data;
+  if(conn_config->verifyhost) {
+    if(peer->sni) {
+      WOLFSSL_X509* cert = wolfSSL_get_peer_certificate(ctx->ssl);
+      if(wolfSSL_X509_check_host(cert, peer->sni, strlen(peer->sni), 0, NULL)
+            == WOLFSSL_FAILURE) {
+        result = CURLE_PEER_FAILED_VERIFICATION;
+      }
+      wolfSSL_X509_free(cert);
+    }
+
+  }
+#endif
+  return result;
+}
+
+
+#endif /* !USE_HTTP3 && (USE_OPENSSL || USE_GNUTLS || USE_WOLFSSL) */
diff --git a/vendor/curl/lib/vquic/vquic-tls.h b/vendor/curl/lib/vquic/vquic-tls.h
new file mode 100644
index 0000000000..1d35fd0e62
--- /dev/null
+++ b/vendor/curl/lib/vquic/vquic-tls.h
@@ -0,0 +1,99 @@
+#ifndef HEADER_CURL_VQUIC_TLS_H
+#define HEADER_CURL_VQUIC_TLS_H
+/***************************************************************************
+ *                                  _   _ ____  _
+ *  Project                     ___| | | |  _ \| |
+ *                             / __| | | | |_) | |
+ *                            | (__| |_| |  _ <| |___
+ *                             \___|\___/|_| \_\_____|
+ *
+ * Copyright (C) Daniel Stenberg, , et al.
+ *
+ * This software is licensed as described in the file COPYING, which
+ * you should have received as part of this distribution. The terms
+ * are also available at https://curl.se/docs/copyright.html.
+ *
+ * You may opt to use, copy, modify, merge, publish, distribute and/or sell
+ * copies of the Software, and permit persons to whom the Software is
+ * furnished to do so, under the terms of the COPYING file.
+ *
+ * This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY
+ * KIND, either express or implied.
+ *
+ * SPDX-License-Identifier: curl
+ *
+ ***************************************************************************/
+
+#include "curl_setup.h"
+#include "bufq.h"
+#include "vtls/openssl.h"
+
+#if defined(USE_HTTP3) && \
+  (defined(USE_OPENSSL) || defined(USE_GNUTLS) || defined(USE_WOLFSSL))
+
+struct curl_tls_ctx {
+#ifdef USE_OPENSSL
+  struct ossl_ctx ossl;
+#elif defined(USE_GNUTLS)
+  struct gtls_ctx gtls;
+#elif defined(USE_WOLFSSL)
+  WOLFSSL_CTX *ssl_ctx;
+  WOLFSSL *ssl;
+#endif
+};
+
+/**
+ * Callback passed to `Curl_vquic_tls_init()` that can
+ * do early initializations on the not otherwise configured TLS
+ * instances created. This varies by TLS backend:
+ * - openssl/wolfssl: SSL_CTX* has just been created
+ * - gnutls: gtls_client_init() has run
+ */
+typedef CURLcode Curl_vquic_tls_ctx_setup(struct Curl_cfilter *cf,
+                                          struct Curl_easy *data,
+                                          void *cb_user_data);
+
+/**
+ * Initialize the QUIC TLS instances based of the SSL configurations
+ * for the connection filter, transfer and peer.
+ * @param ctx         the TLS context to initialize
+ * @param cf          the connection filter involved
+ * @param data        the transfer involved
+ * @param peer        the peer that will be connected to
+ * @param alpn        the ALPN string in protocol format ((len+bytes+)+),
+ *                    may be NULL
+ * @param alpn_len    the overall number of bytes in `alpn`
+ * @param cb_setup    optional callback for very early TLS config
+ ± @param cb_user_data user_data param for callback
+ * @param ssl_user_data  optional pointer to set in TLS application context
+ */
+CURLcode Curl_vquic_tls_init(struct curl_tls_ctx *ctx,
+                             struct Curl_cfilter *cf,
+                             struct Curl_easy *data,
+                             struct ssl_peer *peer,
+                             const char *alpn, size_t alpn_len,
+                             Curl_vquic_tls_ctx_setup *cb_setup,
+                             void *cb_user_data,
+                             void *ssl_user_data);
+
+/**
+ * Cleanup all data that has been initialized.
+ */
+void Curl_vquic_tls_cleanup(struct curl_tls_ctx *ctx);
+
+CURLcode Curl_vquic_tls_before_recv(struct curl_tls_ctx *ctx,
+                                    struct Curl_cfilter *cf,
+                                    struct Curl_easy *data);
+
+/**
+ * After the QUIC basic handshake has been, verify that the peer
+ * (and its certificate) fulfill our requirements.
+ */
+CURLcode Curl_vquic_tls_verify_peer(struct curl_tls_ctx *ctx,
+                                    struct Curl_cfilter *cf,
+                                    struct Curl_easy *data,
+                                    struct ssl_peer *peer);
+
+#endif /* !USE_HTTP3 && (USE_OPENSSL || USE_GNUTLS || USE_WOLFSSL) */
+
+#endif /* HEADER_CURL_VQUIC_TLS_H */
diff --git a/vendor/curl/lib/vquic/vquic.c b/vendor/curl/lib/vquic/vquic.c
index 9a1a1bbb3c..9ce1e4626d 100644
--- a/vendor/curl/lib/vquic/vquic.c
+++ b/vendor/curl/lib/vquic/vquic.c
@@ -46,6 +46,7 @@
 #include "curl_trc.h"
 #include "curl_msh3.h"
 #include "curl_ngtcp2.h"
+#include "curl_osslq.h"
 #include "curl_quiche.h"
 #include "rand.h"
 #include "vquic.h"
@@ -58,7 +59,7 @@
 #include "memdebug.h"
 
 
-#ifdef ENABLE_QUIC
+#ifdef USE_HTTP3
 
 #ifdef O_BINARY
 #define QLOGMODE O_WRONLY|O_CREAT|O_BINARY
@@ -74,6 +75,8 @@ void Curl_quic_ver(char *p, size_t len)
 {
 #if defined(USE_NGTCP2) && defined(USE_NGHTTP3)
   Curl_ngtcp2_ver(p, len);
+#elif defined(USE_OPENSSL_QUIC) && defined(USE_NGHTTP3)
+  Curl_osslq_ver(p, len);
 #elif defined(USE_QUICHE)
   Curl_quiche_ver(p, len);
 #elif defined(USE_MSH3)
@@ -100,6 +103,7 @@ CURLcode vquic_ctx_init(struct cf_quic_ctx *qctx)
     }
   }
 #endif
+  vquic_ctx_update_time(qctx);
 
   return CURLE_OK;
 }
@@ -109,6 +113,11 @@ void vquic_ctx_free(struct cf_quic_ctx *qctx)
   Curl_bufq_free(&qctx->sendbuf);
 }
 
+void vquic_ctx_update_time(struct cf_quic_ctx *qctx)
+{
+  qctx->last_op = Curl_now();
+}
+
 static CURLcode send_packet_no_gso(struct Curl_cfilter *cf,
                                    struct Curl_easy *data,
                                    struct cf_quic_ctx *qctx,
@@ -173,7 +182,7 @@ static CURLcode do_sendmsg(struct Curl_cfilter *cf,
         qctx->no_gso = TRUE;
         return send_packet_no_gso(cf, data, qctx, pkt, pktlen, gsolen, psent);
       }
-      /* FALLTHROUGH */
+      FALLTHROUGH();
     default:
       failf(data, "sendmsg() returned %zd (errno %d)", sent, SOCKERRNO);
       return CURLE_SEND_ERROR;
@@ -242,6 +251,7 @@ static CURLcode vquic_send_packets(struct Curl_cfilter *cf,
                                    const uint8_t *pkt, size_t pktlen,
                                    size_t gsolen, size_t *psent)
 {
+  CURLcode result;
 #ifdef DEBUGBUILD
   /* simulate network blocking/partial writes */
   if(qctx->wblock_percent > 0) {
@@ -254,10 +264,14 @@ static CURLcode vquic_send_packets(struct Curl_cfilter *cf,
   }
 #endif
   if(qctx->no_gso && pktlen > gsolen) {
-    return send_packet_no_gso(cf, data, qctx, pkt, pktlen, gsolen, psent);
+    result = send_packet_no_gso(cf, data, qctx, pkt, pktlen, gsolen, psent);
   }
-
-  return do_sendmsg(cf, data, qctx, pkt, pktlen, gsolen, psent);
+  else {
+    result = do_sendmsg(cf, data, qctx, pkt, pktlen, gsolen, psent);
+  }
+  if(!result)
+    qctx->last_io = qctx->last_op;
+  return result;
 }
 
 CURLcode vquic_flush(struct Curl_cfilter *cf, struct Curl_easy *data,
@@ -356,12 +370,10 @@ static CURLcode recvmmsg_packets(struct Curl_cfilter *cf,
         goto out;
       }
       if(!cf->connected && SOCKERRNO == ECONNREFUSED) {
-        const char *r_ip = NULL;
-        int r_port = 0;
-        Curl_cf_socket_peek(cf->next, data, NULL, NULL,
-                            &r_ip, &r_port, NULL, NULL);
+        struct ip_quadruple ip;
+        Curl_cf_socket_peek(cf->next, data, NULL, NULL, &ip);
         failf(data, "QUIC: connection to %s port %u refused",
-              r_ip, r_port);
+              ip.remote_ip, ip.remote_port);
         result = CURLE_COULDNT_CONNECT;
         goto out;
       }
@@ -426,12 +438,10 @@ static CURLcode recvmsg_packets(struct Curl_cfilter *cf,
         goto out;
       }
       if(!cf->connected && SOCKERRNO == ECONNREFUSED) {
-        const char *r_ip = NULL;
-        int r_port = 0;
-        Curl_cf_socket_peek(cf->next, data, NULL, NULL,
-                            &r_ip, &r_port, NULL, NULL);
+        struct ip_quadruple ip;
+        Curl_cf_socket_peek(cf->next, data, NULL, NULL, &ip);
         failf(data, "QUIC: connection to %s port %u refused",
-              r_ip, r_port);
+              ip.remote_ip, ip.remote_port);
         result = CURLE_COULDNT_CONNECT;
         goto out;
       }
@@ -486,12 +496,10 @@ static CURLcode recvfrom_packets(struct Curl_cfilter *cf,
         goto out;
       }
       if(!cf->connected && SOCKERRNO == ECONNREFUSED) {
-        const char *r_ip = NULL;
-        int r_port = 0;
-        Curl_cf_socket_peek(cf->next, data, NULL, NULL,
-                            &r_ip, &r_port, NULL, NULL);
+        struct ip_quadruple ip;
+        Curl_cf_socket_peek(cf->next, data, NULL, NULL, &ip);
         failf(data, "QUIC: connection to %s port %u refused",
-              r_ip, r_port);
+              ip.remote_ip, ip.remote_port);
         result = CURLE_COULDNT_CONNECT;
         goto out;
       }
@@ -524,13 +532,22 @@ CURLcode vquic_recv_packets(struct Curl_cfilter *cf,
                             size_t max_pkts,
                             vquic_recv_pkt_cb *recv_cb, void *userp)
 {
+  CURLcode result;
 #if defined(HAVE_SENDMMSG)
-  return recvmmsg_packets(cf, data, qctx, max_pkts, recv_cb, userp);
+  result = recvmmsg_packets(cf, data, qctx, max_pkts, recv_cb, userp);
 #elif defined(HAVE_SENDMSG)
-  return recvmsg_packets(cf, data, qctx, max_pkts, recv_cb, userp);
+  result = recvmsg_packets(cf, data, qctx, max_pkts, recv_cb, userp);
 #else
-  return recvfrom_packets(cf, data, qctx, max_pkts, recv_cb, userp);
+  result = recvfrom_packets(cf, data, qctx, max_pkts, recv_cb, userp);
 #endif
+  if(!result) {
+    if(!qctx->got_first_byte) {
+      qctx->got_first_byte = TRUE;
+      qctx->first_byte_at = qctx->last_op;
+    }
+    qctx->last_io = qctx->last_op;
+  }
+  return result;
 }
 
 /*
@@ -588,6 +605,8 @@ CURLcode Curl_cf_quic_create(struct Curl_cfilter **pcf,
   DEBUGASSERT(transport == TRNSPRT_QUIC);
 #if defined(USE_NGTCP2) && defined(USE_NGHTTP3)
   return Curl_cf_ngtcp2_create(pcf, data, conn, ai);
+#elif defined(USE_OPENSSL_QUIC) && defined(USE_NGHTTP3)
+  return Curl_cf_osslq_create(pcf, data, conn, ai);
 #elif defined(USE_QUICHE)
   return Curl_cf_quiche_create(pcf, data, conn, ai);
 #elif defined(USE_MSH3)
@@ -607,6 +626,8 @@ bool Curl_conn_is_http3(const struct Curl_easy *data,
 {
 #if defined(USE_NGTCP2) && defined(USE_NGHTTP3)
   return Curl_conn_is_ngtcp2(data, conn, sockindex);
+#elif defined(USE_OPENSSL_QUIC) && defined(USE_NGHTTP3)
+  return Curl_conn_is_osslq(data, conn, sockindex);
 #elif defined(USE_QUICHE)
   return Curl_conn_is_quiche(data, conn, sockindex);
 #elif defined(USE_MSH3)
@@ -642,7 +663,7 @@ CURLcode Curl_conn_may_http3(struct Curl_easy *data,
   return CURLE_OK;
 }
 
-#else /* ENABLE_QUIC */
+#else /* USE_HTTP3 */
 
 CURLcode Curl_conn_may_http3(struct Curl_easy *data,
                              const struct connectdata *conn)
@@ -653,4 +674,4 @@ CURLcode Curl_conn_may_http3(struct Curl_easy *data,
   return CURLE_NOT_BUILT_IN;
 }
 
-#endif /* !ENABLE_QUIC */
+#endif /* !USE_HTTP3 */
diff --git a/vendor/curl/lib/vquic/vquic.h b/vendor/curl/lib/vquic/vquic.h
index dc73957aaf..c1ca1df6aa 100644
--- a/vendor/curl/lib/vquic/vquic.h
+++ b/vendor/curl/lib/vquic/vquic.h
@@ -26,7 +26,7 @@
 
 #include "curl_setup.h"
 
-#ifdef ENABLE_QUIC
+#ifdef USE_HTTP3
 struct Curl_cfilter;
 struct Curl_easy;
 struct connectdata;
@@ -52,11 +52,11 @@ bool Curl_conn_is_http3(const struct Curl_easy *data,
 
 extern struct Curl_cftype Curl_cft_http3;
 
-#else /* ENABLE_QUIC */
+#else /* USE_HTTP3 */
 
 #define Curl_conn_is_http3(a,b,c)   FALSE
 
-#endif /* !ENABLE_QUIC */
+#endif /* !USE_HTTP3 */
 
 CURLcode Curl_conn_may_http3(struct Curl_easy *data,
                              const struct connectdata *conn);
diff --git a/vendor/curl/lib/vquic/vquic_int.h b/vendor/curl/lib/vquic/vquic_int.h
index dbcd009d72..754e1f5910 100644
--- a/vendor/curl/lib/vquic/vquic_int.h
+++ b/vendor/curl/lib/vquic/vquic_int.h
@@ -27,10 +27,12 @@
 #include "curl_setup.h"
 #include "bufq.h"
 
-#ifdef ENABLE_QUIC
+#ifdef USE_HTTP3
 
 #define MAX_PKT_BURST 10
 #define MAX_UDP_PAYLOAD_SIZE  1452
+/* Default QUIC connection timeout we announce from our side */
+#define CURL_QUIC_MAX_IDLE_MS   (120 * 1000)
 
 struct cf_quic_ctx {
   curl_socket_t sockfd; /* connected UDP socket */
@@ -38,18 +40,24 @@ struct cf_quic_ctx {
   socklen_t local_addrlen; /* length of local address */
 
   struct bufq sendbuf; /* buffer for sending one or more packets */
+  struct curltime first_byte_at;     /* when first byte was recvd */
+  struct curltime last_op; /* last (attempted) send/recv operation */
+  struct curltime last_io; /* last successful socket IO */
   size_t gsolen; /* length of individual packets in send buf */
   size_t split_len; /* if != 0, buffer length after which GSO differs */
   size_t split_gsolen; /* length of individual packets after split_len */
 #ifdef DEBUGBUILD
   int wblock_percent; /* percent of writes doing EAGAIN */
 #endif
-  bool no_gso; /* do not use gso on sending */
+  BIT(got_first_byte); /* if first byte was received */
+  BIT(no_gso); /* do not use gso on sending */
 };
 
 CURLcode vquic_ctx_init(struct cf_quic_ctx *qctx);
 void vquic_ctx_free(struct cf_quic_ctx *qctx);
 
+void vquic_ctx_update_time(struct cf_quic_ctx *qctx);
+
 void vquic_push_blocked_pkt(struct Curl_cfilter *cf,
                             struct cf_quic_ctx *qctx,
                             const uint8_t *pkt, size_t pktlen, size_t gsolen);
@@ -80,6 +88,6 @@ CURLcode vquic_recv_packets(struct Curl_cfilter *cf,
                             size_t max_pkts,
                             vquic_recv_pkt_cb *recv_cb, void *userp);
 
-#endif /* !ENABLE_QUIC */
+#endif /* !USE_HTTP3 */
 
 #endif /* HEADER_CURL_VQUIC_QUIC_INT_H */
diff --git a/vendor/curl/lib/vssh/libssh.c b/vendor/curl/lib/vssh/libssh.c
index dea0084575..d6ba987f1c 100644
--- a/vendor/curl/lib/vssh/libssh.c
+++ b/vendor/curl/lib/vssh/libssh.c
@@ -31,6 +31,8 @@
 
 #include 
 
+/* in 0.10.0 or later, ignore deprecated warnings */
+#define SSH_SUPPRESS_DEPRECATED
 #include 
 #include 
 
@@ -89,13 +91,6 @@
 #include "curl_memory.h"
 #include "memdebug.h"
 
-/* in 0.10.0 or later, ignore deprecated warnings */
-#if defined(__GNUC__) &&                        \
-  (LIBSSH_VERSION_MINOR >= 10) ||               \
-  (LIBSSH_VERSION_MAJOR > 0)
-#pragma GCC diagnostic ignored "-Wdeprecated-declarations"
-#endif
-
 /* A recent macro provided by libssh. Or make our own. */
 #ifndef SSH_STRING_FREE_CHAR
 #define SSH_STRING_FREE_CHAR(x)                 \
@@ -166,7 +161,8 @@ const struct Curl_handler Curl_handler_scp = {
   ZERO_NULL,                    /* domore_getsock */
   myssh_getsock,                /* perform_getsock */
   scp_disconnect,               /* disconnect */
-  ZERO_NULL,                    /* readwrite */
+  ZERO_NULL,                    /* write_resp */
+  ZERO_NULL,                    /* write_resp_hd */
   ZERO_NULL,                    /* connection_check */
   ZERO_NULL,                    /* attach connection */
   PORT_SSH,                     /* defport */
@@ -193,7 +189,8 @@ const struct Curl_handler Curl_handler_sftp = {
   ZERO_NULL,                            /* domore_getsock */
   myssh_getsock,                        /* perform_getsock */
   sftp_disconnect,                      /* disconnect */
-  ZERO_NULL,                            /* readwrite */
+  ZERO_NULL,                            /* write_resp */
+  ZERO_NULL,                            /* write_resp_hd */
   ZERO_NULL,                            /* connection_check */
   ZERO_NULL,                            /* attach connection */
   PORT_SSH,                             /* defport */
@@ -444,11 +441,8 @@ static int myssh_is_known(struct Curl_easy *data)
       keymatch = CURLKHMATCH_OK;
       break;
     case SSH_KNOWN_HOSTS_OTHER:
-      /* fallthrough */
     case SSH_KNOWN_HOSTS_NOT_FOUND:
-      /* fallthrough */
     case SSH_KNOWN_HOSTS_UNKNOWN:
-      /* fallthrough */
     case SSH_KNOWN_HOSTS_ERROR:
       keymatch = CURLKHMATCH_MISSING;
       break;
@@ -464,7 +458,6 @@ static int myssh_is_known(struct Curl_easy *data)
       keymatch = CURLKHMATCH_OK;
       break;
     case SSH_SERVER_FILE_NOT_FOUND:
-      /* fallthrough */
     case SSH_SERVER_NOT_KNOWN:
       keymatch = CURLKHMATCH_MISSING;
       break;
@@ -628,7 +621,7 @@ int myssh_auth_interactive(struct connectdata *conn)
       if(rc < 0)
         return SSH_ERROR;
 
-    /* FALLTHROUGH */
+      FALLTHROUGH();
     case 1:
       sshc->kbd_state = 1;
 
@@ -703,7 +696,7 @@ static CURLcode myssh_statemach_act(struct Curl_easy *data, bool *block)
       ssh_set_blocking(sshc->ssh_session, 0);
 
       state(data, SSH_S_STARTUP);
-      /* FALLTHROUGH */
+      FALLTHROUGH();
 
     case SSH_S_STARTUP:
       rc = ssh_connect(sshc->ssh_session);
@@ -718,7 +711,7 @@ static CURLcode myssh_statemach_act(struct Curl_easy *data, bool *block)
 
       state(data, SSH_HOSTKEY);
 
-      /* FALLTHROUGH */
+      FALLTHROUGH();
     case SSH_HOSTKEY:
 
       rc = myssh_is_known(data);
@@ -728,7 +721,7 @@ static CURLcode myssh_statemach_act(struct Curl_easy *data, bool *block)
       }
 
       state(data, SSH_AUTHLIST);
-      /* FALLTHROUGH */
+      FALLTHROUGH();
     case SSH_AUTHLIST:{
         sshc->authed = FALSE;
 
@@ -909,7 +902,7 @@ static CURLcode myssh_statemach_act(struct Curl_easy *data, bool *block)
         break;
       }
       state(data, SSH_AUTH_PASS);
-      /* FALLTHROUGH */
+      FALLTHROUGH();
 
     case SSH_AUTH_PASS:
       rc = ssh_userauth_password(sshc->ssh_session, NULL, conn->passwd);
@@ -972,7 +965,7 @@ static CURLcode myssh_statemach_act(struct Curl_easy *data, bool *block)
         break;
       }
       state(data, SSH_SFTP_REALPATH);
-      /* FALLTHROUGH */
+      FALLTHROUGH();
     case SSH_SFTP_REALPATH:
       /*
        * Get the "home" directory
@@ -1159,13 +1152,23 @@ static CURLcode myssh_statemach_act(struct Curl_easy *data, bool *block)
         break;
       }
       else if(statvfs) {
+        #ifdef _MSC_VER
+        #define CURL_LIBSSH_VFS_SIZE_MASK "I64u"
+        #else
+        #define CURL_LIBSSH_VFS_SIZE_MASK PRIu64
+        #endif
         char *tmp = aprintf("statvfs:\n"
-                            "f_bsize: %llu\n" "f_frsize: %llu\n"
-                            "f_blocks: %llu\n" "f_bfree: %llu\n"
-                            "f_bavail: %llu\n" "f_files: %llu\n"
-                            "f_ffree: %llu\n" "f_favail: %llu\n"
-                            "f_fsid: %llu\n" "f_flag: %llu\n"
-                            "f_namemax: %llu\n",
+                            "f_bsize: %" CURL_LIBSSH_VFS_SIZE_MASK "\n"
+                            "f_frsize: %" CURL_LIBSSH_VFS_SIZE_MASK "\n"
+                            "f_blocks: %" CURL_LIBSSH_VFS_SIZE_MASK "\n"
+                            "f_bfree: %" CURL_LIBSSH_VFS_SIZE_MASK "\n"
+                            "f_bavail: %" CURL_LIBSSH_VFS_SIZE_MASK "\n"
+                            "f_files: %" CURL_LIBSSH_VFS_SIZE_MASK "\n"
+                            "f_ffree: %" CURL_LIBSSH_VFS_SIZE_MASK "\n"
+                            "f_favail: %" CURL_LIBSSH_VFS_SIZE_MASK "\n"
+                            "f_fsid: %" CURL_LIBSSH_VFS_SIZE_MASK "\n"
+                            "f_flag: %" CURL_LIBSSH_VFS_SIZE_MASK "\n"
+                            "f_namemax: %" CURL_LIBSSH_VFS_SIZE_MASK "\n",
                             statvfs->f_bsize, statvfs->f_frsize,
                             statvfs->f_blocks, statvfs->f_bfree,
                             statvfs->f_bavail, statvfs->f_files,
@@ -1291,10 +1294,10 @@ static CURLcode myssh_statemach_act(struct Curl_easy *data, bool *block)
          position. */
       if(data->state.resume_from > 0) {
         /* Let's read off the proper amount of bytes from the input. */
-        if(conn->seek_func) {
+        if(data->set.seek_func) {
           Curl_set_in_callback(data, true);
-          seekerr = conn->seek_func(conn->seek_client, data->state.resume_from,
-                                    SEEK_SET);
+          seekerr = data->set.seek_func(data->set.seek_client,
+                                        data->state.resume_from, SEEK_SET);
           Curl_set_in_callback(data, false);
         }
 
@@ -1307,13 +1310,14 @@ static CURLcode myssh_statemach_act(struct Curl_easy *data, bool *block)
           }
           /* seekerr == CURL_SEEKFUNC_CANTSEEK (can't seek to offset) */
           do {
+            char scratch[4*1024];
             size_t readthisamountnow =
-              (data->state.resume_from - passed > data->set.buffer_size) ?
-              (size_t)data->set.buffer_size :
-              curlx_sotouz(data->state.resume_from - passed);
+              (data->state.resume_from - passed >
+                (curl_off_t)sizeof(scratch)) ?
+              sizeof(scratch) : curlx_sotouz(data->state.resume_from - passed);
 
             size_t actuallyread =
-              data->state.fread_func(data->state.buffer, 1,
+              data->state.fread_func(scratch, 1,
                                      readthisamountnow, data->state.in);
 
             passed += actuallyread;
@@ -1347,9 +1351,9 @@ static CURLcode myssh_statemach_act(struct Curl_easy *data, bool *block)
         Curl_pgrsSetUploadSize(data, data->state.infilesize);
       }
       /* upload data */
-      Curl_setup_transfer(data, -1, -1, FALSE, FIRSTSOCKET);
+      Curl_xfer_setup(data, -1, -1, FALSE, FIRSTSOCKET);
 
-      /* not set by Curl_setup_transfer to preserve keepon bits */
+      /* not set by Curl_xfer_setup to preserve keepon bits */
       conn->sockfd = conn->writesockfd;
 
       /* store this original bitmask setup to use later on if we can't
@@ -1359,7 +1363,7 @@ static CURLcode myssh_statemach_act(struct Curl_easy *data, bool *block)
       /* we want to use the _sending_ function even when the socket turns
          out readable as the underlying libssh sftp send function will deal
          with both accordingly */
-      conn->cselect_bits = CURL_CSELECT_OUT;
+      data->state.select_bits = CURL_CSELECT_OUT;
 
       /* since we don't really wait for anything at this point, we want the
          state machine to move on as soon as possible so we set a very short
@@ -1466,13 +1470,7 @@ static CURLcode myssh_statemach_act(struct Curl_easy *data, bool *block)
             state(data, SSH_STOP);
             break;
           }
-          /* since this counts what we send to the client, we include the
-             newline in this counter */
-          data->req.bytecount += sshc->readdir_len + 1;
 
-          /* output debug output if that is requested */
-          Curl_debug(data, CURLINFO_DATA_OUT, (char *)sshc->readdir_filename,
-                     sshc->readdir_len);
         }
         else {
           if(Curl_dyn_add(&sshc->readdir_buf, sshc->readdir_longentry)) {
@@ -1555,7 +1553,7 @@ static CURLcode myssh_statemach_act(struct Curl_easy *data, bool *block)
       sshc->readdir_longentry = NULL;
 
       state(data, SSH_SFTP_READDIR_BOTTOM);
-      /* FALLTHROUGH */
+      FALLTHROUGH();
     case SSH_SFTP_READDIR_BOTTOM:
       if(Curl_dyn_addn(&sshc->readdir_buf, "\n", 1))
         result = CURLE_OUT_OF_MEMORY;
@@ -1564,12 +1562,6 @@ static CURLcode myssh_statemach_act(struct Curl_easy *data, bool *block)
                                    Curl_dyn_ptr(&sshc->readdir_buf),
                                    Curl_dyn_len(&sshc->readdir_buf));
 
-      if(!result) {
-        /* output debug output if that is requested */
-        Curl_debug(data, CURLINFO_DATA_OUT, Curl_dyn_ptr(&sshc->readdir_buf),
-                   Curl_dyn_len(&sshc->readdir_buf));
-        data->req.bytecount += Curl_dyn_len(&sshc->readdir_buf);
-      }
       ssh_string_free_char(sshc->readdir_tmp);
       sshc->readdir_tmp = NULL;
 
@@ -1585,7 +1577,7 @@ static CURLcode myssh_statemach_act(struct Curl_easy *data, bool *block)
       sshc->sftp_dir = NULL;
 
       /* no data to transfer */
-      Curl_setup_transfer(data, -1, -1, FALSE, -1);
+      Curl_xfer_setup(data, -1, -1, FALSE, -1);
       state(data, SSH_STOP);
       break;
 
@@ -1675,6 +1667,8 @@ static CURLcode myssh_statemach_act(struct Curl_easy *data, bool *block)
             size = 0;
           }
           else {
+            if((to - from) == CURL_OFF_T_MAX)
+              return CURLE_RANGE_ERROR;
             size = to - from + 1;
           }
 
@@ -1728,20 +1722,20 @@ static CURLcode myssh_statemach_act(struct Curl_easy *data, bool *block)
     /* Setup the actual download */
     if(data->req.size == 0) {
       /* no data to transfer */
-      Curl_setup_transfer(data, -1, -1, FALSE, -1);
+      Curl_xfer_setup(data, -1, -1, FALSE, -1);
       infof(data, "File already completely downloaded");
       state(data, SSH_STOP);
       break;
     }
-    Curl_setup_transfer(data, FIRSTSOCKET, data->req.size, FALSE, -1);
+    Curl_xfer_setup(data, FIRSTSOCKET, data->req.size, FALSE, -1);
 
-    /* not set by Curl_setup_transfer to preserve keepon bits */
+    /* not set by Curl_xfer_setup to preserve keepon bits */
     conn->writesockfd = conn->sockfd;
 
     /* we want to use the _receiving_ function even when the socket turns
        out writableable as the underlying libssh recv function will deal
        with both accordingly */
-    conn->cselect_bits = CURL_CSELECT_IN;
+    data->state.select_bits = CURL_CSELECT_IN;
 
     if(result) {
       /* this should never occur; the close state should be entered
@@ -1857,9 +1851,9 @@ static CURLcode myssh_statemach_act(struct Curl_easy *data, bool *block)
       }
 
       /* upload data */
-      Curl_setup_transfer(data, -1, data->req.size, FALSE, FIRSTSOCKET);
+      Curl_xfer_setup(data, -1, data->req.size, FALSE, FIRSTSOCKET);
 
-      /* not set by Curl_setup_transfer to preserve keepon bits */
+      /* not set by Curl_xfer_setup to preserve keepon bits */
       conn->sockfd = conn->writesockfd;
 
       /* store this original bitmask setup to use later on if we can't
@@ -1869,7 +1863,7 @@ static CURLcode myssh_statemach_act(struct Curl_easy *data, bool *block)
       /* we want to use the _sending_ function even when the socket turns
          out readable as the underlying libssh scp send function will deal
          with both accordingly */
-      conn->cselect_bits = CURL_CSELECT_OUT;
+      data->state.select_bits = CURL_CSELECT_OUT;
 
       state(data, SSH_STOP);
 
@@ -1885,7 +1879,7 @@ static CURLcode myssh_statemach_act(struct Curl_easy *data, bool *block)
         break;
       }
       state(data, SSH_SCP_DOWNLOAD);
-      /* FALLTHROUGH */
+      FALLTHROUGH();
 
     case SSH_SCP_DOWNLOAD:{
         curl_off_t bytecount;
@@ -1901,15 +1895,15 @@ static CURLcode myssh_statemach_act(struct Curl_easy *data, bool *block)
         /* download data */
         bytecount = ssh_scp_request_get_size(sshc->scp_session);
         data->req.maxdownload = (curl_off_t) bytecount;
-        Curl_setup_transfer(data, FIRSTSOCKET, bytecount, FALSE, -1);
+        Curl_xfer_setup(data, FIRSTSOCKET, bytecount, FALSE, -1);
 
-        /* not set by Curl_setup_transfer to preserve keepon bits */
+        /* not set by Curl_xfer_setup to preserve keepon bits */
         conn->writesockfd = conn->sockfd;
 
         /* we want to use the _receiving_ function even when the socket turns
            out writableable as the underlying libssh recv function will deal
            with both accordingly */
-        conn->cselect_bits = CURL_CSELECT_IN;
+        data->state.select_bits = CURL_CSELECT_IN;
 
         state(data, SSH_STOP);
         break;
@@ -1949,7 +1943,7 @@ static CURLcode myssh_statemach_act(struct Curl_easy *data, bool *block)
       ssh_set_blocking(sshc->ssh_session, 0);
 
       state(data, SSH_SESSION_DISCONNECT);
-      /* FALLTHROUGH */
+      FALLTHROUGH();
 
     case SSH_SESSION_DISCONNECT:
       /* during weird times when we've been prematurely aborted, the channel
@@ -1963,17 +1957,16 @@ static CURLcode myssh_statemach_act(struct Curl_easy *data, bool *block)
       ssh_disconnect(sshc->ssh_session);
       if(!ssh_version(SSH_VERSION_INT(0, 10, 0))) {
         /* conn->sock[FIRSTSOCKET] is closed by ssh_disconnect behind our back,
-           explicitly mark it as closed with the memdebug macro. This libssh
+           tell the connection to forget about it. This libssh
            bug is fixed in 0.10.0. */
-        fake_sclose(conn->sock[FIRSTSOCKET]);
-        conn->sock[FIRSTSOCKET] = CURL_SOCKET_BAD;
+        Curl_conn_forget_socket(data, FIRSTSOCKET);
       }
 
       SSH_STRING_FREE_CHAR(sshc->homedir);
       data->state.most_recent_ftp_entrypath = NULL;
 
       state(data, SSH_SESSION_FREE);
-      /* FALLTHROUGH */
+      FALLTHROUGH();
     case SSH_SESSION_FREE:
       if(sshc->ssh_session) {
         ssh_free(sshc->ssh_session);
@@ -2024,7 +2017,6 @@ static CURLcode myssh_statemach_act(struct Curl_easy *data, bool *block)
       break;
 
     case SSH_QUIT:
-      /* fallthrough, just stop! */
     default:
       /* internal error */
       sshc->nextstate = SSH_NO_STATE;
@@ -2567,6 +2559,12 @@ static ssize_t sftp_send(struct Curl_easy *data, int sockindex,
   struct connectdata *conn = data->conn;
   (void)sockindex;
 
+  /* limit the writes to the maximum specified in Section 3 of
+   * https://datatracker.ietf.org/doc/html/draft-ietf-secsh-filexfer-02
+   */
+  if(len > 32768)
+    len = 32768;
+
   nwrite = sftp_write(conn->proto.sshc.sftp_file, mem, len);
 
   myssh_block2waitfor(conn, FALSE);
@@ -2609,7 +2607,7 @@ static ssize_t sftp_recv(struct Curl_easy *data, int sockindex,
         return -1;
       }
 
-      /* FALLTHROUGH */
+      FALLTHROUGH();
     case 1:
       conn->proto.sshc.sftp_recv_state = 1;
 
@@ -2654,7 +2652,7 @@ static void sftp_quote(struct Curl_easy *data)
   /* if a command starts with an asterisk, which a legal SFTP command never
      can, the command will be allowed to fail without it causing any
      aborts or cancels etc. It will cause libcurl to act as if the command
-     is successful, whatever the server reponds. */
+     is successful, whatever the server responds. */
 
   if(cmd[0] == '*') {
     cmd++;
@@ -2828,7 +2826,7 @@ static void sftp_quote_stat(struct Curl_easy *data)
   /* if a command starts with an asterisk, which a legal SFTP command never
      can, the command will be allowed to fail without it causing any
      aborts or cancels etc. It will cause libcurl to act as if the command
-     is successful, whatever the server reponds. */
+     is successful, whatever the server responds. */
 
   if(cmd[0] == '*') {
     cmd++;
diff --git a/vendor/curl/lib/vssh/libssh2.c b/vendor/curl/lib/vssh/libssh2.c
index 37040b4b77..abdf42e558 100644
--- a/vendor/curl/lib/vssh/libssh2.c
+++ b/vendor/curl/lib/vssh/libssh2.c
@@ -138,7 +138,8 @@ const struct Curl_handler Curl_handler_scp = {
   ZERO_NULL,                            /* domore_getsock */
   ssh_getsock,                          /* perform_getsock */
   scp_disconnect,                       /* disconnect */
-  ZERO_NULL,                            /* readwrite */
+  ZERO_NULL,                            /* write_resp */
+  ZERO_NULL,                            /* write_resp_hd */
   ZERO_NULL,                            /* connection_check */
   ssh_attach,                           /* attach */
   PORT_SSH,                             /* defport */
@@ -167,7 +168,8 @@ const struct Curl_handler Curl_handler_sftp = {
   ZERO_NULL,                            /* domore_getsock */
   ssh_getsock,                          /* perform_getsock */
   sftp_disconnect,                      /* disconnect */
-  ZERO_NULL,                            /* readwrite */
+  ZERO_NULL,                            /* write_resp */
+  ZERO_NULL,                            /* write_resp_hd */
   ZERO_NULL,                            /* connection_check */
   ssh_attach,                           /* attach */
   PORT_SSH,                             /* defport */
@@ -201,7 +203,8 @@ kbd_callback(const char *name, int name_len, const char *instruction,
   if(num_prompts == 1) {
     struct connectdata *conn = data->conn;
     responses[0].text = strdup(conn->passwd);
-    responses[0].length = curlx_uztoui(strlen(conn->passwd));
+    responses[0].length =
+      responses[0].text == NULL ? 0 : curlx_uztoui(strlen(conn->passwd));
   }
   (void)prompts;
 } /* kbd_callback */
@@ -589,10 +592,9 @@ static CURLcode ssh_knownhost(struct Curl_easy *data)
 
     switch(rc) {
     default: /* unknown return codes will equal reject */
-      /* FALLTHROUGH */
     case CURLKHSTAT_REJECT:
       state(data, SSH_SESSION_FREE);
-      /* FALLTHROUGH */
+      FALLTHROUGH();
     case CURLKHSTAT_DEFER:
       /* DEFER means bail out but keep the SSH_HOSTKEY state */
       result = sshc->actualcode = CURLE_PEER_FAILED_VERIFICATION;
@@ -601,9 +603,8 @@ static CURLcode ssh_knownhost(struct Curl_easy *data)
       /* remove old host+key that doesn't match */
       if(host)
         libssh2_knownhost_del(sshc->kh, host);
-        /* FALLTHROUGH */
+      FALLTHROUGH();
     case CURLKHSTAT_FINE:
-        /* FALLTHROUGH */
     case CURLKHSTAT_FINE_ADD_TO_FILE:
       /* proceed */
       if(keycheck != LIBSSH2_KNOWNHOST_CHECK_MATCH) {
@@ -997,7 +998,7 @@ static CURLcode ssh_statemach_act(struct Curl_easy *data, bool *block)
       }
 
       state(data, SSH_S_STARTUP);
-      /* FALLTHROUGH */
+      FALLTHROUGH();
 
     case SSH_S_STARTUP:
       rc = session_startup(sshc->ssh_session, sock);
@@ -1016,7 +1017,7 @@ static CURLcode ssh_statemach_act(struct Curl_easy *data, bool *block)
 
       state(data, SSH_HOSTKEY);
 
-      /* FALLTHROUGH */
+      FALLTHROUGH();
     case SSH_HOSTKEY:
       /*
        * Before we authenticate we should check the hostkey's fingerprint
@@ -1085,6 +1086,7 @@ static CURLcode ssh_statemach_act(struct Curl_easy *data, bool *block)
           /* To ponder about: should really the lib be messing about with the
              HOME environment variable etc? */
           char *home = curl_getenv("HOME");
+          struct_stat sbuf;
 
           /* If no private key file is specified, try some common paths. */
           if(home) {
@@ -1092,12 +1094,12 @@ static CURLcode ssh_statemach_act(struct Curl_easy *data, bool *block)
             sshc->rsa = aprintf("%s/.ssh/id_rsa", home);
             if(!sshc->rsa)
               out_of_memory = TRUE;
-            else if(access(sshc->rsa, R_OK) != 0) {
+            else if(stat(sshc->rsa, &sbuf)) {
               Curl_safefree(sshc->rsa);
               sshc->rsa = aprintf("%s/.ssh/id_dsa", home);
               if(!sshc->rsa)
                 out_of_memory = TRUE;
-              else if(access(sshc->rsa, R_OK) != 0) {
+              else if(stat(sshc->rsa, &sbuf)) {
                 Curl_safefree(sshc->rsa);
               }
             }
@@ -1106,10 +1108,10 @@ static CURLcode ssh_statemach_act(struct Curl_easy *data, bool *block)
           if(!out_of_memory && !sshc->rsa) {
             /* Nothing found; try the current dir. */
             sshc->rsa = strdup("id_rsa");
-            if(sshc->rsa && access(sshc->rsa, R_OK) != 0) {
+            if(sshc->rsa && stat(sshc->rsa, &sbuf)) {
               Curl_safefree(sshc->rsa);
               sshc->rsa = strdup("id_dsa");
-              if(sshc->rsa && access(sshc->rsa, R_OK) != 0) {
+              if(sshc->rsa && stat(sshc->rsa, &sbuf)) {
                 Curl_safefree(sshc->rsa);
                 /* Out of guesses. Set to the empty string to avoid
                  * surprising info messages. */
@@ -1178,8 +1180,16 @@ static CURLcode ssh_statemach_act(struct Curl_easy *data, bool *block)
       }
       else {
         char *err_msg = NULL;
-        (void)libssh2_session_last_error(sshc->ssh_session,
-                                         &err_msg, NULL, 0);
+        char unknown[] = "Reason unknown (-1)";
+        if(rc == -1) {
+          /* No error message has been set and the last set error message, if
+             any, is from a previous error so ignore it. #11837 */
+          err_msg = unknown;
+        }
+        else {
+          (void)libssh2_session_last_error(sshc->ssh_session,
+                                           &err_msg, NULL, 0);
+        }
         infof(data, "SSH public key authentication failed: %s", err_msg);
         state(data, SSH_AUTH_PASS_INIT);
         rc = 0; /* clear rc and continue */
@@ -1495,7 +1505,7 @@ static CURLcode ssh_statemach_act(struct Curl_easy *data, bool *block)
       /* if a command starts with an asterisk, which a legal SFTP command never
          can, the command will be allowed to fail without it causing any
          aborts or cancels etc. It will cause libcurl to act as if the command
-         is successful, whatever the server reponds. */
+         is successful, whatever the server responds. */
 
       if(cmd[0] == '*') {
         cmd++;
@@ -1529,139 +1539,137 @@ static CURLcode ssh_statemach_act(struct Curl_easy *data, bool *block)
           state(data, SSH_SFTP_NEXT_QUOTE);
         break;
       }
-      {
-        /*
-         * the arguments following the command must be separated from the
-         * command with a space so we can check for it unconditionally
-         */
-        cp = strchr(cmd, ' ');
-        if(!cp) {
-          failf(data, "Syntax error command '%s', missing parameter",
-                cmd);
+
+      /*
+       * the arguments following the command must be separated from the
+       * command with a space so we can check for it unconditionally
+       */
+      cp = strchr(cmd, ' ');
+      if(!cp) {
+        failf(data, "Syntax error command '%s', missing parameter",
+              cmd);
+        state(data, SSH_SFTP_CLOSE);
+        sshc->nextstate = SSH_NO_STATE;
+        sshc->actualcode = CURLE_QUOTE_ERROR;
+        break;
+      }
+
+      /*
+       * also, every command takes at least one argument so we get that
+       * first argument right now
+       */
+      result = Curl_get_pathname(&cp, &sshc->quote_path1, sshc->homedir);
+      if(result) {
+        if(result == CURLE_OUT_OF_MEMORY)
+          failf(data, "Out of memory");
+        else
+          failf(data, "Syntax error: Bad first parameter to '%s'", cmd);
+        state(data, SSH_SFTP_CLOSE);
+        sshc->nextstate = SSH_NO_STATE;
+        sshc->actualcode = result;
+        break;
+      }
+
+      /*
+       * SFTP is a binary protocol, so we don't send text commands
+       * to the server. Instead, we scan for commands used by
+       * OpenSSH's sftp program and call the appropriate libssh2
+       * functions.
+       */
+      if(strncasecompare(cmd, "chgrp ", 6) ||
+         strncasecompare(cmd, "chmod ", 6) ||
+         strncasecompare(cmd, "chown ", 6) ||
+         strncasecompare(cmd, "atime ", 6) ||
+         strncasecompare(cmd, "mtime ", 6)) {
+        /* attribute change */
+
+        /* sshc->quote_path1 contains the mode to set */
+        /* get the destination */
+        result = Curl_get_pathname(&cp, &sshc->quote_path2, sshc->homedir);
+        if(result) {
+          if(result == CURLE_OUT_OF_MEMORY)
+            failf(data, "Out of memory");
+          else
+            failf(data, "Syntax error in %s: Bad second parameter", cmd);
+          Curl_safefree(sshc->quote_path1);
           state(data, SSH_SFTP_CLOSE);
           sshc->nextstate = SSH_NO_STATE;
-          sshc->actualcode = CURLE_QUOTE_ERROR;
+          sshc->actualcode = result;
           break;
         }
-
-        /*
-         * also, every command takes at least one argument so we get that
-         * first argument right now
-         */
-        result = Curl_get_pathname(&cp, &sshc->quote_path1, sshc->homedir);
+        memset(&sshp->quote_attrs, 0, sizeof(LIBSSH2_SFTP_ATTRIBUTES));
+        state(data, SSH_SFTP_QUOTE_STAT);
+        break;
+      }
+      if(strncasecompare(cmd, "ln ", 3) ||
+         strncasecompare(cmd, "symlink ", 8)) {
+        /* symbolic linking */
+        /* sshc->quote_path1 is the source */
+        /* get the destination */
+        result = Curl_get_pathname(&cp, &sshc->quote_path2, sshc->homedir);
         if(result) {
           if(result == CURLE_OUT_OF_MEMORY)
             failf(data, "Out of memory");
           else
-            failf(data, "Syntax error: Bad first parameter to '%s'", cmd);
+            failf(data,
+                  "Syntax error in ln/symlink: Bad second parameter");
+          Curl_safefree(sshc->quote_path1);
           state(data, SSH_SFTP_CLOSE);
           sshc->nextstate = SSH_NO_STATE;
           sshc->actualcode = result;
           break;
         }
-
-        /*
-         * SFTP is a binary protocol, so we don't send text commands
-         * to the server. Instead, we scan for commands used by
-         * OpenSSH's sftp program and call the appropriate libssh2
-         * functions.
-         */
-        if(strncasecompare(cmd, "chgrp ", 6) ||
-           strncasecompare(cmd, "chmod ", 6) ||
-           strncasecompare(cmd, "chown ", 6) ||
-           strncasecompare(cmd, "atime ", 6) ||
-           strncasecompare(cmd, "mtime ", 6)) {
-          /* attribute change */
-
-          /* sshc->quote_path1 contains the mode to set */
-          /* get the destination */
-          result = Curl_get_pathname(&cp, &sshc->quote_path2, sshc->homedir);
-          if(result) {
-            if(result == CURLE_OUT_OF_MEMORY)
-              failf(data, "Out of memory");
-            else
-              failf(data, "Syntax error in %s: Bad second parameter", cmd);
-            Curl_safefree(sshc->quote_path1);
-            state(data, SSH_SFTP_CLOSE);
-            sshc->nextstate = SSH_NO_STATE;
-            sshc->actualcode = result;
-            break;
-          }
-          memset(&sshp->quote_attrs, 0, sizeof(LIBSSH2_SFTP_ATTRIBUTES));
-          state(data, SSH_SFTP_QUOTE_STAT);
-          break;
-        }
-        if(strncasecompare(cmd, "ln ", 3) ||
-           strncasecompare(cmd, "symlink ", 8)) {
-          /* symbolic linking */
-          /* sshc->quote_path1 is the source */
-          /* get the destination */
-          result = Curl_get_pathname(&cp, &sshc->quote_path2, sshc->homedir);
-          if(result) {
-            if(result == CURLE_OUT_OF_MEMORY)
-              failf(data, "Out of memory");
-            else
-              failf(data,
-                    "Syntax error in ln/symlink: Bad second parameter");
-            Curl_safefree(sshc->quote_path1);
-            state(data, SSH_SFTP_CLOSE);
-            sshc->nextstate = SSH_NO_STATE;
-            sshc->actualcode = result;
-            break;
-          }
-          state(data, SSH_SFTP_QUOTE_SYMLINK);
-          break;
-        }
-        else if(strncasecompare(cmd, "mkdir ", 6)) {
-          /* create dir */
-          state(data, SSH_SFTP_QUOTE_MKDIR);
-          break;
-        }
-        else if(strncasecompare(cmd, "rename ", 7)) {
-          /* rename file */
-          /* first param is the source path */
-          /* second param is the dest. path */
-          result = Curl_get_pathname(&cp, &sshc->quote_path2, sshc->homedir);
-          if(result) {
-            if(result == CURLE_OUT_OF_MEMORY)
-              failf(data, "Out of memory");
-            else
-              failf(data, "Syntax error in rename: Bad second parameter");
-            Curl_safefree(sshc->quote_path1);
-            state(data, SSH_SFTP_CLOSE);
-            sshc->nextstate = SSH_NO_STATE;
-            sshc->actualcode = result;
-            break;
-          }
-          state(data, SSH_SFTP_QUOTE_RENAME);
-          break;
-        }
-        else if(strncasecompare(cmd, "rmdir ", 6)) {
-          /* delete dir */
-          state(data, SSH_SFTP_QUOTE_RMDIR);
-          break;
-        }
-        else if(strncasecompare(cmd, "rm ", 3)) {
-          state(data, SSH_SFTP_QUOTE_UNLINK);
+        state(data, SSH_SFTP_QUOTE_SYMLINK);
+        break;
+      }
+      else if(strncasecompare(cmd, "mkdir ", 6)) {
+        /* create dir */
+        state(data, SSH_SFTP_QUOTE_MKDIR);
+        break;
+      }
+      else if(strncasecompare(cmd, "rename ", 7)) {
+        /* rename file */
+        /* first param is the source path */
+        /* second param is the dest. path */
+        result = Curl_get_pathname(&cp, &sshc->quote_path2, sshc->homedir);
+        if(result) {
+          if(result == CURLE_OUT_OF_MEMORY)
+            failf(data, "Out of memory");
+          else
+            failf(data, "Syntax error in rename: Bad second parameter");
+          Curl_safefree(sshc->quote_path1);
+          state(data, SSH_SFTP_CLOSE);
+          sshc->nextstate = SSH_NO_STATE;
+          sshc->actualcode = result;
           break;
         }
+        state(data, SSH_SFTP_QUOTE_RENAME);
+        break;
+      }
+      else if(strncasecompare(cmd, "rmdir ", 6)) {
+        /* delete dir */
+        state(data, SSH_SFTP_QUOTE_RMDIR);
+        break;
+      }
+      else if(strncasecompare(cmd, "rm ", 3)) {
+        state(data, SSH_SFTP_QUOTE_UNLINK);
+        break;
+      }
 #ifdef HAS_STATVFS_SUPPORT
-        else if(strncasecompare(cmd, "statvfs ", 8)) {
-          state(data, SSH_SFTP_QUOTE_STATVFS);
-          break;
-        }
-#endif
-
-        failf(data, "Unknown SFTP command");
-        Curl_safefree(sshc->quote_path1);
-        Curl_safefree(sshc->quote_path2);
-        state(data, SSH_SFTP_CLOSE);
-        sshc->nextstate = SSH_NO_STATE;
-        sshc->actualcode = CURLE_QUOTE_ERROR;
+      else if(strncasecompare(cmd, "statvfs ", 8)) {
+        state(data, SSH_SFTP_QUOTE_STATVFS);
         break;
       }
+#endif
+
+      failf(data, "Unknown SFTP command");
+      Curl_safefree(sshc->quote_path1);
+      Curl_safefree(sshc->quote_path2);
+      state(data, SSH_SFTP_CLOSE);
+      sshc->nextstate = SSH_NO_STATE;
+      sshc->actualcode = CURLE_QUOTE_ERROR;
+      break;
     }
-    break;
 
     case SSH_SFTP_NEXT_QUOTE:
       Curl_safefree(sshc->quote_path1);
@@ -1691,7 +1699,7 @@ static CURLcode ssh_statemach_act(struct Curl_easy *data, bool *block)
       /* if a command starts with an asterisk, which a legal SFTP command never
          can, the command will be allowed to fail without it causing any
          aborts or cancels etc. It will cause libcurl to act as if the command
-         is successful, whatever the server reponds. */
+         is successful, whatever the server responds. */
 
       if(cmd[0] == '*') {
         cmd++;
@@ -1954,13 +1962,23 @@ static CURLcode ssh_statemach_act(struct Curl_easy *data, bool *block)
         break;
       }
       else if(rc == 0) {
+        #ifdef _MSC_VER
+        #define CURL_LIBSSH2_VFS_SIZE_MASK "I64u"
+        #else
+        #define CURL_LIBSSH2_VFS_SIZE_MASK "llu"
+        #endif
         char *tmp = aprintf("statvfs:\n"
-                            "f_bsize: %llu\n" "f_frsize: %llu\n"
-                            "f_blocks: %llu\n" "f_bfree: %llu\n"
-                            "f_bavail: %llu\n" "f_files: %llu\n"
-                            "f_ffree: %llu\n" "f_favail: %llu\n"
-                            "f_fsid: %llu\n" "f_flag: %llu\n"
-                            "f_namemax: %llu\n",
+                            "f_bsize: %" CURL_LIBSSH2_VFS_SIZE_MASK "\n"
+                            "f_frsize: %" CURL_LIBSSH2_VFS_SIZE_MASK "\n"
+                            "f_blocks: %" CURL_LIBSSH2_VFS_SIZE_MASK "\n"
+                            "f_bfree: %" CURL_LIBSSH2_VFS_SIZE_MASK "\n"
+                            "f_bavail: %" CURL_LIBSSH2_VFS_SIZE_MASK "\n"
+                            "f_files: %" CURL_LIBSSH2_VFS_SIZE_MASK "\n"
+                            "f_ffree: %" CURL_LIBSSH2_VFS_SIZE_MASK "\n"
+                            "f_favail: %" CURL_LIBSSH2_VFS_SIZE_MASK "\n"
+                            "f_fsid: %" CURL_LIBSSH2_VFS_SIZE_MASK "\n"
+                            "f_flag: %" CURL_LIBSSH2_VFS_SIZE_MASK "\n"
+                            "f_namemax: %" CURL_LIBSSH2_VFS_SIZE_MASK "\n",
                             statvfs.f_bsize, statvfs.f_frsize,
                             statvfs.f_blocks, statvfs.f_bfree,
                             statvfs.f_bavail, statvfs.f_files,
@@ -2128,10 +2146,10 @@ static CURLcode ssh_statemach_act(struct Curl_easy *data, bool *block)
          position. */
       if(data->state.resume_from > 0) {
         /* Let's read off the proper amount of bytes from the input. */
-        if(conn->seek_func) {
+        if(data->set.seek_func) {
           Curl_set_in_callback(data, true);
-          seekerr = conn->seek_func(conn->seek_client, data->state.resume_from,
-                                    SEEK_SET);
+          seekerr = data->set.seek_func(data->set.seek_client,
+                                        data->state.resume_from, SEEK_SET);
           Curl_set_in_callback(data, false);
         }
 
@@ -2144,14 +2162,15 @@ static CURLcode ssh_statemach_act(struct Curl_easy *data, bool *block)
           }
           /* seekerr == CURL_SEEKFUNC_CANTSEEK (can't seek to offset) */
           do {
+            char scratch[4*1024];
             size_t readthisamountnow =
-              (data->state.resume_from - passed > data->set.buffer_size) ?
-              (size_t)data->set.buffer_size :
-              curlx_sotouz(data->state.resume_from - passed);
+              (data->state.resume_from - passed >
+                (curl_off_t)sizeof(scratch)) ?
+              sizeof(scratch) : curlx_sotouz(data->state.resume_from - passed);
 
             size_t actuallyread;
             Curl_set_in_callback(data, true);
-            actuallyread = data->state.fread_func(data->state.buffer, 1,
+            actuallyread = data->state.fread_func(scratch, 1,
                                                   readthisamountnow,
                                                   data->state.in);
             Curl_set_in_callback(data, false);
@@ -2180,9 +2199,9 @@ static CURLcode ssh_statemach_act(struct Curl_easy *data, bool *block)
         Curl_pgrsSetUploadSize(data, data->state.infilesize);
       }
       /* upload data */
-      Curl_setup_transfer(data, -1, -1, FALSE, FIRSTSOCKET);
+      Curl_xfer_setup(data, -1, -1, FALSE, FIRSTSOCKET);
 
-      /* not set by Curl_setup_transfer to preserve keepon bits */
+      /* not set by Curl_xfer_setup to preserve keepon bits */
       conn->sockfd = conn->writesockfd;
 
       if(result) {
@@ -2197,7 +2216,7 @@ static CURLcode ssh_statemach_act(struct Curl_easy *data, bool *block)
         /* we want to use the _sending_ function even when the socket turns
            out readable as the underlying libssh2 sftp send function will deal
            with both accordingly */
-        conn->cselect_bits = CURL_CSELECT_OUT;
+        data->state.select_bits = CURL_CSELECT_OUT;
 
         /* since we don't really wait for anything at this point, we want the
            state machine to move on as soon as possible so we set a very short
@@ -2333,14 +2352,7 @@ static CURLcode ssh_statemach_act(struct Curl_easy *data, bool *block)
             state(data, SSH_STOP);
             break;
           }
-          /* since this counts what we send to the client, we include the
-             newline in this counter */
-          data->req.bytecount += readdir_len + 1;
 
-          /* output debug output if that is requested */
-          Curl_debug(data, CURLINFO_DATA_IN, sshp->readdir_filename,
-                     readdir_len);
-          Curl_debug(data, CURLINFO_DATA_IN, (char *)"\n", 1);
         }
         else {
           result = Curl_dyn_add(&sshp->readdir, sshp->readdir_longentry);
@@ -2419,13 +2431,6 @@ static CURLcode ssh_statemach_act(struct Curl_easy *data, bool *block)
                                    Curl_dyn_ptr(&sshp->readdir),
                                    Curl_dyn_len(&sshp->readdir));
 
-      if(!result) {
-        /* output debug output if that is requested */
-        Curl_debug(data, CURLINFO_DATA_IN,
-                   Curl_dyn_ptr(&sshp->readdir),
-                   Curl_dyn_len(&sshp->readdir));
-        data->req.bytecount += Curl_dyn_len(&sshp->readdir);
-      }
       if(result) {
         Curl_dyn_free(&sshp->readdir);
         state(data, SSH_STOP);
@@ -2447,7 +2452,7 @@ static CURLcode ssh_statemach_act(struct Curl_easy *data, bool *block)
       Curl_safefree(sshp->readdir_longentry);
 
       /* no data to transfer */
-      Curl_setup_transfer(data, -1, -1, FALSE, -1);
+      Curl_xfer_setup(data, -1, -1, FALSE, -1);
       state(data, SSH_STOP);
       break;
 
@@ -2543,6 +2548,8 @@ static CURLcode ssh_statemach_act(struct Curl_easy *data, bool *block)
             size = 0;
           }
           else {
+            if((to - from) == CURL_OFF_T_MAX)
+              return CURLE_RANGE_ERROR;
             size = to - from + 1;
           }
 
@@ -2587,20 +2594,20 @@ static CURLcode ssh_statemach_act(struct Curl_easy *data, bool *block)
     /* Setup the actual download */
     if(data->req.size == 0) {
       /* no data to transfer */
-      Curl_setup_transfer(data, -1, -1, FALSE, -1);
+      Curl_xfer_setup(data, -1, -1, FALSE, -1);
       infof(data, "File already completely downloaded");
       state(data, SSH_STOP);
       break;
     }
-    Curl_setup_transfer(data, FIRSTSOCKET, data->req.size, FALSE, -1);
+    Curl_xfer_setup(data, FIRSTSOCKET, data->req.size, FALSE, -1);
 
-    /* not set by Curl_setup_transfer to preserve keepon bits */
+    /* not set by Curl_xfer_setup to preserve keepon bits */
     conn->writesockfd = conn->sockfd;
 
     /* we want to use the _receiving_ function even when the socket turns
        out writableable as the underlying libssh2 recv function will deal
        with both accordingly */
-    conn->cselect_bits = CURL_CSELECT_IN;
+    data->state.select_bits = CURL_CSELECT_IN;
 
     if(result) {
       /* this should never occur; the close state should be entered
@@ -2738,9 +2745,9 @@ static CURLcode ssh_statemach_act(struct Curl_easy *data, bool *block)
       /* upload data */
       data->req.size = data->state.infilesize;
       Curl_pgrsSetUploadSize(data, data->state.infilesize);
-      Curl_setup_transfer(data, -1, -1, FALSE, FIRSTSOCKET);
+      Curl_xfer_setup(data, -1, -1, FALSE, FIRSTSOCKET);
 
-      /* not set by Curl_setup_transfer to preserve keepon bits */
+      /* not set by Curl_xfer_setup to preserve keepon bits */
       conn->sockfd = conn->writesockfd;
 
       if(result) {
@@ -2755,7 +2762,7 @@ static CURLcode ssh_statemach_act(struct Curl_easy *data, bool *block)
         /* we want to use the _sending_ function even when the socket turns
            out readable as the underlying libssh2 scp send function will deal
            with both accordingly */
-        conn->cselect_bits = CURL_CSELECT_OUT;
+        data->state.select_bits = CURL_CSELECT_OUT;
 
         state(data, SSH_STOP);
       }
@@ -2809,15 +2816,15 @@ static CURLcode ssh_statemach_act(struct Curl_easy *data, bool *block)
       /* download data */
       bytecount = (curl_off_t)sb.st_size;
       data->req.maxdownload = (curl_off_t)sb.st_size;
-      Curl_setup_transfer(data, FIRSTSOCKET, bytecount, FALSE, -1);
+      Curl_xfer_setup(data, FIRSTSOCKET, bytecount, FALSE, -1);
 
-      /* not set by Curl_setup_transfer to preserve keepon bits */
+      /* not set by Curl_xfer_setup to preserve keepon bits */
       conn->writesockfd = conn->sockfd;
 
       /* we want to use the _receiving_ function even when the socket turns
          out writableable as the underlying libssh2 recv function will deal
          with both accordingly */
-      conn->cselect_bits = CURL_CSELECT_IN;
+      data->state.select_bits = CURL_CSELECT_IN;
 
       if(result) {
         state(data, SSH_SCP_CHANNEL_FREE);
@@ -3022,7 +3029,6 @@ static CURLcode ssh_statemach_act(struct Curl_easy *data, bool *block)
       break;
 
     case SSH_QUIT:
-      /* fallthrough, just stop! */
     default:
       /* internal error */
       sshc->nextstate = SSH_NO_STATE;
@@ -3191,12 +3197,13 @@ static ssize_t ssh_tls_recv(libssh2_socket_t sock, void *buffer,
   struct connectdata *conn = data->conn;
   Curl_recv *backup = conn->recv[0];
   struct ssh_conn *ssh = &conn->proto.sshc;
+  int socknum = Curl_conn_sockindex(data, sock);
   (void)flags;
 
   /* swap in the TLS reader function for this call only, and then swap back
      the SSH one again */
   conn->recv[0] = ssh->tls_recv;
-  result = Curl_read(data, sock, buffer, length, &nread);
+  result = Curl_conn_recv(data, socknum, buffer, length, &nread);
   conn->recv[0] = backup;
   if(result == CURLE_AGAIN)
     return -EAGAIN; /* magic return code for libssh2 */
@@ -3210,24 +3217,25 @@ static ssize_t ssh_tls_send(libssh2_socket_t sock, const void *buffer,
                             size_t length, int flags, void **abstract)
 {
   struct Curl_easy *data = (struct Curl_easy *)*abstract;
-  ssize_t nwrite;
+  size_t nwrite;
   CURLcode result;
   struct connectdata *conn = data->conn;
   Curl_send *backup = conn->send[0];
   struct ssh_conn *ssh = &conn->proto.sshc;
+  int socknum = Curl_conn_sockindex(data, sock);
   (void)flags;
 
   /* swap in the TLS writer function for this call only, and then swap back
      the SSH one again */
   conn->send[0] = ssh->tls_send;
-  result = Curl_write(data, sock, buffer, length, &nwrite);
+  result = Curl_conn_send(data, socknum, buffer, length, &nwrite);
   conn->send[0] = backup;
   if(result == CURLE_AGAIN)
     return -EAGAIN; /* magic return code for libssh2 */
   else if(result)
     return -1; /* error */
-  Curl_debug(data, CURLINFO_DATA_OUT, (char *)buffer, (size_t)nwrite);
-  return nwrite;
+  Curl_debug(data, CURLINFO_DATA_OUT, (char *)buffer, nwrite);
+  return (ssize_t)nwrite;
 }
 #endif
 
@@ -3268,7 +3276,7 @@ static CURLcode ssh_connect(struct Curl_easy *data, bool *done)
 #endif /* CURL_LIBSSH2_DEBUG */
 
   /* libcurl MUST to set custom memory functions so that the kbd_callback
-     funciton's memory allocations can be properled freed */
+     function's memory allocations can be properly freed */
   sshc->ssh_session = libssh2_session_init_ex(my_libssh2_malloc,
                                               my_libssh2_free,
                                               my_libssh2_realloc, data);
@@ -3278,7 +3286,6 @@ static CURLcode ssh_connect(struct Curl_easy *data, bool *done)
     return CURLE_FAILED_INIT;
   }
 
-#ifdef HAVE_LIBSSH2_VERSION
   /* Set the packet read timeout if the libssh2 version supports it */
 #if LIBSSH2_VERSION_NUM >= 0x010B00
   if(data->set.server_response_timeout > 0) {
@@ -3286,10 +3293,30 @@ static CURLcode ssh_connect(struct Curl_easy *data, bool *done)
                                      data->set.server_response_timeout / 1000);
   }
 #endif
-#endif
 
 #ifndef CURL_DISABLE_PROXY
   if(conn->http_proxy.proxytype == CURLPROXY_HTTPS) {
+    /*
+      Setup libssh2 callbacks to make it read/write TLS from the socket.
+
+      ssize_t
+      recvcb(libssh2_socket_t sock, void *buffer, size_t length,
+      int flags, void **abstract);
+
+      ssize_t
+      sendcb(libssh2_socket_t sock, const void *buffer, size_t length,
+      int flags, void **abstract);
+
+    */
+#if LIBSSH2_VERSION_NUM >= 0x010b01
+    infof(data, "Uses HTTPS proxy");
+    libssh2_session_callback_set2(sshc->ssh_session,
+                                  LIBSSH2_CALLBACK_RECV,
+                                  (libssh2_cb_generic *)ssh_tls_recv);
+    libssh2_session_callback_set2(sshc->ssh_session,
+                                  LIBSSH2_CALLBACK_SEND,
+                                  (libssh2_cb_generic *)ssh_tls_send);
+#else
     /*
      * This crazy union dance is here to avoid assigning a void pointer a
      * function pointer as it is invalid C. The problem is of course that
@@ -3310,22 +3337,11 @@ static CURLcode ssh_connect(struct Curl_easy *data, bool *done)
     sshsend.sendptr = ssh_tls_send;
 
     infof(data, "Uses HTTPS proxy");
-    /*
-      Setup libssh2 callbacks to make it read/write TLS from the socket.
-
-      ssize_t
-      recvcb(libssh2_socket_t sock, void *buffer, size_t length,
-      int flags, void **abstract);
-
-      ssize_t
-      sendcb(libssh2_socket_t sock, const void *buffer, size_t length,
-      int flags, void **abstract);
-
-    */
     libssh2_session_callback_set(sshc->ssh_session,
                                  LIBSSH2_CALLBACK_RECV, sshrecv.recvp);
     libssh2_session_callback_set(sshc->ssh_session,
                                  LIBSSH2_CALLBACK_SEND, sshsend.sendp);
+#endif
 
     /* Store the underlying TLS recv/send function pointers to be used when
        reading from the proxy */
diff --git a/vendor/curl/lib/vssh/ssh.h b/vendor/curl/lib/vssh/ssh.h
index 1e1b1379c2..ca0533aa54 100644
--- a/vendor/curl/lib/vssh/ssh.h
+++ b/vendor/curl/lib/vssh/ssh.h
@@ -267,6 +267,7 @@ void Curl_ssh_attach(struct Curl_easy *data,
 /* for non-SSH builds */
 #define Curl_ssh_cleanup()
 #define Curl_ssh_attach(x,y)
+#define Curl_ssh_init() 0
 #endif
 
 #endif /* HEADER_CURL_SSH_H */
diff --git a/vendor/curl/lib/vssh/wolfssh.c b/vendor/curl/lib/vssh/wolfssh.c
index 306d299bcf..6a5aed88f7 100644
--- a/vendor/curl/lib/vssh/wolfssh.c
+++ b/vendor/curl/lib/vssh/wolfssh.c
@@ -42,6 +42,7 @@
 #include "select.h"
 #include "multiif.h"
 #include "warnless.h"
+#include "strdup.h"
 
 /* The last 3 #include files should be in this order */
 #include "curl_printf.h"
@@ -92,7 +93,8 @@ const struct Curl_handler Curl_handler_scp = {
   ZERO_NULL,                            /* domore_getsock */
   wssh_getsock,                         /* perform_getsock */
   wscp_disconnect,                      /* disconnect */
-  ZERO_NULL,                            /* readwrite */
+  ZERO_NULL,                            /* write_resp */
+  ZERO_NULL,                            /* write_resp_hd */
   ZERO_NULL,                            /* connection_check */
   ZERO_NULL,                            /* attach connection */
   PORT_SSH,                             /* defport */
@@ -121,7 +123,8 @@ const struct Curl_handler Curl_handler_sftp = {
   ZERO_NULL,                            /* domore_getsock */
   wssh_getsock,                         /* perform_getsock */
   wsftp_disconnect,                     /* disconnect */
-  ZERO_NULL,                            /* readwrite */
+  ZERO_NULL,                            /* write_resp */
+  ZERO_NULL,                            /* write_resp_hd */
   ZERO_NULL,                            /* connection_check */
   ZERO_NULL,                            /* attach connection */
   PORT_SSH,                             /* defport */
@@ -343,9 +346,6 @@ static CURLcode wssh_setup_connection(struct Curl_easy *data,
   return CURLE_OK;
 }
 
-static Curl_recv wscp_recv, wsftp_recv;
-static Curl_send wscp_send, wsftp_send;
-
 static int userauth(byte authtype,
                     WS_UserAuthData* authdata,
                     void *ctx)
@@ -515,15 +515,9 @@ static CURLcode wssh_statemach_act(struct Curl_easy *data, bool *block)
         return CURLE_OK;
       }
       else if(name && (rc == WS_SUCCESS)) {
-        sshc->homedir = malloc(name->fSz + 1);
-        if(!sshc->homedir) {
+        sshc->homedir = Curl_memdup0(name->fName, name->fSz);
+        if(!sshc->homedir)
           sshc->actualcode = CURLE_OUT_OF_MEMORY;
-        }
-        else {
-          memcpy(sshc->homedir, name->fName, name->fSz);
-          sshc->homedir[name->fSz] = 0;
-          infof(data, "wolfssh SFTP realpath succeeded");
-        }
         wolfSSH_SFTPNAME_list_free(name);
         state(data, SSH_STOP);
         return CURLE_OK;
@@ -633,10 +627,10 @@ static CURLcode wssh_statemach_act(struct Curl_easy *data, bool *block)
       if(data->state.resume_from > 0) {
         /* Let's read off the proper amount of bytes from the input. */
         int seekerr = CURL_SEEKFUNC_OK;
-        if(conn->seek_func) {
+        if(data->set.seek_func) {
           Curl_set_in_callback(data, true);
-          seekerr = conn->seek_func(conn->seek_client, data->state.resume_from,
-                                    SEEK_SET);
+          seekerr = data->set.seek_func(data->set.seek_client,
+                                        data->state.resume_from, SEEK_SET);
           Curl_set_in_callback(data, false);
         }
 
@@ -649,14 +643,15 @@ static CURLcode wssh_statemach_act(struct Curl_easy *data, bool *block)
           }
           /* seekerr == CURL_SEEKFUNC_CANTSEEK (can't seek to offset) */
           do {
+            char scratch[4*1024];
             size_t readthisamountnow =
-              (data->state.resume_from - passed > data->set.buffer_size) ?
-              (size_t)data->set.buffer_size :
-              curlx_sotouz(data->state.resume_from - passed);
+              (data->state.resume_from - passed >
+                (curl_off_t)sizeof(scratch)) ?
+              sizeof(scratch) : curlx_sotouz(data->state.resume_from - passed);
 
             size_t actuallyread;
             Curl_set_in_callback(data, true);
-            actuallyread = data->state.fread_func(data->state.buffer, 1,
+            actuallyread = data->state.fread_func(scratch, 1,
                                                   readthisamountnow,
                                                   data->state.in);
             Curl_set_in_callback(data, false);
@@ -685,9 +680,9 @@ static CURLcode wssh_statemach_act(struct Curl_easy *data, bool *block)
         Curl_pgrsSetUploadSize(data, data->state.infilesize);
       }
       /* upload data */
-      Curl_setup_transfer(data, -1, -1, FALSE, FIRSTSOCKET);
+      Curl_xfer_setup(data, -1, -1, FALSE, FIRSTSOCKET);
 
-      /* not set by Curl_setup_transfer to preserve keepon bits */
+      /* not set by Curl_xfer_setup to preserve keepon bits */
       conn->sockfd = conn->writesockfd;
 
       if(result) {
@@ -702,7 +697,7 @@ static CURLcode wssh_statemach_act(struct Curl_easy *data, bool *block)
         /* we want to use the _sending_ function even when the socket turns
            out readable as the underlying libssh2 sftp send function will deal
            with both accordingly */
-        conn->cselect_bits = CURL_CSELECT_OUT;
+        data->state.select_bits = CURL_CSELECT_OUT;
 
         /* since we don't really wait for anything at this point, we want the
            state machine to move on as soon as possible so we set a very short
@@ -785,20 +780,20 @@ static CURLcode wssh_statemach_act(struct Curl_easy *data, bool *block)
       /* Setup the actual download */
       if(data->req.size == 0) {
         /* no data to transfer */
-        Curl_setup_transfer(data, -1, -1, FALSE, -1);
+        Curl_xfer_setup(data, -1, -1, FALSE, -1);
         infof(data, "File already completely downloaded");
         state(data, SSH_STOP);
         break;
       }
-      Curl_setup_transfer(data, FIRSTSOCKET, data->req.size, FALSE, -1);
+      Curl_xfer_setup(data, FIRSTSOCKET, data->req.size, FALSE, -1);
 
-      /* not set by Curl_setup_transfer to preserve keepon bits */
+      /* not set by Curl_xfer_setup to preserve keepon bits */
       conn->writesockfd = conn->sockfd;
 
       /* we want to use the _receiving_ function even when the socket turns
          out writableable as the underlying libssh2 recv function will deal
          with both accordingly */
-      conn->cselect_bits = CURL_CSELECT_IN;
+      data->state.select_bits = CURL_CSELECT_IN;
 
       if(result) {
         /* this should never occur; the close state should be entered
@@ -1168,6 +1163,7 @@ CURLcode Curl_ssh_init(void)
 }
 void Curl_ssh_cleanup(void)
 {
+  (void)wolfSSH_Cleanup();
 }
 
 #endif /* USE_WOLFSSH */
diff --git a/vendor/curl/lib/vtls/bearssl.c b/vendor/curl/lib/vtls/bearssl.c
index 934149c1b0..a595f54a9c 100644
--- a/vendor/curl/lib/vtls/bearssl.c
+++ b/vendor/curl/lib/vtls/bearssl.c
@@ -28,6 +28,7 @@
 #include 
 
 #include "bearssl.h"
+#include "cipher_suite.h"
 #include "urldata.h"
 #include "sendf.h"
 #include "inet_pton.h"
@@ -37,7 +38,6 @@
 #include "select.h"
 #include "multiif.h"
 #include "curl_printf.h"
-#include "strcase.h"
 
 /* The last #include files should be: */
 #include "curl_memory.h"
@@ -120,9 +120,9 @@ static CURLcode load_cafile(struct cafile_source *source,
   br_x509_pkey *pkey;
   FILE *fp = 0;
   unsigned char buf[BUFSIZ];
-  const unsigned char *p;
+  const unsigned char *p = NULL;
   const char *name;
-  size_t n, i, pushed;
+  size_t n = 0, i, pushed;
 
   DEBUGASSERT(source->type == CAFILE_SOURCE_PATH
               || source->type == CAFILE_SOURCE_BLOB);
@@ -360,213 +360,121 @@ static const br_x509_class x509_vtable = {
   x509_get_pkey
 };
 
-struct st_cipher {
-  const char *name; /* Cipher suite IANA name. It starts with "TLS_" prefix */
-  const char *alias_name; /* Alias name is the same as OpenSSL cipher name */
-  uint16_t num; /* BearSSL cipher suite */
-};
-
-/* Macro to initialize st_cipher data structure */
-#define CIPHER_DEF(num, alias) { #num, alias, BR_##num }
-
-static const struct st_cipher ciphertable[] = {
+static const uint16_t ciphertable[] = {
   /* RFC 2246 TLS 1.0 */
-  CIPHER_DEF(TLS_RSA_WITH_3DES_EDE_CBC_SHA,                        /* 0x000A */
-             "DES-CBC3-SHA"),
+  BR_TLS_RSA_WITH_3DES_EDE_CBC_SHA,                        /* 0x000A */
 
   /* RFC 3268 TLS 1.0 AES */
-  CIPHER_DEF(TLS_RSA_WITH_AES_128_CBC_SHA,                         /* 0x002F */
-             "AES128-SHA"),
-  CIPHER_DEF(TLS_RSA_WITH_AES_256_CBC_SHA,                         /* 0x0035 */
-             "AES256-SHA"),
+  BR_TLS_RSA_WITH_AES_128_CBC_SHA,                         /* 0x002F */
+  BR_TLS_RSA_WITH_AES_256_CBC_SHA,                         /* 0x0035 */
 
   /* RFC 5246 TLS 1.2 */
-  CIPHER_DEF(TLS_RSA_WITH_AES_128_CBC_SHA256,                      /* 0x003C */
-             "AES128-SHA256"),
-  CIPHER_DEF(TLS_RSA_WITH_AES_256_CBC_SHA256,                      /* 0x003D */
-             "AES256-SHA256"),
+  BR_TLS_RSA_WITH_AES_128_CBC_SHA256,                      /* 0x003C */
+  BR_TLS_RSA_WITH_AES_256_CBC_SHA256,                      /* 0x003D */
 
   /* RFC 5288 TLS 1.2 AES GCM */
-  CIPHER_DEF(TLS_RSA_WITH_AES_128_GCM_SHA256,                      /* 0x009C */
-             "AES128-GCM-SHA256"),
-  CIPHER_DEF(TLS_RSA_WITH_AES_256_GCM_SHA384,                      /* 0x009D */
-             "AES256-GCM-SHA384"),
+  BR_TLS_RSA_WITH_AES_128_GCM_SHA256,                      /* 0x009C */
+  BR_TLS_RSA_WITH_AES_256_GCM_SHA384,                      /* 0x009D */
 
   /* RFC 4492 TLS 1.0 ECC */
-  CIPHER_DEF(TLS_ECDH_ECDSA_WITH_3DES_EDE_CBC_SHA,                 /* 0xC003 */
-             "ECDH-ECDSA-DES-CBC3-SHA"),
-  CIPHER_DEF(TLS_ECDH_ECDSA_WITH_AES_128_CBC_SHA,                  /* 0xC004 */
-             "ECDH-ECDSA-AES128-SHA"),
-  CIPHER_DEF(TLS_ECDH_ECDSA_WITH_AES_256_CBC_SHA,                  /* 0xC005 */
-             "ECDH-ECDSA-AES256-SHA"),
-  CIPHER_DEF(TLS_ECDHE_ECDSA_WITH_3DES_EDE_CBC_SHA,                /* 0xC008 */
-             "ECDHE-ECDSA-DES-CBC3-SHA"),
-  CIPHER_DEF(TLS_ECDHE_ECDSA_WITH_AES_128_CBC_SHA,                 /* 0xC009 */
-             "ECDHE-ECDSA-AES128-SHA"),
-  CIPHER_DEF(TLS_ECDHE_ECDSA_WITH_AES_256_CBC_SHA,                 /* 0xC00A */
-             "ECDHE-ECDSA-AES256-SHA"),
-  CIPHER_DEF(TLS_ECDH_RSA_WITH_3DES_EDE_CBC_SHA,                   /* 0xC00D */
-             "ECDH-RSA-DES-CBC3-SHA"),
-  CIPHER_DEF(TLS_ECDH_RSA_WITH_AES_128_CBC_SHA,                    /* 0xC00E */
-             "ECDH-RSA-AES128-SHA"),
-  CIPHER_DEF(TLS_ECDH_RSA_WITH_AES_256_CBC_SHA,                    /* 0xC00F */
-             "ECDH-RSA-AES256-SHA"),
-  CIPHER_DEF(TLS_ECDHE_RSA_WITH_3DES_EDE_CBC_SHA,                  /* 0xC012 */
-             "ECDHE-RSA-DES-CBC3-SHA"),
-  CIPHER_DEF(TLS_ECDHE_RSA_WITH_AES_128_CBC_SHA,                   /* 0xC013 */
-             "ECDHE-RSA-AES128-SHA"),
-  CIPHER_DEF(TLS_ECDHE_RSA_WITH_AES_256_CBC_SHA,                   /* 0xC014 */
-             "ECDHE-RSA-AES256-SHA"),
+  BR_TLS_ECDH_ECDSA_WITH_3DES_EDE_CBC_SHA,                 /* 0xC003 */
+  BR_TLS_ECDH_ECDSA_WITH_AES_128_CBC_SHA,                  /* 0xC004 */
+  BR_TLS_ECDH_ECDSA_WITH_AES_256_CBC_SHA,                  /* 0xC005 */
+  BR_TLS_ECDHE_ECDSA_WITH_3DES_EDE_CBC_SHA,                /* 0xC008 */
+  BR_TLS_ECDHE_ECDSA_WITH_AES_128_CBC_SHA,                 /* 0xC009 */
+  BR_TLS_ECDHE_ECDSA_WITH_AES_256_CBC_SHA,                 /* 0xC00A */
+  BR_TLS_ECDH_RSA_WITH_3DES_EDE_CBC_SHA,                   /* 0xC00D */
+  BR_TLS_ECDH_RSA_WITH_AES_128_CBC_SHA,                    /* 0xC00E */
+  BR_TLS_ECDH_RSA_WITH_AES_256_CBC_SHA,                    /* 0xC00F */
+  BR_TLS_ECDHE_RSA_WITH_3DES_EDE_CBC_SHA,                  /* 0xC012 */
+  BR_TLS_ECDHE_RSA_WITH_AES_128_CBC_SHA,                   /* 0xC013 */
+  BR_TLS_ECDHE_RSA_WITH_AES_256_CBC_SHA,                   /* 0xC014 */
 
   /* RFC 5289 TLS 1.2 ECC HMAC SHA256/384 */
-  CIPHER_DEF(TLS_ECDHE_ECDSA_WITH_AES_128_CBC_SHA256,              /* 0xC023 */
-             "ECDHE-ECDSA-AES128-SHA256"),
-  CIPHER_DEF(TLS_ECDHE_ECDSA_WITH_AES_256_CBC_SHA384,              /* 0xC024 */
-             "ECDHE-ECDSA-AES256-SHA384"),
-  CIPHER_DEF(TLS_ECDH_ECDSA_WITH_AES_128_CBC_SHA256,               /* 0xC025 */
-             "ECDH-ECDSA-AES128-SHA256"),
-  CIPHER_DEF(TLS_ECDH_ECDSA_WITH_AES_256_CBC_SHA384,               /* 0xC026 */
-             "ECDH-ECDSA-AES256-SHA384"),
-  CIPHER_DEF(TLS_ECDHE_RSA_WITH_AES_128_CBC_SHA256,                /* 0xC027 */
-             "ECDHE-RSA-AES128-SHA256"),
-  CIPHER_DEF(TLS_ECDHE_RSA_WITH_AES_256_CBC_SHA384,                /* 0xC028 */
-             "ECDHE-RSA-AES256-SHA384"),
-  CIPHER_DEF(TLS_ECDH_RSA_WITH_AES_128_CBC_SHA256,                 /* 0xC029 */
-             "ECDH-RSA-AES128-SHA256"),
-  CIPHER_DEF(TLS_ECDH_RSA_WITH_AES_256_CBC_SHA384,                 /* 0xC02A */
-             "ECDH-RSA-AES256-SHA384"),
+  BR_TLS_ECDHE_ECDSA_WITH_AES_128_CBC_SHA256,              /* 0xC023 */
+  BR_TLS_ECDHE_ECDSA_WITH_AES_256_CBC_SHA384,              /* 0xC024 */
+  BR_TLS_ECDH_ECDSA_WITH_AES_128_CBC_SHA256,               /* 0xC025 */
+  BR_TLS_ECDH_ECDSA_WITH_AES_256_CBC_SHA384,               /* 0xC026 */
+  BR_TLS_ECDHE_RSA_WITH_AES_128_CBC_SHA256,                /* 0xC027 */
+  BR_TLS_ECDHE_RSA_WITH_AES_256_CBC_SHA384,                /* 0xC028 */
+  BR_TLS_ECDH_RSA_WITH_AES_128_CBC_SHA256,                 /* 0xC029 */
+  BR_TLS_ECDH_RSA_WITH_AES_256_CBC_SHA384,                 /* 0xC02A */
 
   /* RFC 5289 TLS 1.2 GCM */
-  CIPHER_DEF(TLS_ECDHE_ECDSA_WITH_AES_128_GCM_SHA256,              /* 0xC02B */
-             "ECDHE-ECDSA-AES128-GCM-SHA256"),
-  CIPHER_DEF(TLS_ECDHE_ECDSA_WITH_AES_256_GCM_SHA384,              /* 0xC02C */
-             "ECDHE-ECDSA-AES256-GCM-SHA384"),
-  CIPHER_DEF(TLS_ECDH_ECDSA_WITH_AES_128_GCM_SHA256,               /* 0xC02D */
-             "ECDH-ECDSA-AES128-GCM-SHA256"),
-  CIPHER_DEF(TLS_ECDH_ECDSA_WITH_AES_256_GCM_SHA384,               /* 0xC02E */
-             "ECDH-ECDSA-AES256-GCM-SHA384"),
-  CIPHER_DEF(TLS_ECDHE_RSA_WITH_AES_128_GCM_SHA256,                /* 0xC02F */
-             "ECDHE-RSA-AES128-GCM-SHA256"),
-  CIPHER_DEF(TLS_ECDHE_RSA_WITH_AES_256_GCM_SHA384,                /* 0xC030 */
-             "ECDHE-RSA-AES256-GCM-SHA384"),
-  CIPHER_DEF(TLS_ECDH_RSA_WITH_AES_128_GCM_SHA256,                 /* 0xC031 */
-             "ECDH-RSA-AES128-GCM-SHA256"),
-  CIPHER_DEF(TLS_ECDH_RSA_WITH_AES_256_GCM_SHA384,                 /* 0xC032 */
-             "ECDH-RSA-AES256-GCM-SHA384"),
-#ifdef BR_TLS_RSA_WITH_AES_128_CCM
+  BR_TLS_ECDHE_ECDSA_WITH_AES_128_GCM_SHA256,              /* 0xC02B */
+  BR_TLS_ECDHE_ECDSA_WITH_AES_256_GCM_SHA384,              /* 0xC02C */
+  BR_TLS_ECDH_ECDSA_WITH_AES_128_GCM_SHA256,               /* 0xC02D */
+  BR_TLS_ECDH_ECDSA_WITH_AES_256_GCM_SHA384,               /* 0xC02E */
+  BR_TLS_ECDHE_RSA_WITH_AES_128_GCM_SHA256,                /* 0xC02F */
+  BR_TLS_ECDHE_RSA_WITH_AES_256_GCM_SHA384,                /* 0xC030 */
+  BR_TLS_ECDH_RSA_WITH_AES_128_GCM_SHA256,                 /* 0xC031 */
+  BR_TLS_ECDH_RSA_WITH_AES_256_GCM_SHA384,                 /* 0xC032 */
 
+#ifdef BR_TLS_RSA_WITH_AES_128_CCM
   /* RFC 6655 TLS 1.2 CCM
      Supported since BearSSL 0.6 */
-  CIPHER_DEF(TLS_RSA_WITH_AES_128_CCM,                             /* 0xC09C */
-             "AES128-CCM"),
-  CIPHER_DEF(TLS_RSA_WITH_AES_256_CCM,                             /* 0xC09D */
-             "AES256-CCM"),
-  CIPHER_DEF(TLS_RSA_WITH_AES_128_CCM_8,                           /* 0xC0A0 */
-             "AES128-CCM8"),
-  CIPHER_DEF(TLS_RSA_WITH_AES_256_CCM_8,                           /* 0xC0A1 */
-             "AES256-CCM8"),
+  BR_TLS_RSA_WITH_AES_128_CCM,                             /* 0xC09C */
+  BR_TLS_RSA_WITH_AES_256_CCM,                             /* 0xC09D */
+  BR_TLS_RSA_WITH_AES_128_CCM_8,                           /* 0xC0A0 */
+  BR_TLS_RSA_WITH_AES_256_CCM_8,                           /* 0xC0A1 */
 
   /* RFC 7251 TLS 1.2 ECC CCM
      Supported since BearSSL 0.6 */
-  CIPHER_DEF(TLS_ECDHE_ECDSA_WITH_AES_128_CCM,                     /* 0xC0AC */
-             "ECDHE-ECDSA-AES128-CCM"),
-  CIPHER_DEF(TLS_ECDHE_ECDSA_WITH_AES_256_CCM,                     /* 0xC0AD */
-             "ECDHE-ECDSA-AES256-CCM"),
-  CIPHER_DEF(TLS_ECDHE_ECDSA_WITH_AES_128_CCM_8,                   /* 0xC0AE */
-             "ECDHE-ECDSA-AES128-CCM8"),
-  CIPHER_DEF(TLS_ECDHE_ECDSA_WITH_AES_256_CCM_8,                   /* 0xC0AF */
-             "ECDHE-ECDSA-AES256-CCM8"),
+  BR_TLS_ECDHE_ECDSA_WITH_AES_128_CCM,                     /* 0xC0AC */
+  BR_TLS_ECDHE_ECDSA_WITH_AES_256_CCM,                     /* 0xC0AD */
+  BR_TLS_ECDHE_ECDSA_WITH_AES_128_CCM_8,                   /* 0xC0AE */
+  BR_TLS_ECDHE_ECDSA_WITH_AES_256_CCM_8,                   /* 0xC0AF */
 #endif
 
   /* RFC 7905 TLS 1.2 ChaCha20-Poly1305
      Supported since BearSSL 0.2 */
-  CIPHER_DEF(TLS_ECDHE_RSA_WITH_CHACHA20_POLY1305_SHA256,          /* 0xCCA8 */
-             "ECDHE-RSA-CHACHA20-POLY1305"),
-  CIPHER_DEF(TLS_ECDHE_ECDSA_WITH_CHACHA20_POLY1305_SHA256,        /* 0xCCA9 */
-             "ECDHE-ECDSA-CHACHA20-POLY1305"),
+  BR_TLS_ECDHE_RSA_WITH_CHACHA20_POLY1305_SHA256,          /* 0xCCA8 */
+  BR_TLS_ECDHE_ECDSA_WITH_CHACHA20_POLY1305_SHA256,        /* 0xCCA9 */
 };
 
 #define NUM_OF_CIPHERS (sizeof(ciphertable) / sizeof(ciphertable[0]))
-#define CIPHER_NAME_BUF_LEN 64
-
-static bool is_separator(char c)
-{
-  /* Return whether character is a cipher list separator. */
-  switch(c) {
-    case ' ':
-    case '\t':
-    case ':':
-    case ',':
-    case ';':
-      return true;
-  }
-  return false;
-}
 
 static CURLcode bearssl_set_selected_ciphers(struct Curl_easy *data,
                                              br_ssl_engine_context *ssl_eng,
                                              const char *ciphers)
 {
-  uint16_t selected_ciphers[NUM_OF_CIPHERS];
-  size_t selected_count = 0;
-  char cipher_name[CIPHER_NAME_BUF_LEN];
-  const char *cipher_start = ciphers;
-  const char *cipher_end;
-  size_t i, j;
-
-  if(!cipher_start)
-    return CURLE_SSL_CIPHER;
-
-  while(true) {
-    /* Extract the next cipher name from the ciphers string */
-    while(is_separator(*cipher_start))
-      ++cipher_start;
-    if(*cipher_start == '\0')
-      break;
-    cipher_end = cipher_start;
-    while(*cipher_end != '\0' && !is_separator(*cipher_end))
-      ++cipher_end;
-    j = cipher_end - cipher_start < CIPHER_NAME_BUF_LEN - 1 ?
-        cipher_end - cipher_start : CIPHER_NAME_BUF_LEN - 1;
-    strncpy(cipher_name, cipher_start, j);
-    cipher_name[j] = '\0';
-    cipher_start = cipher_end;
-
-    /* Lookup the cipher name in the table of available ciphers. If the cipher
-       name starts with "TLS_" we do the lookup by IANA name. Otherwise, we try
-       to match cipher name by an (OpenSSL) alias. */
-    if(strncasecompare(cipher_name, "TLS_", 4)) {
-      for(i = 0; i < NUM_OF_CIPHERS &&
-                 !strcasecompare(cipher_name, ciphertable[i].name); ++i);
+  uint16_t selected[NUM_OF_CIPHERS];
+  size_t count = 0, i;
+  const char *ptr, *end;
+
+  for(ptr = ciphers; ptr[0] != '\0' && count < NUM_OF_CIPHERS; ptr = end) {
+    uint16_t id = Curl_cipher_suite_walk_str(&ptr, &end);
+
+    /* Check if cipher is supported */
+    if(id) {
+      for(i = 0; i < NUM_OF_CIPHERS && ciphertable[i] != id; i++);
+      if(i == NUM_OF_CIPHERS)
+        id = 0;
     }
-    else {
-      for(i = 0; i < NUM_OF_CIPHERS &&
-                 !strcasecompare(cipher_name, ciphertable[i].alias_name); ++i);
-    }
-    if(i == NUM_OF_CIPHERS) {
-      infof(data, "BearSSL: unknown cipher in list: %s", cipher_name);
+    if(!id) {
+      if(ptr[0] != '\0')
+        infof(data, "BearSSL: unknown cipher in list: \"%.*s\"",
+              (int) (end - ptr), ptr);
       continue;
     }
 
     /* No duplicates allowed */
-    for(j = 0; j < selected_count &&
-               selected_ciphers[j] != ciphertable[i].num; j++);
-    if(j < selected_count) {
-      infof(data, "BearSSL: duplicate cipher in list: %s", cipher_name);
+    for(i = 0; i < count && selected[i] != id; i++);
+    if(i < count) {
+      infof(data, "BearSSL: duplicate cipher in list: \"%.*s\"",
+            (int) (end - ptr), ptr);
       continue;
     }
 
-    DEBUGASSERT(selected_count < NUM_OF_CIPHERS);
-    selected_ciphers[selected_count] = ciphertable[i].num;
-    ++selected_count;
+    selected[count++] = id;
   }
 
-  if(selected_count == 0) {
+  if(count == 0) {
     failf(data, "BearSSL: no supported cipher in list");
     return CURLE_SSL_CIPHER;
   }
 
-  br_ssl_engine_set_suites(ssl_eng, selected_ciphers, selected_count);
+  br_ssl_engine_set_suites(ssl_eng, selected, count);
   return CURLE_OK;
 }
 
@@ -582,17 +490,12 @@ static CURLcode bearssl_connect_step1(struct Curl_cfilter *cf,
   const char * const ssl_cafile =
     /* CURLOPT_CAINFO_BLOB overrides CURLOPT_CAINFO */
     (ca_info_blob ? NULL : conn_config->CAfile);
-  const char *hostname = connssl->hostname;
+  const char *hostname = connssl->peer.hostname;
   const bool verifypeer = conn_config->verifypeer;
   const bool verifyhost = conn_config->verifyhost;
   CURLcode ret;
   unsigned version_min, version_max;
   int session_set = 0;
-#ifdef ENABLE_IPV6
-  struct in6_addr addr;
-#else
-  struct in_addr addr;
-#endif
 
   DEBUGASSERT(backend);
   CURL_TRC_CF(data, cf, "connect_step1");
@@ -685,7 +588,7 @@ static CURLcode bearssl_connect_step1(struct Curl_cfilter *cf,
 
     CURL_TRC_CF(data, cf, "connect_step1, check session cache");
     Curl_ssl_sessionid_lock(data);
-    if(!Curl_ssl_getsessionid(cf, data, &session, NULL)) {
+    if(!Curl_ssl_getsessionid(cf, data, &connssl->peer, &session, NULL)) {
       br_ssl_engine_set_session_parameters(&backend->ctx.eng, session);
       session_set = 1;
       infof(data, "BearSSL: reusing session ID");
@@ -706,11 +609,7 @@ static CURLcode bearssl_connect_step1(struct Curl_cfilter *cf,
     infof(data, VTLS_INFOF_ALPN_OFFER_1STR, proto.data);
   }
 
-  if((1 == Curl_inet_pton(AF_INET, hostname, &addr))
-#ifdef ENABLE_IPV6
-      || (1 == Curl_inet_pton(AF_INET6, hostname, &addr))
-#endif
-     ) {
+  if(connssl->peer.type != CURL_SSL_PEER_DNS) {
     if(verifyhost) {
       failf(data, "BearSSL: "
             "host verification of IP address is not supported");
@@ -719,12 +618,11 @@ static CURLcode bearssl_connect_step1(struct Curl_cfilter *cf,
     hostname = NULL;
   }
   else {
-    char *snihost = Curl_ssl_snihost(data, hostname, NULL);
-    if(!snihost) {
+    if(!connssl->peer.sni) {
       failf(data, "Failed to set SNI");
       return CURLE_SSL_CONNECT_ERROR;
     }
-    hostname = snihost;
+    hostname = connssl->peer.sni;
     CURL_TRC_CF(data, cf, "connect_step1, SNI set");
   }
 
@@ -749,26 +647,26 @@ static CURLcode bearssl_connect_step1(struct Curl_cfilter *cf,
   return CURLE_OK;
 }
 
-static int bearssl_get_select_socks(struct Curl_cfilter *cf,
-                                    struct Curl_easy *data,
-                                    curl_socket_t *socks)
+static void bearssl_adjust_pollset(struct Curl_cfilter *cf,
+                                   struct Curl_easy *data,
+                                   struct easy_pollset *ps)
 {
-  struct ssl_connect_data *connssl = cf->ctx;
-  curl_socket_t sock = Curl_conn_cf_get_socket(cf->next, data);
-
-  if(sock == CURL_SOCKET_BAD)
-    return GETSOCK_BLANK;
-  else {
-    struct bearssl_ssl_backend_data *backend =
-      (struct bearssl_ssl_backend_data *)connssl->backend;
-    unsigned state = br_ssl_engine_current_state(&backend->ctx.eng);
-    if(state & BR_SSL_SENDREC) {
-      socks[0] = sock;
-      return GETSOCK_WRITESOCK(0);
+  if(!cf->connected) {
+    curl_socket_t sock = Curl_conn_cf_get_socket(cf->next, data);
+    if(sock != CURL_SOCKET_BAD) {
+      struct ssl_connect_data *connssl = cf->ctx;
+      struct bearssl_ssl_backend_data *backend =
+        (struct bearssl_ssl_backend_data *)connssl->backend;
+      unsigned state = br_ssl_engine_current_state(&backend->ctx.eng);
+
+      if(state & BR_SSL_SENDREC) {
+        Curl_pollset_set_out_only(data, ps, sock);
+      }
+      else {
+        Curl_pollset_set_in_only(data, ps, sock);
+      }
     }
   }
-  socks[0] = sock;
-  return GETSOCK_READSOCK(0);
 }
 
 static CURLcode bearssl_run_until(struct Curl_cfilter *cf,
@@ -834,7 +732,7 @@ static CURLcode bearssl_run_until(struct Curl_cfilter *cf,
       CURL_TRC_CF(data, cf, "ssl_recv(len=%zu) -> %zd, %d", len, ret, result);
       if(ret == 0) {
         failf(data, "SSL: EOF without close notify");
-        return CURLE_READ_ERROR;
+        return CURLE_RECV_ERROR;
       }
       if(ret <= 0) {
         return result;
@@ -850,6 +748,9 @@ static CURLcode bearssl_connect_step2(struct Curl_cfilter *cf,
   struct ssl_connect_data *connssl = cf->ctx;
   struct bearssl_ssl_backend_data *backend =
     (struct bearssl_ssl_backend_data *)connssl->backend;
+  br_ssl_session_parameters session;
+  char cipher_str[64];
+  char ver_str[16];
   CURLcode ret;
 
   DEBUGASSERT(backend);
@@ -860,6 +761,7 @@ static CURLcode bearssl_connect_step2(struct Curl_cfilter *cf,
     return CURLE_OK;
   if(ret == CURLE_OK) {
     unsigned int tver;
+
     if(br_ssl_engine_current_state(&backend->ctx.eng) == BR_SSL_CLOSED) {
       failf(data, "SSL: connection closed during handshake");
       return CURLE_SSL_CONNECT_ERROR;
@@ -867,16 +769,29 @@ static CURLcode bearssl_connect_step2(struct Curl_cfilter *cf,
     connssl->connecting_state = ssl_connect_3;
     /* Informational message */
     tver = br_ssl_engine_get_version(&backend->ctx.eng);
-    if(tver == 0x0303)
-      infof(data, "SSL connection using TLSv1.2");
-    else if(tver == 0x0304)
-      infof(data, "SSL connection using TLSv1.3");
-    else
-      infof(data, "SSL connection using TLS 0x%x", tver);
+    if(tver == BR_TLS12)
+      strcpy(ver_str, "TLSv1.2");
+    else if(tver == BR_TLS11)
+      strcpy(ver_str, "TLSv1.1");
+    else if(tver == BR_TLS10)
+      strcpy(ver_str, "TLSv1.0");
+    else {
+      msnprintf(ver_str, sizeof(ver_str), "TLS 0x%04x", tver);
+    }
+    br_ssl_engine_get_session_parameters(&backend->ctx.eng, &session);
+    Curl_cipher_suite_get_str(session.cipher_suite, cipher_str,
+                              sizeof(cipher_str), true);
+    infof(data, "BearSSL: %s connection using %s", ver_str, cipher_str);
   }
   return ret;
 }
 
+static void bearssl_session_free(void *sessionid, size_t idsize)
+{
+  (void)idsize;
+  free(sessionid);
+}
+
 static CURLcode bearssl_connect_step3(struct Curl_cfilter *cf,
                                       struct Curl_easy *data)
 {
@@ -900,7 +815,6 @@ static CURLcode bearssl_connect_step3(struct Curl_cfilter *cf,
 
   if(ssl_config->primary.sessionid) {
     bool incache;
-    bool added = FALSE;
     void *oldsession;
     br_ssl_session_parameters *session;
 
@@ -909,16 +823,16 @@ static CURLcode bearssl_connect_step3(struct Curl_cfilter *cf,
       return CURLE_OUT_OF_MEMORY;
     br_ssl_engine_get_session_parameters(&backend->ctx.eng, session);
     Curl_ssl_sessionid_lock(data);
-    incache = !(Curl_ssl_getsessionid(cf, data, &oldsession, NULL));
+    incache = !(Curl_ssl_getsessionid(cf, data, &connssl->peer,
+                                      &oldsession, NULL));
     if(incache)
       Curl_ssl_delsessionid(data, oldsession);
-    ret = Curl_ssl_addsessionid(cf, data, session, 0, &added);
+
+    ret = Curl_ssl_addsessionid(cf, data, &connssl->peer, session, 0,
+                                bearssl_session_free);
     Curl_ssl_sessionid_unlock(data);
-    if(!added)
-      free(session);
-    if(ret) {
-      return CURLE_OUT_OF_MEMORY;
-    }
+    if(ret)
+      return ret;
   }
 
   connssl->connecting_state = ssl_connect_done;
@@ -1177,11 +1091,6 @@ static void bearssl_close(struct Curl_cfilter *cf, struct Curl_easy *data)
   }
 }
 
-static void bearssl_session_free(void *ptr)
-{
-  free(ptr);
-}
-
 static CURLcode bearssl_sha256sum(const unsigned char *input,
                                   size_t inputlen,
                                   unsigned char *sha256sum,
@@ -1210,11 +1119,10 @@ const struct Curl_ssl Curl_ssl_bearssl = {
   Curl_none_cert_status_request,   /* cert_status_request */
   bearssl_connect,                 /* connect */
   bearssl_connect_nonblocking,     /* connect_nonblocking */
-  bearssl_get_select_socks,        /* getsock */
+  bearssl_adjust_pollset,          /* adjust_pollset */
   bearssl_get_internals,           /* get_internals */
   bearssl_close,                   /* close_one */
   Curl_none_close_all,             /* close_all */
-  bearssl_session_free,            /* session_free */
   Curl_none_set_engine,            /* set_engine */
   Curl_none_set_engine_default,    /* set_engine_default */
   Curl_none_engines_list,          /* engines_list */
diff --git a/vendor/curl/lib/vtls/cipher_suite.c b/vendor/curl/lib/vtls/cipher_suite.c
new file mode 100644
index 0000000000..a78838d195
--- /dev/null
+++ b/vendor/curl/lib/vtls/cipher_suite.c
@@ -0,0 +1,716 @@
+/***************************************************************************
+ *                                  _   _ ____  _
+ *  Project                     ___| | | |  _ \| |
+ *                             / __| | | | |_) | |
+ *                            | (__| |_| |  _ <| |___
+ *                             \___|\___/|_| \_\_____|
+ *
+ * Copyright (C) Jan Venekamp, 
+ *
+ * This software is licensed as described in the file COPYING, which
+ * you should have received as part of this distribution. The terms
+ * are also available at https://curl.se/docs/copyright.html.
+ *
+ * You may opt to use, copy, modify, merge, publish, distribute and/or sell
+ * copies of the Software, and permit persons to whom the Software is
+ * furnished to do so, under the terms of the COPYING file.
+ *
+ * This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY
+ * KIND, either express or implied.
+ *
+ * SPDX-License-Identifier: curl
+ *
+ ***************************************************************************/
+#include "curl_setup.h"
+
+#if defined(USE_MBEDTLS) || defined(USE_BEARSSL)
+#include "cipher_suite.h"
+#include "curl_printf.h"
+#include "strcase.h"
+#include 
+
+/*
+ * To support the CURLOPT_SSL_CIPHER_LIST option on SSL backends
+ * that do not support it natively, but do support setting a list of
+ * IANA ids, we need a list of all supported cipher suite names
+ * (openssl and IANA) to be able to look up the IANA ids.
+ *
+ * To keep the binary size of this list down we compress each entry
+ * down to 2 + 6 bytes using the C preprocessor.
+ */
+
+/*
+ * mbedTLS NOTE: mbedTLS has mbedtls_ssl_get_ciphersuite_id() to
+ * convert a string representation to an IANA id, we do not use that
+ * because it does not support "standard" openssl cipher suite
+ * names, nor IANA names.
+ */
+
+/* NOTE: also see tests/unit/unit3205.c */
+
+/* Text for cipher suite parts (max 64 entries),
+   keep indexes below in sync with this! */
+static const char *cs_txt =
+  "\0"
+  "TLS" "\0"
+  "WITH" "\0"
+  "128" "\0"
+  "256" "\0"
+  "3DES" "\0"
+  "8" "\0"
+  "AES" "\0"
+  "AES128" "\0"
+  "AES256" "\0"
+  "CBC" "\0"
+  "CBC3" "\0"
+  "CCM" "\0"
+  "CCM8" "\0"
+  "CHACHA20" "\0"
+  "DES" "\0"
+  "DHE" "\0"
+  "ECDH" "\0"
+  "ECDHE" "\0"
+  "ECDSA" "\0"
+  "EDE" "\0"
+  "GCM" "\0"
+  "MD5" "\0"
+  "NULL" "\0"
+  "POLY1305" "\0"
+  "PSK" "\0"
+  "RSA" "\0"
+  "SHA" "\0"
+  "SHA256" "\0"
+  "SHA384" "\0"
+#if defined(USE_MBEDTLS)
+  "ARIA" "\0"
+  "ARIA128" "\0"
+  "ARIA256" "\0"
+  "CAMELLIA" "\0"
+  "CAMELLIA128" "\0"
+  "CAMELLIA256" "\0"
+#endif
+;
+/* Indexes of above cs_txt */
+enum {
+  CS_TXT_IDX_,
+  CS_TXT_IDX_TLS,
+  CS_TXT_IDX_WITH,
+  CS_TXT_IDX_128,
+  CS_TXT_IDX_256,
+  CS_TXT_IDX_3DES,
+  CS_TXT_IDX_8,
+  CS_TXT_IDX_AES,
+  CS_TXT_IDX_AES128,
+  CS_TXT_IDX_AES256,
+  CS_TXT_IDX_CBC,
+  CS_TXT_IDX_CBC3,
+  CS_TXT_IDX_CCM,
+  CS_TXT_IDX_CCM8,
+  CS_TXT_IDX_CHACHA20,
+  CS_TXT_IDX_DES,
+  CS_TXT_IDX_DHE,
+  CS_TXT_IDX_ECDH,
+  CS_TXT_IDX_ECDHE,
+  CS_TXT_IDX_ECDSA,
+  CS_TXT_IDX_EDE,
+  CS_TXT_IDX_GCM,
+  CS_TXT_IDX_MD5,
+  CS_TXT_IDX_NULL,
+  CS_TXT_IDX_POLY1305,
+  CS_TXT_IDX_PSK,
+  CS_TXT_IDX_RSA,
+  CS_TXT_IDX_SHA,
+  CS_TXT_IDX_SHA256,
+  CS_TXT_IDX_SHA384,
+#if defined(USE_MBEDTLS)
+  CS_TXT_IDX_ARIA,
+  CS_TXT_IDX_ARIA128,
+  CS_TXT_IDX_ARIA256,
+  CS_TXT_IDX_CAMELLIA,
+  CS_TXT_IDX_CAMELLIA128,
+  CS_TXT_IDX_CAMELLIA256,
+#endif
+  CS_TXT_LEN,
+};
+
+#define CS_ZIP_IDX(a, b, c, d, e, f, g, h)    \
+{                                             \
+  (uint8_t) ((a) << 2 | ((b) & 0x3F) >> 4),   \
+  (uint8_t) ((b) << 4 | ((c) & 0x3F) >> 2),   \
+  (uint8_t) ((c) << 6 | ((d) & 0x3F)),        \
+  (uint8_t) ((e) << 2 | ((f) & 0x3F) >> 4),   \
+  (uint8_t) ((f) << 4 | ((g) & 0x3F) >> 2),   \
+  (uint8_t) ((g) << 6 | ((h) & 0x3F))         \
+}
+#define CS_ENTRY(id, a, b, c, d, e, f, g, h)  \
+{                                             \
+  id,                                         \
+  CS_ZIP_IDX(                                 \
+    CS_TXT_IDX_ ## a, CS_TXT_IDX_ ## b,       \
+    CS_TXT_IDX_ ## c, CS_TXT_IDX_ ## d,       \
+    CS_TXT_IDX_ ## e, CS_TXT_IDX_ ## f,       \
+    CS_TXT_IDX_ ## g, CS_TXT_IDX_ ## h        \
+  )                                           \
+}
+
+struct cs_entry {
+  uint16_t id;
+  uint8_t zip[6];
+};
+
+/* !checksrc! disable COMMANOSPACE all */
+static const struct cs_entry cs_list [] = {
+  CS_ENTRY(0x002F, TLS,RSA,WITH,AES,128,CBC,SHA,),
+  CS_ENTRY(0x002F, AES128,SHA,,,,,,),
+  CS_ENTRY(0x0035, TLS,RSA,WITH,AES,256,CBC,SHA,),
+  CS_ENTRY(0x0035, AES256,SHA,,,,,,),
+  CS_ENTRY(0x003C, TLS,RSA,WITH,AES,128,CBC,SHA256,),
+  CS_ENTRY(0x003C, AES128,SHA256,,,,,,),
+  CS_ENTRY(0x003D, TLS,RSA,WITH,AES,256,CBC,SHA256,),
+  CS_ENTRY(0x003D, AES256,SHA256,,,,,,),
+  CS_ENTRY(0x009C, TLS,RSA,WITH,AES,128,GCM,SHA256,),
+  CS_ENTRY(0x009C, AES128,GCM,SHA256,,,,,),
+  CS_ENTRY(0x009D, TLS,RSA,WITH,AES,256,GCM,SHA384,),
+  CS_ENTRY(0x009D, AES256,GCM,SHA384,,,,,),
+  CS_ENTRY(0xC004, TLS,ECDH,ECDSA,WITH,AES,128,CBC,SHA),
+  CS_ENTRY(0xC004, ECDH,ECDSA,AES128,SHA,,,,),
+  CS_ENTRY(0xC005, TLS,ECDH,ECDSA,WITH,AES,256,CBC,SHA),
+  CS_ENTRY(0xC005, ECDH,ECDSA,AES256,SHA,,,,),
+  CS_ENTRY(0xC009, TLS,ECDHE,ECDSA,WITH,AES,128,CBC,SHA),
+  CS_ENTRY(0xC009, ECDHE,ECDSA,AES128,SHA,,,,),
+  CS_ENTRY(0xC00A, TLS,ECDHE,ECDSA,WITH,AES,256,CBC,SHA),
+  CS_ENTRY(0xC00A, ECDHE,ECDSA,AES256,SHA,,,,),
+  CS_ENTRY(0xC00E, TLS,ECDH,RSA,WITH,AES,128,CBC,SHA),
+  CS_ENTRY(0xC00E, ECDH,RSA,AES128,SHA,,,,),
+  CS_ENTRY(0xC00F, TLS,ECDH,RSA,WITH,AES,256,CBC,SHA),
+  CS_ENTRY(0xC00F, ECDH,RSA,AES256,SHA,,,,),
+  CS_ENTRY(0xC013, TLS,ECDHE,RSA,WITH,AES,128,CBC,SHA),
+  CS_ENTRY(0xC013, ECDHE,RSA,AES128,SHA,,,,),
+  CS_ENTRY(0xC014, TLS,ECDHE,RSA,WITH,AES,256,CBC,SHA),
+  CS_ENTRY(0xC014, ECDHE,RSA,AES256,SHA,,,,),
+  CS_ENTRY(0xC023, TLS,ECDHE,ECDSA,WITH,AES,128,CBC,SHA256),
+  CS_ENTRY(0xC023, ECDHE,ECDSA,AES128,SHA256,,,,),
+  CS_ENTRY(0xC024, TLS,ECDHE,ECDSA,WITH,AES,256,CBC,SHA384),
+  CS_ENTRY(0xC024, ECDHE,ECDSA,AES256,SHA384,,,,),
+  CS_ENTRY(0xC025, TLS,ECDH,ECDSA,WITH,AES,128,CBC,SHA256),
+  CS_ENTRY(0xC025, ECDH,ECDSA,AES128,SHA256,,,,),
+  CS_ENTRY(0xC026, TLS,ECDH,ECDSA,WITH,AES,256,CBC,SHA384),
+  CS_ENTRY(0xC026, ECDH,ECDSA,AES256,SHA384,,,,),
+  CS_ENTRY(0xC027, TLS,ECDHE,RSA,WITH,AES,128,CBC,SHA256),
+  CS_ENTRY(0xC027, ECDHE,RSA,AES128,SHA256,,,,),
+  CS_ENTRY(0xC028, TLS,ECDHE,RSA,WITH,AES,256,CBC,SHA384),
+  CS_ENTRY(0xC028, ECDHE,RSA,AES256,SHA384,,,,),
+  CS_ENTRY(0xC029, TLS,ECDH,RSA,WITH,AES,128,CBC,SHA256),
+  CS_ENTRY(0xC029, ECDH,RSA,AES128,SHA256,,,,),
+  CS_ENTRY(0xC02A, TLS,ECDH,RSA,WITH,AES,256,CBC,SHA384),
+  CS_ENTRY(0xC02A, ECDH,RSA,AES256,SHA384,,,,),
+  CS_ENTRY(0xC02B, TLS,ECDHE,ECDSA,WITH,AES,128,GCM,SHA256),
+  CS_ENTRY(0xC02B, ECDHE,ECDSA,AES128,GCM,SHA256,,,),
+  CS_ENTRY(0xC02C, TLS,ECDHE,ECDSA,WITH,AES,256,GCM,SHA384),
+  CS_ENTRY(0xC02C, ECDHE,ECDSA,AES256,GCM,SHA384,,,),
+  CS_ENTRY(0xC02D, TLS,ECDH,ECDSA,WITH,AES,128,GCM,SHA256),
+  CS_ENTRY(0xC02D, ECDH,ECDSA,AES128,GCM,SHA256,,,),
+  CS_ENTRY(0xC02E, TLS,ECDH,ECDSA,WITH,AES,256,GCM,SHA384),
+  CS_ENTRY(0xC02E, ECDH,ECDSA,AES256,GCM,SHA384,,,),
+  CS_ENTRY(0xC02F, TLS,ECDHE,RSA,WITH,AES,128,GCM,SHA256),
+  CS_ENTRY(0xC02F, ECDHE,RSA,AES128,GCM,SHA256,,,),
+  CS_ENTRY(0xC030, TLS,ECDHE,RSA,WITH,AES,256,GCM,SHA384),
+  CS_ENTRY(0xC030, ECDHE,RSA,AES256,GCM,SHA384,,,),
+  CS_ENTRY(0xC031, TLS,ECDH,RSA,WITH,AES,128,GCM,SHA256),
+  CS_ENTRY(0xC031, ECDH,RSA,AES128,GCM,SHA256,,,),
+  CS_ENTRY(0xC032, TLS,ECDH,RSA,WITH,AES,256,GCM,SHA384),
+  CS_ENTRY(0xC032, ECDH,RSA,AES256,GCM,SHA384,,,),
+  CS_ENTRY(0xCCA8, TLS,ECDHE,RSA,WITH,CHACHA20,POLY1305,SHA256,),
+  CS_ENTRY(0xCCA8, ECDHE,RSA,CHACHA20,POLY1305,,,,),
+  CS_ENTRY(0xCCA9, TLS,ECDHE,ECDSA,WITH,CHACHA20,POLY1305,SHA256,),
+  CS_ENTRY(0xCCA9, ECDHE,ECDSA,CHACHA20,POLY1305,,,,),
+#if defined(USE_MBEDTLS)
+  CS_ENTRY(0x0001, TLS,RSA,WITH,NULL,MD5,,,),
+  CS_ENTRY(0x0001, NULL,MD5,,,,,,),
+  CS_ENTRY(0x0002, TLS,RSA,WITH,NULL,SHA,,,),
+  CS_ENTRY(0x0002, NULL,SHA,,,,,,),
+  CS_ENTRY(0x002C, TLS,PSK,WITH,NULL,SHA,,,),
+  CS_ENTRY(0x002C, PSK,NULL,SHA,,,,,),
+  CS_ENTRY(0x002D, TLS,DHE,PSK,WITH,NULL,SHA,,),
+  CS_ENTRY(0x002D, DHE,PSK,NULL,SHA,,,,),
+  CS_ENTRY(0x002E, TLS,RSA,PSK,WITH,NULL,SHA,,),
+  CS_ENTRY(0x002E, RSA,PSK,NULL,SHA,,,,),
+  CS_ENTRY(0x0033, TLS,DHE,RSA,WITH,AES,128,CBC,SHA),
+  CS_ENTRY(0x0033, DHE,RSA,AES128,SHA,,,,),
+  CS_ENTRY(0x0039, TLS,DHE,RSA,WITH,AES,256,CBC,SHA),
+  CS_ENTRY(0x0039, DHE,RSA,AES256,SHA,,,,),
+  CS_ENTRY(0x003B, TLS,RSA,WITH,NULL,SHA256,,,),
+  CS_ENTRY(0x003B, NULL,SHA256,,,,,,),
+  CS_ENTRY(0x0067, TLS,DHE,RSA,WITH,AES,128,CBC,SHA256),
+  CS_ENTRY(0x0067, DHE,RSA,AES128,SHA256,,,,),
+  CS_ENTRY(0x006B, TLS,DHE,RSA,WITH,AES,256,CBC,SHA256),
+  CS_ENTRY(0x006B, DHE,RSA,AES256,SHA256,,,,),
+  CS_ENTRY(0x008C, TLS,PSK,WITH,AES,128,CBC,SHA,),
+  CS_ENTRY(0x008C, PSK,AES128,CBC,SHA,,,,),
+  CS_ENTRY(0x008D, TLS,PSK,WITH,AES,256,CBC,SHA,),
+  CS_ENTRY(0x008D, PSK,AES256,CBC,SHA,,,,),
+  CS_ENTRY(0x0090, TLS,DHE,PSK,WITH,AES,128,CBC,SHA),
+  CS_ENTRY(0x0090, DHE,PSK,AES128,CBC,SHA,,,),
+  CS_ENTRY(0x0091, TLS,DHE,PSK,WITH,AES,256,CBC,SHA),
+  CS_ENTRY(0x0091, DHE,PSK,AES256,CBC,SHA,,,),
+  CS_ENTRY(0x0094, TLS,RSA,PSK,WITH,AES,128,CBC,SHA),
+  CS_ENTRY(0x0094, RSA,PSK,AES128,CBC,SHA,,,),
+  CS_ENTRY(0x0095, TLS,RSA,PSK,WITH,AES,256,CBC,SHA),
+  CS_ENTRY(0x0095, RSA,PSK,AES256,CBC,SHA,,,),
+  CS_ENTRY(0x009E, TLS,DHE,RSA,WITH,AES,128,GCM,SHA256),
+  CS_ENTRY(0x009E, DHE,RSA,AES128,GCM,SHA256,,,),
+  CS_ENTRY(0x009F, TLS,DHE,RSA,WITH,AES,256,GCM,SHA384),
+  CS_ENTRY(0x009F, DHE,RSA,AES256,GCM,SHA384,,,),
+  CS_ENTRY(0x00A8, TLS,PSK,WITH,AES,128,GCM,SHA256,),
+  CS_ENTRY(0x00A8, PSK,AES128,GCM,SHA256,,,,),
+  CS_ENTRY(0x00A9, TLS,PSK,WITH,AES,256,GCM,SHA384,),
+  CS_ENTRY(0x00A9, PSK,AES256,GCM,SHA384,,,,),
+  CS_ENTRY(0x00AA, TLS,DHE,PSK,WITH,AES,128,GCM,SHA256),
+  CS_ENTRY(0x00AA, DHE,PSK,AES128,GCM,SHA256,,,),
+  CS_ENTRY(0x00AB, TLS,DHE,PSK,WITH,AES,256,GCM,SHA384),
+  CS_ENTRY(0x00AB, DHE,PSK,AES256,GCM,SHA384,,,),
+  CS_ENTRY(0x00AC, TLS,RSA,PSK,WITH,AES,128,GCM,SHA256),
+  CS_ENTRY(0x00AC, RSA,PSK,AES128,GCM,SHA256,,,),
+  CS_ENTRY(0x00AD, TLS,RSA,PSK,WITH,AES,256,GCM,SHA384),
+  CS_ENTRY(0x00AD, RSA,PSK,AES256,GCM,SHA384,,,),
+  CS_ENTRY(0x00AE, TLS,PSK,WITH,AES,128,CBC,SHA256,),
+  CS_ENTRY(0x00AE, PSK,AES128,CBC,SHA256,,,,),
+  CS_ENTRY(0x00AF, TLS,PSK,WITH,AES,256,CBC,SHA384,),
+  CS_ENTRY(0x00AF, PSK,AES256,CBC,SHA384,,,,),
+  CS_ENTRY(0x00B0, TLS,PSK,WITH,NULL,SHA256,,,),
+  CS_ENTRY(0x00B0, PSK,NULL,SHA256,,,,,),
+  CS_ENTRY(0x00B1, TLS,PSK,WITH,NULL,SHA384,,,),
+  CS_ENTRY(0x00B1, PSK,NULL,SHA384,,,,,),
+  CS_ENTRY(0x00B2, TLS,DHE,PSK,WITH,AES,128,CBC,SHA256),
+  CS_ENTRY(0x00B2, DHE,PSK,AES128,CBC,SHA256,,,),
+  CS_ENTRY(0x00B3, TLS,DHE,PSK,WITH,AES,256,CBC,SHA384),
+  CS_ENTRY(0x00B3, DHE,PSK,AES256,CBC,SHA384,,,),
+  CS_ENTRY(0x00B4, TLS,DHE,PSK,WITH,NULL,SHA256,,),
+  CS_ENTRY(0x00B4, DHE,PSK,NULL,SHA256,,,,),
+  CS_ENTRY(0x00B5, TLS,DHE,PSK,WITH,NULL,SHA384,,),
+  CS_ENTRY(0x00B5, DHE,PSK,NULL,SHA384,,,,),
+  CS_ENTRY(0x00B6, TLS,RSA,PSK,WITH,AES,128,CBC,SHA256),
+  CS_ENTRY(0x00B6, RSA,PSK,AES128,CBC,SHA256,,,),
+  CS_ENTRY(0x00B7, TLS,RSA,PSK,WITH,AES,256,CBC,SHA384),
+  CS_ENTRY(0x00B7, RSA,PSK,AES256,CBC,SHA384,,,),
+  CS_ENTRY(0x00B8, TLS,RSA,PSK,WITH,NULL,SHA256,,),
+  CS_ENTRY(0x00B8, RSA,PSK,NULL,SHA256,,,,),
+  CS_ENTRY(0x00B9, TLS,RSA,PSK,WITH,NULL,SHA384,,),
+  CS_ENTRY(0x00B9, RSA,PSK,NULL,SHA384,,,,),
+  CS_ENTRY(0x1301, TLS,AES,128,GCM,SHA256,,,),
+  CS_ENTRY(0x1302, TLS,AES,256,GCM,SHA384,,,),
+  CS_ENTRY(0x1303, TLS,CHACHA20,POLY1305,SHA256,,,,),
+  CS_ENTRY(0x1304, TLS,AES,128,CCM,SHA256,,,),
+  CS_ENTRY(0x1305, TLS,AES,128,CCM,8,SHA256,,),
+  CS_ENTRY(0xC001, TLS,ECDH,ECDSA,WITH,NULL,SHA,,),
+  CS_ENTRY(0xC001, ECDH,ECDSA,NULL,SHA,,,,),
+  CS_ENTRY(0xC006, TLS,ECDHE,ECDSA,WITH,NULL,SHA,,),
+  CS_ENTRY(0xC006, ECDHE,ECDSA,NULL,SHA,,,,),
+  CS_ENTRY(0xC00B, TLS,ECDH,RSA,WITH,NULL,SHA,,),
+  CS_ENTRY(0xC00B, ECDH,RSA,NULL,SHA,,,,),
+  CS_ENTRY(0xC010, TLS,ECDHE,RSA,WITH,NULL,SHA,,),
+  CS_ENTRY(0xC010, ECDHE,RSA,NULL,SHA,,,,),
+  CS_ENTRY(0xC035, TLS,ECDHE,PSK,WITH,AES,128,CBC,SHA),
+  CS_ENTRY(0xC035, ECDHE,PSK,AES128,CBC,SHA,,,),
+  CS_ENTRY(0xC036, TLS,ECDHE,PSK,WITH,AES,256,CBC,SHA),
+  CS_ENTRY(0xC036, ECDHE,PSK,AES256,CBC,SHA,,,),
+  CS_ENTRY(0xCCAB, TLS,PSK,WITH,CHACHA20,POLY1305,SHA256,,),
+  CS_ENTRY(0xCCAB, PSK,CHACHA20,POLY1305,,,,,),
+#endif
+#if defined(USE_BEARSSL)
+  CS_ENTRY(0x000A, TLS,RSA,WITH,3DES,EDE,CBC,SHA,),
+  CS_ENTRY(0x000A, DES,CBC3,SHA,,,,,),
+  CS_ENTRY(0xC003, TLS,ECDH,ECDSA,WITH,3DES,EDE,CBC,SHA),
+  CS_ENTRY(0xC003, ECDH,ECDSA,DES,CBC3,SHA,,,),
+  CS_ENTRY(0xC008, TLS,ECDHE,ECDSA,WITH,3DES,EDE,CBC,SHA),
+  CS_ENTRY(0xC008, ECDHE,ECDSA,DES,CBC3,SHA,,,),
+  CS_ENTRY(0xC00D, TLS,ECDH,RSA,WITH,3DES,EDE,CBC,SHA),
+  CS_ENTRY(0xC00D, ECDH,RSA,DES,CBC3,SHA,,,),
+  CS_ENTRY(0xC012, TLS,ECDHE,RSA,WITH,3DES,EDE,CBC,SHA),
+  CS_ENTRY(0xC012, ECDHE,RSA,DES,CBC3,SHA,,,),
+#endif
+  CS_ENTRY(0xC09C, TLS,RSA,WITH,AES,128,CCM,,),
+  CS_ENTRY(0xC09C, AES128,CCM,,,,,,),
+  CS_ENTRY(0xC09D, TLS,RSA,WITH,AES,256,CCM,,),
+  CS_ENTRY(0xC09D, AES256,CCM,,,,,,),
+  CS_ENTRY(0xC0A0, TLS,RSA,WITH,AES,128,CCM,8,),
+  CS_ENTRY(0xC0A0, AES128,CCM8,,,,,,),
+  CS_ENTRY(0xC0A1, TLS,RSA,WITH,AES,256,CCM,8,),
+  CS_ENTRY(0xC0A1, AES256,CCM8,,,,,,),
+  CS_ENTRY(0xC0AC, TLS,ECDHE,ECDSA,WITH,AES,128,CCM,),
+  CS_ENTRY(0xC0AC, ECDHE,ECDSA,AES128,CCM,,,,),
+  CS_ENTRY(0xC0AD, TLS,ECDHE,ECDSA,WITH,AES,256,CCM,),
+  CS_ENTRY(0xC0AD, ECDHE,ECDSA,AES256,CCM,,,,),
+  CS_ENTRY(0xC0AE, TLS,ECDHE,ECDSA,WITH,AES,128,CCM,8),
+  CS_ENTRY(0xC0AE, ECDHE,ECDSA,AES128,CCM8,,,,),
+  CS_ENTRY(0xC0AF, TLS,ECDHE,ECDSA,WITH,AES,256,CCM,8),
+  CS_ENTRY(0xC0AF, ECDHE,ECDSA,AES256,CCM8,,,,),
+#if defined(USE_MBEDTLS)
+  /* entries marked ns are "non-standard", they are not in openssl */
+  CS_ENTRY(0x0041, TLS,RSA,WITH,CAMELLIA,128,CBC,SHA,),
+  CS_ENTRY(0x0041, CAMELLIA128,SHA,,,,,,),
+  CS_ENTRY(0x0045, TLS,DHE,RSA,WITH,CAMELLIA,128,CBC,SHA),
+  CS_ENTRY(0x0045, DHE,RSA,CAMELLIA128,SHA,,,,),
+  CS_ENTRY(0x0084, TLS,RSA,WITH,CAMELLIA,256,CBC,SHA,),
+  CS_ENTRY(0x0084, CAMELLIA256,SHA,,,,,,),
+  CS_ENTRY(0x0088, TLS,DHE,RSA,WITH,CAMELLIA,256,CBC,SHA),
+  CS_ENTRY(0x0088, DHE,RSA,CAMELLIA256,SHA,,,,),
+  CS_ENTRY(0x00BA, TLS,RSA,WITH,CAMELLIA,128,CBC,SHA256,),
+  CS_ENTRY(0x00BA, CAMELLIA128,SHA256,,,,,,),
+  CS_ENTRY(0x00BE, TLS,DHE,RSA,WITH,CAMELLIA,128,CBC,SHA256),
+  CS_ENTRY(0x00BE, DHE,RSA,CAMELLIA128,SHA256,,,,),
+  CS_ENTRY(0x00C0, TLS,RSA,WITH,CAMELLIA,256,CBC,SHA256,),
+  CS_ENTRY(0x00C0, CAMELLIA256,SHA256,,,,,,),
+  CS_ENTRY(0x00C4, TLS,DHE,RSA,WITH,CAMELLIA,256,CBC,SHA256),
+  CS_ENTRY(0x00C4, DHE,RSA,CAMELLIA256,SHA256,,,,),
+  CS_ENTRY(0xC037, TLS,ECDHE,PSK,WITH,AES,128,CBC,SHA256),
+  CS_ENTRY(0xC037, ECDHE,PSK,AES128,CBC,SHA256,,,),
+  CS_ENTRY(0xC038, TLS,ECDHE,PSK,WITH,AES,256,CBC,SHA384),
+  CS_ENTRY(0xC038, ECDHE,PSK,AES256,CBC,SHA384,,,),
+  CS_ENTRY(0xC039, TLS,ECDHE,PSK,WITH,NULL,SHA,,),
+  CS_ENTRY(0xC039, ECDHE,PSK,NULL,SHA,,,,),
+  CS_ENTRY(0xC03A, TLS,ECDHE,PSK,WITH,NULL,SHA256,,),
+  CS_ENTRY(0xC03A, ECDHE,PSK,NULL,SHA256,,,,),
+  CS_ENTRY(0xC03B, TLS,ECDHE,PSK,WITH,NULL,SHA384,,),
+  CS_ENTRY(0xC03B, ECDHE,PSK,NULL,SHA384,,,,),
+  CS_ENTRY(0xC03C, TLS,RSA,WITH,ARIA,128,CBC,SHA256,),
+  CS_ENTRY(0xC03C, ARIA128,SHA256,,,,,,), /* ns */
+  CS_ENTRY(0xC03D, TLS,RSA,WITH,ARIA,256,CBC,SHA384,),
+  CS_ENTRY(0xC03D, ARIA256,SHA384,,,,,,), /* ns */
+  CS_ENTRY(0xC044, TLS,DHE,RSA,WITH,ARIA,128,CBC,SHA256),
+  CS_ENTRY(0xC044, DHE,RSA,ARIA128,SHA256,,,,), /* ns */
+  CS_ENTRY(0xC045, TLS,DHE,RSA,WITH,ARIA,256,CBC,SHA384),
+  CS_ENTRY(0xC045, DHE,RSA,ARIA256,SHA384,,,,), /* ns */
+  CS_ENTRY(0xC048, TLS,ECDHE,ECDSA,WITH,ARIA,128,CBC,SHA256),
+  CS_ENTRY(0xC048, ECDHE,ECDSA,ARIA128,SHA256,,,,), /* ns */
+  CS_ENTRY(0xC049, TLS,ECDHE,ECDSA,WITH,ARIA,256,CBC,SHA384),
+  CS_ENTRY(0xC049, ECDHE,ECDSA,ARIA256,SHA384,,,,), /* ns */
+  CS_ENTRY(0xC04A, TLS,ECDH,ECDSA,WITH,ARIA,128,CBC,SHA256),
+  CS_ENTRY(0xC04A, ECDH,ECDSA,ARIA128,SHA256,,,,), /* ns */
+  CS_ENTRY(0xC04B, TLS,ECDH,ECDSA,WITH,ARIA,256,CBC,SHA384),
+  CS_ENTRY(0xC04B, ECDH,ECDSA,ARIA256,SHA384,,,,), /* ns */
+  CS_ENTRY(0xC04C, TLS,ECDHE,RSA,WITH,ARIA,128,CBC,SHA256),
+  CS_ENTRY(0xC04C, ECDHE,ARIA128,SHA256,,,,,), /* ns */
+  CS_ENTRY(0xC04D, TLS,ECDHE,RSA,WITH,ARIA,256,CBC,SHA384),
+  CS_ENTRY(0xC04D, ECDHE,ARIA256,SHA384,,,,,), /* ns */
+  CS_ENTRY(0xC04E, TLS,ECDH,RSA,WITH,ARIA,128,CBC,SHA256),
+  CS_ENTRY(0xC04E, ECDH,ARIA128,SHA256,,,,,), /* ns */
+  CS_ENTRY(0xC04F, TLS,ECDH,RSA,WITH,ARIA,256,CBC,SHA384),
+  CS_ENTRY(0xC04F, ECDH,ARIA256,SHA384,,,,,), /* ns */
+  CS_ENTRY(0xC050, TLS,RSA,WITH,ARIA,128,GCM,SHA256,),
+  CS_ENTRY(0xC050, ARIA128,GCM,SHA256,,,,,),
+  CS_ENTRY(0xC051, TLS,RSA,WITH,ARIA,256,GCM,SHA384,),
+  CS_ENTRY(0xC051, ARIA256,GCM,SHA384,,,,,),
+  CS_ENTRY(0xC052, TLS,DHE,RSA,WITH,ARIA,128,GCM,SHA256),
+  CS_ENTRY(0xC052, DHE,RSA,ARIA128,GCM,SHA256,,,),
+  CS_ENTRY(0xC053, TLS,DHE,RSA,WITH,ARIA,256,GCM,SHA384),
+  CS_ENTRY(0xC053, DHE,RSA,ARIA256,GCM,SHA384,,,),
+  CS_ENTRY(0xC05C, TLS,ECDHE,ECDSA,WITH,ARIA,128,GCM,SHA256),
+  CS_ENTRY(0xC05C, ECDHE,ECDSA,ARIA128,GCM,SHA256,,,),
+  CS_ENTRY(0xC05D, TLS,ECDHE,ECDSA,WITH,ARIA,256,GCM,SHA384),
+  CS_ENTRY(0xC05D, ECDHE,ECDSA,ARIA256,GCM,SHA384,,,),
+  CS_ENTRY(0xC05E, TLS,ECDH,ECDSA,WITH,ARIA,128,GCM,SHA256),
+  CS_ENTRY(0xC05E, ECDH,ECDSA,ARIA128,GCM,SHA256,,,), /* ns */
+  CS_ENTRY(0xC05F, TLS,ECDH,ECDSA,WITH,ARIA,256,GCM,SHA384),
+  CS_ENTRY(0xC05F, ECDH,ECDSA,ARIA256,GCM,SHA384,,,), /* ns */
+  CS_ENTRY(0xC060, TLS,ECDHE,RSA,WITH,ARIA,128,GCM,SHA256),
+  CS_ENTRY(0xC060, ECDHE,ARIA128,GCM,SHA256,,,,),
+  CS_ENTRY(0xC061, TLS,ECDHE,RSA,WITH,ARIA,256,GCM,SHA384),
+  CS_ENTRY(0xC061, ECDHE,ARIA256,GCM,SHA384,,,,),
+  CS_ENTRY(0xC062, TLS,ECDH,RSA,WITH,ARIA,128,GCM,SHA256),
+  CS_ENTRY(0xC062, ECDH,ARIA128,GCM,SHA256,,,,), /* ns */
+  CS_ENTRY(0xC063, TLS,ECDH,RSA,WITH,ARIA,256,GCM,SHA384),
+  CS_ENTRY(0xC063, ECDH,ARIA256,GCM,SHA384,,,,), /* ns */
+  CS_ENTRY(0xC064, TLS,PSK,WITH,ARIA,128,CBC,SHA256,),
+  CS_ENTRY(0xC064, PSK,ARIA128,SHA256,,,,,), /* ns */
+  CS_ENTRY(0xC065, TLS,PSK,WITH,ARIA,256,CBC,SHA384,),
+  CS_ENTRY(0xC065, PSK,ARIA256,SHA384,,,,,), /* ns */
+  CS_ENTRY(0xC066, TLS,DHE,PSK,WITH,ARIA,128,CBC,SHA256),
+  CS_ENTRY(0xC066, DHE,PSK,ARIA128,SHA256,,,,), /* ns */
+  CS_ENTRY(0xC067, TLS,DHE,PSK,WITH,ARIA,256,CBC,SHA384),
+  CS_ENTRY(0xC067, DHE,PSK,ARIA256,SHA384,,,,), /* ns */
+  CS_ENTRY(0xC068, TLS,RSA,PSK,WITH,ARIA,128,CBC,SHA256),
+  CS_ENTRY(0xC068, RSA,PSK,ARIA128,SHA256,,,,), /* ns */
+  CS_ENTRY(0xC069, TLS,RSA,PSK,WITH,ARIA,256,CBC,SHA384),
+  CS_ENTRY(0xC069, RSA,PSK,ARIA256,SHA384,,,,), /* ns */
+  CS_ENTRY(0xC06A, TLS,PSK,WITH,ARIA,128,GCM,SHA256,),
+  CS_ENTRY(0xC06A, PSK,ARIA128,GCM,SHA256,,,,),
+  CS_ENTRY(0xC06B, TLS,PSK,WITH,ARIA,256,GCM,SHA384,),
+  CS_ENTRY(0xC06B, PSK,ARIA256,GCM,SHA384,,,,),
+  CS_ENTRY(0xC06C, TLS,DHE,PSK,WITH,ARIA,128,GCM,SHA256),
+  CS_ENTRY(0xC06C, DHE,PSK,ARIA128,GCM,SHA256,,,),
+  CS_ENTRY(0xC06D, TLS,DHE,PSK,WITH,ARIA,256,GCM,SHA384),
+  CS_ENTRY(0xC06D, DHE,PSK,ARIA256,GCM,SHA384,,,),
+  CS_ENTRY(0xC06E, TLS,RSA,PSK,WITH,ARIA,128,GCM,SHA256),
+  CS_ENTRY(0xC06E, RSA,PSK,ARIA128,GCM,SHA256,,,),
+  CS_ENTRY(0xC06F, TLS,RSA,PSK,WITH,ARIA,256,GCM,SHA384),
+  CS_ENTRY(0xC06F, RSA,PSK,ARIA256,GCM,SHA384,,,),
+  CS_ENTRY(0xC070, TLS,ECDHE,PSK,WITH,ARIA,128,CBC,SHA256),
+  CS_ENTRY(0xC070, ECDHE,PSK,ARIA128,SHA256,,,,), /* ns */
+  CS_ENTRY(0xC071, TLS,ECDHE,PSK,WITH,ARIA,256,CBC,SHA384),
+  CS_ENTRY(0xC071, ECDHE,PSK,ARIA256,SHA384,,,,), /* ns */
+  CS_ENTRY(0xC072, TLS,ECDHE,ECDSA,WITH,CAMELLIA,128,CBC,SHA256),
+  CS_ENTRY(0xC072, ECDHE,ECDSA,CAMELLIA128,SHA256,,,,),
+  CS_ENTRY(0xC073, TLS,ECDHE,ECDSA,WITH,CAMELLIA,256,CBC,SHA384),
+  CS_ENTRY(0xC073, ECDHE,ECDSA,CAMELLIA256,SHA384,,,,),
+  CS_ENTRY(0xC074, TLS,ECDH,ECDSA,WITH,CAMELLIA,128,CBC,SHA256),
+  CS_ENTRY(0xC074, ECDH,ECDSA,CAMELLIA128,SHA256,,,,), /* ns */
+  CS_ENTRY(0xC075, TLS,ECDH,ECDSA,WITH,CAMELLIA,256,CBC,SHA384),
+  CS_ENTRY(0xC075, ECDH,ECDSA,CAMELLIA256,SHA384,,,,), /* ns */
+  CS_ENTRY(0xC076, TLS,ECDHE,RSA,WITH,CAMELLIA,128,CBC,SHA256),
+  CS_ENTRY(0xC076, ECDHE,RSA,CAMELLIA128,SHA256,,,,),
+  CS_ENTRY(0xC077, TLS,ECDHE,RSA,WITH,CAMELLIA,256,CBC,SHA384),
+  CS_ENTRY(0xC077, ECDHE,RSA,CAMELLIA256,SHA384,,,,),
+  CS_ENTRY(0xC078, TLS,ECDH,RSA,WITH,CAMELLIA,128,CBC,SHA256),
+  CS_ENTRY(0xC078, ECDH,CAMELLIA128,SHA256,,,,,), /* ns */
+  CS_ENTRY(0xC079, TLS,ECDH,RSA,WITH,CAMELLIA,256,CBC,SHA384),
+  CS_ENTRY(0xC079, ECDH,CAMELLIA256,SHA384,,,,,), /* ns */
+  CS_ENTRY(0xC07A, TLS,RSA,WITH,CAMELLIA,128,GCM,SHA256,),
+  CS_ENTRY(0xC07A, CAMELLIA128,GCM,SHA256,,,,,), /* ns */
+  CS_ENTRY(0xC07B, TLS,RSA,WITH,CAMELLIA,256,GCM,SHA384,),
+  CS_ENTRY(0xC07B, CAMELLIA256,GCM,SHA384,,,,,), /* ns */
+  CS_ENTRY(0xC07C, TLS,DHE,RSA,WITH,CAMELLIA,128,GCM,SHA256),
+  CS_ENTRY(0xC07C, DHE,RSA,CAMELLIA128,GCM,SHA256,,,), /* ns */
+  CS_ENTRY(0xC07D, TLS,DHE,RSA,WITH,CAMELLIA,256,GCM,SHA384),
+  CS_ENTRY(0xC07D, DHE,RSA,CAMELLIA256,GCM,SHA384,,,), /* ns */
+  CS_ENTRY(0xC086, TLS,ECDHE,ECDSA,WITH,CAMELLIA,128,GCM,SHA256),
+  CS_ENTRY(0xC086, ECDHE,ECDSA,CAMELLIA128,GCM,SHA256,,,), /* ns */
+  CS_ENTRY(0xC087, TLS,ECDHE,ECDSA,WITH,CAMELLIA,256,GCM,SHA384),
+  CS_ENTRY(0xC087, ECDHE,ECDSA,CAMELLIA256,GCM,SHA384,,,), /* ns */
+  CS_ENTRY(0xC088, TLS,ECDH,ECDSA,WITH,CAMELLIA,128,GCM,SHA256),
+  CS_ENTRY(0xC088, ECDH,ECDSA,CAMELLIA128,GCM,SHA256,,,), /* ns */
+  CS_ENTRY(0xC089, TLS,ECDH,ECDSA,WITH,CAMELLIA,256,GCM,SHA384),
+  CS_ENTRY(0xC089, ECDH,ECDSA,CAMELLIA256,GCM,SHA384,,,), /* ns */
+  CS_ENTRY(0xC08A, TLS,ECDHE,RSA,WITH,CAMELLIA,128,GCM,SHA256),
+  CS_ENTRY(0xC08A, ECDHE,CAMELLIA128,GCM,SHA256,,,,), /* ns */
+  CS_ENTRY(0xC08B, TLS,ECDHE,RSA,WITH,CAMELLIA,256,GCM,SHA384),
+  CS_ENTRY(0xC08B, ECDHE,CAMELLIA256,GCM,SHA384,,,,), /* ns */
+  CS_ENTRY(0xC08C, TLS,ECDH,RSA,WITH,CAMELLIA,128,GCM,SHA256),
+  CS_ENTRY(0xC08C, ECDH,CAMELLIA128,GCM,SHA256,,,,), /* ns */
+  CS_ENTRY(0xC08D, TLS,ECDH,RSA,WITH,CAMELLIA,256,GCM,SHA384),
+  CS_ENTRY(0xC08D, ECDH,CAMELLIA256,GCM,SHA384,,,,), /* ns */
+  CS_ENTRY(0xC08E, TLS,PSK,WITH,CAMELLIA,128,GCM,SHA256,),
+  CS_ENTRY(0xC08E, PSK,CAMELLIA128,GCM,SHA256,,,,), /* ns */
+  CS_ENTRY(0xC08F, TLS,PSK,WITH,CAMELLIA,256,GCM,SHA384,),
+  CS_ENTRY(0xC08F, PSK,CAMELLIA256,GCM,SHA384,,,,), /* ns */
+  CS_ENTRY(0xC090, TLS,DHE,PSK,WITH,CAMELLIA,128,GCM,SHA256),
+  CS_ENTRY(0xC090, DHE,PSK,CAMELLIA128,GCM,SHA256,,,), /* ns */
+  CS_ENTRY(0xC091, TLS,DHE,PSK,WITH,CAMELLIA,256,GCM,SHA384),
+  CS_ENTRY(0xC091, DHE,PSK,CAMELLIA256,GCM,SHA384,,,), /* ns */
+  CS_ENTRY(0xC092, TLS,RSA,PSK,WITH,CAMELLIA,128,GCM,SHA256),
+  CS_ENTRY(0xC092, RSA,PSK,CAMELLIA128,GCM,SHA256,,,), /* ns */
+  CS_ENTRY(0xC093, TLS,RSA,PSK,WITH,CAMELLIA,256,GCM,SHA384),
+  CS_ENTRY(0xC093, RSA,PSK,CAMELLIA256,GCM,SHA384,,,), /* ns */
+  CS_ENTRY(0xC094, TLS,PSK,WITH,CAMELLIA,128,CBC,SHA256,),
+  CS_ENTRY(0xC094, PSK,CAMELLIA128,SHA256,,,,,),
+  CS_ENTRY(0xC095, TLS,PSK,WITH,CAMELLIA,256,CBC,SHA384,),
+  CS_ENTRY(0xC095, PSK,CAMELLIA256,SHA384,,,,,),
+  CS_ENTRY(0xC096, TLS,DHE,PSK,WITH,CAMELLIA,128,CBC,SHA256),
+  CS_ENTRY(0xC096, DHE,PSK,CAMELLIA128,SHA256,,,,),
+  CS_ENTRY(0xC097, TLS,DHE,PSK,WITH,CAMELLIA,256,CBC,SHA384),
+  CS_ENTRY(0xC097, DHE,PSK,CAMELLIA256,SHA384,,,,),
+  CS_ENTRY(0xC098, TLS,RSA,PSK,WITH,CAMELLIA,128,CBC,SHA256),
+  CS_ENTRY(0xC098, RSA,PSK,CAMELLIA128,SHA256,,,,),
+  CS_ENTRY(0xC099, TLS,RSA,PSK,WITH,CAMELLIA,256,CBC,SHA384),
+  CS_ENTRY(0xC099, RSA,PSK,CAMELLIA256,SHA384,,,,),
+  CS_ENTRY(0xC09A, TLS,ECDHE,PSK,WITH,CAMELLIA,128,CBC,SHA256),
+  CS_ENTRY(0xC09A, ECDHE,PSK,CAMELLIA128,SHA256,,,,),
+  CS_ENTRY(0xC09B, TLS,ECDHE,PSK,WITH,CAMELLIA,256,CBC,SHA384),
+  CS_ENTRY(0xC09B, ECDHE,PSK,CAMELLIA256,SHA384,,,,),
+  CS_ENTRY(0xC09E, TLS,DHE,RSA,WITH,AES,128,CCM,),
+  CS_ENTRY(0xC09E, DHE,RSA,AES128,CCM,,,,),
+  CS_ENTRY(0xC09F, TLS,DHE,RSA,WITH,AES,256,CCM,),
+  CS_ENTRY(0xC09F, DHE,RSA,AES256,CCM,,,,),
+  CS_ENTRY(0xC0A2, TLS,DHE,RSA,WITH,AES,128,CCM,8),
+  CS_ENTRY(0xC0A2, DHE,RSA,AES128,CCM8,,,,),
+  CS_ENTRY(0xC0A3, TLS,DHE,RSA,WITH,AES,256,CCM,8),
+  CS_ENTRY(0xC0A3, DHE,RSA,AES256,CCM8,,,,),
+  CS_ENTRY(0xC0A4, TLS,PSK,WITH,AES,128,CCM,,),
+  CS_ENTRY(0xC0A4, PSK,AES128,CCM,,,,,),
+  CS_ENTRY(0xC0A5, TLS,PSK,WITH,AES,256,CCM,,),
+  CS_ENTRY(0xC0A5, PSK,AES256,CCM,,,,,),
+  CS_ENTRY(0xC0A6, TLS,DHE,PSK,WITH,AES,128,CCM,),
+  CS_ENTRY(0xC0A6, DHE,PSK,AES128,CCM,,,,),
+  CS_ENTRY(0xC0A7, TLS,DHE,PSK,WITH,AES,256,CCM,),
+  CS_ENTRY(0xC0A7, DHE,PSK,AES256,CCM,,,,),
+  CS_ENTRY(0xC0A8, TLS,PSK,WITH,AES,128,CCM,8,),
+  CS_ENTRY(0xC0A8, PSK,AES128,CCM8,,,,,),
+  CS_ENTRY(0xC0A9, TLS,PSK,WITH,AES,256,CCM,8,),
+  CS_ENTRY(0xC0A9, PSK,AES256,CCM8,,,,,),
+  CS_ENTRY(0xC0AA, TLS,PSK,DHE,WITH,AES,128,CCM,8),
+  CS_ENTRY(0xC0AA, DHE,PSK,AES128,CCM8,,,,),
+  CS_ENTRY(0xC0AB, TLS,PSK,DHE,WITH,AES,256,CCM,8),
+  CS_ENTRY(0xC0AB, DHE,PSK,AES256,CCM8,,,,),
+  CS_ENTRY(0xCCAA, TLS,DHE,RSA,WITH,CHACHA20,POLY1305,SHA256,),
+  CS_ENTRY(0xCCAA, DHE,RSA,CHACHA20,POLY1305,,,,),
+  CS_ENTRY(0xCCAC, TLS,ECDHE,PSK,WITH,CHACHA20,POLY1305,SHA256,),
+  CS_ENTRY(0xCCAC, ECDHE,PSK,CHACHA20,POLY1305,,,,),
+  CS_ENTRY(0xCCAD, TLS,DHE,PSK,WITH,CHACHA20,POLY1305,SHA256,),
+  CS_ENTRY(0xCCAD, DHE,PSK,CHACHA20,POLY1305,,,,),
+  CS_ENTRY(0xCCAE, TLS,RSA,PSK,WITH,CHACHA20,POLY1305,SHA256,),
+  CS_ENTRY(0xCCAE, RSA,PSK,CHACHA20,POLY1305,,,,),
+#endif
+};
+#define CS_LIST_LEN (sizeof(cs_list) / sizeof(cs_list[0]))
+
+static int cs_str_to_zip(const char *cs_str, size_t cs_len,
+                         uint8_t zip[6])
+{
+  uint8_t indexes[8] = {0};
+  const char *entry, *cur;
+  const char *nxt = cs_str;
+  const char *end = cs_str + cs_len;
+  char separator = '-';
+  int idx, i = 0;
+  size_t len;
+
+  /* split the cipher string by '-' or '_' */
+  if(strncasecompare(cs_str, "TLS", 3))
+    separator = '_';
+
+  do {
+    if(i == 8)
+      return -1;
+
+    /* determine the length of the part */
+    cur = nxt;
+    for(; nxt < end && *nxt != '\0' && *nxt != separator; nxt++);
+    len = nxt - cur;
+
+    /* lookup index for the part (skip empty string at 0) */
+    for(idx = 1, entry = cs_txt + 1; idx < CS_TXT_LEN; idx++) {
+      size_t elen = strlen(entry);
+      if(elen == len && strncasecompare(entry, cur, len))
+        break;
+      entry += elen + 1;
+    }
+    if(idx == CS_TXT_LEN)
+      return -1;
+
+    indexes[i++] = (uint8_t) idx;
+  } while(nxt < end && *(nxt++) != '\0');
+
+  /* zip the 8 indexes into 48 bits */
+  zip[0] = (uint8_t) (indexes[0] << 2 | (indexes[1] & 0x3F) >> 4);
+  zip[1] = (uint8_t) (indexes[1] << 4 | (indexes[2] & 0x3F) >> 2);
+  zip[2] = (uint8_t) (indexes[2] << 6 | (indexes[3] & 0x3F));
+  zip[3] = (uint8_t) (indexes[4] << 2 | (indexes[5] & 0x3F) >> 4);
+  zip[4] = (uint8_t) (indexes[5] << 4 | (indexes[6] & 0x3F) >> 2);
+  zip[5] = (uint8_t) (indexes[6] << 6 | (indexes[7] & 0x3F));
+
+  return 0;
+}
+
+static int cs_zip_to_str(const uint8_t zip[6],
+                         char *buf, size_t buf_size)
+{
+  uint8_t indexes[8] = {0};
+  const char *entry;
+  char separator = '-';
+  int idx, i, r;
+  size_t len = 0;
+
+  /* unzip the 8 indexes */
+  indexes[0] = zip[0] >> 2;
+  indexes[1] = ((zip[0] << 4) & 0x3F) | zip[1] >> 4;
+  indexes[2] = ((zip[1] << 2) & 0x3F) | zip[2] >> 6;
+  indexes[3] = ((zip[2] << 0) & 0x3F);
+  indexes[4] = zip[3] >> 2;
+  indexes[5] = ((zip[3] << 4) & 0x3F) | zip[4] >> 4;
+  indexes[6] = ((zip[4] << 2) & 0x3F) | zip[5] >> 6;
+  indexes[7] = ((zip[5] << 0) & 0x3F);
+
+  if(indexes[0] == CS_TXT_IDX_TLS)
+    separator = '_';
+
+  for(i = 0; i < 8 && indexes[i] != 0 && len < buf_size; i++) {
+    if(indexes[i] >= CS_TXT_LEN)
+      return -1;
+
+    /* lookup the part string for the index (skip empty string at 0) */
+    for(idx = 1, entry = cs_txt + 1; idx < indexes[i]; idx++) {
+      size_t elen = strlen(entry);
+      entry += elen + 1;
+    }
+
+    /* append the part string to the buffer */
+    if(i > 0)
+      r = msnprintf(&buf[len], buf_size - len, "%c%s", separator, entry);
+    else
+      r = msnprintf(&buf[len], buf_size - len, "%s", entry);
+
+    if(r < 0)
+      return -1;
+    len += r;
+  }
+
+  return 0;
+}
+
+uint16_t Curl_cipher_suite_lookup_id(const char *cs_str, size_t cs_len)
+{
+  size_t i;
+  uint8_t zip[6];
+
+  if(cs_len > 0 && cs_str_to_zip(cs_str, cs_len, zip) == 0) {
+    for(i = 0; i < CS_LIST_LEN; i++) {
+      if(memcmp(cs_list[i].zip, zip, sizeof(zip)) == 0)
+        return cs_list[i].id;
+    }
+  }
+
+  return 0;
+}
+
+static bool cs_is_separator(char c)
+{
+  switch(c) {
+    case ' ':
+    case '\t':
+    case ':':
+    case ',':
+    case ';':
+      return true;
+    default:;
+  }
+  return false;
+}
+
+uint16_t Curl_cipher_suite_walk_str(const char **str, const char **end)
+{
+  /* move string pointer to first non-separator or end of string */
+  for(; cs_is_separator(*str[0]); (*str)++);
+
+  /* move end pointer to next separator or end of string */
+  for(*end = *str; *end[0] != '\0' && !cs_is_separator(*end[0]); (*end)++);
+
+  return Curl_cipher_suite_lookup_id(*str, *end - *str);
+}
+
+int Curl_cipher_suite_get_str(uint16_t id, char *buf, size_t buf_size,
+                              bool prefer_rfc)
+{
+  size_t i, j = CS_LIST_LEN;
+  int r = -1;
+
+  for(i = 0; i < CS_LIST_LEN; i++) {
+    if(cs_list[i].id != id)
+      continue;
+    if((cs_list[i].zip[0] >> 2 != CS_TXT_IDX_TLS) == !prefer_rfc) {
+      j = i;
+      break;
+    }
+    if(j == CS_LIST_LEN)
+      j = i;
+  }
+
+  if(j < CS_LIST_LEN)
+    r = cs_zip_to_str(cs_list[j].zip, buf, buf_size);
+
+  if(r < 0)
+    msnprintf(buf, buf_size, "TLS_UNKNOWN_0x%04x", id);
+
+  return r;
+}
+
+#endif /* defined(USE_MBEDTLS) || defined(USE_BEARSSL) */
diff --git a/vendor/curl/lib/vtls/cipher_suite.h b/vendor/curl/lib/vtls/cipher_suite.h
new file mode 100644
index 0000000000..c1399794fe
--- /dev/null
+++ b/vendor/curl/lib/vtls/cipher_suite.h
@@ -0,0 +1,46 @@
+#ifndef HEADER_CURL_CIPHER_SUITE_H
+#define HEADER_CURL_CIPHER_SUITE_H
+/***************************************************************************
+ *                                  _   _ ____  _
+ *  Project                     ___| | | |  _ \| |
+ *                             / __| | | | |_) | |
+ *                            | (__| |_| |  _ <| |___
+ *                             \___|\___/|_| \_\_____|
+ *
+ * Copyright (C) Jan Venekamp, 
+ *
+ * This software is licensed as described in the file COPYING, which
+ * you should have received as part of this distribution. The terms
+ * are also available at https://curl.se/docs/copyright.html.
+ *
+ * You may opt to use, copy, modify, merge, publish, distribute and/or sell
+ * copies of the Software, and permit persons to whom the Software is
+ * furnished to do so, under the terms of the COPYING file.
+ *
+ * This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY
+ * KIND, either express or implied.
+ *
+ * SPDX-License-Identifier: curl
+ *
+ ***************************************************************************/
+
+#include "curl_setup.h"
+
+#if defined(USE_MBEDTLS) || defined(USE_BEARSSL)
+#include 
+
+/* Lookup IANA id for cipher suite string, returns 0 if not recognized */
+uint16_t Curl_cipher_suite_lookup_id(const char *cs_str, size_t cs_len);
+
+/* Walk over cipher suite string, update str and end pointers to next
+   cipher suite in string, returns IANA id of that suite if recognized */
+uint16_t Curl_cipher_suite_walk_str(const char **str, const char **end);
+
+/* Copy openssl or RFC name for cipher suite in supplied buffer.
+   Caller is responsible to supply sufficiently large buffer (size
+   of 64 should suffice), excess bytes are silently truncated. */
+int Curl_cipher_suite_get_str(uint16_t id, char *buf, size_t buf_size,
+                              bool prefer_rfc);
+
+#endif /* defined(USE_MBEDTLS) || defined(USE_BEARSSL) */
+#endif /* HEADER_CURL_CIPHER_SUITE_H */
diff --git a/vendor/curl/lib/vtls/gtls.c b/vendor/curl/lib/vtls/gtls.c
index e48346903c..5cf3bf9527 100644
--- a/vendor/curl/lib/vtls/gtls.c
+++ b/vendor/curl/lib/vtls/gtls.c
@@ -43,6 +43,7 @@
 #include "urldata.h"
 #include "sendf.h"
 #include "inet_pton.h"
+#include "keylog.h"
 #include "gtls.h"
 #include "vtls.h"
 #include "vtls_int.h"
@@ -59,6 +60,16 @@
 /* The last #include file should be: */
 #include "memdebug.h"
 
+#ifndef ARRAYSIZE
+#define ARRAYSIZE(A) (sizeof(A)/sizeof((A)[0]))
+#endif
+
+#define QUIC_PRIORITY \
+  "NORMAL:-VERS-ALL:+VERS-TLS1.3:-CIPHER-ALL:+AES-128-GCM:+AES-256-GCM:" \
+  "+CHACHA20-POLY1305:+AES-128-CCM:-GROUP-ALL:+GROUP-SECP256R1:" \
+  "+GROUP-X25519:+GROUP-SECP384R1:+GROUP-SECP521R1:" \
+  "%DISABLE_TLS13_COMPAT_MODE"
+
 /* Enable GnuTLS debugging by defining GTLSDEBUG */
 /*#define GTLSDEBUG */
 
@@ -77,22 +88,25 @@ static bool gtls_inited = FALSE;
 # include 
 
 struct gtls_ssl_backend_data {
-  struct gtls_instance gtls;
+  struct gtls_ctx gtls;
 };
 
 static ssize_t gtls_push(void *s, const void *buf, size_t blen)
 {
   struct Curl_cfilter *cf = s;
   struct ssl_connect_data *connssl = cf->ctx;
+  struct gtls_ssl_backend_data *backend =
+    (struct gtls_ssl_backend_data *)connssl->backend;
   struct Curl_easy *data = CF_DATA_CURRENT(cf);
   ssize_t nwritten;
   CURLcode result;
 
   DEBUGASSERT(data);
   nwritten = Curl_conn_cf_send(cf->next, data, buf, blen, &result);
+  CURL_TRC_CF(data, cf, "gtls_push(len=%zu) -> %zd, err=%d",
+              blen, nwritten, result);
+  backend->gtls.io_result = result;
   if(nwritten < 0) {
-    struct gtls_ssl_backend_data *backend =
-      (struct gtls_ssl_backend_data *)connssl->backend;
     gnutls_transport_set_errno(backend->gtls.session,
                                (CURLE_AGAIN == result)? EAGAIN : EINVAL);
     nwritten = -1;
@@ -104,19 +118,33 @@ static ssize_t gtls_pull(void *s, void *buf, size_t blen)
 {
   struct Curl_cfilter *cf = s;
   struct ssl_connect_data *connssl = cf->ctx;
+  struct gtls_ssl_backend_data *backend =
+    (struct gtls_ssl_backend_data *)connssl->backend;
   struct Curl_easy *data = CF_DATA_CURRENT(cf);
   ssize_t nread;
   CURLcode result;
 
   DEBUGASSERT(data);
+  if(!backend->gtls.trust_setup) {
+    result = Curl_gtls_client_trust_setup(cf, data, &backend->gtls);
+    if(result) {
+      gnutls_transport_set_errno(backend->gtls.session, EINVAL);
+      backend->gtls.io_result = result;
+      return -1;
+    }
+  }
+
   nread = Curl_conn_cf_recv(cf->next, data, buf, blen, &result);
+  CURL_TRC_CF(data, cf, "glts_pull(len=%zu) -> %zd, err=%d",
+              blen, nread, result);
+  backend->gtls.io_result = result;
   if(nread < 0) {
-    struct gtls_ssl_backend_data *backend =
-      (struct gtls_ssl_backend_data *)connssl->backend;
     gnutls_transport_set_errno(backend->gtls.session,
                                (CURLE_AGAIN == result)? EAGAIN : EINVAL);
     nread = -1;
   }
+  else if(nread == 0)
+    connssl->peer_closed = TRUE;
   return nread;
 }
 
@@ -266,8 +294,17 @@ static CURLcode handshake(struct Curl_cfilter *cf,
       /* socket is readable or writable */
     }
 
+    backend->gtls.io_result = CURLE_OK;
     rc = gnutls_handshake(session);
 
+    if(!backend->gtls.trust_setup) {
+      /* After having send off the ClientHello, we prepare the trust
+       * store to verify the coming certificate from the server */
+      CURLcode result = Curl_gtls_client_trust_setup(cf, data, &backend->gtls);
+      if(result)
+        return result;
+    }
+
     if((rc == GNUTLS_E_AGAIN) || (rc == GNUTLS_E_INTERRUPTED)) {
       connssl->connecting_state =
         gnutls_record_get_direction(session)?
@@ -288,6 +325,9 @@ static CURLcode handshake(struct Curl_cfilter *cf,
       infof(data, "gnutls_handshake() warning: %s", strerr);
       continue;
     }
+    else if((rc < 0) && backend->gtls.io_result) {
+      return backend->gtls.io_result;
+    }
     else if(rc < 0) {
       const char *strerr = NULL;
 
@@ -328,6 +368,7 @@ static gnutls_x509_crt_fmt_t do_file_type(const char *type)
 
 static CURLcode
 set_ssl_version_min_max(struct Curl_easy *data,
+                        struct ssl_peer *peer,
                         struct ssl_primary_config *conn_config,
                         const char **prioritylist,
                         const char *tls13support)
@@ -335,6 +376,16 @@ set_ssl_version_min_max(struct Curl_easy *data,
   long ssl_version = conn_config->version;
   long ssl_version_max = conn_config->version_max;
 
+  if(peer->transport == TRNSPRT_QUIC) {
+    if((ssl_version != CURL_SSLVERSION_DEFAULT) &&
+       (ssl_version < CURL_SSLVERSION_TLSv1_3)) {
+      failf(data, "QUIC needs at least TLS version 1.3");
+      return CURLE_SSL_CONNECT_ERROR;
+     }
+    *prioritylist = QUIC_PRIORITY;
+    return CURLE_OK;
+  }
+
   if((ssl_version == CURL_SSLVERSION_DEFAULT) ||
      (ssl_version == CURL_SSLVERSION_TLSv1))
     ssl_version = CURL_SSLVERSION_TLSv1_0;
@@ -399,21 +450,180 @@ set_ssl_version_min_max(struct Curl_easy *data,
   return CURLE_SSL_CONNECT_ERROR;
 }
 
-CURLcode gtls_client_init(struct Curl_easy *data,
-                          struct ssl_primary_config *config,
-                          struct ssl_config_data *ssl_config,
-                          const char *hostname,
-                          struct gtls_instance *gtls,
-                          long *pverifyresult)
+CURLcode Curl_gtls_client_trust_setup(struct Curl_cfilter *cf,
+                                      struct Curl_easy *data,
+                                      struct gtls_ctx *gtls)
+{
+  struct ssl_primary_config *config = Curl_ssl_cf_get_primary_config(cf);
+  struct ssl_config_data *ssl_config = Curl_ssl_cf_get_config(cf, data);
+  int rc;
+
+  CURL_TRC_CF(data, cf, "setup trust anchors and CRLs");
+  if(config->verifypeer) {
+    bool imported_native_ca = false;
+
+    if(ssl_config->native_ca_store) {
+      rc = gnutls_certificate_set_x509_system_trust(gtls->cred);
+      if(rc < 0)
+        infof(data, "error reading native ca store (%s), continuing anyway",
+              gnutls_strerror(rc));
+      else {
+        infof(data, "found %d certificates in native ca store", rc);
+        if(rc > 0)
+          imported_native_ca = true;
+      }
+    }
+
+    if(config->CAfile) {
+      /* set the trusted CA cert bundle file */
+      gnutls_certificate_set_verify_flags(gtls->cred,
+                                          GNUTLS_VERIFY_ALLOW_X509_V1_CA_CRT);
+
+      rc = gnutls_certificate_set_x509_trust_file(gtls->cred,
+                                                  config->CAfile,
+                                                  GNUTLS_X509_FMT_PEM);
+      if(rc < 0) {
+        infof(data, "error reading ca cert file %s (%s)%s",
+              config->CAfile, gnutls_strerror(rc),
+              (imported_native_ca ? ", continuing anyway" : ""));
+        if(!imported_native_ca) {
+          ssl_config->certverifyresult = rc;
+          return CURLE_SSL_CACERT_BADFILE;
+        }
+      }
+      else
+        infof(data, "found %d certificates in %s", rc, config->CAfile);
+    }
+
+    if(config->CApath) {
+      /* set the trusted CA cert directory */
+      rc = gnutls_certificate_set_x509_trust_dir(gtls->cred,
+                                                 config->CApath,
+                                                 GNUTLS_X509_FMT_PEM);
+      if(rc < 0) {
+        infof(data, "error reading ca cert file %s (%s)%s",
+              config->CApath, gnutls_strerror(rc),
+              (imported_native_ca ? ", continuing anyway" : ""));
+        if(!imported_native_ca) {
+          ssl_config->certverifyresult = rc;
+          return CURLE_SSL_CACERT_BADFILE;
+        }
+      }
+      else
+        infof(data, "found %d certificates in %s", rc, config->CApath);
+    }
+  }
+
+  if(config->CRLfile) {
+    /* set the CRL list file */
+    rc = gnutls_certificate_set_x509_crl_file(gtls->cred,
+                                              config->CRLfile,
+                                              GNUTLS_X509_FMT_PEM);
+    if(rc < 0) {
+      failf(data, "error reading crl file %s (%s)",
+            config->CRLfile, gnutls_strerror(rc));
+      return CURLE_SSL_CRL_BADFILE;
+    }
+    else
+      infof(data, "found %d CRL in %s", rc, config->CRLfile);
+  }
+
+  gtls->trust_setup = TRUE;
+  return CURLE_OK;
+}
+
+static void gtls_sessionid_free(void *sessionid, size_t idsize)
+{
+  (void)idsize;
+  free(sessionid);
+}
+
+static CURLcode gtls_update_session_id(struct Curl_cfilter *cf,
+                                       struct Curl_easy *data,
+                                       gnutls_session_t session)
 {
+  struct ssl_config_data *ssl_config = Curl_ssl_cf_get_config(cf, data);
+  struct ssl_connect_data *connssl = cf->ctx;
+  CURLcode result = CURLE_OK;
+
+  if(ssl_config->primary.sessionid) {
+    /* we always unconditionally get the session id here, as even if we
+       already got it from the cache and asked to use it in the connection, it
+       might've been rejected and then a new one is in use now and we need to
+       detect that. */
+    void *connect_sessionid;
+    size_t connect_idsize = 0;
+
+    /* get the session ID data size */
+    gnutls_session_get_data(session, NULL, &connect_idsize);
+    connect_sessionid = malloc(connect_idsize); /* get a buffer for it */
+    if(!connect_sessionid) {
+      return CURLE_OUT_OF_MEMORY;
+    }
+    else {
+      bool incache;
+      void *ssl_sessionid;
+
+      /* extract session ID to the allocated buffer */
+      gnutls_session_get_data(session, connect_sessionid, &connect_idsize);
+
+      DEBUGF(infof(data, "get session id (len=%zu) and store in cache",
+                   connect_idsize));
+      Curl_ssl_sessionid_lock(data);
+      incache = !(Curl_ssl_getsessionid(cf, data, &connssl->peer,
+                                        &ssl_sessionid, NULL));
+      if(incache) {
+        /* there was one before in the cache, so instead of risking that the
+           previous one was rejected, we just kill that and store the new */
+        Curl_ssl_delsessionid(data, ssl_sessionid);
+      }
+
+      /* store this session id, takes ownership */
+      result = Curl_ssl_addsessionid(cf, data, &connssl->peer,
+                                     connect_sessionid, connect_idsize,
+                                     gtls_sessionid_free);
+      Curl_ssl_sessionid_unlock(data);
+    }
+  }
+  return result;
+}
+
+static int gtls_handshake_cb(gnutls_session_t session, unsigned int htype,
+                             unsigned when, unsigned int incoming,
+                             const gnutls_datum_t *msg)
+{
+  struct Curl_cfilter *cf = gnutls_session_get_ptr(session);
+
+  (void)msg;
+  (void)incoming;
+  if(when) { /* after message has been processed */
+    struct Curl_easy *data = CF_DATA_CURRENT(cf);
+    if(data) {
+      DEBUGF(infof(data, "handshake: %s message type %d",
+             incoming? "incoming" : "outgoing", htype));
+      switch(htype) {
+      case GNUTLS_HANDSHAKE_NEW_SESSION_TICKET: {
+        gtls_update_session_id(cf, data, session);
+        break;
+      }
+      default:
+        break;
+      }
+    }
+  }
+  return 0;
+}
+
+static CURLcode gtls_client_init(struct Curl_cfilter *cf,
+                                 struct Curl_easy *data,
+                                 struct ssl_peer *peer,
+                                 struct gtls_ctx *gtls)
+{
+  struct ssl_primary_config *config = Curl_ssl_cf_get_primary_config(cf);
+  struct ssl_config_data *ssl_config = Curl_ssl_cf_get_config(cf, data);
   unsigned int init_flags;
   int rc;
   bool sni = TRUE; /* default is SNI enabled */
-#ifdef ENABLE_IPV6
-  struct in6_addr addr;
-#else
-  struct in_addr addr;
-#endif
   const char *prioritylist;
   const char *err = NULL;
   const char *tls13support;
@@ -422,8 +632,6 @@ CURLcode gtls_client_init(struct Curl_easy *data,
   if(!gtls_inited)
     gtls_init();
 
-  *pverifyresult = 0;
-
   if(config->version == CURL_SSLVERSION_SSLv2) {
     failf(data, "GnuTLS does not support SSLv2");
     return CURLE_SSL_CONNECT_ERROR;
@@ -460,64 +668,7 @@ CURLcode gtls_client_init(struct Curl_easy *data,
   }
 #endif
 
-  if(config->CAfile) {
-    /* set the trusted CA cert bundle file */
-    gnutls_certificate_set_verify_flags(gtls->cred,
-                                        GNUTLS_VERIFY_ALLOW_X509_V1_CA_CRT);
-
-    rc = gnutls_certificate_set_x509_trust_file(gtls->cred,
-                                                config->CAfile,
-                                                GNUTLS_X509_FMT_PEM);
-    if(rc < 0) {
-      infof(data, "error reading ca cert file %s (%s)",
-            config->CAfile, gnutls_strerror(rc));
-      if(config->verifypeer) {
-        *pverifyresult = rc;
-        return CURLE_SSL_CACERT_BADFILE;
-      }
-    }
-    else
-      infof(data, "found %d certificates in %s", rc, config->CAfile);
-  }
-
-  if(config->CApath) {
-    /* set the trusted CA cert directory */
-    rc = gnutls_certificate_set_x509_trust_dir(gtls->cred,
-                                               config->CApath,
-                                               GNUTLS_X509_FMT_PEM);
-    if(rc < 0) {
-      infof(data, "error reading ca cert file %s (%s)",
-            config->CApath, gnutls_strerror(rc));
-      if(config->verifypeer) {
-        *pverifyresult = rc;
-        return CURLE_SSL_CACERT_BADFILE;
-      }
-    }
-    else
-      infof(data, "found %d certificates in %s", rc, config->CApath);
-  }
-
-#ifdef CURL_CA_FALLBACK
-  /* use system ca certificate store as fallback */
-  if(config->verifypeer && !(config->CAfile || config->CApath)) {
-    /* this ignores errors on purpose */
-    gnutls_certificate_set_x509_system_trust(gtls->cred);
-  }
-#endif
-
-  if(config->CRLfile) {
-    /* set the CRL list file */
-    rc = gnutls_certificate_set_x509_crl_file(gtls->cred,
-                                              config->CRLfile,
-                                              GNUTLS_X509_FMT_PEM);
-    if(rc < 0) {
-      failf(data, "error reading crl file %s (%s)",
-            config->CRLfile, gnutls_strerror(rc));
-      return CURLE_SSL_CRL_BADFILE;
-    }
-    else
-      infof(data, "found %d CRL in %s", rc, config->CRLfile);
-  }
+  ssl_config->certverifyresult = 0;
 
   /* Initialize TLS session as a client */
   init_flags = GNUTLS_CLIENT;
@@ -537,15 +688,9 @@ CURLcode gtls_client_init(struct Curl_easy *data,
     return CURLE_SSL_CONNECT_ERROR;
   }
 
-  if((0 == Curl_inet_pton(AF_INET, hostname, &addr)) &&
-#ifdef ENABLE_IPV6
-     (0 == Curl_inet_pton(AF_INET6, hostname, &addr)) &&
-#endif
-     sni) {
-    size_t snilen;
-    char *snihost = Curl_ssl_snihost(data, hostname, &snilen);
-    if(!snihost || gnutls_server_name_set(gtls->session, GNUTLS_NAME_DNS,
-                                          snihost, snilen) < 0) {
+  if(sni && peer->sni) {
+    if(gnutls_server_name_set(gtls->session, GNUTLS_NAME_DNS,
+                              peer->sni, strlen(peer->sni)) < 0) {
       failf(data, "Failed to set SNI");
       return CURLE_SSL_CONNECT_ERROR;
     }
@@ -577,7 +722,8 @@ CURLcode gtls_client_init(struct Curl_easy *data,
   }
 
   /* At this point we know we have a supported TLS version, so set it */
-  result = set_ssl_version_min_max(data, config, &prioritylist, tls13support);
+  result = set_ssl_version_min_max(data, peer,
+                                   config, &prioritylist, tls13support);
   if(result)
     return result;
 
@@ -585,13 +731,9 @@ CURLcode gtls_client_init(struct Curl_easy *data,
   /* Only add SRP to the cipher list if SRP is requested. Otherwise
    * GnuTLS will disable TLS 1.3 support. */
   if(config->username) {
-    size_t len = strlen(prioritylist);
-
-    char *prioritysrp = malloc(len + sizeof(GNUTLS_SRP) + 1);
+    char *prioritysrp = aprintf("%s:" GNUTLS_SRP, prioritylist);
     if(!prioritysrp)
       return CURLE_OUT_OF_MEMORY;
-    strcpy(prioritysrp, prioritylist);
-    strcpy(prioritysrp + len, ":" GNUTLS_SRP);
     rc = gnutls_priority_set_direct(gtls->session, prioritysrp, &err);
     free(prioritysrp);
 
@@ -614,6 +756,11 @@ CURLcode gtls_client_init(struct Curl_easy *data,
   }
 
   if(config->clientcert) {
+    if(!gtls->trust_setup) {
+      result = Curl_gtls_client_trust_setup(cf, data, gtls);
+      if(result)
+        return result;
+    }
     if(ssl_config->key_passwd) {
       const unsigned int supported_key_encryption_algorithms =
         GNUTLS_PKCS_USE_PKCS12_3DES | GNUTLS_PKCS_USE_PKCS12_ARCFOUR |
@@ -680,46 +827,78 @@ CURLcode gtls_client_init(struct Curl_easy *data,
   return CURLE_OK;
 }
 
-static CURLcode
-gtls_connect_step1(struct Curl_cfilter *cf, struct Curl_easy *data)
+static int keylog_callback(gnutls_session_t session, const char *label,
+                           const gnutls_datum_t *secret)
+{
+  gnutls_datum_t crandom;
+  gnutls_datum_t srandom;
+
+  gnutls_session_get_random(session, &crandom, &srandom);
+  if(crandom.size != 32) {
+    return -1;
+  }
+
+  Curl_tls_keylog_write(label, crandom.data, secret->data, secret->size);
+  return 0;
+}
+
+CURLcode Curl_gtls_ctx_init(struct gtls_ctx *gctx,
+                            struct Curl_cfilter *cf,
+                            struct Curl_easy *data,
+                            struct ssl_peer *peer,
+                            const unsigned char *alpn, size_t alpn_len,
+                            Curl_gtls_ctx_setup_cb *cb_setup,
+                            void *cb_user_data,
+                            void *ssl_user_data)
 {
-  struct ssl_connect_data *connssl = cf->ctx;
-  struct gtls_ssl_backend_data *backend =
-    (struct gtls_ssl_backend_data *)connssl->backend;
   struct ssl_primary_config *conn_config = Curl_ssl_cf_get_primary_config(cf);
-  struct ssl_config_data *ssl_config = Curl_ssl_cf_get_config(cf, data);
-  long * const pverifyresult = &ssl_config->certverifyresult;
   CURLcode result;
 
-  DEBUGASSERT(backend);
-
-  if(connssl->state == ssl_connection_complete)
-    /* to make us tolerant against being called more than once for the
-       same connection */
-    return CURLE_OK;
+  DEBUGASSERT(gctx);
 
-  result = gtls_client_init(data, conn_config, ssl_config,
-                            connssl->hostname,
-                            &backend->gtls, pverifyresult);
+  result = gtls_client_init(cf, data, peer, gctx);
   if(result)
     return result;
 
-  if(connssl->alpn) {
-    struct alpn_proto_buf proto;
-    gnutls_datum_t alpn[ALPN_ENTRIES_MAX];
-    size_t i;
+  gnutls_session_set_ptr(gctx->session, ssl_user_data);
+
+  if(cb_setup) {
+    result = cb_setup(cf, data, cb_user_data);
+    if(result)
+      return result;
+  }
+
+  /* Open the file if a TLS or QUIC backend has not done this before. */
+  Curl_tls_keylog_open();
+  if(Curl_tls_keylog_enabled()) {
+    gnutls_session_set_keylog_function(gctx->session, keylog_callback);
+  }
 
-    for(i = 0; i < connssl->alpn->count; ++i) {
-      alpn[i].data = (unsigned char *)connssl->alpn->entries[i];
-      alpn[i].size = (unsigned)strlen(connssl->alpn->entries[i]);
+  /* convert the ALPN string from our arguments to a list of strings
+   * that gnutls wants and will convert internally back to this very
+   * string for sending to the server. nice. */
+  if(alpn && alpn_len) {
+    gnutls_datum_t alpns[5];
+    size_t i, alen = alpn_len;
+    unsigned char *s = (unsigned char *)alpn;
+    unsigned char slen;
+    for(i = 0; (i < ARRAYSIZE(alpns)) && alen; ++i) {
+      slen = s[0];
+      if(slen >= alen)
+        return CURLE_FAILED_INIT;
+      alpns[i].data = s + 1;
+      alpns[i].size = slen;
+      s += slen + 1;
+      alen -= (size_t)slen + 1;
     }
-    if(gnutls_alpn_set_protocols(backend->gtls.session, alpn,
-                                 (unsigned)connssl->alpn->count, 0)) {
+    if(alen) /* not all alpn chars used, wrong format or too many */
+        return CURLE_FAILED_INIT;
+    if(i && gnutls_alpn_set_protocols(gctx->session,
+                                      alpns, (unsigned int)i,
+                                      GNUTLS_ALPN_MANDATORY)) {
       failf(data, "failed setting ALPN");
       return CURLE_SSL_CONNECT_ERROR;
     }
-    Curl_alpn_to_proto_str(&proto, connssl->alpn);
-    infof(data, VTLS_INFOF_ALPN_OFFER_1STR, proto.data);
   }
 
   /* This might be a reconnect, so we check for a session ID in the cache
@@ -729,16 +908,55 @@ gtls_connect_step1(struct Curl_cfilter *cf, struct Curl_easy *data)
     size_t ssl_idsize;
 
     Curl_ssl_sessionid_lock(data);
-    if(!Curl_ssl_getsessionid(cf, data, &ssl_sessionid, &ssl_idsize)) {
+    if(!Curl_ssl_getsessionid(cf, data, peer, &ssl_sessionid, &ssl_idsize)) {
       /* we got a session id, use it! */
-      gnutls_session_set_data(backend->gtls.session,
-                              ssl_sessionid, ssl_idsize);
+      int rc;
 
-      /* Informational message */
-      infof(data, "SSL reusing session ID");
+      rc = gnutls_session_set_data(gctx->session, ssl_sessionid, ssl_idsize);
+      if(rc < 0)
+        infof(data, "SSL failed to set session ID");
+      else
+        infof(data, "SSL reusing session ID (size=%zu)", ssl_idsize);
     }
     Curl_ssl_sessionid_unlock(data);
   }
+  return CURLE_OK;
+}
+
+static CURLcode
+gtls_connect_step1(struct Curl_cfilter *cf, struct Curl_easy *data)
+{
+  struct ssl_connect_data *connssl = cf->ctx;
+  struct gtls_ssl_backend_data *backend =
+    (struct gtls_ssl_backend_data *)connssl->backend;
+  struct alpn_proto_buf proto;
+  CURLcode result;
+
+  DEBUGASSERT(backend);
+  DEBUGASSERT(ssl_connect_1 == connssl->connecting_state);
+
+  if(connssl->state == ssl_connection_complete)
+    /* to make us tolerant against being called more than once for the
+       same connection */
+    return CURLE_OK;
+
+  memset(&proto, 0, sizeof(proto));
+  if(connssl->alpn) {
+    result = Curl_alpn_to_proto_buf(&proto, connssl->alpn);
+    if(result) {
+      failf(data, "Error determining ALPN");
+      return CURLE_SSL_CONNECT_ERROR;
+    }
+  }
+
+  result = Curl_gtls_ctx_init(&backend->gtls, cf, data, &connssl->peer,
+                              proto.data, proto.len, NULL, NULL, cf);
+  if(result)
+    return result;
+
+  gnutls_handshake_set_hook_function(backend->gtls.session,
+                                     GNUTLS_HANDSHAKE_ANY, GNUTLS_HOOK_POST,
+                                     gtls_handshake_cb);
 
   /* register callback functions and handle to send and receive data. */
   gnutls_transport_set_ptr(backend->gtls.session, cf);
@@ -811,8 +1029,7 @@ Curl_gtls_verifyserver(struct Curl_easy *data,
                        gnutls_session_t session,
                        struct ssl_primary_config *config,
                        struct ssl_config_data *ssl_config,
-                       const char *hostname,
-                       const char *dispname,
+                       struct ssl_peer *peer,
                        const char *pinned_key)
 {
   unsigned int cert_list_size;
@@ -824,16 +1041,17 @@ Curl_gtls_verifyserver(struct Curl_easy *data,
   char certname[65] = ""; /* limited to 64 chars by ASN.1 */
   size_t size;
   time_t certclock;
-  const char *ptr;
   int rc;
   CURLcode result = CURLE_OK;
 #ifndef CURL_DISABLE_VERBOSE_STRINGS
+  const char *ptr;
   unsigned int algo;
   unsigned int bits;
   gnutls_protocol_t version = gnutls_protocol_get_version(session);
 #endif
   long * const certverifyresult = &ssl_config->certverifyresult;
 
+#ifndef CURL_DISABLE_VERBOSE_STRINGS
   /* the name of the cipher suite used, e.g. ECDHE_RSA_AES_256_GCM_SHA384. */
   ptr = gnutls_cipher_suite_get_name(gnutls_kx_get(session),
                                      gnutls_cipher_get(session),
@@ -841,6 +1059,7 @@ Curl_gtls_verifyserver(struct Curl_easy *data,
 
   infof(data, "SSL connection using %s / %s",
         gnutls_protocol_get_name(version), ptr);
+#endif
 
   /* This function will return the peer's raw certificate (chain) as sent by
      the peer. These certificates are in raw format (DER encoded for
@@ -1068,12 +1287,12 @@ Curl_gtls_verifyserver(struct Curl_easy *data,
      in RFC2818 (HTTPS), which takes into account wildcards, and the subject
      alternative name PKIX extension. Returns non zero on success, and zero on
      failure. */
-  rc = gnutls_x509_crt_check_hostname(x509_cert, hostname);
+  rc = gnutls_x509_crt_check_hostname(x509_cert, peer->hostname);
 #if GNUTLS_VERSION_NUMBER < 0x030306
   /* Before 3.3.6, gnutls_x509_crt_check_hostname() didn't check IP
      addresses. */
   if(!rc) {
-#ifdef ENABLE_IPV6
+#ifdef USE_IPV6
     #define use_addr in6_addr
 #else
     #define use_addr in_addr
@@ -1081,10 +1300,10 @@ Curl_gtls_verifyserver(struct Curl_easy *data,
     unsigned char addrbuf[sizeof(struct use_addr)];
     size_t addrlen = 0;
 
-    if(Curl_inet_pton(AF_INET, hostname, addrbuf) > 0)
+    if(Curl_inet_pton(AF_INET, peer->hostname, addrbuf) > 0)
       addrlen = 4;
-#ifdef ENABLE_IPV6
-    else if(Curl_inet_pton(AF_INET6, hostname, addrbuf) > 0)
+#ifdef USE_IPV6
+    else if(Curl_inet_pton(AF_INET6, peer->hostname, addrbuf) > 0)
       addrlen = 16;
 #endif
 
@@ -1114,13 +1333,13 @@ Curl_gtls_verifyserver(struct Curl_easy *data,
   if(!rc) {
     if(config->verifyhost) {
       failf(data, "SSL: certificate subject name (%s) does not match "
-            "target host name '%s'", certname, dispname);
+            "target host name '%s'", certname, peer->dispname);
       gnutls_x509_crt_deinit(x509_cert);
       return CURLE_PEER_FAILED_VERIFICATION;
     }
     else
       infof(data, "  common name: %s (does not match '%s')",
-            certname, dispname);
+            certname, peer->dispname);
   }
   else
     infof(data, "  common name: %s (matched)", certname);
@@ -1247,14 +1466,17 @@ static CURLcode gtls_verifyserver(struct Curl_cfilter *cf,
   struct ssl_connect_data *connssl = cf->ctx;
   struct ssl_primary_config *conn_config = Curl_ssl_cf_get_primary_config(cf);
   struct ssl_config_data *ssl_config = Curl_ssl_cf_get_config(cf, data);
+#ifndef CURL_DISABLE_PROXY
   const char *pinned_key = Curl_ssl_cf_is_proxy(cf)?
     data->set.str[STRING_SSL_PINNEDPUBLICKEY_PROXY]:
     data->set.str[STRING_SSL_PINNEDPUBLICKEY];
+#else
+  const char *pinned_key = data->set.str[STRING_SSL_PINNEDPUBLICKEY];
+#endif
   CURLcode result;
 
   result = Curl_gtls_verifyserver(data, session, conn_config, ssl_config,
-                                  connssl->hostname, connssl->dispname,
-                                  pinned_key);
+                                  &connssl->peer, pinned_key);
   if(result)
     goto out;
 
@@ -1269,47 +1491,10 @@ static CURLcode gtls_verifyserver(struct Curl_cfilter *cf,
       Curl_alpn_set_negotiated(cf, data, NULL, 0);
   }
 
-  if(ssl_config->primary.sessionid) {
-    /* we always unconditionally get the session id here, as even if we
-       already got it from the cache and asked to use it in the connection, it
-       might've been rejected and then a new one is in use now and we need to
-       detect that. */
-    void *connect_sessionid;
-    size_t connect_idsize = 0;
-
-    /* get the session ID data size */
-    gnutls_session_get_data(session, NULL, &connect_idsize);
-    connect_sessionid = malloc(connect_idsize); /* get a buffer for it */
-
-    if(connect_sessionid) {
-      bool incache;
-      bool added = FALSE;
-      void *ssl_sessionid;
-
-      /* extract session ID to the allocated buffer */
-      gnutls_session_get_data(session, connect_sessionid, &connect_idsize);
-
-      Curl_ssl_sessionid_lock(data);
-      incache = !(Curl_ssl_getsessionid(cf, data, &ssl_sessionid, NULL));
-      if(incache) {
-        /* there was one before in the cache, so instead of risking that the
-           previous one was rejected, we just kill that and store the new */
-        Curl_ssl_delsessionid(data, ssl_sessionid);
-      }
-
-      /* store this session id */
-      result = Curl_ssl_addsessionid(cf, data, connect_sessionid,
-                                     connect_idsize, &added);
-      Curl_ssl_sessionid_unlock(data);
-      if(!added)
-        free(connect_sessionid);
-      if(result) {
-        result = CURLE_OUT_OF_MEMORY;
-      }
-    }
-    else
-      result = CURLE_OUT_OF_MEMORY;
-  }
+  /* Only on TLSv1.2 or lower do we have the session id now. For
+   * TLSv1.3 we get it via a SESSION_TICKET message that arrives later. */
+  if(gnutls_protocol_get_version(session) < GNUTLS_TLS1_3)
+    result = gtls_update_session_id(cf, data, session);
 
 out:
   return result;
@@ -1421,12 +1606,13 @@ static ssize_t gtls_send(struct Curl_cfilter *cf,
 
   (void)data;
   DEBUGASSERT(backend);
+  backend->gtls.io_result = CURLE_OK;
   rc = gnutls_record_send(backend->gtls.session, mem, len);
 
   if(rc < 0) {
-    *curlcode = (rc == GNUTLS_E_AGAIN)
-      ? CURLE_AGAIN
-      : CURLE_SEND_ERROR;
+    *curlcode = (rc == GNUTLS_E_AGAIN)?
+      CURLE_AGAIN :
+      (backend->gtls.io_result? backend->gtls.io_result : CURLE_SEND_ERROR);
 
     rc = -1;
   }
@@ -1473,7 +1659,6 @@ static int gtls_shutdown(struct Curl_cfilter *cf,
                          struct Curl_easy *data)
 {
   struct ssl_connect_data *connssl = cf->ctx;
-  struct ssl_config_data *ssl_config = Curl_ssl_cf_get_config(cf, data);
   struct gtls_ssl_backend_data *backend =
     (struct gtls_ssl_backend_data *)connssl->backend;
   int retval = 0;
@@ -1495,7 +1680,7 @@ static int gtls_shutdown(struct Curl_cfilter *cf,
     bool done = FALSE;
     char buf[120];
 
-    while(!done) {
+    while(!done && !connssl->peer_closed) {
       int what = SOCKET_READABLE(Curl_conn_cf_get_socket(cf, data),
                                  SSL_SHUTDOWN_TIMEOUT);
       if(what > 0) {
@@ -1536,8 +1721,11 @@ static int gtls_shutdown(struct Curl_cfilter *cf,
   gnutls_certificate_free_credentials(backend->gtls.cred);
 
 #ifdef USE_GNUTLS_SRP
-  if(ssl_config->primary.username)
-    gnutls_srp_free_client_credentials(backend->gtls.srp_client_cred);
+  {
+    struct ssl_config_data *ssl_config = Curl_ssl_cf_get_config(cf, data);
+    if(ssl_config->primary.username)
+      gnutls_srp_free_client_credentials(backend->gtls.srp_client_cred);
+  }
 #endif
 
   backend->gtls.cred = NULL;
@@ -1560,6 +1748,7 @@ static ssize_t gtls_recv(struct Curl_cfilter *cf,
   (void)data;
   DEBUGASSERT(backend);
 
+  backend->gtls.io_result = CURLE_OK;
   ret = gnutls_record_recv(backend->gtls.session, buf, buffersize);
   if((ret == GNUTLS_E_AGAIN) || (ret == GNUTLS_E_INTERRUPTED)) {
     *curlcode = CURLE_AGAIN;
@@ -1584,7 +1773,8 @@ static ssize_t gtls_recv(struct Curl_cfilter *cf,
     failf(data, "GnuTLS recv error (%d): %s",
 
           (int)ret, gnutls_strerror((int)ret));
-    *curlcode = CURLE_RECV_ERROR;
+    *curlcode = backend->gtls.io_result?
+                backend->gtls.io_result : CURLE_RECV_ERROR;
     ret = -1;
     goto out;
   }
@@ -1593,11 +1783,6 @@ static ssize_t gtls_recv(struct Curl_cfilter *cf,
   return ret;
 }
 
-static void gtls_session_free(void *ptr)
-{
-  free(ptr);
-}
-
 static size_t gtls_version(char *buffer, size_t size)
 {
   return msnprintf(buffer, size, "GnuTLS/%s", gnutls_check_version(NULL));
@@ -1660,11 +1845,10 @@ const struct Curl_ssl Curl_ssl_gnutls = {
   gtls_cert_status_request,      /* cert_status_request */
   gtls_connect,                  /* connect */
   gtls_connect_nonblocking,      /* connect_nonblocking */
-  Curl_ssl_get_select_socks,              /* getsock */
+  Curl_ssl_adjust_pollset,       /* adjust_pollset */
   gtls_get_internals,            /* get_internals */
   gtls_close,                    /* close_one */
   Curl_none_close_all,           /* close_all */
-  gtls_session_free,             /* session_free */
   Curl_none_set_engine,          /* set_engine */
   Curl_none_set_engine_default,  /* set_engine_default */
   Curl_none_engines_list,        /* engines_list */
diff --git a/vendor/curl/lib/vtls/gtls.h b/vendor/curl/lib/vtls/gtls.h
index ac141e1c61..f8388b37b8 100644
--- a/vendor/curl/lib/vtls/gtls.h
+++ b/vendor/curl/lib/vtls/gtls.h
@@ -43,31 +43,41 @@ struct Curl_easy;
 struct Curl_cfilter;
 struct ssl_primary_config;
 struct ssl_config_data;
+struct ssl_peer;
 
-struct gtls_instance {
+struct gtls_ctx {
   gnutls_session_t session;
   gnutls_certificate_credentials_t cred;
 #ifdef USE_GNUTLS_SRP
   gnutls_srp_client_credentials_t srp_client_cred;
 #endif
+  CURLcode io_result; /* result of last IO cfilter operation */
+  BIT(trust_setup); /* x509 anchors + CRLs have been set up */
 };
 
-CURLcode
-gtls_client_init(struct Curl_easy *data,
-                 struct ssl_primary_config *config,
-                 struct ssl_config_data *ssl_config,
-                 const char *hostname,
-                 struct gtls_instance *gtls,
-                 long *pverifyresult);
+typedef CURLcode Curl_gtls_ctx_setup_cb(struct Curl_cfilter *cf,
+                                        struct Curl_easy *data,
+                                        void *user_data);
 
-CURLcode
-Curl_gtls_verifyserver(struct Curl_easy *data,
-                       gnutls_session_t session,
-                       struct ssl_primary_config *config,
-                       struct ssl_config_data *ssl_config,
-                       const char *hostname,
-                       const char *dispname,
-                       const char *pinned_key);
+CURLcode Curl_gtls_ctx_init(struct gtls_ctx *gctx,
+                            struct Curl_cfilter *cf,
+                            struct Curl_easy *data,
+                            struct ssl_peer *peer,
+                            const unsigned char *alpn, size_t alpn_len,
+                            Curl_gtls_ctx_setup_cb *cb_setup,
+                            void *cb_user_data,
+                            void *ssl_user_data);
+
+CURLcode Curl_gtls_client_trust_setup(struct Curl_cfilter *cf,
+                                      struct Curl_easy *data,
+                                      struct gtls_ctx *gtls);
+
+CURLcode Curl_gtls_verifyserver(struct Curl_easy *data,
+                                gnutls_session_t session,
+                                struct ssl_primary_config *config,
+                                struct ssl_config_data *ssl_config,
+                                struct ssl_peer *peer,
+                                const char *pinned_key);
 
 extern const struct Curl_ssl Curl_ssl_gnutls;
 
diff --git a/vendor/curl/lib/vtls/keylog.c b/vendor/curl/lib/vtls/keylog.c
index d37bb183e7..ab7baaaeca 100644
--- a/vendor/curl/lib/vtls/keylog.c
+++ b/vendor/curl/lib/vtls/keylog.c
@@ -23,6 +23,12 @@
  ***************************************************************************/
 #include "curl_setup.h"
 
+#if defined(USE_OPENSSL) || \
+  defined(USE_GNUTLS) || \
+  defined(USE_WOLFSSL) || \
+  (defined(USE_NGTCP2) && defined(USE_NGHTTP3)) || \
+  defined(USE_QUICHE)
+
 #include "keylog.h"
 #include 
 
@@ -55,7 +61,7 @@ Curl_tls_keylog_open(void)
     if(keylog_file_name) {
       keylog_file_fp = fopen(keylog_file_name, FOPEN_APPENDTEXT);
       if(keylog_file_fp) {
-#ifdef WIN32
+#ifdef _WIN32
         if(setvbuf(keylog_file_fp, NULL, _IONBF, 0))
 #else
         if(setvbuf(keylog_file_fp, NULL, _IOLBF, 4096))
@@ -157,3 +163,5 @@ Curl_tls_keylog_write(const char *label,
   fputs(line, keylog_file_fp);
   return true;
 }
+
+#endif  /* TLS or QUIC backend */
diff --git a/vendor/curl/lib/vtls/mbedtls.c b/vendor/curl/lib/vtls/mbedtls.c
index f45636e57e..968f3cf8c9 100644
--- a/vendor/curl/lib/vtls/mbedtls.c
+++ b/vendor/curl/lib/vtls/mbedtls.c
@@ -36,6 +36,13 @@
 /* Define this to enable lots of debugging for mbedTLS */
 /* #define MBEDTLS_DEBUG */
 
+#ifdef __GNUC__
+#pragma GCC diagnostic push
+/* mbedTLS (as of v3.5.1) has a duplicate function declaration
+   in its public headers. Disable the warning that detects it. */
+#pragma GCC diagnostic ignored "-Wredundant-decls"
+#endif
+
 #include 
 #if MBEDTLS_VERSION_NUMBER >= 0x02040000
 #include 
@@ -56,6 +63,12 @@
 #  endif
 #endif
 
+#ifdef __GNUC__
+#pragma GCC diagnostic pop
+#endif
+
+#include "cipher_suite.h"
+#include "strcase.h"
 #include "urldata.h"
 #include "sendf.h"
 #include "inet_pton.h"
@@ -67,6 +80,7 @@
 #include "select.h"
 #include "multiif.h"
 #include "mbedtls_threadlock.h"
+#include "strdup.h"
 
 /* The last 3 #include files should be in this order */
 #include "curl_printf.h"
@@ -95,10 +109,12 @@ struct mbed_ssl_backend_data {
 #ifdef HAS_ALPN
   const char *protocols[3];
 #endif
+  int *ciphersuites;
 };
 
 /* apply threading? */
-#if defined(USE_THREADS_POSIX) || defined(USE_THREADS_WIN32)
+#if (defined(USE_THREADS_POSIX) && defined(HAVE_PTHREAD_H)) || \
+    defined(_WIN32)
 #define THREADING_SUPPORT
 #endif
 
@@ -106,12 +122,15 @@ struct mbed_ssl_backend_data {
 #define mbedtls_strerror(a,b,c) b[0] = 0
 #endif
 
+#if defined(MBEDTLS_SSL_PROTO_TLS1_3) && MBEDTLS_VERSION_NUMBER >= 0x03060000
+#define TLS13_SUPPORT
+#endif
+
 #if defined(THREADING_SUPPORT)
 static mbedtls_entropy_context ts_entropy;
 
 static int entropy_init_initialized = 0;
 
-/* start of entropy_init_mutex() */
 static void entropy_init_mutex(mbedtls_entropy_context *ctx)
 {
   /* lock 0 = entropy_init_mutex() */
@@ -122,9 +141,18 @@ static void entropy_init_mutex(mbedtls_entropy_context *ctx)
   }
   Curl_mbedtlsthreadlock_unlock_function(0);
 }
-/* end of entropy_init_mutex() */
 
-/* start of entropy_func_mutex() */
+static void entropy_cleanup_mutex(mbedtls_entropy_context *ctx)
+{
+  /* lock 0 = use same lock as init */
+  Curl_mbedtlsthreadlock_lock_function(0);
+  if(entropy_init_initialized == 1) {
+    mbedtls_entropy_free(ctx);
+    entropy_init_initialized = 0;
+  }
+  Curl_mbedtlsthreadlock_unlock_function(0);
+}
+
 static int entropy_func_mutex(void *data, unsigned char *output, size_t len)
 {
   int ret;
@@ -135,7 +163,6 @@ static int entropy_func_mutex(void *data, unsigned char *output, size_t len)
 
   return ret;
 }
-/* end of entropy_func_mutex() */
 
 #endif /* THREADING_SUPPORT */
 
@@ -143,20 +170,23 @@ static int entropy_func_mutex(void *data, unsigned char *output, size_t len)
 static void mbed_debug(void *context, int level, const char *f_name,
                        int line_nb, const char *line)
 {
-  struct Curl_easy *data = NULL;
-
-  if(!context)
-    return;
-
-  data = (struct Curl_easy *)context;
-
-  infof(data, "%s", line);
+  struct Curl_easy *data = (struct Curl_easy *)context;
   (void) level;
+  (void) line_nb;
+  (void) f_name;
+
+  if(data) {
+    size_t len = strlen(line);
+    if(len && (line[len - 1] == '\n'))
+      /* discount any trailing newline */
+      len--;
+    infof(data, "%.*s", (int)len, line);
+  }
 }
-#else
 #endif
 
-static int bio_cf_write(void *bio, const unsigned char *buf, size_t blen)
+static int mbedtls_bio_cf_write(void *bio,
+                                const unsigned char *buf, size_t blen)
 {
   struct Curl_cfilter *cf = bio;
   struct Curl_easy *data = CF_DATA_CURRENT(cf);
@@ -164,8 +194,11 @@ static int bio_cf_write(void *bio, const unsigned char *buf, size_t blen)
   CURLcode result;
 
   DEBUGASSERT(data);
+  if(!data)
+    return 0;
+
   nwritten = Curl_conn_cf_send(cf->next, data, (char *)buf, blen, &result);
-  CURL_TRC_CF(data, cf, "bio_cf_out_write(len=%zu) -> %zd, err=%d",
+  CURL_TRC_CF(data, cf, "mbedtls_bio_cf_out_write(len=%zu) -> %zd, err=%d",
               blen, nwritten, result);
   if(nwritten < 0 && CURLE_AGAIN == result) {
     nwritten = MBEDTLS_ERR_SSL_WANT_WRITE;
@@ -173,7 +206,7 @@ static int bio_cf_write(void *bio, const unsigned char *buf, size_t blen)
   return (int)nwritten;
 }
 
-static int bio_cf_read(void *bio, unsigned char *buf, size_t blen)
+static int mbedtls_bio_cf_read(void *bio, unsigned char *buf, size_t blen)
 {
   struct Curl_cfilter *cf = bio;
   struct Curl_easy *data = CF_DATA_CURRENT(cf);
@@ -181,12 +214,14 @@ static int bio_cf_read(void *bio, unsigned char *buf, size_t blen)
   CURLcode result;
 
   DEBUGASSERT(data);
+  if(!data)
+    return 0;
   /* OpenSSL catches this case, so should we. */
   if(!buf)
     return 0;
 
   nread = Curl_conn_cf_recv(cf->next, data, (char *)buf, blen, &result);
-  CURL_TRC_CF(data, cf, "bio_cf_in_read(len=%zu) -> %zd, err=%d",
+  CURL_TRC_CF(data, cf, "mbedtls_bio_cf_in_read(len=%zu) -> %zd, err=%d",
               blen, nread, result);
   if(nread < 0 && CURLE_AGAIN == result) {
     nread = MBEDTLS_ERR_SSL_WANT_READ;
@@ -220,6 +255,28 @@ static const mbedtls_x509_crt_profile mbedtls_x509_crt_profile_fr =
 #define PUB_DER_MAX_BYTES   (RSA_PUB_DER_MAX_BYTES > ECP_PUB_DER_MAX_BYTES ? \
                              RSA_PUB_DER_MAX_BYTES : ECP_PUB_DER_MAX_BYTES)
 
+#if MBEDTLS_VERSION_NUMBER >= 0x03020000
+static CURLcode mbedtls_version_from_curl(
+  mbedtls_ssl_protocol_version* mbedver, long version)
+{
+  switch(version) {
+  case CURL_SSLVERSION_TLSv1_0:
+  case CURL_SSLVERSION_TLSv1_1:
+  case CURL_SSLVERSION_TLSv1_2:
+    *mbedver = MBEDTLS_SSL_VERSION_TLS1_2;
+    return CURLE_OK;
+  case CURL_SSLVERSION_TLSv1_3:
+#ifdef TLS13_SUPPORT
+    *mbedver = MBEDTLS_SSL_VERSION_TLS1_3;
+    return CURLE_OK;
+#else
+    break;
+#endif
+  }
+
+  return CURLE_SSL_CONNECT_ERROR;
+}
+#else
 static CURLcode mbedtls_version_from_curl(int *mbedver, long version)
 {
 #if MBEDTLS_VERSION_NUMBER >= 0x03000000
@@ -250,6 +307,7 @@ static CURLcode mbedtls_version_from_curl(int *mbedver, long version)
 
   return CURLE_SSL_CONNECT_ERROR;
 }
+#endif
 
 static CURLcode
 set_ssl_version_min_max(struct Curl_cfilter *cf, struct Curl_easy *data)
@@ -258,7 +316,14 @@ set_ssl_version_min_max(struct Curl_cfilter *cf, struct Curl_easy *data)
   struct mbed_ssl_backend_data *backend =
     (struct mbed_ssl_backend_data *)connssl->backend;
   struct ssl_primary_config *conn_config = Curl_ssl_cf_get_primary_config(cf);
-#if MBEDTLS_VERSION_NUMBER >= 0x03000000
+#if MBEDTLS_VERSION_NUMBER >= 0x03020000
+  mbedtls_ssl_protocol_version mbedtls_ver_min = MBEDTLS_SSL_VERSION_TLS1_2;
+#ifdef TLS13_SUPPORT
+  mbedtls_ssl_protocol_version mbedtls_ver_max = MBEDTLS_SSL_VERSION_TLS1_3;
+#else
+  mbedtls_ssl_protocol_version mbedtls_ver_max = MBEDTLS_SSL_VERSION_TLS1_2;
+#endif
+#elif MBEDTLS_VERSION_NUMBER >= 0x03000000
   int mbedtls_ver_min = MBEDTLS_SSL_MINOR_VERSION_3;
   int mbedtls_ver_max = MBEDTLS_SSL_MINOR_VERSION_3;
 #else
@@ -281,7 +346,11 @@ set_ssl_version_min_max(struct Curl_cfilter *cf, struct Curl_easy *data)
   switch(ssl_version_max) {
     case CURL_SSLVERSION_MAX_NONE:
     case CURL_SSLVERSION_MAX_DEFAULT:
+#ifdef TLS13_SUPPORT
+      ssl_version_max = CURL_SSLVERSION_MAX_TLSv1_3;
+#else
       ssl_version_max = CURL_SSLVERSION_MAX_TLSv1_2;
+#endif
       break;
   }
 
@@ -296,14 +365,137 @@ set_ssl_version_min_max(struct Curl_cfilter *cf, struct Curl_easy *data)
     return result;
   }
 
+#if MBEDTLS_VERSION_NUMBER >= 0x03020000
+  mbedtls_ssl_conf_min_tls_version(&backend->config, mbedtls_ver_min);
+  mbedtls_ssl_conf_max_tls_version(&backend->config, mbedtls_ver_max);
+#else
   mbedtls_ssl_conf_min_version(&backend->config, MBEDTLS_SSL_MAJOR_VERSION_3,
                                mbedtls_ver_min);
   mbedtls_ssl_conf_max_version(&backend->config, MBEDTLS_SSL_MAJOR_VERSION_3,
                                mbedtls_ver_max);
+#endif
+
+#ifdef TLS13_SUPPORT
+  if(mbedtls_ver_min == MBEDTLS_SSL_VERSION_TLS1_3) {
+    mbedtls_ssl_conf_authmode(&backend->config, MBEDTLS_SSL_VERIFY_REQUIRED);
+  }
+  else {
+    mbedtls_ssl_conf_authmode(&backend->config, MBEDTLS_SSL_VERIFY_OPTIONAL);
+  }
+#else
+  mbedtls_ssl_conf_authmode(&backend->config, MBEDTLS_SSL_VERIFY_OPTIONAL);
+#endif
 
   return result;
 }
 
+/* TLS_ECJPAKE_WITH_AES_128_CCM_8 (0xC0FF) is marked experimental
+   in mbedTLS. The number is not reserved by IANA nor is the
+   cipher suite present in other SSL implementations. Provide
+   provisional support for specifying the cipher suite here. */
+#ifdef MBEDTLS_TLS_ECJPAKE_WITH_AES_128_CCM_8
+static int
+mbed_cipher_suite_get_str(uint16_t id, char *buf, size_t buf_size,
+                          bool prefer_rfc)
+{
+  if(id == MBEDTLS_TLS_ECJPAKE_WITH_AES_128_CCM_8)
+    msnprintf(buf, buf_size, "%s", "TLS_ECJPAKE_WITH_AES_128_CCM_8");
+  else
+    return Curl_cipher_suite_get_str(id, buf, buf_size, prefer_rfc);
+  return 0;
+}
+
+static uint16_t
+mbed_cipher_suite_walk_str(const char **str, const char **end)
+{
+  uint16_t id = Curl_cipher_suite_walk_str(str, end);
+  size_t len = *end - *str;
+
+  if(!id) {
+    if(strncasecompare("TLS_ECJPAKE_WITH_AES_128_CCM_8", *str, len))
+      id = MBEDTLS_TLS_ECJPAKE_WITH_AES_128_CCM_8;
+  }
+  return id;
+}
+#else
+#define mbed_cipher_suite_get_str Curl_cipher_suite_get_str
+#define mbed_cipher_suite_walk_str Curl_cipher_suite_walk_str
+#endif
+
+static CURLcode
+mbed_set_selected_ciphers(struct Curl_easy *data,
+                          struct mbed_ssl_backend_data *backend,
+                          const char *ciphers)
+{
+  const int *supported;
+  int *selected;
+  size_t supported_len, count = 0, i;
+  const char *ptr, *end;
+
+  supported = mbedtls_ssl_list_ciphersuites();
+  for(i = 0; supported[i] != 0; i++);
+  supported_len = i;
+
+  selected = malloc(sizeof(int) * (supported_len + 1));
+  if(!selected)
+    return CURLE_OUT_OF_MEMORY;
+
+  for(ptr = ciphers; ptr[0] != '\0' && count < supported_len; ptr = end) {
+    uint16_t id = mbed_cipher_suite_walk_str(&ptr, &end);
+
+    /* Check if cipher is supported */
+    if(id) {
+      for(i = 0; i < supported_len && supported[i] != id; i++);
+      if(i == supported_len)
+        id = 0;
+    }
+    if(!id) {
+      if(ptr[0] != '\0')
+        infof(data, "mbedTLS: unknown cipher in list: \"%.*s\"",
+              (int) (end - ptr), ptr);
+      continue;
+    }
+
+    /* No duplicates allowed (so selected cannot overflow) */
+    for(i = 0; i < count && selected[i] != id; i++);
+    if(i < count) {
+      infof(data, "mbedTLS: duplicate cipher in list: \"%.*s\"",
+            (int) (end - ptr), ptr);
+      continue;
+    }
+
+    selected[count++] = id;
+  }
+
+  selected[count] = 0;
+
+  if(count == 0) {
+    free(selected);
+    failf(data, "mbedTLS: no supported cipher in list");
+    return CURLE_SSL_CIPHER;
+  }
+
+  /* mbedtls_ssl_conf_ciphersuites(): The ciphersuites array is not copied.
+     It must remain valid for the lifetime of the SSL configuration */
+  backend->ciphersuites = selected;
+  mbedtls_ssl_conf_ciphersuites(&backend->config, backend->ciphersuites);
+  return CURLE_OK;
+}
+
+#ifdef TLS13_SUPPORT
+static int mbed_no_verify(void *udata, mbedtls_x509_crt *crt,
+                          int depth, uint32_t *flags)
+{
+  (void)udata;
+  (void)crt;
+  (void)depth;
+  /* we clear any faults the mbedtls' own verification found.
+   * See  */
+  *flags = 0;
+  return 0;
+}
+#endif
+
 static CURLcode
 mbed_connect_step1(struct Curl_cfilter *cf, struct Curl_easy *data)
 {
@@ -321,7 +513,7 @@ mbed_connect_step1(struct Curl_cfilter *cf, struct Curl_easy *data)
   char * const ssl_cert = ssl_config->primary.clientcert;
   const struct curl_blob *ssl_cert_blob = ssl_config->primary.cert_blob;
   const char * const ssl_crlfile = ssl_config->primary.CRLfile;
-  const char *hostname = connssl->hostname;
+  const char *hostname = connssl->peer.hostname;
   int ret = -1;
   char errorbuf[128];
 
@@ -333,8 +525,17 @@ mbed_connect_step1(struct Curl_cfilter *cf, struct Curl_easy *data)
     return CURLE_NOT_BUILT_IN;
   }
 
+#ifdef TLS13_SUPPORT
+  ret = psa_crypto_init();
+  if(ret != PSA_SUCCESS) {
+    mbedtls_strerror(ret, errorbuf, sizeof(errorbuf));
+    failf(data, "mbedTLS psa_crypto_init returned (-0x%04X) %s",
+          -ret, errorbuf);
+    return CURLE_SSL_CONNECT_ERROR;
+  }
+#endif /* TLS13_SUPPORT */
+
 #ifdef THREADING_SUPPORT
-  entropy_init_mutex(&ts_entropy);
   mbedtls_ctr_drbg_init(&backend->ctr_drbg);
 
   ret = mbedtls_ctr_drbg_seed(&backend->ctr_drbg, entropy_func_mutex,
@@ -366,11 +567,10 @@ mbed_connect_step1(struct Curl_cfilter *cf, struct Curl_easy *data)
     /* Unfortunately, mbedtls_x509_crt_parse() requires the data to be null
        terminated even when provided the exact length, forcing us to waste
        extra memory here. */
-    unsigned char *newblob = malloc(ca_info_blob->len + 1);
+    unsigned char *newblob = Curl_memdup0(ca_info_blob->data,
+                                          ca_info_blob->len);
     if(!newblob)
       return CURLE_OUT_OF_MEMORY;
-    memcpy(newblob, ca_info_blob->data, ca_info_blob->len);
-    newblob[ca_info_blob->len] = 0; /* null terminate */
     ret = mbedtls_x509_crt_parse(&backend->cacert, newblob,
                                  ca_info_blob->len + 1);
     free(newblob);
@@ -440,11 +640,10 @@ mbed_connect_step1(struct Curl_cfilter *cf, struct Curl_easy *data)
     /* Unfortunately, mbedtls_x509_crt_parse() requires the data to be null
        terminated even when provided the exact length, forcing us to waste
        extra memory here. */
-    unsigned char *newblob = malloc(ssl_cert_blob->len + 1);
+    unsigned char *newblob = Curl_memdup0(ssl_cert_blob->data,
+                                          ssl_cert_blob->len);
     if(!newblob)
       return CURLE_OUT_OF_MEMORY;
-    memcpy(newblob, ssl_cert_blob->data, ssl_cert_blob->len);
-    newblob[ssl_cert_blob->len] = 0; /* null terminate */
     ret = mbedtls_x509_crt_parse(&backend->clicert, newblob,
                                  ssl_cert_blob->len + 1);
     free(newblob);
@@ -541,7 +740,7 @@ mbed_connect_step1(struct Curl_cfilter *cf, struct Curl_easy *data)
   }
 #endif
 
-  infof(data, "mbedTLS: Connecting to %s:%d", hostname, connssl->port);
+  infof(data, "mbedTLS: Connecting to %s:%d", hostname, connssl->peer.port);
 
   mbedtls_ssl_config_init(&backend->config);
   ret = mbedtls_ssl_config_defaults(&backend->config,
@@ -552,12 +751,17 @@ mbed_connect_step1(struct Curl_cfilter *cf, struct Curl_easy *data)
     failf(data, "mbedTLS: ssl_config failed");
     return CURLE_SSL_CONNECT_ERROR;
   }
+#ifdef TLS13_SUPPORT
+  if(!verifypeer) {
+    /* Default verify behaviour changed in mbedtls v3.6.0 with TLS v1.3.
+     * On 1.3 connections, the handshake fails by default without trust
+     * anchors. We override this questionable change by installing our
+     * own verify callback that clears all errors. */
+    mbedtls_ssl_conf_verify(&backend->config, mbed_no_verify, cf);
+  }
+#endif
 
   mbedtls_ssl_init(&backend->ssl);
-  if(mbedtls_ssl_setup(&backend->ssl, &backend->config)) {
-    failf(data, "mbedTLS: ssl_init failed");
-    return CURLE_SSL_CONNECT_ERROR;
-  }
 
   /* new profile with RSA min key len = 1024 ... */
   mbedtls_ssl_conf_cert_profile(&backend->config,
@@ -587,15 +791,34 @@ mbed_connect_step1(struct Curl_cfilter *cf, struct Curl_easy *data)
     return CURLE_SSL_CONNECT_ERROR;
   }
 
-  mbedtls_ssl_conf_authmode(&backend->config, MBEDTLS_SSL_VERIFY_OPTIONAL);
-
   mbedtls_ssl_conf_rng(&backend->config, mbedtls_ctr_drbg_random,
                        &backend->ctr_drbg);
-  mbedtls_ssl_set_bio(&backend->ssl, cf, bio_cf_write, bio_cf_read,
+
+  ret = mbedtls_ssl_setup(&backend->ssl, &backend->config);
+  if(ret) {
+    mbedtls_strerror(ret, errorbuf, sizeof(errorbuf));
+    failf(data, "ssl_setup failed - mbedTLS: (-0x%04X) %s",
+          -ret, errorbuf);
+    return CURLE_SSL_CONNECT_ERROR;
+  }
+
+  mbedtls_ssl_set_bio(&backend->ssl, cf,
+                      mbedtls_bio_cf_write,
+                      mbedtls_bio_cf_read,
                       NULL /*  rev_timeout() */);
 
-  mbedtls_ssl_conf_ciphersuites(&backend->config,
-                                mbedtls_ssl_list_ciphersuites());
+  if(conn_config->cipher_list) {
+    ret = mbed_set_selected_ciphers(data, backend, conn_config->cipher_list);
+    if(ret) {
+      failf(data, "mbedTLS: failed to set cipher suites");
+      return ret;
+    }
+  }
+  else {
+    mbedtls_ssl_conf_ciphersuites(&backend->config,
+                                  mbedtls_ssl_list_ciphersuites());
+  }
+
 
 #if defined(MBEDTLS_SSL_RENEGOTIATION)
   mbedtls_ssl_conf_renegotiation(&backend->config,
@@ -612,7 +835,7 @@ mbed_connect_step1(struct Curl_cfilter *cf, struct Curl_easy *data)
     void *old_session = NULL;
 
     Curl_ssl_sessionid_lock(data);
-    if(!Curl_ssl_getsessionid(cf, data, &old_session, NULL)) {
+    if(!Curl_ssl_getsessionid(cf, data, &connssl->peer, &old_session, NULL)) {
       ret = mbedtls_ssl_set_session(&backend->ssl, old_session);
       if(ret) {
         Curl_ssl_sessionid_unlock(data);
@@ -636,15 +859,14 @@ mbed_connect_step1(struct Curl_cfilter *cf, struct Curl_easy *data)
     mbedtls_ssl_conf_own_cert(&backend->config,
                               &backend->clicert, &backend->pk);
   }
-  {
-    char *snihost = Curl_ssl_snihost(data, hostname, NULL);
-    if(!snihost || mbedtls_ssl_set_hostname(&backend->ssl, snihost)) {
-      /* mbedtls_ssl_set_hostname() sets the name to use in CN/SAN checks and
-         the name to set in the SNI extension. So even if curl connects to a
-         host specified as an IP address, this function must be used. */
-      failf(data, "Failed to set SNI");
-      return CURLE_SSL_CONNECT_ERROR;
-    }
+
+  if(mbedtls_ssl_set_hostname(&backend->ssl, connssl->peer.sni?
+                              connssl->peer.sni : connssl->peer.hostname)) {
+    /* mbedtls_ssl_set_hostname() sets the name to use in CN/SAN checks and
+       the name to set in the SNI extension. So even if curl connects to a
+       host specified as an IP address, this function must be used. */
+    failf(data, "Failed to set SNI");
+    return CURLE_SSL_CONNECT_ERROR;
   }
 
 #ifdef HAS_ALPN
@@ -703,9 +925,13 @@ mbed_connect_step2(struct Curl_cfilter *cf, struct Curl_easy *data)
     (struct mbed_ssl_backend_data *)connssl->backend;
   struct ssl_primary_config *conn_config = Curl_ssl_cf_get_primary_config(cf);
   const mbedtls_x509_crt *peercert;
+#ifndef CURL_DISABLE_PROXY
   const char * const pinnedpubkey = Curl_ssl_cf_is_proxy(cf)?
     data->set.str[STRING_SSL_PINNEDPUBLICKEY_PROXY]:
     data->set.str[STRING_SSL_PINNEDPUBLICKEY];
+#else
+  const char * const pinnedpubkey = data->set.str[STRING_SSL_PINNEDPUBLICKEY];
+#endif
 
   DEBUGASSERT(backend);
 
@@ -719,17 +945,32 @@ mbed_connect_step2(struct Curl_cfilter *cf, struct Curl_easy *data)
     connssl->connecting_state = ssl_connect_2_writing;
     return CURLE_OK;
   }
+  else if(ret == MBEDTLS_ERR_X509_CERT_VERIFY_FAILED) {
+    failf(data, "peer certificate could not be verified");
+    return CURLE_PEER_FAILED_VERIFICATION;
+  }
   else if(ret) {
     char errorbuf[128];
+    CURL_TRC_CF(data, cf, "TLS version %04X",
+                mbedtls_ssl_get_version_number(&backend->ssl));
     mbedtls_strerror(ret, errorbuf, sizeof(errorbuf));
-    failf(data, "ssl_handshake returned - mbedTLS: (-0x%04X) %s",
+    failf(data, "ssl_handshake returned: (-0x%04X) %s",
           -ret, errorbuf);
     return CURLE_SSL_CONNECT_ERROR;
   }
 
-  infof(data, "mbedTLS: Handshake complete, cipher is %s",
-        mbedtls_ssl_get_ciphersuite(&backend->ssl));
-
+#if MBEDTLS_VERSION_NUMBER >= 0x03020000
+  {
+    char cipher_str[64];
+    uint16_t cipher_id;
+    cipher_id = (uint16_t)
+                mbedtls_ssl_get_ciphersuite_id_from_ssl(&backend->ssl);
+    mbed_cipher_suite_get_str(cipher_id, cipher_str, sizeof(cipher_str), true);
+    infof(data, "mbedTLS: Handshake complete, cipher is %s", cipher_str);
+  }
+#else
+  infof(data, "mbedTLS: Handshake complete");
+#endif
   ret = mbedtls_ssl_get_verify_result(&backend->ssl);
 
   if(!conn_config->verifyhost)
@@ -758,6 +999,7 @@ mbed_connect_step2(struct Curl_cfilter *cf, struct Curl_easy *data)
   peercert = mbedtls_ssl_get_peer_cert(&backend->ssl);
 
   if(peercert && data->set.verbose) {
+#ifndef MBEDTLS_X509_REMOVE_INFO
     const size_t bufsize = 16384;
     char *buffer = malloc(bufsize);
 
@@ -770,6 +1012,9 @@ mbed_connect_step2(struct Curl_cfilter *cf, struct Curl_easy *data)
       infof(data, "Unable to dump certificate information");
 
     free(buffer);
+#else
+    infof(data, "Unable to dump certificate information");
+#endif
   }
 
   if(pinnedpubkey) {
@@ -858,6 +1103,13 @@ mbed_connect_step2(struct Curl_cfilter *cf, struct Curl_easy *data)
   return CURLE_OK;
 }
 
+static void mbedtls_session_free(void *sessionid, size_t idsize)
+{
+  (void)idsize;
+  mbedtls_ssl_session_free(sessionid);
+  free(sessionid);
+}
+
 static CURLcode
 mbed_connect_step3(struct Curl_cfilter *cf, struct Curl_easy *data)
 {
@@ -874,7 +1126,6 @@ mbed_connect_step3(struct Curl_cfilter *cf, struct Curl_easy *data)
     int ret;
     mbedtls_ssl_session *our_ssl_sessionid;
     void *old_ssl_sessionid = NULL;
-    bool added = FALSE;
 
     our_ssl_sessionid = malloc(sizeof(mbedtls_ssl_session));
     if(!our_ssl_sessionid)
@@ -893,20 +1144,16 @@ mbed_connect_step3(struct Curl_cfilter *cf, struct Curl_easy *data)
 
     /* If there's already a matching session in the cache, delete it */
     Curl_ssl_sessionid_lock(data);
-    if(!Curl_ssl_getsessionid(cf, data, &old_ssl_sessionid, NULL))
+    if(!Curl_ssl_getsessionid(cf, data, &connssl->peer,
+                              &old_ssl_sessionid, NULL))
       Curl_ssl_delsessionid(data, old_ssl_sessionid);
 
-    retcode = Curl_ssl_addsessionid(cf, data, our_ssl_sessionid,
-                                    0, &added);
+    retcode = Curl_ssl_addsessionid(cf, data, &connssl->peer,
+                                    our_ssl_sessionid, 0,
+                                    mbedtls_session_free);
     Curl_ssl_sessionid_unlock(data);
-    if(!added) {
-      mbedtls_ssl_session_free(our_ssl_sessionid);
-      free(our_ssl_sessionid);
-    }
-    if(retcode) {
-      failf(data, "failed to store ssl session");
+    if(retcode)
       return retcode;
-    }
   }
 
   connssl->connecting_state = ssl_connect_done;
@@ -928,8 +1175,13 @@ static ssize_t mbed_send(struct Curl_cfilter *cf, struct Curl_easy *data,
   ret = mbedtls_ssl_write(&backend->ssl, (unsigned char *)mem, len);
 
   if(ret < 0) {
-    *curlcode = (ret == MBEDTLS_ERR_SSL_WANT_WRITE) ?
-      CURLE_AGAIN : CURLE_SEND_ERROR;
+    CURL_TRC_CF(data, cf, "mbedtls_ssl_write(len=%zu) -> -0x%04X",
+                len, -ret);
+    *curlcode = ((ret == MBEDTLS_ERR_SSL_WANT_WRITE)
+#ifdef TLS13_SUPPORT
+      || (ret == MBEDTLS_ERR_SSL_RECEIVED_NEW_SESSION_TICKET)
+#endif
+      )? CURLE_AGAIN : CURLE_SEND_ERROR;
     ret = -1;
   }
 
@@ -961,6 +1213,7 @@ static void mbedtls_close(struct Curl_cfilter *cf, struct Curl_easy *data)
 #ifdef MBEDTLS_X509_CRL_PARSE_C
   mbedtls_x509_crl_free(&backend->crl);
 #endif
+  Curl_safefree(backend->ciphersuites);
   mbedtls_ssl_config_free(&backend->config);
   mbedtls_ssl_free(&backend->ssl);
   mbedtls_ctr_drbg_free(&backend->ctr_drbg);
@@ -986,11 +1239,21 @@ static ssize_t mbed_recv(struct Curl_cfilter *cf, struct Curl_easy *data,
                          buffersize);
 
   if(ret <= 0) {
+    CURL_TRC_CF(data, cf, "mbedtls_ssl_read(len=%zu) -> -0x%04X",
+                buffersize, -ret);
     if(ret == MBEDTLS_ERR_SSL_PEER_CLOSE_NOTIFY)
       return 0;
 
-    *curlcode = (ret == MBEDTLS_ERR_SSL_WANT_READ) ?
-      CURLE_AGAIN : CURLE_RECV_ERROR;
+    *curlcode = ((ret == MBEDTLS_ERR_SSL_WANT_READ)
+#ifdef TLS13_SUPPORT
+              || (ret == MBEDTLS_ERR_SSL_RECEIVED_NEW_SESSION_TICKET)
+#endif
+    ) ? CURLE_AGAIN : CURLE_RECV_ERROR;
+    if(*curlcode != CURLE_AGAIN) {
+      char errorbuf[128];
+      mbedtls_strerror(ret, errorbuf, sizeof(errorbuf));
+      failf(data, "ssl_read returned: (-0x%04X) %s", -ret, errorbuf);
+    }
     return -1;
   }
 
@@ -999,12 +1262,6 @@ static ssize_t mbed_recv(struct Curl_cfilter *cf, struct Curl_easy *data,
   return len;
 }
 
-static void mbedtls_session_free(void *ptr)
-{
-  mbedtls_ssl_session_free(ptr);
-  free(ptr);
-}
-
 static size_t mbedtls_version(char *buffer, size_t size)
 {
 #ifdef MBEDTLS_VERSION_C
@@ -1199,11 +1456,19 @@ static CURLcode mbedtls_connect(struct Curl_cfilter *cf,
  */
 static int mbedtls_init(void)
 {
-  return Curl_mbedtlsthreadlock_thread_setup();
+  if(!Curl_mbedtlsthreadlock_thread_setup())
+    return 0;
+#ifdef THREADING_SUPPORT
+  entropy_init_mutex(&ts_entropy);
+#endif
+  return 1;
 }
 
 static void mbedtls_cleanup(void)
 {
+#ifdef THREADING_SUPPORT
+  entropy_cleanup_mutex(&ts_entropy);
+#endif
   (void)Curl_mbedtlsthreadlock_thread_cleanup();
 }
 
@@ -1271,11 +1536,10 @@ const struct Curl_ssl Curl_ssl_mbedtls = {
   Curl_none_cert_status_request,    /* cert_status_request */
   mbedtls_connect,                  /* connect */
   mbedtls_connect_nonblocking,      /* connect_nonblocking */
-  Curl_ssl_get_select_socks,                 /* getsock */
+  Curl_ssl_adjust_pollset,          /* adjust_pollset */
   mbedtls_get_internals,            /* get_internals */
   mbedtls_close,                    /* close_one */
   mbedtls_close_all,                /* close_all */
-  mbedtls_session_free,             /* session_free */
   Curl_none_set_engine,             /* set_engine */
   Curl_none_set_engine_default,     /* set_engine_default */
   Curl_none_engines_list,           /* engines_list */
@@ -1288,4 +1552,4 @@ const struct Curl_ssl Curl_ssl_mbedtls = {
   mbed_send,                        /* send data to encrypt */
 };
 
-#endif /* USE_MBEDTLS */
+#endif /* USE_MBEDTLS */
\ No newline at end of file
diff --git a/vendor/curl/lib/vtls/mbedtls_threadlock.c b/vendor/curl/lib/vtls/mbedtls_threadlock.c
index bcb7106a63..b96a904fcb 100644
--- a/vendor/curl/lib/vtls/mbedtls_threadlock.c
+++ b/vendor/curl/lib/vtls/mbedtls_threadlock.c
@@ -26,12 +26,12 @@
 
 #if defined(USE_MBEDTLS) &&                                     \
   ((defined(USE_THREADS_POSIX) && defined(HAVE_PTHREAD_H)) ||   \
-    defined(USE_THREADS_WIN32))
+    defined(_WIN32))
 
 #if defined(USE_THREADS_POSIX) && defined(HAVE_PTHREAD_H)
 #  include 
 #  define MBEDTLS_MUTEX_T pthread_mutex_t
-#elif defined(USE_THREADS_WIN32)
+#elif defined(_WIN32)
 #  define MBEDTLS_MUTEX_T HANDLE
 #endif
 
@@ -51,7 +51,7 @@ int Curl_mbedtlsthreadlock_thread_setup(void)
 {
   int i;
 
-  mutex_buf = calloc(NUMT * sizeof(MBEDTLS_MUTEX_T), 1);
+  mutex_buf = calloc(1, NUMT * sizeof(MBEDTLS_MUTEX_T));
   if(!mutex_buf)
     return 0;     /* error, no number of threads defined */
 
@@ -59,7 +59,7 @@ int Curl_mbedtlsthreadlock_thread_setup(void)
 #if defined(USE_THREADS_POSIX) && defined(HAVE_PTHREAD_H)
     if(pthread_mutex_init(&mutex_buf[i], NULL))
       return 0; /* pthread_mutex_init failed */
-#elif defined(USE_THREADS_WIN32)
+#elif defined(_WIN32)
     mutex_buf[i] = CreateMutex(0, FALSE, 0);
     if(mutex_buf[i] == 0)
       return 0;  /* CreateMutex failed */
@@ -80,7 +80,7 @@ int Curl_mbedtlsthreadlock_thread_cleanup(void)
 #if defined(USE_THREADS_POSIX) && defined(HAVE_PTHREAD_H)
     if(pthread_mutex_destroy(&mutex_buf[i]))
       return 0; /* pthread_mutex_destroy failed */
-#elif defined(USE_THREADS_WIN32)
+#elif defined(_WIN32)
     if(!CloseHandle(mutex_buf[i]))
       return 0; /* CloseHandle failed */
 #endif /* USE_THREADS_POSIX && HAVE_PTHREAD_H */
@@ -100,7 +100,7 @@ int Curl_mbedtlsthreadlock_lock_function(int n)
                      "Error: mbedtlsthreadlock_lock_function failed\n"));
       return 0; /* pthread_mutex_lock failed */
     }
-#elif defined(USE_THREADS_WIN32)
+#elif defined(_WIN32)
     if(WaitForSingleObject(mutex_buf[n], INFINITE) == WAIT_FAILED) {
       DEBUGF(fprintf(stderr,
                      "Error: mbedtlsthreadlock_lock_function failed\n"));
@@ -120,7 +120,7 @@ int Curl_mbedtlsthreadlock_unlock_function(int n)
                      "Error: mbedtlsthreadlock_unlock_function failed\n"));
       return 0; /* pthread_mutex_unlock failed */
     }
-#elif defined(USE_THREADS_WIN32)
+#elif defined(_WIN32)
     if(!ReleaseMutex(mutex_buf[n])) {
       DEBUGF(fprintf(stderr,
                      "Error: mbedtlsthreadlock_unlock_function failed\n"));
diff --git a/vendor/curl/lib/vtls/mbedtls_threadlock.h b/vendor/curl/lib/vtls/mbedtls_threadlock.h
index 2b0bd41c8b..484626852f 100644
--- a/vendor/curl/lib/vtls/mbedtls_threadlock.h
+++ b/vendor/curl/lib/vtls/mbedtls_threadlock.h
@@ -29,7 +29,7 @@
 #ifdef USE_MBEDTLS
 
 #if (defined(USE_THREADS_POSIX) && defined(HAVE_PTHREAD_H)) || \
-     defined(USE_THREADS_WIN32)
+    defined(_WIN32)
 
 int Curl_mbedtlsthreadlock_thread_setup(void);
 int Curl_mbedtlsthreadlock_thread_cleanup(void);
@@ -43,7 +43,7 @@ int Curl_mbedtlsthreadlock_unlock_function(int n);
 #define Curl_mbedtlsthreadlock_lock_function(x) 1
 #define Curl_mbedtlsthreadlock_unlock_function(x) 1
 
-#endif /* USE_THREADS_POSIX || USE_THREADS_WIN32 */
+#endif /* (USE_THREADS_POSIX && HAVE_PTHREAD_H) || _WIN32 */
 
 #endif /* USE_MBEDTLS */
 
diff --git a/vendor/curl/lib/vtls/openssl.c b/vendor/curl/lib/vtls/openssl.c
index a12e712b16..298a488a09 100644
--- a/vendor/curl/lib/vtls/openssl.c
+++ b/vendor/curl/lib/vtls/openssl.c
@@ -79,6 +79,19 @@
 #include 
 #include 
 #include 
+#include 
+#include 
+
+#ifdef USE_ECH
+# ifndef OPENSSL_IS_BORINGSSL
+#  include 
+# endif
+# include "curl_base64.h"
+# define ECH_ENABLED(__data__) \
+    (__data__->set.tls_ech && \
+     !(__data__->set.tls_ech & CURLECH_DISABLE)\
+    )
+#endif /* USE_ECH */
 
 #if (OPENSSL_VERSION_NUMBER >= 0x0090808fL) && !defined(OPENSSL_NO_OCSP)
 #include 
@@ -96,6 +109,9 @@
 #include "curl_memory.h"
 #include "memdebug.h"
 
+#ifndef ARRAYSIZE
+#define ARRAYSIZE(A) (sizeof(A)/sizeof((A)[0]))
+#endif
 
 /* Uncomment the ALLOW_RENEG line to a real #define if you want to allow TLS
    renegotiations when built with BoringSSL. Renegotiating is non-compliant
@@ -173,8 +189,6 @@
 
 #if (OPENSSL_VERSION_NUMBER >= 0x30000000L)
 #define HAVE_EVP_PKEY_GET_PARAMS 1
-#else
-#define SSL_get1_peer_certificate SSL_get_peer_certificate
 #endif
 
 #ifdef HAVE_EVP_PKEY_GET_PARAMS
@@ -190,12 +204,10 @@
  * Whether SSL_CTX_set_keylog_callback is available.
  * OpenSSL: supported since 1.1.1 https://github.com/openssl/openssl/pull/2287
  * BoringSSL: supported since d28f59c27bac (committed 2015-11-19)
- * LibreSSL: supported since 3.5.0 (released 2022-02-24)
+ * LibreSSL: not supported. 3.5.0+ has a stub function that does nothing.
  */
 #if (OPENSSL_VERSION_NUMBER >= 0x10101000L && \
      !defined(LIBRESSL_VERSION_NUMBER)) || \
-    (defined(LIBRESSL_VERSION_NUMBER) && \
-     LIBRESSL_VERSION_NUMBER >= 0x3050000fL) || \
     defined(OPENSSL_IS_BORINGSSL)
 #define HAVE_KEYLOG_CALLBACK
 #endif
@@ -235,7 +247,11 @@
 #elif defined(OPENSSL_IS_AWSLC)
 #define OSSL_PACKAGE "AWS-LC"
 #else
-#define OSSL_PACKAGE "OpenSSL"
+# if defined(USE_NGTCP2) && defined(USE_NGHTTP3)
+#   define OSSL_PACKAGE "quictls"
+# else
+#   define OSSL_PACKAGE "OpenSSL"
+#endif
 #endif
 
 #if (OPENSSL_VERSION_NUMBER >= 0x10100000L)
@@ -291,20 +307,6 @@ typedef unsigned long sslerr_t;
 #define USE_PRE_1_1_API (OPENSSL_VERSION_NUMBER < 0x10100000L)
 #endif /* !LIBRESSL_VERSION_NUMBER */
 
-struct ossl_ssl_backend_data {
-  /* these ones requires specific SSL-types */
-  SSL_CTX* ctx;
-  SSL*     handle;
-  X509*    server_cert;
-  BIO_METHOD *bio_method;
-  CURLcode io_result;       /* result of last BIO cfilter operation */
-#ifndef HAVE_KEYLOG_CALLBACK
-  /* Set to true once a valid keylog entry has been created to avoid dupes. */
-  bool     keylog_done;
-#endif
-  bool x509_store_setup;            /* x509 store has been set up */
-};
-
 #if defined(HAVE_SSL_X509_STORE_SHARE)
 struct multi_ssl_backend_data {
   char *CAfile;         /* CAfile path used to generate X509 store */
@@ -466,7 +468,9 @@ CURLcode Curl_ossl_certchain(struct Curl_easy *data, SSL *ssl)
 
       X509_get0_signature(&psig, &sigalg, x);
       if(sigalg) {
-        i2a_ASN1_OBJECT(mem, sigalg->algorithm);
+        const ASN1_OBJECT *sigalgoid = NULL;
+        X509_ALGOR_get0(&sigalgoid, NULL, NULL, sigalg);
+        i2a_ASN1_OBJECT(mem, sigalgoid);
         push_certinfo("Signature Algorithm", i);
       }
 
@@ -536,9 +540,9 @@ CURLcode Curl_ossl_certchain(struct Curl_easy *data, SSL *ssl)
 #else
           RSA_get0_key(rsa, &n, &e, NULL);
 #endif /* HAVE_EVP_PKEY_GET_PARAMS */
-          BIO_printf(mem, "%d", BN_num_bits(n));
+          BIO_printf(mem, "%d", n ? BN_num_bits(n) : 0);
 #else
-          BIO_printf(mem, "%d", BN_num_bits(rsa->n));
+          BIO_printf(mem, "%d", rsa->n ? BN_num_bits(rsa->n) : 0);
 #endif /* HAVE_OPAQUE_RSA_DSA_DH */
           push_certinfo("RSA Public Key", i);
           print_pubkey_BN(rsa, n, i);
@@ -661,7 +665,7 @@ CURLcode Curl_ossl_certchain(struct Curl_easy *data, SSL *ssl)
 #define BIO_set_shutdown(x,v)      ((x)->shutdown=(v))
 #endif /* USE_PRE_1_1_API */
 
-static int bio_cf_create(BIO *bio)
+static int ossl_bio_cf_create(BIO *bio)
 {
   BIO_set_shutdown(bio, 1);
   BIO_set_init(bio, 1);
@@ -672,14 +676,14 @@ static int bio_cf_create(BIO *bio)
   return 1;
 }
 
-static int bio_cf_destroy(BIO *bio)
+static int ossl_bio_cf_destroy(BIO *bio)
 {
   if(!bio)
     return 0;
   return 1;
 }
 
-static long bio_cf_ctrl(BIO *bio, int cmd, long num, void *ptr)
+static long ossl_bio_cf_ctrl(BIO *bio, int cmd, long num, void *ptr)
 {
   struct Curl_cfilter *cf = BIO_get_data(bio);
   long ret = 1;
@@ -713,22 +717,21 @@ static long bio_cf_ctrl(BIO *bio, int cmd, long num, void *ptr)
   return ret;
 }
 
-static int bio_cf_out_write(BIO *bio, const char *buf, int blen)
+static int ossl_bio_cf_out_write(BIO *bio, const char *buf, int blen)
 {
   struct Curl_cfilter *cf = BIO_get_data(bio);
   struct ssl_connect_data *connssl = cf->ctx;
-  struct ossl_ssl_backend_data *backend =
-    (struct ossl_ssl_backend_data *)connssl->backend;
+  struct ossl_ctx *octx = (struct ossl_ctx *)connssl->backend;
   struct Curl_easy *data = CF_DATA_CURRENT(cf);
   ssize_t nwritten;
   CURLcode result = CURLE_SEND_ERROR;
 
   DEBUGASSERT(data);
   nwritten = Curl_conn_cf_send(cf->next, data, buf, blen, &result);
-  CURL_TRC_CF(data, cf, "bio_cf_out_write(len=%d) -> %d, err=%d",
+  CURL_TRC_CF(data, cf, "ossl_bio_cf_out_write(len=%d) -> %d, err=%d",
               blen, (int)nwritten, result);
   BIO_clear_retry_flags(bio);
-  backend->io_result = result;
+  octx->io_result = result;
   if(nwritten < 0) {
     if(CURLE_AGAIN == result)
       BIO_set_retry_write(bio);
@@ -736,12 +739,11 @@ static int bio_cf_out_write(BIO *bio, const char *buf, int blen)
   return (int)nwritten;
 }
 
-static int bio_cf_in_read(BIO *bio, char *buf, int blen)
+static int ossl_bio_cf_in_read(BIO *bio, char *buf, int blen)
 {
   struct Curl_cfilter *cf = BIO_get_data(bio);
   struct ssl_connect_data *connssl = cf->ctx;
-  struct ossl_ssl_backend_data *backend =
-    (struct ossl_ssl_backend_data *)connssl->backend;
+  struct ossl_ctx *octx = (struct ossl_ctx *)connssl->backend;
   struct Curl_easy *data = CF_DATA_CURRENT(cf);
   ssize_t nread;
   CURLcode result = CURLE_RECV_ERROR;
@@ -752,24 +754,27 @@ static int bio_cf_in_read(BIO *bio, char *buf, int blen)
     return 0;
 
   nread = Curl_conn_cf_recv(cf->next, data, buf, blen, &result);
-  CURL_TRC_CF(data, cf, "bio_cf_in_read(len=%d) -> %d, err=%d",
+  CURL_TRC_CF(data, cf, "ossl_bio_cf_in_read(len=%d) -> %d, err=%d",
               blen, (int)nread, result);
   BIO_clear_retry_flags(bio);
-  backend->io_result = result;
+  octx->io_result = result;
   if(nread < 0) {
     if(CURLE_AGAIN == result)
       BIO_set_retry_read(bio);
   }
+  else if(nread == 0) {
+    connssl->peer_closed = TRUE;
+  }
 
   /* Before returning server replies to the SSL instance, we need
    * to have setup the x509 store or verification will fail. */
-  if(!backend->x509_store_setup) {
-    result = Curl_ssl_setup_x509_store(cf, data, backend->ctx);
+  if(!octx->x509_store_setup) {
+    result = Curl_ssl_setup_x509_store(cf, data, octx->ssl_ctx);
     if(result) {
-      backend->io_result = result;
+      octx->io_result = result;
       return -1;
     }
-    backend->x509_store_setup = TRUE;
+    octx->x509_store_setup = TRUE;
   }
 
   return (int)nread;
@@ -777,42 +782,42 @@ static int bio_cf_in_read(BIO *bio, char *buf, int blen)
 
 #if USE_PRE_1_1_API
 
-static BIO_METHOD bio_cf_meth_1_0 = {
+static BIO_METHOD ossl_bio_cf_meth_1_0 = {
   BIO_TYPE_MEM,
   "OpenSSL CF BIO",
-  bio_cf_out_write,
-  bio_cf_in_read,
+  ossl_bio_cf_out_write,
+  ossl_bio_cf_in_read,
   NULL,                    /* puts is never called */
   NULL,                    /* gets is never called */
-  bio_cf_ctrl,
-  bio_cf_create,
-  bio_cf_destroy,
+  ossl_bio_cf_ctrl,
+  ossl_bio_cf_create,
+  ossl_bio_cf_destroy,
   NULL
 };
 
-static BIO_METHOD *bio_cf_method_create(void)
+static BIO_METHOD *ossl_bio_cf_method_create(void)
 {
-  return &bio_cf_meth_1_0;
+  return &ossl_bio_cf_meth_1_0;
 }
 
-#define bio_cf_method_free(m) Curl_nop_stmt
+#define ossl_bio_cf_method_free(m) Curl_nop_stmt
 
 #else
 
-static BIO_METHOD *bio_cf_method_create(void)
+static BIO_METHOD *ossl_bio_cf_method_create(void)
 {
   BIO_METHOD *m = BIO_meth_new(BIO_TYPE_MEM, "OpenSSL CF BIO");
   if(m) {
-    BIO_meth_set_write(m, &bio_cf_out_write);
-    BIO_meth_set_read(m, &bio_cf_in_read);
-    BIO_meth_set_ctrl(m, &bio_cf_ctrl);
-    BIO_meth_set_create(m, &bio_cf_create);
-    BIO_meth_set_destroy(m, &bio_cf_destroy);
+    BIO_meth_set_write(m, &ossl_bio_cf_out_write);
+    BIO_meth_set_read(m, &ossl_bio_cf_in_read);
+    BIO_meth_set_ctrl(m, &ossl_bio_cf_ctrl);
+    BIO_meth_set_create(m, &ossl_bio_cf_create);
+    BIO_meth_set_destroy(m, &ossl_bio_cf_destroy);
   }
   return m;
 }
 
-static void bio_cf_method_free(BIO_METHOD *m)
+static void ossl_bio_cf_method_free(BIO_METHOD *m)
 {
   if(m)
     BIO_meth_free(m);
@@ -945,8 +950,9 @@ static char *ossl_strerror(unsigned long error, char *buf, size_t size)
 #endif
 
   if(!*buf) {
-    strncpy(buf, (error ? "Unknown error" : "No error"), size);
-    buf[size - 1] = '\0';
+    const char *msg = error ? "Unknown error" : "No error";
+    if(strlen(msg) < size)
+      strcpy(buf, msg);
   }
 
   return buf;
@@ -1078,6 +1084,7 @@ static int ssl_ui_reader(UI *ui, UI_STRING *uis)
       UI_set_result(ui, uis, password);
       return 1;
     }
+    FALLTHROUGH();
   default:
     break;
   }
@@ -1096,6 +1103,7 @@ static int ssl_ui_writer(UI *ui, UI_STRING *uis)
        (UI_get_input_flags(uis) & UI_INPUT_FLAG_DEFAULT_PWD)) {
       return 1;
     }
+    FALLTHROUGH();
   default:
     break;
   }
@@ -1513,7 +1521,7 @@ int cert_stuff(struct Curl_easy *data,
     case SSL_FILETYPE_PEM:
       if(cert_done)
         break;
-      /* FALLTHROUGH */
+      FALLTHROUGH();
     case SSL_FILETYPE_ASN1:
       cert_use_result = key_blob ?
         SSL_CTX_use_PrivateKey_blob(ctx, key_blob, file_type, key_passwd) :
@@ -1551,11 +1559,9 @@ int cert_stuff(struct Curl_easy *data,
         UI_method_set_closer(ui_method, UI_method_get_closer(UI_OpenSSL()));
         UI_method_set_reader(ui_method, ssl_ui_reader);
         UI_method_set_writer(ui_method, ssl_ui_writer);
-        /* the typecast below was added to please mingw32 */
-        priv_key = (EVP_PKEY *)
-          ENGINE_load_private_key(data->state.engine, key_file,
-                                  ui_method,
-                                  key_passwd);
+        priv_key = ENGINE_load_private_key(data->state.engine, key_file,
+                                           ui_method,
+                                           key_passwd);
         UI_destroy_method(ui_method);
         if(!priv_key) {
           failf(data, "failed to load private key from crypto engine");
@@ -1745,7 +1751,7 @@ static int ossl_init(void)
 static void ossl_cleanup(void)
 {
 #if (OPENSSL_VERSION_NUMBER >= 0x10100000L) &&  \
-  !defined(LIBRESSL_VERSION_NUMBER)
+  (!defined(LIBRESSL_VERSION_NUMBER) || LIBRESSL_VERSION_NUMBER >= 0x2070000fL)
   /* OpenSSL 1.1 deprecates all these cleanup functions and
      turns them into no-ops in OpenSSL 1.0 compatibility mode */
 #else
@@ -1870,37 +1876,91 @@ static struct curl_slist *ossl_engines_list(struct Curl_easy *data)
 static void ossl_close(struct Curl_cfilter *cf, struct Curl_easy *data)
 {
   struct ssl_connect_data *connssl = cf->ctx;
-  struct ossl_ssl_backend_data *backend =
-    (struct ossl_ssl_backend_data *)connssl->backend;
+  struct ossl_ctx *octx = (struct ossl_ctx *)connssl->backend;
 
   (void)data;
-  DEBUGASSERT(backend);
+  DEBUGASSERT(octx);
+
+  if(octx->ssl) {
+    /* Send the TLS shutdown if we are still connected *and* if
+     * the peer did not already close the connection. */
+    if(cf->next && cf->next->connected && !connssl->peer_closed) {
+      char buf[1024];
+      int nread, err;
+      long sslerr;
 
-  if(backend->handle) {
-    if(cf->next && cf->next->connected) {
-      char buf[32];
       /* Maybe the server has already sent a close notify alert.
          Read it to avoid an RST on the TCP connection. */
-      (void)SSL_read(backend->handle, buf, (int)sizeof(buf));
-
-      (void)SSL_shutdown(backend->handle);
-
       ERR_clear_error();
+      nread = SSL_read(octx->ssl, buf, (int)sizeof(buf));
+      err = SSL_get_error(octx->ssl, nread);
+      if(!nread && err == SSL_ERROR_ZERO_RETURN) {
+        CURLcode result;
+        ssize_t n;
+        size_t blen = sizeof(buf);
+        CURL_TRC_CF(data, cf, "peer has shutdown TLS");
+        /* SSL_read() will not longer touch the socket, let's receive
+         * directly from the next filter to see if the underlying
+         * connection has also been closed. */
+        n = Curl_conn_cf_recv(cf->next, data, buf, blen, &result);
+        if(!n) {
+          connssl->peer_closed = TRUE;
+          CURL_TRC_CF(data, cf, "peer closed connection");
+        }
+      }
+      ERR_clear_error();
+      if(connssl->peer_closed) {
+        /* As the peer closed, we do not expect it to read anything more we
+         * may send. It may be harmful, leading to TCP RST and delaying
+         * a lingering close. Just leave. */
+        CURL_TRC_CF(data, cf, "not from sending TLS shutdown on "
+                    "connection closed by peer");
+      }
+      else if(SSL_shutdown(octx->ssl) == 1) {
+        CURL_TRC_CF(data, cf, "SSL shutdown finished");
+      }
+      else {
+        nread = SSL_read(octx->ssl, buf, (int)sizeof(buf));
+        err = SSL_get_error(octx->ssl, nread);
+        switch(err) {
+        case SSL_ERROR_NONE: /* this is not an error */
+        case SSL_ERROR_ZERO_RETURN: /* no more data */
+          CURL_TRC_CF(data, cf, "SSL shutdown, EOF from server");
+          break;
+        case SSL_ERROR_WANT_READ:
+          /* SSL has send its notify and now wants to read the reply
+           * from the server. We are not really interested in that. */
+          CURL_TRC_CF(data, cf, "SSL shutdown sent");
+          break;
+        case SSL_ERROR_WANT_WRITE:
+          CURL_TRC_CF(data, cf, "SSL shutdown send blocked");
+          break;
+        default:
+          sslerr = ERR_get_error();
+          CURL_TRC_CF(data, cf, "SSL shutdown, error: '%s', errno %d",
+                      (sslerr ?
+                       ossl_strerror(sslerr, buf, sizeof(buf)) :
+                       SSL_ERROR_to_str(err)),
+                      SOCKERRNO);
+          break;
+        }
+      }
 
-      SSL_set_connect_state(backend->handle);
+      ERR_clear_error();
+      SSL_set_connect_state(octx->ssl);
     }
 
-    SSL_free(backend->handle);
-    backend->handle = NULL;
+    SSL_free(octx->ssl);
+    octx->ssl = NULL;
   }
-  if(backend->ctx) {
-    SSL_CTX_free(backend->ctx);
-    backend->ctx = NULL;
-    backend->x509_store_setup = FALSE;
+  if(octx->ssl_ctx) {
+    SSL_CTX_free(octx->ssl_ctx);
+    octx->ssl_ctx = NULL;
+    octx->x509_store_setup = FALSE;
   }
-  if(backend->bio_method) {
-    bio_cf_method_free(backend->bio_method);
-    backend->bio_method = NULL;
+  if(octx->bio_method) {
+    ossl_bio_cf_method_free(octx->bio_method);
+    octx->bio_method = NULL;
   }
 }
 
@@ -1920,11 +1980,10 @@ static int ossl_shutdown(struct Curl_cfilter *cf,
   int buffsize;
   int err;
   bool done = FALSE;
-  struct ossl_ssl_backend_data *backend =
-    (struct ossl_ssl_backend_data *)connssl->backend;
+  struct ossl_ctx *octx = (struct ossl_ctx *)connssl->backend;
   int loop = 10;
 
-  DEBUGASSERT(backend);
+  DEBUGASSERT(octx);
 
 #ifndef CURL_DISABLE_FTP
   /* This has only been tested on the proftpd server, and the mod_tls code
@@ -1933,10 +1992,10 @@ static int ossl_shutdown(struct Curl_cfilter *cf,
      we do not send one. Let's hope other servers do the same... */
 
   if(data->set.ftp_ccc == CURLFTPSSL_CCC_ACTIVE)
-    (void)SSL_shutdown(backend->handle);
+    (void)SSL_shutdown(octx->ssl);
 #endif
 
-  if(backend->handle) {
+  if(octx->ssl) {
     buffsize = (int)sizeof(buf);
     while(!done && loop--) {
       int what = SOCKET_READABLE(Curl_conn_cf_get_socket(cf, data),
@@ -1946,8 +2005,8 @@ static int ossl_shutdown(struct Curl_cfilter *cf,
 
         /* Something to read, let's do it and hope that it is the close
            notify alert from the server */
-        nread = SSL_read(backend->handle, buf, buffsize);
-        err = SSL_get_error(backend->handle, nread);
+        nread = SSL_read(octx->ssl, buf, buffsize);
+        err = SSL_get_error(octx->ssl, nread);
 
         switch(err) {
         case SSL_ERROR_NONE: /* this is not an error */
@@ -1992,7 +2051,7 @@ static int ossl_shutdown(struct Curl_cfilter *cf,
 
     if(data->set.verbose) {
 #ifdef HAVE_SSL_GET_SHUTDOWN
-      switch(SSL_get_shutdown(backend->handle)) {
+      switch(SSL_get_shutdown(octx->ssl)) {
       case SSL_SENT_SHUTDOWN:
         infof(data, "SSL_get_shutdown() returned SSL_SENT_SHUTDOWN");
         break;
@@ -2007,16 +2066,17 @@ static int ossl_shutdown(struct Curl_cfilter *cf,
 #endif
     }
 
-    SSL_free(backend->handle);
-    backend->handle = NULL;
+    SSL_free(octx->ssl);
+    octx->ssl = NULL;
   }
   return retval;
 }
 
-static void ossl_session_free(void *ptr)
+static void ossl_session_free(void *sessionid, size_t idsize)
 {
   /* free the ID */
-  SSL_SESSION_free(ptr);
+  (void)idsize;
+  SSL_SESSION_free(sessionid);
 }
 
 /*
@@ -2068,22 +2128,6 @@ static bool subj_alt_hostcheck(struct Curl_easy *data,
   return FALSE;
 }
 
-static CURLcode
-ossl_verifyhost(struct Curl_easy *data, struct connectdata *conn,
-                X509 *server_cert, const char *hostname,
-                const char *dispname);
-
-CURLcode Curl_ossl_verifyhost(struct Curl_easy *data, struct connectdata *conn,
-                              X509 *server_cert)
-{
-  const char *hostname, *dispname;
-  int port;
-
-  (void)conn;
-  Curl_conn_get_host(data, FIRSTSOCKET, &hostname, &dispname, &port);
-  return ossl_verifyhost(data, conn, server_cert, hostname, dispname);
-}
-
 /* Quote from RFC2818 section 3.1 "Server Identity"
 
    If a subjectAltName extension of type dNSName is present, that MUST
@@ -2106,45 +2150,48 @@ CURLcode Curl_ossl_verifyhost(struct Curl_easy *data, struct connectdata *conn,
 
    This function is now used from ngtcp2 (QUIC) as well.
 */
-static CURLcode
-ossl_verifyhost(struct Curl_easy *data, struct connectdata *conn,
-                X509 *server_cert, const char *hostname,
-                const char *dispname)
+CURLcode Curl_ossl_verifyhost(struct Curl_easy *data, struct connectdata *conn,
+                              struct ssl_peer *peer, X509 *server_cert)
 {
   bool matched = FALSE;
-  int target = GEN_DNS; /* target type, GEN_DNS or GEN_IPADD */
+  int target; /* target type, GEN_DNS or GEN_IPADD */
   size_t addrlen = 0;
   STACK_OF(GENERAL_NAME) *altnames;
-#ifdef ENABLE_IPV6
+#ifdef USE_IPV6
   struct in6_addr addr;
 #else
   struct in_addr addr;
 #endif
   CURLcode result = CURLE_OK;
   bool dNSName = FALSE; /* if a dNSName field exists in the cert */
-  bool iPAddress = FALSE; /* if a iPAddress field exists in the cert */
+  bool iPAddress = FALSE; /* if an iPAddress field exists in the cert */
   size_t hostlen;
 
   (void)conn;
-  hostlen = strlen(hostname);
-
-#ifndef ENABLE_IPV6
-  /* Silence compiler warnings for unused params */
-  (void) conn;
-#endif
-
-#ifdef ENABLE_IPV6
-  if(conn->bits.ipv6_ip &&
-     Curl_inet_pton(AF_INET6, hostname, &addr)) {
+  hostlen = strlen(peer->hostname);
+  switch(peer->type) {
+  case CURL_SSL_PEER_IPV4:
+    if(!Curl_inet_pton(AF_INET, peer->hostname, &addr))
+      return CURLE_PEER_FAILED_VERIFICATION;
+    target = GEN_IPADD;
+    addrlen = sizeof(struct in_addr);
+    break;
+#ifdef USE_IPV6
+  case CURL_SSL_PEER_IPV6:
+    if(!Curl_inet_pton(AF_INET6, peer->hostname, &addr))
+      return CURLE_PEER_FAILED_VERIFICATION;
     target = GEN_IPADD;
     addrlen = sizeof(struct in6_addr);
-  }
-  else
+    break;
 #endif
-    if(Curl_inet_pton(AF_INET, hostname, &addr)) {
-      target = GEN_IPADD;
-      addrlen = sizeof(struct in_addr);
-    }
+  case CURL_SSL_PEER_DNS:
+    target = GEN_DNS;
+    break;
+  default:
+    DEBUGASSERT(0);
+    failf(data, "unexpected ssl peer type: %d", peer->type);
+    return CURLE_PEER_FAILED_VERIFICATION;
+  }
 
   /* get a "list" of alternative names */
   altnames = X509_get_ext_d2i(server_cert, NID_subject_alt_name, NULL, NULL);
@@ -2194,9 +2241,9 @@ ossl_verifyhost(struct Curl_easy *data, struct connectdata *conn,
           if((altlen == strlen(altptr)) &&
              /* if this isn't true, there was an embedded zero in the name
                 string and we cannot match it. */
-             subj_alt_hostcheck(data,
-                                altptr,
-                                altlen, hostname, hostlen, dispname)) {
+             subj_alt_hostcheck(data, altptr, altlen,
+                                peer->hostname, hostlen,
+                                peer->dispname)) {
             dnsmatched = TRUE;
           }
           break;
@@ -2208,7 +2255,7 @@ ossl_verifyhost(struct Curl_easy *data, struct connectdata *conn,
             ipmatched = TRUE;
             infof(data,
                   " subjectAltName: host \"%s\" matched cert's IP address!",
-                  dispname);
+                  peer->dispname);
           }
           break;
         }
@@ -2224,9 +2271,12 @@ ossl_verifyhost(struct Curl_easy *data, struct connectdata *conn,
     /* an alternative name matched */
     ;
   else if(dNSName || iPAddress) {
-    infof(data, " subjectAltName does not match %s", dispname);
+    const char *tname = (peer->type == CURL_SSL_PEER_DNS) ? "host name" :
+                        (peer->type == CURL_SSL_PEER_IPV4) ?
+                        "ipv4 address" : "ipv6 address";
+    infof(data, " subjectAltName does not match %s %s", tname, peer->dispname);
     failf(data, "SSL: no alternative certificate subject name matches "
-          "target host name '%s'", dispname);
+          "target %s '%s'", tname, peer->dispname);
     result = CURLE_PEER_FAILED_VERIFICATION;
   }
   else {
@@ -2290,9 +2340,9 @@ ossl_verifyhost(struct Curl_easy *data, struct connectdata *conn,
       result = CURLE_PEER_FAILED_VERIFICATION;
     }
     else if(!Curl_cert_hostcheck((const char *)peer_CN,
-                                 peerlen, hostname, hostlen)) {
+                                 peerlen, peer->hostname, hostlen)) {
       failf(data, "SSL: certificate subject name '%s' does not match "
-            "target host name '%s'", peer_CN, dispname);
+            "target host name '%s'", peer_CN, peer->dispname);
       result = CURLE_PEER_FAILED_VERIFICATION;
     }
     else {
@@ -2323,8 +2373,7 @@ static CURLcode verifystatus(struct Curl_cfilter *cf,
   OCSP_BASICRESP *br = NULL;
   X509_STORE     *st = NULL;
   STACK_OF(X509) *ch = NULL;
-  struct ossl_ssl_backend_data *backend =
-    (struct ossl_ssl_backend_data *)connssl->backend;
+  struct ossl_ctx *octx = (struct ossl_ctx *)connssl->backend;
   X509 *cert;
   OCSP_CERTID *id = NULL;
   int cert_status, crl_reason;
@@ -2332,9 +2381,9 @@ static CURLcode verifystatus(struct Curl_cfilter *cf,
   int ret;
   long len;
 
-  DEBUGASSERT(backend);
+  DEBUGASSERT(octx);
 
-  len = SSL_get_tlsext_status_ocsp_resp(backend->handle, &status);
+  len = SSL_get_tlsext_status_ocsp_resp(octx->ssl, &status);
 
   if(!status) {
     failf(data, "No OCSP response received");
@@ -2364,13 +2413,13 @@ static CURLcode verifystatus(struct Curl_cfilter *cf,
     goto end;
   }
 
-  ch = SSL_get_peer_cert_chain(backend->handle);
+  ch = SSL_get_peer_cert_chain(octx->ssl);
   if(!ch) {
     failf(data, "Could not get peer certificate chain");
     result = CURLE_SSL_INVALIDCERTSTATUS;
     goto end;
   }
-  st = SSL_CTX_get_cert_store(backend->ctx);
+  st = SSL_CTX_get_cert_store(octx->ssl_ctx);
 
 #if ((OPENSSL_VERSION_NUMBER <= 0x1000201fL) /* Fixed after 1.0.2a */ || \
      (defined(LIBRESSL_VERSION_NUMBER) &&                               \
@@ -2407,7 +2456,7 @@ static CURLcode verifystatus(struct Curl_cfilter *cf,
   }
 
   /* Compute the certificate's ID */
-  cert = SSL_get1_peer_certificate(backend->handle);
+  cert = SSL_get1_peer_certificate(octx->ssl);
   if(!cert) {
     failf(data, "Error getting peer certificate");
     result = CURLE_SSL_INVALIDCERTSTATUS;
@@ -2701,12 +2750,6 @@ static void ossl_trace(int direction, int ssl_ver, int content_type,
 #ifdef USE_OPENSSL
 /* ====================================================== */
 
-#ifdef SSL_CTRL_SET_TLSEXT_HOSTNAME
-#  define use_sni(x)  sni = (x)
-#else
-#  define use_sni(x)  Curl_nop_stmt
-#endif
-
 /* Check for OpenSSL 1.0.2 which has ALPN support. */
 #undef HAS_ALPN
 #if OPENSSL_VERSION_NUMBER >= 0x10002000L       \
@@ -2828,10 +2871,9 @@ ossl_set_ssl_version_min_max_legacy(ctx_option_t *ctx_options,
 #ifdef TLS1_3_VERSION
   {
     struct ssl_connect_data *connssl = cf->ctx;
-    struct ossl_ssl_backend_data *backend =
-      (struct ossl_ssl_backend_data *)connssl->backend;
-    DEBUGASSERT(backend);
-    SSL_CTX_set_max_proto_version(backend->ctx, TLS1_3_VERSION);
+    struct ossl_ctx *octx = (struct ossl_ctx *)connssl->backend;
+    DEBUGASSERT(octx);
+    SSL_CTX_set_max_proto_version(octx->ssl_ctx, TLS1_3_VERSION);
     *ctx_options |= SSL_OP_NO_TLSv1_2;
   }
 #else
@@ -2839,7 +2881,7 @@ ossl_set_ssl_version_min_max_legacy(ctx_option_t *ctx_options,
   failf(data, OSSL_PACKAGE " was built without TLS 1.3 support");
   return CURLE_NOT_BUILT_IN;
 #endif
-  /* FALLTHROUGH */
+  FALLTHROUGH();
   case CURL_SSLVERSION_TLSv1_2:
 #if OPENSSL_VERSION_NUMBER >= 0x1000100FL
     *ctx_options |= SSL_OP_NO_TLSv1_1;
@@ -2847,7 +2889,7 @@ ossl_set_ssl_version_min_max_legacy(ctx_option_t *ctx_options,
     failf(data, OSSL_PACKAGE " was built without TLS 1.2 support");
     return CURLE_NOT_BUILT_IN;
 #endif
-    /* FALLTHROUGH */
+    FALLTHROUGH();
   case CURL_SSLVERSION_TLSv1_1:
 #if OPENSSL_VERSION_NUMBER >= 0x1000100FL
     *ctx_options |= SSL_OP_NO_TLSv1;
@@ -2855,7 +2897,7 @@ ossl_set_ssl_version_min_max_legacy(ctx_option_t *ctx_options,
     failf(data, OSSL_PACKAGE " was built without TLS 1.1 support");
     return CURLE_NOT_BUILT_IN;
 #endif
-    /* FALLTHROUGH */
+    FALLTHROUGH();
   case CURL_SSLVERSION_TLSv1_0:
   case CURL_SSLVERSION_TLSv1:
     break;
@@ -2866,12 +2908,12 @@ ossl_set_ssl_version_min_max_legacy(ctx_option_t *ctx_options,
 #if OPENSSL_VERSION_NUMBER >= 0x1000100FL
     *ctx_options |= SSL_OP_NO_TLSv1_1;
 #endif
-    /* FALLTHROUGH */
+    FALLTHROUGH();
   case CURL_SSLVERSION_MAX_TLSv1_1:
 #if OPENSSL_VERSION_NUMBER >= 0x1000100FL
     *ctx_options |= SSL_OP_NO_TLSv1_2;
 #endif
-    /* FALLTHROUGH */
+    FALLTHROUGH();
   case CURL_SSLVERSION_MAX_TLSv1_2:
 #ifdef TLS1_3_VERSION
     *ctx_options |= SSL_OP_NO_TLSv1_3;
@@ -2889,61 +2931,64 @@ ossl_set_ssl_version_min_max_legacy(ctx_option_t *ctx_options,
 }
 #endif
 
-/* The "new session" callback must return zero if the session can be removed
- * or non-zero if the session has been put into the session cache.
- */
-static int ossl_new_session_cb(SSL *ssl, SSL_SESSION *ssl_sessionid)
+CURLcode Curl_ossl_add_session(struct Curl_cfilter *cf,
+                               struct Curl_easy *data,
+                               const struct ssl_peer *peer,
+                               SSL_SESSION *session)
 {
-  int res = 0;
-  struct Curl_easy *data;
-  struct Curl_cfilter *cf;
   const struct ssl_config_data *config;
-  struct ssl_connect_data *connssl;
   bool isproxy;
+  bool added = FALSE;
 
-  cf = (struct Curl_cfilter*) SSL_get_app_data(ssl);
-  connssl = cf? cf->ctx : NULL;
-  data = connssl? CF_DATA_CURRENT(cf) : NULL;
-  /* The sockindex has been stored as a pointer to an array element */
   if(!cf || !data)
-    return 0;
+    goto out;
 
   isproxy = Curl_ssl_cf_is_proxy(cf);
 
   config = Curl_ssl_cf_get_config(cf, data);
   if(config->primary.sessionid) {
     bool incache;
-    bool added = FALSE;
-    void *old_ssl_sessionid = NULL;
+    void *old_session = NULL;
 
     Curl_ssl_sessionid_lock(data);
     if(isproxy)
       incache = FALSE;
     else
-      incache = !(Curl_ssl_getsessionid(cf, data, &old_ssl_sessionid, NULL));
-    if(incache) {
-      if(old_ssl_sessionid != ssl_sessionid) {
-        infof(data, "old SSL session ID is stale, removing");
-        Curl_ssl_delsessionid(data, old_ssl_sessionid);
-        incache = FALSE;
-      }
+      incache = !(Curl_ssl_getsessionid(cf, data, peer,
+                                        &old_session, NULL));
+    if(incache && (old_session != session)) {
+      infof(data, "old SSL session ID is stale, removing");
+      Curl_ssl_delsessionid(data, old_session);
+      incache = FALSE;
     }
 
     if(!incache) {
-      if(!Curl_ssl_addsessionid(cf, data, ssl_sessionid,
-                                0 /* unknown size */, &added)) {
-        if(added) {
-          /* the session has been put into the session cache */
-          res = 1;
-        }
-      }
-      else
-        failf(data, "failed to store ssl session");
+      added = TRUE;
+      Curl_ssl_addsessionid(cf, data, peer, session, 0, ossl_session_free);
     }
     Curl_ssl_sessionid_unlock(data);
   }
 
-  return res;
+out:
+  if(!added)
+    ossl_session_free(session, 0);
+  return CURLE_OK;
+}
+
+/* The "new session" callback must return zero if the session can be removed
+ * or non-zero if the session has been put into the session cache.
+ */
+static int ossl_new_session_cb(SSL *ssl, SSL_SESSION *ssl_sessionid)
+{
+  struct Curl_cfilter *cf;
+  struct Curl_easy *data;
+  struct ssl_connect_data *connssl;
+
+  cf = (struct Curl_cfilter*) SSL_get_app_data(ssl);
+  connssl = cf? cf->ctx : NULL;
+  data = connssl? CF_DATA_CURRENT(cf) : NULL;
+  Curl_ossl_add_session(cf, data, &connssl->peer, ssl_sessionid);
+  return 1;
 }
 
 static CURLcode load_cacert_from_memory(X509_STORE *store,
@@ -3002,6 +3047,151 @@ static CURLcode load_cacert_from_memory(X509_STORE *store,
   return (count > 0) ? CURLE_OK : CURLE_SSL_CACERT_BADFILE;
 }
 
+#if defined(USE_WIN32_CRYPTO)
+static CURLcode import_windows_cert_store(struct Curl_easy *data,
+                                          const char *name,
+                                          X509_STORE *store,
+                                          bool *imported)
+{
+  CURLcode result = CURLE_OK;
+  HCERTSTORE hStore;
+
+  *imported = false;
+
+  hStore = CertOpenSystemStoreA(0, name);
+  if(hStore) {
+    PCCERT_CONTEXT pContext = NULL;
+    /* The array of enhanced key usage OIDs will vary per certificate and
+       is declared outside of the loop so that rather than malloc/free each
+       iteration we can grow it with realloc, when necessary. */
+    CERT_ENHKEY_USAGE *enhkey_usage = NULL;
+    DWORD enhkey_usage_size = 0;
+
+    /* This loop makes a best effort to import all valid certificates from
+       the MS root store. If a certificate cannot be imported it is
+       skipped. 'result' is used to store only hard-fail conditions (such
+       as out of memory) that cause an early break. */
+    result = CURLE_OK;
+    for(;;) {
+      X509 *x509;
+      FILETIME now;
+      BYTE key_usage[2];
+      DWORD req_size;
+      const unsigned char *encoded_cert;
+#if defined(DEBUGBUILD) && !defined(CURL_DISABLE_VERBOSE_STRINGS)
+      char cert_name[256];
+#endif
+
+      pContext = CertEnumCertificatesInStore(hStore, pContext);
+      if(!pContext)
+        break;
+
+#if defined(DEBUGBUILD) && !defined(CURL_DISABLE_VERBOSE_STRINGS)
+      if(!CertGetNameStringA(pContext, CERT_NAME_SIMPLE_DISPLAY_TYPE, 0,
+                             NULL, cert_name, sizeof(cert_name))) {
+        strcpy(cert_name, "Unknown");
+      }
+      infof(data, "SSL: Checking cert \"%s\"", cert_name);
+#endif
+      encoded_cert = (const unsigned char *)pContext->pbCertEncoded;
+      if(!encoded_cert)
+        continue;
+
+      GetSystemTimeAsFileTime(&now);
+      if(CompareFileTime(&pContext->pCertInfo->NotBefore, &now) > 0 ||
+         CompareFileTime(&now, &pContext->pCertInfo->NotAfter) > 0)
+        continue;
+
+      /* If key usage exists check for signing attribute */
+      if(CertGetIntendedKeyUsage(pContext->dwCertEncodingType,
+                                 pContext->pCertInfo,
+                                 key_usage, sizeof(key_usage))) {
+        if(!(key_usage[0] & CERT_KEY_CERT_SIGN_KEY_USAGE))
+          continue;
+      }
+      else if(GetLastError())
+        continue;
+
+      /* If enhanced key usage exists check for server auth attribute.
+       *
+       * Note "In a Microsoft environment, a certificate might also have
+       * EKU extended properties that specify valid uses for the
+       * certificate."  The call below checks both, and behavior varies
+       * depending on what is found. For more details see
+       * CertGetEnhancedKeyUsage doc.
+       */
+      if(CertGetEnhancedKeyUsage(pContext, 0, NULL, &req_size)) {
+        if(req_size && req_size > enhkey_usage_size) {
+          void *tmp = realloc(enhkey_usage, req_size);
+
+          if(!tmp) {
+            failf(data, "SSL: Out of memory allocating for OID list");
+            result = CURLE_OUT_OF_MEMORY;
+            break;
+          }
+
+          enhkey_usage = (CERT_ENHKEY_USAGE *)tmp;
+          enhkey_usage_size = req_size;
+        }
+
+        if(CertGetEnhancedKeyUsage(pContext, 0, enhkey_usage, &req_size)) {
+          if(!enhkey_usage->cUsageIdentifier) {
+            /* "If GetLastError returns CRYPT_E_NOT_FOUND, the certificate
+               is good for all uses. If it returns zero, the certificate
+               has no valid uses." */
+            if((HRESULT)GetLastError() != CRYPT_E_NOT_FOUND)
+              continue;
+          }
+          else {
+            DWORD i;
+            bool found = false;
+
+            for(i = 0; i < enhkey_usage->cUsageIdentifier; ++i) {
+              if(!strcmp("1.3.6.1.5.5.7.3.1" /* OID server auth */,
+                         enhkey_usage->rgpszUsageIdentifier[i])) {
+                found = true;
+                break;
+              }
+            }
+
+            if(!found)
+              continue;
+          }
+        }
+        else
+          continue;
+      }
+      else
+        continue;
+
+      x509 = d2i_X509(NULL, &encoded_cert, pContext->cbCertEncoded);
+      if(!x509)
+        continue;
+
+      /* Try to import the certificate. This may fail for legitimate
+         reasons such as duplicate certificate, which is allowed by MS but
+         not OpenSSL. */
+      if(X509_STORE_add_cert(store, x509) == 1) {
+#if defined(DEBUGBUILD) && !defined(CURL_DISABLE_VERBOSE_STRINGS)
+        infof(data, "SSL: Imported cert \"%s\"", cert_name);
+#endif
+        *imported = true;
+      }
+      X509_free(x509);
+    }
+
+    free(enhkey_usage);
+    CertFreeCertificateContext(pContext);
+    CertCloseStore(hStore, 0);
+
+    if(result)
+      return result;
+  }
+
+  return result;
+}
+#endif
+
 static CURLcode populate_x509_store(struct Curl_cfilter *cf,
                                     struct Curl_easy *data,
                                     X509_STORE *store)
@@ -3020,6 +3210,8 @@ static CURLcode populate_x509_store(struct Curl_cfilter *cf,
   bool imported_native_ca = false;
   bool imported_ca_info_blob = false;
 
+  CURL_TRC_CF(data, cf, "populate_x509_store, path=%s, blob=%d",
+              ssl_cafile? ssl_cafile : "none", !!ca_info_blob);
   if(!store)
     return CURLE_OUT_OF_MEMORY;
 
@@ -3031,140 +3223,25 @@ static CURLcode populate_x509_store(struct Curl_cfilter *cf,
        https://github.com/d3x0r/SACK/blob/master/src/netlib/ssl_layer.c#L1037
        https://datatracker.ietf.org/doc/html/rfc5280 */
     if(ssl_config->native_ca_store) {
-      HCERTSTORE hStore = CertOpenSystemStore(0, TEXT("ROOT"));
-
-      if(hStore) {
-        PCCERT_CONTEXT pContext = NULL;
-        /* The array of enhanced key usage OIDs will vary per certificate and
-           is declared outside of the loop so that rather than malloc/free each
-           iteration we can grow it with realloc, when necessary. */
-        CERT_ENHKEY_USAGE *enhkey_usage = NULL;
-        DWORD enhkey_usage_size = 0;
-
-        /* This loop makes a best effort to import all valid certificates from
-           the MS root store. If a certificate cannot be imported it is
-           skipped. 'result' is used to store only hard-fail conditions (such
-           as out of memory) that cause an early break. */
-        result = CURLE_OK;
-        for(;;) {
-          X509 *x509;
-          FILETIME now;
-          BYTE key_usage[2];
-          DWORD req_size;
-          const unsigned char *encoded_cert;
-#if defined(DEBUGBUILD) && !defined(CURL_DISABLE_VERBOSE_STRINGS)
-          char cert_name[256];
-#endif
-
-          pContext = CertEnumCertificatesInStore(hStore, pContext);
-          if(!pContext)
-            break;
-
-#if defined(DEBUGBUILD) && !defined(CURL_DISABLE_VERBOSE_STRINGS)
-          if(!CertGetNameStringA(pContext, CERT_NAME_SIMPLE_DISPLAY_TYPE, 0,
-                                 NULL, cert_name, sizeof(cert_name))) {
-            strcpy(cert_name, "Unknown");
-          }
-          infof(data, "SSL: Checking cert \"%s\"", cert_name);
-#endif
-          encoded_cert = (const unsigned char *)pContext->pbCertEncoded;
-          if(!encoded_cert)
-            continue;
-
-          GetSystemTimeAsFileTime(&now);
-          if(CompareFileTime(&pContext->pCertInfo->NotBefore, &now) > 0 ||
-             CompareFileTime(&now, &pContext->pCertInfo->NotAfter) > 0)
-            continue;
-
-          /* If key usage exists check for signing attribute */
-          if(CertGetIntendedKeyUsage(pContext->dwCertEncodingType,
-                                     pContext->pCertInfo,
-                                     key_usage, sizeof(key_usage))) {
-            if(!(key_usage[0] & CERT_KEY_CERT_SIGN_KEY_USAGE))
-              continue;
-          }
-          else if(GetLastError())
-            continue;
-
-          /* If enhanced key usage exists check for server auth attribute.
-           *
-           * Note "In a Microsoft environment, a certificate might also have
-           * EKU extended properties that specify valid uses for the
-           * certificate."  The call below checks both, and behavior varies
-           * depending on what is found. For more details see
-           * CertGetEnhancedKeyUsage doc.
-           */
-          if(CertGetEnhancedKeyUsage(pContext, 0, NULL, &req_size)) {
-            if(req_size && req_size > enhkey_usage_size) {
-              void *tmp = realloc(enhkey_usage, req_size);
-
-              if(!tmp) {
-                failf(data, "SSL: Out of memory allocating for OID list");
-                result = CURLE_OUT_OF_MEMORY;
-                break;
-              }
-
-              enhkey_usage = (CERT_ENHKEY_USAGE *)tmp;
-              enhkey_usage_size = req_size;
-            }
-
-            if(CertGetEnhancedKeyUsage(pContext, 0, enhkey_usage, &req_size)) {
-              if(!enhkey_usage->cUsageIdentifier) {
-                /* "If GetLastError returns CRYPT_E_NOT_FOUND, the certificate
-                   is good for all uses. If it returns zero, the certificate
-                   has no valid uses." */
-                if((HRESULT)GetLastError() != CRYPT_E_NOT_FOUND)
-                  continue;
-              }
-              else {
-                DWORD i;
-                bool found = false;
-
-                for(i = 0; i < enhkey_usage->cUsageIdentifier; ++i) {
-                  if(!strcmp("1.3.6.1.5.5.7.3.1" /* OID server auth */,
-                             enhkey_usage->rgpszUsageIdentifier[i])) {
-                    found = true;
-                    break;
-                  }
-                }
-
-                if(!found)
-                  continue;
-              }
-            }
-            else
-              continue;
-          }
-          else
-            continue;
-
-          x509 = d2i_X509(NULL, &encoded_cert, pContext->cbCertEncoded);
-          if(!x509)
-            continue;
-
-          /* Try to import the certificate. This may fail for legitimate
-             reasons such as duplicate certificate, which is allowed by MS but
-             not OpenSSL. */
-          if(X509_STORE_add_cert(store, x509) == 1) {
-#if defined(DEBUGBUILD) && !defined(CURL_DISABLE_VERBOSE_STRINGS)
-            infof(data, "SSL: Imported cert \"%s\"", cert_name);
-#endif
-            imported_native_ca = true;
-          }
-          X509_free(x509);
-        }
-
-        free(enhkey_usage);
-        CertFreeCertificateContext(pContext);
-        CertCloseStore(hStore, 0);
-
+      const char *storeNames[] = {
+        "ROOT",   /* Trusted Root Certification Authorities */
+        "CA"      /* Intermediate Certification Authorities */
+      };
+      size_t i;
+      for(i = 0; i < ARRAYSIZE(storeNames); ++i) {
+        bool imported = false;
+        result = import_windows_cert_store(data, storeNames[i], store,
+                                           &imported);
         if(result)
           return result;
+        if(imported) {
+          infof(data, "successfully imported Windows %s store", storeNames[i]);
+          imported_native_ca = true;
+        }
+        else
+          infof(data, "error importing Windows %s store, continuing anyway",
+                storeNames[i]);
       }
-      if(imported_native_ca)
-        infof(data, "successfully imported Windows CA store");
-      else
-        infof(data, "error importing Windows CA store, continuing anyway");
     }
 #endif
     if(ca_info_blob) {
@@ -3180,7 +3257,7 @@ static CURLcode populate_x509_store(struct Curl_cfilter *cf,
     }
 
     if(ssl_cafile || ssl_capath) {
-#if defined(OPENSSL_VERSION_MAJOR) && (OPENSSL_VERSION_MAJOR >= 3)
+#if (OPENSSL_VERSION_NUMBER >= 0x30000000L)
       /* OpenSSL 3.0.0 has deprecated SSL_CTX_load_verify_locations */
       if(ssl_cafile && !X509_STORE_load_file(store, ssl_cafile)) {
         if(!imported_native_ca && !imported_ca_info_blob) {
@@ -3306,9 +3383,10 @@ static bool cached_x509_store_different(
 static X509_STORE *get_cached_x509_store(struct Curl_cfilter *cf,
                                          const struct Curl_easy *data)
 {
-  struct Curl_multi *multi = data->multi_easy ? data->multi_easy : data->multi;
+  struct Curl_multi *multi = data->multi;
   X509_STORE *store = NULL;
 
+  DEBUGASSERT(multi);
   if(multi &&
      multi->ssl_backend_data &&
      multi->ssl_backend_data->store &&
@@ -3325,9 +3403,10 @@ static void set_cached_x509_store(struct Curl_cfilter *cf,
                                   X509_STORE *store)
 {
   struct ssl_primary_config *conn_config = Curl_ssl_cf_get_primary_config(cf);
-  struct Curl_multi *multi = data->multi_easy ? data->multi_easy : data->multi;
+  struct Curl_multi *multi = data->multi;
   struct multi_ssl_backend_data *mbackend;
 
+  DEBUGASSERT(multi);
   if(!multi)
     return;
 
@@ -3407,40 +3486,33 @@ CURLcode Curl_ssl_setup_x509_store(struct Curl_cfilter *cf,
 }
 #endif /* HAVE_SSL_X509_STORE_SHARE */
 
-static CURLcode ossl_connect_step1(struct Curl_cfilter *cf,
-                                   struct Curl_easy *data)
+CURLcode Curl_ossl_ctx_init(struct ossl_ctx *octx,
+                            struct Curl_cfilter *cf,
+                            struct Curl_easy *data,
+                            struct ssl_peer *peer,
+                            int transport, /* TCP or QUIC */
+                            const unsigned char *alpn, size_t alpn_len,
+                            Curl_ossl_ctx_setup_cb *cb_setup,
+                            void *cb_user_data,
+                            Curl_ossl_new_session_cb *cb_new_session,
+                            void *ssl_user_data)
 {
   CURLcode result = CURLE_OK;
-  char *ciphers;
+  const char *ciphers;
   SSL_METHOD_QUAL SSL_METHOD *req_method = NULL;
-  struct ssl_connect_data *connssl = cf->ctx;
   ctx_option_t ctx_options = 0;
   void *ssl_sessionid = NULL;
   struct ssl_primary_config *conn_config = Curl_ssl_cf_get_primary_config(cf);
   struct ssl_config_data *ssl_config = Curl_ssl_cf_get_config(cf, data);
-  BIO *bio;
-
-#ifdef SSL_CTRL_SET_TLSEXT_HOSTNAME
-  bool sni;
-  const char *hostname = connssl->hostname;
-
-#ifdef ENABLE_IPV6
-  struct in6_addr addr;
-#else
-  struct in_addr addr;
-#endif
-#endif
   const long int ssl_version = conn_config->version;
   char * const ssl_cert = ssl_config->primary.clientcert;
   const struct curl_blob *ssl_cert_blob = ssl_config->primary.cert_blob;
   const char * const ssl_cert_type = ssl_config->cert_type;
   const bool verifypeer = conn_config->verifypeer;
   char error_buffer[256];
-  struct ossl_ssl_backend_data *backend =
-    (struct ossl_ssl_backend_data *)connssl->backend;
-
-  DEBUGASSERT(ssl_connect_1 == connssl->connecting_state);
-  DEBUGASSERT(backend);
+#ifdef USE_ECH
+  struct ssl_connect_data *connssl = cf->ctx;
+#endif
 
   /* Make funny stuff to get random input */
   result = ossl_seed(data);
@@ -3449,57 +3521,74 @@ static CURLcode ossl_connect_step1(struct Curl_cfilter *cf,
 
   ssl_config->certverifyresult = !X509_V_OK;
 
-  /* check to see if we've been told to use an explicit SSL/TLS version */
-
-  switch(ssl_version) {
-  case CURL_SSLVERSION_DEFAULT:
-  case CURL_SSLVERSION_TLSv1:
-  case CURL_SSLVERSION_TLSv1_0:
-  case CURL_SSLVERSION_TLSv1_1:
-  case CURL_SSLVERSION_TLSv1_2:
-  case CURL_SSLVERSION_TLSv1_3:
-    /* it will be handled later with the context options */
-#if (OPENSSL_VERSION_NUMBER >= 0x10100000L)
-    req_method = TLS_client_method();
+  switch(transport) {
+  case TRNSPRT_TCP:
+    /* check to see if we've been told to use an explicit SSL/TLS version */
+    switch(ssl_version) {
+    case CURL_SSLVERSION_DEFAULT:
+    case CURL_SSLVERSION_TLSv1:
+    case CURL_SSLVERSION_TLSv1_0:
+    case CURL_SSLVERSION_TLSv1_1:
+    case CURL_SSLVERSION_TLSv1_2:
+    case CURL_SSLVERSION_TLSv1_3:
+      /* it will be handled later with the context options */
+  #if (OPENSSL_VERSION_NUMBER >= 0x10100000L)
+      req_method = TLS_client_method();
+  #else
+      req_method = SSLv23_client_method();
+  #endif
+      break;
+    case CURL_SSLVERSION_SSLv2:
+      failf(data, "No SSLv2 support");
+      return CURLE_NOT_BUILT_IN;
+    case CURL_SSLVERSION_SSLv3:
+      failf(data, "No SSLv3 support");
+      return CURLE_NOT_BUILT_IN;
+    default:
+      failf(data, "Unrecognized parameter passed via CURLOPT_SSLVERSION");
+      return CURLE_SSL_CONNECT_ERROR;
+    }
+    break;
+  case TRNSPRT_QUIC:
+    if((ssl_version != CURL_SSLVERSION_DEFAULT) &&
+       (ssl_version < CURL_SSLVERSION_TLSv1_3)) {
+      failf(data, "QUIC needs at least TLS version 1.3");
+      return CURLE_SSL_CONNECT_ERROR;
+     }
+#ifdef USE_OPENSSL_QUIC
+    req_method = OSSL_QUIC_client_method();
+#elif (OPENSSL_VERSION_NUMBER >= 0x10100000L)
+    req_method = TLS_method();
 #else
     req_method = SSLv23_client_method();
 #endif
-    use_sni(TRUE);
     break;
-  case CURL_SSLVERSION_SSLv2:
-    failf(data, "No SSLv2 support");
-    return CURLE_NOT_BUILT_IN;
-  case CURL_SSLVERSION_SSLv3:
-    failf(data, "No SSLv3 support");
-    return CURLE_NOT_BUILT_IN;
   default:
-    failf(data, "Unrecognized parameter passed via CURLOPT_SSLVERSION");
+    failf(data, "unsupported transport %d in SSL init", transport);
     return CURLE_SSL_CONNECT_ERROR;
   }
 
-  if(backend->ctx) {
-    /* This happens when an error was encountered before in this
-     * step and we are called to do it again. Get rid of any leftover
-     * from the previous call. */
-    ossl_close(cf, data);
-  }
-  backend->ctx = SSL_CTX_new(req_method);
 
-  if(!backend->ctx) {
+  DEBUGASSERT(!octx->ssl_ctx);
+  octx->ssl_ctx = SSL_CTX_new(req_method);
+
+  if(!octx->ssl_ctx) {
     failf(data, "SSL: couldn't create a context: %s",
           ossl_strerror(ERR_peek_error(), error_buffer, sizeof(error_buffer)));
     return CURLE_OUT_OF_MEMORY;
   }
 
-#ifdef SSL_MODE_RELEASE_BUFFERS
-  SSL_CTX_set_mode(backend->ctx, SSL_MODE_RELEASE_BUFFERS);
-#endif
+  if(cb_setup) {
+    result = cb_setup(cf, data, cb_user_data);
+    if(result)
+      return result;
+  }
 
 #ifdef SSL_CTRL_SET_MSG_CALLBACK
   if(data->set.fdebug && data->set.verbose) {
     /* the SSL trace callback is only used for verbose logging */
-    SSL_CTX_set_msg_callback(backend->ctx, ossl_trace);
-    SSL_CTX_set_msg_callback_arg(backend->ctx, cf);
+    SSL_CTX_set_msg_callback(octx->ssl_ctx, ossl_trace);
+    SSL_CTX_set_msg_callback_arg(octx->ssl_ctx, cf);
   }
 #endif
 
@@ -3579,7 +3668,7 @@ static CURLcode ossl_connect_step1(struct Curl_cfilter *cf,
     ctx_options |= SSL_OP_NO_SSLv3;
 
 #if (OPENSSL_VERSION_NUMBER >= 0x10100000L) /* 1.1.0 */
-    result = ossl_set_ssl_version_min_max(cf, backend->ctx);
+    result = ossl_set_ssl_version_min_max(cf, octx->ssl_ctx);
 #else
     result = ossl_set_ssl_version_min_max_legacy(&ctx_options, cf, data);
 #endif
@@ -3592,26 +3681,20 @@ static CURLcode ossl_connect_step1(struct Curl_cfilter *cf,
     return CURLE_SSL_CONNECT_ERROR;
   }
 
-  SSL_CTX_set_options(backend->ctx, ctx_options);
+  SSL_CTX_set_options(octx->ssl_ctx, ctx_options);
 
 #ifdef HAS_ALPN
-  if(connssl->alpn) {
-    struct alpn_proto_buf proto;
-
-    result = Curl_alpn_to_proto_buf(&proto, connssl->alpn);
-    if(result ||
-       SSL_CTX_set_alpn_protos(backend->ctx, proto.data, proto.len)) {
+  if(alpn && alpn_len) {
+    if(SSL_CTX_set_alpn_protos(octx->ssl_ctx, alpn, (int)alpn_len)) {
       failf(data, "Error setting ALPN");
       return CURLE_SSL_CONNECT_ERROR;
     }
-    Curl_alpn_to_proto_str(&proto, connssl->alpn);
-    infof(data, VTLS_INFOF_ALPN_OFFER_1STR, proto.data);
   }
 #endif
 
   if(ssl_cert || ssl_cert_blob || ssl_cert_type) {
     if(!result &&
-       !cert_stuff(data, backend->ctx,
+       !cert_stuff(data, octx->ssl_ctx,
                    ssl_cert, ssl_cert_blob, ssl_cert_type,
                    ssl_config->key, ssl_config->key_blob,
                    ssl_config->key_type, ssl_config->key_passwd))
@@ -3622,10 +3705,10 @@ static CURLcode ossl_connect_step1(struct Curl_cfilter *cf,
   }
 
   ciphers = conn_config->cipher_list;
-  if(!ciphers)
-    ciphers = (char *)DEFAULT_CIPHER_SELECTION;
+  if(!ciphers && (peer->transport != TRNSPRT_QUIC))
+    ciphers = DEFAULT_CIPHER_SELECTION;
   if(ciphers) {
-    if(!SSL_CTX_set_cipher_list(backend->ctx, ciphers)) {
+    if(!SSL_CTX_set_cipher_list(octx->ssl_ctx, ciphers)) {
       failf(data, "failed setting cipher list: %s", ciphers);
       return CURLE_SSL_CIPHER;
     }
@@ -3634,9 +3717,9 @@ static CURLcode ossl_connect_step1(struct Curl_cfilter *cf,
 
 #ifdef HAVE_SSL_CTX_SET_CIPHERSUITES
   {
-    char *ciphers13 = conn_config->cipher_list13;
+    const char *ciphers13 = conn_config->cipher_list13;
     if(ciphers13) {
-      if(!SSL_CTX_set_ciphersuites(backend->ctx, ciphers13)) {
+      if(!SSL_CTX_set_ciphersuites(octx->ssl_ctx, ciphers13)) {
         failf(data, "failed setting TLS 1.3 cipher suite: %s", ciphers13);
         return CURLE_SSL_CIPHER;
       }
@@ -3647,14 +3730,14 @@ static CURLcode ossl_connect_step1(struct Curl_cfilter *cf,
 
 #ifdef HAVE_SSL_CTX_SET_POST_HANDSHAKE_AUTH
   /* OpenSSL 1.1.1 requires clients to opt-in for PHA */
-  SSL_CTX_set_post_handshake_auth(backend->ctx, 1);
+  SSL_CTX_set_post_handshake_auth(octx->ssl_ctx, 1);
 #endif
 
 #ifdef HAVE_SSL_CTX_SET_EC_CURVES
   {
-    char *curves = conn_config->curves;
+    const char *curves = conn_config->curves;
     if(curves) {
-      if(!SSL_CTX_set1_curves_list(backend->ctx, curves)) {
+      if(!SSL_CTX_set1_curves_list(octx->ssl_ctx, curves)) {
         failf(data, "failed setting curves list: '%s'", curves);
         return CURLE_SSL_CIPHER;
       }
@@ -3668,18 +3751,18 @@ static CURLcode ossl_connect_step1(struct Curl_cfilter *cf,
     char * const ssl_password = ssl_config->primary.password;
     infof(data, "Using TLS-SRP username: %s", ssl_username);
 
-    if(!SSL_CTX_set_srp_username(backend->ctx, ssl_username)) {
+    if(!SSL_CTX_set_srp_username(octx->ssl_ctx, ssl_username)) {
       failf(data, "Unable to set SRP user name");
       return CURLE_BAD_FUNCTION_ARGUMENT;
     }
-    if(!SSL_CTX_set_srp_password(backend->ctx, ssl_password)) {
+    if(!SSL_CTX_set_srp_password(octx->ssl_ctx, ssl_password)) {
       failf(data, "failed setting SRP password");
       return CURLE_BAD_FUNCTION_ARGUMENT;
     }
     if(!conn_config->cipher_list) {
       infof(data, "Setting cipher list SRP");
 
-      if(!SSL_CTX_set_cipher_list(backend->ctx, "SRP")) {
+      if(!SSL_CTX_set_cipher_list(octx->ssl_ctx, "SRP")) {
         failf(data, "failed setting SRP cipher list");
         return CURLE_SSL_CIPHER;
       }
@@ -3691,38 +3774,40 @@ static CURLcode ossl_connect_step1(struct Curl_cfilter *cf,
    * fail to connect if the verification fails, or if it should continue
    * anyway. In the latter case the result of the verification is checked with
    * SSL_get_verify_result() below. */
-  SSL_CTX_set_verify(backend->ctx,
+  SSL_CTX_set_verify(octx->ssl_ctx,
                      verifypeer ? SSL_VERIFY_PEER : SSL_VERIFY_NONE, NULL);
 
   /* Enable logging of secrets to the file specified in env SSLKEYLOGFILE. */
 #ifdef HAVE_KEYLOG_CALLBACK
   if(Curl_tls_keylog_enabled()) {
-    SSL_CTX_set_keylog_callback(backend->ctx, ossl_keylog_callback);
+    SSL_CTX_set_keylog_callback(octx->ssl_ctx, ossl_keylog_callback);
   }
 #endif
 
-  /* Enable the session cache because it's a prerequisite for the "new session"
-   * callback. Use the "external storage" mode to prevent OpenSSL from creating
-   * an internal session cache.
-   */
-  SSL_CTX_set_session_cache_mode(backend->ctx,
-                                 SSL_SESS_CACHE_CLIENT |
-                                 SSL_SESS_CACHE_NO_INTERNAL);
-  SSL_CTX_sess_set_new_cb(backend->ctx, ossl_new_session_cb);
+  if(cb_new_session) {
+    /* Enable the session cache because it's a prerequisite for the
+     * "new session" callback. Use the "external storage" mode to prevent
+     * OpenSSL from creating an internal session cache.
+     */
+    SSL_CTX_set_session_cache_mode(octx->ssl_ctx,
+                                   SSL_SESS_CACHE_CLIENT |
+                                   SSL_SESS_CACHE_NO_INTERNAL);
+    SSL_CTX_sess_set_new_cb(octx->ssl_ctx, cb_new_session);
+  }
 
   /* give application a chance to interfere with SSL set up. */
   if(data->set.ssl.fsslctx) {
     /* When a user callback is installed to modify the SSL_CTX,
      * we need to do the full initialization before calling it.
      * See: #11800 */
-    if(!backend->x509_store_setup) {
-      result = Curl_ssl_setup_x509_store(cf, data, backend->ctx);
+    if(!octx->x509_store_setup) {
+      result = Curl_ssl_setup_x509_store(cf, data, octx->ssl_ctx);
       if(result)
         return result;
-      backend->x509_store_setup = TRUE;
+      octx->x509_store_setup = TRUE;
     }
     Curl_set_in_callback(data, true);
-    result = (*data->set.ssl.fsslctx)(data, backend->ctx,
+    result = (*data->set.ssl.fsslctx)(data, octx->ssl_ctx,
                                       data->set.ssl.fsslctxp);
     Curl_set_in_callback(data, false);
     if(result) {
@@ -3732,51 +3817,174 @@ static CURLcode ossl_connect_step1(struct Curl_cfilter *cf,
   }
 
   /* Let's make an SSL structure */
-  if(backend->handle)
-    SSL_free(backend->handle);
-  backend->handle = SSL_new(backend->ctx);
-  if(!backend->handle) {
+  if(octx->ssl)
+    SSL_free(octx->ssl);
+  octx->ssl = SSL_new(octx->ssl_ctx);
+  if(!octx->ssl) {
     failf(data, "SSL: couldn't create a context (handle)");
     return CURLE_OUT_OF_MEMORY;
   }
 
-  SSL_set_app_data(backend->handle, cf);
+  SSL_set_app_data(octx->ssl, ssl_user_data);
 
 #if (OPENSSL_VERSION_NUMBER >= 0x0090808fL) && !defined(OPENSSL_NO_TLSEXT) && \
   !defined(OPENSSL_NO_OCSP)
   if(conn_config->verifystatus)
-    SSL_set_tlsext_status_type(backend->handle, TLSEXT_STATUSTYPE_ocsp);
+    SSL_set_tlsext_status_type(octx->ssl, TLSEXT_STATUSTYPE_ocsp);
 #endif
 
 #if (defined(OPENSSL_IS_BORINGSSL) || defined(OPENSSL_IS_AWSLC)) && \
     defined(ALLOW_RENEG)
-  SSL_set_renegotiate_mode(backend->handle, ssl_renegotiate_freely);
+  SSL_set_renegotiate_mode(octx->ssl, ssl_renegotiate_freely);
 #endif
 
-  SSL_set_connect_state(backend->handle);
+  SSL_set_connect_state(octx->ssl);
 
-  backend->server_cert = 0x0;
+  octx->server_cert = 0x0;
 #ifdef SSL_CTRL_SET_TLSEXT_HOSTNAME
-  if((0 == Curl_inet_pton(AF_INET, hostname, &addr)) &&
-#ifdef ENABLE_IPV6
-     (0 == Curl_inet_pton(AF_INET6, hostname, &addr)) &&
-#endif
-     sni) {
-    char *snihost = Curl_ssl_snihost(data, hostname, NULL);
-    if(!snihost || !SSL_set_tlsext_host_name(backend->handle, snihost)) {
+  if(peer->sni) {
+    if(!SSL_set_tlsext_host_name(octx->ssl, peer->sni)) {
       failf(data, "Failed set SNI");
       return CURLE_SSL_CONNECT_ERROR;
     }
   }
-#endif
 
-  SSL_set_app_data(backend->handle, cf);
+#ifdef USE_ECH
+  if(ECH_ENABLED(data)) {
+    unsigned char *ech_config = NULL;
+    size_t ech_config_len = 0;
+    char *outername = data->set.str[STRING_ECH_PUBLIC];
+    int trying_ech_now = 0;
+
+    if(data->set.tls_ech & CURLECH_GREASE) {
+      infof(data, "ECH: will GREASE ClientHello");
+# ifdef OPENSSL_IS_BORINGSSL
+      SSL_set_enable_ech_grease(octx->ssl, 1);
+# else
+      SSL_set_options(octx->ssl, SSL_OP_ECH_GREASE);
+# endif
+    }
+    else if(data->set.tls_ech & CURLECH_CLA_CFG) {
+# ifdef OPENSSL_IS_BORINGSSL
+      /* have to do base64 decode here for boring */
+      const char *b64 = data->set.str[STRING_ECH_CONFIG];
 
-  if(ssl_config->primary.sessionid) {
+      if(!b64) {
+        infof(data, "ECH: ECHConfig from command line empty");
+        return CURLE_SSL_CONNECT_ERROR;
+      }
+      ech_config_len = 2 * strlen(b64);
+      result = Curl_base64_decode(b64, &ech_config, &ech_config_len);
+      if(result || !ech_config) {
+        infof(data, "ECH: can't base64 decode ECHConfig from command line");
+        if(data->set.tls_ech & CURLECH_HARD)
+          return result;
+      }
+      if(SSL_set1_ech_config_list(octx->ssl, ech_config,
+                                  ech_config_len) != 1) {
+        infof(data, "ECH: SSL_ECH_set1_echconfig failed");
+        if(data->set.tls_ech & CURLECH_HARD) {
+          free(ech_config);
+          return CURLE_SSL_CONNECT_ERROR;
+        }
+      }
+      free(ech_config);
+      trying_ech_now = 1;
+# else
+      ech_config = (unsigned char *) data->set.str[STRING_ECH_CONFIG];
+      if(!ech_config) {
+        infof(data, "ECH: ECHConfig from command line empty");
+        return CURLE_SSL_CONNECT_ERROR;
+      }
+      ech_config_len = strlen(data->set.str[STRING_ECH_CONFIG]);
+      if(SSL_ech_set1_echconfig(octx->ssl, ech_config, ech_config_len) != 1) {
+        infof(data, "ECH: SSL_ECH_set1_echconfig failed");
+        if(data->set.tls_ech & CURLECH_HARD)
+          return CURLE_SSL_CONNECT_ERROR;
+      }
+      else
+        trying_ech_now = 1;
+# endif
+      infof(data, "ECH: ECHConfig from command line");
+    }
+    else {
+      struct Curl_dns_entry *dns = NULL;
+
+      dns = Curl_fetch_addr(data, connssl->peer.hostname, connssl->peer.port);
+      if(!dns) {
+        infof(data, "ECH: requested but no DNS info available");
+        if(data->set.tls_ech & CURLECH_HARD)
+          return CURLE_SSL_CONNECT_ERROR;
+      }
+      else {
+        struct Curl_https_rrinfo *rinfo = NULL;
+
+        rinfo = dns->hinfo;
+        if(rinfo && rinfo->echconfiglist) {
+          unsigned char *ecl = rinfo->echconfiglist;
+          size_t elen = rinfo->echconfiglist_len;
+
+          infof(data, "ECH: ECHConfig from DoH HTTPS RR");
+# ifndef OPENSSL_IS_BORINGSSL
+          if(SSL_ech_set1_echconfig(octx->ssl, ecl, elen) != 1) {
+            infof(data, "ECH: SSL_ECH_set1_echconfig failed");
+            if(data->set.tls_ech & CURLECH_HARD)
+              return CURLE_SSL_CONNECT_ERROR;
+          }
+# else
+          if(SSL_set1_ech_config_list(octx->ssl, ecl, elen) != 1) {
+            infof(data, "ECH: SSL_set1_ech_config_list failed (boring)");
+            if(data->set.tls_ech & CURLECH_HARD)
+              return CURLE_SSL_CONNECT_ERROR;
+          }
+# endif
+          else {
+            trying_ech_now = 1;
+            infof(data, "ECH: imported ECHConfigList of length %ld", elen);
+          }
+        }
+        else {
+          infof(data, "ECH: requested but no ECHConfig available");
+          if(data->set.tls_ech & CURLECH_HARD)
+            return CURLE_SSL_CONNECT_ERROR;
+        }
+        Curl_resolv_unlock(data, dns);
+      }
+    }
+# ifdef OPENSSL_IS_BORINGSSL
+    if(trying_ech_now && outername) {
+      infof(data, "ECH: setting public_name not supported with boringssl");
+      return CURLE_SSL_CONNECT_ERROR;
+    }
+# else
+    if(trying_ech_now && outername) {
+      infof(data, "ECH: inner: '%s', outer: '%s'",
+            connssl->peer.hostname, outername);
+      result = SSL_ech_set_server_names(octx->ssl,
+                                        connssl->peer.hostname, outername,
+                                        0 /* do send outer */);
+      if(result != 1) {
+        infof(data, "ECH: rv failed to set server name(s) %d [ERROR]", result);
+        return CURLE_SSL_CONNECT_ERROR;
+      }
+    }
+# endif  /* not BORING */
+    if(trying_ech_now
+       && SSL_set_min_proto_version(octx->ssl, TLS1_3_VERSION) != 1) {
+      infof(data, "ECH: Can't force TLSv1.3 [ERROR]");
+      return CURLE_SSL_CONNECT_ERROR;
+    }
+  }
+#endif  /* USE_ECH */
+
+#endif
+
+  octx->reused_session = FALSE;
+  if(ssl_config->primary.sessionid && transport == TRNSPRT_TCP) {
     Curl_ssl_sessionid_lock(data);
-    if(!Curl_ssl_getsessionid(cf, data, &ssl_sessionid, NULL)) {
+    if(!Curl_ssl_getsessionid(cf, data, peer, &ssl_sessionid, NULL)) {
       /* we got a session id, use it! */
-      if(!SSL_set_session(backend->handle, ssl_sessionid)) {
+      if(!SSL_set_session(octx->ssl, ssl_sessionid)) {
         Curl_ssl_sessionid_unlock(data);
         failf(data, "SSL: SSL_set_session failed: %s",
               ossl_strerror(ERR_get_error(), error_buffer,
@@ -3785,14 +3993,46 @@ static CURLcode ossl_connect_step1(struct Curl_cfilter *cf,
       }
       /* Informational message */
       infof(data, "SSL reusing session ID");
+      octx->reused_session = TRUE;
     }
     Curl_ssl_sessionid_unlock(data);
   }
 
-  backend->bio_method = bio_cf_method_create();
-  if(!backend->bio_method)
+  return CURLE_OK;
+}
+
+static CURLcode ossl_connect_step1(struct Curl_cfilter *cf,
+                                   struct Curl_easy *data)
+{
+  struct ssl_connect_data *connssl = cf->ctx;
+  struct ossl_ctx *octx = (struct ossl_ctx *)connssl->backend;
+  struct alpn_proto_buf proto;
+  BIO *bio;
+  CURLcode result;
+
+  DEBUGASSERT(ssl_connect_1 == connssl->connecting_state);
+  DEBUGASSERT(octx);
+  memset(&proto, 0, sizeof(proto));
+#ifdef HAS_ALPN
+  if(connssl->alpn) {
+    result = Curl_alpn_to_proto_buf(&proto, connssl->alpn);
+    if(result) {
+      failf(data, "Error determining ALPN");
+      return CURLE_SSL_CONNECT_ERROR;
+    }
+  }
+#endif
+
+  result = Curl_ossl_ctx_init(octx, cf, data, &connssl->peer, TRNSPRT_TCP,
+                              proto.data, proto.len, NULL, NULL,
+                              ossl_new_session_cb, cf);
+  if(result)
+    return result;
+
+  octx->bio_method = ossl_bio_cf_method_create();
+  if(!octx->bio_method)
     return CURLE_OUT_OF_MEMORY;
-  bio = BIO_new(backend->bio_method);
+  bio = BIO_new(octx->bio_method);
   if(!bio)
     return CURLE_OUT_OF_MEMORY;
 
@@ -3804,40 +4044,109 @@ static CURLcode ossl_connect_step1(struct Curl_cfilter *cf,
    * We check on the function in configure, since libressl and friends
    * each have their own versions to add support for this. */
   BIO_up_ref(bio);
-  SSL_set0_rbio(backend->handle, bio);
-  SSL_set0_wbio(backend->handle, bio);
+  SSL_set0_rbio(octx->ssl, bio);
+  SSL_set0_wbio(octx->ssl, bio);
 #else
-  SSL_set_bio(backend->handle, bio, bio);
+  SSL_set_bio(octx->ssl, bio, bio);
 #endif
-  connssl->connecting_state = ssl_connect_2;
 
+#ifdef HAS_ALPN
+  if(connssl->alpn) {
+    Curl_alpn_to_proto_str(&proto, connssl->alpn);
+    infof(data, VTLS_INFOF_ALPN_OFFER_1STR, proto.data);
+  }
+#endif
+  connssl->connecting_state = ssl_connect_2;
   return CURLE_OK;
 }
 
+#ifdef USE_ECH
+/* If we have retry configs, then trace those out */
+static void ossl_trace_ech_retry_configs(struct Curl_easy *data, SSL* ssl,
+                                         int reason)
+{
+  CURLcode result = CURLE_OK;
+  size_t rcl = 0;
+  int rv = 1;
+# ifndef OPENSSL_IS_BORINGSSL
+  char *inner = NULL;
+  unsigned char *rcs = NULL;
+  char *outer = NULL;
+# else
+  const char *inner = NULL;
+  const uint8_t *rcs = NULL;
+  const char *outer = NULL;
+  size_t out_name_len = 0;
+  int servername_type = 0;
+# endif
+
+  /* nothing to trace if not doing ECH */
+  if(!ECH_ENABLED(data))
+    return;
+# ifndef OPENSSL_IS_BORINGSSL
+  rv = SSL_ech_get_retry_config(ssl, &rcs, &rcl);
+# else
+  SSL_get0_ech_retry_configs(ssl, &rcs, &rcl);
+  rv = (int)rcl;
+# endif
+
+  if(rv && rcs) {
+# define HEXSTR_MAX 800
+    char *b64str = NULL;
+    size_t blen = 0;
+
+    result = Curl_base64_encode((const char *)rcs, rcl,
+                                &b64str, &blen);
+    if(!result && b64str)
+      infof(data, "ECH: retry_configs %s", b64str);
+    free(b64str);
+# ifndef OPENSSL_IS_BORINGSSL
+    rv = SSL_ech_get_status(ssl, &inner, &outer);
+    infof(data, "ECH: retry_configs for %s from %s, %d %d",
+          inner ? inner : "NULL", outer ? outer : "NULL", reason, rv);
+#else
+    rv = SSL_ech_accepted(ssl);
+    servername_type = SSL_get_servername_type(ssl);
+    inner = SSL_get_servername(ssl, servername_type);
+    SSL_get0_ech_name_override(ssl, &outer, &out_name_len);
+    /* TODO: get the inner from boring */
+    infof(data, "ECH: retry_configs for %s from %s, %d %d",
+          inner ? inner : "NULL", outer ? outer : "NULL", reason, rv);
+#endif
+  }
+  else
+    infof(data, "ECH: no retry_configs (rv = %d)", rv);
+# ifndef OPENSSL_IS_BORINGSSL
+  OPENSSL_free((void *)rcs);
+# endif
+  return;
+}
+
+#endif
+
 static CURLcode ossl_connect_step2(struct Curl_cfilter *cf,
                                    struct Curl_easy *data)
 {
   int err;
   struct ssl_connect_data *connssl = cf->ctx;
-  struct ossl_ssl_backend_data *backend =
-    (struct ossl_ssl_backend_data *)connssl->backend;
+  struct ossl_ctx *octx = (struct ossl_ctx *)connssl->backend;
   struct ssl_config_data *ssl_config = Curl_ssl_cf_get_config(cf, data);
   DEBUGASSERT(ssl_connect_2 == connssl->connecting_state
               || ssl_connect_2_reading == connssl->connecting_state
               || ssl_connect_2_writing == connssl->connecting_state);
-  DEBUGASSERT(backend);
+  DEBUGASSERT(octx);
 
   ERR_clear_error();
 
-  err = SSL_connect(backend->handle);
+  err = SSL_connect(octx->ssl);
 
-  if(!backend->x509_store_setup) {
+  if(!octx->x509_store_setup) {
     /* After having send off the ClientHello, we prepare the x509
      * store to verify the coming certificate from the server */
-    CURLcode result = Curl_ssl_setup_x509_store(cf, data, backend->ctx);
+    CURLcode result = Curl_ssl_setup_x509_store(cf, data, octx->ssl_ctx);
     if(result)
       return result;
-    backend->x509_store_setup = TRUE;
+    octx->x509_store_setup = TRUE;
   }
 
 #ifndef HAVE_KEYLOG_CALLBACK
@@ -3845,7 +4154,9 @@ static CURLcode ossl_connect_step2(struct Curl_cfilter *cf,
     /* If key logging is enabled, wait for the handshake to complete and then
      * proceed with logging secrets (for TLS 1.2 or older).
      */
-    ossl_log_tls12_secret(backend->handle, &backend->keylog_done);
+    bool done = FALSE;
+    ossl_log_tls12_secret(octx->ssl, &done);
+    octx->keylog_done = done;
   }
 #endif
 
@@ -3853,7 +4164,7 @@ static CURLcode ossl_connect_step2(struct Curl_cfilter *cf,
      0  is "not successful but was shut down controlled"
      <0 is "handshake was not successful, because a fatal error occurred" */
   if(1 != err) {
-    int detail = SSL_get_error(backend->handle, err);
+    int detail = SSL_get_error(octx->ssl, err);
 
     if(SSL_ERROR_WANT_READ == detail) {
       connssl->connecting_state = ssl_connect_2_reading;
@@ -3875,7 +4186,7 @@ static CURLcode ossl_connect_step2(struct Curl_cfilter *cf,
       return CURLE_OK;
     }
 #endif
-    if(backend->io_result == CURLE_AGAIN) {
+    if(octx->io_result == CURLE_AGAIN) {
       return CURLE_OK;
     }
     else {
@@ -3903,7 +4214,7 @@ static CURLcode ossl_connect_step2(struct Curl_cfilter *cf,
           (reason == SSL_R_SSLV3_ALERT_CERTIFICATE_EXPIRED))) {
         result = CURLE_PEER_FAILED_VERIFICATION;
 
-        lerr = SSL_get_verify_result(backend->handle);
+        lerr = SSL_get_verify_result(octx->ssl);
         if(lerr != X509_V_OK) {
           ssl_config->certverifyresult = lerr;
           msnprintf(error_buffer, sizeof(error_buffer),
@@ -3925,6 +4236,21 @@ static CURLcode ossl_connect_step2(struct Curl_cfilter *cf,
         result = CURLE_SSL_CLIENTCERT;
         ossl_strerror(errdetail, error_buffer, sizeof(error_buffer));
       }
+#endif
+#ifdef USE_ECH
+      else if((lib == ERR_LIB_SSL) &&
+# ifndef OPENSSL_IS_BORINGSSL
+              (reason == SSL_R_ECH_REQUIRED)) {
+# else
+              (reason == SSL_R_ECH_REJECTED)) {
+# endif
+
+        /* trace retry_configs if we got some */
+        ossl_trace_ech_retry_configs(data, octx->ssl, reason);
+
+        result = CURLE_ECH_REQUIRED;
+        ossl_strerror(errdetail, error_buffer, sizeof(error_buffer));
+      }
 #endif
       else {
         result = CURLE_SSL_CONNECT_ERROR;
@@ -3945,7 +4271,7 @@ static CURLcode ossl_connect_step2(struct Curl_cfilter *cf,
           Curl_strerror(sockerr, extramsg, sizeof(extramsg));
         failf(data, OSSL_PACKAGE " SSL_connect: %s in connection to %s:%d ",
               extramsg[0] ? extramsg : SSL_ERROR_to_str(detail),
-              connssl->hostname, connssl->port);
+              connssl->peer.hostname, connssl->peer.port);
         return result;
       }
 
@@ -3956,13 +4282,90 @@ static CURLcode ossl_connect_step2(struct Curl_cfilter *cf,
     }
   }
   else {
+    int psigtype_nid = NID_undef;
+    const char *negotiated_group_name = NULL;
+
     /* we connected fine, we're not waiting for anything else. */
     connssl->connecting_state = ssl_connect_3;
 
+#if (OPENSSL_VERSION_NUMBER >= 0x30000000L)
+    SSL_get_peer_signature_type_nid(octx->ssl, &psigtype_nid);
+#if (OPENSSL_VERSION_NUMBER >= 0x30200000L)
+    negotiated_group_name = SSL_get0_group_name(octx->ssl);
+#else
+    negotiated_group_name =
+      OBJ_nid2sn(SSL_get_negotiated_group(octx->ssl) & 0x0000FFFF);
+#endif
+#endif
+
     /* Informational message */
-    infof(data, "SSL connection using %s / %s",
-          SSL_get_version(backend->handle),
-          SSL_get_cipher(backend->handle));
+    infof(data, "SSL connection using %s / %s / %s / %s",
+          SSL_get_version(octx->ssl),
+          SSL_get_cipher(octx->ssl),
+          negotiated_group_name? negotiated_group_name : "[blank]",
+          OBJ_nid2sn(psigtype_nid));
+
+#ifdef USE_ECH
+# ifndef OPENSSL_IS_BORINGSSL
+    if(ECH_ENABLED(data)) {
+      char *inner = NULL, *outer = NULL;
+      const char *status = NULL;
+      int rv;
+
+      rv = SSL_ech_get_status(octx->ssl, &inner, &outer);
+      switch(rv) {
+      case SSL_ECH_STATUS_SUCCESS:
+        status = "succeeded";
+        break;
+      case SSL_ECH_STATUS_GREASE_ECH:
+        status = "sent GREASE, got retry-configs";
+        break;
+      case SSL_ECH_STATUS_GREASE:
+        status = "sent GREASE";
+        break;
+      case SSL_ECH_STATUS_NOT_TRIED:
+        status = "not attempted";
+        break;
+      case SSL_ECH_STATUS_NOT_CONFIGURED:
+        status = "not configured";
+        break;
+      case SSL_ECH_STATUS_BACKEND:
+        status = "backend (unexpected)";
+        break;
+      case SSL_ECH_STATUS_FAILED:
+        status = "failed";
+        break;
+      case SSL_ECH_STATUS_BAD_CALL:
+        status = "bad call (unexpected)";
+        break;
+      case SSL_ECH_STATUS_BAD_NAME:
+        status = "bad name (unexpected)";
+        break;
+      default:
+        status = "unexpected status";
+        infof(data, "ECH: unexpected status %d",rv);
+      }
+      infof(data, "ECH: result: status is %s, inner is %s, outer is %s",
+             (status?status:"NULL"),
+             (inner?inner:"NULL"),
+             (outer?outer:"NULL"));
+      OPENSSL_free(inner);
+      OPENSSL_free(outer);
+      if(rv == SSL_ECH_STATUS_GREASE_ECH) {
+        /* trace retry_configs if we got some */
+        ossl_trace_ech_retry_configs(data, octx->ssl, 0);
+      }
+      if(rv != SSL_ECH_STATUS_SUCCESS
+         && data->set.tls_ech & CURLECH_HARD) {
+        infof(data, "ECH: ech-hard failed");
+        return CURLE_SSL_CONNECT_ERROR;
+      }
+   }
+   else {
+      infof(data, "ECH: result: status is not attempted");
+   }
+# endif  /* BORING */
+#endif  /* USE_ECH */
 
 #ifdef HAS_ALPN
     /* Sets data and len to negotiated protocol, len is 0 if no protocol was
@@ -3971,7 +4374,7 @@ static CURLcode ossl_connect_step2(struct Curl_cfilter *cf,
     if(connssl->alpn) {
       const unsigned char *neg_protocol;
       unsigned int len;
-      SSL_get0_alpn_selected(backend->handle, &neg_protocol, &len);
+      SSL_get0_alpn_selected(octx->ssl, &neg_protocol, &len);
 
       return Curl_alpn_set_negotiated(cf, data, neg_protocol, len);
     }
@@ -4039,20 +4442,81 @@ static CURLcode ossl_pkp_pin_peer_pubkey(struct Curl_easy *data, X509* cert,
   return result;
 }
 
-/*
- * Get the server cert, verify it and show it, etc., only call failf() if the
- * 'strict' argument is TRUE as otherwise all this is for informational
- * purposes only!
- *
- * We check certificates to authenticate the server; otherwise we risk
- * man-in-the-middle attack.
- */
-static CURLcode servercert(struct Curl_cfilter *cf,
-                           struct Curl_easy *data,
-                           bool strict)
+#if (OPENSSL_VERSION_NUMBER >= 0x10100000L) &&  \
+  !(defined(LIBRESSL_VERSION_NUMBER) && \
+    LIBRESSL_VERSION_NUMBER < 0x3060000fL) && \
+  !defined(OPENSSL_IS_BORINGSSL) && \
+  !defined(OPENSSL_IS_AWSLC) && \
+  !defined(CURL_DISABLE_VERBOSE_STRINGS)
+static void infof_certstack(struct Curl_easy *data, const SSL *ssl)
+{
+  STACK_OF(X509) *certstack;
+  long verify_result;
+  int num_cert_levels;
+  int cert_level;
+
+  verify_result = SSL_get_verify_result(ssl);
+  if(verify_result != X509_V_OK)
+    certstack = SSL_get_peer_cert_chain(ssl);
+  else
+    certstack = SSL_get0_verified_chain(ssl);
+  num_cert_levels = sk_X509_num(certstack);
+
+  for(cert_level = 0; cert_level < num_cert_levels; cert_level++) {
+    char cert_algorithm[80] = "";
+    char group_name_final[80] = "";
+    const X509_ALGOR *palg_cert = NULL;
+    const ASN1_OBJECT *paobj_cert = NULL;
+    X509 *current_cert;
+    EVP_PKEY *current_pkey;
+    int key_bits;
+    int key_sec_bits;
+    int get_group_name;
+    const char *type_name;
+
+    current_cert = sk_X509_value(certstack, cert_level);
+
+    X509_get0_signature(NULL, &palg_cert, current_cert);
+    X509_ALGOR_get0(&paobj_cert, NULL, NULL, palg_cert);
+    OBJ_obj2txt(cert_algorithm, sizeof(cert_algorithm), paobj_cert, 0);
+
+    current_pkey = X509_get0_pubkey(current_cert);
+    key_bits = EVP_PKEY_bits(current_pkey);
+#if (OPENSSL_VERSION_NUMBER < 0x30000000L)
+#define EVP_PKEY_get_security_bits EVP_PKEY_security_bits
+#endif
+    key_sec_bits = EVP_PKEY_get_security_bits(current_pkey);
+#if (OPENSSL_VERSION_NUMBER >= 0x30000000L)
+    {
+      char group_name[80] = "";
+      get_group_name = EVP_PKEY_get_group_name(current_pkey, group_name,
+                                               sizeof(group_name), NULL);
+      msnprintf(group_name_final, sizeof(group_name_final), "/%s", group_name);
+    }
+    type_name = EVP_PKEY_get0_type_name(current_pkey);
+#else
+    get_group_name = 0;
+    type_name = NULL;
+#endif
+
+    infof(data,
+          "  Certificate level %d: "
+          "Public key type %s%s (%d/%d Bits/secBits), signed using %s",
+          cert_level, type_name ? type_name : "?",
+          get_group_name == 0 ? "" : group_name_final,
+          key_bits, key_sec_bits, cert_algorithm);
+  }
+}
+#else
+#define infof_certstack(data, ssl)
+#endif
+
+CURLcode Curl_oss_check_peer_cert(struct Curl_cfilter *cf,
+                                  struct Curl_easy *data,
+                                  struct ossl_ctx *octx,
+                                  struct ssl_peer *peer)
 {
   struct connectdata *conn = cf->conn;
-  struct ssl_connect_data *connssl = cf->ctx;
   struct ssl_config_data *ssl_config = Curl_ssl_cf_get_config(cf, data);
   struct ssl_primary_config *conn_config = Curl_ssl_cf_get_primary_config(cf);
   CURLcode result = CURLE_OK;
@@ -4064,10 +4528,9 @@ static CURLcode servercert(struct Curl_cfilter *cf,
   char buffer[2048];
   const char *ptr;
   BIO *mem = BIO_new(BIO_s_mem());
-  struct ossl_ssl_backend_data *backend =
-    (struct ossl_ssl_backend_data *)connssl->backend;
+  bool strict = (conn_config->verifypeer || conn_config->verifyhost);
 
-  DEBUGASSERT(backend);
+  DEBUGASSERT(octx);
 
   if(!mem) {
     failf(data,
@@ -4080,10 +4543,10 @@ static CURLcode servercert(struct Curl_cfilter *cf,
 
   if(data->set.ssl.certinfo)
     /* asked to gather certificate info */
-    (void)Curl_ossl_certchain(data, backend->handle);
+    (void)Curl_ossl_certchain(data, octx->ssl);
 
-  backend->server_cert = SSL_get1_peer_certificate(backend->handle);
-  if(!backend->server_cert) {
+  octx->server_cert = SSL_get1_peer_certificate(octx->ssl);
+  if(!octx->server_cert) {
     BIO_free(mem);
     if(!strict)
       return CURLE_OK;
@@ -4095,19 +4558,19 @@ static CURLcode servercert(struct Curl_cfilter *cf,
   infof(data, "%s certificate:",
         Curl_ssl_cf_is_proxy(cf)? "Proxy" : "Server");
 
-  rc = x509_name_oneline(X509_get_subject_name(backend->server_cert),
+  rc = x509_name_oneline(X509_get_subject_name(octx->server_cert),
                          buffer, sizeof(buffer));
   infof(data, " subject: %s", rc?"[NONE]":buffer);
 
 #ifndef CURL_DISABLE_VERBOSE_STRINGS
   {
     long len;
-    ASN1_TIME_print(mem, X509_get0_notBefore(backend->server_cert));
+    ASN1_TIME_print(mem, X509_get0_notBefore(octx->server_cert));
     len = BIO_get_mem_data(mem, (char **) &ptr);
     infof(data, " start date: %.*s", (int)len, ptr);
     (void)BIO_reset(mem);
 
-    ASN1_TIME_print(mem, X509_get0_notAfter(backend->server_cert));
+    ASN1_TIME_print(mem, X509_get0_notAfter(octx->server_cert));
     len = BIO_get_mem_data(mem, (char **) &ptr);
     infof(data, " expire date: %.*s", (int)len, ptr);
     (void)BIO_reset(mem);
@@ -4117,16 +4580,15 @@ static CURLcode servercert(struct Curl_cfilter *cf,
   BIO_free(mem);
 
   if(conn_config->verifyhost) {
-    result = ossl_verifyhost(data, conn, backend->server_cert,
-                             connssl->hostname, connssl->dispname);
+    result = Curl_ossl_verifyhost(data, conn, peer, octx->server_cert);
     if(result) {
-      X509_free(backend->server_cert);
-      backend->server_cert = NULL;
+      X509_free(octx->server_cert);
+      octx->server_cert = NULL;
       return result;
     }
   }
 
-  rc = x509_name_oneline(X509_get_issuer_name(backend->server_cert),
+  rc = x509_name_oneline(X509_get_issuer_name(octx->server_cert),
                          buffer, sizeof(buffer));
   if(rc) {
     if(strict)
@@ -4150,8 +4612,8 @@ static CURLcode servercert(struct Curl_cfilter *cf,
                 " error %s",
                 ossl_strerror(ERR_get_error(), error_buffer,
                               sizeof(error_buffer)) );
-          X509_free(backend->server_cert);
-          backend->server_cert = NULL;
+          X509_free(octx->server_cert);
+          octx->server_cert = NULL;
           return CURLE_OUT_OF_MEMORY;
         }
       }
@@ -4163,8 +4625,8 @@ static CURLcode servercert(struct Curl_cfilter *cf,
                 " error %s",
                 ossl_strerror(ERR_get_error(), error_buffer,
                               sizeof(error_buffer)) );
-          X509_free(backend->server_cert);
-          backend->server_cert = NULL;
+          X509_free(octx->server_cert);
+          octx->server_cert = NULL;
           return CURLE_OUT_OF_MEMORY;
         }
 
@@ -4173,8 +4635,8 @@ static CURLcode servercert(struct Curl_cfilter *cf,
             failf(data, "SSL: Unable to open issuer cert (%s)",
                   conn_config->issuercert);
           BIO_free(fp);
-          X509_free(backend->server_cert);
-          backend->server_cert = NULL;
+          X509_free(octx->server_cert);
+          octx->server_cert = NULL;
           return CURLE_SSL_ISSUER_ERROR;
         }
       }
@@ -4186,19 +4648,19 @@ static CURLcode servercert(struct Curl_cfilter *cf,
                 conn_config->issuercert);
         BIO_free(fp);
         X509_free(issuer);
-        X509_free(backend->server_cert);
-        backend->server_cert = NULL;
+        X509_free(octx->server_cert);
+        octx->server_cert = NULL;
         return CURLE_SSL_ISSUER_ERROR;
       }
 
-      if(X509_check_issued(issuer, backend->server_cert) != X509_V_OK) {
+      if(X509_check_issued(issuer, octx->server_cert) != X509_V_OK) {
         if(strict)
           failf(data, "SSL: Certificate issuer check failed (%s)",
                 conn_config->issuercert);
         BIO_free(fp);
         X509_free(issuer);
-        X509_free(backend->server_cert);
-        backend->server_cert = NULL;
+        X509_free(octx->server_cert);
+        octx->server_cert = NULL;
         return CURLE_SSL_ISSUER_ERROR;
       }
 
@@ -4208,7 +4670,7 @@ static CURLcode servercert(struct Curl_cfilter *cf,
       X509_free(issuer);
     }
 
-    lerr = SSL_get_verify_result(backend->handle);
+    lerr = SSL_get_verify_result(octx->ssl);
     ssl_config->certverifyresult = lerr;
     if(lerr != X509_V_OK) {
       if(conn_config->verifypeer) {
@@ -4228,13 +4690,31 @@ static CURLcode servercert(struct Curl_cfilter *cf,
       infof(data, " SSL certificate verify ok.");
   }
 
+  infof_certstack(data, octx->ssl);
+
 #if (OPENSSL_VERSION_NUMBER >= 0x0090808fL) && !defined(OPENSSL_NO_TLSEXT) && \
   !defined(OPENSSL_NO_OCSP)
-  if(conn_config->verifystatus) {
+  if(conn_config->verifystatus && !octx->reused_session) {
+    /* don't do this after Session ID reuse */
     result = verifystatus(cf, data);
     if(result) {
-      X509_free(backend->server_cert);
-      backend->server_cert = NULL;
+      /* when verifystatus failed, remove the session id from the cache again
+         if present */
+      if(!Curl_ssl_cf_is_proxy(cf)) {
+        void *old_ssl_sessionid = NULL;
+        bool incache;
+        Curl_ssl_sessionid_lock(data);
+        incache = !(Curl_ssl_getsessionid(cf, data, peer,
+                                          &old_ssl_sessionid, NULL));
+        if(incache) {
+          infof(data, "Remove session ID again from cache");
+          Curl_ssl_delsessionid(data, old_ssl_sessionid);
+        }
+        Curl_ssl_sessionid_unlock(data);
+      }
+
+      X509_free(octx->server_cert);
+      octx->server_cert = NULL;
       return result;
     }
   }
@@ -4244,18 +4724,21 @@ static CURLcode servercert(struct Curl_cfilter *cf,
     /* when not strict, we don't bother about the verify cert problems */
     result = CURLE_OK;
 
+#ifndef CURL_DISABLE_PROXY
   ptr = Curl_ssl_cf_is_proxy(cf)?
     data->set.str[STRING_SSL_PINNEDPUBLICKEY_PROXY]:
     data->set.str[STRING_SSL_PINNEDPUBLICKEY];
+#else
+  ptr = data->set.str[STRING_SSL_PINNEDPUBLICKEY];
+#endif
   if(!result && ptr) {
-    result = ossl_pkp_pin_peer_pubkey(data, backend->server_cert, ptr);
+    result = ossl_pkp_pin_peer_pubkey(data, octx->server_cert, ptr);
     if(result)
       failf(data, "SSL: public key does not match pinned public key");
   }
 
-  X509_free(backend->server_cert);
-  backend->server_cert = NULL;
-  connssl->connecting_state = ssl_connect_done;
+  X509_free(octx->server_cert);
+  octx->server_cert = NULL;
 
   return result;
 }
@@ -4265,7 +4748,7 @@ static CURLcode ossl_connect_step3(struct Curl_cfilter *cf,
 {
   CURLcode result = CURLE_OK;
   struct ssl_connect_data *connssl = cf->ctx;
-  struct ssl_primary_config *conn_config = Curl_ssl_cf_get_primary_config(cf);
+  struct ossl_ctx *octx = (struct ossl_ctx *)connssl->backend;
 
   DEBUGASSERT(ssl_connect_3 == connssl->connecting_state);
 
@@ -4276,9 +4759,7 @@ static CURLcode ossl_connect_step3(struct Curl_cfilter *cf,
    * operations.
    */
 
-  result = servercert(cf, data, conn_config->verifypeer ||
-                      conn_config->verifyhost);
-
+  result = Curl_oss_check_peer_cert(cf, data, octx, &connssl->peer);
   if(!result)
     connssl->connecting_state = ssl_connect_done;
 
@@ -4418,12 +4899,11 @@ static bool ossl_data_pending(struct Curl_cfilter *cf,
                               const struct Curl_easy *data)
 {
   struct ssl_connect_data *connssl = cf->ctx;
-  struct ossl_ssl_backend_data *backend =
-    (struct ossl_ssl_backend_data *)connssl->backend;
+  struct ossl_ctx *octx = (struct ossl_ctx *)connssl->backend;
 
   (void)data;
-  DEBUGASSERT(connssl && backend);
-  if(backend->handle && SSL_pending(backend->handle))
+  DEBUGASSERT(connssl && octx);
+  if(octx->ssl && SSL_pending(octx->ssl))
     return TRUE;
   return FALSE;
 }
@@ -4442,19 +4922,18 @@ static ssize_t ossl_send(struct Curl_cfilter *cf,
   int memlen;
   int rc;
   struct ssl_connect_data *connssl = cf->ctx;
-  struct ossl_ssl_backend_data *backend =
-    (struct ossl_ssl_backend_data *)connssl->backend;
+  struct ossl_ctx *octx = (struct ossl_ctx *)connssl->backend;
 
   (void)data;
-  DEBUGASSERT(backend);
+  DEBUGASSERT(octx);
 
   ERR_clear_error();
 
   memlen = (len > (size_t)INT_MAX) ? INT_MAX : (int)len;
-  rc = SSL_write(backend->handle, mem, memlen);
+  rc = SSL_write(octx->ssl, mem, memlen);
 
   if(rc <= 0) {
-    err = SSL_get_error(backend->handle, rc);
+    err = SSL_get_error(octx->ssl, rc);
 
     switch(err) {
     case SSL_ERROR_WANT_READ:
@@ -4469,7 +4948,7 @@ static ssize_t ossl_send(struct Curl_cfilter *cf,
     {
       int sockerr = SOCKERRNO;
 
-      if(backend->io_result == CURLE_AGAIN) {
+      if(octx->io_result == CURLE_AGAIN) {
         *curlcode = CURLE_AGAIN;
         rc = -1;
         goto out;
@@ -4479,10 +4958,10 @@ static ssize_t ossl_send(struct Curl_cfilter *cf,
         ossl_strerror(sslerror, error_buffer, sizeof(error_buffer));
       else if(sockerr)
         Curl_strerror(sockerr, error_buffer, sizeof(error_buffer));
-      else {
-        strncpy(error_buffer, SSL_ERROR_to_str(err), sizeof(error_buffer));
-        error_buffer[sizeof(error_buffer) - 1] = '\0';
-      }
+      else
+        msnprintf(error_buffer, sizeof(error_buffer), "%s",
+                  SSL_ERROR_to_str(err));
+
       failf(data, OSSL_PACKAGE " SSL_write: %s, errno %d",
             error_buffer, sockerr);
       *curlcode = CURLE_SEND_ERROR;
@@ -4492,22 +4971,9 @@ static ssize_t ossl_send(struct Curl_cfilter *cf,
     case SSL_ERROR_SSL: {
       /*  A failure in the SSL library occurred, usually a protocol error.
           The OpenSSL error queue contains more information on the error. */
-      struct Curl_cfilter *cf_ssl_next = Curl_ssl_cf_get_ssl(cf->next);
-      struct ssl_connect_data *connssl_next = cf_ssl_next?
-        cf_ssl_next->ctx : NULL;
       sslerror = ERR_get_error();
-      if(ERR_GET_LIB(sslerror) == ERR_LIB_SSL &&
-         ERR_GET_REASON(sslerror) == SSL_R_BIO_NOT_SET &&
-         connssl->state == ssl_connection_complete &&
-         (connssl_next && connssl_next->state == ssl_connection_complete)
-        ) {
-        char ver[120];
-        (void)ossl_version(ver, sizeof(ver));
-        failf(data, "Error: %s does not support double SSL tunneling.", ver);
-      }
-      else
-        failf(data, "SSL_write() error: %s",
-              ossl_strerror(sslerror, error_buffer, sizeof(error_buffer)));
+      failf(data, "SSL_write() error: %s",
+            ossl_strerror(sslerror, error_buffer, sizeof(error_buffer)));
       *curlcode = CURLE_SEND_ERROR;
       rc = -1;
       goto out;
@@ -4539,20 +5005,19 @@ static ssize_t ossl_recv(struct Curl_cfilter *cf,
   int buffsize;
   struct connectdata *conn = cf->conn;
   struct ssl_connect_data *connssl = cf->ctx;
-  struct ossl_ssl_backend_data *backend =
-    (struct ossl_ssl_backend_data *)connssl->backend;
+  struct ossl_ctx *octx = (struct ossl_ctx *)connssl->backend;
 
   (void)data;
-  DEBUGASSERT(backend);
+  DEBUGASSERT(octx);
 
   ERR_clear_error();
 
   buffsize = (buffersize > (size_t)INT_MAX) ? INT_MAX : (int)buffersize;
-  nread = (ssize_t)SSL_read(backend->handle, buf, buffsize);
+  nread = (ssize_t)SSL_read(octx->ssl, buf, buffsize);
 
   if(nread <= 0) {
     /* failed SSL_read */
-    int err = SSL_get_error(backend->handle, (int)nread);
+    int err = SSL_get_error(octx->ssl, (int)nread);
 
     switch(err) {
     case SSL_ERROR_NONE: /* this is not an error */
@@ -4574,7 +5039,7 @@ static ssize_t ossl_recv(struct Curl_cfilter *cf,
       /* openssl/ssl.h for SSL_ERROR_SYSCALL says "look at error stack/return
          value/errno" */
       /* https://www.openssl.org/docs/crypto/ERR_get_error.html */
-      if(backend->io_result == CURLE_AGAIN) {
+      if(octx->io_result == CURLE_AGAIN) {
         *curlcode = CURLE_AGAIN;
         nread = -1;
         goto out;
@@ -4588,10 +5053,9 @@ static ssize_t ossl_recv(struct Curl_cfilter *cf,
           ossl_strerror(sslerror, error_buffer, sizeof(error_buffer));
         else if(sockerr && err == SSL_ERROR_SYSCALL)
           Curl_strerror(sockerr, error_buffer, sizeof(error_buffer));
-        else {
-          strncpy(error_buffer, SSL_ERROR_to_str(err), sizeof(error_buffer));
-          error_buffer[sizeof(error_buffer) - 1] = '\0';
-        }
+        else
+          msnprintf(error_buffer, sizeof(error_buffer), "%s",
+                    SSL_ERROR_to_str(err));
         failf(data, OSSL_PACKAGE " SSL_read: %s, errno %d",
               error_buffer, sockerr);
         *curlcode = CURLE_RECV_ERROR;
@@ -4766,11 +5230,10 @@ static void *ossl_get_internals(struct ssl_connect_data *connssl,
                                 CURLINFO info)
 {
   /* Legacy: CURLINFO_TLS_SESSION must return an SSL_CTX pointer. */
-  struct ossl_ssl_backend_data *backend =
-    (struct ossl_ssl_backend_data *)connssl->backend;
-  DEBUGASSERT(backend);
+  struct ossl_ctx *octx = (struct ossl_ctx *)connssl->backend;
+  DEBUGASSERT(octx);
   return info == CURLINFO_TLS_SESSION ?
-    (void *)backend->ctx : (void *)backend->handle;
+    (void *)octx->ssl_ctx : (void *)octx->ssl;
 }
 
 static void ossl_free_multi_ssl_backend_data(
@@ -4797,10 +5260,13 @@ const struct Curl_ssl Curl_ssl_openssl = {
   SSLSUPP_SSL_CTX |
 #ifdef HAVE_SSL_CTX_SET_CIPHERSUITES
   SSLSUPP_TLS13_CIPHERSUITES |
+#endif
+#ifdef USE_ECH
+  SSLSUPP_ECH |
 #endif
   SSLSUPP_HTTPS_PROXY,
 
-  sizeof(struct ossl_ssl_backend_data),
+  sizeof(struct ossl_ctx),
 
   ossl_init,                /* init */
   ossl_cleanup,             /* cleanup */
@@ -4812,11 +5278,10 @@ const struct Curl_ssl Curl_ssl_openssl = {
   ossl_cert_status_request, /* cert_status_request */
   ossl_connect,             /* connect */
   ossl_connect_nonblocking, /* connect_nonblocking */
-  Curl_ssl_get_select_socks,/* getsock */
+  Curl_ssl_adjust_pollset,  /* adjust_pollset */
   ossl_get_internals,       /* get_internals */
   ossl_close,               /* close_one */
   ossl_close_all,           /* close_all */
-  ossl_session_free,        /* session_free */
   ossl_set_engine,          /* set_engine */
   ossl_set_engine_default,  /* set_engine_default */
   ossl_engines_list,        /* engines_list */
diff --git a/vendor/curl/lib/vtls/openssl.h b/vendor/curl/lib/vtls/openssl.h
index 950faab889..55e06bda44 100644
--- a/vendor/curl/lib/vtls/openssl.h
+++ b/vendor/curl/lib/vtls/openssl.h
@@ -31,24 +31,54 @@
  * This header should only be needed to get included by vtls.c, openssl.c
  * and ngtcp2.c
  */
+#include 
 #include 
 
 #include "urldata.h"
 
-/*
- * In an effort to avoid using 'X509 *' here, we instead use the struct
- * x509_st version of the type so that we can forward-declare it here without
- * having to include . Including that header causes name
- * conflicts when libcurl is built with both Schannel and OpenSSL support.
- */
-struct x509_st;
+/* Struct to hold a Curl OpenSSL instance */
+struct ossl_ctx {
+  /* these ones requires specific SSL-types */
+  SSL_CTX* ssl_ctx;
+  SSL*     ssl;
+  X509*    server_cert;
+  BIO_METHOD *bio_method;
+  CURLcode io_result;       /* result of last BIO cfilter operation */
+#ifndef HAVE_KEYLOG_CALLBACK
+  /* Set to true once a valid keylog entry has been created to avoid dupes. */
+  BIT(keylog_done);
+#endif
+  BIT(x509_store_setup);            /* x509 store has been set up */
+  BIT(reused_session);              /* session-ID was reused for this */
+};
+
+typedef CURLcode Curl_ossl_ctx_setup_cb(struct Curl_cfilter *cf,
+                                        struct Curl_easy *data,
+                                        void *user_data);
+
+typedef int Curl_ossl_new_session_cb(SSL *ssl, SSL_SESSION *ssl_sessionid);
+
+CURLcode Curl_ossl_ctx_init(struct ossl_ctx *octx,
+                            struct Curl_cfilter *cf,
+                            struct Curl_easy *data,
+                            struct ssl_peer *peer,
+                            int transport, /* TCP or QUIC */
+                            const unsigned char *alpn, size_t alpn_len,
+                            Curl_ossl_ctx_setup_cb *cb_setup,
+                            void *cb_user_data,
+                            Curl_ossl_new_session_cb *cb_new_session,
+                            void *ssl_user_data);
+
+#if (OPENSSL_VERSION_NUMBER < 0x30000000L)
+#define SSL_get1_peer_certificate SSL_get_peer_certificate
+#endif
+
 CURLcode Curl_ossl_verifyhost(struct Curl_easy *data, struct connectdata *conn,
-                              struct x509_st *server_cert);
+                              struct ssl_peer *peer, X509 *server_cert);
 extern const struct Curl_ssl Curl_ssl_openssl;
 
-struct ssl_ctx_st;
 CURLcode Curl_ossl_set_client_cert(struct Curl_easy *data,
-                                   struct ssl_ctx_st *ctx, char *cert_file,
+                                   SSL_CTX *ctx, char *cert_file,
                                    const struct curl_blob *cert_blob,
                                    const char *cert_type, char *key_file,
                                    const struct curl_blob *key_blob,
@@ -65,5 +95,27 @@ CURLcode Curl_ssl_setup_x509_store(struct Curl_cfilter *cf,
                                    struct Curl_easy *data,
                                    SSL_CTX *ssl_ctx);
 
+CURLcode Curl_ossl_ctx_configure(struct Curl_cfilter *cf,
+                                 struct Curl_easy *data,
+                                 SSL_CTX *ssl_ctx);
+
+/*
+ * Add a new session to the cache. Takes ownership of the session.
+ */
+CURLcode Curl_ossl_add_session(struct Curl_cfilter *cf,
+                               struct Curl_easy *data,
+                               const struct ssl_peer *peer,
+                               SSL_SESSION *ssl_sessionid);
+
+/*
+ * Get the server cert, verify it and show it, etc., only call failf() if
+ * ssl config verifypeer or -host is set. Otherwise all this is for
+ * informational purposes only!
+ */
+CURLcode Curl_oss_check_peer_cert(struct Curl_cfilter *cf,
+                                  struct Curl_easy *data,
+                                  struct ossl_ctx *octx,
+                                  struct ssl_peer *peer);
+
 #endif /* USE_OPENSSL */
 #endif /* HEADER_CURL_SSLUSE_H */
diff --git a/vendor/curl/lib/vtls/rustls.c b/vendor/curl/lib/vtls/rustls.c
index a3e9d964c9..8b6588a376 100644
--- a/vendor/curl/lib/vtls/rustls.c
+++ b/vendor/curl/lib/vtls/rustls.c
@@ -7,6 +7,7 @@
  *
  * Copyright (C) Jacob Hoffman-Andrews,
  * 
+ * Copyright (C) kpcyrd, 
  *
  * This software is licensed as described in the file COPYING, which
  * you should have received as part of this distribution. The terms
@@ -39,12 +40,14 @@
 #include "select.h"
 #include "strerror.h"
 #include "multiif.h"
+#include "connect.h" /* for the connect timeout */
 
 struct rustls_ssl_backend_data
 {
   const struct rustls_client_config *config;
   struct rustls_connection *conn;
-  bool data_pending;
+  size_t plain_out_buffered;
+  BIT(data_in_pending);
 };
 
 /* For a given rustls_result error code, return the best-matching CURLcode. */
@@ -59,7 +62,7 @@ static CURLcode map_error(rustls_result r)
     case RUSTLS_RESULT_NULL_PARAMETER:
       return CURLE_BAD_FUNCTION_ARGUMENT;
     default:
-      return CURLE_READ_ERROR;
+      return CURLE_RECV_ERROR;
   }
 }
 
@@ -72,15 +75,7 @@ cr_data_pending(struct Curl_cfilter *cf, const struct Curl_easy *data)
   (void)data;
   DEBUGASSERT(ctx && ctx->backend);
   backend = (struct rustls_ssl_backend_data *)ctx->backend;
-  return backend->data_pending;
-}
-
-static CURLcode
-cr_connect(struct Curl_cfilter *cf UNUSED_PARAM,
-           struct Curl_easy *data UNUSED_PARAM)
-{
-  infof(data, "rustls_connect: unimplemented");
-  return CURLE_SSL_CONNECT_ERROR;
+  return backend->data_in_pending;
 }
 
 struct io_ctx {
@@ -92,6 +87,7 @@ static int
 read_cb(void *userdata, uint8_t *buf, uintptr_t len, uintptr_t *out_n)
 {
   struct io_ctx *io_ctx = userdata;
+  struct ssl_connect_data *const connssl = io_ctx->cf->ctx;
   CURLcode result;
   int ret = 0;
   ssize_t nread = Curl_conn_cf_recv(io_ctx->cf->next, io_ctx->data,
@@ -103,7 +99,11 @@ read_cb(void *userdata, uint8_t *buf, uintptr_t len, uintptr_t *out_n)
     else
       ret = EINVAL;
   }
+  else if(nread == 0)
+    connssl->peer_closed = TRUE;
   *out_n = (int)nread;
+  CURL_TRC_CF(io_ctx->data, io_ctx->cf, "cf->next recv(len=%zu) -> %zd, %d",
+              len, nread, result);
   return ret;
 }
 
@@ -123,10 +123,8 @@ write_cb(void *userdata, const uint8_t *buf, uintptr_t len, uintptr_t *out_n)
       ret = EINVAL;
   }
   *out_n = (int)nwritten;
-  /*
-  CURL_TRC_CFX(io_ctx->data, io_ctx->cf, "cf->next send(len=%zu) -> %zd, %d",
-                len, nwritten, result));
-  */
+  CURL_TRC_CF(io_ctx->data, io_ctx->cf, "cf->next send(len=%zu) -> %zd, %d",
+              len, nwritten, result);
   return ret;
 }
 
@@ -153,7 +151,7 @@ static ssize_t tls_recv_more(struct Curl_cfilter *cf,
     char buffer[STRERROR_LEN];
     failf(data, "reading from socket: %s",
           Curl_strerror(io_error, buffer, sizeof(buffer)));
-    *err = CURLE_READ_ERROR;
+    *err = CURLE_RECV_ERROR;
     return -1;
   }
 
@@ -163,12 +161,12 @@ static ssize_t tls_recv_more(struct Curl_cfilter *cf,
     size_t errorlen;
     rustls_error(rresult, errorbuf, sizeof(errorbuf), &errorlen);
     failf(data, "rustls_connection_process_new_packets: %.*s",
-      errorlen, errorbuf);
+      (int)errorlen, errorbuf);
     *err = map_error(rresult);
     return -1;
   }
 
-  backend->data_pending = TRUE;
+  backend->data_in_pending = TRUE;
   *err = CURLE_OK;
   return (ssize_t)tls_bytes_read;
 }
@@ -203,7 +201,7 @@ cr_recv(struct Curl_cfilter *cf, struct Curl_easy *data,
   rconn = backend->conn;
 
   while(plain_bytes_copied < plainlen) {
-    if(!backend->data_pending) {
+    if(!backend->data_in_pending) {
       if(tls_recv_more(cf, data, err) < 0) {
         if(*err != CURLE_AGAIN) {
           nread = -1;
@@ -218,12 +216,12 @@ cr_recv(struct Curl_cfilter *cf, struct Curl_easy *data,
       plainlen - plain_bytes_copied,
       &n);
     if(rresult == RUSTLS_RESULT_PLAINTEXT_EMPTY) {
-      backend->data_pending = FALSE;
+      backend->data_in_pending = FALSE;
     }
     else if(rresult == RUSTLS_RESULT_UNEXPECTED_EOF) {
       failf(data, "rustls: peer closed TCP connection "
         "without first closing TLS connection");
-      *err = CURLE_READ_ERROR;
+      *err = CURLE_RECV_ERROR;
       nread = -1;
       goto out;
     }
@@ -232,8 +230,8 @@ cr_recv(struct Curl_cfilter *cf, struct Curl_easy *data,
       char errorbuf[255];
       size_t errorlen;
       rustls_error(rresult, errorbuf, sizeof(errorbuf), &errorlen);
-      failf(data, "rustls_connection_read: %.*s", errorlen, errorbuf);
-      *err = CURLE_READ_ERROR;
+      failf(data, "rustls_connection_read: %.*s", (int)errorlen, errorbuf);
+      *err = CURLE_RECV_ERROR;
       nread = -1;
       goto out;
     }
@@ -268,6 +266,42 @@ cr_recv(struct Curl_cfilter *cf, struct Curl_easy *data,
   return nread;
 }
 
+static CURLcode cr_flush_out(struct Curl_cfilter *cf, struct Curl_easy *data,
+                             struct rustls_connection *rconn)
+{
+  struct io_ctx io_ctx;
+  rustls_io_result io_error;
+  size_t tlswritten = 0;
+  size_t tlswritten_total = 0;
+  CURLcode result = CURLE_OK;
+
+  io_ctx.cf = cf;
+  io_ctx.data = data;
+
+  while(rustls_connection_wants_write(rconn)) {
+    io_error = rustls_connection_write_tls(rconn, write_cb, &io_ctx,
+                                           &tlswritten);
+    if(io_error == EAGAIN || io_error == EWOULDBLOCK) {
+      CURL_TRC_CF(data, cf, "cf_send: EAGAIN after %zu bytes",
+                  tlswritten_total);
+      return CURLE_AGAIN;
+    }
+    else if(io_error) {
+      char buffer[STRERROR_LEN];
+      failf(data, "writing to socket: %s",
+            Curl_strerror(io_error, buffer, sizeof(buffer)));
+      return CURLE_SEND_ERROR;
+    }
+    if(tlswritten == 0) {
+      failf(data, "EOF in swrite");
+      return CURLE_SEND_ERROR;
+    }
+    CURL_TRC_CF(data, cf, "cf_send: wrote %zu TLS bytes", tlswritten);
+    tlswritten_total += tlswritten;
+  }
+  return result;
+}
+
 /*
  * On each call:
  *  - Copy `plainlen` bytes into rustls' plaintext input buffer (if > 0).
@@ -286,29 +320,46 @@ cr_send(struct Curl_cfilter *cf, struct Curl_easy *data,
   struct rustls_ssl_backend_data *const backend =
     (struct rustls_ssl_backend_data *)connssl->backend;
   struct rustls_connection *rconn = NULL;
-  struct io_ctx io_ctx;
   size_t plainwritten = 0;
-  size_t tlswritten = 0;
-  size_t tlswritten_total = 0;
   rustls_result rresult;
-  rustls_io_result io_error;
   char errorbuf[256];
   size_t errorlen;
+  const unsigned char *buf = plainbuf;
+  size_t blen = plainlen;
+  ssize_t nwritten = 0;
 
   DEBUGASSERT(backend);
   rconn = backend->conn;
+  DEBUGASSERT(rconn);
+
+  CURL_TRC_CF(data, cf, "cf_send(len=%zu)", plainlen);
+
+  /* If a previous send blocked, we already added its plain bytes
+   * to rustsls and must not do that again. Flush the TLS bytes and,
+   * if successful, deduct the previous plain bytes from the current
+   * send. */
+  if(backend->plain_out_buffered) {
+    *err = cr_flush_out(cf, data, rconn);
+    CURL_TRC_CF(data, cf, "cf_send: flushing %zu previously added bytes -> %d",
+                backend->plain_out_buffered, *err);
+    if(*err)
+      return -1;
+    if(blen > backend->plain_out_buffered) {
+      blen -= backend->plain_out_buffered;
+      buf += backend->plain_out_buffered;
+    }
+    else
+      blen = 0;
+    nwritten += (ssize_t)backend->plain_out_buffered;
+    backend->plain_out_buffered = 0;
+  }
 
-  CURL_TRC_CF(data, cf, "cf_send: %ld plain bytes", plainlen);
-
-  io_ctx.cf = cf;
-  io_ctx.data = data;
-
-  if(plainlen > 0) {
-    rresult = rustls_connection_write(rconn, plainbuf, plainlen,
-                                      &plainwritten);
+  if(blen > 0) {
+    CURL_TRC_CF(data, cf, "cf_send: adding %zu plain bytes to rustls", blen);
+    rresult = rustls_connection_write(rconn, buf, blen, &plainwritten);
     if(rresult != RUSTLS_RESULT_OK) {
       rustls_error(rresult, errorbuf, sizeof(errorbuf), &errorlen);
-      failf(data, "rustls_connection_write: %.*s", errorlen, errorbuf);
+      failf(data, "rustls_connection_write: %.*s", (int)errorlen, errorbuf);
       *err = CURLE_WRITE_ERROR;
       return -1;
     }
@@ -319,37 +370,32 @@ cr_send(struct Curl_cfilter *cf, struct Curl_easy *data,
     }
   }
 
-  while(rustls_connection_wants_write(rconn)) {
-    io_error = rustls_connection_write_tls(rconn, write_cb, &io_ctx,
-                                           &tlswritten);
-    if(io_error == EAGAIN || io_error == EWOULDBLOCK) {
-      CURL_TRC_CF(data, cf, "cf_send: EAGAIN after %zu bytes",
-                  tlswritten_total);
-      *err = CURLE_AGAIN;
-      return -1;
-    }
-    else if(io_error) {
-      char buffer[STRERROR_LEN];
-      failf(data, "writing to socket: %s",
-            Curl_strerror(io_error, buffer, sizeof(buffer)));
-      *err = CURLE_WRITE_ERROR;
-      return -1;
-    }
-    if(tlswritten == 0) {
-      failf(data, "EOF in swrite");
-      *err = CURLE_WRITE_ERROR;
-      return -1;
+  *err = cr_flush_out(cf, data, rconn);
+  if(*err) {
+    if(CURLE_AGAIN == *err) {
+      /* The TLS bytes may have been partially written, but we fail the
+       * complete send() and remember how much we already added to rustls. */
+      CURL_TRC_CF(data, cf, "cf_send: EAGAIN, remember we added %zu plain"
+                  " bytes already to rustls", blen);
+      backend->plain_out_buffered = plainwritten;
+      if(nwritten) {
+        *err = CURLE_OK;
+        return (ssize_t)nwritten;
+      }
     }
-    CURL_TRC_CF(data, cf, "cf_send: wrote %zu TLS bytes", tlswritten);
-    tlswritten_total += tlswritten;
+    return -1;
   }
+  else
+    nwritten += (ssize_t)plainwritten;
 
-  return plainwritten;
+  CURL_TRC_CF(data, cf, "cf_send(len=%zu) -> %d, %zd",
+              plainlen, *err, nwritten);
+  return nwritten;
 }
 
 /* A server certificate verify callback for rustls that always returns
    RUSTLS_RESULT_OK, or in other words disable certificate verification. */
-static enum rustls_result
+static uint32_t
 cr_verify_none(void *userdata UNUSED_PARAM,
                const rustls_verify_server_cert_params *params UNUSED_PARAM)
 {
@@ -360,12 +406,12 @@ static bool
 cr_hostname_is_ip(const char *hostname)
 {
   struct in_addr in;
-#ifdef ENABLE_IPV6
+#ifdef USE_IPV6
   struct in6_addr in6;
   if(Curl_inet_pton(AF_INET6, hostname, &in6) > 0) {
     return true;
   }
-#endif /* ENABLE_IPV6 */
+#endif /* USE_IPV6 */
   if(Curl_inet_pton(AF_INET, hostname, &in) > 0) {
     return true;
   }
@@ -380,13 +426,16 @@ cr_init_backend(struct Curl_cfilter *cf, struct Curl_easy *data,
   struct ssl_primary_config *conn_config = Curl_ssl_cf_get_primary_config(cf);
   struct rustls_connection *rconn = NULL;
   struct rustls_client_config_builder *config_builder = NULL;
-  struct rustls_root_cert_store *roots = NULL;
+  const struct rustls_root_cert_store *roots = NULL;
+  struct rustls_root_cert_store_builder *roots_builder = NULL;
+  struct rustls_web_pki_server_cert_verifier_builder *verifier_builder = NULL;
+  struct rustls_server_cert_verifier *server_cert_verifier = NULL;
   const struct curl_blob *ca_info_blob = conn_config->ca_info_blob;
   const char * const ssl_cafile =
     /* CURLOPT_CAINFO_BLOB overrides CURLOPT_CAINFO */
     (ca_info_blob ? NULL : conn_config->CAfile);
   const bool verifypeer = conn_config->verifypeer;
-  const char *hostname = connssl->hostname;
+  const char *hostname = connssl->peer.hostname;
   char errorbuf[256];
   size_t errorlen;
   int result;
@@ -421,55 +470,72 @@ cr_init_backend(struct Curl_cfilter *cf, struct Curl_easy *data,
       hostname = "example.invalid";
     }
   }
-  else if(ca_info_blob) {
-    roots = rustls_root_cert_store_new();
-
-    /* Enable strict parsing only if verification isn't disabled. */
-    result = rustls_root_cert_store_add_pem(roots, ca_info_blob->data,
-                                            ca_info_blob->len, verifypeer);
-    if(result != RUSTLS_RESULT_OK) {
-      failf(data, "rustls: failed to parse trusted certificates from blob");
-      rustls_root_cert_store_free(roots);
-      rustls_client_config_free(
-        rustls_client_config_builder_build(config_builder));
-      return CURLE_SSL_CACERT_BADFILE;
+  else if(ca_info_blob || ssl_cafile) {
+    roots_builder = rustls_root_cert_store_builder_new();
+
+    if(ca_info_blob) {
+      /* Enable strict parsing only if verification isn't disabled. */
+      result = rustls_root_cert_store_builder_add_pem(roots_builder,
+                                                      ca_info_blob->data,
+                                                      ca_info_blob->len,
+                                                      verifypeer);
+      if(result != RUSTLS_RESULT_OK) {
+        failf(data, "rustls: failed to parse trusted certificates from blob");
+        rustls_root_cert_store_builder_free(roots_builder);
+        rustls_client_config_free(
+          rustls_client_config_builder_build(config_builder));
+        return CURLE_SSL_CACERT_BADFILE;
+      }
+    }
+    else if(ssl_cafile) {
+      /* Enable strict parsing only if verification isn't disabled. */
+      result = rustls_root_cert_store_builder_load_roots_from_file(
+        roots_builder, ssl_cafile, verifypeer);
+      if(result != RUSTLS_RESULT_OK) {
+        failf(data, "rustls: failed to load trusted certificates");
+        rustls_root_cert_store_builder_free(roots_builder);
+        rustls_client_config_free(
+          rustls_client_config_builder_build(config_builder));
+        return CURLE_SSL_CACERT_BADFILE;
+      }
     }
 
-    result = rustls_client_config_builder_use_roots(config_builder, roots);
-    rustls_root_cert_store_free(roots);
+    result = rustls_root_cert_store_builder_build(roots_builder, &roots);
+    rustls_root_cert_store_builder_free(roots_builder);
     if(result != RUSTLS_RESULT_OK) {
       failf(data, "rustls: failed to load trusted certificates");
       rustls_client_config_free(
         rustls_client_config_builder_build(config_builder));
       return CURLE_SSL_CACERT_BADFILE;
     }
-  }
-  else if(ssl_cafile) {
-    result = rustls_client_config_builder_load_roots_from_file(
-      config_builder, ssl_cafile);
+
+    verifier_builder = rustls_web_pki_server_cert_verifier_builder_new(roots);
+
+    result = rustls_web_pki_server_cert_verifier_builder_build(
+      verifier_builder, &server_cert_verifier);
+    rustls_web_pki_server_cert_verifier_builder_free(verifier_builder);
     if(result != RUSTLS_RESULT_OK) {
       failf(data, "rustls: failed to load trusted certificates");
+      rustls_server_cert_verifier_free(server_cert_verifier);
       rustls_client_config_free(
         rustls_client_config_builder_build(config_builder));
       return CURLE_SSL_CACERT_BADFILE;
     }
+
+    rustls_client_config_builder_set_server_verifier(config_builder,
+                                                     server_cert_verifier);
   }
 
   backend->config = rustls_client_config_builder_build(config_builder);
   DEBUGASSERT(rconn == NULL);
-  {
-    char *snihost = Curl_ssl_snihost(data, hostname, NULL);
-    if(!snihost) {
-      failf(data, "rustls: failed to get SNI");
-      return CURLE_SSL_CONNECT_ERROR;
-    }
-    result = rustls_client_connection_new(backend->config, snihost, &rconn);
-  }
+  result = rustls_client_connection_new(backend->config,
+                                        connssl->peer.hostname, &rconn);
   if(result != RUSTLS_RESULT_OK) {
     rustls_error(result, errorbuf, sizeof(errorbuf), &errorlen);
-    failf(data, "rustls_client_connection_new: %.*s", errorlen, errorbuf);
+    failf(data, "rustls_client_connection_new: %.*s", (int)errorlen, errorbuf);
     return CURLE_COULDNT_CONNECT;
   }
+  DEBUGASSERT(rconn);
   rustls_connection_set_userdata(rconn, backend);
   backend->conn = rconn;
   return CURLE_OK;
@@ -486,9 +552,20 @@ cr_set_negotiated_alpn(struct Curl_cfilter *cf, struct Curl_easy *data,
   Curl_alpn_set_negotiated(cf, data, protocol, len);
 }
 
+/* Given an established network connection, do a TLS handshake.
+ *
+ * If `blocking` is true, this function will block until the handshake is
+ * complete. Otherwise it will return as soon as I/O would block.
+ *
+ * For the non-blocking I/O case, this function will set `*done` to true
+ * once the handshake is complete. This function never reads the value of
+ * `*done*`.
+ */
 static CURLcode
-cr_connect_nonblocking(struct Curl_cfilter *cf,
-                       struct Curl_easy *data, bool *done)
+cr_connect_common(struct Curl_cfilter *cf,
+                  struct Curl_easy *data,
+                  bool blocking,
+                  bool *done)
 {
   struct ssl_connect_data *const connssl = cf->ctx;
   curl_socket_t sockfd = Curl_conn_cf_get_socket(cf, data);
@@ -502,12 +579,17 @@ cr_connect_nonblocking(struct Curl_cfilter *cf,
   bool wants_write;
   curl_socket_t writefd;
   curl_socket_t readfd;
+  timediff_t timeout_ms;
+  timediff_t socket_check_timeout;
 
   DEBUGASSERT(backend);
 
-  if(ssl_connection_none == connssl->state) {
+  CURL_TRC_CF(data, cf, "cr_connect_common, state=%d", connssl->state);
+  *done = FALSE;
+  if(!backend->conn) {
     result = cr_init_backend(cf, data,
                (struct rustls_ssl_backend_data *)connssl->backend);
+    CURL_TRC_CF(data, cf, "cr_connect_common, init backend -> %d", result);
     if(result != CURLE_OK) {
       return result;
     }
@@ -524,41 +606,70 @@ cr_connect_nonblocking(struct Curl_cfilter *cf,
     */
     if(!rustls_connection_is_handshaking(rconn)) {
       infof(data, "Done handshaking");
-      /* Done with the handshake. Set up callbacks to send/receive data. */
-      connssl->state = ssl_connection_complete;
-
+      /* rustls claims it is no longer handshaking *before* it has
+       * send its FINISHED message off. We attempt to let it write
+       * one more time. Oh my.
+       */
       cr_set_negotiated_alpn(cf, data, rconn);
-
+      cr_send(cf, data, NULL, 0, &tmperr);
+      if(tmperr == CURLE_AGAIN) {
+        connssl->connecting_state = ssl_connect_2_writing;
+        return CURLE_OK;
+      }
+      else if(tmperr != CURLE_OK) {
+        return tmperr;
+      }
+      /* REALLY Done with the handshake. */
+      connssl->state = ssl_connection_complete;
       *done = TRUE;
       return CURLE_OK;
     }
 
     wants_read = rustls_connection_wants_read(rconn);
-    wants_write = rustls_connection_wants_write(rconn);
+    wants_write = rustls_connection_wants_write(rconn) ||
+                  backend->plain_out_buffered;
     DEBUGASSERT(wants_read || wants_write);
     writefd = wants_write?sockfd:CURL_SOCKET_BAD;
     readfd = wants_read?sockfd:CURL_SOCKET_BAD;
 
-    what = Curl_socket_check(readfd, CURL_SOCKET_BAD, writefd, 0);
+    connssl->connecting_state = wants_write?
+      ssl_connect_2_writing : ssl_connect_2_reading;
+    /* check allowed time left */
+    timeout_ms = Curl_timeleft(data, NULL, TRUE);
+
+    if(timeout_ms < 0) {
+      /* no need to continue if time already is up */
+      failf(data, "rustls: operation timed out before socket check");
+      return CURLE_OPERATION_TIMEDOUT;
+    }
+
+    socket_check_timeout = blocking?timeout_ms:0;
+
+    what = Curl_socket_check(readfd, CURL_SOCKET_BAD, writefd,
+                             socket_check_timeout);
     if(what < 0) {
       /* fatal error */
       failf(data, "select/poll on SSL socket, errno: %d", SOCKERRNO);
       return CURLE_SSL_CONNECT_ERROR;
     }
+    if(blocking && 0 == what) {
+      failf(data, "rustls connection timeout after %"
+        CURL_FORMAT_TIMEDIFF_T " ms", socket_check_timeout);
+      return CURLE_OPERATION_TIMEDOUT;
+    }
     if(0 == what) {
-      infof(data, "Curl_socket_check: %s would block",
+      CURL_TRC_CF(data, cf, "Curl_socket_check: %s would block",
             wants_read&&wants_write ? "writing and reading" :
             wants_write ? "writing" : "reading");
-      *done = FALSE;
       return CURLE_OK;
     }
     /* socket is readable or writable */
 
     if(wants_write) {
-      infof(data, "rustls_connection wants us to write_tls.");
+      CURL_TRC_CF(data, cf, "rustls_connection wants us to write_tls.");
       cr_send(cf, data, NULL, 0, &tmperr);
       if(tmperr == CURLE_AGAIN) {
-        infof(data, "writing would block");
+        CURL_TRC_CF(data, cf, "writing would block");
         /* fall through */
       }
       else if(tmperr != CURLE_OK) {
@@ -567,14 +678,13 @@ cr_connect_nonblocking(struct Curl_cfilter *cf,
     }
 
     if(wants_read) {
-      infof(data, "rustls_connection wants us to read_tls.");
-
+      CURL_TRC_CF(data, cf, "rustls_connection wants us to read_tls.");
       if(tls_recv_more(cf, data, &tmperr) < 0) {
         if(tmperr == CURLE_AGAIN) {
-          infof(data, "reading would block");
+          CURL_TRC_CF(data, cf, "reading would block");
           /* fall through */
         }
-        else if(tmperr == CURLE_READ_ERROR) {
+        else if(tmperr == CURLE_RECV_ERROR) {
           return CURLE_SSL_CONNECT_ERROR;
         }
         else {
@@ -589,32 +699,18 @@ cr_connect_nonblocking(struct Curl_cfilter *cf,
   DEBUGASSERT(false);
 }
 
-/* returns a bitmap of flags for this connection's first socket indicating
-   whether we want to read or write */
-static int
-cr_get_select_socks(struct Curl_cfilter *cf, struct Curl_easy *data,
-                    curl_socket_t *socks)
+static CURLcode
+cr_connect_nonblocking(struct Curl_cfilter *cf,
+                       struct Curl_easy *data, bool *done)
 {
-  struct ssl_connect_data *const connssl = cf->ctx;
-  curl_socket_t sockfd = Curl_conn_cf_get_socket(cf, data);
-  struct rustls_ssl_backend_data *const backend =
-    (struct rustls_ssl_backend_data *)connssl->backend;
-  struct rustls_connection *rconn = NULL;
-
-  (void)data;
-  DEBUGASSERT(backend);
-  rconn = backend->conn;
-
-  if(rustls_connection_wants_write(rconn)) {
-    socks[0] = sockfd;
-    return GETSOCK_WRITESOCK(0);
-  }
-  if(rustls_connection_wants_read(rconn)) {
-    socks[0] = sockfd;
-    return GETSOCK_READSOCK(0);
-  }
+  return cr_connect_common(cf, data, false, done);
+}
 
-  return GETSOCK_BLANK;
+static CURLcode
+cr_connect_blocking(struct Curl_cfilter *cf, struct Curl_easy *data)
+{
+  bool done; /* unused */
+  return cr_connect_common(cf, data, true, &done);
 }
 
 static void *
@@ -637,8 +733,8 @@ cr_close(struct Curl_cfilter *cf, struct Curl_easy *data)
   ssize_t n = 0;
 
   DEBUGASSERT(backend);
-
-  if(backend->conn) {
+  if(backend->conn && !connssl->peer_closed) {
+    CURL_TRC_CF(data, cf, "closing connection, send notify");
     rustls_connection_send_close_notify(backend->conn);
     n = cr_send(cf, data, NULL, 0, &tmperr);
     if(n < 0) {
@@ -663,7 +759,6 @@ static size_t cr_version(char *buffer, size_t size)
 const struct Curl_ssl Curl_ssl_rustls = {
   { CURLSSLBACKEND_RUSTLS, "rustls" },
   SSLSUPP_CAINFO_BLOB |            /* supports */
-  SSLSUPP_TLS13_CIPHERSUITES |
   SSLSUPP_HTTPS_PROXY,
   sizeof(struct rustls_ssl_backend_data),
 
@@ -675,13 +770,12 @@ const struct Curl_ssl Curl_ssl_rustls = {
   cr_data_pending,                 /* data_pending */
   Curl_none_random,                /* random */
   Curl_none_cert_status_request,   /* cert_status_request */
-  cr_connect,                      /* connect */
+  cr_connect_blocking,             /* connect */
   cr_connect_nonblocking,          /* connect_nonblocking */
-  cr_get_select_socks,             /* get_select_socks */
+  Curl_ssl_adjust_pollset,         /* adjust_pollset */
   cr_get_internals,                /* get_internals */
   cr_close,                        /* close_one */
   Curl_none_close_all,             /* close_all */
-  Curl_none_session_free,          /* session_free */
   Curl_none_set_engine,            /* set_engine */
   Curl_none_set_engine_default,    /* set_engine_default */
   Curl_none_engines_list,          /* engines_list */
diff --git a/vendor/curl/lib/vtls/schannel.c b/vendor/curl/lib/vtls/schannel.c
index f6a5d441a9..19cdc4b20b 100644
--- a/vendor/curl/lib/vtls/schannel.c
+++ b/vendor/curl/lib/vtls/schannel.c
@@ -68,22 +68,6 @@
 #  define HAS_ALPN 1
 #endif
 
-#ifndef UNISP_NAME_A
-#define UNISP_NAME_A "Microsoft Unified Security Protocol Provider"
-#endif
-
-#ifndef UNISP_NAME_W
-#define UNISP_NAME_W L"Microsoft Unified Security Protocol Provider"
-#endif
-
-#ifndef UNISP_NAME
-#ifdef UNICODE
-#define UNISP_NAME  UNISP_NAME_W
-#else
-#define UNISP_NAME  UNISP_NAME_A
-#endif
-#endif
-
 #ifndef BCRYPT_CHACHA20_POLY1305_ALGORITHM
 #define BCRYPT_CHACHA20_POLY1305_ALGORITHM L"CHACHA20_POLY1305"
 #endif
@@ -108,13 +92,6 @@
 #define BCRYPT_SHA384_ALGORITHM L"SHA384"
 #endif
 
-/* Workaround broken compilers like MinGW.
-   Return the number of elements in a statically sized array.
-*/
-#ifndef ARRAYSIZE
-#define ARRAYSIZE(A) (sizeof(A)/sizeof((A)[0]))
-#endif
-
 #ifdef HAS_CLIENT_CERT_PATH
 #ifdef UNICODE
 #define CURL_CERT_STORE_PROV_SYSTEM CERT_STORE_PROV_SYSTEM_W
@@ -123,18 +100,6 @@
 #endif
 #endif
 
-#ifndef SP_PROT_SSL2_CLIENT
-#define SP_PROT_SSL2_CLIENT             0x00000008
-#endif
-
-#ifndef SP_PROT_SSL3_CLIENT
-#define SP_PROT_SSL3_CLIENT             0x00000008
-#endif
-
-#ifndef SP_PROT_TLS1_CLIENT
-#define SP_PROT_TLS1_CLIENT             0x00000080
-#endif
-
 #ifndef SP_PROT_TLS1_0_CLIENT
 #define SP_PROT_TLS1_0_CLIENT           SP_PROT_TLS1_CLIENT
 #endif
@@ -175,12 +140,6 @@
 #  define CALG_SHA_256 0x0000800c
 #endif
 
-/* Work around typo in classic MinGW's w32api up to version 5.0,
-   see https://osdn.net/projects/mingw/ticket/38391 */
-#if !defined(ALG_CLASS_DHASH) && defined(ALG_CLASS_HASH)
-#define ALG_CLASS_DHASH ALG_CLASS_HASH
-#endif
-
 #ifndef PKCS12_NO_PERSIST_KEY
 #define PKCS12_NO_PERSIST_KEY 0x00008000
 #endif
@@ -480,6 +439,12 @@ get_cert_location(TCHAR *path, DWORD *store_name, TCHAR **store_path,
   return CURLE_OK;
 }
 #endif
+
+static bool algo(const char *check, char *namep, size_t nlen)
+{
+  return (strlen(check) == nlen) && !strncmp(check, namep, nlen);
+}
+
 static CURLcode
 schannel_acquire_credential_handle(struct Curl_cfilter *cf,
                                    struct Curl_easy *data)
@@ -701,7 +666,7 @@ schannel_acquire_credential_handle(struct Curl_cfilter *cf,
                 cert_showfilename_error);
         else
           failf(data, "schannel: Failed to import cert file %s, "
-                "last error is 0x%x",
+                "last error is 0x%lx",
                 cert_showfilename_error, errorcode);
         return CURLE_SSL_CERTPROBLEM;
       }
@@ -712,7 +677,7 @@ schannel_acquire_credential_handle(struct Curl_cfilter *cf,
 
       if(!client_certs[0]) {
         failf(data, "schannel: Failed to get certificate from file %s"
-              ", last error is 0x%x",
+              ", last error is 0x%lx",
               cert_showfilename_error, GetLastError());
         CertCloseStore(cert_store, 0);
         return CURLE_SSL_CERTPROBLEM;
@@ -725,10 +690,15 @@ schannel_acquire_credential_handle(struct Curl_cfilter *cf,
                       CERT_STORE_OPEN_EXISTING_FLAG | cert_store_name,
                       cert_store_path);
       if(!cert_store) {
-        failf(data, "schannel: Failed to open cert store %x %s, "
-              "last error is 0x%x",
-              cert_store_name, cert_store_path, GetLastError());
+        char *path_utf8 =
+          curlx_convert_tchar_to_UTF8(cert_store_path);
+        failf(data, "schannel: Failed to open cert store %lx %s, "
+              "last error is 0x%lx",
+              cert_store_name,
+              (path_utf8 ? path_utf8 : "(unknown)"),
+              GetLastError());
         free(cert_store_path);
+        curlx_unicodefree(path_utf8);
         curlx_unicodefree(cert_path);
         return CURLE_SSL_CERTPROBLEM;
       }
@@ -769,7 +739,7 @@ schannel_acquire_credential_handle(struct Curl_cfilter *cf,
   }
 #endif
 
-  /* allocate memory for the re-usable credential handle */
+  /* allocate memory for the reusable credential handle */
   backend->cred = (struct Curl_schannel_cred *)
     calloc(1, sizeof(struct Curl_schannel_cred));
   if(!backend->cred) {
@@ -831,9 +801,7 @@ schannel_acquire_credential_handle(struct Curl_cfilter *cf,
 
       char *startCur = ciphers13;
       int algCount = 0;
-      char tmp[LONGEST_ALG_ID] = { 0 };
       char *nameEnd;
-      size_t n;
 
       disable_aes_gcm_sha384 = TRUE;
       disable_aes_gcm_sha256 = TRUE;
@@ -842,40 +810,34 @@ schannel_acquire_credential_handle(struct Curl_cfilter *cf,
       disable_aes_ccm_sha256 = TRUE;
 
       while(startCur && (0 != *startCur) && (algCount < remaining_ciphers)) {
+        size_t n;
+        char *namep;
         nameEnd = strchr(startCur, ':');
         n = nameEnd ? (size_t)(nameEnd - startCur) : strlen(startCur);
+        namep = startCur;
 
-        /* reject too-long cipher names */
-        if(n > (LONGEST_ALG_ID - 1)) {
-          failf(data, "schannel: Cipher name too long, not checked");
-          return CURLE_SSL_CIPHER;
-        }
-
-        strncpy(tmp, startCur, n);
-        tmp[n] = 0;
-
-        if(disable_aes_gcm_sha384
-           && !strcmp("TLS_AES_256_GCM_SHA384", tmp)) {
+        if(disable_aes_gcm_sha384 &&
+           algo("TLS_AES_256_GCM_SHA384", namep, n)) {
           disable_aes_gcm_sha384 = FALSE;
         }
         else if(disable_aes_gcm_sha256
-                && !strcmp("TLS_AES_128_GCM_SHA256", tmp)) {
+                && algo("TLS_AES_128_GCM_SHA256", namep, n)) {
           disable_aes_gcm_sha256 = FALSE;
         }
         else if(disable_chacha_poly
-                && !strcmp("TLS_CHACHA20_POLY1305_SHA256", tmp)) {
+                && algo("TLS_CHACHA20_POLY1305_SHA256", namep, n)) {
           disable_chacha_poly = FALSE;
         }
         else if(disable_aes_ccm_8_sha256
-                && !strcmp("TLS_AES_128_CCM_8_SHA256", tmp)) {
+                && algo("TLS_AES_128_CCM_8_SHA256", namep, n)) {
           disable_aes_ccm_8_sha256 = FALSE;
         }
         else if(disable_aes_ccm_sha256
-                && !strcmp("TLS_AES_128_CCM_SHA256", tmp)) {
+                && algo("TLS_AES_128_CCM_SHA256", namep, n)) {
           disable_aes_ccm_sha256 = FALSE;
         }
         else {
-          failf(data, "schannel: Unknown TLS 1.3 cipher: %s", tmp);
+          failf(data, "schannel: Unknown TLS 1.3 cipher: %.*s", (int)n, namep);
           return CURLE_SSL_CIPHER;
         }
 
@@ -1104,17 +1066,12 @@ schannel_connect_step1(struct Curl_cfilter *cf, struct Curl_easy *data)
 #endif
   SECURITY_STATUS sspi_status = SEC_E_OK;
   struct Curl_schannel_cred *old_cred = NULL;
-  struct in_addr addr;
-#ifdef ENABLE_IPV6
-  struct in6_addr addr6;
-#endif
   CURLcode result;
-  const char *hostname = connssl->hostname;
 
   DEBUGASSERT(backend);
   DEBUGF(infof(data,
                "schannel: SSL/TLS connection with %s port %d (step 1/3)",
-               hostname, connssl->port));
+               connssl->peer.hostname, connssl->peer.port));
 
   if(curlx_verify_windows_version(5, 1, 0, PLATFORM_WINNT,
                                   VERSION_LESS_THAN_EQUAL)) {
@@ -1169,10 +1126,11 @@ schannel_connect_step1(struct Curl_cfilter *cf, struct Curl_easy *data)
 
   backend->cred = NULL;
 
-  /* check for an existing re-usable credential handle */
+  /* check for an existing reusable credential handle */
   if(ssl_config->primary.sessionid) {
     Curl_ssl_sessionid_lock(data);
-    if(!Curl_ssl_getsessionid(cf, data, (void **)&old_cred, NULL)) {
+    if(!Curl_ssl_getsessionid(cf, data, &connssl->peer,
+                              (void **)&old_cred, NULL)) {
       backend->cred = old_cred;
       DEBUGF(infof(data, "schannel: reusing existing credential handle"));
 
@@ -1195,22 +1153,14 @@ schannel_connect_step1(struct Curl_cfilter *cf, struct Curl_easy *data)
 
     /* A hostname associated with the credential is needed by
        InitializeSecurityContext for SNI and other reasons. */
-    snihost = Curl_ssl_snihost(data, hostname, NULL);
-    if(!snihost) {
-      failf(data, "Failed to set SNI");
-      return CURLE_SSL_CONNECT_ERROR;
-    }
+    snihost = connssl->peer.sni? connssl->peer.sni : connssl->peer.hostname;
     backend->cred->sni_hostname = curlx_convert_UTF8_to_tchar(snihost);
     if(!backend->cred->sni_hostname)
       return CURLE_OUT_OF_MEMORY;
   }
 
   /* Warn if SNI is disabled due to use of an IP address */
-  if(Curl_inet_pton(AF_INET, hostname, &addr)
-#ifdef ENABLE_IPV6
-     || Curl_inet_pton(AF_INET6, hostname, &addr6)
-#endif
-    ) {
+  if(connssl->peer.type != CURL_SSL_PEER_DNS) {
     infof(data, "schannel: using IP address, SNI is not supported by OS.");
   }
 
@@ -1249,9 +1199,8 @@ schannel_connect_step1(struct Curl_cfilter *cf, struct Curl_easy *data)
     cur += proto.len;
 
     *list_len = curlx_uitous(cur - list_start_index);
-    *extension_len = *list_len +
-      (unsigned short)sizeof(unsigned int) +
-      (unsigned short)sizeof(unsigned short);
+    *extension_len = (unsigned int)(*list_len +
+      sizeof(unsigned int) + sizeof(unsigned short));
 
     InitSecBuffer(&inbuf, SECBUFFER_APPLICATION_PROTOCOLS, alpn_buffer, cur);
     InitSecBufferDesc(&inbuf_desc, &inbuf, 1);
@@ -1387,7 +1336,7 @@ schannel_connect_step2(struct Curl_cfilter *cf, struct Curl_easy *data)
 
   DEBUGF(infof(data,
                "schannel: SSL/TLS connection with %s port %d (step 2/3)",
-               connssl->hostname, connssl->port));
+               connssl->peer.hostname, connssl->peer.port));
 
   if(!backend->cred || !backend->ctxt)
     return CURLE_SSL_CONNECT_ERROR;
@@ -1621,9 +1570,13 @@ schannel_connect_step2(struct Curl_cfilter *cf, struct Curl_easy *data)
     DEBUGF(infof(data, "schannel: SSL/TLS handshake complete"));
   }
 
+#ifndef CURL_DISABLE_PROXY
   pubkey_ptr = Curl_ssl_cf_is_proxy(cf)?
     data->set.str[STRING_SSL_PINNEDPUBLICKEY_PROXY]:
     data->set.str[STRING_SSL_PINNEDPUBLICKEY];
+#else
+  pubkey_ptr = data->set.str[STRING_SSL_PINNEDPUBLICKEY];
+#endif
   if(pubkey_ptr) {
     result = schannel_pkp_pin_peer_pubkey(cf, data, pubkey_ptr);
     if(result) {
@@ -1722,6 +1675,28 @@ add_cert_to_certinfo(const CERT_CONTEXT *ccert_context, bool reverse_order,
   return args->result == CURLE_OK;
 }
 
+static void schannel_session_free(void *sessionid, size_t idsize)
+{
+  /* this is expected to be called under sessionid lock */
+  struct Curl_schannel_cred *cred = sessionid;
+
+  (void)idsize;
+  if(cred) {
+    cred->refcount--;
+    if(cred->refcount == 0) {
+      s_pSecFn->FreeCredentialsHandle(&cred->cred_handle);
+      curlx_unicodefree(cred->sni_hostname);
+#ifdef HAS_CLIENT_CERT_PATH
+      if(cred->client_cert_store) {
+        CertCloseStore(cred->client_cert_store, 0);
+        cred->client_cert_store = NULL;
+      }
+#endif
+      Curl_safefree(cred);
+    }
+  }
+}
+
 static CURLcode
 schannel_connect_step3(struct Curl_cfilter *cf, struct Curl_easy *data)
 {
@@ -1741,7 +1716,7 @@ schannel_connect_step3(struct Curl_cfilter *cf, struct Curl_easy *data)
 
   DEBUGF(infof(data,
                "schannel: SSL/TLS connection with %s port %d (step 3/3)",
-               connssl->hostname, connssl->port));
+               connssl->peer.hostname, connssl->peer.port));
 
   if(!backend->cred)
     return CURLE_SSL_CONNECT_ERROR;
@@ -1799,11 +1774,11 @@ schannel_connect_step3(struct Curl_cfilter *cf, struct Curl_easy *data)
   /* save the current session data for possible reuse */
   if(ssl_config->primary.sessionid) {
     bool incache;
-    bool added = FALSE;
     struct Curl_schannel_cred *old_cred = NULL;
 
     Curl_ssl_sessionid_lock(data);
-    incache = !(Curl_ssl_getsessionid(cf, data, (void **)&old_cred, NULL));
+    incache = !(Curl_ssl_getsessionid(cf, data, &connssl->peer,
+                                      (void **)&old_cred, NULL));
     if(incache) {
       if(old_cred != backend->cred) {
         DEBUGF(infof(data,
@@ -1814,20 +1789,15 @@ schannel_connect_step3(struct Curl_cfilter *cf, struct Curl_easy *data)
       }
     }
     if(!incache) {
-      result = Curl_ssl_addsessionid(cf, data, backend->cred,
+      /* Up ref count since call takes ownership */
+      backend->cred->refcount++;
+      result = Curl_ssl_addsessionid(cf, data, &connssl->peer, backend->cred,
                                      sizeof(struct Curl_schannel_cred),
-                                     &added);
+                                     schannel_session_free);
       if(result) {
         Curl_ssl_sessionid_unlock(data);
-        failf(data, "schannel: failed to store credential handle");
         return result;
       }
-      else if(added) {
-        /* this cred session is now also referenced by sessionid cache */
-        backend->cred->refcount++;
-        DEBUGF(infof(data,
-                     "schannel: stored credential handle in session cache"));
-      }
     }
     Curl_ssl_sessionid_unlock(data);
   }
@@ -2185,7 +2155,6 @@ schannel_recv(struct Curl_cfilter *cf, struct Curl_easy *data,
     infof(data, "schannel: server indicated shutdown in a prior call");
     goto cleanup;
   }
-
   /* It's debatable what to return when !len. Regardless we can't return
      immediately because there may be data to decrypt (in the case we want to
      decrypt all encrypted cached data) so handle !len later in cleanup.
@@ -2369,10 +2338,10 @@ schannel_recv(struct Curl_cfilter *cf, struct Curl_easy *data,
         /* In Windows 2000 SEC_I_CONTEXT_EXPIRED (close_notify) is not
            returned so we have to work around that in cleanup. */
         backend->recv_sspi_close_notify = true;
-        if(!backend->recv_connection_closed) {
+        if(!backend->recv_connection_closed)
           backend->recv_connection_closed = true;
-          infof(data, "schannel: server closed the connection");
-        }
+        infof(data,
+              "schannel: server close notification received (close_notify)");
         goto cleanup;
       }
     }
@@ -2386,10 +2355,10 @@ schannel_recv(struct Curl_cfilter *cf, struct Curl_easy *data,
     else {
 #ifndef CURL_DISABLE_VERBOSE_STRINGS
       char buffer[STRERROR_LEN];
-#endif
-      *err = CURLE_RECV_ERROR;
       infof(data, "schannel: failed to read data from server: %s",
             Curl_sspi_strerror(sspi_status, buffer, sizeof(buffer)));
+#endif
+      *err = CURLE_RECV_ERROR;
       goto cleanup;
     }
   }
@@ -2495,32 +2464,14 @@ static bool schannel_data_pending(struct Curl_cfilter *cf,
 
   if(backend->ctxt) /* SSL/TLS is in use */
     return (backend->decdata_offset > 0 ||
-            (backend->encdata_offset > 0 && !backend->encdata_is_incomplete));
+            (backend->encdata_offset > 0 && !backend->encdata_is_incomplete) ||
+            backend->recv_connection_closed ||
+            backend->recv_sspi_close_notify ||
+            backend->recv_unrecoverable_err);
   else
     return FALSE;
 }
 
-static void schannel_session_free(void *ptr)
-{
-  /* this is expected to be called under sessionid lock */
-  struct Curl_schannel_cred *cred = ptr;
-
-  if(cred) {
-    cred->refcount--;
-    if(cred->refcount == 0) {
-      s_pSecFn->FreeCredentialsHandle(&cred->cred_handle);
-      curlx_unicodefree(cred->sni_hostname);
-#ifdef HAS_CLIENT_CERT_PATH
-      if(cred->client_cert_store) {
-        CertCloseStore(cred->client_cert_store, 0);
-        cred->client_cert_store = NULL;
-      }
-#endif
-      Curl_safefree(cred);
-    }
-  }
-}
-
 /* shut down the SSL connection and clean up related memory.
    this function can be called multiple times on the same connection including
    if the SSL connection failed (eg connection made but failed handshake). */
@@ -2539,7 +2490,7 @@ static int schannel_shutdown(struct Curl_cfilter *cf,
 
   if(backend->ctxt) {
     infof(data, "schannel: shutting down SSL/TLS connection with %s port %d",
-          connssl->hostname, connssl->port);
+          connssl->peer.hostname, connssl->peer.port);
   }
 
   if(backend->cred && backend->ctxt) {
@@ -2604,7 +2555,7 @@ static int schannel_shutdown(struct Curl_cfilter *cf,
   /* free SSPI Schannel API credential handle */
   if(backend->cred) {
     Curl_ssl_sessionid_lock(data);
-    schannel_session_free(backend->cred);
+    schannel_session_free(backend->cred, 0);
     Curl_ssl_sessionid_unlock(data);
     backend->cred = NULL;
   }
@@ -2752,8 +2703,7 @@ static void schannel_checksum(const unsigned char *input,
     if(!CryptCreateHash(hProv, algId, 0, 0, &hHash))
       break; /* failed */
 
-    /* workaround for original MinGW, should be (const BYTE*) */
-    if(!CryptHashData(hHash, (BYTE*)input, (DWORD)inputlen, 0))
+    if(!CryptHashData(hHash, input, (DWORD)inputlen, 0))
       break; /* failed */
 
     /* get hash size */
@@ -2796,6 +2746,151 @@ static void *schannel_get_internals(struct ssl_connect_data *connssl,
   return &backend->ctxt->ctxt_handle;
 }
 
+HCERTSTORE Curl_schannel_get_cached_cert_store(struct Curl_cfilter *cf,
+                                               const struct Curl_easy *data)
+{
+  struct ssl_primary_config *conn_config = Curl_ssl_cf_get_primary_config(cf);
+  struct Curl_multi *multi = data->multi;
+  const struct curl_blob *ca_info_blob = conn_config->ca_info_blob;
+  struct schannel_multi_ssl_backend_data *mbackend;
+  const struct ssl_general_config *cfg = &data->set.general_ssl;
+  timediff_t timeout_ms;
+  timediff_t elapsed_ms;
+  struct curltime now;
+  unsigned char info_blob_digest[CURL_SHA256_DIGEST_LENGTH];
+
+  DEBUGASSERT(multi);
+
+  if(!multi || !multi->ssl_backend_data) {
+    return NULL;
+  }
+
+  mbackend = (struct schannel_multi_ssl_backend_data *)multi->ssl_backend_data;
+  if(!mbackend->cert_store) {
+    return NULL;
+  }
+
+  /* zero ca_cache_timeout completely disables caching */
+  if(!cfg->ca_cache_timeout) {
+    return NULL;
+  }
+
+  /* check for cache timeout by using the cached_x509_store_expired timediff
+     calculation pattern from openssl.c.
+     negative timeout means retain forever. */
+  timeout_ms = cfg->ca_cache_timeout * (timediff_t)1000;
+  if(timeout_ms >= 0) {
+    now = Curl_now();
+    elapsed_ms = Curl_timediff(now, mbackend->time);
+    if(elapsed_ms >= timeout_ms) {
+      return NULL;
+    }
+  }
+
+  if(ca_info_blob) {
+    if(!mbackend->CAinfo_blob_digest) {
+      return NULL;
+    }
+    if(mbackend->CAinfo_blob_size != ca_info_blob->len) {
+      return NULL;
+    }
+    schannel_sha256sum((const unsigned char *)ca_info_blob->data,
+                       ca_info_blob->len,
+                       info_blob_digest,
+                       CURL_SHA256_DIGEST_LENGTH);
+    if(memcmp(mbackend->CAinfo_blob_digest,
+              info_blob_digest,
+              CURL_SHA256_DIGEST_LENGTH)) {
+        return NULL;
+    }
+  }
+  else {
+    if(!conn_config->CAfile || !mbackend->CAfile ||
+       strcmp(mbackend->CAfile, conn_config->CAfile)) {
+      return NULL;
+    }
+  }
+
+  return mbackend->cert_store;
+}
+
+bool Curl_schannel_set_cached_cert_store(struct Curl_cfilter *cf,
+                                         const struct Curl_easy *data,
+                                         HCERTSTORE cert_store)
+{
+  struct ssl_primary_config *conn_config = Curl_ssl_cf_get_primary_config(cf);
+  struct Curl_multi *multi = data->multi;
+  const struct curl_blob *ca_info_blob = conn_config->ca_info_blob;
+  struct schannel_multi_ssl_backend_data *mbackend;
+  unsigned char *CAinfo_blob_digest = NULL;
+  size_t CAinfo_blob_size = 0;
+  char *CAfile = NULL;
+
+  DEBUGASSERT(multi);
+
+  if(!multi) {
+    return false;
+  }
+
+  if(!multi->ssl_backend_data) {
+    multi->ssl_backend_data =
+      calloc(1, sizeof(struct schannel_multi_ssl_backend_data));
+    if(!multi->ssl_backend_data) {
+      return false;
+    }
+  }
+
+  mbackend = (struct schannel_multi_ssl_backend_data *)multi->ssl_backend_data;
+
+
+  if(ca_info_blob) {
+    CAinfo_blob_digest = malloc(CURL_SHA256_DIGEST_LENGTH);
+    if(!CAinfo_blob_digest) {
+      return false;
+    }
+    schannel_sha256sum((const unsigned char *)ca_info_blob->data,
+                       ca_info_blob->len,
+                       CAinfo_blob_digest,
+                       CURL_SHA256_DIGEST_LENGTH);
+    CAinfo_blob_size = ca_info_blob->len;
+  }
+  else {
+    if(conn_config->CAfile) {
+      CAfile = strdup(conn_config->CAfile);
+      if(!CAfile) {
+        return false;
+      }
+    }
+  }
+
+  /* free old cache data */
+  if(mbackend->cert_store) {
+    CertCloseStore(mbackend->cert_store, 0);
+  }
+  free(mbackend->CAinfo_blob_digest);
+  free(mbackend->CAfile);
+
+  mbackend->time = Curl_now();
+  mbackend->cert_store = cert_store;
+  mbackend->CAinfo_blob_digest = CAinfo_blob_digest;
+  mbackend->CAinfo_blob_size = CAinfo_blob_size;
+  mbackend->CAfile = CAfile;
+  return true;
+}
+
+static void schannel_free_multi_ssl_backend_data(
+  struct multi_ssl_backend_data *msbd)
+{
+  struct schannel_multi_ssl_backend_data *mbackend =
+    (struct schannel_multi_ssl_backend_data*)msbd;
+  if(mbackend->cert_store) {
+    CertCloseStore(mbackend->cert_store, 0);
+  }
+  free(mbackend->CAinfo_blob_digest);
+  free(mbackend->CAfile);
+  free(mbackend);
+}
+
 const struct Curl_ssl Curl_ssl_schannel = {
   { CURLSSLBACKEND_SCHANNEL, "schannel" }, /* info */
 
@@ -2819,11 +2914,10 @@ const struct Curl_ssl Curl_ssl_schannel = {
   Curl_none_cert_status_request,     /* cert_status_request */
   schannel_connect,                  /* connect */
   schannel_connect_nonblocking,      /* connect_nonblocking */
-  Curl_ssl_get_select_socks,         /* getsock */
+  Curl_ssl_adjust_pollset,           /* adjust_pollset */
   schannel_get_internals,            /* get_internals */
   schannel_close,                    /* close_one */
   Curl_none_close_all,               /* close_all */
-  schannel_session_free,             /* session_free */
   Curl_none_set_engine,              /* set_engine */
   Curl_none_set_engine_default,      /* set_engine_default */
   Curl_none_engines_list,            /* engines_list */
@@ -2831,7 +2925,7 @@ const struct Curl_ssl Curl_ssl_schannel = {
   schannel_sha256sum,                /* sha256sum */
   NULL,                              /* associate_connection */
   NULL,                              /* disassociate_connection */
-  NULL,                              /* free_multi_ssl_backend_data */
+  schannel_free_multi_ssl_backend_data, /* free_multi_ssl_backend_data */
   schannel_recv,                     /* recv decrypted data */
   schannel_send,                     /* send data to encrypt */
 };
diff --git a/vendor/curl/lib/vtls/schannel.h b/vendor/curl/lib/vtls/schannel.h
index be23567302..b26334bcf8 100644
--- a/vendor/curl/lib/vtls/schannel.h
+++ b/vendor/curl/lib/vtls/schannel.h
@@ -68,7 +68,7 @@
  * BoringSSL's : So just undefine those defines here
  * (and only here).
  */
-#if defined(HAVE_BORINGSSL) || defined(OPENSSL_IS_BORINGSSL)
+#if defined(OPENSSL_IS_BORINGSSL)
 # undef X509_NAME
 # undef X509_CERT_PAIR
 # undef X509_EXTENSIONS
diff --git a/vendor/curl/lib/vtls/schannel_int.h b/vendor/curl/lib/vtls/schannel_int.h
index edb20bcd23..5e233a9d05 100644
--- a/vendor/curl/lib/vtls/schannel_int.h
+++ b/vendor/curl/lib/vtls/schannel_int.h
@@ -28,15 +28,9 @@
 
 #ifdef USE_SCHANNEL
 
-#ifdef __MINGW32__
-#ifdef __MINGW64_VERSION_MAJOR
+#if defined(__MINGW32__) || defined(CERT_CHAIN_REVOCATION_CHECK_CHAIN)
 #define HAS_MANUAL_VERIFY_API
 #endif
-#else
-#ifdef CERT_CHAIN_REVOCATION_CHECK_CHAIN
-#define HAS_MANUAL_VERIFY_API
-#endif
-#endif
 
 #if defined(CryptStringToBinary) && defined(CRYPT_STRING_HEX)   \
   && !defined(DISABLE_SCHANNEL_CLIENT_CERT)
@@ -59,40 +53,15 @@
 #define CERT_ALT_NAME_IP_ADDRESS 8
 #endif
 
-
-#if defined(__MINGW32__) && !defined(__MINGW64_VERSION_MAJOR)
-/* Original mingw is missing CERT structs or they're disabled.
-   Refer to w32api-5.0.2-mingw32-dev\include\wincrypt.h. */
-
-/* !checksrc! disable TYPEDEFSTRUCT 4 */
-typedef struct _CERT_OTHER_NAME {
-  LPSTR pszObjId;
-  CRYPT_OBJID_BLOB Value;
-} CERT_OTHER_NAME, *PCERT_OTHER_NAME;
-
-typedef struct _CERT_ALT_NAME_ENTRY {
-  DWORD dwAltNameChoice;
-  union {
-    PCERT_OTHER_NAME pOtherName;
-    LPWSTR pwszRfc822Name;
-    LPWSTR pwszDNSName;
-    CERT_NAME_BLOB DirectoryName;
-    LPWSTR pwszURL;
-    CRYPT_DATA_BLOB IPAddress;
-    LPSTR pszRegisteredID;
-  };
-} CERT_ALT_NAME_ENTRY, *PCERT_ALT_NAME_ENTRY;
-
-typedef struct _CERT_ALT_NAME_INFO {
-  DWORD cAltEntry;
-  PCERT_ALT_NAME_ENTRY rgAltEntry;
-} CERT_ALT_NAME_INFO, *PCERT_ALT_NAME_INFO;
-
-typedef struct _CRYPT_DECODE_PARA {
-  DWORD cbSize;
-  PFN_CRYPT_ALLOC pfnAlloc;
-  PFN_CRYPT_FREE pfnFree;
-} CRYPT_DECODE_PARA, *PCRYPT_DECODE_PARA;
+#if defined(_MSC_VER) && (_MSC_VER <= 1600)
+/* Workaround for warning:
+   'type cast' : conversion from 'int' to 'LPCSTR' of greater size */
+#undef CERT_STORE_PROV_MEMORY
+#undef CERT_STORE_PROV_SYSTEM_A
+#undef CERT_STORE_PROV_SYSTEM_W
+#define CERT_STORE_PROV_MEMORY    ((LPCSTR)(size_t)2)
+#define CERT_STORE_PROV_SYSTEM_A  ((LPCSTR)(size_t)9)
+#define CERT_STORE_PROV_SYSTEM_W  ((LPCSTR)(size_t)10)
 #endif
 
 #ifndef SCH_CREDENTIALS_VERSION
@@ -190,5 +159,22 @@ struct schannel_ssl_backend_data {
 #endif
 };
 
+struct schannel_multi_ssl_backend_data {
+  unsigned char *CAinfo_blob_digest; /* CA info blob digest */
+  size_t CAinfo_blob_size;           /* CA info blob size */
+  char *CAfile;                      /* CAfile path used to generate
+                                        certificate store */
+  HCERTSTORE cert_store;             /* cached certificate store or
+                                        NULL if none */
+  struct curltime time;              /* when the cached store was created */
+};
+
+HCERTSTORE Curl_schannel_get_cached_cert_store(struct Curl_cfilter *cf,
+                                               const struct Curl_easy *data);
+
+bool Curl_schannel_set_cached_cert_store(struct Curl_cfilter *cf,
+                                         const struct Curl_easy *data,
+                                         HCERTSTORE cert_store);
+
 #endif /* USE_SCHANNEL */
 #endif /* HEADER_CURL_SCHANNEL_INT_H */
diff --git a/vendor/curl/lib/vtls/schannel_verify.c b/vendor/curl/lib/vtls/schannel_verify.c
index a5d5c98bb7..24146d0bd6 100644
--- a/vendor/curl/lib/vtls/schannel_verify.c
+++ b/vendor/curl/lib/vtls/schannel_verify.c
@@ -172,7 +172,7 @@ static CURLcode add_certs_data_to_store(HCERTSTORE trust_store,
           /* Sanity check that the cert_context object is the right type */
           if(CERT_QUERY_CONTENT_CERT != actual_content_type) {
             failf(data,
-                  "schannel: unexpected content type '%d' when extracting "
+                  "schannel: unexpected content type '%lu' when extracting "
                   "certificate from CA file '%s'",
                   actual_content_type, ca_file_text);
             result = CURLE_SSL_CACERT_BADFILE;
@@ -470,7 +470,7 @@ CURLcode Curl_verify_host(struct Curl_cfilter *cf,
   CERT_CONTEXT *pCertContextServer = NULL;
   TCHAR *cert_hostname_buff = NULL;
   size_t cert_hostname_buff_index = 0;
-  const char *conn_hostname = connssl->hostname;
+  const char *conn_hostname = connssl->peer.hostname;
   size_t hostlen = strlen(conn_hostname);
   DWORD len = 0;
   DWORD actual_len = 0;
@@ -600,6 +600,7 @@ CURLcode Curl_verify_certificate(struct Curl_cfilter *cf,
   const CERT_CHAIN_CONTEXT *pChainContext = NULL;
   HCERTCHAINENGINE cert_chain_engine = NULL;
   HCERTSTORE trust_store = NULL;
+  HCERTSTORE own_trust_store = NULL;
 
   DEBUGASSERT(BACKEND);
 
@@ -630,31 +631,46 @@ CURLcode Curl_verify_certificate(struct Curl_cfilter *cf,
       result = CURLE_SSL_CACERT_BADFILE;
     }
     else {
-      /* Open the certificate store */
-      trust_store = CertOpenStore(CERT_STORE_PROV_MEMORY,
-                                  0,
-                                  (HCRYPTPROV)NULL,
-                                  CERT_STORE_CREATE_NEW_FLAG,
-                                  NULL);
-      if(!trust_store) {
-        char buffer[STRERROR_LEN];
-        failf(data, "schannel: failed to create certificate store: %s",
-              Curl_winapi_strerror(GetLastError(), buffer, sizeof(buffer)));
-        result = CURLE_SSL_CACERT_BADFILE;
+      /* try cache */
+      trust_store = Curl_schannel_get_cached_cert_store(cf, data);
+
+      if(trust_store) {
+        infof(data, "schannel: reusing certificate store from cache");
       }
       else {
-        const struct curl_blob *ca_info_blob = conn_config->ca_info_blob;
-        if(ca_info_blob) {
-          result = add_certs_data_to_store(trust_store,
-                                           (const char *)ca_info_blob->data,
-                                           ca_info_blob->len,
-                                           "(memory blob)",
-                                           data);
+        /* Open the certificate store */
+        trust_store = CertOpenStore(CERT_STORE_PROV_MEMORY,
+                                    0,
+                                    (HCRYPTPROV)NULL,
+                                    CERT_STORE_CREATE_NEW_FLAG,
+                                    NULL);
+        if(!trust_store) {
+          char buffer[STRERROR_LEN];
+          failf(data, "schannel: failed to create certificate store: %s",
+                Curl_winapi_strerror(GetLastError(), buffer, sizeof(buffer)));
+          result = CURLE_SSL_CACERT_BADFILE;
         }
         else {
-          result = add_certs_file_to_store(trust_store,
-                                           conn_config->CAfile,
-                                           data);
+          const struct curl_blob *ca_info_blob = conn_config->ca_info_blob;
+          own_trust_store = trust_store;
+
+          if(ca_info_blob) {
+            result = add_certs_data_to_store(trust_store,
+                                              (const char *)ca_info_blob->data,
+                                              ca_info_blob->len,
+                                              "(memory blob)",
+                                              data);
+          }
+          else {
+            result = add_certs_file_to_store(trust_store,
+                                              conn_config->CAfile,
+                                              data);
+          }
+          if(result == CURLE_OK) {
+            if(Curl_schannel_set_cached_cert_store(cf, data, trust_store)) {
+              own_trust_store = NULL;
+            }
+          }
         }
       }
     }
@@ -737,7 +753,7 @@ CURLcode Curl_verify_certificate(struct Curl_cfilter *cf,
           failf(data, "schannel: CertGetCertificateChain trust error"
                 " CERT_TRUST_REVOCATION_STATUS_UNKNOWN");
         else
-          failf(data, "schannel: CertGetCertificateChain error mask: 0x%08x",
+          failf(data, "schannel: CertGetCertificateChain error mask: 0x%08lx",
                 dwTrustErrorMask);
         result = CURLE_PEER_FAILED_VERIFICATION;
       }
@@ -754,8 +770,8 @@ CURLcode Curl_verify_certificate(struct Curl_cfilter *cf,
     CertFreeCertificateChainEngine(cert_chain_engine);
   }
 
-  if(trust_store) {
-    CertCloseStore(trust_store, 0);
+  if(own_trust_store) {
+    CertCloseStore(own_trust_store, 0);
   }
 
   if(pChainContext)
diff --git a/vendor/curl/lib/vtls/sectransp.c b/vendor/curl/lib/vtls/sectransp.c
index e6a114ad5f..f49db6481c 100644
--- a/vendor/curl/lib/vtls/sectransp.c
+++ b/vendor/curl/lib/vtls/sectransp.c
@@ -46,8 +46,10 @@
 #endif /* __clang__ */
 
 #ifdef __GNUC__
+#pragma GCC diagnostic push
 #pragma GCC diagnostic ignored "-Waddress"
 #pragma GCC diagnostic ignored "-Wundef"
+#pragma GCC diagnostic ignored "-Wunreachable-code"
 #endif
 
 #include 
@@ -830,9 +832,9 @@ static const unsigned char ecDsaSecp384r1SpkiHeader[] = {
 #endif /* SECTRANSP_PINNEDPUBKEY_V1 */
 #endif /* SECTRANSP_PINNEDPUBKEY */
 
-static OSStatus bio_cf_in_read(SSLConnectionRef connection,
-                               void *buf,
-                               size_t *dataLength)  /* IN/OUT */
+static OSStatus sectransp_bio_cf_in_read(SSLConnectionRef connection,
+                                         void *buf,
+                                         size_t *dataLength)  /* IN/OUT */
 {
   struct Curl_cfilter *cf = (struct Curl_cfilter *)connection;
   struct ssl_connect_data *connssl = cf->ctx;
@@ -870,9 +872,9 @@ static OSStatus bio_cf_in_read(SSLConnectionRef connection,
   return rtn;
 }
 
-static OSStatus bio_cf_out_write(SSLConnectionRef connection,
-                                 const void *buf,
-                                 size_t *dataLength)  /* IN/OUT */
+static OSStatus sectransp_bio_cf_out_write(SSLConnectionRef connection,
+                                           const void *buf,
+                                           size_t *dataLength)  /* IN/OUT */
 {
   struct Curl_cfilter *cf = (struct Curl_cfilter *)connection;
   struct ssl_connect_data *connssl = cf->ctx;
@@ -904,7 +906,6 @@ static OSStatus bio_cf_out_write(SSLConnectionRef connection,
   return rtn;
 }
 
-#ifndef CURL_DISABLE_VERBOSE_STRINGS
 CF_INLINE const char *TLSCipherNameForNumber(SSLCipherSuite cipher)
 {
   /* The first ciphers in the ciphertable are continuous. Here we do small
@@ -923,7 +924,6 @@ CF_INLINE const char *TLSCipherNameForNumber(SSLCipherSuite cipher)
   }
   return ciphertable[SSL_NULL_WITH_NULL_NULL].name;
 }
-#endif /* !CURL_DISABLE_VERBOSE_STRINGS */
 
 #if CURL_BUILD_MAC
 CF_INLINE void GetDarwinVersionNumber(int *major, int *minor)
@@ -1013,7 +1013,7 @@ static CURLcode CopyCertSubject(struct Curl_easy *data,
   }
   else {
     size_t cbuf_size = ((size_t)CFStringGetLength(c) * 4) + 1;
-    cbuf = calloc(cbuf_size, 1);
+    cbuf = calloc(1, cbuf_size);
     if(cbuf) {
       if(!CFStringGetCString(c, cbuf, cbuf_size,
                              kCFStringEncodingUTF8)) {
@@ -1453,7 +1453,7 @@ static bool is_cipher_suite_strong(SSLCipherSuite suite_num)
   return true;
 }
 
-static bool is_separator(char c)
+static bool sectransp_is_separator(char c)
 {
   /* Return whether character is a cipher list separator. */
   switch(c) {
@@ -1547,7 +1547,7 @@ static CURLcode sectransp_set_selected_ciphers(struct Curl_easy *data,
   if(!ciphers)
     return CURLE_OK;
 
-  while(is_separator(*ciphers))     /* Skip initial separators. */
+  while(sectransp_is_separator(*ciphers))  /* Skip initial separators. */
     ciphers++;
   if(!*ciphers)
     return CURLE_OK;
@@ -1561,14 +1561,14 @@ static CURLcode sectransp_set_selected_ciphers(struct Curl_easy *data,
     size_t i;
 
     /* Skip separators */
-    while(is_separator(*cipher_start))
+    while(sectransp_is_separator(*cipher_start))
       cipher_start++;
     if(*cipher_start == '\0') {
       break;
     }
     /* Find last position of a cipher in the ciphers string */
     cipher_end = cipher_start;
-    while(*cipher_end != '\0' && !is_separator(*cipher_end)) {
+    while(*cipher_end != '\0' && !sectransp_is_separator(*cipher_end)) {
       ++cipher_end;
     }
 
@@ -1636,6 +1636,18 @@ static CURLcode sectransp_set_selected_ciphers(struct Curl_easy *data,
   return CURLE_OK;
 }
 
+static void sectransp_session_free(void *sessionid, size_t idsize)
+{
+  /* ST, as of iOS 5 and Mountain Lion, has no public method of deleting a
+     cached session ID inside the Security framework. There is a private
+     function that does this, but I don't want to have to explain to you why I
+     got your application rejected from the App Store due to the use of a
+     private API, so the best we can do is free up our own char array that we
+     created way back in sectransp_connect_step1... */
+  (void)idsize;
+  Curl_safefree(sessionid);
+}
+
 static CURLcode sectransp_connect_step1(struct Curl_cfilter *cf,
                                         struct Curl_easy *data)
 {
@@ -1651,11 +1663,6 @@ static CURLcode sectransp_connect_step1(struct Curl_cfilter *cf,
   const bool verifypeer = conn_config->verifypeer;
   char * const ssl_cert = ssl_config->primary.clientcert;
   const struct curl_blob *ssl_cert_blob = ssl_config->primary.cert_blob;
-#ifdef ENABLE_IPV6
-  struct in6_addr addr;
-#else
-  struct in_addr addr;
-#endif /* ENABLE_IPV6 */
   char *ciphers;
   OSStatus err = noErr;
 #if CURL_BUILD_MAC
@@ -2003,13 +2010,9 @@ static CURLcode sectransp_connect_step1(struct Curl_cfilter *cf,
    * Both hostname check and SNI require SSLSetPeerDomainName().
    * Also: the verifyhost setting influences SNI usage */
   if(conn_config->verifyhost) {
-    size_t snilen;
-    char *snihost = Curl_ssl_snihost(data, connssl->hostname, &snilen);
-    if(!snihost) {
-      failf(data, "Failed to set SNI");
-      return CURLE_SSL_CONNECT_ERROR;
-    }
-    err = SSLSetPeerDomainName(backend->ssl_ctx, snihost, snilen);
+    char *server = connssl->peer.sni?
+                   connssl->peer.sni : connssl->peer.hostname;
+    err = SSLSetPeerDomainName(backend->ssl_ctx, server, strlen(server));
 
     if(err != noErr) {
       failf(data, "SSL: SSLSetPeerDomainName() failed: OSStatus %d",
@@ -2017,11 +2020,7 @@ static CURLcode sectransp_connect_step1(struct Curl_cfilter *cf,
       return CURLE_SSL_CONNECT_ERROR;
     }
 
-    if((Curl_inet_pton(AF_INET, connssl->hostname, &addr))
-  #ifdef ENABLE_IPV6
-    || (Curl_inet_pton(AF_INET6, connssl->hostname, &addr))
-  #endif
-       ) {
+    if(connssl->peer.type != CURL_SSL_PEER_DNS) {
       infof(data, "WARNING: using IP address, SNI is being disabled by "
             "the OS.");
     }
@@ -2060,8 +2059,8 @@ static CURLcode sectransp_connect_step1(struct Curl_cfilter *cf,
     size_t ssl_sessionid_len;
 
     Curl_ssl_sessionid_lock(data);
-    if(!Curl_ssl_getsessionid(cf, data, (void **)&ssl_sessionid,
-                              &ssl_sessionid_len)) {
+    if(!Curl_ssl_getsessionid(cf, data, &connssl->peer,
+                              (void **)&ssl_sessionid, &ssl_sessionid_len)) {
       /* we got a session id, use it! */
       err = SSLSetPeerID(backend->ssl_ctx, ssl_sessionid, ssl_sessionid_len);
       Curl_ssl_sessionid_unlock(data);
@@ -2079,8 +2078,8 @@ static CURLcode sectransp_connect_step1(struct Curl_cfilter *cf,
       ssl_sessionid =
         aprintf("%s:%d:%d:%s:%d",
                 ssl_cafile ? ssl_cafile : "(blob memory)",
-                verifypeer, conn_config->verifyhost, connssl->hostname,
-                connssl->port);
+                verifypeer, conn_config->verifyhost, connssl->peer.hostname,
+                connssl->peer.port);
       ssl_sessionid_len = strlen(ssl_sessionid);
 
       err = SSLSetPeerID(backend->ssl_ctx, ssl_sessionid, ssl_sessionid_len);
@@ -2090,17 +2089,18 @@ static CURLcode sectransp_connect_step1(struct Curl_cfilter *cf,
         return CURLE_SSL_CONNECT_ERROR;
       }
 
-      result = Curl_ssl_addsessionid(cf, data, ssl_sessionid,
-                                     ssl_sessionid_len, NULL);
+      result = Curl_ssl_addsessionid(cf, data, &connssl->peer, ssl_sessionid,
+                                     ssl_sessionid_len,
+                                     sectransp_session_free);
       Curl_ssl_sessionid_unlock(data);
-      if(result) {
-        failf(data, "failed to store ssl session");
+      if(result)
         return result;
-      }
     }
   }
 
-  err = SSLSetIOFuncs(backend->ssl_ctx, bio_cf_in_read, bio_cf_out_write);
+  err = SSLSetIOFuncs(backend->ssl_ctx,
+                      sectransp_bio_cf_in_read,
+                      sectransp_bio_cf_out_write);
   if(err != noErr) {
     failf(data, "SSL: SSLSetIOFuncs() failed: OSStatus %d", err);
     return CURLE_SSL_CONNECT_ERROR;
@@ -2378,19 +2378,15 @@ static CURLcode verify_cert(struct Curl_cfilter *cf,
                             const struct curl_blob *ca_info_blob,
                             SSLContextRef ctx)
 {
-  int result;
+  CURLcode result;
   unsigned char *certbuf;
   size_t buflen;
+  bool free_certbuf = FALSE;
 
   if(ca_info_blob) {
     CURL_TRC_CF(data, cf, "verify_peer, CA from config blob");
-    certbuf = (unsigned char *)malloc(ca_info_blob->len + 1);
-    if(!certbuf) {
-      return CURLE_OUT_OF_MEMORY;
-    }
+    certbuf = ca_info_blob->data;
     buflen = ca_info_blob->len;
-    memcpy(certbuf, ca_info_blob->data, ca_info_blob->len);
-    certbuf[ca_info_blob->len]='\0';
   }
   else if(cafile) {
     CURL_TRC_CF(data, cf, "verify_peer, CA from file '%s'", cafile);
@@ -2398,12 +2394,14 @@ static CURLcode verify_cert(struct Curl_cfilter *cf,
       failf(data, "SSL: failed to read or invalid CA certificate");
       return CURLE_SSL_CACERT_BADFILE;
     }
+    free_certbuf = TRUE;
   }
   else
     return CURLE_SSL_CACERT_BADFILE;
 
   result = verify_cert_buf(cf, data, certbuf, buflen, ctx);
-  free(certbuf);
+  if(free_certbuf)
+    free(certbuf);
   return result;
 }
 
@@ -2663,7 +2661,7 @@ static CURLcode sectransp_connect_step2(struct Curl_cfilter *cf,
          host name: */
       case errSSLHostNameMismatch:
         failf(data, "SSL certificate peer verification failed, the "
-              "certificate did not match \"%s\"\n", connssl->dispname);
+              "certificate did not match \"%s\"\n", connssl->peer.dispname);
         return CURLE_PEER_FAILED_VERIFICATION;
 
       /* Problem with SSL / TLS negotiation */
@@ -2755,7 +2753,7 @@ static CURLcode sectransp_connect_step2(struct Curl_cfilter *cf,
       default:
         /* May also return codes listed in Security Framework Result Codes */
         failf(data, "Unknown SSL protocol error in connection to %s:%d",
-              connssl->hostname, err);
+              connssl->peer.hostname, err);
         break;
     }
     return CURLE_SSL_CONNECT_ERROR;
@@ -3238,17 +3236,6 @@ static int sectransp_shutdown(struct Curl_cfilter *cf,
   return rc;
 }
 
-static void sectransp_session_free(void *ptr)
-{
-  /* ST, as of iOS 5 and Mountain Lion, has no public method of deleting a
-     cached session ID inside the Security framework. There is a private
-     function that does this, but I don't want to have to explain to you why I
-     got your application rejected from the App Store due to the use of a
-     private API, so the best we can do is free up our own char array that we
-     created way back in sectransp_connect_step1... */
-  Curl_safefree(ptr);
-}
-
 static size_t sectransp_version(char *buffer, size_t size)
 {
   return msnprintf(buffer, size, "SecureTransport");
@@ -3413,7 +3400,6 @@ static ssize_t sectransp_recv(struct Curl_cfilter *cf,
         }
         *curlcode = CURLE_AGAIN;
         return -1L;
-        break;
 
       /* errSSLClosedGraceful - server gracefully shut down the SSL session
          errSSLClosedNoNotify - server hung up on us instead of sending a
@@ -3423,7 +3409,6 @@ static ssize_t sectransp_recv(struct Curl_cfilter *cf,
       case errSSLClosedNoNotify:
         *curlcode = CURLE_OK;
         return 0;
-        break;
 
         /* The below is errSSLPeerAuthCompleted; it's not defined in
            Leopard's headers */
@@ -3443,7 +3428,6 @@ static ssize_t sectransp_recv(struct Curl_cfilter *cf,
         failf(data, "SSLRead() return error %d", err);
         *curlcode = CURLE_RECV_ERROR;
         return -1L;
-        break;
     }
   }
   return (ssize_t)processed;
@@ -3481,11 +3465,10 @@ const struct Curl_ssl Curl_ssl_sectransp = {
   Curl_none_cert_status_request,      /* cert_status_request */
   sectransp_connect,                  /* connect */
   sectransp_connect_nonblocking,      /* connect_nonblocking */
-  Curl_ssl_get_select_socks,          /* getsock */
+  Curl_ssl_adjust_pollset,            /* adjust_pollset */
   sectransp_get_internals,            /* get_internals */
   sectransp_close,                    /* close_one */
   Curl_none_close_all,                /* close_all */
-  sectransp_session_free,             /* session_free */
   Curl_none_set_engine,               /* set_engine */
   Curl_none_set_engine_default,       /* set_engine_default */
   Curl_none_engines_list,             /* engines_list */
@@ -3498,6 +3481,10 @@ const struct Curl_ssl Curl_ssl_sectransp = {
   sectransp_send,                     /* send data to encrypt */
 };
 
+#ifdef __GNUC__
+#pragma GCC diagnostic pop
+#endif
+
 #ifdef __clang__
 #pragma clang diagnostic pop
 #endif
diff --git a/vendor/curl/lib/vtls/vtls.c b/vendor/curl/lib/vtls/vtls.c
index 38a20e8bea..570a10d5ac 100644
--- a/vendor/curl/lib/vtls/vtls.c
+++ b/vendor/curl/lib/vtls/vtls.c
@@ -67,6 +67,7 @@
 #include "warnless.h"
 #include "curl_base64.h"
 #include "curl_printf.h"
+#include "inet_pton.h"
 #include "strdup.h"
 
 /* The last #include files should be: */
@@ -131,9 +132,6 @@ static bool blobcmp(struct curl_blob *first, struct curl_blob *second)
 }
 
 #ifdef USE_SSL
-static const struct alpn_spec ALPN_SPEC_H10 = {
-  { ALPN_HTTP_1_0 }, 1
-};
 static const struct alpn_spec ALPN_SPEC_H11 = {
   { ALPN_HTTP_1_1 }, 1
 };
@@ -147,51 +145,83 @@ static const struct alpn_spec *alpn_get_spec(int httpwant, bool use_alpn)
 {
   if(!use_alpn)
     return NULL;
-  if(httpwant == CURL_HTTP_VERSION_1_0)
-    return &ALPN_SPEC_H10;
 #ifdef USE_HTTP2
   if(httpwant >= CURL_HTTP_VERSION_2)
     return &ALPN_SPEC_H2_H11;
+#else
+  (void)httpwant;
 #endif
+  /* Use the ALPN protocol "http/1.1" for HTTP/1.x.
+     Avoid "http/1.0" because some servers don't support it. */
   return &ALPN_SPEC_H11;
 }
 #endif /* USE_SSL */
 
 
-bool
-Curl_ssl_config_matches(struct ssl_primary_config *data,
-                        struct ssl_primary_config *needle)
-{
-  if((data->version == needle->version) &&
-     (data->version_max == needle->version_max) &&
-     (data->ssl_options == needle->ssl_options) &&
-     (data->verifypeer == needle->verifypeer) &&
-     (data->verifyhost == needle->verifyhost) &&
-     (data->verifystatus == needle->verifystatus) &&
-     blobcmp(data->cert_blob, needle->cert_blob) &&
-     blobcmp(data->ca_info_blob, needle->ca_info_blob) &&
-     blobcmp(data->issuercert_blob, needle->issuercert_blob) &&
-     Curl_safecmp(data->CApath, needle->CApath) &&
-     Curl_safecmp(data->CAfile, needle->CAfile) &&
-     Curl_safecmp(data->issuercert, needle->issuercert) &&
-     Curl_safecmp(data->clientcert, needle->clientcert) &&
+void Curl_ssl_easy_config_init(struct Curl_easy *data)
+{
+  /*
+   * libcurl 7.10 introduced SSL verification *by default*! This needs to be
+   * switched off unless wanted.
+   */
+  data->set.ssl.primary.verifypeer = TRUE;
+  data->set.ssl.primary.verifyhost = TRUE;
+  data->set.ssl.primary.sessionid = TRUE; /* session ID caching by default */
+#ifndef CURL_DISABLE_PROXY
+  data->set.proxy_ssl = data->set.ssl;
+#endif
+}
+
+static bool
+match_ssl_primary_config(struct Curl_easy *data,
+                         struct ssl_primary_config *c1,
+                         struct ssl_primary_config *c2)
+{
+  (void)data;
+  if((c1->version == c2->version) &&
+     (c1->version_max == c2->version_max) &&
+     (c1->ssl_options == c2->ssl_options) &&
+     (c1->verifypeer == c2->verifypeer) &&
+     (c1->verifyhost == c2->verifyhost) &&
+     (c1->verifystatus == c2->verifystatus) &&
+     blobcmp(c1->cert_blob, c2->cert_blob) &&
+     blobcmp(c1->ca_info_blob, c2->ca_info_blob) &&
+     blobcmp(c1->issuercert_blob, c2->issuercert_blob) &&
+     Curl_safecmp(c1->CApath, c2->CApath) &&
+     Curl_safecmp(c1->CAfile, c2->CAfile) &&
+     Curl_safecmp(c1->issuercert, c2->issuercert) &&
+     Curl_safecmp(c1->clientcert, c2->clientcert) &&
 #ifdef USE_TLS_SRP
-     !Curl_timestrcmp(data->username, needle->username) &&
-     !Curl_timestrcmp(data->password, needle->password) &&
+     !Curl_timestrcmp(c1->username, c2->username) &&
+     !Curl_timestrcmp(c1->password, c2->password) &&
 #endif
-     strcasecompare(data->cipher_list, needle->cipher_list) &&
-     strcasecompare(data->cipher_list13, needle->cipher_list13) &&
-     strcasecompare(data->curves, needle->curves) &&
-     strcasecompare(data->CRLfile, needle->CRLfile) &&
-     strcasecompare(data->pinned_key, needle->pinned_key))
+     strcasecompare(c1->cipher_list, c2->cipher_list) &&
+     strcasecompare(c1->cipher_list13, c2->cipher_list13) &&
+     strcasecompare(c1->curves, c2->curves) &&
+     strcasecompare(c1->CRLfile, c2->CRLfile) &&
+     strcasecompare(c1->pinned_key, c2->pinned_key))
     return TRUE;
 
   return FALSE;
 }
 
-bool
-Curl_clone_primary_ssl_config(struct ssl_primary_config *source,
-                              struct ssl_primary_config *dest)
+bool Curl_ssl_conn_config_match(struct Curl_easy *data,
+                                struct connectdata *candidate,
+                                bool proxy)
+{
+#ifndef CURL_DISABLE_PROXY
+  if(proxy)
+    return match_ssl_primary_config(data, &data->set.proxy_ssl.primary,
+                                    &candidate->proxy_ssl_config);
+#else
+  (void)proxy;
+#endif
+  return match_ssl_primary_config(data, &data->set.ssl.primary,
+                                  &candidate->ssl_config);
+}
+
+static bool clone_ssl_primary_config(struct ssl_primary_config *source,
+                                     struct ssl_primary_config *dest)
 {
   dest->version = source->version;
   dest->version_max = source->version_max;
@@ -221,7 +251,7 @@ Curl_clone_primary_ssl_config(struct ssl_primary_config *source,
   return TRUE;
 }
 
-void Curl_free_primary_ssl_config(struct ssl_primary_config *sslc)
+static void Curl_free_primary_ssl_config(struct ssl_primary_config *sslc)
 {
   Curl_safefree(sslc->CApath);
   Curl_safefree(sslc->CAfile);
@@ -241,6 +271,111 @@ void Curl_free_primary_ssl_config(struct ssl_primary_config *sslc)
 #endif
 }
 
+CURLcode Curl_ssl_easy_config_complete(struct Curl_easy *data)
+{
+  data->set.ssl.primary.CApath = data->set.str[STRING_SSL_CAPATH];
+  data->set.ssl.primary.CAfile = data->set.str[STRING_SSL_CAFILE];
+  data->set.ssl.primary.CRLfile = data->set.str[STRING_SSL_CRLFILE];
+  data->set.ssl.primary.issuercert = data->set.str[STRING_SSL_ISSUERCERT];
+  data->set.ssl.primary.issuercert_blob = data->set.blobs[BLOB_SSL_ISSUERCERT];
+  data->set.ssl.primary.cipher_list =
+    data->set.str[STRING_SSL_CIPHER_LIST];
+  data->set.ssl.primary.cipher_list13 =
+    data->set.str[STRING_SSL_CIPHER13_LIST];
+  data->set.ssl.primary.pinned_key =
+    data->set.str[STRING_SSL_PINNEDPUBLICKEY];
+  data->set.ssl.primary.cert_blob = data->set.blobs[BLOB_CERT];
+  data->set.ssl.primary.ca_info_blob = data->set.blobs[BLOB_CAINFO];
+  data->set.ssl.primary.curves = data->set.str[STRING_SSL_EC_CURVES];
+#ifdef USE_TLS_SRP
+  data->set.ssl.primary.username = data->set.str[STRING_TLSAUTH_USERNAME];
+  data->set.ssl.primary.password = data->set.str[STRING_TLSAUTH_PASSWORD];
+#endif
+  data->set.ssl.cert_type = data->set.str[STRING_CERT_TYPE];
+  data->set.ssl.key = data->set.str[STRING_KEY];
+  data->set.ssl.key_type = data->set.str[STRING_KEY_TYPE];
+  data->set.ssl.key_passwd = data->set.str[STRING_KEY_PASSWD];
+  data->set.ssl.primary.clientcert = data->set.str[STRING_CERT];
+  data->set.ssl.key_blob = data->set.blobs[BLOB_KEY];
+
+#ifndef CURL_DISABLE_PROXY
+  data->set.proxy_ssl.primary.CApath = data->set.str[STRING_SSL_CAPATH_PROXY];
+  data->set.proxy_ssl.primary.CAfile = data->set.str[STRING_SSL_CAFILE_PROXY];
+  data->set.proxy_ssl.primary.cipher_list =
+    data->set.str[STRING_SSL_CIPHER_LIST_PROXY];
+  data->set.proxy_ssl.primary.cipher_list13 =
+    data->set.str[STRING_SSL_CIPHER13_LIST_PROXY];
+  data->set.proxy_ssl.primary.pinned_key =
+    data->set.str[STRING_SSL_PINNEDPUBLICKEY_PROXY];
+  data->set.proxy_ssl.primary.cert_blob = data->set.blobs[BLOB_CERT_PROXY];
+  data->set.proxy_ssl.primary.ca_info_blob =
+    data->set.blobs[BLOB_CAINFO_PROXY];
+  data->set.proxy_ssl.primary.issuercert =
+    data->set.str[STRING_SSL_ISSUERCERT_PROXY];
+  data->set.proxy_ssl.primary.issuercert_blob =
+    data->set.blobs[BLOB_SSL_ISSUERCERT_PROXY];
+  data->set.proxy_ssl.primary.CRLfile =
+    data->set.str[STRING_SSL_CRLFILE_PROXY];
+  data->set.proxy_ssl.cert_type = data->set.str[STRING_CERT_TYPE_PROXY];
+  data->set.proxy_ssl.key = data->set.str[STRING_KEY_PROXY];
+  data->set.proxy_ssl.key_type = data->set.str[STRING_KEY_TYPE_PROXY];
+  data->set.proxy_ssl.key_passwd = data->set.str[STRING_KEY_PASSWD_PROXY];
+  data->set.proxy_ssl.primary.clientcert = data->set.str[STRING_CERT_PROXY];
+  data->set.proxy_ssl.key_blob = data->set.blobs[BLOB_KEY_PROXY];
+#ifdef USE_TLS_SRP
+  data->set.proxy_ssl.primary.username =
+    data->set.str[STRING_TLSAUTH_USERNAME_PROXY];
+  data->set.proxy_ssl.primary.password =
+    data->set.str[STRING_TLSAUTH_PASSWORD_PROXY];
+#endif
+#endif /* CURL_DISABLE_PROXY */
+
+  return CURLE_OK;
+}
+
+CURLcode Curl_ssl_conn_config_init(struct Curl_easy *data,
+                                   struct connectdata *conn)
+{
+  /* Clone "primary" SSL configurations from the esay handle to
+   * the connection. They are used for connection cache matching and
+   * probably outlive the easy handle */
+  if(!clone_ssl_primary_config(&data->set.ssl.primary, &conn->ssl_config))
+    return CURLE_OUT_OF_MEMORY;
+#ifndef CURL_DISABLE_PROXY
+  if(!clone_ssl_primary_config(&data->set.proxy_ssl.primary,
+                               &conn->proxy_ssl_config))
+    return CURLE_OUT_OF_MEMORY;
+#endif
+  return CURLE_OK;
+}
+
+void Curl_ssl_conn_config_cleanup(struct connectdata *conn)
+{
+  Curl_free_primary_ssl_config(&conn->ssl_config);
+#ifndef CURL_DISABLE_PROXY
+  Curl_free_primary_ssl_config(&conn->proxy_ssl_config);
+#endif
+}
+
+void Curl_ssl_conn_config_update(struct Curl_easy *data, bool for_proxy)
+{
+  /* May be called on an easy that has no connection yet */
+  if(data->conn) {
+    struct ssl_primary_config *src, *dest;
+#ifndef CURL_DISABLE_PROXY
+    src = for_proxy? &data->set.proxy_ssl.primary : &data->set.ssl.primary;
+    dest = for_proxy? &data->conn->proxy_ssl_config : &data->conn->ssl_config;
+#else
+    (void)for_proxy;
+    src = &data->set.ssl.primary;
+    dest = &data->conn->ssl_config;
+#endif
+    dest->verifyhost = src->verifyhost;
+    dest->verifypeer = src->verifypeer;
+    dest->verifystatus = src->verifystatus;
+  }
+}
+
 #ifdef USE_SSL
 static int multissl_setup(const struct Curl_ssl *backend);
 #endif
@@ -399,10 +534,10 @@ void Curl_ssl_sessionid_unlock(struct Curl_easy *data)
  */
 bool Curl_ssl_getsessionid(struct Curl_cfilter *cf,
                            struct Curl_easy *data,
+                           const struct ssl_peer *peer,
                            void **ssl_sessionid,
                            size_t *idsize) /* set 0 if unknown */
 {
-  struct ssl_connect_data *connssl = cf->ctx;
   struct ssl_primary_config *conn_config = Curl_ssl_cf_get_primary_config(cf);
   struct ssl_config_data *ssl_config = Curl_ssl_cf_get_config(cf, data);
   struct Curl_ssl_session *check;
@@ -432,16 +567,17 @@ bool Curl_ssl_getsessionid(struct Curl_cfilter *cf,
     if(!check->sessionid)
       /* not session ID means blank entry */
       continue;
-    if(strcasecompare(connssl->hostname, check->name) &&
+    if(strcasecompare(peer->hostname, check->name) &&
        ((!cf->conn->bits.conn_to_host && !check->conn_to_host) ||
         (cf->conn->bits.conn_to_host && check->conn_to_host &&
          strcasecompare(cf->conn->conn_to_host.name, check->conn_to_host))) &&
        ((!cf->conn->bits.conn_to_port && check->conn_to_port == -1) ||
         (cf->conn->bits.conn_to_port && check->conn_to_port != -1 &&
          cf->conn->conn_to_port == check->conn_to_port)) &&
-       (connssl->port == check->remote_port) &&
+       (peer->port == check->remote_port) &&
+       (peer->transport == check->transport) &&
        strcasecompare(cf->conn->handler->scheme, check->scheme) &&
-       Curl_ssl_config_matches(conn_config, &check->ssl_config)) {
+       match_ssl_primary_config(data, conn_config, &check->ssl_config)) {
       /* yes, we have a session ID! */
       (*general_age)++;          /* increase general age */
       check->age = *general_age; /* set this as used in this age */
@@ -456,7 +592,7 @@ bool Curl_ssl_getsessionid(struct Curl_cfilter *cf,
   DEBUGF(infof(data, "%s Session ID in cache for %s %s://%s:%d",
                no_match? "Didn't find": "Found",
                Curl_ssl_cf_is_proxy(cf) ? "proxy" : "host",
-               cf->conn->handler->scheme, connssl->hostname, connssl->port));
+               cf->conn->handler->scheme, peer->hostname, peer->port));
   return no_match;
 }
 
@@ -469,9 +605,10 @@ void Curl_ssl_kill_session(struct Curl_ssl_session *session)
     /* defensive check */
 
     /* free the ID the SSL-layer specific way */
-    Curl_ssl->session_free(session->sessionid);
+    session->sessionid_free(session->sessionid, session->idsize);
 
     session->sessionid = NULL;
+    session->sessionid_free = NULL;
     session->age = 0; /* fresh */
 
     Curl_free_primary_ssl_config(&session->ssl_config);
@@ -506,45 +643,44 @@ void Curl_ssl_delsessionid(struct Curl_easy *data, void *ssl_sessionid)
  */
 CURLcode Curl_ssl_addsessionid(struct Curl_cfilter *cf,
                                struct Curl_easy *data,
+                               const struct ssl_peer *peer,
                                void *ssl_sessionid,
                                size_t idsize,
-                               bool *added)
+                               Curl_ssl_sessionid_dtor *sessionid_free_cb)
 {
-  struct ssl_connect_data *connssl = cf->ctx;
   struct ssl_config_data *ssl_config = Curl_ssl_cf_get_config(cf, data);
   struct ssl_primary_config *conn_config = Curl_ssl_cf_get_primary_config(cf);
   size_t i;
   struct Curl_ssl_session *store;
   long oldest_age;
-  char *clone_host;
-  char *clone_conn_to_host;
+  char *clone_host = NULL;
+  char *clone_conn_to_host = NULL;
   int conn_to_port;
   long *general_age;
+  CURLcode result = CURLE_OUT_OF_MEMORY;
 
-  if(added)
-    *added = FALSE;
+  DEBUGASSERT(ssl_sessionid);
+  DEBUGASSERT(sessionid_free_cb);
 
-  if(!data->state.session)
+  if(!data->state.session) {
+    sessionid_free_cb(ssl_sessionid, idsize);
     return CURLE_OK;
+  }
 
   store = &data->state.session[0];
   oldest_age = data->state.session[0].age; /* zero if unused */
-  (void)ssl_config;
   DEBUGASSERT(ssl_config->primary.sessionid);
+  (void)ssl_config;
 
-  clone_host = strdup(connssl->hostname);
+  clone_host = strdup(peer->hostname);
   if(!clone_host)
-    return CURLE_OUT_OF_MEMORY; /* bail out */
+    goto out;
 
   if(cf->conn->bits.conn_to_host) {
     clone_conn_to_host = strdup(cf->conn->conn_to_host.name);
-    if(!clone_conn_to_host) {
-      free(clone_host);
-      return CURLE_OUT_OF_MEMORY; /* bail out */
-    }
+    if(!clone_conn_to_host)
+      goto out;
   }
-  else
-    clone_conn_to_host = NULL;
 
   if(cf->conn->bits.conn_to_port)
     conn_to_port = cf->conn->conn_to_port;
@@ -577,33 +713,43 @@ CURLcode Curl_ssl_addsessionid(struct Curl_cfilter *cf,
     store = &data->state.session[i]; /* use this slot */
 
   /* now init the session struct wisely */
+  if(!clone_ssl_primary_config(conn_config, &store->ssl_config)) {
+    Curl_free_primary_ssl_config(&store->ssl_config);
+    store->sessionid = NULL; /* let caller free sessionid */
+    goto out;
+  }
   store->sessionid = ssl_sessionid;
   store->idsize = idsize;
+  store->sessionid_free = sessionid_free_cb;
   store->age = *general_age;    /* set current age */
   /* free it if there's one already present */
   free(store->name);
   free(store->conn_to_host);
   store->name = clone_host;               /* clone host name */
+  clone_host = NULL;
   store->conn_to_host = clone_conn_to_host; /* clone connect to host name */
+  clone_conn_to_host = NULL;
   store->conn_to_port = conn_to_port; /* connect to port number */
   /* port number */
-  store->remote_port = connssl->port;
+  store->remote_port = peer->port;
   store->scheme = cf->conn->handler->scheme;
+  store->transport = peer->transport;
 
-  if(!Curl_clone_primary_ssl_config(conn_config, &store->ssl_config)) {
-    Curl_free_primary_ssl_config(&store->ssl_config);
-    store->sessionid = NULL; /* let caller free sessionid */
-    free(clone_host);
-    free(clone_conn_to_host);
-    return CURLE_OUT_OF_MEMORY;
-  }
-
-  if(added)
-    *added = TRUE;
+  result = CURLE_OK;
 
-  DEBUGF(infof(data, "Added Session ID to cache for %s://%s:%d [%s]",
-               store->scheme, store->name, store->remote_port,
-               Curl_ssl_cf_is_proxy(cf) ? "PROXY" : "server"));
+out:
+  free(clone_host);
+  free(clone_conn_to_host);
+  if(result) {
+    failf(data, "Failed to add Session ID to cache for %s://%s:%d [%s]",
+          store->scheme, store->name, store->remote_port,
+          Curl_ssl_cf_is_proxy(cf) ? "PROXY" : "server");
+    sessionid_free_cb(ssl_sessionid, idsize);
+    return result;
+  }
+  CURL_TRC_CF(data, cf, "Added Session ID to cache for %s://%s:%d [%s]",
+              store->scheme, store->name, store->remote_port,
+              Curl_ssl_cf_is_proxy(cf) ? "PROXY" : "server");
   return CURLE_OK;
 }
 
@@ -629,22 +775,25 @@ void Curl_ssl_close_all(struct Curl_easy *data)
   Curl_ssl->close_all(data);
 }
 
-int Curl_ssl_get_select_socks(struct Curl_cfilter *cf, struct Curl_easy *data,
-                              curl_socket_t *socks)
+void Curl_ssl_adjust_pollset(struct Curl_cfilter *cf, struct Curl_easy *data,
+                              struct easy_pollset *ps)
 {
-  struct ssl_connect_data *connssl = cf->ctx;
-  curl_socket_t sock = Curl_conn_cf_get_socket(cf->next, data);
-
-  if(sock == CURL_SOCKET_BAD)
-    return GETSOCK_BLANK;
-
-  if(connssl->connecting_state == ssl_connect_2_writing) {
-    /* we are only interested in writing */
-    socks[0] = sock;
-    return GETSOCK_WRITESOCK(0);
+  if(!cf->connected) {
+    struct ssl_connect_data *connssl = cf->ctx;
+    curl_socket_t sock = Curl_conn_cf_get_socket(cf->next, data);
+    if(sock != CURL_SOCKET_BAD) {
+      if(connssl->connecting_state == ssl_connect_2_writing) {
+        Curl_pollset_set_out_only(data, ps, sock);
+        CURL_TRC_CF(data, cf, "adjust_pollset, POLLOUT fd=%"
+                    CURL_FORMAT_SOCKET_T, sock);
+      }
+      else {
+        Curl_pollset_set_in_only(data, ps, sock);
+        CURL_TRC_CF(data, cf, "adjust_pollset, POLLIN fd=%"
+                    CURL_FORMAT_SOCKET_T, sock);
+      }
+    }
   }
-  socks[0] = sock;
-  return GETSOCK_READSOCK(0);
 }
 
 /* Selects an SSL crypto engine
@@ -748,28 +897,21 @@ CURLcode Curl_ssl_push_certinfo_len(struct Curl_easy *data,
                                     size_t valuelen)
 {
   struct curl_certinfo *ci = &data->info.certs;
-  char *output;
   struct curl_slist *nl;
   CURLcode result = CURLE_OK;
-  size_t labellen = strlen(label);
-  size_t outlen = labellen + 1 + valuelen + 1; /* label:value\0 */
-
-  output = malloc(outlen);
-  if(!output)
-    return CURLE_OUT_OF_MEMORY;
+  struct dynbuf build;
 
-  /* sprintf the label and colon */
-  msnprintf(output, outlen, "%s:", label);
+  Curl_dyn_init(&build, 10000);
 
-  /* memcpy the value (it might not be null-terminated) */
-  memcpy(&output[labellen + 1], value, valuelen);
-
-  /* null-terminate the output */
-  output[labellen + 1 + valuelen] = 0;
+  if(Curl_dyn_add(&build, label) ||
+     Curl_dyn_addn(&build, ":", 1) ||
+     Curl_dyn_addn(&build, value, valuelen))
+    return CURLE_OUT_OF_MEMORY;
 
-  nl = Curl_slist_append_nodup(ci->certinfo[certnum], output);
+  nl = Curl_slist_append_nodup(ci->certinfo[certnum],
+                               Curl_dyn_ptr(&build));
   if(!nl) {
-    free(output);
+    Curl_dyn_free(&build);
     curl_slist_free_all(ci->certinfo[certnum]);
     result = CURLE_OUT_OF_MEMORY;
   }
@@ -785,32 +927,6 @@ CURLcode Curl_ssl_random(struct Curl_easy *data,
   return Curl_ssl->random(data, entropy, length);
 }
 
-/*
- * Curl_ssl_snihost() converts the input host name to a suitable SNI name put
- * in data->state.buffer. Returns a pointer to the name (or NULL if a problem)
- * and stores the new length in 'olen'.
- *
- * SNI fields must not have any trailing dot and while RFC 6066 section 3 says
- * the SNI field is case insensitive, browsers always send the data lowercase
- * and subsequently there are numerous servers out there that don't work
- * unless the name is lowercased.
- */
-
-char *Curl_ssl_snihost(struct Curl_easy *data, const char *host, size_t *olen)
-{
-  size_t len = strlen(host);
-  if(len && (host[len-1] == '.'))
-    len--;
-  if(len >= data->set.buffer_size)
-    return NULL;
-
-  Curl_strntolower(data->state.buffer, host, len);
-  data->state.buffer[len] = 0;
-  if(olen)
-    *olen = len;
-  return data->state.buffer;
-}
-
 /*
  * Public key pem to der conversion
  */
@@ -893,7 +1009,7 @@ CURLcode Curl_pin_peer_pubkey(struct Curl_easy *data,
   /* only do this if pinnedpubkey starts with "sha256//", length 8 */
   if(strncmp(pinnedpubkey, "sha256//", 8) == 0) {
     CURLcode encode;
-    size_t encodedlen = 0, pinkeylen;
+    size_t encodedlen = 0;
     char *encoded = NULL, *pinkeycopy, *begin_pos, *end_pos;
     unsigned char *sha256sumdigest;
 
@@ -921,13 +1037,11 @@ CURLcode Curl_pin_peer_pubkey(struct Curl_easy *data,
     infof(data, " public key hash: sha256//%s", encoded);
 
     /* it starts with sha256//, copy so we can modify it */
-    pinkeylen = strlen(pinnedpubkey) + 1;
-    pinkeycopy = malloc(pinkeylen);
+    pinkeycopy = strdup(pinnedpubkey);
     if(!pinkeycopy) {
       Curl_safefree(encoded);
       return CURLE_OUT_OF_MEMORY;
     }
-    memcpy(pinkeycopy, pinnedpubkey, pinkeylen);
     /* point begin_pos to the copy, and start extracting keys */
     begin_pos = pinkeycopy;
     do {
@@ -1156,13 +1270,13 @@ static CURLcode multissl_connect_nonblocking(struct Curl_cfilter *cf,
   return Curl_ssl->connect_nonblocking(cf, data, done);
 }
 
-static int multissl_get_select_socks(struct Curl_cfilter *cf,
+static void multissl_adjust_pollset(struct Curl_cfilter *cf,
                                      struct Curl_easy *data,
-                                     curl_socket_t *socks)
+                                     struct easy_pollset *ps)
 {
   if(multissl_setup(NULL))
-    return 0;
-  return Curl_ssl->get_select_socks(cf, data, socks);
+    return;
+  Curl_ssl->adjust_pollset(cf, data, ps);
 }
 
 static void *multissl_get_internals(struct ssl_connect_data *connssl,
@@ -1214,11 +1328,10 @@ static const struct Curl_ssl Curl_ssl_multi = {
   Curl_none_cert_status_request,     /* cert_status_request */
   multissl_connect,                  /* connect */
   multissl_connect_nonblocking,      /* connect_nonblocking */
-  multissl_get_select_socks,         /* getsock */
+  multissl_adjust_pollset,          /* adjust_pollset */
   multissl_get_internals,            /* get_internals */
   multissl_close,                    /* close_one */
   Curl_none_close_all,               /* close_all */
-  Curl_none_session_free,            /* session_free */
   Curl_none_set_engine,              /* set_engine */
   Curl_none_set_engine_default,      /* set_engine_default */
   Curl_none_engines_list,            /* engines_list */
@@ -1313,17 +1426,13 @@ static size_t multissl_version(char *buffer, size_t size)
     backends_len = p - backends;
   }
 
-  if(!size)
-    return 0;
-
-  if(size <= backends_len) {
-    strncpy(buffer, backends, size - 1);
-    buffer[size - 1] = '\0';
-    return size - 1;
+  if(size) {
+    if(backends_len < size)
+      strcpy(buffer, backends);
+    else
+      *buffer = 0; /* did not fit */
   }
-
-  strcpy(buffer, backends);
-  return backends_len;
+  return 0;
 }
 
 static int multissl_setup(const struct Curl_ssl *backend)
@@ -1409,12 +1518,14 @@ CURLsslset Curl_init_sslset_nolock(curl_sslbackend id, const char *name,
 
 #ifdef USE_SSL
 
-static void free_hostname(struct ssl_connect_data *connssl)
+void Curl_ssl_peer_cleanup(struct ssl_peer *peer)
 {
-  if(connssl->dispname != connssl->hostname)
-    free(connssl->dispname);
-  free(connssl->hostname);
-  connssl->hostname = connssl->dispname = NULL;
+  if(peer->dispname != peer->hostname)
+    free(peer->dispname);
+  free(peer->sni);
+  free(peer->hostname);
+  peer->hostname = peer->sni = peer->dispname = NULL;
+  peer->type = CURL_SSL_PEER_DNS;
 }
 
 static void cf_close(struct Curl_cfilter *cf, struct Curl_easy *data)
@@ -1423,14 +1534,33 @@ static void cf_close(struct Curl_cfilter *cf, struct Curl_easy *data)
   if(connssl) {
     Curl_ssl->close(cf, data);
     connssl->state = ssl_connection_none;
-    free_hostname(connssl);
+    Curl_ssl_peer_cleanup(&connssl->peer);
   }
   cf->connected = FALSE;
 }
 
-static CURLcode reinit_hostname(struct Curl_cfilter *cf)
+static ssl_peer_type get_peer_type(const char *hostname)
+{
+  if(hostname && hostname[0]) {
+#ifdef USE_IPV6
+    struct in6_addr addr;
+#else
+    struct in_addr addr;
+#endif
+    if(Curl_inet_pton(AF_INET, hostname, &addr))
+      return CURL_SSL_PEER_IPV4;
+#ifdef USE_IPV6
+    else if(Curl_inet_pton(AF_INET6, hostname, &addr)) {
+      return CURL_SSL_PEER_IPV6;
+    }
+#endif
+  }
+  return CURL_SSL_PEER_DNS;
+}
+
+CURLcode Curl_ssl_peer_init(struct ssl_peer *peer, struct Curl_cfilter *cf,
+                            int transport)
 {
-  struct ssl_connect_data *connssl = cf->ctx;
   const char *ehostname, *edispname;
   int eport;
 
@@ -1454,25 +1584,46 @@ static CURLcode reinit_hostname(struct Curl_cfilter *cf)
   }
 
   /* change if ehostname changed */
-  if(ehostname && (!connssl->hostname
-                   || strcmp(ehostname, connssl->hostname))) {
-    free_hostname(connssl);
-    connssl->hostname = strdup(ehostname);
-    if(!connssl->hostname) {
-      free_hostname(connssl);
+  DEBUGASSERT(!ehostname || ehostname[0]);
+  if(ehostname && (!peer->hostname
+                   || strcmp(ehostname, peer->hostname))) {
+    Curl_ssl_peer_cleanup(peer);
+    peer->hostname = strdup(ehostname);
+    if(!peer->hostname) {
+      Curl_ssl_peer_cleanup(peer);
       return CURLE_OUT_OF_MEMORY;
     }
     if(!edispname || !strcmp(ehostname, edispname))
-      connssl->dispname = connssl->hostname;
+      peer->dispname = peer->hostname;
     else {
-      connssl->dispname = strdup(edispname);
-      if(!connssl->dispname) {
-        free_hostname(connssl);
+      peer->dispname = strdup(edispname);
+      if(!peer->dispname) {
+        Curl_ssl_peer_cleanup(peer);
         return CURLE_OUT_OF_MEMORY;
       }
     }
+
+    peer->type = get_peer_type(peer->hostname);
+    if(peer->type == CURL_SSL_PEER_DNS && peer->hostname[0]) {
+      /* not an IP address, normalize according to RCC 6066 ch. 3,
+       * max len of SNI is 2^16-1, no trailing dot */
+      size_t len = strlen(peer->hostname);
+      if(len && (peer->hostname[len-1] == '.'))
+        len--;
+      if(len < USHRT_MAX) {
+        peer->sni = calloc(1, len + 1);
+        if(!peer->sni) {
+          Curl_ssl_peer_cleanup(peer);
+          return CURLE_OUT_OF_MEMORY;
+        }
+        Curl_strntolower(peer->sni, peer->hostname, len);
+        peer->sni[len] = 0;
+      }
+    }
+
   }
-  connssl->port = eport;
+  peer->port = eport;
+  peer->transport = transport;
   return CURLE_OK;
 }
 
@@ -1494,7 +1645,8 @@ static void ssl_cf_close(struct Curl_cfilter *cf,
 
   CF_DATA_SAVE(save, cf, data);
   cf_close(cf, data);
-  cf->next->cft->do_close(cf->next, data);
+  if(cf->next)
+    cf->next->cft->do_close(cf->next, data);
   CF_DATA_RESTORE(cf, save);
 }
 
@@ -1524,7 +1676,7 @@ static CURLcode ssl_cf_connect(struct Curl_cfilter *cf,
     goto out;
 
   *done = FALSE;
-  result = reinit_hostname(cf);
+  result = Curl_ssl_peer_init(&connssl->peer, cf, TRNSPRT_TCP);
   if(result)
     goto out;
 
@@ -1593,27 +1745,23 @@ static ssize_t ssl_cf_recv(struct Curl_cfilter *cf,
     /* eof */
     *err = CURLE_OK;
   }
-  CURL_TRC_CF(data, cf, "cf_recv(len=%zu) -> %zd, %d", len, nread, *err);
+  CURL_TRC_CF(data, cf, "cf_recv(len=%zu) -> %zd, %d", len,
+              nread, *err);
   CF_DATA_RESTORE(cf, save);
   return nread;
 }
 
-static int ssl_cf_get_select_socks(struct Curl_cfilter *cf,
+static void ssl_cf_adjust_pollset(struct Curl_cfilter *cf,
                                    struct Curl_easy *data,
-                                   curl_socket_t *socks)
+                                   struct easy_pollset *ps)
 {
   struct cf_call_data save;
-  int fds = GETSOCK_BLANK;
 
-  if(!cf->next->connected) {
-    fds = cf->next->cft->get_select_socks(cf->next, data, socks);
-  }
-  else if(!cf->connected) {
+  if(!cf->connected) {
     CF_DATA_SAVE(save, cf, data);
-    fds = Curl_ssl->get_select_socks(cf, data, socks);
+    Curl_ssl->adjust_pollset(cf, data, ps);
     CF_DATA_RESTORE(cf, save);
   }
-  return fds;
 }
 
 static CURLcode ssl_cf_cntrl(struct Curl_cfilter *cf,
@@ -1704,7 +1852,7 @@ struct Curl_cftype Curl_cft_ssl = {
   ssl_cf_connect,
   ssl_cf_close,
   Curl_cf_def_get_host,
-  ssl_cf_get_select_socks,
+  ssl_cf_adjust_pollset,
   ssl_cf_data_pending,
   ssl_cf_send,
   ssl_cf_recv,
@@ -1714,15 +1862,17 @@ struct Curl_cftype Curl_cft_ssl = {
   ssl_cf_query,
 };
 
+#ifndef CURL_DISABLE_PROXY
+
 struct Curl_cftype Curl_cft_ssl_proxy = {
   "SSL-PROXY",
-  CF_TYPE_SSL,
+  CF_TYPE_SSL|CF_TYPE_PROXY,
   CURL_LOG_LVL_NONE,
   ssl_cf_destroy,
   ssl_cf_connect,
   ssl_cf_close,
   Curl_cf_def_get_host,
-  ssl_cf_get_select_socks,
+  ssl_cf_adjust_pollset,
   ssl_cf_data_pending,
   ssl_cf_send,
   ssl_cf_recv,
@@ -1732,6 +1882,8 @@ struct Curl_cftype Curl_cft_ssl_proxy = {
   Curl_cf_def_query,
 };
 
+#endif /* !CURL_DISABLE_PROXY */
+
 static CURLcode cf_ssl_create(struct Curl_cfilter **pcf,
                               struct Curl_easy *data,
                               struct connectdata *conn)
@@ -1836,6 +1988,20 @@ bool Curl_ssl_supports(struct Curl_easy *data, int option)
   return (Curl_ssl->supports & option)? TRUE : FALSE;
 }
 
+static struct Curl_cfilter *get_ssl_filter(struct Curl_cfilter *cf)
+{
+  for(; cf; cf = cf->next) {
+    if(cf->cft == &Curl_cft_ssl)
+      return cf;
+#ifndef CURL_DISABLE_PROXY
+    if(cf->cft == &Curl_cft_ssl_proxy)
+      return cf;
+#endif
+  }
+  return NULL;
+}
+
+
 void *Curl_ssl_get_internals(struct Curl_easy *data, int sockindex,
                              CURLINFO info, int n)
 {
@@ -1843,8 +2009,8 @@ void *Curl_ssl_get_internals(struct Curl_easy *data, int sockindex,
   (void)n;
   if(data->conn) {
     struct Curl_cfilter *cf;
-    /* get first filter in chain, if any is present */
-    cf = Curl_ssl_cf_get_ssl(data->conn->cfilter[sockindex]);
+    /* get first SSL filter in chain, if any is present */
+    cf = get_ssl_filter(data->conn->cfilter[sockindex]);
     if(cf) {
       struct cf_call_data save;
       CF_DATA_SAVE(save, cf, data);
@@ -1874,26 +2040,9 @@ CURLcode Curl_ssl_cfilter_remove(struct Curl_easy *data,
   return result;
 }
 
-static struct Curl_cfilter *get_ssl_cf_engaged(struct connectdata *conn,
-                                               int sockindex)
-{
-  struct Curl_cfilter *cf, *lowest_ssl_cf = NULL;
-
-  for(cf = conn->cfilter[sockindex]; cf; cf = cf->next) {
-    if(cf->cft == &Curl_cft_ssl || cf->cft == &Curl_cft_ssl_proxy) {
-      lowest_ssl_cf = cf;
-      if(cf->connected || (cf->next && cf->next->connected)) {
-        /* connected or about to start */
-        return cf;
-      }
-    }
-  }
-  return lowest_ssl_cf;
-}
-
 bool Curl_ssl_cf_is_proxy(struct Curl_cfilter *cf)
 {
-  return (cf->cft == &Curl_cft_ssl_proxy);
+  return (cf->cft->flags & CF_TYPE_SSL) && (cf->cft->flags & CF_TYPE_PROXY);
 }
 
 struct ssl_config_data *
@@ -1907,17 +2056,6 @@ Curl_ssl_cf_get_config(struct Curl_cfilter *cf, struct Curl_easy *data)
 #endif
 }
 
-struct ssl_config_data *
-Curl_ssl_get_config(struct Curl_easy *data, int sockindex)
-{
-  struct Curl_cfilter *cf;
-
-  (void)data;
-  DEBUGASSERT(data->conn);
-  cf = get_ssl_cf_engaged(data->conn, sockindex);
-  return cf? Curl_ssl_cf_get_config(cf, data) : &data->set.ssl;
-}
-
 struct ssl_primary_config *
 Curl_ssl_cf_get_primary_config(struct Curl_cfilter *cf)
 {
@@ -1929,15 +2067,6 @@ Curl_ssl_cf_get_primary_config(struct Curl_cfilter *cf)
 #endif
 }
 
-struct Curl_cfilter *Curl_ssl_cf_get_ssl(struct Curl_cfilter *cf)
-{
-  for(; cf; cf = cf->next) {
-    if(cf->cft == &Curl_cft_ssl || cf->cft == &Curl_cft_ssl_proxy)
-      return cf;
-  }
-  return NULL;
-}
-
 CURLcode Curl_alpn_to_proto_buf(struct alpn_proto_buf *buf,
                                 const struct alpn_spec *spec)
 {
@@ -2004,10 +2133,6 @@ CURLcode Curl_alpn_set_negotiated(struct Curl_cfilter *cf,
        !memcmp(ALPN_HTTP_1_1, proto, ALPN_HTTP_1_1_LENGTH)) {
       *palpn = CURL_HTTP_VERSION_1_1;
     }
-    else if(proto_len == ALPN_HTTP_1_0_LENGTH &&
-            !memcmp(ALPN_HTTP_1_0, proto, ALPN_HTTP_1_0_LENGTH)) {
-      *palpn = CURL_HTTP_VERSION_1_0;
-    }
 #ifdef USE_HTTP2
     else if(proto_len == ALPN_H2_LENGTH &&
             !memcmp(ALPN_H2, proto, ALPN_H2_LENGTH)) {
diff --git a/vendor/curl/lib/vtls/vtls.h b/vendor/curl/lib/vtls/vtls.h
index 8ad1cf6def..c40ff26208 100644
--- a/vendor/curl/lib/vtls/vtls.h
+++ b/vendor/curl/lib/vtls/vtls.h
@@ -37,6 +37,7 @@ struct Curl_ssl_session;
 #define SSLSUPP_HTTPS_PROXY  (1<<4) /* supports access via HTTPS proxies */
 #define SSLSUPP_TLS13_CIPHERSUITES (1<<5) /* supports TLS 1.3 ciphersuites */
 #define SSLSUPP_CAINFO_BLOB  (1<<6)
+#define SSLSUPP_ECH          (1<<7)
 
 #define ALPN_ACCEPTED "ALPN: server accepted "
 
@@ -65,15 +66,55 @@ CURLsslset Curl_init_sslset_nolock(curl_sslbackend id, const char *name,
 #define CURL_SHA256_DIGEST_LENGTH 32 /* fixed size */
 #endif
 
-char *Curl_ssl_snihost(struct Curl_easy *data, const char *host, size_t *olen);
-bool Curl_ssl_config_matches(struct ssl_primary_config *data,
-                             struct ssl_primary_config *needle);
-bool Curl_clone_primary_ssl_config(struct ssl_primary_config *source,
-                                   struct ssl_primary_config *dest);
-void Curl_free_primary_ssl_config(struct ssl_primary_config *sslc);
-
 curl_sslbackend Curl_ssl_backend(void);
 
+/**
+ * Init ssl config for a new easy handle.
+ */
+void Curl_ssl_easy_config_init(struct Curl_easy *data);
+
+/**
+ * Init the `data->set.ssl` and `data->set.proxy_ssl` for
+ * connection matching use.
+ */
+CURLcode Curl_ssl_easy_config_complete(struct Curl_easy *data);
+
+/**
+ * Init SSL configs (main + proxy) for a new connection from the easy handle.
+ */
+CURLcode Curl_ssl_conn_config_init(struct Curl_easy *data,
+                                   struct connectdata *conn);
+
+/**
+ * Free allocated resources in SSL configs (main + proxy) for
+ * the given connection.
+ */
+void Curl_ssl_conn_config_cleanup(struct connectdata *conn);
+
+/**
+ * Return TRUE iff SSL configuration from `conn` is functionally the
+ * same as the one on `candidate`.
+ * @param proxy   match the proxy SSL config or the main one
+ */
+bool Curl_ssl_conn_config_match(struct Curl_easy *data,
+                                struct connectdata *candidate,
+                                bool proxy);
+
+/* Update certain connection SSL config flags after they have
+ * been changed on the easy handle. Will work for `verifypeer`,
+ * `verifyhost` and `verifystatus`. */
+void Curl_ssl_conn_config_update(struct Curl_easy *data, bool for_proxy);
+
+/**
+ * Init SSL peer information for filter. Can be called repeatedly.
+ */
+CURLcode Curl_ssl_peer_init(struct ssl_peer *peer,
+                            struct Curl_cfilter *cf, int transport);
+/**
+ * Free all allocated data and reset peer information.
+ */
+void Curl_ssl_peer_cleanup(struct ssl_peer *peer);
+
 #ifdef USE_SSL
 int Curl_ssl_init(void);
 void Curl_ssl_cleanup(void);
@@ -159,18 +200,6 @@ CURLcode Curl_cf_ssl_proxy_insert_after(struct Curl_cfilter *cf_at,
                                         struct Curl_easy *data);
 #endif /* !CURL_DISABLE_PROXY */
 
-/**
- * Get the SSL configuration that is used on the connection.
- * This returns NULL if no SSL is configured.
- * Otherwise it returns the config of the first (highest) one that is
- * either connected, in handshake or about to start
- * (e.g. all filters below it are connected). If SSL filters are present,
- * but neither can start operating, return the config of the lowest one
- * that will first come into effect when connecting.
- */
-struct ssl_config_data *Curl_ssl_get_config(struct Curl_easy *data,
-                                            int sockindex);
-
 /**
  * True iff the underlying SSL implementation supports the option.
  * Option is one of the defined SSLSUPP_* values.
@@ -188,8 +217,22 @@ bool Curl_ssl_supports(struct Curl_easy *data, int ssl_option);
 void *Curl_ssl_get_internals(struct Curl_easy *data, int sockindex,
                              CURLINFO info, int n);
 
+/**
+ * Get the ssl_config_data in `data` that is relevant for cfilter `cf`.
+ */
+struct ssl_config_data *Curl_ssl_cf_get_config(struct Curl_cfilter *cf,
+                                               struct Curl_easy *data);
+
+/**
+ * Get the primary config relevant for the filter from its connection.
+ */
+struct ssl_primary_config *
+  Curl_ssl_cf_get_primary_config(struct Curl_cfilter *cf);
+
 extern struct Curl_cftype Curl_cft_ssl;
+#ifndef CURL_DISABLE_PROXY
 extern struct Curl_cftype Curl_cft_ssl_proxy;
+#endif
 
 #else /* if not USE_SSL */
 
@@ -209,8 +252,9 @@ extern struct Curl_cftype Curl_cft_ssl_proxy;
 #define Curl_ssl_get_internals(a,b,c,d) NULL
 #define Curl_ssl_supports(a,b) FALSE
 #define Curl_ssl_cfilter_add(a,b,c) CURLE_NOT_BUILT_IN
-#define Curl_ssl_get_config(a,b) NULL
 #define Curl_ssl_cfilter_remove(a,b) CURLE_OK
+#define Curl_ssl_cf_get_config(a,b) NULL
+#define Curl_ssl_cf_get_primary_config(a) NULL
 #endif
 
 #endif /* HEADER_CURL_VTLS_H */
diff --git a/vendor/curl/lib/vtls/vtls_int.h b/vendor/curl/lib/vtls/vtls_int.h
index a6e4544a87..5259babb25 100644
--- a/vendor/curl/lib/vtls/vtls_int.h
+++ b/vendor/curl/lib/vtls/vtls_int.h
@@ -32,8 +32,6 @@
 /* see https://www.iana.org/assignments/tls-extensiontype-values/ */
 #define ALPN_HTTP_1_1_LENGTH 8
 #define ALPN_HTTP_1_1 "http/1.1"
-#define ALPN_HTTP_1_0_LENGTH 8
-#define ALPN_HTTP_1_0 "http/1.0"
 #define ALPN_H2_LENGTH 2
 #define ALPN_H2 "h2"
 #define ALPN_H3_LENGTH 2
@@ -70,14 +68,13 @@ CURLcode Curl_alpn_set_negotiated(struct Curl_cfilter *cf,
 struct ssl_connect_data {
   ssl_connection_state state;
   ssl_connect_state connecting_state;
-  char *hostname;                   /* hostname for verification */
-  char *dispname;                   /* display version of hostname */
+  struct ssl_peer peer;
   const struct alpn_spec *alpn;     /* ALPN to use or NULL for none */
   void *backend;                    /* vtls backend specific props */
   struct cf_call_data call_data;    /* data handle used in current call */
   struct curltime handshake_done;   /* time when handshake finished */
-  int port;                         /* remote port at origin */
   BIT(use_alpn);                    /* if ALPN shall be used in handshake */
+  BIT(peer_closed);                 /* peer has closed connection */
 };
 
 
@@ -118,18 +115,14 @@ struct Curl_ssl {
                                   struct Curl_easy *data,
                                   bool *done);
 
-  /* If the SSL backend wants to read or write on this connection during a
-     handshake, set socks[0] to the connection's FIRSTSOCKET, and return
-     a bitmap indicating read or write with GETSOCK_WRITESOCK(0) or
-     GETSOCK_READSOCK(0). Otherwise return GETSOCK_BLANK.
-     Mandatory. */
-  int (*get_select_socks)(struct Curl_cfilter *cf, struct Curl_easy *data,
-                          curl_socket_t *socks);
-
+  /* During handshake, adjust the pollset to include the socket
+   * for POLLOUT or POLLIN as needed.
+   * Mandatory. */
+  void (*adjust_pollset)(struct Curl_cfilter *cf, struct Curl_easy *data,
+                          struct easy_pollset *ps);
   void *(*get_internals)(struct ssl_connect_data *connssl, CURLINFO info);
   void (*close)(struct Curl_cfilter *cf, struct Curl_easy *data);
   void (*close_all)(struct Curl_easy *data);
-  void (*session_free)(void *ptr);
 
   CURLcode (*set_engine)(struct Curl_easy *data, const char *engine);
   CURLcode (*set_engine_default)(struct Curl_easy *data);
@@ -169,25 +162,8 @@ CURLcode Curl_none_set_engine(struct Curl_easy *data, const char *engine);
 CURLcode Curl_none_set_engine_default(struct Curl_easy *data);
 struct curl_slist *Curl_none_engines_list(struct Curl_easy *data);
 bool Curl_none_false_start(void);
-int Curl_ssl_get_select_socks(struct Curl_cfilter *cf, struct Curl_easy *data,
-                              curl_socket_t *socks);
-
-/**
- * Get the ssl_config_data in `data` that is relevant for cfilter `cf`.
- */
-struct ssl_config_data *Curl_ssl_cf_get_config(struct Curl_cfilter *cf,
-                                               struct Curl_easy *data);
-
-/**
- * Get the primary config relevant for the filter from its connection.
- */
-struct ssl_primary_config *
-  Curl_ssl_cf_get_primary_config(struct Curl_cfilter *cf);
-
-/**
- * Get the first SSL filter in the chain starting with `cf`, or NULL.
- */
-struct Curl_cfilter *Curl_ssl_cf_get_ssl(struct Curl_cfilter *cf);
+void Curl_ssl_adjust_pollset(struct Curl_cfilter *cf, struct Curl_easy *data,
+                              struct easy_pollset *ps);
 
 /**
  * Get the SSL filter below the given one or NULL if there is none.
@@ -202,18 +178,22 @@ bool Curl_ssl_cf_is_proxy(struct Curl_cfilter *cf);
  */
 bool Curl_ssl_getsessionid(struct Curl_cfilter *cf,
                            struct Curl_easy *data,
+                           const struct ssl_peer *peer,
                            void **ssl_sessionid,
                            size_t *idsize); /* set 0 if unknown */
 /* add a new session ID
  * Sessionid mutex must be locked (see Curl_ssl_sessionid_lock).
  * Caller must ensure that it has properly shared ownership of this sessionid
  * object with cache (e.g. incrementing refcount on success)
+ * Call takes ownership of `ssl_sessionid`, using `sessionid_free_cb`
+ * to destroy it in case of failure or later removal.
  */
 CURLcode Curl_ssl_addsessionid(struct Curl_cfilter *cf,
                                struct Curl_easy *data,
+                               const struct ssl_peer *peer,
                                void *ssl_sessionid,
                                size_t idsize,
-                               bool *added);
+                               Curl_ssl_sessionid_dtor *sessionid_free_cb);
 
 #include "openssl.h"        /* OpenSSL versions */
 #include "gtls.h"           /* GnuTLS versions */
diff --git a/vendor/curl/lib/vtls/wolfssl.c b/vendor/curl/lib/vtls/wolfssl.c
index 5f15720742..2c92f56ea4 100644
--- a/vendor/curl/lib/vtls/wolfssl.c
+++ b/vendor/curl/lib/vtls/wolfssl.c
@@ -74,6 +74,14 @@
 #include "curl_memory.h"
 #include "memdebug.h"
 
+#ifdef USE_ECH
+# include "curl_base64.h"
+# define ECH_ENABLED(__data__) \
+    (__data__->set.tls_ech && \
+     !(__data__->set.tls_ech & CURLECH_DISABLE)\
+    )
+#endif /* USE_ECH */
+
 /* KEEP_PEER_CERT is a product of the presence of build time symbol
    OPENSSL_EXTRA without NO_CERTS, depending on the version. KEEP_PEER_CERT is
    in wolfSSL's settings.h, and the latter two are build time symbols in
@@ -229,22 +237,21 @@ static const struct group_name_map gnm[] = {
 
 #ifdef USE_BIO_CHAIN
 
-static int bio_cf_create(WOLFSSL_BIO *bio)
+static int wolfssl_bio_cf_create(WOLFSSL_BIO *bio)
 {
   wolfSSL_BIO_set_shutdown(bio, 1);
-  wolfSSL_BIO_set_init(bio, 1);
   wolfSSL_BIO_set_data(bio, NULL);
   return 1;
 }
 
-static int bio_cf_destroy(WOLFSSL_BIO *bio)
+static int wolfssl_bio_cf_destroy(WOLFSSL_BIO *bio)
 {
   if(!bio)
     return 0;
   return 1;
 }
 
-static long bio_cf_ctrl(WOLFSSL_BIO *bio, int cmd, long num, void *ptr)
+static long wolfssl_bio_cf_ctrl(WOLFSSL_BIO *bio, int cmd, long num, void *ptr)
 {
   struct Curl_cfilter *cf = BIO_get_data(bio);
   long ret = 1;
@@ -278,7 +285,8 @@ static long bio_cf_ctrl(WOLFSSL_BIO *bio, int cmd, long num, void *ptr)
   return ret;
 }
 
-static int bio_cf_out_write(WOLFSSL_BIO *bio, const char *buf, int blen)
+static int wolfssl_bio_cf_out_write(WOLFSSL_BIO *bio,
+                                    const char *buf, int blen)
 {
   struct Curl_cfilter *cf = wolfSSL_BIO_get_data(bio);
   struct ssl_connect_data *connssl = cf->ctx;
@@ -299,7 +307,7 @@ static int bio_cf_out_write(WOLFSSL_BIO *bio, const char *buf, int blen)
   return (int)nwritten;
 }
 
-static int bio_cf_in_read(WOLFSSL_BIO *bio, char *buf, int blen)
+static int wolfssl_bio_cf_in_read(WOLFSSL_BIO *bio, char *buf, int blen)
 {
   struct Curl_cfilter *cf = wolfSSL_BIO_get_data(bio);
   struct ssl_connect_data *connssl = cf->ctx;
@@ -320,30 +328,32 @@ static int bio_cf_in_read(WOLFSSL_BIO *bio, char *buf, int blen)
   wolfSSL_BIO_clear_retry_flags(bio);
   if(nread < 0 && CURLE_AGAIN == result)
     BIO_set_retry_read(bio);
+  else if(nread == 0)
+    connssl->peer_closed = TRUE;
   return (int)nread;
 }
 
-static WOLFSSL_BIO_METHOD *bio_cf_method = NULL;
+static WOLFSSL_BIO_METHOD *wolfssl_bio_cf_method = NULL;
 
-static void bio_cf_init_methods(void)
+static void wolfssl_bio_cf_init_methods(void)
 {
-  bio_cf_method = wolfSSL_BIO_meth_new(BIO_TYPE_MEM, "wolfSSL CF BIO");
-  wolfSSL_BIO_meth_set_write(bio_cf_method, &bio_cf_out_write);
-  wolfSSL_BIO_meth_set_read(bio_cf_method, &bio_cf_in_read);
-  wolfSSL_BIO_meth_set_ctrl(bio_cf_method, &bio_cf_ctrl);
-  wolfSSL_BIO_meth_set_create(bio_cf_method, &bio_cf_create);
-  wolfSSL_BIO_meth_set_destroy(bio_cf_method, &bio_cf_destroy);
+  wolfssl_bio_cf_method = wolfSSL_BIO_meth_new(BIO_TYPE_MEM, "wolfSSL CF BIO");
+  wolfSSL_BIO_meth_set_write(wolfssl_bio_cf_method, &wolfssl_bio_cf_out_write);
+  wolfSSL_BIO_meth_set_read(wolfssl_bio_cf_method, &wolfssl_bio_cf_in_read);
+  wolfSSL_BIO_meth_set_ctrl(wolfssl_bio_cf_method, &wolfssl_bio_cf_ctrl);
+  wolfSSL_BIO_meth_set_create(wolfssl_bio_cf_method, &wolfssl_bio_cf_create);
+  wolfSSL_BIO_meth_set_destroy(wolfssl_bio_cf_method, &wolfssl_bio_cf_destroy);
 }
 
-static void bio_cf_free_methods(void)
+static void wolfssl_bio_cf_free_methods(void)
 {
-  wolfSSL_BIO_meth_free(bio_cf_method);
+  wolfSSL_BIO_meth_free(wolfssl_bio_cf_method);
 }
 
 #else /* USE_BIO_CHAIN */
 
-#define bio_cf_init_methods() Curl_nop_stmt
-#define bio_cf_free_methods() Curl_nop_stmt
+#define wolfssl_bio_cf_init_methods() Curl_nop_stmt
+#define wolfssl_bio_cf_free_methods() Curl_nop_stmt
 
 #endif /* !USE_BIO_CHAIN */
 
@@ -361,6 +371,10 @@ wolfssl_connect_step1(struct Curl_cfilter *cf, struct Curl_easy *data)
   struct ssl_primary_config *conn_config = Curl_ssl_cf_get_primary_config(cf);
   const struct curl_blob *ca_info_blob = conn_config->ca_info_blob;
   const struct ssl_config_data *ssl_config = Curl_ssl_cf_get_config(cf, data);
+  const char * const ssl_cafile =
+    /* CURLOPT_CAINFO_BLOB overrides CURLOPT_CAINFO */
+    (ca_info_blob ? NULL : conn_config->CAfile);
+  const char * const ssl_capath = conn_config->CApath;
   WOLFSSL_METHOD* req_method = NULL;
 #ifdef HAVE_LIBOQS
   word16 oqsAlg = 0;
@@ -403,11 +417,11 @@ wolfssl_connect_step1(struct Curl_cfilter *cf, struct Curl_easy *data)
 #if defined(WOLFSSL_ALLOW_TLSV10) && !defined(NO_OLD_TLS)
     req_method = TLSv1_client_method();
     use_sni(TRUE);
+    break;
 #else
     failf(data, "wolfSSL does not support TLS 1.0");
     return CURLE_NOT_BUILT_IN;
 #endif
-    break;
   case CURL_SSLVERSION_TLSv1_1:
 #ifndef NO_OLD_TLS
     req_method = TLSv1_1_client_method();
@@ -475,6 +489,8 @@ wolfssl_connect_step1(struct Curl_cfilter *cf, struct Curl_easy *data)
       return CURLE_SSL_CONNECT_ERROR;
     }
 #endif
+    FALLTHROUGH();
+  default:
     break;
   }
 
@@ -508,7 +524,7 @@ wolfssl_connect_step1(struct Curl_cfilter *cf, struct Curl_easy *data)
     }
   }
 
-#ifndef NO_FILESYSTEM
+#if !defined(NO_FILESYSTEM) && defined(WOLFSSL_SYS_CA_CERTS)
   /* load native CA certificates */
   if(ssl_config->native_ca_store) {
     if(wolfSSL_CTX_load_system_CA_certs(backend->ctx) != WOLFSSL_SUCCESS) {
@@ -541,20 +557,21 @@ wolfssl_connect_step1(struct Curl_cfilter *cf, struct Curl_easy *data)
   }
 
 #ifndef NO_FILESYSTEM
-  /* load trusted cacert */
-  if(conn_config->CAfile) {
-    if(1 != wolfSSL_CTX_load_verify_locations(backend->ctx,
-                                              conn_config->CAfile,
-                                              conn_config->CApath)) {
+  /* load trusted cacert from file if not blob */
+  if(ssl_cafile || ssl_capath) {
+    int rc =
+      wolfSSL_CTX_load_verify_locations_ex(backend->ctx,
+                                           ssl_cafile,
+                                           ssl_capath,
+                                           WOLFSSL_LOAD_FLAG_IGNORE_ERR);
+    if(SSL_SUCCESS != rc) {
       if(conn_config->verifypeer && !imported_ca_info_blob &&
          !imported_native_ca) {
         /* Fail if we insist on successfully verifying the server. */
         failf(data, "error setting certificate verify locations:"
               " CAfile: %s CApath: %s",
-              conn_config->CAfile?
-              conn_config->CAfile: "none",
-              conn_config->CApath?
-              conn_config->CApath : "none");
+              ssl_cafile ? ssl_cafile : "none",
+              ssl_capath ? ssl_capath : "none");
         return CURLE_SSL_CACERT_BADFILE;
       }
       else {
@@ -568,22 +585,33 @@ wolfssl_connect_step1(struct Curl_cfilter *cf, struct Curl_easy *data)
       /* Everything is fine. */
       infof(data, "successfully set certificate verify locations:");
     }
-    infof(data, " CAfile: %s",
-          conn_config->CAfile ? conn_config->CAfile : "none");
-    infof(data, " CApath: %s",
-          conn_config->CApath ? conn_config->CApath : "none");
+    infof(data, " CAfile: %s", ssl_cafile ? ssl_cafile : "none");
+    infof(data, " CApath: %s", ssl_capath ? ssl_capath : "none");
   }
 
   /* Load the client certificate, and private key */
   if(ssl_config->primary.clientcert && ssl_config->key) {
     int file_type = do_file_type(ssl_config->cert_type);
 
-    if(wolfSSL_CTX_use_certificate_file(backend->ctx,
-                                        ssl_config->primary.clientcert,
-                                        file_type) != 1) {
-      failf(data, "unable to use client certificate (no key or wrong pass"
-            " phrase?)");
-      return CURLE_SSL_CONNECT_ERROR;
+    if(file_type == WOLFSSL_FILETYPE_PEM) {
+      if(wolfSSL_CTX_use_certificate_chain_file(backend->ctx,
+                                                ssl_config->primary.clientcert)
+         != 1) {
+        failf(data, "unable to use client certificate");
+        return CURLE_SSL_CONNECT_ERROR;
+      }
+    }
+    else if(file_type == WOLFSSL_FILETYPE_ASN1) {
+      if(wolfSSL_CTX_use_certificate_file(backend->ctx,
+                                          ssl_config->primary.clientcert,
+                                          file_type) != 1) {
+        failf(data, "unable to use client certificate");
+        return CURLE_SSL_CONNECT_ERROR;
+      }
+    }
+    else {
+      failf(data, "unknown cert type");
+      return CURLE_BAD_FUNCTION_ARGUMENT;
     }
 
     file_type = do_file_type(ssl_config->key_type);
@@ -604,24 +632,12 @@ wolfssl_connect_step1(struct Curl_cfilter *cf, struct Curl_easy *data)
                          SSL_VERIFY_NONE, NULL);
 
 #ifdef HAVE_SNI
-  if(sni) {
-    struct in_addr addr4;
-#ifdef ENABLE_IPV6
-    struct in6_addr addr6;
-#endif
-    size_t hostname_len = strlen(connssl->hostname);
-
-    if((hostname_len < USHRT_MAX) &&
-       !Curl_inet_pton(AF_INET, connssl->hostname, &addr4)
-#ifdef ENABLE_IPV6
-       && !Curl_inet_pton(AF_INET6, connssl->hostname, &addr6)
-#endif
-      ) {
-      size_t snilen;
-      char *snihost = Curl_ssl_snihost(data, connssl->hostname, &snilen);
-      if(!snihost ||
-         wolfSSL_CTX_UseSNI(backend->ctx, WOLFSSL_SNI_HOST_NAME, snihost,
-                            (unsigned short)snilen) != 1) {
+  if(sni && connssl->peer.sni) {
+    size_t sni_len = strlen(connssl->peer.sni);
+    if((sni_len < USHRT_MAX)) {
+      if(wolfSSL_CTX_UseSNI(backend->ctx, WOLFSSL_SNI_HOST_NAME,
+                            connssl->peer.sni,
+                            (unsigned short)sni_len) != 1) {
         failf(data, "Failed to set SNI");
         return CURLE_SSL_CONNECT_ERROR;
       }
@@ -704,7 +720,8 @@ wolfssl_connect_step1(struct Curl_cfilter *cf, struct Curl_easy *data)
     void *ssl_sessionid = NULL;
 
     Curl_ssl_sessionid_lock(data);
-    if(!Curl_ssl_getsessionid(cf, data, &ssl_sessionid, NULL)) {
+    if(!Curl_ssl_getsessionid(cf, data, &connssl->peer,
+                              &ssl_sessionid, NULL)) {
       /* we got a session id, use it! */
       if(!SSL_set_session(backend->handle, ssl_sessionid)) {
         Curl_ssl_delsessionid(data, ssl_sessionid);
@@ -716,11 +733,87 @@ wolfssl_connect_step1(struct Curl_cfilter *cf, struct Curl_easy *data)
     Curl_ssl_sessionid_unlock(data);
   }
 
+#ifdef USE_ECH
+  if(ECH_ENABLED(data)) {
+    int trying_ech_now = 0;
+
+    if(data->set.str[STRING_ECH_PUBLIC]) {
+      infof(data, "ECH: outername not (yet) supported with WolfSSL");
+      return CURLE_SSL_CONNECT_ERROR;
+    }
+    if(data->set.tls_ech == CURLECH_GREASE) {
+      infof(data, "ECH: GREASE'd ECH not yet supported for wolfSSL");
+      return CURLE_SSL_CONNECT_ERROR;
+    }
+    if(data->set.tls_ech & CURLECH_CLA_CFG
+       && data->set.str[STRING_ECH_CONFIG]) {
+      char *b64val = data->set.str[STRING_ECH_CONFIG];
+      word32 b64len = 0;
+
+      b64len = (word32) strlen(b64val);
+      if(b64len
+         && wolfSSL_SetEchConfigsBase64(backend->handle, b64val, b64len)
+              != WOLFSSL_SUCCESS) {
+        if(data->set.tls_ech & CURLECH_HARD)
+          return CURLE_SSL_CONNECT_ERROR;
+      }
+      else {
+       trying_ech_now = 1;
+       infof(data, "ECH: ECHConfig from command line");
+      }
+    }
+    else {
+      struct Curl_dns_entry *dns = NULL;
+
+      dns = Curl_fetch_addr(data, connssl->peer.hostname, connssl->peer.port);
+      if(!dns) {
+        infof(data, "ECH: requested but no DNS info available");
+        if(data->set.tls_ech & CURLECH_HARD)
+          return CURLE_SSL_CONNECT_ERROR;
+      }
+      else {
+        struct Curl_https_rrinfo *rinfo = NULL;
+
+        rinfo = dns->hinfo;
+        if(rinfo && rinfo->echconfiglist) {
+          unsigned char *ecl = rinfo->echconfiglist;
+          size_t elen = rinfo->echconfiglist_len;
+
+          infof(data, "ECH: ECHConfig from DoH HTTPS RR");
+          if(wolfSSL_SetEchConfigs(backend->handle, ecl, (word32) elen) !=
+                WOLFSSL_SUCCESS) {
+            infof(data, "ECH: wolfSSL_SetEchConfigs failed");
+            if(data->set.tls_ech & CURLECH_HARD)
+              return CURLE_SSL_CONNECT_ERROR;
+          }
+          else {
+            trying_ech_now = 1;
+            infof(data, "ECH: imported ECHConfigList of length %ld", elen);
+          }
+        }
+        else {
+          infof(data, "ECH: requested but no ECHConfig available");
+          if(data->set.tls_ech & CURLECH_HARD)
+            return CURLE_SSL_CONNECT_ERROR;
+        }
+        Curl_resolv_unlock(data, dns);
+      }
+    }
+
+    if(trying_ech_now
+       && SSL_set_min_proto_version(backend->handle, TLS1_3_VERSION) != 1) {
+      infof(data, "ECH: Can't force TLSv1.3 [ERROR]");
+      return CURLE_SSL_CONNECT_ERROR;
+    }
+
+  }
+#endif  /* USE_ECH */
+
 #ifdef USE_BIO_CHAIN
   {
     WOLFSSL_BIO *bio;
 
-    bio = BIO_new(bio_cf_method);
+    bio = BIO_new(wolfssl_bio_cf_method);
     if(!bio)
       return CURLE_OUT_OF_MEMORY;
 
@@ -749,9 +842,13 @@ wolfssl_connect_step2(struct Curl_cfilter *cf, struct Curl_easy *data)
   struct wolfssl_ssl_backend_data *backend =
     (struct wolfssl_ssl_backend_data *)connssl->backend;
   struct ssl_primary_config *conn_config = Curl_ssl_cf_get_primary_config(cf);
+#ifndef CURL_DISABLE_PROXY
   const char * const pinnedpubkey = Curl_ssl_cf_is_proxy(cf)?
     data->set.str[STRING_SSL_PINNEDPUBLICKEY_PROXY]:
     data->set.str[STRING_SSL_PINNEDPUBLICKEY];
+#else
+  const char * const pinnedpubkey = data->set.str[STRING_SSL_PINNEDPUBLICKEY];
+#endif
 
   DEBUGASSERT(backend);
 
@@ -759,9 +856,9 @@ wolfssl_connect_step2(struct Curl_cfilter *cf, struct Curl_easy *data)
 
   /* Enable RFC2818 checks */
   if(conn_config->verifyhost) {
-    char *snihost = Curl_ssl_snihost(data, connssl->hostname, NULL);
-    if(!snihost ||
-       (wolfSSL_check_domain_name(backend->handle, snihost) == SSL_FAILURE))
+    char *snihost = connssl->peer.sni?
+                    connssl->peer.sni : connssl->peer.hostname;
+    if(wolfSSL_check_domain_name(backend->handle, snihost) == SSL_FAILURE)
       return CURLE_SSL_CONNECT_ERROR;
   }
 
@@ -809,7 +906,7 @@ wolfssl_connect_step2(struct Curl_cfilter *cf, struct Curl_easy *data)
     else if(DOMAIN_NAME_MISMATCH == detail) {
 #if 1
       failf(data, " subject alt name(s) or common name do not match \"%s\"",
-            connssl->dispname);
+            connssl->peer.dispname);
       return CURLE_PEER_FAILED_VERIFICATION;
 #else
       /* When the wolfssl_check_domain_name() is used and you desire to
@@ -845,6 +942,31 @@ wolfssl_connect_step2(struct Curl_cfilter *cf, struct Curl_easy *data)
                     "continuing anyway");
       }
     }
+#endif
+#ifdef USE_ECH
+    else if(-1 == detail) {
+      /* try access a retry_config ECHConfigList for tracing */
+      byte echConfigs[1000];
+      word32 echConfigsLen = 1000;
+      int rv = 0;
+
+      /* this currently doesn't produce the retry_configs */
+      rv = wolfSSL_GetEchConfigs(backend->handle, echConfigs,
+                                 &echConfigsLen);
+      if(rv != WOLFSSL_SUCCESS) {
+        infof(data, "Failed to get ECHConfigs");
+      }
+      else {
+        char *b64str = NULL;
+        size_t blen = 0;
+
+        rv = Curl_base64_encode((const char *)echConfigs, echConfigsLen,
+                                &b64str, &blen);
+        if(!rv && b64str)
+          infof(data, "ECH: (not yet) retry_configs %s", b64str);
+        free(b64str);
+      }
+    }
 #endif
     else if(backend->io_result == CURLE_AGAIN) {
       return CURLE_OK;
@@ -891,6 +1013,7 @@ wolfssl_connect_step2(struct Curl_cfilter *cf, struct Curl_easy *data)
                                   pinnedpubkey,
                                   (const unsigned char *)pubkey->header,
                                   (size_t)(pubkey->end - pubkey->header));
+    wolfSSL_FreeX509(x509);
     if(result) {
       failf(data, "SSL: public key does not match pinned public key");
       return result;
@@ -935,6 +1058,13 @@ wolfssl_connect_step2(struct Curl_cfilter *cf, struct Curl_easy *data)
 }
 
 
+static void wolfssl_session_free(void *sessionid, size_t idsize)
+{
+  (void)idsize;
+  wolfSSL_SESSION_free(sessionid);
+}
+
+
 static CURLcode
 wolfssl_connect_step3(struct Curl_cfilter *cf, struct Curl_easy *data)
 {
@@ -948,40 +1078,27 @@ wolfssl_connect_step3(struct Curl_cfilter *cf, struct Curl_easy *data)
   DEBUGASSERT(backend);
 
   if(ssl_config->primary.sessionid) {
-    bool incache;
-    bool added = FALSE;
-    void *old_ssl_sessionid = NULL;
     /* wolfSSL_get1_session allocates memory that has to be freed. */
     WOLFSSL_SESSION *our_ssl_sessionid = wolfSSL_get1_session(backend->handle);
 
     if(our_ssl_sessionid) {
+      void *old_ssl_sessionid = NULL;
+      bool incache;
       Curl_ssl_sessionid_lock(data);
-      incache = !(Curl_ssl_getsessionid(cf, data, &old_ssl_sessionid, NULL));
+      incache = !(Curl_ssl_getsessionid(cf, data, &connssl->peer,
+                                        &old_ssl_sessionid, NULL));
       if(incache) {
-        if(old_ssl_sessionid != our_ssl_sessionid) {
-          infof(data, "old SSL session ID is stale, removing");
-          Curl_ssl_delsessionid(data, old_ssl_sessionid);
-          incache = FALSE;
-        }
+        Curl_ssl_delsessionid(data, old_ssl_sessionid);
       }
 
-      if(!incache) {
-        result = Curl_ssl_addsessionid(cf, data, our_ssl_sessionid, 0, NULL);
-        if(result) {
-          Curl_ssl_sessionid_unlock(data);
-          wolfSSL_SESSION_free(our_ssl_sessionid);
-          failf(data, "failed to store ssl session");
-          return result;
-        }
-        else {
-          added = TRUE;
-        }
-      }
+      /* call takes ownership of `our_ssl_sessionid` */
+      result = Curl_ssl_addsessionid(cf, data, &connssl->peer,
+                                     our_ssl_sessionid, 0,
+                                     wolfssl_session_free);
       Curl_ssl_sessionid_unlock(data);
-
-      if(!added) {
-        /* If the session info wasn't added to the cache, free our copy. */
-        wolfSSL_SESSION_free(our_ssl_sessionid);
+      if(result) {
+        failf(data, "failed to store ssl session");
+        return result;
       }
     }
   }
@@ -1053,7 +1170,8 @@ static void wolfssl_close(struct Curl_cfilter *cf, struct Curl_easy *data)
     /* Maybe the server has already sent a close notify alert.
        Read it to avoid an RST on the TCP connection. */
     (void)wolfSSL_read(backend->handle, buf, (int)sizeof(buf));
-    (void)wolfSSL_shutdown(backend->handle);
+    if(!connssl->peer_closed)
+      (void)wolfSSL_shutdown(backend->handle);
     wolfSSL_free(backend->handle);
     backend->handle = NULL;
   }
@@ -1091,9 +1209,7 @@ static ssize_t wolfssl_recv(struct Curl_cfilter *cf,
       *curlcode = CURLE_OK;
       return 0;
     case SSL_ERROR_NONE:
-      /* FALLTHROUGH */
     case SSL_ERROR_WANT_READ:
-      /* FALLTHROUGH */
     case SSL_ERROR_WANT_WRITE:
       /* there's data pending, re-invoke wolfSSL_read() */
       CURL_TRC_CF(data, cf, "wolfssl_recv(len=%zu) -> AGAIN", blen);
@@ -1116,12 +1232,6 @@ static ssize_t wolfssl_recv(struct Curl_cfilter *cf,
 }
 
 
-static void wolfssl_session_free(void *ptr)
-{
-  wolfSSL_SESSION_free(ptr);
-}
-
-
 static size_t wolfssl_version(char *buffer, size_t size)
 {
 #if LIBWOLFSSL_VERSION_HEX >= 0x03006000
@@ -1140,14 +1250,14 @@ static int wolfssl_init(void)
   Curl_tls_keylog_open();
 #endif
   ret = (wolfSSL_Init() == SSL_SUCCESS);
-  bio_cf_init_methods();
+  wolfssl_bio_cf_init_methods();
   return ret;
 }
 
 
 static void wolfssl_cleanup(void)
 {
-  bio_cf_free_methods();
+  wolfssl_bio_cf_free_methods();
   wolfSSL_Cleanup();
 #ifdef OPENSSL_EXTRA
   Curl_tls_keylog_close();
@@ -1378,7 +1488,11 @@ const struct Curl_ssl Curl_ssl_wolfssl = {
 #ifdef USE_BIO_CHAIN
   SSLSUPP_HTTPS_PROXY |
 #endif
+  SSLSUPP_CA_PATH |
   SSLSUPP_CAINFO_BLOB |
+#ifdef USE_ECH
+  SSLSUPP_ECH |
+#endif
   SSLSUPP_SSL_CTX,
 
   sizeof(struct wolfssl_ssl_backend_data),
@@ -1393,11 +1507,10 @@ const struct Curl_ssl Curl_ssl_wolfssl = {
   Curl_none_cert_status_request,   /* cert_status_request */
   wolfssl_connect,                 /* connect */
   wolfssl_connect_nonblocking,     /* connect_nonblocking */
-  Curl_ssl_get_select_socks,                /* getsock */
+  Curl_ssl_adjust_pollset,         /* adjust_pollset */
   wolfssl_get_internals,           /* get_internals */
   wolfssl_close,                   /* close_one */
   Curl_none_close_all,             /* close_all */
-  wolfssl_session_free,            /* session_free */
   Curl_none_set_engine,            /* set_engine */
   Curl_none_set_engine_default,    /* set_engine_default */
   Curl_none_engines_list,          /* engines_list */
diff --git a/vendor/curl/lib/vtls/x509asn1.c b/vendor/curl/lib/vtls/x509asn1.c
index c3fd3a30bb..4564ea958a 100644
--- a/vendor/curl/lib/vtls/x509asn1.c
+++ b/vendor/curl/lib/vtls/x509asn1.c
@@ -97,6 +97,11 @@
 #define CURL_ASN1_CHARACTER_STRING      29
 #define CURL_ASN1_BMP_STRING            30
 
+/* Max sixes */
+
+#define MAX_X509_STR  10000
+#define MAX_X509_CERT 100000
+
 #ifdef WANT_EXTRACT_CERTINFO
 /* ASN.1 OID table entry. */
 struct Curl_OID {
@@ -155,6 +160,7 @@ static const struct Curl_OID OIDtable[] = {
   { "2.16.840.1.101.3.4.2.1",   "sha256" },
   { "2.16.840.1.101.3.4.2.2",   "sha384" },
   { "2.16.840.1.101.3.4.2.3",   "sha512" },
+  { "1.2.840.113549.1.9.2",     "unstructuredName" },
   { (const char *) NULL,        (const char *) NULL }
 };
 
@@ -255,61 +261,61 @@ static const struct Curl_OID *searchOID(const char *oid)
 }
 
 /*
- * Convert an ASN.1 Boolean value into its string representation.  Return the
- * dynamically allocated string, or NULL if source is not an ASN.1 Boolean
- * value.
+ * Convert an ASN.1 Boolean value into its string representation.
+ *
+ * Return error code.
  */
 
-static const char *bool2str(const char *beg, const char *end)
+static CURLcode bool2str(struct dynbuf *store,
+                         const char *beg, const char *end)
 {
   if(end - beg != 1)
-    return NULL;
-  return strdup(*beg? "TRUE": "FALSE");
+    return CURLE_BAD_FUNCTION_ARGUMENT;
+  return Curl_dyn_add(store, *beg? "TRUE": "FALSE");
 }
 
 /*
  * Convert an ASN.1 octet string to a printable string.
- * Return the dynamically allocated string, or NULL if an error occurs.
+ *
+ * Return error code.
  */
-static const char *octet2str(const char *beg, const char *end)
+static CURLcode octet2str(struct dynbuf *store,
+                          const char *beg, const char *end)
 {
-  struct dynbuf buf;
-  CURLcode result;
-
-  Curl_dyn_init(&buf, 3 * CURL_ASN1_MAX + 1);
-  result = Curl_dyn_addn(&buf, "", 0);
+  CURLcode result = CURLE_OK;
 
   while(!result && beg < end)
-    result = Curl_dyn_addf(&buf, "%02x:", (unsigned char) *beg++);
+    result = Curl_dyn_addf(store, "%02x:", (unsigned char) *beg++);
 
-  return Curl_dyn_ptr(&buf);
+  return result;
 }
 
-static const char *bit2str(const char *beg, const char *end)
+static CURLcode bit2str(struct dynbuf *store,
+                        const char *beg, const char *end)
 {
-  /* Convert an ASN.1 bit string to a printable string.
-     Return the dynamically allocated string, or NULL if an error occurs. */
+  /* Convert an ASN.1 bit string to a printable string. */
 
   if(++beg > end)
-    return NULL;
-  return octet2str(beg, end);
+    return CURLE_BAD_FUNCTION_ARGUMENT;
+  return octet2str(store, beg, end);
 }
 
 /*
  * Convert an ASN.1 integer value into its string representation.
- * Return the dynamically allocated string, or NULL if source is not an
- * ASN.1 integer value.
+ *
+ * Returns error.
  */
-static const char *int2str(const char *beg, const char *end)
+static CURLcode int2str(struct dynbuf *store,
+                        const char *beg, const char *end)
 {
   unsigned int val = 0;
   size_t n = end - beg;
 
   if(!n)
-    return NULL;
+    return CURLE_BAD_FUNCTION_ARGUMENT;
 
   if(n > 4)
-    return octet2str(beg, end);
+    return octet2str(store, beg, end);
 
   /* Represent integers <= 32-bit as a single value. */
   if(*beg & 0x80)
@@ -318,25 +324,24 @@ static const char *int2str(const char *beg, const char *end)
   do
     val = (val << 8) | *(const unsigned char *) beg++;
   while(beg < end);
-  return curl_maprintf("%s%x", val >= 10? "0x": "", val);
+  return Curl_dyn_addf(store, "%s%x", val >= 10? "0x": "", val);
 }
 
 /*
- * Perform a lazy conversion from an ASN.1 typed string to UTF8. Allocate the
- * destination buffer dynamically. The allocation size will normally be too
- * large: this is to avoid buffer overflows.
- * Terminate the string with a nul byte and return the converted
- * string length.
+ * Convert from an ASN.1 typed string to UTF8.
+ *
+ * The result is stored in a dynbuf that is inited by the user of this
+ * function.
+ *
+ * Returns error.
  */
-static ssize_t
-utf8asn1str(char **to, int type, const char *from, const char *end)
+static CURLcode
+utf8asn1str(struct dynbuf *to, int type, const char *from, const char *end)
 {
   size_t inlength = end - from;
   int size = 1;
-  size_t outlength;
-  char *buf;
+  CURLcode result = CURLE_OK;
 
-  *to = NULL;
   switch(type) {
   case CURL_ASN1_BMP_STRING:
     size = 2;
@@ -352,133 +357,85 @@ utf8asn1str(char **to, int type, const char *from, const char *end)
   case CURL_ASN1_UTF8_STRING:
     break;
   default:
-    return -1;  /* Conversion not supported. */
+    return CURLE_BAD_FUNCTION_ARGUMENT;  /* Conversion not supported. */
   }
 
   if(inlength % size)
-    return -1;  /* Length inconsistent with character size. */
-  if(inlength / size > (SIZE_T_MAX - 1) / 4)
-    return -1;  /* Too big. */
-  buf = malloc(4 * (inlength / size) + 1);
-  if(!buf)
-    return -1;  /* Not enough memory. */
+    /* Length inconsistent with character size. */
+    return CURLE_BAD_FUNCTION_ARGUMENT;
 
   if(type == CURL_ASN1_UTF8_STRING) {
     /* Just copy. */
-    outlength = inlength;
-    if(outlength)
-      memcpy(buf, from, outlength);
+    if(inlength)
+      result = Curl_dyn_addn(to, from, inlength);
   }
   else {
-    for(outlength = 0; from < end;) {
-      int charsize;
-      unsigned int wc;
+    while(!result && (from < end)) {
+      char buf[4]; /* decode buffer */
+      int charsize = 1;
+      unsigned int wc = 0;
 
-      wc = 0;
       switch(size) {
       case 4:
         wc = (wc << 8) | *(const unsigned char *) from++;
         wc = (wc << 8) | *(const unsigned char *) from++;
-        /* FALLTHROUGH */
+        FALLTHROUGH();
       case 2:
         wc = (wc << 8) | *(const unsigned char *) from++;
-        /* FALLTHROUGH */
+        FALLTHROUGH();
       default: /* case 1: */
         wc = (wc << 8) | *(const unsigned char *) from++;
       }
-      charsize = 1;
       if(wc >= 0x00000080) {
         if(wc >= 0x00000800) {
           if(wc >= 0x00010000) {
             if(wc >= 0x00200000) {
               free(buf);
-              return -1;        /* Invalid char. size for target encoding. */
+              /* Invalid char. size for target encoding. */
+              return CURLE_WEIRD_SERVER_REPLY;
             }
-            buf[outlength + 3] = (char) (0x80 | (wc & 0x3F));
+            buf[3] = (char) (0x80 | (wc & 0x3F));
             wc = (wc >> 6) | 0x00010000;
             charsize++;
           }
-          buf[outlength + 2] = (char) (0x80 | (wc & 0x3F));
+          buf[2] = (char) (0x80 | (wc & 0x3F));
           wc = (wc >> 6) | 0x00000800;
           charsize++;
         }
-        buf[outlength + 1] = (char) (0x80 | (wc & 0x3F));
+        buf[1] = (char) (0x80 | (wc & 0x3F));
         wc = (wc >> 6) | 0x000000C0;
         charsize++;
       }
-      buf[outlength] = (char) wc;
-      outlength += charsize;
+      buf[0] = (char) wc;
+      result = Curl_dyn_addn(to, buf, charsize);
     }
   }
-  buf[outlength] = '\0';
-  *to = buf;
-  return outlength;
-}
-
-/*
- * Convert an ASN.1 String into its UTF-8 string representation.
- * Return the dynamically allocated string, or NULL if an error occurs.
- */
-static const char *string2str(int type, const char *beg, const char *end)
-{
-  char *buf;
-  if(utf8asn1str(&buf, type, beg, end) < 0)
-    return NULL;
-  return buf;
-}
-
-/*
- * Decimal ASCII encode unsigned integer `x' into the buflen sized buffer at
- * buf.  Return the total number of encoded digits, even if larger than
- * `buflen'.
- */
-static size_t encodeUint(char *buf, size_t buflen, unsigned int x)
-{
-  size_t i = 0;
-  unsigned int y = x / 10;
-
-  if(y) {
-    i = encodeUint(buf, buflen, y);
-    x -= y * 10;
-  }
-  if(i < buflen)
-    buf[i] = (char) ('0' + x);
-  i++;
-  if(i < buflen)
-    buf[i] = '\0';      /* Store a terminator if possible. */
-  return i;
+  return result;
 }
 
 /*
  * Convert an ASN.1 OID into its dotted string representation.
- * Store the result in th `n'-byte buffer at `buf'.
- * Return the converted string length, or 0 on errors.
+ *
+ * Return error code.
  */
-static size_t encodeOID(char *buf, size_t buflen,
-                        const char *beg, const char *end)
+static CURLcode encodeOID(struct dynbuf *store,
+                          const char *beg, const char *end)
 {
-  size_t i;
   unsigned int x;
   unsigned int y;
+  CURLcode result = CURLE_OK;
 
   /* Process the first two numbers. */
   y = *(const unsigned char *) beg++;
   x = y / 40;
   y -= x * 40;
-  i = encodeUint(buf, buflen, x);
-  if(i < buflen)
-    buf[i] = '.';
-  i++;
-  if(i >= buflen)
-    i += encodeUint(NULL, 0, y);
-  else
-    i += encodeUint(buf + i, buflen - i, y);
+
+  result = Curl_dyn_addf(store, "%u.%u", x, y);
+  if(result)
+    return result;
 
   /* Process the trailing numbers. */
   while(beg < end) {
-    if(i < buflen)
-      buf[i] = '.';
-    i++;
     x = 0;
     do {
       if(x & 0xFF000000)
@@ -486,46 +443,44 @@ static size_t encodeOID(char *buf, size_t buflen,
       y = *(const unsigned char *) beg++;
       x = (x << 7) | (y & 0x7F);
     } while(y & 0x80);
-    if(i >= buflen)
-      i += encodeUint(NULL, 0, x);
-    else
-      i += encodeUint(buf + i, buflen - i, x);
+    result = Curl_dyn_addf(store, ".%u", x);
   }
-  if(i < buflen)
-    buf[i] = '\0';
-  return i;
+  return result;
 }
 
 /*
  * Convert an ASN.1 OID into its dotted or symbolic string representation.
- * Return the dynamically allocated string, or NULL if an error occurs.
+ *
+ * Return error code.
  */
 
-static const char *OID2str(const char *beg, const char *end, bool symbolic)
+static CURLcode OID2str(struct dynbuf *store,
+                        const char *beg, const char *end, bool symbolic)
 {
-  char *buf = NULL;
+  CURLcode result = CURLE_OK;
   if(beg < end) {
-    size_t buflen = encodeOID(NULL, 0, beg, end);
-    if(buflen) {
-      buf = malloc(buflen + 1); /* one extra for the zero byte */
-      if(buf) {
-        encodeOID(buf, buflen, beg, end);
-        buf[buflen] = '\0';
-
-        if(symbolic) {
-          const struct Curl_OID *op = searchOID(buf);
-          if(op) {
-            free(buf);
-            buf = strdup(op->textoid);
-          }
-        }
+    if(symbolic) {
+      struct dynbuf buf;
+      Curl_dyn_init(&buf, MAX_X509_STR);
+      result = encodeOID(&buf, beg, end);
+
+      if(!result) {
+        const struct Curl_OID *op = searchOID(Curl_dyn_ptr(&buf));
+        if(op)
+          result = Curl_dyn_add(store, op->textoid);
+        else
+          result = CURLE_BAD_FUNCTION_ARGUMENT;
+        Curl_dyn_free(&buf);
       }
     }
+    else
+      result = encodeOID(store, beg, end);
   }
-  return buf;
+  return result;
 }
 
-static const char *GTime2str(const char *beg, const char *end)
+static CURLcode GTime2str(struct dynbuf *store,
+                          const char *beg, const char *end)
 {
   const char *tzp;
   const char *fracp;
@@ -548,12 +503,12 @@ static const char *GTime2str(const char *beg, const char *end)
     break;
   case 2:
     sec1 = fracp[-2];
-    /* FALLTHROUGH */
+    FALLTHROUGH();
   case 1:
     sec2 = fracp[-1];
     break;
   default:
-    return NULL;
+    return CURLE_BAD_FUNCTION_ARGUMENT;
   }
 
   /* Scan for timezone, measure fractional seconds. */
@@ -582,7 +537,8 @@ static const char *GTime2str(const char *beg, const char *end)
   }
 
   tzl = end - tzp;
-  return curl_maprintf("%.4s-%.2s-%.2s %.2s:%.2s:%c%c%s%.*s%s%.*s",
+  return Curl_dyn_addf(store,
+                       "%.4s-%.2s-%.2s %.2s:%.2s:%c%c%s%.*s%s%.*s",
                        beg, beg + 4, beg + 6,
                        beg + 8, beg + 10, sec1, sec2,
                        fracl? ".": "", (int)fracl, fracp,
@@ -590,10 +546,12 @@ static const char *GTime2str(const char *beg, const char *end)
 }
 
 /*
- *  Convert an ASN.1 UTC time to a printable string.
- * Return the dynamically allocated string, or NULL if an error occurs.
+ * Convert an ASN.1 UTC time to a printable string.
+ *
+ * Return error code.
  */
-static const char *UTime2str(const char *beg, const char *end)
+static CURLcode UTime2str(struct dynbuf *store,
+                             const char *beg, const char *end)
 {
   const char *tzp;
   size_t tzl;
@@ -606,15 +564,16 @@ static const char *UTime2str(const char *beg, const char *end)
   switch(tzp - sec) {
   case 0:
     sec = "00";
+    FALLTHROUGH();
   case 2:
     break;
   default:
-    return NULL;
+    return CURLE_BAD_FUNCTION_ARGUMENT;
   }
 
   /* Process timezone. */
   if(tzp >= end)
-    return NULL;
+    return CURLE_BAD_FUNCTION_ARGUMENT;
   if(*tzp == 'Z') {
     tzp = "GMT";
     end = tzp + 3;
@@ -623,7 +582,7 @@ static const char *UTime2str(const char *beg, const char *end)
     tzp++;
 
   tzl = end - tzp;
-  return curl_maprintf("%u%.2s-%.2s-%.2s %.2s:%.2s:%.2s %.*s",
+  return Curl_dyn_addf(store, "%u%.2s-%.2s-%.2s %.2s:%.2s:%.2s %.*s",
                        20 - (*beg >= '5'), beg, beg + 2, beg + 4,
                        beg + 6, beg + 8, sec,
                        (int)tzl, tzp);
@@ -631,34 +590,45 @@ static const char *UTime2str(const char *beg, const char *end)
 
 /*
  * Convert an ASN.1 element to a printable string.
- * Return the dynamically allocated string, or NULL if an error occurs.
+ *
+ * Return error
  */
-static const char *ASN1tostr(struct Curl_asn1Element *elem, int type)
+static CURLcode ASN1tostr(struct dynbuf *store,
+                          struct Curl_asn1Element *elem, int type)
 {
+  CURLcode result = CURLE_BAD_FUNCTION_ARGUMENT;
   if(elem->constructed)
-    return NULL; /* No conversion of structured elements. */
+    return CURLE_OK; /* No conversion of structured elements. */
 
   if(!type)
     type = elem->tag;   /* Type not forced: use element tag as type. */
 
   switch(type) {
   case CURL_ASN1_BOOLEAN:
-    return bool2str(elem->beg, elem->end);
+    result = bool2str(store, elem->beg, elem->end);
+    break;
   case CURL_ASN1_INTEGER:
   case CURL_ASN1_ENUMERATED:
-    return int2str(elem->beg, elem->end);
+    result = int2str(store, elem->beg, elem->end);
+    break;
   case CURL_ASN1_BIT_STRING:
-    return bit2str(elem->beg, elem->end);
+    result = bit2str(store, elem->beg, elem->end);
+    break;
   case CURL_ASN1_OCTET_STRING:
-    return octet2str(elem->beg, elem->end);
+    result = octet2str(store, elem->beg, elem->end);
+    break;
   case CURL_ASN1_NULL:
-    return strdup("");
+    result = Curl_dyn_addn(store, "", 1);
+    break;
   case CURL_ASN1_OBJECT_IDENTIFIER:
-    return OID2str(elem->beg, elem->end, TRUE);
+    result = OID2str(store, elem->beg, elem->end, TRUE);
+    break;
   case CURL_ASN1_UTC_TIME:
-    return UTime2str(elem->beg, elem->end);
+    result = UTime2str(store, elem->beg, elem->end);
+    break;
   case CURL_ASN1_GENERALIZED_TIME:
-    return GTime2str(elem->beg, elem->end);
+    result = GTime2str(store, elem->beg, elem->end);
+    break;
   case CURL_ASN1_UTF8_STRING:
   case CURL_ASN1_NUMERIC_STRING:
   case CURL_ASN1_PRINTABLE_STRING:
@@ -667,87 +637,96 @@ static const char *ASN1tostr(struct Curl_asn1Element *elem, int type)
   case CURL_ASN1_VISIBLE_STRING:
   case CURL_ASN1_UNIVERSAL_STRING:
   case CURL_ASN1_BMP_STRING:
-    return string2str(type, elem->beg, elem->end);
+    result = utf8asn1str(store, type, elem->beg, elem->end);
+    break;
   }
 
-  return NULL;   /* Unsupported. */
+  return result;
 }
 
 /*
- * ASCII encode distinguished name at `dn' into the `buflen'-sized buffer at
- * `buf'.
+ * ASCII encode distinguished name at `dn' into the store dynbuf.
  *
- * Returns the total string length, even if larger than `buflen' or -1 on
- * error.
+ * Returns error.
  */
-static ssize_t encodeDN(char *buf, size_t buflen, struct Curl_asn1Element *dn)
+static CURLcode encodeDN(struct dynbuf *store, struct Curl_asn1Element *dn)
 {
   struct Curl_asn1Element rdn;
   struct Curl_asn1Element atv;
   struct Curl_asn1Element oid;
   struct Curl_asn1Element value;
-  size_t l = 0;
   const char *p1;
   const char *p2;
   const char *p3;
   const char *str;
+  CURLcode result = CURLE_OK;
+  bool added = FALSE;
+  struct dynbuf temp;
+  Curl_dyn_init(&temp, MAX_X509_STR);
 
   for(p1 = dn->beg; p1 < dn->end;) {
     p1 = getASN1Element(&rdn, p1, dn->end);
-    if(!p1)
-      return -1;
+    if(!p1) {
+      result = CURLE_BAD_FUNCTION_ARGUMENT;
+      goto error;
+    }
     for(p2 = rdn.beg; p2 < rdn.end;) {
       p2 = getASN1Element(&atv, p2, rdn.end);
-      if(!p2)
-        return -1;
+      if(!p2) {
+        result = CURLE_BAD_FUNCTION_ARGUMENT;
+        goto error;
+      }
       p3 = getASN1Element(&oid, atv.beg, atv.end);
-      if(!p3)
-        return -1;
-      if(!getASN1Element(&value, p3, atv.end))
-        return -1;
-      str = ASN1tostr(&oid, 0);
-      if(!str)
-        return -1;
+      if(!p3) {
+        result = CURLE_BAD_FUNCTION_ARGUMENT;
+        goto error;
+      }
+      if(!getASN1Element(&value, p3, atv.end)) {
+        result = CURLE_BAD_FUNCTION_ARGUMENT;
+        goto error;
+      }
+      Curl_dyn_reset(&temp);
+      result = ASN1tostr(&temp, &oid, 0);
+      if(result)
+        goto error;
+
+      str = Curl_dyn_ptr(&temp);
 
       /* Encode delimiter.
          If attribute has a short uppercase name, delimiter is ", ". */
-      if(l) {
-        for(p3 = str; ISUPPER(*p3); p3++)
-          ;
-        for(p3 = (*p3 || p3 - str > 2)? "/": ", "; *p3; p3++) {
-          if(l < buflen)
-            buf[l] = *p3;
-          l++;
-        }
+      for(p3 = str; ISUPPER(*p3); p3++)
+        ;
+      if(added) {
+        if(p3 - str > 2)
+          result = Curl_dyn_addn(store, "/", 1);
+        else
+          result = Curl_dyn_addn(store, ", ", 2);
+        if(result)
+          goto error;
       }
 
       /* Encode attribute name. */
-      for(p3 = str; *p3; p3++) {
-        if(l < buflen)
-          buf[l] = *p3;
-        l++;
-      }
-      free((char *) str);
+      result = Curl_dyn_add(store, str);
+      if(result)
+        goto error;
 
       /* Generate equal sign. */
-      if(l < buflen)
-        buf[l] = '=';
-      l++;
+      result = Curl_dyn_addn(store, "=", 1);
+      if(result)
+        goto error;
 
       /* Generate value. */
-      str = ASN1tostr(&value, 0);
-      if(!str)
-        return -1;
-      for(p3 = str; *p3; p3++) {
-        if(l < buflen)
-          buf[l] = *p3;
-        l++;
-      }
-      free((char *) str);
+      result = ASN1tostr(store, &value, 0);
+      if(result)
+        goto error;
+      Curl_dyn_reset(&temp);
+      added = TRUE; /* use separator for next */
     }
   }
+error:
+  Curl_dyn_free(&temp);
 
-  return l;
+  return result;
 }
 
 #endif /* WANT_EXTRACT_CERTINFO */
@@ -876,25 +855,9 @@ int Curl_parseX509(struct Curl_X509certificate *cert,
 
 #ifdef WANT_EXTRACT_CERTINFO
 
-/*
- * Copy at most 64-characters, terminate with a newline and returns the
- * effective number of stored characters.
- */
-static size_t copySubstring(char *to, const char *from)
-{
-  size_t i;
-  for(i = 0; i < 64; i++) {
-    to[i] = *from;
-    if(!*from++)
-      break;
-  }
-
-  to[i++] = '\n';
-  return i;
-}
-
-static const char *dumpAlgo(struct Curl_asn1Element *param,
-                            const char *beg, const char *end)
+static CURLcode dumpAlgo(struct dynbuf *store,
+                         struct Curl_asn1Element *param,
+                         const char *beg, const char *end)
 {
   struct Curl_asn1Element oid;
 
@@ -902,14 +865,16 @@ static const char *dumpAlgo(struct Curl_asn1Element *param,
 
   beg = getASN1Element(&oid, beg, end);
   if(!beg)
-    return NULL;
+    return CURLE_BAD_FUNCTION_ARGUMENT;
   param->header = NULL;
   param->tag = 0;
   param->beg = param->end = end;
-  if(beg < end)
-    if(!getASN1Element(param, beg, end))
-      return NULL;
-  return OID2str(oid.beg, oid.end, TRUE);
+  if(beg < end) {
+    const char *p = getASN1Element(param, beg, end);
+    if(!p)
+      return CURLE_BAD_FUNCTION_ARGUMENT;
+  }
+  return OID2str(store, oid.beg, oid.end, TRUE);
 }
 
 /*
@@ -926,24 +891,47 @@ static CURLcode ssl_push_certinfo(struct Curl_easy *data,
   return Curl_ssl_push_certinfo_len(data, certnum, label, value, valuelen);
 }
 
-/* return 0 on success, 1 on error */
-static int do_pubkey_field(struct Curl_easy *data, int certnum,
-                           const char *label, struct Curl_asn1Element *elem)
+/*
+ * This is a convenience function for push_certinfo_len that takes a
+ * dynbuf value.
+ *
+ * It also does the verbose output if !certnum.
+ */
+static CURLcode ssl_push_certinfo_dyn(struct Curl_easy *data,
+                                      int certnum,
+                                      const char *label,
+                                      struct dynbuf *ptr)
 {
-  const char *output;
-  CURLcode result = CURLE_OK;
+  size_t valuelen = Curl_dyn_len(ptr);
+  char *value = Curl_dyn_ptr(ptr);
+
+  CURLcode result = Curl_ssl_push_certinfo_len(data, certnum, label,
+                                               value, valuelen);
+
+  if(!certnum && !result)
+    infof(data, "   %s: %s", label, value);
+
+  return result;
+}
+
+static CURLcode do_pubkey_field(struct Curl_easy *data, int certnum,
+                                const char *label,
+                                struct Curl_asn1Element *elem)
+{
+  CURLcode result;
+  struct dynbuf out;
+
+  Curl_dyn_init(&out, MAX_X509_STR);
 
   /* Generate a certificate information record for the public key. */
 
-  output = ASN1tostr(elem, 0);
-  if(output) {
+  result = ASN1tostr(&out, elem, 0);
+  if(!result) {
     if(data->set.ssl.certinfo)
-      result = ssl_push_certinfo(data, certnum, label, output);
-    if(!certnum && !result)
-      infof(data, "   %s: %s", label, output);
-    free((char *) output);
+      result = ssl_push_certinfo_dyn(data, certnum, label, &out);
+    Curl_dyn_free(&out);
   }
-  return result ? 1 : 0;
+  return result;
 }
 
 /* return 0 on success, 1 on error */
@@ -964,7 +952,7 @@ static int do_pubkey(struct Curl_easy *data, int certnum,
      */
     const size_t len = ((pubkey->end - pubkey->beg - 2) * 4);
     if(!certnum)
-      infof(data, "   ECC Public Key (%lu bits)", len);
+      infof(data, "   ECC Public Key (%zu bits)", len);
     if(data->set.ssl.certinfo) {
       char q[sizeof(len) * 8 / 3 + 1];
       (void)msnprintf(q, sizeof(q), "%zu", len);
@@ -998,7 +986,7 @@ static int do_pubkey(struct Curl_easy *data, int certnum,
     if(len > 32)
       elem.beg = q;     /* Strip leading zero bytes. */
     if(!certnum)
-      infof(data, "   RSA Public Key (%lu bits)", len);
+      infof(data, "   RSA Public Key (%zu bits)", len);
     if(data->set.ssl.certinfo) {
       char r[sizeof(len) * 8 / 3 + 1];
       msnprintf(r, sizeof(r), "%zu", len);
@@ -1049,24 +1037,12 @@ static int do_pubkey(struct Curl_easy *data, int certnum,
 
 /*
  * Convert an ASN.1 distinguished name into a printable string.
- * Return the dynamically allocated string, or NULL if an error occurs.
+ * Return error.
  */
-static const char *DNtostr(struct Curl_asn1Element *dn)
+static CURLcode DNtostr(struct dynbuf *store,
+                        struct Curl_asn1Element *dn)
 {
-  char *buf = NULL;
-  ssize_t buflen = encodeDN(NULL, 0, dn);
-
-  if(buflen >= 0) {
-    buf = malloc(buflen + 1);
-    if(buf) {
-      if(encodeDN(buf, buflen + 1, dn) == -1) {
-        free(buf);
-        return NULL;
-      }
-      buf[buflen] = '\0';
-    }
-  }
-  return buf;
+  return encodeDN(store, dn);
 }
 
 CURLcode Curl_extract_certinfo(struct Curl_easy *data,
@@ -1076,19 +1052,19 @@ CURLcode Curl_extract_certinfo(struct Curl_easy *data,
 {
   struct Curl_X509certificate cert;
   struct Curl_asn1Element param;
-  const char *ccp;
-  char *cp1;
-  size_t cl1;
-  char *cp2;
+  char *certptr;
+  size_t clen;
+  struct dynbuf out;
   CURLcode result = CURLE_OK;
   unsigned int version;
-  size_t i;
-  size_t j;
+  const char *ptr;
+  int rc;
 
   if(!data->set.ssl.certinfo)
     if(certnum)
       return CURLE_OK;
 
+  Curl_dyn_init(&out, MAX_X509_STR);
   /* Prepare the certificate information for curl_easy_getinfo(). */
 
   /* Extract the certificate ASN.1 elements. */
@@ -1096,135 +1072,126 @@ CURLcode Curl_extract_certinfo(struct Curl_easy *data,
     return CURLE_PEER_FAILED_VERIFICATION;
 
   /* Subject. */
-  ccp = DNtostr(&cert.subject);
-  if(!ccp)
-    return CURLE_OUT_OF_MEMORY;
+  result = DNtostr(&out, &cert.subject);
+  if(result)
+    goto done;
   if(data->set.ssl.certinfo) {
-    result = ssl_push_certinfo(data, certnum, "Subject", ccp);
+    result = ssl_push_certinfo_dyn(data, certnum, "Subject", &out);
     if(result)
-      return result;
+      goto done;
   }
-  if(!certnum)
-    infof(data, "%2d Subject: %s", certnum, ccp);
-  free((char *) ccp);
+  Curl_dyn_reset(&out);
 
   /* Issuer. */
-  ccp = DNtostr(&cert.issuer);
-  if(!ccp)
-    return CURLE_OUT_OF_MEMORY;
+  result = DNtostr(&out, &cert.issuer);
+  if(result)
+    goto done;
   if(data->set.ssl.certinfo) {
-    result = ssl_push_certinfo(data, certnum, "Issuer", ccp);
+    result = ssl_push_certinfo_dyn(data, certnum, "Issuer", &out);
+    if(result)
+      goto done;
   }
-  if(!certnum)
-    infof(data, "   Issuer: %s", ccp);
-  free((char *) ccp);
-  if(result)
-    return result;
+  Curl_dyn_reset(&out);
 
   /* Version (always fits in less than 32 bits). */
   version = 0;
-  for(ccp = cert.version.beg; ccp < cert.version.end; ccp++)
-    version = (version << 8) | *(const unsigned char *) ccp;
+  for(ptr = cert.version.beg; ptr < cert.version.end; ptr++)
+    version = (version << 8) | *(const unsigned char *) ptr;
   if(data->set.ssl.certinfo) {
-    ccp = curl_maprintf("%x", version);
-    if(!ccp)
-      return CURLE_OUT_OF_MEMORY;
-    result = ssl_push_certinfo(data, certnum, "Version", ccp);
-    free((char *) ccp);
+    result = Curl_dyn_addf(&out, "%x", version);
+    if(result)
+      goto done;
+    result = ssl_push_certinfo_dyn(data, certnum, "Version", &out);
     if(result)
-      return result;
+      goto done;
+    Curl_dyn_reset(&out);
   }
-  if(!certnum)
-    infof(data, "   Version: %u (0x%x)", version + 1, version);
 
   /* Serial number. */
-  ccp = ASN1tostr(&cert.serialNumber, 0);
-  if(!ccp)
-    return CURLE_OUT_OF_MEMORY;
-  if(data->set.ssl.certinfo)
-    result = ssl_push_certinfo(data, certnum, "Serial Number", ccp);
-  if(!certnum)
-    infof(data, "   Serial Number: %s", ccp);
-  free((char *) ccp);
+  result = ASN1tostr(&out, &cert.serialNumber, 0);
   if(result)
-    return result;
+    goto done;
+  if(data->set.ssl.certinfo) {
+    result = ssl_push_certinfo_dyn(data, certnum, "Serial Number", &out);
+    if(result)
+      goto done;
+  }
+  Curl_dyn_reset(&out);
 
   /* Signature algorithm .*/
-  ccp = dumpAlgo(¶m, cert.signatureAlgorithm.beg,
-                 cert.signatureAlgorithm.end);
-  if(!ccp)
-    return CURLE_OUT_OF_MEMORY;
-  if(data->set.ssl.certinfo)
-    result = ssl_push_certinfo(data, certnum, "Signature Algorithm", ccp);
-  if(!certnum)
-    infof(data, "   Signature Algorithm: %s", ccp);
-  free((char *) ccp);
+  result = dumpAlgo(&out, ¶m, cert.signatureAlgorithm.beg,
+                    cert.signatureAlgorithm.end);
   if(result)
-    return result;
+    goto done;
+  if(data->set.ssl.certinfo) {
+    result = ssl_push_certinfo_dyn(data, certnum, "Signature Algorithm",
+                                   &out);
+    if(result)
+      goto done;
+  }
+  Curl_dyn_reset(&out);
 
   /* Start Date. */
-  ccp = ASN1tostr(&cert.notBefore, 0);
-  if(!ccp)
-    return CURLE_OUT_OF_MEMORY;
-  if(data->set.ssl.certinfo)
-    result = ssl_push_certinfo(data, certnum, "Start Date", ccp);
-  if(!certnum)
-    infof(data, "   Start Date: %s", ccp);
-  free((char *) ccp);
+  result = ASN1tostr(&out, &cert.notBefore, 0);
   if(result)
-    return result;
+    goto done;
+  if(data->set.ssl.certinfo) {
+    result = ssl_push_certinfo_dyn(data, certnum, "Start Date", &out);
+    if(result)
+      goto done;
+  }
+  Curl_dyn_reset(&out);
 
   /* Expire Date. */
-  ccp = ASN1tostr(&cert.notAfter, 0);
-  if(!ccp)
-    return CURLE_OUT_OF_MEMORY;
-  if(data->set.ssl.certinfo)
-    result = ssl_push_certinfo(data, certnum, "Expire Date", ccp);
-  if(!certnum)
-    infof(data, "   Expire Date: %s", ccp);
-  free((char *) ccp);
+  result = ASN1tostr(&out, &cert.notAfter, 0);
   if(result)
-    return result;
+    goto done;
+  if(data->set.ssl.certinfo) {
+    result = ssl_push_certinfo_dyn(data, certnum, "Expire Date", &out);
+    if(result)
+      goto done;
+  }
+  Curl_dyn_reset(&out);
 
   /* Public Key Algorithm. */
-  ccp = dumpAlgo(¶m, cert.subjectPublicKeyAlgorithm.beg,
-                 cert.subjectPublicKeyAlgorithm.end);
-  if(!ccp)
-    return CURLE_OUT_OF_MEMORY;
-  if(data->set.ssl.certinfo)
-    result = ssl_push_certinfo(data, certnum, "Public Key Algorithm",
-                                    ccp);
-  if(!result) {
-    int ret;
-    if(!certnum)
-      infof(data, "   Public Key Algorithm: %s", ccp);
-    ret = do_pubkey(data, certnum, ccp, ¶m, &cert.subjectPublicKey);
-    if(ret)
-      result = CURLE_OUT_OF_MEMORY; /* the most likely error */
-  }
-  free((char *) ccp);
+  result = dumpAlgo(&out, ¶m, cert.subjectPublicKeyAlgorithm.beg,
+                    cert.subjectPublicKeyAlgorithm.end);
   if(result)
-    return result;
+    goto done;
+  if(data->set.ssl.certinfo) {
+    result = ssl_push_certinfo_dyn(data, certnum, "Public Key Algorithm",
+                                   &out);
+    if(result)
+      goto done;
+  }
+
+  rc = do_pubkey(data, certnum, Curl_dyn_ptr(&out),
+                 ¶m, &cert.subjectPublicKey);
+  if(rc) {
+    result = CURLE_OUT_OF_MEMORY; /* the most likely error */
+    goto done;
+  }
+  Curl_dyn_reset(&out);
 
   /* Signature. */
-  ccp = ASN1tostr(&cert.signature, 0);
-  if(!ccp)
-    return CURLE_OUT_OF_MEMORY;
-  if(data->set.ssl.certinfo)
-    result = ssl_push_certinfo(data, certnum, "Signature", ccp);
-  if(!certnum)
-    infof(data, "   Signature: %s", ccp);
-  free((char *) ccp);
+  result = ASN1tostr(&out, &cert.signature, 0);
   if(result)
-    return result;
+    goto done;
+  if(data->set.ssl.certinfo) {
+    result = ssl_push_certinfo_dyn(data, certnum, "Signature", &out);
+    if(result)
+      goto done;
+  }
+  Curl_dyn_reset(&out);
 
   /* Generate PEM certificate. */
   result = Curl_base64_encode(cert.certificate.beg,
                               cert.certificate.end - cert.certificate.beg,
-                              &cp1, &cl1);
+                              &certptr, &clen);
   if(result)
-    return result;
-  /* Compute the number of characters in final certificate string. Format is:
+    goto done;
+
+  /* Generate the final output certificate string. Format is:
      -----BEGIN CERTIFICATE-----\n
      \n
      .
@@ -1232,207 +1199,34 @@ CURLcode Curl_extract_certinfo(struct Curl_easy *data,
      .
      -----END CERTIFICATE-----\n
    */
-  i = 28 + cl1 + (cl1 + 64 - 1) / 64 + 26;
-  cp2 = malloc(i + 1);
-  if(!cp2) {
-    free(cp1);
-    return CURLE_OUT_OF_MEMORY;
-  }
-  /* Build the certificate string. */
-  i = copySubstring(cp2, "-----BEGIN CERTIFICATE-----");
-  for(j = 0; j < cl1; j += 64)
-    i += copySubstring(cp2 + i, cp1 + j);
-  i += copySubstring(cp2 + i, "-----END CERTIFICATE-----");
-  cp2[i] = '\0';
-  free(cp1);
-  if(data->set.ssl.certinfo)
-    result = ssl_push_certinfo(data, certnum, "Cert", cp2);
-  if(!certnum)
-    infof(data, "%s", cp2);
-  free(cp2);
-  return result;
-}
 
-#endif /* WANT_EXTRACT_CERTINFO */
-
-#endif /* USE_GNUTLS or USE_WOLFSSL or USE_SCHANNEL or USE_SECTRANSP */
+  Curl_dyn_reset(&out);
 
-#ifdef WANT_VERIFYHOST
-
-static const char *checkOID(const char *beg, const char *end,
-                            const char *oid)
-{
-  struct Curl_asn1Element e;
-  const char *ccp;
-  const char *p;
-  bool matched;
-
-  /* Check if first ASN.1 element at `beg' is the given OID.
-     Return a pointer in the source after the OID if found, else NULL. */
-
-  ccp = getASN1Element(&e, beg, end);
-  if(!ccp || e.tag != CURL_ASN1_OBJECT_IDENTIFIER)
-    return NULL;
-
-  p = OID2str(e.beg, e.end, FALSE);
-  if(!p)
-    return NULL;
-
-  matched = !strcmp(p, oid);
-  free((char *) p);
-  return matched? ccp: NULL;
-}
-
-CURLcode Curl_verifyhost(struct Curl_cfilter *cf,
-                         struct Curl_easy *data,
-                         const char *beg, const char *end)
-{
-  struct ssl_connect_data *connssl = cf->ctx;
-  struct ssl_primary_config *conn_config = Curl_ssl_cf_get_primary_config(cf);
-  struct Curl_X509certificate cert;
-  struct Curl_asn1Element dn;
-  struct Curl_asn1Element elem;
-  struct Curl_asn1Element ext;
-  struct Curl_asn1Element name;
-  const char *p;
-  const char *q;
-  char *dnsname;
-  int matched = -1;
-  size_t addrlen = (size_t) -1;
-  ssize_t len;
-  size_t hostlen;
-
-#ifdef ENABLE_IPV6
-  struct in6_addr addr;
-#else
-  struct in_addr addr;
-#endif
-
-  /* Verify that connection server matches info in X509 certificate at
-     `beg'..`end'. */
-
-  if(!conn_config->verifyhost)
-    return CURLE_OK;
-
-  if(Curl_parseX509(&cert, beg, end))
-    return CURLE_PEER_FAILED_VERIFICATION;
-
-  hostlen = strlen(connssl->hostname);
-
-  /* Get the server IP address. */
-#ifdef ENABLE_IPV6
-  if(cf->conn->bits.ipv6_ip &&
-     Curl_inet_pton(AF_INET6, connssl->hostname, &addr))
-    addrlen = sizeof(struct in6_addr);
-  else
-#endif
-  if(Curl_inet_pton(AF_INET, connssl->hostname, &addr))
-    addrlen = sizeof(struct in_addr);
-
-  /* Process extensions. */
-  for(p = cert.extensions.beg; p < cert.extensions.end && matched != 1;) {
-    p = getASN1Element(&ext, p, cert.extensions.end);
-    if(!p)
-      return CURLE_PEER_FAILED_VERIFICATION;
-
-    /* Check if extension is a subjectAlternativeName. */
-    ext.beg = checkOID(ext.beg, ext.end, sanOID);
-    if(ext.beg) {
-      ext.beg = getASN1Element(&elem, ext.beg, ext.end);
-      if(!ext.beg)
-        return CURLE_PEER_FAILED_VERIFICATION;
-      /* Skip critical if present. */
-      if(elem.tag == CURL_ASN1_BOOLEAN) {
-        ext.beg = getASN1Element(&elem, ext.beg, ext.end);
-        if(!ext.beg)
-          return CURLE_PEER_FAILED_VERIFICATION;
-      }
-      /* Parse the octet string contents: is a single sequence. */
-      if(!getASN1Element(&elem, elem.beg, elem.end))
-        return CURLE_PEER_FAILED_VERIFICATION;
-      /* Check all GeneralNames. */
-      for(q = elem.beg; matched != 1 && q < elem.end;) {
-        q = getASN1Element(&name, q, elem.end);
-        if(!q)
-          break;
-        switch(name.tag) {
-        case 2: /* DNS name. */
-          len = utf8asn1str(&dnsname, CURL_ASN1_IA5_STRING,
-                            name.beg, name.end);
-          if(len > 0 && (size_t)len == strlen(dnsname))
-            matched = Curl_cert_hostcheck(dnsname, (size_t)len,
-                                          connssl->hostname, hostlen);
-          else
-            matched = 0;
-          free(dnsname);
-          break;
-
-        case 7: /* IP address. */
-          matched = (size_t)(name.end - name.beg) == addrlen &&
-            !memcmp(&addr, name.beg, addrlen);
-          break;
-        }
-      }
-    }
-  }
-
-  switch(matched) {
-  case 1:
-    /* an alternative name matched the server hostname */
-    infof(data, "  subjectAltName: %s matched", connssl->dispname);
-    return CURLE_OK;
-  case 0:
-    /* an alternative name field existed, but didn't match and then
-       we MUST fail */
-    infof(data, "  subjectAltName does not match %s", connssl->dispname);
-    return CURLE_PEER_FAILED_VERIFICATION;
-  }
-
-  /* Process subject. */
-  name.header = NULL;
-  name.beg = name.end = "";
-  q = cert.subject.beg;
-  /* we have to look to the last occurrence of a commonName in the
-     distinguished one to get the most significant one. */
-  while(q < cert.subject.end) {
-    q = getASN1Element(&dn, q, cert.subject.end);
-    if(!q)
-      break;
-    for(p = dn.beg; p < dn.end;) {
-      p = getASN1Element(&elem, p, dn.end);
-      if(!p)
-        return CURLE_PEER_FAILED_VERIFICATION;
-      /* We have a DN's AttributeTypeAndValue: check it in case it's a CN. */
-      elem.beg = checkOID(elem.beg, elem.end, cnOID);
-      if(elem.beg)
-        name = elem;    /* Latch CN. */
-    }
-  }
-
-  /* Check the CN if found. */
-  if(!getASN1Element(&elem, name.beg, name.end))
-    failf(data, "SSL: unable to obtain common name from peer certificate");
-  else {
-    len = utf8asn1str(&dnsname, elem.tag, elem.beg, elem.end);
-    if(len < 0) {
-      free(dnsname);
-      return CURLE_OUT_OF_MEMORY;
-    }
-    if(strlen(dnsname) != (size_t) len)         /* Nul byte in string ? */
-      failf(data, "SSL: illegal cert name field");
-    else if(Curl_cert_hostcheck((const char *) dnsname,
-                                len, connssl->hostname, hostlen)) {
-      infof(data, "  common name: %s (matched)", dnsname);
-      free(dnsname);
-      return CURLE_OK;
+  /* Build the certificate string. */
+  result = Curl_dyn_add(&out, "-----BEGIN CERTIFICATE-----\n");
+  if(!result) {
+    size_t j = 0;
+
+    while(!result && (j < clen)) {
+      size_t chunksize = (clen - j) > 64 ? 64 : (clen - j);
+      result = Curl_dyn_addn(&out, &certptr[j], chunksize);
+      if(!result)
+        result = Curl_dyn_addn(&out, "\n", 1);
+      j += chunksize;
     }
-    else
-      failf(data, "SSL: certificate subject name '%s' does not match "
-            "target host name '%s'", dnsname, connssl->dispname);
-    free(dnsname);
+    if(!result)
+      result = Curl_dyn_add(&out, "-----END CERTIFICATE-----\n");
   }
+  free(certptr);
+  if(!result)
+    if(data->set.ssl.certinfo)
+      result = ssl_push_certinfo_dyn(data, certnum, "Cert", &out);
 
-  return CURLE_PEER_FAILED_VERIFICATION;
+done:
+  Curl_dyn_free(&out);
+  return result;
 }
 
-#endif /* WANT_VERIFYHOST */
+#endif /* WANT_EXTRACT_CERTINFO */
+
+#endif /* USE_GNUTLS or USE_WOLFSSL or USE_SCHANNEL or USE_SECTRANSP */
diff --git a/vendor/curl/lib/warnless.c b/vendor/curl/lib/warnless.c
index 65c5ec5354..c80937b843 100644
--- a/vendor/curl/lib/warnless.c
+++ b/vendor/curl/lib/warnless.c
@@ -37,7 +37,7 @@
 
 #include "warnless.h"
 
-#ifdef WIN32
+#ifdef _WIN32
 #undef read
 #undef write
 #endif
@@ -367,7 +367,7 @@ curl_socket_t curlx_sitosk(int i)
 
 #endif /* USE_WINSOCK */
 
-#if defined(WIN32)
+#if defined(_WIN32)
 
 ssize_t curlx_read(int fd, void *buf, size_t count)
 {
@@ -379,59 +379,8 @@ ssize_t curlx_write(int fd, const void *buf, size_t count)
   return (ssize_t)write(fd, buf, curlx_uztoui(count));
 }
 
-/* Ensure that warnless.h continues to have an effect in "unity" builds. */
-#undef HEADER_CURL_WARNLESS_H
+#endif /* _WIN32 */
 
-#endif /* WIN32 */
-
-#if defined(__INTEL_COMPILER) && defined(__unix__)
-
-int curlx_FD_ISSET(int fd, fd_set *fdset)
-{
-  #pragma warning(push)
-  #pragma warning(disable:1469) /* clobber ignored */
-  return FD_ISSET(fd, fdset);
-  #pragma warning(pop)
-}
-
-void curlx_FD_SET(int fd, fd_set *fdset)
-{
-  #pragma warning(push)
-  #pragma warning(disable:1469) /* clobber ignored */
-  FD_SET(fd, fdset);
-  #pragma warning(pop)
-}
-
-void curlx_FD_ZERO(fd_set *fdset)
-{
-  #pragma warning(push)
-  #pragma warning(disable:593) /* variable was set but never used */
-  FD_ZERO(fdset);
-  #pragma warning(pop)
-}
-
-unsigned short curlx_htons(unsigned short usnum)
-{
-#if (__INTEL_COMPILER == 910) && defined(__i386__)
-  return (unsigned short)(((usnum << 8) & 0xFF00) | ((usnum >> 8) & 0x00FF));
-#else
-  #pragma warning(push)
-  #pragma warning(disable:810) /* conversion may lose significant bits */
-  return htons(usnum);
-  #pragma warning(pop)
-#endif
-}
-
-unsigned short curlx_ntohs(unsigned short usnum)
-{
-#if (__INTEL_COMPILER == 910) && defined(__i386__)
-  return (unsigned short)(((usnum << 8) & 0xFF00) | ((usnum >> 8) & 0x00FF));
-#else
-  #pragma warning(push)
-  #pragma warning(disable:810) /* conversion may lose significant bits */
-  return ntohs(usnum);
-  #pragma warning(pop)
-#endif
-}
-
-#endif /* __INTEL_COMPILER && __unix__ */
+/* Ensure that warnless.h redefinitions continue to have an effect
+   in "unity" builds. */
+#undef HEADER_CURL_WARNLESS_H_REDEFS
diff --git a/vendor/curl/lib/warnless.h b/vendor/curl/lib/warnless.h
index 2a5301628f..6adf63a793 100644
--- a/vendor/curl/lib/warnless.h
+++ b/vendor/curl/lib/warnless.h
@@ -69,31 +69,24 @@ curl_socket_t curlx_sitosk(int i);
 
 #endif /* USE_WINSOCK */
 
-#if defined(WIN32)
+#if defined(_WIN32)
 
 ssize_t curlx_read(int fd, void *buf, size_t count);
 
 ssize_t curlx_write(int fd, const void *buf, size_t count);
 
+#endif /* _WIN32 */
+
+#endif /* HEADER_CURL_WARNLESS_H */
+
+#ifndef HEADER_CURL_WARNLESS_H_REDEFS
+#define HEADER_CURL_WARNLESS_H_REDEFS
+
+#if defined(_WIN32)
 #undef  read
 #define read(fd, buf, count)  curlx_read(fd, buf, count)
 #undef  write
 #define write(fd, buf, count) curlx_write(fd, buf, count)
+#endif
 
-#endif /* WIN32 */
-
-#if defined(__INTEL_COMPILER) && defined(__unix__)
-
-int curlx_FD_ISSET(int fd, fd_set *fdset);
-
-void curlx_FD_SET(int fd, fd_set *fdset);
-
-void curlx_FD_ZERO(fd_set *fdset);
-
-unsigned short curlx_htons(unsigned short usnum);
-
-unsigned short curlx_ntohs(unsigned short usnum);
-
-#endif /* __INTEL_COMPILER && __unix__ */
-
-#endif /* HEADER_CURL_WARNLESS_H */
+#endif /* HEADER_CURL_WARNLESS_H_REDEFS */
diff --git a/vendor/curl/lib/ws.c b/vendor/curl/lib/ws.c
index 3c1964b860..6ccf9e65fd 100644
--- a/vendor/curl/lib/ws.c
+++ b/vendor/curl/lib/ws.c
@@ -24,7 +24,7 @@
 #include "curl_setup.h"
 #include 
 
-#ifdef USE_WEBSOCKETS
+#if defined(USE_WEBSOCKETS) && !defined(CURL_DISABLE_HTTP)
 
 #include "urldata.h"
 #include "bufq.h"
@@ -114,23 +114,23 @@ static void ws_dec_info(struct ws_decoder *dec, struct Curl_easy *data,
   case 0:
     break;
   case 1:
-    infof(data, "WS-DEC: %s [%s%s]", msg,
-          ws_frame_name_of_op(dec->head[0]),
-          (dec->head[0] & WSBIT_FIN)? "" : " NON-FINAL");
+    CURL_TRC_WRITE(data, "websocket, decoded %s [%s%s]", msg,
+                   ws_frame_name_of_op(dec->head[0]),
+                   (dec->head[0] & WSBIT_FIN)? "" : " NON-FINAL");
     break;
   default:
     if(dec->head_len < dec->head_total) {
-      infof(data, "WS-DEC: %s [%s%s](%d/%d)", msg,
-            ws_frame_name_of_op(dec->head[0]),
-            (dec->head[0] & WSBIT_FIN)? "" : " NON-FINAL",
-            dec->head_len, dec->head_total);
+      CURL_TRC_WRITE(data, "websocket, decoded %s [%s%s](%d/%d)", msg,
+                     ws_frame_name_of_op(dec->head[0]),
+                     (dec->head[0] & WSBIT_FIN)? "" : " NON-FINAL",
+                     dec->head_len, dec->head_total);
     }
     else {
-      infof(data, "WS-DEC: %s [%s%s payload=%" CURL_FORMAT_CURL_OFF_T
-                  "/%" CURL_FORMAT_CURL_OFF_T "]",
-            msg, ws_frame_name_of_op(dec->head[0]),
-            (dec->head[0] & WSBIT_FIN)? "" : " NON-FINAL",
-            dec->payload_offset, dec->payload_len);
+      CURL_TRC_WRITE(data, "websocket, decoded %s [%s%s payload=%"
+                     CURL_FORMAT_CURL_OFF_T "/%" CURL_FORMAT_CURL_OFF_T "]",
+                     msg, ws_frame_name_of_op(dec->head[0]),
+                     (dec->head[0] & WSBIT_FIN)? "" : " NON-FINAL",
+                     dec->payload_offset, dec->payload_len);
     }
     break;
   }
@@ -225,6 +225,10 @@ static CURLcode ws_dec_read_head(struct ws_decoder *dec,
       dec->payload_len = (dec->head[2] << 8) | dec->head[3];
       break;
     case 10:
+      if(dec->head[2] > 127) {
+        failf(data, "WS: frame length longer than 64 signed not supported");
+        return CURLE_RECV_ERROR;
+      }
       dec->payload_len = ((curl_off_t)dec->head[2] << 56) |
         (curl_off_t)dec->head[3] << 48 |
         (curl_off_t)dec->head[4] << 40 |
@@ -273,9 +277,8 @@ static CURLcode ws_dec_pass_payload(struct ws_decoder *dec,
     Curl_bufq_skip(inraw, (size_t)nwritten);
     dec->payload_offset += (curl_off_t)nwritten;
     remain = dec->payload_len - dec->payload_offset;
-    /* infof(data, "WS-DEC: passed  %zd bytes payload, %"
-                CURL_FORMAT_CURL_OFF_T " remain",
-          nwritten, remain); */
+    CURL_TRC_WRITE(data, "websocket, passed %zd bytes payload, %"
+                   CURL_FORMAT_CURL_OFF_T " remain", nwritten, remain);
   }
 
   return remain? CURLE_AGAIN : CURLE_OK;
@@ -296,7 +299,7 @@ static CURLcode ws_dec_pass(struct ws_decoder *dec,
   case WS_DEC_INIT:
     ws_dec_reset(dec);
     dec->state = WS_DEC_HEAD;
-    /* FALLTHROUGH */
+    FALLTHROUGH();
   case WS_DEC_HEAD:
     result = ws_dec_read_head(dec, data, inraw);
     if(result) {
@@ -321,7 +324,7 @@ static CURLcode ws_dec_pass(struct ws_decoder *dec,
       dec->state = WS_DEC_INIT;
       break;
     }
-    /* FALLTHROUGH */
+    FALLTHROUGH();
   case WS_DEC_PAYLOAD:
     result = ws_dec_pass_payload(dec, data, inraw, write_payload, write_ctx);
     ws_dec_info(dec, data, "passing");
@@ -350,6 +353,138 @@ static void update_meta(struct websocket *ws,
   ws->frame.bytesleft = (payload_len - payload_offset - cur_len);
 }
 
+/* WebSockets decoding client writer */
+struct ws_cw_ctx {
+  struct Curl_cwriter super;
+  struct bufq buf;
+};
+
+static CURLcode ws_cw_init(struct Curl_easy *data,
+                           struct Curl_cwriter *writer)
+{
+  struct ws_cw_ctx *ctx = writer->ctx;
+  (void)data;
+  Curl_bufq_init2(&ctx->buf, WS_CHUNK_SIZE, 1, BUFQ_OPT_SOFT_LIMIT);
+  return CURLE_OK;
+}
+
+static void ws_cw_close(struct Curl_easy *data, struct Curl_cwriter *writer)
+{
+  struct ws_cw_ctx *ctx = writer->ctx;
+  (void) data;
+  Curl_bufq_free(&ctx->buf);
+}
+
+struct ws_cw_dec_ctx {
+  struct Curl_easy *data;
+  struct websocket *ws;
+  struct Curl_cwriter *next_writer;
+  int cw_type;
+};
+
+static ssize_t ws_cw_dec_next(const unsigned char *buf, size_t buflen,
+                              int frame_age, int frame_flags,
+                              curl_off_t payload_offset,
+                              curl_off_t payload_len,
+                              void *user_data,
+                              CURLcode *err)
+{
+  struct ws_cw_dec_ctx *ctx = user_data;
+  struct Curl_easy *data = ctx->data;
+  struct websocket *ws = ctx->ws;
+  curl_off_t remain = (payload_len - (payload_offset + buflen));
+
+  (void)frame_age;
+  if((frame_flags & CURLWS_PING) && !remain) {
+    /* auto-respond to PINGs, only works for single-frame payloads atm */
+    size_t bytes;
+    infof(data, "WS: auto-respond to PING with a PONG");
+    /* send back the exact same content as a PONG */
+    *err = curl_ws_send(data, buf, buflen, &bytes, 0, CURLWS_PONG);
+    if(*err)
+      return -1;
+  }
+  else if(buflen || !remain) {
+    /* forward the decoded frame to the next client writer. */
+    update_meta(ws, frame_age, frame_flags, payload_offset,
+                payload_len, buflen);
+
+    *err = Curl_cwriter_write(data, ctx->next_writer, ctx->cw_type,
+                              (const char *)buf, buflen);
+    if(*err)
+      return -1;
+  }
+  *err = CURLE_OK;
+  return (ssize_t)buflen;
+}
+
+static CURLcode ws_cw_write(struct Curl_easy *data,
+                            struct Curl_cwriter *writer, int type,
+                            const char *buf, size_t nbytes)
+{
+  struct ws_cw_ctx *ctx = writer->ctx;
+  struct websocket *ws;
+  CURLcode result;
+
+  if(!(type & CLIENTWRITE_BODY) || data->set.ws_raw_mode)
+    return Curl_cwriter_write(data, writer->next, type, buf, nbytes);
+
+  ws = data->conn->proto.ws;
+  if(!ws) {
+    failf(data, "WS: not a websocket transfer");
+    return CURLE_FAILED_INIT;
+  }
+
+  if(nbytes) {
+    ssize_t nwritten;
+    nwritten = Curl_bufq_write(&ctx->buf, (const unsigned char *)buf,
+                               nbytes, &result);
+    if(nwritten < 0) {
+      infof(data, "WS: error adding data to buffer %d", result);
+      return result;
+    }
+  }
+
+  while(!Curl_bufq_is_empty(&ctx->buf)) {
+    struct ws_cw_dec_ctx pass_ctx;
+    pass_ctx.data = data;
+    pass_ctx.ws = ws;
+    pass_ctx.next_writer = writer->next;
+    pass_ctx.cw_type = type;
+    result = ws_dec_pass(&ws->dec, data, &ctx->buf,
+                         ws_cw_dec_next, &pass_ctx);
+    if(result == CURLE_AGAIN) {
+      /* insufficient amount of data, keep it for later.
+       * we pretend to have written all since we have a copy */
+      CURL_TRC_WRITE(data, "websocket, buffered incomplete frame head");
+      return CURLE_OK;
+    }
+    else if(result) {
+      infof(data, "WS: decode error %d", (int)result);
+      return result;
+    }
+  }
+
+  if((type & CLIENTWRITE_EOS) && !Curl_bufq_is_empty(&ctx->buf)) {
+    infof(data, "WS: decode ending with %zd frame bytes remaining",
+          Curl_bufq_len(&ctx->buf));
+    return CURLE_RECV_ERROR;
+  }
+
+  return CURLE_OK;
+}
+
+/* WebSocket payload decoding client writer. */
+static const struct Curl_cwtype ws_cw_decode = {
+  "ws-decode",
+  NULL,
+  ws_cw_init,
+  ws_cw_write,
+  ws_cw_close,
+  sizeof(struct ws_cw_ctx)
+};
+
+
 static void ws_enc_info(struct ws_encoder *enc, struct Curl_easy *data,
                         const char *msg)
 {
@@ -410,6 +545,13 @@ static ssize_t ws_enc_write_head(struct Curl_easy *data,
   size_t hlen;
   ssize_t n;
 
+  if(payload_len < 0) {
+    failf(data, "WS: starting new frame with negative payload length %"
+                CURL_FORMAT_CURL_OFF_T, payload_len);
+    *err = CURLE_SEND_ERROR;
+    return -1;
+  }
+
   if(enc->payload_remain > 0) {
     /* trying to write a new frame before the previous one is finished */
     failf(data, "WS: starting new frame with %zd bytes from last one"
@@ -576,8 +718,10 @@ CURLcode Curl_ws_request(struct Curl_easy *data, REQTYPE *req)
   if(result)
     return result;
   DEBUGASSERT(randlen < sizeof(keyval));
-  if(randlen >= sizeof(keyval))
+  if(randlen >= sizeof(keyval)) {
+    free(randstr);
     return CURLE_FAILED_INIT;
+  }
   strcpy(keyval, randstr);
   free(randstr);
   for(i = 0; !result && (i < sizeof(heads)/sizeof(heads[0])); i++) {
@@ -607,17 +751,32 @@ CURLcode Curl_ws_accept(struct Curl_easy *data,
 {
   struct SingleRequest *k = &data->req;
   struct websocket *ws;
+  struct Curl_cwriter *ws_dec_writer;
   CURLcode result;
 
   DEBUGASSERT(data->conn);
   ws = data->conn->proto.ws;
   if(!ws) {
+    size_t chunk_size = WS_CHUNK_SIZE;
     ws = calloc(1, sizeof(*ws));
     if(!ws)
       return CURLE_OUT_OF_MEMORY;
     data->conn->proto.ws = ws;
-    Curl_bufq_init(&ws->recvbuf, WS_CHUNK_SIZE, WS_CHUNK_COUNT);
-    Curl_bufq_init2(&ws->sendbuf, WS_CHUNK_SIZE, WS_CHUNK_COUNT,
+#ifdef DEBUGBUILD
+    {
+      char *p = getenv("CURL_WS_CHUNK_SIZE");
+      if(p) {
+        long l = strtol(p, NULL, 10);
+        if(l > 0 && l <= (1*1024*1024)) {
+          chunk_size = (size_t)l;
+        }
+      }
+    }
+#endif
+    DEBUGF(infof(data, "WS, using chunk size %zu", chunk_size));
+    Curl_bufq_init2(&ws->recvbuf, chunk_size, WS_CHUNK_COUNT,
+                    BUFQ_OPT_SOFT_LIMIT);
+    Curl_bufq_init2(&ws->sendbuf, chunk_size, WS_CHUNK_COUNT,
                     BUFQ_OPT_SOFT_LIMIT);
     ws_dec_init(&ws->dec);
     ws_enc_init(&ws->enc);
@@ -655,6 +814,18 @@ CURLcode Curl_ws_accept(struct Curl_easy *data,
   infof(data, "Received 101, switch to WebSocket; mask %02x%02x%02x%02x",
         ws->enc.mask[0], ws->enc.mask[1], ws->enc.mask[2], ws->enc.mask[3]);
 
+  /* Install our client writer that decodes WS frames payload */
+  result = Curl_cwriter_create(&ws_dec_writer, data, &ws_cw_decode,
+                               CURL_CW_CONTENT_DECODE);
+  if(result)
+    return result;
+
+  result = Curl_cwriter_add(data, ws_dec_writer);
+  if(result) {
+    Curl_cwriter_free(data, ws_dec_writer);
+    return result;
+  }
+
   if(data->set.connect_only) {
     ssize_t nwritten;
     /* In CONNECT_ONLY setup, the payloads from `mem` need to be received
@@ -666,110 +837,20 @@ CURLcode Curl_ws_accept(struct Curl_easy *data,
       return result;
     infof(data, "%zu bytes websocket payload", nread);
   }
-  k->upgr101 = UPGR101_RECEIVED;
-
-  return result;
-}
-
-static ssize_t ws_client_write(const unsigned char *buf, size_t buflen,
-                               int frame_age, int frame_flags,
-                               curl_off_t payload_offset,
-                               curl_off_t payload_len,
-                               void *userp,
-                               CURLcode *err)
-{
-  struct Curl_easy *data = userp;
-  struct websocket *ws;
-  size_t wrote;
-  curl_off_t remain = (payload_len - (payload_offset + buflen));
-
-  (void)frame_age;
-  if(!data->conn || !data->conn->proto.ws) {
-    *err = CURLE_FAILED_INIT;
-    return -1;
-  }
-  ws = data->conn->proto.ws;
-
-  if((frame_flags & CURLWS_PING) && !remain) {
-    /* auto-respond to PINGs, only works for single-frame payloads atm */
-    size_t bytes;
-    infof(data, "WS: auto-respond to PING with a PONG");
-    /* send back the exact same content as a PONG */
-    *err = curl_ws_send(data, buf, buflen, &bytes, 0, CURLWS_PONG);
-    if(*err)
-      return -1;
-  }
-  else if(buflen || !remain) {
-    /* deliver the decoded frame to the user callback. The application
-     * may invoke curl_ws_meta() to access frame information. */
-    update_meta(ws, frame_age, frame_flags, payload_offset,
-                payload_len, buflen);
-    Curl_set_in_callback(data, true);
-    wrote = data->set.fwrite_func((char *)buf, 1,
-                                  buflen, data->set.out);
-    Curl_set_in_callback(data, false);
-    if(wrote != buflen) {
-      *err = CURLE_RECV_ERROR;
-      return -1;
+  else { /* !connect_only */
+    /* And pass any additional data to the writers */
+    if(nread) {
+      result = Curl_client_write(data, CLIENTWRITE_BODY, (char *)mem, nread);
     }
   }
-  *err = CURLE_OK;
-  return (ssize_t)buflen;
-}
-
-/* Curl_ws_writecb() is the write callback for websocket traffic. The
-   websocket data is provided to this raw, in chunks. This function should
-   handle/decode the data and call the "real" underlying callback accordingly.
-*/
-size_t Curl_ws_writecb(char *buffer, size_t size /* 1 */,
-                       size_t nitems, void *userp)
-{
-  struct Curl_easy *data = userp;
-
-  if(data->set.ws_raw_mode)
-    return data->set.fwrite_func(buffer, size, nitems, data->set.out);
-  else if(nitems) {
-    struct websocket *ws;
-    CURLcode result;
-
-    if(!data->conn || !data->conn->proto.ws) {
-      failf(data, "WS: not a websocket transfer");
-      return nitems - 1;
-    }
-    ws = data->conn->proto.ws;
-
-    if(buffer) {
-      ssize_t nwritten;
-
-      nwritten = Curl_bufq_write(&ws->recvbuf, (const unsigned char *)buffer,
-                                 nitems, &result);
-      if(nwritten < 0) {
-        infof(data, "WS: error adding data to buffer %d", (int)result);
-        return nitems - 1;
-      }
-      buffer = NULL;
-    }
-
-    while(!Curl_bufq_is_empty(&ws->recvbuf)) {
+  k->upgr101 = UPGR101_RECEIVED;
 
-      result = ws_dec_pass(&ws->dec, data, &ws->recvbuf,
-                           ws_client_write, data);
-      if(result == CURLE_AGAIN)
-        /* insufficient amount of data, keep it for later.
-         * we pretend to have written all since we have a copy */
-        return nitems;
-      else if(result) {
-        infof(data, "WS: decode error %d", (int)result);
-        return nitems - 1;
-      }
-    }
-  }
-  return nitems;
+  return result;
 }
 
 struct ws_collect {
   struct Curl_easy *data;
-  void *buffer;
+  unsigned char *buffer;
   size_t buflen;
   size_t bufidx;
   int frame_age;
@@ -821,7 +902,7 @@ static ssize_t ws_client_collect(const unsigned char *buf, size_t buflen,
       return -1;
     }
     *err = CURLE_OK;
-    memcpy(ctx->buffer, buf, nwritten);
+    memcpy(ctx->buffer + ctx->bufidx, buf, nwritten);
     ctx->bufidx += nwritten;
   }
   return nwritten;
@@ -871,10 +952,6 @@ CURL_EXTERN CURLcode curl_ws_recv(struct Curl_easy *data, void *buffer,
 
   *nread = 0;
   *metap = NULL;
-  /* get a download buffer */
-  result = Curl_preconnect(data);
-  if(result)
-    return result;
 
   memset(&ctx, 0, sizeof(ctx));
   ctx.data = data;
@@ -925,8 +1002,8 @@ CURL_EXTERN CURLcode curl_ws_recv(struct Curl_easy *data, void *buffer,
   *metap = &ws->frame;
   *nread = ws->frame.len;
   /* infof(data, "curl_ws_recv(len=%zu) -> %zu bytes (frame at %"
-              CURL_FORMAT_CURL_OFF_T ", %" CURL_FORMAT_CURL_OFF_T " left)",
-        buflen, *nread, ws->frame.offset, ws->frame.bytesleft); */
+           CURL_FORMAT_CURL_OFF_T ", %" CURL_FORMAT_CURL_OFF_T " left)",
+           buflen, *nread, ws->frame.offset, ws->frame.bytesleft); */
   return CURLE_OK;
 }
 
@@ -936,14 +1013,17 @@ static CURLcode ws_flush(struct Curl_easy *data, struct websocket *ws,
   if(!Curl_bufq_is_empty(&ws->sendbuf)) {
     CURLcode result;
     const unsigned char *out;
-    size_t outlen;
-    ssize_t n;
+    size_t outlen, n;
 
     while(Curl_bufq_peek(&ws->sendbuf, &out, &outlen)) {
       if(data->set.connect_only)
         result = Curl_senddata(data, out, outlen, &n);
-      else
-        result = Curl_write(data, data->conn->writesockfd, out, outlen, &n);
+      else {
+        result = Curl_xfer_send(data, out, outlen, &n);
+        if(!result && !n && outlen)
+          result = CURLE_AGAIN;
+      }
+
       if(result) {
         if(result == CURLE_AGAIN) {
           if(!complete) {
@@ -962,8 +1042,8 @@ static CURLcode ws_flush(struct Curl_easy *data, struct websocket *ws,
         }
       }
       else {
-        infof(data, "WS: flushed %zu bytes", (size_t)n);
-        Curl_bufq_skip(&ws->sendbuf, (size_t)n);
+        infof(data, "WS: flushed %zu bytes", n);
+        Curl_bufq_skip(&ws->sendbuf, n);
       }
     }
   }
@@ -976,8 +1056,8 @@ CURL_EXTERN CURLcode curl_ws_send(CURL *data, const void *buffer,
                                   unsigned int flags)
 {
   struct websocket *ws;
-  ssize_t nwritten, n;
-  size_t space;
+  ssize_t n;
+  size_t nwritten, space;
   CURLcode result;
 
   *sent = 0;
@@ -997,23 +1077,25 @@ CURL_EXTERN CURLcode curl_ws_send(CURL *data, const void *buffer,
   ws = data->conn->proto.ws;
 
   if(data->set.ws_raw_mode) {
-    if(fragsize || flags)
+    if(fragsize || flags) {
+      DEBUGF(infof(data, "ws_send: "
+                   "fragsize and flags cannot be non-zero in raw mode"));
       return CURLE_BAD_FUNCTION_ARGUMENT;
+    }
     if(!buflen)
       /* nothing to do */
       return CURLE_OK;
     /* raw mode sends exactly what was requested, and this is from within
        the write callback */
     if(Curl_is_in_callback(data)) {
-      result = Curl_write(data, data->conn->writesockfd, buffer, buflen,
-                          &nwritten);
+      result = Curl_xfer_send(data, buffer, buflen, &nwritten);
     }
     else
       result = Curl_senddata(data, buffer, buflen, &nwritten);
 
     infof(data, "WS: wanted to send %zu bytes, sent %zu bytes",
           buflen, nwritten);
-    *sent = (nwritten >= 0)? (size_t)nwritten : 0;
+    *sent = nwritten;
     return result;
   }
 
@@ -1023,7 +1105,7 @@ CURL_EXTERN CURLcode curl_ws_send(CURL *data, const void *buffer,
     return result;
 
   /* TODO: the current design does not allow partial writes, afaict.
-   * It is not clear who the application is supposed to react. */
+   * It is not clear how the application is supposed to react. */
   space = Curl_bufq_space(&ws->sendbuf);
   DEBUGF(infof(data, "curl_ws_send(len=%zu), sendbuf len=%zu space %zu",
                buflen, Curl_bufq_len(&ws->sendbuf), space));
@@ -1071,14 +1153,18 @@ static void ws_free(struct connectdata *conn)
   }
 }
 
-void Curl_ws_done(struct Curl_easy *data)
+static CURLcode ws_setup_conn(struct Curl_easy *data,
+                              struct connectdata *conn)
 {
-  (void)data;
+  /* websockets is 1.1 only (for now) */
+  data->state.httpwant = CURL_HTTP_VERSION_1_1;
+  return Curl_http_setup_conn(data, conn);
 }
 
-CURLcode Curl_ws_disconnect(struct Curl_easy *data,
-                            struct connectdata *conn,
-                            bool dead_connection)
+
+static CURLcode ws_disconnect(struct Curl_easy *data,
+                              struct connectdata *conn,
+                              bool dead_connection)
 {
   (void)data;
   (void)dead_connection;
@@ -1096,6 +1182,59 @@ CURL_EXTERN const struct curl_ws_frame *curl_ws_meta(struct Curl_easy *data)
   return NULL;
 }
 
+const struct Curl_handler Curl_handler_ws = {
+  "WS",                                 /* scheme */
+  ws_setup_conn,                        /* setup_connection */
+  Curl_http,                            /* do_it */
+  Curl_http_done,                       /* done */
+  ZERO_NULL,                            /* do_more */
+  Curl_http_connect,                    /* connect_it */
+  ZERO_NULL,                            /* connecting */
+  ZERO_NULL,                            /* doing */
+  ZERO_NULL,                            /* proto_getsock */
+  Curl_http_getsock_do,                 /* doing_getsock */
+  ZERO_NULL,                            /* domore_getsock */
+  ZERO_NULL,                            /* perform_getsock */
+  ws_disconnect,                        /* disconnect */
+  Curl_http_write_resp,                 /* write_resp */
+  Curl_http_write_resp_hd,              /* write_resp_hd */
+  ZERO_NULL,                            /* connection_check */
+  ZERO_NULL,                            /* attach connection */
+  PORT_HTTP,                            /* defport */
+  CURLPROTO_WS,                         /* protocol */
+  CURLPROTO_HTTP,                       /* family */
+  PROTOPT_CREDSPERREQUEST |             /* flags */
+  PROTOPT_USERPWDCTRL
+};
+
+#ifdef USE_SSL
+const struct Curl_handler Curl_handler_wss = {
+  "WSS",                                /* scheme */
+  ws_setup_conn,                        /* setup_connection */
+  Curl_http,                            /* do_it */
+  Curl_http_done,                       /* done */
+  ZERO_NULL,                            /* do_more */
+  Curl_http_connect,                    /* connect_it */
+  NULL,                                 /* connecting */
+  ZERO_NULL,                            /* doing */
+  NULL,                                 /* proto_getsock */
+  Curl_http_getsock_do,                 /* doing_getsock */
+  ZERO_NULL,                            /* domore_getsock */
+  ZERO_NULL,                            /* perform_getsock */
+  ws_disconnect,                        /* disconnect */
+  Curl_http_write_resp,                 /* write_resp */
+  Curl_http_write_resp_hd,              /* write_resp_hd */
+  ZERO_NULL,                            /* connection_check */
+  ZERO_NULL,                            /* attach connection */
+  PORT_HTTPS,                           /* defport */
+  CURLPROTO_WSS,                        /* protocol */
+  CURLPROTO_HTTP,                       /* family */
+  PROTOPT_SSL | PROTOPT_CREDSPERREQUEST | /* flags */
+  PROTOPT_USERPWDCTRL
+};
+#endif
+
+
 #else
 
 CURL_EXTERN CURLcode curl_ws_recv(CURL *curl, void *buffer, size_t buflen,
diff --git a/vendor/curl/lib/ws.h b/vendor/curl/lib/ws.h
index 0308a42545..baa77b4424 100644
--- a/vendor/curl/lib/ws.h
+++ b/vendor/curl/lib/ws.h
@@ -25,7 +25,7 @@
  ***************************************************************************/
 #include "curl_setup.h"
 
-#ifdef USE_WEBSOCKETS
+#if defined(USE_WEBSOCKETS) && !defined(CURL_DISABLE_HTTP)
 
 #ifdef USE_HYPER
 #define REQTYPE void
@@ -75,14 +75,15 @@ struct websocket {
 
 CURLcode Curl_ws_request(struct Curl_easy *data, REQTYPE *req);
 CURLcode Curl_ws_accept(struct Curl_easy *data, const char *mem, size_t len);
-size_t Curl_ws_writecb(char *buffer, size_t size, size_t nitems, void *userp);
-void Curl_ws_done(struct Curl_easy *data);
-CURLcode Curl_ws_disconnect(struct Curl_easy *data,
-                            struct connectdata *conn,
-                            bool dead_connection);
+
+extern const struct Curl_handler Curl_handler_ws;
+#ifdef USE_SSL
+extern const struct Curl_handler Curl_handler_wss;
+#endif
+
+
 #else
 #define Curl_ws_request(x,y) CURLE_OK
-#define Curl_ws_done(x) Curl_nop_stmt
 #define Curl_ws_free(x) Curl_nop_stmt
 #endif
 
diff --git a/vendor/discord-rpc/premake5.lua b/vendor/discord-rpc/premake5.lua
index dbe7e5776c..3ec2d53835 100644
--- a/vendor/discord-rpc/premake5.lua
+++ b/vendor/discord-rpc/premake5.lua
@@ -8,6 +8,10 @@ project "discord-rpc"
 		"discord/thirdparty/rapidjson/include"
 	}
 
+	defines {
+		"DISCORD_DISABLE_IO_THREAD"
+	}
+
 	files {
 		"premake5.lua",
 		"discord/src/discord_rpc.cpp",
diff --git a/vendor/ehs/ehs.cpp b/vendor/ehs/ehs.cpp
index cd498407e2..af03482975 100644
--- a/vendor/ehs/ehs.cpp
+++ b/vendor/ehs/ehs.cpp
@@ -1079,56 +1079,137 @@ void EHSServer::CheckClientSockets ( )
 } 
 
 
-const char * ResponsePhrase [] = { "INVALID", "OK", "Moved Permanently", "Found", "Unauthorized", "Forbidden", "Not Found", "Internal Server Error" };
-
-const char * GetResponsePhrase ( int inResponseCode ///< HTTP response code to get text version of
-)
+const char* GetHttpStatusReasonPhrase(int statusCode)
 {
-	const char * psReturn = NULL;
-	
-	switch ( inResponseCode ) {
-		
-	case HTTPRESPONSECODE_200_OK:
-		psReturn = ResponsePhrase [ 1 ];
-		break;
-		
-	case HTTPRESPONSECODE_301_MOVEDPERMANENTLY:
-		psReturn = ResponsePhrase [ 2 ];
-		break;
-		
-	case HTTPRESPONSECODE_302_FOUND:
-		psReturn = ResponsePhrase [ 3 ];
-		break;
-
-	case HTTPRESPONSECODE_401_UNAUTHORIZED:
-		psReturn = ResponsePhrase [ 4 ];
-		break;
+	if (statusCode >= 100 && statusCode <= 199)
+	{
+		switch (statusCode)
+		{
+			case HTTP_STATUS_CODE_100_CONTINUE:
+				return "Continue";
+			case HTTP_STATUS_CODE_101_SWITCHING_PROTOCOLS:
+				return "Switching Protocols";
+			default:
+				return "Informational";
+		}
+	}
 
-	case HTTPRESPONSECODE_403_FORBIDDEN:
-		psReturn = ResponsePhrase [ 5 ];
-		break;
+	if (statusCode >= 200 && statusCode <= 299)
+	{
+		switch (statusCode)
+		{
+			case HTTP_STATUS_CODE_200_OK:
+				return "OK";
+			case HTTP_STATUS_CODE_201_CREATED:
+				return "Created";
+			case HTTP_STATUS_CODE_202_ACCEPTED:
+				return "Accepted";
+			case HTTP_STATUS_CODE_203_NON_AUTHORITATIVE_INFO:
+				return "Non-Authoritative Information";
+			case HTTP_STATUS_CODE_204_NO_CONTENT:
+				return "No Content";
+			case HTTP_STATUS_CODE_205_RESET_CONTENT:
+				return "Reset Content";
+			case HTTP_STATUS_CODE_206_PARTIAL_CONTENT:
+				return "Partial Content";
+			default:
+				return "Success";
+		}
+	}
 
-	case HTTPRESPONSECODE_404_NOTFOUND:
-		psReturn = ResponsePhrase [ 6 ];
-		break;
+	if (statusCode >= 300 && statusCode <= 399)
+	{
+		switch (statusCode)
+		{
+			case HTTP_STATUS_CODE_300_MULTIPLE_CHOICES:
+				return "Multiple Choices";
+			case HTTP_STATUS_CODE_301_MOVED_PERMANENTLY:
+				return "Moved Permanently";
+			case HTTP_STATUS_CODE_302_FOUND:
+				return "Found";
+			case HTTP_STATUS_CODE_303_SEE_OTHER:
+				return "See Other";
+			case HTTP_STATUS_CODE_304_NOT_MODIFIED:
+				return "Not Modified";
+			case HTTP_STATUS_CODE_305_USE_PROXY:
+				return "Use Proxy";
+			case HTTP_STATUS_CODE_307_TEMPORARY_REDIRECT:
+				return "Temporary Redirect";
+			default:
+				return "Redirection";
+		}
+	}
 
-	case HTTPRESPONSECODE_500_INTERNALSERVERERROR:
-		psReturn = ResponsePhrase [ 7 ];
-		break;
-		
-	default:
-		assert ( 0 );
-		psReturn = ResponsePhrase [ 0 ];
-		break;
+	if (statusCode >= 400 && statusCode <= 499)
+	{
+		switch (statusCode)
+		{
+			case HTTP_STATUS_CODE_400_BAD_REQUEST:
+				return "Bad Request";
+			case HTTP_STATUS_CODE_401_UNAUTHORIZED:
+				return "Unauthorized";
+			case HTTP_STATUS_CODE_402_PAYMENT_REQUIRED:
+				return "Payment Required";
+			case HTTP_STATUS_CODE_403_FORBIDDEN:
+				return "Forbidden";
+			case HTTP_STATUS_CODE_404_NOT_FOUND:
+				return "Not Found";
+			case HTTP_STATUS_CODE_405_METHOD_NOT_ALLOWED:
+				return "Method Not Allowed";
+			case HTTP_STATUS_CODE_406_NOT_ACCEPTABLE:
+				return "Not Acceptable";
+			case HTTP_STATUS_CODE_407_PROXY_AUTH_REQUIRED:
+				return "Proxy Authentication Required";
+			case HTTP_STATUS_CODE_408_REQUEST_TIMEOUT:
+				return "Request Time-out";
+			case HTTP_STATUS_CODE_409_CONFLICT:
+				return "Conflict";
+			case HTTP_STATUS_CODE_410_GONE:
+				return "Gone";
+			case HTTP_STATUS_CODE_411_LENGTH_REQUIRED:
+				return "Length Required";
+			case HTTP_STATUS_CODE_412_PRECONDITION_FAILED:
+				return "Precondition Failed";
+			case HTTP_STATUS_CODE_413_REQUEST_ENTITY_TOO_LARGE:
+				return "Request Entity Too Large";
+			case HTTP_STATUS_CODE_414_URI_TOO_LARGE:
+				return "Request-URI Too Large";
+			case HTTP_STATUS_CODE_415_UNSUPPORTED_MEDIA_TYPE:
+				return "Unsupported Media Type";
+			case HTTP_STATUS_CODE_416_RANGE_NOT_SATISFIABLE:
+				return "Requested range not satisfiable";
+			case HTTP_STATUS_CODE_417_EXPECTATION_FAILED:
+				return "Expectation Failed";
+			default:
+				return "Client Error";
+		}
+	}
 
+	if (statusCode >= 500 && statusCode <= 599)
+	{
+		switch (statusCode)
+		{
+			case HTTP_STATUS_CODE_500_INTERNAL_SERVER_ERROR:
+				return "Internal Server Error";
+			case HTTP_STATUS_CODE_501_NOT_IMPLEMENTED:
+				return "Not Implemented";
+			case HTTP_STATUS_CODE_502_BAD_GATEWAY:
+				return "Bad Gateway";
+			case HTTP_STATUS_CODE_503_SERVICE_UNAVAILABLE:
+				return "Service Unavailable";
+			case HTTP_STATUS_CODE_504_GATEWAY_TIMEOUT:
+				return "Gateway Time-out";
+			case HTTP_STATUS_CODE_505_VERSION_NOT_SUPPORTED:
+				return "HTTP Version not supported";
+			default:
+				return "Server Error";
+		}
 	}
-	
-	return psReturn;
 
+	return "Unknown";
 }
 
 
-
 void EHSConnection::AddResponse ( HttpResponse * ipoHttpResponse )
 {
 
@@ -1206,7 +1287,7 @@ void EHSConnection::SendHttpResponse ( HttpResponse * ipoHttpResponse )
 	sOutput += psSmallBuffer;
 
 	sOutput += " ";
-	sOutput +=  GetResponsePhrase ( ipoHttpResponse->m_nResponseCode );
+	sOutput +=  GetHttpStatusReasonPhrase ( ipoHttpResponse->m_nResponseCode );
 	sOutput += "\r\n";
 
 
@@ -1496,7 +1577,7 @@ EHS::RouteRequest ( HttpRequest * ipoHttpRequest ///< request info for service
 		HttpResponse * poHttpResponse = new HttpResponse ( ipoHttpRequest->m_nRequestId,
 														   ipoHttpRequest->m_poSourceEHSConnection );
 
-		poHttpResponse->m_nResponseCode = HTTPRESPONSECODE_404_NOTFOUND;
+		poHttpResponse->m_nResponseCode = HTTP_STATUS_CODE_404_NOT_FOUND;
 		poHttpResponse->SetBody ( "404 - Not Found", strlen ( "404 - Not Found" ) );
 
 		return poHttpResponse;
@@ -1506,8 +1587,8 @@ EHS::RouteRequest ( HttpRequest * ipoHttpRequest ///< request info for service
 }
 
 // default handle request does nothing
-ResponseCode EHS::HandleRequest ( HttpRequest * ipoHttpRequest,
-								  HttpResponse * ipoHttpResponse)
+HttpStatusCode EHS::HandleRequest ( HttpRequest * ipoHttpRequest,
+								    HttpResponse * ipoHttpResponse)
 {
 
 	// if we have a source EHS specified, use it
@@ -1519,7 +1600,7 @@ ResponseCode EHS::HandleRequest ( HttpRequest * ipoHttpRequest,
 	char psTime [ 20 ];
 	sprintf ( psTime, "%lld", time ( NULL ) );
 	ipoHttpResponse->SetBody ( psTime, strlen ( psTime ) );
-	return HTTPRESPONSECODE_200_OK;
+	return HTTP_STATUS_CODE_200_OK;
 
 }
 
diff --git a/vendor/ehs/ehs.h b/vendor/ehs/ehs.h
index 3d775d00ba..35e12cfa6c 100644
--- a/vendor/ehs/ehs.h
+++ b/vendor/ehs/ehs.h
@@ -295,7 +295,7 @@ class EHS {
 	virtual HttpResponse * RouteRequest ( HttpRequest * ipoHttpRequest );
 
 	/// This function should be defined by the subclass
-	virtual ResponseCode HandleRequest ( HttpRequest * ipoHttpRequest,
+	virtual HttpStatusCode HandleRequest(HttpRequest* ipoHttpRequest,
 										 HttpResponse * ipoHttpResponse );
 
 	/// This function should be defined by the subclass
diff --git a/vendor/ehs/httprequest.cpp b/vendor/ehs/httprequest.cpp
index 8161fdbd7b..dfc5b4d6b3 100644
--- a/vendor/ehs/httprequest.cpp
+++ b/vendor/ehs/httprequest.cpp
@@ -10,10 +10,10 @@ void HttpRequest::ParseRequestURI(std::string_view uri)
 		return;
 
 	// See: https://www.rfc-editor.org/rfc/rfc3986#section-3.4
-	if (size_t queryDelimiter = uri.find('?'); queryDelimiter != std::string_view::npos)
+	if (size_t queryDelimiter = uri.find_first_of("?&"); queryDelimiter != std::string_view::npos)
 	{
-		// Skip repeating '?' (question mark) characters after the first one.
-		if (queryDelimiter = uri.find_first_not_of('?', queryDelimiter + 1); queryDelimiter == std::string_view::npos)
+		// Skip repeating '?' (question mark) and '&' (ampersand) characters after the first one.
+		if (queryDelimiter = uri.find_first_not_of("?&", queryDelimiter + 1); queryDelimiter == std::string_view::npos)
 			return;
 
 		std::string_view parameters = uri.substr(queryDelimiter);
@@ -32,11 +32,11 @@ void HttpRequest::ParseRequestURI(std::string_view uri)
 
 		// According to the RFC, query can be anything, but this web server implementation only supports "key=value" pairs,
 		// which are parsable as form data.
-		ParseFormData(parameters);
+		ParseFormData(parameters, true);
 	}
 }
 
-void HttpRequest::ParseFormData(std::string_view formData)
+void HttpRequest::ParseFormData(std::string_view formData, bool isQueryData)
 {
 	size_t counter = 0;
 
@@ -88,6 +88,11 @@ void HttpRequest::ParseFormData(std::string_view formData)
 			if (!key.empty())
 			{
 				oFormValueMap[std::string{key}] = FormValue{value};
+
+				if (isQueryData)
+				{
+					oQueryValueMap[std::string{key}] = FormValue{value};
+				}
 			}
 		}
 
@@ -385,7 +390,7 @@ HttpRequest::HttpParseStates HttpRequest::ParseData ( std::string & irsData ///<
 			else {
 				
 				// everything must be uppercase according to rfc2616
-				PME oRequestLineRegex ( "^(OPTIONS|GET|HEAD|POST|PUT|DELETE|TRACE|CONNECT) ([^ ]*) HTTP/([^ ]+)\\r\\n$" );
+				PME oRequestLineRegex ( "^(OPTIONS|GET|HEAD|POST|PUT|DELETE|TRACE|CONNECT|PATCH) ([^ ]*) HTTP/([^ ]+)\\r\\n$" );
 
 				if ( oRequestLineRegex.match ( sLine ) ) {
 
@@ -554,7 +559,7 @@ HttpRequest::HttpParseStates HttpRequest::ParseData ( std::string & irsData ///<
 				// else the body is just one piece
 				else {
 					// check for any form data
-					ParseFormData(sBody);
+					ParseFormData(sBody, false);
 					
 #ifdef EHS_DEBUG
 					fprintf ( stderr, "Done with body, done with entire request\n" );
@@ -662,7 +667,7 @@ int GetNextLine ( std::string & irsLine, ///< line removed from *ippsBuffer
 
 /// List of possible HTTP request methods
 const char * RequestMethodStrings [] = { "OPTIONS", "GET", "HEAD", "POST", 
-								   "PUT", "DELETE", "TRACE", "CONNECT", "*" };
+								   "PUT", "DELETE", "TRACE", "CONNECT", "PATCH", "*"};
 
 
 RequestMethod GetRequestMethodFromString ( const std::string & isRequestMethod  ///< determine the request type enumeration from the request string
diff --git a/vendor/ehs/httprequest.h b/vendor/ehs/httprequest.h
index a477579c67..b1fa53248b 100644
--- a/vendor/ehs/httprequest.h
+++ b/vendor/ehs/httprequest.h
@@ -26,6 +26,7 @@ enum RequestMethod { REQUESTMETHOD_OPTIONS, /* not implemented */
 					 REQUESTMETHOD_DELETE, ///< not implemented
 					 REQUESTMETHOD_TRACE, ///< not implemented
 					 REQUESTMETHOD_CONNECT, ///< not implemented
+					 REQUESTMETHOD_PATCH, ///< not implemented
 					 REQUESTMETHOD_LAST, ///< must be the last valid entry
 					 REQUESTMETHOD_UNKNOWN, ///< used until we find the method
 					 REQUESTMETHOD_INVALID ///< must be the last entry
@@ -92,7 +93,7 @@ class HttpRequest {
 	void ParseRequestURI(std::string_view uri);
 
 	/// parses the form data as if it's key=value pairs and puts them into oFormElements
-	void ParseFormData(std::string_view formData);
+	void ParseFormData(std::string_view formData, bool isQueryData);
 
 	/// the current parse state -- where we are in looking at the data from the client
 	HttpParseStates nCurrentHttpParseState;
@@ -122,6 +123,9 @@ class HttpRequest {
 	/// Data specified by the client.  The 'name' field is mapped to a FormValue object which has the value and any metadata
 	FormValueMap oFormValueMap;
 
+	/// Data specified by the client in the query string.
+	FormValueMap oQueryValueMap;
+
 	/// cookies that come in from the client
 	CookieMap oCookieMap;
 
diff --git a/vendor/ehs/httpresponse.cpp b/vendor/ehs/httpresponse.cpp
index f0cc093617..3725782af0 100644
--- a/vendor/ehs/httpresponse.cpp
+++ b/vendor/ehs/httpresponse.cpp
@@ -46,7 +46,7 @@ char * CreateHttpTime ( )
 
 HttpResponse::HttpResponse ( int inResponseId,
 							 EHSConnection * ipoEHSConnection ) :
-	m_nResponseCode ( HTTPRESPONSECODE_INVALID ),	
+	m_nResponseCode ( HTTP_STATUS_CODE_INVALID ),	
 	psBody ( NULL ),
 	nBodyLength ( 0 ),
 	m_nResponseId ( inResponseId ),
diff --git a/vendor/ehs/httpresponse.h b/vendor/ehs/httpresponse.h
index b7ebcb55bc..98d567c684 100644
--- a/vendor/ehs/httpresponse.h
+++ b/vendor/ehs/httpresponse.h
@@ -16,19 +16,52 @@
 #include "ehstypes.h"
 #include "datum.h"
 
-/// different response codes and their corresponding phrases -- defined in EHS.cpp
-enum ResponseCode { HTTPRESPONSECODE_INVALID = 0,
-					HTTPRESPONSECODE_200_OK = 200,
-					HTTPRESPONSECODE_301_MOVEDPERMANENTLY = 301,
-					HTTPRESPONSECODE_302_FOUND = 302,
-					HTTPRESPONSECODE_401_UNAUTHORIZED = 401,
-					HTTPRESPONSECODE_403_FORBIDDEN = 403,
-					HTTPRESPONSECODE_404_NOTFOUND = 404,
-					HTTPRESPONSECODE_500_INTERNALSERVERERROR = 500 };
-
-/// Holds strings corresponding to the items in the ResponseCode enumeration
-extern const char * ResponsePhrase [ ]; 
+enum HttpStatusCode
+{
+	HTTP_STATUS_CODE_INVALID = 0,
+	HTTP_STATUS_CODE_100_CONTINUE = 100,                            ///< Continue
+	HTTP_STATUS_CODE_101_SWITCHING_PROTOCOLS = 101,                 ///< Switching Protocols
+	HTTP_STATUS_CODE_200_OK = 200,                                  ///< OK
+	HTTP_STATUS_CODE_201_CREATED = 201,                             ///< Created
+	HTTP_STATUS_CODE_202_ACCEPTED = 202,                            ///< Accepted
+	HTTP_STATUS_CODE_203_NON_AUTHORITATIVE_INFO = 203,              ///< Non-Authoritative Information
+	HTTP_STATUS_CODE_204_NO_CONTENT = 204,                          ///< No Content
+	HTTP_STATUS_CODE_205_RESET_CONTENT = 205,                       ///< Reset Content
+	HTTP_STATUS_CODE_206_PARTIAL_CONTENT = 206,                     ///< Partial Content
+	HTTP_STATUS_CODE_300_MULTIPLE_CHOICES = 300,                    ///< Multiple Choices
+	HTTP_STATUS_CODE_301_MOVED_PERMANENTLY = 301,                   ///< Moved Permanently
+	HTTP_STATUS_CODE_302_FOUND = 302,                               ///< Found
+	HTTP_STATUS_CODE_303_SEE_OTHER = 303,                           ///< See Other
+	HTTP_STATUS_CODE_304_NOT_MODIFIED = 304,                        ///< Not Modified
+	HTTP_STATUS_CODE_305_USE_PROXY = 305,                           ///< Use Proxy
+	HTTP_STATUS_CODE_307_TEMPORARY_REDIRECT = 307,                  ///< Temporary Redirect
+	HTTP_STATUS_CODE_400_BAD_REQUEST = 400,                         ///< Bad Request
+	HTTP_STATUS_CODE_401_UNAUTHORIZED = 401,                        ///< Unauthorized
+	HTTP_STATUS_CODE_402_PAYMENT_REQUIRED = 402,                    ///< Payment Required
+	HTTP_STATUS_CODE_403_FORBIDDEN = 403,                           ///< Forbidden
+	HTTP_STATUS_CODE_404_NOT_FOUND = 404,                           ///< Not Found
+	HTTP_STATUS_CODE_405_METHOD_NOT_ALLOWED = 405,                  ///< Method Not Allowed
+	HTTP_STATUS_CODE_406_NOT_ACCEPTABLE = 406,                      ///< Not Acceptable
+	HTTP_STATUS_CODE_407_PROXY_AUTH_REQUIRED = 407,                 ///< Proxy Authentication Required
+	HTTP_STATUS_CODE_408_REQUEST_TIMEOUT = 408,                     ///< Request Time-out
+	HTTP_STATUS_CODE_409_CONFLICT = 409,                            ///< Conflict
+	HTTP_STATUS_CODE_410_GONE = 410,                                ///< Gone
+	HTTP_STATUS_CODE_411_LENGTH_REQUIRED = 411,                     ///< Length Required
+	HTTP_STATUS_CODE_412_PRECONDITION_FAILED = 412,                 ///< Precondition Failed
+	HTTP_STATUS_CODE_413_REQUEST_ENTITY_TOO_LARGE = 413,            ///< Request Entity Too Large
+	HTTP_STATUS_CODE_414_URI_TOO_LARGE = 414,                       ///< Request-URI Too Large
+	HTTP_STATUS_CODE_415_UNSUPPORTED_MEDIA_TYPE = 415,              ///< Unsupported Media Type
+	HTTP_STATUS_CODE_416_RANGE_NOT_SATISFIABLE = 416,               ///< Requested range not satisfiable
+	HTTP_STATUS_CODE_417_EXPECTATION_FAILED = 417,                  ///< Expectation Failed
+	HTTP_STATUS_CODE_500_INTERNAL_SERVER_ERROR = 500,               ///< Internal Server Error
+	HTTP_STATUS_CODE_501_NOT_IMPLEMENTED = 501,                     ///< Not Implemented
+	HTTP_STATUS_CODE_502_BAD_GATEWAY = 502,                         ///< Bad Gateway
+	HTTP_STATUS_CODE_503_SERVICE_UNAVAILABLE = 503,                 ///< Service Unavailable
+	HTTP_STATUS_CODE_504_GATEWAY_TIMEOUT = 504,                     ///< Gateway Time-out
+	HTTP_STATUS_CODE_505_VERSION_NOT_SUPPORTED = 505,               ///< HTTP Version not supported
+};
 
+extern const char* GetHttpStatusReasonPhrase(int statusCode);
 
 /// This defines what is sent back to the client
 /**
@@ -58,7 +91,7 @@ class HttpResponse {
 	char * GetBody ( ) { return psBody; };
 
 	/// the response code to be sent back
-	ResponseCode m_nResponseCode;
+	HttpStatusCode m_nResponseCode;
 
 	/// these are the headers sent back to the client in the http response.  Things like content-type and content-length
 	StringMap oResponseHeaders;
diff --git a/vendor/freetype/README b/vendor/freetype/README
index cd4c1d7d11..19c934256f 100644
--- a/vendor/freetype/README
+++ b/vendor/freetype/README
@@ -94,7 +94,7 @@ Enjoy!
 
 ----------------------------------------------------------------------
 
-Copyright (C) 2006-2023 by
+Copyright (C) 2006-2024 by
 David Turner, Robert Wilhelm, and Werner Lemberg.
 
 This  file is  part of  the FreeType  project, and  may only  be used,
diff --git a/vendor/freetype/builds/windows/ftdebug.c b/vendor/freetype/builds/windows/ftdebug.c
index 360f8c7e32..2c69967638 100644
--- a/vendor/freetype/builds/windows/ftdebug.c
+++ b/vendor/freetype/builds/windows/ftdebug.c
@@ -4,7 +4,7 @@
  *
  *   Debugging and logging component for Win32 (body).
  *
- * Copyright (C) 1996-2023 by
+ * Copyright (C) 1996-2024 by
  * David Turner, Robert Wilhelm, and Werner Lemberg.
  *
  * This file is part of the FreeType project, and may only be used,
diff --git a/vendor/freetype/builds/windows/ftsystem.c b/vendor/freetype/builds/windows/ftsystem.c
index 418d7995e3..477cad71f7 100644
--- a/vendor/freetype/builds/windows/ftsystem.c
+++ b/vendor/freetype/builds/windows/ftsystem.c
@@ -4,7 +4,7 @@
  *
  *   Windows-specific FreeType low-level system interface (body).
  *
- * Copyright (C) 2021-2023 by
+ * Copyright (C) 2021-2024 by
  * David Turner, Robert Wilhelm, and Werner Lemberg.
  *
  * This file is part of the FreeType project, and may only be used,
@@ -196,8 +196,8 @@
   }
 
 
-  /* non-desktop Universal Windows Platform */
-#if defined( WINAPI_FAMILY ) && WINAPI_FAMILY != WINAPI_FAMILY_DESKTOP_APP
+  /* support for Universal Windows Platform UWP, formerly WinRT */
+#ifdef _WINRT_DLL
 
 #define PACK_DWORD64( hi, lo )  ( ( (DWORD64)(hi) << 32 ) | (DWORD)(lo) )
 
@@ -248,10 +248,11 @@
                         dwCreationDisposition, &createExParams );
   }
 
-#endif
+#endif  /* _WINRT_DLL */
 
 
-#if defined( _WIN32_WCE )
+  /* support for Windows CE */
+#ifdef _WIN32_WCE
 
   /* malloc.h provides implementation of alloca()/_alloca() */
   #include 
@@ -291,9 +292,9 @@
                         dwFlagsAndAttributes, hTemplateFile );
   }
 
-#endif
-
+#endif  /* _WIN32_WCE */
 
+  /* support for really old Windows */
 #if defined( _WIN32_WCE ) || defined ( _WIN32_WINDOWS ) || \
     !defined( _WIN32_WINNT ) || _WIN32_WINNT <= 0x0400
 
@@ -311,7 +312,7 @@
       return TRUE;
   }
 
-#endif
+#endif  /* _WIN32_WCE || _WIN32_WINDOWS || _WIN32_WINNT <= 0x0400 */
 
 
   /* documentation is in ftobjs.h */
diff --git a/vendor/freetype/include/dlg/dlg.h b/vendor/freetype/include/dlg/dlg.h
deleted file mode 100644
index fa10730e83..0000000000
--- a/vendor/freetype/include/dlg/dlg.h
+++ /dev/null
@@ -1,290 +0,0 @@
-// Copyright (c) 2019 nyorain
-// Distributed under the Boost Software License, Version 1.0.
-// See accompanying file LICENSE or copy at http://www.boost.org/LICENSE_1_0.txt
-
-#ifndef INC_DLG_DLG_H_
-#define INC_DLG_DLG_H_
-
-#include 
-#include 
-#include 
-#include 
-#include 
-
-// Hosted at https://github.com/nyorain/dlg.
-// There are examples and documentation.
-// Issue reports and contributions appreciated.
-
-// - CONFIG -
-// Define this macro to make all dlg macros have no effect at all
-// #define DLG_DISABLE
-
-// the log/assertion levels below which logs/assertions are ignored
-// defaulted depending on the NDEBUG macro
-#ifndef DLG_LOG_LEVEL
-	#ifdef NDEBUG
-		#define DLG_LOG_LEVEL dlg_level_warn
-	#else
-		#define DLG_LOG_LEVEL dlg_level_trace
-	#endif
-#endif
-
-#ifndef DLG_ASSERT_LEVEL
-	#ifdef NDEBUG
-		#define DLG_ASSERT_LEVEL dlg_level_warn
-	#else
-		#define DLG_ASSERT_LEVEL dlg_level_trace
-	#endif
-#endif
-
-// the assert level of dlg_assert
-#ifndef DLG_DEFAULT_ASSERT
-	#define DLG_DEFAULT_ASSERT dlg_level_error
-#endif
-
-// evaluated to the 'file' member in dlg_origin
-#ifndef DLG_FILE
-	#define DLG_FILE dlg__strip_root_path(__FILE__, DLG_BASE_PATH)
-
-	// the base path stripped from __FILE__. If you don't override DLG_FILE set this to
-	// the project root to make 'main.c' from '/some/bullshit/main.c'
-	#ifndef DLG_BASE_PATH
-		#define DLG_BASE_PATH ""
-	#endif
-#endif
-
-// Default tags applied to all logs/assertions (in the defining file).
-// Must be in format ```#define DLG_DEFAULT_TAGS "tag1", "tag2"```
-// or just nothing (as defaulted here)
-#ifndef DLG_DEFAULT_TAGS
-	#define DLG_DEFAULT_TAGS_TERM NULL
-#else
-	#define DLG_DEFAULT_TAGS_TERM DLG_DEFAULT_TAGS, NULL
-#endif
-
-// The function used for formatting. Can have any signature, but must be callable with
-// the arguments the log/assertions macros are called with. Must return a const char*
-// that will not be freed by dlg, the formatting function must keep track of it.
-// The formatting function might use dlg_thread_buffer or a custom owned buffer.
-// The returned const char* has to be valid until the dlg log/assertion ends.
-// Usually a c function with ... (i.e. using va_list) or a variadic c++ template do
-// allow formatting.
-#ifndef DLG_FMT_FUNC
-	#define DLG_FMT_FUNC dlg__printf_format
-#endif
-
-// Only overwrite (i.e. predefine) this if you know what you are doing.
-// On windows this is used to add the dllimport specified.
-// If you are using the static version of dlg (on windows) define
-// DLG_STATIC before including dlg.h
-#ifndef DLG_API
- 	#if (defined(_WIN32) || defined(__CYGWIN__)) && !defined(DLG_STATIC)
-		#define DLG_API __declspec(dllimport)
-	#else
-		#define DLG_API
-	#endif
-#endif
-
-// This macro is used when an assertion fails. It gets the source expression
-// and can return an alternative (that must stay alive).
-// Mainly useful to execute something on failed assertion.
-#ifndef DLG_FAILED_ASSERTION_TEXT
-	#define DLG_FAILED_ASSERTION_TEXT(x) x
-#endif
-
-// - utility -
-// two methods needed since cplusplus does not support compound literals
-// and c does not support uniform initialization/initializer lists
-#ifdef __cplusplus
-	#include 
-	#define DLG_CREATE_TAGS(...) std::initializer_list \
-		{DLG_DEFAULT_TAGS_TERM, __VA_ARGS__, NULL}.begin()
-#else
-	#define DLG_CREATE_TAGS(...) (const char* const[]) {DLG_DEFAULT_TAGS_TERM, __VA_ARGS__, NULL}
-#endif
-
-#ifdef __GNUC__
-	#define DLG_PRINTF_ATTRIB(a, b) __attribute__ ((format (printf, a, b)))
-#else
-	#define DLG_PRINTF_ATTRIB(a, b)
-#endif
-
-#ifdef __cplusplus
-extern "C" {
-#endif
-
-
-// Represents the importance of a log/assertion call.
-enum dlg_level {
-	dlg_level_trace = 0, // temporary used debug, e.g. to check if control reaches function
-	dlg_level_debug, // general debugging, prints e.g. all major events
-	dlg_level_info, // general useful information
-	dlg_level_warn, // warning, something went wrong but might have no (really bad) side effect
-	dlg_level_error, // something really went wrong; expect serious issues
-	dlg_level_fatal // critical error; application is likely to crash/exit
-};
-
-// Holds various information associated with a log/assertion call.
-// Forwarded to the output handler.
-struct dlg_origin {
-	const char* file;
-	unsigned int line;
-	const char* func;
-	enum dlg_level level;
-	const char** tags; // null-terminated
-	const char* expr; // assertion expression, otherwise null
-};
-
-// Type of the output handler, see dlg_set_handler.
-typedef void(*dlg_handler)(const struct dlg_origin* origin, const char* string, void* data);
-
-#ifndef DLG_DISABLE
-	// Tagged/Untagged logging with variable level
-	// Tags must always be in the format `("tag1", "tag2")` (including brackets)
-	// Example usages:
-	//   dlg_log(dlg_level_warning, "test 1")
-	//   dlg_logt(("tag1, "tag2"), dlg_level_debug, "test %d", 2)
-	#define dlg_log(level, ...) if(level >= DLG_LOG_LEVEL) \
-		dlg__do_log(level, DLG_CREATE_TAGS(NULL), DLG_FILE, __LINE__, __func__,  \
-		DLG_FMT_FUNC(__VA_ARGS__), NULL)
-	#define dlg_logt(level, tags, ...) if(level >= DLG_LOG_LEVEL) \
-		dlg__do_log(level, DLG_CREATE_TAGS tags, DLG_FILE, __LINE__, __func__, \
-		DLG_FMT_FUNC(__VA_ARGS__), NULL)
-
-	// Dynamic level assert macros in various versions for additional arguments
-	// Example usages:
-	//   dlg_assertl(dlg_level_warning, data != nullptr);
-	//   dlg_assertlt(("tag1, "tag2"), dlg_level_trace, data != nullptr);
-	//   dlg_asserttlm(("tag1), dlg_level_warning, data != nullptr, "Data must not be null");
-	//   dlg_assertlm(dlg_level_error, data != nullptr, "Data must not be null");
-	#define dlg_assertl(level, expr) if(level >= DLG_ASSERT_LEVEL && !(expr)) \
-		dlg__do_log(level, DLG_CREATE_TAGS(NULL), DLG_FILE, __LINE__, __func__, NULL, \
-			DLG_FAILED_ASSERTION_TEXT(#expr))
-	#define dlg_assertlt(level, tags, expr) if(level >= DLG_ASSERT_LEVEL && !(expr)) \
-		dlg__do_log(level, DLG_CREATE_TAGS tags, DLG_FILE, __LINE__, __func__, NULL, \
-			DLG_FAILED_ASSERTION_TEXT(#expr))
-	#define dlg_assertlm(level, expr, ...) if(level >= DLG_ASSERT_LEVEL && !(expr)) \
-		dlg__do_log(level, DLG_CREATE_TAGS(NULL), DLG_FILE, __LINE__, __func__,  \
-			DLG_FMT_FUNC(__VA_ARGS__), DLG_FAILED_ASSERTION_TEXT(#expr))
-	#define dlg_assertltm(level, tags, expr, ...) if(level >= DLG_ASSERT_LEVEL && !(expr)) \
-		dlg__do_log(level, DLG_CREATE_TAGS tags, DLG_FILE, __LINE__,  \
-			__func__, DLG_FMT_FUNC(__VA_ARGS__), DLG_FAILED_ASSERTION_TEXT(#expr))
-
-	#define dlg__assert_or(level, tags, expr, code, msg) if(!(expr)) {\
-			if(level >= DLG_ASSERT_LEVEL) \
-				dlg__do_log(level, tags, DLG_FILE, __LINE__, __func__, msg, \
-					DLG_FAILED_ASSERTION_TEXT(#expr)); \
-			code; \
-		} (void) NULL
-
-	// - Private interface: not part of the abi/api but needed in macros -
-	// Formats the given format string and arguments as printf would, uses the thread buffer.
-	DLG_API const char* dlg__printf_format(const char* format, ...) DLG_PRINTF_ATTRIB(1, 2);
-	DLG_API void dlg__do_log(enum dlg_level lvl, const char* const*, const char*, int,
-		const char*, const char*, const char*);
-	DLG_API const char* dlg__strip_root_path(const char* file, const char* base);
-
-#else // DLG_DISABLE
-
-	#define dlg_log(level, ...)
-	#define dlg_logt(level, tags, ...)
-
-	#define dlg_assertl(level, expr) // assert without tags/message
-	#define dlg_assertlt(level, tags, expr) // assert with tags
-	#define dlg_assertlm(level, expr, ...) // assert with message
-	#define dlg_assertltm(level, tags, expr, ...) // assert with tags & message
-
-	#define dlg__assert_or(level, tags, expr, code, msg) if(!(expr)) { code; } (void) NULL
-#endif // DLG_DISABLE
-
-// The API below is independent from DLG_DISABLE
-
-// Sets the handler that is responsible for formatting and outputting log calls.
-// This function is not thread safe and the handler is set globally.
-// The handler itself must not change dlg tags or call a dlg macro (if it
-// does so, the provided string or tags array in 'origin' might get invalid).
-// The handler can also be used for various other things such as dealing
-// with failed assertions or filtering calls based on the passed tags.
-// The default handler is dlg_default_output (see its doc for more info).
-// If using c++ make sure the registered handler cannot throw e.g. by
-// wrapping everything into a try-catch blog.
-DLG_API void dlg_set_handler(dlg_handler handler, void* data);
-
-// The default output handler.
-// Only use this to reset the output handler, prefer to use
-// dlg_generic_output (from output.h) which this function simply calls.
-// It also flushes the stream used and correctly outputs even from multiple threads.
-DLG_API void dlg_default_output(const struct dlg_origin*, const char* string, void*);
-
-// Returns the currently active dlg handler and sets `data` to
-// its user data pointer. `data` must not be NULL.
-// Useful to create handler chains.
-// This function is not threadsafe, i.e. retrieving the handler while
-// changing it from another thread is unsafe.
-// See `dlg_set_handler`.
-DLG_API dlg_handler dlg_get_handler(void** data);
-
-// Adds the given tag associated with the given function to the thread specific list.
-// If func is not NULL the tag will only applied to calls from the same function.
-// Remove the tag again calling dlg_remove_tag (with exactly the same pointers!).
-// Does not check if the tag is already present.
-DLG_API void dlg_add_tag(const char* tag, const char* func);
-
-// Removes a tag added with dlg_add_tag (has no effect for tags no present).
-// The pointers must be exactly the same pointers that were supplied to dlg_add_tag,
-// this function will not check using strcmp. When the same tag/func combination
-// is added multiple times, this function remove exactly one candidate, it is
-// undefined which. Returns whether a tag was found (and removed).
-DLG_API bool dlg_remove_tag(const char* tag, const char* func);
-
-// Returns the thread-specific buffer and its size for dlg.
-// The buffer should only be used by formatting functions.
-// The buffer can be reallocated and the size changed, just make sure
-// to update both values correctly.
-DLG_API char** dlg_thread_buffer(size_t** size);
-
-// Untagged leveled logging
-#define dlg_trace(...) dlg_log(dlg_level_trace, __VA_ARGS__)
-#define dlg_debug(...) dlg_log(dlg_level_debug, __VA_ARGS__)
-#define dlg_info(...) dlg_log(dlg_level_info, __VA_ARGS__)
-#define dlg_warn(...) dlg_log(dlg_level_warn, __VA_ARGS__)
-#define dlg_error(...) dlg_log(dlg_level_error, __VA_ARGS__)
-#define dlg_fatal(...) dlg_log(dlg_level_fatal, __VA_ARGS__)
-
-// Tagged leveled logging
-#define dlg_tracet(tags, ...) dlg_logt(dlg_level_trace, tags, __VA_ARGS__)
-#define dlg_debugt(tags, ...) dlg_logt(dlg_level_debug, tags, __VA_ARGS__)
-#define dlg_infot(tags, ...) dlg_logt(dlg_level_info, tags, __VA_ARGS__)
-#define dlg_warnt(tags, ...) dlg_logt(dlg_level_warn, tags, __VA_ARGS__)
-#define dlg_errort(tags, ...) dlg_logt(dlg_level_error, tags, __VA_ARGS__)
-#define dlg_fatalt(tags, ...) dlg_logt(dlg_level_fatal, tags, __VA_ARGS__)
-
-// Assert macros useing DLG_DEFAULT_ASSERT as level
-#define dlg_assert(expr) dlg_assertl(DLG_DEFAULT_ASSERT, expr)
-#define dlg_assertt(tags, expr) dlg_assertlt(DLG_DEFAULT_ASSERT, tags, expr)
-#define dlg_assertm(expr, ...) dlg_assertlm(DLG_DEFAULT_ASSERT, expr, __VA_ARGS__)
-#define dlg_asserttm(tags, expr, ...) dlg_assertltm(DLG_DEFAULT_ASSERT, tags, expr, __VA_ARGS__)
-
-// If (expr) does not evaluate to true, always executes 'code' (no matter what
-// DLG_ASSERT_LEVEL is or if dlg is disabled or not).
-// When dlg is enabled and the level is greater or equal to DLG_ASSERT_LEVEL,
-// logs the failed assertion.
-// Example usages:
-//   dlg_assertl_or(dlg_level_warn, data != nullptr, return);
-//   dlg_assertlm_or(dlg_level_fatal, data != nullptr, return, "Data must not be null");
-//   dlg_assert_or(data != nullptr, logError(); return false);
-#define dlg_assertltm_or(level, tags, expr, code, ...) dlg__assert_or(level, \
-		DLG_CREATE_TAGS tags, expr, code, DLG_FMT_FUNC(__VA_ARGS__))
-#define dlg_assertlm_or(level, expr, code, ...) dlg__assert_or(level, \
-		DLG_CREATE_TAGS(NULL), expr, code, DLG_FMT_FUNC(__VA_ARGS__))
-#define dlg_assertl_or(level, expr, code) dlg__assert_or(level, \
-		DLG_CREATE_TAGS(NULL), expr, code, NULL)
-
-#define dlg_assert_or(expr, code) dlg_assertl_or(DLG_DEFAULT_ASSERT, expr, code)
-#define dlg_assertm_or(expr, code, ...) dlg_assertlm_or(DLG_DEFAULT_ASSERT, expr, code, __VA_ARGS__)
-
-#ifdef __cplusplus
-}
-#endif
-
-#endif // header guard
diff --git a/vendor/freetype/include/dlg/output.h b/vendor/freetype/include/dlg/output.h
deleted file mode 100644
index 453e4a5613..0000000000
--- a/vendor/freetype/include/dlg/output.h
+++ /dev/null
@@ -1,172 +0,0 @@
-// Copyright (c) 2019 nyorain
-// Distributed under the Boost Software License, Version 1.0.
-// See accompanying file LICENSE or copy at http://www.boost.org/LICENSE_1_0.txt
-
-#ifndef INC_DLG_OUTPUT_H_
-#define INC_DLG_OUTPUT_H_
-
-#include 
-#include 
-
-#ifdef __cplusplus
-extern "C" {
-#endif
-
-// Text style
-enum dlg_text_style {
-	dlg_text_style_reset     = 0,
-	dlg_text_style_bold      = 1,
-	dlg_text_style_dim       = 2,
-	dlg_text_style_italic    = 3,
-	dlg_text_style_underline = 4,
-	dlg_text_style_blink     = 5,
-	dlg_text_style_rblink    = 6,
-	dlg_text_style_reversed  = 7,
-	dlg_text_style_conceal   = 8,
-	dlg_text_style_crossed   = 9,
-	dlg_text_style_none,
-};
-
-// Text color
-enum dlg_color {
-	dlg_color_black = 0,
-	dlg_color_red,
-	dlg_color_green,
-	dlg_color_yellow,
-	dlg_color_blue,
-	dlg_color_magenta,
-	dlg_color_cyan,
-	dlg_color_gray,
-	dlg_color_reset = 9,
-
-	dlg_color_black2 = 60,
-	dlg_color_red2,
-	dlg_color_green2,
-	dlg_color_yellow2,
-	dlg_color_blue2,
-	dlg_color_magenta2,
-	dlg_color_cyan2,
-	dlg_color_gray2,
-
-	dlg_color_none = 69,
-};
-
-struct dlg_style {
-	enum dlg_text_style style;
-	enum dlg_color fg;
-	enum dlg_color bg;
-};
-
-// Like fprintf but fixes utf-8 output to console on windows.
-// On non-windows sytems just uses the corresponding standard library
-// functions. On windows, if dlg was compiled with the win_console option,
-// will first try to output it in a way that allows the default console
-// to display utf-8. If that fails, will fall back to the standard
-// library functions.
-DLG_API int dlg_fprintf(FILE* stream, const char* format, ...) DLG_PRINTF_ATTRIB(2, 3);
-DLG_API int dlg_vfprintf(FILE* stream, const char* format, va_list list);
-
-// Like dlg_printf, but also applies the given style to this output.
-// The style will always be applied (using escape sequences), independent of the given stream.
-// On windows escape sequences don't work out of the box, see dlg_win_init_ansi().
-DLG_API int dlg_styled_fprintf(FILE* stream, struct dlg_style style,
-	const char* format, ...) DLG_PRINTF_ATTRIB(3, 4);
-
-// Features to output from the generic output handler.
-// Some features might have only an effect in the specializations.
-enum dlg_output_feature {
-	dlg_output_tags = 1, // output tags list
-	dlg_output_time = 2, // output time of log call (hour:minute:second)
-	dlg_output_style = 4, // whether to use the supplied styles
-	dlg_output_func = 8, // output function
-	dlg_output_file_line = 16, // output file:line,
-	dlg_output_newline = 32, // output a newline at the end
-	dlg_output_threadsafe = 64, // locks stream before printing
-	dlg_output_time_msecs = 128 // output micro seconds (ms on windows)
-};
-
-// The default level-dependent output styles. The array values represent the styles
-// to be used for the associated level (i.e. [0] for trace level).
-DLG_API extern const struct dlg_style dlg_default_output_styles[6];
-
-// Generic output function. Used by the default output handler and might be useful
-// for custom output handlers (that don't want to manually format the output).
-// Will call the given output func with the given data (and format + args to print)
-// for everything it has to print in printf format.
-// See also the *_stream and *_buf specializations for common usage.
-// The given output function must not be NULL.
-typedef void(*dlg_generic_output_handler)(void* data, const char* format, ...);
-DLG_API void dlg_generic_output(dlg_generic_output_handler output, void* data,
-		unsigned int features, const struct dlg_origin* origin, const char* string,
-		const struct dlg_style styles[6]);
-
-// Generic output function, using a format string instead of feature flags.
-// Use following conversion characters:
-// %h - output the time in H:M:S format
-// %m - output the time in milliseconds
-// %t - output the full list of tags, comma separated
-// %f - output the function name noted in the origin
-// %o - output the file:line of the origin
-// %s - print the appropriate style escape sequence.
-// %r - print the escape sequence to reset the style.
-// %c - The content of the log/assert
-// %% - print the '%' character
-// Only the above specified conversion characters are valid, the rest are
-// written as it is.
-DLG_API void dlg_generic_outputf(dlg_generic_output_handler output, void* data,
-		const char* format_string, const struct dlg_origin* origin,
-		const char* string, const struct dlg_style styles[6]);
-
-// Generic output function. Used by the default output handler and might be useful
-// for custom output handlers (that don't want to manually format the output).
-// If stream is NULL uses stdout.
-// Automatically uses dlg_fprintf to assure correct utf-8 even on windows consoles.
-// Locks the stream (i.e. assures threadsafe access) when the associated feature
-// is passed (note that stdout/stderr might still mix from multiple threads).
-DLG_API void dlg_generic_output_stream(FILE* stream, unsigned int features,
-	const struct dlg_origin* origin, const char* string,
-	const struct dlg_style styles[6]);
-DLG_API void dlg_generic_outputf_stream(FILE* stream, const char* format_string,
-	const struct dlg_origin* origin, const char* string,
-	const struct dlg_style styles[6], bool lock_stream);
-
-// Generic output function (see dlg_generic_output) that uses a buffer instead of
-// a stream. buf must at least point to *size bytes. Will set *size to the number
-// of bytes written (capped to the given size), if buf == NULL will set *size
-// to the needed size. The size parameter must not be NULL.
-DLG_API void dlg_generic_output_buf(char* buf, size_t* size, unsigned int features,
-	const struct dlg_origin* origin, const char* string,
-	const struct dlg_style styles[6]);
-DLG_API void dlg_generic_outputf_buf(char* buf, size_t* size, const char* format_string,
-	const struct dlg_origin* origin, const char* string,
-	const struct dlg_style styles[6]);
-
-// Returns if the given stream is a tty. Useful for custom output handlers
-// e.g. to determine whether to use color.
-// NOTE: Due to windows limitations currently returns false for wsl ttys.
-DLG_API bool dlg_is_tty(FILE* stream);
-
-// Returns the null-terminated escape sequence for the given style into buf.
-// Undefined behvaiour if any member of style has a value outside its enum range (will
-// probably result in a buffer overflow or garbage being printed).
-// If all member of style are 'none' will simply nullterminate the first buf char.
-DLG_API void dlg_escape_sequence(struct dlg_style style, char buf[12]);
-
-// The reset style escape sequence.
-DLG_API extern const char* const dlg_reset_sequence;
-
-// Just returns true without other effect on non-windows systems or if dlg
-// was compiled without the win_console option.
-// On windows tries to set the console mode to ansi to make escape sequences work.
-// This works only on newer windows 10 versions. Returns false on error.
-// Only the first call to it will have an effect, following calls just return the result.
-// The function is threadsafe. Automatically called by the default output handler.
-// This will only be able to set the mode for the stdout and stderr consoles, so
-// other streams to consoles will still not work.
-DLG_API bool dlg_win_init_ansi(void);
-
-#ifdef __cplusplus
-} // extern "C"
-#endif
-
-#endif // header guard
diff --git a/vendor/freetype/include/freetype/config/ftconfig.h b/vendor/freetype/include/freetype/config/ftconfig.h
index a85151699d..0667493fec 100644
--- a/vendor/freetype/include/freetype/config/ftconfig.h
+++ b/vendor/freetype/include/freetype/config/ftconfig.h
@@ -4,7 +4,7 @@
  *
  *   ANSI-specific configuration file (specification only).
  *
- * Copyright (C) 1996-2023 by
+ * Copyright (C) 1996-2024 by
  * David Turner, Robert Wilhelm, and Werner Lemberg.
  *
  * This file is part of the FreeType project, and may only be used,
diff --git a/vendor/freetype/include/freetype/config/ftheader.h b/vendor/freetype/include/freetype/config/ftheader.h
index e607bce15c..f6ef2618de 100644
--- a/vendor/freetype/include/freetype/config/ftheader.h
+++ b/vendor/freetype/include/freetype/config/ftheader.h
@@ -4,7 +4,7 @@
  *
  *   Build macros of the FreeType 2 library.
  *
- * Copyright (C) 1996-2023 by
+ * Copyright (C) 1996-2024 by
  * David Turner, Robert Wilhelm, and Werner Lemberg.
  *
  * This file is part of the FreeType project, and may only be used,
diff --git a/vendor/freetype/include/freetype/config/ftmodule.h b/vendor/freetype/include/freetype/config/ftmodule.h
index b315baba8a..b52779da07 100644
--- a/vendor/freetype/include/freetype/config/ftmodule.h
+++ b/vendor/freetype/include/freetype/config/ftmodule.h
@@ -1,16 +1,4 @@
-/*
- * This file registers the FreeType modules compiled into the library.
- *
- * If you use GNU make, this file IS NOT USED!  Instead, it is created in
- * the objects directory (normally `/objs/`) based on information
- * from `/modules.cfg`.
- *
- * Please read `docs/INSTALL.ANY` and `docs/CUSTOMIZE` how to compile
- * FreeType without GNU make.
- *
- */
-
-FT_USE_MODULE( FT_Module_Class, autofit_module_class )
+/* This is a generated file. */
 FT_USE_MODULE( FT_Driver_ClassRec, tt_driver_class )
 FT_USE_MODULE( FT_Driver_ClassRec, t1_driver_class )
 FT_USE_MODULE( FT_Driver_ClassRec, cff_driver_class )
@@ -20,14 +8,14 @@ FT_USE_MODULE( FT_Driver_ClassRec, t42_driver_class )
 FT_USE_MODULE( FT_Driver_ClassRec, winfnt_driver_class )
 FT_USE_MODULE( FT_Driver_ClassRec, pcf_driver_class )
 FT_USE_MODULE( FT_Driver_ClassRec, bdf_driver_class )
-FT_USE_MODULE( FT_Module_Class, psaux_module_class )
-FT_USE_MODULE( FT_Module_Class, psnames_module_class )
-FT_USE_MODULE( FT_Module_Class, pshinter_module_class )
 FT_USE_MODULE( FT_Module_Class, sfnt_module_class )
+FT_USE_MODULE( FT_Module_Class, autofit_module_class )
+FT_USE_MODULE( FT_Module_Class, pshinter_module_class )
 FT_USE_MODULE( FT_Renderer_Class, ft_smooth_renderer_class )
 FT_USE_MODULE( FT_Renderer_Class, ft_raster1_renderer_class )
+FT_USE_MODULE( FT_Renderer_Class, ft_svg_renderer_class )
 FT_USE_MODULE( FT_Renderer_Class, ft_sdf_renderer_class )
 FT_USE_MODULE( FT_Renderer_Class, ft_bitmap_sdf_renderer_class )
-FT_USE_MODULE( FT_Renderer_Class, ft_svg_renderer_class )
-
+FT_USE_MODULE( FT_Module_Class, psaux_module_class )
+FT_USE_MODULE( FT_Module_Class, psnames_module_class )
 /* EOF */
diff --git a/vendor/freetype/include/freetype/config/ftoption.h b/vendor/freetype/include/freetype/config/ftoption.h
index 1976b33af9..1d347a4d42 100644
--- a/vendor/freetype/include/freetype/config/ftoption.h
+++ b/vendor/freetype/include/freetype/config/ftoption.h
@@ -4,7 +4,7 @@
  *
  *   User-selectable configuration macros (specification only).
  *
- * Copyright (C) 1996-2023 by
+ * Copyright (C) 1996-2024 by
  * David Turner, Robert Wilhelm, and Werner Lemberg.
  *
  * This file is part of the FreeType project, and may only be used,
@@ -273,7 +273,7 @@ FT_BEGIN_HEADER
    *   options set by those programs have precedence, overwriting the value
    *   here with the configured one.
    */
-/* #define FT_CONFIG_OPTION_USE_PNG */
+/* #define FT_CONFIG_OPTION_USE_PNG
 
 
   /**************************************************************************
@@ -757,6 +757,22 @@ FT_BEGIN_HEADER
 #endif
 
 
+  /**************************************************************************
+   *
+   * Option `TT_CONFIG_OPTION_GPOS_KERNING` enables a basic GPOS kerning
+   * implementation (for TrueType fonts only).  With this defined, FreeType
+   * is able to get kerning pair data from the GPOS 'kern' feature as well as
+   * legacy 'kern' tables; without this defined, FreeType will only be able
+   * to use legacy 'kern' tables.
+   *
+   * Note that FreeType does not support more advanced GPOS layout features;
+   * even the 'kern' feature implemented here doesn't handle more
+   * sophisticated kerning variants.  Use a higher-level library like
+   * HarfBuzz instead for that.
+   */
+/* #define TT_CONFIG_OPTION_GPOS_KERNING */
+
+
   /*************************************************************************/
   /*************************************************************************/
   /****                                                                 ****/
diff --git a/vendor/freetype/include/freetype/config/ftstdlib.h b/vendor/freetype/include/freetype/config/ftstdlib.h
index f65148a902..e17aa7b89d 100644
--- a/vendor/freetype/include/freetype/config/ftstdlib.h
+++ b/vendor/freetype/include/freetype/config/ftstdlib.h
@@ -5,7 +5,7 @@
  *   ANSI-specific library and header configuration file (specification
  *   only).
  *
- * Copyright (C) 2002-2023 by
+ * Copyright (C) 2002-2024 by
  * David Turner, Robert Wilhelm, and Werner Lemberg.
  *
  * This file is part of the FreeType project, and may only be used,
diff --git a/vendor/freetype/include/freetype/config/integer-types.h b/vendor/freetype/include/freetype/config/integer-types.h
index 7258b50854..c27505ffc4 100644
--- a/vendor/freetype/include/freetype/config/integer-types.h
+++ b/vendor/freetype/include/freetype/config/integer-types.h
@@ -4,7 +4,7 @@
  *
  *   FreeType integer types definitions.
  *
- * Copyright (C) 1996-2023 by
+ * Copyright (C) 1996-2024 by
  * David Turner, Robert Wilhelm, and Werner Lemberg.
  *
  * This file is part of the FreeType project, and may only be used,
diff --git a/vendor/freetype/include/freetype/config/mac-support.h b/vendor/freetype/include/freetype/config/mac-support.h
index b77b96d5db..07b6f915bd 100644
--- a/vendor/freetype/include/freetype/config/mac-support.h
+++ b/vendor/freetype/include/freetype/config/mac-support.h
@@ -4,7 +4,7 @@
  *
  *   Mac/OS X support configuration header.
  *
- * Copyright (C) 1996-2023 by
+ * Copyright (C) 1996-2024 by
  * David Turner, Robert Wilhelm, and Werner Lemberg.
  *
  * This file is part of the FreeType project, and may only be used,
diff --git a/vendor/freetype/include/freetype/config/public-macros.h b/vendor/freetype/include/freetype/config/public-macros.h
index 23d0fa6a32..f56581a6ee 100644
--- a/vendor/freetype/include/freetype/config/public-macros.h
+++ b/vendor/freetype/include/freetype/config/public-macros.h
@@ -4,7 +4,7 @@
  *
  *   Define a set of compiler macros used in public FreeType headers.
  *
- * Copyright (C) 2020-2023 by
+ * Copyright (C) 2020-2024 by
  * David Turner, Robert Wilhelm, and Werner Lemberg.
  *
  * This file is part of the FreeType project, and may only be used,
diff --git a/vendor/freetype/include/freetype/freetype.h b/vendor/freetype/include/freetype/freetype.h
index 92acf3794a..b88ccc6084 100644
--- a/vendor/freetype/include/freetype/freetype.h
+++ b/vendor/freetype/include/freetype/freetype.h
@@ -4,7 +4,7 @@
  *
  *   FreeType high-level API and common types (specification only).
  *
- * Copyright (C) 1996-2023 by
+ * Copyright (C) 1996-2024 by
  * David Turner, Robert Wilhelm, and Werner Lemberg.
  *
  * This file is part of the FreeType project, and may only be used,
@@ -1322,9 +1322,13 @@ FT_BEGIN_HEADER
    *   FT_FACE_FLAG_KERNING ::
    *     The face contains kerning information.  If set, the kerning distance
    *     can be retrieved using the function @FT_Get_Kerning.  Otherwise the
-   *     function always returns the vector (0,0).  Note that FreeType
-   *     doesn't handle kerning data from the SFNT 'GPOS' table (as present
-   *     in many OpenType fonts).
+   *     function always returns the vector (0,0).
+   *
+   *     Note that for TrueType fonts only, FreeType supports both the 'kern'
+   *     table and the basic, pair-wise kerning feature from the 'GPOS' table
+   *     (with `TT_CONFIG_OPTION_GPOS_KERNING` enabled), though FreeType does
+   *     not support the more advanced GPOS layout features; use a library
+   *     like HarfBuzz for those instead.
    *
    *   FT_FACE_FLAG_FAST_GLYPHS ::
    *     THIS FLAG IS DEPRECATED.  DO NOT USE OR TEST IT.
@@ -3767,87 +3771,18 @@ FT_BEGIN_HEADER
    *     pixels and use the @FT_PIXEL_MODE_LCD_V mode.
    *
    *   FT_RENDER_MODE_SDF ::
-   *     This mode corresponds to 8-bit, single-channel signed distance field
-   *     (SDF) bitmaps.  Each pixel in the SDF grid is the value from the
-   *     pixel's position to the nearest glyph's outline.  The distances are
-   *     calculated from the center of the pixel and are positive if they are
-   *     filled by the outline (i.e., inside the outline) and negative
-   *     otherwise.  Check the note below on how to convert the output values
-   *     to usable data.
+   *     The positive (unsigned) 8-bit bitmap values can be converted to the
+   *     single-channel signed distance field (SDF) by subtracting 128, with
+   *     the positive and negative results corresponding to the inside and
+   *     the outside of a glyph contour, respectively.  The distance units are
+   *     arbitrarily determined by an adjustable @spread property.
    *
    * @note:
-   *   The selected render mode only affects vector glyphs of a font.
+   *   The selected render mode only affects scalable vector glyphs of a font.
    *   Embedded bitmaps often have a different pixel mode like
    *   @FT_PIXEL_MODE_MONO.  You can use @FT_Bitmap_Convert to transform them
    *   into 8-bit pixmaps.
    *
-   *   For @FT_RENDER_MODE_SDF the output bitmap buffer contains normalized
-   *   distances that are packed into unsigned 8-bit values.  To get pixel
-   *   values in floating point representation use the following pseudo-C
-   *   code for the conversion.
-   *
-   *   ```
-   *   // Load glyph and render using FT_RENDER_MODE_SDF,
-   *   // then use the output buffer as follows.
-   *
-   *   ...
-   *   FT_Byte  buffer = glyph->bitmap->buffer;
-   *
-   *
-   *   for pixel in buffer
-   *   {
-   *     // `sd` is the signed distance and `spread` is the current spread;
-   *     // the default spread is 2 and can be changed.
-   *
-   *     float  sd = (float)pixel - 128.0f;
-   *
-   *
-   *     // Convert to pixel values.
-   *     sd = ( sd / 128.0f ) * spread;
-   *
-   *     // Store `sd` in a buffer or use as required.
-   *   }
-   *
-   *   ```
-   *
-   *   FreeType has two rasterizers for generating SDF, namely:
-   *
-   *   1. `sdf` for generating SDF directly from glyph's outline, and
-   *
-   *   2. `bsdf` for generating SDF from rasterized bitmaps.
-   *
-   *   Depending on the glyph type (i.e., outline or bitmap), one of the two
-   *   rasterizers is chosen at runtime and used for generating SDFs.  To
-   *   force the use of `bsdf` you should render the glyph with any of the
-   *   FreeType's other rendering modes (e.g., `FT_RENDER_MODE_NORMAL`) and
-   *   then re-render with `FT_RENDER_MODE_SDF`.
-   *
-   *   There are some issues with stability and possible failures of the SDF
-   *   renderers (specifically `sdf`).
-   *
-   *   1. The `sdf` rasterizer is sensitive to really small features (e.g.,
-   *      sharp turns that are less than 1~pixel) and imperfections in the
-   *      glyph's outline, causing artifacts in the final output.
-   *
-   *   2. The `sdf` rasterizer has limited support for handling intersecting
-   *      contours and *cannot* handle self-intersecting contours whatsoever.
-   *      Self-intersection happens when a single connected contour
-   *      intersects itself at some point; having these in your font
-   *      definitely poses a problem to the rasterizer and cause artifacts,
-   *      too.
-   *
-   *   3. Generating SDF for really small glyphs may result in undesirable
-   *      output; the pixel grid (which stores distance information) becomes
-   *      too coarse.
-   *
-   *   4. Since the output buffer is normalized, precision at smaller spreads
-   *      is greater than precision at larger spread values because the
-   *      output range of [0..255] gets mapped to a smaller SDF range.  A
-   *      spread of~2 should be sufficient in most cases.
-   *
-   *   Points (1) and (2) can be avoided by using the `bsdf` rasterizer,
-   *   which is more stable than the `sdf` rasterizer in general.
-   *
    */
   typedef enum  FT_Render_Mode_
   {
@@ -4058,9 +3993,26 @@ FT_BEGIN_HEADER
    *   out of the scope of this API function -- they can be implemented
    *   through format-specific interfaces.
    *
-   *   Kerning for OpenType fonts implemented in a 'GPOS' table is not
-   *   supported; use @FT_HAS_KERNING to find out whether a font has data
-   *   that can be extracted with `FT_Get_Kerning`.
+   *   Note that, for TrueType fonts only, this can extract data from both
+   *   the 'kern' table and the basic, pair-wise kerning feature from the
+   *   GPOS table (with `TT_CONFIG_OPTION_GPOS_KERNING` enabled), though
+   *   FreeType does not support the more advanced GPOS layout features; use
+   *   a library like HarfBuzz for those instead.  If a font has both a
+   *   'kern' table and kern features of a GPOS table, the 'kern' table will
+   *   be used.
+   *
+   *   Also note for right-to-left scripts, the functionality may differ for
+   *   fonts with GPOS tables vs. 'kern' tables.  For GPOS, right-to-left
+   *   fonts typically use both a placement offset and an advance for pair
+   *   positioning, which this API does not support, so it would output
+   *   kerning values of zero; though if the right-to-left font used only
+   *   advances in GPOS pair positioning, then this API could output kerning
+   *   values for it, but it would use `left_glyph` to mean the first glyph
+   *   for that case.  Whereas 'kern' tables are always advance-only and
+   *   always store the left glyph first.
+   *
+   *   Use @FT_HAS_KERNING to find out whether a font has data that can be
+   *   extracted with `FT_Get_Kerning`.
    */
   FT_EXPORT( FT_Error )
   FT_Get_Kerning( FT_Face     face,
diff --git a/vendor/freetype/include/freetype/ftadvanc.h b/vendor/freetype/include/freetype/ftadvanc.h
index 4560ded6dc..85b8ba2554 100644
--- a/vendor/freetype/include/freetype/ftadvanc.h
+++ b/vendor/freetype/include/freetype/ftadvanc.h
@@ -4,7 +4,7 @@
  *
  *   Quick computation of advance widths (specification only).
  *
- * Copyright (C) 2008-2023 by
+ * Copyright (C) 2008-2024 by
  * David Turner, Robert Wilhelm, and Werner Lemberg.
  *
  * This file is part of the FreeType project, and may only be used,
diff --git a/vendor/freetype/include/freetype/ftbbox.h b/vendor/freetype/include/freetype/ftbbox.h
index fc21740fc2..12bbfa63a6 100644
--- a/vendor/freetype/include/freetype/ftbbox.h
+++ b/vendor/freetype/include/freetype/ftbbox.h
@@ -4,7 +4,7 @@
  *
  *   FreeType exact bbox computation (specification).
  *
- * Copyright (C) 1996-2023 by
+ * Copyright (C) 1996-2024 by
  * David Turner, Robert Wilhelm, and Werner Lemberg.
  *
  * This file is part of the FreeType project, and may only be used,
diff --git a/vendor/freetype/include/freetype/ftbdf.h b/vendor/freetype/include/freetype/ftbdf.h
index e8ce643128..6f63b0b1e7 100644
--- a/vendor/freetype/include/freetype/ftbdf.h
+++ b/vendor/freetype/include/freetype/ftbdf.h
@@ -4,7 +4,7 @@
  *
  *   FreeType API for accessing BDF-specific strings (specification).
  *
- * Copyright (C) 2002-2023 by
+ * Copyright (C) 2002-2024 by
  * David Turner, Robert Wilhelm, and Werner Lemberg.
  *
  * This file is part of the FreeType project, and may only be used,
diff --git a/vendor/freetype/include/freetype/ftbitmap.h b/vendor/freetype/include/freetype/ftbitmap.h
index eb6b4b1eeb..df9d462652 100644
--- a/vendor/freetype/include/freetype/ftbitmap.h
+++ b/vendor/freetype/include/freetype/ftbitmap.h
@@ -4,7 +4,7 @@
  *
  *   FreeType utility functions for bitmaps (specification).
  *
- * Copyright (C) 2004-2023 by
+ * Copyright (C) 2004-2024 by
  * David Turner, Robert Wilhelm, and Werner Lemberg.
  *
  * This file is part of the FreeType project, and may only be used,
diff --git a/vendor/freetype/include/freetype/ftbzip2.h b/vendor/freetype/include/freetype/ftbzip2.h
index 7d29f4682c..c5baea8562 100644
--- a/vendor/freetype/include/freetype/ftbzip2.h
+++ b/vendor/freetype/include/freetype/ftbzip2.h
@@ -4,7 +4,7 @@
  *
  *   Bzip2-compressed stream support.
  *
- * Copyright (C) 2010-2023 by
+ * Copyright (C) 2010-2024 by
  * Joel Klinghed.
  *
  * This file is part of the FreeType project, and may only be used,
diff --git a/vendor/freetype/include/freetype/ftcache.h b/vendor/freetype/include/freetype/ftcache.h
index a2072e26b8..140df4c96c 100644
--- a/vendor/freetype/include/freetype/ftcache.h
+++ b/vendor/freetype/include/freetype/ftcache.h
@@ -4,7 +4,7 @@
  *
  *   FreeType Cache subsystem (specification).
  *
- * Copyright (C) 1996-2023 by
+ * Copyright (C) 1996-2024 by
  * David Turner, Robert Wilhelm, and Werner Lemberg.
  *
  * This file is part of the FreeType project, and may only be used,
diff --git a/vendor/freetype/include/freetype/ftcid.h b/vendor/freetype/include/freetype/ftcid.h
index ef22939022..96b2a90fc5 100644
--- a/vendor/freetype/include/freetype/ftcid.h
+++ b/vendor/freetype/include/freetype/ftcid.h
@@ -4,7 +4,7 @@
  *
  *   FreeType API for accessing CID font information (specification).
  *
- * Copyright (C) 2007-2023 by
+ * Copyright (C) 2007-2024 by
  * Dereg Clegg and Michael Toftdal.
  *
  * This file is part of the FreeType project, and may only be used,
diff --git a/vendor/freetype/include/freetype/ftcolor.h b/vendor/freetype/include/freetype/ftcolor.h
index eae200fdf1..420720ddf2 100644
--- a/vendor/freetype/include/freetype/ftcolor.h
+++ b/vendor/freetype/include/freetype/ftcolor.h
@@ -4,7 +4,7 @@
  *
  *   FreeType's glyph color management (specification).
  *
- * Copyright (C) 2018-2023 by
+ * Copyright (C) 2018-2024 by
  * David Turner, Robert Wilhelm, and Werner Lemberg.
  *
  * This file is part of the FreeType project, and may only be used,
diff --git a/vendor/freetype/include/freetype/ftdriver.h b/vendor/freetype/include/freetype/ftdriver.h
index 7af7465bc7..dd31626b03 100644
--- a/vendor/freetype/include/freetype/ftdriver.h
+++ b/vendor/freetype/include/freetype/ftdriver.h
@@ -4,7 +4,7 @@
  *
  *   FreeType API for controlling driver modules (specification only).
  *
- * Copyright (C) 2017-2023 by
+ * Copyright (C) 2017-2024 by
  * David Turner, Robert Wilhelm, and Werner Lemberg.
  *
  * This file is part of the FreeType project, and may only be used,
@@ -817,6 +817,80 @@ FT_BEGIN_HEADER
    *   2.5
    */
 
+
+  /**************************************************************************
+   *
+   * @property:
+   *   spread
+   *
+   * @description:
+   *   This property of the 'sdf' and 'bsdf' renderers defines how the signed
+   *   distance field (SDF) is represented in the output bitmap.  The output
+   *   values are calculated as follows, '128 * ( SDF / spread + 1 )', with
+   *   the result clamped to the 8-bit range [0..255].  Therefore, 'spread'
+   *   is also the maximum euclidean distance from the edge after which the
+   *   values are clamped.  The spread is specified in pixels with the
+   *   default value of 8.  For accurate SDF texture mapping (interpolation),
+   *   the spread should be large enough to accommodate the target grid unit.
+   *
+   * @example:
+   *   The following example code demonstrates how to set the SDF spread
+   *   (omitting the error handling).
+   *
+   *   ```
+   *     FT_Library  library;
+   *     FT_Int      spread = 2;
+   *
+   *
+   *     FT_Init_FreeType( &library );
+   *
+   *     FT_Property_Set( library, "sdf", "spread", &spread );
+   *   ```
+   *
+   * @note
+   *   FreeType has two rasterizers for generating SDF, namely:
+   *
+   *   1. `sdf` for generating SDF directly from glyph's outline, and
+   *
+   *   2. `bsdf` for generating SDF from rasterized bitmaps.
+   *
+   *   Depending on the glyph type (i.e., outline or bitmap), one of the two
+   *   rasterizers is chosen at runtime and used for generating SDFs.  To
+   *   force the use of `bsdf` you should render the glyph with any of the
+   *   FreeType's other rendering modes (e.g., `FT_RENDER_MODE_NORMAL`) and
+   *   then re-render with `FT_RENDER_MODE_SDF`.
+   *
+   *   There are some issues with stability and possible failures of the SDF
+   *   renderers (specifically `sdf`).
+   *
+   *   1. The `sdf` rasterizer is sensitive to really small features (e.g.,
+   *      sharp turns that are less than 1~pixel) and imperfections in the
+   *      glyph's outline, causing artifacts in the final output.
+   *
+   *   2. The `sdf` rasterizer has limited support for handling intersecting
+   *      contours and *cannot* handle self-intersecting contours whatsoever.
+   *      Self-intersection happens when a single connected contour
+   *      intersects itself at some point; having these in your font
+   *      definitely poses a problem to the rasterizer and cause artifacts,
+   *      too.
+   *
+   *   3. Generating SDF for really small glyphs may result in undesirable
+   *      output; the pixel grid (which stores distance information) becomes
+   *      too coarse.
+   *
+   *   4. Since the output buffer is normalized, precision at smaller spreads
+   *      is greater than precision at larger spread values because the
+   *      output range of [0..255] gets mapped to a smaller SDF range.  A
+   *      spread of~2 should be sufficient in most cases.
+   *
+   *   Points (1) and (2) can be avoided by using the `bsdf` rasterizer,
+   *   which is more stable than the `sdf` rasterizer in general.
+   *
+   * @since:
+   *   2.11
+   */
+
+
   /**************************************************************************
    *
    * @property:
diff --git a/vendor/freetype/include/freetype/fterrdef.h b/vendor/freetype/include/freetype/fterrdef.h
index d59b3cc2da..710ca91bbd 100644
--- a/vendor/freetype/include/freetype/fterrdef.h
+++ b/vendor/freetype/include/freetype/fterrdef.h
@@ -4,7 +4,7 @@
  *
  *   FreeType error codes (specification).
  *
- * Copyright (C) 2002-2023 by
+ * Copyright (C) 2002-2024 by
  * David Turner, Robert Wilhelm, and Werner Lemberg.
  *
  * This file is part of the FreeType project, and may only be used,
diff --git a/vendor/freetype/include/freetype/fterrors.h b/vendor/freetype/include/freetype/fterrors.h
index 15ef3f76b5..27c0ece5c1 100644
--- a/vendor/freetype/include/freetype/fterrors.h
+++ b/vendor/freetype/include/freetype/fterrors.h
@@ -4,7 +4,7 @@
  *
  *   FreeType error code handling (specification).
  *
- * Copyright (C) 1996-2023 by
+ * Copyright (C) 1996-2024 by
  * David Turner, Robert Wilhelm, and Werner Lemberg.
  *
  * This file is part of the FreeType project, and may only be used,
diff --git a/vendor/freetype/include/freetype/ftfntfmt.h b/vendor/freetype/include/freetype/ftfntfmt.h
index c0018fc830..7c8b0874a8 100644
--- a/vendor/freetype/include/freetype/ftfntfmt.h
+++ b/vendor/freetype/include/freetype/ftfntfmt.h
@@ -4,7 +4,7 @@
  *
  *   Support functions for font formats.
  *
- * Copyright (C) 2002-2023 by
+ * Copyright (C) 2002-2024 by
  * David Turner, Robert Wilhelm, and Werner Lemberg.
  *
  * This file is part of the FreeType project, and may only be used,
diff --git a/vendor/freetype/include/freetype/ftgasp.h b/vendor/freetype/include/freetype/ftgasp.h
index d5f19add8f..30e5a9bf82 100644
--- a/vendor/freetype/include/freetype/ftgasp.h
+++ b/vendor/freetype/include/freetype/ftgasp.h
@@ -4,7 +4,7 @@
  *
  *   Access of TrueType's 'gasp' table (specification).
  *
- * Copyright (C) 2007-2023 by
+ * Copyright (C) 2007-2024 by
  * David Turner, Robert Wilhelm, and Werner Lemberg.
  *
  * This file is part of the FreeType project, and may only be used,
diff --git a/vendor/freetype/include/freetype/ftglyph.h b/vendor/freetype/include/freetype/ftglyph.h
index 4658895f7a..dc1eb8873a 100644
--- a/vendor/freetype/include/freetype/ftglyph.h
+++ b/vendor/freetype/include/freetype/ftglyph.h
@@ -4,7 +4,7 @@
  *
  *   FreeType convenience functions to handle glyphs (specification).
  *
- * Copyright (C) 1996-2023 by
+ * Copyright (C) 1996-2024 by
  * David Turner, Robert Wilhelm, and Werner Lemberg.
  *
  * This file is part of the FreeType project, and may only be used,
diff --git a/vendor/freetype/include/freetype/ftgxval.h b/vendor/freetype/include/freetype/ftgxval.h
index e8de9a6ed5..065cd53cc5 100644
--- a/vendor/freetype/include/freetype/ftgxval.h
+++ b/vendor/freetype/include/freetype/ftgxval.h
@@ -4,7 +4,7 @@
  *
  *   FreeType API for validating TrueTypeGX/AAT tables (specification).
  *
- * Copyright (C) 2004-2023 by
+ * Copyright (C) 2004-2024 by
  * Masatake YAMATO, Redhat K.K,
  * David Turner, Robert Wilhelm, and Werner Lemberg.
  *
diff --git a/vendor/freetype/include/freetype/ftgzip.h b/vendor/freetype/include/freetype/ftgzip.h
index 443ec29db1..9516dc030a 100644
--- a/vendor/freetype/include/freetype/ftgzip.h
+++ b/vendor/freetype/include/freetype/ftgzip.h
@@ -4,7 +4,7 @@
  *
  *   Gzip-compressed stream support.
  *
- * Copyright (C) 2002-2023 by
+ * Copyright (C) 2002-2024 by
  * David Turner, Robert Wilhelm, and Werner Lemberg.
  *
  * This file is part of the FreeType project, and may only be used,
diff --git a/vendor/freetype/include/freetype/ftimage.h b/vendor/freetype/include/freetype/ftimage.h
index 6baa812560..6c7085f616 100644
--- a/vendor/freetype/include/freetype/ftimage.h
+++ b/vendor/freetype/include/freetype/ftimage.h
@@ -5,7 +5,7 @@
  *   FreeType glyph image formats and default raster interface
  *   (specification).
  *
- * Copyright (C) 1996-2023 by
+ * Copyright (C) 1996-2024 by
  * David Turner, Robert Wilhelm, and Werner Lemberg.
  *
  * This file is part of the FreeType project, and may only be used,
@@ -21,6 +21,10 @@
    * Note: A 'raster' is simply a scan-line converter, used to render
    *       `FT_Outline`s into `FT_Bitmap`s.
    *
+   * Note: This file can be used for STANDALONE_ compilation of raster (B/W)
+   *       and smooth (anti-aliased) renderers.  Therefore, it must rely on
+   *       standard variable types only rather than aliases in fttypes.h.
+   *
    */
 
 
@@ -318,7 +322,7 @@ FT_BEGIN_HEADER
    *
    *     If bit~2 is set, bits 5-7 contain the drop-out mode (as defined in
    *     the OpenType specification; the value is the same as the argument to
-   *     the 'SCANMODE' instruction).
+   *     the 'SCANTYPE' instruction).
    *
    *     Bits 3 and~4 are reserved for internal purposes.
    *
@@ -341,14 +345,14 @@ FT_BEGIN_HEADER
    */
   typedef struct  FT_Outline_
   {
-    short       n_contours;      /* number of contours in glyph        */
-    short       n_points;        /* number of points in the glyph      */
+    unsigned short   n_contours;  /* number of contours in glyph        */
+    unsigned short   n_points;    /* number of points in the glyph      */
 
-    FT_Vector*  points;          /* the outline's points               */
-    char*       tags;            /* the points flags                   */
-    short*      contours;        /* the contour end points             */
+    FT_Vector*       points;      /* the outline's points               */
+    unsigned char*   tags;        /* the points flags                   */
+    unsigned short*  contours;    /* the contour end points             */
 
-    int         flags;           /* outline masks                      */
+    int              flags;       /* outline masks                      */
 
   } FT_Outline;
 
@@ -356,8 +360,8 @@ FT_BEGIN_HEADER
 
   /* Following limits must be consistent with */
   /* FT_Outline.{n_contours,n_points}         */
-#define FT_OUTLINE_CONTOURS_MAX  SHRT_MAX
-#define FT_OUTLINE_POINTS_MAX    SHRT_MAX
+#define FT_OUTLINE_CONTOURS_MAX  USHRT_MAX
+#define FT_OUTLINE_POINTS_MAX    USHRT_MAX
 
 
   /**************************************************************************
@@ -434,8 +438,8 @@ FT_BEGIN_HEADER
    *   rasterizer; see the `tags` field in @FT_Outline.
    *
    *   Please refer to the description of the 'SCANTYPE' instruction in the
-   *   OpenType specification (in file `ttinst1.doc`) how simple drop-outs,
-   *   smart drop-outs, and stubs are defined.
+   *   [OpenType specification](https://learn.microsoft.com/en-us/typography/opentype/spec/tt_instructions#scantype)
+   *   how simple drop-outs, smart drop-outs, and stubs are defined.
    */
 #define FT_OUTLINE_NONE             0x0
 #define FT_OUTLINE_OWNER            0x1
diff --git a/vendor/freetype/include/freetype/ftincrem.h b/vendor/freetype/include/freetype/ftincrem.h
index 2d4f5def24..816581b78e 100644
--- a/vendor/freetype/include/freetype/ftincrem.h
+++ b/vendor/freetype/include/freetype/ftincrem.h
@@ -4,7 +4,7 @@
  *
  *   FreeType incremental loading (specification).
  *
- * Copyright (C) 2002-2023 by
+ * Copyright (C) 2002-2024 by
  * David Turner, Robert Wilhelm, and Werner Lemberg.
  *
  * This file is part of the FreeType project, and may only be used,
diff --git a/vendor/freetype/include/freetype/ftlcdfil.h b/vendor/freetype/include/freetype/ftlcdfil.h
index d3723e16f6..25274dc4ac 100644
--- a/vendor/freetype/include/freetype/ftlcdfil.h
+++ b/vendor/freetype/include/freetype/ftlcdfil.h
@@ -5,7 +5,7 @@
  *   FreeType API for color filtering of subpixel bitmap glyphs
  *   (specification).
  *
- * Copyright (C) 2006-2023 by
+ * Copyright (C) 2006-2024 by
  * David Turner, Robert Wilhelm, and Werner Lemberg.
  *
  * This file is part of the FreeType project, and may only be used,
diff --git a/vendor/freetype/include/freetype/ftlist.h b/vendor/freetype/include/freetype/ftlist.h
index b553131335..972fbfa2fe 100644
--- a/vendor/freetype/include/freetype/ftlist.h
+++ b/vendor/freetype/include/freetype/ftlist.h
@@ -4,7 +4,7 @@
  *
  *   Generic list support for FreeType (specification).
  *
- * Copyright (C) 1996-2023 by
+ * Copyright (C) 1996-2024 by
  * David Turner, Robert Wilhelm, and Werner Lemberg.
  *
  * This file is part of the FreeType project, and may only be used,
diff --git a/vendor/freetype/include/freetype/ftlogging.h b/vendor/freetype/include/freetype/ftlogging.h
index 53b8b89642..1813cfc2c2 100644
--- a/vendor/freetype/include/freetype/ftlogging.h
+++ b/vendor/freetype/include/freetype/ftlogging.h
@@ -4,7 +4,7 @@
  *
  *   Additional debugging APIs.
  *
- * Copyright (C) 2020-2023 by
+ * Copyright (C) 2020-2024 by
  * David Turner, Robert Wilhelm, and Werner Lemberg.
  *
  * This file is part of the FreeType project, and may only be used,
diff --git a/vendor/freetype/include/freetype/ftlzw.h b/vendor/freetype/include/freetype/ftlzw.h
index adfd172479..bcf59ba706 100644
--- a/vendor/freetype/include/freetype/ftlzw.h
+++ b/vendor/freetype/include/freetype/ftlzw.h
@@ -4,7 +4,7 @@
  *
  *   LZW-compressed stream support.
  *
- * Copyright (C) 2004-2023 by
+ * Copyright (C) 2004-2024 by
  * David Turner, Robert Wilhelm, and Werner Lemberg.
  *
  * This file is part of the FreeType project, and may only be used,
diff --git a/vendor/freetype/include/freetype/ftmac.h b/vendor/freetype/include/freetype/ftmac.h
index a91e38f9ea..e4efde33dd 100644
--- a/vendor/freetype/include/freetype/ftmac.h
+++ b/vendor/freetype/include/freetype/ftmac.h
@@ -4,7 +4,7 @@
  *
  *   Additional Mac-specific API.
  *
- * Copyright (C) 1996-2023 by
+ * Copyright (C) 1996-2024 by
  * Just van Rossum, David Turner, Robert Wilhelm, and Werner Lemberg.
  *
  * This file is part of the FreeType project, and may only be used,
diff --git a/vendor/freetype/include/freetype/ftmm.h b/vendor/freetype/include/freetype/ftmm.h
index d145128a9b..35ed039c89 100644
--- a/vendor/freetype/include/freetype/ftmm.h
+++ b/vendor/freetype/include/freetype/ftmm.h
@@ -4,7 +4,7 @@
  *
  *   FreeType Multiple Master font interface (specification).
  *
- * Copyright (C) 1996-2023 by
+ * Copyright (C) 1996-2024 by
  * David Turner, Robert Wilhelm, and Werner Lemberg.
  *
  * This file is part of the FreeType project, and may only be used,
@@ -19,8 +19,13 @@
 #ifndef FTMM_H_
 #define FTMM_H_
 
+#include 
 
-#include 
+#ifdef FREETYPE_H
+#error "freetype.h of FreeType 1 has been loaded!"
+#error "Please fix the directory search order for header files"
+#error "so that freetype.h of FreeType 2 is found first."
+#endif
 
 
 FT_BEGIN_HEADER
@@ -53,6 +58,30 @@ FT_BEGIN_HEADER
    */
 
 
+  /**************************************************************************
+   *
+   * @enum:
+   *   T1_MAX_MM_XXX
+   *
+   * @description:
+   *   Multiple Masters limits as defined in their specifications.
+   *
+   * @values:
+   *   T1_MAX_MM_AXIS ::
+   *     The maximum number of Multiple Masters axes.
+   *
+   *   T1_MAX_MM_DESIGNS ::
+   *     The maximum number of Multiple Masters designs.
+   *
+   *   T1_MAX_MM_MAP_POINTS ::
+   *     The maximum number of elements in a design map.
+   *
+   */
+#define T1_MAX_MM_AXIS         4
+#define T1_MAX_MM_DESIGNS     16
+#define T1_MAX_MM_MAP_POINTS  20
+
+
   /**************************************************************************
    *
    * @struct:
diff --git a/vendor/freetype/include/freetype/ftmodapi.h b/vendor/freetype/include/freetype/ftmodapi.h
index c8f0c2c2a4..0ee715898f 100644
--- a/vendor/freetype/include/freetype/ftmodapi.h
+++ b/vendor/freetype/include/freetype/ftmodapi.h
@@ -4,7 +4,7 @@
  *
  *   FreeType modules public interface (specification).
  *
- * Copyright (C) 1996-2023 by
+ * Copyright (C) 1996-2024 by
  * David Turner, Robert Wilhelm, and Werner Lemberg.
  *
  * This file is part of the FreeType project, and may only be used,
diff --git a/vendor/freetype/include/freetype/ftmoderr.h b/vendor/freetype/include/freetype/ftmoderr.h
index c8c892dcce..6722fbf8b7 100644
--- a/vendor/freetype/include/freetype/ftmoderr.h
+++ b/vendor/freetype/include/freetype/ftmoderr.h
@@ -4,7 +4,7 @@
  *
  *   FreeType module error offsets (specification).
  *
- * Copyright (C) 2001-2023 by
+ * Copyright (C) 2001-2024 by
  * David Turner, Robert Wilhelm, and Werner Lemberg.
  *
  * This file is part of the FreeType project, and may only be used,
diff --git a/vendor/freetype/include/freetype/ftotval.h b/vendor/freetype/include/freetype/ftotval.h
index 011bdfc837..810200b386 100644
--- a/vendor/freetype/include/freetype/ftotval.h
+++ b/vendor/freetype/include/freetype/ftotval.h
@@ -4,7 +4,7 @@
  *
  *   FreeType API for validating OpenType tables (specification).
  *
- * Copyright (C) 2004-2023 by
+ * Copyright (C) 2004-2024 by
  * David Turner, Robert Wilhelm, and Werner Lemberg.
  *
  * This file is part of the FreeType project, and may only be used,
diff --git a/vendor/freetype/include/freetype/ftoutln.h b/vendor/freetype/include/freetype/ftoutln.h
index f9329ca40c..44e94b4f5b 100644
--- a/vendor/freetype/include/freetype/ftoutln.h
+++ b/vendor/freetype/include/freetype/ftoutln.h
@@ -5,7 +5,7 @@
  *   Support for the FT_Outline type used to store glyph shapes of
  *   most scalable font formats (specification).
  *
- * Copyright (C) 1996-2023 by
+ * Copyright (C) 1996-2024 by
  * David Turner, Robert Wilhelm, and Werner Lemberg.
  *
  * This file is part of the FreeType project, and may only be used,
@@ -112,7 +112,7 @@ FT_BEGIN_HEADER
    *   Degenerate contours, segments, and Bezier arcs may be reported.  In
    *   most cases, it is best to filter these out before using the outline
    *   for stroking or other path modification purposes (which may cause
-   *   degenerate segments to become non-degenrate and visible, like when
+   *   degenerate segments to become non-degenerate and visible, like when
    *   stroke caps are used or the path is otherwise outset).  Some glyph
    *   outlines may contain deliberate degenerate single points for mark
    *   attachement.
diff --git a/vendor/freetype/include/freetype/ftparams.h b/vendor/freetype/include/freetype/ftparams.h
index 6a9f243bc9..43bf69c202 100644
--- a/vendor/freetype/include/freetype/ftparams.h
+++ b/vendor/freetype/include/freetype/ftparams.h
@@ -4,7 +4,7 @@
  *
  *   FreeType API for possible FT_Parameter tags (specification only).
  *
- * Copyright (C) 2017-2023 by
+ * Copyright (C) 2017-2024 by
  * David Turner, Robert Wilhelm, and Werner Lemberg.
  *
  * This file is part of the FreeType project, and may only be used,
diff --git a/vendor/freetype/include/freetype/ftpfr.h b/vendor/freetype/include/freetype/ftpfr.h
index 7111d40a0c..1a712b9552 100644
--- a/vendor/freetype/include/freetype/ftpfr.h
+++ b/vendor/freetype/include/freetype/ftpfr.h
@@ -4,7 +4,7 @@
  *
  *   FreeType API for accessing PFR-specific data (specification only).
  *
- * Copyright (C) 2002-2023 by
+ * Copyright (C) 2002-2024 by
  * David Turner, Robert Wilhelm, and Werner Lemberg.
  *
  * This file is part of the FreeType project, and may only be used,
diff --git a/vendor/freetype/include/freetype/ftrender.h b/vendor/freetype/include/freetype/ftrender.h
index 0b6fad32e8..dc5018a1b5 100644
--- a/vendor/freetype/include/freetype/ftrender.h
+++ b/vendor/freetype/include/freetype/ftrender.h
@@ -4,7 +4,7 @@
  *
  *   FreeType renderer modules public interface (specification).
  *
- * Copyright (C) 1996-2023 by
+ * Copyright (C) 1996-2024 by
  * David Turner, Robert Wilhelm, and Werner Lemberg.
  *
  * This file is part of the FreeType project, and may only be used,
diff --git a/vendor/freetype/include/freetype/ftsizes.h b/vendor/freetype/include/freetype/ftsizes.h
index 7bfb1aed4c..4ef5c7955d 100644
--- a/vendor/freetype/include/freetype/ftsizes.h
+++ b/vendor/freetype/include/freetype/ftsizes.h
@@ -4,7 +4,7 @@
  *
  *   FreeType size objects management (specification).
  *
- * Copyright (C) 1996-2023 by
+ * Copyright (C) 1996-2024 by
  * David Turner, Robert Wilhelm, and Werner Lemberg.
  *
  * This file is part of the FreeType project, and may only be used,
diff --git a/vendor/freetype/include/freetype/ftsnames.h b/vendor/freetype/include/freetype/ftsnames.h
index 9d5d22bb25..d5d5cd9310 100644
--- a/vendor/freetype/include/freetype/ftsnames.h
+++ b/vendor/freetype/include/freetype/ftsnames.h
@@ -7,7 +7,7 @@
  *
  *   This is _not_ used to retrieve glyph names!
  *
- * Copyright (C) 1996-2023 by
+ * Copyright (C) 1996-2024 by
  * David Turner, Robert Wilhelm, and Werner Lemberg.
  *
  * This file is part of the FreeType project, and may only be used,
diff --git a/vendor/freetype/include/freetype/ftstroke.h b/vendor/freetype/include/freetype/ftstroke.h
index b3d90802a5..41626dc9d7 100644
--- a/vendor/freetype/include/freetype/ftstroke.h
+++ b/vendor/freetype/include/freetype/ftstroke.h
@@ -4,7 +4,7 @@
  *
  *   FreeType path stroker (specification).
  *
- * Copyright (C) 2002-2023 by
+ * Copyright (C) 2002-2024 by
  * David Turner, Robert Wilhelm, and Werner Lemberg.
  *
  * This file is part of the FreeType project, and may only be used,
diff --git a/vendor/freetype/include/freetype/ftsynth.h b/vendor/freetype/include/freetype/ftsynth.h
index af90967dda..43081b6c33 100644
--- a/vendor/freetype/include/freetype/ftsynth.h
+++ b/vendor/freetype/include/freetype/ftsynth.h
@@ -5,7 +5,7 @@
  *   FreeType synthesizing code for emboldening and slanting
  *   (specification).
  *
- * Copyright (C) 2000-2023 by
+ * Copyright (C) 2000-2024 by
  * David Turner, Robert Wilhelm, and Werner Lemberg.
  *
  * This file is part of the FreeType project, and may only be used,
diff --git a/vendor/freetype/include/freetype/ftsystem.h b/vendor/freetype/include/freetype/ftsystem.h
index 3a08f4912c..1eacb3af39 100644
--- a/vendor/freetype/include/freetype/ftsystem.h
+++ b/vendor/freetype/include/freetype/ftsystem.h
@@ -4,7 +4,7 @@
  *
  *   FreeType low-level system interface definition (specification).
  *
- * Copyright (C) 1996-2023 by
+ * Copyright (C) 1996-2024 by
  * David Turner, Robert Wilhelm, and Werner Lemberg.
  *
  * This file is part of the FreeType project, and may only be used,
diff --git a/vendor/freetype/include/freetype/fttrigon.h b/vendor/freetype/include/freetype/fttrigon.h
index 294981a6f3..a5299e938d 100644
--- a/vendor/freetype/include/freetype/fttrigon.h
+++ b/vendor/freetype/include/freetype/fttrigon.h
@@ -4,7 +4,7 @@
  *
  *   FreeType trigonometric functions (specification).
  *
- * Copyright (C) 2001-2023 by
+ * Copyright (C) 2001-2024 by
  * David Turner, Robert Wilhelm, and Werner Lemberg.
  *
  * This file is part of the FreeType project, and may only be used,
diff --git a/vendor/freetype/include/freetype/fttypes.h b/vendor/freetype/include/freetype/fttypes.h
index 5b109f0c73..27815143a6 100644
--- a/vendor/freetype/include/freetype/fttypes.h
+++ b/vendor/freetype/include/freetype/fttypes.h
@@ -4,7 +4,7 @@
  *
  *   FreeType simple types definitions (specification only).
  *
- * Copyright (C) 1996-2023 by
+ * Copyright (C) 1996-2024 by
  * David Turner, Robert Wilhelm, and Werner Lemberg.
  *
  * This file is part of the FreeType project, and may only be used,
diff --git a/vendor/freetype/include/freetype/ftwinfnt.h b/vendor/freetype/include/freetype/ftwinfnt.h
index 7b701ea59b..2591e58866 100644
--- a/vendor/freetype/include/freetype/ftwinfnt.h
+++ b/vendor/freetype/include/freetype/ftwinfnt.h
@@ -4,7 +4,7 @@
  *
  *   FreeType API for accessing Windows fnt-specific data.
  *
- * Copyright (C) 2003-2023 by
+ * Copyright (C) 2003-2024 by
  * David Turner, Robert Wilhelm, and Werner Lemberg.
  *
  * This file is part of the FreeType project, and may only be used,
diff --git a/vendor/freetype/include/freetype/internal/autohint.h b/vendor/freetype/include/freetype/internal/autohint.h
index bf9c8b7cf2..8865d53b38 100644
--- a/vendor/freetype/include/freetype/internal/autohint.h
+++ b/vendor/freetype/include/freetype/internal/autohint.h
@@ -4,7 +4,7 @@
  *
  *   High-level 'autohint' module-specific interface (specification).
  *
- * Copyright (C) 1996-2023 by
+ * Copyright (C) 1996-2024 by
  * David Turner, Robert Wilhelm, and Werner Lemberg.
  *
  * This file is part of the FreeType project, and may only be used,
diff --git a/vendor/freetype/include/freetype/internal/cffotypes.h b/vendor/freetype/include/freetype/internal/cffotypes.h
index 50d5353849..36b0390a5a 100644
--- a/vendor/freetype/include/freetype/internal/cffotypes.h
+++ b/vendor/freetype/include/freetype/internal/cffotypes.h
@@ -4,7 +4,7 @@
  *
  *   Basic OpenType/CFF object type definitions (specification).
  *
- * Copyright (C) 2017-2023 by
+ * Copyright (C) 2017-2024 by
  * David Turner, Robert Wilhelm, and Werner Lemberg.
  *
  * This file is part of the FreeType project, and may only be used,
diff --git a/vendor/freetype/include/freetype/internal/cfftypes.h b/vendor/freetype/include/freetype/internal/cfftypes.h
index c2521764ca..ef2e8e7569 100644
--- a/vendor/freetype/include/freetype/internal/cfftypes.h
+++ b/vendor/freetype/include/freetype/internal/cfftypes.h
@@ -5,7 +5,7 @@
  *   Basic OpenType/CFF type definitions and interface (specification
  *   only).
  *
- * Copyright (C) 1996-2023 by
+ * Copyright (C) 1996-2024 by
  * David Turner, Robert Wilhelm, and Werner Lemberg.
  *
  * This file is part of the FreeType project, and may only be used,
@@ -248,10 +248,10 @@ FT_BEGIN_HEADER
     FT_Byte   num_family_blues;
     FT_Byte   num_family_other_blues;
 
-    FT_Pos    blue_values[14];
-    FT_Pos    other_blues[10];
-    FT_Pos    family_blues[14];
-    FT_Pos    family_other_blues[10];
+    FT_Fixed  blue_values[14];
+    FT_Fixed  other_blues[10];
+    FT_Fixed  family_blues[14];
+    FT_Fixed  family_other_blues[10];
 
     FT_Fixed  blue_scale;
     FT_Pos    blue_shift;
diff --git a/vendor/freetype/include/freetype/internal/compiler-macros.h b/vendor/freetype/include/freetype/internal/compiler-macros.h
index 6f67650979..876f66e256 100644
--- a/vendor/freetype/include/freetype/internal/compiler-macros.h
+++ b/vendor/freetype/include/freetype/internal/compiler-macros.h
@@ -4,7 +4,7 @@
  *
  *   Compiler-specific macro definitions used internally by FreeType.
  *
- * Copyright (C) 2020-2023 by
+ * Copyright (C) 2020-2024 by
  * David Turner, Robert Wilhelm, and Werner Lemberg.
  *
  * This file is part of the FreeType project, and may only be used,
diff --git a/vendor/freetype/include/freetype/internal/ftcalc.h b/vendor/freetype/include/freetype/internal/ftcalc.h
index d9aea23602..40634602f1 100644
--- a/vendor/freetype/include/freetype/internal/ftcalc.h
+++ b/vendor/freetype/include/freetype/internal/ftcalc.h
@@ -4,7 +4,7 @@
  *
  *   Arithmetic computations (specification).
  *
- * Copyright (C) 1996-2023 by
+ * Copyright (C) 1996-2024 by
  * David Turner, Robert Wilhelm, and Werner Lemberg.
  *
  * This file is part of the FreeType project, and may only be used,
@@ -455,6 +455,12 @@ FT_BEGIN_HEADER
 
 #define FT_MSB( x )  FT_MSB_i386( x )
 
+#elif defined( __SunOS_5_11 )
+
+#include 
+
+#define FT_MSB( x )  ( fls( x ) - 1 )
+
 #elif defined( __DECC ) || defined( __DECCXX )
 
 #include 
@@ -489,8 +495,6 @@ FT_BEGIN_HEADER
             FT_Fixed  y );
 
 
-#if 0
-
   /**************************************************************************
    *
    * @function:
@@ -507,12 +511,11 @@ FT_BEGIN_HEADER
    *   The result of 'sqrt(x)'.
    *
    * @note:
-   *   This function is not very fast.
+   *   This function is slow and should be avoided.  Consider `FT_Hypot` or
+   *   `FT_Vector_NormLen' instead.
    */
-  FT_BASE( FT_Int32 )
-  FT_SqrtFixed( FT_Int32  x );
-
-#endif /* 0 */
+  FT_BASE( FT_UInt32 )
+  FT_SqrtFixed( FT_UInt32  x );
 
 
 #define INT_TO_F26DOT6( x )    ( (FT_Long)(x) * 64  )    /* << 6  */
diff --git a/vendor/freetype/include/freetype/internal/ftdebug.h b/vendor/freetype/include/freetype/internal/ftdebug.h
index 4e013ba1e2..d7fa8dc93c 100644
--- a/vendor/freetype/include/freetype/internal/ftdebug.h
+++ b/vendor/freetype/include/freetype/internal/ftdebug.h
@@ -4,7 +4,7 @@
  *
  *   Debugging and logging component (specification).
  *
- * Copyright (C) 1996-2023 by
+ * Copyright (C) 1996-2024 by
  * David Turner, Robert Wilhelm, and Werner Lemberg.
  *
  * This file is part of the FreeType project, and may only be used,
diff --git a/vendor/freetype/include/freetype/internal/ftdrv.h b/vendor/freetype/include/freetype/internal/ftdrv.h
index 9001c07ad0..5609b3ef12 100644
--- a/vendor/freetype/include/freetype/internal/ftdrv.h
+++ b/vendor/freetype/include/freetype/internal/ftdrv.h
@@ -4,7 +4,7 @@
  *
  *   FreeType internal font driver interface (specification).
  *
- * Copyright (C) 1996-2023 by
+ * Copyright (C) 1996-2024 by
  * David Turner, Robert Wilhelm, and Werner Lemberg.
  *
  * This file is part of the FreeType project, and may only be used,
diff --git a/vendor/freetype/include/freetype/internal/ftgloadr.h b/vendor/freetype/include/freetype/internal/ftgloadr.h
index 36e5509f9e..f1c155b162 100644
--- a/vendor/freetype/include/freetype/internal/ftgloadr.h
+++ b/vendor/freetype/include/freetype/internal/ftgloadr.h
@@ -4,7 +4,7 @@
  *
  *   The FreeType glyph loader (specification).
  *
- * Copyright (C) 2002-2023 by
+ * Copyright (C) 2002-2024 by
  * David Turner, Robert Wilhelm, and Werner Lemberg
  *
  * This file is part of the FreeType project, and may only be used,
diff --git a/vendor/freetype/include/freetype/internal/ftmemory.h b/vendor/freetype/include/freetype/internal/ftmemory.h
index 5eb1d21ff6..4e05a29f13 100644
--- a/vendor/freetype/include/freetype/internal/ftmemory.h
+++ b/vendor/freetype/include/freetype/internal/ftmemory.h
@@ -4,7 +4,7 @@
  *
  *   The FreeType memory management macros (specification).
  *
- * Copyright (C) 1996-2023 by
+ * Copyright (C) 1996-2024 by
  * David Turner, Robert Wilhelm, and Werner Lemberg
  *
  * This file is part of the FreeType project, and may only be used,
@@ -371,8 +371,11 @@ extern "C++"
 #define FT_STRDUP( dst, str )                           \
           FT_MEM_SET_ERROR( FT_MEM_STRDUP( dst, str ) )
 
-#define FT_MEM_DUP( dst, address, size )                                    \
-          (dst) = ft_mem_dup( memory, (address), (FT_ULong)(size), &error )
+#define FT_MEM_DUP( dst, address, size )                       \
+          FT_ASSIGNP_INNER( dst, ft_mem_dup( memory,           \
+                                             (address),        \
+                                             (FT_ULong)(size), \
+                                             &error ) )
 
 #define FT_DUP( dst, address, size )                           \
           FT_MEM_SET_ERROR( FT_MEM_DUP( dst, address, size ) )
diff --git a/vendor/freetype/include/freetype/internal/ftmmtypes.h b/vendor/freetype/include/freetype/internal/ftmmtypes.h
index c4b21d6144..8449e7a010 100644
--- a/vendor/freetype/include/freetype/internal/ftmmtypes.h
+++ b/vendor/freetype/include/freetype/internal/ftmmtypes.h
@@ -5,7 +5,7 @@
  *   OpenType Variations type definitions for internal use
  *   with the multi-masters service (specification).
  *
- * Copyright (C) 2022-2023 by
+ * Copyright (C) 2022-2024 by
  * David Turner, Robert Wilhelm, Werner Lemberg, George Williams, and
  * Dominik Röttsches.
  *
diff --git a/vendor/freetype/include/freetype/internal/ftobjs.h b/vendor/freetype/include/freetype/internal/ftobjs.h
index 28bc9b65f0..e6333c2aa2 100644
--- a/vendor/freetype/include/freetype/internal/ftobjs.h
+++ b/vendor/freetype/include/freetype/internal/ftobjs.h
@@ -4,7 +4,7 @@
  *
  *   The FreeType private base classes (specification).
  *
- * Copyright (C) 1996-2023 by
+ * Copyright (C) 1996-2024 by
  * David Turner, Robert Wilhelm, and Werner Lemberg.
  *
  * This file is part of the FreeType project, and may only be used,
diff --git a/vendor/freetype/include/freetype/internal/ftpsprop.h b/vendor/freetype/include/freetype/internal/ftpsprop.h
index 1d5b287ad2..4f11aa16ba 100644
--- a/vendor/freetype/include/freetype/internal/ftpsprop.h
+++ b/vendor/freetype/include/freetype/internal/ftpsprop.h
@@ -4,7 +4,7 @@
  *
  *   Get and set properties of PostScript drivers (specification).
  *
- * Copyright (C) 2017-2023 by
+ * Copyright (C) 2017-2024 by
  * David Turner, Robert Wilhelm, and Werner Lemberg.
  *
  * This file is part of the FreeType project, and may only be used,
diff --git a/vendor/freetype/include/freetype/internal/ftrfork.h b/vendor/freetype/include/freetype/internal/ftrfork.h
index e96459921e..05c1d6c48b 100644
--- a/vendor/freetype/include/freetype/internal/ftrfork.h
+++ b/vendor/freetype/include/freetype/internal/ftrfork.h
@@ -4,7 +4,7 @@
  *
  *   Embedded resource forks accessor (specification).
  *
- * Copyright (C) 2004-2023 by
+ * Copyright (C) 2004-2024 by
  * Masatake YAMATO and Redhat K.K.
  *
  * This file is part of the FreeType project, and may only be used,
diff --git a/vendor/freetype/include/freetype/internal/ftserv.h b/vendor/freetype/include/freetype/internal/ftserv.h
index 1e85d6d385..8c35dbd713 100644
--- a/vendor/freetype/include/freetype/internal/ftserv.h
+++ b/vendor/freetype/include/freetype/internal/ftserv.h
@@ -4,7 +4,7 @@
  *
  *   The FreeType services (specification only).
  *
- * Copyright (C) 2003-2023 by
+ * Copyright (C) 2003-2024 by
  * David Turner, Robert Wilhelm, and Werner Lemberg.
  *
  * This file is part of the FreeType project, and may only be used,
diff --git a/vendor/freetype/include/freetype/internal/ftstream.h b/vendor/freetype/include/freetype/internal/ftstream.h
index 88e19287c8..fd52f767ef 100644
--- a/vendor/freetype/include/freetype/internal/ftstream.h
+++ b/vendor/freetype/include/freetype/internal/ftstream.h
@@ -4,7 +4,7 @@
  *
  *   Stream handling (specification).
  *
- * Copyright (C) 1996-2023 by
+ * Copyright (C) 1996-2024 by
  * David Turner, Robert Wilhelm, and Werner Lemberg.
  *
  * This file is part of the FreeType project, and may only be used,
diff --git a/vendor/freetype/include/freetype/internal/fttrace.h b/vendor/freetype/include/freetype/internal/fttrace.h
index 319fe56fd2..42595a29ff 100644
--- a/vendor/freetype/include/freetype/internal/fttrace.h
+++ b/vendor/freetype/include/freetype/internal/fttrace.h
@@ -4,7 +4,7 @@
  *
  *   Tracing handling (specification only).
  *
- * Copyright (C) 2002-2023 by
+ * Copyright (C) 2002-2024 by
  * David Turner, Robert Wilhelm, and Werner Lemberg.
  *
  * This file is part of the FreeType project, and may only be used,
@@ -64,6 +64,7 @@ FT_TRACE_DEF( ttbdf )     /* TrueType embedded BDF   (ttbdf.c)    */
 FT_TRACE_DEF( ttcmap )    /* charmap handler         (ttcmap.c)   */
 FT_TRACE_DEF( ttcolr )    /* glyph layer table       (ttcolr.c)   */
 FT_TRACE_DEF( ttcpal )    /* color palette table     (ttcpal.c)   */
+FT_TRACE_DEF( ttgpos )    /* GPOS handler            (ttgpos.c)   */
 FT_TRACE_DEF( ttsvg )     /* OpenType SVG table      (ttsvg.c)    */
 FT_TRACE_DEF( ttkern )    /* kerning handler         (ttkern.c)   */
 FT_TRACE_DEF( ttload )    /* basic TrueType tables   (ttload.c)   */
diff --git a/vendor/freetype/include/freetype/internal/ftvalid.h b/vendor/freetype/include/freetype/internal/ftvalid.h
index e98ee4e473..a1312f2aba 100644
--- a/vendor/freetype/include/freetype/internal/ftvalid.h
+++ b/vendor/freetype/include/freetype/internal/ftvalid.h
@@ -4,7 +4,7 @@
  *
  *   FreeType validation support (specification).
  *
- * Copyright (C) 2004-2023 by
+ * Copyright (C) 2004-2024 by
  * David Turner, Robert Wilhelm, and Werner Lemberg.
  *
  * This file is part of the FreeType project, and may only be used,
diff --git a/vendor/freetype/include/freetype/internal/psaux.h b/vendor/freetype/include/freetype/internal/psaux.h
index dfb1987f86..745d2cb56b 100644
--- a/vendor/freetype/include/freetype/internal/psaux.h
+++ b/vendor/freetype/include/freetype/internal/psaux.h
@@ -5,7 +5,7 @@
  *   Auxiliary functions and data structures related to PostScript fonts
  *   (specification).
  *
- * Copyright (C) 1996-2023 by
+ * Copyright (C) 1996-2024 by
  * David Turner, Robert Wilhelm, and Werner Lemberg.
  *
  * This file is part of the FreeType project, and may only be used,
@@ -225,6 +225,7 @@ FT_BEGIN_HEADER
 
   typedef enum  T1_FieldLocation_
   {
+    T1_FIELD_LOCATION_NONE = 0,
     T1_FIELD_LOCATION_CID_INFO,
     T1_FIELD_LOCATION_FONT_DICT,
     T1_FIELD_LOCATION_FONT_EXTRA,
@@ -249,6 +250,7 @@ FT_BEGIN_HEADER
   /* structure type used to model object fields */
   typedef struct  T1_FieldRec_
   {
+    FT_UInt             len;          /* field identifier length        */
     const char*         ident;        /* field identifier               */
     T1_FieldLocation    location;
     T1_FieldType        type;         /* type of field                  */
@@ -273,8 +275,9 @@ FT_BEGIN_HEADER
 
 #define T1_NEW_SIMPLE_FIELD( _ident, _type, _fname, _dict ) \
           {                                                 \
+            sizeof ( _ident ) - 1,                          \
             _ident, T1CODE, _type,                          \
-            0,                                              \
+            NULL,                                           \
             FT_FIELD_OFFSET( _fname ),                      \
             FT_FIELD_SIZE( _fname ),                        \
             0, 0,                                           \
@@ -283,6 +286,7 @@ FT_BEGIN_HEADER
 
 #define T1_NEW_CALLBACK_FIELD( _ident, _reader, _dict ) \
           {                                             \
+            sizeof ( _ident ) - 1,                      \
             _ident, T1CODE, T1_FIELD_TYPE_CALLBACK,     \
             (T1_Field_ParseFunc)_reader,                \
             0, 0,                                       \
@@ -292,8 +296,9 @@ FT_BEGIN_HEADER
 
 #define T1_NEW_TABLE_FIELD( _ident, _type, _fname, _max, _dict ) \
           {                                                      \
+            sizeof ( _ident ) - 1,                               \
             _ident, T1CODE, _type,                               \
-            0,                                                   \
+            NULL,                                                \
             FT_FIELD_OFFSET( _fname ),                           \
             FT_FIELD_SIZE_DELTA( _fname ),                       \
             _max,                                                \
@@ -303,8 +308,9 @@ FT_BEGIN_HEADER
 
 #define T1_NEW_TABLE_FIELD2( _ident, _type, _fname, _max, _dict ) \
           {                                                       \
+            sizeof ( _ident ) - 1,                                \
             _ident, T1CODE, _type,                                \
-            0,                                                    \
+            NULL,                                                 \
             FT_FIELD_OFFSET( _fname ),                            \
             FT_FIELD_SIZE_DELTA( _fname ),                        \
             _max, 0,                                              \
@@ -354,6 +360,13 @@ FT_BEGIN_HEADER
 #define T1_FIELD_CALLBACK( _ident, _name, _dict )       \
           T1_NEW_CALLBACK_FIELD( _ident, _name, _dict )
 
+#define T1_FIELD_ZERO                                         \
+          {                                                   \
+            0,                                                \
+            NULL, T1_FIELD_LOCATION_NONE, T1_FIELD_TYPE_NONE, \
+            NULL, 0, 0, 0, 0, 0                               \
+          }
+
 
   /*************************************************************************/
   /*************************************************************************/
diff --git a/vendor/freetype/include/freetype/internal/pshints.h b/vendor/freetype/include/freetype/internal/pshints.h
index ededc4c72e..dba6c7303f 100644
--- a/vendor/freetype/include/freetype/internal/pshints.h
+++ b/vendor/freetype/include/freetype/internal/pshints.h
@@ -6,7 +6,7 @@
  *   recorders (specification only).  These are used to support native
  *   T1/T2 hints in the 'type1', 'cid', and 'cff' font drivers.
  *
- * Copyright (C) 2001-2023 by
+ * Copyright (C) 2001-2024 by
  * David Turner, Robert Wilhelm, and Werner Lemberg.
  *
  * This file is part of the FreeType project, and may only be used,
diff --git a/vendor/freetype/include/freetype/internal/services/svbdf.h b/vendor/freetype/include/freetype/internal/services/svbdf.h
index bf0c1dcc71..89e9c2e5de 100644
--- a/vendor/freetype/include/freetype/internal/services/svbdf.h
+++ b/vendor/freetype/include/freetype/internal/services/svbdf.h
@@ -4,7 +4,7 @@
  *
  *   The FreeType BDF services (specification).
  *
- * Copyright (C) 2003-2023 by
+ * Copyright (C) 2003-2024 by
  * David Turner, Robert Wilhelm, and Werner Lemberg.
  *
  * This file is part of the FreeType project, and may only be used,
diff --git a/vendor/freetype/include/freetype/internal/services/svcfftl.h b/vendor/freetype/include/freetype/internal/services/svcfftl.h
index 4a20498ee0..3cb483c344 100644
--- a/vendor/freetype/include/freetype/internal/services/svcfftl.h
+++ b/vendor/freetype/include/freetype/internal/services/svcfftl.h
@@ -4,7 +4,7 @@
  *
  *   The FreeType CFF tables loader service (specification).
  *
- * Copyright (C) 2017-2023 by
+ * Copyright (C) 2017-2024 by
  * David Turner, Robert Wilhelm, and Werner Lemberg.
  *
  * This file is part of the FreeType project, and may only be used,
diff --git a/vendor/freetype/include/freetype/internal/services/svcid.h b/vendor/freetype/include/freetype/internal/services/svcid.h
index 06d0cb8fd6..8362cb8724 100644
--- a/vendor/freetype/include/freetype/internal/services/svcid.h
+++ b/vendor/freetype/include/freetype/internal/services/svcid.h
@@ -4,7 +4,7 @@
  *
  *   The FreeType CID font services (specification).
  *
- * Copyright (C) 2007-2023 by
+ * Copyright (C) 2007-2024 by
  * Derek Clegg and Michael Toftdal.
  *
  * This file is part of the FreeType project, and may only be used,
diff --git a/vendor/freetype/include/freetype/internal/services/svfntfmt.h b/vendor/freetype/include/freetype/internal/services/svfntfmt.h
index bc45e80568..6b837e79fc 100644
--- a/vendor/freetype/include/freetype/internal/services/svfntfmt.h
+++ b/vendor/freetype/include/freetype/internal/services/svfntfmt.h
@@ -4,7 +4,7 @@
  *
  *   The FreeType font format service (specification only).
  *
- * Copyright (C) 2003-2023 by
+ * Copyright (C) 2003-2024 by
  * David Turner, Robert Wilhelm, and Werner Lemberg.
  *
  * This file is part of the FreeType project, and may only be used,
diff --git a/vendor/freetype/include/freetype/internal/services/svgldict.h b/vendor/freetype/include/freetype/internal/services/svgldict.h
index 6437abfbf2..6126ec9ada 100644
--- a/vendor/freetype/include/freetype/internal/services/svgldict.h
+++ b/vendor/freetype/include/freetype/internal/services/svgldict.h
@@ -4,7 +4,7 @@
  *
  *   The FreeType glyph dictionary services (specification).
  *
- * Copyright (C) 2003-2023 by
+ * Copyright (C) 2003-2024 by
  * David Turner, Robert Wilhelm, and Werner Lemberg.
  *
  * This file is part of the FreeType project, and may only be used,
diff --git a/vendor/freetype/include/freetype/internal/services/svgxval.h b/vendor/freetype/include/freetype/internal/services/svgxval.h
index 31016afe0d..29cf552818 100644
--- a/vendor/freetype/include/freetype/internal/services/svgxval.h
+++ b/vendor/freetype/include/freetype/internal/services/svgxval.h
@@ -4,7 +4,7 @@
  *
  *   FreeType API for validating TrueTypeGX/AAT tables (specification).
  *
- * Copyright (C) 2004-2023 by
+ * Copyright (C) 2004-2024 by
  * Masatake YAMATO, Red Hat K.K.,
  * David Turner, Robert Wilhelm, and Werner Lemberg.
  *
diff --git a/vendor/freetype/include/freetype/internal/services/svkern.h b/vendor/freetype/include/freetype/internal/services/svkern.h
index bcabbc3e68..ac1bc30c41 100644
--- a/vendor/freetype/include/freetype/internal/services/svkern.h
+++ b/vendor/freetype/include/freetype/internal/services/svkern.h
@@ -4,7 +4,7 @@
  *
  *   The FreeType Kerning service (specification).
  *
- * Copyright (C) 2006-2023 by
+ * Copyright (C) 2006-2024 by
  * David Turner, Robert Wilhelm, and Werner Lemberg.
  *
  * This file is part of the FreeType project, and may only be used,
diff --git a/vendor/freetype/include/freetype/internal/services/svmetric.h b/vendor/freetype/include/freetype/internal/services/svmetric.h
index 167617ebb3..8b3563b25c 100644
--- a/vendor/freetype/include/freetype/internal/services/svmetric.h
+++ b/vendor/freetype/include/freetype/internal/services/svmetric.h
@@ -4,7 +4,7 @@
  *
  *   The FreeType services for metrics variations (specification).
  *
- * Copyright (C) 2016-2023 by
+ * Copyright (C) 2016-2024 by
  * David Turner, Robert Wilhelm, and Werner Lemberg.
  *
  * This file is part of the FreeType project, and may only be used,
diff --git a/vendor/freetype/include/freetype/internal/services/svmm.h b/vendor/freetype/include/freetype/internal/services/svmm.h
index 7e76ab8324..5288fadf37 100644
--- a/vendor/freetype/include/freetype/internal/services/svmm.h
+++ b/vendor/freetype/include/freetype/internal/services/svmm.h
@@ -4,7 +4,7 @@
  *
  *   The FreeType Multiple Masters and GX var services (specification).
  *
- * Copyright (C) 2003-2023 by
+ * Copyright (C) 2003-2024 by
  * David Turner, Robert Wilhelm, Werner Lemberg, and Dominik Röttsches.
  *
  * This file is part of the FreeType project, and may only be used,
diff --git a/vendor/freetype/include/freetype/internal/services/svotval.h b/vendor/freetype/include/freetype/internal/services/svotval.h
index a4683cd5fb..7aea7ec11f 100644
--- a/vendor/freetype/include/freetype/internal/services/svotval.h
+++ b/vendor/freetype/include/freetype/internal/services/svotval.h
@@ -4,7 +4,7 @@
  *
  *   The FreeType OpenType validation service (specification).
  *
- * Copyright (C) 2004-2023 by
+ * Copyright (C) 2004-2024 by
  * David Turner, Robert Wilhelm, and Werner Lemberg.
  *
  * This file is part of the FreeType project, and may only be used,
diff --git a/vendor/freetype/include/freetype/internal/services/svpfr.h b/vendor/freetype/include/freetype/internal/services/svpfr.h
index fd189c7de7..b2fac6d086 100644
--- a/vendor/freetype/include/freetype/internal/services/svpfr.h
+++ b/vendor/freetype/include/freetype/internal/services/svpfr.h
@@ -4,7 +4,7 @@
  *
  *   Internal PFR service functions (specification).
  *
- * Copyright (C) 2003-2023 by
+ * Copyright (C) 2003-2024 by
  * David Turner, Robert Wilhelm, and Werner Lemberg.
  *
  * This file is part of the FreeType project, and may only be used,
diff --git a/vendor/freetype/include/freetype/internal/services/svpostnm.h b/vendor/freetype/include/freetype/internal/services/svpostnm.h
index 2b8f6dfecf..d19f3adc6d 100644
--- a/vendor/freetype/include/freetype/internal/services/svpostnm.h
+++ b/vendor/freetype/include/freetype/internal/services/svpostnm.h
@@ -4,7 +4,7 @@
  *
  *   The FreeType PostScript name services (specification).
  *
- * Copyright (C) 2003-2023 by
+ * Copyright (C) 2003-2024 by
  * David Turner, Robert Wilhelm, and Werner Lemberg.
  *
  * This file is part of the FreeType project, and may only be used,
diff --git a/vendor/freetype/include/freetype/internal/services/svprop.h b/vendor/freetype/include/freetype/internal/services/svprop.h
index 932ce32e03..ba39c0dd4d 100644
--- a/vendor/freetype/include/freetype/internal/services/svprop.h
+++ b/vendor/freetype/include/freetype/internal/services/svprop.h
@@ -4,7 +4,7 @@
  *
  *   The FreeType property service (specification).
  *
- * Copyright (C) 2012-2023 by
+ * Copyright (C) 2012-2024 by
  * David Turner, Robert Wilhelm, and Werner Lemberg.
  *
  * This file is part of the FreeType project, and may only be used,
diff --git a/vendor/freetype/include/freetype/internal/services/svpscmap.h b/vendor/freetype/include/freetype/internal/services/svpscmap.h
index 6e599f3aab..d4908ee41a 100644
--- a/vendor/freetype/include/freetype/internal/services/svpscmap.h
+++ b/vendor/freetype/include/freetype/internal/services/svpscmap.h
@@ -4,7 +4,7 @@
  *
  *   The FreeType PostScript charmap service (specification).
  *
- * Copyright (C) 2003-2023 by
+ * Copyright (C) 2003-2024 by
  * David Turner, Robert Wilhelm, and Werner Lemberg.
  *
  * This file is part of the FreeType project, and may only be used,
diff --git a/vendor/freetype/include/freetype/internal/services/svpsinfo.h b/vendor/freetype/include/freetype/internal/services/svpsinfo.h
index 09c4cdccc5..2aadcdd02a 100644
--- a/vendor/freetype/include/freetype/internal/services/svpsinfo.h
+++ b/vendor/freetype/include/freetype/internal/services/svpsinfo.h
@@ -4,7 +4,7 @@
  *
  *   The FreeType PostScript info service (specification).
  *
- * Copyright (C) 2003-2023 by
+ * Copyright (C) 2003-2024 by
  * David Turner, Robert Wilhelm, and Werner Lemberg.
  *
  * This file is part of the FreeType project, and may only be used,
diff --git a/vendor/freetype/include/freetype/internal/services/svsfnt.h b/vendor/freetype/include/freetype/internal/services/svsfnt.h
index f98df2ef5f..9e0f4ff202 100644
--- a/vendor/freetype/include/freetype/internal/services/svsfnt.h
+++ b/vendor/freetype/include/freetype/internal/services/svsfnt.h
@@ -4,7 +4,7 @@
  *
  *   The FreeType SFNT table loading service (specification).
  *
- * Copyright (C) 2003-2023 by
+ * Copyright (C) 2003-2024 by
  * David Turner, Robert Wilhelm, and Werner Lemberg.
  *
  * This file is part of the FreeType project, and may only be used,
diff --git a/vendor/freetype/include/freetype/internal/services/svttcmap.h b/vendor/freetype/include/freetype/internal/services/svttcmap.h
index 5f9eb02d66..250886bcc5 100644
--- a/vendor/freetype/include/freetype/internal/services/svttcmap.h
+++ b/vendor/freetype/include/freetype/internal/services/svttcmap.h
@@ -4,7 +4,7 @@
  *
  *   The FreeType TrueType/sfnt cmap extra information service.
  *
- * Copyright (C) 2003-2023 by
+ * Copyright (C) 2003-2024 by
  * Masatake YAMATO, Redhat K.K.,
  * David Turner, Robert Wilhelm, and Werner Lemberg.
  *
diff --git a/vendor/freetype/include/freetype/internal/services/svtteng.h b/vendor/freetype/include/freetype/internal/services/svtteng.h
index ad577cb290..14967529a9 100644
--- a/vendor/freetype/include/freetype/internal/services/svtteng.h
+++ b/vendor/freetype/include/freetype/internal/services/svtteng.h
@@ -4,7 +4,7 @@
  *
  *   The FreeType TrueType engine query service (specification).
  *
- * Copyright (C) 2006-2023 by
+ * Copyright (C) 2006-2024 by
  * David Turner, Robert Wilhelm, and Werner Lemberg.
  *
  * This file is part of the FreeType project, and may only be used,
diff --git a/vendor/freetype/include/freetype/internal/services/svttglyf.h b/vendor/freetype/include/freetype/internal/services/svttglyf.h
index ca6fff7444..f190b3985d 100644
--- a/vendor/freetype/include/freetype/internal/services/svttglyf.h
+++ b/vendor/freetype/include/freetype/internal/services/svttglyf.h
@@ -4,7 +4,7 @@
  *
  *   The FreeType TrueType glyph service.
  *
- * Copyright (C) 2007-2023 by
+ * Copyright (C) 2007-2024 by
  * David Turner.
  *
  * This file is part of the FreeType project, and may only be used,
diff --git a/vendor/freetype/include/freetype/internal/services/svwinfnt.h b/vendor/freetype/include/freetype/internal/services/svwinfnt.h
index 002923f8c9..49f3fb7f77 100644
--- a/vendor/freetype/include/freetype/internal/services/svwinfnt.h
+++ b/vendor/freetype/include/freetype/internal/services/svwinfnt.h
@@ -4,7 +4,7 @@
  *
  *   The FreeType Windows FNT/FONT service (specification).
  *
- * Copyright (C) 2003-2023 by
+ * Copyright (C) 2003-2024 by
  * David Turner, Robert Wilhelm, and Werner Lemberg.
  *
  * This file is part of the FreeType project, and may only be used,
diff --git a/vendor/freetype/include/freetype/internal/sfnt.h b/vendor/freetype/include/freetype/internal/sfnt.h
index a2d4e15baa..35e4e73af0 100644
--- a/vendor/freetype/include/freetype/internal/sfnt.h
+++ b/vendor/freetype/include/freetype/internal/sfnt.h
@@ -4,7 +4,7 @@
  *
  *   High-level 'sfnt' driver interface (specification).
  *
- * Copyright (C) 1996-2023 by
+ * Copyright (C) 1996-2024 by
  * David Turner, Robert Wilhelm, and Werner Lemberg.
  *
  * This file is part of the FreeType project, and may only be used,
@@ -924,6 +924,7 @@ FT_BEGIN_HEADER
     /* this field was called `load_kerning' up to version 2.1.10 */
     TT_Load_Table_Func  load_kern;
 
+    TT_Load_Table_Func  load_gpos;
     TT_Load_Table_Func  load_gasp;
     TT_Load_Table_Func  load_pclt;
 
@@ -944,6 +945,8 @@ FT_BEGIN_HEADER
 
     /* new elements introduced after version 2.1.10 */
 
+    TT_Face_GetKerningFunc  get_gpos_kerning;
+
     /* load the font directory, i.e., the offset table and */
     /* the table directory                                 */
     TT_Load_Table_Func    load_font_dir;
@@ -1002,6 +1005,7 @@ FT_BEGIN_HEADER
           load_name_,                    \
           free_name_,                    \
           load_kern_,                    \
+          load_gpos_,                    \
           load_gasp_,                    \
           load_pclt_,                    \
           load_bhed_,                    \
@@ -1009,6 +1013,7 @@ FT_BEGIN_HEADER
           get_psname_,                   \
           free_psnames_,                 \
           get_kerning_,                  \
+          get_gpos_kerning_,             \
           load_font_dir_,                \
           load_hmtx_,                    \
           load_eblc_,                    \
@@ -1050,6 +1055,7 @@ FT_BEGIN_HEADER
     load_name_,                          \
     free_name_,                          \
     load_kern_,                          \
+    load_gpos_,                          \
     load_gasp_,                          \
     load_pclt_,                          \
     load_bhed_,                          \
@@ -1057,6 +1063,7 @@ FT_BEGIN_HEADER
     get_psname_,                         \
     free_psnames_,                       \
     get_kerning_,                        \
+    get_gpos_kerning_,                   \
     load_font_dir_,                      \
     load_hmtx_,                          \
     load_eblc_,                          \
diff --git a/vendor/freetype/include/freetype/internal/svginterface.h b/vendor/freetype/include/freetype/internal/svginterface.h
index f464b2c058..68c99efb10 100644
--- a/vendor/freetype/include/freetype/internal/svginterface.h
+++ b/vendor/freetype/include/freetype/internal/svginterface.h
@@ -4,7 +4,7 @@
  *
  *   Interface of ot-svg module (specification only).
  *
- * Copyright (C) 2022-2023 by
+ * Copyright (C) 2022-2024 by
  * David Turner, Robert Wilhelm, Werner Lemberg, and Moazin Khatti.
  *
  * This file is part of the FreeType project, and may only be used,
diff --git a/vendor/freetype/include/freetype/internal/t1types.h b/vendor/freetype/include/freetype/internal/t1types.h
index b9c94398fd..1821ae5cc8 100644
--- a/vendor/freetype/include/freetype/internal/t1types.h
+++ b/vendor/freetype/include/freetype/internal/t1types.h
@@ -5,7 +5,7 @@
  *   Basic Type1/Type2 type definitions and interface (specification
  *   only).
  *
- * Copyright (C) 1996-2023 by
+ * Copyright (C) 1996-2024 by
  * David Turner, Robert Wilhelm, and Werner Lemberg.
  *
  * This file is part of the FreeType project, and may only be used,
@@ -21,7 +21,7 @@
 #define T1TYPES_H_
 
 
-#include 
+#include 
 #include 
 #include 
 #include 
@@ -137,6 +137,54 @@ FT_BEGIN_HEADER
   } CID_SubrsRec, *CID_Subrs;
 
 
+  /* this structure is used to store the BlendDesignMap entry for an axis */
+  typedef struct  PS_DesignMap_
+  {
+    FT_Byte    num_points;
+    FT_Long*   design_points;
+    FT_Fixed*  blend_points;
+
+  } PS_DesignMapRec, *PS_DesignMap;
+
+  /* backward compatible definition */
+  typedef PS_DesignMapRec  T1_DesignMap;
+
+
+  typedef struct  PS_BlendRec_
+  {
+    FT_UInt          num_designs;
+    FT_UInt          num_axis;
+
+    FT_String*       axis_names[T1_MAX_MM_AXIS];
+    FT_Fixed*        design_pos[T1_MAX_MM_DESIGNS];
+    PS_DesignMapRec  design_map[T1_MAX_MM_AXIS];
+
+    FT_Fixed*        weight_vector;
+    FT_Fixed*        default_weight_vector;
+
+    PS_FontInfo      font_infos[T1_MAX_MM_DESIGNS + 1];
+    PS_Private       privates  [T1_MAX_MM_DESIGNS + 1];
+
+    FT_ULong         blend_bitflags;
+
+    FT_BBox*         bboxes    [T1_MAX_MM_DESIGNS + 1];
+
+    /* since 2.3.0 */
+
+    /* undocumented, optional: the default design instance;   */
+    /* corresponds to default_weight_vector --                */
+    /* num_default_design_vector == 0 means it is not present */
+    /* in the font and associated metrics files               */
+    FT_UInt          default_design_vector[T1_MAX_MM_DESIGNS];
+    FT_UInt          num_default_design_vector;
+
+  } PS_BlendRec, *PS_Blend;
+
+
+  /* backward compatible definition */
+  typedef PS_BlendRec  T1_Blend;
+
+
   /*************************************************************************/
   /*************************************************************************/
   /*************************************************************************/
diff --git a/vendor/freetype/include/freetype/internal/tttypes.h b/vendor/freetype/include/freetype/internal/tttypes.h
index b9788c7831..7053e656a7 100644
--- a/vendor/freetype/include/freetype/internal/tttypes.h
+++ b/vendor/freetype/include/freetype/internal/tttypes.h
@@ -5,7 +5,7 @@
  *   Basic SFNT/TrueType type definitions and interface (specification
  *   only).
  *
- * Copyright (C) 1996-2023 by
+ * Copyright (C) 1996-2024 by
  * David Turner, Robert Wilhelm, and Werner Lemberg.
  *
  * This file is part of the FreeType project, and may only be used,
@@ -24,6 +24,7 @@
 #include 
 #include 
 #include 
+#include "freetype/fttypes.h"
 
 #ifdef TT_CONFIG_OPTION_GX_VAR_SUPPORT
 #include 
@@ -1581,6 +1582,11 @@ FT_BEGIN_HEADER
     FT_UInt32             kern_avail_bits;
     FT_UInt32             kern_order_bits;
 
+#ifdef TT_CONFIG_OPTION_GPOS_KERNING
+    FT_Byte*              gpos_table;
+    FT_Bool               gpos_kerning_available;
+#endif
+
 #ifdef TT_CONFIG_OPTION_BDF
     TT_BDFRec             bdf;
 #endif /* TT_CONFIG_OPTION_BDF */
@@ -1649,9 +1655,9 @@ FT_BEGIN_HEADER
   {
     FT_Memory   memory;
     FT_UShort   max_points;
-    FT_Short    max_contours;
+    FT_UShort   max_contours;
     FT_UShort   n_points;    /* number of points in zone    */
-    FT_Short    n_contours;  /* number of contours          */
+    FT_UShort   n_contours;  /* number of contours          */
 
     FT_Vector*  org;         /* original point coordinates  */
     FT_Vector*  cur;         /* current point coordinates   */
diff --git a/vendor/freetype/include/freetype/internal/wofftypes.h b/vendor/freetype/include/freetype/internal/wofftypes.h
index 0c1d8eeaf8..4a169d12f5 100644
--- a/vendor/freetype/include/freetype/internal/wofftypes.h
+++ b/vendor/freetype/include/freetype/internal/wofftypes.h
@@ -5,7 +5,7 @@
  *   Basic WOFF/WOFF2 type definitions and interface (specification
  *   only).
  *
- * Copyright (C) 1996-2023 by
+ * Copyright (C) 1996-2024 by
  * David Turner, Robert Wilhelm, and Werner Lemberg.
  *
  * This file is part of the FreeType project, and may only be used,
diff --git a/vendor/freetype/include/freetype/otsvg.h b/vendor/freetype/include/freetype/otsvg.h
index bfe9a6ab74..9d356938cc 100644
--- a/vendor/freetype/include/freetype/otsvg.h
+++ b/vendor/freetype/include/freetype/otsvg.h
@@ -4,7 +4,7 @@
  *
  *   Interface for OT-SVG support related things (specification).
  *
- * Copyright (C) 2022-2023 by
+ * Copyright (C) 2022-2024 by
  * David Turner, Robert Wilhelm, Werner Lemberg, and Moazin Khatti.
  *
  * This file is part of the FreeType project, and may only be used,
diff --git a/vendor/freetype/include/freetype/t1tables.h b/vendor/freetype/include/freetype/t1tables.h
index 1aecfbbd90..fbd558aa34 100644
--- a/vendor/freetype/include/freetype/t1tables.h
+++ b/vendor/freetype/include/freetype/t1tables.h
@@ -5,7 +5,7 @@
  *   Basic Type 1/Type 2 tables definitions and interface (specification
  *   only).
  *
- * Copyright (C) 1996-2023 by
+ * Copyright (C) 1996-2024 by
  * David Turner, Robert Wilhelm, and Werner Lemberg.
  *
  * This file is part of the FreeType project, and may only be used,
@@ -269,64 +269,6 @@ FT_BEGIN_HEADER
   /* */
 
 
-  /* maximum number of Multiple Masters designs, as defined in the spec */
-#define T1_MAX_MM_DESIGNS     16
-
-  /* maximum number of Multiple Masters axes, as defined in the spec */
-#define T1_MAX_MM_AXIS        4
-
-  /* maximum number of elements in a design map */
-#define T1_MAX_MM_MAP_POINTS  20
-
-
-  /* this structure is used to store the BlendDesignMap entry for an axis */
-  typedef struct  PS_DesignMap_
-  {
-    FT_Byte    num_points;
-    FT_Long*   design_points;
-    FT_Fixed*  blend_points;
-
-  } PS_DesignMapRec, *PS_DesignMap;
-
-  /* backward compatible definition */
-  typedef PS_DesignMapRec  T1_DesignMap;
-
-
-  typedef struct  PS_BlendRec_
-  {
-    FT_UInt          num_designs;
-    FT_UInt          num_axis;
-
-    FT_String*       axis_names[T1_MAX_MM_AXIS];
-    FT_Fixed*        design_pos[T1_MAX_MM_DESIGNS];
-    PS_DesignMapRec  design_map[T1_MAX_MM_AXIS];
-
-    FT_Fixed*        weight_vector;
-    FT_Fixed*        default_weight_vector;
-
-    PS_FontInfo      font_infos[T1_MAX_MM_DESIGNS + 1];
-    PS_Private       privates  [T1_MAX_MM_DESIGNS + 1];
-
-    FT_ULong         blend_bitflags;
-
-    FT_BBox*         bboxes    [T1_MAX_MM_DESIGNS + 1];
-
-    /* since 2.3.0 */
-
-    /* undocumented, optional: the default design instance;   */
-    /* corresponds to default_weight_vector --                */
-    /* num_default_design_vector == 0 means it is not present */
-    /* in the font and associated metrics files               */
-    FT_UInt          default_design_vector[T1_MAX_MM_DESIGNS];
-    FT_UInt          num_default_design_vector;
-
-  } PS_BlendRec, *PS_Blend;
-
-
-  /* backward compatible definition */
-  typedef PS_BlendRec  T1_Blend;
-
-
   /**************************************************************************
    *
    * @struct:
diff --git a/vendor/freetype/include/freetype/ttnameid.h b/vendor/freetype/include/freetype/ttnameid.h
index e31c68b9ba..d5d470e380 100644
--- a/vendor/freetype/include/freetype/ttnameid.h
+++ b/vendor/freetype/include/freetype/ttnameid.h
@@ -4,7 +4,7 @@
  *
  *   TrueType name ID definitions (specification only).
  *
- * Copyright (C) 1996-2023 by
+ * Copyright (C) 1996-2024 by
  * David Turner, Robert Wilhelm, and Werner Lemberg.
  *
  * This file is part of the FreeType project, and may only be used,
diff --git a/vendor/freetype/include/freetype/tttables.h b/vendor/freetype/include/freetype/tttables.h
index a9f60e7620..111f218020 100644
--- a/vendor/freetype/include/freetype/tttables.h
+++ b/vendor/freetype/include/freetype/tttables.h
@@ -5,7 +5,7 @@
  *   Basic SFNT/TrueType tables definitions and interface
  *   (specification only).
  *
- * Copyright (C) 1996-2023 by
+ * Copyright (C) 1996-2024 by
  * David Turner, Robert Wilhelm, and Werner Lemberg.
  *
  * This file is part of the FreeType project, and may only be used,
diff --git a/vendor/freetype/include/freetype/tttags.h b/vendor/freetype/include/freetype/tttags.h
index 9bf4fca23f..da0af5d3f2 100644
--- a/vendor/freetype/include/freetype/tttags.h
+++ b/vendor/freetype/include/freetype/tttags.h
@@ -4,7 +4,7 @@
  *
  *   Tags for TrueType and OpenType tables (specification only).
  *
- * Copyright (C) 1996-2023 by
+ * Copyright (C) 1996-2024 by
  * David Turner, Robert Wilhelm, and Werner Lemberg.
  *
  * This file is part of the FreeType project, and may only be used,
diff --git a/vendor/freetype/include/ft2build.h b/vendor/freetype/include/ft2build.h
index 58491ceea1..d3d7685039 100644
--- a/vendor/freetype/include/ft2build.h
+++ b/vendor/freetype/include/ft2build.h
@@ -4,7 +4,7 @@
  *
  *   FreeType 2 build and setup macros.
  *
- * Copyright (C) 1996-2023 by
+ * Copyright (C) 1996-2024 by
  * David Turner, Robert Wilhelm, and Werner Lemberg.
  *
  * This file is part of the FreeType project, and may only be used,
diff --git a/vendor/freetype/premake5.lua b/vendor/freetype/premake5.lua
index ead564f67d..c5a9c828b0 100644
--- a/vendor/freetype/premake5.lua
+++ b/vendor/freetype/premake5.lua
@@ -38,7 +38,6 @@ project "freetype"
 		"src/cache/ftcache.c",
 		"src/cff/cff.c",
 		"src/cid/type1cid.c",
-		"src/dlg/dlg.c",
 		"src/gxvalid/gxvalid.c",
 		"src/gzip/ftgzip.c",
 		"src/lzw/ftlzw.c",
diff --git a/vendor/freetype/src/autofit/afblue.c b/vendor/freetype/src/autofit/afblue.c
index d7655b9b99..ea83969cdc 100644
--- a/vendor/freetype/src/autofit/afblue.c
+++ b/vendor/freetype/src/autofit/afblue.c
@@ -7,7 +7,7 @@
  *
  *   Auto-fitter data for blue strings (body).
  *
- * Copyright (C) 2013-2023 by
+ * Copyright (C) 2013-2024 by
  * David Turner, Robert Wilhelm, and Werner Lemberg.
  *
  * This file is part of the FreeType project, and may only be used,
diff --git a/vendor/freetype/src/autofit/afblue.cin b/vendor/freetype/src/autofit/afblue.cin
index d561c5093b..d2270fac74 100644
--- a/vendor/freetype/src/autofit/afblue.cin
+++ b/vendor/freetype/src/autofit/afblue.cin
@@ -4,7 +4,7 @@
  *
  *   Auto-fitter data for blue strings (body).
  *
- * Copyright (C) 2013-2023 by
+ * Copyright (C) 2013-2024 by
  * David Turner, Robert Wilhelm, and Werner Lemberg.
  *
  * This file is part of the FreeType project, and may only be used,
diff --git a/vendor/freetype/src/autofit/afblue.dat b/vendor/freetype/src/autofit/afblue.dat
index 8299baa259..9f1ea9a0b8 100644
--- a/vendor/freetype/src/autofit/afblue.dat
+++ b/vendor/freetype/src/autofit/afblue.dat
@@ -1,1121 +1,1121 @@
-// afblue.dat
-//
-//   Auto-fitter data for blue strings.
-//
-// Copyright (C) 2013-2023 by
-// David Turner, Robert Wilhelm, and Werner Lemberg.
-//
-// This file is part of the FreeType project, and may only be used,
-// modified, and distributed under the terms of the FreeType project
-// license, LICENSE.TXT.  By continuing to use, modify, or distribute
-// this file you indicate that you have read the license and
-// understand and accept it fully.
-
-
-// This file contains data specific to blue zones.  It gets processed by
-// a script to simulate `jagged arrays', with enumeration values holding
-// offsets into the arrays.
-//
-// The format of the file is rather simple:  A section starts with three
-// labels separated by whitespace and followed by a colon (everything in a
-// single line); the first label gives the name of the enumeration template,
-// the second the name of the array template, and the third the name of the
-// `maximum' template.  The script then fills the corresponding templates
-// (indicated by `@' characters around the name).
-//
-// A section contains one or more data records.  Each data record consists
-// of two or more lines.  The first line holds the enumeration name, and the
-// remaining lines the corresponding array data.
-//
-// There are two possible representations for array data.
-//
-// - A string of characters or character clusters (for example, representing
-//   Aksharas, Devanagari syllables) in UTF-8 encoding enclosed in double
-//   quotes, using C syntax, where the elements are separated by spaces.
-//   There can be only one string per line, thus the starting and ending
-//   double quote must be the first and last character in the line,
-//   respectively, ignoring whitespace before and after the string.  If
-//   there are multiple strings (in multiple lines), they are concatenated
-//   to a single string.  In the output, a string gets represented as a
-//   series of singles bytes, followed by a zero byte.  The enumeration
-//   values simply hold byte offsets to the start of the corresponding
-//   strings.
-//
-//   For strings, the `maximum' template holds the maximum number of
-//   non-space characters in all strings.
-//
-// - Data blocks enclosed in balanced braces, which get copied verbatim and
-//   which can span multiple lines.  The opening brace of a block must be
-//   the first character of a line (ignoring whitespace), and the closing
-//   brace the last (ignoring whitespace also).  The script appends a comma
-//   character after each block and counts the number of blocks to set the
-//   enumeration values.
-//
-//   For data blocks, the `maximum' template holds the maximum number of
-//   array elements.
-//
-// A section can contain either strings only or data blocks only.
-//
-// A comment line starts with `//'; it gets removed.  A preprocessor
-// directive line (using the standard syntax of `cpp') starts with `#' and
-// gets copied verbatim to both the enumeration and the array.  Whitespace
-// outside of a string is insignificant.
-//
-// Preprocessor directives are ignored while the script computes maximum
-// values; this essentially means that the maximum values can easily be too
-// large.  Given that the purpose of those values is to create local
-// fixed-size arrays at compile time for further processing of the blue zone
-// data, this isn't a problem.  Note the final zero byte of a string is not
-// counted.  Note also that the count holds the number of UTF-8 encoded
-// characters, not bytes.
-
-
-// The blue zone string data, to be used in the blue stringsets below.
-
-AF_BLUE_STRING_ENUM AF_BLUE_STRINGS_ARRAY AF_BLUE_STRING_MAX_LEN:
-
-  AF_BLUE_STRING_ADLAM_CAPITAL_TOP
-    "𞤌 𞤅 𞤈 𞤏 𞤔 𞤚"
-  AF_BLUE_STRING_ADLAM_CAPITAL_BOTTOM
-    "𞤂 𞤖"
-  AF_BLUE_STRING_ADLAM_SMALL_TOP
-    "𞤬 𞤮 𞤻 𞤼 𞤾"
-  AF_BLUE_STRING_ADLAM_SMALL_BOTTOM
-    "𞤤 𞤨 𞤩 𞤭 𞤴 𞤸 𞤺 𞥀"
-
-  AF_BLUE_STRING_ARABIC_TOP
-    "ا إ ل ك ط ظ"
-  AF_BLUE_STRING_ARABIC_BOTTOM
-    "ت ث ط ظ ك"
-  // We don't necessarily have access to medial forms via Unicode in case
-  // Arabic presentational forms are missing.  The only character that is
-  // guaranteed to have the same vertical position with joining (that is,
-  // non-isolated) forms is U+0640, ARABIC TATWEEL, which must join both
-  // round and flat curves.
-  AF_BLUE_STRING_ARABIC_JOIN
-    "ـ"
-
-  AF_BLUE_STRING_ARMENIAN_CAPITAL_TOP
-    "Ա Մ Ւ Ս Բ Գ Դ Օ"
-  AF_BLUE_STRING_ARMENIAN_CAPITAL_BOTTOM
-    "Ւ Ո Դ Ճ Շ Ս Տ Օ"
-  AF_BLUE_STRING_ARMENIAN_SMALL_ASCENDER
-    "ե է ի մ վ ֆ ճ"
-  AF_BLUE_STRING_ARMENIAN_SMALL_TOP
-    "ա յ ւ ս գ շ ր օ"
-  AF_BLUE_STRING_ARMENIAN_SMALL_BOTTOM
-    "հ ո ճ ա ե ծ ս օ"
-  AF_BLUE_STRING_ARMENIAN_SMALL_DESCENDER
-    "բ ը ի լ ղ պ փ ց"
-
-  AF_BLUE_STRING_AVESTAN_TOP
-    "𐬀 𐬁 𐬐 𐬛"
-  AF_BLUE_STRING_AVESTAN_BOTTOM
-    "𐬀 𐬁"
-
-  AF_BLUE_STRING_BAMUM_TOP
-    "ꚧ ꚨ ꛛ ꛉ ꛁ ꛈ ꛫ ꛯ"
-  AF_BLUE_STRING_BAMUM_BOTTOM
-    "ꚭ ꚳ ꚶ ꛬ ꚢ ꚽ ꛯ ꛲"
-
-  AF_BLUE_STRING_BENGALI_BASE
-    "অ ড ত ন ব ভ ল ক"
-  AF_BLUE_STRING_BENGALI_TOP
-    "ই ট ঠ ি ী ৈ ৗ"
-  AF_BLUE_STRING_BENGALI_HEAD
-    "ও এ ড ত ন ব ল ক"
-
-  AF_BLUE_STRING_BUHID_TOP
-    "ᝐ ᝈ"
-  AF_BLUE_STRING_BUHID_LARGE
-    "ᝅ ᝊ ᝎ"
-  AF_BLUE_STRING_BUHID_SMALL
-    "ᝂ ᝃ ᝉ ᝌ"
-  AF_BLUE_STRING_BUHID_BOTTOM
-    "ᝀ ᝃ ᝆ ᝉ ᝋ ᝏ ᝑ"
-
-  AF_BLUE_STRING_CANADIAN_SYLLABICS_TOP
-    "ᗜ ᖴ ᐁ ᒣ ᑫ ᑎ ᔑ ᗰ"
-  AF_BLUE_STRING_CANADIAN_SYLLABICS_BOTTOM
-    "ᗶ ᖵ ᒧ ᐃ ᑌ ᒍ ᔑ ᗢ"
-  AF_BLUE_STRING_CANADIAN_SYLLABICS_SMALL_TOP
-    "ᓓ ᓕ ᓀ ᓂ ᓄ ᕄ ᕆ ᘣ"
-  AF_BLUE_STRING_CANADIAN_SYLLABICS_SMALL_BOTTOM
-    "ᕃ ᓂ ᓀ ᕂ ᓗ ᓚ ᕆ ᘣ"
-  AF_BLUE_STRING_CANADIAN_SYLLABICS_SUPS_TOP
-    "ᐪ ᙆ ᣘ ᐢ ᒾ ᣗ ᔆ"
-  AF_BLUE_STRING_CANADIAN_SYLLABICS_SUPS_BOTTOM
-    "ᙆ ᗮ ᒻ ᐞ ᔆ ᒡ ᒢ ᓑ"
-
-  AF_BLUE_STRING_CARIAN_TOP
-    "𐊧 𐊫 𐊬 𐊭 𐊱 𐊺 𐊼 𐊿"
-  AF_BLUE_STRING_CARIAN_BOTTOM
-    "𐊣 𐊧 𐊷 𐋀 𐊫 𐊸 𐋉"
-
-  AF_BLUE_STRING_CHAKMA_TOP
-    "𑄃 𑄅 𑄉 𑄙 𑄗"
-  AF_BLUE_STRING_CHAKMA_BOTTOM
-    "𑄅 𑄛 𑄝 𑄗 𑄓"
-  AF_BLUE_STRING_CHAKMA_DESCENDER
-    "𑄖𑄳𑄢 𑄘𑄳𑄢 𑄙𑄳𑄢 𑄤𑄳𑄢 𑄥𑄳𑄢"
-
-  AF_BLUE_STRING_CHEROKEE_CAPITAL
-    "Ꮖ Ꮋ Ꭼ Ꮓ Ꭴ Ꮳ Ꭶ Ꮥ"
-  AF_BLUE_STRING_CHEROKEE_SMALL_ASCENDER
-    "ꮒ ꮤ ꮶ ꭴ ꭾ ꮗ ꮝ ꮿ"
-  AF_BLUE_STRING_CHEROKEE_SMALL
-    "ꮖ ꭼ ꮓ ꮠ ꮳ ꭶ ꮥ ꮻ"
-  AF_BLUE_STRING_CHEROKEE_SMALL_DESCENDER
-    "ᏸ ꮐ ꭹ ꭻ"
-
-  AF_BLUE_STRING_COPTIC_CAPITAL_TOP
-    "Ⲍ Ⲏ Ⲡ Ⳟ Ⲟ Ⲑ Ⲥ Ⳋ"
-  AF_BLUE_STRING_COPTIC_CAPITAL_BOTTOM
-    "Ⳑ Ⳙ Ⳟ Ⲏ Ⲟ Ⲑ Ⳝ Ⲱ"
-  AF_BLUE_STRING_COPTIC_SMALL_TOP
-    "ⲍ ⲏ ⲡ ⳟ ⲟ ⲑ ⲥ ⳋ"
-  AF_BLUE_STRING_COPTIC_SMALL_BOTTOM
-    "ⳑ ⳙ ⳟ ⲏ ⲟ ⲑ ⳝ Ⳓ"
-
-  AF_BLUE_STRING_CYPRIOT_TOP
-    "𐠍 𐠙 𐠳 𐠱 𐠅 𐠓 𐠣 𐠦"
-  AF_BLUE_STRING_CYPRIOT_BOTTOM
-    "𐠃 𐠊 𐠛 𐠣 𐠳 𐠵 𐠐"
-  AF_BLUE_STRING_CYPRIOT_SMALL
-    "𐠈 𐠏 𐠖"
-
-  AF_BLUE_STRING_CYRILLIC_CAPITAL_TOP
-    "Б В Е П З О С Э"
-  AF_BLUE_STRING_CYRILLIC_CAPITAL_BOTTOM
-    "Б В Е Ш З О С Э"
-  AF_BLUE_STRING_CYRILLIC_SMALL
-    "х п н ш е з о с"
-  AF_BLUE_STRING_CYRILLIC_SMALL_DESCENDER
-    "р у ф"
-
-  AF_BLUE_STRING_DESERET_CAPITAL_TOP
-    "𐐂 𐐄 𐐋 𐐗 𐐑"
-  AF_BLUE_STRING_DESERET_CAPITAL_BOTTOM
-    "𐐀 𐐂 𐐄 𐐗 𐐛"
-  AF_BLUE_STRING_DESERET_SMALL_TOP
-    "𐐪 𐐬 𐐳 𐐿 𐐹"
-  AF_BLUE_STRING_DESERET_SMALL_BOTTOM
-    "𐐨 𐐪 𐐬 𐐿 𐑃"
-
-  AF_BLUE_STRING_DEVANAGARI_BASE
-    "क न म उ छ ट ठ ड"
-  AF_BLUE_STRING_DEVANAGARI_TOP
-    "ई ऐ ओ औ ि ी ो ौ"
-  // note that some fonts have extreme variation in the height of the
-  // round head elements; for this reason we also define the `base'
-  // blue zone, which must be always present
-  AF_BLUE_STRING_DEVANAGARI_HEAD
-    "क म अ आ थ ध भ श"
-  AF_BLUE_STRING_DEVANAGARI_BOTTOM
-    "ु ृ"
-
-  AF_BLUE_STRING_ETHIOPIC_TOP
-    "ሀ ሃ ዘ ፐ ማ በ ዋ ዐ"
-  AF_BLUE_STRING_ETHIOPIC_BOTTOM
-    "ለ ሐ በ ዘ ሀ ሪ ዐ ጨ"
-
-  AF_BLUE_STRING_GEORGIAN_MKHEDRULI_TOP
-    "გ დ ე ვ თ ი ო ღ"
-  AF_BLUE_STRING_GEORGIAN_MKHEDRULI_BOTTOM
-    "ა ზ მ ს შ ძ ხ პ"
-  AF_BLUE_STRING_GEORGIAN_MKHEDRULI_ASCENDER
-    "ს ხ ქ ზ მ შ ჩ წ"
-  AF_BLUE_STRING_GEORGIAN_MKHEDRULI_DESCENDER
-    "ე ვ ჟ ტ უ ფ ქ ყ"
-
-  AF_BLUE_STRING_GEORGIAN_ASOMTAVRULI_TOP
-    "Ⴑ Ⴇ Ⴙ Ⴜ Ⴄ Ⴅ Ⴓ Ⴚ"
-  AF_BLUE_STRING_GEORGIAN_ASOMTAVRULI_BOTTOM
-    "Ⴄ Ⴅ Ⴇ Ⴈ Ⴆ Ⴑ Ⴊ Ⴋ"
-
-  AF_BLUE_STRING_GEORGIAN_NUSKHURI_TOP
-    "ⴁ ⴗ ⴂ ⴄ ⴅ ⴇ ⴔ ⴖ"
-  AF_BLUE_STRING_GEORGIAN_NUSKHURI_BOTTOM
-    "ⴈ ⴌ ⴖ ⴎ ⴃ ⴆ ⴋ ⴢ"
-  AF_BLUE_STRING_GEORGIAN_NUSKHURI_ASCENDER
-    "ⴐ ⴑ ⴓ ⴕ ⴙ ⴛ ⴡ ⴣ"
-  AF_BLUE_STRING_GEORGIAN_NUSKHURI_DESCENDER
-    "ⴄ ⴅ ⴔ ⴕ ⴁ ⴂ ⴘ ⴝ"
-
-  AF_BLUE_STRING_GEORGIAN_MTAVRULI_TOP
-    "Ნ Ჟ Ჳ Ჸ Გ Ე Ო Ჴ"
-  AF_BLUE_STRING_GEORGIAN_MTAVRULI_BOTTOM
-    "Ი Ჲ Ო Ჩ Მ Შ Ჯ Ჽ"
-
-  AF_BLUE_STRING_GLAGOLITIC_CAPITAL_TOP
-    "Ⰵ Ⱄ Ⱚ Ⰴ Ⰲ Ⰺ Ⱛ Ⰻ"
-  AF_BLUE_STRING_GLAGOLITIC_CAPITAL_BOTTOM
-    "Ⰵ Ⰴ Ⰲ Ⱚ Ⱎ Ⱑ Ⰺ Ⱄ"
-  AF_BLUE_STRING_GLAGOLITIC_SMALL_TOP
-    "ⰵ ⱄ ⱚ ⰴ ⰲ ⰺ ⱛ ⰻ"
-  AF_BLUE_STRING_GLAGOLITIC_SMALL_BOTTOM
-    "ⰵ ⰴ ⰲ ⱚ ⱎ ⱑ ⰺ ⱄ"
-
-  AF_BLUE_STRING_GOTHIC_TOP
-    "𐌲 𐌶 𐍀 𐍄 𐌴 𐍃 𐍈 𐌾"
-  AF_BLUE_STRING_GOTHIC_BOTTOM
-    "𐌶 𐌴 𐍃 𐍈"
-
-  AF_BLUE_STRING_GREEK_CAPITAL_TOP
-    "Γ Β Ε Ζ Θ Ο Ω"
-  AF_BLUE_STRING_GREEK_CAPITAL_BOTTOM
-    "Β Δ Ζ Ξ Θ Ο"
-  AF_BLUE_STRING_GREEK_SMALL_BETA_TOP
-    "β θ δ ζ λ ξ"
-  AF_BLUE_STRING_GREEK_SMALL
-    "α ε ι ο π σ τ ω"
-  AF_BLUE_STRING_GREEK_SMALL_DESCENDER
-    "β γ η μ ρ φ χ ψ"
-
-  AF_BLUE_STRING_GUJARATI_TOP
-    "ત ન ઋ ઌ છ ટ ર ૦"
-  AF_BLUE_STRING_GUJARATI_BOTTOM
-    "ખ ગ ઘ ઞ ઇ ઈ ઠ જ"
-  AF_BLUE_STRING_GUJARATI_ASCENDER
-    "ઈ ઊ િ ી લી શ્ચિ જિ સી"
-  AF_BLUE_STRING_GUJARATI_DESCENDER
-    "ુ ૃ ૄ ખુ છૃ છૄ"
-  AF_BLUE_STRING_GUJARATI_DIGIT_TOP
-    "૦ ૧ ૨ ૩ ૭"
-
-  AF_BLUE_STRING_GURMUKHI_BASE
-    "ਕ ਗ ਙ ਚ ਜ ਤ ਧ ਸ"
-  AF_BLUE_STRING_GURMUKHI_HEAD
-    "ਕ ਗ ਙ ਚ ਜ ਤ ਧ ਸ"
-  AF_BLUE_STRING_GURMUKHI_TOP
-    "ਇ ਈ ਉ ਏ ਓ ੳ ਿ ੀ"
-  AF_BLUE_STRING_GURMUKHI_BOTTOM
-    "ਅ ਏ ਓ ਗ ਜ ਠ ਰ ਸ"
-  AF_BLUE_STRING_GURMUKHI_DIGIT_TOP
-    "੦ ੧ ੨ ੩ ੭"
-
-  AF_BLUE_STRING_HEBREW_TOP
-    "ב ד ה ח ך כ ם ס"
-  AF_BLUE_STRING_HEBREW_BOTTOM
-    "ב ט כ ם ס צ"
-  AF_BLUE_STRING_HEBREW_DESCENDER
-    "ק ך ן ף ץ"
-
-  AF_BLUE_STRING_KANNADA_TOP
-    "ಇ ಊ ಐ ಣ ಸಾ ನಾ ದಾ ರಾ"
-  AF_BLUE_STRING_KANNADA_BOTTOM
-    "ಅ ಉ ಎ ಲ ೦ ೨ ೬ ೭"
-
-  AF_BLUE_STRING_KAYAH_LI_TOP
-    "꤅ ꤏ ꤁ ꤋ ꤀ ꤍ"
-  AF_BLUE_STRING_KAYAH_LI_BOTTOM
-    "꤈ ꤘ ꤀ ꤍ ꤢ"
-  AF_BLUE_STRING_KAYAH_LI_ASCENDER
-    "ꤖ ꤡ"
-  AF_BLUE_STRING_KAYAH_LI_DESCENDER
-    "ꤑ ꤜ ꤞ"
-  AF_BLUE_STRING_KAYAH_LI_LARGE_DESCENDER
-    "ꤑ꤬ ꤜ꤭ ꤔ꤬"
-
-  AF_BLUE_STRING_KHMER_TOP
-    "ខ ទ ន ឧ ឩ ា"
-  AF_BLUE_STRING_KHMER_SUBSCRIPT_TOP
-    "ក្ក ក្ខ ក្គ ក្ថ"
-  AF_BLUE_STRING_KHMER_BOTTOM
-    "ខ ឃ ច ឋ ប ម យ ឲ"
-  AF_BLUE_STRING_KHMER_DESCENDER
-    "ត្រ រៀ ឲ្យ អឿ"
-  AF_BLUE_STRING_KHMER_LARGE_DESCENDER
-    "ន្ត្រៃ ង្ខ្យ ក្បៀ ច្រៀ ន្តឿ ល្បឿ"
-
-  AF_BLUE_STRING_KHMER_SYMBOLS_WAXING_TOP
-    "᧠ ᧡"
-  AF_BLUE_STRING_KHMER_SYMBOLS_WANING_BOTTOM
-    "᧶ ᧹"
-
-  AF_BLUE_STRING_LAO_TOP
-    "າ ດ ອ ມ ລ ວ ຣ ງ"
-  AF_BLUE_STRING_LAO_BOTTOM
-    "າ ອ ບ ຍ ຣ ຮ ວ ຢ"
-  AF_BLUE_STRING_LAO_ASCENDER
-    "ປ ຢ ຟ ຝ"
-  AF_BLUE_STRING_LAO_LARGE_ASCENDER
-    "ໂ ໄ ໃ"
-  AF_BLUE_STRING_LAO_DESCENDER
-    "ງ ຊ ຖ ຽ ໆ ຯ"
-
-  AF_BLUE_STRING_LATIN_CAPITAL_TOP
-    "T H E Z O C Q S"
-  AF_BLUE_STRING_LATIN_CAPITAL_BOTTOM
-    "H E Z L O C U S"
-  AF_BLUE_STRING_LATIN_SMALL_F_TOP
-    "f i j k d b h"
-  AF_BLUE_STRING_LATIN_SMALL_TOP
-    "u v x z o e s c"
-  AF_BLUE_STRING_LATIN_SMALL_BOTTOM
-    "n r x z o e s c"
-  AF_BLUE_STRING_LATIN_SMALL_DESCENDER
-    "p q g j y"
-
-  // we assume that both the subscript and superscript ranges
-  // don't contain oldstyle digits (actually, most fonts probably
-  // have digits only in those ranges)
-  AF_BLUE_STRING_LATIN_SUBS_CAPITAL_TOP
-    "₀ ₃ ₅ ₇ ₈"
-  AF_BLUE_STRING_LATIN_SUBS_CAPITAL_BOTTOM
-    "₀ ₁ ₂ ₃ ₈"
-  AF_BLUE_STRING_LATIN_SUBS_SMALL_F_TOP
-    "ᵢ ⱼ ₕ ₖ ₗ"
-  AF_BLUE_STRING_LATIN_SUBS_SMALL
-    "ₐ ₑ ₒ ₓ ₙ ₛ ᵥ ᵤ ᵣ"
-  AF_BLUE_STRING_LATIN_SUBS_SMALL_DESCENDER
-    "ᵦ ᵧ ᵨ ᵩ ₚ"
-
-  AF_BLUE_STRING_LATIN_SUPS_CAPITAL_TOP
-    "⁰ ³ ⁵ ⁷ ᵀ ᴴ ᴱ ᴼ"
-  AF_BLUE_STRING_LATIN_SUPS_CAPITAL_BOTTOM
-    "⁰ ¹ ² ³ ᴱ ᴸ ᴼ ᵁ"
-  AF_BLUE_STRING_LATIN_SUPS_SMALL_F_TOP
-    "ᵇ ᵈ ᵏ ʰ ʲ ᶠ ⁱ"
-  AF_BLUE_STRING_LATIN_SUPS_SMALL
-    "ᵉ ᵒ ʳ ˢ ˣ ᶜ ᶻ"
-  AF_BLUE_STRING_LATIN_SUPS_SMALL_DESCENDER
-    "ᵖ ʸ ᵍ"
-
-  AF_BLUE_STRING_LISU_TOP
-    "ꓡ ꓧ ꓱ ꓶ ꓩ ꓚ ꓵ ꓳ"
-  AF_BLUE_STRING_LISU_BOTTOM
-    "ꓕ ꓜ ꓞ ꓡ ꓛ ꓢ ꓳ ꓴ"
-
-  AF_BLUE_STRING_MALAYALAM_TOP
-    "ഒ ട ഠ റ ച പ ച്ച പ്പ"
-  AF_BLUE_STRING_MALAYALAM_BOTTOM
-    "ട ഠ ധ ശ ഘ ച ഥ ല"
-
-  AF_BLUE_STRING_MEDEFAIDRIN_CAPITAL_TOP
-    "𖹀 𖹁 𖹂 𖹃 𖹏 𖹚 𖹟"
-  AF_BLUE_STRING_MEDEFAIDRIN_CAPITAL_BOTTOM
-    "𖹀 𖹁 𖹂 𖹃 𖹏 𖹚 𖹒 𖹓"
-  AF_BLUE_STRING_MEDEFAIDRIN_SMALL_F_TOP
-    "𖹤 𖹬 𖹧 𖹴 𖹶 𖹾"
-  AF_BLUE_STRING_MEDEFAIDRIN_SMALL_TOP
-    "𖹠 𖹡 𖹢 𖹹 𖹳 𖹮"
-  AF_BLUE_STRING_MEDEFAIDRIN_SMALL_BOTTOM
-    "𖹠 𖹡 𖹢 𖹳 𖹭 𖹽"
-  AF_BLUE_STRING_MEDEFAIDRIN_SMALL_DESCENDER
-    "𖹥 𖹨 𖹩"
-  AF_BLUE_STRING_MEDEFAIDRIN_DIGIT_TOP
-    "𖺀 𖺅 𖺈 𖺄 𖺍"
-
-  AF_BLUE_STRING_MONGOLIAN_TOP_BASE
-    "ᠳ ᠴ ᠶ ᠽ ᡂ ᡊ ‍ᡡ‍ ‍ᡳ‍"
-  AF_BLUE_STRING_MONGOLIAN_BOTTOM_BASE
-    "ᡃ"
-
-  AF_BLUE_STRING_MYANMAR_TOP
-    "ခ ဂ င ဒ ဝ ၥ ၊ ။"
-  AF_BLUE_STRING_MYANMAR_BOTTOM
-    "င ဎ ဒ ပ ဗ ဝ ၊ ။"
-  AF_BLUE_STRING_MYANMAR_ASCENDER
-    "ဩ ြ ၍ ၏ ၆ ါ ိ"
-  AF_BLUE_STRING_MYANMAR_DESCENDER
-    "ဉ ည ဥ ဩ ဨ ၂ ၅ ၉"
-
-  AF_BLUE_STRING_NKO_TOP
-    "ߐ ߉ ߒ ߟ ߖ ߜ ߠ ߥ"
-  AF_BLUE_STRING_NKO_BOTTOM
-    "߀ ߘ ߡ ߠ ߥ"
-  AF_BLUE_STRING_NKO_SMALL_TOP
-    "ߏ ߛ ߋ"
-  AF_BLUE_STRING_NKO_SMALL_BOTTOM
-    "ߎ ߏ ߛ ߋ"
-
-  AF_BLUE_STRING_OL_CHIKI
-    "ᱛ ᱜ ᱝ ᱡ ᱢ ᱥ"
-
-  AF_BLUE_STRING_OLD_TURKIC_TOP
-    "𐰗 𐰘 𐰧"
-  AF_BLUE_STRING_OLD_TURKIC_BOTTOM
-    "𐰉 𐰗 𐰦 𐰧"
-
-  AF_BLUE_STRING_OSAGE_CAPITAL_TOP
-    "𐒾 𐓍 𐓒 𐓓 𐒻 𐓂 𐒵 𐓆"
-  AF_BLUE_STRING_OSAGE_CAPITAL_BOTTOM
-    "𐒰 𐓍 𐓂 𐒿 𐓎 𐒹"
-  AF_BLUE_STRING_OSAGE_CAPITAL_DESCENDER
-    "𐒼 𐒽 𐒾"
-  AF_BLUE_STRING_OSAGE_SMALL_TOP
-    "𐓵 𐓶 𐓺 𐓻 𐓝 𐓣 𐓪 𐓮"
-  AF_BLUE_STRING_OSAGE_SMALL_BOTTOM
-    "𐓘 𐓚 𐓣 𐓵 𐓡 𐓧 𐓪 𐓶"
-  AF_BLUE_STRING_OSAGE_SMALL_ASCENDER
-    "𐓤 𐓦 𐓸 𐓹 𐓛"
-  AF_BLUE_STRING_OSAGE_SMALL_DESCENDER
-    "𐓤 𐓥 𐓦"
-
-  AF_BLUE_STRING_OSMANYA_TOP
-    "𐒆 𐒉 𐒐 𐒒 𐒘 𐒛 𐒠 𐒣"
-  AF_BLUE_STRING_OSMANYA_BOTTOM
-    "𐒀 𐒂 𐒆 𐒈 𐒊 𐒒 𐒠 𐒩"
-
-  AF_BLUE_STRING_ROHINGYA_TOP
-    "𐴃 𐴀 𐴆 𐴖 𐴕"
-  AF_BLUE_STRING_ROHINGYA_BOTTOM
-    "𐴔 𐴖 𐴕 𐴑 𐴐"
-  AF_BLUE_STRING_ROHINGYA_JOIN
-    "ـ"
-
-  AF_BLUE_STRING_SAURASHTRA_TOP
-    "ꢜ ꢞ ꢳ ꢂ ꢖ ꢒ ꢝ ꢛ"
-  AF_BLUE_STRING_SAURASHTRA_BOTTOM
-    "ꢂ ꢨ ꢺ ꢤ ꢎ"
-
-  AF_BLUE_STRING_SHAVIAN_TOP
-    "𐑕 𐑙"
-  AF_BLUE_STRING_SHAVIAN_BOTTOM
-    "𐑔 𐑖 𐑗 𐑹 𐑻"
-  AF_BLUE_STRING_SHAVIAN_DESCENDER
-    "𐑟 𐑣"
-  AF_BLUE_STRING_SHAVIAN_SMALL_TOP
-    "𐑱 𐑲 𐑳 𐑴 𐑸 𐑺 𐑼"
-  AF_BLUE_STRING_SHAVIAN_SMALL_BOTTOM
-    "𐑴 𐑻 𐑹"
-
-  AF_BLUE_STRING_SINHALA_TOP
-    "ඉ ක ඝ ඳ ප ය ල ෆ"
-  AF_BLUE_STRING_SINHALA_BOTTOM
-    "එ ඔ ඝ ජ ට ථ ධ ර"
-  AF_BLUE_STRING_SINHALA_DESCENDER
-    "ද ඳ උ ල තූ තු බු දු"
-
-  AF_BLUE_STRING_SUNDANESE_TOP
-    "ᮋ ᮞ ᮮ ᮽ ᮰ ᮈ"
-  AF_BLUE_STRING_SUNDANESE_BOTTOM
-    "ᮄ ᮔ ᮕ ᮗ ᮰ ᮆ ᮈ ᮉ"
-  AF_BLUE_STRING_SUNDANESE_DESCENDER
-    "ᮼ ᳄"
-
-  AF_BLUE_STRING_TAI_VIET_TOP
-    "ꪆ ꪔ ꪒ ꪖ ꪫ"
-  AF_BLUE_STRING_TAI_VIET_BOTTOM
-    "ꪉ ꪫ ꪮ"
-
-  AF_BLUE_STRING_TAMIL_TOP
-    "உ ஒ ஓ ற ஈ க ங ச"
-  AF_BLUE_STRING_TAMIL_BOTTOM
-    "க ச ல ஶ உ ங ட ப"
-
-  AF_BLUE_STRING_TELUGU_TOP
-    "ఇ ఌ ఙ ఞ ణ ఱ ౯"
-  AF_BLUE_STRING_TELUGU_BOTTOM
-    "అ క చ ర ఽ ౨ ౬"
-
-  AF_BLUE_STRING_THAI_TOP
-    "บ เ แ อ ก า"
-  AF_BLUE_STRING_THAI_BOTTOM
-    "บ ป ษ ฯ อ ย ฮ"
-  AF_BLUE_STRING_THAI_ASCENDER
-    "ป ฝ ฟ"
-  AF_BLUE_STRING_THAI_LARGE_ASCENDER
-    "โ ใ ไ"
-  AF_BLUE_STRING_THAI_DESCENDER
-    "ฎ ฏ ฤ ฦ"
-  AF_BLUE_STRING_THAI_LARGE_DESCENDER
-    "ญ ฐ"
-  AF_BLUE_STRING_THAI_DIGIT_TOP
-    "๐ ๑ ๓"
-
-  AF_BLUE_STRING_TIFINAGH
-    "ⵔ ⵙ ⵛ ⵞ ⴵ ⴼ ⴹ ⵎ"
-
-  AF_BLUE_STRING_VAI_TOP
-    "ꗍ ꘖ ꘙ ꘜ ꖜ ꖝ ꔅ ꕢ"
-  AF_BLUE_STRING_VAI_BOTTOM
-    "ꗍ ꘖ ꘙ ꗞ ꔅ ꕢ ꖜ ꔆ"
-
-
-#ifdef AF_CONFIG_OPTION_CJK
-
-  AF_BLUE_STRING_CJK_TOP
-    "他 们 你 來 們 到 和 地"
-    " 对 對 就 席 我 时 時 會"
-    " 来 為 能 舰 說 说 这 這"
-    " 齊 |"
-    " 军 同 已 愿 既 星 是 景"
-    " 民 照 现 現 理 用 置 要"
-    " 軍 那 配 里 開 雷 露 面"
-    " 顾"
-  AF_BLUE_STRING_CJK_BOTTOM
-    "个 为 人 他 以 们 你 來"
-    " 個 們 到 和 大 对 對 就"
-    " 我 时 時 有 来 為 要 說"
-    " 说 |"
-    " 主 些 因 它 想 意 理 生"
-    " 當 看 着 置 者 自 著 裡"
-    " 过 还 进 進 過 道 還 里"
-    " 面"
-
-#ifdef AF_CONFIG_OPTION_CJK_BLUE_HANI_VERT
-
-  AF_BLUE_STRING_CJK_LEFT
-    " 些 们 你 來 們 到 和 地"
-    " 她 将 將 就 年 得 情 最"
-    " 样 樣 理 能 說 说 这 這"
-    " 通 |"
-    " 即 吗 吧 听 呢 品 响 嗎"
-    " 师 師 收 断 斷 明 眼 間"
-    " 间 际 陈 限 除 陳 随 際"
-    " 隨"
-  AF_BLUE_STRING_CJK_RIGHT
-    "事 前 學 将 將 情 想 或"
-    " 政 斯 新 样 樣 民 沒 没"
-    " 然 特 现 現 球 第 經 谁"
-    " 起 |"
-    " 例 別 别 制 动 動 吗 嗎"
-    " 增 指 明 朝 期 构 物 确"
-    " 种 調 调 費 费 那 都 間"
-    " 间"
-
-#endif /* AF_CONFIG_OPTION_CJK_BLUE_HANI_VERT */
-
-#endif /* AF_CONFIG_OPTION_CJK                */
-
-
-// The blue zone stringsets, as used in the script styles, cf. `afstyles.h'.
-//
-// The AF_BLUE_PROPERTY_XXX flags are defined in `afblue.h'; here some
-// explanations.
-//
-// A blue zone in general is defined by a reference and an overshoot line.
-// During the hinting process, all coordinate values between those two lines
-// are set equal to the reference value, provided that the blue zone is not
-// wider than 0.75 pixels (otherwise the blue zone gets ignored).  All
-// entries must have `AF_BLUE_STRING_MAX' as the final line.
-//
-// During the glyph analysis, edges are sorted from bottom to top, and then
-// sequentially checked, edge by edge, against the blue zones in the order
-// given below.
-//
-//
-// latin auto-hinter
-// -----------------
-//
-// Characters in a blue string are automatically classified as having a flat
-// (reference) or a round (overshoot) extremum.  The blue zone is then set
-// up by the mean values of all flat extrema and all round extrema,
-// respectively.  Only horizontal blue zones (i.e., adjusting vertical
-// coordinate values) are supported.
-//
-// Some scripts like Khmer need character composition to get all necessary
-// blue zones, since Unicode only provides an abstract data model that
-// doesn't represent all possible glyph shapes.  For such character
-// clusters, the HarfBuzz library is used to convert them into the
-// corresponding glyphs.  The largest glyph element (where `largest' can be
-// either `largest ascender' or `largest descender') then defines the
-// corresponding flat or round extremum.
-//
-// For the latin auto-hinter, the overshoot should be larger than the
-// reference for top zones, and vice versa for bottom zones.
-//
-//   LATIN_TOP
-//     Take the maximum flat and round coordinate values of the blue string
-//     characters for computing the blue zone's reference and overshoot
-//     values.
-//
-//     If not set, take the minimum values.
-//
-//     Mutually exclusive with `LATIN_SUB_TOP'.
-//
-//   LATIN_SUB_TOP
-//     For all glyphs of a character cluster, compute the maximum flat
-//     and round coordinate values of each component, then take the
-//     smallest of the maximum values.  The idea is to get the top of
-//     subscript glyphs, as used in Khmer, for example.  Note that
-//     this mechanism doesn't work for ordinary ligatures.
-//
-//     This flags indicates a secondary blue zone: It gets removed if
-//     there is a non-LATIN_SUB_TOP blue zone at the same coordinate
-//     value (after scaling).
-//
-//     Mutually exclusive with `LATIN_TOP'.
-//
-//   LATIN_NEUTRAL
-//     Ignore round extrema and define the blue zone with flat values only.
-//     Both top and bottom of contours can match.  This is useful for
-//     scripts like Devanagari where vowel signs attach to the base
-//     character and are implemented as components of composite glyphs.
-//
-//     If not set, both round and flat extrema are taken into account.
-//     Additionally, only the top or the bottom of a contour can match,
-//     depending on the LATIN_TOP flag.
-//
-//     Neutral blue zones should always follow non-neutral blue zones.
-//
-//   LATIN_X_HEIGHT
-//     Scale all glyphs vertically from the corresponding script to make the
-//     reference line of this blue zone align on the grid.  The scaling
-//     takes place before all other blue zones get aligned to the grid.
-//     Only one blue character string of a script style can have this flag.
-//
-//   LATIN_LONG
-//     Apply an additional constraint for blue zone values: Don't
-//     necessarily use the extremum as-is but a segment of the topmost (or
-//     bottommost) contour that is longer than a heuristic threshold, and
-//     which is not too far away vertically from the real extremum.  This
-//     ensures that small bumps in the outline are ignored (for example, the
-//     `vertical serifs' found in many Hebrew glyph designs).
-//
-//     The segment must be at least EM/25 font units long, and the distance
-//     to the extremum must be smaller than EM/4.
-//
-//
-// cjk auto-hinter
-// ---------------
-//
-// Characters in a blue string are *not* automatically classified.  Instead,
-// first come the characters used for the overshoot value, then the
-// character `|', then the characters used for the reference value
-// (everything separated by space characters).  The blue zone is then set up
-// by the mean values of all reference values and all overshoot values,
-// respectively.  Both horizontal and vertical blue zones (i.e., adjusting
-// vertical and horizontal coordinate values, respectively) are supported.
-//
-// For the cjk auto-hinter, the overshoot should be smaller than the
-// reference for top zones, and vice versa for bottom zones.
-//
-//   CJK_TOP
-//     Take the maximum flat and round coordinate values of the blue string
-//     characters.  If not set, take the minimum values.
-//
-//   CJK_RIGHT
-//     A synonym for CJK_TOP.  If CJK_HORIZ is set, this flag indicates the
-//     right blue zone, taking horizontal maximum values.
-//
-//   CJK_HORIZ
-//     Define a blue zone for horizontal hinting (i.e., vertical blue
-//     zones).  If not set, this is a blue zone for vertical hinting.
-
-
-AF_BLUE_STRINGSET_ENUM AF_BLUE_STRINGSETS_ARRAY AF_BLUE_STRINGSET_MAX_LEN:
-
-  AF_BLUE_STRINGSET_ADLM
-    { AF_BLUE_STRING_ADLAM_CAPITAL_TOP,    AF_BLUE_PROPERTY_LATIN_TOP        }
-    { AF_BLUE_STRING_ADLAM_CAPITAL_BOTTOM, 0                                 }
-    { AF_BLUE_STRING_ADLAM_SMALL_TOP,      AF_BLUE_PROPERTY_LATIN_TOP      |
-                                           AF_BLUE_PROPERTY_LATIN_X_HEIGHT   }
-    { AF_BLUE_STRING_ADLAM_SMALL_BOTTOM,   0                                 }
-    { AF_BLUE_STRING_MAX,                  0                                 }
-
-  AF_BLUE_STRINGSET_ARAB
-    { AF_BLUE_STRING_ARABIC_TOP,    AF_BLUE_PROPERTY_LATIN_TOP     }
-    { AF_BLUE_STRING_ARABIC_BOTTOM, 0                              }
-    { AF_BLUE_STRING_ARABIC_JOIN,   AF_BLUE_PROPERTY_LATIN_NEUTRAL }
-    { AF_BLUE_STRING_MAX,           0                              }
-
-  AF_BLUE_STRINGSET_ARMN
-    { AF_BLUE_STRING_ARMENIAN_CAPITAL_TOP,     AF_BLUE_PROPERTY_LATIN_TOP        }
-    { AF_BLUE_STRING_ARMENIAN_CAPITAL_BOTTOM,  0                                 }
-    { AF_BLUE_STRING_ARMENIAN_SMALL_ASCENDER,  AF_BLUE_PROPERTY_LATIN_TOP        }
-    { AF_BLUE_STRING_ARMENIAN_SMALL_TOP,       AF_BLUE_PROPERTY_LATIN_TOP      |
-                                               AF_BLUE_PROPERTY_LATIN_X_HEIGHT   }
-    { AF_BLUE_STRING_ARMENIAN_SMALL_BOTTOM,    0                                 }
-    { AF_BLUE_STRING_ARMENIAN_SMALL_DESCENDER, 0                                 }
-    { AF_BLUE_STRING_MAX,                      0                                 }
-
-  AF_BLUE_STRINGSET_AVST
-    { AF_BLUE_STRING_AVESTAN_TOP,    AF_BLUE_PROPERTY_LATIN_TOP }
-    { AF_BLUE_STRING_AVESTAN_BOTTOM, 0                          }
-    { AF_BLUE_STRING_MAX,            0                          }
-
-  AF_BLUE_STRINGSET_BAMU
-    { AF_BLUE_STRING_BAMUM_TOP,    AF_BLUE_PROPERTY_LATIN_TOP }
-    { AF_BLUE_STRING_BAMUM_BOTTOM, 0                          }
-    { AF_BLUE_STRING_MAX,          0                          }
-
-  AF_BLUE_STRINGSET_BENG
-    { AF_BLUE_STRING_BENGALI_TOP,  AF_BLUE_PROPERTY_LATIN_TOP        }
-    { AF_BLUE_STRING_BENGALI_HEAD, AF_BLUE_PROPERTY_LATIN_TOP        }
-    { AF_BLUE_STRING_BENGALI_BASE, AF_BLUE_PROPERTY_LATIN_TOP      |
-                                   AF_BLUE_PROPERTY_LATIN_NEUTRAL  |
-                                   AF_BLUE_PROPERTY_LATIN_X_HEIGHT   }
-    { AF_BLUE_STRING_BENGALI_BASE, 0                                 }
-    { AF_BLUE_STRING_MAX,          0                                 }
-
-  AF_BLUE_STRINGSET_BUHD
-    { AF_BLUE_STRING_BUHID_TOP,    AF_BLUE_PROPERTY_LATIN_TOP        }
-    { AF_BLUE_STRING_BUHID_LARGE,  AF_BLUE_PROPERTY_LATIN_TOP        }
-    { AF_BLUE_STRING_BUHID_SMALL,  AF_BLUE_PROPERTY_LATIN_TOP      |
-                                   AF_BLUE_PROPERTY_LATIN_X_HEIGHT   }
-    { AF_BLUE_STRING_BUHID_BOTTOM, 0                                 }
-    { AF_BLUE_STRING_MAX,          0                                 }
-
-  AF_BLUE_STRINGSET_CAKM
-    { AF_BLUE_STRING_CHAKMA_TOP,       AF_BLUE_PROPERTY_LATIN_TOP }
-    { AF_BLUE_STRING_CHAKMA_BOTTOM,    0                          }
-    { AF_BLUE_STRING_CHAKMA_DESCENDER, 0                          }
-    { AF_BLUE_STRING_MAX,              0                          }
-
-  AF_BLUE_STRINGSET_CANS
-    { AF_BLUE_STRING_CANADIAN_SYLLABICS_TOP,          AF_BLUE_PROPERTY_LATIN_TOP        }
-    { AF_BLUE_STRING_CANADIAN_SYLLABICS_BOTTOM,       0                                 }
-    { AF_BLUE_STRING_CANADIAN_SYLLABICS_SMALL_TOP,    AF_BLUE_PROPERTY_LATIN_TOP      |
-                                                      AF_BLUE_PROPERTY_LATIN_X_HEIGHT   }
-    { AF_BLUE_STRING_CANADIAN_SYLLABICS_SMALL_BOTTOM, 0                                 }
-    { AF_BLUE_STRING_CANADIAN_SYLLABICS_SUPS_TOP,     AF_BLUE_PROPERTY_LATIN_TOP        }
-    { AF_BLUE_STRING_CANADIAN_SYLLABICS_SUPS_BOTTOM,  0                                 }
-    { AF_BLUE_STRING_MAX,                             0                                 }
-
-  AF_BLUE_STRINGSET_CARI
-    { AF_BLUE_STRING_CARIAN_TOP,    AF_BLUE_PROPERTY_LATIN_TOP }
-    { AF_BLUE_STRING_CARIAN_BOTTOM, 0                          }
-    { AF_BLUE_STRING_MAX,           0                          }
-
-  AF_BLUE_STRINGSET_CHER
-    { AF_BLUE_STRING_CHEROKEE_CAPITAL,         AF_BLUE_PROPERTY_LATIN_TOP        }
-    { AF_BLUE_STRING_CHEROKEE_CAPITAL,         0                                 }
-    { AF_BLUE_STRING_CHEROKEE_SMALL_ASCENDER,  AF_BLUE_PROPERTY_LATIN_TOP        }
-    { AF_BLUE_STRING_CHEROKEE_SMALL,           AF_BLUE_PROPERTY_LATIN_TOP      |
-                                               AF_BLUE_PROPERTY_LATIN_X_HEIGHT   }
-    { AF_BLUE_STRING_CHEROKEE_SMALL,           0                                 }
-    { AF_BLUE_STRING_CHEROKEE_SMALL_DESCENDER, 0                                 }
-    { AF_BLUE_STRING_MAX,                      0                                 }
-
-  AF_BLUE_STRINGSET_COPT
-    { AF_BLUE_STRING_COPTIC_CAPITAL_TOP,    AF_BLUE_PROPERTY_LATIN_TOP        }
-    { AF_BLUE_STRING_COPTIC_CAPITAL_BOTTOM, 0                                 }
-    { AF_BLUE_STRING_COPTIC_SMALL_TOP,      AF_BLUE_PROPERTY_LATIN_TOP      |
-                                            AF_BLUE_PROPERTY_LATIN_X_HEIGHT   }
-    { AF_BLUE_STRING_COPTIC_SMALL_BOTTOM,   0                                 }
-    { AF_BLUE_STRING_MAX,                   0                                 }
-
-  AF_BLUE_STRINGSET_CPRT
-    { AF_BLUE_STRING_CYPRIOT_TOP,    AF_BLUE_PROPERTY_LATIN_TOP }
-    { AF_BLUE_STRING_CYPRIOT_BOTTOM, 0                          }
-    { AF_BLUE_STRING_CYPRIOT_SMALL,  AF_BLUE_PROPERTY_LATIN_TOP }
-    { AF_BLUE_STRING_CYPRIOT_SMALL,  0                          }
-    { AF_BLUE_STRING_MAX,            0                          }
-
-  AF_BLUE_STRINGSET_CYRL
-    { AF_BLUE_STRING_CYRILLIC_CAPITAL_TOP,     AF_BLUE_PROPERTY_LATIN_TOP        }
-    { AF_BLUE_STRING_CYRILLIC_CAPITAL_BOTTOM,  0                                 }
-    { AF_BLUE_STRING_CYRILLIC_SMALL,           AF_BLUE_PROPERTY_LATIN_TOP      |
-                                               AF_BLUE_PROPERTY_LATIN_X_HEIGHT   }
-    { AF_BLUE_STRING_CYRILLIC_SMALL,           0                                 }
-    { AF_BLUE_STRING_CYRILLIC_SMALL_DESCENDER, 0                                 }
-    { AF_BLUE_STRING_MAX,                      0                                 }
-
-  AF_BLUE_STRINGSET_DEVA
-    { AF_BLUE_STRING_DEVANAGARI_TOP,    AF_BLUE_PROPERTY_LATIN_TOP        }
-    { AF_BLUE_STRING_DEVANAGARI_HEAD,   AF_BLUE_PROPERTY_LATIN_TOP        }
-    { AF_BLUE_STRING_DEVANAGARI_BASE,   AF_BLUE_PROPERTY_LATIN_TOP      |
-                                        AF_BLUE_PROPERTY_LATIN_NEUTRAL  |
-                                        AF_BLUE_PROPERTY_LATIN_X_HEIGHT   }
-    { AF_BLUE_STRING_DEVANAGARI_BASE,   0                                 }
-    { AF_BLUE_STRING_DEVANAGARI_BOTTOM, 0                                 }
-    { AF_BLUE_STRING_MAX,               0                                 }
-
-  AF_BLUE_STRINGSET_DSRT
-    { AF_BLUE_STRING_DESERET_CAPITAL_TOP,    AF_BLUE_PROPERTY_LATIN_TOP        }
-    { AF_BLUE_STRING_DESERET_CAPITAL_BOTTOM, 0                                 }
-    { AF_BLUE_STRING_DESERET_SMALL_TOP,      AF_BLUE_PROPERTY_LATIN_TOP      |
-                                             AF_BLUE_PROPERTY_LATIN_X_HEIGHT   }
-    { AF_BLUE_STRING_DESERET_SMALL_BOTTOM,   0                                 }
-    { AF_BLUE_STRING_MAX,                    0                                 }
-
-  AF_BLUE_STRINGSET_ETHI
-    { AF_BLUE_STRING_ETHIOPIC_TOP,    AF_BLUE_PROPERTY_LATIN_TOP }
-    { AF_BLUE_STRING_ETHIOPIC_BOTTOM, 0                          }
-    { AF_BLUE_STRING_MAX,             0                          }
-
-  AF_BLUE_STRINGSET_GEOR
-    { AF_BLUE_STRING_GEORGIAN_MKHEDRULI_TOP,       AF_BLUE_PROPERTY_LATIN_TOP      |
-                                                   AF_BLUE_PROPERTY_LATIN_X_HEIGHT   }
-    { AF_BLUE_STRING_GEORGIAN_MKHEDRULI_BOTTOM,    0                                 }
-    { AF_BLUE_STRING_GEORGIAN_MKHEDRULI_ASCENDER,  AF_BLUE_PROPERTY_LATIN_TOP        }
-    { AF_BLUE_STRING_GEORGIAN_MKHEDRULI_DESCENDER, 0                                 }
-    { AF_BLUE_STRING_GEORGIAN_MTAVRULI_TOP,        AF_BLUE_PROPERTY_LATIN_TOP        }
-    { AF_BLUE_STRING_GEORGIAN_MTAVRULI_BOTTOM,     0                                 }
-    { AF_BLUE_STRING_MAX,                          0                                 }
-
-  AF_BLUE_STRINGSET_GEOK
-    { AF_BLUE_STRING_GEORGIAN_ASOMTAVRULI_TOP,    AF_BLUE_PROPERTY_LATIN_TOP        }
-    { AF_BLUE_STRING_GEORGIAN_ASOMTAVRULI_BOTTOM, 0                                 }
-    { AF_BLUE_STRING_GEORGIAN_NUSKHURI_TOP,       AF_BLUE_PROPERTY_LATIN_TOP      |
-                                                  AF_BLUE_PROPERTY_LATIN_X_HEIGHT   }
-    { AF_BLUE_STRING_GEORGIAN_NUSKHURI_BOTTOM,    0                                 }
-    { AF_BLUE_STRING_GEORGIAN_NUSKHURI_ASCENDER,  AF_BLUE_PROPERTY_LATIN_TOP        }
-    { AF_BLUE_STRING_GEORGIAN_NUSKHURI_DESCENDER, 0                                 }
-    { AF_BLUE_STRING_MAX,                         0                                 }
-
-  AF_BLUE_STRINGSET_GLAG
-    { AF_BLUE_STRING_GLAGOLITIC_CAPITAL_TOP,    AF_BLUE_PROPERTY_LATIN_TOP        }
-    { AF_BLUE_STRING_GLAGOLITIC_CAPITAL_BOTTOM, 0                                 }
-    { AF_BLUE_STRING_GLAGOLITIC_SMALL_TOP,      AF_BLUE_PROPERTY_LATIN_TOP      |
-                                                AF_BLUE_PROPERTY_LATIN_X_HEIGHT   }
-    { AF_BLUE_STRING_GLAGOLITIC_SMALL_BOTTOM,   0                                 }
-    { AF_BLUE_STRING_MAX,                       0                                 }
-
-  AF_BLUE_STRINGSET_GOTH
-    { AF_BLUE_STRING_GOTHIC_TOP,    AF_BLUE_PROPERTY_LATIN_TOP }
-    { AF_BLUE_STRING_GOTHIC_BOTTOM, 0                          }
-    { AF_BLUE_STRING_MAX,           0                          }
-
-  AF_BLUE_STRINGSET_GREK
-    { AF_BLUE_STRING_GREEK_CAPITAL_TOP,     AF_BLUE_PROPERTY_LATIN_TOP        }
-    { AF_BLUE_STRING_GREEK_CAPITAL_BOTTOM,  0                                 }
-    { AF_BLUE_STRING_GREEK_SMALL_BETA_TOP,  AF_BLUE_PROPERTY_LATIN_TOP        }
-    { AF_BLUE_STRING_GREEK_SMALL,           AF_BLUE_PROPERTY_LATIN_TOP      |
-                                            AF_BLUE_PROPERTY_LATIN_X_HEIGHT   }
-    { AF_BLUE_STRING_GREEK_SMALL,           0                                 }
-    { AF_BLUE_STRING_GREEK_SMALL_DESCENDER, 0                                 }
-    { AF_BLUE_STRING_MAX,                   0                                 }
-
-  AF_BLUE_STRINGSET_GUJR
-    { AF_BLUE_STRING_GUJARATI_TOP,       AF_BLUE_PROPERTY_LATIN_TOP      |
-                                         AF_BLUE_PROPERTY_LATIN_X_HEIGHT   }
-    { AF_BLUE_STRING_GUJARATI_BOTTOM,    0                                 }
-    { AF_BLUE_STRING_GUJARATI_ASCENDER,  AF_BLUE_PROPERTY_LATIN_TOP        }
-    { AF_BLUE_STRING_GUJARATI_DESCENDER, 0                                 }
-    { AF_BLUE_STRING_GUJARATI_DIGIT_TOP, AF_BLUE_PROPERTY_LATIN_TOP        }
-    { AF_BLUE_STRING_MAX,                0                                 }
-
-  AF_BLUE_STRINGSET_GURU
-    { AF_BLUE_STRING_GURMUKHI_TOP,       AF_BLUE_PROPERTY_LATIN_TOP        }
-    { AF_BLUE_STRING_GURMUKHI_HEAD,      AF_BLUE_PROPERTY_LATIN_TOP        }
-    { AF_BLUE_STRING_GURMUKHI_BASE,      AF_BLUE_PROPERTY_LATIN_TOP      |
-                                         AF_BLUE_PROPERTY_LATIN_NEUTRAL  |
-                                         AF_BLUE_PROPERTY_LATIN_X_HEIGHT   }
-    { AF_BLUE_STRING_GURMUKHI_BOTTOM,    0                                 }
-    { AF_BLUE_STRING_GURMUKHI_DIGIT_TOP, AF_BLUE_PROPERTY_LATIN_TOP        }
-    { AF_BLUE_STRING_MAX,                0                                 }
-
-  AF_BLUE_STRINGSET_HEBR
-    { AF_BLUE_STRING_HEBREW_TOP,       AF_BLUE_PROPERTY_LATIN_TOP  |
-                                       AF_BLUE_PROPERTY_LATIN_LONG   }
-    { AF_BLUE_STRING_HEBREW_BOTTOM,    0                             }
-    { AF_BLUE_STRING_HEBREW_DESCENDER, 0                             }
-    { AF_BLUE_STRING_MAX,              0                             }
-
-  AF_BLUE_STRINGSET_KNDA
-    { AF_BLUE_STRING_KANNADA_TOP,    AF_BLUE_PROPERTY_LATIN_TOP }
-    { AF_BLUE_STRING_KANNADA_BOTTOM, 0                          }
-    { AF_BLUE_STRING_MAX,            0                          }
-
-  AF_BLUE_STRINGSET_KALI
-    { AF_BLUE_STRING_KAYAH_LI_TOP,             AF_BLUE_PROPERTY_LATIN_TOP      |
-                                               AF_BLUE_PROPERTY_LATIN_X_HEIGHT   }
-    { AF_BLUE_STRING_KAYAH_LI_BOTTOM,          0                                 }
-    { AF_BLUE_STRING_KAYAH_LI_ASCENDER,        AF_BLUE_PROPERTY_LATIN_TOP        }
-    { AF_BLUE_STRING_KAYAH_LI_DESCENDER,       0                                 }
-    { AF_BLUE_STRING_KAYAH_LI_LARGE_DESCENDER, 0                                 }
-    { AF_BLUE_STRING_MAX,                      0                                 }
-
-  AF_BLUE_STRINGSET_KHMR
-    { AF_BLUE_STRING_KHMER_TOP,             AF_BLUE_PROPERTY_LATIN_TOP      |
-                                            AF_BLUE_PROPERTY_LATIN_X_HEIGHT   }
-    { AF_BLUE_STRING_KHMER_SUBSCRIPT_TOP,   AF_BLUE_PROPERTY_LATIN_SUB_TOP    }
-    { AF_BLUE_STRING_KHMER_BOTTOM,          0                                 }
-    { AF_BLUE_STRING_KHMER_DESCENDER,       0                                 }
-    { AF_BLUE_STRING_KHMER_LARGE_DESCENDER, 0                                 }
-    { AF_BLUE_STRING_MAX,                   0                                 }
-
-  AF_BLUE_STRINGSET_KHMS
-    { AF_BLUE_STRING_KHMER_SYMBOLS_WAXING_TOP,    AF_BLUE_PROPERTY_LATIN_TOP      |
-                                                  AF_BLUE_PROPERTY_LATIN_X_HEIGHT   }
-    { AF_BLUE_STRING_KHMER_SYMBOLS_WANING_BOTTOM, 0                                 }
-    { AF_BLUE_STRING_MAX,                         0                                 }
-
-  AF_BLUE_STRINGSET_LAO
-    { AF_BLUE_STRING_LAO_TOP,            AF_BLUE_PROPERTY_LATIN_TOP      |
-                                         AF_BLUE_PROPERTY_LATIN_X_HEIGHT   }
-    { AF_BLUE_STRING_LAO_BOTTOM,         0                                 }
-    { AF_BLUE_STRING_LAO_ASCENDER,       AF_BLUE_PROPERTY_LATIN_TOP        }
-    { AF_BLUE_STRING_LAO_LARGE_ASCENDER, AF_BLUE_PROPERTY_LATIN_TOP        }
-    { AF_BLUE_STRING_LAO_DESCENDER,      0                                 }
-    { AF_BLUE_STRING_MAX,                0                                 }
-
-  AF_BLUE_STRINGSET_LATN
-    { AF_BLUE_STRING_LATIN_CAPITAL_TOP,     AF_BLUE_PROPERTY_LATIN_TOP        }
-    { AF_BLUE_STRING_LATIN_CAPITAL_BOTTOM,  0                                 }
-    { AF_BLUE_STRING_LATIN_SMALL_F_TOP,     AF_BLUE_PROPERTY_LATIN_TOP        }
-    { AF_BLUE_STRING_LATIN_SMALL_TOP,       AF_BLUE_PROPERTY_LATIN_TOP      |
-                                            AF_BLUE_PROPERTY_LATIN_X_HEIGHT   }
-    { AF_BLUE_STRING_LATIN_SMALL_BOTTOM,    0                                 }
-    { AF_BLUE_STRING_LATIN_SMALL_DESCENDER, 0                                 }
-    { AF_BLUE_STRING_MAX,                   0                                 }
-
-  AF_BLUE_STRINGSET_LATB
-    { AF_BLUE_STRING_LATIN_SUBS_CAPITAL_TOP,     AF_BLUE_PROPERTY_LATIN_TOP        }
-    { AF_BLUE_STRING_LATIN_SUBS_CAPITAL_BOTTOM,  0                                 }
-    { AF_BLUE_STRING_LATIN_SUBS_SMALL_F_TOP,     AF_BLUE_PROPERTY_LATIN_TOP        }
-    { AF_BLUE_STRING_LATIN_SUBS_SMALL,           AF_BLUE_PROPERTY_LATIN_TOP      |
-                                                 AF_BLUE_PROPERTY_LATIN_X_HEIGHT   }
-    { AF_BLUE_STRING_LATIN_SUBS_SMALL,           0                                 }
-    { AF_BLUE_STRING_LATIN_SUBS_SMALL_DESCENDER, 0                                 }
-    { AF_BLUE_STRING_MAX,                        0                                 }
-
-  AF_BLUE_STRINGSET_LATP
-    { AF_BLUE_STRING_LATIN_SUPS_CAPITAL_TOP,     AF_BLUE_PROPERTY_LATIN_TOP        }
-    { AF_BLUE_STRING_LATIN_SUPS_CAPITAL_BOTTOM,  0                                 }
-    { AF_BLUE_STRING_LATIN_SUPS_SMALL_F_TOP,     AF_BLUE_PROPERTY_LATIN_TOP        }
-    { AF_BLUE_STRING_LATIN_SUPS_SMALL,           AF_BLUE_PROPERTY_LATIN_TOP      |
-                                                 AF_BLUE_PROPERTY_LATIN_X_HEIGHT   }
-    { AF_BLUE_STRING_LATIN_SUPS_SMALL,           0                                 }
-    { AF_BLUE_STRING_LATIN_SUPS_SMALL_DESCENDER, 0                                 }
-    { AF_BLUE_STRING_MAX,                        0                                 }
-
-  AF_BLUE_STRINGSET_LISU
-    { AF_BLUE_STRING_LISU_TOP,    AF_BLUE_PROPERTY_LATIN_TOP }
-    { AF_BLUE_STRING_LISU_BOTTOM, 0                          }
-    { AF_BLUE_STRING_MAX,         0                          }
-
-  AF_BLUE_STRINGSET_MLYM
-    { AF_BLUE_STRING_MALAYALAM_TOP,    AF_BLUE_PROPERTY_LATIN_TOP }
-    { AF_BLUE_STRING_MALAYALAM_BOTTOM, 0                          }
-    { AF_BLUE_STRING_MAX,              0                          }
-
-  AF_BLUE_STRINGSET_MEDF
-    { AF_BLUE_STRING_MEDEFAIDRIN_CAPITAL_TOP,     AF_BLUE_PROPERTY_LATIN_TOP        }
-    { AF_BLUE_STRING_MEDEFAIDRIN_CAPITAL_BOTTOM,  0                                 }
-    { AF_BLUE_STRING_MEDEFAIDRIN_SMALL_F_TOP,     AF_BLUE_PROPERTY_LATIN_TOP        }
-    { AF_BLUE_STRING_MEDEFAIDRIN_SMALL_TOP,       AF_BLUE_PROPERTY_LATIN_TOP      |
-                                                  AF_BLUE_PROPERTY_LATIN_X_HEIGHT   }
-    { AF_BLUE_STRING_MEDEFAIDRIN_SMALL_BOTTOM,    0                                 }
-    { AF_BLUE_STRING_MEDEFAIDRIN_SMALL_DESCENDER, 0                                 }
-    { AF_BLUE_STRING_MEDEFAIDRIN_DIGIT_TOP,       AF_BLUE_PROPERTY_LATIN_TOP        }
-    { AF_BLUE_STRING_MAX,                         0                                 }
-
-  AF_BLUE_STRINGSET_MONG
-    { AF_BLUE_STRING_MONGOLIAN_TOP_BASE,    AF_BLUE_PROPERTY_LATIN_TOP }
-    { AF_BLUE_STRING_MONGOLIAN_BOTTOM_BASE, 0                          }
-    { AF_BLUE_STRING_MAX,                   0                          }
-
-  AF_BLUE_STRINGSET_MYMR
-    { AF_BLUE_STRING_MYANMAR_TOP,       AF_BLUE_PROPERTY_LATIN_TOP      |
-                                        AF_BLUE_PROPERTY_LATIN_X_HEIGHT   }
-    { AF_BLUE_STRING_MYANMAR_BOTTOM,    0                                 }
-    { AF_BLUE_STRING_MYANMAR_ASCENDER,  AF_BLUE_PROPERTY_LATIN_TOP        }
-    { AF_BLUE_STRING_MYANMAR_DESCENDER, 0                                 }
-    { AF_BLUE_STRING_MAX,               0                                 }
-
-  AF_BLUE_STRINGSET_NKOO
-    { AF_BLUE_STRING_NKO_TOP,          AF_BLUE_PROPERTY_LATIN_TOP        }
-    { AF_BLUE_STRING_NKO_BOTTOM,       0                                 }
-    { AF_BLUE_STRING_NKO_SMALL_TOP,    AF_BLUE_PROPERTY_LATIN_TOP      |
-                                       AF_BLUE_PROPERTY_LATIN_X_HEIGHT   }
-    { AF_BLUE_STRING_NKO_SMALL_BOTTOM, 0                                 }
-    { AF_BLUE_STRING_MAX,              0                                 }
-
-  AF_BLUE_STRINGSET_NONE
-    { AF_BLUE_STRING_MAX, 0 }
-
-  AF_BLUE_STRINGSET_OLCK
-    { AF_BLUE_STRING_OL_CHIKI, AF_BLUE_PROPERTY_LATIN_TOP }
-    { AF_BLUE_STRING_OL_CHIKI, 0                          }
-    { AF_BLUE_STRING_MAX,      0                          }
-
-  AF_BLUE_STRINGSET_ORKH
-    { AF_BLUE_STRING_OLD_TURKIC_TOP,    AF_BLUE_PROPERTY_LATIN_TOP }
-    { AF_BLUE_STRING_OLD_TURKIC_BOTTOM, 0                          }
-    { AF_BLUE_STRING_MAX,               0                          }
-
-  AF_BLUE_STRINGSET_OSGE
-    { AF_BLUE_STRING_OSAGE_CAPITAL_TOP,       AF_BLUE_PROPERTY_LATIN_TOP       }
-    { AF_BLUE_STRING_OSAGE_CAPITAL_BOTTOM,    0                                }
-    { AF_BLUE_STRING_OSAGE_CAPITAL_DESCENDER, 0                                }
-    { AF_BLUE_STRING_OSAGE_SMALL_TOP,         AF_BLUE_PROPERTY_LATIN_TOP     |
-                                              AF_BLUE_PROPERTY_LATIN_X_HEIGHT  }
-    { AF_BLUE_STRING_OSAGE_SMALL_BOTTOM,      0                                }
-    { AF_BLUE_STRING_OSAGE_SMALL_ASCENDER,    AF_BLUE_PROPERTY_LATIN_TOP       }
-    { AF_BLUE_STRING_OSAGE_SMALL_DESCENDER,   0                                }
-    { AF_BLUE_STRING_MAX,                     0                                }
-
-  AF_BLUE_STRINGSET_OSMA
-    { AF_BLUE_STRING_OSMANYA_TOP,    AF_BLUE_PROPERTY_LATIN_TOP }
-    { AF_BLUE_STRING_OSMANYA_BOTTOM, 0                          }
-    { AF_BLUE_STRING_MAX,            0                          }
-
-  AF_BLUE_STRINGSET_ROHG
-    { AF_BLUE_STRING_ROHINGYA_TOP,    AF_BLUE_PROPERTY_LATIN_TOP     }
-    { AF_BLUE_STRING_ROHINGYA_BOTTOM, 0                              }
-    { AF_BLUE_STRING_ROHINGYA_JOIN,   AF_BLUE_PROPERTY_LATIN_NEUTRAL }
-    { AF_BLUE_STRING_MAX,             0                              }
-
-  AF_BLUE_STRINGSET_SAUR
-    { AF_BLUE_STRING_SAURASHTRA_TOP,    AF_BLUE_PROPERTY_LATIN_TOP }
-    { AF_BLUE_STRING_SAURASHTRA_BOTTOM, 0                          }
-    { AF_BLUE_STRING_MAX,               0                          }
-
-  AF_BLUE_STRINGSET_SHAW
-    { AF_BLUE_STRING_SHAVIAN_TOP,          AF_BLUE_PROPERTY_LATIN_TOP        }
-    { AF_BLUE_STRING_SHAVIAN_BOTTOM,       0                                 }
-    { AF_BLUE_STRING_SHAVIAN_DESCENDER,    0                                 }
-    { AF_BLUE_STRING_SHAVIAN_SMALL_TOP,    AF_BLUE_PROPERTY_LATIN_TOP      |
-                                           AF_BLUE_PROPERTY_LATIN_X_HEIGHT   }
-    { AF_BLUE_STRING_SHAVIAN_SMALL_BOTTOM, 0                                 }
-    { AF_BLUE_STRING_MAX,                  0                                 }
-
-  AF_BLUE_STRINGSET_SINH
-    { AF_BLUE_STRING_SINHALA_TOP,       AF_BLUE_PROPERTY_LATIN_TOP }
-    { AF_BLUE_STRING_SINHALA_BOTTOM,    0                          }
-    { AF_BLUE_STRING_SINHALA_DESCENDER, 0                          }
-    { AF_BLUE_STRING_MAX,               0                          }
-
-  AF_BLUE_STRINGSET_SUND
-    { AF_BLUE_STRING_SUNDANESE_TOP,       AF_BLUE_PROPERTY_LATIN_TOP }
-    { AF_BLUE_STRING_SUNDANESE_BOTTOM,    0                          }
-    { AF_BLUE_STRING_SUNDANESE_DESCENDER, 0                          }
-    { AF_BLUE_STRING_MAX,                 0                          }
-
-  AF_BLUE_STRINGSET_TAML
-    { AF_BLUE_STRING_TAMIL_TOP,    AF_BLUE_PROPERTY_LATIN_TOP }
-    { AF_BLUE_STRING_TAMIL_BOTTOM, 0                          }
-    { AF_BLUE_STRING_MAX,          0                          }
-
-  AF_BLUE_STRINGSET_TAVT
-    { AF_BLUE_STRING_TAI_VIET_TOP,    AF_BLUE_PROPERTY_LATIN_TOP }
-    { AF_BLUE_STRING_TAI_VIET_BOTTOM, 0                          }
-    { AF_BLUE_STRING_MAX,             0                          }
-
-  AF_BLUE_STRINGSET_TELU
-    { AF_BLUE_STRING_TELUGU_TOP,    AF_BLUE_PROPERTY_LATIN_TOP }
-    { AF_BLUE_STRING_TELUGU_BOTTOM, 0                          }
-    { AF_BLUE_STRING_MAX,           0                          }
-
-  AF_BLUE_STRINGSET_THAI
-    { AF_BLUE_STRING_THAI_TOP,             AF_BLUE_PROPERTY_LATIN_TOP      |
-                                           AF_BLUE_PROPERTY_LATIN_X_HEIGHT   }
-    { AF_BLUE_STRING_THAI_BOTTOM,          0                                 }
-    { AF_BLUE_STRING_THAI_ASCENDER,        AF_BLUE_PROPERTY_LATIN_TOP        }
-    { AF_BLUE_STRING_THAI_LARGE_ASCENDER,  AF_BLUE_PROPERTY_LATIN_TOP        }
-    { AF_BLUE_STRING_THAI_DESCENDER,       0                                 }
-    { AF_BLUE_STRING_THAI_LARGE_DESCENDER, 0                                 }
-    { AF_BLUE_STRING_THAI_DIGIT_TOP,       0                                 }
-    { AF_BLUE_STRING_MAX,                  0                                 }
-
-  AF_BLUE_STRINGSET_TFNG
-    { AF_BLUE_STRING_TIFINAGH, AF_BLUE_PROPERTY_LATIN_TOP }
-    { AF_BLUE_STRING_TIFINAGH, 0                          }
-    { AF_BLUE_STRING_MAX,      0                          }
-
-  AF_BLUE_STRINGSET_VAII
-    { AF_BLUE_STRING_VAI_TOP,    AF_BLUE_PROPERTY_LATIN_TOP }
-    { AF_BLUE_STRING_VAI_BOTTOM, 0                          }
-    { AF_BLUE_STRING_MAX,        0                          }
-
-#ifdef AF_CONFIG_OPTION_CJK
-
-  AF_BLUE_STRINGSET_HANI
-    { AF_BLUE_STRING_CJK_TOP,    AF_BLUE_PROPERTY_CJK_TOP     }
-    { AF_BLUE_STRING_CJK_BOTTOM, 0                            }
-#ifdef AF_CONFIG_OPTION_CJK_BLUE_HANI_VERT
-    { AF_BLUE_STRING_CJK_LEFT,   AF_BLUE_PROPERTY_CJK_HORIZ   }
-    { AF_BLUE_STRING_CJK_RIGHT,  AF_BLUE_PROPERTY_CJK_HORIZ |
-                                 AF_BLUE_PROPERTY_CJK_RIGHT   }
-#endif /* AF_CONFIG_OPTION_CJK_BLUE_HANI_VERT */
-    { AF_BLUE_STRING_MAX,        0                            }
-
-#endif /* AF_CONFIG_OPTION_CJK                */
-
-
-// END
+// afblue.dat
+//
+//   Auto-fitter data for blue strings.
+//
+// Copyright (C) 2013-2024 by
+// David Turner, Robert Wilhelm, and Werner Lemberg.
+//
+// This file is part of the FreeType project, and may only be used,
+// modified, and distributed under the terms of the FreeType project
+// license, LICENSE.TXT.  By continuing to use, modify, or distribute
+// this file you indicate that you have read the license and
+// understand and accept it fully.
+
+
+// This file contains data specific to blue zones.  It gets processed by
+// a script to simulate `jagged arrays', with enumeration values holding
+// offsets into the arrays.
+//
+// The format of the file is rather simple:  A section starts with three
+// labels separated by whitespace and followed by a colon (everything in a
+// single line); the first label gives the name of the enumeration template,
+// the second the name of the array template, and the third the name of the
+// `maximum' template.  The script then fills the corresponding templates
+// (indicated by `@' characters around the name).
+//
+// A section contains one or more data records.  Each data record consists
+// of two or more lines.  The first line holds the enumeration name, and the
+// remaining lines the corresponding array data.
+//
+// There are two possible representations for array data.
+//
+// - A string of characters or character clusters (for example, representing
+//   Aksharas, Devanagari syllables) in UTF-8 encoding enclosed in double
+//   quotes, using C syntax, where the elements are separated by spaces.
+//   There can be only one string per line, thus the starting and ending
+//   double quote must be the first and last character in the line,
+//   respectively, ignoring whitespace before and after the string.  If
+//   there are multiple strings (in multiple lines), they are concatenated
+//   to a single string.  In the output, a string gets represented as a
+//   series of singles bytes, followed by a zero byte.  The enumeration
+//   values simply hold byte offsets to the start of the corresponding
+//   strings.
+//
+//   For strings, the `maximum' template holds the maximum number of
+//   non-space characters in all strings.
+//
+// - Data blocks enclosed in balanced braces, which get copied verbatim and
+//   which can span multiple lines.  The opening brace of a block must be
+//   the first character of a line (ignoring whitespace), and the closing
+//   brace the last (ignoring whitespace also).  The script appends a comma
+//   character after each block and counts the number of blocks to set the
+//   enumeration values.
+//
+//   For data blocks, the `maximum' template holds the maximum number of
+//   array elements.
+//
+// A section can contain either strings only or data blocks only.
+//
+// A comment line starts with `//'; it gets removed.  A preprocessor
+// directive line (using the standard syntax of `cpp') starts with `#' and
+// gets copied verbatim to both the enumeration and the array.  Whitespace
+// outside of a string is insignificant.
+//
+// Preprocessor directives are ignored while the script computes maximum
+// values; this essentially means that the maximum values can easily be too
+// large.  Given that the purpose of those values is to create local
+// fixed-size arrays at compile time for further processing of the blue zone
+// data, this isn't a problem.  Note the final zero byte of a string is not
+// counted.  Note also that the count holds the number of UTF-8 encoded
+// characters, not bytes.
+
+
+// The blue zone string data, to be used in the blue stringsets below.
+
+AF_BLUE_STRING_ENUM AF_BLUE_STRINGS_ARRAY AF_BLUE_STRING_MAX_LEN:
+
+  AF_BLUE_STRING_ADLAM_CAPITAL_TOP
+    "𞤌 𞤅 𞤈 𞤏 𞤔 𞤚"
+  AF_BLUE_STRING_ADLAM_CAPITAL_BOTTOM
+    "𞤂 𞤖"
+  AF_BLUE_STRING_ADLAM_SMALL_TOP
+    "𞤬 𞤮 𞤻 𞤼 𞤾"
+  AF_BLUE_STRING_ADLAM_SMALL_BOTTOM
+    "𞤤 𞤨 𞤩 𞤭 𞤴 𞤸 𞤺 𞥀"
+
+  AF_BLUE_STRING_ARABIC_TOP
+    "ا إ ل ك ط ظ"
+  AF_BLUE_STRING_ARABIC_BOTTOM
+    "ت ث ط ظ ك"
+  // We don't necessarily have access to medial forms via Unicode in case
+  // Arabic presentational forms are missing.  The only character that is
+  // guaranteed to have the same vertical position with joining (that is,
+  // non-isolated) forms is U+0640, ARABIC TATWEEL, which must join both
+  // round and flat curves.
+  AF_BLUE_STRING_ARABIC_JOIN
+    "ـ"
+
+  AF_BLUE_STRING_ARMENIAN_CAPITAL_TOP
+    "Ա Մ Ւ Ս Բ Գ Դ Օ"
+  AF_BLUE_STRING_ARMENIAN_CAPITAL_BOTTOM
+    "Ւ Ո Դ Ճ Շ Ս Տ Օ"
+  AF_BLUE_STRING_ARMENIAN_SMALL_ASCENDER
+    "ե է ի մ վ ֆ ճ"
+  AF_BLUE_STRING_ARMENIAN_SMALL_TOP
+    "ա յ ւ ս գ շ ր օ"
+  AF_BLUE_STRING_ARMENIAN_SMALL_BOTTOM
+    "հ ո ճ ա ե ծ ս օ"
+  AF_BLUE_STRING_ARMENIAN_SMALL_DESCENDER
+    "բ ը ի լ ղ պ փ ց"
+
+  AF_BLUE_STRING_AVESTAN_TOP
+    "𐬀 𐬁 𐬐 𐬛"
+  AF_BLUE_STRING_AVESTAN_BOTTOM
+    "𐬀 𐬁"
+
+  AF_BLUE_STRING_BAMUM_TOP
+    "ꚧ ꚨ ꛛ ꛉ ꛁ ꛈ ꛫ ꛯ"
+  AF_BLUE_STRING_BAMUM_BOTTOM
+    "ꚭ ꚳ ꚶ ꛬ ꚢ ꚽ ꛯ ꛲"
+
+  AF_BLUE_STRING_BENGALI_BASE
+    "অ ড ত ন ব ভ ল ক"
+  AF_BLUE_STRING_BENGALI_TOP
+    "ই ট ঠ ি ী ৈ ৗ"
+  AF_BLUE_STRING_BENGALI_HEAD
+    "ও এ ড ত ন ব ল ক"
+
+  AF_BLUE_STRING_BUHID_TOP
+    "ᝐ ᝈ"
+  AF_BLUE_STRING_BUHID_LARGE
+    "ᝅ ᝊ ᝎ"
+  AF_BLUE_STRING_BUHID_SMALL
+    "ᝂ ᝃ ᝉ ᝌ"
+  AF_BLUE_STRING_BUHID_BOTTOM
+    "ᝀ ᝃ ᝆ ᝉ ᝋ ᝏ ᝑ"
+
+  AF_BLUE_STRING_CANADIAN_SYLLABICS_TOP
+    "ᗜ ᖴ ᐁ ᒣ ᑫ ᑎ ᔑ ᗰ"
+  AF_BLUE_STRING_CANADIAN_SYLLABICS_BOTTOM
+    "ᗶ ᖵ ᒧ ᐃ ᑌ ᒍ ᔑ ᗢ"
+  AF_BLUE_STRING_CANADIAN_SYLLABICS_SMALL_TOP
+    "ᓓ ᓕ ᓀ ᓂ ᓄ ᕄ ᕆ ᘣ"
+  AF_BLUE_STRING_CANADIAN_SYLLABICS_SMALL_BOTTOM
+    "ᕃ ᓂ ᓀ ᕂ ᓗ ᓚ ᕆ ᘣ"
+  AF_BLUE_STRING_CANADIAN_SYLLABICS_SUPS_TOP
+    "ᐪ ᙆ ᣘ ᐢ ᒾ ᣗ ᔆ"
+  AF_BLUE_STRING_CANADIAN_SYLLABICS_SUPS_BOTTOM
+    "ᙆ ᗮ ᒻ ᐞ ᔆ ᒡ ᒢ ᓑ"
+
+  AF_BLUE_STRING_CARIAN_TOP
+    "𐊧 𐊫 𐊬 𐊭 𐊱 𐊺 𐊼 𐊿"
+  AF_BLUE_STRING_CARIAN_BOTTOM
+    "𐊣 𐊧 𐊷 𐋀 𐊫 𐊸 𐋉"
+
+  AF_BLUE_STRING_CHAKMA_TOP
+    "𑄃 𑄅 𑄉 𑄙 𑄗"
+  AF_BLUE_STRING_CHAKMA_BOTTOM
+    "𑄅 𑄛 𑄝 𑄗 𑄓"
+  AF_BLUE_STRING_CHAKMA_DESCENDER
+    "𑄖𑄳𑄢 𑄘𑄳𑄢 𑄙𑄳𑄢 𑄤𑄳𑄢 𑄥𑄳𑄢"
+
+  AF_BLUE_STRING_CHEROKEE_CAPITAL
+    "Ꮖ Ꮋ Ꭼ Ꮓ Ꭴ Ꮳ Ꭶ Ꮥ"
+  AF_BLUE_STRING_CHEROKEE_SMALL_ASCENDER
+    "ꮒ ꮤ ꮶ ꭴ ꭾ ꮗ ꮝ ꮿ"
+  AF_BLUE_STRING_CHEROKEE_SMALL
+    "ꮖ ꭼ ꮓ ꮠ ꮳ ꭶ ꮥ ꮻ"
+  AF_BLUE_STRING_CHEROKEE_SMALL_DESCENDER
+    "ᏸ ꮐ ꭹ ꭻ"
+
+  AF_BLUE_STRING_COPTIC_CAPITAL_TOP
+    "Ⲍ Ⲏ Ⲡ Ⳟ Ⲟ Ⲑ Ⲥ Ⳋ"
+  AF_BLUE_STRING_COPTIC_CAPITAL_BOTTOM
+    "Ⳑ Ⳙ Ⳟ Ⲏ Ⲟ Ⲑ Ⳝ Ⲱ"
+  AF_BLUE_STRING_COPTIC_SMALL_TOP
+    "ⲍ ⲏ ⲡ ⳟ ⲟ ⲑ ⲥ ⳋ"
+  AF_BLUE_STRING_COPTIC_SMALL_BOTTOM
+    "ⳑ ⳙ ⳟ ⲏ ⲟ ⲑ ⳝ Ⳓ"
+
+  AF_BLUE_STRING_CYPRIOT_TOP
+    "𐠍 𐠙 𐠳 𐠱 𐠅 𐠓 𐠣 𐠦"
+  AF_BLUE_STRING_CYPRIOT_BOTTOM
+    "𐠃 𐠊 𐠛 𐠣 𐠳 𐠵 𐠐"
+  AF_BLUE_STRING_CYPRIOT_SMALL
+    "𐠈 𐠏 𐠖"
+
+  AF_BLUE_STRING_CYRILLIC_CAPITAL_TOP
+    "Б В Е П З О С Э"
+  AF_BLUE_STRING_CYRILLIC_CAPITAL_BOTTOM
+    "Б В Е Ш З О С Э"
+  AF_BLUE_STRING_CYRILLIC_SMALL
+    "х п н ш е з о с"
+  AF_BLUE_STRING_CYRILLIC_SMALL_DESCENDER
+    "р у ф"
+
+  AF_BLUE_STRING_DESERET_CAPITAL_TOP
+    "𐐂 𐐄 𐐋 𐐗 𐐑"
+  AF_BLUE_STRING_DESERET_CAPITAL_BOTTOM
+    "𐐀 𐐂 𐐄 𐐗 𐐛"
+  AF_BLUE_STRING_DESERET_SMALL_TOP
+    "𐐪 𐐬 𐐳 𐐿 𐐹"
+  AF_BLUE_STRING_DESERET_SMALL_BOTTOM
+    "𐐨 𐐪 𐐬 𐐿 𐑃"
+
+  AF_BLUE_STRING_DEVANAGARI_BASE
+    "क न म उ छ ट ठ ड"
+  AF_BLUE_STRING_DEVANAGARI_TOP
+    "ई ऐ ओ औ ि ी ो ौ"
+  // note that some fonts have extreme variation in the height of the
+  // round head elements; for this reason we also define the `base'
+  // blue zone, which must be always present
+  AF_BLUE_STRING_DEVANAGARI_HEAD
+    "क म अ आ थ ध भ श"
+  AF_BLUE_STRING_DEVANAGARI_BOTTOM
+    "ु ृ"
+
+  AF_BLUE_STRING_ETHIOPIC_TOP
+    "ሀ ሃ ዘ ፐ ማ በ ዋ ዐ"
+  AF_BLUE_STRING_ETHIOPIC_BOTTOM
+    "ለ ሐ በ ዘ ሀ ሪ ዐ ጨ"
+
+  AF_BLUE_STRING_GEORGIAN_MKHEDRULI_TOP
+    "გ დ ე ვ თ ი ო ღ"
+  AF_BLUE_STRING_GEORGIAN_MKHEDRULI_BOTTOM
+    "ა ზ მ ს შ ძ ხ პ"
+  AF_BLUE_STRING_GEORGIAN_MKHEDRULI_ASCENDER
+    "ს ხ ქ ზ მ შ ჩ წ"
+  AF_BLUE_STRING_GEORGIAN_MKHEDRULI_DESCENDER
+    "ე ვ ჟ ტ უ ფ ქ ყ"
+
+  AF_BLUE_STRING_GEORGIAN_ASOMTAVRULI_TOP
+    "Ⴑ Ⴇ Ⴙ Ⴜ Ⴄ Ⴅ Ⴓ Ⴚ"
+  AF_BLUE_STRING_GEORGIAN_ASOMTAVRULI_BOTTOM
+    "Ⴄ Ⴅ Ⴇ Ⴈ Ⴆ Ⴑ Ⴊ Ⴋ"
+
+  AF_BLUE_STRING_GEORGIAN_NUSKHURI_TOP
+    "ⴁ ⴗ ⴂ ⴄ ⴅ ⴇ ⴔ ⴖ"
+  AF_BLUE_STRING_GEORGIAN_NUSKHURI_BOTTOM
+    "ⴈ ⴌ ⴖ ⴎ ⴃ ⴆ ⴋ ⴢ"
+  AF_BLUE_STRING_GEORGIAN_NUSKHURI_ASCENDER
+    "ⴐ ⴑ ⴓ ⴕ ⴙ ⴛ ⴡ ⴣ"
+  AF_BLUE_STRING_GEORGIAN_NUSKHURI_DESCENDER
+    "ⴄ ⴅ ⴔ ⴕ ⴁ ⴂ ⴘ ⴝ"
+
+  AF_BLUE_STRING_GEORGIAN_MTAVRULI_TOP
+    "Ნ Ჟ Ჳ Ჸ Გ Ე Ო Ჴ"
+  AF_BLUE_STRING_GEORGIAN_MTAVRULI_BOTTOM
+    "Ი Ჲ Ო Ჩ Მ Შ Ჯ Ჽ"
+
+  AF_BLUE_STRING_GLAGOLITIC_CAPITAL_TOP
+    "Ⰵ Ⱄ Ⱚ Ⰴ Ⰲ Ⰺ Ⱛ Ⰻ"
+  AF_BLUE_STRING_GLAGOLITIC_CAPITAL_BOTTOM
+    "Ⰵ Ⰴ Ⰲ Ⱚ Ⱎ Ⱑ Ⰺ Ⱄ"
+  AF_BLUE_STRING_GLAGOLITIC_SMALL_TOP
+    "ⰵ ⱄ ⱚ ⰴ ⰲ ⰺ ⱛ ⰻ"
+  AF_BLUE_STRING_GLAGOLITIC_SMALL_BOTTOM
+    "ⰵ ⰴ ⰲ ⱚ ⱎ ⱑ ⰺ ⱄ"
+
+  AF_BLUE_STRING_GOTHIC_TOP
+    "𐌲 𐌶 𐍀 𐍄 𐌴 𐍃 𐍈 𐌾"
+  AF_BLUE_STRING_GOTHIC_BOTTOM
+    "𐌶 𐌴 𐍃 𐍈"
+
+  AF_BLUE_STRING_GREEK_CAPITAL_TOP
+    "Γ Β Ε Ζ Θ Ο Ω"
+  AF_BLUE_STRING_GREEK_CAPITAL_BOTTOM
+    "Β Δ Ζ Ξ Θ Ο"
+  AF_BLUE_STRING_GREEK_SMALL_BETA_TOP
+    "β θ δ ζ λ ξ"
+  AF_BLUE_STRING_GREEK_SMALL
+    "α ε ι ο π σ τ ω"
+  AF_BLUE_STRING_GREEK_SMALL_DESCENDER
+    "β γ η μ ρ φ χ ψ"
+
+  AF_BLUE_STRING_GUJARATI_TOP
+    "ત ન ઋ ઌ છ ટ ર ૦"
+  AF_BLUE_STRING_GUJARATI_BOTTOM
+    "ખ ગ ઘ ઞ ઇ ઈ ઠ જ"
+  AF_BLUE_STRING_GUJARATI_ASCENDER
+    "ઈ ઊ િ ી લી શ્ચિ જિ સી"
+  AF_BLUE_STRING_GUJARATI_DESCENDER
+    "ુ ૃ ૄ ખુ છૃ છૄ"
+  AF_BLUE_STRING_GUJARATI_DIGIT_TOP
+    "૦ ૧ ૨ ૩ ૭"
+
+  AF_BLUE_STRING_GURMUKHI_BASE
+    "ਕ ਗ ਙ ਚ ਜ ਤ ਧ ਸ"
+  AF_BLUE_STRING_GURMUKHI_HEAD
+    "ਕ ਗ ਙ ਚ ਜ ਤ ਧ ਸ"
+  AF_BLUE_STRING_GURMUKHI_TOP
+    "ਇ ਈ ਉ ਏ ਓ ੳ ਿ ੀ"
+  AF_BLUE_STRING_GURMUKHI_BOTTOM
+    "ਅ ਏ ਓ ਗ ਜ ਠ ਰ ਸ"
+  AF_BLUE_STRING_GURMUKHI_DIGIT_TOP
+    "੦ ੧ ੨ ੩ ੭"
+
+  AF_BLUE_STRING_HEBREW_TOP
+    "ב ד ה ח ך כ ם ס"
+  AF_BLUE_STRING_HEBREW_BOTTOM
+    "ב ט כ ם ס צ"
+  AF_BLUE_STRING_HEBREW_DESCENDER
+    "ק ך ן ף ץ"
+
+  AF_BLUE_STRING_KANNADA_TOP
+    "ಇ ಊ ಐ ಣ ಸಾ ನಾ ದಾ ರಾ"
+  AF_BLUE_STRING_KANNADA_BOTTOM
+    "ಅ ಉ ಎ ಲ ೦ ೨ ೬ ೭"
+
+  AF_BLUE_STRING_KAYAH_LI_TOP
+    "꤅ ꤏ ꤁ ꤋ ꤀ ꤍ"
+  AF_BLUE_STRING_KAYAH_LI_BOTTOM
+    "꤈ ꤘ ꤀ ꤍ ꤢ"
+  AF_BLUE_STRING_KAYAH_LI_ASCENDER
+    "ꤖ ꤡ"
+  AF_BLUE_STRING_KAYAH_LI_DESCENDER
+    "ꤑ ꤜ ꤞ"
+  AF_BLUE_STRING_KAYAH_LI_LARGE_DESCENDER
+    "ꤑ꤬ ꤜ꤭ ꤔ꤬"
+
+  AF_BLUE_STRING_KHMER_TOP
+    "ខ ទ ន ឧ ឩ ា"
+  AF_BLUE_STRING_KHMER_SUBSCRIPT_TOP
+    "ក្ក ក្ខ ក្គ ក្ថ"
+  AF_BLUE_STRING_KHMER_BOTTOM
+    "ខ ឃ ច ឋ ប ម យ ឲ"
+  AF_BLUE_STRING_KHMER_DESCENDER
+    "ត្រ រៀ ឲ្យ អឿ"
+  AF_BLUE_STRING_KHMER_LARGE_DESCENDER
+    "ន្ត្រៃ ង្ខ្យ ក្បៀ ច្រៀ ន្តឿ ល្បឿ"
+
+  AF_BLUE_STRING_KHMER_SYMBOLS_WAXING_TOP
+    "᧠ ᧡"
+  AF_BLUE_STRING_KHMER_SYMBOLS_WANING_BOTTOM
+    "᧶ ᧹"
+
+  AF_BLUE_STRING_LAO_TOP
+    "າ ດ ອ ມ ລ ວ ຣ ງ"
+  AF_BLUE_STRING_LAO_BOTTOM
+    "າ ອ ບ ຍ ຣ ຮ ວ ຢ"
+  AF_BLUE_STRING_LAO_ASCENDER
+    "ປ ຢ ຟ ຝ"
+  AF_BLUE_STRING_LAO_LARGE_ASCENDER
+    "ໂ ໄ ໃ"
+  AF_BLUE_STRING_LAO_DESCENDER
+    "ງ ຊ ຖ ຽ ໆ ຯ"
+
+  AF_BLUE_STRING_LATIN_CAPITAL_TOP
+    "T H E Z O C Q S"
+  AF_BLUE_STRING_LATIN_CAPITAL_BOTTOM
+    "H E Z L O C U S"
+  AF_BLUE_STRING_LATIN_SMALL_F_TOP
+    "f i j k d b h"
+  AF_BLUE_STRING_LATIN_SMALL_TOP
+    "u v x z o e s c"
+  AF_BLUE_STRING_LATIN_SMALL_BOTTOM
+    "n r x z o e s c"
+  AF_BLUE_STRING_LATIN_SMALL_DESCENDER
+    "p q g j y"
+
+  // we assume that both the subscript and superscript ranges
+  // don't contain oldstyle digits (actually, most fonts probably
+  // have digits only in those ranges)
+  AF_BLUE_STRING_LATIN_SUBS_CAPITAL_TOP
+    "₀ ₃ ₅ ₇ ₈"
+  AF_BLUE_STRING_LATIN_SUBS_CAPITAL_BOTTOM
+    "₀ ₁ ₂ ₃ ₈"
+  AF_BLUE_STRING_LATIN_SUBS_SMALL_F_TOP
+    "ᵢ ⱼ ₕ ₖ ₗ"
+  AF_BLUE_STRING_LATIN_SUBS_SMALL
+    "ₐ ₑ ₒ ₓ ₙ ₛ ᵥ ᵤ ᵣ"
+  AF_BLUE_STRING_LATIN_SUBS_SMALL_DESCENDER
+    "ᵦ ᵧ ᵨ ᵩ ₚ"
+
+  AF_BLUE_STRING_LATIN_SUPS_CAPITAL_TOP
+    "⁰ ³ ⁵ ⁷ ᵀ ᴴ ᴱ ᴼ"
+  AF_BLUE_STRING_LATIN_SUPS_CAPITAL_BOTTOM
+    "⁰ ¹ ² ³ ᴱ ᴸ ᴼ ᵁ"
+  AF_BLUE_STRING_LATIN_SUPS_SMALL_F_TOP
+    "ᵇ ᵈ ᵏ ʰ ʲ ᶠ ⁱ"
+  AF_BLUE_STRING_LATIN_SUPS_SMALL
+    "ᵉ ᵒ ʳ ˢ ˣ ᶜ ᶻ"
+  AF_BLUE_STRING_LATIN_SUPS_SMALL_DESCENDER
+    "ᵖ ʸ ᵍ"
+
+  AF_BLUE_STRING_LISU_TOP
+    "ꓡ ꓧ ꓱ ꓶ ꓩ ꓚ ꓵ ꓳ"
+  AF_BLUE_STRING_LISU_BOTTOM
+    "ꓕ ꓜ ꓞ ꓡ ꓛ ꓢ ꓳ ꓴ"
+
+  AF_BLUE_STRING_MALAYALAM_TOP
+    "ഒ ട ഠ റ ച പ ച്ച പ്പ"
+  AF_BLUE_STRING_MALAYALAM_BOTTOM
+    "ട ഠ ധ ശ ഘ ച ഥ ല"
+
+  AF_BLUE_STRING_MEDEFAIDRIN_CAPITAL_TOP
+    "𖹀 𖹁 𖹂 𖹃 𖹏 𖹚 𖹟"
+  AF_BLUE_STRING_MEDEFAIDRIN_CAPITAL_BOTTOM
+    "𖹀 𖹁 𖹂 𖹃 𖹏 𖹚 𖹒 𖹓"
+  AF_BLUE_STRING_MEDEFAIDRIN_SMALL_F_TOP
+    "𖹤 𖹬 𖹧 𖹴 𖹶 𖹾"
+  AF_BLUE_STRING_MEDEFAIDRIN_SMALL_TOP
+    "𖹠 𖹡 𖹢 𖹹 𖹳 𖹮"
+  AF_BLUE_STRING_MEDEFAIDRIN_SMALL_BOTTOM
+    "𖹠 𖹡 𖹢 𖹳 𖹭 𖹽"
+  AF_BLUE_STRING_MEDEFAIDRIN_SMALL_DESCENDER
+    "𖹥 𖹨 𖹩"
+  AF_BLUE_STRING_MEDEFAIDRIN_DIGIT_TOP
+    "𖺀 𖺅 𖺈 𖺄 𖺍"
+
+  AF_BLUE_STRING_MONGOLIAN_TOP_BASE
+    "ᠳ ᠴ ᠶ ᠽ ᡂ ᡊ ‍ᡡ‍ ‍ᡳ‍"
+  AF_BLUE_STRING_MONGOLIAN_BOTTOM_BASE
+    "ᡃ"
+
+  AF_BLUE_STRING_MYANMAR_TOP
+    "ခ ဂ င ဒ ဝ ၥ ၊ ။"
+  AF_BLUE_STRING_MYANMAR_BOTTOM
+    "င ဎ ဒ ပ ဗ ဝ ၊ ။"
+  AF_BLUE_STRING_MYANMAR_ASCENDER
+    "ဩ ြ ၍ ၏ ၆ ါ ိ"
+  AF_BLUE_STRING_MYANMAR_DESCENDER
+    "ဉ ည ဥ ဩ ဨ ၂ ၅ ၉"
+
+  AF_BLUE_STRING_NKO_TOP
+    "ߐ ߉ ߒ ߟ ߖ ߜ ߠ ߥ"
+  AF_BLUE_STRING_NKO_BOTTOM
+    "߀ ߘ ߡ ߠ ߥ"
+  AF_BLUE_STRING_NKO_SMALL_TOP
+    "ߏ ߛ ߋ"
+  AF_BLUE_STRING_NKO_SMALL_BOTTOM
+    "ߎ ߏ ߛ ߋ"
+
+  AF_BLUE_STRING_OL_CHIKI
+    "ᱛ ᱜ ᱝ ᱡ ᱢ ᱥ"
+
+  AF_BLUE_STRING_OLD_TURKIC_TOP
+    "𐰗 𐰘 𐰧"
+  AF_BLUE_STRING_OLD_TURKIC_BOTTOM
+    "𐰉 𐰗 𐰦 𐰧"
+
+  AF_BLUE_STRING_OSAGE_CAPITAL_TOP
+    "𐒾 𐓍 𐓒 𐓓 𐒻 𐓂 𐒵 𐓆"
+  AF_BLUE_STRING_OSAGE_CAPITAL_BOTTOM
+    "𐒰 𐓍 𐓂 𐒿 𐓎 𐒹"
+  AF_BLUE_STRING_OSAGE_CAPITAL_DESCENDER
+    "𐒼 𐒽 𐒾"
+  AF_BLUE_STRING_OSAGE_SMALL_TOP
+    "𐓵 𐓶 𐓺 𐓻 𐓝 𐓣 𐓪 𐓮"
+  AF_BLUE_STRING_OSAGE_SMALL_BOTTOM
+    "𐓘 𐓚 𐓣 𐓵 𐓡 𐓧 𐓪 𐓶"
+  AF_BLUE_STRING_OSAGE_SMALL_ASCENDER
+    "𐓤 𐓦 𐓸 𐓹 𐓛"
+  AF_BLUE_STRING_OSAGE_SMALL_DESCENDER
+    "𐓤 𐓥 𐓦"
+
+  AF_BLUE_STRING_OSMANYA_TOP
+    "𐒆 𐒉 𐒐 𐒒 𐒘 𐒛 𐒠 𐒣"
+  AF_BLUE_STRING_OSMANYA_BOTTOM
+    "𐒀 𐒂 𐒆 𐒈 𐒊 𐒒 𐒠 𐒩"
+
+  AF_BLUE_STRING_ROHINGYA_TOP
+    "𐴃 𐴀 𐴆 𐴖 𐴕"
+  AF_BLUE_STRING_ROHINGYA_BOTTOM
+    "𐴔 𐴖 𐴕 𐴑 𐴐"
+  AF_BLUE_STRING_ROHINGYA_JOIN
+    "ـ"
+
+  AF_BLUE_STRING_SAURASHTRA_TOP
+    "ꢜ ꢞ ꢳ ꢂ ꢖ ꢒ ꢝ ꢛ"
+  AF_BLUE_STRING_SAURASHTRA_BOTTOM
+    "ꢂ ꢨ ꢺ ꢤ ꢎ"
+
+  AF_BLUE_STRING_SHAVIAN_TOP
+    "𐑕 𐑙"
+  AF_BLUE_STRING_SHAVIAN_BOTTOM
+    "𐑔 𐑖 𐑗 𐑹 𐑻"
+  AF_BLUE_STRING_SHAVIAN_DESCENDER
+    "𐑟 𐑣"
+  AF_BLUE_STRING_SHAVIAN_SMALL_TOP
+    "𐑱 𐑲 𐑳 𐑴 𐑸 𐑺 𐑼"
+  AF_BLUE_STRING_SHAVIAN_SMALL_BOTTOM
+    "𐑴 𐑻 𐑹"
+
+  AF_BLUE_STRING_SINHALA_TOP
+    "ඉ ක ඝ ඳ ප ය ල ෆ"
+  AF_BLUE_STRING_SINHALA_BOTTOM
+    "එ ඔ ඝ ජ ට ථ ධ ර"
+  AF_BLUE_STRING_SINHALA_DESCENDER
+    "ද ඳ උ ල තූ තු බු දු"
+
+  AF_BLUE_STRING_SUNDANESE_TOP
+    "ᮋ ᮞ ᮮ ᮽ ᮰ ᮈ"
+  AF_BLUE_STRING_SUNDANESE_BOTTOM
+    "ᮄ ᮔ ᮕ ᮗ ᮰ ᮆ ᮈ ᮉ"
+  AF_BLUE_STRING_SUNDANESE_DESCENDER
+    "ᮼ ᳄"
+
+  AF_BLUE_STRING_TAI_VIET_TOP
+    "ꪆ ꪔ ꪒ ꪖ ꪫ"
+  AF_BLUE_STRING_TAI_VIET_BOTTOM
+    "ꪉ ꪫ ꪮ"
+
+  AF_BLUE_STRING_TAMIL_TOP
+    "உ ஒ ஓ ற ஈ க ங ச"
+  AF_BLUE_STRING_TAMIL_BOTTOM
+    "க ச ல ஶ உ ங ட ப"
+
+  AF_BLUE_STRING_TELUGU_TOP
+    "ఇ ఌ ఙ ఞ ణ ఱ ౯"
+  AF_BLUE_STRING_TELUGU_BOTTOM
+    "అ క చ ర ఽ ౨ ౬"
+
+  AF_BLUE_STRING_THAI_TOP
+    "บ เ แ อ ก า"
+  AF_BLUE_STRING_THAI_BOTTOM
+    "บ ป ษ ฯ อ ย ฮ"
+  AF_BLUE_STRING_THAI_ASCENDER
+    "ป ฝ ฟ"
+  AF_BLUE_STRING_THAI_LARGE_ASCENDER
+    "โ ใ ไ"
+  AF_BLUE_STRING_THAI_DESCENDER
+    "ฎ ฏ ฤ ฦ"
+  AF_BLUE_STRING_THAI_LARGE_DESCENDER
+    "ญ ฐ"
+  AF_BLUE_STRING_THAI_DIGIT_TOP
+    "๐ ๑ ๓"
+
+  AF_BLUE_STRING_TIFINAGH
+    "ⵔ ⵙ ⵛ ⵞ ⴵ ⴼ ⴹ ⵎ"
+
+  AF_BLUE_STRING_VAI_TOP
+    "ꗍ ꘖ ꘙ ꘜ ꖜ ꖝ ꔅ ꕢ"
+  AF_BLUE_STRING_VAI_BOTTOM
+    "ꗍ ꘖ ꘙ ꗞ ꔅ ꕢ ꖜ ꔆ"
+
+
+#ifdef AF_CONFIG_OPTION_CJK
+
+  AF_BLUE_STRING_CJK_TOP
+    "他 们 你 來 們 到 和 地"
+    " 对 對 就 席 我 时 時 會"
+    " 来 為 能 舰 說 说 这 這"
+    " 齊 |"
+    " 军 同 已 愿 既 星 是 景"
+    " 民 照 现 現 理 用 置 要"
+    " 軍 那 配 里 開 雷 露 面"
+    " 顾"
+  AF_BLUE_STRING_CJK_BOTTOM
+    "个 为 人 他 以 们 你 來"
+    " 個 們 到 和 大 对 對 就"
+    " 我 时 時 有 来 為 要 說"
+    " 说 |"
+    " 主 些 因 它 想 意 理 生"
+    " 當 看 着 置 者 自 著 裡"
+    " 过 还 进 進 過 道 還 里"
+    " 面"
+
+#ifdef AF_CONFIG_OPTION_CJK_BLUE_HANI_VERT
+
+  AF_BLUE_STRING_CJK_LEFT
+    " 些 们 你 來 們 到 和 地"
+    " 她 将 將 就 年 得 情 最"
+    " 样 樣 理 能 說 说 这 這"
+    " 通 |"
+    " 即 吗 吧 听 呢 品 响 嗎"
+    " 师 師 收 断 斷 明 眼 間"
+    " 间 际 陈 限 除 陳 随 際"
+    " 隨"
+  AF_BLUE_STRING_CJK_RIGHT
+    "事 前 學 将 將 情 想 或"
+    " 政 斯 新 样 樣 民 沒 没"
+    " 然 特 现 現 球 第 經 谁"
+    " 起 |"
+    " 例 別 别 制 动 動 吗 嗎"
+    " 增 指 明 朝 期 构 物 确"
+    " 种 調 调 費 费 那 都 間"
+    " 间"
+
+#endif /* AF_CONFIG_OPTION_CJK_BLUE_HANI_VERT */
+
+#endif /* AF_CONFIG_OPTION_CJK                */
+
+
+// The blue zone stringsets, as used in the script styles, cf. `afstyles.h'.
+//
+// The AF_BLUE_PROPERTY_XXX flags are defined in `afblue.h'; here some
+// explanations.
+//
+// A blue zone in general is defined by a reference and an overshoot line.
+// During the hinting process, all coordinate values between those two lines
+// are set equal to the reference value, provided that the blue zone is not
+// wider than 0.75 pixels (otherwise the blue zone gets ignored).  All
+// entries must have `AF_BLUE_STRING_MAX' as the final line.
+//
+// During the glyph analysis, edges are sorted from bottom to top, and then
+// sequentially checked, edge by edge, against the blue zones in the order
+// given below.
+//
+//
+// latin auto-hinter
+// -----------------
+//
+// Characters in a blue string are automatically classified as having a flat
+// (reference) or a round (overshoot) extremum.  The blue zone is then set
+// up by the mean values of all flat extrema and all round extrema,
+// respectively.  Only horizontal blue zones (i.e., adjusting vertical
+// coordinate values) are supported.
+//
+// Some scripts like Khmer need character composition to get all necessary
+// blue zones, since Unicode only provides an abstract data model that
+// doesn't represent all possible glyph shapes.  For such character
+// clusters, the HarfBuzz library is used to convert them into the
+// corresponding glyphs.  The largest glyph element (where `largest' can be
+// either `largest ascender' or `largest descender') then defines the
+// corresponding flat or round extremum.
+//
+// For the latin auto-hinter, the overshoot should be larger than the
+// reference for top zones, and vice versa for bottom zones.
+//
+//   LATIN_TOP
+//     Take the maximum flat and round coordinate values of the blue string
+//     characters for computing the blue zone's reference and overshoot
+//     values.
+//
+//     If not set, take the minimum values.
+//
+//     Mutually exclusive with `LATIN_SUB_TOP'.
+//
+//   LATIN_SUB_TOP
+//     For all glyphs of a character cluster, compute the maximum flat
+//     and round coordinate values of each component, then take the
+//     smallest of the maximum values.  The idea is to get the top of
+//     subscript glyphs, as used in Khmer, for example.  Note that
+//     this mechanism doesn't work for ordinary ligatures.
+//
+//     This flags indicates a secondary blue zone: It gets removed if
+//     there is a non-LATIN_SUB_TOP blue zone at the same coordinate
+//     value (after scaling).
+//
+//     Mutually exclusive with `LATIN_TOP'.
+//
+//   LATIN_NEUTRAL
+//     Ignore round extrema and define the blue zone with flat values only.
+//     Both top and bottom of contours can match.  This is useful for
+//     scripts like Devanagari where vowel signs attach to the base
+//     character and are implemented as components of composite glyphs.
+//
+//     If not set, both round and flat extrema are taken into account.
+//     Additionally, only the top or the bottom of a contour can match,
+//     depending on the LATIN_TOP flag.
+//
+//     Neutral blue zones should always follow non-neutral blue zones.
+//
+//   LATIN_X_HEIGHT
+//     Scale all glyphs vertically from the corresponding script to make the
+//     reference line of this blue zone align on the grid.  The scaling
+//     takes place before all other blue zones get aligned to the grid.
+//     Only one blue character string of a script style can have this flag.
+//
+//   LATIN_LONG
+//     Apply an additional constraint for blue zone values: Don't
+//     necessarily use the extremum as-is but a segment of the topmost (or
+//     bottommost) contour that is longer than a heuristic threshold, and
+//     which is not too far away vertically from the real extremum.  This
+//     ensures that small bumps in the outline are ignored (for example, the
+//     `vertical serifs' found in many Hebrew glyph designs).
+//
+//     The segment must be at least EM/25 font units long, and the distance
+//     to the extremum must be smaller than EM/4.
+//
+//
+// cjk auto-hinter
+// ---------------
+//
+// Characters in a blue string are *not* automatically classified.  Instead,
+// first come the characters used for the overshoot value, then the
+// character `|', then the characters used for the reference value
+// (everything separated by space characters).  The blue zone is then set up
+// by the mean values of all reference values and all overshoot values,
+// respectively.  Both horizontal and vertical blue zones (i.e., adjusting
+// vertical and horizontal coordinate values, respectively) are supported.
+//
+// For the cjk auto-hinter, the overshoot should be smaller than the
+// reference for top zones, and vice versa for bottom zones.
+//
+//   CJK_TOP
+//     Take the maximum flat and round coordinate values of the blue string
+//     characters.  If not set, take the minimum values.
+//
+//   CJK_RIGHT
+//     A synonym for CJK_TOP.  If CJK_HORIZ is set, this flag indicates the
+//     right blue zone, taking horizontal maximum values.
+//
+//   CJK_HORIZ
+//     Define a blue zone for horizontal hinting (i.e., vertical blue
+//     zones).  If not set, this is a blue zone for vertical hinting.
+
+
+AF_BLUE_STRINGSET_ENUM AF_BLUE_STRINGSETS_ARRAY AF_BLUE_STRINGSET_MAX_LEN:
+
+  AF_BLUE_STRINGSET_ADLM
+    { AF_BLUE_STRING_ADLAM_CAPITAL_TOP,    AF_BLUE_PROPERTY_LATIN_TOP        }
+    { AF_BLUE_STRING_ADLAM_CAPITAL_BOTTOM, 0                                 }
+    { AF_BLUE_STRING_ADLAM_SMALL_TOP,      AF_BLUE_PROPERTY_LATIN_TOP      |
+                                           AF_BLUE_PROPERTY_LATIN_X_HEIGHT   }
+    { AF_BLUE_STRING_ADLAM_SMALL_BOTTOM,   0                                 }
+    { AF_BLUE_STRING_MAX,                  0                                 }
+
+  AF_BLUE_STRINGSET_ARAB
+    { AF_BLUE_STRING_ARABIC_TOP,    AF_BLUE_PROPERTY_LATIN_TOP     }
+    { AF_BLUE_STRING_ARABIC_BOTTOM, 0                              }
+    { AF_BLUE_STRING_ARABIC_JOIN,   AF_BLUE_PROPERTY_LATIN_NEUTRAL }
+    { AF_BLUE_STRING_MAX,           0                              }
+
+  AF_BLUE_STRINGSET_ARMN
+    { AF_BLUE_STRING_ARMENIAN_CAPITAL_TOP,     AF_BLUE_PROPERTY_LATIN_TOP        }
+    { AF_BLUE_STRING_ARMENIAN_CAPITAL_BOTTOM,  0                                 }
+    { AF_BLUE_STRING_ARMENIAN_SMALL_ASCENDER,  AF_BLUE_PROPERTY_LATIN_TOP        }
+    { AF_BLUE_STRING_ARMENIAN_SMALL_TOP,       AF_BLUE_PROPERTY_LATIN_TOP      |
+                                               AF_BLUE_PROPERTY_LATIN_X_HEIGHT   }
+    { AF_BLUE_STRING_ARMENIAN_SMALL_BOTTOM,    0                                 }
+    { AF_BLUE_STRING_ARMENIAN_SMALL_DESCENDER, 0                                 }
+    { AF_BLUE_STRING_MAX,                      0                                 }
+
+  AF_BLUE_STRINGSET_AVST
+    { AF_BLUE_STRING_AVESTAN_TOP,    AF_BLUE_PROPERTY_LATIN_TOP }
+    { AF_BLUE_STRING_AVESTAN_BOTTOM, 0                          }
+    { AF_BLUE_STRING_MAX,            0                          }
+
+  AF_BLUE_STRINGSET_BAMU
+    { AF_BLUE_STRING_BAMUM_TOP,    AF_BLUE_PROPERTY_LATIN_TOP }
+    { AF_BLUE_STRING_BAMUM_BOTTOM, 0                          }
+    { AF_BLUE_STRING_MAX,          0                          }
+
+  AF_BLUE_STRINGSET_BENG
+    { AF_BLUE_STRING_BENGALI_TOP,  AF_BLUE_PROPERTY_LATIN_TOP        }
+    { AF_BLUE_STRING_BENGALI_HEAD, AF_BLUE_PROPERTY_LATIN_TOP        }
+    { AF_BLUE_STRING_BENGALI_BASE, AF_BLUE_PROPERTY_LATIN_TOP      |
+                                   AF_BLUE_PROPERTY_LATIN_NEUTRAL  |
+                                   AF_BLUE_PROPERTY_LATIN_X_HEIGHT   }
+    { AF_BLUE_STRING_BENGALI_BASE, 0                                 }
+    { AF_BLUE_STRING_MAX,          0                                 }
+
+  AF_BLUE_STRINGSET_BUHD
+    { AF_BLUE_STRING_BUHID_TOP,    AF_BLUE_PROPERTY_LATIN_TOP        }
+    { AF_BLUE_STRING_BUHID_LARGE,  AF_BLUE_PROPERTY_LATIN_TOP        }
+    { AF_BLUE_STRING_BUHID_SMALL,  AF_BLUE_PROPERTY_LATIN_TOP      |
+                                   AF_BLUE_PROPERTY_LATIN_X_HEIGHT   }
+    { AF_BLUE_STRING_BUHID_BOTTOM, 0                                 }
+    { AF_BLUE_STRING_MAX,          0                                 }
+
+  AF_BLUE_STRINGSET_CAKM
+    { AF_BLUE_STRING_CHAKMA_TOP,       AF_BLUE_PROPERTY_LATIN_TOP }
+    { AF_BLUE_STRING_CHAKMA_BOTTOM,    0                          }
+    { AF_BLUE_STRING_CHAKMA_DESCENDER, 0                          }
+    { AF_BLUE_STRING_MAX,              0                          }
+
+  AF_BLUE_STRINGSET_CANS
+    { AF_BLUE_STRING_CANADIAN_SYLLABICS_TOP,          AF_BLUE_PROPERTY_LATIN_TOP        }
+    { AF_BLUE_STRING_CANADIAN_SYLLABICS_BOTTOM,       0                                 }
+    { AF_BLUE_STRING_CANADIAN_SYLLABICS_SMALL_TOP,    AF_BLUE_PROPERTY_LATIN_TOP      |
+                                                      AF_BLUE_PROPERTY_LATIN_X_HEIGHT   }
+    { AF_BLUE_STRING_CANADIAN_SYLLABICS_SMALL_BOTTOM, 0                                 }
+    { AF_BLUE_STRING_CANADIAN_SYLLABICS_SUPS_TOP,     AF_BLUE_PROPERTY_LATIN_TOP        }
+    { AF_BLUE_STRING_CANADIAN_SYLLABICS_SUPS_BOTTOM,  0                                 }
+    { AF_BLUE_STRING_MAX,                             0                                 }
+
+  AF_BLUE_STRINGSET_CARI
+    { AF_BLUE_STRING_CARIAN_TOP,    AF_BLUE_PROPERTY_LATIN_TOP }
+    { AF_BLUE_STRING_CARIAN_BOTTOM, 0                          }
+    { AF_BLUE_STRING_MAX,           0                          }
+
+  AF_BLUE_STRINGSET_CHER
+    { AF_BLUE_STRING_CHEROKEE_CAPITAL,         AF_BLUE_PROPERTY_LATIN_TOP        }
+    { AF_BLUE_STRING_CHEROKEE_CAPITAL,         0                                 }
+    { AF_BLUE_STRING_CHEROKEE_SMALL_ASCENDER,  AF_BLUE_PROPERTY_LATIN_TOP        }
+    { AF_BLUE_STRING_CHEROKEE_SMALL,           AF_BLUE_PROPERTY_LATIN_TOP      |
+                                               AF_BLUE_PROPERTY_LATIN_X_HEIGHT   }
+    { AF_BLUE_STRING_CHEROKEE_SMALL,           0                                 }
+    { AF_BLUE_STRING_CHEROKEE_SMALL_DESCENDER, 0                                 }
+    { AF_BLUE_STRING_MAX,                      0                                 }
+
+  AF_BLUE_STRINGSET_COPT
+    { AF_BLUE_STRING_COPTIC_CAPITAL_TOP,    AF_BLUE_PROPERTY_LATIN_TOP        }
+    { AF_BLUE_STRING_COPTIC_CAPITAL_BOTTOM, 0                                 }
+    { AF_BLUE_STRING_COPTIC_SMALL_TOP,      AF_BLUE_PROPERTY_LATIN_TOP      |
+                                            AF_BLUE_PROPERTY_LATIN_X_HEIGHT   }
+    { AF_BLUE_STRING_COPTIC_SMALL_BOTTOM,   0                                 }
+    { AF_BLUE_STRING_MAX,                   0                                 }
+
+  AF_BLUE_STRINGSET_CPRT
+    { AF_BLUE_STRING_CYPRIOT_TOP,    AF_BLUE_PROPERTY_LATIN_TOP }
+    { AF_BLUE_STRING_CYPRIOT_BOTTOM, 0                          }
+    { AF_BLUE_STRING_CYPRIOT_SMALL,  AF_BLUE_PROPERTY_LATIN_TOP }
+    { AF_BLUE_STRING_CYPRIOT_SMALL,  0                          }
+    { AF_BLUE_STRING_MAX,            0                          }
+
+  AF_BLUE_STRINGSET_CYRL
+    { AF_BLUE_STRING_CYRILLIC_CAPITAL_TOP,     AF_BLUE_PROPERTY_LATIN_TOP        }
+    { AF_BLUE_STRING_CYRILLIC_CAPITAL_BOTTOM,  0                                 }
+    { AF_BLUE_STRING_CYRILLIC_SMALL,           AF_BLUE_PROPERTY_LATIN_TOP      |
+                                               AF_BLUE_PROPERTY_LATIN_X_HEIGHT   }
+    { AF_BLUE_STRING_CYRILLIC_SMALL,           0                                 }
+    { AF_BLUE_STRING_CYRILLIC_SMALL_DESCENDER, 0                                 }
+    { AF_BLUE_STRING_MAX,                      0                                 }
+
+  AF_BLUE_STRINGSET_DEVA
+    { AF_BLUE_STRING_DEVANAGARI_TOP,    AF_BLUE_PROPERTY_LATIN_TOP        }
+    { AF_BLUE_STRING_DEVANAGARI_HEAD,   AF_BLUE_PROPERTY_LATIN_TOP        }
+    { AF_BLUE_STRING_DEVANAGARI_BASE,   AF_BLUE_PROPERTY_LATIN_TOP      |
+                                        AF_BLUE_PROPERTY_LATIN_NEUTRAL  |
+                                        AF_BLUE_PROPERTY_LATIN_X_HEIGHT   }
+    { AF_BLUE_STRING_DEVANAGARI_BASE,   0                                 }
+    { AF_BLUE_STRING_DEVANAGARI_BOTTOM, 0                                 }
+    { AF_BLUE_STRING_MAX,               0                                 }
+
+  AF_BLUE_STRINGSET_DSRT
+    { AF_BLUE_STRING_DESERET_CAPITAL_TOP,    AF_BLUE_PROPERTY_LATIN_TOP        }
+    { AF_BLUE_STRING_DESERET_CAPITAL_BOTTOM, 0                                 }
+    { AF_BLUE_STRING_DESERET_SMALL_TOP,      AF_BLUE_PROPERTY_LATIN_TOP      |
+                                             AF_BLUE_PROPERTY_LATIN_X_HEIGHT   }
+    { AF_BLUE_STRING_DESERET_SMALL_BOTTOM,   0                                 }
+    { AF_BLUE_STRING_MAX,                    0                                 }
+
+  AF_BLUE_STRINGSET_ETHI
+    { AF_BLUE_STRING_ETHIOPIC_TOP,    AF_BLUE_PROPERTY_LATIN_TOP }
+    { AF_BLUE_STRING_ETHIOPIC_BOTTOM, 0                          }
+    { AF_BLUE_STRING_MAX,             0                          }
+
+  AF_BLUE_STRINGSET_GEOR
+    { AF_BLUE_STRING_GEORGIAN_MKHEDRULI_TOP,       AF_BLUE_PROPERTY_LATIN_TOP      |
+                                                   AF_BLUE_PROPERTY_LATIN_X_HEIGHT   }
+    { AF_BLUE_STRING_GEORGIAN_MKHEDRULI_BOTTOM,    0                                 }
+    { AF_BLUE_STRING_GEORGIAN_MKHEDRULI_ASCENDER,  AF_BLUE_PROPERTY_LATIN_TOP        }
+    { AF_BLUE_STRING_GEORGIAN_MKHEDRULI_DESCENDER, 0                                 }
+    { AF_BLUE_STRING_GEORGIAN_MTAVRULI_TOP,        AF_BLUE_PROPERTY_LATIN_TOP        }
+    { AF_BLUE_STRING_GEORGIAN_MTAVRULI_BOTTOM,     0                                 }
+    { AF_BLUE_STRING_MAX,                          0                                 }
+
+  AF_BLUE_STRINGSET_GEOK
+    { AF_BLUE_STRING_GEORGIAN_ASOMTAVRULI_TOP,    AF_BLUE_PROPERTY_LATIN_TOP        }
+    { AF_BLUE_STRING_GEORGIAN_ASOMTAVRULI_BOTTOM, 0                                 }
+    { AF_BLUE_STRING_GEORGIAN_NUSKHURI_TOP,       AF_BLUE_PROPERTY_LATIN_TOP      |
+                                                  AF_BLUE_PROPERTY_LATIN_X_HEIGHT   }
+    { AF_BLUE_STRING_GEORGIAN_NUSKHURI_BOTTOM,    0                                 }
+    { AF_BLUE_STRING_GEORGIAN_NUSKHURI_ASCENDER,  AF_BLUE_PROPERTY_LATIN_TOP        }
+    { AF_BLUE_STRING_GEORGIAN_NUSKHURI_DESCENDER, 0                                 }
+    { AF_BLUE_STRING_MAX,                         0                                 }
+
+  AF_BLUE_STRINGSET_GLAG
+    { AF_BLUE_STRING_GLAGOLITIC_CAPITAL_TOP,    AF_BLUE_PROPERTY_LATIN_TOP        }
+    { AF_BLUE_STRING_GLAGOLITIC_CAPITAL_BOTTOM, 0                                 }
+    { AF_BLUE_STRING_GLAGOLITIC_SMALL_TOP,      AF_BLUE_PROPERTY_LATIN_TOP      |
+                                                AF_BLUE_PROPERTY_LATIN_X_HEIGHT   }
+    { AF_BLUE_STRING_GLAGOLITIC_SMALL_BOTTOM,   0                                 }
+    { AF_BLUE_STRING_MAX,                       0                                 }
+
+  AF_BLUE_STRINGSET_GOTH
+    { AF_BLUE_STRING_GOTHIC_TOP,    AF_BLUE_PROPERTY_LATIN_TOP }
+    { AF_BLUE_STRING_GOTHIC_BOTTOM, 0                          }
+    { AF_BLUE_STRING_MAX,           0                          }
+
+  AF_BLUE_STRINGSET_GREK
+    { AF_BLUE_STRING_GREEK_CAPITAL_TOP,     AF_BLUE_PROPERTY_LATIN_TOP        }
+    { AF_BLUE_STRING_GREEK_CAPITAL_BOTTOM,  0                                 }
+    { AF_BLUE_STRING_GREEK_SMALL_BETA_TOP,  AF_BLUE_PROPERTY_LATIN_TOP        }
+    { AF_BLUE_STRING_GREEK_SMALL,           AF_BLUE_PROPERTY_LATIN_TOP      |
+                                            AF_BLUE_PROPERTY_LATIN_X_HEIGHT   }
+    { AF_BLUE_STRING_GREEK_SMALL,           0                                 }
+    { AF_BLUE_STRING_GREEK_SMALL_DESCENDER, 0                                 }
+    { AF_BLUE_STRING_MAX,                   0                                 }
+
+  AF_BLUE_STRINGSET_GUJR
+    { AF_BLUE_STRING_GUJARATI_TOP,       AF_BLUE_PROPERTY_LATIN_TOP      |
+                                         AF_BLUE_PROPERTY_LATIN_X_HEIGHT   }
+    { AF_BLUE_STRING_GUJARATI_BOTTOM,    0                                 }
+    { AF_BLUE_STRING_GUJARATI_ASCENDER,  AF_BLUE_PROPERTY_LATIN_TOP        }
+    { AF_BLUE_STRING_GUJARATI_DESCENDER, 0                                 }
+    { AF_BLUE_STRING_GUJARATI_DIGIT_TOP, AF_BLUE_PROPERTY_LATIN_TOP        }
+    { AF_BLUE_STRING_MAX,                0                                 }
+
+  AF_BLUE_STRINGSET_GURU
+    { AF_BLUE_STRING_GURMUKHI_TOP,       AF_BLUE_PROPERTY_LATIN_TOP        }
+    { AF_BLUE_STRING_GURMUKHI_HEAD,      AF_BLUE_PROPERTY_LATIN_TOP        }
+    { AF_BLUE_STRING_GURMUKHI_BASE,      AF_BLUE_PROPERTY_LATIN_TOP      |
+                                         AF_BLUE_PROPERTY_LATIN_NEUTRAL  |
+                                         AF_BLUE_PROPERTY_LATIN_X_HEIGHT   }
+    { AF_BLUE_STRING_GURMUKHI_BOTTOM,    0                                 }
+    { AF_BLUE_STRING_GURMUKHI_DIGIT_TOP, AF_BLUE_PROPERTY_LATIN_TOP        }
+    { AF_BLUE_STRING_MAX,                0                                 }
+
+  AF_BLUE_STRINGSET_HEBR
+    { AF_BLUE_STRING_HEBREW_TOP,       AF_BLUE_PROPERTY_LATIN_TOP  |
+                                       AF_BLUE_PROPERTY_LATIN_LONG   }
+    { AF_BLUE_STRING_HEBREW_BOTTOM,    0                             }
+    { AF_BLUE_STRING_HEBREW_DESCENDER, 0                             }
+    { AF_BLUE_STRING_MAX,              0                             }
+
+  AF_BLUE_STRINGSET_KNDA
+    { AF_BLUE_STRING_KANNADA_TOP,    AF_BLUE_PROPERTY_LATIN_TOP }
+    { AF_BLUE_STRING_KANNADA_BOTTOM, 0                          }
+    { AF_BLUE_STRING_MAX,            0                          }
+
+  AF_BLUE_STRINGSET_KALI
+    { AF_BLUE_STRING_KAYAH_LI_TOP,             AF_BLUE_PROPERTY_LATIN_TOP      |
+                                               AF_BLUE_PROPERTY_LATIN_X_HEIGHT   }
+    { AF_BLUE_STRING_KAYAH_LI_BOTTOM,          0                                 }
+    { AF_BLUE_STRING_KAYAH_LI_ASCENDER,        AF_BLUE_PROPERTY_LATIN_TOP        }
+    { AF_BLUE_STRING_KAYAH_LI_DESCENDER,       0                                 }
+    { AF_BLUE_STRING_KAYAH_LI_LARGE_DESCENDER, 0                                 }
+    { AF_BLUE_STRING_MAX,                      0                                 }
+
+  AF_BLUE_STRINGSET_KHMR
+    { AF_BLUE_STRING_KHMER_TOP,             AF_BLUE_PROPERTY_LATIN_TOP      |
+                                            AF_BLUE_PROPERTY_LATIN_X_HEIGHT   }
+    { AF_BLUE_STRING_KHMER_SUBSCRIPT_TOP,   AF_BLUE_PROPERTY_LATIN_SUB_TOP    }
+    { AF_BLUE_STRING_KHMER_BOTTOM,          0                                 }
+    { AF_BLUE_STRING_KHMER_DESCENDER,       0                                 }
+    { AF_BLUE_STRING_KHMER_LARGE_DESCENDER, 0                                 }
+    { AF_BLUE_STRING_MAX,                   0                                 }
+
+  AF_BLUE_STRINGSET_KHMS
+    { AF_BLUE_STRING_KHMER_SYMBOLS_WAXING_TOP,    AF_BLUE_PROPERTY_LATIN_TOP      |
+                                                  AF_BLUE_PROPERTY_LATIN_X_HEIGHT   }
+    { AF_BLUE_STRING_KHMER_SYMBOLS_WANING_BOTTOM, 0                                 }
+    { AF_BLUE_STRING_MAX,                         0                                 }
+
+  AF_BLUE_STRINGSET_LAO
+    { AF_BLUE_STRING_LAO_TOP,            AF_BLUE_PROPERTY_LATIN_TOP      |
+                                         AF_BLUE_PROPERTY_LATIN_X_HEIGHT   }
+    { AF_BLUE_STRING_LAO_BOTTOM,         0                                 }
+    { AF_BLUE_STRING_LAO_ASCENDER,       AF_BLUE_PROPERTY_LATIN_TOP        }
+    { AF_BLUE_STRING_LAO_LARGE_ASCENDER, AF_BLUE_PROPERTY_LATIN_TOP        }
+    { AF_BLUE_STRING_LAO_DESCENDER,      0                                 }
+    { AF_BLUE_STRING_MAX,                0                                 }
+
+  AF_BLUE_STRINGSET_LATN
+    { AF_BLUE_STRING_LATIN_CAPITAL_TOP,     AF_BLUE_PROPERTY_LATIN_TOP        }
+    { AF_BLUE_STRING_LATIN_CAPITAL_BOTTOM,  0                                 }
+    { AF_BLUE_STRING_LATIN_SMALL_F_TOP,     AF_BLUE_PROPERTY_LATIN_TOP        }
+    { AF_BLUE_STRING_LATIN_SMALL_TOP,       AF_BLUE_PROPERTY_LATIN_TOP      |
+                                            AF_BLUE_PROPERTY_LATIN_X_HEIGHT   }
+    { AF_BLUE_STRING_LATIN_SMALL_BOTTOM,    0                                 }
+    { AF_BLUE_STRING_LATIN_SMALL_DESCENDER, 0                                 }
+    { AF_BLUE_STRING_MAX,                   0                                 }
+
+  AF_BLUE_STRINGSET_LATB
+    { AF_BLUE_STRING_LATIN_SUBS_CAPITAL_TOP,     AF_BLUE_PROPERTY_LATIN_TOP        }
+    { AF_BLUE_STRING_LATIN_SUBS_CAPITAL_BOTTOM,  0                                 }
+    { AF_BLUE_STRING_LATIN_SUBS_SMALL_F_TOP,     AF_BLUE_PROPERTY_LATIN_TOP        }
+    { AF_BLUE_STRING_LATIN_SUBS_SMALL,           AF_BLUE_PROPERTY_LATIN_TOP      |
+                                                 AF_BLUE_PROPERTY_LATIN_X_HEIGHT   }
+    { AF_BLUE_STRING_LATIN_SUBS_SMALL,           0                                 }
+    { AF_BLUE_STRING_LATIN_SUBS_SMALL_DESCENDER, 0                                 }
+    { AF_BLUE_STRING_MAX,                        0                                 }
+
+  AF_BLUE_STRINGSET_LATP
+    { AF_BLUE_STRING_LATIN_SUPS_CAPITAL_TOP,     AF_BLUE_PROPERTY_LATIN_TOP        }
+    { AF_BLUE_STRING_LATIN_SUPS_CAPITAL_BOTTOM,  0                                 }
+    { AF_BLUE_STRING_LATIN_SUPS_SMALL_F_TOP,     AF_BLUE_PROPERTY_LATIN_TOP        }
+    { AF_BLUE_STRING_LATIN_SUPS_SMALL,           AF_BLUE_PROPERTY_LATIN_TOP      |
+                                                 AF_BLUE_PROPERTY_LATIN_X_HEIGHT   }
+    { AF_BLUE_STRING_LATIN_SUPS_SMALL,           0                                 }
+    { AF_BLUE_STRING_LATIN_SUPS_SMALL_DESCENDER, 0                                 }
+    { AF_BLUE_STRING_MAX,                        0                                 }
+
+  AF_BLUE_STRINGSET_LISU
+    { AF_BLUE_STRING_LISU_TOP,    AF_BLUE_PROPERTY_LATIN_TOP }
+    { AF_BLUE_STRING_LISU_BOTTOM, 0                          }
+    { AF_BLUE_STRING_MAX,         0                          }
+
+  AF_BLUE_STRINGSET_MLYM
+    { AF_BLUE_STRING_MALAYALAM_TOP,    AF_BLUE_PROPERTY_LATIN_TOP }
+    { AF_BLUE_STRING_MALAYALAM_BOTTOM, 0                          }
+    { AF_BLUE_STRING_MAX,              0                          }
+
+  AF_BLUE_STRINGSET_MEDF
+    { AF_BLUE_STRING_MEDEFAIDRIN_CAPITAL_TOP,     AF_BLUE_PROPERTY_LATIN_TOP        }
+    { AF_BLUE_STRING_MEDEFAIDRIN_CAPITAL_BOTTOM,  0                                 }
+    { AF_BLUE_STRING_MEDEFAIDRIN_SMALL_F_TOP,     AF_BLUE_PROPERTY_LATIN_TOP        }
+    { AF_BLUE_STRING_MEDEFAIDRIN_SMALL_TOP,       AF_BLUE_PROPERTY_LATIN_TOP      |
+                                                  AF_BLUE_PROPERTY_LATIN_X_HEIGHT   }
+    { AF_BLUE_STRING_MEDEFAIDRIN_SMALL_BOTTOM,    0                                 }
+    { AF_BLUE_STRING_MEDEFAIDRIN_SMALL_DESCENDER, 0                                 }
+    { AF_BLUE_STRING_MEDEFAIDRIN_DIGIT_TOP,       AF_BLUE_PROPERTY_LATIN_TOP        }
+    { AF_BLUE_STRING_MAX,                         0                                 }
+
+  AF_BLUE_STRINGSET_MONG
+    { AF_BLUE_STRING_MONGOLIAN_TOP_BASE,    AF_BLUE_PROPERTY_LATIN_TOP }
+    { AF_BLUE_STRING_MONGOLIAN_BOTTOM_BASE, 0                          }
+    { AF_BLUE_STRING_MAX,                   0                          }
+
+  AF_BLUE_STRINGSET_MYMR
+    { AF_BLUE_STRING_MYANMAR_TOP,       AF_BLUE_PROPERTY_LATIN_TOP      |
+                                        AF_BLUE_PROPERTY_LATIN_X_HEIGHT   }
+    { AF_BLUE_STRING_MYANMAR_BOTTOM,    0                                 }
+    { AF_BLUE_STRING_MYANMAR_ASCENDER,  AF_BLUE_PROPERTY_LATIN_TOP        }
+    { AF_BLUE_STRING_MYANMAR_DESCENDER, 0                                 }
+    { AF_BLUE_STRING_MAX,               0                                 }
+
+  AF_BLUE_STRINGSET_NKOO
+    { AF_BLUE_STRING_NKO_TOP,          AF_BLUE_PROPERTY_LATIN_TOP        }
+    { AF_BLUE_STRING_NKO_BOTTOM,       0                                 }
+    { AF_BLUE_STRING_NKO_SMALL_TOP,    AF_BLUE_PROPERTY_LATIN_TOP      |
+                                       AF_BLUE_PROPERTY_LATIN_X_HEIGHT   }
+    { AF_BLUE_STRING_NKO_SMALL_BOTTOM, 0                                 }
+    { AF_BLUE_STRING_MAX,              0                                 }
+
+  AF_BLUE_STRINGSET_NONE
+    { AF_BLUE_STRING_MAX, 0 }
+
+  AF_BLUE_STRINGSET_OLCK
+    { AF_BLUE_STRING_OL_CHIKI, AF_BLUE_PROPERTY_LATIN_TOP }
+    { AF_BLUE_STRING_OL_CHIKI, 0                          }
+    { AF_BLUE_STRING_MAX,      0                          }
+
+  AF_BLUE_STRINGSET_ORKH
+    { AF_BLUE_STRING_OLD_TURKIC_TOP,    AF_BLUE_PROPERTY_LATIN_TOP }
+    { AF_BLUE_STRING_OLD_TURKIC_BOTTOM, 0                          }
+    { AF_BLUE_STRING_MAX,               0                          }
+
+  AF_BLUE_STRINGSET_OSGE
+    { AF_BLUE_STRING_OSAGE_CAPITAL_TOP,       AF_BLUE_PROPERTY_LATIN_TOP       }
+    { AF_BLUE_STRING_OSAGE_CAPITAL_BOTTOM,    0                                }
+    { AF_BLUE_STRING_OSAGE_CAPITAL_DESCENDER, 0                                }
+    { AF_BLUE_STRING_OSAGE_SMALL_TOP,         AF_BLUE_PROPERTY_LATIN_TOP     |
+                                              AF_BLUE_PROPERTY_LATIN_X_HEIGHT  }
+    { AF_BLUE_STRING_OSAGE_SMALL_BOTTOM,      0                                }
+    { AF_BLUE_STRING_OSAGE_SMALL_ASCENDER,    AF_BLUE_PROPERTY_LATIN_TOP       }
+    { AF_BLUE_STRING_OSAGE_SMALL_DESCENDER,   0                                }
+    { AF_BLUE_STRING_MAX,                     0                                }
+
+  AF_BLUE_STRINGSET_OSMA
+    { AF_BLUE_STRING_OSMANYA_TOP,    AF_BLUE_PROPERTY_LATIN_TOP }
+    { AF_BLUE_STRING_OSMANYA_BOTTOM, 0                          }
+    { AF_BLUE_STRING_MAX,            0                          }
+
+  AF_BLUE_STRINGSET_ROHG
+    { AF_BLUE_STRING_ROHINGYA_TOP,    AF_BLUE_PROPERTY_LATIN_TOP     }
+    { AF_BLUE_STRING_ROHINGYA_BOTTOM, 0                              }
+    { AF_BLUE_STRING_ROHINGYA_JOIN,   AF_BLUE_PROPERTY_LATIN_NEUTRAL }
+    { AF_BLUE_STRING_MAX,             0                              }
+
+  AF_BLUE_STRINGSET_SAUR
+    { AF_BLUE_STRING_SAURASHTRA_TOP,    AF_BLUE_PROPERTY_LATIN_TOP }
+    { AF_BLUE_STRING_SAURASHTRA_BOTTOM, 0                          }
+    { AF_BLUE_STRING_MAX,               0                          }
+
+  AF_BLUE_STRINGSET_SHAW
+    { AF_BLUE_STRING_SHAVIAN_TOP,          AF_BLUE_PROPERTY_LATIN_TOP        }
+    { AF_BLUE_STRING_SHAVIAN_BOTTOM,       0                                 }
+    { AF_BLUE_STRING_SHAVIAN_DESCENDER,    0                                 }
+    { AF_BLUE_STRING_SHAVIAN_SMALL_TOP,    AF_BLUE_PROPERTY_LATIN_TOP      |
+                                           AF_BLUE_PROPERTY_LATIN_X_HEIGHT   }
+    { AF_BLUE_STRING_SHAVIAN_SMALL_BOTTOM, 0                                 }
+    { AF_BLUE_STRING_MAX,                  0                                 }
+
+  AF_BLUE_STRINGSET_SINH
+    { AF_BLUE_STRING_SINHALA_TOP,       AF_BLUE_PROPERTY_LATIN_TOP }
+    { AF_BLUE_STRING_SINHALA_BOTTOM,    0                          }
+    { AF_BLUE_STRING_SINHALA_DESCENDER, 0                          }
+    { AF_BLUE_STRING_MAX,               0                          }
+
+  AF_BLUE_STRINGSET_SUND
+    { AF_BLUE_STRING_SUNDANESE_TOP,       AF_BLUE_PROPERTY_LATIN_TOP }
+    { AF_BLUE_STRING_SUNDANESE_BOTTOM,    0                          }
+    { AF_BLUE_STRING_SUNDANESE_DESCENDER, 0                          }
+    { AF_BLUE_STRING_MAX,                 0                          }
+
+  AF_BLUE_STRINGSET_TAML
+    { AF_BLUE_STRING_TAMIL_TOP,    AF_BLUE_PROPERTY_LATIN_TOP }
+    { AF_BLUE_STRING_TAMIL_BOTTOM, 0                          }
+    { AF_BLUE_STRING_MAX,          0                          }
+
+  AF_BLUE_STRINGSET_TAVT
+    { AF_BLUE_STRING_TAI_VIET_TOP,    AF_BLUE_PROPERTY_LATIN_TOP }
+    { AF_BLUE_STRING_TAI_VIET_BOTTOM, 0                          }
+    { AF_BLUE_STRING_MAX,             0                          }
+
+  AF_BLUE_STRINGSET_TELU
+    { AF_BLUE_STRING_TELUGU_TOP,    AF_BLUE_PROPERTY_LATIN_TOP }
+    { AF_BLUE_STRING_TELUGU_BOTTOM, 0                          }
+    { AF_BLUE_STRING_MAX,           0                          }
+
+  AF_BLUE_STRINGSET_THAI
+    { AF_BLUE_STRING_THAI_TOP,             AF_BLUE_PROPERTY_LATIN_TOP      |
+                                           AF_BLUE_PROPERTY_LATIN_X_HEIGHT   }
+    { AF_BLUE_STRING_THAI_BOTTOM,          0                                 }
+    { AF_BLUE_STRING_THAI_ASCENDER,        AF_BLUE_PROPERTY_LATIN_TOP        }
+    { AF_BLUE_STRING_THAI_LARGE_ASCENDER,  AF_BLUE_PROPERTY_LATIN_TOP        }
+    { AF_BLUE_STRING_THAI_DESCENDER,       0                                 }
+    { AF_BLUE_STRING_THAI_LARGE_DESCENDER, 0                                 }
+    { AF_BLUE_STRING_THAI_DIGIT_TOP,       0                                 }
+    { AF_BLUE_STRING_MAX,                  0                                 }
+
+  AF_BLUE_STRINGSET_TFNG
+    { AF_BLUE_STRING_TIFINAGH, AF_BLUE_PROPERTY_LATIN_TOP }
+    { AF_BLUE_STRING_TIFINAGH, 0                          }
+    { AF_BLUE_STRING_MAX,      0                          }
+
+  AF_BLUE_STRINGSET_VAII
+    { AF_BLUE_STRING_VAI_TOP,    AF_BLUE_PROPERTY_LATIN_TOP }
+    { AF_BLUE_STRING_VAI_BOTTOM, 0                          }
+    { AF_BLUE_STRING_MAX,        0                          }
+
+#ifdef AF_CONFIG_OPTION_CJK
+
+  AF_BLUE_STRINGSET_HANI
+    { AF_BLUE_STRING_CJK_TOP,    AF_BLUE_PROPERTY_CJK_TOP     }
+    { AF_BLUE_STRING_CJK_BOTTOM, 0                            }
+#ifdef AF_CONFIG_OPTION_CJK_BLUE_HANI_VERT
+    { AF_BLUE_STRING_CJK_LEFT,   AF_BLUE_PROPERTY_CJK_HORIZ   }
+    { AF_BLUE_STRING_CJK_RIGHT,  AF_BLUE_PROPERTY_CJK_HORIZ |
+                                 AF_BLUE_PROPERTY_CJK_RIGHT   }
+#endif /* AF_CONFIG_OPTION_CJK_BLUE_HANI_VERT */
+    { AF_BLUE_STRING_MAX,        0                            }
+
+#endif /* AF_CONFIG_OPTION_CJK                */
+
+
+// END
diff --git a/vendor/freetype/src/autofit/afblue.h b/vendor/freetype/src/autofit/afblue.h
index 76f2f47cb0..2aa9d0984e 100644
--- a/vendor/freetype/src/autofit/afblue.h
+++ b/vendor/freetype/src/autofit/afblue.h
@@ -7,7 +7,7 @@
  *
  *   Auto-fitter data for blue strings (specification).
  *
- * Copyright (C) 2013-2023 by
+ * Copyright (C) 2013-2024 by
  * David Turner, Robert Wilhelm, and Werner Lemberg.
  *
  * This file is part of the FreeType project, and may only be used,
diff --git a/vendor/freetype/src/autofit/afblue.hin b/vendor/freetype/src/autofit/afblue.hin
index 6a31298e65..38031505a8 100644
--- a/vendor/freetype/src/autofit/afblue.hin
+++ b/vendor/freetype/src/autofit/afblue.hin
@@ -4,7 +4,7 @@
  *
  *   Auto-fitter data for blue strings (specification).
  *
- * Copyright (C) 2013-2023 by
+ * Copyright (C) 2013-2024 by
  * David Turner, Robert Wilhelm, and Werner Lemberg.
  *
  * This file is part of the FreeType project, and may only be used,
diff --git a/vendor/freetype/src/autofit/afcjk.c b/vendor/freetype/src/autofit/afcjk.c
index f414289adc..869b60487c 100644
--- a/vendor/freetype/src/autofit/afcjk.c
+++ b/vendor/freetype/src/autofit/afcjk.c
@@ -4,7 +4,7 @@
  *
  *   Auto-fitter hinting routines for CJK writing system (body).
  *
- * Copyright (C) 2006-2023 by
+ * Copyright (C) 2006-2024 by
  * David Turner, Robert Wilhelm, and Werner Lemberg.
  *
  * This file is part of the FreeType project, and may only be used,
diff --git a/vendor/freetype/src/autofit/afcjk.h b/vendor/freetype/src/autofit/afcjk.h
index f380ef6e03..bc5aaf12e6 100644
--- a/vendor/freetype/src/autofit/afcjk.h
+++ b/vendor/freetype/src/autofit/afcjk.h
@@ -4,7 +4,7 @@
  *
  *   Auto-fitter hinting routines for CJK writing system (specification).
  *
- * Copyright (C) 2006-2023 by
+ * Copyright (C) 2006-2024 by
  * David Turner, Robert Wilhelm, and Werner Lemberg.
  *
  * This file is part of the FreeType project, and may only be used,
@@ -84,7 +84,7 @@ FT_BEGIN_HEADER
     /* used for horizontal metrics too for CJK */
     FT_Bool        control_overshoot;
     FT_UInt        blue_count;
-    AF_CJKBlueRec  blues[AF_BLUE_STRINGSET_MAX];
+    AF_CJKBlueRec  blues[AF_BLUE_STRINGSET_MAX_LEN];
 
     FT_Fixed       org_scale;
     FT_Pos         org_delta;
diff --git a/vendor/freetype/src/autofit/afcover.h b/vendor/freetype/src/autofit/afcover.h
index 102ed42782..7980cf2e97 100644
--- a/vendor/freetype/src/autofit/afcover.h
+++ b/vendor/freetype/src/autofit/afcover.h
@@ -4,7 +4,7 @@
  *
  *   Auto-fitter coverages (specification only).
  *
- * Copyright (C) 2013-2023 by
+ * Copyright (C) 2013-2024 by
  * David Turner, Robert Wilhelm, and Werner Lemberg.
  *
  * This file is part of the FreeType project, and may only be used,
diff --git a/vendor/freetype/src/autofit/afdummy.c b/vendor/freetype/src/autofit/afdummy.c
index a4629b528d..ad667d2edc 100644
--- a/vendor/freetype/src/autofit/afdummy.c
+++ b/vendor/freetype/src/autofit/afdummy.c
@@ -5,7 +5,7 @@
  *   Auto-fitter dummy routines to be used if no hinting should be
  *   performed (body).
  *
- * Copyright (C) 2003-2023 by
+ * Copyright (C) 2003-2024 by
  * David Turner, Robert Wilhelm, and Werner Lemberg.
  *
  * This file is part of the FreeType project, and may only be used,
diff --git a/vendor/freetype/src/autofit/afdummy.h b/vendor/freetype/src/autofit/afdummy.h
index a7af3f62c9..613c2f88a3 100644
--- a/vendor/freetype/src/autofit/afdummy.h
+++ b/vendor/freetype/src/autofit/afdummy.h
@@ -5,7 +5,7 @@
  *   Auto-fitter dummy routines to be used if no hinting should be
  *   performed (specification).
  *
- * Copyright (C) 2003-2023 by
+ * Copyright (C) 2003-2024 by
  * David Turner, Robert Wilhelm, and Werner Lemberg.
  *
  * This file is part of the FreeType project, and may only be used,
diff --git a/vendor/freetype/src/autofit/aferrors.h b/vendor/freetype/src/autofit/aferrors.h
index 88faf05c95..ae584ff06d 100644
--- a/vendor/freetype/src/autofit/aferrors.h
+++ b/vendor/freetype/src/autofit/aferrors.h
@@ -4,7 +4,7 @@
  *
  *   Autofitter error codes (specification only).
  *
- * Copyright (C) 2005-2023 by
+ * Copyright (C) 2005-2024 by
  * David Turner, Robert Wilhelm, and Werner Lemberg.
  *
  * This file is part of the FreeType project, and may only be used,
diff --git a/vendor/freetype/src/autofit/afglobal.c b/vendor/freetype/src/autofit/afglobal.c
index b1957570f0..b7403fa65e 100644
--- a/vendor/freetype/src/autofit/afglobal.c
+++ b/vendor/freetype/src/autofit/afglobal.c
@@ -4,7 +4,7 @@
  *
  *   Auto-fitter routines to compute global hinting values (body).
  *
- * Copyright (C) 2003-2023 by
+ * Copyright (C) 2003-2024 by
  * David Turner, Robert Wilhelm, and Werner Lemberg.
  *
  * This file is part of the FreeType project, and may only be used,
diff --git a/vendor/freetype/src/autofit/afglobal.h b/vendor/freetype/src/autofit/afglobal.h
index 66170e419d..ddb54c89b2 100644
--- a/vendor/freetype/src/autofit/afglobal.h
+++ b/vendor/freetype/src/autofit/afglobal.h
@@ -5,7 +5,7 @@
  *   Auto-fitter routines to compute global hinting values
  *   (specification).
  *
- * Copyright (C) 2003-2023 by
+ * Copyright (C) 2003-2024 by
  * David Turner, Robert Wilhelm, and Werner Lemberg.
  *
  * This file is part of the FreeType project, and may only be used,
diff --git a/vendor/freetype/src/autofit/afhints.c b/vendor/freetype/src/autofit/afhints.c
index e4a378fbf7..96ffe343aa 100644
--- a/vendor/freetype/src/autofit/afhints.c
+++ b/vendor/freetype/src/autofit/afhints.c
@@ -4,7 +4,7 @@
  *
  *   Auto-fitter hinting routines (body).
  *
- * Copyright (C) 2003-2023 by
+ * Copyright (C) 2003-2024 by
  * David Turner, Robert Wilhelm, and Werner Lemberg.
  *
  * This file is part of the FreeType project, and may only be used,
@@ -979,8 +979,8 @@
       /* compute coordinates & Bezier flags, next and prev */
       {
         FT_Vector*  vec           = outline->points;
-        char*       tag           = outline->tags;
-        FT_Short    endpoint      = outline->contours[0];
+        FT_Byte*    tag           = outline->tags;
+        FT_UShort   endpoint      = outline->contours[0];
         AF_Point    end           = points + endpoint;
         AF_Point    prev          = end;
         FT_Int      contour_index = 0;
@@ -1046,16 +1046,16 @@
 
       /* set up the contours array */
       {
-        AF_Point*  contour       = hints->contours;
-        AF_Point*  contour_limit = contour + hints->num_contours;
-        short*     end           = outline->contours;
-        short      idx           = 0;
+        AF_Point*   contour       = hints->contours;
+        AF_Point*   contour_limit = contour + hints->num_contours;
+        FT_UShort*  end           = outline->contours;
+        FT_Int      idx           = 0;
 
 
         for ( ; contour < contour_limit; contour++, end++ )
         {
           contour[0] = points + idx;
-          idx        = (short)( end[0] + 1 );
+          idx        = *end + 1;
         }
       }
 
@@ -1292,7 +1292,7 @@
     AF_Point    point = hints->points;
     AF_Point    limit = point + hints->num_points;
     FT_Vector*  vec   = outline->points;
-    char*       tag   = outline->tags;
+    FT_Byte*    tag   = outline->tags;
 
 
     for ( ; point < limit; point++, vec++, tag++ )
diff --git a/vendor/freetype/src/autofit/afhints.h b/vendor/freetype/src/autofit/afhints.h
index d1cf9529bf..76fe83006a 100644
--- a/vendor/freetype/src/autofit/afhints.h
+++ b/vendor/freetype/src/autofit/afhints.h
@@ -4,7 +4,7 @@
  *
  *   Auto-fitter hinting routines (specification).
  *
- * Copyright (C) 2003-2023 by
+ * Copyright (C) 2003-2024 by
  * David Turner, Robert Wilhelm, and Werner Lemberg.
  *
  * This file is part of the FreeType project, and may only be used,
diff --git a/vendor/freetype/src/autofit/afindic.c b/vendor/freetype/src/autofit/afindic.c
index 7fb12c63d5..c6d23efd86 100644
--- a/vendor/freetype/src/autofit/afindic.c
+++ b/vendor/freetype/src/autofit/afindic.c
@@ -4,7 +4,7 @@
  *
  *   Auto-fitter hinting routines for Indic writing system (body).
  *
- * Copyright (C) 2007-2023 by
+ * Copyright (C) 2007-2024 by
  * Rahul Bhalerao , .
  *
  * This file is part of the FreeType project, and may only be used,
diff --git a/vendor/freetype/src/autofit/afindic.h b/vendor/freetype/src/autofit/afindic.h
index 3eb67f63b0..a7f73f2515 100644
--- a/vendor/freetype/src/autofit/afindic.h
+++ b/vendor/freetype/src/autofit/afindic.h
@@ -5,7 +5,7 @@
  *   Auto-fitter hinting routines for Indic writing system
  *   (specification).
  *
- * Copyright (C) 2007-2023 by
+ * Copyright (C) 2007-2024 by
  * Rahul Bhalerao , .
  *
  * This file is part of the FreeType project, and may only be used,
diff --git a/vendor/freetype/src/autofit/aflatin.c b/vendor/freetype/src/autofit/aflatin.c
index b86367aa94..89287f7ea5 100644
--- a/vendor/freetype/src/autofit/aflatin.c
+++ b/vendor/freetype/src/autofit/aflatin.c
@@ -4,7 +4,7 @@
  *
  *   Auto-fitter hinting routines for latin writing system (body).
  *
- * Copyright (C) 2003-2023 by
+ * Copyright (C) 2003-2024 by
  * David Turner, Robert Wilhelm, and Werner Lemberg.
  *
  * This file is part of the FreeType project, and may only be used,
@@ -981,7 +981,7 @@
       /* `ref' and `shoot' values of two blue zones must not overlap */
 
       FT_UInt       i;
-      AF_LatinBlue  blue_sorted[AF_BLUE_STRINGSET_MAX_LEN + 2];
+      AF_LatinBlue  blue_sorted[AF_BLUE_STRINGSET_MAX_LEN];
 
 
       for ( i = 0; i < axis->blue_count; i++ )
@@ -1263,10 +1263,9 @@
               max_height = FT_MAX( max_height, -Axis->blues[nn].descender );
             }
 
-            dist  = FT_ABS( FT_MulFix( max_height, new_scale - scale ) );
-            dist &= ~127;
+            dist  = FT_MulFix( max_height, new_scale - scale );
 
-            if ( dist == 0 )
+            if ( -128 < dist && dist < 128 )
             {
               FT_TRACE5(( "af_latin_metrics_scale_dim:"
                           " x height alignment (style `%s'):\n",
diff --git a/vendor/freetype/src/autofit/aflatin.h b/vendor/freetype/src/autofit/aflatin.h
index 31aa91d3bd..54e5061502 100644
--- a/vendor/freetype/src/autofit/aflatin.h
+++ b/vendor/freetype/src/autofit/aflatin.h
@@ -5,7 +5,7 @@
  *   Auto-fitter hinting routines for latin writing system
  *   (specification).
  *
- * Copyright (C) 2003-2023 by
+ * Copyright (C) 2003-2024 by
  * David Turner, Robert Wilhelm, and Werner Lemberg.
  *
  * This file is part of the FreeType project, and may only be used,
@@ -98,7 +98,7 @@ FT_BEGIN_HEADER
 
     /* ignored for horizontal metrics */
     FT_UInt          blue_count;
-    AF_LatinBlueRec  blues[AF_BLUE_STRINGSET_MAX];
+    AF_LatinBlueRec  blues[AF_BLUE_STRINGSET_MAX_LEN];
 
     FT_Fixed         org_scale;
     FT_Pos           org_delta;
diff --git a/vendor/freetype/src/autofit/afloader.c b/vendor/freetype/src/autofit/afloader.c
index 7c47d562af..af1d59a689 100644
--- a/vendor/freetype/src/autofit/afloader.c
+++ b/vendor/freetype/src/autofit/afloader.c
@@ -4,7 +4,7 @@
  *
  *   Auto-fitter glyph loading routines (body).
  *
- * Copyright (C) 2003-2023 by
+ * Copyright (C) 2003-2024 by
  * David Turner, Robert Wilhelm, and Werner Lemberg.
  *
  * This file is part of the FreeType project, and may only be used,
diff --git a/vendor/freetype/src/autofit/afloader.h b/vendor/freetype/src/autofit/afloader.h
index e4e197e374..99f0e15f92 100644
--- a/vendor/freetype/src/autofit/afloader.h
+++ b/vendor/freetype/src/autofit/afloader.h
@@ -4,7 +4,7 @@
  *
  *   Auto-fitter glyph loading routines (specification).
  *
- * Copyright (C) 2003-2023 by
+ * Copyright (C) 2003-2024 by
  * David Turner, Robert Wilhelm, and Werner Lemberg.
  *
  * This file is part of the FreeType project, and may only be used,
diff --git a/vendor/freetype/src/autofit/afmodule.c b/vendor/freetype/src/autofit/afmodule.c
index 20a6b96bc4..8b0123b3e3 100644
--- a/vendor/freetype/src/autofit/afmodule.c
+++ b/vendor/freetype/src/autofit/afmodule.c
@@ -4,7 +4,7 @@
  *
  *   Auto-fitter module implementation (body).
  *
- * Copyright (C) 2003-2023 by
+ * Copyright (C) 2003-2024 by
  * David Turner, Robert Wilhelm, and Werner Lemberg.
  *
  * This file is part of the FreeType project, and may only be used,
diff --git a/vendor/freetype/src/autofit/afmodule.h b/vendor/freetype/src/autofit/afmodule.h
index 4b8b4562c6..91a1abfef1 100644
--- a/vendor/freetype/src/autofit/afmodule.h
+++ b/vendor/freetype/src/autofit/afmodule.h
@@ -4,7 +4,7 @@
  *
  *   Auto-fitter module implementation (specification).
  *
- * Copyright (C) 2003-2023 by
+ * Copyright (C) 2003-2024 by
  * David Turner, Robert Wilhelm, and Werner Lemberg.
  *
  * This file is part of the FreeType project, and may only be used,
diff --git a/vendor/freetype/src/autofit/afranges.c b/vendor/freetype/src/autofit/afranges.c
index cfcaf340a7..007b432818 100644
--- a/vendor/freetype/src/autofit/afranges.c
+++ b/vendor/freetype/src/autofit/afranges.c
@@ -4,7 +4,7 @@
  *
  *   Auto-fitter Unicode script ranges (body).
  *
- * Copyright (C) 2013-2023 by
+ * Copyright (C) 2013-2024 by
  * David Turner, Robert Wilhelm, and Werner Lemberg.
  *
  * This file is part of the FreeType project, and may only be used,
diff --git a/vendor/freetype/src/autofit/afranges.h b/vendor/freetype/src/autofit/afranges.h
index 5775738bc0..813b3ee78e 100644
--- a/vendor/freetype/src/autofit/afranges.h
+++ b/vendor/freetype/src/autofit/afranges.h
@@ -4,7 +4,7 @@
  *
  *   Auto-fitter Unicode script ranges (specification).
  *
- * Copyright (C) 2013-2023 by
+ * Copyright (C) 2013-2024 by
  * David Turner, Robert Wilhelm, and Werner Lemberg.
  *
  * This file is part of the FreeType project, and may only be used,
diff --git a/vendor/freetype/src/autofit/afscript.h b/vendor/freetype/src/autofit/afscript.h
index 3a101937d7..0a83d77150 100644
--- a/vendor/freetype/src/autofit/afscript.h
+++ b/vendor/freetype/src/autofit/afscript.h
@@ -4,7 +4,7 @@
  *
  *   Auto-fitter scripts (specification only).
  *
- * Copyright (C) 2013-2023 by
+ * Copyright (C) 2013-2024 by
  * David Turner, Robert Wilhelm, and Werner Lemberg.
  *
  * This file is part of the FreeType project, and may only be used,
diff --git a/vendor/freetype/src/autofit/afshaper.c b/vendor/freetype/src/autofit/afshaper.c
index abc6f1d292..df0f46ada8 100644
--- a/vendor/freetype/src/autofit/afshaper.c
+++ b/vendor/freetype/src/autofit/afshaper.c
@@ -4,7 +4,7 @@
  *
  *   HarfBuzz interface for accessing OpenType features (body).
  *
- * Copyright (C) 2013-2023 by
+ * Copyright (C) 2013-2024 by
  * David Turner, Robert Wilhelm, and Werner Lemberg.
  *
  * This file is part of the FreeType project, and may only be used,
diff --git a/vendor/freetype/src/autofit/afshaper.h b/vendor/freetype/src/autofit/afshaper.h
index 054a18ffbc..2eb03bb5d9 100644
--- a/vendor/freetype/src/autofit/afshaper.h
+++ b/vendor/freetype/src/autofit/afshaper.h
@@ -4,7 +4,7 @@
  *
  *   HarfBuzz interface for accessing OpenType features (specification).
  *
- * Copyright (C) 2013-2023 by
+ * Copyright (C) 2013-2024 by
  * David Turner, Robert Wilhelm, and Werner Lemberg.
  *
  * This file is part of the FreeType project, and may only be used,
diff --git a/vendor/freetype/src/autofit/afstyles.h b/vendor/freetype/src/autofit/afstyles.h
index 73ebef0171..7a33f37a85 100644
--- a/vendor/freetype/src/autofit/afstyles.h
+++ b/vendor/freetype/src/autofit/afstyles.h
@@ -4,7 +4,7 @@
  *
  *   Auto-fitter styles (specification only).
  *
- * Copyright (C) 2013-2023 by
+ * Copyright (C) 2013-2024 by
  * David Turner, Robert Wilhelm, and Werner Lemberg.
  *
  * This file is part of the FreeType project, and may only be used,
diff --git a/vendor/freetype/src/autofit/aftypes.h b/vendor/freetype/src/autofit/aftypes.h
index 6615194496..27e4185e9f 100644
--- a/vendor/freetype/src/autofit/aftypes.h
+++ b/vendor/freetype/src/autofit/aftypes.h
@@ -4,7 +4,7 @@
  *
  *   Auto-fitter types (specification only).
  *
- * Copyright (C) 2003-2023 by
+ * Copyright (C) 2003-2024 by
  * David Turner, Robert Wilhelm, and Werner Lemberg.
  *
  * This file is part of the FreeType project, and may only be used,
diff --git a/vendor/freetype/src/autofit/afws-decl.h b/vendor/freetype/src/autofit/afws-decl.h
index 48c888afed..b78745af74 100644
--- a/vendor/freetype/src/autofit/afws-decl.h
+++ b/vendor/freetype/src/autofit/afws-decl.h
@@ -4,7 +4,7 @@
  *
  *   Auto-fitter writing system declarations (specification only).
  *
- * Copyright (C) 2013-2023 by
+ * Copyright (C) 2013-2024 by
  * David Turner, Robert Wilhelm, and Werner Lemberg.
  *
  * This file is part of the FreeType project, and may only be used,
diff --git a/vendor/freetype/src/autofit/afws-iter.h b/vendor/freetype/src/autofit/afws-iter.h
index a0a686f8ce..c86d609a35 100644
--- a/vendor/freetype/src/autofit/afws-iter.h
+++ b/vendor/freetype/src/autofit/afws-iter.h
@@ -4,7 +4,7 @@
  *
  *   Auto-fitter writing systems iterator (specification only).
  *
- * Copyright (C) 2013-2023 by
+ * Copyright (C) 2013-2024 by
  * David Turner, Robert Wilhelm, and Werner Lemberg.
  *
  * This file is part of the FreeType project, and may only be used,
diff --git a/vendor/freetype/src/autofit/autofit.c b/vendor/freetype/src/autofit/autofit.c
index 8bd609b5e8..de5ec7c7c5 100644
--- a/vendor/freetype/src/autofit/autofit.c
+++ b/vendor/freetype/src/autofit/autofit.c
@@ -4,7 +4,7 @@
  *
  *   Auto-fitter module (body).
  *
- * Copyright (C) 2003-2023 by
+ * Copyright (C) 2003-2024 by
  * David Turner, Robert Wilhelm, and Werner Lemberg.
  *
  * This file is part of the FreeType project, and may only be used,
diff --git a/vendor/freetype/src/base/ftadvanc.c b/vendor/freetype/src/base/ftadvanc.c
index de25476fe9..717f7d08b3 100644
--- a/vendor/freetype/src/base/ftadvanc.c
+++ b/vendor/freetype/src/base/ftadvanc.c
@@ -4,7 +4,7 @@
  *
  *   Quick computation of advance widths (body).
  *
- * Copyright (C) 2008-2023 by
+ * Copyright (C) 2008-2024 by
  * David Turner, Robert Wilhelm, and Werner Lemberg.
  *
  * This file is part of the FreeType project, and may only be used,
diff --git a/vendor/freetype/src/base/ftbase.c b/vendor/freetype/src/base/ftbase.c
index 156510f007..50805ccec4 100644
--- a/vendor/freetype/src/base/ftbase.c
+++ b/vendor/freetype/src/base/ftbase.c
@@ -4,7 +4,7 @@
  *
  *   Single object library component (body only).
  *
- * Copyright (C) 1996-2023 by
+ * Copyright (C) 1996-2024 by
  * David Turner, Robert Wilhelm, and Werner Lemberg.
  *
  * This file is part of the FreeType project, and may only be used,
diff --git a/vendor/freetype/src/base/ftbase.h b/vendor/freetype/src/base/ftbase.h
index 00790d3b22..1d98b26dd5 100644
--- a/vendor/freetype/src/base/ftbase.h
+++ b/vendor/freetype/src/base/ftbase.h
@@ -4,7 +4,7 @@
  *
  *   Private functions used in the `base' module (specification).
  *
- * Copyright (C) 2008-2023 by
+ * Copyright (C) 2008-2024 by
  * David Turner, Robert Wilhelm, Werner Lemberg, and suzuki toshiya.
  *
  * This file is part of the FreeType project, and may only be used,
diff --git a/vendor/freetype/src/base/ftbbox.c b/vendor/freetype/src/base/ftbbox.c
index 385fea4040..d6aa5d56df 100644
--- a/vendor/freetype/src/base/ftbbox.c
+++ b/vendor/freetype/src/base/ftbbox.c
@@ -4,7 +4,7 @@
  *
  *   FreeType bbox computation (body).
  *
- * Copyright (C) 1996-2023 by
+ * Copyright (C) 1996-2024 by
  * David Turner, Robert Wilhelm, and Werner Lemberg.
  *
  * This file is part of the FreeType project, and may only be used
@@ -489,7 +489,7 @@
       return FT_THROW( Invalid_Outline );
 
     /* if outline is empty, return (0,0,0,0) */
-    if ( outline->n_points == 0 || outline->n_contours <= 0 )
+    if ( outline->n_points == 0 || outline->n_contours == 0 )
     {
       abbox->xMin = abbox->xMax = 0;
       abbox->yMin = abbox->yMax = 0;
diff --git a/vendor/freetype/src/base/ftbdf.c b/vendor/freetype/src/base/ftbdf.c
index f697c00fec..d8e9fd7eaf 100644
--- a/vendor/freetype/src/base/ftbdf.c
+++ b/vendor/freetype/src/base/ftbdf.c
@@ -4,7 +4,7 @@
  *
  *   FreeType API for accessing BDF-specific strings (body).
  *
- * Copyright (C) 2002-2023 by
+ * Copyright (C) 2002-2024 by
  * David Turner, Robert Wilhelm, and Werner Lemberg.
  *
  * This file is part of the FreeType project, and may only be used,
diff --git a/vendor/freetype/src/base/ftbitmap.c b/vendor/freetype/src/base/ftbitmap.c
index 1c93648dcb..4be145679f 100644
--- a/vendor/freetype/src/base/ftbitmap.c
+++ b/vendor/freetype/src/base/ftbitmap.c
@@ -4,7 +4,7 @@
  *
  *   FreeType utility functions for bitmaps (body).
  *
- * Copyright (C) 2004-2023 by
+ * Copyright (C) 2004-2024 by
  * David Turner, Robert Wilhelm, and Werner Lemberg.
  *
  * This file is part of the FreeType project, and may only be used,
diff --git a/vendor/freetype/src/base/ftcalc.c b/vendor/freetype/src/base/ftcalc.c
index c5bc7e3b14..5851dae162 100644
--- a/vendor/freetype/src/base/ftcalc.c
+++ b/vendor/freetype/src/base/ftcalc.c
@@ -4,7 +4,7 @@
  *
  *   Arithmetic computations (body).
  *
- * Copyright (C) 1996-2023 by
+ * Copyright (C) 1996-2024 by
  * David Turner, Robert Wilhelm, and Werner Lemberg.
  *
  * This file is part of the FreeType project, and may only be used,
@@ -69,13 +69,15 @@
 
   /* transfer sign, leaving a positive number;                        */
   /* we need an unsigned value to safely negate INT_MIN (or LONG_MIN) */
-#define FT_MOVE_SIGN( x, x_unsigned, s ) \
-  FT_BEGIN_STMNT                         \
-    if ( x < 0 )                         \
-    {                                    \
-      x_unsigned = 0U - (x_unsigned);    \
-      s          = -s;                   \
-    }                                    \
+#define FT_MOVE_SIGN( utype, x, x_unsigned, s ) \
+  FT_BEGIN_STMNT                                \
+    if ( x < 0 )                                \
+    {                                           \
+      x_unsigned = 0U - (utype)x;               \
+      s          = -s;                          \
+    }                                           \
+    else                                        \
+      x_unsigned = (utype)x;                    \
   FT_END_STMNT
 
   /* The following three functions are available regardless of whether */
@@ -179,13 +181,9 @@
     FT_Long    d_;
 
 
-    a = (FT_UInt64)a_;
-    b = (FT_UInt64)b_;
-    c = (FT_UInt64)c_;
-
-    FT_MOVE_SIGN( a_, a, s );
-    FT_MOVE_SIGN( b_, b, s );
-    FT_MOVE_SIGN( c_, c, s );
+    FT_MOVE_SIGN( FT_UInt64, a_, a, s );
+    FT_MOVE_SIGN( FT_UInt64, b_, b, s );
+    FT_MOVE_SIGN( FT_UInt64, c_, c, s );
 
     d = c > 0 ? ( a * b + ( c >> 1 ) ) / c
               : 0x7FFFFFFFUL;
@@ -208,13 +206,9 @@
     FT_Long    d_;
 
 
-    a = (FT_UInt64)a_;
-    b = (FT_UInt64)b_;
-    c = (FT_UInt64)c_;
-
-    FT_MOVE_SIGN( a_, a, s );
-    FT_MOVE_SIGN( b_, b, s );
-    FT_MOVE_SIGN( c_, c, s );
+    FT_MOVE_SIGN( FT_UInt64, a_, a, s );
+    FT_MOVE_SIGN( FT_UInt64, b_, b, s );
+    FT_MOVE_SIGN( FT_UInt64, c_, c, s );
 
     d = c > 0 ? a * b / c
               : 0x7FFFFFFFUL;
@@ -257,11 +251,8 @@
     FT_Long    q_;
 
 
-    a = (FT_UInt64)a_;
-    b = (FT_UInt64)b_;
-
-    FT_MOVE_SIGN( a_, a, s );
-    FT_MOVE_SIGN( b_, b, s );
+    FT_MOVE_SIGN( FT_UInt64, a_, a, s );
+    FT_MOVE_SIGN( FT_UInt64, b_, b, s );
 
     q = b > 0 ? ( ( a << 16 ) + ( b >> 1 ) ) / b
               : 0x7FFFFFFFUL;
@@ -422,13 +413,9 @@
 
     /* XXX: this function does not allow 64-bit arguments */
 
-    a = (FT_UInt32)a_;
-    b = (FT_UInt32)b_;
-    c = (FT_UInt32)c_;
-
-    FT_MOVE_SIGN( a_, a, s );
-    FT_MOVE_SIGN( b_, b, s );
-    FT_MOVE_SIGN( c_, c, s );
+    FT_MOVE_SIGN( FT_UInt32, a_, a, s );
+    FT_MOVE_SIGN( FT_UInt32, b_, b, s );
+    FT_MOVE_SIGN( FT_UInt32, c_, c, s );
 
     if ( c == 0 )
       a = 0x7FFFFFFFUL;
@@ -470,13 +457,9 @@
 
     /* XXX: this function does not allow 64-bit arguments */
 
-    a = (FT_UInt32)a_;
-    b = (FT_UInt32)b_;
-    c = (FT_UInt32)c_;
-
-    FT_MOVE_SIGN( a_, a, s );
-    FT_MOVE_SIGN( b_, b, s );
-    FT_MOVE_SIGN( c_, c, s );
+    FT_MOVE_SIGN( FT_UInt32, a_, a, s );
+    FT_MOVE_SIGN( FT_UInt32, b_, b, s );
+    FT_MOVE_SIGN( FT_UInt32, c_, c, s );
 
     if ( c == 0 )
       a = 0x7FFFFFFFUL;
@@ -575,11 +558,8 @@
 
     /* XXX: this function does not allow 64-bit arguments */
 
-    a = (FT_UInt32)a_;
-    b = (FT_UInt32)b_;
-
-    FT_MOVE_SIGN( a_, a, s );
-    FT_MOVE_SIGN( b_, b, s );
+    FT_MOVE_SIGN( FT_UInt32, a_, a, s );
+    FT_MOVE_SIGN( FT_UInt32, b_, b, s );
 
     if ( a + ( b >> 8 ) <= 8190UL )
       a = ( a * b + 0x8000UL ) >> 16;
@@ -614,11 +594,8 @@
 
     /* XXX: this function does not allow 64-bit arguments */
 
-    a = (FT_UInt32)a_;
-    b = (FT_UInt32)b_;
-
-    FT_MOVE_SIGN( a_, a, s );
-    FT_MOVE_SIGN( b_, b, s );
+    FT_MOVE_SIGN( FT_UInt32, a_, a, s );
+    FT_MOVE_SIGN( FT_UInt32, b_, b, s );
 
     if ( b == 0 )
     {
@@ -829,11 +806,8 @@
     FT_Int     sx = 1, sy = 1, shift;
 
 
-    x = (FT_UInt32)x_;
-    y = (FT_UInt32)y_;
-
-    FT_MOVE_SIGN( x_, x, sx );
-    FT_MOVE_SIGN( y_, y, sy );
+    FT_MOVE_SIGN( FT_UInt32, x_, x, sx );
+    FT_MOVE_SIGN( FT_UInt32, y_, y, sy );
 
     /* trivial cases */
     if ( x == 0 )
@@ -913,43 +887,71 @@
   }
 
 
-#if 0
-
   /* documentation is in ftcalc.h */
 
-  FT_BASE_DEF( FT_Int32 )
-  FT_SqrtFixed( FT_Int32  x )
+  FT_BASE_DEF( FT_UInt32 )
+  FT_SqrtFixed( FT_UInt32  v )
   {
-    FT_UInt32  root, rem_hi, rem_lo, test_div;
-    FT_Int     count;
-
+    if ( v == 0 )
+      return 0;
 
-    root = 0;
+#ifndef FT_INT64
 
-    if ( x > 0 )
+    /* Algorithm by Christophe Meessen (1993) with overflow fixed and    */
+    /* rounding added.  Any unsigned fixed 16.16 argument is acceptable. */
+    /* However, this algorithm is slower than the Babylonian method with */
+    /* a good initial guess. We only use it for large 32-bit values when */
+    /* 64-bit computations are not desirable.                            */
+    else if ( v > 0x10000U )
     {
-      rem_hi = 0;
-      rem_lo = (FT_UInt32)x;
-      count  = 24;
+      FT_UInt32  r = v >> 1;
+      FT_UInt32  q = ( v & 1 ) << 15;
+      FT_UInt32  b = 0x20000000;
+      FT_UInt32  t;
+
+
       do
       {
-        rem_hi   = ( rem_hi << 2 ) | ( rem_lo >> 30 );
-        rem_lo <<= 2;
-        root   <<= 1;
-        test_div = ( root << 1 ) + 1;
-
-        if ( rem_hi >= test_div )
+        t = q + b;
+        if ( r >= t )
         {
-          rem_hi -= test_div;
-          root   += 1;
+          r -= t;
+          q  = t + b;  /* equivalent to q += 2*b */
         }
-      } while ( --count );
+        r <<= 1;
+        b >>= 1;
+      }
+      while ( b > 0x10 );  /* exactly 25 cycles */
+
+      return ( q + 0x40 ) >> 7;
     }
+    else
+    {
+      FT_UInt32  r = ( v << 16 ) - 1;
 
-    return (FT_Int32)root;
-  }
+#else /* FT_INT64 */
 
-#endif /* 0 */
+    else
+    {
+      FT_UInt64  r = ( (FT_UInt64)v << 16 ) - 1;
+
+#endif /* FT_INT64 */
+
+      FT_UInt32  q = 1 << ( ( 17 + FT_MSB( v ) ) >> 1 );
+      FT_UInt32  t;
+
+
+      /* Babylonian method with rounded-up division */
+      do
+      {
+        t = q;
+        q = ( t + (FT_UInt32)( r / t ) + 1 ) >> 1;
+      }
+      while ( q != t );  /* less than 6 cycles */
+
+      return q;
+    }
+  }
 
 
   /* documentation is in ftcalc.h */
@@ -1094,11 +1096,8 @@
       FT_UInt32  factor;
 
 
-      scalar = (FT_UInt32)s[i];
-      factor = (FT_UInt32)f[i];
-
-      FT_MOVE_SIGN( s[i], scalar, sign );
-      FT_MOVE_SIGN( f[i], factor, sign );
+      FT_MOVE_SIGN( FT_UInt32, s[i], scalar, sign );
+      FT_MOVE_SIGN( FT_UInt32, f[i], factor, sign );
 
       ft_multo64( scalar, factor, &multResult );
 
diff --git a/vendor/freetype/src/base/ftcid.c b/vendor/freetype/src/base/ftcid.c
index 866cd23e91..4f2deb19a0 100644
--- a/vendor/freetype/src/base/ftcid.c
+++ b/vendor/freetype/src/base/ftcid.c
@@ -4,7 +4,7 @@
  *
  *   FreeType API for accessing CID font information.
  *
- * Copyright (C) 2007-2023 by
+ * Copyright (C) 2007-2024 by
  * Derek Clegg and Michael Toftdal.
  *
  * This file is part of the FreeType project, and may only be used,
diff --git a/vendor/freetype/src/base/ftcolor.c b/vendor/freetype/src/base/ftcolor.c
index bcd6e893d4..c6bf2a3cd1 100644
--- a/vendor/freetype/src/base/ftcolor.c
+++ b/vendor/freetype/src/base/ftcolor.c
@@ -4,7 +4,7 @@
  *
  *   FreeType's glyph color management (body).
  *
- * Copyright (C) 2018-2023 by
+ * Copyright (C) 2018-2024 by
  * David Turner, Robert Wilhelm, and Werner Lemberg.
  *
  * This file is part of the FreeType project, and may only be used,
diff --git a/vendor/freetype/src/base/ftdbgmem.c b/vendor/freetype/src/base/ftdbgmem.c
index 8fab50dd01..902a5dc8bb 100644
--- a/vendor/freetype/src/base/ftdbgmem.c
+++ b/vendor/freetype/src/base/ftdbgmem.c
@@ -4,7 +4,7 @@
  *
  *   Memory debugger (body).
  *
- * Copyright (C) 2001-2023 by
+ * Copyright (C) 2001-2024 by
  * David Turner, Robert Wilhelm, and Werner Lemberg.
  *
  * This file is part of the FreeType project, and may only be used,
diff --git a/vendor/freetype/src/base/ftdebug.c b/vendor/freetype/src/base/ftdebug.c
index 61c4563b0c..11307eaace 100644
--- a/vendor/freetype/src/base/ftdebug.c
+++ b/vendor/freetype/src/base/ftdebug.c
@@ -4,7 +4,7 @@
  *
  *   Debugging and logging component (body).
  *
- * Copyright (C) 1996-2023 by
+ * Copyright (C) 1996-2024 by
  * David Turner, Robert Wilhelm, and Werner Lemberg.
  *
  * This file is part of the FreeType project, and may only be used,
diff --git a/vendor/freetype/src/base/fterrors.c b/vendor/freetype/src/base/fterrors.c
index 5ad9709c80..61041a37c1 100644
--- a/vendor/freetype/src/base/fterrors.c
+++ b/vendor/freetype/src/base/fterrors.c
@@ -4,7 +4,7 @@
  *
  *   FreeType API for error code handling.
  *
- * Copyright (C) 2018-2023 by
+ * Copyright (C) 2018-2024 by
  * Armin Hasitzka, David Turner, Robert Wilhelm, and Werner Lemberg.
  *
  * This file is part of the FreeType project, and may only be used,
diff --git a/vendor/freetype/src/base/ftfntfmt.c b/vendor/freetype/src/base/ftfntfmt.c
index 0b41f7cc83..77b4089e7e 100644
--- a/vendor/freetype/src/base/ftfntfmt.c
+++ b/vendor/freetype/src/base/ftfntfmt.c
@@ -4,7 +4,7 @@
  *
  *   FreeType utility file for font formats (body).
  *
- * Copyright (C) 2002-2023 by
+ * Copyright (C) 2002-2024 by
  * David Turner, Robert Wilhelm, and Werner Lemberg.
  *
  * This file is part of the FreeType project, and may only be used,
diff --git a/vendor/freetype/src/base/ftfstype.c b/vendor/freetype/src/base/ftfstype.c
index ea24e64c6e..1565c3b7e2 100644
--- a/vendor/freetype/src/base/ftfstype.c
+++ b/vendor/freetype/src/base/ftfstype.c
@@ -4,7 +4,7 @@
  *
  *   FreeType utility file to access FSType data (body).
  *
- * Copyright (C) 2008-2023 by
+ * Copyright (C) 2008-2024 by
  * David Turner, Robert Wilhelm, and Werner Lemberg.
  *
  * This file is part of the FreeType project, and may only be used,
diff --git a/vendor/freetype/src/base/ftgasp.c b/vendor/freetype/src/base/ftgasp.c
index 29b7b08b78..c63d30e978 100644
--- a/vendor/freetype/src/base/ftgasp.c
+++ b/vendor/freetype/src/base/ftgasp.c
@@ -4,7 +4,7 @@
  *
  *   Access of TrueType's `gasp' table (body).
  *
- * Copyright (C) 2007-2023 by
+ * Copyright (C) 2007-2024 by
  * David Turner, Robert Wilhelm, and Werner Lemberg.
  *
  * This file is part of the FreeType project, and may only be used,
diff --git a/vendor/freetype/src/base/ftgloadr.c b/vendor/freetype/src/base/ftgloadr.c
index 9823d09e41..484d98f172 100644
--- a/vendor/freetype/src/base/ftgloadr.c
+++ b/vendor/freetype/src/base/ftgloadr.c
@@ -4,7 +4,7 @@
  *
  *   The FreeType glyph loader (body).
  *
- * Copyright (C) 2002-2023 by
+ * Copyright (C) 2002-2024 by
  * David Turner, Robert Wilhelm, and Werner Lemberg
  *
  * This file is part of the FreeType project, and may only be used,
@@ -355,34 +355,25 @@
   FT_BASE_DEF( void )
   FT_GlyphLoader_Add( FT_GlyphLoader  loader )
   {
-    FT_GlyphLoad  base;
-    FT_GlyphLoad  current;
-
-    FT_Int        n_curr_contours;
-    FT_Int        n_base_points;
-    FT_Int        n;
+    FT_Outline*  base;
+    FT_Outline*  current;
+    FT_Int       n;
 
 
     if ( !loader )
       return;
 
-    base    = &loader->base;
-    current = &loader->current;
-
-    n_curr_contours = current->outline.n_contours;
-    n_base_points   = base->outline.n_points;
+    base    = &loader->base.outline;
+    current = &loader->current.outline;
 
-    base->outline.n_points =
-      (short)( base->outline.n_points + current->outline.n_points );
-    base->outline.n_contours =
-      (short)( base->outline.n_contours + current->outline.n_contours );
+    /* adjust contours count in newest outline */
+    for ( n = 0; n < current->n_contours; n++ )
+      current->contours[n] += base->n_points;
 
-    base->num_subglyphs += current->num_subglyphs;
+    base->n_points   += current->n_points;
+    base->n_contours += current->n_contours;
 
-    /* adjust contours count in newest outline */
-    for ( n = 0; n < n_curr_contours; n++ )
-      current->outline.contours[n] =
-        (short)( current->outline.contours[n] + n_base_points );
+    loader->base.num_subglyphs += loader->current.num_subglyphs;
 
     /* prepare for another new glyph image */
     FT_GlyphLoader_Prepare( loader );
diff --git a/vendor/freetype/src/base/ftglyph.c b/vendor/freetype/src/base/ftglyph.c
index 393d4949f8..1b5849f99a 100644
--- a/vendor/freetype/src/base/ftglyph.c
+++ b/vendor/freetype/src/base/ftglyph.c
@@ -4,7 +4,7 @@
  *
  *   FreeType convenience functions to handle glyphs (body).
  *
- * Copyright (C) 1996-2023 by
+ * Copyright (C) 1996-2024 by
  * David Turner, Robert Wilhelm, and Werner Lemberg.
  *
  * This file is part of the FreeType project, and may only be used,
diff --git a/vendor/freetype/src/base/ftgxval.c b/vendor/freetype/src/base/ftgxval.c
index 6b3c5d2484..6e38cb5ba9 100644
--- a/vendor/freetype/src/base/ftgxval.c
+++ b/vendor/freetype/src/base/ftgxval.c
@@ -4,7 +4,7 @@
  *
  *   FreeType API for validating TrueTypeGX/AAT tables (body).
  *
- * Copyright (C) 2004-2023 by
+ * Copyright (C) 2004-2024 by
  * Masatake YAMATO, Redhat K.K,
  * David Turner, Robert Wilhelm, and Werner Lemberg.
  *
diff --git a/vendor/freetype/src/base/ftinit.c b/vendor/freetype/src/base/ftinit.c
index c9c71d24bf..9a6c00e13e 100644
--- a/vendor/freetype/src/base/ftinit.c
+++ b/vendor/freetype/src/base/ftinit.c
@@ -4,7 +4,7 @@
  *
  *   FreeType initialization layer (body).
  *
- * Copyright (C) 1996-2023 by
+ * Copyright (C) 1996-2024 by
  * David Turner, Robert Wilhelm, and Werner Lemberg.
  *
  * This file is part of the FreeType project, and may only be used,
diff --git a/vendor/freetype/src/base/ftlcdfil.c b/vendor/freetype/src/base/ftlcdfil.c
index 6c3fd66e0b..1e69d4da70 100644
--- a/vendor/freetype/src/base/ftlcdfil.c
+++ b/vendor/freetype/src/base/ftlcdfil.c
@@ -4,7 +4,7 @@
  *
  *   FreeType API for color filtering of subpixel bitmap glyphs (body).
  *
- * Copyright (C) 2006-2023 by
+ * Copyright (C) 2006-2024 by
  * David Turner, Robert Wilhelm, and Werner Lemberg.
  *
  * This file is part of the FreeType project, and may only be used,
diff --git a/vendor/freetype/src/base/ftmac.c b/vendor/freetype/src/base/ftmac.c
index 492d055384..e8e35627b5 100644
--- a/vendor/freetype/src/base/ftmac.c
+++ b/vendor/freetype/src/base/ftmac.c
@@ -8,7 +8,7 @@
  * This file is for Mac OS X only; see builds/mac/ftoldmac.c for
  * classic platforms built by MPW.
  *
- * Copyright (C) 1996-2023 by
+ * Copyright (C) 1996-2024 by
  * Just van Rossum, David Turner, Robert Wilhelm, and Werner Lemberg.
  *
  * This file is part of the FreeType project, and may only be used,
@@ -812,6 +812,7 @@
     ResourceIndex  res_index;
     Handle         fond;
     short          num_faces_in_res;
+    FT_Long        count;
 
 
     if ( noErr != FT_FSPathMakeRes( pathname, &res_ref ) )
@@ -821,8 +822,10 @@
     if ( ResError() )
       return FT_THROW( Cannot_Open_Resource );
 
+    res_index        = 1;
     num_faces_in_res = 0;
-    for ( res_index = 1; ; res_index++ )
+    count            = face_index;
+    while ( count >= 0 )
     {
       short  num_faces_in_fond;
 
@@ -834,15 +837,21 @@
       num_faces_in_fond  = count_faces( fond, pathname );
       num_faces_in_res  += num_faces_in_fond;
 
-      if ( 0 <= face_index && face_index < num_faces_in_fond && error )
-        error = FT_New_Face_From_FOND( library, fond, face_index, aface );
+      if ( count < num_faces_in_fond )
+        error = FT_New_Face_From_FOND( library, fond, count, aface );
 
-      face_index -= num_faces_in_fond;
+      res_index++;
+      count -= num_faces_in_fond;
     }
 
     CloseResFile( res_ref );
+
     if ( !error && aface && *aface )
-      (*aface)->num_faces = num_faces_in_res;
+    {
+      (*aface)->num_faces  = num_faces_in_res;
+      (*aface)->face_index = face_index;
+    }
+
     return error;
   }
 
diff --git a/vendor/freetype/src/base/ftmm.c b/vendor/freetype/src/base/ftmm.c
index 9e2dd7ee79..cc4ca22fba 100644
--- a/vendor/freetype/src/base/ftmm.c
+++ b/vendor/freetype/src/base/ftmm.c
@@ -4,7 +4,7 @@
  *
  *   Multiple Master font support (body).
  *
- * Copyright (C) 1996-2023 by
+ * Copyright (C) 1996-2024 by
  * David Turner, Robert Wilhelm, and Werner Lemberg.
  *
  * This file is part of the FreeType project, and may only be used,
diff --git a/vendor/freetype/src/base/ftobjs.c b/vendor/freetype/src/base/ftobjs.c
index 89a25bc732..9b97820c37 100644
--- a/vendor/freetype/src/base/ftobjs.c
+++ b/vendor/freetype/src/base/ftobjs.c
@@ -4,7 +4,7 @@
  *
  *   The FreeType private base classes (body).
  *
- * Copyright (C) 1996-2023 by
+ * Copyright (C) 1996-2024 by
  * David Turner, Robert Wilhelm, and Werner Lemberg.
  *
  * This file is part of the FreeType project, and may only be used,
@@ -2302,7 +2302,10 @@
                                       face_index_internal, aface );
       FT_FREE( data_offsets );
       if ( !error )
-        (*aface)->num_faces = count;
+      {
+        (*aface)->num_faces  = count;
+        (*aface)->face_index = face_index_internal;
+      }
     }
 
     return error;
@@ -5791,7 +5794,7 @@
     ttface = (TT_Face)face;
     sfnt   = (SFNT_Service)ttface->sfnt;
 
-    if ( sfnt->get_colr_layer )
+    if ( sfnt->get_colr_glyph_paint )
       return sfnt->get_colr_glyph_paint( ttface,
                                          base_glyph,
                                          root_transform,
diff --git a/vendor/freetype/src/base/ftotval.c b/vendor/freetype/src/base/ftotval.c
index 192e12a71f..aed9eef343 100644
--- a/vendor/freetype/src/base/ftotval.c
+++ b/vendor/freetype/src/base/ftotval.c
@@ -4,7 +4,7 @@
  *
  *   FreeType API for validating OpenType tables (body).
  *
- * Copyright (C) 2004-2023 by
+ * Copyright (C) 2004-2024 by
  * David Turner, Robert Wilhelm, and Werner Lemberg.
  *
  * This file is part of the FreeType project, and may only be used,
diff --git a/vendor/freetype/src/base/ftoutln.c b/vendor/freetype/src/base/ftoutln.c
index 134f39d2b1..ef699b3c7c 100644
--- a/vendor/freetype/src/base/ftoutln.c
+++ b/vendor/freetype/src/base/ftoutln.c
@@ -4,7 +4,7 @@
  *
  *   FreeType outline management (body).
  *
- * Copyright (C) 1996-2023 by
+ * Copyright (C) 1996-2024 by
  * David Turner, Robert Wilhelm, and Werner Lemberg.
  *
  * This file is part of the FreeType project, and may only be used,
@@ -53,7 +53,7 @@
 
     FT_Vector*  point;
     FT_Vector*  limit;
-    char*       tags;
+    FT_Byte*    tags;
 
     FT_Error    error;
 
@@ -332,8 +332,8 @@
          FT_NEW_ARRAY( anoutline->contours, numContours ) )
       goto Fail;
 
-    anoutline->n_points    = (FT_Short)numPoints;
-    anoutline->n_contours  = (FT_Short)numContours;
+    anoutline->n_points    = (FT_UShort)numPoints;
+    anoutline->n_contours  = (FT_UShort)numContours;
     anoutline->flags      |= FT_OUTLINE_OWNER;
 
     return FT_Err_Ok;
@@ -359,12 +359,14 @@
       FT_Int  n;
 
 
+      FT_TRACE5(( "FT_Outline_Check: contours = %d, points = %d\n",
+                  n_contours, n_points ));
       /* empty glyph? */
       if ( n_points == 0 && n_contours == 0 )
         return FT_Err_Ok;
 
       /* check point and contour counts */
-      if ( n_points <= 0 || n_contours <= 0 )
+      if ( n_points == 0 || n_contours == 0 )
         goto Bad;
 
       end0 = -1;
@@ -576,13 +578,13 @@
 
       /* reverse tags table */
       {
-        char*  p = outline->tags + first;
-        char*  q = outline->tags + last;
+        FT_Byte*  p = outline->tags + first;
+        FT_Byte*  q = outline->tags + last;
 
 
         while ( p < q )
         {
-          char  swap;
+          FT_Byte  swap;
 
 
           swap = *p;
diff --git a/vendor/freetype/src/base/ftpatent.c b/vendor/freetype/src/base/ftpatent.c
index cb5efadffb..2055757e02 100644
--- a/vendor/freetype/src/base/ftpatent.c
+++ b/vendor/freetype/src/base/ftpatent.c
@@ -5,7 +5,7 @@
  *   FreeType API for checking patented TrueType bytecode instructions
  *   (body).  Obsolete, retained for backward compatibility.
  *
- * Copyright (C) 2007-2023 by
+ * Copyright (C) 2007-2024 by
  * David Turner.
  *
  * This file is part of the FreeType project, and may only be used,
diff --git a/vendor/freetype/src/base/ftpfr.c b/vendor/freetype/src/base/ftpfr.c
index 378385a591..0caa9d1d58 100644
--- a/vendor/freetype/src/base/ftpfr.c
+++ b/vendor/freetype/src/base/ftpfr.c
@@ -4,7 +4,7 @@
  *
  *   FreeType API for accessing PFR-specific data (body).
  *
- * Copyright (C) 2002-2023 by
+ * Copyright (C) 2002-2024 by
  * David Turner, Robert Wilhelm, and Werner Lemberg.
  *
  * This file is part of the FreeType project, and may only be used,
diff --git a/vendor/freetype/src/base/ftpsprop.c b/vendor/freetype/src/base/ftpsprop.c
index cefdf489d7..37a6cee6cc 100644
--- a/vendor/freetype/src/base/ftpsprop.c
+++ b/vendor/freetype/src/base/ftpsprop.c
@@ -5,7 +5,7 @@
  *   Get and set properties of PostScript drivers (body).
  *   See `ftdriver.h' for available properties.
  *
- * Copyright (C) 2017-2023 by
+ * Copyright (C) 2017-2024 by
  * David Turner, Robert Wilhelm, and Werner Lemberg.
  *
  * This file is part of the FreeType project, and may only be used,
diff --git a/vendor/freetype/src/base/ftrfork.c b/vendor/freetype/src/base/ftrfork.c
index 2ab430195f..dc9b043d8b 100644
--- a/vendor/freetype/src/base/ftrfork.c
+++ b/vendor/freetype/src/base/ftrfork.c
@@ -4,7 +4,7 @@
  *
  *   Embedded resource forks accessor (body).
  *
- * Copyright (C) 2004-2023 by
+ * Copyright (C) 2004-2024 by
  * Masatake YAMATO and Redhat K.K.
  *
  * FT_Raccess_Get_HeaderInfo() and raccess_guess_darwin_hfsplus() are
diff --git a/vendor/freetype/src/base/ftsnames.c b/vendor/freetype/src/base/ftsnames.c
index 1917a3f1df..f7231fd61c 100644
--- a/vendor/freetype/src/base/ftsnames.c
+++ b/vendor/freetype/src/base/ftsnames.c
@@ -7,7 +7,7 @@
  *
  *   This is _not_ used to retrieve glyph names!
  *
- * Copyright (C) 1996-2023 by
+ * Copyright (C) 1996-2024 by
  * David Turner, Robert Wilhelm, and Werner Lemberg.
  *
  * This file is part of the FreeType project, and may only be used,
diff --git a/vendor/freetype/src/base/ftstream.c b/vendor/freetype/src/base/ftstream.c
index 64826acebe..41fd913be9 100644
--- a/vendor/freetype/src/base/ftstream.c
+++ b/vendor/freetype/src/base/ftstream.c
@@ -4,7 +4,7 @@
  *
  *   I/O stream support (body).
  *
- * Copyright (C) 2000-2023 by
+ * Copyright (C) 2000-2024 by
  * David Turner, Robert Wilhelm, and Werner Lemberg.
  *
  * This file is part of the FreeType project, and may only be used,
@@ -830,7 +830,7 @@
         goto Exit;
       }
 
-      /* now, compute the signed value is necessary */
+      /* now, compute the signed value if necessary */
       if ( fields->value & FT_FRAME_OP_SIGNED )
         value = (FT_ULong)( (FT_Int32)( value << sign_shift ) >> sign_shift );
 
diff --git a/vendor/freetype/src/base/ftstroke.c b/vendor/freetype/src/base/ftstroke.c
index 92f1e43080..64f46ce43e 100644
--- a/vendor/freetype/src/base/ftstroke.c
+++ b/vendor/freetype/src/base/ftstroke.c
@@ -4,7 +4,7 @@
  *
  *   FreeType path stroker (body).
  *
- * Copyright (C) 2002-2023 by
+ * Copyright (C) 2002-2024 by
  * David Turner, Robert Wilhelm, and Werner Lemberg.
  *
  * This file is part of the FreeType project, and may only be used,
@@ -711,7 +711,7 @@
     {
       FT_UInt   count = border->num_points;
       FT_Byte*  read  = border->tags;
-      FT_Byte*  write = (FT_Byte*)outline->tags + outline->n_points;
+      FT_Byte*  write = outline->tags + outline->n_points;
 
 
       for ( ; count > 0; count--, read++, write++ )
@@ -727,10 +727,10 @@
 
     /* copy contours */
     {
-      FT_UInt    count = border->num_points;
-      FT_Byte*   tags  = border->tags;
-      FT_Short*  write = outline->contours + outline->n_contours;
-      FT_Short   idx   = (FT_Short)outline->n_points;
+      FT_UInt     count = border->num_points;
+      FT_Byte*    tags  = border->tags;
+      FT_UShort*  write = outline->contours + outline->n_contours;
+      FT_UShort   idx   = outline->n_points;
 
 
       for ( ; count > 0; count--, tags++, idx++ )
@@ -743,7 +743,7 @@
       }
     }
 
-    outline->n_points += (short)border->num_points;
+    outline->n_points += (FT_UShort)border->num_points;
 
     FT_ASSERT( FT_Outline_Check( outline ) == 0 );
   }
@@ -2050,7 +2050,7 @@
 
     FT_Vector*  point;
     FT_Vector*  limit;
-    char*       tags;
+    FT_Byte*    tags;
 
     FT_Error    error;
 
diff --git a/vendor/freetype/src/base/ftsynth.c b/vendor/freetype/src/base/ftsynth.c
index f32edd3388..ec05bce33a 100644
--- a/vendor/freetype/src/base/ftsynth.c
+++ b/vendor/freetype/src/base/ftsynth.c
@@ -4,7 +4,7 @@
  *
  *   FreeType synthesizing code for emboldening and slanting (body).
  *
- * Copyright (C) 2000-2023 by
+ * Copyright (C) 2000-2024 by
  * David Turner, Robert Wilhelm, and Werner Lemberg.
  *
  * This file is part of the FreeType project, and may only be used,
diff --git a/vendor/freetype/src/base/ftsystem.c b/vendor/freetype/src/base/ftsystem.c
index 61c99e3635..eee3642334 100644
--- a/vendor/freetype/src/base/ftsystem.c
+++ b/vendor/freetype/src/base/ftsystem.c
@@ -4,7 +4,7 @@
  *
  *   ANSI-specific FreeType low-level system interface (body).
  *
- * Copyright (C) 1996-2023 by
+ * Copyright (C) 1996-2024 by
  * David Turner, Robert Wilhelm, and Werner Lemberg.
  *
  * This file is part of the FreeType project, and may only be used,
diff --git a/vendor/freetype/src/base/fttrigon.c b/vendor/freetype/src/base/fttrigon.c
index 2dd2c3459e..4b1aced1cb 100644
--- a/vendor/freetype/src/base/fttrigon.c
+++ b/vendor/freetype/src/base/fttrigon.c
@@ -4,7 +4,7 @@
  *
  *   FreeType trigonometric functions (body).
  *
- * Copyright (C) 2001-2023 by
+ * Copyright (C) 2001-2024 by
  * David Turner, Robert Wilhelm, and Werner Lemberg.
  *
  * This file is part of the FreeType project, and may only be used,
diff --git a/vendor/freetype/src/base/fttype1.c b/vendor/freetype/src/base/fttype1.c
index 637c5cf775..cedf7c4050 100644
--- a/vendor/freetype/src/base/fttype1.c
+++ b/vendor/freetype/src/base/fttype1.c
@@ -4,7 +4,7 @@
  *
  *   FreeType utility file for PS names support (body).
  *
- * Copyright (C) 2002-2023 by
+ * Copyright (C) 2002-2024 by
  * David Turner, Robert Wilhelm, and Werner Lemberg.
  *
  * This file is part of the FreeType project, and may only be used,
diff --git a/vendor/freetype/src/base/ftutil.c b/vendor/freetype/src/base/ftutil.c
index 6120846d2c..b13512f870 100644
--- a/vendor/freetype/src/base/ftutil.c
+++ b/vendor/freetype/src/base/ftutil.c
@@ -4,7 +4,7 @@
  *
  *   FreeType utility file for memory and list management (body).
  *
- * Copyright (C) 2002-2023 by
+ * Copyright (C) 2002-2024 by
  * David Turner, Robert Wilhelm, and Werner Lemberg.
  *
  * This file is part of the FreeType project, and may only be used,
diff --git a/vendor/freetype/src/base/ftver.rc b/vendor/freetype/src/base/ftver.rc
index 137a6334b7..62490c0638 100644
--- a/vendor/freetype/src/base/ftver.rc
+++ b/vendor/freetype/src/base/ftver.rc
@@ -4,7 +4,7 @@
 /*                                                                         */
 /*    FreeType VERSIONINFO resource for Windows DLLs.                      */
 /*                                                                         */
-/*  Copyright (C) 2018-2023 by                                             */
+/*  Copyright (C) 2018-2024 by                                             */
 /*  David Turner, Robert Wilhelm, and Werner Lemberg.                      */
 /*                                                                         */
 /*  This file is part of the FreeType project, and may only be used,       */
diff --git a/vendor/freetype/src/base/ftwinfnt.c b/vendor/freetype/src/base/ftwinfnt.c
index 03b023e079..e849a15f42 100644
--- a/vendor/freetype/src/base/ftwinfnt.c
+++ b/vendor/freetype/src/base/ftwinfnt.c
@@ -4,7 +4,7 @@
  *
  *   FreeType API for accessing Windows FNT specific info (body).
  *
- * Copyright (C) 2003-2023 by
+ * Copyright (C) 2003-2024 by
  * David Turner, Robert Wilhelm, and Werner Lemberg.
  *
  * This file is part of the FreeType project, and may only be used,
diff --git a/vendor/freetype/src/bdf/bdflib.c b/vendor/freetype/src/bdf/bdflib.c
index 0fa7e0a8c5..813a4d839c 100644
--- a/vendor/freetype/src/bdf/bdflib.c
+++ b/vendor/freetype/src/bdf/bdflib.c
@@ -864,15 +864,9 @@
 
     p = font->user_props + font->nuser_props;
 
-    n = ft_strlen( name ) + 1;
-    if ( n > FT_LONG_MAX )
-      return FT_THROW( Invalid_Argument );
-
-    if ( FT_QALLOC( p->name, n ) )
+    if ( FT_STRDUP( p->name, name ) )
       goto Exit;
 
-    FT_MEM_COPY( (char *)p->name, name, n );
-
     p->format     = format;
     p->builtin    = 0;
     p->value.atom = NULL;  /* nothing is ever stored here */
@@ -1442,11 +1436,9 @@
         goto Exit;
       }
 
-      if ( FT_QALLOC( p->glyph_name, slen + 1 ) )
+      if ( FT_DUP( p->glyph_name, s, slen + 1 ) )
         goto Exit;
 
-      FT_MEM_COPY( p->glyph_name, s, slen + 1 );
-
       p->flags |= BDF_GLYPH_;
 
       FT_TRACE4(( DBGMSG1, lineno, s ));
@@ -2051,9 +2043,8 @@
       /* Allowing multiple `FONT' lines (which is invalid) doesn't hurt... */
       FT_FREE( p->font->name );
 
-      if ( FT_QALLOC( p->font->name, slen + 1 ) )
+      if ( FT_DUP( p->font->name, s, slen + 1 ) )
         goto Exit;
-      FT_MEM_COPY( p->font->name, s, slen + 1 );
 
       /* If the font name is an XLFD name, set the spacing to the one in  */
       /* the font name.  If there is no spacing fall back on the default. */
diff --git a/vendor/freetype/src/bzip2/ftbzip2.c b/vendor/freetype/src/bzip2/ftbzip2.c
index ad342bd011..a0249eb8d4 100644
--- a/vendor/freetype/src/bzip2/ftbzip2.c
+++ b/vendor/freetype/src/bzip2/ftbzip2.c
@@ -8,7 +8,7 @@
  * parse compressed PCF fonts, as found with many X11 server
  * distributions.
  *
- * Copyright (C) 2010-2023 by
+ * Copyright (C) 2010-2024 by
  * Joel Klinghed.
  *
  * based on `src/gzip/ftgzip.c'
diff --git a/vendor/freetype/src/cache/ftcache.c b/vendor/freetype/src/cache/ftcache.c
index 1af2e67727..81e0347af9 100644
--- a/vendor/freetype/src/cache/ftcache.c
+++ b/vendor/freetype/src/cache/ftcache.c
@@ -4,7 +4,7 @@
  *
  *   The FreeType Caching sub-system (body only).
  *
- * Copyright (C) 2000-2023 by
+ * Copyright (C) 2000-2024 by
  * David Turner, Robert Wilhelm, and Werner Lemberg.
  *
  * This file is part of the FreeType project, and may only be used,
diff --git a/vendor/freetype/src/cache/ftcbasic.c b/vendor/freetype/src/cache/ftcbasic.c
index 24a56c8d26..04f664fad7 100644
--- a/vendor/freetype/src/cache/ftcbasic.c
+++ b/vendor/freetype/src/cache/ftcbasic.c
@@ -4,7 +4,7 @@
  *
  *   The FreeType basic cache interface (body).
  *
- * Copyright (C) 2003-2023 by
+ * Copyright (C) 2003-2024 by
  * David Turner, Robert Wilhelm, and Werner Lemberg.
  *
  * This file is part of the FreeType project, and may only be used,
@@ -37,7 +37,7 @@
   typedef struct  FTC_BasicAttrRec_
   {
     FTC_ScalerRec  scaler;
-    FT_UInt        load_flags;
+    FT_Int32       load_flags;
 
   } FTC_BasicAttrRec, *FTC_BasicAttrs;
 
@@ -143,10 +143,9 @@
       FT_Face  face = size->face;
 
 
-      error = FT_Load_Glyph(
-                face,
-                gindex,
-                (FT_Int)family->attrs.load_flags | FT_LOAD_RENDER );
+      error = FT_Load_Glyph( face,
+                             gindex,
+                             family->attrs.load_flags | FT_LOAD_RENDER );
       if ( !error )
         *aface = face;
     }
@@ -176,9 +175,7 @@
     {
       face = size->face;
 
-      error = FT_Load_Glyph( face,
-                             gindex,
-                             (FT_Int)family->attrs.load_flags );
+      error = FT_Load_Glyph( face, gindex, family->attrs.load_flags );
       if ( !error )
       {
         if ( face->glyph->format == FT_GLYPH_FORMAT_BITMAP  ||
@@ -246,7 +243,6 @@
 
       ftc_basic_family_compare, /* FTC_MruNode_CompareFunc  node_compare */
       ftc_basic_family_init,    /* FTC_MruNode_InitFunc     node_init    */
-      NULL,                     /* FTC_MruNode_ResetFunc    node_reset   */
       NULL                      /* FTC_MruNode_DoneFunc     node_done    */
     },
 
@@ -293,40 +289,24 @@
                          FT_Glyph       *aglyph,
                          FTC_Node       *anode )
   {
-    FTC_BasicQueryRec  query;
-    FTC_Node           node = 0; /* make compiler happy */
     FT_Error           error;
+    FTC_BasicQueryRec  query;
+    FTC_Node           node = NULL;  /* make compiler happy */
     FT_Offset          hash;
 
 
-    /* some argument checks are delayed to `FTC_Cache_Lookup' */
+    /* other argument checks delayed to `FTC_Cache_Lookup' */
     if ( !aglyph )
-    {
-      error = FT_THROW( Invalid_Argument );
-      goto Exit;
-    }
+      return FT_THROW( Invalid_Argument );
 
     *aglyph = NULL;
     if ( anode )
-      *anode  = NULL;
-
-    /*
-     * Internal `FTC_BasicAttr->load_flags' is of type `FT_UInt',
-     * but public `FT_ImageType->flags' is of type `FT_Int32'.
-     *
-     * On 16bit systems, higher bits of type->flags cannot be handled.
-     */
-#if 0xFFFFFFFFUL > FT_UINT_MAX
-    if ( (type->flags & (FT_ULong)FT_UINT_MAX) )
-      FT_TRACE1(( "FTC_ImageCache_Lookup:"
-                  " higher bits in load_flags 0x%lx are dropped\n",
-                  (FT_ULong)type->flags & ~((FT_ULong)FT_UINT_MAX) ));
-#endif
+      *anode = NULL;
 
     query.attrs.scaler.face_id = type->face_id;
     query.attrs.scaler.width   = type->width;
     query.attrs.scaler.height  = type->height;
-    query.attrs.load_flags     = (FT_UInt)type->flags;
+    query.attrs.load_flags     = type->flags;
 
     query.attrs.scaler.pixel = 1;
     query.attrs.scaler.x_res = 0;  /* make compilers happy */
@@ -334,7 +314,7 @@
 
     hash = FTC_BASIC_ATTR_HASH( &query.attrs ) + gindex;
 
-#if 1  /* inlining is about 50% faster! */
+#ifdef FTC_INLINE  /* inlining is about 50% faster! */
     FTC_GCACHE_LOOKUP_CMP( cache,
                            ftc_basic_family_compare,
                            ftc_gnode_compare,
@@ -359,7 +339,6 @@
       }
     }
 
-  Exit:
     return error;
   }
 
@@ -374,38 +353,35 @@
                                FT_Glyph       *aglyph,
                                FTC_Node       *anode )
   {
-    FTC_BasicQueryRec  query;
-    FTC_Node           node = 0; /* make compiler happy */
     FT_Error           error;
+    FTC_BasicQueryRec  query;
+    FTC_Node           node = NULL;  /* make compiler happy */
     FT_Offset          hash;
 
 
-    /* some argument checks are delayed to `FTC_Cache_Lookup' */
+    /* other argument checks delayed to `FTC_Cache_Lookup' */
     if ( !aglyph || !scaler )
-    {
-      error = FT_THROW( Invalid_Argument );
-      goto Exit;
-    }
+      return FT_THROW( Invalid_Argument );
 
     *aglyph = NULL;
     if ( anode )
-      *anode  = NULL;
+      *anode = NULL;
 
     /*
-     * Internal `FTC_BasicAttr->load_flags' is of type `FT_UInt',
+     * Internal `FTC_BasicAttr->load_flags' is of type `FT_Int32',
      * but public `FT_Face->face_flags' is of type `FT_Long'.
      *
      * On long > int systems, higher bits of load_flags cannot be handled.
      */
-#if FT_ULONG_MAX > FT_UINT_MAX
-    if ( load_flags > FT_UINT_MAX )
+#if FT_ULONG_MAX > 0xFFFFFFFFUL
+    if ( load_flags > 0xFFFFFFFFUL )
       FT_TRACE1(( "FTC_ImageCache_LookupScaler:"
                   " higher bits in load_flags 0x%lx are dropped\n",
-                  load_flags & ~((FT_ULong)FT_UINT_MAX) ));
+                  load_flags & ~0xFFFFFFFFUL ));
 #endif
 
     query.attrs.scaler     = scaler[0];
-    query.attrs.load_flags = (FT_UInt)load_flags;
+    query.attrs.load_flags = (FT_Int32)load_flags;
 
     hash = FTC_BASIC_ATTR_HASH( &query.attrs ) + gindex;
 
@@ -427,7 +403,6 @@
       }
     }
 
-  Exit:
     return error;
   }
 
@@ -445,7 +420,6 @@
       sizeof ( FTC_BasicFamilyRec ),
       ftc_basic_family_compare,     /* FTC_MruNode_CompareFunc  node_compare */
       ftc_basic_family_init,        /* FTC_MruNode_InitFunc     node_init    */
-      NULL,                         /* FTC_MruNode_ResetFunc    node_reset   */
       NULL                          /* FTC_MruNode_DoneFunc     node_done    */
     },
 
@@ -495,36 +469,22 @@
   {
     FT_Error           error;
     FTC_BasicQueryRec  query;
-    FTC_Node           node = 0; /* make compiler happy */
+    FTC_Node           node = NULL;  /* make compiler happy */
     FT_Offset          hash;
 
 
-    if ( anode )
-      *anode = NULL;
-
     /* other argument checks delayed to `FTC_Cache_Lookup' */
     if ( !ansbit )
       return FT_THROW( Invalid_Argument );
 
     *ansbit = NULL;
-
-    /*
-     * Internal `FTC_BasicAttr->load_flags' is of type `FT_UInt',
-     * but public `FT_ImageType->flags' is of type `FT_Int32'.
-     *
-     * On 16bit systems, higher bits of type->flags cannot be handled.
-     */
-#if 0xFFFFFFFFUL > FT_UINT_MAX
-    if ( (type->flags & (FT_ULong)FT_UINT_MAX) )
-      FT_TRACE1(( "FTC_ImageCache_Lookup:"
-                  " higher bits in load_flags 0x%lx are dropped\n",
-                  (FT_ULong)type->flags & ~((FT_ULong)FT_UINT_MAX) ));
-#endif
+    if ( anode )
+      *anode = NULL;
 
     query.attrs.scaler.face_id = type->face_id;
     query.attrs.scaler.width   = type->width;
     query.attrs.scaler.height  = type->height;
-    query.attrs.load_flags     = (FT_UInt)type->flags;
+    query.attrs.load_flags     = type->flags;
 
     query.attrs.scaler.pixel = 1;
     query.attrs.scaler.x_res = 0;  /* make compilers happy */
@@ -534,7 +494,7 @@
     hash = FTC_BASIC_ATTR_HASH( &query.attrs ) +
            gindex / FTC_SBIT_ITEMS_PER_NODE;
 
-#if 1  /* inlining is about 50% faster! */
+#ifdef FTC_INLINE  /* inlining is about 50% faster! */
     FTC_GCACHE_LOOKUP_CMP( cache,
                            ftc_basic_family_compare,
                            ftc_snode_compare,
@@ -578,34 +538,33 @@
   {
     FT_Error           error;
     FTC_BasicQueryRec  query;
-    FTC_Node           node = 0; /* make compiler happy */
+    FTC_Node           node = NULL;  /* make compiler happy */
     FT_Offset          hash;
 
 
-    if ( anode )
-        *anode = NULL;
-
     /* other argument checks delayed to `FTC_Cache_Lookup' */
     if ( !ansbit || !scaler )
-        return FT_THROW( Invalid_Argument );
+      return FT_THROW( Invalid_Argument );
 
     *ansbit = NULL;
+    if ( anode )
+      *anode = NULL;
 
     /*
-     * Internal `FTC_BasicAttr->load_flags' is of type `FT_UInt',
+     * Internal `FTC_BasicAttr->load_flags' is of type `FT_Int32',
      * but public `FT_Face->face_flags' is of type `FT_Long'.
      *
      * On long > int systems, higher bits of load_flags cannot be handled.
      */
-#if FT_ULONG_MAX > FT_UINT_MAX
-    if ( load_flags > FT_UINT_MAX )
+#if FT_ULONG_MAX > 0xFFFFFFFFUL
+    if ( load_flags > 0xFFFFFFFFUL )
       FT_TRACE1(( "FTC_ImageCache_LookupScaler:"
                   " higher bits in load_flags 0x%lx are dropped\n",
-                  load_flags & ~((FT_ULong)FT_UINT_MAX) ));
+                  load_flags & ~0xFFFFFFFFUL ));
 #endif
 
     query.attrs.scaler     = scaler[0];
-    query.attrs.load_flags = (FT_UInt)load_flags;
+    query.attrs.load_flags = (FT_Int32)load_flags;
 
     /* beware, the hash must be the same for all glyph ranges! */
     hash = FTC_BASIC_ATTR_HASH( &query.attrs ) +
diff --git a/vendor/freetype/src/cache/ftccache.c b/vendor/freetype/src/cache/ftccache.c
index e0698557b7..8a3d887f96 100644
--- a/vendor/freetype/src/cache/ftccache.c
+++ b/vendor/freetype/src/cache/ftccache.c
@@ -4,7 +4,7 @@
  *
  *   The FreeType internal cache interface (body).
  *
- * Copyright (C) 2000-2023 by
+ * Copyright (C) 2000-2024 by
  * David Turner, Robert Wilhelm, and Werner Lemberg.
  *
  * This file is part of the FreeType project, and may only be used,
@@ -544,7 +544,6 @@
                           FTC_FaceID  face_id )
   {
     FTC_Manager  manager = cache->manager;
-    FTC_Node     frees   = NULL;
     FT_UFast     count   = cache->p;
     FT_UFast     i;
 
@@ -557,41 +556,27 @@
       for (;;)
       {
         FTC_Node  node = *pnode;
-        FT_Bool   list_changed = FALSE;
 
 
         if ( !node )
           break;
 
-        if ( cache->clazz.node_remove_faceid( node, face_id,
-                                              cache, &list_changed ) )
+        if ( cache->clazz.node_remove_faceid( node, face_id, cache, NULL ) )
         {
-          *pnode     = node->link;
-          node->link = frees;
-          frees      = node;
+          *pnode = node->link;
+
+          manager->cur_weight -= cache->clazz.node_weight( node, cache );
+          ftc_node_mru_unlink( node, manager );
+
+          cache->clazz.node_free( node, cache );
+
+          cache->slack++;
         }
         else
           pnode = &node->link;
       }
     }
 
-    /* remove all nodes in the free list */
-    while ( frees )
-    {
-      FTC_Node  node;
-
-
-      node  = frees;
-      frees = node->link;
-
-      manager->cur_weight -= cache->clazz.node_weight( node, cache );
-      ftc_node_mru_unlink( node, manager );
-
-      cache->clazz.node_free( node, cache );
-
-      cache->slack++;
-    }
-
     ftc_cache_resize( cache );
   }
 
diff --git a/vendor/freetype/src/cache/ftccache.h b/vendor/freetype/src/cache/ftccache.h
index 850d2554b5..85d321c12c 100644
--- a/vendor/freetype/src/cache/ftccache.h
+++ b/vendor/freetype/src/cache/ftccache.h
@@ -4,7 +4,7 @@
  *
  *   FreeType internal cache interface (specification).
  *
- * Copyright (C) 2000-2023 by
+ * Copyright (C) 2000-2024 by
  * David Turner, Robert Wilhelm, and Werner Lemberg.
  *
  * This file is part of the FreeType project, and may only be used,
@@ -87,6 +87,10 @@ FT_BEGIN_HEADER
         ftc_get_top_node_for_hash( ( cache ), ( hash ) )
 #endif
 
+  FT_LOCAL( void )
+  ftc_node_destroy( FTC_Node     node,
+                    FTC_Manager  manager );
+
 
   /*************************************************************************/
   /*************************************************************************/
diff --git a/vendor/freetype/src/cache/ftccback.h b/vendor/freetype/src/cache/ftccback.h
index 5f9db213a8..a1d76baa74 100644
--- a/vendor/freetype/src/cache/ftccback.h
+++ b/vendor/freetype/src/cache/ftccback.h
@@ -4,7 +4,7 @@
  *
  *   Callback functions of the caching sub-system (specification only).
  *
- * Copyright (C) 2004-2023 by
+ * Copyright (C) 2004-2024 by
  * David Turner, Robert Wilhelm, and Werner Lemberg.
  *
  * This file is part of the FreeType project, and may only be used,
@@ -19,11 +19,7 @@
 #define FTCCBACK_H_
 
 #include 
-#include "ftcmru.h"
-#include "ftcimage.h"
-#include "ftcmanag.h"
-#include "ftcglyph.h"
-#include "ftcsbits.h"
+#include "ftccache.h"
 
 FT_BEGIN_HEADER
 
@@ -81,10 +77,6 @@ FT_BEGIN_HEADER
   FT_LOCAL( void )
   ftc_cache_done( FTC_Cache  cache );
 
-  FT_LOCAL( void )
-  ftc_node_destroy( FTC_Node     node,
-                    FTC_Manager  manager );
-
 FT_END_HEADER
 
 #endif /* FTCCBACK_H_ */
diff --git a/vendor/freetype/src/cache/ftccmap.c b/vendor/freetype/src/cache/ftccmap.c
index 84f22a6675..b5c61e8160 100644
--- a/vendor/freetype/src/cache/ftccmap.c
+++ b/vendor/freetype/src/cache/ftccmap.c
@@ -4,7 +4,7 @@
  *
  *   FreeType CharMap cache (body)
  *
- * Copyright (C) 2000-2023 by
+ * Copyright (C) 2000-2024 by
  * David Turner, Robert Wilhelm, and Werner Lemberg.
  *
  * This file is part of the FreeType project, and may only be used,
@@ -264,7 +264,7 @@
 
     hash = FTC_CMAP_HASH( face_id, (FT_UInt)cmap_index, char_code );
 
-#if 1
+#ifdef FTC_INLINE
     FTC_CACHE_LOOKUP_CMP( cache, ftc_cmap_node_compare, hash, &query,
                           node, error );
 #else
diff --git a/vendor/freetype/src/cache/ftcerror.h b/vendor/freetype/src/cache/ftcerror.h
index dc1a62013d..daabcc6121 100644
--- a/vendor/freetype/src/cache/ftcerror.h
+++ b/vendor/freetype/src/cache/ftcerror.h
@@ -4,7 +4,7 @@
  *
  *   Caching sub-system error codes (specification only).
  *
- * Copyright (C) 2001-2023 by
+ * Copyright (C) 2001-2024 by
  * David Turner, Robert Wilhelm, and Werner Lemberg.
  *
  * This file is part of the FreeType project, and may only be used,
diff --git a/vendor/freetype/src/cache/ftcglyph.c b/vendor/freetype/src/cache/ftcglyph.c
index d344733f37..5e7856378a 100644
--- a/vendor/freetype/src/cache/ftcglyph.c
+++ b/vendor/freetype/src/cache/ftcglyph.c
@@ -4,7 +4,7 @@
  *
  *   FreeType Glyph Image (FT_Glyph) cache (body).
  *
- * Copyright (C) 2000-2023 by
+ * Copyright (C) 2000-2024 by
  * David Turner, Robert Wilhelm, and Werner Lemberg.
  *
  * This file is part of the FreeType project, and may only be used,
@@ -180,7 +180,7 @@
 
     query->gindex = gindex;
 
-    FTC_MRULIST_LOOKUP( &cache->families, query, query->family, error );
+    FTC_MRULIST_LOOKUP( &gcache->families, query, query->family, error );
     if ( !error )
     {
       FTC_Family  family = query->family;
@@ -193,7 +193,7 @@
       error = FTC_Cache_Lookup( FTC_CACHE( gcache ), hash, query, anode );
 
       if ( --family->num_nodes == 0 )
-        FTC_FAMILY_FREE( family, cache );
+        FTC_FAMILY_FREE( family, FTC_CACHE( gcache ) );
     }
     return error;
   }
diff --git a/vendor/freetype/src/cache/ftcglyph.h b/vendor/freetype/src/cache/ftcglyph.h
index 0181e98166..b1a96da8ec 100644
--- a/vendor/freetype/src/cache/ftcglyph.h
+++ b/vendor/freetype/src/cache/ftcglyph.h
@@ -4,7 +4,7 @@
  *
  *   FreeType abstract glyph cache (specification).
  *
- * Copyright (C) 2000-2023 by
+ * Copyright (C) 2000-2024 by
  * David Turner, Robert Wilhelm, and Werner Lemberg.
  *
  * This file is part of the FreeType project, and may only be used,
@@ -65,7 +65,6 @@
    * - FTC_Family sub-class, e.g. MyFamily, with relevant methods:
    *     my_family_compare
    *     my_family_init
-   *     my_family_reset (optional)
    *     my_family_done
    *
    * - FTC_GQuery sub-class, e.g. MyQuery, to hold cache-specific query
diff --git a/vendor/freetype/src/cache/ftcimage.c b/vendor/freetype/src/cache/ftcimage.c
index 428e5e1a71..1463064050 100644
--- a/vendor/freetype/src/cache/ftcimage.c
+++ b/vendor/freetype/src/cache/ftcimage.c
@@ -4,7 +4,7 @@
  *
  *   FreeType Image cache (body).
  *
- * Copyright (C) 2000-2023 by
+ * Copyright (C) 2000-2024 by
  * David Turner, Robert Wilhelm, and Werner Lemberg.
  *
  * This file is part of the FreeType project, and may only be used,
@@ -34,11 +34,7 @@
     FT_Memory  memory = cache->memory;
 
 
-    if ( inode->glyph )
-    {
-      FT_Done_Glyph( inode->glyph );
-      inode->glyph = NULL;
-    }
+    FT_Done_Glyph( inode->glyph );
 
     FTC_GNode_Done( FTC_GNODE( inode ), cache );
     FT_FREE( inode );
@@ -119,10 +115,9 @@
     {
     case FT_GLYPH_FORMAT_BITMAP:
       {
-        FT_BitmapGlyph  bitg;
+        FT_BitmapGlyph  bitg = (FT_BitmapGlyph)glyph;
 
 
-        bitg = (FT_BitmapGlyph)glyph;
         size = bitg->bitmap.rows * (FT_Offset)FT_ABS( bitg->bitmap.pitch ) +
                sizeof ( *bitg );
       }
@@ -130,10 +125,9 @@
 
     case FT_GLYPH_FORMAT_OUTLINE:
       {
-        FT_OutlineGlyph  outg;
+        FT_OutlineGlyph  outg = (FT_OutlineGlyph)glyph;
 
 
-        outg = (FT_OutlineGlyph)glyph;
         size = (FT_Offset)outg->outline.n_points *
                  ( sizeof ( FT_Vector ) + sizeof ( FT_Byte ) ) +
                (FT_Offset)outg->outline.n_contours * sizeof ( FT_Short ) +
diff --git a/vendor/freetype/src/cache/ftcimage.h b/vendor/freetype/src/cache/ftcimage.h
index d2a807f158..a0c4a97259 100644
--- a/vendor/freetype/src/cache/ftcimage.h
+++ b/vendor/freetype/src/cache/ftcimage.h
@@ -4,7 +4,7 @@
  *
  *   FreeType Generic Image cache (specification)
  *
- * Copyright (C) 2000-2023 by
+ * Copyright (C) 2000-2024 by
  * David Turner, Robert Wilhelm, and Werner Lemberg.
  *
  * This file is part of the FreeType project, and may only be used,
diff --git a/vendor/freetype/src/cache/ftcmanag.c b/vendor/freetype/src/cache/ftcmanag.c
index 94f8469c92..c0a48a53b7 100644
--- a/vendor/freetype/src/cache/ftcmanag.c
+++ b/vendor/freetype/src/cache/ftcmanag.c
@@ -4,7 +4,7 @@
  *
  *   FreeType Cache Manager (body).
  *
- * Copyright (C) 2000-2023 by
+ * Copyright (C) 2000-2024 by
  * David Turner, Robert Wilhelm, and Werner Lemberg.
  *
  * This file is part of the FreeType project, and may only be used,
@@ -22,7 +22,6 @@
 #include 
 #include 
 
-#include "ftccback.h"
 #include "ftcerror.h"
 
 
@@ -86,12 +85,10 @@
                       FT_Pointer   data )
   {
     FTC_SizeNode  node = (FTC_SizeNode)ftcnode;
-    FT_Size       size = node->size;
     FT_UNUSED( data );
 
 
-    if ( size )
-      FT_Done_Size( size );
+    FT_Done_Size( node->size );
   }
 
 
@@ -118,32 +115,21 @@
                       FT_Pointer   ftcscaler,
                       FT_Pointer   ftcmanager )
   {
+    FT_Error      error;
+    FT_Size       size;
     FTC_SizeNode  node    = (FTC_SizeNode)ftcnode;
     FTC_Scaler    scaler  = (FTC_Scaler)ftcscaler;
     FTC_Manager   manager = (FTC_Manager)ftcmanager;
 
 
-    node->scaler = scaler[0];
-
-    return ftc_scaler_lookup_size( manager, scaler, &node->size );
-  }
-
-
-  FT_CALLBACK_DEF( FT_Error )
-  ftc_size_node_reset( FTC_MruNode  ftcnode,
-                       FT_Pointer   ftcscaler,
-                       FT_Pointer   ftcmanager )
-  {
-    FTC_SizeNode  node    = (FTC_SizeNode)ftcnode;
-    FTC_Scaler    scaler  = (FTC_Scaler)ftcscaler;
-    FTC_Manager   manager = (FTC_Manager)ftcmanager;
-
-
-    FT_Done_Size( node->size );
-
-    node->scaler = scaler[0];
+    error = ftc_scaler_lookup_size( manager, scaler, &size );
+    if ( !error )
+    {
+      node->size   = size;
+      node->scaler = scaler[0];
+    }
 
-    return ftc_scaler_lookup_size( manager, scaler, &node->size );
+    return error;
   }
 
 
@@ -154,7 +140,6 @@
 
     ftc_size_node_compare,  /* FTC_MruNode_CompareFunc  node_compare */
     ftc_size_node_init,     /* FTC_MruNode_InitFunc     node_init    */
-    ftc_size_node_reset,    /* FTC_MruNode_ResetFunc    node_reset   */
     ftc_size_node_done      /* FTC_MruNode_DoneFunc     node_done    */
   };
 
@@ -231,23 +216,25 @@
                       FT_Pointer   ftcface_id,
                       FT_Pointer   ftcmanager )
   {
+    FT_Error      error;
+    FT_Face       face;
     FTC_FaceNode  node    = (FTC_FaceNode)ftcnode;
     FTC_FaceID    face_id = (FTC_FaceID)ftcface_id;
     FTC_Manager   manager = (FTC_Manager)ftcmanager;
-    FT_Error      error;
-
 
-    node->face_id = face_id;
 
     error = manager->request_face( face_id,
                                    manager->library,
                                    manager->request_data,
-                                   &node->face );
+                                   &face );
     if ( !error )
     {
       /* destroy initial size object; it will be re-created later */
-      if ( node->face->size )
-        FT_Done_Size( node->face->size );
+      if ( face->size )
+        FT_Done_Size( face->size );
+
+      node->face    = face;
+      node->face_id = face_id;
     }
 
     return error;
@@ -294,7 +281,6 @@
 
     ftc_face_node_compare,  /* FTC_MruNode_CompareFunc  node_compare */
     ftc_face_node_init,     /* FTC_MruNode_InitFunc     node_init    */
-    NULL,                   /* FTC_MruNode_ResetFunc    node_reset   */
     ftc_face_node_done      /* FTC_MruNode_DoneFunc     node_done    */
   };
 
@@ -435,18 +421,13 @@
       {
         cache->clazz.cache_done( cache );
         FT_FREE( cache );
-        manager->caches[idx] = NULL;
       }
     }
-    manager->num_caches = 0;
 
     /* discard faces and sizes */
     FTC_MruList_Done( &manager->sizes );
     FTC_MruList_Done( &manager->faces );
 
-    manager->library = NULL;
-    manager->memory  = NULL;
-
     FT_FREE( manager );
   }
 
diff --git a/vendor/freetype/src/cache/ftcmanag.h b/vendor/freetype/src/cache/ftcmanag.h
index 5b30929c9a..bd158f5ffb 100644
--- a/vendor/freetype/src/cache/ftcmanag.h
+++ b/vendor/freetype/src/cache/ftcmanag.h
@@ -4,7 +4,7 @@
  *
  *   FreeType Cache Manager (specification).
  *
- * Copyright (C) 2000-2023 by
+ * Copyright (C) 2000-2024 by
  * David Turner, Robert Wilhelm, and Werner Lemberg.
  *
  * This file is part of the FreeType project, and may only be used,
diff --git a/vendor/freetype/src/cache/ftcmru.c b/vendor/freetype/src/cache/ftcmru.c
index ad10a06bc4..f908eb25a6 100644
--- a/vendor/freetype/src/cache/ftcmru.c
+++ b/vendor/freetype/src/cache/ftcmru.c
@@ -4,7 +4,7 @@
  *
  *   FreeType MRU support (body).
  *
- * Copyright (C) 2003-2023 by
+ * Copyright (C) 2003-2024 by
  * David Turner, Robert Wilhelm, and Werner Lemberg.
  *
  * This file is part of the FreeType project, and may only be used,
@@ -238,52 +238,43 @@
   {
     FT_Error     error;
     FTC_MruNode  node   = NULL;
+    FTC_MruNode  prev   = NULL;
     FT_Memory    memory = list->memory;
 
 
-    if ( list->num_nodes >= list->max_nodes && list->max_nodes > 0 )
-    {
-      node = list->nodes->prev;
-
-      FT_ASSERT( node );
-
-      if ( list->clazz.node_reset )
-      {
-        FTC_MruNode_Up( &list->nodes, node );
-
-        error = list->clazz.node_reset( node, key, list->data );
-        if ( !error )
-          goto Exit;
-      }
-
-      FTC_MruNode_Remove( &list->nodes, node );
-      list->num_nodes--;
-
-      if ( list->clazz.node_done )
-        list->clazz.node_done( node, list->data );
-    }
-
     /* zero new node in case of node_init failure */
-    else if ( FT_ALLOC( node, list->clazz.node_size ) )
+    if ( FT_ALLOC( node, list->clazz.node_size ) )
       goto Exit;
 
     error = list->clazz.node_init( node, key, list->data );
     if ( error )
-      goto Fail;
+    {
+      prev = node;
+      node = NULL;
+
+      goto Clean;
+    }
+    else if ( list->max_nodes > 0 && list->num_nodes >= list->max_nodes )
+      prev = list->nodes->prev;
 
     FTC_MruNode_Prepend( &list->nodes, node );
     list->num_nodes++;
 
-  Exit:
-    *anode = node;
-    return error;
+    if ( !prev )
+      goto Exit;
 
-  Fail:
+    FTC_MruNode_Remove( &list->nodes, prev );
+    list->num_nodes--;
+
+  Clean:
     if ( list->clazz.node_done )
-      list->clazz.node_done( node, list->data );
+      list->clazz.node_done( prev, list->data );
 
-    FT_FREE( node );
-    goto Exit;
+    FT_FREE( prev );
+
+  Exit:
+    *anode = node;
+    return error;
   }
 
 
@@ -309,18 +300,16 @@
   FTC_MruList_Remove( FTC_MruList  list,
                       FTC_MruNode  node )
   {
-    FTC_MruNode_Remove( &list->nodes, node );
-    list->num_nodes--;
+    FT_Memory  memory = list->memory;
 
-    {
-      FT_Memory  memory = list->memory;
 
+    FTC_MruNode_Remove( &list->nodes, node );
+    list->num_nodes--;
 
-      if ( list->clazz.node_done )
-        list->clazz.node_done( node, list->data );
+    if ( list->clazz.node_done )
+      list->clazz.node_done( node, list->data );
 
-      FT_FREE( node );
-    }
+    FT_FREE( node );
   }
 
 
diff --git a/vendor/freetype/src/cache/ftcmru.h b/vendor/freetype/src/cache/ftcmru.h
index 45e5249ca4..68faab9847 100644
--- a/vendor/freetype/src/cache/ftcmru.h
+++ b/vendor/freetype/src/cache/ftcmru.h
@@ -4,7 +4,7 @@
  *
  *   Simple MRU list-cache (specification).
  *
- * Copyright (C) 2000-2023 by
+ * Copyright (C) 2000-2024 by
  * David Turner, Robert Wilhelm, and Werner Lemberg.
  *
  * This file is part of the FreeType project, and may only be used,
@@ -95,11 +95,6 @@ FT_BEGIN_HEADER
                            FT_Pointer   key,
                            FT_Pointer   data );
 
-  typedef FT_Error
-  (*FTC_MruNode_ResetFunc)( FTC_MruNode  node,
-                            FT_Pointer   key,
-                            FT_Pointer   data );
-
   typedef void
   (*FTC_MruNode_DoneFunc)( FTC_MruNode  node,
                            FT_Pointer   data );
@@ -111,7 +106,6 @@ FT_BEGIN_HEADER
 
     FTC_MruNode_CompareFunc  node_compare;
     FTC_MruNode_InitFunc     node_init;
-    FTC_MruNode_ResetFunc    node_reset;
     FTC_MruNode_DoneFunc     node_done;
 
   } FTC_MruListClassRec;
diff --git a/vendor/freetype/src/cache/ftcsbits.c b/vendor/freetype/src/cache/ftcsbits.c
index 9929a0bcc3..19f3ef04d6 100644
--- a/vendor/freetype/src/cache/ftcsbits.c
+++ b/vendor/freetype/src/cache/ftcsbits.c
@@ -4,7 +4,7 @@
  *
  *   FreeType sbits manager (body).
  *
- * Copyright (C) 2000-2023 by
+ * Copyright (C) 2000-2024 by
  * David Turner, Robert Wilhelm, and Werner Lemberg.
  *
  * This file is part of the FreeType project, and may only be used,
@@ -53,8 +53,7 @@
 
     size = (FT_ULong)pitch * bitmap->rows;
 
-    if ( !FT_QALLOC( sbit->buffer, size ) )
-      FT_MEM_COPY( sbit->buffer, bitmap->buffer, size );
+    FT_MEM_DUP( sbit->buffer, bitmap->buffer, size );
 
     return error;
   }
diff --git a/vendor/freetype/src/cache/ftcsbits.h b/vendor/freetype/src/cache/ftcsbits.h
index e833cb5c30..d7c4a36475 100644
--- a/vendor/freetype/src/cache/ftcsbits.h
+++ b/vendor/freetype/src/cache/ftcsbits.h
@@ -4,7 +4,7 @@
  *
  *   A small-bitmap cache (specification).
  *
- * Copyright (C) 2000-2023 by
+ * Copyright (C) 2000-2024 by
  * David Turner, Robert Wilhelm, and Werner Lemberg.
  *
  * This file is part of the FreeType project, and may only be used,
diff --git a/vendor/freetype/src/cff/cff.c b/vendor/freetype/src/cff/cff.c
index b486c389e1..e3e009699d 100644
--- a/vendor/freetype/src/cff/cff.c
+++ b/vendor/freetype/src/cff/cff.c
@@ -4,7 +4,7 @@
  *
  *   FreeType OpenType driver component (body only).
  *
- * Copyright (C) 1996-2023 by
+ * Copyright (C) 1996-2024 by
  * David Turner, Robert Wilhelm, and Werner Lemberg.
  *
  * This file is part of the FreeType project, and may only be used,
diff --git a/vendor/freetype/src/cff/cffcmap.c b/vendor/freetype/src/cff/cffcmap.c
index 10d287bc81..ea5f8ed288 100644
--- a/vendor/freetype/src/cff/cffcmap.c
+++ b/vendor/freetype/src/cff/cffcmap.c
@@ -4,7 +4,7 @@
  *
  *   CFF character mapping table (cmap) support (body).
  *
- * Copyright (C) 2002-2023 by
+ * Copyright (C) 2002-2024 by
  * David Turner, Robert Wilhelm, and Werner Lemberg.
  *
  * This file is part of the FreeType project, and may only be used,
diff --git a/vendor/freetype/src/cff/cffcmap.h b/vendor/freetype/src/cff/cffcmap.h
index b2afc2fab6..1dd8700cd8 100644
--- a/vendor/freetype/src/cff/cffcmap.h
+++ b/vendor/freetype/src/cff/cffcmap.h
@@ -4,7 +4,7 @@
  *
  *   CFF character mapping table (cmap) support (specification).
  *
- * Copyright (C) 2002-2023 by
+ * Copyright (C) 2002-2024 by
  * David Turner, Robert Wilhelm, and Werner Lemberg.
  *
  * This file is part of the FreeType project, and may only be used,
diff --git a/vendor/freetype/src/cff/cffdrivr.c b/vendor/freetype/src/cff/cffdrivr.c
index 9898d625ca..f6ebdb3810 100644
--- a/vendor/freetype/src/cff/cffdrivr.c
+++ b/vendor/freetype/src/cff/cffdrivr.c
@@ -4,7 +4,7 @@
  *
  *   OpenType font driver implementation (body).
  *
- * Copyright (C) 1996-2023 by
+ * Copyright (C) 1996-2024 by
  * David Turner, Robert Wilhelm, Werner Lemberg, and Dominik Röttsches.
  *
  * This file is part of the FreeType project, and may only be used,
diff --git a/vendor/freetype/src/cff/cffdrivr.h b/vendor/freetype/src/cff/cffdrivr.h
index ab1f147bb2..fd5bc37ecd 100644
--- a/vendor/freetype/src/cff/cffdrivr.h
+++ b/vendor/freetype/src/cff/cffdrivr.h
@@ -4,7 +4,7 @@
  *
  *   High-level OpenType driver interface (specification).
  *
- * Copyright (C) 1996-2023 by
+ * Copyright (C) 1996-2024 by
  * David Turner, Robert Wilhelm, and Werner Lemberg.
  *
  * This file is part of the FreeType project, and may only be used,
diff --git a/vendor/freetype/src/cff/cfferrs.h b/vendor/freetype/src/cff/cfferrs.h
index bc9a3043fc..128adc3b71 100644
--- a/vendor/freetype/src/cff/cfferrs.h
+++ b/vendor/freetype/src/cff/cfferrs.h
@@ -4,7 +4,7 @@
  *
  *   CFF error codes (specification only).
  *
- * Copyright (C) 2001-2023 by
+ * Copyright (C) 2001-2024 by
  * David Turner, Robert Wilhelm, and Werner Lemberg.
  *
  * This file is part of the FreeType project, and may only be used,
diff --git a/vendor/freetype/src/cff/cffgload.c b/vendor/freetype/src/cff/cffgload.c
index c483d1d1a5..cbb071abdf 100644
--- a/vendor/freetype/src/cff/cffgload.c
+++ b/vendor/freetype/src/cff/cffgload.c
@@ -4,7 +4,7 @@
  *
  *   OpenType Glyph Loader (body).
  *
- * Copyright (C) 1996-2023 by
+ * Copyright (C) 1996-2024 by
  * David Turner, Robert Wilhelm, and Werner Lemberg.
  *
  * This file is part of the FreeType project, and may only be used,
diff --git a/vendor/freetype/src/cff/cffgload.h b/vendor/freetype/src/cff/cffgload.h
index 3b8cf236dd..346d4b11c3 100644
--- a/vendor/freetype/src/cff/cffgload.h
+++ b/vendor/freetype/src/cff/cffgload.h
@@ -4,7 +4,7 @@
  *
  *   OpenType Glyph Loader (specification).
  *
- * Copyright (C) 1996-2023 by
+ * Copyright (C) 1996-2024 by
  * David Turner, Robert Wilhelm, and Werner Lemberg.
  *
  * This file is part of the FreeType project, and may only be used,
diff --git a/vendor/freetype/src/cff/cffload.c b/vendor/freetype/src/cff/cffload.c
index af79082e98..979fd45f6c 100644
--- a/vendor/freetype/src/cff/cffload.c
+++ b/vendor/freetype/src/cff/cffload.c
@@ -4,7 +4,7 @@
  *
  *   OpenType and CFF data/program tables loader (body).
  *
- * Copyright (C) 1996-2023 by
+ * Copyright (C) 1996-2024 by
  * David Turner, Robert Wilhelm, and Werner Lemberg.
  *
  * This file is part of the FreeType project, and may only be used,
@@ -1202,17 +1202,21 @@
         {
           CFF_AxisCoords*  axis = ®ion->axisList[j];
 
-          FT_Int16  start14, peak14, end14;
+          FT_Int  start, peak, end;
 
 
-          if ( FT_READ_SHORT( start14 ) ||
-               FT_READ_SHORT( peak14 )  ||
-               FT_READ_SHORT( end14 )   )
+          if ( FT_READ_SHORT( start ) ||
+               FT_READ_SHORT( peak )  ||
+               FT_READ_SHORT( end )   )
             goto Exit;
 
-          axis->startCoord = FT_fdot14ToFixed( start14 );
-          axis->peakCoord  = FT_fdot14ToFixed( peak14 );
-          axis->endCoord   = FT_fdot14ToFixed( end14 );
+          /* immediately tag invalid ranges with special peak = 0 */
+          if ( ( start < 0 && end > 0 ) || start > peak || peak > end )
+            peak = 0;
+
+          axis->startCoord = FT_fdot14ToFixed( start );
+          axis->peakCoord  = FT_fdot14ToFixed( peak );
+          axis->endCoord   = FT_fdot14ToFixed( end );
         }
       }
 
@@ -1379,10 +1383,10 @@
       /* opcode in both CFF and CFF2 DICTs.  See `cff_parse_num' for    */
       /* decode of this, which rounds to an integer.                    */
       *subFont->blend_top++ = 255;
-      *subFont->blend_top++ = (FT_Byte)( sum >> 24 );
-      *subFont->blend_top++ = (FT_Byte)( sum >> 16 );
-      *subFont->blend_top++ = (FT_Byte)( sum >>  8 );
-      *subFont->blend_top++ = (FT_Byte)sum;
+      *subFont->blend_top++ = (FT_Byte)( (FT_UInt32)sum >> 24 );
+      *subFont->blend_top++ = (FT_Byte)( (FT_UInt32)sum >> 16 );
+      *subFont->blend_top++ = (FT_Byte)( (FT_UInt32)sum >>  8 );
+      *subFont->blend_top++ = (FT_Byte)( (FT_UInt32)sum );
     }
 
     /* leave only numBlends results on parser stack */
@@ -1495,44 +1499,31 @@
       for ( j = 0; j < lenNDV; j++ )
       {
         CFF_AxisCoords*  axis = &varRegion->axisList[j];
-        FT_Fixed         axisScalar;
-
-
-        /* compute the scalar contribution of this axis; */
-        /* ignore invalid ranges                         */
-        if ( axis->startCoord > axis->peakCoord ||
-             axis->peakCoord > axis->endCoord   )
-          axisScalar = FT_FIXED_ONE;
 
-        else if ( axis->startCoord < 0 &&
-                  axis->endCoord > 0   &&
-                  axis->peakCoord != 0 )
-          axisScalar = FT_FIXED_ONE;
 
-        /* peak of 0 means ignore this axis */
-        else if ( axis->peakCoord == 0 )
-          axisScalar = FT_FIXED_ONE;
+        /* compute the scalar contribution of this axis */
+        /* with peak of 0 used for invalid axes         */
+        if ( axis->peakCoord == NDV[j] ||
+             axis->peakCoord == 0      )
+          continue;
 
         /* ignore this region if coords are out of range */
-        else if ( NDV[j] < axis->startCoord ||
-                  NDV[j] > axis->endCoord   )
-          axisScalar = 0;
-
-        /* calculate a proportional factor */
-        else
+        else if ( NDV[j] <= axis->startCoord ||
+                  NDV[j] >= axis->endCoord   )
         {
-          if ( NDV[j] == axis->peakCoord )
-            axisScalar = FT_FIXED_ONE;
-          else if ( NDV[j] < axis->peakCoord )
-            axisScalar = FT_DivFix( NDV[j] - axis->startCoord,
-                                    axis->peakCoord - axis->startCoord );
-          else
-            axisScalar = FT_DivFix( axis->endCoord - NDV[j],
-                                    axis->endCoord - axis->peakCoord );
+          blend->BV[master] = 0;
+          break;
         }
 
-        /* take product of all the axis scalars */
-        blend->BV[master] = FT_MulFix( blend->BV[master], axisScalar );
+        /* adjust proportionally */
+        else if ( NDV[j] < axis->peakCoord )
+          blend->BV[master] = FT_MulDiv( blend->BV[master],
+                                         NDV[j] - axis->startCoord,
+                                         axis->peakCoord - axis->startCoord );
+        else   /* NDV[j] > axis->peakCoord ) */
+          blend->BV[master] = FT_MulDiv( blend->BV[master],
+                                         axis->endCoord - NDV[j],
+                                         axis->endCoord - axis->peakCoord );
       }
 
       FT_TRACE4(( ", %f ",
diff --git a/vendor/freetype/src/cff/cffload.h b/vendor/freetype/src/cff/cffload.h
index b5286b0c8c..0220924542 100644
--- a/vendor/freetype/src/cff/cffload.h
+++ b/vendor/freetype/src/cff/cffload.h
@@ -4,7 +4,7 @@
  *
  *   OpenType & CFF data/program tables loader (specification).
  *
- * Copyright (C) 1996-2023 by
+ * Copyright (C) 1996-2024 by
  * David Turner, Robert Wilhelm, and Werner Lemberg.
  *
  * This file is part of the FreeType project, and may only be used,
diff --git a/vendor/freetype/src/cff/cffobjs.c b/vendor/freetype/src/cff/cffobjs.c
index 6d08620c48..7c6713739a 100644
--- a/vendor/freetype/src/cff/cffobjs.c
+++ b/vendor/freetype/src/cff/cffobjs.c
@@ -4,7 +4,7 @@
  *
  *   OpenType objects manager (body).
  *
- * Copyright (C) 1996-2023 by
+ * Copyright (C) 1996-2024 by
  * David Turner, Robert Wilhelm, and Werner Lemberg.
  *
  * This file is part of the FreeType project, and may only be used,
@@ -42,6 +42,8 @@
 #include 
 #include 
 
+#define CFF_fixedToInt( x )                          \
+          ( (FT_Short)( ( (x) + 0x8000U ) >> 16 ) )
 
   /**************************************************************************
    *
@@ -124,19 +126,20 @@
 
     count = priv->num_blue_values = cpriv->num_blue_values;
     for ( n = 0; n < count; n++ )
-      priv->blue_values[n] = (FT_Short)cpriv->blue_values[n];
+      priv->blue_values[n] = CFF_fixedToInt( cpriv->blue_values[n] );
 
     count = priv->num_other_blues = cpriv->num_other_blues;
     for ( n = 0; n < count; n++ )
-      priv->other_blues[n] = (FT_Short)cpriv->other_blues[n];
+      priv->other_blues[n] = CFF_fixedToInt( cpriv->other_blues[n] );
 
     count = priv->num_family_blues = cpriv->num_family_blues;
     for ( n = 0; n < count; n++ )
-      priv->family_blues[n] = (FT_Short)cpriv->family_blues[n];
+      priv->family_blues[n] = CFF_fixedToInt( cpriv->family_blues[n] );
 
     count = priv->num_family_other_blues = cpriv->num_family_other_blues;
     for ( n = 0; n < count; n++ )
-      priv->family_other_blues[n] = (FT_Short)cpriv->family_other_blues[n];
+      priv->family_other_blues[n] =
+        CFF_fixedToInt( cpriv->family_other_blues[n] );
 
     priv->blue_scale = cpriv->blue_scale;
     priv->blue_shift = (FT_Int)cpriv->blue_shift;
@@ -421,32 +424,23 @@
   static void
   remove_subset_prefix( FT_String*  name )
   {
-    FT_Int32  idx             = 0;
-    FT_Int32  length          = (FT_Int32)ft_strlen( name ) + 1;
-    FT_Bool   continue_search = 1;
+    FT_UInt32  i = 0, idx = 0;
 
 
-    while ( continue_search )
+    /* six ASCII uppercase letters followed by a plus sign */
+    while ( 'A' <= name[i] && name[i++] <= 'Z' &&
+            'A' <= name[i] && name[i++] <= 'Z' &&
+            'A' <= name[i] && name[i++] <= 'Z' &&
+            'A' <= name[i] && name[i++] <= 'Z' &&
+            'A' <= name[i] && name[i++] <= 'Z' &&
+            'A' <= name[i] && name[i++] <= 'Z' &&
+                              name[i++] == '+' )
     {
-      if ( length >= 7 && name[6] == '+' )
-      {
-        for ( idx = 0; idx < 6; idx++ )
-        {
-          /* ASCII uppercase letters */
-          if ( !( 'A' <= name[idx] && name[idx] <= 'Z' ) )
-            continue_search = 0;
-        }
-
-        if ( continue_search )
-        {
-          for ( idx = 7; idx < length; idx++ )
-            name[idx - 7] = name[idx];
-          length -= 7;
-        }
-      }
-      else
-        continue_search = 0;
+      idx = i;
     }
+
+    if ( idx )
+      FT_MEM_MOVE( name, name + idx, ft_strlen( name + idx ) + 1 );
   }
 
 
@@ -456,42 +450,20 @@
   remove_style( FT_String*        family_name,
                 const FT_String*  style_name )
   {
-    FT_Int32  family_name_length, style_name_length;
+    FT_String*        f = family_name + ft_strlen( family_name );
+    const FT_String*  s =  style_name + ft_strlen(  style_name );
 
 
-    family_name_length = (FT_Int32)ft_strlen( family_name );
-    style_name_length  = (FT_Int32)ft_strlen( style_name );
+    /* compare strings moving backwards */
+    while ( s > style_name )
+      if ( f == family_name || *--s != *--f )
+        return;
 
-    if ( family_name_length > style_name_length )
-    {
-      FT_Int  idx;
-
-
-      for ( idx = 1; idx <= style_name_length; idx++ )
-      {
-        if ( family_name[family_name_length - idx] !=
-             style_name[style_name_length - idx] )
-          break;
-      }
-
-      if ( idx > style_name_length )
-      {
-        /* family_name ends with style_name; remove it */
-        idx = family_name_length - style_name_length - 1;
-
-        /* also remove special characters     */
-        /* between real family name and style */
-        while ( idx > 0                     &&
-                ( family_name[idx] == '-' ||
-                  family_name[idx] == ' ' ||
-                  family_name[idx] == '_' ||
-                  family_name[idx] == '+' ) )
-          idx--;
-
-        if ( idx > 0 )
-          family_name[idx + 1] = '\0';
-      }
-    }
+    /* terminate and remove special characters */
+    do
+      *f = '\0';
+    while ( f-- > family_name                                    &&
+            ( *f == '-' || *f == ' ' || *f == '_' || *f == '+' ) );
   }
 
 
@@ -722,8 +694,7 @@
         FT_UInt  instance_index = (FT_UInt)face_index >> 16;
 
 
-        if ( FT_HAS_MULTIPLE_MASTERS( cffface ) &&
-             instance_index > 0                 )
+        if ( FT_HAS_MULTIPLE_MASTERS( cffface ) )
         {
           error = FT_Set_Named_Instance( cffface, instance_index );
           if ( error )
diff --git a/vendor/freetype/src/cff/cffobjs.h b/vendor/freetype/src/cff/cffobjs.h
index 8f05f6132b..91ad83b1cd 100644
--- a/vendor/freetype/src/cff/cffobjs.h
+++ b/vendor/freetype/src/cff/cffobjs.h
@@ -4,7 +4,7 @@
  *
  *   OpenType objects manager (specification).
  *
- * Copyright (C) 1996-2023 by
+ * Copyright (C) 1996-2024 by
  * David Turner, Robert Wilhelm, and Werner Lemberg.
  *
  * This file is part of the FreeType project, and may only be used,
diff --git a/vendor/freetype/src/cff/cffparse.c b/vendor/freetype/src/cff/cffparse.c
index 3b076704cf..92a69c3b51 100644
--- a/vendor/freetype/src/cff/cffparse.c
+++ b/vendor/freetype/src/cff/cffparse.c
@@ -4,7 +4,7 @@
  *
  *   CFF token stream parser (body)
  *
- * Copyright (C) 1996-2023 by
+ * Copyright (C) 1996-2024 by
  * David Turner, Robert Wilhelm, and Werner Lemberg.
  *
  * This file is part of the FreeType project, and may only be used,
@@ -501,10 +501,10 @@
       return cff_parse_real( *d, parser->limit, scaling, NULL );
     else if ( **d == 255 )
     {
-      FT_Fixed val = ( ( ( (FT_UInt32)*( d[0] + 1 ) << 24 ) |
-                         ( (FT_UInt32)*( d[0] + 2 ) << 16 ) |
-                         ( (FT_UInt32)*( d[0] + 3 ) <<  8 ) |
-                           (FT_UInt32)*( d[0] + 4 )         ) );
+      FT_Fixed val = (FT_Int32)( ( ( (FT_UInt32)*( d[0] + 1 ) << 24 ) |
+                                   ( (FT_UInt32)*( d[0] + 2 ) << 16 ) |
+                                   ( (FT_UInt32)*( d[0] + 3 ) <<  8 ) |
+                                     (FT_UInt32)*( d[0] + 4 )         ) );
 
       if ( scaling )
       {
@@ -1031,10 +1031,14 @@
           CFF_FIELD( code, name, id, cff_kind_string )
 #define CFF_FIELD_BOOL( code, name, id )             \
           CFF_FIELD( code, name, id, cff_kind_bool )
+#define CFF_FIELD_DELTA( code, name, max, id )                        \
+          CFF_FIELD_DELTA_KIND( code, name, max, id, cff_kind_delta )
+#define CFF_FIELD_DELTA_FIXED( code, name, max, id )                        \
+          CFF_FIELD_DELTA_KIND( code, name, max, id, cff_kind_delta_fixed )
 
 
 #undef  CFF_FIELD
-#undef  CFF_FIELD_DELTA
+#undef  CFF_FIELD_DELTA_KIND
 
 
 #ifndef FT_DEBUG_LEVEL_TRACE
@@ -1064,18 +1068,18 @@
             code | CFFCODE,               \
             FT_FIELD_OFFSET( name ),      \
             FT_FIELD_SIZE( name ),        \
-            0, 0, 0                       \
+            NULL, 0, 0                    \
           },
 
-#define CFF_FIELD_DELTA( code, name, max, id ) \
-          {                                    \
-            cff_kind_delta,                    \
-            code | CFFCODE,                    \
-            FT_FIELD_OFFSET( name ),           \
-            FT_FIELD_SIZE_DELTA( name ),       \
-            0,                                 \
-            max,                               \
-            FT_FIELD_OFFSET( num_ ## name )    \
+#define CFF_FIELD_DELTA_KIND( code, name, max, id, kind ) \
+          {                                               \
+            kind,                                         \
+            code | CFFCODE,                               \
+            FT_FIELD_OFFSET( name ),                      \
+            FT_FIELD_SIZE_DELTA( name ),                  \
+            NULL,                                         \
+            max,                                          \
+            FT_FIELD_OFFSET( num_ ## name )               \
           },
 
   static const CFF_Field_Handler  cff_field_handlers[] =
@@ -1083,7 +1087,7 @@
 
 #include "cfftoken.h"
 
-    { 0, 0, 0, 0, 0, 0, 0 }
+    { 0, 0, 0, 0, NULL, 0, 0 }
   };
 
 
@@ -1117,20 +1121,20 @@
             code | CFFCODE,               \
             FT_FIELD_OFFSET( name ),      \
             FT_FIELD_SIZE( name ),        \
-            0, 0, 0,                      \
+            NULL, 0, 0,                   \
             id                            \
           },
 
-#define CFF_FIELD_DELTA( code, name, max, id ) \
-          {                                    \
-            cff_kind_delta,                    \
-            code | CFFCODE,                    \
-            FT_FIELD_OFFSET( name ),           \
-            FT_FIELD_SIZE_DELTA( name ),       \
-            0,                                 \
-            max,                               \
-            FT_FIELD_OFFSET( num_ ## name ),   \
-            id                                 \
+#define CFF_FIELD_DELTA_KIND( code, name, max, id, kind ) \
+          {                                               \
+            kind,                                         \
+            code | CFFCODE,                               \
+            FT_FIELD_OFFSET( name ),                      \
+            FT_FIELD_SIZE_DELTA( name ),                  \
+            NULL,                                         \
+            max,                                          \
+            FT_FIELD_OFFSET( num_ ## name ),              \
+            id                                            \
           },
 
   static const CFF_Field_Handler  cff_field_handlers[] =
@@ -1138,7 +1142,7 @@
 
 #include "cfftoken.h"
 
-    { 0, 0, 0, 0, 0, 0, 0, 0 }
+    { 0, 0, 0, 0, NULL, 0, 0, NULL }
   };
 
 
@@ -1356,7 +1360,8 @@
 
             /* check that we have enough arguments -- except for */
             /* delta encoded arrays, which can be empty          */
-            if ( field->kind != cff_kind_delta && num_args < 1 )
+            if ( field->kind != cff_kind_delta                       &&
+                 field->kind != cff_kind_delta_fixed && num_args < 1 )
               goto Stack_Underflow;
 
             switch ( field->kind )
@@ -1471,6 +1476,38 @@
               }
               break;
 
+            case cff_kind_delta_fixed:
+              {
+                FT_Byte*   qcount = (FT_Byte*)parser->object +
+                                      field->count_offset;
+
+                FT_Byte**  data = parser->stack;
+
+
+                if ( num_args > field->array_max )
+                  num_args = field->array_max;
+
+                FT_TRACE4(( " [" ));
+
+                /* store count */
+                *qcount = (FT_Byte)num_args;
+
+                val = 0;
+                while ( num_args > 0 )
+                {
+                  val = ADD_LONG( val, cff_parse_fixed( parser, data++ ) );
+                  *(FT_Long*)q = val;
+
+                  FT_TRACE4(( " %f\n", (double)val / 65536 ));
+
+                  q += field->size;
+                  num_args--;
+                }
+
+                FT_TRACE4(( "]\n" ));
+              }
+              break;
+
             default:  /* callback or blend */
               error = field->reader( parser );
               if ( error )
diff --git a/vendor/freetype/src/cff/cffparse.h b/vendor/freetype/src/cff/cffparse.h
index 418caacc68..ca6b18af6a 100644
--- a/vendor/freetype/src/cff/cffparse.h
+++ b/vendor/freetype/src/cff/cffparse.h
@@ -4,7 +4,7 @@
  *
  *   CFF token stream parser (specification)
  *
- * Copyright (C) 1996-2023 by
+ * Copyright (C) 1996-2024 by
  * David Turner, Robert Wilhelm, and Werner Lemberg.
  *
  * This file is part of the FreeType project, and may only be used,
@@ -107,6 +107,7 @@ FT_BEGIN_HEADER
     cff_kind_string,
     cff_kind_bool,
     cff_kind_delta,
+    cff_kind_delta_fixed,
     cff_kind_callback,
     cff_kind_blend,
 
diff --git a/vendor/freetype/src/cff/cfftoken.h b/vendor/freetype/src/cff/cfftoken.h
index b61cb0e66e..da45faa7f4 100644
--- a/vendor/freetype/src/cff/cfftoken.h
+++ b/vendor/freetype/src/cff/cfftoken.h
@@ -4,7 +4,7 @@
  *
  *   CFF token definitions (specification only).
  *
- * Copyright (C) 1996-2023 by
+ * Copyright (C) 1996-2024 by
  * David Turner, Robert Wilhelm, and Werner Lemberg.
  *
  * This file is part of the FreeType project, and may only be used,
@@ -80,26 +80,26 @@
 #undef  CFFCODE
 #define CFFCODE       CFF_CODE_PRIVATE
 
-  CFF_FIELD_DELTA     ( 6,     blue_values, 14,        "BlueValues" )
-  CFF_FIELD_DELTA     ( 7,     other_blues, 10,        "OtherBlues" )
-  CFF_FIELD_DELTA     ( 8,     family_blues, 14,       "FamilyBlues" )
-  CFF_FIELD_DELTA     ( 9,     family_other_blues, 10, "FamilyOtherBlues" )
-  CFF_FIELD_FIXED_1000( 0x109, blue_scale,             "BlueScale" )
-  CFF_FIELD_NUM       ( 0x10A, blue_shift,             "BlueShift" )
-  CFF_FIELD_NUM       ( 0x10B, blue_fuzz,              "BlueFuzz" )
-  CFF_FIELD_NUM       ( 10,    standard_width,         "StdHW" )
-  CFF_FIELD_NUM       ( 11,    standard_height,        "StdVW" )
-  CFF_FIELD_DELTA     ( 0x10C, snap_widths, 13,        "StemSnapH" )
-  CFF_FIELD_DELTA     ( 0x10D, snap_heights, 13,       "StemSnapV" )
-  CFF_FIELD_BOOL      ( 0x10E, force_bold,             "ForceBold" )
-  CFF_FIELD_FIXED     ( 0x10F, force_bold_threshold,   "ForceBoldThreshold" )
-  CFF_FIELD_NUM       ( 0x110, lenIV,                  "lenIV" )
-  CFF_FIELD_NUM       ( 0x111, language_group,         "LanguageGroup" )
-  CFF_FIELD_FIXED     ( 0x112, expansion_factor,       "ExpansionFactor" )
-  CFF_FIELD_NUM       ( 0x113, initial_random_seed,    "initialRandomSeed" )
-  CFF_FIELD_NUM       ( 19,    local_subrs_offset,     "Subrs" )
-  CFF_FIELD_NUM       ( 20,    default_width,          "defaultWidthX" )
-  CFF_FIELD_NUM       ( 21,    nominal_width,          "nominalWidthX" )
+  CFF_FIELD_DELTA_FIXED( 6,     blue_values, 14,        "BlueValues" )
+  CFF_FIELD_DELTA_FIXED( 7,     other_blues, 10,        "OtherBlues" )
+  CFF_FIELD_DELTA_FIXED( 8,     family_blues, 14,       "FamilyBlues" )
+  CFF_FIELD_DELTA_FIXED( 9,     family_other_blues, 10, "FamilyOtherBlues" )
+  CFF_FIELD_FIXED_1000 ( 0x109, blue_scale,             "BlueScale" )
+  CFF_FIELD_NUM        ( 0x10A, blue_shift,             "BlueShift" )
+  CFF_FIELD_NUM        ( 0x10B, blue_fuzz,              "BlueFuzz" )
+  CFF_FIELD_NUM        ( 10,    standard_width,         "StdHW" )
+  CFF_FIELD_NUM        ( 11,    standard_height,        "StdVW" )
+  CFF_FIELD_DELTA      ( 0x10C, snap_widths, 13,        "StemSnapH" )
+  CFF_FIELD_DELTA      ( 0x10D, snap_heights, 13,       "StemSnapV" )
+  CFF_FIELD_BOOL       ( 0x10E, force_bold,             "ForceBold" )
+  CFF_FIELD_FIXED      ( 0x10F, force_bold_threshold,   "ForceBoldThreshold" )
+  CFF_FIELD_NUM        ( 0x110, lenIV,                  "lenIV" )
+  CFF_FIELD_NUM        ( 0x111, language_group,         "LanguageGroup" )
+  CFF_FIELD_FIXED      ( 0x112, expansion_factor,       "ExpansionFactor" )
+  CFF_FIELD_NUM        ( 0x113, initial_random_seed,    "initialRandomSeed" )
+  CFF_FIELD_NUM        ( 19,    local_subrs_offset,     "Subrs" )
+  CFF_FIELD_NUM        ( 20,    default_width,          "defaultWidthX" )
+  CFF_FIELD_NUM        ( 21,    nominal_width,          "nominalWidthX" )
 
 
 #undef  FT_STRUCTURE
@@ -129,22 +129,22 @@
 #undef  CFFCODE
 #define CFFCODE       CFF2_CODE_PRIVATE
 
-  CFF_FIELD_DELTA     ( 6,     blue_values, 14,        "BlueValues" )
-  CFF_FIELD_DELTA     ( 7,     other_blues, 10,        "OtherBlues" )
-  CFF_FIELD_DELTA     ( 8,     family_blues, 14,       "FamilyBlues" )
-  CFF_FIELD_DELTA     ( 9,     family_other_blues, 10, "FamilyOtherBlues" )
-  CFF_FIELD_FIXED_1000( 0x109, blue_scale,             "BlueScale" )
-  CFF_FIELD_NUM       ( 0x10A, blue_shift,             "BlueShift" )
-  CFF_FIELD_NUM       ( 0x10B, blue_fuzz,              "BlueFuzz" )
-  CFF_FIELD_NUM       ( 10,    standard_width,         "StdHW" )
-  CFF_FIELD_NUM       ( 11,    standard_height,        "StdVW" )
-  CFF_FIELD_DELTA     ( 0x10C, snap_widths, 13,        "StemSnapH" )
-  CFF_FIELD_DELTA     ( 0x10D, snap_heights, 13,       "StemSnapV" )
-  CFF_FIELD_NUM       ( 0x111, language_group,         "LanguageGroup" )
-  CFF_FIELD_FIXED     ( 0x112, expansion_factor,       "ExpansionFactor" )
-  CFF_FIELD_CALLBACK  ( 22,    vsindex,                "vsindex" )
-  CFF_FIELD_BLEND     ( 23,                            "blend" )
-  CFF_FIELD_NUM       ( 19,    local_subrs_offset,     "Subrs" )
+  CFF_FIELD_DELTA_FIXED( 6,     blue_values, 14,        "BlueValues" )
+  CFF_FIELD_DELTA_FIXED( 7,     other_blues, 10,        "OtherBlues" )
+  CFF_FIELD_DELTA_FIXED( 8,     family_blues, 14,       "FamilyBlues" )
+  CFF_FIELD_DELTA_FIXED( 9,     family_other_blues, 10, "FamilyOtherBlues" )
+  CFF_FIELD_FIXED_1000 ( 0x109, blue_scale,             "BlueScale" )
+  CFF_FIELD_NUM        ( 0x10A, blue_shift,             "BlueShift" )
+  CFF_FIELD_NUM        ( 0x10B, blue_fuzz,              "BlueFuzz" )
+  CFF_FIELD_NUM        ( 10,    standard_width,         "StdHW" )
+  CFF_FIELD_NUM        ( 11,    standard_height,        "StdVW" )
+  CFF_FIELD_DELTA      ( 0x10C, snap_widths, 13,        "StemSnapH" )
+  CFF_FIELD_DELTA      ( 0x10D, snap_heights, 13,       "StemSnapV" )
+  CFF_FIELD_NUM        ( 0x111, language_group,         "LanguageGroup" )
+  CFF_FIELD_FIXED      ( 0x112, expansion_factor,       "ExpansionFactor" )
+  CFF_FIELD_CALLBACK   ( 22,    vsindex,                "vsindex" )
+  CFF_FIELD_BLEND      ( 23,                            "blend" )
+  CFF_FIELD_NUM        ( 19,    local_subrs_offset,     "Subrs" )
 
 
 /* END */
diff --git a/vendor/freetype/src/cid/ciderrs.h b/vendor/freetype/src/cid/ciderrs.h
index 40a1097d0a..c439a8c4a0 100644
--- a/vendor/freetype/src/cid/ciderrs.h
+++ b/vendor/freetype/src/cid/ciderrs.h
@@ -4,7 +4,7 @@
  *
  *   CID error codes (specification only).
  *
- * Copyright (C) 2001-2023 by
+ * Copyright (C) 2001-2024 by
  * David Turner, Robert Wilhelm, and Werner Lemberg.
  *
  * This file is part of the FreeType project, and may only be used,
diff --git a/vendor/freetype/src/cid/cidgload.c b/vendor/freetype/src/cid/cidgload.c
index eaca765ad0..7b571322d4 100644
--- a/vendor/freetype/src/cid/cidgload.c
+++ b/vendor/freetype/src/cid/cidgload.c
@@ -4,7 +4,7 @@
  *
  *   CID-keyed Type1 Glyph Loader (body).
  *
- * Copyright (C) 1996-2023 by
+ * Copyright (C) 1996-2024 by
  * David Turner, Robert Wilhelm, and Werner Lemberg.
  *
  * This file is part of the FreeType project, and may only be used,
diff --git a/vendor/freetype/src/cid/cidgload.h b/vendor/freetype/src/cid/cidgload.h
index edd6229234..9fdc9db589 100644
--- a/vendor/freetype/src/cid/cidgload.h
+++ b/vendor/freetype/src/cid/cidgload.h
@@ -4,7 +4,7 @@
  *
  *   OpenType Glyph Loader (specification).
  *
- * Copyright (C) 1996-2023 by
+ * Copyright (C) 1996-2024 by
  * David Turner, Robert Wilhelm, and Werner Lemberg.
  *
  * This file is part of the FreeType project, and may only be used,
diff --git a/vendor/freetype/src/cid/cidload.c b/vendor/freetype/src/cid/cidload.c
index a7da8ea39d..722f5a34dd 100644
--- a/vendor/freetype/src/cid/cidload.c
+++ b/vendor/freetype/src/cid/cidload.c
@@ -4,7 +4,7 @@
  *
  *   CID-keyed Type1 font loader (body).
  *
- * Copyright (C) 1996-2023 by
+ * Copyright (C) 1996-2024 by
  * David Turner, Robert Wilhelm, and Werner Lemberg.
  *
  * This file is part of the FreeType project, and may only be used,
@@ -388,7 +388,7 @@
     T1_FIELD_CALLBACK( "ExpansionFactor", parse_expansion_factor, 0 )
     T1_FIELD_CALLBACK( "FontName",        parse_font_name, 0 )
 
-    { 0, T1_FIELD_LOCATION_CID_INFO, T1_FIELD_TYPE_NONE, 0, 0, 0, 0, 0, 0 }
+    T1_FIELD_ZERO
   };
 
 
@@ -469,36 +469,23 @@
             T1_Field  keyword = (T1_Field)cid_field_records;
 
 
-            for (;;)
+            while ( keyword->len )
             {
-              FT_Byte*  name;
+              FT_Byte*  name = (FT_Byte*)keyword->ident;
 
 
-              name = (FT_Byte*)keyword->ident;
-              if ( !name )
-                break;
-
-              if ( cur[0] == name[0]                     &&
-                   len == ft_strlen( (const char*)name ) )
+              if ( keyword->len == len              &&
+                   ft_memcmp( cur, name, len ) == 0 )
               {
-                FT_UInt  n;
-
-
-                for ( n = 1; n < len; n++ )
-                  if ( cur[n] != name[n] )
-                    break;
-
-                if ( n >= len )
-                {
-                  /* we found it - run the parsing callback */
-                  parser->root.error = cid_load_keyword( face,
-                                                         loader,
-                                                         keyword );
-                  if ( parser->root.error )
-                    return parser->root.error;
-                  break;
-                }
+                /* we found it - run the parsing callback */
+                parser->root.error = cid_load_keyword( face,
+                                                       loader,
+                                                       keyword );
+                if ( parser->root.error )
+                  return parser->root.error;
+                break;
               }
+
               keyword++;
             }
           }
diff --git a/vendor/freetype/src/cid/cidload.h b/vendor/freetype/src/cid/cidload.h
index d12d2962a6..7f030b32df 100644
--- a/vendor/freetype/src/cid/cidload.h
+++ b/vendor/freetype/src/cid/cidload.h
@@ -4,7 +4,7 @@
  *
  *   CID-keyed Type1 font loader (specification).
  *
- * Copyright (C) 1996-2023 by
+ * Copyright (C) 1996-2024 by
  * David Turner, Robert Wilhelm, and Werner Lemberg.
  *
  * This file is part of the FreeType project, and may only be used,
diff --git a/vendor/freetype/src/cid/cidobjs.c b/vendor/freetype/src/cid/cidobjs.c
index f698a41928..8d337c4112 100644
--- a/vendor/freetype/src/cid/cidobjs.c
+++ b/vendor/freetype/src/cid/cidobjs.c
@@ -4,7 +4,7 @@
  *
  *   CID objects manager (body).
  *
- * Copyright (C) 1996-2023 by
+ * Copyright (C) 1996-2024 by
  * David Turner, Robert Wilhelm, and Werner Lemberg.
  *
  * This file is part of the FreeType project, and may only be used,
diff --git a/vendor/freetype/src/cid/cidobjs.h b/vendor/freetype/src/cid/cidobjs.h
index 83c0c61c3c..d371cbe995 100644
--- a/vendor/freetype/src/cid/cidobjs.h
+++ b/vendor/freetype/src/cid/cidobjs.h
@@ -4,7 +4,7 @@
  *
  *   CID objects manager (specification).
  *
- * Copyright (C) 1996-2023 by
+ * Copyright (C) 1996-2024 by
  * David Turner, Robert Wilhelm, and Werner Lemberg.
  *
  * This file is part of the FreeType project, and may only be used,
diff --git a/vendor/freetype/src/cid/cidparse.c b/vendor/freetype/src/cid/cidparse.c
index 171a886215..73a3ade893 100644
--- a/vendor/freetype/src/cid/cidparse.c
+++ b/vendor/freetype/src/cid/cidparse.c
@@ -4,7 +4,7 @@
  *
  *   CID-keyed Type1 parser (body).
  *
- * Copyright (C) 1996-2023 by
+ * Copyright (C) 1996-2024 by
  * David Turner, Robert Wilhelm, and Werner Lemberg.
  *
  * This file is part of the FreeType project, and may only be used,
@@ -90,10 +90,15 @@
     if ( error )
       goto Exit;
 
-  Again:
-    /* now, read the rest of the file until we find */
-    /* `StartData' or `/sfnts'                      */
+    if ( !stream->read ) {
+      /* just parse memory-based streams */
+      offset = stream->size;
+    }
+    else
     {
+      /* Find the last `StartData` or `/sfnts`.  The parser requires */
+      /* contiguous memory; attempt to pin as little as necessary.   */
+
       /*
        * The algorithm is as follows (omitting the case with less than 256
        * bytes to fill for simplicity).
@@ -119,7 +124,8 @@
       FT_Byte*  p           = buffer;
 
 
-      for ( offset = FT_STREAM_POS(); ; offset += 256 )
+      offset = 0;
+      while ( 1 )
       {
         FT_ULong  stream_len;
 
@@ -127,7 +133,7 @@
         stream_len = stream->size - FT_STREAM_POS();
 
         read_len = FT_MIN( read_len, stream_len );
-        if ( FT_STREAM_READ( p, read_len ) )
+        if ( read_len && FT_STREAM_READ( p, read_len ) )
           goto Exit;
 
         /* ensure that we do not compare with data beyond the buffer */
@@ -141,20 +147,23 @@
                ft_strncmp( (char*)p, STARTDATA, STARTDATA_LEN ) == 0 )
           {
             /* save offset of binary data after `StartData' */
-            offset += (FT_ULong)( p - buffer ) + STARTDATA_LEN + 1;
-            goto Found;
+            offset = FT_STREAM_POS() - read_len - read_offset
+                     + (FT_ULong)( p - buffer ) + STARTDATA_LEN + 1;
           }
           else if ( p[1] == 's'                                   &&
                     ft_strncmp( (char*)p, SFNTS, SFNTS_LEN ) == 0 )
           {
-            offset += (FT_ULong)( p - buffer ) + SFNTS_LEN + 1;
-            goto Found;
+            offset = FT_STREAM_POS() - read_len - read_offset
+                     + (FT_ULong)( p - buffer ) + SFNTS_LEN + 1;
           }
         }
 
-        if ( read_offset + read_len < STARTDATA_LEN )
+        if ( read_offset + read_len <= STARTDATA_LEN )
         {
-          FT_TRACE2(( "cid_parser_new: no `StartData' keyword found\n" ));
+          if ( offset )
+            goto Found;
+
+          FT_TRACE2(( "cid_parser_new: no `StartData` keyword found\n" ));
           error = FT_THROW( Invalid_File_Format );
           goto Exit;
         }
@@ -171,9 +180,9 @@
     }
 
   Found:
-    /* We have found the start of the binary data or the `/sfnts' token. */
-    /* Now rewind and extract the frame corresponding to this PostScript */
-    /* section.                                                          */
+    /* We have found an efficient range to look for the binary data or    */
+    /* `/sfnts' token.  Now rewind and extract the frame corresponding to */
+    /* this PostScript section.                                           */
 
     ps_len = offset - base_offset;
     if ( FT_STREAM_SEEK( base_offset )                  ||
@@ -187,8 +196,8 @@
     parser->root.limit     = parser->root.cursor + ps_len;
     parser->num_dict       = FT_UINT_MAX;
 
-    /* Finally, we check whether `StartData' or `/sfnts' was real --  */
-    /* it could be in a comment or string.  We also get the arguments */
+    /* Find the first real `StartData' or `/sfnts' -- the last one    */
+    /* could be in a comment or string.  We also get the arguments    */
     /* of `StartData' to find out whether the data is represented in  */
     /* binary or hex format.                                          */
 
@@ -216,6 +225,7 @@
       {
         T1_TokenRec  type_token;
         FT_Long      binary_length;
+        FT_ULong     found_offset;
 
 
         parser->root.cursor = arg1;
@@ -234,6 +244,24 @@
             parser->binary_length = (FT_ULong)binary_length;
         }
 
+        /* set the real values for the parser, if different */
+        found_offset = (FT_ULong)( cur - parser->postscript )
+                       + STARTDATA_LEN + 1;
+        if ( found_offset != offset )
+        {
+          FT_FRAME_RELEASE( parser->postscript );
+
+          ps_len = found_offset - base_offset;
+          if ( FT_STREAM_SEEK( base_offset )                  ||
+               FT_FRAME_EXTRACT( ps_len, parser->postscript ) )
+            goto Exit;
+
+          parser->data_offset    = found_offset;
+          parser->postscript_len = ps_len;
+          parser->root.base      = parser->postscript;
+          parser->root.cursor    = parser->postscript;
+          parser->root.limit     = parser->root.cursor + ps_len;
+        }
         goto Exit;
       }
       else if ( cur[1] == 's'                                   &&
@@ -251,11 +279,8 @@
       cur  = parser->root.cursor;
     }
 
-    /* we haven't found the correct `StartData'; go back and continue */
-    /* searching                                                      */
-    FT_FRAME_RELEASE( parser->postscript );
-    if ( !FT_STREAM_SEEK( offset ) )
-      goto Again;
+    FT_TRACE2(( "cid_parser_new: no `StartData` token found\n" ));
+    error = FT_THROW( Invalid_File_Format );
 
   Exit:
     return error;
diff --git a/vendor/freetype/src/cid/cidparse.h b/vendor/freetype/src/cid/cidparse.h
index 2fd4e7a931..0f5baddcb9 100644
--- a/vendor/freetype/src/cid/cidparse.h
+++ b/vendor/freetype/src/cid/cidparse.h
@@ -4,7 +4,7 @@
  *
  *   CID-keyed Type1 parser (specification).
  *
- * Copyright (C) 1996-2023 by
+ * Copyright (C) 1996-2024 by
  * David Turner, Robert Wilhelm, and Werner Lemberg.
  *
  * This file is part of the FreeType project, and may only be used,
diff --git a/vendor/freetype/src/cid/cidriver.c b/vendor/freetype/src/cid/cidriver.c
index 99e7b11839..4be8a5c00d 100644
--- a/vendor/freetype/src/cid/cidriver.c
+++ b/vendor/freetype/src/cid/cidriver.c
@@ -4,7 +4,7 @@
  *
  *   CID driver interface (body).
  *
- * Copyright (C) 1996-2023 by
+ * Copyright (C) 1996-2024 by
  * David Turner, Robert Wilhelm, and Werner Lemberg.
  *
  * This file is part of the FreeType project, and may only be used,
diff --git a/vendor/freetype/src/cid/cidriver.h b/vendor/freetype/src/cid/cidriver.h
index a6249385c8..7ddce431c5 100644
--- a/vendor/freetype/src/cid/cidriver.h
+++ b/vendor/freetype/src/cid/cidriver.h
@@ -4,7 +4,7 @@
  *
  *   High-level CID driver interface (specification).
  *
- * Copyright (C) 1996-2023 by
+ * Copyright (C) 1996-2024 by
  * David Turner, Robert Wilhelm, and Werner Lemberg.
  *
  * This file is part of the FreeType project, and may only be used,
diff --git a/vendor/freetype/src/cid/cidtoken.h b/vendor/freetype/src/cid/cidtoken.h
index 925951acdb..160897d144 100644
--- a/vendor/freetype/src/cid/cidtoken.h
+++ b/vendor/freetype/src/cid/cidtoken.h
@@ -4,7 +4,7 @@
  *
  *   CID token definitions (specification only).
  *
- * Copyright (C) 1996-2023 by
+ * Copyright (C) 1996-2024 by
  * David Turner, Robert Wilhelm, and Werner Lemberg.
  *
  * This file is part of the FreeType project, and may only be used,
diff --git a/vendor/freetype/src/cid/type1cid.c b/vendor/freetype/src/cid/type1cid.c
index 905c896a31..890a3ac549 100644
--- a/vendor/freetype/src/cid/type1cid.c
+++ b/vendor/freetype/src/cid/type1cid.c
@@ -4,7 +4,7 @@
  *
  *   FreeType OpenType driver component (body only).
  *
- * Copyright (C) 1996-2023 by
+ * Copyright (C) 1996-2024 by
  * David Turner, Robert Wilhelm, and Werner Lemberg.
  *
  * This file is part of the FreeType project, and may only be used,
diff --git a/vendor/freetype/src/dlg/dlg.c b/vendor/freetype/src/dlg/dlg.c
deleted file mode 100644
index 0e6bc74b6c..0000000000
--- a/vendor/freetype/src/dlg/dlg.c
+++ /dev/null
@@ -1,803 +0,0 @@
-// Copyright (c) 2019 nyorain
-// Distributed under the Boost Software License, Version 1.0.
-// See accompanying file LICENSE or copy at http://www.boost.org/LICENSE_1_0.txt
-
-#define _XOPEN_SOURCE 600
-#define _POSIX_C_SOURCE 200809L
-#define _WIN32_WINNT 0x0600
-
-// Needed on windows so that we can use sprintf without warning.
-#define _CRT_SECURE_NO_WARNINGS
-
-#include 
-#include 
-#include 
-#include 
-#include 
-#include 
-#include 
-
-const char* const dlg_reset_sequence = "\033[0m";
-const struct dlg_style dlg_default_output_styles[] = {
-	{dlg_text_style_italic, dlg_color_green, dlg_color_none},
-	{dlg_text_style_dim, dlg_color_gray, dlg_color_none},
-	{dlg_text_style_none, dlg_color_cyan, dlg_color_none},
-	{dlg_text_style_none, dlg_color_yellow, dlg_color_none},
-	{dlg_text_style_none, dlg_color_red, dlg_color_none},
-	{dlg_text_style_bold, dlg_color_red, dlg_color_none}
-};
-
-static void* xalloc(size_t size) {
-	void* ret = calloc(size, 1);
-	if(!ret) fprintf(stderr, "dlg: calloc returned NULL, probably crashing (size: %zu)\n", size);
-	return ret;
-}
-
-static void* xrealloc(void* ptr, size_t size) {
-	void* ret = realloc(ptr, size);
-	if(!ret) fprintf(stderr, "dlg: realloc returned NULL, probably crashing (size: %zu)\n", size);
-	return ret;
-}
-
-struct dlg_tag_func_pair {
-	const char* tag;
-	const char* func;
-};
-
-struct dlg_data {
-	const char** tags; // vec
-	struct dlg_tag_func_pair* pairs; // vec
-	char* buffer;
-	size_t buffer_size;
-};
-
-static dlg_handler g_handler = dlg_default_output;
-static void* g_data = NULL;
-
-static void dlg_free_data(void* data);
-static struct dlg_data* dlg_create_data(void);
-
-// platform-specific
-#if defined(__unix__) || defined(__unix) || defined(__linux__) || defined(__APPLE__) || defined(__MACH__)
-	#define DLG_OS_UNIX
-	#include 
-	#include 
-	#include 
-
-	static pthread_key_t dlg_data_key;
-
-	static void dlg_main_cleanup(void) {
-		void* data = pthread_getspecific(dlg_data_key);
-		if(data) {
-			dlg_free_data(data);
-			pthread_setspecific(dlg_data_key, NULL);
-		}
-	}
-
-	static void init_data_key(void) {
-		pthread_key_create(&dlg_data_key, dlg_free_data);
-		atexit(dlg_main_cleanup);
-	}
-
-	static struct dlg_data* dlg_data(void) {
-		static pthread_once_t key_once = PTHREAD_ONCE_INIT;
-		pthread_once(&key_once, init_data_key);
-
-		void* data = pthread_getspecific(dlg_data_key);
-		if(!data) {
-			data = dlg_create_data();
-			pthread_setspecific(dlg_data_key, data);
-		}
-
-		return (struct dlg_data*) data;
-	}
-
-	static void lock_file(FILE* file) {
-		flockfile(file);
-	}
-
-	static void unlock_file(FILE* file) {
-		funlockfile(file);
-	}
-
-	bool dlg_is_tty(FILE* stream) {
-		return isatty(fileno(stream));
-	}
-
-	static unsigned get_msecs(void) {
-		struct timeval tv;
-		gettimeofday(&tv, NULL);
-		return tv.tv_usec;
-	}
-
-// platform switch -- end unix
-#elif defined(WIN32) || defined(_WIN32) || defined(_WIN64)
-	#define DLG_OS_WIN
-	#define WIN32_LEAN_AND_MEAN
-	#define DEFINE_CONSOLEV2_PROPERTIES
-	#include 
-	#include 
-
-	// thanks for nothing, microsoft
-	#ifndef ENABLE_VIRTUAL_TERMINAL_PROCESSING
-	#define ENABLE_VIRTUAL_TERMINAL_PROCESSING 0x0004
-	#endif
-
-	// the max buffer size we will convert on the stack
-	#define DLG_MAX_STACK_BUF_SIZE 1024
-
-	static void WINAPI dlg_fls_destructor(void* data) {
-		dlg_free_data(data);
-	}
-
-	// TODO: error handling
-	static BOOL CALLBACK dlg_init_fls(PINIT_ONCE io, void* param, void** lpContext) {
-		(void) io;
-		(void) param;
-		**((DWORD**) lpContext) = FlsAlloc(dlg_fls_destructor);
-		return true;
-	}
-
-	static struct dlg_data* dlg_data(void) {
-		static INIT_ONCE init_once = INIT_ONCE_STATIC_INIT;
-		static DWORD fls = 0;
-		void* flsp = (void*) &fls;
-		InitOnceExecuteOnce(&init_once, dlg_init_fls, NULL, &flsp);
-		void* data = FlsGetValue(fls);
-		if(!data) {
-			data = dlg_create_data();
-			FlsSetValue(fls, data);
-		}
-
-		return (struct dlg_data*) data;
-	}
-
-	static void lock_file(FILE* file) {
-		_lock_file(file);
-	}
-
-	static void unlock_file(FILE* file) {
-		_unlock_file(file);
-	}
-
-	bool dlg_is_tty(FILE* stream) {
-		return _isatty(_fileno(stream));
-	}
-
-#ifdef DLG_WIN_CONSOLE
-	static bool init_ansi_console(void) {
-		HANDLE out = GetStdHandle(STD_OUTPUT_HANDLE);
-		HANDLE err = GetStdHandle(STD_ERROR_HANDLE);
-		if(out == INVALID_HANDLE_VALUE || err == INVALID_HANDLE_VALUE)
-			return false;
-
-		DWORD outMode, errMode;
-		if(!GetConsoleMode(out, &outMode) || !GetConsoleMode(err, &errMode))
-		   return false;
-
-		outMode |= ENABLE_VIRTUAL_TERMINAL_PROCESSING;
-		errMode |= ENABLE_VIRTUAL_TERMINAL_PROCESSING;
-		if(!SetConsoleMode(out, outMode) || !SetConsoleMode(out, errMode))
-			return false;
-
-		return true;
-	}
-
-	static bool win_write_heap(void* handle, int needed, const char* format, va_list args) {
-		char* buf1 = xalloc(3 * needed + 3 + (needed % 2));
-		wchar_t* buf2 = (wchar_t*) (buf1 + needed + 1 + (needed % 2));
-		vsnprintf(buf1, needed + 1, format, args);
-	    needed = MultiByteToWideChar(CP_UTF8, 0, buf1, needed, buf2, needed + 1);
-		bool ret = (needed != 0 && WriteConsoleW(handle, buf2, needed, NULL, NULL) != 0);
-		free(buf1);
-		return ret;
-	}
-
-	static bool win_write_stack(void* handle, int needed, const char* format, va_list args) {
-		char buf1[DLG_MAX_STACK_BUF_SIZE];
-		wchar_t buf2[DLG_MAX_STACK_BUF_SIZE];
-		vsnprintf(buf1, needed + 1, format, args);
-	    needed = MultiByteToWideChar(CP_UTF8, 0, buf1, needed, buf2, needed + 1);
-		return (needed != 0 && WriteConsoleW(handle, buf2, needed, NULL, NULL) != 0);
-	}
-#endif // DLG_WIN_CONSOLE
-
-	static unsigned get_msecs() {
-		SYSTEMTIME st;
-		GetSystemTime(&st);
-		return st.wMilliseconds;
-	}
-
-#else // platform switch -- end windows
-	#error Cannot determine platform (needed for color and utf-8 and stuff)
-#endif
-
-// general
-void dlg_escape_sequence(struct dlg_style style, char buf[12]) {
-	int nums[3];
-	unsigned int count = 0;
-
-	if(style.fg != dlg_color_none) {
-		nums[count++] = style.fg + 30;
-	}
-
-	if(style.bg != dlg_color_none) {
-		nums[count++] = style.fg + 40;
-	}
-
-	if(style.style != dlg_text_style_none) {
-		nums[count++] = style.style;
-	}
-
-	switch(count) {
-		case 1: snprintf(buf, 12, "\033[%dm", nums[0]); break;
-		case 2: snprintf(buf, 12, "\033[%d;%dm", nums[0], nums[1]); break;
-		case 3: snprintf(buf, 12, "\033[%d;%d;%dm", nums[0], nums[1], nums[2]); break;
-		default: buf[0] = '\0'; break;
-	}
-}
-
-int dlg_vfprintf(FILE* stream, const char* format, va_list args) {
-#if defined(DLG_OS_WIN) && defined(DLG_WIN_CONSOLE)
-	void* handle = NULL;
-	if(stream == stdout) {
-		handle = GetStdHandle(STD_OUTPUT_HANDLE);
-	} else if(stream == stderr) {
-		handle = GetStdHandle(STD_ERROR_HANDLE);
-	}
-
-	if(handle) {
-		va_list args_copy;
-		va_copy(args_copy, args);
-		int needed = vsnprintf(NULL, 0, format, args_copy);
-		va_end(args_copy);
-
-		if(needed < 0) {
-			return needed;
-		}
-
-		// We don't allocate too much on the stack
-		// but we also don't want to call alloc every logging call
-		// or use another cached buffer
-		if(needed >= DLG_MAX_STACK_BUF_SIZE) {
-			if(win_write_heap(handle, needed, format, args)) {
-				return needed;
-			}
-		} else {
-			if(win_write_stack(handle, needed, format, args)) {
-				return needed;
-			}
-		}
-	}
-#endif
-
-	return vfprintf(stream, format, args);
-}
-
-int dlg_fprintf(FILE* stream, const char* format, ...) {
-	va_list args;
-	va_start(args, format);
-	int ret = dlg_vfprintf(stream, format, args);
-	va_end(args);
-	return ret;
-}
-
-int dlg_styled_fprintf(FILE* stream, struct dlg_style style, const char* format, ...) {
-	char buf[12];
-	dlg_escape_sequence(style, buf);
-
-	fprintf(stream, "%s", buf);
-	va_list args;
-	va_start(args, format);
-	int ret = dlg_vfprintf(stream, format, args);
-	va_end(args);
-	fprintf(stream, "%s", dlg_reset_sequence);
-	return ret;
-}
-
-void dlg_generic_output(dlg_generic_output_handler output, void* data,
-		unsigned int features, const struct dlg_origin* origin, const char* string,
-		const struct dlg_style styles[6]) {
-	// We never print any dynamic content below so we can be sure at compile
-	// time that a buffer of size 64 is large enough.
-	char format_buf[64];
-	char* format = format_buf;
-
-	if(features & dlg_output_style) {
-		format += sprintf(format, "%%s");
-	}
-
-	if(features & (dlg_output_time | dlg_output_file_line | dlg_output_tags | dlg_output_func)) {
-		format += sprintf(format, "[");
-	}
-
-	bool first_meta = true;
-	if(features & dlg_output_time) {
-		format += sprintf(format, "%%h");
-		first_meta = false;
-	}
-
-	if(features & dlg_output_time_msecs) {
-		if(!first_meta) {
-			format += sprintf(format, ":");
-		}
-
-		format += sprintf(format, "%%m");
-		first_meta = false;
-	}
-
-	if(features & dlg_output_file_line) {
-		if(!first_meta) {
-			format += sprintf(format, " ");
-		}
-
-		format += sprintf(format, "%%o");
-		first_meta = false;
-	}
-
-	if(features & dlg_output_func) {
-		if(!first_meta) {
-			format += sprintf(format, " ");
-		}
-
-		format += sprintf(format, "%%f");
-		first_meta = false;
-	}
-
-	if(features & dlg_output_tags) {
-		if(!first_meta) {
-			format += sprintf(format, " ");
-		}
-
-		format += sprintf(format, "{%%t}");
-		first_meta = false;
-	}
-
-	if(features & (dlg_output_time | dlg_output_file_line | dlg_output_tags | dlg_output_func)) {
-		format += sprintf(format, "] ");
-	}
-
-	format += sprintf(format, "%%c");
-
-	if(features & dlg_output_newline) {
-		format += sprintf(format, "\n");
-	}
-
-	*format = '\0';
-	dlg_generic_outputf(output, data, format_buf, origin, string, styles);
-}
-
-void dlg_generic_outputf(dlg_generic_output_handler output, void* data,
-		const char* format_string, const struct dlg_origin* origin, const char* string,
-		const struct dlg_style styles[6]) {
-	bool reset_style = false;
-	for(const char* it = format_string; *it; it++) {
-		if(*it != '%') {
-			output(data, "%c", *it);
-			continue;
-		}
-
-		char next = *(it + 1); // must be valid since *it is not '\0'
-		if(next == 'h') {
-			time_t t = time(NULL);
-			struct tm tm_info;
-
-	#ifdef DLG_OS_WIN
-			if(localtime_s(&tm_info, &t)) {
-	#else
-			if(!localtime_r(&t, &tm_info)) {
-	#endif
-				output(data, "");
-			} else {
-				char timebuf[32];
-				strftime(timebuf, sizeof(timebuf), "%H:%M:%S", &tm_info);
-				output(data, "%s", timebuf);
-			}
-			it++;
-		} else if(next == 'm') {
-			output(data, "%06d", get_msecs());
-			it++;
-		} else if(next == 't') {
-			bool first_tag = true;
-			for(const char** tags = origin->tags; *tags; ++tags) {
-				if(!first_tag) {
-					output(data, ", ");
-				}
-
-				output(data, "%s", *tags);
-				first_tag = false;
-			}
-			++it;
-		} else if(next == 'f') {
-			output(data, "%s", origin->func);
-			++it;
-		} else if(next == 'o') {
-			output(data, "%s:%u", origin->file, origin->line);
-			++it;
-		} else if(next == 's') {
-			char buf[12];
-			dlg_escape_sequence(styles[origin->level], buf);
-			output(data, "%s", buf);
-			reset_style = true;
-			++it;
-		} else if(next == 'r') {
-			output(data, "%s", dlg_reset_sequence);
-			reset_style = false;
-			++it;
-		} else if(next == 'c') {
-			if(origin->expr && string) {
-				output(data, "assertion '%s' failed: '%s'", origin->expr, string);
-			} else if(origin->expr) {
-				output(data, "assertion '%s' failed", origin->expr);
-			} else if(string) {
-				output(data, "%s", string);
-			}
-			++it;
-		} else if(next == '%') {
-			output(data, "%s", "%");
-			++it;
-		} else {
-			// in this case it's a '%' without known format specifier following
-			output(data, "%s", "%");
-		}
-	}
-
-	if(reset_style) {
-		output(data, "%s", dlg_reset_sequence);
-	}
-}
-
-struct buf {
-	char* buf;
-	size_t* size;
-};
-
-static void print_size(void* size, const char* format, ...) {
-	va_list args;
-	va_start(args, format);
-
-	int ret = vsnprintf(NULL, 0, format, args);
-	va_end(args);
-
-	if(ret > 0) {
-		*((size_t*) size) += ret;
-	}
-}
-
-static void print_buf(void* dbuf, const char* format, ...) {
-	struct buf* buf = (struct buf*) dbuf;
-	va_list args;
-	va_start(args, format);
-
-	int printed = vsnprintf(buf->buf, *buf->size, format, args);
-	va_end(args);
-
-	if(printed > 0) {
-		*buf->size -= printed;
-		buf->buf += printed;
-	}
-}
-
-void dlg_generic_output_buf(char* buf, size_t* size, unsigned int features,
-		const struct dlg_origin* origin, const char* string,
-		const struct dlg_style styles[6]) {
-	if(buf) {
-		struct buf mbuf;
-		mbuf.buf = buf;
-		mbuf.size = size;
-		dlg_generic_output(print_buf, &mbuf, features, origin, string, styles);
-	} else {
-		*size = 0;
-		dlg_generic_output(print_size, size, features, origin, string, styles);
-	}
-}
-
-void dlg_generic_outputf_buf(char* buf, size_t* size, const char* format_string,
-		const struct dlg_origin* origin, const char* string,
-		const struct dlg_style styles[6]) {
-	if(buf) {
-		struct buf mbuf;
-		mbuf.buf = buf;
-		mbuf.size = size;
-		dlg_generic_outputf(print_buf, &mbuf, format_string, origin, string, styles);
-	} else {
-		*size = 0;
-		dlg_generic_outputf(print_size, size, format_string, origin, string, styles);
-	}
-}
-
-static void print_stream(void* stream, const char* format, ...) {
-	va_list args;
-	va_start(args, format);
-	dlg_vfprintf((FILE*) stream, format, args);
-	va_end(args);
-}
-
-void dlg_generic_output_stream(FILE* stream, unsigned int features,
-		const struct dlg_origin* origin, const char* string,
-		const struct dlg_style styles[6]) {
-	stream = stream ? stream : stdout;
-	if(features & dlg_output_threadsafe) {
-		lock_file(stream);
-	}
-
-	dlg_generic_output(print_stream, stream, features, origin, string, styles);
-	if(features & dlg_output_threadsafe) {
-		unlock_file(stream);
-	}
-}
-
-void dlg_generic_outputf_stream(FILE* stream, const char* format_string,
-		const struct dlg_origin* origin, const char* string,
-		const struct dlg_style styles[6], bool lock_stream) {
-	stream = stream ? stream : stdout;
-	if(lock_stream) {
-		lock_file(stream);
-	}
-
-	dlg_generic_outputf(print_stream, stream, format_string, origin, string, styles);
-	if(lock_stream) {
-		unlock_file(stream);
-	}
-}
-
-void dlg_default_output(const struct dlg_origin* origin, const char* string, void* data) {
-	FILE* stream = data ? (FILE*) data : stdout;
-	unsigned int features = dlg_output_file_line |
-		dlg_output_newline |
-		dlg_output_threadsafe;
-
-#ifdef DLG_DEFAULT_OUTPUT_ALWAYS_COLOR
-	dlg_win_init_ansi();
-	features |= dlg_output_style;
-#else
-	if(dlg_is_tty(stream) && dlg_win_init_ansi()) {
-		features |= dlg_output_style;
-	}
-#endif
-
-	dlg_generic_output_stream(stream, features, origin, string, dlg_default_output_styles);
-	fflush(stream);
-}
-
-bool dlg_win_init_ansi(void) {
-#if defined(DLG_OS_WIN) && defined(DLG_WIN_CONSOLE)
-	// TODO: use init once
-	static volatile LONG status = 0;
-	LONG res = InterlockedCompareExchange(&status, 1, 0);
-	if(res == 0) { // not initialized
-		InterlockedExchange(&status, 3 + init_ansi_console());
-	}
-
-	while(status == 1); // currently initialized in another thread, spinlock
-	return (status == 4);
-#else
-	return true;
-#endif
-}
-
-// small dynamic vec/array implementation
-// Since the macros vec_init and vec_add[c]/vec_push might
-// change the pointers value it must not be referenced somewhere else.
-#define vec__raw(vec) (((unsigned int*) vec) - 2)
-
-static void* vec_do_create(unsigned int typesize, unsigned int cap, unsigned int size) {
-	unsigned long a = (size > cap) ? size : cap;
-	void* ptr = xalloc(2 * sizeof(unsigned int) + a * typesize);
-	unsigned int* begin = (unsigned int*) ptr;
-	begin[0] = size * typesize;
-	begin[1] = a * typesize;
-	return begin + 2;
-}
-
-// NOTE: can be more efficient if we are allowed to reorder vector
-static void vec_do_erase(void* vec, unsigned int pos, unsigned int size) {
-	unsigned int* begin = vec__raw(vec);
-	begin[0] -= size;
-	char* buf = (char*) vec;
-	memcpy(buf + pos, buf + pos + size, size);
-}
-
-static void* vec_do_add(void** vec, unsigned int size) {
-	unsigned int* begin = vec__raw(*vec);
-	unsigned int needed = begin[0] + size;
-	if(needed >= begin[1]) {
-		void* ptr = xrealloc(begin, sizeof(unsigned int) * 2 + needed * 2);
-		begin = (unsigned int*) ptr;
-		begin[1] = needed * 2;
-		(*vec) = begin + 2;
-	}
-
-	void* ptr = ((char*) (*vec)) + begin[0];
-	begin[0] += size;
-	return ptr;
-}
-
-#define vec_create(type, size) (type*) vec_do_create(sizeof(type), size * 2, size)
-#define vec_create_reserve(type, size, capacity) (type*) vec_do_create(sizeof(type), capcity, size)
-#define vec_init(array, size) array = vec_do_create(sizeof(*array), size * 2, size)
-#define vec_init_reserve(array, size, capacity) *((void**) &array) = vec_do_create(sizeof(*array), capacity, size)
-#define vec_free(vec) (free((vec) ? vec__raw(vec) : NULL), vec = NULL)
-#define vec_erase_range(vec, pos, count) vec_do_erase(vec, pos * sizeof(*vec), count * sizeof(*vec))
-#define vec_erase(vec, pos) vec_do_erase(vec, pos * sizeof(*vec), sizeof(*vec))
-#define vec_size(vec) (vec__raw(vec)[0] / sizeof(*vec))
-#define vec_capacity(vec) (vec_raw(vec)[1] / sizeof(*vec))
-#define vec_add(vec) vec_do_add((void**) &vec, sizeof(*vec))
-#define vec_addc(vec, count) (vec_do_add((void**) &vec, sizeof(*vec) * count))
-#define vec_push(vec, value) (vec_do_add((void**) &vec, sizeof(*vec)), vec_last(vec) = (value))
-#define vec_pop(vec) (vec__raw(vec)[0] -= sizeof(*vec))
-#define vec_popc(vec, count) (vec__raw(vec)[0] -= sizeof(*vec) * count)
-#define vec_clear(vec) (vec__raw(vec)[0] = 0)
-#define vec_last(vec) (vec[vec_size(vec) - 1])
-
-static struct dlg_data* dlg_create_data(void) {
-	struct dlg_data* data = (struct dlg_data*) xalloc(sizeof(struct dlg_data));
-	vec_init_reserve(data->tags, 0, 20);
-	vec_init_reserve(data->pairs, 0, 20);
-	data->buffer_size = 100;
-	data->buffer = (char*) xalloc(data->buffer_size);
-	return data;
-}
-
-static void dlg_free_data(void* ddata) {
-	struct dlg_data* data = (struct dlg_data*) ddata;
-	if(data) {
-		vec_free(data->pairs);
-		vec_free(data->tags);
-		free(data->buffer);
-		free(data);
-	}
-}
-
-void dlg_add_tag(const char* tag, const char* func) {
-	struct dlg_data* data = dlg_data();
-	struct dlg_tag_func_pair* pair =
-		(struct dlg_tag_func_pair*) vec_add(data->pairs);
-	pair->tag = tag;
-	pair->func = func;
-}
-
-bool dlg_remove_tag(const char* tag, const char* func) {
-	struct dlg_data* data = dlg_data();
-	for(unsigned int i = 0; i < vec_size(data->pairs); ++i) {
-		if(data->pairs[i].func == func && data->pairs[i].tag == tag) {
-			vec_erase(data->pairs, i);
-			return true;
-		}
-	}
-
-	return false;
-}
-
-char** dlg_thread_buffer(size_t** size) {
-	struct dlg_data* data = dlg_data();
-	if(size) {
-		*size = &data->buffer_size;
-	}
-	return &data->buffer;
-}
-
-void dlg_set_handler(dlg_handler handler, void* data) {
-	g_handler = handler;
-	g_data = data;
-}
-
-dlg_handler dlg_get_handler(void** data) {
-	*data = g_data;
-	return g_handler;
-}
-
-const char* dlg__printf_format(const char* str, ...) {
-	va_list vlist;
-	va_start(vlist, str);
-
-	va_list vlistcopy;
-	va_copy(vlistcopy, vlist);
-	int needed = vsnprintf(NULL, 0, str, vlist);
-	if(needed < 0) {
-		printf("dlg__printf_format: invalid format given\n");
-		va_end(vlist);
-		va_end(vlistcopy);
-		return NULL;
-	}
-
-	va_end(vlist);
-
-	size_t* buf_size;
-	char** buf = dlg_thread_buffer(&buf_size);
-	if(*buf_size <= (unsigned int) needed) {
-		*buf_size = (needed + 1) * 2;
-		*buf = (char*) xrealloc(*buf, *buf_size);
-	}
-
-	vsnprintf(*buf, *buf_size, str, vlistcopy);
-	va_end(vlistcopy);
-
-	return *buf;
-}
-
-void dlg__do_log(enum dlg_level lvl, const char* const* tags, const char* file, int line,
-		const char* func, const char* string, const char* expr) {
-	struct dlg_data* data = dlg_data();
-	unsigned int tag_count = 0;
-
-	// push default tags
-	while(tags[tag_count]) {
-		vec_push(data->tags, tags[tag_count++]);
-	}
-
-	// push current global tags
-	for(size_t i = 0; i < vec_size(data->pairs); ++i) {
-		const struct dlg_tag_func_pair pair = data->pairs[i];
-		if(pair.func == NULL || !strcmp(pair.func, func)) {
-			vec_push(data->tags, pair.tag);
-		}
-	}
-
-	// push call-specific tags, skip first terminating NULL
-	++tag_count;
-	while(tags[tag_count]) {
-		vec_push(data->tags, tags[tag_count++]);
-	}
-
-	vec_push(data->tags, NULL); // terminating NULL
-	struct dlg_origin origin;
-	origin.level = lvl;
-	origin.file = file;
-	origin.line = line;
-	origin.func = func;
-	origin.expr = expr;
-	origin.tags = data->tags;
-
-	g_handler(&origin, string, g_data);
-	vec_clear(data->tags);
-}
-
-#ifdef _MSC_VER
-// shitty msvc compatbility
-// meson gives us sane paths (separated by '/') while on MSVC,
-// __FILE__ contains a '\\' separator.
-static bool path_same(char a, char b) {
-	return (a == b) ||
-		(a == '/' && b == '\\') ||
-		(a == '\\' && b == '/');
-}
-#else
-
-static inline bool path_same(char a, char b) {
-	return a == b;
-}
-
-#endif
-
-const char* dlg__strip_root_path(const char* file, const char* base) {
-	if(!file) {
-		return NULL;
-	}
-
-	const char* saved = file;
-	if(*file == '.') { // relative path detected
-		while(*(++file) == '.' || *file == '/' || *file == '\\');
-		if(*file == '\0') { // weird case: purely relative path without file
-			return saved;
-		}
-
-		return file;
-	}
-
-	// strip base from file if it is given
-	if(base) {
-		char fn = *file;
-		char bn = *base;
-		while(bn != '\0' && path_same(fn, bn)) {
-			fn = *(++file);
-			bn = *(++base);
-		}
-
-		if(fn == '\0' || bn != '\0') { // weird case: base isn't prefix of file
-			return saved;
-		}
-	}
-
-	return file;
-}
diff --git a/vendor/freetype/src/dlg/dlgwrap.c b/vendor/freetype/src/dlg/dlgwrap.c
index e9dc3410a4..e6053cd5bc 100644
--- a/vendor/freetype/src/dlg/dlgwrap.c
+++ b/vendor/freetype/src/dlg/dlgwrap.c
@@ -4,7 +4,7 @@
  *
  *   Wrapper file for the 'dlg' library (body only)
  *
- * Copyright (C) 2020-2023 by
+ * Copyright (C) 2020-2024 by
  * David Turner, Robert Wilhelm, and Werner Lemberg.
  *
  * This file is part of the FreeType project, and may only be used,
diff --git a/vendor/freetype/src/gxvalid/README b/vendor/freetype/src/gxvalid/README
index 0e3db322ef..efd792c9a1 100644
--- a/vendor/freetype/src/gxvalid/README
+++ b/vendor/freetype/src/gxvalid/README
@@ -518,7 +518,7 @@ gxvalid: TrueType GX validator
 
 ------------------------------------------------------------------------
 
-Copyright (C) 2004-2023 by
+Copyright (C) 2004-2024 by
 suzuki toshiya, Masatake YAMATO, Red hat K.K.,
 David Turner, Robert Wilhelm, and Werner Lemberg.
 
diff --git a/vendor/freetype/src/gxvalid/gxvalid.c b/vendor/freetype/src/gxvalid/gxvalid.c
index e0359f4df7..6694c342c0 100644
--- a/vendor/freetype/src/gxvalid/gxvalid.c
+++ b/vendor/freetype/src/gxvalid/gxvalid.c
@@ -4,7 +4,7 @@
  *
  *   FreeType validator for TrueTypeGX/AAT tables (body only).
  *
- * Copyright (C) 2005-2023 by
+ * Copyright (C) 2005-2024 by
  * suzuki toshiya, Masatake YAMATO, Red Hat K.K.,
  * David Turner, Robert Wilhelm, and Werner Lemberg.
  *
diff --git a/vendor/freetype/src/gxvalid/gxvalid.h b/vendor/freetype/src/gxvalid/gxvalid.h
index a83408b416..4ddb625e9e 100644
--- a/vendor/freetype/src/gxvalid/gxvalid.h
+++ b/vendor/freetype/src/gxvalid/gxvalid.h
@@ -4,7 +4,7 @@
  *
  *   TrueTypeGX/AAT table validation (specification only).
  *
- * Copyright (C) 2005-2023 by
+ * Copyright (C) 2005-2024 by
  * suzuki toshiya, Masatake YAMATO, Red Hat K.K.,
  * David Turner, Robert Wilhelm, and Werner Lemberg.
  *
diff --git a/vendor/freetype/src/gxvalid/gxvbsln.c b/vendor/freetype/src/gxvalid/gxvbsln.c
index 030a64ee45..e3a922aebc 100644
--- a/vendor/freetype/src/gxvalid/gxvbsln.c
+++ b/vendor/freetype/src/gxvalid/gxvbsln.c
@@ -4,7 +4,7 @@
  *
  *   TrueTypeGX/AAT bsln table validation (body).
  *
- * Copyright (C) 2004-2023 by
+ * Copyright (C) 2004-2024 by
  * suzuki toshiya, Masatake YAMATO, Red Hat K.K.,
  * David Turner, Robert Wilhelm, and Werner Lemberg.
  *
diff --git a/vendor/freetype/src/gxvalid/gxvcommn.c b/vendor/freetype/src/gxvalid/gxvcommn.c
index 7f908742af..5f8fa115f5 100644
--- a/vendor/freetype/src/gxvalid/gxvcommn.c
+++ b/vendor/freetype/src/gxvalid/gxvcommn.c
@@ -4,7 +4,7 @@
  *
  *   TrueTypeGX/AAT common tables validation (body).
  *
- * Copyright (C) 2004-2023 by
+ * Copyright (C) 2004-2024 by
  * suzuki toshiya, Masatake YAMATO, Red Hat K.K.,
  * David Turner, Robert Wilhelm, and Werner Lemberg.
  *
diff --git a/vendor/freetype/src/gxvalid/gxvcommn.h b/vendor/freetype/src/gxvalid/gxvcommn.h
index f88d23a419..4dbac1db67 100644
--- a/vendor/freetype/src/gxvalid/gxvcommn.h
+++ b/vendor/freetype/src/gxvalid/gxvcommn.h
@@ -4,7 +4,7 @@
  *
  *   TrueTypeGX/AAT common tables validation (specification).
  *
- * Copyright (C) 2004-2023 by
+ * Copyright (C) 2004-2024 by
  * suzuki toshiya, Masatake YAMATO, Red Hat K.K.,
  * David Turner, Robert Wilhelm, and Werner Lemberg.
  *
@@ -516,9 +516,6 @@ FT_BEGIN_HEADER
               FT_INVALID_TOO_SHORT;                         \
           FT_END_STMNT
 
-#define GXV_USHORT_TO_SHORT( _us )                                    \
-          ( ( 0x8000U < ( _us ) ) ? ( ( _us ) - 0x8000U ) : ( _us ) )
-
 #define GXV_STATETABLE_HEADER_SIZE  ( 2 + 2 + 2 + 2 )
 #define GXV_STATEHEADER_SIZE        GXV_STATETABLE_HEADER_SIZE
 
diff --git a/vendor/freetype/src/gxvalid/gxverror.h b/vendor/freetype/src/gxvalid/gxverror.h
index 09311ed3c3..750f22fc3a 100644
--- a/vendor/freetype/src/gxvalid/gxverror.h
+++ b/vendor/freetype/src/gxvalid/gxverror.h
@@ -4,7 +4,7 @@
  *
  *   TrueTypeGX/AAT validation module error codes (specification only).
  *
- * Copyright (C) 2004-2023 by
+ * Copyright (C) 2004-2024 by
  * suzuki toshiya, Masatake YAMATO, Red Hat K.K.,
  * David Turner, Robert Wilhelm, and Werner Lemberg.
  *
diff --git a/vendor/freetype/src/gxvalid/gxvfeat.c b/vendor/freetype/src/gxvalid/gxvfeat.c
index 6cf18212a3..57b389239b 100644
--- a/vendor/freetype/src/gxvalid/gxvfeat.c
+++ b/vendor/freetype/src/gxvalid/gxvfeat.c
@@ -4,7 +4,7 @@
  *
  *   TrueTypeGX/AAT feat table validation (body).
  *
- * Copyright (C) 2004-2023 by
+ * Copyright (C) 2004-2024 by
  * suzuki toshiya, Masatake YAMATO, Red Hat K.K.,
  * David Turner, Robert Wilhelm, and Werner Lemberg.
  *
diff --git a/vendor/freetype/src/gxvalid/gxvfeat.h b/vendor/freetype/src/gxvalid/gxvfeat.h
index b33c1bc681..dd8f1bfe67 100644
--- a/vendor/freetype/src/gxvalid/gxvfeat.h
+++ b/vendor/freetype/src/gxvalid/gxvfeat.h
@@ -4,7 +4,7 @@
  *
  *   TrueTypeGX/AAT feat table validation (specification).
  *
- * Copyright (C) 2004-2023 by
+ * Copyright (C) 2004-2024 by
  * suzuki toshiya, Masatake YAMATO, Red Hat K.K.,
  * David Turner, Robert Wilhelm, and Werner Lemberg.
  *
diff --git a/vendor/freetype/src/gxvalid/gxvfgen.c b/vendor/freetype/src/gxvalid/gxvfgen.c
index cf98bb36c3..27a4ed9a71 100644
--- a/vendor/freetype/src/gxvalid/gxvfgen.c
+++ b/vendor/freetype/src/gxvalid/gxvfgen.c
@@ -5,7 +5,7 @@
  *   Generate feature registry data for gxv `feat' validator.
  *   This program is derived from gxfeatreg.c in gxlayout.
  *
- * Copyright (C) 2004-2023 by
+ * Copyright (C) 2004-2024 by
  * Masatake YAMATO and Redhat K.K.
  *
  * This file may only be used,
diff --git a/vendor/freetype/src/gxvalid/gxvjust.c b/vendor/freetype/src/gxvalid/gxvjust.c
index 5cca94d8fd..1cf9e84ad4 100644
--- a/vendor/freetype/src/gxvalid/gxvjust.c
+++ b/vendor/freetype/src/gxvalid/gxvjust.c
@@ -4,7 +4,7 @@
  *
  *   TrueTypeGX/AAT just table validation (body).
  *
- * Copyright (C) 2005-2023 by
+ * Copyright (C) 2005-2024 by
  * suzuki toshiya, Masatake YAMATO, Red Hat K.K.,
  * David Turner, Robert Wilhelm, and Werner Lemberg.
  *
diff --git a/vendor/freetype/src/gxvalid/gxvkern.c b/vendor/freetype/src/gxvalid/gxvkern.c
index 21fc24596c..cf8c51fb8e 100644
--- a/vendor/freetype/src/gxvalid/gxvkern.c
+++ b/vendor/freetype/src/gxvalid/gxvkern.c
@@ -4,7 +4,7 @@
  *
  *   TrueTypeGX/AAT kern table validation (body).
  *
- * Copyright (C) 2004-2023 by
+ * Copyright (C) 2004-2024 by
  * suzuki toshiya, Masatake YAMATO, Red Hat K.K.,
  * David Turner, Robert Wilhelm, and Werner Lemberg.
  *
diff --git a/vendor/freetype/src/gxvalid/gxvlcar.c b/vendor/freetype/src/gxvalid/gxvlcar.c
index 5f3bf89073..0b310f42df 100644
--- a/vendor/freetype/src/gxvalid/gxvlcar.c
+++ b/vendor/freetype/src/gxvalid/gxvlcar.c
@@ -4,7 +4,7 @@
  *
  *   TrueTypeGX/AAT lcar table validation (body).
  *
- * Copyright (C) 2004-2023 by
+ * Copyright (C) 2004-2024 by
  * suzuki toshiya, Masatake YAMATO, Red Hat K.K.,
  * David Turner, Robert Wilhelm, and Werner Lemberg.
  *
diff --git a/vendor/freetype/src/gxvalid/gxvmod.c b/vendor/freetype/src/gxvalid/gxvmod.c
index 0b4115bbc6..ce1e441eb4 100644
--- a/vendor/freetype/src/gxvalid/gxvmod.c
+++ b/vendor/freetype/src/gxvalid/gxvmod.c
@@ -4,7 +4,7 @@
  *
  *   FreeType's TrueTypeGX/AAT validation module implementation (body).
  *
- * Copyright (C) 2004-2023 by
+ * Copyright (C) 2004-2024 by
  * suzuki toshiya, Masatake YAMATO, Red Hat K.K.,
  * David Turner, Robert Wilhelm, and Werner Lemberg.
  *
diff --git a/vendor/freetype/src/gxvalid/gxvmod.h b/vendor/freetype/src/gxvalid/gxvmod.h
index db3d1d9f56..6def5c5475 100644
--- a/vendor/freetype/src/gxvalid/gxvmod.h
+++ b/vendor/freetype/src/gxvalid/gxvmod.h
@@ -5,7 +5,7 @@
  *   FreeType's TrueTypeGX/AAT validation module implementation
  *   (specification).
  *
- * Copyright (C) 2004-2023 by
+ * Copyright (C) 2004-2024 by
  * suzuki toshiya, Masatake YAMATO, Red Hat K.K.,
  * David Turner, Robert Wilhelm, and Werner Lemberg.
  *
diff --git a/vendor/freetype/src/gxvalid/gxvmort.c b/vendor/freetype/src/gxvalid/gxvmort.c
index 7032d6349f..5ad9d81c59 100644
--- a/vendor/freetype/src/gxvalid/gxvmort.c
+++ b/vendor/freetype/src/gxvalid/gxvmort.c
@@ -4,7 +4,7 @@
  *
  *   TrueTypeGX/AAT mort table validation (body).
  *
- * Copyright (C) 2005-2023 by
+ * Copyright (C) 2005-2024 by
  * suzuki toshiya, Masatake YAMATO, Red Hat K.K.,
  * David Turner, Robert Wilhelm, and Werner Lemberg.
  *
diff --git a/vendor/freetype/src/gxvalid/gxvmort.h b/vendor/freetype/src/gxvalid/gxvmort.h
index 5c819bdbc8..a3970e7862 100644
--- a/vendor/freetype/src/gxvalid/gxvmort.h
+++ b/vendor/freetype/src/gxvalid/gxvmort.h
@@ -4,7 +4,7 @@
  *
  *   TrueTypeGX/AAT common definition for mort table (specification).
  *
- * Copyright (C) 2004-2023 by
+ * Copyright (C) 2004-2024 by
  * suzuki toshiya, Masatake YAMATO, Red Hat K.K.,
  * David Turner, Robert Wilhelm, and Werner Lemberg.
  *
diff --git a/vendor/freetype/src/gxvalid/gxvmort0.c b/vendor/freetype/src/gxvalid/gxvmort0.c
index 24e70a0dae..1a05a6d432 100644
--- a/vendor/freetype/src/gxvalid/gxvmort0.c
+++ b/vendor/freetype/src/gxvalid/gxvmort0.c
@@ -5,7 +5,7 @@
  *   TrueTypeGX/AAT mort table validation
  *   body for type0 (Indic Script Rearrangement) subtable.
  *
- * Copyright (C) 2005-2023 by
+ * Copyright (C) 2005-2024 by
  * suzuki toshiya, Masatake YAMATO, Red Hat K.K.,
  * David Turner, Robert Wilhelm, and Werner Lemberg.
  *
diff --git a/vendor/freetype/src/gxvalid/gxvmort1.c b/vendor/freetype/src/gxvalid/gxvmort1.c
index ea5591f980..f99a8a4987 100644
--- a/vendor/freetype/src/gxvalid/gxvmort1.c
+++ b/vendor/freetype/src/gxvalid/gxvmort1.c
@@ -5,7 +5,7 @@
  *   TrueTypeGX/AAT mort table validation
  *   body for type1 (Contextual Substitution) subtable.
  *
- * Copyright (C) 2005-2023 by
+ * Copyright (C) 2005-2024 by
  * suzuki toshiya, Masatake YAMATO, Red Hat K.K.,
  * David Turner, Robert Wilhelm, and Werner Lemberg.
  *
diff --git a/vendor/freetype/src/gxvalid/gxvmort2.c b/vendor/freetype/src/gxvalid/gxvmort2.c
index 50644f06a6..18c9be6760 100644
--- a/vendor/freetype/src/gxvalid/gxvmort2.c
+++ b/vendor/freetype/src/gxvalid/gxvmort2.c
@@ -5,7 +5,7 @@
  *   TrueTypeGX/AAT mort table validation
  *   body for type2 (Ligature Substitution) subtable.
  *
- * Copyright (C) 2005-2023 by
+ * Copyright (C) 2005-2024 by
  * suzuki toshiya, Masatake YAMATO, Red Hat K.K.,
  * David Turner, Robert Wilhelm, and Werner Lemberg.
  *
diff --git a/vendor/freetype/src/gxvalid/gxvmort4.c b/vendor/freetype/src/gxvalid/gxvmort4.c
index 0641b11330..bc190fadd1 100644
--- a/vendor/freetype/src/gxvalid/gxvmort4.c
+++ b/vendor/freetype/src/gxvalid/gxvmort4.c
@@ -5,7 +5,7 @@
  *   TrueTypeGX/AAT mort table validation
  *   body for type4 (Non-Contextual Glyph Substitution) subtable.
  *
- * Copyright (C) 2005-2023 by
+ * Copyright (C) 2005-2024 by
  * suzuki toshiya, Masatake YAMATO, Red Hat K.K.,
  * David Turner, Robert Wilhelm, and Werner Lemberg.
  *
diff --git a/vendor/freetype/src/gxvalid/gxvmort5.c b/vendor/freetype/src/gxvalid/gxvmort5.c
index 9225bb0c68..8211a294ad 100644
--- a/vendor/freetype/src/gxvalid/gxvmort5.c
+++ b/vendor/freetype/src/gxvalid/gxvmort5.c
@@ -5,7 +5,7 @@
  *   TrueTypeGX/AAT mort table validation
  *   body for type5 (Contextual Glyph Insertion) subtable.
  *
- * Copyright (C) 2005-2023 by
+ * Copyright (C) 2005-2024 by
  * suzuki toshiya, Masatake YAMATO, Red Hat K.K.,
  * David Turner, Robert Wilhelm, and Werner Lemberg.
  *
diff --git a/vendor/freetype/src/gxvalid/gxvmorx.c b/vendor/freetype/src/gxvalid/gxvmorx.c
index 931bf006b8..4e7a0d40aa 100644
--- a/vendor/freetype/src/gxvalid/gxvmorx.c
+++ b/vendor/freetype/src/gxvalid/gxvmorx.c
@@ -4,7 +4,7 @@
  *
  *   TrueTypeGX/AAT morx table validation (body).
  *
- * Copyright (C) 2005-2023 by
+ * Copyright (C) 2005-2024 by
  * suzuki toshiya, Masatake YAMATO, Red Hat K.K.,
  * David Turner, Robert Wilhelm, and Werner Lemberg.
  *
diff --git a/vendor/freetype/src/gxvalid/gxvmorx.h b/vendor/freetype/src/gxvalid/gxvmorx.h
index 27572553dc..7e20b5f96b 100644
--- a/vendor/freetype/src/gxvalid/gxvmorx.h
+++ b/vendor/freetype/src/gxvalid/gxvmorx.h
@@ -4,7 +4,7 @@
  *
  *   TrueTypeGX/AAT common definition for morx table (specification).
  *
- * Copyright (C) 2005-2023 by
+ * Copyright (C) 2005-2024 by
  * suzuki toshiya, Masatake YAMATO, Red Hat K.K.,
  * David Turner, Robert Wilhelm, and Werner Lemberg.
  *
diff --git a/vendor/freetype/src/gxvalid/gxvmorx0.c b/vendor/freetype/src/gxvalid/gxvmorx0.c
index 73523f3634..bff850bac5 100644
--- a/vendor/freetype/src/gxvalid/gxvmorx0.c
+++ b/vendor/freetype/src/gxvalid/gxvmorx0.c
@@ -5,7 +5,7 @@
  *   TrueTypeGX/AAT morx table validation
  *   body for type0 (Indic Script Rearrangement) subtable.
  *
- * Copyright (C) 2005-2023 by
+ * Copyright (C) 2005-2024 by
  * suzuki toshiya, Masatake YAMATO, Red Hat K.K.,
  * David Turner, Robert Wilhelm, and Werner Lemberg.
  *
diff --git a/vendor/freetype/src/gxvalid/gxvmorx1.c b/vendor/freetype/src/gxvalid/gxvmorx1.c
index 71a2018802..d8ded3bc4f 100644
--- a/vendor/freetype/src/gxvalid/gxvmorx1.c
+++ b/vendor/freetype/src/gxvalid/gxvmorx1.c
@@ -5,7 +5,7 @@
  *   TrueTypeGX/AAT morx table validation
  *   body for type1 (Contextual Substitution) subtable.
  *
- * Copyright (C) 2005-2023 by
+ * Copyright (C) 2005-2024 by
  * suzuki toshiya, Masatake YAMATO, Red Hat K.K.,
  * David Turner, Robert Wilhelm, and Werner Lemberg.
  *
diff --git a/vendor/freetype/src/gxvalid/gxvmorx2.c b/vendor/freetype/src/gxvalid/gxvmorx2.c
index 858c81143b..faa09e9025 100644
--- a/vendor/freetype/src/gxvalid/gxvmorx2.c
+++ b/vendor/freetype/src/gxvalid/gxvmorx2.c
@@ -5,7 +5,7 @@
  *   TrueTypeGX/AAT morx table validation
  *   body for type2 (Ligature Substitution) subtable.
  *
- * Copyright (C) 2005-2023 by
+ * Copyright (C) 2005-2024 by
  * suzuki toshiya, Masatake YAMATO, Red Hat K.K.,
  * David Turner, Robert Wilhelm, and Werner Lemberg.
  *
diff --git a/vendor/freetype/src/gxvalid/gxvmorx4.c b/vendor/freetype/src/gxvalid/gxvmorx4.c
index c9ad199060..40468b8491 100644
--- a/vendor/freetype/src/gxvalid/gxvmorx4.c
+++ b/vendor/freetype/src/gxvalid/gxvmorx4.c
@@ -5,7 +5,7 @@
  *   TrueTypeGX/AAT morx table validation
  *   body for "morx" type4 (Non-Contextual Glyph Substitution) subtable.
  *
- * Copyright (C) 2005-2023 by
+ * Copyright (C) 2005-2024 by
  * suzuki toshiya, Masatake YAMATO, Red Hat K.K.,
  * David Turner, Robert Wilhelm, and Werner Lemberg.
  *
diff --git a/vendor/freetype/src/gxvalid/gxvmorx5.c b/vendor/freetype/src/gxvalid/gxvmorx5.c
index 95fa4e288c..a3dbdd43d6 100644
--- a/vendor/freetype/src/gxvalid/gxvmorx5.c
+++ b/vendor/freetype/src/gxvalid/gxvmorx5.c
@@ -5,7 +5,7 @@
  *   TrueTypeGX/AAT morx table validation
  *   body for type5 (Contextual Glyph Insertion) subtable.
  *
- * Copyright (C) 2005-2023 by
+ * Copyright (C) 2005-2024 by
  * suzuki toshiya, Masatake YAMATO, Red Hat K.K.,
  * David Turner, Robert Wilhelm, and Werner Lemberg.
  *
diff --git a/vendor/freetype/src/gxvalid/gxvopbd.c b/vendor/freetype/src/gxvalid/gxvopbd.c
index 5e9a9665eb..98b5bb875a 100644
--- a/vendor/freetype/src/gxvalid/gxvopbd.c
+++ b/vendor/freetype/src/gxvalid/gxvopbd.c
@@ -4,7 +4,7 @@
  *
  *   TrueTypeGX/AAT opbd table validation (body).
  *
- * Copyright (C) 2004-2023 by
+ * Copyright (C) 2004-2024 by
  * suzuki toshiya, Masatake YAMATO, Red Hat K.K.,
  * David Turner, Robert Wilhelm, and Werner Lemberg.
  *
diff --git a/vendor/freetype/src/gxvalid/gxvprop.c b/vendor/freetype/src/gxvalid/gxvprop.c
index 63a052a8e8..e485fa665a 100644
--- a/vendor/freetype/src/gxvalid/gxvprop.c
+++ b/vendor/freetype/src/gxvalid/gxvprop.c
@@ -4,7 +4,7 @@
  *
  *   TrueTypeGX/AAT prop table validation (body).
  *
- * Copyright (C) 2004-2023 by
+ * Copyright (C) 2004-2024 by
  * suzuki toshiya, Masatake YAMATO, Red Hat K.K.,
  * David Turner, Robert Wilhelm, and Werner Lemberg.
  *
diff --git a/vendor/freetype/src/gxvalid/gxvtrak.c b/vendor/freetype/src/gxvalid/gxvtrak.c
index f3fb51c8ad..a402823af7 100644
--- a/vendor/freetype/src/gxvalid/gxvtrak.c
+++ b/vendor/freetype/src/gxvalid/gxvtrak.c
@@ -4,7 +4,7 @@
  *
  *   TrueTypeGX/AAT trak table validation (body).
  *
- * Copyright (C) 2004-2023 by
+ * Copyright (C) 2004-2024 by
  * suzuki toshiya, Masatake YAMATO, Red Hat K.K.,
  * David Turner, Robert Wilhelm, and Werner Lemberg.
  *
diff --git a/vendor/freetype/src/gzip/README.freetype b/vendor/freetype/src/gzip/README.freetype
index 76298b06b5..29304308fd 100644
--- a/vendor/freetype/src/gzip/README.freetype
+++ b/vendor/freetype/src/gzip/README.freetype
@@ -1,7 +1,7 @@
 Name: zlib
 Short Name: zlib
 URL: http://zlib.net/
-Version: 1.2.13
+Version: 1.3
 License: see `zlib.h`
 
 Description:
@@ -19,5 +19,4 @@ The files in this directory have been prepared as follows.
  - Take the unmodified source code files from the zlib distribution that are
    included by `ftgzip.c`.
  - Copy `zconf.h` to `ftzconf.h` (which stays unmodified otherwise).
- - Run zlib's `zlib2ansi` script on all `.c` files.
  - Apply the diff file(s) in the `patches` folder.
diff --git a/vendor/freetype/src/gzip/adler32.c b/vendor/freetype/src/gzip/adler32.c
index aa032e1ddf..260185b672 100644
--- a/vendor/freetype/src/gzip/adler32.c
+++ b/vendor/freetype/src/gzip/adler32.c
@@ -7,10 +7,6 @@
 
 #include "zutil.h"
 
-#ifndef Z_FREETYPE
-local uLong adler32_combine_ OF((uLong adler1, uLong adler2, z_off64_t len2));
-#endif
-
 #define BASE 65521U     /* largest prime smaller than 65536 */
 #define NMAX 5552
 /* NMAX is the largest n such that 255n(n+1)/2 + (n+1)(BASE-1) <= 2^32-1 */
@@ -62,11 +58,7 @@ local uLong adler32_combine_ OF((uLong adler1, uLong adler2, z_off64_t len2));
 #endif
 
 /* ========================================================================= */
-uLong ZEXPORT adler32_z(
-    uLong adler,
-    const Bytef *buf,
-    z_size_t len)
-{
+uLong ZEXPORT adler32_z(uLong adler, const Bytef *buf, z_size_t len) {
     unsigned long sum2;
     unsigned n;
 
@@ -133,22 +125,14 @@ uLong ZEXPORT adler32_z(
 }
 
 /* ========================================================================= */
-uLong ZEXPORT adler32(
-    uLong adler,
-    const Bytef *buf,
-    uInt len)
-{
+uLong ZEXPORT adler32(uLong adler, const Bytef *buf, uInt len) {
     return adler32_z(adler, buf, len);
 }
 
 #ifndef Z_FREETYPE
 
 /* ========================================================================= */
-local uLong adler32_combine_(
-    uLong adler1,
-    uLong adler2,
-    z_off64_t len2)
-{
+local uLong adler32_combine_(uLong adler1, uLong adler2, z_off64_t len2) {
     unsigned long sum1;
     unsigned long sum2;
     unsigned rem;
@@ -173,19 +157,11 @@ local uLong adler32_combine_(
 }
 
 /* ========================================================================= */
-uLong ZEXPORT adler32_combine(
-    uLong adler1,
-    uLong adler2,
-    z_off_t len2)
-{
+uLong ZEXPORT adler32_combine(uLong adler1, uLong adler2, z_off_t len2) {
     return adler32_combine_(adler1, adler2, len2);
 }
 
-uLong ZEXPORT adler32_combine64(
-    uLong adler1,
-    uLong adler2,
-    z_off64_t len2)
-{
+uLong ZEXPORT adler32_combine64(uLong adler1, uLong adler2, z_off64_t len2) {
     return adler32_combine_(adler1, adler2, len2);
 }
 
diff --git a/vendor/freetype/src/gzip/crc32.c b/vendor/freetype/src/gzip/crc32.c
index 6cd1b09d56..27487dcc25 100644
--- a/vendor/freetype/src/gzip/crc32.c
+++ b/vendor/freetype/src/gzip/crc32.c
@@ -103,21 +103,6 @@
 #  define ARMCRC32
 #endif
 
-#ifndef Z_FREETYPE
-/* Local functions. */
-local z_crc_t multmodp OF((z_crc_t a, z_crc_t b));
-local z_crc_t x2nmodp OF((z_off64_t n, unsigned k));
-#endif  /* Z_FREETYPE */
-
-#if defined(W) && (!defined(ARMCRC32) || defined(DYNAMIC_CRC_TABLE))
-    local z_word_t byte_swap OF((z_word_t word));
-#endif
-
-#if defined(W) && !defined(ARMCRC32)
-    local z_crc_t crc_word OF((z_word_t data));
-    local z_word_t crc_word_big OF((z_word_t data));
-#endif
-
 #if defined(W) && (!defined(ARMCRC32) || defined(DYNAMIC_CRC_TABLE))
 /*
   Swap the bytes in a z_word_t to convert between little and big endian. Any
@@ -125,9 +110,7 @@ local z_crc_t x2nmodp OF((z_off64_t n, unsigned k));
   instruction, if one is available. This assumes that word_t is either 32 bits
   or 64 bits.
  */
-local z_word_t byte_swap(
-    z_word_t word)
-{
+local z_word_t byte_swap(z_word_t word) {
 #  if W == 8
     return
         (word & 0xff00000000000000) >> 56 |
@@ -148,24 +131,81 @@ local z_word_t byte_swap(
 }
 #endif
 
+#ifdef DYNAMIC_CRC_TABLE
+/* =========================================================================
+ * Table of powers of x for combining CRC-32s, filled in by make_crc_table()
+ * below.
+ */
+   local z_crc_t FAR x2n_table[32];
+#else
+/* =========================================================================
+ * Tables for byte-wise and braided CRC-32 calculations, and a table of powers
+ * of x for combining CRC-32s, all made by make_crc_table().
+ */
+#  include "crc32.h"
+#endif
+
 /* CRC polynomial. */
 #define POLY 0xedb88320         /* p(x) reflected, with x^32 implied */
 
-#ifdef DYNAMIC_CRC_TABLE
+#ifndef Z_FREETYPE
 
+/*
+  Return a(x) multiplied by b(x) modulo p(x), where p(x) is the CRC polynomial,
+  reflected. For speed, this requires that a not be zero.
+ */
+local z_crc_t multmodp(z_crc_t a, z_crc_t b) {
+    z_crc_t m, p;
+
+    m = (z_crc_t)1 << 31;
+    p = 0;
+    for (;;) {
+        if (a & m) {
+            p ^= b;
+            if ((a & (m - 1)) == 0)
+                break;
+        }
+        m >>= 1;
+        b = b & 1 ? (b >> 1) ^ POLY : b >> 1;
+    }
+    return p;
+}
+
+/*
+  Return x^(n * 2^k) modulo p(x). Requires that x2n_table[] has been
+  initialized.
+ */
+local z_crc_t x2nmodp(z_off64_t n, unsigned k) {
+    z_crc_t p;
+
+    p = (z_crc_t)1 << 31;           /* x^0 == 1 */
+    while (n) {
+        if (n & 1)
+            p = multmodp(x2n_table[k & 31], p);
+        n >>= 1;
+        k++;
+    }
+    return p;
+}
+
+#endif  /* !Z_FREETYPE */
+
+#ifdef DYNAMIC_CRC_TABLE
+/* =========================================================================
+ * Build the tables for byte-wise and braided CRC-32 calculations, and a table
+ * of powers of x for combining CRC-32s.
+ */
 local z_crc_t FAR crc_table[256];
-local z_crc_t FAR x2n_table[32];
-local void make_crc_table OF((void));
 #ifdef W
    local z_word_t FAR crc_big_table[256];
    local z_crc_t FAR crc_braid_table[W][256];
    local z_word_t FAR crc_braid_big_table[W][256];
-   local void braid OF((z_crc_t [][256], z_word_t [][256], int, int));
+   local void braid(z_crc_t [][256], z_word_t [][256], int, int);
 #endif
 #ifdef MAKECRCH
-   local void write_table OF((FILE *, const z_crc_t FAR *, int));
-   local void write_table32hi OF((FILE *, const z_word_t FAR *, int));
-   local void write_table64 OF((FILE *, const z_word_t FAR *, int));
+   local void write_table(FILE *, const z_crc_t FAR *, int);
+   local void write_table32hi(FILE *, const z_word_t FAR *, int);
+   local void write_table64(FILE *, const z_word_t FAR *, int);
 #endif /* MAKECRCH */
 
 /*
@@ -178,7 +218,6 @@ local void make_crc_table OF((void));
 
 /* Definition of once functionality. */
 typedef struct once_s once_t;
-local void once OF((once_t *, void (*)(void)));
 
 /* Check for the availability of atomics. */
 #if defined(__STDC__) && __STDC_VERSION__ >= 201112L && \
@@ -198,10 +237,7 @@ struct once_s {
   invoke once() at the same time. The state must be a once_t initialized with
   ONCE_INIT.
  */
-local void once(state, init)
-    once_t *state;
-    void (*init)(void);
-{
+local void once(once_t *state, void (*init)(void)) {
     if (!atomic_load(&state->done)) {
         if (atomic_flag_test_and_set(&state->begun))
             while (!atomic_load(&state->done))
@@ -224,10 +260,7 @@ struct once_s {
 
 /* Test and set. Alas, not atomic, but tries to minimize the period of
    vulnerability. */
-local int test_and_set OF((int volatile *));
-local int test_and_set(
-    int volatile *flag)
-{
+local int test_and_set(int volatile *flag) {
     int was;
 
     was = *flag;
@@ -236,10 +269,7 @@ local int test_and_set(
 }
 
 /* Run the provided init() function once. This is not thread-safe. */
-local void once(state, init)
-    once_t *state;
-    void (*init)(void);
-{
+local void once(once_t *state, void (*init)(void)) {
     if (!state->done) {
         if (test_and_set(&state->begun))
             while (!state->done)
@@ -281,8 +311,7 @@ local once_t made = ONCE_INIT;
   combinations of CRC register values and incoming bytes.
  */
 
-local void make_crc_table()
-{
+local void make_crc_table(void) {
     unsigned i, j, n;
     z_crc_t p;
 
@@ -449,11 +478,7 @@ local void make_crc_table()
    Write the 32-bit values in table[0..k-1] to out, five per line in
    hexadecimal separated by commas.
  */
-local void write_table(
-    FILE *out,
-    const z_crc_t FAR *table,
-    int k)
-{
+local void write_table(FILE *out, const z_crc_t FAR *table, int k) {
     int n;
 
     for (n = 0; n < k; n++)
@@ -466,11 +491,7 @@ local void write_table(
    Write the high 32-bits of each value in table[0..k-1] to out, five per line
    in hexadecimal separated by commas.
  */
-local void write_table32hi(
-    FILE *out,
-    const z_word_t FAR *table,
-    int k)
-{
+local void write_table32hi(FILE *out, const z_word_t FAR *table, int k) {
     int n;
 
     for (n = 0; n < k; n++)
@@ -486,11 +507,7 @@ local void write_table32hi(
   bits. If not, then the type cast and format string can be adjusted
   accordingly.
  */
-local void write_table64(
-    FILE *out,
-    const z_word_t FAR *table,
-    int k)
-{
+local void write_table64(FILE *out, const z_word_t FAR *table, int k) {
     int n;
 
     for (n = 0; n < k; n++)
@@ -500,8 +517,7 @@ local void write_table64(
 }
 
 /* Actually do the deed. */
-int main()
-{
+int main(void) {
     make_crc_table();
     return 0;
 }
@@ -513,12 +529,7 @@ int main()
   Generate the little and big-endian braid tables for the given n and z_word_t
   size w. Each array must have room for w blocks of 256 elements.
  */
-local void braid(ltl, big, n, w)
-    z_crc_t ltl[][256];
-    z_word_t big[][256];
-    int n;
-    int w;
-{
+local void braid(z_crc_t ltl[][256], z_word_t big[][256], int n, int w) {
     int k;
     z_crc_t i, p, q;
     for (k = 0; k < w; k++) {
@@ -533,78 +544,22 @@ local void braid(ltl, big, n, w)
 }
 #endif
 
-#else /* !DYNAMIC_CRC_TABLE */
-/* ========================================================================
- * Tables for byte-wise and braided CRC-32 calculations, and a table of powers
- * of x for combining CRC-32s, all made by make_crc_table().
- */
-#include "crc32.h"
 #endif /* DYNAMIC_CRC_TABLE */
 
-/* ========================================================================
- * Routines used for CRC calculation. Some are also required for the table
- * generation above.
- */
-
 #ifndef Z_FREETYPE
 
-/*
-  Return a(x) multiplied by b(x) modulo p(x), where p(x) is the CRC polynomial,
-  reflected. For speed, this requires that a not be zero.
- */
-local z_crc_t multmodp(
-    z_crc_t a,
-    z_crc_t b)
-{
-    z_crc_t m, p;
-
-    m = (z_crc_t)1 << 31;
-    p = 0;
-    for (;;) {
-        if (a & m) {
-            p ^= b;
-            if ((a & (m - 1)) == 0)
-                break;
-        }
-        m >>= 1;
-        b = b & 1 ? (b >> 1) ^ POLY : b >> 1;
-    }
-    return p;
-}
-
-/*
-  Return x^(n * 2^k) modulo p(x). Requires that x2n_table[] has been
-  initialized.
- */
-local z_crc_t x2nmodp(
-    z_off64_t n,
-    unsigned k)
-{
-    z_crc_t p;
-
-    p = (z_crc_t)1 << 31;           /* x^0 == 1 */
-    while (n) {
-        if (n & 1)
-            p = multmodp(x2n_table[k & 31], p);
-        n >>= 1;
-        k++;
-    }
-    return p;
-}
-
 /* =========================================================================
  * This function can be used by asm versions of crc32(), and to force the
  * generation of the CRC tables in a threaded application.
  */
-const z_crc_t FAR * ZEXPORT get_crc_table()
-{
+const z_crc_t FAR * ZEXPORT get_crc_table(void) {
 #ifdef DYNAMIC_CRC_TABLE
     once(&made, make_crc_table);
 #endif /* DYNAMIC_CRC_TABLE */
     return (const z_crc_t FAR *)crc_table;
 }
 
-#endif  /* Z_FREETYPE */
+#endif   /* !Z_FREETYPE */
 
 /* =========================================================================
  * Use ARM machine instructions if available. This will compute the CRC about
@@ -625,11 +580,8 @@ const z_crc_t FAR * ZEXPORT get_crc_table()
 #define Z_BATCH_ZEROS 0xa10d3d0c    /* computed from Z_BATCH = 3990 */
 #define Z_BATCH_MIN 800             /* fewest words in a final batch */
 
-unsigned long ZEXPORT crc32_z(
-    unsigned long crc,
-    const unsigned char FAR *buf,
-    z_size_t len)
-{
+unsigned long ZEXPORT crc32_z(unsigned long crc, const unsigned char FAR *buf,
+                              z_size_t len) {
     z_crc_t val;
     z_word_t crc1, crc2;
     const z_word_t *word;
@@ -729,18 +681,14 @@ unsigned long ZEXPORT crc32_z(
   least-significant byte of the word as the first byte of data, without any pre
   or post conditioning. This is used to combine the CRCs of each braid.
  */
-local z_crc_t crc_word(
-    z_word_t data)
-{
+local z_crc_t crc_word(z_word_t data) {
     int k;
     for (k = 0; k < W; k++)
         data = (data >> 8) ^ crc_table[data & 0xff];
     return (z_crc_t)data;
 }
 
-local z_word_t crc_word_big(
-    z_word_t data)
-{
+local z_word_t crc_word_big(z_word_t data) {
     int k;
     for (k = 0; k < W; k++)
         data = (data << 8) ^
@@ -751,11 +699,8 @@ local z_word_t crc_word_big(
 #endif
 
 /* ========================================================================= */
-unsigned long ZEXPORT crc32_z(
-    unsigned long crc,
-    const unsigned char FAR *buf,
-    z_size_t len)
-{
+unsigned long ZEXPORT crc32_z(unsigned long crc, const unsigned char FAR *buf,
+                              z_size_t len) {
     /* Return initial CRC, if requested. */
     if (buf == Z_NULL) return 0;
 
@@ -787,8 +732,8 @@ unsigned long ZEXPORT crc32_z(
         words = (z_word_t const *)buf;
 
         /* Do endian check at execution time instead of compile time, since ARM
-           processors can change the endianess at execution time. If the
-           compiler knows what the endianess will be, it can optimize out the
+           processors can change the endianness at execution time. If the
+           compiler knows what the endianness will be, it can optimize out the
            check and the unused branch. */
         endian = 1;
         if (*(unsigned char *)&endian) {
@@ -1075,22 +1020,15 @@ unsigned long ZEXPORT crc32_z(
 #endif
 
 /* ========================================================================= */
-unsigned long ZEXPORT crc32(
-    unsigned long crc,
-    const unsigned char FAR *buf,
-    uInt len)
-{
+unsigned long ZEXPORT crc32(unsigned long crc, const unsigned char FAR *buf,
+                            uInt len) {
     return crc32_z(crc, buf, len);
 }
 
 #ifndef Z_FREETYPE
 
 /* ========================================================================= */
-uLong ZEXPORT crc32_combine64(
-    uLong crc1,
-    uLong crc2,
-    z_off64_t len2)
-{
+uLong ZEXPORT crc32_combine64(uLong crc1, uLong crc2, z_off64_t len2) {
 #ifdef DYNAMIC_CRC_TABLE
     once(&made, make_crc_table);
 #endif /* DYNAMIC_CRC_TABLE */
@@ -1098,18 +1036,12 @@ uLong ZEXPORT crc32_combine64(
 }
 
 /* ========================================================================= */
-uLong ZEXPORT crc32_combine(
-    uLong crc1,
-    uLong crc2,
-    z_off_t len2)
-{
+uLong ZEXPORT crc32_combine(uLong crc1, uLong crc2, z_off_t len2) {
     return crc32_combine64(crc1, crc2, (z_off64_t)len2);
 }
 
 /* ========================================================================= */
-uLong ZEXPORT crc32_combine_gen64(
-    z_off64_t len2)
-{
+uLong ZEXPORT crc32_combine_gen64(z_off64_t len2) {
 #ifdef DYNAMIC_CRC_TABLE
     once(&made, make_crc_table);
 #endif /* DYNAMIC_CRC_TABLE */
@@ -1117,19 +1049,13 @@ uLong ZEXPORT crc32_combine_gen64(
 }
 
 /* ========================================================================= */
-uLong ZEXPORT crc32_combine_gen(
-    z_off_t len2)
-{
+uLong ZEXPORT crc32_combine_gen(z_off_t len2) {
     return crc32_combine_gen64((z_off64_t)len2);
 }
 
 /* ========================================================================= */
-uLong ZEXPORT crc32_combine_op(
-    uLong crc1,
-    uLong crc2,
-    uLong op)
-{
+uLong ZEXPORT crc32_combine_op(uLong crc1, uLong crc2, uLong op) {
     return multmodp(op, crc1) ^ (crc2 & 0xffffffff);
 }
 
-#endif  /* Z_FREETYPE */
+#endif  /* !Z_FREETYPE */
diff --git a/vendor/freetype/src/gzip/ftgzip.c b/vendor/freetype/src/gzip/ftgzip.c
index ca6a2aabe6..f77377ef9a 100644
--- a/vendor/freetype/src/gzip/ftgzip.c
+++ b/vendor/freetype/src/gzip/ftgzip.c
@@ -8,7 +8,7 @@
  * parse compressed PCF fonts, as found with many X11 server
  * distributions.
  *
- * Copyright (C) 2002-2023 by
+ * Copyright (C) 2002-2024 by
  * David Turner, Robert Wilhelm, and Werner Lemberg.
  *
  * This file is part of the FreeType project, and may only be used,
diff --git a/vendor/freetype/src/gzip/ftzconf.h b/vendor/freetype/src/gzip/ftzconf.h
index bf977d3e70..fb76ffe312 100644
--- a/vendor/freetype/src/gzip/ftzconf.h
+++ b/vendor/freetype/src/gzip/ftzconf.h
@@ -241,7 +241,11 @@
 #endif
 
 #ifdef Z_SOLO
-   typedef unsigned long z_size_t;
+#  ifdef _WIN64
+     typedef unsigned long long z_size_t;
+#  else
+     typedef unsigned long z_size_t;
+#  endif
 #else
 #  define z_longlong long long
 #  if defined(NO_SIZE_T)
@@ -520,7 +524,7 @@ typedef uLong FAR uLongf;
 #if !defined(_WIN32) && defined(Z_LARGE64)
 #  define z_off64_t off64_t
 #else
-#  if defined(_WIN32) && !defined(__GNUC__) && !defined(Z_SOLO)
+#  if defined(_WIN32) && !defined(__GNUC__)
 #    define z_off64_t __int64
 #  else
 #    define z_off64_t z_off_t
diff --git a/vendor/freetype/src/gzip/gzguts.h b/vendor/freetype/src/gzip/gzguts.h
index 4f09a52a7a..f9a250b856 100644
--- a/vendor/freetype/src/gzip/gzguts.h
+++ b/vendor/freetype/src/gzip/gzguts.h
@@ -7,9 +7,8 @@
 #  ifndef _LARGEFILE_SOURCE
 #    define _LARGEFILE_SOURCE 1
 #  endif
-#  ifdef _FILE_OFFSET_BITS
-#    undef _FILE_OFFSET_BITS
-#  endif
+#  undef _FILE_OFFSET_BITS
+#  undef _TIME_BITS
 #endif
 
 #ifdef HAVE_HIDDEN
@@ -119,8 +118,8 @@
 
 /* gz* functions always use library allocation functions */
 #ifndef STDC
-  extern voidp  malloc OF((uInt size));
-  extern void   free   OF((voidpf ptr));
+  extern voidp  malloc(uInt size);
+  extern void   free(voidpf ptr);
 #endif
 
 /* get errno and strerror definition */
@@ -138,10 +137,10 @@
 
 /* provide prototypes for these when building zlib without LFS */
 #if !defined(_LARGEFILE64_SOURCE) || _LFS64_LARGEFILE-0 == 0
-    ZEXTERN gzFile ZEXPORT gzopen64 OF((const char *, const char *));
-    ZEXTERN z_off64_t ZEXPORT gzseek64 OF((gzFile, z_off64_t, int));
-    ZEXTERN z_off64_t ZEXPORT gztell64 OF((gzFile));
-    ZEXTERN z_off64_t ZEXPORT gzoffset64 OF((gzFile));
+    ZEXTERN gzFile ZEXPORT gzopen64(const char *, const char *);
+    ZEXTERN z_off64_t ZEXPORT gzseek64(gzFile, z_off64_t, int);
+    ZEXTERN z_off64_t ZEXPORT gztell64(gzFile);
+    ZEXTERN z_off64_t ZEXPORT gzoffset64(gzFile);
 #endif
 
 /* default memLevel */
@@ -203,9 +202,9 @@ typedef struct {
 typedef gz_state FAR *gz_statep;
 
 /* shared functions */
-void ZLIB_INTERNAL gz_error OF((gz_statep, int, const char *));
+void ZLIB_INTERNAL gz_error(gz_statep, int, const char *);
 #if defined UNDER_CE
-char ZLIB_INTERNAL *gz_strwinerror OF((DWORD error));
+char ZLIB_INTERNAL *gz_strwinerror(DWORD error);
 #endif
 
 /* GT_OFF(x), where x is an unsigned value, is true if x > maximum z_off64_t
@@ -214,6 +213,6 @@ char ZLIB_INTERNAL *gz_strwinerror OF((DWORD error));
 #ifdef INT_MAX
 #  define GT_OFF(x) (sizeof(int) == sizeof(z_off64_t) && (x) > INT_MAX)
 #else
-unsigned ZLIB_INTERNAL gz_intmax OF((void));
+unsigned ZLIB_INTERNAL gz_intmax(void);
 #  define GT_OFF(x) (sizeof(int) == sizeof(z_off64_t) && (x) > gz_intmax())
 #endif
diff --git a/vendor/freetype/src/gzip/inffast.c b/vendor/freetype/src/gzip/inffast.c
index 809737b13c..9354676e78 100644
--- a/vendor/freetype/src/gzip/inffast.c
+++ b/vendor/freetype/src/gzip/inffast.c
@@ -47,10 +47,7 @@
       requires strm->avail_out >= 258 for each loop to avoid checking for
       output space.
  */
-void ZLIB_INTERNAL inflate_fast(
-    z_streamp strm,
-    unsigned start)
-{
+void ZLIB_INTERNAL inflate_fast(z_streamp strm, unsigned start) {
     struct inflate_state FAR *state;
     z_const unsigned char FAR *in;      /* local strm->next_in */
     z_const unsigned char FAR *last;    /* have enough input while in < last */
diff --git a/vendor/freetype/src/gzip/inffast.h b/vendor/freetype/src/gzip/inffast.h
index 684ae878c1..a38c5be450 100644
--- a/vendor/freetype/src/gzip/inffast.h
+++ b/vendor/freetype/src/gzip/inffast.h
@@ -8,4 +8,4 @@
    subject to change. Applications should only use zlib.h.
  */
 
-static void ZLIB_INTERNAL inflate_fast OF((z_streamp strm, unsigned start));
+static void ZLIB_INTERNAL inflate_fast(z_streamp strm, unsigned start);
diff --git a/vendor/freetype/src/gzip/inflate.c b/vendor/freetype/src/gzip/inflate.c
index 5117e2e26a..f7ed5d1813 100644
--- a/vendor/freetype/src/gzip/inflate.c
+++ b/vendor/freetype/src/gzip/inflate.c
@@ -91,22 +91,7 @@
 #  endif
 #endif
 
-/* function prototypes */
-local int inflateStateCheck OF((z_streamp strm));
-local void fixedtables OF((struct inflate_state FAR *state));
-local int updatewindow OF((z_streamp strm, const unsigned char FAR *end,
-                           unsigned copy));
-#ifdef BUILDFIXED
-   void makefixed OF((void));
-#endif
-#ifndef Z_FREETYPE
-local unsigned syncsearch OF((unsigned FAR *have, const unsigned char FAR *buf,
-                              unsigned len));
-#endif
-
-local int inflateStateCheck(
-    z_streamp strm)
-{
+local int inflateStateCheck(z_streamp strm) {
     struct inflate_state FAR *state;
     if (strm == Z_NULL ||
         strm->zalloc == (alloc_func)0 || strm->zfree == (free_func)0)
@@ -118,9 +103,7 @@ local int inflateStateCheck(
     return 0;
 }
 
-int ZEXPORT inflateResetKeep(
-    z_streamp strm)
-{
+int ZEXPORT inflateResetKeep(z_streamp strm) {
     struct inflate_state FAR *state;
 
     if (inflateStateCheck(strm)) return Z_STREAM_ERROR;
@@ -144,9 +127,7 @@ int ZEXPORT inflateResetKeep(
     return Z_OK;
 }
 
-int ZEXPORT inflateReset(
-    z_streamp strm)
-{
+int ZEXPORT inflateReset(z_streamp strm) {
     struct inflate_state FAR *state;
 
     if (inflateStateCheck(strm)) return Z_STREAM_ERROR;
@@ -157,10 +138,7 @@ int ZEXPORT inflateReset(
     return inflateResetKeep(strm);
 }
 
-int ZEXPORT inflateReset2(
-    z_streamp strm,
-    int windowBits)
-{
+int ZEXPORT inflateReset2(z_streamp strm, int windowBits) {
     int wrap;
     struct inflate_state FAR *state;
 
@@ -197,12 +175,8 @@ int ZEXPORT inflateReset2(
     return inflateReset(strm);
 }
 
-int ZEXPORT inflateInit2_(
-    z_streamp strm,
-    int windowBits,
-    const char *version,
-    int stream_size)
-{
+int ZEXPORT inflateInit2_(z_streamp strm, int windowBits,
+                          const char *version, int stream_size) {
     int ret;
     struct inflate_state FAR *state;
 
@@ -243,22 +217,17 @@ int ZEXPORT inflateInit2_(
 
 #ifndef Z_FREETYPE
 
-int ZEXPORT inflateInit_(
-    z_streamp strm,
-    const char *version,
-    int stream_size)
-{
+int ZEXPORT inflateInit_(z_streamp strm, const char *version,
+                         int stream_size) {
     return inflateInit2_(strm, DEF_WBITS, version, stream_size);
 }
 
-int ZEXPORT inflatePrime(
-    z_streamp strm,
-    int bits,
-    int value)
-{
+int ZEXPORT inflatePrime(z_streamp strm, int bits, int value) {
     struct inflate_state FAR *state;
 
     if (inflateStateCheck(strm)) return Z_STREAM_ERROR;
+    if (bits == 0)
+        return Z_OK;
     state = (struct inflate_state FAR *)strm->state;
     if (bits < 0) {
         state->hold = 0;
@@ -284,9 +253,7 @@ int ZEXPORT inflatePrime(
    used for threaded applications, since the rewriting of the tables and virgin
    may not be thread-safe.
  */
-local void fixedtables(
-    struct inflate_state FAR *state)
-{
+local void fixedtables(struct inflate_state FAR *state) {
 #ifdef BUILDFIXED
     static int virgin = 1;
     static code *lenfix, *distfix;
@@ -348,7 +315,7 @@ local void fixedtables(
 
     a.out > inffixed.h
  */
-void makefixed()
+void makefixed(void)
 {
     unsigned low, size;
     struct inflate_state state;
@@ -402,11 +369,7 @@ void makefixed()
    output will fall in the output data, making match copies simpler and faster.
    The advantage may be dependent on the size of the processor's data caches.
  */
-local int updatewindow(
-    z_streamp strm,
-    const Bytef *end,
-    unsigned copy)
-{
+local int updatewindow(z_streamp strm, const Bytef *end, unsigned copy) {
     struct inflate_state FAR *state;
     unsigned dist;
 
@@ -628,10 +591,7 @@ local int updatewindow(
    will return Z_BUF_ERROR if it has not reached the end of the stream.
  */
 
-int ZEXPORT inflate(
-    z_streamp strm,
-    int flush)
-{
+int ZEXPORT inflate(z_streamp strm, int flush) {
     struct inflate_state FAR *state;
     z_const unsigned char FAR *next;    /* next input */
     unsigned char FAR *put;     /* next output */
@@ -1307,9 +1267,7 @@ int ZEXPORT inflate(
     return ret;
 }
 
-int ZEXPORT inflateEnd(
-    z_streamp strm)
-{
+int ZEXPORT inflateEnd(z_streamp strm) {
     struct inflate_state FAR *state;
     if (inflateStateCheck(strm))
         return Z_STREAM_ERROR;
@@ -1323,11 +1281,8 @@ int ZEXPORT inflateEnd(
 
 #ifndef Z_FREETYPE
 
-int ZEXPORT inflateGetDictionary(
-    z_streamp strm,
-    Bytef *dictionary,
-    uInt *dictLength)
-{
+int ZEXPORT inflateGetDictionary(z_streamp strm, Bytef *dictionary,
+                                 uInt *dictLength) {
     struct inflate_state FAR *state;
 
     /* check state */
@@ -1346,11 +1301,8 @@ int ZEXPORT inflateGetDictionary(
     return Z_OK;
 }
 
-int ZEXPORT inflateSetDictionary(
-    z_streamp strm,
-    const Bytef *dictionary,
-    uInt dictLength)
-{
+int ZEXPORT inflateSetDictionary(z_streamp strm, const Bytef *dictionary,
+                                 uInt dictLength) {
     struct inflate_state FAR *state;
     unsigned long dictid;
     int ret;
@@ -1381,10 +1333,7 @@ int ZEXPORT inflateSetDictionary(
     return Z_OK;
 }
 
-int ZEXPORT inflateGetHeader(
-    z_streamp strm,
-    gz_headerp head)
-{
+int ZEXPORT inflateGetHeader(z_streamp strm, gz_headerp head) {
     struct inflate_state FAR *state;
 
     /* check state */
@@ -1409,11 +1358,8 @@ int ZEXPORT inflateGetHeader(
    called again with more data and the *have state.  *have is initialized to
    zero for the first call.
  */
-local unsigned syncsearch(
-    unsigned FAR *have,
-    const unsigned char FAR *buf,
-    unsigned len)
-{
+local unsigned syncsearch(unsigned FAR *have, const unsigned char FAR *buf,
+                          unsigned len) {
     unsigned got;
     unsigned next;
 
@@ -1432,9 +1378,7 @@ local unsigned syncsearch(
     return next;
 }
 
-int ZEXPORT inflateSync(
-    z_streamp strm)
-{
+int ZEXPORT inflateSync(z_streamp strm) {
     unsigned len;               /* number of bytes to look at or looked at */
     int flags;                  /* temporary to save header status */
     unsigned long in, out;      /* temporary to save total_in and total_out */
@@ -1490,9 +1434,7 @@ int ZEXPORT inflateSync(
    block. When decompressing, PPP checks that at the end of input packet,
    inflate is waiting for these length bytes.
  */
-int ZEXPORT inflateSyncPoint(
-    z_streamp strm)
-{
+int ZEXPORT inflateSyncPoint(z_streamp strm) {
     struct inflate_state FAR *state;
 
     if (inflateStateCheck(strm)) return Z_STREAM_ERROR;
@@ -1500,10 +1442,7 @@ int ZEXPORT inflateSyncPoint(
     return state->mode == STORED && state->bits == 0;
 }
 
-int ZEXPORT inflateCopy(
-    z_streamp dest,
-    z_streamp source)
-{
+int ZEXPORT inflateCopy(z_streamp dest, z_streamp source) {
     struct inflate_state FAR *state;
     struct inflate_state FAR *copy;
     unsigned char FAR *window;
@@ -1547,10 +1486,7 @@ int ZEXPORT inflateCopy(
     return Z_OK;
 }
 
-int ZEXPORT inflateUndermine(
-    z_streamp strm,
-    int subvert)
-{
+int ZEXPORT inflateUndermine(z_streamp strm, int subvert) {
     struct inflate_state FAR *state;
 
     if (inflateStateCheck(strm)) return Z_STREAM_ERROR;
@@ -1565,10 +1501,7 @@ int ZEXPORT inflateUndermine(
 #endif
 }
 
-int ZEXPORT inflateValidate(
-    z_streamp strm,
-    int check)
-{
+int ZEXPORT inflateValidate(z_streamp strm, int check) {
     struct inflate_state FAR *state;
 
     if (inflateStateCheck(strm)) return Z_STREAM_ERROR;
@@ -1580,9 +1513,7 @@ int ZEXPORT inflateValidate(
     return Z_OK;
 }
 
-long ZEXPORT inflateMark(
-    z_streamp strm)
-{
+long ZEXPORT inflateMark(z_streamp strm) {
     struct inflate_state FAR *state;
 
     if (inflateStateCheck(strm))
@@ -1593,9 +1524,7 @@ long ZEXPORT inflateMark(
             (state->mode == MATCH ? state->was - state->length : 0));
 }
 
-unsigned long ZEXPORT inflateCodesUsed(
-    z_streamp strm)
-{
+unsigned long ZEXPORT inflateCodesUsed(z_streamp strm) {
     struct inflate_state FAR *state;
     if (inflateStateCheck(strm)) return (unsigned long)-1;
     state = (struct inflate_state FAR *)strm->state;
diff --git a/vendor/freetype/src/gzip/inflate.h b/vendor/freetype/src/gzip/inflate.h
index c6f5a52e16..8a0e437aea 100644
--- a/vendor/freetype/src/gzip/inflate.h
+++ b/vendor/freetype/src/gzip/inflate.h
@@ -128,4 +128,4 @@ struct inflate_state {
     unsigned was;               /* initial length of match */
 };
 
-#endif  /* INFLATE_H */
+#endif  /* !INFLATE_H */
diff --git a/vendor/freetype/src/gzip/inftrees.c b/vendor/freetype/src/gzip/inftrees.c
index dd4965e9a8..1fd655593a 100644
--- a/vendor/freetype/src/gzip/inftrees.c
+++ b/vendor/freetype/src/gzip/inftrees.c
@@ -1,5 +1,5 @@
 /* inftrees.c -- generate Huffman trees for efficient decoding
- * Copyright (C) 1995-2022 Mark Adler
+ * Copyright (C) 1995-2023 Mark Adler
  * For conditions of distribution and use, see copyright notice in zlib.h
  */
 
@@ -9,7 +9,7 @@
 #define MAXBITS 15
 
 static const char inflate_copyright[] =
-   " inflate 1.2.13 Copyright 1995-2022 Mark Adler ";
+   " inflate 1.3 Copyright 1995-2023 Mark Adler ";
 /*
   If you use the zlib library in a product, an acknowledgment is welcome
   in the documentation of your product. If for some reason you cannot
@@ -29,14 +29,9 @@ static const char inflate_copyright[] =
    table index bits.  It will differ if the request is greater than the
    longest code or if it is less than the shortest code.
  */
-int ZLIB_INTERNAL inflate_table(
-    codetype type,
-    unsigned short FAR *lens,
-    unsigned codes,
-    code FAR * FAR *table,
-    unsigned FAR *bits,
-    unsigned short FAR *work)
-{
+int ZLIB_INTERNAL inflate_table(codetype type, unsigned short FAR *lens,
+                                unsigned codes, code FAR * FAR *table,
+                                unsigned FAR *bits, unsigned short FAR *work) {
     unsigned len;               /* a code's length in bits */
     unsigned sym;               /* index of code symbols */
     unsigned min, max;          /* minimum and maximum code lengths */
@@ -62,7 +57,7 @@ int ZLIB_INTERNAL inflate_table(
         35, 43, 51, 59, 67, 83, 99, 115, 131, 163, 195, 227, 258, 0, 0};
     static const unsigned short lext[31] = { /* Length codes 257..285 extra */
         16, 16, 16, 16, 16, 16, 16, 16, 17, 17, 17, 17, 18, 18, 18, 18,
-        19, 19, 19, 19, 20, 20, 20, 20, 21, 21, 21, 21, 16, 194, 65};
+        19, 19, 19, 19, 20, 20, 20, 20, 21, 21, 21, 21, 16, 198, 203};
     static const unsigned short dbase[32] = { /* Distance codes 0..29 base */
         1, 2, 3, 4, 5, 7, 9, 13, 17, 25, 33, 49, 65, 97, 129, 193,
         257, 385, 513, 769, 1025, 1537, 2049, 3073, 4097, 6145,
diff --git a/vendor/freetype/src/gzip/inftrees.h b/vendor/freetype/src/gzip/inftrees.h
index a2207efb1f..47f726c36a 100644
--- a/vendor/freetype/src/gzip/inftrees.h
+++ b/vendor/freetype/src/gzip/inftrees.h
@@ -60,8 +60,8 @@ typedef enum {
     DISTS
 } codetype;
 
-static int ZLIB_INTERNAL inflate_table OF((codetype type, unsigned short FAR *lens,
-                             unsigned codes, code FAR * FAR *table,
-                             unsigned FAR *bits, unsigned short FAR *work));
+static int ZLIB_INTERNAL inflate_table(codetype type, unsigned short FAR *lens,
+                                unsigned codes, code FAR * FAR *table,
+                                unsigned FAR *bits, unsigned short FAR *work);
 
-#endif  /* INFTREES_H_ */
+#endif  /* !INFTREES_H */
diff --git a/vendor/freetype/src/gzip/patches/freetype-zlib.diff b/vendor/freetype/src/gzip/patches/freetype-zlib.diff
index 6ac76df62a..9486bd02aa 100644
--- a/vendor/freetype/src/gzip/patches/freetype-zlib.diff
+++ b/vendor/freetype/src/gzip/patches/freetype-zlib.diff
@@ -30,88 +30,84 @@ prevent compiler errors.
 (inflate_table): Declare as static.
 
 diff --git b/src/gzip/adler32.c a/src/gzip/adler32.c
-index be5e8a247..aa032e1dd 100644
+index 04b81d29b..260185b67 100644
 --- b/src/gzip/adler32.c
 +++ a/src/gzip/adler32.c
-@@ -7,7 +7,9 @@
- 
- #include "zutil.h"
- 
-+#ifndef Z_FREETYPE
- local uLong adler32_combine_ OF((uLong adler1, uLong adler2, z_off64_t len2));
-+#endif
- 
- #define BASE 65521U     /* largest prime smaller than 65536 */
- #define NMAX 5552
-@@ -139,6 +141,8 @@ uLong ZEXPORT adler32(
+@@ -129,6 +129,8 @@ uLong ZEXPORT adler32(uLong adler, const Bytef *buf, uInt len) {
      return adler32_z(adler, buf, len);
  }
  
 +#ifndef Z_FREETYPE
 +
  /* ========================================================================= */
- local uLong adler32_combine_(
-     uLong adler1,
-@@ -184,3 +188,5 @@ uLong ZEXPORT adler32_combine64(
- {
+ local uLong adler32_combine_(uLong adler1, uLong adler2, z_off64_t len2) {
+     unsigned long sum1;
+@@ -162,3 +164,5 @@ uLong ZEXPORT adler32_combine(uLong adler1, uLong adler2, z_off_t len2) {
+ uLong ZEXPORT adler32_combine64(uLong adler1, uLong adler2, z_off64_t len2) {
      return adler32_combine_(adler1, adler2, len2);
  }
 +
 +#endif  /* !Z_FREETYPE */
 diff --git b/src/gzip/crc32.c a/src/gzip/crc32.c
-index 3a52aa89d..6cd1b09d5 100644
+index 6c38f5c04..27487dcc2 100644
 --- b/src/gzip/crc32.c
 +++ a/src/gzip/crc32.c
-@@ -103,9 +103,11 @@
- #  define ARMCRC32
- #endif
- 
-+#ifndef Z_FREETYPE
- /* Local functions. */
- local z_crc_t multmodp OF((z_crc_t a, z_crc_t b));
- local z_crc_t x2nmodp OF((z_off64_t n, unsigned k));
-+#endif  /* Z_FREETYPE */
- 
- #if defined(W) && (!defined(ARMCRC32) || defined(DYNAMIC_CRC_TABLE))
-     local z_word_t byte_swap OF((z_word_t word));
-@@ -544,6 +546,8 @@ local void braid(ltl, big, n, w)
-  * generation above.
-  */
+@@ -148,6 +148,8 @@ local z_word_t byte_swap(z_word_t word) {
+ /* CRC polynomial. */
+ #define POLY 0xedb88320         /* p(x) reflected, with x^32 implied */
  
 +#ifndef Z_FREETYPE
 +
  /*
    Return a(x) multiplied by b(x) modulo p(x), where p(x) is the CRC polynomial,
    reflected. For speed, this requires that a not be zero.
-@@ -600,6 +604,8 @@ const z_crc_t FAR * ZEXPORT get_crc_table()
+@@ -186,6 +188,8 @@ local z_crc_t x2nmodp(z_off64_t n, unsigned k) {
+     return p;
+ }
+ 
++#endif  /* !Z_FREETYPE */
++
+ #ifdef DYNAMIC_CRC_TABLE
+ /* =========================================================================
+  * Build the tables for byte-wise and braided CRC-32 calculations, and a table
+@@ -542,6 +546,8 @@ local void braid(z_crc_t ltl[][256], z_word_t big[][256], int n, int w) {
+ 
+ #endif /* DYNAMIC_CRC_TABLE */
+ 
++#ifndef Z_FREETYPE
++
+ /* =========================================================================
+  * This function can be used by asm versions of crc32(), and to force the
+  * generation of the CRC tables in a threaded application.
+@@ -553,6 +559,8 @@ const z_crc_t FAR * ZEXPORT get_crc_table(void) {
      return (const z_crc_t FAR *)crc_table;
  }
  
-+#endif  /* Z_FREETYPE */
++#endif   /* !Z_FREETYPE */
 +
  /* =========================================================================
   * Use ARM machine instructions if available. This will compute the CRC about
   * ten times faster than the braided calculation. This code does not check for
-@@ -1077,6 +1083,8 @@ unsigned long ZEXPORT crc32(
+@@ -1017,6 +1025,8 @@ unsigned long ZEXPORT crc32(unsigned long crc, const unsigned char FAR *buf,
      return crc32_z(crc, buf, len);
  }
  
 +#ifndef Z_FREETYPE
 +
  /* ========================================================================= */
- uLong ZEXPORT crc32_combine64(
-     uLong crc1,
-@@ -1123,3 +1131,5 @@ uLong ZEXPORT crc32_combine_op(
- {
+ uLong ZEXPORT crc32_combine64(uLong crc1, uLong crc2, z_off64_t len2) {
+ #ifdef DYNAMIC_CRC_TABLE
+@@ -1047,3 +1057,5 @@ uLong ZEXPORT crc32_combine_gen(z_off_t len2) {
+ uLong ZEXPORT crc32_combine_op(uLong crc1, uLong crc2, uLong op) {
      return multmodp(op, crc1) ^ (crc2 & 0xffffffff);
  }
 +
-+#endif  /* Z_FREETYPE */
++#endif  /* !Z_FREETYPE */
 diff --git b/src/gzip/gzguts.h a/src/gzip/gzguts.h
-index 57faf3716..4f09a52a7 100644
+index f9375047e..f9a250b85 100644
 --- b/src/gzip/gzguts.h
 +++ a/src/gzip/gzguts.h
-@@ -163,7 +163,7 @@
+@@ -162,7 +162,7 @@
  
  /* values for gz_state how */
  #define LOOK 0      /* look for a gzip header */
@@ -121,40 +117,29 @@ index 57faf3716..4f09a52a7 100644
  
  /* internal gzip file state data structure */
 diff --git b/src/gzip/inffast.h a/src/gzip/inffast.h
-index e5c1aa4ca..684ae878c 100644
+index 49c6d156c..a38c5be45 100644
 --- b/src/gzip/inffast.h
 +++ a/src/gzip/inffast.h
 @@ -8,4 +8,4 @@
     subject to change. Applications should only use zlib.h.
   */
  
--void ZLIB_INTERNAL inflate_fast OF((z_streamp strm, unsigned start));
-+static void ZLIB_INTERNAL inflate_fast OF((z_streamp strm, unsigned start));
+-void ZLIB_INTERNAL inflate_fast(z_streamp strm, unsigned start);
++static void ZLIB_INTERNAL inflate_fast(z_streamp strm, unsigned start);
 diff --git b/src/gzip/inflate.c a/src/gzip/inflate.c
-index c9e566b03..5117e2e26 100644
+index b0757a9b2..f7ed5d181 100644
 --- b/src/gzip/inflate.c
 +++ a/src/gzip/inflate.c
-@@ -99,8 +99,10 @@ local int updatewindow OF((z_streamp strm, const unsigned char FAR *end,
- #ifdef BUILDFIXED
-    void makefixed OF((void));
- #endif
-+#ifndef Z_FREETYPE
- local unsigned syncsearch OF((unsigned FAR *have, const unsigned char FAR *buf,
-                               unsigned len));
-+#endif
- 
- local int inflateStateCheck(
-     z_streamp strm)
-@@ -239,6 +241,8 @@ int ZEXPORT inflateInit2_(
+@@ -215,6 +215,8 @@ int ZEXPORT inflateInit2_(z_streamp strm, int windowBits,
      return ret;
  }
  
 +#ifndef Z_FREETYPE
 +
- int ZEXPORT inflateInit_(
-     z_streamp strm,
-     const char *version,
-@@ -268,6 +272,8 @@ int ZEXPORT inflatePrime(
+ int ZEXPORT inflateInit_(z_streamp strm, const char *version,
+                          int stream_size) {
+     return inflateInit2_(strm, DEF_WBITS, version, stream_size);
+@@ -239,6 +241,8 @@ int ZEXPORT inflatePrime(z_streamp strm, int bits, int value) {
      return Z_OK;
  }
  
@@ -163,23 +148,23 @@ index c9e566b03..5117e2e26 100644
  /*
     Return state with length and distance decoding tables and index sizes set to
     fixed code decoding.  Normally this returns fixed tables from inffixed.h.
-@@ -1315,6 +1321,8 @@ int ZEXPORT inflateEnd(
+@@ -1275,6 +1279,8 @@ int ZEXPORT inflateEnd(z_streamp strm) {
      return Z_OK;
  }
  
 +#ifndef Z_FREETYPE
 +
- int ZEXPORT inflateGetDictionary(
-     z_streamp strm,
-     Bytef *dictionary,
-@@ -1593,3 +1601,5 @@ unsigned long ZEXPORT inflateCodesUsed(
+ int ZEXPORT inflateGetDictionary(z_streamp strm, Bytef *dictionary,
+                                  uInt *dictLength) {
+     struct inflate_state FAR *state;
+@@ -1524,3 +1530,5 @@ unsigned long ZEXPORT inflateCodesUsed(z_streamp strm) {
      state = (struct inflate_state FAR *)strm->state;
      return (unsigned long)(state->next - state->codes);
  }
 +
 +#endif  /* !Z_FREETYPE */
 diff --git b/src/gzip/inflate.h a/src/gzip/inflate.h
-index f127b6b1f..c6f5a52e1 100644
+index f127b6b1f..8a0e437ae 100644
 --- b/src/gzip/inflate.h
 +++ a/src/gzip/inflate.h
 @@ -3,6 +3,9 @@
@@ -197,9 +182,9 @@ index f127b6b1f..c6f5a52e1 100644
      unsigned was;               /* initial length of match */
  };
 +
-+#endif  /* INFLATE_H */
++#endif  /* !INFLATE_H */
 diff --git b/src/gzip/inftrees.c a/src/gzip/inftrees.c
-index d8405a24c..dd4965e9a 100644
+index 8a208c2da..1fd655593 100644
 --- b/src/gzip/inftrees.c
 +++ a/src/gzip/inftrees.c
 @@ -8,7 +8,7 @@
@@ -208,11 +193,11 @@ index d8405a24c..dd4965e9a 100644
  
 -const char inflate_copyright[] =
 +static const char inflate_copyright[] =
-    " inflate 1.2.13 Copyright 1995-2022 Mark Adler ";
+    " inflate 1.3 Copyright 1995-2023 Mark Adler ";
  /*
    If you use the zlib library in a product, an acknowledgment is welcome
 diff --git b/src/gzip/inftrees.h a/src/gzip/inftrees.h
-index f53665311..a2207efb1 100644
+index a10712d8c..47f726c36 100644
 --- b/src/gzip/inftrees.h
 +++ a/src/gzip/inftrees.h
 @@ -3,6 +3,9 @@
@@ -229,14 +214,14 @@ index f53665311..a2207efb1 100644
      DISTS
  } codetype;
  
--int ZLIB_INTERNAL inflate_table OF((codetype type, unsigned short FAR *lens,
-+static int ZLIB_INTERNAL inflate_table OF((codetype type, unsigned short FAR *lens,
-                              unsigned codes, code FAR * FAR *table,
-                              unsigned FAR *bits, unsigned short FAR *work));
+-int ZLIB_INTERNAL inflate_table(codetype type, unsigned short FAR *lens,
++static int ZLIB_INTERNAL inflate_table(codetype type, unsigned short FAR *lens,
+                                 unsigned codes, code FAR * FAR *table,
+                                 unsigned FAR *bits, unsigned short FAR *work);
 +
-+#endif  /* INFTREES_H_ */
++#endif  /* !INFTREES_H */
 diff --git b/src/gzip/zlib.h a/src/gzip/zlib.h
-index 953cb5012..3f2f76e3c 100644
+index 6b7244f99..5c7a884c9 100644
 --- b/src/gzip/zlib.h
 +++ a/src/gzip/zlib.h
 @@ -31,7 +31,7 @@
@@ -257,60 +242,60 @@ index 953cb5012..3f2f76e3c 100644
  #define zlib_version zlibVersion()
  /* for compatibility with versions < 1.0.2 */
  
-@@ -373,6 +375,7 @@ ZEXTERN int ZEXPORT deflateEnd OF((z_streamp strm));
+@@ -373,6 +375,7 @@ ZEXTERN int ZEXPORT deflateEnd(z_streamp strm);
     deallocated).
  */
  
 +#endif  /* !Z_FREETYPE */
  
  /*
- ZEXTERN int ZEXPORT inflateInit OF((z_streamp strm));
-@@ -534,6 +537,8 @@ ZEXTERN int ZEXPORT inflateEnd OF((z_streamp strm));
+ ZEXTERN int ZEXPORT inflateInit(z_streamp strm);
+@@ -535,6 +538,8 @@ ZEXTERN int ZEXPORT inflateEnd(z_streamp strm);
      The following functions are needed only in some special applications.
  */
  
 +#ifndef Z_FREETYPE
 +
  /*
- ZEXTERN int ZEXPORT deflateInit2 OF((z_streamp strm,
-                                      int  level,
-@@ -956,6 +961,8 @@ ZEXTERN int ZEXPORT inflateCopy OF((z_streamp dest,
+ ZEXTERN int ZEXPORT deflateInit2(z_streamp strm,
+                                  int level,
+@@ -958,6 +963,8 @@ ZEXTERN int ZEXPORT inflateCopy(z_streamp dest,
     destination.
  */
  
 +#endif  /* !Z_FREETYPE */
 +
- ZEXTERN int ZEXPORT inflateReset OF((z_streamp strm));
+ ZEXTERN int ZEXPORT inflateReset(z_streamp strm);
  /*
       This function is equivalent to inflateEnd followed by inflateInit,
-@@ -980,6 +987,8 @@ ZEXTERN int ZEXPORT inflateReset2 OF((z_streamp strm,
+@@ -983,6 +990,8 @@ ZEXTERN int ZEXPORT inflateReset2(z_streamp strm,
     the windowBits parameter is invalid.
  */
  
 +#ifndef Z_FREETYPE
 +
- ZEXTERN int ZEXPORT inflatePrime OF((z_streamp strm,
-                                      int bits,
-                                      int value));
-@@ -1069,6 +1078,8 @@ ZEXTERN int ZEXPORT inflateGetHeader OF((z_streamp strm,
+ ZEXTERN int ZEXPORT inflatePrime(z_streamp strm,
+                                  int bits,
+                                  int value);
+@@ -1072,6 +1081,8 @@ ZEXTERN int ZEXPORT inflateGetHeader(z_streamp strm,
     stream state was inconsistent.
  */
  
 +#endif  /* !Z_FREETYPE */
 +
  /*
- ZEXTERN int ZEXPORT inflateBackInit OF((z_streamp strm, int windowBits,
-                                         unsigned char FAR *window));
-@@ -1095,6 +1106,8 @@ typedef unsigned (*in_func) OF((void FAR *,
-                                 z_const unsigned char FAR * FAR *));
- typedef int (*out_func) OF((void FAR *, unsigned char FAR *, unsigned));
+ ZEXTERN int ZEXPORT inflateBackInit(z_streamp strm, int windowBits,
+                                     unsigned char FAR *window);
+@@ -1098,6 +1109,8 @@ typedef unsigned (*in_func)(void FAR *,
+                             z_const unsigned char FAR * FAR *);
+ typedef int (*out_func)(void FAR *, unsigned char FAR *, unsigned);
  
 +#ifndef Z_FREETYPE
 +
- ZEXTERN int ZEXPORT inflateBack OF((z_streamp strm,
-                                     in_func in, void FAR *in_desc,
-                                     out_func out, void FAR *out_desc));
-@@ -1214,6 +1227,8 @@ ZEXTERN uLong ZEXPORT zlibCompileFlags OF((void));
+ ZEXTERN int ZEXPORT inflateBack(z_streamp strm,
+                                 in_func in, void FAR *in_desc,
+                                 out_func out, void FAR *out_desc);
+@@ -1217,6 +1230,8 @@ ZEXTERN uLong ZEXPORT zlibCompileFlags(void);
       27-31: 0 (reserved)
   */
  
@@ -319,63 +304,61 @@ index 953cb5012..3f2f76e3c 100644
  #ifndef Z_SOLO
  
                          /* utility functions */
-@@ -1765,6 +1780,8 @@ ZEXTERN uLong ZEXPORT crc32_combine_gen OF((z_off_t len2));
+@@ -1768,6 +1783,8 @@ ZEXTERN uLong ZEXPORT crc32_combine_gen(z_off_t len2);
     crc32_combine_op().
  */
  
 +#ifndef Z_FREETYPE
 +
- ZEXTERN uLong ZEXPORT crc32_combine_op OF((uLong crc1, uLong crc2, uLong op));
+ ZEXTERN uLong ZEXPORT crc32_combine_op(uLong crc1, uLong crc2, uLong op);
  /*
       Give the same result as crc32_combine(), using op in place of len2. op is
-@@ -1822,6 +1839,19 @@ ZEXTERN int ZEXPORT inflateBackInit_ OF((z_streamp strm, int windowBits,
+@@ -1825,6 +1842,17 @@ ZEXTERN int ZEXPORT inflateBackInit_(z_streamp strm, int windowBits,
                             ZLIB_VERSION, (int)sizeof(z_stream))
  #endif
  
 +#else  /* Z_FREETYPE */
 +
-+
-+ZEXTERN int ZEXPORT inflateInit2_ OF((z_streamp strm, int  windowBits,
-+                                      const char *version, int stream_size));
++ZEXTERN int ZEXPORT inflateInit2_(z_streamp strm, int  windowBits,
++                                  const char *version, int stream_size);
 +
 +#  define inflateInit2(strm, windowBits) \
 +          inflateInit2_((strm), (windowBits), ZLIB_VERSION, \
 +                        (int)sizeof(z_stream))
 +
 +#endif  /* Z_FREETYPE */
-+
 +
  #ifndef Z_SOLO
  
  /* gzgetc() macro and its supporting function and exposed data structure.  Note
-@@ -1901,20 +1931,25 @@ ZEXTERN int ZEXPORT gzgetc_ OF((gzFile file));  /* backward compatibility */
+@@ -1904,20 +1932,25 @@ ZEXTERN int ZEXPORT gzgetc_(gzFile file);       /* backward compatibility */
  
  #else /* Z_SOLO */
  
 +#ifndef Z_FREETYPE
-    ZEXTERN uLong ZEXPORT adler32_combine OF((uLong, uLong, z_off_t));
-    ZEXTERN uLong ZEXPORT crc32_combine OF((uLong, uLong, z_off_t));
-    ZEXTERN uLong ZEXPORT crc32_combine_gen OF((z_off_t));
+    ZEXTERN uLong ZEXPORT adler32_combine(uLong, uLong, z_off_t);
+    ZEXTERN uLong ZEXPORT crc32_combine(uLong, uLong, z_off_t);
+    ZEXTERN uLong ZEXPORT crc32_combine_gen(z_off_t);
 +#endif
  
  #endif /* !Z_SOLO */
  
  /* undocumented functions */
 +#ifndef Z_FREETYPE
- ZEXTERN const char   * ZEXPORT zError           OF((int));
- ZEXTERN int            ZEXPORT inflateSyncPoint OF((z_streamp));
- ZEXTERN const z_crc_t FAR * ZEXPORT get_crc_table    OF((void));
- ZEXTERN int            ZEXPORT inflateUndermine OF((z_streamp, int));
- ZEXTERN int            ZEXPORT inflateValidate OF((z_streamp, int));
- ZEXTERN unsigned long  ZEXPORT inflateCodesUsed OF((z_streamp));
+ ZEXTERN const char   * ZEXPORT zError(int);
+ ZEXTERN int            ZEXPORT inflateSyncPoint(z_streamp);
+ ZEXTERN const z_crc_t FAR * ZEXPORT get_crc_table(void);
+ ZEXTERN int            ZEXPORT inflateUndermine(z_streamp, int);
+ ZEXTERN int            ZEXPORT inflateValidate(z_streamp, int);
+ ZEXTERN unsigned long  ZEXPORT inflateCodesUsed(z_streamp);
 +#endif  /* !Z_FREETYPE */
- ZEXTERN int            ZEXPORT inflateResetKeep OF((z_streamp));
+ ZEXTERN int            ZEXPORT inflateResetKeep(z_streamp);
 +#ifndef Z_FREETYPE
- ZEXTERN int            ZEXPORT deflateResetKeep OF((z_streamp));
+ ZEXTERN int            ZEXPORT deflateResetKeep(z_streamp);
  #if defined(_WIN32) && !defined(Z_SOLO)
- ZEXTERN gzFile         ZEXPORT gzopen_w OF((const wchar_t *path,
-@@ -1927,6 +1962,7 @@ ZEXTERN int            ZEXPORTVA gzvprintf Z_ARG((gzFile file,
-                                                   va_list va));
+ ZEXTERN gzFile         ZEXPORT gzopen_w(const wchar_t *path,
+@@ -1930,6 +1963,7 @@ ZEXTERN int            ZEXPORTVA gzvprintf(gzFile file,
+                                            va_list va);
  #  endif
  #endif
 +#endif  /* !Z_FREETYPE */
@@ -383,7 +366,7 @@ index 953cb5012..3f2f76e3c 100644
  #ifdef __cplusplus
  }
 diff --git b/src/gzip/zutil.c a/src/gzip/zutil.c
-index ef174ca64..542706ca0 100644
+index b1c5d2d3c..f76def425 100644
 --- b/src/gzip/zutil.c
 +++ a/src/gzip/zutil.c
 @@ -10,6 +10,8 @@
@@ -395,7 +378,7 @@ index ef174ca64..542706ca0 100644
  z_const char * const z_errmsg[10] = {
      (z_const char *)"need dictionary",     /* Z_NEED_DICT       2  */
      (z_const char *)"stream end",          /* Z_STREAM_END      1  */
-@@ -138,6 +140,8 @@ const char * ZEXPORT zError(
+@@ -132,6 +134,8 @@ const char * ZEXPORT zError(int err) {
      return ERR_MSG(err);
  }
  
@@ -404,16 +387,15 @@ index ef174ca64..542706ca0 100644
  #if defined(_WIN32_WCE) && _WIN32_WCE < 0x800
      /* The older Microsoft C Run-Time Library for Windows CE doesn't have
       * errno.  We define it as a global variable to simplify porting.
-@@ -159,6 +163,8 @@ void ZLIB_INTERNAL zmemcpy(
+@@ -149,6 +153,7 @@ void ZLIB_INTERNAL zmemcpy(Bytef* dest, const Bytef* source, uInt len) {
      } while (--len != 0);
  }
  
 +#ifndef Z_FREETYPE
-+
- int ZLIB_INTERNAL zmemcmp(
-     const Bytef* s1,
-     const Bytef* s2,
-@@ -181,6 +187,7 @@ void ZLIB_INTERNAL zmemzero(
+ int ZLIB_INTERNAL zmemcmp(const Bytef* s1, const Bytef* s2, uInt len) {
+     uInt j;
+ 
+@@ -164,6 +169,7 @@ void ZLIB_INTERNAL zmemzero(Bytef* dest, uInt len) {
          *dest++ = 0;  /* ??? to be unrolled */
      } while (--len != 0);
  }
@@ -422,7 +404,7 @@ index ef174ca64..542706ca0 100644
  
  #ifndef Z_SOLO
 diff --git b/src/gzip/zutil.h a/src/gzip/zutil.h
-index 0bc7f4ecd..055ba8b62 100644
+index 902a304cc..a2c046a1f 100644
 --- b/src/gzip/zutil.h
 +++ a/src/gzip/zutil.h
 @@ -53,8 +53,10 @@ typedef unsigned long  ulg;
@@ -432,7 +414,7 @@ index 0bc7f4ecd..055ba8b62 100644
 +#ifndef Z_FREETYPE
  extern z_const char * const z_errmsg[10]; /* indexed by 2-zlib_error */
  /* (size given to avoid silly warnings with Visual C++) */
-+#endif  /* !Z_FREETYPE */
++#endif
  
  #define ERR_MSG(err) z_errmsg[Z_NEED_DICT-(err)]
  
@@ -446,7 +428,7 @@ index 0bc7f4ecd..055ba8b62 100644
  #if !defined(_WIN32) && \
      (!defined(_LARGEFILE64_SOURCE) || _LFS64_LARGEFILE-0 == 0)
 @@ -196,6 +200,8 @@ extern z_const char * const z_errmsg[10]; /* indexed by 2-zlib_error */
-     ZEXTERN uLong ZEXPORT crc32_combine_gen64 OF((z_off_t));
+     ZEXTERN uLong ZEXPORT crc32_combine_gen64(z_off_t);
  #endif
  
 +#endif  /* !Z_FREETYPE */
@@ -466,4 +448,4 @@ index 0bc7f4ecd..055ba8b62 100644
 +#    define zmemzero(dest, len) ft_memset(dest, 0, len)
  #  endif
  #else
-    void ZLIB_INTERNAL zmemcpy OF((Bytef* dest, const Bytef* source, uInt len));
+    void ZLIB_INTERNAL zmemcpy(Bytef* dest, const Bytef* source, uInt len);
diff --git a/vendor/freetype/src/gzip/zlib.h b/vendor/freetype/src/gzip/zlib.h
index 3f2f76e3ca..5c7a884c93 100644
--- a/vendor/freetype/src/gzip/zlib.h
+++ b/vendor/freetype/src/gzip/zlib.h
@@ -1,7 +1,7 @@
 /* zlib.h -- interface of the 'zlib' general purpose compression library
-  version 1.2.13, October 13th, 2022
+  version 1.3, August 18th, 2023
 
-  Copyright (C) 1995-2022 Jean-loup Gailly and Mark Adler
+  Copyright (C) 1995-2023 Jean-loup Gailly and Mark Adler
 
   This software is provided 'as-is', without any express or implied
   warranty.  In no event will the authors be held liable for any damages
@@ -37,11 +37,11 @@
 extern "C" {
 #endif
 
-#define ZLIB_VERSION "1.2.13"
-#define ZLIB_VERNUM 0x12d0
+#define ZLIB_VERSION "1.3"
+#define ZLIB_VERNUM 0x1300
 #define ZLIB_VER_MAJOR 1
-#define ZLIB_VER_MINOR 2
-#define ZLIB_VER_REVISION 13
+#define ZLIB_VER_MINOR 3
+#define ZLIB_VER_REVISION 0
 #define ZLIB_VER_SUBREVISION 0
 
 /*
@@ -78,8 +78,8 @@ extern "C" {
   even in the case of corrupted input.
 */
 
-typedef voidpf (*alloc_func) OF((voidpf opaque, uInt items, uInt size));
-typedef void   (*free_func)  OF((voidpf opaque, voidpf address));
+typedef voidpf (*alloc_func)(voidpf opaque, uInt items, uInt size);
+typedef void   (*free_func)(voidpf opaque, voidpf address);
 
 struct internal_state;
 
@@ -219,7 +219,7 @@ typedef gz_header FAR *gz_headerp;
 
                         /* basic functions */
 
-ZEXTERN const char * ZEXPORT zlibVersion OF((void));
+ZEXTERN const char * ZEXPORT zlibVersion(void);
 /* The application can compare zlibVersion and ZLIB_VERSION for consistency.
    If the first character differs, the library code actually used is not
    compatible with the zlib.h header file used by the application.  This check
@@ -227,12 +227,12 @@ ZEXTERN const char * ZEXPORT zlibVersion OF((void));
  */
 
 /*
-ZEXTERN int ZEXPORT deflateInit OF((z_streamp strm, int level));
+ZEXTERN int ZEXPORT deflateInit(z_streamp strm, int level);
 
      Initializes the internal stream state for compression.  The fields
    zalloc, zfree and opaque must be initialized before by the caller.  If
    zalloc and zfree are set to Z_NULL, deflateInit updates them to use default
-   allocation functions.
+   allocation functions.  total_in, total_out, adler, and msg are initialized.
 
      The compression level must be Z_DEFAULT_COMPRESSION, or between 0 and 9:
    1 gives best speed, 9 gives best compression, 0 gives no compression at all
@@ -249,7 +249,7 @@ ZEXTERN int ZEXPORT deflateInit OF((z_streamp strm, int level));
 */
 
 
-ZEXTERN int ZEXPORT deflate OF((z_streamp strm, int flush));
+ZEXTERN int ZEXPORT deflate(z_streamp strm, int flush);
 /*
     deflate compresses as much data as possible, and stops when the input
   buffer becomes empty or the output buffer becomes full.  It may introduce
@@ -322,8 +322,8 @@ ZEXTERN int ZEXPORT deflate OF((z_streamp strm, int flush));
   with the same value of the flush parameter and more output space (updated
   avail_out), until the flush is complete (deflate returns with non-zero
   avail_out).  In the case of a Z_FULL_FLUSH or Z_SYNC_FLUSH, make sure that
-  avail_out is greater than six to avoid repeated flush markers due to
-  avail_out == 0 on return.
+  avail_out is greater than six when the flush marker begins, in order to avoid
+  repeated flush markers upon calling deflate() again when avail_out == 0.
 
     If the parameter flush is set to Z_FINISH, pending input is processed,
   pending output is flushed and deflate returns with Z_STREAM_END if there was
@@ -362,7 +362,7 @@ ZEXTERN int ZEXPORT deflate OF((z_streamp strm, int flush));
 */
 
 
-ZEXTERN int ZEXPORT deflateEnd OF((z_streamp strm));
+ZEXTERN int ZEXPORT deflateEnd(z_streamp strm);
 /*
      All dynamically allocated data structures for this stream are freed.
    This function discards any unprocessed input and does not flush any pending
@@ -378,7 +378,7 @@ ZEXTERN int ZEXPORT deflateEnd OF((z_streamp strm));
 #endif  /* !Z_FREETYPE */
 
 /*
-ZEXTERN int ZEXPORT inflateInit OF((z_streamp strm));
+ZEXTERN int ZEXPORT inflateInit(z_streamp strm);
 
      Initializes the internal stream state for decompression.  The fields
    next_in, avail_in, zalloc, zfree and opaque must be initialized before by
@@ -386,7 +386,8 @@ ZEXTERN int ZEXPORT inflateInit OF((z_streamp strm));
    read or consumed.  The allocation of a sliding window will be deferred to
    the first call of inflate (if the decompression does not complete on the
    first call).  If zalloc and zfree are set to Z_NULL, inflateInit updates
-   them to use default allocation functions.
+   them to use default allocation functions.  total_in, total_out, adler, and
+   msg are initialized.
 
      inflateInit returns Z_OK if success, Z_MEM_ERROR if there was not enough
    memory, Z_VERSION_ERROR if the zlib library version is incompatible with the
@@ -400,7 +401,7 @@ ZEXTERN int ZEXPORT inflateInit OF((z_streamp strm));
 */
 
 
-ZEXTERN int ZEXPORT inflate OF((z_streamp strm, int flush));
+ZEXTERN int ZEXPORT inflate(z_streamp strm, int flush);
 /*
     inflate decompresses as much data as possible, and stops when the input
   buffer becomes empty or the output buffer becomes full.  It may introduce
@@ -520,7 +521,7 @@ ZEXTERN int ZEXPORT inflate OF((z_streamp strm, int flush));
 */
 
 
-ZEXTERN int ZEXPORT inflateEnd OF((z_streamp strm));
+ZEXTERN int ZEXPORT inflateEnd(z_streamp strm);
 /*
      All dynamically allocated data structures for this stream are freed.
    This function discards any unprocessed input and does not flush any pending
@@ -540,12 +541,12 @@ ZEXTERN int ZEXPORT inflateEnd OF((z_streamp strm));
 #ifndef Z_FREETYPE
 
 /*
-ZEXTERN int ZEXPORT deflateInit2 OF((z_streamp strm,
-                                     int  level,
-                                     int  method,
-                                     int  windowBits,
-                                     int  memLevel,
-                                     int  strategy));
+ZEXTERN int ZEXPORT deflateInit2(z_streamp strm,
+                                 int level,
+                                 int method,
+                                 int windowBits,
+                                 int memLevel,
+                                 int strategy);
 
      This is another version of deflateInit with more compression options.  The
    fields zalloc, zfree and opaque must be initialized before by the caller.
@@ -612,9 +613,9 @@ ZEXTERN int ZEXPORT deflateInit2 OF((z_streamp strm,
    compression: this will be done by deflate().
 */
 
-ZEXTERN int ZEXPORT deflateSetDictionary OF((z_streamp strm,
-                                             const Bytef *dictionary,
-                                             uInt  dictLength));
+ZEXTERN int ZEXPORT deflateSetDictionary(z_streamp strm,
+                                         const Bytef *dictionary,
+                                         uInt  dictLength);
 /*
      Initializes the compression dictionary from the given byte sequence
    without producing any compressed output.  When using the zlib format, this
@@ -656,9 +657,9 @@ ZEXTERN int ZEXPORT deflateSetDictionary OF((z_streamp strm,
    not perform any compression: this will be done by deflate().
 */
 
-ZEXTERN int ZEXPORT deflateGetDictionary OF((z_streamp strm,
-                                             Bytef *dictionary,
-                                             uInt  *dictLength));
+ZEXTERN int ZEXPORT deflateGetDictionary(z_streamp strm,
+                                         Bytef *dictionary,
+                                         uInt  *dictLength);
 /*
      Returns the sliding dictionary being maintained by deflate.  dictLength is
    set to the number of bytes in the dictionary, and that many bytes are copied
@@ -678,8 +679,8 @@ ZEXTERN int ZEXPORT deflateGetDictionary OF((z_streamp strm,
    stream state is inconsistent.
 */
 
-ZEXTERN int ZEXPORT deflateCopy OF((z_streamp dest,
-                                    z_streamp source));
+ZEXTERN int ZEXPORT deflateCopy(z_streamp dest,
+                                z_streamp source);
 /*
      Sets the destination stream as a complete copy of the source stream.
 
@@ -696,20 +697,20 @@ ZEXTERN int ZEXPORT deflateCopy OF((z_streamp dest,
    destination.
 */
 
-ZEXTERN int ZEXPORT deflateReset OF((z_streamp strm));
+ZEXTERN int ZEXPORT deflateReset(z_streamp strm);
 /*
      This function is equivalent to deflateEnd followed by deflateInit, but
    does not free and reallocate the internal compression state.  The stream
    will leave the compression level and any other attributes that may have been
-   set unchanged.
+   set unchanged.  total_in, total_out, adler, and msg are initialized.
 
      deflateReset returns Z_OK if success, or Z_STREAM_ERROR if the source
    stream state was inconsistent (such as zalloc or state being Z_NULL).
 */
 
-ZEXTERN int ZEXPORT deflateParams OF((z_streamp strm,
-                                      int level,
-                                      int strategy));
+ZEXTERN int ZEXPORT deflateParams(z_streamp strm,
+                                  int level,
+                                  int strategy);
 /*
      Dynamically update the compression level and compression strategy.  The
    interpretation of level and strategy is as in deflateInit2().  This can be
@@ -734,7 +735,7 @@ ZEXTERN int ZEXPORT deflateParams OF((z_streamp strm,
    Then no more input data should be provided before the deflateParams() call.
    If this is done, the old level and strategy will be applied to the data
    compressed before deflateParams(), and the new level and strategy will be
-   applied to the the data compressed after deflateParams().
+   applied to the data compressed after deflateParams().
 
      deflateParams returns Z_OK on success, Z_STREAM_ERROR if the source stream
    state was inconsistent or if a parameter was invalid, or Z_BUF_ERROR if
@@ -745,11 +746,11 @@ ZEXTERN int ZEXPORT deflateParams OF((z_streamp strm,
    retried with more output space.
 */
 
-ZEXTERN int ZEXPORT deflateTune OF((z_streamp strm,
-                                    int good_length,
-                                    int max_lazy,
-                                    int nice_length,
-                                    int max_chain));
+ZEXTERN int ZEXPORT deflateTune(z_streamp strm,
+                                int good_length,
+                                int max_lazy,
+                                int nice_length,
+                                int max_chain);
 /*
      Fine tune deflate's internal compression parameters.  This should only be
    used by someone who understands the algorithm used by zlib's deflate for
@@ -762,8 +763,8 @@ ZEXTERN int ZEXPORT deflateTune OF((z_streamp strm,
    returns Z_OK on success, or Z_STREAM_ERROR for an invalid deflate stream.
  */
 
-ZEXTERN uLong ZEXPORT deflateBound OF((z_streamp strm,
-                                       uLong sourceLen));
+ZEXTERN uLong ZEXPORT deflateBound(z_streamp strm,
+                                   uLong sourceLen);
 /*
      deflateBound() returns an upper bound on the compressed size after
    deflation of sourceLen bytes.  It must be called after deflateInit() or
@@ -777,9 +778,9 @@ ZEXTERN uLong ZEXPORT deflateBound OF((z_streamp strm,
    than Z_FINISH or Z_NO_FLUSH are used.
 */
 
-ZEXTERN int ZEXPORT deflatePending OF((z_streamp strm,
-                                       unsigned *pending,
-                                       int *bits));
+ZEXTERN int ZEXPORT deflatePending(z_streamp strm,
+                                   unsigned *pending,
+                                   int *bits);
 /*
      deflatePending() returns the number of bytes and bits of output that have
    been generated, but not yet provided in the available output.  The bytes not
@@ -792,9 +793,9 @@ ZEXTERN int ZEXPORT deflatePending OF((z_streamp strm,
    stream state was inconsistent.
  */
 
-ZEXTERN int ZEXPORT deflatePrime OF((z_streamp strm,
-                                     int bits,
-                                     int value));
+ZEXTERN int ZEXPORT deflatePrime(z_streamp strm,
+                                 int bits,
+                                 int value);
 /*
      deflatePrime() inserts bits in the deflate output stream.  The intent
    is that this function is used to start off the deflate output with the bits
@@ -809,8 +810,8 @@ ZEXTERN int ZEXPORT deflatePrime OF((z_streamp strm,
    source stream state was inconsistent.
 */
 
-ZEXTERN int ZEXPORT deflateSetHeader OF((z_streamp strm,
-                                         gz_headerp head));
+ZEXTERN int ZEXPORT deflateSetHeader(z_streamp strm,
+                                     gz_headerp head);
 /*
      deflateSetHeader() provides gzip header information for when a gzip
    stream is requested by deflateInit2().  deflateSetHeader() may be called
@@ -826,16 +827,17 @@ ZEXTERN int ZEXPORT deflateSetHeader OF((z_streamp strm,
    gzip file" and give up.
 
      If deflateSetHeader is not used, the default gzip header has text false,
-   the time set to zero, and os set to 255, with no extra, name, or comment
-   fields.  The gzip header is returned to the default state by deflateReset().
+   the time set to zero, and os set to the current operating system, with no
+   extra, name, or comment fields.  The gzip header is returned to the default
+   state by deflateReset().
 
      deflateSetHeader returns Z_OK if success, or Z_STREAM_ERROR if the source
    stream state was inconsistent.
 */
 
 /*
-ZEXTERN int ZEXPORT inflateInit2 OF((z_streamp strm,
-                                     int  windowBits));
+ZEXTERN int ZEXPORT inflateInit2(z_streamp strm,
+                                 int windowBits);
 
      This is another version of inflateInit with an extra parameter.  The
    fields next_in, avail_in, zalloc, zfree and opaque must be initialized
@@ -888,9 +890,9 @@ ZEXTERN int ZEXPORT inflateInit2 OF((z_streamp strm,
    deferred until inflate() is called.
 */
 
-ZEXTERN int ZEXPORT inflateSetDictionary OF((z_streamp strm,
-                                             const Bytef *dictionary,
-                                             uInt  dictLength));
+ZEXTERN int ZEXPORT inflateSetDictionary(z_streamp strm,
+                                         const Bytef *dictionary,
+                                         uInt  dictLength);
 /*
      Initializes the decompression dictionary from the given uncompressed byte
    sequence.  This function must be called immediately after a call of inflate,
@@ -911,9 +913,9 @@ ZEXTERN int ZEXPORT inflateSetDictionary OF((z_streamp strm,
    inflate().
 */
 
-ZEXTERN int ZEXPORT inflateGetDictionary OF((z_streamp strm,
-                                             Bytef *dictionary,
-                                             uInt  *dictLength));
+ZEXTERN int ZEXPORT inflateGetDictionary(z_streamp strm,
+                                         Bytef *dictionary,
+                                         uInt  *dictLength);
 /*
      Returns the sliding dictionary being maintained by inflate.  dictLength is
    set to the number of bytes in the dictionary, and that many bytes are copied
@@ -926,7 +928,7 @@ ZEXTERN int ZEXPORT inflateGetDictionary OF((z_streamp strm,
    stream state is inconsistent.
 */
 
-ZEXTERN int ZEXPORT inflateSync OF((z_streamp strm));
+ZEXTERN int ZEXPORT inflateSync(z_streamp strm);
 /*
      Skips invalid compressed data until a possible full flush point (see above
    for the description of deflate with Z_FULL_FLUSH) can be found, or until all
@@ -945,8 +947,8 @@ ZEXTERN int ZEXPORT inflateSync OF((z_streamp strm));
    input each time, until success or end of the input data.
 */
 
-ZEXTERN int ZEXPORT inflateCopy OF((z_streamp dest,
-                                    z_streamp source));
+ZEXTERN int ZEXPORT inflateCopy(z_streamp dest,
+                                z_streamp source);
 /*
      Sets the destination stream as a complete copy of the source stream.
 
@@ -963,18 +965,19 @@ ZEXTERN int ZEXPORT inflateCopy OF((z_streamp dest,
 
 #endif  /* !Z_FREETYPE */
 
-ZEXTERN int ZEXPORT inflateReset OF((z_streamp strm));
+ZEXTERN int ZEXPORT inflateReset(z_streamp strm);
 /*
      This function is equivalent to inflateEnd followed by inflateInit,
    but does not free and reallocate the internal decompression state.  The
    stream will keep attributes that may have been set by inflateInit2.
+   total_in, total_out, adler, and msg are initialized.
 
      inflateReset returns Z_OK if success, or Z_STREAM_ERROR if the source
    stream state was inconsistent (such as zalloc or state being Z_NULL).
 */
 
-ZEXTERN int ZEXPORT inflateReset2 OF((z_streamp strm,
-                                      int windowBits));
+ZEXTERN int ZEXPORT inflateReset2(z_streamp strm,
+                                  int windowBits);
 /*
      This function is the same as inflateReset, but it also permits changing
    the wrap and window size requests.  The windowBits parameter is interpreted
@@ -989,9 +992,9 @@ ZEXTERN int ZEXPORT inflateReset2 OF((z_streamp strm,
 
 #ifndef Z_FREETYPE
 
-ZEXTERN int ZEXPORT inflatePrime OF((z_streamp strm,
-                                     int bits,
-                                     int value));
+ZEXTERN int ZEXPORT inflatePrime(z_streamp strm,
+                                 int bits,
+                                 int value);
 /*
      This function inserts bits in the inflate input stream.  The intent is
    that this function is used to start inflating at a bit position in the
@@ -1010,7 +1013,7 @@ ZEXTERN int ZEXPORT inflatePrime OF((z_streamp strm,
    stream state was inconsistent.
 */
 
-ZEXTERN long ZEXPORT inflateMark OF((z_streamp strm));
+ZEXTERN long ZEXPORT inflateMark(z_streamp strm);
 /*
      This function returns two values, one in the lower 16 bits of the return
    value, and the other in the remaining upper bits, obtained by shifting the
@@ -1038,8 +1041,8 @@ ZEXTERN long ZEXPORT inflateMark OF((z_streamp strm));
    source stream state was inconsistent.
 */
 
-ZEXTERN int ZEXPORT inflateGetHeader OF((z_streamp strm,
-                                         gz_headerp head));
+ZEXTERN int ZEXPORT inflateGetHeader(z_streamp strm,
+                                     gz_headerp head);
 /*
      inflateGetHeader() requests that gzip header information be stored in the
    provided gz_header structure.  inflateGetHeader() may be called after
@@ -1081,8 +1084,8 @@ ZEXTERN int ZEXPORT inflateGetHeader OF((z_streamp strm,
 #endif  /* !Z_FREETYPE */
 
 /*
-ZEXTERN int ZEXPORT inflateBackInit OF((z_streamp strm, int windowBits,
-                                        unsigned char FAR *window));
+ZEXTERN int ZEXPORT inflateBackInit(z_streamp strm, int windowBits,
+                                    unsigned char FAR *window);
 
      Initialize the internal stream state for decompression using inflateBack()
    calls.  The fields zalloc, zfree and opaque in strm must be initialized
@@ -1102,15 +1105,15 @@ ZEXTERN int ZEXPORT inflateBackInit OF((z_streamp strm, int windowBits,
    the version of the header file.
 */
 
-typedef unsigned (*in_func) OF((void FAR *,
-                                z_const unsigned char FAR * FAR *));
-typedef int (*out_func) OF((void FAR *, unsigned char FAR *, unsigned));
+typedef unsigned (*in_func)(void FAR *,
+                            z_const unsigned char FAR * FAR *);
+typedef int (*out_func)(void FAR *, unsigned char FAR *, unsigned);
 
 #ifndef Z_FREETYPE
 
-ZEXTERN int ZEXPORT inflateBack OF((z_streamp strm,
-                                    in_func in, void FAR *in_desc,
-                                    out_func out, void FAR *out_desc));
+ZEXTERN int ZEXPORT inflateBack(z_streamp strm,
+                                in_func in, void FAR *in_desc,
+                                out_func out, void FAR *out_desc);
 /*
      inflateBack() does a raw inflate with a single call using a call-back
    interface for input and output.  This is potentially more efficient than
@@ -1178,7 +1181,7 @@ ZEXTERN int ZEXPORT inflateBack OF((z_streamp strm,
    cannot return Z_OK.
 */
 
-ZEXTERN int ZEXPORT inflateBackEnd OF((z_streamp strm));
+ZEXTERN int ZEXPORT inflateBackEnd(z_streamp strm);
 /*
      All memory allocated by inflateBackInit() is freed.
 
@@ -1186,7 +1189,7 @@ ZEXTERN int ZEXPORT inflateBackEnd OF((z_streamp strm));
    state was inconsistent.
 */
 
-ZEXTERN uLong ZEXPORT zlibCompileFlags OF((void));
+ZEXTERN uLong ZEXPORT zlibCompileFlags(void);
 /* Return flags indicating compile-time options.
 
     Type sizes, two bits each, 00 = 16 bits, 01 = 32, 10 = 64, 11 = other:
@@ -1241,8 +1244,8 @@ ZEXTERN uLong ZEXPORT zlibCompileFlags OF((void));
    you need special options.
 */
 
-ZEXTERN int ZEXPORT compress OF((Bytef *dest,   uLongf *destLen,
-                                 const Bytef *source, uLong sourceLen));
+ZEXTERN int ZEXPORT compress(Bytef *dest,   uLongf *destLen,
+                             const Bytef *source, uLong sourceLen);
 /*
      Compresses the source buffer into the destination buffer.  sourceLen is
    the byte length of the source buffer.  Upon entry, destLen is the total size
@@ -1256,9 +1259,9 @@ ZEXTERN int ZEXPORT compress OF((Bytef *dest,   uLongf *destLen,
    buffer.
 */
 
-ZEXTERN int ZEXPORT compress2 OF((Bytef *dest,   uLongf *destLen,
-                                  const Bytef *source, uLong sourceLen,
-                                  int level));
+ZEXTERN int ZEXPORT compress2(Bytef *dest,   uLongf *destLen,
+                              const Bytef *source, uLong sourceLen,
+                              int level);
 /*
      Compresses the source buffer into the destination buffer.  The level
    parameter has the same meaning as in deflateInit.  sourceLen is the byte
@@ -1272,15 +1275,15 @@ ZEXTERN int ZEXPORT compress2 OF((Bytef *dest,   uLongf *destLen,
    Z_STREAM_ERROR if the level parameter is invalid.
 */
 
-ZEXTERN uLong ZEXPORT compressBound OF((uLong sourceLen));
+ZEXTERN uLong ZEXPORT compressBound(uLong sourceLen);
 /*
      compressBound() returns an upper bound on the compressed size after
    compress() or compress2() on sourceLen bytes.  It would be used before a
    compress() or compress2() call to allocate the destination buffer.
 */
 
-ZEXTERN int ZEXPORT uncompress OF((Bytef *dest,   uLongf *destLen,
-                                   const Bytef *source, uLong sourceLen));
+ZEXTERN int ZEXPORT uncompress(Bytef *dest,   uLongf *destLen,
+                               const Bytef *source, uLong sourceLen);
 /*
      Decompresses the source buffer into the destination buffer.  sourceLen is
    the byte length of the source buffer.  Upon entry, destLen is the total size
@@ -1297,8 +1300,8 @@ ZEXTERN int ZEXPORT uncompress OF((Bytef *dest,   uLongf *destLen,
    buffer with the uncompressed data up to that point.
 */
 
-ZEXTERN int ZEXPORT uncompress2 OF((Bytef *dest,   uLongf *destLen,
-                                    const Bytef *source, uLong *sourceLen));
+ZEXTERN int ZEXPORT uncompress2(Bytef *dest,   uLongf *destLen,
+                                const Bytef *source, uLong *sourceLen);
 /*
      Same as uncompress, except that sourceLen is a pointer, where the
    length of the source is *sourceLen.  On return, *sourceLen is the number of
@@ -1317,7 +1320,7 @@ ZEXTERN int ZEXPORT uncompress2 OF((Bytef *dest,   uLongf *destLen,
 typedef struct gzFile_s *gzFile;    /* semi-opaque gzip file descriptor */
 
 /*
-ZEXTERN gzFile ZEXPORT gzopen OF((const char *path, const char *mode));
+ZEXTERN gzFile ZEXPORT gzopen(const char *path, const char *mode);
 
      Open the gzip (.gz) file at path for reading and decompressing, or
    compressing and writing.  The mode parameter is as in fopen ("rb" or "wb")
@@ -1354,7 +1357,7 @@ ZEXTERN gzFile ZEXPORT gzopen OF((const char *path, const char *mode));
    file could not be opened.
 */
 
-ZEXTERN gzFile ZEXPORT gzdopen OF((int fd, const char *mode));
+ZEXTERN gzFile ZEXPORT gzdopen(int fd, const char *mode);
 /*
      Associate a gzFile with the file descriptor fd.  File descriptors are
    obtained from calls like open, dup, creat, pipe or fileno (if the file has
@@ -1377,7 +1380,7 @@ ZEXTERN gzFile ZEXPORT gzdopen OF((int fd, const char *mode));
    will not detect if fd is invalid (unless fd is -1).
 */
 
-ZEXTERN int ZEXPORT gzbuffer OF((gzFile file, unsigned size));
+ZEXTERN int ZEXPORT gzbuffer(gzFile file, unsigned size);
 /*
      Set the internal buffer size used by this library's functions for file to
    size.  The default buffer size is 8192 bytes.  This function must be called
@@ -1393,7 +1396,7 @@ ZEXTERN int ZEXPORT gzbuffer OF((gzFile file, unsigned size));
    too late.
 */
 
-ZEXTERN int ZEXPORT gzsetparams OF((gzFile file, int level, int strategy));
+ZEXTERN int ZEXPORT gzsetparams(gzFile file, int level, int strategy);
 /*
      Dynamically update the compression level and strategy for file.  See the
    description of deflateInit2 for the meaning of these parameters. Previously
@@ -1404,7 +1407,7 @@ ZEXTERN int ZEXPORT gzsetparams OF((gzFile file, int level, int strategy));
    or Z_MEM_ERROR if there is a memory allocation error.
 */
 
-ZEXTERN int ZEXPORT gzread OF((gzFile file, voidp buf, unsigned len));
+ZEXTERN int ZEXPORT gzread(gzFile file, voidp buf, unsigned len);
 /*
      Read and decompress up to len uncompressed bytes from file into buf.  If
    the input file is not in gzip format, gzread copies the given number of
@@ -1434,8 +1437,8 @@ ZEXTERN int ZEXPORT gzread OF((gzFile file, voidp buf, unsigned len));
    Z_STREAM_ERROR.
 */
 
-ZEXTERN z_size_t ZEXPORT gzfread OF((voidp buf, z_size_t size, z_size_t nitems,
-                                     gzFile file));
+ZEXTERN z_size_t ZEXPORT gzfread(voidp buf, z_size_t size, z_size_t nitems,
+                                 gzFile file);
 /*
      Read and decompress up to nitems items of size size from file into buf,
    otherwise operating as gzread() does.  This duplicates the interface of
@@ -1460,14 +1463,14 @@ ZEXTERN z_size_t ZEXPORT gzfread OF((voidp buf, z_size_t size, z_size_t nitems,
    file, resetting and retrying on end-of-file, when size is not 1.
 */
 
-ZEXTERN int ZEXPORT gzwrite OF((gzFile file, voidpc buf, unsigned len));
+ZEXTERN int ZEXPORT gzwrite(gzFile file, voidpc buf, unsigned len);
 /*
      Compress and write the len uncompressed bytes at buf to file. gzwrite
    returns the number of uncompressed bytes written or 0 in case of error.
 */
 
-ZEXTERN z_size_t ZEXPORT gzfwrite OF((voidpc buf, z_size_t size,
-                                      z_size_t nitems, gzFile file));
+ZEXTERN z_size_t ZEXPORT gzfwrite(voidpc buf, z_size_t size,
+                                  z_size_t nitems, gzFile file);
 /*
      Compress and write nitems items of size size from buf to file, duplicating
    the interface of stdio's fwrite(), with size_t request and return types.  If
@@ -1480,7 +1483,7 @@ ZEXTERN z_size_t ZEXPORT gzfwrite OF((voidpc buf, z_size_t size,
    is returned, and the error state is set to Z_STREAM_ERROR.
 */
 
-ZEXTERN int ZEXPORTVA gzprintf Z_ARG((gzFile file, const char *format, ...));
+ZEXTERN int ZEXPORTVA gzprintf(gzFile file, const char *format, ...);
 /*
      Convert, format, compress, and write the arguments (...) to file under
    control of the string format, as in fprintf.  gzprintf returns the number of
@@ -1495,7 +1498,7 @@ ZEXTERN int ZEXPORTVA gzprintf Z_ARG((gzFile file, const char *format, ...));
    This can be determined using zlibCompileFlags().
 */
 
-ZEXTERN int ZEXPORT gzputs OF((gzFile file, const char *s));
+ZEXTERN int ZEXPORT gzputs(gzFile file, const char *s);
 /*
      Compress and write the given null-terminated string s to file, excluding
    the terminating null character.
@@ -1503,7 +1506,7 @@ ZEXTERN int ZEXPORT gzputs OF((gzFile file, const char *s));
      gzputs returns the number of characters written, or -1 in case of error.
 */
 
-ZEXTERN char * ZEXPORT gzgets OF((gzFile file, char *buf, int len));
+ZEXTERN char * ZEXPORT gzgets(gzFile file, char *buf, int len);
 /*
      Read and decompress bytes from file into buf, until len-1 characters are
    read, or until a newline character is read and transferred to buf, or an
@@ -1517,13 +1520,13 @@ ZEXTERN char * ZEXPORT gzgets OF((gzFile file, char *buf, int len));
    buf are indeterminate.
 */
 
-ZEXTERN int ZEXPORT gzputc OF((gzFile file, int c));
+ZEXTERN int ZEXPORT gzputc(gzFile file, int c);
 /*
      Compress and write c, converted to an unsigned char, into file.  gzputc
    returns the value that was written, or -1 in case of error.
 */
 
-ZEXTERN int ZEXPORT gzgetc OF((gzFile file));
+ZEXTERN int ZEXPORT gzgetc(gzFile file);
 /*
      Read and decompress one byte from file.  gzgetc returns this byte or -1
    in case of end of file or error.  This is implemented as a macro for speed.
@@ -1532,7 +1535,7 @@ ZEXTERN int ZEXPORT gzgetc OF((gzFile file));
    points to has been clobbered or not.
 */
 
-ZEXTERN int ZEXPORT gzungetc OF((int c, gzFile file));
+ZEXTERN int ZEXPORT gzungetc(int c, gzFile file);
 /*
      Push c back onto the stream for file to be read as the first character on
    the next read.  At least one character of push-back is always allowed.
@@ -1544,7 +1547,7 @@ ZEXTERN int ZEXPORT gzungetc OF((int c, gzFile file));
    gzseek() or gzrewind().
 */
 
-ZEXTERN int ZEXPORT gzflush OF((gzFile file, int flush));
+ZEXTERN int ZEXPORT gzflush(gzFile file, int flush);
 /*
      Flush all pending output to file.  The parameter flush is as in the
    deflate() function.  The return value is the zlib error number (see function
@@ -1560,8 +1563,8 @@ ZEXTERN int ZEXPORT gzflush OF((gzFile file, int flush));
 */
 
 /*
-ZEXTERN z_off_t ZEXPORT gzseek OF((gzFile file,
-                                   z_off_t offset, int whence));
+ZEXTERN z_off_t ZEXPORT gzseek(gzFile file,
+                               z_off_t offset, int whence);
 
      Set the starting position to offset relative to whence for the next gzread
    or gzwrite on file.  The offset represents a number of bytes in the
@@ -1579,7 +1582,7 @@ ZEXTERN z_off_t ZEXPORT gzseek OF((gzFile file,
    would be before the current position.
 */
 
-ZEXTERN int ZEXPORT    gzrewind OF((gzFile file));
+ZEXTERN int ZEXPORT    gzrewind(gzFile file);
 /*
      Rewind file. This function is supported only for reading.
 
@@ -1587,7 +1590,7 @@ ZEXTERN int ZEXPORT    gzrewind OF((gzFile file));
 */
 
 /*
-ZEXTERN z_off_t ZEXPORT    gztell OF((gzFile file));
+ZEXTERN z_off_t ZEXPORT    gztell(gzFile file);
 
      Return the starting position for the next gzread or gzwrite on file.
    This position represents a number of bytes in the uncompressed data stream,
@@ -1598,7 +1601,7 @@ ZEXTERN z_off_t ZEXPORT    gztell OF((gzFile file));
 */
 
 /*
-ZEXTERN z_off_t ZEXPORT gzoffset OF((gzFile file));
+ZEXTERN z_off_t ZEXPORT gzoffset(gzFile file);
 
      Return the current compressed (actual) read or write offset of file.  This
    offset includes the count of bytes that precede the gzip stream, for example
@@ -1607,7 +1610,7 @@ ZEXTERN z_off_t ZEXPORT gzoffset OF((gzFile file));
    be used for a progress indicator.  On error, gzoffset() returns -1.
 */
 
-ZEXTERN int ZEXPORT gzeof OF((gzFile file));
+ZEXTERN int ZEXPORT gzeof(gzFile file);
 /*
      Return true (1) if the end-of-file indicator for file has been set while
    reading, false (0) otherwise.  Note that the end-of-file indicator is set
@@ -1622,7 +1625,7 @@ ZEXTERN int ZEXPORT gzeof OF((gzFile file));
    has grown since the previous end of file was detected.
 */
 
-ZEXTERN int ZEXPORT gzdirect OF((gzFile file));
+ZEXTERN int ZEXPORT gzdirect(gzFile file);
 /*
      Return true (1) if file is being copied directly while reading, or false
    (0) if file is a gzip stream being decompressed.
@@ -1643,7 +1646,7 @@ ZEXTERN int ZEXPORT gzdirect OF((gzFile file));
    gzip file reading and decompression, which may not be desired.)
 */
 
-ZEXTERN int ZEXPORT    gzclose OF((gzFile file));
+ZEXTERN int ZEXPORT    gzclose(gzFile file);
 /*
      Flush all pending output for file, if necessary, close file and
    deallocate the (de)compression state.  Note that once file is closed, you
@@ -1656,8 +1659,8 @@ ZEXTERN int ZEXPORT    gzclose OF((gzFile file));
    last read ended in the middle of a gzip stream, or Z_OK on success.
 */
 
-ZEXTERN int ZEXPORT gzclose_r OF((gzFile file));
-ZEXTERN int ZEXPORT gzclose_w OF((gzFile file));
+ZEXTERN int ZEXPORT gzclose_r(gzFile file);
+ZEXTERN int ZEXPORT gzclose_w(gzFile file);
 /*
      Same as gzclose(), but gzclose_r() is only for use when reading, and
    gzclose_w() is only for use when writing or appending.  The advantage to
@@ -1668,7 +1671,7 @@ ZEXTERN int ZEXPORT gzclose_w OF((gzFile file));
    zlib library.
 */
 
-ZEXTERN const char * ZEXPORT gzerror OF((gzFile file, int *errnum));
+ZEXTERN const char * ZEXPORT gzerror(gzFile file, int *errnum);
 /*
      Return the error message for the last error which occurred on file.
    errnum is set to zlib error number.  If an error occurred in the file system
@@ -1684,7 +1687,7 @@ ZEXTERN const char * ZEXPORT gzerror OF((gzFile file, int *errnum));
    functions above that do not distinguish those cases in their return values.
 */
 
-ZEXTERN void ZEXPORT gzclearerr OF((gzFile file));
+ZEXTERN void ZEXPORT gzclearerr(gzFile file);
 /*
      Clear the error and end-of-file flags for file.  This is analogous to the
    clearerr() function in stdio.  This is useful for continuing to read a gzip
@@ -1701,7 +1704,7 @@ ZEXTERN void ZEXPORT gzclearerr OF((gzFile file));
    library.
 */
 
-ZEXTERN uLong ZEXPORT adler32 OF((uLong adler, const Bytef *buf, uInt len));
+ZEXTERN uLong ZEXPORT adler32(uLong adler, const Bytef *buf, uInt len);
 /*
      Update a running Adler-32 checksum with the bytes buf[0..len-1] and
    return the updated checksum. An Adler-32 value is in the range of a 32-bit
@@ -1721,15 +1724,15 @@ ZEXTERN uLong ZEXPORT adler32 OF((uLong adler, const Bytef *buf, uInt len));
      if (adler != original_adler) error();
 */
 
-ZEXTERN uLong ZEXPORT adler32_z OF((uLong adler, const Bytef *buf,
-                                    z_size_t len));
+ZEXTERN uLong ZEXPORT adler32_z(uLong adler, const Bytef *buf,
+                                z_size_t len);
 /*
      Same as adler32(), but with a size_t length.
 */
 
 /*
-ZEXTERN uLong ZEXPORT adler32_combine OF((uLong adler1, uLong adler2,
-                                          z_off_t len2));
+ZEXTERN uLong ZEXPORT adler32_combine(uLong adler1, uLong adler2,
+                                      z_off_t len2);
 
      Combine two Adler-32 checksums into one.  For two sequences of bytes, seq1
    and seq2 with lengths len1 and len2, Adler-32 checksums were calculated for
@@ -1739,7 +1742,7 @@ ZEXTERN uLong ZEXPORT adler32_combine OF((uLong adler1, uLong adler2,
    negative, the result has no meaning or utility.
 */
 
-ZEXTERN uLong ZEXPORT crc32 OF((uLong crc, const Bytef *buf, uInt len));
+ZEXTERN uLong ZEXPORT crc32(uLong crc, const Bytef *buf, uInt len);
 /*
      Update a running CRC-32 with the bytes buf[0..len-1] and return the
    updated CRC-32. A CRC-32 value is in the range of a 32-bit unsigned integer.
@@ -1757,14 +1760,14 @@ ZEXTERN uLong ZEXPORT crc32 OF((uLong crc, const Bytef *buf, uInt len));
      if (crc != original_crc) error();
 */
 
-ZEXTERN uLong ZEXPORT crc32_z OF((uLong crc, const Bytef *buf,
-                                  z_size_t len));
+ZEXTERN uLong ZEXPORT crc32_z(uLong crc, const Bytef *buf,
+                              z_size_t len);
 /*
      Same as crc32(), but with a size_t length.
 */
 
 /*
-ZEXTERN uLong ZEXPORT crc32_combine OF((uLong crc1, uLong crc2, z_off_t len2));
+ZEXTERN uLong ZEXPORT crc32_combine(uLong crc1, uLong crc2, z_off_t len2);
 
      Combine two CRC-32 check values into one.  For two sequences of bytes,
    seq1 and seq2 with lengths len1 and len2, CRC-32 check values were
@@ -1774,7 +1777,7 @@ ZEXTERN uLong ZEXPORT crc32_combine OF((uLong crc1, uLong crc2, z_off_t len2));
 */
 
 /*
-ZEXTERN uLong ZEXPORT crc32_combine_gen OF((z_off_t len2));
+ZEXTERN uLong ZEXPORT crc32_combine_gen(z_off_t len2);
 
      Return the operator corresponding to length len2, to be used with
    crc32_combine_op().
@@ -1782,7 +1785,7 @@ ZEXTERN uLong ZEXPORT crc32_combine_gen OF((z_off_t len2));
 
 #ifndef Z_FREETYPE
 
-ZEXTERN uLong ZEXPORT crc32_combine_op OF((uLong crc1, uLong crc2, uLong op));
+ZEXTERN uLong ZEXPORT crc32_combine_op(uLong crc1, uLong crc2, uLong op);
 /*
      Give the same result as crc32_combine(), using op in place of len2. op is
    is generated from len2 by crc32_combine_gen(). This will be faster than
@@ -1795,20 +1798,20 @@ ZEXTERN uLong ZEXPORT crc32_combine_op OF((uLong crc1, uLong crc2, uLong op));
 /* deflateInit and inflateInit are macros to allow checking the zlib version
  * and the compiler's view of z_stream:
  */
-ZEXTERN int ZEXPORT deflateInit_ OF((z_streamp strm, int level,
-                                     const char *version, int stream_size));
-ZEXTERN int ZEXPORT inflateInit_ OF((z_streamp strm,
-                                     const char *version, int stream_size));
-ZEXTERN int ZEXPORT deflateInit2_ OF((z_streamp strm, int  level, int  method,
-                                      int windowBits, int memLevel,
-                                      int strategy, const char *version,
-                                      int stream_size));
-ZEXTERN int ZEXPORT inflateInit2_ OF((z_streamp strm, int  windowBits,
-                                      const char *version, int stream_size));
-ZEXTERN int ZEXPORT inflateBackInit_ OF((z_streamp strm, int windowBits,
-                                         unsigned char FAR *window,
-                                         const char *version,
-                                         int stream_size));
+ZEXTERN int ZEXPORT deflateInit_(z_streamp strm, int level,
+                                 const char *version, int stream_size);
+ZEXTERN int ZEXPORT inflateInit_(z_streamp strm,
+                                 const char *version, int stream_size);
+ZEXTERN int ZEXPORT deflateInit2_(z_streamp strm, int  level, int  method,
+                                  int windowBits, int memLevel,
+                                  int strategy, const char *version,
+                                  int stream_size);
+ZEXTERN int ZEXPORT inflateInit2_(z_streamp strm, int  windowBits,
+                                  const char *version, int stream_size);
+ZEXTERN int ZEXPORT inflateBackInit_(z_streamp strm, int windowBits,
+                                     unsigned char FAR *window,
+                                     const char *version,
+                                     int stream_size);
 #ifdef Z_PREFIX_SET
 #  define z_deflateInit(strm, level) \
           deflateInit_((strm), (level), ZLIB_VERSION, (int)sizeof(z_stream))
@@ -1841,9 +1844,8 @@ ZEXTERN int ZEXPORT inflateBackInit_ OF((z_streamp strm, int windowBits,
 
 #else  /* Z_FREETYPE */
 
-
-ZEXTERN int ZEXPORT inflateInit2_ OF((z_streamp strm, int  windowBits,
-                                      const char *version, int stream_size));
+ZEXTERN int ZEXPORT inflateInit2_(z_streamp strm, int  windowBits,
+                                  const char *version, int stream_size);
 
 #  define inflateInit2(strm, windowBits) \
           inflateInit2_((strm), (windowBits), ZLIB_VERSION, \
@@ -1851,7 +1853,6 @@ ZEXTERN int ZEXPORT inflateInit2_ OF((z_streamp strm, int  windowBits,
 
 #endif  /* Z_FREETYPE */
 
-
 #ifndef Z_SOLO
 
 /* gzgetc() macro and its supporting function and exposed data structure.  Note
@@ -1866,7 +1867,7 @@ struct gzFile_s {
     unsigned char *next;
     z_off64_t pos;
 };
-ZEXTERN int ZEXPORT gzgetc_ OF((gzFile file));  /* backward compatibility */
+ZEXTERN int ZEXPORT gzgetc_(gzFile file);       /* backward compatibility */
 #ifdef Z_PREFIX_SET
 #  undef z_gzgetc
 #  define z_gzgetc(g) \
@@ -1883,13 +1884,13 @@ ZEXTERN int ZEXPORT gzgetc_ OF((gzFile file));  /* backward compatibility */
  * without large file support, _LFS64_LARGEFILE must also be true
  */
 #ifdef Z_LARGE64
-   ZEXTERN gzFile ZEXPORT gzopen64 OF((const char *, const char *));
-   ZEXTERN z_off64_t ZEXPORT gzseek64 OF((gzFile, z_off64_t, int));
-   ZEXTERN z_off64_t ZEXPORT gztell64 OF((gzFile));
-   ZEXTERN z_off64_t ZEXPORT gzoffset64 OF((gzFile));
-   ZEXTERN uLong ZEXPORT adler32_combine64 OF((uLong, uLong, z_off64_t));
-   ZEXTERN uLong ZEXPORT crc32_combine64 OF((uLong, uLong, z_off64_t));
-   ZEXTERN uLong ZEXPORT crc32_combine_gen64 OF((z_off64_t));
+   ZEXTERN gzFile ZEXPORT gzopen64(const char *, const char *);
+   ZEXTERN z_off64_t ZEXPORT gzseek64(gzFile, z_off64_t, int);
+   ZEXTERN z_off64_t ZEXPORT gztell64(gzFile);
+   ZEXTERN z_off64_t ZEXPORT gzoffset64(gzFile);
+   ZEXTERN uLong ZEXPORT adler32_combine64(uLong, uLong, z_off64_t);
+   ZEXTERN uLong ZEXPORT crc32_combine64(uLong, uLong, z_off64_t);
+   ZEXTERN uLong ZEXPORT crc32_combine_gen64(z_off64_t);
 #endif
 
 #if !defined(ZLIB_INTERNAL) && defined(Z_WANT64)
@@ -1911,55 +1912,55 @@ ZEXTERN int ZEXPORT gzgetc_ OF((gzFile file));  /* backward compatibility */
 #    define crc32_combine_gen crc32_combine_gen64
 #  endif
 #  ifndef Z_LARGE64
-     ZEXTERN gzFile ZEXPORT gzopen64 OF((const char *, const char *));
-     ZEXTERN z_off_t ZEXPORT gzseek64 OF((gzFile, z_off_t, int));
-     ZEXTERN z_off_t ZEXPORT gztell64 OF((gzFile));
-     ZEXTERN z_off_t ZEXPORT gzoffset64 OF((gzFile));
-     ZEXTERN uLong ZEXPORT adler32_combine64 OF((uLong, uLong, z_off_t));
-     ZEXTERN uLong ZEXPORT crc32_combine64 OF((uLong, uLong, z_off_t));
-     ZEXTERN uLong ZEXPORT crc32_combine_gen64 OF((z_off_t));
+     ZEXTERN gzFile ZEXPORT gzopen64(const char *, const char *);
+     ZEXTERN z_off_t ZEXPORT gzseek64(gzFile, z_off_t, int);
+     ZEXTERN z_off_t ZEXPORT gztell64(gzFile);
+     ZEXTERN z_off_t ZEXPORT gzoffset64(gzFile);
+     ZEXTERN uLong ZEXPORT adler32_combine64(uLong, uLong, z_off_t);
+     ZEXTERN uLong ZEXPORT crc32_combine64(uLong, uLong, z_off_t);
+     ZEXTERN uLong ZEXPORT crc32_combine_gen64(z_off_t);
 #  endif
 #else
-   ZEXTERN gzFile ZEXPORT gzopen OF((const char *, const char *));
-   ZEXTERN z_off_t ZEXPORT gzseek OF((gzFile, z_off_t, int));
-   ZEXTERN z_off_t ZEXPORT gztell OF((gzFile));
-   ZEXTERN z_off_t ZEXPORT gzoffset OF((gzFile));
-   ZEXTERN uLong ZEXPORT adler32_combine OF((uLong, uLong, z_off_t));
-   ZEXTERN uLong ZEXPORT crc32_combine OF((uLong, uLong, z_off_t));
-   ZEXTERN uLong ZEXPORT crc32_combine_gen OF((z_off_t));
+   ZEXTERN gzFile ZEXPORT gzopen(const char *, const char *);
+   ZEXTERN z_off_t ZEXPORT gzseek(gzFile, z_off_t, int);
+   ZEXTERN z_off_t ZEXPORT gztell(gzFile);
+   ZEXTERN z_off_t ZEXPORT gzoffset(gzFile);
+   ZEXTERN uLong ZEXPORT adler32_combine(uLong, uLong, z_off_t);
+   ZEXTERN uLong ZEXPORT crc32_combine(uLong, uLong, z_off_t);
+   ZEXTERN uLong ZEXPORT crc32_combine_gen(z_off_t);
 #endif
 
 #else /* Z_SOLO */
 
 #ifndef Z_FREETYPE
-   ZEXTERN uLong ZEXPORT adler32_combine OF((uLong, uLong, z_off_t));
-   ZEXTERN uLong ZEXPORT crc32_combine OF((uLong, uLong, z_off_t));
-   ZEXTERN uLong ZEXPORT crc32_combine_gen OF((z_off_t));
+   ZEXTERN uLong ZEXPORT adler32_combine(uLong, uLong, z_off_t);
+   ZEXTERN uLong ZEXPORT crc32_combine(uLong, uLong, z_off_t);
+   ZEXTERN uLong ZEXPORT crc32_combine_gen(z_off_t);
 #endif
 
 #endif /* !Z_SOLO */
 
 /* undocumented functions */
 #ifndef Z_FREETYPE
-ZEXTERN const char   * ZEXPORT zError           OF((int));
-ZEXTERN int            ZEXPORT inflateSyncPoint OF((z_streamp));
-ZEXTERN const z_crc_t FAR * ZEXPORT get_crc_table    OF((void));
-ZEXTERN int            ZEXPORT inflateUndermine OF((z_streamp, int));
-ZEXTERN int            ZEXPORT inflateValidate OF((z_streamp, int));
-ZEXTERN unsigned long  ZEXPORT inflateCodesUsed OF((z_streamp));
+ZEXTERN const char   * ZEXPORT zError(int);
+ZEXTERN int            ZEXPORT inflateSyncPoint(z_streamp);
+ZEXTERN const z_crc_t FAR * ZEXPORT get_crc_table(void);
+ZEXTERN int            ZEXPORT inflateUndermine(z_streamp, int);
+ZEXTERN int            ZEXPORT inflateValidate(z_streamp, int);
+ZEXTERN unsigned long  ZEXPORT inflateCodesUsed(z_streamp);
 #endif  /* !Z_FREETYPE */
-ZEXTERN int            ZEXPORT inflateResetKeep OF((z_streamp));
+ZEXTERN int            ZEXPORT inflateResetKeep(z_streamp);
 #ifndef Z_FREETYPE
-ZEXTERN int            ZEXPORT deflateResetKeep OF((z_streamp));
+ZEXTERN int            ZEXPORT deflateResetKeep(z_streamp);
 #if defined(_WIN32) && !defined(Z_SOLO)
-ZEXTERN gzFile         ZEXPORT gzopen_w OF((const wchar_t *path,
-                                            const char *mode));
+ZEXTERN gzFile         ZEXPORT gzopen_w(const wchar_t *path,
+                                        const char *mode);
 #endif
 #if defined(STDC) || defined(Z_HAVE_STDARG_H)
 #  ifndef Z_SOLO
-ZEXTERN int            ZEXPORTVA gzvprintf Z_ARG((gzFile file,
-                                                  const char *format,
-                                                  va_list va));
+ZEXTERN int            ZEXPORTVA gzvprintf(gzFile file,
+                                           const char *format,
+                                           va_list va);
 #  endif
 #endif
 #endif  /* !Z_FREETYPE */
diff --git a/vendor/freetype/src/gzip/zutil.c b/vendor/freetype/src/gzip/zutil.c
index 542706ca0c..f76def425c 100644
--- a/vendor/freetype/src/gzip/zutil.c
+++ b/vendor/freetype/src/gzip/zutil.c
@@ -26,13 +26,11 @@ z_const char * const z_errmsg[10] = {
 };
 
 
-const char * ZEXPORT zlibVersion()
-{
+const char * ZEXPORT zlibVersion(void) {
     return ZLIB_VERSION;
 }
 
-uLong ZEXPORT zlibCompileFlags()
-{
+uLong ZEXPORT zlibCompileFlags(void) {
     uLong flags;
 
     flags = 0;
@@ -123,9 +121,7 @@ uLong ZEXPORT zlibCompileFlags()
 #  endif
 int ZLIB_INTERNAL z_verbose = verbose;
 
-void ZLIB_INTERNAL z_error(
-    char *m)
-{
+void ZLIB_INTERNAL z_error(char *m) {
     fprintf(stderr, "%s\n", m);
     exit(1);
 }
@@ -134,9 +130,7 @@ void ZLIB_INTERNAL z_error(
 /* exported to allow conversion of error code to string for compress() and
  * uncompress()
  */
-const char * ZEXPORT zError(
-    int err)
-{
+const char * ZEXPORT zError(int err) {
     return ERR_MSG(err);
 }
 
@@ -152,11 +146,7 @@ const char * ZEXPORT zError(
 
 #ifndef HAVE_MEMCPY
 
-void ZLIB_INTERNAL zmemcpy(
-    Bytef* dest,
-    const Bytef* source,
-    uInt  len)
-{
+void ZLIB_INTERNAL zmemcpy(Bytef* dest, const Bytef* source, uInt len) {
     if (len == 0) return;
     do {
         *dest++ = *source++; /* ??? to be unrolled */
@@ -164,12 +154,7 @@ void ZLIB_INTERNAL zmemcpy(
 }
 
 #ifndef Z_FREETYPE
-
-int ZLIB_INTERNAL zmemcmp(
-    const Bytef* s1,
-    const Bytef* s2,
-    uInt  len)
-{
+int ZLIB_INTERNAL zmemcmp(const Bytef* s1, const Bytef* s2, uInt len) {
     uInt j;
 
     for (j = 0; j < len; j++) {
@@ -178,10 +163,7 @@ int ZLIB_INTERNAL zmemcmp(
     return 0;
 }
 
-void ZLIB_INTERNAL zmemzero(
-    Bytef* dest,
-    uInt  len)
-{
+void ZLIB_INTERNAL zmemzero(Bytef* dest, uInt len) {
     if (len == 0) return;
     do {
         *dest++ = 0;  /* ??? to be unrolled */
@@ -223,8 +205,7 @@ local ptr_table table[MAX_PTR];
  * a protected system like OS/2. Use Microsoft C instead.
  */
 
-voidpf ZLIB_INTERNAL zcalloc(voidpf opaque, unsigned items, unsigned size)
-{
+voidpf ZLIB_INTERNAL zcalloc(voidpf opaque, unsigned items, unsigned size) {
     voidpf buf;
     ulg bsize = (ulg)items*size;
 
@@ -249,8 +230,7 @@ voidpf ZLIB_INTERNAL zcalloc(voidpf opaque, unsigned items, unsigned size)
     return buf;
 }
 
-void ZLIB_INTERNAL zcfree(voidpf opaque, voidpf ptr)
-{
+void ZLIB_INTERNAL zcfree(voidpf opaque, voidpf ptr) {
     int n;
 
     (void)opaque;
@@ -286,14 +266,12 @@ void ZLIB_INTERNAL zcfree(voidpf opaque, voidpf ptr)
 #  define _hfree   hfree
 #endif
 
-voidpf ZLIB_INTERNAL zcalloc(voidpf opaque, uInt items, uInt size)
-{
+voidpf ZLIB_INTERNAL zcalloc(voidpf opaque, uInt items, uInt size) {
     (void)opaque;
     return _halloc((long)items, size);
 }
 
-void ZLIB_INTERNAL zcfree(voidpf opaque, voidpf ptr)
-{
+void ZLIB_INTERNAL zcfree(voidpf opaque, voidpf ptr) {
     (void)opaque;
     _hfree(ptr);
 }
@@ -306,25 +284,18 @@ void ZLIB_INTERNAL zcfree(voidpf opaque, voidpf ptr)
 #ifndef MY_ZCALLOC /* Any system without a special alloc function */
 
 #ifndef STDC
-extern voidp  malloc OF((uInt size));
-extern voidp  calloc OF((uInt items, uInt size));
-extern void   free   OF((voidpf ptr));
+extern voidp malloc(uInt size);
+extern voidp calloc(uInt items, uInt size);
+extern void free(voidpf ptr);
 #endif
 
-voidpf ZLIB_INTERNAL zcalloc(
-    voidpf opaque,
-    unsigned items,
-    unsigned size)
-{
+voidpf ZLIB_INTERNAL zcalloc(voidpf opaque, unsigned items, unsigned size) {
     (void)opaque;
     return sizeof(uInt) > 2 ? (voidpf)malloc(items * size) :
                               (voidpf)calloc(items, size);
 }
 
-void ZLIB_INTERNAL zcfree(
-    voidpf opaque,
-    voidpf ptr)
-{
+void ZLIB_INTERNAL zcfree(voidpf opaque, voidpf ptr) {
     (void)opaque;
     free(ptr);
 }
diff --git a/vendor/freetype/src/gzip/zutil.h b/vendor/freetype/src/gzip/zutil.h
index 055ba8b62f..a2c046a1f0 100644
--- a/vendor/freetype/src/gzip/zutil.h
+++ b/vendor/freetype/src/gzip/zutil.h
@@ -56,7 +56,7 @@ typedef unsigned long  ulg;
 #ifndef Z_FREETYPE
 extern z_const char * const z_errmsg[10]; /* indexed by 2-zlib_error */
 /* (size given to avoid silly warnings with Visual C++) */
-#endif  /* !Z_FREETYPE */
+#endif
 
 #define ERR_MSG(err) z_errmsg[Z_NEED_DICT-(err)]
 
@@ -195,9 +195,9 @@ extern z_const char * const z_errmsg[10]; /* indexed by 2-zlib_error */
 /* provide prototypes for these when building zlib without LFS */
 #if !defined(_WIN32) && \
     (!defined(_LARGEFILE64_SOURCE) || _LFS64_LARGEFILE-0 == 0)
-    ZEXTERN uLong ZEXPORT adler32_combine64 OF((uLong, uLong, z_off_t));
-    ZEXTERN uLong ZEXPORT crc32_combine64 OF((uLong, uLong, z_off_t));
-    ZEXTERN uLong ZEXPORT crc32_combine_gen64 OF((z_off_t));
+    ZEXTERN uLong ZEXPORT adler32_combine64(uLong, uLong, z_off_t);
+    ZEXTERN uLong ZEXPORT crc32_combine64(uLong, uLong, z_off_t);
+    ZEXTERN uLong ZEXPORT crc32_combine_gen64(z_off_t);
 #endif
 
 #endif  /* !Z_FREETYPE */
@@ -238,16 +238,16 @@ extern z_const char * const z_errmsg[10]; /* indexed by 2-zlib_error */
 #    define zmemzero(dest, len) ft_memset(dest, 0, len)
 #  endif
 #else
-   void ZLIB_INTERNAL zmemcpy OF((Bytef* dest, const Bytef* source, uInt len));
-   int ZLIB_INTERNAL zmemcmp OF((const Bytef* s1, const Bytef* s2, uInt len));
-   void ZLIB_INTERNAL zmemzero OF((Bytef* dest, uInt len));
+   void ZLIB_INTERNAL zmemcpy(Bytef* dest, const Bytef* source, uInt len);
+   int ZLIB_INTERNAL zmemcmp(const Bytef* s1, const Bytef* s2, uInt len);
+   void ZLIB_INTERNAL zmemzero(Bytef* dest, uInt len);
 #endif
 
 /* Diagnostic functions */
 #ifdef ZLIB_DEBUG
 #  include 
    extern int ZLIB_INTERNAL z_verbose;
-   extern void ZLIB_INTERNAL z_error OF((char *m));
+   extern void ZLIB_INTERNAL z_error(char *m);
 #  define Assert(cond,msg) {if(!(cond)) z_error(msg);}
 #  define Trace(x) {if (z_verbose>=0) fprintf x ;}
 #  define Tracev(x) {if (z_verbose>0) fprintf x ;}
@@ -264,9 +264,9 @@ extern z_const char * const z_errmsg[10]; /* indexed by 2-zlib_error */
 #endif
 
 #ifndef Z_SOLO
-   voidpf ZLIB_INTERNAL zcalloc OF((voidpf opaque, unsigned items,
-                                    unsigned size));
-   void ZLIB_INTERNAL zcfree  OF((voidpf opaque, voidpf ptr));
+   voidpf ZLIB_INTERNAL zcalloc(voidpf opaque, unsigned items,
+                                unsigned size);
+   void ZLIB_INTERNAL zcfree(voidpf opaque, voidpf ptr);
 #endif
 
 #define ZALLOC(strm, items, size) \
diff --git a/vendor/freetype/src/lzw/ftlzw.c b/vendor/freetype/src/lzw/ftlzw.c
index 88383792a8..e1acf22eee 100644
--- a/vendor/freetype/src/lzw/ftlzw.c
+++ b/vendor/freetype/src/lzw/ftlzw.c
@@ -8,7 +8,7 @@
  * be used to parse compressed PCF fonts, as found with many X11 server
  * distributions.
  *
- * Copyright (C) 2004-2023 by
+ * Copyright (C) 2004-2024 by
  * Albert Chin-A-Young.
  *
  * based on code in `src/gzip/ftgzip.c'
diff --git a/vendor/freetype/src/lzw/ftzopen.c b/vendor/freetype/src/lzw/ftzopen.c
index e680c4de59..e42332466f 100644
--- a/vendor/freetype/src/lzw/ftzopen.c
+++ b/vendor/freetype/src/lzw/ftzopen.c
@@ -8,7 +8,7 @@
  * be used to parse compressed PCF fonts, as found with many X11 server
  * distributions.
  *
- * Copyright (C) 2005-2023 by
+ * Copyright (C) 2005-2024 by
  * David Turner.
  *
  * This file is part of the FreeType project, and may only be used,
diff --git a/vendor/freetype/src/lzw/ftzopen.h b/vendor/freetype/src/lzw/ftzopen.h
index 6c7563643f..6915218292 100644
--- a/vendor/freetype/src/lzw/ftzopen.h
+++ b/vendor/freetype/src/lzw/ftzopen.h
@@ -8,7 +8,7 @@
  * be used to parse compressed PCF fonts, as found with many X11 server
  * distributions.
  *
- * Copyright (C) 2005-2023 by
+ * Copyright (C) 2005-2024 by
  * David Turner.
  *
  * This file is part of the FreeType project, and may only be used,
diff --git a/vendor/freetype/src/otvalid/otvalid.c b/vendor/freetype/src/otvalid/otvalid.c
index 3b1e23a6f7..c96967ce65 100644
--- a/vendor/freetype/src/otvalid/otvalid.c
+++ b/vendor/freetype/src/otvalid/otvalid.c
@@ -4,7 +4,7 @@
  *
  *   FreeType validator for OpenType tables (body only).
  *
- * Copyright (C) 2004-2023 by
+ * Copyright (C) 2004-2024 by
  * David Turner, Robert Wilhelm, and Werner Lemberg.
  *
  * This file is part of the FreeType project, and may only be used,
diff --git a/vendor/freetype/src/otvalid/otvalid.h b/vendor/freetype/src/otvalid/otvalid.h
index 7edadb771b..0f46a7a1f5 100644
--- a/vendor/freetype/src/otvalid/otvalid.h
+++ b/vendor/freetype/src/otvalid/otvalid.h
@@ -4,7 +4,7 @@
  *
  *   OpenType table validation (specification only).
  *
- * Copyright (C) 2004-2023 by
+ * Copyright (C) 2004-2024 by
  * David Turner, Robert Wilhelm, and Werner Lemberg.
  *
  * This file is part of the FreeType project, and may only be used,
diff --git a/vendor/freetype/src/otvalid/otvbase.c b/vendor/freetype/src/otvalid/otvbase.c
index f449795f89..610126242a 100644
--- a/vendor/freetype/src/otvalid/otvbase.c
+++ b/vendor/freetype/src/otvalid/otvbase.c
@@ -4,7 +4,7 @@
  *
  *   OpenType BASE table validation (body).
  *
- * Copyright (C) 2004-2023 by
+ * Copyright (C) 2004-2024 by
  * David Turner, Robert Wilhelm, and Werner Lemberg.
  *
  * This file is part of the FreeType project, and may only be used,
diff --git a/vendor/freetype/src/otvalid/otvcommn.c b/vendor/freetype/src/otvalid/otvcommn.c
index b94d8a0651..f06354b781 100644
--- a/vendor/freetype/src/otvalid/otvcommn.c
+++ b/vendor/freetype/src/otvalid/otvcommn.c
@@ -4,7 +4,7 @@
  *
  *   OpenType common tables validation (body).
  *
- * Copyright (C) 2004-2023 by
+ * Copyright (C) 2004-2024 by
  * David Turner, Robert Wilhelm, and Werner Lemberg.
  *
  * This file is part of the FreeType project, and may only be used,
diff --git a/vendor/freetype/src/otvalid/otvcommn.h b/vendor/freetype/src/otvalid/otvcommn.h
index 6702c00085..7db1a575d9 100644
--- a/vendor/freetype/src/otvalid/otvcommn.h
+++ b/vendor/freetype/src/otvalid/otvcommn.h
@@ -4,7 +4,7 @@
  *
  *   OpenType common tables validation (specification).
  *
- * Copyright (C) 2004-2023 by
+ * Copyright (C) 2004-2024 by
  * David Turner, Robert Wilhelm, and Werner Lemberg.
  *
  * This file is part of the FreeType project, and may only be used,
diff --git a/vendor/freetype/src/otvalid/otverror.h b/vendor/freetype/src/otvalid/otverror.h
index 4c4049ca5b..7f4dd6eb63 100644
--- a/vendor/freetype/src/otvalid/otverror.h
+++ b/vendor/freetype/src/otvalid/otverror.h
@@ -4,7 +4,7 @@
  *
  *   OpenType validation module error codes (specification only).
  *
- * Copyright (C) 2004-2023 by
+ * Copyright (C) 2004-2024 by
  * David Turner, Robert Wilhelm, and Werner Lemberg.
  *
  * This file is part of the FreeType project, and may only be used,
diff --git a/vendor/freetype/src/otvalid/otvgdef.c b/vendor/freetype/src/otvalid/otvgdef.c
index d62e8187f6..e36cda754e 100644
--- a/vendor/freetype/src/otvalid/otvgdef.c
+++ b/vendor/freetype/src/otvalid/otvgdef.c
@@ -4,7 +4,7 @@
  *
  *   OpenType GDEF table validation (body).
  *
- * Copyright (C) 2004-2023 by
+ * Copyright (C) 2004-2024 by
  * David Turner, Robert Wilhelm, and Werner Lemberg.
  *
  * This file is part of the FreeType project, and may only be used,
diff --git a/vendor/freetype/src/otvalid/otvgpos.c b/vendor/freetype/src/otvalid/otvgpos.c
index f6102afbce..d7547a33ef 100644
--- a/vendor/freetype/src/otvalid/otvgpos.c
+++ b/vendor/freetype/src/otvalid/otvgpos.c
@@ -4,7 +4,7 @@
  *
  *   OpenType GPOS table validation (body).
  *
- * Copyright (C) 2002-2023 by
+ * Copyright (C) 2002-2024 by
  * David Turner, Robert Wilhelm, and Werner Lemberg.
  *
  * This file is part of the FreeType project, and may only be used,
diff --git a/vendor/freetype/src/otvalid/otvgpos.h b/vendor/freetype/src/otvalid/otvgpos.h
index b5d0f54850..48a9ed0f02 100644
--- a/vendor/freetype/src/otvalid/otvgpos.h
+++ b/vendor/freetype/src/otvalid/otvgpos.h
@@ -4,7 +4,7 @@
  *
  *   OpenType GPOS table validator (specification).
  *
- * Copyright (C) 2004-2023 by
+ * Copyright (C) 2004-2024 by
  * David Turner, Robert Wilhelm, and Werner Lemberg.
  *
  * This file is part of the FreeType project, and may only be used,
diff --git a/vendor/freetype/src/otvalid/otvgsub.c b/vendor/freetype/src/otvalid/otvgsub.c
index 5d40d9243d..a479101b15 100644
--- a/vendor/freetype/src/otvalid/otvgsub.c
+++ b/vendor/freetype/src/otvalid/otvgsub.c
@@ -4,7 +4,7 @@
  *
  *   OpenType GSUB table validation (body).
  *
- * Copyright (C) 2004-2023 by
+ * Copyright (C) 2004-2024 by
  * David Turner, Robert Wilhelm, and Werner Lemberg.
  *
  * This file is part of the FreeType project, and may only be used,
diff --git a/vendor/freetype/src/otvalid/otvjstf.c b/vendor/freetype/src/otvalid/otvjstf.c
index 712039c661..1309f6d906 100644
--- a/vendor/freetype/src/otvalid/otvjstf.c
+++ b/vendor/freetype/src/otvalid/otvjstf.c
@@ -4,7 +4,7 @@
  *
  *   OpenType JSTF table validation (body).
  *
- * Copyright (C) 2004-2023 by
+ * Copyright (C) 2004-2024 by
  * David Turner, Robert Wilhelm, and Werner Lemberg.
  *
  * This file is part of the FreeType project, and may only be used,
diff --git a/vendor/freetype/src/otvalid/otvmath.c b/vendor/freetype/src/otvalid/otvmath.c
index 01fd863c97..b84845a72b 100644
--- a/vendor/freetype/src/otvalid/otvmath.c
+++ b/vendor/freetype/src/otvalid/otvmath.c
@@ -4,7 +4,7 @@
  *
  *   OpenType MATH table validation (body).
  *
- * Copyright (C) 2007-2023 by
+ * Copyright (C) 2007-2024 by
  * David Turner, Robert Wilhelm, and Werner Lemberg.
  *
  * Written by George Williams.
diff --git a/vendor/freetype/src/otvalid/otvmod.c b/vendor/freetype/src/otvalid/otvmod.c
index d6057c5a47..74e50c787d 100644
--- a/vendor/freetype/src/otvalid/otvmod.c
+++ b/vendor/freetype/src/otvalid/otvmod.c
@@ -4,7 +4,7 @@
  *
  *   FreeType's OpenType validation module implementation (body).
  *
- * Copyright (C) 2004-2023 by
+ * Copyright (C) 2004-2024 by
  * David Turner, Robert Wilhelm, and Werner Lemberg.
  *
  * This file is part of the FreeType project, and may only be used,
diff --git a/vendor/freetype/src/otvalid/otvmod.h b/vendor/freetype/src/otvalid/otvmod.h
index f0e68dbc08..245c78020c 100644
--- a/vendor/freetype/src/otvalid/otvmod.h
+++ b/vendor/freetype/src/otvalid/otvmod.h
@@ -5,7 +5,7 @@
  *   FreeType's OpenType validation module implementation
  *   (specification).
  *
- * Copyright (C) 2004-2023 by
+ * Copyright (C) 2004-2024 by
  * David Turner, Robert Wilhelm, and Werner Lemberg.
  *
  * This file is part of the FreeType project, and may only be used,
diff --git a/vendor/freetype/src/pcf/pcfutil.c b/vendor/freetype/src/pcf/pcfutil.c
index 9575726916..cd26c77cad 100644
--- a/vendor/freetype/src/pcf/pcfutil.c
+++ b/vendor/freetype/src/pcf/pcfutil.c
@@ -57,7 +57,7 @@ in this Software without prior written authorization from The Open Group.
   }
 
 
-#if defined( __clang__ )                                            || \
+#if ( defined( __clang_major__ ) && __clang_major__ >= 5 )          || \
     ( defined( __GNUC__ )                                          &&  \
       ( __GNUC__ > 4 || ( __GNUC__ == 4 && __GNUC_MINOR__ >= 8 ) ) )
 
diff --git a/vendor/freetype/src/pfr/pfr.c b/vendor/freetype/src/pfr/pfr.c
index d3738152dc..71b57930b3 100644
--- a/vendor/freetype/src/pfr/pfr.c
+++ b/vendor/freetype/src/pfr/pfr.c
@@ -4,7 +4,7 @@
  *
  *   FreeType PFR driver component.
  *
- * Copyright (C) 2002-2023 by
+ * Copyright (C) 2002-2024 by
  * David Turner, Robert Wilhelm, and Werner Lemberg.
  *
  * This file is part of the FreeType project, and may only be used,
diff --git a/vendor/freetype/src/pfr/pfrcmap.c b/vendor/freetype/src/pfr/pfrcmap.c
index 08fe41d54e..cd701661f1 100644
--- a/vendor/freetype/src/pfr/pfrcmap.c
+++ b/vendor/freetype/src/pfr/pfrcmap.c
@@ -4,7 +4,7 @@
  *
  *   FreeType PFR cmap handling (body).
  *
- * Copyright (C) 2002-2023 by
+ * Copyright (C) 2002-2024 by
  * David Turner, Robert Wilhelm, and Werner Lemberg.
  *
  * This file is part of the FreeType project, and may only be used,
diff --git a/vendor/freetype/src/pfr/pfrcmap.h b/vendor/freetype/src/pfr/pfrcmap.h
index 8110f175e8..ab7913575d 100644
--- a/vendor/freetype/src/pfr/pfrcmap.h
+++ b/vendor/freetype/src/pfr/pfrcmap.h
@@ -4,7 +4,7 @@
  *
  *   FreeType PFR cmap handling (specification).
  *
- * Copyright (C) 2002-2023 by
+ * Copyright (C) 2002-2024 by
  * David Turner, Robert Wilhelm, and Werner Lemberg.
  *
  * This file is part of the FreeType project, and may only be used,
diff --git a/vendor/freetype/src/pfr/pfrdrivr.c b/vendor/freetype/src/pfr/pfrdrivr.c
index 0048f52411..ffd822273f 100644
--- a/vendor/freetype/src/pfr/pfrdrivr.c
+++ b/vendor/freetype/src/pfr/pfrdrivr.c
@@ -4,7 +4,7 @@
  *
  *   FreeType PFR driver interface (body).
  *
- * Copyright (C) 2002-2023 by
+ * Copyright (C) 2002-2024 by
  * David Turner, Robert Wilhelm, and Werner Lemberg.
  *
  * This file is part of the FreeType project, and may only be used,
diff --git a/vendor/freetype/src/pfr/pfrdrivr.h b/vendor/freetype/src/pfr/pfrdrivr.h
index da14468d42..58954a9af0 100644
--- a/vendor/freetype/src/pfr/pfrdrivr.h
+++ b/vendor/freetype/src/pfr/pfrdrivr.h
@@ -4,7 +4,7 @@
  *
  *   High-level Type PFR driver interface (specification).
  *
- * Copyright (C) 2002-2023 by
+ * Copyright (C) 2002-2024 by
  * David Turner, Robert Wilhelm, and Werner Lemberg.
  *
  * This file is part of the FreeType project, and may only be used,
diff --git a/vendor/freetype/src/pfr/pfrerror.h b/vendor/freetype/src/pfr/pfrerror.h
index 5dfb254d66..af0ddaf184 100644
--- a/vendor/freetype/src/pfr/pfrerror.h
+++ b/vendor/freetype/src/pfr/pfrerror.h
@@ -4,7 +4,7 @@
  *
  *   PFR error codes (specification only).
  *
- * Copyright (C) 2002-2023 by
+ * Copyright (C) 2002-2024 by
  * David Turner, Robert Wilhelm, and Werner Lemberg.
  *
  * This file is part of the FreeType project, and may only be used,
diff --git a/vendor/freetype/src/pfr/pfrgload.c b/vendor/freetype/src/pfr/pfrgload.c
index 48cf27ec80..e850075527 100644
--- a/vendor/freetype/src/pfr/pfrgload.c
+++ b/vendor/freetype/src/pfr/pfrgload.c
@@ -4,7 +4,7 @@
  *
  *   FreeType PFR glyph loader (body).
  *
- * Copyright (C) 2002-2023 by
+ * Copyright (C) 2002-2024 by
  * David Turner, Robert Wilhelm, and Werner Lemberg.
  *
  * This file is part of the FreeType project, and may only be used,
@@ -108,7 +108,7 @@
 
     /* don't add empty contours */
     if ( last >= first )
-      outline->contours[outline->n_contours++] = (short)last;
+      outline->contours[outline->n_contours++] = (FT_UShort)last;
 
     glyph->path_begun = 0;
   }
@@ -178,8 +178,8 @@
     error = FT_GLYPHLOADER_CHECK_POINTS( loader, 3, 0 );
     if ( !error )
     {
-      FT_Vector*  vec = outline->points         + outline->n_points;
-      FT_Byte*    tag = (FT_Byte*)outline->tags + outline->n_points;
+      FT_Vector*  vec = outline->points + outline->n_points;
+      FT_Byte*    tag = outline->tags   + outline->n_points;
 
 
       vec[0] = *control1;
@@ -189,7 +189,7 @@
       tag[1] = FT_CURVE_TAG_CUBIC;
       tag[2] = FT_CURVE_TAG_ON;
 
-      outline->n_points = (FT_Short)( outline->n_points + 3 );
+      outline->n_points += 3;
     }
 
   Exit:
diff --git a/vendor/freetype/src/pfr/pfrgload.h b/vendor/freetype/src/pfr/pfrgload.h
index 92a59bc5db..d86549fbe4 100644
--- a/vendor/freetype/src/pfr/pfrgload.h
+++ b/vendor/freetype/src/pfr/pfrgload.h
@@ -4,7 +4,7 @@
  *
  *   FreeType PFR glyph loader (specification).
  *
- * Copyright (C) 2002-2023 by
+ * Copyright (C) 2002-2024 by
  * David Turner, Robert Wilhelm, and Werner Lemberg.
  *
  * This file is part of the FreeType project, and may only be used,
diff --git a/vendor/freetype/src/pfr/pfrload.c b/vendor/freetype/src/pfr/pfrload.c
index 856a5942f5..358af5c78a 100644
--- a/vendor/freetype/src/pfr/pfrload.c
+++ b/vendor/freetype/src/pfr/pfrload.c
@@ -4,7 +4,7 @@
  *
  *   FreeType PFR loader (body).
  *
- * Copyright (C) 2002-2023 by
+ * Copyright (C) 2002-2024 by
  * David Turner, Robert Wilhelm, and Werner Lemberg.
  *
  * This file is part of the FreeType project, and may only be used,
diff --git a/vendor/freetype/src/pfr/pfrload.h b/vendor/freetype/src/pfr/pfrload.h
index d7b20a4572..7390296d4a 100644
--- a/vendor/freetype/src/pfr/pfrload.h
+++ b/vendor/freetype/src/pfr/pfrload.h
@@ -4,7 +4,7 @@
  *
  *   FreeType PFR loader (specification).
  *
- * Copyright (C) 2002-2023 by
+ * Copyright (C) 2002-2024 by
  * David Turner, Robert Wilhelm, and Werner Lemberg.
  *
  * This file is part of the FreeType project, and may only be used,
diff --git a/vendor/freetype/src/pfr/pfrobjs.c b/vendor/freetype/src/pfr/pfrobjs.c
index 8ef17c6636..084d2ef5a1 100644
--- a/vendor/freetype/src/pfr/pfrobjs.c
+++ b/vendor/freetype/src/pfr/pfrobjs.c
@@ -4,7 +4,7 @@
  *
  *   FreeType PFR object methods (body).
  *
- * Copyright (C) 2002-2023 by
+ * Copyright (C) 2002-2024 by
  * David Turner, Robert Wilhelm, and Werner Lemberg.
  *
  * This file is part of the FreeType project, and may only be used,
diff --git a/vendor/freetype/src/pfr/pfrobjs.h b/vendor/freetype/src/pfr/pfrobjs.h
index fcf8c38122..1b548a1bc2 100644
--- a/vendor/freetype/src/pfr/pfrobjs.h
+++ b/vendor/freetype/src/pfr/pfrobjs.h
@@ -4,7 +4,7 @@
  *
  *   FreeType PFR object methods (specification).
  *
- * Copyright (C) 2002-2023 by
+ * Copyright (C) 2002-2024 by
  * David Turner, Robert Wilhelm, and Werner Lemberg.
  *
  * This file is part of the FreeType project, and may only be used,
diff --git a/vendor/freetype/src/pfr/pfrsbit.c b/vendor/freetype/src/pfr/pfrsbit.c
index 46a988e8e3..96cc7fecec 100644
--- a/vendor/freetype/src/pfr/pfrsbit.c
+++ b/vendor/freetype/src/pfr/pfrsbit.c
@@ -4,7 +4,7 @@
  *
  *   FreeType PFR bitmap loader (body).
  *
- * Copyright (C) 2002-2023 by
+ * Copyright (C) 2002-2024 by
  * David Turner, Robert Wilhelm, and Werner Lemberg.
  *
  * This file is part of the FreeType project, and may only be used,
diff --git a/vendor/freetype/src/pfr/pfrsbit.h b/vendor/freetype/src/pfr/pfrsbit.h
index 3e1dba9ae9..105a2991c2 100644
--- a/vendor/freetype/src/pfr/pfrsbit.h
+++ b/vendor/freetype/src/pfr/pfrsbit.h
@@ -4,7 +4,7 @@
  *
  *   FreeType PFR bitmap loader (specification).
  *
- * Copyright (C) 2002-2023 by
+ * Copyright (C) 2002-2024 by
  * David Turner, Robert Wilhelm, and Werner Lemberg.
  *
  * This file is part of the FreeType project, and may only be used,
diff --git a/vendor/freetype/src/pfr/pfrtypes.h b/vendor/freetype/src/pfr/pfrtypes.h
index 2f8909f062..435a77c8f2 100644
--- a/vendor/freetype/src/pfr/pfrtypes.h
+++ b/vendor/freetype/src/pfr/pfrtypes.h
@@ -4,7 +4,7 @@
  *
  *   FreeType PFR data structures (specification only).
  *
- * Copyright (C) 2002-2023 by
+ * Copyright (C) 2002-2024 by
  * David Turner, Robert Wilhelm, and Werner Lemberg.
  *
  * This file is part of the FreeType project, and may only be used,
diff --git a/vendor/freetype/src/psaux/afmparse.c b/vendor/freetype/src/psaux/afmparse.c
index db08941def..e2f6a8e5ad 100644
--- a/vendor/freetype/src/psaux/afmparse.c
+++ b/vendor/freetype/src/psaux/afmparse.c
@@ -4,7 +4,7 @@
  *
  *   AFM parser (body).
  *
- * Copyright (C) 2006-2023 by
+ * Copyright (C) 2006-2024 by
  * David Turner, Robert Wilhelm, and Werner Lemberg.
  *
  * This file is part of the FreeType project, and may only be used,
diff --git a/vendor/freetype/src/psaux/afmparse.h b/vendor/freetype/src/psaux/afmparse.h
index 2d3b6e6e16..b776637282 100644
--- a/vendor/freetype/src/psaux/afmparse.h
+++ b/vendor/freetype/src/psaux/afmparse.h
@@ -4,7 +4,7 @@
  *
  *   AFM parser (specification).
  *
- * Copyright (C) 2006-2023 by
+ * Copyright (C) 2006-2024 by
  * David Turner, Robert Wilhelm, and Werner Lemberg.
  *
  * This file is part of the FreeType project, and may only be used,
diff --git a/vendor/freetype/src/psaux/cffdecode.c b/vendor/freetype/src/psaux/cffdecode.c
index 562d17d221..9556e11a58 100644
--- a/vendor/freetype/src/psaux/cffdecode.c
+++ b/vendor/freetype/src/psaux/cffdecode.c
@@ -4,7 +4,7 @@
  *
  *   PostScript CFF (Type 2) decoding routines (body).
  *
- * Copyright (C) 2017-2023 by
+ * Copyright (C) 2017-2024 by
  * David Turner, Robert Wilhelm, and Werner Lemberg.
  *
  * This file is part of the FreeType project, and may only be used,
@@ -17,6 +17,7 @@
 
 
 #include 
+#include 
 #include 
 #include 
 #include 
@@ -1752,22 +1753,9 @@
 
           /* without upper limit the loop below might not finish */
           if ( args[0] > 0x7FFFFFFFL )
-            args[0] = 46341;
+            args[0] = 0xB504F4L;    /* sqrt( 32768.0044 ) */
           else if ( args[0] > 0 )
-          {
-            FT_Fixed  root = args[0];
-            FT_Fixed  new_root;
-
-
-            for (;;)
-            {
-              new_root = ( root + FT_DivFix( args[0], root ) + 1 ) >> 1;
-              if ( new_root == root )
-                break;
-              root = new_root;
-            }
-            args[0] = new_root;
-          }
+            args[0] = (FT_Fixed)FT_SqrtFixed( args[0] );
           else
             args[0] = 0;
           args++;
diff --git a/vendor/freetype/src/psaux/cffdecode.h b/vendor/freetype/src/psaux/cffdecode.h
index e8bb4001cb..038f7235c3 100644
--- a/vendor/freetype/src/psaux/cffdecode.h
+++ b/vendor/freetype/src/psaux/cffdecode.h
@@ -4,7 +4,7 @@
  *
  *   PostScript CFF (Type 2) decoding routines (specification).
  *
- * Copyright (C) 2017-2023 by
+ * Copyright (C) 2017-2024 by
  * David Turner, Robert Wilhelm, and Werner Lemberg.
  *
  * This file is part of the FreeType project, and may only be used,
diff --git a/vendor/freetype/src/psaux/psaux.c b/vendor/freetype/src/psaux/psaux.c
index 5879ed1635..ffe89cd624 100644
--- a/vendor/freetype/src/psaux/psaux.c
+++ b/vendor/freetype/src/psaux/psaux.c
@@ -4,7 +4,7 @@
  *
  *   FreeType auxiliary PostScript driver component (body only).
  *
- * Copyright (C) 1996-2023 by
+ * Copyright (C) 1996-2024 by
  * David Turner, Robert Wilhelm, and Werner Lemberg.
  *
  * This file is part of the FreeType project, and may only be used,
diff --git a/vendor/freetype/src/psaux/psauxerr.h b/vendor/freetype/src/psaux/psauxerr.h
index 895ffa48c2..18428c40d5 100644
--- a/vendor/freetype/src/psaux/psauxerr.h
+++ b/vendor/freetype/src/psaux/psauxerr.h
@@ -4,7 +4,7 @@
  *
  *   PS auxiliary module error codes (specification only).
  *
- * Copyright (C) 2001-2023 by
+ * Copyright (C) 2001-2024 by
  * David Turner, Robert Wilhelm, and Werner Lemberg.
  *
  * This file is part of the FreeType project, and may only be used,
diff --git a/vendor/freetype/src/psaux/psauxmod.c b/vendor/freetype/src/psaux/psauxmod.c
index 45e35aa53c..6826f9d8d3 100644
--- a/vendor/freetype/src/psaux/psauxmod.c
+++ b/vendor/freetype/src/psaux/psauxmod.c
@@ -4,7 +4,7 @@
  *
  *   FreeType auxiliary PostScript module implementation (body).
  *
- * Copyright (C) 2000-2023 by
+ * Copyright (C) 2000-2024 by
  * David Turner, Robert Wilhelm, and Werner Lemberg.
  *
  * This file is part of the FreeType project, and may only be used,
diff --git a/vendor/freetype/src/psaux/psauxmod.h b/vendor/freetype/src/psaux/psauxmod.h
index 94dbf48813..82d7e348af 100644
--- a/vendor/freetype/src/psaux/psauxmod.h
+++ b/vendor/freetype/src/psaux/psauxmod.h
@@ -4,7 +4,7 @@
  *
  *   FreeType auxiliary PostScript module implementation (specification).
  *
- * Copyright (C) 2000-2023 by
+ * Copyright (C) 2000-2024 by
  * David Turner, Robert Wilhelm, and Werner Lemberg.
  *
  * This file is part of the FreeType project, and may only be used,
diff --git a/vendor/freetype/src/psaux/psblues.c b/vendor/freetype/src/psaux/psblues.c
index f9c864fea9..213b943b46 100644
--- a/vendor/freetype/src/psaux/psblues.c
+++ b/vendor/freetype/src/psaux/psblues.c
@@ -54,14 +54,6 @@
 #define FT_COMPONENT  cf2blues
 
 
-  /*
-   * For blue values, the FreeType parser produces an array of integers,
-   * while the Adobe CFF engine produces an array of fixed.
-   * Define a macro to convert FreeType to fixed.
-   */
-#define cf2_blueToFixed( x )  cf2_intToFixed( x )
-
-
   FT_LOCAL_DEF( void )
   cf2_blues_init( CF2_Blues  blues,
                   CF2_Font   font )
@@ -78,10 +70,10 @@
     size_t  numFamilyBlues;
     size_t  numFamilyOtherBlues;
 
-    FT_Pos*  blueValues;
-    FT_Pos*  otherBlues;
-    FT_Pos*  familyBlues;
-    FT_Pos*  familyOtherBlues;
+    FT_Fixed*  blueValues;
+    FT_Fixed*  otherBlues;
+    FT_Fixed*  familyBlues;
+    FT_Fixed*  familyOtherBlues;
 
     size_t     i;
     CF2_Fixed  emBoxBottom, emBoxTop;
@@ -138,13 +130,13 @@
       emBoxTop    = CF2_ICF_Top;
     }
 
-    if ( cf2_getLanguageGroup( decoder ) == 1                   &&
-         ( numBlueValues == 0                                 ||
-           ( numBlueValues == 4                             &&
-             cf2_blueToFixed( blueValues[0] ) < emBoxBottom &&
-             cf2_blueToFixed( blueValues[1] ) < emBoxBottom &&
-             cf2_blueToFixed( blueValues[2] ) > emBoxTop    &&
-             cf2_blueToFixed( blueValues[3] ) > emBoxTop    ) ) )
+    if ( cf2_getLanguageGroup( decoder ) == 1     &&
+         ( numBlueValues == 0                   ||
+           ( numBlueValues == 4               &&
+             blueValues[0] < emBoxBottom      &&
+             blueValues[1] < emBoxBottom      &&
+             blueValues[2] > emBoxTop         &&
+             blueValues[3] > emBoxTop         ) ) )
     {
       /*
        * Construct hint edges suitable for synthetic ghost hints at top
@@ -189,10 +181,8 @@
     /* bottom zones                                                      */
     for ( i = 0; i < numBlueValues; i += 2 )
     {
-      blues->zone[blues->count].csBottomEdge =
-        cf2_blueToFixed( blueValues[i] );
-      blues->zone[blues->count].csTopEdge =
-        cf2_blueToFixed( blueValues[i + 1] );
+      blues->zone[blues->count].csBottomEdge = blueValues[i];
+      blues->zone[blues->count].csTopEdge    = blueValues[i + 1];
 
       zoneHeight = SUB_INT32( blues->zone[blues->count].csTopEdge,
                               blues->zone[blues->count].csBottomEdge );
@@ -238,10 +228,8 @@
 
     for ( i = 0; i < numOtherBlues; i += 2 )
     {
-      blues->zone[blues->count].csBottomEdge =
-        cf2_blueToFixed( otherBlues[i] );
-      blues->zone[blues->count].csTopEdge =
-        cf2_blueToFixed( otherBlues[i + 1] );
+      blues->zone[blues->count].csBottomEdge = otherBlues[i];
+      blues->zone[blues->count].csTopEdge    = otherBlues[i + 1];
 
       zoneHeight = SUB_INT32( blues->zone[blues->count].csTopEdge,
                               blues->zone[blues->count].csBottomEdge );
@@ -299,7 +287,7 @@
         for ( j = 0; j < numFamilyOtherBlues; j += 2 )
         {
           /* top edge */
-          flatFamilyEdge = cf2_blueToFixed( familyOtherBlues[j + 1] );
+          flatFamilyEdge = familyOtherBlues[j + 1];
 
           diff = cf2_fixedAbs( SUB_INT32( flatEdge, flatFamilyEdge ) );
 
@@ -317,7 +305,7 @@
         if ( numFamilyBlues >= 2 )
         {
           /* top edge */
-          flatFamilyEdge = cf2_blueToFixed( familyBlues[1] );
+          flatFamilyEdge = familyBlues[1];
 
           diff = cf2_fixedAbs( SUB_INT32( flatEdge, flatFamilyEdge ) );
 
@@ -337,7 +325,7 @@
         for ( j = 2; j < numFamilyBlues; j += 2 )
         {
           /* bottom edge */
-          flatFamilyEdge = cf2_blueToFixed( familyBlues[j] );
+          flatFamilyEdge = familyBlues[j];
 
           /* adjust edges of top zone upward by twice darkening amount */
           flatFamilyEdge += 2 * font->darkenY;      /* bottom edge */
diff --git a/vendor/freetype/src/psaux/psconv.c b/vendor/freetype/src/psaux/psconv.c
index b9c7138d84..56c0ecd1d7 100644
--- a/vendor/freetype/src/psaux/psconv.c
+++ b/vendor/freetype/src/psaux/psconv.c
@@ -4,7 +4,7 @@
  *
  *   Some convenience conversions (body).
  *
- * Copyright (C) 2006-2023 by
+ * Copyright (C) 2006-2024 by
  * David Turner, Robert Wilhelm, and Werner Lemberg.
  *
  * This file is part of the FreeType project, and may only be used,
diff --git a/vendor/freetype/src/psaux/psconv.h b/vendor/freetype/src/psaux/psconv.h
index b7c3ee00be..91fcd15a1c 100644
--- a/vendor/freetype/src/psaux/psconv.h
+++ b/vendor/freetype/src/psaux/psconv.h
@@ -4,7 +4,7 @@
  *
  *   Some convenience conversions (specification).
  *
- * Copyright (C) 2006-2023 by
+ * Copyright (C) 2006-2024 by
  * David Turner, Robert Wilhelm, and Werner Lemberg.
  *
  * This file is part of the FreeType project, and may only be used,
diff --git a/vendor/freetype/src/psaux/psft.c b/vendor/freetype/src/psaux/psft.c
index 618864e6e0..fd0abe1715 100644
--- a/vendor/freetype/src/psaux/psft.c
+++ b/vendor/freetype/src/psaux/psft.c
@@ -566,12 +566,12 @@
   FT_LOCAL_DEF( void )
   cf2_getBlueValues( PS_Decoder*  decoder,
                      size_t*      count,
-                     FT_Pos*     *data )
+                     FT_Fixed*   *data )
   {
     FT_ASSERT( decoder && decoder->current_subfont );
 
     *count = decoder->current_subfont->private_dict.num_blue_values;
-    *data  = (FT_Pos*)
+    *data  = (FT_Fixed*)
                &decoder->current_subfont->private_dict.blue_values;
   }
 
@@ -579,12 +579,12 @@
   FT_LOCAL_DEF( void )
   cf2_getOtherBlues( PS_Decoder*  decoder,
                      size_t*      count,
-                     FT_Pos*     *data )
+                     FT_Fixed*   *data )
   {
     FT_ASSERT( decoder && decoder->current_subfont );
 
     *count = decoder->current_subfont->private_dict.num_other_blues;
-    *data  = (FT_Pos*)
+    *data  = (FT_Fixed*)
                &decoder->current_subfont->private_dict.other_blues;
   }
 
@@ -592,12 +592,12 @@
   FT_LOCAL_DEF( void )
   cf2_getFamilyBlues( PS_Decoder*  decoder,
                       size_t*      count,
-                      FT_Pos*     *data )
+                      FT_Fixed*   *data )
   {
     FT_ASSERT( decoder && decoder->current_subfont );
 
     *count = decoder->current_subfont->private_dict.num_family_blues;
-    *data  = (FT_Pos*)
+    *data  = (FT_Fixed*)
                &decoder->current_subfont->private_dict.family_blues;
   }
 
@@ -605,12 +605,12 @@
   FT_LOCAL_DEF( void )
   cf2_getFamilyOtherBlues( PS_Decoder*  decoder,
                            size_t*      count,
-                           FT_Pos*     *data )
+                           FT_Fixed*   *data )
   {
     FT_ASSERT( decoder && decoder->current_subfont );
 
     *count = decoder->current_subfont->private_dict.num_family_other_blues;
-    *data  = (FT_Pos*)
+    *data  = (FT_Fixed*)
                &decoder->current_subfont->private_dict.family_other_blues;
   }
 
diff --git a/vendor/freetype/src/psaux/psft.h b/vendor/freetype/src/psaux/psft.h
index 3da454e601..d9082f3a2b 100644
--- a/vendor/freetype/src/psaux/psft.h
+++ b/vendor/freetype/src/psaux/psft.h
@@ -92,19 +92,19 @@ FT_BEGIN_HEADER
   FT_LOCAL( void )
   cf2_getBlueValues( PS_Decoder*  decoder,
                      size_t*      count,
-                     FT_Pos*     *data );
+                     FT_Fixed*   *data );
   FT_LOCAL( void )
   cf2_getOtherBlues( PS_Decoder*  decoder,
                      size_t*      count,
-                     FT_Pos*     *data );
+                     FT_Fixed*   *data );
   FT_LOCAL( void )
   cf2_getFamilyBlues( PS_Decoder*  decoder,
                       size_t*      count,
-                      FT_Pos*     *data );
+                      FT_Fixed*   *data );
   FT_LOCAL( void )
   cf2_getFamilyOtherBlues( PS_Decoder*  decoder,
                            size_t*      count,
-                           FT_Pos*     *data );
+                           FT_Fixed*   *data );
 
   FT_LOCAL( CF2_Int )
   cf2_getLanguageGroup( PS_Decoder*  decoder );
diff --git a/vendor/freetype/src/psaux/psintrp.c b/vendor/freetype/src/psaux/psintrp.c
index 6c640eebd5..6b445a9968 100644
--- a/vendor/freetype/src/psaux/psintrp.c
+++ b/vendor/freetype/src/psaux/psintrp.c
@@ -37,6 +37,7 @@
 
 
 #include "psft.h"
+#include 
 #include 
 #include 
 
@@ -428,6 +429,8 @@
     base  = cf2_stack_count( opStack ) - numOperands;
     delta = base + numBlends;
 
+    FT_TRACE6(( " (" ));
+
     for ( i = 0; i < numBlends; i++ )
     {
       const CF2_Fixed*  weight = &blend->BV[1];
@@ -442,10 +445,14 @@
                                     cf2_stack_getReal( opStack,
                                                        delta++ ) ) );
 
+      FT_TRACE6(( "%f ", (float) sum / 65536 ));
+
       /* store blended result  */
       cf2_stack_setReal( opStack, i + base, sum );
     }
 
+    FT_TRACE6(( "blended)\n" ));
+
     /* leave only `numBlends' results on stack */
     cf2_stack_pop( opStack, numOperands - numBlends );
   }
@@ -734,7 +741,7 @@
           FT_UInt  numBlends;
 
 
-          FT_TRACE4(( " blend\n" ));
+          FT_TRACE4(( " blend" ));
 
           if ( !font->isCFF2 )
             break;    /* clear stack & ignore */
@@ -2275,23 +2282,7 @@
 
                     arg = cf2_stack_popFixed( opStack );
                     if ( arg > 0 )
-                    {
-                      /* use a start value that doesn't make */
-                      /* the algorithm's addition overflow   */
-                      FT_Fixed  root = arg < 10 ? arg : arg >> 1;
-                      FT_Fixed  new_root;
-
-
-                      /* Babylonian method */
-                      for (;;)
-                      {
-                        new_root = ( root + FT_DivFix( arg, root ) + 1 ) >> 1;
-                        if ( new_root == root )
-                          break;
-                        root = new_root;
-                      }
-                      arg = new_root;
-                    }
+                      arg = (CF2_F16Dot16)FT_SqrtFixed( arg );
                     else
                       arg = 0;
 
diff --git a/vendor/freetype/src/psaux/psobjs.c b/vendor/freetype/src/psaux/psobjs.c
index 8da755d0e5..eca465f009 100644
--- a/vendor/freetype/src/psaux/psobjs.c
+++ b/vendor/freetype/src/psaux/psobjs.c
@@ -4,7 +4,7 @@
  *
  *   Auxiliary functions for PostScript fonts (body).
  *
- * Copyright (C) 1996-2023 by
+ * Copyright (C) 1996-2024 by
  * David Turner, Robert Wilhelm, and Werner Lemberg.
  *
  * This file is part of the FreeType project, and may only be used,
@@ -23,6 +23,7 @@
 
 #include "psobjs.h"
 #include "psconv.h"
+#include "psft.h"
 
 #include "psauxerr.h"
 #include "psauxmod.h"
@@ -200,7 +201,9 @@
     /* add the object to the base block and adjust offset */
     table->elements[idx] = FT_OFFSET( table->block, table->cursor );
     table->lengths [idx] = length;
-    FT_MEM_COPY( table->block + table->cursor, object, length );
+    /* length == 0 also implies a NULL destination, so skip the copy call */
+    if ( length > 0 )
+      FT_MEM_COPY( table->block + table->cursor, object, length );
 
     table->cursor += length;
     return FT_Err_Ok;
@@ -1624,7 +1627,7 @@
     if ( builder->load_points )
     {
       FT_Vector*  point   = outline->points + outline->n_points;
-      FT_Byte*    control = (FT_Byte*)outline->tags + outline->n_points;
+      FT_Byte*    control = outline->tags   + outline->n_points;
 
 
       point->x = FIXED_TO_INT( x );
@@ -1677,8 +1680,7 @@
     if ( !error )
     {
       if ( outline->n_contours > 0 )
-        outline->contours[outline->n_contours - 1] =
-          (short)( outline->n_points - 1 );
+        outline->contours[outline->n_contours - 1] = outline->n_points - 1;
 
       outline->n_contours++;
     }
@@ -1740,7 +1742,7 @@
     {
       FT_Vector*  p1      = outline->points + first;
       FT_Vector*  p2      = outline->points + outline->n_points - 1;
-      FT_Byte*    control = (FT_Byte*)outline->tags + outline->n_points - 1;
+      FT_Byte*    control = outline->tags   + outline->n_points - 1;
 
 
       /* `delete' last point only if it coincides with the first */
@@ -1760,8 +1762,7 @@
         outline->n_points--;
       }
       else
-        outline->contours[outline->n_contours - 1] =
-          (short)( outline->n_points - 1 );
+        outline->contours[outline->n_contours - 1] = outline->n_points - 1;
     }
   }
 
@@ -1899,7 +1900,7 @@
     if ( builder->load_points )
     {
       FT_Vector*  point   = outline->points + outline->n_points;
-      FT_Byte*    control = (FT_Byte*)outline->tags + outline->n_points;
+      FT_Byte*    control = outline->tags   + outline->n_points;
 
 #ifdef CFF_CONFIG_OPTION_OLD_ENGINE
       PS_Driver  driver   = (PS_Driver)FT_FACE_DRIVER( builder->face );
@@ -1959,8 +1960,7 @@
     if ( !error )
     {
       if ( outline->n_contours > 0 )
-        outline->contours[outline->n_contours - 1] =
-          (short)( outline->n_points - 1 );
+        outline->contours[outline->n_contours - 1] = outline->n_points - 1;
 
       outline->n_contours++;
     }
@@ -2019,7 +2019,7 @@
     {
       FT_Vector*  p1      = outline->points + first;
       FT_Vector*  p2      = outline->points + outline->n_points - 1;
-      FT_Byte*    control = (FT_Byte*)outline->tags + outline->n_points - 1;
+      FT_Byte*    control = outline->tags   + outline->n_points - 1;
 
 
       /* `delete' last point only if it coincides with the first    */
@@ -2039,8 +2039,7 @@
         outline->n_points--;
       }
       else
-        outline->contours[outline->n_contours - 1] =
-          (short)( outline->n_points - 1 );
+        outline->contours[outline->n_contours - 1] = outline->n_points - 1;
     }
   }
 
@@ -2188,7 +2187,7 @@
     if ( builder->load_points )
     {
       FT_Vector*  point   = outline->points + outline->n_points;
-      FT_Byte*    control = (FT_Byte*)outline->tags + outline->n_points;
+      FT_Byte*    control = outline->tags   + outline->n_points;
 
 #ifdef CFF_CONFIG_OPTION_OLD_ENGINE
       PS_Driver  driver   = (PS_Driver)FT_FACE_DRIVER( builder->face );
@@ -2267,8 +2266,7 @@
     if ( !error )
     {
       if ( outline->n_contours > 0 )
-        outline->contours[outline->n_contours - 1] =
-          (short)( outline->n_points - 1 );
+        outline->contours[outline->n_contours - 1] = outline->n_points - 1;
 
       outline->n_contours++;
     }
@@ -2327,7 +2325,7 @@
     {
       FT_Vector*  p1      = outline->points + first;
       FT_Vector*  p2      = outline->points + outline->n_points - 1;
-      FT_Byte*    control = (FT_Byte*)outline->tags + outline->n_points - 1;
+      FT_Byte*    control = outline->tags   + outline->n_points - 1;
 
 
       /* `delete' last point only if it coincides with the first */
@@ -2347,8 +2345,7 @@
         outline->n_points--;
       }
       else
-        outline->contours[outline->n_contours - 1] =
-          (short)( outline->n_points - 1 );
+        outline->contours[outline->n_contours - 1] = outline->n_points - 1;
     }
   }
 
@@ -2463,19 +2460,20 @@
 
     count = cpriv->num_blue_values = priv->num_blue_values;
     for ( n = 0; n < count; n++ )
-      cpriv->blue_values[n] = (FT_Pos)priv->blue_values[n];
+      cpriv->blue_values[n] = cf2_intToFixed( priv->blue_values[n] );
 
     count = cpriv->num_other_blues = priv->num_other_blues;
     for ( n = 0; n < count; n++ )
-      cpriv->other_blues[n] = (FT_Pos)priv->other_blues[n];
+      cpriv->other_blues[n] = cf2_intToFixed( priv->other_blues[n] );
 
     count = cpriv->num_family_blues = priv->num_family_blues;
     for ( n = 0; n < count; n++ )
-      cpriv->family_blues[n] = (FT_Pos)priv->family_blues[n];
+      cpriv->family_blues[n] = cf2_intToFixed( priv->family_blues[n] );
 
     count = cpriv->num_family_other_blues = priv->num_family_other_blues;
     for ( n = 0; n < count; n++ )
-      cpriv->family_other_blues[n] = (FT_Pos)priv->family_other_blues[n];
+      cpriv->family_other_blues[n] =
+        cf2_intToFixed( priv->family_other_blues[n] );
 
     cpriv->blue_scale = priv->blue_scale;
     cpriv->blue_shift = (FT_Pos)priv->blue_shift;
diff --git a/vendor/freetype/src/psaux/psobjs.h b/vendor/freetype/src/psaux/psobjs.h
index d5bce54108..345fc8a733 100644
--- a/vendor/freetype/src/psaux/psobjs.h
+++ b/vendor/freetype/src/psaux/psobjs.h
@@ -4,7 +4,7 @@
  *
  *   Auxiliary functions for PostScript fonts (specification).
  *
- * Copyright (C) 1996-2023 by
+ * Copyright (C) 1996-2024 by
  * David Turner, Robert Wilhelm, and Werner Lemberg.
  *
  * This file is part of the FreeType project, and may only be used,
diff --git a/vendor/freetype/src/psaux/t1cmap.c b/vendor/freetype/src/psaux/t1cmap.c
index c4bcf599ea..5681c3bd0f 100644
--- a/vendor/freetype/src/psaux/t1cmap.c
+++ b/vendor/freetype/src/psaux/t1cmap.c
@@ -4,7 +4,7 @@
  *
  *   Type 1 character map support (body).
  *
- * Copyright (C) 2002-2023 by
+ * Copyright (C) 2002-2024 by
  * David Turner, Robert Wilhelm, and Werner Lemberg.
  *
  * This file is part of the FreeType project, and may only be used,
diff --git a/vendor/freetype/src/psaux/t1cmap.h b/vendor/freetype/src/psaux/t1cmap.h
index b3702498a5..445e6a2784 100644
--- a/vendor/freetype/src/psaux/t1cmap.h
+++ b/vendor/freetype/src/psaux/t1cmap.h
@@ -4,7 +4,7 @@
  *
  *   Type 1 character map support (specification).
  *
- * Copyright (C) 2002-2023 by
+ * Copyright (C) 2002-2024 by
  * David Turner, Robert Wilhelm, and Werner Lemberg.
  *
  * This file is part of the FreeType project, and may only be used,
diff --git a/vendor/freetype/src/psaux/t1decode.c b/vendor/freetype/src/psaux/t1decode.c
index 4b6b969bcb..c74baa8038 100644
--- a/vendor/freetype/src/psaux/t1decode.c
+++ b/vendor/freetype/src/psaux/t1decode.c
@@ -4,7 +4,7 @@
  *
  *   PostScript Type 1 decoding routines (body).
  *
- * Copyright (C) 2000-2023 by
+ * Copyright (C) 2000-2024 by
  * David Turner, Robert Wilhelm, and Werner Lemberg.
  *
  * This file is part of the FreeType project, and may only be used,
diff --git a/vendor/freetype/src/psaux/t1decode.h b/vendor/freetype/src/psaux/t1decode.h
index 0970def960..16203b8f73 100644
--- a/vendor/freetype/src/psaux/t1decode.h
+++ b/vendor/freetype/src/psaux/t1decode.h
@@ -4,7 +4,7 @@
  *
  *   PostScript Type 1 decoding routines (specification).
  *
- * Copyright (C) 2000-2023 by
+ * Copyright (C) 2000-2024 by
  * David Turner, Robert Wilhelm, and Werner Lemberg.
  *
  * This file is part of the FreeType project, and may only be used,
diff --git a/vendor/freetype/src/pshinter/pshalgo.c b/vendor/freetype/src/pshinter/pshalgo.c
index 4f622e1e44..967767b348 100644
--- a/vendor/freetype/src/pshinter/pshalgo.c
+++ b/vendor/freetype/src/pshinter/pshalgo.c
@@ -4,7 +4,7 @@
  *
  *   PostScript hinting algorithm (body).
  *
- * Copyright (C) 2001-2023 by
+ * Copyright (C) 2001-2024 by
  * David Turner, Robert Wilhelm, and Werner Lemberg.
  *
  * This file is part of the FreeType project, and may only be used
@@ -1118,7 +1118,7 @@
     FT_UInt     n;
     PSH_Point   point = glyph->points;
     FT_Vector*  vec   = glyph->outline->points;
-    char*       tags  = glyph->outline->tags;
+    FT_Byte*    tags  = glyph->outline->tags;
 
 
     for ( n = 0; n < glyph->num_points; n++ )
@@ -1171,8 +1171,8 @@
          FT_QNEW_ARRAY( glyph->contours, outline->n_contours ) )
       goto Exit;
 
-    glyph->num_points   = (FT_UInt)outline->n_points;
-    glyph->num_contours = (FT_UInt)outline->n_contours;
+    glyph->num_points   = outline->n_points;
+    glyph->num_contours = outline->n_contours;
 
     {
       FT_UInt      first = 0, next, n;
@@ -1186,7 +1186,7 @@
         PSH_Point  point;
 
 
-        next  = (FT_UInt)outline->contours[n] + 1;
+        next  = outline->contours[n] + 1;
         count = next - first;
 
         contour->start = points + first;
diff --git a/vendor/freetype/src/pshinter/pshalgo.h b/vendor/freetype/src/pshinter/pshalgo.h
index 3f0ba28a69..fb362f061b 100644
--- a/vendor/freetype/src/pshinter/pshalgo.h
+++ b/vendor/freetype/src/pshinter/pshalgo.h
@@ -4,7 +4,7 @@
  *
  *   PostScript hinting algorithm (specification).
  *
- * Copyright (C) 2001-2023 by
+ * Copyright (C) 2001-2024 by
  * David Turner, Robert Wilhelm, and Werner Lemberg.
  *
  * This file is part of the FreeType project, and may only be used,
diff --git a/vendor/freetype/src/pshinter/pshglob.c b/vendor/freetype/src/pshinter/pshglob.c
index d4c5eb32b1..435f45838f 100644
--- a/vendor/freetype/src/pshinter/pshglob.c
+++ b/vendor/freetype/src/pshinter/pshglob.c
@@ -5,7 +5,7 @@
  *   PostScript hinter global hinting management (body).
  *   Inspired by the new auto-hinter module.
  *
- * Copyright (C) 2001-2023 by
+ * Copyright (C) 2001-2024 by
  * David Turner, Robert Wilhelm, and Werner Lemberg.
  *
  * This file is part of the FreeType project, and may only be used
diff --git a/vendor/freetype/src/pshinter/pshglob.h b/vendor/freetype/src/pshinter/pshglob.h
index 579eb2148a..c5a5c91316 100644
--- a/vendor/freetype/src/pshinter/pshglob.h
+++ b/vendor/freetype/src/pshinter/pshglob.h
@@ -4,7 +4,7 @@
  *
  *   PostScript hinter global hinting management.
  *
- * Copyright (C) 2001-2023 by
+ * Copyright (C) 2001-2024 by
  * David Turner, Robert Wilhelm, and Werner Lemberg.
  *
  * This file is part of the FreeType project, and may only be used,
diff --git a/vendor/freetype/src/pshinter/pshinter.c b/vendor/freetype/src/pshinter/pshinter.c
index 54ed410966..ae2b53fee5 100644
--- a/vendor/freetype/src/pshinter/pshinter.c
+++ b/vendor/freetype/src/pshinter/pshinter.c
@@ -4,7 +4,7 @@
  *
  *   FreeType PostScript Hinting module
  *
- * Copyright (C) 2001-2023 by
+ * Copyright (C) 2001-2024 by
  * David Turner, Robert Wilhelm, and Werner Lemberg.
  *
  * This file is part of the FreeType project, and may only be used,
diff --git a/vendor/freetype/src/pshinter/pshmod.c b/vendor/freetype/src/pshinter/pshmod.c
index 974a99e018..9965d5b16b 100644
--- a/vendor/freetype/src/pshinter/pshmod.c
+++ b/vendor/freetype/src/pshinter/pshmod.c
@@ -4,7 +4,7 @@
  *
  *   FreeType PostScript hinter module implementation (body).
  *
- * Copyright (C) 2001-2023 by
+ * Copyright (C) 2001-2024 by
  * David Turner, Robert Wilhelm, and Werner Lemberg.
  *
  * This file is part of the FreeType project, and may only be used,
diff --git a/vendor/freetype/src/pshinter/pshmod.h b/vendor/freetype/src/pshinter/pshmod.h
index 4bd781a35d..62ac0a60fd 100644
--- a/vendor/freetype/src/pshinter/pshmod.h
+++ b/vendor/freetype/src/pshinter/pshmod.h
@@ -4,7 +4,7 @@
  *
  *   PostScript hinter module interface (specification).
  *
- * Copyright (C) 2001-2023 by
+ * Copyright (C) 2001-2024 by
  * David Turner, Robert Wilhelm, and Werner Lemberg.
  *
  * This file is part of the FreeType project, and may only be used,
diff --git a/vendor/freetype/src/pshinter/pshnterr.h b/vendor/freetype/src/pshinter/pshnterr.h
index 97624952d8..e9641340e5 100644
--- a/vendor/freetype/src/pshinter/pshnterr.h
+++ b/vendor/freetype/src/pshinter/pshnterr.h
@@ -4,7 +4,7 @@
  *
  *   PS Hinter error codes (specification only).
  *
- * Copyright (C) 2003-2023 by
+ * Copyright (C) 2003-2024 by
  * David Turner, Robert Wilhelm, and Werner Lemberg.
  *
  * This file is part of the FreeType project, and may only be used,
diff --git a/vendor/freetype/src/pshinter/pshrec.c b/vendor/freetype/src/pshinter/pshrec.c
index 680e6d0135..0b2b549fc2 100644
--- a/vendor/freetype/src/pshinter/pshrec.c
+++ b/vendor/freetype/src/pshinter/pshrec.c
@@ -4,7 +4,7 @@
  *
  *   FreeType PostScript hints recorder (body).
  *
- * Copyright (C) 2001-2023 by
+ * Copyright (C) 2001-2024 by
  * David Turner, Robert Wilhelm, and Werner Lemberg.
  *
  * This file is part of the FreeType project, and may only be used,
@@ -806,7 +806,7 @@
   ps_hints_stem( PS_Hints  hints,
                  FT_UInt   dimension,
                  FT_Int    count,
-                 FT_Long*  stems )
+                 FT_Pos*   stems )
   {
     PS_Dimension  dim;
 
diff --git a/vendor/freetype/src/pshinter/pshrec.h b/vendor/freetype/src/pshinter/pshrec.h
index 0b2484af12..7e375af7ba 100644
--- a/vendor/freetype/src/pshinter/pshrec.h
+++ b/vendor/freetype/src/pshinter/pshrec.h
@@ -4,7 +4,7 @@
  *
  *   Postscript (Type1/Type2) hints recorder (specification).
  *
- * Copyright (C) 2001-2023 by
+ * Copyright (C) 2001-2024 by
  * David Turner, Robert Wilhelm, and Werner Lemberg.
  *
  * This file is part of the FreeType project, and may only be used,
diff --git a/vendor/freetype/src/psnames/psmodule.c b/vendor/freetype/src/psnames/psmodule.c
index 8203a0465d..35d054d1cf 100644
--- a/vendor/freetype/src/psnames/psmodule.c
+++ b/vendor/freetype/src/psnames/psmodule.c
@@ -4,7 +4,7 @@
  *
  *   psnames module implementation (body).
  *
- * Copyright (C) 1996-2023 by
+ * Copyright (C) 1996-2024 by
  * David Turner, Robert Wilhelm, and Werner Lemberg.
  *
  * This file is part of the FreeType project, and may only be used,
diff --git a/vendor/freetype/src/psnames/psmodule.h b/vendor/freetype/src/psnames/psmodule.h
index 0904700bfb..770458316b 100644
--- a/vendor/freetype/src/psnames/psmodule.h
+++ b/vendor/freetype/src/psnames/psmodule.h
@@ -4,7 +4,7 @@
  *
  *   High-level psnames module interface (specification).
  *
- * Copyright (C) 1996-2023 by
+ * Copyright (C) 1996-2024 by
  * David Turner, Robert Wilhelm, and Werner Lemberg.
  *
  * This file is part of the FreeType project, and may only be used,
diff --git a/vendor/freetype/src/psnames/psnamerr.h b/vendor/freetype/src/psnames/psnamerr.h
index 0073f82284..e123eb65e3 100644
--- a/vendor/freetype/src/psnames/psnamerr.h
+++ b/vendor/freetype/src/psnames/psnamerr.h
@@ -4,7 +4,7 @@
  *
  *   PS names module error codes (specification only).
  *
- * Copyright (C) 2001-2023 by
+ * Copyright (C) 2001-2024 by
  * David Turner, Robert Wilhelm, and Werner Lemberg.
  *
  * This file is part of the FreeType project, and may only be used,
diff --git a/vendor/freetype/src/psnames/psnames.c b/vendor/freetype/src/psnames/psnames.c
index 93ed9332fa..2933af1bf5 100644
--- a/vendor/freetype/src/psnames/psnames.c
+++ b/vendor/freetype/src/psnames/psnames.c
@@ -4,7 +4,7 @@
  *
  *   FreeType psnames module component (body only).
  *
- * Copyright (C) 1996-2023 by
+ * Copyright (C) 1996-2024 by
  * David Turner, Robert Wilhelm, and Werner Lemberg.
  *
  * This file is part of the FreeType project, and may only be used,
diff --git a/vendor/freetype/src/psnames/pstables.h b/vendor/freetype/src/psnames/pstables.h
index 7f92cce603..2a941b0460 100644
--- a/vendor/freetype/src/psnames/pstables.h
+++ b/vendor/freetype/src/psnames/pstables.h
@@ -4,7 +4,7 @@
  *
  *   PostScript glyph names.
  *
- * Copyright (C) 2005-2023 by
+ * Copyright (C) 2005-2024 by
  * David Turner, Robert Wilhelm, and Werner Lemberg.
  *
  * This file is part of the FreeType project, and may only be used,
diff --git a/vendor/freetype/src/raster/ftmisc.h b/vendor/freetype/src/raster/ftmisc.h
index 33dbfd631e..943f2aa0a5 100644
--- a/vendor/freetype/src/raster/ftmisc.h
+++ b/vendor/freetype/src/raster/ftmisc.h
@@ -5,7 +5,7 @@
  *   Miscellaneous macros for stand-alone rasterizer (specification
  *   only).
  *
- * Copyright (C) 2005-2023 by
+ * Copyright (C) 2005-2024 by
  * David Turner, Robert Wilhelm, and Werner Lemberg.
  *
  * This file is part of the FreeType project, and may only be used
@@ -92,27 +92,6 @@
 #endif
 
 
-  static FT_Long
-  FT_MulDiv( FT_Long  a,
-             FT_Long  b,
-             FT_Long  c )
-  {
-    FT_Int   s;
-    FT_Long  d;
-
-
-    s = 1;
-    if ( a < 0 ) { a = -a; s = -1; }
-    if ( b < 0 ) { b = -b; s = -s; }
-    if ( c < 0 ) { c = -c; s = -s; }
-
-    d = (FT_Long)( c > 0 ? ( (FT_Int64)a * b + ( c >> 1 ) ) / c
-                         : 0x7FFFFFFFL );
-
-    return ( s > 0 ) ? d : -d;
-  }
-
-
   static FT_Long
   FT_MulDiv_No_Round( FT_Long  a,
                       FT_Long  b,
diff --git a/vendor/freetype/src/raster/ftraster.c b/vendor/freetype/src/raster/ftraster.c
index 192ca0701a..e4b7b937d5 100644
--- a/vendor/freetype/src/raster/ftraster.c
+++ b/vendor/freetype/src/raster/ftraster.c
@@ -4,7 +4,7 @@
  *
  *   The FreeType glyph rasterizer (body).
  *
- * Copyright (C) 1996-2023 by
+ * Copyright (C) 1996-2024 by
  * David Turner, Robert Wilhelm, and Werner Lemberg.
  *
  * This file is part of the FreeType project, and may only be used,
@@ -63,8 +63,7 @@
 #else /* !STANDALONE_ */
 
 #include "ftraster.h"
-#include  /* for FT_MulDiv and FT_MulDiv_No_Round */
-#include          /* for FT_Outline_Get_CBox              */
+#include  /* for FT_MulDiv_No_Round */
 
 #endif /* !STANDALONE_ */
 
@@ -115,12 +114,12 @@
    *   a change of direction is detected in the outline, a new profile is
    *   generated until the end of the outline.
    *
-   *   Note that when all profiles have been generated, the function
-   *   Finalize_Profile_Table() is used to record, for each profile, its
-   *   bottom-most scanline as well as the scanline above its upmost
-   *   boundary.  These positions are called `y-turns' because they (sort
-   *   of) correspond to local extrema.  They are stored in a sorted list
-   *   built from the top of the render pool as a downwards stack:
+   *   Note that, for all generated profiles, the function End_Profile()
+   *   is used to record all their bottom-most scanlines as well as the
+   *   scanline above their upmost boundary.  These positions are called
+   *   `y-turns' because they (sort of) correspond to local extrema.
+   *   They are stored in a sorted list built from the top of the render
+   *   pool as a downwards stack:
    *
    *     _ _ _______________________________________
    *                           |                    |
@@ -136,7 +135,7 @@
    *   optimize performance (see technical note on the sweep below).
    *
    *   Of course, the raster detects whether the two stacks collide and
-   *   handles the situation properly.
+   *   handles the situation by bisecting the job and restarting.
    *
    */
 
@@ -252,7 +251,6 @@
   /* On the other hand, SMulDiv means `Slow MulDiv', and is used typically */
   /* for clipping computations.  It simply uses the FT_MulDiv() function   */
   /* defined in `ftcalc.h'.                                                */
-#define SMulDiv           FT_MulDiv
 #define SMulDiv_No_Round  FT_MulDiv_No_Round
 
   /* The rasterizer is a very general purpose component; please leave */
@@ -305,16 +303,6 @@
   typedef unsigned char   Byte, *PByte;
   typedef char            Bool;
 
-
-  typedef union  Alignment_
-  {
-    Long    l;
-    void*   p;
-    void  (*f)(void);
-
-  } Alignment, *PAlignment;
-
-
   typedef struct  TPoint_
   {
     Long  x;
@@ -327,6 +315,7 @@
 #define Flow_Up           0x08U
 #define Overshoot_Top     0x10U
 #define Overshoot_Bottom  0x20U
+#define Dropout           0x40U
 
 
   /* States of each line, arc, and profile */
@@ -345,31 +334,28 @@
 
   struct  TProfile_
   {
-    FT_F26Dot6  X;           /* current coordinate during sweep          */
     PProfile    link;        /* link to next profile (various purposes)  */
-    PLong       offset;      /* start of profile's data in render pool   */
+    PProfile    next;        /* next profile in same contour, used       */
+                             /* during drop-out control                  */
+    Int         offset;      /* bottom or currently scanned array index  */
+    Int         height;      /* profile's height in scanlines            */
+    Int         start;       /* profile's starting scanline, also use    */
+                             /* as activation counter                    */
     UShort      flags;       /* Bit 0-2: drop-out mode                   */
                              /* Bit 3: profile orientation (up/down)     */
                              /* Bit 4: is top profile?                   */
                              /* Bit 5: is bottom profile?                */
-    Long        height;      /* profile's height in scanlines            */
-    Long        start;       /* profile's starting scanline              */
+                             /* Bit 6: dropout detected                  */
 
-    Int         countL;      /* number of lines to step before this      */
-                             /* profile becomes drawable                 */
-
-    PProfile    next;        /* next profile in same contour, used       */
-                             /* during drop-out control                  */
+    FT_F26Dot6  X;           /* current coordinate during sweep          */
+    Long        x[1];        /* actually variable array of scanline      */
+                             /* intersections with `height` elements     */
   };
 
   typedef PProfile   TProfileList;
   typedef PProfile*  PProfileList;
 
 
-#define AlignProfileSize \
-  ( ( sizeof ( TProfile ) + sizeof ( Alignment ) - 1 ) / sizeof ( Long ) )
-
-
 #undef RAS_ARG
 #undef RAS_ARGS
 #undef RAS_VAR
@@ -407,15 +393,13 @@
 
   /* prototypes used for sweep function dispatch */
   typedef void
-  Function_Sweep_Init( RAS_ARGS Short  min,
-                                Short  max );
+  Function_Sweep_Init( RAS_ARGS Int  min,
+                                Int  max );
 
   typedef void
-  Function_Sweep_Span( RAS_ARGS Short       y,
+  Function_Sweep_Span( RAS_ARGS Int         y,
                                 FT_F26Dot6  x1,
-                                FT_F26Dot6  x2,
-                                PProfile    left,
-                                PProfile    right );
+                                FT_F26Dot6  x2 );
 
   typedef void
   Function_Sweep_Step( RAS_ARG );
@@ -441,8 +425,7 @@
           (Bool)( x - FLOOR( x ) >= ras.precision_half )
 
   /* Smart dropout rounding to find which pixel is closer to span ends. */
-  /* To mimick Windows, symmetric cases break down indepenently of the  */
-  /* precision.                                                         */
+  /* To mimic Windows, symmetric cases do not depend on the precision.  */
 #define SMART( p, q )  FLOOR( ( (p) + (q) + ras.precision * 63 / 64 ) >> 1 )
 
 #if FT_RENDER_POOL_SIZE > 2048
@@ -462,7 +445,6 @@
     Int         precision_half;
     Int         precision_scale;
     Int         precision_step;
-    Int         precision_jitter;
 
     PLong       buff;               /* The profiles buffer                 */
     PLong       sizeBuff;           /* Render pool size                    */
@@ -471,24 +453,14 @@
 
     FT_Error    error;
 
-    Int         numTurns;           /* number of Y-turns in outline        */
-
     Byte        dropOutControl;     /* current drop_out control method     */
 
-    UShort      bWidth;             /* target bitmap width                 */
-    PByte       bOrigin;            /* target bitmap bottom-left origin    */
-    PByte       bLine;              /* target bitmap current line          */
-
     Long        lastX, lastY;
     Long        minY, maxY;
 
     UShort      num_Profs;          /* current number of profiles          */
+    Int         numTurns;           /* number of Y-turns in outline        */
 
-    Bool        fresh;              /* signals a fresh new profile which   */
-                                    /* `start' field must be completed     */
-    Bool        joint;              /* signals that the last arc ended     */
-                                    /* exactly on a scanline.  Allows      */
-                                    /* removal of doublets                 */
     PProfile    cProfile;           /* current profile                     */
     PProfile    fProfile;           /* head of linked list of profiles     */
     PProfile    gProfile;           /* contour's first profile in case     */
@@ -496,9 +468,14 @@
 
     TStates     state;              /* rendering state                     */
 
-    FT_Bitmap   target;             /* description of target bit/pixmap    */
     FT_Outline  outline;
 
+    Int         bTop;               /* target bitmap max line  index       */
+    Int         bRight;             /* target bitmap rightmost index       */
+    Int         bPitch;             /* target bitmap pitch                 */
+    PByte       bOrigin;            /* target bitmap bottom-left origin    */
+    PByte       bLine;              /* target bitmap current line          */
+
     /* dispatch variables */
 
     Function_Sweep_Init*  Proc_Sweep_Init;
@@ -563,37 +540,82 @@
      *
      *   256 / (1 << 12) = 0.0625 pixels.
      *
-     * `precision_jitter' is an epsilon threshold used in
-     * `Vertical_Sweep_Span' to deal with small imperfections in the Bezier
-     * decomposition (after all, we are working with approximations only);
-     * it avoids switching on additional pixels which would cause artifacts
-     * otherwise.
-     *
-     * The value of `precision_jitter' has been determined heuristically.
-     *
      */
 
     if ( High )
     {
       ras.precision_bits   = 12;
       ras.precision_step   = 256;
-      ras.precision_jitter = 30;
     }
     else
     {
       ras.precision_bits   = 6;
       ras.precision_step   = 32;
-      ras.precision_jitter = 2;
     }
 
-    FT_TRACE6(( "Set_High_Precision(%s)\n", High ? "true" : "false" ));
-
     ras.precision       = 1 << ras.precision_bits;
     ras.precision_half  = ras.precision >> 1;
     ras.precision_scale = ras.precision >> Pixel_Bits;
   }
 
 
+  /**************************************************************************
+   *
+   * @Function:
+   *   Insert_Y_Turn
+   *
+   * @Description:
+   *   Insert a salient into the sorted list placed on top of the render
+   *   pool.
+   *
+   * @Input:
+   *   New y scanline position.
+   *
+   * @Return:
+   *   SUCCESS on success.  FAILURE in case of overflow.
+   */
+  static Bool
+  Insert_Y_Turns( RAS_ARGS Int  y,
+                           Int  top )
+  {
+    Int    n       = ras.numTurns;
+    PLong  y_turns = ras.maxBuff;
+
+
+    /* update top value */
+    if ( n == 0 || top > y_turns[n] )
+      y_turns[n] = top;
+
+    /* look for first y value that is <= */
+    while ( n-- && y < y_turns[n] )
+      ;
+
+    /* if it is <, simply insert it, ignore if == */
+    if ( n < 0 || y > y_turns[n] )
+    {
+      ras.maxBuff--;
+      if ( ras.maxBuff <= ras.top )
+      {
+        ras.error = FT_THROW( Raster_Overflow );
+        return FAILURE;
+      }
+
+      do
+      {
+        Int  y2 = (Int)y_turns[n];
+
+
+        y_turns[n] = y;
+        y = y2;
+      } while ( n-- >= 0 );
+
+      ras.numTurns++;
+    }
+
+    return SUCCESS;
+  }
+
+
   /**************************************************************************
    *
    * @Function:
@@ -606,52 +628,48 @@
    *   aState ::
    *     The state/orientation of the new profile.
    *
-   *   overshoot ::
-   *     Whether the profile's unrounded start position
-   *     differs by at least a half pixel.
-   *
    * @Return:
    *  SUCCESS on success.  FAILURE in case of overflow or of incoherent
    *  profile.
    */
   static Bool
-  New_Profile( RAS_ARGS TStates  aState,
-                        Bool     overshoot )
+  New_Profile( RAS_ARGS TStates  aState )
   {
-    if ( !ras.fProfile )
+    Long  e;
+
+
+    if ( !ras.cProfile || ras.cProfile->height )
     {
       ras.cProfile  = (PProfile)ras.top;
-      ras.fProfile  = ras.cProfile;
-      ras.top      += AlignProfileSize;
-    }
+      ras.top       = ras.cProfile->x;
 
-    if ( ras.top >= ras.maxBuff )
-    {
-      ras.error = FT_THROW( Raster_Overflow );
-      return FAILURE;
+      if ( ras.top >= ras.maxBuff )
+      {
+        FT_TRACE1(( "overflow in New_Profile\n" ));
+        ras.error = FT_THROW( Raster_Overflow );
+        return FAILURE;
+      }
+
+      ras.cProfile->height = 0;
     }
 
-    ras.cProfile->start  = 0;
-    ras.cProfile->height = 0;
-    ras.cProfile->offset = ras.top;
-    ras.cProfile->link   = (PProfile)0;
-    ras.cProfile->next   = (PProfile)0;
     ras.cProfile->flags  = ras.dropOutControl;
 
     switch ( aState )
     {
     case Ascending_State:
       ras.cProfile->flags |= Flow_Up;
-      if ( overshoot )
+      if ( IS_BOTTOM_OVERSHOOT( ras.lastY ) )
         ras.cProfile->flags |= Overshoot_Bottom;
 
-      FT_TRACE6(( "  new ascending profile = %p\n", (void *)ras.cProfile ));
+      e = CEILING( ras.lastY );
       break;
 
     case Descending_State:
-      if ( overshoot )
+      if ( IS_TOP_OVERSHOOT( ras.lastY ) )
         ras.cProfile->flags |= Overshoot_Top;
-      FT_TRACE6(( "  new descending profile = %p\n", (void *)ras.cProfile ));
+
+      e = FLOOR( ras.lastY );
       break;
 
     default:
@@ -660,12 +678,20 @@
       return FAILURE;
     }
 
-    if ( !ras.gProfile )
-      ras.gProfile = ras.cProfile;
+    if ( e > ras.maxY )
+      e = ras.maxY;
+    if ( e < ras.minY )
+      e = ras.minY;
+    ras.cProfile->start = (Int)TRUNC( e );
+
+    FT_TRACE7(( "  new %s profile = %p, start = %d\n",
+                aState == Ascending_State ? "ascending" : "descending",
+                (void *)ras.cProfile, ras.cProfile->start ));
+
+    if ( ras.lastY == e )
+      *ras.top++ = ras.lastX;
 
     ras.state = aState;
-    ras.fresh = TRUE;
-    ras.joint = FALSE;
 
     return SUCCESS;
   }
@@ -677,24 +703,19 @@
    *   End_Profile
    *
    * @Description:
-   *   Finalize the current profile.
-   *
-   * @Input:
-   *   overshoot ::
-   *     Whether the profile's unrounded end position differs
-   *     by at least a half pixel.
+   *   Finalize the current profile and record y-turns.
    *
    * @Return:
    *   SUCCESS on success.  FAILURE in case of overflow or incoherency.
    */
   static Bool
-  End_Profile( RAS_ARGS Bool  overshoot )
+  End_Profile( RAS_ARG )
   {
-    Long  h;
+    PProfile  p = ras.cProfile;
+    Int       h = (Int)( ras.top - p->x );
+    Int       bottom, top;
 
 
-    h = (Long)( ras.top - ras.cProfile->offset );
-
     if ( h < 0 )
     {
       FT_ERROR(( "End_Profile: negative height encountered\n" ));
@@ -704,98 +725,46 @@
 
     if ( h > 0 )
     {
-      PProfile  oldProfile;
+      FT_TRACE7(( "  ending profile %p, start = %2d, height = %+3d\n",
+                  (void *)p, p->start, p->flags & Flow_Up ? h : -h ));
 
+      p->height = h;
 
-      FT_TRACE6(( "  ending profile %p, start = %ld, height = %ld\n",
-                  (void *)ras.cProfile, ras.cProfile->start, h ));
+      if ( p->flags & Flow_Up )
+      {
+        if ( IS_TOP_OVERSHOOT( ras.lastY ) )
+          p->flags |= Overshoot_Top;
 
-      ras.cProfile->height = h;
-      if ( overshoot )
+        bottom    = p->start;
+        top       = bottom + h;
+        p->offset = 0;
+        p->X      = p->x[0];
+      }
+      else
       {
-        if ( ras.cProfile->flags & Flow_Up )
-          ras.cProfile->flags |= Overshoot_Top;
-        else
-          ras.cProfile->flags |= Overshoot_Bottom;
+        if ( IS_BOTTOM_OVERSHOOT( ras.lastY ) )
+          p->flags |= Overshoot_Bottom;
+
+        top       = p->start + 1;
+        bottom    = top - h;
+        p->start  = bottom;
+        p->offset = h - 1;
+        p->X      = p->x[h - 1];
       }
 
-      oldProfile   = ras.cProfile;
-      ras.cProfile = (PProfile)ras.top;
+      if ( Insert_Y_Turns( RAS_VARS bottom, top ) )
+        return FAILURE;
 
-      ras.top += AlignProfileSize;
+      if ( !ras.gProfile )
+        ras.gProfile = p;
 
-      ras.cProfile->height = 0;
-      ras.cProfile->offset = ras.top;
+      /* preliminary values to be finalized */
+      p->next = ras.gProfile;
+      p->link = (PProfile)ras.top;
 
-      oldProfile->next = ras.cProfile;
       ras.num_Profs++;
     }
 
-    if ( ras.top >= ras.maxBuff )
-    {
-      FT_TRACE1(( "overflow in End_Profile\n" ));
-      ras.error = FT_THROW( Raster_Overflow );
-      return FAILURE;
-    }
-
-    ras.joint = FALSE;
-
-    return SUCCESS;
-  }
-
-
-  /**************************************************************************
-   *
-   * @Function:
-   *   Insert_Y_Turn
-   *
-   * @Description:
-   *   Insert a salient into the sorted list placed on top of the render
-   *   pool.
-   *
-   * @Input:
-   *   New y scanline position.
-   *
-   * @Return:
-   *   SUCCESS on success.  FAILURE in case of overflow.
-   */
-  static Bool
-  Insert_Y_Turn( RAS_ARGS Int  y )
-  {
-    PLong  y_turns;
-    Int    n;
-
-
-    n       = ras.numTurns - 1;
-    y_turns = ras.sizeBuff - ras.numTurns;
-
-    /* look for first y value that is <= */
-    while ( n >= 0 && y < y_turns[n] )
-      n--;
-
-    /* if it is <, simply insert it, ignore if == */
-    if ( n >= 0 && y > y_turns[n] )
-      do
-      {
-        Int  y2 = (Int)y_turns[n];
-
-
-        y_turns[n] = y;
-        y = y2;
-      } while ( --n >= 0 );
-
-    if ( n < 0 )
-    {
-      ras.maxBuff--;
-      if ( ras.maxBuff <= ras.top )
-      {
-        ras.error = FT_THROW( Raster_Overflow );
-        return FAILURE;
-      }
-      ras.numTurns++;
-      ras.sizeBuff[-ras.numTurns] = y;
-    }
-
     return SUCCESS;
   }
 
@@ -807,56 +776,29 @@
    *
    * @Description:
    *   Adjust all links in the profiles list.
-   *
-   * @Return:
-   *   SUCCESS on success.  FAILURE in case of overflow.
    */
-  static Bool
+  static void
   Finalize_Profile_Table( RAS_ARG )
   {
-    UShort    n;
-    PProfile  p;
-
+    UShort    n = ras.num_Profs;
+    PProfile  p = ras.fProfile;
+    PProfile  q;
 
-    n = ras.num_Profs;
-    p = ras.fProfile;
 
-    if ( n > 1 && p )
+    /* there should be at least two profiles, up and down */
+    while ( --n )
     {
-      do
-      {
-        Int  bottom, top;
+      q = p->link;
 
+      /* fix the contour loop */
+      if ( q->next == p->next )
+        p->next = q;
 
-        if ( n > 1 )
-          p->link = (PProfile)( p->offset + p->height );
-        else
-          p->link = NULL;
-
-        if ( p->flags & Flow_Up )
-        {
-          bottom = (Int)p->start;
-          top    = (Int)( p->start + p->height - 1 );
-        }
-        else
-        {
-          bottom     = (Int)( p->start - p->height + 1 );
-          top        = (Int)p->start;
-          p->start   = bottom;
-          p->offset += p->height - 1;
-        }
-
-        if ( Insert_Y_Turn( RAS_VARS bottom )  ||
-             Insert_Y_Turn( RAS_VARS top + 1 ) )
-          return FAILURE;
-
-        p = p->link;
-      } while ( --n );
+      p = q;
     }
-    else
-      ras.fProfile = NULL;
 
-    return SUCCESS;
+    /* null-terminate */
+    p->link = NULL;
   }
 
 
@@ -986,107 +928,78 @@
                     Long  miny,
                     Long  maxy )
   {
-    Long   Dx, Dy;
-    Int    e1, e2, f1, f2, size;     /* XXX: is `Short' sufficient? */
-    Long   Ix, Rx, Ax;
+    Long  e, e2, Dx, Dy;
+    Long  Ix, Rx, Ax;
+    Int   size;
 
     PLong  top;
 
 
-    Dx = x2 - x1;
-    Dy = y2 - y1;
-
-    if ( Dy <= 0 || y2 < miny || y1 > maxy )
+    if ( y2 < miny || y1 > maxy )
       return SUCCESS;
 
-    if ( y1 < miny )
-    {
-      /* Take care: miny-y1 can be a very large value; we use     */
-      /*            a slow MulDiv function to avoid clipping bugs */
-      x1 += SMulDiv( Dx, miny - y1, Dy );
-      e1  = (Int)TRUNC( miny );
-      f1  = 0;
-    }
-    else
-    {
-      e1 = (Int)TRUNC( y1 );
-      f1 = (Int)FRAC( y1 );
-    }
+    e2 = y2 > maxy ? maxy : FLOOR( y2 );
+    e  = y1 < miny ? miny : CEILING( y1 );
 
-    if ( y2 > maxy )
-    {
-      /* x2 += FMulDiv( Dx, maxy - y2, Dy );  UNNECESSARY */
-      e2  = (Int)TRUNC( maxy );
-      f2  = 0;
-    }
-    else
-    {
-      e2 = (Int)TRUNC( y2 );
-      f2 = (Int)FRAC( y2 );
-    }
+    if ( y1 == e )
+      e += ras.precision;
 
-    if ( f1 > 0 )
-    {
-      if ( e1 == e2 )
-        return SUCCESS;
-      else
-      {
-        x1 += SMulDiv( Dx, ras.precision - f1, Dy );
-        e1 += 1;
-      }
-    }
-    else
-      if ( ras.joint )
-      {
-        ras.top--;
-        ras.joint = FALSE;
-      }
-
-    ras.joint = (char)( f2 == 0 );
+    if ( e2 < e )  /* nothing to do */
+      return SUCCESS;
 
-    if ( ras.fresh )
-    {
-      ras.cProfile->start = e1;
-      ras.fresh           = FALSE;
-    }
+    size = (Int)TRUNC( e2 - e ) + 1;
+    top  = ras.top;
 
-    size = e2 - e1 + 1;
-    if ( ras.top + size >= ras.maxBuff )
+    if ( top + size >= ras.maxBuff )
     {
       ras.error = FT_THROW( Raster_Overflow );
       return FAILURE;
     }
 
-    if ( Dx > 0 )
-    {
-      Ix = SMulDiv_No_Round( ras.precision, Dx, Dy );
-      Rx = ( ras.precision * Dx ) % Dy;
-      Dx = 1;
-    }
-    else
+    Dx = x2 - x1;
+    Dy = y2 - y1;
+
+    if ( Dx == 0 )  /* very easy */
     {
-      Ix = -SMulDiv_No_Round( ras.precision, -Dx, Dy );
-      Rx = ( ras.precision * -Dx ) % Dy;
-      Dx = -1;
+      do
+        *top++ = x1;
+      while ( --size );
+      goto Fin;
     }
 
-    Ax  = -Dy;
-    top = ras.top;
+    Ix     = SMulDiv_No_Round( e - y1, Dx, Dy );
+    x1    += Ix;
+    *top++ = x1;
 
-    while ( size > 0 )
+    if ( --size )
     {
-      *top++ = x1;
+      Ax = Dx * ( e - y1 )    - Dy * Ix;  /* remainder */
+      Ix = FMulDiv( ras.precision, Dx, Dy );
+      Rx = Dx * ras.precision - Dy * Ix;  /* remainder */
+      Dx = 1;
 
-      x1 += Ix;
-      Ax += Rx;
-      if ( Ax >= 0 )
+      if ( x2 < x1 )
+      {
+        Ax = -Ax;
+        Rx = -Rx;
+        Dx = -Dx;
+      }
+
+      do
       {
-        Ax -= Dy;
-        x1 += Dx;
+        x1 += Ix;
+        Ax += Rx;
+        if ( Ax >= Dy )
+        {
+          Ax -= Dy;
+          x1 += Dx;
+        }
+        *top++ = x1;
       }
-      size--;
+      while ( --size );
     }
 
+  Fin:
     ras.top = top;
     return SUCCESS;
   }
@@ -1131,17 +1044,7 @@
                       Long  miny,
                       Long  maxy )
   {
-    Bool  result, fresh;
-
-
-    fresh  = ras.fresh;
-
-    result = Line_Up( RAS_VARS x1, -y1, x2, -y2, -maxy, -miny );
-
-    if ( fresh && !ras.fresh )
-      ras.cProfile->start = -ras.cProfile->start;
-
-    return result;
+    return Line_Up( RAS_VARS x1, -y1, x2, -y2, -maxy, -miny );
   }
 
 
@@ -1181,105 +1084,73 @@
                       Long       miny,
                       Long       maxy )
   {
-    Long   y1, y2, e, e2, e0;
-    Short  f1;
+    Long  y1, y2, e, e2, dy;
+    Long  dx, x2;
 
-    TPoint*  start_arc;
-
-    PLong top;
+    PLong  top;
 
 
     y1  = arc[degree].y;
     y2  = arc[0].y;
-    top = ras.top;
 
     if ( y2 < miny || y1 > maxy )
-      goto Fin;
-
-    e2 = FLOOR( y2 );
-
-    if ( e2 > maxy )
-      e2 = maxy;
-
-    e0 = miny;
-
-    if ( y1 < miny )
-      e = miny;
-    else
-    {
-      e  = CEILING( y1 );
-      f1 = (Short)( FRAC( y1 ) );
-      e0 = e;
-
-      if ( f1 == 0 )
-      {
-        if ( ras.joint )
-        {
-          top--;
-          ras.joint = FALSE;
-        }
+      return SUCCESS;
 
-        *top++ = arc[degree].x;
+    e2 = y2 > maxy ? maxy : FLOOR( y2 );
+    e  = y1 < miny ? miny : CEILING( y1 );
 
-        e += ras.precision;
-      }
-    }
+    if ( y1 == e )
+      e += ras.precision;
 
-    if ( ras.fresh )
-    {
-      ras.cProfile->start = TRUNC( e0 );
-      ras.fresh = FALSE;
-    }
+    if ( e2 < e )  /* nothing to do */
+      return SUCCESS;
 
-    if ( e2 < e )
-      goto Fin;
+    top = ras.top;
 
     if ( ( top + TRUNC( e2 - e ) + 1 ) >= ras.maxBuff )
     {
-      ras.top   = top;
       ras.error = FT_THROW( Raster_Overflow );
       return FAILURE;
     }
 
-    start_arc = arc;
-
     do
     {
-      ras.joint = FALSE;
-
       y2 = arc[0].y;
+      x2 = arc[0].x;
 
       if ( y2 > e )
       {
-        y1 = arc[degree].y;
-        if ( y2 - y1 >= ras.precision_step )
+        dy = y2 - arc[degree].y;
+        dx = x2 - arc[degree].x;
+
+        /* split condition should be invariant of direction */
+        if (  dy > ras.precision_step ||
+              dx > ras.precision_step ||
+             -dx > ras.precision_step )
         {
           splitter( arc );
           arc += degree;
         }
         else
         {
-          *top++ = arc[degree].x + FMulDiv( arc[0].x - arc[degree].x,
-                                            e - y1, y2 - y1 );
+          *top++ = x2 - FMulDiv( y2 - e, dx, dy );
+          e     += ras.precision;
           arc -= degree;
-          e   += ras.precision;
         }
       }
       else
       {
         if ( y2 == e )
         {
-          ras.joint  = TRUE;
-          *top++     = arc[0].x;
-
-          e += ras.precision;
+          *top++ = x2;
+          e     += ras.precision;
         }
-        arc -= degree;
+        arc   -= degree;
       }
-    } while ( arc >= start_arc && e <= e2 );
+    }
+    while ( e <= e2 );
 
-  Fin:
-    ras.top  = top;
+    ras.top = top;
     return SUCCESS;
   }
 
@@ -1316,7 +1187,7 @@
                         Long       miny,
                         Long       maxy )
   {
-    Bool     result, fresh;
+    Bool  result;
 
 
     arc[0].y = -arc[0].y;
@@ -1325,13 +1196,8 @@
     if ( degree > 2 )
       arc[3].y = -arc[3].y;
 
-    fresh = ras.fresh;
-
     result = Bezier_Up( RAS_VARS degree, arc, splitter, -maxy, -miny );
 
-    if ( fresh && !ras.fresh )
-      ras.cProfile->start = -ras.cProfile->start;
-
     arc[0].y = -arc[0].y;
     return result;
   }
@@ -1362,74 +1228,50 @@
   Line_To( RAS_ARGS Long  x,
                     Long  y )
   {
-    /* First, detect a change of direction */
+    TStates  state;
 
-    switch ( ras.state )
-    {
-    case Unknown_State:
-      if ( y > ras.lastY )
-      {
-        if ( New_Profile( RAS_VARS Ascending_State,
-                                   IS_BOTTOM_OVERSHOOT( ras.lastY ) ) )
-          return FAILURE;
-      }
-      else
-      {
-        if ( y < ras.lastY )
-          if ( New_Profile( RAS_VARS Descending_State,
-                                     IS_TOP_OVERSHOOT( ras.lastY ) ) )
-            return FAILURE;
-      }
-      break;
 
-    case Ascending_State:
-      if ( y < ras.lastY )
-      {
-        if ( End_Profile( RAS_VARS IS_TOP_OVERSHOOT( ras.lastY ) ) ||
-             New_Profile( RAS_VARS Descending_State,
-                                   IS_TOP_OVERSHOOT( ras.lastY ) ) )
-          return FAILURE;
-      }
-      break;
+    if ( y == ras.lastY )
+      goto Fin;
 
-    case Descending_State:
-      if ( y > ras.lastY )
-      {
-        if ( End_Profile( RAS_VARS IS_BOTTOM_OVERSHOOT( ras.lastY ) ) ||
-             New_Profile( RAS_VARS Ascending_State,
-                                   IS_BOTTOM_OVERSHOOT( ras.lastY ) ) )
-          return FAILURE;
-      }
-      break;
+    /* First, detect a change of direction */
 
-    default:
-      ;
+    state = ras.lastY < y ? Ascending_State : Descending_State;
+
+    if ( ras.state != state )
+    {
+      /* finalize current profile if any */
+      if ( ras.state != Unknown_State &&
+           End_Profile( RAS_VAR )     )
+        goto Fail;
+
+      /* create a new profile */
+      if ( New_Profile( RAS_VARS state ) )
+        goto Fail;
     }
 
     /* Then compute the lines */
 
-    switch ( ras.state )
+    if ( state == Ascending_State )
     {
-    case Ascending_State:
       if ( Line_Up( RAS_VARS ras.lastX, ras.lastY,
                              x, y, ras.minY, ras.maxY ) )
-        return FAILURE;
-      break;
-
-    case Descending_State:
+        goto Fail;
+    }
+    else
+    {
       if ( Line_Down( RAS_VARS ras.lastX, ras.lastY,
                                x, y, ras.minY, ras.maxY ) )
-        return FAILURE;
-      break;
-
-    default:
-      ;
+        goto Fail;
     }
 
+  Fin:
     ras.lastX = x;
     ras.lastY = y;
-
     return SUCCESS;
+
+  Fail:
+    return FAILURE;
   }
 
 
@@ -1500,7 +1342,7 @@
         ymax = y1;
       }
 
-      if ( y2 < ymin || y2 > ymax )
+      if ( y2 < FLOOR( ymin ) || y2 > CEILING( ymax ) )
       {
         /* this arc has no given direction, split it! */
         Split_Conic( arc );
@@ -1508,8 +1350,12 @@
       }
       else if ( y1 == y3 )
       {
-        /* this arc is flat, ignore it and pop it from the Bezier stack */
+        /* this arc is flat, advance position */
+        /* and pop it from the Bezier stack   */
         arc -= 2;
+
+        ras.lastX = x3;
+        ras.lastY = y3;
       }
       else
       {
@@ -1518,18 +1364,13 @@
         state_bez = y1 < y3 ? Ascending_State : Descending_State;
         if ( ras.state != state_bez )
         {
-          Bool  o = ( state_bez == Ascending_State )
-                      ? IS_BOTTOM_OVERSHOOT( y1 )
-                      : IS_TOP_OVERSHOOT( y1 );
-
-
           /* finalize current profile if any */
           if ( ras.state != Unknown_State &&
-               End_Profile( RAS_VARS o )  )
+               End_Profile( RAS_VAR )     )
             goto Fail;
 
           /* create a new profile */
-          if ( New_Profile( RAS_VARS state_bez, o ) )
+          if ( New_Profile( RAS_VARS state_bez ) )
             goto Fail;
         }
 
@@ -1545,13 +1386,13 @@
                                      ras.minY, ras.maxY ) )
             goto Fail;
         arc -= 2;
+
+        ras.lastX = x3;
+        ras.lastY = y3;
       }
 
     } while ( arc >= arcs );
 
-    ras.lastX = x3;
-    ras.lastY = y3;
-
     return SUCCESS;
 
   Fail:
@@ -1648,7 +1489,7 @@
         ymax2 = y2;
       }
 
-      if ( ymin2 < ymin1 || ymax2 > ymax1 )
+      if ( ymin2 < FLOOR( ymin1 ) || ymax2 > CEILING( ymax1 ) )
       {
         /* this arc has no given direction, split it! */
         Split_Cubic( arc );
@@ -1656,27 +1497,26 @@
       }
       else if ( y1 == y4 )
       {
-        /* this arc is flat, ignore it and pop it from the Bezier stack */
+        /* this arc is flat, advance position */
+        /* and pop it from the Bezier stack   */
         arc -= 3;
+
+        ras.lastX = x4;
+        ras.lastY = y4;
       }
       else
       {
-        state_bez = ( y1 <= y4 ) ? Ascending_State : Descending_State;
+        state_bez = y1 < y4 ? Ascending_State : Descending_State;
 
         /* detect a change of direction */
         if ( ras.state != state_bez )
         {
-          Bool  o = ( state_bez == Ascending_State )
-                      ? IS_BOTTOM_OVERSHOOT( y1 )
-                      : IS_TOP_OVERSHOOT( y1 );
-
-
           /* finalize current profile if any */
           if ( ras.state != Unknown_State &&
-               End_Profile( RAS_VARS o )  )
+               End_Profile( RAS_VAR )     )
             goto Fail;
 
-          if ( New_Profile( RAS_VARS state_bez, o ) )
+          if ( New_Profile( RAS_VARS state_bez ) )
             goto Fail;
         }
 
@@ -1692,13 +1532,13 @@
                                      ras.minY, ras.maxY ) )
             goto Fail;
         arc -= 3;
+
+        ras.lastX = x4;
+        ras.lastY = y4;
       }
 
     } while ( arc >= arcs );
 
-    ras.lastX = x4;
-    ras.lastY = y4;
-
     return SUCCESS;
 
   Fail:
@@ -1740,6 +1580,11 @@
    *
    * @Return:
    *   SUCCESS on success, FAILURE on error.
+   *
+   * @Note:
+   *   Unlike FT_Outline_Decompose(), this function handles the scanmode
+   *   dropout tags in the individual contours.  Therefore, it cannot be
+   *   replaced.
    */
   static Bool
   Decompose_Curve( RAS_ARGS Int  first,
@@ -1753,7 +1598,7 @@
     FT_Vector*  points;
     FT_Vector*  point;
     FT_Vector*  limit;
-    char*       tags;
+    FT_Byte*    tags;
 
     UInt        tag;       /* current point's state           */
 
@@ -1974,24 +1819,17 @@
 
 
     ras.fProfile = NULL;
-    ras.joint    = FALSE;
-    ras.fresh    = FALSE;
-
-    ras.maxBuff  = ras.sizeBuff - AlignProfileSize;
+    ras.cProfile = NULL;
 
-    ras.numTurns = 0;
+    ras.top      = ras.buff;
+    ras.maxBuff  = ras.sizeBuff - 1;  /* top reserve */
 
-    ras.cProfile         = (PProfile)ras.top;
-    ras.cProfile->offset = ras.top;
-    ras.num_Profs        = 0;
+    ras.numTurns  = 0;
+    ras.num_Profs = 0;
 
     last = -1;
     for ( i = 0; i < ras.outline.n_contours; i++ )
     {
-      PProfile  lastProfile;
-      Bool      o;
-
-
       ras.state    = Unknown_State;
       ras.gProfile = NULL;
 
@@ -2001,35 +1839,30 @@
       if ( Decompose_Curve( RAS_VARS first, last, flipped ) )
         return FAILURE;
 
+      /* Note that ras.gProfile can stay nil if the contour was */
+      /* too small to be drawn or degenerate.                   */
+      if ( !ras.gProfile )
+        continue;
+
       /* we must now check whether the extreme arcs join or not */
       if ( FRAC( ras.lastY ) == 0 &&
            ras.lastY >= ras.minY  &&
            ras.lastY <= ras.maxY  )
-        if ( ras.gProfile                        &&
-             ( ras.gProfile->flags & Flow_Up ) ==
+        if ( ( ras.gProfile->flags & Flow_Up ) ==
                ( ras.cProfile->flags & Flow_Up ) )
           ras.top--;
-        /* Note that ras.gProfile can be nil if the contour was too small */
-        /* to be drawn.                                                   */
 
-      lastProfile = ras.cProfile;
-      if ( ras.top != ras.cProfile->offset &&
-           ( ras.cProfile->flags & Flow_Up ) )
-        o = IS_TOP_OVERSHOOT( ras.lastY );
-      else
-        o = IS_BOTTOM_OVERSHOOT( ras.lastY );
-      if ( End_Profile( RAS_VARS o ) )
+      if ( End_Profile( RAS_VAR ) )
         return FAILURE;
 
-      /* close the `next profile in contour' linked list */
-      if ( ras.gProfile )
-        lastProfile->next = ras.gProfile;
+      if ( !ras.fProfile )
+        ras.fProfile = ras.gProfile;
     }
 
-    if ( Finalize_Profile_Table( RAS_VAR ) )
-      return FAILURE;
+    if ( ras.fProfile )
+      Finalize_Profile_Table( RAS_VAR );
 
-    return (Bool)( ras.top < ras.maxBuff ? SUCCESS : FAILURE );
+    return SUCCESS;
   }
 
 
@@ -2042,24 +1875,11 @@
   /*************************************************************************/
 
 
-  /**************************************************************************
-   *
-   * Init_Linked
-   *
-   *   Initializes an empty linked list.
-   */
-  static void
-  Init_Linked( TProfileList*  l )
-  {
-    *l = NULL;
-  }
-
-
   /**************************************************************************
    *
    * InsNew
    *
-   *   Inserts a new profile in a linked list.
+   *   Inserts a new profile in a linked list, sorted by coordinate.
    */
   static void
   InsNew( PProfileList  list,
@@ -2073,10 +1893,8 @@
     current = *old;
     x       = profile->X;
 
-    while ( current )
+    while ( current && current->X < x )
     {
-      if ( x < current->X )
-        break;
       old     = ¤t->link;
       current = *old;
     }
@@ -2088,79 +1906,51 @@
 
   /**************************************************************************
    *
-   * DelOld
+   * Increment
    *
-   *   Removes an old profile from a linked list.
+   *   Advances all profile in the list to the next scanline.  It also
+   *   sorts the trace list in the unlikely case of profile crossing.
+   *   The profiles are inserted in sorted order.  We might need a single
+   *   swap to fix it when profiles (contours) cross.
+   *   Bubble sort with immediate restart is good enough and simple.
    */
   static void
-  DelOld( PProfileList    list,
-          const PProfile  profile )
+  Increment( PProfileList  list,
+             Int           flow )
   {
-    PProfile  *old, current;
-
+    PProfile  *old, current, next;
 
-    old     = list;
-    current = *old;
 
-    while ( current )
+    /* First, set the new X coordinates and remove exhausted profiles */
+    old = list;
+    while ( *old )
     {
-      if ( current == profile )
+      current = *old;
+      if ( --current->height )
       {
-        *old = current->link;
-        return;
+        current->offset += flow;
+        current->X       = current->x[current->offset];
+        old = ¤t->link;
       }
-
-      old     = ¤t->link;
-      current = *old;
-    }
-
-    /* we should never get there, unless the profile was not part of */
-    /* the list.                                                     */
-  }
-
-
-  /**************************************************************************
-   *
-   * Sort
-   *
-   *   Sorts a trace list.  In 95%, the list is already sorted.  We need
-   *   an algorithm which is fast in this case.  Bubble sort is enough
-   *   and simple.
-   */
-  static void
-  Sort( PProfileList  list )
-  {
-    PProfile  *old, current, next;
-
-
-    /* First, set the new X coordinate of each profile */
-    current = *list;
-    while ( current )
-    {
-      current->X       = *current->offset;
-      current->offset += ( current->flags & Flow_Up ) ? 1 : -1;
-      current->height--;
-      current = current->link;
+      else
+        *old = current->link;  /* remove */
     }
 
-    /* Then sort them */
+    /* Then make sure the list remains sorted */
     old     = list;
     current = *old;
 
     if ( !current )
       return;
 
-    next = current->link;
-
-    while ( next )
+    while ( current->link )
     {
+      next = current->link;
+
       if ( current->X <= next->X )
       {
         old     = ¤t->link;
-        current = *old;
-
-        if ( !current )
-          return;
+        current = next;
       }
       else
       {
@@ -2168,11 +1958,10 @@
         current->link = next->link;
         next->link    = current;
 
+        /* this is likely the only necessary swap -- restart */
         old     = list;
         current = *old;
       }
-
-      next = current->link;
     }
   }
 
@@ -2187,74 +1976,51 @@
    */
 
   static void
-  Vertical_Sweep_Init( RAS_ARGS Short  min,
-                                Short  max )
+  Vertical_Sweep_Init( RAS_ARGS Int  min,
+                                Int  max )
   {
     FT_UNUSED( max );
 
 
-    ras.bLine = ras.bOrigin - min * ras.target.pitch;
+    ras.bLine = ras.bOrigin - min * ras.bPitch;
   }
 
 
   static void
-  Vertical_Sweep_Span( RAS_ARGS Short       y,
+  Vertical_Sweep_Span( RAS_ARGS Int         y,
                                 FT_F26Dot6  x1,
-                                FT_F26Dot6  x2,
-                                PProfile    left,
-                                PProfile    right )
+                                FT_F26Dot6  x2 )
   {
-    Long  e1, e2;
-
-    Int  dropOutControl = left->flags & 7;
+    Int  e1 = (Int)TRUNC( CEILING( x1 ) );
+    Int  e2 = (Int)TRUNC(   FLOOR( x2 ) );
 
     FT_UNUSED( y );
-    FT_UNUSED( left );
-    FT_UNUSED( right );
 
 
-    /* in high-precision mode, we need 12 digits after the comma to */
-    /* represent multiples of 1/(1<<12) = 1/4096                    */
-    FT_TRACE7(( "  y=%d x=[% .12f;% .12f]",
+    FT_TRACE7(( "  y=%d x=[% .*f;% .*f]",
                 y,
-                (double)x1 / (double)ras.precision,
-                (double)x2 / (double)ras.precision ));
-
-    /* Drop-out control */
-
-    e1 = CEILING( x1 );
-    e2 = FLOOR( x2 );
-
-    /* take care of the special case where both the left */
-    /* and right contour lie exactly on pixel centers    */
-    if ( dropOutControl != 2                             &&
-         x2 - x1 - ras.precision <= ras.precision_jitter &&
-         e1 != x1 && e2 != x2                            )
-      e2 = e1;
+                ras.precision_bits, (double)x1 / (double)ras.precision,
+                ras.precision_bits, (double)x2 / (double)ras.precision ));
 
-    e1 = TRUNC( e1 );
-    e2 = TRUNC( e2 );
-
-    if ( e2 >= 0 && e1 < ras.bWidth )
+    if ( e2 >= 0 && e1 <= ras.bRight )
     {
-      Byte*  target;
+      PByte  target;
 
-      Int   c1, c2;
-      Byte  f1, f2;
+      Int   c1, f1, c2, f2;
 
 
       if ( e1 < 0 )
         e1 = 0;
-      if ( e2 >= ras.bWidth )
-        e2 = ras.bWidth - 1;
+      if ( e2 > ras.bRight )
+        e2 = ras.bRight;
 
-      FT_TRACE7(( " -> x=[%ld;%ld]", e1, e2 ));
+      FT_TRACE7(( " -> x=[%d;%d]", e1, e2 ));
 
-      c1 = (Short)( e1 >> 3 );
-      c2 = (Short)( e2 >> 3 );
+      c1 = e1 >> 3;
+      c2 = e2 >> 3;
 
-      f1 = (Byte)  ( 0xFF >> ( e1 & 7 ) );
-      f2 = (Byte) ~( 0x7F >> ( e2 & 7 ) );
+      f1 =  0xFF >> ( e1 & 7 );
+      f2 = ~0x7F >> ( e2 & 7 );
 
       target = ras.bLine + c1;
       c2 -= c1;
@@ -2280,163 +2046,50 @@
 
 
   static void
-  Vertical_Sweep_Drop( RAS_ARGS Short       y,
+  Vertical_Sweep_Drop( RAS_ARGS Int         y,
                                 FT_F26Dot6  x1,
-                                FT_F26Dot6  x2,
-                                PProfile    left,
-                                PProfile    right )
+                                FT_F26Dot6  x2 )
   {
-    Long   e1, e2, pxl;
-    Short  c1, f1;
-
-
-    FT_TRACE7(( "  y=%d x=[% .12f;% .12f]",
-                y,
-                (double)x1 / (double)ras.precision,
-                (double)x2 / (double)ras.precision ));
-
-    /* Drop-out control */
-
-    /*   e2            x2                    x1           e1   */
-    /*                                                         */
-    /*                 ^                     |                 */
-    /*                 |                     |                 */
-    /*   +-------------+---------------------+------------+    */
-    /*                 |                     |                 */
-    /*                 |                     v                 */
-    /*                                                         */
-    /* pixel         contour              contour       pixel  */
-    /* center                                           center */
-
-    /* drop-out mode    scan conversion rules (as defined in OpenType) */
-    /* --------------------------------------------------------------- */
-    /*  0                1, 2, 3                                       */
-    /*  1                1, 2, 4                                       */
-    /*  2                1, 2                                          */
-    /*  3                same as mode 2                                */
-    /*  4                1, 2, 5                                       */
-    /*  5                1, 2, 6                                       */
-    /*  6, 7             same as mode 2                                */
-
-    e1  = CEILING( x1 );
-    e2  = FLOOR  ( x2 );
-    pxl = e1;
-
-    if ( e1 > e2 )
-    {
-      Int  dropOutControl = left->flags & 7;
-
-
-      if ( e1 == e2 + ras.precision )
-      {
-        switch ( dropOutControl )
-        {
-        case 0: /* simple drop-outs including stubs */
-          pxl = e2;
-          break;
-
-        case 4: /* smart drop-outs including stubs */
-          pxl = SMART( x1, x2 );
-          break;
-
-        case 1: /* simple drop-outs excluding stubs */
-        case 5: /* smart drop-outs excluding stubs  */
-
-          /* Drop-out Control Rules #4 and #6 */
-
-          /* The specification neither provides an exact definition */
-          /* of a `stub' nor gives exact rules to exclude them.     */
-          /*                                                        */
-          /* Here the constraints we use to recognize a stub.       */
-          /*                                                        */
-          /*  upper stub:                                           */
-          /*                                                        */
-          /*   - P_Left and P_Right are in the same contour         */
-          /*   - P_Right is the successor of P_Left in that contour */
-          /*   - y is the top of P_Left and P_Right                 */
-          /*                                                        */
-          /*  lower stub:                                           */
-          /*                                                        */
-          /*   - P_Left and P_Right are in the same contour         */
-          /*   - P_Left is the successor of P_Right in that contour */
-          /*   - y is the bottom of P_Left                          */
-          /*                                                        */
-          /* We draw a stub if the following constraints are met.   */
-          /*                                                        */
-          /*   - for an upper or lower stub, there is top or bottom */
-          /*     overshoot, respectively                            */
-          /*   - the covered interval is greater or equal to a half */
-          /*     pixel                                              */
-
-          /* upper stub test */
-          if ( left->next == right                &&
-               left->height <= 0                  &&
-               !( left->flags & Overshoot_Top   &&
-                  x2 - x1 >= ras.precision_half ) )
-            goto Exit;
-
-          /* lower stub test */
-          if ( right->next == left                 &&
-               left->start == y                    &&
-               !( left->flags & Overshoot_Bottom &&
-                  x2 - x1 >= ras.precision_half  ) )
-            goto Exit;
-
-          if ( dropOutControl == 1 )
-            pxl = e2;
-          else
-            pxl = SMART( x1, x2 );
-          break;
-
-        default: /* modes 2, 3, 6, 7 */
-          goto Exit;  /* no drop-out control */
-        }
+    Int  e1 = (Int)TRUNC( x1 );
+    Int  e2 = (Int)TRUNC( x2 );
+    Int  c1, f1;
 
-        /* undocumented but confirmed: If the drop-out would result in a  */
-        /* pixel outside of the bounding box, use the pixel inside of the */
-        /* bounding box instead                                           */
-        if ( pxl < 0 )
-          pxl = e1;
-        else if ( TRUNC( pxl ) >= ras.bWidth )
-          pxl = e2;
+    FT_UNUSED( y );
 
-        /* check that the other pixel isn't set */
-        e1 = ( pxl == e1 ) ? e2 : e1;
 
-        e1 = TRUNC( e1 );
+    /* undocumented but confirmed: If the drop-out would result in a  */
+    /* pixel outside of the bounding box, use the pixel inside of the */
+    /* bounding box instead                                           */
+    if ( e1 < 0 || e1 > ras.bRight )
+      e1 = e2;
 
-        c1 = (Short)( e1 >> 3 );
-        f1 = (Short)( e1 &  7 );
+    /* otherwise check that the other pixel isn't set */
+    else if ( e2 >=0 && e2 <= ras.bRight )
+    {
+      c1 = e2 >> 3;
+      f1 = 0x80 >> ( e2 & 7 );
 
-        if ( e1 >= 0 && e1 < ras.bWidth     &&
-             ras.bLine[c1] & ( 0x80 >> f1 ) )
-          goto Exit;
-      }
-      else
-        goto Exit;
+      if ( ras.bLine[c1] & f1 )
+        return;
     }
 
-    e1 = TRUNC( pxl );
-
-    if ( e1 >= 0 && e1 < ras.bWidth )
+    if ( e1 >= 0 && e1 <= ras.bRight )
     {
-      FT_TRACE7(( " -> x=%ld", e1 ));
+      c1 = e1 >> 3;
+      f1 = 0x80 >> ( e1 & 7 );
 
-      c1 = (Short)( e1 >> 3 );
-      f1 = (Short)( e1 & 7 );
+      FT_TRACE7(( "  y=%d x=%d%s\n", y, e1,
+                  ras.bLine[c1] & f1 ? " redundant" : "" ));
 
-      ras.bLine[c1] |= (char)( 0x80 >> f1 );
+      ras.bLine[c1] |= f1;
     }
-
-  Exit:
-    FT_TRACE7(( " dropout=%d\n", left->flags & 7 ));
   }
 
 
   static void
   Vertical_Sweep_Step( RAS_ARG )
   {
-    ras.bLine -= ras.target.pitch;
+    ras.bLine -= ras.bPitch;
   }
 
 
@@ -2450,8 +2103,8 @@
    */
 
   static void
-  Horizontal_Sweep_Init( RAS_ARGS Short  min,
-                                  Short  max )
+  Horizontal_Sweep_Init( RAS_ARGS Int  min,
+                                  Int  max )
   {
     /* nothing, really */
     FT_UNUSED_RASTER;
@@ -2461,22 +2114,18 @@
 
 
   static void
-  Horizontal_Sweep_Span( RAS_ARGS Short       y,
+  Horizontal_Sweep_Span( RAS_ARGS Int         y,
                                   FT_F26Dot6  x1,
-                                  FT_F26Dot6  x2,
-                                  PProfile    left,
-                                  PProfile    right )
+                                  FT_F26Dot6  x2 )
   {
-    Long  e1, e2;
+    Long  e1 = CEILING( x1 );
+    Long  e2 =   FLOOR( x2 );
 
-    FT_UNUSED( left );
-    FT_UNUSED( right );
 
-
-    FT_TRACE7(( "  x=%d y=[% .12f;% .12f]",
+    FT_TRACE7(( "  x=%d y=[% .*f;% .*f]",
                 y,
-                (double)x1 / (double)ras.precision,
-                (double)x2 / (double)ras.precision ));
+                ras.precision_bits, (double)x1 / (double)ras.precision,
+                ras.precision_bits, (double)x2 / (double)ras.precision ));
 
     /* We should not need this procedure but the vertical sweep   */
     /* mishandles horizontal lines through pixel centers.  So we  */
@@ -2484,20 +2133,18 @@
     /*                                                            */
     /* XXX: Can we handle horizontal lines better and drop this?  */
 
-    e1 = CEILING( x1 );
-
     if ( x1 == e1 )
     {
       e1 = TRUNC( e1 );
 
-      if ( e1 >= 0 && (ULong)e1 < ras.target.rows )
+      if ( e1 >= 0 && e1 <= ras.bTop )
       {
-        Byte   f1;
+        Int    f1;
         PByte  bits;
 
 
-        bits = ras.bOrigin + ( y >> 3 ) - e1 * ras.target.pitch;
-        f1   = (Byte)( 0x80 >> ( y & 7 ) );
+        bits = ras.bOrigin + ( y >> 3 ) - e1 * ras.bPitch;
+        f1   = 0x80 >> ( y & 7 );
 
         FT_TRACE7(( bits[0] & f1 ? " redundant"
                                  : " -> y=%ld edge", e1 ));
@@ -2506,20 +2153,18 @@
       }
     }
 
-    e2 = FLOOR  ( x2 );
-
     if ( x2 == e2 )
     {
       e2 = TRUNC( e2 );
 
-      if ( e2 >= 0 && (ULong)e2 < ras.target.rows )
+      if ( e2 >= 0 && e2 <= ras.bTop )
       {
-        Byte   f1;
+        Int    f1;
         PByte  bits;
 
 
-        bits = ras.bOrigin + ( y >> 3 ) - e2 * ras.target.pitch;
-        f1   = (Byte)( 0x80 >> ( y & 7 ) );
+        bits = ras.bOrigin + ( y >> 3 ) - e2 * ras.bPitch;
+        f1   = 0x80 >> ( y & 7 );
 
         FT_TRACE7(( bits[0] & f1 ? " redundant"
                                  : " -> y=%ld edge", e2 ));
@@ -2533,122 +2178,42 @@
 
 
   static void
-  Horizontal_Sweep_Drop( RAS_ARGS Short       y,
+  Horizontal_Sweep_Drop( RAS_ARGS Int         y,
                                   FT_F26Dot6  x1,
-                                  FT_F26Dot6  x2,
-                                  PProfile    left,
-                                  PProfile    right )
+                                  FT_F26Dot6  x2 )
   {
-    Long   e1, e2, pxl;
+    Int    e1 = (Int)TRUNC( x1 );
+    Int    e2 = (Int)TRUNC( x2 );
     PByte  bits;
-    Byte   f1;
-
-
-    FT_TRACE7(( "  x=%d y=[% .12f;% .12f]",
-                y,
-                (double)x1 / (double)ras.precision,
-                (double)x2 / (double)ras.precision ));
-
-    /* During the horizontal sweep, we only take care of drop-outs */
-
-    /* e1     +       <-- pixel center */
-    /*        |                        */
-    /* x1  ---+-->    <-- contour      */
-    /*        |                        */
-    /*        |                        */
-    /* x2  <--+---    <-- contour      */
-    /*        |                        */
-    /*        |                        */
-    /* e2     +       <-- pixel center */
-
-    e1  = CEILING( x1 );
-    e2  = FLOOR  ( x2 );
-    pxl = e1;
-
-    if ( e1 > e2 )
-    {
-      Int  dropOutControl = left->flags & 7;
-
+    Int    f1;
 
-      if ( e1 == e2 + ras.precision )
-      {
-        switch ( dropOutControl )
-        {
-        case 0: /* simple drop-outs including stubs */
-          pxl = e2;
-          break;
-
-        case 4: /* smart drop-outs including stubs */
-          pxl = SMART( x1, x2 );
-          break;
-
-        case 1: /* simple drop-outs excluding stubs */
-        case 5: /* smart drop-outs excluding stubs  */
-          /* see Vertical_Sweep_Drop for details */
-
-          /* rightmost stub test */
-          if ( left->next == right                &&
-               left->height <= 0                  &&
-               !( left->flags & Overshoot_Top   &&
-                  x2 - x1 >= ras.precision_half ) )
-            goto Exit;
-
-          /* leftmost stub test */
-          if ( right->next == left                 &&
-               left->start == y                    &&
-               !( left->flags & Overshoot_Bottom &&
-                  x2 - x1 >= ras.precision_half  ) )
-            goto Exit;
-
-          if ( dropOutControl == 1 )
-            pxl = e2;
-          else
-            pxl = SMART( x1, x2 );
-          break;
 
-        default: /* modes 2, 3, 6, 7 */
-          goto Exit;  /* no drop-out control */
-        }
-
-        /* undocumented but confirmed: If the drop-out would result in a  */
-        /* pixel outside of the bounding box, use the pixel inside of the */
-        /* bounding box instead                                           */
-        if ( pxl < 0 )
-          pxl = e1;
-        else if ( (ULong)( TRUNC( pxl ) ) >= ras.target.rows )
-          pxl = e2;
-
-        /* check that the other pixel isn't set */
-        e1 = ( pxl == e1 ) ? e2 : e1;
-
-        e1 = TRUNC( e1 );
+    /* undocumented but confirmed: If the drop-out would result in a  */
+    /* pixel outside of the bounding box, use the pixel inside of the */
+    /* bounding box instead                                           */
+    if ( e1 < 0 || e1 > ras.bTop )
+      e1 = e2;
 
-        bits = ras.bOrigin + ( y >> 3 ) - e1 * ras.target.pitch;
-        f1   = (Byte)( 0x80 >> ( y & 7 ) );
+    /* otherwise check that the other pixel isn't set */
+    else if ( e2 >=0 && e2 <= ras.bTop )
+    {
+      bits = ras.bOrigin + ( y >> 3 ) - e2 * ras.bPitch;
+      f1   = 0x80 >> ( y & 7 );
 
-        if ( e1 >= 0                     &&
-             (ULong)e1 < ras.target.rows &&
-             *bits & f1                  )
-          goto Exit;
-      }
-      else
-        goto Exit;
+      if ( *bits & f1 )
+        return;
     }
 
-    e1 = TRUNC( pxl );
-
-    if ( e1 >= 0 && (ULong)e1 < ras.target.rows )
+    if ( e1 >= 0 && e1 <= ras.bTop )
     {
-      FT_TRACE7(( " -> y=%ld", e1 ));
+      bits  = ras.bOrigin + ( y >> 3 ) - e1 * ras.bPitch;
+      f1    = 0x80 >> ( y & 7 );
 
-      bits  = ras.bOrigin + ( y >> 3 ) - e1 * ras.target.pitch;
-      f1    = (Byte)( 0x80 >> ( y & 7 ) );
+      FT_TRACE7(( "  x=%d y=%d%s\n", y, e1,
+                  *bits & f1 ? " redundant" : "" ));
 
-      bits[0] |= f1;
+      *bits |= f1;
     }
-
-  Exit:
-    FT_TRACE7(( " dropout=%d\n", left->flags & 7 ));
   }
 
 
@@ -2664,116 +2229,61 @@
    *
    * Generic Sweep Drawing routine
    *
+   * Note that this routine is executed with the pool containing at least
+   * two valid profiles (up and down) and two y-turns (top and bottom).
+   *
    */
 
-  static Bool
+  static void
   Draw_Sweep( RAS_ARG )
   {
-    Short         y, y_change, y_height;
-
-    PProfile      P, Q, P_Left, P_Right;
-
-    Short         min_Y, max_Y, top, bottom, dropouts;
-
-    Long          x1, x2, xs, e1, e2;
-
-    TProfileList  waiting;
-    TProfileList  draw_left, draw_right;
-
-
-    /* initialize empty linked lists */
-
-    Init_Linked( &waiting );
-
-    Init_Linked( &draw_left  );
-    Init_Linked( &draw_right );
-
-    /* first, compute min and max Y */
-
-    P     = ras.fProfile;
-    max_Y = (Short)TRUNC( ras.minY );
-    min_Y = (Short)TRUNC( ras.maxY );
-
-    while ( P )
-    {
-      Q = P->link;
+    Int           min_Y, max_Y, dropouts;
+    Int           y, y_turn;
 
-      bottom = (Short)P->start;
-      top    = (Short)( P->start + P->height - 1 );
+    PProfile      *Q, P, P_Left, P_Right;
 
-      if ( min_Y > bottom )
-        min_Y = bottom;
-      if ( max_Y < top )
-        max_Y = top;
+    TProfileList  waiting    = ras.fProfile;
+    TProfileList  draw_left  = NULL;
+    TProfileList  draw_right = NULL;
 
-      P->X = 0;
-      InsNew( &waiting, P );
 
-      P = Q;
-    }
+    /* use y_turns to set the drawing range */
 
-    /* check the Y-turns */
-    if ( ras.numTurns == 0 )
-    {
-      ras.error = FT_THROW( Invalid_Outline );
-      return FAILURE;
-    }
+    min_Y = (Int)ras.maxBuff[0];
+    max_Y = (Int)ras.maxBuff[ras.numTurns] - 1;
 
     /* now initialize the sweep */
 
     ras.Proc_Sweep_Init( RAS_VARS min_Y, max_Y );
 
-    /* then compute the distance of each profile from min_Y */
-
-    P = waiting;
-
-    while ( P )
-    {
-      P->countL = P->start - min_Y;
-      P = P->link;
-    }
-
     /* let's go */
 
-    y        = min_Y;
-    y_height = 0;
-
-    if ( ras.numTurns > 0                     &&
-         ras.sizeBuff[-ras.numTurns] == min_Y )
-      ras.numTurns--;
-
-    while ( ras.numTurns > 0 )
+    for ( y = min_Y; y <= max_Y; )
     {
-      /* check waiting list for new activations */
-
-      P = waiting;
+      /* check waiting list for new profile activations */
 
-      while ( P )
+      Q = &waiting;
+      while ( *Q )
       {
-        Q = P->link;
-        P->countL -= y_height;
-        if ( P->countL == 0 )
+        P = *Q;
+        if ( P->start == y )
         {
-          DelOld( &waiting, P );
+          *Q = P->link;  /* remove */
 
+          /* each active list contains profiles with the same flow */
+          /* left and right are arbitrary, correspond to TrueType  */
           if ( P->flags & Flow_Up )
             InsNew( &draw_left,  P );
           else
             InsNew( &draw_right, P );
         }
-
-        P = Q;
+        else
+          Q = &P->link;
       }
 
-      /* sort the drawing lists */
+      y_turn = (Int)*++ras.maxBuff;
 
-      Sort( &draw_left );
-      Sort( &draw_right );
-
-      y_change = (Short)ras.sizeBuff[-ras.numTurns--];
-      y_height = (Short)( y_change - y );
-
-      while ( y < y_change )
+      do
       {
         /* let's trace */
 
@@ -2784,9 +2294,13 @@
 
         while ( P_Left && P_Right )
         {
-          x1 = P_Left ->X;
-          x2 = P_Right->X;
+          Long  x1 = P_Left ->X;
+          Long  x2 = P_Right->X;
+          Long  xs;
+
 
+          /* TrueType should have x2 > x1, but can be opposite */
+          /* by mistake or in CFF/Type1, fix it then           */
           if ( x1 > x2 )
           {
             xs = x1;
@@ -2794,205 +2308,130 @@
             x2 = xs;
           }
 
-          e1 = FLOOR( x1 );
-          e2 = CEILING( x2 );
+          if ( CEILING( x1 ) <= FLOOR( x2 ) )
+            ras.Proc_Sweep_Span( RAS_VARS y, x1, x2 );
 
-          if ( x2 - x1 <= ras.precision &&
-               e1 != x1 && e2 != x2     )
+          /* otherwise, bottom ceiling > top floor, it is a drop-out */
+          else
           {
-            if ( e1 > e2 || e2 == e1 + ras.precision )
+            Int  dropOutControl = P_Left->flags & 7;
+
+
+            /* Drop-out control */
+
+            /*   e2            x2                    x1           e1   */
+            /*                                                         */
+            /*                 ^                     |                 */
+            /*                 |                     |                 */
+            /*   +-------------+---------------------+------------+    */
+            /*                 |                     |                 */
+            /*                 |                     v                 */
+            /*                                                         */
+            /* pixel         contour              contour       pixel  */
+            /* center                                           center */
+
+            /* drop-out mode   scan conversion rules (OpenType specs)  */
+            /* ------------------------------------------------------- */
+            /*  bit 0          exclude stubs if set                    */
+            /*  bit 1          ignore drop-outs if set                 */
+            /*  bit 2          smart rounding if set                   */
+
+            if ( dropOutControl & 2 )
+              goto Next_Pair;
+
+            /* The specification neither provides an exact definition */
+            /* of a `stub' nor gives exact rules to exclude them.     */
+            /*                                                        */
+            /* Here the constraints we use to recognize a stub.       */
+            /*                                                        */
+            /*  upper stub:                                           */
+            /*                                                        */
+            /*   - P_Left and P_Right are in the same contour         */
+            /*   - P_Right is the successor of P_Left in that contour */
+            /*   - y is the top of P_Left and P_Right                 */
+            /*                                                        */
+            /*  lower stub:                                           */
+            /*                                                        */
+            /*   - P_Left and P_Right are in the same contour         */
+            /*   - P_Left is the successor of P_Right in that contour */
+            /*   - y is the bottom of P_Left                          */
+            /*                                                        */
+            /* We draw a stub if the following constraints are met.   */
+            /*                                                        */
+            /*   - for an upper or lower stub, there is top or bottom */
+            /*     overshoot, respectively                            */
+            /*   - the covered interval is greater or equal to a half */
+            /*     pixel                                              */
+
+            if ( dropOutControl & 1 )
             {
-              Int  dropOutControl = P_Left->flags & 7;
-
-
-              if ( dropOutControl != 2 )
-              {
-                /* a drop-out was detected */
-
-                P_Left ->X = x1;
-                P_Right->X = x2;
-
-                /* mark profile for drop-out processing */
-                P_Left->countL = 1;
-                dropouts++;
-              }
+              /* upper stub test */
+              if ( P_Left->height == 1                &&
+                   P_Left->next == P_Right            &&
+                   !( P_Left->flags & Overshoot_Top   &&
+                      x2 - x1 >= ras.precision_half   ) )
+                goto Next_Pair;
+
+              /* lower stub test */
+              if ( P_Left->offset == 0                 &&
+                   P_Right->next == P_Left             &&
+                   !( P_Left->flags & Overshoot_Bottom &&
+                      x2 - x1 >= ras.precision_half    ) )
+                goto Next_Pair;
+            }
 
-              goto Skip_To_Next;
+            /* select the pixel to set and the other pixel */
+            if ( dropOutControl & 4 )
+            {
+              x2 = SMART( x1, x2 );
+              x1 = x1 > x2 ? x2 + ras.precision : x2 - ras.precision;
+            }
+            else
+            {
+              x2 = FLOOR  ( x2 );
+              x1 = CEILING( x1 );
             }
-          }
 
-          ras.Proc_Sweep_Span( RAS_VARS y, x1, x2, P_Left, P_Right );
+            P_Left ->X = x2;
+            P_Right->X = x1;
 
-        Skip_To_Next:
+            /* mark profile for drop-out processing */
+            P_Left->flags |= Dropout;
+            dropouts++;
+          }
 
+        Next_Pair:
           P_Left  = P_Left->link;
           P_Right = P_Right->link;
         }
 
-        /* handle drop-outs _after_ the span drawing --       */
-        /* drop-out processing has been moved out of the loop */
-        /* for performance tuning                             */
-        if ( dropouts > 0 )
-          goto Scan_DropOuts;
-
-      Next_Line:
-
-        ras.Proc_Sweep_Step( RAS_VAR );
-
-        y++;
+        /* handle drop-outs _after_ the span drawing */
+        P_Left  = draw_left;
+        P_Right = draw_right;
 
-        if ( y < y_change )
+        while ( dropouts )
         {
-          Sort( &draw_left  );
-          Sort( &draw_right );
-        }
-      }
-
-      /* now finalize the profiles that need it */
-
-      P = draw_left;
-      while ( P )
-      {
-        Q = P->link;
-        if ( P->height == 0 )
-          DelOld( &draw_left, P );
-        P = Q;
-      }
-
-      P = draw_right;
-      while ( P )
-      {
-        Q = P->link;
-        if ( P->height == 0 )
-          DelOld( &draw_right, P );
-        P = Q;
-      }
-    }
-
-    /* for gray-scaling, flush the bitmap scanline cache */
-    while ( y <= max_Y )
-    {
-      ras.Proc_Sweep_Step( RAS_VAR );
-      y++;
-    }
-
-    return SUCCESS;
-
-  Scan_DropOuts:
-
-    P_Left  = draw_left;
-    P_Right = draw_right;
-
-    while ( P_Left && P_Right )
-    {
-      if ( P_Left->countL )
-      {
-        P_Left->countL = 0;
-#if 0
-        dropouts--;  /* -- this is useful when debugging only */
-#endif
-        ras.Proc_Sweep_Drop( RAS_VARS y,
-                                      P_Left->X,
-                                      P_Right->X,
-                                      P_Left,
-                                      P_Right );
-      }
-
-      P_Left  = P_Left->link;
-      P_Right = P_Right->link;
-    }
-
-    goto Next_Line;
-  }
-
-
-#ifdef STANDALONE_
-
-  /**************************************************************************
-   *
-   * The following functions should only compile in stand-alone mode,
-   * i.e., when building this component without the rest of FreeType.
-   *
-   */
-
-  /**************************************************************************
-   *
-   * @Function:
-   *   FT_Outline_Get_CBox
-   *
-   * @Description:
-   *   Return an outline's `control box'.  The control box encloses all
-   *   the outline's points, including Bézier control points.  Though it
-   *   coincides with the exact bounding box for most glyphs, it can be
-   *   slightly larger in some situations (like when rotating an outline
-   *   that contains Bézier outside arcs).
-   *
-   *   Computing the control box is very fast, while getting the bounding
-   *   box can take much more time as it needs to walk over all segments
-   *   and arcs in the outline.  To get the latter, you can use the
-   *   `ftbbox' component, which is dedicated to this single task.
-   *
-   * @Input:
-   *   outline ::
-   *     A pointer to the source outline descriptor.
-   *
-   * @Output:
-   *   acbox ::
-   *     The outline's control box.
-   *
-   * @Note:
-   *   See @FT_Glyph_Get_CBox for a discussion of tricky fonts.
-   */
-
-  static void
-  FT_Outline_Get_CBox( const FT_Outline*  outline,
-                       FT_BBox           *acbox )
-  {
-    if ( outline && acbox )
-    {
-      Long  xMin, yMin, xMax, yMax;
-
-
-      if ( outline->n_points == 0 )
-      {
-        xMin = 0;
-        yMin = 0;
-        xMax = 0;
-        yMax = 0;
-      }
-      else
-      {
-        FT_Vector*  vec   = outline->points;
-        FT_Vector*  limit = vec + outline->n_points;
-
-
-        xMin = xMax = vec->x;
-        yMin = yMax = vec->y;
-        vec++;
+          if ( P_Left->flags & Dropout )
+          {
+            ras.Proc_Sweep_Drop( RAS_VARS y, P_Left->X, P_Right->X );
 
-        for ( ; vec < limit; vec++ )
-        {
-          Long  x, y;
+            P_Left->flags &= ~Dropout;
+            dropouts--;
+          }
 
+          P_Left  = P_Left->link;
+          P_Right = P_Right->link;
+        }
 
-          x = vec->x;
-          if ( x < xMin ) xMin = x;
-          if ( x > xMax ) xMax = x;
+        ras.Proc_Sweep_Step( RAS_VAR );
 
-          y = vec->y;
-          if ( y < yMin ) yMin = y;
-          if ( y > yMax ) yMax = y;
-        }
+        Increment( &draw_left,   1 );
+        Increment( &draw_right, -1 );
       }
-      acbox->xMin = xMin;
-      acbox->xMax = xMax;
-      acbox->yMin = yMin;
-      acbox->yMax = yMax;
+      while ( ++y < y_turn );
     }
   }
 
-#endif /* STANDALONE_ */
-
 
   /**************************************************************************
    *
@@ -3019,13 +2458,15 @@
     Int  band_stack[32];  /* enough to bisect 32-bit int bands */
 
 
+    FT_TRACE6(( "%s pass [%d..%d]\n",
+                flipped ? "Horizontal" : "Vertical",
+                y_min, y_max ));
+
     while ( 1 )
     {
       ras.minY = (Long)y_min * ras.precision;
       ras.maxY = (Long)y_max * ras.precision;
 
-      ras.top = ras.buff;
-
       ras.error = Raster_Err_Ok;
 
       if ( Convert_Glyph( RAS_VARS flipped ) )
@@ -3038,6 +2479,9 @@
         if ( y_min == y_max )
           return ras.error;  /* still Raster_Overflow */
 
+        FT_TRACE6(( "band [%d..%d]: to be bisected\n",
+                    y_min, y_max ));
+
         y_mid = ( y_min + y_max ) >> 1;
 
         band_stack[band_top++] = y_min;
@@ -3045,9 +2489,12 @@
       }
       else
       {
+        FT_TRACE6(( "band [%d..%d]: %hd profiles; %td bytes remaining\n",
+                    y_min, y_max, ras.num_Profs,
+                    (char*)ras.maxBuff - (char*)ras.top ));
+
         if ( ras.fProfile )
-          if ( Draw_Sweep( RAS_VAR ) )
-             return ras.error;
+          Draw_Sweep( RAS_VAR );
 
         if ( --band_top < 0 )
           break;
@@ -3076,53 +2523,48 @@
   Render_Glyph( RAS_ARG )
   {
     FT_Error  error;
+    Long      buffer[FT_MAX_BLACK_POOL];
 
 
+    ras.buff     = buffer;
+    ras.sizeBuff = (&buffer)[1]; /* Points to right after buffer. */
+
     Set_High_Precision( RAS_VARS ras.outline.flags &
                                  FT_OUTLINE_HIGH_PRECISION );
 
+    ras.dropOutControl = 0;
+
     if ( ras.outline.flags & FT_OUTLINE_IGNORE_DROPOUTS )
-      ras.dropOutControl = 2;
-    else
-    {
-      if ( ras.outline.flags & FT_OUTLINE_SMART_DROPOUTS )
-        ras.dropOutControl = 4;
-      else
-        ras.dropOutControl = 0;
+      ras.dropOutControl |= 2;
 
-      if ( !( ras.outline.flags & FT_OUTLINE_INCLUDE_STUBS ) )
-        ras.dropOutControl += 1;
-    }
+    if ( ras.outline.flags & FT_OUTLINE_SMART_DROPOUTS )
+      ras.dropOutControl |= 4;
 
-    /* Vertical Sweep */
-    FT_TRACE7(( "Vertical pass (ftraster)\n" ));
+    if ( !( ras.outline.flags & FT_OUTLINE_INCLUDE_STUBS ) )
+      ras.dropOutControl |= 1;
+
+    FT_TRACE6(( "BW Raster: precision 1/%d, dropout mode %d\n",
+                ras.precision, ras.dropOutControl ));
 
+    /* Vertical Sweep */
     ras.Proc_Sweep_Init = Vertical_Sweep_Init;
     ras.Proc_Sweep_Span = Vertical_Sweep_Span;
     ras.Proc_Sweep_Drop = Vertical_Sweep_Drop;
     ras.Proc_Sweep_Step = Vertical_Sweep_Step;
 
-    ras.bWidth  = (UShort)ras.target.width;
-    ras.bOrigin = (Byte*)ras.target.buffer;
-
-    if ( ras.target.pitch > 0 )
-      ras.bOrigin += (Long)( ras.target.rows - 1 ) * ras.target.pitch;
-
-    error = Render_Single_Pass( RAS_VARS 0, 0, (Int)ras.target.rows - 1 );
+    error = Render_Single_Pass( RAS_VARS 0, 0, ras.bTop );
     if ( error )
       return error;
 
     /* Horizontal Sweep */
     if ( !( ras.outline.flags & FT_OUTLINE_SINGLE_PASS ) )
     {
-      FT_TRACE7(( "Horizontal pass (ftraster)\n" ));
-
       ras.Proc_Sweep_Init = Horizontal_Sweep_Init;
       ras.Proc_Sweep_Span = Horizontal_Sweep_Span;
       ras.Proc_Sweep_Drop = Horizontal_Sweep_Drop;
       ras.Proc_Sweep_Step = Horizontal_Sweep_Step;
 
-      error = Render_Single_Pass( RAS_VARS 1, 0, (Int)ras.target.width - 1 );
+      error = Render_Single_Pass( RAS_VARS 1, 0, ras.bRight );
       if ( error )
         return error;
     }
@@ -3233,8 +2675,6 @@
     black_TWorker  worker[1];
 #endif
 
-    Long  buffer[FT_MAX_BLACK_POOL];
-
 
     if ( !raster )
       return FT_THROW( Raster_Uninitialized );
@@ -3243,7 +2683,7 @@
       return FT_THROW( Invalid_Outline );
 
     /* return immediately if the outline is empty */
-    if ( outline->n_points == 0 || outline->n_contours <= 0 )
+    if ( outline->n_points == 0 || outline->n_contours == 0 )
       return Raster_Err_Ok;
 
     if ( !outline->contours || !outline->points )
@@ -3269,10 +2709,14 @@
       return FT_THROW( Invalid_Argument );
 
     ras.outline = *outline;
-    ras.target  = *target_map;
 
-    ras.buff     = buffer;
-    ras.sizeBuff = (&buffer)[1]; /* Points to right after buffer. */
+    ras.bTop    =   (Int)target_map->rows - 1;
+    ras.bRight  =   (Int)target_map->width - 1;
+    ras.bPitch  =   (Int)target_map->pitch;
+    ras.bOrigin = (PByte)target_map->buffer;
+
+    if ( ras.bPitch > 0 )
+      ras.bOrigin += ras.bTop * ras.bPitch;
 
     return Render_Glyph( RAS_VAR );
   }
diff --git a/vendor/freetype/src/raster/ftraster.h b/vendor/freetype/src/raster/ftraster.h
index b511b3a99e..ad9cb1b9fe 100644
--- a/vendor/freetype/src/raster/ftraster.h
+++ b/vendor/freetype/src/raster/ftraster.h
@@ -4,7 +4,7 @@
  *
  *   The FreeType glyph rasterizer (specification).
  *
- * Copyright (C) 1996-2023 by
+ * Copyright (C) 1996-2024 by
  * David Turner, Robert Wilhelm, and Werner Lemberg.
  *
  * This file is part of the FreeType project, and may only be used
diff --git a/vendor/freetype/src/raster/ftrend1.c b/vendor/freetype/src/raster/ftrend1.c
index 6d442b1ff8..fd9f174f2e 100644
--- a/vendor/freetype/src/raster/ftrend1.c
+++ b/vendor/freetype/src/raster/ftrend1.c
@@ -4,7 +4,7 @@
  *
  *   The FreeType glyph rasterizer interface (body).
  *
- * Copyright (C) 1996-2023 by
+ * Copyright (C) 1996-2024 by
  * David Turner, Robert Wilhelm, and Werner Lemberg.
  *
  * This file is part of the FreeType project, and may only be used,
diff --git a/vendor/freetype/src/raster/ftrend1.h b/vendor/freetype/src/raster/ftrend1.h
index cec35c8528..cf3e73c0a2 100644
--- a/vendor/freetype/src/raster/ftrend1.h
+++ b/vendor/freetype/src/raster/ftrend1.h
@@ -4,7 +4,7 @@
  *
  *   The FreeType glyph rasterizer interface (specification).
  *
- * Copyright (C) 1996-2023 by
+ * Copyright (C) 1996-2024 by
  * David Turner, Robert Wilhelm, and Werner Lemberg.
  *
  * This file is part of the FreeType project, and may only be used,
diff --git a/vendor/freetype/src/raster/raster.c b/vendor/freetype/src/raster/raster.c
index 82f474547d..fe33af2423 100644
--- a/vendor/freetype/src/raster/raster.c
+++ b/vendor/freetype/src/raster/raster.c
@@ -4,7 +4,7 @@
  *
  *   FreeType monochrome rasterer module component (body only).
  *
- * Copyright (C) 1996-2023 by
+ * Copyright (C) 1996-2024 by
  * David Turner, Robert Wilhelm, and Werner Lemberg.
  *
  * This file is part of the FreeType project, and may only be used,
diff --git a/vendor/freetype/src/raster/rasterrs.h b/vendor/freetype/src/raster/rasterrs.h
index 989d8b44be..326d42e043 100644
--- a/vendor/freetype/src/raster/rasterrs.h
+++ b/vendor/freetype/src/raster/rasterrs.h
@@ -4,7 +4,7 @@
  *
  *   monochrome renderer error codes (specification only).
  *
- * Copyright (C) 2001-2023 by
+ * Copyright (C) 2001-2024 by
  * David Turner, Robert Wilhelm, and Werner Lemberg.
  *
  * This file is part of the FreeType project, and may only be used,
diff --git a/vendor/freetype/src/sdf/ftbsdf.c b/vendor/freetype/src/sdf/ftbsdf.c
index e472738339..adde05ba19 100644
--- a/vendor/freetype/src/sdf/ftbsdf.c
+++ b/vendor/freetype/src/sdf/ftbsdf.c
@@ -4,7 +4,7 @@
  *
  *   Signed Distance Field support for bitmap fonts (body only).
  *
- * Copyright (C) 2020-2023 by
+ * Copyright (C) 2020-2024 by
  * David Turner, Robert Wilhelm, and Werner Lemberg.
  *
  * Written by Anuj Verma.
diff --git a/vendor/freetype/src/sdf/ftsdf.c b/vendor/freetype/src/sdf/ftsdf.c
index bc4625d984..dc55d42630 100644
--- a/vendor/freetype/src/sdf/ftsdf.c
+++ b/vendor/freetype/src/sdf/ftsdf.c
@@ -4,7 +4,7 @@
  *
  *   Signed Distance Field support for outline fonts (body).
  *
- * Copyright (C) 2020-2023 by
+ * Copyright (C) 2020-2024 by
  * David Turner, Robert Wilhelm, and Werner Lemberg.
  *
  * Written by Anuj Verma.
@@ -3837,7 +3837,7 @@
     }
 
     /* if the outline is empty, return */
-    if ( outline->n_points <= 0 || outline->n_contours <= 0 )
+    if ( outline->n_points == 0 || outline->n_contours == 0 )
       goto Exit;
 
     /* check whether the outline has valid fields */
diff --git a/vendor/freetype/src/sdf/ftsdf.h b/vendor/freetype/src/sdf/ftsdf.h
index 234c075b0a..25a0a13bb8 100644
--- a/vendor/freetype/src/sdf/ftsdf.h
+++ b/vendor/freetype/src/sdf/ftsdf.h
@@ -4,7 +4,7 @@
  *
  *   Signed Distance Field support (specification).
  *
- * Copyright (C) 2020-2023 by
+ * Copyright (C) 2020-2024 by
  * David Turner, Robert Wilhelm, and Werner Lemberg.
  *
  * Written by Anuj Verma.
diff --git a/vendor/freetype/src/sdf/ftsdfcommon.c b/vendor/freetype/src/sdf/ftsdfcommon.c
index 5052201e22..6b2cf7dfec 100644
--- a/vendor/freetype/src/sdf/ftsdfcommon.c
+++ b/vendor/freetype/src/sdf/ftsdfcommon.c
@@ -4,7 +4,7 @@
  *
  *   Auxiliary data for Signed Distance Field support (body).
  *
- * Copyright (C) 2020-2023 by
+ * Copyright (C) 2020-2024 by
  * David Turner, Robert Wilhelm, and Werner Lemberg.
  *
  * Written by Anuj Verma.
@@ -22,49 +22,6 @@
 #include "ftsdfcommon.h"
 
 
-  /**************************************************************************
-   *
-   * common functions
-   *
-   */
-
-  /*
-   * Original algorithm:
-   *
-   *   https://github.com/chmike/fpsqrt
-   *
-   * Use this to compute the square root of a 16.16 fixed-point number.
-   */
-  FT_LOCAL_DEF( FT_16D16 )
-  square_root( FT_16D16  val )
-  {
-    FT_ULong  t, q, b, r;
-
-
-    r = (FT_ULong)val;
-    b = 0x40000000L;
-    q = 0;
-
-    while ( b > 0x40L )
-    {
-      t = q + b;
-
-      if ( r >= t )
-      {
-        r -= t;
-        q  = t + b;
-      }
-
-      r <<= 1;
-      b >>= 1;
-    }
-
-    q >>= 8;
-
-    return (FT_16D16)q;
-  }
-
-
   /**************************************************************************
    *
    * format and sign manipulating functions
diff --git a/vendor/freetype/src/sdf/ftsdfcommon.h b/vendor/freetype/src/sdf/ftsdfcommon.h
index 60ca9773e3..d0f623f9f3 100644
--- a/vendor/freetype/src/sdf/ftsdfcommon.h
+++ b/vendor/freetype/src/sdf/ftsdfcommon.h
@@ -4,7 +4,7 @@
  *
  *   Auxiliary data for Signed Distance Field support (specification).
  *
- * Copyright (C) 2020-2023 by
+ * Copyright (C) 2020-2024 by
  * David Turner, Robert Wilhelm, and Werner Lemberg.
  *
  * Written by Anuj Verma.
@@ -122,8 +122,7 @@ FT_BEGIN_HEADER
   typedef FT_BBox   FT_CBox;       /* control box of a curve            */
 
 
-  FT_LOCAL( FT_16D16 )
-  square_root( FT_16D16  val );
+#define square_root( x )  (FT_16D16)FT_SqrtFixed( (FT_UInt32)( x ) )
 
   FT_LOCAL( FT_SDFFormat )
   map_fixed_to_sdf( FT_16D16  dist,
diff --git a/vendor/freetype/src/sdf/ftsdferrs.h b/vendor/freetype/src/sdf/ftsdferrs.h
index 519db0fc26..5af873fafb 100644
--- a/vendor/freetype/src/sdf/ftsdferrs.h
+++ b/vendor/freetype/src/sdf/ftsdferrs.h
@@ -4,7 +4,7 @@
  *
  *   Signed Distance Field error codes (specification only).
  *
- * Copyright (C) 2020-2023 by
+ * Copyright (C) 2020-2024 by
  * David Turner, Robert Wilhelm, and Werner Lemberg.
  *
  * Written by Anuj Verma.
diff --git a/vendor/freetype/src/sdf/ftsdfrend.c b/vendor/freetype/src/sdf/ftsdfrend.c
index 5610c119f8..d3324678d6 100644
--- a/vendor/freetype/src/sdf/ftsdfrend.c
+++ b/vendor/freetype/src/sdf/ftsdfrend.c
@@ -4,7 +4,7 @@
  *
  *   Signed Distance Field renderer interface (body).
  *
- * Copyright (C) 2020-2023 by
+ * Copyright (C) 2020-2024 by
  * David Turner, Robert Wilhelm, and Werner Lemberg.
  *
  * Written by Anuj Verma.
diff --git a/vendor/freetype/src/sdf/ftsdfrend.h b/vendor/freetype/src/sdf/ftsdfrend.h
index 571ac833d3..2ea6f86819 100644
--- a/vendor/freetype/src/sdf/ftsdfrend.h
+++ b/vendor/freetype/src/sdf/ftsdfrend.h
@@ -4,7 +4,7 @@
  *
  *   Signed Distance Field renderer interface (specification).
  *
- * Copyright (C) 2020-2023 by
+ * Copyright (C) 2020-2024 by
  * David Turner, Robert Wilhelm, and Werner Lemberg.
  *
  * Written by Anuj Verma.
diff --git a/vendor/freetype/src/sdf/sdf.c b/vendor/freetype/src/sdf/sdf.c
index c159b08128..6045b8330b 100644
--- a/vendor/freetype/src/sdf/sdf.c
+++ b/vendor/freetype/src/sdf/sdf.c
@@ -4,7 +4,7 @@
  *
  *   FreeType Signed Distance Field renderer module component (body only).
  *
- * Copyright (C) 2020-2023 by
+ * Copyright (C) 2020-2024 by
  * David Turner, Robert Wilhelm, and Werner Lemberg.
  *
  * Written by Anuj Verma.
diff --git a/vendor/freetype/src/sfnt/pngshim.c b/vendor/freetype/src/sfnt/pngshim.c
index 33712162e0..76181568af 100644
--- a/vendor/freetype/src/sfnt/pngshim.c
+++ b/vendor/freetype/src/sfnt/pngshim.c
@@ -4,7 +4,7 @@
  *
  *   PNG Bitmap glyph support.
  *
- * Copyright (C) 2013-2023 by
+ * Copyright (C) 2013-2024 by
  * Google, Inc.
  * Written by Stuart Gill and Behdad Esfahbod.
  *
diff --git a/vendor/freetype/src/sfnt/pngshim.h b/vendor/freetype/src/sfnt/pngshim.h
index 903bd2bc34..6e7a5c08e7 100644
--- a/vendor/freetype/src/sfnt/pngshim.h
+++ b/vendor/freetype/src/sfnt/pngshim.h
@@ -4,7 +4,7 @@
  *
  *   PNG Bitmap glyph support.
  *
- * Copyright (C) 2013-2023 by
+ * Copyright (C) 2013-2024 by
  * Google, Inc.
  * Written by Stuart Gill and Behdad Esfahbod.
  *
diff --git a/vendor/freetype/src/sfnt/sfdriver.c b/vendor/freetype/src/sfnt/sfdriver.c
index 0925940b03..81072207b4 100644
--- a/vendor/freetype/src/sfnt/sfdriver.c
+++ b/vendor/freetype/src/sfnt/sfdriver.c
@@ -4,7 +4,7 @@
  *
  *   High-level SFNT driver interface (body).
  *
- * Copyright (C) 1996-2023 by
+ * Copyright (C) 1996-2024 by
  * David Turner, Robert Wilhelm, and Werner Lemberg.
  *
  * This file is part of the FreeType project, and may only be used,
@@ -49,6 +49,10 @@
 #include 
 #endif
 
+#ifdef TT_CONFIG_OPTION_GPOS_KERNING
+#include "ttgpos.h"
+#endif
+
 #include "ttcmap.h"
 #include "ttkern.h"
 #include "ttmtx.h"
@@ -1249,6 +1253,12 @@
 #define PUT_PS_NAMES( a )  a
 #else
 #define PUT_PS_NAMES( a )  NULL
+#endif
+
+#ifdef TT_CONFIG_OPTION_GPOS_KERNING
+#define PUT_GPOS_KERNING( a )  a
+#else
+#define PUT_GPOS_KERNING( a )  NULL
 #endif
 
   FT_DEFINE_SFNT_INTERFACE(
@@ -1274,6 +1284,8 @@
     tt_face_free_name,      /* TT_Free_Table_Func      free_name       */
 
     tt_face_load_kern,      /* TT_Load_Table_Func      load_kern       */
+    PUT_GPOS_KERNING( tt_face_load_gpos ),
+                            /* TT_Load_Table_Func      load_gpos       */
     tt_face_load_gasp,      /* TT_Load_Table_Func      load_gasp       */
     tt_face_load_pclt,      /* TT_Load_Table_Func      load_init       */
 
@@ -1292,6 +1304,9 @@
     /* since version 2.1.8 */
     tt_face_get_kerning,    /* TT_Face_GetKerningFunc  get_kerning     */
 
+    PUT_GPOS_KERNING( tt_face_get_gpos_kerning ),
+                           /* TT_Face_GetKerningFunc  get_gpos_kerning */
+
     /* since version 2.2 */
     tt_face_load_font_dir,  /* TT_Load_Table_Func      load_font_dir   */
     tt_face_load_hmtx,      /* TT_Load_Metrics_Func    load_hmtx       */
diff --git a/vendor/freetype/src/sfnt/sfdriver.h b/vendor/freetype/src/sfnt/sfdriver.h
index 2445958b69..6f71489fdc 100644
--- a/vendor/freetype/src/sfnt/sfdriver.h
+++ b/vendor/freetype/src/sfnt/sfdriver.h
@@ -4,7 +4,7 @@
  *
  *   High-level SFNT driver interface (specification).
  *
- * Copyright (C) 1996-2023 by
+ * Copyright (C) 1996-2024 by
  * David Turner, Robert Wilhelm, and Werner Lemberg.
  *
  * This file is part of the FreeType project, and may only be used,
diff --git a/vendor/freetype/src/sfnt/sferrors.h b/vendor/freetype/src/sfnt/sferrors.h
index e7a8eb04bb..d3ca1d9aa8 100644
--- a/vendor/freetype/src/sfnt/sferrors.h
+++ b/vendor/freetype/src/sfnt/sferrors.h
@@ -4,7 +4,7 @@
  *
  *   SFNT error codes (specification only).
  *
- * Copyright (C) 2001-2023 by
+ * Copyright (C) 2001-2024 by
  * David Turner, Robert Wilhelm, and Werner Lemberg.
  *
  * This file is part of the FreeType project, and may only be used,
diff --git a/vendor/freetype/src/sfnt/sfnt.c b/vendor/freetype/src/sfnt/sfnt.c
index 8e4f08a90c..52411febc4 100644
--- a/vendor/freetype/src/sfnt/sfnt.c
+++ b/vendor/freetype/src/sfnt/sfnt.c
@@ -4,7 +4,7 @@
  *
  *   Single object library component.
  *
- * Copyright (C) 1996-2023 by
+ * Copyright (C) 1996-2024 by
  * David Turner, Robert Wilhelm, and Werner Lemberg.
  *
  * This file is part of the FreeType project, and may only be used,
@@ -29,6 +29,7 @@
 #include "ttcpal.c"
 #include "ttsvg.c"
 
+#include "ttgpos.c"
 #include "ttkern.c"
 #include "ttload.c"
 #include "ttmtx.c"
diff --git a/vendor/freetype/src/sfnt/sfobjs.c b/vendor/freetype/src/sfnt/sfobjs.c
index f5d66ef840..6ee4e5e939 100644
--- a/vendor/freetype/src/sfnt/sfobjs.c
+++ b/vendor/freetype/src/sfnt/sfobjs.c
@@ -4,7 +4,7 @@
  *
  *   SFNT object management (base).
  *
- * Copyright (C) 1996-2023 by
+ * Copyright (C) 1996-2024 by
  * David Turner, Robert Wilhelm, and Werner Lemberg.
  *
  * This file is part of the FreeType project, and may only be used,
@@ -40,6 +40,10 @@
 #include "ttbdf.h"
 #endif
 
+#ifdef TT_CONFIG_OPTION_GPOS_KERNING
+#include "ttgpos.h"
+#endif
+
 
   /**************************************************************************
    *
@@ -1026,6 +1030,10 @@
     LOAD_( gasp );
     LOAD_( kern );
 
+#ifdef TT_CONFIG_OPTION_GPOS_KERNING
+    LOAD_( gpos );
+#endif
+
     face->root.num_glyphs = face->max_profile.numGlyphs;
 
     /* Bit 8 of the `fsSelection' field in the `OS/2' table denotes  */
@@ -1119,7 +1127,11 @@
         flags |= FT_FACE_FLAG_VERTICAL;
 
       /* kerning available ? */
-      if ( TT_FACE_HAS_KERNING( face ) )
+      if ( TT_FACE_HAS_KERNING( face )
+#ifdef TT_CONFIG_OPTION_GPOS_KERNING
+           || face->gpos_kerning_available
+#endif
+         )
         flags |= FT_FACE_FLAG_KERNING;
 
 #ifdef TT_CONFIG_OPTION_GX_VAR_SUPPORT
@@ -1470,6 +1482,11 @@
     /* freeing the kerning table */
     tt_face_done_kern( face );
 
+#ifdef TT_CONFIG_OPTION_GPOS_KERNING
+    /* freeing the GPOS table */
+    tt_face_done_gpos( face );
+#endif
+
     /* freeing the collection table */
     FT_FREE( face->ttc_header.offsets );
     face->ttc_header.count = 0;
diff --git a/vendor/freetype/src/sfnt/sfobjs.h b/vendor/freetype/src/sfnt/sfobjs.h
index 906aebbf90..90847d9573 100644
--- a/vendor/freetype/src/sfnt/sfobjs.h
+++ b/vendor/freetype/src/sfnt/sfobjs.h
@@ -4,7 +4,7 @@
  *
  *   SFNT object management (specification).
  *
- * Copyright (C) 1996-2023 by
+ * Copyright (C) 1996-2024 by
  * David Turner, Robert Wilhelm, and Werner Lemberg.
  *
  * This file is part of the FreeType project, and may only be used,
diff --git a/vendor/freetype/src/sfnt/sfwoff.c b/vendor/freetype/src/sfnt/sfwoff.c
index 7c0ce2205e..14514bf957 100644
--- a/vendor/freetype/src/sfnt/sfwoff.c
+++ b/vendor/freetype/src/sfnt/sfwoff.c
@@ -4,7 +4,7 @@
  *
  *   WOFF format management (base).
  *
- * Copyright (C) 1996-2023 by
+ * Copyright (C) 1996-2024 by
  * David Turner, Robert Wilhelm, and Werner Lemberg.
  *
  * This file is part of the FreeType project, and may only be used,
@@ -18,6 +18,7 @@
 
 #include "sfwoff.h"
 #include 
+#include 
 #include 
 #include 
 #include 
@@ -149,6 +150,7 @@
     /* Miscellaneous checks. */
     if ( woff.length != stream->size                              ||
          woff.num_tables == 0                                     ||
+         woff.num_tables >  0xFFFU                                ||
          44 + woff.num_tables * 20UL >= woff.length               ||
          12 + woff.num_tables * 16UL >= woff.totalSfntSize        ||
          ( woff.totalSfntSize & 3 ) != 0                          ||
@@ -169,21 +171,11 @@
 
     /* Write sfnt header. */
     {
-      FT_UInt  searchRange, entrySelector, rangeShift, x;
+      FT_Int  entrySelector = FT_MSB( woff.num_tables );
+      FT_Int  searchRange   = ( 1 << entrySelector ) * 16;
+      FT_Int  rangeShift    = woff.num_tables * 16 - searchRange;
 
 
-      x             = woff.num_tables;
-      entrySelector = 0;
-      while ( x )
-      {
-        x            >>= 1;
-        entrySelector += 1;
-      }
-      entrySelector--;
-
-      searchRange = ( 1 << entrySelector ) * 16;
-      rangeShift  = woff.num_tables * 16 - searchRange;
-
       WRITE_ULONG ( sfnt_header, woff.flavor );
       WRITE_USHORT( sfnt_header, woff.num_tables );
       WRITE_USHORT( sfnt_header, searchRange );
diff --git a/vendor/freetype/src/sfnt/sfwoff.h b/vendor/freetype/src/sfnt/sfwoff.h
index d438422737..a04735ffe2 100644
--- a/vendor/freetype/src/sfnt/sfwoff.h
+++ b/vendor/freetype/src/sfnt/sfwoff.h
@@ -4,7 +4,7 @@
  *
  *   WOFFF format management (specification).
  *
- * Copyright (C) 1996-2023 by
+ * Copyright (C) 1996-2024 by
  * David Turner, Robert Wilhelm, and Werner Lemberg.
  *
  * This file is part of the FreeType project, and may only be used,
diff --git a/vendor/freetype/src/sfnt/sfwoff2.c b/vendor/freetype/src/sfnt/sfwoff2.c
index 2be44a347a..589b3e0c6b 100644
--- a/vendor/freetype/src/sfnt/sfwoff2.c
+++ b/vendor/freetype/src/sfnt/sfwoff2.c
@@ -4,7 +4,7 @@
  *
  *   WOFF2 format management (base).
  *
- * Copyright (C) 2019-2023 by
+ * Copyright (C) 2019-2024 by
  * Nikhil Ramakrishnan, David Turner, Robert Wilhelm, and Werner Lemberg.
  *
  * This file is part of the FreeType project, and may only be used,
@@ -18,6 +18,7 @@
 #include "sfwoff2.h"
 #include "woff2tags.h"
 #include 
+#include 
 #include 
 #include 
 
@@ -289,23 +290,15 @@
     FT_ULong  checksum     = 0;
     FT_ULong  aligned_size = size & ~3UL;
     FT_ULong  i;
-    FT_ULong  v;
+    FT_Int    shift;
 
 
     for ( i = 0; i < aligned_size; i += 4 )
-      checksum += ( (FT_ULong)buf[i    ] << 24 ) |
-                  ( (FT_ULong)buf[i + 1] << 16 ) |
-                  ( (FT_ULong)buf[i + 2] <<  8 ) |
-                  ( (FT_ULong)buf[i + 3] <<  0 );
+      checksum += FT_NEXT_ULONG( buf );
 
-    /* If size is not aligned to 4, treat as if it is padded with 0s. */
-    if ( size != aligned_size )
-    {
-      v = 0;
-      for ( i = aligned_size ; i < size; ++i )
-        v |= (FT_ULong)buf[i] << ( 24 - 8 * ( i & 3 ) );
-      checksum += v;
-    }
+    /* remaining bytes can be shifted and added one at a time */
+    for ( shift = 24; i < size; i++, shift -= 8 )
+      checksum += (FT_UInt32)FT_NEXT_BYTE( buf ) << shift;
 
     return checksum;
   }
@@ -1799,7 +1792,6 @@
 
     FT_Byte*   sfnt        = NULL;
     FT_Stream  sfnt_stream = NULL;
-    FT_Byte*   sfnt_header;
     FT_ULong   sfnt_size;
 
     FT_Byte*  uncompressed_buf = NULL;
@@ -1853,6 +1845,7 @@
     /* Miscellaneous checks. */
     if ( woff2.length != stream->size                               ||
          woff2.num_tables == 0                                      ||
+         woff2.num_tables >  0xFFFU                                 ||
          48 + woff2.num_tables * 20UL >= woff2.length               ||
          ( woff2.metaOffset == 0 && ( woff2.metaLength != 0     ||
                                       woff2.metaOrigLength != 0 ) ) ||
@@ -2143,6 +2136,13 @@
       WOFF2_TtcFont  ttc_font = woff2.ttc_fonts + face_index;
 
 
+      if ( ttc_font->num_tables == 0 || ttc_font->num_tables > 0xFFFU )
+      {
+        FT_ERROR(( "woff2_open_font: invalid WOFF2 CollectionFontEntry\n" ));
+        error = FT_THROW( Invalid_Table );
+        goto Exit;
+      }
+
       /* Create a temporary array. */
       if ( FT_QNEW_ARRAY( temp_indices,
                           ttc_font->num_tables ) )
@@ -2198,27 +2198,15 @@
          FT_NEW( sfnt_stream )        )
       goto Exit;
 
-    sfnt_header = sfnt;
-
-    WRITE_ULONG( sfnt_header, woff2.flavor );
-
-    if ( woff2.num_tables )
     {
-      FT_UInt  searchRange, entrySelector, rangeShift, x;
+      FT_Byte*  sfnt_header = sfnt;
 
+      FT_Int  entrySelector = FT_MSB( woff2.num_tables );
+      FT_Int  searchRange   = ( 1 << entrySelector ) * 16;
+      FT_Int  rangeShift    = woff2.num_tables * 16 - searchRange;
 
-      x             = woff2.num_tables;
-      entrySelector = 0;
-      while ( x )
-      {
-        x            >>= 1;
-        entrySelector += 1;
-      }
-      entrySelector--;
-
-      searchRange = ( 1 << entrySelector ) * 16;
-      rangeShift  = ( woff2.num_tables * 16 ) - searchRange;
 
+      WRITE_ULONG ( sfnt_header, woff2.flavor );
       WRITE_USHORT( sfnt_header, woff2.num_tables );
       WRITE_USHORT( sfnt_header, searchRange );
       WRITE_USHORT( sfnt_header, entrySelector );
diff --git a/vendor/freetype/src/sfnt/sfwoff2.h b/vendor/freetype/src/sfnt/sfwoff2.h
index 4901286ee0..f41140648d 100644
--- a/vendor/freetype/src/sfnt/sfwoff2.h
+++ b/vendor/freetype/src/sfnt/sfwoff2.h
@@ -4,7 +4,7 @@
  *
  *   WOFFF2 format management (specification).
  *
- * Copyright (C) 2019-2023 by
+ * Copyright (C) 2019-2024 by
  * Nikhil Ramakrishnan, David Turner, Robert Wilhelm, and Werner Lemberg.
  *
  * This file is part of the FreeType project, and may only be used,
diff --git a/vendor/freetype/src/sfnt/ttbdf.c b/vendor/freetype/src/sfnt/ttbdf.c
index 536fa7467e..6138fc46d5 100644
--- a/vendor/freetype/src/sfnt/ttbdf.c
+++ b/vendor/freetype/src/sfnt/ttbdf.c
@@ -4,7 +4,7 @@
  *
  *   TrueType and OpenType embedded BDF properties (body).
  *
- * Copyright (C) 2005-2023 by
+ * Copyright (C) 2005-2024 by
  * David Turner, Robert Wilhelm, and Werner Lemberg.
  *
  * This file is part of the FreeType project, and may only be used,
diff --git a/vendor/freetype/src/sfnt/ttbdf.h b/vendor/freetype/src/sfnt/ttbdf.h
index 0d7a0acecc..d8d722b928 100644
--- a/vendor/freetype/src/sfnt/ttbdf.h
+++ b/vendor/freetype/src/sfnt/ttbdf.h
@@ -4,7 +4,7 @@
  *
  *   TrueType and OpenType embedded BDF properties (specification).
  *
- * Copyright (C) 2005-2023 by
+ * Copyright (C) 2005-2024 by
  * David Turner, Robert Wilhelm, and Werner Lemberg.
  *
  * This file is part of the FreeType project, and may only be used,
diff --git a/vendor/freetype/src/sfnt/ttcmap.c b/vendor/freetype/src/sfnt/ttcmap.c
index 9ba25dcbc1..28f4d1173c 100644
--- a/vendor/freetype/src/sfnt/ttcmap.c
+++ b/vendor/freetype/src/sfnt/ttcmap.c
@@ -4,7 +4,7 @@
  *
  *   TrueType character mapping table (cmap) support (body).
  *
- * Copyright (C) 2002-2023 by
+ * Copyright (C) 2002-2024 by
  * David Turner, Robert Wilhelm, and Werner Lemberg.
  *
  * This file is part of the FreeType project, and may only be used,
diff --git a/vendor/freetype/src/sfnt/ttcmap.h b/vendor/freetype/src/sfnt/ttcmap.h
index ff52917ed5..e2c5e72bf0 100644
--- a/vendor/freetype/src/sfnt/ttcmap.h
+++ b/vendor/freetype/src/sfnt/ttcmap.h
@@ -4,7 +4,7 @@
  *
  *   TrueType character mapping table (cmap) support (specification).
  *
- * Copyright (C) 2002-2023 by
+ * Copyright (C) 2002-2024 by
  * David Turner, Robert Wilhelm, and Werner Lemberg.
  *
  * This file is part of the FreeType project, and may only be used,
diff --git a/vendor/freetype/src/sfnt/ttcmapc.h b/vendor/freetype/src/sfnt/ttcmapc.h
index 0af48c2478..370898363f 100644
--- a/vendor/freetype/src/sfnt/ttcmapc.h
+++ b/vendor/freetype/src/sfnt/ttcmapc.h
@@ -4,7 +4,7 @@
  *
  *   TT CMAP classes definitions (specification only).
  *
- * Copyright (C) 2009-2023 by
+ * Copyright (C) 2009-2024 by
  * Oran Agra and Mickey Gabel.
  *
  * This file is part of the FreeType project, and may only be used,
diff --git a/vendor/freetype/src/sfnt/ttcolr.c b/vendor/freetype/src/sfnt/ttcolr.c
index 281e7135ee..b37658dde9 100644
--- a/vendor/freetype/src/sfnt/ttcolr.c
+++ b/vendor/freetype/src/sfnt/ttcolr.c
@@ -4,7 +4,7 @@
  *
  *   TrueType and OpenType colored glyph layer support (body).
  *
- * Copyright (C) 2018-2023 by
+ * Copyright (C) 2018-2024 by
  * David Turner, Robert Wilhelm, Dominik Röttsches, and Werner Lemberg.
  *
  * Originally written by Shao Yu Zhang .
@@ -208,18 +208,19 @@
     colr->num_base_glyphs = FT_NEXT_USHORT( p );
     base_glyph_offset     = FT_NEXT_ULONG( p );
 
-    if ( base_glyph_offset >= table_size )
+    if ( table_size <= base_glyph_offset )
       goto InvalidTable;
-    if ( colr->num_base_glyphs * BASE_GLYPH_SIZE >
-           table_size - base_glyph_offset )
+    if ( ( table_size - base_glyph_offset ) / BASE_GLYPH_SIZE
+             < colr->num_base_glyphs )
       goto InvalidTable;
 
     layer_offset     = FT_NEXT_ULONG( p );
     colr->num_layers = FT_NEXT_USHORT( p );
 
-    if ( layer_offset >= table_size )
+    if ( table_size <= layer_offset )
       goto InvalidTable;
-    if ( colr->num_layers * LAYER_SIZE > table_size - layer_offset )
+    if ( ( table_size - layer_offset ) / LAYER_SIZE
+             < colr->num_layers )
       goto InvalidTable;
 
     if ( colr->version == 1 )
@@ -229,14 +230,14 @@
 
       base_glyphs_offset_v1 = FT_NEXT_ULONG( p );
 
-      if ( base_glyphs_offset_v1 >= table_size - 4 )
+      if ( table_size - 4 <= base_glyphs_offset_v1 )
         goto InvalidTable;
 
       p1                 = (FT_Byte*)( table + base_glyphs_offset_v1 );
       num_base_glyphs_v1 = FT_PEEK_ULONG( p1 );
 
-      if ( num_base_glyphs_v1 * BASE_GLYPH_PAINT_RECORD_SIZE >
-             table_size - base_glyphs_offset_v1 )
+      if ( ( table_size - base_glyphs_offset_v1 ) / BASE_GLYPH_PAINT_RECORD_SIZE
+               < num_base_glyphs_v1 )
         goto InvalidTable;
 
       colr->num_base_glyphs_v1 = num_base_glyphs_v1;
@@ -244,19 +245,19 @@
 
       layer_offset_v1 = FT_NEXT_ULONG( p );
 
-      if ( layer_offset_v1 >= table_size )
+      if ( table_size <= layer_offset_v1 )
         goto InvalidTable;
 
       if ( layer_offset_v1 )
       {
-        if ( layer_offset_v1 >= table_size - 4 )
+        if ( table_size - 4 <= layer_offset_v1 )
           goto InvalidTable;
 
         p1            = (FT_Byte*)( table + layer_offset_v1 );
         num_layers_v1 = FT_PEEK_ULONG( p1 );
 
-        if ( num_layers_v1 * LAYER_V1_LIST_PAINT_OFFSET_SIZE >
-               table_size - layer_offset_v1 )
+        if ( ( table_size - layer_offset_v1 ) / LAYER_V1_LIST_PAINT_OFFSET_SIZE
+                < num_layers_v1 )
           goto InvalidTable;
 
         colr->num_layers_v1 = num_layers_v1;
@@ -279,7 +280,7 @@
 
       clip_list_offset = FT_NEXT_ULONG( p );
 
-      if ( clip_list_offset >= table_size )
+      if ( table_size <= clip_list_offset )
         goto InvalidTable;
 
       if ( clip_list_offset )
@@ -311,7 +312,7 @@
           goto InvalidTable;
 
         var_store_offset = FT_NEXT_ULONG( p );
-        if ( var_store_offset >= table_size )
+        if ( table_size <= var_store_offset )
           goto InvalidTable;
 
         if ( var_store_offset )
@@ -661,6 +662,7 @@
       FT_UInt32  first_layer_index;
 
 
+      ENSURE_READ_BYTES( 5 );
       num_layers = FT_NEXT_BYTE( p );
       if ( num_layers > colr->num_layers_v1 )
         return 0;
@@ -1278,7 +1280,8 @@
 
     while ( min < max )
     {
-      FT_UInt  mid = min + ( max - min ) / 2;
+      FT_UInt    mid = min + ( max - min ) / 2;
+      FT_UShort  gid;
 
       /*
        * `base_glyph_begin` is the beginning of `BaseGlyphV1List`;
@@ -1287,8 +1290,7 @@
        */
       FT_Byte  *p = base_glyph_begin + 4 + mid * BASE_GLYPH_PAINT_RECORD_SIZE;
 
-      FT_UShort  gid = FT_NEXT_USHORT( p );
-
+      gid = FT_NEXT_USHORT( p );
 
       if ( gid < glyph_id )
         min = mid + 1;
diff --git a/vendor/freetype/src/sfnt/ttcolr.h b/vendor/freetype/src/sfnt/ttcolr.h
index 20c85f0359..30031464c7 100644
--- a/vendor/freetype/src/sfnt/ttcolr.h
+++ b/vendor/freetype/src/sfnt/ttcolr.h
@@ -4,7 +4,7 @@
  *
  *   TrueType and OpenType colored glyph layer support (specification).
  *
- * Copyright (C) 2018-2023 by
+ * Copyright (C) 2018-2024 by
  * David Turner, Robert Wilhelm, and Werner Lemberg.
  *
  * Originally written by Shao Yu Zhang .
diff --git a/vendor/freetype/src/sfnt/ttcpal.c b/vendor/freetype/src/sfnt/ttcpal.c
index 46ae08596f..997eb869ff 100644
--- a/vendor/freetype/src/sfnt/ttcpal.c
+++ b/vendor/freetype/src/sfnt/ttcpal.c
@@ -4,7 +4,7 @@
  *
  *   TrueType and OpenType color palette support (body).
  *
- * Copyright (C) 2018-2023 by
+ * Copyright (C) 2018-2024 by
  * David Turner, Robert Wilhelm, and Werner Lemberg.
  *
  * Originally written by Shao Yu Zhang .
diff --git a/vendor/freetype/src/sfnt/ttcpal.h b/vendor/freetype/src/sfnt/ttcpal.h
index 8e9913f0cc..bb301ae88b 100644
--- a/vendor/freetype/src/sfnt/ttcpal.h
+++ b/vendor/freetype/src/sfnt/ttcpal.h
@@ -4,7 +4,7 @@
  *
  *   TrueType and OpenType color palette support (specification).
  *
- * Copyright (C) 2018-2023 by
+ * Copyright (C) 2018-2024 by
  * David Turner, Robert Wilhelm, and Werner Lemberg.
  *
  * Originally written by Shao Yu Zhang .
diff --git a/vendor/freetype/src/sfnt/ttgpos.c b/vendor/freetype/src/sfnt/ttgpos.c
new file mode 100644
index 0000000000..c5dd043d66
--- /dev/null
+++ b/vendor/freetype/src/sfnt/ttgpos.c
@@ -0,0 +1,606 @@
+/****************************************************************************
+ *
+ * ttgpos.c
+ *
+ *   Load the TrueType GPOS table.  The only GPOS layout feature this
+ *   currently supports is kerning, from x advances in the pair adjustment
+ *   layout feature.
+ *
+ *   Parts of the implementation were adapted from:
+ *   https://github.com/nothings/stb/blob/master/stb_truetype.h
+ *
+ *   GPOS spec reference available at:
+ *   https://learn.microsoft.com/en-us/typography/opentype/spec/gpos
+ *
+ * Copyright (C) 2024 by
+ * David Saltzman
+ *
+ * This file is part of the FreeType project, and may only be used,
+ * modified, and distributed under the terms of the FreeType project
+ * license, LICENSE.TXT.  By continuing to use, modify, or distribute
+ * this file you indicate that you have read the license and
+ * understand and accept it fully.
+ */
+
+#include 
+#include 
+#include 
+#include "freetype/fttypes.h"
+#include "freetype/internal/ftobjs.h"
+#include "ttgpos.h"
+
+
+#ifdef TT_CONFIG_OPTION_GPOS_KERNING
+
+  /**************************************************************************
+   *
+   * The macro FT_COMPONENT is used in trace mode.  It is an implicit
+   * parameter of the FT_TRACE() and FT_ERROR() macros, used to print/log
+   * messages during execution.
+   */
+#undef  FT_COMPONENT
+#define FT_COMPONENT  ttgpos
+
+
+  typedef enum  coverage_table_format_type_
+  {
+    COVERAGE_TABLE_FORMAT_LIST  = 1,
+    COVERAGE_TABLE_FORMAT_RANGE = 2
+
+  } coverage_table_format_type;
+
+  typedef enum  class_def_table_format_type_
+  {
+    CLASS_DEF_TABLE_FORMAT_ARRAY        = 1,
+    CLASS_DEF_TABLE_FORMAT_RANGE_GROUPS = 2
+
+  } class_def_table_format_type;
+
+  typedef enum  gpos_lookup_type_
+  {
+    GPOS_LOOKUP_TYPE_SINGLE_ADJUSTMENT           = 1,
+    GPOS_LOOKUP_TYPE_PAIR_ADJUSTMENT             = 2,
+    GPOS_LOOKUP_TYPE_CURSIVE_ATTACHMENT          = 3,
+    GPOS_LOOKUP_TYPE_MARK_TO_BASE_ATTACHMENT     = 4,
+    GPOS_LOOKUP_TYPE_MARK_TO_LIGATURE_ATTACHMENT = 5,
+    GPOS_LOOKUP_TYPE_MARK_TO_MARK_ATTACHMENT     = 6,
+    GPOS_LOOKUP_TYPE_CONTEXT_POSITIONING         = 7,
+    GPOS_LOOKUP_TYPE_CHAINED_CONTEXT_POSITIONING = 8,
+    GPOS_LOOKUP_TYPE_EXTENSION_POSITIONING       = 9
+
+  } gpos_lookup_type;
+
+  typedef enum  gpos_pair_adjustment_format_
+  {
+    GPOS_PAIR_ADJUSTMENT_FORMAT_GLYPH_PAIR = 1,
+    GPOS_PAIR_ADJUSTMENT_FORMAT_CLASS_PAIR = 2
+
+  } gpos_pair_adjustment_format;
+
+  typedef enum  gpos_value_format_bitmask_
+  {
+    GPOS_VALUE_FORMAT_NONE               = 0x0000,
+    GPOS_VALUE_FORMAT_X_PLACEMENT        = 0x0001,
+    GPOS_VALUE_FORMAT_Y_PLACEMENT        = 0x0002,
+    GPOS_VALUE_FORMAT_X_ADVANCE          = 0x0004,
+    GPOS_VALUE_FORMAT_Y_ADVANCE          = 0x0008,
+    GPOS_VALUE_FORMAT_X_PLACEMENT_DEVICE = 0x0010,
+    GPOS_VALUE_FORMAT_Y_PLACEMENT_DEVICE = 0x0020,
+    GPOS_VALUE_FORMAT_X_ADVANCE_DEVICE   = 0x0040,
+    GPOS_VALUE_FORMAT_Y_ADVANCE_DEVICE   = 0x0080
+
+  } gpos_value_format_bitmask;
+
+
+  typedef struct TT_GPOS_Subtable_Iterator_Context_
+  {
+    /* Iteration state. */
+    FT_Byte*          current_lookup_table;
+    gpos_lookup_type  current_lookup_type;
+    FT_UShort         subtable_count;
+    FT_Byte*          subtable_offsets;
+    FT_UInt           subtable_idx;
+
+    /* Element for the current iteration. */
+    FT_Byte*          subtable;
+    gpos_lookup_type  subtable_type;
+
+  } TT_GPOS_Subtable_Iterator_Context;
+
+
+  /* Initialize a subtable iterator for a given lookup list index. */
+  static void
+  tt_gpos_subtable_iterator_init(
+    TT_GPOS_Subtable_Iterator_Context*  context,
+    FT_Byte*                            gpos_table,
+    FT_ULong                            lookup_list_idx )
+  {
+    FT_Byte*   lookup_list  = gpos_table + FT_PEEK_USHORT( gpos_table + 8 );
+    FT_UInt16  lookup_count = FT_PEEK_USHORT( lookup_list );
+
+
+    if ( lookup_list_idx < lookup_count )
+    {
+      context->current_lookup_table =
+        lookup_list + FT_PEEK_USHORT( lookup_list + 2 + 2 * lookup_list_idx );
+      context->current_lookup_type =
+        (gpos_lookup_type)FT_PEEK_USHORT( context->current_lookup_table );
+      context->subtable_count =
+        FT_PEEK_USHORT( context->current_lookup_table + 4 );
+      context->subtable_offsets = context->current_lookup_table + 6;
+    }
+    else
+    {
+      context->current_lookup_table = NULL;
+      context->current_lookup_type  = 0;
+      context->subtable_count       = 0;
+      context->subtable_offsets     = NULL;
+    }
+
+    context->subtable_idx  = 0;
+    context->subtable      = NULL;
+    context->subtable_type = 0;
+  }
+
+
+  /* Get the next subtable.  Return whether there was a next one. */
+  static FT_Bool
+  tt_gpos_subtable_iterator_next(
+    TT_GPOS_Subtable_Iterator_Context*  context )
+  {
+    if ( context->subtable_idx < context->subtable_count )
+    {
+      FT_UShort  subtable_offset =
+        FT_PEEK_USHORT( context->subtable_offsets +
+                        2 * context->subtable_idx );
+
+
+      context->subtable = context->current_lookup_table + subtable_offset;
+
+      if ( context->current_lookup_type ==
+           GPOS_LOOKUP_TYPE_EXTENSION_POSITIONING )
+      {
+        /* Update type and subtable based on extension positioning header. */
+        context->subtable_type =
+          (gpos_lookup_type)FT_PEEK_USHORT( context->subtable + 2 );
+        context->subtable += FT_PEEK_ULONG( context->subtable + 4 );
+      }
+      else
+        context->subtable_type = context->current_lookup_type;
+
+      context->subtable_idx++;
+      return TRUE;
+    }
+
+    return FALSE;
+  }
+
+
+  static FT_Int
+  tt_gpos_get_coverage_index( FT_Byte  *coverage_table,
+                              FT_UInt   glyph )
+  {
+    coverage_table_format_type  coverage_format =
+      (coverage_table_format_type)FT_PEEK_USHORT( coverage_table );
+
+
+    switch ( coverage_format )
+    {
+    case COVERAGE_TABLE_FORMAT_LIST:
+      {
+        FT_UShort  glyph_count = FT_PEEK_USHORT( coverage_table + 2 );
+
+        FT_Int  l = 0;
+        FT_Int  r = glyph_count - 1;
+        FT_Int  m;
+
+        FT_Int  straw;
+        FT_Int  needle = glyph;
+
+
+        /* Binary search. */
+        while ( l <= r )
+        {
+          FT_Byte   *glyph_array = coverage_table + 4;
+          FT_UShort  glyph_id;
+
+
+          m        = ( l + r ) >> 1;
+          glyph_id = FT_PEEK_USHORT( glyph_array + 2 * m );
+          straw    = glyph_id;
+
+          if ( needle < straw )
+            r = m - 1;
+          else if ( needle > straw )
+            l = m + 1;
+          else
+            return m;
+        }
+        break;
+      }
+
+    case COVERAGE_TABLE_FORMAT_RANGE:
+      {
+        FT_UShort  range_count = FT_PEEK_USHORT( coverage_table + 2 );
+        FT_Byte   *range_array = coverage_table + 4;
+
+        FT_Int  l = 0;
+        FT_Int  r = range_count - 1;
+        FT_Int  m;
+
+        FT_Int  straw_start;
+        FT_Int  straw_end;
+        FT_Int  needle = glyph;
+
+
+        /* Binary search. */
+        while ( l <= r )
+        {
+          FT_Byte  *range_record;
+
+
+          m            = ( l + r ) >> 1;
+          range_record = range_array + 6 * m;
+          straw_start  = FT_PEEK_USHORT( range_record );
+          straw_end    = FT_PEEK_USHORT( range_record + 2 );
+
+          if ( needle < straw_start )
+            r = m - 1;
+          else if ( needle > straw_end )
+            l = m + 1;
+          else
+          {
+            FT_UShort start_coverage_index =
+                        FT_PEEK_USHORT( range_record + 4 );
+
+
+            return start_coverage_index + glyph - straw_start;
+          }
+        }
+        break;
+      }
+
+    default:
+      return -1;  /* unsupported */
+    }
+
+    return -1;
+  }
+
+
+  static FT_Int
+  tt_gpos_get_glyph_class( FT_Byte  *class_def_table,
+                           FT_UInt   glyph )
+  {
+    class_def_table_format_type  class_def_format =
+      (class_def_table_format_type)FT_PEEK_USHORT( class_def_table );
+
+
+    switch ( class_def_format )
+    {
+    case CLASS_DEF_TABLE_FORMAT_ARRAY:
+      {
+        FT_UInt  start_glyph_id    = FT_PEEK_USHORT( class_def_table + 2 );
+        FT_UInt  glyph_count       = FT_PEEK_USHORT( class_def_table + 4 );
+        FT_Byte  *class_value_array = class_def_table + 6;
+
+
+        if ( glyph >= start_glyph_id              &&
+             glyph < start_glyph_id + glyph_count )
+          return (FT_Int)FT_PEEK_USHORT( class_value_array +
+                                         2 * ( glyph - start_glyph_id ) );
+        break;
+      }
+
+    case CLASS_DEF_TABLE_FORMAT_RANGE_GROUPS:
+      {
+        FT_UShort  class_range_count   = FT_PEEK_USHORT( class_def_table + 2 );
+        FT_Byte   *class_range_records = class_def_table + 4;
+
+        FT_Int  l = 0;
+        FT_Int  r = class_range_count - 1;
+        FT_Int  m;
+
+        FT_Int  straw_start;
+        FT_Int  straw_end;
+        FT_Int  needle = glyph;
+
+
+        while ( l <= r )
+        {
+          FT_Byte *class_range_record;
+
+
+          m                  = ( l + r ) >> 1;
+          class_range_record = class_range_records + 6 * m;
+          straw_start        = FT_PEEK_USHORT( class_range_record );
+          straw_end          = FT_PEEK_USHORT( class_range_record + 2 );
+
+          if ( needle < straw_start )
+            r = m - 1;
+          else if ( needle > straw_end )
+            l = m + 1;
+          else
+            return (FT_Int)FT_PEEK_USHORT( class_range_record + 4 );
+        }
+        break;
+      }
+
+    default:
+      return -1;  /* Unsupported definition type, return an error. */
+    }
+
+    /* "All glyphs not assigned to a class fall into class 0." */
+    /* (OpenType spec)                                         */
+    return 0;
+  }
+
+
+  FT_LOCAL_DEF( FT_Error )
+  tt_face_load_gpos( TT_Face    face,
+                     FT_Stream  stream )
+  {
+    FT_Error  error;
+    FT_ULong  table_size;
+
+
+    /* The GPOS table is optional; exit silently if it is missing. */
+    error = face->goto_table( face, TTAG_GPOS, stream, &table_size );
+    if ( error )
+      goto Exit;
+
+    if ( table_size < 4 )  /* the case of a malformed table */
+    {
+      FT_ERROR(( "tt_face_load_gpos:"
+                 " GPOS table is too small - ignored\n" ));
+      error = FT_THROW( Table_Missing );
+      goto Exit;
+    }
+
+    if ( FT_FRAME_EXTRACT( table_size, face->gpos_table ) )
+    {
+      FT_ERROR(( "tt_face_load_gpos:"
+                 " could not extract GPOS table\n" ));
+      goto Exit;
+    }
+
+    face->gpos_kerning_available = FALSE;
+
+    if ( face->gpos_table )
+    {
+      FT_Byte*   feature_list    = face->gpos_table +
+                                   FT_PEEK_USHORT( face->gpos_table + 6 );
+      FT_UInt16  feature_count   = FT_PEEK_USHORT( feature_list );
+      FT_Byte*   feature_records = feature_list + 2;
+
+      FT_UInt  idx;
+
+
+      for ( idx = 0; idx < feature_count; idx++, feature_records += 6 )
+      {
+        FT_ULong  feature_tag = FT_PEEK_ULONG( feature_records );
+
+
+        if ( feature_tag == TTAG_kern )
+        {
+          face->gpos_kerning_available = TRUE;
+          break;
+        }
+      }
+    }
+
+  Exit:
+    return error;
+  }
+
+
+  FT_LOCAL_DEF( void )
+  tt_face_done_gpos( TT_Face  face )
+  {
+    FT_Stream  stream = face->root.stream;
+
+
+    FT_FRAME_RELEASE( face->gpos_table );
+  }
+
+
+  FT_LOCAL_DEF( FT_Int )
+  tt_face_get_gpos_kerning( TT_Face  face,
+                            FT_UInt  left_glyph,
+                            FT_UInt  right_glyph )
+  {
+    FT_Byte*   feature_list;
+    FT_UInt16  feature_count;
+    FT_Byte*   feature_records;
+    FT_UInt    feature_idx;
+
+
+    if ( !face->gpos_kerning_available )
+      return 0;
+
+    feature_list    = face->gpos_table +
+                      FT_PEEK_USHORT( face->gpos_table + 6 );
+    feature_count   = FT_PEEK_USHORT( feature_list );
+    feature_records = feature_list + 2;
+
+    for ( feature_idx = 0;
+          feature_idx < feature_count;
+          feature_idx++, feature_records += 6 )
+    {
+      FT_ULong   feature_tag = FT_PEEK_ULONG( feature_records );
+      FT_Byte*   feature_table;
+      FT_UInt16  lookup_idx_count;
+      FT_UInt16  lookup_idx;
+
+
+      if ( feature_tag != TTAG_kern )
+        continue;
+
+      feature_table    = feature_list + FT_PEEK_USHORT( feature_records + 4 );
+      lookup_idx_count = FT_PEEK_USHORT( feature_table + 2 );
+
+      for ( lookup_idx = 0; lookup_idx < lookup_idx_count; lookup_idx++ )
+      {
+        FT_UInt16 lookup_list_idx =
+          FT_PEEK_USHORT( feature_table + 4 + 2 * lookup_idx );
+        TT_GPOS_Subtable_Iterator_Context  subtable_iter;
+
+
+        tt_gpos_subtable_iterator_init( &subtable_iter,
+                                        face->gpos_table,
+                                        lookup_list_idx );
+
+        while ( tt_gpos_subtable_iterator_next( &subtable_iter ) )
+        {
+          FT_Byte*  subtable;
+
+          gpos_value_format_bitmask    value_format_1;
+          gpos_value_format_bitmask    value_format_2;
+          gpos_pair_adjustment_format  format;
+
+          FT_UShort  coverage_offset;
+          FT_Int     coverage_index;
+
+
+          if ( subtable_iter.subtable_type !=
+               GPOS_LOOKUP_TYPE_PAIR_ADJUSTMENT )
+            continue;
+
+          subtable = subtable_iter.subtable;
+
+          value_format_1 =
+            (gpos_value_format_bitmask)FT_PEEK_USHORT( subtable + 4 );
+          value_format_2 =
+            (gpos_value_format_bitmask)FT_PEEK_USHORT( subtable + 6 );
+
+          if ( !( value_format_1 == GPOS_VALUE_FORMAT_X_ADVANCE &&
+                  value_format_2 == GPOS_VALUE_FORMAT_NONE      ) )
+            continue;
+
+          format = (gpos_pair_adjustment_format)FT_PEEK_USHORT( subtable );
+
+          coverage_offset = FT_PEEK_USHORT( subtable + 2 );
+          coverage_index  =
+            tt_gpos_get_coverage_index( subtable + coverage_offset,
+                                        left_glyph );
+
+          if ( coverage_index == -1 )
+            continue;
+
+          switch ( format )
+          {
+          case GPOS_PAIR_ADJUSTMENT_FORMAT_GLYPH_PAIR:
+            {
+              FT_Int  l, r, m;
+              FT_Int  straw, needle;
+
+              FT_Int  value_record_pair_size_in_bytes = 2;
+
+              FT_UShort  pair_set_count = FT_PEEK_USHORT( subtable + 8 );
+              FT_UShort  pair_pos_offset;
+
+              FT_Byte*   pair_value_table;
+              FT_UShort  pair_value_count;
+              FT_Byte*   pair_value_array;
+
+
+              if ( coverage_index >= pair_set_count )
+                return 0;
+
+              pair_pos_offset =
+                FT_PEEK_USHORT( subtable + 10 + 2 * coverage_index );
+
+              pair_value_table = subtable + pair_pos_offset;
+              pair_value_count = FT_PEEK_USHORT( pair_value_table );
+              pair_value_array = pair_value_table + 2;
+
+              needle = right_glyph;
+              r      = pair_value_count - 1;
+              l      = 0;
+
+              /* Binary search. */
+              while ( l <= r )
+              {
+                FT_UShort  second_glyph;
+                FT_Byte*   pair_value;
+
+
+                m            = ( l + r ) >> 1;
+                pair_value   = pair_value_array +
+                               ( 2 + value_record_pair_size_in_bytes ) * m;
+                second_glyph = FT_PEEK_USHORT( pair_value );
+                straw        = second_glyph;
+
+                if ( needle < straw )
+                  r = m - 1;
+                else if ( needle > straw )
+                  l = m + 1;
+                else
+                {
+                  FT_Short  x_advance = FT_PEEK_SHORT( pair_value + 2 );
+
+
+                  return x_advance;
+                }
+              }
+              break;
+            }
+
+          case GPOS_PAIR_ADJUSTMENT_FORMAT_CLASS_PAIR:
+            {
+              FT_UShort  class_def1_offset = FT_PEEK_USHORT( subtable + 8 );
+              FT_UShort  class_def2_offset = FT_PEEK_USHORT( subtable + 10 );
+
+              FT_Int  left_glyph_class =
+                tt_gpos_get_glyph_class( subtable + class_def1_offset,
+                                         left_glyph );
+              FT_Int  right_glyph_class =
+                tt_gpos_get_glyph_class( subtable + class_def2_offset,
+                                         right_glyph );
+
+              FT_UShort class1_count = FT_PEEK_USHORT( subtable + 12 );
+              FT_UShort class2_count = FT_PEEK_USHORT( subtable + 14 );
+
+              FT_Byte *class1_records, *class2_records;
+              FT_Short x_advance;
+
+
+              if ( left_glyph_class < 0             ||
+                   left_glyph_class >= class1_count )
+                return 0;  /* malformed */
+              if ( right_glyph_class < 0             ||
+                   right_glyph_class >= class2_count )
+                return 0;  /* malformed */
+
+              if ( right_glyph_class == 0 )
+                continue; /* right glyph not found in this table */
+
+              class1_records = subtable + 16;
+              class2_records =
+                class1_records + 2 * ( left_glyph_class * class2_count );
+
+              x_advance =
+                FT_PEEK_SHORT( class2_records + 2 * right_glyph_class );
+
+              return x_advance;
+            }
+
+          default:
+            return 0;
+          }
+        }
+      }
+    }
+
+    return 0;
+  }
+
+#else /* !TT_CONFIG_OPTION_GPOS_KERNING */
+
+  /* ANSI C doesn't like empty source files */
+  typedef int  tt_gpos_dummy_;
+
+#endif /* !TT_CONFIG_OPTION_GPOS_KERNING */
+
+
+/* END */
diff --git a/vendor/freetype/src/sfnt/ttgpos.h b/vendor/freetype/src/sfnt/ttgpos.h
new file mode 100644
index 0000000000..570e9e3d75
--- /dev/null
+++ b/vendor/freetype/src/sfnt/ttgpos.h
@@ -0,0 +1,53 @@
+/****************************************************************************
+ *
+ * ttgpos.c
+ *
+ *   Load the TrueType GPOS table.  The only GPOS layout feature this
+ *   currently supports is kerning, from x advances in the pair adjustment
+ *   layout feature.
+ *
+ * Copyright (C) 2024 by
+ * David Saltzman
+ *
+ * This file is part of the FreeType project, and may only be used,
+ * modified, and distributed under the terms of the FreeType project
+ * license, LICENSE.TXT.  By continuing to use, modify, or distribute
+ * this file you indicate that you have read the license and
+ * understand and accept it fully.
+ */
+
+
+#ifndef TTGPOS_H_
+#define TTGPOS_H_
+
+
+#include 
+#include 
+
+
+FT_BEGIN_HEADER
+
+
+#ifdef TT_CONFIG_OPTION_GPOS_KERNING
+
+  FT_LOCAL( FT_Error  )
+  tt_face_load_gpos( TT_Face    face,
+                     FT_Stream  stream );
+
+  FT_LOCAL( void )
+  tt_face_done_gpos( TT_Face  face );
+
+  FT_LOCAL( FT_Int )
+  tt_face_get_gpos_kerning( TT_Face  face,
+                            FT_UInt  left_glyph,
+                            FT_UInt  right_glyph );
+
+#endif /* TT_CONFIG_OPTION_GPOS_KERNING */
+
+
+FT_END_HEADER
+
+#endif /* TTGPOS_H_ */
+
+
+/* END */
diff --git a/vendor/freetype/src/sfnt/ttkern.c b/vendor/freetype/src/sfnt/ttkern.c
index a47d08bd6d..f0411366af 100644
--- a/vendor/freetype/src/sfnt/ttkern.c
+++ b/vendor/freetype/src/sfnt/ttkern.c
@@ -5,7 +5,7 @@
  *   Load the basic TrueType kerning table.  This doesn't handle
  *   kerning data within the GPOS table at the moment.
  *
- * Copyright (C) 1996-2023 by
+ * Copyright (C) 1996-2024 by
  * David Turner, Robert Wilhelm, and Werner Lemberg.
  *
  * This file is part of the FreeType project, and may only be used,
diff --git a/vendor/freetype/src/sfnt/ttkern.h b/vendor/freetype/src/sfnt/ttkern.h
index 960c7da494..a54e51df12 100644
--- a/vendor/freetype/src/sfnt/ttkern.h
+++ b/vendor/freetype/src/sfnt/ttkern.h
@@ -5,7 +5,7 @@
  *   Load the basic TrueType kerning table.  This doesn't handle
  *   kerning data within the GPOS table at the moment.
  *
- * Copyright (C) 1996-2023 by
+ * Copyright (C) 1996-2024 by
  * David Turner, Robert Wilhelm, and Werner Lemberg.
  *
  * This file is part of the FreeType project, and may only be used,
diff --git a/vendor/freetype/src/sfnt/ttload.c b/vendor/freetype/src/sfnt/ttload.c
index 7b44e9cd2e..fe4d51559c 100644
--- a/vendor/freetype/src/sfnt/ttload.c
+++ b/vendor/freetype/src/sfnt/ttload.c
@@ -5,7 +5,7 @@
  *   Load the basic TrueType tables, i.e., tables that can be either in
  *   TTF or OTF fonts (body).
  *
- * Copyright (C) 1996-2023 by
+ * Copyright (C) 1996-2024 by
  * David Turner, Robert Wilhelm, and Werner Lemberg.
  *
  * This file is part of the FreeType project, and may only be used,
diff --git a/vendor/freetype/src/sfnt/ttload.h b/vendor/freetype/src/sfnt/ttload.h
index 1499dd5735..2b1d62d9bd 100644
--- a/vendor/freetype/src/sfnt/ttload.h
+++ b/vendor/freetype/src/sfnt/ttload.h
@@ -5,7 +5,7 @@
  *   Load the basic TrueType tables, i.e., tables that can be either in
  *   TTF or OTF fonts (specification).
  *
- * Copyright (C) 1996-2023 by
+ * Copyright (C) 1996-2024 by
  * David Turner, Robert Wilhelm, and Werner Lemberg.
  *
  * This file is part of the FreeType project, and may only be used,
diff --git a/vendor/freetype/src/sfnt/ttmtx.c b/vendor/freetype/src/sfnt/ttmtx.c
index 38ee9ae728..2788411856 100644
--- a/vendor/freetype/src/sfnt/ttmtx.c
+++ b/vendor/freetype/src/sfnt/ttmtx.c
@@ -4,7 +4,7 @@
  *
  *   Load the metrics tables common to TTF and OTF fonts (body).
  *
- * Copyright (C) 2006-2023 by
+ * Copyright (C) 2006-2024 by
  * David Turner, Robert Wilhelm, and Werner Lemberg.
  *
  * This file is part of the FreeType project, and may only be used,
diff --git a/vendor/freetype/src/sfnt/ttmtx.h b/vendor/freetype/src/sfnt/ttmtx.h
index 56d2b62766..34b3c0e18f 100644
--- a/vendor/freetype/src/sfnt/ttmtx.h
+++ b/vendor/freetype/src/sfnt/ttmtx.h
@@ -4,7 +4,7 @@
  *
  *   Load the metrics tables common to TTF and OTF fonts (specification).
  *
- * Copyright (C) 2006-2023 by
+ * Copyright (C) 2006-2024 by
  * David Turner, Robert Wilhelm, and Werner Lemberg.
  *
  * This file is part of the FreeType project, and may only be used,
diff --git a/vendor/freetype/src/sfnt/ttpost.c b/vendor/freetype/src/sfnt/ttpost.c
index 1dfad4298b..a90237ad03 100644
--- a/vendor/freetype/src/sfnt/ttpost.c
+++ b/vendor/freetype/src/sfnt/ttpost.c
@@ -5,7 +5,7 @@
  *   PostScript name table processing for TrueType and OpenType fonts
  *   (body).
  *
- * Copyright (C) 1996-2023 by
+ * Copyright (C) 1996-2024 by
  * David Turner, Robert Wilhelm, and Werner Lemberg.
  *
  * This file is part of the FreeType project, and may only be used,
@@ -204,8 +204,8 @@
     /* now load the name strings */
     if ( num_names )
     {
-      FT_ULong   p;
-      FT_Byte*   strings;
+      FT_Byte*   p;
+      FT_Byte*   p_end;
 
 
       post_len -= (FT_ULong)num_glyphs * 2;
@@ -214,27 +214,27 @@
                                     post_len + 1 ) )
         goto Fail;
 
-      strings = (FT_Byte*)( name_strings + num_names );
-      if ( FT_STREAM_READ( strings, post_len ) )
+      p = (FT_Byte*)( name_strings + num_names );
+      if ( FT_STREAM_READ( p, post_len ) )
         goto Fail;
 
+      p_end = p + post_len;
+
       /* convert from Pascal- to C-strings and set pointers */
-      for ( p = 0, n = 0; p < post_len && n < num_names; n++ )
+      for ( n = 0; p < p_end && n < num_names; n++ )
       {
-        FT_UInt  len = strings[p];
+        FT_UInt  len = *p;
 
 
-        if ( len > 63U )
-        {
-          error = FT_THROW( Invalid_File_Format );
-          goto Fail;
-        }
+        /* all names in Adobe Glyph List are shorter than 40 characters */
+        if ( len >= 40U )
+          FT_TRACE4(( "load_format_20: unusual %u-char name found\n", len ));
 
-        strings[p]      = 0;
-        name_strings[n] = strings + p + 1;
-        p              += len + 1;
+        *p++            = 0;
+        name_strings[n] = p;
+        p              += len;
       }
-      strings[post_len] = 0;
+      *p_end = 0;
 
       /* deal with missing or insufficient string data */
       if ( n < num_names )
@@ -243,7 +243,7 @@
                     num_names - n ));
 
         for ( ; n < num_names; n++ )
-          name_strings[n] = strings + post_len;
+          name_strings[n] = p_end;
       }
     }
 
@@ -436,13 +436,8 @@
 
     format = face->postscript.FormatType;
 
-    if ( format == 0x00010000L )
-    {
-      if ( idx < 258 )                    /* paranoid checking */
-        *PSname = MAC_NAME( idx );
-    }
-    else if ( format == 0x00020000L ||
-              format == 0x00025000L )
+    if ( format == 0x00020000L ||
+         format == 0x00025000L )
     {
       TT_Post_Names  names = &face->postscript_names;
 
@@ -466,6 +461,11 @@
       }
     }
 
+    /* version 1.0 is only valid with 258 glyphs */
+    else if ( format == 0x00010000L              &&
+              face->max_profile.numGlyphs == 258 )
+      *PSname = MAC_NAME( idx );
+
     /* nothing to do for format == 0x00030000L */
 
   End:
diff --git a/vendor/freetype/src/sfnt/ttpost.h b/vendor/freetype/src/sfnt/ttpost.h
index 528f1c5f2f..150db6c398 100644
--- a/vendor/freetype/src/sfnt/ttpost.h
+++ b/vendor/freetype/src/sfnt/ttpost.h
@@ -5,7 +5,7 @@
  *   PostScript name table processing for TrueType and OpenType fonts
  *   (specification).
  *
- * Copyright (C) 1996-2023 by
+ * Copyright (C) 1996-2024 by
  * David Turner, Robert Wilhelm, and Werner Lemberg.
  *
  * This file is part of the FreeType project, and may only be used,
diff --git a/vendor/freetype/src/sfnt/ttsbit.c b/vendor/freetype/src/sfnt/ttsbit.c
index 03f90a628d..cb3a8abf18 100644
--- a/vendor/freetype/src/sfnt/ttsbit.c
+++ b/vendor/freetype/src/sfnt/ttsbit.c
@@ -4,7 +4,7 @@
  *
  *   TrueType and OpenType embedded bitmap support (body).
  *
- * Copyright (C) 2005-2023 by
+ * Copyright (C) 2005-2024 by
  * David Turner, Robert Wilhelm, and Werner Lemberg.
  *
  * Copyright 2013 by Google, Inc.
diff --git a/vendor/freetype/src/sfnt/ttsbit.h b/vendor/freetype/src/sfnt/ttsbit.h
index 07e2db461a..96f80a5842 100644
--- a/vendor/freetype/src/sfnt/ttsbit.h
+++ b/vendor/freetype/src/sfnt/ttsbit.h
@@ -4,7 +4,7 @@
  *
  *   TrueType and OpenType embedded bitmap support (specification).
  *
- * Copyright (C) 1996-2023 by
+ * Copyright (C) 1996-2024 by
  * David Turner, Robert Wilhelm, and Werner Lemberg.
  *
  * This file is part of the FreeType project, and may only be used,
diff --git a/vendor/freetype/src/sfnt/ttsvg.c b/vendor/freetype/src/sfnt/ttsvg.c
index 4461d483b0..298afd8b55 100644
--- a/vendor/freetype/src/sfnt/ttsvg.c
+++ b/vendor/freetype/src/sfnt/ttsvg.c
@@ -4,7 +4,7 @@
  *
  *   OpenType SVG Color (specification).
  *
- * Copyright (C) 2022-2023 by
+ * Copyright (C) 2022-2024 by
  * David Turner, Robert Wilhelm, Werner Lemberg, and Moazin Khatti.
  *
  * This file is part of the FreeType project, and may only be used,
diff --git a/vendor/freetype/src/sfnt/ttsvg.h b/vendor/freetype/src/sfnt/ttsvg.h
index 3f32321ded..20f9e47c99 100644
--- a/vendor/freetype/src/sfnt/ttsvg.h
+++ b/vendor/freetype/src/sfnt/ttsvg.h
@@ -4,7 +4,7 @@
  *
  *   OpenType SVG Color (specification).
  *
- * Copyright (C) 2022-2023 by
+ * Copyright (C) 2022-2024 by
  * David Turner, Robert Wilhelm, Werner Lemberg, and Moazin Khatti.
  *
  * This file is part of the FreeType project, and may only be used,
diff --git a/vendor/freetype/src/sfnt/woff2tags.c b/vendor/freetype/src/sfnt/woff2tags.c
index eeedd9906b..532ccfa173 100644
--- a/vendor/freetype/src/sfnt/woff2tags.c
+++ b/vendor/freetype/src/sfnt/woff2tags.c
@@ -4,7 +4,7 @@
  *
  *   WOFF2 Font table tags (base).
  *
- * Copyright (C) 2019-2023 by
+ * Copyright (C) 2019-2024 by
  * Nikhil Ramakrishnan, David Turner, Robert Wilhelm, and Werner Lemberg.
  *
  * This file is part of the FreeType project, and may only be used,
diff --git a/vendor/freetype/src/sfnt/woff2tags.h b/vendor/freetype/src/sfnt/woff2tags.h
index 1201848e5e..d03b4b41bc 100644
--- a/vendor/freetype/src/sfnt/woff2tags.h
+++ b/vendor/freetype/src/sfnt/woff2tags.h
@@ -4,7 +4,7 @@
  *
  *   WOFF2 Font table tags (specification).
  *
- * Copyright (C) 2019-2023 by
+ * Copyright (C) 2019-2024 by
  * Nikhil Ramakrishnan, David Turner, Robert Wilhelm, and Werner Lemberg.
  *
  * This file is part of the FreeType project, and may only be used,
diff --git a/vendor/freetype/src/smooth/ftgrays.c b/vendor/freetype/src/smooth/ftgrays.c
index 0918272f87..b7c0632a6f 100644
--- a/vendor/freetype/src/smooth/ftgrays.c
+++ b/vendor/freetype/src/smooth/ftgrays.c
@@ -4,7 +4,7 @@
  *
  *   A new `perfect' anti-aliasing renderer (body).
  *
- * Copyright (C) 2000-2023 by
+ * Copyright (C) 2000-2024 by
  * David Turner, Robert Wilhelm, and Werner Lemberg.
  *
  * This file is part of the FreeType project, and may only be used,
@@ -489,7 +489,7 @@ typedef ptrdiff_t  FT_PtrDist;
 
   typedef struct  gray_TWorker_
   {
-    ft_jmp_buf  jump_buffer;
+    FT_BBox     cbox;
 
     TCoord  min_ex, max_ex;  /* min and max integer pixel coordinates */
     TCoord  min_ey, max_ey;
@@ -510,6 +510,8 @@ typedef ptrdiff_t  FT_PtrDist;
     FT_Raster_Span_Func  render_span;
     void*                render_span_data;
 
+    ft_jmp_buf  jump_buffer;
+
   } gray_TWorker, *gray_PWorker;
 
 #if defined( _MSC_VER )
@@ -997,49 +999,12 @@ typedef ptrdiff_t  FT_PtrDist;
 #endif
 
   /*
-   * Benchmarking shows that using DDA to flatten the quadratic Bézier arcs
-   * is slightly faster in the following cases:
-   *
-   *   - When the host CPU is 64-bit.
-   *   - When SSE2 SIMD registers and instructions are available (even on
-   *     x86).
-   *
-   * For other cases, using binary splits is actually slightly faster.
-   */
-#if ( defined( __SSE2__ )                          ||   \
-      defined( __x86_64__ )                        ||   \
-      defined( _M_AMD64 )                          ||   \
-      ( defined( _M_IX86_FP ) && _M_IX86_FP >= 2 ) ) && \
-    !defined( __VMS )
-#  define FT_SSE2 1
-#else
-#  define FT_SSE2 0
-#endif
-
-#if FT_SSE2                || \
-    defined( __aarch64__ ) || \
-    defined( _M_ARM64 )
-#  define BEZIER_USE_DDA  1
-#else
-#  define BEZIER_USE_DDA  0
-#endif
-
-  /*
-   * For now, the code that depends on `BEZIER_USE_DDA` requires `FT_Int64`
-   * to be defined.  If `FT_INT64` is not defined, meaning there is no
-   * 64-bit type available, disable it to avoid compilation errors.  See for
-   * example https://gitlab.freedesktop.org/freetype/freetype/-/issues/1071.
+   * For now, the code that uses DDA to render conic curves requires
+   * `FT_Int64` to be defined.  See for example
+   *    https://gitlab.freedesktop.org/freetype/freetype/-/issues/1071.
    */
-#if !defined( FT_INT64 )
-#  undef BEZIER_USE_DDA
-#  define BEZIER_USE_DDA  0
-#endif
-
-#if BEZIER_USE_DDA
 
-#if FT_SSE2
-#  include 
-#endif
+#ifdef FT_INT64
 
 #define LEFT_SHIFT( a, b )  (FT_Int64)( (FT_UInt64)(a) << (b) )
 
@@ -1095,16 +1060,17 @@ typedef ptrdiff_t  FT_PtrDist;
       return;
     }
 
-    /* We can calculate the number of necessary bisections because  */
+    /* We can calculate the number of necessary segments because    */
     /* each bisection predictably reduces deviation exactly 4-fold. */
     /* Even 32-bit deviation would vanish after 16 bisections.      */
-    shift = 0;
+    shift = 16;
     do
     {
-      dx   >>= 2;
-      shift += 1;
+      dx >>= 2;
+      shift--;
 
     } while ( dx > ONE_PIXEL / 4 );
+    count = 0x10000U >> shift;
 
     /*
      * The (P0,P1,P2) arc equation, for t in [0,1] range:
@@ -1150,75 +1116,19 @@ typedef ptrdiff_t  FT_PtrDist;
      *             = (B << (33 - N)) + (A << (32 - 2*N))
      */
 
-#if FT_SSE2
-    /* Experience shows that for small shift values, */
-    /* SSE2 is actually slower.                      */
-    if ( shift > 2 )
-    {
-      union
-      {
-        struct { FT_Int64  ax, ay, bx, by; }  i;
-        struct { __m128i  a, b; }  vec;
-
-      } u;
-
-      union
-      {
-        struct { FT_Int32  px_lo, px_hi, py_lo, py_hi; }  i;
-        __m128i  vec;
-
-      } v;
-
-      __m128i  a, b;
-      __m128i  r, q, q2;
-      __m128i  p;
-
-
-      u.i.ax = ax;
-      u.i.ay = ay;
-      u.i.bx = bx;
-      u.i.by = by;
-
-      a = _mm_load_si128( &u.vec.a );
-      b = _mm_load_si128( &u.vec.b );
-
-      r  = _mm_slli_epi64( a, 33 - 2 * shift );
-      q  = _mm_slli_epi64( b, 33 - shift );
-      q2 = _mm_slli_epi64( a, 32 - 2 * shift );
-
-      q = _mm_add_epi64( q2, q );
-
-      v.i.px_lo = 0;
-      v.i.px_hi = p0.x;
-      v.i.py_lo = 0;
-      v.i.py_hi = p0.y;
-
-      p = _mm_load_si128( &v.vec );
-
-      for ( count = 1U << shift; count > 0; count-- )
-      {
-        p = _mm_add_epi64( p, q );
-        q = _mm_add_epi64( q, r );
-
-        _mm_store_si128( &v.vec, p );
-
-        gray_render_line( RAS_VAR_ v.i.px_hi, v.i.py_hi );
-      }
-
-      return;
-    }
-#endif  /* FT_SSE2 */
+    rx = LEFT_SHIFT( ax, shift + shift );
+    ry = LEFT_SHIFT( ay, shift + shift );
 
-    rx = LEFT_SHIFT( ax, 33 - 2 * shift );
-    ry = LEFT_SHIFT( ay, 33 - 2 * shift );
+    qx = LEFT_SHIFT( bx, shift + 17 ) + rx;
+    qy = LEFT_SHIFT( by, shift + 17 ) + ry;
 
-    qx = LEFT_SHIFT( bx, 33 - shift ) + LEFT_SHIFT( ax, 32 - 2 * shift );
-    qy = LEFT_SHIFT( by, 33 - shift ) + LEFT_SHIFT( ay, 32 - 2 * shift );
+    rx *= 2;
+    ry *= 2;
 
     px = LEFT_SHIFT( p0.x, 32 );
     py = LEFT_SHIFT( p0.y, 32 );
 
-    for ( count = 1U << shift; count > 0; count-- )
+    do
     {
       px += qx;
       py += qy;
@@ -1227,10 +1137,10 @@ typedef ptrdiff_t  FT_PtrDist;
 
       gray_render_line( RAS_VAR_ (FT_Pos)( px >> 32 ),
                                  (FT_Pos)( py >> 32 ) );
-    }
+    } while ( --count );
   }
 
-#else  /* !BEZIER_USE_DDA */
+#else  /* !FT_INT64 */
 
   /*
    * Note that multiple attempts to speed up the function below
@@ -1324,7 +1234,7 @@ typedef ptrdiff_t  FT_PtrDist;
     } while ( --draw );
   }
 
-#endif  /* !BEZIER_USE_DDA */
+#endif  /* !FT_INT64 */
 
 
   /*
@@ -1486,139 +1396,6 @@ typedef ptrdiff_t  FT_PtrDist;
   }
 
 
-  static void
-  gray_sweep( RAS_ARG )
-  {
-    int  fill = ( ras.outline.flags & FT_OUTLINE_EVEN_ODD_FILL ) ? 0x100
-                                                                 : INT_MIN;
-    int  coverage;
-    int  y;
-
-
-    for ( y = ras.min_ey; y < ras.max_ey; y++ )
-    {
-      PCell   cell  = ras.ycells[y - ras.min_ey];
-      TCoord  x     = ras.min_ex;
-      TArea   cover = 0;
-
-      unsigned char*  line = ras.target.origin - ras.target.pitch * y;
-
-
-      for ( ; cell != ras.cell_null; cell = cell->next )
-      {
-        TArea  area;
-
-
-        if ( cover != 0 && cell->x > x )
-        {
-          FT_FILL_RULE( coverage, cover, fill );
-          FT_GRAY_SET( line + x, coverage, cell->x - x );
-        }
-
-        cover += (TArea)cell->cover * ( ONE_PIXEL * 2 );
-        area   = cover - cell->area;
-
-        if ( area != 0 && cell->x >= ras.min_ex )
-        {
-          FT_FILL_RULE( coverage, area, fill );
-          line[cell->x] = (unsigned char)coverage;
-        }
-
-        x = cell->x + 1;
-      }
-
-      if ( cover != 0 )  /* only if cropped */
-      {
-        FT_FILL_RULE( coverage, cover, fill );
-        FT_GRAY_SET( line + x, coverage, ras.max_ex - x );
-      }
-    }
-  }
-
-
-  static void
-  gray_sweep_direct( RAS_ARG )
-  {
-    int  fill = ( ras.outline.flags & FT_OUTLINE_EVEN_ODD_FILL ) ? 0x100
-                                                                 : INT_MIN;
-    int  coverage;
-    int  y;
-
-    FT_Span  span[FT_MAX_GRAY_SPANS];
-    int      n = 0;
-
-
-    for ( y = ras.min_ey; y < ras.max_ey; y++ )
-    {
-      PCell   cell  = ras.ycells[y - ras.min_ey];
-      TCoord  x     = ras.min_ex;
-      TArea   cover = 0;
-
-
-      for ( ; cell != ras.cell_null; cell = cell->next )
-      {
-        TArea  area;
-
-
-        if ( cover != 0 && cell->x > x )
-        {
-          FT_FILL_RULE( coverage, cover, fill );
-
-          span[n].coverage = (unsigned char)coverage;
-          span[n].x        = (short)x;
-          span[n].len      = (unsigned short)( cell->x - x );
-
-          if ( ++n == FT_MAX_GRAY_SPANS )
-          {
-            /* flush the span buffer and reset the count */
-            ras.render_span( y, n, span, ras.render_span_data );
-            n = 0;
-          }
-        }
-
-        cover += (TArea)cell->cover * ( ONE_PIXEL * 2 );
-        area   = cover - cell->area;
-
-        if ( area != 0 && cell->x >= ras.min_ex )
-        {
-          FT_FILL_RULE( coverage, area, fill );
-
-          span[n].coverage = (unsigned char)coverage;
-          span[n].x        = (short)cell->x;
-          span[n].len      = 1;
-
-          if ( ++n == FT_MAX_GRAY_SPANS )
-          {
-            /* flush the span buffer and reset the count */
-            ras.render_span( y, n, span, ras.render_span_data );
-            n = 0;
-          }
-        }
-
-        x = cell->x + 1;
-      }
-
-      if ( cover != 0 )  /* only if cropped */
-      {
-        FT_FILL_RULE( coverage, cover, fill );
-
-        span[n].coverage = (unsigned char)coverage;
-        span[n].x        = (short)x;
-        span[n].len      = (unsigned short)( ras.max_ex - x );
-
-        ++n;
-      }
-
-      if ( n )
-      {
-        /* flush the span buffer and reset the count */
-        ras.render_span( y, n, span, ras.render_span_data );
-        n = 0;
-      }
-    }
-  }
-
-
 #ifdef STANDALONE_
 
   /**************************************************************************
@@ -1934,7 +1711,7 @@ typedef ptrdiff_t  FT_PtrDist;
       if ( continued )
         FT_Trace_Enable();
 
-      FT_TRACE7(( "band [%d..%d]: %td cell%s remaining/\n",
+      FT_TRACE7(( "band [%d..%d]: %td cell%s remaining\n",
                   ras.min_ey,
                   ras.max_ey,
                   ras.cell_null - ras.cell_free,
@@ -1952,14 +1729,144 @@ typedef ptrdiff_t  FT_PtrDist;
   }
 
 
+  static void
+  gray_sweep( RAS_ARG )
+  {
+    int  fill = ( ras.outline.flags & FT_OUTLINE_EVEN_ODD_FILL ) ? 0x100
+                                                                 : INT_MIN;
+    int  coverage;
+    int  y;
+
+
+    for ( y = ras.min_ey; y < ras.max_ey; y++ )
+    {
+      PCell   cell  = ras.ycells[y - ras.min_ey];
+      TCoord  x     = ras.min_ex;
+      TArea   cover = 0;
+
+      unsigned char*  line = ras.target.origin - ras.target.pitch * y;
+
+
+      for ( ; cell != ras.cell_null; cell = cell->next )
+      {
+        TArea  area;
+
+
+        if ( cover != 0 && cell->x > x )
+        {
+          FT_FILL_RULE( coverage, cover, fill );
+          FT_GRAY_SET( line + x, coverage, cell->x - x );
+        }
+
+        cover += (TArea)cell->cover * ( ONE_PIXEL * 2 );
+        area   = cover - cell->area;
+
+        if ( area != 0 && cell->x >= ras.min_ex )
+        {
+          FT_FILL_RULE( coverage, area, fill );
+          line[cell->x] = (unsigned char)coverage;
+        }
+
+        x = cell->x + 1;
+      }
+
+      if ( cover != 0 )  /* only if cropped */
+      {
+        FT_FILL_RULE( coverage, cover, fill );
+        FT_GRAY_SET( line + x, coverage, ras.max_ex - x );
+      }
+    }
+  }
+
+
+  static void
+  gray_sweep_direct( RAS_ARG )
+  {
+    int  fill = ( ras.outline.flags & FT_OUTLINE_EVEN_ODD_FILL ) ? 0x100
+                                                                 : INT_MIN;
+    int  coverage;
+    int  y;
+
+    FT_Span  span[FT_MAX_GRAY_SPANS];
+    int      n = 0;
+
+
+    for ( y = ras.min_ey; y < ras.max_ey; y++ )
+    {
+      PCell   cell  = ras.ycells[y - ras.min_ey];
+      TCoord  x     = ras.min_ex;
+      TArea   cover = 0;
+
+
+      for ( ; cell != ras.cell_null; cell = cell->next )
+      {
+        TArea  area;
+
+
+        if ( cover != 0 && cell->x > x )
+        {
+          FT_FILL_RULE( coverage, cover, fill );
+
+          span[n].coverage = (unsigned char)coverage;
+          span[n].x        = (short)x;
+          span[n].len      = (unsigned short)( cell->x - x );
+
+          if ( ++n == FT_MAX_GRAY_SPANS )
+          {
+            /* flush the span buffer and reset the count */
+            ras.render_span( y, n, span, ras.render_span_data );
+            n = 0;
+          }
+        }
+
+        cover += (TArea)cell->cover * ( ONE_PIXEL * 2 );
+        area   = cover - cell->area;
+
+        if ( area != 0 && cell->x >= ras.min_ex )
+        {
+          FT_FILL_RULE( coverage, area, fill );
+
+          span[n].coverage = (unsigned char)coverage;
+          span[n].x        = (short)cell->x;
+          span[n].len      = 1;
+
+          if ( ++n == FT_MAX_GRAY_SPANS )
+          {
+            /* flush the span buffer and reset the count */
+            ras.render_span( y, n, span, ras.render_span_data );
+            n = 0;
+          }
+        }
+
+        x = cell->x + 1;
+      }
+
+      if ( cover != 0 )  /* only if cropped */
+      {
+        FT_FILL_RULE( coverage, cover, fill );
+
+        span[n].coverage = (unsigned char)coverage;
+        span[n].x        = (short)x;
+        span[n].len      = (unsigned short)( ras.max_ex - x );
+
+        ++n;
+      }
+
+      if ( n )
+      {
+        /* flush the span buffer and reset the count */
+        ras.render_span( y, n, span, ras.render_span_data );
+        n = 0;
+      }
+    }
+  }
+
+
   static int
   gray_convert_glyph( RAS_ARG )
   {
-    const TCoord  yMin = ras.min_ey;
-    const TCoord  yMax = ras.max_ey;
-
     TCell    buffer[FT_MAX_GRAY_POOL];
-    size_t   height = (size_t)( yMax - yMin );
+    size_t   height = (size_t)( ras.cbox.yMax - ras.cbox.yMin );
     size_t   n = FT_MAX_GRAY_POOL / 8;
     TCoord   y;
     TCoord   bands[32];  /* enough to accommodate bisections */
@@ -1985,35 +1892,36 @@ typedef ptrdiff_t  FT_PtrDist;
       height  = ( height + n - 1 ) / n;
     }
 
-    for ( y = yMin; y < yMax; )
+    for ( y = ras.cbox.yMin; y < ras.cbox.yMax; )
     {
       ras.min_ey = y;
       y         += height;
-      ras.max_ey = FT_MIN( y, yMax );
+      ras.max_ey = FT_MIN( y, ras.cbox.yMax );
+
+      ras.count_ey = ras.max_ey - ras.min_ey;
 
       band    = bands;
-      band[1] = ras.min_ey;
-      band[0] = ras.max_ey;
+      band[1] = ras.cbox.xMin;
+      band[0] = ras.cbox.xMax;
 
       do
       {
-        TCoord  width = band[0] - band[1];
-        TCoord  w;
+        TCoord  i;
         int     error;
 
 
-        for ( w = 0; w < width; ++w )
-          ras.ycells[w] = ras.cell_null;
+        ras.min_ex = band[1];
+        ras.max_ex = band[0];
+
+        /* memory management: zero out and skip ycells */
+        for ( i = 0; i < ras.count_ey; ++i )
+          ras.ycells[i] = ras.cell_null;
 
-        /* memory management: skip ycells */
-        n = ( (size_t)width * sizeof ( PCell ) + sizeof ( TCell ) - 1 ) /
-              sizeof ( TCell );
+        n = ( (size_t)ras.count_ey * sizeof ( PCell ) + sizeof ( TCell ) - 1 )
+              / sizeof ( TCell );
 
         ras.cell_free = buffer + n;
         ras.cell      = ras.cell_null;
-        ras.min_ey    = band[1];
-        ras.max_ey    = band[0];
-        ras.count_ey  = width;
 
         error     = gray_convert_glyph_inner( RAS_VAR_ continued );
         continued = 1;
@@ -2031,10 +1939,10 @@ typedef ptrdiff_t  FT_PtrDist;
           return error;
 
         /* render pool overflow; we will reduce the render band by half */
-        width >>= 1;
+        i = ( band[0] - band[1] ) >> 1;
 
         /* this should never happen even with tiny rendering pool */
-        if ( width == 0 )
+        if ( i == 0 )
         {
           FT_TRACE7(( "gray_convert_glyph: rotten glyph\n" ));
           return FT_THROW( Raster_Overflow );
@@ -2042,7 +1950,7 @@ typedef ptrdiff_t  FT_PtrDist;
 
         band++;
         band[1]  = band[0];
-        band[0] += width;
+        band[0] += i;
       } while ( band >= bands );
     }
 
@@ -2073,7 +1981,7 @@ typedef ptrdiff_t  FT_PtrDist;
       return FT_THROW( Invalid_Outline );
 
     /* return immediately if the outline is empty */
-    if ( outline->n_points == 0 || outline->n_contours <= 0 )
+    if ( outline->n_points == 0 || outline->n_contours == 0 )
       return Smooth_Err_Ok;
 
     if ( !outline->contours || !outline->points )
@@ -2093,10 +2001,7 @@ typedef ptrdiff_t  FT_PtrDist;
       ras.render_span      = (FT_Raster_Span_Func)params->gray_spans;
       ras.render_span_data = params->user;
 
-      ras.min_ex = params->clip_box.xMin;
-      ras.min_ey = params->clip_box.yMin;
-      ras.max_ex = params->clip_box.xMax;
-      ras.max_ey = params->clip_box.yMax;
+      ras.cbox = params->clip_box;
     }
     else
     {
@@ -2122,14 +2027,14 @@ typedef ptrdiff_t  FT_PtrDist;
       ras.render_span      = (FT_Raster_Span_Func)NULL;
       ras.render_span_data = NULL;
 
-      ras.min_ex = 0;
-      ras.min_ey = 0;
-      ras.max_ex = (FT_Pos)target_map->width;
-      ras.max_ey = (FT_Pos)target_map->rows;
+      ras.cbox.xMin = 0;
+      ras.cbox.yMin = 0;
+      ras.cbox.xMax = (FT_Pos)target_map->width;
+      ras.cbox.yMax = (FT_Pos)target_map->rows;
     }
 
     /* exit if nothing to do */
-    if ( ras.max_ex <= ras.min_ex || ras.max_ey <= ras.min_ey )
+    if ( ras.cbox.xMin >= ras.cbox.xMax || ras.cbox.yMin >= ras.cbox.yMax )
       return Smooth_Err_Ok;
 
     return gray_convert_glyph( RAS_VAR );
diff --git a/vendor/freetype/src/smooth/ftgrays.h b/vendor/freetype/src/smooth/ftgrays.h
index a5001bf40d..940fbe8c79 100644
--- a/vendor/freetype/src/smooth/ftgrays.h
+++ b/vendor/freetype/src/smooth/ftgrays.h
@@ -4,7 +4,7 @@
  *
  *   FreeType smooth renderer declaration
  *
- * Copyright (C) 1996-2023 by
+ * Copyright (C) 1996-2024 by
  * David Turner, Robert Wilhelm, and Werner Lemberg.
  *
  * This file is part of the FreeType project, and may only be used,
diff --git a/vendor/freetype/src/smooth/ftsmerrs.h b/vendor/freetype/src/smooth/ftsmerrs.h
index f4ac93dc41..6d41fb8e0f 100644
--- a/vendor/freetype/src/smooth/ftsmerrs.h
+++ b/vendor/freetype/src/smooth/ftsmerrs.h
@@ -4,7 +4,7 @@
  *
  *   smooth renderer error codes (specification only).
  *
- * Copyright (C) 2001-2023 by
+ * Copyright (C) 2001-2024 by
  * David Turner, Robert Wilhelm, and Werner Lemberg.
  *
  * This file is part of the FreeType project, and may only be used,
diff --git a/vendor/freetype/src/smooth/ftsmooth.c b/vendor/freetype/src/smooth/ftsmooth.c
index 9b0e8886cb..f0acc1ea4a 100644
--- a/vendor/freetype/src/smooth/ftsmooth.c
+++ b/vendor/freetype/src/smooth/ftsmooth.c
@@ -4,7 +4,7 @@
  *
  *   Anti-aliasing renderer interface (body).
  *
- * Copyright (C) 2000-2023 by
+ * Copyright (C) 2000-2024 by
  * David Turner, Robert Wilhelm, and Werner Lemberg.
  *
  * This file is part of the FreeType project, and may only be used,
diff --git a/vendor/freetype/src/smooth/ftsmooth.h b/vendor/freetype/src/smooth/ftsmooth.h
index f8bdc9938b..d7b61a9e60 100644
--- a/vendor/freetype/src/smooth/ftsmooth.h
+++ b/vendor/freetype/src/smooth/ftsmooth.h
@@ -4,7 +4,7 @@
  *
  *   Anti-aliasing renderer interface (specification).
  *
- * Copyright (C) 1996-2023 by
+ * Copyright (C) 1996-2024 by
  * David Turner, Robert Wilhelm, and Werner Lemberg.
  *
  * This file is part of the FreeType project, and may only be used,
diff --git a/vendor/freetype/src/smooth/smooth.c b/vendor/freetype/src/smooth/smooth.c
index 9a0b824c2a..8c5068180e 100644
--- a/vendor/freetype/src/smooth/smooth.c
+++ b/vendor/freetype/src/smooth/smooth.c
@@ -4,7 +4,7 @@
  *
  *   FreeType anti-aliasing rasterer module component (body only).
  *
- * Copyright (C) 1996-2023 by
+ * Copyright (C) 1996-2024 by
  * David Turner, Robert Wilhelm, and Werner Lemberg.
  *
  * This file is part of the FreeType project, and may only be used,
diff --git a/vendor/freetype/src/svg/ftsvg.c b/vendor/freetype/src/svg/ftsvg.c
index ba237f6380..35788a2d8d 100644
--- a/vendor/freetype/src/svg/ftsvg.c
+++ b/vendor/freetype/src/svg/ftsvg.c
@@ -4,7 +4,7 @@
  *
  *   The FreeType SVG renderer interface (body).
  *
- * Copyright (C) 2022-2023 by
+ * Copyright (C) 2022-2024 by
  * David Turner, Robert Wilhelm, Werner Lemberg, and Moazin Khatti.
  *
  * This file is part of the FreeType project, and may only be used,
diff --git a/vendor/freetype/src/svg/ftsvg.h b/vendor/freetype/src/svg/ftsvg.h
index 9c496caa1a..623c091dc6 100644
--- a/vendor/freetype/src/svg/ftsvg.h
+++ b/vendor/freetype/src/svg/ftsvg.h
@@ -4,7 +4,7 @@
  *
  *   The FreeType SVG renderer interface (specification).
  *
- * Copyright (C) 2022-2023 by
+ * Copyright (C) 2022-2024 by
  * David Turner, Robert Wilhelm, Werner Lemberg, and Moazin Khatti.
  *
  * This file is part of the FreeType project, and may only be used,
diff --git a/vendor/freetype/src/svg/svg.c b/vendor/freetype/src/svg/svg.c
index 373c28ed9a..1f1c04b2f2 100644
--- a/vendor/freetype/src/svg/svg.c
+++ b/vendor/freetype/src/svg/svg.c
@@ -4,7 +4,7 @@
  *
  *   FreeType SVG renderer module component (body only).
  *
- * Copyright (C) 2022-2023 by
+ * Copyright (C) 2022-2024 by
  * David Turner, Robert Wilhelm, Werner Lemberg, and Moazin Khatti.
  *
  * This file is part of the FreeType project, and may only be used,
diff --git a/vendor/freetype/src/svg/svgtypes.h b/vendor/freetype/src/svg/svgtypes.h
index 1d608032cc..f1d6d73c54 100644
--- a/vendor/freetype/src/svg/svgtypes.h
+++ b/vendor/freetype/src/svg/svgtypes.h
@@ -4,7 +4,7 @@
  *
  *   The FreeType SVG renderer internal types (specification).
  *
- * Copyright (C) 2022-2023 by
+ * Copyright (C) 2022-2024 by
  * David Turner, Robert Wilhelm, Werner Lemberg, and Moazin Khatti.
  *
  * This file is part of the FreeType project, and may only be used,
diff --git a/vendor/freetype/src/truetype/truetype.c b/vendor/freetype/src/truetype/truetype.c
index fcc0ea334f..fe9cb9247a 100644
--- a/vendor/freetype/src/truetype/truetype.c
+++ b/vendor/freetype/src/truetype/truetype.c
@@ -4,7 +4,7 @@
  *
  *   FreeType TrueType driver component (body only).
  *
- * Copyright (C) 1996-2023 by
+ * Copyright (C) 1996-2024 by
  * David Turner, Robert Wilhelm, and Werner Lemberg.
  *
  * This file is part of the FreeType project, and may only be used,
diff --git a/vendor/freetype/src/truetype/ttdriver.c b/vendor/freetype/src/truetype/ttdriver.c
index d1496fec7f..4ab68eb9a1 100644
--- a/vendor/freetype/src/truetype/ttdriver.c
+++ b/vendor/freetype/src/truetype/ttdriver.c
@@ -4,7 +4,7 @@
  *
  *   TrueType font driver implementation (body).
  *
- * Copyright (C) 1996-2023 by
+ * Copyright (C) 1996-2024 by
  * David Turner, Robert Wilhelm, and Werner Lemberg.
  *
  * This file is part of the FreeType project, and may only be used,
@@ -217,7 +217,20 @@
     kerning->y = 0;
 
     if ( sfnt )
-      kerning->x = sfnt->get_kerning( ttface, left_glyph, right_glyph );
+    {
+      /* Use 'kern' table if available since that can be faster; otherwise */
+      /* use GPOS kerning pairs if available.                              */
+      if ( ttface->kern_avail_bits != 0 )
+        kerning->x = sfnt->get_kerning( ttface,
+                                        left_glyph,
+                                        right_glyph );
+#ifdef TT_CONFIG_OPTION_GPOS_KERNING
+      else if ( ttface->gpos_kerning_available )
+        kerning->x = sfnt->get_gpos_kerning( ttface,
+                                             left_glyph,
+                                             right_glyph );
+#endif
+    }
 
     return 0;
   }
diff --git a/vendor/freetype/src/truetype/ttdriver.h b/vendor/freetype/src/truetype/ttdriver.h
index 757a66f425..3e1cf234fc 100644
--- a/vendor/freetype/src/truetype/ttdriver.h
+++ b/vendor/freetype/src/truetype/ttdriver.h
@@ -4,7 +4,7 @@
  *
  *   High-level TrueType driver interface (specification).
  *
- * Copyright (C) 1996-2023 by
+ * Copyright (C) 1996-2024 by
  * David Turner, Robert Wilhelm, and Werner Lemberg.
  *
  * This file is part of the FreeType project, and may only be used,
diff --git a/vendor/freetype/src/truetype/tterrors.h b/vendor/freetype/src/truetype/tterrors.h
index 008ee99853..7ad937bd04 100644
--- a/vendor/freetype/src/truetype/tterrors.h
+++ b/vendor/freetype/src/truetype/tterrors.h
@@ -4,7 +4,7 @@
  *
  *   TrueType error codes (specification only).
  *
- * Copyright (C) 2001-2023 by
+ * Copyright (C) 2001-2024 by
  * David Turner, Robert Wilhelm, and Werner Lemberg.
  *
  * This file is part of the FreeType project, and may only be used,
diff --git a/vendor/freetype/src/truetype/ttgload.c b/vendor/freetype/src/truetype/ttgload.c
index dc427e8a11..b656ccf04e 100644
--- a/vendor/freetype/src/truetype/ttgload.c
+++ b/vendor/freetype/src/truetype/ttgload.c
@@ -4,7 +4,7 @@
  *
  *   TrueType Glyph Loader (body).
  *
- * Copyright (C) 1996-2023 by
+ * Copyright (C) 1996-2024 by
  * David Turner, Robert Wilhelm, and Werner Lemberg.
  *
  * This file is part of the FreeType project, and may only be used,
@@ -353,7 +353,8 @@
     FT_Byte         c, count;
     FT_Vector       *vec, *vec_limit;
     FT_Pos          x, y;
-    FT_Short        *cont, *cont_limit, last;
+    FT_UShort       *cont, *cont_limit;
+    FT_Int          last;
 
 
     /* check that we can add the contours to the glyph */
@@ -372,7 +373,7 @@
     last = -1;
     for ( ; cont < cont_limit; cont++ )
     {
-      *cont = FT_NEXT_SHORT( p );
+      *cont = FT_NEXT_USHORT( p );
 
       if ( *cont <= last )
         goto Invalid_Outline;
@@ -418,11 +419,9 @@
       /* and thus allocate the bytecode array size by ourselves     */
       if ( n_ins )
       {
-        if ( FT_QNEW_ARRAY( exec->glyphIns, n_ins ) )
+        if ( FT_DUP( exec->glyphIns, p, n_ins ) )
           return error;
 
-        FT_MEM_COPY( exec->glyphIns, p, (FT_Long)n_ins );
-
         exec->glyphSize  = n_ins;
       }
     }
@@ -432,7 +431,7 @@
     p += n_ins;
 
     /* reading the point tags */
-    flag       = (FT_Byte*)outline->tags;
+    flag       = outline->tags;
     flag_limit = flag + n_points;
 
     FT_ASSERT( flag );
@@ -465,7 +464,7 @@
 
     vec       = outline->points;
     vec_limit = vec + n_points;
-    flag      = (FT_Byte*)outline->tags;
+    flag      = outline->tags;
     x         = 0;
 
     for ( ; vec < vec_limit; vec++, flag++ )
@@ -499,7 +498,7 @@
 
     vec       = outline->points;
     vec_limit = vec + n_points;
-    flag      = (FT_Byte*)outline->tags;
+    flag      = outline->tags;
     y         = 0;
 
     for ( ; vec < vec_limit; vec++, flag++ )
@@ -532,8 +531,8 @@
       *flag  = (FT_Byte)( f & ON_CURVE_POINT );
     }
 
-    outline->n_points   = (FT_Short)n_points;
-    outline->n_contours = (FT_Short)n_contours;
+    outline->n_points   = (FT_UShort)n_points;
+    outline->n_contours = (FT_UShort)n_contours;
 
     load->cursor = p;
 
@@ -754,15 +753,13 @@
                    FT_UInt       start_point,
                    FT_UInt       start_contour )
   {
-    zone->n_points    = (FT_UShort)load->outline.n_points + 4 -
-                          (FT_UShort)start_point;
-    zone->n_contours  = load->outline.n_contours -
-                          (FT_Short)start_contour;
+    zone->n_points    = load->outline.n_points + 4 - (FT_UShort)start_point;
+    zone->n_contours  = load->outline.n_contours - (FT_UShort)start_contour;
     zone->org         = load->extra_points + start_point;
     zone->cur         = load->outline.points + start_point;
     zone->orus        = load->extra_points2 + start_point;
-    zone->tags        = (FT_Byte*)load->outline.tags + start_point;
-    zone->contours    = (FT_UShort*)load->outline.contours + start_contour;
+    zone->tags        = load->outline.tags + start_point;
+    zone->contours    = load->outline.contours + start_contour;
     zone->first_point = (FT_UShort)start_point;
   }
 
@@ -1046,7 +1043,7 @@
     current.points   = gloader->base.outline.points +
                          num_base_points;
     current.n_points = gloader->base.outline.n_points -
-                         (short)num_base_points;
+                         (FT_UShort)num_base_points;
 
     have_scale = FT_BOOL( subglyph->flags & ( WE_HAVE_A_SCALE     |
                                               WE_HAVE_AN_XY_SCALE |
@@ -1059,7 +1056,7 @@
     /* get offset */
     if ( !( subglyph->flags & ARGS_ARE_XY_VALUES ) )
     {
-      FT_UInt     num_points = (FT_UInt)gloader->base.outline.n_points;
+      FT_UInt     num_points = gloader->base.outline.n_points;
       FT_UInt     k = (FT_UInt)subglyph->arg1;
       FT_UInt     l = (FT_UInt)subglyph->arg2;
       FT_Vector*  p1;
@@ -1721,8 +1718,8 @@
         FT_List_Add( &loader->composites, node );
       }
 
-      start_point   = (FT_UInt)gloader->base.outline.n_points;
-      start_contour = (FT_UInt)gloader->base.outline.n_contours;
+      start_point   = gloader->base.outline.n_points;
+      start_contour = gloader->base.outline.n_contours;
 
       /* for each subglyph, read composite header */
       error = face->read_composite_glyph( loader );
@@ -1741,14 +1738,14 @@
       if ( FT_IS_NAMED_INSTANCE( FT_FACE( face ) ) ||
            FT_IS_VARIATION( FT_FACE( face ) )      )
       {
-        short        i, limit;
+        FT_UShort    i, limit;
         FT_SubGlyph  subglyph;
 
         FT_Outline  outline = { 0, 0, NULL, NULL, NULL, 0 };
         FT_Vector*  unrounded = NULL;
 
 
-        limit = (short)gloader->current.num_subglyphs;
+        limit = (FT_UShort)gloader->current.num_subglyphs;
 
         /* construct an outline structure for              */
         /* communication with `TT_Vary_Apply_Glyph_Deltas' */
@@ -1874,7 +1871,7 @@
           linear_hadvance = loader->linear;
           linear_vadvance = loader->vadvance;
 
-          num_base_points = (FT_UInt)gloader->base.outline.n_points;
+          num_base_points = gloader->base.outline.n_points;
 
           error = load_truetype_glyph( loader,
                                        (FT_UInt)subglyph->index,
@@ -1898,7 +1895,7 @@
             loader->vadvance = linear_vadvance;
           }
 
-          num_points = (FT_UInt)gloader->base.outline.n_points;
+          num_points = gloader->base.outline.n_points;
 
           if ( num_points == num_base_points )
             continue;
@@ -2313,7 +2310,7 @@
        *
        * 1) we have a `tricky' font that heavily relies on the interpreter to
        *    render glyphs correctly, for example DFKai-SB, or
-       * 2) FT_RENDER_MODE_MONO (i.e, monochome rendering) is requested.
+       * 2) FT_RENDER_MODE_MONO (i.e, monochrome rendering) is requested.
        *
        * In those cases, backward compatibility needs to be turned off to get
        * correct rendering.  The rendering is then completely up to the
@@ -2719,7 +2716,7 @@
          size->metrics->y_ppem < 24         )
       glyph->outline.flags |= FT_OUTLINE_HIGH_PRECISION;
 
-    FT_TRACE1(( "  subglyphs = %u, contours = %hd, points = %hd,"
+    FT_TRACE1(( "  subglyphs = %u, contours = %hu, points = %hu,"
                 " flags = 0x%.3x\n",
                 loader.gloader->base.num_subglyphs,
                 glyph->outline.n_contours,
diff --git a/vendor/freetype/src/truetype/ttgload.h b/vendor/freetype/src/truetype/ttgload.h
index f18637dce3..22ea967f30 100644
--- a/vendor/freetype/src/truetype/ttgload.h
+++ b/vendor/freetype/src/truetype/ttgload.h
@@ -4,7 +4,7 @@
  *
  *   TrueType Glyph Loader (specification).
  *
- * Copyright (C) 1996-2023 by
+ * Copyright (C) 1996-2024 by
  * David Turner, Robert Wilhelm, and Werner Lemberg.
  *
  * This file is part of the FreeType project, and may only be used,
diff --git a/vendor/freetype/src/truetype/ttgxvar.c b/vendor/freetype/src/truetype/ttgxvar.c
index ad4f266b27..095a72055c 100644
--- a/vendor/freetype/src/truetype/ttgxvar.c
+++ b/vendor/freetype/src/truetype/ttgxvar.c
@@ -4,7 +4,7 @@
  *
  *   TrueType GX Font Variation loader
  *
- * Copyright (C) 2004-2023 by
+ * Copyright (C) 2004-2024 by
  * David Turner, Robert Wilhelm, Werner Lemberg, and George Williams.
  *
  * This file is part of the FreeType project, and may only be used,
@@ -596,7 +596,7 @@
 
       for ( j = 0; j < itemStore->axisCount; j++ )
       {
-        FT_Short  start, peak, end;
+        FT_Int  start, peak, end;
 
 
         if ( FT_READ_SHORT( start ) ||
@@ -604,6 +604,10 @@
              FT_READ_SHORT( end )   )
           goto Exit;
 
+        /* immediately tag invalid ranges with special peak = 0 */
+        if ( ( start < 0 && end > 0 ) || start > peak || peak > end )
+          peak = 0;
+
         axisCoords[j].startCoord = FT_fdot14ToFixed( start );
         axisCoords[j].peakCoord  = FT_fdot14ToFixed( peak );
         axisCoords[j].endCoord   = FT_fdot14ToFixed( end );
@@ -1024,6 +1028,9 @@
     if ( innerIndex >= varData->itemCount )
       return 0; /* Out of range. */
 
+    if ( varData->regionIdxCount == 0 )
+      return 0; /* Avoid "applying zero offset to null pointer". */
+
     if ( varData->regionIdxCount < 16 )
     {
       deltaSet = deltaSetStack;
@@ -1074,43 +1081,32 @@
       /* inner loop steps through axes in this region */
       for ( j = 0; j < itemStore->axisCount; j++, axis++ )
       {
-        /* compute the scalar contribution of this axis; */
-        /* ignore invalid ranges                         */
-        if ( axis->startCoord > axis->peakCoord ||
-             axis->peakCoord > axis->endCoord   )
-          continue;
+        FT_Fixed  ncv = ttface->blend->normalizedcoords[j];
 
-        else if ( axis->startCoord < 0 &&
-                  axis->endCoord > 0   &&
-                  axis->peakCoord != 0 )
-          continue;
 
-        /* peak of 0 means ignore this axis */
-        else if ( axis->peakCoord == 0 )
-          continue;
-
-        else if ( ttface->blend->normalizedcoords[j] == axis->peakCoord )
+        /* compute the scalar contribution of this axis */
+        /* with peak of 0 used for invalid axes         */
+        if ( axis->peakCoord == ncv ||
+             axis->peakCoord == 0   )
           continue;
 
         /* ignore this region if coords are out of range */
-        else if ( ttface->blend->normalizedcoords[j] <= axis->startCoord ||
-                  ttface->blend->normalizedcoords[j] >= axis->endCoord   )
+        else if ( ncv <= axis->startCoord ||
+                  ncv >= axis->endCoord   )
         {
           scalar = 0;
           break;
         }
 
         /* cumulative product of all the axis scalars */
-        else if ( ttface->blend->normalizedcoords[j] < axis->peakCoord )
-          scalar =
-            FT_MulDiv( scalar,
-                       ttface->blend->normalizedcoords[j] - axis->startCoord,
-                       axis->peakCoord - axis->startCoord );
-        else
-          scalar =
-            FT_MulDiv( scalar,
-                       axis->endCoord - ttface->blend->normalizedcoords[j],
-                       axis->endCoord - axis->peakCoord );
+        else if ( ncv < axis->peakCoord )
+          scalar = FT_MulDiv( scalar,
+                              ncv - axis->startCoord,
+                              axis->peakCoord - axis->startCoord );
+        else   /* ncv > axis->peakCoord */
+          scalar = FT_MulDiv( scalar,
+                              axis->endCoord - ncv,
+                              axis->endCoord - axis->peakCoord );
 
       } /* per-axis loop */
 
@@ -1920,32 +1916,27 @@
 
     for ( i = 0; i < blend->num_axis; i++ )
     {
-      FT_TRACE6(( "    axis %d coordinate %.5f:\n",
-                  i, (double)blend->normalizedcoords[i] / 65536 ));
+      FT_Fixed  ncv = blend->normalizedcoords[i];
+
+
+      FT_TRACE6(( "    axis %d coordinate %.5f:\n", i, (double)ncv / 65536 ));
 
       /* It's not clear why (for intermediate tuples) we don't need     */
       /* to check against start/end -- the documentation says we don't. */
       /* Similarly, it's unclear why we don't need to scale along the   */
       /* axis.                                                          */
 
-      if ( tuple_coords[i] == 0 )
+      if ( tuple_coords[i] == ncv )
       {
-        FT_TRACE6(( "      tuple coordinate is zero, ignore\n" ));
+        FT_TRACE6(( "      tuple coordinate %.5f fits perfectly\n",
+                    (double)tuple_coords[i] / 65536 ));
+        /* `apply' does not change */
         continue;
       }
 
-      if ( blend->normalizedcoords[i] == 0 )
-      {
-        FT_TRACE6(( "      axis coordinate is zero, stop\n" ));
-        apply = 0;
-        break;
-      }
-
-      if ( blend->normalizedcoords[i] == tuple_coords[i] )
+      if ( tuple_coords[i] == 0 )
       {
-        FT_TRACE6(( "      tuple coordinate %.5f fits perfectly\n",
-                    (double)tuple_coords[i] / 65536 ));
-        /* `apply' does not change */
+        FT_TRACE6(( "      tuple coordinate is zero, ignore\n" ));
         continue;
       }
 
@@ -1953,27 +1944,27 @@
       {
         /* not an intermediate tuple */
 
-        if ( blend->normalizedcoords[i] < FT_MIN( 0, tuple_coords[i] ) ||
-             blend->normalizedcoords[i] > FT_MAX( 0, tuple_coords[i] ) )
+        if ( ( tuple_coords[i] > ncv && ncv > 0 ) ||
+             ( tuple_coords[i] < ncv && ncv < 0 ) )
+        {
+          FT_TRACE6(( "      tuple coordinate %.5f fits\n",
+                      (double)tuple_coords[i] / 65536 ));
+          apply = FT_MulDiv( apply, ncv, tuple_coords[i] );
+        }
+        else
         {
           FT_TRACE6(( "      tuple coordinate %.5f is exceeded, stop\n",
                       (double)tuple_coords[i] / 65536 ));
           apply = 0;
           break;
         }
-
-        FT_TRACE6(( "      tuple coordinate %.5f fits\n",
-                    (double)tuple_coords[i] / 65536 ));
-        apply = FT_MulDiv( apply,
-                           blend->normalizedcoords[i],
-                           tuple_coords[i] );
       }
       else
       {
         /* intermediate tuple */
 
-        if ( blend->normalizedcoords[i] <= im_start_coords[i] ||
-             blend->normalizedcoords[i] >= im_end_coords[i]   )
+        if ( ncv <= im_start_coords[i] ||
+             ncv >= im_end_coords[i]   )
         {
           FT_TRACE6(( "      intermediate tuple range ]%.5f;%.5f[ is exceeded,"
                       " stop\n",
@@ -1986,13 +1977,13 @@
         FT_TRACE6(( "      intermediate tuple range ]%.5f;%.5f[ fits\n",
                     (double)im_start_coords[i] / 65536,
                     (double)im_end_coords[i] / 65536 ));
-        if ( blend->normalizedcoords[i] < tuple_coords[i] )
+        if ( ncv < tuple_coords[i] )
           apply = FT_MulDiv( apply,
-                             blend->normalizedcoords[i] - im_start_coords[i],
+                             ncv - im_start_coords[i],
                              tuple_coords[i] - im_start_coords[i] );
-        else
+        else /* ncv > tuple_coords[i] */
           apply = FT_MulDiv( apply,
-                             im_end_coords[i] - blend->normalizedcoords[i],
+                             im_end_coords[i] - ncv,
                              im_end_coords[i] - tuple_coords[i] );
       }
     }
@@ -2141,11 +2132,12 @@
                                          outerIndex,
                                          innerIndex );
 
-	  v += delta << 2;
+          /* Convert delta in F2DOT14 to 16.16 before adding. */
+          v += MUL_INT( delta, 4 );
 
-	  /* Clamp value range. */
-	  v = v >=  0x10000L ?  0x10000 : v;
-	  v = v <= -0x10000L ? -0x10000 : v;
+          /* Clamp value range [-1, 1]. */
+          v = v >=  0x10000L ?  0x10000 : v;
+          v = v <= -0x10000L ? -0x10000 : v;
 
           new_normalized[i] = v;
         }
@@ -2721,9 +2713,8 @@
       FT_UInt  n;
 
 
-      if ( FT_ALLOC( mmvar, ttface->blend->mmvar_len ) )
+      if ( FT_DUP( mmvar, ttface->blend->mmvar, ttface->blend->mmvar_len ) )
         goto Exit;
-      FT_MEM_COPY( mmvar, ttface->blend->mmvar, ttface->blend->mmvar_len );
 
       axis_flags =
         (FT_UShort*)( (char*)mmvar + mmvar_size );
@@ -3533,9 +3524,10 @@
     FT_ULong  here;
     FT_UInt   i, j;
 
-    FT_Fixed*  tuple_coords    = NULL;
-    FT_Fixed*  im_start_coords = NULL;
-    FT_Fixed*  im_end_coords   = NULL;
+    FT_Fixed*  peak_coords = NULL;
+    FT_Fixed*  tuple_coords;
+    FT_Fixed*  im_start_coords;
+    FT_Fixed*  im_end_coords;
 
     GX_Blend  blend = face->blend;
 
@@ -3556,16 +3548,16 @@
     {
       FT_TRACE2(( "\n" ));
       FT_TRACE2(( "tt_face_vary_cvt: no blend specified\n" ));
-      error = FT_Err_Ok;
-      goto Exit;
+
+      return FT_Err_Ok;
     }
 
     if ( !face->cvt )
     {
       FT_TRACE2(( "\n" ));
       FT_TRACE2(( "tt_face_vary_cvt: no `cvt ' table\n" ));
-      error = FT_Err_Ok;
-      goto Exit;
+
+      return FT_Err_Ok;
     }
 
     error = face->goto_table( face, TTAG_cvar, stream, &table_len );
@@ -3573,15 +3565,11 @@
     {
       FT_TRACE2(( "is missing\n" ));
 
-      error = FT_Err_Ok;
-      goto Exit;
+      return FT_Err_Ok;
     }
 
     if ( FT_FRAME_ENTER( table_len ) )
-    {
-      error = FT_Err_Ok;
-      goto Exit;
-    }
+      return FT_Err_Ok;
 
     table_start = FT_Stream_FTell( stream );
     if ( FT_GET_LONG() != 0x00010000L )
@@ -3594,11 +3582,6 @@
 
     FT_TRACE2(( "loaded\n" ));
 
-    if ( FT_NEW_ARRAY( tuple_coords, blend->num_axis )    ||
-         FT_NEW_ARRAY( im_start_coords, blend->num_axis ) ||
-         FT_NEW_ARRAY( im_end_coords, blend->num_axis )   )
-      goto FExit;
-
     tupleCount   = FT_GET_USHORT();
     offsetToData = FT_GET_USHORT();
 
@@ -3634,8 +3617,12 @@
                 tupleCount & GX_TC_TUPLE_COUNT_MASK,
                 ( tupleCount & GX_TC_TUPLE_COUNT_MASK ) == 1 ? "" : "s" ));
 
-    if ( FT_NEW_ARRAY( cvt_deltas, face->cvt_size ) )
-      goto FExit;
+    if ( FT_QNEW_ARRAY( peak_coords, 3 * blend->num_axis ) ||
+         FT_NEW_ARRAY( cvt_deltas, face->cvt_size )        )
+      goto Exit;
+
+    im_start_coords = peak_coords + blend->num_axis;
+    im_end_coords = im_start_coords + blend->num_axis;
 
     for ( i = 0; i < ( tupleCount & GX_TC_TUPLE_COUNT_MASK ); i++ )
     {
@@ -3652,32 +3639,19 @@
       if ( tupleIndex & GX_TI_EMBEDDED_TUPLE_COORD )
       {
         for ( j = 0; j < blend->num_axis; j++ )
-          tuple_coords[j] = FT_fdot14ToFixed( FT_GET_SHORT() );
+          peak_coords[j] = FT_fdot14ToFixed( FT_GET_SHORT() );
+        tuple_coords = peak_coords;
       }
-      else if ( ( tupleIndex & GX_TI_TUPLE_INDEX_MASK ) >= blend->tuplecount )
+      else if ( ( tupleIndex & GX_TI_TUPLE_INDEX_MASK ) < blend->tuplecount )
+        tuple_coords = blend->tuplecoords +
+            ( tupleIndex & GX_TI_TUPLE_INDEX_MASK ) * blend->num_axis;
+      else
       {
         FT_TRACE2(( "tt_face_vary_cvt:"
                     " invalid tuple index\n" ));
 
         error = FT_THROW( Invalid_Table );
-        goto FExit;
-      }
-      else
-      {
-        if ( !blend->tuplecoords )
-        {
-          FT_TRACE2(( "tt_face_vary_cvt:"
-                      " no valid tuple coordinates available\n" ));
-
-          error = FT_THROW( Invalid_Table );
-          goto FExit;
-        }
-
-        FT_MEM_COPY(
-          tuple_coords,
-          blend->tuplecoords +
-            ( tupleIndex & GX_TI_TUPLE_INDEX_MASK ) * blend->num_axis,
-          blend->num_axis * sizeof ( FT_Fixed ) );
+        goto Exit;
       }
 
       if ( tupleIndex & GX_TI_INTERMEDIATE_TUPLE )
@@ -3820,22 +3794,20 @@
     for ( i = 0; i < face->cvt_size; i++ )
       face->cvt[i] += FT_fixedToFdot6( cvt_deltas[i] );
 
-  FExit:
-    FT_FRAME_EXIT();
+    /* iterate over all FT_Size objects and set `cvt_ready' to -1 */
+    /* to trigger rescaling of all CVT values                     */
+    FT_List_Iterate( &root->sizes_list,
+                     tt_cvt_ready_iterator,
+                     NULL );
 
   Exit:
     if ( sharedpoints != ALL_POINTS )
       FT_FREE( sharedpoints );
-    FT_FREE( tuple_coords );
-    FT_FREE( im_start_coords );
-    FT_FREE( im_end_coords );
     FT_FREE( cvt_deltas );
+    FT_FREE( peak_coords );
 
-    /* iterate over all FT_Size objects and set `cvt_ready' to -1 */
-    /* to trigger rescaling of all CVT values                     */
-    FT_List_Iterate( &root->sizes_list,
-                     tt_cvt_ready_iterator,
-                     NULL );
+  FExit:
+    FT_FRAME_EXIT();
 
     return error;
 
@@ -4099,9 +4071,10 @@
     FT_ULong  here;
     FT_UInt   i, j;
 
-    FT_Fixed*  tuple_coords    = NULL;
-    FT_Fixed*  im_start_coords = NULL;
-    FT_Fixed*  im_end_coords   = NULL;
+    FT_Fixed*  peak_coords = NULL;
+    FT_Fixed*  tuple_coords;
+    FT_Fixed*  im_start_coords;
+    FT_Fixed*  im_end_coords;
 
     GX_Blend  blend = face->blend;
 
@@ -4136,27 +4109,17 @@
       return FT_Err_Ok;
     }
 
-    if ( FT_NEW_ARRAY( points_org, n_points ) ||
-         FT_NEW_ARRAY( points_out, n_points ) ||
-         FT_NEW_ARRAY( has_delta, n_points )  )
-      goto Fail1;
-
     dataSize = blend->glyphoffsets[glyph_index + 1] -
                  blend->glyphoffsets[glyph_index];
 
     if ( FT_STREAM_SEEK( blend->glyphoffsets[glyph_index] ) ||
          FT_FRAME_ENTER( dataSize )                         )
-      goto Fail1;
+      return error;
 
     glyph_start = FT_Stream_FTell( stream );
 
     /* each set of glyph variation data is formatted similarly to `cvar' */
 
-    if ( FT_NEW_ARRAY( tuple_coords, blend->num_axis )    ||
-         FT_NEW_ARRAY( im_start_coords, blend->num_axis ) ||
-         FT_NEW_ARRAY( im_end_coords, blend->num_axis )   )
-      goto Fail2;
-
     tupleCount   = FT_GET_USHORT();
     offsetToData = FT_GET_USHORT();
 
@@ -4168,7 +4131,7 @@
                   " invalid glyph variation array header\n" ));
 
       error = FT_THROW( Invalid_Table );
-      goto Fail2;
+      goto FExit;
     }
 
     offsetToData += glyph_start;
@@ -4192,9 +4155,16 @@
                 tupleCount & GX_TC_TUPLE_COUNT_MASK,
                 ( tupleCount & GX_TC_TUPLE_COUNT_MASK ) == 1 ? "" : "s" ));
 
-    if ( FT_NEW_ARRAY( point_deltas_x, n_points ) ||
-         FT_NEW_ARRAY( point_deltas_y, n_points ) )
-      goto Fail3;
+    if ( FT_QNEW_ARRAY( peak_coords, 3 * blend->num_axis ) ||
+         FT_NEW_ARRAY( point_deltas_x, 2 * n_points )      ||
+         FT_QNEW_ARRAY( points_org, n_points )             ||
+         FT_QNEW_ARRAY( points_out, n_points )             ||
+         FT_QNEW_ARRAY( has_delta, n_points )              )
+      goto Exit;
+
+    im_start_coords = peak_coords + blend->num_axis;
+    im_end_coords   = im_start_coords + blend->num_axis;
+    point_deltas_y  = point_deltas_x + n_points;
 
     for ( j = 0; j < n_points; j++ )
     {
@@ -4217,22 +4187,20 @@
       if ( tupleIndex & GX_TI_EMBEDDED_TUPLE_COORD )
       {
         for ( j = 0; j < blend->num_axis; j++ )
-          tuple_coords[j] = FT_fdot14ToFixed( FT_GET_SHORT() );
+          peak_coords[j] = FT_fdot14ToFixed( FT_GET_SHORT() );
+        tuple_coords = peak_coords;
       }
-      else if ( ( tupleIndex & GX_TI_TUPLE_INDEX_MASK ) >= blend->tuplecount )
+      else if ( ( tupleIndex & GX_TI_TUPLE_INDEX_MASK ) < blend->tuplecount )
+        tuple_coords = blend->tuplecoords +
+            ( tupleIndex & GX_TI_TUPLE_INDEX_MASK ) * blend->num_axis;
+      else
       {
         FT_TRACE2(( "TT_Vary_Apply_Glyph_Deltas:"
                     " invalid tuple index\n" ));
 
         error = FT_THROW( Invalid_Table );
-        goto Fail3;
+        goto Exit;
       }
-      else
-        FT_MEM_COPY(
-          tuple_coords,
-          blend->tuplecoords +
-            ( tupleIndex & GX_TI_TUPLE_INDEX_MASK ) * blend->num_axis,
-          blend->num_axis * sizeof ( FT_Fixed ) );
 
       if ( tupleIndex & GX_TI_INTERMEDIATE_TUPLE )
       {
@@ -4460,23 +4428,17 @@
                                        unrounded[n_points - 2].y ) / 64;
     }
 
-  Fail3:
-    FT_FREE( point_deltas_x );
-    FT_FREE( point_deltas_y );
-
-  Fail2:
+  Exit:
     if ( sharedpoints != ALL_POINTS )
       FT_FREE( sharedpoints );
-    FT_FREE( tuple_coords );
-    FT_FREE( im_start_coords );
-    FT_FREE( im_end_coords );
-
-    FT_FRAME_EXIT();
-
-  Fail1:
     FT_FREE( points_org );
     FT_FREE( points_out );
     FT_FREE( has_delta );
+    FT_FREE( peak_coords );
+    FT_FREE( point_deltas_x );
+
+  FExit:
+    FT_FRAME_EXIT();
 
     return error;
   }
diff --git a/vendor/freetype/src/truetype/ttgxvar.h b/vendor/freetype/src/truetype/ttgxvar.h
index e3da6d1705..9326011e3a 100644
--- a/vendor/freetype/src/truetype/ttgxvar.h
+++ b/vendor/freetype/src/truetype/ttgxvar.h
@@ -4,7 +4,7 @@
  *
  *   TrueType GX Font Variation loader (specification)
  *
- * Copyright (C) 2004-2023 by
+ * Copyright (C) 2004-2024 by
  * David Turner, Robert Wilhelm, Werner Lemberg and George Williams.
  *
  * This file is part of the FreeType project, and may only be used,
diff --git a/vendor/freetype/src/truetype/ttinterp.c b/vendor/freetype/src/truetype/ttinterp.c
index 79df4555d9..951891dbf5 100644
--- a/vendor/freetype/src/truetype/ttinterp.c
+++ b/vendor/freetype/src/truetype/ttinterp.c
@@ -4,7 +4,7 @@
  *
  *   TrueType bytecode interpreter (body).
  *
- * Copyright (C) 1996-2023 by
+ * Copyright (C) 1996-2024 by
  * David Turner, Robert Wilhelm, and Werner Lemberg.
  *
  * This file is part of the FreeType project, and may only be used,
@@ -5270,11 +5270,11 @@
     FT_UShort        refp;
     FT_F26Dot6       dx, dy;
 
-    FT_Short         contour, bounds;
+    FT_UShort        contour, bounds;
     FT_UShort        start, limit, i;
 
 
-    contour = (FT_Short)args[0];
+    contour = (FT_UShort)args[0];
     bounds  = ( exc->GS.gep2 == 0 ) ? 1 : exc->zp2.n_contours;
 
     if ( BOUNDS( contour, bounds ) )
@@ -5290,15 +5290,13 @@
     if ( contour == 0 )
       start = 0;
     else
-      start = (FT_UShort)( exc->zp2.contours[contour - 1] + 1 -
-                           exc->zp2.first_point );
+      start = exc->zp2.contours[contour - 1] + 1 - exc->zp2.first_point;
 
     /* we use the number of points if in the twilight zone */
     if ( exc->GS.gep2 == 0 )
       limit = exc->zp2.n_points;
     else
-      limit = (FT_UShort)( exc->zp2.contours[contour] -
-                           exc->zp2.first_point + 1 );
+      limit = exc->zp2.contours[contour] + 1 - exc->zp2.first_point;
 
     for ( i = start; i < limit; i++ )
     {
@@ -5341,9 +5339,9 @@
     /*      Normal zone's `n_points' includes phantoms, so must    */
     /*      use end of last contour.                               */
     if ( exc->GS.gep2 == 0 )
-      limit = (FT_UShort)exc->zp2.n_points;
+      limit = exc->zp2.n_points;
     else if ( exc->GS.gep2 == 1 && exc->zp2.n_contours > 0 )
-      limit = (FT_UShort)( exc->zp2.contours[exc->zp2.n_contours - 1] + 1 );
+      limit = exc->zp2.contours[exc->zp2.n_contours - 1] + 1;
     else
       limit = 0;
 
diff --git a/vendor/freetype/src/truetype/ttinterp.h b/vendor/freetype/src/truetype/ttinterp.h
index e98e258fe7..4f1a9bbc67 100644
--- a/vendor/freetype/src/truetype/ttinterp.h
+++ b/vendor/freetype/src/truetype/ttinterp.h
@@ -4,7 +4,7 @@
  *
  *   TrueType bytecode interpreter (specification).
  *
- * Copyright (C) 1996-2023 by
+ * Copyright (C) 1996-2024 by
  * David Turner, Robert Wilhelm, and Werner Lemberg.
  *
  * This file is part of the FreeType project, and may only be used,
diff --git a/vendor/freetype/src/truetype/ttobjs.c b/vendor/freetype/src/truetype/ttobjs.c
index 5b56af711d..08aee62a8b 100644
--- a/vendor/freetype/src/truetype/ttobjs.c
+++ b/vendor/freetype/src/truetype/ttobjs.c
@@ -4,7 +4,7 @@
  *
  *   Objects manager (body).
  *
- * Copyright (C) 1996-2023 by
+ * Copyright (C) 1996-2024 by
  * David Turner, Robert Wilhelm, and Werner Lemberg.
  *
  * This file is part of the FreeType project, and may only be used,
@@ -115,7 +115,7 @@
   FT_LOCAL_DEF( FT_Error )
   tt_glyphzone_new( FT_Memory     memory,
                     FT_UShort     maxPoints,
-                    FT_Short      maxContours,
+                    FT_UShort     maxContours,
                     TT_GlyphZone  zone )
   {
     FT_Error  error;
@@ -152,18 +152,20 @@
   static const FT_String*
   tt_skip_pdffont_random_tag( const FT_String*  name )
   {
-    unsigned int  i;
-
-
-    if ( ft_strlen( name ) < 8 || name[6] != '+' )
-      return name;
-
-    for ( i = 0; i < 6; i++ )
-      if ( !ft_isupper( name[i] ) )
-        return name;
+    if ( ft_isupper( name[0] ) &&
+         ft_isupper( name[1] ) &&
+         ft_isupper( name[2] ) &&
+         ft_isupper( name[3] ) &&
+         ft_isupper( name[4] ) &&
+         ft_isupper( name[5] ) &&
+              '+' == name[6]   &&
+                     name[7]   )
+    {
+      FT_TRACE7(( "name without randomization tag: %s\n", name + 7 ));
+      return name + 7;
+    }
 
-    FT_TRACE7(( "name without randomization tag: %s\n", name + 7 ));
-    return name + 7;
+    return name;
   }
 
 
@@ -254,17 +256,20 @@
   {
     FT_Error   error;
     FT_UInt32  checksum = 0;
-    FT_UInt    i;
+    FT_Byte*   p;
+    FT_Int     shift;
 
 
     if ( FT_FRAME_ENTER( length ) )
       return 0;
 
+    p = (FT_Byte*)stream->cursor;
+
     for ( ; length > 3; length -= 4 )
-      checksum += (FT_UInt32)FT_GET_ULONG();
+      checksum += FT_NEXT_ULONG( p );
 
-    for ( i = 3; length > 0; length--, i-- )
-      checksum += (FT_UInt32)FT_GET_BYTE() << ( i * 8 );
+    for ( shift = 24; length > 0; length--, shift -=8 )
+      checksum += (FT_UInt32)FT_NEXT_BYTE( p ) << shift;
 
     FT_FRAME_EXIT();
 
@@ -782,8 +787,7 @@
       FT_UInt  instance_index = (FT_UInt)face_index >> 16;
 
 
-      if ( FT_HAS_MULTIPLE_MASTERS( ttface ) &&
-           instance_index > 0                )
+      if ( FT_HAS_MULTIPLE_MASTERS( ttface ) )
       {
         error = FT_Set_Named_Instance( ttface, instance_index );
         if ( error )
diff --git a/vendor/freetype/src/truetype/ttobjs.h b/vendor/freetype/src/truetype/ttobjs.h
index 40eb37b4c4..9c36ca7836 100644
--- a/vendor/freetype/src/truetype/ttobjs.h
+++ b/vendor/freetype/src/truetype/ttobjs.h
@@ -4,7 +4,7 @@
  *
  *   Objects manager (specification).
  *
- * Copyright (C) 1996-2023 by
+ * Copyright (C) 1996-2024 by
  * David Turner, Robert Wilhelm, and Werner Lemberg.
  *
  * This file is part of the FreeType project, and may only be used,
@@ -105,7 +105,7 @@ FT_BEGIN_HEADER
   FT_LOCAL( FT_Error )
   tt_glyphzone_new( FT_Memory     memory,
                     FT_UShort     maxPoints,
-                    FT_Short      maxContours,
+                    FT_UShort     maxContours,
                     TT_GlyphZone  zone );
 
 #endif /* TT_USE_BYTECODE_INTERPRETER */
diff --git a/vendor/freetype/src/truetype/ttpload.c b/vendor/freetype/src/truetype/ttpload.c
index 54a64c7b46..9505b5f179 100644
--- a/vendor/freetype/src/truetype/ttpload.c
+++ b/vendor/freetype/src/truetype/ttpload.c
@@ -4,7 +4,7 @@
  *
  *   TrueType-specific tables loader (body).
  *
- * Copyright (C) 1996-2023 by
+ * Copyright (C) 1996-2024 by
  * David Turner, Robert Wilhelm, and Werner Lemberg.
  *
  * This file is part of the FreeType project, and may only be used,
diff --git a/vendor/freetype/src/truetype/ttpload.h b/vendor/freetype/src/truetype/ttpload.h
index ed229fa461..bc32b58020 100644
--- a/vendor/freetype/src/truetype/ttpload.h
+++ b/vendor/freetype/src/truetype/ttpload.h
@@ -4,7 +4,7 @@
  *
  *   TrueType-specific tables loader (specification).
  *
- * Copyright (C) 1996-2023 by
+ * Copyright (C) 1996-2024 by
  * David Turner, Robert Wilhelm, and Werner Lemberg.
  *
  * This file is part of the FreeType project, and may only be used,
diff --git a/vendor/freetype/src/type1/t1afm.c b/vendor/freetype/src/type1/t1afm.c
index d9b9398b01..a63cd4dc48 100644
--- a/vendor/freetype/src/type1/t1afm.c
+++ b/vendor/freetype/src/type1/t1afm.c
@@ -4,7 +4,7 @@
  *
  *   AFM support for Type 1 fonts (body).
  *
- * Copyright (C) 1996-2023 by
+ * Copyright (C) 1996-2024 by
  * David Turner, Robert Wilhelm, and Werner Lemberg.
  *
  * This file is part of the FreeType project, and may only be used,
diff --git a/vendor/freetype/src/type1/t1afm.h b/vendor/freetype/src/type1/t1afm.h
index e0d5aa5a88..7f5cdda191 100644
--- a/vendor/freetype/src/type1/t1afm.h
+++ b/vendor/freetype/src/type1/t1afm.h
@@ -4,7 +4,7 @@
  *
  *   AFM support for Type 1 fonts (specification).
  *
- * Copyright (C) 1996-2023 by
+ * Copyright (C) 1996-2024 by
  * David Turner, Robert Wilhelm, and Werner Lemberg.
  *
  * This file is part of the FreeType project, and may only be used,
diff --git a/vendor/freetype/src/type1/t1driver.c b/vendor/freetype/src/type1/t1driver.c
index a4cdf372a9..8ed01914a5 100644
--- a/vendor/freetype/src/type1/t1driver.c
+++ b/vendor/freetype/src/type1/t1driver.c
@@ -4,7 +4,7 @@
  *
  *   Type 1 driver interface (body).
  *
- * Copyright (C) 1996-2023 by
+ * Copyright (C) 1996-2024 by
  * David Turner, Robert Wilhelm, and Werner Lemberg.
  *
  * This file is part of the FreeType project, and may only be used,
@@ -312,10 +312,7 @@
       {
         retval = ft_strlen( type1->glyph_names[idx] ) + 1;
         if ( value && value_len >= retval )
-        {
           ft_memcpy( value, (void *)( type1->glyph_names[idx] ), retval );
-          ((FT_Char *)value)[retval - 1] = (FT_Char)'\0';
-        }
       }
       break;
 
@@ -344,11 +341,8 @@
       {
         retval = ft_strlen( type1->encoding.char_name[idx] ) + 1;
         if ( value && value_len >= retval )
-        {
           ft_memcpy( value, (void *)( type1->encoding.char_name[idx] ),
-                     retval - 1 );
-          ((FT_Char *)value)[retval - 1] = (FT_Char)'\0';
-        }
+                     retval );
       }
       break;
 
diff --git a/vendor/freetype/src/type1/t1driver.h b/vendor/freetype/src/type1/t1driver.h
index ee7fcf43e0..5ff52b55b1 100644
--- a/vendor/freetype/src/type1/t1driver.h
+++ b/vendor/freetype/src/type1/t1driver.h
@@ -4,7 +4,7 @@
  *
  *   High-level Type 1 driver interface (specification).
  *
- * Copyright (C) 1996-2023 by
+ * Copyright (C) 1996-2024 by
  * David Turner, Robert Wilhelm, and Werner Lemberg.
  *
  * This file is part of the FreeType project, and may only be used,
diff --git a/vendor/freetype/src/type1/t1errors.h b/vendor/freetype/src/type1/t1errors.h
index 2fbd1e513f..8aeb24ae18 100644
--- a/vendor/freetype/src/type1/t1errors.h
+++ b/vendor/freetype/src/type1/t1errors.h
@@ -4,7 +4,7 @@
  *
  *   Type 1 error codes (specification only).
  *
- * Copyright (C) 2001-2023 by
+ * Copyright (C) 2001-2024 by
  * David Turner, Robert Wilhelm, and Werner Lemberg.
  *
  * This file is part of the FreeType project, and may only be used,
diff --git a/vendor/freetype/src/type1/t1gload.c b/vendor/freetype/src/type1/t1gload.c
index a32a4649d6..c29e682510 100644
--- a/vendor/freetype/src/type1/t1gload.c
+++ b/vendor/freetype/src/type1/t1gload.c
@@ -4,7 +4,7 @@
  *
  *   Type 1 Glyph Loader (body).
  *
- * Copyright (C) 1996-2023 by
+ * Copyright (C) 1996-2024 by
  * David Turner, Robert Wilhelm, and Werner Lemberg.
  *
  * This file is part of the FreeType project, and may only be used,
diff --git a/vendor/freetype/src/type1/t1gload.h b/vendor/freetype/src/type1/t1gload.h
index c06484758a..17a6a5941e 100644
--- a/vendor/freetype/src/type1/t1gload.h
+++ b/vendor/freetype/src/type1/t1gload.h
@@ -4,7 +4,7 @@
  *
  *   Type 1 Glyph Loader (specification).
  *
- * Copyright (C) 1996-2023 by
+ * Copyright (C) 1996-2024 by
  * David Turner, Robert Wilhelm, and Werner Lemberg.
  *
  * This file is part of the FreeType project, and may only be used,
diff --git a/vendor/freetype/src/type1/t1load.c b/vendor/freetype/src/type1/t1load.c
index be7cd0fd5e..ee7fb42a51 100644
--- a/vendor/freetype/src/type1/t1load.c
+++ b/vendor/freetype/src/type1/t1load.c
@@ -4,7 +4,7 @@
  *
  *   Type 1 font loader (body).
  *
- * Copyright (C) 1996-2023 by
+ * Copyright (C) 1996-2024 by
  * David Turner, Robert Wilhelm, and Werner Lemberg.
  *
  * This file is part of the FreeType project, and may only be used,
@@ -751,6 +751,7 @@
         PS_DesignMap  dmap = blend->design_map + n;
 
 
+        FT_FREE( dmap->blend_points );
         FT_FREE( dmap->design_points );
         dmap->num_points = 0;
       }
@@ -1043,9 +1044,9 @@
       }
 
       /* allocate design map data */
-      if ( FT_QNEW_ARRAY( map->design_points, num_points * 2 ) )
+      if ( FT_QNEW_ARRAY( map->design_points, num_points ) ||
+           FT_QNEW_ARRAY( map->blend_points,  num_points ) )
         goto Exit;
-      map->blend_points = map->design_points + num_points;
       map->num_points   = (FT_Byte)num_points;
 
       for ( p = 0; p < num_points; p++ )
@@ -1876,9 +1877,8 @@
         }
 
         /* t1_decrypt() shouldn't write to base -- make temporary copy */
-        if ( FT_QALLOC( temp, size ) )
+        if ( FT_DUP( temp, base, size ) )
           goto Fail;
-        FT_MEM_COPY( temp, base, size );
         psaux->t1_decrypt( temp, size, 4330 );
         size -= (FT_ULong)t1face->type1.private_dict.lenIV;
         error = T1_Add_Table( table,
@@ -2090,9 +2090,8 @@
           }
 
           /* t1_decrypt() shouldn't write to base -- make temporary copy */
-          if ( FT_QALLOC( temp, size ) )
+          if ( FT_DUP( temp, base, size ) )
             goto Fail;
-          FT_MEM_COPY( temp, base, size );
           psaux->t1_decrypt( temp, size, 4330 );
           size -= (FT_ULong)t1face->type1.private_dict.lenIV;
           error = T1_Add_Table( code_table,
@@ -2284,7 +2283,7 @@
                        T1_FIELD_DICT_PRIVATE )
 #endif
 
-    { 0, T1_FIELD_LOCATION_CID_INFO, T1_FIELD_TYPE_NONE, 0, 0, 0, 0, 0, 0 }
+    T1_FIELD_ZERO
   };
 
 
@@ -2392,18 +2391,13 @@
           T1_Field  keyword = (T1_Field)t1_keywords;
 
 
-          for (;;)
+          while ( keyword->len )
           {
-            FT_Byte*  name;
+            FT_Byte*  name = (FT_Byte*)keyword->ident;
 
 
-            name = (FT_Byte*)keyword->ident;
-            if ( !name )
-              break;
-
-            if ( cur[0] == name[0]                      &&
-                 len == ft_strlen( (const char *)name ) &&
-                 ft_memcmp( cur, name, len ) == 0       )
+            if ( keyword->len == len              &&
+                 ft_memcmp( cur, name, len ) == 0 )
             {
               /* We found it -- run the parsing callback!     */
               /* We record every instance of every field      */
diff --git a/vendor/freetype/src/type1/t1load.h b/vendor/freetype/src/type1/t1load.h
index d8c9d2d8ab..a45efa7cb7 100644
--- a/vendor/freetype/src/type1/t1load.h
+++ b/vendor/freetype/src/type1/t1load.h
@@ -4,7 +4,7 @@
  *
  *   Type 1 font loader (specification).
  *
- * Copyright (C) 1996-2023 by
+ * Copyright (C) 1996-2024 by
  * David Turner, Robert Wilhelm, and Werner Lemberg.
  *
  * This file is part of the FreeType project, and may only be used,
diff --git a/vendor/freetype/src/type1/t1objs.c b/vendor/freetype/src/type1/t1objs.c
index 69e4fd5065..b1b27c31fe 100644
--- a/vendor/freetype/src/type1/t1objs.c
+++ b/vendor/freetype/src/type1/t1objs.c
@@ -4,7 +4,7 @@
  *
  *   Type 1 objects manager (body).
  *
- * Copyright (C) 1996-2023 by
+ * Copyright (C) 1996-2024 by
  * David Turner, Robert Wilhelm, and Werner Lemberg.
  *
  * This file is part of the FreeType project, and may only be used,
diff --git a/vendor/freetype/src/type1/t1objs.h b/vendor/freetype/src/type1/t1objs.h
index 03847b27e9..3809370c1e 100644
--- a/vendor/freetype/src/type1/t1objs.h
+++ b/vendor/freetype/src/type1/t1objs.h
@@ -4,7 +4,7 @@
  *
  *   Type 1 objects manager (specification).
  *
- * Copyright (C) 1996-2023 by
+ * Copyright (C) 1996-2024 by
  * David Turner, Robert Wilhelm, and Werner Lemberg.
  *
  * This file is part of the FreeType project, and may only be used,
diff --git a/vendor/freetype/src/type1/t1parse.c b/vendor/freetype/src/type1/t1parse.c
index 6dec6c16c3..3717ea7c57 100644
--- a/vendor/freetype/src/type1/t1parse.c
+++ b/vendor/freetype/src/type1/t1parse.c
@@ -4,7 +4,7 @@
  *
  *   Type 1 parser (body).
  *
- * Copyright (C) 1996-2023 by
+ * Copyright (C) 1996-2024 by
  * David Turner, Robert Wilhelm, and Werner Lemberg.
  *
  * This file is part of the FreeType project, and may only be used,
diff --git a/vendor/freetype/src/type1/t1parse.h b/vendor/freetype/src/type1/t1parse.h
index 0d9a2865df..a0a2134d45 100644
--- a/vendor/freetype/src/type1/t1parse.h
+++ b/vendor/freetype/src/type1/t1parse.h
@@ -4,7 +4,7 @@
  *
  *   Type 1 parser (specification).
  *
- * Copyright (C) 1996-2023 by
+ * Copyright (C) 1996-2024 by
  * David Turner, Robert Wilhelm, and Werner Lemberg.
  *
  * This file is part of the FreeType project, and may only be used,
diff --git a/vendor/freetype/src/type1/t1tokens.h b/vendor/freetype/src/type1/t1tokens.h
index 40f3609262..5a3d2f1ef0 100644
--- a/vendor/freetype/src/type1/t1tokens.h
+++ b/vendor/freetype/src/type1/t1tokens.h
@@ -4,7 +4,7 @@
  *
  *   Type 1 tokenizer (specification).
  *
- * Copyright (C) 1996-2023 by
+ * Copyright (C) 1996-2024 by
  * David Turner, Robert Wilhelm, and Werner Lemberg.
  *
  * This file is part of the FreeType project, and may only be used,
diff --git a/vendor/freetype/src/type1/type1.c b/vendor/freetype/src/type1/type1.c
index d9bd8cad92..d7ff53c799 100644
--- a/vendor/freetype/src/type1/type1.c
+++ b/vendor/freetype/src/type1/type1.c
@@ -4,7 +4,7 @@
  *
  *   FreeType Type 1 driver component (body only).
  *
- * Copyright (C) 1996-2023 by
+ * Copyright (C) 1996-2024 by
  * David Turner, Robert Wilhelm, and Werner Lemberg.
  *
  * This file is part of the FreeType project, and may only be used,
diff --git a/vendor/freetype/src/type42/t42drivr.c b/vendor/freetype/src/type42/t42drivr.c
index ee5fd44a9f..25f507f150 100644
--- a/vendor/freetype/src/type42/t42drivr.c
+++ b/vendor/freetype/src/type42/t42drivr.c
@@ -4,7 +4,7 @@
  *
  *   High-level Type 42 driver interface (body).
  *
- * Copyright (C) 2002-2023 by
+ * Copyright (C) 2002-2024 by
  * Roberto Alameda.
  *
  * This file is part of the FreeType project, and may only be used,
diff --git a/vendor/freetype/src/type42/t42drivr.h b/vendor/freetype/src/type42/t42drivr.h
index ec7da18ccf..5b3852b864 100644
--- a/vendor/freetype/src/type42/t42drivr.h
+++ b/vendor/freetype/src/type42/t42drivr.h
@@ -4,7 +4,7 @@
  *
  *   High-level Type 42 driver interface (specification).
  *
- * Copyright (C) 2002-2023 by
+ * Copyright (C) 2002-2024 by
  * Roberto Alameda.
  *
  * This file is part of the FreeType project, and may only be used,
diff --git a/vendor/freetype/src/type42/t42error.h b/vendor/freetype/src/type42/t42error.h
index dcea9c4f66..f52205e2f0 100644
--- a/vendor/freetype/src/type42/t42error.h
+++ b/vendor/freetype/src/type42/t42error.h
@@ -4,7 +4,7 @@
  *
  *   Type 42 error codes (specification only).
  *
- * Copyright (C) 2002-2023 by
+ * Copyright (C) 2002-2024 by
  * David Turner, Robert Wilhelm, and Werner Lemberg.
  *
  * This file is part of the FreeType project, and may only be used,
diff --git a/vendor/freetype/src/type42/t42objs.c b/vendor/freetype/src/type42/t42objs.c
index bf4028e751..7010ba86ed 100644
--- a/vendor/freetype/src/type42/t42objs.c
+++ b/vendor/freetype/src/type42/t42objs.c
@@ -4,7 +4,7 @@
  *
  *   Type 42 objects manager (body).
  *
- * Copyright (C) 2002-2023 by
+ * Copyright (C) 2002-2024 by
  * Roberto Alameda.
  *
  * This file is part of the FreeType project, and may only be used,
diff --git a/vendor/freetype/src/type42/t42objs.h b/vendor/freetype/src/type42/t42objs.h
index 33e6215e10..3ca83bc54e 100644
--- a/vendor/freetype/src/type42/t42objs.h
+++ b/vendor/freetype/src/type42/t42objs.h
@@ -4,7 +4,7 @@
  *
  *   Type 42 objects manager (specification).
  *
- * Copyright (C) 2002-2023 by
+ * Copyright (C) 2002-2024 by
  * Roberto Alameda.
  *
  * This file is part of the FreeType project, and may only be used,
diff --git a/vendor/freetype/src/type42/t42parse.c b/vendor/freetype/src/type42/t42parse.c
index f96a43b14d..e53d352873 100644
--- a/vendor/freetype/src/type42/t42parse.c
+++ b/vendor/freetype/src/type42/t42parse.c
@@ -4,7 +4,7 @@
  *
  *   Type 42 font parser (body).
  *
- * Copyright (C) 2002-2023 by
+ * Copyright (C) 2002-2024 by
  * Roberto Alameda.
  *
  * This file is part of the FreeType project, and may only be used,
@@ -99,7 +99,7 @@
     T1_FIELD_CALLBACK( "CharStrings", t42_parse_charstrings, 0 )
     T1_FIELD_CALLBACK( "sfnts",       t42_parse_sfnts,       0 )
 
-    { 0, T1_FIELD_LOCATION_CID_INFO, T1_FIELD_TYPE_NONE, 0, 0, 0, 0, 0, 0 }
+    T1_FIELD_ZERO
   };
 
 
@@ -1195,8 +1195,6 @@
   {
     T42_Parser  parser     = &loader->parser;
     FT_Byte*    limit;
-    FT_Int      n_keywords = (FT_Int)( sizeof ( t42_keywords ) /
-                                         sizeof ( t42_keywords[0] ) );
 
 
     parser->root.cursor = base;
@@ -1273,24 +1271,20 @@
 
         if ( len > 0 && len < 22 && parser->root.cursor < limit )
         {
-          int  i;
+          T1_Field  keyword = (T1_Field)t42_keywords;
 
 
           /* now compare the immediate name to the keyword table */
-
-          /* loop through all known keywords */
-          for ( i = 0; i < n_keywords; i++ )
+          while ( keyword->len )
           {
-            T1_Field  keyword = (T1_Field)&t42_keywords[i];
-            FT_Byte   *name   = (FT_Byte*)keyword->ident;
+            FT_Byte*  name = (FT_Byte*)keyword->ident;
 
 
             if ( !name )
               continue;
 
-            if ( cur[0] == name[0]                      &&
-                 len == ft_strlen( (const char *)name ) &&
-                 ft_memcmp( cur, name, len ) == 0       )
+            if ( keyword->len == len              &&
+                 ft_memcmp( cur, name, len ) == 0 )
             {
               /* we found it -- run the parsing callback! */
               parser->root.error = t42_load_keyword( face,
@@ -1300,6 +1294,8 @@
                 return parser->root.error;
               break;
             }
+
+            keyword++;
           }
         }
       }
diff --git a/vendor/freetype/src/type42/t42parse.h b/vendor/freetype/src/type42/t42parse.h
index 5741c54137..e977861624 100644
--- a/vendor/freetype/src/type42/t42parse.h
+++ b/vendor/freetype/src/type42/t42parse.h
@@ -4,7 +4,7 @@
  *
  *   Type 42 font parser (specification).
  *
- * Copyright (C) 2002-2023 by
+ * Copyright (C) 2002-2024 by
  * Roberto Alameda.
  *
  * This file is part of the FreeType project, and may only be used,
diff --git a/vendor/freetype/src/type42/t42types.h b/vendor/freetype/src/type42/t42types.h
index 0bfe14ee4d..550cc07ca1 100644
--- a/vendor/freetype/src/type42/t42types.h
+++ b/vendor/freetype/src/type42/t42types.h
@@ -4,7 +4,7 @@
  *
  *   Type 42 font data types (specification only).
  *
- * Copyright (C) 2002-2023 by
+ * Copyright (C) 2002-2024 by
  * Roberto Alameda.
  *
  * This file is part of the FreeType project, and may only be used,
diff --git a/vendor/freetype/src/type42/type42.c b/vendor/freetype/src/type42/type42.c
index 8d2302c8e6..a9444f0f50 100644
--- a/vendor/freetype/src/type42/type42.c
+++ b/vendor/freetype/src/type42/type42.c
@@ -4,7 +4,7 @@
  *
  *   FreeType Type 42 driver component.
  *
- * Copyright (C) 2002-2023 by
+ * Copyright (C) 2002-2024 by
  * David Turner, Robert Wilhelm, and Werner Lemberg.
  *
  * This file is part of the FreeType project, and may only be used,
diff --git a/vendor/freetype/src/winfonts/fnterrs.h b/vendor/freetype/src/winfonts/fnterrs.h
index dafdb07b4e..7ca6592397 100644
--- a/vendor/freetype/src/winfonts/fnterrs.h
+++ b/vendor/freetype/src/winfonts/fnterrs.h
@@ -4,7 +4,7 @@
  *
  *   Win FNT/FON error codes (specification only).
  *
- * Copyright (C) 2001-2023 by
+ * Copyright (C) 2001-2024 by
  * David Turner, Robert Wilhelm, and Werner Lemberg.
  *
  * This file is part of the FreeType project, and may only be used,
diff --git a/vendor/freetype/src/winfonts/winfnt.c b/vendor/freetype/src/winfonts/winfnt.c
index 1160e4ef36..1a0f019495 100644
--- a/vendor/freetype/src/winfonts/winfnt.c
+++ b/vendor/freetype/src/winfonts/winfnt.c
@@ -4,7 +4,7 @@
  *
  *   FreeType font driver for Windows FNT/FON files
  *
- * Copyright (C) 1996-2023 by
+ * Copyright (C) 1996-2024 by
  * David Turner, Robert Wilhelm, and Werner Lemberg.
  * Copyright 2003 Huw D M Davies for Codeweavers
  * Copyright 2007 Dmitry Timoshkov for Codeweavers
diff --git a/vendor/freetype/src/winfonts/winfnt.h b/vendor/freetype/src/winfonts/winfnt.h
index 2f75b9e86c..78137496f9 100644
--- a/vendor/freetype/src/winfonts/winfnt.h
+++ b/vendor/freetype/src/winfonts/winfnt.h
@@ -4,7 +4,7 @@
  *
  *   FreeType font driver for Windows FNT/FON files
  *
- * Copyright (C) 1996-2023 by
+ * Copyright (C) 1996-2024 by
  * David Turner, Robert Wilhelm, and Werner Lemberg.
  * Copyright 2007 Dmitry Timoshkov for Codeweavers
  *
diff --git a/vendor/glob/LICENSE b/vendor/glob/LICENSE
new file mode 100644
index 0000000000..bcae1c6a21
--- /dev/null
+++ b/vendor/glob/LICENSE
@@ -0,0 +1,21 @@
+MIT License
+
+Copyright (c) 2019 Pranav
+
+Permission is hereby granted, free of charge, to any person obtaining a copy
+of this software and associated documentation files (the "Software"), to deal
+in the Software without restriction, including without limitation the rights
+to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+copies of the Software, and to permit persons to whom the Software is
+furnished to do so, subject to the following conditions:
+
+The above copyright notice and this permission notice shall be included in all
+copies or substantial portions of the Software.
+
+THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
+SOFTWARE.
diff --git a/vendor/glob/include/glob/glob.h b/vendor/glob/include/glob/glob.h
new file mode 100644
index 0000000000..e99ef05156
--- /dev/null
+++ b/vendor/glob/include/glob/glob.h
@@ -0,0 +1,54 @@
+
+#pragma once
+#include 
+#include 
+
+#ifdef GLOB_USE_GHC_FILESYSTEM
+#include 
+#else
+#include 
+#endif
+
+namespace glob {
+
+#ifdef GLOB_USE_GHC_FILESYSTEM
+namespace fs = ghc::filesystem;
+#else
+namespace fs = std::filesystem;
+#endif
+
+/// \param pathname string containing a path specification
+/// \return vector of paths that match the pathname
+///
+/// Pathnames can be absolute (/usr/src/Foo/Makefile) or relative (../../Tools/*/*.gif)
+/// Pathnames can contain shell-style wildcards
+/// Broken symlinks are included in the results (as in the shell)
+std::vector glob(const std::string &pathname);
+
+/// \param pathnames string containing a path specification
+/// \return vector of paths that match the pathname
+///
+/// Globs recursively.
+/// The pattern “**” will match any files and zero or more directories, subdirectories and
+/// symbolic links to directories.
+std::vector rglob(const std::string &pathname);
+
+/// Runs `glob` against each pathname in `pathnames` and accumulates the results
+std::vector glob(const std::vector &pathnames);
+
+/// Runs `rglob` against each pathname in `pathnames` and accumulates the results
+std::vector rglob(const std::vector &pathnames);
+
+/// Initializer list overload for convenience
+std::vector glob(const std::initializer_list &pathnames);
+
+/// Initializer list overload for convenience
+std::vector rglob(const std::initializer_list &pathnames);
+
+/// Returns true if the input path matche the glob pattern
+  bool fnmatch(const fs::path &name, const std::string &pattern);
+
+/// Returns true if the input path contains any magic characters
+  bool has_magic(const fs::path& pathname);
+
+} // namespace glob
diff --git a/vendor/glob/premake5.lua b/vendor/glob/premake5.lua
new file mode 100644
index 0000000000..64c01bf30d
--- /dev/null
+++ b/vendor/glob/premake5.lua
@@ -0,0 +1,22 @@
+project "glob"
+	language "C++"
+	cppdialect "C++17"
+	kind "StaticLib"
+	targetname "glob"
+
+	vpaths {
+		["Headers/*"] = "include/**.h",
+		["Sources"] = "source/**.cpp",
+		["*"] = "premake5.lua"
+	}
+
+	files {
+		"premake5.lua",
+		"**.cpp",
+		"**.h",
+	}
+
+	includedirs {
+		"source",
+		"include"
+	}
diff --git a/vendor/glob/source/glob.cpp b/vendor/glob/source/glob.cpp
new file mode 100644
index 0000000000..cf5d23540d
--- /dev/null
+++ b/vendor/glob/source/glob.cpp
@@ -0,0 +1,389 @@
+#include 
+#include 
+#include 
+#include 
+#include 
+#include 
+
+namespace glob {
+
+namespace {
+
+bool string_replace(std::string &str, const std::string &from, const std::string &to) {
+  std::size_t start_pos = str.find(from);
+  if (start_pos == std::string::npos)
+    return false;
+  str.replace(start_pos, from.length(), to);
+  return true;
+}
+
+std::string translate(const std::string &pattern) {
+  std::size_t i = 0, n = pattern.size();
+  std::string result_string;
+
+  while (i < n) {
+    auto c = pattern[i];
+    i += 1;
+    if (c == '*') {
+      result_string += ".*";
+    } else if (c == '?') {
+      result_string += ".";
+    } else if (c == '[') {
+      auto j = i;
+      if (j < n && pattern[j] == '!') {
+        j += 1;
+      }
+      if (j < n && pattern[j] == ']') {
+        j += 1;
+      }
+      while (j < n && pattern[j] != ']') {
+        j += 1;
+      }
+      if (j >= n) {
+        result_string += "\\[";
+      } else {
+        auto stuff = std::string(pattern.begin() + i, pattern.begin() + j);
+        if (stuff.find("--") == std::string::npos) {
+          string_replace(stuff, std::string{"\\"}, std::string{R"(\\)"});
+        } else {
+          std::vector chunks;
+          std::size_t k = 0;
+          if (pattern[i] == '!') {
+            k = i + 2;
+          } else {
+            k = i + 1;
+          }
+
+          while (true) {
+            k = pattern.find("-", k, j);
+            if (k == std::string::npos) {
+              break;
+            }
+            chunks.push_back(std::string(pattern.begin() + i, pattern.begin() + k));
+            i = k + 1;
+            k = k + 3;
+          }
+
+          chunks.push_back(std::string(pattern.begin() + i, pattern.begin() + j));
+          // Escape backslashes and hyphens for set difference (--).
+          // Hyphens that create ranges shouldn't be escaped.
+          bool first = true;
+          for (auto &s : chunks) {
+            string_replace(s, std::string{"\\"}, std::string{R"(\\)"});
+            string_replace(s, std::string{"-"}, std::string{R"(\-)"});
+            if (first) {
+              stuff += s;
+              first = false;
+            } else {
+              stuff += "-" + s;
+            }
+          }
+        }
+
+        // Escape set operations (&&, ~~ and ||).
+        std::string result;
+        std::regex_replace(std::back_inserter(result),          // ressult
+                           stuff.begin(), stuff.end(),          // string
+                           std::regex(std::string{R"([&~|])"}), // pattern
+                           std::string{R"(\\\1)"});             // repl
+        stuff = result;
+        i = j + 1;
+        if (stuff[0] == '!') {
+          stuff = "^" + std::string(stuff.begin() + 1, stuff.end());
+        } else if (stuff[0] == '^' || stuff[0] == '[') {
+          stuff = "\\\\" + stuff;
+        }
+        result_string = result_string + "[" + stuff + "]";
+      }
+    } else {
+      // SPECIAL_CHARS
+      // closing ')', '}' and ']'
+      // '-' (a range in character set)
+      // '&', '~', (extended character set operations)
+      // '#' (comment) and WHITESPACE (ignored) in verbose mode
+      static std::string special_characters = "()[]{}?*+-|^$\\.&~# \t\n\r\v\f";
+      static std::map special_characters_map;
+      if (special_characters_map.empty()) {
+        for (auto &sc : special_characters) {
+          special_characters_map.insert(
+              std::make_pair(static_cast(sc), std::string{"\\"} + std::string(1, sc)));
+        }
+      }
+
+      if (special_characters.find(c) != std::string::npos) {
+        result_string += special_characters_map[static_cast(c)];
+      } else {
+        result_string += c;
+      }
+    }
+  }
+  return std::string{"(("} + result_string + std::string{R"()|[\r\n])$)"};
+}
+
+std::regex compile_pattern(const std::string &pattern) {
+  return std::regex(translate(pattern), std::regex::ECMAScript);
+}
+
+bool fnmatch(const fs::path &name, const std::string &pattern) {
+  return std::regex_match(name.string(), compile_pattern(pattern));
+}
+
+std::vector filter(const std::vector &names,
+                             const std::string &pattern) {
+  // std::cout << "Pattern: " << pattern << "\n";
+  std::vector result;
+  for (auto &name : names) {
+    // std::cout << "Checking for " << name.string() << "\n";
+    if (fnmatch(name, pattern)) {
+      result.push_back(name);
+    }
+  }
+  return result;
+}
+
+fs::path expand_tilde(fs::path path) {
+  if (path.empty()) return path;
+
+#ifdef _WIN32
+    const char * home_variable = "USERNAME";
+#else
+    const char * home_variable = "USER";
+#endif
+    const char * home = std::getenv(home_variable);
+
+  if (home == nullptr) {
+    throw std::invalid_argument("error: Unable to expand `~` - HOME environment variable not set.");
+  }
+
+  std::string s = path.string();
+  if (s[0] == '~') {
+    s = std::string(home) + s.substr(1, s.size() - 1);
+    return fs::path(s);
+  } else {
+    return path;
+  }
+}
+
+bool has_magic(const std::string &pathname) {
+  static const auto magic_check = std::regex("([*?[])");
+  return std::regex_search(pathname, magic_check) && !fs::exists(pathname);
+}
+
+bool is_hidden(const std::string &pathname) { return pathname[0] == '.'; }
+
+bool is_recursive(const std::string &pattern) { return pattern == "**"; }
+
+std::vector iter_directory(const fs::path &dirname, bool dironly) {
+  std::vector result;
+
+  auto current_directory = dirname;
+  if (current_directory.empty()) {
+    current_directory = fs::current_path();
+  }
+
+  if (fs::exists(current_directory)) {
+    try {
+      for (auto &entry : fs::directory_iterator(
+              current_directory, fs::directory_options::follow_directory_symlink |
+                                      fs::directory_options::skip_permission_denied)) {
+        if (!dironly || entry.is_directory()) {
+          if (dirname.is_absolute()) {
+            result.push_back(entry.path());
+          } else {
+            result.push_back(fs::relative(entry.path()));
+          }
+        }
+      }
+    } catch (std::exception&) {
+      // not a directory
+      // do nothing
+    }
+  }
+
+  return result;
+}
+
+// Recursively yields relative pathnames inside a literal directory.
+std::vector rlistdir(const fs::path &dirname, bool dironly) {
+  std::vector result;
+  auto names = iter_directory(dirname, dironly);
+  for (auto &x : names) {
+    if (!is_hidden(x.string())) {
+      result.push_back(x);
+      for (auto &y : rlistdir(x, dironly)) {
+        result.push_back(y);
+      }
+    }
+  }
+  return result;
+}
+
+// This helper function recursively yields relative pathnames inside a literal
+// directory.
+std::vector glob2(const fs::path &dirname, [[maybe_unused]] const fs::path &pattern,
+                            bool dironly) {
+  // std::cout << "In glob2\n";
+  std::vector result{"."};
+  assert(is_recursive(pattern.string()));
+  for (auto &dir : rlistdir(dirname, dironly)) {
+    result.push_back(dir);
+  }
+  return result;
+}
+
+// These 2 helper functions non-recursively glob inside a literal directory.
+// They return a list of basenames.  _glob1 accepts a pattern while _glob0
+// takes a literal basename (so it only has to check for its existence).
+
+std::vector glob1(const fs::path &dirname, const fs::path &pattern,
+                            bool dironly) {
+  // std::cout << "In glob1\n";
+  auto names = iter_directory(dirname, dironly);
+  std::vector filtered_names;
+  for (auto &n : names) {
+    if (!is_hidden(n.string())) {
+      filtered_names.push_back(n.filename());
+      // if (n.is_relative()) {
+      //   // std::cout << "Filtered (Relative): " << n << "\n";
+      //   filtered_names.push_back(fs::relative(n));
+      // } else {
+      //   // std::cout << "Filtered (Absolute): " << n << "\n";
+      //   filtered_names.push_back(n.filename());
+      // }
+    }
+  }
+  return filter(filtered_names, pattern.string());
+}
+
+std::vector glob0(const fs::path &dirname, const fs::path &basename,
+                            bool /*dironly*/) {
+  // std::cout << "In glob0\n";
+  std::vector result;
+  if (basename.empty()) {
+    // 'q*x/' should match only directories.
+    if (fs::is_directory(dirname)) {
+      result = {basename};
+    }
+  } else {
+    if (fs::exists(dirname / basename)) {
+      result = {basename};
+    }
+  }
+  return result;
+}
+
+std::vector glob(const fs::path &inpath, bool recursive = false,
+                           bool dironly = false) {
+  std::vector result;
+
+  const auto pathname = inpath.string();
+  auto path = fs::path(pathname);
+
+  if (pathname[0] == '~') {
+    // expand tilde
+    path = expand_tilde(path);
+  }
+
+  auto dirname = path.parent_path();
+  const auto basename = path.filename();
+
+  if (!has_magic(pathname)) {
+    assert(!dironly);
+    if (!basename.empty()) {
+      if (fs::exists(path)) {
+        result.push_back(path);
+      }
+    } else {
+      // Patterns ending with a slash should match only directories
+      if (fs::is_directory(dirname)) {
+        result.push_back(path);
+      }
+    }
+    return result;
+  }
+
+  if (dirname.empty()) {
+    if (recursive && is_recursive(basename.string())) {
+      return glob2(dirname, basename, dironly);
+    } else {
+      return glob1(dirname, basename, dironly);
+    }
+  }
+
+  std::vector dirs;
+  if (dirname != fs::path(pathname) && has_magic(dirname.string())) {
+    dirs = glob(dirname, recursive, true);
+  } else {
+    dirs = {dirname};
+  }
+
+  std::function(const fs::path &, const fs::path &, bool)>
+      glob_in_dir;
+  if (has_magic(basename.string())) {
+    if (recursive && is_recursive(basename.string())) {
+      glob_in_dir = glob2;
+    } else {
+      glob_in_dir = glob1;
+    }
+  } else {
+    glob_in_dir = glob0;
+  }
+
+  for (auto &d : dirs) {
+    for (auto &name : glob_in_dir(d, basename, dironly)) {
+      fs::path subresult = name;
+      if (name.parent_path().empty()) {
+        subresult = d / name;
+      }
+      result.push_back(subresult.lexically_normal());
+    }
+  }
+
+  return result;
+}
+
+} // namespace end
+
+bool has_magic(const fs::path &pathname) {
+  return has_magic(pathname.string());
+}
+
+std::vector glob(const std::string &pathname) {
+  return glob(pathname, false);
+}
+
+std::vector rglob(const std::string &pathname) {
+  return glob(pathname, true);
+}
+
+std::vector glob(const std::vector &pathnames) {
+  std::vector result;
+  for (auto &pathname : pathnames) {
+    for (auto &match : glob(pathname, false)) {
+      result.push_back(std::move(match));
+    }
+  }
+  return result;
+}
+
+std::vector rglob(const std::vector &pathnames) {
+  std::vector result;
+  for (auto &pathname : pathnames) {
+    for (auto &match : glob(pathname, true)) {
+      result.push_back(std::move(match));
+    }
+  }
+  return result;
+}
+
+std::vector
+glob(const std::initializer_list &pathnames) {
+  return glob(std::vector(pathnames));
+}
+
+std::vector
+rglob(const std::initializer_list &pathnames) {
+  return rglob(std::vector(pathnames));
+}
+
+} // namespace glob
diff --git a/vendor/google-breakpad/src/client/linux/handler/minidump_descriptor.h b/vendor/google-breakpad/src/client/linux/handler/minidump_descriptor.h
index 911beaef45..8c700861af 100644
--- a/vendor/google-breakpad/src/client/linux/handler/minidump_descriptor.h
+++ b/vendor/google-breakpad/src/client/linux/handler/minidump_descriptor.h
@@ -34,6 +34,7 @@
 #include 
 
 #include 
+#include 
 
 #include "client/linux/handler/microdump_extra_info.h"
 #include "common/using_std_string.h"
diff --git a/vendor/jpeg-9e/cderror.h b/vendor/jpeg-9f/cderror.h
similarity index 100%
rename from vendor/jpeg-9e/cderror.h
rename to vendor/jpeg-9f/cderror.h
diff --git a/vendor/jpeg-9e/cdjpeg.c b/vendor/jpeg-9f/cdjpeg.c
similarity index 100%
rename from vendor/jpeg-9e/cdjpeg.c
rename to vendor/jpeg-9f/cdjpeg.c
diff --git a/vendor/jpeg-9e/cdjpeg.h b/vendor/jpeg-9f/cdjpeg.h
similarity index 100%
rename from vendor/jpeg-9e/cdjpeg.h
rename to vendor/jpeg-9f/cdjpeg.h
diff --git a/vendor/jpeg-9e/cjpeg.c b/vendor/jpeg-9f/cjpeg.c
similarity index 100%
rename from vendor/jpeg-9e/cjpeg.c
rename to vendor/jpeg-9f/cjpeg.c
diff --git a/vendor/jpeg-9f/cjpegalt.c b/vendor/jpeg-9f/cjpegalt.c
new file mode 100644
index 0000000000..c89827e26b
--- /dev/null
+++ b/vendor/jpeg-9f/cjpegalt.c
@@ -0,0 +1,791 @@
+/*
+ * alternate cjpeg.c
+ *
+ * Copyright (C) 1991-1998, Thomas G. Lane.
+ * Modified 2009-2023 by Guido Vollbeding.
+ * This file is part of the Independent JPEG Group's software.
+ * For conditions of distribution and use, see the accompanying README file.
+ *
+ * This file contains an alternate user interface for the JPEG compressor.
+ * One or more input files are named on the command line, and output file
+ * names are created by substituting ".jpg" for the input file's extension.
+ */
+
+#include "cdjpeg.h"		/* Common decls for cjpeg/djpeg applications */
+#include "jversion.h"		/* for version message */
+
+#ifdef USE_CCOMMAND		/* command-line reader for Macintosh */
+#ifdef __MWERKS__
+#include               /* Metrowerks needs this */
+#include 		/* ... and this */
+#endif
+#ifdef THINK_C
+#include 		/* Think declares it here */
+#endif
+#endif
+
+#ifndef PATH_MAX		/* ANSI maximum-pathname-length constant */
+#define PATH_MAX 256
+#endif
+
+
+/* Create the add-on message string table. */
+
+#define JMESSAGE(code,string)	string ,
+
+static const char * const cdjpeg_message_table[] = {
+#include "cderror.h"
+  NULL
+};
+
+
+/*
+ * Automatic determination of available memory.
+ */
+
+static long default_maxmem;	/* saves value determined at startup, or 0 */
+
+#ifndef FREE_MEM_ESTIMATE	/* may be defined from command line */
+
+#ifdef MSDOS			/* For MS-DOS (unless flat-memory model) */
+
+#include 		/* for access to intdos() call */
+
+LOCAL(long)
+unused_dos_memory (void)
+/* Obtain total amount of unallocated DOS memory */
+{
+  union REGS regs;
+  long nparas;
+
+  regs.h.ah = 0x48;		/* DOS function Allocate Memory Block */
+  regs.x.bx = 0xFFFF;		/* Ask for more memory than DOS can have */
+  (void) intdos(®s, ®s);
+  /* DOS will fail and return # of paragraphs actually available in BX. */
+  nparas = (unsigned int) regs.x.bx;
+  /* Times 16 to convert to bytes. */
+  return nparas << 4;
+}
+
+/* The default memory setting is 95% of the available space. */
+#define FREE_MEM_ESTIMATE  ((unused_dos_memory() * 95L) / 100L)
+
+#endif /* MSDOS */
+
+#ifdef ATARI	/* For Atari ST/Mega/STE/TT/Falcon, Pure C or Turbo C */
+
+#include 
+
+/* The default memory setting is 90% of the available space. */
+#define FREE_MEM_ESTIMATE  (((long) coreleft() * 90L) / 100L)
+
+#endif /* ATARI */
+
+/* Add memory-estimation procedures for other operating systems here,
+ * with appropriate #ifdef's around them.
+ */
+
+#endif /* !FREE_MEM_ESTIMATE */
+
+
+/*
+ * This routine determines what format the input file is,
+ * and selects the appropriate input-reading module.
+ *
+ * To determine which family of input formats the file belongs to,
+ * we may look only at the first byte of the file, since C does not
+ * guarantee that more than one character can be pushed back with ungetc.
+ * Looking at additional bytes would require one of these approaches:
+ *     1) assume we can fseek() the input file (fails for piped input);
+ *     2) assume we can push back more than one character (works in
+ *        some C implementations, but unportable);
+ *     3) provide our own buffering (breaks input readers that want to use
+ *        stdio directly, such as the RLE library);
+ * or  4) don't put back the data, and modify the input_init methods to assume
+ *        they start reading after the start of file (also breaks RLE library).
+ * #1 is attractive for MS-DOS but is untenable on Unix.
+ *
+ * The most portable solution for file types that can't be identified by their
+ * first byte is to make the user tell us what they are.  This is also the
+ * only approach for "raw" file types that contain only arbitrary values.
+ * We presently apply this method for Targa files.  Most of the time Targa
+ * files start with 0x00, so we recognize that case.  Potentially, however,
+ * a Targa file could start with any byte value (byte 0 is the length of the
+ * seldom-used ID field), so we provide a switch to force Targa input mode.
+ */
+
+static boolean is_targa;	/* records user -targa switch */
+
+
+LOCAL(cjpeg_source_ptr)
+select_file_type (j_compress_ptr cinfo, FILE * infile)
+{
+  int c;
+
+  if (is_targa) {
+#ifdef TARGA_SUPPORTED
+    return jinit_read_targa(cinfo);
+#else
+    ERREXIT(cinfo, JERR_TGA_NOTCOMP);
+#endif
+  }
+
+  if ((c = getc(infile)) == EOF)
+    ERREXIT(cinfo, JERR_INPUT_EMPTY);
+  if (ungetc(c, infile) == EOF)
+    ERREXIT(cinfo, JERR_UNGETC_FAILED);
+
+  switch (c) {
+#ifdef BMP_SUPPORTED
+  case 'B':
+    return jinit_read_bmp(cinfo);
+#endif
+#ifdef GIF_SUPPORTED
+  case 'G':
+    return jinit_read_gif(cinfo);
+#endif
+#ifdef PPM_SUPPORTED
+  case 'P':
+    return jinit_read_ppm(cinfo);
+#endif
+#ifdef RLE_SUPPORTED
+  case 'R':
+    return jinit_read_rle(cinfo);
+#endif
+#ifdef TARGA_SUPPORTED
+  case 0x00:
+    return jinit_read_targa(cinfo);
+#endif
+  default:
+    ERREXIT(cinfo, JERR_UNKNOWN_FORMAT);
+    break;
+  }
+
+  return NULL;			/* suppress compiler warnings */
+}
+
+
+/*
+ * Argument-parsing code.
+ * The switch parser is designed to be useful with DOS-style command line
+ * syntax, ie, intermixed switches and file names, where only the switches
+ * to the left of a given file name affect processing of that file.
+ */
+
+
+static const char * progname;	/* program name for error messages */
+static char * outfilename;	/* for -outfile switch */
+
+
+LOCAL(void)
+usage (void)
+/* complain about bad command line */
+{
+  fprintf(stderr, "usage: %s [switches] inputfile(s)\n", progname);
+  fprintf(stderr, "List of input files may use wildcards (* and ?)\n");
+  fprintf(stderr, "Output filename is same as input filename, but extension .jpg\n");
+
+  fprintf(stderr, "Switches (names may be abbreviated):\n");
+  fprintf(stderr, "  -quality N[,...]   Compression quality (0..100; 5-95 is useful range)\n");
+  fprintf(stderr, "  -grayscale     Create monochrome JPEG file\n");
+  fprintf(stderr, "  -rgb           Create RGB JPEG file\n");
+#ifdef ENTROPY_OPT_SUPPORTED
+  fprintf(stderr, "  -optimize      Optimize Huffman table (smaller file, but slow compression)\n");
+#endif
+#ifdef C_PROGRESSIVE_SUPPORTED
+  fprintf(stderr, "  -progressive   Create progressive JPEG file\n");
+#endif
+#ifdef DCT_SCALING_SUPPORTED
+  fprintf(stderr, "  -scale M/N     Scale image by fraction M/N, eg, 1/2\n");
+#endif
+#ifdef TARGA_SUPPORTED
+  fprintf(stderr, "  -targa         Input file is Targa format (usually not needed)\n");
+#endif
+  fprintf(stderr, "Switches for advanced users:\n");
+#ifdef C_ARITH_CODING_SUPPORTED
+  fprintf(stderr, "  -arithmetic    Use arithmetic coding\n");
+#endif
+#ifdef DCT_SCALING_SUPPORTED
+  fprintf(stderr, "  -block N       DCT block size (1..16; default is 8)\n");
+#endif
+#if JPEG_LIB_VERSION_MAJOR >= 9
+  fprintf(stderr, "  -rgb1          Create RGB JPEG file with reversible color transform\n");
+  fprintf(stderr, "  -bgycc         Create big gamut YCC JPEG file\n");
+#endif
+#ifdef DCT_ISLOW_SUPPORTED
+  fprintf(stderr, "  -dct int       Use integer DCT method%s\n",
+	  (JDCT_DEFAULT == JDCT_ISLOW ? " (default)" : ""));
+#endif
+#ifdef DCT_IFAST_SUPPORTED
+  fprintf(stderr, "  -dct fast      Use fast integer DCT (less accurate)%s\n",
+	  (JDCT_DEFAULT == JDCT_IFAST ? " (default)" : ""));
+#endif
+#ifdef DCT_FLOAT_SUPPORTED
+  fprintf(stderr, "  -dct float     Use floating-point DCT method%s\n",
+	  (JDCT_DEFAULT == JDCT_FLOAT ? " (default)" : ""));
+#endif
+  fprintf(stderr, "  -nosmooth      Don't use high-quality downsampling\n");
+  fprintf(stderr, "  -restart N     Set restart interval in rows, or in blocks with B\n");
+#ifdef INPUT_SMOOTHING_SUPPORTED
+  fprintf(stderr, "  -smooth N      Smooth dithered input (N=1..100 is strength)\n");
+#endif
+#ifndef FREE_MEM_ESTIMATE
+  fprintf(stderr, "  -maxmemory N   Maximum memory to use (in kbytes)\n");
+#endif
+  fprintf(stderr, "  -outfile name  Specify name for output file\n");
+  fprintf(stderr, "  -verbose  or  -debug   Emit debug output\n");
+  fprintf(stderr, "Switches for wizards:\n");
+  fprintf(stderr, "  -baseline      Force baseline quantization tables\n");
+  fprintf(stderr, "  -qtables file  Use quantization tables given in file\n");
+  fprintf(stderr, "  -qslots N[,...]    Set component quantization tables\n");
+  fprintf(stderr, "  -sample HxV[,...]  Set component sampling factors\n");
+#ifdef C_MULTISCAN_FILES_SUPPORTED
+  fprintf(stderr, "  -scans file    Create multi-scan JPEG per script file\n");
+#endif
+  exit(EXIT_FAILURE);
+}
+
+
+LOCAL(int)
+parse_switches (j_compress_ptr cinfo, int argc, char **argv,
+		int last_file_arg_seen, boolean for_real)
+/* Parse optional switches.
+ * Returns argv[] index of first file-name argument (== argc if none).
+ * Any file names with indexes <= last_file_arg_seen are ignored;
+ * they have presumably been processed in a previous iteration.
+ * (Pass 0 for last_file_arg_seen on the first or only iteration.)
+ * for_real is FALSE on the first (dummy) pass; we may skip any expensive
+ * processing.
+ */
+{
+  int argn;
+  char * arg;
+  boolean force_baseline;
+  boolean simple_progressive;
+  char * qualityarg = NULL;	/* saves -quality parm if any */
+  char * qtablefile = NULL;	/* saves -qtables filename if any */
+  char * qslotsarg = NULL;	/* saves -qslots parm if any */
+  char * samplearg = NULL;	/* saves -sample parm if any */
+  char * scansarg = NULL;	/* saves -scans parm if any */
+
+  /* Set up default JPEG parameters. */
+
+  force_baseline = FALSE;	/* by default, allow 16-bit quantizers */
+  simple_progressive = FALSE;
+  is_targa = FALSE;
+  outfilename = NULL;
+  cinfo->err->trace_level = 0;
+  if (default_maxmem > 0)	/* override library's default value */
+    cinfo->mem->max_memory_to_use = default_maxmem;
+
+  /* Scan command line options, adjust parameters */
+
+  for (argn = 1; argn < argc; argn++) {
+    arg = argv[argn];
+    if (*arg != '-') {
+      /* Not a switch, must be a file name argument */
+      if (argn <= last_file_arg_seen) {
+	outfilename = NULL;	/* -outfile applies to just one input file */
+	continue;		/* ignore this name if previously processed */
+      }
+      break;			/* else done parsing switches */
+    }
+    arg++;			/* advance past switch marker character */
+
+    if (keymatch(arg, "arithmetic", 1)) {
+      /* Use arithmetic coding. */
+#ifdef C_ARITH_CODING_SUPPORTED
+      cinfo->arith_code = TRUE;
+#else
+      fprintf(stderr, "%s: sorry, arithmetic coding not supported\n",
+	      progname);
+      exit(EXIT_FAILURE);
+#endif
+
+    } else if (keymatch(arg, "baseline", 2)) {
+      /* Force baseline-compatible output (8-bit quantizer values). */
+      force_baseline = TRUE;
+
+    } else if (keymatch(arg, "block", 2)) {
+      /* Set DCT block size. */
+#if defined DCT_SCALING_SUPPORTED && JPEG_LIB_VERSION_MAJOR >= 8 && \
+      (JPEG_LIB_VERSION_MAJOR > 8 || JPEG_LIB_VERSION_MINOR >= 3)
+      int val;
+
+      if (++argn >= argc)	/* advance to next argument */
+	usage();
+      if (sscanf(argv[argn], "%d", &val) != 1)
+	usage();
+      if (val < 1 || val > 16)
+	usage();
+      cinfo->block_size = val;
+#else
+      fprintf(stderr, "%s: sorry, block size setting not supported\n",
+	      progname);
+      exit(EXIT_FAILURE);
+#endif
+
+    } else if (keymatch(arg, "dct", 2)) {
+      /* Select DCT algorithm. */
+      if (++argn >= argc)	/* advance to next argument */
+	usage();
+      if (keymatch(argv[argn], "int", 1)) {
+	cinfo->dct_method = JDCT_ISLOW;
+      } else if (keymatch(argv[argn], "fast", 2)) {
+	cinfo->dct_method = JDCT_IFAST;
+      } else if (keymatch(argv[argn], "float", 2)) {
+	cinfo->dct_method = JDCT_FLOAT;
+      } else
+	usage();
+
+    } else if (keymatch(arg, "debug", 1) || keymatch(arg, "verbose", 1)) {
+      /* Enable debug printouts. */
+      /* On first -d, print version identification */
+      static boolean printed_version = FALSE;
+
+      if (! printed_version) {
+	fprintf(stderr, "Independent JPEG Group's CJPEG, version %s\n%s\n",
+		JVERSION, JCOPYRIGHT);
+	printed_version = TRUE;
+      }
+      cinfo->err->trace_level++;
+
+    } else if (keymatch(arg, "grayscale", 2) || keymatch(arg, "greyscale",2)) {
+      /* Force a monochrome JPEG file to be generated. */
+      jpeg_set_colorspace(cinfo, JCS_GRAYSCALE);
+
+    } else if (keymatch(arg, "rgb", 3) || keymatch(arg, "rgb1", 4)) {
+      /* Force an RGB JPEG file to be generated. */
+#if JPEG_LIB_VERSION_MAJOR >= 9
+      /* Note: Entropy table assignment in jpeg_set_colorspace depends
+       * on color_transform.
+       */
+      cinfo->color_transform = arg[3] ? JCT_SUBTRACT_GREEN : JCT_NONE;
+#endif
+      jpeg_set_colorspace(cinfo, JCS_RGB);
+
+    } else if (keymatch(arg, "bgycc", 5)) {
+      /* Force a big gamut YCC JPEG file to be generated. */
+#if JPEG_LIB_VERSION_MAJOR >= 9 && \
+      (JPEG_LIB_VERSION_MAJOR > 9 || JPEG_LIB_VERSION_MINOR >= 1)
+      jpeg_set_colorspace(cinfo, JCS_BG_YCC);
+#else
+      fprintf(stderr, "%s: sorry, BG_YCC colorspace not supported\n",
+	      progname);
+      exit(EXIT_FAILURE);
+#endif
+
+    } else if (keymatch(arg, "maxmemory", 3)) {
+      /* Maximum memory in Kb (or Mb with 'm'). */
+      long lval;
+      char ch = 'x';
+
+      if (++argn >= argc)	/* advance to next argument */
+	usage();
+      if (sscanf(argv[argn], "%ld%c", &lval, &ch) < 1)
+	usage();
+      if (ch == 'm' || ch == 'M')
+	lval *= 1000L;
+      cinfo->mem->max_memory_to_use = lval * 1000L;
+
+    } else if (keymatch(arg, "nosmooth", 3)) {
+      /* Suppress fancy downsampling. */
+      cinfo->do_fancy_downsampling = FALSE;
+
+    } else if (keymatch(arg, "optimize", 1) || keymatch(arg, "optimise", 1)) {
+      /* Enable entropy parm optimization. */
+#ifdef ENTROPY_OPT_SUPPORTED
+      cinfo->optimize_coding = TRUE;
+#else
+      fprintf(stderr, "%s: sorry, entropy optimization was not compiled\n",
+	      progname);
+      exit(EXIT_FAILURE);
+#endif
+
+    } else if (keymatch(arg, "outfile", 4)) {
+      /* Set output file name. */
+      if (++argn >= argc)	/* advance to next argument */
+	usage();
+      outfilename = argv[argn];	/* save it away for later use */
+
+    } else if (keymatch(arg, "progressive", 1)) {
+      /* Select simple progressive mode. */
+#ifdef C_PROGRESSIVE_SUPPORTED
+      simple_progressive = TRUE;
+      /* We must postpone execution until num_components is known. */
+#else
+      fprintf(stderr, "%s: sorry, progressive output was not compiled\n",
+	      progname);
+      exit(EXIT_FAILURE);
+#endif
+
+    } else if (keymatch(arg, "quality", 1)) {
+      /* Quality ratings (quantization table scaling factors). */
+      if (++argn >= argc)	/* advance to next argument */
+	usage();
+      qualityarg = argv[argn];
+
+    } else if (keymatch(arg, "qslots", 2)) {
+      /* Quantization table slot numbers. */
+      if (++argn >= argc)	/* advance to next argument */
+	usage();
+      qslotsarg = argv[argn];
+      /* Must delay setting qslots until after we have processed any
+       * colorspace-determining switches, since jpeg_set_colorspace sets
+       * default quant table numbers.
+       */
+
+    } else if (keymatch(arg, "qtables", 2)) {
+      /* Quantization tables fetched from file. */
+      if (++argn >= argc)	/* advance to next argument */
+	usage();
+      qtablefile = argv[argn];
+      /* We postpone actually reading the file in case -quality comes later. */
+
+    } else if (keymatch(arg, "restart", 1)) {
+      /* Restart interval in MCU rows (or in MCUs with 'b'). */
+      long lval;
+      char ch = 'x';
+
+      if (++argn >= argc)	/* advance to next argument */
+	usage();
+      if (sscanf(argv[argn], "%ld%c", &lval, &ch) < 1)
+	usage();
+      if (lval < 0 || lval > 65535L)
+	usage();
+      if (ch == 'b' || ch == 'B') {
+	cinfo->restart_interval = (unsigned int) lval;
+	cinfo->restart_in_rows = 0; /* else prior '-restart n' overrides me */
+      } else {
+	cinfo->restart_in_rows = (int) lval;
+	/* restart_interval will be computed during startup */
+      }
+
+    } else if (keymatch(arg, "sample", 2)) {
+      /* Set sampling factors. */
+      if (++argn >= argc)	/* advance to next argument */
+	usage();
+      samplearg = argv[argn];
+      /* Must delay setting sample factors until after we have processed any
+       * colorspace-determining switches, since jpeg_set_colorspace sets
+       * default sampling factors.
+       */
+
+    } else if (keymatch(arg, "scale", 4)) {
+      /* Scale the image by a fraction M/N. */
+      if (++argn >= argc)	/* advance to next argument */
+	usage();
+      if (sscanf(argv[argn], "%d/%d",
+		 &cinfo->scale_num, &cinfo->scale_denom) != 2)
+	usage();
+
+    } else if (keymatch(arg, "scans", 4)) {
+      /* Set scan script. */
+#ifdef C_MULTISCAN_FILES_SUPPORTED
+      if (++argn >= argc)	/* advance to next argument */
+	usage();
+      scansarg = argv[argn];
+      /* We must postpone reading the file in case -progressive appears. */
+#else
+      fprintf(stderr, "%s: sorry, multi-scan output was not compiled\n",
+	      progname);
+      exit(EXIT_FAILURE);
+#endif
+
+    } else if (keymatch(arg, "smooth", 2)) {
+      /* Set input smoothing factor. */
+      int val;
+
+      if (++argn >= argc)	/* advance to next argument */
+	usage();
+      if (sscanf(argv[argn], "%d", &val) != 1)
+	usage();
+      if (val < 0 || val > 100)
+	usage();
+      cinfo->smoothing_factor = val;
+
+    } else if (keymatch(arg, "targa", 1)) {
+      /* Input file is Targa format. */
+      is_targa = TRUE;
+
+    } else {
+      usage();			/* bogus switch */
+    }
+  }
+
+  /* Post-switch-scanning cleanup */
+
+  if (for_real) {
+
+    /* Set quantization tables for selected quality. */
+    /* Some or all may be overridden if -qtables is present. */
+    if (qualityarg != NULL)	/* process -quality if it was present */
+      if (! set_quality_ratings(cinfo, qualityarg, force_baseline))
+	usage();
+
+    if (qtablefile != NULL)	/* process -qtables if it was present */
+      if (! read_quant_tables(cinfo, qtablefile, force_baseline))
+	usage();
+
+    if (qslotsarg != NULL)	/* process -qslots if it was present */
+      if (! set_quant_slots(cinfo, qslotsarg))
+	usage();
+
+    if (samplearg != NULL)	/* process -sample if it was present */
+      if (! set_sample_factors(cinfo, samplearg))
+	usage();
+
+#ifdef C_PROGRESSIVE_SUPPORTED
+    if (simple_progressive)	/* process -progressive; -scans can override */
+      jpeg_simple_progression(cinfo);
+#endif
+
+#ifdef C_MULTISCAN_FILES_SUPPORTED
+    if (scansarg != NULL)	/* process -scans if it was present */
+      if (! read_scan_script(cinfo, scansarg))
+	usage();
+#endif
+  }
+
+  return argn;			/* return index of next arg (file name) */
+}
+
+
+/*
+ * Check for overwrite of an existing file; clear it with user
+ */
+
+#ifndef NO_OVERWRITE_CHECK
+
+LOCAL(boolean)
+is_write_ok (char * outfname)
+{
+  FILE * ofile;
+  int ch;
+
+  ofile = fopen(outfname, READ_BINARY);
+  if (ofile == NULL)
+    return TRUE;		/* not present */
+  fclose(ofile);		/* oops, it is present */
+
+  for (;;) {
+    fprintf(stderr, "%s already exists, overwrite it? [y/n] ",
+	    outfname);
+    fflush(stderr);
+    ch = getc(stdin);
+    if (ch != '\n')		/* flush rest of line */
+      while (getc(stdin) != '\n')
+	/* nothing */;
+
+    switch (ch) {
+    case 'Y':
+    case 'y':
+      return TRUE;
+    case 'N':
+    case 'n':
+      return FALSE;
+    /* otherwise, ask again */
+    }
+  }
+}
+
+#endif
+
+
+/*
+ * Process a single input file name, and return its index in argv[].
+ * File names at or to left of old_file_index have been processed already.
+ */
+
+LOCAL(int)
+process_one_file (int argc, char **argv, int old_file_index)
+{
+  struct jpeg_compress_struct cinfo;
+  struct jpeg_error_mgr jerr;
+  char *infilename;
+  char workfilename[PATH_MAX];
+#ifdef PROGRESS_REPORT
+  struct cdjpeg_progress_mgr progress;
+#endif
+  int file_index;
+  cjpeg_source_ptr src_mgr;
+  FILE * input_file = NULL;
+  FILE * output_file = NULL;
+  JDIMENSION num_scanlines;
+
+  /* Initialize the JPEG compression object with default error handling. */
+  cinfo.err = jpeg_std_error(&jerr);
+  jpeg_create_compress(&cinfo);
+  /* Add some application-specific error messages (from cderror.h) */
+  jerr.addon_message_table = cdjpeg_message_table;
+  jerr.first_addon_message = JMSG_FIRSTADDONCODE;
+  jerr.last_addon_message = JMSG_LASTADDONCODE;
+
+  /* Now safe to enable signal catcher. */
+#ifdef NEED_SIGNAL_CATCHER
+  enable_signal_catcher((j_common_ptr) &cinfo);
+#endif
+
+  /* Initialize JPEG parameters.
+   * Much of this may be overridden later.
+   * In particular, we don't yet know the input file's color space,
+   * but we need to provide some value for jpeg_set_defaults() to work.
+   */
+
+  cinfo.in_color_space = JCS_RGB; /* arbitrary guess */
+  jpeg_set_defaults(&cinfo);
+
+  /* Scan command line to find next file name.
+   * It is convenient to use just one switch-parsing routine, but the switch
+   * values read here are ignored; we will rescan the switches after opening
+   * the input file.
+   */
+
+  file_index = parse_switches(&cinfo, argc, argv, old_file_index, FALSE);
+  if (file_index >= argc) {
+    fprintf(stderr, "%s: missing input file name\n", progname);
+    usage();
+  }
+
+  /* Open the input file. */
+  infilename = argv[file_index];
+  if ((input_file = fopen(infilename, READ_BINARY)) == NULL) {
+    fprintf(stderr, "%s: can't open %s\n", progname, infilename);
+    goto fail;
+  }
+
+#ifdef PROGRESS_REPORT
+  start_progress_monitor((j_common_ptr) &cinfo, &progress);
+#endif
+
+  /* Figure out the input file format, and set up to read it. */
+  src_mgr = select_file_type(&cinfo, input_file);
+  src_mgr->input_file = input_file;
+
+  /* Read the input file header to obtain file size & colorspace. */
+  (*src_mgr->start_input) (&cinfo, src_mgr);
+
+  /* Now that we know input colorspace, fix colorspace-dependent defaults */
+  jpeg_default_colorspace(&cinfo);
+
+  /* Adjust default compression parameters by re-parsing the options */
+  file_index = parse_switches(&cinfo, argc, argv, old_file_index, TRUE);
+
+  /* If user didn't supply -outfile switch, select output file name. */
+  if (outfilename == NULL) {
+    int i;
+
+    outfilename = workfilename;
+    /* Make outfilename be infilename with .jpg substituted for extension */
+    strcpy(outfilename, infilename);
+    for (i = (int)strlen(outfilename)-1; i >= 0; i--) {
+      switch (outfilename[i]) {
+      case ':':
+      case '/':
+      case '\\':
+	i = 0;			/* stop scanning */
+	break;
+      case '.':
+	outfilename[i] = '\0';	/* lop off existing extension */
+	i = 0;			/* stop scanning */
+	break;
+      default:
+	break;			/* keep scanning */
+      }
+    }
+    strcat(outfilename, ".jpg");
+  }
+
+  fprintf(stderr, "Compressing %s => %s\n", infilename, outfilename);
+#ifndef NO_OVERWRITE_CHECK
+  if (! is_write_ok(outfilename))
+    goto fail;
+#endif
+
+  /* Open the output file. */
+  if ((output_file = fopen(outfilename, WRITE_BINARY)) == NULL) {
+    fprintf(stderr, "%s: can't create %s\n", progname, outfilename);
+    goto fail;
+  }
+
+  /* Specify data destination for compression */
+  jpeg_stdio_dest(&cinfo, output_file);
+
+  /* Start compressor */
+  jpeg_start_compress(&cinfo, TRUE);
+
+  /* Process data */
+  while (cinfo.next_scanline < cinfo.image_height) {
+    num_scanlines = (*src_mgr->get_pixel_rows) (&cinfo, src_mgr);
+    (void) jpeg_write_scanlines(&cinfo, src_mgr->buffer, num_scanlines);
+  }
+
+  /* Finish compression and release memory */
+  (*src_mgr->finish_input) (&cinfo, src_mgr);
+  jpeg_finish_compress(&cinfo);
+
+  /* Clean up and exit */
+fail:
+  jpeg_destroy_compress(&cinfo);
+
+  if (input_file != NULL) fclose(input_file);
+  if (output_file != NULL) fclose(output_file);
+
+#ifdef PROGRESS_REPORT
+  end_progress_monitor((j_common_ptr) &cinfo);
+#endif
+
+  /* Disable signal catcher. */
+#ifdef NEED_SIGNAL_CATCHER
+  enable_signal_catcher((j_common_ptr) NULL);
+#endif
+
+  return file_index;
+}
+
+
+/*
+ * The main program.
+ */
+
+int
+main (int argc, char **argv)
+{
+  int file_index;
+
+  /* On Mac, fetch a command line. */
+#ifdef USE_CCOMMAND
+  argc = ccommand(&argv);
+#endif
+
+#ifdef MSDOS
+  progname = "cjpeg";		/* DOS tends to be too verbose about argv[0] */
+#else
+  progname = argv[0];
+  if (progname == NULL || progname[0] == 0)
+    progname = "cjpeg";		/* in case C library doesn't provide it */
+#endif
+
+  /* The default maxmem must be computed only once at program startup,
+   * since releasing memory with free() won't give it back to the OS.
+   */
+#ifdef FREE_MEM_ESTIMATE
+  default_maxmem = FREE_MEM_ESTIMATE;
+#else
+  default_maxmem = 0;
+#endif
+
+  /* Scan command line, parse switches and locate input file names */
+
+  if (argc < 2)
+    usage();			/* nothing on the command line?? */
+
+  file_index = 0;
+
+  while (file_index < argc-1)
+    file_index = process_one_file(argc, argv, file_index);
+
+  /* All done. */
+  exit(EXIT_SUCCESS);
+  return 0;			/* suppress no-return-value warnings */
+}
diff --git a/vendor/jpeg-9e/ckconfig.c b/vendor/jpeg-9f/ckconfig.c
similarity index 100%
rename from vendor/jpeg-9e/ckconfig.c
rename to vendor/jpeg-9f/ckconfig.c
diff --git a/vendor/jpeg-9e/djpeg.c b/vendor/jpeg-9f/djpeg.c
similarity index 100%
rename from vendor/jpeg-9e/djpeg.c
rename to vendor/jpeg-9f/djpeg.c
diff --git a/vendor/jpeg-9f/djpegalt.c b/vendor/jpeg-9f/djpegalt.c
new file mode 100644
index 0000000000..969c58b49c
--- /dev/null
+++ b/vendor/jpeg-9f/djpegalt.c
@@ -0,0 +1,766 @@
+/*
+ * alternate djpeg.c
+ *
+ * Copyright (C) 1991-1997, Thomas G. Lane.
+ * Modified 2009-2023 by Guido Vollbeding.
+ * This file is part of the Independent JPEG Group's software.
+ * For conditions of distribution and use, see the accompanying README file.
+ *
+ * This file contains an alternate user interface for the JPEG decompressor.
+ * One or more input files are named on the command line, and output file
+ * names are created by substituting an appropriate extension.
+ */
+
+#include "cdjpeg.h"		/* Common decls for cjpeg/djpeg applications */
+#include "jversion.h"		/* for version message */
+
+#include 		/* to declare isprint() */
+
+#ifdef USE_CCOMMAND		/* command-line reader for Macintosh */
+#ifdef __MWERKS__
+#include               /* Metrowerks needs this */
+#include 		/* ... and this */
+#endif
+#ifdef THINK_C
+#include 		/* Think declares it here */
+#endif
+#endif
+
+#ifndef PATH_MAX		/* ANSI maximum-pathname-length constant */
+#define PATH_MAX 256
+#endif
+
+
+/* Create the add-on message string table. */
+
+#define JMESSAGE(code,string)	string ,
+
+static const char * const cdjpeg_message_table[] = {
+#include "cderror.h"
+  NULL
+};
+
+
+/*
+ * Automatic determination of available memory.
+ */
+
+static long default_maxmem;	/* saves value determined at startup, or 0 */
+
+#ifndef FREE_MEM_ESTIMATE	/* may be defined from command line */
+
+#ifdef MSDOS			/* For MS-DOS (unless flat-memory model) */
+
+#include 		/* for access to intdos() call */
+
+LOCAL(long)
+unused_dos_memory (void)
+/* Obtain total amount of unallocated DOS memory */
+{
+  union REGS regs;
+  long nparas;
+
+  regs.h.ah = 0x48;		/* DOS function Allocate Memory Block */
+  regs.x.bx = 0xFFFF;		/* Ask for more memory than DOS can have */
+  (void) intdos(®s, ®s);
+  /* DOS will fail and return # of paragraphs actually available in BX. */
+  nparas = (unsigned int) regs.x.bx;
+  /* Times 16 to convert to bytes. */
+  return nparas << 4;
+}
+
+/* The default memory setting is 95% of the available space. */
+#define FREE_MEM_ESTIMATE  ((unused_dos_memory() * 95L) / 100L)
+
+#endif /* MSDOS */
+
+#ifdef ATARI	/* For Atari ST/Mega/STE/TT/Falcon, Pure C or Turbo C */
+
+#include 
+
+/* The default memory setting is 90% of the available space. */
+#define FREE_MEM_ESTIMATE  (((long) coreleft() * 90L) / 100L)
+
+#endif /* ATARI */
+
+/* Add memory-estimation procedures for other operating systems here,
+ * with appropriate #ifdef's around them.
+ */
+
+#endif /* !FREE_MEM_ESTIMATE */
+
+
+/*
+ * This list defines the known output image formats
+ * (not all of which need be supported by a given version).
+ * You can change the default output format by defining DEFAULT_FMT;
+ * indeed, you had better do so if you undefine PPM_SUPPORTED.
+ */
+
+typedef enum {
+	FMT_BMP,		/* BMP format (Windows flavor) */
+	FMT_GIF,		/* GIF format (LZW compressed) */
+	FMT_GIF0,		/* GIF format (uncompressed) */
+	FMT_OS2,		/* BMP format (OS/2 flavor) */
+	FMT_PPM,		/* PPM/PGM (PBMPLUS formats) */
+	FMT_RLE,		/* RLE format */
+	FMT_TARGA,		/* Targa format */
+	FMT_TIFF		/* TIFF format */
+} IMAGE_FORMATS;
+
+#ifndef DEFAULT_FMT		/* so can override from CFLAGS in Makefile */
+#define DEFAULT_FMT	FMT_BMP
+#endif
+
+static IMAGE_FORMATS requested_fmt;
+
+
+/*
+ * Argument-parsing code.
+ * The switch parser is designed to be useful with DOS-style command line
+ * syntax, ie, intermixed switches and file names, where only the switches
+ * to the left of a given file name affect processing of that file.
+ */
+
+
+static const char * progname;	/* program name for error messages */
+static char * outfilename;	/* for -outfile switch */
+
+
+LOCAL(void)
+usage (void)
+/* complain about bad command line */
+{
+  fprintf(stderr, "usage: %s [switches] inputfile(s)\n", progname);
+  fprintf(stderr, "List of input files may use wildcards (* and ?)\n");
+  fprintf(stderr, "Output filename is same as input filename except for extension\n");
+
+  fprintf(stderr, "Switches (names may be abbreviated):\n");
+  fprintf(stderr, "  -colors N      Reduce image to no more than N colors\n");
+  fprintf(stderr, "  -fast          Fast, low-quality processing\n");
+  fprintf(stderr, "  -grayscale     Force grayscale output\n");
+  fprintf(stderr, "  -rgb           Force RGB output\n");
+#ifdef IDCT_SCALING_SUPPORTED
+  fprintf(stderr, "  -scale M/N     Scale output image by fraction M/N, eg, 1/8\n");
+#endif
+#ifdef BMP_SUPPORTED
+  fprintf(stderr, "  -bmp           Select BMP output format (Windows style)%s\n",
+	  (DEFAULT_FMT == FMT_BMP ? " (default)" : ""));
+#endif
+#ifdef GIF_SUPPORTED
+  fprintf(stderr, "  -gif           Select GIF output format (LZW compressed)%s\n",
+	  (DEFAULT_FMT == FMT_GIF ? " (default)" : ""));
+  fprintf(stderr, "  -gif0          Select GIF output format (uncompressed)%s\n",
+	  (DEFAULT_FMT == FMT_GIF0 ? " (default)" : ""));
+#endif
+#ifdef BMP_SUPPORTED
+  fprintf(stderr, "  -os2           Select BMP output format (OS/2 style)%s\n",
+	  (DEFAULT_FMT == FMT_OS2 ? " (default)" : ""));
+#endif
+#ifdef PPM_SUPPORTED
+  fprintf(stderr, "  -pnm           Select PBMPLUS (PPM/PGM) output format%s\n",
+	  (DEFAULT_FMT == FMT_PPM ? " (default)" : ""));
+#endif
+#ifdef RLE_SUPPORTED
+  fprintf(stderr, "  -rle           Select Utah RLE output format%s\n",
+	  (DEFAULT_FMT == FMT_RLE ? " (default)" : ""));
+#endif
+#ifdef TARGA_SUPPORTED
+  fprintf(stderr, "  -targa         Select Targa output format%s\n",
+	  (DEFAULT_FMT == FMT_TARGA ? " (default)" : ""));
+#endif
+  fprintf(stderr, "Switches for advanced users:\n");
+#ifdef DCT_ISLOW_SUPPORTED
+  fprintf(stderr, "  -dct int       Use integer DCT method%s\n",
+	  (JDCT_DEFAULT == JDCT_ISLOW ? " (default)" : ""));
+#endif
+#ifdef DCT_IFAST_SUPPORTED
+  fprintf(stderr, "  -dct fast      Use fast integer DCT (less accurate)%s\n",
+	  (JDCT_DEFAULT == JDCT_IFAST ? " (default)" : ""));
+#endif
+#ifdef DCT_FLOAT_SUPPORTED
+  fprintf(stderr, "  -dct float     Use floating-point DCT method%s\n",
+	  (JDCT_DEFAULT == JDCT_FLOAT ? " (default)" : ""));
+#endif
+  fprintf(stderr, "  -dither fs     Use F-S dithering (default)\n");
+  fprintf(stderr, "  -dither none   Don't use dithering in quantization\n");
+  fprintf(stderr, "  -dither ordered  Use ordered dither (medium speed, quality)\n");
+#ifdef QUANT_2PASS_SUPPORTED
+  fprintf(stderr, "  -map FILE      Map to colors used in named image file\n");
+#endif
+  fprintf(stderr, "  -nosmooth      Don't use high-quality upsampling\n");
+#ifdef QUANT_1PASS_SUPPORTED
+  fprintf(stderr, "  -onepass       Use 1-pass quantization (fast, low quality)\n");
+#endif
+#ifndef FREE_MEM_ESTIMATE
+  fprintf(stderr, "  -maxmemory N   Maximum memory to use (in kbytes)\n");
+#endif
+  fprintf(stderr, "  -outfile name  Specify name for output file\n");
+  fprintf(stderr, "  -verbose  or  -debug   Emit debug output\n");
+  exit(EXIT_FAILURE);
+}
+
+
+LOCAL(int)
+parse_switches (j_decompress_ptr cinfo, int argc, char **argv,
+		int last_file_arg_seen, boolean for_real)
+/* Parse optional switches.
+ * Returns argv[] index of first file-name argument (== argc if none).
+ * Any file names with indexes <= last_file_arg_seen are ignored;
+ * they have presumably been processed in a previous iteration.
+ * (Pass 0 for last_file_arg_seen on the first or only iteration.)
+ * for_real is FALSE on the first (dummy) pass; we may skip any expensive
+ * processing.
+ */
+{
+  int argn;
+  char * arg;
+
+  /* Set up default JPEG parameters. */
+  requested_fmt = DEFAULT_FMT;	/* set default output file format */
+  outfilename = NULL;
+  cinfo->err->trace_level = 0;
+  if (default_maxmem > 0)	/* override library's default value */
+    cinfo->mem->max_memory_to_use = default_maxmem;
+
+  /* Scan command line options, adjust parameters */
+
+  for (argn = 1; argn < argc; argn++) {
+    arg = argv[argn];
+    if (*arg != '-') {
+      /* Not a switch, must be a file name argument */
+      if (argn <= last_file_arg_seen) {
+	outfilename = NULL;	/* -outfile applies to just one input file */
+	continue;		/* ignore this name if previously processed */
+      }
+      break;			/* else done parsing switches */
+    }
+    arg++;			/* advance past switch marker character */
+
+    if (keymatch(arg, "bmp", 1)) {
+      /* BMP output format (Windows flavor). */
+      requested_fmt = FMT_BMP;
+
+    } else if (keymatch(arg, "colors", 1) || keymatch(arg, "colours", 1) ||
+	       keymatch(arg, "quantize", 1) || keymatch(arg, "quantise", 1)) {
+      /* Do color quantization. */
+      int val;
+
+      if (++argn >= argc)	/* advance to next argument */
+	usage();
+      if (sscanf(argv[argn], "%d", &val) != 1)
+	usage();
+      cinfo->desired_number_of_colors = val;
+      cinfo->quantize_colors = TRUE;
+
+    } else if (keymatch(arg, "dct", 2)) {
+      /* Select IDCT algorithm. */
+      if (++argn >= argc)	/* advance to next argument */
+	usage();
+      if (keymatch(argv[argn], "int", 1)) {
+	cinfo->dct_method = JDCT_ISLOW;
+      } else if (keymatch(argv[argn], "fast", 2)) {
+	cinfo->dct_method = JDCT_IFAST;
+      } else if (keymatch(argv[argn], "float", 2)) {
+	cinfo->dct_method = JDCT_FLOAT;
+      } else
+	usage();
+
+    } else if (keymatch(arg, "dither", 2)) {
+      /* Select dithering algorithm. */
+      if (++argn >= argc)	/* advance to next argument */
+	usage();
+      if (keymatch(argv[argn], "fs", 2)) {
+	cinfo->dither_mode = JDITHER_FS;
+      } else if (keymatch(argv[argn], "none", 2)) {
+	cinfo->dither_mode = JDITHER_NONE;
+      } else if (keymatch(argv[argn], "ordered", 2)) {
+	cinfo->dither_mode = JDITHER_ORDERED;
+      } else
+	usage();
+
+    } else if (keymatch(arg, "debug", 1) || keymatch(arg, "verbose", 1)) {
+      /* Enable debug printouts. */
+      /* On first -d, print version identification */
+      static boolean printed_version = FALSE;
+
+      if (! printed_version) {
+	fprintf(stderr, "Independent JPEG Group's DJPEG, version %s\n%s\n",
+		JVERSION, JCOPYRIGHT);
+	printed_version = TRUE;
+      }
+      cinfo->err->trace_level++;
+
+    } else if (keymatch(arg, "fast", 1)) {
+      /* Select recommended processing options for quick-and-dirty output. */
+      cinfo->two_pass_quantize = FALSE;
+      cinfo->dither_mode = JDITHER_ORDERED;
+      if (! cinfo->quantize_colors) /* don't override an earlier -colors */
+	cinfo->desired_number_of_colors = 216;
+      cinfo->dct_method = JDCT_FASTEST;
+      cinfo->do_fancy_upsampling = FALSE;
+
+    } else if (keymatch(arg, "gif", 1)) {
+      /* GIF output format (LZW compressed). */
+      requested_fmt = FMT_GIF;
+
+    } else if (keymatch(arg, "gif0", 4)) {
+      /* GIF output format (uncompressed). */
+      requested_fmt = FMT_GIF0;
+
+    } else if (keymatch(arg, "grayscale", 2) || keymatch(arg, "greyscale",2)) {
+      /* Force monochrome output. */
+      cinfo->out_color_space = JCS_GRAYSCALE;
+
+    } else if (keymatch(arg, "rgb", 3)) {
+      /* Force RGB output. */
+      cinfo->out_color_space = JCS_RGB;
+
+    } else if (keymatch(arg, "map", 3)) {
+      /* Quantize to a color map taken from an input file. */
+      if (++argn >= argc)	/* advance to next argument */
+	usage();
+      if (for_real) {		/* too expensive to do twice! */
+#ifdef QUANT_2PASS_SUPPORTED	/* otherwise can't quantize to supplied map */
+	FILE * mapfile;
+
+	if ((mapfile = fopen(argv[argn], READ_BINARY)) == NULL) {
+	  fprintf(stderr, "%s: can't open %s\n", progname, argv[argn]);
+	  exit(EXIT_FAILURE);
+	}
+	read_color_map(cinfo, mapfile);
+	fclose(mapfile);
+	cinfo->quantize_colors = TRUE;
+#else
+	ERREXIT(cinfo, JERR_NOT_COMPILED);
+#endif
+      }
+
+    } else if (keymatch(arg, "maxmemory", 3)) {
+      /* Maximum memory in Kb (or Mb with 'm'). */
+      long lval;
+      char ch = 'x';
+
+      if (++argn >= argc)	/* advance to next argument */
+	usage();
+      if (sscanf(argv[argn], "%ld%c", &lval, &ch) < 1)
+	usage();
+      if (ch == 'm' || ch == 'M')
+	lval *= 1000L;
+      cinfo->mem->max_memory_to_use = lval * 1000L;
+
+    } else if (keymatch(arg, "nosmooth", 3)) {
+      /* Suppress fancy upsampling. */
+      cinfo->do_fancy_upsampling = FALSE;
+
+    } else if (keymatch(arg, "onepass", 3)) {
+      /* Use fast one-pass quantization. */
+      cinfo->two_pass_quantize = FALSE;
+
+    } else if (keymatch(arg, "os2", 3)) {
+      /* BMP output format (OS/2 flavor). */
+      requested_fmt = FMT_OS2;
+
+    } else if (keymatch(arg, "outfile", 4)) {
+      /* Set output file name. */
+      if (++argn >= argc)	/* advance to next argument */
+	usage();
+      outfilename = argv[argn];	/* save it away for later use */
+
+    } else if (keymatch(arg, "pnm", 1) || keymatch(arg, "ppm", 1)) {
+      /* PPM/PGM output format. */
+      requested_fmt = FMT_PPM;
+
+    } else if (keymatch(arg, "rle", 1)) {
+      /* RLE output format. */
+      requested_fmt = FMT_RLE;
+
+    } else if (keymatch(arg, "scale", 1)) {
+      /* Scale the output image by a fraction M/N. */
+      if (++argn >= argc)	/* advance to next argument */
+	usage();
+      if (sscanf(argv[argn], "%u/%u",
+		 &cinfo->scale_num, &cinfo->scale_denom) < 1)
+	usage();
+
+    } else if (keymatch(arg, "targa", 1)) {
+      /* Targa output format. */
+      requested_fmt = FMT_TARGA;
+
+    } else {
+      usage();			/* bogus switch */
+    }
+  }
+
+  return argn;			/* return index of next arg (file name) */
+}
+
+
+/*
+ * Marker processor for COM and interesting APPn markers.
+ * This replaces the library's built-in processor, which just skips the marker.
+ * We want to print out the marker as text, to the extent possible.
+ * Note this code relies on a non-suspending data source.
+ */
+
+LOCAL(unsigned int)
+jpeg_getc (j_decompress_ptr cinfo)
+/* Read next byte */
+{
+  struct jpeg_source_mgr * datasrc = cinfo->src;
+
+  if (datasrc->bytes_in_buffer == 0) {
+    if (! (*datasrc->fill_input_buffer) (cinfo))
+      ERREXIT(cinfo, JERR_CANT_SUSPEND);
+  }
+  datasrc->bytes_in_buffer--;
+  return GETJOCTET(*datasrc->next_input_byte++);
+}
+
+
+METHODDEF(boolean)
+print_text_marker (j_decompress_ptr cinfo)
+{
+  boolean traceit = (cinfo->err->trace_level >= 1);
+  INT32 length;
+  unsigned int ch;
+  unsigned int lastch = 0;
+
+  length = jpeg_getc(cinfo) << 8;
+  length += jpeg_getc(cinfo);
+  length -= 2;			/* discount the length word itself */
+
+  if (traceit) {
+    if (cinfo->unread_marker == JPEG_COM)
+      fprintf(stderr, "Comment, length %ld:\n", (long) length);
+    else			/* assume it is an APPn otherwise */
+      fprintf(stderr, "APP%d, length %ld:\n",
+	      cinfo->unread_marker - JPEG_APP0, (long) length);
+  }
+
+  while (--length >= 0) {
+    ch = jpeg_getc(cinfo);
+    if (traceit) {
+      /* Emit the character in a readable form.
+       * Nonprintables are converted to \nnn form,
+       * while \ is converted to \\.
+       * Newlines in CR, CR/LF, or LF form will be printed as one newline.
+       */
+      if (ch == '\r') {
+	fprintf(stderr, "\n");
+      } else if (ch == '\n') {
+	if (lastch != '\r')
+	  fprintf(stderr, "\n");
+      } else if (ch == '\\') {
+	fprintf(stderr, "\\\\");
+      } else if (isprint(ch)) {
+	putc(ch, stderr);
+      } else {
+	fprintf(stderr, "\\%03o", ch);
+      }
+      lastch = ch;
+    }
+  }
+
+  if (traceit)
+    fprintf(stderr, "\n");
+
+  return TRUE;
+}
+
+
+/*
+ * Check for overwrite of an existing file; clear it with user
+ */
+
+#ifndef NO_OVERWRITE_CHECK
+
+LOCAL(boolean)
+is_write_ok (char * outfname)
+{
+  FILE * ofile;
+  int ch;
+
+  ofile = fopen(outfname, READ_BINARY);
+  if (ofile == NULL)
+    return TRUE;		/* not present */
+  fclose(ofile);		/* oops, it is present */
+
+  for (;;) {
+    fprintf(stderr, "%s already exists, overwrite it? [y/n] ",
+	    outfname);
+    fflush(stderr);
+    ch = getc(stdin);
+    if (ch != '\n')		/* flush rest of line */
+      while (getc(stdin) != '\n')
+	/* nothing */;
+
+    switch (ch) {
+    case 'Y':
+    case 'y':
+      return TRUE;
+    case 'N':
+    case 'n':
+      return FALSE;
+    /* otherwise, ask again */
+    }
+  }
+}
+
+#endif
+
+
+/*
+ * Process a single input file name, and return its index in argv[].
+ * File names at or to left of old_file_index have been processed already.
+ */
+
+LOCAL(int)
+process_one_file (int argc, char **argv, int old_file_index)
+{
+  struct jpeg_decompress_struct cinfo;
+  struct jpeg_error_mgr jerr;
+  char *infilename;
+  char workfilename[PATH_MAX];
+  const char *default_extension = NULL;
+#ifdef PROGRESS_REPORT
+  struct cdjpeg_progress_mgr progress;
+#endif
+  int file_index;
+  djpeg_dest_ptr dest_mgr = NULL;
+  FILE * input_file = NULL;
+  FILE * output_file = NULL;
+  JDIMENSION num_scanlines;
+
+  /* Initialize the JPEG decompression object with default error handling. */
+  cinfo.err = jpeg_std_error(&jerr);
+  jpeg_create_decompress(&cinfo);
+  /* Add some application-specific error messages (from cderror.h) */
+  jerr.addon_message_table = cdjpeg_message_table;
+  jerr.first_addon_message = JMSG_FIRSTADDONCODE;
+  jerr.last_addon_message = JMSG_LASTADDONCODE;
+
+  /* Insert custom marker processor for COM and APP12.
+   * APP12 is used by some digital camera makers for textual info,
+   * so we provide the ability to display it as text.
+   * If you like, additional APPn marker types can be selected for display,
+   * but don't try to override APP0 or APP14 this way (see libjpeg.txt).
+   */
+  jpeg_set_marker_processor(&cinfo, JPEG_COM, print_text_marker);
+  jpeg_set_marker_processor(&cinfo, JPEG_APP0+12, print_text_marker);
+
+  /* Now safe to enable signal catcher. */
+#ifdef NEED_SIGNAL_CATCHER
+  enable_signal_catcher((j_common_ptr) &cinfo);
+#endif
+
+  /* Scan command line to find next file name.
+   * It is convenient to use just one switch-parsing routine, but the switch
+   * values read here are ignored; we will rescan the switches after opening
+   * the input file.
+   * (Exception: tracing level set here controls verbosity for COM markers
+   * found during jpeg_read_header...)
+   */
+
+  file_index = parse_switches(&cinfo, argc, argv, old_file_index, FALSE);
+  if (file_index >= argc) {
+    fprintf(stderr, "%s: missing input file name\n", progname);
+    usage();
+  }
+
+  /* Open the input file. */
+  infilename = argv[file_index];
+  if ((input_file = fopen(infilename, READ_BINARY)) == NULL) {
+    fprintf(stderr, "%s: can't open %s\n", progname, infilename);
+    goto fail;
+  }
+
+#ifdef PROGRESS_REPORT
+  start_progress_monitor((j_common_ptr) &cinfo, &progress);
+#endif
+
+  /* Specify data source for decompression */
+  jpeg_stdio_src(&cinfo, input_file);
+
+  /* Read file header, set default decompression parameters */
+  (void) jpeg_read_header(&cinfo, TRUE);
+
+  /* Adjust default decompression parameters by re-parsing the options */
+  file_index = parse_switches(&cinfo, argc, argv, old_file_index, TRUE);
+
+  /* Initialize the output module now to let it override any crucial
+   * option settings (for instance, GIF wants to force color quantization).
+   */
+  switch (requested_fmt) {
+#ifdef BMP_SUPPORTED
+  case FMT_BMP:
+    dest_mgr = jinit_write_bmp(&cinfo, FALSE);
+    default_extension = ".bmp";
+    break;
+  case FMT_OS2:
+    dest_mgr = jinit_write_bmp(&cinfo, TRUE);
+    default_extension = ".bmp";
+    break;
+#endif
+#ifdef GIF_SUPPORTED
+  case FMT_GIF:
+    dest_mgr = jinit_write_gif(&cinfo, TRUE);
+    default_extension = ".gif";
+    break;
+  case FMT_GIF0:
+    dest_mgr = jinit_write_gif(&cinfo, FALSE);
+    default_extension = ".gif";
+    break;
+#endif
+#ifdef PPM_SUPPORTED
+  case FMT_PPM:
+    dest_mgr = jinit_write_ppm(&cinfo);
+    default_extension = ".ppm";
+    break;
+#endif
+#ifdef RLE_SUPPORTED
+  case FMT_RLE:
+    dest_mgr = jinit_write_rle(&cinfo);
+    default_extension = ".rle";
+    break;
+#endif
+#ifdef TARGA_SUPPORTED
+  case FMT_TARGA:
+    dest_mgr = jinit_write_targa(&cinfo);
+    default_extension = ".tga";
+    break;
+#endif
+  default:
+    ERREXIT(&cinfo, JERR_UNSUPPORTED_FORMAT);
+  }
+
+  /* If user didn't supply -outfile switch, select output file name. */
+  if (outfilename == NULL) {
+    int i;
+
+    outfilename = workfilename;
+    /* Make outfilename be infilename with appropriate extension */
+    strcpy(outfilename, infilename);
+    for (i = (int)strlen(outfilename)-1; i >= 0; i--) {
+      switch (outfilename[i]) {
+      case ':':
+      case '/':
+      case '\\':
+	i = 0;			/* stop scanning */
+	break;
+      case '.':
+	outfilename[i] = '\0';	/* lop off existing extension */
+	i = 0;			/* stop scanning */
+	break;
+      default:
+	break;			/* keep scanning */
+      }
+    }
+    strcat(outfilename, default_extension);
+  }
+
+  fprintf(stderr, "Decompressing %s => %s\n", infilename, outfilename);
+#ifndef NO_OVERWRITE_CHECK
+  if (! is_write_ok(outfilename))
+    goto fail;
+#endif
+
+  /* Open the output file. */
+  if ((output_file = fopen(outfilename, WRITE_BINARY)) == NULL) {
+    fprintf(stderr, "%s: can't create %s\n", progname, outfilename);
+    goto fail;
+  }
+  dest_mgr->output_file = output_file;
+
+  /* Start decompressor */
+  (void) jpeg_start_decompress(&cinfo);
+
+  /* Write output file header */
+  (*dest_mgr->start_output) (&cinfo, dest_mgr);
+
+  /* Process data */
+  while (cinfo.output_scanline < cinfo.output_height) {
+    num_scanlines = jpeg_read_scanlines(&cinfo, dest_mgr->buffer,
+					dest_mgr->buffer_height);
+    (*dest_mgr->put_pixel_rows) (&cinfo, dest_mgr, num_scanlines);
+  }
+
+#ifdef PROGRESS_REPORT
+  /* Hack: count final pass as done in case finish_output does an extra pass.
+   * The library won't have updated completed_passes.
+   */
+  progress.pub.completed_passes = progress.pub.total_passes;
+#endif
+
+  /* Finish decompression and release memory.
+   * I must do it in this order because output module has allocated memory
+   * of lifespan JPOOL_IMAGE; it needs to finish before releasing memory.
+   */
+  (*dest_mgr->finish_output) (&cinfo, dest_mgr);
+  (void) jpeg_finish_decompress(&cinfo);
+
+  /* Clean up and exit */
+fail:
+  jpeg_destroy_decompress(&cinfo);
+
+  if (input_file != NULL) fclose(input_file);
+  if (output_file != NULL) fclose(output_file);
+
+#ifdef PROGRESS_REPORT
+  end_progress_monitor((j_common_ptr) &cinfo);
+#endif
+
+  /* Disable signal catcher. */
+#ifdef NEED_SIGNAL_CATCHER
+  enable_signal_catcher((j_common_ptr) NULL);
+#endif
+
+  return file_index;
+}
+
+
+/*
+ * The main program.
+ */
+
+int
+main (int argc, char **argv)
+{
+  int file_index;
+
+  /* On Mac, fetch a command line. */
+#ifdef USE_CCOMMAND
+  argc = ccommand(&argv);
+#endif
+
+#ifdef MSDOS
+  progname = "djpeg";		/* DOS tends to be too verbose about argv[0] */
+#else
+  progname = argv[0];
+  if (progname == NULL || progname[0] == 0)
+    progname = "djpeg";		/* in case C library doesn't provide it */
+#endif
+
+  /* The default maxmem must be computed only once at program startup,
+   * since releasing memory with free() won't give it back to the OS.
+   */
+#ifdef FREE_MEM_ESTIMATE
+  default_maxmem = FREE_MEM_ESTIMATE;
+#else
+  default_maxmem = 0;
+#endif
+
+  /* Scan command line, parse switches and locate input file names */
+
+  if (argc < 2)
+    usage();			/* nothing on the command line?? */
+
+  file_index = 0;
+
+  while (file_index < argc-1)
+    file_index = process_one_file(argc, argv, file_index);
+
+  /* All done. */
+  exit(EXIT_SUCCESS);
+  return 0;			/* suppress no-return-value warnings */
+}
diff --git a/vendor/jpeg-9e/example.c b/vendor/jpeg-9f/example.c
similarity index 100%
rename from vendor/jpeg-9e/example.c
rename to vendor/jpeg-9f/example.c
diff --git a/vendor/jpeg-9e/jaricom.c b/vendor/jpeg-9f/jaricom.c
similarity index 100%
rename from vendor/jpeg-9e/jaricom.c
rename to vendor/jpeg-9f/jaricom.c
diff --git a/vendor/jpeg-9e/jcapimin.c b/vendor/jpeg-9f/jcapimin.c
similarity index 100%
rename from vendor/jpeg-9e/jcapimin.c
rename to vendor/jpeg-9f/jcapimin.c
diff --git a/vendor/jpeg-9e/jcapistd.c b/vendor/jpeg-9f/jcapistd.c
similarity index 100%
rename from vendor/jpeg-9e/jcapistd.c
rename to vendor/jpeg-9f/jcapistd.c
diff --git a/vendor/jpeg-9e/jcarith.c b/vendor/jpeg-9f/jcarith.c
similarity index 100%
rename from vendor/jpeg-9e/jcarith.c
rename to vendor/jpeg-9f/jcarith.c
diff --git a/vendor/jpeg-9e/jccoefct.c b/vendor/jpeg-9f/jccoefct.c
similarity index 98%
rename from vendor/jpeg-9e/jccoefct.c
rename to vendor/jpeg-9f/jccoefct.c
index 77851f390e..494aa22988 100644
--- a/vendor/jpeg-9e/jccoefct.c
+++ b/vendor/jpeg-9f/jccoefct.c
@@ -2,7 +2,7 @@
  * jccoefct.c
  *
  * Copyright (C) 1994-1997, Thomas G. Lane.
- * Modified 2003-2020 by Guido Vollbeding.
+ * Modified 2003-2022 by Guido Vollbeding.
  * This file is part of the Independent JPEG Group's software.
  * For conditions of distribution and use, see the accompanying README file.
  *
@@ -41,9 +41,9 @@ typedef struct {
   int MCU_rows_per_iMCU_row;	/* number of such rows needed */
 
   /* For single-pass compression, it's sufficient to buffer just one MCU
-   * (although this may prove a bit slow in practice).  We append a
-   * workspace of C_MAX_BLOCKS_IN_MCU coefficient blocks, and reuse it
-   * for each MCU constructed and sent.
+   * (although this may prove a bit slow in practice).
+   * We append a workspace of C_MAX_BLOCKS_IN_MCU coefficient blocks,
+   * and reuse it for each MCU constructed and sent.
    * In multi-pass modes, this array points to the current MCU's blocks
    * within the virtual arrays.
    */
diff --git a/vendor/jpeg-9e/jccolor.c b/vendor/jpeg-9f/jccolor.c
similarity index 95%
rename from vendor/jpeg-9e/jccolor.c
rename to vendor/jpeg-9f/jccolor.c
index db2ca429e8..c028dd9db3 100644
--- a/vendor/jpeg-9e/jccolor.c
+++ b/vendor/jpeg-9f/jccolor.c
@@ -2,7 +2,7 @@
  * jccolor.c
  *
  * Copyright (C) 1991-1996, Thomas G. Lane.
- * Modified 2011-2019 by Guido Vollbeding.
+ * Modified 2011-2023 by Guido Vollbeding.
  * This file is part of the Independent JPEG Group's software.
  * For conditions of distribution and use, see the accompanying README file.
  *
@@ -40,10 +40,10 @@ typedef my_color_converter * my_cconvert_ptr;
  * Note that the derived conversion coefficients given in some of these
  * documents are imprecise.  The general conversion equations are
  *	Y  = Kr * R + (1 - Kr - Kb) * G + Kb * B
- *	Cb = 0.5 * (B - Y) / (1 - Kb)
- *	Cr = 0.5 * (R - Y) / (1 - Kr)
+ *	Cb = (B - Y) / (1 - Kb) / K
+ *	Cr = (R - Y) / (1 - Kr) / K
  * With Kr = 0.299 and Kb = 0.114 (derived according to SMPTE RP 177-1993
- * from the 1953 FCC NTSC primaries and CIE Illuminant C),
+ * from the 1953 FCC NTSC primaries and CIE Illuminant C), K = 2 for sYCC,
  * the conversion equations to be implemented are therefore
  *	Y  =  0.299 * R + 0.587 * G + 0.114 * B
  *	Cb = -0.168735892 * R - 0.331264108 * G + 0.5 * B + CENTERJSAMPLE
@@ -62,8 +62,8 @@ typedef my_color_converter * my_cconvert_ptr;
  * by precalculating the constants times R,G,B for all possible values.
  * For 8-bit JSAMPLEs this is very reasonable (only 256 entries per table);
  * for 9-bit to 12-bit samples it is still acceptable.  It's not very
- * reasonable for 16-bit samples, but if you want lossless storage you
- * shouldn't be changing colorspace anyway.
+ * reasonable for 16-bit samples, but if you want lossless storage
+ * you shouldn't be changing colorspace anyway.
  * The CENTERJSAMPLE offsets and the rounding fudge-factor of 0.5 are included
  * in the tables to save adding them separately in the inner loop.
  */
@@ -110,16 +110,16 @@ rgb_ycc_start (j_compress_ptr cinfo)
   for (i = 0; i <= MAXJSAMPLE; i++) {
     rgb_ycc_tab[i+R_Y_OFF] = FIX(0.299) * i;
     rgb_ycc_tab[i+G_Y_OFF] = FIX(0.587) * i;
-    rgb_ycc_tab[i+B_Y_OFF] = FIX(0.114) * i   + ONE_HALF;
+    rgb_ycc_tab[i+B_Y_OFF] = FIX(0.114) * i + ONE_HALF;
     rgb_ycc_tab[i+R_CB_OFF] = (- FIX(0.168735892)) * i;
     rgb_ycc_tab[i+G_CB_OFF] = (- FIX(0.331264108)) * i;
     /* We use a rounding fudge-factor of 0.5-epsilon for Cb and Cr.
      * This ensures that the maximum output will round to MAXJSAMPLE
      * not MAXJSAMPLE+1, and thus that we don't have to range-limit.
      */
-    rgb_ycc_tab[i+B_CB_OFF] = FIX(0.5) * i    + CBCR_OFFSET + ONE_HALF-1;
+    rgb_ycc_tab[i+B_CB_OFF] = (i << (SCALEBITS-1)) + CBCR_OFFSET + ONE_HALF-1;
 /*  B=>Cb and R=>Cr tables are the same
-    rgb_ycc_tab[i+R_CR_OFF] = FIX(0.5) * i    + CBCR_OFFSET + ONE_HALF-1;
+    rgb_ycc_tab[i+R_CR_OFF] = (i << (SCALEBITS-1)) + CBCR_OFFSET + ONE_HALF-1;
 */
     rgb_ycc_tab[i+G_CR_OFF] = (- FIX(0.418687589)) * i;
     rgb_ycc_tab[i+B_CR_OFF] = (- FIX(0.081312411)) * i;
@@ -190,8 +190,8 @@ rgb_ycc_convert (j_compress_ptr cinfo,
 
 /*
  * Convert some rows of samples to the JPEG colorspace.
- * This version handles RGB->grayscale conversion, which is the same
- * as the RGB->Y portion of RGB->YCbCr.
+ * This version handles RGB->grayscale conversion,
+ * which is the same as the RGB->Y portion of RGB->YCbCr.
  * We assume rgb_ycc_start has been called (we only use the Y tables).
  */
 
@@ -201,7 +201,7 @@ rgb_gray_convert (j_compress_ptr cinfo,
 		  JDIMENSION output_row, int num_rows)
 {
   my_cconvert_ptr cconvert = (my_cconvert_ptr) cinfo->cconvert;
-  register int r, g, b;
+  register INT32 y;
   register INT32 * ctab = cconvert->rgb_ycc_tab;
   register JSAMPROW inptr;
   register JSAMPROW outptr;
@@ -212,14 +212,11 @@ rgb_gray_convert (j_compress_ptr cinfo,
     inptr = *input_buf++;
     outptr = output_buf[0][output_row++];
     for (col = 0; col < num_cols; col++) {
-      r = GETJSAMPLE(inptr[RGB_RED]);
-      g = GETJSAMPLE(inptr[RGB_GREEN]);
-      b = GETJSAMPLE(inptr[RGB_BLUE]);
+      y  = ctab[R_Y_OFF + GETJSAMPLE(inptr[RGB_RED])];
+      y += ctab[G_Y_OFF + GETJSAMPLE(inptr[RGB_GREEN])];
+      y += ctab[B_Y_OFF + GETJSAMPLE(inptr[RGB_BLUE])];
       inptr += RGB_PIXELSIZE;
-      /* Y */
-      outptr[col] = (JSAMPLE)
-		((ctab[r+R_Y_OFF] + ctab[g+G_Y_OFF] + ctab[b+B_Y_OFF])
-		 >> SCALEBITS);
+      outptr[col] = (JSAMPLE) (y >> SCALEBITS);
     }
   }
 }
diff --git a/vendor/jpeg-9e/jcdctmgr.c b/vendor/jpeg-9f/jcdctmgr.c
similarity index 100%
rename from vendor/jpeg-9e/jcdctmgr.c
rename to vendor/jpeg-9f/jcdctmgr.c
diff --git a/vendor/jpeg-9e/jchuff.c b/vendor/jpeg-9f/jchuff.c
similarity index 89%
rename from vendor/jpeg-9e/jchuff.c
rename to vendor/jpeg-9f/jchuff.c
index f3272c9fa6..1f527b2182 100644
--- a/vendor/jpeg-9e/jchuff.c
+++ b/vendor/jpeg-9f/jchuff.c
@@ -2,7 +2,7 @@
  * jchuff.c
  *
  * Copyright (C) 1991-1997, Thomas G. Lane.
- * Modified 2006-2020 by Guido Vollbeding.
+ * Modified 2006-2023 by Guido Vollbeding.
  * This file is part of the Independent JPEG Group's software.
  * For conditions of distribution and use, see the accompanying README file.
  *
@@ -26,17 +26,11 @@
 
 
 /* The legal range of a DCT coefficient is
- *  -1024 .. +1023  for 8-bit data;
- * -16384 .. +16383 for 12-bit data.
- * Hence the magnitude should always fit in 10 or 14 bits respectively.
+ *  -1024 .. +1023  for 8-bit sample data precision;
+ * -16384 .. +16383 for 12-bit sample data precision.
+ * Hence the magnitude should always fit in sample data precision + 2 bits.
  */
 
-#if BITS_IN_JSAMPLE == 8
-#define MAX_COEF_BITS 10
-#else
-#define MAX_COEF_BITS 14
-#endif
-
 /* Derived data constructed for each Huffman table */
 
 typedef struct {
@@ -547,6 +541,7 @@ encode_mcu_DC_first (j_compress_ptr cinfo, JBLOCKARRAY MCU_data)
   huff_entropy_ptr entropy = (huff_entropy_ptr) cinfo->entropy;
   register int temp, temp2;
   register int nbits;
+  int max_coef_bits;
   int blkn, ci, tbl;
   ISHIFT_TEMPS
 
@@ -558,6 +553,9 @@ encode_mcu_DC_first (j_compress_ptr cinfo, JBLOCKARRAY MCU_data)
     if (entropy->restarts_to_go == 0)
       emit_restart_e(entropy, entropy->next_restart_num);
 
+  /* Since we're encoding a difference, the range limit is twice as much. */
+  max_coef_bits = cinfo->data_precision + 3;
+
   /* Encode the MCU data blocks */
   for (blkn = 0; blkn < cinfo->blocks_in_MCU; blkn++) {
     ci = cinfo->MCU_membership[blkn];
@@ -569,12 +567,17 @@ encode_mcu_DC_first (j_compress_ptr cinfo, JBLOCKARRAY MCU_data)
     temp = IRIGHT_SHIFT((int) (MCU_data[blkn][0][0]), cinfo->Al);
 
     /* DC differences are figured on the point-transformed values. */
-    temp2 = temp - entropy->saved.last_dc_val[ci];
+    if ((temp2 = temp - entropy->saved.last_dc_val[ci]) == 0) {
+      /* Count/emit the Huffman-coded symbol for the number of bits */
+      emit_dc_symbol(entropy, tbl, 0);
+
+      continue;
+    }
+
     entropy->saved.last_dc_val[ci] = temp;
 
     /* Encode the DC coefficient difference per section G.1.2.1 */
-    temp = temp2;
-    if (temp < 0) {
+    if ((temp = temp2) < 0) {
       temp = -temp;		/* temp is abs value of input */
       /* For a negative input, want temp2 = bitwise complement of abs(input) */
       /* This code assumes we are on a two's complement machine */
@@ -583,14 +586,10 @@ encode_mcu_DC_first (j_compress_ptr cinfo, JBLOCKARRAY MCU_data)
 
     /* Find the number of bits needed for the magnitude of the coefficient */
     nbits = 0;
-    while (temp) {
-      nbits++;
-      temp >>= 1;
-    }
-    /* Check for out-of-range coefficient values.
-     * Since we're encoding a difference, the range limit is twice as much.
-     */
-    if (nbits > MAX_COEF_BITS+1)
+    do nbits++;			/* there must be at least one 1 bit */
+    while ((temp >>= 1));
+    /* Check for out-of-range coefficient values */
+    if (nbits > max_coef_bits)
       ERREXIT(cinfo, JERR_BAD_DCT_COEF);
 
     /* Count/emit the Huffman-coded symbol for the number of bits */
@@ -598,8 +597,7 @@ encode_mcu_DC_first (j_compress_ptr cinfo, JBLOCKARRAY MCU_data)
 
     /* Emit that number of bits of the value, if positive, */
     /* or the complement of its magnitude, if negative. */
-    if (nbits)			/* emit_bits rejects calls with size 0 */
-      emit_bits_e(entropy, (unsigned int) temp2, nbits);
+    emit_bits_e(entropy, (unsigned int) temp2, nbits);
   }
 
   cinfo->dest->next_output_byte = entropy->next_output_byte;
@@ -633,7 +631,7 @@ encode_mcu_AC_first (j_compress_ptr cinfo, JBLOCKARRAY MCU_data)
   register int temp, temp2;
   register int nbits;
   register int r, k;
-  int Se, Al;
+  int Se, Al, max_coef_bits;
 
   entropy->next_output_byte = cinfo->dest->next_output_byte;
   entropy->free_in_buffer = cinfo->dest->free_in_buffer;
@@ -646,6 +644,7 @@ encode_mcu_AC_first (j_compress_ptr cinfo, JBLOCKARRAY MCU_data)
   Se = cinfo->Se;
   Al = cinfo->Al;
   natural_order = cinfo->natural_order;
+  max_coef_bits = cinfo->data_precision + 2;
 
   /* Encode the MCU data block */
   block = MCU_data[0];
@@ -666,18 +665,23 @@ encode_mcu_AC_first (j_compress_ptr cinfo, JBLOCKARRAY MCU_data)
      */
     if (temp < 0) {
       temp = -temp;		/* temp is abs value of input */
-      temp >>= Al;		/* apply the point transform */
+      /* Apply the point transform, and watch out for case */
+      /* that nonzero coef is zero after point transform. */
+      if ((temp >>= Al) == 0) {
+	r++;
+	continue;
+      }
       /* For a negative coef, want temp2 = bitwise complement of abs(coef) */
       temp2 = ~temp;
     } else {
-      temp >>= Al;		/* apply the point transform */
+      /* Apply the point transform, and watch out for case */
+      /* that nonzero coef is zero after point transform. */
+      if ((temp >>= Al) == 0) {
+	r++;
+	continue;
+      }
       temp2 = temp;
     }
-    /* Watch out for case that nonzero coef is zero after point transform */
-    if (temp == 0) {
-      r++;
-      continue;
-    }
 
     /* Emit any pending EOBRUN */
     if (entropy->EOBRUN > 0)
@@ -689,11 +693,11 @@ encode_mcu_AC_first (j_compress_ptr cinfo, JBLOCKARRAY MCU_data)
     }
 
     /* Find the number of bits needed for the magnitude of the coefficient */
-    nbits = 1;			/* there must be at least one 1 bit */
-    while ((temp >>= 1))
-      nbits++;
+    nbits = 0;
+    do nbits++;			/* there must be at least one 1 bit */
+    while ((temp >>= 1));
     /* Check for out-of-range coefficient values */
-    if (nbits > MAX_COEF_BITS)
+    if (nbits > max_coef_bits)
       ERREXIT(cinfo, JERR_BAD_DCT_COEF);
 
     /* Count/emit Huffman symbol for run length / number of bits */
@@ -916,83 +920,89 @@ encode_one_block (working_state * state, JCOEFPTR block, int last_dc_val,
   register int nbits;
   register int r, k;
   int Se = state->cinfo->lim_Se;
+  int max_coef_bits = state->cinfo->data_precision + 3;
   const int * natural_order = state->cinfo->natural_order;
 
   /* Encode the DC coefficient difference per section F.1.2.1 */
 
-  temp = temp2 = block[0] - last_dc_val;
-
-  if (temp < 0) {
-    temp = -temp;		/* temp is abs value of input */
-    /* For a negative input, want temp2 = bitwise complement of abs(input) */
-    /* This code assumes we are on a two's complement machine */
-    temp2--;
-  }
+  if ((temp = block[0] - last_dc_val) == 0) {
+    /* Emit the Huffman-coded symbol for the number of bits */
+    if (! emit_bits_s(state, dctbl->ehufco[0], dctbl->ehufsi[0]))
+      return FALSE;
+  } else {
+    if ((temp2 = temp) < 0) {
+      temp = -temp;		/* temp is abs value of input */
+      /* For a negative input, want temp2 = bitwise complement of abs(input) */
+      /* This code assumes we are on a two's complement machine */
+      temp2--;
+    }
 
-  /* Find the number of bits needed for the magnitude of the coefficient */
-  nbits = 0;
-  while (temp) {
-    nbits++;
-    temp >>= 1;
-  }
-  /* Check for out-of-range coefficient values.
-   * Since we're encoding a difference, the range limit is twice as much.
-   */
-  if (nbits > MAX_COEF_BITS+1)
-    ERREXIT(state->cinfo, JERR_BAD_DCT_COEF);
+    /* Find the number of bits needed for the magnitude of the coefficient */
+    nbits = 0;
+    do nbits++;			/* there must be at least one 1 bit */
+    while ((temp >>= 1));
+    /* Check for out-of-range coefficient values.
+     * Since we're encoding a difference, the range limit is twice as much.
+     */
+    if (nbits > max_coef_bits)
+      ERREXIT(state->cinfo, JERR_BAD_DCT_COEF);
 
-  /* Emit the Huffman-coded symbol for the number of bits */
-  if (! emit_bits_s(state, dctbl->ehufco[nbits], dctbl->ehufsi[nbits]))
-    return FALSE;
+    /* Emit the Huffman-coded symbol for the number of bits */
+    if (! emit_bits_s(state, dctbl->ehufco[nbits], dctbl->ehufsi[nbits]))
+      return FALSE;
 
-  /* Emit that number of bits of the value, if positive, */
-  /* or the complement of its magnitude, if negative. */
-  if (nbits)			/* emit_bits rejects calls with size 0 */
+    /* Emit that number of bits of the value, if positive, */
+    /* or the complement of its magnitude, if negative. */
     if (! emit_bits_s(state, (unsigned int) temp2, nbits))
       return FALSE;
+  }
 
   /* Encode the AC coefficients per section F.1.2.2 */
 
   r = 0;			/* r = run length of zeros */
 
   for (k = 1; k <= Se; k++) {
-    if ((temp2 = block[natural_order[k]]) == 0) {
+    if ((temp = block[natural_order[k]]) == 0) {
       r++;
-    } else {
-      /* if run length > 15, must emit special run-length-16 codes (0xF0) */
-      while (r > 15) {
-	if (! emit_bits_s(state, actbl->ehufco[0xF0], actbl->ehufsi[0xF0]))
-	  return FALSE;
-	r -= 16;
-      }
-
-      temp = temp2;
-      if (temp < 0) {
-	temp = -temp;		/* temp is abs value of input */
-	/* This code assumes we are on a two's complement machine */
-	temp2--;
-      }
-
-      /* Find the number of bits needed for the magnitude of the coefficient */
-      nbits = 1;		/* there must be at least one 1 bit */
-      while ((temp >>= 1))
-	nbits++;
-      /* Check for out-of-range coefficient values */
-      if (nbits > MAX_COEF_BITS)
-	ERREXIT(state->cinfo, JERR_BAD_DCT_COEF);
-
-      /* Emit Huffman symbol for run length / number of bits */
-      temp = (r << 4) + nbits;
-      if (! emit_bits_s(state, actbl->ehufco[temp], actbl->ehufsi[temp]))
-	return FALSE;
+      continue;
+    }
 
-      /* Emit that number of bits of the value, if positive, */
-      /* or the complement of its magnitude, if negative. */
-      if (! emit_bits_s(state, (unsigned int) temp2, nbits))
+    /* if run length > 15, must emit special run-length-16 codes (0xF0) */
+    while (r > 15) {
+      if (! emit_bits_s(state, actbl->ehufco[0xF0], actbl->ehufsi[0xF0]))
 	return FALSE;
+      r -= 16;
+    }
 
-      r = 0;
+    if ((temp2 = temp) < 0) {
+      temp = -temp;		/* temp is abs value of input */
+      /* For a negative coef, want temp2 = bitwise complement of abs(coef) */
+      /* This code assumes we are on a two's complement machine */
+      temp2--;
     }
+
+    /* Find the number of bits needed for the magnitude of the coefficient */
+    nbits = 0;
+    do nbits++;			/* there must be at least one 1 bit */
+    while ((temp >>= 1));
+    /* Check for out-of-range coefficient values.
+     * Use ">=" instead of ">" so can use the
+     * same one larger limit from DC check here.
+     */
+    if (nbits >= max_coef_bits)
+      ERREXIT(state->cinfo, JERR_BAD_DCT_COEF);
+
+    /* Emit Huffman symbol for run length / number of bits */
+    temp = (r << 4) + nbits;
+    if (! emit_bits_s(state, actbl->ehufco[temp], actbl->ehufsi[temp]))
+      return FALSE;
+
+    /* Emit that number of bits of the value, if positive, */
+    /* or the complement of its magnitude, if negative. */
+    if (! emit_bits_s(state, (unsigned int) temp2, nbits))
+      return FALSE;
+
+    r = 0;			/* reset zero run length */
   }
 
   /* If the last coef(s) were zero, emit an end-of-block code */
@@ -1122,28 +1132,31 @@ htest_one_block (j_compress_ptr cinfo, JCOEFPTR block, int last_dc_val,
   register int nbits;
   register int r, k;
   int Se = cinfo->lim_Se;
+  int max_coef_bits = cinfo->data_precision + 3;
   const int * natural_order = cinfo->natural_order;
 
   /* Encode the DC coefficient difference per section F.1.2.1 */
 
-  temp = block[0] - last_dc_val;
-  if (temp < 0)
-    temp = -temp;
+  if ((temp = block[0] - last_dc_val) == 0) {
+    /* Count the Huffman symbol for the number of bits */
+    dc_counts[0]++;
+  } else {
+    if (temp < 0)
+      temp = -temp;		/* temp is abs value of input */
 
-  /* Find the number of bits needed for the magnitude of the coefficient */
-  nbits = 0;
-  while (temp) {
-    nbits++;
-    temp >>= 1;
-  }
-  /* Check for out-of-range coefficient values.
-   * Since we're encoding a difference, the range limit is twice as much.
-   */
-  if (nbits > MAX_COEF_BITS+1)
-    ERREXIT(cinfo, JERR_BAD_DCT_COEF);
+    /* Find the number of bits needed for the magnitude of the coefficient */
+    nbits = 0;
+    do nbits++;			/* there must be at least one 1 bit */
+    while ((temp >>= 1));
+    /* Check for out-of-range coefficient values.
+     * Since we're encoding a difference, the range limit is twice as much.
+     */
+    if (nbits > max_coef_bits)
+      ERREXIT(cinfo, JERR_BAD_DCT_COEF);
 
-  /* Count the Huffman symbol for the number of bits */
-  dc_counts[nbits]++;
+    /* Count the Huffman symbol for the number of bits */
+    dc_counts[nbits]++;
+  }
 
   /* Encode the AC coefficients per section F.1.2.2 */
 
@@ -1152,30 +1165,33 @@ htest_one_block (j_compress_ptr cinfo, JCOEFPTR block, int last_dc_val,
   for (k = 1; k <= Se; k++) {
     if ((temp = block[natural_order[k]]) == 0) {
       r++;
-    } else {
-      /* if run length > 15, must emit special run-length-16 codes (0xF0) */
-      while (r > 15) {
-	ac_counts[0xF0]++;
-	r -= 16;
-      }
+      continue;
+    }
+
+    /* if run length > 15, must emit special run-length-16 codes (0xF0) */
+    while (r > 15) {
+      ac_counts[0xF0]++;
+      r -= 16;
+    }
 
-      /* Find the number of bits needed for the magnitude of the coefficient */
-      if (temp < 0)
-	temp = -temp;
+    if (temp < 0)
+      temp = -temp;		/* temp is abs value of input */
 
-      /* Find the number of bits needed for the magnitude of the coefficient */
-      nbits = 1;		/* there must be at least one 1 bit */
-      while ((temp >>= 1))
-	nbits++;
-      /* Check for out-of-range coefficient values */
-      if (nbits > MAX_COEF_BITS)
-	ERREXIT(cinfo, JERR_BAD_DCT_COEF);
+    /* Find the number of bits needed for the magnitude of the coefficient */
+    nbits = 0;
+    do nbits++;			/* there must be at least one 1 bit */
+    while ((temp >>= 1));
+    /* Check for out-of-range coefficient values.
+     * Use ">=" instead of ">" so can use the
+     * same one larger limit from DC check here.
+     */
+    if (nbits >= max_coef_bits)
+      ERREXIT(cinfo, JERR_BAD_DCT_COEF);
 
-      /* Count Huffman symbol for run length / number of bits */
-      ac_counts[(r << 4) + nbits]++;
+    /* Count Huffman symbol for run length / number of bits */
+    ac_counts[(r << 4) + nbits]++;
 
-      r = 0;
-    }
+    r = 0;			/* reset zero run length */
   }
 
   /* If the last coef(s) were zero, emit an end-of-block code */
diff --git a/vendor/jpeg-9e/jcinit.c b/vendor/jpeg-9f/jcinit.c
similarity index 100%
rename from vendor/jpeg-9e/jcinit.c
rename to vendor/jpeg-9f/jcinit.c
diff --git a/vendor/jpeg-9e/jcmainct.c b/vendor/jpeg-9f/jcmainct.c
similarity index 100%
rename from vendor/jpeg-9e/jcmainct.c
rename to vendor/jpeg-9f/jcmainct.c
diff --git a/vendor/jpeg-9e/jcmarker.c b/vendor/jpeg-9f/jcmarker.c
similarity index 100%
rename from vendor/jpeg-9e/jcmarker.c
rename to vendor/jpeg-9f/jcmarker.c
diff --git a/vendor/jpeg-9e/jcmaster.c b/vendor/jpeg-9f/jcmaster.c
similarity index 100%
rename from vendor/jpeg-9e/jcmaster.c
rename to vendor/jpeg-9f/jcmaster.c
diff --git a/vendor/jpeg-9e/jcomapi.c b/vendor/jpeg-9f/jcomapi.c
similarity index 100%
rename from vendor/jpeg-9e/jcomapi.c
rename to vendor/jpeg-9f/jcomapi.c
diff --git a/vendor/jpeg-9e/jconfig.h b/vendor/jpeg-9f/jconfig.h
similarity index 100%
rename from vendor/jpeg-9e/jconfig.h
rename to vendor/jpeg-9f/jconfig.h
diff --git a/vendor/jpeg-9e/jcparam.c b/vendor/jpeg-9f/jcparam.c
similarity index 100%
rename from vendor/jpeg-9e/jcparam.c
rename to vendor/jpeg-9f/jcparam.c
diff --git a/vendor/jpeg-9e/jcprepct.c b/vendor/jpeg-9f/jcprepct.c
similarity index 100%
rename from vendor/jpeg-9e/jcprepct.c
rename to vendor/jpeg-9f/jcprepct.c
diff --git a/vendor/jpeg-9e/jcsample.c b/vendor/jpeg-9f/jcsample.c
similarity index 100%
rename from vendor/jpeg-9e/jcsample.c
rename to vendor/jpeg-9f/jcsample.c
diff --git a/vendor/jpeg-9e/jctrans.c b/vendor/jpeg-9f/jctrans.c
similarity index 100%
rename from vendor/jpeg-9e/jctrans.c
rename to vendor/jpeg-9f/jctrans.c
diff --git a/vendor/jpeg-9e/jdapimin.c b/vendor/jpeg-9f/jdapimin.c
similarity index 100%
rename from vendor/jpeg-9e/jdapimin.c
rename to vendor/jpeg-9f/jdapimin.c
diff --git a/vendor/jpeg-9e/jdapistd.c b/vendor/jpeg-9f/jdapistd.c
similarity index 100%
rename from vendor/jpeg-9e/jdapistd.c
rename to vendor/jpeg-9f/jdapistd.c
diff --git a/vendor/jpeg-9e/jdarith.c b/vendor/jpeg-9f/jdarith.c
similarity index 100%
rename from vendor/jpeg-9e/jdarith.c
rename to vendor/jpeg-9f/jdarith.c
diff --git a/vendor/jpeg-9e/jdatadst.c b/vendor/jpeg-9f/jdatadst.c
similarity index 95%
rename from vendor/jpeg-9e/jdatadst.c
rename to vendor/jpeg-9f/jdatadst.c
index 75ebd7c22d..b3b4798ea4 100644
--- a/vendor/jpeg-9e/jdatadst.c
+++ b/vendor/jpeg-9f/jdatadst.c
@@ -2,7 +2,7 @@
  * jdatadst.c
  *
  * Copyright (C) 1994-1996, Thomas G. Lane.
- * Modified 2009-2019 by Guido Vollbeding.
+ * Modified 2009-2022 by Guido Vollbeding.
  * This file is part of the Independent JPEG Group's software.
  * For conditions of distribution and use, see the accompanying README file.
  *
@@ -28,17 +28,17 @@ extern void free JPP((void *ptr));
 
 /* Expanded data destination object for stdio output */
 
+#define OUTPUT_BUF_SIZE  4096	/* choose an efficiently fwrite'able size */
+
 typedef struct {
   struct jpeg_destination_mgr pub; /* public fields */
 
   FILE * outfile;		/* target stream */
-  JOCTET * buffer;		/* start of buffer */
+  JOCTET buffer[OUTPUT_BUF_SIZE]; /* output buffer */
 } my_destination_mgr;
 
 typedef my_destination_mgr * my_dest_ptr;
 
-#define OUTPUT_BUF_SIZE  4096	/* choose an efficiently fwrite'able size */
-
 
 /* Expanded data destination object for memory output */
 
@@ -65,10 +65,6 @@ init_destination (j_compress_ptr cinfo)
 {
   my_dest_ptr dest = (my_dest_ptr) cinfo->dest;
 
-  /* Allocate the output buffer --- it will be released when done with image */
-  dest->buffer = (JOCTET *) (*cinfo->mem->alloc_small)
-    ((j_common_ptr) cinfo, JPOOL_IMAGE, OUTPUT_BUF_SIZE * SIZEOF(JOCTET));
-
   dest->pub.next_output_byte = dest->buffer;
   dest->pub.free_in_buffer = OUTPUT_BUF_SIZE;
 }
@@ -187,8 +183,8 @@ term_mem_destination (j_compress_ptr cinfo)
 
 /*
  * Prepare for output to a stdio stream.
- * The caller must have already opened the stream, and is responsible
- * for closing it after finishing compression.
+ * The caller must have already opened the stream,
+ * and is responsible for closing it after finishing compression.
  */
 
 GLOBAL(void)
diff --git a/vendor/jpeg-9e/jdatasrc.c b/vendor/jpeg-9f/jdatasrc.c
similarity index 92%
rename from vendor/jpeg-9e/jdatasrc.c
rename to vendor/jpeg-9f/jdatasrc.c
index 606ae11b4c..fd7a1a594b 100644
--- a/vendor/jpeg-9e/jdatasrc.c
+++ b/vendor/jpeg-9f/jdatasrc.c
@@ -2,7 +2,7 @@
  * jdatasrc.c
  *
  * Copyright (C) 1994-1996, Thomas G. Lane.
- * Modified 2009-2019 by Guido Vollbeding.
+ * Modified 2009-2022 by Guido Vollbeding.
  * This file is part of the Independent JPEG Group's software.
  * For conditions of distribution and use, see the accompanying README file.
  *
@@ -23,18 +23,18 @@
 
 /* Expanded data source object for stdio input */
 
+#define INPUT_BUF_SIZE  4096	/* choose an efficiently fread'able size */
+
 typedef struct {
   struct jpeg_source_mgr pub;	/* public fields */
 
   FILE * infile;		/* source stream */
-  JOCTET * buffer;		/* start of buffer */
+  JOCTET buffer[INPUT_BUF_SIZE]; /* input buffer */
   boolean start_of_file;	/* have we gotten any data yet? */
 } my_source_mgr;
 
 typedef my_source_mgr * my_src_ptr;
 
-#define INPUT_BUF_SIZE  4096	/* choose an efficiently fread'able size */
-
 
 /*
  * Initialize source --- called by jpeg_read_header
@@ -204,8 +204,8 @@ term_source (j_decompress_ptr cinfo)
 
 /*
  * Prepare for input from a stdio stream.
- * The caller must have already opened the stream, and is responsible
- * for closing it after finishing decompression.
+ * The caller must have already opened the stream,
+ * and is responsible for closing it after finishing decompression.
  */
 
 GLOBAL(void)
@@ -213,19 +213,16 @@ jpeg_stdio_src (j_decompress_ptr cinfo, FILE * infile)
 {
   my_src_ptr src;
 
-  /* The source object and input buffer are made permanent so that a series
-   * of JPEG images can be read from the same file by calling jpeg_stdio_src
-   * only before the first one.  (If we discarded the buffer at the end of
-   * one image, we'd likely lose the start of the next one.)
+  /* The source object including the input buffer is made permanent so that
+   * a series of JPEG images can be read from the same file by calling
+   * jpeg_stdio_src only before the first one.  (If we discarded the buffer
+   * at the end of one image, we'd likely lose the start of the next one.)
    * This makes it unsafe to use this manager and a different source
    * manager serially with the same JPEG object.  Caveat programmer.
    */
   if (cinfo->src == NULL) {	/* first time for this JPEG object? */
     cinfo->src = (struct jpeg_source_mgr *) (*cinfo->mem->alloc_small)
       ((j_common_ptr) cinfo, JPOOL_PERMANENT, SIZEOF(my_source_mgr));
-    src = (my_src_ptr) cinfo->src;
-    src->buffer = (JOCTET *) (*cinfo->mem->alloc_small)
-      ((j_common_ptr) cinfo, JPOOL_PERMANENT, INPUT_BUF_SIZE * SIZEOF(JOCTET));
   }
 
   src = (my_src_ptr) cinfo->src;
diff --git a/vendor/jpeg-9e/jdcoefct.c b/vendor/jpeg-9f/jdcoefct.c
similarity index 100%
rename from vendor/jpeg-9e/jdcoefct.c
rename to vendor/jpeg-9f/jdcoefct.c
diff --git a/vendor/jpeg-9e/jdcolor.c b/vendor/jpeg-9f/jdcolor.c
similarity index 91%
rename from vendor/jpeg-9e/jdcolor.c
rename to vendor/jpeg-9f/jdcolor.c
index 7750df125a..6b40fb5340 100644
--- a/vendor/jpeg-9e/jdcolor.c
+++ b/vendor/jpeg-9f/jdcolor.c
@@ -2,7 +2,7 @@
  * jdcolor.c
  *
  * Copyright (C) 1991-1997, Thomas G. Lane.
- * Modified 2011-2020 by Guido Vollbeding.
+ * Modified 2011-2023 by Guido Vollbeding.
  * This file is part of the Independent JPEG Group's software.
  * For conditions of distribution and use, see the accompanying README file.
  *
@@ -32,7 +32,9 @@ typedef struct {
   INT32 * Cb_g_tab;		/* => table for Cb to G conversion */
 
   /* Private state for RGB->Y conversion */
-  INT32 * rgb_y_tab;		/* => table for RGB to Y conversion */
+  INT32 * R_y_tab;		/* => table for R to Y conversion */
+  INT32 * G_y_tab;		/* => table for G to Y conversion */
+  INT32 * B_y_tab;		/* => table for B to Y conversion */
 } my_color_deconverter;
 
 typedef my_color_deconverter * my_cconvert_ptr;
@@ -87,29 +89,17 @@ typedef my_color_deconverter * my_cconvert_ptr;
  * by precalculating the constants times Cb and Cr for all possible values.
  * For 8-bit JSAMPLEs this is very reasonable (only 256 entries per table);
  * for 9-bit to 12-bit samples it is still acceptable.  It's not very
- * reasonable for 16-bit samples, but if you want lossless storage you
- * shouldn't be changing colorspace anyway.
- * The Cr=>R and Cb=>B values can be rounded to integers in advance; the
- * values for the G calculation are left scaled up, since we must add them
- * together before rounding.
+ * reasonable for 16-bit samples, but if you want lossless storage
+ * you shouldn't be changing colorspace anyway.
+ * The Cr=>R and Cb=>B values can be rounded to integers in advance;
+ * the values for the G calculation are left scaled up,
+ * since we must add them together before rounding.
  */
 
 #define SCALEBITS	16	/* speediest right-shift on some machines */
 #define ONE_HALF	((INT32) 1 << (SCALEBITS-1))
 #define FIX(x)		((INT32) ((x) * (1L<Y conversion and divide it up into
- * three parts, instead of doing three alloc_small requests.  This lets us
- * use a single table base address, which can be held in a register in the
- * inner loops on many machines (more than can hold all three addresses,
- * anyway).
- */
-
-#define R_Y_OFF		0			/* offset to R => Y section */
-#define G_Y_OFF		(1*(MAXJSAMPLE+1))	/* offset to G => Y section */
-#define B_Y_OFF		(2*(MAXJSAMPLE+1))	/* etc. */
-#define TABLE_SIZE	(3*(MAXJSAMPLE+1))
-
 
 /*
  * Initialize tables for YCbCr->RGB and BG_YCC->RGB colorspace conversion.
@@ -249,17 +239,19 @@ LOCAL(void)
 build_rgb_y_table (j_decompress_ptr cinfo)
 {
   my_cconvert_ptr cconvert = (my_cconvert_ptr) cinfo->cconvert;
-  INT32 * rgb_y_tab;
   INT32 i;
 
-  /* Allocate and fill in the conversion tables. */
-  cconvert->rgb_y_tab = rgb_y_tab = (INT32 *) (*cinfo->mem->alloc_small)
-    ((j_common_ptr) cinfo, JPOOL_IMAGE, TABLE_SIZE * SIZEOF(INT32));
+  cconvert->R_y_tab = (INT32 *) (*cinfo->mem->alloc_small)
+    ((j_common_ptr) cinfo, JPOOL_IMAGE, (MAXJSAMPLE+1) * SIZEOF(INT32));
+  cconvert->G_y_tab = (INT32 *) (*cinfo->mem->alloc_small)
+    ((j_common_ptr) cinfo, JPOOL_IMAGE, (MAXJSAMPLE+1) * SIZEOF(INT32));
+  cconvert->B_y_tab = (INT32 *) (*cinfo->mem->alloc_small)
+    ((j_common_ptr) cinfo, JPOOL_IMAGE, (MAXJSAMPLE+1) * SIZEOF(INT32));
 
   for (i = 0; i <= MAXJSAMPLE; i++) {
-    rgb_y_tab[i+R_Y_OFF] = FIX(0.299) * i;
-    rgb_y_tab[i+G_Y_OFF] = FIX(0.587) * i;
-    rgb_y_tab[i+B_Y_OFF] = FIX(0.114) * i + ONE_HALF;
+    cconvert->R_y_tab[i] = FIX(0.299) * i;
+    cconvert->G_y_tab[i] = FIX(0.587) * i;
+    cconvert->B_y_tab[i] = FIX(0.114) * i + ONE_HALF;
   }
 }
 
@@ -274,8 +266,10 @@ rgb_gray_convert (j_decompress_ptr cinfo,
 		  JSAMPARRAY output_buf, int num_rows)
 {
   my_cconvert_ptr cconvert = (my_cconvert_ptr) cinfo->cconvert;
-  register int r, g, b;
-  register INT32 * ctab = cconvert->rgb_y_tab;
+  register INT32 y;
+  register INT32 * Rytab = cconvert->R_y_tab;
+  register INT32 * Gytab = cconvert->G_y_tab;
+  register INT32 * Bytab = cconvert->B_y_tab;
   register JSAMPROW outptr;
   register JSAMPROW inptr0, inptr1, inptr2;
   register JDIMENSION col;
@@ -288,13 +282,10 @@ rgb_gray_convert (j_decompress_ptr cinfo,
     input_row++;
     outptr = *output_buf++;
     for (col = 0; col < num_cols; col++) {
-      r = GETJSAMPLE(inptr0[col]);
-      g = GETJSAMPLE(inptr1[col]);
-      b = GETJSAMPLE(inptr2[col]);
-      /* Y */
-      outptr[col] = (JSAMPLE)
-		((ctab[r+R_Y_OFF] + ctab[g+G_Y_OFF] + ctab[b+B_Y_OFF])
-		 >> SCALEBITS);
+      y  = Rytab[GETJSAMPLE(inptr0[col])];
+      y += Gytab[GETJSAMPLE(inptr1[col])];
+      y += Bytab[GETJSAMPLE(inptr2[col])];
+      outptr[col] = (JSAMPLE) (y >> SCALEBITS);
     }
   }
 }
@@ -354,7 +345,10 @@ rgb1_gray_convert (j_decompress_ptr cinfo,
 {
   my_cconvert_ptr cconvert = (my_cconvert_ptr) cinfo->cconvert;
   register int r, g, b;
-  register INT32 * ctab = cconvert->rgb_y_tab;
+  register INT32 y;
+  register INT32 * Rytab = cconvert->R_y_tab;
+  register INT32 * Gytab = cconvert->G_y_tab;
+  register INT32 * Bytab = cconvert->B_y_tab;
   register JSAMPROW outptr;
   register JSAMPROW inptr0, inptr1, inptr2;
   register JDIMENSION col;
@@ -373,12 +367,10 @@ rgb1_gray_convert (j_decompress_ptr cinfo,
       /* Assume that MAXJSAMPLE+1 is a power of 2, so that the MOD
        * (modulo) operator is equivalent to the bitmask operator AND.
        */
-      r = (r + g - CENTERJSAMPLE) & MAXJSAMPLE;
-      b = (b + g - CENTERJSAMPLE) & MAXJSAMPLE;
-      /* Y */
-      outptr[col] = (JSAMPLE)
-		((ctab[r+R_Y_OFF] + ctab[g+G_Y_OFF] + ctab[b+B_Y_OFF])
-		 >> SCALEBITS);
+      y  = Rytab[(r + g - CENTERJSAMPLE) & MAXJSAMPLE];
+      y += Gytab[g];
+      y += Bytab[(b + g - CENTERJSAMPLE) & MAXJSAMPLE];
+      outptr[col] = (JSAMPLE) (y >> SCALEBITS);
     }
   }
 }
@@ -565,8 +557,10 @@ cmyk_yk_convert (j_decompress_ptr cinfo,
 		 JSAMPARRAY output_buf, int num_rows)
 {
   my_cconvert_ptr cconvert = (my_cconvert_ptr) cinfo->cconvert;
-  register int r, g, b;
-  register INT32 * ctab = cconvert->rgb_y_tab;
+  register INT32 y;
+  register INT32 * Rytab = cconvert->R_y_tab;
+  register INT32 * Gytab = cconvert->G_y_tab;
+  register INT32 * Bytab = cconvert->B_y_tab;
   register JSAMPROW outptr;
   register JSAMPROW inptr0, inptr1, inptr2, inptr3;
   register JDIMENSION col;
@@ -580,13 +574,10 @@ cmyk_yk_convert (j_decompress_ptr cinfo,
     input_row++;
     outptr = *output_buf++;
     for (col = 0; col < num_cols; col++) {
-      r = MAXJSAMPLE - GETJSAMPLE(inptr0[col]);
-      g = MAXJSAMPLE - GETJSAMPLE(inptr1[col]);
-      b = MAXJSAMPLE - GETJSAMPLE(inptr2[col]);
-      /* Y */
-      outptr[0] = (JSAMPLE)
-		((ctab[r+R_Y_OFF] + ctab[g+G_Y_OFF] + ctab[b+B_Y_OFF])
-		 >> SCALEBITS);
+      y  = Rytab[MAXJSAMPLE - GETJSAMPLE(inptr0[col])];
+      y += Gytab[MAXJSAMPLE - GETJSAMPLE(inptr1[col])];
+      y += Bytab[MAXJSAMPLE - GETJSAMPLE(inptr2[col])];
+      outptr[0] = (JSAMPLE) (y >> SCALEBITS);
       /* K passes through unchanged */
       outptr[1] = inptr3[col];	/* don't need GETJSAMPLE here */
       outptr += 2;
diff --git a/vendor/jpeg-9e/jdct.h b/vendor/jpeg-9f/jdct.h
similarity index 99%
rename from vendor/jpeg-9e/jdct.h
rename to vendor/jpeg-9f/jdct.h
index c8ec6cd90e..0f251590c4 100644
--- a/vendor/jpeg-9e/jdct.h
+++ b/vendor/jpeg-9f/jdct.h
@@ -2,7 +2,7 @@
  * jdct.h
  *
  * Copyright (C) 1994-1996, Thomas G. Lane.
- * Modified 2002-2019 by Guido Vollbeding.
+ * Modified 2002-2023 by Guido Vollbeding.
  * This file is part of the Independent JPEG Group's software.
  * For conditions of distribution and use, see the accompanying README file.
  *
@@ -158,7 +158,7 @@ typedef FAST_FLOAT FLOAT_MULT_TYPE; /* preferred floating type */
 #define jpeg_idct_6x12		jRD6x12
 #define jpeg_idct_5x10		jRD5x10
 #define jpeg_idct_4x8		jRD4x8
-#define jpeg_idct_3x6		jRD3x8
+#define jpeg_idct_3x6		jRD3x6
 #define jpeg_idct_2x4		jRD2x4
 #define jpeg_idct_1x2		jRD1x2
 #endif /* NEED_SHORT_EXTERNAL_NAMES */
diff --git a/vendor/jpeg-9e/jddctmgr.c b/vendor/jpeg-9f/jddctmgr.c
similarity index 100%
rename from vendor/jpeg-9e/jddctmgr.c
rename to vendor/jpeg-9f/jddctmgr.c
diff --git a/vendor/jpeg-9e/jdhuff.c b/vendor/jpeg-9f/jdhuff.c
similarity index 100%
rename from vendor/jpeg-9e/jdhuff.c
rename to vendor/jpeg-9f/jdhuff.c
diff --git a/vendor/jpeg-9e/jdinput.c b/vendor/jpeg-9f/jdinput.c
similarity index 100%
rename from vendor/jpeg-9e/jdinput.c
rename to vendor/jpeg-9f/jdinput.c
diff --git a/vendor/jpeg-9e/jdmainct.c b/vendor/jpeg-9f/jdmainct.c
similarity index 100%
rename from vendor/jpeg-9e/jdmainct.c
rename to vendor/jpeg-9f/jdmainct.c
diff --git a/vendor/jpeg-9e/jdmarker.c b/vendor/jpeg-9f/jdmarker.c
similarity index 100%
rename from vendor/jpeg-9e/jdmarker.c
rename to vendor/jpeg-9f/jdmarker.c
diff --git a/vendor/jpeg-9e/jdmaster.c b/vendor/jpeg-9f/jdmaster.c
similarity index 100%
rename from vendor/jpeg-9e/jdmaster.c
rename to vendor/jpeg-9f/jdmaster.c
diff --git a/vendor/jpeg-9e/jdmerge.c b/vendor/jpeg-9f/jdmerge.c
similarity index 96%
rename from vendor/jpeg-9e/jdmerge.c
rename to vendor/jpeg-9f/jdmerge.c
index 8ff13143af..0d16821bed 100644
--- a/vendor/jpeg-9e/jdmerge.c
+++ b/vendor/jpeg-9f/jdmerge.c
@@ -2,7 +2,7 @@
  * jdmerge.c
  *
  * Copyright (C) 1994-1996, Thomas G. Lane.
- * Modified 2013-2020 by Guido Vollbeding.
+ * Modified 2013-2022 by Guido Vollbeding.
  * This file is part of the Independent JPEG Group's software.
  * For conditions of distribution and use, see the accompanying README file.
  *
@@ -20,17 +20,17 @@
  *	B = Y + K4 * Cb
  * only the Y term varies among the group of pixels corresponding to a pair
  * of chroma samples, so the rest of the terms can be calculated just once.
- * At typical sampling ratios, this eliminates half or three-quarters of the
- * multiplications needed for color conversion.
+ * At typical sampling ratios, this eliminates half or three-quarters
+ * of the multiplications needed for color conversion.
  *
  * This file currently provides implementations for the following cases:
  *	YCC => RGB color conversion only (YCbCr or BG_YCC).
  *	Sampling ratios of 2h1v or 2h2v.
  *	No scaling needed at upsample time.
  *	Corner-aligned (non-CCIR601) sampling alignment.
- * Other special cases could be added, but in most applications these are
- * the only common cases.  (For uncommon cases we fall back on the more
- * general code in jdsample.c and jdcolor.c.)
+ * Other special cases could be added, but in most applications these
+ * are the only common cases.  (For uncommon cases we fall back on
+ * the more general code in jdsample.c and jdcolor.c.)
  */
 
 #define JPEG_INTERNALS
@@ -286,9 +286,9 @@ h2v1_merged_upsample (j_decompress_ptr cinfo,
     /* Do the chroma part of the calculation */
     cb = GETJSAMPLE(*inptr1++);
     cr = GETJSAMPLE(*inptr2++);
-    cred   = Crrtab[cr];
     cgreen = (int) RIGHT_SHIFT(Cbgtab[cb] + Crgtab[cr], SCALEBITS);
     cblue  = Cbbtab[cb];
+    cred   = Crrtab[cr];
     /* Fetch 2 Y values and emit 2 pixels */
     y  = GETJSAMPLE(*inptr0++);
     outptr[RGB_RED]   = range_limit[y + cred];
@@ -303,15 +303,14 @@ h2v1_merged_upsample (j_decompress_ptr cinfo,
   }
   /* If image width is odd, do the last output column separately */
   if (cinfo->output_width & 1) {
+    y  = GETJSAMPLE(*inptr0);
     cb = GETJSAMPLE(*inptr1);
     cr = GETJSAMPLE(*inptr2);
-    cred   = Crrtab[cr];
-    cgreen = (int) RIGHT_SHIFT(Cbgtab[cb] + Crgtab[cr], SCALEBITS);
-    cblue  = Cbbtab[cb];
-    y  = GETJSAMPLE(*inptr0);
-    outptr[RGB_RED]   = range_limit[y + cred];
-    outptr[RGB_GREEN] = range_limit[y + cgreen];
-    outptr[RGB_BLUE]  = range_limit[y + cblue];
+    outptr[RGB_RED]   = range_limit[y + Crrtab[cr]];
+    outptr[RGB_GREEN] = range_limit[y +
+			      ((int) RIGHT_SHIFT(Cbgtab[cb] + Crgtab[cr],
+						 SCALEBITS))];
+    outptr[RGB_BLUE]  = range_limit[y + Cbbtab[cb]];
   }
 }
 
@@ -350,9 +349,9 @@ h2v2_merged_upsample (j_decompress_ptr cinfo,
     /* Do the chroma part of the calculation */
     cb = GETJSAMPLE(*inptr1++);
     cr = GETJSAMPLE(*inptr2++);
-    cred   = Crrtab[cr];
     cgreen = (int) RIGHT_SHIFT(Cbgtab[cb] + Crgtab[cr], SCALEBITS);
     cblue  = Cbbtab[cb];
+    cred   = Crrtab[cr];
     /* Fetch 4 Y values and emit 4 pixels */
     y  = GETJSAMPLE(*inptr00++);
     outptr0[RGB_RED]   = range_limit[y + cred];
@@ -379,9 +378,9 @@ h2v2_merged_upsample (j_decompress_ptr cinfo,
   if (cinfo->output_width & 1) {
     cb = GETJSAMPLE(*inptr1);
     cr = GETJSAMPLE(*inptr2);
-    cred   = Crrtab[cr];
     cgreen = (int) RIGHT_SHIFT(Cbgtab[cb] + Crgtab[cr], SCALEBITS);
     cblue  = Cbbtab[cb];
+    cred   = Crrtab[cr];
     y  = GETJSAMPLE(*inptr00);
     outptr0[RGB_RED]   = range_limit[y + cred];
     outptr0[RGB_GREEN] = range_limit[y + cgreen];
diff --git a/vendor/jpeg-9e/jdpostct.c b/vendor/jpeg-9f/jdpostct.c
similarity index 100%
rename from vendor/jpeg-9e/jdpostct.c
rename to vendor/jpeg-9f/jdpostct.c
diff --git a/vendor/jpeg-9e/jdsample.c b/vendor/jpeg-9f/jdsample.c
similarity index 100%
rename from vendor/jpeg-9e/jdsample.c
rename to vendor/jpeg-9f/jdsample.c
diff --git a/vendor/jpeg-9e/jdtrans.c b/vendor/jpeg-9f/jdtrans.c
similarity index 100%
rename from vendor/jpeg-9e/jdtrans.c
rename to vendor/jpeg-9f/jdtrans.c
diff --git a/vendor/jpeg-9e/jerror.c b/vendor/jpeg-9f/jerror.c
similarity index 100%
rename from vendor/jpeg-9e/jerror.c
rename to vendor/jpeg-9f/jerror.c
diff --git a/vendor/jpeg-9e/jerror.h b/vendor/jpeg-9f/jerror.h
similarity index 100%
rename from vendor/jpeg-9e/jerror.h
rename to vendor/jpeg-9f/jerror.h
diff --git a/vendor/jpeg-9e/jfdctflt.c b/vendor/jpeg-9f/jfdctflt.c
similarity index 100%
rename from vendor/jpeg-9e/jfdctflt.c
rename to vendor/jpeg-9f/jfdctflt.c
diff --git a/vendor/jpeg-9e/jfdctfst.c b/vendor/jpeg-9f/jfdctfst.c
similarity index 100%
rename from vendor/jpeg-9e/jfdctfst.c
rename to vendor/jpeg-9f/jfdctfst.c
diff --git a/vendor/jpeg-9e/jfdctint.c b/vendor/jpeg-9f/jfdctint.c
similarity index 100%
rename from vendor/jpeg-9e/jfdctint.c
rename to vendor/jpeg-9f/jfdctint.c
diff --git a/vendor/jpeg-9e/jidctflt.c b/vendor/jpeg-9f/jidctflt.c
similarity index 100%
rename from vendor/jpeg-9e/jidctflt.c
rename to vendor/jpeg-9f/jidctflt.c
diff --git a/vendor/jpeg-9e/jidctfst.c b/vendor/jpeg-9f/jidctfst.c
similarity index 100%
rename from vendor/jpeg-9e/jidctfst.c
rename to vendor/jpeg-9f/jidctfst.c
diff --git a/vendor/jpeg-9e/jidctint.c b/vendor/jpeg-9f/jidctint.c
similarity index 100%
rename from vendor/jpeg-9e/jidctint.c
rename to vendor/jpeg-9f/jidctint.c
diff --git a/vendor/jpeg-9e/jinclude.h b/vendor/jpeg-9f/jinclude.h
similarity index 57%
rename from vendor/jpeg-9e/jinclude.h
rename to vendor/jpeg-9f/jinclude.h
index 20ed4ef11f..12ea8cd2fd 100644
--- a/vendor/jpeg-9e/jinclude.h
+++ b/vendor/jpeg-9f/jinclude.h
@@ -2,7 +2,7 @@
  * jinclude.h
  *
  * Copyright (C) 1991-1994, Thomas G. Lane.
- * Modified 2017 by Guido Vollbeding.
+ * Modified 2017-2022 by Guido Vollbeding.
  * This file is part of the Independent JPEG Group's software.
  * For conditions of distribution and use, see the accompanying README file.
  *
@@ -11,8 +11,8 @@
  * care of by the standard jconfig symbols, but on really weird systems
  * you may have to edit this file.)
  *
- * NOTE: this file is NOT intended to be included by applications using the
- * JPEG library.  Most applications need only include jpeglib.h.
+ * NOTE: this file is NOT intended to be included by applications using
+ * the JPEG library.  Most applications need only include jpeglib.h.
  */
 
 
@@ -87,11 +87,71 @@
  *
  * Furthermore, macros are provided for fflush() and ferror() in order
  * to facilitate adaption by applications using an own FILE class.
+ *
+ * You can define your own custom file I/O functions in jconfig.h and
+ * #define JPEG_HAVE_FILE_IO_CUSTOM there to prevent redefinition here.
+ *
+ * You can #define JPEG_USE_FILE_IO_CUSTOM in jconfig.h to use custom file
+ * I/O functions implemented in Delphi VCL (Visual Component Library)
+ * in Vcl.Imaging.jpeg.pas for the TJPEGImage component utilizing
+ * the Delphi RTL (Run-Time Library) TMemoryStream component:
+ *
+ *   procedure jpeg_stdio_src(var cinfo: jpeg_decompress_struct;
+ *     input_file: TStream); external;
+ *
+ *   procedure jpeg_stdio_dest(var cinfo: jpeg_compress_struct;
+ *     output_file: TStream); external;
+ *
+ *   function jfread(var buf; recsize, reccount: Integer; S: TStream): Integer;
+ *   begin
+ *     Result := S.Read(buf, recsize * reccount);
+ *   end;
+ *
+ *   function jfwrite(const buf; recsize, reccount: Integer; S: TStream): Integer;
+ *   begin
+ *     Result := S.Write(buf, recsize * reccount);
+ *   end;
+ *
+ *   function jfflush(S: TStream): Integer;
+ *   begin
+ *     Result := 0;
+ *   end;
+ *
+ *   function jferror(S: TStream): Integer;
+ *   begin
+ *     Result := 0;
+ *   end;
+ *
+ * TMemoryStream of Delphi RTL has the distinctive feature to provide dynamic
+ * memory buffer management with a file/stream-based interface, particularly for
+ * the write (output) operation, which is easier to apply compared with direct
+ * implementations as given in jdatadst.c for memory destination.  Those direct
+ * implementations of dynamic memory write tend to be more difficult to use,
+ * so providing an option like TMemoryStream may be a useful alternative.
+ *
+ * The CFile/CMemFile classes of the Microsoft Foundation Class (MFC) Library
+ * may be used in a similar fashion.
  */
 
+#ifndef JPEG_HAVE_FILE_IO_CUSTOM
+#ifdef JPEG_USE_FILE_IO_CUSTOM
+extern size_t jfread(void * __ptr, size_t __size, size_t __n, FILE * __stream);
+extern size_t jfwrite(const void * __ptr, size_t __size, size_t __n, FILE * __stream);
+extern int    jfflush(FILE * __stream);
+extern int    jferror(FILE * __fp);
+
+#define JFREAD(file,buf,sizeofbuf)  \
+  ((size_t) jfread((void *) (buf), (size_t) 1, (size_t) (sizeofbuf), (file)))
+#define JFWRITE(file,buf,sizeofbuf)  \
+  ((size_t) jfwrite((const void *) (buf), (size_t) 1, (size_t) (sizeofbuf), (file)))
+#define JFFLUSH(file)	jfflush(file)
+#define JFERROR(file)	jferror(file)
+#else
 #define JFREAD(file,buf,sizeofbuf)  \
   ((size_t) fread((void *) (buf), (size_t) 1, (size_t) (sizeofbuf), (file)))
 #define JFWRITE(file,buf,sizeofbuf)  \
   ((size_t) fwrite((const void *) (buf), (size_t) 1, (size_t) (sizeofbuf), (file)))
 #define JFFLUSH(file)	fflush(file)
 #define JFERROR(file)	ferror(file)
+#endif
+#endif
diff --git a/vendor/jpeg-9e/jmemansi.c b/vendor/jpeg-9f/jmemansi.c
similarity index 100%
rename from vendor/jpeg-9e/jmemansi.c
rename to vendor/jpeg-9f/jmemansi.c
diff --git a/vendor/jpeg-9e/jmemdos.c b/vendor/jpeg-9f/jmemdos.c
similarity index 100%
rename from vendor/jpeg-9e/jmemdos.c
rename to vendor/jpeg-9f/jmemdos.c
diff --git a/vendor/jpeg-9e/jmemmac.c b/vendor/jpeg-9f/jmemmac.c
similarity index 100%
rename from vendor/jpeg-9e/jmemmac.c
rename to vendor/jpeg-9f/jmemmac.c
diff --git a/vendor/jpeg-9e/jmemmgr.c b/vendor/jpeg-9f/jmemmgr.c
similarity index 100%
rename from vendor/jpeg-9e/jmemmgr.c
rename to vendor/jpeg-9f/jmemmgr.c
diff --git a/vendor/jpeg-9e/jmemname.c b/vendor/jpeg-9f/jmemname.c
similarity index 100%
rename from vendor/jpeg-9e/jmemname.c
rename to vendor/jpeg-9f/jmemname.c
diff --git a/vendor/jpeg-9e/jmemnobs.c b/vendor/jpeg-9f/jmemnobs.c
similarity index 100%
rename from vendor/jpeg-9e/jmemnobs.c
rename to vendor/jpeg-9f/jmemnobs.c
diff --git a/vendor/jpeg-9e/jmemsys.h b/vendor/jpeg-9f/jmemsys.h
similarity index 100%
rename from vendor/jpeg-9e/jmemsys.h
rename to vendor/jpeg-9f/jmemsys.h
diff --git a/vendor/jpeg-9e/jmorecfg.h b/vendor/jpeg-9f/jmorecfg.h
similarity index 94%
rename from vendor/jpeg-9e/jmorecfg.h
rename to vendor/jpeg-9f/jmorecfg.h
index 679d68bdc5..4638d6af2d 100644
--- a/vendor/jpeg-9e/jmorecfg.h
+++ b/vendor/jpeg-9f/jmorecfg.h
@@ -2,7 +2,7 @@
  * jmorecfg.h
  *
  * Copyright (C) 1991-1997, Thomas G. Lane.
- * Modified 1997-2013 by Guido Vollbeding.
+ * Modified 1997-2022 by Guido Vollbeding.
  * This file is part of the Independent JPEG Group's software.
  * For conditions of distribution and use, see the accompanying README file.
  *
@@ -351,8 +351,8 @@ typedef enum { FALSE = 0, TRUE = 1 } boolean;
 
 #define C_ARITH_CODING_SUPPORTED    /* Arithmetic coding back end? */
 #define C_MULTISCAN_FILES_SUPPORTED /* Multiple-scan JPEG files? */
-#define C_PROGRESSIVE_SUPPORTED	    /* Progressive JPEG? (Requires MULTISCAN)*/
-#define DCT_SCALING_SUPPORTED	    /* Input rescaling via DCT? (Requires DCT_ISLOW)*/
+#define C_PROGRESSIVE_SUPPORTED	    /* Progressive JPEG? (Requires MULTISCAN) */
+#define DCT_SCALING_SUPPORTED	/* Input rescaling via DCT? (Requires DCT_ISLOW) */
 #define ENTROPY_OPT_SUPPORTED	    /* Optimization of entropy coding parms? */
 /* Note: if you selected more than 8-bit data precision, it is dangerous to
  * turn off ENTROPY_OPT_SUPPORTED.  The standard Huffman tables are only
@@ -369,8 +369,8 @@ typedef enum { FALSE = 0, TRUE = 1 } boolean;
 
 #define D_ARITH_CODING_SUPPORTED    /* Arithmetic coding back end? */
 #define D_MULTISCAN_FILES_SUPPORTED /* Multiple-scan JPEG files? */
-#define D_PROGRESSIVE_SUPPORTED	    /* Progressive JPEG? (Requires MULTISCAN)*/
-#define IDCT_SCALING_SUPPORTED	    /* Output rescaling via IDCT? (Requires DCT_ISLOW)*/
+#define D_PROGRESSIVE_SUPPORTED	    /* Progressive JPEG? (Requires MULTISCAN) */
+#define IDCT_SCALING_SUPPORTED	/* Output rescaling via IDCT? (Requires DCT_ISLOW) */
 #define SAVE_MARKERS_SUPPORTED	    /* jpeg_save_markers() needed? */
 #define BLOCK_SMOOTHING_SUPPORTED   /* Block smoothing? (Progressive only) */
 #undef  UPSAMPLE_SCALING_SUPPORTED  /* Output rescaling at upsample stage? */
@@ -384,20 +384,31 @@ typedef enum { FALSE = 0, TRUE = 1 } boolean;
 /*
  * Ordering of RGB data in scanlines passed to or from the application.
  * If your application wants to deal with data in the order B,G,R, just
- * change these macros.  You can also deal with formats such as R,G,B,X
- * (one extra byte per pixel) by changing RGB_PIXELSIZE.  Note that changing
- * the offsets will also change the order in which colormap data is organized.
+ * #define JPEG_USE_RGB_CUSTOM in jconfig.h, or define your own custom
+ * order in jconfig.h and #define JPEG_HAVE_RGB_CUSTOM.
+ * You can also deal with formats such as R,G,B,X (one extra byte per pixel)
+ * by changing RGB_PIXELSIZE.
+ * Note that changing the offsets will also change
+ * the order in which colormap data is organized.
  * RESTRICTIONS:
  * 1. The sample applications cjpeg,djpeg do NOT support modified RGB formats.
  * 2. The color quantizer modules will not behave desirably if RGB_PIXELSIZE
- *    is not 3 (they don't understand about dummy color components!).  So you
- *    can't use color quantization if you change that value.
+ *    is not 3 (they don't understand about dummy color components!).
+ *    So you can't use color quantization if you change that value.
  */
 
+#ifndef JPEG_HAVE_RGB_CUSTOM
+#ifdef JPEG_USE_RGB_CUSTOM
+#define RGB_RED		2	/* Offset of Red in an RGB scanline element */
+#define RGB_GREEN	1	/* Offset of Green */
+#define RGB_BLUE	0	/* Offset of Blue */
+#else
 #define RGB_RED		0	/* Offset of Red in an RGB scanline element */
 #define RGB_GREEN	1	/* Offset of Green */
 #define RGB_BLUE	2	/* Offset of Blue */
+#endif
 #define RGB_PIXELSIZE	3	/* JSAMPLEs per RGB scanline element */
+#endif
 
 
 /* Definitions for speed-related optimizations. */
diff --git a/vendor/jpeg-9e/jpegint.h b/vendor/jpeg-9f/jpegint.h
similarity index 100%
rename from vendor/jpeg-9e/jpegint.h
rename to vendor/jpeg-9f/jpegint.h
diff --git a/vendor/jpeg-9e/jpeglib.h b/vendor/jpeg-9f/jpeglib.h
similarity index 99%
rename from vendor/jpeg-9e/jpeglib.h
rename to vendor/jpeg-9f/jpeglib.h
index b1fa8ea9ad..e7e15ab2cd 100644
--- a/vendor/jpeg-9e/jpeglib.h
+++ b/vendor/jpeg-9f/jpeglib.h
@@ -2,7 +2,7 @@
  * jpeglib.h
  *
  * Copyright (C) 1991-1998, Thomas G. Lane.
- * Modified 2002-2020 by Guido Vollbeding.
+ * Modified 2002-2022 by Guido Vollbeding.
  * This file is part of the Independent JPEG Group's software.
  * For conditions of distribution and use, see the accompanying README file.
  *
@@ -39,7 +39,7 @@ extern "C" {
 
 #define JPEG_LIB_VERSION        90	/* Compatibility version 9.0 */
 #define JPEG_LIB_VERSION_MAJOR  9
-#define JPEG_LIB_VERSION_MINOR  5
+#define JPEG_LIB_VERSION_MINOR  6
 
 
 /* Various constants determining the sizes of things.
diff --git a/vendor/jpeg-9e/jpegtran.c b/vendor/jpeg-9f/jpegtran.c
similarity index 100%
rename from vendor/jpeg-9e/jpegtran.c
rename to vendor/jpeg-9f/jpegtran.c
diff --git a/vendor/jpeg-9e/jquant1.c b/vendor/jpeg-9f/jquant1.c
similarity index 100%
rename from vendor/jpeg-9e/jquant1.c
rename to vendor/jpeg-9f/jquant1.c
diff --git a/vendor/jpeg-9e/jquant2.c b/vendor/jpeg-9f/jquant2.c
similarity index 100%
rename from vendor/jpeg-9e/jquant2.c
rename to vendor/jpeg-9f/jquant2.c
diff --git a/vendor/jpeg-9e/jutils.c b/vendor/jpeg-9f/jutils.c
similarity index 100%
rename from vendor/jpeg-9e/jutils.c
rename to vendor/jpeg-9f/jutils.c
diff --git a/vendor/jpeg-9e/jversion.h b/vendor/jpeg-9f/jversion.h
similarity index 59%
rename from vendor/jpeg-9e/jversion.h
rename to vendor/jpeg-9f/jversion.h
index 17134b7a5b..df53ef5e55 100644
--- a/vendor/jpeg-9e/jversion.h
+++ b/vendor/jpeg-9f/jversion.h
@@ -1,7 +1,7 @@
 /*
  * jversion.h
  *
- * Copyright (C) 1991-2022, Thomas G. Lane, Guido Vollbeding.
+ * Copyright (C) 1991-2024, Thomas G. Lane, Guido Vollbeding.
  * This file is part of the Independent JPEG Group's software.
  * For conditions of distribution and use, see the accompanying README file.
  *
@@ -9,6 +9,6 @@
  */
 
 
-#define JVERSION	"9e  16-Jan-2022"
+#define JVERSION	"9f  14-Jan-2024"
 
-#define JCOPYRIGHT	"Copyright (C) 2022, Thomas G. Lane, Guido Vollbeding"
+#define JCOPYRIGHT	"Copyright (C) 2024, Thomas G. Lane, Guido Vollbeding"
diff --git a/vendor/jpeg-9e/premake5.lua b/vendor/jpeg-9f/premake5.lua
similarity index 100%
rename from vendor/jpeg-9e/premake5.lua
rename to vendor/jpeg-9f/premake5.lua
diff --git a/vendor/jpeg-9e/rdbmp.c b/vendor/jpeg-9f/rdbmp.c
similarity index 100%
rename from vendor/jpeg-9e/rdbmp.c
rename to vendor/jpeg-9f/rdbmp.c
diff --git a/vendor/jpeg-9e/rdcolmap.c b/vendor/jpeg-9f/rdcolmap.c
similarity index 100%
rename from vendor/jpeg-9e/rdcolmap.c
rename to vendor/jpeg-9f/rdcolmap.c
diff --git a/vendor/jpeg-9e/rdgif.c b/vendor/jpeg-9f/rdgif.c
similarity index 100%
rename from vendor/jpeg-9e/rdgif.c
rename to vendor/jpeg-9f/rdgif.c
diff --git a/vendor/jpeg-9e/rdjpgcom.c b/vendor/jpeg-9f/rdjpgcom.c
similarity index 100%
rename from vendor/jpeg-9e/rdjpgcom.c
rename to vendor/jpeg-9f/rdjpgcom.c
diff --git a/vendor/jpeg-9e/rdppm.c b/vendor/jpeg-9f/rdppm.c
similarity index 100%
rename from vendor/jpeg-9e/rdppm.c
rename to vendor/jpeg-9f/rdppm.c
diff --git a/vendor/jpeg-9e/rdrle.c b/vendor/jpeg-9f/rdrle.c
similarity index 100%
rename from vendor/jpeg-9e/rdrle.c
rename to vendor/jpeg-9f/rdrle.c
diff --git a/vendor/jpeg-9e/rdswitch.c b/vendor/jpeg-9f/rdswitch.c
similarity index 100%
rename from vendor/jpeg-9e/rdswitch.c
rename to vendor/jpeg-9f/rdswitch.c
diff --git a/vendor/jpeg-9e/rdtarga.c b/vendor/jpeg-9f/rdtarga.c
similarity index 100%
rename from vendor/jpeg-9e/rdtarga.c
rename to vendor/jpeg-9f/rdtarga.c
diff --git a/vendor/jpeg-9e/transupp.c b/vendor/jpeg-9f/transupp.c
similarity index 99%
rename from vendor/jpeg-9e/transupp.c
rename to vendor/jpeg-9f/transupp.c
index 6d7d090234..6518936a0d 100644
--- a/vendor/jpeg-9e/transupp.c
+++ b/vendor/jpeg-9f/transupp.c
@@ -1,7 +1,7 @@
 /*
  * transupp.c
  *
- * Copyright (C) 1997-2019, Thomas G. Lane, Guido Vollbeding.
+ * Copyright (C) 1997-2023, Thomas G. Lane, Guido Vollbeding.
  * This file is part of the Independent JPEG Group's software.
  * For conditions of distribution and use, see the accompanying README file.
  *
@@ -195,12 +195,11 @@ requant_comp (j_decompress_ptr cinfo, jpeg_component_info *compptr,
 	      jvirt_barray_ptr coef_array, JQUANT_TBL *qtblptr1)
 {
   JDIMENSION blk_x, blk_y;
-  int offset_y, k;
+  int offset_y, k, temp, qval;
   JQUANT_TBL *qtblptr;
   JBLOCKARRAY buffer;
   JBLOCKROW block;
   JCOEFPTR ptr;
-  JCOEF temp, qval;
 
   qtblptr = compptr->quant_table;
   for (blk_y = 0; blk_y < compptr->height_in_blocks;
@@ -213,27 +212,27 @@ requant_comp (j_decompress_ptr cinfo, jpeg_component_info *compptr,
       for (blk_x = 0; blk_x < compptr->width_in_blocks; blk_x++) {
 	ptr = block[blk_x];
 	for (k = 0; k < DCTSIZE2; k++) {
-	  temp = qtblptr->quantval[k];
 	  qval = qtblptr1->quantval[k];
-	  if (temp != qval) {
-	    temp *= ptr[k];
-	    /* The following quantization code is a copy from jcdctmgr.c */
+	  if (qval == 0) continue;
+	  temp = qtblptr->quantval[k];
+	  if (temp == qval) continue;
+	  temp *= ptr[k];
+	  /* The following quantization code is a copy from jcdctmgr.c */
 #ifdef FAST_DIVIDE
 #define DIVIDE_BY(a,b)	a /= b
 #else
 #define DIVIDE_BY(a,b)	if (a >= b) a /= b; else a = 0
 #endif
-	    if (temp < 0) {
-	      temp = -temp;
-	      temp += qval>>1;	/* for rounding */
-	      DIVIDE_BY(temp, qval);
-	      temp = -temp;
-	    } else {
-	      temp += qval>>1;	/* for rounding */
-	      DIVIDE_BY(temp, qval);
-	    }
-	    ptr[k] = temp;
+	  if (temp < 0) {
+	    temp = -temp;
+	    temp += qval>>1;	/* for rounding */
+	    DIVIDE_BY(temp, qval);
+	    temp = -temp;
+	  } else {
+	    temp += qval>>1;	/* for rounding */
+	    DIVIDE_BY(temp, qval);
 	  }
+	  ptr[k] = (JCOEF) temp;
 	}
       }
     }
@@ -248,11 +247,11 @@ largest_common_denominator(JCOEF a, JCOEF b)
 {
   JCOEF c;
 
-  do {
+  while (b) {
     c = a % b;
     a = b;
     b = c;
-  } while (c);
+  }
 
   return a;
 }
diff --git a/vendor/jpeg-9e/transupp.h b/vendor/jpeg-9f/transupp.h
similarity index 100%
rename from vendor/jpeg-9e/transupp.h
rename to vendor/jpeg-9f/transupp.h
diff --git a/vendor/jpeg-9e/wrbmp.c b/vendor/jpeg-9f/wrbmp.c
similarity index 100%
rename from vendor/jpeg-9e/wrbmp.c
rename to vendor/jpeg-9f/wrbmp.c
diff --git a/vendor/jpeg-9e/wrgif.c b/vendor/jpeg-9f/wrgif.c
similarity index 100%
rename from vendor/jpeg-9e/wrgif.c
rename to vendor/jpeg-9f/wrgif.c
diff --git a/vendor/jpeg-9e/wrjpgcom.c b/vendor/jpeg-9f/wrjpgcom.c
similarity index 100%
rename from vendor/jpeg-9e/wrjpgcom.c
rename to vendor/jpeg-9f/wrjpgcom.c
diff --git a/vendor/jpeg-9e/wrppm.c b/vendor/jpeg-9f/wrppm.c
similarity index 100%
rename from vendor/jpeg-9e/wrppm.c
rename to vendor/jpeg-9f/wrppm.c
diff --git a/vendor/jpeg-9e/wrrle.c b/vendor/jpeg-9f/wrrle.c
similarity index 100%
rename from vendor/jpeg-9e/wrrle.c
rename to vendor/jpeg-9f/wrrle.c
diff --git a/vendor/jpeg-9e/wrtarga.c b/vendor/jpeg-9f/wrtarga.c
similarity index 100%
rename from vendor/jpeg-9e/wrtarga.c
rename to vendor/jpeg-9f/wrtarga.c
diff --git a/vendor/json-c/ChangeLog b/vendor/json-c/ChangeLog
index b03a77710e..d6387d854f 100644
--- a/vendor/json-c/ChangeLog
+++ b/vendor/json-c/ChangeLog
@@ -1,3 +1,42 @@
+0.17-master:
+
+The below changelog is incomplete. For this merge in mtasa-blue, we are using revision 6e481aa @ https://github.com/json-c/json-c
+
+
+0.17 (up to commit 077661f, 2023-08-08)
+========================================
+
+Deprecated and removed features:
+--------------------------------
+* None
+
+New features
+------------
+* json_patch: add first implementation only with patch application
+* Add --disable-static and --disable-dynamic options to the cmake-configure script.
+* Add -DBUILD_APPS=NO option to disable app build
+* Minimum cmake version is now 3.9
+
+Significant changes and bug fixes
+---------------------------------
+* When serializing with JSON_C_TO_STRING_PRETTY set, keep the opening and 
+  closing curly or square braces on same line for empty objects or arrays.
+* Disable locale handling when targeting a uClibc system due to problems
+  with its duplocale() function.
+* When parsing with JSON_TOKENER_STRICT set, integer overflow/underflow
+  now result in a json_tokener_error_parse_number.  Without that flag
+  values are capped at INT64_MIN/UINT64_MAX.
+* Fix memory leak with emtpy strings in json_object_set_string
+* json_object_from_fd_ex: fail if file is too large (>=INT_MAX bytes)
+* Add back json_number_chars, but only because it's part of the public API.
+* Entirely drop mode bits from open(O_RDONLY) to avoid warnings on certain
+  platforms.
+* Specify dependent libraries, including -lbsd, in a more consistent way so
+  linking against a static json-c works better
+* Fix a variety of build problems and add & improve tests
+* Update RFC reference to https://www.rfc-editor.org/rfc/rfc8259
+
+***
 
 0.16 (up to commit 66dcdf5, 2022-04-13)
 ========================================
diff --git a/vendor/json-c/arraylist.c b/vendor/json-c/arraylist.c
index d8e12d11cb..bfc1425197 100644
--- a/vendor/json-c/arraylist.c
+++ b/vendor/json-c/arraylist.c
@@ -125,6 +125,27 @@ int array_list_shrink(struct array_list *arr, size_t empty_slots)
 	return 0;
 }
 
+int array_list_insert_idx(struct array_list *arr, size_t idx, void *data)
+{
+	size_t move_amount;
+
+	if (idx >= arr->length)
+		return array_list_put_idx(arr, idx, data);
+
+	/* we're at full size, what size_t can support */
+	if (arr->length == SIZE_T_MAX)
+		return -1;
+
+	if (array_list_expand_internal(arr, arr->length + 1))
+		return -1;
+
+	move_amount = (arr->length - idx) * sizeof(void *);
+	memmove(arr->array + idx + 1, arr->array + idx, move_amount);
+	arr->array[idx] = data;
+	arr->length++;
+	return 0;
+}
+
 //static inline int _array_list_put_idx(struct array_list *arr, size_t idx, void *data)
 int array_list_put_idx(struct array_list *arr, size_t idx, void *data)
 {
diff --git a/vendor/json-c/arraylist.h b/vendor/json-c/arraylist.h
index f541706936..a12f27f54f 100644
--- a/vendor/json-c/arraylist.h
+++ b/vendor/json-c/arraylist.h
@@ -62,6 +62,8 @@ extern void array_list_free(struct array_list *al);
 
 extern void *array_list_get_idx(struct array_list *al, size_t i);
 
+extern int array_list_insert_idx(struct array_list *al, size_t i, void *data);
+
 extern int array_list_put_idx(struct array_list *al, size_t i, void *data);
 
 extern int array_list_add(struct array_list *al, void *data);
diff --git a/vendor/json-c/json_c_version.h b/vendor/json-c/json_c_version.h
index 1b7d531a69..8bf2c34829 100644
--- a/vendor/json-c/json_c_version.h
+++ b/vendor/json-c/json_c_version.h
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2012,2017-2022 Eric Haszlakiewicz
+ * Copyright (c) 2012,2017 Eric Haszlakiewicz
  *
  * This library is free software; you can redistribute it and/or modify
  * it under the terms of the MIT license. See COPYING for details.
@@ -17,11 +17,11 @@ extern "C" {
 #endif
 
 #define JSON_C_MAJOR_VERSION 0
-#define JSON_C_MINOR_VERSION 16
-#define JSON_C_MICRO_VERSION 0
+#define JSON_C_MINOR_VERSION 17
+#define JSON_C_MICRO_VERSION 99
 #define JSON_C_VERSION_NUM \
 	((JSON_C_MAJOR_VERSION << 16) | (JSON_C_MINOR_VERSION << 8) | JSON_C_MICRO_VERSION)
-#define JSON_C_VERSION "0.16"
+#define JSON_C_VERSION "0.17.99"
 
 #ifndef JSON_EXPORT
 #if defined(_MSC_VER) && defined(JSON_C_DLL)
diff --git a/vendor/json-c/json_config.h b/vendor/json-c/json_config.h
index f7fcc64345..9c542a4086 100644
--- a/vendor/json-c/json_config.h
+++ b/vendor/json-c/json_config.h
@@ -1,2 +1,5 @@
+
 /* Define to 1 if you have the  header file. */
+#if defined(_MSC_VER) && _MSC_VER >= 1800
 #define JSON_C_HAVE_INTTYPES_H 1
+#endif
diff --git a/vendor/json-c/json_inttypes.h b/vendor/json-c/json_inttypes.h
index e047d4f18b..a901a8ef39 100644
--- a/vendor/json-c/json_inttypes.h
+++ b/vendor/json-c/json_inttypes.h
@@ -21,4 +21,9 @@
 
 #endif
 
+#if defined(_MSC_VER)
+#include 
+typedef SSIZE_T ssize_t;
+#endif
+
 #endif
diff --git a/vendor/json-c/json_object.c b/vendor/json-c/json_object.c
index e0efbe502c..54413942de 100644
--- a/vendor/json-c/json_object.c
+++ b/vendor/json-c/json_object.c
@@ -53,6 +53,7 @@
 #endif
 #endif
 
+const char *json_number_chars = "0123456789.+-eE"; /* Unused, but part of public API, drop for 1.0 */
 const char *json_hex_chars = "0123456789abcdefABCDEF";
 
 static void json_object_generic_delete(struct json_object *jso);
@@ -64,6 +65,12 @@ static void json_object_generic_delete(struct json_object *jso);
 #define inline
 #endif
 
+/* define colors */
+#define ANSI_COLOR_RESET "\033[0m"
+#define ANSI_COLOR_FG_GREEN "\033[0;32m"
+#define ANSI_COLOR_FG_BLUE "\033[0;34m"
+#define ANSI_COLOR_FG_MAGENTA "\033[0;35m"
+
 /*
  * Helper functions to more safely cast to a particular type of json_object
  */
@@ -460,35 +467,45 @@ static int json_object_object_to_json_string(struct json_object *jso, struct pri
 	struct json_object_iter iter;
 
 	printbuf_strappend(pb, "{" /*}*/);
-	if (flags & JSON_C_TO_STRING_PRETTY)
-		printbuf_strappend(pb, "\n");
 	json_object_object_foreachC(jso, iter)
 	{
 		if (had_children)
 		{
 			printbuf_strappend(pb, ",");
-			if (flags & JSON_C_TO_STRING_PRETTY)
-				printbuf_strappend(pb, "\n");
 		}
+		if (flags & JSON_C_TO_STRING_PRETTY)
+			printbuf_strappend(pb, "\n");
 		had_children = 1;
 		if (flags & JSON_C_TO_STRING_SPACED && !(flags & JSON_C_TO_STRING_PRETTY))
 			printbuf_strappend(pb, " ");
 		indent(pb, level + 1, flags);
+		if (flags & JSON_C_TO_STRING_COLOR)
+			printbuf_strappend(pb, ANSI_COLOR_FG_BLUE);
+
 		printbuf_strappend(pb, "\"");
 		json_escape_str(pb, iter.key, strlen(iter.key), flags);
+		printbuf_strappend(pb, "\"");
+
+		if (flags & JSON_C_TO_STRING_COLOR)
+			printbuf_strappend(pb, ANSI_COLOR_RESET);
+
 		if (flags & JSON_C_TO_STRING_SPACED)
-			printbuf_strappend(pb, "\": ");
+			printbuf_strappend(pb, ": ");
 		else
-			printbuf_strappend(pb, "\":");
-		if (iter.val == NULL)
+			printbuf_strappend(pb, ":");
+
+		if (iter.val == NULL) {
+			if (flags & JSON_C_TO_STRING_COLOR)
+				printbuf_strappend(pb, ANSI_COLOR_FG_MAGENTA);
 			printbuf_strappend(pb, "null");
-		else if (iter.val->_to_json_string(iter.val, pb, level + 1, flags) < 0)
+			if (flags & JSON_C_TO_STRING_COLOR)
+				printbuf_strappend(pb, ANSI_COLOR_RESET);
+		} else if (iter.val->_to_json_string(iter.val, pb, level + 1, flags) < 0)
 			return -1;
 	}
-	if (flags & JSON_C_TO_STRING_PRETTY)
+	if ((flags & JSON_C_TO_STRING_PRETTY) && had_children)
 	{
-		if (had_children)
-			printbuf_strappend(pb, "\n");
+		printbuf_strappend(pb, "\n");
 		indent(pb, level, flags);
 	}
 	if (flags & JSON_C_TO_STRING_SPACED && !(flags & JSON_C_TO_STRING_PRETTY))
@@ -629,9 +646,18 @@ void json_object_object_del(struct json_object *jso, const char *key)
 static int json_object_boolean_to_json_string(struct json_object *jso, struct printbuf *pb,
                                               int level, int flags)
 {
+	int ret;
+
+	if (flags & JSON_C_TO_STRING_COLOR)
+		printbuf_strappend(pb, ANSI_COLOR_FG_MAGENTA);
+
 	if (JC_BOOL(jso)->c_boolean)
-		return printbuf_strappend(pb, "true");
-	return printbuf_strappend(pb, "false");
+		ret = printbuf_strappend(pb, "true");
+	else
+		ret = printbuf_strappend(pb, "false");
+	if (ret > -1 && flags & JSON_C_TO_STRING_COLOR)
+		return printbuf_strappend(pb, ANSI_COLOR_RESET);
+	return ret;
 }
 
 struct json_object *json_object_new_boolean(json_bool b)
@@ -1220,9 +1246,13 @@ static int json_object_string_to_json_string(struct json_object *jso, struct pri
                                              int level, int flags)
 {
 	ssize_t len = JC_STRING(jso)->len;
+	if (flags & JSON_C_TO_STRING_COLOR)
+		printbuf_strappend(pb, ANSI_COLOR_FG_GREEN);
 	printbuf_strappend(pb, "\"");
 	json_escape_str(pb, get_string_component(jso), len < 0 ? -(ssize_t)len : len, flags);
 	printbuf_strappend(pb, "\"");
+	if (flags & JSON_C_TO_STRING_COLOR)
+		printbuf_strappend(pb, ANSI_COLOR_RESET);
 	return 0;
 }
 
@@ -1381,31 +1411,34 @@ static int json_object_array_to_json_string(struct json_object *jso, struct prin
 	size_t ii;
 
 	printbuf_strappend(pb, "[");
-	if (flags & JSON_C_TO_STRING_PRETTY)
-		printbuf_strappend(pb, "\n");
 	for (ii = 0; ii < json_object_array_length(jso); ii++)
 	{
 		struct json_object *val;
 		if (had_children)
 		{
 			printbuf_strappend(pb, ",");
-			if (flags & JSON_C_TO_STRING_PRETTY)
-				printbuf_strappend(pb, "\n");
 		}
+		if (flags & JSON_C_TO_STRING_PRETTY)
+			printbuf_strappend(pb, "\n");
 		had_children = 1;
 		if (flags & JSON_C_TO_STRING_SPACED && !(flags & JSON_C_TO_STRING_PRETTY))
 			printbuf_strappend(pb, " ");
 		indent(pb, level + 1, flags);
 		val = json_object_array_get_idx(jso, ii);
-		if (val == NULL)
+		if (val == NULL) {
+
+			if (flags & JSON_C_TO_STRING_COLOR)
+				printbuf_strappend(pb, ANSI_COLOR_FG_MAGENTA);
 			printbuf_strappend(pb, "null");
-		else if (val->_to_json_string(val, pb, level + 1, flags) < 0)
+			if (flags & JSON_C_TO_STRING_COLOR)
+				printbuf_strappend(pb, ANSI_COLOR_RESET);
+
+		} else if (val->_to_json_string(val, pb, level + 1, flags) < 0)
 			return -1;
 	}
-	if (flags & JSON_C_TO_STRING_PRETTY)
+	if ((flags & JSON_C_TO_STRING_PRETTY) && had_children)
 	{
-		if (had_children)
-			printbuf_strappend(pb, "\n");
+		printbuf_strappend(pb, "\n");
 		indent(pb, level, flags);
 	}
 
@@ -1487,6 +1520,12 @@ int json_object_array_add(struct json_object *jso, struct json_object *val)
 	return array_list_add(JC_ARRAY(jso)->c_array, val);
 }
 
+int json_object_array_insert_idx(struct json_object *jso, size_t idx, struct json_object *val)
+{
+	assert(json_object_get_type(jso) == json_type_array);
+	return array_list_insert_idx(JC_ARRAY(jso)->c_array, idx, val);
+}
+
 int json_object_array_put_idx(struct json_object *jso, size_t idx, struct json_object *val)
 {
 	assert(json_object_get_type(jso) == json_type_array);
diff --git a/vendor/json-c/json_object.h b/vendor/json-c/json_object.h
index e22392f39c..b767b0213e 100644
--- a/vendor/json-c/json_object.h
+++ b/vendor/json-c/json_object.h
@@ -74,6 +74,15 @@ extern "C" {
  */
 #define JSON_C_TO_STRING_NOSLASHESCAPE (1 << 4)
 
+/**
+ * A flag for the json_object_to_json_string_ext() and
+ * json_object_to_file_ext() functions which causes
+ * the output to be formatted.
+ *
+ * Use color for printing json.
+ */
+#define JSON_C_TO_STRING_COLOR (1 << 5)
+
 /**
  * A flag for the json_object_object_add_ex function which
  * causes the value to be added without a check if it already exists.
@@ -163,10 +172,10 @@ JSON_EXPORT struct json_object *json_object_get(struct json_object *obj);
  * is a member of (unless you know you've called `json_object_get(obj)` to
  * explicitly increment the refcount).
  *
- * NULL may be passed, which which case this is a no-op.
+ * NULL may be passed, in which case this is a no-op.
  *
  * @param obj the json_object instance
- * @returns 1 if the object was freed.
+ * @returns 1 if the object was freed, 0 if only the refcount was decremented
  * @see json_object_get()
  */
 JSON_EXPORT int json_object_put(struct json_object *obj);
@@ -182,6 +191,7 @@ JSON_EXPORT int json_object_put(struct json_object *obj);
      json_type_object,
      json_type_array,
      json_type_string
+ * @returns 1 if the object is of the specified type, 0 otherwise
  */
 JSON_EXPORT int json_object_is_type(const struct json_object *obj, enum json_type type);
 
@@ -449,9 +459,9 @@ JSON_EXPORT struct json_object *json_object_object_get(const struct json_object
  *              associated with the given field name.
  *
  *              It is safe to pass a NULL value.
- * @returns whether or not the key exists
+ * @returns 1 if the key exists, 0 otherwise
  */
-JSON_EXPORT json_bool json_object_object_get_ex(const struct json_object *obj, const char *key,
+JSON_EXPORT int json_object_object_get_ex(const struct json_object *obj, const char *key,
                                                 struct json_object **value);
 
 /** Delete the given json_object field
@@ -551,7 +561,7 @@ JSON_EXPORT struct array_list *json_object_get_array(const struct json_object *o
 
 /** Get the length of a json_object of type json_type_array
  * @param obj the json_object instance
- * @returns an int
+ * @returns the length of the array
  */
 JSON_EXPORT size_t json_object_array_length(const struct json_object *obj);
 
@@ -613,6 +623,25 @@ JSON_EXPORT int json_object_array_add(struct json_object *obj, struct json_objec
 JSON_EXPORT int json_object_array_put_idx(struct json_object *obj, size_t idx,
                                           struct json_object *val);
 
+/** Insert an element at a specified index in an array (a json_object of type json_type_array)
+ *
+ * The reference count will *not* be incremented. This is to make adding
+ * fields to objects in code more compact. If you want to retain a reference
+ * to an added object you must wrap the passed object with json_object_get
+ *
+ * The array size will be automatically be expanded to the size of the
+ * index if the index is larger than the current size.
+ * If the index is within the existing array limits, then the element will be
+ * inserted and all elements will be shifted. This is the only difference between
+ * this function and json_object_array_put_idx().
+ *
+ * @param obj the json_object instance
+ * @param idx the index to insert the element at
+ * @param val the json_object to be added
+ */
+JSON_EXPORT int json_object_array_insert_idx(struct json_object *obj, size_t idx,
+                                             struct json_object *val);
+
 /** Get the element at specified index of array `obj` (which must be a json_object of type json_type_array)
  *
  * *No* reference counts will be changed, and ownership of the returned
@@ -1014,7 +1043,7 @@ JSON_EXPORT struct json_object *json_object_new_null(void);
  *
  * @param obj1 the first json_object instance
  * @param obj2 the second json_object instance
- * @returns whether both objects are equal or not
+ * @returns 1 if both objects are equal, 0 otherwise
  */
 JSON_EXPORT int json_object_equal(struct json_object *obj1, struct json_object *obj2);
 
diff --git a/vendor/json-c/json_patch.c b/vendor/json-c/json_patch.c
new file mode 100644
index 0000000000..5bbc308a99
--- /dev/null
+++ b/vendor/json-c/json_patch.c
@@ -0,0 +1,332 @@
+/*
+ * Copyright (c) 2021 Alexandru Ardelean.
+ * Copyright (c) 2023 Eric Hawicz
+ *
+ * This is free software; you can redistribute it and/or modify
+ * it under the terms of the MIT license. See COPYING for details.
+ */
+
+#include "config.h"
+
+#include 
+#include 
+#include 
+
+#include "json_patch.h"
+#include "json_object_private.h"
+#include "json_pointer_private.h"
+
+#include 
+#ifndef SIZE_T_MAX
+#if SIZEOF_SIZE_T == SIZEOF_INT
+#define SIZE_T_MAX UINT_MAX
+#elif SIZEOF_SIZE_T == SIZEOF_LONG
+#define SIZE_T_MAX ULONG_MAX
+#elif SIZEOF_SIZE_T == SIZEOF_LONG_LONG
+#define SIZE_T_MAX ULLONG_MAX
+#else
+#error Unable to determine size of size_t
+#endif
+#endif
+
+#define _set_err(_errval, _errmsg) do { \
+	patch_error->errno_code = (_errval); \
+	patch_error->errmsg = (_errmsg); \
+	errno = 0;  /* To avoid confusion */ \
+} while (0)
+
+#define _set_err_from_ptrget(_errval, _fieldname) do { \
+	patch_error->errno_code = (_errval); \
+	patch_error->errmsg = (_errval) == ENOENT ? \
+		"Did not find element referenced by " _fieldname " field" : \
+		"Invalid " _fieldname " field"; \
+	errno = 0;  /* To avoid confusion */ \
+} while(0)
+
+/**
+ * JavaScript Object Notation (JSON) Patch
+ *   RFC 6902 - https://tools.ietf.org/html/rfc6902
+ */
+
+static int json_patch_apply_test(struct json_object **res,
+                                 struct json_object *patch_elem,
+                                 const char *path, struct json_patch_error *patch_error)
+{
+	struct json_object *value1, *value2;
+
+	if (!json_object_object_get_ex(patch_elem, "value", &value1)) {
+		_set_err(EINVAL, "Patch object does not contain a 'value' field");
+		return -1;
+	}
+
+	if (json_pointer_get(*res, path, &value2))
+	{
+		_set_err_from_ptrget(errno, "path");
+		return -1;
+	}
+
+	if (!json_object_equal(value1, value2)) {
+		_set_err(ENOENT, "Value of element referenced by 'path' field did not match 'value' field");
+		return -1;
+	}
+
+	return 0;
+}
+
+static int __json_patch_apply_remove(struct json_pointer_get_result *jpres)
+{
+	if (json_object_is_type(jpres->parent, json_type_array)) {
+		return json_object_array_del_idx(jpres->parent, jpres->index_in_parent, 1);
+	} else if (jpres->parent && jpres->key_in_parent) {
+		json_object_object_del(jpres->parent, jpres->key_in_parent);
+		return 0;
+	} else {
+		// We're removing the root object
+		(void)json_object_put(jpres->obj);
+		jpres->obj = NULL;
+		return 0;
+	}
+}
+
+static int json_patch_apply_remove(struct json_object **res, const char *path, struct json_patch_error *patch_error)
+{
+	struct json_pointer_get_result jpres;
+	int rc;
+
+	if (json_pointer_get_internal(*res, path, &jpres))
+	{
+		_set_err_from_ptrget(errno, "path");
+		return -1;
+	}
+
+	rc = __json_patch_apply_remove(&jpres);
+	if (rc < 0)
+		_set_err(EINVAL, "Unable to remove path referenced by 'path' field");
+	// This means we removed and freed the root object, i.e. *res
+	if (jpres.parent == NULL)
+		*res = NULL;
+	return rc;
+}
+
+// callback for json_pointer_set_with_array_cb()
+static int json_object_array_insert_idx_cb(struct json_object *parent, size_t idx,
+                                           struct json_object *value, void *priv)
+{
+	int rc;
+	int *add = priv;
+
+	if (idx > json_object_array_length(parent))
+	{
+		// Note: will propagate back out through json_pointer_set_with_array_cb()
+		errno = EINVAL;
+		return -1;
+	}
+
+	if (*add)
+		rc = json_object_array_insert_idx(parent, idx, value);
+	else
+		rc = json_object_array_put_idx(parent, idx, value);
+	if (rc < 0)
+		errno = EINVAL;
+	return rc;
+}
+
+static int json_patch_apply_add_replace(struct json_object **res,
+                                        struct json_object *patch_elem,
+                                        const char *path, int add, struct json_patch_error *patch_error)
+{
+	struct json_object *value;
+	int rc;
+
+	if (!json_object_object_get_ex(patch_elem, "value", &value)) {
+		_set_err(EINVAL, "Patch object does not contain a 'value' field");
+		return -1;
+	}
+	/* if this is a replace op, then we need to make sure it exists before replacing */
+	if (!add && json_pointer_get(*res, path, NULL)) {
+		_set_err_from_ptrget(errno, "path");
+		return -1;
+	}
+
+	rc = json_pointer_set_with_array_cb(res, path, json_object_get(value),
+					    json_object_array_insert_idx_cb, &add);
+	if (rc)
+	{
+		_set_err(errno, "Failed to set value at path referenced by 'path' field");
+		json_object_put(value);
+	}
+
+	return rc;
+}
+
+// callback for json_pointer_set_with_array_cb()
+static int json_object_array_move_cb(struct json_object *parent, size_t idx,
+                                     struct json_object *value, void *priv)
+{
+	int rc;
+	struct json_pointer_get_result *from = priv;
+	size_t len = json_object_array_length(parent);
+
+	/**
+	 * If it's the same array parent, it means that we removed
+	 * and element from it, so the length is temporarily reduced
+	 * by 1, which means that if we try to move an element to
+	 * the last position, we need to check the current length + 1
+	 */
+	if (parent == from->parent)
+		len++;
+
+	if (idx > len)
+	{
+		// Note: will propagate back out through json_pointer_set_with_array_cb()
+		errno = EINVAL;
+		return -1;
+	}
+
+	rc = json_object_array_insert_idx(parent, idx, value);
+	if (rc < 0)
+		errno = EINVAL;
+	return rc;
+}
+
+static int json_patch_apply_move_copy(struct json_object **res,
+                                      struct json_object *patch_elem,
+                                      const char *path, int move, struct json_patch_error *patch_error)
+{
+	json_pointer_array_set_cb array_set_cb;
+	struct json_pointer_get_result from;
+	struct json_object *jfrom;
+	const char *from_s;
+	size_t from_s_len;
+	int rc;
+
+	if (!json_object_object_get_ex(patch_elem, "from", &jfrom)) {
+		_set_err(EINVAL, "Patch does not contain a 'from' field");
+		return -1;
+	}
+
+	from_s = json_object_get_string(jfrom);
+
+	from_s_len = strlen(from_s);
+	if (strncmp(from_s, path, from_s_len) == 0) {
+		/**
+		 * If lengths match, it's a noop, if they don't,
+		 * then we're trying to move a parent under a child
+		 * which is not allowed as per RFC 6902 section 4.4
+		 *   The "from" location MUST NOT be a proper prefix of the "path"
+		 *   location; i.e., a location cannot be moved into one of its children.
+		 */
+		if (from_s_len == strlen(path))
+			return 0;
+		_set_err(EINVAL, "Invalid attempt to move parent under a child");
+		return -1;
+	}
+
+	rc = json_pointer_get_internal(*res, from_s, &from);
+	if (rc)
+	{
+		_set_err_from_ptrget(errno, "from");
+		return rc;
+	}
+
+	// Note: it's impossible for json_pointer to find the root obj, due
+	// to the path check above, so from.parent is guaranteed non-NULL
+	json_object_get(from.obj);
+
+	if (!move) {
+		array_set_cb = json_object_array_insert_idx_cb;
+	} else {
+		rc = __json_patch_apply_remove(&from);
+		if (rc < 0) {
+			json_object_put(from.obj);
+			return rc;
+		}
+		array_set_cb = json_object_array_move_cb;
+	}
+
+	rc = json_pointer_set_with_array_cb(res, path, from.obj, array_set_cb, &from);
+	if (rc)
+	{
+		_set_err(errno, "Failed to set value at path referenced by 'path' field");
+		json_object_put(from.obj);
+	}
+
+	return rc;
+}
+
+int json_patch_apply(struct json_object *copy_from, struct json_object *patch,
+                     struct json_object **base, struct json_patch_error *patch_error)
+{
+	size_t ii;
+	int rc = 0;
+	struct json_patch_error placeholder;
+
+	if (!patch_error)
+		patch_error = &placeholder;
+
+	patch_error->patch_failure_idx = SIZE_T_MAX;
+	patch_error->errno_code = 0;
+
+	if (base == NULL|| 
+	    (*base == NULL && copy_from == NULL) ||
+	    (*base != NULL && copy_from != NULL))
+	{
+		_set_err(EFAULT, "Exactly one of *base or copy_from must be non-NULL");
+		return -1;
+	}
+	    
+	if (!json_object_is_type(patch, json_type_array)) {
+		_set_err(EFAULT, "Patch object is not of type json_type_array");
+		return -1;
+	}
+
+	if (copy_from != NULL)
+	{
+		if (json_object_deep_copy(copy_from, base, NULL) < 0)
+		{
+			_set_err(ENOMEM, "Unable to copy copy_from using json_object_deep_copy()");
+			return -1;
+		}
+	}
+
+	/* Go through all operations ; apply them on res */
+	for (ii = 0; ii < json_object_array_length(patch); ii++) {
+		struct json_object *jop, *jpath;
+		struct json_object *patch_elem = json_object_array_get_idx(patch, ii);
+		const char *op, *path;
+
+		patch_error->patch_failure_idx = ii;
+
+		if (!json_object_object_get_ex(patch_elem, "op", &jop)) {
+			_set_err(EINVAL, "Patch object does not contain 'op' field");
+			return -1;
+		}
+		op = json_object_get_string(jop);
+		if (!json_object_object_get_ex(patch_elem, "path", &jpath)) {
+			_set_err(EINVAL, "Patch object does not contain 'path' field");
+			return -1;
+		}
+		path = json_object_get_string(jpath); // Note: empty string is ok!
+
+		if (!strcmp(op, "test"))
+			rc = json_patch_apply_test(base, patch_elem, path, patch_error);
+		else if (!strcmp(op, "remove"))
+			rc = json_patch_apply_remove(base, path, patch_error);
+		else if (!strcmp(op, "add"))
+			rc = json_patch_apply_add_replace(base, patch_elem, path, 1, patch_error);
+		else if (!strcmp(op, "replace"))
+			rc = json_patch_apply_add_replace(base, patch_elem, path, 0, patch_error);
+		else if (!strcmp(op, "move"))
+			rc = json_patch_apply_move_copy(base, patch_elem, path, 1, patch_error);
+		else if (!strcmp(op, "copy"))
+			rc = json_patch_apply_move_copy(base, patch_elem, path, 0, patch_error);
+		else {
+			_set_err(EINVAL, "Patch object has invalid 'op' field");
+			return -1;
+		}
+		if (rc < 0)
+			break;
+	}
+
+	return rc;
+}
diff --git a/vendor/json-c/json_patch.h b/vendor/json-c/json_patch.h
new file mode 100644
index 0000000000..79de5f9544
--- /dev/null
+++ b/vendor/json-c/json_patch.h
@@ -0,0 +1,80 @@
+/*
+ * Copyright (c) 2021 Alexadru Ardelean.
+ *
+ * This is free software; you can redistribute it and/or modify
+ * it under the terms of the MIT license. See COPYING for details.
+ *
+ */
+
+/**
+ * @file
+ * @brief JSON Patch (RFC 6902) implementation for manipulating JSON objects
+ */
+#ifndef _json_patch_h_
+#define _json_patch_h_
+
+#include "json_pointer.h"
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+/**
+ * Details of an error that occurred during json_patch_apply()
+ */
+struct json_patch_error {
+	/**
+	 * An errno value indicating what kind of error occurred.
+	 * Possible values include:
+	 * - ENOENT - A path referenced in the operation does not exist.
+	 * - EINVAL - An invalid operation or with invalid path was attempted
+	 * - ENOMEM - Unable to allocate memory
+	 * - EFAULT - Invalid arguments were passed to json_patch_apply()
+	 *             (i.e. a C API error, vs. a data error like EINVAL)
+	 */
+	int errno_code;
+
+	/**
+	 * The index into the patch array of the operation that failed,
+	 * or SIZE_T_MAX for overall errors.
+	 */
+	size_t patch_failure_idx;
+
+	/**
+	 * A human readable error message.
+	 * Allocated from static storage, does not need to be freed.
+	 */
+	const char *errmsg;
+};
+
+/**
+ * Apply the JSON patch to the base object.
+ * The patch object must be formatted as per RFC 6902, i.e.
+ * a json_type_array containing patch operations.
+ * If the patch is not correctly formatted, an error will
+ * be returned.
+ *
+ * The json_object at *base will be modified in place.
+ * Exactly one of *base or copy_from must be non-NULL.
+ * If *base is NULL, a new copy of copy_from will allocated and populated
+ * using json_object_deep_copy().  In this case json_object_put() _must_ be 
+ * used to free *base even if the overall patching operation fails.
+ *
+ * If anything fails during patching a negative value will be returned,
+ * and patch_error (if non-NULL) will be populated with error details.
+ *
+ * @param base a pointer to the JSON object which to patch
+ * @param patch the JSON object that describes the patch to be applied
+ * @param copy_from a JSON object to copy to *base
+ * @param patch_error optional, details about errors
+ *
+ * @return negative if an error (or not found), or 0 if patch completely applied
+ */
+JSON_EXPORT int json_patch_apply(struct json_object *copy_from, struct json_object *patch,
+                                 struct json_object **base, struct json_patch_error *patch_error);
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif
diff --git a/vendor/json-c/json_pointer.c b/vendor/json-c/json_pointer.c
index 395567a5ba..6e5609d700 100644
--- a/vendor/json-c/json_pointer.c
+++ b/vendor/json-c/json_pointer.c
@@ -15,7 +15,9 @@
 #include 
 #include 
 
+#include "json_object_private.h"
 #include "json_pointer.h"
+#include "json_pointer_private.h"
 #include "strdup_compat.h"
 #include "vasprintf_compat.h"
 
@@ -29,8 +31,8 @@
 
 static void string_replace_all_occurrences_with_char(char *s, const char *occur, char repl_char)
 {
-	int slen = strlen(s);
-	int skip = strlen(occur) - 1; /* length of the occurrence, minus the char we're replacing */
+	size_t slen = strlen(s);
+	size_t skip = strlen(occur) - 1; /* length of the occurrence, minus the char we're replacing */
 	char *p = s;
 	while ((p = strstr(p, occur)))
 	{
@@ -41,9 +43,9 @@ static void string_replace_all_occurrences_with_char(char *s, const char *occur,
 	}
 }
 
-static int is_valid_index(struct json_object *jo, const char *path, int32_t *idx)
+static int is_valid_index(const char *path, size_t *idx)
 {
-	int i, len = strlen(path);
+	size_t i, len = strlen(path);
 	/* this code-path optimizes a bit, for when we reference the 0-9 index range
 	 * in a JSON array and because leading zeros not allowed
 	 */
@@ -52,7 +54,7 @@ static int is_valid_index(struct json_object *jo, const char *path, int32_t *idx
 		if (is_plain_digit(path[0]))
 		{
 			*idx = (path[0] - '0');
-			goto check_oob;
+			return 1;
 		}
 		errno = EINVAL;
 		return 0;
@@ -73,32 +75,27 @@ static int is_valid_index(struct json_object *jo, const char *path, int32_t *idx
 		}
 	}
 
-	*idx = strtol(path, NULL, 10);
-	if (*idx < 0)
-	{
-		errno = EINVAL;
-		return 0;
-	}
-check_oob:
-	len = json_object_array_length(jo);
-	if (*idx >= len)
-	{
-		errno = ENOENT;
-		return 0;
-	}
+	// We know it's all digits, so the only error case here is overflow,
+	// but ULLONG_MAX will be longer than any array length so that's ok.
+	*idx = strtoull(path, NULL, 10);
 
 	return 1;
 }
 
 static int json_pointer_get_single_path(struct json_object *obj, char *path,
-                                        struct json_object **value)
+                                        struct json_object **value, size_t *idx)
 {
 	if (json_object_is_type(obj, json_type_array))
 	{
-		int32_t idx;
-		if (!is_valid_index(obj, path, &idx))
+		if (!is_valid_index(path, idx))
+			return -1;
+		if (*idx >= json_object_array_length(obj))
+		{
+			errno = ENOENT;
 			return -1;
-		obj = json_object_array_get_idx(obj, idx);
+		}
+
+		obj = json_object_array_get_idx(obj, *idx);
 		if (obj)
 		{
 			if (value)
@@ -123,18 +120,25 @@ static int json_pointer_get_single_path(struct json_object *obj, char *path,
 	return 0;
 }
 
+static int json_object_array_put_idx_cb(struct json_object *parent, size_t idx,
+					struct json_object *value, void *priv)
+{
+	return json_object_array_put_idx(parent, idx, value);
+}
+
 static int json_pointer_set_single_path(struct json_object *parent, const char *path,
-                                        struct json_object *value)
+                                        struct json_object *value,
+					json_pointer_array_set_cb array_set_cb, void *priv)
 {
 	if (json_object_is_type(parent, json_type_array))
 	{
-		int32_t idx;
+		size_t idx;
 		/* RFC (Chapter 4) states that '-' may be used to add new elements to an array */
 		if (path[0] == '-' && path[1] == '\0')
 			return json_object_array_add(parent, value);
-		if (!is_valid_index(parent, path, &idx))
+		if (!is_valid_index(path, &idx))
 			return -1;
-		return json_object_array_put_idx(parent, idx, value);
+		return array_set_cb(parent, idx, value, priv);
 	}
 
 	/* path replacements should have been done in json_pointer_get_single_path(),
@@ -150,9 +154,11 @@ static int json_pointer_set_single_path(struct json_object *parent, const char *
 	return -1;
 }
 
-static int json_pointer_get_recursive(struct json_object *obj, char *path,
-                                      struct json_object **value)
+static int json_pointer_result_get_recursive(struct json_object *obj, char *path,
+                                             struct json_pointer_get_result *res)
 {
+	struct json_object *parent_obj = obj;
+	size_t idx = 0;
 	char *endp;
 	int rc;
 
@@ -169,24 +175,47 @@ static int json_pointer_get_recursive(struct json_object *obj, char *path,
 		*endp = '\0';
 
 	/* If we err-ed here, return here */
-	if ((rc = json_pointer_get_single_path(obj, path, &obj)))
+	if ((rc = json_pointer_get_single_path(obj, path, &obj, &idx)))
 		return rc;
 
 	if (endp)
 	{
 		/* Put the slash back, so that the sanity check passes on next recursion level */
 		*endp = '/';
-		return json_pointer_get_recursive(obj, endp, value);
+		return json_pointer_result_get_recursive(obj, endp, res);
 	}
 
 	/* We should be at the end of the recursion here */
+	if (res) {
+		res->parent = parent_obj;
+		res->obj = obj;
+		if (json_object_is_type(res->parent, json_type_array))
+			res->index_in_parent = idx;
+		else
+			res->key_in_parent = path;
+	}
+
+	return 0;
+}
+
+static int json_pointer_object_get_recursive(struct json_object *obj, char *path,
+                                             struct json_object **value)
+{
+	struct json_pointer_get_result res;
+	int rc;
+
+	rc = json_pointer_result_get_recursive(obj, path, &res);
+	if (rc)
+		return rc;
+
 	if (value)
-		*value = obj;
+		*value = res.obj;
 
 	return 0;
 }
 
-int json_pointer_get(struct json_object *obj, const char *path, struct json_object **res)
+int json_pointer_get_internal(struct json_object *obj, const char *path,
+                              struct json_pointer_get_result *res)
 {
 	char *path_copy = NULL;
 	int rc;
@@ -199,8 +228,10 @@ int json_pointer_get(struct json_object *obj, const char *path, struct json_obje
 
 	if (path[0] == '\0')
 	{
-		if (res)
-			*res = obj;
+		res->parent = NULL;
+		res->obj = obj;
+		res->key_in_parent = NULL;
+		res->index_in_parent = UINT32_MAX;
 		return 0;
 	}
 
@@ -210,12 +241,30 @@ int json_pointer_get(struct json_object *obj, const char *path, struct json_obje
 		errno = ENOMEM;
 		return -1;
 	}
-	rc = json_pointer_get_recursive(obj, path_copy, res);
+	rc = json_pointer_result_get_recursive(obj, path_copy, res);
+	/* re-map the path string to the const-path string */
+	if (rc == 0 && json_object_is_type(res->parent, json_type_object) && res->key_in_parent)
+		res->key_in_parent = path + (res->key_in_parent - path_copy);
 	free(path_copy);
 
 	return rc;
 }
 
+int json_pointer_get(struct json_object *obj, const char *path, struct json_object **res)
+{
+	struct json_pointer_get_result jpres;
+	int rc;
+
+	rc = json_pointer_get_internal(obj, path, &jpres);
+	if (rc)
+		return rc;
+
+	if (res)
+		*res = jpres.obj;
+
+	return 0;
+}
+
 int json_pointer_getf(struct json_object *obj, struct json_object **res, const char *path_fmt, ...)
 {
 	char *path_copy = NULL;
@@ -242,14 +291,16 @@ int json_pointer_getf(struct json_object *obj, struct json_object **res, const c
 		goto out;
 	}
 
-	rc = json_pointer_get_recursive(obj, path_copy, res);
+	rc = json_pointer_object_get_recursive(obj, path_copy, res);
 out:
 	free(path_copy);
 
 	return rc;
 }
 
-int json_pointer_set(struct json_object **obj, const char *path, struct json_object *value)
+int json_pointer_set_with_array_cb(struct json_object **obj, const char *path,
+				   struct json_object *value,
+				   json_pointer_array_set_cb array_set_cb, void *priv)
 {
 	const char *endp;
 	char *path_copy = NULL;
@@ -279,7 +330,7 @@ int json_pointer_set(struct json_object **obj, const char *path, struct json_obj
 	if ((endp = strrchr(path, '/')) == path)
 	{
 		path++;
-		return json_pointer_set_single_path(*obj, path, value);
+		return json_pointer_set_single_path(*obj, path, value, array_set_cb, priv);
 	}
 
 	/* pass a working copy to the recursive call */
@@ -289,14 +340,19 @@ int json_pointer_set(struct json_object **obj, const char *path, struct json_obj
 		return -1;
 	}
 	path_copy[endp - path] = '\0';
-	rc = json_pointer_get_recursive(*obj, path_copy, &set);
+	rc = json_pointer_object_get_recursive(*obj, path_copy, &set);
 	free(path_copy);
 
 	if (rc)
 		return rc;
 
 	endp++;
-	return json_pointer_set_single_path(set, endp, value);
+	return json_pointer_set_single_path(set, endp, value, array_set_cb, priv);
+}
+
+int json_pointer_set(struct json_object **obj, const char *path, struct json_object *value)
+{
+	return json_pointer_set_with_array_cb(obj, path, value, json_object_array_put_idx_cb, NULL);
 }
 
 int json_pointer_setf(struct json_object **obj, struct json_object *value, const char *path_fmt,
@@ -344,14 +400,15 @@ int json_pointer_setf(struct json_object **obj, struct json_object *value, const
 	}
 
 	*endp = '\0';
-	rc = json_pointer_get_recursive(*obj, path_copy, &set);
+	rc = json_pointer_object_get_recursive(*obj, path_copy, &set);
 
 	if (rc)
 		goto out;
 
 set_single_path:
 	endp++;
-	rc = json_pointer_set_single_path(set, endp, value);
+	rc = json_pointer_set_single_path(set, endp, value,
+					  json_object_array_put_idx_cb, NULL);
 out:
 	free(path_copy);
 	return rc;
diff --git a/vendor/json-c/json_pointer.h b/vendor/json-c/json_pointer.h
index 06c395b9ad..dfe1185474 100644
--- a/vendor/json-c/json_pointer.h
+++ b/vendor/json-c/json_pointer.h
@@ -32,11 +32,6 @@ extern "C" {
  * Internally, this is equivalent to doing a series of 'json_object_object_get()'
  * and 'json_object_array_get_idx()' along the given 'path'.
  *
- * Note that the 'path' string supports 'printf()' type arguments, so, whatever
- * is added after the 'res' param will be treated as an argument for 'path'
- * Example: json_pointer_get(obj, "/foo/%d/%s", &res, 0, bar)
- * This means, that you need to escape '%' with '%%' (just like in printf())
- *
  * @param obj the json_object instance/tree from where to retrieve sub-objects
  * @param path a (RFC6901) string notation for the sub-object to retrieve
  * @param res a pointer that stores a reference to the json_object
@@ -50,7 +45,9 @@ JSON_EXPORT int json_pointer_get(struct json_object *obj, const char *path,
 /**
  * This is a variant of 'json_pointer_get()' that supports printf() style arguments.
  *
- * Example: json_pointer_getf(obj, res, "/foo/%d/%s", 0, bak)
+ * Variable arguments go after the 'path_fmt' parameter.
+ *
+ * Example: json_pointer_getf(obj, res, "/foo/%d/%s", 0, "bar")
  * This also means that you need to escape '%' with '%%' (just like in printf())
  *
  * Please take into consideration all recommended 'printf()' format security
@@ -84,11 +81,6 @@ JSON_EXPORT int json_pointer_getf(struct json_object *obj, struct json_object **
  * That also implies that 'json_pointer_set()' does not do any refcount incrementing.
  * (Just that single decrement that was mentioned above).
  *
- * Note that the 'path' string supports 'printf()' type arguments, so, whatever
- * is added after the 'value' param will be treated as an argument for 'path'
- * Example: json_pointer_set(obj, "/foo/%d/%s", value, 0, bak)
- * This means, that you need to escape '%' with '%%' (just like in printf())
- *
  * @param obj the json_object instance/tree to which to add a sub-object
  * @param path a (RFC6901) string notation for the sub-object to set in the tree
  * @param value object to set at path
@@ -101,7 +93,9 @@ JSON_EXPORT int json_pointer_set(struct json_object **obj, const char *path,
 /**
  * This is a variant of 'json_pointer_set()' that supports printf() style arguments.
  *
- * Example: json_pointer_setf(obj, value, "/foo/%d/%s", 0, bak)
+ * Variable arguments go after the 'path_fmt' parameter.
+ *
+ * Example: json_pointer_setf(obj, value, "/foo/%d/%s", 0, "bar")
  * This also means that you need to escape '%' with '%%' (just like in printf())
  *
  * Please take into consideration all recommended 'printf()' format security
diff --git a/vendor/json-c/json_pointer_private.h b/vendor/json-c/json_pointer_private.h
new file mode 100644
index 0000000000..537cabd36e
--- /dev/null
+++ b/vendor/json-c/json_pointer_private.h
@@ -0,0 +1,43 @@
+/*
+ * Copyright (c) 2023 Eric Hawicz
+ *
+ * This library is free software; you can redistribute it and/or modify
+ * it under the terms of the MIT license. See COPYING for details.
+ */
+
+/**
+ * @file
+ * @brief Do not use, json-c internal, may be changed or removed at any time.
+ */
+#ifndef _json_pointer_private_h_
+#define _json_pointer_private_h_
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+struct json_pointer_get_result {
+	struct json_object *parent;
+	struct json_object *obj;
+	// The key of the found object; only valid when parent is json_type_object
+	// Caution: re-uses tail end of the `path` argument to json_pointer_get_internal
+	const char *key_in_parent;
+	// the index of the found object; only valid when parent is json_type_array
+	uint32_t index_in_parent;
+};
+
+int json_pointer_get_internal(struct json_object *obj, const char *path,
+                              struct json_pointer_get_result *res);
+
+typedef int(*json_pointer_array_set_cb)(json_object *parent, size_t idx,
+                                        json_object *value, void *priv);
+
+int json_pointer_set_with_array_cb(struct json_object **obj, const char *path,
+                                   struct json_object *value,
+                                   json_pointer_array_set_cb array_set_cb, void *priv);
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif
diff --git a/vendor/json-c/json_tokener.c b/vendor/json-c/json_tokener.c
index 0c09b66e8d..0a86d82108 100644
--- a/vendor/json-c/json_tokener.c
+++ b/vendor/json-c/json_tokener.c
@@ -17,6 +17,7 @@
 
 #include "math_compat.h"
 #include 
+#include 
 #include 
 #include 
 #include 
@@ -115,7 +116,8 @@ static const char *json_tokener_errors[] = {
 	"invalid string sequence",
 	"expected comment",
 	"invalid utf-8 string",
-	"buffer size overflow"
+	"buffer size overflow",
+	"out of memory"
 };
 /* clang-format on */
 
@@ -224,7 +226,10 @@ struct json_object *json_tokener_parse_verbose(const char *str, enum json_tokene
 
 	tok = json_tokener_new();
 	if (!tok)
+	{
+		*error = json_tokener_error_memory;
 		return NULL;
+	}
 	obj = json_tokener_parse_ex(tok, str, -1);
 	*error = tok->err;
 	if (tok->err != json_tokener_success
@@ -284,11 +289,24 @@ struct json_object *json_tokener_parse_verbose(const char *str, enum json_tokene
 
 /* ADVANCE_CHAR() macro:
  *   Increments str & tok->char_offset.
- *   For convenience of existing conditionals, returns the old value of c (0 on eof)
+ *   For convenience of existing conditionals, returns the old value of c (0 on eof).
  *   Implicit inputs:  c var
  */
 #define ADVANCE_CHAR(str, tok) (++(str), ((tok)->char_offset)++, c)
 
+/* printbuf_memappend_checked(p, s, l) macro:
+ *   Add string s of length l to printbuffer p.
+ *   If operation fails abort parse operation with memory error.
+ */
+#define printbuf_memappend_checked(p, s, l)                   \
+	do {                                                  \
+		if (printbuf_memappend((p), (s), (l)) < 0)    \
+		{                                             \
+			tok->err = json_tokener_error_memory; \
+			goto out;                             \
+		}                                             \
+	} while (0)
+
 /* End optimization macro defs */
 
 struct json_object *json_tokener_parse_ex(struct json_tokener *tok, const char *str, int len)
@@ -323,12 +341,23 @@ struct json_object *json_tokener_parse_ex(struct json_tokener *tok, const char *
 #ifdef HAVE_USELOCALE
 	{
 		locale_t duploc = duplocale(oldlocale);
+		if (duploc == NULL && errno == ENOMEM)
+		{
+			tok->err = json_tokener_error_memory;
+			return NULL;
+		}
 		newloc = newlocale(LC_NUMERIC_MASK, "C", duploc);
 		if (newloc == NULL)
 		{
+			tok->err = json_tokener_error_memory;
 			freelocale(duploc);
 			return NULL;
 		}
+#ifdef NEWLOCALE_NEEDS_FREELOCALE
+		// Older versions of FreeBSD (<12.4) don't free the locale
+		// passed to newlocale(), so do it here
+		freelocale(duploc);
+#endif
 		uselocale(newloc);
 	}
 #elif defined(HAVE_SETLOCALE)
@@ -336,7 +365,14 @@ struct json_object *json_tokener_parse_ex(struct json_tokener *tok, const char *
 		char *tmplocale;
 		tmplocale = setlocale(LC_NUMERIC, NULL);
 		if (tmplocale)
+		{
 			oldlocale = strdup(tmplocale);
+			if (oldlocale == NULL)
+			{
+				tok->err = json_tokener_error_memory;
+				return NULL;
+			}
+		}
 		setlocale(LC_NUMERIC, "C");
 	}
 #endif
@@ -358,7 +394,7 @@ struct json_object *json_tokener_parse_ex(struct json_tokener *tok, const char *
 			if (c == '/' && !(tok->flags & JSON_TOKENER_STRICT))
 			{
 				printbuf_reset(tok->pb);
-				printbuf_memappend_fast(tok->pb, &c, 1);
+				printbuf_memappend_checked(tok->pb, &c, 1);
 				state = json_tokener_state_comment_start;
 			}
 			else
@@ -376,14 +412,20 @@ struct json_object *json_tokener_parse_ex(struct json_tokener *tok, const char *
 				saved_state = json_tokener_state_object_field_start;
 				current = json_object_new_object();
 				if (current == NULL)
+				{
+					tok->err = json_tokener_error_memory;
 					goto out;
+				}
 				break;
 			case '[':
 				state = json_tokener_state_eatws;
 				saved_state = json_tokener_state_array;
 				current = json_object_new_array();
 				if (current == NULL)
+				{
+					tok->err = json_tokener_error_memory;
 					goto out;
+				}
 				break;
 			case 'I':
 			case 'i':
@@ -486,7 +528,10 @@ struct json_object *json_tokener_parse_ex(struct json_tokener *tok, const char *
 			}
 			current = json_object_new_double(is_negative ? -INFINITY : INFINITY);
 			if (current == NULL)
+			{
+				tok->err = json_tokener_error_memory;
 				goto out;
+			}
 			saved_state = json_tokener_state_finish;
 			state = json_tokener_state_eatws;
 			goto redo_char;
@@ -496,7 +541,7 @@ struct json_object *json_tokener_parse_ex(struct json_tokener *tok, const char *
 		{
 			int size;
 			int size_nan;
-			printbuf_memappend_fast(tok->pb, &c, 1);
+			printbuf_memappend_checked(tok->pb, &c, 1);
 			size = json_min(tok->st_pos + 1, json_null_str_len);
 			size_nan = json_min(tok->st_pos + 1, json_nan_str_len);
 			if ((!(tok->flags & JSON_TOKENER_STRICT) &&
@@ -519,7 +564,10 @@ struct json_object *json_tokener_parse_ex(struct json_tokener *tok, const char *
 				{
 					current = json_object_new_double(NAN);
 					if (current == NULL)
+					{
+						tok->err = json_tokener_error_memory;
 						goto out;
+					}
 					saved_state = json_tokener_state_finish;
 					state = json_tokener_state_eatws;
 					goto redo_char;
@@ -548,7 +596,7 @@ struct json_object *json_tokener_parse_ex(struct json_tokener *tok, const char *
 				tok->err = json_tokener_error_parse_comment;
 				goto out;
 			}
-			printbuf_memappend_fast(tok->pb, &c, 1);
+			printbuf_memappend_checked(tok->pb, &c, 1);
 			break;
 
 		case json_tokener_state_comment:
@@ -559,12 +607,12 @@ struct json_object *json_tokener_parse_ex(struct json_tokener *tok, const char *
 			{
 				if (!ADVANCE_CHAR(str, tok) || !PEEK_CHAR(c, tok))
 				{
-					printbuf_memappend_fast(tok->pb, case_start,
-					                        str - case_start);
+					printbuf_memappend_checked(tok->pb, case_start,
+					                           str - case_start);
 					goto out;
 				}
 			}
-			printbuf_memappend_fast(tok->pb, case_start, 1 + str - case_start);
+			printbuf_memappend_checked(tok->pb, case_start, 1 + str - case_start);
 			state = json_tokener_state_comment_end;
 		}
 		break;
@@ -577,19 +625,19 @@ struct json_object *json_tokener_parse_ex(struct json_tokener *tok, const char *
 			{
 				if (!ADVANCE_CHAR(str, tok) || !PEEK_CHAR(c, tok))
 				{
-					printbuf_memappend_fast(tok->pb, case_start,
-					                        str - case_start);
+					printbuf_memappend_checked(tok->pb, case_start,
+					                           str - case_start);
 					goto out;
 				}
 			}
-			printbuf_memappend_fast(tok->pb, case_start, str - case_start);
+			printbuf_memappend_checked(tok->pb, case_start, str - case_start);
 			MC_DEBUG("json_tokener_comment: %s\n", tok->pb->buf);
 			state = json_tokener_state_eatws;
 		}
 		break;
 
 		case json_tokener_state_comment_end:
-			printbuf_memappend_fast(tok->pb, &c, 1);
+			printbuf_memappend_checked(tok->pb, &c, 1);
 			if (c == '/')
 			{
 				MC_DEBUG("json_tokener_comment: %s\n", tok->pb->buf);
@@ -609,28 +657,31 @@ struct json_object *json_tokener_parse_ex(struct json_tokener *tok, const char *
 			{
 				if (c == tok->quote_char)
 				{
-					printbuf_memappend_fast(tok->pb, case_start,
-					                        str - case_start);
+					printbuf_memappend_checked(tok->pb, case_start,
+					                           str - case_start);
 					current =
 					    json_object_new_string_len(tok->pb->buf, tok->pb->bpos);
 					if (current == NULL)
+					{
+						tok->err = json_tokener_error_memory;
 						goto out;
+					}
 					saved_state = json_tokener_state_finish;
 					state = json_tokener_state_eatws;
 					break;
 				}
 				else if (c == '\\')
 				{
-					printbuf_memappend_fast(tok->pb, case_start,
-					                        str - case_start);
+					printbuf_memappend_checked(tok->pb, case_start,
+					                           str - case_start);
 					saved_state = json_tokener_state_string;
 					state = json_tokener_state_string_escape;
 					break;
 				}
 				if (!ADVANCE_CHAR(str, tok) || !PEEK_CHAR(c, tok))
 				{
-					printbuf_memappend_fast(tok->pb, case_start,
-					                        str - case_start);
+					printbuf_memappend_checked(tok->pb, case_start,
+					                           str - case_start);
 					goto out;
 				}
 			}
@@ -643,7 +694,7 @@ struct json_object *json_tokener_parse_ex(struct json_tokener *tok, const char *
 			case '"':
 			case '\\':
 			case '/':
-				printbuf_memappend_fast(tok->pb, &c, 1);
+				printbuf_memappend_checked(tok->pb, &c, 1);
 				state = saved_state;
 				break;
 			case 'b':
@@ -652,15 +703,15 @@ struct json_object *json_tokener_parse_ex(struct json_tokener *tok, const char *
 			case 't':
 			case 'f':
 				if (c == 'b')
-					printbuf_memappend_fast(tok->pb, "\b", 1);
+					printbuf_memappend_checked(tok->pb, "\b", 1);
 				else if (c == 'n')
-					printbuf_memappend_fast(tok->pb, "\n", 1);
+					printbuf_memappend_checked(tok->pb, "\n", 1);
 				else if (c == 'r')
-					printbuf_memappend_fast(tok->pb, "\r", 1);
+					printbuf_memappend_checked(tok->pb, "\r", 1);
 				else if (c == 't')
-					printbuf_memappend_fast(tok->pb, "\t", 1);
+					printbuf_memappend_checked(tok->pb, "\t", 1);
 				else if (c == 'f')
-					printbuf_memappend_fast(tok->pb, "\f", 1);
+					printbuf_memappend_checked(tok->pb, "\f", 1);
 				state = saved_state;
 				break;
 			case 'u':
@@ -720,8 +771,8 @@ struct json_object *json_tokener_parse_ex(struct json_tokener *tok, const char *
 					/* High surrogate was not followed by a low surrogate
 					 * Replace the high and process the rest normally
 					 */
-					printbuf_memappend_fast(tok->pb,
-					                        (char *)utf8_replacement_char, 3);
+					printbuf_memappend_checked(tok->pb,
+					                           (char *)utf8_replacement_char, 3);
 				}
 				tok->high_surrogate = 0;
 			}
@@ -730,14 +781,14 @@ struct json_object *json_tokener_parse_ex(struct json_tokener *tok, const char *
 			{
 				unsigned char unescaped_utf[1];
 				unescaped_utf[0] = tok->ucs_char;
-				printbuf_memappend_fast(tok->pb, (char *)unescaped_utf, 1);
+				printbuf_memappend_checked(tok->pb, (char *)unescaped_utf, 1);
 			}
 			else if (tok->ucs_char < 0x800)
 			{
 				unsigned char unescaped_utf[2];
 				unescaped_utf[0] = 0xc0 | (tok->ucs_char >> 6);
 				unescaped_utf[1] = 0x80 | (tok->ucs_char & 0x3f);
-				printbuf_memappend_fast(tok->pb, (char *)unescaped_utf, 2);
+				printbuf_memappend_checked(tok->pb, (char *)unescaped_utf, 2);
 			}
 			else if (IS_HIGH_SURROGATE(tok->ucs_char))
 			{
@@ -763,7 +814,7 @@ struct json_object *json_tokener_parse_ex(struct json_tokener *tok, const char *
 			else if (IS_LOW_SURROGATE(tok->ucs_char))
 			{
 				/* Got a low surrogate not preceded by a high */
-				printbuf_memappend_fast(tok->pb, (char *)utf8_replacement_char, 3);
+				printbuf_memappend_checked(tok->pb, (char *)utf8_replacement_char, 3);
 			}
 			else if (tok->ucs_char < 0x10000)
 			{
@@ -771,7 +822,7 @@ struct json_object *json_tokener_parse_ex(struct json_tokener *tok, const char *
 				unescaped_utf[0] = 0xe0 | (tok->ucs_char >> 12);
 				unescaped_utf[1] = 0x80 | ((tok->ucs_char >> 6) & 0x3f);
 				unescaped_utf[2] = 0x80 | (tok->ucs_char & 0x3f);
-				printbuf_memappend_fast(tok->pb, (char *)unescaped_utf, 3);
+				printbuf_memappend_checked(tok->pb, (char *)unescaped_utf, 3);
 			}
 			else if (tok->ucs_char < 0x110000)
 			{
@@ -780,12 +831,12 @@ struct json_object *json_tokener_parse_ex(struct json_tokener *tok, const char *
 				unescaped_utf[1] = 0x80 | ((tok->ucs_char >> 12) & 0x3f);
 				unescaped_utf[2] = 0x80 | ((tok->ucs_char >> 6) & 0x3f);
 				unescaped_utf[3] = 0x80 | (tok->ucs_char & 0x3f);
-				printbuf_memappend_fast(tok->pb, (char *)unescaped_utf, 4);
+				printbuf_memappend_checked(tok->pb, (char *)unescaped_utf, 4);
 			}
 			else
 			{
 				/* Don't know what we got--insert the replacement char */
-				printbuf_memappend_fast(tok->pb, (char *)utf8_replacement_char, 3);
+				printbuf_memappend_checked(tok->pb, (char *)utf8_replacement_char, 3);
 			}
 			state = saved_state; // i.e. _state_string or _state_object_field
 		}
@@ -800,7 +851,7 @@ struct json_object *json_tokener_parse_ex(struct json_tokener *tok, const char *
 				 * it.  Put a replacement char in for the high surrogate
 				 * and pop back up to _state_string or _state_object_field.
 				 */
-				printbuf_memappend_fast(tok->pb, (char *)utf8_replacement_char, 3);
+				printbuf_memappend_checked(tok->pb, (char *)utf8_replacement_char, 3);
 				tok->high_surrogate = 0;
 				tok->ucs_char = 0;
 				tok->st_pos = 0;
@@ -819,7 +870,7 @@ struct json_object *json_tokener_parse_ex(struct json_tokener *tok, const char *
 				 * Put a replacement char in for the high surrogate
 				 * and handle the escape sequence normally.
 				 */
-				printbuf_memappend_fast(tok->pb, (char *)utf8_replacement_char, 3);
+				printbuf_memappend_checked(tok->pb, (char *)utf8_replacement_char, 3);
 				tok->high_surrogate = 0;
 				tok->ucs_char = 0;
 				tok->st_pos = 0;
@@ -834,7 +885,7 @@ struct json_object *json_tokener_parse_ex(struct json_tokener *tok, const char *
 		case json_tokener_state_boolean:
 		{
 			int size1, size2;
-			printbuf_memappend_fast(tok->pb, &c, 1);
+			printbuf_memappend_checked(tok->pb, &c, 1);
 			size1 = json_min(tok->st_pos + 1, json_true_str_len);
 			size2 = json_min(tok->st_pos + 1, json_false_str_len);
 			if ((!(tok->flags & JSON_TOKENER_STRICT) &&
@@ -845,7 +896,10 @@ struct json_object *json_tokener_parse_ex(struct json_tokener *tok, const char *
 				{
 					current = json_object_new_boolean(1);
 					if (current == NULL)
+					{
+						tok->err = json_tokener_error_memory;
 						goto out;
+					}
 					saved_state = json_tokener_state_finish;
 					state = json_tokener_state_eatws;
 					goto redo_char;
@@ -859,7 +913,10 @@ struct json_object *json_tokener_parse_ex(struct json_tokener *tok, const char *
 				{
 					current = json_object_new_boolean(0);
 					if (current == NULL)
+					{
+						tok->err = json_tokener_error_memory;
 						goto out;
+					}
 					saved_state = json_tokener_state_finish;
 					state = json_tokener_state_eatws;
 					goto redo_char;
@@ -939,7 +996,7 @@ struct json_object *json_tokener_parse_ex(struct json_tokener *tok, const char *
 
 				if (!ADVANCE_CHAR(str, tok) || !PEEK_CHAR(c, tok))
 				{
-					printbuf_memappend_fast(tok->pb, case_start, case_len);
+					printbuf_memappend_checked(tok->pb, case_start, case_len);
 					goto out;
 				}
 			}
@@ -948,7 +1005,7 @@ struct json_object *json_tokener_parse_ex(struct json_tokener *tok, const char *
 				it might have been intended to be, and return a potentially
 				more understandable error right away.
 				However, if we're at the top-level, use the number as-is
-			    because c can be part of a new object to parse on the
+				because c can be part of a new object to parse on the
 				next call to json_tokener_parse().
 			 */
 			if (tok->depth > 0 && c != ',' && c != ']' && c != '}' && c != '/' &&
@@ -958,7 +1015,7 @@ struct json_object *json_tokener_parse_ex(struct json_tokener *tok, const char *
 				goto out;
 			}
 			if (case_len > 0)
-				printbuf_memappend_fast(tok->pb, case_start, case_len);
+				printbuf_memappend_checked(tok->pb, case_start, case_len);
 
 			// Check for -Infinity
 			if (tok->pb->buf[0] == '-' && case_len <= 1 && (c == 'i' || c == 'I'))
@@ -991,13 +1048,26 @@ struct json_object *json_tokener_parse_ex(struct json_tokener *tok, const char *
 				if (!tok->is_double && tok->pb->buf[0] == '-' &&
 				    json_parse_int64(tok->pb->buf, &num64) == 0)
 				{
+					if (errno == ERANGE && (tok->flags & JSON_TOKENER_STRICT))
+					{
+						tok->err = json_tokener_error_parse_number;
+						goto out;
+					}
 					current = json_object_new_int64(num64);
 					if (current == NULL)
+					{
+						tok->err = json_tokener_error_memory;
 						goto out;
+					}
 				}
 				else if (!tok->is_double && tok->pb->buf[0] != '-' &&
 				         json_parse_uint64(tok->pb->buf, &numuint64) == 0)
 				{
+					if (errno == ERANGE && (tok->flags & JSON_TOKENER_STRICT))
+					{
+						tok->err = json_tokener_error_parse_number;
+						goto out;
+					}
 					if (numuint64 && tok->pb->buf[0] == '0' &&
 					    (tok->flags & JSON_TOKENER_STRICT))
 					{
@@ -1009,13 +1079,19 @@ struct json_object *json_tokener_parse_ex(struct json_tokener *tok, const char *
 						num64 = (uint64_t)numuint64;
 						current = json_object_new_int64(num64);
 						if (current == NULL)
+						{
+							tok->err = json_tokener_error_memory;
 							goto out;
+						}
 					}
 					else
 					{
 						current = json_object_new_uint64(numuint64);
 						if (current == NULL)
+						{
+							tok->err = json_tokener_error_memory;
 							goto out;
+						}
 					}
 				}
 				else if (tok->is_double &&
@@ -1024,7 +1100,10 @@ struct json_object *json_tokener_parse_ex(struct json_tokener *tok, const char *
 				{
 					current = json_object_new_double_s(numd, tok->pb->buf);
 					if (current == NULL)
+					{
+						tok->err = json_tokener_error_memory;
 						goto out;
+					}
 				}
 				else
 				{
@@ -1069,7 +1148,10 @@ struct json_object *json_tokener_parse_ex(struct json_tokener *tok, const char *
 
 		case json_tokener_state_array_add:
 			if (json_object_array_add(current, obj) != 0)
+			{
+				tok->err = json_tokener_error_memory;
 				goto out;
+			}
 			saved_state = json_tokener_state_array_sep;
 			state = json_tokener_state_eatws;
 			goto redo_char;
@@ -1129,25 +1211,30 @@ struct json_object *json_tokener_parse_ex(struct json_tokener *tok, const char *
 			{
 				if (c == tok->quote_char)
 				{
-					printbuf_memappend_fast(tok->pb, case_start,
-					                        str - case_start);
+					printbuf_memappend_checked(tok->pb, case_start,
+					                           str - case_start);
 					obj_field_name = strdup(tok->pb->buf);
+					if (obj_field_name == NULL)
+					{
+						tok->err = json_tokener_error_memory;
+						goto out;
+					}
 					saved_state = json_tokener_state_object_field_end;
 					state = json_tokener_state_eatws;
 					break;
 				}
 				else if (c == '\\')
 				{
-					printbuf_memappend_fast(tok->pb, case_start,
-					                        str - case_start);
+					printbuf_memappend_checked(tok->pb, case_start,
+					                           str - case_start);
 					saved_state = json_tokener_state_object_field;
 					state = json_tokener_state_string_escape;
 					break;
 				}
 				if (!ADVANCE_CHAR(str, tok) || !PEEK_CHAR(c, tok))
 				{
-					printbuf_memappend_fast(tok->pb, case_start,
-					                        str - case_start);
+					printbuf_memappend_checked(tok->pb, case_start,
+					                           str - case_start);
 					goto out;
 				}
 			}
@@ -1179,7 +1266,11 @@ struct json_object *json_tokener_parse_ex(struct json_tokener *tok, const char *
 			goto redo_char;
 
 		case json_tokener_state_object_value_add:
-			json_object_object_add(current, obj_field_name, obj);
+			if (json_object_object_add(current, obj_field_name, obj) != 0)
+			{
+				tok->err = json_tokener_error_memory;
+				goto out;
+			}
 			free(obj_field_name);
 			obj_field_name = NULL;
 			saved_state = json_tokener_state_object_sep;
diff --git a/vendor/json-c/json_tokener.h b/vendor/json-c/json_tokener.h
index a07e12ce7e..54925e5116 100644
--- a/vendor/json-c/json_tokener.h
+++ b/vendor/json-c/json_tokener.h
@@ -40,7 +40,8 @@ enum json_tokener_error
 	json_tokener_error_parse_string,
 	json_tokener_error_parse_comment,
 	json_tokener_error_parse_utf8_string,
-	json_tokener_error_size
+	json_tokener_error_size,   /* A string longer than INT32_MAX was passed as input */
+	json_tokener_error_memory  /* Failed to allocate memory */
 };
 
 /**
@@ -229,7 +230,7 @@ JSON_EXPORT void json_tokener_reset(struct json_tokener *tok);
 JSON_EXPORT struct json_object *json_tokener_parse(const char *str);
 
 /**
- * Parser a json_object out of the string `str`, but if it fails
+ * Parse a json_object out of the string `str`, but if it fails
  * return the error in `*error`.
  * @see json_tokener_parse()
  * @see json_tokener_parse_ex()
diff --git a/vendor/json-c/json_util.c b/vendor/json-c/json_util.c
index 3e6a6c681b..4da3efb4f5 100644
--- a/vendor/json-c/json_util.c
+++ b/vendor/json-c/json_util.c
@@ -37,13 +37,13 @@
 #include 
 #endif /* HAVE_UNISTD_H */
 
-#ifdef WIN32
+#ifdef _WIN32
 #define WIN32_LEAN_AND_MEAN
 #include 
 #include 
-#endif /* defined(WIN32) */
+#endif /* defined(_WIN32) */
 
-#if !defined(HAVE_OPEN) && defined(WIN32)
+#if !defined(HAVE_OPEN) && defined(_WIN32)
 #define open _open
 #endif
 
@@ -60,7 +60,7 @@ static int _json_object_to_fd(int fd, struct json_object *obj, int flags, const
 
 static char _last_err[256] = "";
 
-const char *json_util_get_last_err()
+const char *json_util_get_last_err(void)
 {
 	if (_last_err[0] == '\0')
 		return NULL;
@@ -85,7 +85,7 @@ struct json_object *json_object_from_fd_ex(int fd, int in_depth)
 	struct printbuf *pb;
 	struct json_object *obj;
 	char buf[JSON_FILE_BUF_SIZE];
-	int ret;
+	ssize_t ret;
 	int depth = JSON_TOKENER_DEFAULT_DEPTH;
 	json_tokener *tok;
 
@@ -101,15 +101,25 @@ struct json_object *json_object_from_fd_ex(int fd, int in_depth)
 	if (!tok)
 	{
 		_json_c_set_last_err(
-		    "json_object_from_fd_ex: unable to allocate json_tokener(depth=%d): %s\n", depth,
-		    strerror(errno));
+		    "json_object_from_fd_ex: unable to allocate json_tokener(depth=%d): %s\n",
+		    depth, strerror(errno));
 		printbuf_free(pb);
 		return NULL;
 	}
 
-	while ((ret = read(fd, buf, JSON_FILE_BUF_SIZE)) > 0)
+	while ((ret = read(fd, buf, sizeof(buf))) > 0)
 	{
-		printbuf_memappend(pb, buf, ret);
+		if (printbuf_memappend(pb, buf, ret) < 0)
+		{
+#if JSON_FILE_BUF_SIZE > INT_MAX
+#error "Can't append more than INT_MAX bytes at a time"
+#endif
+			_json_c_set_last_err(
+		    	"json_object_from_fd_ex: failed to printbuf_memappend after reading %d+%d bytes: %s", printbuf_length(pb), (int)ret, strerror(errno));
+			json_tokener_free(tok);
+			printbuf_free(pb);
+			return NULL;
+		}
 	}
 	if (ret < 0)
 	{
@@ -184,9 +194,9 @@ int json_object_to_fd(int fd, struct json_object *obj, int flags)
 }
 static int _json_object_to_fd(int fd, struct json_object *obj, int flags, const char *filename)
 {
-	int ret;
+	ssize_t ret;
 	const char *json_str;
-	unsigned int wpos, wsize;
+	size_t wpos, wsize;
 
 	filename = filename ? filename : "(fd)";
 
@@ -195,8 +205,7 @@ static int _json_object_to_fd(int fd, struct json_object *obj, int flags, const
 		return -1;
 	}
 
-	/* CAW: probably unnecessary, but the most 64bit safe */
-	wsize = (unsigned int)(strlen(json_str) & UINT_MAX);
+	wsize = strlen(json_str);
 	wpos = 0;
 	while (wpos < wsize)
 	{
@@ -208,7 +217,7 @@ static int _json_object_to_fd(int fd, struct json_object *obj, int flags, const
 		}
 
 		/* because of the above check for ret < 0, we can safely cast and add */
-		wpos += (unsigned int)ret;
+		wpos += (size_t)ret;
 	}
 
 	return 0;
@@ -238,7 +247,12 @@ int json_parse_int64(const char *buf, int64_t *retval)
 	val = strtoll(buf, &end, 10);
 	if (end != buf)
 		*retval = val;
-	return ((val == 0 && errno != 0) || (end == buf)) ? 1 : 0;
+	if ((val == 0 && errno != 0) || (end == buf))
+	{
+		errno = EINVAL;
+		return 1;
+	}
+	return 0;
 }
 
 int json_parse_uint64(const char *buf, uint64_t *retval)
@@ -255,7 +269,12 @@ int json_parse_uint64(const char *buf, uint64_t *retval)
 	val = strtoull(buf, &end, 10);
 	if (end != buf)
 		*retval = val;
-	return ((val == 0 && errno != 0) || (end == buf)) ? 1 : 0;
+	if ((val == 0 && errno != 0) || (end == buf))
+	{
+		errno = EINVAL;
+		return 1;
+	}
+	return 0;
 }
 
 #ifndef HAVE_REALLOC
diff --git a/vendor/json-c/json_util.h b/vendor/json-c/json_util.h
index 1f663e872a..62ad68853e 100644
--- a/vendor/json-c/json_util.h
+++ b/vendor/json-c/json_util.h
@@ -100,8 +100,17 @@ JSON_EXPORT int json_object_to_fd(int fd, struct json_object *obj, int flags);
  */
 JSON_EXPORT const char *json_util_get_last_err(void);
 
-/* these parsing helpers return zero on success */
+/**
+ * A parsing helper for integer values.  Returns 0 on success,
+ * with the parsed value assigned to *retval.  Overflow/underflow
+ * are NOT considered errors, but errno will be set to ERANGE,
+ * just like the strtol/strtoll functions do.
+ */
 JSON_EXPORT int json_parse_int64(const char *buf, int64_t *retval);
+/**
+ * A parsing help for integer values, providing one extra bit of 
+ * magnitude beyond json_parse_int64().
+ */
 JSON_EXPORT int json_parse_uint64(const char *buf, uint64_t *retval);
 /**
  * @deprecated
diff --git a/vendor/json-c/printbuf.c b/vendor/json-c/printbuf.c
index a08f7b1582..12d3b3319d 100644
--- a/vendor/json-c/printbuf.c
+++ b/vendor/json-c/printbuf.c
@@ -15,6 +15,7 @@
 
 #include "config.h"
 
+#include 
 #include 
 #include 
 #include 
@@ -56,6 +57,8 @@ struct printbuf *printbuf_new(void)
  *
  * If the current size is large enough, nothing is changed.
  *
+ * If extension failed, errno is set to indicate the error.
+ *
  * Note: this does not check the available space!  The caller
  *  is responsible for performing those calculations.
  */
@@ -68,7 +71,10 @@ static int printbuf_extend(struct printbuf *p, int min_size)
 		return 0;
 	/* Prevent signed integer overflows with large buffers. */
 	if (min_size > INT_MAX - 8)
+	{
+		errno = EFBIG;
 		return -1;
+	}
 	if (p->size > INT_MAX / 2)
 		new_size = min_size + 8;
 	else {
@@ -77,7 +83,7 @@ static int printbuf_extend(struct printbuf *p, int min_size)
 			new_size = min_size + 8;
 	}
 #ifdef PRINTBUF_DEBUG
-	MC_DEBUG("printbuf_memappend: realloc "
+	MC_DEBUG("printbuf_extend: realloc "
 	         "bpos=%d min_size=%d old_size=%d new_size=%d\n",
 	         p->bpos, min_size, p->size, new_size);
 #endif /* PRINTBUF_DEBUG */
@@ -92,7 +98,10 @@ int printbuf_memappend(struct printbuf *p, const char *buf, int size)
 {
 	/* Prevent signed integer overflows with large buffers. */
 	if (size < 0 || size > INT_MAX - p->bpos - 1)
+	{
+		errno = EFBIG;
 		return -1;
+	}
 	if (p->size <= p->bpos + size + 1)
 	{
 		if (printbuf_extend(p, p->bpos + size + 1) < 0)
@@ -112,7 +121,10 @@ int printbuf_memset(struct printbuf *pb, int offset, int charvalue, int len)
 		offset = pb->bpos;
 	/* Prevent signed integer overflows with large buffers. */
 	if (len < 0 || offset < -1 || len > INT_MAX - offset)
+	{
+		errno = EFBIG;
 		return -1;
+	}
 	size_needed = offset + len;
 	if (pb->size < size_needed)
 	{
diff --git a/vendor/json-c/random_seed.c b/vendor/json-c/random_seed.c
index 7945824c7a..a93c8b979a 100644
--- a/vendor/json-c/random_seed.c
+++ b/vendor/json-c/random_seed.c
@@ -229,6 +229,7 @@ static int get_dev_random_seed(int *seed)
 	if ((buf.st_mode & S_IFCHR) == 0)
 		return -1;
 
+	/* coverity[toctou] */
 	int fd = open(dev_random_file, O_RDONLY);
 	if (fd < 0)
 	{
@@ -253,7 +254,7 @@ static int get_dev_random_seed(int *seed)
 
 /* get_cryptgenrandom_seed */
 
-#ifdef WIN32
+#ifdef _WIN32
 
 #define HAVE_CRYPTGENRANDOM 1
 
@@ -310,6 +311,7 @@ static int get_time_seed(void)
 {
 	DEBUG_SEED("get_time_seed");
 
+	/* coverity[store_truncates_time_t] */
 	return (unsigned)time(NULL) * 433494437;
 }
 #endif
diff --git a/vendor/json-c/snprintf_compat.h b/vendor/json-c/snprintf_compat.h
index 76f7a6ce22..64091e6768 100644
--- a/vendor/json-c/snprintf_compat.h
+++ b/vendor/json-c/snprintf_compat.h
@@ -35,7 +35,7 @@ static int json_c_snprintf(char *str, size_t size, const char *format, ...)
 #define snprintf json_c_snprintf
 
 #elif !defined(HAVE_SNPRINTF) /* !HAVE_SNPRINTF */
-#error Need vsnprintf!
-#endif /* !HAVE_SNPRINTF && defined(WIN32) */
+#error snprintf is required but was not found
+#endif /* !HAVE_SNPRINTF */
 
 #endif /* __snprintf_compat_h */
diff --git a/vendor/json-c/strerror_override_private.h b/vendor/json-c/strerror_override_private.h
deleted file mode 100644
index 8726e59fc3..0000000000
--- a/vendor/json-c/strerror_override_private.h
+++ /dev/null
@@ -1,14 +0,0 @@
-#ifndef __json_strerror_override_private_h__
-#define __json_strerror_override_private_h__
-
-/**
- * @file
- * @brief Do not use, json-c internal, may be changed or removed at any time.
- */
-
-#include "json_types.h"
-
-/* Used by tests to get consistent output */
-JSON_EXPORT int _json_c_strerror_enable;
-
-#endif
diff --git a/vendor/json-c/vasprintf_compat.h b/vendor/json-c/vasprintf_compat.h
index 59b2e96074..550b6049cd 100644
--- a/vendor/json-c/vasprintf_compat.h
+++ b/vendor/json-c/vasprintf_compat.h
@@ -8,9 +8,9 @@
 
 #include "snprintf_compat.h"
 
-#ifndef WIN32
+#ifndef _WIN32
 #include 
-#endif /* !defined(WIN32) */
+#endif /* !defined(_WIN32) */
 #include 
 #include 
 
@@ -18,10 +18,10 @@
 /* CAW: compliant version of vasprintf */
 static int vasprintf(char **buf, const char *fmt, va_list ap)
 {
-#ifndef WIN32
+#ifndef _WIN32
 	static char _T_emptybuffer = '\0';
 	va_list ap2;
-#endif /* !defined(WIN32) */
+#endif /* !defined(_WIN32) */
 	int chars;
 	char *b;
 
@@ -30,16 +30,16 @@ static int vasprintf(char **buf, const char *fmt, va_list ap)
 		return -1;
 	}
 
-#ifdef WIN32
+#ifdef _WIN32
 	chars = _vscprintf(fmt, ap);
-#else  /* !defined(WIN32) */
+#else  /* !defined(_WIN32) */
 	/* CAW: RAWR! We have to hope to god here that vsnprintf doesn't overwrite
 	 * our buffer like on some 64bit sun systems... but hey, it's time to move on
 	 */
 	va_copy(ap2, ap);
 	chars = vsnprintf(&_T_emptybuffer, 0, fmt, ap2);
 	va_end(ap2);
-#endif /* defined(WIN32) */
+#endif /* defined(_WIN32) */
 	if (chars < 0 || (size_t)chars + 1 > SIZE_MAX / sizeof(char))
 	{
 		return -1;
diff --git a/vendor/libpng/ANNOUNCE b/vendor/libpng/ANNOUNCE
index 404cbb0de9..bc147adb78 100644
--- a/vendor/libpng/ANNOUNCE
+++ b/vendor/libpng/ANNOUNCE
@@ -1,5 +1,5 @@
-libpng 1.6.40 - June 21, 2023
-=============================
+libpng 1.6.43 - February 23, 2024
+=================================
 
 This is a public release of libpng, intended for use in production code.
 
@@ -9,13 +9,13 @@ Files available for download
 
 Source files with LF line endings (for Unix/Linux):
 
- * libpng-1.6.40.tar.xz (LZMA-compressed, recommended)
- * libpng-1.6.40.tar.gz
+ * libpng-1.6.43.tar.xz (LZMA-compressed, recommended)
+ * libpng-1.6.43.tar.gz (deflate-compressed)
 
 Source files with CRLF line endings (for Windows):
 
- * lpng1640.7z (LZMA-compressed, recommended)
- * lpng1640.zip
+ * lpng1643.7z (LZMA-compressed, recommended)
+ * lpng1643.zip (deflate-compressed)
 
 Other information:
 
@@ -25,15 +25,36 @@ Other information:
  * TRADEMARK.md
 
 
-Changes from version 1.6.39 to version 1.6.40
+Changes from version 1.6.42 to version 1.6.43
 ---------------------------------------------
 
- * Fixed the eXIf chunk multiplicity checks.
- * Fixed a memory leak in pCAL processing.
- * Corrected the validity report about tRNS inside png_get_valid().
- * Fixed various build issues on *BSD, Mac and Windows.
- * Updated the configurations and the scripts for continuous integration.
- * Cleaned up the code, the build scripts, and the documentation.
+ * Fixed the row width check in png_check_IHDR().
+   This corrected a bug that was specific to the 16-bit platforms,
+   and removed a spurious compiler warning from the 64-bit builds.
+   (Reported by Jacek Caban; fixed by John Bowler)
+ * Added eXIf chunk support to the push-mode reader in pngpread.c.
+   (Contributed by Chris Blume)
+ * Added contrib/pngexif for the benefit of the users who would like
+   to inspect the content of eXIf chunks.
+ * Added contrib/conftest/basic.dfa, a basic build-time configuration.
+   (Contributed by John Bowler)
+ * Fixed a preprocessor condition in pngread.c that broke build-time
+   configurations like contrib/conftest/pngcp.dfa.
+   (Contributed by John Bowler)
+ * Added CMake build support for LoongArch LSX.
+   (Contributed by GuXiWei)
+ * Fixed a CMake build error that occurred under a peculiar state of the
+   dependency tree. This was a regression introduced in libpng-1.6.41.
+   (Contributed by Dan Rosser)
+ * Marked the installed libpng headers as system headers in CMake.
+   (Contributed by Benjamin Buch)
+ * Updated the build support for RISCOS.
+   (Contributed by Cameron Cawley)
+ * Updated the makefiles to allow cross-platform builds to initialize
+   conventional make variables like AR and ARFLAGS.
+ * Added various improvements to the CI scripts in areas like version
+   consistency verification and text linting.
+ * Added version consistency verification to pngtest.c also.
 
 
 Send comments/corrections/commendations to png-mng-implement at lists.sf.net.
diff --git a/vendor/libpng/AUTHORS b/vendor/libpng/AUTHORS
index 60f41e5c65..544341694a 100644
--- a/vendor/libpng/AUTHORS
+++ b/vendor/libpng/AUTHORS
@@ -4,7 +4,9 @@ PNG REFERENCE LIBRARY AUTHORS
 This is the list of PNG Reference Library ("libpng") Contributing
 Authors, for copyright and licensing purposes.
 
+ * Adam Richter
  * Andreas Dilger
+ * Chris Blume
  * Cosmin Truta
  * Dave Martindale
  * Eric S. Raymond
@@ -33,20 +35,27 @@ Authors, for copyright and licensing purposes.
  * Vadim Barkov
  * Willem van Schaik
  * Zhijie Liang
+ * Apple Inc.
+    - Zixu Wang (王子旭)
  * Arm Holdings
-   - Richard Townsend
+    - Richard Townsend
  * Google Inc.
-   - Dan Field
-   - Leon Scroggins III
-   - Matt Sarett
-   - Mike Klein
-   - Sami Boukortt
-   - Wan-Teh Chang
+    - Dan Field
+    - Leon Scroggins III
+    - Matt Sarett
+    - Mike Klein
+    - Sami Boukortt
+    - Wan-Teh Chang
+ * Loongson Technology Corporation Ltd.
+    - GuXiWei (顾希伟)
+    - JinBo (金波)
+    - ZhangLixia (张利霞)
 
 The build projects, the build scripts, the test scripts, and other
-files in the "ci", "projects", "scripts" and "tests" directories, have
+files in the "projects", "scripts" and "tests" directories, have
 other copyright owners, but are released under the libpng license.
 
-Some files in the "contrib" directory, and some tools-generated files
-that are distributed with libpng, have other copyright owners, and are
-released under other open source licenses.
+Some files in the "ci" and "contrib" directories, as well as some
+of the tools-generated files that are distributed with libpng, have
+other copyright owners, and are released under other open source
+licenses.
diff --git a/vendor/libpng/CHANGES b/vendor/libpng/CHANGES
index 2d8c585c0e..441b57ecf1 100644
--- a/vendor/libpng/CHANGES
+++ b/vendor/libpng/CHANGES
@@ -6129,6 +6129,73 @@ Version 1.6.40 [June 21, 2023]
   Updated the configurations and the scripts for continuous integration.
   Cleaned up the code, the build scripts, and the documentation.
 
+Version 1.6.41 [January 24, 2024]
+  Added SIMD-optimized code for the LoongArch LSX hardware.
+    (Contributed by GuXiWei, JinBo and ZhangLixia)
+  Fixed the run-time discovery of MIPS MSA hardware.
+    (Contributed by Sui Jingfeng)
+  Fixed an off-by-one error in the function png_do_check_palette_indexes(),
+    which failed to recognize errors that might have existed in the first
+    column of a broken palette-encoded image. This was a benign regression
+    accidentally introduced in libpng-1.6.33. No pixel was harmed.
+    (Contributed by Adam Richter; reviewed by John Bowler)
+  Fixed, improved and modernized the contrib/pngminus programs, i.e.,
+    png2pnm.c and pnm2png.c
+  Removed old and peculiar portability hacks that were meant to silence
+    warnings issued by gcc version 7.1 alone.
+    (Contributed by John Bowler)
+  Fixed and modernized the CMake file, and raised the minimum required
+    CMake version from 3.1 to 3.6.
+    (Contributed by Clinton Ingram, Timothy Lyanguzov, Tyler Kropp, et al.)
+  Allowed the configure script to disable the building of auxiliary tools
+    and tests, thus catching up with the CMake file.
+    (Contributed by Carlo Bramini)
+  Fixed a build issue on Mac.
+    (Contributed by Zixu Wang)
+  Moved the Autoconf macro files to scripts/autoconf.
+  Moved the CMake files (except for the main CMakeLists.txt) to
+    scripts/cmake and moved the list of their contributing authors to
+    scripts/cmake/AUTHORS.md
+  Updated the CI configurations and scripts.
+  Relicensed the CI scripts to the MIT License.
+  Improved the test coverage.
+    (Contributed by John Bowler)
+
+Version 1.6.42 [January 29, 2024]
+  Fixed the implementation of the macro function png_check_sig().
+    This was an API regression, introduced in libpng-1.6.41.
+    (Reported by Matthieu Darbois)
+  Fixed and updated the libpng manual.
+
+Version 1.6.43 [February 23, 2024]
+  Fixed the row width check in png_check_IHDR().
+    This corrected a bug that was specific to the 16-bit platforms,
+    and removed a spurious compiler warning from the 64-bit builds.
+    (Reported by Jacek Caban; fixed by John Bowler)
+  Added eXIf chunk support to the push-mode reader in pngpread.c.
+    (Contributed by Chris Blume)
+  Added contrib/pngexif for the benefit of the users who would like
+    to inspect the content of eXIf chunks.
+  Added contrib/conftest/basic.dfa, a basic build-time configuration.
+    (Contributed by John Bowler)
+  Fixed a preprocessor condition in pngread.c that broke build-time
+    configurations like contrib/conftest/pngcp.dfa.
+    (Contributed by John Bowler)
+  Added CMake build support for LoongArch LSX.
+    (Contributed by GuXiWei)
+  Fixed a CMake build error that occurred under a peculiar state of the
+    dependency tree. This was a regression introduced in libpng-1.6.41.
+    (Contributed by Dan Rosser)
+  Marked the installed libpng headers as system headers in CMake.
+    (Contributed by Benjamin Buch)
+  Updated the build support for RISCOS.
+    (Contributed by Cameron Cawley)
+  Updated the makefiles to allow cross-platform builds to initialize
+    conventional make variables like AR and ARFLAGS.
+  Added various improvements to the CI scripts in areas like version
+    consistency verification and text linting.
+  Added version consistency verification to pngtest.c also.
+
 Send comments/corrections/commendations to png-mng-implement at lists.sf.net.
 Subscription is required; visit
 https://lists.sourceforge.net/lists/listinfo/png-mng-implement
diff --git a/vendor/libpng/LICENSE b/vendor/libpng/LICENSE
index 086d1c2fda..25f298f0fc 100644
--- a/vendor/libpng/LICENSE
+++ b/vendor/libpng/LICENSE
@@ -4,8 +4,8 @@ COPYRIGHT NOTICE, DISCLAIMER, and LICENSE
 PNG Reference Library License version 2
 ---------------------------------------
 
- * Copyright (c) 1995-2023 The PNG Reference Library Authors.
- * Copyright (c) 2018-2023 Cosmin Truta.
+ * Copyright (c) 1995-2024 The PNG Reference Library Authors.
+ * Copyright (c) 2018-2024 Cosmin Truta.
  * Copyright (c) 2000-2002, 2004, 2006-2018 Glenn Randers-Pehrson.
  * Copyright (c) 1996-1997 Andreas Dilger.
  * Copyright (c) 1995-1996 Guy Eric Schalnat, Group 42, Inc.
diff --git a/vendor/libpng/README b/vendor/libpng/README
index dedd2c1639..a6ca3ae9f9 100644
--- a/vendor/libpng/README
+++ b/vendor/libpng/README
@@ -1,4 +1,4 @@
-README for libpng version 1.6.40
+README for libpng version 1.6.43
 ================================
 
 See the note about version numbers near the top of `png.h`.
@@ -142,10 +142,11 @@ Files included in this distribution
     pngwrite.c    =>  High-level write functions
     pngwtran.c    =>  Write data transformations
     pngwutil.c    =>  Write utility functions
-    arm/          =>  Optimized code for the ARM platform
-    intel/        =>  Optimized code for the INTEL-SSE2 platform
-    mips/         =>  Optimized code for the MIPS platform
-    powerpc/      =>  Optimized code for the PowerPC platform
+    arm/          =>  Optimized code for ARM Neon
+    intel/        =>  Optimized code for INTEL SSE2
+    loongarch/    =>  Optimized code for LoongArch LSX
+    mips/         =>  Optimized code for MIPS MSA and MIPS MMI
+    powerpc/      =>  Optimized code for PowerPC VSX
     ci/           =>  Scripts for continuous integration
     contrib/      =>  External contributions
         arm-neon/     =>  Optimized code for the ARM-NEON platform
@@ -158,6 +159,7 @@ Files included in this distribution
         libtests/     =>  Test programs
         oss-fuzz/     =>  Files used by the OSS-Fuzz project for fuzz-testing
                           libpng
+        pngexif/      =>  Program to inspect the EXIF information in PNG files
         pngminim/     =>  Minimal decoder, encoder, and progressive decoder
                           programs demonstrating the use of pngusr.dfa
         pngminus/     =>  Simple pnm2png and png2pnm programs
diff --git a/vendor/libpng/example.c b/vendor/libpng/example.c
new file mode 100644
index 0000000000..3465fbb372
--- /dev/null
+++ b/vendor/libpng/example.c
@@ -0,0 +1,1041 @@
+
+#if 0 /* in case someone actually tries to compile this */
+
+/* example.c - an example of using libpng
+ *
+ * Maintained 2018-2024 Cosmin Truta
+ * Maintained 1998-2016 Glenn Randers-Pehrson
+ * Maintained 1996-1997 Andreas Dilger
+ * Written 1995-1996 Guy Eric Schalnat, Group 42, Inc.
+ *
+ * To the extent possible under law, the authors have waived
+ * all copyright and related or neighboring rights to this file.
+ * This work is published from: United States, Canada.
+ */
+
+/* This is an example of how to use libpng to read and write PNG files.
+ * The file libpng-manual.txt is much more verbose then this.  If you have
+ * not read it, do so first.  This was designed to be a starting point of an
+ * implementation.  This is not officially part of libpng, is hereby placed
+ * in the public domain, and therefore does not require a copyright notice.
+ *
+ * This file does not currently compile, because it is missing certain
+ * parts, like allocating memory to hold an image.  You will have to
+ * supply these parts to get it to compile.  For an example of a minimal
+ * working PNG reader/writer, see pngtest.c, included in this distribution;
+ * see also the programs in the contrib directory.
+ */
+
+/* The simple, but restricted approach to reading a PNG file or data stream
+ * requires just two function calls, as in the following complete program.
+ * Writing a file needs just one function call, so long as the data has an
+ * appropriate layout.
+ *
+ * The following code reads PNG image data from a file and writes it, in a
+ * potentially new format, to a new file.  While this code will compile, there
+ * is minimal (insufficient) error checking.  For a more realistic version,
+ * see contrib/examples/pngtopng.c
+ */
+
+#include 
+#include 
+#include 
+#include 
+#include 
+#include 
+
+int main(int argc, const char **argv)
+{
+   if (argc == 3)
+   {
+      png_image image; /* The control structure used by libpng */
+
+      /* Initialize the 'png_image' structure. */
+      memset(&image, 0, (sizeof image));
+      image.version = PNG_IMAGE_VERSION;
+
+      /* The first argument is the file to read: */
+      if (png_image_begin_read_from_file(&image, argv[1]) != 0)
+      {
+         png_bytep buffer;
+
+         /* Set the format in which to read the PNG file; this code chooses a
+          * simple sRGB format with a non-associated alpha channel, adequate to
+          * store most images.
+          */
+         image.format = PNG_FORMAT_RGBA;
+
+         /* Now allocate enough memory to hold the image in this format; the
+          * PNG_IMAGE_SIZE macro uses the information about the image (width,
+          * height and format) stored in 'image'.
+          */
+         buffer = malloc(PNG_IMAGE_SIZE(image));
+
+         /* If enough memory was available, read the image in the desired
+          * format, then write the result out to the new file.  'background' is
+          * not necessary when reading the image, because the alpha channel is
+          * preserved; if it were to be removed, for example if we requested
+          * PNG_FORMAT_RGB, then either a solid background color would have to
+          * be supplied, or the output buffer would have to be initialized to
+          * the actual background of the image.
+          *
+          * The fourth argument to png_image_finish_read is the 'row_stride' -
+          * this is the number of components allocated for the image in each
+          * row.  It has to be at least as big as the value returned by
+          * PNG_IMAGE_ROW_STRIDE, but if you just allocate space for the
+          * default, minimum size, using PNG_IMAGE_SIZE as above, you can pass
+          * zero.
+          *
+          * The final argument is a pointer to a buffer for the colormap;
+          * colormaps have exactly the same format as a row of image pixels
+          * (so you choose what format to make the colormap by setting
+          * image.format).  A colormap is only returned if
+          * PNG_FORMAT_FLAG_COLORMAP is also set in image.format, so in this
+          * case NULL is passed as the final argument.  If you do want to force
+          * all images into an index/color-mapped format, then you can use:
+          *
+          *    PNG_IMAGE_COLORMAP_SIZE(image)
+          *
+          * to find the maximum size of the colormap in bytes.
+          */
+         if (buffer != NULL &&
+            png_image_finish_read(&image, NULL/*background*/, buffer,
+                0/*row_stride*/, NULL/*colormap*/) != 0)
+         {
+            /* Now write the image out to the second argument.  In the write
+             * call 'convert_to_8bit' allows 16-bit data to be squashed down to
+             * 8 bits; this isn't necessary here because the original read was
+             * to the 8-bit format.
+             */
+            if (png_image_write_to_file(&image, argv[2], 0/*convert_to_8bit*/,
+                buffer, 0/*row_stride*/, NULL/*colormap*/) != 0)
+            {
+               /* The image has been written successfully. */
+               exit(0);
+            }
+         }
+         else
+         {
+            /* Calling png_image_free is optional unless the simplified API was
+             * not run to completion.  In this case, if there wasn't enough
+             * memory for 'buffer', we didn't complete the read, so we must
+             * free the image:
+             */
+            if (buffer == NULL)
+               png_image_free(&image);
+            else
+               free(buffer);
+         }
+      }
+
+      /* Something went wrong reading or writing the image.  libpng stores a
+       * textual message in the 'png_image' structure:
+       */
+      fprintf(stderr, "pngtopng: error: %s\n", image.message);
+      exit(1);
+   }
+
+   fprintf(stderr, "pngtopng: usage: pngtopng input-file output-file\n");
+   exit(2);
+}
+
+/* That's it ;-)  Of course you probably want to do more with PNG files than
+ * just converting them all to 32-bit RGBA PNG files; you can do that between
+ * the call to png_image_finish_read and png_image_write_to_file.  You can also
+ * ask for the image data to be presented in a number of different formats.
+ * You do this by simply changing the 'format' parameter set before allocating
+ * the buffer.
+ *
+ * The format parameter consists of five flags that define various aspects of
+ * the image.  You can simply add these together to get the format, or you can
+ * use one of the predefined macros from png.h (as above):
+ *
+ * PNG_FORMAT_FLAG_COLOR: if set, the image will have three color components
+ *    per pixel (red, green and blue); if not set, the image will just have one
+ *    luminance (grayscale) component.
+ *
+ * PNG_FORMAT_FLAG_ALPHA: if set, each pixel in the image will have an
+ *    additional alpha value; a linear value that describes the degree the
+ *    image pixel covers (overwrites) the contents of the existing pixel on the
+ *    display.
+ *
+ * PNG_FORMAT_FLAG_LINEAR: if set, the components of each pixel will be
+ *    returned as a series of 16-bit linear values; if not set, the components
+ *    will be returned as a series of 8-bit values encoded according to the
+ *    sRGB standard.  The 8-bit format is the normal format for images intended
+ *    for direct display, because almost all display devices do the inverse of
+ *    the sRGB transformation to the data they receive.  The 16-bit format is
+ *    more common for scientific data and image data that must be further
+ *    processed; because it is linear, simple math can be done on the component
+ *    values.  Regardless of the setting of this flag, the alpha channel is
+ *    always linear, although it will be 8 bits or 16 bits wide as specified by
+ *    the flag.
+ *
+ * PNG_FORMAT_FLAG_BGR: if set, the components of a color pixel will be
+ *    returned in the order blue, then green, then red.  If not set, the pixel
+ *    components are in the order red, then green, then blue.
+ *
+ * PNG_FORMAT_FLAG_AFIRST: if set, the alpha channel (if present) precedes the
+ *    color or grayscale components.  If not set, the alpha channel follows the
+ *    components.
+ *
+ * You do not have to read directly from a file.  You can read from memory or,
+ * on systems that support it, from a  FILE*.  This is controlled by
+ * the particular png_image_read_from_ function you call at the start.
+ * Likewise, on write, you can write to a FILE* if your system supports it.
+ * Check the macro PNG_STDIO_SUPPORTED to see if stdio support has been
+ * included in your libpng build.
+ *
+ * If you read 16-bit (PNG_FORMAT_FLAG_LINEAR) data, you may need to write it
+ * in the 8-bit format for display.  You do this by setting the convert_to_8bit
+ * flag to 'true'.
+ *
+ * Don't repeatedly convert between the 8-bit and 16-bit forms.  There is
+ * significant data loss when 16-bit data is converted to the 8-bit encoding,
+ * and the current libpng implementation of conversion to 16-bit is also
+ * significantly lossy.  The latter will be fixed in the future, but the former
+ * is unavoidable - the 8-bit format just doesn't have enough resolution.
+ */
+
+/* If your program needs more information from the PNG data it reads, or if you
+ * need to do more complex transformations, or minimize transformations, on the
+ * data you read, then you must use one of the several lower level libpng
+ * interfaces.
+ *
+ * All these interfaces require that you do your own error handling - your
+ * program must be able to arrange for control to return to your own code, any
+ * time libpng encounters a problem.  There are several ways to do this, but
+ * the standard way is to use the  interface to establish a return
+ * point within your own code.  You must do this if you do not use the
+ * simplified interface (above).
+ *
+ * The first step is to include the header files you need, including the libpng
+ * header file.  Include any standard headers and feature test macros your
+ * program requires before including png.h:
+ */
+#include 
+
+ /* The png_jmpbuf() macro, used in error handling, became available in
+  * libpng version 1.0.6.  If you want to be able to run your code with older
+  * versions of libpng, you must define the macro yourself (but only if it
+  * is not already defined by libpng!)
+  */
+
+#ifndef png_jmpbuf
+#  define png_jmpbuf(png_ptr) ((png_ptr)->png_jmpbuf)
+#endif
+
+/* Check to see if a file is a PNG file using png_sig_cmp().  png_sig_cmp()
+ * returns zero if the image is a PNG, and nonzero otherwise.
+ *
+ * The function check_if_png() shown here, but not used, returns nonzero (true)
+ * if the file can be opened and is a PNG, and 0 (false) otherwise.
+ *
+ * If this call is successful, and you are going to keep the file open,
+ * you should call png_set_sig_bytes(png_ptr, PNG_BYTES_TO_CHECK); once
+ * you have created the png_ptr, so that libpng knows your application
+ * has read that many bytes from the start of the file.  Make sure you
+ * don't call png_set_sig_bytes() with more than 8 bytes read or give it
+ * an incorrect number of bytes read, or you will either have read too
+ * many bytes (your fault), or you are telling libpng to read the wrong
+ * number of magic bytes (also your fault).
+ *
+ * Many applications already read the first 2 or 4 bytes from the start
+ * of the image to determine the file type, so it would be easiest just
+ * to pass the bytes to png_sig_cmp(), or even skip that if you know
+ * you have a PNG file, and call png_set_sig_bytes().
+ */
+#define PNG_BYTES_TO_CHECK 4
+int check_if_png(char *file_name, FILE **fp)
+{
+   char buf[PNG_BYTES_TO_CHECK];
+
+   /* Open the prospective PNG file. */
+   if ((*fp = fopen(file_name, "rb")) == NULL)
+      return 0;
+
+   /* Read in some of the signature bytes. */
+   if (fread(buf, 1, PNG_BYTES_TO_CHECK, *fp) != PNG_BYTES_TO_CHECK)
+      return 0;
+
+   /* Compare the first PNG_BYTES_TO_CHECK bytes of the signature.
+    * Return true if they match.
+    */
+   return png_sig_cmp(buf, 0, PNG_BYTES_TO_CHECK) == 0;
+}
+
+/* Read a PNG file.  You may want to return an error code if the read
+ * fails (depending upon the failure).  There are two "prototypes" given
+ * here - one where we are given the filename, and we need to open the
+ * file, and the other where we are given an open file (possibly with
+ * some or all of the magic bytes read - see comments above).
+ */
+#ifdef open_file /* prototype 1 */
+void read_png(char *file_name) /* We need to open the file */
+{
+   png_structp png_ptr;
+   png_infop info_ptr;
+   int sig_read = 0;
+   png_uint_32 width, height;
+   int bit_depth, color_type, interlace_type;
+   FILE *fp;
+
+   if ((fp = fopen(file_name, "rb")) == NULL)
+      return ERROR;
+
+#else no_open_file /* prototype 2 */
+void read_png(FILE *fp, int sig_read) /* File is already open */
+{
+   png_structp png_ptr;
+   png_infop info_ptr;
+   png_uint_32 width, height;
+   int bit_depth, color_type, interlace_type;
+#endif no_open_file /* Only use one prototype! */
+
+   /* Create and initialize the png_struct with the desired error handler
+    * functions.  If you want to use the default stderr and longjump method,
+    * you can supply NULL for the last three parameters.  We also supply the
+    * the compiler header file version, so that we know if the application
+    * was compiled with a compatible version of the library.  REQUIRED.
+    */
+   png_ptr = png_create_read_struct(PNG_LIBPNG_VER_STRING,
+       png_voidp user_error_ptr, user_error_fn, user_warning_fn);
+
+   if (png_ptr == NULL)
+   {
+      fclose(fp);
+      return ERROR;
+   }
+
+   /* Allocate/initialize the memory for image information.  REQUIRED. */
+   info_ptr = png_create_info_struct(png_ptr);
+   if (info_ptr == NULL)
+   {
+      fclose(fp);
+      png_destroy_read_struct(&png_ptr, NULL, NULL);
+      return ERROR;
+   }
+
+   /* Set error handling if you are using the setjmp/longjmp method (this is
+    * the normal method of doing things with libpng).  REQUIRED unless you
+    * set up your own error handlers in the png_create_read_struct() earlier.
+    */
+   if (setjmp(png_jmpbuf(png_ptr)))
+   {
+      /* Free all of the memory associated with the png_ptr and info_ptr. */
+      png_destroy_read_struct(&png_ptr, &info_ptr, NULL);
+      fclose(fp);
+      /* If we get here, we had a problem reading the file. */
+      return ERROR;
+   }
+
+   /* One of the following I/O initialization methods is REQUIRED. */
+#ifdef streams /* PNG file I/O method 1 */
+   /* Set up the input control if you are using standard C streams. */
+   png_init_io(png_ptr, fp);
+
+#else no_streams /* PNG file I/O method 2 */
+   /* If you are using replacement read functions, instead of calling
+    * png_init_io(), you would call:
+    */
+   png_set_read_fn(png_ptr, (void *)user_io_ptr, user_read_fn);
+   /* where user_io_ptr is a structure you want available to the callbacks. */
+#endif no_streams /* Use only one I/O method! */
+
+   /* If we have already read some of the signature */
+   png_set_sig_bytes(png_ptr, sig_read);
+
+#ifdef hilevel
+   /* If you have enough memory to read in the entire image at once,
+    * and you need to specify only transforms that can be controlled
+    * with one of the PNG_TRANSFORM_* bits (this presently excludes
+    * quantizing, filling, setting background, and doing gamma
+    * adjustment), then you can read the entire image (including
+    * pixels) into the info structure with this call:
+    */
+   png_read_png(png_ptr, info_ptr, png_transforms, NULL);
+
+#else
+   /* OK, you're doing it the hard way, with the lower-level functions. */
+
+   /* The call to png_read_info() gives us all of the information from the
+    * PNG file before the first IDAT (image data chunk).  REQUIRED.
+    */
+   png_read_info(png_ptr, info_ptr);
+
+   png_get_IHDR(png_ptr, info_ptr, &width, &height, &bit_depth, &color_type,
+       &interlace_type, NULL, NULL);
+
+   /* Set up the data transformations you want.  Note that these are all
+    * optional.  Only call them if you want/need them.  Many of the
+    * transformations only work on specific types of images, and many
+    * are mutually exclusive.
+    */
+
+   /* Tell libpng to strip 16 bits/color files down to 8 bits/color.
+    * Use accurate scaling if it's available, otherwise just chop off the
+    * low byte.
+    */
+#ifdef PNG_READ_SCALE_16_TO_8_SUPPORTED
+   png_set_scale_16(png_ptr);
+#else
+   png_set_strip_16(png_ptr);
+#endif
+
+   /* Strip alpha bytes from the input data without combining with the
+    * background (not recommended).
+    */
+   png_set_strip_alpha(png_ptr);
+
+   /* Extract multiple pixels with bit depths of 1, 2 or 4 from a single
+    * byte into separate bytes (useful for paletted and grayscale images).
+    */
+   png_set_packing(png_ptr);
+
+   /* Change the order of packed pixels to least significant bit first
+    * (not useful if you are using png_set_packing).
+    */
+   png_set_packswap(png_ptr);
+
+   /* Expand paletted colors into true RGB triplets. */
+   if (color_type == PNG_COLOR_TYPE_PALETTE)
+      png_set_palette_to_rgb(png_ptr);
+
+   /* Expand grayscale images to the full 8 bits from 1, 2 or 4 bits/pixel. */
+   if (color_type == PNG_COLOR_TYPE_GRAY && bit_depth < 8)
+      png_set_expand_gray_1_2_4_to_8(png_ptr);
+
+   /* Expand paletted or RGB images with transparency to full alpha channels
+    * so the data will be available as RGBA quartets.
+    */
+   if (png_get_valid(png_ptr, info_ptr, PNG_INFO_tRNS) != 0)
+      png_set_tRNS_to_alpha(png_ptr);
+
+   /* Set the background color to draw transparent and alpha images over.
+    * It is possible to set the red, green and blue components directly
+    * for paletted images, instead of supplying a palette index.  Note that,
+    * even if the PNG file supplies a background, you are not required to
+    * use it - you should use the (solid) application background if it has one.
+    */
+   png_color_16 my_background, *image_background;
+
+   if (png_get_bKGD(png_ptr, info_ptr, &image_background) != 0)
+      png_set_background(png_ptr, image_background,
+          PNG_BACKGROUND_GAMMA_FILE, 1, 1.0);
+   else
+      png_set_background(png_ptr, &my_background,
+          PNG_BACKGROUND_GAMMA_SCREEN, 0, 1.0);
+
+   /* Some suggestions as to how to get a screen gamma value.
+    *
+    * Note that screen gamma is the display_exponent, which includes
+    * the CRT_exponent and any correction for viewing conditions.
+    */
+   if (/* We have a user-defined screen gamma value */)
+      screen_gamma = user-defined screen_gamma;
+   /* This is one way that applications share the same screen gamma value. */
+   else if ((gamma_str = getenv("SCREEN_GAMMA")) != NULL)
+      screen_gamma = atof(gamma_str);
+   /* If we don't have another value */
+   else
+   {
+      screen_gamma = PNG_DEFAULT_sRGB; /* A good guess for a PC monitor
+                                          in a dimly lit room */
+      screen_gamma = PNG_GAMMA_MAC_18 or 1.0; /* Good guesses for Mac
+                                                 systems */
+   }
+
+   /* Tell libpng to handle the gamma conversion for you.  The final call
+    * is a good guess for PC generated images, but it should be configurable
+    * by the user at run time.  Gamma correction support in your application
+    * is strongly recommended.
+    */
+
+   int intent;
+
+   if (png_get_sRGB(png_ptr, info_ptr, &intent) != 0)
+      png_set_gamma(png_ptr, screen_gamma, PNG_DEFAULT_sRGB);
+   else
+   {
+      double image_gamma;
+      if (png_get_gAMA(png_ptr, info_ptr, &image_gamma) != 0)
+         png_set_gamma(png_ptr, screen_gamma, image_gamma);
+      else
+         png_set_gamma(png_ptr, screen_gamma, 0.45455);
+   }
+
+#ifdef PNG_READ_QUANTIZE_SUPPORTED
+   /* Quantize RGB files down to 8-bit palette, or reduce palettes
+    * to the number of colors available on your screen.
+    */
+   if ((color_type & PNG_COLOR_MASK_COLOR) != 0)
+   {
+      int num_palette;
+      png_colorp palette;
+
+      /* This reduces the image to the application-supplied palette. */
+      if (/* We have our own palette */)
+      {
+         /* An array of colors to which the image should be quantized. */
+         png_color std_color_cube[MAX_SCREEN_COLORS];
+         png_set_quantize(png_ptr, std_color_cube, MAX_SCREEN_COLORS,
+             MAX_SCREEN_COLORS, NULL, 0);
+      }
+      /* This reduces the image to the palette supplied in the file. */
+      else if (png_get_PLTE(png_ptr, info_ptr, &palette, &num_palette) != 0)
+      {
+         png_uint_16p histogram = NULL;
+         png_get_hIST(png_ptr, info_ptr, &histogram);
+         png_set_quantize(png_ptr, palette, num_palette,
+             max_screen_colors, histogram, 0);
+      }
+   }
+#endif /* READ_QUANTIZE */
+
+   /* Invert monochrome files to have 0 as white and 1 as black. */
+   png_set_invert_mono(png_ptr);
+
+   /* If you want to shift the pixel values from the range [0,255] or
+    * [0,65535] to the original [0,7] or [0,31], or whatever range the
+    * colors were originally in:
+    */
+   if (png_get_valid(png_ptr, info_ptr, PNG_INFO_sBIT) != 0)
+   {
+      png_color_8p sig_bit_p;
+      png_get_sBIT(png_ptr, info_ptr, &sig_bit_p);
+      png_set_shift(png_ptr, sig_bit_p);
+   }
+
+   /* Flip the RGB pixels to BGR (or RGBA to BGRA). */
+   if ((color_type & PNG_COLOR_MASK_COLOR) != 0)
+      png_set_bgr(png_ptr);
+
+   /* Swap the RGBA or GA data to ARGB or AG (or BGRA to ABGR). */
+   png_set_swap_alpha(png_ptr);
+
+   /* Swap bytes of 16-bit files to least significant byte first. */
+   png_set_swap(png_ptr);
+
+   /* Add filler (or alpha) byte (before/after each RGB triplet). */
+   png_set_filler(png_ptr, 0xffff, PNG_FILLER_AFTER);
+
+#ifdef PNG_READ_INTERLACING_SUPPORTED
+   /* Turn on interlace handling.  REQUIRED if you are not using
+    * png_read_image().  To see how to handle interlacing passes,
+    * see the png_read_row() method below:
+    */
+   number_passes = png_set_interlace_handling(png_ptr);
+#else /* !READ_INTERLACING */
+   number_passes = 1;
+#endif /* READ_INTERLACING */
+
+   /* Optional call to gamma correct and add the background to the palette
+    * and update info structure.  REQUIRED if you are expecting libpng to
+    * update the palette for you (i.e. you selected such a transform above).
+    */
+   png_read_update_info(png_ptr, info_ptr);
+
+   /* Allocate the memory to hold the image using the fields of info_ptr. */
+   png_bytep row_pointers[height];
+   for (row = 0; row < height; row++)
+      row_pointers[row] = NULL; /* Clear the pointer array */
+   for (row = 0; row < height; row++)
+      row_pointers[row] = png_malloc(png_ptr, png_get_rowbytes(png_ptr,
+          info_ptr));
+
+   /* Now it's time to read the image.  One of these methods is REQUIRED. */
+#ifdef entire /* Read the entire image in one go */
+   png_read_image(png_ptr, row_pointers);
+
+#else no_entire /* Read the image one or more scanlines at a time */
+   /* The other way to read images - deal with interlacing: */
+   for (pass = 0; pass < number_passes; pass++)
+   {
+#ifdef single /* Read the image a single row at a time */
+      for (y = 0; y < height; y++)
+         png_read_rows(png_ptr, &row_pointers[y], NULL, 1);
+
+#else no_single /* Read the image several rows at a time */
+      for (y = 0; y < height; y += number_of_rows)
+      {
+#ifdef sparkle /* Read the image using the "sparkle" effect. */
+         png_read_rows(png_ptr, &row_pointers[y], NULL,
+             number_of_rows);
+#else no_sparkle /* Read the image using the "rectangle" effect */
+         png_read_rows(png_ptr, NULL, &row_pointers[y],
+             number_of_rows);
+#endif no_sparkle /* Use only one of these two methods */
+      }
+
+      /* If you want to display the image after every pass, do so here. */
+#endif no_single /* Use only one of these two methods */
+   }
+#endif no_entire /* Use only one of these two methods */
+
+   /* Read rest of file, and get additional chunks in info_ptr.  REQUIRED. */
+   png_read_end(png_ptr, info_ptr);
+#endif hilevel
+
+   /* At this point you have read the entire image. */
+
+   /* Clean up after the read, and free any memory allocated.  REQUIRED. */
+   png_destroy_read_struct(&png_ptr, &info_ptr, NULL);
+
+   /* Close the file. */
+   fclose(fp);
+
+   /* That's it! */
+   return OK;
+}
+
+/* Progressively read a file */
+
+int
+initialize_png_reader(png_structp *png_ptr, png_infop *info_ptr)
+{
+   /* Create and initialize the png_struct with the desired error handler
+    * functions.  If you want to use the default stderr and longjump method,
+    * you can supply NULL for the last three parameters.  We also check that
+    * the library version is compatible, in case we are using dynamically
+    * linked libraries.
+    */
+   *png_ptr = png_create_read_struct(PNG_LIBPNG_VER_STRING,
+        png_voidp user_error_ptr, user_error_fn, user_warning_fn);
+   if (*png_ptr == NULL)
+   {
+      *info_ptr = NULL;
+      return ERROR;
+   }
+   *info_ptr = png_create_info_struct(png_ptr);
+   if (*info_ptr == NULL)
+   {
+      png_destroy_read_struct(png_ptr, info_ptr, NULL);
+      return ERROR;
+   }
+   if (setjmp(png_jmpbuf((*png_ptr))))
+   {
+      png_destroy_read_struct(png_ptr, info_ptr, NULL);
+      return ERROR;
+   }
+
+   /* You will need to provide all three function callbacks,
+    * even if you aren't using all of them.
+    * If you aren't using all functions, you can specify NULL
+    * parameters.  Even when all three functions are NULL,
+    * you need to call png_set_progressive_read_fn().
+    * These functions shouldn't be dependent on global or
+    * static variables if you are decoding several images
+    * simultaneously.  You should store stream specific data
+    * in a separate struct, given as the second parameter,
+    * and retrieve the pointer from inside the callbacks using
+    * the function png_get_progressive_ptr(png_ptr).
+    */
+   png_set_progressive_read_fn(*png_ptr, (void *)stream_data,
+       info_callback, row_callback, end_callback);
+   return OK;
+}
+
+int
+process_data(png_structp *png_ptr, png_infop *info_ptr,
+    png_bytep buffer, png_uint_32 length)
+{
+   if (setjmp(png_jmpbuf((*png_ptr))))
+   {
+      /* Free the png_ptr and info_ptr memory on error. */
+      png_destroy_read_struct(png_ptr, info_ptr, NULL);
+      return ERROR;
+   }
+
+   /* Give chunks of data as they arrive from the data stream
+    * (in order, of course).
+    * On segmented machines, don't give it any more than 64K.
+    * The library seems to run fine with sizes of 4K, although
+    * you can give it much less if necessary. (I assume you can
+    * give it chunks of 1 byte, but I haven't tried with less
+    * than 256 bytes yet.)  When this function returns, you may
+    * want to display any rows that were generated in the row
+    * callback, if you aren't already displaying them there.
+    */
+   png_process_data(*png_ptr, *info_ptr, buffer, length);
+   return OK;
+}
+
+info_callback(png_structp png_ptr, png_infop info)
+{
+   /* Do any setup here, including setting any of the transformations
+    * mentioned in the Reading PNG files section.  For now, you _must_
+    * call either png_start_read_image() or png_read_update_info()
+    * after all the transformations are set (even if you don't set
+    * any).  You may start getting rows before png_process_data()
+    * returns, so this is your last chance to prepare for that.
+    */
+}
+
+row_callback(png_structp png_ptr, png_bytep new_row,
+    png_uint_32 row_num, int pass)
+{
+   /* This function is called for every row in the image.  If the
+    * image is interlaced, and you turned on the interlace handler,
+    * this function will be called for every row in every pass.
+    *
+    * In this function you will receive a pointer to new row data from
+    * libpng called new_row that is to replace a corresponding row (of
+    * the same data format) in a buffer allocated by your application.
+    *
+    * The new row data pointer "new_row" may be NULL, indicating there is
+    * no new data to be replaced (in cases of interlace loading).
+    *
+    * If new_row is not NULL, then you need to call
+    * png_progressive_combine_row(), to replace the corresponding row as
+    * shown below:
+    */
+
+   /* Get pointer to corresponding row in our PNG read buffer. */
+   png_bytep old_row = ((png_bytep *)our_data)[row_num];
+
+#ifdef PNG_READ_INTERLACING_SUPPORTED
+   /* If both rows are allocated, then copy the new row
+    * data to the corresponding row data.
+    */
+   if (old_row != NULL && new_row != NULL)
+      png_progressive_combine_row(png_ptr, old_row, new_row);
+
+   /* The rows and passes are called in order, so you don't really
+    * need the row_num and pass, but I'm supplying them because it
+    * may make your life easier.
+    *
+    * For the non-NULL rows of interlaced images, you must call
+    * png_progressive_combine_row() passing in the new row and the
+    * old row, as demonstrated above.  You can call this function for
+    * NULL rows (it will just return) and for non-interlaced images
+    * (it just does the memcpy for you) if it will make the code
+    * easier.  Thus, you can just do this for all cases:
+    */
+   png_progressive_combine_row(png_ptr, old_row, new_row);
+
+   /* where old_row is what was displayed for previous rows.  Note
+    * that the first pass (pass == 0 really) will completely cover
+    * the old row, so the rows do not have to be initialized.  After
+    * the first pass (and only for interlaced images), you will have
+    * to pass the current row as new_row, and the function will combine
+    * the old row and the new row.
+    */
+#endif /* READ_INTERLACING */
+}
+
+end_callback(png_structp png_ptr, png_infop info)
+{
+   /* This function is called when the whole image has been read,
+    * including any chunks after the image (up to and including
+    * the IEND).  You will usually have the same info chunk as you
+    * had in the header, although some data may have been added
+    * to the comments and time fields.
+    *
+    * Most people won't do much here, perhaps setting a flag that
+    * marks the image as finished.
+    */
+}
+
+/* Write a png file */
+void write_png(char *file_name /* , ... other image information ... */)
+{
+   FILE *fp;
+   png_structp png_ptr;
+   png_infop info_ptr;
+   png_colorp palette;
+
+   /* Open the file */
+   fp = fopen(file_name, "wb");
+   if (fp == NULL)
+      return ERROR;
+
+   /* Create and initialize the png_struct with the desired error handler
+    * functions.  If you want to use the default stderr and longjump method,
+    * you can supply NULL for the last three parameters.  We also check that
+    * the library version is compatible with the one used at compile time,
+    * in case we are using dynamically linked libraries.  REQUIRED.
+    */
+   png_ptr = png_create_write_struct(PNG_LIBPNG_VER_STRING,
+       png_voidp user_error_ptr, user_error_fn, user_warning_fn);
+   if (png_ptr == NULL)
+   {
+      fclose(fp);
+      return ERROR;
+   }
+
+   /* Allocate/initialize the image information data.  REQUIRED. */
+   info_ptr = png_create_info_struct(png_ptr);
+   if (info_ptr == NULL)
+   {
+      fclose(fp);
+      png_destroy_write_struct(&png_ptr,  NULL);
+      return ERROR;
+   }
+
+   /* Set up error handling.  REQUIRED if you aren't supplying your own
+    * error handling functions in the png_create_write_struct() call.
+    */
+   if (setjmp(png_jmpbuf(png_ptr)))
+   {
+      /* If we get here, we had a problem writing the file. */
+      fclose(fp);
+      png_destroy_write_struct(&png_ptr, &info_ptr);
+      return ERROR;
+   }
+
+   /* One of the following I/O initialization functions is REQUIRED. */
+
+#ifdef streams /* I/O initialization method 1 */
+   /* Set up the output control if you are using standard C streams. */
+   png_init_io(png_ptr, fp);
+
+#else no_streams /* I/O initialization method 2 */
+   /* If you are using replacement write functions, instead of calling
+    * png_init_io(), you would call:
+    */
+   png_set_write_fn(png_ptr, (void *)user_io_ptr, user_write_fn,
+       user_IO_flush_function);
+   /* where user_io_ptr is a structure you want available to the callbacks. */
+#endif no_streams /* Only use one initialization method */
+
+#ifdef hilevel
+   /* This is the easy way.  Use it if you already have all the
+    * image info living in the structure.  You could "|" many
+    * PNG_TRANSFORM flags into the png_transforms integer here.
+    */
+   png_write_png(png_ptr, info_ptr, png_transforms, NULL);
+
+#else
+   /* This is the hard way. */
+
+   /* Set the image information here.  Width and height are up to 2^31,
+    * bit_depth is one of 1, 2, 4, 8 or 16, but valid values also depend on
+    * the color_type selected.  color_type is one of PNG_COLOR_TYPE_GRAY,
+    * PNG_COLOR_TYPE_GRAY_ALPHA, PNG_COLOR_TYPE_PALETTE, PNG_COLOR_TYPE_RGB,
+    * or PNG_COLOR_TYPE_RGB_ALPHA.  interlace is either PNG_INTERLACE_NONE or
+    * PNG_INTERLACE_ADAM7, and the compression_type and filter_type MUST
+    * currently be PNG_COMPRESSION_TYPE_BASE and PNG_FILTER_TYPE_BASE.
+    * REQUIRED.
+    */
+   png_set_IHDR(png_ptr, info_ptr, width, height, bit_depth,
+       PNG_COLOR_TYPE_???, PNG_INTERLACE_????,
+       PNG_COMPRESSION_TYPE_BASE, PNG_FILTER_TYPE_BASE);
+
+   /* Set the palette if there is one.  REQUIRED for indexed-color images. */
+   palette = (png_colorp)png_malloc(png_ptr,
+       PNG_MAX_PALETTE_LENGTH * (sizeof (png_color)));
+   /* ... Set palette colors ... */
+   png_set_PLTE(png_ptr, info_ptr, palette, PNG_MAX_PALETTE_LENGTH);
+   /* You must not free palette here, because png_set_PLTE only makes a link
+    * to the palette that you allocated.  Wait until you are about to destroy
+    * the png structure.
+    */
+
+   /* Optional significant bit (sBIT) chunk. */
+   png_color_8 sig_bit;
+
+   /* If we are dealing with a grayscale image then */
+   sig_bit.gray = true_bit_depth;
+
+   /* Otherwise, if we are dealing with a color image then */
+   sig_bit.red = true_red_bit_depth;
+   sig_bit.green = true_green_bit_depth;
+   sig_bit.blue = true_blue_bit_depth;
+
+   /* If the image has an alpha channel then */
+   sig_bit.alpha = true_alpha_bit_depth;
+
+   png_set_sBIT(png_ptr, info_ptr, &sig_bit);
+
+   /* Optional gamma chunk is strongly suggested if you have any guess
+    * as to the correct gamma of the image.
+    */
+   png_set_gAMA(png_ptr, info_ptr, gamma);
+
+   /* Optionally write comments into the image. */
+   {
+      png_text text_ptr[3];
+
+      char key0[] = "Title";
+      char text0[] = "Mona Lisa";
+      text_ptr[0].key = key0;
+      text_ptr[0].text = text0;
+      text_ptr[0].compression = PNG_TEXT_COMPRESSION_NONE;
+      text_ptr[0].itxt_length = 0;
+      text_ptr[0].lang = NULL;
+      text_ptr[0].lang_key = NULL;
+
+      char key1[] = "Author";
+      char text1[] = "Leonardo DaVinci";
+      text_ptr[1].key = key1;
+      text_ptr[1].text = text1;
+      text_ptr[1].compression = PNG_TEXT_COMPRESSION_NONE;
+      text_ptr[1].itxt_length = 0;
+      text_ptr[1].lang = NULL;
+      text_ptr[1].lang_key = NULL;
+
+      char key2[] = "Description";
+      char text2[] = "";
+      text_ptr[2].key = key2;
+      text_ptr[2].text = text2;
+      text_ptr[2].compression = PNG_TEXT_COMPRESSION_zTXt;
+      text_ptr[2].itxt_length = 0;
+      text_ptr[2].lang = NULL;
+      text_ptr[2].lang_key = NULL;
+
+      png_set_text(write_ptr, write_info_ptr, text_ptr, 3);
+   }
+
+   /* Other optional chunks like cHRM, bKGD, tRNS, tIME, oFFs, pHYs. */
+
+   /* Note that if sRGB is present, the gAMA and cHRM chunks must be ignored
+    * on read and, if your application chooses to write them, they must
+    * be written in accordance with the sRGB profile.
+    */
+
+   /* Write the file header information.  REQUIRED. */
+   png_write_info(png_ptr, info_ptr);
+
+   /* If you want, you can write the info in two steps, in case you need to
+    * write your private chunk ahead of PLTE:
+    *
+    *   png_write_info_before_PLTE(write_ptr, write_info_ptr);
+    *   write_my_chunk();
+    *   png_write_info(png_ptr, info_ptr);
+    *
+    * However, given the level of known- and unknown-chunk support in 1.2.0
+    * and up, this should no longer be necessary.
+    */
+
+   /* Once we write out the header, the compression type on the text
+    * chunk gets changed to PNG_TEXT_COMPRESSION_NONE_WR or
+    * PNG_TEXT_COMPRESSION_zTXt_WR, so it doesn't get written out again
+    * at the end.
+    */
+
+   /* Set up the transformations you want.  Note that these are
+    * all optional.  Only call them if you want them.
+    */
+
+   /* Invert monochrome pixels. */
+   png_set_invert_mono(png_ptr);
+
+   /* Shift the pixels up to a legal bit depth and fill in
+    * as appropriate to correctly scale the image.
+    */
+   png_set_shift(png_ptr, &sig_bit);
+
+   /* Pack pixels into bytes. */
+   png_set_packing(png_ptr);
+
+   /* Swap location of alpha bytes from ARGB to RGBA. */
+   png_set_swap_alpha(png_ptr);
+
+   /* Get rid of filler (OR ALPHA) bytes, pack XRGB/RGBX/ARGB/RGBA into
+    * RGB (4 channels -> 3 channels).  The second parameter is not used.
+    */
+   png_set_filler(png_ptr, 0, PNG_FILLER_BEFORE);
+
+   /* Flip BGR pixels to RGB. */
+   png_set_bgr(png_ptr);
+
+   /* Swap bytes of 16-bit files to most significant byte first. */
+   png_set_swap(png_ptr);
+
+   /* Swap bits of 1-bit, 2-bit, 4-bit packed pixel formats. */
+   png_set_packswap(png_ptr);
+
+   /* Turn on interlace handling if you are not using png_write_image(). */
+   if (interlacing != 0)
+      number_passes = png_set_interlace_handling(png_ptr);
+   else
+      number_passes = 1;
+
+   /* The easiest way to write the image (you may have a different memory
+    * layout, however, so choose what fits your needs best).  You need to
+    * use the first method if you aren't handling interlacing yourself.
+    */
+   png_uint_32 k, height, width;
+
+   /* In this example, "image" is a one-dimensional array of bytes. */
+
+   /* Guard against integer overflow. */
+   if (height > PNG_SIZE_MAX / (width * bytes_per_pixel))
+      png_error(png_ptr, "Image data buffer would be too large");
+
+   png_byte image[height * width * bytes_per_pixel];
+   png_bytep row_pointers[height];
+
+   if (height > PNG_UINT_32_MAX / (sizeof (png_bytep)))
+      png_error(png_ptr, "Image is too tall to process in memory");
+
+   /* Set up pointers into your "image" byte array. */
+   for (k = 0; k < height; k++)
+      row_pointers[k] = image + k * width * bytes_per_pixel;
+
+   /* One of the following output methods is REQUIRED. */
+
+#ifdef entire /* Write out the entire image data in one call */
+   png_write_image(png_ptr, row_pointers);
+
+   /* The other way to write the image - deal with interlacing. */
+
+#else no_entire /* Write out the image data by one or more scanlines */
+
+   /* The number of passes is either 1 for non-interlaced images,
+    * or 7 for interlaced images.
+    */
+   for (pass = 0; pass < number_passes; pass++)
+   {
+      /* Write a few rows at a time. */
+      png_write_rows(png_ptr, &row_pointers[first_row], number_of_rows);
+
+      /* If you are only writing one row at a time, this works. */
+      for (y = 0; y < height; y++)
+         png_write_rows(png_ptr, &row_pointers[y], 1);
+   }
+#endif no_entire /* Use only one output method */
+
+   /* You can write optional chunks like tEXt, zTXt, and tIME at the end
+    * as well.  Shouldn't be necessary in 1.2.0 and up, as all the public
+    * chunks are supported, and you can use png_set_unknown_chunks() to
+    * register unknown chunks into the info structure to be written out.
+    */
+
+   /* It is REQUIRED to call this to finish writing the rest of the file. */
+   png_write_end(png_ptr, info_ptr);
+#endif hilevel
+
+   /* If you png_malloced a palette, free it here.
+    * (Don't free info_ptr->palette, as shown in versions 1.0.5m and earlier of
+    * this example; if libpng mallocs info_ptr->palette, libpng will free it).
+    * If you allocated it with malloc() instead of png_malloc(), use free()
+    * instead of png_free().
+    */
+   png_free(png_ptr, palette);
+   palette = NULL;
+
+   /* Similarly, if you png_malloced any data that you passed in with
+    * png_set_something(), such as a hist or trans array, free it here,
+    * when you can be sure that libpng is through with it.
+    */
+   png_free(png_ptr, trans);
+   trans = NULL;
+
+   /* Whenever you use png_free(), it is a good idea to set the pointer to
+    * NULL in case your application inadvertently tries to png_free() it
+    * again.  When png_free() sees a NULL it returns without action, avoiding
+    * the double-free problem.
+    */
+
+   /* Clean up after the write, and free any allocated memory. */
+   png_destroy_write_struct(&png_ptr, &info_ptr);
+
+   /* Close the file. */
+   fclose(fp);
+
+   /* That's it! */
+   return OK;
+}
+
+#endif /* if 0 */
diff --git a/vendor/libpng/png.c b/vendor/libpng/png.c
index d6471b06cc..9ed3157009 100644
--- a/vendor/libpng/png.c
+++ b/vendor/libpng/png.c
@@ -1,7 +1,7 @@
 
 /* png.c - location for general purpose libpng functions
  *
- * Copyright (c) 2018-2023 Cosmin Truta
+ * Copyright (c) 2018-2024 Cosmin Truta
  * Copyright (c) 1998-2002,2004,2006-2018 Glenn Randers-Pehrson
  * Copyright (c) 1996-1997 Andreas Dilger
  * Copyright (c) 1995-1996 Guy Eric Schalnat, Group 42, Inc.
@@ -14,27 +14,7 @@
 #include "pngpriv.h"
 
 /* Generate a compiler error if there is an old png.h in the search path. */
-typedef png_libpng_version_1_6_40 Your_png_h_is_not_version_1_6_40;
-
-#ifdef __GNUC__
-/* The version tests may need to be added to, but the problem warning has
- * consistently been fixed in GCC versions which obtain wide-spread release.
- * The problem is that many versions of GCC rearrange comparison expressions in
- * the optimizer in such a way that the results of the comparison will change
- * if signed integer overflow occurs.  Such comparisons are not permitted in
- * ANSI C90, however GCC isn't clever enough to work out that that do not occur
- * below in png_ascii_from_fp and png_muldiv, so it produces a warning with
- * -Wextra.  Unfortunately this is highly dependent on the optimizer and the
- * machine architecture so the warning comes and goes unpredictably and is
- * impossible to "fix", even were that a good idea.
- */
-#if __GNUC__ == 7 && __GNUC_MINOR__ == 1
-#define GCC_STRICT_OVERFLOW 1
-#endif /* GNU 7.1.x */
-#endif /* GNU */
-#ifndef GCC_STRICT_OVERFLOW
-#define GCC_STRICT_OVERFLOW 0
-#endif
+typedef png_libpng_version_1_6_43 Your_png_h_is_not_version_1_6_43;
 
 /* Tells libpng that we have already handled the first "num_bytes" bytes
  * of the PNG file signature.  If the PNG data is embedded into another
@@ -73,21 +53,21 @@ png_set_sig_bytes(png_structrp png_ptr, int num_bytes)
 int PNGAPI
 png_sig_cmp(png_const_bytep sig, size_t start, size_t num_to_check)
 {
-   png_byte png_signature[8] = {137, 80, 78, 71, 13, 10, 26, 10};
+   static const png_byte png_signature[8] = {137, 80, 78, 71, 13, 10, 26, 10};
 
    if (num_to_check > 8)
       num_to_check = 8;
 
    else if (num_to_check < 1)
-      return (-1);
+      return -1;
 
    if (start > 7)
-      return (-1);
+      return -1;
 
    if (start + num_to_check > 8)
       num_to_check = 8 - start;
 
-   return ((int)(memcmp(&sig[start], &png_signature[start], num_to_check)));
+   return memcmp(&sig[start], &png_signature[start], num_to_check);
 }
 
 #endif /* READ */
@@ -447,7 +427,6 @@ png_info_init_3,(png_infopp ptr_ptr, size_t png_info_struct_size),
    memset(info_ptr, 0, (sizeof *info_ptr));
 }
 
-/* The following API is not called internally */
 void PNGAPI
 png_data_freer(png_const_structrp png_ptr, png_inforp info_ptr,
     int freer, png_uint_32 mask)
@@ -686,9 +665,9 @@ png_voidp PNGAPI
 png_get_io_ptr(png_const_structrp png_ptr)
 {
    if (png_ptr == NULL)
-      return (NULL);
+      return NULL;
 
-   return (png_ptr->io_ptr);
+   return png_ptr->io_ptr;
 }
 
 #if defined(PNG_READ_SUPPORTED) || defined(PNG_WRITE_SUPPORTED)
@@ -752,7 +731,7 @@ png_convert_to_rfc1123_buffer(char out[29], png_const_timep ptime)
 
    {
       size_t pos = 0;
-      char number_buf[5]; /* enough for a four-digit year */
+      char number_buf[5] = {0, 0, 0, 0, 0}; /* enough for a four-digit year */
 
 #     define APPEND_STRING(string) pos = png_safecat(out, 29, pos, (string))
 #     define APPEND_NUMBER(format, value)\
@@ -815,8 +794,8 @@ png_get_copyright(png_const_structrp png_ptr)
    return PNG_STRING_COPYRIGHT
 #else
    return PNG_STRING_NEWLINE \
-      "libpng version 1.6.40" PNG_STRING_NEWLINE \
-      "Copyright (c) 2018-2023 Cosmin Truta" PNG_STRING_NEWLINE \
+      "libpng version 1.6.43" PNG_STRING_NEWLINE \
+      "Copyright (c) 2018-2024 Cosmin Truta" PNG_STRING_NEWLINE \
       "Copyright (c) 1998-2002,2004,2006-2018 Glenn Randers-Pehrson" \
       PNG_STRING_NEWLINE \
       "Copyright (c) 1996-1997 Andreas Dilger" PNG_STRING_NEWLINE \
@@ -977,7 +956,7 @@ png_reset_zstream(png_structrp png_ptr)
       return Z_STREAM_ERROR;
 
    /* WARNING: this resets the window bits to the maximum! */
-   return (inflateReset(&png_ptr->zstream));
+   return inflateReset(&png_ptr->zstream);
 }
 #endif /* READ */
 
@@ -986,7 +965,7 @@ png_uint_32 PNGAPI
 png_access_version_number(void)
 {
    /* Version of *.c files used when building libpng */
-   return((png_uint_32)PNG_LIBPNG_VER);
+   return (png_uint_32)PNG_LIBPNG_VER;
 }
 
 #if defined(PNG_READ_SUPPORTED) || defined(PNG_WRITE_SUPPORTED)
@@ -1842,14 +1821,14 @@ png_icc_profile_error(png_const_structrp png_ptr, png_colorspacerp colorspace,
    }
 #  ifdef PNG_WARNINGS_SUPPORTED
    else
-      {
-         char number[PNG_NUMBER_BUFFER_SIZE]; /* +24 = 114 */
+   {
+      char number[PNG_NUMBER_BUFFER_SIZE]; /* +24 = 114 */
 
-         pos = png_safecat(message, (sizeof message), pos,
-             png_format_number(number, number+(sizeof number),
-             PNG_NUMBER_FORMAT_x, value));
-         pos = png_safecat(message, (sizeof message), pos, "h: "); /* +2 = 116 */
-      }
+      pos = png_safecat(message, (sizeof message), pos,
+          png_format_number(number, number+(sizeof number),
+          PNG_NUMBER_FORMAT_x, value));
+      pos = png_safecat(message, (sizeof message), pos, "h: "); /* +2 = 116 */
+   }
 #  endif
    /* The 'reason' is an arbitrary message, allow +79 maximum 195 */
    pos = png_safecat(message, (sizeof message), pos, reason);
@@ -2532,17 +2511,6 @@ png_colorspace_set_rgb_coefficients(png_structrp png_ptr)
 
 #endif /* COLORSPACE */
 
-#ifdef __GNUC__
-/* This exists solely to work round a warning from GNU C. */
-static int /* PRIVATE */
-png_gt(size_t a, size_t b)
-{
-   return a > b;
-}
-#else
-#   define png_gt(a,b) ((a) > (b))
-#endif
-
 void /* PRIVATE */
 png_check_IHDR(png_const_structrp png_ptr,
     png_uint_32 width, png_uint_32 height, int bit_depth,
@@ -2564,8 +2532,16 @@ png_check_IHDR(png_const_structrp png_ptr,
       error = 1;
    }
 
-   if (png_gt(((width + 7) & (~7U)),
-       ((PNG_SIZE_MAX
+   /* The bit mask on the first line below must be at least as big as a
+    * png_uint_32.  "~7U" is not adequate on 16-bit systems because it will
+    * be an unsigned 16-bit value.  Casting to (png_alloc_size_t) makes the
+    * type of the result at least as bit (in bits) as the RHS of the > operator
+    * which also avoids a common warning on 64-bit systems that the comparison
+    * of (png_uint_32) against the constant value on the RHS will always be
+    * false.
+    */
+   if (((width + 7) & ~(png_alloc_size_t)7) >
+       (((PNG_SIZE_MAX
            - 48        /* big_row_buf hack */
            - 1)        /* filter byte */
            / 8)        /* 8-byte RGBA pixels */
@@ -2891,14 +2867,6 @@ png_pow10(int power)
 /* Function to format a floating point value in ASCII with a given
  * precision.
  */
-#if GCC_STRICT_OVERFLOW
-#pragma GCC diagnostic push
-/* The problem arises below with exp_b10, which can never overflow because it
- * comes, originally, from frexp and is therefore limited to a range which is
- * typically +/-710 (log2(DBL_MAX)/log2(DBL_MIN)).
- */
-#pragma GCC diagnostic warning "-Wstrict-overflow=2"
-#endif /* GCC_STRICT_OVERFLOW */
 void /* PRIVATE */
 png_ascii_from_fp(png_const_structrp png_ptr, png_charp ascii, size_t size,
     double fp, unsigned int precision)
@@ -3220,10 +3188,6 @@ png_ascii_from_fp(png_const_structrp png_ptr, png_charp ascii, size_t size,
    /* Here on buffer too small. */
    png_error(png_ptr, "ASCII conversion buffer too small");
 }
-#if GCC_STRICT_OVERFLOW
-#pragma GCC diagnostic pop
-#endif /* GCC_STRICT_OVERFLOW */
-
 #  endif /* FLOATING_POINT */
 
 #  ifdef PNG_FIXED_POINT_SUPPORTED
@@ -3251,7 +3215,7 @@ png_ascii_from_fixed(png_const_structrp png_ptr, png_charp ascii,
       if (num <= 0x80000000) /* else overflowed */
       {
          unsigned int ndigits = 0, first = 16 /* flag value */;
-         char digits[10];
+         char digits[10] = {0};
 
          while (num)
          {
@@ -3336,15 +3300,6 @@ png_fixed(png_const_structrp png_ptr, double fp, png_const_charp text)
  * the nearest .00001).  Overflow and divide by zero are signalled in
  * the result, a boolean - true on success, false on overflow.
  */
-#if GCC_STRICT_OVERFLOW /* from above */
-/* It is not obvious which comparison below gets optimized in such a way that
- * signed overflow would change the result; looking through the code does not
- * reveal any tests which have the form GCC complains about, so presumably the
- * optimizer is moving an add or subtract into the 'if' somewhere.
- */
-#pragma GCC diagnostic push
-#pragma GCC diagnostic warning "-Wstrict-overflow=2"
-#endif /* GCC_STRICT_OVERFLOW */
 int
 png_muldiv(png_fixed_point_p res, png_fixed_point a, png_int_32 times,
     png_int_32 divisor)
@@ -3459,9 +3414,6 @@ png_muldiv(png_fixed_point_p res, png_fixed_point a, png_int_32 times,
 
    return 0;
 }
-#if GCC_STRICT_OVERFLOW
-#pragma GCC diagnostic pop
-#endif /* GCC_STRICT_OVERFLOW */
 #endif /* READ_GAMMA || INCH_CONVERSIONS */
 
 #if defined(PNG_READ_GAMMA_SUPPORTED) || defined(PNG_INCH_CONVERSIONS_SUPPORTED)
diff --git a/vendor/libpng/png.h b/vendor/libpng/png.h
index cfc4841099..83d3903126 100644
--- a/vendor/libpng/png.h
+++ b/vendor/libpng/png.h
@@ -1,9 +1,9 @@
 
 /* png.h - header file for PNG reference library
  *
- * libpng version 1.6.40
+ * libpng version 1.6.43
  *
- * Copyright (c) 2018-2023 Cosmin Truta
+ * Copyright (c) 2018-2024 Cosmin Truta
  * Copyright (c) 1998-2002,2004,2006-2018 Glenn Randers-Pehrson
  * Copyright (c) 1996-1997 Andreas Dilger
  * Copyright (c) 1995-1996 Guy Eric Schalnat, Group 42, Inc.
@@ -15,7 +15,7 @@
  *   libpng versions 0.89, June 1996, through 0.96, May 1997: Andreas Dilger
  *   libpng versions 0.97, January 1998, through 1.6.35, July 2018:
  *     Glenn Randers-Pehrson
- *   libpng versions 1.6.36, December 2018, through 1.6.40, June 2023:
+ *   libpng versions 1.6.36, December 2018, through 1.6.43, February 2024:
  *     Cosmin Truta
  *   See also "Contributing Authors", below.
  */
@@ -27,8 +27,8 @@
  * PNG Reference Library License version 2
  * ---------------------------------------
  *
- *  * Copyright (c) 1995-2023 The PNG Reference Library Authors.
- *  * Copyright (c) 2018-2023 Cosmin Truta.
+ *  * Copyright (c) 1995-2024 The PNG Reference Library Authors.
+ *  * Copyright (c) 2018-2024 Cosmin Truta.
  *  * Copyright (c) 2000-2002, 2004, 2006-2018 Glenn Randers-Pehrson.
  *  * Copyright (c) 1996-1997 Andreas Dilger.
  *  * Copyright (c) 1995-1996 Guy Eric Schalnat, Group 42, Inc.
@@ -239,7 +239,7 @@
  *    ...
  *    1.5.30                  15    10530  15.so.15.30[.0]
  *    ...
- *    1.6.40                  16    10640  16.so.16.40[.0]
+ *    1.6.43                  16    10643  16.so.16.43[.0]
  *
  *    Henceforth the source version will match the shared-library major and
  *    minor numbers; the shared-library major version number will be used for
@@ -255,9 +255,6 @@
  *    to the info_ptr or png_ptr members through png.h, and the compiled
  *    application is loaded with a different version of the library.
  *
- *    DLLNUM will change each time there are forward or backward changes
- *    in binary compatibility (e.g., when a new feature is added).
- *
  * See libpng.txt or libpng.3 for more information.  The PNG specification
  * is available as a W3C Recommendation and as an ISO/IEC Standard; see
  * 
@@ -278,19 +275,21 @@
  */
 
 /* Version information for png.h - this should match the version in png.c */
-#define PNG_LIBPNG_VER_STRING "1.6.40"
-#define PNG_HEADER_VERSION_STRING " libpng version 1.6.40 - June 21, 2023\n"
+#define PNG_LIBPNG_VER_STRING "1.6.43"
+#define PNG_HEADER_VERSION_STRING " libpng version " PNG_LIBPNG_VER_STRING "\n"
 
-#define PNG_LIBPNG_VER_SONUM   16
-#define PNG_LIBPNG_VER_DLLNUM  16
+/* The versions of shared library builds should stay in sync, going forward */
+#define PNG_LIBPNG_VER_SHAREDLIB 16
+#define PNG_LIBPNG_VER_SONUM     PNG_LIBPNG_VER_SHAREDLIB /* [Deprecated] */
+#define PNG_LIBPNG_VER_DLLNUM    PNG_LIBPNG_VER_SHAREDLIB /* [Deprecated] */
 
 /* These should match the first 3 components of PNG_LIBPNG_VER_STRING: */
 #define PNG_LIBPNG_VER_MAJOR   1
 #define PNG_LIBPNG_VER_MINOR   6
-#define PNG_LIBPNG_VER_RELEASE 40
+#define PNG_LIBPNG_VER_RELEASE 43
 
 /* This should be zero for a public release, or non-zero for a
- * development version.  [Deprecated]
+ * development version.
  */
 #define PNG_LIBPNG_VER_BUILD  0
 
@@ -318,7 +317,7 @@
  * From version 1.0.1 it is:
  * XXYYZZ, where XX=major, YY=minor, ZZ=release
  */
-#define PNG_LIBPNG_VER 10640 /* 1.6.40 */
+#define PNG_LIBPNG_VER 10643 /* 1.6.43 */
 
 /* Library configuration: these options cannot be changed after
  * the library has been built.
@@ -428,7 +427,7 @@ extern "C" {
 /* This triggers a compiler error in png.c, if png.c and png.h
  * do not agree upon the version number.
  */
-typedef char* png_libpng_version_1_6_40;
+typedef char* png_libpng_version_1_6_43;
 
 /* Basic control structions.  Read libpng-manual.txt or libpng.3 for more info.
  *
@@ -849,7 +848,7 @@ PNG_FUNCTION(void, (PNGCAPI *png_longjmp_ptr), PNGARG((jmp_buf, int)), typedef);
 #define PNG_TRANSFORM_GRAY_TO_RGB   0x2000      /* read only */
 /* Added to libpng-1.5.4 */
 #define PNG_TRANSFORM_EXPAND_16     0x4000      /* read only */
-#if INT_MAX >= 0x8000 /* else this might break */
+#if ~0U > 0xffffU /* or else this might break on a 16-bit machine */
 #define PNG_TRANSFORM_SCALE_16      0x8000      /* read only */
 #endif
 
@@ -908,15 +907,15 @@ PNG_EXPORT(2, void, png_set_sig_bytes, (png_structrp png_ptr, int num_bytes));
 /* Check sig[start] through sig[start + num_to_check - 1] to see if it's a
  * PNG file.  Returns zero if the supplied bytes match the 8-byte PNG
  * signature, and non-zero otherwise.  Having num_to_check == 0 or
- * start > 7 will always fail (ie return non-zero).
+ * start > 7 will always fail (i.e. return non-zero).
  */
 PNG_EXPORT(3, int, png_sig_cmp, (png_const_bytep sig, size_t start,
     size_t num_to_check));
 
 /* Simple signature checking function.  This is the same as calling
- * png_check_sig(sig, n) := !png_sig_cmp(sig, 0, n).
+ * png_check_sig(sig, n) := (png_sig_cmp(sig, 0, n) == 0).
  */
-#define png_check_sig(sig, n) !png_sig_cmp((sig), 0, (n))
+#define png_check_sig(sig, n) (png_sig_cmp((sig), 0, (n)) == 0) /* DEPRECATED */
 
 /* Allocate and initialize png_ptr struct for reading, and any other memory. */
 PNG_EXPORTA(4, png_structp, png_create_read_struct,
@@ -1730,12 +1729,9 @@ PNG_EXPORT(97, void, png_free, (png_const_structrp png_ptr, png_voidp ptr));
 PNG_EXPORT(98, void, png_free_data, (png_const_structrp png_ptr,
     png_inforp info_ptr, png_uint_32 free_me, int num));
 
-/* Reassign responsibility for freeing existing data, whether allocated
+/* Reassign the responsibility for freeing existing data, whether allocated
  * by libpng or by the application; this works on the png_info structure passed
- * in, it does not change the state for other png_info structures.
- *
- * It is unlikely that this function works correctly as of 1.6.0 and using it
- * may result either in memory leaks or double free of allocated data.
+ * in, without changing the state for other png_info structures.
  */
 PNG_EXPORT(99, void, png_data_freer, (png_const_structrp png_ptr,
     png_inforp info_ptr, int freer, png_uint_32 mask));
@@ -3207,11 +3203,18 @@ PNG_EXPORT(245, int, png_image_write_to_memory, (png_imagep image, void *memory,
 #ifdef PNG_MIPS_MSA_API_SUPPORTED
 #  define PNG_MIPS_MSA   6 /* HARDWARE: MIPS Msa SIMD instructions supported */
 #endif
-#define PNG_IGNORE_ADLER32 8
+#ifdef PNG_DISABLE_ADLER32_CHECK_SUPPORTED
+#  define PNG_IGNORE_ADLER32 8 /* SOFTWARE: disable Adler32 check on IDAT */
+#endif
 #ifdef PNG_POWERPC_VSX_API_SUPPORTED
-#  define PNG_POWERPC_VSX   10 /* HARDWARE: PowerPC VSX SIMD instructions supported */
+#  define PNG_POWERPC_VSX   10 /* HARDWARE: PowerPC VSX SIMD instructions
+                                * supported */
 #endif
-#define PNG_OPTION_NEXT  12 /* Next option - numbers must be even */
+#ifdef PNG_MIPS_MMI_API_SUPPORTED
+#  define PNG_MIPS_MMI   12 /* HARDWARE: MIPS MMI SIMD instructions supported */
+#endif
+
+#define PNG_OPTION_NEXT  14 /* Next option - numbers must be even */
 
 /* Return values: NOTE: there are four values and 'off' is *not* zero */
 #define PNG_OPTION_UNSET   0 /* Unset - defaults to off */
diff --git a/vendor/libpng/pngconf.h b/vendor/libpng/pngconf.h
index 6671e3c335..000d7b1a8a 100644
--- a/vendor/libpng/pngconf.h
+++ b/vendor/libpng/pngconf.h
@@ -1,9 +1,9 @@
 
 /* pngconf.h - machine-configurable file for libpng
  *
- * libpng version 1.6.40
+ * libpng version 1.6.43
  *
- * Copyright (c) 2018-2022 Cosmin Truta
+ * Copyright (c) 2018-2024 Cosmin Truta
  * Copyright (c) 1998-2002,2004,2006-2016,2018 Glenn Randers-Pehrson
  * Copyright (c) 1996-1997 Andreas Dilger
  * Copyright (c) 1995-1996 Guy Eric Schalnat, Group 42, Inc.
diff --git a/vendor/libpng/pngerror.c b/vendor/libpng/pngerror.c
index ec3a709b9d..29ebda7943 100644
--- a/vendor/libpng/pngerror.c
+++ b/vendor/libpng/pngerror.c
@@ -1,7 +1,7 @@
 
 /* pngerror.c - stub functions for i/o and memory allocation
  *
- * Copyright (c) 2018 Cosmin Truta
+ * Copyright (c) 2018-2024 Cosmin Truta
  * Copyright (c) 1998-2002,2004,2006-2017 Glenn Randers-Pehrson
  * Copyright (c) 1996-1997 Andreas Dilger
  * Copyright (c) 1995-1996 Guy Eric Schalnat, Group 42, Inc.
@@ -255,7 +255,7 @@ void
 png_warning_parameter_unsigned(png_warning_parameters p, int number, int format,
     png_alloc_size_t value)
 {
-   char buffer[PNG_NUMBER_BUFFER_SIZE];
+   char buffer[PNG_NUMBER_BUFFER_SIZE] = {0};
    png_warning_parameter(p, number, PNG_FORMAT_NUMBER(buffer, format, value));
 }
 
@@ -265,7 +265,7 @@ png_warning_parameter_signed(png_warning_parameters p, int number, int format,
 {
    png_alloc_size_t u;
    png_charp str;
-   char buffer[PNG_NUMBER_BUFFER_SIZE];
+   char buffer[PNG_NUMBER_BUFFER_SIZE] = {0};
 
    /* Avoid overflow by doing the negate in a png_alloc_size_t: */
    u = (png_alloc_size_t)value;
@@ -858,7 +858,7 @@ png_get_error_ptr(png_const_structrp png_ptr)
    if (png_ptr == NULL)
       return NULL;
 
-   return ((png_voidp)png_ptr->error_ptr);
+   return (png_voidp)png_ptr->error_ptr;
 }
 
 
@@ -933,31 +933,25 @@ png_safe_warning(png_structp png_nonconst_ptr, png_const_charp warning_message)
 #endif
 
 int /* PRIVATE */
-png_safe_execute(png_imagep image_in, int (*function)(png_voidp), png_voidp arg)
+png_safe_execute(png_imagep image, int (*function)(png_voidp), png_voidp arg)
 {
-   volatile png_imagep image = image_in;
-   volatile int result;
-   volatile png_voidp saved_error_buf;
+   png_voidp saved_error_buf = image->opaque->error_buf;
    jmp_buf safe_jmpbuf;
+   int result;
 
-   /* Safely execute function(arg) with png_error returning to this function. */
-   saved_error_buf = image->opaque->error_buf;
-   result = setjmp(safe_jmpbuf) == 0;
-
-   if (result != 0)
+   /* Safely execute function(arg), with png_error returning back here. */
+   if (setjmp(safe_jmpbuf) == 0)
    {
-
       image->opaque->error_buf = safe_jmpbuf;
       result = function(arg);
+      image->opaque->error_buf = saved_error_buf;
+      return result;
    }
 
+   /* On png_error, return via longjmp, pop the jmpbuf, and free the image. */
    image->opaque->error_buf = saved_error_buf;
-
-   /* And do the cleanup prior to any failure return. */
-   if (result == 0)
-      png_image_free(image);
-
-   return result;
+   png_image_free(image);
+   return 0;
 }
 #endif /* SIMPLIFIED READ || SIMPLIFIED_WRITE */
 #endif /* READ || WRITE */
diff --git a/vendor/libpng/pngget.c b/vendor/libpng/pngget.c
index 1490a032e1..1084b268ff 100644
--- a/vendor/libpng/pngget.c
+++ b/vendor/libpng/pngget.c
@@ -1,7 +1,7 @@
 
 /* pngget.c - retrieval of values from info struct
  *
- * Copyright (c) 2018-2023 Cosmin Truta
+ * Copyright (c) 2018-2024 Cosmin Truta
  * Copyright (c) 1998-2002,2004,2006-2018 Glenn Randers-Pehrson
  * Copyright (c) 1996-1997 Andreas Dilger
  * Copyright (c) 1995-1996 Guy Eric Schalnat, Group 42, Inc.
@@ -28,22 +28,22 @@ png_get_valid(png_const_structrp png_ptr, png_const_inforp info_ptr,
        * valid tRNS chunk in this case.
        */
       if (flag == PNG_INFO_tRNS && png_ptr->num_trans == 0)
-         return(0);
+         return 0;
 #endif
 
-      return(info_ptr->valid & flag);
+      return info_ptr->valid & flag;
    }
 
-   return(0);
+   return 0;
 }
 
 size_t PNGAPI
 png_get_rowbytes(png_const_structrp png_ptr, png_const_inforp info_ptr)
 {
    if (png_ptr != NULL && info_ptr != NULL)
-      return(info_ptr->rowbytes);
+      return info_ptr->rowbytes;
 
-   return(0);
+   return 0;
 }
 
 #ifdef PNG_INFO_IMAGE_SUPPORTED
@@ -51,9 +51,9 @@ png_bytepp PNGAPI
 png_get_rows(png_const_structrp png_ptr, png_const_inforp info_ptr)
 {
    if (png_ptr != NULL && info_ptr != NULL)
-      return(info_ptr->row_pointers);
+      return info_ptr->row_pointers;
 
-   return(0);
+   return 0;
 }
 #endif
 
@@ -65,7 +65,7 @@ png_get_image_width(png_const_structrp png_ptr, png_const_inforp info_ptr)
    if (png_ptr != NULL && info_ptr != NULL)
       return info_ptr->width;
 
-   return (0);
+   return 0;
 }
 
 png_uint_32 PNGAPI
@@ -74,7 +74,7 @@ png_get_image_height(png_const_structrp png_ptr, png_const_inforp info_ptr)
    if (png_ptr != NULL && info_ptr != NULL)
       return info_ptr->height;
 
-   return (0);
+   return 0;
 }
 
 png_byte PNGAPI
@@ -83,7 +83,7 @@ png_get_bit_depth(png_const_structrp png_ptr, png_const_inforp info_ptr)
    if (png_ptr != NULL && info_ptr != NULL)
       return info_ptr->bit_depth;
 
-   return (0);
+   return 0;
 }
 
 png_byte PNGAPI
@@ -92,7 +92,7 @@ png_get_color_type(png_const_structrp png_ptr, png_const_inforp info_ptr)
    if (png_ptr != NULL && info_ptr != NULL)
       return info_ptr->color_type;
 
-   return (0);
+   return 0;
 }
 
 png_byte PNGAPI
@@ -101,7 +101,7 @@ png_get_filter_type(png_const_structrp png_ptr, png_const_inforp info_ptr)
    if (png_ptr != NULL && info_ptr != NULL)
       return info_ptr->filter_type;
 
-   return (0);
+   return 0;
 }
 
 png_byte PNGAPI
@@ -110,7 +110,7 @@ png_get_interlace_type(png_const_structrp png_ptr, png_const_inforp info_ptr)
    if (png_ptr != NULL && info_ptr != NULL)
       return info_ptr->interlace_type;
 
-   return (0);
+   return 0;
 }
 
 png_byte PNGAPI
@@ -119,7 +119,7 @@ png_get_compression_type(png_const_structrp png_ptr, png_const_inforp info_ptr)
    if (png_ptr != NULL && info_ptr != NULL)
       return info_ptr->compression_type;
 
-   return (0);
+   return 0;
 }
 
 png_uint_32 PNGAPI
@@ -127,21 +127,20 @@ png_get_x_pixels_per_meter(png_const_structrp png_ptr, png_const_inforp
    info_ptr)
 {
 #ifdef PNG_pHYs_SUPPORTED
+   png_debug(1, "in png_get_x_pixels_per_meter");
+
    if (png_ptr != NULL && info_ptr != NULL &&
        (info_ptr->valid & PNG_INFO_pHYs) != 0)
-      {
-         png_debug1(1, "in %s retrieval function",
-             "png_get_x_pixels_per_meter");
-
-         if (info_ptr->phys_unit_type == PNG_RESOLUTION_METER)
-            return (info_ptr->x_pixels_per_unit);
-      }
+   {
+      if (info_ptr->phys_unit_type == PNG_RESOLUTION_METER)
+         return info_ptr->x_pixels_per_unit;
+   }
 #else
    PNG_UNUSED(png_ptr)
    PNG_UNUSED(info_ptr)
 #endif
 
-   return (0);
+   return 0;
 }
 
 png_uint_32 PNGAPI
@@ -149,42 +148,41 @@ png_get_y_pixels_per_meter(png_const_structrp png_ptr, png_const_inforp
     info_ptr)
 {
 #ifdef PNG_pHYs_SUPPORTED
+   png_debug(1, "in png_get_y_pixels_per_meter");
+
    if (png_ptr != NULL && info_ptr != NULL &&
        (info_ptr->valid & PNG_INFO_pHYs) != 0)
    {
-      png_debug1(1, "in %s retrieval function",
-          "png_get_y_pixels_per_meter");
-
       if (info_ptr->phys_unit_type == PNG_RESOLUTION_METER)
-         return (info_ptr->y_pixels_per_unit);
+         return info_ptr->y_pixels_per_unit;
    }
 #else
    PNG_UNUSED(png_ptr)
    PNG_UNUSED(info_ptr)
 #endif
 
-   return (0);
+   return 0;
 }
 
 png_uint_32 PNGAPI
 png_get_pixels_per_meter(png_const_structrp png_ptr, png_const_inforp info_ptr)
 {
 #ifdef PNG_pHYs_SUPPORTED
+   png_debug(1, "in png_get_pixels_per_meter");
+
    if (png_ptr != NULL && info_ptr != NULL &&
        (info_ptr->valid & PNG_INFO_pHYs) != 0)
    {
-      png_debug1(1, "in %s retrieval function", "png_get_pixels_per_meter");
-
       if (info_ptr->phys_unit_type == PNG_RESOLUTION_METER &&
           info_ptr->x_pixels_per_unit == info_ptr->y_pixels_per_unit)
-         return (info_ptr->x_pixels_per_unit);
+         return info_ptr->x_pixels_per_unit;
    }
 #else
    PNG_UNUSED(png_ptr)
    PNG_UNUSED(info_ptr)
 #endif
 
-   return (0);
+   return 0;
 }
 
 #ifdef PNG_FLOATING_POINT_SUPPORTED
@@ -193,21 +191,21 @@ png_get_pixel_aspect_ratio(png_const_structrp png_ptr, png_const_inforp
    info_ptr)
 {
 #ifdef PNG_READ_pHYs_SUPPORTED
+   png_debug(1, "in png_get_pixel_aspect_ratio");
+
    if (png_ptr != NULL && info_ptr != NULL &&
        (info_ptr->valid & PNG_INFO_pHYs) != 0)
    {
-      png_debug1(1, "in %s retrieval function", "png_get_aspect_ratio");
-
       if (info_ptr->x_pixels_per_unit != 0)
-         return ((float)((float)info_ptr->y_pixels_per_unit
-             /(float)info_ptr->x_pixels_per_unit));
+         return (float)info_ptr->y_pixels_per_unit
+              / (float)info_ptr->x_pixels_per_unit;
    }
 #else
    PNG_UNUSED(png_ptr)
    PNG_UNUSED(info_ptr)
 #endif
 
-   return ((float)0.0);
+   return (float)0.0;
 }
 #endif
 
@@ -217,6 +215,8 @@ png_get_pixel_aspect_ratio_fixed(png_const_structrp png_ptr,
     png_const_inforp info_ptr)
 {
 #ifdef PNG_READ_pHYs_SUPPORTED
+   png_debug(1, "in png_get_pixel_aspect_ratio_fixed");
+
    if (png_ptr != NULL && info_ptr != NULL &&
        (info_ptr->valid & PNG_INFO_pHYs) != 0 &&
        info_ptr->x_pixels_per_unit > 0 && info_ptr->y_pixels_per_unit > 0 &&
@@ -225,8 +225,6 @@ png_get_pixel_aspect_ratio_fixed(png_const_structrp png_ptr,
    {
       png_fixed_point res;
 
-      png_debug1(1, "in %s retrieval function", "png_get_aspect_ratio_fixed");
-
       /* The following casts work because a PNG 4 byte integer only has a valid
        * range of 0..2^31-1; otherwise the cast might overflow.
        */
@@ -247,80 +245,80 @@ png_int_32 PNGAPI
 png_get_x_offset_microns(png_const_structrp png_ptr, png_const_inforp info_ptr)
 {
 #ifdef PNG_oFFs_SUPPORTED
+   png_debug(1, "in png_get_x_offset_microns");
+
    if (png_ptr != NULL && info_ptr != NULL &&
        (info_ptr->valid & PNG_INFO_oFFs) != 0)
    {
-      png_debug1(1, "in %s retrieval function", "png_get_x_offset_microns");
-
       if (info_ptr->offset_unit_type == PNG_OFFSET_MICROMETER)
-         return (info_ptr->x_offset);
+         return info_ptr->x_offset;
    }
 #else
    PNG_UNUSED(png_ptr)
    PNG_UNUSED(info_ptr)
 #endif
 
-   return (0);
+   return 0;
 }
 
 png_int_32 PNGAPI
 png_get_y_offset_microns(png_const_structrp png_ptr, png_const_inforp info_ptr)
 {
 #ifdef PNG_oFFs_SUPPORTED
+   png_debug(1, "in png_get_y_offset_microns");
+
    if (png_ptr != NULL && info_ptr != NULL &&
        (info_ptr->valid & PNG_INFO_oFFs) != 0)
    {
-      png_debug1(1, "in %s retrieval function", "png_get_y_offset_microns");
-
       if (info_ptr->offset_unit_type == PNG_OFFSET_MICROMETER)
-         return (info_ptr->y_offset);
+         return info_ptr->y_offset;
    }
 #else
    PNG_UNUSED(png_ptr)
    PNG_UNUSED(info_ptr)
 #endif
 
-   return (0);
+   return 0;
 }
 
 png_int_32 PNGAPI
 png_get_x_offset_pixels(png_const_structrp png_ptr, png_const_inforp info_ptr)
 {
 #ifdef PNG_oFFs_SUPPORTED
+   png_debug(1, "in png_get_x_offset_pixels");
+
    if (png_ptr != NULL && info_ptr != NULL &&
        (info_ptr->valid & PNG_INFO_oFFs) != 0)
    {
-      png_debug1(1, "in %s retrieval function", "png_get_x_offset_pixels");
-
       if (info_ptr->offset_unit_type == PNG_OFFSET_PIXEL)
-         return (info_ptr->x_offset);
+         return info_ptr->x_offset;
    }
 #else
    PNG_UNUSED(png_ptr)
    PNG_UNUSED(info_ptr)
 #endif
 
-   return (0);
+   return 0;
 }
 
 png_int_32 PNGAPI
 png_get_y_offset_pixels(png_const_structrp png_ptr, png_const_inforp info_ptr)
 {
 #ifdef PNG_oFFs_SUPPORTED
+   png_debug(1, "in png_get_y_offset_pixels");
+
    if (png_ptr != NULL && info_ptr != NULL &&
        (info_ptr->valid & PNG_INFO_oFFs) != 0)
    {
-      png_debug1(1, "in %s retrieval function", "png_get_y_offset_pixels");
-
       if (info_ptr->offset_unit_type == PNG_OFFSET_PIXEL)
-         return (info_ptr->y_offset);
+         return info_ptr->y_offset;
    }
 #else
    PNG_UNUSED(png_ptr)
    PNG_UNUSED(info_ptr)
 #endif
 
-   return (0);
+   return 0;
 }
 
 #ifdef PNG_INCH_CONVERSIONS_SUPPORTED
@@ -434,11 +432,11 @@ png_get_pHYs_dpi(png_const_structrp png_ptr, png_const_inforp info_ptr,
 {
    png_uint_32 retval = 0;
 
+   png_debug1(1, "in %s retrieval function", "pHYs");
+
    if (png_ptr != NULL && info_ptr != NULL &&
        (info_ptr->valid & PNG_INFO_pHYs) != 0)
    {
-      png_debug1(1, "in %s retrieval function", "pHYs");
-
       if (res_x != NULL)
       {
          *res_x = info_ptr->x_pixels_per_unit;
@@ -464,7 +462,7 @@ png_get_pHYs_dpi(png_const_structrp png_ptr, png_const_inforp info_ptr,
       }
    }
 
-   return (retval);
+   return retval;
 }
 #endif /* pHYs */
 #endif /* INCH_CONVERSIONS */
@@ -478,9 +476,9 @@ png_byte PNGAPI
 png_get_channels(png_const_structrp png_ptr, png_const_inforp info_ptr)
 {
    if (png_ptr != NULL && info_ptr != NULL)
-      return(info_ptr->channels);
+      return info_ptr->channels;
 
-   return (0);
+   return 0;
 }
 
 #ifdef PNG_READ_SUPPORTED
@@ -488,9 +486,9 @@ png_const_bytep PNGAPI
 png_get_signature(png_const_structrp png_ptr, png_const_inforp info_ptr)
 {
    if (png_ptr != NULL && info_ptr != NULL)
-      return(info_ptr->signature);
+      return info_ptr->signature;
 
-   return (NULL);
+   return NULL;
 }
 #endif
 
@@ -499,17 +497,17 @@ png_uint_32 PNGAPI
 png_get_bKGD(png_const_structrp png_ptr, png_inforp info_ptr,
     png_color_16p *background)
 {
+   png_debug1(1, "in %s retrieval function", "bKGD");
+
    if (png_ptr != NULL && info_ptr != NULL &&
        (info_ptr->valid & PNG_INFO_bKGD) != 0 &&
        background != NULL)
    {
-      png_debug1(1, "in %s retrieval function", "bKGD");
-
       *background = &(info_ptr->background);
-      return (PNG_INFO_bKGD);
+      return PNG_INFO_bKGD;
    }
 
-   return (0);
+   return 0;
 }
 #endif
 
@@ -524,6 +522,8 @@ png_get_cHRM(png_const_structrp png_ptr, png_const_inforp info_ptr,
     double *white_x, double *white_y, double *red_x, double *red_y,
     double *green_x, double *green_y, double *blue_x, double *blue_y)
 {
+   png_debug1(1, "in %s retrieval function", "cHRM");
+
    /* Quiet API change: this code used to only return the end points if a cHRM
     * chunk was present, but the end points can also come from iCCP or sRGB
     * chunks, so in 1.6.0 the png_get_ APIs return the end points regardless and
@@ -533,8 +533,6 @@ png_get_cHRM(png_const_structrp png_ptr, png_const_inforp info_ptr,
    if (png_ptr != NULL && info_ptr != NULL &&
       (info_ptr->colorspace.flags & PNG_COLORSPACE_HAVE_ENDPOINTS) != 0)
    {
-      png_debug1(1, "in %s retrieval function", "cHRM");
-
       if (white_x != NULL)
          *white_x = png_float(png_ptr,
              info_ptr->colorspace.end_points_xy.whitex, "cHRM white X");
@@ -559,10 +557,10 @@ png_get_cHRM(png_const_structrp png_ptr, png_const_inforp info_ptr,
       if (blue_y != NULL)
          *blue_y = png_float(png_ptr, info_ptr->colorspace.end_points_xy.bluey,
              "cHRM blue Y");
-      return (PNG_INFO_cHRM);
+      return PNG_INFO_cHRM;
    }
 
-   return (0);
+   return 0;
 }
 
 png_uint_32 PNGAPI
@@ -571,11 +569,11 @@ png_get_cHRM_XYZ(png_const_structrp png_ptr, png_const_inforp info_ptr,
     double *green_Y, double *green_Z, double *blue_X, double *blue_Y,
     double *blue_Z)
 {
+   png_debug1(1, "in %s retrieval function", "cHRM_XYZ(float)");
+
    if (png_ptr != NULL && info_ptr != NULL &&
        (info_ptr->colorspace.flags & PNG_COLORSPACE_HAVE_ENDPOINTS) != 0)
    {
-      png_debug1(1, "in %s retrieval function", "cHRM_XYZ(float)");
-
       if (red_X != NULL)
          *red_X = png_float(png_ptr, info_ptr->colorspace.end_points_XYZ.red_X,
              "cHRM red X");
@@ -603,10 +601,10 @@ png_get_cHRM_XYZ(png_const_structrp png_ptr, png_const_inforp info_ptr,
       if (blue_Z != NULL)
          *blue_Z = png_float(png_ptr,
              info_ptr->colorspace.end_points_XYZ.blue_Z, "cHRM blue Z");
-      return (PNG_INFO_cHRM);
+      return PNG_INFO_cHRM;
    }
 
-   return (0);
+   return 0;
 }
 #  endif
 
@@ -619,11 +617,11 @@ png_get_cHRM_XYZ_fixed(png_const_structrp png_ptr, png_const_inforp info_ptr,
     png_fixed_point *int_blue_X, png_fixed_point *int_blue_Y,
     png_fixed_point *int_blue_Z)
 {
+   png_debug1(1, "in %s retrieval function", "cHRM_XYZ");
+
    if (png_ptr != NULL && info_ptr != NULL &&
       (info_ptr->colorspace.flags & PNG_COLORSPACE_HAVE_ENDPOINTS) != 0)
    {
-      png_debug1(1, "in %s retrieval function", "cHRM_XYZ");
-
       if (int_red_X != NULL)
          *int_red_X = info_ptr->colorspace.end_points_XYZ.red_X;
       if (int_red_Y != NULL)
@@ -642,10 +640,10 @@ png_get_cHRM_XYZ_fixed(png_const_structrp png_ptr, png_const_inforp info_ptr,
          *int_blue_Y = info_ptr->colorspace.end_points_XYZ.blue_Y;
       if (int_blue_Z != NULL)
          *int_blue_Z = info_ptr->colorspace.end_points_XYZ.blue_Z;
-      return (PNG_INFO_cHRM);
+      return PNG_INFO_cHRM;
    }
 
-   return (0);
+   return 0;
 }
 
 png_uint_32 PNGAPI
@@ -675,10 +673,10 @@ png_get_cHRM_fixed(png_const_structrp png_ptr, png_const_inforp info_ptr,
          *blue_x = info_ptr->colorspace.end_points_xy.bluex;
       if (blue_y != NULL)
          *blue_y = info_ptr->colorspace.end_points_xy.bluey;
-      return (PNG_INFO_cHRM);
+      return PNG_INFO_cHRM;
    }
 
-   return (0);
+   return 0;
 }
 #  endif
 #endif
@@ -696,10 +694,10 @@ png_get_gAMA_fixed(png_const_structrp png_ptr, png_const_inforp info_ptr,
        file_gamma != NULL)
    {
       *file_gamma = info_ptr->colorspace.gamma;
-      return (PNG_INFO_gAMA);
+      return PNG_INFO_gAMA;
    }
 
-   return (0);
+   return 0;
 }
 #  endif
 
@@ -716,10 +714,10 @@ png_get_gAMA(png_const_structrp png_ptr, png_const_inforp info_ptr,
    {
       *file_gamma = png_float(png_ptr, info_ptr->colorspace.gamma,
           "png_get_gAMA");
-      return (PNG_INFO_gAMA);
+      return PNG_INFO_gAMA;
    }
 
-   return (0);
+   return 0;
 }
 #  endif
 #endif
@@ -735,10 +733,10 @@ png_get_sRGB(png_const_structrp png_ptr, png_const_inforp info_ptr,
       (info_ptr->valid & PNG_INFO_sRGB) != 0 && file_srgb_intent != NULL)
    {
       *file_srgb_intent = info_ptr->colorspace.rendering_intent;
-      return (PNG_INFO_sRGB);
+      return PNG_INFO_sRGB;
    }
 
-   return (0);
+   return 0;
 }
 #endif
 
@@ -762,10 +760,10 @@ png_get_iCCP(png_const_structrp png_ptr, png_inforp info_ptr,
        */
       if (compression_type != NULL)
          *compression_type = PNG_COMPRESSION_TYPE_BASE;
-      return (PNG_INFO_iCCP);
+      return PNG_INFO_iCCP;
    }
 
-   return (0);
+   return 0;
 
 }
 #endif
@@ -775,13 +773,15 @@ int PNGAPI
 png_get_sPLT(png_const_structrp png_ptr, png_inforp info_ptr,
     png_sPLT_tpp spalettes)
 {
+   png_debug1(1, "in %s retrieval function", "sPLT");
+
    if (png_ptr != NULL && info_ptr != NULL && spalettes != NULL)
    {
       *spalettes = info_ptr->splt_palettes;
       return info_ptr->splt_palettes_num;
    }
 
-   return (0);
+   return 0;
 }
 #endif
 
@@ -807,10 +807,10 @@ png_get_eXIf_1(png_const_structrp png_ptr, png_const_inforp info_ptr,
    {
       *num_exif = info_ptr->num_exif;
       *exif = info_ptr->exif;
-      return (PNG_INFO_eXIf);
+      return PNG_INFO_eXIf;
    }
 
-   return (0);
+   return 0;
 }
 #endif
 
@@ -825,10 +825,10 @@ png_get_hIST(png_const_structrp png_ptr, png_inforp info_ptr,
        (info_ptr->valid & PNG_INFO_hIST) != 0 && hist != NULL)
    {
       *hist = info_ptr->hist;
-      return (PNG_INFO_hIST);
+      return PNG_INFO_hIST;
    }
 
-   return (0);
+   return 0;
 }
 #endif
 
@@ -841,7 +841,7 @@ png_get_IHDR(png_const_structrp png_ptr, png_const_inforp info_ptr,
    png_debug1(1, "in %s retrieval function", "IHDR");
 
    if (png_ptr == NULL || info_ptr == NULL)
-      return (0);
+      return 0;
 
    if (width != NULL)
        *width = info_ptr->width;
@@ -873,7 +873,7 @@ png_get_IHDR(png_const_structrp png_ptr, png_const_inforp info_ptr,
        info_ptr->bit_depth, info_ptr->color_type, info_ptr->interlace_type,
        info_ptr->compression_type, info_ptr->filter_type);
 
-   return (1);
+   return 1;
 }
 
 #ifdef PNG_oFFs_SUPPORTED
@@ -890,10 +890,10 @@ png_get_oFFs(png_const_structrp png_ptr, png_const_inforp info_ptr,
       *offset_x = info_ptr->x_offset;
       *offset_y = info_ptr->y_offset;
       *unit_type = (int)info_ptr->offset_unit_type;
-      return (PNG_INFO_oFFs);
+      return PNG_INFO_oFFs;
    }
 
-   return (0);
+   return 0;
 }
 #endif
 
@@ -917,10 +917,10 @@ png_get_pCAL(png_const_structrp png_ptr, png_inforp info_ptr,
       *nparams = (int)info_ptr->pcal_nparams;
       *units = info_ptr->pcal_units;
       *params = info_ptr->pcal_params;
-      return (PNG_INFO_pCAL);
+      return PNG_INFO_pCAL;
    }
 
-   return (0);
+   return 0;
 }
 #endif
 
@@ -932,6 +932,8 @@ png_uint_32 PNGAPI
 png_get_sCAL_fixed(png_const_structrp png_ptr, png_const_inforp info_ptr,
     int *unit, png_fixed_point *width, png_fixed_point *height)
 {
+   png_debug1(1, "in %s retrieval function", "sCAL");
+
    if (png_ptr != NULL && info_ptr != NULL &&
        (info_ptr->valid & PNG_INFO_sCAL) != 0)
    {
@@ -943,10 +945,10 @@ png_get_sCAL_fixed(png_const_structrp png_ptr, png_const_inforp info_ptr,
       *width = png_fixed(png_ptr, atof(info_ptr->scal_s_width), "sCAL width");
       *height = png_fixed(png_ptr, atof(info_ptr->scal_s_height),
           "sCAL height");
-      return (PNG_INFO_sCAL);
+      return PNG_INFO_sCAL;
    }
 
-   return(0);
+   return 0;
 }
 #    endif /* FLOATING_ARITHMETIC */
 #  endif /* FIXED_POINT */
@@ -955,32 +957,36 @@ png_uint_32 PNGAPI
 png_get_sCAL(png_const_structrp png_ptr, png_const_inforp info_ptr,
     int *unit, double *width, double *height)
 {
+   png_debug1(1, "in %s retrieval function", "sCAL(float)");
+
    if (png_ptr != NULL && info_ptr != NULL &&
        (info_ptr->valid & PNG_INFO_sCAL) != 0)
    {
       *unit = info_ptr->scal_unit;
       *width = atof(info_ptr->scal_s_width);
       *height = atof(info_ptr->scal_s_height);
-      return (PNG_INFO_sCAL);
+      return PNG_INFO_sCAL;
    }
 
-   return(0);
+   return 0;
 }
 #  endif /* FLOATING POINT */
 png_uint_32 PNGAPI
 png_get_sCAL_s(png_const_structrp png_ptr, png_const_inforp info_ptr,
     int *unit, png_charpp width, png_charpp height)
 {
+   png_debug1(1, "in %s retrieval function", "sCAL(str)");
+
    if (png_ptr != NULL && info_ptr != NULL &&
        (info_ptr->valid & PNG_INFO_sCAL) != 0)
    {
       *unit = info_ptr->scal_unit;
       *width = info_ptr->scal_s_width;
       *height = info_ptr->scal_s_height;
-      return (PNG_INFO_sCAL);
+      return PNG_INFO_sCAL;
    }
 
-   return(0);
+   return 0;
 }
 #endif /* sCAL */
 
@@ -1015,7 +1021,7 @@ png_get_pHYs(png_const_structrp png_ptr, png_const_inforp info_ptr,
       }
    }
 
-   return (retval);
+   return retval;
 }
 #endif /* pHYs */
 
@@ -1031,10 +1037,10 @@ png_get_PLTE(png_const_structrp png_ptr, png_inforp info_ptr,
       *palette = info_ptr->palette;
       *num_palette = info_ptr->num_palette;
       png_debug1(3, "num_palette = %d", *num_palette);
-      return (PNG_INFO_PLTE);
+      return PNG_INFO_PLTE;
    }
 
-   return (0);
+   return 0;
 }
 
 #ifdef PNG_sBIT_SUPPORTED
@@ -1048,10 +1054,10 @@ png_get_sBIT(png_const_structrp png_ptr, png_inforp info_ptr,
        (info_ptr->valid & PNG_INFO_sBIT) != 0 && sig_bit != NULL)
    {
       *sig_bit = &(info_ptr->sig_bit);
-      return (PNG_INFO_sBIT);
+      return PNG_INFO_sBIT;
    }
 
-   return (0);
+   return 0;
 }
 #endif
 
@@ -1062,7 +1068,7 @@ png_get_text(png_const_structrp png_ptr, png_inforp info_ptr,
 {
    if (png_ptr != NULL && info_ptr != NULL && info_ptr->num_text > 0)
    {
-      png_debug1(1, "in 0x%lx retrieval function",
+      png_debug1(1, "in text retrieval function, chunk typeid = 0x%lx",
          (unsigned long)png_ptr->chunk_name);
 
       if (text_ptr != NULL)
@@ -1077,7 +1083,7 @@ png_get_text(png_const_structrp png_ptr, png_inforp info_ptr,
    if (num_text != NULL)
       *num_text = 0;
 
-   return(0);
+   return 0;
 }
 #endif
 
@@ -1092,10 +1098,10 @@ png_get_tIME(png_const_structrp png_ptr, png_inforp info_ptr,
        (info_ptr->valid & PNG_INFO_tIME) != 0 && mod_time != NULL)
    {
       *mod_time = &(info_ptr->mod_time);
-      return (PNG_INFO_tIME);
+      return PNG_INFO_tIME;
    }
 
-   return (0);
+   return 0;
 }
 #endif
 
@@ -1105,11 +1111,12 @@ png_get_tRNS(png_const_structrp png_ptr, png_inforp info_ptr,
     png_bytep *trans_alpha, int *num_trans, png_color_16p *trans_color)
 {
    png_uint_32 retval = 0;
+
+   png_debug1(1, "in %s retrieval function", "tRNS");
+
    if (png_ptr != NULL && info_ptr != NULL &&
        (info_ptr->valid & PNG_INFO_tRNS) != 0)
    {
-      png_debug1(1, "in %s retrieval function", "tRNS");
-
       if (info_ptr->color_type == PNG_COLOR_TYPE_PALETTE)
       {
          if (trans_alpha != NULL)
@@ -1141,7 +1148,7 @@ png_get_tRNS(png_const_structrp png_ptr, png_inforp info_ptr,
       }
    }
 
-   return (retval);
+   return retval;
 }
 #endif
 
@@ -1156,7 +1163,7 @@ png_get_unknown_chunks(png_const_structrp png_ptr, png_inforp info_ptr,
       return info_ptr->unknown_chunks_num;
    }
 
-   return (0);
+   return 0;
 }
 #endif
 
@@ -1252,7 +1259,7 @@ png_get_palette_max(png_const_structp png_ptr, png_const_infop info_ptr)
    if (png_ptr != NULL && info_ptr != NULL)
       return png_ptr->num_palette_max;
 
-   return (-1);
+   return -1;
 }
 #  endif
 #endif
diff --git a/vendor/libpng/pnglibconf.h b/vendor/libpng/pnglibconf.h
index c58b0c4425..f56126af07 100644
--- a/vendor/libpng/pnglibconf.h
+++ b/vendor/libpng/pnglibconf.h
@@ -209,7 +209,7 @@
 #define PNG_USER_HEIGHT_MAX 1000000
 #define PNG_USER_WIDTH_MAX 1000000
 #define PNG_ZBUF_SIZE 8192
-#define PNG_ZLIB_VERNUM 0x1300 /* this was manually set by MTA (should be same as our zlib vendor version) */
+#define PNG_ZLIB_VERNUM 0x1311 /* this was manually set by MTA (should be same as our zlib vendor version) */
 #define PNG_Z_DEFAULT_COMPRESSION (-1)
 #define PNG_Z_DEFAULT_NOFILTER_STRATEGY 0
 #define PNG_Z_DEFAULT_STRATEGY 1
diff --git a/vendor/libpng/pngpread.c b/vendor/libpng/pngpread.c
index e283627b77..ffab19c08c 100644
--- a/vendor/libpng/pngpread.c
+++ b/vendor/libpng/pngpread.c
@@ -1,7 +1,7 @@
 
 /* pngpread.c - read a png file in push mode
  *
- * Copyright (c) 2018 Cosmin Truta
+ * Copyright (c) 2018-2024 Cosmin Truta
  * Copyright (c) 1998-2002,2004,2006-2018 Glenn Randers-Pehrson
  * Copyright (c) 1996-1997 Andreas Dilger
  * Copyright (c) 1995-1996 Guy Eric Schalnat, Group 42, Inc.
@@ -145,10 +145,10 @@ png_push_read_sig(png_structrp png_ptr, png_inforp info_ptr)
        num_to_check);
    png_ptr->sig_bytes = (png_byte)(png_ptr->sig_bytes + num_to_check);
 
-   if (png_sig_cmp(info_ptr->signature, num_checked, num_to_check))
+   if (png_sig_cmp(info_ptr->signature, num_checked, num_to_check) != 0)
    {
       if (num_checked < 4 &&
-          png_sig_cmp(info_ptr->signature, num_checked, num_to_check - 4))
+          png_sig_cmp(info_ptr->signature, num_checked, num_to_check - 4) != 0)
          png_error(png_ptr, "Not a PNG file");
 
       else
@@ -294,6 +294,14 @@ png_push_read_chunk(png_structrp png_ptr, png_inforp info_ptr)
       png_handle_cHRM(png_ptr, info_ptr, png_ptr->push_length);
    }
 
+#endif
+#ifdef PNG_READ_eXIf_SUPPORTED
+   else if (png_ptr->chunk_name == png_eXIf)
+   {
+      PNG_PUSH_SAVE_BUFFER_IF_FULL
+      png_handle_eXIf(png_ptr, info_ptr, png_ptr->push_length);
+   }
+
 #endif
 #ifdef PNG_READ_sRGB_SUPPORTED
    else if (chunk_name == png_sRGB)
@@ -1089,7 +1097,7 @@ png_voidp PNGAPI
 png_get_progressive_ptr(png_const_structrp png_ptr)
 {
    if (png_ptr == NULL)
-      return (NULL);
+      return NULL;
 
    return png_ptr->io_ptr;
 }
diff --git a/vendor/libpng/pngpriv.h b/vendor/libpng/pngpriv.h
index 7c19373f0b..9bfdb71342 100644
--- a/vendor/libpng/pngpriv.h
+++ b/vendor/libpng/pngpriv.h
@@ -1,7 +1,7 @@
 
 /* pngpriv.h - private declarations for use inside libpng
  *
- * Copyright (c) 2018-2023 Cosmin Truta
+ * Copyright (c) 2018-2024 Cosmin Truta
  * Copyright (c) 1998-2002,2004,2006-2018 Glenn Randers-Pehrson
  * Copyright (c) 1996-1997 Andreas Dilger
  * Copyright (c) 1995-1996 Guy Eric Schalnat, Group 42, Inc.
@@ -36,7 +36,7 @@
  * still required (as of 2011-05-02.)
  */
 #ifndef _POSIX_SOURCE
-# define _POSIX_SOURCE 1 /* Just the POSIX 1003.1 and C89 APIs */
+#  define _POSIX_SOURCE 1 /* Just the POSIX 1003.1 and C89 APIs */
 #endif
 
 #ifndef PNG_VERSION_INFO_ONLY
@@ -190,13 +190,27 @@
 #endif /* PNG_ARM_NEON_OPT > 0 */
 
 #ifndef PNG_MIPS_MSA_OPT
-#  if defined(__mips_msa) && (__mips_isa_rev >= 5) && defined(PNG_ALIGNED_MEMORY_SUPPORTED)
+#  if defined(__mips_msa) && (__mips_isa_rev >= 5) && \
+   defined(PNG_ALIGNED_MEMORY_SUPPORTED)
 #     define PNG_MIPS_MSA_OPT 2
 #  else
 #     define PNG_MIPS_MSA_OPT 0
 #  endif
 #endif
 
+#ifndef PNG_MIPS_MMI_OPT
+#  ifdef PNG_MIPS_MMI
+#    if defined(__mips_loongson_mmi) && (_MIPS_SIM == _ABI64) && \
+     defined(PNG_ALIGNED_MEMORY_SUPPORTED)
+#       define PNG_MIPS_MMI_OPT 1
+#    else
+#       define PNG_MIPS_MMI_OPT 0
+#    endif
+#  else
+#    define PNG_MIPS_MMI_OPT 0
+#  endif
+#endif
+
 #ifndef PNG_POWERPC_VSX_OPT
 #  if defined(__PPC64__) && defined(__ALTIVEC__) && defined(__VSX__)
 #     define PNG_POWERPC_VSX_OPT 2
@@ -205,13 +219,21 @@
 #  endif
 #endif
 
+#ifndef PNG_LOONGARCH_LSX_OPT
+#  if defined(__loongarch_sx)
+#     define PNG_LOONGARCH_LSX_OPT 1
+#  else
+#     define PNG_LOONGARCH_LSX_OPT 0
+#  endif
+#endif
+
 #ifndef PNG_INTEL_SSE_OPT
 #   ifdef PNG_INTEL_SSE
       /* Only check for SSE if the build configuration has been modified to
        * enable SSE optimizations.  This means that these optimizations will
        * be off by default.  See contrib/intel for more details.
        */
-#     if defined(__SSE4_1__) || defined(__AVX__) || defined(__SSSE3__) || \
+#      if defined(__SSE4_1__) || defined(__AVX__) || defined(__SSSE3__) || \
        defined(__SSE2__) || defined(_M_X64) || defined(_M_AMD64) || \
        (defined(_M_IX86_FP) && _M_IX86_FP >= 2)
 #         define PNG_INTEL_SSE_OPT 1
@@ -248,7 +270,6 @@
 #endif
 
 #if PNG_MIPS_MSA_OPT > 0
-#  define PNG_FILTER_OPTIMIZATIONS png_init_filter_functions_msa
 #  ifndef PNG_MIPS_MSA_IMPLEMENTATION
 #     if defined(__mips_msa)
 #        if defined(__clang__)
@@ -264,11 +285,28 @@
 
 #  ifndef PNG_MIPS_MSA_IMPLEMENTATION
 #     define PNG_MIPS_MSA_IMPLEMENTATION 1
+#     define PNG_FILTER_OPTIMIZATIONS png_init_filter_functions_mips
 #  endif
 #else
 #  define PNG_MIPS_MSA_IMPLEMENTATION 0
 #endif /* PNG_MIPS_MSA_OPT > 0 */
 
+#if PNG_MIPS_MMI_OPT > 0
+#  ifndef PNG_MIPS_MMI_IMPLEMENTATION
+#     if defined(__mips_loongson_mmi) && (_MIPS_SIM == _ABI64)
+#        define PNG_MIPS_MMI_IMPLEMENTATION 2
+#     else /* !defined __mips_loongson_mmi  || _MIPS_SIM != _ABI64 */
+#        define PNG_MIPS_MMI_IMPLEMENTATION 0
+#     endif /* __mips_loongson_mmi  && _MIPS_SIM == _ABI64 */
+#  endif /* !PNG_MIPS_MMI_IMPLEMENTATION */
+
+#   if PNG_MIPS_MMI_IMPLEMENTATION > 0
+#      define PNG_FILTER_OPTIMIZATIONS png_init_filter_functions_mips
+#   endif
+#else
+#   define PNG_MIPS_MMI_IMPLEMENTATION 0
+#endif /* PNG_MIPS_MMI_OPT > 0 */
+
 #if PNG_POWERPC_VSX_OPT > 0
 #  define PNG_FILTER_OPTIMIZATIONS png_init_filter_functions_vsx
 #  define PNG_POWERPC_VSX_IMPLEMENTATION 1
@@ -276,6 +314,12 @@
 #  define PNG_POWERPC_VSX_IMPLEMENTATION 0
 #endif
 
+#if PNG_LOONGARCH_LSX_OPT > 0
+#   define PNG_FILTER_OPTIMIZATIONS png_init_filter_functions_lsx
+#   define PNG_LOONGARCH_LSX_IMPLEMENTATION 1
+#else
+#   define PNG_LOONGARCH_LSX_IMPLEMENTATION 0
+#endif
 
 /* Is this a build of a DLL where compilation of the object modules requires
  * different preprocessor settings to those required for a simple library?  If
@@ -514,18 +558,8 @@
     */
 #  include 
 
-#  if (defined(__MWERKS__) && defined(macintosh)) || defined(applec) || \
-    defined(THINK_C) || defined(__SC__) || defined(TARGET_OS_MAC)
-   /* We need to check that  hasn't already been included earlier
-    * as it seems it doesn't agree with , yet we should really use
-    *  if possible.
-    */
-#    if !defined(__MATH_H__) && !defined(__MATH_H) && !defined(__cmath__)
-#      include 
-#    endif
-#  else
-#    include 
-#  endif
+#  include 
+
 #  if defined(_AMIGA) && defined(__SASC) && defined(_M68881)
    /* Amiga SAS/C: We must include builtin FPU functions when compiling using
     * MATH=68881
@@ -1306,7 +1340,7 @@ PNG_INTERNAL_FUNCTION(void,png_read_filter_row_paeth4_neon,(png_row_infop
     row_info, png_bytep row, png_const_bytep prev_row),PNG_EMPTY);
 #endif
 
-#if PNG_MIPS_MSA_OPT > 0
+#if PNG_MIPS_MSA_IMPLEMENTATION == 1
 PNG_INTERNAL_FUNCTION(void,png_read_filter_row_up_msa,(png_row_infop row_info,
     png_bytep row, png_const_bytep prev_row),PNG_EMPTY);
 PNG_INTERNAL_FUNCTION(void,png_read_filter_row_sub3_msa,(png_row_infop
@@ -1323,6 +1357,23 @@ PNG_INTERNAL_FUNCTION(void,png_read_filter_row_paeth4_msa,(png_row_infop
     row_info, png_bytep row, png_const_bytep prev_row),PNG_EMPTY);
 #endif
 
+#if PNG_MIPS_MMI_IMPLEMENTATION > 0
+PNG_INTERNAL_FUNCTION(void,png_read_filter_row_up_mmi,(png_row_infop row_info,
+    png_bytep row, png_const_bytep prev_row),PNG_EMPTY);
+PNG_INTERNAL_FUNCTION(void,png_read_filter_row_sub3_mmi,(png_row_infop
+    row_info, png_bytep row, png_const_bytep prev_row),PNG_EMPTY);
+PNG_INTERNAL_FUNCTION(void,png_read_filter_row_sub4_mmi,(png_row_infop
+    row_info, png_bytep row, png_const_bytep prev_row),PNG_EMPTY);
+PNG_INTERNAL_FUNCTION(void,png_read_filter_row_avg3_mmi,(png_row_infop
+    row_info, png_bytep row, png_const_bytep prev_row),PNG_EMPTY);
+PNG_INTERNAL_FUNCTION(void,png_read_filter_row_avg4_mmi,(png_row_infop
+    row_info, png_bytep row, png_const_bytep prev_row),PNG_EMPTY);
+PNG_INTERNAL_FUNCTION(void,png_read_filter_row_paeth3_mmi,(png_row_infop
+    row_info, png_bytep row, png_const_bytep prev_row),PNG_EMPTY);
+PNG_INTERNAL_FUNCTION(void,png_read_filter_row_paeth4_mmi,(png_row_infop
+    row_info, png_bytep row, png_const_bytep prev_row),PNG_EMPTY);
+#endif
+
 #if PNG_POWERPC_VSX_OPT > 0
 PNG_INTERNAL_FUNCTION(void,png_read_filter_row_up_vsx,(png_row_infop row_info,
     png_bytep row, png_const_bytep prev_row),PNG_EMPTY);
@@ -1355,6 +1406,23 @@ PNG_INTERNAL_FUNCTION(void,png_read_filter_row_paeth4_sse2,(png_row_infop
     row_info, png_bytep row, png_const_bytep prev_row),PNG_EMPTY);
 #endif
 
+#if PNG_LOONGARCH_LSX_IMPLEMENTATION == 1
+PNG_INTERNAL_FUNCTION(void,png_read_filter_row_up_lsx,(png_row_infop
+    row_info, png_bytep row, png_const_bytep prev_row),PNG_EMPTY);
+PNG_INTERNAL_FUNCTION(void,png_read_filter_row_sub3_lsx,(png_row_infop
+    row_info, png_bytep row, png_const_bytep prev_row),PNG_EMPTY);
+PNG_INTERNAL_FUNCTION(void,png_read_filter_row_sub4_lsx,(png_row_infop
+    row_info, png_bytep row, png_const_bytep prev_row),PNG_EMPTY);
+PNG_INTERNAL_FUNCTION(void,png_read_filter_row_avg3_lsx,(png_row_infop
+    row_info, png_bytep row, png_const_bytep prev_row),PNG_EMPTY);
+PNG_INTERNAL_FUNCTION(void,png_read_filter_row_avg4_lsx,(png_row_infop
+    row_info, png_bytep row, png_const_bytep prev_row),PNG_EMPTY);
+PNG_INTERNAL_FUNCTION(void,png_read_filter_row_paeth3_lsx,(png_row_infop
+    row_info, png_bytep row, png_const_bytep prev_row),PNG_EMPTY);
+PNG_INTERNAL_FUNCTION(void,png_read_filter_row_paeth4_lsx,(png_row_infop
+    row_info, png_bytep row, png_const_bytep prev_row),PNG_EMPTY);
+#endif
+
 /* Choose the best filter to use and filter the row data */
 PNG_INTERNAL_FUNCTION(void,png_write_find_filter,(png_structrp png_ptr,
     png_row_infop row_info),PNG_EMPTY);
@@ -2094,17 +2162,27 @@ PNG_INTERNAL_FUNCTION(void, png_init_filter_functions_neon,
    (png_structp png_ptr, unsigned int bpp), PNG_EMPTY);
 #endif
 
-#if PNG_MIPS_MSA_OPT > 0
-PNG_INTERNAL_FUNCTION(void, png_init_filter_functions_msa,
+#if PNG_MIPS_MSA_IMPLEMENTATION == 1
+PNG_INTERNAL_FUNCTION(void, png_init_filter_functions_mips,
    (png_structp png_ptr, unsigned int bpp), PNG_EMPTY);
 #endif
 
+#  if PNG_MIPS_MMI_IMPLEMENTATION > 0
+PNG_INTERNAL_FUNCTION(void, png_init_filter_functions_mips,
+   (png_structp png_ptr, unsigned int bpp), PNG_EMPTY);
+#  endif
+
 #  if PNG_INTEL_SSE_IMPLEMENTATION > 0
 PNG_INTERNAL_FUNCTION(void, png_init_filter_functions_sse2,
    (png_structp png_ptr, unsigned int bpp), PNG_EMPTY);
 #  endif
 #endif
 
+#if PNG_LOONGARCH_LSX_OPT > 0
+PNG_INTERNAL_FUNCTION(void, png_init_filter_functions_lsx,
+    (png_structp png_ptr, unsigned int bpp), PNG_EMPTY);
+#endif
+
 PNG_INTERNAL_FUNCTION(png_uint_32, png_check_keyword, (png_structrp png_ptr,
    png_const_charp key, png_bytep new_key), PNG_EMPTY);
 
diff --git a/vendor/libpng/pngread.c b/vendor/libpng/pngread.c
index 96996ced5b..07a39df6e2 100644
--- a/vendor/libpng/pngread.c
+++ b/vendor/libpng/pngread.c
@@ -1,7 +1,7 @@
 
 /* pngread.c - read a PNG file
  *
- * Copyright (c) 2018-2019 Cosmin Truta
+ * Copyright (c) 2018-2024 Cosmin Truta
  * Copyright (c) 1998-2002,2004,2006-2018 Glenn Randers-Pehrson
  * Copyright (c) 1996-1997 Andreas Dilger
  * Copyright (c) 1995-1996 Guy Eric Schalnat, Group 42, Inc.
@@ -568,7 +568,11 @@ png_read_row(png_structrp png_ptr, png_bytep row, png_bytep dsp_row)
 #endif
 
 #ifdef PNG_READ_TRANSFORMS_SUPPORTED
-   if (png_ptr->transformations)
+   if (png_ptr->transformations
+#     ifdef PNG_CHECK_FOR_INVALID_INDEX_SUPPORTED
+         || png_ptr->num_palette_max >= 0
+#     endif
+      )
       png_do_read_transformations(png_ptr, &row_info);
 #endif
 
@@ -785,7 +789,7 @@ png_read_end(png_structrp png_ptr, png_inforp info_ptr)
 #ifdef PNG_READ_CHECK_FOR_INVALID_INDEX_SUPPORTED
    /* Report invalid palette index; added at libng-1.5.10 */
    if (png_ptr->color_type == PNG_COLOR_TYPE_PALETTE &&
-       png_ptr->num_palette_max > png_ptr->num_palette)
+       png_ptr->num_palette_max >= png_ptr->num_palette)
       png_benign_error(png_ptr, "Read palette index exceeding num_palette");
 #endif
 
@@ -1049,6 +1053,8 @@ void PNGAPI
 png_read_png(png_structrp png_ptr, png_inforp info_ptr,
     int transforms, voidp params)
 {
+   png_debug(1, "in png_read_png");
+
    if (png_ptr == NULL || info_ptr == NULL)
       return;
 
diff --git a/vendor/libpng/pngrtran.c b/vendor/libpng/pngrtran.c
index 238f5afe7e..1526123e02 100644
--- a/vendor/libpng/pngrtran.c
+++ b/vendor/libpng/pngrtran.c
@@ -1,7 +1,7 @@
 
 /* pngrtran.c - transforms the data in a row for PNG readers
  *
- * Copyright (c) 2018-2019 Cosmin Truta
+ * Copyright (c) 2018-2024 Cosmin Truta
  * Copyright (c) 1998-2002,2004,2006-2018 Glenn Randers-Pehrson
  * Copyright (c) 1996-1997 Andreas Dilger
  * Copyright (c) 1995-1996 Guy Eric Schalnat, Group 42, Inc.
@@ -290,21 +290,20 @@ png_set_alpha_mode_fixed(png_structrp png_ptr, int mode,
    int compose = 0;
    png_fixed_point file_gamma;
 
-   png_debug(1, "in png_set_alpha_mode");
+   png_debug(1, "in png_set_alpha_mode_fixed");
 
    if (png_rtran_ok(png_ptr, 0) == 0)
       return;
 
    output_gamma = translate_gamma_flags(png_ptr, output_gamma, 1/*screen*/);
 
-   /* Validate the value to ensure it is in a reasonable range. The value
+   /* Validate the value to ensure it is in a reasonable range.  The value
     * is expected to be 1 or greater, but this range test allows for some
-    * viewing correction values.  The intent is to weed out users of this API
-    * who use the inverse of the gamma value accidentally!  Since some of these
-    * values are reasonable this may have to be changed:
+    * viewing correction values.  The intent is to weed out the API users
+    * who might use the inverse of the gamma value accidentally!
     *
-    * 1.6.x: changed from 0.07..3 to 0.01..100 (to accommodate the optimal 16-bit
-    * gamma of 36, and its reciprocal.)
+    * In libpng 1.6.0, we changed from 0.07..3 to 0.01..100, to accommodate
+    * the optimal 16-bit gamma of 36 and its reciprocal.
     */
    if (output_gamma < 1000 || output_gamma > 10000000)
       png_error(png_ptr, "output gamma out of expected range");
@@ -441,7 +440,7 @@ png_set_quantize(png_structrp png_ptr, png_colorp palette,
       int i;
 
       png_ptr->quantize_index = (png_bytep)png_malloc(png_ptr,
-          (png_alloc_size_t)((png_uint_32)num_palette * (sizeof (png_byte))));
+          (png_alloc_size_t)num_palette);
       for (i = 0; i < num_palette; i++)
          png_ptr->quantize_index[i] = (png_byte)i;
    }
@@ -458,7 +457,7 @@ png_set_quantize(png_structrp png_ptr, png_colorp palette,
 
          /* Initialize an array to sort colors */
          png_ptr->quantize_sort = (png_bytep)png_malloc(png_ptr,
-             (png_alloc_size_t)((png_uint_32)num_palette * (sizeof (png_byte))));
+             (png_alloc_size_t)num_palette);
 
          /* Initialize the quantize_sort array */
          for (i = 0; i < num_palette; i++)
@@ -592,11 +591,9 @@ png_set_quantize(png_structrp png_ptr, png_colorp palette,
 
          /* Initialize palette index arrays */
          png_ptr->index_to_palette = (png_bytep)png_malloc(png_ptr,
-             (png_alloc_size_t)((png_uint_32)num_palette *
-             (sizeof (png_byte))));
+             (png_alloc_size_t)num_palette);
          png_ptr->palette_to_index = (png_bytep)png_malloc(png_ptr,
-             (png_alloc_size_t)((png_uint_32)num_palette *
-             (sizeof (png_byte))));
+             (png_alloc_size_t)num_palette);
 
          /* Initialize the sort array */
          for (i = 0; i < num_palette; i++)
@@ -761,12 +758,11 @@ png_set_quantize(png_structrp png_ptr, png_colorp palette,
       size_t num_entries = ((size_t)1 << total_bits);
 
       png_ptr->palette_lookup = (png_bytep)png_calloc(png_ptr,
-          (png_alloc_size_t)(num_entries * (sizeof (png_byte))));
+          (png_alloc_size_t)(num_entries));
 
-      distance = (png_bytep)png_malloc(png_ptr, (png_alloc_size_t)(num_entries *
-          (sizeof (png_byte))));
+      distance = (png_bytep)png_malloc(png_ptr, (png_alloc_size_t)num_entries);
 
-      memset(distance, 0xff, num_entries * (sizeof (png_byte)));
+      memset(distance, 0xff, num_entries);
 
       for (i = 0; i < num_palette; i++)
       {
@@ -970,7 +966,7 @@ void PNGFAPI
 png_set_rgb_to_gray_fixed(png_structrp png_ptr, int error_action,
     png_fixed_point red, png_fixed_point green)
 {
-   png_debug(1, "in png_set_rgb_to_gray");
+   png_debug(1, "in png_set_rgb_to_gray_fixed");
 
    /* Need the IHDR here because of the check on color_type below. */
    /* TODO: fix this */
diff --git a/vendor/libpng/pngrutil.c b/vendor/libpng/pngrutil.c
index 068ab193a3..d31dc21dae 100644
--- a/vendor/libpng/pngrutil.c
+++ b/vendor/libpng/pngrutil.c
@@ -1,7 +1,7 @@
 
 /* pngrutil.c - utilities to read a PNG file
  *
- * Copyright (c) 2018-2022 Cosmin Truta
+ * Copyright (c) 2018-2024 Cosmin Truta
  * Copyright (c) 1998-2002,2004,2006-2018 Glenn Randers-Pehrson
  * Copyright (c) 1996-1997 Andreas Dilger
  * Copyright (c) 1995-1996 Guy Eric Schalnat, Group 42, Inc.
@@ -26,7 +26,7 @@ png_get_uint_31(png_const_structrp png_ptr, png_const_bytep buf)
    if (uval > PNG_UINT_31_MAX)
       png_error(png_ptr, "PNG unsigned integer out of range");
 
-   return (uval);
+   return uval;
 }
 
 #if defined(PNG_READ_gAMA_SUPPORTED) || defined(PNG_READ_cHRM_SUPPORTED)
@@ -140,7 +140,7 @@ png_read_sig(png_structrp png_ptr, png_inforp info_ptr)
    if (png_sig_cmp(info_ptr->signature, num_checked, num_to_check) != 0)
    {
       if (num_checked < 4 &&
-          png_sig_cmp(info_ptr->signature, num_checked, num_to_check - 4))
+          png_sig_cmp(info_ptr->signature, num_checked, num_to_check - 4) != 0)
          png_error(png_ptr, "Not a PNG file");
       else
          png_error(png_ptr, "PNG file corrupted by ASCII conversion");
@@ -171,7 +171,7 @@ png_read_chunk_header(png_structrp png_ptr)
    /* Put the chunk name into png_ptr->chunk_name. */
    png_ptr->chunk_name = PNG_CHUNK_FROM_STRING(buf+4);
 
-   png_debug2(0, "Reading %lx chunk, length = %lu",
+   png_debug2(0, "Reading chunk typeid = 0x%lx, length = %lu",
        (unsigned long)png_ptr->chunk_name, (unsigned long)length);
 
    /* Reset the crc and run it over the chunk name. */
@@ -238,10 +238,10 @@ png_crc_finish(png_structrp png_ptr, png_uint_32 skip)
       else
          png_chunk_error(png_ptr, "CRC error");
 
-      return (1);
+      return 1;
    }
 
-   return (0);
+   return 0;
 }
 
 /* Compare the CRC stored in the PNG file with that calculated by libpng from
@@ -277,11 +277,11 @@ png_crc_error(png_structrp png_ptr)
    if (need_crc != 0)
    {
       crc = png_get_uint_32(crc_bytes);
-      return ((int)(crc != png_ptr->crc));
+      return crc != png_ptr->crc;
    }
 
    else
-      return (0);
+      return 0;
 }
 
 #if defined(PNG_READ_iCCP_SUPPORTED) || defined(PNG_READ_iTXt_SUPPORTED) ||\
@@ -421,8 +421,7 @@ png_inflate_claim(png_structrp png_ptr, png_uint_32 owner)
             png_ptr->flags |= PNG_FLAG_ZSTREAM_INITIALIZED;
       }
 
-#if ZLIB_VERNUM >= 0x1290 && \
-   defined(PNG_SET_OPTION_SUPPORTED) && defined(PNG_IGNORE_ADLER32)
+#ifdef PNG_DISABLE_ADLER32_CHECK_SUPPORTED
       if (((png_ptr->options >> PNG_IGNORE_ADLER32) & 3) == PNG_OPTION_ON)
          /* Turn off validation of the ADLER32 checksum in IDAT chunks */
          ret = inflateValidate(&png_ptr->zstream, 0);
diff --git a/vendor/libpng/pngset.c b/vendor/libpng/pngset.c
index 3fc31feb0c..eb1c8c7a35 100644
--- a/vendor/libpng/pngset.c
+++ b/vendor/libpng/pngset.c
@@ -1,7 +1,7 @@
 
 /* pngset.c - storage of image information into info struct
  *
- * Copyright (c) 2018-2023 Cosmin Truta
+ * Copyright (c) 2018-2024 Cosmin Truta
  * Copyright (c) 1998-2018 Glenn Randers-Pehrson
  * Copyright (c) 1996-1997 Andreas Dilger
  * Copyright (c) 1995-1996 Guy Eric Schalnat, Group 42, Inc.
@@ -763,11 +763,11 @@ png_set_text_2(png_const_structrp png_ptr, png_inforp info_ptr,
 {
    int i;
 
-   png_debug1(1, "in %lx storage function", png_ptr == NULL ? 0xabadca11U :
-      (unsigned long)png_ptr->chunk_name);
+   png_debug1(1, "in text storage function, chunk typeid = 0x%lx",
+      png_ptr == NULL ? 0xabadca11UL : (unsigned long)png_ptr->chunk_name);
 
    if (png_ptr == NULL || info_ptr == NULL || num_text <= 0 || text_ptr == NULL)
-      return(0);
+      return 0;
 
    /* Make sure we have enough space in the "text" array in info_struct
     * to hold all of the incoming text_ptr objects.  This compare can't overflow
@@ -947,7 +947,7 @@ png_set_text_2(png_const_structrp png_ptr, png_inforp info_ptr,
       png_debug1(3, "transferred text chunk %d", info_ptr->num_text);
    }
 
-   return(0);
+   return 0;
 }
 #endif
 
@@ -1063,6 +1063,8 @@ png_set_sPLT(png_const_structrp png_ptr,
 {
    png_sPLT_tp np;
 
+   png_debug1(1, "in %s storage function", "sPLT");
+
    if (png_ptr == NULL || info_ptr == NULL || nentries <= 0 || entries == NULL)
       return;
 
@@ -1537,7 +1539,7 @@ void PNGAPI
 png_set_rows(png_const_structrp png_ptr, png_inforp info_ptr,
     png_bytepp row_pointers)
 {
-   png_debug1(1, "in %s storage function", "rows");
+   png_debug(1, "in png_set_rows");
 
    if (png_ptr == NULL || info_ptr == NULL)
       return;
@@ -1556,6 +1558,8 @@ png_set_rows(png_const_structrp png_ptr, png_inforp info_ptr,
 void PNGAPI
 png_set_compression_buffer_size(png_structrp png_ptr, size_t size)
 {
+   png_debug(1, "in png_set_compression_buffer_size");
+
    if (png_ptr == NULL)
       return;
 
@@ -1627,6 +1631,8 @@ void PNGAPI
 png_set_user_limits(png_structrp png_ptr, png_uint_32 user_width_max,
     png_uint_32 user_height_max)
 {
+   png_debug(1, "in png_set_user_limits");
+
    /* Images with dimensions larger than these limits will be
     * rejected by png_set_IHDR().  To accept any PNG datastream
     * regardless of dimensions, set both limits to 0x7fffffff.
@@ -1642,6 +1648,8 @@ png_set_user_limits(png_structrp png_ptr, png_uint_32 user_width_max,
 void PNGAPI
 png_set_chunk_cache_max(png_structrp png_ptr, png_uint_32 user_chunk_cache_max)
 {
+   png_debug(1, "in png_set_chunk_cache_max");
+
    if (png_ptr != NULL)
       png_ptr->user_chunk_cache_max = user_chunk_cache_max;
 }
@@ -1651,6 +1659,8 @@ void PNGAPI
 png_set_chunk_malloc_max(png_structrp png_ptr,
     png_alloc_size_t user_chunk_malloc_max)
 {
+   png_debug(1, "in png_set_chunk_malloc_max");
+
    if (png_ptr != NULL)
       png_ptr->user_chunk_malloc_max = user_chunk_malloc_max;
 }
diff --git a/vendor/libpng/pngtest.c b/vendor/libpng/pngtest.c
index 37b42bb346..45ef66a701 100644
--- a/vendor/libpng/pngtest.c
+++ b/vendor/libpng/pngtest.c
@@ -1,7 +1,7 @@
 
-/* pngtest.c - a simple test program to test libpng
+/* pngtest.c - a test program for libpng
  *
- * Copyright (c) 2018-2019 Cosmin Truta
+ * Copyright (c) 2018-2024 Cosmin Truta
  * Copyright (c) 1998-2002,2004,2006-2018 Glenn Randers-Pehrson
  * Copyright (c) 1996-1997 Andreas Dilger
  * Copyright (c) 1995-1996 Guy Eric Schalnat, Group 42, Inc.
@@ -37,73 +37,91 @@
 #include 
 #include 
 
-/* Defined so I can write to a file on gui/windowing platforms */
-/*  #define STDERR stderr  */
-#define STDERR stdout   /* For DOS */
+#ifdef PNG_ZLIB_HEADER
+#  include PNG_ZLIB_HEADER /* defined by pnglibconf.h from 1.7 */
+#else
+#  include 
+#endif
 
 #include "png.h"
 
-/* Known chunks that exist in pngtest.png must be supported or pngtest will fail
- * simply as a result of re-ordering them.  This may be fixed in 1.7
+/* Generate a compiler error if there is an old png.h in the search path. */
+typedef png_libpng_version_1_6_43 Your_png_h_is_not_version_1_6_43;
+
+/* Ensure that all version numbers in png.h are consistent with one another. */
+#if (PNG_LIBPNG_VER != PNG_LIBPNG_VER_MAJOR * 10000 + \
+                       PNG_LIBPNG_VER_MINOR * 100 + \
+                       PNG_LIBPNG_VER_RELEASE) || \
+    (PNG_LIBPNG_VER_SHAREDLIB != PNG_LIBPNG_VER_MAJOR * 10 + \
+                                 PNG_LIBPNG_VER_MINOR) || \
+    (PNG_LIBPNG_VER_SHAREDLIB != PNG_LIBPNG_VER_SONUM) || \
+    (PNG_LIBPNG_VER_SHAREDLIB != PNG_LIBPNG_VER_DLLNUM)
+#  error "Inconsistent version numbers in png.h"
+#endif
+
+/* In version 1.6.1, we added support for the configure test harness, which
+ * uses 77 to indicate a skipped test. On the other hand, in cmake build tests,
+ * we still need to succeed on a skipped test, so:
+ */
+#if defined(HAVE_CONFIG_H)
+#  define SKIP 77
+#else
+#  define SKIP 0
+#endif
+
+/* Known chunks that exist in pngtest.png must be supported, or pngtest will
+ * fail simply as a result of re-ordering them.  This may be fixed in the next
+ * generation of libpng.
  *
  * pngtest allocates a single row buffer for each row and overwrites it,
  * therefore if the write side doesn't support the writing of interlaced images
  * nothing can be done for an interlaced image (and the code below will fail
  * horribly trying to write extra data after writing garbage).
  */
-#if defined PNG_READ_SUPPORTED && /* else nothing can be done */\
-   defined PNG_READ_bKGD_SUPPORTED &&\
-   defined PNG_READ_cHRM_SUPPORTED &&\
-   defined PNG_READ_gAMA_SUPPORTED &&\
-   defined PNG_READ_oFFs_SUPPORTED &&\
-   defined PNG_READ_pCAL_SUPPORTED &&\
-   defined PNG_READ_pHYs_SUPPORTED &&\
-   defined PNG_READ_sBIT_SUPPORTED &&\
-   defined PNG_READ_sCAL_SUPPORTED &&\
-   defined PNG_READ_sRGB_SUPPORTED &&\
-   defined PNG_READ_sPLT_SUPPORTED &&\
-   defined PNG_READ_tEXt_SUPPORTED &&\
-   defined PNG_READ_tIME_SUPPORTED &&\
-   defined PNG_READ_zTXt_SUPPORTED &&\
-   (defined PNG_WRITE_INTERLACING_SUPPORTED || PNG_LIBPNG_VER >= 10700)
-
-#ifdef PNG_ZLIB_HEADER
-#  include PNG_ZLIB_HEADER /* defined by pnglibconf.h from 1.7 */
-#else
-#  include "zlib.h"
-#endif
+#if defined PNG_READ_SUPPORTED && /* else nothing can be done */ \
+    defined PNG_READ_bKGD_SUPPORTED && \
+    defined PNG_READ_cHRM_SUPPORTED && \
+    defined PNG_READ_gAMA_SUPPORTED && \
+    defined PNG_READ_oFFs_SUPPORTED && \
+    defined PNG_READ_pCAL_SUPPORTED && \
+    defined PNG_READ_pHYs_SUPPORTED && \
+    defined PNG_READ_sBIT_SUPPORTED && \
+    defined PNG_READ_sCAL_SUPPORTED && \
+    defined PNG_READ_sRGB_SUPPORTED && \
+    defined PNG_READ_sPLT_SUPPORTED && \
+    defined PNG_READ_tEXt_SUPPORTED && \
+    defined PNG_READ_tIME_SUPPORTED && \
+    defined PNG_READ_zTXt_SUPPORTED && \
+    (defined PNG_WRITE_INTERLACING_SUPPORTED || PNG_LIBPNG_VER >= 10700)
 
 /* Copied from pngpriv.h but only used in error messages below. */
 #ifndef PNG_ZBUF_SIZE
 #  define PNG_ZBUF_SIZE 8192
 #endif
-#define FCLOSE(file) fclose(file)
 
 #ifndef PNG_STDIO_SUPPORTED
-typedef FILE                * png_FILE_p;
+typedef FILE * png_FILE_p;
 #endif
 
-/* Makes pngtest verbose so we can find problems. */
+/* This hack was introduced for historical reasons, and we are
+ * still keeping it in libpng-1.6.x for compatibility reasons.
+ */
+#define STDERR stdout
+
 #ifndef PNG_DEBUG
 #  define PNG_DEBUG 0
 #endif
 
 #if PNG_DEBUG > 1
-#  define pngtest_debug(m)        ((void)fprintf(stderr, m "\n"))
-#  define pngtest_debug1(m,p1)    ((void)fprintf(stderr, m "\n", p1))
-#  define pngtest_debug2(m,p1,p2) ((void)fprintf(stderr, m "\n", p1, p2))
-#else
-#  define pngtest_debug(m)        ((void)0)
-#  define pngtest_debug1(m,p1)    ((void)0)
-#  define pngtest_debug2(m,p1,p2) ((void)0)
-#endif
-
-#if !PNG_DEBUG
-#  define SINGLE_ROWBUF_ALLOC  /* Makes buffer overruns easier to nail */
-#endif
-
-#ifndef PNG_UNUSED
-#  define PNG_UNUSED(param) (void)param;
+#  define pngtest_debug(m)          ((void)fprintf(stderr, m "\n"))
+#  define pngtest_debug1(m, p1)     ((void)fprintf(stderr, m "\n", p1))
+#  define pngtest_debug2(m, p1, p2) ((void)fprintf(stderr, m "\n", p1, p2))
+#elif PNG_DEBUG == 0 || PNG_DEBUG == 1
+#  define pngtest_debug(m)          ((void)0)
+#  define pngtest_debug1(m, p1)     ((void)0)
+#  define pngtest_debug2(m, p1, p2) ((void)0)
+#else /* PNG_DEBUG < 0 */
+#  error "Bad PNG_DEBUG value"
 #endif
 
 /* Turn on CPU timing
@@ -120,25 +138,11 @@ static float t_start, t_stop, t_decode, t_encode, t_misc;
 #endif
 
 #ifdef PNG_TIME_RFC1123_SUPPORTED
-#define PNG_tIME_STRING_LENGTH 29
 static int tIME_chunk_present = 0;
-static char tIME_string[PNG_tIME_STRING_LENGTH] = "tIME chunk is not present";
-
-#if PNG_LIBPNG_VER < 10619
-#define png_convert_to_rfc1123_buffer(ts, t) tIME_to_str(read_ptr, ts, t)
-
-static int
-tIME_to_str(png_structp png_ptr, png_charp ts, png_const_timep t)
-{
-   png_const_charp str = png_convert_to_rfc1123(png_ptr, t);
-
-   if (str == NULL)
-       return 0;
-
-   strcpy(ts, str);
-   return 1;
-}
-#endif /* older libpng */
+static char tIME_string[29] = "tIME chunk is not present";
+/* This use case is deprecated.
+ * See the declaration of png_convert_to_rfc1123_buffer for more details.
+ */
 #endif
 
 static int verbose = 0;
@@ -149,22 +153,6 @@ static int unsupported_chunks = 0; /* chunk unsupported by libpng in input */
 static int error_count = 0; /* count calls to png_error */
 static int warning_count = 0; /* count calls to png_warning */
 
-/* Define png_jmpbuf() in case we are using a pre-1.0.6 version of libpng */
-#ifndef png_jmpbuf
-#  define png_jmpbuf(png_ptr) png_ptr->jmpbuf
-#endif
-
-/* Defines for unknown chunk handling if required. */
-#ifndef PNG_HANDLE_CHUNK_ALWAYS
-#  define PNG_HANDLE_CHUNK_ALWAYS       3
-#endif
-#ifndef PNG_HANDLE_CHUNK_IF_SAFE
-#  define PNG_HANDLE_CHUNK_IF_SAFE      2
-#endif
-
-/* Utility to save typing/errors, the argument must be a name */
-#define MEMZERO(var) ((void)memset(&var, 0, sizeof var))
-
 /* Example of using row callbacks to make a simple progress meter */
 static int status_pass = 1;
 static int status_dots_requested = 0;
@@ -173,8 +161,13 @@ static int status_dots = 1;
 static void PNGCBAPI
 read_row_callback(png_structp png_ptr, png_uint_32 row_number, int pass)
 {
-   if (png_ptr == NULL || row_number > PNG_UINT_31_MAX)
-      return;
+   /* The callback should always receive correct parameters. */
+   if (png_ptr == NULL)
+      png_error(png_ptr, "read_row_callback: bad png_ptr");
+   if (row_number > PNG_UINT_31_MAX)
+      png_error(png_ptr, "read_row_callback: bad row number");
+   if (pass < 0 || pass > 7)
+      png_error(png_ptr, "read_row_callback: bad pass");
 
    if (status_pass != pass)
    {
@@ -188,7 +181,7 @@ read_row_callback(png_structp png_ptr, png_uint_32 row_number, int pass)
    if (status_dots == 0)
    {
       fprintf(stdout, "\n         ");
-      status_dots=30;
+      status_dots = 30;
    }
 
    fprintf(stdout, "r");
@@ -198,8 +191,13 @@ read_row_callback(png_structp png_ptr, png_uint_32 row_number, int pass)
 static void PNGCBAPI
 write_row_callback(png_structp png_ptr, png_uint_32 row_number, int pass)
 {
-   if (png_ptr == NULL || row_number > PNG_UINT_31_MAX || pass > 7)
-      return;
+   /* The callback should always receive correct parameters. */
+   if (png_ptr == NULL)
+      png_error(png_ptr, "write_row_callback: bad png_ptr");
+   if (row_number > PNG_UINT_31_MAX)
+      png_error(png_ptr, "write_row_callback: bad row number");
+   if (pass < 0 || pass > 7)
+      png_error(png_ptr, "write_row_callback: bad pass");
 
    fprintf(stdout, "w");
 }
@@ -212,9 +210,13 @@ write_row_callback(png_structp png_ptr, png_uint_32 row_number, int pass)
 static void PNGCBAPI
 read_user_callback(png_structp png_ptr, png_row_infop row_info, png_bytep data)
 {
-   PNG_UNUSED(png_ptr)
-   PNG_UNUSED(row_info)
-   PNG_UNUSED(data)
+   /* The callback should always receive correct parameters. */
+   if (png_ptr == NULL)
+      png_error(png_ptr, "read_user_callback: bad png_ptr");
+   if (row_info == NULL)
+      png_error(png_ptr, "read_user_callback: bad row info");
+   if (data == NULL)
+      png_error(png_ptr, "read_user_callback: bad data");
 }
 #endif
 
@@ -229,8 +231,14 @@ static void PNGCBAPI
 count_zero_samples(png_structp png_ptr, png_row_infop row_info, png_bytep data)
 {
    png_bytep dp = data;
+
+   /* The callback should always receive correct parameters. */
    if (png_ptr == NULL)
-      return;
+      png_error(png_ptr, "count_zero_samples: bad png_ptr");
+   if (row_info == NULL)
+      png_error(png_ptr, "count_zero_samples: bad row info");
+   if (data == NULL)
+      png_error(png_ptr, "count_zero_samples: bad data");
 
    /* Contents of row_info:
     *  png_uint_32 width      width of row
@@ -248,7 +256,7 @@ count_zero_samples(png_structp png_ptr, png_row_infop row_info, png_bytep data)
       int pos = 0;
       png_uint_32 n, nstop;
 
-      for (n = 0, nstop=row_info->width; nwidth; n < nstop; n++)
       {
          if (row_info->bit_depth == 1)
          {
@@ -294,7 +302,7 @@ count_zero_samples(png_structp png_ptr, png_row_infop row_info, png_bytep data)
          {
             if ((*dp | *(dp+1)) == 0)
                zero_samples++;
-            dp+=2;
+            dp += 2;
          }
       }
    }
@@ -306,7 +314,7 @@ count_zero_samples(png_structp png_ptr, png_row_infop row_info, png_bytep data)
       if (row_info->color_type > 3)
          color_channels--;
 
-      for (n = 0, nstop=row_info->width; nwidth; n < nstop; n++)
       {
          for (channel = 0; channel < color_channels; channel++)
          {
@@ -319,7 +327,7 @@ count_zero_samples(png_structp png_ptr, png_row_infop row_info, png_bytep data)
                if ((*dp | *(dp+1)) == 0)
                   zero_samples++;
 
-               dp+=2;
+               dp += 2;
             }
          }
          if (row_info->color_type > 3)
@@ -345,9 +353,6 @@ count_zero_samples(png_structp png_ptr, png_row_infop row_info, png_bytep data)
 
 #ifdef PNG_IO_STATE_SUPPORTED
 void
-pngtest_check_io_state(png_structp png_ptr, size_t data_length,
-    png_uint_32 io_op);
-void
 pngtest_check_io_state(png_structp png_ptr, size_t data_length,
     png_uint_32 io_op)
 {
@@ -361,7 +366,7 @@ pngtest_check_io_state(png_structp png_ptr, size_t data_length,
    /* Check if the buffer size specific to the current location
     * (file signature / header / data / crc) is as expected.
     */
-   switch (io_state & PNG_IO_MASK_LOC)
+   switch ((io_state & PNG_IO_MASK_LOC) != 0)
    {
    case PNG_IO_SIGNATURE:
       if (data_length > 8)
@@ -391,19 +396,18 @@ pngtest_read_data(png_structp png_ptr, png_bytep data, size_t length)
    size_t check = 0;
    png_voidp io_ptr;
 
+   if (png_ptr == NULL)
+      png_error(png_ptr, "pngtest_read_data: bad png_ptr");
+
    /* fread() returns 0 on error, so it is OK to store this in a size_t
     * instead of an int, which is what fread() actually returns.
     */
    io_ptr = png_get_io_ptr(png_ptr);
    if (io_ptr != NULL)
-   {
       check = fread(data, 1, length, (png_FILE_p)io_ptr);
-   }
 
    if (check != length)
-   {
       png_error(png_ptr, "Read Error");
-   }
 
 #ifdef PNG_IO_STATE_SUPPORTED
    pngtest_check_io_state(png_ptr, length, PNG_IO_READING);
@@ -414,8 +418,10 @@ pngtest_read_data(png_structp png_ptr, png_bytep data, size_t length)
 static void PNGCBAPI
 pngtest_flush(png_structp png_ptr)
 {
+   if (png_ptr == NULL)
+      png_error(png_ptr, "pngtest_flush: bad png_ptr");
+
    /* Do nothing; fflush() is said to be just a waste of energy. */
-   PNG_UNUSED(png_ptr)   /* Stifle compiler warning */
 }
 #endif
 
@@ -429,12 +435,13 @@ pngtest_write_data(png_structp png_ptr, png_bytep data, size_t length)
 {
    size_t check;
 
+   if (png_ptr == NULL)
+      png_error(png_ptr, "pngtest_write_data: bad png_ptr");
+
    check = fwrite(data, 1, length, (png_FILE_p)png_get_io_ptr(png_ptr));
 
    if (check != length)
-   {
       png_error(png_ptr, "Write Error");
-   }
 
 #ifdef PNG_IO_STATE_SUPPORTED
    pngtest_check_io_state(png_ptr, length, PNG_IO_WRITING);
@@ -524,7 +531,7 @@ PNGCBAPI png_debug_malloc(png_structp png_ptr, png_alloc_size_t size)
     */
 
    if (size == 0)
-      return (NULL);
+      return NULL;
 
    /* This calls the library allocator twice, once to get the requested
       buffer and once to get a new free list entry. */
@@ -537,7 +544,7 @@ PNGCBAPI png_debug_malloc(png_structp png_ptr, png_alloc_size_t size)
       pinfo->size = size;
       current_allocation += size;
       total_allocation += size;
-      num_allocations ++;
+      ++num_allocations;
 
       if (current_allocation > maximum_allocation)
          maximum_allocation = current_allocation;
@@ -565,7 +572,7 @@ PNGCBAPI png_debug_malloc(png_structp png_ptr, png_alloc_size_t size)
          printf("png_malloc %lu bytes at %p\n", (unsigned long)size,
              pinfo->pointer);
 
-      return (png_voidp)(pinfo->pointer);
+      return (png_voidp)pinfo->pointer;
    }
 }
 
@@ -635,15 +642,14 @@ png_debug_free(png_structp png_ptr, png_voidp ptr)
 /* (sTER is a public chunk not yet known by libpng.  vpAg is a private
 chunk used in ImageMagick to store "virtual page" size).  */
 
-static struct user_chunk_data
+typedef struct user_chunk_info_def
 {
    png_const_infop info_ptr;
    png_uint_32     vpAg_width, vpAg_height;
    png_byte        vpAg_units;
    png_byte        sTER_mode;
    int             location[2];
-}
-user_chunk_data;
+} user_chunk_info;
 
 /* Used for location and order; zero means nothing. */
 #define have_sTER   0x01
@@ -653,37 +659,38 @@ user_chunk_data;
 #define after_IDAT  0x40
 
 static void
-init_callback_info(png_const_infop info_ptr)
+init_user_chunk_info(png_const_infop info_ptr, user_chunk_info *chunk_data)
 {
-   MEMZERO(user_chunk_data);
-   user_chunk_data.info_ptr = info_ptr;
+   memset(chunk_data, 0, sizeof(*chunk_data));
+   chunk_data->info_ptr = info_ptr;
 }
 
 static int
-set_location(png_structp png_ptr, struct user_chunk_data *data, int what)
+set_chunk_location(png_structp png_ptr, user_chunk_info *chunk_data, int what)
 {
    int location;
 
-   if ((data->location[0] & what) != 0 || (data->location[1] & what) != 0)
-      return 0; /* already have one of these */
+   if ((chunk_data->location[0] & what) != 0 ||
+       (chunk_data->location[1] & what) != 0)
+      return 0; /* we already have one of these */
 
    /* Find where we are (the code below zeroes info_ptr to indicate that the
     * chunks before the first IDAT have been read.)
     */
-   if (data->info_ptr == NULL) /* after IDAT */
+   if (chunk_data->info_ptr == NULL) /* after IDAT */
       location = what | after_IDAT;
 
-   else if (png_get_valid(png_ptr, data->info_ptr, PNG_INFO_PLTE) != 0)
+   else if (png_get_valid(png_ptr, chunk_data->info_ptr, PNG_INFO_PLTE) != 0)
       location = what | before_IDAT;
 
    else
       location = what | before_PLTE;
 
-   if (data->location[0] == 0)
-      data->location[0] = location;
+   if (chunk_data->location[0] == 0)
+      chunk_data->location[0] = location;
 
    else
-      data->location[1] = location;
+      chunk_data->location[1] = location;
 
    return 1; /* handled */
 }
@@ -691,16 +698,16 @@ set_location(png_structp png_ptr, struct user_chunk_data *data, int what)
 static int PNGCBAPI
 read_user_chunk_callback(png_struct *png_ptr, png_unknown_chunkp chunk)
 {
-   struct user_chunk_data *my_user_chunk_data =
-      (struct user_chunk_data*)png_get_user_chunk_ptr(png_ptr);
+   user_chunk_info *my_user_chunk_data =
+      (user_chunk_info*)png_get_user_chunk_ptr(png_ptr);
 
    if (my_user_chunk_data == NULL)
-      png_error(png_ptr, "lost user chunk pointer");
+      png_error(png_ptr, "lost pointer to user chunk data");
 
    /* Return one of the following:
-    *    return (-n);  chunk had an error
-    *    return (0);  did not recognize
-    *    return (n);  success
+    *    return -n;  chunk had an error
+    *    return 0;   did not recognize
+    *    return n;   success
     *
     * The unknown chunk structure contains the chunk data:
     * png_byte name[5];
@@ -715,54 +722,54 @@ read_user_chunk_callback(png_struct *png_ptr, png_unknown_chunkp chunk)
       {
          /* Found sTER chunk */
          if (chunk->size != 1)
-            return (-1); /* Error return */
+            return -1; /* Error return */
 
          if (chunk->data[0] != 0 && chunk->data[0] != 1)
-            return (-1);  /* Invalid mode */
+            return -1;  /* Invalid mode */
 
-         if (set_location(png_ptr, my_user_chunk_data, have_sTER) != 0)
+         if (set_chunk_location(png_ptr, my_user_chunk_data, have_sTER) != 0)
          {
-            my_user_chunk_data->sTER_mode=chunk->data[0];
-            return (1);
+            my_user_chunk_data->sTER_mode = chunk->data[0];
+            return 1;
          }
 
          else
-            return (0); /* duplicate sTER - give it to libpng */
+            return 0; /* duplicate sTER - give it to libpng */
       }
 
    if (chunk->name[0] != 118 || chunk->name[1] != 112 ||    /* v  p */
        chunk->name[2] !=  65 || chunk->name[3] != 103)      /* A  g */
-      return (0); /* Did not recognize */
+      return 0; /* Did not recognize */
 
    /* Found ImageMagick vpAg chunk */
 
    if (chunk->size != 9)
-      return (-1); /* Error return */
+      return -1; /* Error return */
 
-   if (set_location(png_ptr, my_user_chunk_data, have_vpAg) == 0)
-      return (0);  /* duplicate vpAg */
+   if (set_chunk_location(png_ptr, my_user_chunk_data, have_vpAg) == 0)
+      return 0;  /* duplicate vpAg */
 
    my_user_chunk_data->vpAg_width = png_get_uint_31(png_ptr, chunk->data);
    my_user_chunk_data->vpAg_height = png_get_uint_31(png_ptr, chunk->data + 4);
    my_user_chunk_data->vpAg_units = chunk->data[8];
 
-   return (1);
+   return 1;
 }
 
 #ifdef PNG_WRITE_SUPPORTED
 static void
-write_sTER_chunk(png_structp write_ptr)
+write_sTER_chunk(png_structp write_ptr, user_chunk_info *data)
 {
    png_byte sTER[5] = {115,  84,  69,  82, '\0'};
 
    if (verbose != 0)
-      fprintf(STDERR, "\n stereo mode = %d\n", user_chunk_data.sTER_mode);
+      fprintf(STDERR, "\n stereo mode = %d\n", data->sTER_mode);
 
-   png_write_chunk(write_ptr, sTER, &user_chunk_data.sTER_mode, 1);
+   png_write_chunk(write_ptr, sTER, &data->sTER_mode, 1);
 }
 
 static void
-write_vpAg_chunk(png_structp write_ptr)
+write_vpAg_chunk(png_structp write_ptr, user_chunk_info *data)
 {
    png_byte vpAg[5] = {118, 112,  65, 103, '\0'};
 
@@ -770,18 +777,18 @@ write_vpAg_chunk(png_structp write_ptr)
 
    if (verbose != 0)
       fprintf(STDERR, " vpAg = %lu x %lu, units = %d\n",
-          (unsigned long)user_chunk_data.vpAg_width,
-          (unsigned long)user_chunk_data.vpAg_height,
-          user_chunk_data.vpAg_units);
+          (unsigned long)data->vpAg_width,
+          (unsigned long)data->vpAg_height,
+          data->vpAg_units);
 
-   png_save_uint_32(vpag_chunk_data, user_chunk_data.vpAg_width);
-   png_save_uint_32(vpag_chunk_data + 4, user_chunk_data.vpAg_height);
-   vpag_chunk_data[8] = user_chunk_data.vpAg_units;
+   png_save_uint_32(vpag_chunk_data, data->vpAg_width);
+   png_save_uint_32(vpag_chunk_data + 4, data->vpAg_height);
+   vpag_chunk_data[8] = data->vpAg_units;
    png_write_chunk(write_ptr, vpAg, vpag_chunk_data, 9);
 }
 
 static void
-write_chunks(png_structp write_ptr, int location)
+write_chunks(png_structp write_ptr, user_chunk_info *data, int location)
 {
    int i;
 
@@ -791,13 +798,13 @@ write_chunks(png_structp write_ptr, int location)
     * vpAg chunks, resulting in an error later.  This is not worth worrying
     * about - the chunks should not be duplicated!
     */
-   for (i=0; i<2; ++i)
+   for (i = 0; i < 2; ++i)
    {
-      if (user_chunk_data.location[i] == (location | have_sTER))
-         write_sTER_chunk(write_ptr);
+      if (data->location[i] == (location | have_sTER))
+         write_sTER_chunk(write_ptr, data);
 
-      else if (user_chunk_data.location[i] == (location | have_vpAg))
-         write_vpAg_chunk(write_ptr);
+      else if (data->location[i] == (location | have_vpAg))
+         write_vpAg_chunk(write_ptr, data);
    }
 }
 #endif /* WRITE */
@@ -872,9 +879,9 @@ test_one_file(const char *inname, const char *outname)
    png_bytep row_buf;
    png_uint_32 y;
    png_uint_32 width, height;
-   volatile int num_passes;
-   int pass;
    int bit_depth, color_type;
+   user_chunk_info my_user_chunk_data;
+   int pass, num_passes;
 
    row_buf = NULL;
    error_parameters.file_name = inname;
@@ -882,14 +889,14 @@ test_one_file(const char *inname, const char *outname)
    if ((fpin = fopen(inname, "rb")) == NULL)
    {
       fprintf(STDERR, "Could not find input file %s\n", inname);
-      return (1);
+      return 1;
    }
 
    if ((fpout = fopen(outname, "wb")) == NULL)
    {
       fprintf(STDERR, "Could not open output file %s\n", outname);
-      FCLOSE(fpin);
-      return (1);
+      fclose(fpin);
+      return 1;
    }
 
    pngtest_debug("Allocating read and write structures");
@@ -925,8 +932,8 @@ test_one_file(const char *inname, const char *outname)
 #endif
 
 #ifdef PNG_READ_USER_CHUNKS_SUPPORTED
-   init_callback_info(read_info_ptr);
-   png_set_read_user_chunk_fn(read_ptr, &user_chunk_data,
+   init_user_chunk_info(read_info_ptr, &my_user_chunk_data);
+   png_set_read_user_chunk_fn(read_ptr, &my_user_chunk_data,
        read_user_chunk_callback);
 #endif
 
@@ -946,9 +953,9 @@ test_one_file(const char *inname, const char *outname)
       png_destroy_info_struct(write_ptr, &write_end_info_ptr);
       png_destroy_write_struct(&write_ptr, &write_info_ptr);
 #endif
-      FCLOSE(fpin);
-      FCLOSE(fpout);
-      return (1);
+      fclose(fpin);
+      fclose(fpout);
+      return 1;
    }
 
 #ifdef PNG_WRITE_SUPPORTED
@@ -966,9 +973,9 @@ test_one_file(const char *inname, const char *outname)
         fprintf(STDERR, "   destroying write structs\n");
       png_destroy_info_struct(write_ptr, &write_end_info_ptr);
       png_destroy_write_struct(&write_ptr, &write_info_ptr);
-      FCLOSE(fpin);
-      FCLOSE(fpout);
-      return (1);
+      fclose(fpin);
+      fclose(fpout);
+      return 1;
    }
 #endif
 #endif
@@ -1053,13 +1060,13 @@ test_one_file(const char *inname, const char *outname)
 #endif
 
 #ifdef PNG_SET_UNKNOWN_CHUNKS_SUPPORTED
-   /* Preserve all the unknown chunks, if possible.  If this is disabled then,
+   /* Preserve all the unknown chunks, if possible.  If this is disabled, then
     * even if the png_{get,set}_unknown_chunks stuff is enabled, we can't use
     * libpng to *save* the unknown chunks on read (because we can't switch the
     * save option on!)
     *
-    * Notice that if SET_UNKNOWN_CHUNKS is *not* supported read will discard all
-    * unknown chunks and write will write them all.
+    * Notice that if SET_UNKNOWN_CHUNKS is *not* supported, the reader will
+    * discard all unknown chunks, and the writer will write them all.
     */
 #ifdef PNG_SAVE_UNKNOWN_CHUNKS_SUPPORTED
    png_set_keep_unknown_chunks(read_ptr, PNG_HANDLE_CHUNK_ALWAYS,
@@ -1080,7 +1087,7 @@ test_one_file(const char *inname, const char *outname)
     * remove the info_ptr (which is only used to determine position relative to
     * PLTE) here to indicate that we are after the IDAT.
     */
-   user_chunk_data.info_ptr = NULL;
+   my_user_chunk_data.info_ptr = NULL;
 #endif
 
    pngtest_debug("Transferring info struct");
@@ -1196,14 +1203,12 @@ test_one_file(const char *inname, const char *outname)
       png_color_16p background;
 
       if (png_get_bKGD(read_ptr, read_info_ptr, &background) != 0)
-      {
          png_set_bKGD(write_ptr, write_info_ptr, background);
-      }
    }
 #endif
 #ifdef PNG_READ_eXIf_SUPPORTED
    {
-      png_bytep exif=NULL;
+      png_bytep exif = NULL;
       png_uint_32 exif_length;
 
       if (png_get_eXIf_1(read_ptr, read_info_ptr, &exif_length, &exif) != 0)
@@ -1232,9 +1237,7 @@ test_one_file(const char *inname, const char *outname)
 
       if (png_get_oFFs(read_ptr, read_info_ptr, &offset_x, &offset_y,
           &unit_type) != 0)
-      {
          png_set_oFFs(write_ptr, write_info_ptr, offset_x, offset_y, unit_type);
-      }
    }
 #endif
 #ifdef PNG_pCAL_SUPPORTED
@@ -1246,10 +1249,8 @@ test_one_file(const char *inname, const char *outname)
 
       if (png_get_pCAL(read_ptr, read_info_ptr, &purpose, &X0, &X1, &type,
           &nparams, &units, ¶ms) != 0)
-      {
          png_set_pCAL(write_ptr, write_info_ptr, purpose, X0, X1, type,
              nparams, units, params);
-      }
    }
 #endif
 #ifdef PNG_pHYs_SUPPORTED
@@ -1279,9 +1280,7 @@ test_one_file(const char *inname, const char *outname)
 
       if (png_get_sCAL(read_ptr, read_info_ptr, &unit, &scal_width,
           &scal_height) != 0)
-      {
          png_set_sCAL(write_ptr, write_info_ptr, unit, scal_width, scal_height);
-      }
    }
 #else
 #ifdef PNG_FIXED_POINT_SUPPORTED
@@ -1304,11 +1303,9 @@ test_one_file(const char *inname, const char *outname)
    {
        png_sPLT_tp entries;
 
-       int num_entries = (int) png_get_sPLT(read_ptr, read_info_ptr, &entries);
-       if (num_entries)
-       {
+       int num_entries = png_get_sPLT(read_ptr, read_info_ptr, &entries);
+       if (num_entries != 0)
            png_set_sPLT(write_ptr, write_info_ptr, entries, num_entries);
-       }
    }
 #endif
 
@@ -1328,7 +1325,7 @@ test_one_file(const char *inname, const char *outname)
             int i;
 
             fprintf(STDERR,"\n");
-            for (i=0; iinterlaced != 0)
    {
       png_ptr->transformations |= PNG_INTERLACE;
-      return (7);
+      return 7;
    }
 
-   return (1);
+   return 1;
 }
 #endif
 
@@ -498,6 +498,8 @@ png_do_strip_channel(png_row_infop row_info, png_bytep row, int at_start)
    png_bytep dp = row; /* destination pointer */
    png_bytep ep = row + row_info->rowbytes; /* One beyond end of row */
 
+   png_debug(1, "in png_do_strip_channel");
+
    /* At the start sp will point to the first byte to copy and dp to where
     * it is copied to.  ep always points just beyond the end of the row, so
     * the loop simply copies (channels-1) channels until sp reaches ep.
@@ -698,6 +700,8 @@ png_do_bgr(png_row_infop row_info, png_bytep row)
 void /* PRIVATE */
 png_do_check_palette_indexes(png_structrp png_ptr, png_row_infop row_info)
 {
+   png_debug(1, "in png_do_check_palette_indexes");
+
    if (png_ptr->num_palette < (1 << row_info->bit_depth) &&
       png_ptr->num_palette > 0) /* num_palette can be 0 in MNG files */
    {
@@ -708,7 +712,7 @@ png_do_check_palette_indexes(png_structrp png_ptr, png_row_infop row_info)
        * forms produced on either GCC or MSVC.
        */
       int padding = PNG_PADBITS(row_info->pixel_depth, row_info->width);
-      png_bytep rp = png_ptr->row_buf + row_info->rowbytes - 1;
+      png_bytep rp = png_ptr->row_buf + row_info->rowbytes;
 
       switch (row_info->bit_depth)
       {
@@ -833,7 +837,7 @@ png_voidp PNGAPI
 png_get_user_transform_ptr(png_const_structrp png_ptr)
 {
    if (png_ptr == NULL)
-      return (NULL);
+      return NULL;
 
    return png_ptr->user_transform_ptr;
 }
diff --git a/vendor/libpng/pngwrite.c b/vendor/libpng/pngwrite.c
index 32f4bfbe7d..77e412f43d 100644
--- a/vendor/libpng/pngwrite.c
+++ b/vendor/libpng/pngwrite.c
@@ -1,7 +1,7 @@
 
 /* pngwrite.c - general routines to write a PNG file
  *
- * Copyright (c) 2018-2023 Cosmin Truta
+ * Copyright (c) 2018-2024 Cosmin Truta
  * Copyright (c) 1998-2002,2004,2006-2018 Glenn Randers-Pehrson
  * Copyright (c) 1996-1997 Andreas Dilger
  * Copyright (c) 1995-1996 Guy Eric Schalnat, Group 42, Inc.
@@ -369,7 +369,8 @@ png_write_end(png_structrp png_ptr, png_inforp info_ptr)
       png_error(png_ptr, "No IDATs written into file");
 
 #ifdef PNG_WRITE_CHECK_FOR_INVALID_INDEX_SUPPORTED
-   if (png_ptr->num_palette_max > png_ptr->num_palette)
+   if (png_ptr->color_type == PNG_COLOR_TYPE_PALETTE &&
+       png_ptr->num_palette_max >= png_ptr->num_palette)
       png_benign_error(png_ptr, "Wrote palette index exceeding num_palette");
 #endif
 
@@ -714,12 +715,12 @@ png_write_row(png_structrp png_ptr, png_const_bytep row)
    /* 1.5.6: moved from png_struct to be a local structure: */
    png_row_info row_info;
 
-   if (png_ptr == NULL)
-      return;
-
    png_debug2(1, "in png_write_row (row %u, pass %d)",
        png_ptr->row_number, png_ptr->pass);
 
+   if (png_ptr == NULL)
+      return;
+
    /* Initialize transformations and other stuff if first time */
    if (png_ptr->row_number == 0 && png_ptr->pass == 0)
    {
@@ -1210,6 +1211,8 @@ png_set_compression_strategy(png_structrp png_ptr, int strategy)
 void PNGAPI
 png_set_compression_window_bits(png_structrp png_ptr, int window_bits)
 {
+   png_debug(1, "in png_set_compression_window_bits");
+
    if (png_ptr == NULL)
       return;
 
@@ -1293,6 +1296,8 @@ png_set_text_compression_strategy(png_structrp png_ptr, int strategy)
 void PNGAPI
 png_set_text_compression_window_bits(png_structrp png_ptr, int window_bits)
 {
+   png_debug(1, "in png_set_text_compression_window_bits");
+
    if (png_ptr == NULL)
       return;
 
@@ -1330,6 +1335,8 @@ png_set_text_compression_method(png_structrp png_ptr, int method)
 void PNGAPI
 png_set_write_status_fn(png_structrp png_ptr, png_write_status_ptr write_row_fn)
 {
+   png_debug(1, "in png_set_write_status_fn");
+
    if (png_ptr == NULL)
       return;
 
@@ -1357,6 +1364,8 @@ void PNGAPI
 png_write_png(png_structrp png_ptr, png_inforp info_ptr,
     int transforms, voidp params)
 {
+   png_debug(1, "in png_write_png");
+
    if (png_ptr == NULL || info_ptr == NULL)
       return;
 
diff --git a/vendor/libpng/pngwutil.c b/vendor/libpng/pngwutil.c
index 01f0607c70..14cc4ce367 100644
--- a/vendor/libpng/pngwutil.c
+++ b/vendor/libpng/pngwutil.c
@@ -1,7 +1,7 @@
 
 /* pngwutil.c - utilities to write a PNG file
  *
- * Copyright (c) 2018-2022 Cosmin Truta
+ * Copyright (c) 2018-2024 Cosmin Truta
  * Copyright (c) 1998-2002,2004,2006-2018 Glenn Randers-Pehrson
  * Copyright (c) 1996-1997 Andreas Dilger
  * Copyright (c) 1995-1996 Guy Eric Schalnat, Group 42, Inc.
@@ -2311,7 +2311,7 @@ png_setup_sub_row(png_structrp png_ptr, png_uint_32 bpp,
         break;
    }
 
-   return (sum);
+   return sum;
 }
 
 static void /* PRIVATE */
@@ -2361,7 +2361,7 @@ png_setup_up_row(png_structrp png_ptr, size_t row_bytes, size_t lmins)
         break;
    }
 
-   return (sum);
+   return sum;
 }
 static void /* PRIVATE */
 png_setup_up_row_only(png_structrp png_ptr, size_t row_bytes)
@@ -2417,7 +2417,7 @@ png_setup_avg_row(png_structrp png_ptr, png_uint_32 bpp,
         break;
    }
 
-   return (sum);
+   return sum;
 }
 static void /* PRIVATE */
 png_setup_avg_row_only(png_structrp png_ptr, png_uint_32 bpp,
@@ -2500,7 +2500,7 @@ png_setup_paeth_row(png_structrp png_ptr, png_uint_32 bpp,
         break;
    }
 
-   return (sum);
+   return sum;
 }
 static void /* PRIVATE */
 png_setup_paeth_row_only(png_structrp png_ptr, png_uint_32 bpp,
diff --git a/vendor/libspeex/libspeex/_kiss_fft_guts.h b/vendor/libspeex/libspeex/_kiss_fft_guts.h
index 6571e79c0c..f5f2a5fd76 100644
--- a/vendor/libspeex/libspeex/_kiss_fft_guts.h
+++ b/vendor/libspeex/libspeex/_kiss_fft_guts.h
@@ -23,7 +23,7 @@ THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
 #include "math_approx.h"
 
 #define MAXFACTORS 32
-/* e.g. an fft of length 128 has 4 factors 
+/* e.g. an fft of length 128 has 4 factors
  as far as kissfft is concerned
  4*4*4*2
  */
@@ -47,7 +47,7 @@ struct kiss_fft_state{
 #ifdef FIXED_POINT
 #include "arch.h"
 # define FRACBITS 15
-# define SAMPPROD spx_int32_t 
+# define SAMPPROD spx_int32_t
 #define SAMP_MAX 32767
 
 #define SAMP_MIN -SAMP_MAX
diff --git a/vendor/libspeex/libspeex/arch.h b/vendor/libspeex/libspeex/arch.h
index 291cab828c..807469ddb2 100644
--- a/vendor/libspeex/libspeex/arch.h
+++ b/vendor/libspeex/libspeex/arch.h
@@ -7,18 +7,18 @@
    Redistribution and use in source and binary forms, with or without
    modification, are permitted provided that the following conditions
    are met:
-   
+
    - Redistributions of source code must retain the above copyright
    notice, this list of conditions and the following disclaimer.
-   
+
    - Redistributions in binary form must reproduce the above copyright
    notice, this list of conditions and the following disclaimer in the
    documentation and/or other materials provided with the distribution.
-   
+
    - Neither the name of the Xiph.org Foundation nor the names of its
    contributors may be used to endorse or promote products derived from
    this software without specific prior written permission.
-   
+
    THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
    ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
    LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
@@ -37,10 +37,10 @@
 
 #ifndef SPEEX_VERSION
 #define SPEEX_MAJOR_VERSION 1         /**< Major Speex version. */
-#define SPEEX_MINOR_VERSION 1         /**< Minor Speex version. */
-#define SPEEX_MICRO_VERSION 16        /**< Micro Speex version. */
+#define SPEEX_MINOR_VERSION 2         /**< Minor Speex version. */
+#define SPEEX_MICRO_VERSION 1         /**< Micro Speex version. */
 #define SPEEX_EXTRA_VERSION ""        /**< Extra Speex version. */
-#define SPEEX_VERSION "speex-1.2.0"   /**< Speex version string. */
+#define SPEEX_VERSION "speex-1.2.1"   /**< Speex version string. */
 #endif
 
 /* A couple test to catch stupid option combinations */
@@ -215,11 +215,11 @@ typedef float spx_word32_t;
 #if defined (CONFIG_TI_C54X) || defined (CONFIG_TI_C55X)
 
 /* 2 on TI C5x DSP */
-#define BYTES_PER_CHAR 2 
+#define BYTES_PER_CHAR 2
 #define BITS_PER_CHAR 16
 #define LOG2_BITS_PER_CHAR 4
 
-#else 
+#else
 
 #define BYTES_PER_CHAR 1
 #define BITS_PER_CHAR 8
diff --git a/vendor/libspeex/libspeex/bits.c b/vendor/libspeex/libspeex/bits.c
index 2d782a2def..4f457af111 100644
--- a/vendor/libspeex/libspeex/bits.c
+++ b/vendor/libspeex/libspeex/bits.c
@@ -275,7 +275,7 @@ EXPORT int speex_bits_unpack_signed(SpeexBits *bits, int nbBits)
    /* If number is negative */
    if (d>>(nbBits-1))
    {
-      d |= (-1)<max_val)
+         max_val = in[i];
+      if (-in[i]>max_val)
+         max_val = -in[i];
+   }
+   shift=0;
+   while (max_val <= (bound>>1) && max_val != 0)
+   {
+      max_val <<= 1;
+      shift++;
+   }
+   for (i=0;i
+
+void *spx_fft_init(int size)
+{
+   struct drft_lookup *table;
+   table = speex_alloc(sizeof(struct drft_lookup));
+   spx_drft_init((struct drft_lookup *)table, size);
+   return (void*)table;
+}
+
+void spx_fft_destroy(void *table)
+{
+   spx_drft_clear(table);
+   speex_free(table);
+}
+
+void spx_fft(void *table, float *in, float *out)
+{
+   if (in==out)
+   {
+      int i;
+      float scale = 1./((struct drft_lookup *)table)->n;
+      speex_warning("FFT should not be done in-place");
+      for (i=0;i<((struct drft_lookup *)table)->n;i++)
+         out[i] = scale*in[i];
+   } else {
+      int i;
+      float scale = 1./((struct drft_lookup *)table)->n;
+      for (i=0;i<((struct drft_lookup *)table)->n;i++)
+         out[i] = scale*in[i];
+   }
+   spx_drft_forward((struct drft_lookup *)table, out);
+}
+
+void spx_ifft(void *table, float *in, float *out)
+{
+   if (in==out)
+   {
+      speex_warning("FFT should not be done in-place");
+   } else {
+      int i;
+      for (i=0;i<((struct drft_lookup *)table)->n;i++)
+         out[i] = in[i];
+   }
+   spx_drft_backward((struct drft_lookup *)table, out);
+}
+
+#elif defined(USE_INTEL_MKL)
+#include 
+
+struct mkl_config {
+  DFTI_DESCRIPTOR_HANDLE desc;
+  int N;
+};
+
+void *spx_fft_init(int size)
+{
+  struct mkl_config *table = (struct mkl_config *) speex_alloc(sizeof(struct mkl_config));
+  table->N = size;
+  DftiCreateDescriptor(&table->desc, DFTI_SINGLE, DFTI_REAL, 1, size);
+  DftiSetValue(table->desc, DFTI_PACKED_FORMAT, DFTI_PACK_FORMAT);
+  DftiSetValue(table->desc, DFTI_PLACEMENT, DFTI_NOT_INPLACE);
+  DftiSetValue(table->desc, DFTI_FORWARD_SCALE, 1.0f / size);
+  DftiCommitDescriptor(table->desc);
+  return table;
+}
+
+void spx_fft_destroy(void *table)
+{
+  struct mkl_config *t = (struct mkl_config *) table;
+  DftiFreeDescriptor(t->desc);
+  speex_free(table);
+}
+
+void spx_fft(void *table, spx_word16_t *in, spx_word16_t *out)
+{
+  struct mkl_config *t = (struct mkl_config *) table;
+  DftiComputeForward(t->desc, in, out);
+}
+
+void spx_ifft(void *table, spx_word16_t *in, spx_word16_t *out)
+{
+  struct mkl_config *t = (struct mkl_config *) table;
+  DftiComputeBackward(t->desc, in, out);
+}
+
+#elif defined(USE_INTEL_IPP)
+
+#include 
+
+struct ipp_fft_config
+{
+  IppsDFTSpec_R_32f *dftSpec;
+  Ipp8u *buffer;
+};
+
+void *spx_fft_init(int size)
+{
+  int bufferSize = 0;
+  int hint;
+  struct ipp_fft_config *table;
+
+  table = (struct ipp_fft_config *)speex_alloc(sizeof(struct ipp_fft_config));
+
+  /* there appears to be no performance difference between ippAlgHintFast and
+     ippAlgHintAccurate when using the with the floating point version
+     of the fft. */
+  hint = ippAlgHintAccurate;
+
+  ippsDFTInitAlloc_R_32f(&table->dftSpec, size, IPP_FFT_DIV_FWD_BY_N, hint);
+
+  ippsDFTGetBufSize_R_32f(table->dftSpec, &bufferSize);
+  table->buffer = ippsMalloc_8u(bufferSize);
+
+  return table;
+}
+
+void spx_fft_destroy(void *table)
+{
+  struct ipp_fft_config *t = (struct ipp_fft_config *)table;
+  ippsFree(t->buffer);
+  ippsDFTFree_R_32f(t->dftSpec);
+  speex_free(t);
+}
+
+void spx_fft(void *table, spx_word16_t *in, spx_word16_t *out)
+{
+  struct ipp_fft_config *t = (struct ipp_fft_config *)table;
+  ippsDFTFwd_RToPack_32f(in, out, t->dftSpec, t->buffer);
+}
+
+void spx_ifft(void *table, spx_word16_t *in, spx_word16_t *out)
+{
+  struct ipp_fft_config *t = (struct ipp_fft_config *)table;
+  ippsDFTInv_PackToR_32f(in, out, t->dftSpec, t->buffer);
+}
+
+#elif defined(USE_GPL_FFTW3)
+
+#include 
+
+struct fftw_config {
+  float *in;
+  float *out;
+  fftwf_plan fft;
+  fftwf_plan ifft;
+  int N;
+};
+
+void *spx_fft_init(int size)
+{
+  struct fftw_config *table = (struct fftw_config *) speex_alloc(sizeof(struct fftw_config));
+  table->in = fftwf_malloc(sizeof(float) * (size+2));
+  table->out = fftwf_malloc(sizeof(float) * (size+2));
+
+  table->fft = fftwf_plan_dft_r2c_1d(size, table->in, (fftwf_complex *) table->out, FFTW_PATIENT);
+  table->ifft = fftwf_plan_dft_c2r_1d(size, (fftwf_complex *) table->in, table->out, FFTW_PATIENT);
+
+  table->N = size;
+  return table;
+}
+
+void spx_fft_destroy(void *table)
+{
+  struct fftw_config *t = (struct fftw_config *) table;
+  fftwf_destroy_plan(t->fft);
+  fftwf_destroy_plan(t->ifft);
+  fftwf_free(t->in);
+  fftwf_free(t->out);
+  speex_free(table);
+}
+
+
+void spx_fft(void *table, spx_word16_t *in, spx_word16_t *out)
+{
+  int i;
+  struct fftw_config *t = (struct fftw_config *) table;
+  const int N = t->N;
+  float *iptr = t->in;
+  float *optr = t->out;
+  const float m = 1.0 / N;
+  for(i=0;ifft);
+
+  out[0] = optr[0];
+  for(i=1;iN;
+  float *iptr = t->in;
+  float *optr = t->out;
+
+  iptr[0] = in[0];
+  iptr[1] = 0.0f;
+  for(i=1;iifft);
+
+  for(i=0;iforward = kiss_fftr_alloc(size,0,NULL,NULL);
+   table->backward = kiss_fftr_alloc(size,1,NULL,NULL);
+   table->N = size;
+   return table;
+}
+
+void spx_fft_destroy(void *table)
+{
+   struct kiss_config *t = (struct kiss_config *)table;
+   kiss_fftr_free(t->forward);
+   kiss_fftr_free(t->backward);
+   speex_free(table);
+}
+
+#ifdef FIXED_POINT
+
+void spx_fft(void *table, spx_word16_t *in, spx_word16_t *out)
+{
+   int shift;
+   struct kiss_config *t = (struct kiss_config *)table;
+   shift = maximize_range(in, in, 32000, t->N);
+   kiss_fftr2(t->forward, in, out);
+   renorm_range(in, in, shift, t->N);
+   renorm_range(out, out, shift, t->N);
+}
+
+#else
+
+void spx_fft(void *table, spx_word16_t *in, spx_word16_t *out)
+{
+   int i;
+   float scale;
+   struct kiss_config *t = (struct kiss_config *)table;
+   scale = 1./t->N;
+   kiss_fftr2(t->forward, in, out);
+   for (i=0;iN;i++)
+      out[i] *= scale;
+}
+#endif
+
+void spx_ifft(void *table, spx_word16_t *in, spx_word16_t *out)
+{
+   struct kiss_config *t = (struct kiss_config *)table;
+   kiss_fftri2(t->backward, in, out);
+}
+
+
+#else
+
+#error No other FFT implemented
+
+#endif
+
+
+#ifdef FIXED_POINT
+/*#include "smallft.h"*/
+
+
+void spx_fft_float(void *table, float *in, float *out)
+{
+   int i;
+#ifdef USE_SMALLFT
+   int N = ((struct drft_lookup *)table)->n;
+#elif defined(USE_KISS_FFT)
+   int N = ((struct kiss_config *)table)->N;
+#else
+#endif
+#ifdef VAR_ARRAYS
+   spx_word16_t _in[N];
+   spx_word16_t _out[N];
+#else
+   spx_word16_t _in[MAX_FFT_SIZE];
+   spx_word16_t _out[MAX_FFT_SIZE];
+#endif
+   for (i=0;iN);
+      scale = 1./((struct kiss_config *)table)->N;
+      for (i=0;i<((struct kiss_config *)table)->N;i++)
+         out[i] = scale*in[i];
+      spx_drft_forward(&t, out);
+      spx_drft_clear(&t);
+   }
+#endif
+}
+
+void spx_ifft_float(void *table, float *in, float *out)
+{
+   int i;
+#ifdef USE_SMALLFT
+   int N = ((struct drft_lookup *)table)->n;
+#elif defined(USE_KISS_FFT)
+   int N = ((struct kiss_config *)table)->N;
+#else
+#endif
+#ifdef VAR_ARRAYS
+   spx_word16_t _in[N];
+   spx_word16_t _out[N];
+#else
+   spx_word16_t _in[MAX_FFT_SIZE];
+   spx_word16_t _out[MAX_FFT_SIZE];
+#endif
+   for (i=0;iN);
+      for (i=0;i<((struct kiss_config *)table)->N;i++)
+         out[i] = in[i];
+      spx_drft_backward(&t, out);
+      spx_drft_clear(&t);
+   }
+#endif
+}
+
+#else
+
+void spx_fft_float(void *table, float *in, float *out)
+{
+   spx_fft(table, in, out);
+}
+void spx_ifft_float(void *table, float *in, float *out)
+{
+   spx_ifft(table, in, out);
+}
+
+#endif
diff --git a/vendor/libspeex/libspeex/fftwrap.h b/vendor/libspeex/libspeex/fftwrap.h
index dfaf489441..2c0742559c 100644
--- a/vendor/libspeex/libspeex/fftwrap.h
+++ b/vendor/libspeex/libspeex/fftwrap.h
@@ -1,23 +1,23 @@
-/* Copyright (C) 2005 Jean-Marc Valin 
+/* Copyright (C) 2005 Jean-Marc Valin
    File: fftwrap.h
 
-   Wrapper for various FFTs 
+   Wrapper for various FFTs
 
    Redistribution and use in source and binary forms, with or without
    modification, are permitted provided that the following conditions
    are met:
-   
+
    - Redistributions of source code must retain the above copyright
    notice, this list of conditions and the following disclaimer.
-   
+
    - Redistributions in binary form must reproduce the above copyright
    notice, this list of conditions and the following disclaimer in the
    documentation and/or other materials provided with the distribution.
-   
+
    - Neither the name of the Xiph.org Foundation nor the names of its
    contributors may be used to endorse or promote products derived from
    this software without specific prior written permission.
-   
+
    THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
    ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
    LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
diff --git a/vendor/libspeex/libspeex/filters.h b/vendor/libspeex/libspeex/filters.h
index df148510c3..455365a661 100644
--- a/vendor/libspeex/libspeex/filters.h
+++ b/vendor/libspeex/libspeex/filters.h
@@ -7,18 +7,18 @@
    Redistribution and use in source and binary forms, with or without
    modification, are permitted provided that the following conditions
    are met:
-   
+
    - Redistributions of source code must retain the above copyright
    notice, this list of conditions and the following disclaimer.
-   
+
    - Redistributions in binary form must reproduce the above copyright
    notice, this list of conditions and the following disclaimer in the
    documentation and/or other materials provided with the distribution.
-   
+
    - Neither the name of the Xiph.org Foundation nor the names of its
    contributors may be used to endorse or promote products derived from
    this software without specific prior written permission.
-   
+
    THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
    ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
    LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
diff --git a/vendor/libspeex/libspeex/filters_arm4.h b/vendor/libspeex/libspeex/filters_arm4.h
index 2c64625c30..ed5a4f1493 100644
--- a/vendor/libspeex/libspeex/filters_arm4.h
+++ b/vendor/libspeex/libspeex/filters_arm4.h
@@ -7,18 +7,18 @@
    Redistribution and use in source and binary forms, with or without
    modification, are permitted provided that the following conditions
    are met:
-   
+
    - Redistributions of source code must retain the above copyright
    notice, this list of conditions and the following disclaimer.
-   
+
    - Redistributions in binary form must reproduce the above copyright
    notice, this list of conditions and the following disclaimer in the
    documentation and/or other materials provided with the distribution.
-   
+
    - Neither the name of the Xiph.org Foundation nor the names of its
    contributors may be used to endorse or promote products derived from
    this software without specific prior written permission.
-   
+
    THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
    ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
    LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
@@ -68,7 +68,7 @@ int normalize16(const spx_sig_t *x, spx_word16_t *y, spx_sig_t max_scale, int le
       sig_shift++;
       max_val >>= 1;
    }
-   
+
    __asm__ __volatile__ (
          ".normalize16loop%=: \n"
 
diff --git a/vendor/libspeex/libspeex/filters_bfin.h b/vendor/libspeex/libspeex/filters_bfin.h
index ccd57b9d1d..a9bc0d2bc6 100644
--- a/vendor/libspeex/libspeex/filters_bfin.h
+++ b/vendor/libspeex/libspeex/filters_bfin.h
@@ -7,18 +7,18 @@
    Redistribution and use in source and binary forms, with or without
    modification, are permitted provided that the following conditions
    are met:
-   
+
    - Redistributions of source code must retain the above copyright
    notice, this list of conditions and the following disclaimer.
-   
+
    - Redistributions in binary form must reproduce the above copyright
    notice, this list of conditions and the following disclaimer in the
    documentation and/or other materials provided with the distribution.
-   
+
    - Neither the name of the Xiph.org Foundation nor the names of its
    contributors may be used to endorse or promote products derived from
    this software without specific prior written permission.
-   
+
    THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
    ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
    LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
@@ -39,7 +39,7 @@ int normalize16(const spx_sig_t *x, spx_word16_t *y, spx_sig_t max_scale, int le
 {
    spx_sig_t max_val=1;
    int sig_shift;
-   __asm__ 
+   __asm__
    (
    "%0 = 0;\n\t"
    "I0 = %1;\n\t"
@@ -62,7 +62,7 @@ int normalize16(const spx_sig_t *x, spx_word16_t *y, spx_sig_t max_scale, int le
       max_val >>= 1;
    }
 
-   __asm__ __volatile__ 
+   __asm__ __volatile__
    (
    "I0 = %0;\n\t"
    "L0 = 0;\n\t"
@@ -94,7 +94,7 @@ void filter_mem16(const spx_word16_t *_x, const spx_coef_t *num, const spx_coef_
 
    ALLOC(xy2, (N+1), spx_word32_t);
    ALLOC(numden_a, (2*ord+2), spx_word32_t);
-   xy = xy2+1;  
+   xy = xy2+1;
    numden = (spx_word16_t*) numden_a;
 
    for (i=0;i=(EXTEND32(1)<<(15+Q)))
-      fprintf (stderr, "MULT16_32_Q%d: second operand too large: %d %d in %s: line %d\n", Q, (int)a, (int)b, file, line);      
+      fprintf (stderr, "MULT16_32_Q%d: second operand too large: %d %d in %s: line %d\n", Q, (int)a, (int)b, file, line);
    res = (((long long)a)*(long long)b) >> Q;
    if (!VERIFY_INT(res))
       fprintf (stderr, "MULT16_32_Q%d: output is not int: %d*%d=%d in %s: line %d\n", Q, (int)a, (int)b,(int)res, file, line);
@@ -296,7 +296,7 @@ static inline int MULT16_32_PX(int a, long long b, int Q)
       fprintf (stderr, "MULT16_32_P%d: inputs are not short+int: %d %d\n", Q, (int)a, (int)b);
    }
    if (ABS32(b)>=(EXTEND32(1)<<(15+Q)))
-      fprintf (stderr, "MULT16_32_Q%d: second operand too large: %d %d\n", Q, (int)a, (int)b);      
+      fprintf (stderr, "MULT16_32_Q%d: second operand too large: %d %d\n", Q, (int)a, (int)b);
    res = ((((long long)a)*(long long)b) + ((EXTEND32(1)<>1))>> Q;
    if (!VERIFY_INT(res))
       fprintf (stderr, "MULT16_32_P%d: output is not int: %d*%d=%d\n", Q, (int)a, (int)b,(int)res);
@@ -323,7 +323,7 @@ static inline int SATURATE(int a, int b)
    return a;
 }
 
-static inline int MULT16_16_Q11_32(int a, int b) 
+static inline int MULT16_16_Q11_32(int a, int b)
 {
    long long res;
    if (!VERIFY_SHORT(a) || !VERIFY_SHORT(b))
@@ -337,7 +337,7 @@ static inline int MULT16_16_Q11_32(int a, int b)
    spx_mips+=3;
    return res;
 }
-static inline short MULT16_16_Q13(int a, int b) 
+static inline short MULT16_16_Q13(int a, int b)
 {
    long long res;
    if (!VERIFY_SHORT(a) || !VERIFY_SHORT(b))
@@ -351,7 +351,7 @@ static inline short MULT16_16_Q13(int a, int b)
    spx_mips+=3;
    return res;
 }
-static inline short MULT16_16_Q14(int a, int b) 
+static inline short MULT16_16_Q14(int a, int b)
 {
    long long res;
    if (!VERIFY_SHORT(a) || !VERIFY_SHORT(b))
@@ -365,7 +365,7 @@ static inline short MULT16_16_Q14(int a, int b)
    spx_mips+=3;
    return res;
 }
-static inline short MULT16_16_Q15(int a, int b) 
+static inline short MULT16_16_Q15(int a, int b)
 {
    long long res;
    if (!VERIFY_SHORT(a) || !VERIFY_SHORT(b))
@@ -382,7 +382,7 @@ static inline short MULT16_16_Q15(int a, int b)
    return res;
 }
 
-static inline short MULT16_16_P13(int a, int b) 
+static inline short MULT16_16_P13(int a, int b)
 {
    long long res;
    if (!VERIFY_SHORT(a) || !VERIFY_SHORT(b))
@@ -399,7 +399,7 @@ static inline short MULT16_16_P13(int a, int b)
    spx_mips+=4;
    return res;
 }
-static inline short MULT16_16_P14(int a, int b) 
+static inline short MULT16_16_P14(int a, int b)
 {
    long long res;
    if (!VERIFY_SHORT(a) || !VERIFY_SHORT(b))
@@ -416,7 +416,7 @@ static inline short MULT16_16_P14(int a, int b)
    spx_mips+=4;
    return res;
 }
-static inline short MULT16_16_P15(int a, int b) 
+static inline short MULT16_16_P15(int a, int b)
 {
    long long res;
    if (!VERIFY_SHORT(a) || !VERIFY_SHORT(b))
@@ -436,7 +436,7 @@ static inline short MULT16_16_P15(int a, int b)
 
 #define DIV32_16(a, b) _DIV32_16(a, b, __FILE__, __LINE__)
 
-static inline int _DIV32_16(long long a, long long b, char *file, int line) 
+static inline int _DIV32_16(long long a, long long b, char *file, int line)
 {
    long long res;
    if (b==0)
@@ -462,7 +462,7 @@ static inline int _DIV32_16(long long a, long long b, char *file, int line)
 }
 
 #define DIV32(a, b) _DIV32(a, b, __FILE__, __LINE__)
-static inline int _DIV32(long long a, long long b, char *file, int line) 
+static inline int _DIV32(long long a, long long b, char *file, int line)
 {
    long long res;
    if (b==0)
diff --git a/vendor/libspeex/libspeex/fixed_generic.h b/vendor/libspeex/libspeex/fixed_generic.h
index 3fb096ed90..bb320e301e 100644
--- a/vendor/libspeex/libspeex/fixed_generic.h
+++ b/vendor/libspeex/libspeex/fixed_generic.h
@@ -7,18 +7,18 @@
    Redistribution and use in source and binary forms, with or without
    modification, are permitted provided that the following conditions
    are met:
-   
+
    - Redistributions of source code must retain the above copyright
    notice, this list of conditions and the following disclaimer.
-   
+
    - Redistributions in binary form must reproduce the above copyright
    notice, this list of conditions and the following disclaimer in the
    documentation and/or other materials provided with the distribution.
-   
+
    - Neither the name of the Xiph.org Foundation nor the names of its
    contributors may be used to endorse or promote products derived from
    this software without specific prior written permission.
-   
+
    THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
    ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
    LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
@@ -43,9 +43,9 @@
 #define EXTRACT16(x) ((spx_word16_t)(x))
 #define EXTEND32(x) ((spx_word32_t)(x))
 #define SHR16(a,shift) ((a) >> (shift))
-#define SHL16(a,shift) ((a) << (shift))
+#define SHL16(a,shift) ((spx_int16_t)((spx_uint16_t)(a) << (shift)))
 #define SHR32(a,shift) ((a) >> (shift))
-#define SHL32(a,shift) ((a) << (shift))
+#define SHL32(a,shift) ((spx_int32_t)((spx_uint32_t)(a) << (shift)))
 #define PSHR16(a,shift) (SHR16((a)+((1<<((shift))>>1)),shift))
 #define PSHR32(a,shift) (SHR32((a)+((EXTEND32(1)<<((shift))>>1)),shift))
 #define VSHR32(a, shift) (((shift)>0) ? SHR32(a, shift) : SHL32(a, -(shift)))
@@ -53,7 +53,7 @@
 #define SATURATE32(x,a) (((x)>(a) ? (a) : (x)<-(a) ? -(a) : (x)))
 
 #define SHR(a,shift) ((a) >> (shift))
-#define SHL(a,shift) ((spx_word32_t)(a) << (shift))
+#define SHL(a,shift) ((spx_int32_t)((spx_uint32_t)(a) << (shift)))
 #define PSHR(a,shift) (SHR((a)+((EXTEND32(1)<<((shift))>>1)),shift))
 #define SATURATE(x,a) (((x)>(a) ? (a) : (x)<-(a) ? -(a) : (x)))
 
diff --git a/vendor/libspeex/libspeex/kiss_fft.c b/vendor/libspeex/libspeex/kiss_fft.c
index 285e557983..8dc9345428 100644
--- a/vendor/libspeex/libspeex/kiss_fft.c
+++ b/vendor/libspeex/libspeex/kiss_fft.c
@@ -23,7 +23,7 @@ THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
 #include "os_support.h"
 
 /* The guts header contains all the multiplication and addition macros that are defined for
- fixed or floating point complex numbers.  It also delares the kf_ internal functions.
+ fixed or floating point complex numbers.  It also declares the kf_ internal functions.
  */
 
 static void kf_bfly2(
diff --git a/vendor/libspeex/libspeex/kiss_fft.h b/vendor/libspeex/libspeex/kiss_fft.h
index fa3f2c6042..bb19eadbd9 100644
--- a/vendor/libspeex/libspeex/kiss_fft.h
+++ b/vendor/libspeex/libspeex/kiss_fft.h
@@ -26,13 +26,13 @@ extern "C" {
 # include 
 # define kiss_fft_scalar __m128
 #define KISS_FFT_MALLOC(nbytes) memalign(16,nbytes)
-#else	
+#else
 #define KISS_FFT_MALLOC speex_alloc
-#endif	
+#endif
 
 
 #ifdef FIXED_POINT
-#include "arch.h"	
+#include "arch.h"
 #  define kiss_fft_scalar spx_int16_t
 #else
 # ifndef kiss_fft_scalar
@@ -48,9 +48,9 @@ typedef struct {
 
 typedef struct kiss_fft_state* kiss_fft_cfg;
 
-/* 
+/*
  *  kiss_fft_alloc
- *  
+ *
  *  Initialize a FFT (or IFFT) algorithm's cfg/state buffer.
  *
  *  typical usage:      kiss_fft_cfg mycfg=kiss_fft_alloc(1024,0,NULL,NULL);
@@ -60,18 +60,18 @@ typedef struct kiss_fft_state* kiss_fft_cfg;
  *
  *  If lenmem is NULL, then kiss_fft_alloc will allocate a cfg buffer using malloc.
  *  The returned value should be free()d when done to avoid memory leaks.
- *  
+ *
  *  The state can be placed in a user supplied buffer 'mem':
  *  If lenmem is not NULL and mem is not NULL and *lenmem is large enough,
  *      then the function places the cfg in mem and the size used in *lenmem
  *      and returns mem.
- *  
+ *
  *  If lenmem is not NULL and ( mem is NULL or *lenmem is not large enough),
- *      then the function returns NULL and places the minimum cfg 
+ *      then the function returns NULL and places the minimum cfg
  *      buffer size in *lenmem.
  * */
 
-kiss_fft_cfg kiss_fft_alloc(int nfft,int inverse_fft,void * mem,size_t * lenmem); 
+kiss_fft_cfg kiss_fft_alloc(int nfft,int inverse_fft,void * mem,size_t * lenmem);
 
 /*
  * kiss_fft(cfg,in_out_buf)
@@ -90,19 +90,19 @@ void kiss_fft(kiss_fft_cfg cfg,const kiss_fft_cpx *fin,kiss_fft_cpx *fout);
  * */
 void kiss_fft_stride(kiss_fft_cfg cfg,const kiss_fft_cpx *fin,kiss_fft_cpx *fout,int fin_stride);
 
-/* If kiss_fft_alloc allocated a buffer, it is one contiguous 
+/* If kiss_fft_alloc allocated a buffer, it is one contiguous
    buffer and can be simply free()d when no longer needed*/
 #define kiss_fft_free speex_free
 
 /*
- Cleans up some memory that gets managed internally. Not necessary to call, but it might clean up 
+ Cleans up some memory that gets managed internally. Not necessary to call, but it might clean up
  your compiler output to call this before you exit.
 */
 void kiss_fft_cleanup(void);
-	
+
 
 #ifdef __cplusplus
-} 
+}
 #endif
 
 #endif
diff --git a/vendor/libspeex/libspeex/kiss_fftr.h b/vendor/libspeex/libspeex/kiss_fftr.h
index 7bfb423340..8cfeda138a 100644
--- a/vendor/libspeex/libspeex/kiss_fftr.h
+++ b/vendor/libspeex/libspeex/kiss_fftr.h
@@ -6,13 +6,13 @@
 extern "C" {
 #endif
 
-    
-/* 
- 
+
+/*
+
  Real optimized version can save about 45% cpu time vs. complex fft of a real seq.
 
- 
- 
+
+
  */
 
 typedef struct kiss_fftr_state *kiss_fftr_cfg;
@@ -22,7 +22,7 @@ kiss_fftr_cfg kiss_fftr_alloc(int nfft,int inverse_fft,void * mem, size_t * lenm
 /*
  nfft must be even
 
- If you don't care to allocate space, use mem = lenmem = NULL 
+ If you don't care to allocate space, use mem = lenmem = NULL
 */
 
 
diff --git a/vendor/libspeex/libspeex/lpc.h b/vendor/libspeex/libspeex/lpc.h
index 952ecdd933..8885471f8a 100644
--- a/vendor/libspeex/libspeex/lpc.h
+++ b/vendor/libspeex/libspeex/lpc.h
@@ -7,18 +7,18 @@
    Redistribution and use in source and binary forms, with or without
    modification, are permitted provided that the following conditions
    are met:
-   
+
    - Redistributions of source code must retain the above copyright
    notice, this list of conditions and the following disclaimer.
-   
+
    - Redistributions in binary form must reproduce the above copyright
    notice, this list of conditions and the following disclaimer in the
    documentation and/or other materials provided with the distribution.
-   
+
    - Neither the name of the Xiph.org Foundation nor the names of its
    contributors may be used to endorse or promote products derived from
    this software without specific prior written permission.
-   
+
    THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
    ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
    LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
diff --git a/vendor/libspeex/libspeex/lpc_bfin.h b/vendor/libspeex/libspeex/lpc_bfin.h
index d7d11c008e..d2e040656d 100644
--- a/vendor/libspeex/libspeex/lpc_bfin.h
+++ b/vendor/libspeex/libspeex/lpc_bfin.h
@@ -1,25 +1,25 @@
 /* Copyright (C) 2005 Analog Devices */
 /**
    @file lpc_bfin.h
-   @author Jean-Marc Valin 
+   @author Jean-Marc Valin
    @brief Functions for LPC (Linear Prediction Coefficients) analysis (Blackfin version)
 */
 /*
    Redistribution and use in source and binary forms, with or without
    modification, are permitted provided that the following conditions
    are met:
-   
+
    - Redistributions of source code must retain the above copyright
    notice, this list of conditions and the following disclaimer.
-   
+
    - Redistributions in binary form must reproduce the above copyright
    notice, this list of conditions and the following disclaimer in the
    documentation and/or other materials provided with the distribution.
-   
+
    - Neither the name of the Xiph.org Foundation nor the names of its
    contributors may be used to endorse or promote products derived from
    this software without specific prior written permission.
-   
+
    THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
    ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
    LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
@@ -39,7 +39,7 @@
 void _spx_autocorr(
 const spx_word16_t *x,   /*  in: [0...n-1] samples x   */
 spx_word16_t       *ac,  /* out: [0...lag-1] ac values */
-int          lag, 
+int          lag,
 int          n
                   )
 {
@@ -69,10 +69,10 @@ int          n
       ac_shift--;
       ac0 <<= 1;
    }
-   
+
    xs = x+lag-1;
    nshift = -shift;
-   __asm__ __volatile__ 
+   __asm__ __volatile__
    (
          "P2 = %0;\n\t"
          "I0 = P2;\n\t" /* x in I0 */
@@ -102,7 +102,7 @@ int          n
             "LOOP_END inner_prod%=;\n\t"
             "A0 = ASHIFT A0 by R4.L;\n\t"
             "A1 = ASHIFT A1 by R4.L;\n\t"
-   
+
             "R2 = A0, R3 = A1;\n\t"
             "[P1--] = R2;\n\t"
             "[P1--] = R3;\n\t"
@@ -118,7 +118,7 @@ int          n
       d = ADD32(d,SHR32(MULT16_16(x[j],x[j]), shift));
    }
    ac32[0] = d;
-   
+
    for (i=0;i>>= 14;\n\t"
-      "R3 = R3 + R5;\n\t" 
-      
+      "R3 = R3 + R5;\n\t"
+
       "R0 = R2;\n\t"           /* R0: b0 */
       "R1 = 16384;\n\t"        /* R1: b1 */
       "LOOP cpe%= LC0 = %3;\n\t"
       "LOOP_BEGIN cpe%=;\n\t"
-        "P1 = R0;\n\t" 
+        "P1 = R0;\n\t"
         "R0 = R2.L * R0.L (IS) || R5 = W[P0--] (X);\n\t"
         "R0 >>>= 13;\n\t"
         "R0 = R0 - R1;\n\t"
diff --git a/vendor/libspeex/libspeex/ltp.h b/vendor/libspeex/libspeex/ltp.h
index 95bb126997..28d25173e4 100644
--- a/vendor/libspeex/libspeex/ltp.h
+++ b/vendor/libspeex/libspeex/ltp.h
@@ -7,18 +7,18 @@
    Redistribution and use in source and binary forms, with or without
    modification, are permitted provided that the following conditions
    are met:
-   
+
    - Redistributions of source code must retain the above copyright
    notice, this list of conditions and the following disclaimer.
-   
+
    - Redistributions in binary form must reproduce the above copyright
    notice, this list of conditions and the following disclaimer in the
    documentation and/or other materials provided with the distribution.
-   
+
    - Neither the name of the Xiph.org Foundation nor the names of its
    contributors may be used to endorse or promote products derived from
    this software without specific prior written permission.
-   
+
    THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
    ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
    LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
diff --git a/vendor/libspeex/libspeex/ltp_arm4.h b/vendor/libspeex/libspeex/ltp_arm4.h
index cdb94e603a..18be0d126e 100644
--- a/vendor/libspeex/libspeex/ltp_arm4.h
+++ b/vendor/libspeex/libspeex/ltp_arm4.h
@@ -7,18 +7,18 @@
    Redistribution and use in source and binary forms, with or without
    modification, are permitted provided that the following conditions
    are met:
-   
+
    - Redistributions of source code must retain the above copyright
    notice, this list of conditions and the following disclaimer.
-   
+
    - Redistributions in binary form must reproduce the above copyright
    notice, this list of conditions and the following disclaimer in the
    documentation and/or other materials provided with the distribution.
-   
+
    - Neither the name of the Xiph.org Foundation nor the names of its
    contributors may be used to endorse or promote products derived from
    this software without specific prior written permission.
-   
+
    THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
    ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
    LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
@@ -117,8 +117,8 @@ void pitch_xcorr(const spx_word16_t *_x, const spx_word16_t *_y, spx_word32_t *c
                "\tmul %6, %10, %2 \n"
                "\tldrsh %1, [%9], #2 \n"
                "\tmul %7, %10, %3 \n"
-               
-               
+
+
                "\tmla %4, %15, %2, %4 \n"
                "\tldrsh %2, [%9], #2 \n"
                "\tmla %5, %15, %3, %5 \n"
diff --git a/vendor/libspeex/libspeex/ltp_bfin.h b/vendor/libspeex/libspeex/ltp_bfin.h
index b7edd37aad..c2ba482112 100644
--- a/vendor/libspeex/libspeex/ltp_bfin.h
+++ b/vendor/libspeex/libspeex/ltp_bfin.h
@@ -8,18 +8,18 @@
    Redistribution and use in source and binary forms, with or without
    modification, are permitted provided that the following conditions
    are met:
-   
+
    - Redistributions of source code must retain the above copyright
    notice, this list of conditions and the following disclaimer.
-   
+
    - Redistributions in binary form must reproduce the above copyright
    notice, this list of conditions and the following disclaimer in the
    documentation and/or other materials provided with the distribution.
-   
+
    - Neither the name of the Xiph.org Foundation nor the names of its
    contributors may be used to endorse or promote products derived from
    this software without specific prior written permission.
-   
+
    THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
    ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
    LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
@@ -118,35 +118,35 @@ static inline spx_word32_t compute_pitch_error(spx_word16_t *C, spx_word16_t *g,
    __asm__ __volatile__
          (
          "A0 = 0;\n\t"
-         
+
          "R0 = W[%1++];\n\t"
          "R1.L = %2.L*%5.L (IS);\n\t"
          "A0 += R1.L*R0.L (IS) || R0 = W[%1++];\n\t"
-         
+
          "R1.L = %3.L*%5.L (IS);\n\t"
          "A0 += R1.L*R0.L (IS) || R0 = W[%1++];\n\t"
-         
+
          "R1.L = %4.L*%5.L (IS);\n\t"
          "A0 += R1.L*R0.L (IS) || R0 = W[%1++];\n\t"
-         
+
          "R1.L = %2.L*%3.L (IS);\n\t"
          "A0 -= R1.L*R0.L (IS) || R0 = W[%1++];\n\t"
 
          "R1.L = %4.L*%3.L (IS);\n\t"
          "A0 -= R1.L*R0.L (IS) || R0 = W[%1++];\n\t"
-         
+
          "R1.L = %4.L*%2.L (IS);\n\t"
          "A0 -= R1.L*R0.L (IS) || R0 = W[%1++];\n\t"
-         
+
          "R1.L = %2.L*%2.L (IS);\n\t"
          "A0 -= R1.L*R0.L (IS) || R0 = W[%1++];\n\t"
 
          "R1.L = %3.L*%3.L (IS);\n\t"
          "A0 -= R1.L*R0.L (IS) || R0 = W[%1++];\n\t"
-         
+
          "R1.L = %4.L*%4.L (IS);\n\t"
          "A0 -= R1.L*R0.L (IS);\n\t"
-         
+
          "%0 = A0;\n\t"
    : "=&D" (sum), "=a" (C)
    : "d" (g[0]), "d" (g[1]), "d" (g[2]), "d" (pitch_control), "1" (C)
@@ -203,7 +203,7 @@ void open_loop_nbest_pitch(spx_word16_t *sw, int start, int end, int len, int *p
 "          R2 = MAX(R1,R3);\n\t"
 "eu2:      [P0++] = R2;\n\t"
        : : "d" (energy), "d" (&sw[-start-1]), "d" (&sw[-start+len-1]),
-           "a" (end-start)  
+           "a" (end-start)
        : "P0", "I1", "I2", "R0", "R1", "R2", "R3", "ASTAT" BFIN_HWLOOP1_REGS
        );
 
@@ -232,7 +232,7 @@ void open_loop_nbest_pitch(spx_word16_t *sw, int start, int end, int len, int *p
 "        P0 = %4;\n\t"                     /* P0: best pitch  */
 "        P1 = %4;\n\t"                     /* P1: counter     */
 "        LSETUP (sl1, sl2) LC1 = %3;\n\t"
-"sl1:      R0.L = W [I0++] || R1.L = W [I1++];\n\t"         
+"sl1:      R0.L = W [I0++] || R1.L = W [I1++];\n\t"
 "          R0 = R0.L * R0.L (IS);\n\t"
 "          R1   += 1;\n\t"
 "          R4   = R0.L * R3.L;\n\t"
@@ -244,7 +244,7 @@ void open_loop_nbest_pitch(spx_word16_t *sw, int start, int end, int len, int *p
 "sl2:      P1 += 1;\n\t"
 "        %0 = P0;\n\t"
        : "=&d" (pitch[0])
-       : "a" (corr16), "a" (ener16), "a" (end+1-start), "d" (start) 
+       : "a" (corr16), "a" (ener16), "a" (end+1-start), "d" (start)
        : "P0", "P1", "I0", "I1", "R0", "R1", "R2", "R3", "R4", "R5",
          "ASTAT", "CC" BFIN_HWLOOP1_REGS
        );
@@ -338,39 +338,39 @@ static int pitch_gain_search_3tap_vq(
 "          R4 += 32;\n\t"
 "          R4.H = 64;\n\t"                 /* R4.H: pitch_control    */
 
-"          R0  = B [P0++] (X);\n\t"              
+"          R0  = B [P0++] (X);\n\t"
 "          B0  = R0;\n\t"                  /* BO: gain_sum         */
-          
+
            /* compute_pitch_error() -------------------------------*/
 
 "          I1 = %3;\n\t"                   /* I1: ptr to C         */
 "          A0 = 0;\n\t"
-         
+
 "          R0.L = W[I1++];\n\t"
 "          R1.L = R2.L*R4.H (IS);\n\t"
 "          A0 += R1.L*R0.L (IS) || R0.L = W[I1++];\n\t"
-         
+
 "          R1.L = R3.L*R4.H (IS);\n\t"
 "          A0 += R1.L*R0.L (IS) || R0.L = W[I1++];\n\t"
-         
+
 "          R1.L = R4.L*R4.H (IS);\n\t"
 "          A0 += R1.L*R0.L (IS) || R0.L = W[I1++];\n\t"
-         
+
 "          R1.L = R2.L*R3.L (IS);\n\t"
 "          A0 -= R1.L*R0.L (IS) || R0.L = W[I1++];\n\t"
 
 "          R1.L = R4.L*R3.L (IS);\n\t"
 "          A0 -= R1.L*R0.L (IS) || R0.L = W[I1++];\n\t"
-         
+
 "          R1.L = R4.L*R2.L (IS);\n\t"
 "          A0 -= R1.L*R0.L (IS) || R0.L = W[I1++];\n\t"
-         
+
 "          R1.L = R2.L*R2.L (IS);\n\t"
 "          A0 -= R1.L*R0.L (IS) || R0.L = W[I1++];\n\t"
 
 "          R1.L = R3.L*R3.L (IS);\n\t"
 "          A0 -= R1.L*R0.L (IS) || R0.L = W[I1++];\n\t"
-         
+
 "          R1.L = R4.L*R4.L (IS);\n\t"
 "          R0 = (A0 -= R1.L*R0.L) (IS);\n\t"
 
@@ -393,18 +393,18 @@ static int pitch_gain_search_3tap_vq(
 "          R1 = B0\n\t"
 "          R2 = %5\n\t"
 "          R3 = %6\n\t"
-"          cc = R2 <= R1;\n\t" 
+"          cc = R2 <= R1;\n\t"
 "          if cc R0 = R3;\n\t"
 "          cc = %0 <= R0;\n\t"
 "          if cc %0 = R0;\n\t"
 "          if cc %1 = P1;\n\t"
 
 "pgs2:     P1 += 1;\n\t"
-   
-       : "=&d" (best_sum), "=&d" (best_cdbk) 
+
+       : "=&d" (best_sum), "=&d" (best_cdbk)
        : "a" (gain_cdbk), "a" (C16), "a" (gain_cdbk_size), "a" (max_gain),
          "b" (-VERY_LARGE32)
-       : "R0", "R1", "R2", "R3", "R4", "P0", 
+       : "R0", "R1", "R2", "R3", "R4", "P0",
          "P1", "I1", "L1", "A0", "B0", "CC", "ASTAT" BFIN_HWLOOP1_REGS
        );
 
diff --git a/vendor/libspeex/libspeex/ltp_sse.h b/vendor/libspeex/libspeex/ltp_sse.h
index bed6eaac9a..326000831b 100644
--- a/vendor/libspeex/libspeex/ltp_sse.h
+++ b/vendor/libspeex/libspeex/ltp_sse.h
@@ -7,18 +7,18 @@
    Redistribution and use in source and binary forms, with or without
    modification, are permitted provided that the following conditions
    are met:
-   
+
    - Redistributions of source code must retain the above copyright
    notice, this list of conditions and the following disclaimer.
-   
+
    - Redistributions in binary form must reproduce the above copyright
    notice, this list of conditions and the following disclaimer in the
    documentation and/or other materials provided with the distribution.
-   
+
    - Neither the name of the Xiph.org Foundation nor the names of its
    contributors may be used to endorse or promote products derived from
    this software without specific prior written permission.
-   
+
    THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
    ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
    LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
diff --git a/vendor/libspeex/libspeex/math_approx.h b/vendor/libspeex/libspeex/math_approx.h
index 9ca830755d..2c0e115e2e 100644
--- a/vendor/libspeex/libspeex/math_approx.h
+++ b/vendor/libspeex/libspeex/math_approx.h
@@ -7,18 +7,18 @@
    Redistribution and use in source and binary forms, with or without
    modification, are permitted provided that the following conditions
    are met:
-   
+
    - Redistributions of source code must retain the above copyright
    notice, this list of conditions and the following disclaimer.
-   
+
    - Redistributions in binary form must reproduce the above copyright
    notice, this list of conditions and the following disclaimer in the
    documentation and/or other materials provided with the distribution.
-   
+
    - Neither the name of the Xiph.org Foundation nor the names of its
    contributors may be used to endorse or promote products derived from
    this software without specific prior written permission.
-   
+
    THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
    ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
    LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
@@ -46,7 +46,7 @@
 #define spx_atan atan
 
 /** Generate a pseudo-random number */
-static inline spx_word16_t speex_rand(spx_word16_t std, spx_int32_t *seed)
+static inline spx_word16_t speex_rand(spx_word16_t std, spx_uint32_t *seed)
 {
    const unsigned int jflone = 0x3f800000;
    const unsigned int jflmsk = 0x007fffff;
@@ -119,7 +119,7 @@ static inline spx_int16_t spx_ilog4(spx_uint32_t x)
 #ifdef FIXED_POINT
 
 /** Generate a pseudo-random number */
-static inline spx_word16_t speex_rand(spx_word16_t std, spx_int32_t *seed)
+static inline spx_word16_t speex_rand(spx_word16_t std, spx_uint32_t *seed)
 {
    spx_word32_t res;
    *seed = 1664525 * *seed + 1013904223;
@@ -168,11 +168,11 @@ static inline spx_word16_t spx_acos(spx_word16_t x)
       x = NEG16(x);
    }
    x = SUB16(16384,x);
-   
+
    x = x >> 1;
    sq = MULT16_16_Q13(x, ADD16(A1, MULT16_16_Q13(x, ADD16(A2, MULT16_16_Q13(x, (A3))))));
    ret = spx_sqrt(SHL32(EXTEND32(sq),13));
-   
+
    /*ret = spx_sqrt(67108864*(-1.6129e-04 + 2.0104e+00*f + 2.7373e-01*f*f + 1.8136e-01*f*f*f));*/
    if (s)
       ret = SUB16(25736,ret);
@@ -208,7 +208,7 @@ static inline spx_word16_t spx_cos(spx_word16_t x)
 static inline spx_word16_t _spx_cos_pi_2(spx_word16_t x)
 {
    spx_word16_t x2;
-   
+
    x2 = MULT16_16_P15(x,x);
    return ADD16(1,MIN16(32766,ADD32(SUB16(L1,x2), MULT16_16_P15(x2, ADD32(L2, MULT16_16_P15(x2, ADD32(L3, MULT16_16_P15(L4, x2))))))));
 }
diff --git a/vendor/libspeex/libspeex/misc_bfin.h b/vendor/libspeex/libspeex/misc_bfin.h
index 3c8c09d236..4e27681c95 100644
--- a/vendor/libspeex/libspeex/misc_bfin.h
+++ b/vendor/libspeex/libspeex/misc_bfin.h
@@ -1,25 +1,25 @@
 /* Copyright (C) 2005 Analog Devices */
 /**
    @file misc_bfin.h
-   @author Jean-Marc Valin 
+   @author Jean-Marc Valin
    @brief Various compatibility routines for Speex (Blackfin version)
 */
 /*
    Redistribution and use in source and binary forms, with or without
    modification, are permitted provided that the following conditions
    are met:
-   
+
    - Redistributions of source code must retain the above copyright
    notice, this list of conditions and the following disclaimer.
-   
+
    - Redistributions in binary form must reproduce the above copyright
    notice, this list of conditions and the following disclaimer in the
    documentation and/or other materials provided with the distribution.
-   
+
    - Neither the name of the Xiph.org Foundation nor the names of its
    contributors may be used to endorse or promote products derived from
    this software without specific prior written permission.
-   
+
    THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
    ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
    LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
diff --git a/vendor/libspeex/libspeex/modes.h b/vendor/libspeex/libspeex/modes.h
index 0977a579b8..2d5adc423f 100644
--- a/vendor/libspeex/libspeex/modes.h
+++ b/vendor/libspeex/libspeex/modes.h
@@ -7,18 +7,18 @@
    Redistribution and use in source and binary forms, with or without
    modification, are permitted provided that the following conditions
    are met:
-   
+
    - Redistributions of source code must retain the above copyright
    notice, this list of conditions and the following disclaimer.
-   
+
    - Redistributions in binary form must reproduce the above copyright
    notice, this list of conditions and the following disclaimer in the
    documentation and/or other materials provided with the distribution.
-   
+
    - Neither the name of the Xiph.org Foundation nor the names of its
    contributors may be used to endorse or promote products derived from
    this software without specific prior written permission.
-   
+
    THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
    ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
    LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
@@ -71,8 +71,8 @@ typedef void (*lsp_unquant_func)(spx_lsp_t *, int, SpeexBits *);
 
 
 /** Long-term predictor quantization */
-typedef int (*ltp_quant_func)(spx_word16_t *, spx_word16_t *, spx_coef_t *, spx_coef_t *, 
-                              spx_coef_t *, spx_sig_t *, const void *, int, int, spx_word16_t, 
+typedef int (*ltp_quant_func)(spx_word16_t *, spx_word16_t *, spx_coef_t *, spx_coef_t *,
+                              spx_coef_t *, spx_sig_t *, const void *, int, int, spx_word16_t,
                               int, int, SpeexBits*, char *, spx_word16_t *, spx_word16_t *, int, int, int, spx_word32_t *);
 
 /** Long-term un-quantize */
@@ -81,13 +81,13 @@ typedef void (*ltp_unquant_func)(spx_word16_t *, spx_word32_t *, int, int, spx_w
 
 
 /** Innovation quantization function */
-typedef void (*innovation_quant_func)(spx_word16_t *, spx_coef_t *, spx_coef_t *, spx_coef_t *, const void *, int, int, 
+typedef void (*innovation_quant_func)(spx_word16_t *, spx_coef_t *, spx_coef_t *, spx_coef_t *, const void *, int, int,
                                       spx_sig_t *, spx_word16_t *, SpeexBits *, char *, int, int);
 
 /** Innovation unquantization function */
-typedef void (*innovation_unquant_func)(spx_sig_t *, const void *, int, SpeexBits*, char *, spx_int32_t *);
+typedef void (*innovation_unquant_func)(spx_sig_t *, const void *, int, SpeexBits*, char *, spx_uint32_t *);
 
-/** Description of a Speex sub-mode (wither narrowband or wideband */
+/** Description of a Speex sub-mode (either narrowband or wideband) */
 typedef struct SpeexSubmode {
    int     lbr_pitch;          /**< Set to -1 for "normal" modes, otherwise encode pitch using a global pitch and allowing a +- lbr_pitch variation (for low not-rates)*/
    int     forced_pitch_gain;  /**< Use the same (forced) pitch gain for all sub-frames */
diff --git a/vendor/libspeex/libspeex/nb_celp.c b/vendor/libspeex/libspeex/nb_celp.c
index b68d5070a2..e6d7979723 100644
--- a/vendor/libspeex/libspeex/nb_celp.c
+++ b/vendor/libspeex/libspeex/nb_celp.c
@@ -93,13 +93,6 @@ static const float exc_gain_quant_scal1[2]={0.70469f, 1.05127f};
 
 #endif
 
-#ifdef VORBIS_PSYCHO
-#define EXTRA_BUFFER 100
-#else
-#define EXTRA_BUFFER 0
-#endif
-
-
 extern const spx_word16_t lag_window[];
 extern const spx_word16_t lpc_window[];
 
@@ -172,7 +165,7 @@ void *nb_encoder_init(const SpeexMode *m)
    st->highpass_enabled = 1;
 
 #ifdef ENABLE_VALGRIND
-   VALGRIND_MAKE_READABLE(st, NB_ENC_STACK);
+   VALGRIND_MAKE_MEM_DEFINED(st, NB_ENC_STACK);
 #endif
    return st;
 }
@@ -1113,7 +1106,7 @@ void *nb_decoder_init(const SpeexMode *m)
    st->highpass_enabled = 1;
 
 #ifdef ENABLE_VALGRIND
-   VALGRIND_MAKE_READABLE(st, NB_DEC_STACK);
+   VALGRIND_MAKE_MEM_DEFINED(st, NB_DEC_STACK);
 #endif
    return st;
 }
@@ -1472,6 +1465,11 @@ int nb_decode(void *state, SpeexBits *bits, void *vout)
       /* Final signal synthesis from excitation */
       iir_mem16(st->exc, lpc, out, NB_FRAME_SIZE, NB_ORDER, st->mem_sp, stack);
 
+      /* Normally this is written to later but since this is returning early,
+         avoid reading uninitialized memory in caller */
+      if (st->innov_save)
+         SPEEX_MEMSET(st->innov_save, 0, NB_NB_SUBFRAMES*NB_SUBFRAME_SIZE);
+
       st->count_lost=0;
       return 0;
    }
diff --git a/vendor/libspeex/libspeex/nb_celp.h b/vendor/libspeex/libspeex/nb_celp.h
index a8d3088063..8fe60ce11f 100644
--- a/vendor/libspeex/libspeex/nb_celp.h
+++ b/vendor/libspeex/libspeex/nb_celp.h
@@ -7,18 +7,18 @@
    Redistribution and use in source and binary forms, with or without
    modification, are permitted provided that the following conditions
    are met:
-   
+
    - Redistributions of source code must retain the above copyright
    notice, this list of conditions and the following disclaimer.
-   
+
    - Redistributions in binary form must reproduce the above copyright
    notice, this list of conditions and the following disclaimer in the
    documentation and/or other materials provided with the distribution.
-   
+
    - Neither the name of the Xiph.org Foundation nor the names of its
    contributors may be used to endorse or promote products derived from
    this software without specific prior written permission.
-   
+
    THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
    ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
    LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
@@ -109,7 +109,7 @@ typedef struct EncState {
    float  abr_drift2;
    float  abr_count;
 #endif /* #ifndef DISABLE_VBR */
-   
+
    int    complexity;            /**< Complexity setting (0-10 from least complex to most complex) */
    spx_int32_t sampling_rate;
    int    plc_tuning;
@@ -139,18 +139,18 @@ typedef struct DecState {
    spx_mem_t mem_hp[2];         /**< High-pass filter memory */
    spx_word32_t pi_gain[NB_NB_SUBFRAMES];       /**< Gain of LPC filter at theta=pi (fe/2) */
    spx_word16_t *innov_save;    /** If non-NULL, innovation is copied here */
-   
+
    spx_word16_t level;
    spx_word16_t max_level;
    spx_word16_t min_level;
-   
+
    /* This is used in packet loss concealment */
    int    last_pitch;           /**< Pitch of last correctly decoded frame */
    spx_word16_t  last_pitch_gain; /**< Pitch gain of last correctly decoded frame */
    spx_word16_t  pitch_gain_buf[3]; /**< Pitch gain of last decoded frames */
    int    pitch_gain_buf_idx;   /**< Tail of the buffer */
-   spx_int32_t seed;            /** Seed used for random number generation */
-   
+   spx_uint32_t seed;            /** Seed used for random number generation */
+
    int    encode_submode;
    const SpeexSubmode * const *submodes; /**< Sub-mode data */
    int    submodeID;            /**< Activated sub-mode */
diff --git a/vendor/libspeex/libspeex/os_support.h b/vendor/libspeex/libspeex/os_support.h
index 2e23a5eb41..0db31a61df 100644
--- a/vendor/libspeex/libspeex/os_support.h
+++ b/vendor/libspeex/libspeex/os_support.h
@@ -1,5 +1,5 @@
 /* Copyright (C) 2007 Jean-Marc Valin
-      
+
    File: os_support.h
    This is the (tiny) OS abstraction layer. Aside from math.h, this is the
    only place where system headers are allowed.
@@ -45,12 +45,12 @@
 #include "os_support_custom.h"
 #endif
 
-/** Speex wrapper for calloc. To do your own dynamic allocation, all you need to do is replace this function, speex_realloc and speex_free 
+/** Speex wrapper for calloc. To do your own dynamic allocation, all you need to do is replace this function, speex_realloc and speex_free
     NOTE: speex_alloc needs to CLEAR THE MEMORY */
 #ifndef OVERRIDE_SPEEX_ALLOC
 static inline void *speex_alloc (int size)
 {
-   /* WARNING: this is not equivalent to malloc(). If you want to use malloc() 
+   /* WARNING: this is not equivalent to malloc(). If you want to use malloc()
       or your own allocator, YOU NEED TO CLEAR THE MEMORY ALLOCATED. Otherwise
       you will experience strange bugs */
    return calloc(size,1);
diff --git a/vendor/libspeex/libspeex/quant_lsp.h b/vendor/libspeex/libspeex/quant_lsp.h
index 0fc206be6f..aea6eb2b7b 100644
--- a/vendor/libspeex/libspeex/quant_lsp.h
+++ b/vendor/libspeex/libspeex/quant_lsp.h
@@ -7,18 +7,18 @@
    Redistribution and use in source and binary forms, with or without
    modification, are permitted provided that the following conditions
    are met:
-   
+
    - Redistributions of source code must retain the above copyright
    notice, this list of conditions and the following disclaimer.
-   
+
    - Redistributions in binary form must reproduce the above copyright
    notice, this list of conditions and the following disclaimer in the
    documentation and/or other materials provided with the distribution.
-   
+
    - Neither the name of the Xiph.org Foundation nor the names of its
    contributors may be used to endorse or promote products derived from
    this software without specific prior written permission.
-   
+
    THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
    ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
    LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
diff --git a/vendor/libspeex/libspeex/quant_lsp_bfin.h b/vendor/libspeex/libspeex/quant_lsp_bfin.h
index efd23f5509..238adb9301 100644
--- a/vendor/libspeex/libspeex/quant_lsp_bfin.h
+++ b/vendor/libspeex/libspeex/quant_lsp_bfin.h
@@ -8,18 +8,18 @@
    Redistribution and use in source and binary forms, with or without
    modification, are permitted provided that the following conditions
    are met:
-   
+
    - Redistributions of source code must retain the above copyright
    notice, this list of conditions and the following disclaimer.
-   
+
    - Redistributions in binary form must reproduce the above copyright
    notice, this list of conditions and the following disclaimer in the
    documentation and/or other materials provided with the distribution.
-   
+
    - Neither the name of the Xiph.org Foundation nor the names of its
    contributors may be used to endorse or promote products derived from
    this software without specific prior written permission.
-   
+
    THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
    ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
    LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
@@ -40,14 +40,14 @@
 
 /*
   Note http://gcc.gnu.org/onlinedocs/gcc/Machine-Constraints.html
-  well tell you all the magic resgister constraints used below
+  well tell you all the magic register constraints used below
   for gcc in-line asm.
 */
 
 static int lsp_quant(
-  spx_word16_t      *x, 
-  const signed char *cdbk, 
-  int                nbVec, 
+  spx_word16_t      *x,
+  const signed char *cdbk,
+  int                nbVec,
   int                nbDim
 )
 {
@@ -57,23 +57,23 @@ static int lsp_quant(
 
    __asm__ __volatile__
      (
-"	%0 = 1 (X);\n\t"                       /* %0: best_dist */    
-"	%0 <<= 30;\n\t"     
+"	%0 = 1 (X);\n\t"                       /* %0: best_dist */
+"	%0 <<= 30;\n\t"
 "	%1 = 0 (X);\n\t"                       /* %1: best_i         */
 "       P2 = %3\n\t"                           /* P2: ptr to cdbk    */
 "       R5 = 0;\n\t"                           /* R5: best cb entry  */
 
 "       R0 = %5;\n\t"                          /* set up circ addr   */
 "       R0 <<= 1;\n\t"
-"       L0 = R0;\n\t"                          
+"       L0 = R0;\n\t"
 "       I0 = %2;\n\t"                          /* %2: &x[0]          */
-"       B0 = %2;\n\t"                          
+"       B0 = %2;\n\t"
 
 "       R2.L = W [I0++];\n\t"
 "	LSETUP (1f, 2f) LC0 = %4;\n\t"
 "1:	  R3 = 0;\n\t"                         /* R3: dist           */
 "	  LSETUP (3f, 4f) LC1 = %5;\n\t"
-"3:       R1 = B [P2++] (X);\n\t"            
+"3:       R1 = B [P2++] (X);\n\t"
 "	    R1 <<= 5;\n\t"
 "	    R0.L = R2.L - R1.L || R2.L = W [I0++];\n\t"
 "	    R0 = R0.L*R0.L;\n\t"
@@ -102,15 +102,15 @@ static int lsp_quant(
 
 /*
   Note http://gcc.gnu.org/onlinedocs/gcc/Machine-Constraints.html
-  well tell you all the magic resgister constraints used below
+  well tell you all the magic register constraints used below
   for gcc in-line asm.
 */
 
 static int lsp_weight_quant(
-  spx_word16_t      *x, 
-  spx_word16_t      *weight, 
-  const signed char *cdbk, 
-  int                nbVec, 
+  spx_word16_t      *x,
+  spx_word16_t      *weight,
+  const signed char *cdbk,
+  int                nbVec,
   int                nbDim
 )
 {
@@ -120,26 +120,26 @@ static int lsp_weight_quant(
 
    __asm__ __volatile__
      (
-"	%0 = 1 (X);\n\t"                       /* %0: best_dist */    
-"	%0 <<= 30;\n\t"     
+"	%0 = 1 (X);\n\t"                       /* %0: best_dist */
+"	%0 <<= 30;\n\t"
 "	%1 = 0 (X);\n\t"                       /* %1: best_i         */
 "       P2 = %4\n\t"                           /* P2: ptr to cdbk    */
 "       R5 = 0;\n\t"                           /* R5: best cb entry  */
 
 "       R0 = %6;\n\t"                          /* set up circ addr   */
 "       R0 <<= 1;\n\t"
-"       L0 = R0;\n\t"                          
+"       L0 = R0;\n\t"
 "       L1 = R0;\n\t"
 "       I0 = %2;\n\t"                          /* %2: &x[0]          */
 "	I1 = %3;\n\t"                          /* %3: &weight[0]     */
-"       B0 = %2;\n\t"                          
-"	B1 = %3;\n\t"                          
+"       B0 = %2;\n\t"
+"	B1 = %3;\n\t"
 
 "	LSETUP (1f, 2f) LC0 = %5;\n\t"
 "1:	  R3 = 0 (X);\n\t"                     /* R3: dist           */
 "	  LSETUP (3f, 4f) LC1 = %6;\n\t"
 "3:	    R0.L = W [I0++] || R2.L = W [I1++];\n\t"
-"           R1 = B [P2++] (X);\n\t"            
+"           R1 = B [P2++] (X);\n\t"
 "	    R1 <<= 5;\n\t"
 "	    R0.L = R0.L - R1.L;\n\t"
 "           R0 = R0.L*R0.L;\n\t"
diff --git a/vendor/libspeex/libspeex/sb_celp.c b/vendor/libspeex/libspeex/sb_celp.c
index 3aab085cc9..61d5c27a6a 100644
--- a/vendor/libspeex/libspeex/sb_celp.c
+++ b/vendor/libspeex/libspeex/sb_celp.c
@@ -64,9 +64,6 @@
 
 #ifndef DISABLE_WIDEBAND
 
-
-#define sqr(x) ((x)*(x))
-
 #define SUBMODE(x) st->submodes[st->submodeID]->x
 
 #ifdef FIXED_POINT
@@ -223,7 +220,7 @@ void *sb_encoder_init(const SpeexMode *m)
    speex_encoder_ctl(st->st_low, SPEEX_GET_SAMPLING_RATE, &st->sampling_rate);
    st->sampling_rate*=2;
 #ifdef ENABLE_VALGRIND
-   VALGRIND_MAKE_READABLE(st, (st->stack-(char*)st));
+   VALGRIND_MAKE_MEM_DEFINED(st, (st->stack-(char*)st));
 #endif
    return st;
 }
@@ -1017,7 +1014,7 @@ void *sb_decoder_init(const SpeexMode *m)
    st->seed = 1000;
 
 #ifdef ENABLE_VALGRIND
-   VALGRIND_MAKE_READABLE(st, (st->stack-(char*)st));
+   VALGRIND_MAKE_MEM_DEFINED(st, (st->stack-(char*)st));
 #endif
    return st;
 }
@@ -1280,6 +1277,9 @@ int sb_decode(void *state, SpeexBits *bits, void *vout)
    /* If null mode (no transmission), just set a couple things to zero*/
    if (st->submodes[st->submodeID] == NULL)
    {
+      if (st->innov_save)
+        SPEEX_MEMSET(st->innov_save, 0, st->full_frame_size);
+
       if (dtx)
       {
          sb_decode_lost(st, out, 1, stack);
@@ -1343,7 +1343,7 @@ int sb_decode(void *state, SpeexBits *bits, void *vout)
       /* LSP to LPC */
       lsp_to_lpc(interp_qlsp, ak, st->lpcSize, stack);
 
-      /* Calculate reponse ratio between the low and high filter in the middle
+      /* Calculate response ratio between the low and high filter in the middle
          of the band (4000 Hz) */
 
          st->pi_gain[sub]=LPC_SCALING;
diff --git a/vendor/libspeex/libspeex/sb_celp.h b/vendor/libspeex/libspeex/sb_celp.h
index 141d0c2e1b..c6b92940db 100644
--- a/vendor/libspeex/libspeex/sb_celp.h
+++ b/vendor/libspeex/libspeex/sb_celp.h
@@ -7,18 +7,18 @@
    Redistribution and use in source and binary forms, with or without
    modification, are permitted provided that the following conditions
    are met:
-   
+
    - Redistributions of source code must retain the above copyright
    notice, this list of conditions and the following disclaimer.
-   
+
    - Redistributions in binary form must reproduce the above copyright
    notice, this list of conditions and the following disclaimer in the
    documentation and/or other materials provided with the distribution.
-   
+
    - Neither the name of the Xiph.org Foundation nor the names of its
    contributors may be used to endorse or promote products derived from
    this software without specific prior written permission.
-   
+
    THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
    ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
    LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
@@ -83,7 +83,7 @@ typedef struct SBEncState {
    int    vad_enabled;            /**< 1 for enabling VAD, 0 otherwise */
    float  relative_quality;
 #endif /* #ifndef DISABLE_VBR */
-   
+
    int    encode_submode;
    const SpeexSubmode * const *submodes;
    int    submodeID;
@@ -118,9 +118,9 @@ typedef struct SBDecState {
    spx_word32_t *pi_gain;
    spx_word16_t *exc_rms;
    spx_word16_t *innov_save;      /** If non-NULL, innovation is copied here */
-   
+
    spx_word16_t last_ener;
-   spx_int32_t seed;
+   spx_uint32_t seed;
 
    int    encode_submode;
    const SpeexSubmode * const *submodes;
diff --git a/vendor/libspeex/libspeex/stack_alloc.h b/vendor/libspeex/libspeex/stack_alloc.h
index 5264e666b0..a446065825 100644
--- a/vendor/libspeex/libspeex/stack_alloc.h
+++ b/vendor/libspeex/libspeex/stack_alloc.h
@@ -7,18 +7,18 @@
    Redistribution and use in source and binary forms, with or without
    modification, are permitted provided that the following conditions
    are met:
-   
+
    - Redistributions of source code must retain the above copyright
    notice, this list of conditions and the following disclaimer.
-   
+
    - Redistributions in binary form must reproduce the above copyright
    notice, this list of conditions and the following disclaimer in the
    documentation and/or other materials provided with the distribution.
-   
+
    - Neither the name of the Xiph.org Foundation nor the names of its
    contributors may be used to endorse or promote products derived from
    this software without specific prior written permission.
-   
+
    THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
    ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
    LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
@@ -36,7 +36,7 @@
 #define STACK_ALLOC_H
 
 #ifdef USE_ALLOCA
-# ifdef WIN32
+# ifdef _WIN32
 #  include 
 # else
 #  ifdef HAVE_ALLOCA_H
@@ -101,7 +101,7 @@
 #endif
 
 #if defined(VAR_ARRAYS)
-#define VARDECL(var) 
+#define VARDECL(var)
 #define ALLOC(var, size, type) type var[size]
 #elif defined(USE_ALLOCA)
 #define VARDECL(var) var
diff --git a/vendor/libspeex/libspeex/testenc.c b/vendor/libspeex/libspeex/testenc.c
new file mode 100644
index 0000000000..1f634ed745
--- /dev/null
+++ b/vendor/libspeex/libspeex/testenc.c
@@ -0,0 +1,145 @@
+#ifdef HAVE_CONFIG_H
+#include "config.h"
+#endif
+
+#include "speex/speex_callbacks.h"
+#include 
+#include 
+
+#ifdef FIXED_DEBUG
+extern long long spx_mips;
+#endif
+
+#define FRAME_SIZE 160
+#include 
+int main(int argc, char **argv)
+{
+   char *inFile, *outFile, *bitsFile;
+   FILE *fin, *fout, *fbits=NULL;
+   short in_short[FRAME_SIZE];
+   short out_short[FRAME_SIZE];
+   int snr_frames = 0;
+   char cbits[200];
+   int nbBits;
+   int i;
+   void *st;
+   void *dec;
+   SpeexBits bits;
+   spx_int32_t tmp;
+   int bitCount=0;
+   spx_int32_t skip_group_delay;
+   SpeexCallback callback;
+
+   st = speex_encoder_init(speex_lib_get_mode(SPEEX_MODEID_NB));
+   dec = speex_decoder_init(speex_lib_get_mode(SPEEX_MODEID_NB));
+
+   /* BEGIN: You probably don't need the following in a real application */
+   callback.callback_id = SPEEX_INBAND_CHAR;
+   callback.func = speex_std_char_handler;
+   callback.data = stderr;
+   speex_decoder_ctl(dec, SPEEX_SET_HANDLER, &callback);
+
+   callback.callback_id = SPEEX_INBAND_MODE_REQUEST;
+   callback.func = speex_std_mode_request_handler;
+   callback.data = st;
+   speex_decoder_ctl(dec, SPEEX_SET_HANDLER, &callback);
+   /* END of unnecessary stuff */
+
+   tmp=1;
+   speex_decoder_ctl(dec, SPEEX_SET_ENH, &tmp);
+   tmp=0;
+   speex_encoder_ctl(st, SPEEX_SET_VBR, &tmp);
+   tmp=8;
+   speex_encoder_ctl(st, SPEEX_SET_QUALITY, &tmp);
+   tmp=1;
+   speex_encoder_ctl(st, SPEEX_SET_COMPLEXITY, &tmp);
+
+   /* Turn this off if you want to measure SNR (on by default) */
+   tmp=1;
+   speex_encoder_ctl(st, SPEEX_SET_HIGHPASS, &tmp);
+   speex_decoder_ctl(dec, SPEEX_SET_HIGHPASS, &tmp);
+
+   speex_encoder_ctl(st, SPEEX_GET_LOOKAHEAD, &skip_group_delay);
+   speex_decoder_ctl(dec, SPEEX_GET_LOOKAHEAD, &tmp);
+   skip_group_delay += tmp;
+
+   if (argc != 4 && argc != 3)
+   {
+      fprintf (stderr, "Usage: encode [in file] [out file] [bits file]\nargc = %d", argc);
+      exit(1);
+   }
+   inFile = argv[1];
+   fin = fopen(inFile, "rb");
+   outFile = argv[2];
+   fout = fopen(outFile, "wb+");
+   if (argc==4)
+   {
+      bitsFile = argv[3];
+      fbits = fopen(bitsFile, "wb");
+   }
+   speex_bits_init(&bits);
+   while (!feof(fin))
+   {
+      fread(in_short, sizeof(short), FRAME_SIZE, fin);
+      if (feof(fin))
+         break;
+      speex_bits_reset(&bits);
+
+      speex_encode_int(st, in_short, &bits);
+      nbBits = speex_bits_write(&bits, cbits, 200);
+      bitCount+=bits.nbBits;
+
+      if (argc==4)
+         fwrite(cbits, 1, nbBits, fbits);
+      speex_bits_rewind(&bits);
+
+      speex_decode_int(dec, &bits, out_short);
+      speex_bits_reset(&bits);
+
+      fwrite(&out_short[skip_group_delay], sizeof(short), FRAME_SIZE-skip_group_delay, fout);
+      skip_group_delay = 0;
+   }
+   fprintf (stderr, "Total encoded size: %d bits\n", bitCount);
+   speex_encoder_destroy(st);
+   speex_decoder_destroy(dec);
+   speex_bits_destroy(&bits);
+
+#ifndef DISABLE_FLOAT_API
+   {
+   float sigpow,errpow,snr, seg_snr=0;
+   sigpow = 0;
+   errpow = 0;
+
+   /* This code just computes SNR, so you don't need it either */
+   rewind(fin);
+   rewind(fout);
+
+   while ( FRAME_SIZE == fread(in_short, sizeof(short), FRAME_SIZE, fin)
+           &&
+           FRAME_SIZE ==  fread(out_short, sizeof(short), FRAME_SIZE,fout) )
+   {
+	float s=0, e=0;
+        for (i=0;i
+#include 
+
+#ifdef FIXED_DEBUG
+extern long long spx_mips;
+#endif
+
+#define FRAME_SIZE 640
+#include 
+int main(int argc, char **argv)
+{
+   char *inFile, *outFile, *bitsFile;
+   FILE *fin, *fout, *fbits=NULL;
+   short in_short[FRAME_SIZE];
+   short out_short[FRAME_SIZE];
+   float sigpow,errpow,snr, seg_snr=0;
+   int snr_frames = 0;
+   char cbits[200];
+   int nbBits;
+   int i;
+   void *st;
+   void *dec;
+   SpeexBits bits;
+   spx_int32_t tmp;
+   int bitCount=0;
+   spx_int32_t skip_group_delay;
+   SpeexCallback callback;
+
+   sigpow = 0;
+   errpow = 0;
+
+   st = speex_encoder_init(speex_lib_get_mode(SPEEX_MODEID_UWB));
+   dec = speex_decoder_init(speex_lib_get_mode(SPEEX_MODEID_UWB));
+
+   callback.callback_id = SPEEX_INBAND_CHAR;
+   callback.func = speex_std_char_handler;
+   callback.data = stderr;
+   speex_decoder_ctl(dec, SPEEX_SET_HANDLER, &callback);
+
+   callback.callback_id = SPEEX_INBAND_MODE_REQUEST;
+   callback.func = speex_std_mode_request_handler;
+   callback.data = st;
+   speex_decoder_ctl(dec, SPEEX_SET_HANDLER, &callback);
+
+   tmp=0;
+   speex_decoder_ctl(dec, SPEEX_SET_ENH, &tmp);
+   tmp=0;
+   speex_encoder_ctl(st, SPEEX_SET_VBR, &tmp);
+   tmp=7;
+   speex_encoder_ctl(st, SPEEX_SET_QUALITY, &tmp);
+   tmp=1;
+   speex_encoder_ctl(st, SPEEX_SET_COMPLEXITY, &tmp);
+
+   speex_encoder_ctl(st, SPEEX_GET_LOOKAHEAD, &skip_group_delay);
+   speex_decoder_ctl(dec, SPEEX_GET_LOOKAHEAD, &tmp);
+   skip_group_delay += tmp;
+
+
+   if (argc != 4 && argc != 3)
+   {
+      fprintf (stderr, "Usage: encode [in file] [out file] [bits file]\nargc = %d", argc);
+      exit(1);
+   }
+   inFile = argv[1];
+   fin = fopen(inFile, "rb");
+   outFile = argv[2];
+   fout = fopen(outFile, "wb+");
+   if (argc==4)
+   {
+      bitsFile = argv[3];
+      fbits = fopen(bitsFile, "wb");
+   }
+   speex_bits_init(&bits);
+   while (!feof(fin))
+   {
+      fread(in_short, sizeof(short), FRAME_SIZE, fin);
+      if (feof(fin))
+         break;
+      speex_bits_reset(&bits);
+
+      speex_encode_int(st, in_short, &bits);
+      nbBits = speex_bits_write(&bits, cbits, 200);
+      bitCount+=bits.nbBits;
+
+      if (argc==4)
+         fwrite(cbits, 1, nbBits, fbits);
+      speex_bits_rewind(&bits);
+
+      speex_decode_int(dec, &bits, out_short);
+      speex_bits_reset(&bits);
+
+      fwrite(&out_short[skip_group_delay], sizeof(short), FRAME_SIZE-skip_group_delay, fout);
+      skip_group_delay = 0;
+   }
+   fprintf (stderr, "Total encoded size: %d bits\n", bitCount);
+   speex_encoder_destroy(st);
+   speex_decoder_destroy(dec);
+
+   rewind(fin);
+   rewind(fout);
+
+   while ( FRAME_SIZE == fread(in_short, sizeof(short), FRAME_SIZE, fin)
+           &&
+           FRAME_SIZE ==  fread(out_short, sizeof(short), FRAME_SIZE,fout) )
+   {
+	float s=0, e=0;
+        for (i=0;i
+#include 
+
+#ifdef FIXED_DEBUG
+extern long long spx_mips;
+#endif
+
+#define FRAME_SIZE 320
+#include 
+int main(int argc, char **argv)
+{
+   char *inFile, *outFile, *bitsFile;
+   FILE *fin, *fout, *fbits=NULL;
+   short in_short[FRAME_SIZE];
+   short out_short[FRAME_SIZE];
+   float sigpow,errpow,snr, seg_snr=0;
+   int snr_frames = 0;
+   char cbits[200];
+   int nbBits;
+   int i;
+   void *st;
+   void *dec;
+   SpeexBits bits;
+   spx_int32_t tmp;
+   int bitCount=0;
+   spx_int32_t skip_group_delay;
+   SpeexCallback callback;
+
+   sigpow = 0;
+   errpow = 0;
+
+   st = speex_encoder_init(speex_lib_get_mode(SPEEX_MODEID_WB));
+   dec = speex_decoder_init(speex_lib_get_mode(SPEEX_MODEID_WB));
+
+   callback.callback_id = SPEEX_INBAND_CHAR;
+   callback.func = speex_std_char_handler;
+   callback.data = stderr;
+   speex_decoder_ctl(dec, SPEEX_SET_HANDLER, &callback);
+
+   callback.callback_id = SPEEX_INBAND_MODE_REQUEST;
+   callback.func = speex_std_mode_request_handler;
+   callback.data = st;
+   speex_decoder_ctl(dec, SPEEX_SET_HANDLER, &callback);
+
+   tmp=1;
+   speex_decoder_ctl(dec, SPEEX_SET_ENH, &tmp);
+   tmp=0;
+   speex_encoder_ctl(st, SPEEX_SET_VBR, &tmp);
+   tmp=8;
+   speex_encoder_ctl(st, SPEEX_SET_QUALITY, &tmp);
+   tmp=3;
+   speex_encoder_ctl(st, SPEEX_SET_COMPLEXITY, &tmp);
+   /*tmp=3;
+   speex_encoder_ctl(st, SPEEX_SET_HIGH_MODE, &tmp);
+   tmp=6;
+   speex_encoder_ctl(st, SPEEX_SET_LOW_MODE, &tmp);
+*/
+
+   speex_encoder_ctl(st, SPEEX_GET_LOOKAHEAD, &skip_group_delay);
+   speex_decoder_ctl(dec, SPEEX_GET_LOOKAHEAD, &tmp);
+   skip_group_delay += tmp;
+
+
+   if (argc != 4 && argc != 3)
+   {
+      fprintf (stderr, "Usage: encode [in file] [out file] [bits file]\nargc = %d", argc);
+      exit(1);
+   }
+   inFile = argv[1];
+   fin = fopen(inFile, "rb");
+   outFile = argv[2];
+   fout = fopen(outFile, "wb+");
+   if (argc==4)
+   {
+      bitsFile = argv[3];
+      fbits = fopen(bitsFile, "wb");
+   }
+   speex_bits_init(&bits);
+   while (!feof(fin))
+   {
+      fread(in_short, sizeof(short), FRAME_SIZE, fin);
+      if (feof(fin))
+         break;
+      speex_bits_reset(&bits);
+
+      speex_encode_int(st, in_short, &bits);
+      nbBits = speex_bits_write(&bits, cbits, 200);
+      bitCount+=bits.nbBits;
+
+      if (argc==4)
+         fwrite(cbits, 1, nbBits, fbits);
+      speex_bits_rewind(&bits);
+
+      speex_decode_int(dec, &bits, out_short);
+      speex_bits_reset(&bits);
+
+      fwrite(&out_short[skip_group_delay], sizeof(short), FRAME_SIZE-skip_group_delay, fout);
+      skip_group_delay = 0;
+   }
+   fprintf (stderr, "Total encoded size: %d bits\n", bitCount);
+   speex_encoder_destroy(st);
+   speex_decoder_destroy(dec);
+   speex_bits_destroy(&bits);
+
+   rewind(fin);
+   rewind(fout);
+
+   while ( FRAME_SIZE == fread(in_short, sizeof(short), FRAME_SIZE, fin)
+           &&
+           FRAME_SIZE ==  fread(out_short, sizeof(short), FRAME_SIZE,fout) )
+   {
+	float s=0, e=0;
+        for (i=0;i1e-13?log((x)*(x))*4.34294480f:-30)
-#define fromdB(x) (exp((x)*.11512925f))  
+#define fromdB(x) (exp((x)*.11512925f))
 
 /* The bark scale equations are approximations, since the original
    table was somewhat hand rolled.  The below are chosen to have the
diff --git a/vendor/libspeex/libspeex/vq.h b/vendor/libspeex/libspeex/vq.h
index 5a4ced249c..5c707f0555 100644
--- a/vendor/libspeex/libspeex/vq.h
+++ b/vendor/libspeex/libspeex/vq.h
@@ -7,18 +7,18 @@
    Redistribution and use in source and binary forms, with or without
    modification, are permitted provided that the following conditions
    are met:
-   
+
    - Redistributions of source code must retain the above copyright
    notice, this list of conditions and the following disclaimer.
-   
+
    - Redistributions in binary form must reproduce the above copyright
    notice, this list of conditions and the following disclaimer in the
    documentation and/or other materials provided with the distribution.
-   
+
    - Neither the name of the Xiph.org Foundation nor the names of its
    contributors may be used to endorse or promote products derived from
    this software without specific prior written permission.
-   
+
    THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
    ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
    LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
diff --git a/vendor/libspeex/libspeex/vq_arm4.h b/vendor/libspeex/libspeex/vq_arm4.h
index 585b8613c5..957e195f24 100644
--- a/vendor/libspeex/libspeex/vq_arm4.h
+++ b/vendor/libspeex/libspeex/vq_arm4.h
@@ -7,18 +7,18 @@
    Redistribution and use in source and binary forms, with or without
    modification, are permitted provided that the following conditions
    are met:
-   
+
    - Redistributions of source code must retain the above copyright
    notice, this list of conditions and the following disclaimer.
-   
+
    - Redistributions in binary form must reproduce the above copyright
    notice, this list of conditions and the following disclaimer in the
    documentation and/or other materials provided with the distribution.
-   
+
    - Neither the name of the Xiph.org Foundation nor the names of its
    contributors may be used to endorse or promote products derived from
    this software without specific prior written permission.
-   
+
    THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
    ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
    LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
diff --git a/vendor/libspeex/libspeex/vq_bfin.h b/vendor/libspeex/libspeex/vq_bfin.h
index a4d2d2ff3b..82979894eb 100644
--- a/vendor/libspeex/libspeex/vq_bfin.h
+++ b/vendor/libspeex/libspeex/vq_bfin.h
@@ -1,25 +1,25 @@
 /* Copyright (C) 2005 Analog Devices */
 /**
    @file vq_bfin.h
-   @author Jean-Marc Valin 
+   @author Jean-Marc Valin
    @brief Blackfin-optimized vq routine
 */
 /*
    Redistribution and use in source and binary forms, with or without
    modification, are permitted provided that the following conditions
    are met:
-   
+
    - Redistributions of source code must retain the above copyright
    notice, this list of conditions and the following disclaimer.
-   
+
    - Redistributions in binary form must reproduce the above copyright
    notice, this list of conditions and the following disclaimer in the
    documentation and/or other materials provided with the distribution.
-   
+
    - Neither the name of the Xiph.org Foundation nor the names of its
    contributors may be used to endorse or promote products derived from
    this software without specific prior written permission.
-   
+
    THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
    ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
    LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
diff --git a/vendor/libspeex/libspeexdsp/_kiss_fft_guts.h b/vendor/libspeex/libspeexdsp/_kiss_fft_guts.h
index 6571e79c0c..f5f2a5fd76 100644
--- a/vendor/libspeex/libspeexdsp/_kiss_fft_guts.h
+++ b/vendor/libspeex/libspeexdsp/_kiss_fft_guts.h
@@ -23,7 +23,7 @@ THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
 #include "math_approx.h"
 
 #define MAXFACTORS 32
-/* e.g. an fft of length 128 has 4 factors 
+/* e.g. an fft of length 128 has 4 factors
  as far as kissfft is concerned
  4*4*4*2
  */
@@ -47,7 +47,7 @@ struct kiss_fft_state{
 #ifdef FIXED_POINT
 #include "arch.h"
 # define FRACBITS 15
-# define SAMPPROD spx_int32_t 
+# define SAMPPROD spx_int32_t
 #define SAMP_MAX 32767
 
 #define SAMP_MIN -SAMP_MAX
diff --git a/vendor/libspeex/libspeexdsp/arch.h b/vendor/libspeex/libspeexdsp/arch.h
index 535d308302..1cac3d9c89 100644
--- a/vendor/libspeex/libspeexdsp/arch.h
+++ b/vendor/libspeex/libspeexdsp/arch.h
@@ -7,18 +7,18 @@
    Redistribution and use in source and binary forms, with or without
    modification, are permitted provided that the following conditions
    are met:
-   
+
    - Redistributions of source code must retain the above copyright
    notice, this list of conditions and the following disclaimer.
-   
+
    - Redistributions in binary form must reproduce the above copyright
    notice, this list of conditions and the following disclaimer in the
    documentation and/or other materials provided with the distribution.
-   
+
    - Neither the name of the Xiph.org Foundation nor the names of its
    contributors may be used to endorse or promote products derived from
    this software without specific prior written permission.
-   
+
    THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
    ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
    LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
@@ -41,10 +41,10 @@
 #ifdef FLOATING_POINT
 #error You cannot compile as floating point and fixed point at the same time
 #endif
-#ifdef _USE_SSE
+#ifdef USE_SSE
 #error SSE is only for floating-point
 #endif
-#if ((defined (ARM4_ASM)||defined (ARM4_ASM)) && defined(BFIN_ASM)) || (defined (ARM4_ASM)&&defined(ARM5E_ASM))
+#if defined(ARM4_ASM) + defined(ARM5E_ASM) + defined(BFIN_ASM) > 1
 #error Make up your mind. What CPU do you have?
 #endif
 #ifdef VORBIS_PSYCHO
@@ -56,10 +56,10 @@
 #ifndef FLOATING_POINT
 #error You now need to define either FIXED_POINT or FLOATING_POINT
 #endif
-#if defined (ARM4_ASM) || defined(ARM5E_ASM) || defined(BFIN_ASM)
+#if defined(ARM4_ASM) || defined(ARM5E_ASM) || defined(BFIN_ASM)
 #error I suppose you can have a [ARM4/ARM5E/Blackfin] that has float instructions?
 #endif
-#ifdef FIXED_POINT_DEBUG
+#ifdef FIXED_DEBUG
 #error "Don't you think enabling fixed-point is a good thing to do if you want to debug that?"
 #endif
 
@@ -101,6 +101,8 @@ typedef spx_word32_t spx_sig_t;
 #define SIG_SHIFT    14
 #define GAIN_SHIFT   6
 
+#define WORD2INT(x) ((x) < -32767 ? -32768 : ((x) > 32766 ? 32767 : (x)))
+
 #define VERY_SMALL 0
 #define VERY_LARGE32 ((spx_word32_t)2147483647)
 #define VERY_LARGE16 ((spx_word16_t)32767)
@@ -115,9 +117,9 @@ typedef spx_word32_t spx_sig_t;
 
 #ifdef ARM5E_ASM
 #include "fixed_arm5e.h"
-#elif defined (ARM4_ASM)
+#elif defined(ARM4_ASM)
 #include "fixed_arm4.h"
-#elif defined (BFIN_ASM)
+#elif defined(BFIN_ASM)
 #include "fixed_bfin.h"
 #endif
 
@@ -175,16 +177,13 @@ typedef float spx_word32_t;
 #define ADD32(a,b) ((a)+(b))
 #define SUB32(a,b) ((a)-(b))
 #define MULT16_16_16(a,b)     ((a)*(b))
+#define MULT16_32_32(a,b)     ((a)*(b))
 #define MULT16_16(a,b)     ((spx_word32_t)(a)*(spx_word32_t)(b))
 #define MAC16_16(c,a,b)     ((c)+(spx_word32_t)(a)*(spx_word32_t)(b))
 
-#define MULT16_32_Q11(a,b)     ((a)*(b))
-#define MULT16_32_Q13(a,b)     ((a)*(b))
-#define MULT16_32_Q14(a,b)     ((a)*(b))
 #define MULT16_32_Q15(a,b)     ((a)*(b))
 #define MULT16_32_P15(a,b)     ((a)*(b))
 
-#define MAC16_32_Q11(c,a,b)     ((c)+(a)*(b))
 #define MAC16_32_Q15(c,a,b)     ((c)+(a)*(b))
 
 #define MAC16_16_Q11(c,a,b)     ((c)+(a)*(b))
@@ -203,18 +202,19 @@ typedef float spx_word32_t;
 #define DIV32(a,b)     (((spx_word32_t)(a))/(spx_word32_t)(b))
 #define PDIV32(a,b)     (((spx_word32_t)(a))/(spx_word32_t)(b))
 
-
+#define WORD2INT(x) ((x) < -32767.5f ? -32768 : \
+                    ((x) > 32766.5f ? 32767 : (spx_int16_t)floor(.5 + (x))))
 #endif
 
 
-#if defined (CONFIG_TI_C54X) || defined (CONFIG_TI_C55X)
+#if defined(CONFIG_TI_C54X) || defined(CONFIG_TI_C55X)
 
 /* 2 on TI C5x DSP */
-#define BYTES_PER_CHAR 2 
+#define BYTES_PER_CHAR 2
 #define BITS_PER_CHAR 16
 #define LOG2_BITS_PER_CHAR 4
 
-#else 
+#else
 
 #define BYTES_PER_CHAR 1
 #define BITS_PER_CHAR 8
diff --git a/vendor/libspeex/libspeexdsp/buffer.c b/vendor/libspeex/libspeexdsp/buffer.c
index c82cab5bc5..b06a155434 100644
--- a/vendor/libspeex/libspeexdsp/buffer.c
+++ b/vendor/libspeex/libspeexdsp/buffer.c
@@ -1,5 +1,5 @@
 /* Copyright (C) 2007 Jean-Marc Valin
-      
+
    File: buffer.c
    This is a very simple ring buffer implementation. It is not thread-safe
    so you need to do your own locking.
@@ -99,7 +99,7 @@ EXPORT int speex_buffer_write(SpeexBuffer *st, void *_data, int len)
 
 EXPORT int speex_buffer_writezeros(SpeexBuffer *st, int len)
 {
-   /* This is almost the same as for speex_buffer_write() but using 
+   /* This is almost the same as for speex_buffer_write() but using
    SPEEX_MEMSET() instead of SPEEX_COPY(). Update accordingly. */
    int end;
    int end1;
@@ -135,7 +135,7 @@ EXPORT int speex_buffer_read(SpeexBuffer *st, void *_data, int len)
    char *data = _data;
    if (len > st->available)
    {
-      SPEEX_MEMSET(data+st->available, 0, st->size-st->available);
+      SPEEX_MEMSET(data+st->available, 0, len - st->available);
       len = st->available;
    }
    end = st->read_ptr + len;
diff --git a/vendor/libspeex/libspeexdsp/config.h b/vendor/libspeex/libspeexdsp/config.h
index d4a0050a30..a7455d8c39 100644
--- a/vendor/libspeex/libspeexdsp/config.h
+++ b/vendor/libspeex/libspeexdsp/config.h
@@ -3,19 +3,19 @@
 
 // In Visual Studio, _M_IX86_FP=1 means /arch:SSE was used, likewise
 // _M_IX86_FP=2 means /arch:SSE2 was used.
-// Also, enable both _USE_SSE and _USE_SSE2 if we're compiling for x86-64
+// Also, enable both USE_SSE and USE_SSE2 if we're compiling for x86-64
 #if _M_IX86_FP >= 1 || defined(_M_X64)
-#define _USE_SSE
+#define USE_SSE
 #endif
 
 #if _M_IX86_FP >= 2 || defined(_M_X64)
-#define _USE_SSE2
+#define USE_SSE2
 #endif
 
 // Visual Studio support alloca(), but it always align variables to 16-bit
 // boundary, while SSE need 128-bit alignment. So we disable alloca() when
 // SSE is enabled.
-#ifndef _USE_SSE
+#ifndef USE_SSE
 #  define USE_ALLOCA
 #endif
 
diff --git a/vendor/libspeex/libspeexdsp/fftwrap.c b/vendor/libspeex/libspeexdsp/fftwrap.c
index a14b1e4fb0..4573479d00 100644
--- a/vendor/libspeex/libspeexdsp/fftwrap.c
+++ b/vendor/libspeex/libspeexdsp/fftwrap.c
@@ -1,23 +1,23 @@
-/* Copyright (C) 2005-2006 Jean-Marc Valin 
+/* Copyright (C) 2005-2006 Jean-Marc Valin
    File: fftwrap.c
 
-   Wrapper for various FFTs 
+   Wrapper for various FFTs
 
    Redistribution and use in source and binary forms, with or without
    modification, are permitted provided that the following conditions
    are met:
-   
+
    - Redistributions of source code must retain the above copyright
    notice, this list of conditions and the following disclaimer.
-   
+
    - Redistributions in binary form must reproduce the above copyright
    notice, this list of conditions and the following disclaimer in the
    documentation and/or other materials provided with the distribution.
-   
+
    - Neither the name of the Xiph.org Foundation nor the names of its
    contributors may be used to endorse or promote products derived from
    this software without specific prior written permission.
-   
+
    THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
    ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
    LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
@@ -62,7 +62,7 @@ static int maximize_range(spx_word16_t *in, spx_word16_t *out, spx_word16_t boun
    for (i=0;iifft);
-  
+
   for(i=0;i
 #include "math_approx.h"
 #include "os_support.h"
-      
+
 #ifdef FIXED_POINT
 
 #define toBARK(n)   (MULT16_16(26829,spx_atan(SHR32(MULT16_16(97,n),2))) + MULT16_16(4588,spx_atan(MULT16_32_Q15(20,MULT16_16(n,n)))) + MULT16_16(3355,n))
-      
+
 #else
 #define toBARK(n)   (13.1f*atan(.00074f*(n))+2.24f*atan((n)*(n)*1.85e-8f)+1e-4f*(n))
 #endif
-       
+
 #define toMEL(n)    (2595.f*log10(1.f+(n)/700.f))
 
 FilterBank *filterbank_new(int banks, spx_word32_t sampling, int len, int type)
@@ -62,7 +62,7 @@ FilterBank *filterbank_new(int banks, spx_word32_t sampling, int len, int type)
    df = DIV32(SHL32(sampling,15),MULT16_16(2,len));
    max_mel = toBARK(EXTRACT16(sampling/2));
    mel_interval = PDIV32(max_mel,banks-1);
-   
+
    bank = (FilterBank*)speex_alloc(sizeof(FilterBank));
    bank->nb_banks = banks;
    bank->len = len;
@@ -85,7 +85,7 @@ FilterBank *filterbank_new(int banks, spx_word32_t sampling, int len, int type)
          break;
 #ifdef FIXED_POINT
       id1 = DIV32(mel,mel_interval);
-#else      
+#else
       id1 = (int)(floor(mel/mel_interval));
 #endif
       if (id1>banks-2)
@@ -101,7 +101,7 @@ FilterBank *filterbank_new(int banks, spx_word32_t sampling, int len, int type)
       bank->bank_right[i] = id2;
       bank->filter_right[i] = val;
    }
-   
+
    /* Think I can safely disable normalisation for fixed-point (and probably float as well) */
 #ifndef FIXED_POINT
    for (i=0;inb_banks;i++)
diff --git a/vendor/libspeex/libspeexdsp/fixed_arm4.h b/vendor/libspeex/libspeexdsp/fixed_arm4.h
index b6981cae72..a7040b8a9d 100644
--- a/vendor/libspeex/libspeexdsp/fixed_arm4.h
+++ b/vendor/libspeex/libspeexdsp/fixed_arm4.h
@@ -7,18 +7,18 @@
    Redistribution and use in source and binary forms, with or without
    modification, are permitted provided that the following conditions
    are met:
-   
+
    - Redistributions of source code must retain the above copyright
    notice, this list of conditions and the following disclaimer.
-   
+
    - Redistributions in binary form must reproduce the above copyright
    notice, this list of conditions and the following disclaimer in the
    documentation and/or other materials provided with the distribution.
-   
+
    - Neither the name of the Xiph.org Foundation nor the names of its
    contributors may be used to endorse or promote products derived from
    this software without specific prior written permission.
-   
+
    THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
    ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
    LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
@@ -35,19 +35,6 @@
 #ifndef FIXED_ARM4_H
 #define FIXED_ARM4_H
 
-#undef MULT16_32_Q14
-static inline spx_word32_t MULT16_32_Q14(spx_word16_t x, spx_word32_t y) {
-  int res;
-  int dummy;
-  asm (
-        "smull  %0,%1,%2,%3 \n\t"
-        "mov %0, %0, lsr #14 \n\t"
-        "add %0, %0, %1, lsl #18 \n\t"
-   : "=&r"(res), "=&r" (dummy)
-   : "r"(y),"r"((int)x));
-  return(res);
-}
-
 #undef MULT16_32_Q15
 static inline spx_word32_t MULT16_32_Q15(spx_word16_t x, spx_word32_t y) {
   int res;
@@ -109,7 +96,7 @@ static inline short DIV32_16(int a, int b)
          "\tsubs %3, %0, %1, asl #6 \n"
          "\tmovpl %0, %3 \n"
          "\torrpl %2, %2, %4, asl #6 \n"
-         
+
          "\tsubs %3, %0, %1, asl #5 \n"
          "\tmovpl %0, %3 \n"
          "\torrpl %2, %2, %4, asl #5 \n"
diff --git a/vendor/libspeex/libspeexdsp/fixed_arm5e.h b/vendor/libspeex/libspeexdsp/fixed_arm5e.h
index 9b4861c9a7..15c6d5dee1 100644
--- a/vendor/libspeex/libspeexdsp/fixed_arm5e.h
+++ b/vendor/libspeex/libspeexdsp/fixed_arm5e.h
@@ -7,18 +7,18 @@
    Redistribution and use in source and binary forms, with or without
    modification, are permitted provided that the following conditions
    are met:
-   
+
    - Redistributions of source code must retain the above copyright
    notice, this list of conditions and the following disclaimer.
-   
+
    - Redistributions in binary form must reproduce the above copyright
    notice, this list of conditions and the following disclaimer in the
    documentation and/or other materials provided with the distribution.
-   
+
    - Neither the name of the Xiph.org Foundation nor the names of its
    contributors may be used to endorse or promote products derived from
    this software without specific prior written permission.
-   
+
    THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
    ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
    LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
@@ -71,24 +71,6 @@ static inline spx_word32_t MAC16_32_Q15(spx_word32_t a, spx_word16_t x, spx_word
   return(res);
 }
 
-#undef MULT16_32_Q11
-static inline spx_word32_t MULT16_32_Q11(spx_word16_t x, spx_word32_t y) {
-  int res;
-  asm ("smulwb  %0,%1,%2;\n"
-              : "=&r"(res)
-               : "%r"(y<<5),"r"(x));
-  return(res);
-}
-
-#undef MAC16_32_Q11
-static inline spx_word32_t MAC16_32_Q11(spx_word32_t a, spx_word16_t x, spx_word32_t y) {
-  int res;
-  asm ("smlawb  %0,%1,%2,%3;\n"
-              : "=&r"(res)
-               : "%r"(y<<5),"r"(x),"r"(a));
-  return(res);
-}
-
 #undef DIV32_16
 static inline short DIV32_16(int a, int b)
 {
@@ -161,7 +143,7 @@ static inline short DIV32_16(int a, int b)
          "\tsubs %3, %0, %1 \n"
          "\torrpl %2, %2, %4 \n"
          "\tmovpl %0, %3 \n"
-         
+
          "\tmovs %5, %5, lsr #31 \n"
          "\trsbne %2, %2, #0 \n"
    : "=r" (dead1), "=r" (dead2), "=r" (res),
diff --git a/vendor/libspeex/libspeexdsp/fixed_bfin.h b/vendor/libspeex/libspeexdsp/fixed_bfin.h
index 9eb21e3396..9a54d64e65 100644
--- a/vendor/libspeex/libspeexdsp/fixed_bfin.h
+++ b/vendor/libspeex/libspeexdsp/fixed_bfin.h
@@ -8,18 +8,18 @@
    Redistribution and use in source and binary forms, with or without
    modification, are permitted provided that the following conditions
    are met:
-   
+
    - Redistributions of source code must retain the above copyright
    notice, this list of conditions and the following disclaimer.
-   
+
    - Redistributions in binary form must reproduce the above copyright
    notice, this list of conditions and the following disclaimer in the
    documentation and/or other materials provided with the distribution.
-   
+
    - Neither the name of the Xiph.org Foundation nor the names of its
    contributors may be used to endorse or promote products derived from
    this software without specific prior written permission.
-   
+
    THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
    ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
    LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
@@ -68,9 +68,9 @@ static inline spx_word16_t DIV32_16(spx_word32_t a, spx_word16_t b)
 {
    spx_word32_t res, bb;
    bb = b;
-   /* Make the roundinf consistent with the C version 
+   /* Make the roundinf consistent with the C version
       (do we need to do that?)*/
-   if (a<0) 
+   if (a<0)
       a += (b-1);
    __asm__  (
          "P0 = 15;\n\t"
@@ -138,39 +138,4 @@ static inline spx_word32_t MAC16_32_Q15(spx_word32_t c, spx_word16_t a, spx_word
    return res;
 }
 
-#undef MULT16_32_Q14
-static inline spx_word32_t MULT16_32_Q14(spx_word16_t a, spx_word32_t b)
-{
-   spx_word32_t res;
-   __asm__
-         (
-         "%2 <<= 1;\n\t"
-         "A1 = %1.L*%2.L (M);\n\t"
-         "A1 = A1 >>> 15;\n\t"
-         "%0 = (A1 += %1.L*%2.H);\n\t"
-   : "=W" (res), "=d" (a), "=d" (b)
-   : "1" (a), "2" (b)
-   : "A1", "ASTAT"
-         );
-   return res;
-}
-
-#undef MAC16_32_Q14
-static inline spx_word32_t MAC16_32_Q14(spx_word32_t c, spx_word16_t a, spx_word32_t b)
-{
-   spx_word32_t res;
-   __asm__
-         (
-         "%1 <<= 1;\n\t"
-         "A1 = %2.L*%1.L (M);\n\t"
-         "A1 = A1 >>> 15;\n\t"
-         "%0 = (A1 += %2.L*%1.H);\n\t"
-         "%0 = %0 + %4;\n\t"
-   : "=&W" (res), "=&d" (b)
-   : "d" (a), "1" (b), "d" (c)
-   : "A1", "ASTAT"
-         );
-   return res;
-}
-
 #endif
diff --git a/vendor/libspeex/libspeexdsp/fixed_debug.h b/vendor/libspeex/libspeexdsp/fixed_debug.h
index 54f3866e8f..dbf02f191b 100644
--- a/vendor/libspeex/libspeexdsp/fixed_debug.h
+++ b/vendor/libspeex/libspeexdsp/fixed_debug.h
@@ -7,18 +7,18 @@
    Redistribution and use in source and binary forms, with or without
    modification, are permitted provided that the following conditions
    are met:
-   
+
    - Redistributions of source code must retain the above copyright
    notice, this list of conditions and the following disclaimer.
-   
+
    - Redistributions in binary form must reproduce the above copyright
    notice, this list of conditions and the following disclaimer in the
    documentation and/or other materials provided with the distribution.
-   
+
    - Neither the name of the Xiph.org Foundation nor the names of its
    contributors may be used to endorse or promote products derived from
    this software without specific prior written permission.
-   
+
    THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
    ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
    LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
@@ -101,7 +101,7 @@ static inline int _EXTEND32(int x, char *file, int line)
 }
 
 #define SHR16(a, shift) _SHR16(a, shift, __FILE__, __LINE__)
-static inline short _SHR16(int a, int shift, char *file, int line) 
+static inline short _SHR16(int a, int shift, char *file, int line)
 {
    int res;
    if (!VERIFY_SHORT(a) || !VERIFY_SHORT(shift))
@@ -115,7 +115,7 @@ static inline short _SHR16(int a, int shift, char *file, int line)
    return res;
 }
 #define SHL16(a, shift) _SHL16(a, shift, __FILE__, __LINE__)
-static inline short _SHL16(int a, int shift, char *file, int line) 
+static inline short _SHL16(int a, int shift, char *file, int line)
 {
    int res;
    if (!VERIFY_SHORT(a) || !VERIFY_SHORT(shift))
@@ -129,7 +129,7 @@ static inline short _SHL16(int a, int shift, char *file, int line)
    return res;
 }
 
-static inline int SHR32(long long a, int shift) 
+static inline int SHR32(long long a, int shift)
 {
    long long  res;
    if (!VERIFY_INT(a) || !VERIFY_SHORT(shift))
@@ -144,7 +144,7 @@ static inline int SHR32(long long a, int shift)
    spx_mips++;
    return res;
 }
-static inline int SHL32(long long a, int shift) 
+static inline int SHL32(long long a, int shift)
 {
    long long  res;
    if (!VERIFY_INT(a) || !VERIFY_SHORT(shift))
@@ -171,7 +171,7 @@ static inline int SHL32(long long a, int shift)
 //#define SHL(a,shift) ((a) << (shift))
 
 #define ADD16(a, b) _ADD16(a, b, __FILE__, __LINE__)
-static inline short _ADD16(int a, int b, char *file, int line) 
+static inline short _ADD16(int a, int b, char *file, int line)
 {
    int res;
    if (!VERIFY_SHORT(a) || !VERIFY_SHORT(b))
@@ -188,7 +188,7 @@ static inline short _ADD16(int a, int b, char *file, int line)
 }
 
 #define SUB16(a, b) _SUB16(a, b, __FILE__, __LINE__)
-static inline short _SUB16(int a, int b, char *file, int line) 
+static inline short _SUB16(int a, int b, char *file, int line)
 {
    int res;
    if (!VERIFY_SHORT(a) || !VERIFY_SHORT(b))
@@ -203,7 +203,7 @@ static inline short _SUB16(int a, int b, char *file, int line)
 }
 
 #define ADD32(a, b) _ADD32(a, b, __FILE__, __LINE__)
-static inline int _ADD32(long long a, long long b, char *file, int line) 
+static inline int _ADD32(long long a, long long b, char *file, int line)
 {
    long long res;
    if (!VERIFY_INT(a) || !VERIFY_INT(b))
@@ -219,7 +219,7 @@ static inline int _ADD32(long long a, long long b, char *file, int line)
    return res;
 }
 
-static inline int SUB32(long long a, long long b) 
+static inline int SUB32(long long a, long long b)
 {
    long long res;
    if (!VERIFY_INT(a) || !VERIFY_INT(b))
@@ -236,7 +236,7 @@ static inline int SUB32(long long a, long long b)
 #define ADD64(a,b) (MIPS_INC(a)+(b))
 
 /* result fits in 16 bits */
-static inline short MULT16_16_16(int a, int b) 
+static inline short MULT16_16_16(int a, int b)
 {
    int res;
    if (!VERIFY_SHORT(a) || !VERIFY_SHORT(b))
@@ -250,8 +250,23 @@ static inline short MULT16_16_16(int a, int b)
    return res;
 }
 
+/* result fits in 32 bits */
+static inline int MULT16_32_32(int a, long long b)
+{
+   long long res;
+   if (!VERIFY_SHORT(a) || !VERIFY_INT(b))
+   {
+      fprintf (stderr, "MULT16_32_32: inputs are not short+int: %d %d\n", a, (int)b);
+   }
+   res = a*b;
+   if (!VERIFY_INT(res))
+      fprintf (stderr, "MULT16_32_32: output is not int: %d\n", (int)res);
+   spx_mips++;
+   return res;
+}
+
 #define MULT16_16(a, b) _MULT16_16(a, b, __FILE__, __LINE__)
-static inline int _MULT16_16(int a, int b, char *file, int line) 
+static inline int _MULT16_16(int a, int b, char *file, int line)
 {
    long long res;
    if (!VERIFY_SHORT(a) || !VERIFY_SHORT(b))
@@ -279,8 +294,8 @@ static inline int _MULT16_32_QX(int a, long long b, int Q, char *file, int line)
    {
       fprintf (stderr, "MULT16_32_Q%d: inputs are not short+int: %d %d in %s: line %d\n", Q, (int)a, (int)b, file, line);
    }
-   if (ABS32(b)>=(EXTEND32(1)<<(15+Q)))
-      fprintf (stderr, "MULT16_32_Q%d: second operand too large: %d %d in %s: line %d\n", Q, (int)a, (int)b, file, line);      
+   if (ABS(b)>>(16+Q))
+      fprintf (stderr, "MULT16_32_Q%d: second operand too large: %d %d in %s: line %d\n", Q, (int)a, (int)b, file, line);
    res = (((long long)a)*(long long)b) >> Q;
    if (!VERIFY_INT(res))
       fprintf (stderr, "MULT16_32_Q%d: output is not int: %d*%d=%d in %s: line %d\n", Q, (int)a, (int)b,(int)res, file, line);
@@ -295,8 +310,8 @@ static inline int MULT16_32_PX(int a, long long b, int Q)
    {
       fprintf (stderr, "MULT16_32_P%d: inputs are not short+int: %d %d\n", Q, (int)a, (int)b);
    }
-   if (ABS32(b)>=(EXTEND32(1)<<(15+Q)))
-      fprintf (stderr, "MULT16_32_Q%d: second operand too large: %d %d\n", Q, (int)a, (int)b);      
+   if (ABS(b)>>(16+Q))
+      fprintf (stderr, "MULT16_32_Q%d: second operand too large: %d %d\n", Q, (int)a, (int)b);
    res = ((((long long)a)*(long long)b) + ((EXTEND32(1)<>1))>> Q;
    if (!VERIFY_INT(res))
       fprintf (stderr, "MULT16_32_P%d: output is not int: %d*%d=%d\n", Q, (int)a, (int)b,(int)res);
@@ -305,11 +320,6 @@ static inline int MULT16_32_PX(int a, long long b, int Q)
 }
 
 
-#define MULT16_32_Q11(a,b) MULT16_32_QX(a,b,11)
-#define MAC16_32_Q11(c,a,b) ADD32((c),MULT16_32_Q11((a),(b)))
-#define MULT16_32_Q12(a,b) MULT16_32_QX(a,b,12)
-#define MULT16_32_Q13(a,b) MULT16_32_QX(a,b,13)
-#define MULT16_32_Q14(a,b) MULT16_32_QX(a,b,14)
 #define MULT16_32_Q15(a,b) MULT16_32_QX(a,b,15)
 #define MULT16_32_P15(a,b) MULT16_32_PX(a,b,15)
 #define MAC16_32_Q15(c,a,b) ADD32((c),MULT16_32_Q15((a),(b)))
@@ -323,7 +333,7 @@ static inline int SATURATE(int a, int b)
    return a;
 }
 
-static inline int MULT16_16_Q11_32(int a, int b) 
+static inline int MULT16_16_Q11_32(int a, int b)
 {
    long long res;
    if (!VERIFY_SHORT(a) || !VERIFY_SHORT(b))
@@ -337,7 +347,7 @@ static inline int MULT16_16_Q11_32(int a, int b)
    spx_mips+=3;
    return res;
 }
-static inline short MULT16_16_Q13(int a, int b) 
+static inline short MULT16_16_Q13(int a, int b)
 {
    long long res;
    if (!VERIFY_SHORT(a) || !VERIFY_SHORT(b))
@@ -351,7 +361,7 @@ static inline short MULT16_16_Q13(int a, int b)
    spx_mips+=3;
    return res;
 }
-static inline short MULT16_16_Q14(int a, int b) 
+static inline short MULT16_16_Q14(int a, int b)
 {
    long long res;
    if (!VERIFY_SHORT(a) || !VERIFY_SHORT(b))
@@ -365,7 +375,7 @@ static inline short MULT16_16_Q14(int a, int b)
    spx_mips+=3;
    return res;
 }
-static inline short MULT16_16_Q15(int a, int b) 
+static inline short MULT16_16_Q15(int a, int b)
 {
    long long res;
    if (!VERIFY_SHORT(a) || !VERIFY_SHORT(b))
@@ -382,7 +392,7 @@ static inline short MULT16_16_Q15(int a, int b)
    return res;
 }
 
-static inline short MULT16_16_P13(int a, int b) 
+static inline short MULT16_16_P13(int a, int b)
 {
    long long res;
    if (!VERIFY_SHORT(a) || !VERIFY_SHORT(b))
@@ -399,7 +409,7 @@ static inline short MULT16_16_P13(int a, int b)
    spx_mips+=4;
    return res;
 }
-static inline short MULT16_16_P14(int a, int b) 
+static inline short MULT16_16_P14(int a, int b)
 {
    long long res;
    if (!VERIFY_SHORT(a) || !VERIFY_SHORT(b))
@@ -416,7 +426,7 @@ static inline short MULT16_16_P14(int a, int b)
    spx_mips+=4;
    return res;
 }
-static inline short MULT16_16_P15(int a, int b) 
+static inline short MULT16_16_P15(int a, int b)
 {
    long long res;
    if (!VERIFY_SHORT(a) || !VERIFY_SHORT(b))
@@ -436,7 +446,7 @@ static inline short MULT16_16_P15(int a, int b)
 
 #define DIV32_16(a, b) _DIV32_16(a, b, __FILE__, __LINE__)
 
-static inline int _DIV32_16(long long a, long long b, char *file, int line) 
+static inline int _DIV32_16(long long a, long long b, char *file, int line)
 {
    long long res;
    if (b==0)
@@ -462,7 +472,7 @@ static inline int _DIV32_16(long long a, long long b, char *file, int line)
 }
 
 #define DIV32(a, b) _DIV32(a, b, __FILE__, __LINE__)
-static inline int _DIV32(long long a, long long b, char *file, int line) 
+static inline int _DIV32(long long a, long long b, char *file, int line)
 {
    long long res;
    if (b==0)
diff --git a/vendor/libspeex/libspeexdsp/fixed_generic.h b/vendor/libspeex/libspeexdsp/fixed_generic.h
index 0e012e9ab1..09366c36ce 100644
--- a/vendor/libspeex/libspeexdsp/fixed_generic.h
+++ b/vendor/libspeex/libspeexdsp/fixed_generic.h
@@ -7,18 +7,18 @@
    Redistribution and use in source and binary forms, with or without
    modification, are permitted provided that the following conditions
    are met:
-   
+
    - Redistributions of source code must retain the above copyright
    notice, this list of conditions and the following disclaimer.
-   
+
    - Redistributions in binary form must reproduce the above copyright
    notice, this list of conditions and the following disclaimer in the
    documentation and/or other materials provided with the distribution.
-   
+
    - Neither the name of the Xiph.org Foundation nor the names of its
    contributors may be used to endorse or promote products derived from
    this software without specific prior written permission.
-   
+
    THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
    ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
    LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
@@ -69,22 +69,18 @@
 
 
 /* result fits in 16 bits */
-#define MULT16_16_16(a,b)     ((((spx_word16_t)(a))*((spx_word16_t)(b))))
+#define MULT16_16_16(a,b)     (((spx_word16_t)(a))*((spx_word16_t)(b)))
+/* result fits in 32 bits */
+#define MULT16_32_32(a,b)     (((spx_word16_t)(a))*((spx_word32_t)(b)))
 
 /* (spx_word32_t)(spx_word16_t) gives TI compiler a hint that it's 16x16->32 multiply */
 #define MULT16_16(a,b)     (((spx_word32_t)(spx_word16_t)(a))*((spx_word32_t)(spx_word16_t)(b)))
 
 #define MAC16_16(c,a,b) (ADD32((c),MULT16_16((a),(b))))
-#define MULT16_32_Q12(a,b) ADD32(MULT16_16((a),SHR((b),12)), SHR(MULT16_16((a),((b)&0x00000fff)),12))
-#define MULT16_32_Q13(a,b) ADD32(MULT16_16((a),SHR((b),13)), SHR(MULT16_16((a),((b)&0x00001fff)),13))
-#define MULT16_32_Q14(a,b) ADD32(MULT16_16((a),SHR((b),14)), SHR(MULT16_16((a),((b)&0x00003fff)),14))
-
-#define MULT16_32_Q11(a,b) ADD32(MULT16_16((a),SHR((b),11)), SHR(MULT16_16((a),((b)&0x000007ff)),11))
-#define MAC16_32_Q11(c,a,b) ADD32(c,ADD32(MULT16_16((a),SHR((b),11)), SHR(MULT16_16((a),((b)&0x000007ff)),11)))
 
-#define MULT16_32_P15(a,b) ADD32(MULT16_16((a),SHR((b),15)), PSHR(MULT16_16((a),((b)&0x00007fff)),15))
-#define MULT16_32_Q15(a,b) ADD32(MULT16_16((a),SHR((b),15)), SHR(MULT16_16((a),((b)&0x00007fff)),15))
-#define MAC16_32_Q15(c,a,b) ADD32(c,ADD32(MULT16_16((a),SHR((b),15)), SHR(MULT16_16((a),((b)&0x00007fff)),15)))
+#define MULT16_32_P15(a,b) ADD32(MULT16_32_32(a,SHR((b),15)), PSHR(MULT16_16((a),((b)&0x00007fff)),15))
+#define MULT16_32_Q15(a,b) ADD32(MULT16_32_32(a,SHR((b),15)), SHR(MULT16_16((a),((b)&0x00007fff)),15))
+#define MAC16_32_Q15(c,a,b) ADD32(c,MULT16_32_Q15(a,b))
 
 
 #define MAC16_16_Q11(c,a,b)     (ADD32((c),SHR(MULT16_16((a),(b)),11)))
diff --git a/vendor/libspeex/libspeexdsp/jitter.c b/vendor/libspeex/libspeexdsp/jitter.c
index a077d8dd41..4441a821d1 100644
--- a/vendor/libspeex/libspeexdsp/jitter.c
+++ b/vendor/libspeex/libspeexdsp/jitter.c
@@ -1,4 +1,4 @@
-/* Copyright (C) 2002 Jean-Marc Valin 
+/* Copyright (C) 2002 Jean-Marc Valin
    File: speex_jitter.h
 
    Adaptive jitter buffer for Speex
@@ -6,18 +6,18 @@
    Redistribution and use in source and binary forms, with or without
    modification, are permitted provided that the following conditions
    are met:
-   
+
    - Redistributions of source code must retain the above copyright
    notice, this list of conditions and the following disclaimer.
-   
+
    - Redistributions in binary form must reproduce the above copyright
    notice, this list of conditions and the following disclaimer in the
    documentation and/or other materials provided with the distribution.
-   
+
    - Neither the name of the Xiph.org Foundation nor the names of its
    contributors may be used to endorse or promote products derived from
    this software without specific prior written permission.
-   
+
    THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
    ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
    LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
@@ -71,7 +71,7 @@
 #define LT32(a,b) (((spx_int32_t)((a)-(b)))<0)
 #define LE32(a,b) (((spx_int32_t)((a)-(b)))<=0)
 
-#define ROUND_DOWN(x, step) ((x)<0 ? ((x)-(step)+1)/(step)*(step) : (x)/(step)*(step)) 
+#define ROUND_DOWN(x, step) ((x)<0 ? ((x)-(step)+1)/(step)*(step) : (x)/(step)*(step))
 
 #define MAX_TIMINGS 40
 #define MAX_BUFFERS 3
@@ -101,7 +101,7 @@ static void tb_add(struct TimingBuffer *tb, spx_int16_t timing)
       tb->curr_count++;
       return;
    }
-   
+
    /* Find where the timing info goes in the sorted list */
    pos = 0;
    /* FIXME: Do bisection instead of linear search */
@@ -109,9 +109,9 @@ static void tb_add(struct TimingBuffer *tb, spx_int16_t timing)
    {
       pos++;
    }
-   
+
    speex_assert(pos <= tb->filled && pos < MAX_TIMINGS);
-   
+
    /* Shift everything so we can perform the insertion */
    if (pos < tb->filled)
    {
@@ -124,7 +124,7 @@ static void tb_add(struct TimingBuffer *tb, spx_int16_t timing)
    /* Insert */
    tb->timing[pos] = timing;
    tb->counts[pos] = tb->curr_count;
-   
+
    tb->curr_count++;
    if (tb->filledfilled++;
@@ -137,12 +137,12 @@ struct JitterBuffer_ {
    spx_uint32_t pointer_timestamp;                             /**< Timestamp of what we will *get* next */
    spx_uint32_t last_returned_timestamp;                       /**< Useful for getting the next packet with the same timestamp (for fragmented media) */
    spx_uint32_t next_stop;                                     /**< Estimated time the next get() will be called */
-   
+
    spx_int32_t buffered;                                       /**< Amount of data we think is still buffered by the application (timestamp units)*/
-   
+
    JitterBufferPacket packets[SPEEX_JITTER_MAX_BUFFER_SIZE];   /**< Packets stored in the buffer */
    spx_uint32_t arrival[SPEEX_JITTER_MAX_BUFFER_SIZE];         /**< Packet arrival time (0 means it was late, even though it's a valid timestamp) */
-   
+
    void (*destroy) (void *);                                   /**< Callback for destroying a packet */
 
    spx_int32_t delay_step;                                     /**< Size of the steps when adjusting buffering (timestamp units) */
@@ -152,7 +152,7 @@ struct JitterBuffer_ {
    int late_cutoff;                                            /**< How late must a packet be for it not to be considered at all */
    int interp_requested;                                       /**< An interpolation is requested by speex_jitter_update_delay() */
    int auto_adjust;                                            /**< Whether to automatically adjust the delay at any time */
-   
+
    struct TimingBuffer _tb[MAX_BUFFERS];                       /**< Don't use those directly */
    struct TimingBuffer *timeBuffers[MAX_BUFFERS];              /**< Storing arrival time of latest frames so we can compute some stats */
    int window_size;                                            /**< Total window over which the late frames are counted */
@@ -160,15 +160,15 @@ struct JitterBuffer_ {
    int max_late_rate;                                          /**< Absolute maximum amount of late packets tolerable (in percent) */
    int latency_tradeoff;                                       /**< Latency equivalent of losing one percent of packets */
    int auto_tradeoff;                                          /**< Latency equivalent of losing one percent of packets (automatic default) */
-   
+
    int lost_count;                                             /**< Number of consecutive lost packets  */
 };
 
-/** Based on available data, this computes the optimal delay for the jitter buffer. 
+/** Based on available data, this computes the optimal delay for the jitter buffer.
    The optimised function is in timestamp units and is:
    cost = delay + late_factor*[number of frames that would be late if we used that delay]
    @param tb Array of buffers
-   @param late_factor Equivalent cost of a late frame (in timestamp units) 
+   @param late_factor Equivalent cost of a late frame (in timestamp units)
  */
 static spx_int16_t compute_opt_delay(JitterBuffer *jitter)
 {
@@ -184,34 +184,34 @@ static spx_int16_t compute_opt_delay(JitterBuffer *jitter)
    int worst = 0;
    spx_int32_t deltaT;
    struct TimingBuffer *tb;
-   
+
    tb = jitter->_tb;
-   
+
    /* Number of packet timings we have received (including those we didn't keep) */
    tot_count = 0;
    for (i=0;ilatency_tradeoff != 0)
       late_factor = jitter->latency_tradeoff * 100.0f / tot_count;
    else
       late_factor = jitter->auto_tradeoff * jitter->window_size/tot_count;
-   
+
    /*fprintf(stderr, "late_factor = %f\n", late_factor);*/
    for (i=0;idelay_step);
          pos[next]++;
-         
+
          /* Actual cost function that tells us how bad using this delay would be */
          cost = -latest + late_factor*late;
          /*fprintf(stderr, "cost %d = %d + %f * %d\n", cost, -latest, late_factor, late);*/
@@ -241,7 +241,7 @@ static spx_int16_t compute_opt_delay(JitterBuffer *jitter)
       } else {
          break;
       }
-      
+
       /* For the next timing we will consider, there will be one more late packet to count */
       late++;
       /* Two-frame penalty if we're going to increase the amount of late frames (hysteresis) */
@@ -251,14 +251,14 @@ static spx_int16_t compute_opt_delay(JitterBuffer *jitter)
          late+=4;
       }
    }
-   
+
    deltaT = best-worst;
    /* This is a default "automatic latency tradeoff" when none is provided */
    jitter->auto_tradeoff = 1 + deltaT/TOP_DELAY;
    /*fprintf(stderr, "auto_tradeoff = %d (%d %d %d)\n", jitter->auto_tradeoff, best, worst, i);*/
-   
+
    /* FIXME: Compute a short-term estimate too and combine with the long-term one */
-   
+
    /* Prevents reducing the buffer size when we haven't really had much data */
    if (tot_count < TOP_DELAY && opt > 0)
       return 0;
@@ -313,7 +313,7 @@ EXPORT void jitter_buffer_reset(JitterBuffer *jitter)
    jitter->lost_count = 0;
    jitter->buffered = 0;
    jitter->auto_tradeoff = 32000;
-   
+
    for (i=0;i_tb[i]);
@@ -368,7 +368,7 @@ EXPORT void jitter_buffer_put(JitterBuffer *jitter, const JitterBufferPacket *pa
    int i,j;
    int late;
    /*fprintf (stderr, "put packet %d %d\n", timestamp, span);*/
-   
+
    /* Cleanup buffer (remove old packets that weren't played) */
    if (!jitter->reset_state)
    {
@@ -386,7 +386,7 @@ EXPORT void jitter_buffer_put(JitterBuffer *jitter, const JitterBufferPacket *pa
          }
       }
    }
-   
+
    /*fprintf(stderr, "arrival: %d %d %d\n", packet->timestamp, jitter->next_stop, jitter->pointer_timestamp);*/
    /* Check if packet is late (could still be useful though) */
    if (!jitter->reset_state && LT32(packet->timestamp, jitter->next_stop))
@@ -403,7 +403,7 @@ EXPORT void jitter_buffer_put(JitterBuffer *jitter, const JitterBufferPacket *pa
    {
       jitter_buffer_reset(jitter);
    }
-   
+
    /* Only insert the packet if it's not hopelessly late (i.e. totally useless) */
    if (jitter->reset_state || GE32(packet->timestamp+packet->span+jitter->delay_step, jitter->pointer_timestamp))
    {
@@ -414,7 +414,7 @@ EXPORT void jitter_buffer_put(JitterBuffer *jitter, const JitterBufferPacket *pa
          if (jitter->packets[i].data==NULL)
             break;
       }
-      
+
       /*No place left in the buffer, need to make room for it by discarding the oldest packet */
       if (i==SPEEX_JITTER_MAX_BUFFER_SIZE)
       {
@@ -433,9 +433,9 @@ EXPORT void jitter_buffer_put(JitterBuffer *jitter, const JitterBufferPacket *pa
          else
             speex_free(jitter->packets[i].data);
          jitter->packets[i].data=NULL;
-         /*fprintf (stderr, "Buffer is full, discarding earliest frame %d (currently at %d)\n", timestamp, jitter->pointer_timestamp);*/      
+         /*fprintf (stderr, "Buffer is full, discarding earliest frame %d (currently at %d)\n", timestamp, jitter->pointer_timestamp);*/
       }
-   
+
       /* Copy packet in buffer */
       if (jitter->destroy)
       {
@@ -455,8 +455,8 @@ EXPORT void jitter_buffer_put(JitterBuffer *jitter, const JitterBufferPacket *pa
       else
          jitter->arrival[i] = jitter->next_stop;
    }
-   
-   
+
+
 }
 
 /** Get one packet from the jitter buffer */
@@ -465,7 +465,7 @@ EXPORT int jitter_buffer_get(JitterBuffer *jitter, JitterBufferPacket *packet, s
    int i;
    unsigned int j;
    spx_int16_t opt;
-   
+
    if (start_offset != NULL)
       *start_offset = 0;
 
@@ -485,7 +485,7 @@ EXPORT int jitter_buffer_get(JitterBuffer *jitter, JitterBufferPacket *packet, s
       }
       if (found)
       {
-         jitter->reset_state=0;         
+         jitter->reset_state=0;
          jitter->pointer_timestamp = oldest;
          jitter->next_stop = oldest;
       } else {
@@ -494,36 +494,36 @@ EXPORT int jitter_buffer_get(JitterBuffer *jitter, JitterBufferPacket *packet, s
          return JITTER_BUFFER_MISSING;
       }
    }
-   
+
 
    jitter->last_returned_timestamp = jitter->pointer_timestamp;
-         
+
    if (jitter->interp_requested != 0)
    {
       packet->timestamp = jitter->pointer_timestamp;
       packet->span = jitter->interp_requested;
-      
+
       /* Increment the pointer because it got decremented in the delay update */
       jitter->pointer_timestamp += jitter->interp_requested;
       packet->len = 0;
       /*fprintf (stderr, "Deferred interpolate\n");*/
-      
+
       jitter->interp_requested = 0;
-      
+
       jitter->buffered = packet->span - desired_span;
 
       return JITTER_BUFFER_INSERTION;
    }
-   
+
    /* Searching for the packet that fits best */
-   
+
    /* Search the buffer for a packet with the right timestamp and spanning the whole current chunk */
    for (i=0;ipackets[i].data && jitter->packets[i].timestamp==jitter->pointer_timestamp && GE32(jitter->packets[i].timestamp+jitter->packets[i].span,jitter->pointer_timestamp+desired_span))
          break;
    }
-   
+
    /* If no match, try for an "older" packet that still spans (fully) the current chunk */
    if (i==SPEEX_JITTER_MAX_BUFFER_SIZE)
    {
@@ -533,7 +533,7 @@ EXPORT int jitter_buffer_get(JitterBuffer *jitter, JitterBufferPacket *packet, s
             break;
       }
    }
-   
+
    /* If still no match, try for an "older" packet that spans part of the current chunk */
    if (i==SPEEX_JITTER_MAX_BUFFER_SIZE)
    {
@@ -543,7 +543,7 @@ EXPORT int jitter_buffer_get(JitterBuffer *jitter, JitterBufferPacket *packet, s
             break;
       }
    }
-   
+
    /* If still no match, try for earliest packet possible */
    if (i==SPEEX_JITTER_MAX_BUFFER_SIZE)
    {
@@ -576,17 +576,17 @@ EXPORT int jitter_buffer_get(JitterBuffer *jitter, JitterBufferPacket *packet, s
    if (i!=SPEEX_JITTER_MAX_BUFFER_SIZE)
    {
       spx_int32_t offset;
-      
+
       /* We (obviously) haven't lost this packet */
       jitter->lost_count = 0;
-      
+
       /* In this case, 0 isn't as a valid timestamp */
       if (jitter->arrival[i] != 0)
       {
          update_timings(jitter, ((spx_int32_t)jitter->packets[i].timestamp) - ((spx_int32_t)jitter->arrival[i]) - jitter->buffer_margin);
       }
-      
-      
+
+
       /* Copy packet */
       if (jitter->destroy)
       {
@@ -611,10 +611,10 @@ EXPORT int jitter_buffer_get(JitterBuffer *jitter, JitterBufferPacket *packet, s
          *start_offset = offset;
       else if (offset != 0)
          speex_warning_int("jitter_buffer_get() discarding non-zero start_offset", offset);
-      
+
       packet->timestamp = jitter->packets[i].timestamp;
       jitter->last_returned_timestamp = packet->timestamp;
-      
+
       packet->span = jitter->packets[i].span;
       packet->sequence = jitter->packets[i].sequence;
       packet->user_data = jitter->packets[i].user_data;
@@ -622,36 +622,36 @@ EXPORT int jitter_buffer_get(JitterBuffer *jitter, JitterBufferPacket *packet, s
       jitter->pointer_timestamp = jitter->packets[i].timestamp+jitter->packets[i].span;
 
       jitter->buffered = packet->span - desired_span;
-      
+
       if (start_offset != NULL)
          jitter->buffered += *start_offset;
-      
+
       return JITTER_BUFFER_OK;
    }
-   
-   
+
+
    /* If we haven't found anything worth returning */
-   
+
    /*fprintf (stderr, "not found\n");*/
    jitter->lost_count++;
    /*fprintf (stderr, "m");*/
    /*fprintf (stderr, "lost_count = %d\n", jitter->lost_count);*/
-   
+
    opt = compute_opt_delay(jitter);
-   
-   /* Should we force an increase in the buffer or just do normal interpolation? */   
+
+   /* Should we force an increase in the buffer or just do normal interpolation? */
    if (opt < 0)
    {
       /* Need to increase buffering */
-      
+
       /* Shift histogram to compensate */
       shift_timings(jitter, -opt);
-      
+
       packet->timestamp = jitter->pointer_timestamp;
       packet->span = -opt;
       /* Don't move the pointer_timestamp forward */
       packet->len = 0;
-      
+
       jitter->buffered = packet->span - desired_span;
       return JITTER_BUFFER_INSERTION;
       /*jitter->pointer_timestamp -= jitter->delay_step;*/
@@ -659,12 +659,12 @@ EXPORT int jitter_buffer_get(JitterBuffer *jitter, JitterBufferPacket *packet, s
    } else {
       /* Normal packet loss */
       packet->timestamp = jitter->pointer_timestamp;
-      
+
       desired_span = ROUND_DOWN(desired_span, jitter->concealment_size);
       packet->span = desired_span;
       jitter->pointer_timestamp += desired_span;
       packet->len = 0;
-      
+
       jitter->buffered = packet->span - desired_span;
       return JITTER_BUFFER_MISSING;
       /*fprintf (stderr, "Normal loss\n");*/
@@ -713,11 +713,11 @@ static int _jitter_buffer_update_delay(JitterBuffer *jitter, JitterBufferPacket
 {
    spx_int16_t opt = compute_opt_delay(jitter);
    /*fprintf(stderr, "opt adjustment is %d ", opt);*/
-   
+
    if (opt < 0)
    {
       shift_timings(jitter, -opt);
-      
+
       jitter->pointer_timestamp += opt;
       jitter->interp_requested = -opt;
       /*fprintf (stderr, "Decision to interpolate %d samples\n", -opt);*/
@@ -727,14 +727,14 @@ static int _jitter_buffer_update_delay(JitterBuffer *jitter, JitterBufferPacket
       jitter->pointer_timestamp += opt;
       /*fprintf (stderr, "Decision to drop %d samples\n", opt);*/
    }
-   
+
    return opt;
 }
 
 /* Let the jitter buffer know it's the right time to adjust the buffering delay to the network conditions */
 EXPORT int jitter_buffer_update_delay(JitterBuffer *jitter, JitterBufferPacket *packet, spx_int32_t *start_offset)
 {
-   /* If the programmer calls jitter_buffer_update_delay() directly, 
+   /* If the programmer calls jitter_buffer_update_delay() directly,
       automatically disable auto-adjustment */
    jitter->auto_adjust = 0;
 
@@ -752,7 +752,7 @@ EXPORT void jitter_buffer_tick(JitterBuffer *jitter)
    /* Automatically-adjust the buffering delay if requested */
    if (jitter->auto_adjust)
       _jitter_buffer_update_delay(jitter, NULL, NULL);
-   
+
    if (jitter->buffered >= 0)
    {
       jitter->next_stop = jitter->pointer_timestamp - jitter->buffered;
@@ -768,7 +768,7 @@ EXPORT void jitter_buffer_remaining_span(JitterBuffer *jitter, spx_uint32_t rem)
    /* Automatically-adjust the buffering delay if requested */
    if (jitter->auto_adjust)
       _jitter_buffer_update_delay(jitter, NULL, NULL);
-   
+
    if (jitter->buffered < 0)
       speex_warning_int("jitter buffer sees negative buffering, your code might be broken. Value is ", jitter->buffered);
    jitter->next_stop = jitter->pointer_timestamp - rem;
diff --git a/vendor/libspeex/libspeexdsp/kiss_fft.c b/vendor/libspeex/libspeexdsp/kiss_fft.c
index 67782810fe..8dc9345428 100644
--- a/vendor/libspeex/libspeexdsp/kiss_fft.c
+++ b/vendor/libspeex/libspeexdsp/kiss_fft.c
@@ -23,7 +23,7 @@ THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
 #include "os_support.h"
 
 /* The guts header contains all the multiplication and addition macros that are defined for
- fixed or floating point complex numbers.  It also delares the kf_ internal functions.
+ fixed or floating point complex numbers.  It also declares the kf_ internal functions.
  */
 
 static void kf_bfly2(
@@ -110,7 +110,7 @@ static void kf_bfly4(
              C_MUL(scratch[0],Fout[m] , *tw1 );
              C_MUL(scratch[1],Fout[m2] , *tw2 );
              C_MUL(scratch[2],Fout[m3] , *tw3 );
-             
+
              C_SUB( scratch[5] , *Fout, scratch[1] );
              C_ADDTO(*Fout, scratch[1]);
              C_ADD( scratch[3] , scratch[0] , scratch[2] );
@@ -120,7 +120,7 @@ static void kf_bfly4(
              tw2 += fstride*2;
              tw3 += fstride*3;
              C_ADDTO( *Fout , scratch[3] );
-             
+
              Fout[m].r = scratch[5].r - scratch[4].i;
              Fout[m].i = scratch[5].i + scratch[4].r;
              Fout[m3].r = scratch[5].r + scratch[4].i;
@@ -140,7 +140,7 @@ static void kf_bfly4(
              C_MUL4(scratch[0],Fout[m] , *tw1 );
              C_MUL4(scratch[1],Fout[m2] , *tw2 );
              C_MUL4(scratch[2],Fout[m3] , *tw3 );
-             
+
              Fout->r = PSHR16(Fout->r, 2);
              Fout->i = PSHR16(Fout->i, 2);
              C_SUB( scratch[5] , *Fout, scratch[1] );
@@ -154,7 +154,7 @@ static void kf_bfly4(
              tw2 += fstride*2;
              tw3 += fstride*3;
              C_ADDTO( *Fout , scratch[3] );
-             
+
              Fout[m].r = scratch[5].r + scratch[4].i;
              Fout[m].i = scratch[5].i - scratch[4].r;
              Fout[m3].r = scratch[5].r - scratch[4].i;
@@ -292,7 +292,7 @@ static void kf_bfly_generic(
     /*CHECKBUF(scratchbuf,nscratchbuf,p);*/
     if (p>17)
        speex_fatal("KissFFT: max radix supported is 17");
-    
+
     for ( u=0; unfft);
diff --git a/vendor/libspeex/libspeexdsp/kiss_fft.h b/vendor/libspeex/libspeexdsp/kiss_fft.h
index fa3f2c6042..bb19eadbd9 100644
--- a/vendor/libspeex/libspeexdsp/kiss_fft.h
+++ b/vendor/libspeex/libspeexdsp/kiss_fft.h
@@ -26,13 +26,13 @@ extern "C" {
 # include 
 # define kiss_fft_scalar __m128
 #define KISS_FFT_MALLOC(nbytes) memalign(16,nbytes)
-#else	
+#else
 #define KISS_FFT_MALLOC speex_alloc
-#endif	
+#endif
 
 
 #ifdef FIXED_POINT
-#include "arch.h"	
+#include "arch.h"
 #  define kiss_fft_scalar spx_int16_t
 #else
 # ifndef kiss_fft_scalar
@@ -48,9 +48,9 @@ typedef struct {
 
 typedef struct kiss_fft_state* kiss_fft_cfg;
 
-/* 
+/*
  *  kiss_fft_alloc
- *  
+ *
  *  Initialize a FFT (or IFFT) algorithm's cfg/state buffer.
  *
  *  typical usage:      kiss_fft_cfg mycfg=kiss_fft_alloc(1024,0,NULL,NULL);
@@ -60,18 +60,18 @@ typedef struct kiss_fft_state* kiss_fft_cfg;
  *
  *  If lenmem is NULL, then kiss_fft_alloc will allocate a cfg buffer using malloc.
  *  The returned value should be free()d when done to avoid memory leaks.
- *  
+ *
  *  The state can be placed in a user supplied buffer 'mem':
  *  If lenmem is not NULL and mem is not NULL and *lenmem is large enough,
  *      then the function places the cfg in mem and the size used in *lenmem
  *      and returns mem.
- *  
+ *
  *  If lenmem is not NULL and ( mem is NULL or *lenmem is not large enough),
- *      then the function returns NULL and places the minimum cfg 
+ *      then the function returns NULL and places the minimum cfg
  *      buffer size in *lenmem.
  * */
 
-kiss_fft_cfg kiss_fft_alloc(int nfft,int inverse_fft,void * mem,size_t * lenmem); 
+kiss_fft_cfg kiss_fft_alloc(int nfft,int inverse_fft,void * mem,size_t * lenmem);
 
 /*
  * kiss_fft(cfg,in_out_buf)
@@ -90,19 +90,19 @@ void kiss_fft(kiss_fft_cfg cfg,const kiss_fft_cpx *fin,kiss_fft_cpx *fout);
  * */
 void kiss_fft_stride(kiss_fft_cfg cfg,const kiss_fft_cpx *fin,kiss_fft_cpx *fout,int fin_stride);
 
-/* If kiss_fft_alloc allocated a buffer, it is one contiguous 
+/* If kiss_fft_alloc allocated a buffer, it is one contiguous
    buffer and can be simply free()d when no longer needed*/
 #define kiss_fft_free speex_free
 
 /*
- Cleans up some memory that gets managed internally. Not necessary to call, but it might clean up 
+ Cleans up some memory that gets managed internally. Not necessary to call, but it might clean up
  your compiler output to call this before you exit.
 */
 void kiss_fft_cleanup(void);
-	
+
 
 #ifdef __cplusplus
-} 
+}
 #endif
 
 #endif
diff --git a/vendor/libspeex/libspeexdsp/kiss_fftr.c b/vendor/libspeex/libspeexdsp/kiss_fftr.c
index f6275b8794..827e0b14df 100644
--- a/vendor/libspeex/libspeexdsp/kiss_fftr.c
+++ b/vendor/libspeex/libspeexdsp/kiss_fftr.c
@@ -24,9 +24,9 @@ struct kiss_fftr_state{
     kiss_fft_cfg substate;
     kiss_fft_cpx * tmpbuf;
     kiss_fft_cpx * super_twiddles;
-#ifdef USE_SIMD    
+#ifdef USE_SIMD
     long pad;
-#endif    
+#endif
 };
 
 kiss_fftr_cfg kiss_fftr_alloc(int nfft,int inverse_fft,void * mem,size_t * lenmem)
@@ -96,12 +96,12 @@ void kiss_fftr(kiss_fftr_cfg st,const kiss_fft_scalar *timedata,kiss_fft_cpx *fr
      * contains the sum of the even-numbered elements of the input time sequence
      * The imag part is the sum of the odd-numbered elements
      *
-     * The sum of tdc.r and tdc.i is the sum of the input time sequence. 
+     * The sum of tdc.r and tdc.i is the sum of the input time sequence.
      *      yielding DC of input time sequence
-     * The difference of tdc.r - tdc.i is the sum of the input (dot product) [1,-1,1,-1... 
+     * The difference of tdc.r - tdc.i is the sum of the input (dot product) [1,-1,1,-1...
      *      yielding Nyquist bin of input time sequence
      */
- 
+
     tdc.r = st->tmpbuf[0].r;
     tdc.i = st->tmpbuf[0].i;
     C_FIXDIV(tdc,2);
@@ -109,14 +109,14 @@ void kiss_fftr(kiss_fftr_cfg st,const kiss_fft_scalar *timedata,kiss_fft_cpx *fr
     CHECK_OVERFLOW_OP(tdc.r ,-, tdc.i);
     freqdata[0].r = tdc.r + tdc.i;
     freqdata[ncfft].r = tdc.r - tdc.i;
-#ifdef USE_SIMD    
+#ifdef USE_SIMD
     freqdata[ncfft].i = freqdata[0].i = _mm_set1_ps(0);
 #else
     freqdata[ncfft].i = freqdata[0].i = 0;
 #endif
 
     for ( k=1;k <= ncfft/2 ; ++k ) {
-        fpk    = st->tmpbuf[k]; 
+        fpk    = st->tmpbuf[k];
         fpnk.r =   st->tmpbuf[ncfft-k].r;
         fpnk.i = - st->tmpbuf[ncfft-k].i;
         C_FIXDIV(fpk,2);
@@ -161,7 +161,7 @@ void kiss_fftri(kiss_fftr_cfg st,const kiss_fft_cpx *freqdata, kiss_fft_scalar *
         C_MUL (fok, tmp, st->super_twiddles[k]);
         C_ADD (st->tmpbuf[k],     fek, fok);
         C_SUB (st->tmpbuf[ncfft - k], fek, fok);
-#ifdef USE_SIMD        
+#ifdef USE_SIMD
         st->tmpbuf[ncfft - k].i *= _mm_set1_ps(-1.0);
 #else
         st->tmpbuf[ncfft - k].i *= -1;
@@ -189,12 +189,12 @@ void kiss_fftr2(kiss_fftr_cfg st,const kiss_fft_scalar *timedata,kiss_fft_scalar
    * contains the sum of the even-numbered elements of the input time sequence
    * The imag part is the sum of the odd-numbered elements
    *
-   * The sum of tdc.r and tdc.i is the sum of the input time sequence. 
+   * The sum of tdc.r and tdc.i is the sum of the input time sequence.
    *      yielding DC of input time sequence
-   * The difference of tdc.r - tdc.i is the sum of the input (dot product) [1,-1,1,-1... 
+   * The difference of tdc.r - tdc.i is the sum of the input (dot product) [1,-1,1,-1...
    *      yielding Nyquist bin of input time sequence
     */
- 
+
    tdc.r = st->tmpbuf[0].r;
    tdc.i = st->tmpbuf[0].i;
    C_FIXDIV(tdc,2);
@@ -205,7 +205,7 @@ void kiss_fftr2(kiss_fftr_cfg st,const kiss_fft_scalar *timedata,kiss_fft_scalar
 
    for ( k=1;k <= ncfft/2 ; ++k )
    {
-      /*fpk    = st->tmpbuf[k]; 
+      /*fpk    = st->tmpbuf[k];
       fpnk.r =   st->tmpbuf[ncfft-k].r;
       fpnk.i = - st->tmpbuf[ncfft-k].i;
       C_FIXDIV(fpk,2);
@@ -213,7 +213,7 @@ void kiss_fftr2(kiss_fftr_cfg st,const kiss_fft_scalar *timedata,kiss_fft_scalar
 
       C_ADD( f1k, fpk , fpnk );
       C_SUB( f2k, fpk , fpnk );
-      
+
       C_MUL( tw , f2k , st->super_twiddles[k]);
 
       freqdata[2*k-1] = HALF_OF(f1k.r + tw.r);
@@ -226,7 +226,7 @@ void kiss_fftr2(kiss_fftr_cfg st,const kiss_fft_scalar *timedata,kiss_fft_scalar
       f1k.i = PSHR32(SUB32(EXTEND32(st->tmpbuf[k].i), EXTEND32(st->tmpbuf[ncfft-k].i)),1);
       f2k.r = PSHR32(SUB32(EXTEND32(st->tmpbuf[k].r), EXTEND32(st->tmpbuf[ncfft-k].r)),1);
       f2k.i = SHR32(ADD32(EXTEND32(st->tmpbuf[k].i), EXTEND32(st->tmpbuf[ncfft-k].i)),1);
-      
+
       C_MUL( tw , f2k , st->super_twiddles[k]);
 
       freqdata[2*k-1] = HALF_OF(f1k.r + tw.r);
@@ -236,13 +236,13 @@ void kiss_fftr2(kiss_fftr_cfg st,const kiss_fft_scalar *timedata,kiss_fft_scalar
    */
       f2k.r = SHR32(SUB32(EXTEND32(st->tmpbuf[k].r), EXTEND32(st->tmpbuf[ncfft-k].r)),1);
       f2k.i = PSHR32(ADD32(EXTEND32(st->tmpbuf[k].i), EXTEND32(st->tmpbuf[ncfft-k].i)),1);
-      
+
       f1kr = SHL32(ADD32(EXTEND32(st->tmpbuf[k].r), EXTEND32(st->tmpbuf[ncfft-k].r)),13);
       f1ki = SHL32(SUB32(EXTEND32(st->tmpbuf[k].i), EXTEND32(st->tmpbuf[ncfft-k].i)),13);
-      
+
       twr = SHR32(SUB32(MULT16_16(f2k.r,st->super_twiddles[k].r),MULT16_16(f2k.i,st->super_twiddles[k].i)), 1);
       twi = SHR32(ADD32(MULT16_16(f2k.i,st->super_twiddles[k].r),MULT16_16(f2k.r,st->super_twiddles[k].i)), 1);
-      
+
 #ifdef FIXED_POINT
       freqdata[2*k-1] = PSHR32(f1kr + twr, 15);
       freqdata[2*k] = PSHR32(f1ki + twi, 15);
@@ -253,7 +253,7 @@ void kiss_fftr2(kiss_fftr_cfg st,const kiss_fft_scalar *timedata,kiss_fft_scalar
       freqdata[2*k] = .5f*(f1ki + twi);
       freqdata[2*(ncfft-k)-1] = .5f*(f1kr - twr);
       freqdata[2*(ncfft-k)] = .5f*(twi - f1ki);
-      
+
 #endif
    }
 }
@@ -287,7 +287,7 @@ void kiss_fftri2(kiss_fftr_cfg st,const kiss_fft_scalar *freqdata,kiss_fft_scala
       C_MUL (fok, tmp, st->super_twiddles[k]);
       C_ADD (st->tmpbuf[k],     fek, fok);
       C_SUB (st->tmpbuf[ncfft - k], fek, fok);
-#ifdef USE_SIMD        
+#ifdef USE_SIMD
       st->tmpbuf[ncfft - k].i *= _mm_set1_ps(-1.0);
 #else
       st->tmpbuf[ncfft - k].i *= -1;
diff --git a/vendor/libspeex/libspeexdsp/kiss_fftr.h b/vendor/libspeex/libspeexdsp/kiss_fftr.h
index 7bfb423340..8cfeda138a 100644
--- a/vendor/libspeex/libspeexdsp/kiss_fftr.h
+++ b/vendor/libspeex/libspeexdsp/kiss_fftr.h
@@ -6,13 +6,13 @@
 extern "C" {
 #endif
 
-    
-/* 
- 
+
+/*
+
  Real optimized version can save about 45% cpu time vs. complex fft of a real seq.
 
- 
- 
+
+
  */
 
 typedef struct kiss_fftr_state *kiss_fftr_cfg;
@@ -22,7 +22,7 @@ kiss_fftr_cfg kiss_fftr_alloc(int nfft,int inverse_fft,void * mem, size_t * lenm
 /*
  nfft must be even
 
- If you don't care to allocate space, use mem = lenmem = NULL 
+ If you don't care to allocate space, use mem = lenmem = NULL
 */
 
 
diff --git a/vendor/libspeex/libspeexdsp/math_approx.h b/vendor/libspeex/libspeexdsp/math_approx.h
index 9ca830755d..596dfdc1b7 100644
--- a/vendor/libspeex/libspeexdsp/math_approx.h
+++ b/vendor/libspeex/libspeexdsp/math_approx.h
@@ -7,18 +7,18 @@
    Redistribution and use in source and binary forms, with or without
    modification, are permitted provided that the following conditions
    are met:
-   
+
    - Redistributions of source code must retain the above copyright
    notice, this list of conditions and the following disclaimer.
-   
+
    - Redistributions in binary form must reproduce the above copyright
    notice, this list of conditions and the following disclaimer in the
    documentation and/or other materials provided with the distribution.
-   
+
    - Neither the name of the Xiph.org Foundation nor the names of its
    contributors may be used to endorse or promote products derived from
    this software without specific prior written permission.
-   
+
    THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
    ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
    LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
@@ -168,11 +168,11 @@ static inline spx_word16_t spx_acos(spx_word16_t x)
       x = NEG16(x);
    }
    x = SUB16(16384,x);
-   
+
    x = x >> 1;
    sq = MULT16_16_Q13(x, ADD16(A1, MULT16_16_Q13(x, ADD16(A2, MULT16_16_Q13(x, (A3))))));
    ret = spx_sqrt(SHL32(EXTEND32(sq),13));
-   
+
    /*ret = spx_sqrt(67108864*(-1.6129e-04 + 2.0104e+00*f + 2.7373e-01*f*f + 1.8136e-01*f*f*f));*/
    if (s)
       ret = SUB16(25736,ret);
@@ -208,7 +208,7 @@ static inline spx_word16_t spx_cos(spx_word16_t x)
 static inline spx_word16_t _spx_cos_pi_2(spx_word16_t x)
 {
    spx_word16_t x2;
-   
+
    x2 = MULT16_16_P15(x,x);
    return ADD16(1,MIN16(32766,ADD32(SUB16(L1,x2), MULT16_16_P15(x2, ADD32(L2, MULT16_16_P15(x2, ADD32(L3, MULT16_16_P15(L4, x2))))))));
 }
diff --git a/vendor/libspeex/libspeexdsp/mdf.c b/vendor/libspeex/libspeexdsp/mdf.c
index 456ab847e4..7b367f9a88 100644
--- a/vendor/libspeex/libspeexdsp/mdf.c
+++ b/vendor/libspeex/libspeexdsp/mdf.c
@@ -33,36 +33,36 @@
 /*
    The echo canceller is based on the MDF algorithm described in:
 
-   J. S. Soo, K. K. Pang Multidelay block frequency adaptive filter, 
-   IEEE Trans. Acoust. Speech Signal Process., Vol. ASSP-38, No. 2, 
+   J. S. Soo, K. K. Pang Multidelay block frequency adaptive filter,
+   IEEE Trans. Acoust. Speech Signal Process., Vol. ASSP-38, No. 2,
    February 1990.
-   
-   We use the Alternatively Updated MDF (AUMDF) variant. Robustness to 
+
+   We use the Alternatively Updated MDF (AUMDF) variant. Robustness to
    double-talk is achieved using a variable learning rate as described in:
-   
-   Valin, J.-M., On Adjusting the Learning Rate in Frequency Domain Echo 
+
+   Valin, J.-M., On Adjusting the Learning Rate in Frequency Domain Echo
    Cancellation With Double-Talk. IEEE Transactions on Audio,
    Speech and Language Processing, Vol. 15, No. 3, pp. 1030-1034, 2007.
    http://people.xiph.org/~jm/papers/valin_taslp2006.pdf
-   
+
    There is no explicit double-talk detection, but a continuous variation
    in the learning rate based on residual echo, double-talk and background
    noise.
-   
+
    About the fixed-point version:
-   All the signals are represented with 16-bit words. The filter weights 
+   All the signals are represented with 16-bit words. The filter weights
    are represented with 32-bit words, but only the top 16 bits are used
    in most cases. The lower 16 bits are completely unreliable (due to the
    fact that the update is done only on the top bits), but help in the
    adaptation -- probably by removing a "threshold effect" due to
    quantization (rounding going to zero) when the gradient is small.
-   
+
    Another kludge that seems to work good: when performing the weight
    update, we only move half the way toward the "goal" this seems to
    reduce the effect of quantization noise in the update phase. This
    can be seen as applying a gradient descent on a "soft constraint"
    instead of having a hard constraint.
-   
+
 */
 
 #ifdef HAVE_CONFIG_H
@@ -88,12 +88,6 @@
 #define WEIGHT_SHIFT 0
 #endif
 
-#ifdef FIXED_POINT
-#define WORD2INT(x) ((x) < -32767 ? -32768 : ((x) > 32766 ? 32767 : (x)))  
-#else
-#define WORD2INT(x) ((x) < -32767.5f ? -32768 : ((x) > 32766.5f ? 32767 : floor(.5+(x))))  
-#endif
-
 /* If enabled, the AEC will use a foreground filter and a background filter to be more robust to double-talk
    and difficult signals in general. The cost is an extra FFT and a matrix-vector multiply */
 #define TWO_PATH
@@ -145,7 +139,7 @@ struct SpeexEchoState_ {
    spx_word16_t beta_max;
    spx_word32_t sum_adapt;
    spx_word16_t leak_estimate;
-   
+
    spx_word16_t *e;      /* scratch */
    spx_word16_t *x;      /* Far-end input buffer (2N) */
    spx_word16_t *X;      /* Far-end buffer (M+1 frames) in frequency domain */
@@ -198,7 +192,7 @@ static inline void filter_dc_notch16(const spx_int16_t *in, spx_word16_t radius,
    den2 = MULT16_16_Q15(radius,radius) + MULT16_16_Q15(QCONST16(.7,15),MULT16_16_Q15(32767-radius,32767-radius));
 #else
    den2 = radius*radius + .7*(1-radius)*(1-radius);
-#endif   
+#endif
    /*printf ("%d %d %d %d %d %d\n", num[0], num[1], num[2], den[0], den[1], den[2]);*/
    for (i=0;iframe_size = frame_size;
    st->window_size = 2*frame_size;
    N = st->window_size;
@@ -442,7 +436,7 @@ EXPORT SpeexEchoState *speex_echo_state_init_mc(int frame_size, int filter_lengt
    st->leak_estimate = 0;
 
    st->fft_table = spx_fft_init(N);
-   
+
    st->e = (spx_word16_t*)speex_alloc(C*N*sizeof(spx_word16_t));
    st->x = (spx_word16_t*)speex_alloc(K*N*sizeof(spx_word16_t));
    st->input = (spx_word16_t*)speex_alloc(C*st->frame_size*sizeof(spx_word16_t));
@@ -498,7 +492,7 @@ EXPORT SpeexEchoState *speex_echo_state_init_mc(int frame_size, int filter_lengt
          st->prop[i] = DIV32(MULT16_16(QCONST16(.8f,15), st->prop[i]),sum);
       }
    }
-   
+
    st->memX = (spx_word16_t*)speex_alloc(K*sizeof(spx_word16_t));
    st->memD = (spx_word16_t*)speex_alloc(C*sizeof(spx_word16_t));
    st->memE = (spx_word16_t*)speex_alloc(C*sizeof(spx_word16_t));
@@ -513,16 +507,16 @@ EXPORT SpeexEchoState *speex_echo_state_init_mc(int frame_size, int filter_lengt
    st->notch_mem = (spx_mem_t*)speex_alloc(2*C*sizeof(spx_mem_t));
    st->adapted = 0;
    st->Pey = st->Pyy = FLOAT_ONE;
-   
+
 #ifdef TWO_PATH
    st->Davg1 = st->Davg2 = 0;
    st->Dvar1 = st->Dvar2 = FLOAT_ZERO;
 #endif
-   
+
    st->play_buf = (spx_int16_t*)speex_alloc(K*(PLAYBACK_DELAY+1)*st->frame_size*sizeof(spx_int16_t));
    st->play_buf_pos = PLAYBACK_DELAY*st->frame_size;
    st->play_buf_started = 0;
-   
+
    return st;
 }
 
@@ -624,7 +618,7 @@ EXPORT void speex_echo_state_destroy(SpeexEchoState *st)
 
    speex_free(st->play_buf);
    speex_free(st);
-   
+
 #ifdef DUMP_ECHO_CANCEL_DATA
    fclose(rFile);
    fclose(pFile);
@@ -704,7 +698,7 @@ EXPORT void speex_echo_cancellation(SpeexEchoState *st, const spx_int16_t *in, c
    spx_float_t alpha, alpha_1;
    spx_word16_t RER;
    spx_word32_t tmp32;
-   
+
    N = st->window_size;
    M = st->M;
    C = st->C;
@@ -736,7 +730,7 @@ EXPORT void speex_echo_cancellation(SpeexEchoState *st, const spx_int16_t *in, c
             tmp32 = 32767;
             if (st->saturated == 0)
                st->saturated = 1;
-         }      
+         }
          if (tmp32 < -32767)
          {
             tmp32 = -32767;
@@ -762,18 +756,18 @@ EXPORT void speex_echo_cancellation(SpeexEchoState *st, const spx_int16_t *in, c
          {
             tmp32 = 32767;
             st->saturated = M+1;
-         }      
+         }
          if (tmp32 < -32767)
          {
             tmp32 = -32767;
             st->saturated = M+1;
-         }      
+         }
 #endif
          st->x[speak*N+i+st->frame_size] = EXTRACT16(tmp32);
          st->memX[speak] = far_end[i*K+speak];
       }
-   }   
-   
+   }
+
    for (speak = 0; speak < K; speak++)
    {
       /* Shift memory: this could be optimized eventually*/
@@ -785,15 +779,15 @@ EXPORT void speex_echo_cancellation(SpeexEchoState *st, const spx_int16_t *in, c
       /* Convert x (echo input) to frequency domain */
       spx_fft(st->fft_table, st->x+speak*N, &st->X[speak*N]);
    }
-   
+
    Sxx = 0;
    for (speak = 0; speak < K; speak++)
    {
       Sxx += mdf_inner_prod(st->x+speak*N+st->frame_size, st->x+speak*N+st->frame_size, st->frame_size);
       power_spectrum_accum(st->X+speak*N, st->Xf, N);
    }
-   
-   Sff = 0;  
+
+   Sff = 0;
    for (chan = 0; chan < C; chan++)
    {
 #ifdef TWO_PATH
@@ -805,7 +799,7 @@ EXPORT void speex_echo_cancellation(SpeexEchoState *st, const spx_int16_t *in, c
       Sff += mdf_inner_prod(st->e+chan*N, st->e+chan*N, st->frame_size);
 #endif
    }
-   
+
    /* Adjust proportional adaption rate */
    /* FIXME: Adjust that for C, K*/
    if (st->adapted)
@@ -828,8 +822,8 @@ EXPORT void speex_echo_cancellation(SpeexEchoState *st, const spx_int16_t *in, c
    } else {
       st->saturated--;
    }
-   
-   /* FIXME: MC conversion required */ 
+
+   /* FIXME: MC conversion required */
    /* Update weight to prevent circular convolution (MDF / AUMDF) */
    for (chan = 0; chan < C; chan++)
    {
@@ -869,13 +863,13 @@ EXPORT void speex_echo_cancellation(SpeexEchoState *st, const spx_int16_t *in, c
          }
       }
    }
-   
-   /* So we can use power_spectrum_accum */ 
+
+   /* So we can use power_spectrum_accum */
    for (i=0;i<=st->frame_size;i++)
       st->Rf[i] = st->Yf[i] = st->Xf[i] = 0;
-      
+
    Dbf = 0;
-   See = 0;    
+   See = 0;
 #ifdef TWO_PATH
    /* Difference in response, this is used to estimate the variance of our residual power estimate */
    for (chan = 0; chan < C; chan++)
@@ -897,20 +891,20 @@ EXPORT void speex_echo_cancellation(SpeexEchoState *st, const spx_int16_t *in, c
 
 #ifdef TWO_PATH
    /* Logic for updating the foreground filter */
-   
+
    /* For two time windows, compute the mean of the energy difference, as well as the variance */
    st->Davg1 = ADD32(MULT16_32_Q15(QCONST16(.6f,15),st->Davg1), MULT16_32_Q15(QCONST16(.4f,15),SUB32(Sff,See)));
    st->Davg2 = ADD32(MULT16_32_Q15(QCONST16(.85f,15),st->Davg2), MULT16_32_Q15(QCONST16(.15f,15),SUB32(Sff,See)));
    st->Dvar1 = FLOAT_ADD(FLOAT_MULT(VAR1_SMOOTH, st->Dvar1), FLOAT_MUL32U(MULT16_32_Q15(QCONST16(.4f,15),Sff), MULT16_32_Q15(QCONST16(.4f,15),Dbf)));
    st->Dvar2 = FLOAT_ADD(FLOAT_MULT(VAR2_SMOOTH, st->Dvar2), FLOAT_MUL32U(MULT16_32_Q15(QCONST16(.15f,15),Sff), MULT16_32_Q15(QCONST16(.15f,15),Dbf)));
-   
+
    /* Equivalent float code:
    st->Davg1 = .6*st->Davg1 + .4*(Sff-See);
    st->Davg2 = .85*st->Davg2 + .15*(Sff-See);
    st->Dvar1 = .36*st->Dvar1 + .16*Sff*Dbf;
    st->Dvar2 = .7225*st->Dvar2 + .0225*Sff*Dbf;
    */
-   
+
    update_foreground = 0;
    /* Check if we have a statistically significant reduction in the residual echo */
    /* Note that this is *not* Gaussian, so we need to be careful about the longer tail */
@@ -920,7 +914,7 @@ EXPORT void speex_echo_cancellation(SpeexEchoState *st, const spx_int16_t *in, c
       update_foreground = 1;
    else if (FLOAT_GT(FLOAT_MUL32U(st->Davg2, ABS32(st->Davg2)), FLOAT_MULT(VAR2_UPDATE,(st->Dvar2))))
       update_foreground = 1;
-   
+
    /* Do we update? */
    if (update_foreground)
    {
@@ -949,12 +943,12 @@ EXPORT void speex_echo_cancellation(SpeexEchoState *st, const spx_int16_t *in, c
             st->W[i] = SHL32(EXTEND32(st->foreground[i]),16);
          /* We also need to copy the output so as to get correct adaptation */
          for (chan = 0; chan < C; chan++)
-         {        
+         {
             for (i=0;iframe_size;i++)
                st->y[chan*N+i+st->frame_size] = st->e[chan*N+i+st->frame_size];
             for (i=0;iframe_size;i++)
                st->e[chan*N+i] = SUB16(st->input[chan*st->frame_size+i], st->y[chan*N+i+st->frame_size]);
-         }        
+         }
          See = Sff;
          st->Davg1 = st->Davg2 = 0;
          st->Dvar1 = st->Dvar2 = FLOAT_ZERO;
@@ -962,10 +956,10 @@ EXPORT void speex_echo_cancellation(SpeexEchoState *st, const spx_int16_t *in, c
    }
 #endif
 
-   Sey = Syy = Sdd = 0;  
+   Sey = Syy = Sdd = 0;
    for (chan = 0; chan < C; chan++)
-   {    
-      /* Compute error signal (for the output with de-emphasis) */ 
+   {
+      /* Compute error signal (for the output with de-emphasis) */
       for (i=0;iframe_size;i++)
       {
          spx_word32_t tmp_out;
@@ -988,34 +982,34 @@ EXPORT void speex_echo_cancellation(SpeexEchoState *st, const spx_int16_t *in, c
 #ifdef DUMP_ECHO_CANCEL_DATA
       dump_audio(in, far_end, out, st->frame_size);
 #endif
-   
-      /* Compute error signal (filter update version) */ 
+
+      /* Compute error signal (filter update version) */
       for (i=0;iframe_size;i++)
       {
          st->e[chan*N+i+st->frame_size] = st->e[chan*N+i];
          st->e[chan*N+i] = 0;
       }
-      
+
       /* Compute a bunch of correlations */
       /* FIXME: bad merge */
       Sey += mdf_inner_prod(st->e+chan*N+st->frame_size, st->y+chan*N+st->frame_size, st->frame_size);
       Syy += mdf_inner_prod(st->y+chan*N+st->frame_size, st->y+chan*N+st->frame_size, st->frame_size);
       Sdd += mdf_inner_prod(st->input+chan*st->frame_size, st->input+chan*st->frame_size, st->frame_size);
-      
+
       /* Convert error to frequency domain */
       spx_fft(st->fft_table, st->e+chan*N, st->E+chan*N);
       for (i=0;iframe_size;i++)
          st->y[i+chan*N] = 0;
       spx_fft(st->fft_table, st->y+chan*N, st->Y+chan*N);
-   
+
       /* Compute power spectrum of echo (X), error (E) and filter response (Y) */
       power_spectrum_accum(st->E+chan*N, st->Rf, N);
       power_spectrum_accum(st->Y+chan*N, st->Yf, N);
-    
+
    }
-   
+
    /*printf ("%f %f %f %f\n", Sff, See, Syy, Sdd, st->update_cond);*/
-   
+
    /* Do some sanity check */
    if (!(Syy>=0 && Sxx>=0 && See >= 0)
 #ifndef FIXED_POINT
@@ -1044,14 +1038,14 @@ EXPORT void speex_echo_cancellation(SpeexEchoState *st, const spx_int16_t *in, c
 
    /* Add a small noise floor to make sure not to have problems when dividing */
    See = MAX32(See, SHR32(MULT16_16(N, 100),6));
-     
+
    for (speak = 0; speak < K; speak++)
    {
       Sxx += mdf_inner_prod(st->x+speak*N+st->frame_size, st->x+speak*N+st->frame_size, st->frame_size);
       power_spectrum_accum(st->X+speak*N, st->Xf, N);
    }
 
-   
+
    /* Smooth far end energy estimate over time */
    for (j=0;j<=st->frame_size;j++)
       st->power[j] = MULT16_32_Q15(ss_1,st->power[j]) + 1 + MULT16_32_Q15(ss,st->Xf[j]);
@@ -1072,7 +1066,7 @@ EXPORT void speex_echo_cancellation(SpeexEchoState *st, const spx_int16_t *in, c
       st->Yh[j] = (1-st->spec_average)*st->Yh[j] + st->spec_average*st->Yf[j];
 #endif
    }
-   
+
    Pyy = FLOAT_SQRT(Pyy);
    Pey = FLOAT_DIVU(Pey,Pyy);
 
@@ -1100,7 +1094,7 @@ EXPORT void speex_echo_cancellation(SpeexEchoState *st, const spx_int16_t *in, c
    else
       st->leak_estimate = SHL16(st->leak_estimate,1);
    /*printf ("%f\n", st->leak_estimate);*/
-   
+
    /* Compute Residual to Error Ratio */
 #ifdef FIXED_POINT
    tmp32 = MULT16_32_Q15(st->leak_estimate,Syy);
@@ -1156,7 +1150,7 @@ EXPORT void speex_echo_cancellation(SpeexEchoState *st, const spx_int16_t *in, c
       /* Temporary adaption rate if filter is not yet adapted enough */
       spx_word16_t adapt_rate=0;
 
-      if (Sxx > SHR32(MULT16_16(N, 1000),6)) 
+      if (Sxx > SHR32(MULT16_16(N, 1000),6))
       {
          tmp32 = MULT16_32_Q15(QCONST16(.25f, 15), Sxx);
 #ifdef FIXED_POINT
@@ -1176,7 +1170,7 @@ EXPORT void speex_echo_cancellation(SpeexEchoState *st, const spx_int16_t *in, c
       st->sum_adapt = ADD32(st->sum_adapt,adapt_rate);
    }
 
-   /* FIXME: MC conversion required */ 
+   /* FIXME: MC conversion required */
       for (i=0;iframe_size;i++)
          st->last_y[i] = st->last_y[st->frame_size+i];
    if (st->adapted)
@@ -1198,17 +1192,17 @@ void speex_echo_get_residual(SpeexEchoState *st, spx_word32_t *residual_echo, in
    int i;
    spx_word16_t leak2;
    int N;
-   
+
    N = st->window_size;
 
    /* Apply hanning window (should pre-compute it)*/
    for (i=0;iy[i] = MULT16_16_Q15(st->window[i],st->last_y[i]);
-      
+
    /* Compute power spectrum of the echo */
    spx_fft(st->fft_table, st->y, st->Y);
    power_spectrum(st->Y, residual_echo, N);
-      
+
 #ifdef FIXED_POINT
    if (st->leak_estimate > 16383)
       leak2 = 32767;
@@ -1223,14 +1217,14 @@ void speex_echo_get_residual(SpeexEchoState *st, spx_word32_t *residual_echo, in
    /* Estimate residual echo */
    for (i=0;i<=st->frame_size;i++)
       residual_echo[i] = (spx_int32_t)MULT16_32_Q15(leak2,residual_echo[i]);
-   
+
 }
 
 EXPORT int speex_echo_ctl(SpeexEchoState *st, int request, void *ptr)
 {
    switch(request)
    {
-      
+
       case SPEEX_ECHO_GET_FRAME_SIZE:
          (*(int*)ptr) = st->frame_size;
          break;
diff --git a/vendor/libspeex/libspeexdsp/misc_bfin.h b/vendor/libspeex/libspeexdsp/misc_bfin.h
index 3c8c09d236..4e27681c95 100644
--- a/vendor/libspeex/libspeexdsp/misc_bfin.h
+++ b/vendor/libspeex/libspeexdsp/misc_bfin.h
@@ -1,25 +1,25 @@
 /* Copyright (C) 2005 Analog Devices */
 /**
    @file misc_bfin.h
-   @author Jean-Marc Valin 
+   @author Jean-Marc Valin
    @brief Various compatibility routines for Speex (Blackfin version)
 */
 /*
    Redistribution and use in source and binary forms, with or without
    modification, are permitted provided that the following conditions
    are met:
-   
+
    - Redistributions of source code must retain the above copyright
    notice, this list of conditions and the following disclaimer.
-   
+
    - Redistributions in binary form must reproduce the above copyright
    notice, this list of conditions and the following disclaimer in the
    documentation and/or other materials provided with the distribution.
-   
+
    - Neither the name of the Xiph.org Foundation nor the names of its
    contributors may be used to endorse or promote products derived from
    this software without specific prior written permission.
-   
+
    THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
    ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
    LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
diff --git a/vendor/libspeex/libspeexdsp/os_support.h b/vendor/libspeex/libspeexdsp/os_support.h
index 2e23a5eb41..0db31a61df 100644
--- a/vendor/libspeex/libspeexdsp/os_support.h
+++ b/vendor/libspeex/libspeexdsp/os_support.h
@@ -1,5 +1,5 @@
 /* Copyright (C) 2007 Jean-Marc Valin
-      
+
    File: os_support.h
    This is the (tiny) OS abstraction layer. Aside from math.h, this is the
    only place where system headers are allowed.
@@ -45,12 +45,12 @@
 #include "os_support_custom.h"
 #endif
 
-/** Speex wrapper for calloc. To do your own dynamic allocation, all you need to do is replace this function, speex_realloc and speex_free 
+/** Speex wrapper for calloc. To do your own dynamic allocation, all you need to do is replace this function, speex_realloc and speex_free
     NOTE: speex_alloc needs to CLEAR THE MEMORY */
 #ifndef OVERRIDE_SPEEX_ALLOC
 static inline void *speex_alloc (int size)
 {
-   /* WARNING: this is not equivalent to malloc(). If you want to use malloc() 
+   /* WARNING: this is not equivalent to malloc(). If you want to use malloc()
       or your own allocator, YOU NEED TO CLEAR THE MEMORY ALLOCATED. Otherwise
       you will experience strange bugs */
    return calloc(size,1);
diff --git a/vendor/libspeex/libspeexdsp/preprocess.c b/vendor/libspeex/libspeexdsp/preprocess.c
index b8e287a7e7..3053eb5adb 100644
--- a/vendor/libspeex/libspeexdsp/preprocess.c
+++ b/vendor/libspeex/libspeexdsp/preprocess.c
@@ -1,6 +1,6 @@
 /* Copyright (C) 2003 Epic Games (written by Jean-Marc Valin)
-   Copyright (C) 2004-2006 Epic Games 
-   
+   Copyright (C) 2004-2006 Epic Games
+
    File: preprocess.c
    Preprocessor with denoising based on the algorithm by Ephraim and Malah
 
@@ -34,24 +34,24 @@
 
 /*
    Recommended papers:
-   
+
    Y. Ephraim and D. Malah, "Speech enhancement using minimum mean-square error
-   short-time spectral amplitude estimator". IEEE Transactions on Acoustics, 
+   short-time spectral amplitude estimator". IEEE Transactions on Acoustics,
    Speech and Signal Processing, vol. ASSP-32, no. 6, pp. 1109-1121, 1984.
-   
+
    Y. Ephraim and D. Malah, "Speech enhancement using minimum mean-square error
-   log-spectral amplitude estimator". IEEE Transactions on Acoustics, Speech and 
+   log-spectral amplitude estimator". IEEE Transactions on Acoustics, Speech and
    Signal Processing, vol. ASSP-33, no. 2, pp. 443-445, 1985.
-   
+
    I. Cohen and B. Berdugo, "Speech enhancement for non-stationary noise environments".
    Signal Processing, vol. 81, no. 2, pp. 2403-2418, 2001.
 
-   Stefan Gustafsson, Rainer Martin, Peter Jax, and Peter Vary. "A psychoacoustic 
-   approach to combined acoustic echo cancellation and noise reduction". IEEE 
+   Stefan Gustafsson, Rainer Martin, Peter Jax, and Peter Vary. "A psychoacoustic
+   approach to combined acoustic echo cancellation and noise reduction". IEEE
    Transactions on Speech and Audio Processing, 2002.
-   
+
    J.-M. Valin, J. Rouat, and F. Michaud, "Microphone array post-filter for separation
-   of simultaneous non-stationary sources". In Proceedings IEEE International 
+   of simultaneous non-stationary sources". In Proceedings IEEE International
    Conference on Acoustics, Speech, and Signal Processing, 2004.
 */
 
@@ -71,7 +71,7 @@
 #define LOUDNESS_EXP 5.f
 #define AMP_SCALE .001f
 #define AMP_SCALE_1 1000.f
-      
+
 #define NB_BANDS 24
 
 #define SPEECH_PROB_START_DEFAULT       QCONST16(0.35f,15)
@@ -113,7 +113,7 @@ static inline spx_word16_t DIV32_16_Q8(spx_word32_t a, spx_word32_t b)
       a = SHL32(a,8);
       return PDIV32_16(a,b);
    }
-   
+
 }
 static inline spx_word16_t DIV32_16_Q15(spx_word32_t a, spx_word32_t b)
 {
@@ -181,7 +181,7 @@ struct SpeexPreprocessState_ {
    int    sampling_rate;     /**< Sampling rate of the input/output */
    int    nbands;
    FilterBank *bank;
-   
+
    /* Parameters */
    int    denoise_enabled;
    int    vad_enabled;
@@ -194,7 +194,7 @@ struct SpeexPreprocessState_ {
    int    echo_suppress;
    int    echo_suppress_active;
    SpeexEchoState *echo_state;
-   
+
    spx_word16_t	speech_prob;  /**< Probability last frame was speech */
 
    /* DSP-related arrays */
@@ -256,7 +256,7 @@ static void conj_window(spx_word16_t *w, int len)
       spx_word16_t tmp;
 #ifdef FIXED_POINT
       spx_word16_t x = DIV32_16(MULT16_16(32767,i),len);
-#else      
+#else
       spx_word16_t x = DIV32_16(MULT16_16(QCONST16(4.f,13),i),len);
 #endif
       int inv=0;
@@ -281,10 +281,10 @@ static void conj_window(spx_word16_t *w, int len)
    }
 }
 
-      
+
 #ifdef FIXED_POINT
-/* This function approximates the gain function 
-   y = gamma(1.25)^2 * M(-.25;1;-x) / sqrt(x)  
+/* This function approximates the gain function
+   y = gamma(1.25)^2 * M(-.25;1;-x) / sqrt(x)
    which multiplied by xi/(1+xi) is the optimal gain
    in the loudness domain ( sqrt[amplitude] )
    Input in Q11 format, output in Q15
@@ -317,7 +317,7 @@ static inline spx_word16_t qcurve(spx_word16_t x)
 static void compute_gain_floor(int noise_suppress, int effective_echo_suppress, spx_word32_t *noise, spx_word32_t *echo, spx_word16_t *gain_floor, int len)
 {
    int i;
-   
+
    if (noise_suppress > effective_echo_suppress)
    {
       spx_word16_t noise_gain, gain_ratio;
@@ -343,8 +343,8 @@ static void compute_gain_floor(int noise_suppress, int effective_echo_suppress,
 }
 
 #else
-/* This function approximates the gain function 
-   y = gamma(1.25)^2 * M(-.25;1;-x) / sqrt(x)  
+/* This function approximates the gain function
+   y = gamma(1.25)^2 * M(-.25;1;-x) / sqrt(x)
    which multiplied by xi/(1+xi) is the optimal gain
    in the loudness domain ( sqrt[amplitude] )
 */
@@ -410,8 +410,8 @@ EXPORT SpeexPreprocessState *speex_preprocess_state_init(int frame_size, int sam
          break;
       }
    }
-   
-   
+
+
    if (st->ps_size < 3*st->frame_size/4)
       st->ps_size = st->ps_size * 3 / 2;
 #else
@@ -421,7 +421,7 @@ EXPORT SpeexPreprocessState *speex_preprocess_state_init(int frame_size, int sam
    N = st->ps_size;
    N3 = 2*N - st->frame_size;
    N4 = st->frame_size - N3;
-   
+
    st->sampling_rate = sampling_rate;
    st->denoise_enabled = 1;
    st->vad_enabled = 0;
@@ -436,15 +436,15 @@ EXPORT SpeexPreprocessState *speex_preprocess_state_init(int frame_size, int sam
    st->speech_prob_continue = SPEECH_PROB_CONTINUE_DEFAULT;
 
    st->echo_state = NULL;
-   
+
    st->nbands = NB_BANDS;
    M = st->nbands;
    st->bank = filterbank_new(M, sampling_rate, N, 1);
-   
+
    st->frame = (spx_word16_t*)speex_alloc(2*N*sizeof(spx_word16_t));
    st->window = (spx_word16_t*)speex_alloc(2*N*sizeof(spx_word16_t));
    st->ft = (spx_word16_t*)speex_alloc(2*N*sizeof(spx_word16_t));
-   
+
    st->ps = (spx_word32_t*)speex_alloc((N+M)*sizeof(spx_word32_t));
    st->noise = (spx_word32_t*)speex_alloc((N+M)*sizeof(spx_word32_t));
    st->echo_noise = (spx_word32_t*)speex_alloc((N+M)*sizeof(spx_word32_t));
@@ -457,19 +457,19 @@ EXPORT SpeexPreprocessState *speex_preprocess_state_init(int frame_size, int sam
    st->gain2 = (spx_word16_t*)speex_alloc((N+M)*sizeof(spx_word16_t));
    st->gain_floor = (spx_word16_t*)speex_alloc((N+M)*sizeof(spx_word16_t));
    st->zeta = (spx_word16_t*)speex_alloc((N+M)*sizeof(spx_word16_t));
-   
+
    st->S = (spx_word32_t*)speex_alloc(N*sizeof(spx_word32_t));
    st->Smin = (spx_word32_t*)speex_alloc(N*sizeof(spx_word32_t));
    st->Stmp = (spx_word32_t*)speex_alloc(N*sizeof(spx_word32_t));
    st->update_prob = (int*)speex_alloc(N*sizeof(int));
-   
+
    st->inbuf = (spx_word16_t*)speex_alloc(N3*sizeof(spx_word16_t));
    st->outbuf = (spx_word16_t*)speex_alloc(N3*sizeof(spx_word16_t));
 
    conj_window(st->window, 2*N3);
    for (i=2*N3;i<2*st->ps_size;i++)
       st->window[i]=Q15_ONE;
-   
+
    if (N4>0)
    {
       for (i=N3-1;i>=0;i--)
@@ -569,7 +569,7 @@ static void speex_compute_agc(SpeexPreprocessState *st, spx_word16_t Pframe, spx
    float target_gain;
    float loudness=1.f;
    float rate;
-   
+
    for (i=2;ips[i]* st->loudness_weight[i];
@@ -587,7 +587,7 @@ static void speex_compute_agc(SpeexPreprocessState *st, spx_word16_t Pframe, spx
          st->init_max *= 1.f + .1f*Pframe*Pframe;
    }
    /*printf ("%f %f %f %f\n", Pframe, loudness, pow(st->loudness, 1.0f/LOUDNESS_EXP), st->loudness2);*/
-   
+
    target_gain = AMP_SCALE*st->agc_level*pow(st->loudness/(1e-4+st->loudness_accum), -1.0f/LOUDNESS_EXP);
 
    if ((Pframe>.5  && st->nb_adapt > 20) || target_gain < st->agc_gain)
@@ -600,11 +600,11 @@ static void speex_compute_agc(SpeexPreprocessState *st, spx_word16_t Pframe, spx
          target_gain = st->max_gain;
       if (target_gain > st->init_max)
          target_gain = st->init_max;
-   
+
       st->agc_gain = target_gain;
    }
    /*fprintf (stderr, "%f %f %f\n", loudness, (float)AMP_SCALE_1*pow(st->loudness, 1.0f/LOUDNESS_EXP), st->agc_gain);*/
-      
+
    for (i=0;i<2*N;i++)
       ft[i] *= st->agc_gain;
    st->prev_loudness = loudness;
@@ -624,7 +624,7 @@ static void preprocess_analysis(SpeexPreprocessState *st, spx_int16_t *x)
       st->frame[i]=st->inbuf[i];
    for (i=0;iframe_size;i++)
       st->frame[N3+i]=x[i];
-   
+
    /* Update inbuf */
    for (i=0;iinbuf[i]=x[N4+i];
@@ -643,10 +643,10 @@ static void preprocess_analysis(SpeexPreprocessState *st, spx_int16_t *x)
          st->frame[i] = SHL16(st->frame[i], st->frame_shift);
    }
 #endif
-   
+
    /* Perform FFT */
    spx_fft(st->fft_lookup, st->frame, st->ft);
-         
+
    /* Power spectrum */
    ps[0]=MULT16_16(st->ft[0],st->ft[0]);
    for (i=1;ips_size;
 
    for (i=1;iS[i] =  MULT16_32_Q15(QCONST16(.8f,15),st->S[i]) + MULT16_32_Q15(QCONST16(.05f,15),st->ps[i-1]) 
+      st->S[i] =  MULT16_32_Q15(QCONST16(.8f,15),st->S[i]) + MULT16_32_Q15(QCONST16(.05f,15),st->ps[i-1])
                       + MULT16_32_Q15(QCONST16(.1f,15),st->ps[i]) + MULT16_32_Q15(QCONST16(.05f,15),st->ps[i+1]);
    st->S[0] =  MULT16_32_Q15(QCONST16(.8f,15),st->S[0]) + MULT16_32_Q15(QCONST16(.2f,15),st->ps[0]);
    st->S[N-1] =  MULT16_32_Q15(QCONST16(.8f,15),st->S[N-1]) + MULT16_32_Q15(QCONST16(.2f,15),st->ps[N-1]);
-   
+
    if (st->nb_adapt==1)
    {
       for (i=0;iSmin[i] = MIN32(st->Smin[i], st->S[i]);
-         st->Stmp[i] = MIN32(st->Stmp[i], st->S[i]);      
+         st->Stmp[i] = MIN32(st->Stmp[i], st->S[i]);
       }
    }
    for (i=0;inb_adapt++;
    if (st->nb_adapt>20000)
       st->nb_adapt = 20000;
    st->min_count++;
-   
+
    beta = MAX16(QCONST16(.03,15),DIV32_16(Q15_ONE,st->nb_adapt));
    beta_1 = Q15_ONE-beta;
    M = st->nbands;
@@ -770,7 +770,7 @@ EXPORT int speex_preprocess_run(SpeexPreprocessState *st, spx_int16_t *x)
          st->update_prob[i] = 0;
    }
    */
-   
+
    /* Update the noise estimate for the frequencies where it can be */
    for (i=0;inoise[i],NOISE_SHIFT)) , st->echo_noise[i]) , st->reverb_estimate[i]);
-      
+
       /* A posteriori SNR = ps/noise - 1*/
       st->post[i] = SUB16(DIV32_16_Q8(ps[i],tot_noise), QCONST16(1.f,SNR_SHIFT));
       st->post[i]=MIN16(st->post[i], QCONST16(100.f,SNR_SHIFT));
-      
+
       /* Computing update gamma = .1 + .9*(old/(old+noise))^2 */
       gamma = QCONST16(.1f,15)+MULT16_16_Q15(QCONST16(.89f,15),SQR16_Q15(DIV32_16_Q15(st->old_ps[i],ADD32(st->old_ps[i],tot_noise))));
-      
+
       /* A priori SNR update = gamma*max(0,post) + (1-gamma)*old/noise */
       st->prior[i] = EXTRACT16(PSHR32(ADD32(MULT16_16(gamma,MAX16(0,st->post[i])), MULT16_16(Q15_ONE-gamma,DIV32_16_Q8(st->old_ps[i],tot_noise))), 15));
       st->prior[i]=MIN16(st->prior[i], QCONST16(100.f,SNR_SHIFT));
@@ -819,13 +819,13 @@ EXPORT int speex_preprocess_run(SpeexPreprocessState *st, spx_int16_t *x)
    for (i=N;izeta[i]));
    Pframe = QCONST16(.1f,15)+MULT16_16_Q15(QCONST16(.899f,15),qcurve(DIV32_16(Zframe,st->nbands)));
-   
+
    effective_echo_suppress = EXTRACT16(PSHR32(ADD32(MULT16_16(SUB16(Q15_ONE,Pframe), st->echo_suppress), MULT16_16(Pframe, st->echo_suppress_active)),15));
-   
+
    compute_gain_floor(st->noise_suppress, effective_echo_suppress, st->noise+N, st->echo_noise+N, st->gain_floor+N, M);
-         
-   /* Compute Ephraim & Malah gain speech probability of presence for each critical band (Bark scale) 
-      Technically this is actually wrong because the EM gaim assumes a slightly different probability 
+
+   /* Compute Ephraim & Malah gain speech probability of presence for each critical band (Bark scale)
+      Technically this is actually wrong because the EM gaim assumes a slightly different probability
       distribution */
    for (i=N;iprior[i]), 15), ADD16(st->prior[i], SHL32(1,SNR_SHIFT)));
       theta = MULT16_32_P15(prior_ratio, QCONST32(1.f,EXPIN_SHIFT)+SHL32(EXTEND32(st->post[i]),EXPIN_SHIFT-SNR_SHIFT));
 
@@ -867,12 +867,12 @@ EXPORT int speex_preprocess_run(SpeexPreprocessState *st, spx_int16_t *x)
    /* Convert the EM gains and speech prob to linear frequency */
    filterbank_compute_psd16(st->bank,st->gain2+N, st->gain2);
    filterbank_compute_psd16(st->bank,st->gain+N, st->gain);
-   
+
    /* Use 1 for linear gain resolution (best) or 0 for Bark gain resolution (faster) */
    if (1)
    {
       filterbank_compute_psd16(st->bank,st->gain_floor+N, st->gain_floor);
-   
+
       /* Compute gain according to the Ephraim-Malah algorithm -- linear frequency */
       for (i=0;iprior[i]), 15), ADD16(st->prior[i], SHL32(1,SNR_SHIFT)));
          theta = MULT16_32_P15(prior_ratio, QCONST32(1.f,EXPIN_SHIFT)+SHL32(EXTEND32(st->post[i]),EXPIN_SHIFT-SNR_SHIFT));
@@ -893,22 +893,22 @@ EXPORT int speex_preprocess_run(SpeexPreprocessState *st, spx_int16_t *x)
          g = EXTRACT16(MIN32(Q15_ONE, MULT16_32_Q15(prior_ratio, MM)));
          /* Interpolated speech probability of presence */
          p = st->gain2[i];
-                  
+
          /* Constrain the gain to be close to the Bark scale gain */
          if (MULT16_16_Q15(QCONST16(.333f,15),g) > st->gain[i])
             g = MULT16_16(3,st->gain[i]);
          st->gain[i] = g;
-         
+
          /* Save old power spectrum */
          st->old_ps[i] = MULT16_32_P15(QCONST16(.2f,15),st->old_ps[i]) + MULT16_32_P15(MULT16_16_P15(QCONST16(.8f,15),SQR16_Q15(st->gain[i])),ps[i]);
-         
+
          /* Apply gain floor */
          if (st->gain[i] < st->gain_floor[i])
             st->gain[i] = st->gain_floor[i];
 
          /* Exponential decay model for reverberation (unused) */
          /*st->reverb_estimate[i] = st->reverb_decay*st->reverb_estimate[i] + st->reverb_decay*st->reverb_level*st->gain[i]*st->gain[i]*st->ps[i];*/
-         
+
          /* Take into account speech probability of presence (loudness domain MMSE estimator) */
          /* gain2 = [p*sqrt(gain)+(1-p)*sqrt(gain _floor) ]^2 */
          tmp = MULT16_16_P15(p,spx_sqrt(SHL32(EXTEND32(st->gain[i]),15))) + MULT16_16_P15(SUB16(Q15_ONE,p),spx_sqrt(SHL32(EXTEND32(st->gain_floor[i]),15)));
@@ -922,20 +922,20 @@ EXPORT int speex_preprocess_run(SpeexPreprocessState *st, spx_int16_t *x)
       {
          spx_word16_t tmp;
          spx_word16_t p = st->gain2[i];
-         st->gain[i] = MAX16(st->gain[i], st->gain_floor[i]);         
+         st->gain[i] = MAX16(st->gain[i], st->gain_floor[i]);
          tmp = MULT16_16_P15(p,spx_sqrt(SHL32(EXTEND32(st->gain[i]),15))) + MULT16_16_P15(SUB16(Q15_ONE,p),spx_sqrt(SHL32(EXTEND32(st->gain_floor[i]),15)));
          st->gain2[i]=SQR16_Q15(tmp);
       }
       filterbank_compute_psd16(st->bank,st->gain2+N, st->gain2);
    }
-   
+
    /* If noise suppression is off, don't apply the gain (but then why call this in the first place!) */
    if (!st->denoise_enabled)
    {
       for (i=0;igain2[i]=Q15_ONE;
    }
-      
+
    /* Apply computed gain */
    for (i=1;ift[0] = MULT16_16_P15(st->gain2[0],st->ft[0]);
    st->ft[2*N-1] = MULT16_16_P15(st->gain2[N-1],st->ft[2*N-1]);
-   
+
    /*FIXME: This *will* not work for fixed-point */
 #ifndef FIXED_POINT
    if (st->agc_enabled)
@@ -973,17 +973,17 @@ EXPORT int speex_preprocess_run(SpeexPreprocessState *st, spx_int16_t *x)
       }
    }
 #endif
-   
+
    /* Synthesis window (for WOLA) */
    for (i=0;i<2*N;i++)
       st->frame[i] = MULT16_16_Q15(st->frame[i], st->window[i]);
 
    /* Perform overlap and add */
    for (i=0;ioutbuf[i] + st->frame[i];
+      x[i] = WORD2INT(ADD32(EXTEND32(st->outbuf[i]), EXTEND32(st->frame[i])));
    for (i=0;iframe[N3+i];
-   
+
    /* Update outbuf */
    for (i=0;ioutbuf[i] = st->frame[st->frame_size+i];
@@ -1016,11 +1016,11 @@ EXPORT void speex_preprocess_estimate_update(SpeexPreprocessState *st, spx_int16
 
    M = st->nbands;
    st->min_count++;
-   
+
    preprocess_analysis(st, x);
 
    update_noise_prob(st);
-   
+
    for (i=1;iupdate_prob[i] || st->ps[i] < PSHR32(st->noise[i],NOISE_SHIFT))
@@ -1099,7 +1099,7 @@ EXPORT int speex_preprocess_ctl(SpeexPreprocessState *state, int request, void *
    case SPEEX_PREPROCESS_GET_VAD:
       (*(spx_int32_t*)ptr) = st->vad_enabled;
       break;
-   
+
    case SPEEX_PREPROCESS_SET_DEREVERB:
       st->dereverb_enabled = (*(spx_int32_t*)ptr);
       for (i=0;ips_size;i++)
@@ -1117,7 +1117,7 @@ EXPORT int speex_preprocess_ctl(SpeexPreprocessState *state, int request, void *
       /* FIXME: Re-enable when de-reverberation is actually enabled again */
       /*(*(float*)ptr) = st->reverb_level;*/
       break;
-   
+
    case SPEEX_PREPROCESS_SET_DEREVERB_DECAY:
       /* FIXME: Re-enable when de-reverberation is actually enabled again */
       /*st->reverb_decay = (*(float*)ptr);*/
diff --git a/vendor/libspeex/libspeexdsp/pseudofloat.h b/vendor/libspeex/libspeexdsp/pseudofloat.h
index fa841a0101..ed5ab14b05 100644
--- a/vendor/libspeex/libspeexdsp/pseudofloat.h
+++ b/vendor/libspeex/libspeexdsp/pseudofloat.h
@@ -3,7 +3,7 @@
    @file pseudofloat.h
    @brief Pseudo-floating point
  * This header file provides a lightweight floating point type for
- * use on fixed-point platforms when a large dynamic range is 
+ * use on fixed-point platforms when a large dynamic range is
  * required. The new type is not compatible with the 32-bit IEEE format,
  * it is not even remotely as accurate as 32-bit floats, and is not
  * even guaranteed to produce even remotely correct results for code
@@ -16,18 +16,18 @@
    Redistribution and use in source and binary forms, with or without
    modification, are permitted provided that the following conditions
    are met:
-   
+
    - Redistributions of source code must retain the above copyright
    notice, this list of conditions and the following disclaimer.
-   
+
    - Redistributions in binary form must reproduce the above copyright
    notice, this list of conditions and the following disclaimer in the
    documentation and/or other materials provided with the distribution.
-   
+
    - Neither the name of the Xiph.org Foundation nor the names of its
    contributors may be used to endorse or promote products derived from
    this software without specific prior written permission.
-   
+
    THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
    ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
    LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
@@ -84,7 +84,7 @@ static inline spx_float_t PSEUDOFLOAT(spx_int32_t x)
       r.e = e;
       return r;
    }
-   else      
+   else
    {
       spx_float_t r;
       r.m = x;
@@ -101,12 +101,12 @@ static inline spx_float_t FLOAT_ADD(spx_float_t a, spx_float_t b)
       return b;
    else if (b.m==0)
       return a;
-   if ((a).e > (b).e) 
+   if ((a).e > (b).e)
    {
       r.m = ((a).m>>1) + ((b).m>>MIN(15,(a).e-(b).e+1));
       r.e = (a).e+1;
    }
-   else 
+   else
    {
       r.m = ((b).m>>1) + ((a).m>>MIN(15,(b).e-(a).e+1));
       r.e = (b).e+1;
@@ -141,7 +141,7 @@ static inline spx_float_t FLOAT_SUB(spx_float_t a, spx_float_t b)
       r.m = ((a).m>>1) - ((b).m>>MIN(15,(a).e-(b).e+1));
       r.e = (a).e+1;
    }
-   else 
+   else
    {
       r.m = ((a).m>>MIN(15,(b).e-(a).e+1)) - ((b).m>>1);
       r.e = (b).e+1;
@@ -169,10 +169,10 @@ static inline int FLOAT_LT(spx_float_t a, spx_float_t b)
    if (a.m==0)
       return b.m>0;
    else if (b.m==0)
-      return a.m<0;   
+      return a.m<0;
    if ((a).e > (b).e)
       return ((a).m>>1) < ((b).m>>MIN(15,(a).e-(b).e+1));
-   else 
+   else
       return ((b).m>>1) > ((a).m>>MIN(15,(b).e-(a).e+1));
 
 }
@@ -202,7 +202,7 @@ static inline spx_float_t FLOAT_MULT(spx_float_t a, spx_float_t b)
       }
    }
    /*printf ("%f * %f = %f\n", REALFLOAT(a), REALFLOAT(b), REALFLOAT(r));*/
-   return r;   
+   return r;
 }
 
 static inline spx_float_t FLOAT_AMULT(spx_float_t a, spx_float_t b)
@@ -210,7 +210,7 @@ static inline spx_float_t FLOAT_AMULT(spx_float_t a, spx_float_t b)
    spx_float_t r;
    r.m = (spx_int16_t)((spx_int32_t)(a).m*(b).m>>15);
    r.e = (a).e+(b).e+15;
-   return r;   
+   return r;
 }
 
 
diff --git a/vendor/libspeex/libspeexdsp/resample.c b/vendor/libspeex/libspeexdsp/resample.c
index edbd65b5d4..2783f55f0c 100644
--- a/vendor/libspeex/libspeexdsp/resample.c
+++ b/vendor/libspeex/libspeexdsp/resample.c
@@ -1,6 +1,6 @@
 /* Copyright (C) 2007-2008 Jean-Marc Valin
    Copyright (C) 2008      Thorvald Natvig
-      
+
    File: resample.c
    Arbitrary resampling code
 
@@ -38,22 +38,22 @@
       - Low memory requirement
       - Good *perceptual* quality (and not best SNR)
 
-   Warning: This resampler is relatively new. Although I think I got rid of 
+   Warning: This resampler is relatively new. Although I think I got rid of
    all the major bugs and I don't expect the API to change anymore, there
    may be something I've missed. So use with caution.
 
    This algorithm is based on this original resampling algorithm:
    Smith, Julius O. Digital Audio Resampling Home Page
-   Center for Computer Research in Music and Acoustics (CCRMA), 
+   Center for Computer Research in Music and Acoustics (CCRMA),
    Stanford University, 2007.
-   Web published at http://www-ccrma.stanford.edu/~jos/resample/.
+   Web published at https://ccrma.stanford.edu/~jos/resample/.
 
-   There is one main difference, though. This resampler uses cubic 
+   There is one main difference, though. This resampler uses cubic
    interpolation instead of linear interpolation in the above paper. This
    makes the table much smaller and makes it possible to compute that table
-   on a per-stream basis. In turn, being able to tweak the table for each 
-   stream makes it possible to both reduce complexity on simple ratios 
-   (e.g. 2/3), and get rid of the rounding operations in the inner loop. 
+   on a per-stream basis. In turn, being able to tweak the table for each
+   stream makes it possible to both reduce complexity on simple ratios
+   (e.g. 2/3), and get rid of the rounding operations in the inner loop.
    The latter both reduces CPU time and makes the algorithm more SIMD-friendly.
 */
 
@@ -63,9 +63,12 @@
 
 #ifdef OUTSIDE_SPEEX
 #include 
-static void *speex_alloc (int size) {return calloc(size,1);}
-static void *speex_realloc (void *ptr, int size) {return realloc(ptr, size);}
-static void speex_free (void *ptr) {free(ptr);}
+static void *speex_alloc(int size) {return calloc(size,1);}
+static void *speex_realloc(void *ptr, int size) {return realloc(ptr, size);}
+static void speex_free(void *ptr) {free(ptr);}
+#ifndef EXPORT
+#define EXPORT
+#endif
 #include "speex_resampler.h"
 #include "arch.h"
 #else /* OUTSIDE_SPEEX */
@@ -75,7 +78,6 @@ static void speex_free (void *ptr) {free(ptr);}
 #include "os_support.h"
 #endif /* OUTSIDE_SPEEX */
 
-#include "stack_alloc.h"
 #include 
 #include 
 
@@ -83,12 +85,6 @@ static void speex_free (void *ptr) {free(ptr);}
 #define M_PI 3.14159265358979323846
 #endif
 
-#ifdef FIXED_POINT
-#define WORD2INT(x) ((x) < -32767 ? -32768 : ((x) > 32766 ? 32767 : (x)))  
-#else
-#define WORD2INT(x) ((x) < -32767.5f ? -32768 : ((x) > 32766.5f ? 32767 : floor(.5+(x))))  
-#endif
-               
 #define IMAX(a,b) ((a) > (b) ? (a) : (b))
 #define IMIN(a,b) ((a) < (b) ? (a) : (b))
 
@@ -96,15 +92,19 @@ static void speex_free (void *ptr) {free(ptr);}
 #define NULL 0
 #endif
 
-#ifdef _USE_SSE
+#ifndef UINT32_MAX
+#define UINT32_MAX 4294967295U
+#endif
+
+#ifdef USE_SSE
 #include "resample_sse.h"
 #endif
 
-#ifdef _USE_NEON
+#ifdef USE_NEON
 #include "resample_neon.h"
 #endif
 
-/* Numer of elements to allocate on the stack */
+/* Number of elements to allocate on the stack */
 #ifdef VAR_ARRAYS
 #define FIXED_STACK_ALLOC 8192
 #else
@@ -118,7 +118,7 @@ struct SpeexResamplerState_ {
    spx_uint32_t out_rate;
    spx_uint32_t num_rate;
    spx_uint32_t den_rate;
-   
+
    int    quality;
    spx_uint32_t nb_channels;
    spx_uint32_t filt_len;
@@ -130,17 +130,17 @@ struct SpeexResamplerState_ {
    spx_uint32_t oversample;
    int          initialised;
    int          started;
-   
+
    /* These are per-channel */
    spx_int32_t  *last_sample;
    spx_uint32_t *samp_frac_num;
    spx_uint32_t *magic_samples;
-   
+
    spx_word16_t *mem;
    spx_word16_t *sinc_table;
    spx_uint32_t sinc_table_length;
    resampler_basic_func resampler_ptr;
-         
+
    int    in_stride;
    int    out_stride;
 } ;
@@ -182,7 +182,7 @@ static const double kaiser8_table[36] = {
    0.32108304, 0.27619388, 0.23465776, 0.19672670, 0.16255380, 0.13219758,
    0.10562887, 0.08273982, 0.06335451, 0.04724088, 0.03412321, 0.02369490,
    0.01563093, 0.00959968, 0.00527363, 0.00233883, 0.00050000, 0.00000000};
-   
+
 static const double kaiser6_table[36] = {
    0.99733006, 1.00000000, 0.99733006, 0.98935595, 0.97618418, 0.95799003,
    0.93501423, 0.90755855, 0.87598009, 0.84068475, 0.80211977, 0.76076565,
@@ -195,17 +195,15 @@ struct FuncDef {
    const double *table;
    int oversample;
 };
-      
-static const struct FuncDef _KAISER12 = {kaiser12_table, 64};
-#define KAISER12 (&_KAISER12)
-/*static struct FuncDef _KAISER12 = {kaiser12_table, 32};
-#define KAISER12 (&_KAISER12)*/
-static const struct FuncDef _KAISER10 = {kaiser10_table, 32};
-#define KAISER10 (&_KAISER10)
-static const struct FuncDef _KAISER8 = {kaiser8_table, 32};
-#define KAISER8 (&_KAISER8)
-static const struct FuncDef _KAISER6 = {kaiser6_table, 32};
-#define KAISER6 (&_KAISER6)
+
+static const struct FuncDef kaiser12_funcdef = {kaiser12_table, 64};
+#define KAISER12 (&kaiser12_funcdef)
+static const struct FuncDef kaiser10_funcdef = {kaiser10_table, 32};
+#define KAISER10 (&kaiser10_funcdef)
+static const struct FuncDef kaiser8_funcdef = {kaiser8_table, 32};
+#define KAISER8 (&kaiser8_funcdef)
+static const struct FuncDef kaiser6_funcdef = {kaiser6_table, 32};
+#define KAISER6 (&kaiser6_funcdef)
 
 struct QualityMapping {
    int base_length;
@@ -217,7 +215,7 @@ struct QualityMapping {
 
 
 /* This table maps conversion quality to internal parameters. There are two
-   reasons that explain why the up-sampling bandwidth is larger than the 
+   reasons that explain why the up-sampling bandwidth is larger than the
    down-sampling bandwidth:
    1) When up-sampling, we can assume that the spectrum is already attenuated
       close to the Nyquist rate (from an A/D or a previous resampling filter)
@@ -243,7 +241,7 @@ static double compute_func(float x, const struct FuncDef *func)
 {
    float y, frac;
    double interp[4];
-   int ind; 
+   int ind;
    y = x*func->oversample;
    ind = (int)floor(y);
    frac = (y-ind);
@@ -254,7 +252,7 @@ static double compute_func(float x, const struct FuncDef *func)
    interp[0] = -0.3333333333*frac + 0.5*(frac*frac) - 0.1666666667*(frac*frac*frac);
    /* Just to make sure we don't have rounding problems */
    interp[1] = 1.f-interp[3]-interp[2]-interp[0];
-   
+
    /*sum = frac*accum[1] + (1-frac)*accum[2];*/
    return interp[0]*func->table[ind] + interp[1]*func->table[ind+1] + interp[2]*func->table[ind+2] + interp[3]*func->table[ind+3];
 }
@@ -475,13 +473,13 @@ static int resampler_basic_interpolate_single(SpeexResamplerState *st, spx_uint3
       }
 
       cubic_coef(frac, interp);
-      sum = MULT16_32_Q15(interp[0],SHR32(accum[0], 1)) + MULT16_32_Q15(interp[1],SHR32(accum[1], 1)) + MULT16_32_Q15(interp[2],SHR32(accum[2], 1)) + MULT16_32_Q15(interp[3],SHR32(accum[3], 1));
+      sum = MULT16_32_Q15(interp[0],accum[0]) + MULT16_32_Q15(interp[1],accum[1]) + MULT16_32_Q15(interp[2],accum[2]) + MULT16_32_Q15(interp[3],accum[3]);
       sum = SATURATE32PSHR(sum, 15, 32767);
 #else
       cubic_coef(frac, interp);
       sum = interpolate_product_single(iptr, st->sinc_table + st->oversample + 4 - offset - 2, N, st->oversample, interp);
 #endif
-      
+
       out[out_stride * out_sample++] = sum;
       last_sample += int_advance;
       samp_frac_num += frac_advance;
@@ -543,7 +541,7 @@ static int resampler_basic_interpolate_double(SpeexResamplerState *st, spx_uint3
       cubic_coef(frac, interp);
       sum = interpolate_product_double(iptr, st->sinc_table + st->oversample + 4 - offset - 2, N, st->oversample, interp);
 #endif
-      
+
       out[out_stride * out_sample++] = PSHR32(sum,15);
       last_sample += int_advance;
       samp_frac_num += frac_advance;
@@ -574,6 +572,7 @@ static int resampler_basic_zero(SpeexResamplerState *st, spx_uint32_t channel_in
    const int frac_advance = st->frac_advance;
    const spx_uint32_t den_rate = st->den_rate;
 
+   (void)in;
    while (!(last_sample >= (spx_int32_t)*in_len || out_sample >= (spx_int32_t)*out_len))
    {
       out[out_stride * out_sample++] = 0;
@@ -591,6 +590,18 @@ static int resampler_basic_zero(SpeexResamplerState *st, spx_uint32_t channel_in
    return out_sample;
 }
 
+static int multiply_frac(spx_uint32_t *result, spx_uint32_t value, spx_uint32_t num, spx_uint32_t den)
+{
+   spx_uint32_t major = value / den;
+   spx_uint32_t remain = value % den;
+   /* TODO: Could use 64 bits operation to check for overflow. But only guaranteed in C99+ */
+   if (remain > UINT32_MAX / num || major > UINT32_MAX / num
+       || major * num > UINT32_MAX - remain * num / den)
+      return RESAMPLER_ERR_OVERFLOW;
+   *result = remain * num / den + major * num;
+   return RESAMPLER_ERR_SUCCESS;
+}
+
 static int update_filter(SpeexResamplerState *st)
 {
    spx_uint32_t old_length = st->filt_len;
@@ -603,13 +614,13 @@ static int update_filter(SpeexResamplerState *st)
    st->frac_advance = st->num_rate%st->den_rate;
    st->oversample = quality_map[st->quality].oversample;
    st->filt_len = quality_map[st->quality].base_length;
-   
+
    if (st->num_rate > st->den_rate)
    {
       /* down-sampling */
       st->cutoff = quality_map[st->quality].downsample_bandwidth * st->den_rate / st->num_rate;
-      /* FIXME: divide the numerator and denominator by a certain amount if they're too large */
-      st->filt_len = st->filt_len*st->num_rate / st->den_rate;
+      if (multiply_frac(&st->filt_len,st->filt_len,st->num_rate,st->den_rate) != RESAMPLER_ERR_SUCCESS)
+         goto fail;
       /* Round up to make sure we have a multiple of 8 for SSE */
       st->filt_len = ((st->filt_len-1)&(~0x7))+8;
       if (2*st->den_rate < st->num_rate)
@@ -626,13 +637,13 @@ static int update_filter(SpeexResamplerState *st)
       /* up-sampling */
       st->cutoff = quality_map[st->quality].upsample_bandwidth;
    }
-   
-   /* Choose the resampling type that requires the least amount of memory */
+
 #ifdef RESAMPLE_FULL_SINC_TABLE
    use_direct = 1;
    if (INT_MAX/sizeof(spx_word16_t)/st->den_rate < st->filt_len)
       goto fail;
 #else
+   /* Choose the resampling type that requires the least amount of memory */
    use_direct = st->filt_len*st->den_rate <= st->filt_len*st->oversample+8
                 && INT_MAX/sizeof(spx_word16_t)/st->den_rate >= st->filt_len;
 #endif
@@ -722,16 +733,18 @@ static int update_filter(SpeexResamplerState *st)
       {
          spx_uint32_t j;
          spx_uint32_t olen = old_length;
+         spx_uint32_t start = i*st->mem_alloc_size;
+         spx_uint32_t magic_samples = st->magic_samples[i];
          /*if (st->magic_samples[i])*/
          {
             /* Try and remove the magic samples as if nothing had happened */
-            
+
             /* FIXME: This is wrong but for now we need it to avoid going over the array bounds */
-            olen = old_length + 2*st->magic_samples[i];
-            for (j=old_length-1+st->magic_samples[i];j--;)
-               st->mem[i*st->mem_alloc_size+j+st->magic_samples[i]] = st->mem[i*old_alloc_size+j];
-            for (j=0;jmagic_samples[i];j++)
-               st->mem[i*st->mem_alloc_size+j] = 0;
+            olen = old_length + 2*magic_samples;
+            for (j=old_length-1+magic_samples;j--;)
+               st->mem[start+j+magic_samples] = st->mem[i*old_alloc_size+j];
+            for (j=0;jmem[start+j] = 0;
             st->magic_samples[i] = 0;
          }
          if (st->filt_len > olen)
@@ -739,17 +752,18 @@ static int update_filter(SpeexResamplerState *st)
             /* If the new filter length is still bigger than the "augmented" length */
             /* Copy data going backward */
             for (j=0;jmem[i*st->mem_alloc_size+(st->filt_len-2-j)] = st->mem[i*st->mem_alloc_size+(olen-2-j)];
+               st->mem[start+(st->filt_len-2-j)] = st->mem[start+(olen-2-j)];
             /* Then put zeros for lack of anything better */
             for (;jfilt_len-1;j++)
-               st->mem[i*st->mem_alloc_size+(st->filt_len-2-j)] = 0;
+               st->mem[start+(st->filt_len-2-j)] = 0;
             /* Adjust last_sample */
             st->last_sample[i] += (st->filt_len - olen)/2;
          } else {
             /* Put back some of the magic! */
-            st->magic_samples[i] = (olen - st->filt_len)/2;
-            for (j=0;jfilt_len-1+st->magic_samples[i];j++)
-               st->mem[i*st->mem_alloc_size+j] = st->mem[i*st->mem_alloc_size+j+st->magic_samples[i]];
+            magic_samples = (olen - st->filt_len)/2;
+            for (j=0;jfilt_len-1+magic_samples;j++)
+               st->mem[start+j] = st->mem[start+j+magic_samples];
+            st->magic_samples[i] = magic_samples;
          }
       }
    } else if (st->filt_len < old_length)
@@ -787,17 +801,22 @@ EXPORT SpeexResamplerState *speex_resampler_init(spx_uint32_t nb_channels, spx_u
 
 EXPORT SpeexResamplerState *speex_resampler_init_frac(spx_uint32_t nb_channels, spx_uint32_t ratio_num, spx_uint32_t ratio_den, spx_uint32_t in_rate, spx_uint32_t out_rate, int quality, int *err)
 {
-   spx_uint32_t i;
    SpeexResamplerState *st;
    int filter_err;
 
-   if (quality > 10 || quality < 0)
+   if (nb_channels == 0 || ratio_num == 0 || ratio_den == 0 || quality > 10 || quality < 0)
    {
       if (err)
          *err = RESAMPLER_ERR_INVALID_ARG;
       return NULL;
    }
    st = (SpeexResamplerState *)speex_alloc(sizeof(SpeexResamplerState));
+   if (!st)
+   {
+      if (err)
+         *err = RESAMPLER_ERR_ALLOC_FAILED;
+      return NULL;
+   }
    st->initialised = 0;
    st->started = 0;
    st->in_rate = 0;
@@ -810,24 +829,21 @@ EXPORT SpeexResamplerState *speex_resampler_init_frac(spx_uint32_t nb_channels,
    st->filt_len = 0;
    st->mem = 0;
    st->resampler_ptr = 0;
-         
+
    st->cutoff = 1.f;
    st->nb_channels = nb_channels;
    st->in_stride = 1;
    st->out_stride = 1;
-   
+
    st->buffer_size = 160;
-   
+
    /* Per channel data */
-   st->last_sample = (spx_int32_t*)speex_alloc(nb_channels*sizeof(spx_int32_t));
-   st->magic_samples = (spx_uint32_t*)speex_alloc(nb_channels*sizeof(spx_uint32_t));
-   st->samp_frac_num = (spx_uint32_t*)speex_alloc(nb_channels*sizeof(spx_uint32_t));
-   for (i=0;ilast_sample[i] = 0;
-      st->magic_samples[i] = 0;
-      st->samp_frac_num[i] = 0;
-   }
+   if (!(st->last_sample = (spx_int32_t*)speex_alloc(nb_channels*sizeof(spx_int32_t))))
+      goto fail;
+   if (!(st->magic_samples = (spx_uint32_t*)speex_alloc(nb_channels*sizeof(spx_uint32_t))))
+      goto fail;
+   if (!(st->samp_frac_num = (spx_uint32_t*)speex_alloc(nb_channels*sizeof(spx_uint32_t))))
+      goto fail;
 
    speex_resampler_set_quality(st, quality);
    speex_resampler_set_rate_frac(st, ratio_num, ratio_den, in_rate, out_rate);
@@ -844,6 +860,12 @@ EXPORT SpeexResamplerState *speex_resampler_init_frac(spx_uint32_t nb_channels,
       *err = filter_err;
 
    return st;
+
+fail:
+   if (err)
+      *err = RESAMPLER_ERR_ALLOC_FAILED;
+   speex_resampler_destroy(st);
+   return NULL;
 }
 
 EXPORT void speex_resampler_destroy(SpeexResamplerState *st)
@@ -863,17 +885,17 @@ static int speex_resampler_process_native(SpeexResamplerState *st, spx_uint32_t
    int out_sample = 0;
    spx_word16_t *mem = st->mem + channel_index * st->mem_alloc_size;
    spx_uint32_t ilen;
-   
+
    st->started = 1;
-   
+
    /* Call the right resampler through the function ptr */
    out_sample = st->resampler_ptr(st, channel_index, mem, in_len, out, out_len);
-   
+
    if (st->last_sample[channel_index] < (spx_int32_t)*in_len)
       *in_len = st->last_sample[channel_index];
    *out_len = out_sample;
    st->last_sample[channel_index] -= *in_len;
-   
+
    ilen = *in_len;
 
    for(j=0;jmagic_samples[channel_index];
    spx_word16_t *mem = st->mem + channel_index * st->mem_alloc_size;
    const int N = st->filt_len;
-   
+
    speex_resampler_process_native(st, channel_index, &tmp_in_len, *out, &out_len);
 
    st->magic_samples[channel_index] -= tmp_in_len;
-   
+
    /* If we couldn't process all "magic" input samples, save the rest for next time */
    if (st->magic_samples[channel_index])
    {
@@ -916,13 +938,13 @@ EXPORT int speex_resampler_process_float(SpeexResamplerState *st, spx_uint32_t c
    const spx_uint32_t xlen = st->mem_alloc_size - filt_offs;
    const int istride = st->in_stride;
 
-   if (st->magic_samples[channel_index]) 
+   if (st->magic_samples[channel_index])
       olen -= speex_resampler_magic(st, channel_index, &out, olen);
    if (! st->magic_samples[channel_index]) {
       while (ilen && olen) {
         spx_uint32_t ichunk = (ilen > xlen) ? xlen : ilen;
         spx_uint32_t ochunk = olen;
- 
+
         if (in) {
            for(j=0;jmem_alloc_size - (st->filt_len - 1);
 #ifdef VAR_ARRAYS
    const unsigned int ylen = (olen < FIXED_STACK_ALLOC) ? olen : FIXED_STACK_ALLOC;
-   VARDECL(spx_word16_t *ystack);
-   ALLOC(ystack, ylen, spx_word16_t);
+   spx_word16_t ystack[ylen];
 #else
    const unsigned int ylen = FIXED_STACK_ALLOC;
    spx_word16_t ystack[FIXED_STACK_ALLOC];
 #endif
 
    st->out_stride = 1;
-   
+
    while (ilen && olen) {
      spx_word16_t *y = ystack;
      spx_uint32_t ichunk = (ilen > xlen) ? xlen : ilen;
@@ -1003,7 +1024,7 @@ EXPORT int speex_resampler_process_int(SpeexResamplerState *st, spx_uint32_t cha
 #else
         out[j*ostride_save] = WORD2INT(ystack[j]);
 #endif
-     
+
      ilen -= ichunk;
      olen -= ochunk;
      out += (ochunk+omagic) * ostride_save;
@@ -1039,7 +1060,7 @@ EXPORT int speex_resampler_process_interleaved_float(SpeexResamplerState *st, co
    st->out_stride = ostride_save;
    return st->resampler_ptr == resampler_basic_zero ? RESAMPLER_ERR_ALLOC_FAILED : RESAMPLER_ERR_SUCCESS;
 }
-               
+
 EXPORT int speex_resampler_process_interleaved_int(SpeexResamplerState *st, const spx_int16_t *in, spx_uint32_t *in_len, spx_int16_t *out, spx_uint32_t *out_len)
 {
    spx_uint32_t i;
@@ -1074,40 +1095,53 @@ EXPORT void speex_resampler_get_rate(SpeexResamplerState *st, spx_uint32_t *in_r
    *out_rate = st->out_rate;
 }
 
+static inline spx_uint32_t compute_gcd(spx_uint32_t a, spx_uint32_t b)
+{
+   while (b != 0)
+   {
+      spx_uint32_t temp = a;
+
+      a = b;
+      b = temp % b;
+   }
+   return a;
+}
+
 EXPORT int speex_resampler_set_rate_frac(SpeexResamplerState *st, spx_uint32_t ratio_num, spx_uint32_t ratio_den, spx_uint32_t in_rate, spx_uint32_t out_rate)
 {
    spx_uint32_t fact;
    spx_uint32_t old_den;
    spx_uint32_t i;
+
+   if (ratio_num == 0 || ratio_den == 0)
+      return RESAMPLER_ERR_INVALID_ARG;
+
    if (st->in_rate == in_rate && st->out_rate == out_rate && st->num_rate == ratio_num && st->den_rate == ratio_den)
       return RESAMPLER_ERR_SUCCESS;
-   
+
    old_den = st->den_rate;
    st->in_rate = in_rate;
    st->out_rate = out_rate;
    st->num_rate = ratio_num;
    st->den_rate = ratio_den;
-   /* FIXME: This is terribly inefficient, but who cares (at least for now)? */
-   for (fact=2;fact<=IMIN(st->num_rate, st->den_rate);fact++)
-   {
-      while ((st->num_rate % fact == 0) && (st->den_rate % fact == 0))
-      {
-         st->num_rate /= fact;
-         st->den_rate /= fact;
-      }
-   }
-      
+
+   fact = compute_gcd(st->num_rate, st->den_rate);
+
+   st->num_rate /= fact;
+   st->den_rate /= fact;
+
    if (old_den > 0)
    {
       for (i=0;inb_channels;i++)
       {
-         st->samp_frac_num[i]=st->samp_frac_num[i]*st->den_rate/old_den;
+         if (multiply_frac(&st->samp_frac_num[i],st->samp_frac_num[i],st->den_rate,old_den) != RESAMPLER_ERR_SUCCESS)
+            return RESAMPLER_ERR_OVERFLOW;
          /* Safety net */
          if (st->samp_frac_num[i] >= st->den_rate)
             st->samp_frac_num[i] = st->den_rate-1;
       }
    }
-   
+
    if (st->initialised)
       return update_filter(st);
    return RESAMPLER_ERR_SUCCESS;
diff --git a/vendor/libspeex/libspeexdsp/resample_neon.h b/vendor/libspeex/libspeexdsp/resample_neon.h
index 0acbd27b9a..85a51fe1c3 100644
--- a/vendor/libspeex/libspeexdsp/resample_neon.h
+++ b/vendor/libspeex/libspeexdsp/resample_neon.h
@@ -36,14 +36,26 @@
    SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
 */
 
-#include 
+#include 
 
 #ifdef FIXED_POINT
-#ifdef __thumb2__
+#if defined(__aarch64__)
+static inline int32_t saturate_32bit_to_16bit(int32_t a) {
+    int32_t ret;
+    asm ("fmov s0, %w[a]\n"
+         "sqxtn h0, s0\n"
+         "sxtl v0.4s, v0.4h\n"
+         "fmov %w[ret], s0\n"
+         : [ret] "=r" (ret)
+         : [a] "r" (a)
+         : "v0" );
+    return ret;
+}
+#elif defined(__thumb2__)
 static inline int32_t saturate_32bit_to_16bit(int32_t a) {
     int32_t ret;
     asm ("ssat %[ret], #16, %[a]"
-         : [ret] "=&r" (ret)
+         : [ret] "=r" (ret)
          : [a] "r" (a)
          : );
     return ret;
@@ -54,7 +66,7 @@ static inline int32_t saturate_32bit_to_16bit(int32_t a) {
     asm ("vmov.s32 d0[0], %[a]\n"
          "vqmovn.s32 d0, q0\n"
          "vmov.s16 %[ret], d0[0]\n"
-         : [ret] "=&r" (ret)
+         : [ret] "=r" (ret)
          : [a] "r" (a)
          : "q0");
     return ret;
@@ -64,7 +76,63 @@ static inline int32_t saturate_32bit_to_16bit(int32_t a) {
 #define WORD2INT(x) (saturate_32bit_to_16bit(x))
 
 #define OVERRIDE_INNER_PRODUCT_SINGLE
-/* Only works when len % 4 == 0 */
+/* Only works when len % 4 == 0 and len >= 4 */
+#if defined(__aarch64__)
+static inline int32_t inner_product_single(const int16_t *a, const int16_t *b, unsigned int len)
+{
+    int32_t ret;
+    uint32_t remainder = len % 16;
+    len = len - remainder;
+
+    asm volatile ("	 cmp %w[len], #0\n"
+		  "	 b.ne 1f\n"
+		  "	 ld1 {v16.4h}, [%[b]], #8\n"
+		  "	 ld1 {v20.4h}, [%[a]], #8\n"
+		  "	 subs %w[remainder], %w[remainder], #4\n"
+		  "	 smull v0.4s, v16.4h, v20.4h\n"
+		  "      b.ne 4f\n"
+		  "	 b 5f\n"
+		  "1:"
+		  "	 ld1 {v16.4h, v17.4h, v18.4h, v19.4h}, [%[b]], #32\n"
+		  "	 ld1 {v20.4h, v21.4h, v22.4h, v23.4h}, [%[a]], #32\n"
+		  "	 subs %w[len], %w[len], #16\n"
+		  "	 smull v0.4s, v16.4h, v20.4h\n"
+		  "	 smlal v0.4s, v17.4h, v21.4h\n"
+		  "	 smlal v0.4s, v18.4h, v22.4h\n"
+		  "	 smlal v0.4s, v19.4h, v23.4h\n"
+		  "	 b.eq 3f\n"
+		  "2:"
+		  "	 ld1 {v16.4h, v17.4h, v18.4h, v19.4h}, [%[b]], #32\n"
+		  "	 ld1 {v20.4h, v21.4h, v22.4h, v23.4h}, [%[a]], #32\n"
+		  "	 subs %w[len], %w[len], #16\n"
+		  "	 smlal v0.4s, v16.4h, v20.4h\n"
+		  "	 smlal v0.4s, v17.4h, v21.4h\n"
+		  "	 smlal v0.4s, v18.4h, v22.4h\n"
+		  "	 smlal v0.4s, v19.4h, v23.4h\n"
+		  "	 b.ne 2b\n"
+		  "3:"
+		  "	 cmp %w[remainder], #0\n"
+		  "	 b.eq 5f\n"
+		  "4:"
+		  "	 ld1 {v18.4h}, [%[b]], #8\n"
+		  "	 ld1 {v22.4h}, [%[a]], #8\n"
+		  "	 subs %w[remainder], %w[remainder], #4\n"
+		  "	 smlal v0.4s, v18.4h, v22.4h\n"
+		  "	 b.ne 4b\n"
+		  "5:"
+		  "	 saddlv d0, v0.4s\n"
+		  "	 sqxtn s0, d0\n"
+		  "	 sqrshrn h0, s0, #15\n"
+		  "	 sxtl v0.4s, v0.4h\n"
+		  "	 fmov %w[ret], s0\n"
+		  : [ret] "=r" (ret), [a] "+r" (a), [b] "+r" (b),
+		    [len] "+r" (len), [remainder] "+r" (remainder)
+		  :
+		  : "cc", "v0",
+		    "v16", "v17", "v18", "v19", "v20", "v21", "v22", "v23");
+    return ret;
+}
+#else
 static inline int32_t inner_product_single(const int16_t *a, const int16_t *b, unsigned int len)
 {
     int32_t ret;
@@ -112,33 +180,104 @@ static inline int32_t inner_product_single(const int16_t *a, const int16_t *b, u
 		  "	 vqmovn.s64 d0, q0\n"
 		  "	 vqrshrn.s32 d0, q0, #15\n"
 		  "	 vmov.s16 %[ret], d0[0]\n"
-		  : [ret] "=&r" (ret), [a] "+r" (a), [b] "+r" (b),
+		  : [ret] "=r" (ret), [a] "+r" (a), [b] "+r" (b),
 		    [len] "+r" (len), [remainder] "+r" (remainder)
 		  :
 		  : "cc", "q0",
-		    "d16", "d17", "d18", "d19",
-		    "d20", "d21", "d22", "d23");
+		    "d16", "d17", "d18", "d19", "d20", "d21", "d22", "d23");
 
     return ret;
 }
-#elif defined(FLOATING_POINT)
+#endif  // !defined(__aarch64__)
 
+#elif defined(FLOATING_POINT)
+#if defined(__aarch64__)
+static inline int32_t saturate_float_to_16bit(float a) {
+    int32_t ret;
+    asm ("fcvtas s1, %s[a]\n"
+         "sqxtn h1, s1\n"
+         "sxtl v1.4s, v1.4h\n"
+         "fmov %w[ret], s1\n"
+         : [ret] "=r" (ret)
+         : [a] "w" (a)
+         : "v1");
+    return ret;
+}
+#else
 static inline int32_t saturate_float_to_16bit(float a) {
     int32_t ret;
     asm ("vmov.f32 d0[0], %[a]\n"
          "vcvt.s32.f32 d0, d0, #15\n"
          "vqrshrn.s32 d0, q0, #15\n"
          "vmov.s16 %[ret], d0[0]\n"
-         : [ret] "=&r" (ret)
+         : [ret] "=r" (ret)
          : [a] "r" (a)
          : "q0");
     return ret;
 }
+#endif
+
 #undef WORD2INT
 #define WORD2INT(x) (saturate_float_to_16bit(x))
 
 #define OVERRIDE_INNER_PRODUCT_SINGLE
-/* Only works when len % 4 == 0 */
+/* Only works when len % 4 == 0 and len >= 4 */
+#if defined(__aarch64__)
+static inline float inner_product_single(const float *a, const float *b, unsigned int len)
+{
+    float ret;
+    uint32_t remainder = len % 16;
+    len = len - remainder;
+
+    asm volatile ("	 cmp %w[len], #0\n"
+		  "	 b.ne 1f\n"
+		  "	 ld1 {v16.4s}, [%[b]], #16\n"
+		  "	 ld1 {v20.4s}, [%[a]], #16\n"
+		  "	 subs %w[remainder], %w[remainder], #4\n"
+		  "	 fmul v1.4s, v16.4s, v20.4s\n"
+		  "      b.ne 4f\n"
+		  "	 b 5f\n"
+		  "1:"
+		  "	 ld1 {v16.4s, v17.4s, v18.4s, v19.4s}, [%[b]], #64\n"
+		  "	 ld1 {v20.4s, v21.4s, v22.4s, v23.4s}, [%[a]], #64\n"
+		  "	 subs %w[len], %w[len], #16\n"
+		  "	 fmul v1.4s, v16.4s, v20.4s\n"
+		  "	 fmul v2.4s, v17.4s, v21.4s\n"
+		  "	 fmul v3.4s, v18.4s, v22.4s\n"
+		  "	 fmul v4.4s, v19.4s, v23.4s\n"
+		  "	 b.eq 3f\n"
+		  "2:"
+		  "	 ld1 {v16.4s, v17.4s, v18.4s, v19.4s}, [%[b]], #64\n"
+		  "	 ld1 {v20.4s, v21.4s, v22.4s, v23.4s}, [%[a]], #64\n"
+		  "	 subs %w[len], %w[len], #16\n"
+		  "	 fmla v1.4s, v16.4s, v20.4s\n"
+		  "	 fmla v2.4s, v17.4s, v21.4s\n"
+		  "	 fmla v3.4s, v18.4s, v22.4s\n"
+		  "	 fmla v4.4s, v19.4s, v23.4s\n"
+		  "	 b.ne 2b\n"
+		  "3:"
+		  "	 fadd v16.4s, v1.4s, v2.4s\n"
+		  "	 fadd v17.4s, v3.4s, v4.4s\n"
+		  "	 cmp %w[remainder], #0\n"
+		  "	 fadd v1.4s, v16.4s, v17.4s\n"
+		  "	 b.eq 5f\n"
+		  "4:"
+		  "	 ld1 {v18.4s}, [%[b]], #16\n"
+		  "	 ld1 {v22.4s}, [%[a]], #16\n"
+		  "	 subs %w[remainder], %w[remainder], #4\n"
+		  "	 fmla v1.4s, v18.4s, v22.4s\n"
+		  "	 b.ne 4b\n"
+		  "5:"
+		  "	 faddp v1.4s, v1.4s, v1.4s\n"
+		  "	 faddp %[ret].4s, v1.4s, v1.4s\n"
+		  : [ret] "=w" (ret), [a] "+r" (a), [b] "+r" (b),
+		    [len] "+r" (len), [remainder] "+r" (remainder)
+		  :
+		  : "cc", "v1", "v2", "v3", "v4",
+		    "v16", "v17", "v18", "v19", "v20", "v21", "v22", "v23");
+    return ret;
+}
+#else
 static inline float inner_product_single(const float *a, const float *b, unsigned int len)
 {
     float ret;
@@ -191,11 +330,12 @@ static inline float inner_product_single(const float *a, const float *b, unsigne
 		  "	 vadd.f32 d0, d0, d1\n"
 		  "	 vpadd.f32 d0, d0, d0\n"
 		  "	 vmov.f32 %[ret], d0[0]\n"
-		  : [ret] "=&r" (ret), [a] "+r" (a), [b] "+r" (b),
+		  : [ret] "=r" (ret), [a] "+r" (a), [b] "+r" (b),
 		    [len] "+l" (len), [remainder] "+l" (remainder)
 		  :
-		  : "cc", "q0", "q1", "q2", "q3", "q4", "q5", "q6", "q7", "q8",
-                    "q9", "q10", "q11");
+		  : "cc", "q0", "q1", "q2", "q3",
+		    "q4", "q5", "q6", "q7", "q8", "q9", "q10", "q11");
     return ret;
 }
+#endif  // defined(__aarch64__)
 #endif
diff --git a/vendor/libspeex/libspeexdsp/resample_sse.h b/vendor/libspeex/libspeexdsp/resample_sse.h
index 64be8a1616..00dc29465b 100644
--- a/vendor/libspeex/libspeexdsp/resample_sse.h
+++ b/vendor/libspeex/libspeexdsp/resample_sse.h
@@ -9,18 +9,18 @@
    Redistribution and use in source and binary forms, with or without
    modification, are permitted provided that the following conditions
    are met:
-   
+
    - Redistributions of source code must retain the above copyright
    notice, this list of conditions and the following disclaimer.
-   
+
    - Redistributions in binary form must reproduce the above copyright
    notice, this list of conditions and the following disclaimer in the
    documentation and/or other materials provided with the distribution.
-   
+
    - Neither the name of the Xiph.org Foundation nor the names of its
    contributors may be used to endorse or promote products derived from
    this software without specific prior written permission.
-   
+
    THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
    ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
    LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
@@ -71,7 +71,7 @@ static inline float interpolate_product_single(const float *a, const float *b, u
    return ret;
 }
 
-#ifdef _USE_SSE2
+#ifdef USE_SSE2
 #include 
 #define OVERRIDE_INNER_PRODUCT_DOUBLE
 
diff --git a/vendor/libspeex/libspeexdsp/scal.c b/vendor/libspeex/libspeexdsp/scal.c
index d2ea59c758..807cb51238 100644
--- a/vendor/libspeex/libspeexdsp/scal.c
+++ b/vendor/libspeex/libspeexdsp/scal.c
@@ -33,8 +33,8 @@
 /*
 The algorithm implemented here is described in:
 
-* J.-M. Valin, Perceptually-Motivated Nonlinear Channel Decorrelation For 
-  Stereo Acoustic Echo Cancellation, Accepted for Joint Workshop on 
+* J.-M. Valin, Perceptually-Motivated Nonlinear Channel Decorrelation For
+  Stereo Acoustic Echo Cancellation, Accepted for Joint Workshop on
   Hands­free Speech Communication and Microphone Arrays (HSCMA), 2008.
   http://people.xiph.org/~jm/papers/valin_hscma2008.pdf
 
@@ -71,7 +71,7 @@ struct SpeexDecorrState_ {
    float *vorbis_win;
    int    seed;
    float *y;
-   
+
    /* Per-channel stuff */
    float *buff;
    float (*ring)[ALLPASS_ORDER];
@@ -102,13 +102,13 @@ EXPORT SpeexDecorrState *speex_decorrelate_new(int rate, int channels, int frame
    st->order = speex_alloc(channels*sizeof(int));
    st->alpha = speex_alloc(channels*sizeof(float));
    st->ring = speex_alloc(channels*ALLPASS_ORDER*sizeof(float));
-   
+
    /*FIXME: The +20 is there only as a kludge for ALL_PASS_OLA*/
    st->vorbis_win = speex_alloc((2*frame_size+20)*sizeof(float));
    for (i=0;i<2*frame_size;i++)
       st->vorbis_win[i] = sin(.5*M_PI* sin(M_PI*i/(2*frame_size))*sin(M_PI*i/(2*frame_size)) );
    st->seed = rand();
-   
+
    for (ch=0;ch100)
       strength = 100;
-   
+
    amount = .01*strength;
    for (ch=0;chchannels;ch++)
    {
@@ -156,7 +156,7 @@ EXPORT void speex_decorrelate(SpeexDecorrState *st, const spx_int16_t *in, spx_i
       float beta, beta2;
       float *x;
       float max_alpha = 0;
-      
+
       float *buff;
       float *ring;
       int ringID;
@@ -168,7 +168,7 @@ EXPORT void speex_decorrelate(SpeexDecorrState *st, const spx_int16_t *in, spx_i
       ringID = st->ringID[ch];
       order = st->order[ch];
       alpha = st->alpha[ch];
-      
+
       for (i=0;iframe_size;i++)
          buff[i] = buff[i+st->frame_size];
       for (i=0;iframe_size;i++)
@@ -182,12 +182,12 @@ EXPORT void speex_decorrelate(SpeexDecorrState *st, const spx_int16_t *in, spx_i
          beta = 1-0.63246*amount;
       if (beta<0)
          beta = 0;
-   
+
       beta2 = beta;
       for (i=0;iframe_size;i++)
       {
-         st->y[i] = alpha*(x[i-ALLPASS_ORDER+order]-beta*x[i-ALLPASS_ORDER+order-1])*st->vorbis_win[st->frame_size+i+order] 
-               + x[i-ALLPASS_ORDER]*st->vorbis_win[st->frame_size+i] 
+         st->y[i] = alpha*(x[i-ALLPASS_ORDER+order]-beta*x[i-ALLPASS_ORDER+order-1])*st->vorbis_win[st->frame_size+i+order]
+               + x[i-ALLPASS_ORDER]*st->vorbis_win[st->frame_size+i]
                - alpha*(ring[ringID]
                - beta*ring[ringID+1>=order?0:ringID+1]);
          ring[ringID++]=st->y[i];
@@ -204,7 +204,7 @@ EXPORT void speex_decorrelate(SpeexDecorrState *st, const spx_int16_t *in, spx_i
       max_alpha = pow(.96+.04*(amount-1),order);
       if (max_alpha > .98/(1.+beta2))
          max_alpha = .98/(1.+beta2);
-   
+
       alpha = alpha + .4*uni_rand(&st->seed);
       if (alpha > max_alpha)
          alpha = max_alpha;
@@ -215,8 +215,8 @@ EXPORT void speex_decorrelate(SpeexDecorrState *st, const spx_int16_t *in, spx_i
       ringID = 0;
       for (i=0;iframe_size;i++)
       {
-         float tmp =  alpha*(x[i-ALLPASS_ORDER+order]-beta*x[i-ALLPASS_ORDER+order-1])*st->vorbis_win[i+order] 
-               + x[i-ALLPASS_ORDER]*st->vorbis_win[i] 
+         float tmp =  alpha*(x[i-ALLPASS_ORDER+order]-beta*x[i-ALLPASS_ORDER+order-1])*st->vorbis_win[i+order]
+               + x[i-ALLPASS_ORDER]*st->vorbis_win[i]
                - alpha*(ring[ringID]
                - beta*ring[ringID+1>=order?0:ringID+1]);
          ring[ringID++]=tmp;
@@ -225,7 +225,7 @@ EXPORT void speex_decorrelate(SpeexDecorrState *st, const spx_int16_t *in, spx_i
             ringID=0;
          st->y[i] += tmp;
       }
-   
+
 #ifdef VORBIS_PSYCHO
       float frame[N];
       float scale = 1./N;
@@ -252,7 +252,7 @@ EXPORT void speex_decorrelate(SpeexDecorrState *st, const spx_int16_t *in, spx_i
       for (i=0;i<2*st->frame_size;i++)
          frame[i] *= st->vorbis_win[i];
 #endif
-   
+
       for (i=0;iframe_size;i++)
       {
 #ifdef VORBIS_PSYCHO
@@ -267,7 +267,7 @@ EXPORT void speex_decorrelate(SpeexDecorrState *st, const spx_int16_t *in, spx_i
             tmp = -32767;
          out[i*st->channels+ch] = tmp;
       }
-      
+
       st->ringID[ch] = ringID;
       st->order[ch] = order;
       st->alpha[ch] = alpha;
diff --git a/vendor/libspeex/libspeexdsp/smallft.c b/vendor/libspeex/libspeexdsp/smallft.c
index 5c26d016fe..82c3b0a4a1 100644
--- a/vendor/libspeex/libspeexdsp/smallft.c
+++ b/vendor/libspeex/libspeexdsp/smallft.c
@@ -127,7 +127,7 @@ static void dradf2(int ido,int l1,float *cc,float *ch,float *wa1){
     t1+=ido;
     t2+=ido;
   }
-    
+
   if(ido<2)return;
   if(ido==2)goto L105;
 
@@ -174,7 +174,7 @@ static void dradf4(int ido,int l1,float *cc,float *ch,float *wa1,
   int i,k,t0,t1,t2,t3,t4,t5,t6;
   float ci2,ci3,ci4,cr2,cr3,cr4,ti1,ti2,ti3,ti4,tr1,tr2,tr3,tr4;
   t0=l1*ido;
-  
+
   t1=t0;
   t4=t1<<1;
   t2=t1+(t1<<1);
@@ -246,7 +246,7 @@ static void dradf4(int ido,int l1,float *cc,float *ch,float *wa1,
   if(ido&1)return;
 
  L105:
-  
+
   t2=(t1=t0+ido-1)+(t0<<1);
   t3=ido<<2;
   t4=ido;
@@ -280,7 +280,7 @@ static void dradfg(int ido,int ip,int l1,int idl1,float *cc,float *c1,
   int nbd;
   float dcp,arg,dsp,ar1h,ar2h;
   int idp2,ipp2;
-  
+
   arg=tpi/(float)ip;
   dcp=cos(arg);
   dsp=sin(arg);
@@ -638,7 +638,7 @@ static void dradb2(int ido,int l1,float *cc,float *ch,float *wa1){
   float ti2,tr2;
 
   t0=l1*ido;
-  
+
   t1=0;
   t2=0;
   t3=(ido<<1)-1;
@@ -754,7 +754,7 @@ static void dradb4(int ido,int l1,float *cc,float *ch,float *wa1,
   int i,k,t0,t1,t2,t3,t4,t5,t6,t7,t8;
   float ci2,ci3,ci4,cr2,cr3,cr4,ti1,ti2,ti3,ti4,tr1,tr2,tr3,tr4;
   t0=l1*ido;
-  
+
   t1=0;
   t2=ido<<2;
   t3=0;
@@ -763,7 +763,7 @@ static void dradb4(int ido,int l1,float *cc,float *ch,float *wa1,
     t4=t3+t6;
     t5=t1;
     tr3=cc[t4-1]+cc[t4-1];
-    tr4=cc[t4]+cc[t4]; 
+    tr4=cc[t4]+cc[t4];
     tr1=cc[t3]-cc[(t4+=t6)-1];
     tr2=cc[t3]+cc[t4-1];
     ch[t5]=tr2+tr3;
@@ -858,7 +858,7 @@ static void dradbg(int ido,int ip,int l1,int idl1,float *cc,float *c1,
   ipp2=ip;
   ipph=(ip+1)>>1;
   if(ido
 # else
 #  ifdef HAVE_ALLOCA_H
@@ -101,7 +101,7 @@
 #endif
 
 #if defined(VAR_ARRAYS)
-#define VARDECL(var) 
+#define VARDECL(var)
 #define ALLOC(var, size, type) type var[size]
 #elif defined(USE_ALLOCA)
 #define VARDECL(var) var
diff --git a/vendor/libspeex/libspeexdsp/testdenoise.c b/vendor/libspeex/libspeexdsp/testdenoise.c
new file mode 100644
index 0000000000..adebe941e4
--- /dev/null
+++ b/vendor/libspeex/libspeexdsp/testdenoise.c
@@ -0,0 +1,44 @@
+#ifdef HAVE_CONFIG_H
+#include "config.h"
+#endif
+
+#include "speex/speex_preprocess.h"
+#include 
+
+#define NN 160
+
+int main()
+{
+   short in[NN];
+   int i;
+   SpeexPreprocessState *st;
+   int count=0;
+   float f;
+
+   st = speex_preprocess_state_init(NN, 8000);
+   i=1;
+   speex_preprocess_ctl(st, SPEEX_PREPROCESS_SET_DENOISE, &i);
+   i=0;
+   speex_preprocess_ctl(st, SPEEX_PREPROCESS_SET_AGC, &i);
+   i=8000;
+   speex_preprocess_ctl(st, SPEEX_PREPROCESS_SET_AGC_LEVEL, &i);
+   i=0;
+   speex_preprocess_ctl(st, SPEEX_PREPROCESS_SET_DEREVERB, &i);
+   f=.0;
+   speex_preprocess_ctl(st, SPEEX_PREPROCESS_SET_DEREVERB_DECAY, &f);
+   f=.0;
+   speex_preprocess_ctl(st, SPEEX_PREPROCESS_SET_DEREVERB_LEVEL, &f);
+   while (1)
+   {
+      int vad;
+      fread(in, sizeof(short), NN, stdin);
+      if (feof(stdin))
+         break;
+      vad = speex_preprocess_run(st, in);
+      /*fprintf (stderr, "%d\n", vad);*/
+      fwrite(in, sizeof(short), NN, stdout);
+      count++;
+   }
+   speex_preprocess_state_destroy(st);
+   return 0;
+}
diff --git a/vendor/libspeex/libspeexdsp/testecho.c b/vendor/libspeex/libspeexdsp/testecho.c
new file mode 100644
index 0000000000..1624dc2a31
--- /dev/null
+++ b/vendor/libspeex/libspeexdsp/testecho.c
@@ -0,0 +1,53 @@
+#ifdef HAVE_CONFIG_H
+#include "config.h"
+#endif
+
+#include "speex/speex_echo.h"
+#include "speex/speex_preprocess.h"
+#include 
+#include 
+#include 
+#include 
+#include 
+
+
+#define NN 128
+#define TAIL 1024
+
+int main(int argc, char **argv)
+{
+   FILE *echo_fd, *ref_fd, *e_fd;
+   short echo_buf[NN], ref_buf[NN], e_buf[NN];
+   SpeexEchoState *st;
+   SpeexPreprocessState *den;
+   int sampleRate = 8000;
+
+   if (argc != 4)
+   {
+      fprintf(stderr, "testecho mic_signal.sw speaker_signal.sw output.sw\n");
+      exit(1);
+   }
+   echo_fd = fopen(argv[2], "rb");
+   ref_fd  = fopen(argv[1],  "rb");
+   e_fd    = fopen(argv[3], "wb");
+
+   st = speex_echo_state_init(NN, TAIL);
+   den = speex_preprocess_state_init(NN, sampleRate);
+   speex_echo_ctl(st, SPEEX_ECHO_SET_SAMPLING_RATE, &sampleRate);
+   speex_preprocess_ctl(den, SPEEX_PREPROCESS_SET_ECHO_STATE, st);
+
+   while (!feof(ref_fd) && !feof(echo_fd))
+   {
+      fread(ref_buf, sizeof(short), NN, ref_fd);
+      fread(echo_buf, sizeof(short), NN, echo_fd);
+      speex_echo_cancellation(st, ref_buf, echo_buf, e_buf);
+      speex_preprocess_run(den, e_buf);
+      fwrite(e_buf, sizeof(short), NN, e_fd);
+   }
+   speex_echo_state_destroy(st);
+   speex_preprocess_state_destroy(den);
+   fclose(e_fd);
+   fclose(echo_fd);
+   fclose(ref_fd);
+   return 0;
+}
diff --git a/vendor/libspeex/libspeexdsp/testjitter.c b/vendor/libspeex/libspeexdsp/testjitter.c
new file mode 100644
index 0000000000..399dfe956c
--- /dev/null
+++ b/vendor/libspeex/libspeexdsp/testjitter.c
@@ -0,0 +1,75 @@
+#ifdef HAVE_CONFIG_H
+#include "config.h"
+#endif
+
+#include "speex/speex_jitter.h"
+#include 
+
+union jbpdata {
+  unsigned int idx;
+  unsigned char data[4];
+};
+
+void synthIn(JitterBufferPacket *in, int idx, int span) {
+  union jbpdata d;
+  d.idx = idx;
+
+  in->data = d.data;
+  in->len = sizeof(d);
+  in->timestamp = idx * 10;
+  in->span = span * 10;
+  in->sequence = idx;
+  in->user_data = 0;
+}
+
+void jitterFill(JitterBuffer *jb) {
+   char buffer[65536];
+   JitterBufferPacket in, out;
+   int i;
+
+   out.data = buffer;
+
+   jitter_buffer_reset(jb);
+
+   for(i=0;i<100;++i) {
+     synthIn(&in, i, 1);
+     jitter_buffer_put(jb, &in);
+
+     out.len = 65536;
+     if (jitter_buffer_get(jb, &out, 10, NULL) != JITTER_BUFFER_OK) {
+       printf("Fill test failed iteration %d\n", i);
+     }
+     if (out.timestamp != i * 10) {
+       printf("Fill test expected %d got %d\n", i*10, out.timestamp);
+     }
+     jitter_buffer_tick(jb);
+   }
+}
+
+int main()
+{
+   char buffer[65536];
+   JitterBufferPacket in, out;
+   int i;
+
+   JitterBuffer *jb = jitter_buffer_init(10);
+
+   out.data = buffer;
+
+   /* Frozen sender case */
+   jitterFill(jb);
+   for(i=0;i<100;++i) {
+     out.len = 65536;
+     jitter_buffer_get(jb, &out, 10, NULL);
+     jitter_buffer_tick(jb);
+   }
+   synthIn(&in, 100, 1);
+   jitter_buffer_put(jb, &in);
+   out.len = 65536;
+   if (jitter_buffer_get(jb, &out, 10, NULL) != JITTER_BUFFER_OK) {
+     printf("Failed frozen sender resynchronize\n");
+   } else {
+     printf("Frozen sender: Jitter %d\n", out.timestamp - 100*10);
+   }
+   return 0;
+}
diff --git a/vendor/libspeex/libspeexdsp/testresample.c b/vendor/libspeex/libspeexdsp/testresample.c
new file mode 100644
index 0000000000..7ed866756f
--- /dev/null
+++ b/vendor/libspeex/libspeexdsp/testresample.c
@@ -0,0 +1,86 @@
+/* Copyright (C) 2007 Jean-Marc Valin
+
+   File: testresample.c
+   Testing the resampling code
+
+   Redistribution and use in source and binary forms, with or without
+   modification, are permitted provided that the following conditions are
+   met:
+
+   1. Redistributions of source code must retain the above copyright notice,
+   this list of conditions and the following disclaimer.
+
+   2. Redistributions in binary form must reproduce the above copyright
+   notice, this list of conditions and the following disclaimer in the
+   documentation and/or other materials provided with the distribution.
+
+   3. The name of the author may not be used to endorse or promote products
+   derived from this software without specific prior written permission.
+
+   THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
+   IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
+   OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
+   DISCLAIMED. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT,
+   INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
+   (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
+   SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+   HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
+   STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
+   ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
+   POSSIBILITY OF SUCH DAMAGE.
+*/
+
+#ifdef HAVE_CONFIG_H
+#include "config.h"
+#endif
+
+#include "speex/speex_resampler.h"
+#include 
+#include 
+#include 
+
+#define NN 256
+
+int main()
+{
+   spx_uint32_t i;
+   short *in;
+   short *out;
+   float *fin, *fout;
+   int count = 0;
+   SpeexResamplerState *st = speex_resampler_init(1, 8000, 12000, 10, NULL);
+   speex_resampler_set_rate(st, 96000, 44100);
+   speex_resampler_skip_zeros(st);
+
+   in = malloc(NN*sizeof(short));
+   out = malloc(2*NN*sizeof(short));
+   fin = malloc(NN*sizeof(float));
+   fout = malloc(2*NN*sizeof(float));
+   while (1)
+   {
+      spx_uint32_t in_len;
+      spx_uint32_t out_len;
+      fread(in, sizeof(short), NN, stdin);
+      if (feof(stdin))
+         break;
+      for (i=0;i
+
+#ifdef HAVE_CONFIG_H
+#include "config.h"
+#endif
+
+#include "speex/speex_resampler.h"
+#include 
+#include 
+
+#define PERIOD 32
+#define INBLOCK 1024
+#define RATE 48000
+
+int main()
+{
+   spx_uint32_t i;
+   float *fin, *fout;
+   int rate = 1000, off = 0, avail = INBLOCK;
+   SpeexResamplerState *st = speex_resampler_init(1, RATE, RATE, 4, NULL);
+   speex_resampler_set_rate(st, RATE, rate);
+   speex_resampler_skip_zeros(st);
+
+   fin = malloc(INBLOCK*2*sizeof(float));
+   for (i=0; i ", rate, off, in_len, out_len);
+
+      speex_resampler_process_float(st, 0, fin + off, &in_len, fout, &out_len);
+
+      fprintf (stderr, "%d %d\n", in_len, out_len);
+      off += in_len;
+      avail = avail - in_len + INBLOCK;
+
+      if (off >= INBLOCK)
+        off -= INBLOCK;
+
+      fwrite(fout, sizeof(float), out_len, stdout);
+
+      rate += 100;
+      if (rate > 128000)
+        break;
+
+      speex_resampler_set_rate(st, RATE, rate);
+   }
+   speex_resampler_destroy(st);
+   free(fin);
+   free(fout);
+   return 0;
+}
+
diff --git a/vendor/libspeex/libspeexdsp/vorbis_psy.h b/vendor/libspeex/libspeexdsp/vorbis_psy.h
index 6871057753..19ea9c3cf2 100644
--- a/vendor/libspeex/libspeexdsp/vorbis_psy.h
+++ b/vendor/libspeex/libspeexdsp/vorbis_psy.h
@@ -4,18 +4,18 @@
    Redistribution and use in source and binary forms, with or without
    modification, are permitted provided that the following conditions
    are met:
-   
+
    - Redistributions of source code must retain the above copyright
    notice, this list of conditions and the following disclaimer.
-   
+
    - Redistributions in binary form must reproduce the above copyright
    notice, this list of conditions and the following disclaimer in the
    documentation and/or other materials provided with the distribution.
-   
+
    - Neither the name of the Xiph.org Foundation nor the names of its
    contributors may be used to endorse or promote products derived from
    this software without specific prior written permission.
-   
+
    THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
    ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
    LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
@@ -40,7 +40,7 @@
 
 
 #define todB(x)   ((x)>1e-13?log((x)*(x))*4.34294480f:-30)
-#define fromdB(x) (exp((x)*.11512925f))  
+#define fromdB(x) (exp((x)*.11512925f))
 
 /* The bark scale equations are approximations, since the original
    table was somewhat hand rolled.  The below are chosen to have the
diff --git a/vendor/libspeex/speex/speex.h b/vendor/libspeex/speex/speex.h
index 28c4b44df8..34919e2f00 100644
--- a/vendor/libspeex/speex/speex.h
+++ b/vendor/libspeex/speex/speex.h
@@ -412,7 +412,7 @@ extern const SpeexMode * const speex_mode_list[SPEEX_NB_MODES];
 /** Obtain one of the modes available */
 const SpeexMode * speex_lib_get_mode (int mode);
 
-#ifndef WIN32
+#ifndef _WIN32
 /* We actually override the function in the narrowband case so that we can avoid linking in the wideband stuff */
 #define speex_lib_get_mode(mode) ((mode)==SPEEX_MODEID_NB ? &speex_nb_mode : speex_lib_get_mode (mode))
 #endif
diff --git a/vendor/libspeex/speex/speex_buffer.h b/vendor/libspeex/speex/speex_buffer.h
index 5bd128ae7d..9e85cfcf0e 100644
--- a/vendor/libspeex/speex/speex_buffer.h
+++ b/vendor/libspeex/speex/speex_buffer.h
@@ -1,5 +1,5 @@
 /* Copyright (C) 2007 Jean-Marc Valin
-      
+
    File: speex_buffer.h
    This is a very simple ring buffer implementation. It is not thread-safe
    so you need to do your own locking.
diff --git a/vendor/libspeex/speex/speex_config_types.h b/vendor/libspeex/speex/speex_config_types.h
index f864522910..ca1f5a3c20 100644
--- a/vendor/libspeex/speex/speex_config_types.h
+++ b/vendor/libspeex/speex/speex_config_types.h
@@ -1,7 +1,7 @@
 #ifndef __SPEEX_TYPES_H__
 #define __SPEEX_TYPES_H__
 
-#include 
+#include 
 
 typedef int16_t spx_int16_t;
 typedef uint16_t spx_uint16_t;
diff --git a/vendor/libspeex/speex/speex_echo.h b/vendor/libspeex/speex/speex_echo.h
index 6f14d0913f..4c1aa5a5f2 100644
--- a/vendor/libspeex/speex/speex_echo.h
+++ b/vendor/libspeex/speex/speex_echo.h
@@ -63,7 +63,7 @@ extern "C" {
 struct SpeexEchoState_;
 
 /** @class SpeexEchoState
- * This holds the state of the echo canceller. You need one per channel. 
+ * This holds the state of the echo canceller. You need one per channel.
 */
 
 /** Internal echo canceller state. Should never be accessed directly. */
@@ -85,7 +85,7 @@ SpeexEchoState *speex_echo_state_init(int frame_size, int filter_length);
  */
 SpeexEchoState *speex_echo_state_init_mc(int frame_size, int filter_length, int nb_mic, int nb_speakers);
 
-/** Destroys an echo canceller state 
+/** Destroys an echo canceller state
  * @param st Echo canceller state
 */
 void speex_echo_state_destroy(SpeexEchoState *st);
@@ -117,7 +117,7 @@ void speex_echo_capture(SpeexEchoState *st, const spx_int16_t *rec, spx_int16_t
 */
 void speex_echo_playback(SpeexEchoState *st, const spx_int16_t *play);
 
-/** Reset the echo canceller to its original state 
+/** Reset the echo canceller to its original state
  * @param st Echo canceller state
  */
 void speex_echo_state_reset(SpeexEchoState *st);
@@ -139,7 +139,7 @@ typedef struct SpeexDecorrState_ SpeexDecorrState;
 
 
 /** Create a state for the channel decorrelation algorithm
-    This is useful for multi-channel echo cancellation only 
+    This is useful for multi-channel echo cancellation only
  * @param rate Sampling rate
  * @param channels Number of channels (it's a bit pointless if you don't have at least 2)
  * @param frame_size Size of the frame to process at ones (counting samples *per* channel)
@@ -155,7 +155,7 @@ SpeexDecorrState *speex_decorrelate_new(int rate, int channels, int frame_size);
 */
 void speex_decorrelate(SpeexDecorrState *st, const spx_int16_t *in, spx_int16_t *out, int strength);
 
-/** Destroy a Decorrelation state 
+/** Destroy a Decorrelation state
  * @param st State to destroy
 */
 void speex_decorrelate_destroy(SpeexDecorrState *st);
diff --git a/vendor/libspeex/speex/speex_jitter.h b/vendor/libspeex/speex/speex_jitter.h
index 66708da5c9..8fc8d7ec66 100644
--- a/vendor/libspeex/speex/speex_jitter.h
+++ b/vendor/libspeex/speex/speex_jitter.h
@@ -7,18 +7,18 @@
    Redistribution and use in source and binary forms, with or without
    modification, are permitted provided that the following conditions
    are met:
-   
+
    - Redistributions of source code must retain the above copyright
    notice, this list of conditions and the following disclaimer.
-   
+
    - Redistributions in binary form must reproduce the above copyright
    notice, this list of conditions and the following disclaimer in the
    documentation and/or other materials provided with the distribution.
-   
+
    - Neither the name of the Xiph.org Foundation nor the names of its
    contributors may be used to endorse or promote products derived from
    this software without specific prior written permission.
-   
+
    THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
    ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
    LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
@@ -89,7 +89,7 @@ struct _JitterBufferPacket {
 /** Included because of an early misspelling (will remove in next release) */
 #define JITTER_BUFFER_GET_AVALIABLE_COUNT 3
 
-/** Assign a function to destroy unused packet. When setting that, the jitter 
+/** Assign a function to destroy unused packet. When setting that, the jitter
     buffer no longer copies packet data. */
 #define JITTER_BUFFER_SET_DESTROY_CALLBACK 4
 /**  */
@@ -104,7 +104,7 @@ struct _JitterBufferPacket {
 #define JITTER_BUFFER_SET_CONCEALMENT_SIZE 8
 #define JITTER_BUFFER_GET_CONCEALMENT_SIZE 9
 
-/** Absolute max amount of loss that can be tolerated regardless of the delay. Typical loss 
+/** Absolute max amount of loss that can be tolerated regardless of the delay. Typical loss
     should be half of that or less. */
 #define JITTER_BUFFER_SET_MAX_LATE_RATE 10
 #define JITTER_BUFFER_GET_MAX_LATE_RATE 11
@@ -114,59 +114,59 @@ struct _JitterBufferPacket {
 #define JITTER_BUFFER_GET_LATE_COST 13
 
 
-/** Initialises jitter buffer 
- * 
- * @param step_size Starting value for the size of concleanment packets and delay 
+/** Initialises jitter buffer
+ *
+ * @param step_size Starting value for the size of concleanment packets and delay
        adjustment steps. Can be changed at any time using JITTER_BUFFER_SET_DELAY_STEP
        and JITTER_BUFFER_GET_CONCEALMENT_SIZE.
  * @return Newly created jitter buffer state
  */
 JitterBuffer *jitter_buffer_init(int step_size);
 
-/** Restores jitter buffer to its original state 
- * 
+/** Restores jitter buffer to its original state
+ *
  * @param jitter Jitter buffer state
  */
 void jitter_buffer_reset(JitterBuffer *jitter);
 
-/** Destroys jitter buffer 
- * 
+/** Destroys jitter buffer
+ *
  * @param jitter Jitter buffer state
  */
 void jitter_buffer_destroy(JitterBuffer *jitter);
 
 /** Put one packet into the jitter buffer
- * 
+ *
  * @param jitter Jitter buffer state
  * @param packet Incoming packet
 */
 void jitter_buffer_put(JitterBuffer *jitter, const JitterBufferPacket *packet);
 
 /** Get one packet from the jitter buffer
- * 
+ *
  * @param jitter Jitter buffer state
  * @param packet Returned packet
  * @param desired_span Number of samples (or units) we wish to get from the buffer (no guarantee)
- * @param current_timestamp Timestamp for the returned packet 
+ * @param current_timestamp Timestamp for the returned packet
 */
 int jitter_buffer_get(JitterBuffer *jitter, JitterBufferPacket *packet, spx_int32_t desired_span, spx_int32_t *start_offset);
 
 /** Used right after jitter_buffer_get() to obtain another packet that would have the same timestamp.
  * This is mainly useful for media where a single "frame" can be split into several packets.
- * 
+ *
  * @param jitter Jitter buffer state
  * @param packet Returned packet
  */
 int jitter_buffer_get_another(JitterBuffer *jitter, JitterBufferPacket *packet);
 
 /** Get pointer timestamp of jitter buffer
- * 
+ *
  * @param jitter Jitter buffer state
 */
 int jitter_buffer_get_pointer_timestamp(JitterBuffer *jitter);
 
 /** Advance by one tick
- * 
+ *
  * @param jitter Jitter buffer state
 */
 void jitter_buffer_tick(JitterBuffer *jitter);
@@ -178,7 +178,7 @@ void jitter_buffer_tick(JitterBuffer *jitter);
 void jitter_buffer_remaining_span(JitterBuffer *jitter, spx_uint32_t rem);
 
 /** Used like the ioctl function to control the jitter buffer parameters
- * 
+ *
  * @param jitter Jitter buffer state
  * @param request ioctl-type request (one of the JITTER_BUFFER_* macros)
  * @param ptr Data exchanged to-from function
diff --git a/vendor/libspeex/speex/speex_preprocess.h b/vendor/libspeex/speex/speex_preprocess.h
index b9555eb551..a2e1210d41 100644
--- a/vendor/libspeex/speex/speex_preprocess.h
+++ b/vendor/libspeex/speex/speex_preprocess.h
@@ -2,7 +2,7 @@
    Written by Jean-Marc Valin */
 /**
  *  @file speex_preprocess.h
- *  @brief Speex preprocessor. The preprocess can do noise suppression, 
+ *  @brief Speex preprocessor. The preprocess can do noise suppression,
  * residual echo suppression (after using the echo canceller), automatic
  * gain control (AGC) and voice activity detection (VAD).
 */
@@ -37,7 +37,7 @@
 #ifndef SPEEX_PREPROCESS_H
 #define SPEEX_PREPROCESS_H
 /** @defgroup SpeexPreprocessState SpeexPreprocessState: The Speex preprocessor
- *  This is the Speex preprocessor. The preprocess can do noise suppression, 
+ *  This is the Speex preprocessor. The preprocess can do noise suppression,
  * residual echo suppression (after using the echo canceller), automatic
  * gain control (AGC) and voice activity detection (VAD).
  *  @{
@@ -48,7 +48,7 @@
 #ifdef __cplusplus
 extern "C" {
 #endif
-   
+
 /** State of the preprocessor (one per channel). Should never be accessed directly. */
 struct SpeexPreprocessState_;
 
@@ -64,12 +64,12 @@ typedef struct SpeexPreprocessState_ SpeexPreprocessState;
 */
 SpeexPreprocessState *speex_preprocess_state_init(int frame_size, int sampling_rate);
 
-/** Destroys a preprocessor state 
+/** Destroys a preprocessor state
  * @param st Preprocessor state to destroy
 */
 void speex_preprocess_state_destroy(SpeexPreprocessState *st);
 
-/** Preprocess a frame 
+/** Preprocess a frame
  * @param st Preprocessor state
  * @param x Audio sample vector (in and out). Must be same size as specified in speex_preprocess_state_init().
  * @return Bool value for voice activity (1 for speech, 0 for noise/silence), ONLY if VAD turned on.
@@ -85,7 +85,7 @@ int speex_preprocess(SpeexPreprocessState *st, spx_int16_t *x, spx_int32_t *echo
 */
 void speex_preprocess_estimate_update(SpeexPreprocessState *st, spx_int16_t *x);
 
-/** Used like the ioctl function to control the preprocessor parameters 
+/** Used like the ioctl function to control the preprocessor parameters
  * @param st Preprocessor state
  * @param request ioctl-type request (one of the SPEEX_PREPROCESS_* macros)
  * @param ptr Data exchanged to-from function
diff --git a/vendor/libspeex/speex/speex_resampler.h b/vendor/libspeex/speex/speex_resampler.h
index 50d777f5b4..901de37b3d 100644
--- a/vendor/libspeex/speex/speex_resampler.h
+++ b/vendor/libspeex/speex/speex_resampler.h
@@ -1,8 +1,8 @@
 /* Copyright (C) 2007 Jean-Marc Valin
-      
+
    File: speex_resampler.h
    Resampling code
-      
+
    The design goals of this code are:
       - Very fast algorithm
       - Low memory requirement
@@ -43,7 +43,7 @@
 
 /********* WARNING: MENTAL SANITY ENDS HERE *************/
 
-/* If the resampler is defined outside of Speex, we change the symbol names so that 
+/* If the resampler is defined outside of Speex, we change the symbol names so that
    there won't be any clash if linking with Speex later on. */
 
 /* #define RANDOM_PREFIX your software name here */
@@ -53,7 +53,7 @@
 
 #define CAT_PREFIX2(a,b) a ## b
 #define CAT_PREFIX(a,b) CAT_PREFIX2(a, b)
-      
+
 #define speex_resampler_init CAT_PREFIX(RANDOM_PREFIX,_resampler_init)
 #define speex_resampler_init_frac CAT_PREFIX(RANDOM_PREFIX,_resampler_init_frac)
 #define speex_resampler_destroy CAT_PREFIX(RANDOM_PREFIX,_resampler_destroy)
@@ -81,7 +81,9 @@
 #define spx_int32_t int
 #define spx_uint16_t unsigned short
 #define spx_uint32_t unsigned int
-      
+
+#define speex_assert(cond)
+
 #else /* OUTSIDE_SPEEX */
 
 #include "speexdsp_types.h"
@@ -104,7 +106,8 @@ enum {
    RESAMPLER_ERR_BAD_STATE       = 2,
    RESAMPLER_ERR_INVALID_ARG     = 3,
    RESAMPLER_ERR_PTR_OVERLAP     = 4,
-   
+   RESAMPLER_ERR_OVERFLOW        = 5,
+
    RESAMPLER_ERR_MAX_ERROR
 };
 
@@ -120,14 +123,14 @@ typedef struct SpeexResamplerState_ SpeexResamplerState;
  * @return Newly created resampler state
  * @retval NULL Error: not enough memory
  */
-SpeexResamplerState *speex_resampler_init(spx_uint32_t nb_channels, 
-                                          spx_uint32_t in_rate, 
-                                          spx_uint32_t out_rate, 
+SpeexResamplerState *speex_resampler_init(spx_uint32_t nb_channels,
+                                          spx_uint32_t in_rate,
+                                          spx_uint32_t out_rate,
                                           int quality,
                                           int *err);
 
-/** Create a new resampler with fractional input/output rates. The sampling 
- * rate ratio is an arbitrary rational number with both the numerator and 
+/** Create a new resampler with fractional input/output rates. The sampling
+ * rate ratio is an arbitrary rational number with both the numerator and
  * denominator being 32-bit integers.
  * @param nb_channels Number of channels to be processed
  * @param ratio_num Numerator of the sampling rate ratio
@@ -139,11 +142,11 @@ SpeexResamplerState *speex_resampler_init(spx_uint32_t nb_channels,
  * @return Newly created resampler state
  * @retval NULL Error: not enough memory
  */
-SpeexResamplerState *speex_resampler_init_frac(spx_uint32_t nb_channels, 
-                                               spx_uint32_t ratio_num, 
-                                               spx_uint32_t ratio_den, 
-                                               spx_uint32_t in_rate, 
-                                               spx_uint32_t out_rate, 
+SpeexResamplerState *speex_resampler_init_frac(spx_uint32_t nb_channels,
+                                               spx_uint32_t ratio_num,
+                                               spx_uint32_t ratio_den,
+                                               spx_uint32_t in_rate,
+                                               spx_uint32_t out_rate,
                                                int quality,
                                                int *err);
 
@@ -154,24 +157,24 @@ void speex_resampler_destroy(SpeexResamplerState *st);
 
 /** Resample a float array. The input and output buffers must *not* overlap.
  * @param st Resampler state
- * @param channel_index Index of the channel to process for the multi-channel 
+ * @param channel_index Index of the channel to process for the multi-channel
  * base (0 otherwise)
  * @param in Input buffer
- * @param in_len Number of input samples in the input buffer. Returns the 
+ * @param in_len Number of input samples in the input buffer. Returns the
  * number of samples processed
  * @param out Output buffer
  * @param out_len Size of the output buffer. Returns the number of samples written
  */
-int speex_resampler_process_float(SpeexResamplerState *st, 
-                                   spx_uint32_t channel_index, 
-                                   const float *in, 
-                                   spx_uint32_t *in_len, 
-                                   float *out, 
+int speex_resampler_process_float(SpeexResamplerState *st,
+                                   spx_uint32_t channel_index,
+                                   const float *in,
+                                   spx_uint32_t *in_len,
+                                   float *out,
                                    spx_uint32_t *out_len);
 
 /** Resample an int array. The input and output buffers must *not* overlap.
  * @param st Resampler state
- * @param channel_index Index of the channel to process for the multi-channel 
+ * @param channel_index Index of the channel to process for the multi-channel
  * base (0 otherwise)
  * @param in Input buffer
  * @param in_len Number of input samples in the input buffer. Returns the number
@@ -179,11 +182,11 @@ int speex_resampler_process_float(SpeexResamplerState *st,
  * @param out Output buffer
  * @param out_len Size of the output buffer. Returns the number of samples written
  */
-int speex_resampler_process_int(SpeexResamplerState *st, 
-                                 spx_uint32_t channel_index, 
-                                 const spx_int16_t *in, 
-                                 spx_uint32_t *in_len, 
-                                 spx_int16_t *out, 
+int speex_resampler_process_int(SpeexResamplerState *st,
+                                 spx_uint32_t channel_index,
+                                 const spx_int16_t *in,
+                                 spx_uint32_t *in_len,
+                                 spx_int16_t *out,
                                  spx_uint32_t *out_len);
 
 /** Resample an interleaved float array. The input and output buffers must *not* overlap.
@@ -195,10 +198,10 @@ int speex_resampler_process_int(SpeexResamplerState *st,
  * @param out_len Size of the output buffer. Returns the number of samples written.
  * This is all per-channel.
  */
-int speex_resampler_process_interleaved_float(SpeexResamplerState *st, 
-                                               const float *in, 
-                                               spx_uint32_t *in_len, 
-                                               float *out, 
+int speex_resampler_process_interleaved_float(SpeexResamplerState *st,
+                                               const float *in,
+                                               spx_uint32_t *in_len,
+                                               float *out,
                                                spx_uint32_t *out_len);
 
 /** Resample an interleaved int array. The input and output buffers must *not* overlap.
@@ -210,10 +213,10 @@ int speex_resampler_process_interleaved_float(SpeexResamplerState *st,
  * @param out_len Size of the output buffer. Returns the number of samples written.
  * This is all per-channel.
  */
-int speex_resampler_process_interleaved_int(SpeexResamplerState *st, 
-                                             const spx_int16_t *in, 
-                                             spx_uint32_t *in_len, 
-                                             spx_int16_t *out, 
+int speex_resampler_process_interleaved_int(SpeexResamplerState *st,
+                                             const spx_int16_t *in,
+                                             spx_uint32_t *in_len,
+                                             spx_int16_t *out,
                                              spx_uint32_t *out_len);
 
 /** Set (change) the input/output sampling rates (integer value).
@@ -221,8 +224,8 @@ int speex_resampler_process_interleaved_int(SpeexResamplerState *st,
  * @param in_rate Input sampling rate (integer number of Hz).
  * @param out_rate Output sampling rate (integer number of Hz).
  */
-int speex_resampler_set_rate(SpeexResamplerState *st, 
-                              spx_uint32_t in_rate, 
+int speex_resampler_set_rate(SpeexResamplerState *st,
+                              spx_uint32_t in_rate,
                               spx_uint32_t out_rate);
 
 /** Get the current input/output sampling rates (integer value).
@@ -230,11 +233,11 @@ int speex_resampler_set_rate(SpeexResamplerState *st,
  * @param in_rate Input sampling rate (integer number of Hz) copied.
  * @param out_rate Output sampling rate (integer number of Hz) copied.
  */
-void speex_resampler_get_rate(SpeexResamplerState *st, 
-                              spx_uint32_t *in_rate, 
+void speex_resampler_get_rate(SpeexResamplerState *st,
+                              spx_uint32_t *in_rate,
                               spx_uint32_t *out_rate);
 
-/** Set (change) the input/output sampling rates and resampling ratio 
+/** Set (change) the input/output sampling rates and resampling ratio
  * (fractional values in Hz supported).
  * @param st Resampler state
  * @param ratio_num Numerator of the sampling rate ratio
@@ -242,10 +245,10 @@ void speex_resampler_get_rate(SpeexResamplerState *st,
  * @param in_rate Input sampling rate rounded to the nearest integer (in Hz).
  * @param out_rate Output sampling rate rounded to the nearest integer (in Hz).
  */
-int speex_resampler_set_rate_frac(SpeexResamplerState *st, 
-                                   spx_uint32_t ratio_num, 
-                                   spx_uint32_t ratio_den, 
-                                   spx_uint32_t in_rate, 
+int speex_resampler_set_rate_frac(SpeexResamplerState *st,
+                                   spx_uint32_t ratio_num,
+                                   spx_uint32_t ratio_den,
+                                   spx_uint32_t in_rate,
                                    spx_uint32_t out_rate);
 
 /** Get the current resampling ratio. This will be reduced to the least
@@ -254,52 +257,52 @@ int speex_resampler_set_rate_frac(SpeexResamplerState *st,
  * @param ratio_num Numerator of the sampling rate ratio copied
  * @param ratio_den Denominator of the sampling rate ratio copied
  */
-void speex_resampler_get_ratio(SpeexResamplerState *st, 
-                               spx_uint32_t *ratio_num, 
+void speex_resampler_get_ratio(SpeexResamplerState *st,
+                               spx_uint32_t *ratio_num,
                                spx_uint32_t *ratio_den);
 
 /** Set (change) the conversion quality.
  * @param st Resampler state
- * @param quality Resampling quality between 0 and 10, where 0 has poor 
+ * @param quality Resampling quality between 0 and 10, where 0 has poor
  * quality and 10 has very high quality.
  */
-int speex_resampler_set_quality(SpeexResamplerState *st, 
+int speex_resampler_set_quality(SpeexResamplerState *st,
                                  int quality);
 
 /** Get the conversion quality.
  * @param st Resampler state
- * @param quality Resampling quality between 0 and 10, where 0 has poor 
+ * @param quality Resampling quality between 0 and 10, where 0 has poor
  * quality and 10 has very high quality.
  */
-void speex_resampler_get_quality(SpeexResamplerState *st, 
+void speex_resampler_get_quality(SpeexResamplerState *st,
                                  int *quality);
 
 /** Set (change) the input stride.
  * @param st Resampler state
  * @param stride Input stride
  */
-void speex_resampler_set_input_stride(SpeexResamplerState *st, 
+void speex_resampler_set_input_stride(SpeexResamplerState *st,
                                       spx_uint32_t stride);
 
 /** Get the input stride.
  * @param st Resampler state
  * @param stride Input stride copied
  */
-void speex_resampler_get_input_stride(SpeexResamplerState *st, 
+void speex_resampler_get_input_stride(SpeexResamplerState *st,
                                       spx_uint32_t *stride);
 
 /** Set (change) the output stride.
  * @param st Resampler state
  * @param stride Output stride
  */
-void speex_resampler_set_output_stride(SpeexResamplerState *st, 
+void speex_resampler_set_output_stride(SpeexResamplerState *st,
                                       spx_uint32_t stride);
 
 /** Get the output stride.
  * @param st Resampler state copied
  * @param stride Output stride
  */
-void speex_resampler_get_output_stride(SpeexResamplerState *st, 
+void speex_resampler_get_output_stride(SpeexResamplerState *st,
                                       spx_uint32_t *stride);
 
 /** Get the latency introduced by the resampler measured in input samples.
@@ -312,8 +315,8 @@ int speex_resampler_get_input_latency(SpeexResamplerState *st);
  */
 int speex_resampler_get_output_latency(SpeexResamplerState *st);
 
-/** Make sure that the first samples to go out of the resamplers don't have 
- * leading zeros. This is only useful before starting to use a newly created 
+/** Make sure that the first samples to go out of the resamplers don't have
+ * leading zeros. This is only useful before starting to use a newly created
  * resampler. It is recommended to use that when resampling an audio file, as
  * it will generate a file with the same length. For real-time processing,
  * it is probably easier not to use this call (so that the output duration
diff --git a/vendor/libspeex/speex/speex_stereo.h b/vendor/libspeex/speex/speex_stereo.h
index 5844f5a102..12af2bbf6e 100644
--- a/vendor/libspeex/speex/speex_stereo.h
+++ b/vendor/libspeex/speex/speex_stereo.h
@@ -61,7 +61,7 @@ typedef struct SpeexStereoState {
 #define SPEEX_STEREO_STATE_INIT {1,.5,1,1,0,0}
 
 /** Initialise/create a stereo stereo state */
-SpeexStereoState *speex_stereo_state_init();
+SpeexStereoState *speex_stereo_state_init(void);
 
 /** Reset/re-initialise an already allocated stereo state */
 void speex_stereo_state_reset(SpeexStereoState *stereo);
diff --git a/vendor/libspeex/speex/speexdsp_config_types.h b/vendor/libspeex/speex/speexdsp_config_types.h
index f864522910..d77d0ca8f9 100644
--- a/vendor/libspeex/speex/speexdsp_config_types.h
+++ b/vendor/libspeex/speex/speexdsp_config_types.h
@@ -9,4 +9,3 @@ typedef int32_t spx_int32_t;
 typedef uint32_t spx_uint32_t;
 
 #endif
-
diff --git a/vendor/libspeex/speex/speexdsp_types.h b/vendor/libspeex/speex/speexdsp_types.h
index 334d6745ac..4b4a76a474 100644
--- a/vendor/libspeex/speex/speexdsp_types.h
+++ b/vendor/libspeex/speex/speexdsp_types.h
@@ -22,7 +22,7 @@
 #ifndef _SPEEX_TYPES_H
 #define _SPEEX_TYPES_H
 
-#if defined(_WIN32) 
+#if defined(_WIN32)
 
 #  if defined(__CYGWIN__)
 #    include <_G_config.h>
diff --git a/vendor/lunasvg/premake5.lua b/vendor/lunasvg/premake5.lua
index cb6fa4ea87..3c7ce68612 100644
--- a/vendor/lunasvg/premake5.lua
+++ b/vendor/lunasvg/premake5.lua
@@ -35,3 +35,8 @@ project "lunasvg"
 		"source",
 		"include"
 	}
+
+	filter "architecture:not x86"
+		flags { "ExcludeFromBuild" }
+	filter "system:not windows"
+		flags { "ExcludeFromBuild" }
diff --git a/vendor/mbedtls/3rdparty/everest/README.md b/vendor/mbedtls/3rdparty/everest/README.md
deleted file mode 100644
index bcf12c0c05..0000000000
--- a/vendor/mbedtls/3rdparty/everest/README.md
+++ /dev/null
@@ -1,5 +0,0 @@
-The files in this directory stem from [Project Everest](https://project-everest.github.io/) and are distributed under the Apache 2.0 license.
-
-This is a formally verified implementation of Curve25519-based handshakes. The C code is automatically derived from the (verified) [original implementation](https://github.com/project-everest/hacl-star/tree/master/code/curve25519) in the [F* language](https://github.com/fstarlang/fstar) by [KreMLin](https://github.com/fstarlang/kremlin). In addition to the improved safety and security of the implementation, it is also significantly faster than the default implementation of Curve25519 in mbedTLS.
-
-The caveat is that not all platforms are supported, although the version in `everest/library/legacy` should work on most systems. The main issue is that some platforms do not provide a 128-bit integer type and KreMLin therefore has to use additional (also verified) code to simulate them, resulting in less of a performance gain overall. Explicitly supported platforms are currently `x86` and `x86_64` using gcc or clang, and Visual C (2010 and later).
diff --git a/vendor/mbedtls/3rdparty/everest/include/everest/vs2010/Hacl_Curve25519.h b/vendor/mbedtls/3rdparty/everest/include/everest/vs2013/Hacl_Curve25519.h
similarity index 100%
rename from vendor/mbedtls/3rdparty/everest/include/everest/vs2010/Hacl_Curve25519.h
rename to vendor/mbedtls/3rdparty/everest/include/everest/vs2013/Hacl_Curve25519.h
diff --git a/vendor/mbedtls/3rdparty/everest/include/everest/vs2010/inttypes.h b/vendor/mbedtls/3rdparty/everest/include/everest/vs2013/inttypes.h
similarity index 100%
rename from vendor/mbedtls/3rdparty/everest/include/everest/vs2010/inttypes.h
rename to vendor/mbedtls/3rdparty/everest/include/everest/vs2013/inttypes.h
diff --git a/vendor/mbedtls/3rdparty/everest/include/everest/vs2010/stdbool.h b/vendor/mbedtls/3rdparty/everest/include/everest/vs2013/stdbool.h
similarity index 100%
rename from vendor/mbedtls/3rdparty/everest/include/everest/vs2010/stdbool.h
rename to vendor/mbedtls/3rdparty/everest/include/everest/vs2013/stdbool.h
diff --git a/vendor/mbedtls/3rdparty/everest/library/Hacl_Curve25519_joined.c b/vendor/mbedtls/3rdparty/everest/library/Hacl_Curve25519_joined.c
index b7d0c929c9..a778160fff 100644
--- a/vendor/mbedtls/3rdparty/everest/library/Hacl_Curve25519_joined.c
+++ b/vendor/mbedtls/3rdparty/everest/library/Hacl_Curve25519_joined.c
@@ -18,6 +18,15 @@
  *
  *  This file is part of Mbed TLS (https://tls.mbed.org)
  */
+#ifndef _BSD_SOURCE
+/* Required to get htole64() from gcc/glibc's endian.h (older systems)
+ * when we compile with -std=c99 */
+#define _BSD_SOURCE
+#endif
+#ifndef _DEFAULT_SOURCE
+/* (modern version of _BSD_SOURCE) */
+#define _DEFAULT_SOURCE
+#endif
 
 #include "common.h"
 
diff --git a/vendor/mbedtls/3rdparty/p256-m/p256-m/p256-m.c b/vendor/mbedtls/3rdparty/p256-m/p256-m/p256-m.c
new file mode 100644
index 0000000000..42c35b5bf5
--- /dev/null
+++ b/vendor/mbedtls/3rdparty/p256-m/p256-m/p256-m.c
@@ -0,0 +1,1514 @@
+/*
+ * Implementation of curve P-256 (ECDH and ECDSA)
+ *
+ * Copyright The Mbed TLS Contributors
+ * Author: Manuel Pégourié-Gonnard.
+ * SPDX-License-Identifier: Apache-2.0 OR GPL-2.0-or-later
+ */
+
+#include "p256-m.h"
+#include "mbedtls/platform_util.h"
+#include "psa/crypto.h"
+#include 
+#include 
+#include 
+
+#if defined (MBEDTLS_PSA_P256M_DRIVER_ENABLED)
+
+/*
+ * Zeroize memory - this should not be optimized away
+ */
+#define zeroize mbedtls_platform_zeroize
+
+/*
+ * Helpers to test constant-time behaviour with valgrind or MemSan.
+ *
+ * CT_POISON() is used for secret data. It marks the memory area as
+ * uninitialised, so that any branch or pointer dereference that depends on it
+ * (even indirectly) triggers a warning.
+ * CT_UNPOISON() is used for public data; it marks the area as initialised.
+ *
+ * These are macros in order to avoid interfering with origin tracking.
+ */
+#if defined(CT_MEMSAN)
+
+#include 
+#define CT_POISON   __msan_allocated_memory
+// void __msan_allocated_memory(const volatile void* data, size_t size);
+#define CT_UNPOISON __msan_unpoison
+// void __msan_unpoison(const volatile void *a, size_t size);
+
+#elif defined(CT_VALGRIND)
+
+#include 
+#define CT_POISON   VALGRIND_MAKE_MEM_UNDEFINED
+// VALGRIND_MAKE_MEM_UNDEFINED(_qzz_addr,_qzz_len)
+#define CT_UNPOISON VALGRIND_MAKE_MEM_DEFINED
+// VALGRIND_MAKE_MEM_DEFINED(_qzz_addr,_qzz_len)
+
+#else
+#define CT_POISON(p, sz)
+#define CT_UNPOISON(p, sz)
+#endif
+
+/**********************************************************************
+ *
+ * Operations on fixed-width unsigned integers
+ *
+ * Represented using 32-bit limbs, least significant limb first.
+ * That is: x = x[0] + 2^32 x[1] + ... + 2^224 x[7] for 256-bit.
+ *
+ **********************************************************************/
+
+/*
+ * 256-bit set to 32-bit value
+ *
+ * in: x in [0, 2^32)
+ * out: z = x
+ */
+static void u256_set32(uint32_t z[8], uint32_t x)
+{
+    z[0] = x;
+    for (unsigned i = 1; i < 8; i++) {
+        z[i] = 0;
+    }
+}
+
+/*
+ * 256-bit addition
+ *
+ * in: x, y in [0, 2^256)
+ * out: z = (x + y) mod 2^256
+ *      c = (x + y) div 2^256
+ * That is, z + c * 2^256 = x + y
+ *
+ * Note: as a memory area, z must be either equal to x or y, or not overlap.
+ */
+static uint32_t u256_add(uint32_t z[8],
+                         const uint32_t x[8], const uint32_t y[8])
+{
+    uint32_t carry = 0;
+
+    for (unsigned i = 0; i < 8; i++) {
+        uint64_t sum = (uint64_t) carry + x[i] + y[i];
+        z[i] = (uint32_t) sum;
+        carry = (uint32_t) (sum >> 32);
+    }
+
+    return carry;
+}
+
+/*
+ * 256-bit subtraction
+ *
+ * in: x, y in [0, 2^256)
+ * out: z = (x - y) mod 2^256
+ *      c = 0 if x >=y, 1 otherwise
+ * That is, z = c * 2^256 + x - y
+ *
+ * Note: as a memory area, z must be either equal to x or y, or not overlap.
+ */
+static uint32_t u256_sub(uint32_t z[8],
+                         const uint32_t x[8], const uint32_t y[8])
+{
+    uint32_t carry = 0;
+
+    for (unsigned i = 0; i < 8; i++) {
+        uint64_t diff = (uint64_t) x[i] - y[i] - carry;
+        z[i] = (uint32_t) diff;
+        carry = -(uint32_t) (diff >> 32);
+    }
+
+    return carry;
+}
+
+/*
+ * 256-bit conditional assignment
+ *
+ * in: x in [0, 2^256)
+ *     c in [0, 1]
+ * out: z = x if c == 1, z unchanged otherwise
+ *
+ * Note: as a memory area, z must be either equal to x, or not overlap.
+ */
+static void u256_cmov(uint32_t z[8], const uint32_t x[8], uint32_t c)
+{
+    const uint32_t x_mask = -c;
+    for (unsigned i = 0; i < 8; i++) {
+        z[i] = (z[i] & ~x_mask) | (x[i] & x_mask);
+    }
+}
+
+/*
+ * 256-bit compare for equality
+ *
+ * in: x in [0, 2^256)
+ *     y in [0, 2^256)
+ * out: 0 if x == y, unspecified non-zero otherwise
+ */
+static uint32_t u256_diff(const uint32_t x[8], const uint32_t y[8])
+{
+    uint32_t diff = 0;
+    for (unsigned i = 0; i < 8; i++) {
+        diff |= x[i] ^ y[i];
+    }
+    return diff;
+}
+
+/*
+ * 256-bit compare to zero
+ *
+ * in: x in [0, 2^256)
+ * out: 0 if x == 0, unspecified non-zero otherwise
+ */
+static uint32_t u256_diff0(const uint32_t x[8])
+{
+    uint32_t diff = 0;
+    for (unsigned i = 0; i < 8; i++) {
+        diff |= x[i];
+    }
+    return diff;
+}
+
+/*
+ * 32 x 32 -> 64-bit multiply-and-accumulate
+ *
+ * in: x, y, z, t in [0, 2^32)
+ * out: x * y + z + t in [0, 2^64)
+ *
+ * Note: this computation cannot overflow.
+ *
+ * Note: this function has two pure-C implementations (depending on whether
+ * MUL64_IS_CONSTANT_TIME), and possibly optimised asm implementations.
+ * Start with the potential asm definitions, and use the C definition only if
+ * we no have no asm for the current toolchain & CPU.
+ */
+static uint64_t u32_muladd64(uint32_t x, uint32_t y, uint32_t z, uint32_t t);
+
+/* This macro is used to mark whether an asm implentation is found */
+#undef MULADD64_ASM
+/* This macro is used to mark whether the implementation has a small
+ * code size (ie, it can be inlined even in an unrolled loop) */
+#undef MULADD64_SMALL
+
+/*
+ * Currently assembly optimisations are only supported with GCC/Clang for
+ * Arm's Cortex-A and Cortex-M lines of CPUs, which start with the v6-M and
+ * v7-M architectures. __ARM_ARCH_PROFILE is not defined for v6 and earlier.
+ * Thumb and 32-bit assembly is supported; aarch64 is not supported.
+ */
+#if defined(__GNUC__) &&\
+    defined(__ARM_ARCH) && __ARM_ARCH >= 6 && defined(__ARM_ARCH_PROFILE) && \
+    ( __ARM_ARCH_PROFILE == 77 || __ARM_ARCH_PROFILE == 65 ) /* 'M' or 'A' */ && \
+    !defined(__aarch64__)
+
+/*
+ * This set of CPUs is conveniently partitioned as follows:
+ *
+ * 1. Cores that have the DSP extension, which includes a 1-cycle UMAAL
+ *    instruction: M4, M7, M33, all A-class cores.
+ * 2. Cores that don't have the DSP extension, and also lack a constant-time
+ *    64-bit multiplication instruction:
+ *    - M0, M0+, M23: 32-bit multiplication only;
+ *    - M3: 64-bit multiplication is not constant-time.
+ */
+#if defined(__ARM_FEATURE_DSP)
+
+static uint64_t u32_muladd64(uint32_t x, uint32_t y, uint32_t z, uint32_t t)
+{
+    __asm__(
+        /* UMAAL , , ,  */
+        "umaal   %[z], %[t], %[x], %[y]"
+        : [z] "+l" (z), [t] "+l" (t)
+        : [x] "l" (x), [y] "l" (y)
+    );
+    return ((uint64_t) t << 32) | z;
+}
+#define MULADD64_ASM
+#define MULADD64_SMALL
+
+#else /* __ARM_FEATURE_DSP */
+
+/*
+ * This implementation only uses 16x16->32 bit multiplication.
+ *
+ * It decomposes the multiplicands as:
+ *      x = xh:xl = 2^16 * xh + xl
+ *      y = yh:yl = 2^16 * yh + yl
+ * and computes their product as:
+ *      x*y = xl*yl + 2**16 (xh*yl + yl*yh) + 2**32 xh*yh
+ * then adds z and t to the result.
+ */
+static uint64_t u32_muladd64(uint32_t x, uint32_t y, uint32_t z, uint32_t t)
+{
+    /* First compute x*y, using 3 temporary registers */
+    uint32_t tmp1, tmp2, tmp3;
+    __asm__(
+        ".syntax unified\n\t"
+        /* start by splitting the inputs into halves */
+        "lsrs    %[u], %[x], #16\n\t"
+        "lsrs    %[v], %[y], #16\n\t"
+        "uxth    %[x], %[x]\n\t"
+        "uxth    %[y], %[y]\n\t"
+        /* now we have %[x], %[y], %[u], %[v] = xl, yl, xh, yh */
+        /* let's compute the 4 products we can form with those */
+        "movs    %[w], %[v]\n\t"
+        "muls    %[w], %[u]\n\t"
+        "muls    %[v], %[x]\n\t"
+        "muls    %[x], %[y]\n\t"
+        "muls    %[y], %[u]\n\t"
+        /* now we have %[x], %[y], %[v], %[w] = xl*yl, xh*yl, xl*yh, xh*yh */
+        /* let's split and add the first middle product */
+        "lsls    %[u], %[y], #16\n\t"
+        "lsrs    %[y], %[y], #16\n\t"
+        "adds    %[x], %[u]\n\t"
+        "adcs    %[y], %[w]\n\t"
+        /* let's finish with the second middle product */
+        "lsls    %[u], %[v], #16\n\t"
+        "lsrs    %[v], %[v], #16\n\t"
+        "adds    %[x], %[u]\n\t"
+        "adcs    %[y], %[v]\n\t"
+        : [x] "+l" (x), [y] "+l" (y),
+          [u] "=&l" (tmp1), [v] "=&l" (tmp2), [w] "=&l" (tmp3)
+        : /* no read-only inputs */
+        : "cc"
+    );
+    (void) tmp1;
+    (void) tmp2;
+    (void) tmp3;
+
+    /* Add z and t, using one temporary register */
+    __asm__(
+        ".syntax unified\n\t"
+        "movs    %[u], #0\n\t"
+        "adds    %[x], %[z]\n\t"
+        "adcs    %[y], %[u]\n\t"
+        "adds    %[x], %[t]\n\t"
+        "adcs    %[y], %[u]\n\t"
+        : [x] "+l" (x), [y] "+l" (y), [u] "=&l" (tmp1)
+        : [z] "l" (z), [t] "l" (t)
+        : "cc"
+    );
+    (void) tmp1;
+
+    return ((uint64_t) y << 32) | x;
+}
+#define MULADD64_ASM
+
+#endif /* __ARM_FEATURE_DSP */
+
+#endif /* GCC/Clang with Cortex-M/A CPU */
+
+#if !defined(MULADD64_ASM)
+#if defined(MUL64_IS_CONSTANT_TIME)
+static uint64_t u32_muladd64(uint32_t x, uint32_t y, uint32_t z, uint32_t t)
+{
+    return (uint64_t) x * y + z + t;
+}
+#define MULADD64_SMALL
+#else
+static uint64_t u32_muladd64(uint32_t x, uint32_t y, uint32_t z, uint32_t t)
+{
+    /* x = xl + 2**16 xh, y = yl + 2**16 yh */
+    const uint16_t xl = (uint16_t) x;
+    const uint16_t yl = (uint16_t) y;
+    const uint16_t xh = x >> 16;
+    const uint16_t yh = y >> 16;
+
+    /* x*y = xl*yl + 2**16 (xh*yl + yl*yh) + 2**32 xh*yh
+     *     = lo    + 2**16 (m1    + m2   ) + 2**32 hi    */
+    const uint32_t lo = (uint32_t) xl * yl;
+    const uint32_t m1 = (uint32_t) xh * yl;
+    const uint32_t m2 = (uint32_t) xl * yh;
+    const uint32_t hi = (uint32_t) xh * yh;
+
+    uint64_t acc = lo + ((uint64_t) (hi + (m1 >> 16) + (m2 >> 16)) << 32);
+    acc += m1 << 16;
+    acc += m2 << 16;
+    acc += z;
+    acc += t;
+
+    return acc;
+}
+#endif /* MUL64_IS_CONSTANT_TIME */
+#endif /* MULADD64_ASM */
+
+/*
+ * 288 + 32 x 256 -> 288-bit multiply and add
+ *
+ * in: x in [0, 2^32)
+ *     y in [0, 2^256)
+ *     z in [0, 2^288)
+ * out: z_out = z_in + x * y mod 2^288
+ *      c     = z_in + x * y div 2^288
+ * That is, z_out + c * 2^288 = z_in + x * y
+ *
+ * Note: as a memory area, z must be either equal to y, or not overlap.
+ *
+ * This is a helper for Montgomery multiplication.
+ */
+static uint32_t u288_muladd(uint32_t z[9], uint32_t x, const uint32_t y[8])
+{
+    uint32_t carry = 0;
+
+#define U288_MULADD_STEP(i) \
+    do { \
+        uint64_t prod = u32_muladd64(x, y[i], z[i], carry); \
+        z[i] = (uint32_t) prod; \
+        carry = (uint32_t) (prod >> 32); \
+    } while( 0 )
+
+#if defined(MULADD64_SMALL)
+    U288_MULADD_STEP(0);
+    U288_MULADD_STEP(1);
+    U288_MULADD_STEP(2);
+    U288_MULADD_STEP(3);
+    U288_MULADD_STEP(4);
+    U288_MULADD_STEP(5);
+    U288_MULADD_STEP(6);
+    U288_MULADD_STEP(7);
+#else
+    for (unsigned i = 0; i < 8; i++) {
+        U288_MULADD_STEP(i);
+    }
+#endif
+
+    uint64_t sum = (uint64_t) z[8] + carry;
+    z[8] = (uint32_t) sum;
+    carry = (uint32_t) (sum >> 32);
+
+    return carry;
+}
+
+/*
+ * 288-bit in-place right shift by 32 bits
+ *
+ * in: z in [0, 2^288)
+ *     c in [0, 2^32)
+ * out: z_out = z_in div 2^32 + c * 2^256
+ *            = (z_in + c * 2^288) div 2^32
+ *
+ * This is a helper for Montgomery multiplication.
+ */
+static void u288_rshift32(uint32_t z[9], uint32_t c)
+{
+    for (unsigned i = 0; i < 8; i++) {
+        z[i] = z[i + 1];
+    }
+    z[8] = c;
+}
+
+/*
+ * 256-bit import from big-endian bytes
+ *
+ * in: p = p0, ..., p31
+ * out: z = p0 * 2^248 + p1 * 2^240 + ... + p30 * 2^8 + p31
+ */
+static void u256_from_bytes(uint32_t z[8], const uint8_t p[32])
+{
+    for (unsigned i = 0; i < 8; i++) {
+        unsigned j = 4 * (7 - i);
+        z[i] = ((uint32_t) p[j + 0] << 24) |
+               ((uint32_t) p[j + 1] << 16) |
+               ((uint32_t) p[j + 2] <<  8) |
+               ((uint32_t) p[j + 3] <<  0);
+    }
+}
+
+/*
+ * 256-bit export to big-endian bytes
+ *
+ * in: z in [0, 2^256)
+ * out: p = p0, ..., p31 such that
+ *      z = p0 * 2^248 + p1 * 2^240 + ... + p30 * 2^8 + p31
+ */
+static void u256_to_bytes(uint8_t p[32], const uint32_t z[8])
+{
+    for (unsigned i = 0; i < 8; i++) {
+        unsigned j = 4 * (7 - i);
+        p[j + 0] = (uint8_t) (z[i] >> 24);
+        p[j + 1] = (uint8_t) (z[i] >> 16);
+        p[j + 2] = (uint8_t) (z[i] >>  8);
+        p[j + 3] = (uint8_t) (z[i] >>  0);
+    }
+}
+
+/**********************************************************************
+ *
+ * Operations modulo a 256-bit prime m
+ *
+ * These are done in the Montgomery domain, that is x is represented by
+ *  x * 2^256 mod m
+ * Numbers need to be converted to that domain before computations,
+ * and back from it afterwards.
+ *
+ * Inversion is computed using Fermat's little theorem.
+ *
+ * Assumptions on m:
+ * - Montgomery operations require that m is odd.
+ * - Fermat's little theorem require it to be a prime.
+ * - m256_inv() further requires that m % 2^32 >= 2.
+ * - m256_inv() also assumes that the value of m is not a secret.
+ *
+ * In practice operations are done modulo the curve's p and n,
+ * both of which satisfy those assumptions.
+ *
+ **********************************************************************/
+
+/*
+ * Data associated to a modulus for Montgomery operations.
+ *
+ * m in [0, 2^256) - the modulus itself, must be odd
+ * R2 = 2^512 mod m
+ * ni = -m^-1 mod 2^32
+ */
+typedef struct {
+    uint32_t m[8];
+    uint32_t R2[8];
+    uint32_t ni;
+}
+m256_mod;
+
+/*
+ * Data for Montgomery operations modulo the curve's p
+ */
+static const m256_mod p256_p = {
+    {   /* the curve's p */
+        0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0x00000000,
+        0x00000000, 0x00000000, 0x00000001, 0xFFFFFFFF,
+    },
+    {   /* 2^512 mod p */
+        0x00000003, 0x00000000, 0xffffffff, 0xfffffffb,
+        0xfffffffe, 0xffffffff, 0xfffffffd, 0x00000004,
+    },
+    0x00000001, /* -p^-1 mod 2^32 */
+};
+
+/*
+ * Data for Montgomery operations modulo the curve's n
+ */
+static const m256_mod p256_n = {
+    {   /* the curve's n */
+        0xFC632551, 0xF3B9CAC2, 0xA7179E84, 0xBCE6FAAD,
+        0xFFFFFFFF, 0xFFFFFFFF, 0x00000000, 0xFFFFFFFF,
+    },
+    {   /* 2^512 mod n */
+        0xbe79eea2, 0x83244c95, 0x49bd6fa6, 0x4699799c,
+        0x2b6bec59, 0x2845b239, 0xf3d95620, 0x66e12d94,
+    },
+    0xee00bc4f, /* -n^-1 mod 2^32 */
+};
+
+/*
+ * Modular addition
+ *
+ * in: x, y in [0, m)
+ *     mod must point to a valid m256_mod structure
+ * out: z = (x + y) mod m, in [0, m)
+ *
+ * Note: as a memory area, z must be either equal to x or y, or not overlap.
+ */
+static void m256_add(uint32_t z[8],
+                     const uint32_t x[8], const uint32_t y[8],
+                     const m256_mod *mod)
+{
+    uint32_t r[8];
+    uint32_t carry_add = u256_add(z, x, y);
+    uint32_t carry_sub = u256_sub(r, z, mod->m);
+    /* Need to subract m if:
+     *      x+y >= 2^256 > m (that is, carry_add == 1)
+     *   OR z >= m (that is, carry_sub == 0) */
+    uint32_t use_sub = carry_add | (1 - carry_sub);
+    u256_cmov(z, r, use_sub);
+}
+
+/*
+ * Modular addition mod p
+ *
+ * in: x, y in [0, p)
+ * out: z = (x + y) mod p, in [0, p)
+ *
+ * Note: as a memory area, z must be either equal to x or y, or not overlap.
+ */
+static void m256_add_p(uint32_t z[8],
+                       const uint32_t x[8], const uint32_t y[8])
+{
+    m256_add(z, x, y, &p256_p);
+}
+
+/*
+ * Modular subtraction
+ *
+ * in: x, y in [0, m)
+ *     mod must point to a valid m256_mod structure
+ * out: z = (x - y) mod m, in [0, m)
+ *
+ * Note: as a memory area, z must be either equal to x or y, or not overlap.
+ */
+static void m256_sub(uint32_t z[8],
+                     const uint32_t x[8], const uint32_t y[8],
+                     const m256_mod *mod)
+{
+    uint32_t r[8];
+    uint32_t carry = u256_sub(z, x, y);
+    (void) u256_add(r, z, mod->m);
+    /* Need to add m if and only if x < y, that is carry == 1.
+     * In that case z is in [2^256 - m + 1, 2^256 - 1], so the
+     * addition will have a carry as well, which cancels out. */
+    u256_cmov(z, r, carry);
+}
+
+/*
+ * Modular subtraction mod p
+ *
+ * in: x, y in [0, p)
+ * out: z = (x + y) mod p, in [0, p)
+ *
+ * Note: as a memory area, z must be either equal to x or y, or not overlap.
+ */
+static void m256_sub_p(uint32_t z[8],
+                       const uint32_t x[8], const uint32_t y[8])
+{
+    m256_sub(z, x, y, &p256_p);
+}
+
+/*
+ * Montgomery modular multiplication
+ *
+ * in: x, y in [0, m)
+ *     mod must point to a valid m256_mod structure
+ * out: z = (x * y) / 2^256 mod m, in [0, m)
+ *
+ * Note: as a memory area, z may overlap with x or y.
+ */
+static void m256_mul(uint32_t z[8],
+                     const uint32_t x[8], const uint32_t y[8],
+                     const m256_mod *mod)
+{
+    /*
+     * Algorithm 14.36 in Handbook of Applied Cryptography with:
+     * b = 2^32, n = 8, R = 2^256
+     */
+    uint32_t m_prime = mod->ni;
+    uint32_t a[9];
+
+    for (unsigned i = 0; i < 9; i++) {
+        a[i] = 0;
+    }
+
+    for (unsigned i = 0; i < 8; i++) {
+        /* the "mod 2^32" is implicit from the type */
+        uint32_t u = (a[0] + x[i] * y[0]) * m_prime;
+
+        /* a = (a + x[i] * y + u * m) div b */
+        uint32_t c = u288_muladd(a, x[i], y);
+        c += u288_muladd(a, u, mod->m);
+        u288_rshift32(a, c);
+    }
+
+    /* a = a > m ? a - m : a */
+    uint32_t carry_add = a[8];  // 0 or 1 since a < 2m, see HAC Note 14.37
+    uint32_t carry_sub = u256_sub(z, a, mod->m);
+    uint32_t use_sub = carry_add | (1 - carry_sub);     // see m256_add()
+    u256_cmov(z, a, 1 - use_sub);
+}
+
+/*
+ * Montgomery modular multiplication modulo p.
+ *
+ * in: x, y in [0, p)
+ * out: z = (x * y) / 2^256 mod p, in [0, p)
+ *
+ * Note: as a memory area, z may overlap with x or y.
+ */
+static void m256_mul_p(uint32_t z[8],
+                       const uint32_t x[8], const uint32_t y[8])
+{
+    m256_mul(z, x, y, &p256_p);
+}
+
+/*
+ * In-place conversion to Montgomery form
+ *
+ * in: z in [0, m)
+ *     mod must point to a valid m256_mod structure
+ * out: z_out = z_in * 2^256 mod m, in [0, m)
+ */
+static void m256_prep(uint32_t z[8], const m256_mod *mod)
+{
+    m256_mul(z, z, mod->R2, mod);
+}
+
+/*
+ * In-place conversion from Montgomery form
+ *
+ * in: z in [0, m)
+ *     mod must point to a valid m256_mod structure
+ * out: z_out = z_in / 2^256 mod m, in [0, m)
+ * That is, z_in was z_actual * 2^256 mod m, and z_out is z_actual
+ */
+static void m256_done(uint32_t z[8], const m256_mod *mod)
+{
+    uint32_t one[8];
+    u256_set32(one, 1);
+    m256_mul(z, z, one, mod);
+}
+
+/*
+ * Set to 32-bit value
+ *
+ * in: x in [0, 2^32)
+ *     mod must point to a valid m256_mod structure
+ * out: z = x * 2^256 mod m, in [0, m)
+ * That is, z is set to the image of x in the Montgomery domain.
+ */
+static void m256_set32(uint32_t z[8], uint32_t x, const m256_mod *mod)
+{
+    u256_set32(z, x);
+    m256_prep(z, mod);
+}
+
+/*
+ * Modular inversion in Montgomery form
+ *
+ * in: x in [0, m)
+ *     mod must point to a valid m256_mod structure
+ *     such that mod->m % 2^32 >= 2, assumed to be public.
+ * out: z = x^-1 * 2^512 mod m if x != 0,
+ *      z = 0 if x == 0
+ * That is, if x = x_actual    * 2^256 mod m, then
+ *             z = x_actual^-1 * 2^256 mod m
+ *
+ * Note: as a memory area, z may overlap with x.
+ */
+static void m256_inv(uint32_t z[8], const uint32_t x[8],
+                     const m256_mod *mod)
+{
+    /*
+     * Use Fermat's little theorem to compute x^-1 as x^(m-2).
+     *
+     * Take advantage of the fact that both p's and n's least significant limb
+     * is at least 2 to perform the subtraction on the flight (no carry).
+     *
+     * Use plain right-to-left binary exponentiation;
+     * branches are OK as the exponent is not a secret.
+     */
+    uint32_t bitval[8];
+    u256_cmov(bitval, x, 1);    /* copy x before writing to z */
+
+    m256_set32(z, 1, mod);
+
+    unsigned i = 0;
+    uint32_t limb = mod->m[i] - 2;
+    while (1) {
+        for (unsigned j = 0; j < 32; j++) {
+            if ((limb & 1) != 0) {
+                m256_mul(z, z, bitval, mod);
+            }
+            m256_mul(bitval, bitval, bitval, mod);
+            limb >>= 1;
+        }
+
+        if (i == 7)
+            break;
+
+        i++;
+        limb = mod->m[i];
+    }
+}
+
+/*
+ * Import modular integer from bytes to Montgomery domain
+ *
+ * in: p = p0, ..., p32
+ *     mod must point to a valid m256_mod structure
+ * out: z = (p0 * 2^248 + ... + p31) * 2^256 mod m, in [0, m)
+ *      return 0 if the number was already in [0, m), or -1.
+ *      z may be incorrect and must be discared when -1 is returned.
+ */
+static int m256_from_bytes(uint32_t z[8],
+                           const uint8_t p[32], const m256_mod *mod)
+{
+    u256_from_bytes(z, p);
+
+    uint32_t t[8];
+    uint32_t lt_m = u256_sub(t, z, mod->m);
+    if (lt_m != 1)
+        return -1;
+
+    m256_prep(z, mod);
+    return 0;
+}
+
+/*
+ * Export modular integer from Montgomery domain to bytes
+ *
+ * in: z in [0, 2^256)
+ *     mod must point to a valid m256_mod structure
+ * out: p = p0, ..., p31 such that
+ *      z = (p0 * 2^248 + ... + p31) * 2^256 mod m
+ */
+static void m256_to_bytes(uint8_t p[32],
+                          const uint32_t z[8], const m256_mod *mod)
+{
+    uint32_t zi[8];
+    u256_cmov(zi, z, 1);
+    m256_done(zi, mod);
+
+    u256_to_bytes(p, zi);
+}
+
+/**********************************************************************
+ *
+ * Operations on curve points
+ *
+ * Points are represented in two coordinates system:
+ *  - affine (x, y) - extended to represent 0 (see below)
+ *  - jacobian (x:y:z)
+ * In either case, coordinates are integers modulo p256_p and
+ * are always represented in the Montgomery domain.
+ *
+ * For background on jacobian coordinates, see for example [GECC] 3.2.2:
+ * - conversions go (x, y) -> (x:y:1) and (x:y:z) -> (x/z^2, y/z^3)
+ * - the curve equation becomes y^2 = x^3 - 3 x z^4 + b z^6
+ * - 0 (aka the origin aka point at infinity) is (x:y:0) with y^2 = x^3.
+ * - point negation goes -(x:y:z) = (x:-y:z)
+ *
+ * Normally 0 (the point at infinity) can't be represented in affine
+ * coordinates. However we extend affine coordinates with the convention that
+ * (0, 0) (which is normally not a point on the curve) is interpreted as 0.
+ *
+ * References:
+ * - [GECC]: Guide to Elliptic Curve Cryptography; Hankerson, Menezes,
+ *   Vanstone; Springer, 2004.
+ * - [CMO98]: Efficient Elliptic Curve Exponentiation Using Mixed Coordinates;
+ *   Cohen, Miyaji, Ono; Springer, ASIACRYPT 1998.
+ *   https://link.springer.com/content/pdf/10.1007/3-540-49649-1_6.pdf
+ * - [RCB15]: Complete addition formulas for prime order elliptic curves;
+ *   Renes, Costello, Batina; IACR e-print 2015-1060.
+ *   https://eprint.iacr.org/2015/1060.pdf
+ *
+ **********************************************************************/
+
+/*
+ * The curve's b parameter in the Short Weierstrass equation
+ *  y^2 = x^3 - 3*x + b
+ * Compared to the standard, this is converted to the Montgomery domain.
+ */
+static const uint32_t p256_b[8] = { /* b * 2^256 mod p */
+    0x29c4bddf, 0xd89cdf62, 0x78843090, 0xacf005cd,
+    0xf7212ed6, 0xe5a220ab, 0x04874834, 0xdc30061d,
+};
+
+/*
+ * The curve's conventional base point G.
+ * Compared to the standard, coordinates converted to the Montgomery domain.
+ */
+static const uint32_t p256_gx[8] = { /* G_x * 2^256 mod p */
+    0x18a9143c, 0x79e730d4, 0x5fedb601, 0x75ba95fc,
+    0x77622510, 0x79fb732b, 0xa53755c6, 0x18905f76,
+};
+static const uint32_t p256_gy[8] = { /* G_y * 2^256 mod p */
+    0xce95560a, 0xddf25357, 0xba19e45c, 0x8b4ab8e4,
+    0xdd21f325, 0xd2e88688, 0x25885d85, 0x8571ff18,
+};
+
+/*
+ * Point-on-curve check - do the coordinates satisfy the curve's equation?
+ *
+ * in: x, y in [0, p)   (Montgomery domain)
+ * out: 0 if the point lies on the curve and is not 0,
+ *      unspecified non-zero otherwise
+ */
+static uint32_t point_check(const uint32_t x[8], const uint32_t y[8])
+{
+    uint32_t lhs[8], rhs[8];
+
+    /* lhs = y^2 */
+    m256_mul_p(lhs, y, y);
+
+    /* rhs = x^3 - 3x + b */
+    m256_mul_p(rhs, x,   x);      /* x^2 */
+    m256_mul_p(rhs, rhs, x);      /* x^3 */
+    for (unsigned i = 0; i < 3; i++)
+        m256_sub_p(rhs, rhs, x);  /* x^3 - 3x */
+    m256_add_p(rhs, rhs, p256_b); /* x^3 - 3x + b */
+
+    return u256_diff(lhs, rhs);
+}
+
+/*
+ * In-place jacobian to affine coordinate conversion
+ *
+ * in: (x:y:z) must be on the curve (coordinates in Montegomery domain)
+ * out: x_out = x_in / z_in^2   (Montgomery domain)
+ *      y_out = y_in / z_in^3   (Montgomery domain)
+ *      z_out unspecified, must be disregarded
+ *
+ * Note: if z is 0 (that is, the input point is 0), x_out = y_out = 0.
+ */
+static void point_to_affine(uint32_t x[8], uint32_t y[8], uint32_t z[8])
+{
+    uint32_t t[8];
+
+    m256_inv(z, z, &p256_p);    /* z = z^-1 */
+
+    m256_mul_p(t, z, z);        /* t = z^-2 */
+    m256_mul_p(x, x, t);        /* x = x * z^-2 */
+
+    m256_mul_p(t, t, z);        /* t = z^-3 */
+    m256_mul_p(y, y, t);        /* y = y * z^-3 */
+}
+
+/*
+ * In-place point doubling in jacobian coordinates (Montgomery domain)
+ *
+ * in: P_in = (x:y:z), must be on the curve
+ * out: (x:y:z) = P_out = 2 * P_in
+ */
+static void point_double(uint32_t x[8], uint32_t y[8], uint32_t z[8])
+{
+    /*
+     * This is formula 6 from [CMO98], cited as complete in [RCB15] (table 1).
+     * Notations as in the paper, except u added and t ommited (it's x3).
+     */
+    uint32_t m[8], s[8], u[8];
+
+    /* m = 3 * x^2 + a * z^4 = 3 * (x + z^2) * (x - z^2) */
+    m256_mul_p(s, z, z);
+    m256_add_p(m, x, s);
+    m256_sub_p(u, x, s);
+    m256_mul_p(s, m, u);
+    m256_add_p(m, s, s);
+    m256_add_p(m, m, s);
+
+    /* s = 4 * x * y^2 */
+    m256_mul_p(u, y, y);
+    m256_add_p(u, u, u); /* u = 2 * y^2 (used below) */
+    m256_mul_p(s, x, u);
+    m256_add_p(s, s, s);
+
+    /* u = 8 * y^4 (not named in the paper, first term of y3) */
+    m256_mul_p(u, u, u);
+    m256_add_p(u, u, u);
+
+    /* x3 = t = m^2 - 2 * s */
+    m256_mul_p(x, m, m);
+    m256_sub_p(x, x, s);
+    m256_sub_p(x, x, s);
+
+    /* z3 = 2 * y * z */
+    m256_mul_p(z, y, z);
+    m256_add_p(z, z, z);
+
+    /* y3 = -u + m * (s - t) */
+    m256_sub_p(y, s, x);
+    m256_mul_p(y, y, m);
+    m256_sub_p(y, y, u);
+}
+
+/*
+ * In-place point addition in jacobian-affine coordinates (Montgomery domain)
+ *
+ * in: P_in = (x1:y1:z1), must be on the curve and not 0
+ *     Q = (x2, y2), must be on the curve and not P_in or -P_in or 0
+ * out: P_out = (x1:y1:z1) = P_in + Q
+ */
+static void point_add(uint32_t x1[8], uint32_t y1[8], uint32_t z1[8],
+                      const uint32_t x2[8], const uint32_t y2[8])
+{
+    /*
+     * This is formula 5 from [CMO98], with z2 == 1 substituted. We use
+     * intermediates with neutral names, and names from the paper in comments.
+     */
+    uint32_t t1[8], t2[8], t3[8];
+
+    /* u1 = x1 and s1 = y1 (no computations) */
+
+    /* t1 = u2 = x2 z1^2 */
+    m256_mul_p(t1, z1, z1);
+    m256_mul_p(t2, t1, z1);
+    m256_mul_p(t1, t1, x2);
+
+    /* t2 = s2 = y2 z1^3 */
+    m256_mul_p(t2, t2, y2);
+
+    /* t1 = h = u2 - u1 */
+    m256_sub_p(t1, t1, x1); /* t1 = x2 * z1^2 - x1 */
+
+    /* t2 = r = s2 - s1 */
+    m256_sub_p(t2, t2, y1);
+
+    /* z3 = z1 * h */
+    m256_mul_p(z1, z1, t1);
+
+    /* t1 = h^3 */
+    m256_mul_p(t3, t1, t1);
+    m256_mul_p(t1, t3, t1);
+
+    /* t3 = x1 * h^2 */
+    m256_mul_p(t3, t3, x1);
+
+    /* x3 = r^2 - 2 * x1 * h^2 - h^3 */
+    m256_mul_p(x1, t2, t2);
+    m256_sub_p(x1, x1, t3);
+    m256_sub_p(x1, x1, t3);
+    m256_sub_p(x1, x1, t1);
+
+    /* y3 = r * (x1 * h^2 - x3) - y1 h^3 */
+    m256_sub_p(t3, t3, x1);
+    m256_mul_p(t3, t3, t2);
+    m256_mul_p(t1, t1, y1);
+    m256_sub_p(y1, t3, t1);
+}
+
+/*
+ * Point addition or doubling (affine to jacobian, Montgomery domain)
+ *
+ * in: P = (x1, y1) - must be on the curve and not 0
+ *     Q = (x2, y2) - must be on the curve and not 0
+ * out: (x3, y3) = R = P + Q
+ *
+ * Note: unlike point_add(), this function works if P = +- Q;
+ * however it leaks information on its input through timing,
+ * branches taken and memory access patterns (if observable).
+ */
+static void point_add_or_double_leaky(
+                        uint32_t x3[8], uint32_t y3[8],
+                        const uint32_t x1[8], const uint32_t y1[8],
+                        const uint32_t x2[8], const uint32_t y2[8])
+{
+
+    uint32_t z3[8];
+    u256_cmov(x3, x1, 1);
+    u256_cmov(y3, y1, 1);
+    m256_set32(z3, 1, &p256_p);
+
+    if (u256_diff(x1, x2) != 0) {
+        // P != +- Q -> generic addition
+        point_add(x3, y3, z3, x2, y2);
+        point_to_affine(x3, y3, z3);
+    }
+    else if (u256_diff(y1, y2) == 0) {
+        // P == Q -> double
+        point_double(x3, y3, z3);
+        point_to_affine(x3, y3, z3);
+    } else {
+        // P == -Q -> zero
+        m256_set32(x3, 0, &p256_p);
+        m256_set32(y3, 0, &p256_p);
+    }
+}
+
+/*
+ * Import curve point from bytes
+ *
+ * in: p = (x, y) concatenated, fixed-width 256-bit big-endian integers
+ * out: x, y in Mongomery domain
+ *      return 0 if x and y are both in [0, p)
+ *                  and (x, y) is on the curve and not 0
+ *             unspecified non-zero otherwise.
+ *      x and y are unspecified and must be discarded if returning non-zero.
+ */
+static int point_from_bytes(uint32_t x[8], uint32_t y[8], const uint8_t p[64])
+{
+    int ret;
+
+    ret = m256_from_bytes(x, p, &p256_p);
+    if (ret != 0)
+        return ret;
+
+    ret = m256_from_bytes(y, p + 32, &p256_p);
+    if (ret != 0)
+        return ret;
+
+    return (int) point_check(x, y);
+}
+
+/*
+ * Export curve point to bytes
+ *
+ * in: x, y affine coordinates of a point (Montgomery domain)
+ *     must be on the curve and not 0
+ * out: p = (x, y) concatenated, fixed-width 256-bit big-endian integers
+ */
+static void point_to_bytes(uint8_t p[64],
+                           const uint32_t x[8], const uint32_t y[8])
+{
+    m256_to_bytes(p,        x, &p256_p);
+    m256_to_bytes(p + 32,   y, &p256_p);
+}
+
+/**********************************************************************
+ *
+ * Scalar multiplication and other scalar-related operations
+ *
+ **********************************************************************/
+
+/*
+ * Scalar multiplication
+ *
+ * in: P = (px, py), affine (Montgomery), must be on the curve and not 0
+ *     s in [1, n-1]
+ * out: R = s * P = (rx, ry), affine coordinates (Montgomery).
+ *
+ * Note: as memory areas, none of the parameters may overlap.
+ */
+static void scalar_mult(uint32_t rx[8], uint32_t ry[8],
+                        const uint32_t px[8], const uint32_t py[8],
+                        const uint32_t s[8])
+{
+    /*
+     * We use a signed binary ladder, see for example slides 10-14 of
+     * http://ecc2015.math.u-bordeaux1.fr/documents/hamburg.pdf but with
+     * implicit recoding, and a different loop initialisation to avoid feeding
+     * 0 to our addition formulas, as they don't support it.
+     */
+    uint32_t s_odd[8], py_neg[8], py_use[8], rz[8];
+
+    /*
+     * Make s odd by replacing it with n - s if necessary.
+     *
+     * If s was odd, we'll have s_odd = s, and define P' = P.
+     * Otherwise, we'll have s_odd = n - s and define P' = -P.
+     *
+     * Either way, we can compute s * P as s_odd * P'.
+     */
+    u256_sub(s_odd, p256_n.m, s); /* no carry, result still in [1, n-1] */
+    uint32_t negate = ~s[0] & 1;
+    u256_cmov(s_odd, s, 1 - negate);
+
+    /* Compute py_neg = - py mod p (that's the y coordinate of -P) */
+    u256_set32(py_use, 0);
+    m256_sub_p(py_neg, py_use, py);
+
+    /* Initialize R = P' = (x:(-1)^negate * y:1) */
+    u256_cmov(rx, px, 1);
+    u256_cmov(ry, py, 1);
+    m256_set32(rz, 1, &p256_p);
+    u256_cmov(ry, py_neg, negate);
+
+    /*
+     * For any odd number s_odd = b255 ... b1 1, we have
+     *      s_odd = 2^255 + 2^254 sbit(b255) + ... + 2 sbit(b2) + sbit(b1)
+     * writing
+     *      sbit(b) = 2 * b - 1 = b ? 1 : -1
+     *
+     * Use that to compute s_odd * P' by repeating R = 2 * R +- P':
+     *      s_odd * P' = 2 * ( ... (2 * P' + sbit(b255) P') ... ) + sbit(b1) P'
+     *
+     * The loop invariant is that when beginning an iteration we have
+     *      R = s_i P'
+     * with
+     *      s_i = 2^(255-i) + 2^(254-i) sbit(b_255) + ...
+     * where the sum has 256 - i terms.
+     *
+     * When updating R we need to make sure the input to point_add() is
+     * neither 0 not +-P'. Since that input is 2 s_i P', it is sufficient to
+     * see that 1 < 2 s_i < n-1. The lower bound is obvious since s_i is a
+     * positive integer, and for the upper bound we distinguish three cases.
+     *
+     * If i > 1, then s_i < 2^254, so 2 s_i < 2^255 < n-1.
+     * Otherwise, i == 1 and we have 2 s_i = s_odd - sbit(b1).
+     *      If s_odd <= n-4, then 2 s_1 <= n-3.
+     *      Otherwise, s_odd = n-2, and for this curve's value of n,
+     *      we have b1 == 1, so sbit(b1) = 1 and 2 s_1 <= n-3.
+     */
+    for (unsigned i = 255; i > 0; i--) {
+        uint32_t bit = (s_odd[i / 32] >> i % 32) & 1;
+
+        /* set (px, py_use) = sbit(bit) P' = sbit(bit) * (-1)^negate P */
+        u256_cmov(py_use, py, bit ^ negate);
+        u256_cmov(py_use, py_neg, (1 - bit) ^ negate);
+
+        /* Update R = 2 * R +- P' */
+        point_double(rx, ry, rz);
+        point_add(rx, ry, rz, px, py_use);
+    }
+
+    point_to_affine(rx, ry, rz);
+}
+
+/*
+ * Scalar import from big-endian bytes
+ *
+ * in: p = p0, ..., p31
+ * out: s = p0 * 2^248 + p1 * 2^240 + ... + p30 * 2^8 + p31
+ *      return 0 if s in [1, n-1],
+ *            -1 otherwise.
+ */
+static int scalar_from_bytes(uint32_t s[8], const uint8_t p[32])
+{
+    u256_from_bytes(s, p);
+
+    uint32_t r[8];
+    uint32_t lt_n = u256_sub(r, s, p256_n.m);
+
+    u256_set32(r, 1);
+    uint32_t lt_1 = u256_sub(r, s, r);
+
+    if (lt_n && !lt_1)
+        return 0;
+
+    return -1;
+}
+
+/* Using RNG functions from Mbed TLS as p256-m does not come with a
+ * cryptographically secure RNG function.
+ */
+int p256_generate_random(uint8_t *output, unsigned output_size)
+{
+    int ret;
+    ret = psa_generate_random(output, output_size);
+
+    if (ret != 0){
+        return P256_RANDOM_FAILED;
+    }
+    return P256_SUCCESS;
+}
+
+/*
+ * Scalar generation, with public key
+ *
+ * out: sbytes the big-endian bytes representation of the scalar
+ *      s its u256 representation
+ *      x, y the affine coordinates of s * G (Montgomery domain)
+ *      return 0 if OK, -1 on failure
+ *      sbytes, s, x, y must be discarded when returning non-zero.
+ */
+static int scalar_gen_with_pub(uint8_t sbytes[32], uint32_t s[8],
+                               uint32_t x[8], uint32_t y[8])
+{
+    /* generate a random valid scalar */
+    int ret;
+    unsigned nb_tried = 0;
+    do {
+        if (nb_tried++ >= 4)
+            return -1;
+
+        ret = p256_generate_random(sbytes, 32);
+        CT_POISON(sbytes, 32);
+        if (ret != 0)
+            return -1;
+
+        ret = scalar_from_bytes(s, sbytes);
+        CT_UNPOISON(&ret, sizeof ret);
+    }
+    while (ret != 0);
+
+    /* compute and ouput the associated public key */
+    scalar_mult(x, y, p256_gx, p256_gy, s);
+
+    /* the associated public key is not a secret */
+    CT_UNPOISON(x, 32);
+    CT_UNPOISON(y, 32);
+
+    return 0;
+}
+
+/*
+ * ECDH/ECDSA generate pair
+ */
+int p256_gen_keypair(uint8_t priv[32], uint8_t pub[64])
+{
+    uint32_t s[8], x[8], y[8];
+    int ret = scalar_gen_with_pub(priv, s, x, y);
+    zeroize(s, sizeof s);
+    if (ret != 0)
+        return P256_RANDOM_FAILED;
+
+    point_to_bytes(pub, x, y);
+    return 0;
+}
+
+/**********************************************************************
+ *
+ * ECDH
+ *
+ **********************************************************************/
+
+/*
+ * ECDH compute shared secret
+ */
+int p256_ecdh_shared_secret(uint8_t secret[32],
+                            const uint8_t priv[32], const uint8_t peer[64])
+{
+    CT_POISON(priv, 32);
+
+    uint32_t s[8], px[8], py[8], x[8], y[8];
+    int ret;
+
+    ret = scalar_from_bytes(s, priv);
+    CT_UNPOISON(&ret, sizeof ret);
+    if (ret != 0) {
+        ret = P256_INVALID_PRIVKEY;
+        goto cleanup;
+    }
+
+    ret = point_from_bytes(px, py, peer);
+    if (ret != 0) {
+        ret = P256_INVALID_PUBKEY;
+        goto cleanup;
+    }
+
+    scalar_mult(x, y, px, py, s);
+
+    m256_to_bytes(secret, x, &p256_p);
+    CT_UNPOISON(secret, 32);
+
+cleanup:
+    zeroize(s, sizeof s);
+    return ret;
+}
+
+/**********************************************************************
+ *
+ * ECDSA
+ *
+ * Reference:
+ * [SEC1] SEC 1: Elliptic Curve Cryptography, Certicom research, 2009.
+ *        http://www.secg.org/sec1-v2.pdf
+ **********************************************************************/
+
+/*
+ * Reduction mod n of a small number
+ *
+ * in: x in [0, 2^256)
+ * out: x_out = x_in mod n in [0, n)
+ */
+static void ecdsa_m256_mod_n(uint32_t x[8])
+{
+    uint32_t t[8];
+    uint32_t c = u256_sub(t, x, p256_n.m);
+    u256_cmov(x, t, 1 - c);
+}
+
+/*
+ * Import integer mod n (Montgomery domain) from hash
+ *
+ * in: h = h0, ..., h_hlen
+ *     hlen the length of h in bytes
+ * out: z = (h0 * 2^l-8 + ... + h_l) * 2^256 mod n
+ *      with l = min(32, hlen)
+ *
+ * Note: in [SEC1] this is step 5 of 4.1.3 (sign) or step 3 or 4.1.4 (verify),
+ * with obvious simplications since n's bit-length is a multiple of 8.
+ */
+static void ecdsa_m256_from_hash(uint32_t z[8],
+                                 const uint8_t *h, size_t hlen)
+{
+    /* convert from h (big-endian) */
+    /* hlen is public data so it's OK to branch on it */
+    if (hlen < 32) {
+        uint8_t p[32];
+        for (unsigned i = 0; i < 32; i++)
+            p[i] = 0;
+        for (unsigned i = 0; i < hlen; i++)
+            p[32 - hlen + i] = h[i];
+        u256_from_bytes(z, p);
+    } else {
+        u256_from_bytes(z, h);
+    }
+
+    /* ensure the result is in [0, n) */
+    ecdsa_m256_mod_n(z);
+
+    /* map to Montgomery domain */
+    m256_prep(z, &p256_n);
+}
+
+/*
+ * ECDSA sign
+ */
+int p256_ecdsa_sign(uint8_t sig[64], const uint8_t priv[32],
+                    const uint8_t *hash, size_t hlen)
+{
+    CT_POISON(priv, 32);
+
+    /*
+     * Steps and notations from [SEC1] 4.1.3
+     *
+     * Instead of retrying on r == 0 or s == 0, just abort,
+     * as those events have negligible probability.
+     */
+    int ret;
+
+    /* Temporary buffers - the first two are mostly stable, so have names */
+    uint32_t xr[8], k[8], t3[8], t4[8];
+
+    /* 1. Set ephemeral keypair */
+    uint8_t *kb = (uint8_t *) t4;
+    /* kb will be erased by re-using t4 for dU - if we exit before that, we
+     * haven't read the private key yet so we kb isn't sensitive yet */
+    ret = scalar_gen_with_pub(kb, k, xr, t3);   /* xr = x_coord(k * G) */
+    if (ret != 0)
+        return P256_RANDOM_FAILED;
+    m256_prep(k, &p256_n);
+
+    /* 2. Convert xr to an integer */
+    m256_done(xr, &p256_p);
+
+    /* 3. Reduce xr mod n (extra: output it while at it) */
+    ecdsa_m256_mod_n(xr);    /* xr = int(xr) mod n */
+
+    /* xr is public data so it's OK to use a branch */
+    if (u256_diff0(xr) == 0)
+        return P256_RANDOM_FAILED;
+
+    u256_to_bytes(sig, xr);
+
+    m256_prep(xr, &p256_n);
+
+    /* 4. Skipped - we take the hash as an input, not the message */
+
+    /* 5. Derive an integer from the hash */
+    ecdsa_m256_from_hash(t3, hash, hlen);   /* t3 = e */
+
+    /* 6. Compute s = k^-1 * (e + r * dU) */
+
+    /* Note: dU will be erased by re-using t4 for the value of s (public) */
+    ret = scalar_from_bytes(t4, priv);   /* t4 = dU (integer domain) */
+    CT_UNPOISON(&ret, sizeof ret); /* Result of input validation */
+    if (ret != 0)
+        return P256_INVALID_PRIVKEY;
+    m256_prep(t4, &p256_n);         /* t4 = dU (Montgomery domain) */
+
+    m256_inv(k, k, &p256_n);        /* k^-1 */
+    m256_mul(t4, xr, t4, &p256_n);  /* t4 = r * dU */
+    m256_add(t4, t3, t4, &p256_n);  /* t4 = e + r * dU */
+    m256_mul(t4, k, t4, &p256_n);   /* t4 = s = k^-1 * (e + r * dU) */
+    zeroize(k, sizeof k);
+
+    /* 7. Output s (r already outputed at step 3) */
+    CT_UNPOISON(t4, 32);
+    if (u256_diff0(t4) == 0) {
+        /* undo early output of r */
+        u256_to_bytes(sig, t4);
+        return P256_RANDOM_FAILED;
+    }
+    m256_to_bytes(sig + 32, t4, &p256_n);
+
+    return P256_SUCCESS;
+}
+
+/*
+ * ECDSA verify
+ */
+int p256_ecdsa_verify(const uint8_t sig[64], const uint8_t pub[64],
+                      const uint8_t *hash, size_t hlen)
+{
+    /*
+     * Steps and notations from [SEC1] 4.1.3
+     *
+     * Note: we're using public data only, so branches are OK
+     */
+    int ret;
+
+    /* 1. Validate range of r and s : [1, n-1] */
+    uint32_t r[8], s[8];
+    ret = scalar_from_bytes(r, sig);
+    if (ret != 0)
+        return P256_INVALID_SIGNATURE;
+    ret = scalar_from_bytes(s, sig + 32);
+    if (ret != 0)
+        return P256_INVALID_SIGNATURE;
+
+    /* 2. Skipped - we take the hash as an input, not the message */
+
+    /* 3. Derive an integer from the hash */
+    uint32_t e[8];
+    ecdsa_m256_from_hash(e, hash, hlen);
+
+    /* 4. Compute u1 = e * s^-1 and u2 = r * s^-1 */
+    uint32_t u1[8], u2[8];
+    m256_prep(s, &p256_n);           /* s in Montgomery domain */
+    m256_inv(s, s, &p256_n);         /* s = s^-1 mod n */
+    m256_mul(u1, e, s, &p256_n);     /* u1 = e * s^-1 mod n */
+    m256_done(u1, &p256_n);          /* u1 out of Montgomery domain */
+
+    u256_cmov(u2, r, 1);
+    m256_prep(u2, &p256_n);          /* r in Montgomery domain */
+    m256_mul(u2, u2, s, &p256_n);    /* u2 = r * s^-1 mod n */
+    m256_done(u2, &p256_n);          /* u2 out of Montgomery domain */
+
+    /* 5. Compute R (and re-use (u1, u2) to store its coordinates */
+    uint32_t px[8], py[8];
+    ret = point_from_bytes(px, py, pub);
+    if (ret != 0)
+        return P256_INVALID_PUBKEY;
+
+    scalar_mult(e, s, px, py, u2);      /* (e, s) = R2 = u2 * Qu */
+
+    if (u256_diff0(u1) == 0) {
+        /* u1 out of range for scalar_mult() - just skip it */
+        u256_cmov(u1, e, 1);
+        /* we don't care about the y coordinate */
+    } else {
+        scalar_mult(px, py, p256_gx, p256_gy, u1); /* (px, py) = R1 = u1 * G */
+
+        /* (u1, u2) = R = R1 + R2 */
+        point_add_or_double_leaky(u1, u2, px, py, e, s);
+        /* No need to check if R == 0 here: if that's the case, it will be
+         * caught when comparating rx (which will be 0) to r (which isn't). */
+    }
+
+    /* 6. Convert xR to an integer */
+    m256_done(u1, &p256_p);
+
+    /* 7. Reduce xR mod n */
+    ecdsa_m256_mod_n(u1);
+
+    /* 8. Compare xR mod n to r */
+    uint32_t diff = u256_diff(u1, r);
+    if (diff == 0)
+        return P256_SUCCESS;
+
+    return P256_INVALID_SIGNATURE;
+}
+
+/**********************************************************************
+ *
+ * Key management utilities
+ *
+ **********************************************************************/
+
+int p256_validate_pubkey(const uint8_t pub[64])
+{
+    uint32_t x[8], y[8];
+    int ret = point_from_bytes(x, y, pub);
+
+    return ret == 0 ? P256_SUCCESS : P256_INVALID_PUBKEY;
+}
+
+int p256_validate_privkey(const uint8_t priv[32])
+{
+    uint32_t s[8];
+    int ret = scalar_from_bytes(s, priv);
+    zeroize(s, sizeof(s));
+
+    return ret == 0 ? P256_SUCCESS : P256_INVALID_PRIVKEY;
+}
+
+int p256_public_from_private(uint8_t pub[64], const uint8_t priv[32])
+{
+    int ret;
+    uint32_t s[8];
+
+    ret = scalar_from_bytes(s, priv);
+    if (ret != 0)
+        return P256_INVALID_PRIVKEY;
+
+    /* compute and ouput the associated public key */
+    uint32_t x[8], y[8];
+    scalar_mult(x, y, p256_gx, p256_gy, s);
+
+    /* the associated public key is not a secret, the scalar was */
+    CT_UNPOISON(x, 32);
+    CT_UNPOISON(y, 32);
+    zeroize(s, sizeof(s));
+
+    point_to_bytes(pub, x, y);
+    return P256_SUCCESS;
+}
+
+#endif
diff --git a/vendor/mbedtls/3rdparty/p256-m/p256-m/p256-m.h b/vendor/mbedtls/3rdparty/p256-m/p256-m/p256-m.h
new file mode 100644
index 0000000000..c267800248
--- /dev/null
+++ b/vendor/mbedtls/3rdparty/p256-m/p256-m/p256-m.h
@@ -0,0 +1,135 @@
+/*
+ * Interface of curve P-256 (ECDH and ECDSA)
+ *
+ * Copyright The Mbed TLS Contributors
+ * Author: Manuel Pégourié-Gonnard.
+ * SPDX-License-Identifier: Apache-2.0 OR GPL-2.0-or-later
+ */
+#ifndef P256_M_H
+#define P256_M_H
+
+#include 
+#include 
+
+/* Status codes */
+#define P256_SUCCESS            0
+#define P256_RANDOM_FAILED      -1
+#define P256_INVALID_PUBKEY     -2
+#define P256_INVALID_PRIVKEY    -3
+#define P256_INVALID_SIGNATURE  -4
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+/*
+ * RNG function - must be provided externally and be cryptographically secure.
+ *
+ * in: output - must point to a writable buffer of at least output_size bytes.
+ *     output_size - the number of random bytes to write to output.
+ * out: output is filled with output_size random bytes.
+ *      return 0 on success, non-zero on errors.
+ */
+extern int p256_generate_random(uint8_t * output, unsigned output_size);
+
+/*
+ * ECDH/ECDSA generate key pair
+ *
+ * [in] draws from p256_generate_random()
+ * [out] priv: on success, holds the private key, as a big-endian integer
+ * [out] pub: on success, holds the public key, as two big-endian integers
+ *
+ * return:  P256_SUCCESS on success
+ *          P256_RANDOM_FAILED on failure
+ */
+int p256_gen_keypair(uint8_t priv[32], uint8_t pub[64]);
+
+/*
+ * ECDH compute shared secret
+ *
+ * [out] secret: on success, holds the shared secret, as a big-endian integer
+ * [in] priv: our private key as a big-endian integer
+ * [in] pub: the peer's public key, as two big-endian integers
+ *
+ * return:  P256_SUCCESS on success
+ *          P256_INVALID_PRIVKEY if priv is invalid
+ *          P256_INVALID_PUBKEY if pub is invalid
+ */
+int p256_ecdh_shared_secret(uint8_t secret[32],
+                            const uint8_t priv[32], const uint8_t pub[64]);
+
+/*
+ * ECDSA sign
+ *
+ * [in] draws from p256_generate_random()
+ * [out] sig: on success, holds the signature, as two big-endian integers
+ * [in] priv: our private key as a big-endian integer
+ * [in] hash: the hash of the message to be signed
+ * [in] hlen: the size of hash in bytes
+ *
+ * return:  P256_SUCCESS on success
+ *          P256_RANDOM_FAILED on failure
+ *          P256_INVALID_PRIVKEY if priv is invalid
+ */
+int p256_ecdsa_sign(uint8_t sig[64], const uint8_t priv[32],
+                    const uint8_t *hash, size_t hlen);
+
+/*
+ * ECDSA verify
+ *
+ * [in] sig: the signature to be verified, as two big-endian integers
+ * [in] pub: the associated public key, as two big-endian integers
+ * [in] hash: the hash of the message that was signed
+ * [in] hlen: the size of hash in bytes
+ *
+ * return:  P256_SUCCESS on success - the signature was verified as valid
+ *          P256_INVALID_PUBKEY if pub is invalid
+ *          P256_INVALID_SIGNATURE if the signature was found to be invalid
+ */
+int p256_ecdsa_verify(const uint8_t sig[64], const uint8_t pub[64],
+                      const uint8_t *hash, size_t hlen);
+
+/*
+ * Public key validation
+ *
+ * Note: you never need to call this function, as all other functions always
+ * validate their input; however it's availabe if you want to validate the key
+ * without performing an operation.
+ *
+ * [in] pub: the public key, as two big-endian integers
+ *
+ * return:  P256_SUCCESS if the key is valid
+ *          P256_INVALID_PUBKEY if pub is invalid
+ */
+int p256_validate_pubkey(const uint8_t pub[64]);
+
+/*
+ * Private key validation
+ *
+ * Note: you never need to call this function, as all other functions always
+ * validate their input; however it's availabe if you want to validate the key
+ * without performing an operation.
+ *
+ * [in] priv: the private key, as a big-endian integer
+ *
+ * return:  P256_SUCCESS if the key is valid
+ *          P256_INVALID_PRIVKEY if priv is invalid
+ */
+int p256_validate_privkey(const uint8_t priv[32]);
+
+/*
+ * Compute public key from private key
+ *
+ * [out] pub: the associated public key, as two big-endian integers
+ * [in] priv: the private key, as a big-endian integer
+ *
+ * return:  P256_SUCCESS on success
+ *          P256_INVALID_PRIVKEY if priv is invalid
+ */
+int p256_public_from_private(uint8_t pub[64], const uint8_t priv[32]);
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif /* P256_M_H */
diff --git a/vendor/mbedtls/3rdparty/p256-m/p256-m_driver_entrypoints.c b/vendor/mbedtls/3rdparty/p256-m/p256-m_driver_entrypoints.c
new file mode 100644
index 0000000000..d272dcbb1e
--- /dev/null
+++ b/vendor/mbedtls/3rdparty/p256-m/p256-m_driver_entrypoints.c
@@ -0,0 +1,312 @@
+/*
+ *  Driver entry points for p256-m
+ */
+/*
+ *  Copyright The Mbed TLS Contributors
+ *  SPDX-License-Identifier: Apache-2.0 OR GPL-2.0-or-later
+ */
+
+#include "mbedtls/platform.h"
+#include "p256-m_driver_entrypoints.h"
+#include "p256-m/p256-m.h"
+#include "psa/crypto.h"
+#include 
+#include 
+#include "psa_crypto_driver_wrappers_no_static.h"
+
+#if defined(MBEDTLS_PSA_P256M_DRIVER_ENABLED)
+
+/* INFORMATION ON PSA KEY EXPORT FORMATS:
+ *
+ * PSA exports SECP256R1 keys in two formats:
+ * 1. Keypair format: 32 byte string which is just the private key (public key
+ *                    can be calculated from the private key)
+ * 2. Public Key format: A leading byte 0x04 (indicating uncompressed format),
+ *                       followed by the 64 byte public key. This results in a
+ *                       total of 65 bytes.
+ *
+ * p256-m's internal format for private keys matches PSA. Its format for public
+ * keys is only 64 bytes: the same as PSA but without the leading byte (0x04).
+ * Hence, when passing public keys from PSA to p256-m, the leading byte is
+ * removed.
+ *
+ * Shared secret and signature have the same format between PSA and p256-m.
+ */
+#define PSA_PUBKEY_SIZE         65
+#define PSA_PUBKEY_HEADER_BYTE  0x04
+#define P256_PUBKEY_SIZE        64
+#define PRIVKEY_SIZE            32
+#define SHARED_SECRET_SIZE      32
+#define SIGNATURE_SIZE          64
+
+#define CURVE_BITS              256
+
+/* Convert between p256-m and PSA error codes */
+static psa_status_t p256_to_psa_error(int ret)
+{
+    switch (ret) {
+        case P256_SUCCESS:
+            return PSA_SUCCESS;
+        case P256_INVALID_PUBKEY:
+        case P256_INVALID_PRIVKEY:
+            return PSA_ERROR_INVALID_ARGUMENT;
+        case P256_INVALID_SIGNATURE:
+            return PSA_ERROR_INVALID_SIGNATURE;
+        case P256_RANDOM_FAILED:
+        default:
+            return PSA_ERROR_GENERIC_ERROR;
+    }
+}
+
+psa_status_t p256_transparent_import_key(const psa_key_attributes_t *attributes,
+                             const uint8_t *data,
+                             size_t data_length,
+                             uint8_t *key_buffer,
+                             size_t key_buffer_size,
+                             size_t *key_buffer_length,
+                             size_t *bits)
+{
+    /* Check the key size */
+    if (*bits != 0 && *bits != CURVE_BITS) {
+        return PSA_ERROR_NOT_SUPPORTED;
+    }
+
+    /* Validate the key (and its type and size) */
+    psa_key_type_t type = psa_get_key_type(attributes);
+    if (type == PSA_KEY_TYPE_ECC_PUBLIC_KEY(PSA_ECC_FAMILY_SECP_R1)) {
+        if (data_length != PSA_PUBKEY_SIZE) {
+            return *bits == 0 ? PSA_ERROR_NOT_SUPPORTED : PSA_ERROR_INVALID_ARGUMENT;
+        }
+        /* See INFORMATION ON PSA KEY EXPORT FORMATS near top of file */
+        if (p256_validate_pubkey(data + 1) != P256_SUCCESS) {
+            return PSA_ERROR_INVALID_ARGUMENT;
+        }
+    } else if (type == PSA_KEY_TYPE_ECC_KEY_PAIR(PSA_ECC_FAMILY_SECP_R1)) {
+        if (data_length != PRIVKEY_SIZE) {
+            return *bits == 0 ? PSA_ERROR_NOT_SUPPORTED : PSA_ERROR_INVALID_ARGUMENT;
+        }
+        if (p256_validate_privkey(data) != P256_SUCCESS) {
+            return PSA_ERROR_INVALID_ARGUMENT;
+        }
+    } else {
+        return PSA_ERROR_NOT_SUPPORTED;
+    }
+    *bits = CURVE_BITS;
+
+    /* We only support the export format for input, so just copy. */
+    if (key_buffer_size < data_length) {
+        return PSA_ERROR_BUFFER_TOO_SMALL;
+    }
+    memcpy(key_buffer, data, data_length);
+    *key_buffer_length = data_length;
+
+    return PSA_SUCCESS;
+}
+
+psa_status_t p256_transparent_export_public_key(const psa_key_attributes_t *attributes,
+                                    const uint8_t *key_buffer,
+                                    size_t key_buffer_size,
+                                    uint8_t *data,
+                                    size_t data_size,
+                                    size_t *data_length)
+{
+    /* Is this the right curve? */
+    size_t bits = psa_get_key_bits(attributes);
+    psa_key_type_t type = psa_get_key_type(attributes);
+    if (bits != CURVE_BITS || type != PSA_KEY_TYPE_ECC_KEY_PAIR(PSA_ECC_FAMILY_SECP_R1)) {
+        return PSA_ERROR_NOT_SUPPORTED;
+    }
+
+    /* Validate sizes, as p256-m expects fixed-size buffers */
+    if (key_buffer_size != PRIVKEY_SIZE) {
+        return PSA_ERROR_INVALID_ARGUMENT;
+    }
+    if (data_size < PSA_PUBKEY_SIZE) {
+        return PSA_ERROR_BUFFER_TOO_SMALL;
+    }
+
+    /* See INFORMATION ON PSA KEY EXPORT FORMATS near top of file */
+    data[0] = PSA_PUBKEY_HEADER_BYTE;
+    int ret = p256_public_from_private(data + 1, key_buffer);
+    if (ret == P256_SUCCESS) {
+        *data_length = PSA_PUBKEY_SIZE;
+    }
+
+    return p256_to_psa_error(ret);
+}
+
+psa_status_t p256_transparent_generate_key(
+    const psa_key_attributes_t *attributes,
+    uint8_t *key_buffer,
+    size_t key_buffer_size,
+    size_t *key_buffer_length)
+{
+    /* We don't use this argument, but the specification mandates the signature
+     * of driver entry-points. (void) used to avoid compiler warning. */
+    (void) attributes;
+
+    /* Validate sizes, as p256-m expects fixed-size buffers */
+    if (key_buffer_size != PRIVKEY_SIZE) {
+        return PSA_ERROR_BUFFER_TOO_SMALL;
+    }
+
+    /*
+     *  p256-m's keypair generation function outputs both public and private
+     *  keys. Allocate a buffer to which the public key will be written. The
+     *  private key will be written to key_buffer, which is passed to this
+     *  function as an argument. */
+    uint8_t public_key_buffer[P256_PUBKEY_SIZE];
+
+    int ret = p256_gen_keypair(key_buffer, public_key_buffer);
+    if (ret == P256_SUCCESS) {
+        *key_buffer_length = PRIVKEY_SIZE;
+    }
+
+    return p256_to_psa_error(ret);
+}
+
+psa_status_t p256_transparent_key_agreement(
+    const psa_key_attributes_t *attributes,
+    const uint8_t *key_buffer,
+    size_t key_buffer_size,
+    psa_algorithm_t alg,
+    const uint8_t *peer_key,
+    size_t peer_key_length,
+    uint8_t *shared_secret,
+    size_t shared_secret_size,
+    size_t *shared_secret_length)
+{
+    /* We don't use these arguments, but the specification mandates the
+     * sginature of driver entry-points. (void) used to avoid compiler
+     * warning. */
+    (void) attributes;
+    (void) alg;
+
+    /* Validate sizes, as p256-m expects fixed-size buffers */
+    if (key_buffer_size != PRIVKEY_SIZE || peer_key_length != PSA_PUBKEY_SIZE) {
+        return PSA_ERROR_INVALID_ARGUMENT;
+    }
+    if (shared_secret_size < SHARED_SECRET_SIZE) {
+        return PSA_ERROR_BUFFER_TOO_SMALL;
+    }
+
+    /* See INFORMATION ON PSA KEY EXPORT FORMATS near top of file */
+    const uint8_t *peer_key_p256m = peer_key + 1;
+    int ret = p256_ecdh_shared_secret(shared_secret, key_buffer, peer_key_p256m);
+    if (ret == P256_SUCCESS) {
+        *shared_secret_length = SHARED_SECRET_SIZE;
+    }
+
+    return p256_to_psa_error(ret);
+}
+
+psa_status_t p256_transparent_sign_hash(
+    const psa_key_attributes_t *attributes,
+    const uint8_t *key_buffer,
+    size_t key_buffer_size,
+    psa_algorithm_t alg,
+    const uint8_t *hash,
+    size_t hash_length,
+    uint8_t *signature,
+    size_t signature_size,
+    size_t *signature_length)
+{
+    /* We don't use these arguments, but the specification mandates the
+     * sginature of driver entry-points. (void) used to avoid compiler
+     * warning. */
+    (void) attributes;
+    (void) alg;
+
+    /* Validate sizes, as p256-m expects fixed-size buffers */
+    if (key_buffer_size != PRIVKEY_SIZE) {
+        return PSA_ERROR_INVALID_ARGUMENT;
+    }
+    if (signature_size < SIGNATURE_SIZE) {
+        return PSA_ERROR_BUFFER_TOO_SMALL;
+    }
+
+    int ret = p256_ecdsa_sign(signature, key_buffer, hash, hash_length);
+    if (ret == P256_SUCCESS) {
+        *signature_length = SIGNATURE_SIZE;
+    }
+
+    return p256_to_psa_error(ret);
+}
+
+/*  This function expects the key buffer to contain a PSA public key,
+ *  as exported by psa_export_public_key() */
+static psa_status_t p256_verify_hash_with_public_key(
+    const uint8_t *key_buffer,
+    size_t key_buffer_size,
+    const uint8_t *hash,
+    size_t hash_length,
+    const uint8_t *signature,
+    size_t signature_length)
+{
+    /* Validate sizes, as p256-m expects fixed-size buffers */
+    if (key_buffer_size != PSA_PUBKEY_SIZE || *key_buffer != PSA_PUBKEY_HEADER_BYTE) {
+        return PSA_ERROR_INVALID_ARGUMENT;
+    }
+    if (signature_length != SIGNATURE_SIZE) {
+        return PSA_ERROR_INVALID_SIGNATURE;
+    }
+
+    /* See INFORMATION ON PSA KEY EXPORT FORMATS near top of file */
+    const uint8_t *public_key_p256m = key_buffer + 1;
+    int ret = p256_ecdsa_verify(signature, public_key_p256m, hash, hash_length);
+
+    return p256_to_psa_error(ret);
+}
+
+psa_status_t p256_transparent_verify_hash(
+    const psa_key_attributes_t *attributes,
+    const uint8_t *key_buffer,
+    size_t key_buffer_size,
+    psa_algorithm_t alg,
+    const uint8_t *hash,
+    size_t hash_length,
+    const uint8_t *signature,
+    size_t signature_length)
+{
+    /* We don't use this argument, but the specification mandates the signature
+     * of driver entry-points. (void) used to avoid compiler warning. */
+    (void) alg;
+
+    psa_status_t status;
+    uint8_t public_key_buffer[PSA_PUBKEY_SIZE];
+    size_t public_key_buffer_size = PSA_PUBKEY_SIZE;
+
+    size_t public_key_length = PSA_PUBKEY_SIZE;
+    /* As p256-m doesn't require dynamic allocation, we want to avoid it in
+     * the entrypoint functions as well. psa_driver_wrapper_export_public_key()
+     * requires size_t*, so we use a pointer to a stack variable. */
+    size_t *public_key_length_ptr = &public_key_length;
+
+    /* The contents of key_buffer may either be the 32 byte private key
+     * (keypair format), or 0x04 followed by the 64 byte public key (public
+     * key format). To ensure the key is in the latter format, the public key
+     * is exported. */
+    status = psa_driver_wrapper_export_public_key(
+        attributes,
+        key_buffer,
+        key_buffer_size,
+        public_key_buffer,
+        public_key_buffer_size,
+        public_key_length_ptr);
+    if (status != PSA_SUCCESS) {
+        goto exit;
+    }
+
+    status = p256_verify_hash_with_public_key(
+        public_key_buffer,
+        public_key_buffer_size,
+        hash,
+        hash_length,
+        signature,
+        signature_length);
+
+exit:
+    return status;
+}
+
+#endif /* MBEDTLS_PSA_P256M_DRIVER_ENABLED */
diff --git a/vendor/mbedtls/3rdparty/p256-m/p256-m_driver_entrypoints.h b/vendor/mbedtls/3rdparty/p256-m/p256-m_driver_entrypoints.h
new file mode 100644
index 0000000000..c740c4522d
--- /dev/null
+++ b/vendor/mbedtls/3rdparty/p256-m/p256-m_driver_entrypoints.h
@@ -0,0 +1,219 @@
+/*
+ *   Driver entry points for p256-m
+ */
+/*
+ *  Copyright The Mbed TLS Contributors
+ *  SPDX-License-Identifier: Apache-2.0 OR GPL-2.0-or-later
+ */
+
+#ifndef P256M_DRIVER_ENTRYPOINTS_H
+#define P256M_DRIVER_ENTRYPOINTS_H
+
+#if defined(MBEDTLS_PSA_P256M_DRIVER_ENABLED)
+#ifndef PSA_CRYPTO_ACCELERATOR_DRIVER_PRESENT
+#define PSA_CRYPTO_ACCELERATOR_DRIVER_PRESENT
+#endif /* PSA_CRYPTO_ACCELERATOR_DRIVER_PRESENT */
+#endif /* MBEDTLS_PSA_P256M_DRIVER_ENABLED */
+
+#include "psa/crypto_types.h"
+
+/** Import SECP256R1 key.
+ *
+ * \param[in]  attributes           The attributes of the key to use for the
+ *                                  operation.
+ * \param[in]  data                 The raw key material. For private keys
+ *                                  this must be a big-endian integer of 32
+ *                                  bytes; for public key this must be an
+ *                                  uncompressed ECPoint (65 bytes).
+ * \param[in]  data_length          The size of the raw key material.
+ * \param[out] key_buffer           The buffer to contain the key data in
+ *                                  output format upon successful return.
+ * \param[in]  key_buffer_size      Size of the \p key_buffer buffer in bytes.
+ * \param[out] key_buffer_length    The length of the data written in \p
+ *                                  key_buffer in bytes.
+ * \param[out] bits                 The bitsize of the key.
+ *
+ * \retval  #PSA_SUCCESS
+ *          Success. Keypair generated and stored in buffer.
+ * \retval  #PSA_ERROR_NOT_SUPPORTED
+ *          The input is not supported by this driver (not SECP256R1).
+ * \retval  #PSA_ERROR_INVALID_ARGUMENT
+ *          The input is invalid.
+ * \retval  #PSA_ERROR_BUFFER_TOO_SMALL
+ *          \p key_buffer_size is too small.
+ */
+psa_status_t p256_transparent_import_key(const psa_key_attributes_t *attributes,
+                             const uint8_t *data,
+                             size_t data_length,
+                             uint8_t *key_buffer,
+                             size_t key_buffer_size,
+                             size_t *key_buffer_length,
+                             size_t *bits);
+
+/** Export SECP256R1 public key, from the private key.
+ *
+ * \param[in]  attributes           The attributes of the key to use for the
+ *                                  operation.
+ * \param[in]  key_buffer           The private key in the export format.
+ * \param[in]  key_buffer_size      The size of the private key in bytes.
+ * \param[out] data                 The buffer to contain the public key in
+ *                                  the export format upon successful return.
+ * \param[in]  data_size            The size of the \p data buffer in bytes.
+ * \param[out] data_length          The length written to \p data in bytes.
+ *
+ * \retval  #PSA_SUCCESS
+ *          Success. Keypair generated and stored in buffer.
+ * \retval  #PSA_ERROR_NOT_SUPPORTED
+ *          The input is not supported by this driver (not SECP256R1).
+ * \retval  #PSA_ERROR_INVALID_ARGUMENT
+ *          The input is invalid.
+ * \retval  #PSA_ERROR_BUFFER_TOO_SMALL
+ *          \p key_buffer_size is too small.
+ */
+psa_status_t p256_transparent_export_public_key(const psa_key_attributes_t *attributes,
+                                    const uint8_t *key_buffer,
+                                    size_t key_buffer_size,
+                                    uint8_t *data,
+                                    size_t data_size,
+                                    size_t *data_length);
+
+/** Generate SECP256R1 ECC Key Pair.
+ *  Interface function which calls the p256-m key generation function and
+ *  places it in the key buffer provided by the caller (Mbed TLS) in the
+ *  correct format. For a SECP256R1 curve this is the 32 bit private key.
+ *
+ * \param[in]  attributes           The attributes of the key to use for the
+ *                                  operation.
+ * \param[out]  key_buffer          The buffer to contain the key data in
+ *                                  output format upon successful return.
+ * \param[in]   key_buffer_size     Size of the \p key_buffer buffer in bytes.
+ * \param[out]  key_buffer_length   The length of the data written in \p
+ *                                  key_buffer in bytes.
+ *
+ * \retval  #PSA_SUCCESS
+ *          Success. Keypair generated and stored in buffer.
+ * \retval  #PSA_ERROR_BUFFER_TOO_SMALL
+ *          \p key_buffer_size is too small.
+ * \retval  #PSA_ERROR_GENERIC_ERROR
+ *          The internal RNG failed.
+ */
+psa_status_t p256_transparent_generate_key(
+    const psa_key_attributes_t *attributes,
+    uint8_t *key_buffer,
+    size_t key_buffer_size,
+    size_t *key_buffer_length);
+
+/** Perform raw key agreement using p256-m's ECDH implementation
+ * \param[in]  attributes           The attributes of the key to use for the
+ *                                  operation.
+ * \param[in]  key_buffer           The buffer containing the private key
+ *                                  in the format specified by PSA.
+ * \param[in]  key_buffer_size      Size of the \p key_buffer buffer in bytes.
+ * \param[in]  alg                  A key agreement algorithm that is
+ *                                  compatible with the type of the key.
+ * \param[in]  peer_key             The buffer containing the peer's public
+ *                                  key in format specified by PSA.
+ * \param[in]  peer_key_length      Size of the \p peer_key buffer in
+ *                                  bytes.
+ * \param[out] shared_secret        The buffer to which the shared secret
+ *                                  is to be written.
+ * \param[in]  shared_secret_size   Size of the \p shared_secret buffer in
+ *                                  bytes.
+ * \param[out] shared_secret_length On success, the number of bytes that
+ *                                  make up the returned shared secret.
+ * \retval  #PSA_SUCCESS
+ *          Success. Shared secret successfully calculated.
+ * \retval  #PSA_ERROR_INVALID_ARGUMENT
+ *          The input is invalid.
+ * \retval  #PSA_ERROR_BUFFER_TOO_SMALL
+ *          \p shared_secret_size is too small.
+ */
+psa_status_t p256_transparent_key_agreement(
+    const psa_key_attributes_t *attributes,
+    const uint8_t *key_buffer,
+    size_t key_buffer_size,
+    psa_algorithm_t alg,
+    const uint8_t *peer_key,
+    size_t peer_key_length,
+    uint8_t *shared_secret,
+    size_t shared_secret_size,
+    size_t *shared_secret_length);
+
+/** Sign an already-calculated hash with a private key using p256-m's ECDSA
+ *  implementation
+ * \param[in]  attributes           The attributes of the key to use for the
+ *                                  operation.
+ * \param[in]  key_buffer           The buffer containing the private key
+ *                                  in the format specified by PSA.
+ * \param[in]  key_buffer_size      Size of the \p key_buffer buffer in bytes.
+ * \param[in]  alg                  A signature algorithm that is compatible
+ *                                  with the type of the key.
+ * \param[in]  hash                 The hash to sign.
+ * \param[in]  hash_length          Size of the \p hash buffer in bytes.
+ * \param[out] signature            Buffer where signature is to be written.
+ * \param[in]  signature_size       Size of the \p signature buffer in bytes.
+ * \param[out] signature_length     On success, the number of bytes
+ *                                  that make up the returned signature value.
+ *
+ * \retval  #PSA_SUCCESS
+ *          Success. Hash was signed successfully.
+ * \retval  #PSA_ERROR_INVALID_ARGUMENT
+ *          The input is invalid.
+ * \retval  #PSA_ERROR_BUFFER_TOO_SMALL
+ *          \p signature_size is too small.
+ * \retval  #PSA_ERROR_GENERIC_ERROR
+ *          The internal RNG failed.
+ */
+psa_status_t p256_transparent_sign_hash(
+    const psa_key_attributes_t *attributes,
+    const uint8_t *key_buffer,
+    size_t key_buffer_size,
+    psa_algorithm_t alg,
+    const uint8_t *hash,
+    size_t hash_length,
+    uint8_t *signature,
+    size_t signature_size,
+    size_t *signature_length);
+
+/** Verify the signature of a hash using a SECP256R1 public key using p256-m's
+ *  ECDSA implementation.
+ *
+ * \note p256-m expects a 64 byte public key, but the contents of the key
+         buffer may be the 32 byte keypair representation or the 65 byte
+         public key representation. As a result, this function calls
+         psa_driver_wrapper_export_public_key() to ensure the public key
+         can be passed to p256-m.
+ *
+ * \param[in]  attributes       The attributes of the key to use for the
+ *                              operation.
+ *
+ * \param[in]  key_buffer       The buffer containing the key
+ *                              in the format specified by PSA.
+ * \param[in]  key_buffer_size  Size of the \p key_buffer buffer in bytes.
+ * \param[in]  alg              A signature algorithm that is compatible with
+ *                              the type of the key.
+ * \param[in]  hash             The hash whose signature is to be
+ *                              verified.
+ * \param[in]  hash_length      Size of the \p hash buffer in bytes.
+ * \param[in]  signature        Buffer containing the signature to verify.
+ * \param[in]  signature_length Size of the \p signature buffer in bytes.
+ *
+ * \retval  #PSA_SUCCESS
+ *          The signature is valid.
+ * \retval  #PSA_ERROR_INVALID_SIGNATURE
+ *          The calculation was performed successfully, but the passed
+ *          signature is not a valid signature.
+ * \retval  #PSA_ERROR_INVALID_ARGUMENT
+ *          The input is invalid.
+ */
+psa_status_t p256_transparent_verify_hash(
+    const psa_key_attributes_t *attributes,
+    const uint8_t *key_buffer,
+    size_t key_buffer_size,
+    psa_algorithm_t alg,
+    const uint8_t *hash,
+    size_t hash_length,
+    const uint8_t *signature,
+    size_t signature_length);
+
+#endif /* P256M_DRIVER_ENTRYPOINTS_H */
diff --git a/vendor/mbedtls/LICENSE b/vendor/mbedtls/LICENSE
index d645695673..776ac77eaf 100644
--- a/vendor/mbedtls/LICENSE
+++ b/vendor/mbedtls/LICENSE
@@ -1,3 +1,10 @@
+Mbed TLS files are provided under a dual [Apache-2.0](https://spdx.org/licenses/Apache-2.0.html)
+OR [GPL-2.0-or-later](https://spdx.org/licenses/GPL-2.0-or-later.html) license.
+This means that users may choose which of these licenses they take the code
+under.
+
+The full text of each of these licenses is given below.
+
 
                                  Apache License
                            Version 2.0, January 2004
@@ -200,3 +207,347 @@
    WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
    See the License for the specific language governing permissions and
    limitations under the License.
+
+
+===============================================================================
+
+
+                    GNU GENERAL PUBLIC LICENSE
+                       Version 2, June 1991
+
+ Copyright (C) 1989, 1991 Free Software Foundation, Inc.,
+ 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
+ Everyone is permitted to copy and distribute verbatim copies
+ of this license document, but changing it is not allowed.
+
+                            Preamble
+
+  The licenses for most software are designed to take away your
+freedom to share and change it.  By contrast, the GNU General Public
+License is intended to guarantee your freedom to share and change free
+software--to make sure the software is free for all its users.  This
+General Public License applies to most of the Free Software
+Foundation's software and to any other program whose authors commit to
+using it.  (Some other Free Software Foundation software is covered by
+the GNU Lesser General Public License instead.)  You can apply it to
+your programs, too.
+
+  When we speak of free software, we are referring to freedom, not
+price.  Our General Public Licenses are designed to make sure that you
+have the freedom to distribute copies of free software (and charge for
+this service if you wish), that you receive source code or can get it
+if you want it, that you can change the software or use pieces of it
+in new free programs; and that you know you can do these things.
+
+  To protect your rights, we need to make restrictions that forbid
+anyone to deny you these rights or to ask you to surrender the rights.
+These restrictions translate to certain responsibilities for you if you
+distribute copies of the software, or if you modify it.
+
+  For example, if you distribute copies of such a program, whether
+gratis or for a fee, you must give the recipients all the rights that
+you have.  You must make sure that they, too, receive or can get the
+source code.  And you must show them these terms so they know their
+rights.
+
+  We protect your rights with two steps: (1) copyright the software, and
+(2) offer you this license which gives you legal permission to copy,
+distribute and/or modify the software.
+
+  Also, for each author's protection and ours, we want to make certain
+that everyone understands that there is no warranty for this free
+software.  If the software is modified by someone else and passed on, we
+want its recipients to know that what they have is not the original, so
+that any problems introduced by others will not reflect on the original
+authors' reputations.
+
+  Finally, any free program is threatened constantly by software
+patents.  We wish to avoid the danger that redistributors of a free
+program will individually obtain patent licenses, in effect making the
+program proprietary.  To prevent this, we have made it clear that any
+patent must be licensed for everyone's free use or not licensed at all.
+
+  The precise terms and conditions for copying, distribution and
+modification follow.
+
+                    GNU GENERAL PUBLIC LICENSE
+   TERMS AND CONDITIONS FOR COPYING, DISTRIBUTION AND MODIFICATION
+
+  0. This License applies to any program or other work which contains
+a notice placed by the copyright holder saying it may be distributed
+under the terms of this General Public License.  The "Program", below,
+refers to any such program or work, and a "work based on the Program"
+means either the Program or any derivative work under copyright law:
+that is to say, a work containing the Program or a portion of it,
+either verbatim or with modifications and/or translated into another
+language.  (Hereinafter, translation is included without limitation in
+the term "modification".)  Each licensee is addressed as "you".
+
+Activities other than copying, distribution and modification are not
+covered by this License; they are outside its scope.  The act of
+running the Program is not restricted, and the output from the Program
+is covered only if its contents constitute a work based on the
+Program (independent of having been made by running the Program).
+Whether that is true depends on what the Program does.
+
+  1. You may copy and distribute verbatim copies of the Program's
+source code as you receive it, in any medium, provided that you
+conspicuously and appropriately publish on each copy an appropriate
+copyright notice and disclaimer of warranty; keep intact all the
+notices that refer to this License and to the absence of any warranty;
+and give any other recipients of the Program a copy of this License
+along with the Program.
+
+You may charge a fee for the physical act of transferring a copy, and
+you may at your option offer warranty protection in exchange for a fee.
+
+  2. You may modify your copy or copies of the Program or any portion
+of it, thus forming a work based on the Program, and copy and
+distribute such modifications or work under the terms of Section 1
+above, provided that you also meet all of these conditions:
+
+    a) You must cause the modified files to carry prominent notices
+    stating that you changed the files and the date of any change.
+
+    b) You must cause any work that you distribute or publish, that in
+    whole or in part contains or is derived from the Program or any
+    part thereof, to be licensed as a whole at no charge to all third
+    parties under the terms of this License.
+
+    c) If the modified program normally reads commands interactively
+    when run, you must cause it, when started running for such
+    interactive use in the most ordinary way, to print or display an
+    announcement including an appropriate copyright notice and a
+    notice that there is no warranty (or else, saying that you provide
+    a warranty) and that users may redistribute the program under
+    these conditions, and telling the user how to view a copy of this
+    License.  (Exception: if the Program itself is interactive but
+    does not normally print such an announcement, your work based on
+    the Program is not required to print an announcement.)
+
+These requirements apply to the modified work as a whole.  If
+identifiable sections of that work are not derived from the Program,
+and can be reasonably considered independent and separate works in
+themselves, then this License, and its terms, do not apply to those
+sections when you distribute them as separate works.  But when you
+distribute the same sections as part of a whole which is a work based
+on the Program, the distribution of the whole must be on the terms of
+this License, whose permissions for other licensees extend to the
+entire whole, and thus to each and every part regardless of who wrote it.
+
+Thus, it is not the intent of this section to claim rights or contest
+your rights to work written entirely by you; rather, the intent is to
+exercise the right to control the distribution of derivative or
+collective works based on the Program.
+
+In addition, mere aggregation of another work not based on the Program
+with the Program (or with a work based on the Program) on a volume of
+a storage or distribution medium does not bring the other work under
+the scope of this License.
+
+  3. You may copy and distribute the Program (or a work based on it,
+under Section 2) in object code or executable form under the terms of
+Sections 1 and 2 above provided that you also do one of the following:
+
+    a) Accompany it with the complete corresponding machine-readable
+    source code, which must be distributed under the terms of Sections
+    1 and 2 above on a medium customarily used for software interchange; or,
+
+    b) Accompany it with a written offer, valid for at least three
+    years, to give any third party, for a charge no more than your
+    cost of physically performing source distribution, a complete
+    machine-readable copy of the corresponding source code, to be
+    distributed under the terms of Sections 1 and 2 above on a medium
+    customarily used for software interchange; or,
+
+    c) Accompany it with the information you received as to the offer
+    to distribute corresponding source code.  (This alternative is
+    allowed only for noncommercial distribution and only if you
+    received the program in object code or executable form with such
+    an offer, in accord with Subsection b above.)
+
+The source code for a work means the preferred form of the work for
+making modifications to it.  For an executable work, complete source
+code means all the source code for all modules it contains, plus any
+associated interface definition files, plus the scripts used to
+control compilation and installation of the executable.  However, as a
+special exception, the source code distributed need not include
+anything that is normally distributed (in either source or binary
+form) with the major components (compiler, kernel, and so on) of the
+operating system on which the executable runs, unless that component
+itself accompanies the executable.
+
+If distribution of executable or object code is made by offering
+access to copy from a designated place, then offering equivalent
+access to copy the source code from the same place counts as
+distribution of the source code, even though third parties are not
+compelled to copy the source along with the object code.
+
+  4. You may not copy, modify, sublicense, or distribute the Program
+except as expressly provided under this License.  Any attempt
+otherwise to copy, modify, sublicense or distribute the Program is
+void, and will automatically terminate your rights under this License.
+However, parties who have received copies, or rights, from you under
+this License will not have their licenses terminated so long as such
+parties remain in full compliance.
+
+  5. You are not required to accept this License, since you have not
+signed it.  However, nothing else grants you permission to modify or
+distribute the Program or its derivative works.  These actions are
+prohibited by law if you do not accept this License.  Therefore, by
+modifying or distributing the Program (or any work based on the
+Program), you indicate your acceptance of this License to do so, and
+all its terms and conditions for copying, distributing or modifying
+the Program or works based on it.
+
+  6. Each time you redistribute the Program (or any work based on the
+Program), the recipient automatically receives a license from the
+original licensor to copy, distribute or modify the Program subject to
+these terms and conditions.  You may not impose any further
+restrictions on the recipients' exercise of the rights granted herein.
+You are not responsible for enforcing compliance by third parties to
+this License.
+
+  7. If, as a consequence of a court judgment or allegation of patent
+infringement or for any other reason (not limited to patent issues),
+conditions are imposed on you (whether by court order, agreement or
+otherwise) that contradict the conditions of this License, they do not
+excuse you from the conditions of this License.  If you cannot
+distribute so as to satisfy simultaneously your obligations under this
+License and any other pertinent obligations, then as a consequence you
+may not distribute the Program at all.  For example, if a patent
+license would not permit royalty-free redistribution of the Program by
+all those who receive copies directly or indirectly through you, then
+the only way you could satisfy both it and this License would be to
+refrain entirely from distribution of the Program.
+
+If any portion of this section is held invalid or unenforceable under
+any particular circumstance, the balance of the section is intended to
+apply and the section as a whole is intended to apply in other
+circumstances.
+
+It is not the purpose of this section to induce you to infringe any
+patents or other property right claims or to contest validity of any
+such claims; this section has the sole purpose of protecting the
+integrity of the free software distribution system, which is
+implemented by public license practices.  Many people have made
+generous contributions to the wide range of software distributed
+through that system in reliance on consistent application of that
+system; it is up to the author/donor to decide if he or she is willing
+to distribute software through any other system and a licensee cannot
+impose that choice.
+
+This section is intended to make thoroughly clear what is believed to
+be a consequence of the rest of this License.
+
+  8. If the distribution and/or use of the Program is restricted in
+certain countries either by patents or by copyrighted interfaces, the
+original copyright holder who places the Program under this License
+may add an explicit geographical distribution limitation excluding
+those countries, so that distribution is permitted only in or among
+countries not thus excluded.  In such case, this License incorporates
+the limitation as if written in the body of this License.
+
+  9. The Free Software Foundation may publish revised and/or new versions
+of the General Public License from time to time.  Such new versions will
+be similar in spirit to the present version, but may differ in detail to
+address new problems or concerns.
+
+Each version is given a distinguishing version number.  If the Program
+specifies a version number of this License which applies to it and "any
+later version", you have the option of following the terms and conditions
+either of that version or of any later version published by the Free
+Software Foundation.  If the Program does not specify a version number of
+this License, you may choose any version ever published by the Free Software
+Foundation.
+
+  10. If you wish to incorporate parts of the Program into other free
+programs whose distribution conditions are different, write to the author
+to ask for permission.  For software which is copyrighted by the Free
+Software Foundation, write to the Free Software Foundation; we sometimes
+make exceptions for this.  Our decision will be guided by the two goals
+of preserving the free status of all derivatives of our free software and
+of promoting the sharing and reuse of software generally.
+
+                            NO WARRANTY
+
+  11. BECAUSE THE PROGRAM IS LICENSED FREE OF CHARGE, THERE IS NO WARRANTY
+FOR THE PROGRAM, TO THE EXTENT PERMITTED BY APPLICABLE LAW.  EXCEPT WHEN
+OTHERWISE STATED IN WRITING THE COPYRIGHT HOLDERS AND/OR OTHER PARTIES
+PROVIDE THE PROGRAM "AS IS" WITHOUT WARRANTY OF ANY KIND, EITHER EXPRESSED
+OR IMPLIED, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
+MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE.  THE ENTIRE RISK AS
+TO THE QUALITY AND PERFORMANCE OF THE PROGRAM IS WITH YOU.  SHOULD THE
+PROGRAM PROVE DEFECTIVE, YOU ASSUME THE COST OF ALL NECESSARY SERVICING,
+REPAIR OR CORRECTION.
+
+  12. IN NO EVENT UNLESS REQUIRED BY APPLICABLE LAW OR AGREED TO IN WRITING
+WILL ANY COPYRIGHT HOLDER, OR ANY OTHER PARTY WHO MAY MODIFY AND/OR
+REDISTRIBUTE THE PROGRAM AS PERMITTED ABOVE, BE LIABLE TO YOU FOR DAMAGES,
+INCLUDING ANY GENERAL, SPECIAL, INCIDENTAL OR CONSEQUENTIAL DAMAGES ARISING
+OUT OF THE USE OR INABILITY TO USE THE PROGRAM (INCLUDING BUT NOT LIMITED
+TO LOSS OF DATA OR DATA BEING RENDERED INACCURATE OR LOSSES SUSTAINED BY
+YOU OR THIRD PARTIES OR A FAILURE OF THE PROGRAM TO OPERATE WITH ANY OTHER
+PROGRAMS), EVEN IF SUCH HOLDER OR OTHER PARTY HAS BEEN ADVISED OF THE
+POSSIBILITY OF SUCH DAMAGES.
+
+                     END OF TERMS AND CONDITIONS
+
+            How to Apply These Terms to Your New Programs
+
+  If you develop a new program, and you want it to be of the greatest
+possible use to the public, the best way to achieve this is to make it
+free software which everyone can redistribute and change under these terms.
+
+  To do so, attach the following notices to the program.  It is safest
+to attach them to the start of each source file to most effectively
+convey the exclusion of warranty; and each file should have at least
+the "copyright" line and a pointer to where the full notice is found.
+
+    
+    Copyright (C)   
+
+    This program is free software; you can redistribute it and/or modify
+    it under the terms of the GNU General Public License as published by
+    the Free Software Foundation; either version 2 of the License, or
+    (at your option) any later version.
+
+    This program is distributed in the hope that it will be useful,
+    but WITHOUT ANY WARRANTY; without even the implied warranty of
+    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+    GNU General Public License for more details.
+
+    You should have received a copy of the GNU General Public License along
+    with this program; if not, write to the Free Software Foundation, Inc.,
+    51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
+
+Also add information on how to contact you by electronic and paper mail.
+
+If the program is interactive, make it output a short notice like this
+when it starts in an interactive mode:
+
+    Gnomovision version 69, Copyright (C) year name of author
+    Gnomovision comes with ABSOLUTELY NO WARRANTY; for details type `show w'.
+    This is free software, and you are welcome to redistribute it
+    under certain conditions; type `show c' for details.
+
+The hypothetical commands `show w' and `show c' should show the appropriate
+parts of the General Public License.  Of course, the commands you use may
+be called something other than `show w' and `show c'; they could even be
+mouse-clicks or menu items--whatever suits your program.
+
+You should also get your employer (if you work as a programmer) or your
+school, if any, to sign a "copyright disclaimer" for the program, if
+necessary.  Here is a sample; alter the names:
+
+  Yoyodyne, Inc., hereby disclaims all copyright interest in the program
+  `Gnomovision' (which makes passes at compilers) written by James Hacker.
+
+  , 1 April 1989
+  Ty Coon, President of Vice
+
+This General Public License does not permit incorporating your program into
+proprietary programs.  If your program is a subroutine library, you may
+consider it more useful to permit linking proprietary applications with the
+library.  If this is what you want to do, use the GNU Lesser General
+Public License instead of this License.
diff --git a/vendor/mbedtls/README.md b/vendor/mbedtls/README.md
index 875e6bf350..b70c67e030 100644
--- a/vendor/mbedtls/README.md
+++ b/vendor/mbedtls/README.md
@@ -8,7 +8,7 @@ Mbed TLS includes a reference implementation of the [PSA Cryptography API](#psa-
 Configuration
 -------------
 
-Mbed TLS should build out of the box on most systems. Some platform specific options are available in the fully documented configuration file `include/mbedtls/config.h`, which is also the place where features can be selected. This file can be edited manually, or in a more programmatic way using the Python 3 script `scripts/config.py` (use `--help` for usage instructions).
+Mbed TLS should build out of the box on most systems. Some platform specific options are available in the fully documented configuration file `include/mbedtls/mbedtls_config.h`, which is also the place where features can be selected. This file can be edited manually, or in a more programmatic way using the Python 3 script `scripts/config.py` (use `--help` for usage instructions).
 
 Compiler options can be set using conventional environment variables such as `CC` and `CFLAGS` when using the Make and CMake build system (see below).
 
@@ -23,7 +23,7 @@ Documentation for the PSA Cryptography API is available [on GitHub](https://arm-
 
 To generate a local copy of the library documentation in HTML format, tailored to your compile-time configuration:
 
-1. Make sure that [Doxygen](http://www.doxygen.nl/) is installed. We use version 1.8.11 but slightly older or more recent versions should work.
+1. Make sure that [Doxygen](http://www.doxygen.nl/) is installed.
 1. Run `make apidoc`.
 1. Browse `apidoc/index.html` or `apidoc/modules.html`.
 
@@ -36,7 +36,7 @@ There are currently three active build systems used within Mbed TLS releases:
 
 -   GNU Make
 -   CMake
--   Microsoft Visual Studio (Microsoft Visual Studio 2013 or later)
+-   Microsoft Visual Studio
 
 The main systems used for development are CMake and GNU Make. Those systems are always complete and up-to-date. The others should reflect all changes present in the CMake and Make build system, although features may not be ported there automatically.
 
@@ -46,10 +46,41 @@ The Make and CMake build systems create three libraries: libmbedcrypto, libmbedx
 
 You need the following tools to build the library with the provided makefiles:
 
-* GNU Make or a build tool that CMake supports.
-* A C99 toolchain (compiler, linker, archiver). We actively test with GCC 5.4, Clang 3.8, IAR8 and Visual Studio 2013. More recent versions should work. Slightly older versions may work.
-* Python 3.6 or later to generate the test code.
-* Perl to run the tests.
+* GNU Make 3.82 or a build tool that CMake supports.
+* A C99 toolchain (compiler, linker, archiver). We actively test with GCC 5.4, Clang 3.8, Arm Compiler 6, IAR 8 and Visual Studio 2017. More recent versions should work. Slightly older versions may work.
+* Python 3.8 to generate the test code. Python is also needed to integrate PSA drivers and to build the development branch (see next section).
+* Perl to run the tests, and to generate some source files in the development branch.
+* CMake 3.10.2 or later (if using CMake).
+* Microsoft Visual Studio 2017 or later (if using Visual Studio).
+* Doxygen 1.8.11 or later (if building the documentation; slightly older versions should work).
+
+### Git usage
+
+The `development` branch and the `mbedtls-3.6` long-term support branch of Mbed TLS use a [Git submodule](https://git-scm.com/book/en/v2/Git-Tools-Submodules#_cloning_submodules) ([framework](https://github.com/Mbed-TLS/mbedtls-framework)). This is not needed to merely compile the library at a release tag. This is not needed to consume a release archive (zip or tar).
+
+### Generated source files in the development branch
+
+The source code of Mbed TLS includes some files that are automatically generated by scripts and whose content depends only on the Mbed TLS source, not on the platform or on the library configuration. These files are not included in the development branch of Mbed TLS, but the generated files are included in official releases. This section explains how to generate the missing files in the development branch.
+
+The following tools are required:
+
+* Perl, for some library source files and for Visual Studio build files.
+* Python 3.8 and some Python packages, for some library source files, sample programs and test data. To install the necessary packages, run:
+    ```
+    python3 -m pip install --user -r scripts/basic.requirements.txt
+    ```
+    Depending on your Python installation, you may need to invoke `python` instead of `python3`. To install the packages system-wide, omit the `--user` option.
+* A C compiler for the host platform, for some test data.
+
+If you are cross-compiling, you must set the `CC` environment variable to a C compiler for the host platform when generating the configuration-independent files.
+
+Any of the following methods are available to generate the configuration-independent files:
+
+* If not cross-compiling, running `make` with any target, or just `make`, will automatically generate required files.
+* On non-Windows systems, when not cross-compiling, CMake will generate the required files automatically.
+* Run `make generated_files` to generate all the configuration-independent files.
+* On Unix/POSIX systems, run `tests/scripts/check-generated-files.sh -u` to generate all the configuration-independent files.
+* On Windows, run `scripts\make_generated_files.bat` to generate all the configuration-independent files.
 
 ### Make
 
@@ -159,6 +190,33 @@ Regarding variables, also note that if you set CFLAGS when invoking cmake,
 your value of CFLAGS doesn't override the content provided by cmake (depending
 on the build mode as seen above), it's merely prepended to it.
 
+#### Consuming Mbed TLS
+
+Mbed TLS provides a package config file for consumption as a dependency in other
+CMake projects. You can include Mbed TLS's CMake targets yourself with:
+
+    find_package(MbedTLS)
+
+If prompted, set `MbedTLS_DIR` to `${YOUR_MBEDTLS_INSTALL_DIR}/cmake`. This
+creates the following targets:
+
+- `MbedTLS::mbedcrypto` (Crypto library)
+- `MbedTLS::mbedtls` (TLS library)
+- `MbedTLS::mbedx509` (X509 library)
+
+You can then use these directly through `target_link_libraries()`:
+
+    add_executable(xyz)
+
+    target_link_libraries(xyz
+        PUBLIC MbedTLS::mbedtls
+               MbedTLS::mbedcrypto
+               MbedTLS::mbedx509)
+
+This will link the Mbed TLS libraries to your library or application, and add
+its include directories to your target (transitively, in the case of `PUBLIC` or
+`INTERFACE` link libraries).
+
 #### Mbed TLS as a subproject
 
 Mbed TLS supports being built as a CMake subproject. One can
@@ -167,10 +225,12 @@ subproject.
 
 ### Microsoft Visual Studio
 
-The build files for Microsoft Visual Studio are generated for Visual Studio 2010.
+The build files for Microsoft Visual Studio are generated for Visual Studio 2017.
 
 The solution file `mbedTLS.sln` contains all the basic projects needed to build the library and all the programs. The files in tests are not generated and compiled, as these need Python and perl environments as well. However, the selftest program in `programs/test/` is still available.
 
+In the development branch of Mbed TLS, the Visual Studio solution files need to be generated first as described in [“Generated source files in the development branch”](#generated-source-files-in-the-development-branch).
+
 Example programs
 ----------------
 
@@ -188,9 +248,9 @@ For machines with a Unix shell and OpenSSL (and optionally GnuTLS) installed, ad
 -   `tests/compat.sh` tests interoperability of every ciphersuite with other implementations.
 -   `tests/scripts/test-ref-configs.pl` test builds in various reduced configurations.
 -   `tests/scripts/depends.py` test builds in configurations with a single curve, key exchange, hash, cipher, or pkalg on.
--   `tests/scripts/all.sh` runs a combination of the above tests, plus some more, with various build options (such as ASan, full `config.h`, etc).
+-   `tests/scripts/all.sh` runs a combination of the above tests, plus some more, with various build options (such as ASan, full `mbedtls_config.h`, etc).
 
-Instead of manually installing the required versions of all tools required for testing, it is possible to use the Docker images from our CI systems, as explained in [our testing infrastructure repository](https://github.com/Mbed-TLS/mbedtls-test/blob/master/README.md#quick-start).
+Instead of manually installing the required versions of all tools required for testing, it is possible to use the Docker images from our CI systems, as explained in [our testing infrastructure repository](https://github.com/Mbed-TLS/mbedtls-test/blob/main/README.md#quick-start).
 
 Porting Mbed TLS
 ----------------
@@ -208,6 +268,8 @@ Mbed TLS is mostly written in portable C99; however, it has a few platform requi
 - Signed integers must be represented using two's complement.
 - `int` and `size_t` must be at least 32 bits wide.
 - The types `uint8_t`, `uint16_t`, `uint32_t` and their signed equivalents must be available.
+- Mixed-endian platforms are not supported.
+- SIZE_MAX must be at least as big as INT_MAX and UINT_MAX.
 
 PSA cryptography API
 --------------------
@@ -231,25 +293,32 @@ Arm welcomes feedback on the design of the API. If you think something could be
 ### PSA implementation in Mbed TLS
 
 Mbed TLS includes a reference implementation of the PSA Cryptography API.
-This implementation is not yet as mature as the rest of the library. Some parts of the code have not been reviewed as thoroughly, and some parts of the PSA implementation are not yet well optimized for code size.
+However, it does not aim to implement the whole specification; in particular it does not implement all the algorithms.
+
+The X.509 and TLS code can use PSA cryptography for most operations. To enable this support, activate the compilation option `MBEDTLS_USE_PSA_CRYPTO` in `mbedtls_config.h`. Note that TLS 1.3 uses PSA cryptography for most operations regardless of this option. See `docs/use-psa-crypto.md` for details.
 
-The X.509 and TLS code can use PSA cryptography for a limited subset of operations. To enable this support, activate the compilation option `MBEDTLS_USE_PSA_CRYPTO` in `config.h`.
+### PSA drivers
 
-There are currently a few deviations where the library does not yet implement the latest version of the specification. Please refer to the [compliance issues on Github](https://github.com/Mbed-TLS/mbed-crypto/labels/compliance) for an up-to-date list.
+Mbed TLS supports drivers for cryptographic accelerators, secure elements and random generators. This is work in progress. Please note that the driver interfaces are not fully stable yet and may change without notice. We intend to preserve backward compatibility for application code (using the PSA Crypto API), but the code of the drivers may have to change in future minor releases of Mbed TLS.
 
-### Upcoming features
+Please see the [PSA driver example and guide](docs/psa-driver-example-and-guide.md) for information on writing a driver.
 
-Future releases of this library will include:
+When using drivers, you will generally want to enable two compilation options (see the reference manual for more information):
 
-* A driver programming interface, which makes it possible to use hardware accelerators instead of the default software implementation for chosen algorithms.
-* Support for external keys to be stored and manipulated exclusively in a separate cryptoprocessor.
-* A configuration mechanism to compile only the algorithms you need for your application.
-* A wider set of cryptographic algorithms.
+* `MBEDTLS_USE_PSA_CRYPTO` is necessary so that the X.509 and TLS code calls the PSA drivers rather than the built-in software implementation.
+* `MBEDTLS_PSA_CRYPTO_CONFIG` allows you to enable PSA cryptographic mechanisms without including the code of the corresponding software implementation. This is not yet supported for all mechanisms.
 
 License
 -------
 
-Unless specifically indicated otherwise in a file, Mbed TLS files are provided under the [Apache-2.0](https://spdx.org/licenses/Apache-2.0.html) license. See the [LICENSE](LICENSE) file for the full text of this license, and [the 'License and Copyright' section in the contributing guidelines](CONTRIBUTING.md#License-and-Copyright) for more information.
+Unless specifically indicated otherwise in a file, Mbed TLS files are provided under a dual [Apache-2.0](https://spdx.org/licenses/Apache-2.0.html) OR [GPL-2.0-or-later](https://spdx.org/licenses/GPL-2.0-or-later.html) license. See the [LICENSE](LICENSE) file for the full text of these licenses, and [the 'License and Copyright' section in the contributing guidelines](CONTRIBUTING.md#License-and-Copyright) for more information.
+
+### Third-party code included in Mbed TLS
+
+This project contains code from other projects. This code is located within the `3rdparty/` directory. The original license text is included within project subdirectories, where it differs from the normal Mbed TLS license, and/or in source files. The projects are listed below:
+
+* `3rdparty/everest/`: Files stem from [Project Everest](https://project-everest.github.io/) and are distributed under the Apache 2.0 license.
+* `3rdparty/p256-m/p256-m/`: Files have been taken from the [p256-m](https://github.com/mpg/p256-m) repository. The code in the original repository is distributed under the Apache 2.0 license. It is distributed in Mbed TLS under a dual Apache-2.0 OR GPL-2.0-or-later license with permission from the author.
 
 Contributing
 ------------
diff --git a/vendor/mbedtls/configs/README.txt b/vendor/mbedtls/configs/README.txt
deleted file mode 100644
index d2f9bcb008..0000000000
--- a/vendor/mbedtls/configs/README.txt
+++ /dev/null
@@ -1,26 +0,0 @@
-This directory contains example configuration files.
-
-The examples are generally focused on a particular usage case (eg, support for
-a restricted number of ciphersuites) and aim at minimizing resource usage for
-this target. They can be used as a basis for custom configurations.
-
-These files are complete replacements for the default config.h. To use one of
-them, you can pick one of the following methods:
-
-1. Replace the default file include/mbedtls/config.h with the chosen one.
-   (Depending on your compiler, you may need to adjust the line with
-   #include "mbedtls/check_config.h" then.)
-
-2. Define MBEDTLS_CONFIG_FILE and adjust the include path accordingly.
-   For example, using make:
-
-    CFLAGS="-I$PWD/configs -DMBEDTLS_CONFIG_FILE=''" make
-
-   Or, using cmake:
-
-    find . -iname '*cmake*' -not -name CMakeLists.txt -exec rm -rf {} +
-    CFLAGS="-I$PWD/configs -DMBEDTLS_CONFIG_FILE=''" cmake .
-    make
-
-Note that the second method also works if you want to keep your custom
-configuration file outside the Mbed TLS tree.
diff --git a/vendor/mbedtls/configs/config-ccm-psk-dtls1_2.h b/vendor/mbedtls/configs/config-ccm-psk-dtls1_2.h
index 5d7e663d65..19e09d957f 100644
--- a/vendor/mbedtls/configs/config-ccm-psk-dtls1_2.h
+++ b/vendor/mbedtls/configs/config-ccm-psk-dtls1_2.h
@@ -5,19 +5,7 @@
  */
 /*
  *  Copyright The Mbed TLS Contributors
- *  SPDX-License-Identifier: Apache-2.0
- *
- *  Licensed under the Apache License, Version 2.0 (the "License"); you may
- *  not use this file except in compliance with the License.
- *  You may obtain a copy of the License at
- *
- *  http://www.apache.org/licenses/LICENSE-2.0
- *
- *  Unless required by applicable law or agreed to in writing, software
- *  distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
- *  WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- *  See the License for the specific language governing permissions and
- *  limitations under the License.
+ *  SPDX-License-Identifier: Apache-2.0 OR GPL-2.0-or-later
  */
 /*
  * Minimal configuration for DTLS 1.2 with PSK and AES-CCM ciphersuites
@@ -34,8 +22,6 @@
  *
  * See README.txt for usage instructions.
  */
-#ifndef MBEDTLS_CONFIG_H
-#define MBEDTLS_CONFIG_H
 
 /* System support */
 //#define MBEDTLS_HAVE_TIME /* Optionally used in Hello messages */
@@ -61,7 +47,6 @@
 #define MBEDTLS_SSL_PROTO_TLS1_2
 #define MBEDTLS_SSL_PROTO_DTLS
 #define MBEDTLS_SSL_DTLS_ANTI_REPLAY
-#define MBEDTLS_SSL_DTLS_BADMAC_LIMIT
 #define MBEDTLS_SSL_DTLS_CLIENT_PORT_REUSE
 #define MBEDTLS_SSL_DTLS_CONNECTION_ID
 #define MBEDTLS_SSL_DTLS_HELLO_VERIFY
@@ -80,7 +65,8 @@
  * both ends of the connection!  (See comments in "mbedtls/ssl.h".)
  * The optimal size here depends on the typical size of records.
  */
-#define MBEDTLS_SSL_MAX_CONTENT_LEN             256
+#define MBEDTLS_SSL_IN_CONTENT_LEN              256
+#define MBEDTLS_SSL_OUT_CONTENT_LEN             256
 
 /* Save RAM at the expense of ROM */
 #define MBEDTLS_AES_ROM_TABLES
@@ -90,10 +76,10 @@
 
 /*
  * You should adjust this to the exact number of sources you're using: default
- * is the "platform_entropy_poll" source plus a weak clock source, but you may
- * want to add other ones. Minimum is 3 for the entropy test suite.
+ * is the "platform_entropy_poll" source, but you may want to add other ones
+ * Minimum is 2 for the entropy test suite.
  */
-#define MBEDTLS_ENTROPY_MAX_SOURCES 3
+#define MBEDTLS_ENTROPY_MAX_SOURCES 2
 
 /* These defines are present so that the config modifying scripts can enable
  * them during tests/scripts/test-ref-configs.pl */
@@ -104,7 +90,3 @@
  * (huge code size increase, needed for tests/ssl-opt.sh) */
 //#define MBEDTLS_DEBUG_C
 //#define MBEDTLS_ERROR_C
-
-#include "mbedtls/check_config.h"
-
-#endif /* MBEDTLS_CONFIG_H */
diff --git a/vendor/mbedtls/configs/config-ccm-psk-tls1_2.h b/vendor/mbedtls/configs/config-ccm-psk-tls1_2.h
index 1aa52a7cbc..d49adfd725 100644
--- a/vendor/mbedtls/configs/config-ccm-psk-tls1_2.h
+++ b/vendor/mbedtls/configs/config-ccm-psk-tls1_2.h
@@ -5,19 +5,7 @@
  */
 /*
  *  Copyright The Mbed TLS Contributors
- *  SPDX-License-Identifier: Apache-2.0
- *
- *  Licensed under the Apache License, Version 2.0 (the "License"); you may
- *  not use this file except in compliance with the License.
- *  You may obtain a copy of the License at
- *
- *  http://www.apache.org/licenses/LICENSE-2.0
- *
- *  Unless required by applicable law or agreed to in writing, software
- *  distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
- *  WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- *  See the License for the specific language governing permissions and
- *  limitations under the License.
+ *  SPDX-License-Identifier: Apache-2.0 OR GPL-2.0-or-later
  */
 /*
  * Minimal configuration for TLS 1.2 with PSK and AES-CCM ciphersuites
@@ -33,8 +21,6 @@
  *
  * See README.txt for usage instructions.
  */
-#ifndef MBEDTLS_CONFIG_H
-#define MBEDTLS_CONFIG_H
 
 /* System support */
 //#define MBEDTLS_HAVE_TIME /* Optionally used in Hello messages */
@@ -70,7 +56,8 @@
  * both ends of the connection!  (See comments in "mbedtls/ssl.h".)
  * The optimal size here depends on the typical size of records.
  */
-#define MBEDTLS_SSL_MAX_CONTENT_LEN             1024
+#define MBEDTLS_SSL_IN_CONTENT_LEN              1024
+#define MBEDTLS_SSL_OUT_CONTENT_LEN             1024
 
 /* Save RAM at the expense of ROM */
 #define MBEDTLS_AES_ROM_TABLES
@@ -94,7 +81,3 @@
  * (huge code size increase, needed for tests/ssl-opt.sh) */
 //#define MBEDTLS_DEBUG_C
 //#define MBEDTLS_ERROR_C
-
-#include "mbedtls/check_config.h"
-
-#endif /* MBEDTLS_CONFIG_H */
diff --git a/vendor/mbedtls/configs/config-mini-tls1_1.h b/vendor/mbedtls/configs/config-mini-tls1_1.h
deleted file mode 100644
index 318e0fba8b..0000000000
--- a/vendor/mbedtls/configs/config-mini-tls1_1.h
+++ /dev/null
@@ -1,90 +0,0 @@
-/**
- * \file config-mini-tls1_1.h
- *
- * \brief Minimal configuration for TLS 1.1 (RFC 4346)
- */
-/*
- *  Copyright The Mbed TLS Contributors
- *  SPDX-License-Identifier: Apache-2.0
- *
- *  Licensed under the Apache License, Version 2.0 (the "License"); you may
- *  not use this file except in compliance with the License.
- *  You may obtain a copy of the License at
- *
- *  http://www.apache.org/licenses/LICENSE-2.0
- *
- *  Unless required by applicable law or agreed to in writing, software
- *  distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
- *  WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- *  See the License for the specific language governing permissions and
- *  limitations under the License.
- */
-/*
- * Minimal configuration for TLS 1.1 (RFC 4346), implementing only the
- * required ciphersuite: MBEDTLS_TLS_RSA_WITH_3DES_EDE_CBC_SHA
- *
- * See README.txt for usage instructions.
- */
-
-#ifndef MBEDTLS_CONFIG_H
-#define MBEDTLS_CONFIG_H
-
-/* System support */
-#define MBEDTLS_HAVE_ASM
-#define MBEDTLS_HAVE_TIME
-
-/* Mbed TLS feature support */
-#define MBEDTLS_CIPHER_MODE_CBC
-#define MBEDTLS_PKCS1_V15
-#define MBEDTLS_KEY_EXCHANGE_RSA_ENABLED
-#define MBEDTLS_SSL_PROTO_TLS1_1
-
-/* Mbed TLS modules */
-#define MBEDTLS_AES_C
-#define MBEDTLS_ASN1_PARSE_C
-#define MBEDTLS_ASN1_WRITE_C
-#define MBEDTLS_BIGNUM_C
-#define MBEDTLS_CIPHER_C
-#define MBEDTLS_CTR_DRBG_C
-#define MBEDTLS_DES_C
-#define MBEDTLS_ENTROPY_C
-#define MBEDTLS_MD_C
-#define MBEDTLS_MD5_C
-#define MBEDTLS_NET_C
-#define MBEDTLS_OID_C
-#define MBEDTLS_PK_C
-#define MBEDTLS_PK_PARSE_C
-#define MBEDTLS_RSA_C
-#define MBEDTLS_SHA1_C
-#define MBEDTLS_SHA256_C
-#define MBEDTLS_SSL_CLI_C
-#define MBEDTLS_SSL_SRV_C
-#define MBEDTLS_SSL_TLS_C
-#define MBEDTLS_X509_CRT_PARSE_C
-#define MBEDTLS_X509_USE_C
-
-/* For test certificates */
-#define MBEDTLS_BASE64_C
-#define MBEDTLS_CERTS_C
-#define MBEDTLS_PEM_PARSE_C
-
-/* For testing with compat.sh */
-#define MBEDTLS_FS_IO
-
-/* These defines are present so that the config modifying scripts can enable
- * them during tests/scripts/test-ref-configs.pl */
-//#define MBEDTLS_USE_PSA_CRYPTO
-//#define MBEDTLS_PSA_CRYPTO_C
-
-/* With MBEDTLS_PSA_CRYPTO_C, importing an RSA key requires MBEDTLS_PK_WRITE_C */
-#if defined(MBEDTLS_PSA_CRYPTO_C)
-#define MBEDTLS_PK_WRITE_C
-#endif
-#include "mbedtls/check_config.h"
-
-/* Error messages and TLS debugging traces
- * (huge code size increase, needed for tests/ssl-opt.sh) */
-//#define MBEDTLS_DEBUG_C
-//#define MBEDTLS_ERROR_C
-
-#endif /* MBEDTLS_CONFIG_H */
diff --git a/vendor/mbedtls/configs/config-no-entropy.h b/vendor/mbedtls/configs/config-no-entropy.h
index 72006eb6ef..ddb00b41ef 100644
--- a/vendor/mbedtls/configs/config-no-entropy.h
+++ b/vendor/mbedtls/configs/config-no-entropy.h
@@ -5,19 +5,7 @@
  */
 /*
  *  Copyright The Mbed TLS Contributors
- *  SPDX-License-Identifier: Apache-2.0
- *
- *  Licensed under the Apache License, Version 2.0 (the "License"); you may
- *  not use this file except in compliance with the License.
- *  You may obtain a copy of the License at
- *
- *  http://www.apache.org/licenses/LICENSE-2.0
- *
- *  Unless required by applicable law or agreed to in writing, software
- *  distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
- *  WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- *  See the License for the specific language governing permissions and
- *  limitations under the License.
+ *  SPDX-License-Identifier: Apache-2.0 OR GPL-2.0-or-later
  */
 /*
  * Minimal configuration of features that do not require an entropy source
@@ -29,9 +17,6 @@
  * See README.txt for usage instructions.
  */
 
-#ifndef MBEDTLS_CONFIG_H
-#define MBEDTLS_CONFIG_H
-
 /* System support */
 #define MBEDTLS_HAVE_ASM
 #define MBEDTLS_HAVE_TIME
@@ -39,7 +24,6 @@
 /* Mbed TLS feature support */
 #define MBEDTLS_CIPHER_MODE_CBC
 #define MBEDTLS_CIPHER_PADDING_PKCS7
-#define MBEDTLS_REMOVE_ARC4_CIPHERSUITES
 #define MBEDTLS_ECP_DP_SECP256R1_ENABLED
 #define MBEDTLS_ECP_DP_SECP384R1_ENABLED
 #define MBEDTLS_ECP_DP_CURVE25519_ENABLED
@@ -50,8 +34,6 @@
 #define MBEDTLS_PKCS1_V21
 #define MBEDTLS_SELF_TEST
 #define MBEDTLS_VERSION_FEATURES
-#define MBEDTLS_X509_CHECK_KEY_USAGE
-#define MBEDTLS_X509_CHECK_EXTENDED_KEY_USAGE
 
 /* Mbed TLS modules */
 #define MBEDTLS_AES_C
@@ -74,7 +56,12 @@
 #define MBEDTLS_PK_WRITE_C
 #define MBEDTLS_PLATFORM_C
 #define MBEDTLS_RSA_C
+/* The library does not currently support enabling SHA-224 without SHA-256.
+ * A future version of the library will have this option disabled
+ * by default. */
+#define MBEDTLS_SHA224_C
 #define MBEDTLS_SHA256_C
+#define MBEDTLS_SHA384_C
 #define MBEDTLS_SHA512_C
 #define MBEDTLS_VERSION_C
 #define MBEDTLS_X509_USE_C
@@ -84,7 +71,3 @@
 
 /* Miscellaneous options */
 #define MBEDTLS_AES_ROM_TABLES
-
-#include "mbedtls/check_config.h"
-
-#endif /* MBEDTLS_CONFIG_H */
diff --git a/vendor/mbedtls/configs/config-suite-b.h b/vendor/mbedtls/configs/config-suite-b.h
index 545a7912d8..9bba6e6cbd 100644
--- a/vendor/mbedtls/configs/config-suite-b.h
+++ b/vendor/mbedtls/configs/config-suite-b.h
@@ -5,19 +5,7 @@
  */
 /*
  *  Copyright The Mbed TLS Contributors
- *  SPDX-License-Identifier: Apache-2.0
- *
- *  Licensed under the Apache License, Version 2.0 (the "License"); you may
- *  not use this file except in compliance with the License.
- *  You may obtain a copy of the License at
- *
- *  http://www.apache.org/licenses/LICENSE-2.0
- *
- *  Unless required by applicable law or agreed to in writing, software
- *  distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
- *  WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- *  See the License for the specific language governing permissions and
- *  limitations under the License.
+ *  SPDX-License-Identifier: Apache-2.0 OR GPL-2.0-or-later
  */
 /*
  * Minimal configuration for TLS NSA Suite B Profile (RFC 6460)
@@ -33,9 +21,6 @@
  * See README.txt for usage instructions.
  */
 
-#ifndef MBEDTLS_CONFIG_H
-#define MBEDTLS_CONFIG_H
-
 /* System support */
 #define MBEDTLS_HAVE_ASM
 #define MBEDTLS_HAVE_TIME
@@ -64,6 +49,7 @@
 #define MBEDTLS_PK_C
 #define MBEDTLS_PK_PARSE_C
 #define MBEDTLS_SHA256_C
+#define MBEDTLS_SHA384_C
 #define MBEDTLS_SHA512_C
 #define MBEDTLS_SSL_CLI_C
 #define MBEDTLS_SSL_SRV_C
@@ -73,14 +59,13 @@
 
 /* For test certificates */
 #define MBEDTLS_BASE64_C
-#define MBEDTLS_CERTS_C
 #define MBEDTLS_PEM_PARSE_C
 
 /* Save RAM at the expense of ROM */
 #define MBEDTLS_AES_ROM_TABLES
 
 /* Save RAM by adjusting to our exact needs */
-#define MBEDTLS_MPI_MAX_SIZE    48 // 48 bytes for a 384-bit elliptic curve
+#define MBEDTLS_MPI_MAX_SIZE    48 // 384-bit EC curve = 48 bytes
 
 /* Save RAM at the expense of speed, see ecp.h */
 #define MBEDTLS_ECP_WINDOW_SIZE        2
@@ -107,23 +92,15 @@
  * The minimum size here depends on the certificate chain used as well as the
  * typical size of records.
  */
-#define MBEDTLS_SSL_MAX_CONTENT_LEN             1024
+#define MBEDTLS_SSL_IN_CONTENT_LEN             1024
+#define MBEDTLS_SSL_OUT_CONTENT_LEN             1024
 
 /* These defines are present so that the config modifying scripts can enable
  * them during tests/scripts/test-ref-configs.pl */
 //#define MBEDTLS_USE_PSA_CRYPTO
 //#define MBEDTLS_PSA_CRYPTO_C
 
-/* With USE_PSA_CRYPTO, some PK operations also need PK_WRITE */
-#if defined(MBEDTLS_USE_PSA_CRYPTO)
-#define MBEDTLS_PK_WRITE_C
-#endif
-
 /* Error messages and TLS debugging traces
  * (huge code size increase, needed for tests/ssl-opt.sh) */
 //#define MBEDTLS_DEBUG_C
 //#define MBEDTLS_ERROR_C
-
-#include "mbedtls/check_config.h"
-
-#endif /* MBEDTLS_CONFIG_H */
diff --git a/vendor/mbedtls/configs/config-symmetric-only.h b/vendor/mbedtls/configs/config-symmetric-only.h
index 3498738a6f..512dd7616c 100644
--- a/vendor/mbedtls/configs/config-symmetric-only.h
+++ b/vendor/mbedtls/configs/config-symmetric-only.h
@@ -5,24 +5,9 @@
  */
 /*
  *  Copyright The Mbed TLS Contributors
- *  SPDX-License-Identifier: Apache-2.0
- *
- *  Licensed under the Apache License, Version 2.0 (the "License"); you may
- *  not use this file except in compliance with the License.
- *  You may obtain a copy of the License at
- *
- *  http://www.apache.org/licenses/LICENSE-2.0
- *
- *  Unless required by applicable law or agreed to in writing, software
- *  distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
- *  WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- *  See the License for the specific language governing permissions and
- *  limitations under the License.
+ *  SPDX-License-Identifier: Apache-2.0 OR GPL-2.0-or-later
  */
 
-#ifndef MBEDTLS_CONFIG_H
-#define MBEDTLS_CONFIG_H
-
 /* System support */
 //#define MBEDTLS_HAVE_ASM
 #define MBEDTLS_HAVE_TIME
@@ -47,11 +32,9 @@
 
 /* Mbed TLS modules */
 #define MBEDTLS_AES_C
-#define MBEDTLS_ARC4_C
 #define MBEDTLS_ASN1_PARSE_C
 #define MBEDTLS_ASN1_WRITE_C
 #define MBEDTLS_BASE64_C
-#define MBEDTLS_BLOWFISH_C
 #define MBEDTLS_CAMELLIA_C
 #define MBEDTLS_ARIA_C
 #define MBEDTLS_CCM_C
@@ -64,13 +47,10 @@
 #define MBEDTLS_ENTROPY_C
 #define MBEDTLS_ERROR_C
 #define MBEDTLS_GCM_C
-//#define MBEDTLS_HAVEGE_C
 #define MBEDTLS_HKDF_C
 #define MBEDTLS_HMAC_DRBG_C
 #define MBEDTLS_NIST_KW_C
 #define MBEDTLS_MD_C
-#define MBEDTLS_MD2_C
-#define MBEDTLS_MD4_C
 #define MBEDTLS_MD5_C
 #define MBEDTLS_OID_C
 #define MBEDTLS_PEM_PARSE_C
@@ -85,15 +65,13 @@
 #define MBEDTLS_PSA_ITS_FILE_C
 #define MBEDTLS_RIPEMD160_C
 #define MBEDTLS_SHA1_C
+/* The library does not currently support enabling SHA-224 without SHA-256.
+ * A future version of the library will have this option disabled
+ * by default. */
+#define MBEDTLS_SHA224_C
 #define MBEDTLS_SHA256_C
+#define MBEDTLS_SHA384_C
 #define MBEDTLS_SHA512_C
 //#define MBEDTLS_THREADING_C
 #define MBEDTLS_TIMING_C
 #define MBEDTLS_VERSION_C
-#define MBEDTLS_XTEA_C
-
-#include "mbedtls/config_psa.h"
-
-#include "check_config.h"
-
-#endif /* MBEDTLS_CONFIG_H */
diff --git a/vendor/mbedtls/configs/config-tfm.h b/vendor/mbedtls/configs/config-tfm.h
new file mode 100644
index 0000000000..14896d40f3
--- /dev/null
+++ b/vendor/mbedtls/configs/config-tfm.h
@@ -0,0 +1,68 @@
+/**
+ * \file config-tfm.h
+ *
+ * \brief TF-M medium profile, adapted to work on other platforms.
+ */
+/*
+ *  Copyright The Mbed TLS Contributors
+ *  SPDX-License-Identifier: Apache-2.0 OR GPL-2.0-or-later
+ */
+
+/* TF-M medium profile: mbedtls legacy configuration */
+#include "../configs/ext/tfm_mbedcrypto_config_profile_medium.h"
+
+/* TF-M medium profile: PSA crypto configuration */
+#define MBEDTLS_PSA_CRYPTO_CONFIG_FILE "../configs/ext/crypto_config_profile_medium.h"
+
+/***********************************************************/
+/* Tweak the configuration to remove dependencies on TF-M. */
+/***********************************************************/
+
+/* MBEDTLS_PSA_CRYPTO_SPM needs third-party files, so disable it. */
+#undef MBEDTLS_PSA_CRYPTO_SPM
+
+/* Disable buffer-based memory allocator. This isn't strictly required,
+ * but using the native allocator is faster and works better with
+ * memory management analysis frameworks such as ASan. */
+#undef MBEDTLS_MEMORY_BUFFER_ALLOC_C
+
+// This macro is enabled in TFM Medium but is disabled here because it is
+// incompatible with baremetal builds in Mbed TLS.
+#undef MBEDTLS_PSA_CRYPTO_STORAGE_C
+
+// This macro is enabled in TFM Medium but is disabled here because it is
+// incompatible with baremetal builds in Mbed TLS.
+#undef MBEDTLS_ENTROPY_NV_SEED
+
+// These platform-related TF-M settings are not useful here.
+#undef MBEDTLS_PLATFORM_NO_STD_FUNCTIONS
+#undef MBEDTLS_PLATFORM_STD_MEM_HDR
+#undef MBEDTLS_PLATFORM_SNPRINTF_MACRO
+#undef MBEDTLS_PLATFORM_PRINTF_ALT
+#undef MBEDTLS_PLATFORM_STD_EXIT_SUCCESS
+#undef MBEDTLS_PLATFORM_STD_EXIT_FAILURE
+
+/*
+ * In order to get an example config that works cleanly out-of-the-box
+ * for both baremetal and non-baremetal builds, we detect baremetal builds
+ * (either IAR, Arm compiler or __ARM_EABI__ defined), and adjust some
+ * variables accordingly.
+ */
+#if defined(__IAR_SYSTEMS_ICC__) || defined(__ARMCC_VERSION) || defined(__ARM_EABI__)
+#define MBEDTLS_NO_PLATFORM_ENTROPY
+#else
+/* Use built-in platform entropy functions (TF-M provides its own). */
+#undef MBEDTLS_NO_PLATFORM_ENTROPY
+#endif
+
+/***********************************************************************
+ * Local changes to crypto config below this delimiter
+ **********************************************************************/
+
+// We expect TF-M to pick this up soon
+#define MBEDTLS_BLOCK_CIPHER_NO_DECRYPT
+
+/* CCM is the only cipher/AEAD enabled in TF-M configuration files, but it
+ * does not need CIPHER_C to be enabled, so we can disable it in order
+ * to reduce code size further. */
+#undef MBEDTLS_CIPHER_C
diff --git a/vendor/mbedtls/configs/config-thread.h b/vendor/mbedtls/configs/config-thread.h
index 0de7e1679f..2f81f90078 100644
--- a/vendor/mbedtls/configs/config-thread.h
+++ b/vendor/mbedtls/configs/config-thread.h
@@ -5,19 +5,7 @@
  */
 /*
  *  Copyright The Mbed TLS Contributors
- *  SPDX-License-Identifier: Apache-2.0
- *
- *  Licensed under the Apache License, Version 2.0 (the "License"); you may
- *  not use this file except in compliance with the License.
- *  You may obtain a copy of the License at
- *
- *  http://www.apache.org/licenses/LICENSE-2.0
- *
- *  Unless required by applicable law or agreed to in writing, software
- *  distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
- *  WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- *  See the License for the specific language governing permissions and
- *  limitations under the License.
+ *  SPDX-License-Identifier: Apache-2.0 OR GPL-2.0-or-later
  */
 
 /*
@@ -32,9 +20,6 @@
  * See README.txt for usage instructions.
  */
 
-#ifndef MBEDTLS_CONFIG_H
-#define MBEDTLS_CONFIG_H
-
 /* System support */
 #define MBEDTLS_HAVE_ASM
 
@@ -48,7 +33,6 @@
 #define MBEDTLS_SSL_PROTO_DTLS
 #define MBEDTLS_SSL_DTLS_ANTI_REPLAY
 #define MBEDTLS_SSL_DTLS_HELLO_VERIFY
-#define MBEDTLS_SSL_EXPORT_KEYS
 
 /* Mbed TLS modules */
 #define MBEDTLS_AES_C
@@ -81,7 +65,7 @@
 #define MBEDTLS_AES_ROM_TABLES
 
 /* Save RAM by adjusting to our exact needs */
-#define MBEDTLS_MPI_MAX_SIZE              32 // 32 bytes for a 256-bit elliptic curve
+#define MBEDTLS_MPI_MAX_SIZE              32 // 256-bit EC curve = 32 bytes
 
 /* Save ROM and a few bytes of RAM by specifying our own ciphersuite list */
 #define MBEDTLS_SSL_CIPHERSUITES MBEDTLS_TLS_ECJPAKE_WITH_AES_128_CCM_8
@@ -90,7 +74,3 @@
  * them during tests/scripts/test-ref-configs.pl */
 //#define MBEDTLS_USE_PSA_CRYPTO
 //#define MBEDTLS_PSA_CRYPTO_C
-
-#include "mbedtls/check_config.h"
-
-#endif /* MBEDTLS_CONFIG_H */
diff --git a/vendor/mbedtls/configs/crypto-config-ccm-aes-sha256.h b/vendor/mbedtls/configs/crypto-config-ccm-aes-sha256.h
new file mode 100644
index 0000000000..7f8d58768c
--- /dev/null
+++ b/vendor/mbedtls/configs/crypto-config-ccm-aes-sha256.h
@@ -0,0 +1,25 @@
+/**
+ * \file configs/crypto-config-ccm-aes-sha256.h
+ *
+ * \brief PSA crypto configuration with only symmetric cryptography: CCM-AES,
+ *        SHA-256, HMAC and key derivation
+ */
+/*
+ *  Copyright The Mbed TLS Contributors
+ *  SPDX-License-Identifier: Apache-2.0 OR GPL-2.0-or-later
+ */
+
+#ifndef PSA_CRYPTO_CONFIG_H
+#define PSA_CRYPTO_CONFIG_H
+
+#define PSA_WANT_ALG_CCM 1
+#define PSA_WANT_ALG_HMAC 1
+#define PSA_WANT_ALG_SHA_256 1
+#define PSA_WANT_ALG_TLS12_PRF 1
+#define PSA_WANT_ALG_TLS12_PSK_TO_MS 1
+#define PSA_WANT_KEY_TYPE_DERIVE 1
+#define PSA_WANT_KEY_TYPE_HMAC 1
+#define PSA_WANT_KEY_TYPE_AES 1
+#define PSA_WANT_KEY_TYPE_RAW_DATA 1
+
+#endif /* PSA_CRYPTO_CONFIG_H */
diff --git a/vendor/mbedtls/configs/ext/config_tfm.h b/vendor/mbedtls/configs/ext/config_tfm.h
new file mode 100644
index 0000000000..60d855ed59
--- /dev/null
+++ b/vendor/mbedtls/configs/ext/config_tfm.h
@@ -0,0 +1,13 @@
+/*
+ *  Empty placeholder
+ *
+ *  Copyright The Mbed TLS Contributors
+ *  SPDX-License-Identifier: Apache-2.0 OR GPL-2.0-or-later
+ */
+
+/*
+ * This file is intentionally empty.
+ *
+ * Having an empty file here allows us to build the TF-M config, which references this file,
+ * without making any changes to the TF-M config.
+ */
diff --git a/vendor/mbedtls/configs/ext/crypto_config_profile_medium.h b/vendor/mbedtls/configs/ext/crypto_config_profile_medium.h
new file mode 100644
index 0000000000..af8869f136
--- /dev/null
+++ b/vendor/mbedtls/configs/ext/crypto_config_profile_medium.h
@@ -0,0 +1,132 @@
+/*
+ * Copyright (c) 2018-2023, Arm Limited. All rights reserved.
+ *
+ * SPDX-License-Identifier: BSD-3-Clause
+ *
+ */
+/**
+ * \file psa/crypto_config.h
+ * \brief PSA crypto configuration options (set of defines)
+ *
+ */
+#if defined(MBEDTLS_PSA_CRYPTO_CONFIG)
+/**
+ * When #MBEDTLS_PSA_CRYPTO_CONFIG is enabled in mbedtls_config.h,
+ * this file determines which cryptographic mechanisms are enabled
+ * through the PSA Cryptography API (\c psa_xxx() functions).
+ *
+ * To enable a cryptographic mechanism, uncomment the definition of
+ * the corresponding \c PSA_WANT_xxx preprocessor symbol.
+ * To disable a cryptographic mechanism, comment out the definition of
+ * the corresponding \c PSA_WANT_xxx preprocessor symbol.
+ * The names of cryptographic mechanisms correspond to values
+ * defined in psa/crypto_values.h, with the prefix \c PSA_WANT_ instead
+ * of \c PSA_.
+ *
+ * Note that many cryptographic mechanisms involve two symbols: one for
+ * the key type (\c PSA_WANT_KEY_TYPE_xxx) and one for the algorithm
+ * (\c PSA_WANT_ALG_xxx). Mechanisms with additional parameters may involve
+ * additional symbols.
+ */
+#else
+/**
+ * When \c MBEDTLS_PSA_CRYPTO_CONFIG is disabled in mbedtls_config.h,
+ * this file is not used, and cryptographic mechanisms are supported
+ * through the PSA API if and only if they are supported through the
+ * mbedtls_xxx API.
+ */
+#endif
+
+#ifndef PROFILE_M_PSA_CRYPTO_CONFIG_H
+#define PROFILE_M_PSA_CRYPTO_CONFIG_H
+
+/*
+ * CBC-MAC is not yet supported via the PSA API in Mbed TLS.
+ */
+//#define PSA_WANT_ALG_CBC_MAC                    1
+//#define PSA_WANT_ALG_CBC_NO_PADDING             1
+//#define PSA_WANT_ALG_CBC_PKCS7                  1
+#define PSA_WANT_ALG_CCM                        1
+//#define PSA_WANT_ALG_CMAC                       1
+//#define PSA_WANT_ALG_CFB                        1
+//#define PSA_WANT_ALG_CHACHA20_POLY1305          1
+//#define PSA_WANT_ALG_CTR                        1
+//#define PSA_WANT_ALG_DETERMINISTIC_ECDSA        1
+//#define PSA_WANT_ALG_ECB_NO_PADDING             1
+#define PSA_WANT_ALG_ECDH                       1
+#define PSA_WANT_ALG_ECDSA                      1
+//#define PSA_WANT_ALG_GCM                        1
+#define PSA_WANT_ALG_HKDF                       1
+#define PSA_WANT_ALG_HMAC                       1
+//#define PSA_WANT_ALG_MD5                        1
+//#define PSA_WANT_ALG_OFB                        1
+/* PBKDF2-HMAC is not yet supported via the PSA API in Mbed TLS.
+ * Note: when adding support, also adjust include/mbedtls/config_psa.h */
+//#define PSA_WANT_ALG_PBKDF2_HMAC                1
+//#define PSA_WANT_ALG_RIPEMD160                  1
+//#define PSA_WANT_ALG_RSA_OAEP                   1
+//#define PSA_WANT_ALG_RSA_PKCS1V15_CRYPT         1
+//#define PSA_WANT_ALG_RSA_PKCS1V15_SIGN          1
+//#define PSA_WANT_ALG_RSA_PSS                    1
+//#define PSA_WANT_ALG_SHA_1                      1
+#define PSA_WANT_ALG_SHA_224                    1
+#define PSA_WANT_ALG_SHA_256                    1
+//#define PSA_WANT_ALG_SHA_384                    1
+//#define PSA_WANT_ALG_SHA_512                    1
+//#define PSA_WANT_ALG_STREAM_CIPHER              1
+#define PSA_WANT_ALG_TLS12_PRF                  1
+#define PSA_WANT_ALG_TLS12_PSK_TO_MS            1
+/* PBKDF2-HMAC is not yet supported via the PSA API in Mbed TLS.
+ * Note: when adding support, also adjust include/mbedtls/config_psa.h */
+//#define PSA_WANT_ALG_XTS                        1
+
+//#define PSA_WANT_ECC_BRAINPOOL_P_R1_256         1
+//#define PSA_WANT_ECC_BRAINPOOL_P_R1_384         1
+//#define PSA_WANT_ECC_BRAINPOOL_P_R1_512         1
+//#define PSA_WANT_ECC_MONTGOMERY_255             1
+//#define PSA_WANT_ECC_MONTGOMERY_448             1
+//#define PSA_WANT_ECC_SECP_K1_192                1
+/*
+ * SECP224K1 is buggy via the PSA API in Mbed TLS
+ * (https://github.com/Mbed-TLS/mbedtls/issues/3541). Thus, do not enable it by
+ * default.
+ */
+//#define PSA_WANT_ECC_SECP_K1_224                1
+//#define PSA_WANT_ECC_SECP_K1_256                1
+//#define PSA_WANT_ECC_SECP_R1_192                1
+//#define PSA_WANT_ECC_SECP_R1_224                1
+#define PSA_WANT_ECC_SECP_R1_256                1
+//#define PSA_WANT_ECC_SECP_R1_384                1
+//#define PSA_WANT_ECC_SECP_R1_521                1
+
+#define PSA_WANT_KEY_TYPE_DERIVE                1
+#define PSA_WANT_KEY_TYPE_HMAC                  1
+#define PSA_WANT_KEY_TYPE_AES                   1
+//#define PSA_WANT_KEY_TYPE_ARIA                  1
+//#define PSA_WANT_KEY_TYPE_CAMELLIA              1
+//#define PSA_WANT_KEY_TYPE_CHACHA20              1
+//#define PSA_WANT_KEY_TYPE_DES                   1
+//#define PSA_WANT_KEY_TYPE_ECC_KEY_PAIR          1 /* Deprecated */
+#define PSA_WANT_KEY_TYPE_ECC_PUBLIC_KEY        1
+#define PSA_WANT_KEY_TYPE_RAW_DATA              1
+//#define PSA_WANT_KEY_TYPE_RSA_KEY_PAIR          1 /* Deprecated */
+//#define PSA_WANT_KEY_TYPE_RSA_PUBLIC_KEY        1
+
+/*
+ * The following symbols extend and deprecate the legacy
+ * PSA_WANT_KEY_TYPE_xxx_KEY_PAIR ones. They include the usage of that key in
+ * the name's suffix. "_USE" is the most generic and it can be used to describe
+ * a generic suport, whereas other ones add more features on top of that and
+ * they are more specific.
+ */
+#define PSA_WANT_KEY_TYPE_ECC_KEY_PAIR_BASIC      1
+#define PSA_WANT_KEY_TYPE_ECC_KEY_PAIR_IMPORT   1
+#define PSA_WANT_KEY_TYPE_ECC_KEY_PAIR_EXPORT   1
+#define PSA_WANT_KEY_TYPE_ECC_KEY_PAIR_GENERATE 1
+//#define PSA_WANT_KEY_TYPE_ECC_KEY_PAIR_DERIVE   1
+
+#ifdef CRYPTO_HW_ACCELERATOR
+#include "crypto_accelerator_config.h"
+#endif
+
+#endif /* PROFILE_M_PSA_CRYPTO_CONFIG_H */
diff --git a/vendor/mbedtls/configs/ext/mbedtls_entropy_nv_seed_config.h b/vendor/mbedtls/configs/ext/mbedtls_entropy_nv_seed_config.h
new file mode 100644
index 0000000000..60d855ed59
--- /dev/null
+++ b/vendor/mbedtls/configs/ext/mbedtls_entropy_nv_seed_config.h
@@ -0,0 +1,13 @@
+/*
+ *  Empty placeholder
+ *
+ *  Copyright The Mbed TLS Contributors
+ *  SPDX-License-Identifier: Apache-2.0 OR GPL-2.0-or-later
+ */
+
+/*
+ * This file is intentionally empty.
+ *
+ * Having an empty file here allows us to build the TF-M config, which references this file,
+ * without making any changes to the TF-M config.
+ */
diff --git a/vendor/mbedtls/configs/ext/tfm_mbedcrypto_config_profile_medium.h b/vendor/mbedtls/configs/ext/tfm_mbedcrypto_config_profile_medium.h
new file mode 100644
index 0000000000..ecdecea5ee
--- /dev/null
+++ b/vendor/mbedtls/configs/ext/tfm_mbedcrypto_config_profile_medium.h
@@ -0,0 +1,573 @@
+/**
+ * \file config.h
+ *
+ * \brief Configuration options (set of defines)
+ *
+ *  This set of compile-time options may be used to enable
+ *  or disable features selectively, and reduce the global
+ *  memory footprint.
+ */
+/*
+ *  Copyright (C) 2006-2023, ARM Limited, All Rights Reserved
+ *  SPDX-License-Identifier: Apache-2.0
+ *
+ *  Licensed under the Apache License, Version 2.0 (the "License"); you may
+ *  not use this file except in compliance with the License.
+ *  You may obtain a copy of the License at
+ *
+ *  http://www.apache.org/licenses/LICENSE-2.0
+ *
+ *  Unless required by applicable law or agreed to in writing, software
+ *  distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
+ *  WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ *  See the License for the specific language governing permissions and
+ *  limitations under the License.
+ *
+ *  This file is part of mbed TLS (https://tls.mbed.org)
+ */
+
+#ifndef PROFILE_M_MBEDTLS_CONFIG_H
+#define PROFILE_M_MBEDTLS_CONFIG_H
+
+#include "config_tfm.h"
+
+#if defined(_MSC_VER) && !defined(_CRT_SECURE_NO_DEPRECATE)
+#define _CRT_SECURE_NO_DEPRECATE 1
+#endif
+
+/**
+ * \name SECTION: System support
+ *
+ * This section sets system specific settings.
+ * \{
+ */
+
+/**
+ * \def MBEDTLS_HAVE_ASM
+ *
+ * The compiler has support for asm().
+ *
+ * Requires support for asm() in compiler.
+ *
+ * Used in:
+ *      library/aria.c
+ *      library/timing.c
+ *      include/mbedtls/bn_mul.h
+ *
+ * Required by:
+ *      MBEDTLS_AESNI_C
+ *      MBEDTLS_PADLOCK_C
+ *
+ * Comment to disable the use of assembly code.
+ */
+#define MBEDTLS_HAVE_ASM
+
+/**
+ * \def MBEDTLS_PLATFORM_MEMORY
+ *
+ * Enable the memory allocation layer.
+ *
+ * By default mbed TLS uses the system-provided calloc() and free().
+ * This allows different allocators (self-implemented or provided) to be
+ * provided to the platform abstraction layer.
+ *
+ * Enabling MBEDTLS_PLATFORM_MEMORY without the
+ * MBEDTLS_PLATFORM_{FREE,CALLOC}_MACROs will provide
+ * "mbedtls_platform_set_calloc_free()" allowing you to set an alternative calloc() and
+ * free() function pointer at runtime.
+ *
+ * Enabling MBEDTLS_PLATFORM_MEMORY and specifying
+ * MBEDTLS_PLATFORM_{CALLOC,FREE}_MACROs will allow you to specify the
+ * alternate function at compile time.
+ *
+ * Requires: MBEDTLS_PLATFORM_C
+ *
+ * Enable this layer to allow use of alternative memory allocators.
+ */
+#define MBEDTLS_PLATFORM_MEMORY
+
+/* \} name SECTION: System support */
+
+/**
+ * \name SECTION: mbed TLS feature support
+ *
+ * This section sets support for features that are or are not needed
+ * within the modules that are enabled.
+ * \{
+ */
+
+/**
+ * \def MBEDTLS_AES_ROM_TABLES
+ *
+ * Use precomputed AES tables stored in ROM.
+ *
+ * Uncomment this macro to use precomputed AES tables stored in ROM.
+ * Comment this macro to generate AES tables in RAM at runtime.
+ *
+ * Tradeoff: Using precomputed ROM tables reduces RAM usage by ~8kb
+ * (or ~2kb if \c MBEDTLS_AES_FEWER_TABLES is used) and reduces the
+ * initialization time before the first AES operation can be performed.
+ * It comes at the cost of additional ~8kb ROM use (resp. ~2kb if \c
+ * MBEDTLS_AES_FEWER_TABLES below is used), and potentially degraded
+ * performance if ROM access is slower than RAM access.
+ *
+ * This option is independent of \c MBEDTLS_AES_FEWER_TABLES.
+ *
+ */
+#define MBEDTLS_AES_ROM_TABLES
+
+/**
+ * \def MBEDTLS_AES_FEWER_TABLES
+ *
+ * Use less ROM/RAM for AES tables.
+ *
+ * Uncommenting this macro omits 75% of the AES tables from
+ * ROM / RAM (depending on the value of \c MBEDTLS_AES_ROM_TABLES)
+ * by computing their values on the fly during operations
+ * (the tables are entry-wise rotations of one another).
+ *
+ * Tradeoff: Uncommenting this reduces the RAM / ROM footprint
+ * by ~6kb but at the cost of more arithmetic operations during
+ * runtime. Specifically, one has to compare 4 accesses within
+ * different tables to 4 accesses with additional arithmetic
+ * operations within the same table. The performance gain/loss
+ * depends on the system and memory details.
+ *
+ * This option is independent of \c MBEDTLS_AES_ROM_TABLES.
+ *
+ */
+#define MBEDTLS_AES_FEWER_TABLES
+
+/**
+ * \def MBEDTLS_ECP_NIST_OPTIM
+ *
+ * Enable specific 'modulo p' routines for each NIST prime.
+ * Depending on the prime and architecture, makes operations 4 to 8 times
+ * faster on the corresponding curve.
+ *
+ * Comment this macro to disable NIST curves optimisation.
+ */
+#define MBEDTLS_ECP_NIST_OPTIM
+
+/**
+ * \def MBEDTLS_NO_PLATFORM_ENTROPY
+ *
+ * Do not use built-in platform entropy functions.
+ * This is useful if your platform does not support
+ * standards like the /dev/urandom or Windows CryptoAPI.
+ *
+ * Uncomment this macro to disable the built-in platform entropy functions.
+ */
+#define MBEDTLS_NO_PLATFORM_ENTROPY
+
+/**
+ * \def MBEDTLS_ENTROPY_NV_SEED
+ *
+ * Enable the non-volatile (NV) seed file-based entropy source.
+ * (Also enables the NV seed read/write functions in the platform layer)
+ *
+ * This is crucial (if not required) on systems that do not have a
+ * cryptographic entropy source (in hardware or kernel) available.
+ *
+ * Requires: MBEDTLS_ENTROPY_C, MBEDTLS_PLATFORM_C
+ *
+ * \note The read/write functions that are used by the entropy source are
+ *       determined in the platform layer, and can be modified at runtime and/or
+ *       compile-time depending on the flags (MBEDTLS_PLATFORM_NV_SEED_*) used.
+ *
+ * \note If you use the default implementation functions that read a seedfile
+ *       with regular fopen(), please make sure you make a seedfile with the
+ *       proper name (defined in MBEDTLS_PLATFORM_STD_NV_SEED_FILE) and at
+ *       least MBEDTLS_ENTROPY_BLOCK_SIZE bytes in size that can be read from
+ *       and written to or you will get an entropy source error! The default
+ *       implementation will only use the first MBEDTLS_ENTROPY_BLOCK_SIZE
+ *       bytes from the file.
+ *
+ * \note The entropy collector will write to the seed file before entropy is
+ *       given to an external source, to update it.
+ */
+#define MBEDTLS_ENTROPY_NV_SEED
+
+/**
+ * \def MBEDTLS_PSA_CRYPTO_SPM
+ *
+ * When MBEDTLS_PSA_CRYPTO_SPM is defined, the code is built for SPM (Secure
+ * Partition Manager) integration which separates the code into two parts: a
+ * NSPE (Non-Secure Process Environment) and an SPE (Secure Process
+ * Environment).
+ *
+ * Module:  library/psa_crypto.c
+ * Requires: MBEDTLS_PSA_CRYPTO_C
+ *
+ */
+#define MBEDTLS_PSA_CRYPTO_SPM
+
+/**
+ * \def MBEDTLS_SHA256_SMALLER
+ *
+ * Enable an implementation of SHA-256 that has lower ROM footprint but also
+ * lower performance.
+ *
+ * The default implementation is meant to be a reasonnable compromise between
+ * performance and size. This version optimizes more aggressively for size at
+ * the expense of performance. Eg on Cortex-M4 it reduces the size of
+ * mbedtls_sha256_process() from ~2KB to ~0.5KB for a performance hit of about
+ * 30%.
+ *
+ * Uncomment to enable the smaller implementation of SHA256.
+ */
+#define MBEDTLS_SHA256_SMALLER
+
+/**
+ * \def MBEDTLS_PSA_CRYPTO_CONFIG
+ *
+ * This setting allows support for cryptographic mechanisms through the PSA
+ * API to be configured separately from support through the mbedtls API.
+ *
+ * When this option is disabled, the PSA API exposes the cryptographic
+ * mechanisms that can be implemented on top of the `mbedtls_xxx` API
+ * configured with `MBEDTLS_XXX` symbols.
+ *
+ * When this option is enabled, the PSA API exposes the cryptographic
+ * mechanisms requested by the `PSA_WANT_XXX` symbols defined in
+ * include/psa/crypto_config.h. The corresponding `MBEDTLS_XXX` settings are
+ * automatically enabled if required (i.e. if no PSA driver provides the
+ * mechanism). You may still freely enable additional `MBEDTLS_XXX` symbols
+ * in mbedtls_config.h.
+ *
+ * If the symbol #MBEDTLS_PSA_CRYPTO_CONFIG_FILE is defined, it specifies
+ * an alternative header to include instead of include/psa/crypto_config.h.
+ *
+ * This feature is still experimental and is not ready for production since
+ * it is not completed.
+ */
+#define MBEDTLS_PSA_CRYPTO_CONFIG
+
+/* \} name SECTION: mbed TLS feature support */
+
+/**
+ * \name SECTION: mbed TLS modules
+ *
+ * This section enables or disables entire modules in mbed TLS
+ * \{
+ */
+
+/**
+ * \def MBEDTLS_AES_C
+ *
+ * Enable the AES block cipher.
+ *
+ * Module:  library/aes.c
+ * Caller:  library/cipher.c
+ *          library/pem.c
+ *          library/ctr_drbg.c
+ *
+ * This module is required to support the TLS ciphersuites that use the AES
+ * cipher.
+ *
+ * PEM_PARSE uses AES for decrypting encrypted keys.
+ */
+#define MBEDTLS_AES_C
+
+/**
+ * \def MBEDTLS_AES_ONLY_128_BIT_KEY_LENGTH
+ *
+ * Use only 128-bit keys in AES operations to save ROM.
+ *
+ * Uncomment this macro to remove support for AES operations that use 192-
+ * or 256-bit keys.
+ *
+ * Uncommenting this macro reduces the size of AES code by ~300 bytes
+ * on v8-M/Thumb2.
+ *
+ * Module:  library/aes.c
+ *
+ * Requires: MBEDTLS_AES_C
+ */
+#define MBEDTLS_AES_ONLY_128_BIT_KEY_LENGTH
+
+/**
+ * \def MBEDTLS_CIPHER_C
+ *
+ * Enable the generic cipher layer.
+ *
+ * Module:  library/cipher.c
+ *
+ * Uncomment to enable generic cipher wrappers.
+ */
+#define MBEDTLS_CIPHER_C
+
+/**
+ * \def MBEDTLS_CTR_DRBG_C
+ *
+ * Enable the CTR_DRBG AES-based random generator.
+ * The CTR_DRBG generator uses AES-256 by default.
+ * To use AES-128 instead, enable MBEDTLS_CTR_DRBG_USE_128_BIT_KEY below.
+ *
+ * Module:  library/ctr_drbg.c
+ * Caller:
+ *
+ * Requires: MBEDTLS_AES_C
+ *
+ * This module provides the CTR_DRBG AES random number generator.
+ */
+#define MBEDTLS_CTR_DRBG_C
+
+/**
+ * \def MBEDTLS_ENTROPY_C
+ *
+ * Enable the platform-specific entropy code.
+ *
+ * Module:  library/entropy.c
+ * Caller:
+ *
+ * Requires: MBEDTLS_SHA512_C or MBEDTLS_SHA256_C
+ *
+ * This module provides a generic entropy pool
+ */
+#define MBEDTLS_ENTROPY_C
+
+/**
+ * \def MBEDTLS_HKDF_C
+ *
+ * Enable the HKDF algorithm (RFC 5869).
+ *
+ * Module:  library/hkdf.c
+ * Caller:
+ *
+ * Requires: MBEDTLS_MD_C
+ *
+ * This module adds support for the Hashed Message Authentication Code
+ * (HMAC)-based key derivation function (HKDF).
+ */
+//#define MBEDTLS_HKDF_C /* Used for HUK deriviation */
+
+/**
+ * \def MBEDTLS_MEMORY_BUFFER_ALLOC_C
+ *
+ * Enable the buffer allocator implementation that makes use of a (stack)
+ * based buffer to 'allocate' dynamic memory. (replaces calloc() and free()
+ * calls)
+ *
+ * Module:  library/memory_buffer_alloc.c
+ *
+ * Requires: MBEDTLS_PLATFORM_C
+ *           MBEDTLS_PLATFORM_MEMORY (to use it within mbed TLS)
+ *
+ * Enable this module to enable the buffer memory allocator.
+ */
+#define MBEDTLS_MEMORY_BUFFER_ALLOC_C
+
+/**
+ * \def MBEDTLS_PLATFORM_C
+ *
+ * Enable the platform abstraction layer that allows you to re-assign
+ * functions like calloc(), free(), snprintf(), printf(), fprintf(), exit().
+ *
+ * Enabling MBEDTLS_PLATFORM_C enables to use of MBEDTLS_PLATFORM_XXX_ALT
+ * or MBEDTLS_PLATFORM_XXX_MACRO directives, allowing the functions mentioned
+ * above to be specified at runtime or compile time respectively.
+ *
+ * \note This abstraction layer must be enabled on Windows (including MSYS2)
+ * as other module rely on it for a fixed snprintf implementation.
+ *
+ * Module:  library/platform.c
+ * Caller:  Most other .c files
+ *
+ * This module enables abstraction of common (libc) functions.
+ */
+#define MBEDTLS_PLATFORM_C
+
+#define MBEDTLS_PLATFORM_NO_STD_FUNCTIONS
+#define MBEDTLS_PLATFORM_STD_MEM_HDR   
+
+#include 
+
+#define MBEDTLS_PLATFORM_SNPRINTF_MACRO      snprintf
+#define MBEDTLS_PLATFORM_PRINTF_ALT
+#define MBEDTLS_PLATFORM_STD_EXIT_SUCCESS  EXIT_SUCCESS
+#define MBEDTLS_PLATFORM_STD_EXIT_FAILURE  EXIT_FAILURE
+
+/**
+ * \def MBEDTLS_PSA_CRYPTO_C
+ *
+ * Enable the Platform Security Architecture cryptography API.
+ *
+ * Module:  library/psa_crypto.c
+ *
+ * Requires: MBEDTLS_CTR_DRBG_C, MBEDTLS_ENTROPY_C
+ *
+ */
+#define MBEDTLS_PSA_CRYPTO_C
+
+/**
+ * \def MBEDTLS_PSA_CRYPTO_STORAGE_C
+ *
+ * Enable the Platform Security Architecture persistent key storage.
+ *
+ * Module:  library/psa_crypto_storage.c
+ *
+ * Requires: MBEDTLS_PSA_CRYPTO_C,
+ *           either MBEDTLS_PSA_ITS_FILE_C or a native implementation of
+ *           the PSA ITS interface
+ */
+#define MBEDTLS_PSA_CRYPTO_STORAGE_C
+
+/* \} name SECTION: mbed TLS modules */
+
+/**
+ * \name SECTION: General configuration options
+ *
+ * This section contains Mbed TLS build settings that are not associated
+ * with a particular module.
+ *
+ * \{
+ */
+
+/**
+ * \def MBEDTLS_CONFIG_FILE
+ *
+ * If defined, this is a header which will be included instead of
+ * `"mbedtls/mbedtls_config.h"`.
+ * This header file specifies the compile-time configuration of Mbed TLS.
+ * Unlike other configuration options, this one must be defined on the
+ * compiler command line: a definition in `mbedtls_config.h` would have
+ * no effect.
+ *
+ * This macro is expanded after an \#include directive. This is a popular but
+ * non-standard feature of the C language, so this feature is only available
+ * with compilers that perform macro expansion on an \#include line.
+ *
+ * The value of this symbol is typically a path in double quotes, either
+ * absolute or relative to a directory on the include search path.
+ */
+//#define MBEDTLS_CONFIG_FILE "mbedtls/mbedtls_config.h"
+
+/**
+ * \def MBEDTLS_USER_CONFIG_FILE
+ *
+ * If defined, this is a header which will be included after
+ * `"mbedtls/mbedtls_config.h"` or #MBEDTLS_CONFIG_FILE.
+ * This allows you to modify the default configuration, including the ability
+ * to undefine options that are enabled by default.
+ *
+ * This macro is expanded after an \#include directive. This is a popular but
+ * non-standard feature of the C language, so this feature is only available
+ * with compilers that perform macro expansion on an \#include line.
+ *
+ * The value of this symbol is typically a path in double quotes, either
+ * absolute or relative to a directory on the include search path.
+ */
+//#define MBEDTLS_USER_CONFIG_FILE "/dev/null"
+
+/**
+ * \def MBEDTLS_PSA_CRYPTO_CONFIG_FILE
+ *
+ * If defined, this is a header which will be included instead of
+ * `"psa/crypto_config.h"`.
+ * This header file specifies which cryptographic mechanisms are available
+ * through the PSA API when #MBEDTLS_PSA_CRYPTO_CONFIG is enabled, and
+ * is not used when #MBEDTLS_PSA_CRYPTO_CONFIG is disabled.
+ *
+ * This macro is expanded after an \#include directive. This is a popular but
+ * non-standard feature of the C language, so this feature is only available
+ * with compilers that perform macro expansion on an \#include line.
+ *
+ * The value of this symbol is typically a path in double quotes, either
+ * absolute or relative to a directory on the include search path.
+ */
+//#define MBEDTLS_PSA_CRYPTO_CONFIG_FILE "psa/crypto_config.h"
+
+/**
+ * \def MBEDTLS_PSA_CRYPTO_USER_CONFIG_FILE
+ *
+ * If defined, this is a header which will be included after
+ * `"psa/crypto_config.h"` or #MBEDTLS_PSA_CRYPTO_CONFIG_FILE.
+ * This allows you to modify the default configuration, including the ability
+ * to undefine options that are enabled by default.
+ *
+ * This macro is expanded after an \#include directive. This is a popular but
+ * non-standard feature of the C language, so this feature is only available
+ * with compilers that perform macro expansion on an \#include line.
+ *
+ * The value of this symbol is typically a path in double quotes, either
+ * absolute or relative to a directory on the include search path.
+ */
+//#define MBEDTLS_PSA_CRYPTO_USER_CONFIG_FILE "/dev/null"
+
+/** \} name SECTION: General configuration options */
+
+/**
+ * \name SECTION: Module configuration options
+ *
+ * This section allows for the setting of module specific sizes and
+ * configuration options. The default values are already present in the
+ * relevant header files and should suffice for the regular use cases.
+ *
+ * Our advice is to enable options and change their values here
+ * only if you have a good reason and know the consequences.
+ *
+ * Please check the respective header file for documentation on these
+ * parameters (to prevent duplicate documentation).
+ * \{
+ */
+
+/* ECP options */
+#define MBEDTLS_ECP_FIXED_POINT_OPTIM        0 /**< Disable fixed-point speed-up */
+
+/**
+ * Uncomment to enable p256-m. This is an alternative implementation of
+ * key generation, ECDH and (randomized) ECDSA on the curve SECP256R1.
+ * Compared to the default implementation:
+ *
+ * - p256-m has a much smaller code size and RAM footprint.
+ * - p256-m is only available via the PSA API. This includes the pk module
+ *   when #MBEDTLS_USE_PSA_CRYPTO is enabled.
+ * - p256-m does not support deterministic ECDSA, EC-JPAKE, custom protocols
+ *   over the core arithmetic, or deterministic derivation of keys.
+ *
+ * We recommend enabling this option if your application uses the PSA API
+ * and the only elliptic curve support it needs is ECDH and ECDSA over
+ * SECP256R1.
+ *
+ * If you enable this option, you do not need to enable any ECC-related
+ * MBEDTLS_xxx option. You do need to separately request support for the
+ * cryptographic mechanisms through the PSA API:
+ * - #MBEDTLS_PSA_CRYPTO_C and #MBEDTLS_PSA_CRYPTO_CONFIG for PSA-based
+ *   configuration;
+ * - #MBEDTLS_USE_PSA_CRYPTO if you want to use p256-m from PK, X.509 or TLS;
+ * - #PSA_WANT_ECC_SECP_R1_256;
+ * - #PSA_WANT_ALG_ECDH and/or #PSA_WANT_ALG_ECDSA as needed;
+ * - #PSA_WANT_KEY_TYPE_ECC_PUBLIC_KEY, #PSA_WANT_KEY_TYPE_ECC_KEY_PAIR_BASIC,
+ *   #PSA_WANT_KEY_TYPE_ECC_KEY_PAIR_IMPORT,
+ *   #PSA_WANT_KEY_TYPE_ECC_KEY_PAIR_EXPORT and/or
+ *   #PSA_WANT_KEY_TYPE_ECC_KEY_PAIR_GENERATE as needed.
+ *
+ * \note To benefit from the smaller code size of p256-m, make sure that you
+ *       do not enable any ECC-related option not supported by p256-m: this
+ *       would cause the built-in ECC implementation to be built as well, in
+ *       order to provide the required option.
+ *       Make sure #PSA_WANT_ALG_DETERMINISTIC_ECDSA, #PSA_WANT_ALG_JPAKE and
+ *       #PSA_WANT_KEY_TYPE_ECC_KEY_PAIR_DERIVE, and curves other than
+ *       SECP256R1 are disabled as they are not supported by this driver.
+ *       Also, avoid defining #MBEDTLS_PK_PARSE_EC_COMPRESSED or
+ *       #MBEDTLS_PK_PARSE_EC_EXTENDED as those currently require a subset of
+ *       the built-in ECC implementation, see docs/driver-only-builds.md.
+ */
+#define MBEDTLS_PSA_P256M_DRIVER_ENABLED
+
+/* \} name SECTION: Customisation configuration options */
+
+#if CRYPTO_NV_SEED
+#include "tfm_mbedcrypto_config_extra_nv_seed.h"
+#endif /* CRYPTO_NV_SEED */
+
+#if !defined(CRYPTO_HW_ACCELERATOR) && defined(MBEDTLS_ENTROPY_NV_SEED)
+#include "mbedtls_entropy_nv_seed_config.h"
+#endif
+
+#ifdef CRYPTO_HW_ACCELERATOR
+#include "mbedtls_accelerator_config.h"
+#endif
+
+#endif /* PROFILE_M_MBEDTLS_CONFIG_H */
diff --git a/vendor/mbedtls/include/mbedtls/aes.h b/vendor/mbedtls/include/mbedtls/aes.h
index fb2322a6bb..d5eb1fd5c2 100644
--- a/vendor/mbedtls/include/mbedtls/aes.h
+++ b/vendor/mbedtls/include/mbedtls/aes.h
@@ -22,29 +22,14 @@
 
 /*
  *  Copyright The Mbed TLS Contributors
- *  SPDX-License-Identifier: Apache-2.0
- *
- *  Licensed under the Apache License, Version 2.0 (the "License"); you may
- *  not use this file except in compliance with the License.
- *  You may obtain a copy of the License at
- *
- *  http://www.apache.org/licenses/LICENSE-2.0
- *
- *  Unless required by applicable law or agreed to in writing, software
- *  distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
- *  WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- *  See the License for the specific language governing permissions and
- *  limitations under the License.
+ *  SPDX-License-Identifier: Apache-2.0 OR GPL-2.0-or-later
  */
 
 #ifndef MBEDTLS_AES_H
 #define MBEDTLS_AES_H
+#include "mbedtls/private_access.h"
 
-#if !defined(MBEDTLS_CONFIG_FILE)
-#include "mbedtls/config.h"
-#else
-#include MBEDTLS_CONFIG_FILE
-#endif
+#include "mbedtls/build_info.h"
 #include "mbedtls/platform_util.h"
 
 #include 
@@ -64,19 +49,6 @@
 /** Invalid input data. */
 #define MBEDTLS_ERR_AES_BAD_INPUT_DATA                    -0x0021
 
-/* MBEDTLS_ERR_AES_FEATURE_UNAVAILABLE is deprecated and should not be used. */
-/** Feature not available. For example, an unsupported AES key size. */
-#define MBEDTLS_ERR_AES_FEATURE_UNAVAILABLE               -0x0023
-
-/* MBEDTLS_ERR_AES_HW_ACCEL_FAILED is deprecated and should not be used. */
-/** AES hardware accelerator failed. */
-#define MBEDTLS_ERR_AES_HW_ACCEL_FAILED                   -0x0025
-
-#if (defined(__ARMCC_VERSION) || defined(_MSC_VER)) && \
-    !defined(inline) && !defined(__cplusplus)
-#define inline __inline
-#endif
-
 #ifdef __cplusplus
 extern "C" {
 #endif
@@ -89,16 +61,22 @@ extern "C" {
  * \brief The AES context-type definition.
  */
 typedef struct mbedtls_aes_context {
-    int nr;                     /*!< The number of rounds. */
-    uint32_t *rk;               /*!< AES round keys. */
-    uint32_t buf[68];           /*!< Unaligned data buffer. This buffer can
-                                     hold 32 extra Bytes, which can be used for
-                                     one of the following purposes:
-                                     
  • Alignment if VIA padlock is - used.
  • -
  • Simplifying key expansion in the 256-bit - case by generating an extra round key. -
*/ + int MBEDTLS_PRIVATE(nr); /*!< The number of rounds. */ + size_t MBEDTLS_PRIVATE(rk_offset); /*!< The offset in array elements to AES + round keys in the buffer. */ +#if defined(MBEDTLS_AES_ONLY_128_BIT_KEY_LENGTH) && !defined(MBEDTLS_PADLOCK_C) + uint32_t MBEDTLS_PRIVATE(buf)[44]; /*!< Aligned data buffer to hold + 10 round keys for 128-bit case. */ +#else + uint32_t MBEDTLS_PRIVATE(buf)[68]; /*!< Unaligned data buffer. This buffer can + hold 32 extra Bytes, which can be used for + one of the following purposes: +
  • Alignment if VIA padlock is + used.
  • +
  • Simplifying key expansion in the 256-bit + case by generating an extra round key. +
*/ +#endif /* MBEDTLS_AES_ONLY_128_BIT_KEY_LENGTH && !MBEDTLS_PADLOCK_C */ } mbedtls_aes_context; @@ -107,10 +85,10 @@ mbedtls_aes_context; * \brief The AES XTS context-type definition. */ typedef struct mbedtls_aes_xts_context { - mbedtls_aes_context crypt; /*!< The AES context to use for AES block - encryption or decryption. */ - mbedtls_aes_context tweak; /*!< The AES context used for tweak - computation. */ + mbedtls_aes_context MBEDTLS_PRIVATE(crypt); /*!< The AES context to use for AES block + encryption or decryption. */ + mbedtls_aes_context MBEDTLS_PRIVATE(tweak); /*!< The AES context used for tweak + computation. */ } mbedtls_aes_xts_context; #endif /* MBEDTLS_CIPHER_MODE_XTS */ @@ -177,6 +155,7 @@ MBEDTLS_CHECK_RETURN_TYPICAL int mbedtls_aes_setkey_enc(mbedtls_aes_context *ctx, const unsigned char *key, unsigned int keybits); +#if !defined(MBEDTLS_BLOCK_CIPHER_NO_DECRYPT) /** * \brief This function sets the decryption key. * @@ -195,6 +174,7 @@ int mbedtls_aes_setkey_enc(mbedtls_aes_context *ctx, const unsigned char *key, MBEDTLS_CHECK_RETURN_TYPICAL int mbedtls_aes_setkey_dec(mbedtls_aes_context *ctx, const unsigned char *key, unsigned int keybits); +#endif /* !MBEDTLS_BLOCK_CIPHER_NO_DECRYPT */ #if defined(MBEDTLS_CIPHER_MODE_XTS) /** @@ -614,6 +594,7 @@ int mbedtls_internal_aes_encrypt(mbedtls_aes_context *ctx, const unsigned char input[16], unsigned char output[16]); +#if !defined(MBEDTLS_BLOCK_CIPHER_NO_DECRYPT) /** * \brief Internal AES block decryption function. This is only * exposed to allow overriding it using see @@ -629,44 +610,7 @@ MBEDTLS_CHECK_RETURN_TYPICAL int mbedtls_internal_aes_decrypt(mbedtls_aes_context *ctx, const unsigned char input[16], unsigned char output[16]); - -#if !defined(MBEDTLS_DEPRECATED_REMOVED) -#if defined(MBEDTLS_DEPRECATED_WARNING) -#define MBEDTLS_DEPRECATED __attribute__((deprecated)) -#else -#define MBEDTLS_DEPRECATED -#endif -/** - * \brief Deprecated internal AES block encryption function - * without return value. - * - * \deprecated Superseded by mbedtls_internal_aes_encrypt() - * - * \param ctx The AES context to use for encryption. - * \param input Plaintext block. - * \param output Output (ciphertext) block. - */ -MBEDTLS_DEPRECATED void mbedtls_aes_encrypt(mbedtls_aes_context *ctx, - const unsigned char input[16], - unsigned char output[16]); - -/** - * \brief Deprecated internal AES block decryption function - * without return value. - * - * \deprecated Superseded by mbedtls_internal_aes_decrypt() - * - * \param ctx The AES context to use for decryption. - * \param input Ciphertext block. - * \param output Output (plaintext) block. - */ -MBEDTLS_DEPRECATED void mbedtls_aes_decrypt(mbedtls_aes_context *ctx, - const unsigned char input[16], - unsigned char output[16]); - -#undef MBEDTLS_DEPRECATED -#endif /* !MBEDTLS_DEPRECATED_REMOVED */ - +#endif /* !MBEDTLS_BLOCK_CIPHER_NO_DECRYPT */ #if defined(MBEDTLS_SELF_TEST) /** diff --git a/vendor/mbedtls/include/mbedtls/arc4.h b/vendor/mbedtls/include/mbedtls/arc4.h deleted file mode 100644 index d116dda4e9..0000000000 --- a/vendor/mbedtls/include/mbedtls/arc4.h +++ /dev/null @@ -1,144 +0,0 @@ -/** - * \file arc4.h - * - * \brief The ARCFOUR stream cipher - * - * \warning ARC4 is considered a weak cipher and its use constitutes a - * security risk. We recommend considering stronger ciphers instead. - */ -/* - * Copyright The Mbed TLS Contributors - * SPDX-License-Identifier: Apache-2.0 - * - * Licensed under the Apache License, Version 2.0 (the "License"); you may - * not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT - * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - * - */ -#ifndef MBEDTLS_ARC4_H -#define MBEDTLS_ARC4_H - -#if !defined(MBEDTLS_CONFIG_FILE) -#include "mbedtls/config.h" -#else -#include MBEDTLS_CONFIG_FILE -#endif - -#include - -/* MBEDTLS_ERR_ARC4_HW_ACCEL_FAILED is deprecated and should not be used. */ -/** ARC4 hardware accelerator failed. */ -#define MBEDTLS_ERR_ARC4_HW_ACCEL_FAILED -0x0019 - -#ifdef __cplusplus -extern "C" { -#endif - -#if !defined(MBEDTLS_ARC4_ALT) -// Regular implementation -// - -/** - * \brief ARC4 context structure - * - * \warning ARC4 is considered a weak cipher and its use constitutes a - * security risk. We recommend considering stronger ciphers instead. - * - */ -typedef struct mbedtls_arc4_context { - int x; /*!< permutation index */ - int y; /*!< permutation index */ - unsigned char m[256]; /*!< permutation table */ -} -mbedtls_arc4_context; - -#else /* MBEDTLS_ARC4_ALT */ -#include "arc4_alt.h" -#endif /* MBEDTLS_ARC4_ALT */ - -/** - * \brief Initialize ARC4 context - * - * \param ctx ARC4 context to be initialized - * - * \warning ARC4 is considered a weak cipher and its use constitutes a - * security risk. We recommend considering stronger ciphers - * instead. - * - */ -void mbedtls_arc4_init(mbedtls_arc4_context *ctx); - -/** - * \brief Clear ARC4 context - * - * \param ctx ARC4 context to be cleared - * - * \warning ARC4 is considered a weak cipher and its use constitutes a - * security risk. We recommend considering stronger ciphers - * instead. - * - */ -void mbedtls_arc4_free(mbedtls_arc4_context *ctx); - -/** - * \brief ARC4 key schedule - * - * \param ctx ARC4 context to be setup - * \param key the secret key - * \param keylen length of the key, in bytes - * - * \warning ARC4 is considered a weak cipher and its use constitutes a - * security risk. We recommend considering stronger ciphers - * instead. - * - */ -void mbedtls_arc4_setup(mbedtls_arc4_context *ctx, const unsigned char *key, - unsigned int keylen); - -/** - * \brief ARC4 cipher function - * - * \param ctx ARC4 context - * \param length length of the input data - * \param input buffer holding the input data - * \param output buffer for the output data - * - * \return 0 if successful - * - * \warning ARC4 is considered a weak cipher and its use constitutes a - * security risk. We recommend considering stronger ciphers - * instead. - * - */ -int mbedtls_arc4_crypt(mbedtls_arc4_context *ctx, size_t length, const unsigned char *input, - unsigned char *output); - -#if defined(MBEDTLS_SELF_TEST) - -/** - * \brief Checkup routine - * - * \return 0 if successful, or 1 if the test failed - * - * \warning ARC4 is considered a weak cipher and its use constitutes a - * security risk. We recommend considering stronger ciphers - * instead. - * - */ -int mbedtls_arc4_self_test(int verbose); - -#endif /* MBEDTLS_SELF_TEST */ - -#ifdef __cplusplus -} -#endif - -#endif /* arc4.h */ diff --git a/vendor/mbedtls/include/mbedtls/aria.h b/vendor/mbedtls/include/mbedtls/aria.h index d307ff9e47..c685fc3141 100644 --- a/vendor/mbedtls/include/mbedtls/aria.h +++ b/vendor/mbedtls/include/mbedtls/aria.h @@ -11,29 +11,14 @@ */ /* * Copyright The Mbed TLS Contributors - * SPDX-License-Identifier: Apache-2.0 - * - * Licensed under the Apache License, Version 2.0 (the "License"); you may - * not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT - * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. + * SPDX-License-Identifier: Apache-2.0 OR GPL-2.0-or-later */ #ifndef MBEDTLS_ARIA_H #define MBEDTLS_ARIA_H +#include "mbedtls/private_access.h" -#if !defined(MBEDTLS_CONFIG_FILE) -#include "mbedtls/config.h" -#else -#include MBEDTLS_CONFIG_FILE -#endif +#include "mbedtls/build_info.h" #include #include @@ -47,24 +32,12 @@ #define MBEDTLS_ARIA_MAX_ROUNDS 16 /**< Maximum number of rounds in ARIA. */ #define MBEDTLS_ARIA_MAX_KEYSIZE 32 /**< Maximum size of an ARIA key in bytes. */ -#if !defined(MBEDTLS_DEPRECATED_REMOVED) -#define MBEDTLS_ERR_ARIA_INVALID_KEY_LENGTH MBEDTLS_DEPRECATED_NUMERIC_CONSTANT(-0x005C) -#endif /* !MBEDTLS_DEPRECATED_REMOVED */ /** Bad input data. */ #define MBEDTLS_ERR_ARIA_BAD_INPUT_DATA -0x005C /** Invalid data input length. */ #define MBEDTLS_ERR_ARIA_INVALID_INPUT_LENGTH -0x005E -/* MBEDTLS_ERR_ARIA_FEATURE_UNAVAILABLE is deprecated and should not be used. - */ -/** Feature not available. For example, an unsupported ARIA key size. */ -#define MBEDTLS_ERR_ARIA_FEATURE_UNAVAILABLE -0x005A - -/* MBEDTLS_ERR_ARIA_HW_ACCEL_FAILED is deprecated and should not be used. */ -/** ARIA hardware accelerator failed. */ -#define MBEDTLS_ERR_ARIA_HW_ACCEL_FAILED -0x0058 - #ifdef __cplusplus extern "C" { #endif @@ -77,9 +50,9 @@ extern "C" { * \brief The ARIA context-type definition. */ typedef struct mbedtls_aria_context { - unsigned char nr; /*!< The number of rounds (12, 14 or 16) */ + unsigned char MBEDTLS_PRIVATE(nr); /*!< The number of rounds (12, 14 or 16) */ /*! The ARIA round keys. */ - uint32_t rk[MBEDTLS_ARIA_MAX_ROUNDS + 1][MBEDTLS_ARIA_BLOCKSIZE / 4]; + uint32_t MBEDTLS_PRIVATE(rk)[MBEDTLS_ARIA_MAX_ROUNDS + 1][MBEDTLS_ARIA_BLOCKSIZE / 4]; } mbedtls_aria_context; @@ -125,6 +98,7 @@ int mbedtls_aria_setkey_enc(mbedtls_aria_context *ctx, const unsigned char *key, unsigned int keybits); +#if !defined(MBEDTLS_BLOCK_CIPHER_NO_DECRYPT) /** * \brief This function sets the decryption key. * @@ -143,6 +117,7 @@ int mbedtls_aria_setkey_enc(mbedtls_aria_context *ctx, int mbedtls_aria_setkey_dec(mbedtls_aria_context *ctx, const unsigned char *key, unsigned int keybits); +#endif /* !MBEDTLS_BLOCK_CIPHER_NO_DECRYPT */ /** * \brief This function performs an ARIA single-block encryption or diff --git a/vendor/mbedtls/include/mbedtls/asn1.h b/vendor/mbedtls/include/mbedtls/asn1.h index 82aaee8f30..ff019f432a 100644 --- a/vendor/mbedtls/include/mbedtls/asn1.h +++ b/vendor/mbedtls/include/mbedtls/asn1.h @@ -5,28 +5,14 @@ */ /* * Copyright The Mbed TLS Contributors - * SPDX-License-Identifier: Apache-2.0 - * - * Licensed under the Apache License, Version 2.0 (the "License"); you may - * not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT - * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. + * SPDX-License-Identifier: Apache-2.0 OR GPL-2.0-or-later */ #ifndef MBEDTLS_ASN1_H #define MBEDTLS_ASN1_H +#include "mbedtls/private_access.h" -#if !defined(MBEDTLS_CONFIG_FILE) -#include "mbedtls/config.h" -#else -#include MBEDTLS_CONFIG_FILE -#endif +#include "mbedtls/build_info.h" +#include "mbedtls/platform_util.h" #include @@ -41,8 +27,9 @@ /** * \name ASN1 Error codes - * These error codes are OR'ed to X509 error codes for + * These error codes are combined with other error codes for * higher error granularity. + * e.g. X.509 and PKCS #7 error codes * ASN1 is a standard to specify data structures. * \{ */ @@ -97,15 +84,14 @@ /* Slightly smaller way to check if tag is a string tag * compared to canonical implementation. */ -#define MBEDTLS_ASN1_IS_STRING_TAG(tag) \ - ((tag) < 32u && ( \ +#define MBEDTLS_ASN1_IS_STRING_TAG(tag) \ + ((unsigned int) (tag) < 32u && ( \ ((1u << (tag)) & ((1u << MBEDTLS_ASN1_BMP_STRING) | \ (1u << MBEDTLS_ASN1_UTF8_STRING) | \ (1u << MBEDTLS_ASN1_T61_STRING) | \ (1u << MBEDTLS_ASN1_IA5_STRING) | \ (1u << MBEDTLS_ASN1_UNIVERSAL_STRING) | \ - (1u << MBEDTLS_ASN1_PRINTABLE_STRING) | \ - (1u << MBEDTLS_ASN1_BIT_STRING))) != 0)) + (1u << MBEDTLS_ASN1_PRINTABLE_STRING))) != 0)) /* * Bit masks for each of the components of an ASN.1 tag as specified in @@ -174,7 +160,15 @@ mbedtls_asn1_bitstring; */ typedef struct mbedtls_asn1_sequence { mbedtls_asn1_buf buf; /**< Buffer containing the given ASN.1 item. */ - struct mbedtls_asn1_sequence *next; /**< The next entry in the sequence. */ + + /** The next entry in the sequence. + * + * The details of memory management for sequences are not documented and + * may change in future versions. Set this field to \p NULL when + * initializing a structure, and do not modify it except via Mbed TLS + * library functions. + */ + struct mbedtls_asn1_sequence *next; } mbedtls_asn1_sequence; @@ -184,11 +178,27 @@ mbedtls_asn1_sequence; typedef struct mbedtls_asn1_named_data { mbedtls_asn1_buf oid; /**< The object identifier. */ mbedtls_asn1_buf val; /**< The named value. */ - struct mbedtls_asn1_named_data *next; /**< The next entry in the sequence. */ - unsigned char next_merged; /**< Merge next item into the current one? */ + + /** The next entry in the sequence. + * + * The details of memory management for named data sequences are not + * documented and may change in future versions. Set this field to \p NULL + * when initializing a structure, and do not modify it except via Mbed TLS + * library functions. + */ + struct mbedtls_asn1_named_data *next; + + /** Merge next item into the current one? + * + * This field exists for the sake of Mbed TLS's X.509 certificate parsing + * code and may change in future versions of the library. + */ + unsigned char MBEDTLS_PRIVATE(next_merged); } mbedtls_asn1_named_data; +#if defined(MBEDTLS_ASN1_PARSE_C) || defined(MBEDTLS_X509_CREATE_C) || \ + defined(MBEDTLS_PSA_UTIL_HAVE_ECDSA) /** * \brief Get the length of an ASN.1 element. * Updates the pointer to immediately behind the length. @@ -235,7 +245,9 @@ int mbedtls_asn1_get_len(unsigned char **p, int mbedtls_asn1_get_tag(unsigned char **p, const unsigned char *end, size_t *len, int tag); +#endif /* MBEDTLS_ASN1_PARSE_C || MBEDTLS_X509_CREATE_C || MBEDTLS_PSA_UTIL_HAVE_ECDSA */ +#if defined(MBEDTLS_ASN1_PARSE_C) /** * \brief Retrieve a boolean ASN.1 tag and its value. * Updates the pointer to immediately behind the full tag. @@ -580,31 +592,49 @@ int mbedtls_asn1_get_alg_null(unsigned char **p, * * \return NULL if not found, or a pointer to the existing entry. */ -mbedtls_asn1_named_data *mbedtls_asn1_find_named_data(mbedtls_asn1_named_data *list, - const char *oid, size_t len); +const mbedtls_asn1_named_data *mbedtls_asn1_find_named_data(const mbedtls_asn1_named_data *list, + const char *oid, size_t len); +#if !defined(MBEDTLS_DEPRECATED_REMOVED) /** * \brief Free a mbedtls_asn1_named_data entry * + * \deprecated This function is deprecated and will be removed in a + * future version of the library. + * Please use mbedtls_asn1_free_named_data_list() + * or mbedtls_asn1_free_named_data_list_shallow(). + * * \param entry The named data entry to free. * This function calls mbedtls_free() on * `entry->oid.p` and `entry->val.p`. */ -void mbedtls_asn1_free_named_data(mbedtls_asn1_named_data *entry); +void MBEDTLS_DEPRECATED mbedtls_asn1_free_named_data(mbedtls_asn1_named_data *entry); +#endif /* MBEDTLS_DEPRECATED_REMOVED */ /** * \brief Free all entries in a mbedtls_asn1_named_data list. * * \param head Pointer to the head of the list of named data entries to free. - * This function calls mbedtls_asn1_free_named_data() and - * mbedtls_free() on each list element and - * sets \c *head to \c NULL. + * This function calls mbedtls_free() on + * `entry->oid.p` and `entry->val.p` and then on `entry` + * for each list entry, and sets \c *head to \c NULL. */ void mbedtls_asn1_free_named_data_list(mbedtls_asn1_named_data **head); +/** + * \brief Free all shallow entries in a mbedtls_asn1_named_data list, + * but do not free internal pointer targets. + * + * \param name Head of the list of named data entries to free. + * This function calls mbedtls_free() on each list element. + */ +void mbedtls_asn1_free_named_data_list_shallow(mbedtls_asn1_named_data *name); + /** \} name Functions to parse ASN.1 data structures */ /** \} addtogroup asn1_module */ +#endif /* MBEDTLS_ASN1_PARSE_C */ + #ifdef __cplusplus } #endif diff --git a/vendor/mbedtls/include/mbedtls/asn1write.h b/vendor/mbedtls/include/mbedtls/asn1write.h index f453169e2e..0c5a85ac27 100644 --- a/vendor/mbedtls/include/mbedtls/asn1write.h +++ b/vendor/mbedtls/include/mbedtls/asn1write.h @@ -5,28 +5,12 @@ */ /* * Copyright The Mbed TLS Contributors - * SPDX-License-Identifier: Apache-2.0 - * - * Licensed under the Apache License, Version 2.0 (the "License"); you may - * not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT - * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. + * SPDX-License-Identifier: Apache-2.0 OR GPL-2.0-or-later */ #ifndef MBEDTLS_ASN1_WRITE_H #define MBEDTLS_ASN1_WRITE_H -#if !defined(MBEDTLS_CONFIG_FILE) -#include "mbedtls/config.h" -#else -#include MBEDTLS_CONFIG_FILE -#endif +#include "mbedtls/build_info.h" #include "mbedtls/asn1.h" @@ -39,10 +23,21 @@ (g) += ret; \ } while (0) +#define MBEDTLS_ASN1_CHK_CLEANUP_ADD(g, f) \ + do \ + { \ + if ((ret = (f)) < 0) \ + goto cleanup; \ + else \ + (g) += ret; \ + } while (0) + #ifdef __cplusplus extern "C" { #endif +#if defined(MBEDTLS_ASN1_WRITE_C) || defined(MBEDTLS_X509_USE_C) || \ + defined(MBEDTLS_PSA_UTIL_HAVE_ECDSA) /** * \brief Write a length field in ASN.1 format. * @@ -55,7 +50,7 @@ extern "C" { * \return The number of bytes written to \p p on success. * \return A negative \c MBEDTLS_ERR_ASN1_XXX error code on failure. */ -int mbedtls_asn1_write_len(unsigned char **p, unsigned char *start, +int mbedtls_asn1_write_len(unsigned char **p, const unsigned char *start, size_t len); /** * \brief Write an ASN.1 tag in ASN.1 format. @@ -69,9 +64,11 @@ int mbedtls_asn1_write_len(unsigned char **p, unsigned char *start, * \return The number of bytes written to \p p on success. * \return A negative \c MBEDTLS_ERR_ASN1_XXX error code on failure. */ -int mbedtls_asn1_write_tag(unsigned char **p, unsigned char *start, +int mbedtls_asn1_write_tag(unsigned char **p, const unsigned char *start, unsigned char tag); +#endif /* MBEDTLS_ASN1_WRITE_C || MBEDTLS_X509_USE_C || MBEDTLS_PSA_UTIL_HAVE_ECDSA*/ +#if defined(MBEDTLS_ASN1_WRITE_C) /** * \brief Write raw buffer data. * @@ -85,7 +82,7 @@ int mbedtls_asn1_write_tag(unsigned char **p, unsigned char *start, * \return The number of bytes written to \p p on success. * \return A negative \c MBEDTLS_ERR_ASN1_XXX error code on failure. */ -int mbedtls_asn1_write_raw_buffer(unsigned char **p, unsigned char *start, +int mbedtls_asn1_write_raw_buffer(unsigned char **p, const unsigned char *start, const unsigned char *buf, size_t size); #if defined(MBEDTLS_BIGNUM_C) @@ -103,7 +100,7 @@ int mbedtls_asn1_write_raw_buffer(unsigned char **p, unsigned char *start, * \return The number of bytes written to \p p on success. * \return A negative \c MBEDTLS_ERR_ASN1_XXX error code on failure. */ -int mbedtls_asn1_write_mpi(unsigned char **p, unsigned char *start, +int mbedtls_asn1_write_mpi(unsigned char **p, const unsigned char *start, const mbedtls_mpi *X); #endif /* MBEDTLS_BIGNUM_C */ @@ -119,7 +116,7 @@ int mbedtls_asn1_write_mpi(unsigned char **p, unsigned char *start, * \return The number of bytes written to \p p on success. * \return A negative \c MBEDTLS_ERR_ASN1_XXX error code on failure. */ -int mbedtls_asn1_write_null(unsigned char **p, unsigned char *start); +int mbedtls_asn1_write_null(unsigned char **p, const unsigned char *start); /** * \brief Write an OID tag (#MBEDTLS_ASN1_OID) and data @@ -135,7 +132,7 @@ int mbedtls_asn1_write_null(unsigned char **p, unsigned char *start); * \return The number of bytes written to \p p on success. * \return A negative \c MBEDTLS_ERR_ASN1_XXX error code on failure. */ -int mbedtls_asn1_write_oid(unsigned char **p, unsigned char *start, +int mbedtls_asn1_write_oid(unsigned char **p, const unsigned char *start, const char *oid, size_t oid_len); /** @@ -154,7 +151,7 @@ int mbedtls_asn1_write_oid(unsigned char **p, unsigned char *start, * \return A negative \c MBEDTLS_ERR_ASN1_XXX error code on failure. */ int mbedtls_asn1_write_algorithm_identifier(unsigned char **p, - unsigned char *start, + const unsigned char *start, const char *oid, size_t oid_len, size_t par_len); @@ -175,7 +172,7 @@ int mbedtls_asn1_write_algorithm_identifier(unsigned char **p, * \return A negative \c MBEDTLS_ERR_ASN1_XXX error code on failure. */ int mbedtls_asn1_write_algorithm_identifier_ext(unsigned char **p, - unsigned char *start, + const unsigned char *start, const char *oid, size_t oid_len, size_t par_len, int has_par); @@ -192,7 +189,7 @@ int mbedtls_asn1_write_algorithm_identifier_ext(unsigned char **p, * \return The number of bytes written to \p p on success. * \return A negative \c MBEDTLS_ERR_ASN1_XXX error code on failure. */ -int mbedtls_asn1_write_bool(unsigned char **p, unsigned char *start, +int mbedtls_asn1_write_bool(unsigned char **p, const unsigned char *start, int boolean); /** @@ -209,7 +206,7 @@ int mbedtls_asn1_write_bool(unsigned char **p, unsigned char *start, * \return The number of bytes written to \p p on success. * \return A negative \c MBEDTLS_ERR_ASN1_XXX error code on failure. */ -int mbedtls_asn1_write_int(unsigned char **p, unsigned char *start, int val); +int mbedtls_asn1_write_int(unsigned char **p, const unsigned char *start, int val); /** * \brief Write an enum tag (#MBEDTLS_ASN1_ENUMERATED) and value @@ -224,7 +221,7 @@ int mbedtls_asn1_write_int(unsigned char **p, unsigned char *start, int val); * \return The number of bytes written to \p p on success. * \return A negative \c MBEDTLS_ERR_ASN1_XXX error code on failure. */ -int mbedtls_asn1_write_enum(unsigned char **p, unsigned char *start, int val); +int mbedtls_asn1_write_enum(unsigned char **p, const unsigned char *start, int val); /** * \brief Write a string in ASN.1 format using a specific @@ -243,7 +240,7 @@ int mbedtls_asn1_write_enum(unsigned char **p, unsigned char *start, int val); * \return The number of bytes written to \p p on success. * \return A negative error code on failure. */ -int mbedtls_asn1_write_tagged_string(unsigned char **p, unsigned char *start, +int mbedtls_asn1_write_tagged_string(unsigned char **p, const unsigned char *start, int tag, const char *text, size_t text_len); @@ -263,7 +260,7 @@ int mbedtls_asn1_write_tagged_string(unsigned char **p, unsigned char *start, * \return A negative error code on failure. */ int mbedtls_asn1_write_printable_string(unsigned char **p, - unsigned char *start, + const unsigned char *start, const char *text, size_t text_len); /** @@ -281,7 +278,7 @@ int mbedtls_asn1_write_printable_string(unsigned char **p, * \return The number of bytes written to \p p on success. * \return A negative error code on failure. */ -int mbedtls_asn1_write_utf8_string(unsigned char **p, unsigned char *start, +int mbedtls_asn1_write_utf8_string(unsigned char **p, const unsigned char *start, const char *text, size_t text_len); /** @@ -299,7 +296,7 @@ int mbedtls_asn1_write_utf8_string(unsigned char **p, unsigned char *start, * \return The number of bytes written to \p p on success. * \return A negative error code on failure. */ -int mbedtls_asn1_write_ia5_string(unsigned char **p, unsigned char *start, +int mbedtls_asn1_write_ia5_string(unsigned char **p, const unsigned char *start, const char *text, size_t text_len); /** @@ -316,7 +313,7 @@ int mbedtls_asn1_write_ia5_string(unsigned char **p, unsigned char *start, * \return The number of bytes written to \p p on success. * \return A negative error code on failure. */ -int mbedtls_asn1_write_bitstring(unsigned char **p, unsigned char *start, +int mbedtls_asn1_write_bitstring(unsigned char **p, const unsigned char *start, const unsigned char *buf, size_t bits); /** @@ -337,7 +334,7 @@ int mbedtls_asn1_write_bitstring(unsigned char **p, unsigned char *start, * \return A negative error code on failure. */ int mbedtls_asn1_write_named_bitstring(unsigned char **p, - unsigned char *start, + const unsigned char *start, const unsigned char *buf, size_t bits); @@ -355,7 +352,7 @@ int mbedtls_asn1_write_named_bitstring(unsigned char **p, * \return The number of bytes written to \p p on success. * \return A negative error code on failure. */ -int mbedtls_asn1_write_octet_string(unsigned char **p, unsigned char *start, +int mbedtls_asn1_write_octet_string(unsigned char **p, const unsigned char *start, const unsigned char *buf, size_t size); /** @@ -377,7 +374,7 @@ int mbedtls_asn1_write_octet_string(unsigned char **p, unsigned char *start, * the existing buffer to fit \p val_len. * * \return A pointer to the new / existing entry on success. - * \return \c NULL if if there was a memory allocation error. + * \return \c NULL if there was a memory allocation error. */ mbedtls_asn1_named_data *mbedtls_asn1_store_named_data(mbedtls_asn1_named_data **list, const char *oid, size_t oid_len, @@ -388,4 +385,6 @@ mbedtls_asn1_named_data *mbedtls_asn1_store_named_data(mbedtls_asn1_named_data * } #endif +#endif /* MBEDTLS_ASN1_WRITE_C */ + #endif /* MBEDTLS_ASN1_WRITE_H */ diff --git a/vendor/mbedtls/include/mbedtls/base64.h b/vendor/mbedtls/include/mbedtls/base64.h index ec9c408f52..8f459b74c5 100644 --- a/vendor/mbedtls/include/mbedtls/base64.h +++ b/vendor/mbedtls/include/mbedtls/base64.h @@ -5,28 +5,12 @@ */ /* * Copyright The Mbed TLS Contributors - * SPDX-License-Identifier: Apache-2.0 - * - * Licensed under the Apache License, Version 2.0 (the "License"); you may - * not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT - * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. + * SPDX-License-Identifier: Apache-2.0 OR GPL-2.0-or-later */ #ifndef MBEDTLS_BASE64_H #define MBEDTLS_BASE64_H -#if !defined(MBEDTLS_CONFIG_FILE) -#include "mbedtls/config.h" -#else -#include MBEDTLS_CONFIG_FILE -#endif +#include "mbedtls/build_info.h" #include diff --git a/vendor/mbedtls/include/mbedtls/bignum.h b/vendor/mbedtls/include/mbedtls/bignum.h index cbed25984e..71d7b97672 100644 --- a/vendor/mbedtls/include/mbedtls/bignum.h +++ b/vendor/mbedtls/include/mbedtls/bignum.h @@ -5,28 +5,13 @@ */ /* * Copyright The Mbed TLS Contributors - * SPDX-License-Identifier: Apache-2.0 - * - * Licensed under the Apache License, Version 2.0 (the "License"); you may - * not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT - * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. + * SPDX-License-Identifier: Apache-2.0 OR GPL-2.0-or-later */ #ifndef MBEDTLS_BIGNUM_H #define MBEDTLS_BIGNUM_H +#include "mbedtls/private_access.h" -#if !defined(MBEDTLS_CONFIG_FILE) -#include "mbedtls/config.h" -#else -#include MBEDTLS_CONFIG_FILE -#endif +#include "mbedtls/build_info.h" #include #include @@ -66,15 +51,15 @@ #if !defined(MBEDTLS_MPI_WINDOW_SIZE) /* - * Maximum window size used for modular exponentiation. Default: 2 + * Maximum window size used for modular exponentiation. Default: 3 * Minimum value: 1. Maximum value: 6. * * Result is an array of ( 2 ** MBEDTLS_MPI_WINDOW_SIZE ) MPIs used - * for the sliding window calculation. (So 64 by default) + * for the sliding window calculation. (So 8 by default) * * Reduction in size, reduces speed. */ -#define MBEDTLS_MPI_WINDOW_SIZE 2 /**< Maximum window size used. */ +#define MBEDTLS_MPI_WINDOW_SIZE 3 /**< Maximum window size used. */ #endif /* !MBEDTLS_MPI_WINDOW_SIZE */ #if !defined(MBEDTLS_MPI_MAX_SIZE) @@ -132,6 +117,7 @@ #endif /* !MBEDTLS_HAVE_INT64 */ typedef int64_t mbedtls_mpi_sint; typedef uint64_t mbedtls_mpi_uint; +#define MBEDTLS_MPI_UINT_MAX UINT64_MAX #elif defined(__GNUC__) && ( \ defined(__amd64__) || defined(__x86_64__) || \ defined(__ppc64__) || defined(__powerpc64__) || \ @@ -144,6 +130,7 @@ typedef uint64_t mbedtls_mpi_uint; #endif /* MBEDTLS_HAVE_INT64 */ typedef int64_t mbedtls_mpi_sint; typedef uint64_t mbedtls_mpi_uint; +#define MBEDTLS_MPI_UINT_MAX UINT64_MAX #if !defined(MBEDTLS_NO_UDBL_DIVISION) /* mbedtls_t_udbl defined as 128-bit unsigned int */ typedef unsigned int mbedtls_t_udbl __attribute__((mode(TI))); @@ -159,6 +146,7 @@ typedef unsigned int mbedtls_t_udbl __attribute__((mode(TI))); #endif /* !MBEDTLS_HAVE_INT64 */ typedef int64_t mbedtls_mpi_sint; typedef uint64_t mbedtls_mpi_uint; +#define MBEDTLS_MPI_UINT_MAX UINT64_MAX #if !defined(MBEDTLS_NO_UDBL_DIVISION) /* mbedtls_t_udbl defined as 128-bit unsigned int */ typedef __uint128_t mbedtls_t_udbl; @@ -168,6 +156,7 @@ typedef __uint128_t mbedtls_t_udbl; /* Force 64-bit integers with unknown compiler */ typedef int64_t mbedtls_mpi_sint; typedef uint64_t mbedtls_mpi_uint; +#define MBEDTLS_MPI_UINT_MAX UINT64_MAX #endif #endif /* !MBEDTLS_HAVE_INT32 */ @@ -178,12 +167,22 @@ typedef uint64_t mbedtls_mpi_uint; #endif /* !MBEDTLS_HAVE_INT32 */ typedef int32_t mbedtls_mpi_sint; typedef uint32_t mbedtls_mpi_uint; +#define MBEDTLS_MPI_UINT_MAX UINT32_MAX #if !defined(MBEDTLS_NO_UDBL_DIVISION) typedef uint64_t mbedtls_t_udbl; #define MBEDTLS_HAVE_UDBL #endif /* !MBEDTLS_NO_UDBL_DIVISION */ #endif /* !MBEDTLS_HAVE_INT64 */ +/* + * Sanity check that exactly one of MBEDTLS_HAVE_INT32 or MBEDTLS_HAVE_INT64 is defined, + * so that code elsewhere doesn't have to check. + */ +#if (!(defined(MBEDTLS_HAVE_INT32) || defined(MBEDTLS_HAVE_INT64))) || \ + (defined(MBEDTLS_HAVE_INT32) && defined(MBEDTLS_HAVE_INT64)) +#error "Only 32-bit or 64-bit limbs are supported in bignum" +#endif + /** \typedef mbedtls_mpi_uint * \brief The type of machine digits in a bignum, called _limbs_. * @@ -194,7 +193,7 @@ typedef uint64_t mbedtls_t_udbl; /** \typedef mbedtls_mpi_sint * \brief The signed type corresponding to #mbedtls_mpi_uint. * - * This is always a signed integer type with no padding bits. The size + * This is always an signed integer type with no padding bits. The size * is platform-dependent. */ @@ -206,6 +205,12 @@ extern "C" { * \brief MPI structure */ typedef struct mbedtls_mpi { + /** Pointer to limbs. + * + * This may be \c NULL if \c n is 0. + */ + mbedtls_mpi_uint *MBEDTLS_PRIVATE(p); + /** Sign: -1 if the mpi is negative, 1 otherwise. * * The number 0 must be represented with `s = +1`. Although many library @@ -217,16 +222,19 @@ typedef struct mbedtls_mpi { * Note that this implies that calloc() or `... = {0}` does not create * a valid MPI representation. You must call mbedtls_mpi_init(). */ - int s; + signed short MBEDTLS_PRIVATE(s); /** Total number of limbs in \c p. */ - size_t n; - - /** Pointer to limbs. - * - * This may be \c NULL if \c n is 0. + unsigned short MBEDTLS_PRIVATE(n); + /* Make sure that MBEDTLS_MPI_MAX_LIMBS fits in n. + * Use the same limit value on all platforms so that we don't have to + * think about different behavior on the rare platforms where + * unsigned short can store values larger than the minimum required by + * the C language, which is 65535. */ - mbedtls_mpi_uint *p; +#if MBEDTLS_MPI_MAX_LIMBS > 65535 +#error "MBEDTLS_MPI_MAX_LIMBS > 65535 is not supported" +#endif } mbedtls_mpi; @@ -597,6 +605,8 @@ int mbedtls_mpi_write_binary_le(const mbedtls_mpi *X, * \brief Perform a left-shift on an MPI: X <<= count * * \param X The MPI to shift. This must point to an initialized MPI. + * The MPI pointed by \p X may be resized to fit + * the resulting number. * \param count The number of bits to shift by. * * \return \c 0 if successful. @@ -992,37 +1002,6 @@ int mbedtls_mpi_gcd(mbedtls_mpi *G, const mbedtls_mpi *A, int mbedtls_mpi_inv_mod(mbedtls_mpi *X, const mbedtls_mpi *A, const mbedtls_mpi *N); -#if !defined(MBEDTLS_DEPRECATED_REMOVED) -#if defined(MBEDTLS_DEPRECATED_WARNING) -#define MBEDTLS_DEPRECATED __attribute__((deprecated)) -#else -#define MBEDTLS_DEPRECATED -#endif -/** - * \brief Perform a Miller-Rabin primality test with error - * probability of 2-80. - * - * \deprecated Superseded by mbedtls_mpi_is_prime_ext() which allows - * specifying the number of Miller-Rabin rounds. - * - * \param X The MPI to check for primality. - * This must point to an initialized MPI. - * \param f_rng The RNG function to use. This must not be \c NULL. - * \param p_rng The RNG parameter to be passed to \p f_rng. - * This may be \c NULL if \p f_rng doesn't use a - * context parameter. - * - * \return \c 0 if successful, i.e. \p X is probably prime. - * \return #MBEDTLS_ERR_MPI_ALLOC_FAILED if a memory allocation failed. - * \return #MBEDTLS_ERR_MPI_NOT_ACCEPTABLE if \p X is not prime. - * \return Another negative error code on other kinds of failure. - */ -MBEDTLS_DEPRECATED int mbedtls_mpi_is_prime(const mbedtls_mpi *X, - int (*f_rng)(void *, unsigned char *, size_t), - void *p_rng); -#undef MBEDTLS_DEPRECATED -#endif /* !MBEDTLS_DEPRECATED_REMOVED */ - /** * \brief Miller-Rabin primality test. * diff --git a/vendor/mbedtls/include/mbedtls/block_cipher.h b/vendor/mbedtls/include/mbedtls/block_cipher.h new file mode 100644 index 0000000000..3f60f6f7dd --- /dev/null +++ b/vendor/mbedtls/include/mbedtls/block_cipher.h @@ -0,0 +1,76 @@ +/** + * \file block_cipher.h + * + * \brief Internal abstraction layer. + */ +/* + * Copyright The Mbed TLS Contributors + * SPDX-License-Identifier: Apache-2.0 OR GPL-2.0-or-later + */ +#ifndef MBEDTLS_BLOCK_CIPHER_H +#define MBEDTLS_BLOCK_CIPHER_H + +#include "mbedtls/private_access.h" + +#include "mbedtls/build_info.h" + +#if defined(MBEDTLS_AES_C) +#include "mbedtls/aes.h" +#endif +#if defined(MBEDTLS_ARIA_C) +#include "mbedtls/aria.h" +#endif +#if defined(MBEDTLS_CAMELLIA_C) +#include "mbedtls/camellia.h" +#endif + +#if defined(MBEDTLS_BLOCK_CIPHER_SOME_PSA) +#include "psa/crypto_types.h" +#endif + +#ifdef __cplusplus +extern "C" { +#endif + +typedef enum { + MBEDTLS_BLOCK_CIPHER_ID_NONE = 0, /**< Unset. */ + MBEDTLS_BLOCK_CIPHER_ID_AES, /**< The AES cipher. */ + MBEDTLS_BLOCK_CIPHER_ID_CAMELLIA, /**< The Camellia cipher. */ + MBEDTLS_BLOCK_CIPHER_ID_ARIA, /**< The Aria cipher. */ +} mbedtls_block_cipher_id_t; + +/** + * Used internally to indicate whether a context uses legacy or PSA. + * + * Internal use only. + */ +typedef enum { + MBEDTLS_BLOCK_CIPHER_ENGINE_LEGACY = 0, + MBEDTLS_BLOCK_CIPHER_ENGINE_PSA, +} mbedtls_block_cipher_engine_t; + +typedef struct { + mbedtls_block_cipher_id_t MBEDTLS_PRIVATE(id); +#if defined(MBEDTLS_BLOCK_CIPHER_SOME_PSA) + mbedtls_block_cipher_engine_t MBEDTLS_PRIVATE(engine); + mbedtls_svc_key_id_t MBEDTLS_PRIVATE(psa_key_id); +#endif + union { + unsigned dummy; /* Make the union non-empty even with no supported algorithms. */ +#if defined(MBEDTLS_AES_C) + mbedtls_aes_context MBEDTLS_PRIVATE(aes); +#endif +#if defined(MBEDTLS_ARIA_C) + mbedtls_aria_context MBEDTLS_PRIVATE(aria); +#endif +#if defined(MBEDTLS_CAMELLIA_C) + mbedtls_camellia_context MBEDTLS_PRIVATE(camellia); +#endif + } MBEDTLS_PRIVATE(ctx); +} mbedtls_block_cipher_context_t; + +#ifdef __cplusplus +} +#endif + +#endif /* MBEDTLS_BLOCK_CIPHER_H */ diff --git a/vendor/mbedtls/include/mbedtls/blowfish.h b/vendor/mbedtls/include/mbedtls/blowfish.h deleted file mode 100644 index 7936d2f8a4..0000000000 --- a/vendor/mbedtls/include/mbedtls/blowfish.h +++ /dev/null @@ -1,287 +0,0 @@ -/** - * \file blowfish.h - * - * \brief Blowfish block cipher - */ -/* - * Copyright The Mbed TLS Contributors - * SPDX-License-Identifier: Apache-2.0 - * - * Licensed under the Apache License, Version 2.0 (the "License"); you may - * not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT - * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ -#ifndef MBEDTLS_BLOWFISH_H -#define MBEDTLS_BLOWFISH_H - -#if !defined(MBEDTLS_CONFIG_FILE) -#include "mbedtls/config.h" -#else -#include MBEDTLS_CONFIG_FILE -#endif - -#include -#include - -#include "mbedtls/platform_util.h" - -#define MBEDTLS_BLOWFISH_ENCRYPT 1 -#define MBEDTLS_BLOWFISH_DECRYPT 0 -#define MBEDTLS_BLOWFISH_MAX_KEY_BITS 448 -#define MBEDTLS_BLOWFISH_MIN_KEY_BITS 32 -#define MBEDTLS_BLOWFISH_ROUNDS 16 /**< Rounds to use. When increasing this value, make sure to extend the initialisation vectors */ -#define MBEDTLS_BLOWFISH_BLOCKSIZE 8 /* Blowfish uses 64 bit blocks */ - -#if !defined(MBEDTLS_DEPRECATED_REMOVED) -#define MBEDTLS_ERR_BLOWFISH_INVALID_KEY_LENGTH MBEDTLS_DEPRECATED_NUMERIC_CONSTANT(-0x0016) -#endif /* !MBEDTLS_DEPRECATED_REMOVED */ -/** Bad input data. */ -#define MBEDTLS_ERR_BLOWFISH_BAD_INPUT_DATA -0x0016 - -/** Invalid data input length. */ -#define MBEDTLS_ERR_BLOWFISH_INVALID_INPUT_LENGTH -0x0018 - -/* MBEDTLS_ERR_BLOWFISH_HW_ACCEL_FAILED is deprecated and should not be used. - */ -/** Blowfish hardware accelerator failed. */ -#define MBEDTLS_ERR_BLOWFISH_HW_ACCEL_FAILED -0x0017 - -#ifdef __cplusplus -extern "C" { -#endif - -#if !defined(MBEDTLS_BLOWFISH_ALT) -// Regular implementation -// - -/** - * \brief Blowfish context structure - */ -typedef struct mbedtls_blowfish_context { - uint32_t P[MBEDTLS_BLOWFISH_ROUNDS + 2]; /*!< Blowfish round keys */ - uint32_t S[4][256]; /*!< key dependent S-boxes */ -} -mbedtls_blowfish_context; - -#else /* MBEDTLS_BLOWFISH_ALT */ -#include "blowfish_alt.h" -#endif /* MBEDTLS_BLOWFISH_ALT */ - -/** - * \brief Initialize a Blowfish context. - * - * \param ctx The Blowfish context to be initialized. - * This must not be \c NULL. - */ -void mbedtls_blowfish_init(mbedtls_blowfish_context *ctx); - -/** - * \brief Clear a Blowfish context. - * - * \param ctx The Blowfish context to be cleared. - * This may be \c NULL, in which case this function - * returns immediately. If it is not \c NULL, it must - * point to an initialized Blowfish context. - */ -void mbedtls_blowfish_free(mbedtls_blowfish_context *ctx); - -/** - * \brief Perform a Blowfish key schedule operation. - * - * \param ctx The Blowfish context to perform the key schedule on. - * \param key The encryption key. This must be a readable buffer of - * length \p keybits Bits. - * \param keybits The length of \p key in Bits. This must be between - * \c 32 and \c 448 and a multiple of \c 8. - * - * \return \c 0 if successful. - * \return A negative error code on failure. - */ -int mbedtls_blowfish_setkey(mbedtls_blowfish_context *ctx, const unsigned char *key, - unsigned int keybits); - -/** - * \brief Perform a Blowfish-ECB block encryption/decryption operation. - * - * \param ctx The Blowfish context to use. This must be initialized - * and bound to a key. - * \param mode The mode of operation. Possible values are - * #MBEDTLS_BLOWFISH_ENCRYPT for encryption, or - * #MBEDTLS_BLOWFISH_DECRYPT for decryption. - * \param input The input block. This must be a readable buffer - * of size \c 8 Bytes. - * \param output The output block. This must be a writable buffer - * of size \c 8 Bytes. - * - * \return \c 0 if successful. - * \return A negative error code on failure. - */ -int mbedtls_blowfish_crypt_ecb(mbedtls_blowfish_context *ctx, - int mode, - const unsigned char input[MBEDTLS_BLOWFISH_BLOCKSIZE], - unsigned char output[MBEDTLS_BLOWFISH_BLOCKSIZE]); - -#if defined(MBEDTLS_CIPHER_MODE_CBC) -/** - * \brief Perform a Blowfish-CBC buffer encryption/decryption operation. - * - * \note Upon exit, the content of the IV is updated so that you can - * call the function same function again on the following - * block(s) of data and get the same result as if it was - * encrypted in one call. This allows a "streaming" usage. - * If on the other hand you need to retain the contents of the - * IV, you should either save it manually or use the cipher - * module instead. - * - * \param ctx The Blowfish context to use. This must be initialized - * and bound to a key. - * \param mode The mode of operation. Possible values are - * #MBEDTLS_BLOWFISH_ENCRYPT for encryption, or - * #MBEDTLS_BLOWFISH_DECRYPT for decryption. - * \param length The length of the input data in Bytes. This must be - * multiple of \c 8. - * \param iv The initialization vector. This must be a read/write buffer - * of length \c 8 Bytes. It is updated by this function. - * \param input The input data. This must be a readable buffer of length - * \p length Bytes. - * \param output The output data. This must be a writable buffer of length - * \p length Bytes. - * - * \return \c 0 if successful. - * \return A negative error code on failure. - */ -int mbedtls_blowfish_crypt_cbc(mbedtls_blowfish_context *ctx, - int mode, - size_t length, - unsigned char iv[MBEDTLS_BLOWFISH_BLOCKSIZE], - const unsigned char *input, - unsigned char *output); -#endif /* MBEDTLS_CIPHER_MODE_CBC */ - -#if defined(MBEDTLS_CIPHER_MODE_CFB) -/** - * \brief Perform a Blowfish CFB buffer encryption/decryption operation. - * - * \note Upon exit, the content of the IV is updated so that you can - * call the function same function again on the following - * block(s) of data and get the same result as if it was - * encrypted in one call. This allows a "streaming" usage. - * If on the other hand you need to retain the contents of the - * IV, you should either save it manually or use the cipher - * module instead. - * - * \param ctx The Blowfish context to use. This must be initialized - * and bound to a key. - * \param mode The mode of operation. Possible values are - * #MBEDTLS_BLOWFISH_ENCRYPT for encryption, or - * #MBEDTLS_BLOWFISH_DECRYPT for decryption. - * \param length The length of the input data in Bytes. - * \param iv_off The offset in the initialization vector. - * The value pointed to must be smaller than \c 8 Bytes. - * It is updated by this function to support the aforementioned - * streaming usage. - * \param iv The initialization vector. This must be a read/write buffer - * of size \c 8 Bytes. It is updated after use. - * \param input The input data. This must be a readable buffer of length - * \p length Bytes. - * \param output The output data. This must be a writable buffer of length - * \p length Bytes. - * - * \return \c 0 if successful. - * \return A negative error code on failure. - */ -int mbedtls_blowfish_crypt_cfb64(mbedtls_blowfish_context *ctx, - int mode, - size_t length, - size_t *iv_off, - unsigned char iv[MBEDTLS_BLOWFISH_BLOCKSIZE], - const unsigned char *input, - unsigned char *output); -#endif /*MBEDTLS_CIPHER_MODE_CFB */ - -#if defined(MBEDTLS_CIPHER_MODE_CTR) -/** - * \brief Perform a Blowfish-CTR buffer encryption/decryption operation. - * - * \warning You must never reuse a nonce value with the same key. Doing so - * would void the encryption for the two messages encrypted with - * the same nonce and key. - * - * There are two common strategies for managing nonces with CTR: - * - * 1. You can handle everything as a single message processed over - * successive calls to this function. In that case, you want to - * set \p nonce_counter and \p nc_off to 0 for the first call, and - * then preserve the values of \p nonce_counter, \p nc_off and \p - * stream_block across calls to this function as they will be - * updated by this function. - * - * With this strategy, you must not encrypt more than 2**64 - * blocks of data with the same key. - * - * 2. You can encrypt separate messages by dividing the \p - * nonce_counter buffer in two areas: the first one used for a - * per-message nonce, handled by yourself, and the second one - * updated by this function internally. - * - * For example, you might reserve the first 4 bytes for the - * per-message nonce, and the last 4 bytes for internal use. In that - * case, before calling this function on a new message you need to - * set the first 4 bytes of \p nonce_counter to your chosen nonce - * value, the last 4 to 0, and \p nc_off to 0 (which will cause \p - * stream_block to be ignored). That way, you can encrypt at most - * 2**32 messages of up to 2**32 blocks each with the same key. - * - * The per-message nonce (or information sufficient to reconstruct - * it) needs to be communicated with the ciphertext and must be unique. - * The recommended way to ensure uniqueness is to use a message - * counter. - * - * Note that for both strategies, sizes are measured in blocks and - * that a Blowfish block is 8 bytes. - * - * \warning Upon return, \p stream_block contains sensitive data. Its - * content must not be written to insecure storage and should be - * securely discarded as soon as it's no longer needed. - * - * \param ctx The Blowfish context to use. This must be initialized - * and bound to a key. - * \param length The length of the input data in Bytes. - * \param nc_off The offset in the current stream_block (for resuming - * within current cipher stream). The offset pointer - * should be \c 0 at the start of a stream and must be - * smaller than \c 8. It is updated by this function. - * \param nonce_counter The 64-bit nonce and counter. This must point to a - * read/write buffer of length \c 8 Bytes. - * \param stream_block The saved stream-block for resuming. This must point to - * a read/write buffer of length \c 8 Bytes. - * \param input The input data. This must be a readable buffer of - * length \p length Bytes. - * \param output The output data. This must be a writable buffer of - * length \p length Bytes. - * - * \return \c 0 if successful. - * \return A negative error code on failure. - */ -int mbedtls_blowfish_crypt_ctr(mbedtls_blowfish_context *ctx, - size_t length, - size_t *nc_off, - unsigned char nonce_counter[MBEDTLS_BLOWFISH_BLOCKSIZE], - unsigned char stream_block[MBEDTLS_BLOWFISH_BLOCKSIZE], - const unsigned char *input, - unsigned char *output); -#endif /* MBEDTLS_CIPHER_MODE_CTR */ - -#ifdef __cplusplus -} -#endif - -#endif /* blowfish.h */ diff --git a/vendor/mbedtls/include/mbedtls/build_info.h b/vendor/mbedtls/include/mbedtls/build_info.h new file mode 100644 index 0000000000..eab167f383 --- /dev/null +++ b/vendor/mbedtls/include/mbedtls/build_info.h @@ -0,0 +1,176 @@ +/** + * \file mbedtls/build_info.h + * + * \brief Build-time configuration info + * + * Include this file if you need to depend on the + * configuration options defined in mbedtls_config.h or MBEDTLS_CONFIG_FILE + */ +/* + * Copyright The Mbed TLS Contributors + * SPDX-License-Identifier: Apache-2.0 OR GPL-2.0-or-later + */ + +#ifndef MBEDTLS_BUILD_INFO_H +#define MBEDTLS_BUILD_INFO_H + +/* + * This set of compile-time defines can be used to determine the version number + * of the Mbed TLS library used. Run-time variables for the same can be found in + * version.h + */ + +/** + * The version number x.y.z is split into three parts. + * Major, Minor, Patchlevel + */ +#define MBEDTLS_VERSION_MAJOR 3 +#define MBEDTLS_VERSION_MINOR 6 +#define MBEDTLS_VERSION_PATCH 0 + +/** + * The single version number has the following structure: + * MMNNPP00 + * Major version | Minor version | Patch version + */ +#define MBEDTLS_VERSION_NUMBER 0x03060000 +#define MBEDTLS_VERSION_STRING "3.6.0" +#define MBEDTLS_VERSION_STRING_FULL "Mbed TLS 3.6.0" + +/* Macros for build-time platform detection */ + +#if !defined(MBEDTLS_ARCH_IS_ARM64) && \ + (defined(__aarch64__) || defined(_M_ARM64) || defined(_M_ARM64EC)) +#define MBEDTLS_ARCH_IS_ARM64 +#endif + +#if !defined(MBEDTLS_ARCH_IS_ARM32) && \ + (defined(__arm__) || defined(_M_ARM) || \ + defined(_M_ARMT) || defined(__thumb__) || defined(__thumb2__)) +#define MBEDTLS_ARCH_IS_ARM32 +#endif + +#if !defined(MBEDTLS_ARCH_IS_X64) && \ + (defined(__amd64__) || defined(__x86_64__) || \ + ((defined(_M_X64) || defined(_M_AMD64)) && !defined(_M_ARM64EC))) +#define MBEDTLS_ARCH_IS_X64 +#endif + +#if !defined(MBEDTLS_ARCH_IS_X86) && \ + (defined(__i386__) || defined(_X86_) || \ + (defined(_M_IX86) && !defined(_M_I86))) +#define MBEDTLS_ARCH_IS_X86 +#endif + +#if !defined(MBEDTLS_PLATFORM_IS_WINDOWS_ON_ARM64) && \ + (defined(_M_ARM64) || defined(_M_ARM64EC)) +#define MBEDTLS_PLATFORM_IS_WINDOWS_ON_ARM64 +#endif + +/* This is defined if the architecture is Armv8-A, or higher */ +#if !defined(MBEDTLS_ARCH_IS_ARMV8_A) +#if defined(__ARM_ARCH) && defined(__ARM_ARCH_PROFILE) +#if (__ARM_ARCH >= 8) && (__ARM_ARCH_PROFILE == 'A') +/* GCC, clang, armclang and IAR */ +#define MBEDTLS_ARCH_IS_ARMV8_A +#endif +#elif defined(__ARM_ARCH_8A) +/* Alternative defined by clang */ +#define MBEDTLS_ARCH_IS_ARMV8_A +#elif defined(_M_ARM64) || defined(_M_ARM64EC) +/* MSVC ARM64 is at least Armv8.0-A */ +#define MBEDTLS_ARCH_IS_ARMV8_A +#endif +#endif + +#if defined(__GNUC__) && !defined(__ARMCC_VERSION) && !defined(__clang__) \ + && !defined(__llvm__) && !defined(__INTEL_COMPILER) +/* Defined if the compiler really is gcc and not clang, etc */ +#define MBEDTLS_COMPILER_IS_GCC +#define MBEDTLS_GCC_VERSION \ + (__GNUC__ * 10000 + __GNUC_MINOR__ * 100 + __GNUC_PATCHLEVEL__) +#endif + +#if defined(_MSC_VER) && !defined(_CRT_SECURE_NO_DEPRECATE) +#define _CRT_SECURE_NO_DEPRECATE 1 +#endif + +/* Define `inline` on some non-C99-compliant compilers. */ +#if (defined(__ARMCC_VERSION) || defined(_MSC_VER)) && \ + !defined(inline) && !defined(__cplusplus) +#define inline __inline +#endif + +/* X.509, TLS and non-PSA crypto configuration */ +#if !defined(MBEDTLS_CONFIG_FILE) +#include "mbedtls/mbedtls_config.h" +#else +#include MBEDTLS_CONFIG_FILE +#endif + +#if defined(MBEDTLS_CONFIG_VERSION) && ( \ + MBEDTLS_CONFIG_VERSION < 0x03000000 || \ + MBEDTLS_CONFIG_VERSION > MBEDTLS_VERSION_NUMBER) +#error "Invalid config version, defined value of MBEDTLS_CONFIG_VERSION is unsupported" +#endif + +/* Target and application specific configurations + * + * Allow user to override any previous default. + * + */ +#if defined(MBEDTLS_USER_CONFIG_FILE) +#include MBEDTLS_USER_CONFIG_FILE +#endif + +/* PSA crypto configuration */ +#if defined(MBEDTLS_PSA_CRYPTO_CONFIG) +#if defined(MBEDTLS_PSA_CRYPTO_CONFIG_FILE) +#include MBEDTLS_PSA_CRYPTO_CONFIG_FILE +#else +#include "psa/crypto_config.h" +#endif +#if defined(MBEDTLS_PSA_CRYPTO_USER_CONFIG_FILE) +#include MBEDTLS_PSA_CRYPTO_USER_CONFIG_FILE +#endif +#endif /* defined(MBEDTLS_PSA_CRYPTO_CONFIG) */ + +/* Auto-enable MBEDTLS_CTR_DRBG_USE_128_BIT_KEY if + * MBEDTLS_AES_ONLY_128_BIT_KEY_LENGTH and MBEDTLS_CTR_DRBG_C defined + * to ensure a 128-bit key size in CTR_DRBG. + */ +#if defined(MBEDTLS_AES_ONLY_128_BIT_KEY_LENGTH) && defined(MBEDTLS_CTR_DRBG_C) +#define MBEDTLS_CTR_DRBG_USE_128_BIT_KEY +#endif + +/* Auto-enable MBEDTLS_MD_C if needed by a module that didn't require it + * in a previous release, to ensure backwards compatibility. + */ +#if defined(MBEDTLS_PKCS5_C) +#define MBEDTLS_MD_C +#endif + +/* PSA crypto specific configuration options + * - If config_psa.h reads a configuration option in preprocessor directive, + * this symbol should be set before its inclusion. (e.g. MBEDTLS_MD_C) + * - If config_psa.h writes a configuration option in conditional directive, + * this symbol should be consulted after its inclusion. + * (e.g. MBEDTLS_MD_LIGHT) + */ +#if defined(MBEDTLS_PSA_CRYPTO_CONFIG) /* PSA_WANT_xxx influences MBEDTLS_xxx */ || \ + defined(MBEDTLS_PSA_CRYPTO_C) /* MBEDTLS_xxx influences PSA_WANT_xxx */ || \ + defined(MBEDTLS_PSA_CRYPTO_CLIENT) /* The same as the previous, but with separation only */ +#include "mbedtls/config_psa.h" +#endif + +#include "mbedtls/config_adjust_legacy_crypto.h" + +#include "mbedtls/config_adjust_x509.h" + +#include "mbedtls/config_adjust_ssl.h" + +/* Make sure all configuration symbols are set before including check_config.h, + * even the ones that are calculated programmatically. */ +#include "mbedtls/check_config.h" + +#endif /* MBEDTLS_BUILD_INFO_H */ diff --git a/vendor/mbedtls/include/mbedtls/camellia.h b/vendor/mbedtls/include/mbedtls/camellia.h index e840947d4b..557f472531 100644 --- a/vendor/mbedtls/include/mbedtls/camellia.h +++ b/vendor/mbedtls/include/mbedtls/camellia.h @@ -5,28 +5,13 @@ */ /* * Copyright The Mbed TLS Contributors - * SPDX-License-Identifier: Apache-2.0 - * - * Licensed under the Apache License, Version 2.0 (the "License"); you may - * not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT - * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. + * SPDX-License-Identifier: Apache-2.0 OR GPL-2.0-or-later */ #ifndef MBEDTLS_CAMELLIA_H #define MBEDTLS_CAMELLIA_H +#include "mbedtls/private_access.h" -#if !defined(MBEDTLS_CONFIG_FILE) -#include "mbedtls/config.h" -#else -#include MBEDTLS_CONFIG_FILE -#endif +#include "mbedtls/build_info.h" #include #include @@ -36,20 +21,12 @@ #define MBEDTLS_CAMELLIA_ENCRYPT 1 #define MBEDTLS_CAMELLIA_DECRYPT 0 -#if !defined(MBEDTLS_DEPRECATED_REMOVED) -#define MBEDTLS_ERR_CAMELLIA_INVALID_KEY_LENGTH MBEDTLS_DEPRECATED_NUMERIC_CONSTANT(-0x0024) -#endif /* !MBEDTLS_DEPRECATED_REMOVED */ /** Bad input data. */ #define MBEDTLS_ERR_CAMELLIA_BAD_INPUT_DATA -0x0024 /** Invalid data input length. */ #define MBEDTLS_ERR_CAMELLIA_INVALID_INPUT_LENGTH -0x0026 -/* MBEDTLS_ERR_CAMELLIA_HW_ACCEL_FAILED is deprecated and should not be used. - */ -/** Camellia hardware accelerator failed. */ -#define MBEDTLS_ERR_CAMELLIA_HW_ACCEL_FAILED -0x0027 - #ifdef __cplusplus extern "C" { #endif @@ -62,8 +39,8 @@ extern "C" { * \brief CAMELLIA context structure */ typedef struct mbedtls_camellia_context { - int nr; /*!< number of rounds */ - uint32_t rk[68]; /*!< CAMELLIA round keys */ + int MBEDTLS_PRIVATE(nr); /*!< number of rounds */ + uint32_t MBEDTLS_PRIVATE(rk)[68]; /*!< CAMELLIA round keys */ } mbedtls_camellia_context; @@ -104,6 +81,7 @@ int mbedtls_camellia_setkey_enc(mbedtls_camellia_context *ctx, const unsigned char *key, unsigned int keybits); +#if !defined(MBEDTLS_BLOCK_CIPHER_NO_DECRYPT) /** * \brief Perform a CAMELLIA key schedule operation for decryption. * @@ -119,6 +97,7 @@ int mbedtls_camellia_setkey_enc(mbedtls_camellia_context *ctx, int mbedtls_camellia_setkey_dec(mbedtls_camellia_context *ctx, const unsigned char *key, unsigned int keybits); +#endif /* !MBEDTLS_BLOCK_CIPHER_NO_DECRYPT */ /** * \brief Perform a CAMELLIA-ECB block encryption/decryption operation. diff --git a/vendor/mbedtls/include/mbedtls/ccm.h b/vendor/mbedtls/include/mbedtls/ccm.h index f082aba054..1da57c921b 100644 --- a/vendor/mbedtls/include/mbedtls/ccm.h +++ b/vendor/mbedtls/include/mbedtls/ccm.h @@ -29,41 +29,31 @@ */ /* * Copyright The Mbed TLS Contributors - * SPDX-License-Identifier: Apache-2.0 - * - * Licensed under the Apache License, Version 2.0 (the "License"); you may - * not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT - * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. + * SPDX-License-Identifier: Apache-2.0 OR GPL-2.0-or-later */ #ifndef MBEDTLS_CCM_H #define MBEDTLS_CCM_H +#include "mbedtls/private_access.h" -#if !defined(MBEDTLS_CONFIG_FILE) -#include "mbedtls/config.h" -#else -#include MBEDTLS_CONFIG_FILE -#endif +#include "mbedtls/build_info.h" #include "mbedtls/cipher.h" +#if defined(MBEDTLS_BLOCK_CIPHER_C) +#include "mbedtls/block_cipher.h" +#endif + +#define MBEDTLS_CCM_DECRYPT 0 +#define MBEDTLS_CCM_ENCRYPT 1 +#define MBEDTLS_CCM_STAR_DECRYPT 2 +#define MBEDTLS_CCM_STAR_ENCRYPT 3 + /** Bad input parameters to the function. */ #define MBEDTLS_ERR_CCM_BAD_INPUT -0x000D /** Authenticated decryption failed. */ #define MBEDTLS_ERR_CCM_AUTH_FAILED -0x000F -/* MBEDTLS_ERR_CCM_HW_ACCEL_FAILED is deprecated and should not be used. */ -/** CCM hardware accelerator failed. */ -#define MBEDTLS_ERR_CCM_HW_ACCEL_FAILED -0x0011 - #ifdef __cplusplus extern "C" { #endif @@ -77,7 +67,30 @@ extern "C" { * to the APIs called. */ typedef struct mbedtls_ccm_context { - mbedtls_cipher_context_t cipher_ctx; /*!< The cipher context used. */ + unsigned char MBEDTLS_PRIVATE(y)[16]; /*!< The Y working buffer */ + unsigned char MBEDTLS_PRIVATE(ctr)[16]; /*!< The counter buffer */ + size_t MBEDTLS_PRIVATE(plaintext_len); /*!< Total plaintext length */ + size_t MBEDTLS_PRIVATE(add_len); /*!< Total authentication data length */ + size_t MBEDTLS_PRIVATE(tag_len); /*!< Total tag length */ + size_t MBEDTLS_PRIVATE(processed); /*!< Track how many bytes of input data + were processed (chunked input). + Used independently for both auth data + and plaintext/ciphertext. + This variable is set to zero after + auth data input is finished. */ + unsigned int MBEDTLS_PRIVATE(q); /*!< The Q working value */ + unsigned int MBEDTLS_PRIVATE(mode); /*!< The operation to perform: + #MBEDTLS_CCM_ENCRYPT or + #MBEDTLS_CCM_DECRYPT or + #MBEDTLS_CCM_STAR_ENCRYPT or + #MBEDTLS_CCM_STAR_DECRYPT. */ +#if defined(MBEDTLS_BLOCK_CIPHER_C) + mbedtls_block_cipher_context_t MBEDTLS_PRIVATE(block_cipher_ctx); /*!< The cipher context used. */ +#else + mbedtls_cipher_context_t MBEDTLS_PRIVATE(cipher_ctx); /*!< The cipher context used. */ +#endif + int MBEDTLS_PRIVATE(state); /*!< Working value holding context's + state. Used for chunked data input */ } mbedtls_ccm_context; @@ -138,10 +151,10 @@ void mbedtls_ccm_free(mbedtls_ccm_context *ctx); * \param iv_len The length of the nonce in Bytes: 7, 8, 9, 10, 11, 12, * or 13. The length L of the message length field is * 15 - \p iv_len. - * \param add The additional data field. If \p add_len is greater than - * zero, \p add must be a readable buffer of at least that + * \param ad The additional data field. If \p ad_len is greater than + * zero, \p ad must be a readable buffer of at least that * length. - * \param add_len The length of additional data in Bytes. + * \param ad_len The length of additional data in Bytes. * This must be less than `2^16 - 2^8`. * \param input The buffer holding the input data. If \p length is greater * than zero, \p input must be a readable buffer of at least @@ -159,7 +172,7 @@ void mbedtls_ccm_free(mbedtls_ccm_context *ctx); */ int mbedtls_ccm_encrypt_and_tag(mbedtls_ccm_context *ctx, size_t length, const unsigned char *iv, size_t iv_len, - const unsigned char *add, size_t add_len, + const unsigned char *ad, size_t ad_len, const unsigned char *input, unsigned char *output, unsigned char *tag, size_t tag_len); @@ -179,14 +192,15 @@ int mbedtls_ccm_encrypt_and_tag(mbedtls_ccm_context *ctx, size_t length, * \param ctx The CCM context to use for encryption. This must be * initialized and bound to a key. * \param length The length of the input data in Bytes. + * For tag length = 0, input length is ignored. * \param iv The initialization vector (nonce). This must be a readable * buffer of at least \p iv_len Bytes. * \param iv_len The length of the nonce in Bytes: 7, 8, 9, 10, 11, 12, * or 13. The length L of the message length field is * 15 - \p iv_len. - * \param add The additional data field. This must be a readable buffer of - * at least \p add_len Bytes. - * \param add_len The length of additional data in Bytes. + * \param ad The additional data field. This must be a readable buffer of + * at least \p ad_len Bytes. + * \param ad_len The length of additional data in Bytes. * This must be less than 2^16 - 2^8. * \param input The buffer holding the input data. If \p length is greater * than zero, \p input must be a readable buffer of at least @@ -207,7 +221,7 @@ int mbedtls_ccm_encrypt_and_tag(mbedtls_ccm_context *ctx, size_t length, */ int mbedtls_ccm_star_encrypt_and_tag(mbedtls_ccm_context *ctx, size_t length, const unsigned char *iv, size_t iv_len, - const unsigned char *add, size_t add_len, + const unsigned char *ad, size_t ad_len, const unsigned char *input, unsigned char *output, unsigned char *tag, size_t tag_len); @@ -223,9 +237,9 @@ int mbedtls_ccm_star_encrypt_and_tag(mbedtls_ccm_context *ctx, size_t length, * \param iv_len The length of the nonce in Bytes: 7, 8, 9, 10, 11, 12, * or 13. The length L of the message length field is * 15 - \p iv_len. - * \param add The additional data field. This must be a readable buffer - * of at least that \p add_len Bytes.. - * \param add_len The length of additional data in Bytes. + * \param ad The additional data field. This must be a readable buffer + * of at least that \p ad_len Bytes.. + * \param ad_len The length of additional data in Bytes. * This must be less than 2^16 - 2^8. * \param input The buffer holding the input data. If \p length is greater * than zero, \p input must be a readable buffer of at least @@ -244,7 +258,7 @@ int mbedtls_ccm_star_encrypt_and_tag(mbedtls_ccm_context *ctx, size_t length, */ int mbedtls_ccm_auth_decrypt(mbedtls_ccm_context *ctx, size_t length, const unsigned char *iv, size_t iv_len, - const unsigned char *add, size_t add_len, + const unsigned char *ad, size_t ad_len, const unsigned char *input, unsigned char *output, const unsigned char *tag, size_t tag_len); @@ -260,14 +274,15 @@ int mbedtls_ccm_auth_decrypt(mbedtls_ccm_context *ctx, size_t length, * \param ctx The CCM context to use for decryption. This must be * initialized and bound to a key. * \param length The length of the input data in Bytes. + * For tag length = 0, input length is ignored. * \param iv The initialization vector (nonce). This must be a readable * buffer of at least \p iv_len Bytes. * \param iv_len The length of the nonce in Bytes: 7, 8, 9, 10, 11, 12, * or 13. The length L of the message length field is * 15 - \p iv_len. - * \param add The additional data field. This must be a readable buffer of - * at least that \p add_len Bytes. - * \param add_len The length of additional data in Bytes. + * \param ad The additional data field. This must be a readable buffer of + * at least that \p ad_len Bytes. + * \param ad_len The length of additional data in Bytes. * This must be less than 2^16 - 2^8. * \param input The buffer holding the input data. If \p length is greater * than zero, \p input must be a readable buffer of at least @@ -289,11 +304,212 @@ int mbedtls_ccm_auth_decrypt(mbedtls_ccm_context *ctx, size_t length, */ int mbedtls_ccm_star_auth_decrypt(mbedtls_ccm_context *ctx, size_t length, const unsigned char *iv, size_t iv_len, - const unsigned char *add, size_t add_len, + const unsigned char *ad, size_t ad_len, const unsigned char *input, unsigned char *output, const unsigned char *tag, size_t tag_len); -#if defined(MBEDTLS_SELF_TEST) && defined(MBEDTLS_AES_C) +/** + * \brief This function starts a CCM encryption or decryption + * operation. + * + * This function and mbedtls_ccm_set_lengths() must be called + * before calling mbedtls_ccm_update_ad() or + * mbedtls_ccm_update(). This function can be called before + * or after mbedtls_ccm_set_lengths(). + * + * \note This function is not implemented in Mbed TLS yet. + * + * \param ctx The CCM context. This must be initialized. + * \param mode The operation to perform: #MBEDTLS_CCM_ENCRYPT or + * #MBEDTLS_CCM_DECRYPT or #MBEDTLS_CCM_STAR_ENCRYPT or + * #MBEDTLS_CCM_STAR_DECRYPT. + * \param iv The initialization vector. This must be a readable buffer + * of at least \p iv_len Bytes. + * \param iv_len The length of the nonce in Bytes: 7, 8, 9, 10, 11, 12, + * or 13. The length L of the message length field is + * 15 - \p iv_len. + * + * \return \c 0 on success. + * \return #MBEDTLS_ERR_CCM_BAD_INPUT on failure: + * \p ctx is in an invalid state, + * \p mode is invalid, + * \p iv_len is invalid (lower than \c 7 or greater than + * \c 13). + */ +int mbedtls_ccm_starts(mbedtls_ccm_context *ctx, + int mode, + const unsigned char *iv, + size_t iv_len); + +/** + * \brief This function declares the lengths of the message + * and additional data for a CCM encryption or decryption + * operation. + * + * This function and mbedtls_ccm_starts() must be called + * before calling mbedtls_ccm_update_ad() or + * mbedtls_ccm_update(). This function can be called before + * or after mbedtls_ccm_starts(). + * + * \note This function is not implemented in Mbed TLS yet. + * + * \param ctx The CCM context. This must be initialized. + * \param total_ad_len The total length of additional data in bytes. + * This must be less than `2^16 - 2^8`. + * \param plaintext_len The length in bytes of the plaintext to encrypt or + * result of the decryption (thus not encompassing the + * additional data that are not encrypted). + * \param tag_len The length of the tag to generate in Bytes: + * 4, 6, 8, 10, 12, 14 or 16. + * For CCM*, zero is also valid. + * + * \return \c 0 on success. + * \return #MBEDTLS_ERR_CCM_BAD_INPUT on failure: + * \p ctx is in an invalid state, + * \p total_ad_len is greater than \c 0xFF00. + */ +int mbedtls_ccm_set_lengths(mbedtls_ccm_context *ctx, + size_t total_ad_len, + size_t plaintext_len, + size_t tag_len); + +/** + * \brief This function feeds an input buffer as associated data + * (authenticated but not encrypted data) in a CCM + * encryption or decryption operation. + * + * You may call this function zero, one or more times + * to pass successive parts of the additional data. The + * lengths \p ad_len of the data parts should eventually add + * up exactly to the total length of additional data + * \c total_ad_len passed to mbedtls_ccm_set_lengths(). You + * may not call this function after calling + * mbedtls_ccm_update(). + * + * \note This function is not implemented in Mbed TLS yet. + * + * \param ctx The CCM context. This must have been started with + * mbedtls_ccm_starts(), the lengths of the message and + * additional data must have been declared with + * mbedtls_ccm_set_lengths() and this must not have yet + * received any input with mbedtls_ccm_update(). + * \param ad The buffer holding the additional data, or \c NULL + * if \p ad_len is \c 0. + * \param ad_len The length of the additional data. If \c 0, + * \p ad may be \c NULL. + * + * \return \c 0 on success. + * \return #MBEDTLS_ERR_CCM_BAD_INPUT on failure: + * \p ctx is in an invalid state, + * total input length too long. + */ +int mbedtls_ccm_update_ad(mbedtls_ccm_context *ctx, + const unsigned char *ad, + size_t ad_len); + +/** + * \brief This function feeds an input buffer into an ongoing CCM + * encryption or decryption operation. + * + * You may call this function zero, one or more times + * to pass successive parts of the input: the plaintext to + * encrypt, or the ciphertext (not including the tag) to + * decrypt. After the last part of the input, call + * mbedtls_ccm_finish(). The lengths \p input_len of the + * data parts should eventually add up exactly to the + * plaintext length \c plaintext_len passed to + * mbedtls_ccm_set_lengths(). + * + * This function may produce output in one of the following + * ways: + * - Immediate output: the output length is always equal + * to the input length. + * - Buffered output: except for the last part of input data, + * the output consists of a whole number of 16-byte blocks. + * If the total input length so far (not including + * associated data) is 16 \* *B* + *A* with *A* < 16 then + * the total output length is 16 \* *B*. + * For the last part of input data, the output length is + * equal to the input length plus the number of bytes (*A*) + * buffered in the previous call to the function (if any). + * The function uses the plaintext length + * \c plaintext_len passed to mbedtls_ccm_set_lengths() + * to detect the last part of input data. + * + * In particular: + * - It is always correct to call this function with + * \p output_size >= \p input_len + 15. + * - If \p input_len is a multiple of 16 for all the calls + * to this function during an operation (not necessary for + * the last one) then it is correct to use \p output_size + * =\p input_len. + * + * \note This function is not implemented in Mbed TLS yet. + * + * \param ctx The CCM context. This must have been started with + * mbedtls_ccm_starts() and the lengths of the message and + * additional data must have been declared with + * mbedtls_ccm_set_lengths(). + * \param input The buffer holding the input data. If \p input_len + * is greater than zero, this must be a readable buffer + * of at least \p input_len bytes. + * \param input_len The length of the input data in bytes. + * \param output The buffer for the output data. If \p output_size + * is greater than zero, this must be a writable buffer of + * at least \p output_size bytes. + * \param output_size The size of the output buffer in bytes. + * See the function description regarding the output size. + * \param output_len On success, \p *output_len contains the actual + * length of the output written in \p output. + * On failure, the content of \p *output_len is + * unspecified. + * + * \return \c 0 on success. + * \return #MBEDTLS_ERR_CCM_BAD_INPUT on failure: + * \p ctx is in an invalid state, + * total input length too long, + * or \p output_size too small. + */ +int mbedtls_ccm_update(mbedtls_ccm_context *ctx, + const unsigned char *input, size_t input_len, + unsigned char *output, size_t output_size, + size_t *output_len); + +/** + * \brief This function finishes the CCM operation and generates + * the authentication tag. + * + * It wraps up the CCM stream, and generates the + * tag. The tag can have a maximum length of 16 Bytes. + * + * \note This function is not implemented in Mbed TLS yet. + * + * \param ctx The CCM context. This must have been started with + * mbedtls_ccm_starts() and the lengths of the message and + * additional data must have been declared with + * mbedtls_ccm_set_lengths(). + * \param tag The buffer for holding the tag. If \p tag_len is greater + * than zero, this must be a writable buffer of at least \p + * tag_len Bytes. + * \param tag_len The length of the tag. Must match the tag length passed to + * mbedtls_ccm_set_lengths() function. + * + * \return \c 0 on success. + * \return #MBEDTLS_ERR_CCM_BAD_INPUT on failure: + * \p ctx is in an invalid state, + * invalid value of \p tag_len, + * the total amount of additional data passed to + * mbedtls_ccm_update_ad() was lower than the total length of + * additional data \c total_ad_len passed to + * mbedtls_ccm_set_lengths(), + * the total amount of input data passed to + * mbedtls_ccm_update() was lower than the plaintext length + * \c plaintext_len passed to mbedtls_ccm_set_lengths(). + */ +int mbedtls_ccm_finish(mbedtls_ccm_context *ctx, + unsigned char *tag, size_t tag_len); + +#if defined(MBEDTLS_SELF_TEST) && defined(MBEDTLS_CCM_GCM_CAN_AES) /** * \brief The CCM checkup routine. * diff --git a/vendor/mbedtls/include/mbedtls/certs.h b/vendor/mbedtls/include/mbedtls/certs.h deleted file mode 100644 index 0ec6971e83..0000000000 --- a/vendor/mbedtls/include/mbedtls/certs.h +++ /dev/null @@ -1,250 +0,0 @@ -/** - * \file certs.h - * - * \brief Sample certificates and DHM parameters for testing - */ -/* - * Copyright The Mbed TLS Contributors - * SPDX-License-Identifier: Apache-2.0 - * - * Licensed under the Apache License, Version 2.0 (the "License"); you may - * not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT - * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ -#ifndef MBEDTLS_CERTS_H -#define MBEDTLS_CERTS_H - -#if !defined(MBEDTLS_CONFIG_FILE) -#include "mbedtls/config.h" -#else -#include MBEDTLS_CONFIG_FILE -#endif - -#include - -#ifdef __cplusplus -extern "C" { -#endif - -/* List of all PEM-encoded CA certificates, terminated by NULL; - * PEM encoded if MBEDTLS_PEM_PARSE_C is enabled, DER encoded - * otherwise. */ -extern const char *mbedtls_test_cas[]; -extern const size_t mbedtls_test_cas_len[]; - -/* List of all DER-encoded CA certificates, terminated by NULL */ -extern const unsigned char *mbedtls_test_cas_der[]; -extern const size_t mbedtls_test_cas_der_len[]; - -#if defined(MBEDTLS_PEM_PARSE_C) -/* Concatenation of all CA certificates in PEM format if available */ -extern const char mbedtls_test_cas_pem[]; -extern const size_t mbedtls_test_cas_pem_len; -#endif /* MBEDTLS_PEM_PARSE_C */ - -/* - * CA test certificates - */ - -extern const char mbedtls_test_ca_crt_ec_pem[]; -extern const char mbedtls_test_ca_key_ec_pem[]; -extern const char mbedtls_test_ca_pwd_ec_pem[]; -extern const char mbedtls_test_ca_key_rsa_pem[]; -extern const char mbedtls_test_ca_pwd_rsa_pem[]; -extern const char mbedtls_test_ca_crt_rsa_sha1_pem[]; -extern const char mbedtls_test_ca_crt_rsa_sha256_pem[]; - -extern const unsigned char mbedtls_test_ca_crt_ec_der[]; -extern const unsigned char mbedtls_test_ca_key_ec_der[]; -extern const unsigned char mbedtls_test_ca_key_rsa_der[]; -extern const unsigned char mbedtls_test_ca_crt_rsa_sha1_der[]; -extern const unsigned char mbedtls_test_ca_crt_rsa_sha256_der[]; - -extern const size_t mbedtls_test_ca_crt_ec_pem_len; -extern const size_t mbedtls_test_ca_key_ec_pem_len; -extern const size_t mbedtls_test_ca_pwd_ec_pem_len; -extern const size_t mbedtls_test_ca_key_rsa_pem_len; -extern const size_t mbedtls_test_ca_pwd_rsa_pem_len; -extern const size_t mbedtls_test_ca_crt_rsa_sha1_pem_len; -extern const size_t mbedtls_test_ca_crt_rsa_sha256_pem_len; - -extern const size_t mbedtls_test_ca_crt_ec_der_len; -extern const size_t mbedtls_test_ca_key_ec_der_len; -extern const size_t mbedtls_test_ca_pwd_ec_der_len; -extern const size_t mbedtls_test_ca_key_rsa_der_len; -extern const size_t mbedtls_test_ca_pwd_rsa_der_len; -extern const size_t mbedtls_test_ca_crt_rsa_sha1_der_len; -extern const size_t mbedtls_test_ca_crt_rsa_sha256_der_len; - -/* Config-dependent dispatch between PEM and DER encoding - * (PEM if enabled, otherwise DER) */ - -extern const char mbedtls_test_ca_crt_ec[]; -extern const char mbedtls_test_ca_key_ec[]; -extern const char mbedtls_test_ca_pwd_ec[]; -extern const char mbedtls_test_ca_key_rsa[]; -extern const char mbedtls_test_ca_pwd_rsa[]; -extern const char mbedtls_test_ca_crt_rsa_sha1[]; -extern const char mbedtls_test_ca_crt_rsa_sha256[]; - -extern const size_t mbedtls_test_ca_crt_ec_len; -extern const size_t mbedtls_test_ca_key_ec_len; -extern const size_t mbedtls_test_ca_pwd_ec_len; -extern const size_t mbedtls_test_ca_key_rsa_len; -extern const size_t mbedtls_test_ca_pwd_rsa_len; -extern const size_t mbedtls_test_ca_crt_rsa_sha1_len; -extern const size_t mbedtls_test_ca_crt_rsa_sha256_len; - -/* Config-dependent dispatch between SHA-1 and SHA-256 - * (SHA-256 if enabled, otherwise SHA-1) */ - -extern const char mbedtls_test_ca_crt_rsa[]; -extern const size_t mbedtls_test_ca_crt_rsa_len; - -/* Config-dependent dispatch between EC and RSA - * (RSA if enabled, otherwise EC) */ - -extern const char *mbedtls_test_ca_crt; -extern const char *mbedtls_test_ca_key; -extern const char *mbedtls_test_ca_pwd; -extern const size_t mbedtls_test_ca_crt_len; -extern const size_t mbedtls_test_ca_key_len; -extern const size_t mbedtls_test_ca_pwd_len; - -/* - * Server test certificates - */ - -extern const char mbedtls_test_srv_crt_ec_pem[]; -extern const char mbedtls_test_srv_key_ec_pem[]; -extern const char mbedtls_test_srv_pwd_ec_pem[]; -extern const char mbedtls_test_srv_key_rsa_pem[]; -extern const char mbedtls_test_srv_pwd_rsa_pem[]; -extern const char mbedtls_test_srv_crt_rsa_sha1_pem[]; -extern const char mbedtls_test_srv_crt_rsa_sha256_pem[]; - -extern const unsigned char mbedtls_test_srv_crt_ec_der[]; -extern const unsigned char mbedtls_test_srv_key_ec_der[]; -extern const unsigned char mbedtls_test_srv_key_rsa_der[]; -extern const unsigned char mbedtls_test_srv_crt_rsa_sha1_der[]; -extern const unsigned char mbedtls_test_srv_crt_rsa_sha256_der[]; - -extern const size_t mbedtls_test_srv_crt_ec_pem_len; -extern const size_t mbedtls_test_srv_key_ec_pem_len; -extern const size_t mbedtls_test_srv_pwd_ec_pem_len; -extern const size_t mbedtls_test_srv_key_rsa_pem_len; -extern const size_t mbedtls_test_srv_pwd_rsa_pem_len; -extern const size_t mbedtls_test_srv_crt_rsa_sha1_pem_len; -extern const size_t mbedtls_test_srv_crt_rsa_sha256_pem_len; - -extern const size_t mbedtls_test_srv_crt_ec_der_len; -extern const size_t mbedtls_test_srv_key_ec_der_len; -extern const size_t mbedtls_test_srv_pwd_ec_der_len; -extern const size_t mbedtls_test_srv_key_rsa_der_len; -extern const size_t mbedtls_test_srv_pwd_rsa_der_len; -extern const size_t mbedtls_test_srv_crt_rsa_sha1_der_len; -extern const size_t mbedtls_test_srv_crt_rsa_sha256_der_len; - -/* Config-dependent dispatch between PEM and DER encoding - * (PEM if enabled, otherwise DER) */ - -extern const char mbedtls_test_srv_crt_ec[]; -extern const char mbedtls_test_srv_key_ec[]; -extern const char mbedtls_test_srv_pwd_ec[]; -extern const char mbedtls_test_srv_key_rsa[]; -extern const char mbedtls_test_srv_pwd_rsa[]; -extern const char mbedtls_test_srv_crt_rsa_sha1[]; -extern const char mbedtls_test_srv_crt_rsa_sha256[]; - -extern const size_t mbedtls_test_srv_crt_ec_len; -extern const size_t mbedtls_test_srv_key_ec_len; -extern const size_t mbedtls_test_srv_pwd_ec_len; -extern const size_t mbedtls_test_srv_key_rsa_len; -extern const size_t mbedtls_test_srv_pwd_rsa_len; -extern const size_t mbedtls_test_srv_crt_rsa_sha1_len; -extern const size_t mbedtls_test_srv_crt_rsa_sha256_len; - -/* Config-dependent dispatch between SHA-1 and SHA-256 - * (SHA-256 if enabled, otherwise SHA-1) */ - -extern const char mbedtls_test_srv_crt_rsa[]; -extern const size_t mbedtls_test_srv_crt_rsa_len; - -/* Config-dependent dispatch between EC and RSA - * (RSA if enabled, otherwise EC) */ - -extern const char *mbedtls_test_srv_crt; -extern const char *mbedtls_test_srv_key; -extern const char *mbedtls_test_srv_pwd; -extern const size_t mbedtls_test_srv_crt_len; -extern const size_t mbedtls_test_srv_key_len; -extern const size_t mbedtls_test_srv_pwd_len; - -/* - * Client test certificates - */ - -extern const char mbedtls_test_cli_crt_ec_pem[]; -extern const char mbedtls_test_cli_key_ec_pem[]; -extern const char mbedtls_test_cli_pwd_ec_pem[]; -extern const char mbedtls_test_cli_key_rsa_pem[]; -extern const char mbedtls_test_cli_pwd_rsa_pem[]; -extern const char mbedtls_test_cli_crt_rsa_pem[]; - -extern const unsigned char mbedtls_test_cli_crt_ec_der[]; -extern const unsigned char mbedtls_test_cli_key_ec_der[]; -extern const unsigned char mbedtls_test_cli_key_rsa_der[]; -extern const unsigned char mbedtls_test_cli_crt_rsa_der[]; - -extern const size_t mbedtls_test_cli_crt_ec_pem_len; -extern const size_t mbedtls_test_cli_key_ec_pem_len; -extern const size_t mbedtls_test_cli_pwd_ec_pem_len; -extern const size_t mbedtls_test_cli_key_rsa_pem_len; -extern const size_t mbedtls_test_cli_pwd_rsa_pem_len; -extern const size_t mbedtls_test_cli_crt_rsa_pem_len; - -extern const size_t mbedtls_test_cli_crt_ec_der_len; -extern const size_t mbedtls_test_cli_key_ec_der_len; -extern const size_t mbedtls_test_cli_key_rsa_der_len; -extern const size_t mbedtls_test_cli_crt_rsa_der_len; - -/* Config-dependent dispatch between PEM and DER encoding - * (PEM if enabled, otherwise DER) */ - -extern const char mbedtls_test_cli_crt_ec[]; -extern const char mbedtls_test_cli_key_ec[]; -extern const char mbedtls_test_cli_pwd_ec[]; -extern const char mbedtls_test_cli_key_rsa[]; -extern const char mbedtls_test_cli_pwd_rsa[]; -extern const char mbedtls_test_cli_crt_rsa[]; - -extern const size_t mbedtls_test_cli_crt_ec_len; -extern const size_t mbedtls_test_cli_key_ec_len; -extern const size_t mbedtls_test_cli_pwd_ec_len; -extern const size_t mbedtls_test_cli_key_rsa_len; -extern const size_t mbedtls_test_cli_pwd_rsa_len; -extern const size_t mbedtls_test_cli_crt_rsa_len; - -/* Config-dependent dispatch between EC and RSA - * (RSA if enabled, otherwise EC) */ - -extern const char *mbedtls_test_cli_crt; -extern const char *mbedtls_test_cli_key; -extern const char *mbedtls_test_cli_pwd; -extern const size_t mbedtls_test_cli_crt_len; -extern const size_t mbedtls_test_cli_key_len; -extern const size_t mbedtls_test_cli_pwd_len; - -#ifdef __cplusplus -} -#endif - -#endif /* certs.h */ diff --git a/vendor/mbedtls/include/mbedtls/chacha20.h b/vendor/mbedtls/include/mbedtls/chacha20.h index cd9f91a931..680fe36046 100644 --- a/vendor/mbedtls/include/mbedtls/chacha20.h +++ b/vendor/mbedtls/include/mbedtls/chacha20.h @@ -14,29 +14,14 @@ /* * Copyright The Mbed TLS Contributors - * SPDX-License-Identifier: Apache-2.0 - * - * Licensed under the Apache License, Version 2.0 (the "License"); you may - * not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT - * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. + * SPDX-License-Identifier: Apache-2.0 OR GPL-2.0-or-later */ #ifndef MBEDTLS_CHACHA20_H #define MBEDTLS_CHACHA20_H +#include "mbedtls/private_access.h" -#if !defined(MBEDTLS_CONFIG_FILE) -#include "mbedtls/config.h" -#else -#include MBEDTLS_CONFIG_FILE -#endif +#include "mbedtls/build_info.h" #include #include @@ -44,16 +29,6 @@ /** Invalid input parameter(s). */ #define MBEDTLS_ERR_CHACHA20_BAD_INPUT_DATA -0x0051 -/* MBEDTLS_ERR_CHACHA20_FEATURE_UNAVAILABLE is deprecated and should not be - * used. */ -/** Feature not available. For example, s part of the API is not implemented. */ -#define MBEDTLS_ERR_CHACHA20_FEATURE_UNAVAILABLE -0x0053 - -/* MBEDTLS_ERR_CHACHA20_HW_ACCEL_FAILED is deprecated and should not be used. - */ -/** Chacha20 hardware accelerator failed. */ -#define MBEDTLS_ERR_CHACHA20_HW_ACCEL_FAILED -0x0055 - #ifdef __cplusplus extern "C" { #endif @@ -61,9 +36,9 @@ extern "C" { #if !defined(MBEDTLS_CHACHA20_ALT) typedef struct mbedtls_chacha20_context { - uint32_t state[16]; /*! The state (before round operations). */ - uint8_t keystream8[64]; /*! Leftover keystream bytes. */ - size_t keystream_bytes_used; /*! Number of keystream bytes already used. */ + uint32_t MBEDTLS_PRIVATE(state)[16]; /*! The state (before round operations). */ + uint8_t MBEDTLS_PRIVATE(keystream8)[64]; /*! Leftover keystream bytes. */ + size_t MBEDTLS_PRIVATE(keystream_bytes_used); /*! Number of keystream bytes already used. */ } mbedtls_chacha20_context; diff --git a/vendor/mbedtls/include/mbedtls/chachapoly.h b/vendor/mbedtls/include/mbedtls/chachapoly.h index c3f1720704..3dc21e380b 100644 --- a/vendor/mbedtls/include/mbedtls/chachapoly.h +++ b/vendor/mbedtls/include/mbedtls/chachapoly.h @@ -14,29 +14,14 @@ /* * Copyright The Mbed TLS Contributors - * SPDX-License-Identifier: Apache-2.0 - * - * Licensed under the Apache License, Version 2.0 (the "License"); you may - * not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT - * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. + * SPDX-License-Identifier: Apache-2.0 OR GPL-2.0-or-later */ #ifndef MBEDTLS_CHACHAPOLY_H #define MBEDTLS_CHACHAPOLY_H +#include "mbedtls/private_access.h" -#if !defined(MBEDTLS_CONFIG_FILE) -#include "mbedtls/config.h" -#else -#include MBEDTLS_CONFIG_FILE -#endif +#include "mbedtls/build_info.h" /* for shared error codes */ #include "mbedtls/poly1305.h" @@ -61,12 +46,12 @@ mbedtls_chachapoly_mode_t; #include "mbedtls/chacha20.h" typedef struct mbedtls_chachapoly_context { - mbedtls_chacha20_context chacha20_ctx; /**< The ChaCha20 context. */ - mbedtls_poly1305_context poly1305_ctx; /**< The Poly1305 context. */ - uint64_t aad_len; /**< The length (bytes) of the Additional Authenticated Data. */ - uint64_t ciphertext_len; /**< The length (bytes) of the ciphertext. */ - int state; /**< The current state of the context. */ - mbedtls_chachapoly_mode_t mode; /**< Cipher mode (encrypt or decrypt). */ + mbedtls_chacha20_context MBEDTLS_PRIVATE(chacha20_ctx); /**< The ChaCha20 context. */ + mbedtls_poly1305_context MBEDTLS_PRIVATE(poly1305_ctx); /**< The Poly1305 context. */ + uint64_t MBEDTLS_PRIVATE(aad_len); /**< The length (bytes) of the Additional Authenticated Data. */ + uint64_t MBEDTLS_PRIVATE(ciphertext_len); /**< The length (bytes) of the ciphertext. */ + int MBEDTLS_PRIVATE(state); /**< The current state of the context. */ + mbedtls_chachapoly_mode_t MBEDTLS_PRIVATE(mode); /**< Cipher mode (encrypt or decrypt). */ } mbedtls_chachapoly_context; diff --git a/vendor/mbedtls/include/mbedtls/check_config.h b/vendor/mbedtls/include/mbedtls/check_config.h index dddcb73c75..b3c038dd2e 100644 --- a/vendor/mbedtls/include/mbedtls/check_config.h +++ b/vendor/mbedtls/include/mbedtls/check_config.h @@ -5,24 +5,7 @@ */ /* * Copyright The Mbed TLS Contributors - * SPDX-License-Identifier: Apache-2.0 - * - * Licensed under the Apache License, Version 2.0 (the "License"); you may - * not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT - * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -/* - * It is recommended to include this file from your config.h - * in order to catch dependency issues early. + * SPDX-License-Identifier: Apache-2.0 OR GPL-2.0-or-later */ #ifndef MBEDTLS_CHECK_CONFIG_H @@ -38,23 +21,15 @@ #error "Mbed TLS requires a platform with 8-bit chars" #endif -#if defined(_WIN32) +#include + +#if defined(__MINGW32__) || (defined(_MSC_VER) && _MSC_VER <= 1900) #if !defined(MBEDTLS_PLATFORM_C) #error "MBEDTLS_PLATFORM_C is required on Windows" #endif - -/* Fix the config here. Not convenient to put an #ifdef _WIN32 in config.h as - * it would confuse config.py. */ -#if !defined(MBEDTLS_PLATFORM_SNPRINTF_ALT) && \ - !defined(MBEDTLS_PLATFORM_SNPRINTF_MACRO) -#define MBEDTLS_PLATFORM_SNPRINTF_ALT -#endif - -#if !defined(MBEDTLS_PLATFORM_VSNPRINTF_ALT) && \ - !defined(MBEDTLS_PLATFORM_VSNPRINTF_MACRO) -#define MBEDTLS_PLATFORM_VSNPRINTF_ALT -#endif -#endif /* _WIN32 */ +/* See auto-enabling SNPRINTF_ALT and VSNPRINTF_ALT + * in * config_adjust_legacy_crypto.h */ +#endif /* _MINGW32__ || (_MSC_VER && (_MSC_VER <= 1900)) */ #if defined(TARGET_LIKE_MBED) && defined(MBEDTLS_NET_C) #error "The NET module is not available for mbed OS - please use the network functions provided by Mbed OS" @@ -69,7 +44,49 @@ #error "MBEDTLS_HAVE_TIME_DATE without MBEDTLS_HAVE_TIME does not make sense" #endif -#if defined(MBEDTLS_CTR_DRBG_C) && !defined(MBEDTLS_AES_C) +/* Limitations on ECC key types acceleration: if we have any of `PUBLIC_KEY`, + * `KEY_PAIR_BASIC`, `KEY_PAIR_IMPORT`, `KEY_PAIR_EXPORT` then we must have + * all 4 of them. + */ +#if defined(MBEDTLS_PSA_ACCEL_KEY_TYPE_ECC_PUBLIC_KEY) || \ + defined(MBEDTLS_PSA_ACCEL_KEY_TYPE_ECC_KEY_PAIR_BASIC) || \ + defined(MBEDTLS_PSA_ACCEL_KEY_TYPE_ECC_KEY_PAIR_IMPORT) || \ + defined(MBEDTLS_PSA_ACCEL_KEY_TYPE_ECC_KEY_PAIR_EXPORT) +#if !defined(MBEDTLS_PSA_ACCEL_KEY_TYPE_ECC_PUBLIC_KEY) || \ + !defined(MBEDTLS_PSA_ACCEL_KEY_TYPE_ECC_KEY_PAIR_BASIC) || \ + !defined(MBEDTLS_PSA_ACCEL_KEY_TYPE_ECC_KEY_PAIR_IMPORT) || \ + !defined(MBEDTLS_PSA_ACCEL_KEY_TYPE_ECC_KEY_PAIR_EXPORT) +#error "Unsupported partial support for ECC key type acceleration, see docs/driver-only-builds.md" +#endif /* not all of public, basic, import, export */ +#endif /* one of public, basic, import, export */ + +/* Limitations on ECC curves acceleration: partial curve acceleration is only + * supported with crypto excluding PK, X.509 or TLS. + * Note: no need to check X.509 as it depends on PK. */ +#if defined(MBEDTLS_PSA_ACCEL_ECC_BRAINPOOL_P_R1_256) || \ + defined(MBEDTLS_PSA_ACCEL_ECC_BRAINPOOL_P_R1_384) || \ + defined(MBEDTLS_PSA_ACCEL_ECC_BRAINPOOL_P_R1_512) || \ + defined(MBEDTLS_PSA_ACCEL_ECC_MONTGOMERY_255) || \ + defined(MBEDTLS_PSA_ACCEL_ECC_MONTGOMERY_448) || \ + defined(MBEDTLS_PSA_ACCEL_ECC_SECP_K1_192) || \ + defined(MBEDTLS_PSA_ACCEL_ECC_SECP_K1_224) || \ + defined(MBEDTLS_PSA_ACCEL_ECC_SECP_K1_256) || \ + defined(MBEDTLS_PSA_ACCEL_ECC_SECP_R1_192) || \ + defined(MBEDTLS_PSA_ACCEL_ECC_SECP_R1_224) || \ + defined(MBEDTLS_PSA_ACCEL_ECC_SECP_R1_256) || \ + defined(MBEDTLS_PSA_ACCEL_ECC_SECP_R1_384) || \ + defined(MBEDTLS_PSA_ACCEL_ECC_SECP_R1_521) +#if defined(MBEDTLS_PSA_ECC_ACCEL_INCOMPLETE_CURVES) +#if defined(MBEDTLS_PK_C) || \ + defined(MBEDTLS_SSL_TLS_C) +#error "Unsupported partial support for ECC curves acceleration, see docs/driver-only-builds.md" +#endif /* modules beyond what's supported */ +#endif /* not all curves accelerated */ +#endif /* some curve accelerated */ + +#if defined(MBEDTLS_CTR_DRBG_C) && !(defined(MBEDTLS_AES_C) || \ + (defined(MBEDTLS_PSA_CRYPTO_CLIENT) && defined(PSA_WANT_KEY_TYPE_AES) && \ + defined(PSA_WANT_ALG_ECB_NO_PADDING))) #error "MBEDTLS_CTR_DRBG_C defined, but not all prerequisites" #endif @@ -77,12 +94,8 @@ #error "MBEDTLS_DHM_C defined, but not all prerequisites" #endif -#if defined(MBEDTLS_SSL_TRUNCATED_HMAC_COMPAT) && !defined(MBEDTLS_SSL_TRUNCATED_HMAC) -#error "MBEDTLS_SSL_TRUNCATED_HMAC_COMPAT defined, but not all prerequisites" -#endif - #if defined(MBEDTLS_CMAC_C) && \ - !defined(MBEDTLS_AES_C) && !defined(MBEDTLS_DES_C) + ( !defined(MBEDTLS_CIPHER_C ) || ( !defined(MBEDTLS_AES_C) && !defined(MBEDTLS_DES_C) ) ) #error "MBEDTLS_CMAC_C defined, but not all prerequisites" #endif @@ -91,6 +104,36 @@ #error "MBEDTLS_NIST_KW_C defined, but not all prerequisites" #endif +#if defined(MBEDTLS_BLOCK_CIPHER_NO_DECRYPT) && defined(MBEDTLS_PSA_CRYPTO_CONFIG) +#if defined(PSA_WANT_ALG_CBC_NO_PADDING) +#error "MBEDTLS_BLOCK_CIPHER_NO_DECRYPT and PSA_WANT_ALG_CBC_NO_PADDING cannot be defined simultaneously" +#endif +#if defined(PSA_WANT_ALG_CBC_PKCS7) +#error "MBEDTLS_BLOCK_CIPHER_NO_DECRYPT and PSA_WANT_ALG_CBC_PKCS7 cannot be defined simultaneously" +#endif +#if defined(PSA_WANT_ALG_ECB_NO_PADDING) +#error "MBEDTLS_BLOCK_CIPHER_NO_DECRYPT and PSA_WANT_ALG_ECB_NO_PADDING cannot be defined simultaneously" +#endif +#if defined(PSA_WANT_KEY_TYPE_DES) +#error "MBEDTLS_BLOCK_CIPHER_NO_DECRYPT and PSA_WANT_KEY_TYPE_DES cannot be defined simultaneously" +#endif +#endif + +#if defined(MBEDTLS_BLOCK_CIPHER_NO_DECRYPT) +#if defined(MBEDTLS_CIPHER_MODE_CBC) +#error "MBEDTLS_BLOCK_CIPHER_NO_DECRYPT and MBEDTLS_CIPHER_MODE_CBC cannot be defined simultaneously" +#endif +#if defined(MBEDTLS_CIPHER_MODE_XTS) +#error "MBEDTLS_BLOCK_CIPHER_NO_DECRYPT and MBEDTLS_CIPHER_MODE_XTS cannot be defined simultaneously" +#endif +#if defined(MBEDTLS_DES_C) +#error "MBEDTLS_BLOCK_CIPHER_NO_DECRYPT and MBEDTLS_DES_C cannot be defined simultaneously" +#endif +#if defined(MBEDTLS_NIST_KW_C) +#error "MBEDTLS_BLOCK_CIPHER_NO_DECRYPT and MBEDTLS_NIST_KW_C cannot be defined simultaneously" +#endif +#endif + #if defined(MBEDTLS_ECDH_C) && !defined(MBEDTLS_ECP_C) #error "MBEDTLS_ECDH_C defined, but not all prerequisites" #endif @@ -113,31 +156,29 @@ #error "MBEDTLS_ECDSA_C defined, but not all prerequisites" #endif -#if defined(MBEDTLS_ECJPAKE_C) && \ - ( !defined(MBEDTLS_ECP_C) || !defined(MBEDTLS_MD_C) ) +#if defined(MBEDTLS_PK_C) && defined(MBEDTLS_USE_PSA_CRYPTO) +#if defined(MBEDTLS_PK_CAN_ECDSA_SIGN) && !defined(MBEDTLS_ASN1_WRITE_C) +#error "MBEDTLS_PK_C with MBEDTLS_USE_PSA_CRYPTO needs MBEDTLS_ASN1_WRITE_C for ECDSA signature" +#endif +#if defined(MBEDTLS_PK_CAN_ECDSA_VERIFY) && !defined(MBEDTLS_ASN1_PARSE_C) +#error "MBEDTLS_PK_C with MBEDTLS_USE_PSA_CRYPTO needs MBEDTLS_ASN1_PARSE_C for ECDSA verification" +#endif +#endif /* MBEDTLS_PK_C && MBEDTLS_USE_PSA_CRYPTO */ + +#if defined(MBEDTLS_ECJPAKE_C) && \ + !defined(MBEDTLS_ECP_C) #error "MBEDTLS_ECJPAKE_C defined, but not all prerequisites" #endif #if defined(MBEDTLS_ECP_RESTARTABLE) && \ - ( defined(MBEDTLS_USE_PSA_CRYPTO) || \ - defined(MBEDTLS_ECDH_COMPUTE_SHARED_ALT) || \ + ( defined(MBEDTLS_ECDH_COMPUTE_SHARED_ALT) || \ defined(MBEDTLS_ECDH_GEN_PUBLIC_ALT) || \ defined(MBEDTLS_ECDSA_SIGN_ALT) || \ defined(MBEDTLS_ECDSA_VERIFY_ALT) || \ defined(MBEDTLS_ECDSA_GENKEY_ALT) || \ defined(MBEDTLS_ECP_INTERNAL_ALT) || \ defined(MBEDTLS_ECP_ALT) ) -#error "MBEDTLS_ECP_RESTARTABLE defined, but it cannot coexist with an alternative or PSA-based ECP implementation" -#endif - -#if defined(MBEDTLS_ECP_RESTARTABLE) && \ - ! defined(MBEDTLS_ECDH_LEGACY_CONTEXT) -#error "MBEDTLS_ECP_RESTARTABLE defined, but not MBEDTLS_ECDH_LEGACY_CONTEXT" -#endif - -#if defined(MBEDTLS_ECDH_VARIANT_EVEREST_ENABLED) && \ - defined(MBEDTLS_ECDH_LEGACY_CONTEXT) -#error "MBEDTLS_ECDH_VARIANT_EVEREST_ENABLED defined, but MBEDTLS_ECDH_LEGACY_CONTEXT not disabled" +#error "MBEDTLS_ECP_RESTARTABLE defined, but it cannot coexist with an alternative ECP implementation" #endif #if defined(MBEDTLS_ECP_RESTARTABLE) && \ @@ -149,7 +190,7 @@ #error "MBEDTLS_ECDSA_DETERMINISTIC defined, but not all prerequisites" #endif -#if defined(MBEDTLS_ECP_C) && ( !defined(MBEDTLS_BIGNUM_C) || ( \ +#if defined(MBEDTLS_ECP_LIGHT) && ( !defined(MBEDTLS_BIGNUM_C) || ( \ !defined(MBEDTLS_ECP_DP_SECP192R1_ENABLED) && \ !defined(MBEDTLS_ECP_DP_SECP224R1_ENABLED) && \ !defined(MBEDTLS_ECP_DP_SECP256R1_ENABLED) && \ @@ -163,78 +204,46 @@ !defined(MBEDTLS_ECP_DP_SECP256K1_ENABLED) && \ !defined(MBEDTLS_ECP_DP_CURVE25519_ENABLED) && \ !defined(MBEDTLS_ECP_DP_CURVE448_ENABLED) ) ) -#error "MBEDTLS_ECP_C defined, but not all prerequisites" +#error "MBEDTLS_ECP_C defined (or a subset enabled), but not all prerequisites" #endif -#if defined(MBEDTLS_ECP_C) && !( \ - defined(MBEDTLS_ECP_ALT) || \ - defined(MBEDTLS_CTR_DRBG_C) || \ - defined(MBEDTLS_HMAC_DRBG_C) || \ - defined(MBEDTLS_ECP_NO_INTERNAL_RNG)) -#error "MBEDTLS_ECP_C requires a DRBG module unless MBEDTLS_ECP_NO_INTERNAL_RNG is defined or an alternative implementation is used" -#endif - -#if defined(MBEDTLS_PK_PARSE_C) && !defined(MBEDTLS_ASN1_PARSE_C) -#error "MBEDTLS_PK_PARSE_C defined, but not all prerequisites" -#endif - -#if defined(MBEDTLS_PKCS5_C) && !defined(MBEDTLS_MD_C) -#error "MBEDTLS_PKCS5_C defined, but not all prerequisites" -#endif - -#if defined(MBEDTLS_ENTROPY_C) && (!defined(MBEDTLS_SHA512_C) && \ - !defined(MBEDTLS_SHA256_C)) +#if defined(MBEDTLS_ENTROPY_C) && \ + !(defined(MBEDTLS_MD_CAN_SHA512) || defined(MBEDTLS_MD_CAN_SHA256)) #error "MBEDTLS_ENTROPY_C defined, but not all prerequisites" #endif -#if defined(MBEDTLS_ENTROPY_C) && defined(MBEDTLS_SHA512_C) && \ +#if defined(MBEDTLS_ENTROPY_C) && \ defined(MBEDTLS_CTR_DRBG_ENTROPY_LEN) && (MBEDTLS_CTR_DRBG_ENTROPY_LEN > 64) #error "MBEDTLS_CTR_DRBG_ENTROPY_LEN value too high" #endif #if defined(MBEDTLS_ENTROPY_C) && \ - ( !defined(MBEDTLS_SHA512_C) || defined(MBEDTLS_ENTROPY_FORCE_SHA256) ) \ + (defined(MBEDTLS_ENTROPY_FORCE_SHA256) || !defined(MBEDTLS_MD_CAN_SHA512)) \ && defined(MBEDTLS_CTR_DRBG_ENTROPY_LEN) && (MBEDTLS_CTR_DRBG_ENTROPY_LEN > 32) #error "MBEDTLS_CTR_DRBG_ENTROPY_LEN value too high" #endif #if defined(MBEDTLS_ENTROPY_C) && \ - defined(MBEDTLS_ENTROPY_FORCE_SHA256) && !defined(MBEDTLS_SHA256_C) + defined(MBEDTLS_ENTROPY_FORCE_SHA256) && !defined(MBEDTLS_MD_CAN_SHA256) #error "MBEDTLS_ENTROPY_FORCE_SHA256 defined, but not all prerequisites" #endif #if defined(__has_feature) #if __has_feature(memory_sanitizer) -#define MBEDTLS_HAS_MEMSAN +#define MBEDTLS_HAS_MEMSAN // #undef at the end of this paragraph #endif #endif #if defined(MBEDTLS_TEST_CONSTANT_FLOW_MEMSAN) && !defined(MBEDTLS_HAS_MEMSAN) #error "MBEDTLS_TEST_CONSTANT_FLOW_MEMSAN requires building with MemorySanitizer" #endif -#undef MBEDTLS_HAS_MEMSAN - -#if defined(MBEDTLS_TEST_NULL_ENTROPY) && \ - ( !defined(MBEDTLS_ENTROPY_C) || !defined(MBEDTLS_NO_DEFAULT_ENTROPY_SOURCES) ) -#error "MBEDTLS_TEST_NULL_ENTROPY defined, but not all prerequisites" -#endif -#if defined(MBEDTLS_TEST_NULL_ENTROPY) && \ - ( defined(MBEDTLS_ENTROPY_NV_SEED) || defined(MBEDTLS_ENTROPY_HARDWARE_ALT) || \ - defined(MBEDTLS_HAVEGE_C) ) -#error "MBEDTLS_TEST_NULL_ENTROPY defined, but entropy sources too" -#endif - -#if defined(MBEDTLS_CCM_C) && ( \ - !defined(MBEDTLS_AES_C) && !defined(MBEDTLS_CAMELLIA_C) && !defined(MBEDTLS_ARIA_C) ) -#error "MBEDTLS_CCM_C defined, but not all prerequisites" -#endif +#undef MBEDTLS_HAS_MEMSAN // temporary macro defined above -#if defined(MBEDTLS_CCM_C) && !defined(MBEDTLS_CIPHER_C) +#if defined(MBEDTLS_CCM_C) && \ + !(defined(MBEDTLS_CCM_GCM_CAN_AES) || defined(MBEDTLS_CCM_GCM_CAN_ARIA) || \ + defined(MBEDTLS_CCM_GCM_CAN_CAMELLIA)) #error "MBEDTLS_CCM_C defined, but not all prerequisites" #endif -#if defined(MBEDTLS_GCM_C) && ( \ - !defined(MBEDTLS_AES_C) && !defined(MBEDTLS_CAMELLIA_C) && !defined(MBEDTLS_ARIA_C) ) -#error "MBEDTLS_GCM_C defined, but not all prerequisites" -#endif - -#if defined(MBEDTLS_GCM_C) && !defined(MBEDTLS_CIPHER_C) +#if defined(MBEDTLS_GCM_C) && \ + !(defined(MBEDTLS_CCM_GCM_CAN_AES) || defined(MBEDTLS_CCM_GCM_CAN_ARIA) || \ + defined(MBEDTLS_CCM_GCM_CAN_CAMELLIA)) #error "MBEDTLS_GCM_C defined, but not all prerequisites" #endif @@ -282,10 +291,6 @@ #error "MBEDTLS_ECP_NO_FALLBACK defined, but no alternative implementation enabled" #endif -#if defined(MBEDTLS_HAVEGE_C) && !defined(MBEDTLS_TIMING_C) -#error "MBEDTLS_HAVEGE_C defined, but not all prerequisites" -#endif - #if defined(MBEDTLS_HKDF_C) && !defined(MBEDTLS_MD_C) #error "MBEDTLS_HKDF_C defined, but not all prerequisites" #endif @@ -295,13 +300,14 @@ #endif #if defined(MBEDTLS_KEY_EXCHANGE_ECDH_ECDSA_ENABLED) && \ - ( !defined(MBEDTLS_ECDH_C) || !defined(MBEDTLS_ECDSA_C) || \ + ( !defined(MBEDTLS_CAN_ECDH) || \ + !defined(MBEDTLS_PK_CAN_ECDSA_SIGN) || \ !defined(MBEDTLS_X509_CRT_PARSE_C) ) #error "MBEDTLS_KEY_EXCHANGE_ECDH_ECDSA_ENABLED defined, but not all prerequisites" #endif #if defined(MBEDTLS_KEY_EXCHANGE_ECDH_RSA_ENABLED) && \ - ( !defined(MBEDTLS_ECDH_C) || !defined(MBEDTLS_RSA_C) || \ + ( !defined(MBEDTLS_CAN_ECDH) || !defined(MBEDTLS_RSA_C) || \ !defined(MBEDTLS_X509_CRT_PARSE_C) ) #error "MBEDTLS_KEY_EXCHANGE_ECDH_RSA_ENABLED defined, but not all prerequisites" #endif @@ -311,7 +317,7 @@ #endif #if defined(MBEDTLS_KEY_EXCHANGE_ECDHE_PSK_ENABLED) && \ - !defined(MBEDTLS_ECDH_C) + !defined(MBEDTLS_CAN_ECDH) #error "MBEDTLS_KEY_EXCHANGE_ECDHE_PSK_ENABLED defined, but not all prerequisites" #endif @@ -322,13 +328,14 @@ #endif #if defined(MBEDTLS_KEY_EXCHANGE_ECDHE_RSA_ENABLED) && \ - ( !defined(MBEDTLS_ECDH_C) || !defined(MBEDTLS_RSA_C) || \ + ( !defined(MBEDTLS_CAN_ECDH) || !defined(MBEDTLS_RSA_C) || \ !defined(MBEDTLS_X509_CRT_PARSE_C) || !defined(MBEDTLS_PKCS1_V15) ) #error "MBEDTLS_KEY_EXCHANGE_ECDHE_RSA_ENABLED defined, but not all prerequisites" #endif -#if defined(MBEDTLS_KEY_EXCHANGE_ECDHE_ECDSA_ENABLED) && \ - ( !defined(MBEDTLS_ECDH_C) || !defined(MBEDTLS_ECDSA_C) || \ +#if defined(MBEDTLS_KEY_EXCHANGE_ECDHE_ECDSA_ENABLED) && \ + ( !defined(MBEDTLS_CAN_ECDH) || \ + !defined(MBEDTLS_PK_CAN_ECDSA_SIGN) || \ !defined(MBEDTLS_X509_CRT_PARSE_C) ) #error "MBEDTLS_KEY_EXCHANGE_ECDHE_ECDSA_ENABLED defined, but not all prerequisites" #endif @@ -345,18 +352,58 @@ #error "MBEDTLS_KEY_EXCHANGE_RSA_ENABLED defined, but not all prerequisites" #endif -#if defined(MBEDTLS_KEY_EXCHANGE_ECJPAKE_ENABLED) && \ - ( !defined(MBEDTLS_ECJPAKE_C) || !defined(MBEDTLS_SHA256_C) || \ +#if defined(MBEDTLS_USE_PSA_CRYPTO) +#if defined(MBEDTLS_KEY_EXCHANGE_ECJPAKE_ENABLED) && \ + ( !defined(PSA_WANT_ALG_JPAKE) || \ + !defined(PSA_WANT_KEY_TYPE_ECC_KEY_PAIR_BASIC) || \ + !defined(PSA_WANT_ECC_SECP_R1_256) ) +#error "MBEDTLS_KEY_EXCHANGE_ECJPAKE_ENABLED defined, but not all prerequisites" +#endif +#else /* MBEDTLS_USE_PSA_CRYPTO */ +#if defined(MBEDTLS_KEY_EXCHANGE_ECJPAKE_ENABLED) && \ + ( !defined(MBEDTLS_ECJPAKE_C) || \ !defined(MBEDTLS_ECP_DP_SECP256R1_ENABLED) ) #error "MBEDTLS_KEY_EXCHANGE_ECJPAKE_ENABLED defined, but not all prerequisites" #endif +#endif /* MBEDTLS_USE_PSA_CRYPTO */ + +/* Use of EC J-PAKE in TLS requires SHA-256. */ +#if defined(MBEDTLS_KEY_EXCHANGE_ECJPAKE_ENABLED) && \ + !defined(MBEDTLS_MD_CAN_SHA256) +#error "MBEDTLS_KEY_EXCHANGE_ECJPAKE_ENABLED defined, but not all prerequisites" +#endif #if defined(MBEDTLS_KEY_EXCHANGE_WITH_CERT_ENABLED) && \ - !defined(MBEDTLS_SSL_KEEP_PEER_CERTIFICATE) && \ - ( !defined(MBEDTLS_SHA256_C) && \ - !defined(MBEDTLS_SHA512_C) && \ - !defined(MBEDTLS_SHA1_C) ) -#error "!MBEDTLS_SSL_KEEP_PEER_CERTIFICATE requires MBEDTLS_SHA512_C, MBEDTLS_SHA256_C or MBEDTLS_SHA1_C" + !defined(MBEDTLS_SSL_KEEP_PEER_CERTIFICATE) && \ + !defined(MBEDTLS_MD_CAN_SHA256) && \ + !defined(MBEDTLS_MD_CAN_SHA512) && \ + !defined(MBEDTLS_MD_CAN_SHA1) +#error "!MBEDTLS_SSL_KEEP_PEER_CERTIFICATE requires SHA-512, SHA-256 or SHA-1". +#endif + +#if defined(MBEDTLS_MD_C) && \ + !defined(MBEDTLS_MD_CAN_MD5) && \ + !defined(MBEDTLS_MD_CAN_RIPEMD160) && \ + !defined(MBEDTLS_MD_CAN_SHA1) && \ + !defined(MBEDTLS_MD_CAN_SHA224) && \ + !defined(MBEDTLS_MD_CAN_SHA256) && \ + !defined(MBEDTLS_MD_CAN_SHA384) && \ + !defined(MBEDTLS_MD_CAN_SHA512) && \ + !defined(MBEDTLS_MD_CAN_SHA3_224) && \ + !defined(MBEDTLS_MD_CAN_SHA3_256) && \ + !defined(MBEDTLS_MD_CAN_SHA3_384) && \ + !defined(MBEDTLS_MD_CAN_SHA3_512) +#error "MBEDTLS_MD_C defined, but no hash algorithm" +#endif + +#if defined(MBEDTLS_LMS_C) && \ + ! ( defined(MBEDTLS_PSA_CRYPTO_CLIENT) && defined(PSA_WANT_ALG_SHA_256) ) +#error "MBEDTLS_LMS_C requires MBEDTLS_PSA_CRYPTO_C and PSA_WANT_ALG_SHA_256" +#endif + +#if defined(MBEDTLS_LMS_PRIVATE) && \ + ( !defined(MBEDTLS_LMS_C) ) +#error "MBEDTLS_LMS_PRIVATE requires MBEDTLS_LMS_C" #endif #if defined(MBEDTLS_MEMORY_BUFFER_ALLOC_C) && \ @@ -372,10 +419,6 @@ #error "MBEDTLS_MEMORY_DEBUG defined, but not all prerequisites" #endif -#if defined(MBEDTLS_PADLOCK_C) && !defined(MBEDTLS_HAVE_ASM) -#error "MBEDTLS_PADLOCK_C defined, but not all prerequisites" -#endif - #if defined(MBEDTLS_PEM_PARSE_C) && !defined(MBEDTLS_BASE64_C) #error "MBEDTLS_PEM_PARSE_C defined, but not all prerequisites" #endif @@ -385,30 +428,24 @@ #endif #if defined(MBEDTLS_PK_C) && \ - ( !defined(MBEDTLS_RSA_C) && !defined(MBEDTLS_ECP_C) ) + !defined(MBEDTLS_RSA_C) && !defined(MBEDTLS_PK_HAVE_ECC_KEYS) #error "MBEDTLS_PK_C defined, but not all prerequisites" #endif -#if defined(MBEDTLS_PK_PARSE_C) && !defined(MBEDTLS_PK_C) +#if defined(MBEDTLS_PK_PARSE_C) && \ + (!defined(MBEDTLS_ASN1_PARSE_C) || \ + !defined(MBEDTLS_OID_C) || \ + !defined(MBEDTLS_PK_C)) #error "MBEDTLS_PK_PARSE_C defined, but not all prerequisites" #endif -#if defined(MBEDTLS_PK_WRITE_C) && !defined(MBEDTLS_PK_C) +#if defined(MBEDTLS_PK_WRITE_C) && \ + (!defined(MBEDTLS_ASN1_WRITE_C) || \ + !defined(MBEDTLS_OID_C) || \ + !defined(MBEDTLS_PK_C)) #error "MBEDTLS_PK_WRITE_C defined, but not all prerequisites" #endif -#if defined(MBEDTLS_PKCS11_C) && !defined(MBEDTLS_PK_C) -#error "MBEDTLS_PKCS11_C defined, but not all prerequisites" -#endif - -#if defined(MBEDTLS_PKCS11_C) -#if defined(MBEDTLS_DEPRECATED_REMOVED) -#error "MBEDTLS_PKCS11_C is deprecated and will be removed in a future version of Mbed TLS" -#elif defined(MBEDTLS_DEPRECATED_WARNING) -#warning "MBEDTLS_PKCS11_C is deprecated and will be removed in a future version of Mbed TLS" -#endif -#endif /* MBEDTLS_PKCS11_C */ - #if defined(MBEDTLS_PLATFORM_EXIT_ALT) && !defined(MBEDTLS_PLATFORM_C) #error "MBEDTLS_PLATFORM_EXIT_ALT defined, but not all prerequisites" #endif @@ -423,6 +460,20 @@ #error "MBEDTLS_PLATFORM_EXIT_MACRO and MBEDTLS_PLATFORM_STD_EXIT/MBEDTLS_PLATFORM_EXIT_ALT cannot be defined simultaneously" #endif +#if defined(MBEDTLS_PLATFORM_SETBUF_ALT) && !defined(MBEDTLS_PLATFORM_C) +#error "MBEDTLS_PLATFORM_SETBUF_ALT defined, but not all prerequisites" +#endif + +#if defined(MBEDTLS_PLATFORM_SETBUF_MACRO) && !defined(MBEDTLS_PLATFORM_C) +#error "MBEDTLS_PLATFORM_SETBUF_MACRO defined, but not all prerequisites" +#endif + +#if defined(MBEDTLS_PLATFORM_SETBUF_MACRO) &&\ + ( defined(MBEDTLS_PLATFORM_STD_SETBUF) ||\ + defined(MBEDTLS_PLATFORM_SETBUF_ALT) ) +#error "MBEDTLS_PLATFORM_SETBUF_MACRO and MBEDTLS_PLATFORM_STD_SETBUF/MBEDTLS_PLATFORM_SETBUF_ALT cannot be defined simultaneously" +#endif + #if defined(MBEDTLS_PLATFORM_TIME_ALT) &&\ ( !defined(MBEDTLS_PLATFORM_C) ||\ !defined(MBEDTLS_HAVE_TIME) ) @@ -435,6 +486,16 @@ #error "MBEDTLS_PLATFORM_TIME_MACRO defined, but not all prerequisites" #endif +#if defined(MBEDTLS_PLATFORM_MS_TIME_TYPE_MACRO) &&\ + ( !defined(MBEDTLS_PLATFORM_C) || !defined(MBEDTLS_HAVE_TIME) ) +#error "MBEDTLS_PLATFORM_MS_TIME_TYPE_MACRO defined, but not all prerequisites" +#endif + +#if defined(MBEDTLS_PLATFORM_MS_TIME_ALT) && \ + ( !defined(MBEDTLS_PLATFORM_C) || !defined(MBEDTLS_HAVE_TIME) ) +#error "MBEDTLS_PLATFORM_MS_TIME_ALT defined, but not all prerequisites" +#endif + #if defined(MBEDTLS_PLATFORM_TIME_TYPE_MACRO) &&\ ( !defined(MBEDTLS_PLATFORM_C) ||\ !defined(MBEDTLS_HAVE_TIME) ) @@ -619,6 +680,11 @@ #error "MBEDTLS_PSA_CRYPTO_C defined, but not all prerequisites (missing RNG)" #endif +#if defined(MBEDTLS_PSA_CRYPTO_C) && defined(PSA_HAVE_SOFT_BLOCK_MODE) && \ + defined(PSA_HAVE_SOFT_BLOCK_CIPHER) && !defined(MBEDTLS_CIPHER_C) +#error "MBEDTLS_PSA_CRYPTO_C defined, but not all prerequisites" +#endif + #if defined(MBEDTLS_PSA_CRYPTO_SPM) && !defined(MBEDTLS_PSA_CRYPTO_C) #error "MBEDTLS_PSA_CRYPTO_SPM defined, but not all prerequisites" #endif @@ -629,6 +695,14 @@ #error "MBEDTLS_PSA_CRYPTO_SE_C defined, but not all prerequisites" #endif +#if defined(MBEDTLS_PSA_CRYPTO_SE_C) +#if defined(MBEDTLS_DEPRECATED_REMOVED) +#error "MBEDTLS_PSA_CRYPTO_SE_C is deprecated and will be removed in a future version of Mbed TLS" +#elif defined(MBEDTLS_DEPRECATED_WARNING) +#warning "MBEDTLS_PSA_CRYPTO_SE_C is deprecated and will be removed in a future version of Mbed TLS" +#endif +#endif /* MBEDTLS_PSA_CRYPTO_SE_C */ + #if defined(MBEDTLS_PSA_CRYPTO_STORAGE_C) && \ ! defined(MBEDTLS_PSA_CRYPTO_C) #error "MBEDTLS_PSA_CRYPTO_STORAGE_C defined, but not all prerequisites" @@ -655,22 +729,6 @@ #error "MBEDTLS_PSA_ITS_FILE_C defined, but not all prerequisites" #endif -#if defined(MBEDTLS_PSA_CRYPTO_KEY_ID_ENCODES_OWNER) && \ - defined(MBEDTLS_USE_PSA_CRYPTO) -#error "MBEDTLS_PSA_CRYPTO_KEY_ID_ENCODES_OWNER defined, but it cannot coexist with MBEDTLS_USE_PSA_CRYPTO." -#endif - -#if defined(MBEDTLS_PK_C) && defined(MBEDTLS_USE_PSA_CRYPTO) && \ - !defined(MBEDTLS_PK_WRITE_C) && defined(MBEDTLS_ECDSA_C) -#error "MBEDTLS_PK_C in configuration with MBEDTLS_USE_PSA_CRYPTO and \ - MBEDTLS_ECDSA_C requires MBEDTLS_PK_WRITE_C to be defined." -#endif - -#if defined(MBEDTLS_PSA_CRYPTO_C) && defined(MBEDTLS_RSA_C) && \ - !( defined(MBEDTLS_PK_PARSE_C) && defined(MBEDTLS_PK_WRITE_C) ) -#error "MBEDTLS_PSA_CRYPTO_C with MBEDTLS_RSA_C requires MBEDTLS_PK_PARSE_C and MBEDTLS_PK_WRITE_C" -#endif - #if defined(MBEDTLS_RSA_C) && ( !defined(MBEDTLS_BIGNUM_C) || \ !defined(MBEDTLS_OID_C) ) #error "MBEDTLS_RSA_C defined, but not all prerequisites" @@ -686,37 +744,82 @@ #error "MBEDTLS_X509_RSASSA_PSS_SUPPORT defined, but not all prerequisites" #endif -#if defined(MBEDTLS_SHA512_NO_SHA384) && !defined(MBEDTLS_SHA512_C) -#error "MBEDTLS_SHA512_NO_SHA384 defined without MBEDTLS_SHA512_C" +#if defined(MBEDTLS_SHA512_USE_A64_CRYPTO_IF_PRESENT) && \ + defined(MBEDTLS_SHA512_USE_A64_CRYPTO_ONLY) +#error "Must only define one of MBEDTLS_SHA512_USE_A64_CRYPTO_*" #endif -#if defined(MBEDTLS_SSL_PROTO_SSL3) && ( !defined(MBEDTLS_MD5_C) || \ - !defined(MBEDTLS_SHA1_C) ) -#error "MBEDTLS_SSL_PROTO_SSL3 defined, but not all prerequisites" +#if defined(MBEDTLS_SHA512_USE_A64_CRYPTO_IF_PRESENT) || \ + defined(MBEDTLS_SHA512_USE_A64_CRYPTO_ONLY) +#if !defined(MBEDTLS_SHA512_C) +#error "MBEDTLS_SHA512_USE_A64_CRYPTO_* defined without MBEDTLS_SHA512_C" +#endif +#if defined(MBEDTLS_SHA512_ALT) || defined(MBEDTLS_SHA512_PROCESS_ALT) +#error "MBEDTLS_SHA512_*ALT can't be used with MBEDTLS_SHA512_USE_A64_CRYPTO_*" +#endif + +#endif /* MBEDTLS_SHA512_USE_A64_CRYPTO_IF_PRESENT || MBEDTLS_SHA512_USE_A64_CRYPTO_ONLY */ + +#if defined(MBEDTLS_SHA512_USE_A64_CRYPTO_ONLY) && !defined(__aarch64__) +#error "MBEDTLS_SHA512_USE_A64_CRYPTO_ONLY defined on non-Aarch64 system" #endif -#if defined(MBEDTLS_SSL_PROTO_TLS1) && ( !defined(MBEDTLS_MD5_C) || \ - !defined(MBEDTLS_SHA1_C) ) -#error "MBEDTLS_SSL_PROTO_TLS1 defined, but not all prerequisites" +#if defined(MBEDTLS_SHA256_USE_ARMV8_A_CRYPTO_IF_PRESENT) && \ + defined(MBEDTLS_SHA256_USE_ARMV8_A_CRYPTO_ONLY) +#error "Must only define one of MBEDTLS_SHA256_USE_ARMV8_A_CRYPTO_*" #endif -#if defined(MBEDTLS_SSL_PROTO_TLS1_1) && ( !defined(MBEDTLS_MD5_C) || \ - !defined(MBEDTLS_SHA1_C) ) -#error "MBEDTLS_SSL_PROTO_TLS1_1 defined, but not all prerequisites" +#if defined(MBEDTLS_SHA256_USE_ARMV8_A_CRYPTO_IF_PRESENT) || \ + defined(MBEDTLS_SHA256_USE_ARMV8_A_CRYPTO_ONLY) +#if !defined(MBEDTLS_SHA256_C) +#error "MBEDTLS_SHA256_USE_ARMV8_A_CRYPTO_* defined without MBEDTLS_SHA256_C" +#endif +#if defined(MBEDTLS_SHA256_ALT) || defined(MBEDTLS_SHA256_PROCESS_ALT) +#error "MBEDTLS_SHA256_*ALT can't be used with MBEDTLS_SHA256_USE_ARMV8_A_CRYPTO_*" #endif -#if defined(MBEDTLS_SSL_PROTO_TLS1_2) && ( !defined(MBEDTLS_SHA1_C) && \ - !defined(MBEDTLS_SHA256_C) && !defined(MBEDTLS_SHA512_C) ) -#error "MBEDTLS_SSL_PROTO_TLS1_2 defined, but not all prerequisites" #endif -#if defined(MBEDTLS_SSL_PROTO_TLS1_3_EXPERIMENTAL) && ( !defined(MBEDTLS_HKDF_C) && \ - !defined(MBEDTLS_SHA256_C) && !defined(MBEDTLS_SHA512_C) ) -#error "MBEDTLS_SSL_PROTO_TLS1_3_EXPERIMENTAL defined, but not all prerequisites" +#if defined(MBEDTLS_SHA256_USE_ARMV8_A_CRYPTO_ONLY) && !defined(MBEDTLS_ARCH_IS_ARMV8_A) +#error "MBEDTLS_SHA256_USE_ARMV8_A_CRYPTO_ONLY defined on non-Armv8-A system" +#endif + +/* TLS 1.3 requires separate HKDF parts from PSA, + * and at least one ciphersuite, so at least SHA-256 or SHA-384 + * from PSA to use with HKDF. + * + * Note: for dependencies common with TLS 1.2 (running handshake hash), + * see MBEDTLS_SSL_TLS_C. */ +#if defined(MBEDTLS_SSL_PROTO_TLS1_3) && \ + !(defined(MBEDTLS_PSA_CRYPTO_CLIENT) && \ + defined(PSA_WANT_ALG_HKDF_EXTRACT) && \ + defined(PSA_WANT_ALG_HKDF_EXPAND) && \ + (defined(PSA_WANT_ALG_SHA_256) || defined(PSA_WANT_ALG_SHA_384))) +#error "MBEDTLS_SSL_PROTO_TLS1_3 defined, but not all prerequisites" +#endif + +#if defined(MBEDTLS_SSL_TLS1_3_KEY_EXCHANGE_MODE_EPHEMERAL_ENABLED) +#if !( (defined(PSA_WANT_ALG_ECDH) || defined(PSA_WANT_ALG_FFDH)) && \ + defined(MBEDTLS_X509_CRT_PARSE_C) && \ + ( defined(MBEDTLS_PK_CAN_ECDSA_SIGN) || defined(MBEDTLS_PKCS1_V21) ) ) +#error "MBEDTLS_SSL_TLS1_3_KEY_EXCHANGE_MODE_EPHEMERAL_ENABLED defined, but not all prerequisites" +#endif +#endif + +#if defined(MBEDTLS_SSL_TLS1_3_KEY_EXCHANGE_MODE_PSK_EPHEMERAL_ENABLED) +#if !( defined(PSA_WANT_ALG_ECDH) || defined(PSA_WANT_ALG_FFDH) ) +#error "MBEDTLS_SSL_TLS1_3_KEY_EXCHANGE_MODE_PSK_EPHEMERAL_ENABLED defined, but not all prerequisites" +#endif +#endif + +/* + * The current implementation of TLS 1.3 requires MBEDTLS_SSL_KEEP_PEER_CERTIFICATE. + */ +#if defined(MBEDTLS_SSL_PROTO_TLS1_3) && !defined(MBEDTLS_SSL_KEEP_PEER_CERTIFICATE) +#error "MBEDTLS_SSL_PROTO_TLS1_3 defined without MBEDTLS_SSL_KEEP_PEER_CERTIFICATE" #endif -#if (defined(MBEDTLS_SSL_PROTO_SSL3) || defined(MBEDTLS_SSL_PROTO_TLS1) || \ - defined(MBEDTLS_SSL_PROTO_TLS1_1) || defined(MBEDTLS_SSL_PROTO_TLS1_2)) && \ +#if defined(MBEDTLS_SSL_PROTO_TLS1_2) && \ !(defined(MBEDTLS_KEY_EXCHANGE_RSA_ENABLED) || \ defined(MBEDTLS_KEY_EXCHANGE_DHE_RSA_ENABLED) || \ defined(MBEDTLS_KEY_EXCHANGE_ECDHE_RSA_ENABLED) || \ @@ -732,8 +835,21 @@ "but no key exchange methods defined with MBEDTLS_KEY_EXCHANGE_xxxx" #endif +#if defined(MBEDTLS_SSL_EARLY_DATA) && \ + ( !defined(MBEDTLS_SSL_SESSION_TICKETS) || \ + ( !defined(MBEDTLS_SSL_TLS1_3_KEY_EXCHANGE_MODE_PSK_ENABLED) && \ + !defined(MBEDTLS_SSL_TLS1_3_KEY_EXCHANGE_MODE_PSK_EPHEMERAL_ENABLED) ) ) +#error "MBEDTLS_SSL_EARLY_DATA defined, but not all prerequisites" +#endif + +#if defined(MBEDTLS_SSL_EARLY_DATA) && defined(MBEDTLS_SSL_SRV_C) && \ + defined(MBEDTLS_SSL_MAX_EARLY_DATA_SIZE) && \ + ((MBEDTLS_SSL_MAX_EARLY_DATA_SIZE < 0) || \ + (MBEDTLS_SSL_MAX_EARLY_DATA_SIZE > UINT32_MAX)) +#error "MBEDTLS_SSL_MAX_EARLY_DATA_SIZE must be in the range(0..UINT32_MAX)" +#endif + #if defined(MBEDTLS_SSL_PROTO_DTLS) && \ - !defined(MBEDTLS_SSL_PROTO_TLS1_1) && \ !defined(MBEDTLS_SSL_PROTO_TLS1_2) #error "MBEDTLS_SSL_PROTO_DTLS defined, but not all prerequisites" #endif @@ -742,35 +858,36 @@ #error "MBEDTLS_SSL_CLI_C defined, but not all prerequisites" #endif -#if defined(MBEDTLS_SSL_TLS_C) && ( !defined(MBEDTLS_CIPHER_C) || \ - !defined(MBEDTLS_MD_C) ) -#error "MBEDTLS_SSL_TLS_C defined, but not all prerequisites" +#if defined(MBEDTLS_SSL_ASYNC_PRIVATE) && !defined(MBEDTLS_X509_CRT_PARSE_C) +#error "MBEDTLS_SSL_ASYNC_PRIVATE defined, but not all prerequisites" #endif -#if defined(MBEDTLS_SSL_SRV_C) && !defined(MBEDTLS_SSL_TLS_C) -#error "MBEDTLS_SSL_SRV_C defined, but not all prerequisites" +#if defined(MBEDTLS_SSL_TLS_C) && !(defined(MBEDTLS_CIPHER_C) || \ + defined(MBEDTLS_USE_PSA_CRYPTO)) +#error "MBEDTLS_SSL_TLS_C defined, but not all prerequisites" #endif -#if defined(MBEDTLS_SSL_TLS_C) && (!defined(MBEDTLS_SSL_PROTO_SSL3) && \ - !defined(MBEDTLS_SSL_PROTO_TLS1) && !defined(MBEDTLS_SSL_PROTO_TLS1_1) && \ - !defined(MBEDTLS_SSL_PROTO_TLS1_2)) -#error "MBEDTLS_SSL_TLS_C defined, but no protocols are active" +/* TLS 1.2 and 1.3 require SHA-256 or SHA-384 (running handshake hash) */ +#if defined(MBEDTLS_SSL_TLS_C) +#if defined(MBEDTLS_USE_PSA_CRYPTO) +#if !(defined(PSA_WANT_ALG_SHA_256) || defined(PSA_WANT_ALG_SHA_384)) +#error "MBEDTLS_SSL_TLS_C defined, but not all prerequisites" #endif - -#if defined(MBEDTLS_SSL_TLS_C) && (defined(MBEDTLS_SSL_PROTO_SSL3) && \ - defined(MBEDTLS_SSL_PROTO_TLS1_1) && !defined(MBEDTLS_SSL_PROTO_TLS1)) -#error "Illegal protocol selection" +#else /* MBEDTLS_USE_PSA_CRYPTO */ +#if !defined(MBEDTLS_MD_C) || \ + !(defined(MBEDTLS_MD_CAN_SHA256) || defined(MBEDTLS_MD_CAN_SHA384)) +#error "MBEDTLS_SSL_TLS_C defined, but not all prerequisites" #endif +#endif /* MBEDTLS_USE_PSA_CRYPTO */ +#endif /* MBEDTLS_SSL_TLS_C */ -#if defined(MBEDTLS_SSL_TLS_C) && (defined(MBEDTLS_SSL_PROTO_TLS1) && \ - defined(MBEDTLS_SSL_PROTO_TLS1_2) && !defined(MBEDTLS_SSL_PROTO_TLS1_1)) -#error "Illegal protocol selection" +#if defined(MBEDTLS_SSL_SRV_C) && !defined(MBEDTLS_SSL_TLS_C) +#error "MBEDTLS_SSL_SRV_C defined, but not all prerequisites" #endif -#if defined(MBEDTLS_SSL_TLS_C) && (defined(MBEDTLS_SSL_PROTO_SSL3) && \ - defined(MBEDTLS_SSL_PROTO_TLS1_2) && (!defined(MBEDTLS_SSL_PROTO_TLS1) || \ - !defined(MBEDTLS_SSL_PROTO_TLS1_1))) -#error "Illegal protocol selection" +#if defined(MBEDTLS_SSL_TLS_C) && \ + !( defined(MBEDTLS_SSL_PROTO_TLS1_2) || defined(MBEDTLS_SSL_PROTO_TLS1_3) ) +#error "MBEDTLS_SSL_TLS_C defined, but no protocols are active" #endif #if defined(MBEDTLS_SSL_DTLS_HELLO_VERIFY) && !defined(MBEDTLS_SSL_PROTO_DTLS) @@ -804,37 +921,48 @@ #error "MBEDTLS_SSL_CID_OUT_LEN_MAX too large (max 255)" #endif -#if defined(MBEDTLS_SSL_DTLS_BADMAC_LIMIT) && \ - ( !defined(MBEDTLS_SSL_TLS_C) || !defined(MBEDTLS_SSL_PROTO_DTLS) ) -#error "MBEDTLS_SSL_DTLS_BADMAC_LIMIT defined, but not all prerequisites" +#if defined(MBEDTLS_SSL_DTLS_CONNECTION_ID_COMPAT) && \ + !defined(MBEDTLS_SSL_DTLS_CONNECTION_ID) +#error "MBEDTLS_SSL_DTLS_CONNECTION_ID_COMPAT defined, but not all prerequisites" #endif +#if defined(MBEDTLS_SSL_DTLS_CONNECTION_ID_COMPAT) && MBEDTLS_SSL_DTLS_CONNECTION_ID_COMPAT != 0 +#if defined(MBEDTLS_DEPRECATED_REMOVED) +#error "MBEDTLS_SSL_DTLS_CONNECTION_ID_COMPAT is deprecated and will be removed in a future version of Mbed TLS" +#elif defined(MBEDTLS_DEPRECATED_WARNING) +#warning "MBEDTLS_SSL_DTLS_CONNECTION_ID_COMPAT is deprecated and will be removed in a future version of Mbed TLS" +#endif +#endif /* MBEDTLS_SSL_DTLS_CONNECTION_ID_COMPAT && MBEDTLS_SSL_DTLS_CONNECTION_ID_COMPAT != 0 */ + #if defined(MBEDTLS_SSL_ENCRYPT_THEN_MAC) && \ - !defined(MBEDTLS_SSL_PROTO_TLS1) && \ - !defined(MBEDTLS_SSL_PROTO_TLS1_1) && \ !defined(MBEDTLS_SSL_PROTO_TLS1_2) #error "MBEDTLS_SSL_ENCRYPT_THEN_MAC defined, but not all prerequisites" #endif #if defined(MBEDTLS_SSL_EXTENDED_MASTER_SECRET) && \ - !defined(MBEDTLS_SSL_PROTO_TLS1) && \ - !defined(MBEDTLS_SSL_PROTO_TLS1_1) && \ !defined(MBEDTLS_SSL_PROTO_TLS1_2) #error "MBEDTLS_SSL_EXTENDED_MASTER_SECRET defined, but not all prerequisites" #endif -#if defined(MBEDTLS_SSL_TICKET_C) && !defined(MBEDTLS_CIPHER_C) +#if defined(MBEDTLS_SSL_RENEGOTIATION) && \ + !defined(MBEDTLS_SSL_PROTO_TLS1_2) +#error "MBEDTLS_SSL_RENEGOTIATION defined, but not all prerequisites" +#endif + +#if defined(MBEDTLS_SSL_TICKET_C) && ( !defined(MBEDTLS_CIPHER_C) && \ + !defined(MBEDTLS_USE_PSA_CRYPTO) ) #error "MBEDTLS_SSL_TICKET_C defined, but not all prerequisites" #endif #if defined(MBEDTLS_SSL_TICKET_C) && \ - !( defined(MBEDTLS_GCM_C) || defined(MBEDTLS_CCM_C) || defined(MBEDTLS_CHACHAPOLY_C) ) + !( defined(MBEDTLS_SSL_HAVE_CCM) || defined(MBEDTLS_SSL_HAVE_GCM) || \ + defined(MBEDTLS_SSL_HAVE_CHACHAPOLY) ) #error "MBEDTLS_SSL_TICKET_C defined, but not all prerequisites" #endif -#if defined(MBEDTLS_SSL_CBC_RECORD_SPLITTING) && \ - !defined(MBEDTLS_SSL_PROTO_SSL3) && !defined(MBEDTLS_SSL_PROTO_TLS1) -#error "MBEDTLS_SSL_CBC_RECORD_SPLITTING defined, but not all prerequisites" +#if defined(MBEDTLS_SSL_TLS1_3_TICKET_NONCE_LENGTH) && \ + MBEDTLS_SSL_TLS1_3_TICKET_NONCE_LENGTH >= 256 +#error "MBEDTLS_SSL_TLS1_3_TICKET_NONCE_LENGTH must be less than 256" #endif #if defined(MBEDTLS_SSL_SERVER_NAME_INDICATION) && \ @@ -846,22 +974,20 @@ #if !defined(MBEDTLS_THREADING_C) || defined(MBEDTLS_THREADING_IMPL) #error "MBEDTLS_THREADING_PTHREAD defined, but not all prerequisites" #endif -#define MBEDTLS_THREADING_IMPL +#define MBEDTLS_THREADING_IMPL // undef at the end of this paragraph #endif - #if defined(MBEDTLS_THREADING_ALT) #if !defined(MBEDTLS_THREADING_C) || defined(MBEDTLS_THREADING_IMPL) #error "MBEDTLS_THREADING_ALT defined, but not all prerequisites" #endif -#define MBEDTLS_THREADING_IMPL +#define MBEDTLS_THREADING_IMPL // undef at the end of this paragraph #endif - #if defined(MBEDTLS_THREADING_C) && !defined(MBEDTLS_THREADING_IMPL) #error "MBEDTLS_THREADING_C defined, single threading implementation required" #endif -#undef MBEDTLS_THREADING_IMPL +#undef MBEDTLS_THREADING_IMPL // temporary macro defined above -#if defined(MBEDTLS_USE_PSA_CRYPTO) && !defined(MBEDTLS_PSA_CRYPTO_C) +#if defined(MBEDTLS_USE_PSA_CRYPTO) && !defined(MBEDTLS_PSA_CRYPTO_CLIENT) #error "MBEDTLS_USE_PSA_CRYPTO defined, but not all prerequisites" #endif @@ -869,22 +995,20 @@ #error "MBEDTLS_VERSION_FEATURES defined, but not all prerequisites" #endif -#if defined(MBEDTLS_X509_USE_C) && ( !defined(MBEDTLS_BIGNUM_C) || \ - !defined(MBEDTLS_OID_C) || !defined(MBEDTLS_ASN1_PARSE_C) || \ - !defined(MBEDTLS_PK_PARSE_C) ) +#if defined(MBEDTLS_X509_USE_C) && \ + (!defined(MBEDTLS_OID_C) || !defined(MBEDTLS_ASN1_PARSE_C) || \ + !defined(MBEDTLS_PK_PARSE_C) || \ + ( !defined(MBEDTLS_MD_C) && !defined(MBEDTLS_USE_PSA_CRYPTO) ) ) #error "MBEDTLS_X509_USE_C defined, but not all prerequisites" #endif -#if defined(MBEDTLS_X509_CREATE_C) && ( !defined(MBEDTLS_BIGNUM_C) || \ - !defined(MBEDTLS_OID_C) || !defined(MBEDTLS_ASN1_WRITE_C) || \ - !defined(MBEDTLS_PK_WRITE_C) ) +#if defined(MBEDTLS_X509_CREATE_C) && \ + (!defined(MBEDTLS_OID_C) || !defined(MBEDTLS_ASN1_WRITE_C) || \ + !defined(MBEDTLS_PK_PARSE_C) || \ + ( !defined(MBEDTLS_MD_C) && !defined(MBEDTLS_USE_PSA_CRYPTO) ) ) #error "MBEDTLS_X509_CREATE_C defined, but not all prerequisites" #endif -#if defined(MBEDTLS_CERTS_C) && !defined(MBEDTLS_X509_USE_C) -#error "MBEDTLS_CERTS_C defined, but not all prerequisites" -#endif - #if defined(MBEDTLS_X509_CRT_PARSE_C) && ( !defined(MBEDTLS_X509_USE_C) ) #error "MBEDTLS_X509_CRT_PARSE_C defined, but not all prerequisites" #endif @@ -905,6 +1029,11 @@ #error "MBEDTLS_X509_CSR_WRITE_C defined, but not all prerequisites" #endif +#if defined(MBEDTLS_X509_TRUSTED_CERTIFICATE_CALLBACK) && \ + ( !defined(MBEDTLS_X509_CRT_PARSE_C) ) +#error "MBEDTLS_X509_TRUSTED_CERTIFICATE_CALLBACK defined, but not all prerequisites" +#endif + #if defined(MBEDTLS_HAVE_INT32) && defined(MBEDTLS_HAVE_INT64) #error "MBEDTLS_HAVE_INT32 and MBEDTLS_HAVE_INT64 cannot be defined simultaneously" #endif /* MBEDTLS_HAVE_INT32 && MBEDTLS_HAVE_INT64 */ @@ -914,30 +1043,6 @@ #error "MBEDTLS_HAVE_INT32/MBEDTLS_HAVE_INT64 and MBEDTLS_HAVE_ASM cannot be defined simultaneously" #endif /* (MBEDTLS_HAVE_INT32 || MBEDTLS_HAVE_INT64) && MBEDTLS_HAVE_ASM */ -#if defined(MBEDTLS_SSL_PROTO_SSL3) -#if defined(MBEDTLS_DEPRECATED_REMOVED) -#error "MBEDTLS_SSL_PROTO_SSL3 is deprecated and will be removed in a future version of Mbed TLS" -#elif defined(MBEDTLS_DEPRECATED_WARNING) -#warning "MBEDTLS_SSL_PROTO_SSL3 is deprecated and will be removed in a future version of Mbed TLS" -#endif -#endif /* MBEDTLS_SSL_PROTO_SSL3 */ - -#if defined(MBEDTLS_SSL_SRV_SUPPORT_SSLV2_CLIENT_HELLO) -#if defined(MBEDTLS_DEPRECATED_REMOVED) -#error "MBEDTLS_SSL_SRV_SUPPORT_SSLV2_CLIENT_HELLO is deprecated and will be removed in a future version of Mbed TLS" -#elif defined(MBEDTLS_DEPRECATED_WARNING) -#warning "MBEDTLS_SSL_SRV_SUPPORT_SSLV2_CLIENT_HELLO is deprecated and will be removed in a future version of Mbed TLS" -#endif -#endif /* MBEDTLS_SSL_SRV_SUPPORT_SSLV2_CLIENT_HELLO */ - -#if defined(MBEDTLS_SSL_HW_RECORD_ACCEL) -#if defined(MBEDTLS_DEPRECATED_REMOVED) -#error "MBEDTLS_SSL_HW_RECORD_ACCEL is deprecated and will be removed in a future version of Mbed TLS" -#elif defined(MBEDTLS_DEPRECATED_WARNING) -#warning "MBEDTLS_SSL_HW_RECORD_ACCEL is deprecated and will be removed in a future version of Mbed TLS" -#endif /* MBEDTLS_DEPRECATED_REMOVED */ -#endif /* MBEDTLS_SSL_HW_RECORD_ACCEL */ - #if defined(MBEDTLS_SSL_DTLS_SRTP) && ( !defined(MBEDTLS_SSL_PROTO_DTLS) ) #error "MBEDTLS_SSL_DTLS_SRTP defined, but not all prerequisites" #endif @@ -946,10 +1051,71 @@ #error "MBEDTLS_SSL_VARIABLE_BUFFER_LENGTH defined, but not all prerequisites" #endif -#if defined(MBEDTLS_SSL_CONTEXT_SERIALIZATION) && !( defined(MBEDTLS_GCM_C) || defined(MBEDTLS_CCM_C) || defined(MBEDTLS_CHACHAPOLY_C) ) +#if defined(MBEDTLS_SSL_RECORD_SIZE_LIMIT) && ( !defined(MBEDTLS_SSL_PROTO_TLS1_3) ) +#error "MBEDTLS_SSL_RECORD_SIZE_LIMIT defined, but not all prerequisites" +#endif + +#if defined(MBEDTLS_SSL_CONTEXT_SERIALIZATION) && \ + !( defined(MBEDTLS_SSL_HAVE_CCM) || defined(MBEDTLS_SSL_HAVE_GCM) || \ + defined(MBEDTLS_SSL_HAVE_CHACHAPOLY) ) #error "MBEDTLS_SSL_CONTEXT_SERIALIZATION defined, but not all prerequisites" #endif +/* Reject attempts to enable options that have been removed and that could + * cause a build to succeed but with features removed. */ + +#if defined(MBEDTLS_HAVEGE_C) //no-check-names +#error "MBEDTLS_HAVEGE_C was removed in Mbed TLS 3.0. See https://github.com/Mbed-TLS/mbedtls/issues/2599" +#endif + +#if defined(MBEDTLS_SSL_HW_RECORD_ACCEL) //no-check-names +#error "MBEDTLS_SSL_HW_RECORD_ACCEL was removed in Mbed TLS 3.0. See https://github.com/Mbed-TLS/mbedtls/issues/4031" +#endif + +#if defined(MBEDTLS_SSL_PROTO_SSL3) //no-check-names +#error "MBEDTLS_SSL_PROTO_SSL3 (SSL v3.0 support) was removed in Mbed TLS 3.0. See https://github.com/Mbed-TLS/mbedtls/issues/4031" +#endif + +#if defined(MBEDTLS_SSL_SRV_SUPPORT_SSLV2_CLIENT_HELLO) //no-check-names +#error "MBEDTLS_SSL_SRV_SUPPORT_SSLV2_CLIENT_HELLO (SSL v2 ClientHello support) was removed in Mbed TLS 3.0. See https://github.com/Mbed-TLS/mbedtls/issues/4031" +#endif + +#if defined(MBEDTLS_SSL_TRUNCATED_HMAC_COMPAT) //no-check-names +#error "MBEDTLS_SSL_TRUNCATED_HMAC_COMPAT (compatibility with the buggy implementation of truncated HMAC in Mbed TLS up to 2.7) was removed in Mbed TLS 3.0. See https://github.com/Mbed-TLS/mbedtls/issues/4031" +#endif + +#if defined(MBEDTLS_TLS_DEFAULT_ALLOW_SHA1_IN_CERTIFICATES) //no-check-names +#error "MBEDTLS_TLS_DEFAULT_ALLOW_SHA1_IN_CERTIFICATES was removed in Mbed TLS 3.0. See the ChangeLog entry if you really need SHA-1-signed certificates." +#endif + +#if defined(MBEDTLS_ZLIB_SUPPORT) //no-check-names +#error "MBEDTLS_ZLIB_SUPPORT was removed in Mbed TLS 3.0. See https://github.com/Mbed-TLS/mbedtls/issues/4031" +#endif + +#if defined(MBEDTLS_CHECK_PARAMS) //no-check-names +#error "MBEDTLS_CHECK_PARAMS was removed in Mbed TLS 3.0. See https://github.com/Mbed-TLS/mbedtls/issues/4313" +#endif + +#if defined(MBEDTLS_SSL_CID_PADDING_GRANULARITY) //no-check-names +#error "MBEDTLS_SSL_CID_PADDING_GRANULARITY was removed in Mbed TLS 3.0. See https://github.com/Mbed-TLS/mbedtls/issues/4335" +#endif + +#if defined(MBEDTLS_SSL_TLS1_3_PADDING_GRANULARITY) //no-check-names +#error "MBEDTLS_SSL_TLS1_3_PADDING_GRANULARITY was removed in Mbed TLS 3.0. See https://github.com/Mbed-TLS/mbedtls/issues/4335" +#endif + +#if defined(MBEDTLS_SSL_TRUNCATED_HMAC) //no-check-names +#error "MBEDTLS_SSL_TRUNCATED_HMAC was removed in Mbed TLS 3.0. See https://github.com/Mbed-TLS/mbedtls/issues/4341" +#endif + +#if defined(MBEDTLS_PKCS7_C) && ( ( !defined(MBEDTLS_ASN1_PARSE_C) ) || \ + ( !defined(MBEDTLS_OID_C) ) || ( !defined(MBEDTLS_PK_PARSE_C) ) || \ + ( !defined(MBEDTLS_X509_CRT_PARSE_C) ) || \ + ( !defined(MBEDTLS_X509_CRL_PARSE_C) ) || \ + ( !defined(MBEDTLS_MD_C) ) ) +#error "MBEDTLS_PKCS7_C is defined, but not all prerequisites" +#endif + /* * Avoid warning from -pedantic. This is a convenient place for this * workaround since this is included by every single file before the diff --git a/vendor/mbedtls/include/mbedtls/cipher.h b/vendor/mbedtls/include/mbedtls/cipher.h index fa57efeb0b..1dc31c9c24 100644 --- a/vendor/mbedtls/include/mbedtls/cipher.h +++ b/vendor/mbedtls/include/mbedtls/cipher.h @@ -9,29 +9,14 @@ */ /* * Copyright The Mbed TLS Contributors - * SPDX-License-Identifier: Apache-2.0 - * - * Licensed under the Apache License, Version 2.0 (the "License"); you may - * not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT - * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. + * SPDX-License-Identifier: Apache-2.0 OR GPL-2.0-or-later */ #ifndef MBEDTLS_CIPHER_H #define MBEDTLS_CIPHER_H +#include "mbedtls/private_access.h" -#if !defined(MBEDTLS_CONFIG_FILE) -#include "mbedtls/config.h" -#else -#include MBEDTLS_CONFIG_FILE -#endif +#include "mbedtls/build_info.h" #include #include "mbedtls/platform_util.h" @@ -44,16 +29,11 @@ #define MBEDTLS_CIPHER_MODE_WITH_PADDING #endif -#if defined(MBEDTLS_ARC4_C) || defined(MBEDTLS_CIPHER_NULL_CIPHER) || \ +#if defined(MBEDTLS_CIPHER_NULL_CIPHER) || \ defined(MBEDTLS_CHACHA20_C) #define MBEDTLS_CIPHER_MODE_STREAM #endif -#if (defined(__ARMCC_VERSION) || defined(_MSC_VER)) && \ - !defined(inline) && !defined(__cplusplus) -#define inline __inline -#endif - /** The selected feature is not available. */ #define MBEDTLS_ERR_CIPHER_FEATURE_UNAVAILABLE -0x6080 /** Bad input parameters. */ @@ -69,10 +49,6 @@ /** The context is invalid. For example, because it was freed. */ #define MBEDTLS_ERR_CIPHER_INVALID_CONTEXT -0x6380 -/* MBEDTLS_ERR_CIPHER_HW_ACCEL_FAILED is deprecated and should not be used. */ -/** Cipher hardware accelerator failed. */ -#define MBEDTLS_ERR_CIPHER_HW_ACCEL_FAILED -0x6400 - #define MBEDTLS_CIPHER_VARIABLE_IV_LEN 0x01 /**< Cipher accepts IVs of variable length. */ #define MBEDTLS_CIPHER_VARIABLE_KEY_LEN 0x02 /**< Cipher accepts keys of variable length. */ @@ -83,7 +59,7 @@ extern "C" { /** * \brief Supported cipher types. * - * \warning RC4 and DES/3DES are considered weak ciphers and their use + * \warning DES/3DES are considered weak ciphers and their use * constitutes a security risk. We recommend considering stronger * ciphers instead. */ @@ -94,8 +70,6 @@ typedef enum { MBEDTLS_CIPHER_ID_DES, /**< The DES cipher. \warning DES is considered weak. */ MBEDTLS_CIPHER_ID_3DES, /**< The Triple DES cipher. \warning 3DES is considered weak. */ MBEDTLS_CIPHER_ID_CAMELLIA, /**< The Camellia cipher. */ - MBEDTLS_CIPHER_ID_BLOWFISH, /**< The Blowfish cipher. */ - MBEDTLS_CIPHER_ID_ARC4, /**< The RC4 cipher. */ MBEDTLS_CIPHER_ID_ARIA, /**< The Aria cipher. */ MBEDTLS_CIPHER_ID_CHACHA20, /**< The ChaCha20 cipher. */ } mbedtls_cipher_id_t; @@ -103,7 +77,7 @@ typedef enum { /** * \brief Supported {cipher type, cipher mode} pairs. * - * \warning RC4 and DES/3DES are considered weak ciphers and their use + * \warning DES/3DES are considered weak ciphers and their use * constitutes a security risk. We recommend considering stronger * ciphers instead. */ @@ -146,17 +120,18 @@ typedef enum { MBEDTLS_CIPHER_DES_EDE_CBC, /**< DES cipher with EDE CBC mode. \warning 3DES is considered weak. */ MBEDTLS_CIPHER_DES_EDE3_ECB, /**< DES cipher with EDE3 ECB mode. \warning 3DES is considered weak. */ MBEDTLS_CIPHER_DES_EDE3_CBC, /**< DES cipher with EDE3 CBC mode. \warning 3DES is considered weak. */ - MBEDTLS_CIPHER_BLOWFISH_ECB, /**< Blowfish cipher with ECB mode. */ - MBEDTLS_CIPHER_BLOWFISH_CBC, /**< Blowfish cipher with CBC mode. */ - MBEDTLS_CIPHER_BLOWFISH_CFB64, /**< Blowfish cipher with CFB64 mode. */ - MBEDTLS_CIPHER_BLOWFISH_CTR, /**< Blowfish cipher with CTR mode. */ - MBEDTLS_CIPHER_ARC4_128, /**< RC4 cipher with 128-bit mode. */ MBEDTLS_CIPHER_AES_128_CCM, /**< AES cipher with 128-bit CCM mode. */ MBEDTLS_CIPHER_AES_192_CCM, /**< AES cipher with 192-bit CCM mode. */ MBEDTLS_CIPHER_AES_256_CCM, /**< AES cipher with 256-bit CCM mode. */ + MBEDTLS_CIPHER_AES_128_CCM_STAR_NO_TAG, /**< AES cipher with 128-bit CCM_STAR_NO_TAG mode. */ + MBEDTLS_CIPHER_AES_192_CCM_STAR_NO_TAG, /**< AES cipher with 192-bit CCM_STAR_NO_TAG mode. */ + MBEDTLS_CIPHER_AES_256_CCM_STAR_NO_TAG, /**< AES cipher with 256-bit CCM_STAR_NO_TAG mode. */ MBEDTLS_CIPHER_CAMELLIA_128_CCM, /**< Camellia cipher with 128-bit CCM mode. */ MBEDTLS_CIPHER_CAMELLIA_192_CCM, /**< Camellia cipher with 192-bit CCM mode. */ MBEDTLS_CIPHER_CAMELLIA_256_CCM, /**< Camellia cipher with 256-bit CCM mode. */ + MBEDTLS_CIPHER_CAMELLIA_128_CCM_STAR_NO_TAG, /**< Camellia cipher with 128-bit CCM_STAR_NO_TAG mode. */ + MBEDTLS_CIPHER_CAMELLIA_192_CCM_STAR_NO_TAG, /**< Camellia cipher with 192-bit CCM_STAR_NO_TAG mode. */ + MBEDTLS_CIPHER_CAMELLIA_256_CCM_STAR_NO_TAG, /**< Camellia cipher with 256-bit CCM_STAR_NO_TAG mode. */ MBEDTLS_CIPHER_ARIA_128_ECB, /**< Aria cipher with 128-bit key and ECB mode. */ MBEDTLS_CIPHER_ARIA_192_ECB, /**< Aria cipher with 192-bit key and ECB mode. */ MBEDTLS_CIPHER_ARIA_256_ECB, /**< Aria cipher with 256-bit key and ECB mode. */ @@ -175,6 +150,9 @@ typedef enum { MBEDTLS_CIPHER_ARIA_128_CCM, /**< Aria cipher with 128-bit key and CCM mode. */ MBEDTLS_CIPHER_ARIA_192_CCM, /**< Aria cipher with 192-bit key and CCM mode. */ MBEDTLS_CIPHER_ARIA_256_CCM, /**< Aria cipher with 256-bit key and CCM mode. */ + MBEDTLS_CIPHER_ARIA_128_CCM_STAR_NO_TAG, /**< Aria cipher with 128-bit key and CCM_STAR_NO_TAG mode. */ + MBEDTLS_CIPHER_ARIA_192_CCM_STAR_NO_TAG, /**< Aria cipher with 192-bit key and CCM_STAR_NO_TAG mode. */ + MBEDTLS_CIPHER_ARIA_256_CCM_STAR_NO_TAG, /**< Aria cipher with 256-bit key and CCM_STAR_NO_TAG mode. */ MBEDTLS_CIPHER_AES_128_OFB, /**< AES 128-bit cipher in OFB mode. */ MBEDTLS_CIPHER_AES_192_OFB, /**< AES 192-bit cipher in OFB mode. */ MBEDTLS_CIPHER_AES_256_OFB, /**< AES 256-bit cipher in OFB mode. */ @@ -201,6 +179,7 @@ typedef enum { MBEDTLS_MODE_GCM, /**< The GCM cipher mode. */ MBEDTLS_MODE_STREAM, /**< The stream cipher mode. */ MBEDTLS_MODE_CCM, /**< The CCM cipher mode. */ + MBEDTLS_MODE_CCM_STAR_NO_TAG, /**< The CCM*-no-tag cipher mode. */ MBEDTLS_MODE_XTS, /**< The XTS cipher mode. */ MBEDTLS_MODE_CHACHAPOLY, /**< The ChaCha-Poly cipher mode. */ MBEDTLS_MODE_KW, /**< The SP800-38F KW mode */ @@ -237,13 +216,13 @@ enum { /** Maximum length of any IV, in Bytes. */ /* This should ideally be derived automatically from list of ciphers. * This should be kept in sync with MBEDTLS_SSL_MAX_IV_LENGTH defined - * in ssl_internal.h. */ + * in library/ssl_misc.h. */ #define MBEDTLS_MAX_IV_LENGTH 16 /** Maximum block size of any cipher, in Bytes. */ /* This should ideally be derived automatically from list of ciphers. * This should be kept in sync with MBEDTLS_SSL_MAX_BLOCK_LENGTH defined - * in ssl_internal.h. */ + * in library/ssl_misc.h. */ #define MBEDTLS_MAX_BLOCK_LENGTH 16 /** Maximum key length, in Bytes. */ @@ -251,7 +230,7 @@ enum { * For now, only check whether XTS is enabled which uses 64 Byte keys, * and use 32 Bytes as an upper bound for the maximum key length otherwise. * This should be kept in sync with MBEDTLS_SSL_MAX_BLOCK_LENGTH defined - * in ssl_internal.h, which however deliberately ignores the case of XTS + * in library/ssl_misc.h, which however deliberately ignores the case of XTS * since the latter isn't used in SSL/TLS. */ #if defined(MBEDTLS_CIPHER_MODE_XTS) #define MBEDTLS_MAX_KEY_LENGTH 64 @@ -272,90 +251,110 @@ typedef struct mbedtls_cmac_context_t mbedtls_cmac_context_t; /** * Cipher information. Allows calling cipher functions * in a generic way. + * + * \note The library does not support custom cipher info structures, + * only built-in structures returned by the functions + * mbedtls_cipher_info_from_string(), + * mbedtls_cipher_info_from_type(), + * mbedtls_cipher_info_from_values(), + * mbedtls_cipher_info_from_psa(). + * + * \note Some fields store a value that has been right-shifted to save + * code-size, so should not be used directly. The accessor + * functions adjust for this and return the "natural" value. */ typedef struct mbedtls_cipher_info_t { - /** Full cipher identifier. For example, - * MBEDTLS_CIPHER_AES_256_CBC. - */ - mbedtls_cipher_type_t type; + /** Name of the cipher. */ + const char *MBEDTLS_PRIVATE(name); + + /** The block size, in bytes. */ + unsigned int MBEDTLS_PRIVATE(block_size) : 5; - /** The cipher mode. For example, MBEDTLS_MODE_CBC. */ - mbedtls_cipher_mode_t mode; + /** IV or nonce size, in bytes (right shifted by #MBEDTLS_IV_SIZE_SHIFT). + * For ciphers that accept variable IV sizes, + * this is the recommended size. + */ + unsigned int MBEDTLS_PRIVATE(iv_size) : 3; - /** The cipher key length, in bits. This is the - * default length for variable sized ciphers. + /** The cipher key length, in bits (right shifted by #MBEDTLS_KEY_BITLEN_SHIFT). + * This is the default length for variable sized ciphers. * Includes parity bits for ciphers like DES. */ - unsigned int key_bitlen; + unsigned int MBEDTLS_PRIVATE(key_bitlen) : 4; - /** Name of the cipher. */ - const char *name; + /** The cipher mode (as per mbedtls_cipher_mode_t). + * For example, MBEDTLS_MODE_CBC. + */ + unsigned int MBEDTLS_PRIVATE(mode) : 4; - /** IV or nonce size, in Bytes. - * For ciphers that accept variable IV sizes, - * this is the recommended size. + /** Full cipher identifier (as per mbedtls_cipher_type_t). + * For example, MBEDTLS_CIPHER_AES_256_CBC. + * + * This could be 7 bits, but 8 bits retains byte alignment for the + * next field, which reduces code size to access that field. */ - unsigned int iv_size; + unsigned int MBEDTLS_PRIVATE(type) : 8; /** Bitflag comprised of MBEDTLS_CIPHER_VARIABLE_IV_LEN and * MBEDTLS_CIPHER_VARIABLE_KEY_LEN indicating whether the * cipher supports variable IV or variable key sizes, respectively. */ - int flags; - - /** The block size, in Bytes. */ - unsigned int block_size; + unsigned int MBEDTLS_PRIVATE(flags) : 2; - /** Struct for base cipher information and functions. */ - const mbedtls_cipher_base_t *base; + /** Index to LUT for base cipher information and functions. */ + unsigned int MBEDTLS_PRIVATE(base_idx) : 5; } mbedtls_cipher_info_t; +/* For internal use only. + * These are used to more compactly represent the fields above. */ +#define MBEDTLS_KEY_BITLEN_SHIFT 6 +#define MBEDTLS_IV_SIZE_SHIFT 2 /** * Generic cipher context. */ typedef struct mbedtls_cipher_context_t { /** Information about the associated cipher. */ - const mbedtls_cipher_info_t *cipher_info; + const mbedtls_cipher_info_t *MBEDTLS_PRIVATE(cipher_info); /** Key length to use. */ - int key_bitlen; + int MBEDTLS_PRIVATE(key_bitlen); /** Operation that the key of the context has been * initialized for. */ - mbedtls_operation_t operation; + mbedtls_operation_t MBEDTLS_PRIVATE(operation); #if defined(MBEDTLS_CIPHER_MODE_WITH_PADDING) /** Padding functions to use, if relevant for * the specific cipher mode. */ - void (*add_padding)(unsigned char *output, size_t olen, size_t data_len); - int (*get_padding)(unsigned char *input, size_t ilen, size_t *data_len); + void(*MBEDTLS_PRIVATE(add_padding))(unsigned char *output, size_t olen, size_t data_len); + int(*MBEDTLS_PRIVATE(get_padding))(unsigned char *input, size_t ilen, size_t *data_len); #endif /** Buffer for input that has not been processed yet. */ - unsigned char unprocessed_data[MBEDTLS_MAX_BLOCK_LENGTH]; + unsigned char MBEDTLS_PRIVATE(unprocessed_data)[MBEDTLS_MAX_BLOCK_LENGTH]; /** Number of Bytes that have not been processed yet. */ - size_t unprocessed_len; + size_t MBEDTLS_PRIVATE(unprocessed_len); /** Current IV or NONCE_COUNTER for CTR-mode, data unit (or sector) number * for XTS-mode. */ - unsigned char iv[MBEDTLS_MAX_IV_LENGTH]; + unsigned char MBEDTLS_PRIVATE(iv)[MBEDTLS_MAX_IV_LENGTH]; /** IV size in Bytes, for ciphers with variable-length IVs. */ - size_t iv_size; + size_t MBEDTLS_PRIVATE(iv_size); /** The cipher-specific context. */ - void *cipher_ctx; + void *MBEDTLS_PRIVATE(cipher_ctx); #if defined(MBEDTLS_CMAC_C) /** CMAC-specific context. */ - mbedtls_cmac_context_t *cmac_ctx; + mbedtls_cmac_context_t *MBEDTLS_PRIVATE(cmac_ctx); #endif -#if defined(MBEDTLS_USE_PSA_CRYPTO) +#if defined(MBEDTLS_USE_PSA_CRYPTO) && !defined(MBEDTLS_DEPRECATED_REMOVED) /** Indicates whether the cipher operations should be performed * by Mbed TLS' own crypto library or an external implementation * of the PSA Crypto API. @@ -363,8 +362,8 @@ typedef struct mbedtls_cipher_context_t { * mbedtls_cipher_setup(), and set if it was established through * mbedtls_cipher_setup_psa(). */ - unsigned char psa_enabled; -#endif /* MBEDTLS_USE_PSA_CRYPTO */ + unsigned char MBEDTLS_PRIVATE(psa_enabled); +#endif /* MBEDTLS_USE_PSA_CRYPTO && !MBEDTLS_DEPRECATED_REMOVED */ } mbedtls_cipher_context_t; @@ -426,6 +425,164 @@ const mbedtls_cipher_info_t *mbedtls_cipher_info_from_values(const mbedtls_ciphe int key_bitlen, const mbedtls_cipher_mode_t mode); +/** + * \brief Retrieve the identifier for a cipher info structure. + * + * \param[in] info The cipher info structure to query. + * This may be \c NULL. + * + * \return The full cipher identifier (\c MBEDTLS_CIPHER_xxx). + * \return #MBEDTLS_CIPHER_NONE if \p info is \c NULL. + */ +static inline mbedtls_cipher_type_t mbedtls_cipher_info_get_type( + const mbedtls_cipher_info_t *info) +{ + if (info == NULL) { + return MBEDTLS_CIPHER_NONE; + } else { + return (mbedtls_cipher_type_t) info->MBEDTLS_PRIVATE(type); + } +} + +/** + * \brief Retrieve the operation mode for a cipher info structure. + * + * \param[in] info The cipher info structure to query. + * This may be \c NULL. + * + * \return The cipher mode (\c MBEDTLS_MODE_xxx). + * \return #MBEDTLS_MODE_NONE if \p info is \c NULL. + */ +static inline mbedtls_cipher_mode_t mbedtls_cipher_info_get_mode( + const mbedtls_cipher_info_t *info) +{ + if (info == NULL) { + return MBEDTLS_MODE_NONE; + } else { + return (mbedtls_cipher_mode_t) info->MBEDTLS_PRIVATE(mode); + } +} + +/** + * \brief Retrieve the key size for a cipher info structure. + * + * \param[in] info The cipher info structure to query. + * This may be \c NULL. + * + * \return The key length in bits. + * For variable-sized ciphers, this is the default length. + * For DES, this includes the parity bits. + * \return \c 0 if \p info is \c NULL. + */ +static inline size_t mbedtls_cipher_info_get_key_bitlen( + const mbedtls_cipher_info_t *info) +{ + if (info == NULL) { + return 0; + } else { + return ((size_t) info->MBEDTLS_PRIVATE(key_bitlen)) << MBEDTLS_KEY_BITLEN_SHIFT; + } +} + +/** + * \brief Retrieve the human-readable name for a + * cipher info structure. + * + * \param[in] info The cipher info structure to query. + * This may be \c NULL. + * + * \return The cipher name, which is a human readable string, + * with static storage duration. + * \return \c NULL if \p info is \c NULL. + */ +static inline const char *mbedtls_cipher_info_get_name( + const mbedtls_cipher_info_t *info) +{ + if (info == NULL) { + return NULL; + } else { + return info->MBEDTLS_PRIVATE(name); + } +} + +/** + * \brief This function returns the size of the IV or nonce + * for the cipher info structure, in bytes. + * + * \param info The cipher info structure. This may be \c NULL. + * + * \return The recommended IV size. + * \return \c 0 for ciphers not using an IV or a nonce. + * \return \c 0 if \p info is \c NULL. + */ +static inline size_t mbedtls_cipher_info_get_iv_size( + const mbedtls_cipher_info_t *info) +{ + if (info == NULL) { + return 0; + } + + return ((size_t) info->MBEDTLS_PRIVATE(iv_size)) << MBEDTLS_IV_SIZE_SHIFT; +} + +/** + * \brief This function returns the block size of the given + * cipher info structure in bytes. + * + * \param info The cipher info structure. This may be \c NULL. + * + * \return The block size of the cipher. + * \return \c 1 if the cipher is a stream cipher. + * \return \c 0 if \p info is \c NULL. + */ +static inline size_t mbedtls_cipher_info_get_block_size( + const mbedtls_cipher_info_t *info) +{ + if (info == NULL) { + return 0; + } + + return (size_t) (info->MBEDTLS_PRIVATE(block_size)); +} + +/** + * \brief This function returns a non-zero value if the key length for + * the given cipher is variable. + * + * \param info The cipher info structure. This may be \c NULL. + * + * \return Non-zero if the key length is variable, \c 0 otherwise. + * \return \c 0 if the given pointer is \c NULL. + */ +static inline int mbedtls_cipher_info_has_variable_key_bitlen( + const mbedtls_cipher_info_t *info) +{ + if (info == NULL) { + return 0; + } + + return info->MBEDTLS_PRIVATE(flags) & MBEDTLS_CIPHER_VARIABLE_KEY_LEN; +} + +/** + * \brief This function returns a non-zero value if the IV size for + * the given cipher is variable. + * + * \param info The cipher info structure. This may be \c NULL. + * + * \return Non-zero if the IV size is variable, \c 0 otherwise. + * \return \c 0 if the given pointer is \c NULL. + */ +static inline int mbedtls_cipher_info_has_variable_iv_size( + const mbedtls_cipher_info_t *info) +{ + if (info == NULL) { + return 0; + } + + return info->MBEDTLS_PRIVATE(flags) & MBEDTLS_CIPHER_VARIABLE_IV_LEN; +} + /** * \brief This function initializes a \p ctx as NONE. * @@ -449,12 +606,6 @@ void mbedtls_cipher_free(mbedtls_cipher_context_t *ctx); * \brief This function prepares a cipher context for * use with the given cipher primitive. * - * \warning In CBC mode, if mbedtls_cipher_set_padding_mode() is not called: - * - If MBEDTLS_CIPHER_PADDING_PKCS7 is enabled, the - * context will use PKCS7 padding. - * - Otherwise the context uses no padding and the input - * must be a whole number of blocks. - * * \note After calling this function, you should call * mbedtls_cipher_setkey() and, if the mode uses padding, * mbedtls_cipher_set_padding_mode(), then for each @@ -476,27 +627,29 @@ void mbedtls_cipher_free(mbedtls_cipher_context_t *ctx); * parameter-verification failure. * \return #MBEDTLS_ERR_CIPHER_ALLOC_FAILED if allocation of the * cipher-specific context fails. - * - * \internal Currently, the function also clears the structure. - * In future versions, the caller will be required to call - * mbedtls_cipher_init() on the structure first. */ int mbedtls_cipher_setup(mbedtls_cipher_context_t *ctx, const mbedtls_cipher_info_t *cipher_info); #if defined(MBEDTLS_USE_PSA_CRYPTO) +#if !defined(MBEDTLS_DEPRECATED_REMOVED) /** * \brief This function initializes a cipher context for * PSA-based use with the given cipher primitive. * + * \deprecated This function is deprecated and will be removed in a + * future version of the library. + * Please use psa_aead_xxx() / psa_cipher_xxx() directly + * instead. + * * \note See #MBEDTLS_USE_PSA_CRYPTO for information on PSA. * * \param ctx The context to initialize. May not be \c NULL. * \param cipher_info The cipher to use. * \param taglen For AEAD ciphers, the length in bytes of the * authentication tag to use. Subsequent uses of - * mbedtls_cipher_auth_encrypt() or - * mbedtls_cipher_auth_decrypt() must provide + * mbedtls_cipher_auth_encrypt_ext() or + * mbedtls_cipher_auth_decrypt_ext() must provide * the same tag length. * For non-AEAD ciphers, the value must be \c 0. * @@ -506,28 +659,30 @@ int mbedtls_cipher_setup(mbedtls_cipher_context_t *ctx, * \return #MBEDTLS_ERR_CIPHER_ALLOC_FAILED if allocation of the * cipher-specific context fails. */ -int mbedtls_cipher_setup_psa(mbedtls_cipher_context_t *ctx, - const mbedtls_cipher_info_t *cipher_info, - size_t taglen); +int MBEDTLS_DEPRECATED mbedtls_cipher_setup_psa(mbedtls_cipher_context_t *ctx, + const mbedtls_cipher_info_t *cipher_info, + size_t taglen); +#endif /* MBEDTLS_DEPRECATED_REMOVED */ #endif /* MBEDTLS_USE_PSA_CRYPTO */ /** - * \brief This function returns the block size of the given cipher. + * \brief This function returns the block size of the given cipher + * in bytes. * - * \param ctx The context of the cipher. This must be initialized. + * \param ctx The context of the cipher. * * \return The block size of the underlying cipher. + * \return \c 1 if the cipher is a stream cipher. * \return \c 0 if \p ctx has not been initialized. */ static inline unsigned int mbedtls_cipher_get_block_size( const mbedtls_cipher_context_t *ctx) { - MBEDTLS_INTERNAL_VALIDATE_RET(ctx != NULL, 0); - if (ctx->cipher_info == NULL) { + if (ctx->MBEDTLS_PRIVATE(cipher_info) == NULL) { return 0; } - return ctx->cipher_info->block_size; + return (unsigned int) ctx->MBEDTLS_PRIVATE(cipher_info)->MBEDTLS_PRIVATE(block_size); } /** @@ -542,12 +697,11 @@ static inline unsigned int mbedtls_cipher_get_block_size( static inline mbedtls_cipher_mode_t mbedtls_cipher_get_cipher_mode( const mbedtls_cipher_context_t *ctx) { - MBEDTLS_INTERNAL_VALIDATE_RET(ctx != NULL, MBEDTLS_MODE_NONE); - if (ctx->cipher_info == NULL) { + if (ctx->MBEDTLS_PRIVATE(cipher_info) == NULL) { return MBEDTLS_MODE_NONE; } - return ctx->cipher_info->mode; + return (mbedtls_cipher_mode_t) ctx->MBEDTLS_PRIVATE(cipher_info)->MBEDTLS_PRIVATE(mode); } /** @@ -563,16 +717,16 @@ static inline mbedtls_cipher_mode_t mbedtls_cipher_get_cipher_mode( static inline int mbedtls_cipher_get_iv_size( const mbedtls_cipher_context_t *ctx) { - MBEDTLS_INTERNAL_VALIDATE_RET(ctx != NULL, 0); - if (ctx->cipher_info == NULL) { + if (ctx->MBEDTLS_PRIVATE(cipher_info) == NULL) { return 0; } - if (ctx->iv_size != 0) { - return (int) ctx->iv_size; + if (ctx->MBEDTLS_PRIVATE(iv_size) != 0) { + return (int) ctx->MBEDTLS_PRIVATE(iv_size); } - return (int) ctx->cipher_info->iv_size; + return (int) (((int) ctx->MBEDTLS_PRIVATE(cipher_info)->MBEDTLS_PRIVATE(iv_size)) << + MBEDTLS_IV_SIZE_SHIFT); } /** @@ -586,13 +740,11 @@ static inline int mbedtls_cipher_get_iv_size( static inline mbedtls_cipher_type_t mbedtls_cipher_get_type( const mbedtls_cipher_context_t *ctx) { - MBEDTLS_INTERNAL_VALIDATE_RET( - ctx != NULL, MBEDTLS_CIPHER_NONE); - if (ctx->cipher_info == NULL) { + if (ctx->MBEDTLS_PRIVATE(cipher_info) == NULL) { return MBEDTLS_CIPHER_NONE; } - return ctx->cipher_info->type; + return (mbedtls_cipher_type_t) ctx->MBEDTLS_PRIVATE(cipher_info)->MBEDTLS_PRIVATE(type); } /** @@ -607,12 +759,11 @@ static inline mbedtls_cipher_type_t mbedtls_cipher_get_type( static inline const char *mbedtls_cipher_get_name( const mbedtls_cipher_context_t *ctx) { - MBEDTLS_INTERNAL_VALIDATE_RET(ctx != NULL, 0); - if (ctx->cipher_info == NULL) { + if (ctx->MBEDTLS_PRIVATE(cipher_info) == NULL) { return 0; } - return ctx->cipher_info->name; + return ctx->MBEDTLS_PRIVATE(cipher_info)->MBEDTLS_PRIVATE(name); } /** @@ -627,13 +778,12 @@ static inline const char *mbedtls_cipher_get_name( static inline int mbedtls_cipher_get_key_bitlen( const mbedtls_cipher_context_t *ctx) { - MBEDTLS_INTERNAL_VALIDATE_RET( - ctx != NULL, MBEDTLS_KEY_LENGTH_NONE); - if (ctx->cipher_info == NULL) { + if (ctx->MBEDTLS_PRIVATE(cipher_info) == NULL) { return MBEDTLS_KEY_LENGTH_NONE; } - return (int) ctx->cipher_info->key_bitlen; + return (int) ctx->MBEDTLS_PRIVATE(cipher_info)->MBEDTLS_PRIVATE(key_bitlen) << + MBEDTLS_KEY_BITLEN_SHIFT; } /** @@ -647,13 +797,11 @@ static inline int mbedtls_cipher_get_key_bitlen( static inline mbedtls_operation_t mbedtls_cipher_get_operation( const mbedtls_cipher_context_t *ctx) { - MBEDTLS_INTERNAL_VALIDATE_RET( - ctx != NULL, MBEDTLS_OPERATION_NONE); - if (ctx->cipher_info == NULL) { + if (ctx->MBEDTLS_PRIVATE(cipher_info) == NULL) { return MBEDTLS_OPERATION_NONE; } - return ctx->operation; + return ctx->MBEDTLS_PRIVATE(operation); } /** @@ -682,6 +830,7 @@ int mbedtls_cipher_setkey(mbedtls_cipher_context_t *ctx, * \brief This function sets the padding mode, for cipher modes * that use padding. * + * * \param ctx The generic cipher context. This must be initialized and * bound to a cipher information structure. * \param mode The padding mode. @@ -703,6 +852,12 @@ int mbedtls_cipher_set_padding_mode(mbedtls_cipher_context_t *ctx, * \note Some ciphers do not use IVs nor nonce. For these * ciphers, this function has no effect. * + * \note For #MBEDTLS_CIPHER_CHACHA20, the nonce length must + * be 12, and the initial counter value is 0. + * + * \note For #MBEDTLS_CIPHER_CHACHA20_POLY1305, the nonce length + * must be 12. + * * \param ctx The generic cipher context. This must be initialized and * bound to a cipher information structure. * \param iv The IV to use, or NONCE_COUNTER for CTR-mode ciphers. This @@ -737,7 +892,8 @@ int mbedtls_cipher_set_iv(mbedtls_cipher_context_t *ctx, * 2. mbedtls_cipher_reset() * 3. mbedtls_cipher_update_ad() * 4. mbedtls_cipher_update() one or more times - * 5. mbedtls_cipher_check_tag() (for decryption) or + * 5. mbedtls_cipher_finish() + * 6. mbedtls_cipher_check_tag() (for decryption) or * mbedtls_cipher_write_tag() (for encryption). * . * This sequence can be repeated to encrypt or decrypt multiple @@ -755,8 +911,6 @@ int mbedtls_cipher_reset(mbedtls_cipher_context_t *ctx); /** * \brief This function adds additional data for AEAD ciphers. * Currently supported with GCM and ChaCha20+Poly1305. - * This must be called exactly once, after - * mbedtls_cipher_reset(). * * \param ctx The generic cipher context. This must be initialized. * \param ad The additional data to use. This must be a readable @@ -780,11 +934,6 @@ int mbedtls_cipher_update_ad(mbedtls_cipher_context_t *ctx, * Exception: For MBEDTLS_MODE_ECB, expects a single block * in size. For example, 16 Bytes for AES. * - * \note If the underlying cipher is used in GCM mode, all calls - * to this function, except for the last one before - * mbedtls_cipher_finish(), must have \p ilen as a - * multiple of the block size of the cipher. - * * \param ctx The generic cipher context. This must be initialized and * bound to a key. * \param input The buffer holding the input data. This must be a @@ -909,129 +1058,6 @@ int mbedtls_cipher_crypt(mbedtls_cipher_context_t *ctx, const unsigned char *input, size_t ilen, unsigned char *output, size_t *olen); -#if defined(MBEDTLS_CIPHER_MODE_AEAD) -#if !defined(MBEDTLS_DEPRECATED_REMOVED) -#if defined(MBEDTLS_DEPRECATED_WARNING) -#define MBEDTLS_DEPRECATED __attribute__((deprecated)) -#else -#define MBEDTLS_DEPRECATED -#endif /* MBEDTLS_DEPRECATED_WARNING */ -/** - * \brief The generic authenticated encryption (AEAD) function. - * - * \deprecated Superseded by mbedtls_cipher_auth_encrypt_ext(). - * - * \note This function only supports AEAD algorithms, not key - * wrapping algorithms such as NIST_KW; for this, see - * mbedtls_cipher_auth_encrypt_ext(). - * - * \param ctx The generic cipher context. This must be initialized and - * bound to a key associated with an AEAD algorithm. - * \param iv The nonce to use. This must be a readable buffer of - * at least \p iv_len Bytes and must not be \c NULL. - * \param iv_len The length of the nonce. This must satisfy the - * constraints imposed by the AEAD cipher used. - * \param ad The additional data to authenticate. This must be a - * readable buffer of at least \p ad_len Bytes, and may - * be \c NULL is \p ad_len is \c 0. - * \param ad_len The length of \p ad. - * \param input The buffer holding the input data. This must be a - * readable buffer of at least \p ilen Bytes, and may be - * \c NULL if \p ilen is \c 0. - * \param ilen The length of the input data. - * \param output The buffer for the output data. This must be a - * writable buffer of at least \p ilen Bytes, and must - * not be \c NULL. - * \param olen This will be filled with the actual number of Bytes - * written to the \p output buffer. This must point to a - * writable object of type \c size_t. - * \param tag The buffer for the authentication tag. This must be a - * writable buffer of at least \p tag_len Bytes. See note - * below regarding restrictions with PSA-based contexts. - * \param tag_len The desired length of the authentication tag. This - * must match the constraints imposed by the AEAD cipher - * used, and in particular must not be \c 0. - * - * \note If the context is based on PSA (that is, it was set up - * with mbedtls_cipher_setup_psa()), then it is required - * that \c tag == output + ilen. That is, the tag must be - * appended to the ciphertext as recommended by RFC 5116. - * - * \return \c 0 on success. - * \return #MBEDTLS_ERR_CIPHER_BAD_INPUT_DATA on - * parameter-verification failure. - * \return A cipher-specific error code on failure. - */ -int MBEDTLS_DEPRECATED mbedtls_cipher_auth_encrypt( - mbedtls_cipher_context_t *ctx, - const unsigned char *iv, size_t iv_len, - const unsigned char *ad, size_t ad_len, - const unsigned char *input, size_t ilen, - unsigned char *output, size_t *olen, - unsigned char *tag, size_t tag_len); - -/** - * \brief The generic authenticated decryption (AEAD) function. - * - * \deprecated Superseded by mbedtls_cipher_auth_decrypt_ext(). - * - * \note This function only supports AEAD algorithms, not key - * wrapping algorithms such as NIST_KW; for this, see - * mbedtls_cipher_auth_decrypt_ext(). - * - * \note If the data is not authentic, then the output buffer - * is zeroed out to prevent the unauthentic plaintext being - * used, making this interface safer. - * - * \param ctx The generic cipher context. This must be initialized and - * bound to a key associated with an AEAD algorithm. - * \param iv The nonce to use. This must be a readable buffer of - * at least \p iv_len Bytes and must not be \c NULL. - * \param iv_len The length of the nonce. This must satisfy the - * constraints imposed by the AEAD cipher used. - * \param ad The additional data to authenticate. This must be a - * readable buffer of at least \p ad_len Bytes, and may - * be \c NULL is \p ad_len is \c 0. - * \param ad_len The length of \p ad. - * \param input The buffer holding the input data. This must be a - * readable buffer of at least \p ilen Bytes, and may be - * \c NULL if \p ilen is \c 0. - * \param ilen The length of the input data. - * \param output The buffer for the output data. This must be a - * writable buffer of at least \p ilen Bytes, and must - * not be \c NULL. - * \param olen This will be filled with the actual number of Bytes - * written to the \p output buffer. This must point to a - * writable object of type \c size_t. - * \param tag The buffer for the authentication tag. This must be a - * readable buffer of at least \p tag_len Bytes. See note - * below regarding restrictions with PSA-based contexts. - * \param tag_len The length of the authentication tag. This must match - * the constraints imposed by the AEAD cipher used, and in - * particular must not be \c 0. - * - * \note If the context is based on PSA (that is, it was set up - * with mbedtls_cipher_setup_psa()), then it is required - * that \c tag == input + len. That is, the tag must be - * appended to the ciphertext as recommended by RFC 5116. - * - * \return \c 0 on success. - * \return #MBEDTLS_ERR_CIPHER_BAD_INPUT_DATA on - * parameter-verification failure. - * \return #MBEDTLS_ERR_CIPHER_AUTH_FAILED if data is not authentic. - * \return A cipher-specific error code on failure. - */ -int MBEDTLS_DEPRECATED mbedtls_cipher_auth_decrypt( - mbedtls_cipher_context_t *ctx, - const unsigned char *iv, size_t iv_len, - const unsigned char *ad, size_t ad_len, - const unsigned char *input, size_t ilen, - unsigned char *output, size_t *olen, - const unsigned char *tag, size_t tag_len); -#undef MBEDTLS_DEPRECATED -#endif /* MBEDTLS_DEPRECATED_REMOVED */ -#endif /* MBEDTLS_CIPHER_MODE_AEAD */ - #if defined(MBEDTLS_CIPHER_MODE_AEAD) || defined(MBEDTLS_NIST_KW_C) /** * \brief The authenticated encryption (AEAD/NIST_KW) function. diff --git a/vendor/mbedtls/include/mbedtls/cmac.h b/vendor/mbedtls/include/mbedtls/cmac.h index 5c3bcbaecb..97b86fc42b 100644 --- a/vendor/mbedtls/include/mbedtls/cmac.h +++ b/vendor/mbedtls/include/mbedtls/cmac.h @@ -5,32 +5,18 @@ * * The Cipher-based Message Authentication Code (CMAC) Mode for * Authentication is defined in RFC-4493: The AES-CMAC Algorithm. + * It is supported with AES and DES. */ /* * Copyright The Mbed TLS Contributors - * SPDX-License-Identifier: Apache-2.0 - * - * Licensed under the Apache License, Version 2.0 (the "License"); you may - * not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT - * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. + * SPDX-License-Identifier: Apache-2.0 OR GPL-2.0-or-later */ #ifndef MBEDTLS_CMAC_H #define MBEDTLS_CMAC_H +#include "mbedtls/private_access.h" -#if !defined(MBEDTLS_CONFIG_FILE) -#include "mbedtls/config.h" -#else -#include MBEDTLS_CONFIG_FILE -#endif +#include "mbedtls/build_info.h" #include "mbedtls/cipher.h" @@ -38,23 +24,33 @@ extern "C" { #endif -/* MBEDTLS_ERR_CMAC_HW_ACCEL_FAILED is deprecated and should not be used. */ -/** CMAC hardware accelerator failed. */ -#define MBEDTLS_ERR_CMAC_HW_ACCEL_FAILED -0x007A - #define MBEDTLS_AES_BLOCK_SIZE 16 #define MBEDTLS_DES3_BLOCK_SIZE 8 - -/* Although the CMAC module does not support ARIA or CAMELLIA, we adjust the value of - * MBEDTLS_CIPHER_BLKSIZE_MAX to reflect these ciphers. - * This is done to avoid confusion, given the general-purpose name of the macro. */ -#if defined(MBEDTLS_AES_C) || defined(MBEDTLS_ARIA_C) || defined(MBEDTLS_CAMELLIA_C) -#define MBEDTLS_CIPHER_BLKSIZE_MAX 16 /**< The longest block used by CMAC is that of AES. */ +/* We don't support Camellia or ARIA in this module */ +#if defined(MBEDTLS_AES_C) +#define MBEDTLS_CMAC_MAX_BLOCK_SIZE 16 /**< The longest block used by CMAC is that of AES. */ #else -#define MBEDTLS_CIPHER_BLKSIZE_MAX 8 /**< The longest block used by CMAC is that of 3DES. */ +#define MBEDTLS_CMAC_MAX_BLOCK_SIZE 8 /**< The longest block used by CMAC is that of 3DES. */ #endif +#if !defined(MBEDTLS_DEPRECATED_REMOVED) +/** The longest block supported by the cipher module. + * + * \deprecated + * For the maximum block size of a cipher supported by the CMAC module, + * use #MBEDTLS_CMAC_MAX_BLOCK_SIZE. + * For the maximum block size of a cipher supported by the cipher module, + * use #MBEDTLS_MAX_BLOCK_LENGTH. + */ +/* Before Mbed TLS 3.5, this was the maximum block size supported by the CMAC + * module, so it didn't take Camellia or ARIA into account. Since the name + * of the macro doesn't even convey "CMAC", this was misleading. Now the size + * is sufficient for any cipher, but the name is defined in cmac.h for + * backward compatibility. */ +#define MBEDTLS_CIPHER_BLKSIZE_MAX MBEDTLS_MAX_BLOCK_LENGTH +#endif /* MBEDTLS_DEPRECATED_REMOVED */ + #if !defined(MBEDTLS_CMAC_ALT) /** @@ -62,14 +58,14 @@ extern "C" { */ struct mbedtls_cmac_context_t { /** The internal state of the CMAC algorithm. */ - unsigned char state[MBEDTLS_CIPHER_BLKSIZE_MAX]; + unsigned char MBEDTLS_PRIVATE(state)[MBEDTLS_CMAC_MAX_BLOCK_SIZE]; /** Unprocessed data - either data that was not block aligned and is still * pending processing, or the final block. */ - unsigned char unprocessed_block[MBEDTLS_CIPHER_BLKSIZE_MAX]; + unsigned char MBEDTLS_PRIVATE(unprocessed_block)[MBEDTLS_CMAC_MAX_BLOCK_SIZE]; /** The length of data pending processing. */ - size_t unprocessed_len; + size_t MBEDTLS_PRIVATE(unprocessed_len); }; #else /* !MBEDTLS_CMAC_ALT */ diff --git a/vendor/mbedtls/include/mbedtls/compat-1.3.h b/vendor/mbedtls/include/mbedtls/compat-1.3.h deleted file mode 100644 index 117c88ae73..0000000000 --- a/vendor/mbedtls/include/mbedtls/compat-1.3.h +++ /dev/null @@ -1,2545 +0,0 @@ -/** - * \file compat-1.3.h - * - * \brief Compatibility definitions for using Mbed TLS with client code written - * for the PolarSSL naming conventions. - * - * \deprecated Use the new names directly instead - */ -/* - * Copyright The Mbed TLS Contributors - * SPDX-License-Identifier: Apache-2.0 - * - * Licensed under the Apache License, Version 2.0 (the "License"); you may - * not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT - * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -#if !defined(MBEDTLS_CONFIG_FILE) -#include "mbedtls/config.h" -#else -#include MBEDTLS_CONFIG_FILE -#endif - -#if !defined(MBEDTLS_DEPRECATED_REMOVED) - -#if defined(MBEDTLS_DEPRECATED_WARNING) -#warning "Including compat-1.3.h is deprecated" -#endif - -#ifndef MBEDTLS_COMPAT13_H -#define MBEDTLS_COMPAT13_H - -/* - * config.h options - */ -#if defined MBEDTLS_AESNI_C -#define POLARSSL_AESNI_C MBEDTLS_AESNI_C -#endif -#if defined MBEDTLS_AES_ALT -#define POLARSSL_AES_ALT MBEDTLS_AES_ALT -#endif -#if defined MBEDTLS_AES_C -#define POLARSSL_AES_C MBEDTLS_AES_C -#endif -#if defined MBEDTLS_AES_ROM_TABLES -#define POLARSSL_AES_ROM_TABLES MBEDTLS_AES_ROM_TABLES -#endif -#if defined MBEDTLS_ARC4_ALT -#define POLARSSL_ARC4_ALT MBEDTLS_ARC4_ALT -#endif -#if defined MBEDTLS_ARC4_C -#define POLARSSL_ARC4_C MBEDTLS_ARC4_C -#endif -#if defined MBEDTLS_ASN1_PARSE_C -#define POLARSSL_ASN1_PARSE_C MBEDTLS_ASN1_PARSE_C -#endif -#if defined MBEDTLS_ASN1_WRITE_C -#define POLARSSL_ASN1_WRITE_C MBEDTLS_ASN1_WRITE_C -#endif -#if defined MBEDTLS_BASE64_C -#define POLARSSL_BASE64_C MBEDTLS_BASE64_C -#endif -#if defined MBEDTLS_BIGNUM_C -#define POLARSSL_BIGNUM_C MBEDTLS_BIGNUM_C -#endif -#if defined MBEDTLS_BLOWFISH_ALT -#define POLARSSL_BLOWFISH_ALT MBEDTLS_BLOWFISH_ALT -#endif -#if defined MBEDTLS_BLOWFISH_C -#define POLARSSL_BLOWFISH_C MBEDTLS_BLOWFISH_C -#endif -#if defined MBEDTLS_CAMELLIA_ALT -#define POLARSSL_CAMELLIA_ALT MBEDTLS_CAMELLIA_ALT -#endif -#if defined MBEDTLS_CAMELLIA_C -#define POLARSSL_CAMELLIA_C MBEDTLS_CAMELLIA_C -#endif -#if defined MBEDTLS_CAMELLIA_SMALL_MEMORY -#define POLARSSL_CAMELLIA_SMALL_MEMORY MBEDTLS_CAMELLIA_SMALL_MEMORY -#endif -#if defined MBEDTLS_CCM_C -#define POLARSSL_CCM_C MBEDTLS_CCM_C -#endif -#if defined MBEDTLS_CERTS_C -#define POLARSSL_CERTS_C MBEDTLS_CERTS_C -#endif -#if defined MBEDTLS_CIPHER_C -#define POLARSSL_CIPHER_C MBEDTLS_CIPHER_C -#endif -#if defined MBEDTLS_CIPHER_MODE_CBC -#define POLARSSL_CIPHER_MODE_CBC MBEDTLS_CIPHER_MODE_CBC -#endif -#if defined MBEDTLS_CIPHER_MODE_CFB -#define POLARSSL_CIPHER_MODE_CFB MBEDTLS_CIPHER_MODE_CFB -#endif -#if defined MBEDTLS_CIPHER_MODE_CTR -#define POLARSSL_CIPHER_MODE_CTR MBEDTLS_CIPHER_MODE_CTR -#endif -#if defined MBEDTLS_CIPHER_NULL_CIPHER -#define POLARSSL_CIPHER_NULL_CIPHER MBEDTLS_CIPHER_NULL_CIPHER -#endif -#if defined MBEDTLS_CIPHER_PADDING_ONE_AND_ZEROS -#define POLARSSL_CIPHER_PADDING_ONE_AND_ZEROS MBEDTLS_CIPHER_PADDING_ONE_AND_ZEROS -#endif -#if defined MBEDTLS_CIPHER_PADDING_PKCS7 -#define POLARSSL_CIPHER_PADDING_PKCS7 MBEDTLS_CIPHER_PADDING_PKCS7 -#endif -#if defined MBEDTLS_CIPHER_PADDING_ZEROS -#define POLARSSL_CIPHER_PADDING_ZEROS MBEDTLS_CIPHER_PADDING_ZEROS -#endif -#if defined MBEDTLS_CIPHER_PADDING_ZEROS_AND_LEN -#define POLARSSL_CIPHER_PADDING_ZEROS_AND_LEN MBEDTLS_CIPHER_PADDING_ZEROS_AND_LEN -#endif -#if defined MBEDTLS_CTR_DRBG_C -#define POLARSSL_CTR_DRBG_C MBEDTLS_CTR_DRBG_C -#endif -#if defined MBEDTLS_DEBUG_C -#define POLARSSL_DEBUG_C MBEDTLS_DEBUG_C -#endif -#if defined MBEDTLS_DEPRECATED_REMOVED -#define POLARSSL_DEPRECATED_REMOVED MBEDTLS_DEPRECATED_REMOVED -#endif -#if defined MBEDTLS_DEPRECATED_WARNING -#define POLARSSL_DEPRECATED_WARNING MBEDTLS_DEPRECATED_WARNING -#endif -#if defined MBEDTLS_DES_ALT -#define POLARSSL_DES_ALT MBEDTLS_DES_ALT -#endif -#if defined MBEDTLS_DES_C -#define POLARSSL_DES_C MBEDTLS_DES_C -#endif -#if defined MBEDTLS_DHM_C -#define POLARSSL_DHM_C MBEDTLS_DHM_C -#endif -#if defined MBEDTLS_ECDH_C -#define POLARSSL_ECDH_C MBEDTLS_ECDH_C -#endif -#if defined MBEDTLS_ECDSA_C -#define POLARSSL_ECDSA_C MBEDTLS_ECDSA_C -#endif -#if defined MBEDTLS_ECDSA_DETERMINISTIC -#define POLARSSL_ECDSA_DETERMINISTIC MBEDTLS_ECDSA_DETERMINISTIC -#endif -#if defined MBEDTLS_ECP_C -#define POLARSSL_ECP_C MBEDTLS_ECP_C -#endif -#if defined MBEDTLS_ECP_DP_BP256R1_ENABLED -#define POLARSSL_ECP_DP_BP256R1_ENABLED MBEDTLS_ECP_DP_BP256R1_ENABLED -#endif -#if defined MBEDTLS_ECP_DP_BP384R1_ENABLED -#define POLARSSL_ECP_DP_BP384R1_ENABLED MBEDTLS_ECP_DP_BP384R1_ENABLED -#endif -#if defined MBEDTLS_ECP_DP_BP512R1_ENABLED -#define POLARSSL_ECP_DP_BP512R1_ENABLED MBEDTLS_ECP_DP_BP512R1_ENABLED -#endif -#if defined MBEDTLS_ECP_DP_CURVE25519_ENABLED -#define POLARSSL_ECP_DP_M255_ENABLED MBEDTLS_ECP_DP_CURVE25519_ENABLED -#endif -#if defined MBEDTLS_ECP_DP_SECP192K1_ENABLED -#define POLARSSL_ECP_DP_SECP192K1_ENABLED MBEDTLS_ECP_DP_SECP192K1_ENABLED -#endif -#if defined MBEDTLS_ECP_DP_SECP192R1_ENABLED -#define POLARSSL_ECP_DP_SECP192R1_ENABLED MBEDTLS_ECP_DP_SECP192R1_ENABLED -#endif -#if defined MBEDTLS_ECP_DP_SECP224K1_ENABLED -#define POLARSSL_ECP_DP_SECP224K1_ENABLED MBEDTLS_ECP_DP_SECP224K1_ENABLED -#endif -#if defined MBEDTLS_ECP_DP_SECP224R1_ENABLED -#define POLARSSL_ECP_DP_SECP224R1_ENABLED MBEDTLS_ECP_DP_SECP224R1_ENABLED -#endif -#if defined MBEDTLS_ECP_DP_SECP256K1_ENABLED -#define POLARSSL_ECP_DP_SECP256K1_ENABLED MBEDTLS_ECP_DP_SECP256K1_ENABLED -#endif -#if defined MBEDTLS_ECP_DP_SECP256R1_ENABLED -#define POLARSSL_ECP_DP_SECP256R1_ENABLED MBEDTLS_ECP_DP_SECP256R1_ENABLED -#endif -#if defined MBEDTLS_ECP_DP_SECP384R1_ENABLED -#define POLARSSL_ECP_DP_SECP384R1_ENABLED MBEDTLS_ECP_DP_SECP384R1_ENABLED -#endif -#if defined MBEDTLS_ECP_DP_SECP521R1_ENABLED -#define POLARSSL_ECP_DP_SECP521R1_ENABLED MBEDTLS_ECP_DP_SECP521R1_ENABLED -#endif -#if defined MBEDTLS_ECP_FIXED_POINT_OPTIM -#define POLARSSL_ECP_FIXED_POINT_OPTIM MBEDTLS_ECP_FIXED_POINT_OPTIM -#endif -#if defined MBEDTLS_ECP_MAX_BITS -#define POLARSSL_ECP_MAX_BITS MBEDTLS_ECP_MAX_BITS -#endif -#if defined MBEDTLS_ECP_NIST_OPTIM -#define POLARSSL_ECP_NIST_OPTIM MBEDTLS_ECP_NIST_OPTIM -#endif -#if defined MBEDTLS_ECP_WINDOW_SIZE -#define POLARSSL_ECP_WINDOW_SIZE MBEDTLS_ECP_WINDOW_SIZE -#endif -#if defined MBEDTLS_ENABLE_WEAK_CIPHERSUITES -#define POLARSSL_ENABLE_WEAK_CIPHERSUITES MBEDTLS_ENABLE_WEAK_CIPHERSUITES -#endif -#if defined MBEDTLS_ENTROPY_C -#define POLARSSL_ENTROPY_C MBEDTLS_ENTROPY_C -#endif -#if defined MBEDTLS_ENTROPY_FORCE_SHA256 -#define POLARSSL_ENTROPY_FORCE_SHA256 MBEDTLS_ENTROPY_FORCE_SHA256 -#endif -#if defined MBEDTLS_ERROR_C -#define POLARSSL_ERROR_C MBEDTLS_ERROR_C -#endif -#if defined MBEDTLS_ERROR_STRERROR_DUMMY -#define POLARSSL_ERROR_STRERROR_DUMMY MBEDTLS_ERROR_STRERROR_DUMMY -#endif -#if defined MBEDTLS_FS_IO -#define POLARSSL_FS_IO MBEDTLS_FS_IO -#endif -#if defined MBEDTLS_GCM_C -#define POLARSSL_GCM_C MBEDTLS_GCM_C -#endif -#if defined MBEDTLS_GENPRIME -#define POLARSSL_GENPRIME MBEDTLS_GENPRIME -#endif -#if defined MBEDTLS_HAVEGE_C -#define POLARSSL_HAVEGE_C MBEDTLS_HAVEGE_C -#endif -#if defined MBEDTLS_HAVE_ASM -#define POLARSSL_HAVE_ASM MBEDTLS_HAVE_ASM -#endif -#if defined MBEDTLS_HAVE_SSE2 -#define POLARSSL_HAVE_SSE2 MBEDTLS_HAVE_SSE2 -#endif -#if defined MBEDTLS_HAVE_TIME -#define POLARSSL_HAVE_TIME MBEDTLS_HAVE_TIME -#endif -#if defined MBEDTLS_HMAC_DRBG_C -#define POLARSSL_HMAC_DRBG_C MBEDTLS_HMAC_DRBG_C -#endif -#if defined MBEDTLS_HMAC_DRBG_MAX_INPUT -#define POLARSSL_HMAC_DRBG_MAX_INPUT MBEDTLS_HMAC_DRBG_MAX_INPUT -#endif -#if defined MBEDTLS_HMAC_DRBG_MAX_REQUEST -#define POLARSSL_HMAC_DRBG_MAX_REQUEST MBEDTLS_HMAC_DRBG_MAX_REQUEST -#endif -#if defined MBEDTLS_HMAC_DRBG_MAX_SEED_INPUT -#define POLARSSL_HMAC_DRBG_MAX_SEED_INPUT MBEDTLS_HMAC_DRBG_MAX_SEED_INPUT -#endif -#if defined MBEDTLS_HMAC_DRBG_RESEED_INTERVAL -#define POLARSSL_HMAC_DRBG_RESEED_INTERVAL MBEDTLS_HMAC_DRBG_RESEED_INTERVAL -#endif -#if defined MBEDTLS_KEY_EXCHANGE_DHE_PSK_ENABLED -#define POLARSSL_KEY_EXCHANGE_DHE_PSK_ENABLED MBEDTLS_KEY_EXCHANGE_DHE_PSK_ENABLED -#endif -#if defined MBEDTLS_KEY_EXCHANGE_DHE_RSA_ENABLED -#define POLARSSL_KEY_EXCHANGE_DHE_RSA_ENABLED MBEDTLS_KEY_EXCHANGE_DHE_RSA_ENABLED -#endif -#if defined MBEDTLS_KEY_EXCHANGE_ECDHE_ECDSA_ENABLED -#define POLARSSL_KEY_EXCHANGE_ECDHE_ECDSA_ENABLED MBEDTLS_KEY_EXCHANGE_ECDHE_ECDSA_ENABLED -#endif -#if defined MBEDTLS_KEY_EXCHANGE_ECDHE_PSK_ENABLED -#define POLARSSL_KEY_EXCHANGE_ECDHE_PSK_ENABLED MBEDTLS_KEY_EXCHANGE_ECDHE_PSK_ENABLED -#endif -#if defined MBEDTLS_KEY_EXCHANGE_ECDHE_RSA_ENABLED -#define POLARSSL_KEY_EXCHANGE_ECDHE_RSA_ENABLED MBEDTLS_KEY_EXCHANGE_ECDHE_RSA_ENABLED -#endif -#if defined MBEDTLS_KEY_EXCHANGE_ECDH_ECDSA_ENABLED -#define POLARSSL_KEY_EXCHANGE_ECDH_ECDSA_ENABLED MBEDTLS_KEY_EXCHANGE_ECDH_ECDSA_ENABLED -#endif -#if defined MBEDTLS_KEY_EXCHANGE_ECDH_RSA_ENABLED -#define POLARSSL_KEY_EXCHANGE_ECDH_RSA_ENABLED MBEDTLS_KEY_EXCHANGE_ECDH_RSA_ENABLED -#endif -#if defined MBEDTLS_KEY_EXCHANGE_PSK_ENABLED -#define POLARSSL_KEY_EXCHANGE_PSK_ENABLED MBEDTLS_KEY_EXCHANGE_PSK_ENABLED -#endif -#if defined MBEDTLS_KEY_EXCHANGE_RSA_ENABLED -#define POLARSSL_KEY_EXCHANGE_RSA_ENABLED MBEDTLS_KEY_EXCHANGE_RSA_ENABLED -#endif -#if defined MBEDTLS_KEY_EXCHANGE_RSA_PSK_ENABLED -#define POLARSSL_KEY_EXCHANGE_RSA_PSK_ENABLED MBEDTLS_KEY_EXCHANGE_RSA_PSK_ENABLED -#endif -#if defined MBEDTLS_MD2_ALT -#define POLARSSL_MD2_ALT MBEDTLS_MD2_ALT -#endif -#if defined MBEDTLS_MD2_C -#define POLARSSL_MD2_C MBEDTLS_MD2_C -#endif -#if defined MBEDTLS_MD2_PROCESS_ALT -#define POLARSSL_MD2_PROCESS_ALT MBEDTLS_MD2_PROCESS_ALT -#endif -#if defined MBEDTLS_MD4_ALT -#define POLARSSL_MD4_ALT MBEDTLS_MD4_ALT -#endif -#if defined MBEDTLS_MD4_C -#define POLARSSL_MD4_C MBEDTLS_MD4_C -#endif -#if defined MBEDTLS_MD4_PROCESS_ALT -#define POLARSSL_MD4_PROCESS_ALT MBEDTLS_MD4_PROCESS_ALT -#endif -#if defined MBEDTLS_MD5_ALT -#define POLARSSL_MD5_ALT MBEDTLS_MD5_ALT -#endif -#if defined MBEDTLS_MD5_C -#define POLARSSL_MD5_C MBEDTLS_MD5_C -#endif -#if defined MBEDTLS_MD5_PROCESS_ALT -#define POLARSSL_MD5_PROCESS_ALT MBEDTLS_MD5_PROCESS_ALT -#endif -#if defined MBEDTLS_MD_C -#define POLARSSL_MD_C MBEDTLS_MD_C -#endif -#if defined MBEDTLS_MEMORY_ALIGN_MULTIPLE -#define POLARSSL_MEMORY_ALIGN_MULTIPLE MBEDTLS_MEMORY_ALIGN_MULTIPLE -#endif -#if defined MBEDTLS_MEMORY_BACKTRACE -#define POLARSSL_MEMORY_BACKTRACE MBEDTLS_MEMORY_BACKTRACE -#endif -#if defined MBEDTLS_MEMORY_BUFFER_ALLOC_C -#define POLARSSL_MEMORY_BUFFER_ALLOC_C MBEDTLS_MEMORY_BUFFER_ALLOC_C -#endif -#if defined MBEDTLS_MEMORY_DEBUG -#define POLARSSL_MEMORY_DEBUG MBEDTLS_MEMORY_DEBUG -#endif -#if defined MBEDTLS_MPI_MAX_SIZE -#define POLARSSL_MPI_MAX_SIZE MBEDTLS_MPI_MAX_SIZE -#endif -#if defined MBEDTLS_MPI_WINDOW_SIZE -#define POLARSSL_MPI_WINDOW_SIZE MBEDTLS_MPI_WINDOW_SIZE -#endif -#if defined MBEDTLS_NET_C -#define POLARSSL_NET_C MBEDTLS_NET_C -#endif -#if defined MBEDTLS_NO_DEFAULT_ENTROPY_SOURCES -#define POLARSSL_NO_DEFAULT_ENTROPY_SOURCES MBEDTLS_NO_DEFAULT_ENTROPY_SOURCES -#endif -#if defined MBEDTLS_NO_PLATFORM_ENTROPY -#define POLARSSL_NO_PLATFORM_ENTROPY MBEDTLS_NO_PLATFORM_ENTROPY -#endif -#if defined MBEDTLS_OID_C -#define POLARSSL_OID_C MBEDTLS_OID_C -#endif -#if defined MBEDTLS_PADLOCK_C -#define POLARSSL_PADLOCK_C MBEDTLS_PADLOCK_C -#endif -#if defined MBEDTLS_PEM_PARSE_C -#define POLARSSL_PEM_PARSE_C MBEDTLS_PEM_PARSE_C -#endif -#if defined MBEDTLS_PEM_WRITE_C -#define POLARSSL_PEM_WRITE_C MBEDTLS_PEM_WRITE_C -#endif -#if defined MBEDTLS_PKCS11_C -#define POLARSSL_PKCS11_C MBEDTLS_PKCS11_C -#endif -#if defined MBEDTLS_PKCS12_C -#define POLARSSL_PKCS12_C MBEDTLS_PKCS12_C -#endif -#if defined MBEDTLS_PKCS1_V15 -#define POLARSSL_PKCS1_V15 MBEDTLS_PKCS1_V15 -#endif -#if defined MBEDTLS_PKCS1_V21 -#define POLARSSL_PKCS1_V21 MBEDTLS_PKCS1_V21 -#endif -#if defined MBEDTLS_PKCS5_C -#define POLARSSL_PKCS5_C MBEDTLS_PKCS5_C -#endif -#if defined MBEDTLS_PK_C -#define POLARSSL_PK_C MBEDTLS_PK_C -#endif -#if defined MBEDTLS_PK_PARSE_C -#define POLARSSL_PK_PARSE_C MBEDTLS_PK_PARSE_C -#endif -#if defined MBEDTLS_PK_PARSE_EC_EXTENDED -#define POLARSSL_PK_PARSE_EC_EXTENDED MBEDTLS_PK_PARSE_EC_EXTENDED -#endif -#if defined MBEDTLS_PK_RSA_ALT_SUPPORT -#define POLARSSL_PK_RSA_ALT_SUPPORT MBEDTLS_PK_RSA_ALT_SUPPORT -#endif -#if defined MBEDTLS_PK_WRITE_C -#define POLARSSL_PK_WRITE_C MBEDTLS_PK_WRITE_C -#endif -#if defined MBEDTLS_PLATFORM_C -#define POLARSSL_PLATFORM_C MBEDTLS_PLATFORM_C -#endif -#if defined MBEDTLS_PLATFORM_EXIT_ALT -#define POLARSSL_PLATFORM_EXIT_ALT MBEDTLS_PLATFORM_EXIT_ALT -#endif -#if defined MBEDTLS_PLATFORM_EXIT_MACRO -#define POLARSSL_PLATFORM_EXIT_MACRO MBEDTLS_PLATFORM_EXIT_MACRO -#endif -#if defined MBEDTLS_PLATFORM_FPRINTF_ALT -#define POLARSSL_PLATFORM_FPRINTF_ALT MBEDTLS_PLATFORM_FPRINTF_ALT -#endif -#if defined MBEDTLS_PLATFORM_FPRINTF_MACRO -#define POLARSSL_PLATFORM_FPRINTF_MACRO MBEDTLS_PLATFORM_FPRINTF_MACRO -#endif -#if defined MBEDTLS_PLATFORM_FREE_MACRO -#define POLARSSL_PLATFORM_FREE_MACRO MBEDTLS_PLATFORM_FREE_MACRO -#endif -#if defined MBEDTLS_PLATFORM_MEMORY -#define POLARSSL_PLATFORM_MEMORY MBEDTLS_PLATFORM_MEMORY -#endif -#if defined MBEDTLS_PLATFORM_NO_STD_FUNCTIONS -#define POLARSSL_PLATFORM_NO_STD_FUNCTIONS MBEDTLS_PLATFORM_NO_STD_FUNCTIONS -#endif -#if defined MBEDTLS_PLATFORM_PRINTF_ALT -#define POLARSSL_PLATFORM_PRINTF_ALT MBEDTLS_PLATFORM_PRINTF_ALT -#endif -#if defined MBEDTLS_PLATFORM_PRINTF_MACRO -#define POLARSSL_PLATFORM_PRINTF_MACRO MBEDTLS_PLATFORM_PRINTF_MACRO -#endif -#if defined MBEDTLS_PLATFORM_SNPRINTF_ALT -#define POLARSSL_PLATFORM_SNPRINTF_ALT MBEDTLS_PLATFORM_SNPRINTF_ALT -#endif -#if defined MBEDTLS_PLATFORM_SNPRINTF_MACRO -#define POLARSSL_PLATFORM_SNPRINTF_MACRO MBEDTLS_PLATFORM_SNPRINTF_MACRO -#endif -#if defined MBEDTLS_PLATFORM_STD_EXIT -#define POLARSSL_PLATFORM_STD_EXIT MBEDTLS_PLATFORM_STD_EXIT -#endif -#if defined MBEDTLS_PLATFORM_STD_FPRINTF -#define POLARSSL_PLATFORM_STD_FPRINTF MBEDTLS_PLATFORM_STD_FPRINTF -#endif -#if defined MBEDTLS_PLATFORM_STD_FREE -#define POLARSSL_PLATFORM_STD_FREE MBEDTLS_PLATFORM_STD_FREE -#endif -#if defined MBEDTLS_PLATFORM_STD_MEM_HDR -#define POLARSSL_PLATFORM_STD_MEM_HDR MBEDTLS_PLATFORM_STD_MEM_HDR -#endif -#if defined MBEDTLS_PLATFORM_STD_PRINTF -#define POLARSSL_PLATFORM_STD_PRINTF MBEDTLS_PLATFORM_STD_PRINTF -#endif -#if defined MBEDTLS_PLATFORM_STD_SNPRINTF -#define POLARSSL_PLATFORM_STD_SNPRINTF MBEDTLS_PLATFORM_STD_SNPRINTF -#endif -#if defined MBEDTLS_PSK_MAX_LEN -#define POLARSSL_PSK_MAX_LEN MBEDTLS_PSK_MAX_LEN -#endif -#if defined MBEDTLS_REMOVE_ARC4_CIPHERSUITES -#define POLARSSL_REMOVE_ARC4_CIPHERSUITES MBEDTLS_REMOVE_ARC4_CIPHERSUITES -#endif -#if defined MBEDTLS_RIPEMD160_ALT -#define POLARSSL_RIPEMD160_ALT MBEDTLS_RIPEMD160_ALT -#endif -#if defined MBEDTLS_RIPEMD160_C -#define POLARSSL_RIPEMD160_C MBEDTLS_RIPEMD160_C -#endif -#if defined MBEDTLS_RIPEMD160_PROCESS_ALT -#define POLARSSL_RIPEMD160_PROCESS_ALT MBEDTLS_RIPEMD160_PROCESS_ALT -#endif -#if defined MBEDTLS_RSA_C -#define POLARSSL_RSA_C MBEDTLS_RSA_C -#endif -#if defined MBEDTLS_RSA_NO_CRT -#define POLARSSL_RSA_NO_CRT MBEDTLS_RSA_NO_CRT -#endif -#if defined MBEDTLS_SELF_TEST -#define POLARSSL_SELF_TEST MBEDTLS_SELF_TEST -#endif -#if defined MBEDTLS_SHA1_ALT -#define POLARSSL_SHA1_ALT MBEDTLS_SHA1_ALT -#endif -#if defined MBEDTLS_SHA1_C -#define POLARSSL_SHA1_C MBEDTLS_SHA1_C -#endif -#if defined MBEDTLS_SHA1_PROCESS_ALT -#define POLARSSL_SHA1_PROCESS_ALT MBEDTLS_SHA1_PROCESS_ALT -#endif -#if defined MBEDTLS_SHA256_ALT -#define POLARSSL_SHA256_ALT MBEDTLS_SHA256_ALT -#endif -#if defined MBEDTLS_SHA256_C -#define POLARSSL_SHA256_C MBEDTLS_SHA256_C -#endif -#if defined MBEDTLS_SHA256_PROCESS_ALT -#define POLARSSL_SHA256_PROCESS_ALT MBEDTLS_SHA256_PROCESS_ALT -#endif -#if defined MBEDTLS_SHA512_ALT -#define POLARSSL_SHA512_ALT MBEDTLS_SHA512_ALT -#endif -#if defined MBEDTLS_SHA512_C -#define POLARSSL_SHA512_C MBEDTLS_SHA512_C -#endif -#if defined MBEDTLS_SHA512_PROCESS_ALT -#define POLARSSL_SHA512_PROCESS_ALT MBEDTLS_SHA512_PROCESS_ALT -#endif -#if defined MBEDTLS_SSL_ALL_ALERT_MESSAGES -#define POLARSSL_SSL_ALL_ALERT_MESSAGES MBEDTLS_SSL_ALL_ALERT_MESSAGES -#endif -#if defined MBEDTLS_SSL_ALPN -#define POLARSSL_SSL_ALPN MBEDTLS_SSL_ALPN -#endif -#if defined MBEDTLS_SSL_CACHE_C -#define POLARSSL_SSL_CACHE_C MBEDTLS_SSL_CACHE_C -#endif -#if defined MBEDTLS_SSL_CBC_RECORD_SPLITTING -#define POLARSSL_SSL_CBC_RECORD_SPLITTING MBEDTLS_SSL_CBC_RECORD_SPLITTING -#endif -#if defined MBEDTLS_SSL_CLI_C -#define POLARSSL_SSL_CLI_C MBEDTLS_SSL_CLI_C -#endif -#if defined MBEDTLS_SSL_COOKIE_C -#define POLARSSL_SSL_COOKIE_C MBEDTLS_SSL_COOKIE_C -#endif -#if defined MBEDTLS_SSL_COOKIE_TIMEOUT -#define POLARSSL_SSL_COOKIE_TIMEOUT MBEDTLS_SSL_COOKIE_TIMEOUT -#endif -#if defined MBEDTLS_SSL_DEBUG_ALL -#define POLARSSL_SSL_DEBUG_ALL MBEDTLS_SSL_DEBUG_ALL -#endif -#if defined MBEDTLS_SSL_DTLS_ANTI_REPLAY -#define POLARSSL_SSL_DTLS_ANTI_REPLAY MBEDTLS_SSL_DTLS_ANTI_REPLAY -#endif -#if defined MBEDTLS_SSL_DTLS_BADMAC_LIMIT -#define POLARSSL_SSL_DTLS_BADMAC_LIMIT MBEDTLS_SSL_DTLS_BADMAC_LIMIT -#endif -#if defined MBEDTLS_SSL_DTLS_HELLO_VERIFY -#define POLARSSL_SSL_DTLS_HELLO_VERIFY MBEDTLS_SSL_DTLS_HELLO_VERIFY -#endif -#if defined MBEDTLS_SSL_ENCRYPT_THEN_MAC -#define POLARSSL_SSL_ENCRYPT_THEN_MAC MBEDTLS_SSL_ENCRYPT_THEN_MAC -#endif -#if defined MBEDTLS_SSL_EXTENDED_MASTER_SECRET -#define POLARSSL_SSL_EXTENDED_MASTER_SECRET MBEDTLS_SSL_EXTENDED_MASTER_SECRET -#endif -#if defined MBEDTLS_SSL_FALLBACK_SCSV -#define POLARSSL_SSL_FALLBACK_SCSV MBEDTLS_SSL_FALLBACK_SCSV -#endif -#if defined MBEDTLS_SSL_HW_RECORD_ACCEL -#define POLARSSL_SSL_HW_RECORD_ACCEL MBEDTLS_SSL_HW_RECORD_ACCEL -#endif -#if defined MBEDTLS_SSL_MAX_FRAGMENT_LENGTH -#define POLARSSL_SSL_MAX_FRAGMENT_LENGTH MBEDTLS_SSL_MAX_FRAGMENT_LENGTH -#endif -#if defined MBEDTLS_SSL_PROTO_DTLS -#define POLARSSL_SSL_PROTO_DTLS MBEDTLS_SSL_PROTO_DTLS -#endif -#if defined MBEDTLS_SSL_PROTO_SSL3 -#define POLARSSL_SSL_PROTO_SSL3 MBEDTLS_SSL_PROTO_SSL3 -#endif -#if defined MBEDTLS_SSL_PROTO_TLS1 -#define POLARSSL_SSL_PROTO_TLS1 MBEDTLS_SSL_PROTO_TLS1 -#endif -#if defined MBEDTLS_SSL_PROTO_TLS1_1 -#define POLARSSL_SSL_PROTO_TLS1_1 MBEDTLS_SSL_PROTO_TLS1_1 -#endif -#if defined MBEDTLS_SSL_PROTO_TLS1_2 -#define POLARSSL_SSL_PROTO_TLS1_2 MBEDTLS_SSL_PROTO_TLS1_2 -#endif -#if defined MBEDTLS_SSL_RENEGOTIATION -#define POLARSSL_SSL_RENEGOTIATION MBEDTLS_SSL_RENEGOTIATION -#endif -#if defined MBEDTLS_SSL_SERVER_NAME_INDICATION -#define POLARSSL_SSL_SERVER_NAME_INDICATION MBEDTLS_SSL_SERVER_NAME_INDICATION -#endif -#if defined MBEDTLS_SSL_SESSION_TICKETS -#define POLARSSL_SSL_SESSION_TICKETS MBEDTLS_SSL_SESSION_TICKETS -#endif -#if defined MBEDTLS_SSL_SRV_C -#define POLARSSL_SSL_SRV_C MBEDTLS_SSL_SRV_C -#endif -#if defined MBEDTLS_SSL_SRV_RESPECT_CLIENT_PREFERENCE -#define POLARSSL_SSL_SRV_RESPECT_CLIENT_PREFERENCE MBEDTLS_SSL_SRV_RESPECT_CLIENT_PREFERENCE -#endif -#if defined MBEDTLS_SSL_SRV_SUPPORT_SSLV2_CLIENT_HELLO -#define POLARSSL_SSL_SRV_SUPPORT_SSLV2_CLIENT_HELLO MBEDTLS_SSL_SRV_SUPPORT_SSLV2_CLIENT_HELLO -#endif -#if defined MBEDTLS_SSL_TLS_C -#define POLARSSL_SSL_TLS_C MBEDTLS_SSL_TLS_C -#endif -#if defined MBEDTLS_SSL_TRUNCATED_HMAC -#define POLARSSL_SSL_TRUNCATED_HMAC MBEDTLS_SSL_TRUNCATED_HMAC -#endif -#if defined MBEDTLS_THREADING_ALT -#define POLARSSL_THREADING_ALT MBEDTLS_THREADING_ALT -#endif -#if defined MBEDTLS_THREADING_C -#define POLARSSL_THREADING_C MBEDTLS_THREADING_C -#endif -#if defined MBEDTLS_THREADING_PTHREAD -#define POLARSSL_THREADING_PTHREAD MBEDTLS_THREADING_PTHREAD -#endif -#if defined MBEDTLS_TIMING_ALT -#define POLARSSL_TIMING_ALT MBEDTLS_TIMING_ALT -#endif -#if defined MBEDTLS_TIMING_C -#define POLARSSL_TIMING_C MBEDTLS_TIMING_C -#endif -#if defined MBEDTLS_VERSION_C -#define POLARSSL_VERSION_C MBEDTLS_VERSION_C -#endif -#if defined MBEDTLS_VERSION_FEATURES -#define POLARSSL_VERSION_FEATURES MBEDTLS_VERSION_FEATURES -#endif -#if defined MBEDTLS_X509_ALLOW_EXTENSIONS_NON_V3 -#define POLARSSL_X509_ALLOW_EXTENSIONS_NON_V3 MBEDTLS_X509_ALLOW_EXTENSIONS_NON_V3 -#endif -#if defined MBEDTLS_X509_ALLOW_UNSUPPORTED_CRITICAL_EXTENSION -#define POLARSSL_X509_ALLOW_UNSUPPORTED_CRITICAL_EXTENSION \ - MBEDTLS_X509_ALLOW_UNSUPPORTED_CRITICAL_EXTENSION -#endif -#if defined MBEDTLS_X509_CHECK_EXTENDED_KEY_USAGE -#define POLARSSL_X509_CHECK_EXTENDED_KEY_USAGE MBEDTLS_X509_CHECK_EXTENDED_KEY_USAGE -#endif -#if defined MBEDTLS_X509_CHECK_KEY_USAGE -#define POLARSSL_X509_CHECK_KEY_USAGE MBEDTLS_X509_CHECK_KEY_USAGE -#endif -#if defined MBEDTLS_X509_CREATE_C -#define POLARSSL_X509_CREATE_C MBEDTLS_X509_CREATE_C -#endif -#if defined MBEDTLS_X509_CRL_PARSE_C -#define POLARSSL_X509_CRL_PARSE_C MBEDTLS_X509_CRL_PARSE_C -#endif -#if defined MBEDTLS_X509_CRT_PARSE_C -#define POLARSSL_X509_CRT_PARSE_C MBEDTLS_X509_CRT_PARSE_C -#endif -#if defined MBEDTLS_X509_CRT_WRITE_C -#define POLARSSL_X509_CRT_WRITE_C MBEDTLS_X509_CRT_WRITE_C -#endif -#if defined MBEDTLS_X509_CSR_PARSE_C -#define POLARSSL_X509_CSR_PARSE_C MBEDTLS_X509_CSR_PARSE_C -#endif -#if defined MBEDTLS_X509_CSR_WRITE_C -#define POLARSSL_X509_CSR_WRITE_C MBEDTLS_X509_CSR_WRITE_C -#endif -#if defined MBEDTLS_X509_MAX_INTERMEDIATE_CA -#define POLARSSL_X509_MAX_INTERMEDIATE_CA MBEDTLS_X509_MAX_INTERMEDIATE_CA -#endif -#if defined MBEDTLS_X509_RSASSA_PSS_SUPPORT -#define POLARSSL_X509_RSASSA_PSS_SUPPORT MBEDTLS_X509_RSASSA_PSS_SUPPORT -#endif -#if defined MBEDTLS_X509_USE_C -#define POLARSSL_X509_USE_C MBEDTLS_X509_USE_C -#endif -#if defined MBEDTLS_XTEA_ALT -#define POLARSSL_XTEA_ALT MBEDTLS_XTEA_ALT -#endif -#if defined MBEDTLS_XTEA_C -#define POLARSSL_XTEA_C MBEDTLS_XTEA_C -#endif -#if defined MBEDTLS_ZLIB_SUPPORT -#define POLARSSL_ZLIB_SUPPORT MBEDTLS_ZLIB_SUPPORT -#endif - -/* - * Misc names (macros, types, functions, enum constants...) - */ -#define AES_DECRYPT MBEDTLS_AES_DECRYPT -#define AES_ENCRYPT MBEDTLS_AES_ENCRYPT -#define ASN1_BIT_STRING MBEDTLS_ASN1_BIT_STRING -#define ASN1_BMP_STRING MBEDTLS_ASN1_BMP_STRING -#define ASN1_BOOLEAN MBEDTLS_ASN1_BOOLEAN -#define ASN1_CHK_ADD MBEDTLS_ASN1_CHK_ADD -#define ASN1_CONSTRUCTED MBEDTLS_ASN1_CONSTRUCTED -#define ASN1_CONTEXT_SPECIFIC MBEDTLS_ASN1_CONTEXT_SPECIFIC -#define ASN1_GENERALIZED_TIME MBEDTLS_ASN1_GENERALIZED_TIME -#define ASN1_IA5_STRING MBEDTLS_ASN1_IA5_STRING -#define ASN1_INTEGER MBEDTLS_ASN1_INTEGER -#define ASN1_NULL MBEDTLS_ASN1_NULL -#define ASN1_OCTET_STRING MBEDTLS_ASN1_OCTET_STRING -#define ASN1_OID MBEDTLS_ASN1_OID -#define ASN1_PRIMITIVE MBEDTLS_ASN1_PRIMITIVE -#define ASN1_PRINTABLE_STRING MBEDTLS_ASN1_PRINTABLE_STRING -#define ASN1_SEQUENCE MBEDTLS_ASN1_SEQUENCE -#define ASN1_SET MBEDTLS_ASN1_SET -#define ASN1_T61_STRING MBEDTLS_ASN1_T61_STRING -#define ASN1_UNIVERSAL_STRING MBEDTLS_ASN1_UNIVERSAL_STRING -#define ASN1_UTC_TIME MBEDTLS_ASN1_UTC_TIME -#define ASN1_UTF8_STRING MBEDTLS_ASN1_UTF8_STRING -#define BADCERT_CN_MISMATCH MBEDTLS_X509_BADCERT_CN_MISMATCH -#define BADCERT_EXPIRED MBEDTLS_X509_BADCERT_EXPIRED -#define BADCERT_FUTURE MBEDTLS_X509_BADCERT_FUTURE -#define BADCERT_MISSING MBEDTLS_X509_BADCERT_MISSING -#define BADCERT_NOT_TRUSTED MBEDTLS_X509_BADCERT_NOT_TRUSTED -#define BADCERT_OTHER MBEDTLS_X509_BADCERT_OTHER -#define BADCERT_REVOKED MBEDTLS_X509_BADCERT_REVOKED -#define BADCERT_SKIP_VERIFY MBEDTLS_X509_BADCERT_SKIP_VERIFY -#define BADCRL_EXPIRED MBEDTLS_X509_BADCRL_EXPIRED -#define BADCRL_FUTURE MBEDTLS_X509_BADCRL_FUTURE -#define BADCRL_NOT_TRUSTED MBEDTLS_X509_BADCRL_NOT_TRUSTED -#define BLOWFISH_BLOCKSIZE MBEDTLS_BLOWFISH_BLOCKSIZE -#define BLOWFISH_DECRYPT MBEDTLS_BLOWFISH_DECRYPT -#define BLOWFISH_ENCRYPT MBEDTLS_BLOWFISH_ENCRYPT -#define BLOWFISH_MAX_KEY MBEDTLS_BLOWFISH_MAX_KEY_BITS -#define BLOWFISH_MIN_KEY MBEDTLS_BLOWFISH_MIN_KEY_BITS -#define BLOWFISH_ROUNDS MBEDTLS_BLOWFISH_ROUNDS -#define CAMELLIA_DECRYPT MBEDTLS_CAMELLIA_DECRYPT -#define CAMELLIA_ENCRYPT MBEDTLS_CAMELLIA_ENCRYPT -#define COLLECT_SIZE MBEDTLS_HAVEGE_COLLECT_SIZE -#define CTR_DRBG_BLOCKSIZE MBEDTLS_CTR_DRBG_BLOCKSIZE -#define CTR_DRBG_ENTROPY_LEN MBEDTLS_CTR_DRBG_ENTROPY_LEN -#define CTR_DRBG_KEYBITS MBEDTLS_CTR_DRBG_KEYBITS -#define CTR_DRBG_KEYSIZE MBEDTLS_CTR_DRBG_KEYSIZE -#define CTR_DRBG_MAX_INPUT MBEDTLS_CTR_DRBG_MAX_INPUT -#define CTR_DRBG_MAX_REQUEST MBEDTLS_CTR_DRBG_MAX_REQUEST -#define CTR_DRBG_MAX_SEED_INPUT MBEDTLS_CTR_DRBG_MAX_SEED_INPUT -#define CTR_DRBG_PR_OFF MBEDTLS_CTR_DRBG_PR_OFF -#define CTR_DRBG_PR_ON MBEDTLS_CTR_DRBG_PR_ON -#define CTR_DRBG_RESEED_INTERVAL MBEDTLS_CTR_DRBG_RESEED_INTERVAL -#define CTR_DRBG_SEEDLEN MBEDTLS_CTR_DRBG_SEEDLEN -#define DEPRECATED MBEDTLS_DEPRECATED -#define DES_DECRYPT MBEDTLS_DES_DECRYPT -#define DES_ENCRYPT MBEDTLS_DES_ENCRYPT -#define DES_KEY_SIZE MBEDTLS_DES_KEY_SIZE -#define ENTROPY_BLOCK_SIZE MBEDTLS_ENTROPY_BLOCK_SIZE -#define ENTROPY_MAX_GATHER MBEDTLS_ENTROPY_MAX_GATHER -#define ENTROPY_MAX_SEED_SIZE MBEDTLS_ENTROPY_MAX_SEED_SIZE -#define ENTROPY_MAX_SOURCES MBEDTLS_ENTROPY_MAX_SOURCES -#define ENTROPY_MIN_HARDCLOCK MBEDTLS_ENTROPY_MIN_HARDCLOCK -#define ENTROPY_MIN_HAVEGE MBEDTLS_ENTROPY_MIN_HAVEGE -#define ENTROPY_MIN_PLATFORM MBEDTLS_ENTROPY_MIN_PLATFORM -#define ENTROPY_SOURCE_MANUAL MBEDTLS_ENTROPY_SOURCE_MANUAL -#define EXT_AUTHORITY_KEY_IDENTIFIER MBEDTLS_X509_EXT_AUTHORITY_KEY_IDENTIFIER -#define EXT_BASIC_CONSTRAINTS MBEDTLS_X509_EXT_BASIC_CONSTRAINTS -#define EXT_CERTIFICATE_POLICIES MBEDTLS_X509_EXT_CERTIFICATE_POLICIES -#define EXT_CRL_DISTRIBUTION_POINTS MBEDTLS_X509_EXT_CRL_DISTRIBUTION_POINTS -#define EXT_EXTENDED_KEY_USAGE MBEDTLS_X509_EXT_EXTENDED_KEY_USAGE -#define EXT_FRESHEST_CRL MBEDTLS_X509_EXT_FRESHEST_CRL -#define EXT_INIHIBIT_ANYPOLICY MBEDTLS_X509_EXT_INIHIBIT_ANYPOLICY -#define EXT_ISSUER_ALT_NAME MBEDTLS_X509_EXT_ISSUER_ALT_NAME -#define EXT_KEY_USAGE MBEDTLS_X509_EXT_KEY_USAGE -#define EXT_NAME_CONSTRAINTS MBEDTLS_X509_EXT_NAME_CONSTRAINTS -#define EXT_NS_CERT_TYPE MBEDTLS_X509_EXT_NS_CERT_TYPE -#define EXT_POLICY_CONSTRAINTS MBEDTLS_X509_EXT_POLICY_CONSTRAINTS -#define EXT_POLICY_MAPPINGS MBEDTLS_X509_EXT_POLICY_MAPPINGS -#define EXT_SUBJECT_ALT_NAME MBEDTLS_X509_EXT_SUBJECT_ALT_NAME -#define EXT_SUBJECT_DIRECTORY_ATTRS MBEDTLS_X509_EXT_SUBJECT_DIRECTORY_ATTRS -#define EXT_SUBJECT_KEY_IDENTIFIER MBEDTLS_X509_EXT_SUBJECT_KEY_IDENTIFIER -#define GCM_DECRYPT MBEDTLS_GCM_DECRYPT -#define GCM_ENCRYPT MBEDTLS_GCM_ENCRYPT -#define KU_CRL_SIGN MBEDTLS_X509_KU_CRL_SIGN -#define KU_DATA_ENCIPHERMENT MBEDTLS_X509_KU_DATA_ENCIPHERMENT -#define KU_DIGITAL_SIGNATURE MBEDTLS_X509_KU_DIGITAL_SIGNATURE -#define KU_KEY_AGREEMENT MBEDTLS_X509_KU_KEY_AGREEMENT -#define KU_KEY_CERT_SIGN MBEDTLS_X509_KU_KEY_CERT_SIGN -#define KU_KEY_ENCIPHERMENT MBEDTLS_X509_KU_KEY_ENCIPHERMENT -#define KU_NON_REPUDIATION MBEDTLS_X509_KU_NON_REPUDIATION -#define LN_2_DIV_LN_10_SCALE100 MBEDTLS_LN_2_DIV_LN_10_SCALE100 -#define MEMORY_VERIFY_ALLOC MBEDTLS_MEMORY_VERIFY_ALLOC -#define MEMORY_VERIFY_ALWAYS MBEDTLS_MEMORY_VERIFY_ALWAYS -#define MEMORY_VERIFY_FREE MBEDTLS_MEMORY_VERIFY_FREE -#define MEMORY_VERIFY_NONE MBEDTLS_MEMORY_VERIFY_NONE -#define MPI_CHK MBEDTLS_MPI_CHK -#define NET_PROTO_TCP MBEDTLS_NET_PROTO_TCP -#define NET_PROTO_UDP MBEDTLS_NET_PROTO_UDP -#define NS_CERT_TYPE_EMAIL MBEDTLS_X509_NS_CERT_TYPE_EMAIL -#define NS_CERT_TYPE_EMAIL_CA MBEDTLS_X509_NS_CERT_TYPE_EMAIL_CA -#define NS_CERT_TYPE_OBJECT_SIGNING MBEDTLS_X509_NS_CERT_TYPE_OBJECT_SIGNING -#define NS_CERT_TYPE_OBJECT_SIGNING_CA MBEDTLS_X509_NS_CERT_TYPE_OBJECT_SIGNING_CA -#define NS_CERT_TYPE_RESERVED MBEDTLS_X509_NS_CERT_TYPE_RESERVED -#define NS_CERT_TYPE_SSL_CA MBEDTLS_X509_NS_CERT_TYPE_SSL_CA -#define NS_CERT_TYPE_SSL_CLIENT MBEDTLS_X509_NS_CERT_TYPE_SSL_CLIENT -#define NS_CERT_TYPE_SSL_SERVER MBEDTLS_X509_NS_CERT_TYPE_SSL_SERVER -#define OID_ANSI_X9_62 MBEDTLS_OID_ANSI_X9_62 -#define OID_ANSI_X9_62_FIELD_TYPE MBEDTLS_OID_ANSI_X9_62_FIELD_TYPE -#define OID_ANSI_X9_62_PRIME_FIELD MBEDTLS_OID_ANSI_X9_62_PRIME_FIELD -#define OID_ANSI_X9_62_SIG MBEDTLS_OID_ANSI_X9_62_SIG -#define OID_ANSI_X9_62_SIG_SHA2 MBEDTLS_OID_ANSI_X9_62_SIG_SHA2 -#define OID_ANY_EXTENDED_KEY_USAGE MBEDTLS_OID_ANY_EXTENDED_KEY_USAGE -#define OID_AT MBEDTLS_OID_AT -#define OID_AT_CN MBEDTLS_OID_AT_CN -#define OID_AT_COUNTRY MBEDTLS_OID_AT_COUNTRY -#define OID_AT_DN_QUALIFIER MBEDTLS_OID_AT_DN_QUALIFIER -#define OID_AT_GENERATION_QUALIFIER MBEDTLS_OID_AT_GENERATION_QUALIFIER -#define OID_AT_GIVEN_NAME MBEDTLS_OID_AT_GIVEN_NAME -#define OID_AT_INITIALS MBEDTLS_OID_AT_INITIALS -#define OID_AT_LOCALITY MBEDTLS_OID_AT_LOCALITY -#define OID_AT_ORGANIZATION MBEDTLS_OID_AT_ORGANIZATION -#define OID_AT_ORG_UNIT MBEDTLS_OID_AT_ORG_UNIT -#define OID_AT_POSTAL_ADDRESS MBEDTLS_OID_AT_POSTAL_ADDRESS -#define OID_AT_POSTAL_CODE MBEDTLS_OID_AT_POSTAL_CODE -#define OID_AT_PSEUDONYM MBEDTLS_OID_AT_PSEUDONYM -#define OID_AT_SERIAL_NUMBER MBEDTLS_OID_AT_SERIAL_NUMBER -#define OID_AT_STATE MBEDTLS_OID_AT_STATE -#define OID_AT_SUR_NAME MBEDTLS_OID_AT_SUR_NAME -#define OID_AT_TITLE MBEDTLS_OID_AT_TITLE -#define OID_AT_UNIQUE_IDENTIFIER MBEDTLS_OID_AT_UNIQUE_IDENTIFIER -#define OID_AUTHORITY_KEY_IDENTIFIER MBEDTLS_OID_AUTHORITY_KEY_IDENTIFIER -#define OID_BASIC_CONSTRAINTS MBEDTLS_OID_BASIC_CONSTRAINTS -#define OID_CERTICOM MBEDTLS_OID_CERTICOM -#define OID_CERTIFICATE_POLICIES MBEDTLS_OID_CERTIFICATE_POLICIES -#define OID_CLIENT_AUTH MBEDTLS_OID_CLIENT_AUTH -#define OID_CMP MBEDTLS_OID_CMP -#define OID_CODE_SIGNING MBEDTLS_OID_CODE_SIGNING -#define OID_COUNTRY_US MBEDTLS_OID_COUNTRY_US -#define OID_CRL_DISTRIBUTION_POINTS MBEDTLS_OID_CRL_DISTRIBUTION_POINTS -#define OID_CRL_NUMBER MBEDTLS_OID_CRL_NUMBER -#define OID_DES_CBC MBEDTLS_OID_DES_CBC -#define OID_DES_EDE3_CBC MBEDTLS_OID_DES_EDE3_CBC -#define OID_DIGEST_ALG_MD2 MBEDTLS_OID_DIGEST_ALG_MD2 -#define OID_DIGEST_ALG_MD4 MBEDTLS_OID_DIGEST_ALG_MD4 -#define OID_DIGEST_ALG_MD5 MBEDTLS_OID_DIGEST_ALG_MD5 -#define OID_DIGEST_ALG_SHA1 MBEDTLS_OID_DIGEST_ALG_SHA1 -#define OID_DIGEST_ALG_SHA224 MBEDTLS_OID_DIGEST_ALG_SHA224 -#define OID_DIGEST_ALG_SHA256 MBEDTLS_OID_DIGEST_ALG_SHA256 -#define OID_DIGEST_ALG_SHA384 MBEDTLS_OID_DIGEST_ALG_SHA384 -#define OID_DIGEST_ALG_SHA512 MBEDTLS_OID_DIGEST_ALG_SHA512 -#define OID_DOMAIN_COMPONENT MBEDTLS_OID_DOMAIN_COMPONENT -#define OID_ECDSA_SHA1 MBEDTLS_OID_ECDSA_SHA1 -#define OID_ECDSA_SHA224 MBEDTLS_OID_ECDSA_SHA224 -#define OID_ECDSA_SHA256 MBEDTLS_OID_ECDSA_SHA256 -#define OID_ECDSA_SHA384 MBEDTLS_OID_ECDSA_SHA384 -#define OID_ECDSA_SHA512 MBEDTLS_OID_ECDSA_SHA512 -#define OID_EC_ALG_ECDH MBEDTLS_OID_EC_ALG_ECDH -#define OID_EC_ALG_UNRESTRICTED MBEDTLS_OID_EC_ALG_UNRESTRICTED -#define OID_EC_BRAINPOOL_V1 MBEDTLS_OID_EC_BRAINPOOL_V1 -#define OID_EC_GRP_BP256R1 MBEDTLS_OID_EC_GRP_BP256R1 -#define OID_EC_GRP_BP384R1 MBEDTLS_OID_EC_GRP_BP384R1 -#define OID_EC_GRP_BP512R1 MBEDTLS_OID_EC_GRP_BP512R1 -#define OID_EC_GRP_SECP192K1 MBEDTLS_OID_EC_GRP_SECP192K1 -#define OID_EC_GRP_SECP192R1 MBEDTLS_OID_EC_GRP_SECP192R1 -#define OID_EC_GRP_SECP224K1 MBEDTLS_OID_EC_GRP_SECP224K1 -#define OID_EC_GRP_SECP224R1 MBEDTLS_OID_EC_GRP_SECP224R1 -#define OID_EC_GRP_SECP256K1 MBEDTLS_OID_EC_GRP_SECP256K1 -#define OID_EC_GRP_SECP256R1 MBEDTLS_OID_EC_GRP_SECP256R1 -#define OID_EC_GRP_SECP384R1 MBEDTLS_OID_EC_GRP_SECP384R1 -#define OID_EC_GRP_SECP521R1 MBEDTLS_OID_EC_GRP_SECP521R1 -#define OID_EMAIL_PROTECTION MBEDTLS_OID_EMAIL_PROTECTION -#define OID_EXTENDED_KEY_USAGE MBEDTLS_OID_EXTENDED_KEY_USAGE -#define OID_FRESHEST_CRL MBEDTLS_OID_FRESHEST_CRL -#define OID_GOV MBEDTLS_OID_GOV -#define OID_HMAC_SHA1 MBEDTLS_OID_HMAC_SHA1 -#define OID_ID_CE MBEDTLS_OID_ID_CE -#define OID_INIHIBIT_ANYPOLICY MBEDTLS_OID_INIHIBIT_ANYPOLICY -#define OID_ISO_CCITT_DS MBEDTLS_OID_ISO_CCITT_DS -#define OID_ISO_IDENTIFIED_ORG MBEDTLS_OID_ISO_IDENTIFIED_ORG -#define OID_ISO_ITU_COUNTRY MBEDTLS_OID_ISO_ITU_COUNTRY -#define OID_ISO_ITU_US_ORG MBEDTLS_OID_ISO_ITU_US_ORG -#define OID_ISO_MEMBER_BODIES MBEDTLS_OID_ISO_MEMBER_BODIES -#define OID_ISSUER_ALT_NAME MBEDTLS_OID_ISSUER_ALT_NAME -#define OID_KEY_USAGE MBEDTLS_OID_KEY_USAGE -#define OID_KP MBEDTLS_OID_KP -#define OID_MGF1 MBEDTLS_OID_MGF1 -#define OID_NAME_CONSTRAINTS MBEDTLS_OID_NAME_CONSTRAINTS -#define OID_NETSCAPE MBEDTLS_OID_NETSCAPE -#define OID_NS_BASE_URL MBEDTLS_OID_NS_BASE_URL -#define OID_NS_CA_POLICY_URL MBEDTLS_OID_NS_CA_POLICY_URL -#define OID_NS_CA_REVOCATION_URL MBEDTLS_OID_NS_CA_REVOCATION_URL -#define OID_NS_CERT MBEDTLS_OID_NS_CERT -#define OID_NS_CERT_SEQUENCE MBEDTLS_OID_NS_CERT_SEQUENCE -#define OID_NS_CERT_TYPE MBEDTLS_OID_NS_CERT_TYPE -#define OID_NS_COMMENT MBEDTLS_OID_NS_COMMENT -#define OID_NS_DATA_TYPE MBEDTLS_OID_NS_DATA_TYPE -#define OID_NS_RENEWAL_URL MBEDTLS_OID_NS_RENEWAL_URL -#define OID_NS_REVOCATION_URL MBEDTLS_OID_NS_REVOCATION_URL -#define OID_NS_SSL_SERVER_NAME MBEDTLS_OID_NS_SSL_SERVER_NAME -#define OID_OCSP_SIGNING MBEDTLS_OID_OCSP_SIGNING -#define OID_OIW_SECSIG MBEDTLS_OID_OIW_SECSIG -#define OID_OIW_SECSIG_ALG MBEDTLS_OID_OIW_SECSIG_ALG -#define OID_OIW_SECSIG_SHA1 MBEDTLS_OID_OIW_SECSIG_SHA1 -#define OID_ORGANIZATION MBEDTLS_OID_ORGANIZATION -#define OID_ORG_ANSI_X9_62 MBEDTLS_OID_ORG_ANSI_X9_62 -#define OID_ORG_CERTICOM MBEDTLS_OID_ORG_CERTICOM -#define OID_ORG_DOD MBEDTLS_OID_ORG_DOD -#define OID_ORG_GOV MBEDTLS_OID_ORG_GOV -#define OID_ORG_NETSCAPE MBEDTLS_OID_ORG_NETSCAPE -#define OID_ORG_OIW MBEDTLS_OID_ORG_OIW -#define OID_ORG_RSA_DATA_SECURITY MBEDTLS_OID_ORG_RSA_DATA_SECURITY -#define OID_ORG_TELETRUST MBEDTLS_OID_ORG_TELETRUST -#define OID_PKCS MBEDTLS_OID_PKCS -#define OID_PKCS1 MBEDTLS_OID_PKCS1 -#define OID_PKCS12 MBEDTLS_OID_PKCS12 -#define OID_PKCS12_PBE MBEDTLS_OID_PKCS12_PBE -#define OID_PKCS12_PBE_SHA1_DES2_EDE_CBC MBEDTLS_OID_PKCS12_PBE_SHA1_DES2_EDE_CBC -#define OID_PKCS12_PBE_SHA1_DES3_EDE_CBC MBEDTLS_OID_PKCS12_PBE_SHA1_DES3_EDE_CBC -#define OID_PKCS12_PBE_SHA1_RC2_128_CBC MBEDTLS_OID_PKCS12_PBE_SHA1_RC2_128_CBC -#define OID_PKCS12_PBE_SHA1_RC2_40_CBC MBEDTLS_OID_PKCS12_PBE_SHA1_RC2_40_CBC -#define OID_PKCS12_PBE_SHA1_RC4_128 MBEDTLS_OID_PKCS12_PBE_SHA1_RC4_128 -#define OID_PKCS12_PBE_SHA1_RC4_40 MBEDTLS_OID_PKCS12_PBE_SHA1_RC4_40 -#define OID_PKCS1_MD2 MBEDTLS_OID_PKCS1_MD2 -#define OID_PKCS1_MD4 MBEDTLS_OID_PKCS1_MD4 -#define OID_PKCS1_MD5 MBEDTLS_OID_PKCS1_MD5 -#define OID_PKCS1_RSA MBEDTLS_OID_PKCS1_RSA -#define OID_PKCS1_SHA1 MBEDTLS_OID_PKCS1_SHA1 -#define OID_PKCS1_SHA224 MBEDTLS_OID_PKCS1_SHA224 -#define OID_PKCS1_SHA256 MBEDTLS_OID_PKCS1_SHA256 -#define OID_PKCS1_SHA384 MBEDTLS_OID_PKCS1_SHA384 -#define OID_PKCS1_SHA512 MBEDTLS_OID_PKCS1_SHA512 -#define OID_PKCS5 MBEDTLS_OID_PKCS5 -#define OID_PKCS5_PBES2 MBEDTLS_OID_PKCS5_PBES2 -#define OID_PKCS5_PBE_MD2_DES_CBC MBEDTLS_OID_PKCS5_PBE_MD2_DES_CBC -#define OID_PKCS5_PBE_MD2_RC2_CBC MBEDTLS_OID_PKCS5_PBE_MD2_RC2_CBC -#define OID_PKCS5_PBE_MD5_DES_CBC MBEDTLS_OID_PKCS5_PBE_MD5_DES_CBC -#define OID_PKCS5_PBE_MD5_RC2_CBC MBEDTLS_OID_PKCS5_PBE_MD5_RC2_CBC -#define OID_PKCS5_PBE_SHA1_DES_CBC MBEDTLS_OID_PKCS5_PBE_SHA1_DES_CBC -#define OID_PKCS5_PBE_SHA1_RC2_CBC MBEDTLS_OID_PKCS5_PBE_SHA1_RC2_CBC -#define OID_PKCS5_PBKDF2 MBEDTLS_OID_PKCS5_PBKDF2 -#define OID_PKCS5_PBMAC1 MBEDTLS_OID_PKCS5_PBMAC1 -#define OID_PKCS9 MBEDTLS_OID_PKCS9 -#define OID_PKCS9_CSR_EXT_REQ MBEDTLS_OID_PKCS9_CSR_EXT_REQ -#define OID_PKCS9_EMAIL MBEDTLS_OID_PKCS9_EMAIL -#define OID_PKIX MBEDTLS_OID_PKIX -#define OID_POLICY_CONSTRAINTS MBEDTLS_OID_POLICY_CONSTRAINTS -#define OID_POLICY_MAPPINGS MBEDTLS_OID_POLICY_MAPPINGS -#define OID_PRIVATE_KEY_USAGE_PERIOD MBEDTLS_OID_PRIVATE_KEY_USAGE_PERIOD -#define OID_RSASSA_PSS MBEDTLS_OID_RSASSA_PSS -#define OID_RSA_COMPANY MBEDTLS_OID_RSA_COMPANY -#define OID_RSA_SHA_OBS MBEDTLS_OID_RSA_SHA_OBS -#define OID_SERVER_AUTH MBEDTLS_OID_SERVER_AUTH -#define OID_SIZE MBEDTLS_OID_SIZE -#define OID_SUBJECT_ALT_NAME MBEDTLS_OID_SUBJECT_ALT_NAME -#define OID_SUBJECT_DIRECTORY_ATTRS MBEDTLS_OID_SUBJECT_DIRECTORY_ATTRS -#define OID_SUBJECT_KEY_IDENTIFIER MBEDTLS_OID_SUBJECT_KEY_IDENTIFIER -#define OID_TELETRUST MBEDTLS_OID_TELETRUST -#define OID_TIME_STAMPING MBEDTLS_OID_TIME_STAMPING -#define PADLOCK_ACE MBEDTLS_PADLOCK_ACE -#define PADLOCK_ALIGN16 MBEDTLS_PADLOCK_ALIGN16 -#define PADLOCK_PHE MBEDTLS_PADLOCK_PHE -#define PADLOCK_PMM MBEDTLS_PADLOCK_PMM -#define PADLOCK_RNG MBEDTLS_PADLOCK_RNG -#define PKCS12_DERIVE_IV MBEDTLS_PKCS12_DERIVE_IV -#define PKCS12_DERIVE_KEY MBEDTLS_PKCS12_DERIVE_KEY -#define PKCS12_DERIVE_MAC_KEY MBEDTLS_PKCS12_DERIVE_MAC_KEY -#define PKCS12_PBE_DECRYPT MBEDTLS_PKCS12_PBE_DECRYPT -#define PKCS12_PBE_ENCRYPT MBEDTLS_PKCS12_PBE_ENCRYPT -#define PKCS5_DECRYPT MBEDTLS_PKCS5_DECRYPT -#define PKCS5_ENCRYPT MBEDTLS_PKCS5_ENCRYPT -#define POLARSSL_AESNI_AES MBEDTLS_AESNI_AES -#define POLARSSL_AESNI_CLMUL MBEDTLS_AESNI_CLMUL -#define POLARSSL_AESNI_H MBEDTLS_AESNI_H -#define POLARSSL_AES_H MBEDTLS_AES_H -#define POLARSSL_ARC4_H MBEDTLS_ARC4_H -#define POLARSSL_ASN1_H MBEDTLS_ASN1_H -#define POLARSSL_ASN1_WRITE_H MBEDTLS_ASN1_WRITE_H -#define POLARSSL_BASE64_H MBEDTLS_BASE64_H -#define POLARSSL_BIGNUM_H MBEDTLS_BIGNUM_H -#define POLARSSL_BLOWFISH_H MBEDTLS_BLOWFISH_H -#define POLARSSL_BN_MUL_H MBEDTLS_BN_MUL_H -#define POLARSSL_CAMELLIA_H MBEDTLS_CAMELLIA_H -#define POLARSSL_CCM_H MBEDTLS_CCM_H -#define POLARSSL_CERTS_H MBEDTLS_CERTS_H -#define POLARSSL_CHECK_CONFIG_H MBEDTLS_CHECK_CONFIG_H -#define POLARSSL_CIPHERSUITE_NODTLS MBEDTLS_CIPHERSUITE_NODTLS -#define POLARSSL_CIPHERSUITE_SHORT_TAG MBEDTLS_CIPHERSUITE_SHORT_TAG -#define POLARSSL_CIPHERSUITE_WEAK MBEDTLS_CIPHERSUITE_WEAK -#define POLARSSL_CIPHER_AES_128_CBC MBEDTLS_CIPHER_AES_128_CBC -#define POLARSSL_CIPHER_AES_128_CCM MBEDTLS_CIPHER_AES_128_CCM -#define POLARSSL_CIPHER_AES_128_CFB128 MBEDTLS_CIPHER_AES_128_CFB128 -#define POLARSSL_CIPHER_AES_128_CTR MBEDTLS_CIPHER_AES_128_CTR -#define POLARSSL_CIPHER_AES_128_ECB MBEDTLS_CIPHER_AES_128_ECB -#define POLARSSL_CIPHER_AES_128_GCM MBEDTLS_CIPHER_AES_128_GCM -#define POLARSSL_CIPHER_AES_192_CBC MBEDTLS_CIPHER_AES_192_CBC -#define POLARSSL_CIPHER_AES_192_CCM MBEDTLS_CIPHER_AES_192_CCM -#define POLARSSL_CIPHER_AES_192_CFB128 MBEDTLS_CIPHER_AES_192_CFB128 -#define POLARSSL_CIPHER_AES_192_CTR MBEDTLS_CIPHER_AES_192_CTR -#define POLARSSL_CIPHER_AES_192_ECB MBEDTLS_CIPHER_AES_192_ECB -#define POLARSSL_CIPHER_AES_192_GCM MBEDTLS_CIPHER_AES_192_GCM -#define POLARSSL_CIPHER_AES_256_CBC MBEDTLS_CIPHER_AES_256_CBC -#define POLARSSL_CIPHER_AES_256_CCM MBEDTLS_CIPHER_AES_256_CCM -#define POLARSSL_CIPHER_AES_256_CFB128 MBEDTLS_CIPHER_AES_256_CFB128 -#define POLARSSL_CIPHER_AES_256_CTR MBEDTLS_CIPHER_AES_256_CTR -#define POLARSSL_CIPHER_AES_256_ECB MBEDTLS_CIPHER_AES_256_ECB -#define POLARSSL_CIPHER_AES_256_GCM MBEDTLS_CIPHER_AES_256_GCM -#define POLARSSL_CIPHER_ARC4_128 MBEDTLS_CIPHER_ARC4_128 -#define POLARSSL_CIPHER_BLOWFISH_CBC MBEDTLS_CIPHER_BLOWFISH_CBC -#define POLARSSL_CIPHER_BLOWFISH_CFB64 MBEDTLS_CIPHER_BLOWFISH_CFB64 -#define POLARSSL_CIPHER_BLOWFISH_CTR MBEDTLS_CIPHER_BLOWFISH_CTR -#define POLARSSL_CIPHER_BLOWFISH_ECB MBEDTLS_CIPHER_BLOWFISH_ECB -#define POLARSSL_CIPHER_CAMELLIA_128_CBC MBEDTLS_CIPHER_CAMELLIA_128_CBC -#define POLARSSL_CIPHER_CAMELLIA_128_CCM MBEDTLS_CIPHER_CAMELLIA_128_CCM -#define POLARSSL_CIPHER_CAMELLIA_128_CFB128 MBEDTLS_CIPHER_CAMELLIA_128_CFB128 -#define POLARSSL_CIPHER_CAMELLIA_128_CTR MBEDTLS_CIPHER_CAMELLIA_128_CTR -#define POLARSSL_CIPHER_CAMELLIA_128_ECB MBEDTLS_CIPHER_CAMELLIA_128_ECB -#define POLARSSL_CIPHER_CAMELLIA_128_GCM MBEDTLS_CIPHER_CAMELLIA_128_GCM -#define POLARSSL_CIPHER_CAMELLIA_192_CBC MBEDTLS_CIPHER_CAMELLIA_192_CBC -#define POLARSSL_CIPHER_CAMELLIA_192_CCM MBEDTLS_CIPHER_CAMELLIA_192_CCM -#define POLARSSL_CIPHER_CAMELLIA_192_CFB128 MBEDTLS_CIPHER_CAMELLIA_192_CFB128 -#define POLARSSL_CIPHER_CAMELLIA_192_CTR MBEDTLS_CIPHER_CAMELLIA_192_CTR -#define POLARSSL_CIPHER_CAMELLIA_192_ECB MBEDTLS_CIPHER_CAMELLIA_192_ECB -#define POLARSSL_CIPHER_CAMELLIA_192_GCM MBEDTLS_CIPHER_CAMELLIA_192_GCM -#define POLARSSL_CIPHER_CAMELLIA_256_CBC MBEDTLS_CIPHER_CAMELLIA_256_CBC -#define POLARSSL_CIPHER_CAMELLIA_256_CCM MBEDTLS_CIPHER_CAMELLIA_256_CCM -#define POLARSSL_CIPHER_CAMELLIA_256_CFB128 MBEDTLS_CIPHER_CAMELLIA_256_CFB128 -#define POLARSSL_CIPHER_CAMELLIA_256_CTR MBEDTLS_CIPHER_CAMELLIA_256_CTR -#define POLARSSL_CIPHER_CAMELLIA_256_ECB MBEDTLS_CIPHER_CAMELLIA_256_ECB -#define POLARSSL_CIPHER_CAMELLIA_256_GCM MBEDTLS_CIPHER_CAMELLIA_256_GCM -#define POLARSSL_CIPHER_DES_CBC MBEDTLS_CIPHER_DES_CBC -#define POLARSSL_CIPHER_DES_ECB MBEDTLS_CIPHER_DES_ECB -#define POLARSSL_CIPHER_DES_EDE3_CBC MBEDTLS_CIPHER_DES_EDE3_CBC -#define POLARSSL_CIPHER_DES_EDE3_ECB MBEDTLS_CIPHER_DES_EDE3_ECB -#define POLARSSL_CIPHER_DES_EDE_CBC MBEDTLS_CIPHER_DES_EDE_CBC -#define POLARSSL_CIPHER_DES_EDE_ECB MBEDTLS_CIPHER_DES_EDE_ECB -#define POLARSSL_CIPHER_H MBEDTLS_CIPHER_H -#define POLARSSL_CIPHER_ID_3DES MBEDTLS_CIPHER_ID_3DES -#define POLARSSL_CIPHER_ID_AES MBEDTLS_CIPHER_ID_AES -#define POLARSSL_CIPHER_ID_ARC4 MBEDTLS_CIPHER_ID_ARC4 -#define POLARSSL_CIPHER_ID_BLOWFISH MBEDTLS_CIPHER_ID_BLOWFISH -#define POLARSSL_CIPHER_ID_CAMELLIA MBEDTLS_CIPHER_ID_CAMELLIA -#define POLARSSL_CIPHER_ID_DES MBEDTLS_CIPHER_ID_DES -#define POLARSSL_CIPHER_ID_NONE MBEDTLS_CIPHER_ID_NONE -#define POLARSSL_CIPHER_ID_NULL MBEDTLS_CIPHER_ID_NULL -#define POLARSSL_CIPHER_MODE_AEAD MBEDTLS_CIPHER_MODE_AEAD -#define POLARSSL_CIPHER_MODE_STREAM MBEDTLS_CIPHER_MODE_STREAM -#define POLARSSL_CIPHER_MODE_WITH_PADDING MBEDTLS_CIPHER_MODE_WITH_PADDING -#define POLARSSL_CIPHER_NONE MBEDTLS_CIPHER_NONE -#define POLARSSL_CIPHER_NULL MBEDTLS_CIPHER_NULL -#define POLARSSL_CIPHER_VARIABLE_IV_LEN MBEDTLS_CIPHER_VARIABLE_IV_LEN -#define POLARSSL_CIPHER_VARIABLE_KEY_LEN MBEDTLS_CIPHER_VARIABLE_KEY_LEN -#define POLARSSL_CIPHER_WRAP_H MBEDTLS_CIPHER_WRAP_H -#define POLARSSL_CONFIG_H MBEDTLS_CONFIG_H -#define POLARSSL_CTR_DRBG_H MBEDTLS_CTR_DRBG_H -#define POLARSSL_DEBUG_H MBEDTLS_DEBUG_H -#define POLARSSL_DECRYPT MBEDTLS_DECRYPT -#define POLARSSL_DES_H MBEDTLS_DES_H -#define POLARSSL_DHM_H MBEDTLS_DHM_H -#define POLARSSL_DHM_RFC3526_MODP_2048_G MBEDTLS_DHM_RFC3526_MODP_2048_G -#define POLARSSL_DHM_RFC3526_MODP_2048_P MBEDTLS_DHM_RFC3526_MODP_2048_P -#define POLARSSL_DHM_RFC3526_MODP_3072_G MBEDTLS_DHM_RFC3526_MODP_3072_G -#define POLARSSL_DHM_RFC3526_MODP_3072_P MBEDTLS_DHM_RFC3526_MODP_3072_P -#define POLARSSL_DHM_RFC5114_MODP_2048_G MBEDTLS_DHM_RFC5114_MODP_2048_G -#define POLARSSL_DHM_RFC5114_MODP_2048_P MBEDTLS_DHM_RFC5114_MODP_2048_P -#define POLARSSL_ECDH_H MBEDTLS_ECDH_H -#define POLARSSL_ECDH_OURS MBEDTLS_ECDH_OURS -#define POLARSSL_ECDH_THEIRS MBEDTLS_ECDH_THEIRS -#define POLARSSL_ECDSA_H MBEDTLS_ECDSA_H -#define POLARSSL_ECP_DP_BP256R1 MBEDTLS_ECP_DP_BP256R1 -#define POLARSSL_ECP_DP_BP384R1 MBEDTLS_ECP_DP_BP384R1 -#define POLARSSL_ECP_DP_BP512R1 MBEDTLS_ECP_DP_BP512R1 -#define POLARSSL_ECP_DP_M255 MBEDTLS_ECP_DP_CURVE25519 -#define POLARSSL_ECP_DP_MAX MBEDTLS_ECP_DP_MAX -#define POLARSSL_ECP_DP_NONE MBEDTLS_ECP_DP_NONE -#define POLARSSL_ECP_DP_SECP192K1 MBEDTLS_ECP_DP_SECP192K1 -#define POLARSSL_ECP_DP_SECP192R1 MBEDTLS_ECP_DP_SECP192R1 -#define POLARSSL_ECP_DP_SECP224K1 MBEDTLS_ECP_DP_SECP224K1 -#define POLARSSL_ECP_DP_SECP224R1 MBEDTLS_ECP_DP_SECP224R1 -#define POLARSSL_ECP_DP_SECP256K1 MBEDTLS_ECP_DP_SECP256K1 -#define POLARSSL_ECP_DP_SECP256R1 MBEDTLS_ECP_DP_SECP256R1 -#define POLARSSL_ECP_DP_SECP384R1 MBEDTLS_ECP_DP_SECP384R1 -#define POLARSSL_ECP_DP_SECP521R1 MBEDTLS_ECP_DP_SECP521R1 -#define POLARSSL_ECP_H MBEDTLS_ECP_H -#define POLARSSL_ECP_MAX_BYTES MBEDTLS_ECP_MAX_BYTES -#define POLARSSL_ECP_MAX_PT_LEN MBEDTLS_ECP_MAX_PT_LEN -#define POLARSSL_ECP_PF_COMPRESSED MBEDTLS_ECP_PF_COMPRESSED -#define POLARSSL_ECP_PF_UNCOMPRESSED MBEDTLS_ECP_PF_UNCOMPRESSED -#define POLARSSL_ECP_TLS_NAMED_CURVE MBEDTLS_ECP_TLS_NAMED_CURVE -#define POLARSSL_ENCRYPT MBEDTLS_ENCRYPT -#define POLARSSL_ENTROPY_H MBEDTLS_ENTROPY_H -#define POLARSSL_ENTROPY_POLL_H MBEDTLS_ENTROPY_POLL_H -#define POLARSSL_ENTROPY_SHA256_ACCUMULATOR MBEDTLS_ENTROPY_SHA256_ACCUMULATOR -#define POLARSSL_ENTROPY_SHA512_ACCUMULATOR MBEDTLS_ENTROPY_SHA512_ACCUMULATOR -#define POLARSSL_ERROR_H MBEDTLS_ERROR_H -#define POLARSSL_ERR_AES_INVALID_INPUT_LENGTH MBEDTLS_ERR_AES_INVALID_INPUT_LENGTH -#define POLARSSL_ERR_AES_INVALID_KEY_LENGTH MBEDTLS_ERR_AES_INVALID_KEY_LENGTH -#define POLARSSL_ERR_ASN1_BUF_TOO_SMALL MBEDTLS_ERR_ASN1_BUF_TOO_SMALL -#define POLARSSL_ERR_ASN1_INVALID_DATA MBEDTLS_ERR_ASN1_INVALID_DATA -#define POLARSSL_ERR_ASN1_INVALID_LENGTH MBEDTLS_ERR_ASN1_INVALID_LENGTH -#define POLARSSL_ERR_ASN1_LENGTH_MISMATCH MBEDTLS_ERR_ASN1_LENGTH_MISMATCH -#define POLARSSL_ERR_ASN1_MALLOC_FAILED MBEDTLS_ERR_ASN1_ALLOC_FAILED -#define POLARSSL_ERR_ASN1_OUT_OF_DATA MBEDTLS_ERR_ASN1_OUT_OF_DATA -#define POLARSSL_ERR_ASN1_UNEXPECTED_TAG MBEDTLS_ERR_ASN1_UNEXPECTED_TAG -#define POLARSSL_ERR_BASE64_BUFFER_TOO_SMALL MBEDTLS_ERR_BASE64_BUFFER_TOO_SMALL -#define POLARSSL_ERR_BASE64_INVALID_CHARACTER MBEDTLS_ERR_BASE64_INVALID_CHARACTER -#define POLARSSL_ERR_BLOWFISH_INVALID_INPUT_LENGTH MBEDTLS_ERR_BLOWFISH_INVALID_INPUT_LENGTH -#define POLARSSL_ERR_BLOWFISH_INVALID_KEY_LENGTH MBEDTLS_ERR_BLOWFISH_INVALID_KEY_LENGTH -#define POLARSSL_ERR_CAMELLIA_INVALID_INPUT_LENGTH MBEDTLS_ERR_CAMELLIA_INVALID_INPUT_LENGTH -#define POLARSSL_ERR_CAMELLIA_INVALID_KEY_LENGTH MBEDTLS_ERR_CAMELLIA_INVALID_KEY_LENGTH -#define POLARSSL_ERR_CCM_AUTH_FAILED MBEDTLS_ERR_CCM_AUTH_FAILED -#define POLARSSL_ERR_CCM_BAD_INPUT MBEDTLS_ERR_CCM_BAD_INPUT -#define POLARSSL_ERR_CIPHER_ALLOC_FAILED MBEDTLS_ERR_CIPHER_ALLOC_FAILED -#define POLARSSL_ERR_CIPHER_AUTH_FAILED MBEDTLS_ERR_CIPHER_AUTH_FAILED -#define POLARSSL_ERR_CIPHER_BAD_INPUT_DATA MBEDTLS_ERR_CIPHER_BAD_INPUT_DATA -#define POLARSSL_ERR_CIPHER_FEATURE_UNAVAILABLE MBEDTLS_ERR_CIPHER_FEATURE_UNAVAILABLE -#define POLARSSL_ERR_CIPHER_FULL_BLOCK_EXPECTED MBEDTLS_ERR_CIPHER_FULL_BLOCK_EXPECTED -#define POLARSSL_ERR_CIPHER_INVALID_PADDING MBEDTLS_ERR_CIPHER_INVALID_PADDING -#define POLARSSL_ERR_CTR_DRBG_ENTROPY_SOURCE_FAILED MBEDTLS_ERR_CTR_DRBG_ENTROPY_SOURCE_FAILED -#define POLARSSL_ERR_CTR_DRBG_FILE_IO_ERROR MBEDTLS_ERR_CTR_DRBG_FILE_IO_ERROR -#define POLARSSL_ERR_CTR_DRBG_INPUT_TOO_BIG MBEDTLS_ERR_CTR_DRBG_INPUT_TOO_BIG -#define POLARSSL_ERR_CTR_DRBG_REQUEST_TOO_BIG MBEDTLS_ERR_CTR_DRBG_REQUEST_TOO_BIG -#define POLARSSL_ERR_DES_INVALID_INPUT_LENGTH MBEDTLS_ERR_DES_INVALID_INPUT_LENGTH -#define POLARSSL_ERR_DHM_BAD_INPUT_DATA MBEDTLS_ERR_DHM_BAD_INPUT_DATA -#define POLARSSL_ERR_DHM_CALC_SECRET_FAILED MBEDTLS_ERR_DHM_CALC_SECRET_FAILED -#define POLARSSL_ERR_DHM_FILE_IO_ERROR MBEDTLS_ERR_DHM_FILE_IO_ERROR -#define POLARSSL_ERR_DHM_INVALID_FORMAT MBEDTLS_ERR_DHM_INVALID_FORMAT -#define POLARSSL_ERR_DHM_MAKE_PARAMS_FAILED MBEDTLS_ERR_DHM_MAKE_PARAMS_FAILED -#define POLARSSL_ERR_DHM_MAKE_PUBLIC_FAILED MBEDTLS_ERR_DHM_MAKE_PUBLIC_FAILED -#define POLARSSL_ERR_DHM_MALLOC_FAILED MBEDTLS_ERR_DHM_ALLOC_FAILED -#define POLARSSL_ERR_DHM_READ_PARAMS_FAILED MBEDTLS_ERR_DHM_READ_PARAMS_FAILED -#define POLARSSL_ERR_DHM_READ_PUBLIC_FAILED MBEDTLS_ERR_DHM_READ_PUBLIC_FAILED -#define POLARSSL_ERR_ECP_BAD_INPUT_DATA MBEDTLS_ERR_ECP_BAD_INPUT_DATA -#define POLARSSL_ERR_ECP_BUFFER_TOO_SMALL MBEDTLS_ERR_ECP_BUFFER_TOO_SMALL -#define POLARSSL_ERR_ECP_FEATURE_UNAVAILABLE MBEDTLS_ERR_ECP_FEATURE_UNAVAILABLE -#define POLARSSL_ERR_ECP_INVALID_KEY MBEDTLS_ERR_ECP_INVALID_KEY -#define POLARSSL_ERR_ECP_MALLOC_FAILED MBEDTLS_ERR_ECP_ALLOC_FAILED -#define POLARSSL_ERR_ECP_RANDOM_FAILED MBEDTLS_ERR_ECP_RANDOM_FAILED -#define POLARSSL_ERR_ECP_SIG_LEN_MISMATCH MBEDTLS_ERR_ECP_SIG_LEN_MISMATCH -#define POLARSSL_ERR_ECP_VERIFY_FAILED MBEDTLS_ERR_ECP_VERIFY_FAILED -#define POLARSSL_ERR_ENTROPY_FILE_IO_ERROR MBEDTLS_ERR_ENTROPY_FILE_IO_ERROR -#define POLARSSL_ERR_ENTROPY_MAX_SOURCES MBEDTLS_ERR_ENTROPY_MAX_SOURCES -#define POLARSSL_ERR_ENTROPY_NO_SOURCES_DEFINED MBEDTLS_ERR_ENTROPY_NO_SOURCES_DEFINED -#define POLARSSL_ERR_ENTROPY_SOURCE_FAILED MBEDTLS_ERR_ENTROPY_SOURCE_FAILED -#define POLARSSL_ERR_GCM_AUTH_FAILED MBEDTLS_ERR_GCM_AUTH_FAILED -#define POLARSSL_ERR_GCM_BAD_INPUT MBEDTLS_ERR_GCM_BAD_INPUT -#define POLARSSL_ERR_HMAC_DRBG_ENTROPY_SOURCE_FAILED MBEDTLS_ERR_HMAC_DRBG_ENTROPY_SOURCE_FAILED -#define POLARSSL_ERR_HMAC_DRBG_FILE_IO_ERROR MBEDTLS_ERR_HMAC_DRBG_FILE_IO_ERROR -#define POLARSSL_ERR_HMAC_DRBG_INPUT_TOO_BIG MBEDTLS_ERR_HMAC_DRBG_INPUT_TOO_BIG -#define POLARSSL_ERR_HMAC_DRBG_REQUEST_TOO_BIG MBEDTLS_ERR_HMAC_DRBG_REQUEST_TOO_BIG -#define POLARSSL_ERR_MD_ALLOC_FAILED MBEDTLS_ERR_MD_ALLOC_FAILED -#define POLARSSL_ERR_MD_BAD_INPUT_DATA MBEDTLS_ERR_MD_BAD_INPUT_DATA -#define POLARSSL_ERR_MD_FEATURE_UNAVAILABLE MBEDTLS_ERR_MD_FEATURE_UNAVAILABLE -#define POLARSSL_ERR_MD_FILE_IO_ERROR MBEDTLS_ERR_MD_FILE_IO_ERROR -#define POLARSSL_ERR_MPI_BAD_INPUT_DATA MBEDTLS_ERR_MPI_BAD_INPUT_DATA -#define POLARSSL_ERR_MPI_BUFFER_TOO_SMALL MBEDTLS_ERR_MPI_BUFFER_TOO_SMALL -#define POLARSSL_ERR_MPI_DIVISION_BY_ZERO MBEDTLS_ERR_MPI_DIVISION_BY_ZERO -#define POLARSSL_ERR_MPI_FILE_IO_ERROR MBEDTLS_ERR_MPI_FILE_IO_ERROR -#define POLARSSL_ERR_MPI_INVALID_CHARACTER MBEDTLS_ERR_MPI_INVALID_CHARACTER -#define POLARSSL_ERR_MPI_MALLOC_FAILED MBEDTLS_ERR_MPI_ALLOC_FAILED -#define POLARSSL_ERR_MPI_NEGATIVE_VALUE MBEDTLS_ERR_MPI_NEGATIVE_VALUE -#define POLARSSL_ERR_MPI_NOT_ACCEPTABLE MBEDTLS_ERR_MPI_NOT_ACCEPTABLE -#define POLARSSL_ERR_NET_ACCEPT_FAILED MBEDTLS_ERR_NET_ACCEPT_FAILED -#define POLARSSL_ERR_NET_BIND_FAILED MBEDTLS_ERR_NET_BIND_FAILED -#define POLARSSL_ERR_NET_CONNECT_FAILED MBEDTLS_ERR_NET_CONNECT_FAILED -#define POLARSSL_ERR_NET_CONN_RESET MBEDTLS_ERR_NET_CONN_RESET -#define POLARSSL_ERR_NET_LISTEN_FAILED MBEDTLS_ERR_NET_LISTEN_FAILED -#define POLARSSL_ERR_NET_RECV_FAILED MBEDTLS_ERR_NET_RECV_FAILED -#define POLARSSL_ERR_NET_SEND_FAILED MBEDTLS_ERR_NET_SEND_FAILED -#define POLARSSL_ERR_NET_SOCKET_FAILED MBEDTLS_ERR_NET_SOCKET_FAILED -#define POLARSSL_ERR_NET_TIMEOUT MBEDTLS_ERR_SSL_TIMEOUT -#define POLARSSL_ERR_NET_UNKNOWN_HOST MBEDTLS_ERR_NET_UNKNOWN_HOST -#define POLARSSL_ERR_NET_WANT_READ MBEDTLS_ERR_SSL_WANT_READ -#define POLARSSL_ERR_NET_WANT_WRITE MBEDTLS_ERR_SSL_WANT_WRITE -#define POLARSSL_ERR_OID_BUF_TOO_SMALL MBEDTLS_ERR_OID_BUF_TOO_SMALL -#define POLARSSL_ERR_OID_NOT_FOUND MBEDTLS_ERR_OID_NOT_FOUND -#define POLARSSL_ERR_PADLOCK_DATA_MISALIGNED MBEDTLS_ERR_PADLOCK_DATA_MISALIGNED -#define POLARSSL_ERR_PEM_BAD_INPUT_DATA MBEDTLS_ERR_PEM_BAD_INPUT_DATA -#define POLARSSL_ERR_PEM_FEATURE_UNAVAILABLE MBEDTLS_ERR_PEM_FEATURE_UNAVAILABLE -#define POLARSSL_ERR_PEM_INVALID_DATA MBEDTLS_ERR_PEM_INVALID_DATA -#define POLARSSL_ERR_PEM_INVALID_ENC_IV MBEDTLS_ERR_PEM_INVALID_ENC_IV -#define POLARSSL_ERR_PEM_MALLOC_FAILED MBEDTLS_ERR_PEM_ALLOC_FAILED -#define POLARSSL_ERR_PEM_NO_HEADER_FOOTER_PRESENT MBEDTLS_ERR_PEM_NO_HEADER_FOOTER_PRESENT -#define POLARSSL_ERR_PEM_PASSWORD_MISMATCH MBEDTLS_ERR_PEM_PASSWORD_MISMATCH -#define POLARSSL_ERR_PEM_PASSWORD_REQUIRED MBEDTLS_ERR_PEM_PASSWORD_REQUIRED -#define POLARSSL_ERR_PEM_UNKNOWN_ENC_ALG MBEDTLS_ERR_PEM_UNKNOWN_ENC_ALG -#define POLARSSL_ERR_PKCS12_BAD_INPUT_DATA MBEDTLS_ERR_PKCS12_BAD_INPUT_DATA -#define POLARSSL_ERR_PKCS12_FEATURE_UNAVAILABLE MBEDTLS_ERR_PKCS12_FEATURE_UNAVAILABLE -#define POLARSSL_ERR_PKCS12_PASSWORD_MISMATCH MBEDTLS_ERR_PKCS12_PASSWORD_MISMATCH -#define POLARSSL_ERR_PKCS12_PBE_INVALID_FORMAT MBEDTLS_ERR_PKCS12_PBE_INVALID_FORMAT -#define POLARSSL_ERR_PKCS5_BAD_INPUT_DATA MBEDTLS_ERR_PKCS5_BAD_INPUT_DATA -#define POLARSSL_ERR_PKCS5_FEATURE_UNAVAILABLE MBEDTLS_ERR_PKCS5_FEATURE_UNAVAILABLE -#define POLARSSL_ERR_PKCS5_INVALID_FORMAT MBEDTLS_ERR_PKCS5_INVALID_FORMAT -#define POLARSSL_ERR_PKCS5_PASSWORD_MISMATCH MBEDTLS_ERR_PKCS5_PASSWORD_MISMATCH -#define POLARSSL_ERR_PK_BAD_INPUT_DATA MBEDTLS_ERR_PK_BAD_INPUT_DATA -#define POLARSSL_ERR_PK_FEATURE_UNAVAILABLE MBEDTLS_ERR_PK_FEATURE_UNAVAILABLE -#define POLARSSL_ERR_PK_FILE_IO_ERROR MBEDTLS_ERR_PK_FILE_IO_ERROR -#define POLARSSL_ERR_PK_INVALID_ALG MBEDTLS_ERR_PK_INVALID_ALG -#define POLARSSL_ERR_PK_INVALID_PUBKEY MBEDTLS_ERR_PK_INVALID_PUBKEY -#define POLARSSL_ERR_PK_KEY_INVALID_FORMAT MBEDTLS_ERR_PK_KEY_INVALID_FORMAT -#define POLARSSL_ERR_PK_KEY_INVALID_VERSION MBEDTLS_ERR_PK_KEY_INVALID_VERSION -#define POLARSSL_ERR_PK_MALLOC_FAILED MBEDTLS_ERR_PK_ALLOC_FAILED -#define POLARSSL_ERR_PK_PASSWORD_MISMATCH MBEDTLS_ERR_PK_PASSWORD_MISMATCH -#define POLARSSL_ERR_PK_PASSWORD_REQUIRED MBEDTLS_ERR_PK_PASSWORD_REQUIRED -#define POLARSSL_ERR_PK_SIG_LEN_MISMATCH MBEDTLS_ERR_PK_SIG_LEN_MISMATCH -#define POLARSSL_ERR_PK_TYPE_MISMATCH MBEDTLS_ERR_PK_TYPE_MISMATCH -#define POLARSSL_ERR_PK_UNKNOWN_NAMED_CURVE MBEDTLS_ERR_PK_UNKNOWN_NAMED_CURVE -#define POLARSSL_ERR_PK_UNKNOWN_PK_ALG MBEDTLS_ERR_PK_UNKNOWN_PK_ALG -#define POLARSSL_ERR_RSA_BAD_INPUT_DATA MBEDTLS_ERR_RSA_BAD_INPUT_DATA -#define POLARSSL_ERR_RSA_INVALID_PADDING MBEDTLS_ERR_RSA_INVALID_PADDING -#define POLARSSL_ERR_RSA_KEY_CHECK_FAILED MBEDTLS_ERR_RSA_KEY_CHECK_FAILED -#define POLARSSL_ERR_RSA_KEY_GEN_FAILED MBEDTLS_ERR_RSA_KEY_GEN_FAILED -#define POLARSSL_ERR_RSA_OUTPUT_TOO_LARGE MBEDTLS_ERR_RSA_OUTPUT_TOO_LARGE -#define POLARSSL_ERR_RSA_PRIVATE_FAILED MBEDTLS_ERR_RSA_PRIVATE_FAILED -#define POLARSSL_ERR_RSA_PUBLIC_FAILED MBEDTLS_ERR_RSA_PUBLIC_FAILED -#define POLARSSL_ERR_RSA_RNG_FAILED MBEDTLS_ERR_RSA_RNG_FAILED -#define POLARSSL_ERR_RSA_VERIFY_FAILED MBEDTLS_ERR_RSA_VERIFY_FAILED -#define POLARSSL_ERR_SSL_BAD_HS_CERTIFICATE MBEDTLS_ERR_SSL_BAD_HS_CERTIFICATE -#define POLARSSL_ERR_SSL_BAD_HS_CERTIFICATE_REQUEST MBEDTLS_ERR_SSL_BAD_HS_CERTIFICATE_REQUEST -#define POLARSSL_ERR_SSL_BAD_HS_CERTIFICATE_VERIFY MBEDTLS_ERR_SSL_BAD_HS_CERTIFICATE_VERIFY -#define POLARSSL_ERR_SSL_BAD_HS_CHANGE_CIPHER_SPEC MBEDTLS_ERR_SSL_BAD_HS_CHANGE_CIPHER_SPEC -#define POLARSSL_ERR_SSL_BAD_HS_CLIENT_HELLO MBEDTLS_ERR_SSL_BAD_HS_CLIENT_HELLO -#define POLARSSL_ERR_SSL_BAD_HS_CLIENT_KEY_EXCHANGE MBEDTLS_ERR_SSL_BAD_HS_CLIENT_KEY_EXCHANGE -#define POLARSSL_ERR_SSL_BAD_HS_CLIENT_KEY_EXCHANGE_CS MBEDTLS_ERR_SSL_BAD_HS_CLIENT_KEY_EXCHANGE_CS -#define POLARSSL_ERR_SSL_BAD_HS_CLIENT_KEY_EXCHANGE_RP MBEDTLS_ERR_SSL_BAD_HS_CLIENT_KEY_EXCHANGE_RP -#define POLARSSL_ERR_SSL_BAD_HS_FINISHED MBEDTLS_ERR_SSL_BAD_HS_FINISHED -#define POLARSSL_ERR_SSL_BAD_HS_NEW_SESSION_TICKET MBEDTLS_ERR_SSL_BAD_HS_NEW_SESSION_TICKET -#define POLARSSL_ERR_SSL_BAD_HS_PROTOCOL_VERSION MBEDTLS_ERR_SSL_BAD_HS_PROTOCOL_VERSION -#define POLARSSL_ERR_SSL_BAD_HS_SERVER_HELLO MBEDTLS_ERR_SSL_BAD_HS_SERVER_HELLO -#define POLARSSL_ERR_SSL_BAD_HS_SERVER_HELLO_DONE MBEDTLS_ERR_SSL_BAD_HS_SERVER_HELLO_DONE -#define POLARSSL_ERR_SSL_BAD_HS_SERVER_KEY_EXCHANGE MBEDTLS_ERR_SSL_BAD_HS_SERVER_KEY_EXCHANGE -#define POLARSSL_ERR_SSL_BAD_INPUT_DATA MBEDTLS_ERR_SSL_BAD_INPUT_DATA -#define POLARSSL_ERR_SSL_BUFFER_TOO_SMALL MBEDTLS_ERR_SSL_BUFFER_TOO_SMALL -#define POLARSSL_ERR_SSL_CA_CHAIN_REQUIRED MBEDTLS_ERR_SSL_CA_CHAIN_REQUIRED -#define POLARSSL_ERR_SSL_CERTIFICATE_REQUIRED MBEDTLS_ERR_SSL_CERTIFICATE_REQUIRED -#define POLARSSL_ERR_SSL_CERTIFICATE_TOO_LARGE MBEDTLS_ERR_SSL_CERTIFICATE_TOO_LARGE -#define POLARSSL_ERR_SSL_COMPRESSION_FAILED MBEDTLS_ERR_SSL_COMPRESSION_FAILED -#define POLARSSL_ERR_SSL_CONN_EOF MBEDTLS_ERR_SSL_CONN_EOF -#define POLARSSL_ERR_SSL_COUNTER_WRAPPING MBEDTLS_ERR_SSL_COUNTER_WRAPPING -#define POLARSSL_ERR_SSL_FATAL_ALERT_MESSAGE MBEDTLS_ERR_SSL_FATAL_ALERT_MESSAGE -#define POLARSSL_ERR_SSL_FEATURE_UNAVAILABLE MBEDTLS_ERR_SSL_FEATURE_UNAVAILABLE -#define POLARSSL_ERR_SSL_HELLO_VERIFY_REQUIRED MBEDTLS_ERR_SSL_HELLO_VERIFY_REQUIRED -#define POLARSSL_ERR_SSL_HW_ACCEL_FAILED MBEDTLS_ERR_SSL_HW_ACCEL_FAILED -#define POLARSSL_ERR_SSL_HW_ACCEL_FALLTHROUGH MBEDTLS_ERR_SSL_HW_ACCEL_FALLTHROUGH -#define POLARSSL_ERR_SSL_INTERNAL_ERROR MBEDTLS_ERR_SSL_INTERNAL_ERROR -#define POLARSSL_ERR_SSL_INVALID_MAC MBEDTLS_ERR_SSL_INVALID_MAC -#define POLARSSL_ERR_SSL_INVALID_RECORD MBEDTLS_ERR_SSL_INVALID_RECORD -#define POLARSSL_ERR_SSL_MALLOC_FAILED MBEDTLS_ERR_SSL_ALLOC_FAILED -#define POLARSSL_ERR_SSL_NO_CIPHER_CHOSEN MBEDTLS_ERR_SSL_NO_CIPHER_CHOSEN -#define POLARSSL_ERR_SSL_NO_CLIENT_CERTIFICATE MBEDTLS_ERR_SSL_NO_CLIENT_CERTIFICATE -#define POLARSSL_ERR_SSL_NO_RNG MBEDTLS_ERR_SSL_NO_RNG -#define POLARSSL_ERR_SSL_NO_USABLE_CIPHERSUITE MBEDTLS_ERR_SSL_NO_USABLE_CIPHERSUITE -#define POLARSSL_ERR_SSL_PEER_CLOSE_NOTIFY MBEDTLS_ERR_SSL_PEER_CLOSE_NOTIFY -#define POLARSSL_ERR_SSL_PEER_VERIFY_FAILED MBEDTLS_ERR_SSL_PEER_VERIFY_FAILED -#define POLARSSL_ERR_SSL_PK_TYPE_MISMATCH MBEDTLS_ERR_SSL_PK_TYPE_MISMATCH -#define POLARSSL_ERR_SSL_PRIVATE_KEY_REQUIRED MBEDTLS_ERR_SSL_PRIVATE_KEY_REQUIRED -#define POLARSSL_ERR_SSL_SESSION_TICKET_EXPIRED MBEDTLS_ERR_SSL_SESSION_TICKET_EXPIRED -#define POLARSSL_ERR_SSL_UNEXPECTED_MESSAGE MBEDTLS_ERR_SSL_UNEXPECTED_MESSAGE -#define POLARSSL_ERR_SSL_UNKNOWN_CIPHER MBEDTLS_ERR_SSL_UNKNOWN_CIPHER -#define POLARSSL_ERR_SSL_UNKNOWN_IDENTITY MBEDTLS_ERR_SSL_UNKNOWN_IDENTITY -#define POLARSSL_ERR_SSL_WAITING_SERVER_HELLO_RENEGO MBEDTLS_ERR_SSL_WAITING_SERVER_HELLO_RENEGO -#define POLARSSL_ERR_THREADING_BAD_INPUT_DATA MBEDTLS_ERR_THREADING_BAD_INPUT_DATA -#define POLARSSL_ERR_THREADING_FEATURE_UNAVAILABLE MBEDTLS_ERR_THREADING_FEATURE_UNAVAILABLE -#define POLARSSL_ERR_THREADING_MUTEX_ERROR MBEDTLS_ERR_THREADING_MUTEX_ERROR -#define POLARSSL_ERR_X509_BAD_INPUT_DATA MBEDTLS_ERR_X509_BAD_INPUT_DATA -#define POLARSSL_ERR_X509_CERT_UNKNOWN_FORMAT MBEDTLS_ERR_X509_CERT_UNKNOWN_FORMAT -#define POLARSSL_ERR_X509_CERT_VERIFY_FAILED MBEDTLS_ERR_X509_CERT_VERIFY_FAILED -#define POLARSSL_ERR_X509_FEATURE_UNAVAILABLE MBEDTLS_ERR_X509_FEATURE_UNAVAILABLE -#define POLARSSL_ERR_X509_FILE_IO_ERROR MBEDTLS_ERR_X509_FILE_IO_ERROR -#define POLARSSL_ERR_X509_INVALID_ALG MBEDTLS_ERR_X509_INVALID_ALG -#define POLARSSL_ERR_X509_INVALID_DATE MBEDTLS_ERR_X509_INVALID_DATE -#define POLARSSL_ERR_X509_INVALID_EXTENSIONS MBEDTLS_ERR_X509_INVALID_EXTENSIONS -#define POLARSSL_ERR_X509_INVALID_FORMAT MBEDTLS_ERR_X509_INVALID_FORMAT -#define POLARSSL_ERR_X509_INVALID_NAME MBEDTLS_ERR_X509_INVALID_NAME -#define POLARSSL_ERR_X509_INVALID_SERIAL MBEDTLS_ERR_X509_INVALID_SERIAL -#define POLARSSL_ERR_X509_INVALID_SIGNATURE MBEDTLS_ERR_X509_INVALID_SIGNATURE -#define POLARSSL_ERR_X509_INVALID_VERSION MBEDTLS_ERR_X509_INVALID_VERSION -#define POLARSSL_ERR_X509_MALLOC_FAILED MBEDTLS_ERR_X509_ALLOC_FAILED -#define POLARSSL_ERR_X509_SIG_MISMATCH MBEDTLS_ERR_X509_SIG_MISMATCH -#define POLARSSL_ERR_X509_UNKNOWN_OID MBEDTLS_ERR_X509_UNKNOWN_OID -#define POLARSSL_ERR_X509_UNKNOWN_SIG_ALG MBEDTLS_ERR_X509_UNKNOWN_SIG_ALG -#define POLARSSL_ERR_X509_UNKNOWN_VERSION MBEDTLS_ERR_X509_UNKNOWN_VERSION -#define POLARSSL_ERR_XTEA_INVALID_INPUT_LENGTH MBEDTLS_ERR_XTEA_INVALID_INPUT_LENGTH -#define POLARSSL_GCM_H MBEDTLS_GCM_H -#define POLARSSL_HAVEGE_H MBEDTLS_HAVEGE_H -#define POLARSSL_HAVE_INT32 MBEDTLS_HAVE_INT32 -#define POLARSSL_HAVE_INT64 MBEDTLS_HAVE_INT64 -#define POLARSSL_HAVE_UDBL MBEDTLS_HAVE_UDBL -#define POLARSSL_HAVE_X86 MBEDTLS_HAVE_X86 -#define POLARSSL_HAVE_X86_64 MBEDTLS_HAVE_X86_64 -#define POLARSSL_HMAC_DRBG_H MBEDTLS_HMAC_DRBG_H -#define POLARSSL_HMAC_DRBG_PR_OFF MBEDTLS_HMAC_DRBG_PR_OFF -#define POLARSSL_HMAC_DRBG_PR_ON MBEDTLS_HMAC_DRBG_PR_ON -#define POLARSSL_KEY_EXCHANGE_DHE_PSK MBEDTLS_KEY_EXCHANGE_DHE_PSK -#define POLARSSL_KEY_EXCHANGE_DHE_RSA MBEDTLS_KEY_EXCHANGE_DHE_RSA -#define POLARSSL_KEY_EXCHANGE_ECDHE_ECDSA MBEDTLS_KEY_EXCHANGE_ECDHE_ECDSA -#define POLARSSL_KEY_EXCHANGE_ECDHE_PSK MBEDTLS_KEY_EXCHANGE_ECDHE_PSK -#define POLARSSL_KEY_EXCHANGE_ECDHE_RSA MBEDTLS_KEY_EXCHANGE_ECDHE_RSA -#define POLARSSL_KEY_EXCHANGE_ECDH_ECDSA MBEDTLS_KEY_EXCHANGE_ECDH_ECDSA -#define POLARSSL_KEY_EXCHANGE_ECDH_RSA MBEDTLS_KEY_EXCHANGE_ECDH_RSA -#define POLARSSL_KEY_EXCHANGE_NONE MBEDTLS_KEY_EXCHANGE_NONE -#define POLARSSL_KEY_EXCHANGE_PSK MBEDTLS_KEY_EXCHANGE_PSK -#define POLARSSL_KEY_EXCHANGE_RSA MBEDTLS_KEY_EXCHANGE_RSA -#define POLARSSL_KEY_EXCHANGE_RSA_PSK MBEDTLS_KEY_EXCHANGE_RSA_PSK -#define POLARSSL_KEY_EXCHANGE__SOME__ECDHE_ENABLED MBEDTLS_KEY_EXCHANGE_SOME_ECDHE_ENABLED -#define POLARSSL_KEY_EXCHANGE__SOME__PSK_ENABLED MBEDTLS_KEY_EXCHANGE_SOME_PSK_ENABLED -#define POLARSSL_KEY_EXCHANGE__WITH_CERT__ENABLED MBEDTLS_KEY_EXCHANGE_WITH_CERT_ENABLED -#define POLARSSL_KEY_LENGTH_DES MBEDTLS_KEY_LENGTH_DES -#define POLARSSL_KEY_LENGTH_DES_EDE MBEDTLS_KEY_LENGTH_DES_EDE -#define POLARSSL_KEY_LENGTH_DES_EDE3 MBEDTLS_KEY_LENGTH_DES_EDE3 -#define POLARSSL_KEY_LENGTH_NONE MBEDTLS_KEY_LENGTH_NONE -#define POLARSSL_MAX_BLOCK_LENGTH MBEDTLS_MAX_BLOCK_LENGTH -#define POLARSSL_MAX_IV_LENGTH MBEDTLS_MAX_IV_LENGTH -#define POLARSSL_MD2_H MBEDTLS_MD2_H -#define POLARSSL_MD4_H MBEDTLS_MD4_H -#define POLARSSL_MD5_H MBEDTLS_MD5_H -#define POLARSSL_MD_H MBEDTLS_MD_H -#define POLARSSL_MD_MAX_SIZE MBEDTLS_MD_MAX_SIZE -#define POLARSSL_MD_MD2 MBEDTLS_MD_MD2 -#define POLARSSL_MD_MD4 MBEDTLS_MD_MD4 -#define POLARSSL_MD_MD5 MBEDTLS_MD_MD5 -#define POLARSSL_MD_NONE MBEDTLS_MD_NONE -#define POLARSSL_MD_RIPEMD160 MBEDTLS_MD_RIPEMD160 -#define POLARSSL_MD_SHA1 MBEDTLS_MD_SHA1 -#define POLARSSL_MD_SHA224 MBEDTLS_MD_SHA224 -#define POLARSSL_MD_SHA256 MBEDTLS_MD_SHA256 -#define POLARSSL_MD_SHA384 MBEDTLS_MD_SHA384 -#define POLARSSL_MD_SHA512 MBEDTLS_MD_SHA512 -#define POLARSSL_MD_WRAP_H MBEDTLS_MD_WRAP_H -#define POLARSSL_MEMORY_BUFFER_ALLOC_H MBEDTLS_MEMORY_BUFFER_ALLOC_H -#define POLARSSL_MODE_CBC MBEDTLS_MODE_CBC -#define POLARSSL_MODE_CCM MBEDTLS_MODE_CCM -#define POLARSSL_MODE_CFB MBEDTLS_MODE_CFB -#define POLARSSL_MODE_CTR MBEDTLS_MODE_CTR -#define POLARSSL_MODE_ECB MBEDTLS_MODE_ECB -#define POLARSSL_MODE_GCM MBEDTLS_MODE_GCM -#define POLARSSL_MODE_NONE MBEDTLS_MODE_NONE -#define POLARSSL_MODE_OFB MBEDTLS_MODE_OFB -#define POLARSSL_MODE_STREAM MBEDTLS_MODE_STREAM -#define POLARSSL_MPI_MAX_BITS MBEDTLS_MPI_MAX_BITS -#define POLARSSL_MPI_MAX_BITS_SCALE100 MBEDTLS_MPI_MAX_BITS_SCALE100 -#define POLARSSL_MPI_MAX_LIMBS MBEDTLS_MPI_MAX_LIMBS -#define POLARSSL_MPI_RW_BUFFER_SIZE MBEDTLS_MPI_RW_BUFFER_SIZE -#define POLARSSL_NET_H MBEDTLS_NET_SOCKETS_H -#define POLARSSL_NET_LISTEN_BACKLOG MBEDTLS_NET_LISTEN_BACKLOG -#define POLARSSL_OID_H MBEDTLS_OID_H -#define POLARSSL_OPERATION_NONE MBEDTLS_OPERATION_NONE -#define POLARSSL_PADDING_NONE MBEDTLS_PADDING_NONE -#define POLARSSL_PADDING_ONE_AND_ZEROS MBEDTLS_PADDING_ONE_AND_ZEROS -#define POLARSSL_PADDING_PKCS7 MBEDTLS_PADDING_PKCS7 -#define POLARSSL_PADDING_ZEROS MBEDTLS_PADDING_ZEROS -#define POLARSSL_PADDING_ZEROS_AND_LEN MBEDTLS_PADDING_ZEROS_AND_LEN -#define POLARSSL_PADLOCK_H MBEDTLS_PADLOCK_H -#define POLARSSL_PEM_H MBEDTLS_PEM_H -#define POLARSSL_PKCS11_H MBEDTLS_PKCS11_H -#define POLARSSL_PKCS12_H MBEDTLS_PKCS12_H -#define POLARSSL_PKCS5_H MBEDTLS_PKCS5_H -#define POLARSSL_PK_DEBUG_ECP MBEDTLS_PK_DEBUG_ECP -#define POLARSSL_PK_DEBUG_MAX_ITEMS MBEDTLS_PK_DEBUG_MAX_ITEMS -#define POLARSSL_PK_DEBUG_MPI MBEDTLS_PK_DEBUG_MPI -#define POLARSSL_PK_DEBUG_NONE MBEDTLS_PK_DEBUG_NONE -#define POLARSSL_PK_ECDSA MBEDTLS_PK_ECDSA -#define POLARSSL_PK_ECKEY MBEDTLS_PK_ECKEY -#define POLARSSL_PK_ECKEY_DH MBEDTLS_PK_ECKEY_DH -#define POLARSSL_PK_H MBEDTLS_PK_H -#define POLARSSL_PK_NONE MBEDTLS_PK_NONE -#define POLARSSL_PK_RSA MBEDTLS_PK_RSA -#define POLARSSL_PK_RSASSA_PSS MBEDTLS_PK_RSASSA_PSS -#define POLARSSL_PK_RSA_ALT MBEDTLS_PK_RSA_ALT -#define POLARSSL_PK_WRAP_H MBEDTLS_PK_WRAP_H -#define POLARSSL_PLATFORM_H MBEDTLS_PLATFORM_H -#define POLARSSL_PREMASTER_SIZE MBEDTLS_PREMASTER_SIZE -#define POLARSSL_RIPEMD160_H MBEDTLS_RIPEMD160_H -#define POLARSSL_RSA_H MBEDTLS_RSA_H -#define POLARSSL_SHA1_H MBEDTLS_SHA1_H -#define POLARSSL_SHA256_H MBEDTLS_SHA256_H -#define POLARSSL_SHA512_H MBEDTLS_SHA512_H -#define POLARSSL_SSL_CACHE_H MBEDTLS_SSL_CACHE_H -#define POLARSSL_SSL_CIPHERSUITES_H MBEDTLS_SSL_CIPHERSUITES_H -#define POLARSSL_SSL_COOKIE_H MBEDTLS_SSL_COOKIE_H -#define POLARSSL_SSL_H MBEDTLS_SSL_H -#define POLARSSL_THREADING_H MBEDTLS_THREADING_H -#define POLARSSL_THREADING_IMPL MBEDTLS_THREADING_IMPL -#define POLARSSL_TIMING_H MBEDTLS_TIMING_H -#define POLARSSL_VERSION_H MBEDTLS_VERSION_H -#define POLARSSL_VERSION_MAJOR MBEDTLS_VERSION_MAJOR -#define POLARSSL_VERSION_MINOR MBEDTLS_VERSION_MINOR -#define POLARSSL_VERSION_NUMBER MBEDTLS_VERSION_NUMBER -#define POLARSSL_VERSION_PATCH MBEDTLS_VERSION_PATCH -#define POLARSSL_VERSION_STRING MBEDTLS_VERSION_STRING -#define POLARSSL_VERSION_STRING_FULL MBEDTLS_VERSION_STRING_FULL -#define POLARSSL_X509_CRL_H MBEDTLS_X509_CRL_H -#define POLARSSL_X509_CRT_H MBEDTLS_X509_CRT_H -#define POLARSSL_X509_CSR_H MBEDTLS_X509_CSR_H -#define POLARSSL_X509_H MBEDTLS_X509_H -#define POLARSSL_XTEA_H MBEDTLS_XTEA_H -#define RSA_CRYPT MBEDTLS_RSA_CRYPT -#define RSA_PKCS_V15 MBEDTLS_RSA_PKCS_V15 -#define RSA_PKCS_V21 MBEDTLS_RSA_PKCS_V21 -#define RSA_PRIVATE MBEDTLS_RSA_PRIVATE -#define RSA_PUBLIC MBEDTLS_RSA_PUBLIC -#define RSA_SALT_LEN_ANY MBEDTLS_RSA_SALT_LEN_ANY -#define RSA_SIGN MBEDTLS_RSA_SIGN -#define SSL_ALERT_LEVEL_FATAL MBEDTLS_SSL_ALERT_LEVEL_FATAL -#define SSL_ALERT_LEVEL_WARNING MBEDTLS_SSL_ALERT_LEVEL_WARNING -#define SSL_ALERT_MSG_ACCESS_DENIED MBEDTLS_SSL_ALERT_MSG_ACCESS_DENIED -#define SSL_ALERT_MSG_BAD_CERT MBEDTLS_SSL_ALERT_MSG_BAD_CERT -#define SSL_ALERT_MSG_BAD_RECORD_MAC MBEDTLS_SSL_ALERT_MSG_BAD_RECORD_MAC -#define SSL_ALERT_MSG_CERT_EXPIRED MBEDTLS_SSL_ALERT_MSG_CERT_EXPIRED -#define SSL_ALERT_MSG_CERT_REVOKED MBEDTLS_SSL_ALERT_MSG_CERT_REVOKED -#define SSL_ALERT_MSG_CERT_UNKNOWN MBEDTLS_SSL_ALERT_MSG_CERT_UNKNOWN -#define SSL_ALERT_MSG_CLOSE_NOTIFY MBEDTLS_SSL_ALERT_MSG_CLOSE_NOTIFY -#define SSL_ALERT_MSG_DECODE_ERROR MBEDTLS_SSL_ALERT_MSG_DECODE_ERROR -#define SSL_ALERT_MSG_DECOMPRESSION_FAILURE MBEDTLS_SSL_ALERT_MSG_DECOMPRESSION_FAILURE -#define SSL_ALERT_MSG_DECRYPTION_FAILED MBEDTLS_SSL_ALERT_MSG_DECRYPTION_FAILED -#define SSL_ALERT_MSG_DECRYPT_ERROR MBEDTLS_SSL_ALERT_MSG_DECRYPT_ERROR -#define SSL_ALERT_MSG_EXPORT_RESTRICTION MBEDTLS_SSL_ALERT_MSG_EXPORT_RESTRICTION -#define SSL_ALERT_MSG_HANDSHAKE_FAILURE MBEDTLS_SSL_ALERT_MSG_HANDSHAKE_FAILURE -#define SSL_ALERT_MSG_ILLEGAL_PARAMETER MBEDTLS_SSL_ALERT_MSG_ILLEGAL_PARAMETER -#define SSL_ALERT_MSG_INAPROPRIATE_FALLBACK MBEDTLS_SSL_ALERT_MSG_INAPROPRIATE_FALLBACK -#define SSL_ALERT_MSG_INSUFFICIENT_SECURITY MBEDTLS_SSL_ALERT_MSG_INSUFFICIENT_SECURITY -#define SSL_ALERT_MSG_INTERNAL_ERROR MBEDTLS_SSL_ALERT_MSG_INTERNAL_ERROR -#define SSL_ALERT_MSG_NO_APPLICATION_PROTOCOL MBEDTLS_SSL_ALERT_MSG_NO_APPLICATION_PROTOCOL -#define SSL_ALERT_MSG_NO_CERT MBEDTLS_SSL_ALERT_MSG_NO_CERT -#define SSL_ALERT_MSG_NO_RENEGOTIATION MBEDTLS_SSL_ALERT_MSG_NO_RENEGOTIATION -#define SSL_ALERT_MSG_PROTOCOL_VERSION MBEDTLS_SSL_ALERT_MSG_PROTOCOL_VERSION -#define SSL_ALERT_MSG_RECORD_OVERFLOW MBEDTLS_SSL_ALERT_MSG_RECORD_OVERFLOW -#define SSL_ALERT_MSG_UNEXPECTED_MESSAGE MBEDTLS_SSL_ALERT_MSG_UNEXPECTED_MESSAGE -#define SSL_ALERT_MSG_UNKNOWN_CA MBEDTLS_SSL_ALERT_MSG_UNKNOWN_CA -#define SSL_ALERT_MSG_UNKNOWN_PSK_IDENTITY MBEDTLS_SSL_ALERT_MSG_UNKNOWN_PSK_IDENTITY -#define SSL_ALERT_MSG_UNRECOGNIZED_NAME MBEDTLS_SSL_ALERT_MSG_UNRECOGNIZED_NAME -#define SSL_ALERT_MSG_UNSUPPORTED_CERT MBEDTLS_SSL_ALERT_MSG_UNSUPPORTED_CERT -#define SSL_ALERT_MSG_UNSUPPORTED_EXT MBEDTLS_SSL_ALERT_MSG_UNSUPPORTED_EXT -#define SSL_ALERT_MSG_USER_CANCELED MBEDTLS_SSL_ALERT_MSG_USER_CANCELED -#define SSL_ANTI_REPLAY_DISABLED MBEDTLS_SSL_ANTI_REPLAY_DISABLED -#define SSL_ANTI_REPLAY_ENABLED MBEDTLS_SSL_ANTI_REPLAY_ENABLED -#define SSL_ARC4_DISABLED MBEDTLS_SSL_ARC4_DISABLED -#define SSL_ARC4_ENABLED MBEDTLS_SSL_ARC4_ENABLED -#define SSL_BUFFER_LEN (((MBEDTLS_SSL_IN_BUFFER_LEN) < (MBEDTLS_SSL_OUT_BUFFER_LEN)) \ - ? (MBEDTLS_SSL_IN_BUFFER_LEN) : (MBEDTLS_SSL_OUT_BUFFER_LEN)) -#define SSL_CACHE_DEFAULT_MAX_ENTRIES MBEDTLS_SSL_CACHE_DEFAULT_MAX_ENTRIES -#define SSL_CACHE_DEFAULT_TIMEOUT MBEDTLS_SSL_CACHE_DEFAULT_TIMEOUT -#define SSL_CBC_RECORD_SPLITTING_DISABLED MBEDTLS_SSL_CBC_RECORD_SPLITTING_DISABLED -#define SSL_CBC_RECORD_SPLITTING_ENABLED MBEDTLS_SSL_CBC_RECORD_SPLITTING_ENABLED -#define SSL_CERTIFICATE_REQUEST MBEDTLS_SSL_CERTIFICATE_REQUEST -#define SSL_CERTIFICATE_VERIFY MBEDTLS_SSL_CERTIFICATE_VERIFY -#define SSL_CERT_TYPE_ECDSA_SIGN MBEDTLS_SSL_CERT_TYPE_ECDSA_SIGN -#define SSL_CERT_TYPE_RSA_SIGN MBEDTLS_SSL_CERT_TYPE_RSA_SIGN -#define SSL_CHANNEL_INBOUND MBEDTLS_SSL_CHANNEL_INBOUND -#define SSL_CHANNEL_OUTBOUND MBEDTLS_SSL_CHANNEL_OUTBOUND -#define SSL_CIPHERSUITES MBEDTLS_SSL_CIPHERSUITES -#define SSL_CLIENT_CERTIFICATE MBEDTLS_SSL_CLIENT_CERTIFICATE -#define SSL_CLIENT_CHANGE_CIPHER_SPEC MBEDTLS_SSL_CLIENT_CHANGE_CIPHER_SPEC -#define SSL_CLIENT_FINISHED MBEDTLS_SSL_CLIENT_FINISHED -#define SSL_CLIENT_HELLO MBEDTLS_SSL_CLIENT_HELLO -#define SSL_CLIENT_KEY_EXCHANGE MBEDTLS_SSL_CLIENT_KEY_EXCHANGE -#define SSL_COMPRESSION_ADD MBEDTLS_SSL_COMPRESSION_ADD -#define SSL_COMPRESS_DEFLATE MBEDTLS_SSL_COMPRESS_DEFLATE -#define SSL_COMPRESS_NULL MBEDTLS_SSL_COMPRESS_NULL -#define SSL_DEBUG_BUF MBEDTLS_SSL_DEBUG_BUF -#define SSL_DEBUG_CRT MBEDTLS_SSL_DEBUG_CRT -#define SSL_DEBUG_ECP MBEDTLS_SSL_DEBUG_ECP -#define SSL_DEBUG_MPI MBEDTLS_SSL_DEBUG_MPI -#define SSL_DEBUG_MSG MBEDTLS_SSL_DEBUG_MSG -#define SSL_DEBUG_RET MBEDTLS_SSL_DEBUG_RET -#define SSL_DEFAULT_TICKET_LIFETIME MBEDTLS_SSL_DEFAULT_TICKET_LIFETIME -#define SSL_DTLS_TIMEOUT_DFL_MAX MBEDTLS_SSL_DTLS_TIMEOUT_DFL_MAX -#define SSL_DTLS_TIMEOUT_DFL_MIN MBEDTLS_SSL_DTLS_TIMEOUT_DFL_MIN -#define SSL_EMPTY_RENEGOTIATION_INFO MBEDTLS_SSL_EMPTY_RENEGOTIATION_INFO -#define SSL_ETM_DISABLED MBEDTLS_SSL_ETM_DISABLED -#define SSL_ETM_ENABLED MBEDTLS_SSL_ETM_ENABLED -#define SSL_EXTENDED_MS_DISABLED MBEDTLS_SSL_EXTENDED_MS_DISABLED -#define SSL_EXTENDED_MS_ENABLED MBEDTLS_SSL_EXTENDED_MS_ENABLED -#define SSL_FALLBACK_SCSV MBEDTLS_SSL_FALLBACK_SCSV -#define SSL_FLUSH_BUFFERS MBEDTLS_SSL_FLUSH_BUFFERS -#define SSL_HANDSHAKE_OVER MBEDTLS_SSL_HANDSHAKE_OVER -#define SSL_HANDSHAKE_WRAPUP MBEDTLS_SSL_HANDSHAKE_WRAPUP -#define SSL_HASH_MD5 MBEDTLS_SSL_HASH_MD5 -#define SSL_HASH_NONE MBEDTLS_SSL_HASH_NONE -#define SSL_HASH_SHA1 MBEDTLS_SSL_HASH_SHA1 -#define SSL_HASH_SHA224 MBEDTLS_SSL_HASH_SHA224 -#define SSL_HASH_SHA256 MBEDTLS_SSL_HASH_SHA256 -#define SSL_HASH_SHA384 MBEDTLS_SSL_HASH_SHA384 -#define SSL_HASH_SHA512 MBEDTLS_SSL_HASH_SHA512 -#define SSL_HELLO_REQUEST MBEDTLS_SSL_HELLO_REQUEST -#define SSL_HS_CERTIFICATE MBEDTLS_SSL_HS_CERTIFICATE -#define SSL_HS_CERTIFICATE_REQUEST MBEDTLS_SSL_HS_CERTIFICATE_REQUEST -#define SSL_HS_CERTIFICATE_VERIFY MBEDTLS_SSL_HS_CERTIFICATE_VERIFY -#define SSL_HS_CLIENT_HELLO MBEDTLS_SSL_HS_CLIENT_HELLO -#define SSL_HS_CLIENT_KEY_EXCHANGE MBEDTLS_SSL_HS_CLIENT_KEY_EXCHANGE -#define SSL_HS_FINISHED MBEDTLS_SSL_HS_FINISHED -#define SSL_HS_HELLO_REQUEST MBEDTLS_SSL_HS_HELLO_REQUEST -#define SSL_HS_HELLO_VERIFY_REQUEST MBEDTLS_SSL_HS_HELLO_VERIFY_REQUEST -#define SSL_HS_NEW_SESSION_TICKET MBEDTLS_SSL_HS_NEW_SESSION_TICKET -#define SSL_HS_SERVER_HELLO MBEDTLS_SSL_HS_SERVER_HELLO -#define SSL_HS_SERVER_HELLO_DONE MBEDTLS_SSL_HS_SERVER_HELLO_DONE -#define SSL_HS_SERVER_KEY_EXCHANGE MBEDTLS_SSL_HS_SERVER_KEY_EXCHANGE -#define SSL_INITIAL_HANDSHAKE MBEDTLS_SSL_INITIAL_HANDSHAKE -#define SSL_IS_CLIENT MBEDTLS_SSL_IS_CLIENT -#define SSL_IS_FALLBACK MBEDTLS_SSL_IS_FALLBACK -#define SSL_IS_NOT_FALLBACK MBEDTLS_SSL_IS_NOT_FALLBACK -#define SSL_IS_SERVER MBEDTLS_SSL_IS_SERVER -#define SSL_LEGACY_ALLOW_RENEGOTIATION MBEDTLS_SSL_LEGACY_ALLOW_RENEGOTIATION -#define SSL_LEGACY_BREAK_HANDSHAKE MBEDTLS_SSL_LEGACY_BREAK_HANDSHAKE -#define SSL_LEGACY_NO_RENEGOTIATION MBEDTLS_SSL_LEGACY_NO_RENEGOTIATION -#define SSL_LEGACY_RENEGOTIATION MBEDTLS_SSL_LEGACY_RENEGOTIATION -#define SSL_MAC_ADD MBEDTLS_SSL_MAC_ADD -#define SSL_MAJOR_VERSION_3 MBEDTLS_SSL_MAJOR_VERSION_3 -#define SSL_MAX_CONTENT_LEN MBEDTLS_SSL_MAX_CONTENT_LEN -#define SSL_MAX_FRAG_LEN_1024 MBEDTLS_SSL_MAX_FRAG_LEN_1024 -#define SSL_MAX_FRAG_LEN_2048 MBEDTLS_SSL_MAX_FRAG_LEN_2048 -#define SSL_MAX_FRAG_LEN_4096 MBEDTLS_SSL_MAX_FRAG_LEN_4096 -#define SSL_MAX_FRAG_LEN_512 MBEDTLS_SSL_MAX_FRAG_LEN_512 -#define SSL_MAX_FRAG_LEN_INVALID MBEDTLS_SSL_MAX_FRAG_LEN_INVALID -#define SSL_MAX_FRAG_LEN_NONE MBEDTLS_SSL_MAX_FRAG_LEN_NONE -#define SSL_MAX_MAJOR_VERSION MBEDTLS_SSL_MAX_MAJOR_VERSION -#define SSL_MAX_MINOR_VERSION MBEDTLS_SSL_MAX_MINOR_VERSION -#define SSL_MINOR_VERSION_0 MBEDTLS_SSL_MINOR_VERSION_0 -#define SSL_MINOR_VERSION_1 MBEDTLS_SSL_MINOR_VERSION_1 -#define SSL_MINOR_VERSION_2 MBEDTLS_SSL_MINOR_VERSION_2 -#define SSL_MINOR_VERSION_3 MBEDTLS_SSL_MINOR_VERSION_3 -#define SSL_MIN_MAJOR_VERSION MBEDTLS_SSL_MIN_MAJOR_VERSION -#define SSL_MIN_MINOR_VERSION MBEDTLS_SSL_MIN_MINOR_VERSION -#define SSL_MSG_ALERT MBEDTLS_SSL_MSG_ALERT -#define SSL_MSG_APPLICATION_DATA MBEDTLS_SSL_MSG_APPLICATION_DATA -#define SSL_MSG_CHANGE_CIPHER_SPEC MBEDTLS_SSL_MSG_CHANGE_CIPHER_SPEC -#define SSL_MSG_HANDSHAKE MBEDTLS_SSL_MSG_HANDSHAKE -#define SSL_PADDING_ADD MBEDTLS_SSL_PADDING_ADD -#define SSL_RENEGOTIATION MBEDTLS_SSL_RENEGOTIATION -#define SSL_RENEGOTIATION_DISABLED MBEDTLS_SSL_RENEGOTIATION_DISABLED -#define SSL_RENEGOTIATION_DONE MBEDTLS_SSL_RENEGOTIATION_DONE -#define SSL_RENEGOTIATION_ENABLED MBEDTLS_SSL_RENEGOTIATION_ENABLED -#define SSL_RENEGOTIATION_NOT_ENFORCED MBEDTLS_SSL_RENEGOTIATION_NOT_ENFORCED -#define SSL_RENEGOTIATION_PENDING MBEDTLS_SSL_RENEGOTIATION_PENDING -#define SSL_RENEGO_MAX_RECORDS_DEFAULT MBEDTLS_SSL_RENEGO_MAX_RECORDS_DEFAULT -#define SSL_RETRANS_FINISHED MBEDTLS_SSL_RETRANS_FINISHED -#define SSL_RETRANS_PREPARING MBEDTLS_SSL_RETRANS_PREPARING -#define SSL_RETRANS_SENDING MBEDTLS_SSL_RETRANS_SENDING -#define SSL_RETRANS_WAITING MBEDTLS_SSL_RETRANS_WAITING -#define SSL_SECURE_RENEGOTIATION MBEDTLS_SSL_SECURE_RENEGOTIATION -#define SSL_SERVER_CERTIFICATE MBEDTLS_SSL_SERVER_CERTIFICATE -#define SSL_SERVER_CHANGE_CIPHER_SPEC MBEDTLS_SSL_SERVER_CHANGE_CIPHER_SPEC -#define SSL_SERVER_FINISHED MBEDTLS_SSL_SERVER_FINISHED -#define SSL_SERVER_HELLO MBEDTLS_SSL_SERVER_HELLO -#define SSL_SERVER_HELLO_DONE MBEDTLS_SSL_SERVER_HELLO_DONE -#define SSL_SERVER_HELLO_VERIFY_REQUEST_SENT MBEDTLS_SSL_SERVER_HELLO_VERIFY_REQUEST_SENT -#define SSL_SERVER_KEY_EXCHANGE MBEDTLS_SSL_SERVER_KEY_EXCHANGE -#define SSL_SERVER_NEW_SESSION_TICKET MBEDTLS_SSL_SERVER_NEW_SESSION_TICKET -#define SSL_SESSION_TICKETS_DISABLED MBEDTLS_SSL_SESSION_TICKETS_DISABLED -#define SSL_SESSION_TICKETS_ENABLED MBEDTLS_SSL_SESSION_TICKETS_ENABLED -#define SSL_SIG_ANON MBEDTLS_SSL_SIG_ANON -#define SSL_SIG_ECDSA MBEDTLS_SSL_SIG_ECDSA -#define SSL_SIG_RSA MBEDTLS_SSL_SIG_RSA -#define SSL_TRANSPORT_DATAGRAM MBEDTLS_SSL_TRANSPORT_DATAGRAM -#define SSL_TRANSPORT_STREAM MBEDTLS_SSL_TRANSPORT_STREAM -#define SSL_TRUNCATED_HMAC_LEN MBEDTLS_SSL_TRUNCATED_HMAC_LEN -#define SSL_TRUNC_HMAC_DISABLED MBEDTLS_SSL_TRUNC_HMAC_DISABLED -#define SSL_TRUNC_HMAC_ENABLED MBEDTLS_SSL_TRUNC_HMAC_ENABLED -#define SSL_VERIFY_DATA_MAX_LEN MBEDTLS_SSL_VERIFY_DATA_MAX_LEN -#define SSL_VERIFY_NONE MBEDTLS_SSL_VERIFY_NONE -#define SSL_VERIFY_OPTIONAL MBEDTLS_SSL_VERIFY_OPTIONAL -#define SSL_VERIFY_REQUIRED MBEDTLS_SSL_VERIFY_REQUIRED -#define TLS_DHE_PSK_WITH_3DES_EDE_CBC_SHA MBEDTLS_TLS_DHE_PSK_WITH_3DES_EDE_CBC_SHA -#define TLS_DHE_PSK_WITH_AES_128_CBC_SHA MBEDTLS_TLS_DHE_PSK_WITH_AES_128_CBC_SHA -#define TLS_DHE_PSK_WITH_AES_128_CBC_SHA256 MBEDTLS_TLS_DHE_PSK_WITH_AES_128_CBC_SHA256 -#define TLS_DHE_PSK_WITH_AES_128_CCM MBEDTLS_TLS_DHE_PSK_WITH_AES_128_CCM -#define TLS_DHE_PSK_WITH_AES_128_CCM_8 MBEDTLS_TLS_DHE_PSK_WITH_AES_128_CCM_8 -#define TLS_DHE_PSK_WITH_AES_128_GCM_SHA256 MBEDTLS_TLS_DHE_PSK_WITH_AES_128_GCM_SHA256 -#define TLS_DHE_PSK_WITH_AES_256_CBC_SHA MBEDTLS_TLS_DHE_PSK_WITH_AES_256_CBC_SHA -#define TLS_DHE_PSK_WITH_AES_256_CBC_SHA384 MBEDTLS_TLS_DHE_PSK_WITH_AES_256_CBC_SHA384 -#define TLS_DHE_PSK_WITH_AES_256_CCM MBEDTLS_TLS_DHE_PSK_WITH_AES_256_CCM -#define TLS_DHE_PSK_WITH_AES_256_CCM_8 MBEDTLS_TLS_DHE_PSK_WITH_AES_256_CCM_8 -#define TLS_DHE_PSK_WITH_AES_256_GCM_SHA384 MBEDTLS_TLS_DHE_PSK_WITH_AES_256_GCM_SHA384 -#define TLS_DHE_PSK_WITH_CAMELLIA_128_CBC_SHA256 MBEDTLS_TLS_DHE_PSK_WITH_CAMELLIA_128_CBC_SHA256 -#define TLS_DHE_PSK_WITH_CAMELLIA_128_GCM_SHA256 MBEDTLS_TLS_DHE_PSK_WITH_CAMELLIA_128_GCM_SHA256 -#define TLS_DHE_PSK_WITH_CAMELLIA_256_CBC_SHA384 MBEDTLS_TLS_DHE_PSK_WITH_CAMELLIA_256_CBC_SHA384 -#define TLS_DHE_PSK_WITH_CAMELLIA_256_GCM_SHA384 MBEDTLS_TLS_DHE_PSK_WITH_CAMELLIA_256_GCM_SHA384 -#define TLS_DHE_PSK_WITH_NULL_SHA MBEDTLS_TLS_DHE_PSK_WITH_NULL_SHA -#define TLS_DHE_PSK_WITH_NULL_SHA256 MBEDTLS_TLS_DHE_PSK_WITH_NULL_SHA256 -#define TLS_DHE_PSK_WITH_NULL_SHA384 MBEDTLS_TLS_DHE_PSK_WITH_NULL_SHA384 -#define TLS_DHE_PSK_WITH_RC4_128_SHA MBEDTLS_TLS_DHE_PSK_WITH_RC4_128_SHA -#define TLS_DHE_RSA_WITH_3DES_EDE_CBC_SHA MBEDTLS_TLS_DHE_RSA_WITH_3DES_EDE_CBC_SHA -#define TLS_DHE_RSA_WITH_AES_128_CBC_SHA MBEDTLS_TLS_DHE_RSA_WITH_AES_128_CBC_SHA -#define TLS_DHE_RSA_WITH_AES_128_CBC_SHA256 MBEDTLS_TLS_DHE_RSA_WITH_AES_128_CBC_SHA256 -#define TLS_DHE_RSA_WITH_AES_128_CCM MBEDTLS_TLS_DHE_RSA_WITH_AES_128_CCM -#define TLS_DHE_RSA_WITH_AES_128_CCM_8 MBEDTLS_TLS_DHE_RSA_WITH_AES_128_CCM_8 -#define TLS_DHE_RSA_WITH_AES_128_GCM_SHA256 MBEDTLS_TLS_DHE_RSA_WITH_AES_128_GCM_SHA256 -#define TLS_DHE_RSA_WITH_AES_256_CBC_SHA MBEDTLS_TLS_DHE_RSA_WITH_AES_256_CBC_SHA -#define TLS_DHE_RSA_WITH_AES_256_CBC_SHA256 MBEDTLS_TLS_DHE_RSA_WITH_AES_256_CBC_SHA256 -#define TLS_DHE_RSA_WITH_AES_256_CCM MBEDTLS_TLS_DHE_RSA_WITH_AES_256_CCM -#define TLS_DHE_RSA_WITH_AES_256_CCM_8 MBEDTLS_TLS_DHE_RSA_WITH_AES_256_CCM_8 -#define TLS_DHE_RSA_WITH_AES_256_GCM_SHA384 MBEDTLS_TLS_DHE_RSA_WITH_AES_256_GCM_SHA384 -#define TLS_DHE_RSA_WITH_CAMELLIA_128_CBC_SHA MBEDTLS_TLS_DHE_RSA_WITH_CAMELLIA_128_CBC_SHA -#define TLS_DHE_RSA_WITH_CAMELLIA_128_CBC_SHA256 MBEDTLS_TLS_DHE_RSA_WITH_CAMELLIA_128_CBC_SHA256 -#define TLS_DHE_RSA_WITH_CAMELLIA_128_GCM_SHA256 MBEDTLS_TLS_DHE_RSA_WITH_CAMELLIA_128_GCM_SHA256 -#define TLS_DHE_RSA_WITH_CAMELLIA_256_CBC_SHA MBEDTLS_TLS_DHE_RSA_WITH_CAMELLIA_256_CBC_SHA -#define TLS_DHE_RSA_WITH_CAMELLIA_256_CBC_SHA256 MBEDTLS_TLS_DHE_RSA_WITH_CAMELLIA_256_CBC_SHA256 -#define TLS_DHE_RSA_WITH_CAMELLIA_256_GCM_SHA384 MBEDTLS_TLS_DHE_RSA_WITH_CAMELLIA_256_GCM_SHA384 -#define TLS_DHE_RSA_WITH_DES_CBC_SHA MBEDTLS_TLS_DHE_RSA_WITH_DES_CBC_SHA -#define TLS_ECDHE_ECDSA_WITH_3DES_EDE_CBC_SHA MBEDTLS_TLS_ECDHE_ECDSA_WITH_3DES_EDE_CBC_SHA -#define TLS_ECDHE_ECDSA_WITH_AES_128_CBC_SHA MBEDTLS_TLS_ECDHE_ECDSA_WITH_AES_128_CBC_SHA -#define TLS_ECDHE_ECDSA_WITH_AES_128_CBC_SHA256 MBEDTLS_TLS_ECDHE_ECDSA_WITH_AES_128_CBC_SHA256 -#define TLS_ECDHE_ECDSA_WITH_AES_128_CCM MBEDTLS_TLS_ECDHE_ECDSA_WITH_AES_128_CCM -#define TLS_ECDHE_ECDSA_WITH_AES_128_CCM_8 MBEDTLS_TLS_ECDHE_ECDSA_WITH_AES_128_CCM_8 -#define TLS_ECDHE_ECDSA_WITH_AES_128_GCM_SHA256 MBEDTLS_TLS_ECDHE_ECDSA_WITH_AES_128_GCM_SHA256 -#define TLS_ECDHE_ECDSA_WITH_AES_256_CBC_SHA MBEDTLS_TLS_ECDHE_ECDSA_WITH_AES_256_CBC_SHA -#define TLS_ECDHE_ECDSA_WITH_AES_256_CBC_SHA384 MBEDTLS_TLS_ECDHE_ECDSA_WITH_AES_256_CBC_SHA384 -#define TLS_ECDHE_ECDSA_WITH_AES_256_CCM MBEDTLS_TLS_ECDHE_ECDSA_WITH_AES_256_CCM -#define TLS_ECDHE_ECDSA_WITH_AES_256_CCM_8 MBEDTLS_TLS_ECDHE_ECDSA_WITH_AES_256_CCM_8 -#define TLS_ECDHE_ECDSA_WITH_AES_256_GCM_SHA384 MBEDTLS_TLS_ECDHE_ECDSA_WITH_AES_256_GCM_SHA384 -#define TLS_ECDHE_ECDSA_WITH_CAMELLIA_128_CBC_SHA256 \ - MBEDTLS_TLS_ECDHE_ECDSA_WITH_CAMELLIA_128_CBC_SHA256 -#define TLS_ECDHE_ECDSA_WITH_CAMELLIA_128_GCM_SHA256 \ - MBEDTLS_TLS_ECDHE_ECDSA_WITH_CAMELLIA_128_GCM_SHA256 -#define TLS_ECDHE_ECDSA_WITH_CAMELLIA_256_CBC_SHA384 \ - MBEDTLS_TLS_ECDHE_ECDSA_WITH_CAMELLIA_256_CBC_SHA384 -#define TLS_ECDHE_ECDSA_WITH_CAMELLIA_256_GCM_SHA384 \ - MBEDTLS_TLS_ECDHE_ECDSA_WITH_CAMELLIA_256_GCM_SHA384 -#define TLS_ECDHE_ECDSA_WITH_NULL_SHA MBEDTLS_TLS_ECDHE_ECDSA_WITH_NULL_SHA -#define TLS_ECDHE_ECDSA_WITH_RC4_128_SHA MBEDTLS_TLS_ECDHE_ECDSA_WITH_RC4_128_SHA -#define TLS_ECDHE_PSK_WITH_3DES_EDE_CBC_SHA MBEDTLS_TLS_ECDHE_PSK_WITH_3DES_EDE_CBC_SHA -#define TLS_ECDHE_PSK_WITH_AES_128_CBC_SHA MBEDTLS_TLS_ECDHE_PSK_WITH_AES_128_CBC_SHA -#define TLS_ECDHE_PSK_WITH_AES_128_CBC_SHA256 MBEDTLS_TLS_ECDHE_PSK_WITH_AES_128_CBC_SHA256 -#define TLS_ECDHE_PSK_WITH_AES_256_CBC_SHA MBEDTLS_TLS_ECDHE_PSK_WITH_AES_256_CBC_SHA -#define TLS_ECDHE_PSK_WITH_AES_256_CBC_SHA384 MBEDTLS_TLS_ECDHE_PSK_WITH_AES_256_CBC_SHA384 -#define TLS_ECDHE_PSK_WITH_CAMELLIA_128_CBC_SHA256 \ - MBEDTLS_TLS_ECDHE_PSK_WITH_CAMELLIA_128_CBC_SHA256 -#define TLS_ECDHE_PSK_WITH_CAMELLIA_256_CBC_SHA384 \ - MBEDTLS_TLS_ECDHE_PSK_WITH_CAMELLIA_256_CBC_SHA384 -#define TLS_ECDHE_PSK_WITH_NULL_SHA MBEDTLS_TLS_ECDHE_PSK_WITH_NULL_SHA -#define TLS_ECDHE_PSK_WITH_NULL_SHA256 MBEDTLS_TLS_ECDHE_PSK_WITH_NULL_SHA256 -#define TLS_ECDHE_PSK_WITH_NULL_SHA384 MBEDTLS_TLS_ECDHE_PSK_WITH_NULL_SHA384 -#define TLS_ECDHE_PSK_WITH_RC4_128_SHA MBEDTLS_TLS_ECDHE_PSK_WITH_RC4_128_SHA -#define TLS_ECDHE_RSA_WITH_3DES_EDE_CBC_SHA MBEDTLS_TLS_ECDHE_RSA_WITH_3DES_EDE_CBC_SHA -#define TLS_ECDHE_RSA_WITH_AES_128_CBC_SHA MBEDTLS_TLS_ECDHE_RSA_WITH_AES_128_CBC_SHA -#define TLS_ECDHE_RSA_WITH_AES_128_CBC_SHA256 MBEDTLS_TLS_ECDHE_RSA_WITH_AES_128_CBC_SHA256 -#define TLS_ECDHE_RSA_WITH_AES_128_GCM_SHA256 MBEDTLS_TLS_ECDHE_RSA_WITH_AES_128_GCM_SHA256 -#define TLS_ECDHE_RSA_WITH_AES_256_CBC_SHA MBEDTLS_TLS_ECDHE_RSA_WITH_AES_256_CBC_SHA -#define TLS_ECDHE_RSA_WITH_AES_256_CBC_SHA384 MBEDTLS_TLS_ECDHE_RSA_WITH_AES_256_CBC_SHA384 -#define TLS_ECDHE_RSA_WITH_AES_256_GCM_SHA384 MBEDTLS_TLS_ECDHE_RSA_WITH_AES_256_GCM_SHA384 -#define TLS_ECDHE_RSA_WITH_CAMELLIA_128_CBC_SHA256 \ - MBEDTLS_TLS_ECDHE_RSA_WITH_CAMELLIA_128_CBC_SHA256 -#define TLS_ECDHE_RSA_WITH_CAMELLIA_128_GCM_SHA256 \ - MBEDTLS_TLS_ECDHE_RSA_WITH_CAMELLIA_128_GCM_SHA256 -#define TLS_ECDHE_RSA_WITH_CAMELLIA_256_CBC_SHA384 \ - MBEDTLS_TLS_ECDHE_RSA_WITH_CAMELLIA_256_CBC_SHA384 -#define TLS_ECDHE_RSA_WITH_CAMELLIA_256_GCM_SHA384 \ - MBEDTLS_TLS_ECDHE_RSA_WITH_CAMELLIA_256_GCM_SHA384 -#define TLS_ECDHE_RSA_WITH_NULL_SHA MBEDTLS_TLS_ECDHE_RSA_WITH_NULL_SHA -#define TLS_ECDHE_RSA_WITH_RC4_128_SHA MBEDTLS_TLS_ECDHE_RSA_WITH_RC4_128_SHA -#define TLS_ECDH_ECDSA_WITH_3DES_EDE_CBC_SHA MBEDTLS_TLS_ECDH_ECDSA_WITH_3DES_EDE_CBC_SHA -#define TLS_ECDH_ECDSA_WITH_AES_128_CBC_SHA MBEDTLS_TLS_ECDH_ECDSA_WITH_AES_128_CBC_SHA -#define TLS_ECDH_ECDSA_WITH_AES_128_CBC_SHA256 MBEDTLS_TLS_ECDH_ECDSA_WITH_AES_128_CBC_SHA256 -#define TLS_ECDH_ECDSA_WITH_AES_128_GCM_SHA256 MBEDTLS_TLS_ECDH_ECDSA_WITH_AES_128_GCM_SHA256 -#define TLS_ECDH_ECDSA_WITH_AES_256_CBC_SHA MBEDTLS_TLS_ECDH_ECDSA_WITH_AES_256_CBC_SHA -#define TLS_ECDH_ECDSA_WITH_AES_256_CBC_SHA384 MBEDTLS_TLS_ECDH_ECDSA_WITH_AES_256_CBC_SHA384 -#define TLS_ECDH_ECDSA_WITH_AES_256_GCM_SHA384 MBEDTLS_TLS_ECDH_ECDSA_WITH_AES_256_GCM_SHA384 -#define TLS_ECDH_ECDSA_WITH_CAMELLIA_128_CBC_SHA256 \ - MBEDTLS_TLS_ECDH_ECDSA_WITH_CAMELLIA_128_CBC_SHA256 -#define TLS_ECDH_ECDSA_WITH_CAMELLIA_128_GCM_SHA256 \ - MBEDTLS_TLS_ECDH_ECDSA_WITH_CAMELLIA_128_GCM_SHA256 -#define TLS_ECDH_ECDSA_WITH_CAMELLIA_256_CBC_SHA384 \ - MBEDTLS_TLS_ECDH_ECDSA_WITH_CAMELLIA_256_CBC_SHA384 -#define TLS_ECDH_ECDSA_WITH_CAMELLIA_256_GCM_SHA384 \ - MBEDTLS_TLS_ECDH_ECDSA_WITH_CAMELLIA_256_GCM_SHA384 -#define TLS_ECDH_ECDSA_WITH_NULL_SHA MBEDTLS_TLS_ECDH_ECDSA_WITH_NULL_SHA -#define TLS_ECDH_ECDSA_WITH_RC4_128_SHA MBEDTLS_TLS_ECDH_ECDSA_WITH_RC4_128_SHA -#define TLS_ECDH_RSA_WITH_3DES_EDE_CBC_SHA MBEDTLS_TLS_ECDH_RSA_WITH_3DES_EDE_CBC_SHA -#define TLS_ECDH_RSA_WITH_AES_128_CBC_SHA MBEDTLS_TLS_ECDH_RSA_WITH_AES_128_CBC_SHA -#define TLS_ECDH_RSA_WITH_AES_128_CBC_SHA256 MBEDTLS_TLS_ECDH_RSA_WITH_AES_128_CBC_SHA256 -#define TLS_ECDH_RSA_WITH_AES_128_GCM_SHA256 MBEDTLS_TLS_ECDH_RSA_WITH_AES_128_GCM_SHA256 -#define TLS_ECDH_RSA_WITH_AES_256_CBC_SHA MBEDTLS_TLS_ECDH_RSA_WITH_AES_256_CBC_SHA -#define TLS_ECDH_RSA_WITH_AES_256_CBC_SHA384 MBEDTLS_TLS_ECDH_RSA_WITH_AES_256_CBC_SHA384 -#define TLS_ECDH_RSA_WITH_AES_256_GCM_SHA384 MBEDTLS_TLS_ECDH_RSA_WITH_AES_256_GCM_SHA384 -#define TLS_ECDH_RSA_WITH_CAMELLIA_128_CBC_SHA256 MBEDTLS_TLS_ECDH_RSA_WITH_CAMELLIA_128_CBC_SHA256 -#define TLS_ECDH_RSA_WITH_CAMELLIA_128_GCM_SHA256 MBEDTLS_TLS_ECDH_RSA_WITH_CAMELLIA_128_GCM_SHA256 -#define TLS_ECDH_RSA_WITH_CAMELLIA_256_CBC_SHA384 MBEDTLS_TLS_ECDH_RSA_WITH_CAMELLIA_256_CBC_SHA384 -#define TLS_ECDH_RSA_WITH_CAMELLIA_256_GCM_SHA384 MBEDTLS_TLS_ECDH_RSA_WITH_CAMELLIA_256_GCM_SHA384 -#define TLS_ECDH_RSA_WITH_NULL_SHA MBEDTLS_TLS_ECDH_RSA_WITH_NULL_SHA -#define TLS_ECDH_RSA_WITH_RC4_128_SHA MBEDTLS_TLS_ECDH_RSA_WITH_RC4_128_SHA -#define TLS_EXT_ALPN MBEDTLS_TLS_EXT_ALPN -#define TLS_EXT_ENCRYPT_THEN_MAC MBEDTLS_TLS_EXT_ENCRYPT_THEN_MAC -#define TLS_EXT_EXTENDED_MASTER_SECRET MBEDTLS_TLS_EXT_EXTENDED_MASTER_SECRET -#define TLS_EXT_MAX_FRAGMENT_LENGTH MBEDTLS_TLS_EXT_MAX_FRAGMENT_LENGTH -#define TLS_EXT_RENEGOTIATION_INFO MBEDTLS_TLS_EXT_RENEGOTIATION_INFO -#define TLS_EXT_SERVERNAME MBEDTLS_TLS_EXT_SERVERNAME -#define TLS_EXT_SERVERNAME_HOSTNAME MBEDTLS_TLS_EXT_SERVERNAME_HOSTNAME -#define TLS_EXT_SESSION_TICKET MBEDTLS_TLS_EXT_SESSION_TICKET -#define TLS_EXT_SIG_ALG MBEDTLS_TLS_EXT_SIG_ALG -#define TLS_EXT_SUPPORTED_ELLIPTIC_CURVES MBEDTLS_TLS_EXT_SUPPORTED_ELLIPTIC_CURVES -#define TLS_EXT_SUPPORTED_POINT_FORMATS MBEDTLS_TLS_EXT_SUPPORTED_POINT_FORMATS -#define TLS_EXT_SUPPORTED_POINT_FORMATS_PRESENT MBEDTLS_TLS_EXT_SUPPORTED_POINT_FORMATS_PRESENT -#define TLS_EXT_TRUNCATED_HMAC MBEDTLS_TLS_EXT_TRUNCATED_HMAC -#define TLS_PSK_WITH_3DES_EDE_CBC_SHA MBEDTLS_TLS_PSK_WITH_3DES_EDE_CBC_SHA -#define TLS_PSK_WITH_AES_128_CBC_SHA MBEDTLS_TLS_PSK_WITH_AES_128_CBC_SHA -#define TLS_PSK_WITH_AES_128_CBC_SHA256 MBEDTLS_TLS_PSK_WITH_AES_128_CBC_SHA256 -#define TLS_PSK_WITH_AES_128_CCM MBEDTLS_TLS_PSK_WITH_AES_128_CCM -#define TLS_PSK_WITH_AES_128_CCM_8 MBEDTLS_TLS_PSK_WITH_AES_128_CCM_8 -#define TLS_PSK_WITH_AES_128_GCM_SHA256 MBEDTLS_TLS_PSK_WITH_AES_128_GCM_SHA256 -#define TLS_PSK_WITH_AES_256_CBC_SHA MBEDTLS_TLS_PSK_WITH_AES_256_CBC_SHA -#define TLS_PSK_WITH_AES_256_CBC_SHA384 MBEDTLS_TLS_PSK_WITH_AES_256_CBC_SHA384 -#define TLS_PSK_WITH_AES_256_CCM MBEDTLS_TLS_PSK_WITH_AES_256_CCM -#define TLS_PSK_WITH_AES_256_CCM_8 MBEDTLS_TLS_PSK_WITH_AES_256_CCM_8 -#define TLS_PSK_WITH_AES_256_GCM_SHA384 MBEDTLS_TLS_PSK_WITH_AES_256_GCM_SHA384 -#define TLS_PSK_WITH_CAMELLIA_128_CBC_SHA256 MBEDTLS_TLS_PSK_WITH_CAMELLIA_128_CBC_SHA256 -#define TLS_PSK_WITH_CAMELLIA_128_GCM_SHA256 MBEDTLS_TLS_PSK_WITH_CAMELLIA_128_GCM_SHA256 -#define TLS_PSK_WITH_CAMELLIA_256_CBC_SHA384 MBEDTLS_TLS_PSK_WITH_CAMELLIA_256_CBC_SHA384 -#define TLS_PSK_WITH_CAMELLIA_256_GCM_SHA384 MBEDTLS_TLS_PSK_WITH_CAMELLIA_256_GCM_SHA384 -#define TLS_PSK_WITH_NULL_SHA MBEDTLS_TLS_PSK_WITH_NULL_SHA -#define TLS_PSK_WITH_NULL_SHA256 MBEDTLS_TLS_PSK_WITH_NULL_SHA256 -#define TLS_PSK_WITH_NULL_SHA384 MBEDTLS_TLS_PSK_WITH_NULL_SHA384 -#define TLS_PSK_WITH_RC4_128_SHA MBEDTLS_TLS_PSK_WITH_RC4_128_SHA -#define TLS_RSA_PSK_WITH_3DES_EDE_CBC_SHA MBEDTLS_TLS_RSA_PSK_WITH_3DES_EDE_CBC_SHA -#define TLS_RSA_PSK_WITH_AES_128_CBC_SHA MBEDTLS_TLS_RSA_PSK_WITH_AES_128_CBC_SHA -#define TLS_RSA_PSK_WITH_AES_128_CBC_SHA256 MBEDTLS_TLS_RSA_PSK_WITH_AES_128_CBC_SHA256 -#define TLS_RSA_PSK_WITH_AES_128_GCM_SHA256 MBEDTLS_TLS_RSA_PSK_WITH_AES_128_GCM_SHA256 -#define TLS_RSA_PSK_WITH_AES_256_CBC_SHA MBEDTLS_TLS_RSA_PSK_WITH_AES_256_CBC_SHA -#define TLS_RSA_PSK_WITH_AES_256_CBC_SHA384 MBEDTLS_TLS_RSA_PSK_WITH_AES_256_CBC_SHA384 -#define TLS_RSA_PSK_WITH_AES_256_GCM_SHA384 MBEDTLS_TLS_RSA_PSK_WITH_AES_256_GCM_SHA384 -#define TLS_RSA_PSK_WITH_CAMELLIA_128_CBC_SHA256 MBEDTLS_TLS_RSA_PSK_WITH_CAMELLIA_128_CBC_SHA256 -#define TLS_RSA_PSK_WITH_CAMELLIA_128_GCM_SHA256 MBEDTLS_TLS_RSA_PSK_WITH_CAMELLIA_128_GCM_SHA256 -#define TLS_RSA_PSK_WITH_CAMELLIA_256_CBC_SHA384 MBEDTLS_TLS_RSA_PSK_WITH_CAMELLIA_256_CBC_SHA384 -#define TLS_RSA_PSK_WITH_CAMELLIA_256_GCM_SHA384 MBEDTLS_TLS_RSA_PSK_WITH_CAMELLIA_256_GCM_SHA384 -#define TLS_RSA_PSK_WITH_NULL_SHA MBEDTLS_TLS_RSA_PSK_WITH_NULL_SHA -#define TLS_RSA_PSK_WITH_NULL_SHA256 MBEDTLS_TLS_RSA_PSK_WITH_NULL_SHA256 -#define TLS_RSA_PSK_WITH_NULL_SHA384 MBEDTLS_TLS_RSA_PSK_WITH_NULL_SHA384 -#define TLS_RSA_PSK_WITH_RC4_128_SHA MBEDTLS_TLS_RSA_PSK_WITH_RC4_128_SHA -#define TLS_RSA_WITH_3DES_EDE_CBC_SHA MBEDTLS_TLS_RSA_WITH_3DES_EDE_CBC_SHA -#define TLS_RSA_WITH_AES_128_CBC_SHA MBEDTLS_TLS_RSA_WITH_AES_128_CBC_SHA -#define TLS_RSA_WITH_AES_128_CBC_SHA256 MBEDTLS_TLS_RSA_WITH_AES_128_CBC_SHA256 -#define TLS_RSA_WITH_AES_128_CCM MBEDTLS_TLS_RSA_WITH_AES_128_CCM -#define TLS_RSA_WITH_AES_128_CCM_8 MBEDTLS_TLS_RSA_WITH_AES_128_CCM_8 -#define TLS_RSA_WITH_AES_128_GCM_SHA256 MBEDTLS_TLS_RSA_WITH_AES_128_GCM_SHA256 -#define TLS_RSA_WITH_AES_256_CBC_SHA MBEDTLS_TLS_RSA_WITH_AES_256_CBC_SHA -#define TLS_RSA_WITH_AES_256_CBC_SHA256 MBEDTLS_TLS_RSA_WITH_AES_256_CBC_SHA256 -#define TLS_RSA_WITH_AES_256_CCM MBEDTLS_TLS_RSA_WITH_AES_256_CCM -#define TLS_RSA_WITH_AES_256_CCM_8 MBEDTLS_TLS_RSA_WITH_AES_256_CCM_8 -#define TLS_RSA_WITH_AES_256_GCM_SHA384 MBEDTLS_TLS_RSA_WITH_AES_256_GCM_SHA384 -#define TLS_RSA_WITH_CAMELLIA_128_CBC_SHA MBEDTLS_TLS_RSA_WITH_CAMELLIA_128_CBC_SHA -#define TLS_RSA_WITH_CAMELLIA_128_CBC_SHA256 MBEDTLS_TLS_RSA_WITH_CAMELLIA_128_CBC_SHA256 -#define TLS_RSA_WITH_CAMELLIA_128_GCM_SHA256 MBEDTLS_TLS_RSA_WITH_CAMELLIA_128_GCM_SHA256 -#define TLS_RSA_WITH_CAMELLIA_256_CBC_SHA MBEDTLS_TLS_RSA_WITH_CAMELLIA_256_CBC_SHA -#define TLS_RSA_WITH_CAMELLIA_256_CBC_SHA256 MBEDTLS_TLS_RSA_WITH_CAMELLIA_256_CBC_SHA256 -#define TLS_RSA_WITH_CAMELLIA_256_GCM_SHA384 MBEDTLS_TLS_RSA_WITH_CAMELLIA_256_GCM_SHA384 -#define TLS_RSA_WITH_DES_CBC_SHA MBEDTLS_TLS_RSA_WITH_DES_CBC_SHA -#define TLS_RSA_WITH_NULL_MD5 MBEDTLS_TLS_RSA_WITH_NULL_MD5 -#define TLS_RSA_WITH_NULL_SHA MBEDTLS_TLS_RSA_WITH_NULL_SHA -#define TLS_RSA_WITH_NULL_SHA256 MBEDTLS_TLS_RSA_WITH_NULL_SHA256 -#define TLS_RSA_WITH_RC4_128_MD5 MBEDTLS_TLS_RSA_WITH_RC4_128_MD5 -#define TLS_RSA_WITH_RC4_128_SHA MBEDTLS_TLS_RSA_WITH_RC4_128_SHA -#define X509_CRT_VERSION_1 MBEDTLS_X509_CRT_VERSION_1 -#define X509_CRT_VERSION_2 MBEDTLS_X509_CRT_VERSION_2 -#define X509_CRT_VERSION_3 MBEDTLS_X509_CRT_VERSION_3 -#define X509_FORMAT_DER MBEDTLS_X509_FORMAT_DER -#define X509_FORMAT_PEM MBEDTLS_X509_FORMAT_PEM -#define X509_MAX_DN_NAME_SIZE MBEDTLS_X509_MAX_DN_NAME_SIZE -#define X509_RFC5280_MAX_SERIAL_LEN MBEDTLS_X509_RFC5280_MAX_SERIAL_LEN -#define X509_RFC5280_UTC_TIME_LEN MBEDTLS_X509_RFC5280_UTC_TIME_LEN -#define XTEA_DECRYPT MBEDTLS_XTEA_DECRYPT -#define XTEA_ENCRYPT MBEDTLS_XTEA_ENCRYPT -#define _asn1_bitstring mbedtls_asn1_bitstring -#define _asn1_buf mbedtls_asn1_buf -#define _asn1_named_data mbedtls_asn1_named_data -#define _asn1_sequence mbedtls_asn1_sequence -#define _ssl_cache_context mbedtls_ssl_cache_context -#define _ssl_cache_entry mbedtls_ssl_cache_entry -#define _ssl_ciphersuite_t mbedtls_ssl_ciphersuite_t -#define _ssl_context mbedtls_ssl_context -#define _ssl_flight_item mbedtls_ssl_flight_item -#define _ssl_handshake_params mbedtls_ssl_handshake_params -#define _ssl_key_cert mbedtls_ssl_key_cert -#define _ssl_premaster_secret mbedtls_ssl_premaster_secret -#define _ssl_session mbedtls_ssl_session -#define _ssl_transform mbedtls_ssl_transform -#define _x509_crl mbedtls_x509_crl -#define _x509_crl_entry mbedtls_x509_crl_entry -#define _x509_crt mbedtls_x509_crt -#define _x509_csr mbedtls_x509_csr -#define _x509_time mbedtls_x509_time -#define _x509write_cert mbedtls_x509write_cert -#define _x509write_csr mbedtls_x509write_csr -#define aes_context mbedtls_aes_context -#define aes_crypt_cbc mbedtls_aes_crypt_cbc -#define aes_crypt_cfb128 mbedtls_aes_crypt_cfb128 -#define aes_crypt_cfb8 mbedtls_aes_crypt_cfb8 -#define aes_crypt_ctr mbedtls_aes_crypt_ctr -#define aes_crypt_ecb mbedtls_aes_crypt_ecb -#define aes_free mbedtls_aes_free -#define aes_init mbedtls_aes_init -#define aes_self_test mbedtls_aes_self_test -#define aes_setkey_dec mbedtls_aes_setkey_dec -#define aes_setkey_enc mbedtls_aes_setkey_enc -#define aesni_crypt_ecb mbedtls_aesni_crypt_ecb -#define aesni_gcm_mult mbedtls_aesni_gcm_mult -#define aesni_inverse_key mbedtls_aesni_inverse_key -#define aesni_setkey_enc mbedtls_aesni_setkey_enc -#define aesni_supports mbedtls_aesni_has_support -#define alarmed mbedtls_timing_alarmed -#define arc4_context mbedtls_arc4_context -#define arc4_crypt mbedtls_arc4_crypt -#define arc4_free mbedtls_arc4_free -#define arc4_init mbedtls_arc4_init -#define arc4_self_test mbedtls_arc4_self_test -#define arc4_setup mbedtls_arc4_setup -#define asn1_bitstring mbedtls_asn1_bitstring -#define asn1_buf mbedtls_asn1_buf -#define asn1_find_named_data mbedtls_asn1_find_named_data -#define asn1_free_named_data mbedtls_asn1_free_named_data -#define asn1_free_named_data_list mbedtls_asn1_free_named_data_list -#define asn1_get_alg mbedtls_asn1_get_alg -#define asn1_get_alg_null mbedtls_asn1_get_alg_null -#define asn1_get_bitstring mbedtls_asn1_get_bitstring -#define asn1_get_bitstring_null mbedtls_asn1_get_bitstring_null -#define asn1_get_bool mbedtls_asn1_get_bool -#define asn1_get_int mbedtls_asn1_get_int -#define asn1_get_len mbedtls_asn1_get_len -#define asn1_get_mpi mbedtls_asn1_get_mpi -#define asn1_get_sequence_of mbedtls_asn1_get_sequence_of -#define asn1_get_tag mbedtls_asn1_get_tag -#define asn1_named_data mbedtls_asn1_named_data -#define asn1_sequence mbedtls_asn1_sequence -#define asn1_store_named_data mbedtls_asn1_store_named_data -#define asn1_write_algorithm_identifier mbedtls_asn1_write_algorithm_identifier -#define asn1_write_bitstring mbedtls_asn1_write_bitstring -#define asn1_write_bool mbedtls_asn1_write_bool -#define asn1_write_ia5_string mbedtls_asn1_write_ia5_string -#define asn1_write_int mbedtls_asn1_write_int -#define asn1_write_len mbedtls_asn1_write_len -#define asn1_write_mpi mbedtls_asn1_write_mpi -#define asn1_write_null mbedtls_asn1_write_null -#define asn1_write_octet_string mbedtls_asn1_write_octet_string -#define asn1_write_oid mbedtls_asn1_write_oid -#define asn1_write_printable_string mbedtls_asn1_write_printable_string -#define asn1_write_raw_buffer mbedtls_asn1_write_raw_buffer -#define asn1_write_tag mbedtls_asn1_write_tag -#define base64_decode mbedtls_base64_decode -#define base64_encode mbedtls_base64_encode -#define base64_self_test mbedtls_base64_self_test -#define blowfish_context mbedtls_blowfish_context -#define blowfish_crypt_cbc mbedtls_blowfish_crypt_cbc -#define blowfish_crypt_cfb64 mbedtls_blowfish_crypt_cfb64 -#define blowfish_crypt_ctr mbedtls_blowfish_crypt_ctr -#define blowfish_crypt_ecb mbedtls_blowfish_crypt_ecb -#define blowfish_free mbedtls_blowfish_free -#define blowfish_init mbedtls_blowfish_init -#define blowfish_setkey mbedtls_blowfish_setkey -#define camellia_context mbedtls_camellia_context -#define camellia_crypt_cbc mbedtls_camellia_crypt_cbc -#define camellia_crypt_cfb128 mbedtls_camellia_crypt_cfb128 -#define camellia_crypt_ctr mbedtls_camellia_crypt_ctr -#define camellia_crypt_ecb mbedtls_camellia_crypt_ecb -#define camellia_free mbedtls_camellia_free -#define camellia_init mbedtls_camellia_init -#define camellia_self_test mbedtls_camellia_self_test -#define camellia_setkey_dec mbedtls_camellia_setkey_dec -#define camellia_setkey_enc mbedtls_camellia_setkey_enc -#define ccm_auth_decrypt mbedtls_ccm_auth_decrypt -#define ccm_context mbedtls_ccm_context -#define ccm_encrypt_and_tag mbedtls_ccm_encrypt_and_tag -#define ccm_free mbedtls_ccm_free -#define ccm_init mbedtls_ccm_init -#define ccm_self_test mbedtls_ccm_self_test -#define cipher_auth_decrypt mbedtls_cipher_auth_decrypt -#define cipher_auth_encrypt mbedtls_cipher_auth_encrypt -#define cipher_base_t mbedtls_cipher_base_t -#define cipher_check_tag mbedtls_cipher_check_tag -#define cipher_context_t mbedtls_cipher_context_t -#define cipher_crypt mbedtls_cipher_crypt -#define cipher_definition_t mbedtls_cipher_definition_t -#define cipher_definitions mbedtls_cipher_definitions -#define cipher_finish mbedtls_cipher_finish -#define cipher_free mbedtls_cipher_free -#define cipher_get_block_size mbedtls_cipher_get_block_size -#define cipher_get_cipher_mode mbedtls_cipher_get_cipher_mode -#define cipher_get_iv_size mbedtls_cipher_get_iv_size -#define cipher_get_key_size mbedtls_cipher_get_key_bitlen -#define cipher_get_name mbedtls_cipher_get_name -#define cipher_get_operation mbedtls_cipher_get_operation -#define cipher_get_type mbedtls_cipher_get_type -#define cipher_id_t mbedtls_cipher_id_t -#define cipher_info_from_string mbedtls_cipher_info_from_string -#define cipher_info_from_type mbedtls_cipher_info_from_type -#define cipher_info_from_values mbedtls_cipher_info_from_values -#define cipher_info_t mbedtls_cipher_info_t -#define cipher_init mbedtls_cipher_init -#define cipher_init_ctx mbedtls_cipher_setup -#define cipher_list mbedtls_cipher_list -#define cipher_mode_t mbedtls_cipher_mode_t -#define cipher_padding_t mbedtls_cipher_padding_t -#define cipher_reset mbedtls_cipher_reset -#define cipher_set_iv mbedtls_cipher_set_iv -#define cipher_set_padding_mode mbedtls_cipher_set_padding_mode -#define cipher_setkey mbedtls_cipher_setkey -#define cipher_type_t mbedtls_cipher_type_t -#define cipher_update mbedtls_cipher_update -#define cipher_update_ad mbedtls_cipher_update_ad -#define cipher_write_tag mbedtls_cipher_write_tag -#define ctr_drbg_context mbedtls_ctr_drbg_context -#define ctr_drbg_free mbedtls_ctr_drbg_free -#define ctr_drbg_init mbedtls_ctr_drbg_init -#define ctr_drbg_random mbedtls_ctr_drbg_random -#define ctr_drbg_random_with_add mbedtls_ctr_drbg_random_with_add -#define ctr_drbg_reseed mbedtls_ctr_drbg_reseed -#define ctr_drbg_self_test mbedtls_ctr_drbg_self_test -#define ctr_drbg_set_entropy_len mbedtls_ctr_drbg_set_entropy_len -#define ctr_drbg_set_prediction_resistance mbedtls_ctr_drbg_set_prediction_resistance -#define ctr_drbg_set_reseed_interval mbedtls_ctr_drbg_set_reseed_interval -#define ctr_drbg_update mbedtls_ctr_drbg_update -#define ctr_drbg_update_seed_file mbedtls_ctr_drbg_update_seed_file -#define ctr_drbg_write_seed_file mbedtls_ctr_drbg_write_seed_file -#define debug_print_buf mbedtls_debug_print_buf -#define debug_print_crt mbedtls_debug_print_crt -#define debug_print_ecp mbedtls_debug_print_ecp -#define debug_print_mpi mbedtls_debug_print_mpi -#define debug_print_msg mbedtls_debug_print_msg -#define debug_print_ret mbedtls_debug_print_ret -#define debug_set_threshold mbedtls_debug_set_threshold -#define des3_context mbedtls_des3_context -#define des3_crypt_cbc mbedtls_des3_crypt_cbc -#define des3_crypt_ecb mbedtls_des3_crypt_ecb -#define des3_free mbedtls_des3_free -#define des3_init mbedtls_des3_init -#define des3_set2key_dec mbedtls_des3_set2key_dec -#define des3_set2key_enc mbedtls_des3_set2key_enc -#define des3_set3key_dec mbedtls_des3_set3key_dec -#define des3_set3key_enc mbedtls_des3_set3key_enc -#define des_context mbedtls_des_context -#define des_crypt_cbc mbedtls_des_crypt_cbc -#define des_crypt_ecb mbedtls_des_crypt_ecb -#define des_free mbedtls_des_free -#define des_init mbedtls_des_init -#define des_key_check_key_parity mbedtls_des_key_check_key_parity -#define des_key_check_weak mbedtls_des_key_check_weak -#define des_key_set_parity mbedtls_des_key_set_parity -#define des_self_test mbedtls_des_self_test -#define des_setkey_dec mbedtls_des_setkey_dec -#define des_setkey_enc mbedtls_des_setkey_enc -#define dhm_calc_secret mbedtls_dhm_calc_secret -#define dhm_context mbedtls_dhm_context -#define dhm_free mbedtls_dhm_free -#define dhm_init mbedtls_dhm_init -#define dhm_make_params mbedtls_dhm_make_params -#define dhm_make_public mbedtls_dhm_make_public -#define dhm_parse_dhm mbedtls_dhm_parse_dhm -#define dhm_parse_dhmfile mbedtls_dhm_parse_dhmfile -#define dhm_read_params mbedtls_dhm_read_params -#define dhm_read_public mbedtls_dhm_read_public -#define dhm_self_test mbedtls_dhm_self_test -#define ecdh_calc_secret mbedtls_ecdh_calc_secret -#define ecdh_compute_shared mbedtls_ecdh_compute_shared -#define ecdh_context mbedtls_ecdh_context -#define ecdh_free mbedtls_ecdh_free -#define ecdh_gen_public mbedtls_ecdh_gen_public -#define ecdh_get_params mbedtls_ecdh_get_params -#define ecdh_init mbedtls_ecdh_init -#define ecdh_make_params mbedtls_ecdh_make_params -#define ecdh_make_public mbedtls_ecdh_make_public -#define ecdh_read_params mbedtls_ecdh_read_params -#define ecdh_read_public mbedtls_ecdh_read_public -#define ecdh_side mbedtls_ecdh_side -#define ecdsa_context mbedtls_ecdsa_context -#define ecdsa_free mbedtls_ecdsa_free -#define ecdsa_from_keypair mbedtls_ecdsa_from_keypair -#define ecdsa_genkey mbedtls_ecdsa_genkey -#define ecdsa_info mbedtls_ecdsa_info -#define ecdsa_init mbedtls_ecdsa_init -#define ecdsa_read_signature mbedtls_ecdsa_read_signature -#define ecdsa_sign mbedtls_ecdsa_sign -#define ecdsa_sign_det mbedtls_ecdsa_sign_det -#define ecdsa_verify mbedtls_ecdsa_verify -#define ecdsa_write_signature mbedtls_ecdsa_write_signature -#define ecdsa_write_signature_det mbedtls_ecdsa_write_signature_det -#define eckey_info mbedtls_eckey_info -#define eckeydh_info mbedtls_eckeydh_info -#define ecp_check_privkey mbedtls_ecp_check_privkey -#define ecp_check_pub_priv mbedtls_ecp_check_pub_priv -#define ecp_check_pubkey mbedtls_ecp_check_pubkey -#define ecp_copy mbedtls_ecp_copy -#define ecp_curve_info mbedtls_ecp_curve_info -#define ecp_curve_info_from_grp_id mbedtls_ecp_curve_info_from_grp_id -#define ecp_curve_info_from_name mbedtls_ecp_curve_info_from_name -#define ecp_curve_info_from_tls_id mbedtls_ecp_curve_info_from_tls_id -#define ecp_curve_list mbedtls_ecp_curve_list -#define ecp_gen_key mbedtls_ecp_gen_key -#define ecp_gen_keypair mbedtls_ecp_gen_keypair -#define ecp_group mbedtls_ecp_group -#define ecp_group_copy mbedtls_ecp_group_copy -#define ecp_group_free mbedtls_ecp_group_free -#define ecp_group_id mbedtls_ecp_group_id -#define ecp_group_init mbedtls_ecp_group_init -#define ecp_grp_id_list mbedtls_ecp_grp_id_list -#define ecp_is_zero mbedtls_ecp_is_zero -#define ecp_keypair mbedtls_ecp_keypair -#define ecp_keypair_free mbedtls_ecp_keypair_free -#define ecp_keypair_init mbedtls_ecp_keypair_init -#define ecp_mul mbedtls_ecp_mul -#define ecp_point mbedtls_ecp_point -#define ecp_point_free mbedtls_ecp_point_free -#define ecp_point_init mbedtls_ecp_point_init -#define ecp_point_read_binary mbedtls_ecp_point_read_binary -#define ecp_point_read_string mbedtls_ecp_point_read_string -#define ecp_point_write_binary mbedtls_ecp_point_write_binary -#define ecp_self_test mbedtls_ecp_self_test -#define ecp_set_zero mbedtls_ecp_set_zero -#define ecp_tls_read_group mbedtls_ecp_tls_read_group -#define ecp_tls_read_point mbedtls_ecp_tls_read_point -#define ecp_tls_write_group mbedtls_ecp_tls_write_group -#define ecp_tls_write_point mbedtls_ecp_tls_write_point -#define ecp_use_known_dp mbedtls_ecp_group_load -#define entropy_add_source mbedtls_entropy_add_source -#define entropy_context mbedtls_entropy_context -#define entropy_free mbedtls_entropy_free -#define entropy_func mbedtls_entropy_func -#define entropy_gather mbedtls_entropy_gather -#define entropy_init mbedtls_entropy_init -#define entropy_self_test mbedtls_entropy_self_test -#define entropy_update_manual mbedtls_entropy_update_manual -#define entropy_update_seed_file mbedtls_entropy_update_seed_file -#define entropy_write_seed_file mbedtls_entropy_write_seed_file -#define error_strerror mbedtls_strerror -#define f_source_ptr mbedtls_entropy_f_source_ptr -#define gcm_auth_decrypt mbedtls_gcm_auth_decrypt -#define gcm_context mbedtls_gcm_context -#define gcm_crypt_and_tag mbedtls_gcm_crypt_and_tag -#define gcm_finish mbedtls_gcm_finish -#define gcm_free mbedtls_gcm_free -#define gcm_init mbedtls_gcm_init -#define gcm_self_test mbedtls_gcm_self_test -#define gcm_starts mbedtls_gcm_starts -#define gcm_update mbedtls_gcm_update -#define get_timer mbedtls_timing_get_timer -#define hardclock mbedtls_timing_hardclock -#define hardclock_poll mbedtls_hardclock_poll -#define havege_free mbedtls_havege_free -#define havege_init mbedtls_havege_init -#define havege_poll mbedtls_havege_poll -#define havege_random mbedtls_havege_random -#define havege_state mbedtls_havege_state -#define hmac_drbg_context mbedtls_hmac_drbg_context -#define hmac_drbg_free mbedtls_hmac_drbg_free -#define hmac_drbg_init mbedtls_hmac_drbg_init -#define hmac_drbg_random mbedtls_hmac_drbg_random -#define hmac_drbg_random_with_add mbedtls_hmac_drbg_random_with_add -#define hmac_drbg_reseed mbedtls_hmac_drbg_reseed -#define hmac_drbg_self_test mbedtls_hmac_drbg_self_test -#define hmac_drbg_set_entropy_len mbedtls_hmac_drbg_set_entropy_len -#define hmac_drbg_set_prediction_resistance mbedtls_hmac_drbg_set_prediction_resistance -#define hmac_drbg_set_reseed_interval mbedtls_hmac_drbg_set_reseed_interval -#define hmac_drbg_update mbedtls_hmac_drbg_update -#define hmac_drbg_update_seed_file mbedtls_hmac_drbg_update_seed_file -#define hmac_drbg_write_seed_file mbedtls_hmac_drbg_write_seed_file -#define hr_time mbedtls_timing_hr_time -#define key_exchange_type_t mbedtls_key_exchange_type_t -#define md mbedtls_md -#define md2 mbedtls_md2 -#define md2_context mbedtls_md2_context -#define md2_finish mbedtls_md2_finish -#define md2_free mbedtls_md2_free -#define md2_info mbedtls_md2_info -#define md2_init mbedtls_md2_init -#define md2_process mbedtls_md2_process -#define md2_self_test mbedtls_md2_self_test -#define md2_starts mbedtls_md2_starts -#define md2_update mbedtls_md2_update -#define md4 mbedtls_md4 -#define md4_context mbedtls_md4_context -#define md4_finish mbedtls_md4_finish -#define md4_free mbedtls_md4_free -#define md4_info mbedtls_md4_info -#define md4_init mbedtls_md4_init -#define md4_process mbedtls_md4_process -#define md4_self_test mbedtls_md4_self_test -#define md4_starts mbedtls_md4_starts -#define md4_update mbedtls_md4_update -#define md5 mbedtls_md5 -#define md5_context mbedtls_md5_context -#define md5_finish mbedtls_md5_finish -#define md5_free mbedtls_md5_free -#define md5_info mbedtls_md5_info -#define md5_init mbedtls_md5_init -#define md5_process mbedtls_md5_process -#define md5_self_test mbedtls_md5_self_test -#define md5_starts mbedtls_md5_starts -#define md5_update mbedtls_md5_update -#define md_context_t mbedtls_md_context_t -#define md_file mbedtls_md_file -#define md_finish mbedtls_md_finish -#define md_free mbedtls_md_free -#define md_get_name mbedtls_md_get_name -#define md_get_size mbedtls_md_get_size -#define md_get_type mbedtls_md_get_type -#define md_hmac mbedtls_md_hmac -#define md_hmac_finish mbedtls_md_hmac_finish -#define md_hmac_reset mbedtls_md_hmac_reset -#define md_hmac_starts mbedtls_md_hmac_starts -#define md_hmac_update mbedtls_md_hmac_update -#define md_info_from_string mbedtls_md_info_from_string -#define md_info_from_type mbedtls_md_info_from_type -#define md_info_t mbedtls_md_info_t -#define md_init mbedtls_md_init -#define md_init_ctx mbedtls_md_init_ctx -#define md_list mbedtls_md_list -#define md_process mbedtls_md_process -#define md_starts mbedtls_md_starts -#define md_type_t mbedtls_md_type_t -#define md_update mbedtls_md_update -#define memory_buffer_alloc_cur_get mbedtls_memory_buffer_alloc_cur_get -#define memory_buffer_alloc_free mbedtls_memory_buffer_alloc_free -#define memory_buffer_alloc_init mbedtls_memory_buffer_alloc_init -#define memory_buffer_alloc_max_get mbedtls_memory_buffer_alloc_max_get -#define memory_buffer_alloc_max_reset mbedtls_memory_buffer_alloc_max_reset -#define memory_buffer_alloc_self_test mbedtls_memory_buffer_alloc_self_test -#define memory_buffer_alloc_status mbedtls_memory_buffer_alloc_status -#define memory_buffer_alloc_verify mbedtls_memory_buffer_alloc_verify -#define memory_buffer_set_verify mbedtls_memory_buffer_set_verify -#define mpi mbedtls_mpi -#define mpi_add_abs mbedtls_mpi_add_abs -#define mpi_add_int mbedtls_mpi_add_int -#define mpi_add_mpi mbedtls_mpi_add_mpi -#define mpi_cmp_abs mbedtls_mpi_cmp_abs -#define mpi_cmp_int mbedtls_mpi_cmp_int -#define mpi_cmp_mpi mbedtls_mpi_cmp_mpi -#define mpi_copy mbedtls_mpi_copy -#define mpi_div_int mbedtls_mpi_div_int -#define mpi_div_mpi mbedtls_mpi_div_mpi -#define mpi_exp_mod mbedtls_mpi_exp_mod -#define mpi_fill_random mbedtls_mpi_fill_random -#define mpi_free mbedtls_mpi_free -#define mpi_gcd mbedtls_mpi_gcd -#define mpi_gen_prime mbedtls_mpi_gen_prime -#define mpi_get_bit mbedtls_mpi_get_bit -#define mpi_grow mbedtls_mpi_grow -#define mpi_init mbedtls_mpi_init -#define mpi_inv_mod mbedtls_mpi_inv_mod -#define mpi_is_prime mbedtls_mpi_is_prime -#define mpi_lsb mbedtls_mpi_lsb -#define mpi_lset mbedtls_mpi_lset -#define mpi_mod_int mbedtls_mpi_mod_int -#define mpi_mod_mpi mbedtls_mpi_mod_mpi -#define mpi_msb mbedtls_mpi_bitlen -#define mpi_mul_int mbedtls_mpi_mul_int -#define mpi_mul_mpi mbedtls_mpi_mul_mpi -#define mpi_read_binary mbedtls_mpi_read_binary -#define mpi_read_file mbedtls_mpi_read_file -#define mpi_read_string mbedtls_mpi_read_string -#define mpi_safe_cond_assign mbedtls_mpi_safe_cond_assign -#define mpi_safe_cond_swap mbedtls_mpi_safe_cond_swap -#define mpi_self_test mbedtls_mpi_self_test -#define mpi_set_bit mbedtls_mpi_set_bit -#define mpi_shift_l mbedtls_mpi_shift_l -#define mpi_shift_r mbedtls_mpi_shift_r -#define mpi_shrink mbedtls_mpi_shrink -#define mpi_size mbedtls_mpi_size -#define mpi_sub_abs mbedtls_mpi_sub_abs -#define mpi_sub_int mbedtls_mpi_sub_int -#define mpi_sub_mpi mbedtls_mpi_sub_mpi -#define mpi_swap mbedtls_mpi_swap -#define mpi_write_binary mbedtls_mpi_write_binary -#define mpi_write_file mbedtls_mpi_write_file -#define mpi_write_string mbedtls_mpi_write_string -#define net_accept mbedtls_net_accept -#define net_bind mbedtls_net_bind -#define net_close mbedtls_net_free -#define net_connect mbedtls_net_connect -#define net_recv mbedtls_net_recv -#define net_recv_timeout mbedtls_net_recv_timeout -#define net_send mbedtls_net_send -#define net_set_block mbedtls_net_set_block -#define net_set_nonblock mbedtls_net_set_nonblock -#define net_usleep mbedtls_net_usleep -#define oid_descriptor_t mbedtls_oid_descriptor_t -#define oid_get_attr_short_name mbedtls_oid_get_attr_short_name -#define oid_get_cipher_alg mbedtls_oid_get_cipher_alg -#define oid_get_ec_grp mbedtls_oid_get_ec_grp -#define oid_get_extended_key_usage mbedtls_oid_get_extended_key_usage -#define oid_get_md_alg mbedtls_oid_get_md_alg -#define oid_get_numeric_string mbedtls_oid_get_numeric_string -#define oid_get_oid_by_ec_grp mbedtls_oid_get_oid_by_ec_grp -#define oid_get_oid_by_md mbedtls_oid_get_oid_by_md -#define oid_get_oid_by_pk_alg mbedtls_oid_get_oid_by_pk_alg -#define oid_get_oid_by_sig_alg mbedtls_oid_get_oid_by_sig_alg -#define oid_get_pk_alg mbedtls_oid_get_pk_alg -#define oid_get_pkcs12_pbe_alg mbedtls_oid_get_pkcs12_pbe_alg -#define oid_get_sig_alg mbedtls_oid_get_sig_alg -#define oid_get_sig_alg_desc mbedtls_oid_get_sig_alg_desc -#define oid_get_x509_ext_type mbedtls_oid_get_x509_ext_type -#define operation_t mbedtls_operation_t -#define padlock_supports mbedtls_padlock_has_support -#define padlock_xcryptcbc mbedtls_padlock_xcryptcbc -#define padlock_xcryptecb mbedtls_padlock_xcryptecb -#define pem_context mbedtls_pem_context -#define pem_free mbedtls_pem_free -#define pem_init mbedtls_pem_init -#define pem_read_buffer mbedtls_pem_read_buffer -#define pem_write_buffer mbedtls_pem_write_buffer -#define pk_can_do mbedtls_pk_can_do -#define pk_check_pair mbedtls_pk_check_pair -#define pk_context mbedtls_pk_context -#define pk_debug mbedtls_pk_debug -#define pk_debug_item mbedtls_pk_debug_item -#define pk_debug_type mbedtls_pk_debug_type -#define pk_decrypt mbedtls_pk_decrypt -#define pk_ec mbedtls_pk_ec -#define pk_encrypt mbedtls_pk_encrypt -#define pk_free mbedtls_pk_free -#define pk_get_len mbedtls_pk_get_len -#define pk_get_name mbedtls_pk_get_name -#define pk_get_size mbedtls_pk_get_bitlen -#define pk_get_type mbedtls_pk_get_type -#define pk_info_from_type mbedtls_pk_info_from_type -#define pk_info_t mbedtls_pk_info_t -#define pk_init mbedtls_pk_init -#define pk_init_ctx mbedtls_pk_setup -#define pk_init_ctx_rsa_alt mbedtls_pk_setup_rsa_alt -#define pk_load_file mbedtls_pk_load_file -#define pk_parse_key mbedtls_pk_parse_key -#define pk_parse_keyfile mbedtls_pk_parse_keyfile -#define pk_parse_public_key mbedtls_pk_parse_public_key -#define pk_parse_public_keyfile mbedtls_pk_parse_public_keyfile -#define pk_parse_subpubkey mbedtls_pk_parse_subpubkey -#define pk_rsa mbedtls_pk_rsa -#define pk_rsa_alt_decrypt_func mbedtls_pk_rsa_alt_decrypt_func -#define pk_rsa_alt_key_len_func mbedtls_pk_rsa_alt_key_len_func -#define pk_rsa_alt_sign_func mbedtls_pk_rsa_alt_sign_func -#define pk_rsassa_pss_options mbedtls_pk_rsassa_pss_options -#define pk_sign mbedtls_pk_sign -#define pk_type_t mbedtls_pk_type_t -#define pk_verify mbedtls_pk_verify -#define pk_verify_ext mbedtls_pk_verify_ext -#define pk_write_key_der mbedtls_pk_write_key_der -#define pk_write_key_pem mbedtls_pk_write_key_pem -#define pk_write_pubkey mbedtls_pk_write_pubkey -#define pk_write_pubkey_der mbedtls_pk_write_pubkey_der -#define pk_write_pubkey_pem mbedtls_pk_write_pubkey_pem -#define pkcs11_context mbedtls_pkcs11_context -#define pkcs11_decrypt mbedtls_pkcs11_decrypt -#define pkcs11_priv_key_free mbedtls_pkcs11_priv_key_free -#define pkcs11_priv_key_init mbedtls_pkcs11_priv_key_bind -#define pkcs11_sign mbedtls_pkcs11_sign -#define pkcs11_x509_cert_init mbedtls_pkcs11_x509_cert_bind -#define pkcs12_derivation mbedtls_pkcs12_derivation -#define pkcs12_pbe mbedtls_pkcs12_pbe -#define pkcs12_pbe_sha1_rc4_128 mbedtls_pkcs12_pbe_sha1_rc4_128 -#define pkcs5_pbes2 mbedtls_pkcs5_pbes2 -#define pkcs5_pbkdf2_hmac mbedtls_pkcs5_pbkdf2_hmac -#define pkcs5_self_test mbedtls_pkcs5_self_test -#define platform_entropy_poll mbedtls_platform_entropy_poll -#define platform_set_exit mbedtls_platform_set_exit -#define platform_set_fprintf mbedtls_platform_set_fprintf -#define platform_set_printf mbedtls_platform_set_printf -#define platform_set_snprintf mbedtls_platform_set_snprintf -#define polarssl_exit mbedtls_exit -#define polarssl_fprintf mbedtls_fprintf -#define polarssl_free mbedtls_free -#define polarssl_mutex_free mbedtls_mutex_free -#define polarssl_mutex_init mbedtls_mutex_init -#define polarssl_mutex_lock mbedtls_mutex_lock -#define polarssl_mutex_unlock mbedtls_mutex_unlock -#define polarssl_printf mbedtls_printf -#define polarssl_snprintf mbedtls_snprintf -#define polarssl_strerror mbedtls_strerror -#define ripemd160 mbedtls_ripemd160 -#define ripemd160_context mbedtls_ripemd160_context -#define ripemd160_finish mbedtls_ripemd160_finish -#define ripemd160_free mbedtls_ripemd160_free -#define ripemd160_info mbedtls_ripemd160_info -#define ripemd160_init mbedtls_ripemd160_init -#define ripemd160_process mbedtls_ripemd160_process -#define ripemd160_self_test mbedtls_ripemd160_self_test -#define ripemd160_starts mbedtls_ripemd160_starts -#define ripemd160_update mbedtls_ripemd160_update -#define rsa_alt_context mbedtls_rsa_alt_context -#define rsa_alt_info mbedtls_rsa_alt_info -#define rsa_check_privkey mbedtls_rsa_check_privkey -#define rsa_check_pub_priv mbedtls_rsa_check_pub_priv -#define rsa_check_pubkey mbedtls_rsa_check_pubkey -#define rsa_context mbedtls_rsa_context -#define rsa_copy mbedtls_rsa_copy -#define rsa_free mbedtls_rsa_free -#define rsa_gen_key mbedtls_rsa_gen_key -#define rsa_info mbedtls_rsa_info -#define rsa_init mbedtls_rsa_init -#define rsa_pkcs1_decrypt mbedtls_rsa_pkcs1_decrypt -#define rsa_pkcs1_encrypt mbedtls_rsa_pkcs1_encrypt -#define rsa_pkcs1_sign mbedtls_rsa_pkcs1_sign -#define rsa_pkcs1_verify mbedtls_rsa_pkcs1_verify -#define rsa_private mbedtls_rsa_private -#define rsa_public mbedtls_rsa_public -#define rsa_rsaes_oaep_decrypt mbedtls_rsa_rsaes_oaep_decrypt -#define rsa_rsaes_oaep_encrypt mbedtls_rsa_rsaes_oaep_encrypt -#define rsa_rsaes_pkcs1_v15_decrypt mbedtls_rsa_rsaes_pkcs1_v15_decrypt -#define rsa_rsaes_pkcs1_v15_encrypt mbedtls_rsa_rsaes_pkcs1_v15_encrypt -#define rsa_rsassa_pkcs1_v15_sign mbedtls_rsa_rsassa_pkcs1_v15_sign -#define rsa_rsassa_pkcs1_v15_verify mbedtls_rsa_rsassa_pkcs1_v15_verify -#define rsa_rsassa_pss_sign mbedtls_rsa_rsassa_pss_sign -#define rsa_rsassa_pss_verify mbedtls_rsa_rsassa_pss_verify -#define rsa_rsassa_pss_verify_ext mbedtls_rsa_rsassa_pss_verify_ext -#define rsa_self_test mbedtls_rsa_self_test -#define rsa_set_padding mbedtls_rsa_set_padding -#define safer_memcmp mbedtls_ssl_safer_memcmp -#define set_alarm mbedtls_set_alarm -#define sha1 mbedtls_sha1 -#define sha1_context mbedtls_sha1_context -#define sha1_finish mbedtls_sha1_finish -#define sha1_free mbedtls_sha1_free -#define sha1_info mbedtls_sha1_info -#define sha1_init mbedtls_sha1_init -#define sha1_process mbedtls_sha1_process -#define sha1_self_test mbedtls_sha1_self_test -#define sha1_starts mbedtls_sha1_starts -#define sha1_update mbedtls_sha1_update -#define sha224_info mbedtls_sha224_info -#define sha256 mbedtls_sha256 -#define sha256_context mbedtls_sha256_context -#define sha256_finish mbedtls_sha256_finish -#define sha256_free mbedtls_sha256_free -#define sha256_info mbedtls_sha256_info -#define sha256_init mbedtls_sha256_init -#define sha256_process mbedtls_sha256_process -#define sha256_self_test mbedtls_sha256_self_test -#define sha256_starts mbedtls_sha256_starts -#define sha256_update mbedtls_sha256_update -#define sha384_info mbedtls_sha384_info -#define sha512 mbedtls_sha512 -#define sha512_context mbedtls_sha512_context -#define sha512_finish mbedtls_sha512_finish -#define sha512_free mbedtls_sha512_free -#define sha512_info mbedtls_sha512_info -#define sha512_init mbedtls_sha512_init -#define sha512_process mbedtls_sha512_process -#define sha512_self_test mbedtls_sha512_self_test -#define sha512_starts mbedtls_sha512_starts -#define sha512_update mbedtls_sha512_update -#define source_state mbedtls_entropy_source_state -#define ssl_cache_context mbedtls_ssl_cache_context -#define ssl_cache_entry mbedtls_ssl_cache_entry -#define ssl_cache_free mbedtls_ssl_cache_free -#define ssl_cache_get mbedtls_ssl_cache_get -#define ssl_cache_init mbedtls_ssl_cache_init -#define ssl_cache_set mbedtls_ssl_cache_set -#define ssl_cache_set_max_entries mbedtls_ssl_cache_set_max_entries -#define ssl_cache_set_timeout mbedtls_ssl_cache_set_timeout -#define ssl_check_cert_usage mbedtls_ssl_check_cert_usage -#define ssl_ciphersuite_from_id mbedtls_ssl_ciphersuite_from_id -#define ssl_ciphersuite_from_string mbedtls_ssl_ciphersuite_from_string -#define ssl_ciphersuite_t mbedtls_ssl_ciphersuite_t -#define ssl_ciphersuite_uses_ec mbedtls_ssl_ciphersuite_uses_ec -#define ssl_ciphersuite_uses_psk mbedtls_ssl_ciphersuite_uses_psk -#define ssl_close_notify mbedtls_ssl_close_notify -#define ssl_context mbedtls_ssl_context -#define ssl_cookie_check mbedtls_ssl_cookie_check -#define ssl_cookie_check_t mbedtls_ssl_cookie_check_t -#define ssl_cookie_ctx mbedtls_ssl_cookie_ctx -#define ssl_cookie_free mbedtls_ssl_cookie_free -#define ssl_cookie_init mbedtls_ssl_cookie_init -#define ssl_cookie_set_timeout mbedtls_ssl_cookie_set_timeout -#define ssl_cookie_setup mbedtls_ssl_cookie_setup -#define ssl_cookie_write mbedtls_ssl_cookie_write -#define ssl_cookie_write_t mbedtls_ssl_cookie_write_t -#define ssl_derive_keys mbedtls_ssl_derive_keys -#define ssl_dtls_replay_check mbedtls_ssl_dtls_replay_check -#define ssl_dtls_replay_update mbedtls_ssl_dtls_replay_update -#define ssl_fetch_input mbedtls_ssl_fetch_input -#define ssl_flight_item mbedtls_ssl_flight_item -#define ssl_flush_output mbedtls_ssl_flush_output -#define ssl_free mbedtls_ssl_free -#define ssl_get_alpn_protocol mbedtls_ssl_get_alpn_protocol -#define ssl_get_bytes_avail mbedtls_ssl_get_bytes_avail -#define ssl_get_ciphersuite mbedtls_ssl_get_ciphersuite -#define ssl_get_ciphersuite_id mbedtls_ssl_get_ciphersuite_id -#define ssl_get_ciphersuite_name mbedtls_ssl_get_ciphersuite_name -#define ssl_get_ciphersuite_sig_pk_alg mbedtls_ssl_get_ciphersuite_sig_pk_alg -#define ssl_get_peer_cert mbedtls_ssl_get_peer_cert -#define ssl_get_record_expansion mbedtls_ssl_get_record_expansion -#define ssl_get_session mbedtls_ssl_get_session -#define ssl_get_verify_result mbedtls_ssl_get_verify_result -#define ssl_get_version mbedtls_ssl_get_version -#define ssl_handshake mbedtls_ssl_handshake -#define ssl_handshake_client_step mbedtls_ssl_handshake_client_step -#define ssl_handshake_free mbedtls_ssl_handshake_free -#define ssl_handshake_params mbedtls_ssl_handshake_params -#define ssl_handshake_server_step mbedtls_ssl_handshake_server_step -#define ssl_handshake_step mbedtls_ssl_handshake_step -#define ssl_handshake_wrapup mbedtls_ssl_handshake_wrapup -#define ssl_hdr_len mbedtls_ssl_hdr_len -#define ssl_hs_hdr_len mbedtls_ssl_hs_hdr_len -#define ssl_hw_record_activate mbedtls_ssl_hw_record_activate -#define ssl_hw_record_finish mbedtls_ssl_hw_record_finish -#define ssl_hw_record_init mbedtls_ssl_hw_record_init -#define ssl_hw_record_read mbedtls_ssl_hw_record_read -#define ssl_hw_record_reset mbedtls_ssl_hw_record_reset -#define ssl_hw_record_write mbedtls_ssl_hw_record_write -#define ssl_init mbedtls_ssl_init -#define ssl_key_cert mbedtls_ssl_key_cert -#define ssl_legacy_renegotiation mbedtls_ssl_conf_legacy_renegotiation -#define ssl_list_ciphersuites mbedtls_ssl_list_ciphersuites -#define ssl_md_alg_from_hash mbedtls_ssl_md_alg_from_hash -#define ssl_optimize_checksum mbedtls_ssl_optimize_checksum -#define ssl_own_cert mbedtls_ssl_own_cert -#define ssl_own_key mbedtls_ssl_own_key -#define ssl_parse_certificate mbedtls_ssl_parse_certificate -#define ssl_parse_change_cipher_spec mbedtls_ssl_parse_change_cipher_spec -#define ssl_parse_finished mbedtls_ssl_parse_finished -#define ssl_pk_alg_from_sig mbedtls_ssl_pk_alg_from_sig -#define ssl_pkcs11_decrypt mbedtls_ssl_pkcs11_decrypt -#define ssl_pkcs11_key_len mbedtls_ssl_pkcs11_key_len -#define ssl_pkcs11_sign mbedtls_ssl_pkcs11_sign -#define ssl_psk_derive_premaster mbedtls_ssl_psk_derive_premaster -#define ssl_read mbedtls_ssl_read -#define ssl_read_record mbedtls_ssl_read_record -#define ssl_read_version mbedtls_ssl_read_version -#define ssl_recv_flight_completed mbedtls_ssl_recv_flight_completed -#define ssl_renegotiate mbedtls_ssl_renegotiate -#define ssl_resend mbedtls_ssl_resend -#define ssl_reset_checksum mbedtls_ssl_reset_checksum -#define ssl_send_alert_message mbedtls_ssl_send_alert_message -#define ssl_send_fatal_handshake_failure mbedtls_ssl_send_fatal_handshake_failure -#define ssl_send_flight_completed mbedtls_ssl_send_flight_completed -#define ssl_session mbedtls_ssl_session -#define ssl_session_free mbedtls_ssl_session_free -#define ssl_session_init mbedtls_ssl_session_init -#define ssl_session_reset mbedtls_ssl_session_reset -#define ssl_set_alpn_protocols mbedtls_ssl_conf_alpn_protocols -#define ssl_set_arc4_support mbedtls_ssl_conf_arc4_support -#define ssl_set_authmode mbedtls_ssl_conf_authmode -#define ssl_set_bio mbedtls_ssl_set_bio -#define ssl_set_ca_chain mbedtls_ssl_conf_ca_chain -#define ssl_set_cbc_record_splitting mbedtls_ssl_conf_cbc_record_splitting -#define ssl_set_ciphersuites mbedtls_ssl_conf_ciphersuites -#define ssl_set_ciphersuites_for_version mbedtls_ssl_conf_ciphersuites_for_version -#define ssl_set_client_transport_id mbedtls_ssl_set_client_transport_id -#define ssl_set_curves mbedtls_ssl_conf_curves -#define ssl_set_dbg mbedtls_ssl_conf_dbg -#define ssl_set_dh_param mbedtls_ssl_conf_dh_param -#define ssl_set_dh_param_ctx mbedtls_ssl_conf_dh_param_ctx -#define ssl_set_dtls_anti_replay mbedtls_ssl_conf_dtls_anti_replay -#define ssl_set_dtls_badmac_limit mbedtls_ssl_conf_dtls_badmac_limit -#define ssl_set_dtls_cookies mbedtls_ssl_conf_dtls_cookies -#define ssl_set_encrypt_then_mac mbedtls_ssl_conf_encrypt_then_mac -#define ssl_set_endpoint mbedtls_ssl_conf_endpoint -#define ssl_set_extended_master_secret mbedtls_ssl_conf_extended_master_secret -#define ssl_set_fallback mbedtls_ssl_conf_fallback -#define ssl_set_handshake_timeout mbedtls_ssl_conf_handshake_timeout -#define ssl_set_hostname mbedtls_ssl_set_hostname -#define ssl_set_max_frag_len mbedtls_ssl_conf_max_frag_len -#define ssl_set_max_version mbedtls_ssl_conf_max_version -#define ssl_set_min_version mbedtls_ssl_conf_min_version -#define ssl_set_own_cert mbedtls_ssl_conf_own_cert -#define ssl_set_psk mbedtls_ssl_conf_psk -#define ssl_set_psk_cb mbedtls_ssl_conf_psk_cb -#define ssl_set_renegotiation mbedtls_ssl_conf_renegotiation -#define ssl_set_renegotiation_enforced mbedtls_ssl_conf_renegotiation_enforced -#define ssl_set_renegotiation_period mbedtls_ssl_conf_renegotiation_period -#define ssl_set_rng mbedtls_ssl_conf_rng -#define ssl_set_session mbedtls_ssl_set_session -#define ssl_set_session_cache mbedtls_ssl_conf_session_cache -#define ssl_set_session_tickets mbedtls_ssl_conf_session_tickets -#define ssl_set_sni mbedtls_ssl_conf_sni -#define ssl_set_transport mbedtls_ssl_conf_transport -#define ssl_set_truncated_hmac mbedtls_ssl_conf_truncated_hmac -#define ssl_set_verify mbedtls_ssl_conf_verify -#define ssl_sig_from_pk mbedtls_ssl_sig_from_pk -#define ssl_states mbedtls_ssl_states -#define ssl_transform mbedtls_ssl_transform -#define ssl_transform_free mbedtls_ssl_transform_free -#define ssl_write mbedtls_ssl_write -#define ssl_write_certificate mbedtls_ssl_write_certificate -#define ssl_write_change_cipher_spec mbedtls_ssl_write_change_cipher_spec -#define ssl_write_finished mbedtls_ssl_write_finished -#define ssl_write_record mbedtls_ssl_write_record -#define ssl_write_version mbedtls_ssl_write_version -#define supported_ciphers mbedtls_cipher_supported -#define t_sint mbedtls_mpi_sint -#define t_udbl mbedtls_t_udbl -#define t_uint mbedtls_mpi_uint -#define test_ca_crt mbedtls_test_ca_crt -#define test_ca_crt_ec mbedtls_test_ca_crt_ec -#define test_ca_crt_rsa mbedtls_test_ca_crt_rsa -#define test_ca_key mbedtls_test_ca_key -#define test_ca_key_ec mbedtls_test_ca_key_ec -#define test_ca_key_rsa mbedtls_test_ca_key_rsa -#define test_ca_list mbedtls_test_cas_pem -#define test_ca_pwd mbedtls_test_ca_pwd -#define test_ca_pwd_ec mbedtls_test_ca_pwd_ec -#define test_ca_pwd_rsa mbedtls_test_ca_pwd_rsa -#define test_cli_crt mbedtls_test_cli_crt -#define test_cli_crt_ec mbedtls_test_cli_crt_ec -#define test_cli_crt_rsa mbedtls_test_cli_crt_rsa -#define test_cli_key mbedtls_test_cli_key -#define test_cli_key_ec mbedtls_test_cli_key_ec -#define test_cli_key_rsa mbedtls_test_cli_key_rsa -#define test_srv_crt mbedtls_test_srv_crt -#define test_srv_crt_ec mbedtls_test_srv_crt_ec -#define test_srv_crt_rsa mbedtls_test_srv_crt_rsa -#define test_srv_key mbedtls_test_srv_key -#define test_srv_key_ec mbedtls_test_srv_key_ec -#define test_srv_key_rsa mbedtls_test_srv_key_rsa -#define threading_mutex_t mbedtls_threading_mutex_t -#define threading_set_alt mbedtls_threading_set_alt -#define timing_self_test mbedtls_timing_self_test -#define version_check_feature mbedtls_version_check_feature -#define version_get_number mbedtls_version_get_number -#define version_get_string mbedtls_version_get_string -#define version_get_string_full mbedtls_version_get_string_full -#define x509_bitstring mbedtls_x509_bitstring -#define x509_buf mbedtls_x509_buf -#define x509_crl mbedtls_x509_crl -#define x509_crl_entry mbedtls_x509_crl_entry -#define x509_crl_free mbedtls_x509_crl_free -#define x509_crl_info mbedtls_x509_crl_info -#define x509_crl_init mbedtls_x509_crl_init -#define x509_crl_parse mbedtls_x509_crl_parse -#define x509_crl_parse_der mbedtls_x509_crl_parse_der -#define x509_crl_parse_file mbedtls_x509_crl_parse_file -#define x509_crt mbedtls_x509_crt -#define x509_crt_check_extended_key_usage mbedtls_x509_crt_check_extended_key_usage -#define x509_crt_check_key_usage mbedtls_x509_crt_check_key_usage -#define x509_crt_free mbedtls_x509_crt_free -#define x509_crt_info mbedtls_x509_crt_info -#define x509_crt_init mbedtls_x509_crt_init -#define x509_crt_parse mbedtls_x509_crt_parse -#define x509_crt_parse_der mbedtls_x509_crt_parse_der -#define x509_crt_parse_file mbedtls_x509_crt_parse_file -#define x509_crt_parse_path mbedtls_x509_crt_parse_path -#define x509_crt_revoked mbedtls_x509_crt_is_revoked -#define x509_crt_verify mbedtls_x509_crt_verify -#define x509_csr mbedtls_x509_csr -#define x509_csr_free mbedtls_x509_csr_free -#define x509_csr_info mbedtls_x509_csr_info -#define x509_csr_init mbedtls_x509_csr_init -#define x509_csr_parse mbedtls_x509_csr_parse -#define x509_csr_parse_der mbedtls_x509_csr_parse_der -#define x509_csr_parse_file mbedtls_x509_csr_parse_file -#define x509_dn_gets mbedtls_x509_dn_gets -#define x509_get_alg mbedtls_x509_get_alg -#define x509_get_alg_null mbedtls_x509_get_alg_null -#define x509_get_ext mbedtls_x509_get_ext -#define x509_get_name mbedtls_x509_get_name -#define x509_get_rsassa_pss_params mbedtls_x509_get_rsassa_pss_params -#define x509_get_serial mbedtls_x509_get_serial -#define x509_get_sig mbedtls_x509_get_sig -#define x509_get_sig_alg mbedtls_x509_get_sig_alg -#define x509_get_time mbedtls_x509_get_time -#define x509_key_size_helper mbedtls_x509_key_size_helper -#define x509_name mbedtls_x509_name -#define x509_self_test mbedtls_x509_self_test -#define x509_sequence mbedtls_x509_sequence -#define x509_serial_gets mbedtls_x509_serial_gets -#define x509_set_extension mbedtls_x509_set_extension -#define x509_sig_alg_gets mbedtls_x509_sig_alg_gets -#define x509_string_to_names mbedtls_x509_string_to_names -#define x509_time mbedtls_x509_time -#define x509_time_expired mbedtls_x509_time_is_past -#define x509_time_future mbedtls_x509_time_is_future -#define x509_write_extensions mbedtls_x509_write_extensions -#define x509_write_names mbedtls_x509_write_names -#define x509_write_sig mbedtls_x509_write_sig -#define x509write_cert mbedtls_x509write_cert -#define x509write_crt_der mbedtls_x509write_crt_der -#define x509write_crt_free mbedtls_x509write_crt_free -#define x509write_crt_init mbedtls_x509write_crt_init -#define x509write_crt_pem mbedtls_x509write_crt_pem -#define x509write_crt_set_authority_key_identifier \ - mbedtls_x509write_crt_set_authority_key_identifier -#define x509write_crt_set_basic_constraints mbedtls_x509write_crt_set_basic_constraints -#define x509write_crt_set_extension mbedtls_x509write_crt_set_extension -#define x509write_crt_set_issuer_key mbedtls_x509write_crt_set_issuer_key -#define x509write_crt_set_issuer_name mbedtls_x509write_crt_set_issuer_name -#define x509write_crt_set_key_usage mbedtls_x509write_crt_set_key_usage -#define x509write_crt_set_md_alg mbedtls_x509write_crt_set_md_alg -#define x509write_crt_set_ns_cert_type mbedtls_x509write_crt_set_ns_cert_type -#define x509write_crt_set_serial mbedtls_x509write_crt_set_serial -#define x509write_crt_set_subject_key mbedtls_x509write_crt_set_subject_key -#define x509write_crt_set_subject_key_identifier mbedtls_x509write_crt_set_subject_key_identifier -#define x509write_crt_set_subject_name mbedtls_x509write_crt_set_subject_name -#define x509write_crt_set_validity mbedtls_x509write_crt_set_validity -#define x509write_crt_set_version mbedtls_x509write_crt_set_version -#define x509write_csr mbedtls_x509write_csr -#define x509write_csr_der mbedtls_x509write_csr_der -#define x509write_csr_free mbedtls_x509write_csr_free -#define x509write_csr_init mbedtls_x509write_csr_init -#define x509write_csr_pem mbedtls_x509write_csr_pem -#define x509write_csr_set_extension mbedtls_x509write_csr_set_extension -#define x509write_csr_set_key mbedtls_x509write_csr_set_key -#define x509write_csr_set_key_usage mbedtls_x509write_csr_set_key_usage -#define x509write_csr_set_md_alg mbedtls_x509write_csr_set_md_alg -#define x509write_csr_set_ns_cert_type mbedtls_x509write_csr_set_ns_cert_type -#define x509write_csr_set_subject_name mbedtls_x509write_csr_set_subject_name -#define xtea_context mbedtls_xtea_context -#define xtea_crypt_cbc mbedtls_xtea_crypt_cbc -#define xtea_crypt_ecb mbedtls_xtea_crypt_ecb -#define xtea_free mbedtls_xtea_free -#define xtea_init mbedtls_xtea_init -#define xtea_self_test mbedtls_xtea_self_test -#define xtea_setup mbedtls_xtea_setup - -#endif /* compat-1.3.h */ -#endif /* MBEDTLS_DEPRECATED_REMOVED */ diff --git a/vendor/mbedtls/include/mbedtls/compat-2.x.h b/vendor/mbedtls/include/mbedtls/compat-2.x.h new file mode 100644 index 0000000000..096341ba76 --- /dev/null +++ b/vendor/mbedtls/include/mbedtls/compat-2.x.h @@ -0,0 +1,46 @@ +/** + * \file compat-2.x.h + * + * \brief Compatibility definitions + * + * \deprecated Use the new names directly instead + */ +/* + * Copyright The Mbed TLS Contributors + * SPDX-License-Identifier: Apache-2.0 OR GPL-2.0-or-later + */ + +#if defined(MBEDTLS_DEPRECATED_WARNING) +#warning "Including compat-2.x.h is deprecated" +#endif + +#ifndef MBEDTLS_COMPAT2X_H +#define MBEDTLS_COMPAT2X_H + +/* + * Macros for renamed functions + */ +#define mbedtls_ctr_drbg_update_ret mbedtls_ctr_drbg_update +#define mbedtls_hmac_drbg_update_ret mbedtls_hmac_drbg_update +#define mbedtls_md5_starts_ret mbedtls_md5_starts +#define mbedtls_md5_update_ret mbedtls_md5_update +#define mbedtls_md5_finish_ret mbedtls_md5_finish +#define mbedtls_md5_ret mbedtls_md5 +#define mbedtls_ripemd160_starts_ret mbedtls_ripemd160_starts +#define mbedtls_ripemd160_update_ret mbedtls_ripemd160_update +#define mbedtls_ripemd160_finish_ret mbedtls_ripemd160_finish +#define mbedtls_ripemd160_ret mbedtls_ripemd160 +#define mbedtls_sha1_starts_ret mbedtls_sha1_starts +#define mbedtls_sha1_update_ret mbedtls_sha1_update +#define mbedtls_sha1_finish_ret mbedtls_sha1_finish +#define mbedtls_sha1_ret mbedtls_sha1 +#define mbedtls_sha256_starts_ret mbedtls_sha256_starts +#define mbedtls_sha256_update_ret mbedtls_sha256_update +#define mbedtls_sha256_finish_ret mbedtls_sha256_finish +#define mbedtls_sha256_ret mbedtls_sha256 +#define mbedtls_sha512_starts_ret mbedtls_sha512_starts +#define mbedtls_sha512_update_ret mbedtls_sha512_update +#define mbedtls_sha512_finish_ret mbedtls_sha512_finish +#define mbedtls_sha512_ret mbedtls_sha512 + +#endif /* MBEDTLS_COMPAT2X_H */ diff --git a/vendor/mbedtls/include/mbedtls/config_adjust_legacy_crypto.h b/vendor/mbedtls/include/mbedtls/config_adjust_legacy_crypto.h new file mode 100644 index 0000000000..9b06041228 --- /dev/null +++ b/vendor/mbedtls/include/mbedtls/config_adjust_legacy_crypto.h @@ -0,0 +1,457 @@ +/** + * \file mbedtls/config_adjust_legacy_crypto.h + * \brief Adjust legacy configuration configuration + * + * Automatically enable certain dependencies. Generally, MBEDLTS_xxx + * configurations need to be explicitly enabled by the user: enabling + * MBEDTLS_xxx_A but not MBEDTLS_xxx_B when A requires B results in a + * compilation error. However, we do automatically enable certain options + * in some circumstances. One case is if MBEDTLS_xxx_B is an internal option + * used to identify parts of a module that are used by other module, and we + * don't want to make the symbol MBEDTLS_xxx_B part of the public API. + * Another case is if A didn't depend on B in earlier versions, and we + * want to use B in A but we need to preserve backward compatibility with + * configurations that explicitly activate MBEDTLS_xxx_A but not + * MBEDTLS_xxx_B. + */ +/* + * Copyright The Mbed TLS Contributors + * SPDX-License-Identifier: Apache-2.0 OR GPL-2.0-or-later + */ + +#ifndef MBEDTLS_CONFIG_ADJUST_LEGACY_CRYPTO_H +#define MBEDTLS_CONFIG_ADJUST_LEGACY_CRYPTO_H + +/* Ideally, we'd set those as defaults in mbedtls_config.h, but + * putting an #ifdef _WIN32 in mbedtls_config.h would confuse config.py. + * + * So, adjust it here. + * Not related to crypto, but this is the bottom of the stack. */ +#if defined(__MINGW32__) || (defined(_MSC_VER) && _MSC_VER <= 1900) +#if !defined(MBEDTLS_PLATFORM_SNPRINTF_ALT) && \ + !defined(MBEDTLS_PLATFORM_SNPRINTF_MACRO) +#define MBEDTLS_PLATFORM_SNPRINTF_ALT +#endif +#if !defined(MBEDTLS_PLATFORM_VSNPRINTF_ALT) && \ + !defined(MBEDTLS_PLATFORM_VSNPRINTF_MACRO) +#define MBEDTLS_PLATFORM_VSNPRINTF_ALT +#endif +#endif /* _MINGW32__ || (_MSC_VER && (_MSC_VER <= 1900)) */ + +/* Auto-enable CIPHER_C when any of the unauthenticated ciphers is builtin + * in PSA. */ +#if defined(MBEDTLS_PSA_CRYPTO_C) && \ + (defined(MBEDTLS_PSA_BUILTIN_ALG_STREAM_CIPHER) || \ + defined(MBEDTLS_PSA_BUILTIN_ALG_CTR) || \ + defined(MBEDTLS_PSA_BUILTIN_ALG_CFB) || \ + defined(MBEDTLS_PSA_BUILTIN_ALG_OFB) || \ + defined(MBEDTLS_PSA_BUILTIN_ALG_ECB_NO_PADDING) || \ + defined(MBEDTLS_PSA_BUILTIN_ALG_CBC_NO_PADDING) || \ + defined(MBEDTLS_PSA_BUILTIN_ALG_CBC_PKCS7) || \ + defined(MBEDTLS_PSA_BUILTIN_ALG_CCM_STAR_NO_TAG)) +#define MBEDTLS_CIPHER_C +#endif + +/* Auto-enable MBEDTLS_MD_LIGHT based on MBEDTLS_MD_C. + * This allows checking for MD_LIGHT rather than MD_LIGHT || MD_C. + */ +#if defined(MBEDTLS_MD_C) +#define MBEDTLS_MD_LIGHT +#endif + +/* Auto-enable MBEDTLS_MD_LIGHT if needed by a module that didn't require it + * in a previous release, to ensure backwards compatibility. + */ +#if defined(MBEDTLS_ECJPAKE_C) || \ + defined(MBEDTLS_PEM_PARSE_C) || \ + defined(MBEDTLS_ENTROPY_C) || \ + defined(MBEDTLS_PK_C) || \ + defined(MBEDTLS_PKCS12_C) || \ + defined(MBEDTLS_RSA_C) || \ + defined(MBEDTLS_SSL_TLS_C) || \ + defined(MBEDTLS_X509_USE_C) || \ + defined(MBEDTLS_X509_CREATE_C) +#define MBEDTLS_MD_LIGHT +#endif + +#if defined(MBEDTLS_MD_LIGHT) +/* + * - MBEDTLS_MD_CAN_xxx is defined if the md module can perform xxx. + * - MBEDTLS_MD_xxx_VIA_PSA is defined if the md module may perform xxx via PSA + * (see below). + * - MBEDTLS_MD_SOME_PSA is defined if at least one algorithm may be performed + * via PSA (see below). + * - MBEDTLS_MD_SOME_LEGACY is defined if at least one algorithm may be performed + * via a direct legacy call (see below). + * + * The md module performs an algorithm via PSA if there is a PSA hash + * accelerator and the PSA driver subsytem is initialized at the time the + * operation is started, and makes a direct legacy call otherwise. + */ + +/* PSA accelerated implementations */ +#if defined(MBEDTLS_PSA_CRYPTO_C) + +#if defined(MBEDTLS_PSA_ACCEL_ALG_MD5) +#define MBEDTLS_MD_CAN_MD5 +#define MBEDTLS_MD_MD5_VIA_PSA +#define MBEDTLS_MD_SOME_PSA +#endif +#if defined(MBEDTLS_PSA_ACCEL_ALG_SHA_1) +#define MBEDTLS_MD_CAN_SHA1 +#define MBEDTLS_MD_SHA1_VIA_PSA +#define MBEDTLS_MD_SOME_PSA +#endif +#if defined(MBEDTLS_PSA_ACCEL_ALG_SHA_224) +#define MBEDTLS_MD_CAN_SHA224 +#define MBEDTLS_MD_SHA224_VIA_PSA +#define MBEDTLS_MD_SOME_PSA +#endif +#if defined(MBEDTLS_PSA_ACCEL_ALG_SHA_256) +#define MBEDTLS_MD_CAN_SHA256 +#define MBEDTLS_MD_SHA256_VIA_PSA +#define MBEDTLS_MD_SOME_PSA +#endif +#if defined(MBEDTLS_PSA_ACCEL_ALG_SHA_384) +#define MBEDTLS_MD_CAN_SHA384 +#define MBEDTLS_MD_SHA384_VIA_PSA +#define MBEDTLS_MD_SOME_PSA +#endif +#if defined(MBEDTLS_PSA_ACCEL_ALG_SHA_512) +#define MBEDTLS_MD_CAN_SHA512 +#define MBEDTLS_MD_SHA512_VIA_PSA +#define MBEDTLS_MD_SOME_PSA +#endif +#if defined(MBEDTLS_PSA_ACCEL_ALG_RIPEMD160) +#define MBEDTLS_MD_CAN_RIPEMD160 +#define MBEDTLS_MD_RIPEMD160_VIA_PSA +#define MBEDTLS_MD_SOME_PSA +#endif +#if defined(MBEDTLS_PSA_ACCEL_ALG_SHA3_224) +#define MBEDTLS_MD_CAN_SHA3_224 +#define MBEDTLS_MD_SHA3_224_VIA_PSA +#define MBEDTLS_MD_SOME_PSA +#endif +#if defined(MBEDTLS_PSA_ACCEL_ALG_SHA3_256) +#define MBEDTLS_MD_CAN_SHA3_256 +#define MBEDTLS_MD_SHA3_256_VIA_PSA +#define MBEDTLS_MD_SOME_PSA +#endif +#if defined(MBEDTLS_PSA_ACCEL_ALG_SHA3_384) +#define MBEDTLS_MD_CAN_SHA3_384 +#define MBEDTLS_MD_SHA3_384_VIA_PSA +#define MBEDTLS_MD_SOME_PSA +#endif +#if defined(MBEDTLS_PSA_ACCEL_ALG_SHA3_512) +#define MBEDTLS_MD_CAN_SHA3_512 +#define MBEDTLS_MD_SHA3_512_VIA_PSA +#define MBEDTLS_MD_SOME_PSA +#endif +#endif /* MBEDTLS_PSA_CRYPTO_C */ + +/* Built-in implementations */ +#if defined(MBEDTLS_MD5_C) +#define MBEDTLS_MD_CAN_MD5 +#define MBEDTLS_MD_SOME_LEGACY +#endif +#if defined(MBEDTLS_SHA1_C) +#define MBEDTLS_MD_CAN_SHA1 +#define MBEDTLS_MD_SOME_LEGACY +#endif +#if defined(MBEDTLS_SHA224_C) +#define MBEDTLS_MD_CAN_SHA224 +#define MBEDTLS_MD_SOME_LEGACY +#endif +#if defined(MBEDTLS_SHA256_C) +#define MBEDTLS_MD_CAN_SHA256 +#define MBEDTLS_MD_SOME_LEGACY +#endif +#if defined(MBEDTLS_SHA384_C) +#define MBEDTLS_MD_CAN_SHA384 +#define MBEDTLS_MD_SOME_LEGACY +#endif +#if defined(MBEDTLS_SHA512_C) +#define MBEDTLS_MD_CAN_SHA512 +#define MBEDTLS_MD_SOME_LEGACY +#endif +#if defined(MBEDTLS_SHA3_C) +#define MBEDTLS_MD_CAN_SHA3_224 +#define MBEDTLS_MD_CAN_SHA3_256 +#define MBEDTLS_MD_CAN_SHA3_384 +#define MBEDTLS_MD_CAN_SHA3_512 +#define MBEDTLS_MD_SOME_LEGACY +#endif +#if defined(MBEDTLS_RIPEMD160_C) +#define MBEDTLS_MD_CAN_RIPEMD160 +#define MBEDTLS_MD_SOME_LEGACY +#endif + +#endif /* MBEDTLS_MD_LIGHT */ + +/* BLOCK_CIPHER module can dispatch to PSA when: + * - PSA is enabled and drivers have been initialized + * - desired key type is supported on the PSA side + * If the above conditions are not met, but the legacy support is enabled, then + * BLOCK_CIPHER will dynamically fallback to it. + * + * In case BLOCK_CIPHER is defined (see below) the following symbols/helpers + * can be used to define its capabilities: + * - MBEDTLS_BLOCK_CIPHER_SOME_PSA: there is at least 1 key type between AES, + * ARIA and Camellia which is supported through a driver; + * - MBEDTLS_BLOCK_CIPHER_xxx_VIA_PSA: xxx key type is supported through a + * driver; + * - MBEDTLS_BLOCK_CIPHER_xxx_VIA_LEGACY: xxx key type is supported through + * a legacy module (i.e. MBEDTLS_xxx_C) + */ +#if defined(MBEDTLS_PSA_CRYPTO_C) +#if defined(MBEDTLS_PSA_ACCEL_KEY_TYPE_AES) +#define MBEDTLS_BLOCK_CIPHER_AES_VIA_PSA +#define MBEDTLS_BLOCK_CIPHER_SOME_PSA +#endif +#if defined(MBEDTLS_PSA_ACCEL_KEY_TYPE_ARIA) +#define MBEDTLS_BLOCK_CIPHER_ARIA_VIA_PSA +#define MBEDTLS_BLOCK_CIPHER_SOME_PSA +#endif +#if defined(MBEDTLS_PSA_ACCEL_KEY_TYPE_CAMELLIA) +#define MBEDTLS_BLOCK_CIPHER_CAMELLIA_VIA_PSA +#define MBEDTLS_BLOCK_CIPHER_SOME_PSA +#endif +#endif /* MBEDTLS_PSA_CRYPTO_C */ + +#if defined(MBEDTLS_AES_C) +#define MBEDTLS_BLOCK_CIPHER_AES_VIA_LEGACY +#endif +#if defined(MBEDTLS_ARIA_C) +#define MBEDTLS_BLOCK_CIPHER_ARIA_VIA_LEGACY +#endif +#if defined(MBEDTLS_CAMELLIA_C) +#define MBEDTLS_BLOCK_CIPHER_CAMELLIA_VIA_LEGACY +#endif + +/* Helpers to state that BLOCK_CIPHER module supports AES, ARIA and/or Camellia + * block ciphers via either PSA or legacy. */ +#if defined(MBEDTLS_BLOCK_CIPHER_AES_VIA_PSA) || \ + defined(MBEDTLS_BLOCK_CIPHER_AES_VIA_LEGACY) +#define MBEDTLS_BLOCK_CIPHER_CAN_AES +#endif +#if defined(MBEDTLS_BLOCK_CIPHER_ARIA_VIA_PSA) || \ + defined(MBEDTLS_BLOCK_CIPHER_ARIA_VIA_LEGACY) +#define MBEDTLS_BLOCK_CIPHER_CAN_ARIA +#endif +#if defined(MBEDTLS_BLOCK_CIPHER_CAMELLIA_VIA_PSA) || \ + defined(MBEDTLS_BLOCK_CIPHER_CAMELLIA_VIA_LEGACY) +#define MBEDTLS_BLOCK_CIPHER_CAN_CAMELLIA +#endif + +/* GCM_C and CCM_C can either depend on (in order of preference) BLOCK_CIPHER_C + * or CIPHER_C. The former is auto-enabled when: + * - CIPHER_C is not defined, which is also the legacy solution; + * - BLOCK_CIPHER_SOME_PSA because in this case BLOCK_CIPHER can take advantage + * of the driver's acceleration. + */ +#if (defined(MBEDTLS_GCM_C) || defined(MBEDTLS_CCM_C)) && \ + (!defined(MBEDTLS_CIPHER_C) || defined(MBEDTLS_BLOCK_CIPHER_SOME_PSA)) +#define MBEDTLS_BLOCK_CIPHER_C +#endif + +/* Helpers for GCM/CCM capabilities */ +#if (defined(MBEDTLS_CIPHER_C) && defined(MBEDTLS_AES_C)) || \ + (defined(MBEDTLS_BLOCK_CIPHER_C) && defined(MBEDTLS_BLOCK_CIPHER_CAN_AES)) +#define MBEDTLS_CCM_GCM_CAN_AES +#endif + +#if (defined(MBEDTLS_CIPHER_C) && defined(MBEDTLS_ARIA_C)) || \ + (defined(MBEDTLS_BLOCK_CIPHER_C) && defined(MBEDTLS_BLOCK_CIPHER_CAN_ARIA)) +#define MBEDTLS_CCM_GCM_CAN_ARIA +#endif + +#if (defined(MBEDTLS_CIPHER_C) && defined(MBEDTLS_CAMELLIA_C)) || \ + (defined(MBEDTLS_BLOCK_CIPHER_C) && defined(MBEDTLS_BLOCK_CIPHER_CAN_CAMELLIA)) +#define MBEDTLS_CCM_GCM_CAN_CAMELLIA +#endif + +/* MBEDTLS_ECP_LIGHT is auto-enabled by the following symbols: + * - MBEDTLS_ECP_C because now it consists of MBEDTLS_ECP_LIGHT plus functions + * for curve arithmetic. As a consequence if MBEDTLS_ECP_C is required for + * some reason, then MBEDTLS_ECP_LIGHT should be enabled as well. + * - MBEDTLS_PK_PARSE_EC_EXTENDED and MBEDTLS_PK_PARSE_EC_COMPRESSED because + * these features are not supported in PSA so the only way to have them is + * to enable the built-in solution. + * Both of them are temporary dependencies: + * - PK_PARSE_EC_EXTENDED will be removed after #7779 and #7789 + * - support for compressed points should also be added to PSA, but in this + * case there is no associated issue to track it yet. + * - PSA_WANT_KEY_TYPE_ECC_KEY_PAIR_DERIVE because Weierstrass key derivation + * still depends on ECP_LIGHT. + * - PK_C + USE_PSA + PSA_WANT_ALG_ECDSA is a temporary dependency which will + * be fixed by #7453. + */ +#if defined(MBEDTLS_ECP_C) || \ + defined(MBEDTLS_PK_PARSE_EC_EXTENDED) || \ + defined(MBEDTLS_PK_PARSE_EC_COMPRESSED) || \ + defined(MBEDTLS_PSA_BUILTIN_KEY_TYPE_ECC_KEY_PAIR_DERIVE) +#define MBEDTLS_ECP_LIGHT +#endif + +/* MBEDTLS_PK_PARSE_EC_COMPRESSED is introduced in Mbed TLS version 3.5, while + * in previous version compressed points were automatically supported as long + * as PK_PARSE_C and ECP_C were enabled. As a consequence, for backward + * compatibility, we auto-enable PK_PARSE_EC_COMPRESSED when these conditions + * are met. */ +#if defined(MBEDTLS_PK_PARSE_C) && defined(MBEDTLS_ECP_C) +#define MBEDTLS_PK_PARSE_EC_COMPRESSED +#endif + +/* Helper symbol to state that there is support for ECDH, either through + * library implementation (ECDH_C) or through PSA. */ +#if (defined(MBEDTLS_USE_PSA_CRYPTO) && defined(PSA_WANT_ALG_ECDH)) || \ + (!defined(MBEDTLS_USE_PSA_CRYPTO) && defined(MBEDTLS_ECDH_C)) +#define MBEDTLS_CAN_ECDH +#endif + +/* PK module can achieve ECDSA functionalities by means of either software + * implementations (ECDSA_C) or through a PSA driver. The following defines + * are meant to list these capabilities in a general way which abstracts how + * they are implemented under the hood. */ +#if !defined(MBEDTLS_USE_PSA_CRYPTO) +#if defined(MBEDTLS_ECDSA_C) +#define MBEDTLS_PK_CAN_ECDSA_SIGN +#define MBEDTLS_PK_CAN_ECDSA_VERIFY +#endif /* MBEDTLS_ECDSA_C */ +#else /* MBEDTLS_USE_PSA_CRYPTO */ +#if defined(PSA_WANT_ALG_ECDSA) +#if defined(PSA_WANT_KEY_TYPE_ECC_KEY_PAIR_BASIC) +#define MBEDTLS_PK_CAN_ECDSA_SIGN +#endif /* PSA_WANT_KEY_TYPE_ECC_KEY_PAIR_BASIC */ +#if defined(PSA_WANT_KEY_TYPE_ECC_PUBLIC_KEY) +#define MBEDTLS_PK_CAN_ECDSA_VERIFY +#endif /* PSA_WANT_KEY_TYPE_ECC_PUBLIC_KEY */ +#endif /* PSA_WANT_ALG_ECDSA */ +#endif /* MBEDTLS_USE_PSA_CRYPTO */ + +#if defined(MBEDTLS_PK_CAN_ECDSA_VERIFY) || defined(MBEDTLS_PK_CAN_ECDSA_SIGN) +#define MBEDTLS_PK_CAN_ECDSA_SOME +#endif + +/* If MBEDTLS_PSA_CRYPTO_C is defined, make sure MBEDTLS_PSA_CRYPTO_CLIENT + * is defined as well to include all PSA code. + */ +#if defined(MBEDTLS_PSA_CRYPTO_C) +#define MBEDTLS_PSA_CRYPTO_CLIENT +#endif /* MBEDTLS_PSA_CRYPTO_C */ + +/* Helpers to state that each key is supported either on the builtin or PSA side. */ +#if defined(MBEDTLS_ECP_DP_SECP521R1_ENABLED) || defined(PSA_WANT_ECC_SECP_R1_521) +#define MBEDTLS_ECP_HAVE_SECP521R1 +#endif +#if defined(MBEDTLS_ECP_DP_BP512R1_ENABLED) || defined(PSA_WANT_ECC_BRAINPOOL_P_R1_512) +#define MBEDTLS_ECP_HAVE_BP512R1 +#endif +#if defined(MBEDTLS_ECP_DP_CURVE448_ENABLED) || defined(PSA_WANT_ECC_MONTGOMERY_448) +#define MBEDTLS_ECP_HAVE_CURVE448 +#endif +#if defined(MBEDTLS_ECP_DP_BP384R1_ENABLED) || defined(PSA_WANT_ECC_BRAINPOOL_P_R1_384) +#define MBEDTLS_ECP_HAVE_BP384R1 +#endif +#if defined(MBEDTLS_ECP_DP_SECP384R1_ENABLED) || defined(PSA_WANT_ECC_SECP_R1_384) +#define MBEDTLS_ECP_HAVE_SECP384R1 +#endif +#if defined(MBEDTLS_ECP_DP_BP256R1_ENABLED) || defined(PSA_WANT_ECC_BRAINPOOL_P_R1_256) +#define MBEDTLS_ECP_HAVE_BP256R1 +#endif +#if defined(MBEDTLS_ECP_DP_SECP256K1_ENABLED) || defined(PSA_WANT_ECC_SECP_K1_256) +#define MBEDTLS_ECP_HAVE_SECP256K1 +#endif +#if defined(MBEDTLS_ECP_DP_SECP256R1_ENABLED) || defined(PSA_WANT_ECC_SECP_R1_256) +#define MBEDTLS_ECP_HAVE_SECP256R1 +#endif +#if defined(MBEDTLS_ECP_DP_CURVE25519_ENABLED) || defined(PSA_WANT_ECC_MONTGOMERY_255) +#define MBEDTLS_ECP_HAVE_CURVE25519 +#endif +#if defined(MBEDTLS_ECP_DP_SECP224K1_ENABLED) || defined(PSA_WANT_ECC_SECP_K1_224) +#define MBEDTLS_ECP_HAVE_SECP224K1 +#endif +#if defined(MBEDTLS_ECP_DP_SECP224R1_ENABLED) || defined(PSA_WANT_ECC_SECP_R1_224) +#define MBEDTLS_ECP_HAVE_SECP224R1 +#endif +#if defined(MBEDTLS_ECP_DP_SECP192K1_ENABLED) || defined(PSA_WANT_ECC_SECP_K1_192) +#define MBEDTLS_ECP_HAVE_SECP192K1 +#endif +#if defined(MBEDTLS_ECP_DP_SECP192R1_ENABLED) || defined(PSA_WANT_ECC_SECP_R1_192) +#define MBEDTLS_ECP_HAVE_SECP192R1 +#endif + +/* Helper symbol to state that the PK module has support for EC keys. This + * can either be provided through the legacy ECP solution or through the + * PSA friendly MBEDTLS_PK_USE_PSA_EC_DATA (see pk.h for its description). */ +#if defined(MBEDTLS_ECP_C) || \ + (defined(MBEDTLS_USE_PSA_CRYPTO) && defined(PSA_WANT_KEY_TYPE_ECC_PUBLIC_KEY)) +#define MBEDTLS_PK_HAVE_ECC_KEYS +#endif /* MBEDTLS_PK_USE_PSA_EC_DATA || MBEDTLS_ECP_C */ + +/* Historically pkparse did not check the CBC padding when decrypting + * a key. This was a bug, which is now fixed. As a consequence, pkparse + * now needs PKCS7 padding support, but existing configurations might not + * enable it, so we enable it here. */ +#if defined(MBEDTLS_PK_PARSE_C) && defined(MBEDTLS_PKCS5_C) && defined(MBEDTLS_CIPHER_MODE_CBC) +#define MBEDTLS_CIPHER_PADDING_PKCS7 +#endif + +/* Backwards compatibility for some macros which were renamed to reflect that + * they are related to Armv8, not aarch64. */ +#if defined(MBEDTLS_SHA256_USE_A64_CRYPTO_IF_PRESENT) && \ + !defined(MBEDTLS_SHA256_USE_ARMV8_A_CRYPTO_IF_PRESENT) +#define MBEDTLS_SHA256_USE_ARMV8_A_CRYPTO_IF_PRESENT +#endif +#if defined(MBEDTLS_SHA256_USE_A64_CRYPTO_ONLY) && !defined(MBEDTLS_SHA256_USE_ARMV8_A_CRYPTO_ONLY) +#define MBEDTLS_SHA256_USE_ARMV8_A_CRYPTO_ONLY +#endif + +/* psa_util file features some ECDSA conversion functions, to convert between + * legacy's ASN.1 DER format and PSA's raw one. */ +#if defined(MBEDTLS_ECDSA_C) || (defined(MBEDTLS_PSA_CRYPTO_C) && \ + (defined(PSA_WANT_ALG_ECDSA) || defined(PSA_WANT_ALG_DETERMINISTIC_ECDSA))) +#define MBEDTLS_PSA_UTIL_HAVE_ECDSA +#endif + +/* Some internal helpers to determine which keys are availble. */ +#if (!defined(MBEDTLS_USE_PSA_CRYPTO) && defined(MBEDTLS_AES_C)) || \ + (defined(MBEDTLS_USE_PSA_CRYPTO) && defined(PSA_WANT_KEY_TYPE_AES)) +#define MBEDTLS_SSL_HAVE_AES +#endif +#if (!defined(MBEDTLS_USE_PSA_CRYPTO) && defined(MBEDTLS_ARIA_C)) || \ + (defined(MBEDTLS_USE_PSA_CRYPTO) && defined(PSA_WANT_KEY_TYPE_ARIA)) +#define MBEDTLS_SSL_HAVE_ARIA +#endif +#if (!defined(MBEDTLS_USE_PSA_CRYPTO) && defined(MBEDTLS_CAMELLIA_C)) || \ + (defined(MBEDTLS_USE_PSA_CRYPTO) && defined(PSA_WANT_KEY_TYPE_CAMELLIA)) +#define MBEDTLS_SSL_HAVE_CAMELLIA +#endif + +/* Some internal helpers to determine which operation modes are availble. */ +#if (!defined(MBEDTLS_USE_PSA_CRYPTO) && defined(MBEDTLS_CIPHER_MODE_CBC)) || \ + (defined(MBEDTLS_USE_PSA_CRYPTO) && defined(PSA_WANT_ALG_CBC_NO_PADDING)) +#define MBEDTLS_SSL_HAVE_CBC +#endif + +#if (!defined(MBEDTLS_USE_PSA_CRYPTO) && defined(MBEDTLS_GCM_C)) || \ + (defined(MBEDTLS_USE_PSA_CRYPTO) && defined(PSA_WANT_ALG_GCM)) +#define MBEDTLS_SSL_HAVE_GCM +#endif + +#if (!defined(MBEDTLS_USE_PSA_CRYPTO) && defined(MBEDTLS_CCM_C)) || \ + (defined(MBEDTLS_USE_PSA_CRYPTO) && defined(PSA_WANT_ALG_CCM)) +#define MBEDTLS_SSL_HAVE_CCM +#endif + +#if (!defined(MBEDTLS_USE_PSA_CRYPTO) && defined(MBEDTLS_CHACHAPOLY_C)) || \ + (defined(MBEDTLS_USE_PSA_CRYPTO) && defined(PSA_WANT_ALG_CHACHA20_POLY1305)) +#define MBEDTLS_SSL_HAVE_CHACHAPOLY +#endif + +#if defined(MBEDTLS_SSL_HAVE_GCM) || defined(MBEDTLS_SSL_HAVE_CCM) || \ + defined(MBEDTLS_SSL_HAVE_CHACHAPOLY) +#define MBEDTLS_SSL_HAVE_AEAD +#endif + +#endif /* MBEDTLS_CONFIG_ADJUST_LEGACY_CRYPTO_H */ diff --git a/vendor/mbedtls/include/mbedtls/config_adjust_legacy_from_psa.h b/vendor/mbedtls/include/mbedtls/config_adjust_legacy_from_psa.h new file mode 100644 index 0000000000..0091e246b2 --- /dev/null +++ b/vendor/mbedtls/include/mbedtls/config_adjust_legacy_from_psa.h @@ -0,0 +1,888 @@ +/** + * \file mbedtls/config_adjust_legacy_from_psa.h + * \brief Adjust PSA configuration: activate legacy implementations + * + * When MBEDTLS_PSA_CRYPTO_CONFIG is enabled, activate legacy implementations + * of cryptographic mechanisms as needed to fulfill the needs of the PSA + * configuration. Generally speaking, we activate a legacy mechanism if + * it's needed for a requested PSA mechanism and there is no PSA driver + * for it. + */ +/* + * Copyright The Mbed TLS Contributors + * SPDX-License-Identifier: Apache-2.0 OR GPL-2.0-or-later + */ + +#ifndef MBEDTLS_CONFIG_ADJUST_LEGACY_FROM_PSA_H +#define MBEDTLS_CONFIG_ADJUST_LEGACY_FROM_PSA_H + +/* Define appropriate ACCEL macros for the p256-m driver. + * In the future, those should be generated from the drivers JSON description. + */ +#if defined(MBEDTLS_PSA_P256M_DRIVER_ENABLED) +#define MBEDTLS_PSA_ACCEL_ECC_SECP_R1_256 +#define MBEDTLS_PSA_ACCEL_ALG_ECDSA +#define MBEDTLS_PSA_ACCEL_ALG_ECDH +#define MBEDTLS_PSA_ACCEL_KEY_TYPE_ECC_PUBLIC_KEY +#define MBEDTLS_PSA_ACCEL_KEY_TYPE_ECC_KEY_PAIR_BASIC +#define MBEDTLS_PSA_ACCEL_KEY_TYPE_ECC_KEY_PAIR_IMPORT +#define MBEDTLS_PSA_ACCEL_KEY_TYPE_ECC_KEY_PAIR_EXPORT +#define MBEDTLS_PSA_ACCEL_KEY_TYPE_ECC_KEY_PAIR_GENERATE +#endif + +/* + * ECC: support for a feature is controlled by a triplet or a pair: + * (curve, key_type public/basic, alg) or (curve, key_type_). + * + * A triplet/pair is accelerated if all of is components are accelerated; + * otherwise each component needs to be built in. + * + * We proceed in two passes: + * 1. Check if acceleration is complete for curves, key types, algs. + * 2. Then enable built-ins for each thing that's either not accelerated of + * doesn't have complete acceleration of the other triplet/pair components. + * + * Note: this needs psa/crypto_adjust_keypair_types.h to have been included + * already, so that we know the full set of key types that are requested. + */ + +/* ECC: curves: is acceleration complete? */ +#if (defined(PSA_WANT_ECC_BRAINPOOL_P_R1_256) && \ + !defined(MBEDTLS_PSA_ACCEL_ECC_BRAINPOOL_P_R1_256)) || \ + (defined(PSA_WANT_ECC_BRAINPOOL_P_R1_384) && \ + !defined(MBEDTLS_PSA_ACCEL_ECC_BRAINPOOL_P_R1_384)) || \ + (defined(PSA_WANT_ECC_BRAINPOOL_P_R1_512) && \ + !defined(MBEDTLS_PSA_ACCEL_ECC_BRAINPOOL_P_R1_512)) || \ + (defined(PSA_WANT_ECC_SECP_R1_192) && !defined(MBEDTLS_PSA_ACCEL_ECC_SECP_R1_192)) || \ + (defined(PSA_WANT_ECC_SECP_R1_224) && !defined(MBEDTLS_PSA_ACCEL_ECC_SECP_R1_224)) || \ + (defined(PSA_WANT_ECC_SECP_R1_256) && !defined(MBEDTLS_PSA_ACCEL_ECC_SECP_R1_256)) || \ + (defined(PSA_WANT_ECC_SECP_R1_384) && !defined(MBEDTLS_PSA_ACCEL_ECC_SECP_R1_384)) || \ + (defined(PSA_WANT_ECC_SECP_R1_521) && !defined(MBEDTLS_PSA_ACCEL_ECC_SECP_R1_521)) || \ + (defined(PSA_WANT_ECC_SECP_K1_192) && !defined(MBEDTLS_PSA_ACCEL_ECC_SECP_K1_192)) || \ + (defined(PSA_WANT_ECC_SECP_K1_224) && !defined(MBEDTLS_PSA_ACCEL_ECC_SECP_K1_224)) || \ + (defined(PSA_WANT_ECC_SECP_K1_256) && !defined(MBEDTLS_PSA_ACCEL_ECC_SECP_K1_256)) +#define MBEDTLS_PSA_ECC_ACCEL_INCOMPLETE_CURVES +#define MBEDTLS_PSA_ECC_ACCEL_INCOMPLETE_WEIERSTRASS_CURVES +#endif + +#if (defined(PSA_WANT_ECC_MONTGOMERY_255) && !defined(MBEDTLS_PSA_ACCEL_ECC_MONTGOMERY_255)) || \ + (defined(PSA_WANT_ECC_MONTGOMERY_448) && !defined(MBEDTLS_PSA_ACCEL_ECC_MONTGOMERY_448)) +#define MBEDTLS_PSA_ECC_ACCEL_INCOMPLETE_CURVES +#endif + +/* ECC: algs: is acceleration complete? */ +#if (defined(PSA_WANT_ALG_ECDH) && !defined(MBEDTLS_PSA_ACCEL_ALG_ECDH)) || \ + (defined(PSA_WANT_ALG_ECDSA) && !defined(MBEDTLS_PSA_ACCEL_ALG_ECDSA)) || \ + (defined(PSA_WANT_ALG_DETERMINISTIC_ECDSA) && \ + !defined(MBEDTLS_PSA_ACCEL_ALG_DETERMINISTIC_ECDSA)) || \ + (defined(PSA_WANT_ALG_JPAKE) && !defined(MBEDTLS_PSA_ACCEL_ALG_JPAKE)) +#define MBEDTLS_PSA_ECC_ACCEL_INCOMPLETE_ALGS +#endif + +/* ECC: key types: is acceleration complete? */ +#if (defined(PSA_WANT_KEY_TYPE_ECC_PUBLIC_KEY) && \ + !defined(MBEDTLS_PSA_ACCEL_KEY_TYPE_ECC_PUBLIC_KEY)) || \ + (defined(PSA_WANT_KEY_TYPE_ECC_KEY_PAIR_BASIC) && \ + !defined(MBEDTLS_PSA_ACCEL_KEY_TYPE_ECC_KEY_PAIR_BASIC)) +#define MBEDTLS_PSA_ECC_ACCEL_INCOMPLETE_KEY_TYPES_BASIC +#endif + +/* Special case: we don't support cooked key derivation in drivers yet */ +#if defined(MBEDTLS_PSA_ACCEL_KEY_TYPE_ECC_KEY_PAIR_DERIVE) +#undef MBEDTLS_PSA_ACCEL_KEY_TYPE_ECC_KEY_PAIR_DERIVE +#endif + +/* Note: the condition about key derivation is always true as DERIVE can't be + * accelerated yet */ +#if (defined(PSA_WANT_KEY_TYPE_ECC_PUBLIC_KEY) && \ + !defined(MBEDTLS_PSA_ACCEL_KEY_TYPE_ECC_PUBLIC_KEY)) || \ + (defined(PSA_WANT_KEY_TYPE_ECC_KEY_PAIR_BASIC) && \ + !defined(MBEDTLS_PSA_ACCEL_KEY_TYPE_ECC_KEY_PAIR_BASIC)) || \ + (defined(PSA_WANT_KEY_TYPE_ECC_KEY_PAIR_IMPORT) && \ + !defined(MBEDTLS_PSA_ACCEL_KEY_TYPE_ECC_KEY_PAIR_IMPORT)) || \ + (defined(PSA_WANT_KEY_TYPE_ECC_KEY_PAIR_EXPORT) && \ + !defined(MBEDTLS_PSA_ACCEL_KEY_TYPE_ECC_KEY_PAIR_EXPORT)) || \ + (defined(PSA_WANT_KEY_TYPE_ECC_KEY_PAIR_GENERATE) && \ + !defined(MBEDTLS_PSA_ACCEL_KEY_TYPE_ECC_KEY_PAIR_GENERATE)) || \ + (defined(PSA_WANT_KEY_TYPE_ECC_KEY_PAIR_DERIVE) && \ + !defined(MBEDTLS_PSA_ACCEL_KEY_TYPE_ECC_KEY_PAIR_DERIVE)) +#define MBEDTLS_PSA_ECC_ACCEL_INCOMPLETE_KEY_TYPES +#endif + +/* ECC: curves: enable built-ins as needed. + * + * We need the curve built-in: + * - if it's not accelerated, or + * - if there's a key type with missing acceleration, or + * - if there's a alg with missing acceleration. + */ +#if defined(PSA_WANT_ECC_BRAINPOOL_P_R1_256) +#if !defined(MBEDTLS_PSA_ACCEL_ECC_BRAINPOOL_P_R1_256) || \ + defined(MBEDTLS_PSA_ECC_ACCEL_INCOMPLETE_KEY_TYPES) || \ + defined(MBEDTLS_PSA_ECC_ACCEL_INCOMPLETE_ALGS) +#define MBEDTLS_PSA_BUILTIN_ECC_BRAINPOOL_P_R1_256 1 +#define MBEDTLS_ECP_DP_BP256R1_ENABLED +#endif /* missing accel */ +#endif /* PSA_WANT_ECC_BRAINPOOL_P_R1_256 */ + +#if defined(PSA_WANT_ECC_BRAINPOOL_P_R1_384) +#if !defined(MBEDTLS_PSA_ACCEL_ECC_BRAINPOOL_P_R1_384) || \ + defined(MBEDTLS_PSA_ECC_ACCEL_INCOMPLETE_KEY_TYPES) || \ + defined(MBEDTLS_PSA_ECC_ACCEL_INCOMPLETE_ALGS) +#define MBEDTLS_PSA_BUILTIN_ECC_BRAINPOOL_P_R1_384 1 +#define MBEDTLS_ECP_DP_BP384R1_ENABLED +#endif /* missing accel */ +#endif /* PSA_WANT_ECC_BRAINPOOL_P_R1_384 */ + +#if defined(PSA_WANT_ECC_BRAINPOOL_P_R1_512) +#if !defined(MBEDTLS_PSA_ACCEL_ECC_BRAINPOOL_P_R1_512) || \ + defined(MBEDTLS_PSA_ECC_ACCEL_INCOMPLETE_KEY_TYPES) || \ + defined(MBEDTLS_PSA_ECC_ACCEL_INCOMPLETE_ALGS) +#define MBEDTLS_PSA_BUILTIN_ECC_BRAINPOOL_P_R1_512 1 +#define MBEDTLS_ECP_DP_BP512R1_ENABLED +#endif /* missing accel */ +#endif /* PSA_WANT_ECC_BRAINPOOL_P_R1_512 */ + +#if defined(PSA_WANT_ECC_MONTGOMERY_255) +#if !defined(MBEDTLS_PSA_ACCEL_ECC_MONTGOMERY_255) || \ + defined(MBEDTLS_PSA_ECC_ACCEL_INCOMPLETE_KEY_TYPES) || \ + defined(MBEDTLS_PSA_ECC_ACCEL_INCOMPLETE_ALGS) +#define MBEDTLS_PSA_BUILTIN_ECC_MONTGOMERY_255 1 +#define MBEDTLS_ECP_DP_CURVE25519_ENABLED +#endif /* missing accel */ +#endif /* PSA_WANT_ECC_MONTGOMERY_255 */ + +#if defined(PSA_WANT_ECC_MONTGOMERY_448) +#if !defined(MBEDTLS_PSA_ACCEL_ECC_MONTGOMERY_448) || \ + defined(MBEDTLS_PSA_ECC_ACCEL_INCOMPLETE_KEY_TYPES) || \ + defined(MBEDTLS_PSA_ECC_ACCEL_INCOMPLETE_ALGS) +#define MBEDTLS_PSA_BUILTIN_ECC_MONTGOMERY_448 1 +#define MBEDTLS_ECP_DP_CURVE448_ENABLED +#endif /* missing accel */ +#endif /* PSA_WANT_ECC_MONTGOMERY_448 */ + +#if defined(PSA_WANT_ECC_SECP_R1_192) +#if !defined(MBEDTLS_PSA_ACCEL_ECC_SECP_R1_192) || \ + defined(MBEDTLS_PSA_ECC_ACCEL_INCOMPLETE_KEY_TYPES) || \ + defined(MBEDTLS_PSA_ECC_ACCEL_INCOMPLETE_ALGS) +#define MBEDTLS_PSA_BUILTIN_ECC_SECP_R1_192 1 +#define MBEDTLS_ECP_DP_SECP192R1_ENABLED +#endif /* missing accel */ +#endif /* PSA_WANT_ECC_SECP_R1_192 */ + +#if defined(PSA_WANT_ECC_SECP_R1_224) +#if !defined(MBEDTLS_PSA_ACCEL_ECC_SECP_R1_224) || \ + defined(MBEDTLS_PSA_ECC_ACCEL_INCOMPLETE_KEY_TYPES) || \ + defined(MBEDTLS_PSA_ECC_ACCEL_INCOMPLETE_ALGS) +#define MBEDTLS_PSA_BUILTIN_ECC_SECP_R1_224 1 +#define MBEDTLS_ECP_DP_SECP224R1_ENABLED +#endif /* missing accel */ +#endif /* PSA_WANT_ECC_SECP_R1_224 */ + +#if defined(PSA_WANT_ECC_SECP_R1_256) +#if !defined(MBEDTLS_PSA_ACCEL_ECC_SECP_R1_256) || \ + defined(MBEDTLS_PSA_ECC_ACCEL_INCOMPLETE_KEY_TYPES) || \ + defined(MBEDTLS_PSA_ECC_ACCEL_INCOMPLETE_ALGS) +#define MBEDTLS_PSA_BUILTIN_ECC_SECP_R1_256 1 +#define MBEDTLS_ECP_DP_SECP256R1_ENABLED +#endif /* missing accel */ +#endif /* PSA_WANT_ECC_SECP_R1_256 */ + +#if defined(PSA_WANT_ECC_SECP_R1_384) +#if !defined(MBEDTLS_PSA_ACCEL_ECC_SECP_R1_384) || \ + defined(MBEDTLS_PSA_ECC_ACCEL_INCOMPLETE_KEY_TYPES) || \ + defined(MBEDTLS_PSA_ECC_ACCEL_INCOMPLETE_ALGS) +#define MBEDTLS_PSA_BUILTIN_ECC_SECP_R1_384 1 +#define MBEDTLS_ECP_DP_SECP384R1_ENABLED +#endif /* missing accel */ +#endif /* PSA_WANT_ECC_SECP_R1_384 */ + +#if defined(PSA_WANT_ECC_SECP_R1_521) +#if !defined(MBEDTLS_PSA_ACCEL_ECC_SECP_R1_521) || \ + defined(MBEDTLS_PSA_ECC_ACCEL_INCOMPLETE_KEY_TYPES) || \ + defined(MBEDTLS_PSA_ECC_ACCEL_INCOMPLETE_ALGS) +#define MBEDTLS_PSA_BUILTIN_ECC_SECP_R1_521 1 +#define MBEDTLS_ECP_DP_SECP521R1_ENABLED +#endif /* missing accel */ +#endif /* PSA_WANT_ECC_SECP_R1_521 */ + +#if defined(PSA_WANT_ECC_SECP_K1_192) +#if !defined(MBEDTLS_PSA_ACCEL_ECC_SECP_K1_192) || \ + defined(MBEDTLS_PSA_ECC_ACCEL_INCOMPLETE_KEY_TYPES) || \ + defined(MBEDTLS_PSA_ECC_ACCEL_INCOMPLETE_ALGS) +#define MBEDTLS_PSA_BUILTIN_ECC_SECP_K1_192 1 +#define MBEDTLS_ECP_DP_SECP192K1_ENABLED +#endif /* missing accel */ +#endif /* PSA_WANT_ECC_SECP_K1_192 */ + +#if defined(PSA_WANT_ECC_SECP_K1_224) +#if !defined(MBEDTLS_PSA_ACCEL_ECC_SECP_K1_224) || \ + defined(MBEDTLS_PSA_ECC_ACCEL_INCOMPLETE_KEY_TYPES) || \ + defined(MBEDTLS_PSA_ECC_ACCEL_INCOMPLETE_ALGS) +#define MBEDTLS_PSA_BUILTIN_ECC_SECP_K1_224 1 +#define MBEDTLS_ECP_DP_SECP224K1_ENABLED +/* https://github.com/Mbed-TLS/mbedtls/issues/3541 */ +#error "SECP224K1 is buggy via the PSA API in Mbed TLS." +#endif /* missing accel */ +#endif /* PSA_WANT_ECC_SECP_K1_224 */ + +#if defined(PSA_WANT_ECC_SECP_K1_256) +#if !defined(MBEDTLS_PSA_ACCEL_ECC_SECP_K1_256) || \ + defined(MBEDTLS_PSA_ECC_ACCEL_INCOMPLETE_KEY_TYPES) || \ + defined(MBEDTLS_PSA_ECC_ACCEL_INCOMPLETE_ALGS) +#define MBEDTLS_PSA_BUILTIN_ECC_SECP_K1_256 1 +#define MBEDTLS_ECP_DP_SECP256K1_ENABLED +#endif /* missing accel */ +#endif /* PSA_WANT_ECC_SECP_K1_256 */ + +/* ECC: algs: enable built-ins as needed. + * + * We need the alg built-in: + * - if it's not accelerated, or + * - if there's a relevant curve (see below) with missing acceleration, or + * - if there's a key type among (public, basic) with missing acceleration. + * + * Relevant curves are: + * - all curves for ECDH + * - Weierstrass curves for (deterministic) ECDSA + * - secp256r1 for EC J-PAKE + */ +#if defined(PSA_WANT_ALG_DETERMINISTIC_ECDSA) +#if !defined(MBEDTLS_PSA_ACCEL_ALG_DETERMINISTIC_ECDSA) || \ + defined(MBEDTLS_PSA_ECC_ACCEL_INCOMPLETE_WEIERSTRASS_CURVES) || \ + defined(MBEDTLS_PSA_ECC_ACCEL_INCOMPLETE_KEY_TYPES_BASIC) +#define MBEDTLS_PSA_BUILTIN_ALG_DETERMINISTIC_ECDSA 1 +#define MBEDTLS_ECDSA_DETERMINISTIC +#define MBEDTLS_HMAC_DRBG_C +#define MBEDTLS_MD_C +#define MBEDTLS_ECDSA_C +#define MBEDTLS_ECP_C +#define MBEDTLS_BIGNUM_C +#define MBEDTLS_ASN1_PARSE_C +#define MBEDTLS_ASN1_WRITE_C +#endif /* missing accel */ +#endif /* PSA_WANT_ALG_DETERMINISTIC_ECDSA */ + +#if defined(PSA_WANT_ALG_ECDH) +#if !defined(MBEDTLS_PSA_ACCEL_ALG_ECDH) || \ + defined(MBEDTLS_PSA_ECC_ACCEL_INCOMPLETE_CURVES) || \ + defined(MBEDTLS_PSA_ECC_ACCEL_INCOMPLETE_KEY_TYPES_BASIC) +#define MBEDTLS_PSA_BUILTIN_ALG_ECDH 1 +#define MBEDTLS_ECDH_C +#define MBEDTLS_ECP_C +#define MBEDTLS_BIGNUM_C +#endif /* missing accel */ +#endif /* PSA_WANT_ALG_ECDH */ + +#if defined(PSA_WANT_ALG_ECDSA) +#if !defined(MBEDTLS_PSA_ACCEL_ALG_ECDSA) || \ + defined(MBEDTLS_PSA_ECC_ACCEL_INCOMPLETE_WEIERSTRASS_CURVES) || \ + defined(MBEDTLS_PSA_ECC_ACCEL_INCOMPLETE_KEY_TYPES_BASIC) +#define MBEDTLS_PSA_BUILTIN_ALG_ECDSA 1 +#define MBEDTLS_ECDSA_C +#define MBEDTLS_ECP_C +#define MBEDTLS_BIGNUM_C +#define MBEDTLS_ASN1_PARSE_C +#define MBEDTLS_ASN1_WRITE_C +#endif /* missing accel */ +#endif /* PSA_WANT_ALG_ECDSA */ + +#if defined(PSA_WANT_ALG_JPAKE) +#if !defined(MBEDTLS_PSA_ACCEL_ALG_JPAKE) || \ + !defined(MBEDTLS_PSA_ACCEL_ECC_SECP_R1_256) || \ + defined(MBEDTLS_PSA_ECC_ACCEL_INCOMPLETE_KEY_TYPES_BASIC) +#define MBEDTLS_PSA_BUILTIN_PAKE 1 +#define MBEDTLS_PSA_BUILTIN_ALG_JPAKE 1 +#define MBEDTLS_ECP_DP_SECP256R1_ENABLED +#define MBEDTLS_BIGNUM_C +#define MBEDTLS_ECP_C +#define MBEDTLS_ECJPAKE_C +#endif /* missing accel */ +#endif /* PSA_WANT_ALG_JPAKE */ + +/* ECC: key types: enable built-ins as needed. + * + * We need the key type built-in: + * - if it's not accelerated, or + * - if there's a curve with missing acceleration, or + * - only for public/basic: if there's an alg with missing acceleration. + */ +#if defined(PSA_WANT_KEY_TYPE_ECC_PUBLIC_KEY) +#if !defined(MBEDTLS_PSA_ACCEL_KEY_TYPE_ECC_PUBLIC_KEY) || \ + defined(MBEDTLS_PSA_ECC_ACCEL_INCOMPLETE_CURVES) || \ + defined(MBEDTLS_PSA_ECC_ACCEL_INCOMPLETE_ALGS) +#define MBEDTLS_PSA_BUILTIN_KEY_TYPE_ECC_PUBLIC_KEY 1 +#endif /* missing accel */ +#endif /* PSA_WANT_KEY_TYPE_ECC_PUBLIC_KEY */ + +#if defined(PSA_WANT_KEY_TYPE_ECC_KEY_PAIR_BASIC) +#if !defined(MBEDTLS_PSA_ACCEL_KEY_TYPE_ECC_KEY_PAIR_BASIC) || \ + defined(MBEDTLS_PSA_ECC_ACCEL_INCOMPLETE_CURVES) || \ + defined(MBEDTLS_PSA_ECC_ACCEL_INCOMPLETE_ALGS) +#define MBEDTLS_PSA_BUILTIN_KEY_TYPE_ECC_KEY_PAIR_BASIC 1 +#endif /* missing accel */ +#endif /* PSA_WANT_KEY_TYPE_ECC_KEY_PAIR_BASIC */ + +#if defined(PSA_WANT_KEY_TYPE_ECC_KEY_PAIR_IMPORT) +#if !defined(MBEDTLS_PSA_ACCEL_KEY_TYPE_ECC_KEY_PAIR_IMPORT) || \ + defined(MBEDTLS_PSA_ECC_ACCEL_INCOMPLETE_CURVES) +#define MBEDTLS_PSA_BUILTIN_KEY_TYPE_ECC_KEY_PAIR_IMPORT 1 +#endif /* missing accel */ +#endif /* PSA_WANT_KEY_TYPE_ECC_KEY_PAIR_IMPORT */ + +#if defined(PSA_WANT_KEY_TYPE_ECC_KEY_PAIR_EXPORT) +#if !defined(MBEDTLS_PSA_ACCEL_KEY_TYPE_ECC_KEY_PAIR_EXPORT) || \ + defined(MBEDTLS_PSA_ECC_ACCEL_INCOMPLETE_CURVES) +#define MBEDTLS_PSA_BUILTIN_KEY_TYPE_ECC_KEY_PAIR_EXPORT 1 +#endif /* missing accel */ +#endif /* PSA_WANT_KEY_TYPE_ECC_KEY_PAIR_EXPORT */ + +#if defined(PSA_WANT_KEY_TYPE_ECC_KEY_PAIR_GENERATE) +#if !defined(MBEDTLS_PSA_ACCEL_KEY_TYPE_ECC_KEY_PAIR_GENERATE) || \ + defined(MBEDTLS_PSA_ECC_ACCEL_INCOMPLETE_CURVES) +#define MBEDTLS_PSA_BUILTIN_KEY_TYPE_ECC_KEY_PAIR_GENERATE 1 +#endif /* missing accel */ +#endif /* PSA_WANT_KEY_TYPE_ECC_KEY_PAIR_GENERATE */ + +/* Note: the condition is always true as DERIVE can't be accelerated yet */ +#if defined(PSA_WANT_KEY_TYPE_ECC_KEY_PAIR_DERIVE) +#if !defined(MBEDTLS_PSA_ACCEL_KEY_TYPE_ECC_KEY_PAIR_DERIVE) || \ + defined(MBEDTLS_PSA_ECC_ACCEL_INCOMPLETE_CURVES) +#define MBEDTLS_PSA_BUILTIN_KEY_TYPE_ECC_KEY_PAIR_DERIVE 1 +#endif /* missing accel */ +#endif /* !MBEDTLS_PSA_ACCEL_KEY_TYPE_ECC_KEY_PAIR_DERIVE */ + +#if defined(MBEDTLS_PSA_BUILTIN_KEY_TYPE_ECC_PUBLIC_KEY) || \ + defined(MBEDTLS_PSA_BUILTIN_KEY_TYPE_ECC_KEY_PAIR_BASIC) || \ + defined(MBEDTLS_PSA_BUILTIN_KEY_TYPE_ECC_KEY_PAIR_IMPORT) || \ + defined(MBEDTLS_PSA_BUILTIN_KEY_TYPE_ECC_KEY_PAIR_DERIVE) +#define MBEDTLS_ECP_LIGHT +#define MBEDTLS_BIGNUM_C +#endif + +#if defined(MBEDTLS_PSA_BUILTIN_KEY_TYPE_ECC_KEY_PAIR_EXPORT) || \ + defined(MBEDTLS_PSA_BUILTIN_KEY_TYPE_ECC_KEY_PAIR_GENERATE) +#define MBEDTLS_ECP_C +#define MBEDTLS_BIGNUM_C +#endif + +/* End of ECC section */ + +/* + * DH key types follow the same pattern used above for EC keys. They are defined + * by a triplet (group, key_type, alg). A triplet is accelerated if all its + * component are accelerated, otherwise each component needs to be builtin. + */ + +/* DH: groups: is acceleration complete? */ +#if (defined(PSA_WANT_DH_RFC7919_2048) && !defined(MBEDTLS_PSA_ACCEL_DH_RFC7919_2048)) || \ + (defined(PSA_WANT_DH_RFC7919_3072) && !defined(MBEDTLS_PSA_ACCEL_DH_RFC7919_3072)) || \ + (defined(PSA_WANT_DH_RFC7919_4096) && !defined(MBEDTLS_PSA_ACCEL_DH_RFC7919_4096)) || \ + (defined(PSA_WANT_DH_RFC7919_6144) && !defined(MBEDTLS_PSA_ACCEL_DH_RFC7919_6144)) || \ + (defined(PSA_WANT_DH_RFC7919_8192) && !defined(MBEDTLS_PSA_ACCEL_DH_RFC7919_8192)) +#define MBEDTLS_PSA_DH_ACCEL_INCOMPLETE_GROUPS +#endif + +/* DH: algs: is acceleration complete? */ +#if defined(PSA_WANT_ALG_FFDH) && !defined(MBEDTLS_PSA_ACCEL_ALG_FFDH) +#define MBEDTLS_PSA_DH_ACCEL_INCOMPLETE_ALGS +#endif + +/* DH: key types: is acceleration complete? */ +#if (defined(PSA_WANT_KEY_TYPE_DH_PUBLIC_KEY) && \ + !defined(MBEDTLS_PSA_ACCEL_KEY_TYPE_DH_PUBLIC_KEY)) || \ + (defined(PSA_WANT_KEY_TYPE_DH_KEY_PAIR_BASIC) && \ + !defined(MBEDTLS_PSA_ACCEL_KEY_TYPE_DH_KEY_PAIR_BASIC)) || \ + (defined(PSA_WANT_KEY_TYPE_DH_KEY_PAIR_IMPORT) && \ + !defined(MBEDTLS_PSA_ACCEL_KEY_TYPE_DH_KEY_PAIR_IMPORT)) || \ + (defined(PSA_WANT_KEY_TYPE_DH_KEY_PAIR_EXPORT) && \ + !defined(MBEDTLS_PSA_ACCEL_KEY_TYPE_DH_KEY_PAIR_EXPORT)) || \ + (defined(PSA_WANT_KEY_TYPE_DH_KEY_PAIR_GENERATE) && \ + !defined(MBEDTLS_PSA_ACCEL_KEY_TYPE_DH_KEY_PAIR_GENERATE)) +#define MBEDTLS_PSA_DH_ACCEL_INCOMPLETE_KEY_TYPES +#endif + +#if defined(PSA_WANT_DH_RFC7919_2048) +#if !defined(MBEDTLS_PSA_ACCEL_DH_RFC7919_2048) || \ + defined(MBEDTLS_PSA_DH_ACCEL_INCOMPLETE_ALGS) || \ + defined(MBEDTLS_PSA_DH_ACCEL_INCOMPLETE_KEY_TYPES) +#define MBEDTLS_PSA_BUILTIN_DH_RFC7919_2048 1 +#endif /* !MBEDTLS_PSA_BUILTIN_DH_RFC7919_2048 */ +#endif /* PSA_WANT_DH_RFC7919_2048 */ + +#if defined(PSA_WANT_DH_RFC7919_3072) +#if !defined(MBEDTLS_PSA_ACCEL_DH_RFC7919_3072) || \ + defined(MBEDTLS_PSA_DH_ACCEL_INCOMPLETE_ALGS) || \ + defined(MBEDTLS_PSA_DH_ACCEL_INCOMPLETE_KEY_TYPES) +#define MBEDTLS_PSA_BUILTIN_DH_RFC7919_3072 1 +#endif /* !MBEDTLS_PSA_BUILTIN_DH_RFC7919_3072 */ +#endif /* PSA_WANT_DH_RFC7919_3072 */ + +#if defined(PSA_WANT_DH_RFC7919_4096) +#if !defined(MBEDTLS_PSA_ACCEL_DH_RFC7919_4096) || \ + defined(MBEDTLS_PSA_DH_ACCEL_INCOMPLETE_ALGS) || \ + defined(MBEDTLS_PSA_DH_ACCEL_INCOMPLETE_KEY_TYPES) +#define MBEDTLS_PSA_BUILTIN_DH_RFC7919_4096 1 +#endif /* !MBEDTLS_PSA_BUILTIN_DH_RFC7919_4096 */ +#endif /* PSA_WANT_DH_RFC7919_4096 */ + +#if defined(PSA_WANT_DH_RFC7919_6144) +#if !defined(MBEDTLS_PSA_ACCEL_DH_RFC7919_6144) || \ + defined(MBEDTLS_PSA_DH_ACCEL_INCOMPLETE_ALGS) || \ + defined(MBEDTLS_PSA_DH_ACCEL_INCOMPLETE_KEY_TYPES) +#define MBEDTLS_PSA_BUILTIN_DH_RFC7919_6144 1 +#endif /* !MBEDTLS_PSA_BUILTIN_DH_RFC7919_6144 */ +#endif /* PSA_WANT_DH_RFC7919_6144 */ + +#if defined(PSA_WANT_DH_RFC7919_8192) +#if !defined(MBEDTLS_PSA_ACCEL_DH_RFC7919_8192) || \ + defined(MBEDTLS_PSA_DH_ACCEL_INCOMPLETE_ALGS) || \ + defined(MBEDTLS_PSA_DH_ACCEL_INCOMPLETE_KEY_TYPES) +#define MBEDTLS_PSA_BUILTIN_DH_RFC7919_8192 1 +#endif /* !MBEDTLS_PSA_BUILTIN_DH_RFC7919_8192 */ +#endif /* PSA_WANT_DH_RFC7919_8192 */ + +#if defined(PSA_WANT_ALG_FFDH) +#if !defined(MBEDTLS_PSA_ACCEL_ALG_FFDH) || \ + defined(MBEDTLS_PSA_DH_ACCEL_INCOMPLETE_GROUPS) || \ + defined(MBEDTLS_PSA_DH_ACCEL_INCOMPLETE_KEY_TYPES) +#define MBEDTLS_PSA_BUILTIN_ALG_FFDH 1 +#define MBEDTLS_BIGNUM_C +#endif /* !MBEDTLS_PSA_ACCEL_ALG_FFDH */ +#endif /* PSA_WANT_ALG_FFDH */ + +#if defined(PSA_WANT_KEY_TYPE_DH_KEY_PAIR_IMPORT) +#if !defined(MBEDTLS_PSA_ACCEL_KEY_TYPE_DH_KEY_PAIR_IMPORT) || \ + defined(MBEDTLS_PSA_DH_ACCEL_INCOMPLETE_GROUPS) || \ + defined(MBEDTLS_PSA_DH_ACCEL_INCOMPLETE_ALGS) +#define MBEDTLS_PSA_BUILTIN_KEY_TYPE_DH_KEY_PAIR_IMPORT 1 +#endif /* !MBEDTLS_PSA_ACCEL_KEY_TYPE_DH_KEY_PAIR_IMPORT */ +#endif /* PSA_WANT_KEY_TYPE_DH_KEY_PAIR_IMPORT */ + +#if defined(PSA_WANT_KEY_TYPE_DH_KEY_PAIR_EXPORT) +#if !defined(MBEDTLS_PSA_ACCEL_KEY_TYPE_DH_KEY_PAIR_EXPORT) || \ + defined(MBEDTLS_PSA_DH_ACCEL_INCOMPLETE_GROUPS) || \ + defined(MBEDTLS_PSA_DH_ACCEL_INCOMPLETE_ALGS) +#define MBEDTLS_PSA_BUILTIN_KEY_TYPE_DH_KEY_PAIR_EXPORT 1 +#endif /* !MBEDTLS_PSA_ACCEL_KEY_TYPE_DH_KEY_PAIR_EXPORT */ +#endif /* PSA_WANT_KEY_TYPE_DH_KEY_PAIR_EXPORT */ + +#if defined(PSA_WANT_KEY_TYPE_DH_KEY_PAIR_GENERATE) +#if !defined(MBEDTLS_PSA_ACCEL_KEY_TYPE_DH_KEY_PAIR_GENERATE) +#define MBEDTLS_PSA_BUILTIN_KEY_TYPE_DH_KEY_PAIR_GENERATE 1 +#endif /* !MBEDTLS_PSA_ACCEL_KEY_TYPE_DH_KEY_PAIR_GENERATE */ +#endif /* PSA_WANT_KEY_TYPE_DH_KEY_PAIR_GENERATE */ + +#if defined(PSA_WANT_KEY_TYPE_DH_KEY_PAIR_BASIC) +#if !defined(MBEDTLS_PSA_ACCEL_KEY_TYPE_DH_KEY_PAIR_BASIC) || \ + defined(MBEDTLS_PSA_DH_ACCEL_INCOMPLETE_GROUPS) || \ + defined(MBEDTLS_PSA_DH_ACCEL_INCOMPLETE_ALGS) +#define MBEDTLS_PSA_BUILTIN_KEY_TYPE_DH_KEY_PAIR_BASIC 1 +#endif /* !MBEDTLS_PSA_ACCEL_KEY_TYPE_DH_KEY_PAIR_BASIC */ +#endif /* PSA_WANT_KEY_TYPE_DH_KEY_PAIR_BASIC */ + +#if defined(PSA_WANT_KEY_TYPE_DH_PUBLIC_KEY) +#if !defined(MBEDTLS_PSA_ACCEL_KEY_TYPE_DH_PUBLIC_KEY) || \ + defined(MBEDTLS_PSA_DH_ACCEL_INCOMPLETE_GROUPS) || \ + defined(MBEDTLS_PSA_DH_ACCEL_INCOMPLETE_ALGS) +#define MBEDTLS_PSA_BUILTIN_KEY_TYPE_DH_PUBLIC_KEY 1 +#define MBEDTLS_BIGNUM_C +#endif /* !MBEDTLS_PSA_ACCEL_KEY_TYPE_DH_PUBLIC_KEY */ +#endif /* PSA_WANT_KEY_TYPE_DH_PUBLIC_KEY */ + +/* End of DH section */ + +#if defined(PSA_WANT_ALG_HKDF) +#if !defined(MBEDTLS_PSA_ACCEL_ALG_HKDF) +/* + * The PSA implementation has its own implementation of HKDF, separate from + * hkdf.c. No need to enable MBEDTLS_HKDF_C here. + */ +#define MBEDTLS_PSA_BUILTIN_ALG_HMAC 1 +#define MBEDTLS_PSA_BUILTIN_ALG_HKDF 1 +#endif /* !MBEDTLS_PSA_ACCEL_ALG_HKDF */ +#endif /* PSA_WANT_ALG_HKDF */ + +#if defined(PSA_WANT_ALG_HKDF_EXTRACT) +#if !defined(MBEDTLS_PSA_ACCEL_ALG_HKDF_EXTRACT) +/* + * The PSA implementation has its own implementation of HKDF, separate from + * hkdf.c. No need to enable MBEDTLS_HKDF_C here. + */ +#define MBEDTLS_PSA_BUILTIN_ALG_HMAC 1 +#define MBEDTLS_PSA_BUILTIN_ALG_HKDF_EXTRACT 1 +#endif /* !MBEDTLS_PSA_ACCEL_ALG_HKDF_EXTRACT */ +#endif /* PSA_WANT_ALG_HKDF_EXTRACT */ + +#if defined(PSA_WANT_ALG_HKDF_EXPAND) +#if !defined(MBEDTLS_PSA_ACCEL_ALG_HKDF_EXPAND) +/* + * The PSA implementation has its own implementation of HKDF, separate from + * hkdf.c. No need to enable MBEDTLS_HKDF_C here. + */ +#define MBEDTLS_PSA_BUILTIN_ALG_HMAC 1 +#define MBEDTLS_PSA_BUILTIN_ALG_HKDF_EXPAND 1 +#endif /* !MBEDTLS_PSA_ACCEL_ALG_HKDF_EXPAND */ +#endif /* PSA_WANT_ALG_HKDF_EXPAND */ + +#if defined(PSA_WANT_ALG_HMAC) +#if !defined(MBEDTLS_PSA_ACCEL_ALG_HMAC) +#define MBEDTLS_PSA_BUILTIN_ALG_HMAC 1 +#endif /* !MBEDTLS_PSA_ACCEL_ALG_HMAC */ +#endif /* PSA_WANT_ALG_HMAC */ + +#if defined(PSA_WANT_ALG_MD5) && !defined(MBEDTLS_PSA_ACCEL_ALG_MD5) +#define MBEDTLS_PSA_BUILTIN_ALG_MD5 1 +#define MBEDTLS_MD5_C +#endif + +#if defined(PSA_WANT_ALG_RIPEMD160) && !defined(MBEDTLS_PSA_ACCEL_ALG_RIPEMD160) +#define MBEDTLS_PSA_BUILTIN_ALG_RIPEMD160 1 +#define MBEDTLS_RIPEMD160_C +#endif + +#if defined(PSA_WANT_ALG_RSA_OAEP) +#if !defined(MBEDTLS_PSA_ACCEL_ALG_RSA_OAEP) +#define MBEDTLS_PSA_BUILTIN_ALG_RSA_OAEP 1 +#define MBEDTLS_RSA_C +#define MBEDTLS_BIGNUM_C +#define MBEDTLS_OID_C +#define MBEDTLS_PKCS1_V21 +#endif /* !MBEDTLS_PSA_ACCEL_ALG_RSA_OAEP */ +#endif /* PSA_WANT_ALG_RSA_OAEP */ + +#if defined(PSA_WANT_ALG_RSA_PKCS1V15_CRYPT) +#if !defined(MBEDTLS_PSA_ACCEL_ALG_RSA_PKCS1V15_CRYPT) +#define MBEDTLS_PSA_BUILTIN_ALG_RSA_PKCS1V15_CRYPT 1 +#define MBEDTLS_RSA_C +#define MBEDTLS_BIGNUM_C +#define MBEDTLS_OID_C +#define MBEDTLS_PKCS1_V15 +#endif /* !MBEDTLS_PSA_ACCEL_ALG_RSA_PKCS1V15_CRYPT */ +#endif /* PSA_WANT_ALG_RSA_PKCS1V15_CRYPT */ + +#if defined(PSA_WANT_ALG_RSA_PKCS1V15_SIGN) +#if !defined(MBEDTLS_PSA_ACCEL_ALG_RSA_PKCS1V15_SIGN) +#define MBEDTLS_PSA_BUILTIN_ALG_RSA_PKCS1V15_SIGN 1 +#define MBEDTLS_RSA_C +#define MBEDTLS_BIGNUM_C +#define MBEDTLS_OID_C +#define MBEDTLS_PKCS1_V15 +#endif /* !MBEDTLS_PSA_ACCEL_ALG_RSA_PKCS1V15_SIGN */ +#endif /* PSA_WANT_ALG_RSA_PKCS1V15_SIGN */ + +#if defined(PSA_WANT_ALG_RSA_PSS) +#if !defined(MBEDTLS_PSA_ACCEL_ALG_RSA_PSS) +#define MBEDTLS_PSA_BUILTIN_ALG_RSA_PSS 1 +#define MBEDTLS_RSA_C +#define MBEDTLS_BIGNUM_C +#define MBEDTLS_OID_C +#define MBEDTLS_PKCS1_V21 +#endif /* !MBEDTLS_PSA_ACCEL_ALG_RSA_PSS */ +#endif /* PSA_WANT_ALG_RSA_PSS */ + +#if defined(PSA_WANT_ALG_SHA_1) && !defined(MBEDTLS_PSA_ACCEL_ALG_SHA_1) +#define MBEDTLS_PSA_BUILTIN_ALG_SHA_1 1 +#define MBEDTLS_SHA1_C +#endif + +#if defined(PSA_WANT_ALG_SHA_224) && !defined(MBEDTLS_PSA_ACCEL_ALG_SHA_224) +#define MBEDTLS_PSA_BUILTIN_ALG_SHA_224 1 +#define MBEDTLS_SHA224_C +#endif + +#if defined(PSA_WANT_ALG_SHA_256) && !defined(MBEDTLS_PSA_ACCEL_ALG_SHA_256) +#define MBEDTLS_PSA_BUILTIN_ALG_SHA_256 1 +#define MBEDTLS_SHA256_C +#endif + +#if defined(PSA_WANT_ALG_SHA_384) && !defined(MBEDTLS_PSA_ACCEL_ALG_SHA_384) +#define MBEDTLS_PSA_BUILTIN_ALG_SHA_384 1 +#define MBEDTLS_SHA384_C +#endif + +#if defined(PSA_WANT_ALG_SHA_512) && !defined(MBEDTLS_PSA_ACCEL_ALG_SHA_512) +#define MBEDTLS_PSA_BUILTIN_ALG_SHA_512 1 +#define MBEDTLS_SHA512_C +#endif + +#if defined(PSA_WANT_ALG_SHA3_224) && !defined(MBEDTLS_PSA_ACCEL_ALG_SHA3_224) +#define MBEDTLS_PSA_BUILTIN_ALG_SHA3_224 1 +#define MBEDTLS_SHA3_C +#endif + +#if defined(PSA_WANT_ALG_SHA3_256) && !defined(MBEDTLS_PSA_ACCEL_ALG_SHA3_256) +#define MBEDTLS_PSA_BUILTIN_ALG_SHA3_256 1 +#define MBEDTLS_SHA3_C +#endif + +#if defined(PSA_WANT_ALG_SHA3_384) && !defined(MBEDTLS_PSA_ACCEL_ALG_SHA3_384) +#define MBEDTLS_PSA_BUILTIN_ALG_SHA3_384 1 +#define MBEDTLS_SHA3_C +#endif + +#if defined(PSA_WANT_ALG_SHA3_512) && !defined(MBEDTLS_PSA_ACCEL_ALG_SHA3_512) +#define MBEDTLS_PSA_BUILTIN_ALG_SHA3_512 1 +#define MBEDTLS_SHA3_C +#endif + +#if defined(PSA_WANT_ALG_PBKDF2_HMAC) +#if !defined(MBEDTLS_PSA_ACCEL_ALG_PBKDF2_HMAC) +#define MBEDTLS_PSA_BUILTIN_ALG_PBKDF2_HMAC 1 +#define PSA_HAVE_SOFT_PBKDF2_HMAC 1 +#if !defined(MBEDTLS_PSA_ACCEL_ALG_HMAC) +#define MBEDTLS_PSA_BUILTIN_ALG_HMAC 1 +#endif /* !MBEDTLS_PSA_ACCEL_ALG_HMAC */ +#endif /* !MBEDTLS_PSA_BUILTIN_ALG_PBKDF2_HMAC */ +#endif /* PSA_WANT_ALG_PBKDF2_HMAC */ + +#if defined(PSA_WANT_ALG_TLS12_PRF) +#if !defined(MBEDTLS_PSA_ACCEL_ALG_TLS12_PRF) +#define MBEDTLS_PSA_BUILTIN_ALG_TLS12_PRF 1 +#endif /* !MBEDTLS_PSA_ACCEL_ALG_TLS12_PRF */ +#endif /* PSA_WANT_ALG_TLS12_PRF */ + +#if defined(PSA_WANT_ALG_TLS12_PSK_TO_MS) +#if !defined(MBEDTLS_PSA_ACCEL_ALG_TLS12_PSK_TO_MS) +#define MBEDTLS_PSA_BUILTIN_ALG_TLS12_PSK_TO_MS 1 +#endif /* !MBEDTLS_PSA_ACCEL_ALG_TLS12_PSK_TO_MS */ +#endif /* PSA_WANT_ALG_TLS12_PSK_TO_MS */ + +#if defined(PSA_WANT_ALG_TLS12_ECJPAKE_TO_PMS) +#if !defined(MBEDTLS_PSA_ACCEL_ALG_TLS12_ECJPAKE_TO_PMS) +#define MBEDTLS_PSA_BUILTIN_ALG_TLS12_ECJPAKE_TO_PMS 1 +#endif /* !MBEDTLS_PSA_ACCEL_ALG_TLS12_ECJPAKE_TO_PMS */ +#endif /* PSA_WANT_ALG_TLS12_ECJPAKE_TO_PMS */ + +#if defined(PSA_WANT_KEY_TYPE_RSA_KEY_PAIR_IMPORT) +#if !defined(MBEDTLS_PSA_ACCEL_KEY_TYPE_RSA_KEY_PAIR_IMPORT) +#define MBEDTLS_PSA_BUILTIN_KEY_TYPE_RSA_KEY_PAIR_IMPORT 1 +#endif /* !MBEDTLS_PSA_ACCEL_KEY_TYPE_RSA_KEY_PAIR_IMPORT */ +#endif /* PSA_WANT_KEY_TYPE_RSA_KEY_PAIR_IMPORT */ + +#if defined(PSA_WANT_KEY_TYPE_RSA_KEY_PAIR_EXPORT) +#if !defined(MBEDTLS_PSA_ACCEL_KEY_TYPE_RSA_KEY_PAIR_EXPORT) +#define MBEDTLS_PSA_BUILTIN_KEY_TYPE_RSA_KEY_PAIR_EXPORT 1 +#endif /* !MBEDTLS_PSA_ACCEL_KEY_TYPE_RSA_KEY_PAIR_EXPORT */ +#endif /* PSA_WANT_KEY_TYPE_RSA_KEY_PAIR_EXPORT */ + +#if defined(PSA_WANT_KEY_TYPE_RSA_KEY_PAIR_GENERATE) +#if !defined(MBEDTLS_PSA_ACCEL_KEY_TYPE_RSA_KEY_PAIR_GENERATE) +#define MBEDTLS_PSA_BUILTIN_KEY_TYPE_RSA_KEY_PAIR_GENERATE 1 +#define MBEDTLS_GENPRIME +#endif /* !MBEDTLS_PSA_ACCEL_KEY_TYPE_RSA_KEY_PAIR_GENERATE */ +#endif /* PSA_WANT_KEY_TYPE_RSA_KEY_PAIR_GENERATE */ + +#if defined(PSA_WANT_KEY_TYPE_RSA_KEY_PAIR_BASIC) +#if !defined(MBEDTLS_PSA_ACCEL_KEY_TYPE_RSA_KEY_PAIR_BASIC) +#define MBEDTLS_PSA_BUILTIN_KEY_TYPE_RSA_KEY_PAIR_BASIC 1 +#endif /* !MBEDTLS_PSA_ACCEL_KEY_TYPE_RSA_KEY_PAIR_BASIC */ +#endif /* PSA_WANT_KEY_TYPE_RSA_KEY_PAIR_BASIC */ + +#if defined(PSA_WANT_KEY_TYPE_RSA_PUBLIC_KEY) +#if !defined(MBEDTLS_PSA_ACCEL_KEY_TYPE_RSA_PUBLIC_KEY) +#define MBEDTLS_PSA_BUILTIN_KEY_TYPE_RSA_PUBLIC_KEY 1 +#define MBEDTLS_RSA_C +#define MBEDTLS_BIGNUM_C +#define MBEDTLS_OID_C +#define MBEDTLS_ASN1_PARSE_C +#define MBEDTLS_ASN1_WRITE_C +#endif /* !MBEDTLS_PSA_ACCEL_KEY_TYPE_RSA_PUBLIC_KEY */ +#endif /* PSA_WANT_KEY_TYPE_RSA_PUBLIC_KEY */ + +/* If any of the block modes are requested that don't have an + * associated HW assist, define PSA_HAVE_SOFT_BLOCK_MODE for checking + * in the block cipher key types. */ +#if (defined(PSA_WANT_ALG_CTR) && !defined(MBEDTLS_PSA_ACCEL_ALG_CTR)) || \ + (defined(PSA_WANT_ALG_CFB) && !defined(MBEDTLS_PSA_ACCEL_ALG_CFB)) || \ + (defined(PSA_WANT_ALG_OFB) && !defined(MBEDTLS_PSA_ACCEL_ALG_OFB)) || \ + (defined(PSA_WANT_ALG_ECB_NO_PADDING) && !defined(MBEDTLS_PSA_ACCEL_ALG_ECB_NO_PADDING)) || \ + (defined(PSA_WANT_ALG_CBC_NO_PADDING) && !defined(MBEDTLS_PSA_ACCEL_ALG_CBC_NO_PADDING)) || \ + (defined(PSA_WANT_ALG_CBC_PKCS7) && !defined(MBEDTLS_PSA_ACCEL_ALG_CBC_PKCS7)) || \ + (defined(PSA_WANT_ALG_CMAC) && !defined(MBEDTLS_PSA_ACCEL_ALG_CMAC)) +#define PSA_HAVE_SOFT_BLOCK_MODE 1 +#endif + +#if defined(PSA_WANT_ALG_PBKDF2_AES_CMAC_PRF_128) +#if !defined(MBEDTLS_PSA_ACCEL_ALG_PBKDF2_AES_CMAC_PRF_128) +#define MBEDTLS_PSA_BUILTIN_ALG_PBKDF2_AES_CMAC_PRF_128 1 +#define PSA_HAVE_SOFT_PBKDF2_CMAC 1 +#endif /* !MBEDTLS_PSA_ACCEL_ALG_PBKDF2_AES_CMAC_PRF_128 */ +#endif /* PSA_WANT_ALG_PBKDF2_AES_CMAC_PRF_128 */ + +#if defined(PSA_WANT_KEY_TYPE_AES) +#if !defined(MBEDTLS_PSA_ACCEL_KEY_TYPE_AES) +#define PSA_HAVE_SOFT_KEY_TYPE_AES 1 +#endif /* !MBEDTLS_PSA_ACCEL_KEY_TYPE_AES */ +#if defined(PSA_HAVE_SOFT_KEY_TYPE_AES) || \ + defined(PSA_HAVE_SOFT_BLOCK_MODE) +#define MBEDTLS_PSA_BUILTIN_KEY_TYPE_AES 1 +#define MBEDTLS_AES_C +#endif /* PSA_HAVE_SOFT_KEY_TYPE_AES || PSA_HAVE_SOFT_BLOCK_MODE */ +#endif /* PSA_WANT_KEY_TYPE_AES */ + +#if defined(PSA_WANT_KEY_TYPE_ARIA) +#if !defined(MBEDTLS_PSA_ACCEL_KEY_TYPE_ARIA) +#define PSA_HAVE_SOFT_KEY_TYPE_ARIA 1 +#endif /* !MBEDTLS_PSA_ACCEL_KEY_TYPE_ARIA */ +#if defined(PSA_HAVE_SOFT_KEY_TYPE_ARIA) || \ + defined(PSA_HAVE_SOFT_BLOCK_MODE) +#define MBEDTLS_PSA_BUILTIN_KEY_TYPE_ARIA 1 +#define MBEDTLS_ARIA_C +#endif /* PSA_HAVE_SOFT_KEY_TYPE_ARIA || PSA_HAVE_SOFT_BLOCK_MODE */ +#endif /* PSA_WANT_KEY_TYPE_ARIA */ + +#if defined(PSA_WANT_KEY_TYPE_CAMELLIA) +#if !defined(MBEDTLS_PSA_ACCEL_KEY_TYPE_CAMELLIA) +#define PSA_HAVE_SOFT_KEY_TYPE_CAMELLIA 1 +#endif /* !MBEDTLS_PSA_ACCEL_KEY_TYPE_CAMELLIA */ +#if defined(PSA_HAVE_SOFT_KEY_TYPE_CAMELLIA) || \ + defined(PSA_HAVE_SOFT_BLOCK_MODE) +#define MBEDTLS_PSA_BUILTIN_KEY_TYPE_CAMELLIA 1 +#define MBEDTLS_CAMELLIA_C +#endif /* PSA_HAVE_SOFT_KEY_TYPE_CAMELLIA || PSA_HAVE_SOFT_BLOCK_MODE */ +#endif /* PSA_WANT_KEY_TYPE_CAMELLIA */ + +#if defined(PSA_WANT_KEY_TYPE_DES) +#if !defined(MBEDTLS_PSA_ACCEL_KEY_TYPE_DES) +#define PSA_HAVE_SOFT_KEY_TYPE_DES 1 +#endif /* !MBEDTLS_PSA_ACCEL_KEY_TYPE_DES */ +#if defined(PSA_HAVE_SOFT_KEY_TYPE_DES) || \ + defined(PSA_HAVE_SOFT_BLOCK_MODE) +#define MBEDTLS_PSA_BUILTIN_KEY_TYPE_DES 1 +#define MBEDTLS_DES_C +#endif /*PSA_HAVE_SOFT_KEY_TYPE_DES || PSA_HAVE_SOFT_BLOCK_MODE */ +#endif /* PSA_WANT_KEY_TYPE_DES */ + +#if defined(PSA_WANT_ALG_STREAM_CIPHER) +#if !defined(MBEDTLS_PSA_ACCEL_ALG_STREAM_CIPHER) +#define MBEDTLS_PSA_BUILTIN_ALG_STREAM_CIPHER 1 +#endif /* MBEDTLS_PSA_ACCEL_ALG_STREAM_CIPHER */ +#endif /* PSA_WANT_ALG_STREAM_CIPHER */ + +#if defined(PSA_WANT_KEY_TYPE_CHACHA20) +#if !defined(MBEDTLS_PSA_ACCEL_KEY_TYPE_CHACHA20) || \ + defined(MBEDTLS_PSA_BUILTIN_ALG_STREAM_CIPHER) +#define MBEDTLS_PSA_BUILTIN_KEY_TYPE_CHACHA20 1 +#define MBEDTLS_CHACHA20_C +#endif /*!MBEDTLS_PSA_ACCEL_KEY_TYPE_CHACHA20 */ +#endif /* PSA_WANT_KEY_TYPE_CHACHA20 */ + +/* If any of the software block ciphers are selected, define + * PSA_HAVE_SOFT_BLOCK_CIPHER, which can be used in any of these + * situations. */ +#if defined(PSA_HAVE_SOFT_KEY_TYPE_AES) || \ + defined(PSA_HAVE_SOFT_KEY_TYPE_ARIA) || \ + defined(PSA_HAVE_SOFT_KEY_TYPE_DES) || \ + defined(PSA_HAVE_SOFT_KEY_TYPE_CAMELLIA) +#define PSA_HAVE_SOFT_BLOCK_CIPHER 1 +#endif + +#if defined(PSA_WANT_ALG_CBC_MAC) +#if !defined(MBEDTLS_PSA_ACCEL_ALG_CBC_MAC) +#error "CBC-MAC is not yet supported via the PSA API in Mbed TLS." +#define MBEDTLS_PSA_BUILTIN_ALG_CBC_MAC 1 +#endif /* !MBEDTLS_PSA_ACCEL_ALG_CBC_MAC */ +#endif /* PSA_WANT_ALG_CBC_MAC */ + +#if defined(PSA_WANT_ALG_CMAC) +#if !defined(MBEDTLS_PSA_ACCEL_ALG_CMAC) || \ + defined(PSA_HAVE_SOFT_BLOCK_CIPHER) +#define MBEDTLS_PSA_BUILTIN_ALG_CMAC 1 +#define MBEDTLS_CMAC_C +#endif /* !MBEDTLS_PSA_ACCEL_ALG_CMAC */ +#endif /* PSA_WANT_ALG_CMAC */ + +#if defined(PSA_HAVE_SOFT_PBKDF2_HMAC) || \ + defined(PSA_HAVE_SOFT_PBKDF2_CMAC) +#define PSA_HAVE_SOFT_PBKDF2 1 +#endif /* PSA_HAVE_SOFT_PBKDF2_HMAC || PSA_HAVE_SOFT_PBKDF2_CMAC */ + +#if defined(PSA_WANT_ALG_CTR) +#if !defined(MBEDTLS_PSA_ACCEL_ALG_CTR) || \ + defined(PSA_HAVE_SOFT_BLOCK_CIPHER) +#define MBEDTLS_PSA_BUILTIN_ALG_CTR 1 +#define MBEDTLS_CIPHER_MODE_CTR +#endif +#endif /* PSA_WANT_ALG_CTR */ + +#if defined(PSA_WANT_ALG_CFB) +#if !defined(MBEDTLS_PSA_ACCEL_ALG_CFB) || \ + defined(PSA_HAVE_SOFT_BLOCK_CIPHER) +#define MBEDTLS_PSA_BUILTIN_ALG_CFB 1 +#define MBEDTLS_CIPHER_MODE_CFB +#endif +#endif /* PSA_WANT_ALG_CFB */ + +#if defined(PSA_WANT_ALG_OFB) +#if !defined(MBEDTLS_PSA_ACCEL_ALG_OFB) || \ + defined(PSA_HAVE_SOFT_BLOCK_CIPHER) +#define MBEDTLS_PSA_BUILTIN_ALG_OFB 1 +#define MBEDTLS_CIPHER_MODE_OFB +#endif +#endif /* PSA_WANT_ALG_OFB */ + +#if defined(PSA_WANT_ALG_ECB_NO_PADDING) && \ + !defined(MBEDTLS_PSA_ACCEL_ALG_ECB_NO_PADDING) +#define MBEDTLS_PSA_BUILTIN_ALG_ECB_NO_PADDING 1 +#endif + +#if defined(PSA_WANT_ALG_CBC_NO_PADDING) +#if !defined(MBEDTLS_PSA_ACCEL_ALG_CBC_NO_PADDING) || \ + defined(PSA_HAVE_SOFT_BLOCK_CIPHER) +#define MBEDTLS_CIPHER_MODE_CBC +#define MBEDTLS_PSA_BUILTIN_ALG_CBC_NO_PADDING 1 +#endif +#endif /* PSA_WANT_ALG_CBC_NO_PADDING */ + +#if defined(PSA_WANT_ALG_CBC_PKCS7) +#if !defined(MBEDTLS_PSA_ACCEL_ALG_CBC_PKCS7) || \ + defined(PSA_HAVE_SOFT_BLOCK_CIPHER) +#define MBEDTLS_CIPHER_MODE_CBC +#define MBEDTLS_PSA_BUILTIN_ALG_CBC_PKCS7 1 +#define MBEDTLS_CIPHER_PADDING_PKCS7 +#endif +#endif /* PSA_WANT_ALG_CBC_PKCS7 */ + +#if defined(PSA_WANT_ALG_CCM) +#if !defined(MBEDTLS_PSA_ACCEL_ALG_CCM) || \ + defined(PSA_HAVE_SOFT_KEY_TYPE_AES) || \ + defined(PSA_HAVE_SOFT_KEY_TYPE_ARIA) || \ + defined(PSA_HAVE_SOFT_KEY_TYPE_CAMELLIA) +#define MBEDTLS_PSA_BUILTIN_ALG_CCM 1 +#define MBEDTLS_CCM_C +#endif +#endif /* PSA_WANT_ALG_CCM */ + +#if defined(PSA_WANT_ALG_CCM_STAR_NO_TAG) +#if !defined(MBEDTLS_PSA_ACCEL_ALG_CCM_STAR_NO_TAG) || \ + defined(PSA_HAVE_SOFT_KEY_TYPE_AES) || \ + defined(PSA_HAVE_SOFT_KEY_TYPE_ARIA) || \ + defined(PSA_HAVE_SOFT_KEY_TYPE_CAMELLIA) +#define MBEDTLS_PSA_BUILTIN_ALG_CCM_STAR_NO_TAG 1 +#define MBEDTLS_CCM_C +#endif +#endif /* PSA_WANT_ALG_CCM_STAR_NO_TAG */ + +#if defined(PSA_WANT_ALG_GCM) +#if !defined(MBEDTLS_PSA_ACCEL_ALG_GCM) || \ + defined(PSA_HAVE_SOFT_KEY_TYPE_AES) || \ + defined(PSA_HAVE_SOFT_KEY_TYPE_ARIA) || \ + defined(PSA_HAVE_SOFT_KEY_TYPE_CAMELLIA) +#define MBEDTLS_PSA_BUILTIN_ALG_GCM 1 +#define MBEDTLS_GCM_C +#endif +#endif /* PSA_WANT_ALG_GCM */ + +#if defined(PSA_WANT_ALG_CHACHA20_POLY1305) +#if !defined(MBEDTLS_PSA_ACCEL_ALG_CHACHA20_POLY1305) +#if defined(PSA_WANT_KEY_TYPE_CHACHA20) +#define MBEDTLS_CHACHAPOLY_C +#define MBEDTLS_CHACHA20_C +#define MBEDTLS_POLY1305_C +#define MBEDTLS_PSA_BUILTIN_ALG_CHACHA20_POLY1305 1 +#endif /* PSA_WANT_KEY_TYPE_CHACHA20 */ +#endif /* !MBEDTLS_PSA_ACCEL_ALG_CHACHA20_POLY1305 */ +#endif /* PSA_WANT_ALG_CHACHA20_POLY1305 */ + +#endif /* MBEDTLS_CONFIG_ADJUST_LEGACY_FROM_PSA_H */ diff --git a/vendor/mbedtls/include/mbedtls/config_adjust_psa_from_legacy.h b/vendor/mbedtls/include/mbedtls/config_adjust_psa_from_legacy.h new file mode 100644 index 0000000000..3456615943 --- /dev/null +++ b/vendor/mbedtls/include/mbedtls/config_adjust_psa_from_legacy.h @@ -0,0 +1,349 @@ +/** + * \file mbedtls/config_adjust_psa_from_legacy.h + * \brief Adjust PSA configuration: construct PSA configuration from legacy + * + * When MBEDTLS_PSA_CRYPTO_CONFIG is disabled, we automatically enable + * cryptographic mechanisms through the PSA interface when the corresponding + * legacy mechanism is enabled. In many cases, this just enables the PSA + * wrapper code around the legacy implementation, but we also do this for + * some mechanisms where PSA has its own independent implementation so + * that high-level modules that can use either cryptographic API have the + * same feature set in both cases. + */ +/* + * Copyright The Mbed TLS Contributors + * SPDX-License-Identifier: Apache-2.0 OR GPL-2.0-or-later + */ + +#ifndef MBEDTLS_CONFIG_ADJUST_PSA_FROM_LEGACY_H +#define MBEDTLS_CONFIG_ADJUST_PSA_FROM_LEGACY_H + +/* + * Ensure PSA_WANT_* defines are setup properly if MBEDTLS_PSA_CRYPTO_CONFIG + * is not defined + */ + +#if defined(MBEDTLS_CCM_C) +#define MBEDTLS_PSA_BUILTIN_ALG_CCM 1 +#define PSA_WANT_ALG_CCM 1 +#if defined(MBEDTLS_CIPHER_C) +#define MBEDTLS_PSA_BUILTIN_ALG_CCM_STAR_NO_TAG 1 +#define PSA_WANT_ALG_CCM_STAR_NO_TAG 1 +#endif /* MBEDTLS_CIPHER_C */ +#endif /* MBEDTLS_CCM_C */ + +#if defined(MBEDTLS_CMAC_C) +#define MBEDTLS_PSA_BUILTIN_ALG_CMAC 1 +#define PSA_WANT_ALG_CMAC 1 +#endif /* MBEDTLS_CMAC_C */ + +#if defined(MBEDTLS_ECDH_C) +#define MBEDTLS_PSA_BUILTIN_ALG_ECDH 1 +#define PSA_WANT_ALG_ECDH 1 +#endif /* MBEDTLS_ECDH_C */ + +#if defined(MBEDTLS_ECDSA_C) +#define MBEDTLS_PSA_BUILTIN_ALG_ECDSA 1 +#define PSA_WANT_ALG_ECDSA 1 +#define PSA_WANT_ALG_ECDSA_ANY 1 + +// Only add in DETERMINISTIC support if ECDSA is also enabled +#if defined(MBEDTLS_ECDSA_DETERMINISTIC) +#define MBEDTLS_PSA_BUILTIN_ALG_DETERMINISTIC_ECDSA 1 +#define PSA_WANT_ALG_DETERMINISTIC_ECDSA 1 +#endif /* MBEDTLS_ECDSA_DETERMINISTIC */ + +#endif /* MBEDTLS_ECDSA_C */ + +#if defined(MBEDTLS_ECP_C) +#define PSA_WANT_KEY_TYPE_ECC_KEY_PAIR_BASIC 1 +#define PSA_WANT_KEY_TYPE_ECC_KEY_PAIR_IMPORT 1 +#define PSA_WANT_KEY_TYPE_ECC_KEY_PAIR_EXPORT 1 +#define PSA_WANT_KEY_TYPE_ECC_KEY_PAIR_GENERATE 1 +/* Normally we wouldn't enable this because it's not implemented in ecp.c, + * but since it used to be available any time ECP_C was enabled, let's enable + * it anyway for the sake of backwards compatibility */ +#define PSA_WANT_KEY_TYPE_ECC_KEY_PAIR_DERIVE 1 +#define MBEDTLS_PSA_BUILTIN_KEY_TYPE_ECC_KEY_PAIR_BASIC 1 +#define MBEDTLS_PSA_BUILTIN_KEY_TYPE_ECC_KEY_PAIR_IMPORT 1 +#define MBEDTLS_PSA_BUILTIN_KEY_TYPE_ECC_KEY_PAIR_EXPORT 1 +#define MBEDTLS_PSA_BUILTIN_KEY_TYPE_ECC_KEY_PAIR_GENERATE 1 +/* See comment for PSA_WANT_KEY_TYPE_ECC_KEY_PAIR_DERIVE above. */ +#define MBEDTLS_PSA_BUILTIN_KEY_TYPE_ECC_KEY_PAIR_DERIVE 1 +#define MBEDTLS_PSA_BUILTIN_KEY_TYPE_ECC_PUBLIC_KEY 1 +#define PSA_WANT_KEY_TYPE_ECC_PUBLIC_KEY 1 +#endif /* MBEDTLS_ECP_C */ + +#if defined(MBEDTLS_DHM_C) +#define PSA_WANT_KEY_TYPE_DH_KEY_PAIR_BASIC 1 +#define PSA_WANT_KEY_TYPE_DH_KEY_PAIR_IMPORT 1 +#define PSA_WANT_KEY_TYPE_DH_KEY_PAIR_EXPORT 1 +#define PSA_WANT_KEY_TYPE_DH_KEY_PAIR_GENERATE 1 +#define PSA_WANT_KEY_TYPE_DH_PUBLIC_KEY 1 +#define PSA_WANT_ALG_FFDH 1 +#define PSA_WANT_DH_RFC7919_2048 1 +#define PSA_WANT_DH_RFC7919_3072 1 +#define PSA_WANT_DH_RFC7919_4096 1 +#define PSA_WANT_DH_RFC7919_6144 1 +#define PSA_WANT_DH_RFC7919_8192 1 +#define MBEDTLS_PSA_BUILTIN_ALG_FFDH 1 +#define MBEDTLS_PSA_BUILTIN_KEY_TYPE_DH_KEY_PAIR_BASIC 1 +#define MBEDTLS_PSA_BUILTIN_KEY_TYPE_DH_KEY_PAIR_IMPORT 1 +#define MBEDTLS_PSA_BUILTIN_KEY_TYPE_DH_KEY_PAIR_EXPORT 1 +#define MBEDTLS_PSA_BUILTIN_KEY_TYPE_DH_KEY_PAIR_GENERATE 1 +#define MBEDTLS_PSA_BUILTIN_KEY_TYPE_DH_PUBLIC_KEY 1 +#define MBEDTLS_PSA_BUILTIN_DH_RFC7919_2048 1 +#define MBEDTLS_PSA_BUILTIN_DH_RFC7919_3072 1 +#define MBEDTLS_PSA_BUILTIN_DH_RFC7919_4096 1 +#define MBEDTLS_PSA_BUILTIN_DH_RFC7919_6144 1 +#define MBEDTLS_PSA_BUILTIN_DH_RFC7919_8192 1 +#endif /* MBEDTLS_DHM_C */ + +#if defined(MBEDTLS_GCM_C) +#define MBEDTLS_PSA_BUILTIN_ALG_GCM 1 +#define PSA_WANT_ALG_GCM 1 +#endif /* MBEDTLS_GCM_C */ + +/* Enable PSA HKDF algorithm if mbedtls HKDF is supported. + * PSA HKDF EXTRACT and PSA HKDF EXPAND have minimal cost when + * PSA HKDF is enabled, so enable both algorithms together + * with PSA HKDF. */ +#if defined(MBEDTLS_HKDF_C) +#define MBEDTLS_PSA_BUILTIN_ALG_HMAC 1 +#define PSA_WANT_ALG_HMAC 1 +#define MBEDTLS_PSA_BUILTIN_ALG_HKDF 1 +#define PSA_WANT_ALG_HKDF 1 +#define MBEDTLS_PSA_BUILTIN_ALG_HKDF_EXTRACT 1 +#define PSA_WANT_ALG_HKDF_EXTRACT 1 +#define MBEDTLS_PSA_BUILTIN_ALG_HKDF_EXPAND 1 +#define PSA_WANT_ALG_HKDF_EXPAND 1 +#endif /* MBEDTLS_HKDF_C */ + +#define MBEDTLS_PSA_BUILTIN_ALG_HMAC 1 +#define PSA_WANT_ALG_HMAC 1 +#define PSA_WANT_KEY_TYPE_HMAC 1 + +#if defined(MBEDTLS_MD_C) +#define MBEDTLS_PSA_BUILTIN_ALG_TLS12_PRF 1 +#define PSA_WANT_ALG_TLS12_PRF 1 +#define MBEDTLS_PSA_BUILTIN_ALG_TLS12_PSK_TO_MS 1 +#define PSA_WANT_ALG_TLS12_PSK_TO_MS 1 +#endif /* MBEDTLS_MD_C */ + +#if defined(MBEDTLS_MD5_C) +#define MBEDTLS_PSA_BUILTIN_ALG_MD5 1 +#define PSA_WANT_ALG_MD5 1 +#endif + +#if defined(MBEDTLS_ECJPAKE_C) +#define MBEDTLS_PSA_BUILTIN_PAKE 1 +#define MBEDTLS_PSA_BUILTIN_ALG_JPAKE 1 +#define PSA_WANT_ALG_JPAKE 1 +#endif + +#if defined(MBEDTLS_RIPEMD160_C) +#define MBEDTLS_PSA_BUILTIN_ALG_RIPEMD160 1 +#define PSA_WANT_ALG_RIPEMD160 1 +#endif + +#if defined(MBEDTLS_RSA_C) +#if defined(MBEDTLS_PKCS1_V15) +#define MBEDTLS_PSA_BUILTIN_ALG_RSA_PKCS1V15_CRYPT 1 +#define PSA_WANT_ALG_RSA_PKCS1V15_CRYPT 1 +#define MBEDTLS_PSA_BUILTIN_ALG_RSA_PKCS1V15_SIGN 1 +#define PSA_WANT_ALG_RSA_PKCS1V15_SIGN 1 +#define PSA_WANT_ALG_RSA_PKCS1V15_SIGN_RAW 1 +#endif /* MBEDTLS_PKCS1_V15 */ +#if defined(MBEDTLS_PKCS1_V21) +#define MBEDTLS_PSA_BUILTIN_ALG_RSA_OAEP 1 +#define PSA_WANT_ALG_RSA_OAEP 1 +#define MBEDTLS_PSA_BUILTIN_ALG_RSA_PSS 1 +#define PSA_WANT_ALG_RSA_PSS 1 +#endif /* MBEDTLS_PKCS1_V21 */ +#if defined(MBEDTLS_GENPRIME) +#define MBEDTLS_PSA_BUILTIN_KEY_TYPE_RSA_KEY_PAIR_GENERATE 1 +#define PSA_WANT_KEY_TYPE_RSA_KEY_PAIR_GENERATE 1 +#endif /* MBEDTLS_GENPRIME */ +#define MBEDTLS_PSA_BUILTIN_KEY_TYPE_RSA_KEY_PAIR_BASIC 1 +#define MBEDTLS_PSA_BUILTIN_KEY_TYPE_RSA_KEY_PAIR_IMPORT 1 +#define MBEDTLS_PSA_BUILTIN_KEY_TYPE_RSA_KEY_PAIR_EXPORT 1 +#define PSA_WANT_KEY_TYPE_RSA_KEY_PAIR_BASIC 1 +#define PSA_WANT_KEY_TYPE_RSA_KEY_PAIR_IMPORT 1 +#define PSA_WANT_KEY_TYPE_RSA_KEY_PAIR_EXPORT 1 +#define MBEDTLS_PSA_BUILTIN_KEY_TYPE_RSA_PUBLIC_KEY 1 +#define PSA_WANT_KEY_TYPE_RSA_PUBLIC_KEY 1 +#endif /* MBEDTLS_RSA_C */ + +#if defined(MBEDTLS_SHA1_C) +#define MBEDTLS_PSA_BUILTIN_ALG_SHA_1 1 +#define PSA_WANT_ALG_SHA_1 1 +#endif + +#if defined(MBEDTLS_SHA224_C) +#define MBEDTLS_PSA_BUILTIN_ALG_SHA_224 1 +#define PSA_WANT_ALG_SHA_224 1 +#endif + +#if defined(MBEDTLS_SHA256_C) +#define MBEDTLS_PSA_BUILTIN_ALG_SHA_256 1 +#define PSA_WANT_ALG_SHA_256 1 +#endif + +#if defined(MBEDTLS_SHA384_C) +#define MBEDTLS_PSA_BUILTIN_ALG_SHA_384 1 +#define PSA_WANT_ALG_SHA_384 1 +#endif + +#if defined(MBEDTLS_SHA512_C) +#define MBEDTLS_PSA_BUILTIN_ALG_SHA_512 1 +#define PSA_WANT_ALG_SHA_512 1 +#endif + +#if defined(MBEDTLS_SHA3_C) +#define MBEDTLS_PSA_BUILTIN_ALG_SHA3_224 1 +#define MBEDTLS_PSA_BUILTIN_ALG_SHA3_256 1 +#define MBEDTLS_PSA_BUILTIN_ALG_SHA3_384 1 +#define MBEDTLS_PSA_BUILTIN_ALG_SHA3_512 1 +#define PSA_WANT_ALG_SHA3_224 1 +#define PSA_WANT_ALG_SHA3_256 1 +#define PSA_WANT_ALG_SHA3_384 1 +#define PSA_WANT_ALG_SHA3_512 1 +#endif + +#if defined(MBEDTLS_AES_C) +#define PSA_WANT_KEY_TYPE_AES 1 +#define MBEDTLS_PSA_BUILTIN_KEY_TYPE_AES 1 +#endif + +#if defined(MBEDTLS_ARIA_C) +#define PSA_WANT_KEY_TYPE_ARIA 1 +#define MBEDTLS_PSA_BUILTIN_KEY_TYPE_ARIA 1 +#endif + +#if defined(MBEDTLS_CAMELLIA_C) +#define PSA_WANT_KEY_TYPE_CAMELLIA 1 +#define MBEDTLS_PSA_BUILTIN_KEY_TYPE_CAMELLIA 1 +#endif + +#if defined(MBEDTLS_DES_C) +#define PSA_WANT_KEY_TYPE_DES 1 +#define MBEDTLS_PSA_BUILTIN_KEY_TYPE_DES 1 +#endif + +#if defined(MBEDTLS_PSA_BUILTIN_ALG_SHA_256) +#define MBEDTLS_PSA_BUILTIN_ALG_TLS12_ECJPAKE_TO_PMS 1 +#define PSA_WANT_ALG_TLS12_ECJPAKE_TO_PMS 1 +#endif + +#if defined(MBEDTLS_CHACHA20_C) +#define PSA_WANT_KEY_TYPE_CHACHA20 1 +#define MBEDTLS_PSA_BUILTIN_KEY_TYPE_CHACHA20 1 +/* ALG_STREAM_CIPHER requires CIPHER_C in order to be supported in PSA */ +#if defined(MBEDTLS_CIPHER_C) +#define PSA_WANT_ALG_STREAM_CIPHER 1 +#define MBEDTLS_PSA_BUILTIN_ALG_STREAM_CIPHER 1 +#endif +#if defined(MBEDTLS_CHACHAPOLY_C) +#define PSA_WANT_ALG_CHACHA20_POLY1305 1 +#define MBEDTLS_PSA_BUILTIN_ALG_CHACHA20_POLY1305 1 +#endif +#endif + +#if defined(MBEDTLS_CIPHER_MODE_CBC) +#define MBEDTLS_PSA_BUILTIN_ALG_CBC_NO_PADDING 1 +#define PSA_WANT_ALG_CBC_NO_PADDING 1 +#if defined(MBEDTLS_CIPHER_PADDING_PKCS7) +#define MBEDTLS_PSA_BUILTIN_ALG_CBC_PKCS7 1 +#define PSA_WANT_ALG_CBC_PKCS7 1 +#endif +#endif + +#if (defined(MBEDTLS_AES_C) || defined(MBEDTLS_DES_C) || \ + defined(MBEDTLS_ARIA_C) || defined(MBEDTLS_CAMELLIA_C)) && \ + defined(MBEDTLS_CIPHER_C) +#define MBEDTLS_PSA_BUILTIN_ALG_ECB_NO_PADDING 1 +#define PSA_WANT_ALG_ECB_NO_PADDING 1 +#endif + +#if defined(MBEDTLS_CIPHER_MODE_CFB) +#define MBEDTLS_PSA_BUILTIN_ALG_CFB 1 +#define PSA_WANT_ALG_CFB 1 +#endif + +#if defined(MBEDTLS_CIPHER_MODE_CTR) +#define MBEDTLS_PSA_BUILTIN_ALG_CTR 1 +#define PSA_WANT_ALG_CTR 1 +#endif + +#if defined(MBEDTLS_CIPHER_MODE_OFB) +#define MBEDTLS_PSA_BUILTIN_ALG_OFB 1 +#define PSA_WANT_ALG_OFB 1 +#endif + +#if defined(MBEDTLS_ECP_DP_BP256R1_ENABLED) +#define MBEDTLS_PSA_BUILTIN_ECC_BRAINPOOL_P_R1_256 1 +#define PSA_WANT_ECC_BRAINPOOL_P_R1_256 1 +#endif + +#if defined(MBEDTLS_ECP_DP_BP384R1_ENABLED) +#define MBEDTLS_PSA_BUILTIN_ECC_BRAINPOOL_P_R1_384 1 +#define PSA_WANT_ECC_BRAINPOOL_P_R1_384 1 +#endif + +#if defined(MBEDTLS_ECP_DP_BP512R1_ENABLED) +#define MBEDTLS_PSA_BUILTIN_ECC_BRAINPOOL_P_R1_512 1 +#define PSA_WANT_ECC_BRAINPOOL_P_R1_512 1 +#endif + +#if defined(MBEDTLS_ECP_DP_CURVE25519_ENABLED) +#define MBEDTLS_PSA_BUILTIN_ECC_MONTGOMERY_255 1 +#define PSA_WANT_ECC_MONTGOMERY_255 1 +#endif + +#if defined(MBEDTLS_ECP_DP_CURVE448_ENABLED) +#define MBEDTLS_PSA_BUILTIN_ECC_MONTGOMERY_448 1 +#define PSA_WANT_ECC_MONTGOMERY_448 1 +#endif + +#if defined(MBEDTLS_ECP_DP_SECP192R1_ENABLED) +#define MBEDTLS_PSA_BUILTIN_ECC_SECP_R1_192 1 +#define PSA_WANT_ECC_SECP_R1_192 1 +#endif + +#if defined(MBEDTLS_ECP_DP_SECP224R1_ENABLED) +#define MBEDTLS_PSA_BUILTIN_ECC_SECP_R1_224 1 +#define PSA_WANT_ECC_SECP_R1_224 1 +#endif + +#if defined(MBEDTLS_ECP_DP_SECP256R1_ENABLED) +#define MBEDTLS_PSA_BUILTIN_ECC_SECP_R1_256 1 +#define PSA_WANT_ECC_SECP_R1_256 1 +#endif + +#if defined(MBEDTLS_ECP_DP_SECP384R1_ENABLED) +#define MBEDTLS_PSA_BUILTIN_ECC_SECP_R1_384 1 +#define PSA_WANT_ECC_SECP_R1_384 1 +#endif + +#if defined(MBEDTLS_ECP_DP_SECP521R1_ENABLED) +#define MBEDTLS_PSA_BUILTIN_ECC_SECP_R1_521 1 +#define PSA_WANT_ECC_SECP_R1_521 1 +#endif + +#if defined(MBEDTLS_ECP_DP_SECP192K1_ENABLED) +#define MBEDTLS_PSA_BUILTIN_ECC_SECP_K1_192 1 +#define PSA_WANT_ECC_SECP_K1_192 1 +#endif + +/* SECP224K1 is buggy via the PSA API (https://github.com/Mbed-TLS/mbedtls/issues/3541) */ +#if 0 && defined(MBEDTLS_ECP_DP_SECP224K1_ENABLED) +#define MBEDTLS_PSA_BUILTIN_ECC_SECP_K1_224 1 +#define PSA_WANT_ECC_SECP_K1_224 1 +#endif + +#if defined(MBEDTLS_ECP_DP_SECP256K1_ENABLED) +#define MBEDTLS_PSA_BUILTIN_ECC_SECP_K1_256 1 +#define PSA_WANT_ECC_SECP_K1_256 1 +#endif + +#endif /* MBEDTLS_CONFIG_ADJUST_PSA_FROM_LEGACY_H */ diff --git a/vendor/mbedtls/include/mbedtls/config_adjust_psa_superset_legacy.h b/vendor/mbedtls/include/mbedtls/config_adjust_psa_superset_legacy.h new file mode 100644 index 0000000000..3a55c3f6e1 --- /dev/null +++ b/vendor/mbedtls/include/mbedtls/config_adjust_psa_superset_legacy.h @@ -0,0 +1,142 @@ +/** + * \file mbedtls/config_adjust_psa_superset_legacy.h + * \brief Adjust PSA configuration: automatic enablement from legacy + * + * To simplify some edge cases, we automatically enable certain cryptographic + * mechanisms in the PSA API if they are enabled in the legacy API. The general + * idea is that if legacy module M uses mechanism A internally, and A has + * both a legacy and a PSA implementation, we enable A through PSA whenever + * it's enabled through legacy. This facilitates the transition to PSA + * implementations of A for users of M. + */ +/* + * Copyright The Mbed TLS Contributors + * SPDX-License-Identifier: Apache-2.0 OR GPL-2.0-or-later + */ + +#ifndef MBEDTLS_CONFIG_ADJUST_PSA_SUPERSET_LEGACY_H +#define MBEDTLS_CONFIG_ADJUST_PSA_SUPERSET_LEGACY_H + +/****************************************************************/ +/* Hashes that are built in are also enabled in PSA. + * This simplifies dependency declarations especially + * for modules that obey MBEDTLS_USE_PSA_CRYPTO. */ +/****************************************************************/ + +#if defined(MBEDTLS_MD5_C) +#define PSA_WANT_ALG_MD5 1 +#endif + +#if defined(MBEDTLS_RIPEMD160_C) +#define PSA_WANT_ALG_RIPEMD160 1 +#endif + +#if defined(MBEDTLS_SHA1_C) +#define PSA_WANT_ALG_SHA_1 1 +#endif + +#if defined(MBEDTLS_SHA224_C) +#define PSA_WANT_ALG_SHA_224 1 +#endif + +#if defined(MBEDTLS_SHA256_C) +#define PSA_WANT_ALG_SHA_256 1 +#endif + +#if defined(MBEDTLS_SHA384_C) +#define PSA_WANT_ALG_SHA_384 1 +#endif + +#if defined(MBEDTLS_SHA512_C) +#define PSA_WANT_ALG_SHA_512 1 +#endif + +#if defined(MBEDTLS_SHA3_C) +#define PSA_WANT_ALG_SHA3_224 1 +#define PSA_WANT_ALG_SHA3_256 1 +#define PSA_WANT_ALG_SHA3_384 1 +#define PSA_WANT_ALG_SHA3_512 1 +#endif + +/* Ensure that the PSA's supported curves (PSA_WANT_ECC_xxx) are always a + * superset of the builtin ones (MBEDTLS_ECP_DP_xxx). */ +#if defined(MBEDTLS_ECP_DP_BP256R1_ENABLED) +#if !defined(PSA_WANT_ECC_BRAINPOOL_P_R1_256) +#define PSA_WANT_ECC_BRAINPOOL_P_R1_256 1 +#endif /* PSA_WANT_ECC_BRAINPOOL_P_R1_256 */ +#endif /* MBEDTLS_ECP_DP_BP256R1_ENABLED */ + +#if defined(MBEDTLS_ECP_DP_BP384R1_ENABLED) +#if !defined(PSA_WANT_ECC_BRAINPOOL_P_R1_384) +#define PSA_WANT_ECC_BRAINPOOL_P_R1_384 1 +#endif /* PSA_WANT_ECC_BRAINPOOL_P_R1_384 */ +#endif /*MBEDTLS_ECP_DP_BP384R1_ENABLED */ + +#if defined(MBEDTLS_ECP_DP_BP512R1_ENABLED) +#if !defined(PSA_WANT_ECC_BRAINPOOL_P_R1_512) +#define PSA_WANT_ECC_BRAINPOOL_P_R1_512 1 +#endif /* PSA_WANT_ECC_BRAINPOOL_P_R1_512 */ +#endif /* MBEDTLS_ECP_DP_BP512R1_ENABLED */ + +#if defined(MBEDTLS_ECP_DP_CURVE25519_ENABLED) +#if !defined(PSA_WANT_ECC_MONTGOMERY_255) +#define PSA_WANT_ECC_MONTGOMERY_255 1 +#endif /* PSA_WANT_ECC_MONTGOMERY_255 */ +#endif /* MBEDTLS_ECP_DP_CURVE25519_ENABLED */ + +#if defined(MBEDTLS_ECP_DP_CURVE448_ENABLED) +#if !defined(PSA_WANT_ECC_MONTGOMERY_448) +#define PSA_WANT_ECC_MONTGOMERY_448 1 +#endif /* PSA_WANT_ECC_MONTGOMERY_448 */ +#endif /* MBEDTLS_ECP_DP_CURVE448_ENABLED */ + +#if defined(MBEDTLS_ECP_DP_SECP192R1_ENABLED) +#if !defined(PSA_WANT_ECC_SECP_R1_192) +#define PSA_WANT_ECC_SECP_R1_192 1 +#endif /* PSA_WANT_ECC_SECP_R1_192 */ +#endif /* MBEDTLS_ECP_DP_SECP192R1_ENABLED */ + +#if defined(MBEDTLS_ECP_DP_SECP224R1_ENABLED) +#if !defined(PSA_WANT_ECC_SECP_R1_224) +#define PSA_WANT_ECC_SECP_R1_224 1 +#endif /* PSA_WANT_ECC_SECP_R1_224 */ +#endif /* MBEDTLS_ECP_DP_SECP224R1_ENABLED */ + +#if defined(MBEDTLS_ECP_DP_SECP256R1_ENABLED) +#if !defined(PSA_WANT_ECC_SECP_R1_256) +#define PSA_WANT_ECC_SECP_R1_256 1 +#endif /* PSA_WANT_ECC_SECP_R1_256 */ +#endif /* MBEDTLS_ECP_DP_SECP256R1_ENABLED */ + +#if defined(MBEDTLS_ECP_DP_SECP384R1_ENABLED) +#if !defined(PSA_WANT_ECC_SECP_R1_384) +#define PSA_WANT_ECC_SECP_R1_384 1 +#endif /* PSA_WANT_ECC_SECP_R1_384 */ +#endif /* MBEDTLS_ECP_DP_SECP384R1_ENABLED */ + +#if defined(MBEDTLS_ECP_DP_SECP521R1_ENABLED) +#if !defined(PSA_WANT_ECC_SECP_R1_521) +#define PSA_WANT_ECC_SECP_R1_521 1 +#endif /* PSA_WANT_ECC_SECP_R1_521 */ +#endif /* MBEDTLS_ECP_DP_SECP521R1_ENABLED */ + +#if defined(MBEDTLS_ECP_DP_SECP192K1_ENABLED) +#if !defined(PSA_WANT_ECC_SECP_K1_192) +#define PSA_WANT_ECC_SECP_K1_192 1 +#endif /* PSA_WANT_ECC_SECP_K1_192 */ +#endif /* MBEDTLS_ECP_DP_SECP192K1_ENABLED */ + +/* SECP224K1 is buggy via the PSA API (https://github.com/Mbed-TLS/mbedtls/issues/3541) */ +#if 0 && defined(MBEDTLS_ECP_DP_SECP224K1_ENABLED) +#if !defined(PSA_WANT_ECC_SECP_K1_224) +#define PSA_WANT_ECC_SECP_K1_224 1 +#endif /* PSA_WANT_ECC_SECP_K1_224 */ +#endif /* MBEDTLS_ECP_DP_SECP224K1_ENABLED */ + +#if defined(MBEDTLS_ECP_DP_SECP256K1_ENABLED) +#if !defined(PSA_WANT_ECC_SECP_K1_256) +#define PSA_WANT_ECC_SECP_K1_256 1 +#endif /* PSA_WANT_ECC_SECP_K1_256 */ +#endif /* MBEDTLS_ECP_DP_SECP256K1_ENABLED */ + +#endif /* MBEDTLS_CONFIG_ADJUST_PSA_SUPERSET_LEGACY_H */ diff --git a/vendor/mbedtls/include/mbedtls/config_adjust_ssl.h b/vendor/mbedtls/include/mbedtls/config_adjust_ssl.h new file mode 100644 index 0000000000..39c7b3b117 --- /dev/null +++ b/vendor/mbedtls/include/mbedtls/config_adjust_ssl.h @@ -0,0 +1,81 @@ +/** + * \file mbedtls/config_adjust_ssl.h + * \brief Adjust TLS configuration + * + * Automatically enable certain dependencies. Generally, MBEDLTS_xxx + * configurations need to be explicitly enabled by the user: enabling + * MBEDTLS_xxx_A but not MBEDTLS_xxx_B when A requires B results in a + * compilation error. However, we do automatically enable certain options + * in some circumstances. One case is if MBEDTLS_xxx_B is an internal option + * used to identify parts of a module that are used by other module, and we + * don't want to make the symbol MBEDTLS_xxx_B part of the public API. + * Another case is if A didn't depend on B in earlier versions, and we + * want to use B in A but we need to preserve backward compatibility with + * configurations that explicitly activate MBEDTLS_xxx_A but not + * MBEDTLS_xxx_B. + */ +/* + * Copyright The Mbed TLS Contributors + * SPDX-License-Identifier: Apache-2.0 OR GPL-2.0-or-later + */ + +#ifndef MBEDTLS_CONFIG_ADJUST_SSL_H +#define MBEDTLS_CONFIG_ADJUST_SSL_H + +/* The following blocks make it easier to disable all of TLS, + * or of TLS 1.2 or 1.3 or DTLS, without having to manually disable all + * key exchanges, options and extensions related to them. */ + +#if !defined(MBEDTLS_SSL_TLS_C) +#undef MBEDTLS_SSL_CLI_C +#undef MBEDTLS_SSL_SRV_C +#undef MBEDTLS_SSL_PROTO_TLS1_3 +#undef MBEDTLS_SSL_PROTO_TLS1_2 +#undef MBEDTLS_SSL_PROTO_DTLS +#endif + +#if !(defined(MBEDTLS_SSL_SRV_C) && defined(MBEDTLS_SSL_SESSION_TICKETS)) +#undef MBEDTLS_SSL_TICKET_C +#endif + +#if !defined(MBEDTLS_SSL_PROTO_DTLS) +#undef MBEDTLS_SSL_DTLS_ANTI_REPLAY +#undef MBEDTLS_SSL_DTLS_CONNECTION_ID +#undef MBEDTLS_SSL_DTLS_CONNECTION_ID_COMPAT +#undef MBEDTLS_SSL_DTLS_HELLO_VERIFY +#undef MBEDTLS_SSL_DTLS_SRTP +#undef MBEDTLS_SSL_DTLS_CLIENT_PORT_REUSE +#endif + +#if !defined(MBEDTLS_SSL_PROTO_TLS1_2) +#undef MBEDTLS_SSL_ENCRYPT_THEN_MAC +#undef MBEDTLS_SSL_EXTENDED_MASTER_SECRET +#undef MBEDTLS_SSL_RENEGOTIATION +#undef MBEDTLS_KEY_EXCHANGE_RSA_ENABLED +#undef MBEDTLS_KEY_EXCHANGE_DHE_RSA_ENABLED +#undef MBEDTLS_KEY_EXCHANGE_ECDHE_RSA_ENABLED +#undef MBEDTLS_KEY_EXCHANGE_ECDHE_ECDSA_ENABLED +#undef MBEDTLS_KEY_EXCHANGE_PSK_ENABLED +#undef MBEDTLS_KEY_EXCHANGE_DHE_PSK_ENABLED +#undef MBEDTLS_KEY_EXCHANGE_RSA_PSK_ENABLED +#undef MBEDTLS_KEY_EXCHANGE_ECDHE_PSK_ENABLED +#undef MBEDTLS_KEY_EXCHANGE_ECDH_RSA_ENABLED +#undef MBEDTLS_KEY_EXCHANGE_ECDH_ECDSA_ENABLED +#undef MBEDTLS_KEY_EXCHANGE_ECJPAKE_ENABLED +#endif + +#if !defined(MBEDTLS_SSL_PROTO_TLS1_3) +#undef MBEDTLS_SSL_TLS1_3_KEY_EXCHANGE_MODE_PSK_ENABLED +#undef MBEDTLS_SSL_TLS1_3_KEY_EXCHANGE_MODE_EPHEMERAL_ENABLED +#undef MBEDTLS_SSL_TLS1_3_KEY_EXCHANGE_MODE_PSK_EPHEMERAL_ENABLED +#undef MBEDTLS_SSL_EARLY_DATA +#undef MBEDTLS_SSL_RECORD_SIZE_LIMIT +#endif + +#if defined(MBEDTLS_SSL_PROTO_TLS1_2) && \ + (defined(MBEDTLS_ECDH_C) || defined(MBEDTLS_ECDSA_C) || \ + defined(MBEDTLS_KEY_EXCHANGE_ECJPAKE_ENABLED)) +#define MBEDTLS_SSL_TLS1_2_SOME_ECC +#endif + +#endif /* MBEDTLS_CONFIG_ADJUST_SSL_H */ diff --git a/vendor/mbedtls/include/mbedtls/config_adjust_x509.h b/vendor/mbedtls/include/mbedtls/config_adjust_x509.h new file mode 100644 index 0000000000..346c8ae6d5 --- /dev/null +++ b/vendor/mbedtls/include/mbedtls/config_adjust_x509.h @@ -0,0 +1,25 @@ +/** + * \file mbedtls/config_adjust_x509.h + * \brief Adjust X.509 configuration + * + * Automatically enable certain dependencies. Generally, MBEDLTS_xxx + * configurations need to be explicitly enabled by the user: enabling + * MBEDTLS_xxx_A but not MBEDTLS_xxx_B when A requires B results in a + * compilation error. However, we do automatically enable certain options + * in some circumstances. One case is if MBEDTLS_xxx_B is an internal option + * used to identify parts of a module that are used by other module, and we + * don't want to make the symbol MBEDTLS_xxx_B part of the public API. + * Another case is if A didn't depend on B in earlier versions, and we + * want to use B in A but we need to preserve backward compatibility with + * configurations that explicitly activate MBEDTLS_xxx_A but not + * MBEDTLS_xxx_B. + */ +/* + * Copyright The Mbed TLS Contributors + * SPDX-License-Identifier: Apache-2.0 OR GPL-2.0-or-later + */ + +#ifndef MBEDTLS_CONFIG_ADJUST_X509_H +#define MBEDTLS_CONFIG_ADJUST_X509_H + +#endif /* MBEDTLS_CONFIG_ADJUST_X509_H */ diff --git a/vendor/mbedtls/include/mbedtls/config_psa.h b/vendor/mbedtls/include/mbedtls/config_psa.h index 67d5df11b3..17da61b3e8 100644 --- a/vendor/mbedtls/include/mbedtls/config_psa.h +++ b/vendor/mbedtls/include/mbedtls/config_psa.h @@ -3,835 +3,53 @@ * \brief PSA crypto configuration options (set of defines) * * This set of compile-time options takes settings defined in - * include/mbedtls/config.h and include/psa/crypto_config.h and uses + * include/mbedtls/mbedtls_config.h and include/psa/crypto_config.h and uses * those definitions to define symbols used in the library code. * * Users and integrators should not edit this file, please edit - * include/mbedtls/config.h for MBEDTLS_XXX settings or + * include/mbedtls/mbedtls_config.h for MBEDTLS_XXX settings or * include/psa/crypto_config.h for PSA_WANT_XXX settings. */ /* * Copyright The Mbed TLS Contributors - * SPDX-License-Identifier: Apache-2.0 - * - * Licensed under the Apache License, Version 2.0 (the "License"); you may - * not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT - * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. + * SPDX-License-Identifier: Apache-2.0 OR GPL-2.0-or-later */ #ifndef MBEDTLS_CONFIG_PSA_H #define MBEDTLS_CONFIG_PSA_H -#if defined(MBEDTLS_PSA_CRYPTO_CONFIG) -#if defined(MBEDTLS_PSA_CRYPTO_CONFIG_FILE) -#include MBEDTLS_PSA_CRYPTO_CONFIG_FILE -#else -#include "psa/crypto_config.h" -#endif -#endif /* defined(MBEDTLS_PSA_CRYPTO_CONFIG) */ - -#if defined(MBEDTLS_PSA_CRYPTO_USER_CONFIG_FILE) -#include MBEDTLS_PSA_CRYPTO_USER_CONFIG_FILE -#endif - -#ifdef __cplusplus -extern "C" { -#endif - - - -/****************************************************************/ -/* De facto synonyms */ -/****************************************************************/ - -#if defined(PSA_WANT_ALG_ECDSA_ANY) && !defined(PSA_WANT_ALG_ECDSA) -#define PSA_WANT_ALG_ECDSA PSA_WANT_ALG_ECDSA_ANY -#elif !defined(PSA_WANT_ALG_ECDSA_ANY) && defined(PSA_WANT_ALG_ECDSA) -#define PSA_WANT_ALG_ECDSA_ANY PSA_WANT_ALG_ECDSA -#endif - -#if defined(PSA_WANT_ALG_RSA_PKCS1V15_SIGN_RAW) && !defined(PSA_WANT_ALG_RSA_PKCS1V15_SIGN) -#define PSA_WANT_ALG_RSA_PKCS1V15_SIGN PSA_WANT_ALG_RSA_PKCS1V15_SIGN_RAW -#elif !defined(PSA_WANT_ALG_RSA_PKCS1V15_SIGN_RAW) && defined(PSA_WANT_ALG_RSA_PKCS1V15_SIGN) -#define PSA_WANT_ALG_RSA_PKCS1V15_SIGN_RAW PSA_WANT_ALG_RSA_PKCS1V15_SIGN -#endif - -#if defined(PSA_WANT_ALG_RSA_PSS_ANY_SALT) && !defined(PSA_WANT_ALG_RSA_PSS) -#define PSA_WANT_ALG_RSA_PSS PSA_WANT_ALG_RSA_PSS_ANY_SALT -#elif !defined(PSA_WANT_ALG_RSA_PSS_ANY_SALT) && defined(PSA_WANT_ALG_RSA_PSS) -#define PSA_WANT_ALG_RSA_PSS_ANY_SALT PSA_WANT_ALG_RSA_PSS -#endif +#include "psa/crypto_legacy.h" +#include "psa/crypto_adjust_config_synonyms.h" - -/****************************************************************/ -/* Require built-in implementations based on PSA requirements */ -/****************************************************************/ +#include "mbedtls/config_adjust_psa_superset_legacy.h" #if defined(MBEDTLS_PSA_CRYPTO_CONFIG) -#if defined(PSA_WANT_ALG_DETERMINISTIC_ECDSA) -#if !defined(MBEDTLS_PSA_ACCEL_ALG_DETERMINISTIC_ECDSA) -#define MBEDTLS_PSA_BUILTIN_ALG_DETERMINISTIC_ECDSA 1 -#define MBEDTLS_ECDSA_DETERMINISTIC -#define MBEDTLS_ECDSA_C -#define MBEDTLS_HMAC_DRBG_C -#define MBEDTLS_MD_C -#endif /* !MBEDTLS_PSA_ACCEL_ALG_DETERMINISTIC_ECDSA */ -#endif /* PSA_WANT_ALG_DETERMINISTIC_ECDSA */ - -#if defined(PSA_WANT_ALG_ECDH) -#if !defined(MBEDTLS_PSA_ACCEL_ALG_ECDH) -#define MBEDTLS_PSA_BUILTIN_ALG_ECDH 1 -#define MBEDTLS_ECDH_C -#define MBEDTLS_ECP_C -#define MBEDTLS_BIGNUM_C -#endif /* !MBEDTLS_PSA_ACCEL_ALG_ECDH */ -#endif /* PSA_WANT_ALG_ECDH */ - -#if defined(PSA_WANT_ALG_ECDSA) -#if !defined(MBEDTLS_PSA_ACCEL_ALG_ECDSA) -#define MBEDTLS_PSA_BUILTIN_ALG_ECDSA 1 -#define MBEDTLS_ECDSA_C -#define MBEDTLS_ECP_C -#define MBEDTLS_BIGNUM_C -#define MBEDTLS_ASN1_PARSE_C -#define MBEDTLS_ASN1_WRITE_C -#endif /* !MBEDTLS_PSA_ACCEL_ALG_ECDSA */ -#endif /* PSA_WANT_ALG_ECDSA */ - -#if defined(PSA_WANT_ALG_HKDF) -#if !defined(MBEDTLS_PSA_ACCEL_ALG_HKDF) -/* - * The PSA implementation has its own implementation of HKDF, separate from - * hkdf.c. No need to enable MBEDTLS_HKDF_C here. - */ -#define MBEDTLS_PSA_BUILTIN_ALG_HMAC 1 -#define MBEDTLS_PSA_BUILTIN_ALG_HKDF 1 -#endif /* !MBEDTLS_PSA_ACCEL_ALG_HKDF */ -#endif /* PSA_WANT_ALG_HKDF */ - -#if defined(PSA_WANT_ALG_HMAC) -#if !defined(MBEDTLS_PSA_ACCEL_ALG_HMAC) -#define MBEDTLS_PSA_BUILTIN_ALG_HMAC 1 -#endif /* !MBEDTLS_PSA_ACCEL_ALG_HMAC */ -#endif /* PSA_WANT_ALG_HMAC */ - -#if defined(PSA_WANT_ALG_MD2) && !defined(MBEDTLS_PSA_ACCEL_ALG_MD2) -#define MBEDTLS_PSA_BUILTIN_ALG_MD2 1 -#define MBEDTLS_MD2_C -#endif - -#if defined(PSA_WANT_ALG_MD4) && !defined(MBEDTLS_PSA_ACCEL_ALG_MD4) -#define MBEDTLS_PSA_BUILTIN_ALG_MD4 1 -#define MBEDTLS_MD4_C -#endif - -#if defined(PSA_WANT_ALG_MD5) && !defined(MBEDTLS_PSA_ACCEL_ALG_MD5) -#define MBEDTLS_PSA_BUILTIN_ALG_MD5 1 -#define MBEDTLS_MD5_C -#endif - -#if defined(PSA_WANT_ALG_RIPEMD160) && !defined(MBEDTLS_PSA_ACCEL_ALG_RIPEMD160) -#define MBEDTLS_PSA_BUILTIN_ALG_RIPEMD160 1 -#define MBEDTLS_RIPEMD160_C -#endif - -#if defined(PSA_WANT_ALG_RSA_OAEP) -#if !defined(MBEDTLS_PSA_ACCEL_ALG_RSA_OAEP) -#define MBEDTLS_PSA_BUILTIN_ALG_RSA_OAEP 1 -#define MBEDTLS_RSA_C -#define MBEDTLS_BIGNUM_C -#define MBEDTLS_OID_C -#define MBEDTLS_PKCS1_V21 -#define MBEDTLS_MD_C -#endif /* !MBEDTLS_PSA_ACCEL_ALG_RSA_OAEP */ -#endif /* PSA_WANT_ALG_RSA_OAEP */ - -#if defined(PSA_WANT_ALG_RSA_PKCS1V15_CRYPT) -#if !defined(MBEDTLS_PSA_ACCEL_ALG_RSA_PKCS1V15_CRYPT) -#define MBEDTLS_PSA_BUILTIN_ALG_RSA_PKCS1V15_CRYPT 1 -#define MBEDTLS_RSA_C -#define MBEDTLS_BIGNUM_C -#define MBEDTLS_OID_C -#define MBEDTLS_PKCS1_V15 -#endif /* !MBEDTLS_PSA_ACCEL_ALG_RSA_PKCS1V15_CRYPT */ -#endif /* PSA_WANT_ALG_RSA_PKCS1V15_CRYPT */ - -#if defined(PSA_WANT_ALG_RSA_PKCS1V15_SIGN) -#if !defined(MBEDTLS_PSA_ACCEL_ALG_RSA_PKCS1V15_SIGN) -#define MBEDTLS_PSA_BUILTIN_ALG_RSA_PKCS1V15_SIGN 1 -#define MBEDTLS_RSA_C -#define MBEDTLS_BIGNUM_C -#define MBEDTLS_OID_C -#define MBEDTLS_PKCS1_V15 -#define MBEDTLS_MD_C -#endif /* !MBEDTLS_PSA_ACCEL_ALG_RSA_PKCS1V15_SIGN */ -#endif /* PSA_WANT_ALG_RSA_PKCS1V15_SIGN */ - -#if defined(PSA_WANT_ALG_RSA_PSS) -#if !defined(MBEDTLS_PSA_ACCEL_ALG_RSA_PSS) -#define MBEDTLS_PSA_BUILTIN_ALG_RSA_PSS 1 -#define MBEDTLS_RSA_C -#define MBEDTLS_BIGNUM_C -#define MBEDTLS_OID_C -#define MBEDTLS_PKCS1_V21 -#define MBEDTLS_MD_C -#endif /* !MBEDTLS_PSA_ACCEL_ALG_RSA_PSS */ -#endif /* PSA_WANT_ALG_RSA_PSS */ - -#if defined(PSA_WANT_ALG_SHA_1) && !defined(MBEDTLS_PSA_ACCEL_ALG_SHA_1) -#define MBEDTLS_PSA_BUILTIN_ALG_SHA_1 1 -#define MBEDTLS_SHA1_C -#endif - -#if defined(PSA_WANT_ALG_SHA_224) && !defined(MBEDTLS_PSA_ACCEL_ALG_SHA_224) -#define MBEDTLS_PSA_BUILTIN_ALG_SHA_224 1 -#define MBEDTLS_SHA256_C -#endif - -#if defined(PSA_WANT_ALG_SHA_256) && !defined(MBEDTLS_PSA_ACCEL_ALG_SHA_256) -#define MBEDTLS_PSA_BUILTIN_ALG_SHA_256 1 -#define MBEDTLS_SHA256_C -#endif - -#if defined(PSA_WANT_ALG_SHA_384) && !defined(MBEDTLS_PSA_ACCEL_ALG_SHA_384) -#define MBEDTLS_PSA_BUILTIN_ALG_SHA_384 1 -#define MBEDTLS_SHA512_C -#endif - -#if defined(PSA_WANT_ALG_SHA_512) && !defined(MBEDTLS_PSA_ACCEL_ALG_SHA_512) -#define MBEDTLS_PSA_BUILTIN_ALG_SHA_512 1 -#define MBEDTLS_SHA512_C -#endif - -#if defined(PSA_WANT_ALG_TLS12_PRF) -#if !defined(MBEDTLS_PSA_ACCEL_ALG_TLS12_PRF) -#define MBEDTLS_PSA_BUILTIN_ALG_TLS12_PRF 1 -#endif /* !MBEDTLS_PSA_ACCEL_ALG_TLS12_PRF */ -#endif /* PSA_WANT_ALG_TLS12_PRF */ - -#if defined(PSA_WANT_ALG_TLS12_PSK_TO_MS) -#if !defined(MBEDTLS_PSA_ACCEL_ALG_TLS12_PSK_TO_MS) -#define MBEDTLS_PSA_BUILTIN_ALG_TLS12_PSK_TO_MS 1 -#endif /* !MBEDTLS_PSA_ACCEL_ALG_TLS12_PSK_TO_MS */ -#endif /* PSA_WANT_ALG_TLS12_PSK_TO_MS */ - -#if defined(PSA_WANT_KEY_TYPE_ECC_KEY_PAIR) -#if !defined(MBEDTLS_PSA_ACCEL_KEY_TYPE_ECC_KEY_PAIR) -#define MBEDTLS_PSA_BUILTIN_KEY_TYPE_ECC_KEY_PAIR 1 -#define MBEDTLS_ECP_C -#define MBEDTLS_BIGNUM_C -#endif /* !MBEDTLS_PSA_ACCEL_KEY_TYPE_ECC_KEY_PAIR */ -#endif /* PSA_WANT_KEY_TYPE_ECC_KEY_PAIR */ - -#if defined(PSA_WANT_KEY_TYPE_ECC_PUBLIC_KEY) -#if !defined(MBEDTLS_PSA_ACCEL_KEY_TYPE_ECC_PUBLIC_KEY) -#define MBEDTLS_PSA_BUILTIN_KEY_TYPE_ECC_PUBLIC_KEY 1 -#define MBEDTLS_ECP_C -#define MBEDTLS_BIGNUM_C -#endif /* !MBEDTLS_PSA_ACCEL_KEY_TYPE_ECC_PUBLIC_KEY */ -#endif /* PSA_WANT_KEY_TYPE_ECC_PUBLIC_KEY */ - -#if defined(PSA_WANT_KEY_TYPE_RSA_KEY_PAIR) -#if !defined(MBEDTLS_PSA_ACCEL_KEY_TYPE_RSA_KEY_PAIR) -#define MBEDTLS_PSA_BUILTIN_KEY_TYPE_RSA_KEY_PAIR 1 -#define MBEDTLS_RSA_C -#define MBEDTLS_BIGNUM_C -#define MBEDTLS_OID_C -#define MBEDTLS_GENPRIME -#define MBEDTLS_PK_PARSE_C -#define MBEDTLS_PK_WRITE_C -#define MBEDTLS_PK_C -#define MBEDTLS_ASN1_PARSE_C -#define MBEDTLS_ASN1_WRITE_C -#endif /* !MBEDTLS_PSA_ACCEL_KEY_TYPE_RSA_KEY_PAIR */ -#endif /* PSA_WANT_KEY_TYPE_RSA_KEY_PAIR */ - -#if defined(PSA_WANT_KEY_TYPE_RSA_PUBLIC_KEY) -#if !defined(MBEDTLS_PSA_ACCEL_KEY_TYPE_RSA_PUBLIC_KEY) -#define MBEDTLS_PSA_BUILTIN_KEY_TYPE_RSA_PUBLIC_KEY 1 -#define MBEDTLS_RSA_C -#define MBEDTLS_BIGNUM_C -#define MBEDTLS_OID_C -#define MBEDTLS_PK_PARSE_C -#define MBEDTLS_PK_WRITE_C -#define MBEDTLS_PK_C -#define MBEDTLS_ASN1_PARSE_C -#define MBEDTLS_ASN1_WRITE_C -#endif /* !MBEDTLS_PSA_ACCEL_KEY_TYPE_RSA_PUBLIC_KEY */ -#endif /* PSA_WANT_KEY_TYPE_RSA_PUBLIC_KEY */ - -/* If any of the block modes are requested that don't have an - * associated HW assist, define PSA_HAVE_SOFT_BLOCK_MODE for checking - * in the block cipher key types. */ -#if (defined(PSA_WANT_ALG_CTR) && !defined(MBEDTLS_PSA_ACCEL_ALG_CTR)) || \ - (defined(PSA_WANT_ALG_CFB) && !defined(MBEDTLS_PSA_ACCEL_ALG_CFB)) || \ - (defined(PSA_WANT_ALG_OFB) && !defined(MBEDTLS_PSA_ACCEL_ALG_OFB)) || \ - defined(PSA_WANT_ALG_ECB_NO_PADDING) || \ - (defined(PSA_WANT_ALG_CBC_NO_PADDING) && \ - !defined(MBEDTLS_PSA_ACCEL_ALG_CBC_NO_PADDING)) || \ - (defined(PSA_WANT_ALG_CBC_PKCS7) && \ - !defined(MBEDTLS_PSA_ACCEL_ALG_CBC_PKCS7)) || \ - (defined(PSA_WANT_ALG_CMAC) && !defined(MBEDTLS_PSA_ACCEL_ALG_CMAC)) -#define PSA_HAVE_SOFT_BLOCK_MODE 1 -#endif - -#if (defined(PSA_WANT_ALG_GCM) && !defined(MBEDTLS_PSA_ACCEL_ALG_GCM)) || \ - (defined(PSA_WANT_ALG_CCM) && !defined(MBEDTLS_PSA_ACCEL_ALG_CCM)) -#define PSA_HAVE_SOFT_BLOCK_AEAD 1 -#endif - -#if defined(PSA_WANT_KEY_TYPE_AES) -#if !defined(MBEDTLS_PSA_ACCEL_KEY_TYPE_AES) -#define PSA_HAVE_SOFT_KEY_TYPE_AES 1 -#endif /* !MBEDTLS_PSA_ACCEL_KEY_TYPE_AES */ -#if defined(PSA_HAVE_SOFT_KEY_TYPE_AES) || \ - defined(PSA_HAVE_SOFT_BLOCK_MODE) || \ - defined(PSA_HAVE_SOFT_BLOCK_AEAD) -#define MBEDTLS_PSA_BUILTIN_KEY_TYPE_AES 1 -#define MBEDTLS_AES_C -#endif /* PSA_HAVE_SOFT_KEY_TYPE_AES || PSA_HAVE_SOFT_BLOCK_MODE */ -#endif /* PSA_WANT_KEY_TYPE_AES */ - -#if defined(PSA_WANT_KEY_TYPE_ARC4) -#if !defined(MBEDTLS_PSA_ACCEL_KEY_TYPE_ARC4) -#define MBEDTLS_PSA_BUILTIN_KEY_TYPE_ARC4 1 -#define MBEDTLS_ARC4_C -#endif /*!MBEDTLS_PSA_ACCEL_KEY_TYPE_ARC4 */ -#endif /* PSA_WANT_KEY_TYPE_ARC4 */ - -#if defined(PSA_WANT_KEY_TYPE_ARIA) -#if !defined(MBEDTLS_PSA_ACCEL_KEY_TYPE_ARIA) -#define PSA_HAVE_SOFT_KEY_TYPE_ARIA 1 -#endif /* !MBEDTLS_PSA_ACCEL_KEY_TYPE_ARIA */ -#if defined(PSA_HAVE_SOFT_KEY_TYPE_ARIA) || \ - defined(PSA_HAVE_SOFT_BLOCK_MODE) || \ - defined(PSA_HAVE_SOFT_BLOCK_AEAD) -#define MBEDTLS_PSA_BUILTIN_KEY_TYPE_ARIA 1 -#define MBEDTLS_ARIA_C -#endif /* PSA_HAVE_SOFT_KEY_TYPE_ARIA || PSA_HAVE_SOFT_BLOCK_MODE */ -#endif /* PSA_WANT_KEY_TYPE_ARIA */ - -#if defined(PSA_WANT_KEY_TYPE_CAMELLIA) -#if !defined(MBEDTLS_PSA_ACCEL_KEY_TYPE_CAMELLIA) -#define PSA_HAVE_SOFT_KEY_TYPE_CAMELLIA 1 -#endif /* !MBEDTLS_PSA_ACCEL_KEY_TYPE_CAMELLIA */ -#if defined(PSA_HAVE_SOFT_KEY_TYPE_CAMELLIA) || \ - defined(PSA_HAVE_SOFT_BLOCK_MODE) || \ - defined(PSA_HAVE_SOFT_BLOCK_AEAD) -#define MBEDTLS_PSA_BUILTIN_KEY_TYPE_CAMELLIA 1 -#define MBEDTLS_CAMELLIA_C -#endif /* PSA_HAVE_SOFT_KEY_TYPE_CAMELLIA || PSA_HAVE_SOFT_BLOCK_MODE */ -#endif /* PSA_WANT_KEY_TYPE_CAMELLIA */ - -#if defined(PSA_WANT_KEY_TYPE_DES) -#if !defined(MBEDTLS_PSA_ACCEL_KEY_TYPE_DES) -#define PSA_HAVE_SOFT_KEY_TYPE_DES 1 -#endif /* !MBEDTLS_PSA_ACCEL_KEY_TYPE_DES */ -#if defined(PSA_HAVE_SOFT_KEY_TYPE_DES) || \ - defined(PSA_HAVE_SOFT_BLOCK_MODE) -#define MBEDTLS_PSA_BUILTIN_KEY_TYPE_DES 1 -#define MBEDTLS_DES_C -#endif /*PSA_HAVE_SOFT_KEY_TYPE_DES || PSA_HAVE_SOFT_BLOCK_MODE */ -#endif /* PSA_WANT_KEY_TYPE_DES */ - -#if defined(PSA_WANT_KEY_TYPE_CHACHA20) -#if !defined(MBEDTLS_PSA_ACCEL_KEY_TYPE_CHACHA20) -#define MBEDTLS_PSA_BUILTIN_KEY_TYPE_CHACHA20 1 -#define MBEDTLS_CHACHA20_C -#endif /*!MBEDTLS_PSA_ACCEL_KEY_TYPE_CHACHA20 */ -#endif /* PSA_WANT_KEY_TYPE_CHACHA20 */ - -/* If any of the software block ciphers are selected, define - * PSA_HAVE_SOFT_BLOCK_CIPHER, which can be used in any of these - * situations. */ -#if defined(PSA_HAVE_SOFT_KEY_TYPE_AES) || \ - defined(PSA_HAVE_SOFT_KEY_TYPE_ARIA) || \ - defined(PSA_HAVE_SOFT_KEY_TYPE_DES) || \ - defined(PSA_HAVE_SOFT_KEY_TYPE_CAMELLIA) -#define PSA_HAVE_SOFT_BLOCK_CIPHER 1 -#endif - -#if defined(PSA_WANT_ALG_STREAM_CIPHER) -#define MBEDTLS_PSA_BUILTIN_ALG_STREAM_CIPHER 1 -#endif /* PSA_WANT_ALG_STREAM_CIPHER */ - -#if defined(PSA_WANT_ALG_CBC_MAC) -#if !defined(MBEDTLS_PSA_ACCEL_ALG_CBC_MAC) -#error "CBC-MAC is not yet supported via the PSA API in Mbed TLS." -#define MBEDTLS_PSA_BUILTIN_ALG_CBC_MAC 1 -#endif /* !MBEDTLS_PSA_ACCEL_ALG_CBC_MAC */ -#endif /* PSA_WANT_ALG_CBC_MAC */ - -#if defined(PSA_WANT_ALG_CMAC) -#if !defined(MBEDTLS_PSA_ACCEL_ALG_CMAC) || \ - defined(PSA_HAVE_SOFT_BLOCK_CIPHER) -#define MBEDTLS_PSA_BUILTIN_ALG_CMAC 1 -#define MBEDTLS_CMAC_C -#endif /* !MBEDTLS_PSA_ACCEL_ALG_CMAC */ -#endif /* PSA_WANT_ALG_CMAC */ - -#if defined(PSA_WANT_ALG_CTR) -#if !defined(MBEDTLS_PSA_ACCEL_ALG_CTR) || \ - defined(PSA_HAVE_SOFT_BLOCK_CIPHER) -#define MBEDTLS_PSA_BUILTIN_ALG_CTR 1 -#define MBEDTLS_CIPHER_MODE_CTR -#endif -#endif /* PSA_WANT_ALG_CTR */ - -#if defined(PSA_WANT_ALG_CFB) -#if !defined(MBEDTLS_PSA_ACCEL_ALG_CFB) || \ - defined(PSA_HAVE_SOFT_BLOCK_CIPHER) -#define MBEDTLS_PSA_BUILTIN_ALG_CFB 1 -#define MBEDTLS_CIPHER_MODE_CFB -#endif -#endif /* PSA_WANT_ALG_CFB */ - -#if defined(PSA_WANT_ALG_OFB) -#if !defined(MBEDTLS_PSA_ACCEL_ALG_OFB) || \ - defined(PSA_HAVE_SOFT_BLOCK_CIPHER) -#define MBEDTLS_PSA_BUILTIN_ALG_OFB 1 -#define MBEDTLS_CIPHER_MODE_OFB -#endif -#endif /* PSA_WANT_ALG_OFB */ - -#if defined(PSA_WANT_ALG_ECB_NO_PADDING) && \ - !defined(MBEDTLS_PSA_ACCEL_ALG_ECB_NO_PADDING) -#define MBEDTLS_PSA_BUILTIN_ALG_ECB_NO_PADDING 1 -#endif - -#if defined(PSA_WANT_ALG_CBC_NO_PADDING) -#if !defined(MBEDTLS_PSA_ACCEL_ALG_CBC_NO_PADDING) || \ - defined(PSA_HAVE_SOFT_BLOCK_CIPHER) -#define MBEDTLS_CIPHER_MODE_CBC -#define MBEDTLS_PSA_BUILTIN_ALG_CBC_NO_PADDING 1 -#endif -#endif /* PSA_WANT_ALG_CBC_NO_PADDING */ - -#if defined(PSA_WANT_ALG_CBC_PKCS7) -#if !defined(MBEDTLS_PSA_ACCEL_ALG_CBC_PKCS7) || \ - defined(PSA_HAVE_SOFT_BLOCK_CIPHER) -#define MBEDTLS_CIPHER_MODE_CBC -#define MBEDTLS_PSA_BUILTIN_ALG_CBC_PKCS7 1 -#define MBEDTLS_CIPHER_PADDING_PKCS7 -#endif -#endif /* PSA_WANT_ALG_CBC_PKCS7 */ - -#if defined(PSA_WANT_ALG_CCM) -#if !defined(MBEDTLS_PSA_ACCEL_ALG_CCM) || \ - defined(PSA_HAVE_SOFT_KEY_TYPE_AES) || \ - defined(PSA_HAVE_SOFT_KEY_TYPE_ARIA) || \ - defined(PSA_HAVE_SOFT_KEY_TYPE_CAMELLIA) -#define MBEDTLS_PSA_BUILTIN_ALG_CCM 1 -#define MBEDTLS_CCM_C -#endif -#endif /* PSA_WANT_ALG_CCM */ - -#if defined(PSA_WANT_ALG_GCM) -#if !defined(MBEDTLS_PSA_ACCEL_ALG_GCM) || \ - defined(PSA_HAVE_SOFT_KEY_TYPE_AES) || \ - defined(PSA_HAVE_SOFT_KEY_TYPE_ARIA) || \ - defined(PSA_HAVE_SOFT_KEY_TYPE_CAMELLIA) -#define MBEDTLS_PSA_BUILTIN_ALG_GCM 1 -#define MBEDTLS_GCM_C -#endif -#endif /* PSA_WANT_ALG_GCM */ - -#if defined(PSA_WANT_ALG_CHACHA20_POLY1305) -#if !defined(MBEDTLS_PSA_ACCEL_ALG_CHACHA20_POLY1305) -#if defined(PSA_WANT_KEY_TYPE_CHACHA20) -#define MBEDTLS_CHACHAPOLY_C -#define MBEDTLS_CHACHA20_C -#define MBEDTLS_POLY1305_C -#define MBEDTLS_PSA_BUILTIN_ALG_CHACHA20_POLY1305 1 -#endif /* PSA_WANT_KEY_TYPE_CHACHA20 */ -#endif /* !MBEDTLS_PSA_ACCEL_ALG_CHACHA20_POLY1305 */ -#endif /* PSA_WANT_ALG_CHACHA20_POLY1305 */ - -#if defined(PSA_WANT_ECC_BRAINPOOL_P_R1_256) -#if !defined(MBEDTLS_PSA_ACCEL_ECC_BRAINPOOL_P_R1_256) -#define MBEDTLS_ECP_DP_BP256R1_ENABLED -#define MBEDTLS_PSA_BUILTIN_ECC_BRAINPOOL_P_R1_256 1 -#endif /* !MBEDTLS_PSA_ACCEL_ECC_BRAINPOOL_P_R1_256 */ -#endif /* PSA_WANT_ECC_BRAINPOOL_P_R1_256 */ - -#if defined(PSA_WANT_ECC_BRAINPOOL_P_R1_384) -#if !defined(MBEDTLS_PSA_ACCEL_ECC_BRAINPOOL_P_R1_384) -#define MBEDTLS_ECP_DP_BP384R1_ENABLED -#define MBEDTLS_PSA_BUILTIN_ECC_BRAINPOOL_P_R1_384 1 -#endif /* !MBEDTLS_PSA_ACCEL_ECC_BRAINPOOL_P_R1_384 */ -#endif /* PSA_WANT_ECC_BRAINPOOL_P_R1_384 */ - -#if defined(PSA_WANT_ECC_BRAINPOOL_P_R1_512) -#if !defined(MBEDTLS_PSA_ACCEL_ECC_BRAINPOOL_P_R1_512) -#define MBEDTLS_ECP_DP_BP512R1_ENABLED -#define MBEDTLS_PSA_BUILTIN_ECC_BRAINPOOL_P_R1_512 1 -#endif /* !MBEDTLS_PSA_ACCEL_ECC_BRAINPOOL_P_R1_512 */ -#endif /* PSA_WANT_ECC_BRAINPOOL_P_R1_512 */ - -#if defined(PSA_WANT_ECC_MONTGOMERY_255) -#if !defined(MBEDTLS_PSA_ACCEL_ECC_MONTGOMERY_255) -#define MBEDTLS_ECP_DP_CURVE25519_ENABLED -#define MBEDTLS_PSA_BUILTIN_ECC_MONTGOMERY_255 1 -#endif /* !MBEDTLS_PSA_ACCEL_ECC_MONTGOMERY_255 */ -#endif /* PSA_WANT_ECC_MONTGOMERY_255 */ - -#if defined(PSA_WANT_ECC_MONTGOMERY_448) -#if !defined(MBEDTLS_PSA_ACCEL_ECC_MONTGOMERY_448) -/* - * Curve448 is not yet supported via the PSA API in Mbed TLS - * (https://github.com/Mbed-TLS/mbedtls/issues/4249). - */ -#error "Curve448 is not yet supported via the PSA API in Mbed TLS." -#define MBEDTLS_ECP_DP_CURVE448_ENABLED -#define MBEDTLS_PSA_BUILTIN_ECC_MONTGOMERY_448 1 -#endif /* !MBEDTLS_PSA_ACCEL_ECC_MONTGOMERY_448 */ -#endif /* PSA_WANT_ECC_MONTGOMERY_448 */ - -#if defined(PSA_WANT_ECC_SECP_R1_192) -#if !defined(MBEDTLS_PSA_ACCEL_ECC_SECP_R1_192) -#define MBEDTLS_ECP_DP_SECP192R1_ENABLED -#define MBEDTLS_PSA_BUILTIN_ECC_SECP_R1_192 1 -#endif /* !MBEDTLS_PSA_ACCEL_ECC_SECP_R1_192 */ -#endif /* PSA_WANT_ECC_SECP_R1_192 */ - -#if defined(PSA_WANT_ECC_SECP_R1_224) -#if !defined(MBEDTLS_PSA_ACCEL_ECC_SECP_R1_224) -#define MBEDTLS_ECP_DP_SECP224R1_ENABLED -#define MBEDTLS_PSA_BUILTIN_ECC_SECP_R1_224 1 -#endif /* !MBEDTLS_PSA_ACCEL_ECC_SECP_R1_224 */ -#endif /* PSA_WANT_ECC_SECP_R1_224 */ - -#if defined(PSA_WANT_ECC_SECP_R1_256) -#if !defined(MBEDTLS_PSA_ACCEL_ECC_SECP_R1_256) -#define MBEDTLS_ECP_DP_SECP256R1_ENABLED -#define MBEDTLS_PSA_BUILTIN_ECC_SECP_R1_256 1 -#endif /* !MBEDTLS_PSA_ACCEL_ECC_SECP_R1_256 */ -#endif /* PSA_WANT_ECC_SECP_R1_256 */ - -#if defined(PSA_WANT_ECC_SECP_R1_384) -#if !defined(MBEDTLS_PSA_ACCEL_ECC_SECP_R1_384) -#define MBEDTLS_ECP_DP_SECP384R1_ENABLED -#define MBEDTLS_PSA_BUILTIN_ECC_SECP_R1_384 1 -#endif /* !MBEDTLS_PSA_ACCEL_ECC_SECP_R1_384 */ -#endif /* PSA_WANT_ECC_SECP_R1_384 */ - -#if defined(PSA_WANT_ECC_SECP_R1_521) -#if !defined(MBEDTLS_PSA_ACCEL_ECC_SECP_R1_521) -#define MBEDTLS_ECP_DP_SECP521R1_ENABLED -#define MBEDTLS_PSA_BUILTIN_ECC_SECP_R1_521 1 -#endif /* !MBEDTLS_PSA_ACCEL_ECC_SECP_R1_521 */ -#endif /* PSA_WANT_ECC_SECP_R1_521 */ - -#if defined(PSA_WANT_ECC_SECP_K1_192) -#if !defined(MBEDTLS_PSA_ACCEL_ECC_SECP_K1_192) -#define MBEDTLS_ECP_DP_SECP192K1_ENABLED -#define MBEDTLS_PSA_BUILTIN_ECC_SECP_K1_192 1 -#endif /* !MBEDTLS_PSA_ACCEL_ECC_SECP_K1_192 */ -#endif /* PSA_WANT_ECC_SECP_K1_192 */ - -#if defined(PSA_WANT_ECC_SECP_K1_224) -#if !defined(MBEDTLS_PSA_ACCEL_ECC_SECP_K1_224) -/* - * SECP224K1 is buggy via the PSA API in Mbed TLS - * (https://github.com/Mbed-TLS/mbedtls/issues/3541). - */ -#error "SECP224K1 is buggy via the PSA API in Mbed TLS." -#define MBEDTLS_ECP_DP_SECP224K1_ENABLED -#define MBEDTLS_PSA_BUILTIN_ECC_SECP_K1_224 1 -#endif /* !MBEDTLS_PSA_ACCEL_ECC_SECP_K1_224 */ -#endif /* PSA_WANT_ECC_SECP_K1_224 */ - -#if defined(PSA_WANT_ECC_SECP_K1_256) -#if !defined(MBEDTLS_PSA_ACCEL_ECC_SECP_K1_256) -#define MBEDTLS_ECP_DP_SECP256K1_ENABLED -#define MBEDTLS_PSA_BUILTIN_ECC_SECP_K1_256 1 -#endif /* !MBEDTLS_PSA_ACCEL_ECC_SECP_K1_256 */ -#endif /* PSA_WANT_ECC_SECP_K1_256 */ +/* Require built-in implementations based on PSA requirements */ +/* We need this to have a complete list of requirements + * before we deduce what built-ins are required. */ +#include "psa/crypto_adjust_config_key_pair_types.h" - -/****************************************************************/ -/* Infer PSA requirements from Mbed TLS capabilities */ -/****************************************************************/ +#include "mbedtls/config_adjust_legacy_from_psa.h" #else /* MBEDTLS_PSA_CRYPTO_CONFIG */ -/* - * Ensure PSA_WANT_* defines are setup properly if MBEDTLS_PSA_CRYPTO_CONFIG - * is not defined - */ - -#if defined(MBEDTLS_CCM_C) -#define MBEDTLS_PSA_BUILTIN_ALG_CCM 1 -#define PSA_WANT_ALG_CCM 1 -#endif /* MBEDTLS_CCM_C */ - -#if defined(MBEDTLS_CMAC_C) -#define MBEDTLS_PSA_BUILTIN_ALG_CMAC 1 -#define PSA_WANT_ALG_CMAC 1 -#endif /* MBEDTLS_CMAC_C */ - -#if defined(MBEDTLS_ECDH_C) -#define MBEDTLS_PSA_BUILTIN_ALG_ECDH 1 -#define PSA_WANT_ALG_ECDH 1 -#endif /* MBEDTLS_ECDH_C */ - -#if defined(MBEDTLS_ECDSA_C) -#define MBEDTLS_PSA_BUILTIN_ALG_ECDSA 1 -#define PSA_WANT_ALG_ECDSA 1 -#define PSA_WANT_ALG_ECDSA_ANY 1 - -// Only add in DETERMINISTIC support if ECDSA is also enabled -#if defined(MBEDTLS_ECDSA_DETERMINISTIC) -#define MBEDTLS_PSA_BUILTIN_ALG_DETERMINISTIC_ECDSA 1 -#define PSA_WANT_ALG_DETERMINISTIC_ECDSA 1 -#endif /* MBEDTLS_ECDSA_DETERMINISTIC */ - -#endif /* MBEDTLS_ECDSA_C */ - -#if defined(MBEDTLS_ECP_C) -#define MBEDTLS_PSA_BUILTIN_KEY_TYPE_ECC_KEY_PAIR 1 -#define PSA_WANT_KEY_TYPE_ECC_KEY_PAIR 1 -#define MBEDTLS_PSA_BUILTIN_KEY_TYPE_ECC_PUBLIC_KEY 1 -#define PSA_WANT_KEY_TYPE_ECC_PUBLIC_KEY 1 -#endif /* MBEDTLS_ECP_C */ - -#if defined(MBEDTLS_GCM_C) -#define MBEDTLS_PSA_BUILTIN_ALG_GCM 1 -#define PSA_WANT_ALG_GCM 1 -#endif /* MBEDTLS_GCM_C */ - -#if defined(MBEDTLS_HKDF_C) -#define MBEDTLS_PSA_BUILTIN_ALG_HMAC 1 -#define PSA_WANT_ALG_HMAC 1 -#define MBEDTLS_PSA_BUILTIN_ALG_HKDF 1 -#define PSA_WANT_ALG_HKDF 1 -#endif /* MBEDTLS_HKDF_C */ - -#if defined(MBEDTLS_MD_C) -#define MBEDTLS_PSA_BUILTIN_ALG_HMAC 1 -#define PSA_WANT_ALG_HMAC 1 -#define PSA_WANT_KEY_TYPE_HMAC 1 -#define MBEDTLS_PSA_BUILTIN_ALG_TLS12_PRF 1 -#define PSA_WANT_ALG_TLS12_PRF 1 -#define MBEDTLS_PSA_BUILTIN_ALG_TLS12_PSK_TO_MS 1 -#define PSA_WANT_ALG_TLS12_PSK_TO_MS 1 -#endif /* MBEDTLS_MD_C */ - -#if defined(MBEDTLS_MD2_C) -#define MBEDTLS_PSA_BUILTIN_ALG_MD2 1 -#define PSA_WANT_ALG_MD2 1 -#endif - -#if defined(MBEDTLS_MD4_C) -#define MBEDTLS_PSA_BUILTIN_ALG_MD4 1 -#define PSA_WANT_ALG_MD4 1 -#endif - -#if defined(MBEDTLS_MD5_C) -#define MBEDTLS_PSA_BUILTIN_ALG_MD5 1 -#define PSA_WANT_ALG_MD5 1 -#endif - -#if defined(MBEDTLS_RIPEMD160_C) -#define MBEDTLS_PSA_BUILTIN_ALG_RIPEMD160 1 -#define PSA_WANT_ALG_RIPEMD160 1 -#endif - -#if defined(MBEDTLS_RSA_C) -#if defined(MBEDTLS_PKCS1_V15) -#define MBEDTLS_PSA_BUILTIN_ALG_RSA_PKCS1V15_CRYPT 1 -#define PSA_WANT_ALG_RSA_PKCS1V15_CRYPT 1 -#define MBEDTLS_PSA_BUILTIN_ALG_RSA_PKCS1V15_SIGN 1 -#define PSA_WANT_ALG_RSA_PKCS1V15_SIGN 1 -#define PSA_WANT_ALG_RSA_PKCS1V15_SIGN_RAW 1 -#endif /* MBEDTLS_PKCS1_V15 */ -#if defined(MBEDTLS_PKCS1_V21) -#define MBEDTLS_PSA_BUILTIN_ALG_RSA_OAEP 1 -#define PSA_WANT_ALG_RSA_OAEP 1 -#define MBEDTLS_PSA_BUILTIN_ALG_RSA_PSS 1 -#define PSA_WANT_ALG_RSA_PSS 1 -#endif /* MBEDTLS_PKCS1_V21 */ -#define MBEDTLS_PSA_BUILTIN_KEY_TYPE_RSA_KEY_PAIR 1 -#define PSA_WANT_KEY_TYPE_RSA_KEY_PAIR 1 -#define MBEDTLS_PSA_BUILTIN_KEY_TYPE_RSA_PUBLIC_KEY 1 -#define PSA_WANT_KEY_TYPE_RSA_PUBLIC_KEY 1 -#endif /* MBEDTLS_RSA_C */ - -#if defined(MBEDTLS_SHA1_C) -#define MBEDTLS_PSA_BUILTIN_ALG_SHA_1 1 -#define PSA_WANT_ALG_SHA_1 1 -#endif - -#if defined(MBEDTLS_SHA256_C) -#define MBEDTLS_PSA_BUILTIN_ALG_SHA_224 1 -#define MBEDTLS_PSA_BUILTIN_ALG_SHA_256 1 -#define PSA_WANT_ALG_SHA_224 1 -#define PSA_WANT_ALG_SHA_256 1 -#endif - -#if defined(MBEDTLS_SHA512_C) -#if !defined(MBEDTLS_SHA512_NO_SHA384) -#define MBEDTLS_PSA_BUILTIN_ALG_SHA_384 1 -#define PSA_WANT_ALG_SHA_384 1 -#endif -#define MBEDTLS_PSA_BUILTIN_ALG_SHA_512 1 -#define PSA_WANT_ALG_SHA_512 1 -#endif - -#if defined(MBEDTLS_AES_C) -#define PSA_WANT_KEY_TYPE_AES 1 -#define MBEDTLS_PSA_BUILTIN_KEY_TYPE_AES 1 -#endif - -#if defined(MBEDTLS_ARC4_C) -#define PSA_WANT_KEY_TYPE_ARC4 1 -#define PSA_WANT_ALG_STREAM_CIPHER 1 -#define MBEDTLS_PSA_BUILTIN_KEY_TYPE_ARC4 1 -#define MBEDTLS_PSA_BUILTIN_ALG_STREAM_CIPHER 1 -#endif - -#if defined(MBEDTLS_ARIA_C) -#define PSA_WANT_KEY_TYPE_ARIA 1 -#define MBEDTLS_PSA_BUILTIN_KEY_TYPE_ARIA 1 -#endif - -#if defined(MBEDTLS_CAMELLIA_C) -#define PSA_WANT_KEY_TYPE_CAMELLIA 1 -#define MBEDTLS_PSA_BUILTIN_KEY_TYPE_CAMELLIA 1 -#endif - -#if defined(MBEDTLS_DES_C) -#define PSA_WANT_KEY_TYPE_DES 1 -#define MBEDTLS_PSA_BUILTIN_KEY_TYPE_DES 1 -#endif - -#if defined(MBEDTLS_CHACHA20_C) -#define PSA_WANT_KEY_TYPE_CHACHA20 1 -#define PSA_WANT_ALG_STREAM_CIPHER 1 -#define MBEDTLS_PSA_BUILTIN_KEY_TYPE_CHACHA20 1 -#define MBEDTLS_PSA_BUILTIN_ALG_STREAM_CIPHER 1 -#if defined(MBEDTLS_CHACHAPOLY_C) -#define PSA_WANT_ALG_CHACHA20_POLY1305 1 -#define MBEDTLS_PSA_BUILTIN_ALG_CHACHA20_POLY1305 1 -#endif -#endif - -#if defined(MBEDTLS_CIPHER_MODE_CBC) -#define MBEDTLS_PSA_BUILTIN_ALG_CBC_NO_PADDING 1 -#define PSA_WANT_ALG_CBC_NO_PADDING 1 -#if defined(MBEDTLS_CIPHER_PADDING_PKCS7) -#define MBEDTLS_PSA_BUILTIN_ALG_CBC_PKCS7 1 -#define PSA_WANT_ALG_CBC_PKCS7 1 -#endif -#endif - -#if defined(MBEDTLS_AES_C) || defined(MBEDTLS_DES_C) || \ - defined(MBEDTLS_ARIA_C) || defined(MBEDTLS_CAMELLIA_C) -#define MBEDTLS_PSA_BUILTIN_ALG_ECB_NO_PADDING 1 -#define PSA_WANT_ALG_ECB_NO_PADDING 1 -#endif - -#if defined(MBEDTLS_CIPHER_MODE_CFB) -#define MBEDTLS_PSA_BUILTIN_ALG_CFB 1 -#define PSA_WANT_ALG_CFB 1 -#endif - -#if defined(MBEDTLS_CIPHER_MODE_CTR) -#define MBEDTLS_PSA_BUILTIN_ALG_CTR 1 -#define PSA_WANT_ALG_CTR 1 -#endif - -#if defined(MBEDTLS_CIPHER_MODE_OFB) -#define MBEDTLS_PSA_BUILTIN_ALG_OFB 1 -#define PSA_WANT_ALG_OFB 1 -#endif - -#if defined(MBEDTLS_ECP_DP_BP256R1_ENABLED) -#define MBEDTLS_PSA_BUILTIN_ECC_BRAINPOOL_P_R1_256 1 -#define PSA_WANT_ECC_BRAINPOOL_P_R1_256 1 -#endif - -#if defined(MBEDTLS_ECP_DP_BP384R1_ENABLED) -#define MBEDTLS_PSA_BUILTIN_ECC_BRAINPOOL_P_R1_384 1 -#define PSA_WANT_ECC_BRAINPOOL_P_R1_384 1 -#endif - -#if defined(MBEDTLS_ECP_DP_BP512R1_ENABLED) -#define MBEDTLS_PSA_BUILTIN_ECC_BRAINPOOL_P_R1_512 1 -#define PSA_WANT_ECC_BRAINPOOL_P_R1_512 1 -#endif - -#if defined(MBEDTLS_ECP_DP_CURVE25519_ENABLED) -#define MBEDTLS_PSA_BUILTIN_ECC_MONTGOMERY_255 1 -#define PSA_WANT_ECC_MONTGOMERY_255 1 -#endif - -/* Curve448 is not yet supported via the PSA API (https://github.com/Mbed-TLS/mbedtls/issues/4249) */ -#if 0 && defined(MBEDTLS_ECP_DP_CURVE448_ENABLED) -#define MBEDTLS_PSA_BUILTIN_ECC_MONTGOMERY_448 1 -#define PSA_WANT_ECC_MONTGOMERY_448 1 -#endif - -#if defined(MBEDTLS_ECP_DP_SECP192R1_ENABLED) -#define MBEDTLS_PSA_BUILTIN_ECC_SECP_R1_192 1 -#define PSA_WANT_ECC_SECP_R1_192 1 -#endif - -#if defined(MBEDTLS_ECP_DP_SECP224R1_ENABLED) -#define MBEDTLS_PSA_BUILTIN_ECC_SECP_R1_224 1 -#define PSA_WANT_ECC_SECP_R1_224 1 -#endif - -#if defined(MBEDTLS_ECP_DP_SECP256R1_ENABLED) -#define MBEDTLS_PSA_BUILTIN_ECC_SECP_R1_256 1 -#define PSA_WANT_ECC_SECP_R1_256 1 -#endif - -#if defined(MBEDTLS_ECP_DP_SECP384R1_ENABLED) -#define MBEDTLS_PSA_BUILTIN_ECC_SECP_R1_384 1 -#define PSA_WANT_ECC_SECP_R1_384 1 -#endif - -#if defined(MBEDTLS_ECP_DP_SECP521R1_ENABLED) -#define MBEDTLS_PSA_BUILTIN_ECC_SECP_R1_521 1 -#define PSA_WANT_ECC_SECP_R1_521 1 -#endif - -#if defined(MBEDTLS_ECP_DP_SECP192K1_ENABLED) -#define MBEDTLS_PSA_BUILTIN_ECC_SECP_K1_192 1 -#define PSA_WANT_ECC_SECP_K1_192 1 -#endif +/* Infer PSA requirements from Mbed TLS capabilities */ -/* SECP224K1 is buggy via the PSA API (https://github.com/Mbed-TLS/mbedtls/issues/3541) */ -#if 0 && defined(MBEDTLS_ECP_DP_SECP224K1_ENABLED) -#define MBEDTLS_PSA_BUILTIN_ECC_SECP_K1_224 1 -#define PSA_WANT_ECC_SECP_K1_224 1 -#endif +#include "mbedtls/config_adjust_psa_from_legacy.h" -#if defined(MBEDTLS_ECP_DP_SECP256K1_ENABLED) -#define MBEDTLS_PSA_BUILTIN_ECC_SECP_K1_256 1 -#define PSA_WANT_ECC_SECP_K1_256 1 -#endif +/* Hopefully the file above will have enabled keypair symbols in a consistent + * way, but including this here fixes them if that wasn't the case. */ +#include "psa/crypto_adjust_config_key_pair_types.h" #endif /* MBEDTLS_PSA_CRYPTO_CONFIG */ -/* These features are always enabled. */ -#define PSA_WANT_KEY_TYPE_DERIVE 1 -#define PSA_WANT_KEY_TYPE_RAW_DATA 1 - -#ifdef __cplusplus -} +#if defined(PSA_WANT_ALG_JPAKE) +#define PSA_WANT_ALG_SOME_PAKE 1 #endif +#include "psa/crypto_adjust_auto_enabled.h" + #endif /* MBEDTLS_CONFIG_PSA_H */ diff --git a/vendor/mbedtls/include/mbedtls/constant_time.h b/vendor/mbedtls/include/mbedtls/constant_time.h index 8419c99138..d31bff677e 100644 --- a/vendor/mbedtls/include/mbedtls/constant_time.h +++ b/vendor/mbedtls/include/mbedtls/constant_time.h @@ -1,20 +1,9 @@ /** * Constant-time functions - * + */ +/* * Copyright The Mbed TLS Contributors - * SPDX-License-Identifier: Apache-2.0 - * - * Licensed under the Apache License, Version 2.0 (the "License"); you may - * not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT - * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. + * SPDX-License-Identifier: Apache-2.0 OR GPL-2.0-or-later */ #ifndef MBEDTLS_CONSTANT_TIME_H @@ -22,20 +11,22 @@ #include - /** Constant-time buffer comparison without branches. * * This is equivalent to the standard memcmp function, but is likely to be - * compiled to code using bitwise operation rather than a branch. + * compiled to code using bitwise operations rather than a branch, such that + * the time taken is constant w.r.t. the data pointed to by \p a and \p b, + * and w.r.t. whether \p a and \p b are equal or not. It is not constant-time + * w.r.t. \p n . * * This function can be used to write constant-time code by replacing branches * with bit operations using masks. * - * \param a Pointer to the first buffer. - * \param b Pointer to the second buffer. - * \param n The number of bytes to compare in the buffer. + * \param a Pointer to the first buffer, containing at least \p n bytes. May not be NULL. + * \param b Pointer to the second buffer, containing at least \p n bytes. May not be NULL. + * \param n The number of bytes to compare. * - * \return Zero if the content of the two buffer is the same, + * \return Zero if the contents of the two buffers are the same, * otherwise non-zero. */ int mbedtls_ct_memcmp(const void *a, diff --git a/vendor/mbedtls/include/mbedtls/ctr_drbg.h b/vendor/mbedtls/include/mbedtls/ctr_drbg.h index 1bf427c437..c00756df1b 100644 --- a/vendor/mbedtls/include/mbedtls/ctr_drbg.h +++ b/vendor/mbedtls/include/mbedtls/ctr_drbg.h @@ -16,38 +16,31 @@ * The security strength as defined in NIST SP 800-90A is * 128 bits when AES-128 is used (\c MBEDTLS_CTR_DRBG_USE_128_BIT_KEY enabled) * and 256 bits otherwise, provided that #MBEDTLS_CTR_DRBG_ENTROPY_LEN is - * kept at its default value (and not overridden in config.h) and that the + * kept at its default value (and not overridden in mbedtls_config.h) and that the * DRBG instance is set up with default parameters. * See the documentation of mbedtls_ctr_drbg_seed() for more * information. */ /* * Copyright The Mbed TLS Contributors - * SPDX-License-Identifier: Apache-2.0 - * - * Licensed under the Apache License, Version 2.0 (the "License"); you may - * not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT - * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. + * SPDX-License-Identifier: Apache-2.0 OR GPL-2.0-or-later */ #ifndef MBEDTLS_CTR_DRBG_H #define MBEDTLS_CTR_DRBG_H +#include "mbedtls/private_access.h" -#if !defined(MBEDTLS_CONFIG_FILE) -#include "mbedtls/config.h" +#include "mbedtls/build_info.h" + +/* In case AES_C is defined then it is the primary option for backward + * compatibility purposes. If that's not available, PSA is used instead */ +#if defined(MBEDTLS_AES_C) +#include "mbedtls/aes.h" #else -#include MBEDTLS_CONFIG_FILE +#include "psa/crypto.h" #endif -#include "mbedtls/aes.h" +#include "entropy.h" #if defined(MBEDTLS_THREADING_C) #include "mbedtls/threading.h" @@ -87,7 +80,7 @@ * \name SECTION: Module settings * * The configuration options you can set for this module are in this section. - * Either change them in config.h or define them using the compiler command + * Either change them in mbedtls_config.h or define them using the compiler command * line. * \{ */ @@ -97,17 +90,14 @@ * \brief The amount of entropy used per seed by default, in bytes. */ #if !defined(MBEDTLS_CTR_DRBG_ENTROPY_LEN) -#if defined(MBEDTLS_SHA512_C) && !defined(MBEDTLS_ENTROPY_FORCE_SHA256) -/** This is 48 bytes because the entropy module uses SHA-512 - * (\c MBEDTLS_ENTROPY_FORCE_SHA256 is disabled). +#if defined(MBEDTLS_ENTROPY_SHA512_ACCUMULATOR) +/** This is 48 bytes because the entropy module uses SHA-512. */ #define MBEDTLS_CTR_DRBG_ENTROPY_LEN 48 -#else /* defined(MBEDTLS_SHA512_C) && !defined(MBEDTLS_ENTROPY_FORCE_SHA256) */ +#else /* MBEDTLS_ENTROPY_SHA512_ACCUMULATOR */ -/** This is 32 bytes because the entropy module uses SHA-256 - * (the SHA512 module is disabled or - * \c MBEDTLS_ENTROPY_FORCE_SHA256 is enabled). +/** This is 32 bytes because the entropy module uses SHA-256. */ #if !defined(MBEDTLS_CTR_DRBG_USE_128_BIT_KEY) /** \warning To achieve a 256-bit security strength, you must pass a nonce @@ -115,7 +105,7 @@ */ #endif /* !defined(MBEDTLS_CTR_DRBG_USE_128_BIT_KEY) */ #define MBEDTLS_CTR_DRBG_ENTROPY_LEN 32 -#endif /* defined(MBEDTLS_SHA512_C) && !defined(MBEDTLS_ENTROPY_FORCE_SHA256) */ +#endif /* MBEDTLS_ENTROPY_SHA512_ACCUMULATOR */ #endif /* !defined(MBEDTLS_CTR_DRBG_ENTROPY_LEN) */ #if !defined(MBEDTLS_CTR_DRBG_RESEED_INTERVAL) @@ -167,40 +157,51 @@ extern "C" { #define MBEDTLS_CTR_DRBG_ENTROPY_NONCE_LEN (MBEDTLS_CTR_DRBG_ENTROPY_LEN + 1) / 2 #endif +#if !defined(MBEDTLS_AES_C) +typedef struct mbedtls_ctr_drbg_psa_context { + mbedtls_svc_key_id_t key_id; + psa_cipher_operation_t operation; +} mbedtls_ctr_drbg_psa_context; +#endif + /** * \brief The CTR_DRBG context structure. */ typedef struct mbedtls_ctr_drbg_context { - unsigned char counter[16]; /*!< The counter (V). */ - int reseed_counter; /*!< The reseed counter. - * This is the number of requests that have - * been made since the last (re)seeding, - * minus one. - * Before the initial seeding, this field - * contains the amount of entropy in bytes - * to use as a nonce for the initial seeding, - * or -1 if no nonce length has been explicitly - * set (see mbedtls_ctr_drbg_set_nonce_len()). - */ - int prediction_resistance; /*!< This determines whether prediction - resistance is enabled, that is - whether to systematically reseed before - each random generation. */ - size_t entropy_len; /*!< The amount of entropy grabbed on each - seed or reseed operation, in bytes. */ - int reseed_interval; /*!< The reseed interval. - * This is the maximum number of requests - * that can be made between reseedings. */ - - mbedtls_aes_context aes_ctx; /*!< The AES context. */ + unsigned char MBEDTLS_PRIVATE(counter)[16]; /*!< The counter (V). */ + int MBEDTLS_PRIVATE(reseed_counter); /*!< The reseed counter. + * This is the number of requests that have + * been made since the last (re)seeding, + * minus one. + * Before the initial seeding, this field + * contains the amount of entropy in bytes + * to use as a nonce for the initial seeding, + * or -1 if no nonce length has been explicitly + * set (see mbedtls_ctr_drbg_set_nonce_len()). + */ + int MBEDTLS_PRIVATE(prediction_resistance); /*!< This determines whether prediction + resistance is enabled, that is + whether to systematically reseed before + each random generation. */ + size_t MBEDTLS_PRIVATE(entropy_len); /*!< The amount of entropy grabbed on each + seed or reseed operation, in bytes. */ + int MBEDTLS_PRIVATE(reseed_interval); /*!< The reseed interval. + * This is the maximum number of requests + * that can be made between reseedings. */ + +#if defined(MBEDTLS_AES_C) + mbedtls_aes_context MBEDTLS_PRIVATE(aes_ctx); /*!< The AES context. */ +#else + mbedtls_ctr_drbg_psa_context MBEDTLS_PRIVATE(psa_ctx); /*!< The PSA context. */ +#endif /* * Callbacks (Entropy) */ - int (*f_entropy)(void *, unsigned char *, size_t); + int(*MBEDTLS_PRIVATE(f_entropy))(void *, unsigned char *, size_t); /*!< The entropy callback function. */ - void *p_entropy; /*!< The context for the entropy function. */ + void *MBEDTLS_PRIVATE(p_entropy); /*!< The context for the entropy function. */ #if defined(MBEDTLS_THREADING_C) /* Invariant: the mutex is initialized if and only if f_entropy != NULL. @@ -210,7 +211,7 @@ typedef struct mbedtls_ctr_drbg_context { * Note that this invariant may change without notice. Do not rely on it * and do not access the mutex directly in application code. */ - mbedtls_threading_mutex_t mutex; + mbedtls_threading_mutex_t MBEDTLS_PRIVATE(mutex); #endif } mbedtls_ctr_drbg_context; @@ -465,9 +466,9 @@ int mbedtls_ctr_drbg_reseed(mbedtls_ctr_drbg_context *ctx, * #MBEDTLS_CTR_DRBG_MAX_SEED_INPUT. * \return An error from the underlying AES cipher on failure. */ -int mbedtls_ctr_drbg_update_ret(mbedtls_ctr_drbg_context *ctx, - const unsigned char *additional, - size_t add_len); +int mbedtls_ctr_drbg_update(mbedtls_ctr_drbg_context *ctx, + const unsigned char *additional, + size_t add_len); /** * \brief This function updates a CTR_DRBG instance with additional @@ -531,35 +532,6 @@ int mbedtls_ctr_drbg_random_with_add(void *p_rng, int mbedtls_ctr_drbg_random(void *p_rng, unsigned char *output, size_t output_len); - -#if !defined(MBEDTLS_DEPRECATED_REMOVED) -#if defined(MBEDTLS_DEPRECATED_WARNING) -#define MBEDTLS_DEPRECATED __attribute__((deprecated)) -#else -#define MBEDTLS_DEPRECATED -#endif -/** - * \brief This function updates the state of the CTR_DRBG context. - * - * \deprecated Superseded by mbedtls_ctr_drbg_update_ret() - * in 2.16.0. - * - * \note If \p add_len is greater than - * #MBEDTLS_CTR_DRBG_MAX_SEED_INPUT, only the first - * #MBEDTLS_CTR_DRBG_MAX_SEED_INPUT Bytes are used. - * The remaining Bytes are silently discarded. - * - * \param ctx The CTR_DRBG context. - * \param additional The data to update the state with. - * \param add_len Length of \p additional data. - */ -MBEDTLS_DEPRECATED void mbedtls_ctr_drbg_update( - mbedtls_ctr_drbg_context *ctx, - const unsigned char *additional, - size_t add_len); -#undef MBEDTLS_DEPRECATED -#endif /* !MBEDTLS_DEPRECATED_REMOVED */ - #if defined(MBEDTLS_FS_IO) /** * \brief This function writes a seed file. diff --git a/vendor/mbedtls/include/mbedtls/debug.h b/vendor/mbedtls/include/mbedtls/debug.h index bcc640c611..424ed4b3fd 100644 --- a/vendor/mbedtls/include/mbedtls/debug.h +++ b/vendor/mbedtls/include/mbedtls/debug.h @@ -5,28 +5,12 @@ */ /* * Copyright The Mbed TLS Contributors - * SPDX-License-Identifier: Apache-2.0 - * - * Licensed under the Apache License, Version 2.0 (the "License"); you may - * not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT - * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. + * SPDX-License-Identifier: Apache-2.0 OR GPL-2.0-or-later */ #ifndef MBEDTLS_DEBUG_H #define MBEDTLS_DEBUG_H -#if !defined(MBEDTLS_CONFIG_FILE) -#include "mbedtls/config.h" -#else -#include MBEDTLS_CONFIG_FILE -#endif +#include "mbedtls/build_info.h" #include "mbedtls/ssl.h" @@ -59,9 +43,13 @@ #endif #if defined(MBEDTLS_X509_CRT_PARSE_C) +#if !defined(MBEDTLS_X509_REMOVE_INFO) #define MBEDTLS_SSL_DEBUG_CRT(level, text, crt) \ mbedtls_debug_print_crt(ssl, level, __FILE__, __LINE__, text, crt) -#endif +#else +#define MBEDTLS_SSL_DEBUG_CRT(level, text, crt) do { } while (0) +#endif /* MBEDTLS_X509_REMOVE_INFO */ +#endif /* MBEDTLS_X509_CRT_PARSE_C */ #if defined(MBEDTLS_ECDH_C) #define MBEDTLS_SSL_DEBUG_ECDH(level, ecdh, attr) \ @@ -131,6 +119,15 @@ #endif \ /* (defined(__MINGW32__) && __USE_MINGW_ANSI_STDIO == 0) || (defined(_MSC_VER) && _MSC_VER < 1800) */ +#if !defined(MBEDTLS_PRINTF_MS_TIME) +#include +#if !defined(PRId64) +#define MBEDTLS_PRINTF_MS_TIME MBEDTLS_PRINTF_LONGLONG +#else +#define MBEDTLS_PRINTF_MS_TIME PRId64 +#endif +#endif /* MBEDTLS_PRINTF_MS_TIME */ + #ifdef __cplusplus extern "C" { #endif @@ -152,161 +149,8 @@ extern "C" { */ void mbedtls_debug_set_threshold(int threshold); -/** - * \brief Print a message to the debug output. This function is always used - * through the MBEDTLS_SSL_DEBUG_MSG() macro, which supplies the ssl - * context, file and line number parameters. - * - * \param ssl SSL context - * \param level error level of the debug message - * \param file file the message has occurred in - * \param line line number the message has occurred at - * \param format format specifier, in printf format - * \param ... variables used by the format specifier - * - * \attention This function is intended for INTERNAL usage within the - * library only. - */ -void mbedtls_debug_print_msg(const mbedtls_ssl_context *ssl, int level, - const char *file, int line, - const char *format, ...) MBEDTLS_PRINTF_ATTRIBUTE(5, 6); - -/** - * \brief Print the return value of a function to the debug output. This - * function is always used through the MBEDTLS_SSL_DEBUG_RET() macro, - * which supplies the ssl context, file and line number parameters. - * - * \param ssl SSL context - * \param level error level of the debug message - * \param file file the error has occurred in - * \param line line number the error has occurred in - * \param text the name of the function that returned the error - * \param ret the return code value - * - * \attention This function is intended for INTERNAL usage within the - * library only. - */ -void mbedtls_debug_print_ret(const mbedtls_ssl_context *ssl, int level, - const char *file, int line, - const char *text, int ret); - -/** - * \brief Output a buffer of size len bytes to the debug output. This function - * is always used through the MBEDTLS_SSL_DEBUG_BUF() macro, - * which supplies the ssl context, file and line number parameters. - * - * \param ssl SSL context - * \param level error level of the debug message - * \param file file the error has occurred in - * \param line line number the error has occurred in - * \param text a name or label for the buffer being dumped. Normally the - * variable or buffer name - * \param buf the buffer to be outputted - * \param len length of the buffer - * - * \attention This function is intended for INTERNAL usage within the - * library only. - */ -void mbedtls_debug_print_buf(const mbedtls_ssl_context *ssl, int level, - const char *file, int line, const char *text, - const unsigned char *buf, size_t len); - -#if defined(MBEDTLS_BIGNUM_C) -/** - * \brief Print a MPI variable to the debug output. This function is always - * used through the MBEDTLS_SSL_DEBUG_MPI() macro, which supplies the - * ssl context, file and line number parameters. - * - * \param ssl SSL context - * \param level error level of the debug message - * \param file file the error has occurred in - * \param line line number the error has occurred in - * \param text a name or label for the MPI being output. Normally the - * variable name - * \param X the MPI variable - * - * \attention This function is intended for INTERNAL usage within the - * library only. - */ -void mbedtls_debug_print_mpi(const mbedtls_ssl_context *ssl, int level, - const char *file, int line, - const char *text, const mbedtls_mpi *X); -#endif - -#if defined(MBEDTLS_ECP_C) -/** - * \brief Print an ECP point to the debug output. This function is always - * used through the MBEDTLS_SSL_DEBUG_ECP() macro, which supplies the - * ssl context, file and line number parameters. - * - * \param ssl SSL context - * \param level error level of the debug message - * \param file file the error has occurred in - * \param line line number the error has occurred in - * \param text a name or label for the ECP point being output. Normally the - * variable name - * \param X the ECP point - * - * \attention This function is intended for INTERNAL usage within the - * library only. - */ -void mbedtls_debug_print_ecp(const mbedtls_ssl_context *ssl, int level, - const char *file, int line, - const char *text, const mbedtls_ecp_point *X); -#endif - -#if defined(MBEDTLS_X509_CRT_PARSE_C) -/** - * \brief Print a X.509 certificate structure to the debug output. This - * function is always used through the MBEDTLS_SSL_DEBUG_CRT() macro, - * which supplies the ssl context, file and line number parameters. - * - * \param ssl SSL context - * \param level error level of the debug message - * \param file file the error has occurred in - * \param line line number the error has occurred in - * \param text a name or label for the certificate being output - * \param crt X.509 certificate structure - * - * \attention This function is intended for INTERNAL usage within the - * library only. - */ -void mbedtls_debug_print_crt(const mbedtls_ssl_context *ssl, int level, - const char *file, int line, - const char *text, const mbedtls_x509_crt *crt); -#endif - -#if defined(MBEDTLS_ECDH_C) -typedef enum { - MBEDTLS_DEBUG_ECDH_Q, - MBEDTLS_DEBUG_ECDH_QP, - MBEDTLS_DEBUG_ECDH_Z, -} mbedtls_debug_ecdh_attr; - -/** - * \brief Print a field of the ECDH structure in the SSL context to the debug - * output. This function is always used through the - * MBEDTLS_SSL_DEBUG_ECDH() macro, which supplies the ssl context, file - * and line number parameters. - * - * \param ssl SSL context - * \param level error level of the debug message - * \param file file the error has occurred in - * \param line line number the error has occurred in - * \param ecdh the ECDH context - * \param attr the identifier of the attribute being output - * - * \attention This function is intended for INTERNAL usage within the - * library only. - */ -void mbedtls_debug_printf_ecdh(const mbedtls_ssl_context *ssl, int level, - const char *file, int line, - const mbedtls_ecdh_context *ecdh, - mbedtls_debug_ecdh_attr attr); -#endif - #ifdef __cplusplus } #endif -#endif /* debug.h */ +#endif /* MBEDTLS_DEBUG_H */ diff --git a/vendor/mbedtls/include/mbedtls/des.h b/vendor/mbedtls/include/mbedtls/des.h index f2bc58138e..2b097a13dd 100644 --- a/vendor/mbedtls/include/mbedtls/des.h +++ b/vendor/mbedtls/include/mbedtls/des.h @@ -9,29 +9,14 @@ */ /* * Copyright The Mbed TLS Contributors - * SPDX-License-Identifier: Apache-2.0 - * - * Licensed under the Apache License, Version 2.0 (the "License"); you may - * not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT - * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. + * SPDX-License-Identifier: Apache-2.0 OR GPL-2.0-or-later * */ #ifndef MBEDTLS_DES_H #define MBEDTLS_DES_H +#include "mbedtls/private_access.h" -#if !defined(MBEDTLS_CONFIG_FILE) -#include "mbedtls/config.h" -#else -#include MBEDTLS_CONFIG_FILE -#endif +#include "mbedtls/build_info.h" #include "mbedtls/platform_util.h" #include @@ -43,10 +28,6 @@ /** The data input has an invalid length. */ #define MBEDTLS_ERR_DES_INVALID_INPUT_LENGTH -0x0032 -/* MBEDTLS_ERR_DES_HW_ACCEL_FAILED is deprecated and should not be used. */ -/** DES hardware accelerator failed. */ -#define MBEDTLS_ERR_DES_HW_ACCEL_FAILED -0x0033 - #define MBEDTLS_DES_KEY_SIZE 8 #ifdef __cplusplus @@ -65,7 +46,7 @@ extern "C" { * instead. */ typedef struct mbedtls_des_context { - uint32_t sk[32]; /*!< DES subkeys */ + uint32_t MBEDTLS_PRIVATE(sk)[32]; /*!< DES subkeys */ } mbedtls_des_context; @@ -77,7 +58,7 @@ mbedtls_des_context; * instead. */ typedef struct mbedtls_des3_context { - uint32_t sk[96]; /*!< 3DES subkeys */ + uint32_t MBEDTLS_PRIVATE(sk)[96]; /*!< 3DES subkeys */ } mbedtls_des3_context; diff --git a/vendor/mbedtls/include/mbedtls/dhm.h b/vendor/mbedtls/include/mbedtls/dhm.h index 117af93400..fcba3d2af0 100644 --- a/vendor/mbedtls/include/mbedtls/dhm.h +++ b/vendor/mbedtls/include/mbedtls/dhm.h @@ -45,29 +45,14 @@ */ /* * Copyright The Mbed TLS Contributors - * SPDX-License-Identifier: Apache-2.0 - * - * Licensed under the Apache License, Version 2.0 (the "License"); you may - * not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT - * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. + * SPDX-License-Identifier: Apache-2.0 OR GPL-2.0-or-later */ #ifndef MBEDTLS_DHM_H #define MBEDTLS_DHM_H +#include "mbedtls/private_access.h" -#if !defined(MBEDTLS_CONFIG_FILE) -#include "mbedtls/config.h" -#else -#include MBEDTLS_CONFIG_FILE -#endif +#include "mbedtls/build_info.h" #include "mbedtls/bignum.h" /* @@ -91,14 +76,19 @@ #define MBEDTLS_ERR_DHM_ALLOC_FAILED -0x3400 /** Read or write of file failed. */ #define MBEDTLS_ERR_DHM_FILE_IO_ERROR -0x3480 - -/* MBEDTLS_ERR_DHM_HW_ACCEL_FAILED is deprecated and should not be used. */ -/** DHM hardware accelerator failed. */ -#define MBEDTLS_ERR_DHM_HW_ACCEL_FAILED -0x3500 - /** Setting the modulus and generator failed. */ #define MBEDTLS_ERR_DHM_SET_GROUP_FAILED -0x3580 +/** Which parameter to access in mbedtls_dhm_get_value(). */ +typedef enum { + MBEDTLS_DHM_PARAM_P, /*!< The prime modulus. */ + MBEDTLS_DHM_PARAM_G, /*!< The generator. */ + MBEDTLS_DHM_PARAM_X, /*!< Our secret value. */ + MBEDTLS_DHM_PARAM_GX, /*!< Our public key = \c G^X mod \c P. */ + MBEDTLS_DHM_PARAM_GY, /*!< The public key of the peer = \c G^Y mod \c P. */ + MBEDTLS_DHM_PARAM_K, /*!< The shared secret = \c G^(XY) mod \c P. */ +} mbedtls_dhm_parameter; + #ifdef __cplusplus extern "C" { #endif @@ -109,17 +99,16 @@ extern "C" { * \brief The DHM context structure. */ typedef struct mbedtls_dhm_context { - size_t len; /*!< The size of \p P in Bytes. */ - mbedtls_mpi P; /*!< The prime modulus. */ - mbedtls_mpi G; /*!< The generator. */ - mbedtls_mpi X; /*!< Our secret value. */ - mbedtls_mpi GX; /*!< Our public key = \c G^X mod \c P. */ - mbedtls_mpi GY; /*!< The public key of the peer = \c G^Y mod \c P. */ - mbedtls_mpi K; /*!< The shared secret = \c G^(XY) mod \c P. */ - mbedtls_mpi RP; /*!< The cached value = \c R^2 mod \c P. */ - mbedtls_mpi Vi; /*!< The blinding value. */ - mbedtls_mpi Vf; /*!< The unblinding value. */ - mbedtls_mpi pX; /*!< The previous \c X. */ + mbedtls_mpi MBEDTLS_PRIVATE(P); /*!< The prime modulus. */ + mbedtls_mpi MBEDTLS_PRIVATE(G); /*!< The generator. */ + mbedtls_mpi MBEDTLS_PRIVATE(X); /*!< Our secret value. */ + mbedtls_mpi MBEDTLS_PRIVATE(GX); /*!< Our public key = \c G^X mod \c P. */ + mbedtls_mpi MBEDTLS_PRIVATE(GY); /*!< The public key of the peer = \c G^Y mod \c P. */ + mbedtls_mpi MBEDTLS_PRIVATE(K); /*!< The shared secret = \c G^(XY) mod \c P. */ + mbedtls_mpi MBEDTLS_PRIVATE(RP); /*!< The cached value = \c R^2 mod \c P. */ + mbedtls_mpi MBEDTLS_PRIVATE(Vi); /*!< The blinding value. */ + mbedtls_mpi MBEDTLS_PRIVATE(Vf); /*!< The unblinding value. */ + mbedtls_mpi MBEDTLS_PRIVATE(pX); /*!< The previous \c X. */ } mbedtls_dhm_context; @@ -282,10 +271,10 @@ int mbedtls_dhm_make_public(mbedtls_dhm_context *ctx, int x_size, * \param output_size The size of the destination buffer. This must be at * least the size of \c ctx->len (the size of \c P). * \param olen On exit, holds the actual number of Bytes written. - * \param f_rng The RNG function, for blinding purposes. This may - * b \c NULL if blinding isn't needed. - * \param p_rng The RNG context. This may be \c NULL if \p f_rng - * doesn't need a context argument. + * \param f_rng The RNG function. Must not be \c NULL. Used for + * blinding. + * \param p_rng The RNG context to be passed to \p f_rng. This may be + * \c NULL if \p f_rng doesn't need a context parameter. * * \return \c 0 on success. * \return An \c MBEDTLS_ERR_DHM_XXX error code on failure. @@ -295,6 +284,42 @@ int mbedtls_dhm_calc_secret(mbedtls_dhm_context *ctx, int (*f_rng)(void *, unsigned char *, size_t), void *p_rng); +/** + * \brief This function returns the size of the prime modulus in bits. + * + * \param ctx The DHM context to query. + * + * \return The size of the prime modulus in bits, + * i.e. the number n such that 2^(n-1) <= P < 2^n. + */ +size_t mbedtls_dhm_get_bitlen(const mbedtls_dhm_context *ctx); + +/** + * \brief This function returns the size of the prime modulus in bytes. + * + * \param ctx The DHM context to query. + * + * \return The size of the prime modulus in bytes, + * i.e. the number n such that 2^(8*(n-1)) <= P < 2^(8*n). + */ +size_t mbedtls_dhm_get_len(const mbedtls_dhm_context *ctx); + +/** + * \brief This function copies a parameter of a DHM key. + * + * \param ctx The DHM context to query. + * \param param The parameter to copy. + * \param dest The MPI object to copy the value into. It must be + * initialized. + * + * \return \c 0 on success. + * \return #MBEDTLS_ERR_DHM_BAD_INPUT_DATA if \p param is invalid. + * \return An \c MBEDTLS_ERR_MPI_XXX error code if the copy fails. + */ +int mbedtls_dhm_get_value(const mbedtls_dhm_context *ctx, + mbedtls_dhm_parameter param, + mbedtls_mpi *dest); + /** * \brief This function frees and clears the components * of a DHM context. @@ -396,161 +421,6 @@ int mbedtls_dhm_self_test(int verbose); * */ -#if !defined(MBEDTLS_DEPRECATED_REMOVED) - -/** - * \warning The origin of the primes in RFC 5114 is not documented and - * their use therefore constitutes a security risk! - * - * \deprecated The hex-encoded primes from RFC 5114 are deprecated and are - * likely to be removed in a future version of the library without - * replacement. - */ - -/** - * The hexadecimal presentation of the prime underlying the - * 2048-bit MODP Group with 224-bit Prime Order Subgroup, as defined - * in RFC-5114: Additional Diffie-Hellman Groups for Use with - * IETF Standards. - */ -#define MBEDTLS_DHM_RFC5114_MODP_2048_P \ - MBEDTLS_DEPRECATED_STRING_CONSTANT( \ - "AD107E1E9123A9D0D660FAA79559C51FA20D64E5683B9FD1" \ - "B54B1597B61D0A75E6FA141DF95A56DBAF9A3C407BA1DF15" \ - "EB3D688A309C180E1DE6B85A1274A0A66D3F8152AD6AC212" \ - "9037C9EDEFDA4DF8D91E8FEF55B7394B7AD5B7D0B6C12207" \ - "C9F98D11ED34DBF6C6BA0B2C8BBC27BE6A00E0A0B9C49708" \ - "B3BF8A317091883681286130BC8985DB1602E714415D9330" \ - "278273C7DE31EFDC7310F7121FD5A07415987D9ADC0A486D" \ - "CDF93ACC44328387315D75E198C641A480CD86A1B9E587E8" \ - "BE60E69CC928B2B9C52172E413042E9B23F10B0E16E79763" \ - "C9B53DCF4BA80A29E3FB73C16B8E75B97EF363E2FFA31F71" \ - "CF9DE5384E71B81C0AC4DFFE0C10E64F") - -/** - * The hexadecimal presentation of the chosen generator of the 2048-bit MODP - * Group with 224-bit Prime Order Subgroup, as defined in RFC-5114: - * Additional Diffie-Hellman Groups for Use with IETF Standards. - */ -#define MBEDTLS_DHM_RFC5114_MODP_2048_G \ - MBEDTLS_DEPRECATED_STRING_CONSTANT( \ - "AC4032EF4F2D9AE39DF30B5C8FFDAC506CDEBE7B89998CAF" \ - "74866A08CFE4FFE3A6824A4E10B9A6F0DD921F01A70C4AFA" \ - "AB739D7700C29F52C57DB17C620A8652BE5E9001A8D66AD7" \ - "C17669101999024AF4D027275AC1348BB8A762D0521BC98A" \ - "E247150422EA1ED409939D54DA7460CDB5F6C6B250717CBE" \ - "F180EB34118E98D119529A45D6F834566E3025E316A330EF" \ - "BB77A86F0C1AB15B051AE3D428C8F8ACB70A8137150B8EEB" \ - "10E183EDD19963DDD9E263E4770589EF6AA21E7F5F2FF381" \ - "B539CCE3409D13CD566AFBB48D6C019181E1BCFE94B30269" \ - "EDFE72FE9B6AA4BD7B5A0F1C71CFFF4C19C418E1F6EC0179" \ - "81BC087F2A7065B384B890D3191F2BFA") - -/** - * The hexadecimal presentation of the prime underlying the 2048-bit MODP - * Group, as defined in RFC-3526: More Modular Exponential (MODP) - * Diffie-Hellman groups for Internet Key Exchange (IKE). - * - * \deprecated The hex-encoded primes from RFC 3625 are deprecated and - * superseded by the corresponding macros providing them as - * binary constants. Their hex-encoded constants are likely - * to be removed in a future version of the library. - * - */ -#define MBEDTLS_DHM_RFC3526_MODP_2048_P \ - MBEDTLS_DEPRECATED_STRING_CONSTANT( \ - "FFFFFFFFFFFFFFFFC90FDAA22168C234C4C6628B80DC1CD1" \ - "29024E088A67CC74020BBEA63B139B22514A08798E3404DD" \ - "EF9519B3CD3A431B302B0A6DF25F14374FE1356D6D51C245" \ - "E485B576625E7EC6F44C42E9A637ED6B0BFF5CB6F406B7ED" \ - "EE386BFB5A899FA5AE9F24117C4B1FE649286651ECE45B3D" \ - "C2007CB8A163BF0598DA48361C55D39A69163FA8FD24CF5F" \ - "83655D23DCA3AD961C62F356208552BB9ED529077096966D" \ - "670C354E4ABC9804F1746C08CA18217C32905E462E36CE3B" \ - "E39E772C180E86039B2783A2EC07A28FB5C55DF06F4C52C9" \ - "DE2BCBF6955817183995497CEA956AE515D2261898FA0510" \ - "15728E5A8AACAA68FFFFFFFFFFFFFFFF") - -/** - * The hexadecimal presentation of the chosen generator of the 2048-bit MODP - * Group, as defined in RFC-3526: More Modular Exponential (MODP) - * Diffie-Hellman groups for Internet Key Exchange (IKE). - */ -#define MBEDTLS_DHM_RFC3526_MODP_2048_G \ - MBEDTLS_DEPRECATED_STRING_CONSTANT("02") - -/** - * The hexadecimal presentation of the prime underlying the 3072-bit MODP - * Group, as defined in RFC-3072: More Modular Exponential (MODP) - * Diffie-Hellman groups for Internet Key Exchange (IKE). - */ -#define MBEDTLS_DHM_RFC3526_MODP_3072_P \ - MBEDTLS_DEPRECATED_STRING_CONSTANT( \ - "FFFFFFFFFFFFFFFFC90FDAA22168C234C4C6628B80DC1CD1" \ - "29024E088A67CC74020BBEA63B139B22514A08798E3404DD" \ - "EF9519B3CD3A431B302B0A6DF25F14374FE1356D6D51C245" \ - "E485B576625E7EC6F44C42E9A637ED6B0BFF5CB6F406B7ED" \ - "EE386BFB5A899FA5AE9F24117C4B1FE649286651ECE45B3D" \ - "C2007CB8A163BF0598DA48361C55D39A69163FA8FD24CF5F" \ - "83655D23DCA3AD961C62F356208552BB9ED529077096966D" \ - "670C354E4ABC9804F1746C08CA18217C32905E462E36CE3B" \ - "E39E772C180E86039B2783A2EC07A28FB5C55DF06F4C52C9" \ - "DE2BCBF6955817183995497CEA956AE515D2261898FA0510" \ - "15728E5A8AAAC42DAD33170D04507A33A85521ABDF1CBA64" \ - "ECFB850458DBEF0A8AEA71575D060C7DB3970F85A6E1E4C7" \ - "ABF5AE8CDB0933D71E8C94E04A25619DCEE3D2261AD2EE6B" \ - "F12FFA06D98A0864D87602733EC86A64521F2B18177B200C" \ - "BBE117577A615D6C770988C0BAD946E208E24FA074E5AB31" \ - "43DB5BFCE0FD108E4B82D120A93AD2CAFFFFFFFFFFFFFFFF") - -/** - * The hexadecimal presentation of the chosen generator of the 3072-bit MODP - * Group, as defined in RFC-3526: More Modular Exponential (MODP) - * Diffie-Hellman groups for Internet Key Exchange (IKE). - */ -#define MBEDTLS_DHM_RFC3526_MODP_3072_G \ - MBEDTLS_DEPRECATED_STRING_CONSTANT("02") - -/** - * The hexadecimal presentation of the prime underlying the 4096-bit MODP - * Group, as defined in RFC-3526: More Modular Exponential (MODP) - * Diffie-Hellman groups for Internet Key Exchange (IKE). - */ -#define MBEDTLS_DHM_RFC3526_MODP_4096_P \ - MBEDTLS_DEPRECATED_STRING_CONSTANT( \ - "FFFFFFFFFFFFFFFFC90FDAA22168C234C4C6628B80DC1CD1" \ - "29024E088A67CC74020BBEA63B139B22514A08798E3404DD" \ - "EF9519B3CD3A431B302B0A6DF25F14374FE1356D6D51C245" \ - "E485B576625E7EC6F44C42E9A637ED6B0BFF5CB6F406B7ED" \ - "EE386BFB5A899FA5AE9F24117C4B1FE649286651ECE45B3D" \ - "C2007CB8A163BF0598DA48361C55D39A69163FA8FD24CF5F" \ - "83655D23DCA3AD961C62F356208552BB9ED529077096966D" \ - "670C354E4ABC9804F1746C08CA18217C32905E462E36CE3B" \ - "E39E772C180E86039B2783A2EC07A28FB5C55DF06F4C52C9" \ - "DE2BCBF6955817183995497CEA956AE515D2261898FA0510" \ - "15728E5A8AAAC42DAD33170D04507A33A85521ABDF1CBA64" \ - "ECFB850458DBEF0A8AEA71575D060C7DB3970F85A6E1E4C7" \ - "ABF5AE8CDB0933D71E8C94E04A25619DCEE3D2261AD2EE6B" \ - "F12FFA06D98A0864D87602733EC86A64521F2B18177B200C" \ - "BBE117577A615D6C770988C0BAD946E208E24FA074E5AB31" \ - "43DB5BFCE0FD108E4B82D120A92108011A723C12A787E6D7" \ - "88719A10BDBA5B2699C327186AF4E23C1A946834B6150BDA" \ - "2583E9CA2AD44CE8DBBBC2DB04DE8EF92E8EFC141FBECAA6" \ - "287C59474E6BC05D99B2964FA090C3A2233BA186515BE7ED" \ - "1F612970CEE2D7AFB81BDD762170481CD0069127D5B05AA9" \ - "93B4EA988D8FDDC186FFB7DC90A6C08F4DF435C934063199" \ - "FFFFFFFFFFFFFFFF") - -/** - * The hexadecimal presentation of the chosen generator of the 4096-bit MODP - * Group, as defined in RFC-3526: More Modular Exponential (MODP) - * Diffie-Hellman groups for Internet Key Exchange (IKE). - */ -#define MBEDTLS_DHM_RFC3526_MODP_4096_G \ - MBEDTLS_DEPRECATED_STRING_CONSTANT("02") - -#endif /* MBEDTLS_DEPRECATED_REMOVED */ - /* * Trustworthy DHM parameters in binary form */ diff --git a/vendor/mbedtls/include/mbedtls/ecdh.h b/vendor/mbedtls/include/mbedtls/ecdh.h index aade25a42e..a0909d6b44 100644 --- a/vendor/mbedtls/include/mbedtls/ecdh.h +++ b/vendor/mbedtls/include/mbedtls/ecdh.h @@ -14,32 +14,36 @@ */ /* * Copyright The Mbed TLS Contributors - * SPDX-License-Identifier: Apache-2.0 - * - * Licensed under the Apache License, Version 2.0 (the "License"); you may - * not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT - * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. + * SPDX-License-Identifier: Apache-2.0 OR GPL-2.0-or-later */ #ifndef MBEDTLS_ECDH_H #define MBEDTLS_ECDH_H +#include "mbedtls/private_access.h" -#if !defined(MBEDTLS_CONFIG_FILE) -#include "mbedtls/config.h" -#else -#include MBEDTLS_CONFIG_FILE -#endif +#include "mbedtls/build_info.h" #include "mbedtls/ecp.h" +/* + * Mbed TLS supports two formats for ECDH contexts (#mbedtls_ecdh_context + * defined in `ecdh.h`). For most applications, the choice of format makes + * no difference, since all library functions can work with either format, + * except that the new format is incompatible with MBEDTLS_ECP_RESTARTABLE. + + * The new format used when this option is disabled is smaller + * (56 bytes on a 32-bit platform). In future versions of the library, it + * will support alternative implementations of ECDH operations. + * The new format is incompatible with applications that access + * context fields directly and with restartable ECP operations. + */ + +#if defined(MBEDTLS_ECP_RESTARTABLE) +#define MBEDTLS_ECDH_LEGACY_CONTEXT +#else +#undef MBEDTLS_ECDH_LEGACY_CONTEXT +#endif + #if defined(MBEDTLS_ECDH_VARIANT_EVEREST_ENABLED) #undef MBEDTLS_ECDH_LEGACY_CONTEXT #include "everest/everest.h" @@ -80,13 +84,13 @@ typedef enum { * mbedtls_ecdh_context_mbed. */ typedef struct mbedtls_ecdh_context_mbed { - mbedtls_ecp_group grp; /*!< The elliptic curve used. */ - mbedtls_mpi d; /*!< The private key. */ - mbedtls_ecp_point Q; /*!< The public key. */ - mbedtls_ecp_point Qp; /*!< The value of the public key of the peer. */ - mbedtls_mpi z; /*!< The shared secret. */ + mbedtls_ecp_group MBEDTLS_PRIVATE(grp); /*!< The elliptic curve used. */ + mbedtls_mpi MBEDTLS_PRIVATE(d); /*!< The private key. */ + mbedtls_ecp_point MBEDTLS_PRIVATE(Q); /*!< The public key. */ + mbedtls_ecp_point MBEDTLS_PRIVATE(Qp); /*!< The value of the public key of the peer. */ + mbedtls_mpi MBEDTLS_PRIVATE(z); /*!< The shared secret. */ #if defined(MBEDTLS_ECP_RESTARTABLE) - mbedtls_ecp_restart_ctx rs; /*!< The restart context for EC computations. */ + mbedtls_ecp_restart_ctx MBEDTLS_PRIVATE(rs); /*!< The restart context for EC computations. */ #endif } mbedtls_ecdh_context_mbed; #endif @@ -100,43 +104,56 @@ typedef struct mbedtls_ecdh_context_mbed { */ typedef struct mbedtls_ecdh_context { #if defined(MBEDTLS_ECDH_LEGACY_CONTEXT) - mbedtls_ecp_group grp; /*!< The elliptic curve used. */ - mbedtls_mpi d; /*!< The private key. */ - mbedtls_ecp_point Q; /*!< The public key. */ - mbedtls_ecp_point Qp; /*!< The value of the public key of the peer. */ - mbedtls_mpi z; /*!< The shared secret. */ - int point_format; /*!< The format of point export in TLS messages. */ - mbedtls_ecp_point Vi; /*!< The blinding value. */ - mbedtls_ecp_point Vf; /*!< The unblinding value. */ - mbedtls_mpi _d; /*!< The previous \p d. */ + mbedtls_ecp_group MBEDTLS_PRIVATE(grp); /*!< The elliptic curve used. */ + mbedtls_mpi MBEDTLS_PRIVATE(d); /*!< The private key. */ + mbedtls_ecp_point MBEDTLS_PRIVATE(Q); /*!< The public key. */ + mbedtls_ecp_point MBEDTLS_PRIVATE(Qp); /*!< The value of the public key of the peer. */ + mbedtls_mpi MBEDTLS_PRIVATE(z); /*!< The shared secret. */ + int MBEDTLS_PRIVATE(point_format); /*!< The format of point export in TLS messages. */ + mbedtls_ecp_point MBEDTLS_PRIVATE(Vi); /*!< The blinding value. */ + mbedtls_ecp_point MBEDTLS_PRIVATE(Vf); /*!< The unblinding value. */ + mbedtls_mpi MBEDTLS_PRIVATE(_d); /*!< The previous \p d. */ #if defined(MBEDTLS_ECP_RESTARTABLE) - int restart_enabled; /*!< The flag for restartable mode. */ - mbedtls_ecp_restart_ctx rs; /*!< The restart context for EC computations. */ + int MBEDTLS_PRIVATE(restart_enabled); /*!< The flag for restartable mode. */ + mbedtls_ecp_restart_ctx MBEDTLS_PRIVATE(rs); /*!< The restart context for EC computations. */ #endif /* MBEDTLS_ECP_RESTARTABLE */ #else - uint8_t point_format; /*!< The format of point export in TLS messages - as defined in RFC 4492. */ - mbedtls_ecp_group_id grp_id;/*!< The elliptic curve used. */ - mbedtls_ecdh_variant var; /*!< The ECDH implementation/structure used. */ + uint8_t MBEDTLS_PRIVATE(point_format); /*!< The format of point export in TLS messages + as defined in RFC 4492. */ + mbedtls_ecp_group_id MBEDTLS_PRIVATE(grp_id);/*!< The elliptic curve used. */ + mbedtls_ecdh_variant MBEDTLS_PRIVATE(var); /*!< The ECDH implementation/structure used. */ union { - mbedtls_ecdh_context_mbed mbed_ecdh; + mbedtls_ecdh_context_mbed MBEDTLS_PRIVATE(mbed_ecdh); #if defined(MBEDTLS_ECDH_VARIANT_EVEREST_ENABLED) - mbedtls_ecdh_context_everest everest_ecdh; + mbedtls_ecdh_context_everest MBEDTLS_PRIVATE(everest_ecdh); #endif - } ctx; /*!< Implementation-specific context. The - context in use is specified by the \c var - field. */ + } MBEDTLS_PRIVATE(ctx); /*!< Implementation-specific context. The + context in use is specified by the \c var + field. */ #if defined(MBEDTLS_ECP_RESTARTABLE) - uint8_t restart_enabled; /*!< The flag for restartable mode. Functions of - an alternative implementation not supporting - restartable mode must return - MBEDTLS_ERR_PLATFORM_FEATURE_UNSUPPORTED error - if this flag is set. */ + uint8_t MBEDTLS_PRIVATE(restart_enabled); /*!< The flag for restartable mode. Functions of + an alternative implementation not supporting + restartable mode must return + MBEDTLS_ERR_PLATFORM_FEATURE_UNSUPPORTED error + if this flag is set. */ #endif /* MBEDTLS_ECP_RESTARTABLE */ #endif /* MBEDTLS_ECDH_LEGACY_CONTEXT */ } mbedtls_ecdh_context; +/** + * \brief Return the ECP group for provided context. + * + * \note To access group specific fields, users should use + * `mbedtls_ecp_curve_info_from_grp_id` or + * `mbedtls_ecp_group_load` on the extracted `group_id`. + * + * \param ctx The ECDH context to parse. This must not be \c NULL. + * + * \return The \c mbedtls_ecp_group_id of the context. + */ +mbedtls_ecp_group_id mbedtls_ecdh_get_grp_id(mbedtls_ecdh_context *ctx); + /** * \brief Check whether a given group can be used for ECDH. * @@ -197,10 +214,7 @@ int mbedtls_ecdh_gen_public(mbedtls_ecp_group *grp, mbedtls_mpi *d, mbedtls_ecp_ * This must be initialized. * \param d Our secret exponent (private key). * This must be initialized. - * \param f_rng The RNG function. This may be \c NULL if randomization - * of intermediate results during the ECP computations is - * not needed (discouraged). See the documentation of - * mbedtls_ecp_mul() for more. + * \param f_rng The RNG function to use. This must not be \c NULL. * \param p_rng The RNG context to be passed to \p f_rng. This may be * \c NULL if \p f_rng is \c NULL or doesn't need a * context argument. @@ -403,8 +417,7 @@ int mbedtls_ecdh_read_public(mbedtls_ecdh_context *ctx, * \param buf The buffer to write the generated shared key to. This * must be a writable buffer of size \p blen Bytes. * \param blen The length of the destination buffer \p buf in Bytes. - * \param f_rng The RNG function, for blinding purposes. This may - * b \c NULL if blinding isn't needed. + * \param f_rng The RNG function to use. This must not be \c NULL. * \param p_rng The RNG context. This may be \c NULL if \p f_rng * doesn't need a context argument. * diff --git a/vendor/mbedtls/include/mbedtls/ecdsa.h b/vendor/mbedtls/include/mbedtls/ecdsa.h index b7029d7d56..2ecf349115 100644 --- a/vendor/mbedtls/include/mbedtls/ecdsa.h +++ b/vendor/mbedtls/include/mbedtls/ecdsa.h @@ -12,29 +12,14 @@ */ /* * Copyright The Mbed TLS Contributors - * SPDX-License-Identifier: Apache-2.0 - * - * Licensed under the Apache License, Version 2.0 (the "License"); you may - * not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT - * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. + * SPDX-License-Identifier: Apache-2.0 OR GPL-2.0-or-later */ #ifndef MBEDTLS_ECDSA_H #define MBEDTLS_ECDSA_H +#include "mbedtls/private_access.h" -#if !defined(MBEDTLS_CONFIG_FILE) -#include "mbedtls/config.h" -#else -#include MBEDTLS_CONFIG_FILE -#endif +#include "mbedtls/build_info.h" #include "mbedtls/ecp.h" #include "mbedtls/md.h" @@ -74,6 +59,11 @@ extern "C" { * \warning Performing multiple operations concurrently on the same * ECDSA context is not supported; objects of this type * should not be shared between multiple threads. + * + * \note pk_wrap module assumes that "ecdsa_context" is identical + * to "ecp_keypair" (see for example structure + * "mbedtls_eckey_info" where ECDSA sign/verify functions + * are used also for EC key) */ typedef mbedtls_ecp_keypair mbedtls_ecdsa_context; @@ -106,12 +96,12 @@ typedef struct mbedtls_ecdsa_restart_det mbedtls_ecdsa_restart_det_ctx; * \brief General context for resuming ECDSA operations */ typedef struct { - mbedtls_ecp_restart_ctx ecp; /*!< base context for ECP restart and - shared administrative info */ - mbedtls_ecdsa_restart_ver_ctx *ver; /*!< ecdsa_verify() sub-context */ - mbedtls_ecdsa_restart_sig_ctx *sig; /*!< ecdsa_sign() sub-context */ + mbedtls_ecp_restart_ctx MBEDTLS_PRIVATE(ecp); /*!< base context for ECP restart and + shared administrative info */ + mbedtls_ecdsa_restart_ver_ctx *MBEDTLS_PRIVATE(ver); /*!< ecdsa_verify() sub-context */ + mbedtls_ecdsa_restart_sig_ctx *MBEDTLS_PRIVATE(sig); /*!< ecdsa_sign() sub-context */ #if defined(MBEDTLS_ECDSA_DETERMINISTIC) - mbedtls_ecdsa_restart_det_ctx *det; /*!< ecdsa_sign_det() sub-context */ + mbedtls_ecdsa_restart_det_ctx *MBEDTLS_PRIVATE(det); /*!< ecdsa_sign_det() sub-context */ #endif } mbedtls_ecdsa_restart_ctx; @@ -137,7 +127,7 @@ int mbedtls_ecdsa_can_do(mbedtls_ecp_group_id gid); * previously-hashed message. * * \note The deterministic version implemented in - * mbedtls_ecdsa_sign_det() is usually preferred. + * mbedtls_ecdsa_sign_det_ext() is usually preferred. * * \note If the bitlength of the message hash is larger than the * bitlength of the group order, then the hash is truncated @@ -173,67 +163,6 @@ int mbedtls_ecdsa_sign(mbedtls_ecp_group *grp, mbedtls_mpi *r, mbedtls_mpi *s, int (*f_rng)(void *, unsigned char *, size_t), void *p_rng); #if defined(MBEDTLS_ECDSA_DETERMINISTIC) -#if !defined(MBEDTLS_DEPRECATED_REMOVED) -#if defined(MBEDTLS_DEPRECATED_WARNING) -#define MBEDTLS_DEPRECATED __attribute__((deprecated)) -#else -#define MBEDTLS_DEPRECATED -#endif -/** - * \brief This function computes the ECDSA signature of a - * previously-hashed message, deterministic version. - * - * For more information, see RFC-6979: Deterministic - * Usage of the Digital Signature Algorithm (DSA) and Elliptic - * Curve Digital Signature Algorithm (ECDSA). - * - * \note If the bitlength of the message hash is larger than the - * bitlength of the group order, then the hash is truncated as - * defined in Standards for Efficient Cryptography Group - * (SECG): SEC1 Elliptic Curve Cryptography, section - * 4.1.3, step 5. - * - * \warning Since the output of the internal RNG is always the same for - * the same key and message, this limits the efficiency of - * blinding and leaks information through side channels. For - * secure behavior use mbedtls_ecdsa_sign_det_ext() instead. - * - * (Optimally the blinding is a random value that is different - * on every execution. In this case the blinding is still - * random from the attackers perspective, but is the same on - * each execution. This means that this blinding does not - * prevent attackers from recovering secrets by combining - * several measurement traces, but may prevent some attacks - * that exploit relationships between secret data.) - * - * \see ecp.h - * - * \param grp The context for the elliptic curve to use. - * This must be initialized and have group parameters - * set, for example through mbedtls_ecp_group_load(). - * \param r The MPI context in which to store the first part - * the signature. This must be initialized. - * \param s The MPI context in which to store the second part - * the signature. This must be initialized. - * \param d The private signing key. This must be initialized - * and setup, for example through mbedtls_ecp_gen_privkey(). - * \param buf The hashed content to be signed. This must be a readable - * buffer of length \p blen Bytes. It may be \c NULL if - * \p blen is zero. - * \param blen The length of \p buf in Bytes. - * \param md_alg The hash algorithm used to hash the original data. - * - * \return \c 0 on success. - * \return An \c MBEDTLS_ERR_ECP_XXX or \c MBEDTLS_MPI_XXX - * error code on failure. - */ -int mbedtls_ecdsa_sign_det(mbedtls_ecp_group *grp, mbedtls_mpi *r, - mbedtls_mpi *s, const mbedtls_mpi *d, - const unsigned char *buf, size_t blen, - mbedtls_md_type_t md_alg) MBEDTLS_DEPRECATED; -#undef MBEDTLS_DEPRECATED -#endif /* MBEDTLS_DEPRECATED_REMOVED */ - /** * \brief This function computes the ECDSA signature of a * previously-hashed message, deterministic version. @@ -267,8 +196,8 @@ int mbedtls_ecdsa_sign_det(mbedtls_ecp_group *grp, mbedtls_mpi *r, * \param f_rng_blind The RNG function used for blinding. This must not be * \c NULL. * \param p_rng_blind The RNG context to be passed to \p f_rng_blind. This - * may be \c NULL if \p f_rng_blind doesn't need - * a context parameter. + * may be \c NULL if \p f_rng_blind doesn't need a context + * parameter. * * \return \c 0 on success. * \return An \c MBEDTLS_ERR_ECP_XXX or \c MBEDTLS_MPI_XXX @@ -282,6 +211,135 @@ int mbedtls_ecdsa_sign_det_ext(mbedtls_ecp_group *grp, mbedtls_mpi *r, void *p_rng_blind); #endif /* MBEDTLS_ECDSA_DETERMINISTIC */ +#if !defined(MBEDTLS_ECDSA_SIGN_ALT) +/** + * \brief This function computes the ECDSA signature of a + * previously-hashed message, in a restartable way. + * + * \note The deterministic version implemented in + * mbedtls_ecdsa_sign_det_restartable() is usually + * preferred. + * + * \note This function is like \c mbedtls_ecdsa_sign() but + * it can return early and restart according to the + * limit set with \c mbedtls_ecp_set_max_ops() to + * reduce blocking. + * + * \note If the bitlength of the message hash is larger + * than the bitlength of the group order, then the + * hash is truncated as defined in Standards for + * Efficient Cryptography Group (SECG): SEC1 Elliptic + * Curve Cryptography, section 4.1.3, step 5. + * + * \see ecp.h + * + * \param grp The context for the elliptic curve to use. + * This must be initialized and have group parameters + * set, for example through mbedtls_ecp_group_load(). + * \param r The MPI context in which to store the first part + * the signature. This must be initialized. + * \param s The MPI context in which to store the second part + * the signature. This must be initialized. + * \param d The private signing key. This must be initialized + * and setup, for example through + * mbedtls_ecp_gen_privkey(). + * \param buf The hashed content to be signed. This must be a readable + * buffer of length \p blen Bytes. It may be \c NULL if + * \p blen is zero. + * \param blen The length of \p buf in Bytes. + * \param f_rng The RNG function. This must not be \c NULL. + * \param p_rng The RNG context to be passed to \p f_rng. This may be + * \c NULL if \p f_rng doesn't need a context parameter. + * \param f_rng_blind The RNG function used for blinding. This must not be + * \c NULL. + * \param p_rng_blind The RNG context to be passed to \p f_rng. This may be + * \c NULL if \p f_rng doesn't need a context parameter. + * \param rs_ctx The restart context to use. This may be \c NULL + * to disable restarting. If it is not \c NULL, it + * must point to an initialized restart context. + * + * \return \c 0 on success. + * \return #MBEDTLS_ERR_ECP_IN_PROGRESS if maximum number of + * operations was reached: see \c + * mbedtls_ecp_set_max_ops(). + * \return Another \c MBEDTLS_ERR_ECP_XXX, \c + * MBEDTLS_ERR_MPI_XXX or \c MBEDTLS_ERR_ASN1_XXX + * error code on failure. + */ +int mbedtls_ecdsa_sign_restartable( + mbedtls_ecp_group *grp, + mbedtls_mpi *r, mbedtls_mpi *s, + const mbedtls_mpi *d, + const unsigned char *buf, size_t blen, + int (*f_rng)(void *, unsigned char *, size_t), + void *p_rng, + int (*f_rng_blind)(void *, unsigned char *, size_t), + void *p_rng_blind, + mbedtls_ecdsa_restart_ctx *rs_ctx); + +#endif /* !MBEDTLS_ECDSA_SIGN_ALT */ + +#if defined(MBEDTLS_ECDSA_DETERMINISTIC) + +/** + * \brief This function computes the ECDSA signature of a + * previously-hashed message, in a restartable way. + * + * \note This function is like \c + * mbedtls_ecdsa_sign_det_ext() but it can return + * early and restart according to the limit set with + * \c mbedtls_ecp_set_max_ops() to reduce blocking. + * + * \note If the bitlength of the message hash is larger + * than the bitlength of the group order, then the + * hash is truncated as defined in Standards for + * Efficient Cryptography Group (SECG): SEC1 Elliptic + * Curve Cryptography, section 4.1.3, step 5. + * + * \see ecp.h + * + * \param grp The context for the elliptic curve to use. + * This must be initialized and have group parameters + * set, for example through mbedtls_ecp_group_load(). + * \param r The MPI context in which to store the first part + * the signature. This must be initialized. + * \param s The MPI context in which to store the second part + * the signature. This must be initialized. + * \param d The private signing key. This must be initialized + * and setup, for example through + * mbedtls_ecp_gen_privkey(). + * \param buf The hashed content to be signed. This must be a readable + * buffer of length \p blen Bytes. It may be \c NULL if + * \p blen is zero. + * \param blen The length of \p buf in Bytes. + * \param md_alg The hash algorithm used to hash the original data. + * \param f_rng_blind The RNG function used for blinding. This must not be + * \c NULL. + * \param p_rng_blind The RNG context to be passed to \p f_rng_blind. This may be + * \c NULL if \p f_rng_blind doesn't need a context parameter. + * \param rs_ctx The restart context to use. This may be \c NULL + * to disable restarting. If it is not \c NULL, it + * must point to an initialized restart context. + * + * \return \c 0 on success. + * \return #MBEDTLS_ERR_ECP_IN_PROGRESS if maximum number of + * operations was reached: see \c + * mbedtls_ecp_set_max_ops(). + * \return Another \c MBEDTLS_ERR_ECP_XXX, \c + * MBEDTLS_ERR_MPI_XXX or \c MBEDTLS_ERR_ASN1_XXX + * error code on failure. + */ +int mbedtls_ecdsa_sign_det_restartable( + mbedtls_ecp_group *grp, + mbedtls_mpi *r, mbedtls_mpi *s, + const mbedtls_mpi *d, const unsigned char *buf, size_t blen, + mbedtls_md_type_t md_alg, + int (*f_rng_blind)(void *, unsigned char *, size_t), + void *p_rng_blind, + mbedtls_ecdsa_restart_ctx *rs_ctx); + +#endif /* MBEDTLS_ECDSA_DETERMINISTIC */ + /** * \brief This function verifies the ECDSA signature of a * previously-hashed message. @@ -317,6 +375,51 @@ int mbedtls_ecdsa_verify(mbedtls_ecp_group *grp, const mbedtls_ecp_point *Q, const mbedtls_mpi *r, const mbedtls_mpi *s); +#if !defined(MBEDTLS_ECDSA_VERIFY_ALT) +/** + * \brief This function verifies the ECDSA signature of a + * previously-hashed message, in a restartable manner + * + * \note If the bitlength of the message hash is larger than the + * bitlength of the group order, then the hash is truncated as + * defined in Standards for Efficient Cryptography Group + * (SECG): SEC1 Elliptic Curve Cryptography, section + * 4.1.4, step 3. + * + * \see ecp.h + * + * \param grp The ECP group to use. + * This must be initialized and have group parameters + * set, for example through mbedtls_ecp_group_load(). + * \param buf The hashed content that was signed. This must be a readable + * buffer of length \p blen Bytes. It may be \c NULL if + * \p blen is zero. + * \param blen The length of \p buf in Bytes. + * \param Q The public key to use for verification. This must be + * initialized and setup. + * \param r The first integer of the signature. + * This must be initialized. + * \param s The second integer of the signature. + * This must be initialized. + * \param rs_ctx The restart context to use. This may be \c NULL to disable + * restarting. If it is not \c NULL, it must point to an + * initialized restart context. + * + * \return \c 0 on success. + * \return #MBEDTLS_ERR_ECP_IN_PROGRESS if maximum number of + * operations was reached: see \c mbedtls_ecp_set_max_ops(). + * \return An \c MBEDTLS_ERR_ECP_XXX or \c MBEDTLS_MPI_XXX + * error code on failure. + */ +int mbedtls_ecdsa_verify_restartable(mbedtls_ecp_group *grp, + const unsigned char *buf, size_t blen, + const mbedtls_ecp_point *Q, + const mbedtls_mpi *r, + const mbedtls_mpi *s, + mbedtls_ecdsa_restart_ctx *rs_ctx); + +#endif /* !MBEDTLS_ECDSA_VERIFY_ALT */ + /** * \brief This function computes the ECDSA signature and writes it * to a buffer, serialized as defined in RFC-4492: @@ -352,6 +455,7 @@ int mbedtls_ecdsa_verify(mbedtls_ecp_group *grp, * size of the curve used, plus 9. For example, 73 Bytes if * a 256-bit curve is used. A buffer length of * #MBEDTLS_ECDSA_MAX_LEN is always safe. + * \param sig_size The size of the \p sig buffer in bytes. * \param slen The address at which to store the actual length of * the signature written. Must not be \c NULL. * \param f_rng The RNG function. This must not be \c NULL if @@ -368,7 +472,7 @@ int mbedtls_ecdsa_verify(mbedtls_ecp_group *grp, int mbedtls_ecdsa_write_signature(mbedtls_ecdsa_context *ctx, mbedtls_md_type_t md_alg, const unsigned char *hash, size_t hlen, - unsigned char *sig, size_t *slen, + unsigned char *sig, size_t sig_size, size_t *slen, int (*f_rng)(void *, unsigned char *, size_t), void *p_rng); @@ -394,6 +498,7 @@ int mbedtls_ecdsa_write_signature(mbedtls_ecdsa_context *ctx, * size of the curve used, plus 9. For example, 73 Bytes if * a 256-bit curve is used. A buffer length of * #MBEDTLS_ECDSA_MAX_LEN is always safe. + * \param sig_size The size of the \p sig buffer in bytes. * \param slen The address at which to store the actual length of * the signature written. Must not be \c NULL. * \param f_rng The RNG function. This must not be \c NULL if @@ -414,69 +519,11 @@ int mbedtls_ecdsa_write_signature(mbedtls_ecdsa_context *ctx, int mbedtls_ecdsa_write_signature_restartable(mbedtls_ecdsa_context *ctx, mbedtls_md_type_t md_alg, const unsigned char *hash, size_t hlen, - unsigned char *sig, size_t *slen, + unsigned char *sig, size_t sig_size, size_t *slen, int (*f_rng)(void *, unsigned char *, size_t), void *p_rng, mbedtls_ecdsa_restart_ctx *rs_ctx); -#if defined(MBEDTLS_ECDSA_DETERMINISTIC) -#if !defined(MBEDTLS_DEPRECATED_REMOVED) -#if defined(MBEDTLS_DEPRECATED_WARNING) -#define MBEDTLS_DEPRECATED __attribute__((deprecated)) -#else -#define MBEDTLS_DEPRECATED -#endif -/** - * \brief This function computes an ECDSA signature and writes - * it to a buffer, serialized as defined in RFC-4492: - * Elliptic Curve Cryptography (ECC) Cipher Suites for - * Transport Layer Security (TLS). - * - * The deterministic version is defined in RFC-6979: - * Deterministic Usage of the Digital Signature Algorithm (DSA) - * and Elliptic Curve Digital Signature Algorithm (ECDSA). - * - * \warning It is not thread-safe to use the same context in - * multiple threads. - * - * \note If the bitlength of the message hash is larger than the - * bitlength of the group order, then the hash is truncated as - * defined in Standards for Efficient Cryptography Group - * (SECG): SEC1 Elliptic Curve Cryptography, section - * 4.1.3, step 5. - * - * \see ecp.h - * - * \deprecated Superseded by mbedtls_ecdsa_write_signature() in - * Mbed TLS version 2.0 and later. - * - * \param ctx The ECDSA context to use. This must be initialized - * and have a group and private key bound to it, for example - * via mbedtls_ecdsa_genkey() or mbedtls_ecdsa_from_keypair(). - * \param hash The message hash to be signed. This must be a readable - * buffer of length \p hlen Bytes. - * \param hlen The length of the hash \p hash in Bytes. - * \param sig The buffer to which to write the signature. This must be a - * writable buffer of length at least twice as large as the - * size of the curve used, plus 9. For example, 73 Bytes if - * a 256-bit curve is used. A buffer length of - * #MBEDTLS_ECDSA_MAX_LEN is always safe. - * \param slen The address at which to store the actual length of - * the signature written. Must not be \c NULL. - * \param md_alg The message digest that was used to hash the message. - * - * \return \c 0 on success. - * \return An \c MBEDTLS_ERR_ECP_XXX, \c MBEDTLS_ERR_MPI_XXX or - * \c MBEDTLS_ERR_ASN1_XXX error code on failure. - */ -int mbedtls_ecdsa_write_signature_det(mbedtls_ecdsa_context *ctx, - const unsigned char *hash, size_t hlen, - unsigned char *sig, size_t *slen, - mbedtls_md_type_t md_alg) MBEDTLS_DEPRECATED; -#undef MBEDTLS_DEPRECATED -#endif /* MBEDTLS_DEPRECATED_REMOVED */ -#endif /* MBEDTLS_ECDSA_DETERMINISTIC */ - /** * \brief This function reads and verifies an ECDSA signature. * diff --git a/vendor/mbedtls/include/mbedtls/ecjpake.h b/vendor/mbedtls/include/mbedtls/ecjpake.h index b9928386dc..c2148a2bd1 100644 --- a/vendor/mbedtls/include/mbedtls/ecjpake.h +++ b/vendor/mbedtls/include/mbedtls/ecjpake.h @@ -5,22 +5,11 @@ */ /* * Copyright The Mbed TLS Contributors - * SPDX-License-Identifier: Apache-2.0 - * - * Licensed under the Apache License, Version 2.0 (the "License"); you may - * not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT - * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. + * SPDX-License-Identifier: Apache-2.0 OR GPL-2.0-or-later */ #ifndef MBEDTLS_ECJPAKE_H #define MBEDTLS_ECJPAKE_H +#include "mbedtls/private_access.h" /* * J-PAKE is a password-authenticated key exchange that allows deriving a @@ -38,11 +27,7 @@ * The payloads are serialized in a way suitable for use in TLS, but could * also be use outside TLS. */ -#if !defined(MBEDTLS_CONFIG_FILE) -#include "mbedtls/config.h" -#else -#include MBEDTLS_CONFIG_FILE -#endif +#include "mbedtls/build_info.h" #include "mbedtls/ecp.h" #include "mbedtls/md.h" @@ -57,6 +42,7 @@ extern "C" { typedef enum { MBEDTLS_ECJPAKE_CLIENT = 0, /**< Client */ MBEDTLS_ECJPAKE_SERVER, /**< Server */ + MBEDTLS_ECJPAKE_NONE, /**< Undefined */ } mbedtls_ecjpake_role; #if !defined(MBEDTLS_ECJPAKE_ALT) @@ -72,21 +58,21 @@ typedef enum { * description as a pair C: client name, S: server name */ typedef struct mbedtls_ecjpake_context { - const mbedtls_md_info_t *md_info; /**< Hash to use */ - mbedtls_ecp_group grp; /**< Elliptic curve */ - mbedtls_ecjpake_role role; /**< Are we client or server? */ - int point_format; /**< Format for point export */ + mbedtls_md_type_t MBEDTLS_PRIVATE(md_type); /**< Hash to use */ + mbedtls_ecp_group MBEDTLS_PRIVATE(grp); /**< Elliptic curve */ + mbedtls_ecjpake_role MBEDTLS_PRIVATE(role); /**< Are we client or server? */ + int MBEDTLS_PRIVATE(point_format); /**< Format for point export */ - mbedtls_ecp_point Xm1; /**< My public key 1 C: X1, S: X3 */ - mbedtls_ecp_point Xm2; /**< My public key 2 C: X2, S: X4 */ - mbedtls_ecp_point Xp1; /**< Peer public key 1 C: X3, S: X1 */ - mbedtls_ecp_point Xp2; /**< Peer public key 2 C: X4, S: X2 */ - mbedtls_ecp_point Xp; /**< Peer public key C: Xs, S: Xc */ + mbedtls_ecp_point MBEDTLS_PRIVATE(Xm1); /**< My public key 1 C: X1, S: X3 */ + mbedtls_ecp_point MBEDTLS_PRIVATE(Xm2); /**< My public key 2 C: X2, S: X4 */ + mbedtls_ecp_point MBEDTLS_PRIVATE(Xp1); /**< Peer public key 1 C: X3, S: X1 */ + mbedtls_ecp_point MBEDTLS_PRIVATE(Xp2); /**< Peer public key 2 C: X4, S: X2 */ + mbedtls_ecp_point MBEDTLS_PRIVATE(Xp); /**< Peer public key C: Xs, S: Xc */ - mbedtls_mpi xm1; /**< My private key 1 C: x1, S: x3 */ - mbedtls_mpi xm2; /**< My private key 2 C: x2, S: x4 */ + mbedtls_mpi MBEDTLS_PRIVATE(xm1); /**< My private key 1 C: x1, S: x3 */ + mbedtls_mpi MBEDTLS_PRIVATE(xm2); /**< My private key 2 C: x2, S: x4 */ - mbedtls_mpi s; /**< Pre-shared secret (passphrase) */ + mbedtls_mpi MBEDTLS_PRIVATE(s); /**< Pre-shared secret (passphrase) */ } mbedtls_ecjpake_context; #else /* MBEDTLS_ECJPAKE_ALT */ @@ -115,7 +101,7 @@ void mbedtls_ecjpake_init(mbedtls_ecjpake_context *ctx); * \param curve The identifier of the elliptic curve to use, * for example #MBEDTLS_ECP_DP_SECP256R1. * \param secret The pre-shared secret (passphrase). This must be - * a readable buffer of length \p len Bytes. It need + * a readable not empty buffer of length \p len Bytes. It need * only be valid for the duration of this call. * \param len The length of the pre-shared secret \p secret. * @@ -129,6 +115,21 @@ int mbedtls_ecjpake_setup(mbedtls_ecjpake_context *ctx, const unsigned char *secret, size_t len); +/** + * \brief Set the point format for future reads and writes. + * + * \param ctx The ECJPAKE context to configure. + * \param point_format The point format to use: + * #MBEDTLS_ECP_PF_UNCOMPRESSED (default) + * or #MBEDTLS_ECP_PF_COMPRESSED. + * + * \return \c 0 if successful. + * \return #MBEDTLS_ERR_ECP_BAD_INPUT_DATA if \p point_format + * is invalid. + */ +int mbedtls_ecjpake_set_point_format(mbedtls_ecjpake_context *ctx, + int point_format); + /** * \brief Check if an ECJPAKE context is ready for use. * @@ -245,6 +246,29 @@ int mbedtls_ecjpake_derive_secret(mbedtls_ecjpake_context *ctx, int (*f_rng)(void *, unsigned char *, size_t), void *p_rng); +/** + * \brief Write the shared key material to be passed to a Key + * Derivation Function as described in RFC8236. + * + * \param ctx The ECJPAKE context to use. This must be initialized, + * set up and have performed both round one and two. + * \param buf The buffer to write the derived secret to. This must + * be a writable buffer of length \p len Bytes. + * \param len The length of \p buf in Bytes. + * \param olen The address at which to store the total number of bytes + * written to \p buf. This must not be \c NULL. + * \param f_rng The RNG function to use. This must not be \c NULL. + * \param p_rng The RNG parameter to be passed to \p f_rng. This + * may be \c NULL if \p f_rng doesn't use a context. + * + * \return \c 0 if successful. + * \return A negative error code on failure. + */ +int mbedtls_ecjpake_write_shared_key(mbedtls_ecjpake_context *ctx, + unsigned char *buf, size_t len, size_t *olen, + int (*f_rng)(void *, unsigned char *, size_t), + void *p_rng); + /** * \brief This clears an ECJPAKE context and frees any * embedded data structure. diff --git a/vendor/mbedtls/include/mbedtls/ecp.h b/vendor/mbedtls/include/mbedtls/ecp.h index 4995090f9b..d8f73ae965 100644 --- a/vendor/mbedtls/include/mbedtls/ecp.h +++ b/vendor/mbedtls/include/mbedtls/ecp.h @@ -16,37 +16,18 @@ /* * Copyright The Mbed TLS Contributors - * SPDX-License-Identifier: Apache-2.0 - * - * Licensed under the Apache License, Version 2.0 (the "License"); you may - * not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT - * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. + * SPDX-License-Identifier: Apache-2.0 OR GPL-2.0-or-later */ #ifndef MBEDTLS_ECP_H #define MBEDTLS_ECP_H +#include "mbedtls/private_access.h" -#if !defined(MBEDTLS_CONFIG_FILE) -#include "mbedtls/config.h" -#else -#include MBEDTLS_CONFIG_FILE -#endif +#include "mbedtls/build_info.h" +#include "mbedtls/platform_util.h" #include "mbedtls/bignum.h" -#if (defined(__ARMCC_VERSION) || defined(_MSC_VER)) && \ - !defined(inline) && !defined(__cplusplus) -#define inline __inline -#endif - /* * ECP error codes */ @@ -66,11 +47,6 @@ #define MBEDTLS_ERR_ECP_INVALID_KEY -0x4C80 /** The buffer contains a valid signature followed by more data. */ #define MBEDTLS_ERR_ECP_SIG_LEN_MISMATCH -0x4C00 - -/* MBEDTLS_ERR_ECP_HW_ACCEL_FAILED is deprecated and should not be used. */ -/** The ECP hardware accelerator failed. */ -#define MBEDTLS_ERR_ECP_HW_ACCEL_FAILED -0x4B80 - /** Operation in progress, call again with the same parameters to continue. */ #define MBEDTLS_ERR_ECP_IN_PROGRESS -0x4B00 @@ -111,16 +87,17 @@ extern "C" { * - Add it at the end of this enum, otherwise you'll break the ABI by * changing the numerical value for existing curves. * - Increment MBEDTLS_ECP_DP_MAX below if needed. - * - Update the calculation of MBEDTLS_ECP_MAX_BITS_MIN below. + * - Update the calculation of MBEDTLS_ECP_MAX_BITS below. * - Add the corresponding MBEDTLS_ECP_DP_xxx_ENABLED macro definition to - * config.h. + * mbedtls_config.h. * - List the curve as a dependency of MBEDTLS_ECP_C and * MBEDTLS_ECDSA_C if supported in check_config.h. * - Add the curve to the appropriate curve type macro * MBEDTLS_ECP_yyy_ENABLED above. * - Add the necessary definitions to ecp_curves.c. * - Add the curve to the ecp_supported_curves array in ecp.c. - * - Add the curve to applicable profiles in x509_crt.c if applicable. + * - Add the curve to applicable profiles in x509_crt.c. + * - Add the curve to applicable presets in ssl_tls.c. */ typedef enum { MBEDTLS_ECP_DP_NONE = 0, /*!< Curve not defined. */ @@ -141,10 +118,8 @@ typedef enum { /** * The number of supported curves, plus one for #MBEDTLS_ECP_DP_NONE. - * - * \note Montgomery curves are currently excluded. */ -#define MBEDTLS_ECP_DP_MAX 12 +#define MBEDTLS_ECP_DP_MAX 14 /* * Curve types @@ -157,6 +132,10 @@ typedef enum { /** * Curve information, for use by other modules. + * + * The fields of this structure are part of the public API and can be + * accessed directly by applications. Future versions of the library may + * add extra fields or reorder existing fields. */ typedef struct mbedtls_ecp_curve_info { mbedtls_ecp_group_id grp_id; /*!< An internal identifier. */ @@ -177,46 +156,12 @@ typedef struct mbedtls_ecp_curve_info { * coordinates. */ typedef struct mbedtls_ecp_point { - mbedtls_mpi X; /*!< The X coordinate of the ECP point. */ - mbedtls_mpi Y; /*!< The Y coordinate of the ECP point. */ - mbedtls_mpi Z; /*!< The Z coordinate of the ECP point. */ + mbedtls_mpi MBEDTLS_PRIVATE(X); /*!< The X coordinate of the ECP point. */ + mbedtls_mpi MBEDTLS_PRIVATE(Y); /*!< The Y coordinate of the ECP point. */ + mbedtls_mpi MBEDTLS_PRIVATE(Z); /*!< The Z coordinate of the ECP point. */ } mbedtls_ecp_point; -/* Determine the minimum safe value of MBEDTLS_ECP_MAX_BITS. */ -#if !defined(MBEDTLS_ECP_C) -#define MBEDTLS_ECP_MAX_BITS_MIN 0 -/* Note: the curves must be listed in DECREASING size! */ -#elif defined(MBEDTLS_ECP_DP_SECP521R1_ENABLED) -#define MBEDTLS_ECP_MAX_BITS_MIN 521 -#elif defined(MBEDTLS_ECP_DP_BP512R1_ENABLED) -#define MBEDTLS_ECP_MAX_BITS_MIN 512 -#elif defined(MBEDTLS_ECP_DP_CURVE448_ENABLED) -#define MBEDTLS_ECP_MAX_BITS_MIN 448 -#elif defined(MBEDTLS_ECP_DP_BP384R1_ENABLED) -#define MBEDTLS_ECP_MAX_BITS_MIN 384 -#elif defined(MBEDTLS_ECP_DP_SECP384R1_ENABLED) -#define MBEDTLS_ECP_MAX_BITS_MIN 384 -#elif defined(MBEDTLS_ECP_DP_BP256R1_ENABLED) -#define MBEDTLS_ECP_MAX_BITS_MIN 256 -#elif defined(MBEDTLS_ECP_DP_SECP256K1_ENABLED) -#define MBEDTLS_ECP_MAX_BITS_MIN 256 -#elif defined(MBEDTLS_ECP_DP_SECP256R1_ENABLED) -#define MBEDTLS_ECP_MAX_BITS_MIN 256 -#elif defined(MBEDTLS_ECP_DP_CURVE25519_ENABLED) -#define MBEDTLS_ECP_MAX_BITS_MIN 255 -#elif defined(MBEDTLS_ECP_DP_SECP224K1_ENABLED) -#define MBEDTLS_ECP_MAX_BITS_MIN 225 // n is slightly above 2^224 -#elif defined(MBEDTLS_ECP_DP_SECP224R1_ENABLED) -#define MBEDTLS_ECP_MAX_BITS_MIN 224 -#elif defined(MBEDTLS_ECP_DP_SECP192K1_ENABLED) -#define MBEDTLS_ECP_MAX_BITS_MIN 192 -#elif defined(MBEDTLS_ECP_DP_SECP192R1_ENABLED) -#define MBEDTLS_ECP_MAX_BITS_MIN 192 -#else -#error "MBEDTLS_ECP_C enabled, but no curve?" -#endif - #if !defined(MBEDTLS_ECP_ALT) /* * default Mbed TLS elliptic curve arithmetic implementation @@ -274,10 +219,16 @@ mbedtls_ecp_point; * additions or subtractions. Therefore, it is only an approximative modular * reduction. It must return 0 on success and non-zero on failure. * - * \note Alternative implementations must keep the group IDs distinct. If - * two group structures have the same ID, then they must be - * identical. - * + * \note Alternative implementations of the ECP module must obey the + * following constraints. + * * Group IDs must be distinct: if two group structures have + * the same ID, then they must be identical. + * * The fields \c id, \c P, \c A, \c B, \c G, \c N, + * \c pbits and \c nbits must have the same type and semantics + * as in the built-in implementation. + * They must be available for reading, but direct modification + * of these fields does not need to be supported. + * They do not need to be at the same offset in the structure. */ typedef struct mbedtls_ecp_group { mbedtls_ecp_group_id id; /*!< An internal group identifier. */ @@ -295,14 +246,16 @@ typedef struct mbedtls_ecp_group { size_t nbits; /*!< For Short Weierstrass: The number of bits in \p P. For Montgomery curves: the number of bits in the private keys. */ - unsigned int h; /*!< \internal 1 if the constants are static. */ - int (*modp)(mbedtls_mpi *); /*!< The function for fast pseudo-reduction - mod \p P (see above).*/ - int (*t_pre)(mbedtls_ecp_point *, void *); /*!< Unused. */ - int (*t_post)(mbedtls_ecp_point *, void *); /*!< Unused. */ - void *t_data; /*!< Unused. */ - mbedtls_ecp_point *T; /*!< Pre-computed points for ecp_mul_comb(). */ - size_t T_size; /*!< The number of pre-computed points. */ + /* End of public fields */ + + unsigned int MBEDTLS_PRIVATE(h); /*!< \internal 1 if the constants are static. */ + int(*MBEDTLS_PRIVATE(modp))(mbedtls_mpi *); /*!< The function for fast pseudo-reduction + mod \p P (see above).*/ + int(*MBEDTLS_PRIVATE(t_pre))(mbedtls_ecp_point *, void *); /*!< Unused. */ + int(*MBEDTLS_PRIVATE(t_post))(mbedtls_ecp_point *, void *); /*!< Unused. */ + void *MBEDTLS_PRIVATE(t_data); /*!< Unused. */ + mbedtls_ecp_point *MBEDTLS_PRIVATE(T); /*!< Pre-computed points for ecp_mul_comb(). */ + size_t MBEDTLS_PRIVATE(T_size); /*!< The number of dynamic allocated pre-computed points. */ } mbedtls_ecp_group; @@ -310,32 +263,10 @@ mbedtls_ecp_group; * \name SECTION: Module settings * * The configuration options you can set for this module are in this section. - * Either change them in config.h, or define them using the compiler command line. + * Either change them in mbedtls_config.h, or define them using the compiler command line. * \{ */ -#if defined(MBEDTLS_ECP_MAX_BITS) - -#if MBEDTLS_ECP_MAX_BITS < MBEDTLS_ECP_MAX_BITS_MIN -#error "MBEDTLS_ECP_MAX_BITS is smaller than the largest supported curve" -#endif - -#elif defined(MBEDTLS_ECP_C) -/** - * The maximum size of the groups, that is, of \c N and \c P. - */ -#define MBEDTLS_ECP_MAX_BITS MBEDTLS_ECP_MAX_BITS_MIN - -#else -/* MBEDTLS_ECP_MAX_BITS is not relevant without MBEDTLS_ECP_C, but set it - * to a nonzero value so that code that unconditionally allocates an array - * of a size based on it keeps working if built without ECC support. */ -#define MBEDTLS_ECP_MAX_BITS 1 -#endif - -#define MBEDTLS_ECP_MAX_BYTES ((MBEDTLS_ECP_MAX_BITS + 7) / 8) -#define MBEDTLS_ECP_MAX_PT_LEN (2 * MBEDTLS_ECP_MAX_BYTES + 1) - #if !defined(MBEDTLS_ECP_WINDOW_SIZE) /* * Maximum "window" size used for point multiplication. @@ -362,15 +293,16 @@ mbedtls_ecp_group; #if !defined(MBEDTLS_ECP_FIXED_POINT_OPTIM) /* - * Trade memory for speed on fixed-point multiplication. + * Trade code size for speed on fixed-point multiplication. * * This speeds up repeated multiplication of the generator (that is, the * multiplication in ECDSA signatures, and half of the multiplications in * ECDSA verification and ECDHE) by a factor roughly 3 to 4. * - * The cost is increasing EC peak memory usage by a factor roughly 2. + * For each n-bit Short Weierstrass curve that is enabled, this adds 4n bytes + * of code size if n < 384 and 8n otherwise. * - * Change this value to 0 to reduce peak memory usage. + * Change this value to 0 to reduce code size. */ #define MBEDTLS_ECP_FIXED_POINT_OPTIM 1 /**< Enable fixed-point speed-up. */ #endif /* MBEDTLS_ECP_FIXED_POINT_OPTIM */ @@ -381,6 +313,47 @@ mbedtls_ecp_group; #include "ecp_alt.h" #endif /* MBEDTLS_ECP_ALT */ +/** + * The maximum size of the groups, that is, of \c N and \c P. + */ +#if !defined(MBEDTLS_ECP_LIGHT) +/* Dummy definition to help code that has optional ECP support and + * defines an MBEDTLS_ECP_MAX_BYTES-sized array unconditionally. */ +#define MBEDTLS_ECP_MAX_BITS 1 +/* Note: the curves must be listed in DECREASING size! */ +#elif defined(MBEDTLS_ECP_DP_SECP521R1_ENABLED) +#define MBEDTLS_ECP_MAX_BITS 521 +#elif defined(MBEDTLS_ECP_DP_BP512R1_ENABLED) +#define MBEDTLS_ECP_MAX_BITS 512 +#elif defined(MBEDTLS_ECP_DP_CURVE448_ENABLED) +#define MBEDTLS_ECP_MAX_BITS 448 +#elif defined(MBEDTLS_ECP_DP_BP384R1_ENABLED) +#define MBEDTLS_ECP_MAX_BITS 384 +#elif defined(MBEDTLS_ECP_DP_SECP384R1_ENABLED) +#define MBEDTLS_ECP_MAX_BITS 384 +#elif defined(MBEDTLS_ECP_DP_BP256R1_ENABLED) +#define MBEDTLS_ECP_MAX_BITS 256 +#elif defined(MBEDTLS_ECP_DP_SECP256K1_ENABLED) +#define MBEDTLS_ECP_MAX_BITS 256 +#elif defined(MBEDTLS_ECP_DP_SECP256R1_ENABLED) +#define MBEDTLS_ECP_MAX_BITS 256 +#elif defined(MBEDTLS_ECP_DP_CURVE25519_ENABLED) +#define MBEDTLS_ECP_MAX_BITS 255 +#elif defined(MBEDTLS_ECP_DP_SECP224K1_ENABLED) +#define MBEDTLS_ECP_MAX_BITS 225 // n is slightly above 2^224 +#elif defined(MBEDTLS_ECP_DP_SECP224R1_ENABLED) +#define MBEDTLS_ECP_MAX_BITS 224 +#elif defined(MBEDTLS_ECP_DP_SECP192K1_ENABLED) +#define MBEDTLS_ECP_MAX_BITS 192 +#elif defined(MBEDTLS_ECP_DP_SECP192R1_ENABLED) +#define MBEDTLS_ECP_MAX_BITS 192 +#else /* !MBEDTLS_ECP_LIGHT */ +#error "Missing definition of MBEDTLS_ECP_MAX_BITS" +#endif /* !MBEDTLS_ECP_LIGHT */ + +#define MBEDTLS_ECP_MAX_BYTES ((MBEDTLS_ECP_MAX_BITS + 7) / 8) +#define MBEDTLS_ECP_MAX_PT_LEN (2 * MBEDTLS_ECP_MAX_BYTES + 1) + #if defined(MBEDTLS_ECP_RESTARTABLE) /** @@ -401,10 +374,10 @@ typedef struct mbedtls_ecp_restart_muladd mbedtls_ecp_restart_muladd_ctx; * \brief General context for resuming ECC operations */ typedef struct { - unsigned ops_done; /*!< current ops count */ - unsigned depth; /*!< call depth (0 = top-level) */ - mbedtls_ecp_restart_mul_ctx *rsm; /*!< ecp_mul_comb() sub-context */ - mbedtls_ecp_restart_muladd_ctx *ma; /*!< ecp_muladd() sub-context */ + unsigned MBEDTLS_PRIVATE(ops_done); /*!< current ops count */ + unsigned MBEDTLS_PRIVATE(depth); /*!< call depth (0 = top-level) */ + mbedtls_ecp_restart_mul_ctx *MBEDTLS_PRIVATE(rsm); /*!< ecp_mul_comb() sub-context */ + mbedtls_ecp_restart_muladd_ctx *MBEDTLS_PRIVATE(ma); /*!< ecp_muladd() sub-context */ } mbedtls_ecp_restart_ctx; /* @@ -453,17 +426,28 @@ typedef void mbedtls_ecp_restart_ctx; * ::mbedtls_ecdsa_context structure. */ typedef struct mbedtls_ecp_keypair { - mbedtls_ecp_group grp; /*!< Elliptic curve and base point */ - mbedtls_mpi d; /*!< our secret value */ - mbedtls_ecp_point Q; /*!< our public value */ + mbedtls_ecp_group MBEDTLS_PRIVATE(grp); /*!< Elliptic curve and base point */ + mbedtls_mpi MBEDTLS_PRIVATE(d); /*!< our secret value */ + mbedtls_ecp_point MBEDTLS_PRIVATE(Q); /*!< our public value */ } mbedtls_ecp_keypair; -/* - * Point formats, from RFC 4492's enum ECPointFormat +/** + * The uncompressed point format for Short Weierstrass curves + * (MBEDTLS_ECP_DP_SECP_XXX and MBEDTLS_ECP_DP_BP_XXX). */ -#define MBEDTLS_ECP_PF_UNCOMPRESSED 0 /**< Uncompressed point format. */ -#define MBEDTLS_ECP_PF_COMPRESSED 1 /**< Compressed point format. */ +#define MBEDTLS_ECP_PF_UNCOMPRESSED 0 +/** + * The compressed point format for Short Weierstrass curves + * (MBEDTLS_ECP_DP_SECP_XXX and MBEDTLS_ECP_DP_BP_XXX). + * + * \warning While this format is supported for all concerned curves for + * writing, when it comes to parsing, it is not supported for all + * curves. Specifically, parsing compressed points on + * MBEDTLS_ECP_DP_SECP224R1 and MBEDTLS_ECP_DP_SECP224K1 is not + * supported. + */ +#define MBEDTLS_ECP_PF_COMPRESSED 1 /* * Some other constants from RFC 4492 @@ -501,6 +485,12 @@ mbedtls_ecp_keypair; * only enabled for specific sides and key exchanges * (currently only for clients and ECDHE-ECDSA). * + * \warning Using the PSA interruptible interfaces with keys in local + * storage and no accelerator driver will also call this + * function to set the values specified via those interfaces, + * overwriting values previously set. Care should be taken if + * mixing these two interfaces. + * * \param max_ops Maximum number of basic operations done in a row. * Default: 0 (unlimited). * Lower (non-zero) values mean ECC functions will block for @@ -792,6 +782,9 @@ int mbedtls_ecp_point_write_binary(const mbedtls_ecp_group *grp, * belongs to the given group, see mbedtls_ecp_check_pubkey() * for that. * + * \note For compressed points, see #MBEDTLS_ECP_PF_COMPRESSED for + * limitations. + * * \param grp The group to which the point should belong. * This must be initialized and have group parameters * set, for example through mbedtls_ecp_group_load(). @@ -951,15 +944,8 @@ int mbedtls_ecp_tls_write_group(const mbedtls_ecp_group *grp, * \note To prevent timing attacks, this function * executes the exact same sequence of base-field * operations for any valid \p m. It avoids any if-branch or - * array index depending on the value of \p m. - * - * \note If \p f_rng is not NULL, it is used to randomize - * intermediate results to prevent potential timing attacks - * targeting these results. We recommend always providing - * a non-NULL \p f_rng. The overhead is negligible. - * Note: unless #MBEDTLS_ECP_NO_INTERNAL_RNG is defined, when - * \p f_rng is NULL, an internal RNG (seeded from the value - * of \p m) will be used instead. + * array index depending on the value of \p m. It also uses + * \p f_rng to randomize some intermediate results. * * \param grp The ECP group to use. * This must be initialized and have group parameters @@ -968,9 +954,9 @@ int mbedtls_ecp_tls_write_group(const mbedtls_ecp_group *grp, * This must be initialized. * \param m The integer by which to multiply. This must be initialized. * \param P The point to multiply. This must be initialized. - * \param f_rng The RNG function. This may be \c NULL if randomization - * of intermediate results isn't desired (discouraged). - * \param p_rng The RNG context to be passed to \p p_rng. + * \param f_rng The RNG function. This must not be \c NULL. + * \param p_rng The RNG context to be passed to \p f_rng. This may be \c + * NULL if \p f_rng doesn't need a context. * * \return \c 0 on success. * \return #MBEDTLS_ERR_ECP_INVALID_KEY if \p m is not a valid private @@ -999,9 +985,9 @@ int mbedtls_ecp_mul(mbedtls_ecp_group *grp, mbedtls_ecp_point *R, * This must be initialized. * \param m The integer by which to multiply. This must be initialized. * \param P The point to multiply. This must be initialized. - * \param f_rng The RNG function. This may be \c NULL if randomization - * of intermediate results isn't desired (discouraged). - * \param p_rng The RNG context to be passed to \p p_rng. + * \param f_rng The RNG function. This must not be \c NULL. + * \param p_rng The RNG context to be passed to \p f_rng. This may be \c + * NULL if \p f_rng doesn't need a context. * \param rs_ctx The restart context (NULL disables restart). * * \return \c 0 on success. @@ -1035,7 +1021,7 @@ int mbedtls_ecp_mul_restartable(mbedtls_ecp_group *grp, mbedtls_ecp_point *R, */ static inline int mbedtls_ecp_group_a_is_minus_3(const mbedtls_ecp_group *grp) { - return grp->A.p == NULL; + return grp->A.MBEDTLS_PRIVATE(p) == NULL; } /** @@ -1274,9 +1260,56 @@ int mbedtls_ecp_gen_key(mbedtls_ecp_group_id grp_id, mbedtls_ecp_keypair *key, int (*f_rng)(void *, unsigned char *, size_t), void *p_rng); +/** \brief Set the public key in a key pair object. + * + * \note This function does not check that the point actually + * belongs to the given group. Call mbedtls_ecp_check_pubkey() + * on \p Q before calling this function to check that. + * + * \note This function does not check that the public key matches + * the private key that is already in \p key, if any. + * To check the consistency of the resulting key pair object, + * call mbedtls_ecp_check_pub_priv() after setting both + * the public key and the private key. + * + * \param grp_id The ECP group identifier. + * \param key The key pair object. It must be initialized. + * If its group has already been set, it must match \p grp_id. + * If its group has not been set, it will be set to \p grp_id. + * If the public key has already been set, it is overwritten. + * \param Q The public key to copy. This must be a point on the + * curve indicated by \p grp_id. + * + * \return \c 0 on success. + * \return #MBEDTLS_ERR_ECP_BAD_INPUT_DATA if \p key does not + * match \p grp_id. + * \return #MBEDTLS_ERR_ECP_FEATURE_UNAVAILABLE if the operation for + * the group is not implemented. + * \return #MBEDTLS_ERR_MPI_ALLOC_FAILED on memory-allocation failure. + * \return Another negative error code on other kinds of failure. + */ +int mbedtls_ecp_set_public_key(mbedtls_ecp_group_id grp_id, + mbedtls_ecp_keypair *key, + const mbedtls_ecp_point *Q); + /** * \brief This function reads an elliptic curve private key. * + * \note This function does not set the public key in the + * key pair object. Without a public key, the key pair object + * cannot be used with operations that require the public key. + * Call mbedtls_ecp_keypair_calc_public() to set the public + * key from the private key. Alternatively, you can call + * mbedtls_ecp_set_public_key() to set the public key part, + * and then optionally mbedtls_ecp_check_pub_priv() to check + * that the private and public parts are consistent. + * + * \note If a public key has already been set in the key pair + * object, this function does not check that it is consistent + * with the private key. Call mbedtls_ecp_check_pub_priv() + * after setting both the public key and the private key + * to make that check. + * * \param grp_id The ECP group identifier. * \param key The destination key. * \param buf The buffer containing the binary representation of the @@ -1295,24 +1328,106 @@ int mbedtls_ecp_gen_key(mbedtls_ecp_group_id grp_id, mbedtls_ecp_keypair *key, int mbedtls_ecp_read_key(mbedtls_ecp_group_id grp_id, mbedtls_ecp_keypair *key, const unsigned char *buf, size_t buflen); +#if !defined(MBEDTLS_DEPRECATED_REMOVED) /** * \brief This function exports an elliptic curve private key. * + * \deprecated Note that although this function accepts an output + * buffer that is smaller or larger than the key, most key + * import interfaces require the output to have exactly + * key's nominal length. It is generally simplest to + * pass the key's nominal length as \c buflen, after + * checking that the output buffer is large enough. + * See the description of the \p buflen parameter for + * how to calculate the nominal length. + * To avoid this difficulty, use mbedtls_ecp_write_key_ext() + * instead. + * mbedtls_ecp_write_key() is deprecated and will be + * removed in a future version of the library. + * + * \note If the private key was not set in \p key, + * the output is unspecified. Future versions + * may return an error in that case. + * * \param key The private key. * \param buf The output buffer for containing the binary representation - * of the key. (Big endian integer for Weierstrass curves, byte - * string for Montgomery curves.) + * of the key. + * For Weierstrass curves, this is the big-endian + * representation, padded with null bytes at the beginning + * to reach \p buflen bytes. + * For Montgomery curves, this is the standard byte string + * representation (which is little-endian), padded with + * null bytes at the end to reach \p buflen bytes. + * \param buflen The total length of the buffer in bytes. + * The length of the output is + * (`grp->nbits` + 7) / 8 bytes + * where `grp->nbits` is the private key size in bits. + * For Weierstrass keys, if the output buffer is smaller, + * leading zeros are trimmed to fit if possible. For + * Montgomery keys, the output buffer must always be large + * enough for the nominal length. + * + * \return \c 0 on success. + * \return #MBEDTLS_ERR_ECP_BUFFER_TOO_SMALL or + * #MBEDTLS_ERR_MPI_BUFFER_TOO_SMALL if the \p key + * representation is larger than the available space in \p buf. + * \return Another negative error code on different kinds of failure. + */ +int MBEDTLS_DEPRECATED mbedtls_ecp_write_key(mbedtls_ecp_keypair *key, + unsigned char *buf, size_t buflen); +#endif /* MBEDTLS_DEPRECATED_REMOVED */ + +/** + * \brief This function exports an elliptic curve private key. + * + * \param key The private key. + * \param olen On success, the length of the private key. + * This is always (`grp->nbits` + 7) / 8 bytes + * where `grp->nbits` is the private key size in bits. + * \param buf The output buffer for containing the binary representation + * of the key. * \param buflen The total length of the buffer in bytes. + * #MBEDTLS_ECP_MAX_BYTES is always sufficient. * * \return \c 0 on success. * \return #MBEDTLS_ERR_ECP_BUFFER_TOO_SMALL if the \p key - representation is larger than the available space in \p buf. - * \return #MBEDTLS_ERR_ECP_FEATURE_UNAVAILABLE if the operation for - * the group is not implemented. + * representation is larger than the available space in \p buf. + * \return #MBEDTLS_ERR_ECP_BAD_INPUT_DATA if no private key is + * set in \p key. * \return Another negative error code on different kinds of failure. */ -int mbedtls_ecp_write_key(mbedtls_ecp_keypair *key, - unsigned char *buf, size_t buflen); +int mbedtls_ecp_write_key_ext(const mbedtls_ecp_keypair *key, + size_t *olen, unsigned char *buf, size_t buflen); + +/** + * \brief This function exports an elliptic curve public key. + * + * \note If the public key was not set in \p key, + * the output is unspecified. Future versions + * may return an error in that case. + * + * \param key The public key. + * \param format The point format. This must be either + * #MBEDTLS_ECP_PF_COMPRESSED or #MBEDTLS_ECP_PF_UNCOMPRESSED. + * (For groups without these formats, this parameter is + * ignored. But it still has to be either of the above + * values.) + * \param olen The address at which to store the length of + * the output in Bytes. This must not be \c NULL. + * \param buf The output buffer. This must be a writable buffer + * of length \p buflen Bytes. + * \param buflen The length of the output buffer \p buf in Bytes. + * + * \return \c 0 on success. + * \return #MBEDTLS_ERR_ECP_BUFFER_TOO_SMALL if the output buffer + * is too small to hold the point. + * \return #MBEDTLS_ERR_ECP_FEATURE_UNAVAILABLE if the point format + * or the export for the given group is not implemented. + * \return Another negative error code on other kinds of failure. + */ +int mbedtls_ecp_write_public_key(const mbedtls_ecp_keypair *key, + int format, size_t *olen, + unsigned char *buf, size_t buflen); /** * \brief This function checks that the keypair objects @@ -1325,14 +1440,74 @@ int mbedtls_ecp_write_key(mbedtls_ecp_keypair *key, * part is ignored. * \param prv The keypair structure holding the full keypair. * This must be initialized. + * \param f_rng The RNG function. This must not be \c NULL. + * \param p_rng The RNG context to be passed to \p f_rng. This may be \c + * NULL if \p f_rng doesn't need a context. * * \return \c 0 on success, meaning that the keys are valid and match. * \return #MBEDTLS_ERR_ECP_BAD_INPUT_DATA if the keys are invalid or do not match. * \return An \c MBEDTLS_ERR_ECP_XXX or an \c MBEDTLS_ERR_MPI_XXX * error code on calculation failure. */ -int mbedtls_ecp_check_pub_priv(const mbedtls_ecp_keypair *pub, - const mbedtls_ecp_keypair *prv); +int mbedtls_ecp_check_pub_priv( + const mbedtls_ecp_keypair *pub, const mbedtls_ecp_keypair *prv, + int (*f_rng)(void *, unsigned char *, size_t), void *p_rng); + +/** \brief Calculate the public key from a private key in a key pair. + * + * \param key A keypair structure. It must have a private key set. + * If the public key is set, it will be overwritten. + * \param f_rng The RNG function. This must not be \c NULL. + * \param p_rng The RNG context to be passed to \p f_rng. This may be \c + * NULL if \p f_rng doesn't need a context. + * + * \return \c 0 on success. The key pair object can be used for + * operations that require the public key. + * \return An \c MBEDTLS_ERR_ECP_XXX or an \c MBEDTLS_ERR_MPI_XXX + * error code on calculation failure. + */ +int mbedtls_ecp_keypair_calc_public( + mbedtls_ecp_keypair *key, + int (*f_rng)(void *, unsigned char *, size_t), void *p_rng); + +/** \brief Query the group that a key pair belongs to. + * + * \param key The key pair to query. + * + * \return The group ID for the group registered in the key pair + * object. + * This is \c MBEDTLS_ECP_DP_NONE if no group has been set + * in the key pair object. + */ +mbedtls_ecp_group_id mbedtls_ecp_keypair_get_group_id( + const mbedtls_ecp_keypair *key); + +/** + * \brief This function exports generic key-pair parameters. + * + * Each of the output parameters can be a null pointer + * if you do not need that parameter. + * + * \note If the private key or the public key was not set in \p key, + * the corresponding output is unspecified. Future versions + * may return an error in that case. + * + * \param key The key pair to export from. + * \param grp Slot for exported ECP group. + * It must either be null or point to an initialized ECP group. + * \param d Slot for the exported secret value. + * It must either be null or point to an initialized mpi. + * \param Q Slot for the exported public value. + * It must either be null or point to an initialized ECP point. + * + * \return \c 0 on success, + * \return #MBEDTLS_ERR_MPI_ALLOC_FAILED on memory-allocation failure. + * \return #MBEDTLS_ERR_ECP_FEATURE_UNAVAILABLE if key id doesn't + * correspond to a known group. + * \return Another negative error code on other kinds of failure. + */ +int mbedtls_ecp_export(const mbedtls_ecp_keypair *key, mbedtls_ecp_group *grp, + mbedtls_mpi *d, mbedtls_ecp_point *Q); #if defined(MBEDTLS_SELF_TEST) diff --git a/vendor/mbedtls/include/mbedtls/entropy.h b/vendor/mbedtls/include/mbedtls/entropy.h index 4075d2ae60..20fd6872b8 100644 --- a/vendor/mbedtls/include/mbedtls/entropy.h +++ b/vendor/mbedtls/include/mbedtls/entropy.h @@ -5,38 +5,27 @@ */ /* * Copyright The Mbed TLS Contributors - * SPDX-License-Identifier: Apache-2.0 - * - * Licensed under the Apache License, Version 2.0 (the "License"); you may - * not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT - * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. + * SPDX-License-Identifier: Apache-2.0 OR GPL-2.0-or-later */ #ifndef MBEDTLS_ENTROPY_H #define MBEDTLS_ENTROPY_H +#include "mbedtls/private_access.h" -#if !defined(MBEDTLS_CONFIG_FILE) -#include "mbedtls/config.h" -#else -#include MBEDTLS_CONFIG_FILE -#endif +#include "mbedtls/build_info.h" #include -#if defined(MBEDTLS_SHA512_C) && !defined(MBEDTLS_ENTROPY_FORCE_SHA256) -#include "mbedtls/sha512.h" +#include "md.h" + +#if defined(MBEDTLS_MD_CAN_SHA512) && !defined(MBEDTLS_ENTROPY_FORCE_SHA256) #define MBEDTLS_ENTROPY_SHA512_ACCUMULATOR +#define MBEDTLS_ENTROPY_MD MBEDTLS_MD_SHA512 +#define MBEDTLS_ENTROPY_BLOCK_SIZE 64 /**< Block size of entropy accumulator (SHA-512) */ #else -#if defined(MBEDTLS_SHA256_C) +#if defined(MBEDTLS_MD_CAN_SHA256) #define MBEDTLS_ENTROPY_SHA256_ACCUMULATOR -#include "mbedtls/sha256.h" +#define MBEDTLS_ENTROPY_MD MBEDTLS_MD_SHA256 +#define MBEDTLS_ENTROPY_BLOCK_SIZE 32 /**< Block size of entropy accumulator (SHA-256) */ #endif #endif @@ -44,9 +33,6 @@ #include "mbedtls/threading.h" #endif -#if defined(MBEDTLS_HAVEGE_C) -#include "mbedtls/havege.h" -#endif /** Critical entropy source failure. */ #define MBEDTLS_ERR_ENTROPY_SOURCE_FAILED -0x003C @@ -63,7 +49,7 @@ * \name SECTION: Module settings * * The configuration options you can set for this module are in this section. - * Either change them in config.h or define them on the compiler command line. + * Either change them in mbedtls_config.h or define them on the compiler command line. * \{ */ @@ -77,12 +63,6 @@ /** \} name SECTION: Module settings */ -#if defined(MBEDTLS_ENTROPY_SHA512_ACCUMULATOR) -#define MBEDTLS_ENTROPY_BLOCK_SIZE 64 /**< Block size of entropy accumulator (SHA-512) */ -#else -#define MBEDTLS_ENTROPY_BLOCK_SIZE 32 /**< Block size of entropy accumulator (SHA-256) */ -#endif - #define MBEDTLS_ENTROPY_MAX_SEED_SIZE 1024 /**< Maximum size of seed we read from seed file */ #define MBEDTLS_ENTROPY_SOURCE_MANUAL MBEDTLS_ENTROPY_MAX_SOURCES @@ -111,11 +91,11 @@ typedef int (*mbedtls_entropy_f_source_ptr)(void *data, unsigned char *output, s * \brief Entropy source state */ typedef struct mbedtls_entropy_source_state { - mbedtls_entropy_f_source_ptr f_source; /**< The entropy source callback */ - void *p_source; /**< The callback data pointer */ - size_t size; /**< Amount received in bytes */ - size_t threshold; /**< Minimum bytes required before release */ - int strong; /**< Is the source strong? */ + mbedtls_entropy_f_source_ptr MBEDTLS_PRIVATE(f_source); /**< The entropy source callback */ + void *MBEDTLS_PRIVATE(p_source); /**< The callback data pointer */ + size_t MBEDTLS_PRIVATE(size); /**< Amount received in bytes */ + size_t MBEDTLS_PRIVATE(threshold); /**< Minimum bytes required before release */ + int MBEDTLS_PRIVATE(strong); /**< Is the source strong? */ } mbedtls_entropy_source_state; @@ -123,28 +103,29 @@ mbedtls_entropy_source_state; * \brief Entropy context structure */ typedef struct mbedtls_entropy_context { - int accumulator_started; /* 0 after init. - * 1 after the first update. - * -1 after free. */ -#if defined(MBEDTLS_ENTROPY_SHA512_ACCUMULATOR) - mbedtls_sha512_context accumulator; -#elif defined(MBEDTLS_ENTROPY_SHA256_ACCUMULATOR) - mbedtls_sha256_context accumulator; -#endif - int source_count; /* Number of entries used in source. */ - mbedtls_entropy_source_state source[MBEDTLS_ENTROPY_MAX_SOURCES]; -#if defined(MBEDTLS_HAVEGE_C) - mbedtls_havege_state havege_data; -#endif + mbedtls_md_context_t MBEDTLS_PRIVATE(accumulator); + int MBEDTLS_PRIVATE(accumulator_started); /* 0 after init. + * 1 after the first update. + * -1 after free. */ + int MBEDTLS_PRIVATE(source_count); /* Number of entries used in source. */ + mbedtls_entropy_source_state MBEDTLS_PRIVATE(source)[MBEDTLS_ENTROPY_MAX_SOURCES]; #if defined(MBEDTLS_THREADING_C) - mbedtls_threading_mutex_t mutex; /*!< mutex */ + mbedtls_threading_mutex_t MBEDTLS_PRIVATE(mutex); /*!< mutex */ #endif #if defined(MBEDTLS_ENTROPY_NV_SEED) - int initial_entropy_run; + int MBEDTLS_PRIVATE(initial_entropy_run); #endif } mbedtls_entropy_context; +#if !defined(MBEDTLS_NO_PLATFORM_ENTROPY) +/** + * \brief Platform-specific entropy poll callback + */ +int mbedtls_platform_entropy_poll(void *data, + unsigned char *output, size_t len, size_t *olen); +#endif + /** * \brief Initialize the context * diff --git a/vendor/mbedtls/include/mbedtls/entropy_poll.h b/vendor/mbedtls/include/mbedtls/entropy_poll.h deleted file mode 100644 index fed686235f..0000000000 --- a/vendor/mbedtls/include/mbedtls/entropy_poll.h +++ /dev/null @@ -1,108 +0,0 @@ -/** - * \file entropy_poll.h - * - * \brief Platform-specific and custom entropy polling functions - */ -/* - * Copyright The Mbed TLS Contributors - * SPDX-License-Identifier: Apache-2.0 - * - * Licensed under the Apache License, Version 2.0 (the "License"); you may - * not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT - * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ -#ifndef MBEDTLS_ENTROPY_POLL_H -#define MBEDTLS_ENTROPY_POLL_H - -#if !defined(MBEDTLS_CONFIG_FILE) -#include "mbedtls/config.h" -#else -#include MBEDTLS_CONFIG_FILE -#endif - -#include - -#ifdef __cplusplus -extern "C" { -#endif - -/* - * Default thresholds for built-in sources, in bytes - */ -#define MBEDTLS_ENTROPY_MIN_PLATFORM 32 /**< Minimum for platform source */ -#define MBEDTLS_ENTROPY_MIN_HAVEGE 32 /**< Minimum for HAVEGE */ -#define MBEDTLS_ENTROPY_MIN_HARDCLOCK 4 /**< Minimum for mbedtls_timing_hardclock() */ -#if !defined(MBEDTLS_ENTROPY_MIN_HARDWARE) -#define MBEDTLS_ENTROPY_MIN_HARDWARE 32 /**< Minimum for the hardware source */ -#endif - -/** - * \brief Entropy poll callback that provides 0 entropy. - */ -#if defined(MBEDTLS_TEST_NULL_ENTROPY) -int mbedtls_null_entropy_poll(void *data, - unsigned char *output, size_t len, size_t *olen); -#endif - -#if !defined(MBEDTLS_NO_PLATFORM_ENTROPY) -/** - * \brief Platform-specific entropy poll callback - */ -int mbedtls_platform_entropy_poll(void *data, - unsigned char *output, size_t len, size_t *olen); -#endif - -#if defined(MBEDTLS_HAVEGE_C) -/** - * \brief HAVEGE based entropy poll callback - * - * Requires an HAVEGE state as its data pointer. - */ -int mbedtls_havege_poll(void *data, - unsigned char *output, size_t len, size_t *olen); -#endif - -#if defined(MBEDTLS_TIMING_C) -/** - * \brief mbedtls_timing_hardclock-based entropy poll callback - */ -int mbedtls_hardclock_poll(void *data, - unsigned char *output, size_t len, size_t *olen); -#endif - -#if defined(MBEDTLS_ENTROPY_HARDWARE_ALT) -/** - * \brief Entropy poll callback for a hardware source - * - * \warning This is not provided by Mbed TLS! - * See \c MBEDTLS_ENTROPY_HARDWARE_ALT in config.h. - * - * \note This must accept NULL as its first argument. - */ -int mbedtls_hardware_poll(void *data, - unsigned char *output, size_t len, size_t *olen); -#endif - -#if defined(MBEDTLS_ENTROPY_NV_SEED) -/** - * \brief Entropy poll callback for a non-volatile seed file - * - * \note This must accept NULL as its first argument. - */ -int mbedtls_nv_seed_poll(void *data, - unsigned char *output, size_t len, size_t *olen); -#endif - -#ifdef __cplusplus -} -#endif - -#endif /* entropy_poll.h */ diff --git a/vendor/mbedtls/include/mbedtls/error.h b/vendor/mbedtls/include/mbedtls/error.h index 0d6230f597..186589ac5b 100644 --- a/vendor/mbedtls/include/mbedtls/error.h +++ b/vendor/mbedtls/include/mbedtls/error.h @@ -5,36 +5,15 @@ */ /* * Copyright The Mbed TLS Contributors - * SPDX-License-Identifier: Apache-2.0 - * - * Licensed under the Apache License, Version 2.0 (the "License"); you may - * not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT - * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. + * SPDX-License-Identifier: Apache-2.0 OR GPL-2.0-or-later */ #ifndef MBEDTLS_ERROR_H #define MBEDTLS_ERROR_H -#if !defined(MBEDTLS_CONFIG_FILE) -#include "mbedtls/config.h" -#else -#include MBEDTLS_CONFIG_FILE -#endif +#include "mbedtls/build_info.h" #include -#if (defined(__ARMCC_VERSION) || defined(_MSC_VER)) && \ - !defined(inline) && !defined(__cplusplus) -#define inline __inline -#endif - /** * Error code layout. * @@ -60,12 +39,10 @@ * Module Nr Codes assigned * ERROR 2 0x006E 0x0001 * MPI 7 0x0002-0x0010 - * GCM 3 0x0012-0x0014 0x0013-0x0013 - * BLOWFISH 3 0x0016-0x0018 0x0017-0x0017 + * GCM 3 0x0012-0x0016 0x0013-0x0013 * THREADING 3 0x001A-0x001E * AES 5 0x0020-0x0022 0x0021-0x0025 * CAMELLIA 3 0x0024-0x0026 0x0027-0x0027 - * XTEA 2 0x0028-0x0028 0x0029-0x0029 * BASE64 2 0x002A-0x002C * OID 1 0x002E-0x002E 0x000B-0x000B * PADLOCK 1 0x0030-0x0030 @@ -79,18 +56,17 @@ * PBKDF2 1 0x007C-0x007C * HMAC_DRBG 4 0x0003-0x0009 * CCM 3 0x000D-0x0011 - * ARC4 1 0x0019-0x0019 - * MD2 1 0x002B-0x002B - * MD4 1 0x002D-0x002D * MD5 1 0x002F-0x002F * RIPEMD160 1 0x0031-0x0031 * SHA1 1 0x0035-0x0035 0x0073-0x0073 * SHA256 1 0x0037-0x0037 0x0074-0x0074 * SHA512 1 0x0039-0x0039 0x0075-0x0075 + * SHA-3 1 0x0076-0x0076 * CHACHA20 3 0x0051-0x0055 * POLY1305 3 0x0057-0x005B * CHACHAPOLY 2 0x0054-0x0056 * PLATFORM 2 0x0070-0x0072 + * LMS 5 0x0011-0x0019 * * High-level module nr (3 bits - 0x0...-0x7...) * Name ID Nr of Errors @@ -104,10 +80,12 @@ * ECP 4 10 (Started from top) * MD 5 5 * HKDF 5 1 (Started from top) + * PKCS7 5 12 (Started from 0x5300) * SSL 5 2 (Started from 0x5F00) * CIPHER 6 8 (Started from 0x6080) - * SSL 6 24 (Started from top, plus 0x6000) - * SSL 7 32 + * SSL 6 22 (Started from top, plus 0x6000) + * SSL 7 20 (Started from 0x7000, gaps at + * 0x7380, 0x7900-0x7980, 0x7A80-0x7E80) * * Module dependent error code (5 bits 0x.00.-0x.F8.) */ @@ -121,6 +99,11 @@ extern "C" { /** This is a bug in the library */ #define MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED -0x006E +/** Hardware accelerator failed */ +#define MBEDTLS_ERR_PLATFORM_HW_ACCEL_FAILED -0x0070 +/** The requested feature is not supported by the platform */ +#define MBEDTLS_ERR_PLATFORM_FEATURE_UNSUPPORTED -0x0072 + /** * \brief Combines a high-level and low-level error code together. * diff --git a/vendor/mbedtls/include/mbedtls/gcm.h b/vendor/mbedtls/include/mbedtls/gcm.h index c04088388c..98faa43612 100644 --- a/vendor/mbedtls/include/mbedtls/gcm.h +++ b/vendor/mbedtls/include/mbedtls/gcm.h @@ -13,32 +13,21 @@ */ /* * Copyright The Mbed TLS Contributors - * SPDX-License-Identifier: Apache-2.0 - * - * Licensed under the Apache License, Version 2.0 (the "License"); you may - * not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT - * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. + * SPDX-License-Identifier: Apache-2.0 OR GPL-2.0-or-later */ #ifndef MBEDTLS_GCM_H #define MBEDTLS_GCM_H +#include "mbedtls/private_access.h" -#if !defined(MBEDTLS_CONFIG_FILE) -#include "mbedtls/config.h" -#else -#include MBEDTLS_CONFIG_FILE -#endif +#include "mbedtls/build_info.h" #include "mbedtls/cipher.h" +#if defined(MBEDTLS_BLOCK_CIPHER_C) +#include "mbedtls/block_cipher.h" +#endif + #include #define MBEDTLS_GCM_ENCRYPT 1 @@ -46,13 +35,10 @@ /** Authenticated decryption failed. */ #define MBEDTLS_ERR_GCM_AUTH_FAILED -0x0012 - -/* MBEDTLS_ERR_GCM_HW_ACCEL_FAILED is deprecated and should not be used. */ -/** GCM hardware accelerator failed. */ -#define MBEDTLS_ERR_GCM_HW_ACCEL_FAILED -0x0013 - /** Bad input parameters to function. */ #define MBEDTLS_ERR_GCM_BAD_INPUT -0x0014 +/** An output buffer is too small. */ +#define MBEDTLS_ERR_GCM_BUFFER_TOO_SMALL -0x0016 #ifdef __cplusplus extern "C" { @@ -60,21 +46,31 @@ extern "C" { #if !defined(MBEDTLS_GCM_ALT) +#if defined(MBEDTLS_GCM_LARGE_TABLE) +#define MBEDTLS_GCM_HTABLE_SIZE 256 +#else +#define MBEDTLS_GCM_HTABLE_SIZE 16 +#endif + /** * \brief The GCM context structure. */ typedef struct mbedtls_gcm_context { - mbedtls_cipher_context_t cipher_ctx; /*!< The cipher context used. */ - uint64_t HL[16]; /*!< Precalculated HTable low. */ - uint64_t HH[16]; /*!< Precalculated HTable high. */ - uint64_t len; /*!< The total length of the encrypted data. */ - uint64_t add_len; /*!< The total length of the additional data. */ - unsigned char base_ectr[16]; /*!< The first ECTR for tag. */ - unsigned char y[16]; /*!< The Y working value. */ - unsigned char buf[16]; /*!< The buf working value. */ - int mode; /*!< The operation to perform: - #MBEDTLS_GCM_ENCRYPT or - #MBEDTLS_GCM_DECRYPT. */ +#if defined(MBEDTLS_BLOCK_CIPHER_C) + mbedtls_block_cipher_context_t MBEDTLS_PRIVATE(block_cipher_ctx); /*!< The cipher context used. */ +#else + mbedtls_cipher_context_t MBEDTLS_PRIVATE(cipher_ctx); /*!< The cipher context used. */ +#endif + uint64_t MBEDTLS_PRIVATE(H)[MBEDTLS_GCM_HTABLE_SIZE][2]; /*!< Precalculated HTable. */ + uint64_t MBEDTLS_PRIVATE(len); /*!< The total length of the encrypted data. */ + uint64_t MBEDTLS_PRIVATE(add_len); /*!< The total length of the additional data. */ + unsigned char MBEDTLS_PRIVATE(base_ectr)[16]; /*!< The first ECTR for tag. */ + unsigned char MBEDTLS_PRIVATE(y)[16]; /*!< The Y working value. */ + unsigned char MBEDTLS_PRIVATE(buf)[16]; /*!< The buf working value. */ + unsigned char MBEDTLS_PRIVATE(mode); /*!< The operation to perform: + #MBEDTLS_GCM_ENCRYPT or + #MBEDTLS_GCM_DECRYPT. */ + unsigned char MBEDTLS_PRIVATE(acceleration); /*!< The acceleration to use. */ } mbedtls_gcm_context; @@ -233,6 +229,27 @@ int mbedtls_gcm_auth_decrypt(mbedtls_gcm_context *ctx, * \param iv The initialization vector. This must be a readable buffer of * at least \p iv_len Bytes. * \param iv_len The length of the IV. + * + * \return \c 0 on success. + */ +int mbedtls_gcm_starts(mbedtls_gcm_context *ctx, + int mode, + const unsigned char *iv, + size_t iv_len); + +/** + * \brief This function feeds an input buffer as associated data + * (authenticated but not encrypted data) in a GCM + * encryption or decryption operation. + * + * Call this function after mbedtls_gcm_starts() to pass + * the associated data. If the associated data is empty, + * you do not need to call this function. You may not + * call this function after calling mbedtls_cipher_update(). + * + * \param ctx The GCM context. This must have been started with + * mbedtls_gcm_starts() and must not have yet received + * any input with mbedtls_gcm_update(). * \param add The buffer holding the additional data, or \c NULL * if \p add_len is \c 0. * \param add_len The length of the additional data. If \c 0, @@ -240,42 +257,65 @@ int mbedtls_gcm_auth_decrypt(mbedtls_gcm_context *ctx, * * \return \c 0 on success. */ -int mbedtls_gcm_starts(mbedtls_gcm_context *ctx, - int mode, - const unsigned char *iv, - size_t iv_len, - const unsigned char *add, - size_t add_len); +int mbedtls_gcm_update_ad(mbedtls_gcm_context *ctx, + const unsigned char *add, + size_t add_len); /** * \brief This function feeds an input buffer into an ongoing GCM * encryption or decryption operation. * - * ` The function expects input to be a multiple of 16 - * Bytes. Only the last call before calling - * mbedtls_gcm_finish() can be less than 16 Bytes. + * You may call this function zero, one or more times + * to pass successive parts of the input: the plaintext to + * encrypt, or the ciphertext (not including the tag) to + * decrypt. After the last part of the input, call + * mbedtls_gcm_finish(). + * + * This function may produce output in one of the following + * ways: + * - Immediate output: the output length is always equal + * to the input length. + * - Buffered output: the output consists of a whole number + * of 16-byte blocks. If the total input length so far + * (not including associated data) is 16 \* *B* + *A* + * with *A* < 16 then the total output length is 16 \* *B*. + * + * In particular: + * - It is always correct to call this function with + * \p output_size >= \p input_length + 15. + * - If \p input_length is a multiple of 16 for all the calls + * to this function during an operation, then it is + * correct to use \p output_size = \p input_length. * * \note For decryption, the output buffer cannot be the same as * input buffer. If the buffers overlap, the output buffer * must trail at least 8 Bytes behind the input buffer. * - * \param ctx The GCM context. This must be initialized. - * \param length The length of the input data. This must be a multiple of - * 16 except in the last call before mbedtls_gcm_finish(). - * \param input The buffer holding the input data. If \p length is greater - * than zero, this must be a readable buffer of at least that - * size in Bytes. - * \param output The buffer for holding the output data. If \p length is - * greater than zero, this must be a writable buffer of at - * least that size in Bytes. + * \param ctx The GCM context. This must be initialized. + * \param input The buffer holding the input data. If \p input_length + * is greater than zero, this must be a readable buffer + * of at least \p input_length bytes. + * \param input_length The length of the input data in bytes. + * \param output The buffer for the output data. If \p output_size + * is greater than zero, this must be a writable buffer of + * of at least \p output_size bytes. + * \param output_size The size of the output buffer in bytes. + * See the function description regarding the output size. + * \param output_length On success, \p *output_length contains the actual + * length of the output written in \p output. + * On failure, the content of \p *output_length is + * unspecified. * * \return \c 0 on success. - * \return #MBEDTLS_ERR_GCM_BAD_INPUT on failure. + * \return #MBEDTLS_ERR_GCM_BAD_INPUT on failure: + * total input length too long, + * unsupported input/output buffer overlap detected, + * or \p output_size too small. */ int mbedtls_gcm_update(mbedtls_gcm_context *ctx, - size_t length, - const unsigned char *input, - unsigned char *output); + const unsigned char *input, size_t input_length, + unsigned char *output, size_t output_size, + size_t *output_length); /** * \brief This function finishes the GCM operation and generates @@ -289,13 +329,31 @@ int mbedtls_gcm_update(mbedtls_gcm_context *ctx, * buffer of at least \p tag_len Bytes. * \param tag_len The length of the tag to generate. This must be at least * four. + * \param output The buffer for the final output. + * If \p output_size is nonzero, this must be a writable + * buffer of at least \p output_size bytes. + * \param output_size The size of the \p output buffer in bytes. + * This must be large enough for the output that + * mbedtls_gcm_update() has not produced. In particular: + * - If mbedtls_gcm_update() produces immediate output, + * or if the total input size is a multiple of \c 16, + * then mbedtls_gcm_finish() never produces any output, + * so \p output_size can be \c 0. + * - \p output_size never needs to be more than \c 15. + * \param output_length On success, \p *output_length contains the actual + * length of the output written in \p output. + * On failure, the content of \p *output_length is + * unspecified. * * \return \c 0 on success. - * \return #MBEDTLS_ERR_GCM_BAD_INPUT on failure. + * \return #MBEDTLS_ERR_GCM_BAD_INPUT on failure: + * invalid value of \p tag_len, + * or \p output_size too small. */ int mbedtls_gcm_finish(mbedtls_gcm_context *ctx, - unsigned char *tag, - size_t tag_len); + unsigned char *output, size_t output_size, + size_t *output_length, + unsigned char *tag, size_t tag_len); /** * \brief This function clears a GCM context and the underlying diff --git a/vendor/mbedtls/include/mbedtls/havege.h b/vendor/mbedtls/include/mbedtls/havege.h deleted file mode 100644 index 7d042d1966..0000000000 --- a/vendor/mbedtls/include/mbedtls/havege.h +++ /dev/null @@ -1,79 +0,0 @@ -/** - * \file havege.h - * - * \brief HAVEGE: HArdware Volatile Entropy Gathering and Expansion - */ -/* - * Copyright The Mbed TLS Contributors - * SPDX-License-Identifier: Apache-2.0 - * - * Licensed under the Apache License, Version 2.0 (the "License"); you may - * not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT - * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ -#ifndef MBEDTLS_HAVEGE_H -#define MBEDTLS_HAVEGE_H - -#if !defined(MBEDTLS_CONFIG_FILE) -#include "mbedtls/config.h" -#else -#include MBEDTLS_CONFIG_FILE -#endif - -#include -#include - -#define MBEDTLS_HAVEGE_COLLECT_SIZE 1024 - -#ifdef __cplusplus -extern "C" { -#endif - -/** - * \brief HAVEGE state structure - */ -typedef struct mbedtls_havege_state { - uint32_t PT1, PT2, offset[2]; - uint32_t pool[MBEDTLS_HAVEGE_COLLECT_SIZE]; - uint32_t WALK[8192]; -} -mbedtls_havege_state; - -/** - * \brief HAVEGE initialization - * - * \param hs HAVEGE state to be initialized - */ -void mbedtls_havege_init(mbedtls_havege_state *hs); - -/** - * \brief Clear HAVEGE state - * - * \param hs HAVEGE state to be cleared - */ -void mbedtls_havege_free(mbedtls_havege_state *hs); - -/** - * \brief HAVEGE rand function - * - * \param p_rng A HAVEGE state - * \param output Buffer to fill - * \param len Length of buffer - * - * \return 0 - */ -int mbedtls_havege_random(void *p_rng, unsigned char *output, size_t len); - -#ifdef __cplusplus -} -#endif - -#endif /* havege.h */ diff --git a/vendor/mbedtls/include/mbedtls/hkdf.h b/vendor/mbedtls/include/mbedtls/hkdf.h index 3118369f0d..930e93f325 100644 --- a/vendor/mbedtls/include/mbedtls/hkdf.h +++ b/vendor/mbedtls/include/mbedtls/hkdf.h @@ -8,28 +8,12 @@ */ /* * Copyright The Mbed TLS Contributors - * SPDX-License-Identifier: Apache-2.0 - * - * Licensed under the Apache License, Version 2.0 (the "License"); you may - * not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT - * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. + * SPDX-License-Identifier: Apache-2.0 OR GPL-2.0-or-later */ #ifndef MBEDTLS_HKDF_H #define MBEDTLS_HKDF_H -#if !defined(MBEDTLS_CONFIG_FILE) -#include "mbedtls/config.h" -#else -#include MBEDTLS_CONFIG_FILE -#endif +#include "mbedtls/build_info.h" #include "mbedtls/md.h" diff --git a/vendor/mbedtls/include/mbedtls/hmac_drbg.h b/vendor/mbedtls/include/mbedtls/hmac_drbg.h index 6b2248531b..18b1b75a69 100644 --- a/vendor/mbedtls/include/mbedtls/hmac_drbg.h +++ b/vendor/mbedtls/include/mbedtls/hmac_drbg.h @@ -9,28 +9,13 @@ */ /* * Copyright The Mbed TLS Contributors - * SPDX-License-Identifier: Apache-2.0 - * - * Licensed under the Apache License, Version 2.0 (the "License"); you may - * not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT - * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. + * SPDX-License-Identifier: Apache-2.0 OR GPL-2.0-or-later */ #ifndef MBEDTLS_HMAC_DRBG_H #define MBEDTLS_HMAC_DRBG_H +#include "mbedtls/private_access.h" -#if !defined(MBEDTLS_CONFIG_FILE) -#include "mbedtls/config.h" -#else -#include MBEDTLS_CONFIG_FILE -#endif +#include "mbedtls/build_info.h" #include "mbedtls/md.h" @@ -54,7 +39,7 @@ * \name SECTION: Module settings * * The configuration options you can set for this module are in this section. - * Either change them in config.h or define them on the compiler command line. + * Either change them in mbedtls_config.h or define them on the compiler command line. * \{ */ @@ -89,19 +74,19 @@ extern "C" { typedef struct mbedtls_hmac_drbg_context { /* Working state: the key K is not stored explicitly, * but is implied by the HMAC context */ - mbedtls_md_context_t md_ctx; /*!< HMAC context (inc. K) */ - unsigned char V[MBEDTLS_MD_MAX_SIZE]; /*!< V in the spec */ - int reseed_counter; /*!< reseed counter */ + mbedtls_md_context_t MBEDTLS_PRIVATE(md_ctx); /*!< HMAC context (inc. K) */ + unsigned char MBEDTLS_PRIVATE(V)[MBEDTLS_MD_MAX_SIZE]; /*!< V in the spec */ + int MBEDTLS_PRIVATE(reseed_counter); /*!< reseed counter */ /* Administrative state */ - size_t entropy_len; /*!< entropy bytes grabbed on each (re)seed */ - int prediction_resistance; /*!< enable prediction resistance (Automatic - reseed before every random generation) */ - int reseed_interval; /*!< reseed interval */ + size_t MBEDTLS_PRIVATE(entropy_len); /*!< entropy bytes grabbed on each (re)seed */ + int MBEDTLS_PRIVATE(prediction_resistance); /*!< enable prediction resistance (Automatic + reseed before every random generation) */ + int MBEDTLS_PRIVATE(reseed_interval); /*!< reseed interval */ /* Callbacks */ - int (*f_entropy)(void *, unsigned char *, size_t); /*!< entropy function */ - void *p_entropy; /*!< context for the entropy function */ + int(*MBEDTLS_PRIVATE(f_entropy))(void *, unsigned char *, size_t); /*!< entropy function */ + void *MBEDTLS_PRIVATE(p_entropy); /*!< context for the entropy function */ #if defined(MBEDTLS_THREADING_C) /* Invariant: the mutex is initialized if and only if @@ -112,7 +97,7 @@ typedef struct mbedtls_hmac_drbg_context { * Note that this invariant may change without notice. Do not rely on it * and do not access the mutex directly in application code. */ - mbedtls_threading_mutex_t mutex; + mbedtls_threading_mutex_t MBEDTLS_PRIVATE(mutex); #endif } mbedtls_hmac_drbg_context; @@ -297,8 +282,8 @@ void mbedtls_hmac_drbg_set_reseed_interval(mbedtls_hmac_drbg_context *ctx, * \return \c 0 on success, or an error from the underlying * hash calculation. */ -int mbedtls_hmac_drbg_update_ret(mbedtls_hmac_drbg_context *ctx, - const unsigned char *additional, size_t add_len); +int mbedtls_hmac_drbg_update(mbedtls_hmac_drbg_context *ctx, + const unsigned char *additional, size_t add_len); /** * \brief This function reseeds the HMAC_DRBG context, that is @@ -400,30 +385,6 @@ int mbedtls_hmac_drbg_random(void *p_rng, unsigned char *output, size_t out_len) */ void mbedtls_hmac_drbg_free(mbedtls_hmac_drbg_context *ctx); -#if !defined(MBEDTLS_DEPRECATED_REMOVED) -#if defined(MBEDTLS_DEPRECATED_WARNING) -#define MBEDTLS_DEPRECATED __attribute__((deprecated)) -#else -#define MBEDTLS_DEPRECATED -#endif -/** - * \brief This function updates the state of the HMAC_DRBG context. - * - * \deprecated Superseded by mbedtls_hmac_drbg_update_ret() - * in 2.16.0. - * - * \param ctx The HMAC_DRBG context. - * \param additional The data to update the state with. - * If this is \c NULL, there is no additional data. - * \param add_len Length of \p additional in bytes. - * Unused if \p additional is \c NULL. - */ -MBEDTLS_DEPRECATED void mbedtls_hmac_drbg_update( - mbedtls_hmac_drbg_context *ctx, - const unsigned char *additional, size_t add_len); -#undef MBEDTLS_DEPRECATED -#endif /* !MBEDTLS_DEPRECATED_REMOVED */ - #if defined(MBEDTLS_FS_IO) /** * \brief This function writes a seed file. diff --git a/vendor/mbedtls/include/mbedtls/lms.h b/vendor/mbedtls/include/mbedtls/lms.h new file mode 100644 index 0000000000..95fce21337 --- /dev/null +++ b/vendor/mbedtls/include/mbedtls/lms.h @@ -0,0 +1,440 @@ +/** + * \file lms.h + * + * \brief This file provides an API for the LMS post-quantum-safe stateful-hash + public-key signature scheme as defined in RFC8554 and NIST.SP.200-208. + * This implementation currently only supports a single parameter set + * MBEDTLS_LMS_SHA256_M32_H10 in order to reduce complexity. This is one + * of the signature schemes recommended by the IETF draft SUIT standard + * for IOT firmware upgrades (RFC9019). + */ +/* + * Copyright The Mbed TLS Contributors + * SPDX-License-Identifier: Apache-2.0 OR GPL-2.0-or-later + */ +#ifndef MBEDTLS_LMS_H +#define MBEDTLS_LMS_H + +#include +#include + +#include "mbedtls/private_access.h" +#include "mbedtls/build_info.h" + +#define MBEDTLS_ERR_LMS_BAD_INPUT_DATA -0x0011 /**< Bad data has been input to an LMS function */ +#define MBEDTLS_ERR_LMS_OUT_OF_PRIVATE_KEYS -0x0013 /**< Specified LMS key has utilised all of its private keys */ +#define MBEDTLS_ERR_LMS_VERIFY_FAILED -0x0015 /**< LMS signature verification failed */ +#define MBEDTLS_ERR_LMS_ALLOC_FAILED -0x0017 /**< LMS failed to allocate space for a private key */ +#define MBEDTLS_ERR_LMS_BUFFER_TOO_SMALL -0x0019 /**< Input/output buffer is too small to contain requited data */ + +/* Currently only defined for SHA256, 32 is the max hash output size */ +#define MBEDTLS_LMOTS_N_HASH_LEN_MAX (32u) +#define MBEDTLS_LMOTS_P_SIG_DIGIT_COUNT_MAX (34u) +#define MBEDTLS_LMOTS_N_HASH_LEN(type) ((type) == MBEDTLS_LMOTS_SHA256_N32_W8 ? 32u : 0) +#define MBEDTLS_LMOTS_I_KEY_ID_LEN (16u) +#define MBEDTLS_LMOTS_Q_LEAF_ID_LEN (4u) +#define MBEDTLS_LMOTS_TYPE_LEN (4u) +#define MBEDTLS_LMOTS_P_SIG_DIGIT_COUNT(type) ((type) == MBEDTLS_LMOTS_SHA256_N32_W8 ? 34u : 0) +#define MBEDTLS_LMOTS_C_RANDOM_VALUE_LEN(type) (MBEDTLS_LMOTS_N_HASH_LEN(type)) + +#define MBEDTLS_LMOTS_SIG_LEN(type) (MBEDTLS_LMOTS_TYPE_LEN + \ + MBEDTLS_LMOTS_C_RANDOM_VALUE_LEN(type) + \ + (MBEDTLS_LMOTS_P_SIG_DIGIT_COUNT(type) * \ + MBEDTLS_LMOTS_N_HASH_LEN(type))) + + +#define MBEDTLS_LMS_TYPE_LEN (4) +#define MBEDTLS_LMS_H_TREE_HEIGHT(type) ((type) == MBEDTLS_LMS_SHA256_M32_H10 ? 10u : 0) + +/* The length of a hash output, Currently only implemented for SHA256. + * Max is 32 bytes. + */ +#define MBEDTLS_LMS_M_NODE_BYTES(type) ((type) == MBEDTLS_LMS_SHA256_M32_H10 ? 32 : 0) +#define MBEDTLS_LMS_M_NODE_BYTES_MAX 32 + +#define MBEDTLS_LMS_SIG_LEN(type, otstype) (MBEDTLS_LMOTS_Q_LEAF_ID_LEN + \ + MBEDTLS_LMOTS_SIG_LEN(otstype) + \ + MBEDTLS_LMS_TYPE_LEN + \ + (MBEDTLS_LMS_H_TREE_HEIGHT(type) * \ + MBEDTLS_LMS_M_NODE_BYTES(type))) + +#define MBEDTLS_LMS_PUBLIC_KEY_LEN(type) (MBEDTLS_LMS_TYPE_LEN + \ + MBEDTLS_LMOTS_TYPE_LEN + \ + MBEDTLS_LMOTS_I_KEY_ID_LEN + \ + MBEDTLS_LMS_M_NODE_BYTES(type)) + + +#ifdef __cplusplus +extern "C" { +#endif + +/** The Identifier of the LMS parameter set, as per + * https://www.iana.org/assignments/leighton-micali-signatures/leighton-micali-signatures.xhtml + * We are only implementing a subset of the types, particularly H10, for the sake of simplicity. + */ +typedef enum { + MBEDTLS_LMS_SHA256_M32_H10 = 0x6, +} mbedtls_lms_algorithm_type_t; + +/** The Identifier of the LMOTS parameter set, as per + * https://www.iana.org/assignments/leighton-micali-signatures/leighton-micali-signatures.xhtml. + * We are only implementing a subset of the types, particularly N32_W8, for the sake of simplicity. + */ +typedef enum { + MBEDTLS_LMOTS_SHA256_N32_W8 = 4 +} mbedtls_lmots_algorithm_type_t; + +/** LMOTS parameters structure. + * + * This contains the metadata associated with an LMOTS key, detailing the + * algorithm type, the key ID, and the leaf identifier should be key be part of + * a LMS key. + */ +typedef struct { + unsigned char MBEDTLS_PRIVATE(I_key_identifier[MBEDTLS_LMOTS_I_KEY_ID_LEN]); /*!< The key + identifier. */ + unsigned char MBEDTLS_PRIVATE(q_leaf_identifier[MBEDTLS_LMOTS_Q_LEAF_ID_LEN]); /*!< Which + leaf of the LMS key this is. + 0 if the key is not part of an LMS key. */ + mbedtls_lmots_algorithm_type_t MBEDTLS_PRIVATE(type); /*!< The LM-OTS key type identifier as + per IANA. Only SHA256_N32_W8 is + currently supported. */ +} mbedtls_lmots_parameters_t; + +/** LMOTS public context structure. + * + * A LMOTS public key is a hash output, and the applicable parameter set. + * + * The context must be initialized before it is used. A public key must either + * be imported or generated from a private context. + * + * \dot + * digraph lmots_public_t { + * UNINITIALIZED -> INIT [label="init"]; + * HAVE_PUBLIC_KEY -> INIT [label="free"]; + * INIT -> HAVE_PUBLIC_KEY [label="import_public_key"]; + * INIT -> HAVE_PUBLIC_KEY [label="calculate_public_key from private key"]; + * HAVE_PUBLIC_KEY -> HAVE_PUBLIC_KEY [label="export_public_key"]; + * } + * \enddot + */ +typedef struct { + mbedtls_lmots_parameters_t MBEDTLS_PRIVATE(params); + unsigned char MBEDTLS_PRIVATE(public_key)[MBEDTLS_LMOTS_N_HASH_LEN_MAX]; + unsigned char MBEDTLS_PRIVATE(have_public_key); /*!< Whether the context contains a public key. + Boolean values only. */ +} mbedtls_lmots_public_t; + +#if defined(MBEDTLS_LMS_PRIVATE) +/** LMOTS private context structure. + * + * A LMOTS private key is one hash output for each of digit of the digest + + * checksum, and the applicable parameter set. + * + * The context must be initialized before it is used. A public key must either + * be imported or generated from a private context. + * + * \dot + * digraph lmots_public_t { + * UNINITIALIZED -> INIT [label="init"]; + * HAVE_PRIVATE_KEY -> INIT [label="free"]; + * INIT -> HAVE_PRIVATE_KEY [label="generate_private_key"]; + * HAVE_PRIVATE_KEY -> INIT [label="sign"]; + * } + * \enddot + */ +typedef struct { + mbedtls_lmots_parameters_t MBEDTLS_PRIVATE(params); + unsigned char MBEDTLS_PRIVATE(private_key)[MBEDTLS_LMOTS_P_SIG_DIGIT_COUNT_MAX][ + MBEDTLS_LMOTS_N_HASH_LEN_MAX]; + unsigned char MBEDTLS_PRIVATE(have_private_key); /*!< Whether the context contains a private key. + Boolean values only. */ +} mbedtls_lmots_private_t; +#endif /* defined(MBEDTLS_LMS_PRIVATE) */ + + +/** LMS parameters structure. + * + * This contains the metadata associated with an LMS key, detailing the + * algorithm type, the type of the underlying OTS algorithm, and the key ID. + */ +typedef struct { + unsigned char MBEDTLS_PRIVATE(I_key_identifier[MBEDTLS_LMOTS_I_KEY_ID_LEN]); /*!< The key + identifier. */ + mbedtls_lmots_algorithm_type_t MBEDTLS_PRIVATE(otstype); /*!< The LM-OTS key type identifier as + per IANA. Only SHA256_N32_W8 is + currently supported. */ + mbedtls_lms_algorithm_type_t MBEDTLS_PRIVATE(type); /*!< The LMS key type identifier as per + IANA. Only SHA256_M32_H10 is currently + supported. */ +} mbedtls_lms_parameters_t; + +/** LMS public context structure. + * + * A LMS public key is the hash output that is the root of the Merkle tree, and + * the applicable parameter set + * + * The context must be initialized before it is used. A public key must either + * be imported or generated from a private context. + * + * \dot + * digraph lms_public_t { + * UNINITIALIZED -> INIT [label="init"]; + * HAVE_PUBLIC_KEY -> INIT [label="free"]; + * INIT -> HAVE_PUBLIC_KEY [label="import_public_key"]; + * INIT -> HAVE_PUBLIC_KEY [label="calculate_public_key from private key"]; + * HAVE_PUBLIC_KEY -> HAVE_PUBLIC_KEY [label="export_public_key"]; + * } + * \enddot + */ +typedef struct { + mbedtls_lms_parameters_t MBEDTLS_PRIVATE(params); + unsigned char MBEDTLS_PRIVATE(T_1_pub_key)[MBEDTLS_LMS_M_NODE_BYTES_MAX]; /*!< The public key, in + the form of the Merkle tree root node. */ + unsigned char MBEDTLS_PRIVATE(have_public_key); /*!< Whether the context contains a public key. + Boolean values only. */ +} mbedtls_lms_public_t; + + +#if defined(MBEDTLS_LMS_PRIVATE) +/** LMS private context structure. + * + * A LMS private key is a set of LMOTS private keys, an index to the next usable + * key, and the applicable parameter set. + * + * The context must be initialized before it is used. A public key must either + * be imported or generated from a private context. + * + * \dot + * digraph lms_public_t { + * UNINITIALIZED -> INIT [label="init"]; + * HAVE_PRIVATE_KEY -> INIT [label="free"]; + * INIT -> HAVE_PRIVATE_KEY [label="generate_private_key"]; + * } + * \enddot + */ +typedef struct { + mbedtls_lms_parameters_t MBEDTLS_PRIVATE(params); + uint32_t MBEDTLS_PRIVATE(q_next_usable_key); /*!< The index of the next OTS key that has not + been used. */ + mbedtls_lmots_private_t *MBEDTLS_PRIVATE(ots_private_keys); /*!< The private key material. One OTS key + for each leaf node in the Merkle tree. NULL + when have_private_key is 0 and non-NULL otherwise. + is 2^MBEDTLS_LMS_H_TREE_HEIGHT(type) in length. */ + mbedtls_lmots_public_t *MBEDTLS_PRIVATE(ots_public_keys); /*!< The OTS key public keys, used to + build the Merkle tree. NULL + when have_private_key is 0 and + non-NULL otherwise. + Is 2^MBEDTLS_LMS_H_TREE_HEIGHT(type) + in length. */ + unsigned char MBEDTLS_PRIVATE(have_private_key); /*!< Whether the context contains a private key. + Boolean values only. */ +} mbedtls_lms_private_t; +#endif /* defined(MBEDTLS_LMS_PRIVATE) */ + +/** + * \brief This function initializes an LMS public context + * + * \param ctx The uninitialized LMS context that will then be + * initialized. + */ +void mbedtls_lms_public_init(mbedtls_lms_public_t *ctx); + +/** + * \brief This function uninitializes an LMS public context + * + * \param ctx The initialized LMS context that will then be + * uninitialized. + */ +void mbedtls_lms_public_free(mbedtls_lms_public_t *ctx); + +/** + * \brief This function imports an LMS public key into a + * public LMS context. + * + * \note Before this function is called, the context must + * have been initialized. + * + * \note See IETF RFC8554 for details of the encoding of + * this public key. + * + * \param ctx The initialized LMS context store the key in. + * \param key The buffer from which the key will be read. + * #MBEDTLS_LMS_PUBLIC_KEY_LEN bytes will be read from + * this. + * \param key_size The size of the key being imported. + * + * \return \c 0 on success. + * \return A non-zero error code on failure. + */ +int mbedtls_lms_import_public_key(mbedtls_lms_public_t *ctx, + const unsigned char *key, size_t key_size); + +/** + * \brief This function exports an LMS public key from a + * LMS public context that already contains a public + * key. + * + * \note Before this function is called, the context must + * have been initialized and the context must contain + * a public key. + * + * \note See IETF RFC8554 for details of the encoding of + * this public key. + * + * \param ctx The initialized LMS public context that contains + * the public key. + * \param key The buffer into which the key will be output. Must + * be at least #MBEDTLS_LMS_PUBLIC_KEY_LEN in size. + * \param key_size The size of the key buffer. + * \param key_len If not NULL, will be written with the size of the + * key. + * + * \return \c 0 on success. + * \return A non-zero error code on failure. + */ +int mbedtls_lms_export_public_key(const mbedtls_lms_public_t *ctx, + unsigned char *key, size_t key_size, + size_t *key_len); + +/** + * \brief This function verifies a LMS signature, using a + * LMS context that contains a public key. + * + * \note Before this function is called, the context must + * have been initialized and must contain a public key + * (either by import or generation). + * + * \param ctx The initialized LMS public context from which the + * public key will be read. + * \param msg The buffer from which the message will be read. + * \param msg_size The size of the message that will be read. + * \param sig The buf from which the signature will be read. + * #MBEDTLS_LMS_SIG_LEN bytes will be read from + * this. + * \param sig_size The size of the signature to be verified. + * + * \return \c 0 on successful verification. + * \return A non-zero error code on failure. + */ +int mbedtls_lms_verify(const mbedtls_lms_public_t *ctx, + const unsigned char *msg, size_t msg_size, + const unsigned char *sig, size_t sig_size); + +#if defined(MBEDTLS_LMS_PRIVATE) +/** + * \brief This function initializes an LMS private context + * + * \param ctx The uninitialized LMS private context that will + * then be initialized. */ +void mbedtls_lms_private_init(mbedtls_lms_private_t *ctx); + +/** + * \brief This function uninitializes an LMS private context + * + * \param ctx The initialized LMS private context that will then + * be uninitialized. + */ +void mbedtls_lms_private_free(mbedtls_lms_private_t *ctx); + +/** + * \brief This function generates an LMS private key, and + * stores in into an LMS private context. + * + * \warning This function is **not intended for use in + * production**, due to as-yet unsolved problems with + * handling stateful keys. The API for this function + * may change considerably in future versions. + * + * \note The seed must have at least 256 bits of entropy. + * + * \param ctx The initialized LMOTS context to generate the key + * into. + * \param type The LMS parameter set identifier. + * \param otstype The LMOTS parameter set identifier. + * \param f_rng The RNG function to be used to generate the key ID. + * \param p_rng The RNG context to be passed to f_rng + * \param seed The seed used to deterministically generate the + * key. + * \param seed_size The length of the seed. + * + * \return \c 0 on success. + * \return A non-zero error code on failure. + */ +int mbedtls_lms_generate_private_key(mbedtls_lms_private_t *ctx, + mbedtls_lms_algorithm_type_t type, + mbedtls_lmots_algorithm_type_t otstype, + int (*f_rng)(void *, unsigned char *, size_t), + void *p_rng, const unsigned char *seed, + size_t seed_size); + +/** + * \brief This function calculates an LMS public key from a + * LMS context that already contains a private key. + * + * \note Before this function is called, the context must + * have been initialized and the context must contain + * a private key. + * + * \param ctx The initialized LMS public context to calculate the key + * from and store it into. + * + * \param priv_ctx The LMS private context to read the private key + * from. This must have been initialized and contain a + * private key. + * + * \return \c 0 on success. + * \return A non-zero error code on failure. + */ +int mbedtls_lms_calculate_public_key(mbedtls_lms_public_t *ctx, + const mbedtls_lms_private_t *priv_ctx); + +/** + * \brief This function creates a LMS signature, using a + * LMS context that contains unused private keys. + * + * \warning This function is **not intended for use in + * production**, due to as-yet unsolved problems with + * handling stateful keys. The API for this function + * may change considerably in future versions. + * + * \note Before this function is called, the context must + * have been initialized and must contain a private + * key. + * + * \note Each of the LMOTS private keys inside a LMS private + * key can only be used once. If they are reused, then + * attackers may be able to forge signatures with that + * key. This is all handled transparently, but it is + * important to not perform copy operations on LMS + * contexts that contain private key material. + * + * \param ctx The initialized LMS private context from which the + * private key will be read. + * \param f_rng The RNG function to be used for signature + * generation. + * \param p_rng The RNG context to be passed to f_rng + * \param msg The buffer from which the message will be read. + * \param msg_size The size of the message that will be read. + * \param sig The buf into which the signature will be stored. + * Must be at least #MBEDTLS_LMS_SIG_LEN in size. + * \param sig_size The size of the buffer the signature will be + * written into. + * \param sig_len If not NULL, will be written with the size of the + * signature. + * + * \return \c 0 on success. + * \return A non-zero error code on failure. + */ +int mbedtls_lms_sign(mbedtls_lms_private_t *ctx, + int (*f_rng)(void *, unsigned char *, size_t), + void *p_rng, const unsigned char *msg, + unsigned int msg_size, unsigned char *sig, size_t sig_size, + size_t *sig_len); +#endif /* defined(MBEDTLS_LMS_PRIVATE) */ + +#ifdef __cplusplus +} +#endif + +#endif /* MBEDTLS_LMS_H */ diff --git a/vendor/mbedtls/include/mbedtls/config.h b/vendor/mbedtls/include/mbedtls/mbedtls_config.h similarity index 75% rename from vendor/mbedtls/include/mbedtls/config.h rename to vendor/mbedtls/include/mbedtls/mbedtls_config.h index 7b1f38aa9e..35921412c6 100644 --- a/vendor/mbedtls/include/mbedtls/config.h +++ b/vendor/mbedtls/include/mbedtls/mbedtls_config.h @@ -1,5 +1,5 @@ /** - * \file config.h + * \file mbedtls_config.h * * \brief Configuration options (set of defines) * @@ -9,27 +9,17 @@ */ /* * Copyright The Mbed TLS Contributors - * SPDX-License-Identifier: Apache-2.0 - * - * Licensed under the Apache License, Version 2.0 (the "License"); you may - * not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT - * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. + * SPDX-License-Identifier: Apache-2.0 OR GPL-2.0-or-later */ -#ifndef MBEDTLS_CONFIG_H -#define MBEDTLS_CONFIG_H - -#if defined(_MSC_VER) && !defined(_CRT_SECURE_NO_DEPRECATE) -#define _CRT_SECURE_NO_DEPRECATE 1 -#endif +/** + * This is an optional version symbol that enables compatibility handling of + * config files. + * + * It is equal to the #MBEDTLS_VERSION_NUMBER of the Mbed TLS version that + * introduced the config format we want to be compatible with. + */ +//#define MBEDTLS_CONFIG_VERSION 0x03000000 /** * \name SECTION: System support @@ -46,11 +36,14 @@ * Requires support for asm() in compiler. * * Used in: + * library/aesni.h * library/aria.c - * library/timing.c - * include/mbedtls/bn_mul.h + * library/bn_mul.h + * library/constant_time.c + * library/padlock.h * * Required by: + * MBEDTLS_AESCE_C * MBEDTLS_AESNI_C (on some platforms) * MBEDTLS_PADLOCK_C * @@ -256,6 +249,7 @@ * Uncomment a macro to enable alternate implementation of specific base * platform function */ +//#define MBEDTLS_PLATFORM_SETBUF_ALT //#define MBEDTLS_PLATFORM_EXIT_ALT //#define MBEDTLS_PLATFORM_TIME_ALT //#define MBEDTLS_PLATFORM_FPRINTF_ALT @@ -264,6 +258,7 @@ //#define MBEDTLS_PLATFORM_VSNPRINTF_ALT //#define MBEDTLS_PLATFORM_NV_SEED_ALT //#define MBEDTLS_PLATFORM_SETUP_TEARDOWN_ALT +//#define MBEDTLS_PLATFORM_MS_TIME_ALT /** * Uncomment the macro to let Mbed TLS use your alternate implementation of @@ -286,21 +281,24 @@ /** * Uncomment the macro to let Mbed TLS use your alternate implementation of - * mbedtls_platform_zeroize(). This replaces the default implementation in - * platform_util.c. - * - * mbedtls_platform_zeroize() is a widely used function across the library to - * zero a block of memory. The implementation is expected to be secure in the - * sense that it has been written to prevent the compiler from removing calls - * to mbedtls_platform_zeroize() as part of redundant code elimination - * optimizations. However, it is difficult to guarantee that calls to - * mbedtls_platform_zeroize() will not be optimized by the compiler as older - * versions of the C language standards do not provide a secure implementation - * of memset(). Therefore, MBEDTLS_PLATFORM_ZEROIZE_ALT enables users to - * configure their own implementation of mbedtls_platform_zeroize(), for - * example by using directives specific to their compiler, features from newer - * C standards (e.g using memset_s() in C11) or calling a secure memset() from - * their system (e.g explicit_bzero() in BSD). + * mbedtls_platform_zeroize(), to wipe sensitive data in memory. This replaces + * the default implementation in platform_util.c. + * + * By default, the library uses a system function such as memset_s() + * (optional feature of C11), explicit_bzero() (BSD and compatible), or + * SecureZeroMemory (Windows). If no such function is detected, the library + * falls back to a plain C implementation. Compilers are technically + * permitted to optimize this implementation out, meaning that the memory is + * not actually wiped. The library tries to prevent that, but the C language + * makes it impossible to guarantee that the memory will always be wiped. + * + * If your platform provides a guaranteed method to wipe memory which + * `platform_util.c` does not detect, define this macro to the name of + * a function that takes two arguments, a `void *` pointer and a length, + * and wipes that many bytes starting at the specified address. For example, + * if your platform has explicit_bzero() but `platform_util.c` does not + * detect its presence, define `MBEDTLS_PLATFORM_ZEROIZE_ALT` to be + * `explicit_bzero` to use that function as mbedtls_platform_zeroize(). */ //#define MBEDTLS_PLATFORM_ZEROIZE_ALT @@ -331,72 +329,6 @@ */ //#define MBEDTLS_DEPRECATED_REMOVED -/** - * \def MBEDTLS_CHECK_PARAMS - * - * This configuration option controls whether the library validates more of - * the parameters passed to it. - * - * When this flag is not defined, the library only attempts to validate an - * input parameter if: (1) they may come from the outside world (such as the - * network, the filesystem, etc.) or (2) not validating them could result in - * internal memory errors such as overflowing a buffer controlled by the - * library. On the other hand, it doesn't attempt to validate parameters whose - * values are fully controlled by the application (such as pointers). - * - * When this flag is defined, the library additionally attempts to validate - * parameters that are fully controlled by the application, and should always - * be valid if the application code is fully correct and trusted. - * - * For example, when a function accepts as input a pointer to a buffer that may - * contain untrusted data, and its documentation mentions that this pointer - * must not be NULL: - * - The pointer is checked to be non-NULL only if this option is enabled. - * - The content of the buffer is always validated. - * - * When this flag is defined, if a library function receives a parameter that - * is invalid: - * 1. The function will invoke the macro MBEDTLS_PARAM_FAILED(). - * 2. If MBEDTLS_PARAM_FAILED() did not terminate the program, the function - * will immediately return. If the function returns an Mbed TLS error code, - * the error code in this case is MBEDTLS_ERR_xxx_BAD_INPUT_DATA. - * - * When defining this flag, you also need to arrange a definition for - * MBEDTLS_PARAM_FAILED(). You can do this by any of the following methods: - * - By default, the library defines MBEDTLS_PARAM_FAILED() to call a - * function mbedtls_param_failed(), but the library does not define this - * function. If you do not make any other arrangements, you must provide - * the function mbedtls_param_failed() in your application. - * See `platform_util.h` for its prototype. - * - If you enable the macro #MBEDTLS_CHECK_PARAMS_ASSERT, then the - * library defines MBEDTLS_PARAM_FAILED(\c cond) to be `assert(cond)`. - * You can still supply an alternative definition of - * MBEDTLS_PARAM_FAILED(), which may call `assert`. - * - If you define a macro MBEDTLS_PARAM_FAILED() before including `config.h` - * or you uncomment the definition of MBEDTLS_PARAM_FAILED() in `config.h`, - * the library will call the macro that you defined and will not supply - * its own version. Note that if MBEDTLS_PARAM_FAILED() calls `assert`, - * you need to enable #MBEDTLS_CHECK_PARAMS_ASSERT so that library source - * files include ``. - * - * Uncomment to enable validation of application-controlled parameters. - */ -//#define MBEDTLS_CHECK_PARAMS - -/** - * \def MBEDTLS_CHECK_PARAMS_ASSERT - * - * Allow MBEDTLS_PARAM_FAILED() to call `assert`, and make it default to - * `assert`. This macro is only used if #MBEDTLS_CHECK_PARAMS is defined. - * - * If this macro is not defined, then MBEDTLS_PARAM_FAILED() defaults to - * calling a function mbedtls_param_failed(). See the documentation of - * #MBEDTLS_CHECK_PARAMS for details. - * - * Uncomment to allow MBEDTLS_PARAM_FAILED() to call `assert`. - */ -//#define MBEDTLS_CHECK_PARAMS_ASSERT - /** \} name SECTION: System support */ /** @@ -410,7 +342,7 @@ /** * \def MBEDTLS_TIMING_ALT * - * Uncomment to provide your own alternate implementation for mbedtls_timing_hardclock(), + * Uncomment to provide your own alternate implementation for * mbedtls_timing_get_timer(), mbedtls_set_alarm(), mbedtls_set/get_delay() * * Only works if you have MBEDTLS_TIMING_C enabled. @@ -439,16 +371,14 @@ * Uncomment a macro to enable alternate implementation of the corresponding * module. * - * \warning MD2, MD4, MD5, ARC4, DES and SHA-1 are considered weak and their + * \warning MD5, DES and SHA-1 are considered weak and their * use constitutes a security risk. If possible, we recommend * avoiding dependencies on them, and considering stronger message * digests and ciphers instead. * */ //#define MBEDTLS_AES_ALT -//#define MBEDTLS_ARC4_ALT //#define MBEDTLS_ARIA_ALT -//#define MBEDTLS_BLOWFISH_ALT //#define MBEDTLS_CAMELLIA_ALT //#define MBEDTLS_CCM_ALT //#define MBEDTLS_CHACHA20_ALT @@ -459,8 +389,6 @@ //#define MBEDTLS_ECJPAKE_ALT //#define MBEDTLS_GCM_ALT //#define MBEDTLS_NIST_KW_ALT -//#define MBEDTLS_MD2_ALT -//#define MBEDTLS_MD4_ALT //#define MBEDTLS_MD5_ALT //#define MBEDTLS_POLY1305_ALT //#define MBEDTLS_RIPEMD160_ALT @@ -468,7 +396,6 @@ //#define MBEDTLS_SHA1_ALT //#define MBEDTLS_SHA256_ALT //#define MBEDTLS_SHA512_ALT -//#define MBEDTLS_XTEA_ALT /* * When replacing the elliptic curve module, please consider, that it is @@ -482,7 +409,7 @@ //#define MBEDTLS_ECP_ALT /** - * \def MBEDTLS_MD2_PROCESS_ALT + * \def MBEDTLS_SHA256_PROCESS_ALT * * MBEDTLS__FUNCTION_NAME__ALT: Uncomment a macro to let Mbed TLS use you * alternate core implementation of symmetric crypto or hash function. Keep in @@ -497,12 +424,6 @@ * of mbedtls_sha1_context, so your implementation of mbedtls_sha1_process must be compatible * with this definition. * - * \note Because of a signature change, the core AES encryption and decryption routines are - * currently named mbedtls_aes_internal_encrypt and mbedtls_aes_internal_decrypt, - * respectively. When setting up alternative implementations, these functions should - * be overridden, but the wrapper functions mbedtls_aes_decrypt and mbedtls_aes_encrypt - * must stay untouched. - * * \note If you use the AES_xxx_ALT macros, then it is recommended to also set * MBEDTLS_AES_ROM_TABLES in order to help the linker garbage-collect the AES * tables. @@ -510,7 +431,7 @@ * Uncomment a macro to enable alternate implementation of the corresponding * function. * - * \warning MD2, MD4, MD5, DES and SHA-1 are considered weak and their use + * \warning MD5, DES and SHA-1 are considered weak and their use * constitutes a security risk. If possible, we recommend avoiding * dependencies on them, and considering stronger message digests * and ciphers instead. @@ -521,13 +442,9 @@ * alternative implementations should use the RNG only for generating * the ephemeral key and nothing else. If this is not possible, then * MBEDTLS_ECDSA_DETERMINISTIC should be disabled and an alternative - * implementation should be provided for mbedtls_ecdsa_sign_det_ext() - * (and for mbedtls_ecdsa_sign_det() too if backward compatibility is - * desirable). + * implementation should be provided for mbedtls_ecdsa_sign_det_ext(). * */ -//#define MBEDTLS_MD2_PROCESS_ALT -//#define MBEDTLS_MD4_PROCESS_ALT //#define MBEDTLS_MD5_PROCESS_ALT //#define MBEDTLS_RIPEMD160_PROCESS_ALT //#define MBEDTLS_SHA1_PROCESS_ALT @@ -611,23 +528,6 @@ //#define MBEDTLS_ECP_RANDOMIZE_MXZ_ALT //#define MBEDTLS_ECP_NORMALIZE_MXZ_ALT -/** - * \def MBEDTLS_TEST_NULL_ENTROPY - * - * Enables testing and use of Mbed TLS without any configured entropy sources. - * This permits use of the library on platforms before an entropy source has - * been integrated (see for example the MBEDTLS_ENTROPY_HARDWARE_ALT or the - * MBEDTLS_ENTROPY_NV_SEED switches). - * - * WARNING! This switch MUST be disabled in production builds, and is suitable - * only for development. - * Enabling the switch negates any security provided by the library. - * - * Requires MBEDTLS_ENTROPY_C, MBEDTLS_NO_DEFAULT_ENTROPY_SOURCES - * - */ -//#define MBEDTLS_TEST_NULL_ENTROPY - /** * \def MBEDTLS_ENTROPY_HARDWARE_ALT * @@ -635,7 +535,8 @@ * hardware entropy collector. * * Your function must be called \c mbedtls_hardware_poll(), have the same - * prototype as declared in entropy_poll.h, and accept NULL as first argument. + * prototype as declared in library/entropy_poll.h, and accept NULL as first + * argument. * * Uncomment to use your own hardware entropy collector. */ @@ -657,7 +558,6 @@ * performance if ROM access is slower than RAM access. * * This option is independent of \c MBEDTLS_AES_FEWER_TABLES. - * */ //#define MBEDTLS_AES_ROM_TABLES @@ -679,10 +579,40 @@ * depends on the system and memory details. * * This option is independent of \c MBEDTLS_AES_ROM_TABLES. - * */ //#define MBEDTLS_AES_FEWER_TABLES +/** + * \def MBEDTLS_AES_ONLY_128_BIT_KEY_LENGTH + * + * Use only 128-bit keys in AES operations to save ROM. + * + * Uncomment this macro to remove support for AES operations that use 192- + * or 256-bit keys. + * + * Uncommenting this macro reduces the size of AES code by ~300 bytes + * on v8-M/Thumb2. + * + * Module: library/aes.c + * + * Requires: MBEDTLS_AES_C + */ +//#define MBEDTLS_AES_ONLY_128_BIT_KEY_LENGTH + +/* + * Disable plain C implementation for AES. + * + * When the plain C implementation is enabled, and an implementation using a + * special CPU feature (such as MBEDTLS_AESCE_C) is also enabled, runtime + * detection will be used to select between them. + * + * If only one implementation is present, runtime detection will not be used. + * This configuration will crash at runtime if running on a CPU without the + * necessary features. It will not build unless at least one of MBEDTLS_AESCE_C + * and/or MBEDTLS_AESNI_C is enabled & present in the build. + */ +//#define MBEDTLS_AES_USE_HARDWARE_ONLY + /** * \def MBEDTLS_CAMELLIA_SMALL_MEMORY * @@ -757,8 +687,7 @@ * Warning: Only do so when you know what you are doing. This allows for * encryption or channels without any security! * - * Requires MBEDTLS_ENABLE_WEAK_CIPHERSUITES as well to enable - * the following ciphersuites: + * To enable the following ciphersuites: * MBEDTLS_TLS_ECDH_ECDSA_WITH_NULL_SHA * MBEDTLS_TLS_ECDH_RSA_WITH_NULL_SHA * MBEDTLS_TLS_ECDHE_ECDSA_WITH_NULL_SHA @@ -802,67 +731,20 @@ /** \def MBEDTLS_CTR_DRBG_USE_128_BIT_KEY * * Uncomment this macro to use a 128-bit key in the CTR_DRBG module. - * By default, CTR_DRBG uses a 256-bit key. + * Without this, CTR_DRBG uses a 256-bit key + * unless \c MBEDTLS_AES_ONLY_128_BIT_KEY_LENGTH is set. */ //#define MBEDTLS_CTR_DRBG_USE_128_BIT_KEY -/** - * \def MBEDTLS_ENABLE_WEAK_CIPHERSUITES - * - * Enable weak ciphersuites in SSL / TLS. - * Warning: Only do so when you know what you are doing. This allows for - * channels with virtually no security at all! - * - * This enables the following ciphersuites: - * MBEDTLS_TLS_RSA_WITH_DES_CBC_SHA - * MBEDTLS_TLS_DHE_RSA_WITH_DES_CBC_SHA - * - * Uncomment this macro to enable weak ciphersuites - * - * \warning DES is considered a weak cipher and its use constitutes a - * security risk. We recommend considering stronger ciphers instead. - */ -//#define MBEDTLS_ENABLE_WEAK_CIPHERSUITES - -/** - * \def MBEDTLS_REMOVE_ARC4_CIPHERSUITES - * - * Remove RC4 ciphersuites by default in SSL / TLS. - * This flag removes the ciphersuites based on RC4 from the default list as - * returned by mbedtls_ssl_list_ciphersuites(). However, it is still possible to - * enable (some of) them with mbedtls_ssl_conf_ciphersuites() by including them - * explicitly. - * - * Uncomment this macro to remove RC4 ciphersuites by default. - */ -#define MBEDTLS_REMOVE_ARC4_CIPHERSUITES - -/** - * \def MBEDTLS_REMOVE_3DES_CIPHERSUITES - * - * Remove 3DES ciphersuites by default in SSL / TLS. - * This flag removes the ciphersuites based on 3DES from the default list as - * returned by mbedtls_ssl_list_ciphersuites(). However, it is still possible - * to enable (some of) them with mbedtls_ssl_conf_ciphersuites() by including - * them explicitly. - * - * A man-in-the-browser attacker can recover authentication tokens sent through - * a TLS connection using a 3DES based cipher suite (see "On the Practical - * (In-)Security of 64-bit Block Ciphers" by Karthikeyan Bhargavan and Gaëtan - * Leurent, see https://sweet32.info/SWEET32_CCS16.pdf). If this attack falls - * in your threat model or you are unsure, then you should keep this option - * enabled to remove 3DES based cipher suites. - * - * Comment this macro to keep 3DES in the default ciphersuite list. - */ -#define MBEDTLS_REMOVE_3DES_CIPHERSUITES - /** * Enable the verified implementations of ECDH primitives from Project Everest * (currently only Curve25519). This feature changes the layout of ECDH * contexts and therefore is a compatibility break for applications that access * fields of a mbedtls_ecdh_context structure directly. See also * MBEDTLS_ECDH_LEGACY_CONTEXT in include/mbedtls/ecdh.h. + * + * The Everest code is provided under the Apache 2.0 license only; therefore enabling this + * option is not compatible with taking the library under the GPL v2.0-or-later license. */ //#define MBEDTLS_ECDH_VARIANT_EVEREST_ENABLED @@ -901,28 +783,6 @@ */ #define MBEDTLS_ECP_NIST_OPTIM -/** - * \def MBEDTLS_ECP_NO_INTERNAL_RNG - * - * When this option is disabled, mbedtls_ecp_mul() will make use of an - * internal RNG when called with a NULL \c f_rng argument, in order to protect - * against some side-channel attacks. - * - * This protection introduces a dependency of the ECP module on one of the - * DRBG modules. For very constrained implementations that don't require this - * protection (for example, because you're only doing signature verification, - * so not manipulating any secret, or because local/physical side-channel - * attacks are outside your threat model), it might be desirable to get rid of - * that dependency. - * - * \warning Enabling this option makes some uses of ECP vulnerable to some - * side-channel attacks. Only enable it if you know that's not a problem for - * your use case. - * - * Uncomment this macro to disable some counter-measures in ECP. - */ -//#define MBEDTLS_ECP_NO_INTERNAL_RNG - /** * \def MBEDTLS_ECP_RESTARTABLE * @@ -952,7 +812,7 @@ * ECDHE-ECDSA key exchange (not other key exchanges) to make all ECC * computations restartable: * - ECDH operations from the key exchange, only for Short Weierstrass - * curves; + * curves, only when MBEDTLS_USE_PSA_CRYPTO is not enabled. * - verification of the server's key exchange signature; * - verification of the server's certificate chain; * - generation of the client's signature if client authentication is used, @@ -962,10 +822,15 @@ * mbedtls_ssl_handshake(), can now return * MBEDTLS_ERR_SSL_CRYPTO_IN_PROGRESS. * + * \note When this option and MBEDTLS_USE_PSA_CRYPTO are both enabled, + * restartable operations in PK, X.509 and TLS (see above) are not + * using PSA. On the other hand, ECDH computations in TLS are using + * PSA, and are not restartable. These are temporary limitations that + * should be lifted in the future. + * * \note This option only works with the default software implementation of * elliptic curve functionality. It is incompatible with - * MBEDTLS_ECP_ALT, MBEDTLS_ECDH_XXX_ALT, MBEDTLS_ECDSA_XXX_ALT, - * MBEDTLS_ECDH_LEGACY_CONTEXT, and MBEDTLS_USE_PSA_CRYPTO. + * MBEDTLS_ECP_ALT, MBEDTLS_ECDH_XXX_ALT, MBEDTLS_ECDSA_XXX_ALT. * * Requires: MBEDTLS_ECP_C * @@ -974,32 +839,12 @@ //#define MBEDTLS_ECP_RESTARTABLE /** - * \def MBEDTLS_ECDH_LEGACY_CONTEXT - * - * Use a backward compatible ECDH context. + * Uncomment to enable using new bignum code in the ECC modules. * - * Mbed TLS supports two formats for ECDH contexts (#mbedtls_ecdh_context - * defined in `ecdh.h`). For most applications, the choice of format makes - * no difference, since all library functions can work with either format, - * except that the new format is incompatible with MBEDTLS_ECP_RESTARTABLE. - - * The new format used when this option is disabled is smaller - * (56 bytes on a 32-bit platform). In future versions of the library, it - * will support alternative implementations of ECDH operations. - * The new format is incompatible with applications that access - * context fields directly and with restartable ECP operations. - * - * Define this macro if you enable MBEDTLS_ECP_RESTARTABLE or if you - * want to access ECDH context fields directly. Otherwise you should - * comment out this macro definition. - * - * This option has no effect if #MBEDTLS_ECDH_C is not enabled. - * - * \note This configuration option is experimental. Future versions of the - * library may modify the way the ECDH context layout is configured - * and may modify the layout of the new context type. + * \warning This is currently experimental, incomplete and therefore should not + * be used in production. */ -#define MBEDTLS_ECDH_LEGACY_CONTEXT +//#define MBEDTLS_ECP_WITH_MPI_UINT /** * \def MBEDTLS_ECDSA_DETERMINISTIC @@ -1032,8 +877,6 @@ * MBEDTLS_TLS_PSK_WITH_AES_128_CBC_SHA * MBEDTLS_TLS_PSK_WITH_CAMELLIA_128_GCM_SHA256 * MBEDTLS_TLS_PSK_WITH_CAMELLIA_128_CBC_SHA256 - * MBEDTLS_TLS_PSK_WITH_3DES_EDE_CBC_SHA - * MBEDTLS_TLS_PSK_WITH_RC4_128_SHA */ #define MBEDTLS_KEY_EXCHANGE_PSK_ENABLED @@ -1056,8 +899,6 @@ * MBEDTLS_TLS_DHE_PSK_WITH_AES_128_CBC_SHA * MBEDTLS_TLS_DHE_PSK_WITH_CAMELLIA_128_GCM_SHA256 * MBEDTLS_TLS_DHE_PSK_WITH_CAMELLIA_128_CBC_SHA256 - * MBEDTLS_TLS_DHE_PSK_WITH_3DES_EDE_CBC_SHA - * MBEDTLS_TLS_DHE_PSK_WITH_RC4_128_SHA * * \warning Using DHE constitutes a security risk as it * is not possible to validate custom DH parameters. @@ -1073,7 +914,7 @@ * * Enable the ECDHE-PSK based ciphersuite modes in SSL / TLS. * - * Requires: MBEDTLS_ECDH_C + * Requires: MBEDTLS_ECDH_C or (MBEDTLS_USE_PSA_CRYPTO and PSA_WANT_ALG_ECDH) * * This enables the following ciphersuites (if other requisites are * enabled as well): @@ -1083,8 +924,6 @@ * MBEDTLS_TLS_ECDHE_PSK_WITH_AES_128_CBC_SHA256 * MBEDTLS_TLS_ECDHE_PSK_WITH_AES_128_CBC_SHA * MBEDTLS_TLS_ECDHE_PSK_WITH_CAMELLIA_128_CBC_SHA256 - * MBEDTLS_TLS_ECDHE_PSK_WITH_3DES_EDE_CBC_SHA - * MBEDTLS_TLS_ECDHE_PSK_WITH_RC4_128_SHA */ #define MBEDTLS_KEY_EXCHANGE_ECDHE_PSK_ENABLED @@ -1108,8 +947,6 @@ * MBEDTLS_TLS_RSA_PSK_WITH_AES_128_CBC_SHA * MBEDTLS_TLS_RSA_PSK_WITH_CAMELLIA_128_GCM_SHA256 * MBEDTLS_TLS_RSA_PSK_WITH_CAMELLIA_128_CBC_SHA256 - * MBEDTLS_TLS_RSA_PSK_WITH_3DES_EDE_CBC_SHA - * MBEDTLS_TLS_RSA_PSK_WITH_RC4_128_SHA */ #define MBEDTLS_KEY_EXCHANGE_RSA_PSK_ENABLED @@ -1135,9 +972,6 @@ * MBEDTLS_TLS_RSA_WITH_CAMELLIA_128_GCM_SHA256 * MBEDTLS_TLS_RSA_WITH_CAMELLIA_128_CBC_SHA256 * MBEDTLS_TLS_RSA_WITH_CAMELLIA_128_CBC_SHA - * MBEDTLS_TLS_RSA_WITH_3DES_EDE_CBC_SHA - * MBEDTLS_TLS_RSA_WITH_RC4_128_SHA - * MBEDTLS_TLS_RSA_WITH_RC4_128_MD5 */ #define MBEDTLS_KEY_EXCHANGE_RSA_ENABLED @@ -1163,7 +997,6 @@ * MBEDTLS_TLS_DHE_RSA_WITH_CAMELLIA_128_GCM_SHA256 * MBEDTLS_TLS_DHE_RSA_WITH_CAMELLIA_128_CBC_SHA256 * MBEDTLS_TLS_DHE_RSA_WITH_CAMELLIA_128_CBC_SHA - * MBEDTLS_TLS_DHE_RSA_WITH_3DES_EDE_CBC_SHA * * \warning Using DHE constitutes a security risk as it * is not possible to validate custom DH parameters. @@ -1179,7 +1012,9 @@ * * Enable the ECDHE-RSA based ciphersuite modes in SSL / TLS. * - * Requires: MBEDTLS_ECDH_C, MBEDTLS_RSA_C, MBEDTLS_PKCS1_V15, + * Requires: MBEDTLS_ECDH_C or (MBEDTLS_USE_PSA_CRYPTO and PSA_WANT_ALG_ECDH) + * MBEDTLS_RSA_C + * MBEDTLS_PKCS1_V15 * MBEDTLS_X509_CRT_PARSE_C * * This enables the following ciphersuites (if other requisites are @@ -1194,8 +1029,6 @@ * MBEDTLS_TLS_ECDHE_RSA_WITH_AES_128_CBC_SHA * MBEDTLS_TLS_ECDHE_RSA_WITH_CAMELLIA_128_GCM_SHA256 * MBEDTLS_TLS_ECDHE_RSA_WITH_CAMELLIA_128_CBC_SHA256 - * MBEDTLS_TLS_ECDHE_RSA_WITH_3DES_EDE_CBC_SHA - * MBEDTLS_TLS_ECDHE_RSA_WITH_RC4_128_SHA */ #define MBEDTLS_KEY_EXCHANGE_ECDHE_RSA_ENABLED @@ -1204,7 +1037,9 @@ * * Enable the ECDHE-ECDSA based ciphersuite modes in SSL / TLS. * - * Requires: MBEDTLS_ECDH_C, MBEDTLS_ECDSA_C, MBEDTLS_X509_CRT_PARSE_C, + * Requires: MBEDTLS_ECDH_C or (MBEDTLS_USE_PSA_CRYPTO and PSA_WANT_ALG_ECDH) + * MBEDTLS_ECDSA_C or (MBEDTLS_USE_PSA_CRYPTO and PSA_WANT_ALG_ECDSA) + * MBEDTLS_X509_CRT_PARSE_C * * This enables the following ciphersuites (if other requisites are * enabled as well): @@ -1218,8 +1053,6 @@ * MBEDTLS_TLS_ECDHE_ECDSA_WITH_AES_128_CBC_SHA * MBEDTLS_TLS_ECDHE_ECDSA_WITH_CAMELLIA_128_GCM_SHA256 * MBEDTLS_TLS_ECDHE_ECDSA_WITH_CAMELLIA_128_CBC_SHA256 - * MBEDTLS_TLS_ECDHE_ECDSA_WITH_3DES_EDE_CBC_SHA - * MBEDTLS_TLS_ECDHE_ECDSA_WITH_RC4_128_SHA */ #define MBEDTLS_KEY_EXCHANGE_ECDHE_ECDSA_ENABLED @@ -1228,12 +1061,12 @@ * * Enable the ECDH-ECDSA based ciphersuite modes in SSL / TLS. * - * Requires: MBEDTLS_ECDH_C, MBEDTLS_ECDSA_C, MBEDTLS_X509_CRT_PARSE_C + * Requires: MBEDTLS_ECDH_C or (MBEDTLS_USE_PSA_CRYPTO and PSA_WANT_ALG_ECDH) + * MBEDTLS_ECDSA_C or (MBEDTLS_USE_PSA_CRYPTO and PSA_WANT_ALG_ECDSA) + * MBEDTLS_X509_CRT_PARSE_C * * This enables the following ciphersuites (if other requisites are * enabled as well): - * MBEDTLS_TLS_ECDH_ECDSA_WITH_RC4_128_SHA - * MBEDTLS_TLS_ECDH_ECDSA_WITH_3DES_EDE_CBC_SHA * MBEDTLS_TLS_ECDH_ECDSA_WITH_AES_128_CBC_SHA * MBEDTLS_TLS_ECDH_ECDSA_WITH_AES_256_CBC_SHA * MBEDTLS_TLS_ECDH_ECDSA_WITH_AES_128_CBC_SHA256 @@ -1252,12 +1085,12 @@ * * Enable the ECDH-RSA based ciphersuite modes in SSL / TLS. * - * Requires: MBEDTLS_ECDH_C, MBEDTLS_RSA_C, MBEDTLS_X509_CRT_PARSE_C + * Requires: MBEDTLS_ECDH_C or (MBEDTLS_USE_PSA_CRYPTO and PSA_WANT_ALG_ECDH) + * MBEDTLS_RSA_C + * MBEDTLS_X509_CRT_PARSE_C * * This enables the following ciphersuites (if other requisites are * enabled as well): - * MBEDTLS_TLS_ECDH_RSA_WITH_RC4_128_SHA - * MBEDTLS_TLS_ECDH_RSA_WITH_3DES_EDE_CBC_SHA * MBEDTLS_TLS_ECDH_RSA_WITH_AES_128_CBC_SHA * MBEDTLS_TLS_ECDH_RSA_WITH_AES_256_CBC_SHA * MBEDTLS_TLS_ECDH_RSA_WITH_AES_128_CBC_SHA256 @@ -1280,10 +1113,14 @@ * Thread v1.0.0 specification; incompatible changes to the specification * might still happen. For this reason, this is disabled by default. * - * Requires: MBEDTLS_ECJPAKE_C - * MBEDTLS_SHA256_C + * Requires: MBEDTLS_ECJPAKE_C or (MBEDTLS_USE_PSA_CRYPTO and PSA_WANT_ALG_JPAKE) + * SHA-256 (via MBEDTLS_SHA256_C or a PSA driver) * MBEDTLS_ECP_DP_SECP256R1_ENABLED * + * \warning If SHA-256 is provided only by a PSA driver, you must call + * psa_crypto_init() before the first hanshake (even if + * MBEDTLS_USE_PSA_CRYPTO is disabled). + * * This enables the following ciphersuites (if other requisites are * enabled as well): * MBEDTLS_TLS_ECJPAKE_WITH_AES_128_CCM_8 @@ -1304,6 +1141,19 @@ */ #define MBEDTLS_PK_PARSE_EC_EXTENDED +/** + * \def MBEDTLS_PK_PARSE_EC_COMPRESSED + * + * Enable the support for parsing public keys of type Short Weierstrass + * (MBEDTLS_ECP_DP_SECP_XXX and MBEDTLS_ECP_DP_BP_XXX) which are using the + * compressed point format. This parsing is done through ECP module's functions. + * + * \note As explained in the description of MBEDTLS_ECP_PF_COMPRESSED (in ecp.h) + * the only unsupported curves are MBEDTLS_ECP_DP_SECP224R1 and + * MBEDTLS_ECP_DP_SECP224K1. + */ +#define MBEDTLS_PK_PARSE_EC_COMPRESSED + /** * \def MBEDTLS_ERROR_STRERROR_DUMMY * @@ -1338,8 +1188,7 @@ /** * \def MBEDTLS_NO_DEFAULT_ENTROPY_SOURCES * - * Do not add default entropy sources. These are the platform specific, - * mbedtls_timing_hardclock and HAVEGE based poll functions. + * Do not add default entropy sources in mbedtls_entropy_init(). * * This is useful to have more control over the added entropy sources in an * application. @@ -1411,7 +1260,7 @@ * which is currently hard-coded to be int32_t. * * Note that this option is meant for internal use only and may be removed - * without notice. It is incompatible with MBEDTLS_USE_PSA_CRYPTO. + * without notice. */ //#define MBEDTLS_PSA_CRYPTO_KEY_ID_ENCODES_OWNER @@ -1465,7 +1314,10 @@ * * Enable support for PKCS#1 v2.1 encoding. * - * Requires: MBEDTLS_MD_C, MBEDTLS_RSA_C + * Requires: MBEDTLS_RSA_C + * + * \warning If using a hash that is only provided by PSA drivers, you must + * call psa_crypto_init() before doing any PKCS#1 v2.1 operation. * * This enables support for RSAES-OAEP and RSASSA-PSS operations. */ @@ -1503,17 +1355,6 @@ */ //#define MBEDTLS_PSA_CRYPTO_CLIENT -/** \def MBEDTLS_PSA_CRYPTO_DRIVERS - * - * Enable support for the experimental PSA crypto driver interface. - * - * Requires: MBEDTLS_PSA_CRYPTO_C - * - * \warning This interface is experimental and may change or be removed - * without notice. - */ -//#define MBEDTLS_PSA_CRYPTO_DRIVERS - /** \def MBEDTLS_PSA_CRYPTO_EXTERNAL_RNG * * Make the PSA Crypto module use an external random generator provided @@ -1560,12 +1401,60 @@ * NSPE (Non-Secure Process Environment) and an SPE (Secure Process * Environment). * + * If you enable this option, your build environment must include a header + * file `"crypto_spe.h"` (either in the `psa` subdirectory of the Mbed TLS + * header files, or in another directory on the compiler's include search + * path). Alternatively, your platform may customize the header + * `psa/crypto_platform.h`, in which case it can skip or replace the + * inclusion of `"crypto_spe.h"`. + * * Module: library/psa_crypto.c * Requires: MBEDTLS_PSA_CRYPTO_C * */ //#define MBEDTLS_PSA_CRYPTO_SPM +/** + * Uncomment to enable p256-m. This is an alternative implementation of + * key generation, ECDH and (randomized) ECDSA on the curve SECP256R1. + * Compared to the default implementation: + * + * - p256-m has a much smaller code size and RAM footprint. + * - p256-m is only available via the PSA API. This includes the pk module + * when #MBEDTLS_USE_PSA_CRYPTO is enabled. + * - p256-m does not support deterministic ECDSA, EC-JPAKE, custom protocols + * over the core arithmetic, or deterministic derivation of keys. + * + * We recommend enabling this option if your application uses the PSA API + * and the only elliptic curve support it needs is ECDH and ECDSA over + * SECP256R1. + * + * If you enable this option, you do not need to enable any ECC-related + * MBEDTLS_xxx option. You do need to separately request support for the + * cryptographic mechanisms through the PSA API: + * - #MBEDTLS_PSA_CRYPTO_C and #MBEDTLS_PSA_CRYPTO_CONFIG for PSA-based + * configuration; + * - #MBEDTLS_USE_PSA_CRYPTO if you want to use p256-m from PK, X.509 or TLS; + * - #PSA_WANT_ECC_SECP_R1_256; + * - #PSA_WANT_ALG_ECDH and/or #PSA_WANT_ALG_ECDSA as needed; + * - #PSA_WANT_KEY_TYPE_ECC_PUBLIC_KEY, #PSA_WANT_KEY_TYPE_ECC_KEY_PAIR_BASIC, + * #PSA_WANT_KEY_TYPE_ECC_KEY_PAIR_IMPORT, + * #PSA_WANT_KEY_TYPE_ECC_KEY_PAIR_EXPORT and/or + * #PSA_WANT_KEY_TYPE_ECC_KEY_PAIR_GENERATE as needed. + * + * \note To benefit from the smaller code size of p256-m, make sure that you + * do not enable any ECC-related option not supported by p256-m: this + * would cause the built-in ECC implementation to be built as well, in + * order to provide the required option. + * Make sure #PSA_WANT_ALG_DETERMINISTIC_ECDSA, #PSA_WANT_ALG_JPAKE and + * #PSA_WANT_KEY_TYPE_ECC_KEY_PAIR_DERIVE, and curves other than + * SECP256R1 are disabled as they are not supported by this driver. + * Also, avoid defining #MBEDTLS_PK_PARSE_EC_COMPRESSED or + * #MBEDTLS_PK_PARSE_EC_EXTENDED as those currently require a subset of + * the built-in ECC implementation, see docs/driver-only-builds.md. + */ +//#define MBEDTLS_PSA_P256M_DRIVER_ENABLED + /** * \def MBEDTLS_PSA_INJECT_ENTROPY * @@ -1579,6 +1468,26 @@ */ //#define MBEDTLS_PSA_INJECT_ENTROPY +/** + * \def MBEDTLS_PSA_ASSUME_EXCLUSIVE_BUFFERS + * + * Assume all buffers passed to PSA functions are owned exclusively by the + * PSA function and are not stored in shared memory. + * + * This option may be enabled if all buffers passed to any PSA function reside + * in memory that is accessible only to the PSA function during its execution. + * + * This option MUST be disabled whenever buffer arguments are in memory shared + * with an untrusted party, for example where arguments to PSA calls are passed + * across a trust boundary. + * + * \note Enabling this option reduces memory usage and code size. + * + * \note Enabling this option causes overlap of input and output buffers + * not to be supported by PSA functions. + */ +//#define MBEDTLS_PSA_ASSUME_EXCLUSIVE_BUFFERS + /** * \def MBEDTLS_RSA_NO_CRT * @@ -1623,18 +1532,6 @@ */ //#define MBEDTLS_SHA512_SMALLER -/** - * \def MBEDTLS_SHA512_NO_SHA384 - * - * Disable the SHA-384 option of the SHA-512 module. Use this to save some - * code size on devices that don't use SHA-384. - * - * Requires: MBEDTLS_SHA512_C - * - * Uncomment to disable SHA-384 - */ -//#define MBEDTLS_SHA512_NO_SHA384 - /** * \def MBEDTLS_SSL_ALL_ALERT_MESSAGES * @@ -1649,36 +1546,18 @@ */ #define MBEDTLS_SSL_ALL_ALERT_MESSAGES -/** - * \def MBEDTLS_SSL_RECORD_CHECKING - * - * Enable the function mbedtls_ssl_check_record() which can be used to check - * the validity and authenticity of an incoming record, to verify that it has - * not been seen before. These checks are performed without modifying the - * externally visible state of the SSL context. - * - * See mbedtls_ssl_check_record() for more information. - * - * Uncomment to enable support for record checking. - */ -#define MBEDTLS_SSL_RECORD_CHECKING - /** * \def MBEDTLS_SSL_DTLS_CONNECTION_ID * - * Enable support for the DTLS Connection ID extension - * (version draft-ietf-tls-dtls-connection-id-05, - * https://tools.ietf.org/html/draft-ietf-tls-dtls-connection-id-05) + * Enable support for the DTLS Connection ID (CID) extension, * which allows to identify DTLS connections across changes - * in the underlying transport. + * in the underlying transport. The CID functionality is described + * in RFC 9146. * * Setting this option enables the SSL APIs `mbedtls_ssl_set_cid()`, - * `mbedtls_ssl_get_peer_cid()` and `mbedtls_ssl_conf_cid()`. - * See the corresponding documentation for more information. - * - * \warning The Connection ID extension is still in draft state. - * We make no stability promises for the availability - * or the shape of the API controlled by this option. + * mbedtls_ssl_get_own_cid()`, `mbedtls_ssl_get_peer_cid()` and + * `mbedtls_ssl_conf_cid()`. See the corresponding documentation for + * more information. * * The maximum lengths of outgoing and incoming CIDs can be configured * through the options @@ -1689,7 +1568,30 @@ * * Uncomment to enable the Connection ID extension. */ -//#define MBEDTLS_SSL_DTLS_CONNECTION_ID +#define MBEDTLS_SSL_DTLS_CONNECTION_ID + + +/** + * \def MBEDTLS_SSL_DTLS_CONNECTION_ID_COMPAT + * + * Defines whether RFC 9146 (default) or the legacy version + * (version draft-ietf-tls-dtls-connection-id-05, + * https://tools.ietf.org/html/draft-ietf-tls-dtls-connection-id-05) + * is used. + * + * Set the value to 0 for the standard version, and + * 1 for the legacy draft version. + * + * \deprecated Support for the legacy version of the DTLS + * Connection ID feature is deprecated. Please + * switch to the standardized version defined + * in RFC 9146 enabled by utilizing + * MBEDTLS_SSL_DTLS_CONNECTION_ID without use + * of MBEDTLS_SSL_DTLS_CONNECTION_ID_COMPAT. + * + * Requires: MBEDTLS_SSL_DTLS_CONNECTION_ID + */ +#define MBEDTLS_SSL_DTLS_CONNECTION_ID_COMPAT 0 /** * \def MBEDTLS_SSL_ASYNC_PRIVATE @@ -1699,6 +1601,7 @@ * module to perform private key operations instead of performing the * operation inside the library. * + * Requires: MBEDTLS_X509_CRT_PARSE_C */ //#define MBEDTLS_SSL_ASYNC_PRIVATE @@ -1757,9 +1660,7 @@ * * This only affects CBC ciphersuites, and is useless if none is defined. * - * Requires: MBEDTLS_SSL_PROTO_TLS1 or - * MBEDTLS_SSL_PROTO_TLS1_1 or - * MBEDTLS_SSL_PROTO_TLS1_2 + * Requires: MBEDTLS_SSL_PROTO_TLS1_2 * * Comment this macro to disable support for Encrypt-then-MAC */ @@ -1775,32 +1676,12 @@ * renegotiation), since it actually fixes a more fundamental issue in the * original SSL/TLS design, and has implications beyond Triple Handshake. * - * Requires: MBEDTLS_SSL_PROTO_TLS1 or - * MBEDTLS_SSL_PROTO_TLS1_1 or - * MBEDTLS_SSL_PROTO_TLS1_2 + * Requires: MBEDTLS_SSL_PROTO_TLS1_2 * * Comment this macro to disable support for Extended Master Secret. */ #define MBEDTLS_SSL_EXTENDED_MASTER_SECRET -/** - * \def MBEDTLS_SSL_FALLBACK_SCSV - * - * Enable support for RFC 7507: Fallback Signaling Cipher Suite Value (SCSV) - * for Preventing Protocol Downgrade Attacks. - * - * For servers, it is recommended to always enable this, unless you support - * only one version of TLS, or know for sure that none of your clients - * implements a fallback strategy. - * - * For clients, you only need this if you're using a fallback strategy, which - * is not recommended in the first place, unless you absolutely need it to - * interoperate with buggy (version-intolerant) servers. - * - * Comment this macro to disable support for FALLBACK_SCSV - */ -#define MBEDTLS_SSL_FALLBACK_SCSV - /** * \def MBEDTLS_SSL_KEEP_PEER_CERTIFICATE * @@ -1818,36 +1699,13 @@ * still ensure that certificates do not change during renegotiation, * for example by keeping a hash of the peer's certificate. * + * \note This option is required if MBEDTLS_SSL_PROTO_TLS1_3 is set. + * * Comment this macro to disable storing the peer's certificate * after the handshake. */ #define MBEDTLS_SSL_KEEP_PEER_CERTIFICATE -/** - * \def MBEDTLS_SSL_HW_RECORD_ACCEL - * - * Enable hooking functions in SSL module for hardware acceleration of - * individual records. - * - * \deprecated This option is deprecated and will be removed in a future - * version of Mbed TLS. - * - * Uncomment this macro to enable hooking functions. - */ -//#define MBEDTLS_SSL_HW_RECORD_ACCEL - -/** - * \def MBEDTLS_SSL_CBC_RECORD_SPLITTING - * - * Enable 1/n-1 record splitting for CBC mode in SSLv3 and TLS 1.0. - * - * This is a countermeasure to the BEAST attack, which also minimizes the risk - * of interoperability issues compared to sending 0-length records. - * - * Comment this macro to disable 1/n-1 record splitting. - */ -#define MBEDTLS_SSL_CBC_RECORD_SPLITTING - /** * \def MBEDTLS_SSL_RENEGOTIATION * @@ -1859,6 +1717,8 @@ * it has been associated with security issues in the past and is easy to * misuse/misunderstand. * + * Requires: MBEDTLS_SSL_PROTO_TLS1_2 + * * Comment this to disable support for renegotiation. * * \note Even if this option is disabled, both client and server are aware @@ -1871,117 +1731,160 @@ #define MBEDTLS_SSL_RENEGOTIATION /** - * \def MBEDTLS_SSL_SRV_SUPPORT_SSLV2_CLIENT_HELLO + * \def MBEDTLS_SSL_MAX_FRAGMENT_LENGTH + * + * Enable support for RFC 6066 max_fragment_length extension in SSL. + * + * Comment this macro to disable support for the max_fragment_length extension + */ +#define MBEDTLS_SSL_MAX_FRAGMENT_LENGTH + +/** + * \def MBEDTLS_SSL_RECORD_SIZE_LIMIT * - * Enable support for receiving and parsing SSLv2 Client Hello messages for the - * SSL Server module (MBEDTLS_SSL_SRV_C). + * Enable support for RFC 8449 record_size_limit extension in SSL (TLS 1.3 only). * - * \deprecated This option is deprecated and will be removed in a future - * version of Mbed TLS. + * Requires: MBEDTLS_SSL_PROTO_TLS1_3 * - * Uncomment this macro to enable support for SSLv2 Client Hello messages. + * Uncomment this macro to enable support for the record_size_limit extension */ -//#define MBEDTLS_SSL_SRV_SUPPORT_SSLV2_CLIENT_HELLO +//#define MBEDTLS_SSL_RECORD_SIZE_LIMIT /** - * \def MBEDTLS_SSL_SRV_RESPECT_CLIENT_PREFERENCE + * \def MBEDTLS_SSL_PROTO_TLS1_2 * - * Pick the ciphersuite according to the client's preferences rather than ours - * in the SSL Server module (MBEDTLS_SSL_SRV_C). + * Enable support for TLS 1.2 (and DTLS 1.2 if DTLS is enabled). + * + * Requires: Without MBEDTLS_USE_PSA_CRYPTO: MBEDTLS_MD_C and + * (MBEDTLS_SHA256_C or MBEDTLS_SHA384_C or + * SHA-256 or SHA-512 provided by a PSA driver) + * With MBEDTLS_USE_PSA_CRYPTO: + * PSA_WANT_ALG_SHA_256 or PSA_WANT_ALG_SHA_384 * - * Uncomment this macro to respect client's ciphersuite order + * \warning If building with MBEDTLS_USE_PSA_CRYPTO, or if the hash(es) used + * are only provided by PSA drivers, you must call psa_crypto_init() before + * doing any TLS operations. + * + * Comment this macro to disable support for TLS 1.2 / DTLS 1.2 */ -//#define MBEDTLS_SSL_SRV_RESPECT_CLIENT_PREFERENCE +#define MBEDTLS_SSL_PROTO_TLS1_2 /** - * \def MBEDTLS_SSL_MAX_FRAGMENT_LENGTH + * \def MBEDTLS_SSL_PROTO_TLS1_3 * - * Enable support for RFC 6066 max_fragment_length extension in SSL. + * Enable support for TLS 1.3. * - * Comment this macro to disable support for the max_fragment_length extension + * \note See docs/architecture/tls13-support.md for a description of the TLS + * 1.3 support that this option enables. + * + * Requires: MBEDTLS_SSL_KEEP_PEER_CERTIFICATE + * Requires: MBEDTLS_PSA_CRYPTO_C + * + * \note TLS 1.3 uses PSA crypto for cryptographic operations that are + * directly performed by TLS 1.3 code. As a consequence, you must + * call psa_crypto_init() before the first TLS 1.3 handshake. + * + * \note Cryptographic operations performed indirectly via another module + * (X.509, PK) or by code shared with TLS 1.2 (record protection, + * running handshake hash) only use PSA crypto if + * #MBEDTLS_USE_PSA_CRYPTO is enabled. + * + * Uncomment this macro to enable the support for TLS 1.3. */ -#define MBEDTLS_SSL_MAX_FRAGMENT_LENGTH +#define MBEDTLS_SSL_PROTO_TLS1_3 /** - * \def MBEDTLS_SSL_PROTO_SSL3 + * \def MBEDTLS_SSL_TLS1_3_COMPATIBILITY_MODE * - * Enable support for SSL 3.0. + * Enable TLS 1.3 middlebox compatibility mode. * - * Requires: MBEDTLS_MD5_C - * MBEDTLS_SHA1_C + * As specified in Section D.4 of RFC 8446, TLS 1.3 offers a compatibility + * mode to make a TLS 1.3 connection more likely to pass through middle boxes + * expecting TLS 1.2 traffic. * - * \deprecated This option is deprecated and will be removed in a future - * version of Mbed TLS. + * Turning on the compatibility mode comes at the cost of a few added bytes + * on the wire, but it doesn't affect compatibility with TLS 1.3 implementations + * that don't use it. Therefore, unless transmission bandwidth is critical and + * you know that middlebox compatibility issues won't occur, it is therefore + * recommended to set this option. + * + * Comment to disable compatibility mode for TLS 1.3. If + * MBEDTLS_SSL_PROTO_TLS1_3 is not enabled, this option does not have any + * effect on the build. * - * Comment this macro to disable support for SSL 3.0 */ -//#define MBEDTLS_SSL_PROTO_SSL3 +#define MBEDTLS_SSL_TLS1_3_COMPATIBILITY_MODE /** - * \def MBEDTLS_SSL_PROTO_TLS1 + * \def MBEDTLS_SSL_TLS1_3_KEY_EXCHANGE_MODE_PSK_ENABLED * - * Enable support for TLS 1.0. + * Enable TLS 1.3 PSK key exchange mode. * - * Requires: MBEDTLS_MD5_C - * MBEDTLS_SHA1_C + * Comment to disable support for the PSK key exchange mode in TLS 1.3. If + * MBEDTLS_SSL_PROTO_TLS1_3 is not enabled, this option does not have any + * effect on the build. * - * Comment this macro to disable support for TLS 1.0 */ -#define MBEDTLS_SSL_PROTO_TLS1 +#define MBEDTLS_SSL_TLS1_3_KEY_EXCHANGE_MODE_PSK_ENABLED /** - * \def MBEDTLS_SSL_PROTO_TLS1_1 + * \def MBEDTLS_SSL_TLS1_3_KEY_EXCHANGE_MODE_EPHEMERAL_ENABLED + * + * Enable TLS 1.3 ephemeral key exchange mode. * - * Enable support for TLS 1.1 (and DTLS 1.0 if DTLS is enabled). + * Requires: PSA_WANT_ALG_ECDH or PSA_WANT_ALG_FFDH + * MBEDTLS_X509_CRT_PARSE_C + * and at least one of: + * MBEDTLS_ECDSA_C or (MBEDTLS_USE_PSA_CRYPTO and PSA_WANT_ALG_ECDSA) + * MBEDTLS_PKCS1_V21 * - * Requires: MBEDTLS_MD5_C - * MBEDTLS_SHA1_C + * Comment to disable support for the ephemeral key exchange mode in TLS 1.3. + * If MBEDTLS_SSL_PROTO_TLS1_3 is not enabled, this option does not have any + * effect on the build. * - * Comment this macro to disable support for TLS 1.1 / DTLS 1.0 */ -#define MBEDTLS_SSL_PROTO_TLS1_1 +#define MBEDTLS_SSL_TLS1_3_KEY_EXCHANGE_MODE_EPHEMERAL_ENABLED /** - * \def MBEDTLS_SSL_PROTO_TLS1_2 + * \def MBEDTLS_SSL_TLS1_3_KEY_EXCHANGE_MODE_PSK_EPHEMERAL_ENABLED * - * Enable support for TLS 1.2 (and DTLS 1.2 if DTLS is enabled). + * Enable TLS 1.3 PSK ephemeral key exchange mode. * - * Requires: MBEDTLS_SHA1_C or MBEDTLS_SHA256_C or MBEDTLS_SHA512_C - * (Depends on ciphersuites) + * Requires: PSA_WANT_ALG_ECDH or PSA_WANT_ALG_FFDH + * + * Comment to disable support for the PSK ephemeral key exchange mode in + * TLS 1.3. If MBEDTLS_SSL_PROTO_TLS1_3 is not enabled, this option does not + * have any effect on the build. * - * Comment this macro to disable support for TLS 1.2 / DTLS 1.2 */ -#define MBEDTLS_SSL_PROTO_TLS1_2 +#define MBEDTLS_SSL_TLS1_3_KEY_EXCHANGE_MODE_PSK_EPHEMERAL_ENABLED /** - * \def MBEDTLS_SSL_PROTO_TLS1_3_EXPERIMENTAL + * \def MBEDTLS_SSL_EARLY_DATA + * + * Enable support for RFC 8446 TLS 1.3 early data. + * + * Requires: MBEDTLS_SSL_SESSION_TICKETS and either + * MBEDTLS_SSL_TLS1_3_KEY_EXCHANGE_MODE_PSK_ENABLED or + * MBEDTLS_SSL_TLS1_3_KEY_EXCHANGE_MODE_PSK_EPHEMERAL_ENABLED * - * This macro is used to selectively enable experimental parts - * of the code that contribute to the ongoing development of - * the prototype TLS 1.3 and DTLS 1.3 implementation, and provide - * no other purpose. + * Comment this to disable support for early data. If MBEDTLS_SSL_PROTO_TLS1_3 + * is not enabled, this option does not have any effect on the build. * - * \warning TLS 1.3 and DTLS 1.3 aren't yet supported in Mbed TLS, - * and no feature exposed through this macro is part of the - * public API. In particular, features under the control - * of this macro are experimental and don't come with any - * stability guarantees. + * \note The maximum amount of early data can be set with + * MBEDTLS_SSL_MAX_EARLY_DATA_SIZE. * - * Uncomment this macro to enable experimental and partial - * functionality specific to TLS 1.3. */ -//#define MBEDTLS_SSL_PROTO_TLS1_3_EXPERIMENTAL +//#define MBEDTLS_SSL_EARLY_DATA /** * \def MBEDTLS_SSL_PROTO_DTLS * * Enable support for DTLS (all available versions). * - * Enable this and MBEDTLS_SSL_PROTO_TLS1_1 to enable DTLS 1.0, - * and/or this and MBEDTLS_SSL_PROTO_TLS1_2 to enable DTLS 1.2. + * Enable this and MBEDTLS_SSL_PROTO_TLS1_2 to enable DTLS 1.2. * - * Requires: MBEDTLS_SSL_PROTO_TLS1_1 - * or MBEDTLS_SSL_PROTO_TLS1_2 + * Requires: MBEDTLS_SSL_PROTO_TLS1_2 * * Comment this macro to disable support for DTLS */ @@ -2043,7 +1946,7 @@ * (see Section 5 of RFC 5764), are not handled by this feature. * Instead, after successful completion of a handshake negotiating * the use of DTLS-SRTP, the extended key exporter API - * mbedtls_ssl_conf_export_keys_ext_cb() should be used to implement + * mbedtls_ssl_conf_export_keys_cb() should be used to implement * the key exporter described in Section 4.2 of RFC 5764 and RFC 5705 * (this is implemented in the SSL example programs). * The resulting key should then be passed to an SRTP stack. @@ -2076,17 +1979,6 @@ */ #define MBEDTLS_SSL_DTLS_CLIENT_PORT_REUSE -/** - * \def MBEDTLS_SSL_DTLS_BADMAC_LIMIT - * - * Enable support for a limit of records with bad MAC. - * - * See mbedtls_ssl_conf_dtls_badmac_limit(). - * - * Requires: MBEDTLS_SSL_PROTO_DTLS - */ -#define MBEDTLS_SSL_DTLS_BADMAC_LIMIT - /** * \def MBEDTLS_SSL_SESSION_TICKETS * @@ -2101,16 +1993,6 @@ */ #define MBEDTLS_SSL_SESSION_TICKETS -/** - * \def MBEDTLS_SSL_EXPORT_KEYS - * - * Enable support for exporting key block and master secret. - * This is required for certain users of TLS, e.g. EAP-TLS. - * - * Comment this macro to disable support for key export - */ -#define MBEDTLS_SSL_EXPORT_KEYS - /** * \def MBEDTLS_SSL_SERVER_NAME_INDICATION * @@ -2122,39 +2004,6 @@ */ #define MBEDTLS_SSL_SERVER_NAME_INDICATION -/** - * \def MBEDTLS_SSL_TRUNCATED_HMAC - * - * Enable support for RFC 6066 truncated HMAC in SSL. - * - * Comment this macro to disable support for truncated HMAC in SSL - */ -#define MBEDTLS_SSL_TRUNCATED_HMAC - -/** - * \def MBEDTLS_SSL_TRUNCATED_HMAC_COMPAT - * - * Fallback to old (pre-2.7), non-conforming implementation of the truncated - * HMAC extension which also truncates the HMAC key. Note that this option is - * only meant for a transitory upgrade period and will be removed in a future - * version of the library. - * - * \warning The old implementation is non-compliant and has a security weakness - * (2^80 brute force attack on the HMAC key used for a single, - * uninterrupted connection). This should only be enabled temporarily - * when (1) the use of truncated HMAC is essential in order to save - * bandwidth, and (2) the peer is an Mbed TLS stack that doesn't use - * the fixed implementation yet (pre-2.7). - * - * \deprecated This option is deprecated and will be removed in a - * future version of Mbed TLS. - * - * Uncomment to fallback to old, non-compliant truncated HMAC implementation. - * - * Requires: MBEDTLS_SSL_TRUNCATED_HMAC - */ -//#define MBEDTLS_SSL_TRUNCATED_HMAC_COMPAT - /** * \def MBEDTLS_SSL_VARIABLE_BUFFER_LENGTH * @@ -2165,23 +2014,6 @@ */ //#define MBEDTLS_SSL_VARIABLE_BUFFER_LENGTH -/** - * Allow SHA-1 in the default TLS configuration for TLS 1.2 handshake - * signature and ciphersuite selection. Without this build-time option, SHA-1 - * support must be activated explicitly through mbedtls_ssl_conf_sig_hashes. - * The use of SHA-1 in TLS <= 1.1 and in HMAC-SHA-1 is always allowed by - * default. At the time of writing, there is no practical attack on the use - * of SHA-1 in handshake signatures, hence this option is turned on by default - * to preserve compatibility with existing peers, but the general - * warning applies nonetheless: - * - * \warning SHA-1 is considered a weak message digest and its use constitutes - * a security risk. If possible, we recommend avoiding dependencies - * on it, and considering stronger message digests instead. - * - */ -//#define MBEDTLS_TLS_DEFAULT_ALLOW_SHA1_IN_KEY_EXCHANGE - /** * \def MBEDTLS_TEST_CONSTANT_FLOW_MEMSAN * @@ -2263,21 +2095,26 @@ /** * \def MBEDTLS_USE_PSA_CRYPTO * - * Make the X.509 and TLS library use PSA for cryptographic operations, and - * enable new APIs for using keys handled by PSA Crypto. + * Make the X.509 and TLS libraries use PSA for cryptographic operations as + * much as possible, and enable new APIs for using keys handled by PSA Crypto. * * \note Development of this option is currently in progress, and parts of Mbed * TLS's X.509 and TLS modules are not ported to PSA yet. However, these parts * will still continue to work as usual, so enabling this option should not * break backwards compatibility. * - * \note See docs/use-psa-crypto.md for a complete description of what this - * option currently does, and of parts that are not affected by it so far. + * \warning If you enable this option, you need to call `psa_crypto_init()` + * before calling any function from the SSL/TLS, X.509 or PK modules, except + * for the various mbedtls_xxx_init() functions which can be called at any time. + * + * \note An important and desirable effect of this option is that it allows + * PK, X.509 and TLS to take advantage of PSA drivers. For example, enabling + * this option is what allows use of drivers for ECDSA, ECDH and EC J-PAKE in + * those modules. However, note that even with this option disabled, some code + * in PK, X.509, TLS or the crypto library might still use PSA drivers, if it + * can determine it's safe to do so; currently that's the case for hashes. * - * \warning This option enables new Mbed TLS APIs which are currently - * considered experimental and may change in incompatible ways at any time. - * That is, the APIs enabled by this option are not covered by the usual - * promises of API stability. + * \note See docs/use-psa-crypto.md for a complete description this option. * * Requires: MBEDTLS_PSA_CRYPTO_C. * @@ -2300,17 +2137,20 @@ * include/psa/crypto_config.h. The corresponding `MBEDTLS_XXX` settings are * automatically enabled if required (i.e. if no PSA driver provides the * mechanism). You may still freely enable additional `MBEDTLS_XXX` symbols - * in config.h. + * in mbedtls_config.h. * * If the symbol #MBEDTLS_PSA_CRYPTO_CONFIG_FILE is defined, it specifies * an alternative header to include instead of include/psa/crypto_config.h. * - * If you enable this option and write your own configuration file, you must - * include mbedtls/config_psa.h in your configuration file. The default - * provided mbedtls/config.h contains the necessary inclusion. - * - * This feature is still experimental and is not ready for production since - * it is not completed. + * \warning This option is experimental, in that the set of `PSA_WANT_XXX` + * symbols is not completely finalized yet, and the configuration + * tooling is not ideally adapted to having two separate configuration + * files. + * Future minor releases of Mbed TLS may make minor changes to those + * symbols, but we will endeavor to provide a transition path. + * Nonetheless, this option is considered mature enough to use in + * production, as long as you accept that you may need to make + * minor changes to psa/crypto_config.h when upgrading Mbed TLS. */ //#define MBEDTLS_PSA_CRYPTO_CONFIG @@ -2327,28 +2167,6 @@ */ #define MBEDTLS_VERSION_FEATURES -/** - * \def MBEDTLS_X509_ALLOW_EXTENSIONS_NON_V3 - * - * If set, the X509 parser will not break-off when parsing an X509 certificate - * and encountering an extension in a v1 or v2 certificate. - * - * Uncomment to prevent an error. - */ -//#define MBEDTLS_X509_ALLOW_EXTENSIONS_NON_V3 - -/** - * \def MBEDTLS_X509_ALLOW_UNSUPPORTED_CRITICAL_EXTENSION - * - * If set, the X509 parser will not break-off when parsing an X509 certificate - * and encountering an unknown critical extension. - * - * \warning Depending on your PKI use, enabling this can be a security risk! - * - * Uncomment to prevent an error. - */ -//#define MBEDTLS_X509_ALLOW_UNSUPPORTED_CRITICAL_EXTENSION - /** * \def MBEDTLS_X509_TRUSTED_CERTIFICATE_CALLBACK * @@ -2364,36 +2182,22 @@ * See the documentation of `mbedtls_x509_crt_verify_with_ca_cb()` and * `mbedtls_ssl_conf_ca_cb()` for more information. * + * Requires: MBEDTLS_X509_CRT_PARSE_C + * * Uncomment to enable trusted certificate callbacks. */ //#define MBEDTLS_X509_TRUSTED_CERTIFICATE_CALLBACK /** - * \def MBEDTLS_X509_CHECK_KEY_USAGE - * - * Enable verification of the keyUsage extension (CA and leaf certificates). - * - * Disabling this avoids problems with mis-issued and/or misused - * (intermediate) CA and leaf certificates. - * - * \warning Depending on your PKI use, disabling this can be a security risk! - * - * Comment to skip keyUsage checking for both CA and leaf certificates. - */ -#define MBEDTLS_X509_CHECK_KEY_USAGE - -/** - * \def MBEDTLS_X509_CHECK_EXTENDED_KEY_USAGE - * - * Enable verification of the extendedKeyUsage extension (leaf certificates). + * \def MBEDTLS_X509_REMOVE_INFO * - * Disabling this avoids problems with mis-issued and/or misused certificates. + * Disable mbedtls_x509_*_info() and related APIs. * - * \warning Depending on your PKI use, disabling this can be a security risk! - * - * Comment to skip extendedKeyUsage checking for certificates. + * Uncomment to omit mbedtls_x509_*_info(), as well as mbedtls_debug_print_crt() + * and other functions/constants only used by these functions, thus reducing + * the code footprint by several KB. */ -#define MBEDTLS_X509_CHECK_EXTENDED_KEY_USAGE +//#define MBEDTLS_X509_REMOVE_INFO /** * \def MBEDTLS_X509_RSASSA_PSS_SUPPORT @@ -2401,38 +2205,15 @@ * Enable parsing and verification of X.509 certificates, CRLs and CSRS * signed with RSASSA-PSS (aka PKCS#1 v2.1). * + * Requires: MBEDTLS_PKCS1_V21 + * * Comment this macro to disallow using RSASSA-PSS in certificates. */ #define MBEDTLS_X509_RSASSA_PSS_SUPPORT +/** \} name SECTION: Mbed TLS feature support */ /** - * \def MBEDTLS_ZLIB_SUPPORT - * - * If set, the SSL/TLS module uses ZLIB to support compression and - * decompression of packet data. - * - * \warning TLS-level compression MAY REDUCE SECURITY! See for example the - * CRIME attack. Before enabling this option, you should examine with care if - * CRIME or similar exploits may be applicable to your use case. - * - * \note Currently compression can't be used with DTLS. - * - * \deprecated This feature is deprecated and will be removed - * in the next major revision of the library. - * - * Used in: library/ssl_tls.c - * library/ssl_cli.c - * library/ssl_srv.c - * - * This feature requires zlib library and headers to be present. - * - * Uncomment to enable use of ZLIB - */ -//#define MBEDTLS_ZLIB_SUPPORT -/** \} name SECTION: Mbed TLS feature support */ - -/** - * \name SECTION: Mbed TLS modules + * \name SECTION: Mbed TLS modules * * This section enables or disables entire modules in Mbed TLS * \{ @@ -2444,7 +2225,7 @@ * Enable AES-NI support on x86-64 or x86-32. * * \note AESNI is only supported with certain compilers and target options: - * - Visual Studio 2013: supported. + * - Visual Studio: supported * - GCC, x86-64, target not explicitly supporting AESNI: * requires MBEDTLS_HAVE_ASM. * - GCC, x86-32, target not explicitly supporting AESNI: @@ -2470,6 +2251,32 @@ */ #define MBEDTLS_AESNI_C +/** + * \def MBEDTLS_AESCE_C + * + * Enable AES cryptographic extension support on Armv8. + * + * Module: library/aesce.c + * Caller: library/aes.c + * + * Requires: MBEDTLS_AES_C + * + * \warning Runtime detection only works on Linux. For non-Linux operating + * system, Armv8-A Cryptographic Extensions must be supported by + * the CPU when this option is enabled. + * + * \note Minimum compiler versions for this feature when targeting aarch64 + * are Clang 4.0; armclang 6.6; GCC 6.0; or MSVC 2019 version 16.11.2. + * Minimum compiler versions for this feature when targeting 32-bit + * Arm or Thumb are Clang 11.0; armclang 6.20; or GCC 6.0. + * + * \note \c CFLAGS must be set to a minimum of \c -march=armv8-a+crypto for + * armclang <= 6.9 + * + * This module adds support for the AES Armv8-A Cryptographic Extensions on Armv8 systems. + */ +#define MBEDTLS_AESCE_C + /** * \def MBEDTLS_AES_C * @@ -2545,34 +2352,6 @@ */ #define MBEDTLS_AES_C -/** - * \def MBEDTLS_ARC4_C - * - * Enable the ARCFOUR stream cipher. - * - * Module: library/arc4.c - * Caller: library/cipher.c - * - * This module enables the following ciphersuites (if other requisites are - * enabled as well): - * MBEDTLS_TLS_ECDH_ECDSA_WITH_RC4_128_SHA - * MBEDTLS_TLS_ECDH_RSA_WITH_RC4_128_SHA - * MBEDTLS_TLS_ECDHE_ECDSA_WITH_RC4_128_SHA - * MBEDTLS_TLS_ECDHE_RSA_WITH_RC4_128_SHA - * MBEDTLS_TLS_ECDHE_PSK_WITH_RC4_128_SHA - * MBEDTLS_TLS_DHE_PSK_WITH_RC4_128_SHA - * MBEDTLS_TLS_RSA_WITH_RC4_128_SHA - * MBEDTLS_TLS_RSA_WITH_RC4_128_MD5 - * MBEDTLS_TLS_RSA_PSK_WITH_RC4_128_SHA - * MBEDTLS_TLS_PSK_WITH_RC4_128_SHA - * - * \warning ARC4 is considered a weak cipher and its use constitutes a - * security risk. If possible, we recommend avoiding dependencies on - * it, and considering stronger ciphers instead. - * - */ -#define MBEDTLS_ARC4_C - /** * \def MBEDTLS_ASN1_PARSE_C * @@ -2613,32 +2392,48 @@ */ #define MBEDTLS_BASE64_C +/** + * \def MBEDTLS_BLOCK_CIPHER_NO_DECRYPT + * + * Remove decryption operation for AES, ARIA and Camellia block cipher. + * + * \note This feature is incompatible with insecure block cipher, + * MBEDTLS_DES_C, and cipher modes which always require decryption + * operation, MBEDTLS_CIPHER_MODE_CBC, MBEDTLS_CIPHER_MODE_XTS and + * MBEDTLS_NIST_KW_C. When #MBEDTLS_PSA_CRYPTO_CONFIG is enabled, + * this feature is incompatible with following supported PSA equivalence, + * PSA_WANT_ALG_ECB_NO_PADDING, PSA_WANT_ALG_CBC_NO_PADDING, + * PSA_WANT_ALG_CBC_PKCS7 and PSA_WANT_KEY_TYPE_DES. + * + * Module: library/aes.c + * library/aesce.c + * library/aesni.c + * library/aria.c + * library/camellia.c + * library/cipher.c + */ +//#define MBEDTLS_BLOCK_CIPHER_NO_DECRYPT + /** * \def MBEDTLS_BIGNUM_C * * Enable the multi-precision integer library. * * Module: library/bignum.c + * library/bignum_core.c + * library/bignum_mod.c + * library/bignum_mod_raw.c * Caller: library/dhm.c * library/ecp.c * library/ecdsa.c * library/rsa.c - * library/rsa_internal.c + * library/rsa_alt_helpers.c * library/ssl_tls.c * * This module is required for RSA, DHM and ECC (ECDH, ECDSA) support. */ #define MBEDTLS_BIGNUM_C -/** - * \def MBEDTLS_BLOWFISH_C - * - * Enable the Blowfish block cipher. - * - * Module: library/blowfish.c - */ -#define MBEDTLS_BLOWFISH_C - /** * \def MBEDTLS_CAMELLIA_C * @@ -2744,7 +2539,7 @@ * MBEDTLS_TLS_ECDHE_PSK_WITH_ARIA_128_CBC_SHA256 * MBEDTLS_TLS_ECDHE_PSK_WITH_ARIA_256_CBC_SHA384 */ -//#define MBEDTLS_ARIA_C +#define MBEDTLS_ARIA_C /** * \def MBEDTLS_CCM_C @@ -2753,25 +2548,14 @@ * * Module: library/ccm.c * - * Requires: MBEDTLS_AES_C or MBEDTLS_CAMELLIA_C + * Requires: MBEDTLS_CIPHER_C, MBEDTLS_AES_C or MBEDTLS_CAMELLIA_C or + * MBEDTLS_ARIA_C * * This module enables the AES-CCM ciphersuites, if other requisites are * enabled as well. */ #define MBEDTLS_CCM_C -/** - * \def MBEDTLS_CERTS_C - * - * Enable the test certificates. - * - * Module: library/certs.c - * Caller: - * - * This module is used for testing (ssl_client/server). - */ -#define MBEDTLS_CERTS_C - /** * \def MBEDTLS_CHACHA20_C * @@ -2798,7 +2582,19 @@ * Enable the generic cipher layer. * * Module: library/cipher.c - * Caller: library/ssl_tls.c + * Caller: library/ccm.c + * library/cmac.c + * library/gcm.c + * library/nist_kw.c + * library/pkcs12.c + * library/pkcs5.c + * library/psa_crypto_aead.c + * library/psa_crypto_mac.c + * library/ssl_ciphersuites.c + * library/ssl_msg.c + * library/ssl_ticket.c (unless MBEDTLS_USE_PSA_CRYPTO is enabled) + * Auto-enabled by: MBEDTLS_PSA_CRYPTO_C depending on which ciphers are enabled + * (see the documentation of that option for details). * * Uncomment to enable generic cipher wrappers. */ @@ -2817,10 +2613,10 @@ * * Module: library/cmac.c * - * Requires: MBEDTLS_AES_C or MBEDTLS_DES_C + * Requires: MBEDTLS_CIPHER_C, MBEDTLS_AES_C or MBEDTLS_DES_C * */ -//#define MBEDTLS_CMAC_C +#define MBEDTLS_CMAC_C /** * \def MBEDTLS_CTR_DRBG_C @@ -2829,6 +2625,15 @@ * The CTR_DRBG generator uses AES-256 by default. * To use AES-128 instead, enable \c MBEDTLS_CTR_DRBG_USE_128_BIT_KEY above. * + * AES support can either be achived through builtin (MBEDTLS_AES_C) or PSA. + * Builtin is the default option when MBEDTLS_AES_C is defined otherwise PSA + * is used. + * + * \warning When using PSA, the user should call `psa_crypto_init()` before + * using any CTR_DRBG operation (except `mbedtls_ctr_drbg_init()`). + * + * \note AES-128 will be used if \c MBEDTLS_AES_ONLY_128_BIT_KEY_LENGTH is set. + * * \note To achieve a 256-bit security strength with CTR_DRBG, * you must use AES-256 *and* use sufficient entropy. * See ctr_drbg.h for more details. @@ -2836,7 +2641,9 @@ * Module: library/ctr_drbg.c * Caller: * - * Requires: MBEDTLS_AES_C + * Requires: MBEDTLS_AES_C or + * (PSA_WANT_KEY_TYPE_AES and PSA_WANT_ALG_ECB_NO_PADDING and + * MBEDTLS_PSA_CRYPTO_C) * * This module provides the CTR_DRBG AES random number generator. */ @@ -2848,9 +2655,10 @@ * Enable the debug functions. * * Module: library/debug.c - * Caller: library/ssl_cli.c - * library/ssl_srv.c + * Caller: library/ssl_msg.c * library/ssl_tls.c + * library/ssl_tls12_*.c + * library/ssl_tls13_*.c * * This module provides debugging functions. */ @@ -2865,19 +2673,6 @@ * Caller: library/pem.c * library/cipher.c * - * This module enables the following ciphersuites (if other requisites are - * enabled as well): - * MBEDTLS_TLS_ECDH_ECDSA_WITH_3DES_EDE_CBC_SHA - * MBEDTLS_TLS_ECDH_RSA_WITH_3DES_EDE_CBC_SHA - * MBEDTLS_TLS_ECDHE_ECDSA_WITH_3DES_EDE_CBC_SHA - * MBEDTLS_TLS_ECDHE_RSA_WITH_3DES_EDE_CBC_SHA - * MBEDTLS_TLS_DHE_RSA_WITH_3DES_EDE_CBC_SHA - * MBEDTLS_TLS_ECDHE_PSK_WITH_3DES_EDE_CBC_SHA - * MBEDTLS_TLS_DHE_PSK_WITH_3DES_EDE_CBC_SHA - * MBEDTLS_TLS_RSA_WITH_3DES_EDE_CBC_SHA - * MBEDTLS_TLS_RSA_PSK_WITH_3DES_EDE_CBC_SHA - * MBEDTLS_TLS_PSK_WITH_3DES_EDE_CBC_SHA - * * PEM_PARSE uses DES/3DES for decrypting encrypted keys. * * \warning DES/3DES are considered weak ciphers and their use constitutes a @@ -2891,8 +2686,9 @@ * Enable the Diffie-Hellman-Merkle module. * * Module: library/dhm.c - * Caller: library/ssl_cli.c - * library/ssl_srv.c + * Caller: library/ssl_tls.c + * library/ssl*_client.c + * library/ssl*_server.c * * This module is used by the following key exchanges: * DHE-RSA, DHE-PSK @@ -2912,8 +2708,10 @@ * Enable the elliptic curve Diffie-Hellman library. * * Module: library/ecdh.c - * Caller: library/ssl_cli.c - * library/ssl_srv.c + * Caller: library/psa_crypto.c + * library/ssl_tls.c + * library/ssl*_client.c + * library/ssl*_server.c * * This module is used by the following key exchanges: * ECDHE-ECDSA, ECDHE-RSA, DHE-PSK @@ -2944,9 +2742,9 @@ * * Enable the elliptic curve J-PAKE library. * - * \warning This is currently experimental. EC J-PAKE support is based on the - * Thread v1.0.0 specification; incompatible changes to the specification - * might still happen. For this reason, this is disabled by default. + * \note EC J-PAKE support is based on the Thread v1.0.0 specification. + * It has not been reviewed for compliance with newer standards such as + * Thread v1.1 or RFC 8236. * * Module: library/ecjpake.c * Caller: @@ -2954,9 +2752,12 @@ * This module is used by the following key exchanges: * ECJPAKE * - * Requires: MBEDTLS_ECP_C, MBEDTLS_MD_C + * Requires: MBEDTLS_ECP_C and either MBEDTLS_MD_C or MBEDTLS_PSA_CRYPTO_C + * + * \warning If using a hash that is only provided by PSA drivers, you must + * call psa_crypto_init() before doing any EC J-PAKE operations. */ -//#define MBEDTLS_ECJPAKE_C +#define MBEDTLS_ECJPAKE_C /** * \def MBEDTLS_ECP_C @@ -3005,7 +2806,8 @@ * * Module: library/gcm.c * - * Requires: MBEDTLS_AES_C or MBEDTLS_CAMELLIA_C or MBEDTLS_ARIA_C + * Requires: MBEDTLS_CIPHER_C, MBEDTLS_AES_C or MBEDTLS_CAMELLIA_C or + * MBEDTLS_ARIA_C * * This module enables the AES-GCM and CAMELLIA-GCM ciphersuites, if other * requisites are enabled as well. @@ -3013,27 +2815,20 @@ #define MBEDTLS_GCM_C /** - * \def MBEDTLS_HAVEGE_C - * - * Enable the HAVEGE random generator. + * \def MBEDTLS_GCM_LARGE_TABLE * - * Warning: the HAVEGE random generator is not suitable for virtualized - * environments + * Enable large pre-computed tables for Galois/Counter Mode (GCM). + * Can significantly increase throughput on systems without GCM hardware + * acceleration (e.g., AESNI, AESCE). * - * Warning: the HAVEGE random generator is dependent on timing and specific - * processor traits. It is therefore not advised to use HAVEGE as - * your applications primary random generator or primary entropy pool - * input. As a secondary input to your entropy pool, it IS able add - * the (limited) extra entropy it provides. + * The mbedtls_gcm_context size will increase by 3840 bytes. + * The code size will increase by roughly 344 bytes. * - * Module: library/havege.c - * Caller: - * - * Requires: MBEDTLS_TIMING_C + * Module: library/gcm.c * - * Uncomment to enable the HAVEGE random generator. + * Requires: MBEDTLS_GCM_C */ -//#define MBEDTLS_HAVEGE_C +//#define MBEDTLS_GCM_LARGE_TABLE /** * \def MBEDTLS_HKDF_C @@ -3065,63 +2860,76 @@ #define MBEDTLS_HMAC_DRBG_C /** - * \def MBEDTLS_NIST_KW_C + * \def MBEDTLS_LMS_C * - * Enable the Key Wrapping mode for 128-bit block ciphers, - * as defined in NIST SP 800-38F. Only KW and KWP modes - * are supported. At the moment, only AES is approved by NIST. + * Enable the LMS stateful-hash asymmetric signature algorithm. * - * Module: library/nist_kw.c + * Module: library/lms.c + * Caller: * - * Requires: MBEDTLS_AES_C and MBEDTLS_CIPHER_C + * Requires: MBEDTLS_PSA_CRYPTO_C + * + * Uncomment to enable the LMS verification algorithm and public key operations. */ -//#define MBEDTLS_NIST_KW_C +#define MBEDTLS_LMS_C /** - * \def MBEDTLS_MD_C + * \def MBEDTLS_LMS_PRIVATE * - * Enable the generic message digest layer. + * Enable LMS private-key operations and signing code. Functions enabled by this + * option are experimental, and should not be used in production. * - * Module: library/md.c - * Caller: + * Requires: MBEDTLS_LMS_C * - * Uncomment to enable generic message digest wrappers. + * Uncomment to enable the LMS signature algorithm and private key operations. */ -#define MBEDTLS_MD_C +//#define MBEDTLS_LMS_PRIVATE /** - * \def MBEDTLS_MD2_C - * - * Enable the MD2 hash algorithm. - * - * Module: library/md2.c - * Caller: + * \def MBEDTLS_NIST_KW_C * - * Uncomment to enable support for (rare) MD2-signed X.509 certs. + * Enable the Key Wrapping mode for 128-bit block ciphers, + * as defined in NIST SP 800-38F. Only KW and KWP modes + * are supported. At the moment, only AES is approved by NIST. * - * \warning MD2 is considered a weak message digest and its use constitutes a - * security risk. If possible, we recommend avoiding dependencies on - * it, and considering stronger message digests instead. + * Module: library/nist_kw.c * + * Requires: MBEDTLS_AES_C and MBEDTLS_CIPHER_C */ -//#define MBEDTLS_MD2_C +#define MBEDTLS_NIST_KW_C /** - * \def MBEDTLS_MD4_C - * - * Enable the MD4 hash algorithm. - * - * Module: library/md4.c - * Caller: + * \def MBEDTLS_MD_C * - * Uncomment to enable support for (rare) MD4-signed X.509 certs. + * Enable the generic layer for message digest (hashing) and HMAC. * - * \warning MD4 is considered a weak message digest and its use constitutes a - * security risk. If possible, we recommend avoiding dependencies on - * it, and considering stronger message digests instead. + * Requires: one of: MBEDTLS_MD5_C, MBEDTLS_RIPEMD160_C, MBEDTLS_SHA1_C, + * MBEDTLS_SHA224_C, MBEDTLS_SHA256_C, MBEDTLS_SHA384_C, + * MBEDTLS_SHA512_C, or MBEDTLS_PSA_CRYPTO_C with at least + * one hash. + * Module: library/md.c + * Caller: library/constant_time.c + * library/ecdsa.c + * library/ecjpake.c + * library/hkdf.c + * library/hmac_drbg.c + * library/pk.c + * library/pkcs5.c + * library/pkcs12.c + * library/psa_crypto_ecp.c + * library/psa_crypto_rsa.c + * library/rsa.c + * library/ssl_cookie.c + * library/ssl_msg.c + * library/ssl_tls.c + * library/x509.c + * library/x509_crt.c + * library/x509write_crt.c + * library/x509write_csr.c * + * Uncomment to enable generic message digest wrappers. */ -//#define MBEDTLS_MD4_C +#define MBEDTLS_MD_C /** * \def MBEDTLS_MD5_C @@ -3133,10 +2941,9 @@ * library/pem.c * library/ssl_tls.c * - * This module is required for SSL/TLS up to version 1.1, and for TLS 1.2 - * depending on the handshake parameters. Further, it is used for checking - * MD5-signed certificates, and for PBKDF1 when decrypting PEM-encoded - * encrypted keys. + * This module is required for TLS 1.2 depending on the handshake parameters. + * Further, it is used for checking MD5-signed certificates, and for PBKDF1 + * when decrypting PEM-encoded encrypted keys. * * \warning MD5 is considered a weak message digest and its use constitutes a * security risk. If possible, we recommend avoiding dependencies on @@ -3230,6 +3037,10 @@ * library/x509_csr.c * * Requires: MBEDTLS_BASE64_C + * optionally MBEDTLS_MD5_C, or PSA Crypto with MD5 (see below) + * + * \warning When parsing password-protected files, if MD5 is provided only by + * a PSA driver, you must call psa_crypto_init() before the first file. * * This modules adds support for decoding / parsing PEM files. */ @@ -3257,11 +3068,13 @@ * Enable the generic public (asymmetric) key layer. * * Module: library/pk.c - * Caller: library/ssl_tls.c - * library/ssl_cli.c - * library/ssl_srv.c + * Caller: library/psa_crypto_rsa.c + * library/ssl_tls.c + * library/ssl*_client.c + * library/ssl*_server.c + * library/x509.c * - * Requires: MBEDTLS_RSA_C or MBEDTLS_ECP_C + * Requires: MBEDTLS_MD_C, MBEDTLS_RSA_C or MBEDTLS_ECP_C * * Uncomment to enable generic public key wrappers. */ @@ -3276,7 +3089,7 @@ * Caller: library/x509_crt.c * library/x509_csr.c * - * Requires: MBEDTLS_PK_C + * Requires: MBEDTLS_ASN1_PARSE_C, MBEDTLS_OID_C, MBEDTLS_PK_C * * Uncomment to enable generic public key parse functions. */ @@ -3290,7 +3103,7 @@ * Module: library/pkwrite.c * Caller: library/x509write.c * - * Requires: MBEDTLS_PK_C + * Requires: MBEDTLS_ASN1_WRITE_C, MBEDTLS_OID_C, MBEDTLS_PK_C * * Uncomment to enable generic public key write functions. */ @@ -3303,29 +3116,30 @@ * * Module: library/pkcs5.c * - * Requires: MBEDTLS_MD_C + * Auto-enables: MBEDTLS_MD_C + * + * \warning If using a hash that is only provided by PSA drivers, you must + * call psa_crypto_init() before doing any PKCS5 operations. * * This module adds support for the PKCS#5 functions. */ #define MBEDTLS_PKCS5_C /** - * \def MBEDTLS_PKCS11_C + * \def MBEDTLS_PKCS7_C * - * Enable wrapper for PKCS#11 smartcard support via the pkcs11-helper library. + * Enable PKCS #7 core for using PKCS #7-formatted signatures. + * RFC Link - https://tools.ietf.org/html/rfc2315 * - * \deprecated This option is deprecated and will be removed in a future - * version of Mbed TLS. + * Module: library/pkcs7.c * - * Module: library/pkcs11.c - * Caller: library/pk.c + * Requires: MBEDTLS_ASN1_PARSE_C, MBEDTLS_OID_C, MBEDTLS_PK_PARSE_C, + * MBEDTLS_X509_CRT_PARSE_C MBEDTLS_X509_CRL_PARSE_C, + * MBEDTLS_BIGNUM_C, MBEDTLS_MD_C * - * Requires: MBEDTLS_PK_C - * - * This module enables SSL/TLS PKCS #11 smartcard support. - * Requires the presence of the PKCS#11 helper library (libpkcs11-helper) + * This module is required for the PKCS #7 parsing modules. */ -//#define MBEDTLS_PKCS11_C +#define MBEDTLS_PKCS7_C /** * \def MBEDTLS_PKCS12_C @@ -3336,8 +3150,11 @@ * Module: library/pkcs12.c * Caller: library/pkparse.c * - * Requires: MBEDTLS_ASN1_PARSE_C, MBEDTLS_CIPHER_C, MBEDTLS_MD_C - * Can use: MBEDTLS_ARC4_C + * Requires: MBEDTLS_ASN1_PARSE_C and either MBEDTLS_MD_C or + * MBEDTLS_PSA_CRYPTO_C. + * + * \warning If using a hash that is only provided by PSA drivers, you must + * call psa_crypto_init() before doing any PKCS12 operations. * * This module enables PKCS#12 functions. */ @@ -3354,7 +3171,7 @@ * above to be specified at runtime or compile time respectively. * * \note This abstraction layer must be enabled on Windows (including MSYS2) - * as other module rely on it for a fixed snprintf implementation. + * as other modules rely on it for a fixed snprintf implementation. * * Module: library/platform.c * Caller: Most other .c files @@ -3383,18 +3200,23 @@ * Requires: either MBEDTLS_CTR_DRBG_C and MBEDTLS_ENTROPY_C, * or MBEDTLS_HMAC_DRBG_C and MBEDTLS_ENTROPY_C, * or MBEDTLS_PSA_CRYPTO_EXTERNAL_RNG. - * + * Auto-enables: MBEDTLS_CIPHER_C if any unauthenticated (ie, non-AEAD) cipher + * is enabled in PSA (unless it's fully accelerated, see + * docs/driver-only-builds.md about that). */ #define MBEDTLS_PSA_CRYPTO_C /** * \def MBEDTLS_PSA_CRYPTO_SE_C * - * Enable secure element support in the Platform Security Architecture + * Enable dynamic secure element support in the Platform Security Architecture * cryptography API. * - * \warning This feature is not yet suitable for production. It is provided - * for API evaluation and testing purposes only. + * \deprecated This feature is deprecated. Please switch to the PSA driver + * interface. + * + * \warning This feature is not thread-safe, and should not be used in a + * multi-threaded environment. * * Module: library/psa_crypto_se.c * @@ -3445,11 +3267,12 @@ * Enable the RSA public-key cryptosystem. * * Module: library/rsa.c - * library/rsa_internal.c - * Caller: library/ssl_cli.c - * library/ssl_srv.c + * library/rsa_alt_helpers.c + * Caller: library/pk.c + * library/psa_crypto.c * library/ssl_tls.c - * library/x509.c + * library/ssl*_client.c + * library/ssl*_server.c * * This module is used by the following key exchanges: * RSA, DHE-RSA, ECDHE-RSA, RSA-PSK @@ -3465,13 +3288,10 @@ * * Module: library/sha1.c * Caller: library/md.c - * library/ssl_cli.c - * library/ssl_srv.c - * library/ssl_tls.c - * library/x509write_crt.c + * library/psa_crypto_hash.c * - * This module is required for SSL/TLS up to version 1.1, for TLS 1.2 - * depending on the handshake parameters, and for SHA1-signed certificates. + * This module is required for TLS 1.2 depending on the handshake parameters, + * and for SHA1-signed certificates. * * \warning SHA-1 is considered a weak message digest and its use constitutes * a security risk. If possible, we recommend avoiding dependencies @@ -3480,38 +3300,216 @@ */ #define MBEDTLS_SHA1_C +/** + * \def MBEDTLS_SHA224_C + * + * Enable the SHA-224 cryptographic hash algorithm. + * + * Module: library/sha256.c + * Caller: library/md.c + * library/ssl_cookie.c + * + * This module adds support for SHA-224. + */ +#define MBEDTLS_SHA224_C + /** * \def MBEDTLS_SHA256_C * - * Enable the SHA-224 and SHA-256 cryptographic hash algorithms. + * Enable the SHA-256 cryptographic hash algorithm. * * Module: library/sha256.c * Caller: library/entropy.c * library/md.c - * library/ssl_cli.c - * library/ssl_srv.c * library/ssl_tls.c + * library/ssl*_client.c + * library/ssl*_server.c * - * This module adds support for SHA-224 and SHA-256. + * This module adds support for SHA-256. * This module is required for the SSL/TLS 1.2 PRF function. */ #define MBEDTLS_SHA256_C +/** + * \def MBEDTLS_SHA256_USE_ARMV8_A_CRYPTO_IF_PRESENT + * + * Enable acceleration of the SHA-256 and SHA-224 cryptographic hash algorithms + * with the ARMv8 cryptographic extensions if they are available at runtime. + * If not, the library will fall back to the C implementation. + * + * \note If MBEDTLS_SHA256_USE_ARMV8_A_CRYPTO_IF_PRESENT is defined when building + * for a non-Armv8-A build it will be silently ignored. + * + * \note Minimum compiler versions for this feature are Clang 4.0, + * armclang 6.6 or GCC 6.0. + * + * \note \c CFLAGS must be set to a minimum of \c -march=armv8-a+crypto for + * armclang <= 6.9 + * + * \note This was previously known as MBEDTLS_SHA256_USE_A64_CRYPTO_IF_PRESENT. + * That name is deprecated, but may still be used as an alternative form for this + * option. + * + * \warning MBEDTLS_SHA256_USE_ARMV8_A_CRYPTO_IF_PRESENT cannot be defined at the + * same time as MBEDTLS_SHA256_USE_ARMV8_A_CRYPTO_ONLY. + * + * Requires: MBEDTLS_SHA256_C. + * + * Module: library/sha256.c + * + * Uncomment to have the library check for the Armv8-A SHA-256 crypto extensions + * and use them if available. + */ +//#define MBEDTLS_SHA256_USE_ARMV8_A_CRYPTO_IF_PRESENT + +/** + * \def MBEDTLS_SHA256_USE_A64_CRYPTO_IF_PRESENT + * + * \deprecated This is now known as MBEDTLS_SHA256_USE_ARMV8_A_CRYPTO_IF_PRESENT. + * This name is now deprecated, but may still be used as an alternative form for + * this option. + */ +//#define MBEDTLS_SHA256_USE_A64_CRYPTO_IF_PRESENT + +/** + * \def MBEDTLS_SHA256_USE_ARMV8_A_CRYPTO_ONLY + * + * Enable acceleration of the SHA-256 and SHA-224 cryptographic hash algorithms + * with the ARMv8 cryptographic extensions, which must be available at runtime + * or else an illegal instruction fault will occur. + * + * \note This allows builds with a smaller code size than with + * MBEDTLS_SHA256_USE_ARMV8_A_CRYPTO_IF_PRESENT + * + * \note Minimum compiler versions for this feature are Clang 4.0, + * armclang 6.6 or GCC 6.0. + * + * \note \c CFLAGS must be set to a minimum of \c -march=armv8-a+crypto for + * armclang <= 6.9 + * + * \note This was previously known as MBEDTLS_SHA256_USE_A64_CRYPTO_ONLY. + * That name is deprecated, but may still be used as an alternative form for this + * option. + * + * \warning MBEDTLS_SHA256_USE_ARMV8_A_CRYPTO_ONLY cannot be defined at the same + * time as MBEDTLS_SHA256_USE_ARMV8_A_CRYPTO_IF_PRESENT. + * + * Requires: MBEDTLS_SHA256_C. + * + * Module: library/sha256.c + * + * Uncomment to have the library use the Armv8-A SHA-256 crypto extensions + * unconditionally. + */ +//#define MBEDTLS_SHA256_USE_ARMV8_A_CRYPTO_ONLY + +/** + * \def MBEDTLS_SHA256_USE_A64_CRYPTO_ONLY + * + * \deprecated This is now known as MBEDTLS_SHA256_USE_ARMV8_A_CRYPTO_ONLY. + * This name is now deprecated, but may still be used as an alternative form for + * this option. + */ +//#define MBEDTLS_SHA256_USE_A64_CRYPTO_ONLY + +/** + * \def MBEDTLS_SHA384_C + * + * Enable the SHA-384 cryptographic hash algorithm. + * + * Module: library/sha512.c + * Caller: library/md.c + * library/psa_crypto_hash.c + * library/ssl_tls.c + * library/ssl*_client.c + * library/ssl*_server.c + * + * Comment to disable SHA-384 + */ +#define MBEDTLS_SHA384_C + /** * \def MBEDTLS_SHA512_C * - * Enable the SHA-384 and SHA-512 cryptographic hash algorithms. + * Enable SHA-512 cryptographic hash algorithms. * * Module: library/sha512.c * Caller: library/entropy.c * library/md.c - * library/ssl_cli.c - * library/ssl_srv.c + * library/ssl_tls.c + * library/ssl_cookie.c * - * This module adds support for SHA-384 and SHA-512. + * This module adds support for SHA-512. */ #define MBEDTLS_SHA512_C +/** + * \def MBEDTLS_SHA3_C + * + * Enable the SHA3 cryptographic hash algorithm. + * + * Module: library/sha3.c + * + * This module adds support for SHA3. + */ +#define MBEDTLS_SHA3_C + +/** + * \def MBEDTLS_SHA512_USE_A64_CRYPTO_IF_PRESENT + * + * Enable acceleration of the SHA-512 and SHA-384 cryptographic hash algorithms + * with the ARMv8 cryptographic extensions if they are available at runtime. + * If not, the library will fall back to the C implementation. + * + * \note If MBEDTLS_SHA512_USE_A64_CRYPTO_IF_PRESENT is defined when building + * for a non-Aarch64 build it will be silently ignored. + * + * \note Minimum compiler versions for this feature are Clang 7.0, + * armclang 6.9 or GCC 8.0. + * + * \note \c CFLAGS must be set to a minimum of \c -march=armv8.2-a+sha3 for + * armclang 6.9 + * + * \warning MBEDTLS_SHA512_USE_A64_CRYPTO_IF_PRESENT cannot be defined at the + * same time as MBEDTLS_SHA512_USE_A64_CRYPTO_ONLY. + * + * Requires: MBEDTLS_SHA512_C. + * + * Module: library/sha512.c + * + * Uncomment to have the library check for the A64 SHA-512 crypto extensions + * and use them if available. + */ +//#define MBEDTLS_SHA512_USE_A64_CRYPTO_IF_PRESENT + +/** + * \def MBEDTLS_SHA512_USE_A64_CRYPTO_ONLY + * + * Enable acceleration of the SHA-512 and SHA-384 cryptographic hash algorithms + * with the ARMv8 cryptographic extensions, which must be available at runtime + * or else an illegal instruction fault will occur. + * + * \note This allows builds with a smaller code size than with + * MBEDTLS_SHA512_USE_A64_CRYPTO_IF_PRESENT + * + * \note Minimum compiler versions for this feature are Clang 7.0, + * armclang 6.9 or GCC 8.0. + * + * \note \c CFLAGS must be set to a minimum of \c -march=armv8.2-a+sha3 for + * armclang 6.9 + * + * \warning MBEDTLS_SHA512_USE_A64_CRYPTO_ONLY cannot be defined at the same + * time as MBEDTLS_SHA512_USE_A64_CRYPTO_IF_PRESENT. + * + * Requires: MBEDTLS_SHA512_C. + * + * Module: library/sha512.c + * + * Uncomment to have the library use the A64 SHA-512 crypto extensions + * unconditionally. + */ +//#define MBEDTLS_SHA512_USE_A64_CRYPTO_ONLY + /** * \def MBEDTLS_SSL_CACHE_C * @@ -3542,8 +3540,8 @@ * Module: library/ssl_ticket.c * Caller: * - * Requires: MBEDTLS_CIPHER_C && - * ( MBEDTLS_GCM_C || MBEDTLS_CCM_C || MBEDTLS_CHACHAPOLY_C ) + * Requires: (MBEDTLS_CIPHER_C || MBEDTLS_USE_PSA_CRYPTO) && + * (MBEDTLS_GCM_C || MBEDTLS_CCM_C || MBEDTLS_CHACHAPOLY_C) */ #define MBEDTLS_SSL_TICKET_C @@ -3552,7 +3550,7 @@ * * Enable the SSL/TLS client code. * - * Module: library/ssl_cli.c + * Module: library/ssl*_client.c * Caller: * * Requires: MBEDTLS_SSL_TLS_C @@ -3566,7 +3564,7 @@ * * Enable the SSL/TLS server code. * - * Module: library/ssl_srv.c + * Module: library/ssl*_server.c * Caller: * * Requires: MBEDTLS_SSL_TLS_C @@ -3581,8 +3579,8 @@ * Enable the generic SSL/TLS code. * * Module: library/ssl_tls.c - * Caller: library/ssl_cli.c - * library/ssl_srv.c + * Caller: library/ssl*_client.c + * library/ssl*_server.c * * Requires: MBEDTLS_CIPHER_C, MBEDTLS_MD_C * and at least one of the MBEDTLS_SSL_PROTO_XXX defines @@ -3634,9 +3632,6 @@ * https://mbed-tls.readthedocs.io/en/latest/kb/how-to/how-do-i-port-mbed-tls-to-a-new-environment-OS * * Module: library/timing.c - * Caller: library/havege.c - * - * This module is used by the HAVEGE random number generator. */ #define MBEDTLS_TIMING_C @@ -3661,8 +3656,11 @@ * library/x509_crt.c * library/x509_csr.c * - * Requires: MBEDTLS_ASN1_PARSE_C, MBEDTLS_BIGNUM_C, MBEDTLS_OID_C, - * MBEDTLS_PK_PARSE_C + * Requires: MBEDTLS_ASN1_PARSE_C, MBEDTLS_BIGNUM_C, MBEDTLS_OID_C, MBEDTLS_PK_PARSE_C, + * (MBEDTLS_MD_C or MBEDTLS_USE_PSA_CRYPTO) + * + * \warning If building with MBEDTLS_USE_PSA_CRYPTO, you must call + * psa_crypto_init() before doing any X.509 operation. * * This module is required for the X.509 parsing modules. */ @@ -3674,9 +3672,9 @@ * Enable X.509 certificate parsing. * * Module: library/x509_crt.c - * Caller: library/ssl_cli.c - * library/ssl_srv.c - * library/ssl_tls.c + * Caller: library/ssl_tls.c + * library/ssl*_client.c + * library/ssl*_server.c * * Requires: MBEDTLS_X509_USE_C * @@ -3719,7 +3717,11 @@ * * Module: library/x509_create.c * - * Requires: MBEDTLS_BIGNUM_C, MBEDTLS_OID_C, MBEDTLS_PK_WRITE_C + * Requires: MBEDTLS_BIGNUM_C, MBEDTLS_OID_C, MBEDTLS_PK_PARSE_C, + * (MBEDTLS_MD_C or MBEDTLS_USE_PSA_CRYPTO) + * + * \warning If building with MBEDTLS_USE_PSA_CRYPTO, you must call + * psa_crypto_init() before doing any X.509 create operation. * * This module is the basis for creating X.509 certificates and CSRs. */ @@ -3751,16 +3753,6 @@ */ #define MBEDTLS_X509_CSR_WRITE_C -/** - * \def MBEDTLS_XTEA_C - * - * Enable the XTEA block cipher. - * - * Module: library/xtea.c - * Caller: - */ -#define MBEDTLS_XTEA_C - /** \} name SECTION: Mbed TLS modules */ /** @@ -3776,10 +3768,11 @@ * \def MBEDTLS_CONFIG_FILE * * If defined, this is a header which will be included instead of - * `"mbedtls/config.h"`. + * `"mbedtls/mbedtls_config.h"`. * This header file specifies the compile-time configuration of Mbed TLS. * Unlike other configuration options, this one must be defined on the - * compiler command line: a definition in `config.h` would have no effect. + * compiler command line: a definition in `mbedtls_config.h` would have + * no effect. * * This macro is expanded after an \#include directive. This is a popular but * non-standard feature of the C language, so this feature is only available @@ -3788,13 +3781,13 @@ * The value of this symbol is typically a path in double quotes, either * absolute or relative to a directory on the include search path. */ -//#define MBEDTLS_CONFIG_FILE "mbedtls/config.h" +//#define MBEDTLS_CONFIG_FILE "mbedtls/mbedtls_config.h" /** * \def MBEDTLS_USER_CONFIG_FILE * * If defined, this is a header which will be included after - * `"mbedtls/config.h"` or #MBEDTLS_CONFIG_FILE. + * `"mbedtls/mbedtls_config.h"` or #MBEDTLS_CONFIG_FILE. * This allows you to modify the default configuration, including the ability * to undefine options that are enabled by default. * @@ -3842,6 +3835,53 @@ */ //#define MBEDTLS_PSA_CRYPTO_USER_CONFIG_FILE "/dev/null" +/** + * \def MBEDTLS_PSA_CRYPTO_PLATFORM_FILE + * + * If defined, this is a header which will be included instead of + * `"psa/crypto_platform.h"`. This file should declare the same identifiers + * as the one in Mbed TLS, but with definitions adapted to the platform on + * which the library code will run. + * + * \note The required content of this header can vary from one version of + * Mbed TLS to the next. Integrators who provide an alternative file + * should review the changes in the original file whenever they + * upgrade Mbed TLS. + * + * This macro is expanded after an \#include directive. This is a popular but + * non-standard feature of the C language, so this feature is only available + * with compilers that perform macro expansion on an \#include line. + * + * The value of this symbol is typically a path in double quotes, either + * absolute or relative to a directory on the include search path. + */ +//#define MBEDTLS_PSA_CRYPTO_PLATFORM_FILE "psa/crypto_platform_alt.h" + +/** + * \def MBEDTLS_PSA_CRYPTO_STRUCT_FILE + * + * If defined, this is a header which will be included instead of + * `"psa/crypto_struct.h"`. This file should declare the same identifiers + * as the one in Mbed TLS, but with definitions adapted to the environment + * in which the library code will run. The typical use for this feature + * is to provide alternative type definitions on the client side in + * client-server integrations of PSA crypto, where operation structures + * contain handles instead of cryptographic data. + * + * \note The required content of this header can vary from one version of + * Mbed TLS to the next. Integrators who provide an alternative file + * should review the changes in the original file whenever they + * upgrade Mbed TLS. + * + * This macro is expanded after an \#include directive. This is a popular but + * non-standard feature of the C language, so this feature is only available + * with compilers that perform macro expansion on an \#include line. + * + * The value of this symbol is typically a path in double quotes, either + * absolute or relative to a directory on the include search path. + */ +//#define MBEDTLS_PSA_CRYPTO_STRUCT_FILE "psa/crypto_struct_alt.h" + /** \} name SECTION: General configuration options */ /** @@ -3881,7 +3921,6 @@ //#define MBEDTLS_HMAC_DRBG_MAX_SEED_INPUT 384 /**< Maximum size of (re)seed buffer */ /* ECP options */ -//#define MBEDTLS_ECP_MAX_BITS 521 /**< Maximum bit size of groups. Normally determined automatically from the configured curves. */ //#define MBEDTLS_ECP_WINDOW_SIZE 4 /**< Maximum window size used */ //#define MBEDTLS_ECP_FIXED_POINT_OPTIM 1 /**< Enable fixed-point speed-up */ @@ -3918,6 +3957,7 @@ * See the description of #MBEDTLS_PLATFORM_MEMORY for more details (same principles as for MBEDTLS_PLATFORM_STD_CALLOC apply). */ //#define MBEDTLS_PLATFORM_STD_FREE free +//#define MBEDTLS_PLATFORM_STD_SETBUF setbuf /**< Default setbuf to use, can be undefined */ //#define MBEDTLS_PLATFORM_STD_EXIT exit /**< Default exit to use, can be undefined */ //#define MBEDTLS_PLATFORM_STD_TIME time /**< Default time to use, can be undefined. MBEDTLS_HAVE_TIME must be enabled */ //#define MBEDTLS_PLATFORM_STD_FPRINTF fprintf /**< Default fprintf to use, can be undefined */ @@ -3935,6 +3975,7 @@ //#define MBEDTLS_PLATFORM_CALLOC_MACRO calloc /**< Default allocator macro to use, can be undefined. See MBEDTLS_PLATFORM_STD_CALLOC for requirements. */ //#define MBEDTLS_PLATFORM_FREE_MACRO free /**< Default free macro to use, can be undefined. See MBEDTLS_PLATFORM_STD_FREE for requirements. */ //#define MBEDTLS_PLATFORM_EXIT_MACRO exit /**< Default exit macro to use, can be undefined */ +//#define MBEDTLS_PLATFORM_SETBUF_MACRO setbuf /**< Default setbuf macro to use, can be undefined */ //#define MBEDTLS_PLATFORM_TIME_MACRO time /**< Default time macro to use, can be undefined. MBEDTLS_HAVE_TIME must be enabled */ //#define MBEDTLS_PLATFORM_TIME_TYPE_MACRO time_t /**< Default time macro to use, can be undefined. MBEDTLS_HAVE_TIME must be enabled */ //#define MBEDTLS_PLATFORM_FPRINTF_MACRO fprintf /**< Default fprintf macro to use, can be undefined */ @@ -3944,42 +3985,8 @@ //#define MBEDTLS_PLATFORM_VSNPRINTF_MACRO vsnprintf /**< Default vsnprintf macro to use, can be undefined */ //#define MBEDTLS_PLATFORM_NV_SEED_READ_MACRO mbedtls_platform_std_nv_seed_read /**< Default nv_seed_read function to use, can be undefined */ //#define MBEDTLS_PLATFORM_NV_SEED_WRITE_MACRO mbedtls_platform_std_nv_seed_write /**< Default nv_seed_write function to use, can be undefined */ - -/** - * \brief This macro is invoked by the library when an invalid parameter - * is detected that is only checked with #MBEDTLS_CHECK_PARAMS - * (see the documentation of that option for context). - * - * When you leave this undefined here, the library provides - * a default definition. If the macro #MBEDTLS_CHECK_PARAMS_ASSERT - * is defined, the default definition is `assert(cond)`, - * otherwise the default definition calls a function - * mbedtls_param_failed(). This function is declared in - * `platform_util.h` for the benefit of the library, but - * you need to define in your application. - * - * When you define this here, this replaces the default - * definition in platform_util.h (which no longer declares the - * function mbedtls_param_failed()) and it is your responsibility - * to make sure this macro expands to something suitable (in - * particular, that all the necessary declarations are visible - * from within the library - you can ensure that by providing - * them in this file next to the macro definition). - * If you define this macro to call `assert`, also define - * #MBEDTLS_CHECK_PARAMS_ASSERT so that library source files - * include ``. - * - * Note that you may define this macro to expand to nothing, in - * which case you don't have to worry about declarations or - * definitions. However, you will then be notified about invalid - * parameters only in non-void functions, and void function will - * just silently return early on invalid parameters, which - * partially negates the benefits of enabling - * #MBEDTLS_CHECK_PARAMS in the first place, so is discouraged. - * - * \param cond The expression that should evaluate to true, but doesn't. - */ -//#define MBEDTLS_PARAM_FAILED( cond ) assert( cond ) +//#define MBEDTLS_PLATFORM_MS_TIME_TYPE_MACRO int64_t //#define MBEDTLS_PLATFORM_MS_TIME_TYPE_MACRO int64_t /**< Default milliseconds time macro to use, can be undefined. MBEDTLS_HAVE_TIME must be enabled. It must be signed, and at least 64 bits. If it is changed from the default, MBEDTLS_PRINTF_MS_TIME must be updated to match.*/ +//#define MBEDTLS_PRINTF_MS_TIME PRId64 /**< Default fmt for printf. That's avoid compiler warning if mbedtls_ms_time_t is redefined */ /** \def MBEDTLS_CHECK_RETURN * @@ -4028,38 +4035,15 @@ */ //#define MBEDTLS_PSA_KEY_SLOT_COUNT 32 +/* RSA OPTIONS */ +//#define MBEDTLS_RSA_GEN_KEY_MIN_BITS 1024 /**< Minimum RSA key size that can be generated in bits (Minimum possible value is 128 bits) */ + /* SSL Cache options */ //#define MBEDTLS_SSL_CACHE_DEFAULT_TIMEOUT 86400 /**< 1 day */ //#define MBEDTLS_SSL_CACHE_DEFAULT_MAX_ENTRIES 50 /**< Maximum entries in cache */ /* SSL options */ -/** \def MBEDTLS_SSL_MAX_CONTENT_LEN - * - * Maximum length (in bytes) of incoming and outgoing plaintext fragments. - * - * This determines the size of both the incoming and outgoing TLS I/O buffers - * in such a way that both are capable of holding the specified amount of - * plaintext data, regardless of the protection mechanism used. - * - * To configure incoming and outgoing I/O buffers separately, use - * #MBEDTLS_SSL_IN_CONTENT_LEN and #MBEDTLS_SSL_OUT_CONTENT_LEN, - * which overwrite the value set by this option. - * - * \note When using a value less than the default of 16KB on the client, it is - * recommended to use the Maximum Fragment Length (MFL) extension to - * inform the server about this limitation. On the server, there - * is no supported, standardized way of informing the client about - * restriction on the maximum size of incoming messages, and unless - * the limitation has been communicated by other means, it is recommended - * to only change the outgoing buffer size #MBEDTLS_SSL_OUT_CONTENT_LEN - * while keeping the default value of 16KB for the incoming buffer. - * - * Uncomment to set the maximum plaintext size of both - * incoming and outgoing I/O buffers. - */ -//#define MBEDTLS_SSL_MAX_CONTENT_LEN 16384 - /** \def MBEDTLS_SSL_IN_CONTENT_LEN * * Maximum length (in bytes) of incoming plaintext fragments. @@ -4068,9 +4052,6 @@ * that it is capable of holding the specified amount of plaintext data, * regardless of the protection mechanism used. * - * If this option is undefined, it inherits its value from - * #MBEDTLS_SSL_MAX_CONTENT_LEN. - * * \note When using a value less than the default of 16KB on the client, it is * recommended to use the Maximum Fragment Length (MFL) extension to * inform the server about this limitation. On the server, there @@ -4080,8 +4061,7 @@ * to only change the outgoing buffer size #MBEDTLS_SSL_OUT_CONTENT_LEN * while keeping the default value of 16KB for the incoming buffer. * - * Uncomment to set the maximum plaintext size of the incoming I/O buffer - * independently of the outgoing I/O buffer. + * Uncomment to set the maximum plaintext size of the incoming I/O buffer. */ //#define MBEDTLS_SSL_IN_CONTENT_LEN 16384 @@ -4099,27 +4079,10 @@ */ //#define MBEDTLS_SSL_CID_OUT_LEN_MAX 32 -/** \def MBEDTLS_SSL_CID_PADDING_GRANULARITY - * - * This option controls the use of record plaintext padding - * when using the Connection ID extension in DTLS 1.2. - * - * The padding will always be chosen so that the length of the - * padded plaintext is a multiple of the value of this option. - * - * Note: A value of \c 1 means that no padding will be used - * for outgoing records. - * - * Note: On systems lacking division instructions, - * a power of two should be preferred. - * - */ -//#define MBEDTLS_SSL_CID_PADDING_GRANULARITY 16 - -/** \def MBEDTLS_SSL_TLS1_3_PADDING_GRANULARITY +/** \def MBEDTLS_SSL_CID_TLS1_3_PADDING_GRANULARITY * * This option controls the use of record plaintext padding - * in TLS 1.3. + * in TLS 1.3 and when using the Connection ID extension in DTLS 1.2. * * The padding will always be chosen so that the length of the * padded plaintext is a multiple of the value of this option. @@ -4130,7 +4093,7 @@ * Note: On systems lacking division instructions, * a power of two should be preferred. */ -//#define MBEDTLS_SSL_TLS1_3_PADDING_GRANULARITY 1 +//#define MBEDTLS_SSL_CID_TLS1_3_PADDING_GRANULARITY 16 /** \def MBEDTLS_SSL_OUT_CONTENT_LEN * @@ -4140,9 +4103,6 @@ * that it is capable of holding the specified amount of plaintext data, * regardless of the protection mechanism used. * - * If this option undefined, it inherits its value from - * #MBEDTLS_SSL_MAX_CONTENT_LEN. - * * It is possible to save RAM by setting a smaller outward buffer, while keeping * the default inward 16384 byte buffer to conform to the TLS specification. * @@ -4151,8 +4111,7 @@ * The specific size requirement depends on the configured ciphers and any * certificate data which is sent during the handshake. * - * Uncomment to set the maximum plaintext size of the outgoing I/O buffer - * independently of the incoming I/O buffer. + * Uncomment to set the maximum plaintext size of the outgoing I/O buffer. */ //#define MBEDTLS_SSL_OUT_CONTENT_LEN 16384 @@ -4173,21 +4132,9 @@ */ //#define MBEDTLS_SSL_DTLS_MAX_BUFFERING 32768 -//#define MBEDTLS_SSL_DEFAULT_TICKET_LIFETIME 86400 /**< Lifetime of session tickets (if enabled) */ -//#define MBEDTLS_PSK_MAX_LEN 32 /**< Max size of TLS pre-shared keys, in bytes (default 256 bits) */ +//#define MBEDTLS_PSK_MAX_LEN 32 /**< Max size of TLS pre-shared keys, in bytes (default 256 or 384 bits) */ //#define MBEDTLS_SSL_COOKIE_TIMEOUT 60 /**< Default expiration delay of DTLS cookies, in seconds if HAVE_TIME, or in number of cookies issued */ -/** \def MBEDTLS_TLS_EXT_CID - * - * At the time of writing, the CID extension has not been assigned its - * final value. Set this configuration option to make Mbed TLS use a - * different value. - * - * A future minor revision of Mbed TLS may change the default value of - * this option to match evolving standards and usage. - */ -//#define MBEDTLS_TLS_EXT_CID 254 - /** * Complete list of ciphersuites to use, in order of preference. * @@ -4202,25 +4149,63 @@ */ //#define MBEDTLS_SSL_CIPHERSUITES MBEDTLS_TLS_ECDHE_ECDSA_WITH_AES_256_GCM_SHA384,MBEDTLS_TLS_ECDHE_ECDSA_WITH_AES_128_GCM_SHA256 -/* X509 options */ -//#define MBEDTLS_X509_MAX_INTERMEDIATE_CA 8 /**< Maximum number of intermediate CAs in a verification chain. */ -//#define MBEDTLS_X509_MAX_FILE_PATH_LEN 512 /**< Maximum length of a path/filename string in bytes including the null terminator character ('\0'). */ +/** + * \def MBEDTLS_SSL_MAX_EARLY_DATA_SIZE + * + * The default maximum amount of 0-RTT data. See the documentation of + * \c mbedtls_ssl_conf_max_early_data_size() for more information. + * + * It must be positive and smaller than UINT32_MAX. + * + * If MBEDTLS_SSL_EARLY_DATA is not defined, this default value does not + * have any impact on the build. + */ +//#define MBEDTLS_SSL_MAX_EARLY_DATA_SIZE 1024 -/** \} name SECTION: Module configuration options */ +/** + * \def MBEDTLS_SSL_TLS1_3_TICKET_AGE_TOLERANCE + * + * Maximum allowed ticket age difference in milliseconds tolerated between + * server and client. Default value is 6000. This is not used in TLS 1.2. + * + * - The client ticket age is the time difference between the time when the + * client proposes to the server to use the ticket and the time the client + * received the ticket from the server. + * - The server ticket age is the time difference between the time when the + * server receives a proposition from the client to use the ticket and the + * time when the ticket was created by the server. + * + * The ages might be different due to the client and server clocks not running + * at the same pace. The typical accuracy of an RTC crystal is ±100 to ±20 parts + * per million (360 to 72 milliseconds per hour). Default tolerance window is + * 6s, thus in the worst case clients and servers must sync up their system time + * every 6000/360/2~=8 hours. + * + * See section 8.3 of the TLS 1.3 specification(RFC 8446) for more information. + */ +//#define MBEDTLS_SSL_TLS1_3_TICKET_AGE_TOLERANCE 6000 -/* Target and application specific configurations +/** + * \def MBEDTLS_SSL_TLS1_3_TICKET_NONCE_LENGTH * - * Allow user to override any previous default. + * Size in bytes of a ticket nonce. This is not used in TLS 1.2. * + * This must be less than 256. */ -#if defined(MBEDTLS_USER_CONFIG_FILE) -#include MBEDTLS_USER_CONFIG_FILE -#endif +//#define MBEDTLS_SSL_TLS1_3_TICKET_NONCE_LENGTH 32 -#if defined(MBEDTLS_PSA_CRYPTO_CONFIG) -#include "mbedtls/config_psa.h" -#endif +/** + * \def MBEDTLS_SSL_TLS1_3_DEFAULT_NEW_SESSION_TICKETS + * + * Default number of NewSessionTicket messages to be sent by a TLS 1.3 server + * after handshake completion. This is not used in TLS 1.2 and relevant only if + * the MBEDTLS_SSL_SESSION_TICKETS option is enabled. + * + */ +//#define MBEDTLS_SSL_TLS1_3_DEFAULT_NEW_SESSION_TICKETS 1 -#include "mbedtls/check_config.h" +/* X509 options */ +//#define MBEDTLS_X509_MAX_INTERMEDIATE_CA 8 /**< Maximum number of intermediate CAs in a verification chain. */ +//#define MBEDTLS_X509_MAX_FILE_PATH_LEN 512 /**< Maximum length of a path/filename string in bytes including the null terminator character ('\0'). */ -#endif /* MBEDTLS_CONFIG_H */ +/** \} name SECTION: Module configuration options */ diff --git a/vendor/mbedtls/include/mbedtls/md.h b/vendor/mbedtls/include/mbedtls/md.h index db4d14c044..478e9f7667 100644 --- a/vendor/mbedtls/include/mbedtls/md.h +++ b/vendor/mbedtls/include/mbedtls/md.h @@ -1,37 +1,23 @@ /** * \file md.h * - * \brief This file contains the generic message-digest wrapper. + * \brief This file contains the generic functions for message-digest + * (hashing) and HMAC. * * \author Adriaan de Jong */ /* * Copyright The Mbed TLS Contributors - * SPDX-License-Identifier: Apache-2.0 - * - * Licensed under the Apache License, Version 2.0 (the "License"); you may - * not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT - * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. + * SPDX-License-Identifier: Apache-2.0 OR GPL-2.0-or-later */ #ifndef MBEDTLS_MD_H #define MBEDTLS_MD_H +#include "mbedtls/private_access.h" #include -#if !defined(MBEDTLS_CONFIG_FILE) -#include "mbedtls/config.h" -#else -#include MBEDTLS_CONFIG_FILE -#endif +#include "mbedtls/build_info.h" #include "mbedtls/platform_util.h" /** The selected feature is not available. */ @@ -43,10 +29,6 @@ /** Opening or reading of file failed. */ #define MBEDTLS_ERR_MD_FILE_IO_ERROR -0x5200 -/* MBEDTLS_ERR_MD_HW_ACCEL_FAILED is deprecated and should not be used. */ -/** MD hardware accelerator failed. */ -#define MBEDTLS_ERR_MD_HW_ACCEL_FAILED -0x5280 - #ifdef __cplusplus extern "C" { #endif @@ -54,79 +36,107 @@ extern "C" { /** * \brief Supported message digests. * - * \warning MD2, MD4, MD5 and SHA-1 are considered weak message digests and + * \warning MD5 and SHA-1 are considered weak message digests and * their use constitutes a security risk. We recommend considering * stronger message digests instead. * */ +/* Note: these are aligned with the definitions of PSA_ALG_ macros for hashes, + * in order to enable an efficient implementation of conversion functions. + * This is tested by md_to_from_psa() in test_suite_md. */ typedef enum { MBEDTLS_MD_NONE=0, /**< None. */ - MBEDTLS_MD_MD2, /**< The MD2 message digest. */ - MBEDTLS_MD_MD4, /**< The MD4 message digest. */ - MBEDTLS_MD_MD5, /**< The MD5 message digest. */ - MBEDTLS_MD_SHA1, /**< The SHA-1 message digest. */ - MBEDTLS_MD_SHA224, /**< The SHA-224 message digest. */ - MBEDTLS_MD_SHA256, /**< The SHA-256 message digest. */ - MBEDTLS_MD_SHA384, /**< The SHA-384 message digest. */ - MBEDTLS_MD_SHA512, /**< The SHA-512 message digest. */ - MBEDTLS_MD_RIPEMD160, /**< The RIPEMD-160 message digest. */ + MBEDTLS_MD_MD5=0x03, /**< The MD5 message digest. */ + MBEDTLS_MD_RIPEMD160=0x04, /**< The RIPEMD-160 message digest. */ + MBEDTLS_MD_SHA1=0x05, /**< The SHA-1 message digest. */ + MBEDTLS_MD_SHA224=0x08, /**< The SHA-224 message digest. */ + MBEDTLS_MD_SHA256=0x09, /**< The SHA-256 message digest. */ + MBEDTLS_MD_SHA384=0x0a, /**< The SHA-384 message digest. */ + MBEDTLS_MD_SHA512=0x0b, /**< The SHA-512 message digest. */ + MBEDTLS_MD_SHA3_224=0x10, /**< The SHA3-224 message digest. */ + MBEDTLS_MD_SHA3_256=0x11, /**< The SHA3-256 message digest. */ + MBEDTLS_MD_SHA3_384=0x12, /**< The SHA3-384 message digest. */ + MBEDTLS_MD_SHA3_512=0x13, /**< The SHA3-512 message digest. */ } mbedtls_md_type_t; -#if defined(MBEDTLS_SHA512_C) +/* Note: this should always be >= PSA_HASH_MAX_SIZE + * in all builds with both CRYPTO_C and MD_LIGHT. + * + * This is to make things easier for modules such as TLS that may define a + * buffer size using MD_MAX_SIZE in a part of the code that's common to PSA + * and legacy, then assume the buffer's size is PSA_HASH_MAX_SIZE in another + * part of the code based on PSA. + */ +#if defined(MBEDTLS_MD_CAN_SHA512) || defined(MBEDTLS_MD_CAN_SHA3_512) #define MBEDTLS_MD_MAX_SIZE 64 /* longest known is SHA512 */ +#elif defined(MBEDTLS_MD_CAN_SHA384) || defined(MBEDTLS_MD_CAN_SHA3_384) +#define MBEDTLS_MD_MAX_SIZE 48 /* longest known is SHA384 */ +#elif defined(MBEDTLS_MD_CAN_SHA256) || defined(MBEDTLS_MD_CAN_SHA3_256) +#define MBEDTLS_MD_MAX_SIZE 32 /* longest known is SHA256 */ +#elif defined(MBEDTLS_MD_CAN_SHA224) || defined(MBEDTLS_MD_CAN_SHA3_224) +#define MBEDTLS_MD_MAX_SIZE 28 /* longest known is SHA224 */ #else -#define MBEDTLS_MD_MAX_SIZE 32 /* longest known is SHA256 or less */ +#define MBEDTLS_MD_MAX_SIZE 20 /* longest known is SHA1 or RIPE MD-160 + or smaller (MD5 and earlier) */ #endif -#if defined(MBEDTLS_SHA512_C) +#if defined(MBEDTLS_MD_CAN_SHA3_224) +#define MBEDTLS_MD_MAX_BLOCK_SIZE 144 /* the longest known is SHA3-224 */ +#elif defined(MBEDTLS_MD_CAN_SHA3_256) +#define MBEDTLS_MD_MAX_BLOCK_SIZE 136 +#elif defined(MBEDTLS_MD_CAN_SHA512) || defined(MBEDTLS_MD_CAN_SHA384) #define MBEDTLS_MD_MAX_BLOCK_SIZE 128 +#elif defined(MBEDTLS_MD_CAN_SHA3_384) +#define MBEDTLS_MD_MAX_BLOCK_SIZE 104 +#elif defined(MBEDTLS_MD_CAN_SHA3_512) +#define MBEDTLS_MD_MAX_BLOCK_SIZE 72 #else #define MBEDTLS_MD_MAX_BLOCK_SIZE 64 #endif /** - * Opaque struct defined in md_internal.h. + * Opaque struct. + * + * Constructed using either #mbedtls_md_info_from_string or + * #mbedtls_md_info_from_type. + * + * Fields can be accessed with #mbedtls_md_get_size, + * #mbedtls_md_get_type and #mbedtls_md_get_name. */ +/* Defined internally in library/md_wrap.h. */ typedef struct mbedtls_md_info_t mbedtls_md_info_t; +/** + * Used internally to indicate whether a context uses legacy or PSA. + * + * Internal use only. + */ +typedef enum { + MBEDTLS_MD_ENGINE_LEGACY = 0, + MBEDTLS_MD_ENGINE_PSA, +} mbedtls_md_engine_t; + /** * The generic message-digest context. */ typedef struct mbedtls_md_context_t { /** Information about the associated message digest. */ - const mbedtls_md_info_t *md_info; + const mbedtls_md_info_t *MBEDTLS_PRIVATE(md_info); + +#if defined(MBEDTLS_MD_SOME_PSA) + /** Are hash operations dispatched to PSA or legacy? */ + mbedtls_md_engine_t MBEDTLS_PRIVATE(engine); +#endif - /** The digest-specific context. */ - void *md_ctx; + /** The digest-specific context (legacy) or the PSA operation. */ + void *MBEDTLS_PRIVATE(md_ctx); +#if defined(MBEDTLS_MD_C) /** The HMAC part of the context. */ - void *hmac_ctx; + void *MBEDTLS_PRIVATE(hmac_ctx); +#endif } mbedtls_md_context_t; -/** - * \brief This function returns the list of digests supported by the - * generic digest module. - * - * \note The list starts with the strongest available hashes. - * - * \return A statically allocated array of digests. Each element - * in the returned list is an integer belonging to the - * message-digest enumeration #mbedtls_md_type_t. - * The last entry is 0. - */ -const int *mbedtls_md_list(void); - -/** - * \brief This function returns the message-digest information - * associated with the given digest name. - * - * \param md_name The name of the digest to search for. - * - * \return The message-digest information associated with \p md_name. - * \return NULL if the associated message-digest information is not found. - */ -const mbedtls_md_info_t *mbedtls_md_info_from_string(const char *md_name); - /** * \brief This function returns the message-digest information * associated with the given digest type. @@ -163,34 +173,6 @@ void mbedtls_md_init(mbedtls_md_context_t *ctx); */ void mbedtls_md_free(mbedtls_md_context_t *ctx); -#if !defined(MBEDTLS_DEPRECATED_REMOVED) -#if defined(MBEDTLS_DEPRECATED_WARNING) -#define MBEDTLS_DEPRECATED __attribute__((deprecated)) -#else -#define MBEDTLS_DEPRECATED -#endif -/** - * \brief This function selects the message digest algorithm to use, - * and allocates internal structures. - * - * It should be called after mbedtls_md_init() or mbedtls_md_free(). - * Makes it necessary to call mbedtls_md_free() later. - * - * \deprecated Superseded by mbedtls_md_setup() in 2.0.0 - * - * \param ctx The context to set up. - * \param md_info The information structure of the message-digest algorithm - * to use. - * - * \return \c 0 on success. - * \return #MBEDTLS_ERR_MD_BAD_INPUT_DATA on parameter-verification - * failure. - * \return #MBEDTLS_ERR_MD_ALLOC_FAILED on memory-allocation failure. - */ -int mbedtls_md_init_ctx(mbedtls_md_context_t *ctx, - const mbedtls_md_info_t *md_info) MBEDTLS_DEPRECATED; -#undef MBEDTLS_DEPRECATED -#endif /* MBEDTLS_DEPRECATED_REMOVED */ /** * \brief This function selects the message digest algorithm to use, @@ -232,6 +214,10 @@ int mbedtls_md_setup(mbedtls_md_context_t *ctx, const mbedtls_md_info_t *md_info * * \return \c 0 on success. * \return #MBEDTLS_ERR_MD_BAD_INPUT_DATA on parameter-verification failure. + * \return #MBEDTLS_ERR_MD_FEATURE_UNAVAILABLE if both contexts are + * not using the same engine. This can be avoided by moving + * the call to psa_crypto_init() before the first call to + * mbedtls_md_setup(). */ MBEDTLS_CHECK_RETURN_TYPICAL int mbedtls_md_clone(mbedtls_md_context_t *dst, @@ -249,26 +235,29 @@ int mbedtls_md_clone(mbedtls_md_context_t *dst, unsigned char mbedtls_md_get_size(const mbedtls_md_info_t *md_info); /** - * \brief This function extracts the message-digest type from the - * message-digest information structure. + * \brief This function gives the message-digest size associated to + * message-digest type. * - * \param md_info The information structure of the message-digest algorithm - * to use. + * \param md_type The message-digest type. * - * \return The type of the message digest. + * \return The size of the message-digest output in Bytes, + * or 0 if the message-digest type is not known. */ -mbedtls_md_type_t mbedtls_md_get_type(const mbedtls_md_info_t *md_info); +static inline unsigned char mbedtls_md_get_size_from_type(mbedtls_md_type_t md_type) +{ + return mbedtls_md_get_size(mbedtls_md_info_from_type(md_type)); +} /** - * \brief This function extracts the message-digest name from the + * \brief This function extracts the message-digest type from the * message-digest information structure. * * \param md_info The information structure of the message-digest algorithm * to use. * - * \return The name of the message digest. + * \return The type of the message digest. */ -const char *mbedtls_md_get_name(const mbedtls_md_info_t *md_info); +mbedtls_md_type_t mbedtls_md_get_type(const mbedtls_md_info_t *md_info); /** * \brief This function starts a message-digest computation. @@ -348,6 +337,54 @@ MBEDTLS_CHECK_RETURN_TYPICAL int mbedtls_md(const mbedtls_md_info_t *md_info, const unsigned char *input, size_t ilen, unsigned char *output); +/** + * \brief This function returns the list of digests supported by the + * generic digest module. + * + * \note The list starts with the strongest available hashes. + * + * \return A statically allocated array of digests. Each element + * in the returned list is an integer belonging to the + * message-digest enumeration #mbedtls_md_type_t. + * The last entry is 0. + */ +const int *mbedtls_md_list(void); + +/** + * \brief This function returns the message-digest information + * associated with the given digest name. + * + * \param md_name The name of the digest to search for. + * + * \return The message-digest information associated with \p md_name. + * \return NULL if the associated message-digest information is not found. + */ +const mbedtls_md_info_t *mbedtls_md_info_from_string(const char *md_name); + +/** + * \brief This function returns the name of the message digest for + * the message-digest information structure given. + * + * \param md_info The information structure of the message-digest algorithm + * to use. + * + * \return The name of the message digest. + */ +const char *mbedtls_md_get_name(const mbedtls_md_info_t *md_info); + +/** + * \brief This function returns the message-digest information + * from the given context. + * + * \param ctx The context from which to extract the information. + * This must be initialized (or \c NULL). + * + * \return The message-digest information associated with \p ctx. + * \return \c NULL if \p ctx is \c NULL. + */ +const mbedtls_md_info_t *mbedtls_md_info_from_ctx( + const mbedtls_md_context_t *ctx); + #if defined(MBEDTLS_FS_IO) /** * \brief This function calculates the message-digest checksum @@ -482,10 +519,6 @@ int mbedtls_md_hmac(const mbedtls_md_info_t *md_info, const unsigned char *key, const unsigned char *input, size_t ilen, unsigned char *output); -/* Internal use */ -MBEDTLS_CHECK_RETURN_TYPICAL -int mbedtls_md_process(mbedtls_md_context_t *ctx, const unsigned char *data); - #ifdef __cplusplus } #endif diff --git a/vendor/mbedtls/include/mbedtls/md2.h b/vendor/mbedtls/include/mbedtls/md2.h deleted file mode 100644 index 68b0d32712..0000000000 --- a/vendor/mbedtls/include/mbedtls/md2.h +++ /dev/null @@ -1,304 +0,0 @@ -/** - * \file md2.h - * - * \brief MD2 message digest algorithm (hash function) - * - * \warning MD2 is considered a weak message digest and its use constitutes a - * security risk. We recommend considering stronger message digests - * instead. - */ -/* - * Copyright The Mbed TLS Contributors - * SPDX-License-Identifier: Apache-2.0 - * - * Licensed under the Apache License, Version 2.0 (the "License"); you may - * not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT - * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - * - */ -#ifndef MBEDTLS_MD2_H -#define MBEDTLS_MD2_H - -#if !defined(MBEDTLS_CONFIG_FILE) -#include "mbedtls/config.h" -#else -#include MBEDTLS_CONFIG_FILE -#endif - -#include - -/* MBEDTLS_ERR_MD2_HW_ACCEL_FAILED is deprecated and should not be used. */ -/** MD2 hardware accelerator failed */ -#define MBEDTLS_ERR_MD2_HW_ACCEL_FAILED -0x002B - -#ifdef __cplusplus -extern "C" { -#endif - -#if !defined(MBEDTLS_MD2_ALT) -// Regular implementation -// - -/** - * \brief MD2 context structure - * - * \warning MD2 is considered a weak message digest and its use - * constitutes a security risk. We recommend considering - * stronger message digests instead. - * - */ -typedef struct mbedtls_md2_context { - unsigned char cksum[16]; /*!< checksum of the data block */ - unsigned char state[48]; /*!< intermediate digest state */ - unsigned char buffer[16]; /*!< data block being processed */ - size_t left; /*!< amount of data in buffer */ -} -mbedtls_md2_context; - -#else /* MBEDTLS_MD2_ALT */ -#include "md2_alt.h" -#endif /* MBEDTLS_MD2_ALT */ - -/** - * \brief Initialize MD2 context - * - * \param ctx MD2 context to be initialized - * - * \warning MD2 is considered a weak message digest and its use - * constitutes a security risk. We recommend considering - * stronger message digests instead. - * - */ -void mbedtls_md2_init(mbedtls_md2_context *ctx); - -/** - * \brief Clear MD2 context - * - * \param ctx MD2 context to be cleared - * - * \warning MD2 is considered a weak message digest and its use - * constitutes a security risk. We recommend considering - * stronger message digests instead. - * - */ -void mbedtls_md2_free(mbedtls_md2_context *ctx); - -/** - * \brief Clone (the state of) an MD2 context - * - * \param dst The destination context - * \param src The context to be cloned - * - * \warning MD2 is considered a weak message digest and its use - * constitutes a security risk. We recommend considering - * stronger message digests instead. - * - */ -void mbedtls_md2_clone(mbedtls_md2_context *dst, - const mbedtls_md2_context *src); - -/** - * \brief MD2 context setup - * - * \param ctx context to be initialized - * - * \return 0 if successful - * - * \warning MD2 is considered a weak message digest and its use - * constitutes a security risk. We recommend considering - * stronger message digests instead. - * - */ -int mbedtls_md2_starts_ret(mbedtls_md2_context *ctx); - -/** - * \brief MD2 process buffer - * - * \param ctx MD2 context - * \param input buffer holding the data - * \param ilen length of the input data - * - * \return 0 if successful - * - * \warning MD2 is considered a weak message digest and its use - * constitutes a security risk. We recommend considering - * stronger message digests instead. - * - */ -int mbedtls_md2_update_ret(mbedtls_md2_context *ctx, - const unsigned char *input, - size_t ilen); - -/** - * \brief MD2 final digest - * - * \param ctx MD2 context - * \param output MD2 checksum result - * - * \return 0 if successful - * - * \warning MD2 is considered a weak message digest and its use - * constitutes a security risk. We recommend considering - * stronger message digests instead. - * - */ -int mbedtls_md2_finish_ret(mbedtls_md2_context *ctx, - unsigned char output[16]); - -/** - * \brief MD2 process data block (internal use only) - * - * \param ctx MD2 context - * - * \return 0 if successful - * - * \warning MD2 is considered a weak message digest and its use - * constitutes a security risk. We recommend considering - * stronger message digests instead. - * - */ -int mbedtls_internal_md2_process(mbedtls_md2_context *ctx); - -#if !defined(MBEDTLS_DEPRECATED_REMOVED) -#if defined(MBEDTLS_DEPRECATED_WARNING) -#define MBEDTLS_DEPRECATED __attribute__((deprecated)) -#else -#define MBEDTLS_DEPRECATED -#endif -/** - * \brief MD2 context setup - * - * \deprecated Superseded by mbedtls_md2_starts_ret() in 2.7.0 - * - * \param ctx context to be initialized - * - * \warning MD2 is considered a weak message digest and its use - * constitutes a security risk. We recommend considering - * stronger message digests instead. - * - */ -MBEDTLS_DEPRECATED void mbedtls_md2_starts(mbedtls_md2_context *ctx); - -/** - * \brief MD2 process buffer - * - * \deprecated Superseded by mbedtls_md2_update_ret() in 2.7.0 - * - * \param ctx MD2 context - * \param input buffer holding the data - * \param ilen length of the input data - * - * \warning MD2 is considered a weak message digest and its use - * constitutes a security risk. We recommend considering - * stronger message digests instead. - * - */ -MBEDTLS_DEPRECATED void mbedtls_md2_update(mbedtls_md2_context *ctx, - const unsigned char *input, - size_t ilen); - -/** - * \brief MD2 final digest - * - * \deprecated Superseded by mbedtls_md2_finish_ret() in 2.7.0 - * - * \param ctx MD2 context - * \param output MD2 checksum result - * - * \warning MD2 is considered a weak message digest and its use - * constitutes a security risk. We recommend considering - * stronger message digests instead. - * - */ -MBEDTLS_DEPRECATED void mbedtls_md2_finish(mbedtls_md2_context *ctx, - unsigned char output[16]); - -/** - * \brief MD2 process data block (internal use only) - * - * \deprecated Superseded by mbedtls_internal_md2_process() in 2.7.0 - * - * \param ctx MD2 context - * - * \warning MD2 is considered a weak message digest and its use - * constitutes a security risk. We recommend considering - * stronger message digests instead. - * - */ -MBEDTLS_DEPRECATED void mbedtls_md2_process(mbedtls_md2_context *ctx); - -#undef MBEDTLS_DEPRECATED -#endif /* !MBEDTLS_DEPRECATED_REMOVED */ - -/** - * \brief Output = MD2( input buffer ) - * - * \param input buffer holding the data - * \param ilen length of the input data - * \param output MD2 checksum result - * - * \warning MD2 is considered a weak message digest and its use - * constitutes a security risk. We recommend considering - * stronger message digests instead. - * - */ -int mbedtls_md2_ret(const unsigned char *input, - size_t ilen, - unsigned char output[16]); - -#if !defined(MBEDTLS_DEPRECATED_REMOVED) -#if defined(MBEDTLS_DEPRECATED_WARNING) -#define MBEDTLS_DEPRECATED __attribute__((deprecated)) -#else -#define MBEDTLS_DEPRECATED -#endif -/** - * \brief Output = MD2( input buffer ) - * - * \deprecated Superseded by mbedtls_md2_ret() in 2.7.0 - * - * \param input buffer holding the data - * \param ilen length of the input data - * \param output MD2 checksum result - * - * \warning MD2 is considered a weak message digest and its use - * constitutes a security risk. We recommend considering - * stronger message digests instead. - * - */ -MBEDTLS_DEPRECATED void mbedtls_md2(const unsigned char *input, - size_t ilen, - unsigned char output[16]); - -#undef MBEDTLS_DEPRECATED -#endif /* !MBEDTLS_DEPRECATED_REMOVED */ - -#if defined(MBEDTLS_SELF_TEST) - -/** - * \brief Checkup routine - * - * \return 0 if successful, or 1 if the test failed - * - * \warning MD2 is considered a weak message digest and its use - * constitutes a security risk. We recommend considering - * stronger message digests instead. - * - */ -int mbedtls_md2_self_test(int verbose); - -#endif /* MBEDTLS_SELF_TEST */ - -#ifdef __cplusplus -} -#endif - -#endif /* mbedtls_md2.h */ diff --git a/vendor/mbedtls/include/mbedtls/md4.h b/vendor/mbedtls/include/mbedtls/md4.h deleted file mode 100644 index fd64710a1b..0000000000 --- a/vendor/mbedtls/include/mbedtls/md4.h +++ /dev/null @@ -1,309 +0,0 @@ -/** - * \file md4.h - * - * \brief MD4 message digest algorithm (hash function) - * - * \warning MD4 is considered a weak message digest and its use constitutes a - * security risk. We recommend considering stronger message digests - * instead. - */ -/* - * Copyright The Mbed TLS Contributors - * SPDX-License-Identifier: Apache-2.0 - * - * Licensed under the Apache License, Version 2.0 (the "License"); you may - * not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT - * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - * - */ -#ifndef MBEDTLS_MD4_H -#define MBEDTLS_MD4_H - -#if !defined(MBEDTLS_CONFIG_FILE) -#include "mbedtls/config.h" -#else -#include MBEDTLS_CONFIG_FILE -#endif - -#include -#include - -/* MBEDTLS_ERR_MD4_HW_ACCEL_FAILED is deprecated and should not be used. */ -/** MD4 hardware accelerator failed */ -#define MBEDTLS_ERR_MD4_HW_ACCEL_FAILED -0x002D - -#ifdef __cplusplus -extern "C" { -#endif - -#if !defined(MBEDTLS_MD4_ALT) -// Regular implementation -// - -/** - * \brief MD4 context structure - * - * \warning MD4 is considered a weak message digest and its use - * constitutes a security risk. We recommend considering - * stronger message digests instead. - * - */ -typedef struct mbedtls_md4_context { - uint32_t total[2]; /*!< number of bytes processed */ - uint32_t state[4]; /*!< intermediate digest state */ - unsigned char buffer[64]; /*!< data block being processed */ -} -mbedtls_md4_context; - -#else /* MBEDTLS_MD4_ALT */ -#include "md4_alt.h" -#endif /* MBEDTLS_MD4_ALT */ - -/** - * \brief Initialize MD4 context - * - * \param ctx MD4 context to be initialized - * - * \warning MD4 is considered a weak message digest and its use - * constitutes a security risk. We recommend considering - * stronger message digests instead. - * - */ -void mbedtls_md4_init(mbedtls_md4_context *ctx); - -/** - * \brief Clear MD4 context - * - * \param ctx MD4 context to be cleared - * - * \warning MD4 is considered a weak message digest and its use - * constitutes a security risk. We recommend considering - * stronger message digests instead. - * - */ -void mbedtls_md4_free(mbedtls_md4_context *ctx); - -/** - * \brief Clone (the state of) an MD4 context - * - * \param dst The destination context - * \param src The context to be cloned - * - * \warning MD4 is considered a weak message digest and its use - * constitutes a security risk. We recommend considering - * stronger message digests instead. - * - */ -void mbedtls_md4_clone(mbedtls_md4_context *dst, - const mbedtls_md4_context *src); - -/** - * \brief MD4 context setup - * - * \param ctx context to be initialized - * - * \return 0 if successful - * - * \warning MD4 is considered a weak message digest and its use - * constitutes a security risk. We recommend considering - * stronger message digests instead. - */ -int mbedtls_md4_starts_ret(mbedtls_md4_context *ctx); - -/** - * \brief MD4 process buffer - * - * \param ctx MD4 context - * \param input buffer holding the data - * \param ilen length of the input data - * - * \return 0 if successful - * - * \warning MD4 is considered a weak message digest and its use - * constitutes a security risk. We recommend considering - * stronger message digests instead. - * - */ -int mbedtls_md4_update_ret(mbedtls_md4_context *ctx, - const unsigned char *input, - size_t ilen); - -/** - * \brief MD4 final digest - * - * \param ctx MD4 context - * \param output MD4 checksum result - * - * \return 0 if successful - * - * \warning MD4 is considered a weak message digest and its use - * constitutes a security risk. We recommend considering - * stronger message digests instead. - * - */ -int mbedtls_md4_finish_ret(mbedtls_md4_context *ctx, - unsigned char output[16]); - -/** - * \brief MD4 process data block (internal use only) - * - * \param ctx MD4 context - * \param data buffer holding one block of data - * - * \return 0 if successful - * - * \warning MD4 is considered a weak message digest and its use - * constitutes a security risk. We recommend considering - * stronger message digests instead. - * - */ -int mbedtls_internal_md4_process(mbedtls_md4_context *ctx, - const unsigned char data[64]); - -#if !defined(MBEDTLS_DEPRECATED_REMOVED) -#if defined(MBEDTLS_DEPRECATED_WARNING) -#define MBEDTLS_DEPRECATED __attribute__((deprecated)) -#else -#define MBEDTLS_DEPRECATED -#endif -/** - * \brief MD4 context setup - * - * \deprecated Superseded by mbedtls_md4_starts_ret() in 2.7.0 - * - * \param ctx context to be initialized - * - * \warning MD4 is considered a weak message digest and its use - * constitutes a security risk. We recommend considering - * stronger message digests instead. - * - */ -MBEDTLS_DEPRECATED void mbedtls_md4_starts(mbedtls_md4_context *ctx); - -/** - * \brief MD4 process buffer - * - * \deprecated Superseded by mbedtls_md4_update_ret() in 2.7.0 - * - * \param ctx MD4 context - * \param input buffer holding the data - * \param ilen length of the input data - * - * \warning MD4 is considered a weak message digest and its use - * constitutes a security risk. We recommend considering - * stronger message digests instead. - * - */ -MBEDTLS_DEPRECATED void mbedtls_md4_update(mbedtls_md4_context *ctx, - const unsigned char *input, - size_t ilen); - -/** - * \brief MD4 final digest - * - * \deprecated Superseded by mbedtls_md4_finish_ret() in 2.7.0 - * - * \param ctx MD4 context - * \param output MD4 checksum result - * - * \warning MD4 is considered a weak message digest and its use - * constitutes a security risk. We recommend considering - * stronger message digests instead. - * - */ -MBEDTLS_DEPRECATED void mbedtls_md4_finish(mbedtls_md4_context *ctx, - unsigned char output[16]); - -/** - * \brief MD4 process data block (internal use only) - * - * \deprecated Superseded by mbedtls_internal_md4_process() in 2.7.0 - * - * \param ctx MD4 context - * \param data buffer holding one block of data - * - * \warning MD4 is considered a weak message digest and its use - * constitutes a security risk. We recommend considering - * stronger message digests instead. - * - */ -MBEDTLS_DEPRECATED void mbedtls_md4_process(mbedtls_md4_context *ctx, - const unsigned char data[64]); - -#undef MBEDTLS_DEPRECATED -#endif /* !MBEDTLS_DEPRECATED_REMOVED */ - -/** - * \brief Output = MD4( input buffer ) - * - * \param input buffer holding the data - * \param ilen length of the input data - * \param output MD4 checksum result - * - * \return 0 if successful - * - * \warning MD4 is considered a weak message digest and its use - * constitutes a security risk. We recommend considering - * stronger message digests instead. - * - */ -int mbedtls_md4_ret(const unsigned char *input, - size_t ilen, - unsigned char output[16]); - -#if !defined(MBEDTLS_DEPRECATED_REMOVED) -#if defined(MBEDTLS_DEPRECATED_WARNING) -#define MBEDTLS_DEPRECATED __attribute__((deprecated)) -#else -#define MBEDTLS_DEPRECATED -#endif -/** - * \brief Output = MD4( input buffer ) - * - * \deprecated Superseded by mbedtls_md4_ret() in 2.7.0 - * - * \param input buffer holding the data - * \param ilen length of the input data - * \param output MD4 checksum result - * - * \warning MD4 is considered a weak message digest and its use - * constitutes a security risk. We recommend considering - * stronger message digests instead. - * - */ -MBEDTLS_DEPRECATED void mbedtls_md4(const unsigned char *input, - size_t ilen, - unsigned char output[16]); - -#undef MBEDTLS_DEPRECATED -#endif /* !MBEDTLS_DEPRECATED_REMOVED */ - -#if defined(MBEDTLS_SELF_TEST) - -/** - * \brief Checkup routine - * - * \return 0 if successful, or 1 if the test failed - * - * \warning MD4 is considered a weak message digest and its use - * constitutes a security risk. We recommend considering - * stronger message digests instead. - * - */ -int mbedtls_md4_self_test(int verbose); - -#endif /* MBEDTLS_SELF_TEST */ - -#ifdef __cplusplus -} -#endif - -#endif /* mbedtls_md4.h */ diff --git a/vendor/mbedtls/include/mbedtls/md5.h b/vendor/mbedtls/include/mbedtls/md5.h index 04f71ee3f5..6bf0754a4a 100644 --- a/vendor/mbedtls/include/mbedtls/md5.h +++ b/vendor/mbedtls/include/mbedtls/md5.h @@ -9,36 +9,17 @@ */ /* * Copyright The Mbed TLS Contributors - * SPDX-License-Identifier: Apache-2.0 - * - * Licensed under the Apache License, Version 2.0 (the "License"); you may - * not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT - * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. + * SPDX-License-Identifier: Apache-2.0 OR GPL-2.0-or-later */ #ifndef MBEDTLS_MD5_H #define MBEDTLS_MD5_H +#include "mbedtls/private_access.h" -#if !defined(MBEDTLS_CONFIG_FILE) -#include "mbedtls/config.h" -#else -#include MBEDTLS_CONFIG_FILE -#endif +#include "mbedtls/build_info.h" #include #include -/* MBEDTLS_ERR_MD5_HW_ACCEL_FAILED is deprecated and should not be used. */ -/** MD5 hardware accelerator failed */ -#define MBEDTLS_ERR_MD5_HW_ACCEL_FAILED -0x002F - #ifdef __cplusplus extern "C" { #endif @@ -56,9 +37,9 @@ extern "C" { * */ typedef struct mbedtls_md5_context { - uint32_t total[2]; /*!< number of bytes processed */ - uint32_t state[4]; /*!< intermediate digest state */ - unsigned char buffer[64]; /*!< data block being processed */ + uint32_t MBEDTLS_PRIVATE(total)[2]; /*!< number of bytes processed */ + uint32_t MBEDTLS_PRIVATE(state)[4]; /*!< intermediate digest state */ + unsigned char MBEDTLS_PRIVATE(buffer)[64]; /*!< data block being processed */ } mbedtls_md5_context; @@ -116,7 +97,7 @@ void mbedtls_md5_clone(mbedtls_md5_context *dst, * stronger message digests instead. * */ -int mbedtls_md5_starts_ret(mbedtls_md5_context *ctx); +int mbedtls_md5_starts(mbedtls_md5_context *ctx); /** * \brief MD5 process buffer @@ -132,9 +113,9 @@ int mbedtls_md5_starts_ret(mbedtls_md5_context *ctx); * stronger message digests instead. * */ -int mbedtls_md5_update_ret(mbedtls_md5_context *ctx, - const unsigned char *input, - size_t ilen); +int mbedtls_md5_update(mbedtls_md5_context *ctx, + const unsigned char *input, + size_t ilen); /** * \brief MD5 final digest @@ -149,8 +130,8 @@ int mbedtls_md5_update_ret(mbedtls_md5_context *ctx, * stronger message digests instead. * */ -int mbedtls_md5_finish_ret(mbedtls_md5_context *ctx, - unsigned char output[16]); +int mbedtls_md5_finish(mbedtls_md5_context *ctx, + unsigned char output[16]); /** * \brief MD5 process data block (internal use only) @@ -168,79 +149,6 @@ int mbedtls_md5_finish_ret(mbedtls_md5_context *ctx, int mbedtls_internal_md5_process(mbedtls_md5_context *ctx, const unsigned char data[64]); -#if !defined(MBEDTLS_DEPRECATED_REMOVED) -#if defined(MBEDTLS_DEPRECATED_WARNING) -#define MBEDTLS_DEPRECATED __attribute__((deprecated)) -#else -#define MBEDTLS_DEPRECATED -#endif -/** - * \brief MD5 context setup - * - * \deprecated Superseded by mbedtls_md5_starts_ret() in 2.7.0 - * - * \param ctx context to be initialized - * - * \warning MD5 is considered a weak message digest and its use - * constitutes a security risk. We recommend considering - * stronger message digests instead. - * - */ -MBEDTLS_DEPRECATED void mbedtls_md5_starts(mbedtls_md5_context *ctx); - -/** - * \brief MD5 process buffer - * - * \deprecated Superseded by mbedtls_md5_update_ret() in 2.7.0 - * - * \param ctx MD5 context - * \param input buffer holding the data - * \param ilen length of the input data - * - * \warning MD5 is considered a weak message digest and its use - * constitutes a security risk. We recommend considering - * stronger message digests instead. - * - */ -MBEDTLS_DEPRECATED void mbedtls_md5_update(mbedtls_md5_context *ctx, - const unsigned char *input, - size_t ilen); - -/** - * \brief MD5 final digest - * - * \deprecated Superseded by mbedtls_md5_finish_ret() in 2.7.0 - * - * \param ctx MD5 context - * \param output MD5 checksum result - * - * \warning MD5 is considered a weak message digest and its use - * constitutes a security risk. We recommend considering - * stronger message digests instead. - * - */ -MBEDTLS_DEPRECATED void mbedtls_md5_finish(mbedtls_md5_context *ctx, - unsigned char output[16]); - -/** - * \brief MD5 process data block (internal use only) - * - * \deprecated Superseded by mbedtls_internal_md5_process() in 2.7.0 - * - * \param ctx MD5 context - * \param data buffer holding one block of data - * - * \warning MD5 is considered a weak message digest and its use - * constitutes a security risk. We recommend considering - * stronger message digests instead. - * - */ -MBEDTLS_DEPRECATED void mbedtls_md5_process(mbedtls_md5_context *ctx, - const unsigned char data[64]); - -#undef MBEDTLS_DEPRECATED -#endif /* !MBEDTLS_DEPRECATED_REMOVED */ - /** * \brief Output = MD5( input buffer ) * @@ -255,36 +163,9 @@ MBEDTLS_DEPRECATED void mbedtls_md5_process(mbedtls_md5_context *ctx, * stronger message digests instead. * */ -int mbedtls_md5_ret(const unsigned char *input, - size_t ilen, - unsigned char output[16]); - -#if !defined(MBEDTLS_DEPRECATED_REMOVED) -#if defined(MBEDTLS_DEPRECATED_WARNING) -#define MBEDTLS_DEPRECATED __attribute__((deprecated)) -#else -#define MBEDTLS_DEPRECATED -#endif -/** - * \brief Output = MD5( input buffer ) - * - * \deprecated Superseded by mbedtls_md5_ret() in 2.7.0 - * - * \param input buffer holding the data - * \param ilen length of the input data - * \param output MD5 checksum result - * - * \warning MD5 is considered a weak message digest and its use - * constitutes a security risk. We recommend considering - * stronger message digests instead. - * - */ -MBEDTLS_DEPRECATED void mbedtls_md5(const unsigned char *input, - size_t ilen, - unsigned char output[16]); - -#undef MBEDTLS_DEPRECATED -#endif /* !MBEDTLS_DEPRECATED_REMOVED */ +int mbedtls_md5(const unsigned char *input, + size_t ilen, + unsigned char output[16]); #if defined(MBEDTLS_SELF_TEST) diff --git a/vendor/mbedtls/include/mbedtls/md_internal.h b/vendor/mbedtls/include/mbedtls/md_internal.h deleted file mode 100644 index 9e10f2409d..0000000000 --- a/vendor/mbedtls/include/mbedtls/md_internal.h +++ /dev/null @@ -1,89 +0,0 @@ -/** - * \file md_internal.h - * - * \brief Message digest wrappers. - * - * \warning This in an internal header. Do not include directly. - * - * \author Adriaan de Jong - */ -/* - * Copyright The Mbed TLS Contributors - * SPDX-License-Identifier: Apache-2.0 - * - * Licensed under the Apache License, Version 2.0 (the "License"); you may - * not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT - * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ -#ifndef MBEDTLS_MD_WRAP_H -#define MBEDTLS_MD_WRAP_H - -#if !defined(MBEDTLS_CONFIG_FILE) -#include "mbedtls/config.h" -#else -#include MBEDTLS_CONFIG_FILE -#endif - -#include "mbedtls/md.h" - -#ifdef __cplusplus -extern "C" { -#endif - -/** - * Message digest information. - * Allows message digest functions to be called in a generic way. - */ -struct mbedtls_md_info_t { - /** Name of the message digest */ - const char *name; - - /** Digest identifier */ - mbedtls_md_type_t type; - - /** Output length of the digest function in bytes */ - unsigned char size; - - /** Block length of the digest function in bytes */ - unsigned char block_size; -}; - -#if defined(MBEDTLS_MD2_C) -extern const mbedtls_md_info_t mbedtls_md2_info; -#endif -#if defined(MBEDTLS_MD4_C) -extern const mbedtls_md_info_t mbedtls_md4_info; -#endif -#if defined(MBEDTLS_MD5_C) -extern const mbedtls_md_info_t mbedtls_md5_info; -#endif -#if defined(MBEDTLS_RIPEMD160_C) -extern const mbedtls_md_info_t mbedtls_ripemd160_info; -#endif -#if defined(MBEDTLS_SHA1_C) -extern const mbedtls_md_info_t mbedtls_sha1_info; -#endif -#if defined(MBEDTLS_SHA256_C) -extern const mbedtls_md_info_t mbedtls_sha224_info; -extern const mbedtls_md_info_t mbedtls_sha256_info; -#endif -#if defined(MBEDTLS_SHA512_C) -#if !defined(MBEDTLS_SHA512_NO_SHA384) -extern const mbedtls_md_info_t mbedtls_sha384_info; -#endif -extern const mbedtls_md_info_t mbedtls_sha512_info; -#endif - -#ifdef __cplusplus -} -#endif - -#endif /* MBEDTLS_MD_WRAP_H */ diff --git a/vendor/mbedtls/include/mbedtls/memory_buffer_alloc.h b/vendor/mbedtls/include/mbedtls/memory_buffer_alloc.h index bc28252113..b527d9b665 100644 --- a/vendor/mbedtls/include/mbedtls/memory_buffer_alloc.h +++ b/vendor/mbedtls/include/mbedtls/memory_buffer_alloc.h @@ -5,28 +5,12 @@ */ /* * Copyright The Mbed TLS Contributors - * SPDX-License-Identifier: Apache-2.0 - * - * Licensed under the Apache License, Version 2.0 (the "License"); you may - * not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT - * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. + * SPDX-License-Identifier: Apache-2.0 OR GPL-2.0-or-later */ #ifndef MBEDTLS_MEMORY_BUFFER_ALLOC_H #define MBEDTLS_MEMORY_BUFFER_ALLOC_H -#if !defined(MBEDTLS_CONFIG_FILE) -#include "mbedtls/config.h" -#else -#include MBEDTLS_CONFIG_FILE -#endif +#include "mbedtls/build_info.h" #include @@ -34,7 +18,7 @@ * \name SECTION: Module settings * * The configuration options you can set for this module are in this section. - * Either change them in config.h or define them on the compiler command line. + * Either change them in mbedtls_config.h or define them on the compiler command line. * \{ */ @@ -95,6 +79,14 @@ void mbedtls_memory_buffer_set_verify(int verify); */ void mbedtls_memory_buffer_alloc_status(void); +/** + * \brief Get the number of alloc/free so far. + * + * \param alloc_count Number of allocations. + * \param free_count Number of frees. + */ +void mbedtls_memory_buffer_alloc_count_get(size_t *alloc_count, size_t *free_count); + /** * \brief Get the peak heap usage so far * diff --git a/vendor/mbedtls/include/mbedtls/net.h b/vendor/mbedtls/include/mbedtls/net.h deleted file mode 100644 index 66921887da..0000000000 --- a/vendor/mbedtls/include/mbedtls/net.h +++ /dev/null @@ -1,35 +0,0 @@ -/** - * \file net.h - * - * \brief Deprecated header file that includes net_sockets.h - * - * \deprecated Superseded by mbedtls/net_sockets.h - */ -/* - * Copyright The Mbed TLS Contributors - * SPDX-License-Identifier: Apache-2.0 - * - * Licensed under the Apache License, Version 2.0 (the "License"); you may - * not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT - * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ -#if !defined(MBEDTLS_CONFIG_FILE) -#include "mbedtls/config.h" -#else -#include MBEDTLS_CONFIG_FILE -#endif - -#if !defined(MBEDTLS_DEPRECATED_REMOVED) -#include "mbedtls/net_sockets.h" -#if defined(MBEDTLS_DEPRECATED_WARNING) -#warning "Deprecated header file: Superseded by mbedtls/net_sockets.h" -#endif /* MBEDTLS_DEPRECATED_WARNING */ -#endif /* !MBEDTLS_DEPRECATED_REMOVED */ diff --git a/vendor/mbedtls/include/mbedtls/net_sockets.h b/vendor/mbedtls/include/mbedtls/net_sockets.h index 6bcd9208f9..85c11971d8 100644 --- a/vendor/mbedtls/include/mbedtls/net_sockets.h +++ b/vendor/mbedtls/include/mbedtls/net_sockets.h @@ -21,28 +21,13 @@ */ /* * Copyright The Mbed TLS Contributors - * SPDX-License-Identifier: Apache-2.0 - * - * Licensed under the Apache License, Version 2.0 (the "License"); you may - * not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT - * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. + * SPDX-License-Identifier: Apache-2.0 OR GPL-2.0-or-later */ #ifndef MBEDTLS_NET_SOCKETS_H #define MBEDTLS_NET_SOCKETS_H +#include "mbedtls/private_access.h" -#if !defined(MBEDTLS_CONFIG_FILE) -#include "mbedtls/config.h" -#else -#include MBEDTLS_CONFIG_FILE -#endif +#include "mbedtls/build_info.h" #include "mbedtls/ssl.h" @@ -96,7 +81,13 @@ extern "C" { * structures for hand-made UDP demultiplexing). */ typedef struct mbedtls_net_context { - int fd; /**< The underlying file descriptor */ + /** The underlying file descriptor. + * + * This field is only guaranteed to be present on POSIX/Unix-like platforms. + * On other platforms, it may have a different type, have a different + * meaning, or be absent altogether. + */ + int fd; } mbedtls_net_context; @@ -152,7 +143,7 @@ int mbedtls_net_bind(mbedtls_net_context *ctx, const char *bind_ip, const char * * \param client_ctx Will contain the connected client socket * \param client_ip Will contain the client IP address, can be NULL * \param buf_size Size of the client_ip buffer - * \param ip_len Will receive the size of the client IP written, + * \param cip_len Will receive the size of the client IP written, * can be NULL if client_ip is null * * \return 0 if successful, or @@ -165,7 +156,7 @@ int mbedtls_net_bind(mbedtls_net_context *ctx, const char *bind_ip, const char * */ int mbedtls_net_accept(mbedtls_net_context *bind_ctx, mbedtls_net_context *client_ctx, - void *client_ip, size_t buf_size, size_t *ip_len); + void *client_ip, size_t buf_size, size_t *cip_len); /** * \brief Check and wait for the context to be ready for read/write diff --git a/vendor/mbedtls/include/mbedtls/nist_kw.h b/vendor/mbedtls/include/mbedtls/nist_kw.h index 8d3a4a53b1..d353f3d1a8 100644 --- a/vendor/mbedtls/include/mbedtls/nist_kw.h +++ b/vendor/mbedtls/include/mbedtls/nist_kw.h @@ -17,29 +17,14 @@ */ /* * Copyright The Mbed TLS Contributors - * SPDX-License-Identifier: Apache-2.0 - * - * Licensed under the Apache License, Version 2.0 (the "License"); you may - * not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT - * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. + * SPDX-License-Identifier: Apache-2.0 OR GPL-2.0-or-later */ #ifndef MBEDTLS_NIST_KW_H #define MBEDTLS_NIST_KW_H +#include "mbedtls/private_access.h" -#if !defined(MBEDTLS_CONFIG_FILE) -#include "mbedtls/config.h" -#else -#include MBEDTLS_CONFIG_FILE -#endif +#include "mbedtls/build_info.h" #include "mbedtls/cipher.h" @@ -64,7 +49,7 @@ typedef enum { * Don't make any assumptions on this context! */ typedef struct { - mbedtls_cipher_context_t cipher_ctx; /*!< The cipher context used. */ + mbedtls_cipher_context_t MBEDTLS_PRIVATE(cipher_ctx); /*!< The cipher context used. */ } mbedtls_nist_kw_context; #else /* MBEDTLS_NIST_key wrapping_ALT */ diff --git a/vendor/mbedtls/include/mbedtls/oid.h b/vendor/mbedtls/include/mbedtls/oid.h index a64eaebef2..fdc25ebf88 100644 --- a/vendor/mbedtls/include/mbedtls/oid.h +++ b/vendor/mbedtls/include/mbedtls/oid.h @@ -5,28 +5,13 @@ */ /* * Copyright The Mbed TLS Contributors - * SPDX-License-Identifier: Apache-2.0 - * - * Licensed under the Apache License, Version 2.0 (the "License"); you may - * not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT - * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. + * SPDX-License-Identifier: Apache-2.0 OR GPL-2.0-or-later */ #ifndef MBEDTLS_OID_H #define MBEDTLS_OID_H +#include "mbedtls/private_access.h" -#if !defined(MBEDTLS_CONFIG_FILE) -#include "mbedtls/config.h" -#else -#include MBEDTLS_CONFIG_FILE -#endif +#include "mbedtls/build_info.h" #include "mbedtls/asn1.h" #include "mbedtls/pk.h" @@ -37,9 +22,7 @@ #include "mbedtls/cipher.h" #endif -#if defined(MBEDTLS_MD_C) #include "mbedtls/md.h" -#endif /** OID is not found. */ #define MBEDTLS_ERR_OID_NOT_FOUND -0x002E @@ -68,6 +51,11 @@ #define MBEDTLS_OID_X509_EXT_FRESHEST_CRL (1 << 14) #define MBEDTLS_OID_X509_EXT_NS_CERT_TYPE (1 << 16) +/* + * Maximum number of OID components allowed + */ +#define MBEDTLS_OID_MAX_COMPONENTS 128 + /* * Top level OID tuples */ @@ -95,6 +83,9 @@ #define MBEDTLS_OID_OIW_SECSIG MBEDTLS_OID_ORG_OIW "\x03" #define MBEDTLS_OID_OIW_SECSIG_ALG MBEDTLS_OID_OIW_SECSIG "\x02" #define MBEDTLS_OID_OIW_SECSIG_SHA1 MBEDTLS_OID_OIW_SECSIG_ALG "\x1a" +#define MBEDTLS_OID_ORG_THAWTE "\x65" /* thawte(101) */ +#define MBEDTLS_OID_THAWTE MBEDTLS_OID_ISO_IDENTIFIED_ORG \ + MBEDTLS_OID_ORG_THAWTE #define MBEDTLS_OID_ORG_CERTICOM "\x81\x04" /* certicom(132) */ #define MBEDTLS_OID_CERTICOM MBEDTLS_OID_ISO_IDENTIFIED_ORG \ MBEDTLS_OID_ORG_CERTICOM @@ -151,6 +142,7 @@ #define MBEDTLS_OID_AT_DN_QUALIFIER MBEDTLS_OID_AT "\x2E" /**< id-at-dnQualifier AttributeType:= {id-at 46} */ #define MBEDTLS_OID_AT_PSEUDONYM MBEDTLS_OID_AT "\x41" /**< id-at-pseudonym AttributeType:= {id-at 65} */ +#define MBEDTLS_OID_UID "\x09\x92\x26\x89\x93\xF2\x2C\x64\x01\x01" /** id-domainComponent AttributeType:= {itu-t(0) data(9) pss(2342) ucl(19200300) pilot(100) pilotAttributeType(1) uid(1)} */ #define MBEDTLS_OID_DOMAIN_COMPONENT "\x09\x92\x26\x89\x93\xF2\x2C\x64\x01\x19" /** id-domainComponent AttributeType:= {itu-t(0) data(9) pss(2342) ucl(19200300) pilot(100) pilotAttributeType(1) domainComponent(25)} */ /* @@ -228,6 +220,7 @@ #define MBEDTLS_OID_PKCS MBEDTLS_OID_RSA_COMPANY "\x01" /**< pkcs OBJECT IDENTIFIER ::= { iso(1) member-body(2) us(840) rsadsi(113549) 1 } */ #define MBEDTLS_OID_PKCS1 MBEDTLS_OID_PKCS "\x01" /**< pkcs-1 OBJECT IDENTIFIER ::= { iso(1) member-body(2) us(840) rsadsi(113549) pkcs(1) 1 } */ #define MBEDTLS_OID_PKCS5 MBEDTLS_OID_PKCS "\x05" /**< pkcs-5 OBJECT IDENTIFIER ::= { iso(1) member-body(2) us(840) rsadsi(113549) pkcs(1) 5 } */ +#define MBEDTLS_OID_PKCS7 MBEDTLS_OID_PKCS "\x07" /**< pkcs-7 OBJECT IDENTIFIER ::= { iso(1) member-body(2) us(840) rsadsi(113549) pkcs(1) 7 } */ #define MBEDTLS_OID_PKCS9 MBEDTLS_OID_PKCS "\x09" /**< pkcs-9 OBJECT IDENTIFIER ::= { iso(1) member-body(2) us(840) rsadsi(113549) pkcs(1) 9 } */ #define MBEDTLS_OID_PKCS12 MBEDTLS_OID_PKCS "\x0c" /**< pkcs-12 OBJECT IDENTIFIER ::= { iso(1) member-body(2) us(840) rsadsi(113549) pkcs(1) 12 } */ @@ -235,8 +228,6 @@ * PKCS#1 OIDs */ #define MBEDTLS_OID_PKCS1_RSA MBEDTLS_OID_PKCS1 "\x01" /**< rsaEncryption OBJECT IDENTIFIER ::= { pkcs-1 1 } */ -#define MBEDTLS_OID_PKCS1_MD2 MBEDTLS_OID_PKCS1 "\x02" /**< md2WithRSAEncryption ::= { pkcs-1 2 } */ -#define MBEDTLS_OID_PKCS1_MD4 MBEDTLS_OID_PKCS1 "\x03" /**< md4WithRSAEncryption ::= { pkcs-1 3 } */ #define MBEDTLS_OID_PKCS1_MD5 MBEDTLS_OID_PKCS1 "\x04" /**< md5WithRSAEncryption ::= { pkcs-1 4 } */ #define MBEDTLS_OID_PKCS1_SHA1 MBEDTLS_OID_PKCS1 "\x05" /**< sha1WithRSAEncryption ::= { pkcs-1 5 } */ #define MBEDTLS_OID_PKCS1_SHA224 MBEDTLS_OID_PKCS1 "\x0e" /**< sha224WithRSAEncryption ::= { pkcs-1 14 } */ @@ -255,8 +246,6 @@ /* * Digest algorithms */ -#define MBEDTLS_OID_DIGEST_ALG_MD2 MBEDTLS_OID_RSA_COMPANY "\x02\x02" /**< id-mbedtls_md2 OBJECT IDENTIFIER ::= { iso(1) member-body(2) us(840) rsadsi(113549) digestAlgorithm(2) 2 } */ -#define MBEDTLS_OID_DIGEST_ALG_MD4 MBEDTLS_OID_RSA_COMPANY "\x02\x04" /**< id-mbedtls_md4 OBJECT IDENTIFIER ::= { iso(1) member-body(2) us(840) rsadsi(113549) digestAlgorithm(2) 4 } */ #define MBEDTLS_OID_DIGEST_ALG_MD5 MBEDTLS_OID_RSA_COMPANY "\x02\x05" /**< id-mbedtls_md5 OBJECT IDENTIFIER ::= { iso(1) member-body(2) us(840) rsadsi(113549) digestAlgorithm(2) 5 } */ #define MBEDTLS_OID_DIGEST_ALG_SHA1 MBEDTLS_OID_ISO_IDENTIFIED_ORG \ MBEDTLS_OID_OIW_SECSIG_SHA1 /**< id-mbedtls_sha1 OBJECT IDENTIFIER ::= { iso(1) identified-organization(3) oiw(14) secsig(3) algorithms(2) 26 } */ @@ -269,6 +258,15 @@ #define MBEDTLS_OID_DIGEST_ALG_RIPEMD160 MBEDTLS_OID_TELETRUST "\x03\x02\x01" /**< id-ripemd160 OBJECT IDENTIFIER :: { iso(1) identified-organization(3) teletrust(36) algorithm(3) hashAlgorithm(2) ripemd160(1) } */ +#define MBEDTLS_OID_DIGEST_ALG_SHA3_224 MBEDTLS_OID_NIST_ALG "\x02\x07" /**< id-sha3-224 OBJECT IDENTIFIER ::= { joint-iso-itu-t(2) country(16) us(840) organization(1) gov(101) csor(3) nistAlgorithms(4) hashalgs(2) sha3-224(7) } */ + +#define MBEDTLS_OID_DIGEST_ALG_SHA3_256 MBEDTLS_OID_NIST_ALG "\x02\x08" /**< id-sha3-256 OBJECT IDENTIFIER ::= { joint-iso-itu-t(2) country(16) us(840) organization(1) gov(101) csor(3) nistAlgorithms(4) hashalgs(2) sha3-256(8) } */ + +#define MBEDTLS_OID_DIGEST_ALG_SHA3_384 MBEDTLS_OID_NIST_ALG "\x02\x09" /**< id-sha3-384 OBJECT IDENTIFIER ::= { joint-iso-itu-t(2) country(16) us(840) organization(1) gov(101) csor(3) nistAlgorithms(4) hashalgs(2) sha3-384(9) } */ + +#define MBEDTLS_OID_DIGEST_ALG_SHA3_512 MBEDTLS_OID_NIST_ALG "\x02\x0a" /**< id-sha3-512 OBJECT IDENTIFIER ::= { joint-iso-itu-t(2) country(16) us(840) organization(1) gov(101) csor(3) nistAlgorithms(4) hashalgs(2) sha3-512(10) } */ + + #define MBEDTLS_OID_HMAC_SHA1 MBEDTLS_OID_RSA_COMPANY "\x02\x07" /**< id-hmacWithSHA1 OBJECT IDENTIFIER ::= { iso(1) member-body(2) us(840) rsadsi(113549) digestAlgorithm(2) 7 } */ #define MBEDTLS_OID_HMAC_SHA224 MBEDTLS_OID_RSA_COMPANY "\x02\x08" /**< id-hmacWithSHA224 OBJECT IDENTIFIER ::= { iso(1) member-body(2) us(840) rsadsi(113549) digestAlgorithm(2) 8 } */ @@ -279,13 +277,28 @@ #define MBEDTLS_OID_HMAC_SHA512 MBEDTLS_OID_RSA_COMPANY "\x02\x0B" /**< id-hmacWithSHA512 OBJECT IDENTIFIER ::= { iso(1) member-body(2) us(840) rsadsi(113549) digestAlgorithm(2) 11 } */ +#define MBEDTLS_OID_HMAC_SHA3_224 MBEDTLS_OID_NIST_ALG "\x02\x0d" /**< id-hmacWithSHA3-512 OBJECT IDENTIFIER ::= { joint-iso-itu-t(2) country(16) us(840) organization(1) gov(101) csor(3) nistAlgorithms(4) hashalgs(2) hmacWithSHA3-224(13) } */ + +#define MBEDTLS_OID_HMAC_SHA3_256 MBEDTLS_OID_NIST_ALG "\x02\x0e" /**< id-hmacWithSHA3-512 OBJECT IDENTIFIER ::= { joint-iso-itu-t(2) country(16) us(840) organization(1) gov(101) csor(3) nistAlgorithms(4) hashalgs(2) hmacWithSHA3-256(14) } */ + +#define MBEDTLS_OID_HMAC_SHA3_384 MBEDTLS_OID_NIST_ALG "\x02\x0f" /**< id-hmacWithSHA3-512 OBJECT IDENTIFIER ::= { joint-iso-itu-t(2) country(16) us(840) organization(1) gov(101) csor(3) nistAlgorithms(4) hashalgs(2) hmacWithSHA3-384(15) } */ + +#define MBEDTLS_OID_HMAC_SHA3_512 MBEDTLS_OID_NIST_ALG "\x02\x10" /**< id-hmacWithSHA3-512 OBJECT IDENTIFIER ::= { joint-iso-itu-t(2) country(16) us(840) organization(1) gov(101) csor(3) nistAlgorithms(4) hashalgs(2) hmacWithSHA3-512(16) } */ + +#define MBEDTLS_OID_HMAC_RIPEMD160 MBEDTLS_OID_INTERNET "\x05\x05\x08\x01\x04" /**< id-hmacWithSHA1 OBJECT IDENTIFIER ::= {iso(1) iso-identified-organization(3) dod(6) internet(1) security(5) mechanisms(5) ipsec(8) isakmpOakley(1) hmacRIPEMD160(4)} */ + /* - * Encryption algorithms + * Encryption algorithms, + * the following standardized object identifiers are specified at + * https://datatracker.ietf.org/doc/html/rfc8018#appendix-C. */ #define MBEDTLS_OID_DES_CBC MBEDTLS_OID_ISO_IDENTIFIED_ORG \ MBEDTLS_OID_OIW_SECSIG_ALG "\x07" /**< desCBC OBJECT IDENTIFIER ::= { iso(1) identified-organization(3) oiw(14) secsig(3) algorithms(2) 7 } */ #define MBEDTLS_OID_DES_EDE3_CBC MBEDTLS_OID_RSA_COMPANY "\x03\x07" /**< des-ede3-cbc OBJECT IDENTIFIER ::= { iso(1) member-body(2) -- us(840) rsadsi(113549) encryptionAlgorithm(3) 7 } */ #define MBEDTLS_OID_AES MBEDTLS_OID_NIST_ALG "\x01" /** aes OBJECT IDENTIFIER ::= { joint-iso-itu-t(2) country(16) us(840) organization(1) gov(101) csor(3) nistAlgorithm(4) 1 } */ +#define MBEDTLS_OID_AES_128_CBC MBEDTLS_OID_AES "\x02" /** aes128-cbc-pad OBJECT IDENTIFIER ::= { joint-iso-itu-t(2) country(16) us(840) organization(1) gov(101) csor(3) nistAlgorithms(4) aes(1) aes128-CBC-PAD(2) } */ +#define MBEDTLS_OID_AES_192_CBC MBEDTLS_OID_AES "\x16" /** aes192-cbc-pad OBJECT IDENTIFIER ::= { joint-iso-itu-t(2) country(16) us(840) organization(1) gov(101) csor(3) nistAlgorithms(4) aes(1) aes192-CBC-PAD(22) } */ +#define MBEDTLS_OID_AES_256_CBC MBEDTLS_OID_AES "\x2a" /** aes256-cbc-pad OBJECT IDENTIFIER ::= { joint-iso-itu-t(2) country(16) us(840) organization(1) gov(101) csor(3) nistAlgorithms(4) aes(1) aes256-CBC-PAD(42) } */ /* * Key Wrapping algorithms @@ -309,13 +322,21 @@ /* * PKCS#5 PBES1 algorithms */ -#define MBEDTLS_OID_PKCS5_PBE_MD2_DES_CBC MBEDTLS_OID_PKCS5 "\x01" /**< pbeWithMD2AndDES-CBC OBJECT IDENTIFIER ::= {pkcs-5 1} */ -#define MBEDTLS_OID_PKCS5_PBE_MD2_RC2_CBC MBEDTLS_OID_PKCS5 "\x04" /**< pbeWithMD2AndRC2-CBC OBJECT IDENTIFIER ::= {pkcs-5 4} */ #define MBEDTLS_OID_PKCS5_PBE_MD5_DES_CBC MBEDTLS_OID_PKCS5 "\x03" /**< pbeWithMD5AndDES-CBC OBJECT IDENTIFIER ::= {pkcs-5 3} */ #define MBEDTLS_OID_PKCS5_PBE_MD5_RC2_CBC MBEDTLS_OID_PKCS5 "\x06" /**< pbeWithMD5AndRC2-CBC OBJECT IDENTIFIER ::= {pkcs-5 6} */ #define MBEDTLS_OID_PKCS5_PBE_SHA1_DES_CBC MBEDTLS_OID_PKCS5 "\x0a" /**< pbeWithSHA1AndDES-CBC OBJECT IDENTIFIER ::= {pkcs-5 10} */ #define MBEDTLS_OID_PKCS5_PBE_SHA1_RC2_CBC MBEDTLS_OID_PKCS5 "\x0b" /**< pbeWithSHA1AndRC2-CBC OBJECT IDENTIFIER ::= {pkcs-5 11} */ +/* + * PKCS#7 OIDs + */ +#define MBEDTLS_OID_PKCS7_DATA MBEDTLS_OID_PKCS7 "\x01" /**< Content type is Data OBJECT IDENTIFIER ::= {pkcs-7 1} */ +#define MBEDTLS_OID_PKCS7_SIGNED_DATA MBEDTLS_OID_PKCS7 "\x02" /**< Content type is Signed Data OBJECT IDENTIFIER ::= {pkcs-7 2} */ +#define MBEDTLS_OID_PKCS7_ENVELOPED_DATA MBEDTLS_OID_PKCS7 "\x03" /**< Content type is Enveloped Data OBJECT IDENTIFIER ::= {pkcs-7 3} */ +#define MBEDTLS_OID_PKCS7_SIGNED_AND_ENVELOPED_DATA MBEDTLS_OID_PKCS7 "\x04" /**< Content type is Signed and Enveloped Data OBJECT IDENTIFIER ::= {pkcs-7 4} */ +#define MBEDTLS_OID_PKCS7_DIGESTED_DATA MBEDTLS_OID_PKCS7 "\x05" /**< Content type is Digested Data OBJECT IDENTIFIER ::= {pkcs-7 5} */ +#define MBEDTLS_OID_PKCS7_ENCRYPTED_DATA MBEDTLS_OID_PKCS7 "\x06" /**< Content type is Encrypted Data OBJECT IDENTIFIER ::= {pkcs-7 6} */ + /* * PKCS#8 OIDs */ @@ -326,8 +347,6 @@ */ #define MBEDTLS_OID_PKCS12_PBE MBEDTLS_OID_PKCS12 "\x01" /**< pkcs-12PbeIds OBJECT IDENTIFIER ::= {pkcs-12 1} */ -#define MBEDTLS_OID_PKCS12_PBE_SHA1_RC4_128 MBEDTLS_OID_PKCS12_PBE "\x01" /**< pbeWithSHAAnd128BitRC4 OBJECT IDENTIFIER ::= {pkcs-12PbeIds 1} */ -#define MBEDTLS_OID_PKCS12_PBE_SHA1_RC4_40 MBEDTLS_OID_PKCS12_PBE "\x02" /**< pbeWithSHAAnd40BitRC4 OBJECT IDENTIFIER ::= {pkcs-12PbeIds 2} */ #define MBEDTLS_OID_PKCS12_PBE_SHA1_DES3_EDE_CBC MBEDTLS_OID_PKCS12_PBE "\x03" /**< pbeWithSHAAnd3-KeyTripleDES-CBC OBJECT IDENTIFIER ::= {pkcs-12PbeIds 3} */ #define MBEDTLS_OID_PKCS12_PBE_SHA1_DES2_EDE_CBC MBEDTLS_OID_PKCS12_PBE "\x04" /**< pbeWithSHAAnd2-KeyTripleDES-CBC OBJECT IDENTIFIER ::= {pkcs-12PbeIds 4} */ #define MBEDTLS_OID_PKCS12_PBE_SHA1_RC2_128_CBC MBEDTLS_OID_PKCS12_PBE "\x05" /**< pbeWithSHAAnd128BitRC2-CBC OBJECT IDENTIFIER ::= {pkcs-12PbeIds 5} */ @@ -438,6 +457,15 @@ * ecdsa-with-SHA2(3) 4 } */ #define MBEDTLS_OID_ECDSA_SHA512 MBEDTLS_OID_ANSI_X9_62_SIG_SHA2 "\x04" +/* + * EC key algorithms from RFC 8410 + */ + +#define MBEDTLS_OID_X25519 MBEDTLS_OID_THAWTE "\x6e" /**< id-X25519 OBJECT IDENTIFIER ::= { 1 3 101 110 } */ +#define MBEDTLS_OID_X448 MBEDTLS_OID_THAWTE "\x6f" /**< id-X448 OBJECT IDENTIFIER ::= { 1 3 101 111 } */ +#define MBEDTLS_OID_ED25519 MBEDTLS_OID_THAWTE "\x70" /**< id-Ed25519 OBJECT IDENTIFIER ::= { 1 3 101 112 } */ +#define MBEDTLS_OID_ED448 MBEDTLS_OID_THAWTE "\x71" /**< id-Ed448 OBJECT IDENTIFIER ::= { 1 3 101 113 } */ + #ifdef __cplusplus extern "C" { #endif @@ -446,10 +474,12 @@ extern "C" { * \brief Base OID descriptor structure */ typedef struct mbedtls_oid_descriptor_t { - const char *asn1; /*!< OID ASN.1 representation */ - size_t asn1_len; /*!< length of asn1 */ - const char *name; /*!< official name (e.g. from RFC) */ - const char *description; /*!< human friendly description */ + const char *MBEDTLS_PRIVATE(asn1); /*!< OID ASN.1 representation */ + size_t MBEDTLS_PRIVATE(asn1_len); /*!< length of asn1 */ +#if !defined(MBEDTLS_X509_REMOVE_INFO) + const char *MBEDTLS_PRIVATE(name); /*!< official name (e.g. from RFC) */ + const char *MBEDTLS_PRIVATE(description); /*!< human friendly description */ +#endif } mbedtls_oid_descriptor_t; /** @@ -465,6 +495,25 @@ typedef struct mbedtls_oid_descriptor_t { */ int mbedtls_oid_get_numeric_string(char *buf, size_t size, const mbedtls_asn1_buf *oid); +/** + * \brief Translate a string containing a dotted-decimal + * representation of an ASN.1 OID into its encoded form + * (e.g. "1.2.840.113549" into "\x2A\x86\x48\x86\xF7\x0D"). + * On success, this function allocates oid->buf from the + * heap. It must be freed by the caller using mbedtls_free(). + * + * \param oid #mbedtls_asn1_buf to populate with the DER-encoded OID + * \param oid_str string representation of the OID to parse + * \param size length of the OID string, not including any null terminator + * + * \return 0 if successful + * \return #MBEDTLS_ERR_ASN1_INVALID_DATA if \p oid_str does not + * represent a valid OID + * \return #MBEDTLS_ERR_ASN1_ALLOC_FAILED if the function fails to + * allocate oid->buf + */ +int mbedtls_oid_from_numeric_string(mbedtls_asn1_buf *oid, const char *oid_str, size_t size); + /** * \brief Translate an X.509 extension OID into local values * @@ -508,7 +557,7 @@ int mbedtls_oid_get_pk_alg(const mbedtls_asn1_buf *oid, mbedtls_pk_type_t *pk_al int mbedtls_oid_get_oid_by_pk_alg(mbedtls_pk_type_t pk_alg, const char **oid, size_t *olen); -#if defined(MBEDTLS_ECP_C) +#if defined(MBEDTLS_PK_HAVE_ECC_KEYS) /** * \brief Translate NamedCurve OID into an EC group identifier * @@ -530,9 +579,32 @@ int mbedtls_oid_get_ec_grp(const mbedtls_asn1_buf *oid, mbedtls_ecp_group_id *gr */ int mbedtls_oid_get_oid_by_ec_grp(mbedtls_ecp_group_id grp_id, const char **oid, size_t *olen); -#endif /* MBEDTLS_ECP_C */ -#if defined(MBEDTLS_MD_C) +/** + * \brief Translate AlgorithmIdentifier OID into an EC group identifier, + * for curves that are directly encoded at this level + * + * \param oid OID to use + * \param grp_id place to store group id + * + * \return 0 if successful, or MBEDTLS_ERR_OID_NOT_FOUND + */ +int mbedtls_oid_get_ec_grp_algid(const mbedtls_asn1_buf *oid, mbedtls_ecp_group_id *grp_id); + +/** + * \brief Translate EC group identifier into AlgorithmIdentifier OID, + * for curves that are directly encoded at this level + * + * \param grp_id EC group identifier + * \param oid place to store ASN.1 OID string pointer + * \param olen length of the OID + * + * \return 0 if successful, or MBEDTLS_ERR_OID_NOT_FOUND + */ +int mbedtls_oid_get_oid_by_ec_grp_algid(mbedtls_ecp_group_id grp_id, + const char **oid, size_t *olen); +#endif /* MBEDTLS_PK_HAVE_ECC_KEYS */ + /** * \brief Translate SignatureAlgorithm OID into md_type and pk_type * @@ -569,26 +641,26 @@ int mbedtls_oid_get_oid_by_sig_alg(mbedtls_pk_type_t pk_alg, mbedtls_md_type_t m const char **oid, size_t *olen); /** - * \brief Translate hash algorithm OID into md_type + * \brief Translate hmac algorithm OID into md_type * * \param oid OID to use - * \param md_alg place to store message digest algorithm + * \param md_hmac place to store message hmac algorithm * * \return 0 if successful, or MBEDTLS_ERR_OID_NOT_FOUND */ -int mbedtls_oid_get_md_alg(const mbedtls_asn1_buf *oid, mbedtls_md_type_t *md_alg); +int mbedtls_oid_get_md_hmac(const mbedtls_asn1_buf *oid, mbedtls_md_type_t *md_hmac); /** - * \brief Translate hmac algorithm OID into md_type + * \brief Translate hash algorithm OID into md_type * * \param oid OID to use - * \param md_hmac place to store message hmac algorithm + * \param md_alg place to store message digest algorithm * * \return 0 if successful, or MBEDTLS_ERR_OID_NOT_FOUND */ -int mbedtls_oid_get_md_hmac(const mbedtls_asn1_buf *oid, mbedtls_md_type_t *md_hmac); -#endif /* MBEDTLS_MD_C */ +int mbedtls_oid_get_md_alg(const mbedtls_asn1_buf *oid, mbedtls_md_type_t *md_alg); +#if !defined(MBEDTLS_X509_REMOVE_INFO) /** * \brief Translate Extended Key Usage OID into description * @@ -598,6 +670,7 @@ int mbedtls_oid_get_md_hmac(const mbedtls_asn1_buf *oid, mbedtls_md_type_t *md_h * \return 0 if successful, or MBEDTLS_ERR_OID_NOT_FOUND */ int mbedtls_oid_get_extended_key_usage(const mbedtls_asn1_buf *oid, const char **desc); +#endif /** * \brief Translate certificate policies OID into description @@ -630,7 +703,6 @@ int mbedtls_oid_get_oid_by_md(mbedtls_md_type_t md_alg, const char **oid, size_t * \return 0 if successful, or MBEDTLS_ERR_OID_NOT_FOUND */ int mbedtls_oid_get_cipher_alg(const mbedtls_asn1_buf *oid, mbedtls_cipher_type_t *cipher_alg); -#endif /* MBEDTLS_CIPHER_C */ #if defined(MBEDTLS_PKCS12_C) /** @@ -646,6 +718,7 @@ int mbedtls_oid_get_cipher_alg(const mbedtls_asn1_buf *oid, mbedtls_cipher_type_ int mbedtls_oid_get_pkcs12_pbe_alg(const mbedtls_asn1_buf *oid, mbedtls_md_type_t *md_alg, mbedtls_cipher_type_t *cipher_alg); #endif /* MBEDTLS_PKCS12_C */ +#endif /* MBEDTLS_CIPHER_C */ #ifdef __cplusplus } diff --git a/vendor/mbedtls/include/mbedtls/pem.h b/vendor/mbedtls/include/mbedtls/pem.h index fee32a3bdb..3c6a28d98d 100644 --- a/vendor/mbedtls/include/mbedtls/pem.h +++ b/vendor/mbedtls/include/mbedtls/pem.h @@ -5,28 +5,13 @@ */ /* * Copyright The Mbed TLS Contributors - * SPDX-License-Identifier: Apache-2.0 - * - * Licensed under the Apache License, Version 2.0 (the "License"); you may - * not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT - * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. + * SPDX-License-Identifier: Apache-2.0 OR GPL-2.0-or-later */ #ifndef MBEDTLS_PEM_H #define MBEDTLS_PEM_H +#include "mbedtls/private_access.h" -#if !defined(MBEDTLS_CONFIG_FILE) -#include "mbedtls/config.h" -#else -#include MBEDTLS_CONFIG_FILE -#endif +#include "mbedtls/build_info.h" #include @@ -65,9 +50,9 @@ extern "C" { * \brief PEM context structure */ typedef struct mbedtls_pem_context { - unsigned char *buf; /*!< buffer for decoded data */ - size_t buflen; /*!< length of the buffer */ - unsigned char *info; /*!< buffer for extra header information */ + unsigned char *MBEDTLS_PRIVATE(buf); /*!< buffer for decoded data */ + size_t MBEDTLS_PRIVATE(buflen); /*!< length of the buffer */ + unsigned char *MBEDTLS_PRIVATE(info); /*!< buffer for extra header information */ } mbedtls_pem_context; @@ -88,16 +73,20 @@ void mbedtls_pem_init(mbedtls_pem_context *ctx); * \param data source data to look in (must be nul-terminated) * \param pwd password for decryption (can be NULL) * \param pwdlen length of password - * \param use_len destination for total length used (set after header is - * correctly read, so unless you get + * \param use_len destination for total length used from data buffer. It is + * set after header is correctly read, so unless you get * MBEDTLS_ERR_PEM_BAD_INPUT_DATA or * MBEDTLS_ERR_PEM_NO_HEADER_FOOTER_PRESENT, use_len is - * the length to skip) + * the length to skip. * * \note Attempts to check password correctness by verifying if * the decrypted text starts with an ASN.1 sequence of * appropriate length * + * \note \c mbedtls_pem_free must be called on PEM context before + * the PEM context can be reused in another call to + * \c mbedtls_pem_read_buffer + * * \return 0 on success, or a specific PEM error code */ int mbedtls_pem_read_buffer(mbedtls_pem_context *ctx, const char *header, const char *footer, @@ -105,6 +94,25 @@ int mbedtls_pem_read_buffer(mbedtls_pem_context *ctx, const char *header, const const unsigned char *pwd, size_t pwdlen, size_t *use_len); +/** + * \brief Get the pointer to the decoded binary data in a PEM context. + * + * \param ctx PEM context to access. + * \param buflen On success, this will contain the length of the binary data. + * This must be a valid (non-null) pointer. + * + * \return A pointer to the decoded binary data. + * + * \note The returned pointer remains valid only until \p ctx is + modified or freed. + */ +static inline const unsigned char *mbedtls_pem_get_buffer(mbedtls_pem_context *ctx, size_t *buflen) +{ + *buflen = ctx->MBEDTLS_PRIVATE(buflen); + return ctx->MBEDTLS_PRIVATE(buf); +} + + /** * \brief PEM context memory freeing * diff --git a/vendor/mbedtls/include/mbedtls/pk.h b/vendor/mbedtls/include/mbedtls/pk.h index 0e9d58aec6..fde302f872 100644 --- a/vendor/mbedtls/include/mbedtls/pk.h +++ b/vendor/mbedtls/include/mbedtls/pk.h @@ -5,29 +5,14 @@ */ /* * Copyright The Mbed TLS Contributors - * SPDX-License-Identifier: Apache-2.0 - * - * Licensed under the Apache License, Version 2.0 (the "License"); you may - * not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT - * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. + * SPDX-License-Identifier: Apache-2.0 OR GPL-2.0-or-later */ #ifndef MBEDTLS_PK_H #define MBEDTLS_PK_H +#include "mbedtls/private_access.h" -#if !defined(MBEDTLS_CONFIG_FILE) -#include "mbedtls/config.h" -#else -#include MBEDTLS_CONFIG_FILE -#endif +#include "mbedtls/build_info.h" #include "mbedtls/md.h" @@ -43,15 +28,10 @@ #include "mbedtls/ecdsa.h" #endif -#if defined(MBEDTLS_USE_PSA_CRYPTO) +#if defined(MBEDTLS_PSA_CRYPTO_CLIENT) #include "psa/crypto.h" #endif -#if (defined(__ARMCC_VERSION) || defined(_MSC_VER)) && \ - !defined(inline) && !defined(__cplusplus) -#define inline __inline -#endif - /** Memory allocation failed. */ #define MBEDTLS_ERR_PK_ALLOC_FAILED -0x3F80 /** Type mismatch, eg attempt to encrypt with an ECDSA key */ @@ -80,10 +60,8 @@ #define MBEDTLS_ERR_PK_FEATURE_UNAVAILABLE -0x3980 /** The buffer contains a valid signature followed by more data. */ #define MBEDTLS_ERR_PK_SIG_LEN_MISMATCH -0x3900 - -/* MBEDTLS_ERR_PK_HW_ACCEL_FAILED is deprecated and should not be used. */ -/** PK hardware accelerator failed. */ -#define MBEDTLS_ERR_PK_HW_ACCEL_FAILED -0x3880 +/** The output buffer is too small. */ +#define MBEDTLS_ERR_PK_BUFFER_TOO_SMALL -0x3880 #ifdef __cplusplus extern "C" { @@ -108,7 +86,23 @@ typedef enum { * See \c mbedtls_rsa_rsassa_pss_verify_ext() */ typedef struct mbedtls_pk_rsassa_pss_options { + /** The digest to use for MGF1 in PSS. + * + * \note When #MBEDTLS_USE_PSA_CRYPTO is enabled and #MBEDTLS_RSA_C is + * disabled, this must be equal to the \c md_alg argument passed + * to mbedtls_pk_verify_ext(). In a future version of the library, + * this constraint may apply whenever #MBEDTLS_USE_PSA_CRYPTO is + * enabled regardless of the status of #MBEDTLS_RSA_C. + */ mbedtls_md_type_t mgf1_hash_id; + + /** The expected length of the salt, in bytes. This may be + * #MBEDTLS_RSA_SALT_LEN_ANY to accept any salt length. + * + * \note When #MBEDTLS_USE_PSA_CRYPTO is enabled, only + * #MBEDTLS_RSA_SALT_LEN_ANY is valid. Any other value may be + * ignored (allowing any salt length). + */ int expected_salt_len; } mbedtls_pk_rsassa_pss_options; @@ -132,7 +126,7 @@ typedef struct mbedtls_pk_rsassa_pss_options { /* For RSA, the signature can be as large as the bignum module allows. * For RSA_ALT, the signature size is not necessarily tied to what the * bignum module can do, but in the absence of any specific setting, - * we use that (rsa_alt_sign_wrap in pk_wrap will check). */ + * we use that (rsa_alt_sign_wrap in library/pk_wrap.h will check). */ #undef MBEDTLS_PK_SIGNATURE_MAX_SIZE #define MBEDTLS_PK_SIGNATURE_MAX_SIZE MBEDTLS_MPI_MAX_SIZE #endif @@ -165,6 +159,28 @@ typedef struct mbedtls_pk_rsassa_pss_options { #endif #endif /* defined(MBEDTLS_USE_PSA_CRYPTO) */ +/* Internal helper to define which fields in the pk_context structure below + * should be used for EC keys: legacy ecp_keypair or the raw (PSA friendly) + * format. It should be noted that this only affects how data is stored, not + * which functions are used for various operations. The overall picture looks + * like this: + * - if USE_PSA is not defined and ECP_C is defined then use ecp_keypair data + * structure and legacy functions + * - if USE_PSA is defined and + * - if ECP_C then use ecp_keypair structure, convert data to a PSA friendly + * format and use PSA functions + * - if !ECP_C then use new raw data and PSA functions directly. + * + * The main reason for the "intermediate" (USE_PSA + ECP_C) above is that as long + * as ECP_C is defined mbedtls_pk_ec() gives the user a read/write access to the + * ecp_keypair structure inside the pk_context so they can modify it using + * ECP functions which are not under PK module's control. + */ +#if defined(MBEDTLS_USE_PSA_CRYPTO) && defined(PSA_WANT_KEY_TYPE_ECC_PUBLIC_KEY) && \ + !defined(MBEDTLS_ECP_C) +#define MBEDTLS_PK_USE_PSA_EC_DATA +#endif + /** * \brief Types for interfacing with the debug module */ @@ -172,15 +188,16 @@ typedef enum { MBEDTLS_PK_DEBUG_NONE = 0, MBEDTLS_PK_DEBUG_MPI, MBEDTLS_PK_DEBUG_ECP, + MBEDTLS_PK_DEBUG_PSA_EC, } mbedtls_pk_debug_type; /** * \brief Item to send to the debug module */ typedef struct mbedtls_pk_debug_item { - mbedtls_pk_debug_type type; - const char *name; - void *value; + mbedtls_pk_debug_type MBEDTLS_PRIVATE(type); + const char *MBEDTLS_PRIVATE(name); + void *MBEDTLS_PRIVATE(value); } mbedtls_pk_debug_item; /** Maximum number of item send for debugging, plus 1 */ @@ -188,15 +205,63 @@ typedef struct mbedtls_pk_debug_item { /** * \brief Public key information and operations + * + * \note The library does not support custom pk info structures, + * only built-in structures returned by + * mbedtls_cipher_info_from_type(). */ typedef struct mbedtls_pk_info_t mbedtls_pk_info_t; +#define MBEDTLS_PK_MAX_EC_PUBKEY_RAW_LEN \ + PSA_KEY_EXPORT_ECC_PUBLIC_KEY_MAX_SIZE(PSA_VENDOR_ECC_MAX_CURVE_BITS) /** * \brief Public key container */ typedef struct mbedtls_pk_context { - const mbedtls_pk_info_t *pk_info; /**< Public key information */ - void *pk_ctx; /**< Underlying public key context */ + const mbedtls_pk_info_t *MBEDTLS_PRIVATE(pk_info); /**< Public key information */ + void *MBEDTLS_PRIVATE(pk_ctx); /**< Underlying public key context */ + /* The following field is used to store the ID of a private key in the + * following cases: + * - opaque key when MBEDTLS_USE_PSA_CRYPTO is defined + * - normal key when MBEDTLS_PK_USE_PSA_EC_DATA is defined. In this case: + * - the pk_ctx above is not not used to store the private key anymore. + * Actually that field not populated at all in this case because also + * the public key will be stored in raw format as explained below + * - this ID is used for all private key operations (ex: sign, check + * key pair, key write, etc) using PSA functions + * + * Note: this private key storing solution only affects EC keys, not the + * other ones. The latters still use the pk_ctx to store their own + * context. */ +#if defined(MBEDTLS_USE_PSA_CRYPTO) + mbedtls_svc_key_id_t MBEDTLS_PRIVATE(priv_id); /**< Key ID for opaque keys */ +#endif /* MBEDTLS_USE_PSA_CRYPTO */ + /* The following fields are meant for storing the public key in raw format + * which is handy for: + * - easily importing it into the PSA context + * - reducing the ECP module dependencies in the PK one. + * + * When MBEDTLS_PK_USE_PSA_EC_DATA is enabled: + * - the pk_ctx above is not used anymore for storing the public key + * inside the ecp_keypair structure + * - the following fields are used for all public key operations: signature + * verify, key pair check and key write. + * - For a key pair, priv_id contains the private key. For a public key, + * priv_id is null. + * Of course, when MBEDTLS_PK_USE_PSA_EC_DATA is not enabled, the legacy + * ecp_keypair structure is used for storing the public key and performing + * all the operations. + * + * Note: This new public key storing solution only works for EC keys, not + * other ones. The latters still use pk_ctx to store their own + * context. + */ +#if defined(MBEDTLS_PK_USE_PSA_EC_DATA) + uint8_t MBEDTLS_PRIVATE(pub_raw)[MBEDTLS_PK_MAX_EC_PUBKEY_RAW_LEN]; /**< Raw public key */ + size_t MBEDTLS_PRIVATE(pub_raw_len); /**< Valid bytes in "pub_raw" */ + psa_ecc_family_t MBEDTLS_PRIVATE(ec_family); /**< EC family of pk */ + size_t MBEDTLS_PRIVATE(ec_bits); /**< Curve's bits of pk */ +#endif /* MBEDTLS_PK_USE_PSA_EC_DATA */ } mbedtls_pk_context; #if defined(MBEDTLS_ECDSA_C) && defined(MBEDTLS_ECP_RESTARTABLE) @@ -204,8 +269,8 @@ typedef struct mbedtls_pk_context { * \brief Context for resuming operations */ typedef struct { - const mbedtls_pk_info_t *pk_info; /**< Public key information */ - void *rs_ctx; /**< Underlying restart context */ + const mbedtls_pk_info_t *MBEDTLS_PRIVATE(pk_info); /**< Public key information */ + void *MBEDTLS_PRIVATE(rs_ctx); /**< Underlying restart context */ } mbedtls_pk_restart_ctx; #else /* MBEDTLS_ECDSA_C && MBEDTLS_ECP_RESTARTABLE */ /* Now we can declare functions that take a pointer to that */ @@ -216,14 +281,13 @@ typedef void mbedtls_pk_restart_ctx; /** * \brief Types for RSA-alt abstraction */ -typedef int (*mbedtls_pk_rsa_alt_decrypt_func)(void *ctx, int mode, size_t *olen, +typedef int (*mbedtls_pk_rsa_alt_decrypt_func)(void *ctx, size_t *olen, const unsigned char *input, unsigned char *output, size_t output_max_len); typedef int (*mbedtls_pk_rsa_alt_sign_func)(void *ctx, int (*f_rng)(void *, unsigned char *, size_t), void *p_rng, - int mode, mbedtls_md_type_t md_alg, - unsigned int hashlen, + mbedtls_md_type_t md_alg, unsigned int hashlen, const unsigned char *hash, unsigned char *sig); typedef size_t (*mbedtls_pk_rsa_alt_key_len_func)(void *ctx); #endif /* MBEDTLS_PK_RSA_ALT_SUPPORT */ @@ -302,8 +366,8 @@ int mbedtls_pk_setup(mbedtls_pk_context *ctx, const mbedtls_pk_info_t *info); * storing and manipulating the key material directly. * * \param ctx The context to initialize. It must be empty (type NONE). - * \param key The PSA key to wrap, which must hold an ECC key pair - * (see notes below). + * \param key The PSA key to wrap, which must hold an ECC or RSA key + * pair (see notes below). * * \note The wrapped key must remain valid as long as the * wrapping PK context is in use, that is at least between @@ -311,8 +375,8 @@ int mbedtls_pk_setup(mbedtls_pk_context *ctx, const mbedtls_pk_info_t *info); * mbedtls_pk_free() is called on this context. The wrapped * key might then be independently used or destroyed. * - * \note This function is currently only available for ECC key - * pairs (that is, ECC keys containing private key material). + * \note This function is currently only available for ECC or RSA + * key pairs (that is, keys containing private key material). * Support for other key types may be added later. * * \return \c 0 on success. @@ -323,7 +387,7 @@ int mbedtls_pk_setup(mbedtls_pk_context *ctx, const mbedtls_pk_info_t *info); * \return #MBEDTLS_ERR_PK_ALLOC_FAILED on allocation failure. */ int mbedtls_pk_setup_opaque(mbedtls_pk_context *ctx, - const psa_key_id_t key); + const mbedtls_svc_key_id_t key); #endif /* MBEDTLS_USE_PSA_CRYPTO */ #if defined(MBEDTLS_PK_RSA_ALT_SUPPORT) @@ -383,34 +447,298 @@ static inline size_t mbedtls_pk_get_len(const mbedtls_pk_context *ctx) */ int mbedtls_pk_can_do(const mbedtls_pk_context *ctx, mbedtls_pk_type_t type); +#if defined(MBEDTLS_USE_PSA_CRYPTO) +/** + * \brief Tell if context can do the operation given by PSA algorithm + * + * \param ctx The context to query. It must have been initialized. + * \param alg PSA algorithm to check against, the following are allowed: + * PSA_ALG_RSA_PKCS1V15_SIGN(hash), + * PSA_ALG_RSA_PSS(hash), + * PSA_ALG_RSA_PKCS1V15_CRYPT, + * PSA_ALG_ECDSA(hash), + * PSA_ALG_ECDH, where hash is a specific hash. + * \param usage PSA usage flag to check against, must be composed of: + * PSA_KEY_USAGE_SIGN_HASH + * PSA_KEY_USAGE_DECRYPT + * PSA_KEY_USAGE_DERIVE. + * Context key must match all passed usage flags. + * + * \warning Since the set of allowed algorithms and usage flags may be + * expanded in the future, the return value \c 0 should not + * be taken in account for non-allowed algorithms and usage + * flags. + * + * \return 1 if the context can do operations on the given type. + * \return 0 if the context cannot do the operations on the given + * type, for non-allowed algorithms and usage flags, or + * for a context that has been initialized but not set up + * or that has been cleared with mbedtls_pk_free(). + */ +int mbedtls_pk_can_do_ext(const mbedtls_pk_context *ctx, psa_algorithm_t alg, + psa_key_usage_t usage); +#endif /* MBEDTLS_USE_PSA_CRYPTO */ + +#if defined(MBEDTLS_PSA_CRYPTO_CLIENT) +/** + * \brief Determine valid PSA attributes that can be used to + * import a key into PSA. + * + * The attributes determined by this function are suitable + * for calling mbedtls_pk_import_into_psa() to create + * a PSA key with the same key material. + * + * The typical flow of operations involving this function is + * ``` + * psa_key_attributes_t attributes = PSA_KEY_ATTRIBUTES_INIT; + * int ret = mbedtls_pk_get_psa_attributes(pk, &attributes); + * if (ret != 0) ...; // error handling omitted + * // Tweak attributes if desired + * psa_key_id_t key_id = 0; + * ret = mbedtls_pk_import_into_psa(pk, &attributes, &key_id); + * if (ret != 0) ...; // error handling omitted + * ``` + * + * \note This function does not support RSA-alt contexts + * (set up with mbedtls_pk_setup_rsa_alt()). + * + * \param[in] pk The PK context to use. It must have been set up. + * It can either contain a key pair or just a public key. + * \param usage A single `PSA_KEY_USAGE_xxx` flag among the following: + * - #PSA_KEY_USAGE_DECRYPT: \p pk must contain a + * key pair. The output \p attributes will contain a + * key pair type, and the usage policy will allow + * #PSA_KEY_USAGE_ENCRYPT as well as + * #PSA_KEY_USAGE_DECRYPT. + * - #PSA_KEY_USAGE_DERIVE: \p pk must contain a + * key pair. The output \p attributes will contain a + * key pair type. + * - #PSA_KEY_USAGE_ENCRYPT: The output + * \p attributes will contain a public key type. + * - #PSA_KEY_USAGE_SIGN_HASH: \p pk must contain a + * key pair. The output \p attributes will contain a + * key pair type, and the usage policy will allow + * #PSA_KEY_USAGE_VERIFY_HASH as well as + * #PSA_KEY_USAGE_SIGN_HASH. + * - #PSA_KEY_USAGE_SIGN_MESSAGE: \p pk must contain a + * key pair. The output \p attributes will contain a + * key pair type, and the usage policy will allow + * #PSA_KEY_USAGE_VERIFY_MESSAGE as well as + * #PSA_KEY_USAGE_SIGN_MESSAGE. + * - #PSA_KEY_USAGE_VERIFY_HASH: The output + * \p attributes will contain a public key type. + * - #PSA_KEY_USAGE_VERIFY_MESSAGE: The output + * \p attributes will contain a public key type. + * \param[out] attributes + * On success, valid attributes to import the key into PSA. + * - The lifetime and key identifier are unchanged. If the + * attribute structure was initialized or reset before + * calling this function, this will result in a volatile + * key. Call psa_set_key_identifier() before or after this + * function if you wish to create a persistent key. Call + * psa_set_key_lifetime() before or after this function if + * you wish to import the key in a secure element. + * - The key type and bit-size are determined by the contents + * of the PK context. If the PK context contains a key + * pair, the key type can be either a key pair type or + * the corresponding public key type, depending on + * \p usage. If the PK context contains a public key, + * the key type is a public key type. + * - The key's policy is determined by the key type and + * the \p usage parameter. The usage always allows + * \p usage, exporting and copying the key, and + * possibly other permissions as documented for the + * \p usage parameter. + * The permitted algorithm policy is determined as follows + * based on the #mbedtls_pk_type_t type of \p pk, + * the chosen \p usage and other factors: + * - #MBEDTLS_PK_RSA whose underlying + * #mbedtls_rsa_context has the padding mode + * #MBEDTLS_RSA_PKCS_V15: + * #PSA_ALG_RSA_PKCS1V15_SIGN(#PSA_ALG_ANY_HASH) + * if \p usage is SIGN/VERIFY, and + * #PSA_ALG_RSA_PKCS1V15_CRYPT + * if \p usage is ENCRYPT/DECRYPT. + * - #MBEDTLS_PK_RSA whose underlying + * #mbedtls_rsa_context has the padding mode + * #MBEDTLS_RSA_PKCS_V21 and the digest type + * corresponding to the PSA algorithm \c hash: + * #PSA_ALG_RSA_PSS_ANY_SALT(#PSA_ALG_ANY_HASH) + * if \p usage is SIGN/VERIFY, and + * #PSA_ALG_RSA_OAEP(\c hash) + * if \p usage is ENCRYPT/DECRYPT. + * - #MBEDTLS_PK_RSA_ALT: not supported. + * - #MBEDTLS_PK_ECDSA or #MBEDTLS_PK_ECKEY + * if \p usage is SIGN/VERIFY: + * #PSA_ALG_DETERMINISTIC_ECDSA(#PSA_ALG_ANY_HASH) + * if #MBEDTLS_ECDSA_DETERMINISTIC is enabled, + * otherwise #PSA_ALG_ECDSA(#PSA_ALG_ANY_HASH). + * - #MBEDTLS_PK_ECKEY_DH or #MBEDTLS_PK_ECKEY + * if \p usage is DERIVE: + * #PSA_ALG_ECDH. + * - #MBEDTLS_PK_OPAQUE: same as the primary algorithm + * set for the underlying PSA key, except that + * sign/decrypt flags are removed if the type is + * set to a public key type. + * The underlying key must allow \p usage. + * Note that the enrollment algorithm set with + * psa_set_key_enrollment_algorithm() is not copied. + * + * \return 0 on success. + * #MBEDTLS_ERR_PK_TYPE_MISMATCH if \p pk does not contain + * a key of the type identified in \p attributes. + * Another error code on other failures. + */ +int mbedtls_pk_get_psa_attributes(const mbedtls_pk_context *pk, + psa_key_usage_t usage, + psa_key_attributes_t *attributes); + +/** + * \brief Import a key into the PSA key store. + * + * This function is equivalent to calling psa_import_key() + * with the key material from \p pk. + * + * The typical way to use this function is: + * -# Call mbedtls_pk_get_psa_attributes() to obtain + * attributes for the given key. + * -# If desired, modify the attributes, for example: + * - To create a persistent key, call + * psa_set_key_identifier() and optionally + * psa_set_key_lifetime(). + * - To import only the public part of a key pair: + * + * psa_set_key_type(&attributes, + * PSA_KEY_TYPE_PUBLIC_KEY_OF_KEY_PAIR( + * psa_get_key_type(&attributes))); + * - Restrict the key usage if desired. + * -# Call mbedtls_pk_import_into_psa(). + * + * \note This function does not support RSA-alt contexts + * (set up with mbedtls_pk_setup_rsa_alt()). + * + * \param[in] pk The PK context to use. It must have been set up. + * It can either contain a key pair or just a public key. + * \param[in] attributes + * The attributes to use for the new key. They must be + * compatible with \p pk. In particular, the key type + * must match the content of \p pk. + * If \p pk contains a key pair, the key type in + * attributes can be either the key pair type or the + * corresponding public key type (to import only the + * public part). + * \param[out] key_id + * On success, the identifier of the newly created key. + * On error, this is #MBEDTLS_SVC_KEY_ID_INIT. + * + * \return 0 on success. + * #MBEDTLS_ERR_PK_TYPE_MISMATCH if \p pk does not contain + * a key of the type identified in \p attributes. + * Another error code on other failures. + */ +int mbedtls_pk_import_into_psa(const mbedtls_pk_context *pk, + const psa_key_attributes_t *attributes, + mbedtls_svc_key_id_t *key_id); + +/** + * \brief Create a PK context starting from a key stored in PSA. + * This key: + * - must be exportable and + * - must be an RSA or EC key pair or public key (FFDH is not supported in PK). + * + * The resulting PK object will be a transparent type: + * - #MBEDTLS_PK_RSA for RSA keys or + * - #MBEDTLS_PK_ECKEY for EC keys. + * + * Once this functions returns the PK object will be completely + * independent from the original PSA key that it was generated + * from. + * Calling mbedtls_pk_sign(), mbedtls_pk_verify(), + * mbedtls_pk_encrypt(), mbedtls_pk_decrypt() on the resulting + * PK context will perform the corresponding algorithm for that + * PK context type. + * * For ECDSA, the choice of deterministic vs randomized will + * be based on the compile-time setting #MBEDTLS_ECDSA_DETERMINISTIC. + * * For an RSA key, the output PK context will allow both + * encrypt/decrypt and sign/verify regardless of the original + * key's policy. + * The original key's policy determines the output key's padding + * mode: PCKS1 v2.1 is set if the PSA key policy is OAEP or PSS, + * otherwise PKCS1 v1.5 is set. + * + * \param key_id The key identifier of the key stored in PSA. + * \param pk The PK context that will be filled. It must be initialized, + * but not set up. + * + * \return 0 on success. + * \return #MBEDTLS_ERR_PK_BAD_INPUT_DATA in case the provided input + * parameters are not correct. + */ +int mbedtls_pk_copy_from_psa(mbedtls_svc_key_id_t key_id, mbedtls_pk_context *pk); + +/** + * \brief Create a PK context for the public key of a PSA key. + * + * The key must be an RSA or ECC key. It can be either a + * public key or a key pair, and only the public key is copied. + * The resulting PK object will be a transparent type: + * - #MBEDTLS_PK_RSA for RSA keys or + * - #MBEDTLS_PK_ECKEY for EC keys. + * + * Once this functions returns the PK object will be completely + * independent from the original PSA key that it was generated + * from. + * Calling mbedtls_pk_verify() or + * mbedtls_pk_encrypt() on the resulting + * PK context will perform the corresponding algorithm for that + * PK context type. + * + * For an RSA key, the output PK context will allow both + * encrypt and verify regardless of the original key's policy. + * The original key's policy determines the output key's padding + * mode: PCKS1 v2.1 is set if the PSA key policy is OAEP or PSS, + * otherwise PKCS1 v1.5 is set. + * + * \param key_id The key identifier of the key stored in PSA. + * \param pk The PK context that will be filled. It must be initialized, + * but not set up. + * + * \return 0 on success. + * \return MBEDTLS_ERR_PK_BAD_INPUT_DATA in case the provided input + * parameters are not correct. + */ +int mbedtls_pk_copy_public_from_psa(mbedtls_svc_key_id_t key_id, mbedtls_pk_context *pk); +#endif /* MBEDTLS_PSA_CRYPTO_CLIENT */ + /** * \brief Verify signature (including padding if relevant). * * \param ctx The PK context to use. It must have been set up. - * \param md_alg Hash algorithm used (see notes) + * \param md_alg Hash algorithm used. + * This can be #MBEDTLS_MD_NONE if the signature algorithm + * does not rely on a hash algorithm (non-deterministic + * ECDSA, RSA PKCS#1 v1.5). + * For PKCS#1 v1.5, if \p md_alg is #MBEDTLS_MD_NONE, then + * \p hash is the DigestInfo structure used by RFC 8017 + * §9.2 steps 3–6. If \p md_alg is a valid hash + * algorithm then \p hash is the digest itself, and this + * function calculates the DigestInfo encoding internally. * \param hash Hash of the message to sign - * \param hash_len Hash length or 0 (see notes) + * \param hash_len Hash length * \param sig Signature to verify * \param sig_len Signature length * + * \note For keys of type #MBEDTLS_PK_RSA, the signature algorithm is + * either PKCS#1 v1.5 or PSS (accepting any salt length), + * depending on the padding mode in the underlying RSA context. + * For a pk object constructed by parsing, this is PKCS#1 v1.5 + * by default. Use mbedtls_pk_verify_ext() to explicitly select + * a different algorithm. + * * \return 0 on success (signature is valid), * #MBEDTLS_ERR_PK_SIG_LEN_MISMATCH if there is a valid * signature in \p sig but its length is less than \p sig_len, * or a specific error code. - * - * \note For RSA keys, the default padding type is PKCS#1 v1.5. - * Use \c mbedtls_pk_verify_ext( MBEDTLS_PK_RSASSA_PSS, ... ) - * to verify RSASSA_PSS signatures. - * - * \note If #MBEDTLS_USE_PSA_CRYPTO is enabled, the PSA crypto - * subsystem must have been initialized by calling - * psa_crypto_init() before calling this function, - * if the key might be an ECC (ECDSA) key. - * - * \note If hash_len is 0, then the length associated with md_alg - * is used instead, or an error returned if it is invalid. - * - * \note md_alg may be MBEDTLS_MD_NONE, only if hash_len != 0 */ int mbedtls_pk_verify(mbedtls_pk_context *ctx, mbedtls_md_type_t md_alg, const unsigned char *hash, size_t hash_len, @@ -469,7 +797,9 @@ int mbedtls_pk_verify_restartable(mbedtls_pk_context *ctx, * * \note If type is MBEDTLS_PK_RSASSA_PSS, then options must point * to a mbedtls_pk_rsassa_pss_options structure, - * otherwise it must be NULL. + * otherwise it must be NULL. Note that if + * #MBEDTLS_USE_PSA_CRYPTO is defined, the salt length is not + * verified as PSA_ALG_RSA_PSS_ANY_SALT is used. */ int mbedtls_pk_verify_ext(mbedtls_pk_type_t type, const void *options, mbedtls_pk_context *ctx, mbedtls_md_type_t md_alg, @@ -483,34 +813,73 @@ int mbedtls_pk_verify_ext(mbedtls_pk_type_t type, const void *options, * with a private key. * \param md_alg Hash algorithm used (see notes) * \param hash Hash of the message to sign - * \param hash_len Hash length or 0 (see notes) + * \param hash_len Hash length * \param sig Place to write the signature. * It must have enough room for the signature. * #MBEDTLS_PK_SIGNATURE_MAX_SIZE is always enough. * You may use a smaller buffer if it is large enough * given the key type. + * \param sig_size The size of the \p sig buffer in bytes. * \param sig_len On successful return, * the number of bytes written to \p sig. - * \param f_rng RNG function + * \param f_rng RNG function, must not be \c NULL. * \param p_rng RNG parameter * - * \return 0 on success, or a specific error code. - * - * \note For RSA keys, the default padding type is PKCS#1 v1.5. - * There is no interface in the PK module to make RSASSA-PSS - * signatures yet. + * \note For keys of type #MBEDTLS_PK_RSA, the signature algorithm is + * either PKCS#1 v1.5 or PSS (using the largest possible salt + * length up to the hash length), depending on the padding mode + * in the underlying RSA context. For a pk object constructed + * by parsing, this is PKCS#1 v1.5 by default. Use + * mbedtls_pk_verify_ext() to explicitly select a different + * algorithm. * - * \note If hash_len is 0, then the length associated with md_alg - * is used instead, or an error returned if it is invalid. + * \return 0 on success, or a specific error code. * * \note For RSA, md_alg may be MBEDTLS_MD_NONE if hash_len != 0. * For ECDSA, md_alg may never be MBEDTLS_MD_NONE. */ int mbedtls_pk_sign(mbedtls_pk_context *ctx, mbedtls_md_type_t md_alg, const unsigned char *hash, size_t hash_len, - unsigned char *sig, size_t *sig_len, + unsigned char *sig, size_t sig_size, size_t *sig_len, int (*f_rng)(void *, unsigned char *, size_t), void *p_rng); +/** + * \brief Make signature given a signature type. + * + * \param pk_type Signature type. + * \param ctx The PK context to use. It must have been set up + * with a private key. + * \param md_alg Hash algorithm used (see notes) + * \param hash Hash of the message to sign + * \param hash_len Hash length + * \param sig Place to write the signature. + * It must have enough room for the signature. + * #MBEDTLS_PK_SIGNATURE_MAX_SIZE is always enough. + * You may use a smaller buffer if it is large enough + * given the key type. + * \param sig_size The size of the \p sig buffer in bytes. + * \param sig_len On successful return, + * the number of bytes written to \p sig. + * \param f_rng RNG function, must not be \c NULL. + * \param p_rng RNG parameter + * + * \return 0 on success, or a specific error code. + * + * \note When \p pk_type is #MBEDTLS_PK_RSASSA_PSS, + * see #PSA_ALG_RSA_PSS for a description of PSS options used. + * + * \note For RSA, md_alg may be MBEDTLS_MD_NONE if hash_len != 0. + * For ECDSA, md_alg may never be MBEDTLS_MD_NONE. + * + */ +int mbedtls_pk_sign_ext(mbedtls_pk_type_t pk_type, + mbedtls_pk_context *ctx, + mbedtls_md_type_t md_alg, + const unsigned char *hash, size_t hash_len, + unsigned char *sig, size_t sig_size, size_t *sig_len, + int (*f_rng)(void *, unsigned char *, size_t), + void *p_rng); + /** * \brief Restartable version of \c mbedtls_pk_sign() * @@ -523,15 +892,16 @@ int mbedtls_pk_sign(mbedtls_pk_context *ctx, mbedtls_md_type_t md_alg, * with a private key. * \param md_alg Hash algorithm used (see notes for mbedtls_pk_sign()) * \param hash Hash of the message to sign - * \param hash_len Hash length or 0 (see notes for mbedtls_pk_sign()) + * \param hash_len Hash length * \param sig Place to write the signature. * It must have enough room for the signature. * #MBEDTLS_PK_SIGNATURE_MAX_SIZE is always enough. * You may use a smaller buffer if it is large enough * given the key type. + * \param sig_size The size of the \p sig buffer in bytes. * \param sig_len On successful return, * the number of bytes written to \p sig. - * \param f_rng RNG function + * \param f_rng RNG function, must not be \c NULL. * \param p_rng RNG parameter * \param rs_ctx Restart context (NULL to disable restart) * @@ -542,7 +912,7 @@ int mbedtls_pk_sign(mbedtls_pk_context *ctx, mbedtls_md_type_t md_alg, int mbedtls_pk_sign_restartable(mbedtls_pk_context *ctx, mbedtls_md_type_t md_alg, const unsigned char *hash, size_t hash_len, - unsigned char *sig, size_t *sig_len, + unsigned char *sig, size_t sig_size, size_t *sig_len, int (*f_rng)(void *, unsigned char *, size_t), void *p_rng, mbedtls_pk_restart_ctx *rs_ctx); @@ -556,10 +926,13 @@ int mbedtls_pk_sign_restartable(mbedtls_pk_context *ctx, * \param output Decrypted output * \param olen Decrypted message length * \param osize Size of the output buffer - * \param f_rng RNG function + * \param f_rng RNG function, must not be \c NULL. * \param p_rng RNG parameter * - * \note For RSA keys, the default padding type is PKCS#1 v1.5. + * \note For keys of type #MBEDTLS_PK_RSA, the signature algorithm is + * either PKCS#1 v1.5 or OAEP, depending on the padding mode in + * the underlying RSA context. For a pk object constructed by + * parsing, this is PKCS#1 v1.5 by default. * * \return 0 on success, or a specific error code. */ @@ -577,10 +950,15 @@ int mbedtls_pk_decrypt(mbedtls_pk_context *ctx, * \param output Encrypted output * \param olen Encrypted output length * \param osize Size of the output buffer - * \param f_rng RNG function + * \param f_rng RNG function, must not be \c NULL. * \param p_rng RNG parameter * - * \note For RSA keys, the default padding type is PKCS#1 v1.5. + * \note For keys of type #MBEDTLS_PK_RSA, the signature algorithm is + * either PKCS#1 v1.5 or OAEP, depending on the padding mode in + * the underlying RSA context. For a pk object constructed by + * parsing, this is PKCS#1 v1.5 by default. + * + * \note \p f_rng is used for padding generation. * * \return 0 on success, or a specific error code. */ @@ -594,6 +972,8 @@ int mbedtls_pk_encrypt(mbedtls_pk_context *ctx, * * \param pub Context holding a public key. * \param prv Context holding a private (and public) key. + * \param f_rng RNG function, must not be \c NULL. + * \param p_rng RNG parameter * * \return \c 0 on success (keys were checked and match each other). * \return #MBEDTLS_ERR_PK_FEATURE_UNAVAILABLE if the keys could not @@ -601,7 +981,10 @@ int mbedtls_pk_encrypt(mbedtls_pk_context *ctx, * \return #MBEDTLS_ERR_PK_BAD_INPUT_DATA if a context is invalid. * \return Another non-zero value if the keys do not match. */ -int mbedtls_pk_check_pair(const mbedtls_pk_context *pub, const mbedtls_pk_context *prv); +int mbedtls_pk_check_pair(const mbedtls_pk_context *pub, + const mbedtls_pk_context *prv, + int (*f_rng)(void *, unsigned char *, size_t), + void *p_rng); /** * \brief Export debug information @@ -647,7 +1030,7 @@ static inline mbedtls_rsa_context *mbedtls_pk_rsa(const mbedtls_pk_context pk) { switch (mbedtls_pk_get_type(&pk)) { case MBEDTLS_PK_RSA: - return (mbedtls_rsa_context *) (pk).pk_ctx; + return (mbedtls_rsa_context *) (pk).MBEDTLS_PRIVATE(pk_ctx); default: return NULL; } @@ -672,7 +1055,7 @@ static inline mbedtls_ecp_keypair *mbedtls_pk_ec(const mbedtls_pk_context pk) case MBEDTLS_PK_ECKEY: case MBEDTLS_PK_ECKEY_DH: case MBEDTLS_PK_ECDSA: - return (mbedtls_ecp_keypair *) (pk).pk_ctx; + return (mbedtls_ecp_keypair *) (pk).MBEDTLS_PRIVATE(pk_ctx); default: return NULL; } @@ -684,6 +1067,10 @@ static inline mbedtls_ecp_keypair *mbedtls_pk_ec(const mbedtls_pk_context pk) /** * \brief Parse a private key in PEM or DER format * + * \note If #MBEDTLS_USE_PSA_CRYPTO is enabled, the PSA crypto + * subsystem must have been initialized by calling + * psa_crypto_init() before calling this function. + * * \param ctx The PK context to fill. It must have been initialized * but not set up. * \param key Input buffer to parse. @@ -700,6 +1087,8 @@ static inline mbedtls_ecp_keypair *mbedtls_pk_ec(const mbedtls_pk_context pk) * The empty password is not supported. * \param pwdlen Size of the password in bytes. * Ignored if \p pwd is \c NULL. + * \param f_rng RNG function, must not be \c NULL. Used for blinding. + * \param p_rng RNG parameter * * \note On entry, ctx must be empty, either freshly initialised * with mbedtls_pk_init() or reset with mbedtls_pk_free(). If you need a @@ -711,12 +1100,17 @@ static inline mbedtls_ecp_keypair *mbedtls_pk_ec(const mbedtls_pk_context pk) */ int mbedtls_pk_parse_key(mbedtls_pk_context *ctx, const unsigned char *key, size_t keylen, - const unsigned char *pwd, size_t pwdlen); + const unsigned char *pwd, size_t pwdlen, + int (*f_rng)(void *, unsigned char *, size_t), void *p_rng); /** \ingroup pk_module */ /** * \brief Parse a public key in PEM or DER format * + * \note If #MBEDTLS_USE_PSA_CRYPTO is enabled, the PSA crypto + * subsystem must have been initialized by calling + * psa_crypto_init() before calling this function. + * * \param ctx The PK context to fill. It must have been initialized * but not set up. * \param key Input buffer to parse. @@ -731,6 +1125,9 @@ int mbedtls_pk_parse_key(mbedtls_pk_context *ctx, * with mbedtls_pk_init() or reset with mbedtls_pk_free(). If you need a * specific key type, check the result with mbedtls_pk_can_do(). * + * \note For compressed points, see #MBEDTLS_ECP_PF_COMPRESSED for + * limitations. + * * \note The key is also checked for correctness. * * \return 0 if successful, or a specific PK or PEM error code @@ -743,6 +1140,10 @@ int mbedtls_pk_parse_public_key(mbedtls_pk_context *ctx, /** * \brief Load and parse a private key * + * \note If #MBEDTLS_USE_PSA_CRYPTO is enabled, the PSA crypto + * subsystem must have been initialized by calling + * psa_crypto_init() before calling this function. + * * \param ctx The PK context to fill. It must have been initialized * but not set up. * \param path filename to read the private key from @@ -751,6 +1152,8 @@ int mbedtls_pk_parse_public_key(mbedtls_pk_context *ctx, * Pass a null-terminated string if expecting an encrypted * key; a non-encrypted key will also be accepted. * The empty password is not supported. + * \param f_rng RNG function, must not be \c NULL. Used for blinding. + * \param p_rng RNG parameter * * \note On entry, ctx must be empty, either freshly initialised * with mbedtls_pk_init() or reset with mbedtls_pk_free(). If you need a @@ -761,7 +1164,8 @@ int mbedtls_pk_parse_public_key(mbedtls_pk_context *ctx, * \return 0 if successful, or a specific PK or PEM error code */ int mbedtls_pk_parse_keyfile(mbedtls_pk_context *ctx, - const char *path, const char *password); + const char *path, const char *password, + int (*f_rng)(void *, unsigned char *, size_t), void *p_rng); /** \ingroup pk_module */ /** @@ -798,7 +1202,7 @@ int mbedtls_pk_parse_public_keyfile(mbedtls_pk_context *ctx, const char *path); * \return length of data written if successful, or a specific * error code */ -int mbedtls_pk_write_key_der(mbedtls_pk_context *ctx, unsigned char *buf, size_t size); +int mbedtls_pk_write_key_der(const mbedtls_pk_context *ctx, unsigned char *buf, size_t size); /** * \brief Write a public key to a SubjectPublicKeyInfo DER structure @@ -813,7 +1217,7 @@ int mbedtls_pk_write_key_der(mbedtls_pk_context *ctx, unsigned char *buf, size_t * \return length of data written if successful, or a specific * error code */ -int mbedtls_pk_write_pubkey_der(mbedtls_pk_context *ctx, unsigned char *buf, size_t size); +int mbedtls_pk_write_pubkey_der(const mbedtls_pk_context *ctx, unsigned char *buf, size_t size); #if defined(MBEDTLS_PEM_WRITE_C) /** @@ -826,7 +1230,7 @@ int mbedtls_pk_write_pubkey_der(mbedtls_pk_context *ctx, unsigned char *buf, siz * * \return 0 if successful, or a specific error code */ -int mbedtls_pk_write_pubkey_pem(mbedtls_pk_context *ctx, unsigned char *buf, size_t size); +int mbedtls_pk_write_pubkey_pem(const mbedtls_pk_context *ctx, unsigned char *buf, size_t size); /** * \brief Write a private key to a PKCS#1 or SEC1 PEM string @@ -838,7 +1242,7 @@ int mbedtls_pk_write_pubkey_pem(mbedtls_pk_context *ctx, unsigned char *buf, siz * * \return 0 if successful, or a specific error code */ -int mbedtls_pk_write_key_pem(mbedtls_pk_context *ctx, unsigned char *buf, size_t size); +int mbedtls_pk_write_key_pem(const mbedtls_pk_context *ctx, unsigned char *buf, size_t size); #endif /* MBEDTLS_PEM_WRITE_C */ #endif /* MBEDTLS_PK_WRITE_C */ @@ -877,40 +1281,6 @@ int mbedtls_pk_write_pubkey(unsigned char **p, unsigned char *start, const mbedtls_pk_context *key); #endif /* MBEDTLS_PK_WRITE_C */ -/* - * Internal module functions. You probably do not want to use these unless you - * know you do. - */ -#if defined(MBEDTLS_FS_IO) -int mbedtls_pk_load_file(const char *path, unsigned char **buf, size_t *n); -#endif - -#if defined(MBEDTLS_USE_PSA_CRYPTO) -/** - * \brief Turn an EC key into an opaque one. - * - * \warning This is a temporary utility function for tests. It might - * change or be removed at any time without notice. - * - * \note Only ECDSA keys are supported so far. Signing with the - * specified hash is the only allowed use of that key. - * - * \param pk Input: the EC key to import to a PSA key. - * Output: a PK context wrapping that PSA key. - * \param key Output: a PSA key identifier. - * It's the caller's responsibility to call - * psa_destroy_key() on that key identifier after calling - * mbedtls_pk_free() on the PK context. - * \param hash_alg The hash algorithm to allow for use with that key. - * - * \return \c 0 if successful. - * \return An Mbed TLS error code otherwise. - */ -int mbedtls_pk_wrap_as_opaque(mbedtls_pk_context *pk, - psa_key_id_t *key, - psa_algorithm_t hash_alg); -#endif /* MBEDTLS_USE_PSA_CRYPTO */ - #ifdef __cplusplus } #endif diff --git a/vendor/mbedtls/include/mbedtls/pkcs11.h b/vendor/mbedtls/include/mbedtls/pkcs11.h deleted file mode 100644 index 908a1bc35c..0000000000 --- a/vendor/mbedtls/include/mbedtls/pkcs11.h +++ /dev/null @@ -1,253 +0,0 @@ -/** - * \file pkcs11.h - * - * \brief Wrapper for PKCS#11 library libpkcs11-helper - * - * \author Adriaan de Jong - */ -/* - * Copyright The Mbed TLS Contributors - * SPDX-License-Identifier: Apache-2.0 - * - * Licensed under the Apache License, Version 2.0 (the "License"); you may - * not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT - * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ -#ifndef MBEDTLS_PKCS11_H -#define MBEDTLS_PKCS11_H - -#if !defined(MBEDTLS_CONFIG_FILE) -#include "mbedtls/config.h" -#else -#include MBEDTLS_CONFIG_FILE -#endif - -#if defined(MBEDTLS_PKCS11_C) - -#include "mbedtls/x509_crt.h" - -#include - -#if (defined(__ARMCC_VERSION) || defined(_MSC_VER)) && \ - !defined(inline) && !defined(__cplusplus) -#define inline __inline -#endif - -#ifdef __cplusplus -extern "C" { -#endif - -#if defined(MBEDTLS_DEPRECATED_REMOVED) - -/** - * Context for PKCS #11 private keys. - */ -typedef struct mbedtls_pkcs11_context { - pkcs11h_certificate_t pkcs11h_cert; - int len; -} mbedtls_pkcs11_context; - -#if defined(MBEDTLS_DEPRECATED_WARNING) -#define MBEDTLS_DEPRECATED __attribute__((deprecated)) -#else -#define MBEDTLS_DEPRECATED -#endif - -/** - * Initialize a mbedtls_pkcs11_context. - * (Just making memory references valid.) - * - * \deprecated This function is deprecated and will be removed in a - * future version of the library. - */ -MBEDTLS_DEPRECATED void mbedtls_pkcs11_init(mbedtls_pkcs11_context *ctx); - -/** - * Fill in a Mbed TLS certificate, based on the given PKCS11 helper certificate. - * - * \deprecated This function is deprecated and will be removed in a - * future version of the library. - * - * \param cert X.509 certificate to fill - * \param pkcs11h_cert PKCS #11 helper certificate - * - * \return 0 on success. - */ -MBEDTLS_DEPRECATED int mbedtls_pkcs11_x509_cert_bind(mbedtls_x509_crt *cert, - pkcs11h_certificate_t pkcs11h_cert); - -/** - * Set up a mbedtls_pkcs11_context storing the given certificate. Note that the - * mbedtls_pkcs11_context will take over control of the certificate, freeing it when - * done. - * - * \deprecated This function is deprecated and will be removed in a - * future version of the library. - * - * \param priv_key Private key structure to fill. - * \param pkcs11_cert PKCS #11 helper certificate - * - * \return 0 on success - */ -MBEDTLS_DEPRECATED int mbedtls_pkcs11_priv_key_bind( - mbedtls_pkcs11_context *priv_key, - pkcs11h_certificate_t pkcs11_cert); - -/** - * Free the contents of the given private key context. Note that the structure - * itself is not freed. - * - * \deprecated This function is deprecated and will be removed in a - * future version of the library. - * - * \param priv_key Private key structure to cleanup - */ -MBEDTLS_DEPRECATED void mbedtls_pkcs11_priv_key_free( - mbedtls_pkcs11_context *priv_key); - -/** - * \brief Do an RSA private key decrypt, then remove the message - * padding - * - * \deprecated This function is deprecated and will be removed in a future - * version of the library. - * - * \param ctx PKCS #11 context - * \param mode must be MBEDTLS_RSA_PRIVATE, for compatibility with rsa.c's signature - * \param input buffer holding the encrypted data - * \param output buffer that will hold the plaintext - * \param olen will contain the plaintext length - * \param output_max_len maximum length of the output buffer - * - * \return 0 if successful, or an MBEDTLS_ERR_RSA_XXX error code - * - * \note The output buffer must be as large as the size - * of ctx->N (eg. 128 bytes if RSA-1024 is used) otherwise - * an error is thrown. - */ -MBEDTLS_DEPRECATED int mbedtls_pkcs11_decrypt(mbedtls_pkcs11_context *ctx, - int mode, size_t *olen, - const unsigned char *input, - unsigned char *output, - size_t output_max_len); - -/** - * \brief Do a private RSA to sign a message digest - * - * \deprecated This function is deprecated and will be removed in a future - * version of the library. - * - * \param ctx PKCS #11 context - * \param mode must be MBEDTLS_RSA_PRIVATE, for compatibility with rsa.c's signature - * \param md_alg a MBEDTLS_MD_XXX (use MBEDTLS_MD_NONE for signing raw data) - * \param hashlen message digest length (for MBEDTLS_MD_NONE only) - * \param hash buffer holding the message digest - * \param sig buffer that will hold the ciphertext - * - * \return 0 if the signing operation was successful, - * or an MBEDTLS_ERR_RSA_XXX error code - * - * \note The "sig" buffer must be as large as the size - * of ctx->N (eg. 128 bytes if RSA-1024 is used). - */ -MBEDTLS_DEPRECATED int mbedtls_pkcs11_sign(mbedtls_pkcs11_context *ctx, - int mode, - mbedtls_md_type_t md_alg, - unsigned int hashlen, - const unsigned char *hash, - unsigned char *sig); - -/** - * SSL/TLS wrappers for PKCS#11 functions - * - * \deprecated This function is deprecated and will be removed in a future - * version of the library. - */ -MBEDTLS_DEPRECATED static inline int mbedtls_ssl_pkcs11_decrypt(void *ctx, - int mode, - size_t *olen, - const unsigned char *input, - unsigned char *output, - size_t output_max_len) -{ - return mbedtls_pkcs11_decrypt((mbedtls_pkcs11_context *) ctx, mode, olen, input, output, - output_max_len); -} - -/** - * \brief This function signs a message digest using RSA. - * - * \deprecated This function is deprecated and will be removed in a future - * version of the library. - * - * \param ctx The PKCS #11 context. - * \param f_rng The RNG function. This parameter is unused. - * \param p_rng The RNG context. This parameter is unused. - * \param mode The operation to run. This must be set to - * MBEDTLS_RSA_PRIVATE, for compatibility with rsa.c's - * signature. - * \param md_alg The message digest algorithm. One of the MBEDTLS_MD_XXX - * must be passed to this function and MBEDTLS_MD_NONE can be - * used for signing raw data. - * \param hashlen The message digest length (for MBEDTLS_MD_NONE only). - * \param hash The buffer holding the message digest. - * \param sig The buffer that will hold the ciphertext. - * - * \return \c 0 if the signing operation was successful. - * \return A non-zero error code on failure. - * - * \note The \p sig buffer must be as large as the size of - * ctx->N. For example, 128 bytes if RSA-1024 is - * used. - */ -MBEDTLS_DEPRECATED static inline int mbedtls_ssl_pkcs11_sign(void *ctx, - int (*f_rng)(void *, - unsigned char *, - size_t), - void *p_rng, - int mode, - mbedtls_md_type_t md_alg, - unsigned int hashlen, - const unsigned char *hash, - unsigned char *sig) -{ - ((void) f_rng); - ((void) p_rng); - return mbedtls_pkcs11_sign((mbedtls_pkcs11_context *) ctx, mode, md_alg, - hashlen, hash, sig); -} - -/** - * This function gets the length of the private key. - * - * \deprecated This function is deprecated and will be removed in a future - * version of the library. - * - * \param ctx The PKCS #11 context. - * - * \return The length of the private key. - */ -MBEDTLS_DEPRECATED static inline size_t mbedtls_ssl_pkcs11_key_len(void *ctx) -{ - return ((mbedtls_pkcs11_context *) ctx)->len; -} - -#undef MBEDTLS_DEPRECATED - -#endif /* MBEDTLS_DEPRECATED_REMOVED */ - -#ifdef __cplusplus -} -#endif - -#endif /* MBEDTLS_PKCS11_C */ - -#endif /* MBEDTLS_PKCS11_H */ diff --git a/vendor/mbedtls/include/mbedtls/pkcs12.h b/vendor/mbedtls/include/mbedtls/pkcs12.h index 63e2e63b58..87f7681f29 100644 --- a/vendor/mbedtls/include/mbedtls/pkcs12.h +++ b/vendor/mbedtls/include/mbedtls/pkcs12.h @@ -5,28 +5,12 @@ */ /* * Copyright The Mbed TLS Contributors - * SPDX-License-Identifier: Apache-2.0 - * - * Licensed under the Apache License, Version 2.0 (the "License"); you may - * not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT - * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. + * SPDX-License-Identifier: Apache-2.0 OR GPL-2.0-or-later */ #ifndef MBEDTLS_PKCS12_H #define MBEDTLS_PKCS12_H -#if !defined(MBEDTLS_CONFIG_FILE) -#include "mbedtls/config.h" -#else -#include MBEDTLS_CONFIG_FILE -#endif +#include "mbedtls/build_info.h" #include "mbedtls/md.h" #include "mbedtls/cipher.h" @@ -47,34 +31,16 @@ #define MBEDTLS_PKCS12_DERIVE_IV 2 /**< initialization vector */ #define MBEDTLS_PKCS12_DERIVE_MAC_KEY 3 /**< integrity / MAC key */ -#define MBEDTLS_PKCS12_PBE_DECRYPT 0 -#define MBEDTLS_PKCS12_PBE_ENCRYPT 1 +#define MBEDTLS_PKCS12_PBE_DECRYPT MBEDTLS_DECRYPT +#define MBEDTLS_PKCS12_PBE_ENCRYPT MBEDTLS_ENCRYPT #ifdef __cplusplus extern "C" { #endif -#if defined(MBEDTLS_ASN1_PARSE_C) - -/** - * \brief PKCS12 Password Based function (encryption / decryption) - * for pbeWithSHAAnd128BitRC4 - * - * \param pbe_params an ASN1 buffer containing the pkcs-12PbeParams structure - * \param mode either MBEDTLS_PKCS12_PBE_ENCRYPT or MBEDTLS_PKCS12_PBE_DECRYPT - * \param pwd the password used (may be NULL if no password is used) - * \param pwdlen length of the password (may be 0) - * \param input the input data - * \param len data length - * \param output the output buffer - * - * \return 0 if successful, or a MBEDTLS_ERR_XXX code - */ -int mbedtls_pkcs12_pbe_sha1_rc4_128(mbedtls_asn1_buf *pbe_params, int mode, - const unsigned char *pwd, size_t pwdlen, - const unsigned char *input, size_t len, - unsigned char *output); +#if defined(MBEDTLS_ASN1_PARSE_C) && defined(MBEDTLS_CIPHER_C) +#if !defined(MBEDTLS_DEPRECATED_REMOVED) /** * \brief PKCS12 Password Based function (encryption / decryption) * for cipher-based and mbedtls_md-based PBE's @@ -82,6 +48,10 @@ int mbedtls_pkcs12_pbe_sha1_rc4_128(mbedtls_asn1_buf *pbe_params, int mode, * \note When encrypting, #MBEDTLS_CIPHER_PADDING_PKCS7 must * be enabled at compile time. * + * \deprecated This function is deprecated and will be removed in a + * future version of the library. + * Please use mbedtls_pkcs12_pbe_ext() instead. + * * \warning When decrypting: * - if #MBEDTLS_CIPHER_PADDING_PKCS7 is enabled at compile * time, this function validates the CBC padding and returns @@ -116,11 +86,13 @@ int mbedtls_pkcs12_pbe_sha1_rc4_128(mbedtls_asn1_buf *pbe_params, int mode, * * \return 0 if successful, or a MBEDTLS_ERR_XXX code */ -int mbedtls_pkcs12_pbe(mbedtls_asn1_buf *pbe_params, int mode, - mbedtls_cipher_type_t cipher_type, mbedtls_md_type_t md_type, - const unsigned char *pwd, size_t pwdlen, - const unsigned char *data, size_t len, - unsigned char *output); +int MBEDTLS_DEPRECATED mbedtls_pkcs12_pbe(mbedtls_asn1_buf *pbe_params, int mode, + mbedtls_cipher_type_t cipher_type, + mbedtls_md_type_t md_type, + const unsigned char *pwd, size_t pwdlen, + const unsigned char *data, size_t len, + unsigned char *output); +#endif /* MBEDTLS_DEPRECATED_REMOVED */ #if defined(MBEDTLS_CIPHER_PADDING_PKCS7) @@ -173,7 +145,7 @@ int mbedtls_pkcs12_pbe_ext(mbedtls_asn1_buf *pbe_params, int mode, #endif /* MBEDTLS_CIPHER_PADDING_PKCS7 */ -#endif /* MBEDTLS_ASN1_PARSE_C */ +#endif /* MBEDTLS_ASN1_PARSE_C && MBEDTLS_CIPHER_C */ /** * \brief The PKCS#12 derivation function uses a password and a salt @@ -191,7 +163,7 @@ int mbedtls_pkcs12_pbe_ext(mbedtls_asn1_buf *pbe_params, int mode, * no byte order mark and with a null terminator (i.e. the * last two bytes should be 0x00 0x00). * \param pwdlen length of the password (may be 0). - * \param salt Salt buffer to use This may only be \c NULL when + * \param salt Salt buffer to use. This may only be \c NULL when * \p saltlen is 0. * \param saltlen length of the salt (may be zero) * \param mbedtls_md mbedtls_md type to use during the derivation diff --git a/vendor/mbedtls/include/mbedtls/pkcs5.h b/vendor/mbedtls/include/mbedtls/pkcs5.h index e995d3d9d6..9ba5689d4a 100644 --- a/vendor/mbedtls/include/mbedtls/pkcs5.h +++ b/vendor/mbedtls/include/mbedtls/pkcs5.h @@ -7,31 +7,17 @@ */ /* * Copyright The Mbed TLS Contributors - * SPDX-License-Identifier: Apache-2.0 - * - * Licensed under the Apache License, Version 2.0 (the "License"); you may - * not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT - * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. + * SPDX-License-Identifier: Apache-2.0 OR GPL-2.0-or-later */ #ifndef MBEDTLS_PKCS5_H #define MBEDTLS_PKCS5_H -#if !defined(MBEDTLS_CONFIG_FILE) -#include "mbedtls/config.h" -#else -#include MBEDTLS_CONFIG_FILE -#endif +#include "mbedtls/build_info.h" +#include "mbedtls/platform_util.h" #include "mbedtls/asn1.h" #include "mbedtls/md.h" +#include "mbedtls/cipher.h" #include #include @@ -45,21 +31,26 @@ /** Given private key password does not allow for correct decryption. */ #define MBEDTLS_ERR_PKCS5_PASSWORD_MISMATCH -0x2e00 -#define MBEDTLS_PKCS5_DECRYPT 0 -#define MBEDTLS_PKCS5_ENCRYPT 1 +#define MBEDTLS_PKCS5_DECRYPT MBEDTLS_DECRYPT +#define MBEDTLS_PKCS5_ENCRYPT MBEDTLS_ENCRYPT #ifdef __cplusplus extern "C" { #endif -#if defined(MBEDTLS_ASN1_PARSE_C) +#if defined(MBEDTLS_ASN1_PARSE_C) && defined(MBEDTLS_CIPHER_C) +#if !defined(MBEDTLS_DEPRECATED_REMOVED) /** * \brief PKCS#5 PBES2 function * * \note When encrypting, #MBEDTLS_CIPHER_PADDING_PKCS7 must * be enabled at compile time. * + * \deprecated This function is deprecated and will be removed in a + * future version of the library. + * Please use mbedtls_pkcs5_pbes2_ext() instead. + * * \warning When decrypting: * - if #MBEDTLS_CIPHER_PADDING_PKCS7 is enabled at compile * time, this function validates the CBC padding and returns @@ -90,10 +81,11 @@ extern "C" { * * \returns 0 on success, or a MBEDTLS_ERR_XXX code if verification fails. */ -int mbedtls_pkcs5_pbes2(const mbedtls_asn1_buf *pbe_params, int mode, - const unsigned char *pwd, size_t pwdlen, - const unsigned char *data, size_t datalen, - unsigned char *output); +int MBEDTLS_DEPRECATED mbedtls_pkcs5_pbes2(const mbedtls_asn1_buf *pbe_params, int mode, + const unsigned char *pwd, size_t pwdlen, + const unsigned char *data, size_t datalen, + unsigned char *output); +#endif /* MBEDTLS_DEPRECATED_REMOVED */ #if defined(MBEDTLS_CIPHER_PADDING_PKCS7) @@ -138,11 +130,35 @@ int mbedtls_pkcs5_pbes2_ext(const mbedtls_asn1_buf *pbe_params, int mode, #endif /* MBEDTLS_CIPHER_PADDING_PKCS7 */ -#endif /* MBEDTLS_ASN1_PARSE_C */ +#endif /* MBEDTLS_ASN1_PARSE_C && MBEDTLS_CIPHER_C*/ +/** + * \brief PKCS#5 PBKDF2 using HMAC without using the HMAC context + * + * \param md_type Hash algorithm used + * \param password Password to use when generating key + * \param plen Length of password + * \param salt Salt to use when generating key + * \param slen Length of salt + * \param iteration_count Iteration count + * \param key_length Length of generated key in bytes + * \param output Generated key. Must be at least as big as key_length + * + * \returns 0 on success, or a MBEDTLS_ERR_XXX code if verification fails. + */ +int mbedtls_pkcs5_pbkdf2_hmac_ext(mbedtls_md_type_t md_type, + const unsigned char *password, + size_t plen, const unsigned char *salt, size_t slen, + unsigned int iteration_count, + uint32_t key_length, unsigned char *output); + +#if defined(MBEDTLS_MD_C) +#if !defined(MBEDTLS_DEPRECATED_REMOVED) /** * \brief PKCS#5 PBKDF2 using HMAC * + * \deprecated Superseded by mbedtls_pkcs5_pbkdf2_hmac_ext(). + * * \param ctx Generic HMAC context * \param password Password to use when generating key * \param plen Length of password @@ -154,11 +170,16 @@ int mbedtls_pkcs5_pbes2_ext(const mbedtls_asn1_buf *pbe_params, int mode, * * \returns 0 on success, or a MBEDTLS_ERR_XXX code if verification fails. */ -int mbedtls_pkcs5_pbkdf2_hmac(mbedtls_md_context_t *ctx, const unsigned char *password, - size_t plen, const unsigned char *salt, size_t slen, - unsigned int iteration_count, - uint32_t key_length, unsigned char *output); - +int MBEDTLS_DEPRECATED mbedtls_pkcs5_pbkdf2_hmac(mbedtls_md_context_t *ctx, + const unsigned char *password, + size_t plen, + const unsigned char *salt, + size_t slen, + unsigned int iteration_count, + uint32_t key_length, + unsigned char *output); +#endif /* !MBEDTLS_DEPRECATED_REMOVED */ +#endif /* MBEDTLS_MD_C */ #if defined(MBEDTLS_SELF_TEST) /** diff --git a/vendor/mbedtls/include/mbedtls/pkcs7.h b/vendor/mbedtls/include/mbedtls/pkcs7.h new file mode 100644 index 0000000000..e9b482208e --- /dev/null +++ b/vendor/mbedtls/include/mbedtls/pkcs7.h @@ -0,0 +1,240 @@ +/** + * \file pkcs7.h + * + * \brief PKCS #7 generic defines and structures + * https://tools.ietf.org/html/rfc2315 + */ +/* + * Copyright The Mbed TLS Contributors + * SPDX-License-Identifier: Apache-2.0 OR GPL-2.0-or-later + */ + +/** + * Note: For the time being, this implementation of the PKCS #7 cryptographic + * message syntax is a partial implementation of RFC 2315. + * Differences include: + * - The RFC specifies 6 different content types. The only type currently + * supported in Mbed TLS is the signed-data content type. + * - The only supported PKCS #7 Signed Data syntax version is version 1 + * - The RFC specifies support for BER. This implementation is limited to + * DER only. + * - The RFC specifies that multiple digest algorithms can be specified + * in the Signed Data type. Only one digest algorithm is supported in Mbed TLS. + * - The RFC specifies the Signed Data type can contain multiple X.509 or PKCS #6 extended + * certificates. In Mbed TLS, this list can only contain 0 or 1 certificates + * and they must be in X.509 format. + * - The RFC specifies the Signed Data type can contain + * certificate-revocation lists (CRLs). This implementation has no support + * for CRLs so it is assumed to be an empty list. + * - The RFC allows for SignerInfo structure to optionally contain + * unauthenticatedAttributes and authenticatedAttributes. In Mbed TLS it is + * assumed these fields are empty. + * - The RFC allows for the signed Data type to contain contentInfo. This + * implementation assumes the type is DATA and the content is empty. + */ + +#ifndef MBEDTLS_PKCS7_H +#define MBEDTLS_PKCS7_H + +#include "mbedtls/private_access.h" + +#include "mbedtls/build_info.h" + +#include "mbedtls/asn1.h" +#include "mbedtls/x509_crt.h" + +/** + * \name PKCS #7 Module Error codes + * \{ + */ +#define MBEDTLS_ERR_PKCS7_INVALID_FORMAT -0x5300 /**< The format is invalid, e.g. different type expected. */ +#define MBEDTLS_ERR_PKCS7_FEATURE_UNAVAILABLE -0x5380 /**< Unavailable feature, e.g. anything other than signed data. */ +#define MBEDTLS_ERR_PKCS7_INVALID_VERSION -0x5400 /**< The PKCS #7 version element is invalid or cannot be parsed. */ +#define MBEDTLS_ERR_PKCS7_INVALID_CONTENT_INFO -0x5480 /**< The PKCS #7 content info is invalid or cannot be parsed. */ +#define MBEDTLS_ERR_PKCS7_INVALID_ALG -0x5500 /**< The algorithm tag or value is invalid or cannot be parsed. */ +#define MBEDTLS_ERR_PKCS7_INVALID_CERT -0x5580 /**< The certificate tag or value is invalid or cannot be parsed. */ +#define MBEDTLS_ERR_PKCS7_INVALID_SIGNATURE -0x5600 /**< Error parsing the signature */ +#define MBEDTLS_ERR_PKCS7_INVALID_SIGNER_INFO -0x5680 /**< Error parsing the signer's info */ +#define MBEDTLS_ERR_PKCS7_BAD_INPUT_DATA -0x5700 /**< Input invalid. */ +#define MBEDTLS_ERR_PKCS7_ALLOC_FAILED -0x5780 /**< Allocation of memory failed. */ +#define MBEDTLS_ERR_PKCS7_VERIFY_FAIL -0x5800 /**< Verification Failed */ +#define MBEDTLS_ERR_PKCS7_CERT_DATE_INVALID -0x5880 /**< The PKCS #7 date issued/expired dates are invalid */ +/* \} name */ + +/** + * \name PKCS #7 Supported Version + * \{ + */ +#define MBEDTLS_PKCS7_SUPPORTED_VERSION 0x01 +/* \} name */ + +#ifdef __cplusplus +extern "C" { +#endif + +/** + * Type-length-value structure that allows for ASN.1 using DER. + */ +typedef mbedtls_asn1_buf mbedtls_pkcs7_buf; + +/** + * Container for ASN.1 named information objects. + * It allows for Relative Distinguished Names (e.g. cn=localhost,ou=code,etc.). + */ +typedef mbedtls_asn1_named_data mbedtls_pkcs7_name; + +/** + * Container for a sequence of ASN.1 items + */ +typedef mbedtls_asn1_sequence mbedtls_pkcs7_sequence; + +/** + * PKCS #7 types + */ +typedef enum { + MBEDTLS_PKCS7_NONE=0, + MBEDTLS_PKCS7_DATA, + MBEDTLS_PKCS7_SIGNED_DATA, + MBEDTLS_PKCS7_ENVELOPED_DATA, + MBEDTLS_PKCS7_SIGNED_AND_ENVELOPED_DATA, + MBEDTLS_PKCS7_DIGESTED_DATA, + MBEDTLS_PKCS7_ENCRYPTED_DATA, +} +mbedtls_pkcs7_type; + +/** + * Structure holding PKCS #7 signer info + */ +typedef struct mbedtls_pkcs7_signer_info { + int MBEDTLS_PRIVATE(version); + mbedtls_x509_buf MBEDTLS_PRIVATE(serial); + mbedtls_x509_name MBEDTLS_PRIVATE(issuer); + mbedtls_x509_buf MBEDTLS_PRIVATE(issuer_raw); + mbedtls_x509_buf MBEDTLS_PRIVATE(alg_identifier); + mbedtls_x509_buf MBEDTLS_PRIVATE(sig_alg_identifier); + mbedtls_x509_buf MBEDTLS_PRIVATE(sig); + struct mbedtls_pkcs7_signer_info *MBEDTLS_PRIVATE(next); +} +mbedtls_pkcs7_signer_info; + +/** + * Structure holding the signed data section + */ +typedef struct mbedtls_pkcs7_signed_data { + int MBEDTLS_PRIVATE(version); + mbedtls_pkcs7_buf MBEDTLS_PRIVATE(digest_alg_identifiers); + int MBEDTLS_PRIVATE(no_of_certs); + mbedtls_x509_crt MBEDTLS_PRIVATE(certs); + int MBEDTLS_PRIVATE(no_of_crls); + mbedtls_x509_crl MBEDTLS_PRIVATE(crl); + int MBEDTLS_PRIVATE(no_of_signers); + mbedtls_pkcs7_signer_info MBEDTLS_PRIVATE(signers); +} +mbedtls_pkcs7_signed_data; + +/** + * Structure holding PKCS #7 structure, only signed data for now + */ +typedef struct mbedtls_pkcs7 { + mbedtls_pkcs7_buf MBEDTLS_PRIVATE(raw); + mbedtls_pkcs7_signed_data MBEDTLS_PRIVATE(signed_data); +} +mbedtls_pkcs7; + +/** + * \brief Initialize mbedtls_pkcs7 structure. + * + * \param pkcs7 mbedtls_pkcs7 structure. + */ +void mbedtls_pkcs7_init(mbedtls_pkcs7 *pkcs7); + +/** + * \brief Parse a single DER formatted PKCS #7 detached signature. + * + * \param pkcs7 The mbedtls_pkcs7 structure to be filled by the parser. + * \param buf The buffer holding only the DER encoded PKCS #7 content. + * \param buflen The size in bytes of \p buf. The size must be exactly the + * length of the DER encoded PKCS #7 content. + * + * \note This function makes an internal copy of the PKCS #7 buffer + * \p buf. In particular, \p buf may be destroyed or reused + * after this call returns. + * \note Signatures with internal data are not supported. + * + * \return The \c mbedtls_pkcs7_type of \p buf, if successful. + * \return A negative error code on failure. + */ +int mbedtls_pkcs7_parse_der(mbedtls_pkcs7 *pkcs7, const unsigned char *buf, + const size_t buflen); + +/** + * \brief Verification of PKCS #7 signature against a caller-supplied + * certificate. + * + * For each signer in the PKCS structure, this function computes + * a signature over the supplied data, using the supplied + * certificate and the same digest algorithm as specified by the + * signer. It then compares this signature against the + * signer's signature; verification succeeds if any comparison + * matches. + * + * This function does not use the certificates held within the + * PKCS #7 structure itself, and does not check that the + * certificate is signed by a trusted certification authority. + * + * \param pkcs7 mbedtls_pkcs7 structure containing signature. + * \param cert Certificate containing key to verify signature. + * \param data Plain data on which signature has to be verified. + * \param datalen Length of the data. + * + * \note This function internally calculates the hash on the supplied + * plain data for signature verification. + * + * \return 0 if the signature verifies, or a negative error code on failure. + */ +int mbedtls_pkcs7_signed_data_verify(mbedtls_pkcs7 *pkcs7, + const mbedtls_x509_crt *cert, + const unsigned char *data, + size_t datalen); + +/** + * \brief Verification of PKCS #7 signature against a caller-supplied + * certificate. + * + * For each signer in the PKCS structure, this function + * validates a signature over the supplied hash, using the + * supplied certificate and the same digest algorithm as + * specified by the signer. Verification succeeds if any + * signature is good. + * + * This function does not use the certificates held within the + * PKCS #7 structure itself, and does not check that the + * certificate is signed by a trusted certification authority. + * + * \param pkcs7 PKCS #7 structure containing signature. + * \param cert Certificate containing key to verify signature. + * \param hash Hash of the plain data on which signature has to be verified. + * \param hashlen Length of the hash. + * + * \note This function is different from mbedtls_pkcs7_signed_data_verify() + * in that it is directly passed the hash of the data. + * + * \return 0 if the signature verifies, or a negative error code on failure. + */ +int mbedtls_pkcs7_signed_hash_verify(mbedtls_pkcs7 *pkcs7, + const mbedtls_x509_crt *cert, + const unsigned char *hash, size_t hashlen); + +/** + * \brief Unallocate all PKCS #7 data and zeroize the memory. + * It doesn't free \p pkcs7 itself. This should be done by the caller. + * + * \param pkcs7 mbedtls_pkcs7 structure to free. + */ +void mbedtls_pkcs7_free(mbedtls_pkcs7 *pkcs7); + +#ifdef __cplusplus +} +#endif + +#endif /* pkcs7.h */ diff --git a/vendor/mbedtls/include/mbedtls/platform.h b/vendor/mbedtls/include/mbedtls/platform.h index c8c6e63f01..de3d71d9dc 100644 --- a/vendor/mbedtls/include/mbedtls/platform.h +++ b/vendor/mbedtls/include/mbedtls/platform.h @@ -21,38 +21,18 @@ */ /* * Copyright The Mbed TLS Contributors - * SPDX-License-Identifier: Apache-2.0 - * - * Licensed under the Apache License, Version 2.0 (the "License"); you may - * not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT - * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. + * SPDX-License-Identifier: Apache-2.0 OR GPL-2.0-or-later */ #ifndef MBEDTLS_PLATFORM_H #define MBEDTLS_PLATFORM_H +#include "mbedtls/private_access.h" -#if !defined(MBEDTLS_CONFIG_FILE) -#include "mbedtls/config.h" -#else -#include MBEDTLS_CONFIG_FILE -#endif +#include "mbedtls/build_info.h" #if defined(MBEDTLS_HAVE_TIME) #include "mbedtls/platform_time.h" #endif -/** Hardware accelerator failed */ -#define MBEDTLS_ERR_PLATFORM_HW_ACCEL_FAILED -0x0070 -/** The requested feature is not supported by the platform */ -#define MBEDTLS_ERR_PLATFORM_FEATURE_UNSUPPORTED -0x0072 - #ifdef __cplusplus extern "C" { #endif @@ -61,7 +41,7 @@ extern "C" { * \name SECTION: Module settings * * The configuration options you can set for this module are in this section. - * Either change them in config.h or define them on the compiler command line. + * Either change them in mbedtls_config.h or define them on the compiler command line. * \{ */ @@ -106,6 +86,9 @@ extern "C" { #if !defined(MBEDTLS_PLATFORM_STD_FREE) #define MBEDTLS_PLATFORM_STD_FREE free /**< The default \c free function to use. */ #endif +#if !defined(MBEDTLS_PLATFORM_STD_SETBUF) +#define MBEDTLS_PLATFORM_STD_SETBUF setbuf /**< The default \c setbuf function to use. */ +#endif #if !defined(MBEDTLS_PLATFORM_STD_EXIT) #define MBEDTLS_PLATFORM_STD_EXIT exit /**< The default \c exit function to use. */ #endif @@ -310,6 +293,59 @@ int mbedtls_platform_set_vsnprintf(int (*vsnprintf_func)(char *s, size_t n, #endif /* MBEDTLS_PLATFORM_VSNPRINTF_MACRO */ #endif /* MBEDTLS_PLATFORM_VSNPRINTF_ALT */ +/* + * The function pointers for setbuf + */ +#if defined(MBEDTLS_PLATFORM_SETBUF_ALT) +#include +/** + * \brief Function pointer to call for `setbuf()` functionality + * (changing the internal buffering on stdio calls). + * + * \note The library calls this function to disable + * buffering when reading or writing sensitive data, + * to avoid having extra copies of sensitive data + * remaining in stdio buffers after the file is + * closed. If this is not a concern, for example if + * your platform's stdio doesn't have any buffering, + * you can set mbedtls_setbuf to a function that + * does nothing. + * + * The library always calls this function with + * `buf` equal to `NULL`. + */ +extern void (*mbedtls_setbuf)(FILE *stream, char *buf); + +/** + * \brief Dynamically configure the function that is called + * when the mbedtls_setbuf() function is called by the + * library. + * + * \param setbuf_func The \c setbuf function implementation + * + * \return \c 0 + */ +int mbedtls_platform_set_setbuf(void (*setbuf_func)( + FILE *stream, char *buf)); +#else +#undef mbedtls_setbuf +#if defined(MBEDTLS_PLATFORM_SETBUF_MACRO) +/** + * \brief Macro defining the function for the library to + * call for `setbuf` functionality (changing the + * internal buffering on stdio calls). + * + * \note See extra comments on the mbedtls_setbuf() function + * pointer above. + * + * \return \c 0 on success, negative on error. + */ +#define mbedtls_setbuf MBEDTLS_PLATFORM_SETBUF_MACRO +#else +#define mbedtls_setbuf setbuf +#endif /* MBEDTLS_PLATFORM_SETBUF_MACRO */ +#endif /* MBEDTLS_PLATFORM_SETBUF_ALT */ + /* * The function pointers for exit */ @@ -402,7 +438,7 @@ int mbedtls_platform_set_nv_seed( * setup or teardown operations. */ typedef struct mbedtls_platform_context { - char dummy; /**< A placeholder member, as empty structs are not portable. */ + char MBEDTLS_PRIVATE(dummy); /**< A placeholder member, as empty structs are not portable. */ } mbedtls_platform_context; diff --git a/vendor/mbedtls/include/mbedtls/platform_time.h b/vendor/mbedtls/include/mbedtls/platform_time.h index 112286bef8..97f1963aba 100644 --- a/vendor/mbedtls/include/mbedtls/platform_time.h +++ b/vendor/mbedtls/include/mbedtls/platform_time.h @@ -5,28 +5,12 @@ */ /* * Copyright The Mbed TLS Contributors - * SPDX-License-Identifier: Apache-2.0 - * - * Licensed under the Apache License, Version 2.0 (the "License"); you may - * not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT - * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. + * SPDX-License-Identifier: Apache-2.0 OR GPL-2.0-or-later */ #ifndef MBEDTLS_PLATFORM_TIME_H #define MBEDTLS_PLATFORM_TIME_H -#if !defined(MBEDTLS_CONFIG_FILE) -#include "mbedtls/config.h" -#else -#include MBEDTLS_CONFIG_FILE -#endif +#include "mbedtls/build_info.h" #ifdef __cplusplus extern "C" { @@ -43,6 +27,29 @@ typedef MBEDTLS_PLATFORM_TIME_TYPE_MACRO mbedtls_time_t; typedef time_t mbedtls_time_t; #endif /* MBEDTLS_PLATFORM_TIME_TYPE_MACRO */ +#if defined(MBEDTLS_PLATFORM_MS_TIME_TYPE_MACRO) +typedef MBEDTLS_PLATFORM_MS_TIME_TYPE_MACRO mbedtls_ms_time_t; +#else +#include +#include +typedef int64_t mbedtls_ms_time_t; +#endif /* MBEDTLS_PLATFORM_MS_TIME_TYPE_MACRO */ + +/** + * \brief Get time in milliseconds. + * + * \return Monotonically-increasing current time in milliseconds. + * + * \note Define MBEDTLS_PLATFORM_MS_TIME_ALT to be able to provide an + * alternative implementation + * + * \warning This function returns a monotonically-increasing time value from a + * start time that will differ from platform to platform, and possibly + * from run to run of the process. + * + */ +mbedtls_ms_time_t mbedtls_ms_time(void); + /* * The function pointers for time */ diff --git a/vendor/mbedtls/include/mbedtls/platform_util.h b/vendor/mbedtls/include/mbedtls/platform_util.h index 62f6d70388..1b371ef3f4 100644 --- a/vendor/mbedtls/include/mbedtls/platform_util.h +++ b/vendor/mbedtls/include/mbedtls/platform_util.h @@ -6,28 +6,12 @@ */ /* * Copyright The Mbed TLS Contributors - * SPDX-License-Identifier: Apache-2.0 - * - * Licensed under the Apache License, Version 2.0 (the "License"); you may - * not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT - * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. + * SPDX-License-Identifier: Apache-2.0 OR GPL-2.0-or-later */ #ifndef MBEDTLS_PLATFORM_UTIL_H #define MBEDTLS_PLATFORM_UTIL_H -#if !defined(MBEDTLS_CONFIG_FILE) -#include "mbedtls/config.h" -#else -#include MBEDTLS_CONFIG_FILE -#endif +#include "mbedtls/build_info.h" #include #if defined(MBEDTLS_HAVE_TIME_DATE) @@ -39,85 +23,9 @@ extern "C" { #endif -#if defined(MBEDTLS_CHECK_PARAMS) - -#if defined(MBEDTLS_CHECK_PARAMS_ASSERT) -/* Allow the user to define MBEDTLS_PARAM_FAILED to something like assert - * (which is what our config.h suggests). */ -#include -#endif /* MBEDTLS_CHECK_PARAMS_ASSERT */ - -#if defined(MBEDTLS_PARAM_FAILED) -/** An alternative definition of MBEDTLS_PARAM_FAILED has been set in config.h. - * - * This flag can be used to check whether it is safe to assume that - * MBEDTLS_PARAM_FAILED() will expand to a call to mbedtls_param_failed(). - */ -#define MBEDTLS_PARAM_FAILED_ALT - -#elif defined(MBEDTLS_CHECK_PARAMS_ASSERT) -#define MBEDTLS_PARAM_FAILED(cond) assert(cond) -#define MBEDTLS_PARAM_FAILED_ALT - -#else /* MBEDTLS_PARAM_FAILED */ -#define MBEDTLS_PARAM_FAILED(cond) \ - mbedtls_param_failed( #cond, __FILE__, __LINE__) - -/** - * \brief User supplied callback function for parameter validation failure. - * See #MBEDTLS_CHECK_PARAMS for context. - * - * This function will be called unless an alternative treatment - * is defined through the #MBEDTLS_PARAM_FAILED macro. - * - * This function can return, and the operation will be aborted, or - * alternatively, through use of setjmp()/longjmp() can resume - * execution in the application code. - * - * \param failure_condition The assertion that didn't hold. - * \param file The file where the assertion failed. - * \param line The line in the file where the assertion failed. - */ -void mbedtls_param_failed(const char *failure_condition, - const char *file, - int line); -#endif /* MBEDTLS_PARAM_FAILED */ - -/* Internal macro meant to be called only from within the library. */ -#define MBEDTLS_INTERNAL_VALIDATE_RET(cond, ret) \ - do { \ - if (!(cond)) \ - { \ - MBEDTLS_PARAM_FAILED(cond); \ - return ret; \ - } \ - } while (0) - -/* Internal macro meant to be called only from within the library. */ -#define MBEDTLS_INTERNAL_VALIDATE(cond) \ - do { \ - if (!(cond)) \ - { \ - MBEDTLS_PARAM_FAILED(cond); \ - return; \ - } \ - } while (0) - -#else /* MBEDTLS_CHECK_PARAMS */ - -/* Internal macros meant to be called only from within the library. */ -#define MBEDTLS_INTERNAL_VALIDATE_RET(cond, ret) do { } while (0) -#define MBEDTLS_INTERNAL_VALIDATE(cond) do { } while (0) - -#endif /* MBEDTLS_CHECK_PARAMS */ - /* Internal helper macros for deprecating API constants. */ #if !defined(MBEDTLS_DEPRECATED_REMOVED) #if defined(MBEDTLS_DEPRECATED_WARNING) -/* Deliberately don't (yet) export MBEDTLS_DEPRECATED here - * to avoid conflict with other headers which define and use - * it, too. We might want to move all these definitions here at - * some point for uniformity. */ #define MBEDTLS_DEPRECATED __attribute__((deprecated)) MBEDTLS_DEPRECATED typedef char const *mbedtls_deprecated_string_constant_t; #define MBEDTLS_DEPRECATED_STRING_CONSTANT(VAL) \ @@ -125,15 +33,15 @@ MBEDTLS_DEPRECATED typedef char const *mbedtls_deprecated_string_constant_t; MBEDTLS_DEPRECATED typedef int mbedtls_deprecated_numeric_constant_t; #define MBEDTLS_DEPRECATED_NUMERIC_CONSTANT(VAL) \ ((mbedtls_deprecated_numeric_constant_t) (VAL)) -#undef MBEDTLS_DEPRECATED #else /* MBEDTLS_DEPRECATED_WARNING */ +#define MBEDTLS_DEPRECATED #define MBEDTLS_DEPRECATED_STRING_CONSTANT(VAL) VAL #define MBEDTLS_DEPRECATED_NUMERIC_CONSTANT(VAL) VAL #endif /* MBEDTLS_DEPRECATED_WARNING */ #endif /* MBEDTLS_DEPRECATED_REMOVED */ /* Implementation of the check-return facility. - * See the user documentation in config.h. + * See the user documentation in mbedtls_config.h. * * Do not use this macro directly to annotate function: instead, * use one of MBEDTLS_CHECK_RETURN_CRITICAL or MBEDTLS_CHECK_RETURN_TYPICAL diff --git a/vendor/mbedtls/include/mbedtls/poly1305.h b/vendor/mbedtls/include/mbedtls/poly1305.h index 7b1faa51f3..61bcaa6b64 100644 --- a/vendor/mbedtls/include/mbedtls/poly1305.h +++ b/vendor/mbedtls/include/mbedtls/poly1305.h @@ -14,29 +14,14 @@ /* * Copyright The Mbed TLS Contributors - * SPDX-License-Identifier: Apache-2.0 - * - * Licensed under the Apache License, Version 2.0 (the "License"); you may - * not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT - * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. + * SPDX-License-Identifier: Apache-2.0 OR GPL-2.0-or-later */ #ifndef MBEDTLS_POLY1305_H #define MBEDTLS_POLY1305_H +#include "mbedtls/private_access.h" -#if !defined(MBEDTLS_CONFIG_FILE) -#include "mbedtls/config.h" -#else -#include MBEDTLS_CONFIG_FILE -#endif +#include "mbedtls/build_info.h" #include #include @@ -44,16 +29,6 @@ /** Invalid input parameter(s). */ #define MBEDTLS_ERR_POLY1305_BAD_INPUT_DATA -0x0057 -/* MBEDTLS_ERR_POLY1305_FEATURE_UNAVAILABLE is deprecated and should not be - * used. */ -/** Feature not available. For example, s part of the API is not implemented. */ -#define MBEDTLS_ERR_POLY1305_FEATURE_UNAVAILABLE -0x0059 - -/* MBEDTLS_ERR_POLY1305_HW_ACCEL_FAILED is deprecated and should not be used. - */ -/** Poly1305 hardware accelerator failed. */ -#define MBEDTLS_ERR_POLY1305_HW_ACCEL_FAILED -0x005B - #ifdef __cplusplus extern "C" { #endif @@ -61,11 +36,11 @@ extern "C" { #if !defined(MBEDTLS_POLY1305_ALT) typedef struct mbedtls_poly1305_context { - uint32_t r[4]; /** The value for 'r' (low 128 bits of the key). */ - uint32_t s[4]; /** The value for 's' (high 128 bits of the key). */ - uint32_t acc[5]; /** The accumulator number. */ - uint8_t queue[16]; /** The current partial block of data. */ - size_t queue_len; /** The number of bytes stored in 'queue'. */ + uint32_t MBEDTLS_PRIVATE(r)[4]; /** The value for 'r' (low 128 bits of the key). */ + uint32_t MBEDTLS_PRIVATE(s)[4]; /** The value for 's' (high 128 bits of the key). */ + uint32_t MBEDTLS_PRIVATE(acc)[5]; /** The accumulator number. */ + uint8_t MBEDTLS_PRIVATE(queue)[16]; /** The current partial block of data. */ + size_t MBEDTLS_PRIVATE(queue_len); /** The number of bytes stored in 'queue'. */ } mbedtls_poly1305_context; diff --git a/vendor/mbedtls/include/mbedtls/private_access.h b/vendor/mbedtls/include/mbedtls/private_access.h new file mode 100644 index 0000000000..580f3eb446 --- /dev/null +++ b/vendor/mbedtls/include/mbedtls/private_access.h @@ -0,0 +1,20 @@ +/** + * \file private_access.h + * + * \brief Macro wrapper for struct's members. + */ +/* + * Copyright The Mbed TLS Contributors + * SPDX-License-Identifier: Apache-2.0 OR GPL-2.0-or-later + */ + +#ifndef MBEDTLS_PRIVATE_ACCESS_H +#define MBEDTLS_PRIVATE_ACCESS_H + +#ifndef MBEDTLS_ALLOW_PRIVATE_ACCESS +#define MBEDTLS_PRIVATE(member) private_##member +#else +#define MBEDTLS_PRIVATE(member) member +#endif + +#endif /* MBEDTLS_PRIVATE_ACCESS_H */ diff --git a/vendor/mbedtls/include/mbedtls/psa_util.h b/vendor/mbedtls/include/mbedtls/psa_util.h index 9a1a2eae2f..c78cc23333 100644 --- a/vendor/mbedtls/include/mbedtls/psa_util.h +++ b/vendor/mbedtls/include/mbedtls/psa_util.h @@ -2,457 +2,43 @@ * \file psa_util.h * * \brief Utility functions for the use of the PSA Crypto library. - * - * \warning This function is not part of the public API and may - * change at any time. */ /* * Copyright The Mbed TLS Contributors - * SPDX-License-Identifier: Apache-2.0 - * - * Licensed under the Apache License, Version 2.0 (the "License"); you may - * not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT - * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. + * SPDX-License-Identifier: Apache-2.0 OR GPL-2.0-or-later */ #ifndef MBEDTLS_PSA_UTIL_H #define MBEDTLS_PSA_UTIL_H +#include "mbedtls/private_access.h" -#if !defined(MBEDTLS_CONFIG_FILE) -#include "mbedtls/config.h" -#else -#include MBEDTLS_CONFIG_FILE -#endif - -#if defined(MBEDTLS_USE_PSA_CRYPTO) +#include "mbedtls/build_info.h" #include "psa/crypto.h" -#include "mbedtls/ecp.h" -#include "mbedtls/md.h" -#include "mbedtls/pk.h" -#include "mbedtls/oid.h" - -#include - -/* Translations for symmetric crypto. */ - -static inline psa_key_type_t mbedtls_psa_translate_cipher_type( - mbedtls_cipher_type_t cipher) -{ - switch (cipher) { - case MBEDTLS_CIPHER_AES_128_CCM: - case MBEDTLS_CIPHER_AES_192_CCM: - case MBEDTLS_CIPHER_AES_256_CCM: - case MBEDTLS_CIPHER_AES_128_GCM: - case MBEDTLS_CIPHER_AES_192_GCM: - case MBEDTLS_CIPHER_AES_256_GCM: - case MBEDTLS_CIPHER_AES_128_CBC: - case MBEDTLS_CIPHER_AES_192_CBC: - case MBEDTLS_CIPHER_AES_256_CBC: - case MBEDTLS_CIPHER_AES_128_ECB: - case MBEDTLS_CIPHER_AES_192_ECB: - case MBEDTLS_CIPHER_AES_256_ECB: - return PSA_KEY_TYPE_AES; - - /* ARIA not yet supported in PSA. */ - /* case MBEDTLS_CIPHER_ARIA_128_CCM: - case MBEDTLS_CIPHER_ARIA_192_CCM: - case MBEDTLS_CIPHER_ARIA_256_CCM: - case MBEDTLS_CIPHER_ARIA_128_GCM: - case MBEDTLS_CIPHER_ARIA_192_GCM: - case MBEDTLS_CIPHER_ARIA_256_GCM: - case MBEDTLS_CIPHER_ARIA_128_CBC: - case MBEDTLS_CIPHER_ARIA_192_CBC: - case MBEDTLS_CIPHER_ARIA_256_CBC: - return( PSA_KEY_TYPE_ARIA ); */ - - default: - return 0; - } -} - -static inline psa_algorithm_t mbedtls_psa_translate_cipher_mode( - mbedtls_cipher_mode_t mode, size_t taglen) -{ - switch (mode) { - case MBEDTLS_MODE_ECB: - return PSA_ALG_ECB_NO_PADDING; - case MBEDTLS_MODE_GCM: - return PSA_ALG_AEAD_WITH_SHORTENED_TAG(PSA_ALG_GCM, taglen); - case MBEDTLS_MODE_CCM: - return PSA_ALG_AEAD_WITH_SHORTENED_TAG(PSA_ALG_CCM, taglen); - case MBEDTLS_MODE_CBC: - if (taglen == 0) { - return PSA_ALG_CBC_NO_PADDING; - } else { - return 0; - } - default: - return 0; - } -} - -static inline psa_key_usage_t mbedtls_psa_translate_cipher_operation( - mbedtls_operation_t op) -{ - switch (op) { - case MBEDTLS_ENCRYPT: - return PSA_KEY_USAGE_ENCRYPT; - case MBEDTLS_DECRYPT: - return PSA_KEY_USAGE_DECRYPT; - default: - return 0; - } -} - -/* Translations for hashing. */ - -static inline psa_algorithm_t mbedtls_psa_translate_md(mbedtls_md_type_t md_alg) -{ - switch (md_alg) { -#if defined(MBEDTLS_MD2_C) - case MBEDTLS_MD_MD2: - return PSA_ALG_MD2; -#endif -#if defined(MBEDTLS_MD4_C) - case MBEDTLS_MD_MD4: - return PSA_ALG_MD4; -#endif -#if defined(MBEDTLS_MD5_C) - case MBEDTLS_MD_MD5: - return PSA_ALG_MD5; -#endif -#if defined(MBEDTLS_SHA1_C) - case MBEDTLS_MD_SHA1: - return PSA_ALG_SHA_1; -#endif -#if defined(MBEDTLS_SHA256_C) - case MBEDTLS_MD_SHA224: - return PSA_ALG_SHA_224; - case MBEDTLS_MD_SHA256: - return PSA_ALG_SHA_256; -#endif -#if defined(MBEDTLS_SHA512_C) - case MBEDTLS_MD_SHA384: - return PSA_ALG_SHA_384; - case MBEDTLS_MD_SHA512: - return PSA_ALG_SHA_512; -#endif -#if defined(MBEDTLS_RIPEMD160_C) - case MBEDTLS_MD_RIPEMD160: - return PSA_ALG_RIPEMD160; -#endif - case MBEDTLS_MD_NONE: - return 0; - default: - return 0; - } -} +/* ASN1 defines used in the ECDSA conversion functions. + * Note: intentionally not adding MBEDTLS_ASN1_[PARSE|WRITE]_C guards here + * otherwise error codes would be unknown in test_suite_psa_crypto_util.data.*/ +#include -/* Translations for ECC. */ - -static inline int mbedtls_psa_get_ecc_oid_from_id( - psa_ecc_family_t curve, size_t bits, - char const **oid, size_t *oid_len) -{ - switch (curve) { - case PSA_ECC_FAMILY_SECP_R1: - switch (bits) { -#if defined(MBEDTLS_ECP_DP_SECP192R1_ENABLED) - case 192: - *oid = MBEDTLS_OID_EC_GRP_SECP192R1; - *oid_len = MBEDTLS_OID_SIZE(MBEDTLS_OID_EC_GRP_SECP192R1); - return 0; -#endif /* MBEDTLS_ECP_DP_SECP192R1_ENABLED */ -#if defined(MBEDTLS_ECP_DP_SECP224R1_ENABLED) - case 224: - *oid = MBEDTLS_OID_EC_GRP_SECP224R1; - *oid_len = MBEDTLS_OID_SIZE(MBEDTLS_OID_EC_GRP_SECP224R1); - return 0; -#endif /* MBEDTLS_ECP_DP_SECP224R1_ENABLED */ -#if defined(MBEDTLS_ECP_DP_SECP256R1_ENABLED) - case 256: - *oid = MBEDTLS_OID_EC_GRP_SECP256R1; - *oid_len = MBEDTLS_OID_SIZE(MBEDTLS_OID_EC_GRP_SECP256R1); - return 0; -#endif /* MBEDTLS_ECP_DP_SECP256R1_ENABLED */ -#if defined(MBEDTLS_ECP_DP_SECP384R1_ENABLED) - case 384: - *oid = MBEDTLS_OID_EC_GRP_SECP384R1; - *oid_len = MBEDTLS_OID_SIZE(MBEDTLS_OID_EC_GRP_SECP384R1); - return 0; -#endif /* MBEDTLS_ECP_DP_SECP384R1_ENABLED */ -#if defined(MBEDTLS_ECP_DP_SECP521R1_ENABLED) - case 521: - *oid = MBEDTLS_OID_EC_GRP_SECP521R1; - *oid_len = MBEDTLS_OID_SIZE(MBEDTLS_OID_EC_GRP_SECP521R1); - return 0; -#endif /* MBEDTLS_ECP_DP_SECP521R1_ENABLED */ - } - break; - case PSA_ECC_FAMILY_SECP_K1: - switch (bits) { -#if defined(MBEDTLS_ECP_DP_SECP192K1_ENABLED) - case 192: - *oid = MBEDTLS_OID_EC_GRP_SECP192K1; - *oid_len = MBEDTLS_OID_SIZE(MBEDTLS_OID_EC_GRP_SECP192K1); - return 0; -#endif /* MBEDTLS_ECP_DP_SECP192K1_ENABLED */ -#if defined(MBEDTLS_ECP_DP_SECP224K1_ENABLED) - case 224: - *oid = MBEDTLS_OID_EC_GRP_SECP224K1; - *oid_len = MBEDTLS_OID_SIZE(MBEDTLS_OID_EC_GRP_SECP224K1); - return 0; -#endif /* MBEDTLS_ECP_DP_SECP224K1_ENABLED */ -#if defined(MBEDTLS_ECP_DP_SECP256K1_ENABLED) - case 256: - *oid = MBEDTLS_OID_EC_GRP_SECP256K1; - *oid_len = MBEDTLS_OID_SIZE(MBEDTLS_OID_EC_GRP_SECP256K1); - return 0; -#endif /* MBEDTLS_ECP_DP_SECP256K1_ENABLED */ - } - break; - case PSA_ECC_FAMILY_BRAINPOOL_P_R1: - switch (bits) { -#if defined(MBEDTLS_ECP_DP_BP256R1_ENABLED) - case 256: - *oid = MBEDTLS_OID_EC_GRP_BP256R1; - *oid_len = MBEDTLS_OID_SIZE(MBEDTLS_OID_EC_GRP_BP256R1); - return 0; -#endif /* MBEDTLS_ECP_DP_BP256R1_ENABLED */ -#if defined(MBEDTLS_ECP_DP_BP384R1_ENABLED) - case 384: - *oid = MBEDTLS_OID_EC_GRP_BP384R1; - *oid_len = MBEDTLS_OID_SIZE(MBEDTLS_OID_EC_GRP_BP384R1); - return 0; -#endif /* MBEDTLS_ECP_DP_BP384R1_ENABLED */ -#if defined(MBEDTLS_ECP_DP_BP512R1_ENABLED) - case 512: - *oid = MBEDTLS_OID_EC_GRP_BP512R1; - *oid_len = MBEDTLS_OID_SIZE(MBEDTLS_OID_EC_GRP_BP512R1); - return 0; -#endif /* MBEDTLS_ECP_DP_BP512R1_ENABLED */ - } - break; - } - (void) oid; - (void) oid_len; - return -1; -} - -#define MBEDTLS_PSA_MAX_EC_PUBKEY_LENGTH 1 - -#if defined(MBEDTLS_ECP_DP_SECP192R1_ENABLED) -#if MBEDTLS_PSA_MAX_EC_PUBKEY_LENGTH < (2 * ((192 + 7) / 8) + 1) -#undef MBEDTLS_PSA_MAX_EC_PUBKEY_LENGTH -#define MBEDTLS_PSA_MAX_EC_PUBKEY_LENGTH (2 * ((192 + 7) / 8) + 1) -#endif -#endif /* MBEDTLS_ECP_DP_SECP192R1_ENABLED */ - -#if defined(MBEDTLS_ECP_DP_SECP224R1_ENABLED) -#if MBEDTLS_PSA_MAX_EC_PUBKEY_LENGTH < (2 * ((224 + 7) / 8) + 1) -#undef MBEDTLS_PSA_MAX_EC_PUBKEY_LENGTH -#define MBEDTLS_PSA_MAX_EC_PUBKEY_LENGTH (2 * ((224 + 7) / 8) + 1) -#endif -#endif /* MBEDTLS_ECP_DP_SECP224R1_ENABLED */ - -#if defined(MBEDTLS_ECP_DP_SECP256R1_ENABLED) -#if MBEDTLS_PSA_MAX_EC_PUBKEY_LENGTH < (2 * ((256 + 7) / 8) + 1) -#undef MBEDTLS_PSA_MAX_EC_PUBKEY_LENGTH -#define MBEDTLS_PSA_MAX_EC_PUBKEY_LENGTH (2 * ((256 + 7) / 8) + 1) -#endif -#endif /* MBEDTLS_ECP_DP_SECP256R1_ENABLED */ - -#if defined(MBEDTLS_ECP_DP_SECP384R1_ENABLED) -#if MBEDTLS_PSA_MAX_EC_PUBKEY_LENGTH < (2 * ((384 + 7) / 8) + 1) -#undef MBEDTLS_PSA_MAX_EC_PUBKEY_LENGTH -#define MBEDTLS_PSA_MAX_EC_PUBKEY_LENGTH (2 * ((384 + 7) / 8) + 1) -#endif -#endif /* MBEDTLS_ECP_DP_SECP384R1_ENABLED */ - -#if defined(MBEDTLS_ECP_DP_SECP521R1_ENABLED) -#if MBEDTLS_PSA_MAX_EC_PUBKEY_LENGTH < (2 * ((521 + 7) / 8) + 1) -#undef MBEDTLS_PSA_MAX_EC_PUBKEY_LENGTH -#define MBEDTLS_PSA_MAX_EC_PUBKEY_LENGTH (2 * ((521 + 7) / 8) + 1) -#endif -#endif /* MBEDTLS_ECP_DP_SECP521R1_ENABLED */ - -#if defined(MBEDTLS_ECP_DP_SECP192K1_ENABLED) -#if MBEDTLS_PSA_MAX_EC_PUBKEY_LENGTH < (2 * ((192 + 7) / 8) + 1) -#undef MBEDTLS_PSA_MAX_EC_PUBKEY_LENGTH -#define MBEDTLS_PSA_MAX_EC_PUBKEY_LENGTH (2 * ((192 + 7) / 8) + 1) -#endif -#endif /* MBEDTLS_ECP_DP_SECP192K1_ENABLED */ - -#if defined(MBEDTLS_ECP_DP_SECP224K1_ENABLED) -#if MBEDTLS_PSA_MAX_EC_PUBKEY_LENGTH < (2 * ((224 + 7) / 8) + 1) -#undef MBEDTLS_PSA_MAX_EC_PUBKEY_LENGTH -#define MBEDTLS_PSA_MAX_EC_PUBKEY_LENGTH (2 * ((224 + 7) / 8) + 1) -#endif -#endif /* MBEDTLS_ECP_DP_SECP224K1_ENABLED */ - -#if defined(MBEDTLS_ECP_DP_SECP256K1_ENABLED) -#if MBEDTLS_PSA_MAX_EC_PUBKEY_LENGTH < (2 * ((256 + 7) / 8) + 1) -#undef MBEDTLS_PSA_MAX_EC_PUBKEY_LENGTH -#define MBEDTLS_PSA_MAX_EC_PUBKEY_LENGTH (2 * ((256 + 7) / 8) + 1) -#endif -#endif /* MBEDTLS_ECP_DP_SECP256K1_ENABLED */ - -#if defined(MBEDTLS_ECP_DP_BP256R1_ENABLED) -#if MBEDTLS_PSA_MAX_EC_PUBKEY_LENGTH < (2 * ((256 + 7) / 8) + 1) -#undef MBEDTLS_PSA_MAX_EC_PUBKEY_LENGTH -#define MBEDTLS_PSA_MAX_EC_PUBKEY_LENGTH (2 * ((256 + 7) / 8) + 1) -#endif -#endif /* MBEDTLS_ECP_DP_BP256R1_ENABLED */ - -#if defined(MBEDTLS_ECP_DP_BP384R1_ENABLED) -#if MBEDTLS_PSA_MAX_EC_PUBKEY_LENGTH < (2 * ((384 + 7) / 8) + 1) -#undef MBEDTLS_PSA_MAX_EC_PUBKEY_LENGTH -#define MBEDTLS_PSA_MAX_EC_PUBKEY_LENGTH (2 * ((384 + 7) / 8) + 1) -#endif -#endif /* MBEDTLS_ECP_DP_BP384R1_ENABLED */ - -#if defined(MBEDTLS_ECP_DP_BP512R1_ENABLED) -#if MBEDTLS_PSA_MAX_EC_PUBKEY_LENGTH < (2 * ((512 + 7) / 8) + 1) -#undef MBEDTLS_PSA_MAX_EC_PUBKEY_LENGTH -#define MBEDTLS_PSA_MAX_EC_PUBKEY_LENGTH (2 * ((512 + 7) / 8) + 1) -#endif -#endif /* MBEDTLS_ECP_DP_BP512R1_ENABLED */ - - -/* Translations for PK layer */ - -static inline int mbedtls_psa_err_translate_pk(psa_status_t status) -{ - switch (status) { - case PSA_SUCCESS: - return 0; - case PSA_ERROR_NOT_SUPPORTED: - return MBEDTLS_ERR_PK_FEATURE_UNAVAILABLE; - case PSA_ERROR_INSUFFICIENT_MEMORY: - return MBEDTLS_ERR_PK_ALLOC_FAILED; - case PSA_ERROR_INSUFFICIENT_ENTROPY: - return MBEDTLS_ERR_ECP_RANDOM_FAILED; - case PSA_ERROR_BAD_STATE: - return MBEDTLS_ERR_PK_BAD_INPUT_DATA; - /* All other failures */ - case PSA_ERROR_COMMUNICATION_FAILURE: - case PSA_ERROR_HARDWARE_FAILURE: - case PSA_ERROR_CORRUPTION_DETECTED: - return MBEDTLS_ERR_PK_HW_ACCEL_FAILED; - default: /* We return the same as for the 'other failures', - * but list them separately nonetheless to indicate - * which failure conditions we have considered. */ - return MBEDTLS_ERR_PK_HW_ACCEL_FAILED; - } -} - -/* Translations for ECC */ - -/* This function transforms an ECC group identifier from - * https://www.iana.org/assignments/tls-parameters/tls-parameters.xhtml#tls-parameters-8 - * into a PSA ECC group identifier. */ -#if defined(MBEDTLS_ECP_C) -static inline psa_key_type_t mbedtls_psa_parse_tls_ecc_group( - uint16_t tls_ecc_grp_reg_id, size_t *bits) -{ - const mbedtls_ecp_curve_info *curve_info = - mbedtls_ecp_curve_info_from_tls_id(tls_ecc_grp_reg_id); - if (curve_info == NULL) { - return 0; - } - return PSA_KEY_TYPE_ECC_KEY_PAIR( - mbedtls_ecc_group_to_psa(curve_info->grp_id, bits)); -} -#endif /* MBEDTLS_ECP_C */ - -/* This function takes a buffer holding an EC public key - * exported through psa_export_public_key(), and converts - * it into an ECPoint structure to be put into a ClientKeyExchange - * message in an ECDHE exchange. - * - * Both the present and the foreseeable future format of EC public keys - * used by PSA have the ECPoint structure contained in the exported key - * as a subbuffer, and the function merely selects this subbuffer instead - * of making a copy. - */ -static inline int mbedtls_psa_tls_psa_ec_to_ecpoint(unsigned char *src, - size_t srclen, - unsigned char **dst, - size_t *dstlen) -{ - *dst = src; - *dstlen = srclen; - return 0; -} - -/* This function takes a buffer holding an ECPoint structure - * (as contained in a TLS ServerKeyExchange message for ECDHE - * exchanges) and converts it into a format that the PSA key - * agreement API understands. - */ -static inline int mbedtls_psa_tls_ecpoint_to_psa_ec(unsigned char const *src, - size_t srclen, - unsigned char *dst, - size_t dstlen, - size_t *olen) -{ - if (srclen > dstlen) { - return MBEDTLS_ERR_ECP_BUFFER_TOO_SMALL; - } - - memcpy(dst, src, srclen); - *olen = srclen; - return 0; -} - -#endif /* MBEDTLS_USE_PSA_CRYPTO */ - -/* Expose whatever RNG the PSA subsystem uses to applications using the - * mbedtls_xxx API. The declarations and definitions here need to be - * consistent with the implementation in library/psa_crypto_random_impl.h. - * See that file for implementation documentation. */ -#if defined(MBEDTLS_PSA_CRYPTO_C) - -/* The type of a `f_rng` random generator function that many library functions - * take. - * - * This type name is not part of the Mbed TLS stable API. It may be renamed - * or moved without warning. - */ -typedef int mbedtls_f_rng_t(void *p_rng, unsigned char *output, size_t output_size); - -#if defined(MBEDTLS_PSA_CRYPTO_EXTERNAL_RNG) +#if defined(MBEDTLS_PSA_CRYPTO_CLIENT) /** The random generator function for the PSA subsystem. * * This function is suitable as the `f_rng` random generator function - * parameter of many `mbedtls_xxx` functions. Use #MBEDTLS_PSA_RANDOM_STATE - * to obtain the \p p_rng parameter. + * parameter of many `mbedtls_xxx` functions. * * The implementation of this function depends on the configuration of the * library. * - * \note Depending on the configuration, this may be a function or - * a pointer to a function. - * * \note This function may only be used if the PSA crypto subsystem is active. * This means that you must call psa_crypto_init() before any call to * this function, and you must not call this function after calling * mbedtls_psa_crypto_free(). * - * \param p_rng The random generator context. This must be - * #MBEDTLS_PSA_RANDOM_STATE. No other state is - * supported. + * \param p_rng This parameter is only kept for backward compatibility + * reasons with legacy `f_rng` functions and it's ignored. + * Set to #MBEDTLS_PSA_RANDOM_STATE or NULL. * \param output The buffer to fill. It must have room for * \c output_size bytes. * \param output_size The number of bytes to write to \p output. @@ -474,33 +60,129 @@ int mbedtls_psa_get_random(void *p_rng, /** The random generator state for the PSA subsystem. * - * This macro expands to an expression which is suitable as the `p_rng` - * random generator state parameter of many `mbedtls_xxx` functions. - * It must be used in combination with the random generator function - * mbedtls_psa_get_random(). + * This macro always expands to NULL because the `p_rng` parameter is unused + * in mbedtls_psa_get_random(), but it's kept for interface's backward + * compatibility. + */ +#define MBEDTLS_PSA_RANDOM_STATE NULL + +/** \defgroup psa_tls_helpers TLS helper functions + * @{ + */ +#if defined(PSA_WANT_KEY_TYPE_ECC_PUBLIC_KEY) +#include + +/** Convert an ECC curve identifier from the Mbed TLS encoding to PSA. + * + * \param grpid An Mbed TLS elliptic curve identifier + * (`MBEDTLS_ECP_DP_xxx`). + * \param[out] bits On success the bit size of the curve; 0 on failure. + * + * \return If the curve is supported in the PSA API, this function + * returns the proper PSA curve identifier + * (`PSA_ECC_FAMILY_xxx`). This holds even if the curve is + * not supported by the ECP module. + * \return \c 0 if the curve is not supported in the PSA API. + */ +psa_ecc_family_t mbedtls_ecc_group_to_psa(mbedtls_ecp_group_id grpid, + size_t *bits); + +/** Convert an ECC curve identifier from the PSA encoding to Mbed TLS. + * + * \param family A PSA elliptic curve family identifier + * (`PSA_ECC_FAMILY_xxx`). + * \param bits The bit-length of a private key on \p curve. * - * The implementation of this macro depends on the configuration of the - * library. Do not make any assumption on its nature. + * \return If the curve is supported in the PSA API, this function + * returns the corresponding Mbed TLS elliptic curve + * identifier (`MBEDTLS_ECP_DP_xxx`). + * \return #MBEDTLS_ECP_DP_NONE if the combination of \c curve + * and \p bits is not supported. */ -#define MBEDTLS_PSA_RANDOM_STATE NULL +mbedtls_ecp_group_id mbedtls_ecc_group_from_psa(psa_ecc_family_t family, + size_t bits); +#endif /* PSA_WANT_KEY_TYPE_ECC_PUBLIC_KEY */ -#else /* !defined(MBEDTLS_PSA_CRYPTO_EXTERNAL_RNG) */ +/** + * \brief This function returns the PSA algorithm identifier + * associated with the given digest type. + * + * \param md_type The type of digest to search for. Must not be NONE. + * + * \warning If \p md_type is \c MBEDTLS_MD_NONE, this function will + * not return \c PSA_ALG_NONE, but an invalid algorithm. + * + * \warning This function does not check if the algorithm is + * supported, it always returns the corresponding identifier. + * + * \return The PSA algorithm identifier associated with \p md_type, + * regardless of whether it is supported or not. + */ +static inline psa_algorithm_t mbedtls_md_psa_alg_from_type(mbedtls_md_type_t md_type) +{ + return PSA_ALG_CATEGORY_HASH | (psa_algorithm_t) md_type; +} -#if defined(MBEDTLS_CTR_DRBG_C) -#include "mbedtls/ctr_drbg.h" -typedef mbedtls_ctr_drbg_context mbedtls_psa_drbg_context_t; -static mbedtls_f_rng_t *const mbedtls_psa_get_random = mbedtls_ctr_drbg_random; -#elif defined(MBEDTLS_HMAC_DRBG_C) -#include "mbedtls/hmac_drbg.h" -typedef mbedtls_hmac_drbg_context mbedtls_psa_drbg_context_t; -static mbedtls_f_rng_t *const mbedtls_psa_get_random = mbedtls_hmac_drbg_random; -#endif -extern mbedtls_psa_drbg_context_t *const mbedtls_psa_random_state; +/** + * \brief This function returns the given digest type + * associated with the PSA algorithm identifier. + * + * \param psa_alg The PSA algorithm identifier to search for. + * + * \warning This function does not check if the algorithm is + * supported, it always returns the corresponding identifier. + * + * \return The MD type associated with \p psa_alg, + * regardless of whether it is supported or not. + */ +static inline mbedtls_md_type_t mbedtls_md_type_from_psa_alg(psa_algorithm_t psa_alg) +{ + return (mbedtls_md_type_t) (psa_alg & PSA_ALG_HASH_MASK); +} +#endif /* MBEDTLS_PSA_CRYPTO_CLIENT */ + +#if defined(MBEDTLS_PSA_UTIL_HAVE_ECDSA) -#define MBEDTLS_PSA_RANDOM_STATE mbedtls_psa_random_state +/** Convert an ECDSA signature from raw format to DER ASN.1 format. + * + * \param bits Size of each coordinate in bits. + * \param raw Buffer that contains the signature in raw format. + * \param raw_len Length of \p raw in bytes. This must be + * PSA_BITS_TO_BYTES(bits) bytes. + * \param[out] der Buffer that will be filled with the converted DER + * output. It can overlap with raw buffer. + * \param der_size Size of \p der in bytes. It is enough if \p der_size + * is at least the size of the actual output. (The size + * of the output can vary depending on the presence of + * leading zeros in the data.) You can use + * #MBEDTLS_ECDSA_MAX_SIG_LEN(\p bits) to determine a + * size that is large enough for all signatures for a + * given value of \p bits. + * \param[out] der_len On success it contains the amount of valid data + * (in bytes) written to \p der. It's undefined + * in case of failure. + */ +int mbedtls_ecdsa_raw_to_der(size_t bits, const unsigned char *raw, size_t raw_len, + unsigned char *der, size_t der_size, size_t *der_len); + +/** Convert an ECDSA signature from DER ASN.1 format to raw format. + * + * \param bits Size of each coordinate in bits. + * \param der Buffer that contains the signature in DER format. + * \param der_len Size of \p der in bytes. + * \param[out] raw Buffer that will be filled with the converted raw + * signature. It can overlap with der buffer. + * \param raw_size Size of \p raw in bytes. Must be at least + * 2 * PSA_BITS_TO_BYTES(bits) bytes. + * \param[out] raw_len On success it is updated with the amount of valid + * data (in bytes) written to \p raw. It's undefined + * in case of failure. + */ +int mbedtls_ecdsa_der_to_raw(size_t bits, const unsigned char *der, size_t der_len, + unsigned char *raw, size_t raw_size, size_t *raw_len); -#endif /* !defined(MBEDTLS_PSA_CRYPTO_EXTERNAL_RNG) */ +#endif /* MBEDTLS_PSA_UTIL_HAVE_ECDSA */ -#endif /* MBEDTLS_PSA_CRYPTO_C */ +/**@}*/ #endif /* MBEDTLS_PSA_UTIL_H */ diff --git a/vendor/mbedtls/include/mbedtls/ripemd160.h b/vendor/mbedtls/include/mbedtls/ripemd160.h index 6d9a1a2a32..279f92b512 100644 --- a/vendor/mbedtls/include/mbedtls/ripemd160.h +++ b/vendor/mbedtls/include/mbedtls/ripemd160.h @@ -5,37 +5,17 @@ */ /* * Copyright The Mbed TLS Contributors - * SPDX-License-Identifier: Apache-2.0 - * - * Licensed under the Apache License, Version 2.0 (the "License"); you may - * not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT - * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. + * SPDX-License-Identifier: Apache-2.0 OR GPL-2.0-or-later */ #ifndef MBEDTLS_RIPEMD160_H #define MBEDTLS_RIPEMD160_H +#include "mbedtls/private_access.h" -#if !defined(MBEDTLS_CONFIG_FILE) -#include "mbedtls/config.h" -#else -#include MBEDTLS_CONFIG_FILE -#endif +#include "mbedtls/build_info.h" #include #include -/* MBEDTLS_ERR_RIPEMD160_HW_ACCEL_FAILED is deprecated and should not be used. - */ -/** RIPEMD160 hardware accelerator failed */ -#define MBEDTLS_ERR_RIPEMD160_HW_ACCEL_FAILED -0x0031 - #ifdef __cplusplus extern "C" { #endif @@ -48,9 +28,9 @@ extern "C" { * \brief RIPEMD-160 context structure */ typedef struct mbedtls_ripemd160_context { - uint32_t total[2]; /*!< number of bytes processed */ - uint32_t state[5]; /*!< intermediate digest state */ - unsigned char buffer[64]; /*!< data block being processed */ + uint32_t MBEDTLS_PRIVATE(total)[2]; /*!< number of bytes processed */ + uint32_t MBEDTLS_PRIVATE(state)[5]; /*!< intermediate digest state */ + unsigned char MBEDTLS_PRIVATE(buffer)[64]; /*!< data block being processed */ } mbedtls_ripemd160_context; @@ -88,7 +68,7 @@ void mbedtls_ripemd160_clone(mbedtls_ripemd160_context *dst, * * \return 0 if successful */ -int mbedtls_ripemd160_starts_ret(mbedtls_ripemd160_context *ctx); +int mbedtls_ripemd160_starts(mbedtls_ripemd160_context *ctx); /** * \brief RIPEMD-160 process buffer @@ -99,9 +79,9 @@ int mbedtls_ripemd160_starts_ret(mbedtls_ripemd160_context *ctx); * * \return 0 if successful */ -int mbedtls_ripemd160_update_ret(mbedtls_ripemd160_context *ctx, - const unsigned char *input, - size_t ilen); +int mbedtls_ripemd160_update(mbedtls_ripemd160_context *ctx, + const unsigned char *input, + size_t ilen); /** * \brief RIPEMD-160 final digest @@ -111,8 +91,8 @@ int mbedtls_ripemd160_update_ret(mbedtls_ripemd160_context *ctx, * * \return 0 if successful */ -int mbedtls_ripemd160_finish_ret(mbedtls_ripemd160_context *ctx, - unsigned char output[20]); +int mbedtls_ripemd160_finish(mbedtls_ripemd160_context *ctx, + unsigned char output[20]); /** * \brief RIPEMD-160 process data block (internal use only) @@ -125,63 +105,6 @@ int mbedtls_ripemd160_finish_ret(mbedtls_ripemd160_context *ctx, int mbedtls_internal_ripemd160_process(mbedtls_ripemd160_context *ctx, const unsigned char data[64]); -#if !defined(MBEDTLS_DEPRECATED_REMOVED) -#if defined(MBEDTLS_DEPRECATED_WARNING) -#define MBEDTLS_DEPRECATED __attribute__((deprecated)) -#else -#define MBEDTLS_DEPRECATED -#endif -/** - * \brief RIPEMD-160 context setup - * - * \deprecated Superseded by mbedtls_ripemd160_starts_ret() in 2.7.0 - * - * \param ctx context to be initialized - */ -MBEDTLS_DEPRECATED void mbedtls_ripemd160_starts( - mbedtls_ripemd160_context *ctx); - -/** - * \brief RIPEMD-160 process buffer - * - * \deprecated Superseded by mbedtls_ripemd160_update_ret() in 2.7.0 - * - * \param ctx RIPEMD-160 context - * \param input buffer holding the data - * \param ilen length of the input data - */ -MBEDTLS_DEPRECATED void mbedtls_ripemd160_update( - mbedtls_ripemd160_context *ctx, - const unsigned char *input, - size_t ilen); - -/** - * \brief RIPEMD-160 final digest - * - * \deprecated Superseded by mbedtls_ripemd160_finish_ret() in 2.7.0 - * - * \param ctx RIPEMD-160 context - * \param output RIPEMD-160 checksum result - */ -MBEDTLS_DEPRECATED void mbedtls_ripemd160_finish( - mbedtls_ripemd160_context *ctx, - unsigned char output[20]); - -/** - * \brief RIPEMD-160 process data block (internal use only) - * - * \deprecated Superseded by mbedtls_internal_ripemd160_process() in 2.7.0 - * - * \param ctx RIPEMD-160 context - * \param data buffer holding one block of data - */ -MBEDTLS_DEPRECATED void mbedtls_ripemd160_process( - mbedtls_ripemd160_context *ctx, - const unsigned char data[64]); - -#undef MBEDTLS_DEPRECATED -#endif /* !MBEDTLS_DEPRECATED_REMOVED */ - /** * \brief Output = RIPEMD-160( input buffer ) * @@ -191,31 +114,9 @@ MBEDTLS_DEPRECATED void mbedtls_ripemd160_process( * * \return 0 if successful */ -int mbedtls_ripemd160_ret(const unsigned char *input, - size_t ilen, - unsigned char output[20]); - -#if !defined(MBEDTLS_DEPRECATED_REMOVED) -#if defined(MBEDTLS_DEPRECATED_WARNING) -#define MBEDTLS_DEPRECATED __attribute__((deprecated)) -#else -#define MBEDTLS_DEPRECATED -#endif -/** - * \brief Output = RIPEMD-160( input buffer ) - * - * \deprecated Superseded by mbedtls_ripemd160_ret() in 2.7.0 - * - * \param input buffer holding the data - * \param ilen length of the input data - * \param output RIPEMD-160 checksum result - */ -MBEDTLS_DEPRECATED void mbedtls_ripemd160(const unsigned char *input, - size_t ilen, - unsigned char output[20]); - -#undef MBEDTLS_DEPRECATED -#endif /* !MBEDTLS_DEPRECATED_REMOVED */ +int mbedtls_ripemd160(const unsigned char *input, + size_t ilen, + unsigned char output[20]); #if defined(MBEDTLS_SELF_TEST) diff --git a/vendor/mbedtls/include/mbedtls/rsa.h b/vendor/mbedtls/include/mbedtls/rsa.h index 37f07c0766..c1e76b3927 100644 --- a/vendor/mbedtls/include/mbedtls/rsa.h +++ b/vendor/mbedtls/include/mbedtls/rsa.h @@ -11,28 +11,13 @@ */ /* * Copyright The Mbed TLS Contributors - * SPDX-License-Identifier: Apache-2.0 - * - * Licensed under the Apache License, Version 2.0 (the "License"); you may - * not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT - * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. + * SPDX-License-Identifier: Apache-2.0 OR GPL-2.0-or-later */ #ifndef MBEDTLS_RSA_H #define MBEDTLS_RSA_H +#include "mbedtls/private_access.h" -#if !defined(MBEDTLS_CONFIG_FILE) -#include "mbedtls/config.h" -#else -#include MBEDTLS_CONFIG_FILE -#endif +#include "mbedtls/build_info.h" #include "mbedtls/bignum.h" #include "mbedtls/md.h" @@ -63,20 +48,9 @@ /** The random generator failed to generate non-zeros. */ #define MBEDTLS_ERR_RSA_RNG_FAILED -0x4480 -/* MBEDTLS_ERR_RSA_UNSUPPORTED_OPERATION is deprecated and should not be used. - */ -/** The implementation does not offer the requested operation, for example, because of security violations or lack of functionality. */ -#define MBEDTLS_ERR_RSA_UNSUPPORTED_OPERATION -0x4500 - -/* MBEDTLS_ERR_RSA_HW_ACCEL_FAILED is deprecated and should not be used. */ -/** RSA hardware accelerator failed. */ -#define MBEDTLS_ERR_RSA_HW_ACCEL_FAILED -0x4580 - /* * RSA constants */ -#define MBEDTLS_RSA_PUBLIC 0 /**< Request private key operation. */ -#define MBEDTLS_RSA_PRIVATE 1 /**< Request public key operation. */ #define MBEDTLS_RSA_PKCS_V15 0 /**< Use PKCS#1 v1.5 encoding. */ #define MBEDTLS_RSA_PKCS_V21 1 /**< Use PKCS#1 v2.1 encoding. */ @@ -99,49 +73,51 @@ extern "C" { // Regular implementation // +#if !defined(MBEDTLS_RSA_GEN_KEY_MIN_BITS) +#define MBEDTLS_RSA_GEN_KEY_MIN_BITS 1024 +#elif MBEDTLS_RSA_GEN_KEY_MIN_BITS < 128 +#error "MBEDTLS_RSA_GEN_KEY_MIN_BITS must be at least 128 bits" +#endif + /** * \brief The RSA context structure. - * - * \note Direct manipulation of the members of this structure - * is deprecated. All manipulation should instead be done through - * the public interface functions. */ typedef struct mbedtls_rsa_context { - int ver; /*!< Reserved for internal purposes. - * Do not set this field in application - * code. Its meaning might change without - * notice. */ - size_t len; /*!< The size of \p N in Bytes. */ + int MBEDTLS_PRIVATE(ver); /*!< Reserved for internal purposes. + * Do not set this field in application + * code. Its meaning might change without + * notice. */ + size_t MBEDTLS_PRIVATE(len); /*!< The size of \p N in Bytes. */ - mbedtls_mpi N; /*!< The public modulus. */ - mbedtls_mpi E; /*!< The public exponent. */ + mbedtls_mpi MBEDTLS_PRIVATE(N); /*!< The public modulus. */ + mbedtls_mpi MBEDTLS_PRIVATE(E); /*!< The public exponent. */ - mbedtls_mpi D; /*!< The private exponent. */ - mbedtls_mpi P; /*!< The first prime factor. */ - mbedtls_mpi Q; /*!< The second prime factor. */ + mbedtls_mpi MBEDTLS_PRIVATE(D); /*!< The private exponent. */ + mbedtls_mpi MBEDTLS_PRIVATE(P); /*!< The first prime factor. */ + mbedtls_mpi MBEDTLS_PRIVATE(Q); /*!< The second prime factor. */ - mbedtls_mpi DP; /*!< D % (P - 1). */ - mbedtls_mpi DQ; /*!< D % (Q - 1). */ - mbedtls_mpi QP; /*!< 1 / (Q % P). */ + mbedtls_mpi MBEDTLS_PRIVATE(DP); /*!< D % (P - 1). */ + mbedtls_mpi MBEDTLS_PRIVATE(DQ); /*!< D % (Q - 1). */ + mbedtls_mpi MBEDTLS_PRIVATE(QP); /*!< 1 / (Q % P). */ - mbedtls_mpi RN; /*!< cached R^2 mod N. */ + mbedtls_mpi MBEDTLS_PRIVATE(RN); /*!< cached R^2 mod N. */ - mbedtls_mpi RP; /*!< cached R^2 mod P. */ - mbedtls_mpi RQ; /*!< cached R^2 mod Q. */ + mbedtls_mpi MBEDTLS_PRIVATE(RP); /*!< cached R^2 mod P. */ + mbedtls_mpi MBEDTLS_PRIVATE(RQ); /*!< cached R^2 mod Q. */ - mbedtls_mpi Vi; /*!< The cached blinding value. */ - mbedtls_mpi Vf; /*!< The cached un-blinding value. */ + mbedtls_mpi MBEDTLS_PRIVATE(Vi); /*!< The cached blinding value. */ + mbedtls_mpi MBEDTLS_PRIVATE(Vf); /*!< The cached un-blinding value. */ - int padding; /*!< Selects padding mode: - #MBEDTLS_RSA_PKCS_V15 for 1.5 padding and - #MBEDTLS_RSA_PKCS_V21 for OAEP or PSS. */ - int hash_id; /*!< Hash identifier of mbedtls_md_type_t type, - as specified in md.h for use in the MGF - mask generating function used in the - EME-OAEP and EMSA-PSS encodings. */ + int MBEDTLS_PRIVATE(padding); /*!< Selects padding mode: + #MBEDTLS_RSA_PKCS_V15 for 1.5 padding and + #MBEDTLS_RSA_PKCS_V21 for OAEP or PSS. */ + int MBEDTLS_PRIVATE(hash_id); /*!< Hash identifier of mbedtls_md_type_t type, + as specified in md.h for use in the MGF + mask generating function used in the + EME-OAEP and EMSA-PSS encodings. */ #if defined(MBEDTLS_THREADING_C) /* Invariant: the mutex is initialized iff ver != 0. */ - mbedtls_threading_mutex_t mutex; /*!< Thread-safety mutex. */ + mbedtls_threading_mutex_t MBEDTLS_PRIVATE(mutex); /*!< Thread-safety mutex. */ #endif } mbedtls_rsa_context; @@ -153,33 +129,73 @@ mbedtls_rsa_context; /** * \brief This function initializes an RSA context. * + * \note This function initializes the padding and the hash + * identifier to respectively #MBEDTLS_RSA_PKCS_V15 and + * #MBEDTLS_MD_NONE. See mbedtls_rsa_set_padding() for more + * information about those parameters. + * + * \param ctx The RSA context to initialize. This must not be \c NULL. + */ +void mbedtls_rsa_init(mbedtls_rsa_context *ctx); + +/** + * \brief This function sets padding for an already initialized RSA + * context. + * * \note Set padding to #MBEDTLS_RSA_PKCS_V21 for the RSAES-OAEP * encryption scheme and the RSASSA-PSS signature scheme. * * \note The \p hash_id parameter is ignored when using * #MBEDTLS_RSA_PKCS_V15 padding. * - * \note The choice of padding mode is strictly enforced for private key - * operations, since there might be security concerns in + * \note The choice of padding mode is strictly enforced for private + * key operations, since there might be security concerns in * mixing padding modes. For public key operations it is * a default value, which can be overridden by calling specific - * \c rsa_rsaes_xxx or \c rsa_rsassa_xxx functions. + * \c mbedtls_rsa_rsaes_xxx or \c mbedtls_rsa_rsassa_xxx + * functions. * * \note The hash selected in \p hash_id is always used for OEAP * encryption. For PSS signatures, it is always used for * making signatures, but can be overridden for verifying them. * If set to #MBEDTLS_MD_NONE, it is always overridden. * - * \param ctx The RSA context to initialize. This must not be \c NULL. + * \param ctx The initialized RSA context to be configured. * \param padding The padding mode to use. This must be either * #MBEDTLS_RSA_PKCS_V15 or #MBEDTLS_RSA_PKCS_V21. - * \param hash_id The hash identifier of ::mbedtls_md_type_t type, if - * \p padding is #MBEDTLS_RSA_PKCS_V21. It is unused - * otherwise. + * \param hash_id The hash identifier for PSS or OAEP, if \p padding is + * #MBEDTLS_RSA_PKCS_V21. #MBEDTLS_MD_NONE is accepted by this + * function but may be not suitable for some operations. + * Ignored if \p padding is #MBEDTLS_RSA_PKCS_V15. + * + * \return \c 0 on success. + * \return #MBEDTLS_ERR_RSA_INVALID_PADDING failure: + * \p padding or \p hash_id is invalid. */ -void mbedtls_rsa_init(mbedtls_rsa_context *ctx, - int padding, - int hash_id); +int mbedtls_rsa_set_padding(mbedtls_rsa_context *ctx, int padding, + mbedtls_md_type_t hash_id); + +/** + * \brief This function retrieves padding mode of initialized + * RSA context. + * + * \param ctx The initialized RSA context. + * + * \return RSA padding mode. + * + */ +int mbedtls_rsa_get_padding_mode(const mbedtls_rsa_context *ctx); + +/** + * \brief This function retrieves hash identifier of mbedtls_md_type_t + * type. + * + * \param ctx The initialized RSA context. + * + * \return Hash identifier of mbedtls_md_type_t type. + * + */ +int mbedtls_rsa_get_md_alg(const mbedtls_rsa_context *ctx); /** * \brief This function imports a set of core parameters into an @@ -238,7 +254,7 @@ int mbedtls_rsa_import(mbedtls_rsa_context *ctx, * \param N The RSA modulus. This may be \c NULL. * \param N_len The Byte length of \p N; it is ignored if \p N == NULL. * \param P The first prime factor of \p N. This may be \c NULL. - * \param P_len The Byte length of \p P; it ns ignored if \p P == NULL. + * \param P_len The Byte length of \p P; it is ignored if \p P == NULL. * \param Q The second prime factor of \p N. This may be \c NULL. * \param Q_len The Byte length of \p Q; it is ignored if \p Q == NULL. * \param D The private exponent. This may be \c NULL. @@ -411,16 +427,14 @@ int mbedtls_rsa_export_crt(const mbedtls_rsa_context *ctx, mbedtls_mpi *DP, mbedtls_mpi *DQ, mbedtls_mpi *QP); /** - * \brief This function sets padding for an already initialized RSA - * context. See mbedtls_rsa_init() for details. + * \brief This function retrieves the length of the RSA modulus in bits. + * + * \param ctx The initialized RSA context. + * + * \return The length of the RSA modulus in bits. * - * \param ctx The initialized RSA context to be configured. - * \param padding The padding mode to use. This must be either - * #MBEDTLS_RSA_PKCS_V15 or #MBEDTLS_RSA_PKCS_V21. - * \param hash_id The #MBEDTLS_RSA_PKCS_V21 hash identifier. */ -void mbedtls_rsa_set_padding(mbedtls_rsa_context *ctx, int padding, - int hash_id); +size_t mbedtls_rsa_get_bitlen(const mbedtls_rsa_context *ctx); /** * \brief This function retrieves the length of RSA modulus in Bytes. @@ -440,7 +454,7 @@ size_t mbedtls_rsa_get_len(const mbedtls_rsa_context *ctx); * * \param ctx The initialized RSA context used to hold the key. * \param f_rng The RNG function to be used for key generation. - * This must not be \c NULL. + * This is mandatory and must not be \c NULL. * \param p_rng The RNG context to be passed to \p f_rng. * This may be \c NULL if \p f_rng doesn't need a context. * \param nbits The size of the public key in bits. @@ -561,11 +575,9 @@ int mbedtls_rsa_public(mbedtls_rsa_context *ctx, * of a PRNG. * * \param ctx The initialized RSA context to use. - * \param f_rng The RNG function, used for blinding. It is discouraged - * and deprecated to pass \c NULL here, in which case - * blinding will be omitted. + * \param f_rng The RNG function, used for blinding. It is mandatory. * \param p_rng The RNG context to pass to \p f_rng. This may be \c NULL - * if \p f_rng is \c NULL or if \p f_rng doesn't need a context. + * if \p f_rng doesn't need a context. * \param input The input buffer. This must be a readable buffer * of length \c ctx->len Bytes. For example, \c 256 Bytes * for an 2048-bit RSA modulus. @@ -588,29 +600,13 @@ int mbedtls_rsa_private(mbedtls_rsa_context *ctx, * operation. * * It is the generic wrapper for performing a PKCS#1 encryption - * operation using the \p mode from the context. - * - * \deprecated It is deprecated and discouraged to call this function - * in #MBEDTLS_RSA_PRIVATE mode. Future versions of the library - * are likely to remove the \p mode argument and have it - * implicitly set to #MBEDTLS_RSA_PUBLIC. - * - * \note Alternative implementations of RSA need not support - * mode being set to #MBEDTLS_RSA_PRIVATE and might instead - * return #MBEDTLS_ERR_PLATFORM_FEATURE_UNSUPPORTED. + * operation. * * \param ctx The initialized RSA context to use. - * \param f_rng The RNG to use. It is mandatory for PKCS#1 v2.1 padding - * encoding, and for PKCS#1 v1.5 padding encoding when used - * with \p mode set to #MBEDTLS_RSA_PUBLIC. For PKCS#1 v1.5 - * padding encoding and \p mode set to #MBEDTLS_RSA_PRIVATE, - * it is used for blinding and should be provided in this - * case; see mbedtls_rsa_private() for more. + * \param f_rng The RNG to use. It is used for padding generation + * and it is mandatory. * \param p_rng The RNG context to be passed to \p f_rng. May be - * \c NULL if \p f_rng is \c NULL or if \p f_rng doesn't - * need a context argument. - * \param mode The mode of operation. This must be either - * #MBEDTLS_RSA_PUBLIC or #MBEDTLS_RSA_PRIVATE (deprecated). + * \c NULL if \p f_rng doesn't need a context argument. * \param ilen The length of the plaintext in Bytes. * \param input The input data to encrypt. This must be a readable * buffer of size \p ilen Bytes. It may be \c NULL if @@ -625,7 +621,7 @@ int mbedtls_rsa_private(mbedtls_rsa_context *ctx, int mbedtls_rsa_pkcs1_encrypt(mbedtls_rsa_context *ctx, int (*f_rng)(void *, unsigned char *, size_t), void *p_rng, - int mode, size_t ilen, + size_t ilen, const unsigned char *input, unsigned char *output); @@ -633,25 +629,11 @@ int mbedtls_rsa_pkcs1_encrypt(mbedtls_rsa_context *ctx, * \brief This function performs a PKCS#1 v1.5 encryption operation * (RSAES-PKCS1-v1_5-ENCRYPT). * - * \deprecated It is deprecated and discouraged to call this function - * in #MBEDTLS_RSA_PRIVATE mode. Future versions of the library - * are likely to remove the \p mode argument and have it - * implicitly set to #MBEDTLS_RSA_PUBLIC. - * - * \note Alternative implementations of RSA need not support - * mode being set to #MBEDTLS_RSA_PRIVATE and might instead - * return #MBEDTLS_ERR_PLATFORM_FEATURE_UNSUPPORTED. - * * \param ctx The initialized RSA context to use. - * \param f_rng The RNG function to use. It is needed for padding generation - * if \p mode is #MBEDTLS_RSA_PUBLIC. If \p mode is - * #MBEDTLS_RSA_PRIVATE (discouraged), it is used for - * blinding and should be provided; see mbedtls_rsa_private(). + * \param f_rng The RNG function to use. It is mandatory and used for + * padding generation. * \param p_rng The RNG context to be passed to \p f_rng. This may - * be \c NULL if \p f_rng is \c NULL or if \p f_rng - * doesn't need a context argument. - * \param mode The mode of operation. This must be either - * #MBEDTLS_RSA_PUBLIC or #MBEDTLS_RSA_PRIVATE (deprecated). + * be \c NULL if \p f_rng doesn't need a context argument. * \param ilen The length of the plaintext in Bytes. * \param input The input data to encrypt. This must be a readable * buffer of size \p ilen Bytes. It may be \c NULL if @@ -666,7 +648,7 @@ int mbedtls_rsa_pkcs1_encrypt(mbedtls_rsa_context *ctx, int mbedtls_rsa_rsaes_pkcs1_v15_encrypt(mbedtls_rsa_context *ctx, int (*f_rng)(void *, unsigned char *, size_t), void *p_rng, - int mode, size_t ilen, + size_t ilen, const unsigned char *input, unsigned char *output); @@ -677,22 +659,11 @@ int mbedtls_rsa_rsaes_pkcs1_v15_encrypt(mbedtls_rsa_context *ctx, * \note The output buffer must be as large as the size * of ctx->N. For example, 128 Bytes if RSA-1024 is used. * - * \deprecated It is deprecated and discouraged to call this function - * in #MBEDTLS_RSA_PRIVATE mode. Future versions of the library - * are likely to remove the \p mode argument and have it - * implicitly set to #MBEDTLS_RSA_PUBLIC. - * - * \note Alternative implementations of RSA need not support - * mode being set to #MBEDTLS_RSA_PRIVATE and might instead - * return #MBEDTLS_ERR_PLATFORM_FEATURE_UNSUPPORTED. - * * \param ctx The initialized RSA context to use. * \param f_rng The RNG function to use. This is needed for padding - * generation and must be provided. + * generation and is mandatory. * \param p_rng The RNG context to be passed to \p f_rng. This may * be \c NULL if \p f_rng doesn't need a context argument. - * \param mode The mode of operation. This must be either - * #MBEDTLS_RSA_PUBLIC or #MBEDTLS_RSA_PRIVATE (deprecated). * \param label The buffer holding the custom label to use. * This must be a readable buffer of length \p label_len * Bytes. It may be \c NULL if \p label_len is \c 0. @@ -711,7 +682,6 @@ int mbedtls_rsa_rsaes_pkcs1_v15_encrypt(mbedtls_rsa_context *ctx, int mbedtls_rsa_rsaes_oaep_encrypt(mbedtls_rsa_context *ctx, int (*f_rng)(void *, unsigned char *, size_t), void *p_rng, - int mode, const unsigned char *label, size_t label_len, size_t ilen, const unsigned char *input, @@ -722,7 +692,11 @@ int mbedtls_rsa_rsaes_oaep_encrypt(mbedtls_rsa_context *ctx, * message padding. * * It is the generic wrapper for performing a PKCS#1 decryption - * operation using the \p mode from the context. + * operation. + * + * \warning When \p ctx->padding is set to #MBEDTLS_RSA_PKCS_V15, + * mbedtls_rsa_rsaes_pkcs1_v15_decrypt() is called, which is an + * inherently dangerous function (CWE-242). * * \note The output buffer length \c output_max_len should be * as large as the size \p ctx->len of \p ctx->N (for example, @@ -731,24 +705,11 @@ int mbedtls_rsa_rsaes_oaep_encrypt(mbedtls_rsa_context *ctx, * hold the decryption of the particular ciphertext provided, * the function returns \c MBEDTLS_ERR_RSA_OUTPUT_TOO_LARGE. * - * \deprecated It is deprecated and discouraged to call this function - * in #MBEDTLS_RSA_PUBLIC mode. Future versions of the library - * are likely to remove the \p mode argument and have it - * implicitly set to #MBEDTLS_RSA_PRIVATE. - * - * \note Alternative implementations of RSA need not support - * mode being set to #MBEDTLS_RSA_PUBLIC and might instead - * return #MBEDTLS_ERR_PLATFORM_FEATURE_UNSUPPORTED. - * * \param ctx The initialized RSA context to use. - * \param f_rng The RNG function. If \p mode is #MBEDTLS_RSA_PRIVATE, - * this is used for blinding and should be provided; see - * mbedtls_rsa_private() for more. If \p mode is - * #MBEDTLS_RSA_PUBLIC, it is ignored. + * \param f_rng The RNG function. This is used for blinding and is + * mandatory; see mbedtls_rsa_private() for more. * \param p_rng The RNG context to be passed to \p f_rng. This may be - * \c NULL if \p f_rng is \c NULL or doesn't need a context. - * \param mode The mode of operation. This must be either - * #MBEDTLS_RSA_PRIVATE or #MBEDTLS_RSA_PUBLIC (deprecated). + * \c NULL if \p f_rng doesn't need a context. * \param olen The address at which to store the length of * the plaintext. This must not be \c NULL. * \param input The ciphertext buffer. This must be a readable buffer @@ -764,7 +725,7 @@ int mbedtls_rsa_rsaes_oaep_encrypt(mbedtls_rsa_context *ctx, int mbedtls_rsa_pkcs1_decrypt(mbedtls_rsa_context *ctx, int (*f_rng)(void *, unsigned char *, size_t), void *p_rng, - int mode, size_t *olen, + size_t *olen, const unsigned char *input, unsigned char *output, size_t output_max_len); @@ -773,6 +734,11 @@ int mbedtls_rsa_pkcs1_decrypt(mbedtls_rsa_context *ctx, * \brief This function performs a PKCS#1 v1.5 decryption * operation (RSAES-PKCS1-v1_5-DECRYPT). * + * \warning This is an inherently dangerous function (CWE-242). Unless + * it is used in a side channel free and safe way (eg. + * implementing the TLS protocol as per 7.4.7.1 of RFC 5246), + * the calling code is vulnerable. + * * \note The output buffer length \c output_max_len should be * as large as the size \p ctx->len of \p ctx->N, for example, * 128 Bytes if RSA-1024 is used, to be able to hold an @@ -780,24 +746,11 @@ int mbedtls_rsa_pkcs1_decrypt(mbedtls_rsa_context *ctx, * hold the decryption of the particular ciphertext provided, * the function returns #MBEDTLS_ERR_RSA_OUTPUT_TOO_LARGE. * - * \deprecated It is deprecated and discouraged to call this function - * in #MBEDTLS_RSA_PUBLIC mode. Future versions of the library - * are likely to remove the \p mode argument and have it - * implicitly set to #MBEDTLS_RSA_PRIVATE. - * - * \note Alternative implementations of RSA need not support - * mode being set to #MBEDTLS_RSA_PUBLIC and might instead - * return #MBEDTLS_ERR_PLATFORM_FEATURE_UNSUPPORTED. - * * \param ctx The initialized RSA context to use. - * \param f_rng The RNG function. If \p mode is #MBEDTLS_RSA_PRIVATE, - * this is used for blinding and should be provided; see - * mbedtls_rsa_private() for more. If \p mode is - * #MBEDTLS_RSA_PUBLIC, it is ignored. + * \param f_rng The RNG function. This is used for blinding and is + * mandatory; see mbedtls_rsa_private() for more. * \param p_rng The RNG context to be passed to \p f_rng. This may be - * \c NULL if \p f_rng is \c NULL or doesn't need a context. - * \param mode The mode of operation. This must be either - * #MBEDTLS_RSA_PRIVATE or #MBEDTLS_RSA_PUBLIC (deprecated). + * \c NULL if \p f_rng doesn't need a context. * \param olen The address at which to store the length of * the plaintext. This must not be \c NULL. * \param input The ciphertext buffer. This must be a readable buffer @@ -814,7 +767,7 @@ int mbedtls_rsa_pkcs1_decrypt(mbedtls_rsa_context *ctx, int mbedtls_rsa_rsaes_pkcs1_v15_decrypt(mbedtls_rsa_context *ctx, int (*f_rng)(void *, unsigned char *, size_t), void *p_rng, - int mode, size_t *olen, + size_t *olen, const unsigned char *input, unsigned char *output, size_t output_max_len); @@ -831,24 +784,11 @@ int mbedtls_rsa_rsaes_pkcs1_v15_decrypt(mbedtls_rsa_context *ctx, * ciphertext provided, the function returns * #MBEDTLS_ERR_RSA_OUTPUT_TOO_LARGE. * - * \deprecated It is deprecated and discouraged to call this function - * in #MBEDTLS_RSA_PUBLIC mode. Future versions of the library - * are likely to remove the \p mode argument and have it - * implicitly set to #MBEDTLS_RSA_PRIVATE. - * - * \note Alternative implementations of RSA need not support - * mode being set to #MBEDTLS_RSA_PUBLIC and might instead - * return #MBEDTLS_ERR_PLATFORM_FEATURE_UNSUPPORTED. - * * \param ctx The initialized RSA context to use. - * \param f_rng The RNG function. If \p mode is #MBEDTLS_RSA_PRIVATE, - * this is used for blinding and should be provided; see - * mbedtls_rsa_private() for more. If \p mode is - * #MBEDTLS_RSA_PUBLIC, it is ignored. + * \param f_rng The RNG function. This is used for blinding and is + * mandatory. * \param p_rng The RNG context to be passed to \p f_rng. This may be - * \c NULL if \p f_rng is \c NULL or doesn't need a context. - * \param mode The mode of operation. This must be either - * #MBEDTLS_RSA_PRIVATE or #MBEDTLS_RSA_PUBLIC (deprecated). + * \c NULL if \p f_rng doesn't need a context. * \param label The buffer holding the custom label to use. * This must be a readable buffer of length \p label_len * Bytes. It may be \c NULL if \p label_len is \c 0. @@ -868,7 +808,6 @@ int mbedtls_rsa_rsaes_pkcs1_v15_decrypt(mbedtls_rsa_context *ctx, int mbedtls_rsa_rsaes_oaep_decrypt(mbedtls_rsa_context *ctx, int (*f_rng)(void *, unsigned char *, size_t), void *p_rng, - int mode, const unsigned char *label, size_t label_len, size_t *olen, const unsigned char *input, @@ -880,7 +819,7 @@ int mbedtls_rsa_rsaes_oaep_decrypt(mbedtls_rsa_context *ctx, * a message digest using PKCS#1. * * It is the generic wrapper for performing a PKCS#1 - * signature using the \p mode from the context. + * signature. * * \note The \p sig buffer must be as large as the size * of \p ctx->N. For example, 128 Bytes if RSA-1024 is used. @@ -889,34 +828,18 @@ int mbedtls_rsa_rsaes_oaep_decrypt(mbedtls_rsa_context *ctx, * mbedtls_rsa_rsassa_pss_sign() for details on * \p md_alg and \p hash_id. * - * \deprecated It is deprecated and discouraged to call this function - * in #MBEDTLS_RSA_PUBLIC mode. Future versions of the library - * are likely to remove the \p mode argument and have it - * implicitly set to #MBEDTLS_RSA_PRIVATE. - * - * \note Alternative implementations of RSA need not support - * mode being set to #MBEDTLS_RSA_PUBLIC and might instead - * return #MBEDTLS_ERR_PLATFORM_FEATURE_UNSUPPORTED. - * * \param ctx The initialized RSA context to use. - * \param f_rng The RNG function to use. If the padding mode is PKCS#1 v2.1, - * this must be provided. If the padding mode is PKCS#1 v1.5 and - * \p mode is #MBEDTLS_RSA_PRIVATE, it is used for blinding - * and should be provided; see mbedtls_rsa_private() for more - * more. It is ignored otherwise. + * \param f_rng The RNG function to use. This is mandatory and + * must not be \c NULL. * \param p_rng The RNG context to be passed to \p f_rng. This may be \c NULL - * if \p f_rng is \c NULL or doesn't need a context argument. - * \param mode The mode of operation. This must be either - * #MBEDTLS_RSA_PRIVATE or #MBEDTLS_RSA_PUBLIC (deprecated). + * if \p f_rng doesn't need a context argument. * \param md_alg The message-digest algorithm used to hash the original data. * Use #MBEDTLS_MD_NONE for signing raw data. - * \param hashlen The length of the message digest. - * Ths is only used if \p md_alg is #MBEDTLS_MD_NONE. + * \param hashlen The length of the message digest or raw data in Bytes. + * If \p md_alg is not #MBEDTLS_MD_NONE, this must match the + * output length of the corresponding hash algorithm. * \param hash The buffer holding the message digest or raw data. - * If \p md_alg is #MBEDTLS_MD_NONE, this must be a readable - * buffer of length \p hashlen Bytes. If \p md_alg is not - * #MBEDTLS_MD_NONE, it must be a readable buffer of length - * the size of the hash corresponding to \p md_alg. + * This must be a readable buffer of at least \p hashlen Bytes. * \param sig The buffer to hold the signature. This must be a writable * buffer of length \c ctx->len Bytes. For example, \c 256 Bytes * for an 2048-bit RSA modulus. A buffer length of @@ -928,7 +851,6 @@ int mbedtls_rsa_rsaes_oaep_decrypt(mbedtls_rsa_context *ctx, int mbedtls_rsa_pkcs1_sign(mbedtls_rsa_context *ctx, int (*f_rng)(void *, unsigned char *, size_t), void *p_rng, - int mode, mbedtls_md_type_t md_alg, unsigned int hashlen, const unsigned char *hash, @@ -938,33 +860,18 @@ int mbedtls_rsa_pkcs1_sign(mbedtls_rsa_context *ctx, * \brief This function performs a PKCS#1 v1.5 signature * operation (RSASSA-PKCS1-v1_5-SIGN). * - * \deprecated It is deprecated and discouraged to call this function - * in #MBEDTLS_RSA_PUBLIC mode. Future versions of the library - * are likely to remove the \p mode argument and have it - * implicitly set to #MBEDTLS_RSA_PRIVATE. - * - * \note Alternative implementations of RSA need not support - * mode being set to #MBEDTLS_RSA_PUBLIC and might instead - * return #MBEDTLS_ERR_PLATFORM_FEATURE_UNSUPPORTED. - * * \param ctx The initialized RSA context to use. - * \param f_rng The RNG function. If \p mode is #MBEDTLS_RSA_PRIVATE, - * this is used for blinding and should be provided; see - * mbedtls_rsa_private() for more. If \p mode is - * #MBEDTLS_RSA_PUBLIC, it is ignored. + * \param f_rng The RNG function. This is used for blinding and is + * mandatory; see mbedtls_rsa_private() for more. * \param p_rng The RNG context to be passed to \p f_rng. This may be \c NULL - * if \p f_rng is \c NULL or doesn't need a context argument. - * \param mode The mode of operation. This must be either - * #MBEDTLS_RSA_PRIVATE or #MBEDTLS_RSA_PUBLIC (deprecated). + * if \p f_rng doesn't need a context argument. * \param md_alg The message-digest algorithm used to hash the original data. * Use #MBEDTLS_MD_NONE for signing raw data. - * \param hashlen The length of the message digest. - * Ths is only used if \p md_alg is #MBEDTLS_MD_NONE. + * \param hashlen The length of the message digest or raw data in Bytes. + * If \p md_alg is not #MBEDTLS_MD_NONE, this must match the + * output length of the corresponding hash algorithm. * \param hash The buffer holding the message digest or raw data. - * If \p md_alg is #MBEDTLS_MD_NONE, this must be a readable - * buffer of length \p hashlen Bytes. If \p md_alg is not - * #MBEDTLS_MD_NONE, it must be a readable buffer of length - * the size of the hash corresponding to \p md_alg. + * This must be a readable buffer of at least \p hashlen Bytes. * \param sig The buffer to hold the signature. This must be a writable * buffer of length \c ctx->len Bytes. For example, \c 256 Bytes * for an 2048-bit RSA modulus. A buffer length of @@ -976,19 +883,18 @@ int mbedtls_rsa_pkcs1_sign(mbedtls_rsa_context *ctx, int mbedtls_rsa_rsassa_pkcs1_v15_sign(mbedtls_rsa_context *ctx, int (*f_rng)(void *, unsigned char *, size_t), void *p_rng, - int mode, mbedtls_md_type_t md_alg, unsigned int hashlen, const unsigned char *hash, unsigned char *sig); +#if defined(MBEDTLS_PKCS1_V21) /** * \brief This function performs a PKCS#1 v2.1 PSS signature * operation (RSASSA-PSS-SIGN). * - * \note The \c hash_id set in \p ctx (when calling - * mbedtls_rsa_init() or by calling mbedtls_rsa_set_padding() - * afterwards) selects the hash used for the + * \note The \c hash_id set in \p ctx by calling + * mbedtls_rsa_set_padding() selects the hash used for the * encoding operation and for the mask generation function * (MGF1). For more details on the encoding operation and the * mask generation function, consult RFC-3447: Public-Key @@ -1003,18 +909,16 @@ int mbedtls_rsa_rsassa_pkcs1_v15_sign(mbedtls_rsa_context *ctx, * #MBEDTLS_ERR_RSA_BAD_INPUT_DATA. * * \param ctx The initialized RSA context to use. - * \param f_rng The RNG function. It must not be \c NULL. + * \param f_rng The RNG function. It is mandatory and must not be \c NULL. * \param p_rng The RNG context to be passed to \p f_rng. This may be \c NULL * if \p f_rng doesn't need a context argument. * \param md_alg The message-digest algorithm used to hash the original data. * Use #MBEDTLS_MD_NONE for signing raw data. - * \param hashlen The length of the message digest. - * Ths is only used if \p md_alg is #MBEDTLS_MD_NONE. + * \param hashlen The length of the message digest or raw data in Bytes. + * If \p md_alg is not #MBEDTLS_MD_NONE, this must match the + * output length of the corresponding hash algorithm. * \param hash The buffer holding the message digest or raw data. - * If \p md_alg is #MBEDTLS_MD_NONE, this must be a readable - * buffer of length \p hashlen Bytes. If \p md_alg is not - * #MBEDTLS_MD_NONE, it must be a readable buffer of length - * the size of the hash corresponding to \p md_alg. + * This must be a readable buffer of at least \p hashlen Bytes. * \param saltlen The length of the salt that should be used. * If passed #MBEDTLS_RSA_SALT_LEN_ANY, the function will use * the largest possible salt length up to the hash length, @@ -1041,9 +945,8 @@ int mbedtls_rsa_rsassa_pss_sign_ext(mbedtls_rsa_context *ctx, * \brief This function performs a PKCS#1 v2.1 PSS signature * operation (RSASSA-PSS-SIGN). * - * \note The \c hash_id set in \p ctx (when calling - * mbedtls_rsa_init() or by calling mbedtls_rsa_set_padding() - * afterwards) selects the hash used for the + * \note The \c hash_id set in \p ctx by calling + * mbedtls_rsa_set_padding() selects the hash used for the * encoding operation and for the mask generation function * (MGF1). For more details on the encoding operation and the * mask generation function, consult RFC-3447: Public-Key @@ -1060,30 +963,17 @@ int mbedtls_rsa_rsassa_pss_sign_ext(mbedtls_rsa_context *ctx, * the key size in bytes), this function returns * #MBEDTLS_ERR_RSA_BAD_INPUT_DATA. * - * \deprecated It is deprecated and discouraged to call this function - * in #MBEDTLS_RSA_PUBLIC mode. Future versions of the library - * are likely to remove the \p mode argument and have it - * implicitly set to #MBEDTLS_RSA_PRIVATE. - * - * \note Alternative implementations of RSA need not support - * mode being set to #MBEDTLS_RSA_PUBLIC and might instead - * return #MBEDTLS_ERR_PLATFORM_FEATURE_UNSUPPORTED. - * * \param ctx The initialized RSA context to use. - * \param f_rng The RNG function. It must not be \c NULL. + * \param f_rng The RNG function. It is mandatory and must not be \c NULL. * \param p_rng The RNG context to be passed to \p f_rng. This may be \c NULL * if \p f_rng doesn't need a context argument. - * \param mode The mode of operation. This must be either - * #MBEDTLS_RSA_PRIVATE or #MBEDTLS_RSA_PUBLIC (deprecated). * \param md_alg The message-digest algorithm used to hash the original data. * Use #MBEDTLS_MD_NONE for signing raw data. - * \param hashlen The length of the message digest. - * This is only used if \p md_alg is #MBEDTLS_MD_NONE. + * \param hashlen The length of the message digest or raw data in Bytes. + * If \p md_alg is not #MBEDTLS_MD_NONE, this must match the + * output length of the corresponding hash algorithm. * \param hash The buffer holding the message digest or raw data. - * If \p md_alg is #MBEDTLS_MD_NONE, this must be a readable - * buffer of length \p hashlen Bytes. If \p md_alg is not - * #MBEDTLS_MD_NONE, it must be a readable buffer of length - * the size of the hash corresponding to \p md_alg. + * This must be a readable buffer of at least \p hashlen Bytes. * \param sig The buffer to hold the signature. This must be a writable * buffer of length \c ctx->len Bytes. For example, \c 256 Bytes * for an 2048-bit RSA modulus. A buffer length of @@ -1095,49 +985,31 @@ int mbedtls_rsa_rsassa_pss_sign_ext(mbedtls_rsa_context *ctx, int mbedtls_rsa_rsassa_pss_sign(mbedtls_rsa_context *ctx, int (*f_rng)(void *, unsigned char *, size_t), void *p_rng, - int mode, mbedtls_md_type_t md_alg, unsigned int hashlen, const unsigned char *hash, unsigned char *sig); +#endif /* MBEDTLS_PKCS1_V21 */ /** * \brief This function performs a public RSA operation and checks * the message digest. * * This is the generic wrapper for performing a PKCS#1 - * verification using the mode from the context. + * verification. * * \note For PKCS#1 v2.1 encoding, see comments on * mbedtls_rsa_rsassa_pss_verify() about \c md_alg and * \c hash_id. * - * \deprecated It is deprecated and discouraged to call this function - * in #MBEDTLS_RSA_PRIVATE mode. Future versions of the library - * are likely to remove the \p mode argument and have it - * set to #MBEDTLS_RSA_PUBLIC. - * - * \note Alternative implementations of RSA need not support - * mode being set to #MBEDTLS_RSA_PRIVATE and might instead - * return #MBEDTLS_ERR_PLATFORM_FEATURE_UNSUPPORTED. - * * \param ctx The initialized RSA public key context to use. - * \param f_rng The RNG function to use. If \p mode is #MBEDTLS_RSA_PRIVATE, - * this is used for blinding and should be provided; see - * mbedtls_rsa_private() for more. Otherwise, it is ignored. - * \param p_rng The RNG context to be passed to \p f_rng. This may be - * \c NULL if \p f_rng is \c NULL or doesn't need a context. - * \param mode The mode of operation. This must be either - * #MBEDTLS_RSA_PUBLIC or #MBEDTLS_RSA_PRIVATE (deprecated). * \param md_alg The message-digest algorithm used to hash the original data. * Use #MBEDTLS_MD_NONE for signing raw data. - * \param hashlen The length of the message digest. - * This is only used if \p md_alg is #MBEDTLS_MD_NONE. + * \param hashlen The length of the message digest or raw data in Bytes. + * If \p md_alg is not #MBEDTLS_MD_NONE, this must match the + * output length of the corresponding hash algorithm. * \param hash The buffer holding the message digest or raw data. - * If \p md_alg is #MBEDTLS_MD_NONE, this must be a readable - * buffer of length \p hashlen Bytes. If \p md_alg is not - * #MBEDTLS_MD_NONE, it must be a readable buffer of length - * the size of the hash corresponding to \p md_alg. + * This must be a readable buffer of at least \p hashlen Bytes. * \param sig The buffer holding the signature. This must be a readable * buffer of length \c ctx->len Bytes. For example, \c 256 Bytes * for an 2048-bit RSA modulus. @@ -1146,9 +1018,6 @@ int mbedtls_rsa_rsassa_pss_sign(mbedtls_rsa_context *ctx, * \return An \c MBEDTLS_ERR_RSA_XXX error code on failure. */ int mbedtls_rsa_pkcs1_verify(mbedtls_rsa_context *ctx, - int (*f_rng)(void *, unsigned char *, size_t), - void *p_rng, - int mode, mbedtls_md_type_t md_alg, unsigned int hashlen, const unsigned char *hash, @@ -1158,32 +1027,14 @@ int mbedtls_rsa_pkcs1_verify(mbedtls_rsa_context *ctx, * \brief This function performs a PKCS#1 v1.5 verification * operation (RSASSA-PKCS1-v1_5-VERIFY). * - * \deprecated It is deprecated and discouraged to call this function - * in #MBEDTLS_RSA_PRIVATE mode. Future versions of the library - * are likely to remove the \p mode argument and have it - * set to #MBEDTLS_RSA_PUBLIC. - * - * \note Alternative implementations of RSA need not support - * mode being set to #MBEDTLS_RSA_PRIVATE and might instead - * return #MBEDTLS_ERR_PLATFORM_FEATURE_UNSUPPORTED. - * * \param ctx The initialized RSA public key context to use. - * \param f_rng The RNG function to use. If \p mode is #MBEDTLS_RSA_PRIVATE, - * this is used for blinding and should be provided; see - * mbedtls_rsa_private() for more. Otherwise, it is ignored. - * \param p_rng The RNG context to be passed to \p f_rng. This may be - * \c NULL if \p f_rng is \c NULL or doesn't need a context. - * \param mode The mode of operation. This must be either - * #MBEDTLS_RSA_PUBLIC or #MBEDTLS_RSA_PRIVATE (deprecated). * \param md_alg The message-digest algorithm used to hash the original data. * Use #MBEDTLS_MD_NONE for signing raw data. - * \param hashlen The length of the message digest. - * This is only used if \p md_alg is #MBEDTLS_MD_NONE. + * \param hashlen The length of the message digest or raw data in Bytes. + * If \p md_alg is not #MBEDTLS_MD_NONE, this must match the + * output length of the corresponding hash algorithm. * \param hash The buffer holding the message digest or raw data. - * If \p md_alg is #MBEDTLS_MD_NONE, this must be a readable - * buffer of length \p hashlen Bytes. If \p md_alg is not - * #MBEDTLS_MD_NONE, it must be a readable buffer of length - * the size of the hash corresponding to \p md_alg. + * This must be a readable buffer of at least \p hashlen Bytes. * \param sig The buffer holding the signature. This must be a readable * buffer of length \c ctx->len Bytes. For example, \c 256 Bytes * for an 2048-bit RSA modulus. @@ -1192,9 +1043,6 @@ int mbedtls_rsa_pkcs1_verify(mbedtls_rsa_context *ctx, * \return An \c MBEDTLS_ERR_RSA_XXX error code on failure. */ int mbedtls_rsa_rsassa_pkcs1_v15_verify(mbedtls_rsa_context *ctx, - int (*f_rng)(void *, unsigned char *, size_t), - void *p_rng, - int mode, mbedtls_md_type_t md_alg, unsigned int hashlen, const unsigned char *hash, @@ -1204,42 +1052,24 @@ int mbedtls_rsa_rsassa_pkcs1_v15_verify(mbedtls_rsa_context *ctx, * \brief This function performs a PKCS#1 v2.1 PSS verification * operation (RSASSA-PSS-VERIFY). * - * \note The \c hash_id set in \p ctx (when calling - * mbedtls_rsa_init() or by calling mbedtls_rsa_set_padding() - * afterwards) selects the hash used for the + * \note The \c hash_id set in \p ctx by calling + * mbedtls_rsa_set_padding() selects the hash used for the * encoding operation and for the mask generation function * (MGF1). For more details on the encoding operation and the * mask generation function, consult RFC-3447: Public-Key * Cryptography Standards (PKCS) #1 v2.1: RSA Cryptography - * Specifications. If the \c hash_id set in \p ctx is - * #MBEDTLS_MD_NONE, the \p md_alg parameter is used. - * - * \deprecated It is deprecated and discouraged to call this function - * in #MBEDTLS_RSA_PRIVATE mode. Future versions of the library - * are likely to remove the \p mode argument and have it - * implicitly set to #MBEDTLS_RSA_PUBLIC. - * - * \note Alternative implementations of RSA need not support - * mode being set to #MBEDTLS_RSA_PRIVATE and might instead - * return #MBEDTLS_ERR_PLATFORM_FEATURE_UNSUPPORTED. + * Specifications. If the \c hash_id set in \p ctx by + * mbedtls_rsa_set_padding() is #MBEDTLS_MD_NONE, the \p md_alg + * parameter is used. * * \param ctx The initialized RSA public key context to use. - * \param f_rng The RNG function to use. If \p mode is #MBEDTLS_RSA_PRIVATE, - * this is used for blinding and should be provided; see - * mbedtls_rsa_private() for more. Otherwise, it is ignored. - * \param p_rng The RNG context to be passed to \p f_rng. This may be - * \c NULL if \p f_rng is \c NULL or doesn't need a context. - * \param mode The mode of operation. This must be either - * #MBEDTLS_RSA_PUBLIC or #MBEDTLS_RSA_PRIVATE (deprecated). * \param md_alg The message-digest algorithm used to hash the original data. * Use #MBEDTLS_MD_NONE for signing raw data. - * \param hashlen The length of the message digest. - * This is only used if \p md_alg is #MBEDTLS_MD_NONE. + * \param hashlen The length of the message digest or raw data in Bytes. + * If \p md_alg is not #MBEDTLS_MD_NONE, this must match the + * output length of the corresponding hash algorithm. * \param hash The buffer holding the message digest or raw data. - * If \p md_alg is #MBEDTLS_MD_NONE, this must be a readable - * buffer of length \p hashlen Bytes. If \p md_alg is not - * #MBEDTLS_MD_NONE, it must be a readable buffer of length - * the size of the hash corresponding to \p md_alg. + * This must be a readable buffer of at least \p hashlen Bytes. * \param sig The buffer holding the signature. This must be a readable * buffer of length \c ctx->len Bytes. For example, \c 256 Bytes * for an 2048-bit RSA modulus. @@ -1248,9 +1078,6 @@ int mbedtls_rsa_rsassa_pkcs1_v15_verify(mbedtls_rsa_context *ctx, * \return An \c MBEDTLS_ERR_RSA_XXX error code on failure. */ int mbedtls_rsa_rsassa_pss_verify(mbedtls_rsa_context *ctx, - int (*f_rng)(void *, unsigned char *, size_t), - void *p_rng, - int mode, mbedtls_md_type_t md_alg, unsigned int hashlen, const unsigned char *hash, @@ -1263,27 +1090,17 @@ int mbedtls_rsa_rsassa_pss_verify(mbedtls_rsa_context *ctx, * \note The \p sig buffer must be as large as the size * of \p ctx->N. For example, 128 Bytes if RSA-1024 is used. * - * \note The \c hash_id set in \p ctx (when calling - * mbedtls_rsa_init() or by calling mbedtls_rsa_set_padding() - * afterwards) is ignored. + * \note The \c hash_id set in \p ctx by mbedtls_rsa_set_padding() is + * ignored. * * \param ctx The initialized RSA public key context to use. - * \param f_rng The RNG function to use. If \p mode is #MBEDTLS_RSA_PRIVATE, - * this is used for blinding and should be provided; see - * mbedtls_rsa_private() for more. Otherwise, it is ignored. - * \param p_rng The RNG context to be passed to \p f_rng. This may be - * \c NULL if \p f_rng is \c NULL or doesn't need a context. - * \param mode The mode of operation. This must be either - * #MBEDTLS_RSA_PUBLIC or #MBEDTLS_RSA_PRIVATE. * \param md_alg The message-digest algorithm used to hash the original data. * Use #MBEDTLS_MD_NONE for signing raw data. - * \param hashlen The length of the message digest. - * This is only used if \p md_alg is #MBEDTLS_MD_NONE. + * \param hashlen The length of the message digest or raw data in Bytes. + * If \p md_alg is not #MBEDTLS_MD_NONE, this must match the + * output length of the corresponding hash algorithm. * \param hash The buffer holding the message digest or raw data. - * If \p md_alg is #MBEDTLS_MD_NONE, this must be a readable - * buffer of length \p hashlen Bytes. If \p md_alg is not - * #MBEDTLS_MD_NONE, it must be a readable buffer of length - * the size of the hash corresponding to \p md_alg. + * This must be a readable buffer of at least \p hashlen Bytes. * \param mgf1_hash_id The message digest algorithm used for the * verification operation and the mask generation * function (MGF1). For more details on the encoding @@ -1301,9 +1118,6 @@ int mbedtls_rsa_rsassa_pss_verify(mbedtls_rsa_context *ctx, * \return An \c MBEDTLS_ERR_RSA_XXX error code on failure. */ int mbedtls_rsa_rsassa_pss_verify_ext(mbedtls_rsa_context *ctx, - int (*f_rng)(void *, unsigned char *, size_t), - void *p_rng, - int mode, mbedtls_md_type_t md_alg, unsigned int hashlen, const unsigned char *hash, diff --git a/vendor/mbedtls/include/mbedtls/sha1.h b/vendor/mbedtls/include/mbedtls/sha1.h index 7a7319f26a..592ffd13f2 100644 --- a/vendor/mbedtls/include/mbedtls/sha1.h +++ b/vendor/mbedtls/include/mbedtls/sha1.h @@ -12,35 +12,17 @@ */ /* * Copyright The Mbed TLS Contributors - * SPDX-License-Identifier: Apache-2.0 - * - * Licensed under the Apache License, Version 2.0 (the "License"); you may - * not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT - * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. + * SPDX-License-Identifier: Apache-2.0 OR GPL-2.0-or-later */ #ifndef MBEDTLS_SHA1_H #define MBEDTLS_SHA1_H +#include "mbedtls/private_access.h" -#if !defined(MBEDTLS_CONFIG_FILE) -#include "mbedtls/config.h" -#else -#include MBEDTLS_CONFIG_FILE -#endif +#include "mbedtls/build_info.h" #include #include -/* MBEDTLS_ERR_SHA1_HW_ACCEL_FAILED is deprecated and should not be used. */ -/** SHA-1 hardware accelerator failed */ -#define MBEDTLS_ERR_SHA1_HW_ACCEL_FAILED -0x0035 /** SHA-1 input data was malformed. */ #define MBEDTLS_ERR_SHA1_BAD_INPUT_DATA -0x0073 @@ -61,9 +43,9 @@ extern "C" { * */ typedef struct mbedtls_sha1_context { - uint32_t total[2]; /*!< The number of Bytes processed. */ - uint32_t state[5]; /*!< The intermediate digest state. */ - unsigned char buffer[64]; /*!< The data block being processed. */ + uint32_t MBEDTLS_PRIVATE(total)[2]; /*!< The number of Bytes processed. */ + uint32_t MBEDTLS_PRIVATE(state)[5]; /*!< The intermediate digest state. */ + unsigned char MBEDTLS_PRIVATE(buffer)[64]; /*!< The data block being processed. */ } mbedtls_sha1_context; @@ -126,7 +108,7 @@ void mbedtls_sha1_clone(mbedtls_sha1_context *dst, * \return A negative error code on failure. * */ -int mbedtls_sha1_starts_ret(mbedtls_sha1_context *ctx); +int mbedtls_sha1_starts(mbedtls_sha1_context *ctx); /** * \brief This function feeds an input buffer into an ongoing SHA-1 @@ -145,9 +127,9 @@ int mbedtls_sha1_starts_ret(mbedtls_sha1_context *ctx); * \return \c 0 on success. * \return A negative error code on failure. */ -int mbedtls_sha1_update_ret(mbedtls_sha1_context *ctx, - const unsigned char *input, - size_t ilen); +int mbedtls_sha1_update(mbedtls_sha1_context *ctx, + const unsigned char *input, + size_t ilen); /** * \brief This function finishes the SHA-1 operation, and writes @@ -165,8 +147,8 @@ int mbedtls_sha1_update_ret(mbedtls_sha1_context *ctx, * \return \c 0 on success. * \return A negative error code on failure. */ -int mbedtls_sha1_finish_ret(mbedtls_sha1_context *ctx, - unsigned char output[20]); +int mbedtls_sha1_finish(mbedtls_sha1_context *ctx, + unsigned char output[20]); /** * \brief SHA-1 process data block (internal use only). @@ -186,85 +168,6 @@ int mbedtls_sha1_finish_ret(mbedtls_sha1_context *ctx, int mbedtls_internal_sha1_process(mbedtls_sha1_context *ctx, const unsigned char data[64]); -#if !defined(MBEDTLS_DEPRECATED_REMOVED) -#if defined(MBEDTLS_DEPRECATED_WARNING) -#define MBEDTLS_DEPRECATED __attribute__((deprecated)) -#else -#define MBEDTLS_DEPRECATED -#endif -/** - * \brief This function starts a SHA-1 checksum calculation. - * - * \warning SHA-1 is considered a weak message digest and its use - * constitutes a security risk. We recommend considering - * stronger message digests instead. - * - * \deprecated Superseded by mbedtls_sha1_starts_ret() in 2.7.0. - * - * \param ctx The SHA-1 context to initialize. This must be initialized. - * - */ -MBEDTLS_DEPRECATED void mbedtls_sha1_starts(mbedtls_sha1_context *ctx); - -/** - * \brief This function feeds an input buffer into an ongoing SHA-1 - * checksum calculation. - * - * \warning SHA-1 is considered a weak message digest and its use - * constitutes a security risk. We recommend considering - * stronger message digests instead. - * - * \deprecated Superseded by mbedtls_sha1_update_ret() in 2.7.0. - * - * \param ctx The SHA-1 context. This must be initialized and - * have a hash operation started. - * \param input The buffer holding the input data. - * This must be a readable buffer of length \p ilen Bytes. - * \param ilen The length of the input data \p input in Bytes. - * - */ -MBEDTLS_DEPRECATED void mbedtls_sha1_update(mbedtls_sha1_context *ctx, - const unsigned char *input, - size_t ilen); - -/** - * \brief This function finishes the SHA-1 operation, and writes - * the result to the output buffer. - * - * \warning SHA-1 is considered a weak message digest and its use - * constitutes a security risk. We recommend considering - * stronger message digests instead. - * - * \deprecated Superseded by mbedtls_sha1_finish_ret() in 2.7.0. - * - * \param ctx The SHA-1 context. This must be initialized and - * have a hash operation started. - * \param output The SHA-1 checksum result. - * This must be a writable buffer of length \c 20 Bytes. - */ -MBEDTLS_DEPRECATED void mbedtls_sha1_finish(mbedtls_sha1_context *ctx, - unsigned char output[20]); - -/** - * \brief SHA-1 process data block (internal use only). - * - * \warning SHA-1 is considered a weak message digest and its use - * constitutes a security risk. We recommend considering - * stronger message digests instead. - * - * \deprecated Superseded by mbedtls_internal_sha1_process() in 2.7.0. - * - * \param ctx The SHA-1 context. This must be initialized. - * \param data The data block being processed. - * This must be a readable buffer of length \c 64 bytes. - * - */ -MBEDTLS_DEPRECATED void mbedtls_sha1_process(mbedtls_sha1_context *ctx, - const unsigned char data[64]); - -#undef MBEDTLS_DEPRECATED -#endif /* !MBEDTLS_DEPRECATED_REMOVED */ - /** * \brief This function calculates the SHA-1 checksum of a buffer. * @@ -288,44 +191,9 @@ MBEDTLS_DEPRECATED void mbedtls_sha1_process(mbedtls_sha1_context *ctx, * \return A negative error code on failure. * */ -int mbedtls_sha1_ret(const unsigned char *input, - size_t ilen, - unsigned char output[20]); - -#if !defined(MBEDTLS_DEPRECATED_REMOVED) -#if defined(MBEDTLS_DEPRECATED_WARNING) -#define MBEDTLS_DEPRECATED __attribute__((deprecated)) -#else -#define MBEDTLS_DEPRECATED -#endif -/** - * \brief This function calculates the SHA-1 checksum of a buffer. - * - * The function allocates the context, performs the - * calculation, and frees the context. - * - * The SHA-1 result is calculated as - * output = SHA-1(input buffer). - * - * \warning SHA-1 is considered a weak message digest and its use - * constitutes a security risk. We recommend considering - * stronger message digests instead. - * - * \deprecated Superseded by mbedtls_sha1_ret() in 2.7.0 - * - * \param input The buffer holding the input data. - * This must be a readable buffer of length \p ilen Bytes. - * \param ilen The length of the input data \p input in Bytes. - * \param output The SHA-1 checksum result. This must be a writable - * buffer of size \c 20 Bytes. - * - */ -MBEDTLS_DEPRECATED void mbedtls_sha1(const unsigned char *input, - size_t ilen, - unsigned char output[20]); - -#undef MBEDTLS_DEPRECATED -#endif /* !MBEDTLS_DEPRECATED_REMOVED */ +int mbedtls_sha1(const unsigned char *input, + size_t ilen, + unsigned char output[20]); #if defined(MBEDTLS_SELF_TEST) diff --git a/vendor/mbedtls/include/mbedtls/sha256.h b/vendor/mbedtls/include/mbedtls/sha256.h index 00bd17d0cf..ca568e291e 100644 --- a/vendor/mbedtls/include/mbedtls/sha256.h +++ b/vendor/mbedtls/include/mbedtls/sha256.h @@ -8,35 +8,17 @@ */ /* * Copyright The Mbed TLS Contributors - * SPDX-License-Identifier: Apache-2.0 - * - * Licensed under the Apache License, Version 2.0 (the "License"); you may - * not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT - * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. + * SPDX-License-Identifier: Apache-2.0 OR GPL-2.0-or-later */ #ifndef MBEDTLS_SHA256_H #define MBEDTLS_SHA256_H +#include "mbedtls/private_access.h" -#if !defined(MBEDTLS_CONFIG_FILE) -#include "mbedtls/config.h" -#else -#include MBEDTLS_CONFIG_FILE -#endif +#include "mbedtls/build_info.h" #include #include -/* MBEDTLS_ERR_SHA256_HW_ACCEL_FAILED is deprecated and should not be used. */ -/** SHA-256 hardware accelerator failed */ -#define MBEDTLS_ERR_SHA256_HW_ACCEL_FAILED -0x0037 /** SHA-256 input data was malformed. */ #define MBEDTLS_ERR_SHA256_BAD_INPUT_DATA -0x0074 @@ -53,14 +35,16 @@ extern "C" { * * The structure is used both for SHA-256 and for SHA-224 * checksum calculations. The choice between these two is - * made in the call to mbedtls_sha256_starts_ret(). + * made in the call to mbedtls_sha256_starts(). */ typedef struct mbedtls_sha256_context { - uint32_t total[2]; /*!< The number of Bytes processed. */ - uint32_t state[8]; /*!< The intermediate digest state. */ - unsigned char buffer[64]; /*!< The data block being processed. */ - int is224; /*!< Determines which function to use: - 0: Use SHA-256, or 1: Use SHA-224. */ + unsigned char MBEDTLS_PRIVATE(buffer)[64]; /*!< The data block being processed. */ + uint32_t MBEDTLS_PRIVATE(total)[2]; /*!< The number of Bytes processed. */ + uint32_t MBEDTLS_PRIVATE(state)[8]; /*!< The intermediate digest state. */ +#if defined(MBEDTLS_SHA224_C) + int MBEDTLS_PRIVATE(is224); /*!< Determines which function to use: + 0: Use SHA-256, or 1: Use SHA-224. */ +#endif } mbedtls_sha256_context; @@ -101,10 +85,14 @@ void mbedtls_sha256_clone(mbedtls_sha256_context *dst, * \param is224 This determines which function to use. This must be * either \c 0 for SHA-256, or \c 1 for SHA-224. * + * \note is224 must be defined accordingly to the enabled + * MBEDTLS_SHA224_C/MBEDTLS_SHA256_C symbols otherwise the + * function will return #MBEDTLS_ERR_SHA512_BAD_INPUT_DATA. + * * \return \c 0 on success. * \return A negative error code on failure. */ -int mbedtls_sha256_starts_ret(mbedtls_sha256_context *ctx, int is224); +int mbedtls_sha256_starts(mbedtls_sha256_context *ctx, int is224); /** * \brief This function feeds an input buffer into an ongoing @@ -119,9 +107,9 @@ int mbedtls_sha256_starts_ret(mbedtls_sha256_context *ctx, int is224); * \return \c 0 on success. * \return A negative error code on failure. */ -int mbedtls_sha256_update_ret(mbedtls_sha256_context *ctx, - const unsigned char *input, - size_t ilen); +int mbedtls_sha256_update(mbedtls_sha256_context *ctx, + const unsigned char *input, + size_t ilen); /** * \brief This function finishes the SHA-256 operation, and writes @@ -130,13 +118,14 @@ int mbedtls_sha256_update_ret(mbedtls_sha256_context *ctx, * \param ctx The SHA-256 context. This must be initialized * and have a hash operation started. * \param output The SHA-224 or SHA-256 checksum result. - * This must be a writable buffer of length \c 32 Bytes. + * This must be a writable buffer of length \c 32 bytes + * for SHA-256, \c 28 bytes for SHA-224. * * \return \c 0 on success. * \return A negative error code on failure. */ -int mbedtls_sha256_finish_ret(mbedtls_sha256_context *ctx, - unsigned char output[32]); +int mbedtls_sha256_finish(mbedtls_sha256_context *ctx, + unsigned char *output); /** * \brief This function processes a single data block within @@ -153,72 +142,6 @@ int mbedtls_sha256_finish_ret(mbedtls_sha256_context *ctx, int mbedtls_internal_sha256_process(mbedtls_sha256_context *ctx, const unsigned char data[64]); -#if !defined(MBEDTLS_DEPRECATED_REMOVED) -#if defined(MBEDTLS_DEPRECATED_WARNING) -#define MBEDTLS_DEPRECATED __attribute__((deprecated)) -#else -#define MBEDTLS_DEPRECATED -#endif -/** - * \brief This function starts a SHA-224 or SHA-256 checksum - * calculation. - * - * \deprecated Superseded by mbedtls_sha256_starts_ret() in 2.7.0. - * - * \param ctx The context to use. This must be initialized. - * \param is224 Determines which function to use. This must be - * either \c 0 for SHA-256, or \c 1 for SHA-224. - */ -MBEDTLS_DEPRECATED void mbedtls_sha256_starts(mbedtls_sha256_context *ctx, - int is224); - -/** - * \brief This function feeds an input buffer into an ongoing - * SHA-256 checksum calculation. - * - * \deprecated Superseded by mbedtls_sha256_update_ret() in 2.7.0. - * - * \param ctx The SHA-256 context to use. This must be - * initialized and have a hash operation started. - * \param input The buffer holding the data. This must be a readable - * buffer of length \p ilen Bytes. - * \param ilen The length of the input data in Bytes. - */ -MBEDTLS_DEPRECATED void mbedtls_sha256_update(mbedtls_sha256_context *ctx, - const unsigned char *input, - size_t ilen); - -/** - * \brief This function finishes the SHA-256 operation, and writes - * the result to the output buffer. - * - * \deprecated Superseded by mbedtls_sha256_finish_ret() in 2.7.0. - * - * \param ctx The SHA-256 context. This must be initialized and - * have a hash operation started. - * \param output The SHA-224 or SHA-256 checksum result. This must be - * a writable buffer of length \c 32 Bytes. - */ -MBEDTLS_DEPRECATED void mbedtls_sha256_finish(mbedtls_sha256_context *ctx, - unsigned char output[32]); - -/** - * \brief This function processes a single data block within - * the ongoing SHA-256 computation. This function is for - * internal use only. - * - * \deprecated Superseded by mbedtls_internal_sha256_process() in 2.7.0. - * - * \param ctx The SHA-256 context. This must be initialized. - * \param data The buffer holding one block of data. This must be - * a readable buffer of size \c 64 Bytes. - */ -MBEDTLS_DEPRECATED void mbedtls_sha256_process(mbedtls_sha256_context *ctx, - const unsigned char data[64]); - -#undef MBEDTLS_DEPRECATED -#endif /* !MBEDTLS_DEPRECATED_REMOVED */ - /** * \brief This function calculates the SHA-224 or SHA-256 * checksum of a buffer. @@ -232,63 +155,41 @@ MBEDTLS_DEPRECATED void mbedtls_sha256_process(mbedtls_sha256_context *ctx, * \param input The buffer holding the data. This must be a readable * buffer of length \p ilen Bytes. * \param ilen The length of the input data in Bytes. - * \param output The SHA-224 or SHA-256 checksum result. This must - * be a writable buffer of length \c 32 Bytes. + * \param output The SHA-224 or SHA-256 checksum result. + * This must be a writable buffer of length \c 32 bytes + * for SHA-256, \c 28 bytes for SHA-224. * \param is224 Determines which function to use. This must be * either \c 0 for SHA-256, or \c 1 for SHA-224. * * \return \c 0 on success. * \return A negative error code on failure. */ -int mbedtls_sha256_ret(const unsigned char *input, - size_t ilen, - unsigned char output[32], - int is224); +int mbedtls_sha256(const unsigned char *input, + size_t ilen, + unsigned char *output, + int is224); -#if !defined(MBEDTLS_DEPRECATED_REMOVED) -#if defined(MBEDTLS_DEPRECATED_WARNING) -#define MBEDTLS_DEPRECATED __attribute__((deprecated)) -#else -#define MBEDTLS_DEPRECATED -#endif +#if defined(MBEDTLS_SELF_TEST) +#if defined(MBEDTLS_SHA224_C) /** - * \brief This function calculates the SHA-224 or SHA-256 checksum - * of a buffer. + * \brief The SHA-224 checkup routine. * - * The function allocates the context, performs the - * calculation, and frees the context. - * - * The SHA-256 result is calculated as - * output = SHA-256(input buffer). - * - * \deprecated Superseded by mbedtls_sha256_ret() in 2.7.0. - * - * \param input The buffer holding the data. This must be a readable - * buffer of length \p ilen Bytes. - * \param ilen The length of the input data in Bytes. - * \param output The SHA-224 or SHA-256 checksum result. This must be - * a writable buffer of length \c 32 Bytes. - * \param is224 Determines which function to use. This must be either - * \c 0 for SHA-256, or \c 1 for SHA-224. + * \return \c 0 on success. + * \return \c 1 on failure. */ -MBEDTLS_DEPRECATED void mbedtls_sha256(const unsigned char *input, - size_t ilen, - unsigned char output[32], - int is224); - -#undef MBEDTLS_DEPRECATED -#endif /* !MBEDTLS_DEPRECATED_REMOVED */ - -#if defined(MBEDTLS_SELF_TEST) +int mbedtls_sha224_self_test(int verbose); +#endif /* MBEDTLS_SHA224_C */ +#if defined(MBEDTLS_SHA256_C) /** - * \brief The SHA-224 and SHA-256 checkup routine. + * \brief The SHA-256 checkup routine. * * \return \c 0 on success. * \return \c 1 on failure. */ int mbedtls_sha256_self_test(int verbose); +#endif /* MBEDTLS_SHA256_C */ #endif /* MBEDTLS_SELF_TEST */ diff --git a/vendor/mbedtls/include/mbedtls/sha3.h b/vendor/mbedtls/include/mbedtls/sha3.h new file mode 100644 index 0000000000..3eeee65e66 --- /dev/null +++ b/vendor/mbedtls/include/mbedtls/sha3.h @@ -0,0 +1,172 @@ +/** + * \file sha3.h + * + * \brief This file contains SHA-3 definitions and functions. + * + * The Secure Hash Algorithms cryptographic + * hash functions are defined in FIPS 202: SHA-3 Standard: + * Permutation-Based Hash and Extendable-Output Functions . + */ +/* + * Copyright The Mbed TLS Contributors + * SPDX-License-Identifier: Apache-2.0 OR GPL-2.0-or-later + */ + +#ifndef MBEDTLS_SHA3_H +#define MBEDTLS_SHA3_H +#include "mbedtls/private_access.h" + +#include "mbedtls/build_info.h" + +#include +#include + +#ifdef __cplusplus +extern "C" { +#endif + +/** SHA-3 input data was malformed. */ +#define MBEDTLS_ERR_SHA3_BAD_INPUT_DATA -0x0076 + +/** + * SHA-3 family id. + * + * It identifies the family (SHA3-256, SHA3-512, etc.) + */ + +typedef enum { + MBEDTLS_SHA3_NONE = 0, /*!< Operation not defined. */ + MBEDTLS_SHA3_224, /*!< SHA3-224 */ + MBEDTLS_SHA3_256, /*!< SHA3-256 */ + MBEDTLS_SHA3_384, /*!< SHA3-384 */ + MBEDTLS_SHA3_512, /*!< SHA3-512 */ +} mbedtls_sha3_id; + +/** + * \brief The SHA-3 context structure. + * + * The structure is used SHA-3 checksum calculations. + */ +typedef struct { + uint64_t MBEDTLS_PRIVATE(state[25]); + uint32_t MBEDTLS_PRIVATE(index); + uint16_t MBEDTLS_PRIVATE(olen); + uint16_t MBEDTLS_PRIVATE(max_block_size); +} +mbedtls_sha3_context; + +/** + * \brief This function initializes a SHA-3 context. + * + * \param ctx The SHA-3 context to initialize. This must not be \c NULL. + */ +void mbedtls_sha3_init(mbedtls_sha3_context *ctx); + +/** + * \brief This function clears a SHA-3 context. + * + * \param ctx The SHA-3 context to clear. This may be \c NULL, in which + * case this function returns immediately. If it is not \c NULL, + * it must point to an initialized SHA-3 context. + */ +void mbedtls_sha3_free(mbedtls_sha3_context *ctx); + +/** + * \brief This function clones the state of a SHA-3 context. + * + * \param dst The destination context. This must be initialized. + * \param src The context to clone. This must be initialized. + */ +void mbedtls_sha3_clone(mbedtls_sha3_context *dst, + const mbedtls_sha3_context *src); + +/** + * \brief This function starts a SHA-3 checksum + * calculation. + * + * \param ctx The context to use. This must be initialized. + * \param id The id of the SHA-3 family. + * + * \return \c 0 on success. + * \return A negative error code on failure. + */ +int mbedtls_sha3_starts(mbedtls_sha3_context *ctx, mbedtls_sha3_id id); + +/** + * \brief This function feeds an input buffer into an ongoing + * SHA-3 checksum calculation. + * + * \param ctx The SHA-3 context. This must be initialized + * and have a hash operation started. + * \param input The buffer holding the data. This must be a readable + * buffer of length \p ilen Bytes. + * \param ilen The length of the input data in Bytes. + * + * \return \c 0 on success. + * \return A negative error code on failure. + */ +int mbedtls_sha3_update(mbedtls_sha3_context *ctx, + const uint8_t *input, + size_t ilen); + +/** + * \brief This function finishes the SHA-3 operation, and writes + * the result to the output buffer. + * + * \param ctx The SHA-3 context. This must be initialized + * and have a hash operation started. + * \param output The SHA-3 checksum result. + * This must be a writable buffer of length \c olen bytes. + * \param olen Defines the length of output buffer (in bytes). For SHA-3 224, SHA-3 256, + * SHA-3 384 and SHA-3 512 \c olen must equal to 28, 32, 48 and 64, + * respectively. + * + * \return \c 0 on success. + * \return A negative error code on failure. + */ +int mbedtls_sha3_finish(mbedtls_sha3_context *ctx, + uint8_t *output, size_t olen); + +/** + * \brief This function calculates the SHA-3 + * checksum of a buffer. + * + * The function allocates the context, performs the + * calculation, and frees the context. + * + * The SHA-3 result is calculated as + * output = SHA-3(id, input buffer, d). + * + * \param id The id of the SHA-3 family. + * \param input The buffer holding the data. This must be a readable + * buffer of length \p ilen Bytes. + * \param ilen The length of the input data in Bytes. + * \param output The SHA-3 checksum result. + * This must be a writable buffer of length \c olen bytes. + * \param olen Defines the length of output buffer (in bytes). For SHA-3 224, SHA-3 256, + * SHA-3 384 and SHA-3 512 \c olen must equal to 28, 32, 48 and 64, + * respectively. + * + * \return \c 0 on success. + * \return A negative error code on failure. + */ +int mbedtls_sha3(mbedtls_sha3_id id, const uint8_t *input, + size_t ilen, + uint8_t *output, + size_t olen); + +#if defined(MBEDTLS_SELF_TEST) +/** + * \brief Checkup routine for the algorithms implemented + * by this module: SHA3-224, SHA3-256, SHA3-384, SHA3-512. + * + * \return 0 if successful, or 1 if the test failed. + */ +int mbedtls_sha3_self_test(int verbose); +#endif /* MBEDTLS_SELF_TEST */ + +#ifdef __cplusplus +} +#endif + +#endif /* mbedtls_sha3.h */ diff --git a/vendor/mbedtls/include/mbedtls/sha512.h b/vendor/mbedtls/include/mbedtls/sha512.h index 1df87f99f7..1c20e4c228 100644 --- a/vendor/mbedtls/include/mbedtls/sha512.h +++ b/vendor/mbedtls/include/mbedtls/sha512.h @@ -7,35 +7,17 @@ */ /* * Copyright The Mbed TLS Contributors - * SPDX-License-Identifier: Apache-2.0 - * - * Licensed under the Apache License, Version 2.0 (the "License"); you may - * not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT - * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. + * SPDX-License-Identifier: Apache-2.0 OR GPL-2.0-or-later */ #ifndef MBEDTLS_SHA512_H #define MBEDTLS_SHA512_H +#include "mbedtls/private_access.h" -#if !defined(MBEDTLS_CONFIG_FILE) -#include "mbedtls/config.h" -#else -#include MBEDTLS_CONFIG_FILE -#endif +#include "mbedtls/build_info.h" #include #include -/* MBEDTLS_ERR_SHA512_HW_ACCEL_FAILED is deprecated and should not be used. */ -/** SHA-512 hardware accelerator failed */ -#define MBEDTLS_ERR_SHA512_HW_ACCEL_FAILED -0x0039 /** SHA-512 input data was malformed. */ #define MBEDTLS_ERR_SHA512_BAD_INPUT_DATA -0x0075 @@ -52,15 +34,15 @@ extern "C" { * * The structure is used both for SHA-384 and for SHA-512 * checksum calculations. The choice between these two is - * made in the call to mbedtls_sha512_starts_ret(). + * made in the call to mbedtls_sha512_starts(). */ typedef struct mbedtls_sha512_context { - uint64_t total[2]; /*!< The number of Bytes processed. */ - uint64_t state[8]; /*!< The intermediate digest state. */ - unsigned char buffer[128]; /*!< The data block being processed. */ -#if !defined(MBEDTLS_SHA512_NO_SHA384) - int is384; /*!< Determines which function to use: - 0: Use SHA-512, or 1: Use SHA-384. */ + uint64_t MBEDTLS_PRIVATE(total)[2]; /*!< The number of Bytes processed. */ + uint64_t MBEDTLS_PRIVATE(state)[8]; /*!< The intermediate digest state. */ + unsigned char MBEDTLS_PRIVATE(buffer)[128]; /*!< The data block being processed. */ +#if defined(MBEDTLS_SHA384_C) + int MBEDTLS_PRIVATE(is384); /*!< Determines which function to use: + 0: Use SHA-512, or 1: Use SHA-384. */ #endif } mbedtls_sha512_context; @@ -104,14 +86,14 @@ void mbedtls_sha512_clone(mbedtls_sha512_context *dst, * \param is384 Determines which function to use. This must be * either \c 0 for SHA-512, or \c 1 for SHA-384. * - * \note When \c MBEDTLS_SHA512_NO_SHA384 is defined, \p is384 must - * be \c 0, or the function will return - * #MBEDTLS_ERR_SHA512_BAD_INPUT_DATA. + * \note is384 must be defined accordingly to the enabled + * MBEDTLS_SHA384_C/MBEDTLS_SHA512_C symbols otherwise the + * function will return #MBEDTLS_ERR_SHA512_BAD_INPUT_DATA. * * \return \c 0 on success. * \return A negative error code on failure. */ -int mbedtls_sha512_starts_ret(mbedtls_sha512_context *ctx, int is384); +int mbedtls_sha512_starts(mbedtls_sha512_context *ctx, int is384); /** * \brief This function feeds an input buffer into an ongoing @@ -126,9 +108,9 @@ int mbedtls_sha512_starts_ret(mbedtls_sha512_context *ctx, int is384); * \return \c 0 on success. * \return A negative error code on failure. */ -int mbedtls_sha512_update_ret(mbedtls_sha512_context *ctx, - const unsigned char *input, - size_t ilen); +int mbedtls_sha512_update(mbedtls_sha512_context *ctx, + const unsigned char *input, + size_t ilen); /** * \brief This function finishes the SHA-512 operation, and writes @@ -137,13 +119,14 @@ int mbedtls_sha512_update_ret(mbedtls_sha512_context *ctx, * \param ctx The SHA-512 context. This must be initialized * and have a hash operation started. * \param output The SHA-384 or SHA-512 checksum result. - * This must be a writable buffer of length \c 64 Bytes. + * This must be a writable buffer of length \c 64 bytes + * for SHA-512, \c 48 bytes for SHA-384. * * \return \c 0 on success. * \return A negative error code on failure. */ -int mbedtls_sha512_finish_ret(mbedtls_sha512_context *ctx, - unsigned char output[64]); +int mbedtls_sha512_finish(mbedtls_sha512_context *ctx, + unsigned char *output); /** * \brief This function processes a single data block within @@ -159,75 +142,6 @@ int mbedtls_sha512_finish_ret(mbedtls_sha512_context *ctx, */ int mbedtls_internal_sha512_process(mbedtls_sha512_context *ctx, const unsigned char data[128]); -#if !defined(MBEDTLS_DEPRECATED_REMOVED) -#if defined(MBEDTLS_DEPRECATED_WARNING) -#define MBEDTLS_DEPRECATED __attribute__((deprecated)) -#else -#define MBEDTLS_DEPRECATED -#endif -/** - * \brief This function starts a SHA-384 or SHA-512 checksum - * calculation. - * - * \deprecated Superseded by mbedtls_sha512_starts_ret() in 2.7.0 - * - * \param ctx The SHA-512 context to use. This must be initialized. - * \param is384 Determines which function to use. This must be either - * \c 0 for SHA-512 or \c 1 for SHA-384. - * - * \note When \c MBEDTLS_SHA512_NO_SHA384 is defined, \p is384 must - * be \c 0, or the function will fail to work. - */ -MBEDTLS_DEPRECATED void mbedtls_sha512_starts(mbedtls_sha512_context *ctx, - int is384); - -/** - * \brief This function feeds an input buffer into an ongoing - * SHA-512 checksum calculation. - * - * \deprecated Superseded by mbedtls_sha512_update_ret() in 2.7.0. - * - * \param ctx The SHA-512 context. This must be initialized - * and have a hash operation started. - * \param input The buffer holding the data. This must be a readable - * buffer of length \p ilen Bytes. - * \param ilen The length of the input data in Bytes. - */ -MBEDTLS_DEPRECATED void mbedtls_sha512_update(mbedtls_sha512_context *ctx, - const unsigned char *input, - size_t ilen); - -/** - * \brief This function finishes the SHA-512 operation, and writes - * the result to the output buffer. - * - * \deprecated Superseded by mbedtls_sha512_finish_ret() in 2.7.0. - * - * \param ctx The SHA-512 context. This must be initialized - * and have a hash operation started. - * \param output The SHA-384 or SHA-512 checksum result. This must - * be a writable buffer of size \c 64 Bytes. - */ -MBEDTLS_DEPRECATED void mbedtls_sha512_finish(mbedtls_sha512_context *ctx, - unsigned char output[64]); - -/** - * \brief This function processes a single data block within - * the ongoing SHA-512 computation. This function is for - * internal use only. - * - * \deprecated Superseded by mbedtls_internal_sha512_process() in 2.7.0. - * - * \param ctx The SHA-512 context. This must be initialized. - * \param data The buffer holding one block of data. This must be - * a readable buffer of length \c 128 Bytes. - */ -MBEDTLS_DEPRECATED void mbedtls_sha512_process( - mbedtls_sha512_context *ctx, - const unsigned char data[128]); - -#undef MBEDTLS_DEPRECATED -#endif /* !MBEDTLS_DEPRECATED_REMOVED */ /** * \brief This function calculates the SHA-512 or SHA-384 @@ -243,69 +157,48 @@ MBEDTLS_DEPRECATED void mbedtls_sha512_process( * a readable buffer of length \p ilen Bytes. * \param ilen The length of the input data in Bytes. * \param output The SHA-384 or SHA-512 checksum result. - * This must be a writable buffer of length \c 64 Bytes. + * This must be a writable buffer of length \c 64 bytes + * for SHA-512, \c 48 bytes for SHA-384. * \param is384 Determines which function to use. This must be either * \c 0 for SHA-512, or \c 1 for SHA-384. * - * \note When \c MBEDTLS_SHA512_NO_SHA384 is defined, \p is384 must - * be \c 0, or the function will return + * \note is384 must be defined accordingly with the supported + * symbols in the config file. If: + * - is384 is 0, but \c MBEDTLS_SHA384_C is not defined, or + * - is384 is 1, but \c MBEDTLS_SHA512_C is not defined + * then the function will return * #MBEDTLS_ERR_SHA512_BAD_INPUT_DATA. * * \return \c 0 on success. * \return A negative error code on failure. */ -int mbedtls_sha512_ret(const unsigned char *input, - size_t ilen, - unsigned char output[64], - int is384); +int mbedtls_sha512(const unsigned char *input, + size_t ilen, + unsigned char *output, + int is384); -#if !defined(MBEDTLS_DEPRECATED_REMOVED) -#if defined(MBEDTLS_DEPRECATED_WARNING) -#define MBEDTLS_DEPRECATED __attribute__((deprecated)) -#else -#define MBEDTLS_DEPRECATED -#endif +#if defined(MBEDTLS_SELF_TEST) +#if defined(MBEDTLS_SHA384_C) /** - * \brief This function calculates the SHA-512 or SHA-384 - * checksum of a buffer. + * \brief The SHA-384 checkup routine. * - * The function allocates the context, performs the - * calculation, and frees the context. - * - * The SHA-512 result is calculated as - * output = SHA-512(input buffer). - * - * \deprecated Superseded by mbedtls_sha512_ret() in 2.7.0 - * - * \param input The buffer holding the data. This must be a - * readable buffer of length \p ilen Bytes. - * \param ilen The length of the input data in Bytes. - * \param output The SHA-384 or SHA-512 checksum result. This must - * be a writable buffer of length \c 64 Bytes. - * \param is384 Determines which function to use. This must be either - * \c 0 for SHA-512, or \c 1 for SHA-384. - * - * \note When \c MBEDTLS_SHA512_NO_SHA384 is defined, \p is384 must - * be \c 0, or the function will fail to work. + * \return \c 0 on success. + * \return \c 1 on failure. */ -MBEDTLS_DEPRECATED void mbedtls_sha512(const unsigned char *input, - size_t ilen, - unsigned char output[64], - int is384); - -#undef MBEDTLS_DEPRECATED -#endif /* !MBEDTLS_DEPRECATED_REMOVED */ - -#if defined(MBEDTLS_SELF_TEST) +int mbedtls_sha384_self_test(int verbose); +#endif /* MBEDTLS_SHA384_C */ +#if defined(MBEDTLS_SHA512_C) /** - * \brief The SHA-384 or SHA-512 checkup routine. + * \brief The SHA-512 checkup routine. * * \return \c 0 on success. * \return \c 1 on failure. */ int mbedtls_sha512_self_test(int verbose); +#endif /* MBEDTLS_SHA512_C */ + #endif /* MBEDTLS_SELF_TEST */ #ifdef __cplusplus diff --git a/vendor/mbedtls/include/mbedtls/ssl.h b/vendor/mbedtls/include/mbedtls/ssl.h index 3ec558b4f2..172d4693b2 100644 --- a/vendor/mbedtls/include/mbedtls/ssl.h +++ b/vendor/mbedtls/include/mbedtls/ssl.h @@ -5,28 +5,14 @@ */ /* * Copyright The Mbed TLS Contributors - * SPDX-License-Identifier: Apache-2.0 - * - * Licensed under the Apache License, Version 2.0 (the "License"); you may - * not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT - * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. + * SPDX-License-Identifier: Apache-2.0 OR GPL-2.0-or-later */ #ifndef MBEDTLS_SSL_H #define MBEDTLS_SSL_H +#include "mbedtls/platform_util.h" +#include "mbedtls/private_access.h" -#if !defined(MBEDTLS_CONFIG_FILE) -#include "mbedtls/config.h" -#else -#include MBEDTLS_CONFIG_FILE -#endif +#include "mbedtls/build_info.h" #include "mbedtls/bignum.h" #include "mbedtls/ecp.h" @@ -42,41 +28,23 @@ #include "mbedtls/dhm.h" #endif -/* Adding guard for MBEDTLS_ECDSA_C to ensure no compile errors due - * to guards also being in ssl_srv.c and ssl_cli.c. There is a gap - * in functionality that access to ecdh_ctx structure is needed for - * MBEDTLS_ECDSA_C which does not seem correct. - */ -#if defined(MBEDTLS_ECDH_C) || defined(MBEDTLS_ECDSA_C) -#include "mbedtls/ecdh.h" -#endif - -#if defined(MBEDTLS_ZLIB_SUPPORT) - -#if defined(MBEDTLS_DEPRECATED_WARNING) -#warning \ - "Record compression support via MBEDTLS_ZLIB_SUPPORT is deprecated and will be removed in the next major revision of the library" -#endif - -#if defined(MBEDTLS_DEPRECATED_REMOVED) -#error \ - "Record compression support via MBEDTLS_ZLIB_SUPPORT is deprecated and cannot be used if MBEDTLS_DEPRECATED_REMOVED is set" -#endif +#include "mbedtls/md.h" -#include "zlib.h" +#if defined(MBEDTLS_KEY_EXCHANGE_SOME_ECDH_OR_ECDHE_ANY_ENABLED) +#include "mbedtls/ecdh.h" #endif #if defined(MBEDTLS_HAVE_TIME) #include "mbedtls/platform_time.h" #endif -#if defined(MBEDTLS_USE_PSA_CRYPTO) #include "psa/crypto.h" -#endif /* MBEDTLS_USE_PSA_CRYPTO */ /* * SSL Error codes */ +/** A cryptographic operation is in progress. Try again later. */ +#define MBEDTLS_ERR_SSL_CRYPTO_IN_PROGRESS -0x7000 /** The requested feature is not available. */ #define MBEDTLS_ERR_SSL_FEATURE_UNAVAILABLE -0x7080 /** Bad input parameters to function. */ @@ -87,18 +55,17 @@ #define MBEDTLS_ERR_SSL_INVALID_RECORD -0x7200 /** The connection indicated an EOF. */ #define MBEDTLS_ERR_SSL_CONN_EOF -0x7280 -/** An unknown cipher was received. */ -#define MBEDTLS_ERR_SSL_UNKNOWN_CIPHER -0x7300 -/** The server has no ciphersuites in common with the client. */ -#define MBEDTLS_ERR_SSL_NO_CIPHER_CHOSEN -0x7380 +/** A message could not be parsed due to a syntactic error. */ +#define MBEDTLS_ERR_SSL_DECODE_ERROR -0x7300 +/* Error space gap */ /** No RNG was provided to the SSL module. */ #define MBEDTLS_ERR_SSL_NO_RNG -0x7400 /** No client certification received from the client, but required by the authentication mode. */ #define MBEDTLS_ERR_SSL_NO_CLIENT_CERTIFICATE -0x7480 -/** Our own certificate(s) is/are too large to send in an SSL message. */ -#define MBEDTLS_ERR_SSL_CERTIFICATE_TOO_LARGE -0x7500 -/** The own certificate is not set, but needed by the server. */ -#define MBEDTLS_ERR_SSL_CERTIFICATE_REQUIRED -0x7580 +/** Client received an extended server hello containing an unsupported extension */ +#define MBEDTLS_ERR_SSL_UNSUPPORTED_EXTENSION -0x7500 +/** No ALPN protocols supported that the client advertises */ +#define MBEDTLS_ERR_SSL_NO_APPLICATION_PROTOCOL -0x7580 /** The own private key or pre-shared key is not set, but needed. */ #define MBEDTLS_ERR_SSL_PRIVATE_KEY_REQUIRED -0x7600 /** No CA Chain is set, but required to operate. */ @@ -107,46 +74,50 @@ #define MBEDTLS_ERR_SSL_UNEXPECTED_MESSAGE -0x7700 /** A fatal alert message was received from our peer. */ #define MBEDTLS_ERR_SSL_FATAL_ALERT_MESSAGE -0x7780 -/** Verification of our peer failed. */ -#define MBEDTLS_ERR_SSL_PEER_VERIFY_FAILED -0x7800 +/** No server could be identified matching the client's SNI. */ +#define MBEDTLS_ERR_SSL_UNRECOGNIZED_NAME -0x7800 /** The peer notified us that the connection is going to be closed. */ #define MBEDTLS_ERR_SSL_PEER_CLOSE_NOTIFY -0x7880 -/** Processing of the ClientHello handshake message failed. */ -#define MBEDTLS_ERR_SSL_BAD_HS_CLIENT_HELLO -0x7900 -/** Processing of the ServerHello handshake message failed. */ -#define MBEDTLS_ERR_SSL_BAD_HS_SERVER_HELLO -0x7980 +/* Error space gap */ +/* Error space gap */ /** Processing of the Certificate handshake message failed. */ -#define MBEDTLS_ERR_SSL_BAD_HS_CERTIFICATE -0x7A00 -/** Processing of the CertificateRequest handshake message failed. */ -#define MBEDTLS_ERR_SSL_BAD_HS_CERTIFICATE_REQUEST -0x7A80 -/** Processing of the ServerKeyExchange handshake message failed. */ -#define MBEDTLS_ERR_SSL_BAD_HS_SERVER_KEY_EXCHANGE -0x7B00 -/** Processing of the ServerHelloDone handshake message failed. */ -#define MBEDTLS_ERR_SSL_BAD_HS_SERVER_HELLO_DONE -0x7B80 -/** Processing of the ClientKeyExchange handshake message failed. */ -#define MBEDTLS_ERR_SSL_BAD_HS_CLIENT_KEY_EXCHANGE -0x7C00 -/** Processing of the ClientKeyExchange handshake message failed in DHM / ECDH Read Public. */ -#define MBEDTLS_ERR_SSL_BAD_HS_CLIENT_KEY_EXCHANGE_RP -0x7C80 -/** Processing of the ClientKeyExchange handshake message failed in DHM / ECDH Calculate Secret. */ -#define MBEDTLS_ERR_SSL_BAD_HS_CLIENT_KEY_EXCHANGE_CS -0x7D00 -/** Processing of the CertificateVerify handshake message failed. */ -#define MBEDTLS_ERR_SSL_BAD_HS_CERTIFICATE_VERIFY -0x7D80 -/** Processing of the ChangeCipherSpec handshake message failed. */ -#define MBEDTLS_ERR_SSL_BAD_HS_CHANGE_CIPHER_SPEC -0x7E00 -/** Processing of the Finished handshake message failed. */ -#define MBEDTLS_ERR_SSL_BAD_HS_FINISHED -0x7E80 +#define MBEDTLS_ERR_SSL_BAD_CERTIFICATE -0x7A00 +/* Error space gap */ +/** + * Received NewSessionTicket Post Handshake Message. + * This error code is experimental and may be changed or removed without notice. + */ +#define MBEDTLS_ERR_SSL_RECEIVED_NEW_SESSION_TICKET -0x7B00 +/** Not possible to read early data */ +#define MBEDTLS_ERR_SSL_CANNOT_READ_EARLY_DATA -0x7B80 +/** + * Early data has been received as part of an on-going handshake. + * This error code can be returned only on server side if and only if early + * data has been enabled by means of the mbedtls_ssl_conf_early_data() API. + * This error code can then be returned by mbedtls_ssl_handshake(), + * mbedtls_ssl_handshake_step(), mbedtls_ssl_read() or mbedtls_ssl_write() if + * early data has been received as part of the handshake sequence they + * triggered. To read the early data, call mbedtls_ssl_read_early_data(). + */ +#define MBEDTLS_ERR_SSL_RECEIVED_EARLY_DATA -0x7C00 +/** Not possible to write early data */ +#define MBEDTLS_ERR_SSL_CANNOT_WRITE_EARLY_DATA -0x7C80 +/* Error space gap */ +/* Error space gap */ +/* Error space gap */ +/* Error space gap */ +/** Cache entry not found */ +#define MBEDTLS_ERR_SSL_CACHE_ENTRY_NOT_FOUND -0x7E80 /** Memory allocation failed */ #define MBEDTLS_ERR_SSL_ALLOC_FAILED -0x7F00 /** Hardware acceleration function returned with error */ #define MBEDTLS_ERR_SSL_HW_ACCEL_FAILED -0x7F80 /** Hardware acceleration function skipped / left alone data */ #define MBEDTLS_ERR_SSL_HW_ACCEL_FALLTHROUGH -0x6F80 -/** Processing of the compression / decompression failed */ -#define MBEDTLS_ERR_SSL_COMPRESSION_FAILED -0x6F00 /** Handshake protocol not within min/max boundaries */ -#define MBEDTLS_ERR_SSL_BAD_HS_PROTOCOL_VERSION -0x6E80 -/** Processing of the NewSessionTicket handshake message failed. */ -#define MBEDTLS_ERR_SSL_BAD_HS_NEW_SESSION_TICKET -0x6E00 +#define MBEDTLS_ERR_SSL_BAD_PROTOCOL_VERSION -0x6E80 +/** The handshake negotiation failed. */ +#define MBEDTLS_ERR_SSL_HANDSHAKE_FAILURE -0x6E00 /** Session ticket has expired. */ #define MBEDTLS_ERR_SSL_SESSION_TICKET_EXPIRED -0x6D80 /** Public key type mismatch (eg, asked for RSA key exchange and presented EC key) */ @@ -163,8 +134,7 @@ #define MBEDTLS_ERR_SSL_HELLO_VERIFY_REQUIRED -0x6A80 /** A buffer is too small to receive or write a message */ #define MBEDTLS_ERR_SSL_BUFFER_TOO_SMALL -0x6A00 -/** None of the common ciphersuites is usable (eg, no suitable certificate, see debug messages). */ -#define MBEDTLS_ERR_SSL_NO_USABLE_CIPHERSUITE -0x6980 +/* Error space gap */ /** No data of requested type currently available on underlying transport. */ #define MBEDTLS_ERR_SSL_WANT_READ -0x6900 /** Connection requires a write call. */ @@ -177,34 +147,123 @@ #define MBEDTLS_ERR_SSL_UNEXPECTED_RECORD -0x6700 /** The alert message received indicates a non-fatal error. */ #define MBEDTLS_ERR_SSL_NON_FATAL -0x6680 -/** Couldn't set the hash for verifying CertificateVerify */ -#define MBEDTLS_ERR_SSL_INVALID_VERIFY_HASH -0x6600 +/** A field in a message was incorrect or inconsistent with other fields. */ +#define MBEDTLS_ERR_SSL_ILLEGAL_PARAMETER -0x6600 /** Internal-only message signaling that further message-processing should be done */ #define MBEDTLS_ERR_SSL_CONTINUE_PROCESSING -0x6580 /** The asynchronous operation is not completed yet. */ #define MBEDTLS_ERR_SSL_ASYNC_IN_PROGRESS -0x6500 /** Internal-only message signaling that a message arrived early. */ #define MBEDTLS_ERR_SSL_EARLY_MESSAGE -0x6480 +/* Error space gap */ +/* Error space gap */ +/* Error space gap */ +/* Error space gap */ +/* Error space gap */ +/* Error space gap */ +/* Error space gap */ +/* Error space gap */ /** An encrypted DTLS-frame with an unexpected CID was received. */ #define MBEDTLS_ERR_SSL_UNEXPECTED_CID -0x6000 /** An operation failed due to an unexpected version or configuration. */ #define MBEDTLS_ERR_SSL_VERSION_MISMATCH -0x5F00 -/** A cryptographic operation is in progress. Try again later. */ -#define MBEDTLS_ERR_SSL_CRYPTO_IN_PROGRESS -0x7000 /** Invalid value in SSL config */ #define MBEDTLS_ERR_SSL_BAD_CONFIG -0x5E80 -/** Cache entry not found */ -#define MBEDTLS_ERR_SSL_CACHE_ENTRY_NOT_FOUND -0x5E00 + +/* + * Constants from RFC 8446 for TLS 1.3 PSK modes + * + * Those are used in the Pre-Shared Key Exchange Modes extension. + * See Section 4.2.9 in RFC 8446. + */ +#define MBEDTLS_SSL_TLS1_3_PSK_MODE_PURE 0 /* Pure PSK-based exchange */ +#define MBEDTLS_SSL_TLS1_3_PSK_MODE_ECDHE 1 /* PSK+ECDHE-based exchange */ + +/* + * TLS 1.3 NamedGroup values + * + * From RF 8446 + * enum { + * // Elliptic Curve Groups (ECDHE) + * secp256r1(0x0017), secp384r1(0x0018), secp521r1(0x0019), + * x25519(0x001D), x448(0x001E), + * // Finite Field Groups (DHE) + * ffdhe2048(0x0100), ffdhe3072(0x0101), ffdhe4096(0x0102), + * ffdhe6144(0x0103), ffdhe8192(0x0104), + * // Reserved Code Points + * ffdhe_private_use(0x01FC..0x01FF), + * ecdhe_private_use(0xFE00..0xFEFF), + * (0xFFFF) + * } NamedGroup; + * + */ + +/* Elliptic Curve Groups (ECDHE) */ +#define MBEDTLS_SSL_IANA_TLS_GROUP_NONE 0 +#define MBEDTLS_SSL_IANA_TLS_GROUP_SECP192K1 0x0012 +#define MBEDTLS_SSL_IANA_TLS_GROUP_SECP192R1 0x0013 +#define MBEDTLS_SSL_IANA_TLS_GROUP_SECP224K1 0x0014 +#define MBEDTLS_SSL_IANA_TLS_GROUP_SECP224R1 0x0015 +#define MBEDTLS_SSL_IANA_TLS_GROUP_SECP256K1 0x0016 +#define MBEDTLS_SSL_IANA_TLS_GROUP_SECP256R1 0x0017 +#define MBEDTLS_SSL_IANA_TLS_GROUP_SECP384R1 0x0018 +#define MBEDTLS_SSL_IANA_TLS_GROUP_SECP521R1 0x0019 +#define MBEDTLS_SSL_IANA_TLS_GROUP_BP256R1 0x001A +#define MBEDTLS_SSL_IANA_TLS_GROUP_BP384R1 0x001B +#define MBEDTLS_SSL_IANA_TLS_GROUP_BP512R1 0x001C +#define MBEDTLS_SSL_IANA_TLS_GROUP_X25519 0x001D +#define MBEDTLS_SSL_IANA_TLS_GROUP_X448 0x001E +/* Finite Field Groups (DHE) */ +#define MBEDTLS_SSL_IANA_TLS_GROUP_FFDHE2048 0x0100 +#define MBEDTLS_SSL_IANA_TLS_GROUP_FFDHE3072 0x0101 +#define MBEDTLS_SSL_IANA_TLS_GROUP_FFDHE4096 0x0102 +#define MBEDTLS_SSL_IANA_TLS_GROUP_FFDHE6144 0x0103 +#define MBEDTLS_SSL_IANA_TLS_GROUP_FFDHE8192 0x0104 + +/* + * TLS 1.3 Key Exchange Modes + * + * Mbed TLS internal identifiers for use with the SSL configuration API + * mbedtls_ssl_conf_tls13_key_exchange_modes(). + */ + +#define MBEDTLS_SSL_TLS1_3_KEY_EXCHANGE_MODE_PSK (1u << 0) /*!< Pure-PSK TLS 1.3 key exchange, + * encompassing both externally agreed PSKs + * as well as resumption PSKs. */ +#define MBEDTLS_SSL_TLS1_3_KEY_EXCHANGE_MODE_EPHEMERAL (1u << 1) /*!< Pure-Ephemeral TLS 1.3 key exchanges, + * including for example ECDHE and DHE + * key exchanges. */ +#define MBEDTLS_SSL_TLS1_3_KEY_EXCHANGE_MODE_PSK_EPHEMERAL (1u << 2) /*!< PSK-Ephemeral TLS 1.3 key exchanges, + * using both a PSK and an ephemeral + * key exchange. */ + +/* Convenience macros for sets of key exchanges. */ +#define MBEDTLS_SSL_TLS1_3_KEY_EXCHANGE_MODE_ALL \ + (MBEDTLS_SSL_TLS1_3_KEY_EXCHANGE_MODE_PSK | \ + MBEDTLS_SSL_TLS1_3_KEY_EXCHANGE_MODE_PSK_EPHEMERAL | \ + MBEDTLS_SSL_TLS1_3_KEY_EXCHANGE_MODE_EPHEMERAL) /*!< All TLS 1.3 key exchanges */ +#define MBEDTLS_SSL_TLS1_3_KEY_EXCHANGE_MODE_PSK_ALL \ + (MBEDTLS_SSL_TLS1_3_KEY_EXCHANGE_MODE_PSK | \ + MBEDTLS_SSL_TLS1_3_KEY_EXCHANGE_MODE_PSK_EPHEMERAL) /*!< All PSK-based TLS 1.3 key exchanges */ +#define MBEDTLS_SSL_TLS1_3_KEY_EXCHANGE_MODE_EPHEMERAL_ALL \ + (MBEDTLS_SSL_TLS1_3_KEY_EXCHANGE_MODE_EPHEMERAL | \ + MBEDTLS_SSL_TLS1_3_KEY_EXCHANGE_MODE_PSK_EPHEMERAL) /*!< All ephemeral TLS 1.3 key exchanges */ + +#define MBEDTLS_SSL_TLS1_3_KEY_EXCHANGE_MODE_NONE (0) /* * Various constants */ + +#if !defined(MBEDTLS_DEPRECATED_REMOVED) +/* These are the high and low bytes of ProtocolVersion as defined by: + * - RFC 5246: ProtocolVersion version = { 3, 3 }; // TLS v1.2 + * - RFC 8446: see section 4.2.1 + */ #define MBEDTLS_SSL_MAJOR_VERSION_3 3 -#define MBEDTLS_SSL_MINOR_VERSION_0 0 /*!< SSL v3.0 */ -#define MBEDTLS_SSL_MINOR_VERSION_1 1 /*!< TLS v1.0 */ -#define MBEDTLS_SSL_MINOR_VERSION_2 2 /*!< TLS v1.1 */ #define MBEDTLS_SSL_MINOR_VERSION_3 3 /*!< TLS v1.2 */ -#define MBEDTLS_SSL_MINOR_VERSION_4 4 /*!< TLS v1.3 (experimental) */ +#define MBEDTLS_SSL_MINOR_VERSION_4 4 /*!< TLS v1.3 */ +#endif /* MBEDTLS_DEPRECATED_REMOVED */ #define MBEDTLS_SSL_TRANSPORT_STREAM 0 /*!< TLS */ #define MBEDTLS_SSL_TRANSPORT_DATAGRAM 1 /*!< DTLS */ @@ -226,9 +285,6 @@ #define MBEDTLS_SSL_IS_CLIENT 0 #define MBEDTLS_SSL_IS_SERVER 1 -#define MBEDTLS_SSL_IS_NOT_FALLBACK 0 -#define MBEDTLS_SSL_IS_FALLBACK 1 - #define MBEDTLS_SSL_EXTENDED_MS_DISABLED 0 #define MBEDTLS_SSL_EXTENDED_MS_ENABLED 1 @@ -239,7 +295,6 @@ #define MBEDTLS_SSL_ETM_ENABLED 1 #define MBEDTLS_SSL_COMPRESS_NULL 0 -#define MBEDTLS_SSL_COMPRESS_DEFLATE 1 #define MBEDTLS_SSL_VERIFY_NONE 0 #define MBEDTLS_SSL_VERIFY_OPTIONAL 1 @@ -269,21 +324,28 @@ #define MBEDTLS_SSL_SESSION_TICKETS_DISABLED 0 #define MBEDTLS_SSL_SESSION_TICKETS_ENABLED 1 -#define MBEDTLS_SSL_CBC_RECORD_SPLITTING_DISABLED 0 -#define MBEDTLS_SSL_CBC_RECORD_SPLITTING_ENABLED 1 - -#define MBEDTLS_SSL_ARC4_ENABLED 0 -#define MBEDTLS_SSL_ARC4_DISABLED 1 - #define MBEDTLS_SSL_PRESET_DEFAULT 0 #define MBEDTLS_SSL_PRESET_SUITEB 2 #define MBEDTLS_SSL_CERT_REQ_CA_LIST_ENABLED 1 #define MBEDTLS_SSL_CERT_REQ_CA_LIST_DISABLED 0 +#define MBEDTLS_SSL_EARLY_DATA_DISABLED 0 +#define MBEDTLS_SSL_EARLY_DATA_ENABLED 1 + #define MBEDTLS_SSL_DTLS_SRTP_MKI_UNSUPPORTED 0 #define MBEDTLS_SSL_DTLS_SRTP_MKI_SUPPORTED 1 +#define MBEDTLS_SSL_SRV_CIPHERSUITE_ORDER_CLIENT 1 +#define MBEDTLS_SSL_SRV_CIPHERSUITE_ORDER_SERVER 0 + +#if defined(MBEDTLS_SSL_PROTO_TLS1_3) && defined(MBEDTLS_SSL_SESSION_TICKETS) +#if defined(PSA_WANT_ALG_SHA_384) +#define MBEDTLS_SSL_TLS1_3_TICKET_RESUMPTION_KEY_LEN 48 +#elif defined(PSA_WANT_ALG_SHA_256) +#define MBEDTLS_SSL_TLS1_3_TICKET_RESUMPTION_KEY_LEN 32 +#endif +#endif /* MBEDTLS_SSL_PROTO_TLS1_3 && MBEDTLS_SSL_SESSION_TICKETS */ /* * Default range for DTLS retransmission timer value, in milliseconds. * RFC 6347 4.2.4.1 says from 1 second to 60 seconds. @@ -291,18 +353,34 @@ #define MBEDTLS_SSL_DTLS_TIMEOUT_DFL_MIN 1000 #define MBEDTLS_SSL_DTLS_TIMEOUT_DFL_MAX 60000 +/* + * Whether early data record should be discarded or not and how. + * + * The client has indicated early data and the server has rejected them. + * The server has then to skip past early data by either: + * - attempting to deprotect received records using the handshake traffic + * key, discarding records which fail deprotection (up to the configured + * max_early_data_size). Once a record is deprotected successfully, + * it is treated as the start of the client's second flight and the + * server proceeds as with an ordinary 1-RTT handshake. + * - skipping all records with an external content type of + * "application_data" (indicating that they are encrypted), up to the + * configured max_early_data_size. This is the expected behavior if the + * server has sent an HelloRetryRequest message. The server ignores + * application data message before 2nd ClientHello. + */ +#define MBEDTLS_SSL_EARLY_DATA_NO_DISCARD 0 +#define MBEDTLS_SSL_EARLY_DATA_TRY_TO_DEPROTECT_AND_DISCARD 1 +#define MBEDTLS_SSL_EARLY_DATA_DISCARD 2 + /** * \name SECTION: Module settings * * The configuration options you can set for this module are in this section. - * Either change them in config.h or define them on the compiler command line. + * Either change them in mbedtls_config.h or define them on the compiler command line. * \{ */ -#if !defined(MBEDTLS_SSL_DEFAULT_TICKET_LIFETIME) -#define MBEDTLS_SSL_DEFAULT_TICKET_LIFETIME 86400 /**< Lifetime of session tickets (if enabled) */ -#endif - /* * Maximum fragment length in bytes, * determines the size of each of the two internal I/O buffers. @@ -314,16 +392,12 @@ * if you're using the Max Fragment Length extension and you know all your * peers are using it too! */ -#if !defined(MBEDTLS_SSL_MAX_CONTENT_LEN) -#define MBEDTLS_SSL_MAX_CONTENT_LEN 16384 /**< Size of the input / output buffer */ -#endif - #if !defined(MBEDTLS_SSL_IN_CONTENT_LEN) -#define MBEDTLS_SSL_IN_CONTENT_LEN MBEDTLS_SSL_MAX_CONTENT_LEN +#define MBEDTLS_SSL_IN_CONTENT_LEN 16384 #endif #if !defined(MBEDTLS_SSL_OUT_CONTENT_LEN) -#define MBEDTLS_SSL_OUT_CONTENT_LEN MBEDTLS_SSL_MAX_CONTENT_LEN +#define MBEDTLS_SSL_OUT_CONTENT_LEN 16384 #endif /* @@ -345,30 +419,45 @@ #define MBEDTLS_SSL_CID_OUT_LEN_MAX 32 #endif -#if !defined(MBEDTLS_SSL_CID_PADDING_GRANULARITY) -#define MBEDTLS_SSL_CID_PADDING_GRANULARITY 16 +#if !defined(MBEDTLS_SSL_CID_TLS1_3_PADDING_GRANULARITY) +#define MBEDTLS_SSL_CID_TLS1_3_PADDING_GRANULARITY 16 +#endif + +#if !defined(MBEDTLS_SSL_MAX_EARLY_DATA_SIZE) +#define MBEDTLS_SSL_MAX_EARLY_DATA_SIZE 1024 #endif -#if !defined(MBEDTLS_SSL_TLS1_3_PADDING_GRANULARITY) -#define MBEDTLS_SSL_TLS1_3_PADDING_GRANULARITY 1 +#if !defined(MBEDTLS_SSL_TLS1_3_TICKET_AGE_TOLERANCE) +#define MBEDTLS_SSL_TLS1_3_TICKET_AGE_TOLERANCE 6000 +#endif + +#if !defined(MBEDTLS_SSL_TLS1_3_TICKET_NONCE_LENGTH) +#define MBEDTLS_SSL_TLS1_3_TICKET_NONCE_LENGTH 32 +#endif + +#if !defined(MBEDTLS_SSL_TLS1_3_DEFAULT_NEW_SESSION_TICKETS) +#define MBEDTLS_SSL_TLS1_3_DEFAULT_NEW_SESSION_TICKETS 1 #endif /** \} name SECTION: Module settings */ +/* + * Default to standard CID mode + */ +#if defined(MBEDTLS_SSL_DTLS_CONNECTION_ID) && \ + !defined(MBEDTLS_SSL_DTLS_CONNECTION_ID_COMPAT) +#define MBEDTLS_SSL_DTLS_CONNECTION_ID_COMPAT 0 +#endif + /* * Length of the verify data for secure renegotiation */ -#if defined(MBEDTLS_SSL_PROTO_SSL3) -#define MBEDTLS_SSL_VERIFY_DATA_MAX_LEN 36 -#else #define MBEDTLS_SSL_VERIFY_DATA_MAX_LEN 12 -#endif /* * Signaling ciphersuite values (SCSV) */ #define MBEDTLS_SSL_EMPTY_RENEGOTIATION_INFO 0xFF /**< renegotiation info ext */ -#define MBEDTLS_SSL_FALLBACK_SCSV_VALUE 0x5600 /**< RFC 7507 section 2 */ /* * Supported Signature and Hash algorithms (For TLS 1.2) @@ -386,6 +475,41 @@ #define MBEDTLS_SSL_SIG_RSA 1 #define MBEDTLS_SSL_SIG_ECDSA 3 +/* + * TLS 1.3 signature algorithms + * RFC 8446, Section 4.2.3 + */ + +/* RSASSA-PKCS1-v1_5 algorithms */ +#define MBEDTLS_TLS1_3_SIG_RSA_PKCS1_SHA256 0x0401 +#define MBEDTLS_TLS1_3_SIG_RSA_PKCS1_SHA384 0x0501 +#define MBEDTLS_TLS1_3_SIG_RSA_PKCS1_SHA512 0x0601 + +/* ECDSA algorithms */ +#define MBEDTLS_TLS1_3_SIG_ECDSA_SECP256R1_SHA256 0x0403 +#define MBEDTLS_TLS1_3_SIG_ECDSA_SECP384R1_SHA384 0x0503 +#define MBEDTLS_TLS1_3_SIG_ECDSA_SECP521R1_SHA512 0x0603 + +/* RSASSA-PSS algorithms with public key OID rsaEncryption */ +#define MBEDTLS_TLS1_3_SIG_RSA_PSS_RSAE_SHA256 0x0804 +#define MBEDTLS_TLS1_3_SIG_RSA_PSS_RSAE_SHA384 0x0805 +#define MBEDTLS_TLS1_3_SIG_RSA_PSS_RSAE_SHA512 0x0806 + +/* EdDSA algorithms */ +#define MBEDTLS_TLS1_3_SIG_ED25519 0x0807 +#define MBEDTLS_TLS1_3_SIG_ED448 0x0808 + +/* RSASSA-PSS algorithms with public key OID RSASSA-PSS */ +#define MBEDTLS_TLS1_3_SIG_RSA_PSS_PSS_SHA256 0x0809 +#define MBEDTLS_TLS1_3_SIG_RSA_PSS_PSS_SHA384 0x080A +#define MBEDTLS_TLS1_3_SIG_RSA_PSS_PSS_SHA512 0x080B + +/* LEGACY ALGORITHMS */ +#define MBEDTLS_TLS1_3_SIG_RSA_PKCS1_SHA1 0x0201 +#define MBEDTLS_TLS1_3_SIG_ECDSA_SHA1 0x0203 + +#define MBEDTLS_TLS1_3_SIG_NONE 0x0 + /* * Client Certificate Types * RFC 5246 section 7.4.4 plus RFC 4492 section 5.5 @@ -430,9 +554,11 @@ #define MBEDTLS_SSL_ALERT_MSG_INAPROPRIATE_FALLBACK 86 /* 0x56 */ #define MBEDTLS_SSL_ALERT_MSG_USER_CANCELED 90 /* 0x5A */ #define MBEDTLS_SSL_ALERT_MSG_NO_RENEGOTIATION 100 /* 0x64 */ +#define MBEDTLS_SSL_ALERT_MSG_MISSING_EXTENSION 109 /* 0x6d -- new in TLS 1.3 */ #define MBEDTLS_SSL_ALERT_MSG_UNSUPPORTED_EXT 110 /* 0x6E */ #define MBEDTLS_SSL_ALERT_MSG_UNRECOGNIZED_NAME 112 /* 0x70 */ #define MBEDTLS_SSL_ALERT_MSG_UNKNOWN_PSK_IDENTITY 115 /* 0x73 */ +#define MBEDTLS_SSL_ALERT_MSG_CERT_REQUIRED 116 /* 0x74 */ #define MBEDTLS_SSL_ALERT_MSG_NO_APPLICATION_PROTOCOL 120 /* 0x78 */ #define MBEDTLS_SSL_HS_HELLO_REQUEST 0 @@ -440,6 +566,8 @@ #define MBEDTLS_SSL_HS_SERVER_HELLO 2 #define MBEDTLS_SSL_HS_HELLO_VERIFY_REQUEST 3 #define MBEDTLS_SSL_HS_NEW_SESSION_TICKET 4 +#define MBEDTLS_SSL_HS_END_OF_EARLY_DATA 5 +#define MBEDTLS_SSL_HS_ENCRYPTED_EXTENSIONS 8 #define MBEDTLS_SSL_HS_CERTIFICATE 11 #define MBEDTLS_SSL_HS_SERVER_KEY_EXCHANGE 12 #define MBEDTLS_SSL_HS_CERTIFICATE_REQUEST 13 @@ -447,6 +575,7 @@ #define MBEDTLS_SSL_HS_CERTIFICATE_VERIFY 15 #define MBEDTLS_SSL_HS_CLIENT_KEY_EXCHANGE 16 #define MBEDTLS_SSL_HS_FINISHED 20 +#define MBEDTLS_SSL_HS_MESSAGE_HASH 254 /* * TLS extensions @@ -457,30 +586,44 @@ #define MBEDTLS_TLS_EXT_MAX_FRAGMENT_LENGTH 1 #define MBEDTLS_TLS_EXT_TRUNCATED_HMAC 4 +#define MBEDTLS_TLS_EXT_STATUS_REQUEST 5 /* RFC 6066 TLS 1.2 and 1.3 */ #define MBEDTLS_TLS_EXT_SUPPORTED_ELLIPTIC_CURVES 10 +#define MBEDTLS_TLS_EXT_SUPPORTED_GROUPS 10 /* RFC 8422,7919 TLS 1.2 and 1.3 */ #define MBEDTLS_TLS_EXT_SUPPORTED_POINT_FORMATS 11 -#define MBEDTLS_TLS_EXT_SIG_ALG 13 - +#define MBEDTLS_TLS_EXT_SIG_ALG 13 /* RFC 8446 TLS 1.3 */ #define MBEDTLS_TLS_EXT_USE_SRTP 14 - +#define MBEDTLS_TLS_EXT_HEARTBEAT 15 /* RFC 6520 TLS 1.2 and 1.3 */ #define MBEDTLS_TLS_EXT_ALPN 16 +#define MBEDTLS_TLS_EXT_SCT 18 /* RFC 6962 TLS 1.2 and 1.3 */ +#define MBEDTLS_TLS_EXT_CLI_CERT_TYPE 19 /* RFC 7250 TLS 1.2 and 1.3 */ +#define MBEDTLS_TLS_EXT_SERV_CERT_TYPE 20 /* RFC 7250 TLS 1.2 and 1.3 */ +#define MBEDTLS_TLS_EXT_PADDING 21 /* RFC 7685 TLS 1.2 and 1.3 */ #define MBEDTLS_TLS_EXT_ENCRYPT_THEN_MAC 22 /* 0x16 */ #define MBEDTLS_TLS_EXT_EXTENDED_MASTER_SECRET 0x0017 /* 23 */ +#define MBEDTLS_TLS_EXT_RECORD_SIZE_LIMIT 28 /* RFC 8449 (implemented for TLS 1.3 only) */ + #define MBEDTLS_TLS_EXT_SESSION_TICKET 35 -/* The value of the CID extension is still TBD as of - * draft-ietf-tls-dtls-connection-id-05 - * (https://tools.ietf.org/html/draft-ietf-tls-dtls-connection-id-05). - * - * A future minor revision of Mbed TLS may change the default value of - * this option to match evolving standards and usage. - */ -#if !defined(MBEDTLS_TLS_EXT_CID) -#define MBEDTLS_TLS_EXT_CID 254 /* TBD */ +#define MBEDTLS_TLS_EXT_PRE_SHARED_KEY 41 /* RFC 8446 TLS 1.3 */ +#define MBEDTLS_TLS_EXT_EARLY_DATA 42 /* RFC 8446 TLS 1.3 */ +#define MBEDTLS_TLS_EXT_SUPPORTED_VERSIONS 43 /* RFC 8446 TLS 1.3 */ +#define MBEDTLS_TLS_EXT_COOKIE 44 /* RFC 8446 TLS 1.3 */ +#define MBEDTLS_TLS_EXT_PSK_KEY_EXCHANGE_MODES 45 /* RFC 8446 TLS 1.3 */ + +#define MBEDTLS_TLS_EXT_CERT_AUTH 47 /* RFC 8446 TLS 1.3 */ +#define MBEDTLS_TLS_EXT_OID_FILTERS 48 /* RFC 8446 TLS 1.3 */ +#define MBEDTLS_TLS_EXT_POST_HANDSHAKE_AUTH 49 /* RFC 8446 TLS 1.3 */ +#define MBEDTLS_TLS_EXT_SIG_ALG_CERT 50 /* RFC 8446 TLS 1.3 */ +#define MBEDTLS_TLS_EXT_KEY_SHARE 51 /* RFC 8446 TLS 1.3 */ + +#if MBEDTLS_SSL_DTLS_CONNECTION_ID_COMPAT == 0 +#define MBEDTLS_TLS_EXT_CID 54 /* RFC 9146 DTLS 1.2 CID */ +#else +#define MBEDTLS_TLS_EXT_CID 254 /* Pre-RFC 9146 DTLS 1.2 CID */ #endif #define MBEDTLS_TLS_EXT_ECJPAKE_KKPP 256 /* experimental */ @@ -491,8 +634,22 @@ * Size defines */ #if !defined(MBEDTLS_PSK_MAX_LEN) -#define MBEDTLS_PSK_MAX_LEN 32 /* 256 bits */ +/* + * If the library supports TLS 1.3 tickets and the cipher suite + * TLS1-3-AES-256-GCM-SHA384, set the PSK maximum length to 48 instead of 32. + * That way, the TLS 1.3 client and server are able to resume sessions where + * the cipher suite is TLS1-3-AES-256-GCM-SHA384 (pre-shared keys are 48 + * bytes long in that case). + */ +#if defined(MBEDTLS_SSL_PROTO_TLS1_3) && \ + defined(MBEDTLS_SSL_SESSION_TICKETS) && \ + defined(MBEDTLS_SSL_HAVE_AES) && defined(MBEDTLS_SSL_HAVE_GCM) && \ + defined(MBEDTLS_MD_CAN_SHA384) +#define MBEDTLS_PSK_MAX_LEN 48 /* 384 bits */ +#else +#define MBEDTLS_PSK_MAX_LEN 32 /* 256 bits */ #endif +#endif /* !MBEDTLS_PSK_MAX_LEN */ /* Dummy type used only for its size */ union mbedtls_ssl_premaster_secret { @@ -530,6 +687,12 @@ union mbedtls_ssl_premaster_secret { #define MBEDTLS_PREMASTER_SIZE sizeof(union mbedtls_ssl_premaster_secret) +#define MBEDTLS_TLS1_3_MD_MAX_SIZE PSA_HASH_MAX_SIZE + + +/* Length in number of bytes of the TLS sequence number */ +#define MBEDTLS_SSL_SEQUENCE_NUMBER_LEN 8 + #ifdef __cplusplus extern "C" { #endif @@ -554,23 +717,38 @@ typedef enum { MBEDTLS_SSL_SERVER_FINISHED, MBEDTLS_SSL_FLUSH_BUFFERS, MBEDTLS_SSL_HANDSHAKE_WRAPUP, - MBEDTLS_SSL_HANDSHAKE_OVER, - MBEDTLS_SSL_SERVER_NEW_SESSION_TICKET, + MBEDTLS_SSL_NEW_SESSION_TICKET, MBEDTLS_SSL_SERVER_HELLO_VERIFY_REQUEST_SENT, + MBEDTLS_SSL_HELLO_RETRY_REQUEST, + MBEDTLS_SSL_ENCRYPTED_EXTENSIONS, + MBEDTLS_SSL_END_OF_EARLY_DATA, + MBEDTLS_SSL_CLIENT_CERTIFICATE_VERIFY, + MBEDTLS_SSL_CLIENT_CCS_AFTER_SERVER_FINISHED, + MBEDTLS_SSL_CLIENT_CCS_BEFORE_2ND_CLIENT_HELLO, + MBEDTLS_SSL_SERVER_CCS_AFTER_SERVER_HELLO, + MBEDTLS_SSL_CLIENT_CCS_AFTER_CLIENT_HELLO, + MBEDTLS_SSL_SERVER_CCS_AFTER_HELLO_RETRY_REQUEST, + MBEDTLS_SSL_HANDSHAKE_OVER, + MBEDTLS_SSL_TLS1_3_NEW_SESSION_TICKET, + MBEDTLS_SSL_TLS1_3_NEW_SESSION_TICKET_FLUSH, } mbedtls_ssl_states; /* - * The tls_prf function types. + * Early data status, client side only. */ + +#if defined(MBEDTLS_SSL_EARLY_DATA) && defined(MBEDTLS_SSL_CLI_C) typedef enum { - MBEDTLS_SSL_TLS_PRF_NONE, - MBEDTLS_SSL_TLS_PRF_SSL3, - MBEDTLS_SSL_TLS_PRF_TLS1, - MBEDTLS_SSL_TLS_PRF_SHA384, - MBEDTLS_SSL_TLS_PRF_SHA256 -} -mbedtls_tls_prf_types; +/* + * See documentation of mbedtls_ssl_get_early_data_status(). + */ + MBEDTLS_SSL_EARLY_DATA_STATUS_NOT_INDICATED, + MBEDTLS_SSL_EARLY_DATA_STATUS_ACCEPTED, + MBEDTLS_SSL_EARLY_DATA_STATUS_REJECTED, +} mbedtls_ssl_early_data_status; +#endif /* MBEDTLS_SSL_EARLY_DATA && MBEDTLS_SSL_CLI_C */ + /** * \brief Callback type: send data on the network. * @@ -686,7 +864,7 @@ typedef struct mbedtls_ssl_session mbedtls_ssl_session; typedef struct mbedtls_ssl_context mbedtls_ssl_context; typedef struct mbedtls_ssl_config mbedtls_ssl_config; -/* Defined in ssl_internal.h */ +/* Defined in library/ssl_misc.h */ typedef struct mbedtls_ssl_transform mbedtls_ssl_transform; typedef struct mbedtls_ssl_handshake_params mbedtls_ssl_handshake_params; typedef struct mbedtls_ssl_sig_hash_set_t mbedtls_ssl_sig_hash_set_t; @@ -697,6 +875,69 @@ typedef struct mbedtls_ssl_key_cert mbedtls_ssl_key_cert; typedef struct mbedtls_ssl_flight_item mbedtls_ssl_flight_item; #endif +#if defined(MBEDTLS_SSL_PROTO_TLS1_3) && defined(MBEDTLS_SSL_SESSION_TICKETS) +#define MBEDTLS_SSL_TLS1_3_TICKET_ALLOW_PSK_RESUMPTION \ + MBEDTLS_SSL_TLS1_3_KEY_EXCHANGE_MODE_PSK /* 1U << 0 */ +#define MBEDTLS_SSL_TLS1_3_TICKET_ALLOW_PSK_EPHEMERAL_RESUMPTION \ + MBEDTLS_SSL_TLS1_3_KEY_EXCHANGE_MODE_PSK_EPHEMERAL /* 1U << 2 */ +#define MBEDTLS_SSL_TLS1_3_TICKET_ALLOW_EARLY_DATA (1U << 3) + +#define MBEDTLS_SSL_TLS1_3_TICKET_FLAGS_MASK \ + (MBEDTLS_SSL_TLS1_3_TICKET_ALLOW_PSK_RESUMPTION | \ + MBEDTLS_SSL_TLS1_3_TICKET_ALLOW_PSK_EPHEMERAL_RESUMPTION | \ + MBEDTLS_SSL_TLS1_3_TICKET_ALLOW_EARLY_DATA) +#endif /* MBEDTLS_SSL_PROTO_TLS1_3 && MBEDTLS_SSL_SESSION_TICKETS */ + +/** + * \brief Callback type: server-side session cache getter + * + * The session cache is logically a key value store, with + * keys being session IDs and values being instances of + * mbedtls_ssl_session. + * + * This callback retrieves an entry in this key-value store. + * + * \param data The address of the session cache structure to query. + * \param session_id The buffer holding the session ID to query. + * \param session_id_len The length of \p session_id in Bytes. + * \param session The address of the session structure to populate. + * It is initialized with mbdtls_ssl_session_init(), + * and the callback must always leave it in a state + * where it can safely be freed via + * mbedtls_ssl_session_free() independent of the + * return code of this function. + * + * \return \c 0 on success + * \return A non-zero return value on failure. + * + */ +typedef int mbedtls_ssl_cache_get_t(void *data, + unsigned char const *session_id, + size_t session_id_len, + mbedtls_ssl_session *session); +/** + * \brief Callback type: server-side session cache setter + * + * The session cache is logically a key value store, with + * keys being session IDs and values being instances of + * mbedtls_ssl_session. + * + * This callback sets an entry in this key-value store. + * + * \param data The address of the session cache structure to modify. + * \param session_id The buffer holding the session ID to query. + * \param session_id_len The length of \p session_id in Bytes. + * \param session The address of the session to be stored in the + * session cache. + * + * \return \c 0 on success + * \return A non-zero return value on failure. + */ +typedef int mbedtls_ssl_cache_set_t(void *data, + unsigned char const *session_id, + size_t session_id_len, + const mbedtls_ssl_session *session); + #if defined(MBEDTLS_SSL_ASYNC_PRIVATE) #if defined(MBEDTLS_X509_CRT_PARSE_C) /** @@ -912,13 +1153,13 @@ typedef void mbedtls_ssl_async_cancel_t(mbedtls_ssl_context *ssl); #if defined(MBEDTLS_KEY_EXCHANGE_WITH_CERT_ENABLED) && \ !defined(MBEDTLS_SSL_KEEP_PEER_CERTIFICATE) #define MBEDTLS_SSL_PEER_CERT_DIGEST_MAX_LEN 48 -#if defined(MBEDTLS_SHA256_C) +#if defined(MBEDTLS_MD_CAN_SHA256) #define MBEDTLS_SSL_PEER_CERT_DIGEST_DFL_TYPE MBEDTLS_MD_SHA256 #define MBEDTLS_SSL_PEER_CERT_DIGEST_DFL_LEN 32 -#elif defined(MBEDTLS_SHA512_C) +#elif defined(MBEDTLS_MD_CAN_SHA384) #define MBEDTLS_SSL_PEER_CERT_DIGEST_DFL_TYPE MBEDTLS_MD_SHA384 #define MBEDTLS_SSL_PEER_CERT_DIGEST_DFL_LEN 48 -#elif defined(MBEDTLS_SHA1_C) +#elif defined(MBEDTLS_MD_CAN_SHA1) #define MBEDTLS_SSL_PEER_CERT_DIGEST_DFL_TYPE MBEDTLS_MD_SHA1 #define MBEDTLS_SSL_PEER_CERT_DIGEST_DFL_LEN 20 #else @@ -928,6 +1169,13 @@ typedef void mbedtls_ssl_async_cancel_t(mbedtls_ssl_context *ssl); #endif /* MBEDTLS_KEY_EXCHANGE_WITH_CERT_ENABLED && !MBEDTLS_SSL_KEEP_PEER_CERTIFICATE */ +typedef struct { + unsigned char client_application_traffic_secret_N[MBEDTLS_TLS1_3_MD_MAX_SIZE]; + unsigned char server_application_traffic_secret_N[MBEDTLS_TLS1_3_MD_MAX_SIZE]; + unsigned char exporter_master_secret[MBEDTLS_TLS1_3_MD_MAX_SIZE]; + unsigned char resumption_master_secret[MBEDTLS_TLS1_3_MD_MAX_SIZE]; +} mbedtls_ssl_tls13_application_secrets; + #if defined(MBEDTLS_SSL_DTLS_SRTP) #define MBEDTLS_TLS_SRTP_MAX_MKI_LENGTH 255 @@ -952,16 +1200,23 @@ typedef uint16_t mbedtls_ssl_srtp_profile; typedef struct mbedtls_dtls_srtp_info_t { /*! The SRTP profile that was negotiated. */ - mbedtls_ssl_srtp_profile chosen_dtls_srtp_profile; + mbedtls_ssl_srtp_profile MBEDTLS_PRIVATE(chosen_dtls_srtp_profile); /*! The length of mki_value. */ - uint16_t mki_len; + uint16_t MBEDTLS_PRIVATE(mki_len); /*! The mki_value used, with max size of 256 bytes. */ - unsigned char mki_value[MBEDTLS_TLS_SRTP_MAX_MKI_LENGTH]; + unsigned char MBEDTLS_PRIVATE(mki_value)[MBEDTLS_TLS_SRTP_MAX_MKI_LENGTH]; } mbedtls_dtls_srtp_info; #endif /* MBEDTLS_SSL_DTLS_SRTP */ +/** Human-friendly representation of the (D)TLS protocol version. */ +typedef enum { + MBEDTLS_SSL_VERSION_UNKNOWN, /*!< Context not in use or version not yet negotiated. */ + MBEDTLS_SSL_VERSION_TLS1_2 = 0x0303, /*!< (D)TLS 1.2 */ + MBEDTLS_SSL_VERSION_TLS1_3 = 0x0304, /*!< (D)TLS 1.3 */ +} mbedtls_ssl_protocol_version; + /* * This structure is used for storing current session data. * @@ -975,60 +1230,192 @@ mbedtls_dtls_srtp_info; */ struct mbedtls_ssl_session { #if defined(MBEDTLS_SSL_MAX_FRAGMENT_LENGTH) - unsigned char mfl_code; /*!< MaxFragmentLength negotiated by peer */ + unsigned char MBEDTLS_PRIVATE(mfl_code); /*!< MaxFragmentLength negotiated by peer */ #endif /* MBEDTLS_SSL_MAX_FRAGMENT_LENGTH */ +/*!< RecordSizeLimit received from the peer */ +#if defined(MBEDTLS_SSL_RECORD_SIZE_LIMIT) + uint16_t MBEDTLS_PRIVATE(record_size_limit); +#endif /* MBEDTLS_SSL_RECORD_SIZE_LIMIT */ + + unsigned char MBEDTLS_PRIVATE(exported); + uint8_t MBEDTLS_PRIVATE(endpoint); /*!< 0: client, 1: server */ + + /** TLS version negotiated in the session. Used if and when renegotiating + * or resuming a session instead of the configured minor TLS version. + */ + mbedtls_ssl_protocol_version MBEDTLS_PRIVATE(tls_version); + #if defined(MBEDTLS_HAVE_TIME) - mbedtls_time_t start; /*!< starting time */ + mbedtls_time_t MBEDTLS_PRIVATE(start); /*!< start time of current session */ #endif - int ciphersuite; /*!< chosen ciphersuite */ - int compression; /*!< chosen compression */ - size_t id_len; /*!< session id length */ - unsigned char id[32]; /*!< session identifier */ - unsigned char master[48]; /*!< the master secret */ + int MBEDTLS_PRIVATE(ciphersuite); /*!< chosen ciphersuite */ + size_t MBEDTLS_PRIVATE(id_len); /*!< session id length */ + unsigned char MBEDTLS_PRIVATE(id)[32]; /*!< session identifier */ + unsigned char MBEDTLS_PRIVATE(master)[48]; /*!< the master secret */ #if defined(MBEDTLS_X509_CRT_PARSE_C) #if defined(MBEDTLS_SSL_KEEP_PEER_CERTIFICATE) - mbedtls_x509_crt *peer_cert; /*!< peer X.509 cert chain */ + mbedtls_x509_crt *MBEDTLS_PRIVATE(peer_cert); /*!< peer X.509 cert chain */ #else /* MBEDTLS_SSL_KEEP_PEER_CERTIFICATE */ /*! The digest of the peer's end-CRT. This must be kept to detect CRT * changes during renegotiation, mitigating the triple handshake attack. */ - unsigned char *peer_cert_digest; - size_t peer_cert_digest_len; - mbedtls_md_type_t peer_cert_digest_type; + unsigned char *MBEDTLS_PRIVATE(peer_cert_digest); + size_t MBEDTLS_PRIVATE(peer_cert_digest_len); + mbedtls_md_type_t MBEDTLS_PRIVATE(peer_cert_digest_type); #endif /* !MBEDTLS_SSL_KEEP_PEER_CERTIFICATE */ #endif /* MBEDTLS_X509_CRT_PARSE_C */ - uint32_t verify_result; /*!< verification result */ + uint32_t MBEDTLS_PRIVATE(verify_result); /*!< verification result */ #if defined(MBEDTLS_SSL_SESSION_TICKETS) && defined(MBEDTLS_SSL_CLI_C) - unsigned char *ticket; /*!< RFC 5077 session ticket */ - size_t ticket_len; /*!< session ticket length */ - uint32_t ticket_lifetime; /*!< ticket lifetime hint */ + unsigned char *MBEDTLS_PRIVATE(ticket); /*!< RFC 5077 session ticket */ + size_t MBEDTLS_PRIVATE(ticket_len); /*!< session ticket length */ + uint32_t MBEDTLS_PRIVATE(ticket_lifetime); /*!< ticket lifetime hint */ #endif /* MBEDTLS_SSL_SESSION_TICKETS && MBEDTLS_SSL_CLI_C */ -#if defined(MBEDTLS_SSL_TRUNCATED_HMAC) - int trunc_hmac; /*!< flag for truncated hmac activation */ -#endif /* MBEDTLS_SSL_TRUNCATED_HMAC */ +#if defined(MBEDTLS_SSL_SESSION_TICKETS) && defined(MBEDTLS_SSL_SRV_C) && \ + defined(MBEDTLS_HAVE_TIME) + /*! When a ticket is created by a TLS server as part of an established TLS + * session, the ticket creation time may need to be saved for the ticket + * module to be able to check the ticket age when the ticket is used. + * That's the purpose of this field. + * Before creating a new ticket, an Mbed TLS server set this field with + * its current time in milliseconds. This time may then be saved in the + * session ticket data by the session ticket writing function and + * recovered by the ticket parsing function later when the ticket is used. + * The ticket module may then use this time to compute the ticket age and + * determine if it has expired or not. + * The Mbed TLS implementations of the session ticket writing and parsing + * functions save and retrieve the ticket creation time as part of the + * session ticket data. The session ticket parsing function relies on + * the mbedtls_ssl_session_get_ticket_creation_time() API to get the + * ticket creation time from the session ticket data. + */ + mbedtls_ms_time_t MBEDTLS_PRIVATE(ticket_creation_time); +#endif + +#if defined(MBEDTLS_SSL_PROTO_TLS1_3) && defined(MBEDTLS_SSL_SESSION_TICKETS) + uint32_t MBEDTLS_PRIVATE(ticket_age_add); /*!< Randomly generated value used to obscure the age of the ticket */ + uint8_t MBEDTLS_PRIVATE(ticket_flags); /*!< Ticket flags */ + uint8_t MBEDTLS_PRIVATE(resumption_key_len); /*!< resumption_key length */ + unsigned char MBEDTLS_PRIVATE(resumption_key)[MBEDTLS_SSL_TLS1_3_TICKET_RESUMPTION_KEY_LEN]; + +#if defined(MBEDTLS_SSL_SERVER_NAME_INDICATION) && defined(MBEDTLS_SSL_CLI_C) + char *MBEDTLS_PRIVATE(hostname); /*!< host name binded with tickets */ +#endif /* MBEDTLS_SSL_SERVER_NAME_INDICATION && MBEDTLS_SSL_CLI_C */ + +#if defined(MBEDTLS_SSL_EARLY_DATA) && defined(MBEDTLS_SSL_ALPN) && defined(MBEDTLS_SSL_SRV_C) + char *ticket_alpn; /*!< ALPN negotiated in the session + during which the ticket was generated. */ +#endif + +#if defined(MBEDTLS_HAVE_TIME) && defined(MBEDTLS_SSL_CLI_C) + /*! Time in milliseconds when the last ticket was received. */ + mbedtls_ms_time_t MBEDTLS_PRIVATE(ticket_reception_time); +#endif +#endif /* MBEDTLS_SSL_PROTO_TLS1_3 && MBEDTLS_SSL_SESSION_TICKETS */ + +#if defined(MBEDTLS_SSL_EARLY_DATA) + uint32_t MBEDTLS_PRIVATE(max_early_data_size); /*!< maximum amount of early data in tickets */ +#endif #if defined(MBEDTLS_SSL_ENCRYPT_THEN_MAC) - int encrypt_then_mac; /*!< flag for EtM activation */ + int MBEDTLS_PRIVATE(encrypt_then_mac); /*!< flag for EtM activation */ +#endif + +#if defined(MBEDTLS_SSL_PROTO_TLS1_3) + mbedtls_ssl_tls13_application_secrets MBEDTLS_PRIVATE(app_secrets); #endif }; +/* + * Identifiers for PRFs used in various versions of TLS. + */ +typedef enum { + MBEDTLS_SSL_TLS_PRF_NONE, + MBEDTLS_SSL_TLS_PRF_SHA384, + MBEDTLS_SSL_TLS_PRF_SHA256, + MBEDTLS_SSL_HKDF_EXPAND_SHA384, + MBEDTLS_SSL_HKDF_EXPAND_SHA256 +} +mbedtls_tls_prf_types; + +typedef enum { + MBEDTLS_SSL_KEY_EXPORT_TLS12_MASTER_SECRET = 0, +#if defined(MBEDTLS_SSL_PROTO_TLS1_3) + MBEDTLS_SSL_KEY_EXPORT_TLS1_3_CLIENT_EARLY_SECRET, + MBEDTLS_SSL_KEY_EXPORT_TLS1_3_EARLY_EXPORTER_SECRET, + MBEDTLS_SSL_KEY_EXPORT_TLS1_3_CLIENT_HANDSHAKE_TRAFFIC_SECRET, + MBEDTLS_SSL_KEY_EXPORT_TLS1_3_SERVER_HANDSHAKE_TRAFFIC_SECRET, + MBEDTLS_SSL_KEY_EXPORT_TLS1_3_CLIENT_APPLICATION_TRAFFIC_SECRET, + MBEDTLS_SSL_KEY_EXPORT_TLS1_3_SERVER_APPLICATION_TRAFFIC_SECRET, +#endif /* MBEDTLS_SSL_PROTO_TLS1_3 */ +} mbedtls_ssl_key_export_type; + +/** + * \brief Callback type: Export key alongside random values for + * session identification, and PRF for + * implementation of TLS key exporters. + * + * \param p_expkey Context for the callback. + * \param type The type of the key that is being exported. + * \param secret The address of the buffer holding the secret + * that's being exporterd. + * \param secret_len The length of \p secret in bytes. + * \param client_random The client random bytes. + * \param server_random The server random bytes. + * \param tls_prf_type The identifier for the PRF used in the handshake + * to which the key belongs. + */ +typedef void mbedtls_ssl_export_keys_t(void *p_expkey, + mbedtls_ssl_key_export_type type, + const unsigned char *secret, + size_t secret_len, + const unsigned char client_random[32], + const unsigned char server_random[32], + mbedtls_tls_prf_types tls_prf_type); + +#if defined(MBEDTLS_SSL_SRV_C) +/** + * \brief Callback type: generic handshake callback + * + * \note Callbacks may use user_data funcs to set/get app user data. + * See \c mbedtls_ssl_get_user_data_p() + * \c mbedtls_ssl_get_user_data_n() + * \c mbedtls_ssl_conf_get_user_data_p() + * \c mbedtls_ssl_conf_get_user_data_n() + * + * \param ssl \c mbedtls_ssl_context on which the callback is run + * + * \return The return value of the callback is 0 if successful, + * or a specific MBEDTLS_ERR_XXX code, which will cause + * the handshake to be aborted. + */ +typedef int (*mbedtls_ssl_hs_cb_t)(mbedtls_ssl_context *ssl); +#endif + +/* A type for storing user data in a library structure. + * + * The representation of type may change in future versions of the library. + * Only the behaviors guaranteed by documented accessor functions are + * guaranteed to remain stable. + */ +typedef union { + uintptr_t n; /* typically a handle to an associated object */ + void *p; /* typically a pointer to extra data */ +} mbedtls_ssl_user_data_t; + /** * SSL/TLS configuration to be shared between mbedtls_ssl_context structures. */ struct mbedtls_ssl_config { - /* Group items by size and reorder them to maximize usage of immediate offset access. */ + /* Group items mostly by size. This helps to reduce memory wasted to + * padding. It also helps to keep smaller fields early in the structure, + * so that elements tend to be in the 128-element direct access window + * on Arm Thumb, which reduces the code size. */ - /* - * Numerical settings (char) - */ - - unsigned char max_major_ver; /*!< max. major version used */ - unsigned char max_minor_ver; /*!< max. minor version used */ - unsigned char min_major_ver; /*!< min. major version used */ - unsigned char min_minor_ver; /*!< min. minor version used */ + mbedtls_ssl_protocol_version MBEDTLS_PRIVATE(max_tls_version); /*!< max. TLS version used */ + mbedtls_ssl_protocol_version MBEDTLS_PRIVATE(min_tls_version); /*!< min. TLS version used */ /* * Flags (could be bit-fields to save RAM, but separate bytes make @@ -1036,418 +1423,494 @@ struct mbedtls_ssl_config { * byte access). */ - uint8_t endpoint /*bool*/; /*!< 0: client, 1: server */ - uint8_t transport /*bool*/; /*!< stream (TLS) or datagram (DTLS) */ - uint8_t authmode /*2 bits*/; /*!< MBEDTLS_SSL_VERIFY_XXX */ + uint8_t MBEDTLS_PRIVATE(endpoint); /*!< 0: client, 1: server */ + uint8_t MBEDTLS_PRIVATE(transport); /*!< 0: stream (TLS), 1: datagram (DTLS) */ + uint8_t MBEDTLS_PRIVATE(authmode); /*!< MBEDTLS_SSL_VERIFY_XXX */ /* needed even with renego disabled for LEGACY_BREAK_HANDSHAKE */ - uint8_t allow_legacy_renegotiation /*2 bits*/; /*!< MBEDTLS_LEGACY_XXX */ -#if defined(MBEDTLS_ARC4_C) - uint8_t arc4_disabled /*bool*/; /*!< blacklist RC4 ciphersuites? */ -#endif + uint8_t MBEDTLS_PRIVATE(allow_legacy_renegotiation); /*!< MBEDTLS_LEGACY_XXX */ #if defined(MBEDTLS_SSL_MAX_FRAGMENT_LENGTH) - uint8_t mfl_code /*3 bits*/; /*!< desired fragment length */ + uint8_t MBEDTLS_PRIVATE(mfl_code); /*!< desired fragment length indicator + (MBEDTLS_SSL_MAX_FRAG_LEN_XXX) */ #endif #if defined(MBEDTLS_SSL_ENCRYPT_THEN_MAC) - uint8_t encrypt_then_mac /*bool*/; /*!< negotiate encrypt-then-mac? */ + uint8_t MBEDTLS_PRIVATE(encrypt_then_mac); /*!< negotiate encrypt-then-mac? */ #endif #if defined(MBEDTLS_SSL_EXTENDED_MASTER_SECRET) - uint8_t extended_ms /*bool*/; /*!< negotiate extended master secret? */ + uint8_t MBEDTLS_PRIVATE(extended_ms); /*!< negotiate extended master secret? */ #endif #if defined(MBEDTLS_SSL_DTLS_ANTI_REPLAY) - uint8_t anti_replay /*bool*/; /*!< detect and prevent replay? */ -#endif -#if defined(MBEDTLS_SSL_CBC_RECORD_SPLITTING) - uint8_t cbc_record_splitting /*bool*/; /*!< do cbc record splitting */ + uint8_t MBEDTLS_PRIVATE(anti_replay); /*!< detect and prevent replay? */ #endif #if defined(MBEDTLS_SSL_RENEGOTIATION) - uint8_t disable_renegotiation /*bool*/; /*!< disable renegotiation? */ -#endif -#if defined(MBEDTLS_SSL_TRUNCATED_HMAC) - uint8_t trunc_hmac /*bool*/; /*!< negotiate truncated hmac? */ + uint8_t MBEDTLS_PRIVATE(disable_renegotiation); /*!< disable renegotiation? */ #endif -#if defined(MBEDTLS_SSL_SESSION_TICKETS) - uint8_t session_tickets /*bool*/; /*!< use session tickets? */ +#if defined(MBEDTLS_SSL_SESSION_TICKETS) && \ + defined(MBEDTLS_SSL_CLI_C) + uint8_t MBEDTLS_PRIVATE(session_tickets); /*!< use session tickets? */ #endif -#if defined(MBEDTLS_SSL_FALLBACK_SCSV) && defined(MBEDTLS_SSL_CLI_C) - uint8_t fallback /*bool*/; /*!< is this a fallback? */ + +#if defined(MBEDTLS_SSL_SESSION_TICKETS) && \ + defined(MBEDTLS_SSL_SRV_C) && \ + defined(MBEDTLS_SSL_PROTO_TLS1_3) + uint16_t MBEDTLS_PRIVATE(new_session_tickets_count); /*!< number of NewSessionTicket */ #endif + #if defined(MBEDTLS_SSL_SRV_C) - uint8_t cert_req_ca_list /*bool*/; /*!< enable sending CA list in - Certificate Request messages? */ + uint8_t MBEDTLS_PRIVATE(cert_req_ca_list); /*!< enable sending CA list in + Certificate Request messages? */ + uint8_t MBEDTLS_PRIVATE(respect_cli_pref); /*!< pick the ciphersuite according to + the client's preferences rather + than ours? */ #endif #if defined(MBEDTLS_SSL_DTLS_CONNECTION_ID) - uint8_t ignore_unexpected_cid /*bool*/; /*!< Determines whether DTLS - * record with unexpected CID - * should lead to failure. */ + uint8_t MBEDTLS_PRIVATE(ignore_unexpected_cid); /*!< Should DTLS record with + * unexpected CID + * lead to failure? */ #endif /* MBEDTLS_SSL_DTLS_CONNECTION_ID */ #if defined(MBEDTLS_SSL_DTLS_SRTP) - uint8_t dtls_srtp_mki_support /*bool*/; /*!< support having mki_value - in the use_srtp extension? */ -#endif - - /* - * Numerical settings (int or larger) - */ - - uint32_t read_timeout; /*!< timeout for mbedtls_ssl_read (ms) */ - -#if defined(MBEDTLS_SSL_PROTO_DTLS) - uint32_t hs_timeout_min; /*!< initial value of the handshake - retransmission timeout (ms) */ - uint32_t hs_timeout_max; /*!< maximum value of the handshake - retransmission timeout (ms) */ -#endif - -#if defined(MBEDTLS_SSL_RENEGOTIATION) - int renego_max_records; /*!< grace period for renegotiation */ - unsigned char renego_period[8]; /*!< value of the record counters - that triggers renegotiation */ -#endif - -#if defined(MBEDTLS_SSL_DTLS_BADMAC_LIMIT) - unsigned int badmac_limit; /*!< limit of records with a bad MAC */ -#endif - -#if defined(MBEDTLS_DHM_C) && defined(MBEDTLS_SSL_CLI_C) - unsigned int dhm_min_bitlen; /*!< min. bit length of the DHM prime */ + uint8_t MBEDTLS_PRIVATE(dtls_srtp_mki_support); /* support having mki_value + in the use_srtp extension? */ #endif /* * Pointers */ - const int *ciphersuite_list[4]; /*!< allowed ciphersuites per version */ + /** Allowed ciphersuites for (D)TLS 1.2 (0-terminated) */ + const int *MBEDTLS_PRIVATE(ciphersuite_list); + +#if defined(MBEDTLS_SSL_PROTO_TLS1_3) + /** Allowed TLS 1.3 key exchange modes. */ + int MBEDTLS_PRIVATE(tls13_kex_modes); +#endif /* MBEDTLS_SSL_PROTO_TLS1_3 */ /** Callback for printing debug output */ - void (*f_dbg)(void *, int, const char *, int, const char *); - void *p_dbg; /*!< context for the debug function */ + void(*MBEDTLS_PRIVATE(f_dbg))(void *, int, const char *, int, const char *); + void *MBEDTLS_PRIVATE(p_dbg); /*!< context for the debug function */ /** Callback for getting (pseudo-)random numbers */ - int (*f_rng)(void *, unsigned char *, size_t); - void *p_rng; /*!< context for the RNG function */ + int(*MBEDTLS_PRIVATE(f_rng))(void *, unsigned char *, size_t); + void *MBEDTLS_PRIVATE(p_rng); /*!< context for the RNG function */ /** Callback to retrieve a session from the cache */ - int (*f_get_cache)(void *, mbedtls_ssl_session *); + mbedtls_ssl_cache_get_t *MBEDTLS_PRIVATE(f_get_cache); /** Callback to store a session into the cache */ - int (*f_set_cache)(void *, const mbedtls_ssl_session *); - void *p_cache; /*!< context for cache callbacks */ + mbedtls_ssl_cache_set_t *MBEDTLS_PRIVATE(f_set_cache); + void *MBEDTLS_PRIVATE(p_cache); /*!< context for cache callbacks */ #if defined(MBEDTLS_SSL_SERVER_NAME_INDICATION) /** Callback for setting cert according to SNI extension */ - int (*f_sni)(void *, mbedtls_ssl_context *, const unsigned char *, size_t); - void *p_sni; /*!< context for SNI callback */ + int(*MBEDTLS_PRIVATE(f_sni))(void *, mbedtls_ssl_context *, const unsigned char *, size_t); + void *MBEDTLS_PRIVATE(p_sni); /*!< context for SNI callback */ #endif #if defined(MBEDTLS_X509_CRT_PARSE_C) /** Callback to customize X.509 certificate chain verification */ - int (*f_vrfy)(void *, mbedtls_x509_crt *, int, uint32_t *); - void *p_vrfy; /*!< context for X.509 verify calllback */ + int(*MBEDTLS_PRIVATE(f_vrfy))(void *, mbedtls_x509_crt *, int, uint32_t *); + void *MBEDTLS_PRIVATE(p_vrfy); /*!< context for X.509 verify calllback */ #endif -#if defined(MBEDTLS_KEY_EXCHANGE_SOME_PSK_ENABLED) +#if defined(MBEDTLS_SSL_HANDSHAKE_WITH_PSK_ENABLED) +#if defined(MBEDTLS_SSL_SRV_C) /** Callback to retrieve PSK key from identity */ - int (*f_psk)(void *, mbedtls_ssl_context *, const unsigned char *, size_t); - void *p_psk; /*!< context for PSK callback */ + int(*MBEDTLS_PRIVATE(f_psk))(void *, mbedtls_ssl_context *, const unsigned char *, size_t); + void *MBEDTLS_PRIVATE(p_psk); /*!< context for PSK callback */ +#endif #endif #if defined(MBEDTLS_SSL_DTLS_HELLO_VERIFY) && defined(MBEDTLS_SSL_SRV_C) /** Callback to create & write a cookie for ClientHello verification */ - int (*f_cookie_write)(void *, unsigned char **, unsigned char *, - const unsigned char *, size_t); + int(*MBEDTLS_PRIVATE(f_cookie_write))(void *, unsigned char **, unsigned char *, + const unsigned char *, size_t); /** Callback to verify validity of a ClientHello cookie */ - int (*f_cookie_check)(void *, const unsigned char *, size_t, - const unsigned char *, size_t); - void *p_cookie; /*!< context for the cookie callbacks */ + int(*MBEDTLS_PRIVATE(f_cookie_check))(void *, const unsigned char *, size_t, + const unsigned char *, size_t); + void *MBEDTLS_PRIVATE(p_cookie); /*!< context for the cookie callbacks */ #endif #if defined(MBEDTLS_SSL_SESSION_TICKETS) && defined(MBEDTLS_SSL_SRV_C) /** Callback to create & write a session ticket */ - int (*f_ticket_write)(void *, const mbedtls_ssl_session *, - unsigned char *, const unsigned char *, size_t *, uint32_t *); + int(*MBEDTLS_PRIVATE(f_ticket_write))(void *, const mbedtls_ssl_session *, + unsigned char *, const unsigned char *, size_t *, + uint32_t *); /** Callback to parse a session ticket into a session structure */ - int (*f_ticket_parse)(void *, mbedtls_ssl_session *, unsigned char *, size_t); - void *p_ticket; /*!< context for the ticket callbacks */ + int(*MBEDTLS_PRIVATE(f_ticket_parse))(void *, mbedtls_ssl_session *, unsigned char *, size_t); + void *MBEDTLS_PRIVATE(p_ticket); /*!< context for the ticket callbacks */ #endif /* MBEDTLS_SSL_SESSION_TICKETS && MBEDTLS_SSL_SRV_C */ - -#if defined(MBEDTLS_SSL_EXPORT_KEYS) - /** Callback to export key block and master secret */ - int (*f_export_keys)(void *, const unsigned char *, - const unsigned char *, size_t, size_t, size_t); - /** Callback to export key block, master secret, - * tls_prf and random bytes. Should replace f_export_keys */ - int (*f_export_keys_ext)(void *, const unsigned char *, - const unsigned char *, size_t, size_t, size_t, - const unsigned char[32], const unsigned char[32], - mbedtls_tls_prf_types); - void *p_export_keys; /*!< context for key export callback */ -#endif - #if defined(MBEDTLS_SSL_DTLS_CONNECTION_ID) - size_t cid_len; /*!< The length of CIDs for incoming DTLS records. */ + size_t MBEDTLS_PRIVATE(cid_len); /*!< The length of CIDs for incoming DTLS records. */ #endif /* MBEDTLS_SSL_DTLS_CONNECTION_ID */ #if defined(MBEDTLS_X509_CRT_PARSE_C) - const mbedtls_x509_crt_profile *cert_profile; /*!< verification profile */ - mbedtls_ssl_key_cert *key_cert; /*!< own certificate/key pair(s) */ - mbedtls_x509_crt *ca_chain; /*!< trusted CAs */ - mbedtls_x509_crl *ca_crl; /*!< trusted CAs CRLs */ + const mbedtls_x509_crt_profile *MBEDTLS_PRIVATE(cert_profile); /*!< verification profile */ + mbedtls_ssl_key_cert *MBEDTLS_PRIVATE(key_cert); /*!< own certificate/key pair(s) */ + mbedtls_x509_crt *MBEDTLS_PRIVATE(ca_chain); /*!< trusted CAs */ + mbedtls_x509_crl *MBEDTLS_PRIVATE(ca_crl); /*!< trusted CAs CRLs */ #if defined(MBEDTLS_X509_TRUSTED_CERTIFICATE_CALLBACK) - mbedtls_x509_crt_ca_cb_t f_ca_cb; - void *p_ca_cb; + mbedtls_x509_crt_ca_cb_t MBEDTLS_PRIVATE(f_ca_cb); + void *MBEDTLS_PRIVATE(p_ca_cb); #endif /* MBEDTLS_X509_TRUSTED_CERTIFICATE_CALLBACK */ #endif /* MBEDTLS_X509_CRT_PARSE_C */ #if defined(MBEDTLS_SSL_ASYNC_PRIVATE) #if defined(MBEDTLS_X509_CRT_PARSE_C) - mbedtls_ssl_async_sign_t *f_async_sign_start; /*!< start asynchronous signature operation */ - mbedtls_ssl_async_decrypt_t *f_async_decrypt_start; /*!< start asynchronous decryption operation */ + mbedtls_ssl_async_sign_t *MBEDTLS_PRIVATE(f_async_sign_start); /*!< start asynchronous signature operation */ + mbedtls_ssl_async_decrypt_t *MBEDTLS_PRIVATE(f_async_decrypt_start); /*!< start asynchronous decryption operation */ #endif /* MBEDTLS_X509_CRT_PARSE_C */ - mbedtls_ssl_async_resume_t *f_async_resume; /*!< resume asynchronous operation */ - mbedtls_ssl_async_cancel_t *f_async_cancel; /*!< cancel asynchronous operation */ - void *p_async_config_data; /*!< Configuration data set by mbedtls_ssl_conf_async_private_cb(). */ + mbedtls_ssl_async_resume_t *MBEDTLS_PRIVATE(f_async_resume); /*!< resume asynchronous operation */ + mbedtls_ssl_async_cancel_t *MBEDTLS_PRIVATE(f_async_cancel); /*!< cancel asynchronous operation */ + void *MBEDTLS_PRIVATE(p_async_config_data); /*!< Configuration data set by mbedtls_ssl_conf_async_private_cb(). */ #endif /* MBEDTLS_SSL_ASYNC_PRIVATE */ -#if defined(MBEDTLS_KEY_EXCHANGE_WITH_CERT_ENABLED) - const int *sig_hashes; /*!< allowed signature hashes */ +#if defined(MBEDTLS_SSL_HANDSHAKE_WITH_CERT_ENABLED) + +#if !defined(MBEDTLS_DEPRECATED_REMOVED) + const int *MBEDTLS_PRIVATE(sig_hashes); /*!< allowed signature hashes */ #endif + const uint16_t *MBEDTLS_PRIVATE(sig_algs); /*!< allowed signature algorithms */ +#endif /* MBEDTLS_SSL_HANDSHAKE_WITH_CERT_ENABLED */ -#if defined(MBEDTLS_ECP_C) - const mbedtls_ecp_group_id *curve_list; /*!< allowed curves */ +#if defined(MBEDTLS_ECP_C) && !defined(MBEDTLS_DEPRECATED_REMOVED) + const mbedtls_ecp_group_id *MBEDTLS_PRIVATE(curve_list); /*!< allowed curves */ #endif + const uint16_t *MBEDTLS_PRIVATE(group_list); /*!< allowed IANA NamedGroups */ + #if defined(MBEDTLS_DHM_C) - mbedtls_mpi dhm_P; /*!< prime modulus for DHM */ - mbedtls_mpi dhm_G; /*!< generator for DHM */ + mbedtls_mpi MBEDTLS_PRIVATE(dhm_P); /*!< prime modulus for DHM */ + mbedtls_mpi MBEDTLS_PRIVATE(dhm_G); /*!< generator for DHM */ #endif -#if defined(MBEDTLS_KEY_EXCHANGE_SOME_PSK_ENABLED) +#if defined(MBEDTLS_SSL_HANDSHAKE_WITH_PSK_ENABLED) #if defined(MBEDTLS_USE_PSA_CRYPTO) - psa_key_id_t psk_opaque; /*!< PSA key slot holding opaque PSK. This field - * should only be set via - * mbedtls_ssl_conf_psk_opaque(). - * If either no PSK or a raw PSK have been - * configured, this has value \c 0. - */ + mbedtls_svc_key_id_t MBEDTLS_PRIVATE(psk_opaque); /*!< PSA key slot holding opaque PSK. This field + * should only be set via + * mbedtls_ssl_conf_psk_opaque(). + * If either no PSK or a raw PSK have been + * configured, this has value \c 0. + */ #endif /* MBEDTLS_USE_PSA_CRYPTO */ + unsigned char *MBEDTLS_PRIVATE(psk); /*!< The raw pre-shared key. This field should + * only be set via mbedtls_ssl_conf_psk(). + * If either no PSK or an opaque PSK + * have been configured, this has value NULL. */ + size_t MBEDTLS_PRIVATE(psk_len); /*!< The length of the raw pre-shared key. + * This field should only be set via + * mbedtls_ssl_conf_psk(). + * Its value is non-zero if and only if + * \c psk is not \c NULL. */ + + unsigned char *MBEDTLS_PRIVATE(psk_identity); /*!< The PSK identity for PSK negotiation. + * This field should only be set via + * mbedtls_ssl_conf_psk(). + * This is set if and only if either + * \c psk or \c psk_opaque are set. */ + size_t MBEDTLS_PRIVATE(psk_identity_len);/*!< The length of PSK identity. + * This field should only be set via + * mbedtls_ssl_conf_psk(). + * Its value is non-zero if and only if + * \c psk is not \c NULL or \c psk_opaque + * is not \c 0. */ +#endif /* MBEDTLS_SSL_HANDSHAKE_WITH_PSK_ENABLED */ + +#if defined(MBEDTLS_SSL_EARLY_DATA) + int MBEDTLS_PRIVATE(early_data_enabled); /*!< Early data enablement: + * - MBEDTLS_SSL_EARLY_DATA_DISABLED, + * - MBEDTLS_SSL_EARLY_DATA_ENABLED */ - unsigned char *psk; /*!< The raw pre-shared key. This field should - * only be set via mbedtls_ssl_conf_psk(). - * If either no PSK or an opaque PSK - * have been configured, this has value NULL. */ - size_t psk_len; /*!< The length of the raw pre-shared key. - * This field should only be set via - * mbedtls_ssl_conf_psk(). - * Its value is non-zero if and only if - * \c psk is not \c NULL. */ - - unsigned char *psk_identity; /*!< The PSK identity for PSK negotiation. - * This field should only be set via - * mbedtls_ssl_conf_psk(). - * This is set if and only if either - * \c psk or \c psk_opaque are set. */ - size_t psk_identity_len;/*!< The length of PSK identity. - * This field should only be set via - * mbedtls_ssl_conf_psk(). - * Its value is non-zero if and only if - * \c psk is not \c NULL or \c psk_opaque - * is not \c 0. */ -#endif /* MBEDTLS_KEY_EXCHANGE_SOME_PSK_ENABLED */ +#if defined(MBEDTLS_SSL_SRV_C) + /* The maximum amount of 0-RTT data. RFC 8446 section 4.6.1 */ + uint32_t MBEDTLS_PRIVATE(max_early_data_size); +#endif /* MBEDTLS_SSL_SRV_C */ + +#endif /* MBEDTLS_SSL_EARLY_DATA */ #if defined(MBEDTLS_SSL_ALPN) - const char **alpn_list; /*!< ordered list of protocols */ + const char **MBEDTLS_PRIVATE(alpn_list); /*!< ordered list of protocols */ #endif #if defined(MBEDTLS_SSL_DTLS_SRTP) /*! ordered list of supported srtp profile */ - const mbedtls_ssl_srtp_profile *dtls_srtp_profile_list; + const mbedtls_ssl_srtp_profile *MBEDTLS_PRIVATE(dtls_srtp_profile_list); /*! number of supported profiles */ - size_t dtls_srtp_profile_list_len; + size_t MBEDTLS_PRIVATE(dtls_srtp_profile_list_len); #endif /* MBEDTLS_SSL_DTLS_SRTP */ + + /* + * Numerical settings (int) + */ + + uint32_t MBEDTLS_PRIVATE(read_timeout); /*!< timeout for mbedtls_ssl_read (ms) */ + +#if defined(MBEDTLS_SSL_PROTO_DTLS) + uint32_t MBEDTLS_PRIVATE(hs_timeout_min); /*!< initial value of the handshake + retransmission timeout (ms) */ + uint32_t MBEDTLS_PRIVATE(hs_timeout_max); /*!< maximum value of the handshake + retransmission timeout (ms) */ +#endif + +#if defined(MBEDTLS_SSL_RENEGOTIATION) + int MBEDTLS_PRIVATE(renego_max_records); /*!< grace period for renegotiation */ + unsigned char MBEDTLS_PRIVATE(renego_period)[8]; /*!< value of the record counters + that triggers renegotiation */ +#endif + + unsigned int MBEDTLS_PRIVATE(badmac_limit); /*!< limit of records with a bad MAC */ + +#if defined(MBEDTLS_DHM_C) && defined(MBEDTLS_SSL_CLI_C) + unsigned int MBEDTLS_PRIVATE(dhm_min_bitlen); /*!< min. bit length of the DHM prime */ +#endif + + /** User data pointer or handle. + * + * The library sets this to \p 0 when creating a context and does not + * access it afterwards. + */ + mbedtls_ssl_user_data_t MBEDTLS_PRIVATE(user_data); + +#if defined(MBEDTLS_SSL_SRV_C) + mbedtls_ssl_hs_cb_t MBEDTLS_PRIVATE(f_cert_cb); /*!< certificate selection callback */ +#endif /* MBEDTLS_SSL_SRV_C */ + +#if defined(MBEDTLS_KEY_EXCHANGE_CERT_REQ_ALLOWED_ENABLED) + const mbedtls_x509_crt *MBEDTLS_PRIVATE(dn_hints);/*!< acceptable client cert issuers */ +#endif }; struct mbedtls_ssl_context { - const mbedtls_ssl_config *conf; /*!< configuration information */ + const mbedtls_ssl_config *MBEDTLS_PRIVATE(conf); /*!< configuration information */ /* * Miscellaneous */ - int state; /*!< SSL handshake: current state */ + int MBEDTLS_PRIVATE(state); /*!< SSL handshake: current state */ #if defined(MBEDTLS_SSL_RENEGOTIATION) - int renego_status; /*!< Initial, in progress, pending? */ - int renego_records_seen; /*!< Records since renego request, or with DTLS, - number of retransmissions of request if - renego_max_records is < 0 */ + int MBEDTLS_PRIVATE(renego_status); /*!< Initial, in progress, pending? */ + int MBEDTLS_PRIVATE(renego_records_seen); /*!< Records since renego request, or with DTLS, + number of retransmissions of request if + renego_max_records is < 0 */ #endif /* MBEDTLS_SSL_RENEGOTIATION */ - int major_ver; /*!< equal to MBEDTLS_SSL_MAJOR_VERSION_3 */ - int minor_ver; /*!< either 0 (SSL3) or 1 (TLS1.0) */ + /** + * Maximum TLS version to be negotiated, then negotiated TLS version. + * + * It is initialized as the configured maximum TLS version to be + * negotiated by mbedtls_ssl_setup(). + * + * When renegotiating or resuming a session, it is overwritten in the + * ClientHello writing preparation stage with the previously negotiated + * TLS version. + * + * On client side, it is updated to the TLS version selected by the server + * for the handshake when the ServerHello is received. + * + * On server side, it is updated to the TLS version the server selects for + * the handshake when the ClientHello is received. + */ + mbedtls_ssl_protocol_version MBEDTLS_PRIVATE(tls_version); -#if defined(MBEDTLS_SSL_DTLS_BADMAC_LIMIT) - unsigned badmac_seen; /*!< records with a bad MAC received */ -#endif /* MBEDTLS_SSL_DTLS_BADMAC_LIMIT */ +#if defined(MBEDTLS_SSL_EARLY_DATA) && defined(MBEDTLS_SSL_CLI_C) + /** + * State of the negotiation and transfer of early data. Reset to + * MBEDTLS_SSL_EARLY_DATA_STATE_IDLE when the context is reset. + */ + int MBEDTLS_PRIVATE(early_data_state); +#endif + + unsigned MBEDTLS_PRIVATE(badmac_seen); /*!< records with a bad MAC received */ #if defined(MBEDTLS_X509_CRT_PARSE_C) /** Callback to customize X.509 certificate chain verification */ - int (*f_vrfy)(void *, mbedtls_x509_crt *, int, uint32_t *); - void *p_vrfy; /*!< context for X.509 verify callback */ + int(*MBEDTLS_PRIVATE(f_vrfy))(void *, mbedtls_x509_crt *, int, uint32_t *); + void *MBEDTLS_PRIVATE(p_vrfy); /*!< context for X.509 verify callback */ #endif - mbedtls_ssl_send_t *f_send; /*!< Callback for network send */ - mbedtls_ssl_recv_t *f_recv; /*!< Callback for network receive */ - mbedtls_ssl_recv_timeout_t *f_recv_timeout; + mbedtls_ssl_send_t *MBEDTLS_PRIVATE(f_send); /*!< Callback for network send */ + mbedtls_ssl_recv_t *MBEDTLS_PRIVATE(f_recv); /*!< Callback for network receive */ + mbedtls_ssl_recv_timeout_t *MBEDTLS_PRIVATE(f_recv_timeout); /*!< Callback for network receive with timeout */ - void *p_bio; /*!< context for I/O operations */ + void *MBEDTLS_PRIVATE(p_bio); /*!< context for I/O operations */ /* * Session layer */ - mbedtls_ssl_session *session_in; /*!< current session data (in) */ - mbedtls_ssl_session *session_out; /*!< current session data (out) */ - mbedtls_ssl_session *session; /*!< negotiated session data */ - mbedtls_ssl_session *session_negotiate; /*!< session data in negotiation */ + mbedtls_ssl_session *MBEDTLS_PRIVATE(session_in); /*!< current session data (in) */ + mbedtls_ssl_session *MBEDTLS_PRIVATE(session_out); /*!< current session data (out) */ + mbedtls_ssl_session *MBEDTLS_PRIVATE(session); /*!< negotiated session data */ + mbedtls_ssl_session *MBEDTLS_PRIVATE(session_negotiate); /*!< session data in negotiation */ - mbedtls_ssl_handshake_params *handshake; /*!< params required only during - the handshake process */ + mbedtls_ssl_handshake_params *MBEDTLS_PRIVATE(handshake); /*!< params required only during + the handshake process */ /* * Record layer transformations */ - mbedtls_ssl_transform *transform_in; /*!< current transform params (in) */ - mbedtls_ssl_transform *transform_out; /*!< current transform params (in) */ - mbedtls_ssl_transform *transform; /*!< negotiated transform params */ - mbedtls_ssl_transform *transform_negotiate; /*!< transform params in negotiation */ + mbedtls_ssl_transform *MBEDTLS_PRIVATE(transform_in); /*!< current transform params (in) + * This is always a reference, + * never an owning pointer. */ + mbedtls_ssl_transform *MBEDTLS_PRIVATE(transform_out); /*!< current transform params (out) + * This is always a reference, + * never an owning pointer. */ + mbedtls_ssl_transform *MBEDTLS_PRIVATE(transform); /*!< negotiated transform params + * This pointer owns the transform + * it references. */ +#if defined(MBEDTLS_SSL_PROTO_TLS1_2) + mbedtls_ssl_transform *MBEDTLS_PRIVATE(transform_negotiate); /*!< transform params in negotiation + * This pointer owns the transform + * it references. */ +#endif /* MBEDTLS_SSL_PROTO_TLS1_2 */ + +#if defined(MBEDTLS_SSL_PROTO_TLS1_3) + /*! The application data transform in TLS 1.3. + * This pointer owns the transform it references. */ + mbedtls_ssl_transform *MBEDTLS_PRIVATE(transform_application); +#endif /* MBEDTLS_SSL_PROTO_TLS1_3 */ /* * Timers */ - void *p_timer; /*!< context for the timer callbacks */ + void *MBEDTLS_PRIVATE(p_timer); /*!< context for the timer callbacks */ - mbedtls_ssl_set_timer_t *f_set_timer; /*!< set timer callback */ - mbedtls_ssl_get_timer_t *f_get_timer; /*!< get timer callback */ + mbedtls_ssl_set_timer_t *MBEDTLS_PRIVATE(f_set_timer); /*!< set timer callback */ + mbedtls_ssl_get_timer_t *MBEDTLS_PRIVATE(f_get_timer); /*!< get timer callback */ /* * Record layer (incoming data) */ - unsigned char *in_buf; /*!< input buffer */ - unsigned char *in_ctr; /*!< 64-bit incoming message counter - TLS: maintained by us - DTLS: read from peer */ - unsigned char *in_hdr; /*!< start of record header */ + unsigned char *MBEDTLS_PRIVATE(in_buf); /*!< input buffer */ + unsigned char *MBEDTLS_PRIVATE(in_ctr); /*!< 64-bit incoming message counter + TLS: maintained by us + DTLS: read from peer */ + unsigned char *MBEDTLS_PRIVATE(in_hdr); /*!< start of record header */ #if defined(MBEDTLS_SSL_DTLS_CONNECTION_ID) - unsigned char *in_cid; /*!< The start of the CID; - * (the end is marked by in_len). */ + unsigned char *MBEDTLS_PRIVATE(in_cid); /*!< The start of the CID; + * (the end is marked by in_len). */ #endif /* MBEDTLS_SSL_DTLS_CONNECTION_ID */ - unsigned char *in_len; /*!< two-bytes message length field */ - unsigned char *in_iv; /*!< ivlen-byte IV */ - unsigned char *in_msg; /*!< message contents (in_iv+ivlen) */ - unsigned char *in_offt; /*!< read offset in application data */ - - int in_msgtype; /*!< record header: message type */ - size_t in_msglen; /*!< record header: message length */ - size_t in_left; /*!< amount of data read so far */ + unsigned char *MBEDTLS_PRIVATE(in_len); /*!< two-bytes message length field */ + unsigned char *MBEDTLS_PRIVATE(in_iv); /*!< ivlen-byte IV */ + unsigned char *MBEDTLS_PRIVATE(in_msg); /*!< message contents (in_iv+ivlen) */ + unsigned char *MBEDTLS_PRIVATE(in_offt); /*!< read offset in application data */ + + int MBEDTLS_PRIVATE(in_msgtype); /*!< record header: message type */ + size_t MBEDTLS_PRIVATE(in_msglen); /*!< record header: message length */ + size_t MBEDTLS_PRIVATE(in_left); /*!< amount of data read so far */ #if defined(MBEDTLS_SSL_VARIABLE_BUFFER_LENGTH) - size_t in_buf_len; /*!< length of input buffer */ + size_t MBEDTLS_PRIVATE(in_buf_len); /*!< length of input buffer */ #endif #if defined(MBEDTLS_SSL_PROTO_DTLS) - uint16_t in_epoch; /*!< DTLS epoch for incoming records */ - size_t next_record_offset; /*!< offset of the next record in datagram - (equal to in_left if none) */ + uint16_t MBEDTLS_PRIVATE(in_epoch); /*!< DTLS epoch for incoming records */ + size_t MBEDTLS_PRIVATE(next_record_offset); /*!< offset of the next record in datagram + (equal to in_left if none) */ #endif /* MBEDTLS_SSL_PROTO_DTLS */ #if defined(MBEDTLS_SSL_DTLS_ANTI_REPLAY) - uint64_t in_window_top; /*!< last validated record seq_num */ - uint64_t in_window; /*!< bitmask for replay detection */ + uint64_t MBEDTLS_PRIVATE(in_window_top); /*!< last validated record seq_num */ + uint64_t MBEDTLS_PRIVATE(in_window); /*!< bitmask for replay detection */ #endif /* MBEDTLS_SSL_DTLS_ANTI_REPLAY */ - size_t in_hslen; /*!< current handshake message length, - including the handshake header */ - int nb_zero; /*!< # of 0-length encrypted messages */ + size_t MBEDTLS_PRIVATE(in_hslen); /*!< current handshake message length, + including the handshake header */ + int MBEDTLS_PRIVATE(nb_zero); /*!< # of 0-length encrypted messages */ - int keep_current_message; /*!< drop or reuse current message - on next call to record layer? */ + int MBEDTLS_PRIVATE(keep_current_message); /*!< drop or reuse current message + on next call to record layer? */ + + /* The following three variables indicate if and, if yes, + * what kind of alert is pending to be sent. + */ + unsigned char MBEDTLS_PRIVATE(send_alert); /*!< Determines if a fatal alert + should be sent. Values: + - \c 0 , no alert is to be sent. + - \c 1 , alert is to be sent. */ + unsigned char MBEDTLS_PRIVATE(alert_type); /*!< Type of alert if send_alert + != 0 */ + int MBEDTLS_PRIVATE(alert_reason); /*!< The error code to be returned + to the user once the fatal alert + has been sent. */ #if defined(MBEDTLS_SSL_PROTO_DTLS) - uint8_t disable_datagram_packing; /*!< Disable packing multiple records - * within a single datagram. */ + uint8_t MBEDTLS_PRIVATE(disable_datagram_packing); /*!< Disable packing multiple records + * within a single datagram. */ #endif /* MBEDTLS_SSL_PROTO_DTLS */ +#if defined(MBEDTLS_SSL_EARLY_DATA) +#if defined(MBEDTLS_SSL_SRV_C) + /* + * One of: + * MBEDTLS_SSL_EARLY_DATA_NO_DISCARD + * MBEDTLS_SSL_EARLY_DATA_TRY_TO_DEPROTECT_AND_DISCARD + * MBEDTLS_SSL_EARLY_DATA_DISCARD + */ + uint8_t MBEDTLS_PRIVATE(discard_early_data_record); +#endif + uint32_t MBEDTLS_PRIVATE(total_early_data_size); /*!< Number of received/written early data bytes */ +#endif /* MBEDTLS_SSL_EARLY_DATA */ + /* * Record layer (outgoing data) */ - unsigned char *out_buf; /*!< output buffer */ - unsigned char *out_ctr; /*!< 64-bit outgoing message counter */ - unsigned char *out_hdr; /*!< start of record header */ + unsigned char *MBEDTLS_PRIVATE(out_buf); /*!< output buffer */ + unsigned char *MBEDTLS_PRIVATE(out_ctr); /*!< 64-bit outgoing message counter */ + unsigned char *MBEDTLS_PRIVATE(out_hdr); /*!< start of record header */ #if defined(MBEDTLS_SSL_DTLS_CONNECTION_ID) - unsigned char *out_cid; /*!< The start of the CID; - * (the end is marked by in_len). */ + unsigned char *MBEDTLS_PRIVATE(out_cid); /*!< The start of the CID; + * (the end is marked by in_len). */ #endif /* MBEDTLS_SSL_DTLS_CONNECTION_ID */ - unsigned char *out_len; /*!< two-bytes message length field */ - unsigned char *out_iv; /*!< ivlen-byte IV */ - unsigned char *out_msg; /*!< message contents (out_iv+ivlen) */ + unsigned char *MBEDTLS_PRIVATE(out_len); /*!< two-bytes message length field */ + unsigned char *MBEDTLS_PRIVATE(out_iv); /*!< ivlen-byte IV */ + unsigned char *MBEDTLS_PRIVATE(out_msg); /*!< message contents (out_iv+ivlen) */ - int out_msgtype; /*!< record header: message type */ - size_t out_msglen; /*!< record header: message length */ - size_t out_left; /*!< amount of data not yet written */ + int MBEDTLS_PRIVATE(out_msgtype); /*!< record header: message type */ + size_t MBEDTLS_PRIVATE(out_msglen); /*!< record header: message length */ + size_t MBEDTLS_PRIVATE(out_left); /*!< amount of data not yet written */ #if defined(MBEDTLS_SSL_VARIABLE_BUFFER_LENGTH) - size_t out_buf_len; /*!< length of output buffer */ + size_t MBEDTLS_PRIVATE(out_buf_len); /*!< length of output buffer */ #endif - unsigned char cur_out_ctr[8]; /*!< Outgoing record sequence number. */ + unsigned char MBEDTLS_PRIVATE(cur_out_ctr)[MBEDTLS_SSL_SEQUENCE_NUMBER_LEN]; /*!< Outgoing record sequence number. */ #if defined(MBEDTLS_SSL_PROTO_DTLS) - uint16_t mtu; /*!< path mtu, used to fragment outgoing messages */ + uint16_t MBEDTLS_PRIVATE(mtu); /*!< path mtu, used to fragment outgoing messages */ #endif /* MBEDTLS_SSL_PROTO_DTLS */ -#if defined(MBEDTLS_ZLIB_SUPPORT) - unsigned char *compress_buf; /*!< zlib data buffer */ -#endif /* MBEDTLS_ZLIB_SUPPORT */ -#if defined(MBEDTLS_SSL_CBC_RECORD_SPLITTING) - signed char split_done; /*!< current record already split? */ -#endif /* MBEDTLS_SSL_CBC_RECORD_SPLITTING */ - - /* - * PKI layer - */ - int client_auth; /*!< flag for client auth. */ - /* * User settings */ #if defined(MBEDTLS_X509_CRT_PARSE_C) - char *hostname; /*!< expected peer CN for verification - (and SNI if available) */ + char *MBEDTLS_PRIVATE(hostname); /*!< expected peer CN for verification + (and SNI if available) */ #endif /* MBEDTLS_X509_CRT_PARSE_C */ #if defined(MBEDTLS_SSL_ALPN) - const char *alpn_chosen; /*!< negotiated protocol */ + const char *MBEDTLS_PRIVATE(alpn_chosen); /*!< negotiated protocol */ #endif /* MBEDTLS_SSL_ALPN */ #if defined(MBEDTLS_SSL_DTLS_SRTP) /* * use_srtp extension */ - mbedtls_dtls_srtp_info dtls_srtp_info; + mbedtls_dtls_srtp_info MBEDTLS_PRIVATE(dtls_srtp_info); #endif /* MBEDTLS_SSL_DTLS_SRTP */ /* * Information for DTLS hello verify */ #if defined(MBEDTLS_SSL_DTLS_HELLO_VERIFY) && defined(MBEDTLS_SSL_SRV_C) - unsigned char *cli_id; /*!< transport-level ID of the client */ - size_t cli_id_len; /*!< length of cli_id */ + unsigned char *MBEDTLS_PRIVATE(cli_id); /*!< transport-level ID of the client */ + size_t MBEDTLS_PRIVATE(cli_id_len); /*!< length of cli_id */ #endif /* MBEDTLS_SSL_DTLS_HELLO_VERIFY && MBEDTLS_SSL_SRV_C */ /* * Secure renegotiation */ /* needed to know when to send extension on server */ - int secure_renegotiation; /*!< does peer support legacy or - secure renegotiation */ + int MBEDTLS_PRIVATE(secure_renegotiation); /*!< does peer support legacy or + secure renegotiation */ #if defined(MBEDTLS_SSL_RENEGOTIATION) - size_t verify_data_len; /*!< length of verify data stored */ - char own_verify_data[MBEDTLS_SSL_VERIFY_DATA_MAX_LEN]; /*!< previous handshake verify data */ - char peer_verify_data[MBEDTLS_SSL_VERIFY_DATA_MAX_LEN]; /*!< previous handshake verify data */ + size_t MBEDTLS_PRIVATE(verify_data_len); /*!< length of verify data stored */ + char MBEDTLS_PRIVATE(own_verify_data)[MBEDTLS_SSL_VERIFY_DATA_MAX_LEN]; /*!< previous handshake verify data */ + char MBEDTLS_PRIVATE(peer_verify_data)[MBEDTLS_SSL_VERIFY_DATA_MAX_LEN]; /*!< previous handshake verify data */ #endif /* MBEDTLS_SSL_RENEGOTIATION */ #if defined(MBEDTLS_SSL_DTLS_CONNECTION_ID) @@ -1457,52 +1920,29 @@ struct mbedtls_ssl_context { * all subsequent handshakes. This may be different from the * CID currently used in case the user has re-configured the CID * after an initial handshake. */ - unsigned char own_cid[MBEDTLS_SSL_CID_IN_LEN_MAX]; - uint8_t own_cid_len; /*!< The length of \c own_cid. */ - uint8_t negotiate_cid; /*!< This indicates whether the CID extension should - * be negotiated in the next handshake or not. - * Possible values are #MBEDTLS_SSL_CID_ENABLED - * and #MBEDTLS_SSL_CID_DISABLED. */ + unsigned char MBEDTLS_PRIVATE(own_cid)[MBEDTLS_SSL_CID_IN_LEN_MAX]; + uint8_t MBEDTLS_PRIVATE(own_cid_len); /*!< The length of \c own_cid. */ + uint8_t MBEDTLS_PRIVATE(negotiate_cid); /*!< This indicates whether the CID extension should + * be negotiated in the next handshake or not. + * Possible values are #MBEDTLS_SSL_CID_ENABLED + * and #MBEDTLS_SSL_CID_DISABLED. */ #endif /* MBEDTLS_SSL_DTLS_CONNECTION_ID */ -}; - -#if defined(MBEDTLS_SSL_HW_RECORD_ACCEL) - -#if !defined(MBEDTLS_DEPRECATED_REMOVED) - -#define MBEDTLS_SSL_CHANNEL_OUTBOUND MBEDTLS_DEPRECATED_NUMERIC_CONSTANT(0) -#define MBEDTLS_SSL_CHANNEL_INBOUND MBEDTLS_DEPRECATED_NUMERIC_CONSTANT(1) -#if defined(MBEDTLS_DEPRECATED_WARNING) -#define MBEDTLS_DEPRECATED __attribute__((deprecated)) -#else -#define MBEDTLS_DEPRECATED -#endif /* MBEDTLS_DEPRECATED_WARNING */ - -MBEDTLS_DEPRECATED extern int (*mbedtls_ssl_hw_record_init)( - mbedtls_ssl_context *ssl, - const unsigned char *key_enc, const unsigned char *key_dec, - size_t keylen, - const unsigned char *iv_enc, const unsigned char *iv_dec, - size_t ivlen, - const unsigned char *mac_enc, const unsigned char *mac_dec, - size_t maclen); -MBEDTLS_DEPRECATED extern int (*mbedtls_ssl_hw_record_activate)( - mbedtls_ssl_context *ssl, - int direction); -MBEDTLS_DEPRECATED extern int (*mbedtls_ssl_hw_record_reset)( - mbedtls_ssl_context *ssl); -MBEDTLS_DEPRECATED extern int (*mbedtls_ssl_hw_record_write)( - mbedtls_ssl_context *ssl); -MBEDTLS_DEPRECATED extern int (*mbedtls_ssl_hw_record_read)( - mbedtls_ssl_context *ssl); -MBEDTLS_DEPRECATED extern int (*mbedtls_ssl_hw_record_finish)( - mbedtls_ssl_context *ssl); - -#undef MBEDTLS_DEPRECATED -#endif /* !MBEDTLS_DEPRECATED_REMOVED */ - -#endif /* MBEDTLS_SSL_HW_RECORD_ACCEL */ + /** Callback to export key block and master secret */ + mbedtls_ssl_export_keys_t *MBEDTLS_PRIVATE(f_export_keys); + void *MBEDTLS_PRIVATE(p_export_keys); /*!< context for key export callback */ + + /** User data pointer or handle. + * + * The library sets this to \p 0 when creating a context and does not + * access it afterwards. + * + * \warning Serializing and restoring an SSL context with + * mbedtls_ssl_context_save() and mbedtls_ssl_context_load() + * does not currently restore the user data. + */ + mbedtls_ssl_user_data_t MBEDTLS_PRIVATE(user_data); +}; /** * \brief Return the name of the ciphersuite associated with the @@ -1566,9 +2006,8 @@ int mbedtls_ssl_setup(mbedtls_ssl_context *ssl, * pointers and data. * * \param ssl SSL context - * \return 0 if successful, or MBEDTLS_ERR_SSL_ALLOC_FAILED, - MBEDTLS_ERR_SSL_HW_ACCEL_FAILED or - * MBEDTLS_ERR_SSL_COMPRESSION_FAILED + * \return 0 if successful, or MBEDTLS_ERR_SSL_ALLOC_FAILED or + MBEDTLS_ERR_SSL_HW_ACCEL_FAILED */ int mbedtls_ssl_session_reset(mbedtls_ssl_context *ssl); @@ -1580,6 +2019,19 @@ int mbedtls_ssl_session_reset(mbedtls_ssl_context *ssl); */ void mbedtls_ssl_conf_endpoint(mbedtls_ssl_config *conf, int endpoint); +/** + * \brief Get the current endpoint type + * + * \param conf SSL configuration + * + * \return Endpoint type, either MBEDTLS_SSL_IS_CLIENT + * or MBEDTLS_SSL_IS_SERVER + */ +static inline int mbedtls_ssl_conf_get_endpoint(const mbedtls_ssl_config *conf) +{ + return conf->MBEDTLS_PRIVATE(endpoint); +} + /** * \brief Set the transport type (TLS or DTLS). * Default: TLS @@ -1624,6 +2076,67 @@ void mbedtls_ssl_conf_transport(mbedtls_ssl_config *conf, int transport); */ void mbedtls_ssl_conf_authmode(mbedtls_ssl_config *conf, int authmode); +#if defined(MBEDTLS_SSL_EARLY_DATA) +/** + * \brief Set the early data mode + * Default: disabled on server and client + * + * \param conf The SSL configuration to use. + * \param early_data_enabled can be: + * + * MBEDTLS_SSL_EARLY_DATA_DISABLED: + * Early data functionality is disabled. This is the default on client and + * server. + * + * MBEDTLS_SSL_EARLY_DATA_ENABLED: + * Early data functionality is enabled and may be negotiated in the handshake. + * Application using early data functionality needs to be aware that the + * security properties for early data (also refered to as 0-RTT data) are + * weaker than those for other kinds of TLS data. See the documentation of + * mbedtls_ssl_write_early_data() and mbedtls_ssl_read_early_data() for more + * information. + * When early data functionality is enabled on server and only in that case, + * the call to one of the APIs that trigger or resume an handshake sequence, + * namely mbedtls_ssl_handshake(), mbedtls_ssl_handshake_step(), + * mbedtls_ssl_read() or mbedtls_ssl_write() may return with the error code + * MBEDTLS_ERR_SSL_RECEIVED_EARLY_DATA indicating that some early data have + * been received. To read the early data, call mbedtls_ssl_read_early_data() + * before calling the original function again. + */ +void mbedtls_ssl_conf_early_data(mbedtls_ssl_config *conf, + int early_data_enabled); + +#if defined(MBEDTLS_SSL_SRV_C) +/** + * \brief Set the maximum amount of 0-RTT data in bytes + * Default: #MBEDTLS_SSL_MAX_EARLY_DATA_SIZE + * + * This function sets the value of the max_early_data_size + * field of the early data indication extension included in + * the NewSessionTicket messages that the server may send. + * + * The value defines the maximum amount of 0-RTT data + * in bytes that a client will be allowed to send when using + * one of the tickets defined by the NewSessionTicket messages. + * + * \note When resuming a session using a ticket, if the server receives more + * early data than allowed for the ticket, it terminates the connection. + * The maximum amount of 0-RTT data should thus be large enough + * to allow a minimum of early data to be exchanged. + * + * \param[in] conf The SSL configuration to use. + * \param[in] max_early_data_size The maximum amount of 0-RTT data. + * + * \warning This interface DOES NOT influence/limit the amount of early data + * that can be received through previously created and issued tickets, + * which clients may have stored. + */ +void mbedtls_ssl_conf_max_early_data_size( + mbedtls_ssl_config *conf, uint32_t max_early_data_size); +#endif /* MBEDTLS_SSL_SRV_C */ + +#endif /* MBEDTLS_SSL_EARLY_DATA */ + #if defined(MBEDTLS_X509_CRT_PARSE_C) /** * \brief Set the verification callback (Optional). @@ -1649,7 +2162,7 @@ void mbedtls_ssl_conf_verify(mbedtls_ssl_config *conf, * \brief Set the random number generator callback * * \param conf SSL configuration - * \param f_rng RNG function + * \param f_rng RNG function (mandatory) * \param p_rng RNG parameter */ void mbedtls_ssl_conf_rng(mbedtls_ssl_config *conf, @@ -1674,6 +2187,22 @@ void mbedtls_ssl_conf_dbg(mbedtls_ssl_config *conf, void (*f_dbg)(void *, int, const char *, int, const char *), void *p_dbg); +/** + * \brief Return the SSL configuration structure associated + * with the given SSL context. + * + * \note The pointer returned by this function is guaranteed to + * remain valid until the context is freed. + * + * \param ssl The SSL context to query. + * \return Pointer to the SSL configuration associated with \p ssl. + */ +static inline const mbedtls_ssl_config *mbedtls_ssl_context_get_config( + const mbedtls_ssl_context *ssl) +{ + return ssl->MBEDTLS_PRIVATE(conf); +} + /** * \brief Set the underlying BIO callbacks for write, read and * read-with-timeout. @@ -1719,8 +2248,9 @@ void mbedtls_ssl_set_bio(mbedtls_ssl_context *ssl, * \brief Configure the use of the Connection ID (CID) * extension in the next handshake. * - * Reference: draft-ietf-tls-dtls-connection-id-05 + * Reference: RFC 9146 (or draft-ietf-tls-dtls-connection-id-05 * https://tools.ietf.org/html/draft-ietf-tls-dtls-connection-id-05 + * for legacy version) * * The DTLS CID extension allows the reliable association of * DTLS records to DTLS connections across changes in the @@ -1777,7 +2307,7 @@ void mbedtls_ssl_set_bio(mbedtls_ssl_context *ssl, * the `ServerHello` contains the CID extension, too, * the CID extension will actually be put to use. * - On the Server, enabling the use of the CID through - * this call implies that that the server will look for + * this call implies that the server will look for * the CID extension in a `ClientHello` from the client, * and, if present, reply with a CID extension in its * `ServerHello`. @@ -1803,6 +2333,40 @@ int mbedtls_ssl_set_cid(mbedtls_ssl_context *ssl, unsigned char const *own_cid, size_t own_cid_len); +/** + * \brief Get information about our request for usage of the CID + * extension in the current connection. + * + * \param ssl The SSL context to query. + * \param enabled The address at which to store whether the CID extension + * is requested to be used or not. If the CID is + * requested, `*enabled` is set to + * MBEDTLS_SSL_CID_ENABLED; otherwise, it is set to + * MBEDTLS_SSL_CID_DISABLED. + * \param own_cid The address of the buffer in which to store our own + * CID (if the CID extension is requested). This may be + * \c NULL in case the value of our CID isn't needed. If + * it is not \c NULL, \p own_cid_len must not be \c NULL. + * \param own_cid_len The address at which to store the size of our own CID + * (if the CID extension is requested). This is also the + * number of Bytes in \p own_cid that have been written. + * This may be \c NULL in case the length of our own CID + * isn't needed. If it is \c NULL, \p own_cid must be + * \c NULL, too. + * + *\note If we are requesting an empty CID this function sets + * `*enabled` to #MBEDTLS_SSL_CID_DISABLED (the rationale + * for this is that the resulting outcome is the + * same as if the CID extensions wasn't requested). + * + * \return \c 0 on success. + * \return A negative error code on failure. + */ +int mbedtls_ssl_get_own_cid(mbedtls_ssl_context *ssl, + int *enabled, + unsigned char own_cid[MBEDTLS_SSL_CID_OUT_LEN_MAX], + size_t *own_cid_len); + /** * \brief Get information about the use of the CID extension * in the current connection. @@ -1883,9 +2447,6 @@ int mbedtls_ssl_get_peer_cid(mbedtls_ssl_context *ssl, * \note Values lower than the current record layer expansion will * result in an error when trying to send data. * - * \note Using record compression together with a non-zero MTU value - * will result in an error when trying to send data. - * * \param ssl SSL context * \param mtu Value of the path MTU in bytes */ @@ -1934,7 +2495,6 @@ void mbedtls_ssl_set_verify(mbedtls_ssl_context *ssl, */ void mbedtls_ssl_conf_read_timeout(mbedtls_ssl_config *conf, uint32_t timeout); -#if defined(MBEDTLS_SSL_RECORD_CHECKING) /** * \brief Check whether a buffer contains a valid and authentic record * that has not been seen before. (DTLS only). @@ -1982,7 +2542,6 @@ void mbedtls_ssl_conf_read_timeout(mbedtls_ssl_config *conf, uint32_t timeout); int mbedtls_ssl_check_record(mbedtls_ssl_context const *ssl, unsigned char *buf, size_t buflen); -#endif /* MBEDTLS_SSL_RECORD_CHECKING */ /** * \brief Set the timer callbacks (Mandatory for DTLS.) @@ -2009,6 +2568,24 @@ void mbedtls_ssl_set_timer_cb(mbedtls_ssl_context *ssl, mbedtls_ssl_set_timer_t *f_set_timer, mbedtls_ssl_get_timer_t *f_get_timer); +#if defined(MBEDTLS_SSL_SRV_C) +/** + * \brief Set the certificate selection callback (server-side only). + * + * If set, the callback is always called for each handshake, + * after `ClientHello` processing has finished. + * + * \param conf The SSL configuration to register the callback with. + * \param f_cert_cb The callback for selecting server certificate after + * `ClientHello` processing has finished. + */ +static inline void mbedtls_ssl_conf_cert_cb(mbedtls_ssl_config *conf, + mbedtls_ssl_hs_cb_t f_cert_cb) +{ + conf->MBEDTLS_PRIVATE(f_cert_cb) = f_cert_cb; +} +#endif /* MBEDTLS_SSL_SRV_C */ + /** * \brief Callback type: generate and write session ticket * @@ -2035,70 +2612,6 @@ typedef int mbedtls_ssl_ticket_write_t(void *p_ticket, size_t *tlen, uint32_t *lifetime); -#if defined(MBEDTLS_SSL_EXPORT_KEYS) -/** - * \brief Callback type: Export key block and master secret - * - * \note This is required for certain uses of TLS, e.g. EAP-TLS - * (RFC 5216) and Thread. The key pointers are ephemeral and - * therefore must not be stored. The master secret and keys - * should not be used directly except as an input to a key - * derivation function. - * - * \param p_expkey Context for the callback - * \param ms Pointer to master secret (fixed length: 48 bytes) - * \param kb Pointer to key block, see RFC 5246 section 6.3 - * (variable length: 2 * maclen + 2 * keylen + 2 * ivlen). - * \param maclen MAC length - * \param keylen Key length - * \param ivlen IV length - * - * \return 0 if successful, or - * a specific MBEDTLS_ERR_XXX code. - */ -typedef int mbedtls_ssl_export_keys_t(void *p_expkey, - const unsigned char *ms, - const unsigned char *kb, - size_t maclen, - size_t keylen, - size_t ivlen); - -/** - * \brief Callback type: Export key block, master secret, - * handshake randbytes and the tls_prf function - * used to derive keys. - * - * \note This is required for certain uses of TLS, e.g. EAP-TLS - * (RFC 5216) and Thread. The key pointers are ephemeral and - * therefore must not be stored. The master secret and keys - * should not be used directly except as an input to a key - * derivation function. - * - * \param p_expkey Context for the callback. - * \param ms Pointer to master secret (fixed length: 48 bytes). - * \param kb Pointer to key block, see RFC 5246 section 6.3. - * (variable length: 2 * maclen + 2 * keylen + 2 * ivlen). - * \param maclen MAC length. - * \param keylen Key length. - * \param ivlen IV length. - * \param client_random The client random bytes. - * \param server_random The server random bytes. - * \param tls_prf_type The tls_prf enum type. - * - * \return 0 if successful, or - * a specific MBEDTLS_ERR_XXX code. - */ -typedef int mbedtls_ssl_export_keys_ext_t(void *p_expkey, - const unsigned char *ms, - const unsigned char *kb, - size_t maclen, - size_t keylen, - size_t ivlen, - const unsigned char client_random[32], - const unsigned char server_random[32], - mbedtls_tls_prf_types tls_prf_type); -#endif /* MBEDTLS_SSL_EXPORT_KEYS */ - /** * \brief Callback type: parse and load session ticket * @@ -2146,39 +2659,220 @@ void mbedtls_ssl_conf_session_tickets_cb(mbedtls_ssl_config *conf, mbedtls_ssl_ticket_write_t *f_ticket_write, mbedtls_ssl_ticket_parse_t *f_ticket_parse, void *p_ticket); + +#if defined(MBEDTLS_HAVE_TIME) +/** + * \brief Get the creation time of a session ticket. + * + * \note See the documentation of \c ticket_creation_time for information about + * the intended usage of this function. + * + * \param session SSL session + * \param ticket_creation_time On exit, holds the ticket creation time in + * milliseconds. + * + * \return 0 on success, + * MBEDTLS_ERR_SSL_BAD_INPUT_DATA if an input is not valid. + */ +static inline int mbedtls_ssl_session_get_ticket_creation_time( + mbedtls_ssl_session *session, mbedtls_ms_time_t *ticket_creation_time) +{ + if (session == NULL || ticket_creation_time == NULL || + session->MBEDTLS_PRIVATE(endpoint) != MBEDTLS_SSL_IS_SERVER) { + return MBEDTLS_ERR_SSL_BAD_INPUT_DATA; + } + + *ticket_creation_time = session->MBEDTLS_PRIVATE(ticket_creation_time); + + return 0; +} +#endif /* MBEDTLS_HAVE_TIME */ #endif /* MBEDTLS_SSL_SESSION_TICKETS && MBEDTLS_SSL_SRV_C */ -#if defined(MBEDTLS_SSL_EXPORT_KEYS) /** - * \brief Configure key export callback. - * (Default: none.) + * \brief Get the session-id buffer. * - * \note See \c mbedtls_ssl_export_keys_t. + * \param session SSL session. * - * \param conf SSL configuration context - * \param f_export_keys Callback for exporting keys - * \param p_export_keys Context for the callback + * \return The address of the session-id buffer. */ -void mbedtls_ssl_conf_export_keys_cb(mbedtls_ssl_config *conf, - mbedtls_ssl_export_keys_t *f_export_keys, - void *p_export_keys); +static inline unsigned const char (*mbedtls_ssl_session_get_id(const mbedtls_ssl_session * + session))[32] +{ + return &session->MBEDTLS_PRIVATE(id); +} /** - * \brief Configure extended key export callback. - * (Default: none.) + * \brief Get the size of the session-id. * - * \note See \c mbedtls_ssl_export_keys_ext_t. - * \warning Exported key material must not be used for any purpose - * before the (D)TLS handshake is completed + * \param session SSL session. * - * \param conf SSL configuration context - * \param f_export_keys_ext Callback for exporting keys - * \param p_export_keys Context for the callback + * \return size_t size of session-id buffer. */ -void mbedtls_ssl_conf_export_keys_ext_cb(mbedtls_ssl_config *conf, - mbedtls_ssl_export_keys_ext_t *f_export_keys_ext, - void *p_export_keys); -#endif /* MBEDTLS_SSL_EXPORT_KEYS */ +static inline size_t mbedtls_ssl_session_get_id_len(const mbedtls_ssl_session *session) +{ + return session->MBEDTLS_PRIVATE(id_len); +} + +/** + * \brief Get the ciphersuite-id. + * + * \param session SSL session. + * + * \return int represetation for ciphersuite. + */ +static inline int mbedtls_ssl_session_get_ciphersuite_id(const mbedtls_ssl_session *session) +{ + return session->MBEDTLS_PRIVATE(ciphersuite); +} + +/** + * \brief Configure a key export callback. + * (Default: none.) + * + * This API can be used for two purposes: + * - Debugging: Use this API to e.g. generate an NSSKeylog + * file and use it to inspect encrypted traffic in tools + * such as Wireshark. + * - Application-specific export: Use this API to implement + * key exporters, e.g. for EAP-TLS or DTLS-SRTP. + * + * + * \param ssl The SSL context to which the export + * callback should be attached. + * \param f_export_keys The callback for the key export. + * \param p_export_keys The opaque context pointer to be passed to the + * callback \p f_export_keys. + */ +void mbedtls_ssl_set_export_keys_cb(mbedtls_ssl_context *ssl, + mbedtls_ssl_export_keys_t *f_export_keys, + void *p_export_keys); + +/** \brief Set the user data in an SSL configuration to a pointer. + * + * You can retrieve this value later with mbedtls_ssl_conf_get_user_data_p(). + * + * \note The library stores \c p without accessing it. It is the responsibility + * of the caller to ensure that the pointer remains valid. + * + * \param conf The SSL configuration context to modify. + * \param p The new value of the user data. + */ +static inline void mbedtls_ssl_conf_set_user_data_p( + mbedtls_ssl_config *conf, + void *p) +{ + conf->MBEDTLS_PRIVATE(user_data).p = p; +} + +/** \brief Set the user data in an SSL configuration to an integer. + * + * You can retrieve this value later with mbedtls_ssl_conf_get_user_data_n(). + * + * \param conf The SSL configuration context to modify. + * \param n The new value of the user data. + */ +static inline void mbedtls_ssl_conf_set_user_data_n( + mbedtls_ssl_config *conf, + uintptr_t n) +{ + conf->MBEDTLS_PRIVATE(user_data).n = n; +} + +/** \brief Retrieve the user data in an SSL configuration as a pointer. + * + * This is the value last set with mbedtls_ssl_conf_set_user_data_p(), or + * \c NULL if mbedtls_ssl_conf_set_user_data_p() has not previously been + * called. The value is undefined if mbedtls_ssl_conf_set_user_data_n() has + * been called without a subsequent call to mbedtls_ssl_conf_set_user_data_p(). + * + * \param conf The SSL configuration context to modify. + * \return The current value of the user data. + */ +static inline void *mbedtls_ssl_conf_get_user_data_p( + mbedtls_ssl_config *conf) +{ + return conf->MBEDTLS_PRIVATE(user_data).p; +} + +/** \brief Retrieve the user data in an SSL configuration as an integer. + * + * This is the value last set with mbedtls_ssl_conf_set_user_data_n(), or + * \c 0 if mbedtls_ssl_conf_set_user_data_n() has not previously been + * called. The value is undefined if mbedtls_ssl_conf_set_user_data_p() has + * been called without a subsequent call to mbedtls_ssl_conf_set_user_data_n(). + * + * \param conf The SSL configuration context to modify. + * \return The current value of the user data. + */ +static inline uintptr_t mbedtls_ssl_conf_get_user_data_n( + mbedtls_ssl_config *conf) +{ + return conf->MBEDTLS_PRIVATE(user_data).n; +} + +/** \brief Set the user data in an SSL context to a pointer. + * + * You can retrieve this value later with mbedtls_ssl_get_user_data_p(). + * + * \note The library stores \c p without accessing it. It is the responsibility + * of the caller to ensure that the pointer remains valid. + * + * \param ssl The SSL context to modify. + * \param p The new value of the user data. + */ +static inline void mbedtls_ssl_set_user_data_p( + mbedtls_ssl_context *ssl, + void *p) +{ + ssl->MBEDTLS_PRIVATE(user_data).p = p; +} + +/** \brief Set the user data in an SSL context to an integer. + * + * You can retrieve this value later with mbedtls_ssl_get_user_data_n(). + * + * \param ssl The SSL context to modify. + * \param n The new value of the user data. + */ +static inline void mbedtls_ssl_set_user_data_n( + mbedtls_ssl_context *ssl, + uintptr_t n) +{ + ssl->MBEDTLS_PRIVATE(user_data).n = n; +} + +/** \brief Retrieve the user data in an SSL context as a pointer. + * + * This is the value last set with mbedtls_ssl_set_user_data_p(), or + * \c NULL if mbedtls_ssl_set_user_data_p() has not previously been + * called. The value is undefined if mbedtls_ssl_set_user_data_n() has + * been called without a subsequent call to mbedtls_ssl_set_user_data_p(). + * + * \param ssl The SSL context to modify. + * \return The current value of the user data. + */ +static inline void *mbedtls_ssl_get_user_data_p( + mbedtls_ssl_context *ssl) +{ + return ssl->MBEDTLS_PRIVATE(user_data).p; +} + +/** \brief Retrieve the user data in an SSL context as an integer. + * + * This is the value last set with mbedtls_ssl_set_user_data_n(), or + * \c 0 if mbedtls_ssl_set_user_data_n() has not previously been + * called. The value is undefined if mbedtls_ssl_set_user_data_p() has + * been called without a subsequent call to mbedtls_ssl_set_user_data_n(). + * + * \param ssl The SSL context to modify. + * \return The current value of the user data. + */ +static inline uintptr_t mbedtls_ssl_get_user_data_n( + mbedtls_ssl_context *ssl) +{ + return ssl->MBEDTLS_PRIVATE(user_data).n; +} #if defined(MBEDTLS_SSL_ASYNC_PRIVATE) /** @@ -2372,7 +3066,6 @@ int mbedtls_ssl_set_client_transport_id(mbedtls_ssl_context *ssl, void mbedtls_ssl_conf_dtls_anti_replay(mbedtls_ssl_config *conf, char mode); #endif /* MBEDTLS_SSL_DTLS_ANTI_REPLAY */ -#if defined(MBEDTLS_SSL_DTLS_BADMAC_LIMIT) /** * \brief Set a limit on the number of records with a bad MAC * before terminating the connection. @@ -2397,7 +3090,6 @@ void mbedtls_ssl_conf_dtls_anti_replay(mbedtls_ssl_config *conf, char mode); * many bogus packets. */ void mbedtls_ssl_conf_dtls_badmac_limit(mbedtls_ssl_config *conf, unsigned limit); -#endif /* MBEDTLS_SSL_DTLS_BADMAC_LIMIT */ #if defined(MBEDTLS_SSL_PROTO_DTLS) @@ -2506,24 +3198,55 @@ void mbedtls_ssl_conf_handshake_timeout(mbedtls_ssl_config *conf, uint32_t min, */ void mbedtls_ssl_conf_session_cache(mbedtls_ssl_config *conf, void *p_cache, - int (*f_get_cache)(void *, mbedtls_ssl_session *), - int (*f_set_cache)(void *, const mbedtls_ssl_session *)); + mbedtls_ssl_cache_get_t *f_get_cache, + mbedtls_ssl_cache_set_t *f_set_cache); #endif /* MBEDTLS_SSL_SRV_C */ #if defined(MBEDTLS_SSL_CLI_C) /** - * \brief Request resumption of session (client-side only) - * Session data is copied from presented session structure. + * \brief Load a session for session resumption. + * + * Sessions loaded through this call will be considered + * for session resumption in the next handshake. + * + * \note Even if this call succeeds, it is not guaranteed that + * the next handshake will indeed be shortened through the + * use of session resumption: The server is always free + * to reject any attempt for resumption and fall back to + * a full handshake. + * + * \note This function can handle a variety of mechanisms for session + * resumption: For TLS 1.2, both session ID-based resumption and + * ticket-based resumption will be considered. For TLS 1.3, + * once implemented, sessions equate to tickets, and loading + * one or more sessions via this call will lead to their + * corresponding tickets being advertised as resumption PSKs + * by the client. + * + * \note Calling this function multiple times will only be useful + * once TLS 1.3 is supported. For TLS 1.2 connections, this + * function should be called at most once. + * + * \param ssl The SSL context representing the connection which should + * be attempted to be setup using session resumption. This + * must be initialized via mbedtls_ssl_init() and bound to + * an SSL configuration via mbedtls_ssl_setup(), but + * the handshake must not yet have been started. + * \param session The session to be considered for session resumption. + * This must be a session previously exported via + * mbedtls_ssl_get_session(), and potentially serialized and + * deserialized through mbedtls_ssl_session_save() and + * mbedtls_ssl_session_load() in the meantime. * - * \param ssl SSL context - * \param session session context - * - * \return 0 if successful, - * MBEDTLS_ERR_SSL_ALLOC_FAILED if memory allocation failed, - * MBEDTLS_ERR_SSL_BAD_INPUT_DATA if used server-side or - * arguments are otherwise invalid + * \return \c 0 if successful. + * \return \c MBEDTLS_ERR_SSL_FEATURE_UNAVAILABLE if the session + * could not be loaded because of an implementation limitation. + * This error is non-fatal, and has no observable effect on + * the SSL context or the session that was attempted to be loaded. + * \return Another negative error code on other kinds of failure. * * \sa mbedtls_ssl_get_session() + * \sa mbedtls_ssl_session_load() */ int mbedtls_ssl_set_session(mbedtls_ssl_context *ssl, const mbedtls_ssl_session *session); #endif /* MBEDTLS_SSL_CLI_C */ @@ -2572,7 +3295,6 @@ int mbedtls_ssl_session_load(mbedtls_ssl_session *session, * of session cache or session tickets. * * \see mbedtls_ssl_session_load() - * \see mbedtls_ssl_get_session_pointer() * * \param session The session structure to be saved. * \param buf The buffer to write the serialized data to. It must be a @@ -2595,41 +3317,97 @@ int mbedtls_ssl_session_save(const mbedtls_ssl_session *session, size_t buf_len, size_t *olen); -/** - * \brief Get a pointer to the current session structure, for example - * to serialize it. - * - * \warning Ownership of the session remains with the SSL context, and - * the returned pointer is only guaranteed to be valid until - * the next API call operating on the same \p ssl context. - * - * \see mbedtls_ssl_session_save() - * - * \param ssl The SSL context. - * - * \return A pointer to the current session if successful. - * \return \c NULL if no session is active. - */ -const mbedtls_ssl_session *mbedtls_ssl_get_session_pointer(const mbedtls_ssl_context *ssl); - /** * \brief Set the list of allowed ciphersuites and the preference * order. First in the list has the highest preference. - * (Overrides all version-specific lists) - * - * The ciphersuites array is not copied, and must remain - * valid for the lifetime of the ssl_config. * - * Note: The server uses its own preferences - * over the preference of the client unless - * MBEDTLS_SSL_SRV_RESPECT_CLIENT_PREFERENCE is defined! + * For TLS 1.2, the notion of ciphersuite determines both + * the key exchange mechanism and the suite of symmetric + * algorithms to be used during and after the handshake. + * + * For TLS 1.3 (in development), the notion of ciphersuite + * only determines the suite of symmetric algorithms to be + * used during and after the handshake, while key exchange + * mechanisms are configured separately. + * + * In Mbed TLS, ciphersuites for both TLS 1.2 and TLS 1.3 + * are configured via this function. For users of TLS 1.3, + * there will be separate API for the configuration of key + * exchange mechanisms. + * + * The list of ciphersuites passed to this function may + * contain a mixture of TLS 1.2 and TLS 1.3 ciphersuite + * identifiers. This is useful if negotiation of TLS 1.3 + * should be attempted, but a fallback to TLS 1.2 would + * be tolerated. + * + * \note By default, the server chooses its preferred + * ciphersuite among those that the client supports. If + * mbedtls_ssl_conf_preference_order() is called to prefer + * the client's preferences, the server instead chooses + * the client's preferred ciphersuite among those that + * the server supports. + * + * \warning The ciphersuites array \p ciphersuites is not copied. + * It must remain valid for the lifetime of the SSL + * configuration \p conf. * - * \param conf SSL configuration - * \param ciphersuites 0-terminated list of allowed ciphersuites + * \param conf The SSL configuration to modify. + * \param ciphersuites A 0-terminated list of IANA identifiers of supported + * ciphersuites, accessible through \c MBEDTLS_TLS_XXX + * and \c MBEDTLS_TLS1_3_XXX macros defined in + * ssl_ciphersuites.h. */ void mbedtls_ssl_conf_ciphersuites(mbedtls_ssl_config *conf, const int *ciphersuites); +#if defined(MBEDTLS_SSL_PROTO_TLS1_3) +/** + * \brief Set the supported key exchange modes for TLS 1.3 connections. + * + * In contrast to TLS 1.2, the ciphersuite concept in TLS 1.3 does not + * include the choice of key exchange mechanism. It is therefore not + * covered by the API mbedtls_ssl_conf_ciphersuites(). See the + * documentation of mbedtls_ssl_conf_ciphersuites() for more + * information on the ciphersuite concept in TLS 1.2 and TLS 1.3. + * + * The present function is specific to TLS 1.3 and allows users to + * configure the set of supported key exchange mechanisms in TLS 1.3. + * + * \param conf The SSL configuration the change should apply to. + * \param kex_modes A bitwise combination of one or more of the following: + * - MBEDTLS_SSL_TLS1_3_KEY_EXCHANGE_MODE_PSK + * This flag enables pure-PSK key exchanges. + * - MBEDTLS_SSL_TLS1_3_KEY_EXCHANGE_MODE_PSK_EPHEMERAL + * This flag enables combined PSK-ephemeral key exchanges. + * - MBEDTLS_SSL_TLS1_3_KEY_EXCHANGE_MODE_EPHEMERAL + * This flag enables pure-ephemeral key exchanges. + * For convenience, the following pre-defined macros are + * available for combinations of the above: + * - MBEDTLS_SSL_TLS1_3_KEY_EXCHANGE_MODE_ALL + * Includes all of pure-PSK, PSK-ephemeral and pure-ephemeral. + * - MBEDTLS_SSL_TLS1_3_KEY_EXCHANGE_MODE_PSK_ALL + * Includes both pure-PSK and combined PSK-ephemeral + * key exchanges, but excludes pure-ephemeral key exchanges. + * - MBEDTLS_SSL_TLS1_3_KEY_EXCHANGE_MODE_EPHEMERAL_ALL + * Includes both pure-ephemeral and combined PSK-ephemeral + * key exchanges. + * + * \note If a PSK-based key exchange mode shall be supported, applications + * must also use the APIs mbedtls_ssl_conf_psk() or + * mbedtls_ssl_conf_psk_cb() or mbedtls_ssl_conf_psk_opaque() + * to configure the PSKs to be used. + * + * \note If a pure-ephemeral key exchange mode shall be supported, + * server-side applications must also provide a certificate via + * mbedtls_ssl_conf_own_cert(). + * + */ + +void mbedtls_ssl_conf_tls13_key_exchange_modes(mbedtls_ssl_config *conf, + const int kex_modes); +#endif /* MBEDTLS_SSL_PROTO_TLS1_3 */ + #if defined(MBEDTLS_SSL_DTLS_CONNECTION_ID) #define MBEDTLS_SSL_UNEXPECTED_CID_IGNORE 0 #define MBEDTLS_SSL_UNEXPECTED_CID_FAIL 1 @@ -2669,29 +3447,6 @@ int mbedtls_ssl_conf_cid(mbedtls_ssl_config *conf, size_t len, int ignore_other_cids); #endif /* MBEDTLS_SSL_DTLS_CONNECTION_ID */ -/** - * \brief Set the list of allowed ciphersuites and the - * preference order for a specific version of the protocol. - * (Only useful on the server side) - * - * The ciphersuites array is not copied, and must remain - * valid for the lifetime of the ssl_config. - * - * \param conf SSL configuration - * \param ciphersuites 0-terminated list of allowed ciphersuites - * \param major Major version number (only MBEDTLS_SSL_MAJOR_VERSION_3 - * supported) - * \param minor Minor version number (MBEDTLS_SSL_MINOR_VERSION_0, - * MBEDTLS_SSL_MINOR_VERSION_1 and MBEDTLS_SSL_MINOR_VERSION_2, - * MBEDTLS_SSL_MINOR_VERSION_3 supported) - * - * \note With DTLS, use MBEDTLS_SSL_MINOR_VERSION_2 for DTLS 1.0 - * and MBEDTLS_SSL_MINOR_VERSION_3 for DTLS 1.2 - */ -void mbedtls_ssl_conf_ciphersuites_for_version(mbedtls_ssl_config *conf, - const int *ciphersuites, - int major, int minor); - #if defined(MBEDTLS_X509_CRT_PARSE_C) /** * \brief Set the X.509 security profile used for verification @@ -2721,6 +3476,26 @@ void mbedtls_ssl_conf_ca_chain(mbedtls_ssl_config *conf, mbedtls_x509_crt *ca_chain, mbedtls_x509_crl *ca_crl); +#if defined(MBEDTLS_KEY_EXCHANGE_CERT_REQ_ALLOWED_ENABLED) +/** + * \brief Set DN hints sent to client in CertificateRequest message + * + * \note If not set, subject distinguished names (DNs) are taken + * from \c mbedtls_ssl_conf_ca_chain() + * or \c mbedtls_ssl_set_hs_ca_chain()) + * + * \param conf SSL configuration + * \param crt crt chain whose subject DNs are issuer DNs of client certs + * from which the client should select client peer certificate. + */ +static inline +void mbedtls_ssl_conf_dn_hints(mbedtls_ssl_config *conf, + const mbedtls_x509_crt *crt) +{ + conf->MBEDTLS_PRIVATE(dn_hints) = crt; +} +#endif /* MBEDTLS_KEY_EXCHANGE_CERT_REQ_ALLOWED_ENABLED */ + #if defined(MBEDTLS_X509_TRUSTED_CERTIFICATE_CALLBACK) /** * \brief Set the trusted certificate callback. @@ -2819,10 +3594,16 @@ int mbedtls_ssl_conf_own_cert(mbedtls_ssl_config *conf, mbedtls_pk_context *pk_key); #endif /* MBEDTLS_X509_CRT_PARSE_C */ -#if defined(MBEDTLS_KEY_EXCHANGE_SOME_PSK_ENABLED) +#if defined(MBEDTLS_SSL_HANDSHAKE_WITH_PSK_ENABLED) /** - * \brief Configure a pre-shared key (PSK) and identity - * to be used in PSK-based ciphersuites. + * \brief Configure pre-shared keys (PSKs) and their + * identities to be used in PSK-based ciphersuites. + * + * Only one PSK can be registered, through either + * mbedtls_ssl_conf_psk() or mbedtls_ssl_conf_psk_opaque(). + * If you attempt to register more than one PSK, this function + * fails, though this may change in future versions, which + * may add support for multiple PSKs. * * \note This is mainly useful for clients. Servers will usually * want to use \c mbedtls_ssl_conf_psk_cb() instead. @@ -2830,13 +3611,6 @@ int mbedtls_ssl_conf_own_cert(mbedtls_ssl_config *conf, * \note A PSK set by \c mbedtls_ssl_set_hs_psk() in the PSK callback * takes precedence over a PSK configured by this function. * - * \warning Currently, clients can only register a single pre-shared key. - * Calling this function or mbedtls_ssl_conf_psk_opaque() more - * than once will overwrite values configured in previous calls. - * Support for setting multiple PSKs on clients and selecting - * one based on the identity hint is not a planned feature, - * but feedback is welcomed. - * * \param conf The SSL configuration to register the PSK with. * \param psk The pointer to the pre-shared key to use. * \param psk_len The length of the pre-shared key in bytes. @@ -2849,7 +3623,9 @@ int mbedtls_ssl_conf_own_cert(mbedtls_ssl_config *conf, * of the SSL configuration. * * \return \c 0 if successful. - * \return An \c MBEDTLS_ERR_SSL_XXX error code on failure. + * \return #MBEDTLS_ERR_SSL_FEATURE_UNAVAILABLE if no more PSKs + * can be configured. In this case, the old PSK(s) remain intact. + * \return Another negative error code on other kinds of failure. */ int mbedtls_ssl_conf_psk(mbedtls_ssl_config *conf, const unsigned char *psk, size_t psk_len, @@ -2857,8 +3633,14 @@ int mbedtls_ssl_conf_psk(mbedtls_ssl_config *conf, #if defined(MBEDTLS_USE_PSA_CRYPTO) /** - * \brief Configure an opaque pre-shared key (PSK) and identity - * to be used in PSK-based ciphersuites. + * \brief Configure one or more opaque pre-shared keys (PSKs) and + * their identities to be used in PSK-based ciphersuites. + * + * Only one PSK can be registered, through either + * mbedtls_ssl_conf_psk() or mbedtls_ssl_conf_psk_opaque(). + * If you attempt to register more than one PSK, this function + * fails, though this may change in future versions, which + * may add support for multiple PSKs. * * \note This is mainly useful for clients. Servers will usually * want to use \c mbedtls_ssl_conf_psk_cb() instead. @@ -2867,13 +3649,6 @@ int mbedtls_ssl_conf_psk(mbedtls_ssl_config *conf, * the PSK callback takes precedence over an opaque PSK * configured by this function. * - * \warning Currently, clients can only register a single pre-shared key. - * Calling this function or mbedtls_ssl_conf_psk() more than - * once will overwrite values configured in previous calls. - * Support for setting multiple PSKs on clients and selecting - * one based on the identity hint is not a planned feature, - * but feedback is welcomed. - * * \param conf The SSL configuration to register the PSK with. * \param psk The identifier of the key slot holding the PSK. * Until \p conf is destroyed or this function is successfully @@ -2890,10 +3665,12 @@ int mbedtls_ssl_conf_psk(mbedtls_ssl_config *conf, * SSL configuration. * * \return \c 0 if successful. - * \return An \c MBEDTLS_ERR_SSL_XXX error code on failure. + * \return #MBEDTLS_ERR_SSL_FEATURE_UNAVAILABLE if no more PSKs + * can be configured. In this case, the old PSK(s) remain intact. + * \return Another negative error code on other kinds of failure. */ int mbedtls_ssl_conf_psk_opaque(mbedtls_ssl_config *conf, - psa_key_id_t psk, + mbedtls_svc_key_id_t psk, const unsigned char *psk_identity, size_t psk_identity_len); #endif /* MBEDTLS_USE_PSA_CRYPTO */ @@ -2939,9 +3716,10 @@ int mbedtls_ssl_set_hs_psk(mbedtls_ssl_context *ssl, * \return An \c MBEDTLS_ERR_SSL_XXX error code on failure. */ int mbedtls_ssl_set_hs_psk_opaque(mbedtls_ssl_context *ssl, - psa_key_id_t psk); + mbedtls_svc_key_id_t psk); #endif /* MBEDTLS_USE_PSA_CRYPTO */ +#if defined(MBEDTLS_SSL_SRV_C) /** * \brief Set the PSK callback (server-side only). * @@ -2984,37 +3762,10 @@ void mbedtls_ssl_conf_psk_cb(mbedtls_ssl_config *conf, int (*f_psk)(void *, mbedtls_ssl_context *, const unsigned char *, size_t), void *p_psk); -#endif /* MBEDTLS_KEY_EXCHANGE_SOME_PSK_ENABLED */ +#endif /* MBEDTLS_SSL_SRV_C */ +#endif /* MBEDTLS_SSL_HANDSHAKE_WITH_PSK_ENABLED */ #if defined(MBEDTLS_DHM_C) && defined(MBEDTLS_SSL_SRV_C) - -#if !defined(MBEDTLS_DEPRECATED_REMOVED) - -#if defined(MBEDTLS_DEPRECATED_WARNING) -#define MBEDTLS_DEPRECATED __attribute__((deprecated)) -#else -#define MBEDTLS_DEPRECATED -#endif - -/** - * \brief Set the Diffie-Hellman public P and G values, - * read as hexadecimal strings (server-side only) - * (Default values: MBEDTLS_DHM_RFC3526_MODP_2048_[PG]) - * - * \param conf SSL configuration - * \param dhm_P Diffie-Hellman-Merkle modulus - * \param dhm_G Diffie-Hellman-Merkle generator - * - * \deprecated Superseded by \c mbedtls_ssl_conf_dh_param_bin. - * - * \return 0 if successful - */ -MBEDTLS_DEPRECATED int mbedtls_ssl_conf_dh_param(mbedtls_ssl_config *conf, - const char *dhm_P, - const char *dhm_G); - -#endif /* MBEDTLS_DEPRECATED_REMOVED */ - /** * \brief Set the Diffie-Hellman public P and G values * from big-endian binary presentations. @@ -3058,11 +3809,9 @@ void mbedtls_ssl_conf_dhm_min_bitlen(mbedtls_ssl_config *conf, #endif /* MBEDTLS_DHM_C && MBEDTLS_SSL_CLI_C */ #if defined(MBEDTLS_ECP_C) +#if !defined(MBEDTLS_DEPRECATED_REMOVED) /** * \brief Set the allowed curves in order of preference. - * (Default: all defined curves in order of decreasing size, - * except that Montgomery curves come last. This order - * is likely to change in a future version.) * * On server: this only affects selection of the ECDHE curve; * the curves used for ECDH and ECDSA are determined by the @@ -3074,6 +3823,8 @@ void mbedtls_ssl_conf_dhm_min_bitlen(mbedtls_ssl_config *conf, * Both sides: limits the set of curves accepted for use in * ECDHE and in the peer's end-entity certificate. * + * \deprecated Superseded by mbedtls_ssl_conf_groups(). + * * \note This has no influence on which curves are allowed inside the * certificate chains, see \c mbedtls_ssl_conf_cert_profile() * for that. For the end-entity certificate however, the key @@ -3083,20 +3834,72 @@ void mbedtls_ssl_conf_dhm_min_bitlen(mbedtls_ssl_config *conf, * \note This list should be ordered by decreasing preference * (preferred curve first). * + * \note The default list is the same set of curves that + * #mbedtls_x509_crt_profile_default allows, plus + * ECDHE-only curves selected according to the same criteria. + * The order favors curves with the lowest resource usage. + * + * \note New minor versions of Mbed TLS may extend this list, + * for example if new curves are added to the library. + * New minor versions of Mbed TLS will not remove items + * from this list unless serious security concerns require it. + * New minor versions of Mbed TLS may change the order in + * keeping with the general principle of favoring the lowest + * resource usage. + * * \param conf SSL configuration * \param curves Ordered list of allowed curves, * terminated by MBEDTLS_ECP_DP_NONE. */ -void mbedtls_ssl_conf_curves(mbedtls_ssl_config *conf, - const mbedtls_ecp_group_id *curves); +void MBEDTLS_DEPRECATED mbedtls_ssl_conf_curves(mbedtls_ssl_config *conf, + const mbedtls_ecp_group_id *curves); +#endif /* MBEDTLS_DEPRECATED_REMOVED */ #endif /* MBEDTLS_ECP_C */ -#if defined(MBEDTLS_KEY_EXCHANGE_WITH_CERT_ENABLED) +/** + * \brief Set the allowed groups in order of preference. + * + * On server: This only affects the choice of key agreement mechanism + * + * On client: this affects the list of groups offered for any + * use. The server can override our preference order. + * + * Both sides: limits the set of groups accepted for use in + * key sharing. + * + * \note This function replaces the deprecated mbedtls_ssl_conf_curves(), + * which only allows ECP curves to be configured. + * + * \note The most recent invocation of either mbedtls_ssl_conf_curves() + * or mbedtls_ssl_conf_groups() nullifies all previous invocations + * of both. + * + * \note This list should be ordered by decreasing preference + * (preferred group first). + * + * \note When this function is not called, a default list is used, + * consisting of all supported curves at 255 bits and above, + * and all supported finite fields at 2048 bits and above. + * The order favors groups with the lowest resource usage. + * + * \note New minor versions of Mbed TLS will not remove items + * from the default list unless serious security concerns require it. + * New minor versions of Mbed TLS may change the order in + * keeping with the general principle of favoring the lowest + * resource usage. + * + * \param conf SSL configuration + * \param groups List of allowed groups ordered by preference, terminated by 0. + * Must contain valid IANA NamedGroup IDs (provided via either an integer + * or using MBEDTLS_TLS1_3_NAMED_GROUP_XXX macros). + */ +void mbedtls_ssl_conf_groups(mbedtls_ssl_config *conf, + const uint16_t *groups); + +#if defined(MBEDTLS_SSL_HANDSHAKE_WITH_CERT_ENABLED) +#if !defined(MBEDTLS_DEPRECATED_REMOVED) && defined(MBEDTLS_SSL_PROTO_TLS1_2) /** * \brief Set the allowed hashes for signatures during the handshake. - * (Default: all SHA-2 hashes, largest first. Also SHA-1 if - * the compile-time option - * `MBEDTLS_TLS_DEFAULT_ALLOW_SHA1_IN_KEY_EXCHANGE` is enabled.) * * \note This only affects which hashes are offered and can be used * for signatures during the handshake. Hashes for message @@ -3105,16 +3908,46 @@ void mbedtls_ssl_conf_curves(mbedtls_ssl_config *conf, * used for certificate signature are controlled by the * verification profile, see \c mbedtls_ssl_conf_cert_profile(). * + * \deprecated Superseded by mbedtls_ssl_conf_sig_algs(). + * * \note This list should be ordered by decreasing preference * (preferred hash first). * + * \note By default, all supported hashes whose length is at least + * 256 bits are allowed. This is the same set as the default + * for certificate verification + * (#mbedtls_x509_crt_profile_default). + * The preference order is currently unspecified and may + * change in future versions. + * + * \note New minor versions of Mbed TLS may extend this list, + * for example if new curves are added to the library. + * New minor versions of Mbed TLS will not remove items + * from this list unless serious security concerns require it. + * * \param conf SSL configuration * \param hashes Ordered list of allowed signature hashes, * terminated by \c MBEDTLS_MD_NONE. */ -void mbedtls_ssl_conf_sig_hashes(mbedtls_ssl_config *conf, - const int *hashes); -#endif /* MBEDTLS_KEY_EXCHANGE_WITH_CERT_ENABLED */ +void MBEDTLS_DEPRECATED mbedtls_ssl_conf_sig_hashes(mbedtls_ssl_config *conf, + const int *hashes); +#endif /* !MBEDTLS_DEPRECATED_REMOVED && MBEDTLS_SSL_PROTO_TLS1_2 */ + +/** + * \brief Configure allowed signature algorithms for use in TLS + * + * \param conf The SSL configuration to use. + * \param sig_algs List of allowed IANA values for TLS 1.3 signature algorithms, + * terminated by #MBEDTLS_TLS1_3_SIG_NONE. The list must remain + * available throughout the lifetime of the conf object. + * - For TLS 1.3, values of \c MBEDTLS_TLS1_3_SIG_XXXX should be + * used. + * - For TLS 1.2, values should be given as + * "(HashAlgorithm << 8) | SignatureAlgorithm". + */ +void mbedtls_ssl_conf_sig_algs(mbedtls_ssl_config *conf, + const uint16_t *sig_algs); +#endif /* MBEDTLS_SSL_HANDSHAKE_WITH_CERT_ENABLED */ #if defined(MBEDTLS_X509_CRT_PARSE_C) /** @@ -3136,14 +3969,53 @@ void mbedtls_ssl_conf_sig_hashes(mbedtls_ssl_config *conf, * On too long input failure, old hostname is unchanged. */ int mbedtls_ssl_set_hostname(mbedtls_ssl_context *ssl, const char *hostname); + +/** + * \brief Get the hostname that checked against the received + * server certificate. It is used to set the ServerName + * TLS extension, too, if that extension is enabled. + * (client-side only) + * + * \param ssl SSL context + * + * \return const pointer to the hostname value + */ +static inline const char *mbedtls_ssl_get_hostname(mbedtls_ssl_context *ssl) +{ + return ssl->MBEDTLS_PRIVATE(hostname); +} #endif /* MBEDTLS_X509_CRT_PARSE_C */ #if defined(MBEDTLS_SSL_SERVER_NAME_INDICATION) +/** + * \brief Retrieve SNI extension value for the current handshake. + * Available in \c f_cert_cb of \c mbedtls_ssl_conf_cert_cb(), + * this is the same value passed to \c f_sni callback of + * \c mbedtls_ssl_conf_sni() and may be used instead of + * \c mbedtls_ssl_conf_sni(). + * + * \param ssl SSL context + * \param name_len pointer into which to store length of returned value. + * 0 if SNI extension is not present or not yet processed. + * + * \return const pointer to SNI extension value. + * - value is valid only when called in \c f_cert_cb + * registered with \c mbedtls_ssl_conf_cert_cb(). + * - value is NULL if SNI extension is not present. + * - value is not '\0'-terminated. Use \c name_len for len. + * - value must not be freed. + */ +const unsigned char *mbedtls_ssl_get_hs_sni(mbedtls_ssl_context *ssl, + size_t *name_len); + /** * \brief Set own certificate and key for the current handshake * * \note Same as \c mbedtls_ssl_conf_own_cert() but for use within - * the SNI callback. + * the SNI callback or the certificate selection callback. + * + * \note Passing null \c own_cert clears the certificate list for + * the current handshake. * * \param ssl SSL context * \param own_cert own public certificate chain @@ -3160,7 +4032,7 @@ int mbedtls_ssl_set_hs_own_cert(mbedtls_ssl_context *ssl, * current handshake * * \note Same as \c mbedtls_ssl_conf_ca_chain() but for use within - * the SNI callback. + * the SNI callback or the certificate selection callback. * * \param ssl SSL context * \param ca_chain trusted CA chain (meaning all fully trusted top-level CAs) @@ -3170,11 +4042,26 @@ void mbedtls_ssl_set_hs_ca_chain(mbedtls_ssl_context *ssl, mbedtls_x509_crt *ca_chain, mbedtls_x509_crl *ca_crl); +#if defined(MBEDTLS_KEY_EXCHANGE_CERT_REQ_ALLOWED_ENABLED) +/** + * \brief Set DN hints sent to client in CertificateRequest message + * + * \note Same as \c mbedtls_ssl_conf_dn_hints() but for use within + * the SNI callback or the certificate selection callback. + * + * \param ssl SSL context + * \param crt crt chain whose subject DNs are issuer DNs of client certs + * from which the client should select client peer certificate. + */ +void mbedtls_ssl_set_hs_dn_hints(mbedtls_ssl_context *ssl, + const mbedtls_x509_crt *crt); +#endif /* MBEDTLS_KEY_EXCHANGE_CERT_REQ_ALLOWED_ENABLED */ + /** * \brief Set authmode for the current handshake. * * \note Same as \c mbedtls_ssl_conf_authmode() but for use within - * the SNI callback. + * the SNI callback or the certificate selection callback. * * \param ssl SSL context * \param authmode MBEDTLS_SSL_VERIFY_NONE, MBEDTLS_SSL_VERIFY_OPTIONAL or @@ -3199,8 +4086,7 @@ void mbedtls_ssl_set_hs_authmode(mbedtls_ssl_context *ssl, * mbedtls_ssl_set_hs_ca_chain() as well as the client * authentication mode with \c mbedtls_ssl_set_hs_authmode(), * then must return 0. If no matching name is found, the - * callback must either set a default cert, or - * return non-zero to abort the handshake at this point. + * callback may return non-zero to abort the handshake. * * \param conf SSL configuration * \param f_sni verification function @@ -3223,9 +4109,10 @@ void mbedtls_ssl_conf_sni(mbedtls_ssl_config *conf, * \note The SSL context needs to be already set up. The right place * to call this function is between \c mbedtls_ssl_setup() or * \c mbedtls_ssl_reset() and \c mbedtls_ssl_handshake(). + * Password cannot be empty (see RFC 8236). * * \param ssl SSL context - * \param pw EC J-PAKE password (pre-shared secret) + * \param pw EC J-PAKE password (pre-shared secret). It cannot be empty * \param pw_len length of pw in bytes * * \return 0 on success, or a negative error code. @@ -3233,6 +4120,23 @@ void mbedtls_ssl_conf_sni(mbedtls_ssl_config *conf, int mbedtls_ssl_set_hs_ecjpake_password(mbedtls_ssl_context *ssl, const unsigned char *pw, size_t pw_len); + +/** + * \brief Set the EC J-PAKE opaque password for current handshake. + * + * \note The key must remain valid until the handshake is over. + * + * \note The SSL context needs to be already set up. The right place + * to call this function is between \c mbedtls_ssl_setup() or + * \c mbedtls_ssl_reset() and \c mbedtls_ssl_handshake(). + * + * \param ssl SSL context + * \param pwd EC J-PAKE opaque password + * + * \return 0 on success, or a negative error code. + */ +int mbedtls_ssl_set_hs_ecjpake_password_opaque(mbedtls_ssl_context *ssl, + mbedtls_svc_key_id_t pwd); #endif /*MBEDTLS_KEY_EXCHANGE_ECJPAKE_ENABLED */ #if defined(MBEDTLS_SSL_ALPN) @@ -3360,66 +4264,102 @@ void mbedtls_ssl_get_dtls_srtp_negotiation_result(const mbedtls_ssl_context *ssl mbedtls_dtls_srtp_info *dtls_srtp_info); #endif /* MBEDTLS_SSL_DTLS_SRTP */ +#if !defined(MBEDTLS_DEPRECATED_REMOVED) /** * \brief Set the maximum supported version sent from the client side - * and/or accepted at the server side - * (Default: MBEDTLS_SSL_MAX_MAJOR_VERSION, MBEDTLS_SSL_MAX_MINOR_VERSION) + * and/or accepted at the server side. + * + * See also the documentation of mbedtls_ssl_conf_min_version(). * * \note This ignores ciphersuites from higher versions. * - * \note With DTLS, use MBEDTLS_SSL_MINOR_VERSION_2 for DTLS 1.0 and - * MBEDTLS_SSL_MINOR_VERSION_3 for DTLS 1.2 + * \note This function is deprecated and has been replaced by + * \c mbedtls_ssl_conf_max_tls_version(). * * \param conf SSL configuration - * \param major Major version number (only MBEDTLS_SSL_MAJOR_VERSION_3 supported) - * \param minor Minor version number (MBEDTLS_SSL_MINOR_VERSION_0, - * MBEDTLS_SSL_MINOR_VERSION_1 and MBEDTLS_SSL_MINOR_VERSION_2, - * MBEDTLS_SSL_MINOR_VERSION_3 supported) + * \param major Major version number (#MBEDTLS_SSL_MAJOR_VERSION_3) + * \param minor Minor version number + * (#MBEDTLS_SSL_MINOR_VERSION_3 for (D)TLS 1.2, + * #MBEDTLS_SSL_MINOR_VERSION_4 for TLS 1.3) + */ +void MBEDTLS_DEPRECATED mbedtls_ssl_conf_max_version(mbedtls_ssl_config *conf, int major, + int minor); +#endif /* MBEDTLS_DEPRECATED_REMOVED */ + +/** + * \brief Set the maximum supported version sent from the client side + * and/or accepted at the server side. + * + * \note After the handshake, you can call + * mbedtls_ssl_get_version_number() to see what version was + * negotiated. + * + * \param conf SSL configuration + * \param tls_version TLS protocol version number (\c mbedtls_ssl_protocol_version) + * (#MBEDTLS_SSL_VERSION_UNKNOWN is not valid) */ -void mbedtls_ssl_conf_max_version(mbedtls_ssl_config *conf, int major, int minor); +static inline void mbedtls_ssl_conf_max_tls_version(mbedtls_ssl_config *conf, + mbedtls_ssl_protocol_version tls_version) +{ + conf->MBEDTLS_PRIVATE(max_tls_version) = tls_version; +} +#if !defined(MBEDTLS_DEPRECATED_REMOVED) /** * \brief Set the minimum accepted SSL/TLS protocol version - * (Default: TLS 1.0) + * + * \note By default, all supported versions are accepted. + * Future versions of the library may disable older + * protocol versions by default if they become deprecated. + * + * \note The following versions are supported (if enabled at + * compile time): + * - (D)TLS 1.2: \p major = #MBEDTLS_SSL_MAJOR_VERSION_3, + * \p minor = #MBEDTLS_SSL_MINOR_VERSION_3 + * - TLS 1.3: \p major = #MBEDTLS_SSL_MAJOR_VERSION_3, + * \p minor = #MBEDTLS_SSL_MINOR_VERSION_4 + * + * Note that the numbers in the constant names are the + * TLS internal protocol numbers, and the minor versions + * differ by one from the human-readable versions! * * \note Input outside of the SSL_MAX_XXXXX_VERSION and * SSL_MIN_XXXXX_VERSION range is ignored. * - * \note MBEDTLS_SSL_MINOR_VERSION_0 (SSL v3) should be avoided. + * \note After the handshake, you can call + * mbedtls_ssl_get_version_number() to see what version was + * negotiated. * - * \note With DTLS, use MBEDTLS_SSL_MINOR_VERSION_2 for DTLS 1.0 and - * MBEDTLS_SSL_MINOR_VERSION_3 for DTLS 1.2 + * \note This function is deprecated and has been replaced by + * \c mbedtls_ssl_conf_min_tls_version(). * * \param conf SSL configuration - * \param major Major version number (only MBEDTLS_SSL_MAJOR_VERSION_3 supported) - * \param minor Minor version number (MBEDTLS_SSL_MINOR_VERSION_0, - * MBEDTLS_SSL_MINOR_VERSION_1 and MBEDTLS_SSL_MINOR_VERSION_2, - * MBEDTLS_SSL_MINOR_VERSION_3 supported) + * \param major Major version number (#MBEDTLS_SSL_MAJOR_VERSION_3) + * \param minor Minor version number + * (#MBEDTLS_SSL_MINOR_VERSION_3 for (D)TLS 1.2, + * #MBEDTLS_SSL_MINOR_VERSION_4 for TLS 1.3) */ -void mbedtls_ssl_conf_min_version(mbedtls_ssl_config *conf, int major, int minor); +void MBEDTLS_DEPRECATED mbedtls_ssl_conf_min_version(mbedtls_ssl_config *conf, int major, + int minor); +#endif /* MBEDTLS_DEPRECATED_REMOVED */ -#if defined(MBEDTLS_SSL_FALLBACK_SCSV) && defined(MBEDTLS_SSL_CLI_C) /** - * \brief Set the fallback flag (client-side only). - * (Default: MBEDTLS_SSL_IS_NOT_FALLBACK). + * \brief Set the minimum supported version sent from the client side + * and/or accepted at the server side. * - * \note Set to MBEDTLS_SSL_IS_FALLBACK when preparing a fallback - * connection, that is a connection with max_version set to a - * lower value than the value you're willing to use. Such - * fallback connections are not recommended but are sometimes - * necessary to interoperate with buggy (version-intolerant) - * servers. + * \note After the handshake, you can call + * mbedtls_ssl_get_version_number() to see what version was + * negotiated. * - * \warning You should NOT set this to MBEDTLS_SSL_IS_FALLBACK for - * non-fallback connections! This would appear to work for a - * while, then cause failures when the server is upgraded to - * support a newer TLS version. - * - * \param conf SSL configuration - * \param fallback MBEDTLS_SSL_IS_NOT_FALLBACK or MBEDTLS_SSL_IS_FALLBACK + * \param conf SSL configuration + * \param tls_version TLS protocol version number (\c mbedtls_ssl_protocol_version) + * (#MBEDTLS_SSL_VERSION_UNKNOWN is not valid) */ -void mbedtls_ssl_conf_fallback(mbedtls_ssl_config *conf, char fallback); -#endif /* MBEDTLS_SSL_FALLBACK_SCSV && MBEDTLS_SSL_CLI_C */ +static inline void mbedtls_ssl_conf_min_tls_version(mbedtls_ssl_config *conf, + mbedtls_ssl_protocol_version tls_version) +{ + conf->MBEDTLS_PRIVATE(min_tls_version) = tls_version; +} #if defined(MBEDTLS_SSL_ENCRYPT_THEN_MAC) /** @@ -3451,25 +4391,6 @@ void mbedtls_ssl_conf_encrypt_then_mac(mbedtls_ssl_config *conf, char etm); void mbedtls_ssl_conf_extended_master_secret(mbedtls_ssl_config *conf, char ems); #endif /* MBEDTLS_SSL_EXTENDED_MASTER_SECRET */ -#if defined(MBEDTLS_ARC4_C) -/** - * \brief Disable or enable support for RC4 - * (Default: MBEDTLS_SSL_ARC4_DISABLED) - * - * \warning Use of RC4 in DTLS/TLS has been prohibited by RFC 7465 - * for security reasons. Use at your own risk. - * - * \note This function is deprecated and will be removed in - * a future version of the library. - * RC4 is disabled by default at compile time and needs to be - * actively enabled for use with legacy systems. - * - * \param conf SSL configuration - * \param arc4 MBEDTLS_SSL_ARC4_ENABLED or MBEDTLS_SSL_ARC4_DISABLED - */ -void mbedtls_ssl_conf_arc4_support(mbedtls_ssl_config *conf, char arc4); -#endif /* MBEDTLS_ARC4_C */ - #if defined(MBEDTLS_SSL_SRV_C) /** * \brief Whether to send a list of acceptable CAs in @@ -3522,34 +4443,21 @@ void mbedtls_ssl_conf_cert_req_ca_list(mbedtls_ssl_config *conf, int mbedtls_ssl_conf_max_frag_len(mbedtls_ssl_config *conf, unsigned char mfl_code); #endif /* MBEDTLS_SSL_MAX_FRAGMENT_LENGTH */ -#if defined(MBEDTLS_SSL_TRUNCATED_HMAC) -/** - * \brief Activate negotiation of truncated HMAC - * (Default: MBEDTLS_SSL_TRUNC_HMAC_DISABLED) - * - * \param conf SSL configuration - * \param truncate Enable or disable (MBEDTLS_SSL_TRUNC_HMAC_ENABLED or - * MBEDTLS_SSL_TRUNC_HMAC_DISABLED) - */ -void mbedtls_ssl_conf_truncated_hmac(mbedtls_ssl_config *conf, int truncate); -#endif /* MBEDTLS_SSL_TRUNCATED_HMAC */ - -#if defined(MBEDTLS_SSL_CBC_RECORD_SPLITTING) +#if defined(MBEDTLS_SSL_SRV_C) /** - * \brief Enable / Disable 1/n-1 record splitting - * (Default: MBEDTLS_SSL_CBC_RECORD_SPLITTING_ENABLED) - * - * \note Only affects SSLv3 and TLS 1.0, not higher versions. - * Does not affect non-CBC ciphersuites in any version. + * \brief Pick the ciphersuites order according to the second parameter + * in the SSL Server module (MBEDTLS_SSL_SRV_C). + * (Default, if never called: MBEDTLS_SSL_SRV_CIPHERSUITE_ORDER_SERVER) * * \param conf SSL configuration - * \param split MBEDTLS_SSL_CBC_RECORD_SPLITTING_ENABLED or - * MBEDTLS_SSL_CBC_RECORD_SPLITTING_DISABLED + * \param order Server or client (MBEDTLS_SSL_SRV_CIPHERSUITE_ORDER_SERVER + * or MBEDTLS_SSL_SRV_CIPHERSUITE_ORDER_CLIENT) */ -void mbedtls_ssl_conf_cbc_record_splitting(mbedtls_ssl_config *conf, char split); -#endif /* MBEDTLS_SSL_CBC_RECORD_SPLITTING */ +void mbedtls_ssl_conf_preference_order(mbedtls_ssl_config *conf, int order); +#endif /* MBEDTLS_SSL_SRV_C */ -#if defined(MBEDTLS_SSL_SESSION_TICKETS) && defined(MBEDTLS_SSL_CLI_C) +#if defined(MBEDTLS_SSL_SESSION_TICKETS) && \ + defined(MBEDTLS_SSL_CLI_C) /** * \brief Enable / Disable session tickets (client only). * (Default: MBEDTLS_SSL_SESSION_TICKETS_ENABLED.) @@ -3561,7 +4469,34 @@ void mbedtls_ssl_conf_cbc_record_splitting(mbedtls_ssl_config *conf, char split) * MBEDTLS_SSL_SESSION_TICKETS_DISABLED) */ void mbedtls_ssl_conf_session_tickets(mbedtls_ssl_config *conf, int use_tickets); -#endif /* MBEDTLS_SSL_SESSION_TICKETS && MBEDTLS_SSL_CLI_C */ +#endif /* MBEDTLS_SSL_SESSION_TICKETS && + MBEDTLS_SSL_CLI_C */ + +#if defined(MBEDTLS_SSL_SESSION_TICKETS) && \ + defined(MBEDTLS_SSL_SRV_C) && \ + defined(MBEDTLS_SSL_PROTO_TLS1_3) +/** + * \brief Number of NewSessionTicket messages for the server to send + * after handshake completion. + * + * \note The default value is + * \c MBEDTLS_SSL_TLS1_3_DEFAULT_NEW_SESSION_TICKETS. + * + * \note In case of a session resumption, this setting only partially apply. + * At most one ticket is sent in that case to just renew the pool of + * tickets of the client. The rationale is to avoid the number of + * tickets on the server to become rapidly out of control when the + * server has the same configuration for all its connection instances. + * + * \param conf SSL configuration + * \param num_tickets Number of NewSessionTicket. + * + */ +void mbedtls_ssl_conf_new_session_tickets(mbedtls_ssl_config *conf, + uint16_t num_tickets); +#endif /* MBEDTLS_SSL_SESSION_TICKETS && + MBEDTLS_SSL_SRV_C && + MBEDTLS_SSL_PROTO_TLS1_3*/ #if defined(MBEDTLS_SSL_RENEGOTIATION) /** @@ -3754,103 +4689,69 @@ size_t mbedtls_ssl_get_bytes_avail(const mbedtls_ssl_context *ssl); uint32_t mbedtls_ssl_get_verify_result(const mbedtls_ssl_context *ssl); /** - * \brief Return the name of the current ciphersuite + * \brief Return the id of the current ciphersuite * * \param ssl SSL context * - * \return a string containing the ciphersuite name + * \return a ciphersuite id */ -const char *mbedtls_ssl_get_ciphersuite(const mbedtls_ssl_context *ssl); +int mbedtls_ssl_get_ciphersuite_id_from_ssl(const mbedtls_ssl_context *ssl); /** - * \brief Return the current SSL version (SSLv3/TLSv1/etc) + * \brief Return the name of the current ciphersuite * * \param ssl SSL context * - * \return a string containing the SSL version + * \return a string containing the ciphersuite name */ -const char *mbedtls_ssl_get_version(const mbedtls_ssl_context *ssl); +const char *mbedtls_ssl_get_ciphersuite(const mbedtls_ssl_context *ssl); -/** - * \brief Return the (maximum) number of bytes added by the record - * layer: header + encryption/MAC overhead (inc. padding) - * - * \note This function is not available (always returns an error) - * when record compression is enabled. - * - * \param ssl SSL context - * - * \return Current maximum record expansion in bytes, or - * MBEDTLS_ERR_SSL_FEATURE_UNAVAILABLE if compression is - * enabled, which makes expansion much less predictable - */ -int mbedtls_ssl_get_record_expansion(const mbedtls_ssl_context *ssl); -#if defined(MBEDTLS_SSL_MAX_FRAGMENT_LENGTH) /** - * \brief Return the maximum fragment length (payload, in bytes) for - * the output buffer. For the client, this is the configured - * value. For the server, it is the minimum of two - the - * configured value and the negotiated one. + * \brief Return the (D)TLS protocol version negotiated in the + * given connection. * - * \sa mbedtls_ssl_conf_max_frag_len() - * \sa mbedtls_ssl_get_max_record_payload() - * - * \param ssl SSL context + * \note If you call this function too early during the initial + * handshake, before the two sides have agreed on a version, + * this function returns #MBEDTLS_SSL_VERSION_UNKNOWN. * - * \return Current maximum fragment length for the output buffer. + * \param ssl The SSL context to query. + * \return The negotiated protocol version. */ -size_t mbedtls_ssl_get_output_max_frag_len(const mbedtls_ssl_context *ssl); +static inline mbedtls_ssl_protocol_version mbedtls_ssl_get_version_number( + const mbedtls_ssl_context *ssl) +{ + return ssl->MBEDTLS_PRIVATE(tls_version); +} /** - * \brief Return the maximum fragment length (payload, in bytes) for - * the input buffer. This is the negotiated maximum fragment - * length, or, if there is none, MBEDTLS_SSL_MAX_CONTENT_LEN. - * If it is not defined either, the value is 2^14. This function - * works as its predecessor, \c mbedtls_ssl_get_max_frag_len(). - * - * \sa mbedtls_ssl_conf_max_frag_len() - * \sa mbedtls_ssl_get_max_record_payload() + * \brief Return the current TLS version * * \param ssl SSL context * - * \return Current maximum fragment length for the output buffer. + * \return a string containing the TLS version */ -size_t mbedtls_ssl_get_input_max_frag_len(const mbedtls_ssl_context *ssl); - -#if !defined(MBEDTLS_DEPRECATED_REMOVED) - -#if defined(MBEDTLS_DEPRECATED_WARNING) -#define MBEDTLS_DEPRECATED __attribute__((deprecated)) -#else -#define MBEDTLS_DEPRECATED -#endif +const char *mbedtls_ssl_get_version(const mbedtls_ssl_context *ssl); /** - * \brief This function is a deprecated approach to getting the max - * fragment length. Its an alias for - * \c mbedtls_ssl_get_output_max_frag_len(), as the behaviour - * is the same. See \c mbedtls_ssl_get_output_max_frag_len() for - * more detail. - * - * \sa mbedtls_ssl_get_input_max_frag_len() - * \sa mbedtls_ssl_get_output_max_frag_len() + * \brief Return the (maximum) number of bytes added by the record + * layer: header + encryption/MAC overhead (inc. padding) * * \param ssl SSL context * - * \return Current maximum fragment length for the output buffer. + * \return Current maximum record expansion in bytes */ -MBEDTLS_DEPRECATED size_t mbedtls_ssl_get_max_frag_len( - const mbedtls_ssl_context *ssl); -#endif /* MBEDTLS_DEPRECATED_REMOVED */ -#endif /* MBEDTLS_SSL_MAX_FRAGMENT_LENGTH */ +int mbedtls_ssl_get_record_expansion(const mbedtls_ssl_context *ssl); /** * \brief Return the current maximum outgoing record payload in bytes. - * This takes into account the config.h setting \c - * MBEDTLS_SSL_OUT_CONTENT_LEN, the configured and negotiated - * max fragment length extension if used, and for DTLS the - * path MTU as configured and current record expansion. + * + * \note The logic to determine the maximum outgoing record payload is + * version-specific. It takes into account various factors, such as + * the mbedtls_config.h setting \c MBEDTLS_SSL_OUT_CONTENT_LEN, extensions + * such as the max fragment length or record size limit extension if + * used, and for DTLS the path MTU as configured and current + * record expansion. * * \note With DTLS, \c mbedtls_ssl_write() will return an error if * called with a larger length value. @@ -3859,12 +4760,7 @@ MBEDTLS_DEPRECATED size_t mbedtls_ssl_get_max_frag_len( * to the caller to call \c mbedtls_ssl_write() again in * order to send the remaining bytes if any. * - * \note This function is not available (always returns an error) - * when record compression is enabled. - * - * \sa mbedtls_ssl_set_mtu() - * \sa mbedtls_ssl_get_output_max_frag_len() - * \sa mbedtls_ssl_get_input_max_frag_len() + * \sa mbedtls_ssl_get_max_out_record_payload() * \sa mbedtls_ssl_get_record_expansion() * * \param ssl SSL context @@ -3874,6 +4770,26 @@ MBEDTLS_DEPRECATED size_t mbedtls_ssl_get_max_frag_len( */ int mbedtls_ssl_get_max_out_record_payload(const mbedtls_ssl_context *ssl); +/** + * \brief Return the current maximum incoming record payload in bytes. + * + * \note The logic to determine the maximum incoming record payload is + * version-specific. It takes into account various factors, such as + * the mbedtls_config.h setting \c MBEDTLS_SSL_IN_CONTENT_LEN, extensions + * such as the max fragment length extension or record size limit + * extension if used, and the current record expansion. + * + * \sa mbedtls_ssl_set_mtu() + * \sa mbedtls_ssl_get_max_in_record_payload() + * \sa mbedtls_ssl_get_record_expansion() + * + * \param ssl SSL context + * + * \return Current maximum payload for an incoming record, + * or a negative error code. + */ +int mbedtls_ssl_get_max_in_record_payload(const mbedtls_ssl_context *ssl); + #if defined(MBEDTLS_X509_CRT_PARSE_C) /** * \brief Return the peer certificate from the current connection. @@ -3910,32 +4826,41 @@ const mbedtls_x509_crt *mbedtls_ssl_get_peer_cert(const mbedtls_ssl_context *ssl #if defined(MBEDTLS_SSL_CLI_C) /** - * \brief Save session in order to resume it later (client-side only) - * Session data is copied to presented session structure. - * - * - * \param ssl SSL context - * \param session session context - * - * \return 0 if successful, - * MBEDTLS_ERR_SSL_ALLOC_FAILED if memory allocation failed, - * MBEDTLS_ERR_SSL_BAD_INPUT_DATA if used server-side or - * arguments are otherwise invalid. - * - * \note Only the server certificate is copied, and not the full chain, - * so you should not attempt to validate the certificate again - * by calling \c mbedtls_x509_crt_verify() on it. - * Instead, you should use the results from the verification - * in the original handshake by calling \c mbedtls_ssl_get_verify_result() - * after loading the session again into a new SSL context - * using \c mbedtls_ssl_set_session(). - * - * \note Once the session object is not needed anymore, you should - * free it by calling \c mbedtls_ssl_session_free(). + * \brief Export a session in order to resume it later. + * + * \param ssl The SSL context representing the connection for which to + * to export a session structure for later resumption. + * \param session The target structure in which to store the exported session. + * This must have been initialized with mbedtls_ssl_session_init() + * but otherwise be unused. + * + * \note This function can handle a variety of mechanisms for session + * resumption: For TLS 1.2, both session ID-based resumption and + * ticket-based resumption will be considered. For TLS 1.3, + * once implemented, sessions equate to tickets, and calling + * this function multiple times will export the available + * tickets one a time until no further tickets are available, + * in which case MBEDTLS_ERR_SSL_FEATURE_UNAVAILABLE will + * be returned. + * + * \note Calling this function multiple times will only be useful + * once TLS 1.3 is supported. For TLS 1.2 connections, this + * function should be called at most once. + * + * \return \c 0 if successful. In this case, \p session can be used for + * session resumption by passing it to mbedtls_ssl_set_session(), + * and serialized for storage via mbedtls_ssl_session_save(). + * \return #MBEDTLS_ERR_SSL_FEATURE_UNAVAILABLE if no further session + * is available for export. + * This error is a non-fatal, and has no observable effect on + * the SSL context or the destination session. + * \return Another negative error code on other kinds of failure. * * \sa mbedtls_ssl_set_session() + * \sa mbedtls_ssl_session_save() */ -int mbedtls_ssl_get_session(const mbedtls_ssl_context *ssl, mbedtls_ssl_session *session); +int mbedtls_ssl_get_session(const mbedtls_ssl_context *ssl, + mbedtls_ssl_session *session); #endif /* MBEDTLS_SSL_CLI_C */ /** @@ -3960,6 +4885,13 @@ int mbedtls_ssl_get_session(const mbedtls_ssl_context *ssl, mbedtls_ssl_session * \return #MBEDTLS_ERR_SSL_HELLO_VERIFY_REQUIRED if DTLS is in use * and the client did not demonstrate reachability yet - in * this case you must stop using the context (see below). + * \return #MBEDTLS_ERR_SSL_RECEIVED_EARLY_DATA if early data, as + * defined in RFC 8446 (TLS 1.3 specification), has been + * received as part of the handshake. This is server specific + * and may occur only if the early data feature has been + * enabled on server (see mbedtls_ssl_conf_early_data() + * documentation). You must call mbedtls_ssl_read_early_data() + * to read the early data before resuming the handshake. * \return Another SSL error code - in this case you must stop using * the context (see below). * @@ -3968,7 +4900,8 @@ int mbedtls_ssl_get_session(const mbedtls_ssl_context *ssl, mbedtls_ssl_session * #MBEDTLS_ERR_SSL_WANT_READ, * #MBEDTLS_ERR_SSL_WANT_WRITE, * #MBEDTLS_ERR_SSL_ASYNC_IN_PROGRESS or - * #MBEDTLS_ERR_SSL_CRYPTO_IN_PROGRESS, + * #MBEDTLS_ERR_SSL_CRYPTO_IN_PROGRESS or + * #MBEDTLS_ERR_SSL_RECEIVED_EARLY_DATA, * you must stop using the SSL context for reading or writing, * and either free it or call \c mbedtls_ssl_session_reset() * on it before re-using it for a new connection; the current @@ -3988,18 +4921,48 @@ int mbedtls_ssl_get_session(const mbedtls_ssl_context *ssl, mbedtls_ssl_session * currently being processed might or might not contain further * DTLS records. * - * \note If #MBEDTLS_USE_PSA_CRYPTO is enabled, the PSA crypto + * \note If the context is configured to allow TLS 1.3, or if + * #MBEDTLS_USE_PSA_CRYPTO is enabled, the PSA crypto * subsystem must have been initialized by calling * psa_crypto_init() before calling this function. */ int mbedtls_ssl_handshake(mbedtls_ssl_context *ssl); +/** + * \brief After calling mbedtls_ssl_handshake() to start the SSL + * handshake you can call this function to check whether the + * handshake is over for a given SSL context. This function + * should be also used to determine when to stop calling + * mbedtls_handshake_step() for that context. + * + * \param ssl SSL context + * + * \return \c 1 if handshake is over, \c 0 if it is still ongoing. + */ +static inline int mbedtls_ssl_is_handshake_over(mbedtls_ssl_context *ssl) +{ + return ssl->MBEDTLS_PRIVATE(state) >= MBEDTLS_SSL_HANDSHAKE_OVER; +} + /** * \brief Perform a single step of the SSL handshake * * \note The state of the context (ssl->state) will be at * the next state after this function returns \c 0. Do not - * call this function if state is MBEDTLS_SSL_HANDSHAKE_OVER. + * call this function if mbedtls_ssl_is_handshake_over() + * returns \c 1. + * + * \warning Whilst in the past you may have used direct access to the + * context state (ssl->state) in order to ascertain when to + * stop calling this function and although you can still do + * so with something like ssl->MBEDTLS_PRIVATE(state) or by + * defining MBEDTLS_ALLOW_PRIVATE_ACCESS, this is now + * considered deprecated and could be broken in any future + * release. If you still find you have good reason for such + * direct access, then please do contact the team to explain + * this (raise an issue or post to the mailing list), so that + * we can add a solution to your problem that will be + * guaranteed to work in the future. * * \param ssl SSL context * @@ -4007,8 +4970,9 @@ int mbedtls_ssl_handshake(mbedtls_ssl_context *ssl); * * \warning If this function returns something other than \c 0, * #MBEDTLS_ERR_SSL_WANT_READ, #MBEDTLS_ERR_SSL_WANT_WRITE, - * #MBEDTLS_ERR_SSL_ASYNC_IN_PROGRESS or - * #MBEDTLS_ERR_SSL_CRYPTO_IN_PROGRESS, you must stop using + * #MBEDTLS_ERR_SSL_ASYNC_IN_PROGRESS, + * #MBEDTLS_ERR_SSL_CRYPTO_IN_PROGRESS or + * #MBEDTLS_ERR_SSL_RECEIVED_EARLY_DATA, you must stop using * the SSL context for reading or writing, and either free it * or call \c mbedtls_ssl_session_reset() on it before * re-using it for a new connection; the current connection @@ -4076,6 +5040,13 @@ int mbedtls_ssl_renegotiate(mbedtls_ssl_context *ssl); * \return #MBEDTLS_ERR_SSL_CLIENT_RECONNECT if we're at the server * side of a DTLS connection and the client is initiating a * new connection using the same source port. See below. + * \return #MBEDTLS_ERR_SSL_RECEIVED_EARLY_DATA if early data, as + * defined in RFC 8446 (TLS 1.3 specification), has been + * received as part of the handshake. This is server specific + * and may occur only if the early data feature has been + * enabled on server (see mbedtls_ssl_conf_early_data() + * documentation). You must call mbedtls_ssl_read_early_data() + * to read the early data before resuming the handshake. * \return Another SSL error code - in this case you must stop using * the context (see below). * @@ -4084,8 +5055,9 @@ int mbedtls_ssl_renegotiate(mbedtls_ssl_context *ssl); * #MBEDTLS_ERR_SSL_WANT_READ, * #MBEDTLS_ERR_SSL_WANT_WRITE, * #MBEDTLS_ERR_SSL_ASYNC_IN_PROGRESS, - * #MBEDTLS_ERR_SSL_CRYPTO_IN_PROGRESS or - * #MBEDTLS_ERR_SSL_CLIENT_RECONNECT, + * #MBEDTLS_ERR_SSL_CRYPTO_IN_PROGRESS, + * #MBEDTLS_ERR_SSL_CLIENT_RECONNECT or + * #MBEDTLS_ERR_SSL_RECEIVED_EARLY_DATA, * you must stop using the SSL context for reading or writing, * and either free it or call \c mbedtls_ssl_session_reset() * on it before re-using it for a new connection; the current @@ -4150,6 +5122,13 @@ int mbedtls_ssl_read(mbedtls_ssl_context *ssl, unsigned char *buf, size_t len); * operation is in progress (see mbedtls_ecp_set_max_ops()) - * in this case you must call this function again to complete * the handshake when you're done attending other tasks. + * \return #MBEDTLS_ERR_SSL_RECEIVED_EARLY_DATA if early data, as + * defined in RFC 8446 (TLS 1.3 specification), has been + * received as part of the handshake. This is server specific + * and may occur only if the early data feature has been + * enabled on server (see mbedtls_ssl_conf_early_data() + * documentation). You must call mbedtls_ssl_read_early_data() + * to read the early data before resuming the handshake. * \return Another SSL error code - in this case you must stop using * the context (see below). * @@ -4157,8 +5136,9 @@ int mbedtls_ssl_read(mbedtls_ssl_context *ssl, unsigned char *buf, size_t len); * a non-negative value, * #MBEDTLS_ERR_SSL_WANT_READ, * #MBEDTLS_ERR_SSL_WANT_WRITE, - * #MBEDTLS_ERR_SSL_ASYNC_IN_PROGRESS or - * #MBEDTLS_ERR_SSL_CRYPTO_IN_PROGRESS, + * #MBEDTLS_ERR_SSL_ASYNC_IN_PROGRESS, + * #MBEDTLS_ERR_SSL_CRYPTO_IN_PROGRESS or + * #MBEDTLS_ERR_SSL_RECEIVED_EARLY_DATA, * you must stop using the SSL context for reading or writing, * and either free it or call \c mbedtls_ssl_session_reset() * on it before re-using it for a new connection; the current @@ -4166,7 +5146,7 @@ int mbedtls_ssl_read(mbedtls_ssl_context *ssl, unsigned char *buf, size_t len); * * \note When this function returns #MBEDTLS_ERR_SSL_WANT_WRITE/READ, * it must be called later with the *same* arguments, - * until it returns a value greater that or equal to 0. When + * until it returns a value greater than or equal to 0. When * the function returns #MBEDTLS_ERR_SSL_WANT_WRITE there may be * some partial data in the output buffer, however this is not * yet sent. @@ -4176,7 +5156,7 @@ int mbedtls_ssl_read(mbedtls_ssl_context *ssl, unsigned char *buf, size_t len); * or negotiated with the peer), then: * - with TLS, less bytes than requested are written. * - with DTLS, MBEDTLS_ERR_SSL_BAD_INPUT_DATA is returned. - * \c mbedtls_ssl_get_output_max_frag_len() may be used to + * \c mbedtls_ssl_get_max_out_record_payload() may be used to * query the active maximum fragment length. * * \note Attempting to write 0 bytes will result in an empty TLS @@ -4218,6 +5198,179 @@ int mbedtls_ssl_send_alert_message(mbedtls_ssl_context *ssl, */ int mbedtls_ssl_close_notify(mbedtls_ssl_context *ssl); +#if defined(MBEDTLS_SSL_EARLY_DATA) + +#if defined(MBEDTLS_SSL_SRV_C) +/** + * \brief Read at most 'len' bytes of early data + * + * \note This API is server specific. + * + * \warning Early data is defined in the TLS 1.3 specification, RFC 8446. + * IMPORTANT NOTE from section 2.3 of the specification: + * + * The security properties for 0-RTT data are weaker than + * those for other kinds of TLS data. Specifically: + * - This data is not forward secret, as it is encrypted + * solely under keys derived using the offered PSK. + * - There are no guarantees of non-replay between connections. + * Protection against replay for ordinary TLS 1.3 1-RTT data + * is provided via the server's Random value, but 0-RTT data + * does not depend on the ServerHello and therefore has + * weaker guarantees. This is especially relevant if the + * data is authenticated either with TLS client + * authentication or inside the application protocol. The + * same warnings apply to any use of the + * early_exporter_master_secret. + * + * \warning Mbed TLS does not implement any of the anti-replay defenses + * defined in section 8 of the TLS 1.3 specification: + * single-use of tickets or ClientHello recording within a + * given time window. + * + * \note This function is used in conjunction with + * mbedtls_ssl_handshake(), mbedtls_ssl_handshake_step(), + * mbedtls_ssl_read() and mbedtls_ssl_write() to read early + * data when these functions return + * #MBEDTLS_ERR_SSL_RECEIVED_EARLY_DATA. + * + * \param ssl SSL context, it must have been initialized and set up. + * \param buf buffer that will hold the data + * \param len maximum number of bytes to read + * + * \return The (positive) number of bytes read if successful. + * \return #MBEDTLS_ERR_SSL_BAD_INPUT_DATA if input data is invalid. + * \return #MBEDTLS_ERR_SSL_CANNOT_READ_EARLY_DATA if it is not + * possible to read early data for the SSL context \p ssl. Note + * that this function is intended to be called for an SSL + * context \p ssl only after a call to mbedtls_ssl_handshake(), + * mbedtls_ssl_handshake_step(), mbedtls_ssl_read() or + * mbedtls_ssl_write() for \p ssl that has returned + * #MBEDTLS_ERR_SSL_RECEIVED_EARLY_DATA. + */ +int mbedtls_ssl_read_early_data(mbedtls_ssl_context *ssl, + unsigned char *buf, size_t len); +#endif /* MBEDTLS_SSL_SRV_C */ + +#if defined(MBEDTLS_SSL_CLI_C) +/** + * \brief Try to write exactly 'len' application data bytes while + * performing the handshake (early data). + * + * \warning Early data is defined in the TLS 1.3 specification, RFC 8446. + * IMPORTANT NOTE from section 2.3 of the specification: + * + * The security properties for 0-RTT data are weaker than + * those for other kinds of TLS data. Specifically: + * - This data is not forward secret, as it is encrypted + * solely under keys derived using the offered PSK. + * - There are no guarantees of non-replay between connections. + * Protection against replay for ordinary TLS 1.3 1-RTT data + * is provided via the server's Random value, but 0-RTT data + * does not depend on the ServerHello and therefore has + * weaker guarantees. This is especially relevant if the + * data is authenticated either with TLS client + * authentication or inside the application protocol. The + * same warnings apply to any use of the + * early_exporter_master_secret. + * + * \note This function behaves mainly as mbedtls_ssl_write(). The + * specification of mbedtls_ssl_write() relevant to TLS 1.3 + * (thus not the parts specific to (D)TLS1.2) applies to this + * function and the present documentation is mainly restricted + * to the differences with mbedtls_ssl_write(). One noticeable + * difference though is that mbedtls_ssl_write() aims to + * complete the handshake before to write application data + * while mbedtls_ssl_write_early() aims to drive the handshake + * just past the point where it is not possible to send early + * data anymore. + * + * \param ssl SSL context + * \param buf buffer holding the data + * \param len how many bytes must be written + * + * \return The (non-negative) number of bytes actually written if + * successful (may be less than \p len). + * + * \return One additional specific error code compared to + * mbedtls_ssl_write(): + * #MBEDTLS_ERR_SSL_CANNOT_WRITE_EARLY_DATA. + * + * #MBEDTLS_ERR_SSL_CANNOT_WRITE_EARLY_DATA is returned when it + * is not possible to write early data for the SSL context + * \p ssl. + * + * It may have been possible and it is not possible + * anymore because the client received the server Finished + * message, the server rejected early data or the maximum + * number of allowed early data for the PSK in use has been + * reached. + * + * It may never have been possible and will never be possible + * for the SSL context \p ssl because the use of early data + * is disabled for that context or more generally the context + * is not suitably configured to enable early data or the first + * call to the function was done while the handshake was + * already completed. + * + * It is not possible to write early data for the SSL context + * \p ssl and any subsequent call to this API will return this + * error code. But this does not preclude for using it with + * mbedtls_ssl_write(), mbedtls_ssl_read() or + * mbedtls_ssl_handshake() and the handshake can be + * completed by calling one of these APIs. + * + * \note This function may write early data only if the SSL context + * has been configured for the handshake with a PSK for which + * early data is allowed. + * + * \note To maximize the number of early data that can be written in + * the course of the handshake, it is expected that this + * function starts the handshake for the SSL context \p ssl. + * But this is not mandatory. + * + * \note This function does not provide any information on whether + * the server has accepted or will accept early data or not. + * When it returns a positive value, it just means that it + * has written early data to the server. To know whether the + * server has accepted early data or not, you should call + * mbedtls_ssl_get_early_data_status() with the handshake + * completed. + */ +int mbedtls_ssl_write_early_data(mbedtls_ssl_context *ssl, + const unsigned char *buf, size_t len); + +/** + * \brief Get the status of the negotiation of the use of early data. + * + * \param ssl The SSL context to query + * + * \return #MBEDTLS_ERR_SSL_BAD_INPUT_DATA if this function is called + * from the server-side. + * + * \return #MBEDTLS_ERR_SSL_BAD_INPUT_DATA if this function is called + * prior to completion of the handshake. + * + * \return #MBEDTLS_SSL_EARLY_DATA_STATUS_NOT_INDICATED if the client + * has not indicated the use of early data to the server. + * + * \return #MBEDTLS_SSL_EARLY_DATA_STATUS_ACCEPTED if the client has + * indicated the use of early data and the server has accepted + * it. + * + * \return #MBEDTLS_SSL_EARLY_DATA_STATUS_REJECTED if the client has + * indicated the use of early data but the server has rejected + * it. In this situation, the client may want to re-send the + * early data it may have tried to send by calling + * mbedtls_ssl_write_early_data() as ordinary post-handshake + * application data by calling mbedtls_ssl_write(). + * + */ +int mbedtls_ssl_get_early_data_status(mbedtls_ssl_context *ssl); +#endif /* MBEDTLS_SSL_CLI_C */ + +#endif /* MBEDTLS_SSL_EARLY_DATA */ + /** * \brief Free referenced items in an SSL context and clear memory * @@ -4234,6 +5387,14 @@ void mbedtls_ssl_free(mbedtls_ssl_context *ssl); * * \see mbedtls_ssl_context_load() * + * \note The serialized data only contains the data that is + * necessary to resume the connection: negotiated protocol + * options, session identifier, keys, etc. + * Loading a saved SSL context does not restore settings and + * state related to how the application accesses the context, + * such as configured callback functions, user data, pending + * incoming or outgoing data, etc. + * * \note This feature is currently only available under certain * conditions, see the documentation of the return value * #MBEDTLS_ERR_SSL_BAD_INPUT_DATA for details. @@ -4312,8 +5473,11 @@ int mbedtls_ssl_context_save(mbedtls_ssl_context *ssl, * (unless they were already set before calling * mbedtls_ssl_session_reset() and the values are suitable for * the present connection). Specifically, you want to call - * at least mbedtls_ssl_set_bio() and - * mbedtls_ssl_set_timer_cb(). All other SSL setter functions + * at least mbedtls_ssl_set_bio(), + * mbedtls_ssl_set_timer_cb(), and + * mbedtls_ssl_set_user_data_n() or + * mbedtls_ssl_set_user_data_p() if they were set originally. + * All other SSL setter functions * are not necessary to call, either because they're only used * in handshakes, or because the setting is already saved. You * might choose to call them anyway, for example in order to diff --git a/vendor/mbedtls/include/mbedtls/ssl_cache.h b/vendor/mbedtls/include/mbedtls/ssl_cache.h index b1ea801930..a1307b4508 100644 --- a/vendor/mbedtls/include/mbedtls/ssl_cache.h +++ b/vendor/mbedtls/include/mbedtls/ssl_cache.h @@ -5,28 +5,13 @@ */ /* * Copyright The Mbed TLS Contributors - * SPDX-License-Identifier: Apache-2.0 - * - * Licensed under the Apache License, Version 2.0 (the "License"); you may - * not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT - * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. + * SPDX-License-Identifier: Apache-2.0 OR GPL-2.0-or-later */ #ifndef MBEDTLS_SSL_CACHE_H #define MBEDTLS_SSL_CACHE_H +#include "mbedtls/private_access.h" -#if !defined(MBEDTLS_CONFIG_FILE) -#include "mbedtls/config.h" -#else -#include MBEDTLS_CONFIG_FILE -#endif +#include "mbedtls/build_info.h" #include "mbedtls/ssl.h" @@ -38,7 +23,7 @@ * \name SECTION: Module settings * * The configuration options you can set for this module are in this section. - * Either change them in config.h or define them on the compiler command line. + * Either change them in mbedtls_config.h or define them on the compiler command line. * \{ */ @@ -64,25 +49,27 @@ typedef struct mbedtls_ssl_cache_entry mbedtls_ssl_cache_entry; */ struct mbedtls_ssl_cache_entry { #if defined(MBEDTLS_HAVE_TIME) - mbedtls_time_t timestamp; /*!< entry timestamp */ -#endif - mbedtls_ssl_session session; /*!< entry session */ -#if defined(MBEDTLS_X509_CRT_PARSE_C) && \ - defined(MBEDTLS_SSL_KEEP_PEER_CERTIFICATE) - mbedtls_x509_buf peer_cert; /*!< entry peer_cert */ + mbedtls_time_t MBEDTLS_PRIVATE(timestamp); /*!< entry timestamp */ #endif - mbedtls_ssl_cache_entry *next; /*!< chain pointer */ + + unsigned char MBEDTLS_PRIVATE(session_id)[32]; /*!< session ID */ + size_t MBEDTLS_PRIVATE(session_id_len); + + unsigned char *MBEDTLS_PRIVATE(session); /*!< serialized session */ + size_t MBEDTLS_PRIVATE(session_len); + + mbedtls_ssl_cache_entry *MBEDTLS_PRIVATE(next); /*!< chain pointer */ }; /** * \brief Cache context */ struct mbedtls_ssl_cache_context { - mbedtls_ssl_cache_entry *chain; /*!< start of the chain */ - int timeout; /*!< cache entry timeout */ - int max_entries; /*!< maximum entries */ + mbedtls_ssl_cache_entry *MBEDTLS_PRIVATE(chain); /*!< start of the chain */ + int MBEDTLS_PRIVATE(timeout); /*!< cache entry timeout */ + int MBEDTLS_PRIVATE(max_entries); /*!< maximum entries */ #if defined(MBEDTLS_THREADING_C) - mbedtls_threading_mutex_t mutex; /*!< mutex */ + mbedtls_threading_mutex_t MBEDTLS_PRIVATE(mutex); /*!< mutex */ #endif }; @@ -97,27 +84,58 @@ void mbedtls_ssl_cache_init(mbedtls_ssl_cache_context *cache); * \brief Cache get callback implementation * (Thread-safe if MBEDTLS_THREADING_C is enabled) * - * \param data SSL cache context - * \param session session to retrieve entry for + * \param data The SSL cache context to use. + * \param session_id The pointer to the buffer holding the session ID + * for the session to load. + * \param session_id_len The length of \p session_id in bytes. + * \param session The address at which to store the session + * associated with \p session_id, if present. * * \return \c 0 on success. * \return #MBEDTLS_ERR_SSL_CACHE_ENTRY_NOT_FOUND if there is * no cache entry with specified session ID found, or * any other negative error code for other failures. */ -int mbedtls_ssl_cache_get(void *data, mbedtls_ssl_session *session); +int mbedtls_ssl_cache_get(void *data, + unsigned char const *session_id, + size_t session_id_len, + mbedtls_ssl_session *session); /** * \brief Cache set callback implementation * (Thread-safe if MBEDTLS_THREADING_C is enabled) * - * \param data SSL cache context - * \param session session to store entry for + * \param data The SSL cache context to use. + * \param session_id The pointer to the buffer holding the session ID + * associated to \p session. + * \param session_id_len The length of \p session_id in bytes. + * \param session The session to store. * * \return \c 0 on success. * \return A negative error code on failure. */ -int mbedtls_ssl_cache_set(void *data, const mbedtls_ssl_session *session); +int mbedtls_ssl_cache_set(void *data, + unsigned char const *session_id, + size_t session_id_len, + const mbedtls_ssl_session *session); + +/** + * \brief Remove the cache entry by the session ID + * (Thread-safe if MBEDTLS_THREADING_C is enabled) + * + * \param data The SSL cache context to use. + * \param session_id The pointer to the buffer holding the session ID + * associated to session. + * \param session_id_len The length of \p session_id in bytes. + * + * \return \c 0 on success. This indicates the cache entry for + * the session with provided ID is removed or does not + * exist. + * \return A negative error code on failure. + */ +int mbedtls_ssl_cache_remove(void *data, + unsigned char const *session_id, + size_t session_id_len); #if defined(MBEDTLS_HAVE_TIME) /** @@ -130,6 +148,20 @@ int mbedtls_ssl_cache_set(void *data, const mbedtls_ssl_session *session); * \param timeout cache entry timeout in seconds */ void mbedtls_ssl_cache_set_timeout(mbedtls_ssl_cache_context *cache, int timeout); + +/** + * \brief Get the cache timeout + * + * A timeout of 0 indicates no timeout. + * + * \param cache SSL cache context + * + * \return cache entry timeout in seconds + */ +static inline int mbedtls_ssl_cache_get_timeout(mbedtls_ssl_cache_context *cache) +{ + return cache->MBEDTLS_PRIVATE(timeout); +} #endif /* MBEDTLS_HAVE_TIME */ /** diff --git a/vendor/mbedtls/include/mbedtls/ssl_ciphersuites.h b/vendor/mbedtls/include/mbedtls/ssl_ciphersuites.h index cdf724c229..12d446200f 100644 --- a/vendor/mbedtls/include/mbedtls/ssl_ciphersuites.h +++ b/vendor/mbedtls/include/mbedtls/ssl_ciphersuites.h @@ -5,28 +5,13 @@ */ /* * Copyright The Mbed TLS Contributors - * SPDX-License-Identifier: Apache-2.0 - * - * Licensed under the Apache License, Version 2.0 (the "License"); you may - * not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT - * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. + * SPDX-License-Identifier: Apache-2.0 OR GPL-2.0-or-later */ #ifndef MBEDTLS_SSL_CIPHERSUITES_H #define MBEDTLS_SSL_CIPHERSUITES_H +#include "mbedtls/private_access.h" -#if !defined(MBEDTLS_CONFIG_FILE) -#include "mbedtls/config.h" -#else -#include MBEDTLS_CONFIG_FILE -#endif +#include "mbedtls/build_info.h" #include "mbedtls/pk.h" #include "mbedtls/cipher.h" @@ -42,15 +27,6 @@ extern "C" { #define MBEDTLS_TLS_RSA_WITH_NULL_MD5 0x01 /**< Weak! */ #define MBEDTLS_TLS_RSA_WITH_NULL_SHA 0x02 /**< Weak! */ -#define MBEDTLS_TLS_RSA_WITH_RC4_128_MD5 0x04 -#define MBEDTLS_TLS_RSA_WITH_RC4_128_SHA 0x05 -#define MBEDTLS_TLS_RSA_WITH_DES_CBC_SHA 0x09 /**< Weak! Not in TLS 1.2 */ - -#define MBEDTLS_TLS_RSA_WITH_3DES_EDE_CBC_SHA 0x0A - -#define MBEDTLS_TLS_DHE_RSA_WITH_DES_CBC_SHA 0x15 /**< Weak! Not in TLS 1.2 */ -#define MBEDTLS_TLS_DHE_RSA_WITH_3DES_EDE_CBC_SHA 0x16 - #define MBEDTLS_TLS_PSK_WITH_NULL_SHA 0x2C /**< Weak! */ #define MBEDTLS_TLS_DHE_PSK_WITH_NULL_SHA 0x2D /**< Weak! */ #define MBEDTLS_TLS_RSA_PSK_WITH_NULL_SHA 0x2E /**< Weak! */ @@ -73,18 +49,12 @@ extern "C" { #define MBEDTLS_TLS_RSA_WITH_CAMELLIA_256_CBC_SHA 0x84 #define MBEDTLS_TLS_DHE_RSA_WITH_CAMELLIA_256_CBC_SHA 0x88 -#define MBEDTLS_TLS_PSK_WITH_RC4_128_SHA 0x8A -#define MBEDTLS_TLS_PSK_WITH_3DES_EDE_CBC_SHA 0x8B #define MBEDTLS_TLS_PSK_WITH_AES_128_CBC_SHA 0x8C #define MBEDTLS_TLS_PSK_WITH_AES_256_CBC_SHA 0x8D -#define MBEDTLS_TLS_DHE_PSK_WITH_RC4_128_SHA 0x8E -#define MBEDTLS_TLS_DHE_PSK_WITH_3DES_EDE_CBC_SHA 0x8F #define MBEDTLS_TLS_DHE_PSK_WITH_AES_128_CBC_SHA 0x90 #define MBEDTLS_TLS_DHE_PSK_WITH_AES_256_CBC_SHA 0x91 -#define MBEDTLS_TLS_RSA_PSK_WITH_RC4_128_SHA 0x92 -#define MBEDTLS_TLS_RSA_PSK_WITH_3DES_EDE_CBC_SHA 0x93 #define MBEDTLS_TLS_RSA_PSK_WITH_AES_128_CBC_SHA 0x94 #define MBEDTLS_TLS_RSA_PSK_WITH_AES_256_CBC_SHA 0x95 @@ -122,28 +92,20 @@ extern "C" { #define MBEDTLS_TLS_DHE_RSA_WITH_CAMELLIA_256_CBC_SHA256 0xC4 /**< TLS 1.2 */ #define MBEDTLS_TLS_ECDH_ECDSA_WITH_NULL_SHA 0xC001 /**< Weak! */ -#define MBEDTLS_TLS_ECDH_ECDSA_WITH_RC4_128_SHA 0xC002 /**< Not in SSL3! */ -#define MBEDTLS_TLS_ECDH_ECDSA_WITH_3DES_EDE_CBC_SHA 0xC003 /**< Not in SSL3! */ -#define MBEDTLS_TLS_ECDH_ECDSA_WITH_AES_128_CBC_SHA 0xC004 /**< Not in SSL3! */ -#define MBEDTLS_TLS_ECDH_ECDSA_WITH_AES_256_CBC_SHA 0xC005 /**< Not in SSL3! */ +#define MBEDTLS_TLS_ECDH_ECDSA_WITH_AES_128_CBC_SHA 0xC004 +#define MBEDTLS_TLS_ECDH_ECDSA_WITH_AES_256_CBC_SHA 0xC005 #define MBEDTLS_TLS_ECDHE_ECDSA_WITH_NULL_SHA 0xC006 /**< Weak! */ -#define MBEDTLS_TLS_ECDHE_ECDSA_WITH_RC4_128_SHA 0xC007 /**< Not in SSL3! */ -#define MBEDTLS_TLS_ECDHE_ECDSA_WITH_3DES_EDE_CBC_SHA 0xC008 /**< Not in SSL3! */ -#define MBEDTLS_TLS_ECDHE_ECDSA_WITH_AES_128_CBC_SHA 0xC009 /**< Not in SSL3! */ -#define MBEDTLS_TLS_ECDHE_ECDSA_WITH_AES_256_CBC_SHA 0xC00A /**< Not in SSL3! */ +#define MBEDTLS_TLS_ECDHE_ECDSA_WITH_AES_128_CBC_SHA 0xC009 +#define MBEDTLS_TLS_ECDHE_ECDSA_WITH_AES_256_CBC_SHA 0xC00A #define MBEDTLS_TLS_ECDH_RSA_WITH_NULL_SHA 0xC00B /**< Weak! */ -#define MBEDTLS_TLS_ECDH_RSA_WITH_RC4_128_SHA 0xC00C /**< Not in SSL3! */ -#define MBEDTLS_TLS_ECDH_RSA_WITH_3DES_EDE_CBC_SHA 0xC00D /**< Not in SSL3! */ -#define MBEDTLS_TLS_ECDH_RSA_WITH_AES_128_CBC_SHA 0xC00E /**< Not in SSL3! */ -#define MBEDTLS_TLS_ECDH_RSA_WITH_AES_256_CBC_SHA 0xC00F /**< Not in SSL3! */ +#define MBEDTLS_TLS_ECDH_RSA_WITH_AES_128_CBC_SHA 0xC00E +#define MBEDTLS_TLS_ECDH_RSA_WITH_AES_256_CBC_SHA 0xC00F #define MBEDTLS_TLS_ECDHE_RSA_WITH_NULL_SHA 0xC010 /**< Weak! */ -#define MBEDTLS_TLS_ECDHE_RSA_WITH_RC4_128_SHA 0xC011 /**< Not in SSL3! */ -#define MBEDTLS_TLS_ECDHE_RSA_WITH_3DES_EDE_CBC_SHA 0xC012 /**< Not in SSL3! */ -#define MBEDTLS_TLS_ECDHE_RSA_WITH_AES_128_CBC_SHA 0xC013 /**< Not in SSL3! */ -#define MBEDTLS_TLS_ECDHE_RSA_WITH_AES_256_CBC_SHA 0xC014 /**< Not in SSL3! */ +#define MBEDTLS_TLS_ECDHE_RSA_WITH_AES_128_CBC_SHA 0xC013 +#define MBEDTLS_TLS_ECDHE_RSA_WITH_AES_256_CBC_SHA 0xC014 #define MBEDTLS_TLS_ECDHE_ECDSA_WITH_AES_128_CBC_SHA256 0xC023 /**< TLS 1.2 */ #define MBEDTLS_TLS_ECDHE_ECDSA_WITH_AES_256_CBC_SHA384 0xC024 /**< TLS 1.2 */ @@ -163,15 +125,13 @@ extern "C" { #define MBEDTLS_TLS_ECDH_RSA_WITH_AES_128_GCM_SHA256 0xC031 /**< TLS 1.2 */ #define MBEDTLS_TLS_ECDH_RSA_WITH_AES_256_GCM_SHA384 0xC032 /**< TLS 1.2 */ -#define MBEDTLS_TLS_ECDHE_PSK_WITH_RC4_128_SHA 0xC033 /**< Not in SSL3! */ -#define MBEDTLS_TLS_ECDHE_PSK_WITH_3DES_EDE_CBC_SHA 0xC034 /**< Not in SSL3! */ -#define MBEDTLS_TLS_ECDHE_PSK_WITH_AES_128_CBC_SHA 0xC035 /**< Not in SSL3! */ -#define MBEDTLS_TLS_ECDHE_PSK_WITH_AES_256_CBC_SHA 0xC036 /**< Not in SSL3! */ -#define MBEDTLS_TLS_ECDHE_PSK_WITH_AES_128_CBC_SHA256 0xC037 /**< Not in SSL3! */ -#define MBEDTLS_TLS_ECDHE_PSK_WITH_AES_256_CBC_SHA384 0xC038 /**< Not in SSL3! */ -#define MBEDTLS_TLS_ECDHE_PSK_WITH_NULL_SHA 0xC039 /**< Weak! No SSL3! */ -#define MBEDTLS_TLS_ECDHE_PSK_WITH_NULL_SHA256 0xC03A /**< Weak! No SSL3! */ -#define MBEDTLS_TLS_ECDHE_PSK_WITH_NULL_SHA384 0xC03B /**< Weak! No SSL3! */ +#define MBEDTLS_TLS_ECDHE_PSK_WITH_AES_128_CBC_SHA 0xC035 +#define MBEDTLS_TLS_ECDHE_PSK_WITH_AES_256_CBC_SHA 0xC036 +#define MBEDTLS_TLS_ECDHE_PSK_WITH_AES_128_CBC_SHA256 0xC037 +#define MBEDTLS_TLS_ECDHE_PSK_WITH_AES_256_CBC_SHA384 0xC038 +#define MBEDTLS_TLS_ECDHE_PSK_WITH_NULL_SHA 0xC039 +#define MBEDTLS_TLS_ECDHE_PSK_WITH_NULL_SHA256 0xC03A +#define MBEDTLS_TLS_ECDHE_PSK_WITH_NULL_SHA384 0xC03B #define MBEDTLS_TLS_RSA_WITH_ARIA_128_CBC_SHA256 0xC03C /**< TLS 1.2 */ #define MBEDTLS_TLS_RSA_WITH_ARIA_256_CBC_SHA384 0xC03D /**< TLS 1.2 */ @@ -212,14 +172,14 @@ extern "C" { #define MBEDTLS_TLS_ECDHE_PSK_WITH_ARIA_128_CBC_SHA256 0xC070 /**< TLS 1.2 */ #define MBEDTLS_TLS_ECDHE_PSK_WITH_ARIA_256_CBC_SHA384 0xC071 /**< TLS 1.2 */ -#define MBEDTLS_TLS_ECDHE_ECDSA_WITH_CAMELLIA_128_CBC_SHA256 0xC072 /**< Not in SSL3! */ -#define MBEDTLS_TLS_ECDHE_ECDSA_WITH_CAMELLIA_256_CBC_SHA384 0xC073 /**< Not in SSL3! */ -#define MBEDTLS_TLS_ECDH_ECDSA_WITH_CAMELLIA_128_CBC_SHA256 0xC074 /**< Not in SSL3! */ -#define MBEDTLS_TLS_ECDH_ECDSA_WITH_CAMELLIA_256_CBC_SHA384 0xC075 /**< Not in SSL3! */ -#define MBEDTLS_TLS_ECDHE_RSA_WITH_CAMELLIA_128_CBC_SHA256 0xC076 /**< Not in SSL3! */ -#define MBEDTLS_TLS_ECDHE_RSA_WITH_CAMELLIA_256_CBC_SHA384 0xC077 /**< Not in SSL3! */ -#define MBEDTLS_TLS_ECDH_RSA_WITH_CAMELLIA_128_CBC_SHA256 0xC078 /**< Not in SSL3! */ -#define MBEDTLS_TLS_ECDH_RSA_WITH_CAMELLIA_256_CBC_SHA384 0xC079 /**< Not in SSL3! */ +#define MBEDTLS_TLS_ECDHE_ECDSA_WITH_CAMELLIA_128_CBC_SHA256 0xC072 +#define MBEDTLS_TLS_ECDHE_ECDSA_WITH_CAMELLIA_256_CBC_SHA384 0xC073 +#define MBEDTLS_TLS_ECDH_ECDSA_WITH_CAMELLIA_128_CBC_SHA256 0xC074 +#define MBEDTLS_TLS_ECDH_ECDSA_WITH_CAMELLIA_256_CBC_SHA384 0xC075 +#define MBEDTLS_TLS_ECDHE_RSA_WITH_CAMELLIA_128_CBC_SHA256 0xC076 +#define MBEDTLS_TLS_ECDHE_RSA_WITH_CAMELLIA_256_CBC_SHA384 0xC077 +#define MBEDTLS_TLS_ECDH_RSA_WITH_CAMELLIA_128_CBC_SHA256 0xC078 +#define MBEDTLS_TLS_ECDH_RSA_WITH_CAMELLIA_256_CBC_SHA384 0xC079 #define MBEDTLS_TLS_RSA_WITH_CAMELLIA_128_GCM_SHA256 0xC07A /**< TLS 1.2 */ #define MBEDTLS_TLS_RSA_WITH_CAMELLIA_256_GCM_SHA384 0xC07B /**< TLS 1.2 */ @@ -247,8 +207,8 @@ extern "C" { #define MBEDTLS_TLS_DHE_PSK_WITH_CAMELLIA_256_CBC_SHA384 0xC097 #define MBEDTLS_TLS_RSA_PSK_WITH_CAMELLIA_128_CBC_SHA256 0xC098 #define MBEDTLS_TLS_RSA_PSK_WITH_CAMELLIA_256_CBC_SHA384 0xC099 -#define MBEDTLS_TLS_ECDHE_PSK_WITH_CAMELLIA_128_CBC_SHA256 0xC09A /**< Not in SSL3! */ -#define MBEDTLS_TLS_ECDHE_PSK_WITH_CAMELLIA_256_CBC_SHA384 0xC09B /**< Not in SSL3! */ +#define MBEDTLS_TLS_ECDHE_PSK_WITH_CAMELLIA_128_CBC_SHA256 0xC09A +#define MBEDTLS_TLS_ECDHE_PSK_WITH_CAMELLIA_256_CBC_SHA384 0xC09B #define MBEDTLS_TLS_RSA_WITH_AES_128_CCM 0xC09C /**< TLS 1.2 */ #define MBEDTLS_TLS_RSA_WITH_AES_256_CCM 0xC09D /**< TLS 1.2 */ @@ -284,6 +244,13 @@ extern "C" { #define MBEDTLS_TLS_DHE_PSK_WITH_CHACHA20_POLY1305_SHA256 0xCCAD /**< TLS 1.2 */ #define MBEDTLS_TLS_RSA_PSK_WITH_CHACHA20_POLY1305_SHA256 0xCCAE /**< TLS 1.2 */ +/* RFC 8446, Appendix B.4 */ +#define MBEDTLS_TLS1_3_AES_128_GCM_SHA256 0x1301 /**< TLS 1.3 */ +#define MBEDTLS_TLS1_3_AES_256_GCM_SHA384 0x1302 /**< TLS 1.3 */ +#define MBEDTLS_TLS1_3_CHACHA20_POLY1305_SHA256 0x1303 /**< TLS 1.3 */ +#define MBEDTLS_TLS1_3_AES_128_CCM_SHA256 0x1304 /**< TLS 1.3 */ +#define MBEDTLS_TLS1_3_AES_128_CCM_8_SHA256 0x1305 /**< TLS 1.3 */ + /* Reminder: update mbedtls_ssl_premaster_secret when adding a new key exchange. * Reminder: update MBEDTLS_KEY_EXCHANGE__xxx below */ @@ -313,16 +280,49 @@ typedef enum { #define MBEDTLS_KEY_EXCHANGE_WITH_CERT_ENABLED #endif -/* Key exchanges allowing client certificate requests */ +/* Key exchanges in either TLS 1.2 or 1.3 which are using an ECDSA + * signature */ +#if defined(MBEDTLS_KEY_EXCHANGE_ECDHE_ECDSA_ENABLED) || \ + defined(MBEDTLS_SSL_TLS1_3_KEY_EXCHANGE_MODE_EPHEMERAL_ENABLED) +#define MBEDTLS_KEY_EXCHANGE_WITH_ECDSA_ANY_ENABLED +#endif + +#if defined(MBEDTLS_KEY_EXCHANGE_WITH_CERT_ENABLED) || \ + defined(MBEDTLS_SSL_TLS1_3_KEY_EXCHANGE_MODE_EPHEMERAL_ENABLED) +#define MBEDTLS_SSL_HANDSHAKE_WITH_CERT_ENABLED +#endif + +/* Key exchanges allowing client certificate requests. + * + * Note: that's almost the same as MBEDTLS_KEY_EXCHANGE_WITH_CERT_ENABLED + * above, except RSA-PSK uses a server certificate but no client cert. + * + * Note: this difference is specific to TLS 1.2, as with TLS 1.3, things are + * more symmetrical: client certs and server certs are either both allowed + * (Ephemeral mode) or both disallowed (PSK and PKS-Ephemeral modes). + */ #if defined(MBEDTLS_KEY_EXCHANGE_RSA_ENABLED) || \ defined(MBEDTLS_KEY_EXCHANGE_DHE_RSA_ENABLED) || \ - defined(MBEDTLS_KEY_EXCHANGE_ECDH_RSA_ENABLED) || \ defined(MBEDTLS_KEY_EXCHANGE_ECDHE_RSA_ENABLED) || \ + defined(MBEDTLS_KEY_EXCHANGE_ECDHE_ECDSA_ENABLED) || \ defined(MBEDTLS_KEY_EXCHANGE_ECDH_ECDSA_ENABLED) || \ - defined(MBEDTLS_KEY_EXCHANGE_ECDHE_ECDSA_ENABLED) + defined(MBEDTLS_KEY_EXCHANGE_ECDH_RSA_ENABLED) #define MBEDTLS_KEY_EXCHANGE_CERT_REQ_ALLOWED_ENABLED #endif +/* Helper to state that certificate-based client authentication through ECDSA + * is supported in TLS 1.2 */ +#if defined(MBEDTLS_KEY_EXCHANGE_CERT_REQ_ALLOWED_ENABLED) && \ + defined(MBEDTLS_PK_CAN_ECDSA_SIGN) && defined(MBEDTLS_PK_CAN_ECDSA_VERIFY) +#define MBEDTLS_KEY_EXCHANGE_ECDSA_CERT_REQ_ALLOWED_ENABLED +#endif + +/* ECDSA required for certificates in either TLS 1.2 or 1.3 */ +#if defined(MBEDTLS_KEY_EXCHANGE_ECDSA_CERT_REQ_ALLOWED_ENABLED) || \ + defined(MBEDTLS_SSL_TLS1_3_KEY_EXCHANGE_MODE_EPHEMERAL_ENABLED) +#define MBEDTLS_KEY_EXCHANGE_ECDSA_CERT_REQ_ANY_ALLOWED_ENABLED +#endif + /* Key exchanges involving server signature in ServerKeyExchange */ #if defined(MBEDTLS_KEY_EXCHANGE_DHE_RSA_ENABLED) || \ defined(MBEDTLS_KEY_EXCHANGE_ECDHE_RSA_ENABLED) || \ @@ -375,6 +375,62 @@ typedef enum { #define MBEDTLS_KEY_EXCHANGE_SOME_ECDHE_ENABLED #endif +/* TLS 1.2 key exchanges using ECDH or ECDHE*/ +#if defined(MBEDTLS_KEY_EXCHANGE_SOME_ECDH_ENABLED) || \ + defined(MBEDTLS_KEY_EXCHANGE_SOME_ECDHE_ENABLED) +#define MBEDTLS_KEY_EXCHANGE_SOME_ECDH_OR_ECDHE_1_2_ENABLED +#endif + +/* TLS 1.3 PSK key exchanges */ +#if defined(MBEDTLS_SSL_TLS1_3_KEY_EXCHANGE_MODE_PSK_ENABLED) || \ + defined(MBEDTLS_SSL_TLS1_3_KEY_EXCHANGE_MODE_PSK_EPHEMERAL_ENABLED) +#define MBEDTLS_SSL_TLS1_3_KEY_EXCHANGE_MODE_SOME_PSK_ENABLED +#endif + +/* TLS 1.2 or 1.3 key exchanges with PSK */ +#if defined(MBEDTLS_KEY_EXCHANGE_SOME_PSK_ENABLED) || \ + defined(MBEDTLS_SSL_TLS1_3_KEY_EXCHANGE_MODE_SOME_PSK_ENABLED) +#define MBEDTLS_SSL_HANDSHAKE_WITH_PSK_ENABLED +#endif + +/* TLS 1.3 ephemeral key exchanges */ +#if defined(MBEDTLS_SSL_TLS1_3_KEY_EXCHANGE_MODE_EPHEMERAL_ENABLED) || \ + defined(MBEDTLS_SSL_TLS1_3_KEY_EXCHANGE_MODE_PSK_EPHEMERAL_ENABLED) +#define MBEDTLS_SSL_TLS1_3_KEY_EXCHANGE_MODE_SOME_EPHEMERAL_ENABLED +#endif + +/* TLS 1.3 key exchanges using ECDHE */ +#if defined(MBEDTLS_SSL_TLS1_3_KEY_EXCHANGE_MODE_SOME_EPHEMERAL_ENABLED) && \ + defined(PSA_WANT_ALG_ECDH) +#define MBEDTLS_SSL_TLS1_3_KEY_EXCHANGE_MODE_SOME_ECDHE_ENABLED +#endif + +/* TLS 1.2 or 1.3 key exchanges using ECDH or ECDHE */ +#if defined(MBEDTLS_KEY_EXCHANGE_SOME_ECDH_OR_ECDHE_1_2_ENABLED) || \ + defined(MBEDTLS_SSL_TLS1_3_KEY_EXCHANGE_MODE_SOME_ECDHE_ENABLED) +#define MBEDTLS_KEY_EXCHANGE_SOME_ECDH_OR_ECDHE_ANY_ENABLED +#endif + +/* TLS 1.2 XXDH key exchanges: ECDH or ECDHE or FFDH */ +#if (defined(MBEDTLS_KEY_EXCHANGE_SOME_ECDH_OR_ECDHE_1_2_ENABLED) || \ + defined(MBEDTLS_KEY_EXCHANGE_SOME_DHE_ENABLED)) +#define MBEDTLS_KEY_EXCHANGE_SOME_XXDH_1_2_ENABLED +#endif + +/* The handshake params structure has a set of fields called xxdh_psa which are used: + * - by TLS 1.2 with `USE_PSA` to do ECDH or ECDHE; + * - by TLS 1.3 to do ECDHE or FFDHE. + * The following macros can be used to guard their declaration and use. + */ +#if defined(MBEDTLS_KEY_EXCHANGE_SOME_ECDH_OR_ECDHE_1_2_ENABLED) && \ + defined(MBEDTLS_USE_PSA_CRYPTO) +#define MBEDTLS_KEY_EXCHANGE_SOME_XXDH_PSA_1_2_ENABLED +#endif +#if defined(MBEDTLS_KEY_EXCHANGE_SOME_XXDH_PSA_1_2_ENABLED) || \ + defined(MBEDTLS_SSL_TLS1_3_KEY_EXCHANGE_MODE_SOME_EPHEMERAL_ENABLED) +#define MBEDTLS_KEY_EXCHANGE_SOME_XXDH_PSA_ANY_ENABLED +#endif + typedef struct mbedtls_ssl_ciphersuite_t mbedtls_ssl_ciphersuite_t; #define MBEDTLS_CIPHERSUITE_WEAK 0x01 /**< Weak ciphersuite flag */ @@ -384,21 +440,22 @@ typedef struct mbedtls_ssl_ciphersuite_t mbedtls_ssl_ciphersuite_t; /** * \brief This structure is used for storing ciphersuite information + * + * \note members are defined using integral types instead of enums + * in order to pack structure and reduce memory usage by internal + * \c ciphersuite_definitions[] */ struct mbedtls_ssl_ciphersuite_t { - int id; - const char *name; - - mbedtls_cipher_type_t cipher; - mbedtls_md_type_t mac; - mbedtls_key_exchange_type_t key_exchange; + int MBEDTLS_PRIVATE(id); + const char *MBEDTLS_PRIVATE(name); - int min_major_ver; - int min_minor_ver; - int max_major_ver; - int max_minor_ver; + uint8_t MBEDTLS_PRIVATE(cipher); /* mbedtls_cipher_type_t */ + uint8_t MBEDTLS_PRIVATE(mac); /* mbedtls_md_type_t */ + uint8_t MBEDTLS_PRIVATE(key_exchange); /* mbedtls_key_exchange_type_t */ + uint8_t MBEDTLS_PRIVATE(flags); - unsigned char flags; + uint16_t MBEDTLS_PRIVATE(min_tls_version); /* mbedtls_ssl_protocol_version */ + uint16_t MBEDTLS_PRIVATE(max_tls_version); /* mbedtls_ssl_protocol_version */ }; const int *mbedtls_ssl_list_ciphersuites(void); @@ -406,140 +463,17 @@ const int *mbedtls_ssl_list_ciphersuites(void); const mbedtls_ssl_ciphersuite_t *mbedtls_ssl_ciphersuite_from_string(const char *ciphersuite_name); const mbedtls_ssl_ciphersuite_t *mbedtls_ssl_ciphersuite_from_id(int ciphersuite_id); -#if defined(MBEDTLS_PK_C) -mbedtls_pk_type_t mbedtls_ssl_get_ciphersuite_sig_pk_alg(const mbedtls_ssl_ciphersuite_t *info); -mbedtls_pk_type_t mbedtls_ssl_get_ciphersuite_sig_alg(const mbedtls_ssl_ciphersuite_t *info); -#endif - -int mbedtls_ssl_ciphersuite_uses_ec(const mbedtls_ssl_ciphersuite_t *info); -int mbedtls_ssl_ciphersuite_uses_psk(const mbedtls_ssl_ciphersuite_t *info); - -#if defined(MBEDTLS_KEY_EXCHANGE_SOME_PFS_ENABLED) -static inline int mbedtls_ssl_ciphersuite_has_pfs(const mbedtls_ssl_ciphersuite_t *info) -{ - switch (info->key_exchange) { - case MBEDTLS_KEY_EXCHANGE_DHE_RSA: - case MBEDTLS_KEY_EXCHANGE_DHE_PSK: - case MBEDTLS_KEY_EXCHANGE_ECDHE_RSA: - case MBEDTLS_KEY_EXCHANGE_ECDHE_PSK: - case MBEDTLS_KEY_EXCHANGE_ECDHE_ECDSA: - case MBEDTLS_KEY_EXCHANGE_ECJPAKE: - return 1; - - default: - return 0; - } -} -#endif /* MBEDTLS_KEY_EXCHANGE_SOME_PFS_ENABLED */ - -#if defined(MBEDTLS_KEY_EXCHANGE_SOME_NON_PFS_ENABLED) -static inline int mbedtls_ssl_ciphersuite_no_pfs(const mbedtls_ssl_ciphersuite_t *info) -{ - switch (info->key_exchange) { - case MBEDTLS_KEY_EXCHANGE_ECDH_RSA: - case MBEDTLS_KEY_EXCHANGE_ECDH_ECDSA: - case MBEDTLS_KEY_EXCHANGE_RSA: - case MBEDTLS_KEY_EXCHANGE_PSK: - case MBEDTLS_KEY_EXCHANGE_RSA_PSK: - return 1; - - default: - return 0; - } -} -#endif /* MBEDTLS_KEY_EXCHANGE_SOME_NON_PFS_ENABLED */ - -#if defined(MBEDTLS_KEY_EXCHANGE_SOME_ECDH_ENABLED) -static inline int mbedtls_ssl_ciphersuite_uses_ecdh(const mbedtls_ssl_ciphersuite_t *info) +static inline const char *mbedtls_ssl_ciphersuite_get_name(const mbedtls_ssl_ciphersuite_t *info) { - switch (info->key_exchange) { - case MBEDTLS_KEY_EXCHANGE_ECDH_RSA: - case MBEDTLS_KEY_EXCHANGE_ECDH_ECDSA: - return 1; - - default: - return 0; - } + return info->MBEDTLS_PRIVATE(name); } -#endif /* MBEDTLS_KEY_EXCHANGE_SOME_ECDH_ENABLED */ -static inline int mbedtls_ssl_ciphersuite_cert_req_allowed(const mbedtls_ssl_ciphersuite_t *info) +static inline int mbedtls_ssl_ciphersuite_get_id(const mbedtls_ssl_ciphersuite_t *info) { - switch (info->key_exchange) { - case MBEDTLS_KEY_EXCHANGE_RSA: - case MBEDTLS_KEY_EXCHANGE_DHE_RSA: - case MBEDTLS_KEY_EXCHANGE_ECDH_RSA: - case MBEDTLS_KEY_EXCHANGE_ECDHE_RSA: - case MBEDTLS_KEY_EXCHANGE_ECDH_ECDSA: - case MBEDTLS_KEY_EXCHANGE_ECDHE_ECDSA: - return 1; - - default: - return 0; - } + return info->MBEDTLS_PRIVATE(id); } -static inline int mbedtls_ssl_ciphersuite_uses_srv_cert(const mbedtls_ssl_ciphersuite_t *info) -{ - switch (info->key_exchange) { - case MBEDTLS_KEY_EXCHANGE_RSA: - case MBEDTLS_KEY_EXCHANGE_RSA_PSK: - case MBEDTLS_KEY_EXCHANGE_DHE_RSA: - case MBEDTLS_KEY_EXCHANGE_ECDH_RSA: - case MBEDTLS_KEY_EXCHANGE_ECDHE_RSA: - case MBEDTLS_KEY_EXCHANGE_ECDH_ECDSA: - case MBEDTLS_KEY_EXCHANGE_ECDHE_ECDSA: - return 1; - - default: - return 0; - } -} - -#if defined(MBEDTLS_KEY_EXCHANGE_SOME_DHE_ENABLED) -static inline int mbedtls_ssl_ciphersuite_uses_dhe(const mbedtls_ssl_ciphersuite_t *info) -{ - switch (info->key_exchange) { - case MBEDTLS_KEY_EXCHANGE_DHE_RSA: - case MBEDTLS_KEY_EXCHANGE_DHE_PSK: - return 1; - - default: - return 0; - } -} -#endif /* MBEDTLS_KEY_EXCHANGE_SOME_DHE_ENABLED) */ - -#if defined(MBEDTLS_KEY_EXCHANGE_SOME_ECDHE_ENABLED) -static inline int mbedtls_ssl_ciphersuite_uses_ecdhe(const mbedtls_ssl_ciphersuite_t *info) -{ - switch (info->key_exchange) { - case MBEDTLS_KEY_EXCHANGE_ECDHE_ECDSA: - case MBEDTLS_KEY_EXCHANGE_ECDHE_RSA: - case MBEDTLS_KEY_EXCHANGE_ECDHE_PSK: - return 1; - - default: - return 0; - } -} -#endif /* MBEDTLS_KEY_EXCHANGE_SOME_ECDHE_ENABLED) */ - -#if defined(MBEDTLS_KEY_EXCHANGE_WITH_SERVER_SIGNATURE_ENABLED) -static inline int mbedtls_ssl_ciphersuite_uses_server_signature( - const mbedtls_ssl_ciphersuite_t *info) -{ - switch (info->key_exchange) { - case MBEDTLS_KEY_EXCHANGE_DHE_RSA: - case MBEDTLS_KEY_EXCHANGE_ECDHE_RSA: - case MBEDTLS_KEY_EXCHANGE_ECDHE_ECDSA: - return 1; - - default: - return 0; - } -} -#endif /* MBEDTLS_KEY_EXCHANGE_WITH_SERVER_SIGNATURE_ENABLED */ +size_t mbedtls_ssl_ciphersuite_get_cipher_key_bitlen(const mbedtls_ssl_ciphersuite_t *info); #ifdef __cplusplus } diff --git a/vendor/mbedtls/include/mbedtls/ssl_cookie.h b/vendor/mbedtls/include/mbedtls/ssl_cookie.h index 334c005a82..71c258ea48 100644 --- a/vendor/mbedtls/include/mbedtls/ssl_cookie.h +++ b/vendor/mbedtls/include/mbedtls/ssl_cookie.h @@ -5,40 +5,27 @@ */ /* * Copyright The Mbed TLS Contributors - * SPDX-License-Identifier: Apache-2.0 - * - * Licensed under the Apache License, Version 2.0 (the "License"); you may - * not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT - * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. + * SPDX-License-Identifier: Apache-2.0 OR GPL-2.0-or-later */ #ifndef MBEDTLS_SSL_COOKIE_H #define MBEDTLS_SSL_COOKIE_H +#include "mbedtls/private_access.h" -#if !defined(MBEDTLS_CONFIG_FILE) -#include "mbedtls/config.h" -#else -#include MBEDTLS_CONFIG_FILE -#endif +#include "mbedtls/build_info.h" #include "mbedtls/ssl.h" +#if !defined(MBEDTLS_USE_PSA_CRYPTO) #if defined(MBEDTLS_THREADING_C) #include "mbedtls/threading.h" #endif +#endif /* !MBEDTLS_USE_PSA_CRYPTO */ /** * \name SECTION: Module settings * * The configuration options you can set for this module are in this section. - * Either change them in config.h or define them on the compiler command line. + * Either change them in mbedtls_config.h or define them on the compiler command line. * \{ */ #ifndef MBEDTLS_SSL_COOKIE_TIMEOUT @@ -55,16 +42,23 @@ extern "C" { * \brief Context for the default cookie functions. */ typedef struct mbedtls_ssl_cookie_ctx { - mbedtls_md_context_t hmac_ctx; /*!< context for the HMAC portion */ +#if defined(MBEDTLS_USE_PSA_CRYPTO) + mbedtls_svc_key_id_t MBEDTLS_PRIVATE(psa_hmac_key); /*!< key id for the HMAC portion */ + psa_algorithm_t MBEDTLS_PRIVATE(psa_hmac_alg); /*!< key algorithm for the HMAC portion */ +#else + mbedtls_md_context_t MBEDTLS_PRIVATE(hmac_ctx); /*!< context for the HMAC portion */ +#endif /* MBEDTLS_USE_PSA_CRYPTO */ #if !defined(MBEDTLS_HAVE_TIME) - unsigned long serial; /*!< serial number for expiration */ + unsigned long MBEDTLS_PRIVATE(serial); /*!< serial number for expiration */ #endif - unsigned long timeout; /*!< timeout delay, in seconds if HAVE_TIME, - or in number of tickets issued */ + unsigned long MBEDTLS_PRIVATE(timeout); /*!< timeout delay, in seconds if HAVE_TIME, + or in number of tickets issued */ +#if !defined(MBEDTLS_USE_PSA_CRYPTO) #if defined(MBEDTLS_THREADING_C) - mbedtls_threading_mutex_t mutex; + mbedtls_threading_mutex_t MBEDTLS_PRIVATE(mutex); #endif +#endif /* !MBEDTLS_USE_PSA_CRYPTO */ } mbedtls_ssl_cookie_ctx; /** diff --git a/vendor/mbedtls/include/mbedtls/ssl_internal.h b/vendor/mbedtls/include/mbedtls/ssl_internal.h deleted file mode 100644 index b1915c8a1b..0000000000 --- a/vendor/mbedtls/include/mbedtls/ssl_internal.h +++ /dev/null @@ -1,1340 +0,0 @@ -/** - * \file ssl_internal.h - * - * \brief Internal functions shared by the SSL modules - */ -/* - * Copyright The Mbed TLS Contributors - * SPDX-License-Identifier: Apache-2.0 - * - * Licensed under the Apache License, Version 2.0 (the "License"); you may - * not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT - * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ -#ifndef MBEDTLS_SSL_INTERNAL_H -#define MBEDTLS_SSL_INTERNAL_H - -#if !defined(MBEDTLS_CONFIG_FILE) -#include "mbedtls/config.h" -#else -#include MBEDTLS_CONFIG_FILE -#endif - -#include "mbedtls/ssl.h" -#include "mbedtls/cipher.h" - -#if defined(MBEDTLS_USE_PSA_CRYPTO) -#include "psa/crypto.h" -#endif - -#if defined(MBEDTLS_MD5_C) -#include "mbedtls/md5.h" -#endif - -#if defined(MBEDTLS_SHA1_C) -#include "mbedtls/sha1.h" -#endif - -#if defined(MBEDTLS_SHA256_C) -#include "mbedtls/sha256.h" -#endif - -#if defined(MBEDTLS_SHA512_C) -#include "mbedtls/sha512.h" -#endif - -#if defined(MBEDTLS_KEY_EXCHANGE_ECJPAKE_ENABLED) -#include "mbedtls/ecjpake.h" -#endif - -#if defined(MBEDTLS_USE_PSA_CRYPTO) -#include "psa/crypto.h" -#include "mbedtls/psa_util.h" -#endif /* MBEDTLS_USE_PSA_CRYPTO */ - -#if (defined(__ARMCC_VERSION) || defined(_MSC_VER)) && \ - !defined(inline) && !defined(__cplusplus) -#define inline __inline -#endif - -/* Determine minimum supported version */ -#define MBEDTLS_SSL_MIN_MAJOR_VERSION MBEDTLS_SSL_MAJOR_VERSION_3 - -#if defined(MBEDTLS_SSL_PROTO_SSL3) -#define MBEDTLS_SSL_MIN_MINOR_VERSION MBEDTLS_SSL_MINOR_VERSION_0 -#else -#if defined(MBEDTLS_SSL_PROTO_TLS1) -#define MBEDTLS_SSL_MIN_MINOR_VERSION MBEDTLS_SSL_MINOR_VERSION_1 -#else -#if defined(MBEDTLS_SSL_PROTO_TLS1_1) -#define MBEDTLS_SSL_MIN_MINOR_VERSION MBEDTLS_SSL_MINOR_VERSION_2 -#else -#if defined(MBEDTLS_SSL_PROTO_TLS1_2) -#define MBEDTLS_SSL_MIN_MINOR_VERSION MBEDTLS_SSL_MINOR_VERSION_3 -#endif /* MBEDTLS_SSL_PROTO_TLS1_2 */ -#endif /* MBEDTLS_SSL_PROTO_TLS1_1 */ -#endif /* MBEDTLS_SSL_PROTO_TLS1 */ -#endif /* MBEDTLS_SSL_PROTO_SSL3 */ - -#define MBEDTLS_SSL_MIN_VALID_MINOR_VERSION MBEDTLS_SSL_MINOR_VERSION_1 -#define MBEDTLS_SSL_MIN_VALID_MAJOR_VERSION MBEDTLS_SSL_MAJOR_VERSION_3 - -/* Determine maximum supported version */ -#define MBEDTLS_SSL_MAX_MAJOR_VERSION MBEDTLS_SSL_MAJOR_VERSION_3 - -#if defined(MBEDTLS_SSL_PROTO_TLS1_2) -#define MBEDTLS_SSL_MAX_MINOR_VERSION MBEDTLS_SSL_MINOR_VERSION_3 -#else -#if defined(MBEDTLS_SSL_PROTO_TLS1_1) -#define MBEDTLS_SSL_MAX_MINOR_VERSION MBEDTLS_SSL_MINOR_VERSION_2 -#else -#if defined(MBEDTLS_SSL_PROTO_TLS1) -#define MBEDTLS_SSL_MAX_MINOR_VERSION MBEDTLS_SSL_MINOR_VERSION_1 -#else -#if defined(MBEDTLS_SSL_PROTO_SSL3) -#define MBEDTLS_SSL_MAX_MINOR_VERSION MBEDTLS_SSL_MINOR_VERSION_0 -#endif /* MBEDTLS_SSL_PROTO_SSL3 */ -#endif /* MBEDTLS_SSL_PROTO_TLS1 */ -#endif /* MBEDTLS_SSL_PROTO_TLS1_1 */ -#endif /* MBEDTLS_SSL_PROTO_TLS1_2 */ - -/* Shorthand for restartable ECC */ -#if defined(MBEDTLS_ECP_RESTARTABLE) && \ - defined(MBEDTLS_SSL_CLI_C) && \ - defined(MBEDTLS_SSL_PROTO_TLS1_2) && \ - defined(MBEDTLS_KEY_EXCHANGE_ECDHE_ECDSA_ENABLED) -#define MBEDTLS_SSL_ECP_RESTARTABLE_ENABLED -#endif - -#define MBEDTLS_SSL_INITIAL_HANDSHAKE 0 -#define MBEDTLS_SSL_RENEGOTIATION_IN_PROGRESS 1 /* In progress */ -#define MBEDTLS_SSL_RENEGOTIATION_DONE 2 /* Done or aborted */ -#define MBEDTLS_SSL_RENEGOTIATION_PENDING 3 /* Requested (server only) */ - -/* - * DTLS retransmission states, see RFC 6347 4.2.4 - * - * The SENDING state is merged in PREPARING for initial sends, - * but is distinct for resends. - * - * Note: initial state is wrong for server, but is not used anyway. - */ -#define MBEDTLS_SSL_RETRANS_PREPARING 0 -#define MBEDTLS_SSL_RETRANS_SENDING 1 -#define MBEDTLS_SSL_RETRANS_WAITING 2 -#define MBEDTLS_SSL_RETRANS_FINISHED 3 - -/* - * Allow extra bytes for record, authentication and encryption overhead: - * counter (8) + header (5) + IV(16) + MAC (16-48) + padding (0-256) - * and allow for a maximum of 1024 of compression expansion if - * enabled. - */ -#if defined(MBEDTLS_ZLIB_SUPPORT) -#define MBEDTLS_SSL_COMPRESSION_ADD 1024 -#else -#define MBEDTLS_SSL_COMPRESSION_ADD 0 -#endif - -/* This macro determines whether CBC is supported. */ -#if defined(MBEDTLS_CIPHER_MODE_CBC) && \ - (defined(MBEDTLS_AES_C) || \ - defined(MBEDTLS_CAMELLIA_C) || \ - defined(MBEDTLS_ARIA_C) || \ - defined(MBEDTLS_DES_C)) -#define MBEDTLS_SSL_SOME_SUITES_USE_CBC -#endif - -/* This macro determines whether the CBC construct used in TLS 1.0-1.2 (as - * opposed to the very different CBC construct used in SSLv3) is supported. */ -#if defined(MBEDTLS_SSL_SOME_SUITES_USE_CBC) && \ - (defined(MBEDTLS_SSL_PROTO_TLS1) || \ - defined(MBEDTLS_SSL_PROTO_TLS1_1) || \ - defined(MBEDTLS_SSL_PROTO_TLS1_2)) -#define MBEDTLS_SSL_SOME_SUITES_USE_TLS_CBC -#endif - -#if defined(MBEDTLS_ARC4_C) || defined(MBEDTLS_CIPHER_NULL_CIPHER) || \ - defined(MBEDTLS_SSL_SOME_SUITES_USE_CBC) -#define MBEDTLS_SSL_SOME_MODES_USE_MAC -#endif - -#if defined(MBEDTLS_SSL_SOME_MODES_USE_MAC) -/* Ciphersuites using HMAC */ -#if defined(MBEDTLS_SHA512_C) -#define MBEDTLS_SSL_MAC_ADD 48 /* SHA-384 used for HMAC */ -#elif defined(MBEDTLS_SHA256_C) -#define MBEDTLS_SSL_MAC_ADD 32 /* SHA-256 used for HMAC */ -#else -#define MBEDTLS_SSL_MAC_ADD 20 /* SHA-1 used for HMAC */ -#endif -#else /* MBEDTLS_SSL_SOME_MODES_USE_MAC */ -/* AEAD ciphersuites: GCM and CCM use a 128 bits tag */ -#define MBEDTLS_SSL_MAC_ADD 16 -#endif - -#if defined(MBEDTLS_CIPHER_MODE_CBC) -#define MBEDTLS_SSL_PADDING_ADD 256 -#else -#define MBEDTLS_SSL_PADDING_ADD 0 -#endif - -#if defined(MBEDTLS_SSL_DTLS_CONNECTION_ID) -#define MBEDTLS_SSL_MAX_CID_EXPANSION MBEDTLS_SSL_CID_PADDING_GRANULARITY -#else -#define MBEDTLS_SSL_MAX_CID_EXPANSION 0 -#endif - -#define MBEDTLS_SSL_PAYLOAD_OVERHEAD (MBEDTLS_SSL_COMPRESSION_ADD + \ - MBEDTLS_MAX_IV_LENGTH + \ - MBEDTLS_SSL_MAC_ADD + \ - MBEDTLS_SSL_PADDING_ADD + \ - MBEDTLS_SSL_MAX_CID_EXPANSION \ - ) - -#define MBEDTLS_SSL_IN_PAYLOAD_LEN (MBEDTLS_SSL_PAYLOAD_OVERHEAD + \ - (MBEDTLS_SSL_IN_CONTENT_LEN)) - -#define MBEDTLS_SSL_OUT_PAYLOAD_LEN (MBEDTLS_SSL_PAYLOAD_OVERHEAD + \ - (MBEDTLS_SSL_OUT_CONTENT_LEN)) - -/* The maximum number of buffered handshake messages. */ -#define MBEDTLS_SSL_MAX_BUFFERED_HS 4 - -/* Maximum length we can advertise as our max content length for - RFC 6066 max_fragment_length extension negotiation purposes - (the lesser of both sizes, if they are unequal.) - */ -#define MBEDTLS_TLS_EXT_ADV_CONTENT_LEN ( \ - (MBEDTLS_SSL_IN_CONTENT_LEN > MBEDTLS_SSL_OUT_CONTENT_LEN) \ - ? (MBEDTLS_SSL_OUT_CONTENT_LEN) \ - : (MBEDTLS_SSL_IN_CONTENT_LEN) \ - ) - -/* Maximum size in bytes of list in sig-hash algorithm ext., RFC 5246 */ -#define MBEDTLS_SSL_MAX_SIG_HASH_ALG_LIST_LEN 65534 - -/* Maximum size in bytes of list in supported elliptic curve ext., RFC 4492 */ -#define MBEDTLS_SSL_MAX_CURVE_LIST_LEN 65535 - -/* - * Check that we obey the standard's message size bounds - */ - -#if MBEDTLS_SSL_MAX_CONTENT_LEN > 16384 -#error "Bad configuration - record content too large." -#endif - -#if MBEDTLS_SSL_IN_CONTENT_LEN > MBEDTLS_SSL_MAX_CONTENT_LEN -#error \ - "Bad configuration - incoming record content should not be larger than MBEDTLS_SSL_MAX_CONTENT_LEN." -#endif - -#if MBEDTLS_SSL_OUT_CONTENT_LEN > MBEDTLS_SSL_MAX_CONTENT_LEN -#error \ - "Bad configuration - outgoing record content should not be larger than MBEDTLS_SSL_MAX_CONTENT_LEN." -#endif - -#if MBEDTLS_SSL_IN_PAYLOAD_LEN > MBEDTLS_SSL_MAX_CONTENT_LEN + 2048 -#error "Bad configuration - incoming protected record payload too large." -#endif - -#if MBEDTLS_SSL_OUT_PAYLOAD_LEN > MBEDTLS_SSL_MAX_CONTENT_LEN + 2048 -#error "Bad configuration - outgoing protected record payload too large." -#endif - -/* Calculate buffer sizes */ - -/* Note: Even though the TLS record header is only 5 bytes - long, we're internally using 8 bytes to store the - implicit sequence number. */ -#define MBEDTLS_SSL_HEADER_LEN 13 - -#if !defined(MBEDTLS_SSL_DTLS_CONNECTION_ID) -#define MBEDTLS_SSL_IN_BUFFER_LEN \ - ((MBEDTLS_SSL_HEADER_LEN) + (MBEDTLS_SSL_IN_PAYLOAD_LEN)) -#else -#define MBEDTLS_SSL_IN_BUFFER_LEN \ - ((MBEDTLS_SSL_HEADER_LEN) + (MBEDTLS_SSL_IN_PAYLOAD_LEN) \ - + (MBEDTLS_SSL_CID_IN_LEN_MAX)) -#endif - -#if !defined(MBEDTLS_SSL_DTLS_CONNECTION_ID) -#define MBEDTLS_SSL_OUT_BUFFER_LEN \ - ((MBEDTLS_SSL_HEADER_LEN) + (MBEDTLS_SSL_OUT_PAYLOAD_LEN)) -#else -#define MBEDTLS_SSL_OUT_BUFFER_LEN \ - ((MBEDTLS_SSL_HEADER_LEN) + (MBEDTLS_SSL_OUT_PAYLOAD_LEN) \ - + (MBEDTLS_SSL_CID_OUT_LEN_MAX)) -#endif - -#if defined(MBEDTLS_SSL_VARIABLE_BUFFER_LENGTH) -static inline size_t mbedtls_ssl_get_output_buflen(const mbedtls_ssl_context *ctx) -{ -#if defined(MBEDTLS_SSL_DTLS_CONNECTION_ID) - return mbedtls_ssl_get_output_max_frag_len(ctx) - + MBEDTLS_SSL_HEADER_LEN + MBEDTLS_SSL_PAYLOAD_OVERHEAD - + MBEDTLS_SSL_CID_OUT_LEN_MAX; -#else - return mbedtls_ssl_get_output_max_frag_len(ctx) - + MBEDTLS_SSL_HEADER_LEN + MBEDTLS_SSL_PAYLOAD_OVERHEAD; -#endif -} - -static inline size_t mbedtls_ssl_get_input_buflen(const mbedtls_ssl_context *ctx) -{ -#if defined(MBEDTLS_SSL_DTLS_CONNECTION_ID) - return mbedtls_ssl_get_input_max_frag_len(ctx) - + MBEDTLS_SSL_HEADER_LEN + MBEDTLS_SSL_PAYLOAD_OVERHEAD - + MBEDTLS_SSL_CID_IN_LEN_MAX; -#else - return mbedtls_ssl_get_input_max_frag_len(ctx) - + MBEDTLS_SSL_HEADER_LEN + MBEDTLS_SSL_PAYLOAD_OVERHEAD; -#endif -} -#endif - -#ifdef MBEDTLS_ZLIB_SUPPORT -/* Compression buffer holds both IN and OUT buffers, so should be size of the larger */ -#define MBEDTLS_SSL_COMPRESS_BUFFER_LEN ( \ - (MBEDTLS_SSL_IN_BUFFER_LEN > MBEDTLS_SSL_OUT_BUFFER_LEN) \ - ? MBEDTLS_SSL_IN_BUFFER_LEN \ - : MBEDTLS_SSL_OUT_BUFFER_LEN \ - ) -#endif - -/* - * TLS extension flags (for extensions with outgoing ServerHello content - * that need it (e.g. for RENEGOTIATION_INFO the server already knows because - * of state of the renegotiation flag, so no indicator is required) - */ -#define MBEDTLS_TLS_EXT_SUPPORTED_POINT_FORMATS_PRESENT (1 << 0) -#define MBEDTLS_TLS_EXT_ECJPAKE_KKPP_OK (1 << 1) - -/** - * \brief This function checks if the remaining size in a buffer is - * greater or equal than a needed space. - * - * \param cur Pointer to the current position in the buffer. - * \param end Pointer to one past the end of the buffer. - * \param need Needed space in bytes. - * - * \return Zero if the needed space is available in the buffer, non-zero - * otherwise. - */ -static inline int mbedtls_ssl_chk_buf_ptr(const uint8_t *cur, - const uint8_t *end, size_t need) -{ - return (cur > end) || (need > (size_t) (end - cur)); -} - -/** - * \brief This macro checks if the remaining size in a buffer is - * greater or equal than a needed space. If it is not the case, - * it returns an SSL_BUFFER_TOO_SMALL error. - * - * \param cur Pointer to the current position in the buffer. - * \param end Pointer to one past the end of the buffer. - * \param need Needed space in bytes. - * - */ -#define MBEDTLS_SSL_CHK_BUF_PTR(cur, end, need) \ - do { \ - if (mbedtls_ssl_chk_buf_ptr((cur), (end), (need)) != 0) \ - { \ - return MBEDTLS_ERR_SSL_BUFFER_TOO_SMALL; \ - } \ - } while (0) - -#ifdef __cplusplus -extern "C" { -#endif - -#if defined(MBEDTLS_SSL_PROTO_TLS1_2) && \ - defined(MBEDTLS_KEY_EXCHANGE_WITH_CERT_ENABLED) -/* - * Abstraction for a grid of allowed signature-hash-algorithm pairs. - */ -struct mbedtls_ssl_sig_hash_set_t { - /* At the moment, we only need to remember a single suitable - * hash algorithm per signature algorithm. As long as that's - * the case - and we don't need a general lookup function - - * we can implement the sig-hash-set as a map from signatures - * to hash algorithms. */ - mbedtls_md_type_t rsa; - mbedtls_md_type_t ecdsa; -}; -#endif /* MBEDTLS_SSL_PROTO_TLS1_2 && - MBEDTLS_KEY_EXCHANGE_WITH_CERT_ENABLED */ - -typedef int mbedtls_ssl_tls_prf_cb(const unsigned char *secret, size_t slen, - const char *label, - const unsigned char *random, size_t rlen, - unsigned char *dstbuf, size_t dlen); - -/* cipher.h exports the maximum IV, key and block length from - * all ciphers enabled in the config, regardless of whether those - * ciphers are actually usable in SSL/TLS. Notably, XTS is enabled - * in the default configuration and uses 64 Byte keys, but it is - * not used for record protection in SSL/TLS. - * - * In order to prevent unnecessary inflation of key structures, - * we introduce SSL-specific variants of the max-{key,block,IV} - * macros here which are meant to only take those ciphers into - * account which can be negotiated in SSL/TLS. - * - * Since the current definitions of MBEDTLS_MAX_{KEY|BLOCK|IV}_LENGTH - * in cipher.h are rough overapproximations of the real maxima, here - * we content ourselves with replicating those overapproximations - * for the maximum block and IV length, and excluding XTS from the - * computation of the maximum key length. */ -#define MBEDTLS_SSL_MAX_BLOCK_LENGTH 16 -#define MBEDTLS_SSL_MAX_IV_LENGTH 16 -#define MBEDTLS_SSL_MAX_KEY_LENGTH 32 - -/** - * \brief The data structure holding the cryptographic material (key and IV) - * used for record protection in TLS 1.3. - */ -struct mbedtls_ssl_key_set { - /*! The key for client->server records. */ - unsigned char client_write_key[MBEDTLS_SSL_MAX_KEY_LENGTH]; - /*! The key for server->client records. */ - unsigned char server_write_key[MBEDTLS_SSL_MAX_KEY_LENGTH]; - /*! The IV for client->server records. */ - unsigned char client_write_iv[MBEDTLS_SSL_MAX_IV_LENGTH]; - /*! The IV for server->client records. */ - unsigned char server_write_iv[MBEDTLS_SSL_MAX_IV_LENGTH]; - - size_t key_len; /*!< The length of client_write_key and - * server_write_key, in Bytes. */ - size_t iv_len; /*!< The length of client_write_iv and - * server_write_iv, in Bytes. */ -}; -typedef struct mbedtls_ssl_key_set mbedtls_ssl_key_set; - -/* - * This structure contains the parameters only needed during handshake. - */ -struct mbedtls_ssl_handshake_params { - /* - * Handshake specific crypto variables - */ - - uint8_t max_major_ver; /*!< max. major version client*/ - uint8_t max_minor_ver; /*!< max. minor version client*/ - uint8_t resume; /*!< session resume indicator*/ - uint8_t cli_exts; /*!< client extension presence*/ - -#if defined(MBEDTLS_X509_CRT_PARSE_C) && \ - defined(MBEDTLS_SSL_SERVER_NAME_INDICATION) - uint8_t sni_authmode; /*!< authmode from SNI callback */ -#endif - -#if defined(MBEDTLS_SSL_SESSION_TICKETS) - uint8_t new_session_ticket; /*!< use NewSessionTicket? */ -#endif /* MBEDTLS_SSL_SESSION_TICKETS */ - -#if defined(MBEDTLS_SSL_EXTENDED_MASTER_SECRET) - uint8_t extended_ms; /*!< use Extended Master Secret? */ -#endif - -#if defined(MBEDTLS_SSL_ASYNC_PRIVATE) - uint8_t async_in_progress; /*!< an asynchronous operation is in progress */ -#endif /* MBEDTLS_SSL_ASYNC_PRIVATE */ - -#if defined(MBEDTLS_SSL_PROTO_DTLS) - unsigned char retransmit_state; /*!< Retransmission state */ -#endif - -#if defined(MBEDTLS_SSL_ECP_RESTARTABLE_ENABLED) - uint8_t ecrs_enabled; /*!< Handshake supports EC restart? */ - enum { /* this complements ssl->state with info on intra-state operations */ - ssl_ecrs_none = 0, /*!< nothing going on (yet) */ - ssl_ecrs_crt_verify, /*!< Certificate: crt_verify() */ - ssl_ecrs_ske_start_processing, /*!< ServerKeyExchange: pk_verify() */ - ssl_ecrs_cke_ecdh_calc_secret, /*!< ClientKeyExchange: ECDH step 2 */ - ssl_ecrs_crt_vrfy_sign, /*!< CertificateVerify: pk_sign() */ - } ecrs_state; /*!< current (or last) operation */ - mbedtls_x509_crt *ecrs_peer_cert; /*!< The peer's CRT chain. */ - size_t ecrs_n; /*!< place for saving a length */ -#endif - -#if defined(MBEDTLS_SSL_PROTO_TLS1_2) && \ - defined(MBEDTLS_KEY_EXCHANGE_WITH_CERT_ENABLED) - mbedtls_ssl_sig_hash_set_t hash_algs; /*!< Set of suitable sig-hash pairs */ -#endif - - size_t pmslen; /*!< premaster length */ - - mbedtls_ssl_ciphersuite_t const *ciphersuite_info; - - void (*update_checksum)(mbedtls_ssl_context *, const unsigned char *, size_t); - void (*calc_verify)(const mbedtls_ssl_context *, unsigned char *, size_t *); - void (*calc_finished)(mbedtls_ssl_context *, unsigned char *, int); - mbedtls_ssl_tls_prf_cb *tls_prf; - -#if defined(MBEDTLS_DHM_C) - mbedtls_dhm_context dhm_ctx; /*!< DHM key exchange */ -#endif - -/* Adding guard for MBEDTLS_ECDSA_C to ensure no compile errors due - * to guards also being in ssl_srv.c and ssl_cli.c. There is a gap - * in functionality that access to ecdh_ctx structure is needed for - * MBEDTLS_ECDSA_C which does not seem correct. - */ -#if defined(MBEDTLS_ECDH_C) || defined(MBEDTLS_ECDSA_C) - mbedtls_ecdh_context ecdh_ctx; /*!< ECDH key exchange */ - -#if defined(MBEDTLS_USE_PSA_CRYPTO) - psa_key_type_t ecdh_psa_type; - uint16_t ecdh_bits; - psa_key_id_t ecdh_psa_privkey; - unsigned char ecdh_psa_peerkey[MBEDTLS_PSA_MAX_EC_PUBKEY_LENGTH]; - size_t ecdh_psa_peerkey_len; -#endif /* MBEDTLS_USE_PSA_CRYPTO */ -#endif /* MBEDTLS_ECDH_C || MBEDTLS_ECDSA_C */ - -#if defined(MBEDTLS_KEY_EXCHANGE_ECJPAKE_ENABLED) - mbedtls_ecjpake_context ecjpake_ctx; /*!< EC J-PAKE key exchange */ -#if defined(MBEDTLS_SSL_CLI_C) - unsigned char *ecjpake_cache; /*!< Cache for ClientHello ext */ - size_t ecjpake_cache_len; /*!< Length of cached data */ -#endif -#endif /* MBEDTLS_KEY_EXCHANGE_ECJPAKE_ENABLED */ - -#if defined(MBEDTLS_ECDH_C) || defined(MBEDTLS_ECDSA_C) || \ - defined(MBEDTLS_KEY_EXCHANGE_ECJPAKE_ENABLED) - const mbedtls_ecp_curve_info **curves; /*!< Supported elliptic curves */ -#endif - -#if defined(MBEDTLS_KEY_EXCHANGE_SOME_PSK_ENABLED) -#if defined(MBEDTLS_USE_PSA_CRYPTO) - psa_key_id_t psk_opaque; /*!< Opaque PSK from the callback */ -#endif /* MBEDTLS_USE_PSA_CRYPTO */ - unsigned char *psk; /*!< PSK from the callback */ - size_t psk_len; /*!< Length of PSK from callback */ -#endif /* MBEDTLS_KEY_EXCHANGE_SOME_PSK_ENABLED */ - -#if defined(MBEDTLS_X509_CRT_PARSE_C) - mbedtls_ssl_key_cert *key_cert; /*!< chosen key/cert pair (server) */ -#if defined(MBEDTLS_SSL_SERVER_NAME_INDICATION) - mbedtls_ssl_key_cert *sni_key_cert; /*!< key/cert list from SNI */ - mbedtls_x509_crt *sni_ca_chain; /*!< trusted CAs from SNI callback */ - mbedtls_x509_crl *sni_ca_crl; /*!< trusted CAs CRLs from SNI */ -#endif /* MBEDTLS_SSL_SERVER_NAME_INDICATION */ -#endif /* MBEDTLS_X509_CRT_PARSE_C */ - -#if defined(MBEDTLS_SSL_ECP_RESTARTABLE_ENABLED) - mbedtls_x509_crt_restart_ctx ecrs_ctx; /*!< restart context */ -#endif - -#if defined(MBEDTLS_X509_CRT_PARSE_C) && \ - !defined(MBEDTLS_SSL_KEEP_PEER_CERTIFICATE) - mbedtls_pk_context peer_pubkey; /*!< The public key from the peer. */ -#endif /* MBEDTLS_X509_CRT_PARSE_C && !MBEDTLS_SSL_KEEP_PEER_CERTIFICATE */ - -#if defined(MBEDTLS_SSL_PROTO_DTLS) - struct { - size_t total_bytes_buffered; /*!< Cumulative size of heap allocated - * buffers used for message buffering. */ - - uint8_t seen_ccs; /*!< Indicates if a CCS message has - * been seen in the current flight. */ - - struct mbedtls_ssl_hs_buffer { - unsigned is_valid : 1; - unsigned is_fragmented : 1; - unsigned is_complete : 1; - unsigned char *data; - size_t data_len; - } hs[MBEDTLS_SSL_MAX_BUFFERED_HS]; - - struct { - unsigned char *data; - size_t len; - unsigned epoch; - } future_record; - - } buffering; - - unsigned int out_msg_seq; /*!< Outgoing handshake sequence number */ - unsigned int in_msg_seq; /*!< Incoming handshake sequence number */ - - unsigned char *verify_cookie; /*!< Cli: HelloVerifyRequest cookie - Srv: unused */ - unsigned char verify_cookie_len; /*!< Cli: cookie length - Srv: flag for sending a cookie */ - - uint32_t retransmit_timeout; /*!< Current value of timeout */ - mbedtls_ssl_flight_item *flight; /*!< Current outgoing flight */ - mbedtls_ssl_flight_item *cur_msg; /*!< Current message in flight */ - unsigned char *cur_msg_p; /*!< Position in current message */ - unsigned int in_flight_start_seq; /*!< Minimum message sequence in the - flight being received */ - mbedtls_ssl_transform *alt_transform_out; /*!< Alternative transform for - resending messages */ - unsigned char alt_out_ctr[8]; /*!< Alternative record epoch/counter - for resending messages */ - -#if defined(MBEDTLS_SSL_DTLS_CONNECTION_ID) - /* The state of CID configuration in this handshake. */ - - uint8_t cid_in_use; /*!< This indicates whether the use of the CID extension - * has been negotiated. Possible values are - * #MBEDTLS_SSL_CID_ENABLED and - * #MBEDTLS_SSL_CID_DISABLED. */ - unsigned char peer_cid[MBEDTLS_SSL_CID_OUT_LEN_MAX]; /*! The peer's CID */ - uint8_t peer_cid_len; /*!< The length of - * \c peer_cid. */ -#endif /* MBEDTLS_SSL_DTLS_CONNECTION_ID */ - - uint16_t mtu; /*!< Handshake mtu, used to fragment outgoing messages */ -#endif /* MBEDTLS_SSL_PROTO_DTLS */ - - /* - * Checksum contexts - */ -#if defined(MBEDTLS_SSL_PROTO_SSL3) || defined(MBEDTLS_SSL_PROTO_TLS1) || \ - defined(MBEDTLS_SSL_PROTO_TLS1_1) - mbedtls_md5_context fin_md5; - mbedtls_sha1_context fin_sha1; -#endif -#if defined(MBEDTLS_SSL_PROTO_TLS1_2) -#if defined(MBEDTLS_SHA256_C) -#if defined(MBEDTLS_USE_PSA_CRYPTO) - psa_hash_operation_t fin_sha256_psa; -#else - mbedtls_sha256_context fin_sha256; -#endif -#endif -#if defined(MBEDTLS_SHA512_C) -#if defined(MBEDTLS_USE_PSA_CRYPTO) - psa_hash_operation_t fin_sha384_psa; -#else - mbedtls_sha512_context fin_sha512; -#endif -#endif -#endif /* MBEDTLS_SSL_PROTO_TLS1_2 */ - - unsigned char randbytes[64]; /*!< random bytes */ - unsigned char premaster[MBEDTLS_PREMASTER_SIZE]; - /*!< premaster secret */ - -#if defined(MBEDTLS_SSL_ASYNC_PRIVATE) - /** Asynchronous operation context. This field is meant for use by the - * asynchronous operation callbacks (mbedtls_ssl_config::f_async_sign_start, - * mbedtls_ssl_config::f_async_decrypt_start, - * mbedtls_ssl_config::f_async_resume, mbedtls_ssl_config::f_async_cancel). - * The library does not use it internally. */ - void *user_async_ctx; -#endif /* MBEDTLS_SSL_ASYNC_PRIVATE */ -}; - -typedef struct mbedtls_ssl_hs_buffer mbedtls_ssl_hs_buffer; - -/* - * Representation of decryption/encryption transformations on records - * - * There are the following general types of record transformations: - * - Stream transformations (TLS versions <= 1.2 only) - * Transformation adding a MAC and applying a stream-cipher - * to the authenticated message. - * - CBC block cipher transformations ([D]TLS versions <= 1.2 only) - * In addition to the distinction of the order of encryption and - * authentication, there's a fundamental difference between the - * handling in SSL3 & TLS 1.0 and TLS 1.1 and TLS 1.2: For SSL3 - * and TLS 1.0, the final IV after processing a record is used - * as the IV for the next record. No explicit IV is contained - * in an encrypted record. The IV for the first record is extracted - * at key extraction time. In contrast, for TLS 1.1 and 1.2, no - * IV is generated at key extraction time, but every encrypted - * record is explicitly prefixed by the IV with which it was encrypted. - * - AEAD transformations ([D]TLS versions >= 1.2 only) - * These come in two fundamentally different versions, the first one - * used in TLS 1.2, excluding ChaChaPoly ciphersuites, and the second - * one used for ChaChaPoly ciphersuites in TLS 1.2 as well as for TLS 1.3. - * In the first transformation, the IV to be used for a record is obtained - * as the concatenation of an explicit, static 4-byte IV and the 8-byte - * record sequence number, and explicitly prepending this sequence number - * to the encrypted record. In contrast, in the second transformation - * the IV is obtained by XOR'ing a static IV obtained at key extraction - * time with the 8-byte record sequence number, without prepending the - * latter to the encrypted record. - * - * Additionally, DTLS 1.2 + CID as well as TLS 1.3 use an inner plaintext - * which allows to add flexible length padding and to hide a record's true - * content type. - * - * In addition to type and version, the following parameters are relevant: - * - The symmetric cipher algorithm to be used. - * - The (static) encryption/decryption keys for the cipher. - * - For stream/CBC, the type of message digest to be used. - * - For stream/CBC, (static) encryption/decryption keys for the digest. - * - For AEAD transformations, the size (potentially 0) of an explicit, - * random initialization vector placed in encrypted records. - * - For some transformations (currently AEAD and CBC in SSL3 and TLS 1.0) - * an implicit IV. It may be static (e.g. AEAD) or dynamic (e.g. CBC) - * and (if present) is combined with the explicit IV in a transformation- - * dependent way (e.g. appending in TLS 1.2 and XOR'ing in TLS 1.3). - * - For stream/CBC, a flag determining the order of encryption and MAC. - * - The details of the transformation depend on the SSL/TLS version. - * - The length of the authentication tag. - * - * Note: Except for CBC in SSL3 and TLS 1.0, these parameters are - * constant across multiple encryption/decryption operations. - * For CBC, the implicit IV needs to be updated after each - * operation. - * - * The struct below refines this abstract view as follows: - * - The cipher underlying the transformation is managed in - * cipher contexts cipher_ctx_{enc/dec}, which must have the - * same cipher type. The mode of these cipher contexts determines - * the type of the transformation in the sense above: e.g., if - * the type is MBEDTLS_CIPHER_AES_256_CBC resp. MBEDTLS_CIPHER_AES_192_GCM - * then the transformation has type CBC resp. AEAD. - * - The cipher keys are never stored explicitly but - * are maintained within cipher_ctx_{enc/dec}. - * - For stream/CBC transformations, the message digest contexts - * used for the MAC's are stored in md_ctx_{enc/dec}. These contexts - * are unused for AEAD transformations. - * - For stream/CBC transformations and versions > SSL3, the - * MAC keys are not stored explicitly but maintained within - * md_ctx_{enc/dec}. - * - For stream/CBC transformations and version SSL3, the MAC - * keys are stored explicitly in mac_enc, mac_dec and have - * a fixed size of 20 bytes. These fields are unused for - * AEAD transformations or transformations >= TLS 1.0. - * - For transformations using an implicit IV maintained within - * the transformation context, its contents are stored within - * iv_{enc/dec}. - * - The value of ivlen indicates the length of the IV. - * This is redundant in case of stream/CBC transformations - * which always use 0 resp. the cipher's block length as the - * IV length, but is needed for AEAD ciphers and may be - * different from the underlying cipher's block length - * in this case. - * - The field fixed_ivlen is nonzero for AEAD transformations only - * and indicates the length of the static part of the IV which is - * constant throughout the communication, and which is stored in - * the first fixed_ivlen bytes of the iv_{enc/dec} arrays. - * Note: For CBC in SSL3 and TLS 1.0, the fields iv_{enc/dec} - * still store IV's for continued use across multiple transformations, - * so it is not true that fixed_ivlen == 0 means that iv_{enc/dec} are - * not being used! - * - minor_ver denotes the SSL/TLS version - * - For stream/CBC transformations, maclen denotes the length of the - * authentication tag, while taglen is unused and 0. - * - For AEAD transformations, taglen denotes the length of the - * authentication tag, while maclen is unused and 0. - * - For CBC transformations, encrypt_then_mac determines the - * order of encryption and authentication. This field is unused - * in other transformations. - * - */ -struct mbedtls_ssl_transform { - /* - * Session specific crypto layer - */ - size_t minlen; /*!< min. ciphertext length */ - size_t ivlen; /*!< IV length */ - size_t fixed_ivlen; /*!< Fixed part of IV (AEAD) */ - size_t maclen; /*!< MAC(CBC) len */ - size_t taglen; /*!< TAG(AEAD) len */ - - unsigned char iv_enc[16]; /*!< IV (encryption) */ - unsigned char iv_dec[16]; /*!< IV (decryption) */ - -#if defined(MBEDTLS_SSL_SOME_MODES_USE_MAC) - -#if defined(MBEDTLS_SSL_PROTO_SSL3) - /* Needed only for SSL v3.0 secret */ - unsigned char mac_enc[20]; /*!< SSL v3.0 secret (enc) */ - unsigned char mac_dec[20]; /*!< SSL v3.0 secret (dec) */ -#endif /* MBEDTLS_SSL_PROTO_SSL3 */ - - mbedtls_md_context_t md_ctx_enc; /*!< MAC (encryption) */ - mbedtls_md_context_t md_ctx_dec; /*!< MAC (decryption) */ - -#if defined(MBEDTLS_SSL_ENCRYPT_THEN_MAC) - int encrypt_then_mac; /*!< flag for EtM activation */ -#endif - -#endif /* MBEDTLS_SSL_SOME_MODES_USE_MAC */ - - mbedtls_cipher_context_t cipher_ctx_enc; /*!< encryption context */ - mbedtls_cipher_context_t cipher_ctx_dec; /*!< decryption context */ - int minor_ver; - -#if defined(MBEDTLS_SSL_DTLS_CONNECTION_ID) - uint8_t in_cid_len; - uint8_t out_cid_len; - unsigned char in_cid[MBEDTLS_SSL_CID_IN_LEN_MAX]; - unsigned char out_cid[MBEDTLS_SSL_CID_OUT_LEN_MAX]; -#endif /* MBEDTLS_SSL_DTLS_CONNECTION_ID */ - - /* - * Session specific compression layer - */ -#if defined(MBEDTLS_ZLIB_SUPPORT) - z_stream ctx_deflate; /*!< compression context */ - z_stream ctx_inflate; /*!< decompression context */ -#endif - -#if defined(MBEDTLS_SSL_CONTEXT_SERIALIZATION) - /* We need the Hello random bytes in order to re-derive keys from the - * Master Secret and other session info, see ssl_populate_transform() */ - unsigned char randbytes[64]; /*!< ServerHello.random+ClientHello.random */ -#endif /* MBEDTLS_SSL_CONTEXT_SERIALIZATION */ -}; - -/* - * Return 1 if the transform uses an AEAD cipher, 0 otherwise. - * Equivalently, return 0 if a separate MAC is used, 1 otherwise. - */ -static inline int mbedtls_ssl_transform_uses_aead( - const mbedtls_ssl_transform *transform) -{ -#if defined(MBEDTLS_SSL_SOME_MODES_USE_MAC) - return transform->maclen == 0 && transform->taglen != 0; -#else - (void) transform; - return 1; -#endif -} - -/* - * Internal representation of record frames - * - * Instances come in two flavors: - * (1) Encrypted - * These always have data_offset = 0 - * (2) Unencrypted - * These have data_offset set to the amount of - * pre-expansion during record protection. Concretely, - * this is the length of the fixed part of the explicit IV - * used for encryption, or 0 if no explicit IV is used - * (e.g. for CBC in TLS 1.0, or stream ciphers). - * - * The reason for the data_offset in the unencrypted case - * is to allow for in-place conversion of an unencrypted to - * an encrypted record. If the offset wasn't included, the - * encrypted content would need to be shifted afterwards to - * make space for the fixed IV. - * - */ -#if MBEDTLS_SSL_CID_OUT_LEN_MAX > MBEDTLS_SSL_CID_IN_LEN_MAX -#define MBEDTLS_SSL_CID_LEN_MAX MBEDTLS_SSL_CID_OUT_LEN_MAX -#else -#define MBEDTLS_SSL_CID_LEN_MAX MBEDTLS_SSL_CID_IN_LEN_MAX -#endif - -typedef struct { - uint8_t ctr[8]; /* In TLS: The implicit record sequence number. - * In DTLS: The 2-byte epoch followed by - * the 6-byte sequence number. - * This is stored as a raw big endian byte array - * as opposed to a uint64_t because we rarely - * need to perform arithmetic on this, but do - * need it as a Byte array for the purpose of - * MAC computations. */ - uint8_t type; /* The record content type. */ - uint8_t ver[2]; /* SSL/TLS version as present on the wire. - * Convert to internal presentation of versions - * using mbedtls_ssl_read_version() and - * mbedtls_ssl_write_version(). - * Keep wire-format for MAC computations. */ - - unsigned char *buf; /* Memory buffer enclosing the record content */ - size_t buf_len; /* Buffer length */ - size_t data_offset; /* Offset of record content */ - size_t data_len; /* Length of record content */ - -#if defined(MBEDTLS_SSL_DTLS_CONNECTION_ID) - uint8_t cid_len; /* Length of the CID (0 if not present) */ - unsigned char cid[MBEDTLS_SSL_CID_LEN_MAX]; /* The CID */ -#endif /* MBEDTLS_SSL_DTLS_CONNECTION_ID */ -} mbedtls_record; - -#if defined(MBEDTLS_X509_CRT_PARSE_C) -/* - * List of certificate + private key pairs - */ -struct mbedtls_ssl_key_cert { - mbedtls_x509_crt *cert; /*!< cert */ - mbedtls_pk_context *key; /*!< private key */ - mbedtls_ssl_key_cert *next; /*!< next key/cert pair */ -}; -#endif /* MBEDTLS_X509_CRT_PARSE_C */ - -#if defined(MBEDTLS_SSL_PROTO_DTLS) -/* - * List of handshake messages kept around for resending - */ -struct mbedtls_ssl_flight_item { - unsigned char *p; /*!< message, including handshake headers */ - size_t len; /*!< length of p */ - unsigned char type; /*!< type of the message: handshake or CCS */ - mbedtls_ssl_flight_item *next; /*!< next handshake message(s) */ -}; -#endif /* MBEDTLS_SSL_PROTO_DTLS */ - -#if defined(MBEDTLS_SSL_PROTO_TLS1_2) && \ - defined(MBEDTLS_KEY_EXCHANGE_WITH_CERT_ENABLED) - -/* Find an entry in a signature-hash set matching a given hash algorithm. */ -mbedtls_md_type_t mbedtls_ssl_sig_hash_set_find(mbedtls_ssl_sig_hash_set_t *set, - mbedtls_pk_type_t sig_alg); -/* Add a signature-hash-pair to a signature-hash set */ -void mbedtls_ssl_sig_hash_set_add(mbedtls_ssl_sig_hash_set_t *set, - mbedtls_pk_type_t sig_alg, - mbedtls_md_type_t md_alg); -/* Allow exactly one hash algorithm for each signature. */ -void mbedtls_ssl_sig_hash_set_const_hash(mbedtls_ssl_sig_hash_set_t *set, - mbedtls_md_type_t md_alg); - -/* Setup an empty signature-hash set */ -static inline void mbedtls_ssl_sig_hash_set_init(mbedtls_ssl_sig_hash_set_t *set) -{ - mbedtls_ssl_sig_hash_set_const_hash(set, MBEDTLS_MD_NONE); -} - -#endif /* MBEDTLS_SSL_PROTO_TLS1_2) && - MBEDTLS_KEY_EXCHANGE_WITH_CERT_ENABLED */ - -/** - * \brief Free referenced items in an SSL transform context and clear - * memory - * - * \param transform SSL transform context - */ -void mbedtls_ssl_transform_free(mbedtls_ssl_transform *transform); - -/** - * \brief Free referenced items in an SSL handshake context and clear - * memory - * - * \param ssl SSL context - */ -void mbedtls_ssl_handshake_free(mbedtls_ssl_context *ssl); - -MBEDTLS_CHECK_RETURN_CRITICAL -int mbedtls_ssl_handshake_client_step(mbedtls_ssl_context *ssl); -MBEDTLS_CHECK_RETURN_CRITICAL -int mbedtls_ssl_handshake_server_step(mbedtls_ssl_context *ssl); -void mbedtls_ssl_handshake_wrapup(mbedtls_ssl_context *ssl); - -MBEDTLS_CHECK_RETURN_CRITICAL -int mbedtls_ssl_send_fatal_handshake_failure(mbedtls_ssl_context *ssl); - -void mbedtls_ssl_reset_checksum(mbedtls_ssl_context *ssl); -MBEDTLS_CHECK_RETURN_CRITICAL -int mbedtls_ssl_derive_keys(mbedtls_ssl_context *ssl); - -MBEDTLS_CHECK_RETURN_CRITICAL -int mbedtls_ssl_handle_message_type(mbedtls_ssl_context *ssl); -MBEDTLS_CHECK_RETURN_CRITICAL -int mbedtls_ssl_prepare_handshake_record(mbedtls_ssl_context *ssl); -void mbedtls_ssl_update_handshake_status(mbedtls_ssl_context *ssl); - -/** - * \brief Update record layer - * - * This function roughly separates the implementation - * of the logic of (D)TLS from the implementation - * of the secure transport. - * - * \param ssl The SSL context to use. - * \param update_hs_digest This indicates if the handshake digest - * should be automatically updated in case - * a handshake message is found. - * - * \return 0 or non-zero error code. - * - * \note A clarification on what is called 'record layer' here - * is in order, as many sensible definitions are possible: - * - * The record layer takes as input an untrusted underlying - * transport (stream or datagram) and transforms it into - * a serially multiplexed, secure transport, which - * conceptually provides the following: - * - * (1) Three datagram based, content-agnostic transports - * for handshake, alert and CCS messages. - * (2) One stream- or datagram-based transport - * for application data. - * (3) Functionality for changing the underlying transform - * securing the contents. - * - * The interface to this functionality is given as follows: - * - * a Updating - * [Currently implemented by mbedtls_ssl_read_record] - * - * Check if and on which of the four 'ports' data is pending: - * Nothing, a controlling datagram of type (1), or application - * data (2). In any case data is present, internal buffers - * provide access to the data for the user to process it. - * Consumption of type (1) datagrams is done automatically - * on the next update, invalidating that the internal buffers - * for previous datagrams, while consumption of application - * data (2) is user-controlled. - * - * b Reading of application data - * [Currently manual adaption of ssl->in_offt pointer] - * - * As mentioned in the last paragraph, consumption of data - * is different from the automatic consumption of control - * datagrams (1) because application data is treated as a stream. - * - * c Tracking availability of application data - * [Currently manually through decreasing ssl->in_msglen] - * - * For efficiency and to retain datagram semantics for - * application data in case of DTLS, the record layer - * provides functionality for checking how much application - * data is still available in the internal buffer. - * - * d Changing the transformation securing the communication. - * - * Given an opaque implementation of the record layer in the - * above sense, it should be possible to implement the logic - * of (D)TLS on top of it without the need to know anything - * about the record layer's internals. This is done e.g. - * in all the handshake handling functions, and in the - * application data reading function mbedtls_ssl_read. - * - * \note The above tries to give a conceptual picture of the - * record layer, but the current implementation deviates - * from it in some places. For example, our implementation of - * the update functionality through mbedtls_ssl_read_record - * discards datagrams depending on the current state, which - * wouldn't fall under the record layer's responsibility - * following the above definition. - * - */ -MBEDTLS_CHECK_RETURN_CRITICAL -int mbedtls_ssl_read_record(mbedtls_ssl_context *ssl, - unsigned update_hs_digest); -MBEDTLS_CHECK_RETURN_CRITICAL -int mbedtls_ssl_fetch_input(mbedtls_ssl_context *ssl, size_t nb_want); - -MBEDTLS_CHECK_RETURN_CRITICAL -int mbedtls_ssl_write_handshake_msg(mbedtls_ssl_context *ssl); -MBEDTLS_CHECK_RETURN_CRITICAL -int mbedtls_ssl_write_record(mbedtls_ssl_context *ssl, uint8_t force_flush); -MBEDTLS_CHECK_RETURN_CRITICAL -int mbedtls_ssl_flush_output(mbedtls_ssl_context *ssl); - -MBEDTLS_CHECK_RETURN_CRITICAL -int mbedtls_ssl_parse_certificate(mbedtls_ssl_context *ssl); -MBEDTLS_CHECK_RETURN_CRITICAL -int mbedtls_ssl_write_certificate(mbedtls_ssl_context *ssl); - -MBEDTLS_CHECK_RETURN_CRITICAL -int mbedtls_ssl_parse_change_cipher_spec(mbedtls_ssl_context *ssl); -MBEDTLS_CHECK_RETURN_CRITICAL -int mbedtls_ssl_write_change_cipher_spec(mbedtls_ssl_context *ssl); - -MBEDTLS_CHECK_RETURN_CRITICAL -int mbedtls_ssl_parse_finished(mbedtls_ssl_context *ssl); -MBEDTLS_CHECK_RETURN_CRITICAL -int mbedtls_ssl_write_finished(mbedtls_ssl_context *ssl); - -void mbedtls_ssl_optimize_checksum(mbedtls_ssl_context *ssl, - const mbedtls_ssl_ciphersuite_t *ciphersuite_info); - -#if defined(MBEDTLS_KEY_EXCHANGE_SOME_PSK_ENABLED) -MBEDTLS_CHECK_RETURN_CRITICAL -int mbedtls_ssl_psk_derive_premaster(mbedtls_ssl_context *ssl, mbedtls_key_exchange_type_t key_ex); - -/** - * Get the first defined PSK by order of precedence: - * 1. handshake PSK set by \c mbedtls_ssl_set_hs_psk() in the PSK callback - * 2. static PSK configured by \c mbedtls_ssl_conf_psk() - * Return a code and update the pair (PSK, PSK length) passed to this function - */ -static inline int mbedtls_ssl_get_psk(const mbedtls_ssl_context *ssl, - const unsigned char **psk, size_t *psk_len) -{ - if (ssl->handshake->psk != NULL && ssl->handshake->psk_len > 0) { - *psk = ssl->handshake->psk; - *psk_len = ssl->handshake->psk_len; - } else if (ssl->conf->psk != NULL && ssl->conf->psk_len > 0) { - *psk = ssl->conf->psk; - *psk_len = ssl->conf->psk_len; - } else { - *psk = NULL; - *psk_len = 0; - return MBEDTLS_ERR_SSL_PRIVATE_KEY_REQUIRED; - } - - return 0; -} - -#if defined(MBEDTLS_USE_PSA_CRYPTO) -/** - * Get the first defined opaque PSK by order of precedence: - * 1. handshake PSK set by \c mbedtls_ssl_set_hs_psk_opaque() in the PSK - * callback - * 2. static PSK configured by \c mbedtls_ssl_conf_psk_opaque() - * Return an opaque PSK - */ -static inline psa_key_id_t mbedtls_ssl_get_opaque_psk( - const mbedtls_ssl_context *ssl) -{ - if (!mbedtls_svc_key_id_is_null(ssl->handshake->psk_opaque)) { - return ssl->handshake->psk_opaque; - } - - if (!mbedtls_svc_key_id_is_null(ssl->conf->psk_opaque)) { - return ssl->conf->psk_opaque; - } - - return MBEDTLS_SVC_KEY_ID_INIT; -} -#endif /* MBEDTLS_USE_PSA_CRYPTO */ - -#endif /* MBEDTLS_KEY_EXCHANGE_SOME_PSK_ENABLED */ - -#if defined(MBEDTLS_PK_C) -unsigned char mbedtls_ssl_sig_from_pk(mbedtls_pk_context *pk); -unsigned char mbedtls_ssl_sig_from_pk_alg(mbedtls_pk_type_t type); -mbedtls_pk_type_t mbedtls_ssl_pk_alg_from_sig(unsigned char sig); -#endif - -mbedtls_md_type_t mbedtls_ssl_md_alg_from_hash(unsigned char hash); -unsigned char mbedtls_ssl_hash_from_md_alg(int md); -MBEDTLS_CHECK_RETURN_CRITICAL -int mbedtls_ssl_set_calc_verify_md(mbedtls_ssl_context *ssl, int md); - -#if defined(MBEDTLS_ECP_C) -MBEDTLS_CHECK_RETURN_CRITICAL -int mbedtls_ssl_check_curve(const mbedtls_ssl_context *ssl, mbedtls_ecp_group_id grp_id); -MBEDTLS_CHECK_RETURN_CRITICAL -int mbedtls_ssl_check_curve_tls_id(const mbedtls_ssl_context *ssl, uint16_t tls_id); -#endif - -#if defined(MBEDTLS_KEY_EXCHANGE_WITH_CERT_ENABLED) -MBEDTLS_CHECK_RETURN_CRITICAL -int mbedtls_ssl_check_sig_hash(const mbedtls_ssl_context *ssl, - mbedtls_md_type_t md); -#endif - -#if defined(MBEDTLS_SSL_DTLS_SRTP) -static inline mbedtls_ssl_srtp_profile mbedtls_ssl_check_srtp_profile_value - (const uint16_t srtp_profile_value) -{ - switch (srtp_profile_value) { - case MBEDTLS_TLS_SRTP_AES128_CM_HMAC_SHA1_80: - case MBEDTLS_TLS_SRTP_AES128_CM_HMAC_SHA1_32: - case MBEDTLS_TLS_SRTP_NULL_HMAC_SHA1_80: - case MBEDTLS_TLS_SRTP_NULL_HMAC_SHA1_32: - return srtp_profile_value; - default: break; - } - return MBEDTLS_TLS_SRTP_UNSET; -} -#endif - -#if defined(MBEDTLS_X509_CRT_PARSE_C) -static inline mbedtls_pk_context *mbedtls_ssl_own_key(mbedtls_ssl_context *ssl) -{ - mbedtls_ssl_key_cert *key_cert; - - if (ssl->handshake != NULL && ssl->handshake->key_cert != NULL) { - key_cert = ssl->handshake->key_cert; - } else { - key_cert = ssl->conf->key_cert; - } - - return key_cert == NULL ? NULL : key_cert->key; -} - -static inline mbedtls_x509_crt *mbedtls_ssl_own_cert(mbedtls_ssl_context *ssl) -{ - mbedtls_ssl_key_cert *key_cert; - - if (ssl->handshake != NULL && ssl->handshake->key_cert != NULL) { - key_cert = ssl->handshake->key_cert; - } else { - key_cert = ssl->conf->key_cert; - } - - return key_cert == NULL ? NULL : key_cert->cert; -} - -/* - * Check usage of a certificate wrt extensions: - * keyUsage, extendedKeyUsage (later), and nSCertType (later). - * - * Warning: cert_endpoint is the endpoint of the cert (ie, of our peer when we - * check a cert we received from them)! - * - * Return 0 if everything is OK, -1 if not. - */ -MBEDTLS_CHECK_RETURN_CRITICAL -int mbedtls_ssl_check_cert_usage(const mbedtls_x509_crt *cert, - const mbedtls_ssl_ciphersuite_t *ciphersuite, - int cert_endpoint, - uint32_t *flags); -#endif /* MBEDTLS_X509_CRT_PARSE_C */ - -void mbedtls_ssl_write_version(int major, int minor, int transport, - unsigned char ver[2]); -void mbedtls_ssl_read_version(int *major, int *minor, int transport, - const unsigned char ver[2]); - -static inline size_t mbedtls_ssl_in_hdr_len(const mbedtls_ssl_context *ssl) -{ -#if !defined(MBEDTLS_SSL_PROTO_DTLS) - ((void) ssl); -#endif - -#if defined(MBEDTLS_SSL_PROTO_DTLS) - if (ssl->conf->transport == MBEDTLS_SSL_TRANSPORT_DATAGRAM) { - return 13; - } else -#endif /* MBEDTLS_SSL_PROTO_DTLS */ - { - return 5; - } -} - -static inline size_t mbedtls_ssl_out_hdr_len(const mbedtls_ssl_context *ssl) -{ - return (size_t) (ssl->out_iv - ssl->out_hdr); -} - -static inline size_t mbedtls_ssl_hs_hdr_len(const mbedtls_ssl_context *ssl) -{ -#if defined(MBEDTLS_SSL_PROTO_DTLS) - if (ssl->conf->transport == MBEDTLS_SSL_TRANSPORT_DATAGRAM) { - return 12; - } -#else - ((void) ssl); -#endif - return 4; -} - -#if defined(MBEDTLS_SSL_PROTO_DTLS) -void mbedtls_ssl_send_flight_completed(mbedtls_ssl_context *ssl); -void mbedtls_ssl_recv_flight_completed(mbedtls_ssl_context *ssl); -MBEDTLS_CHECK_RETURN_CRITICAL -int mbedtls_ssl_resend(mbedtls_ssl_context *ssl); -MBEDTLS_CHECK_RETURN_CRITICAL -int mbedtls_ssl_flight_transmit(mbedtls_ssl_context *ssl); -#endif - -/* Visible for testing purposes only */ -#if defined(MBEDTLS_SSL_DTLS_ANTI_REPLAY) -MBEDTLS_CHECK_RETURN_CRITICAL -int mbedtls_ssl_dtls_replay_check(mbedtls_ssl_context const *ssl); -void mbedtls_ssl_dtls_replay_update(mbedtls_ssl_context *ssl); -#endif - -MBEDTLS_CHECK_RETURN_CRITICAL -int mbedtls_ssl_session_copy(mbedtls_ssl_session *dst, - const mbedtls_ssl_session *src); - -#if defined(MBEDTLS_SSL_PROTO_SSL3) || defined(MBEDTLS_SSL_PROTO_TLS1) || \ - defined(MBEDTLS_SSL_PROTO_TLS1_1) -MBEDTLS_CHECK_RETURN_CRITICAL -int mbedtls_ssl_get_key_exchange_md_ssl_tls(mbedtls_ssl_context *ssl, - unsigned char *output, - unsigned char *data, size_t data_len); -#endif /* MBEDTLS_SSL_PROTO_SSL3 || MBEDTLS_SSL_PROTO_TLS1 || \ - MBEDTLS_SSL_PROTO_TLS1_1 */ - -#if defined(MBEDTLS_SSL_PROTO_TLS1) || defined(MBEDTLS_SSL_PROTO_TLS1_1) || \ - defined(MBEDTLS_SSL_PROTO_TLS1_2) -/* The hash buffer must have at least MBEDTLS_MD_MAX_SIZE bytes of length. */ -MBEDTLS_CHECK_RETURN_CRITICAL -int mbedtls_ssl_get_key_exchange_md_tls1_2(mbedtls_ssl_context *ssl, - unsigned char *hash, size_t *hashlen, - unsigned char *data, size_t data_len, - mbedtls_md_type_t md_alg); -#endif /* MBEDTLS_SSL_PROTO_TLS1 || MBEDTLS_SSL_PROTO_TLS1_1 || \ - MBEDTLS_SSL_PROTO_TLS1_2 */ - -#ifdef __cplusplus -} -#endif - -void mbedtls_ssl_transform_init(mbedtls_ssl_transform *transform); -MBEDTLS_CHECK_RETURN_CRITICAL -int mbedtls_ssl_encrypt_buf(mbedtls_ssl_context *ssl, - mbedtls_ssl_transform *transform, - mbedtls_record *rec, - int (*f_rng)(void *, unsigned char *, size_t), - void *p_rng); -MBEDTLS_CHECK_RETURN_CRITICAL -int mbedtls_ssl_decrypt_buf(mbedtls_ssl_context const *ssl, - mbedtls_ssl_transform *transform, - mbedtls_record *rec); - -/* Length of the "epoch" field in the record header */ -static inline size_t mbedtls_ssl_ep_len(const mbedtls_ssl_context *ssl) -{ -#if defined(MBEDTLS_SSL_PROTO_DTLS) - if (ssl->conf->transport == MBEDTLS_SSL_TRANSPORT_DATAGRAM) { - return 2; - } -#else - ((void) ssl); -#endif - return 0; -} - -#if defined(MBEDTLS_SSL_PROTO_DTLS) -MBEDTLS_CHECK_RETURN_CRITICAL -int mbedtls_ssl_resend_hello_request(mbedtls_ssl_context *ssl); -#endif /* MBEDTLS_SSL_PROTO_DTLS */ - -void mbedtls_ssl_set_timer(mbedtls_ssl_context *ssl, uint32_t millisecs); -MBEDTLS_CHECK_RETURN_CRITICAL -int mbedtls_ssl_check_timer(mbedtls_ssl_context *ssl); - -void mbedtls_ssl_reset_in_out_pointers(mbedtls_ssl_context *ssl); -void mbedtls_ssl_update_out_pointers(mbedtls_ssl_context *ssl, - mbedtls_ssl_transform *transform); -void mbedtls_ssl_update_in_pointers(mbedtls_ssl_context *ssl); - -MBEDTLS_CHECK_RETURN_CRITICAL -int mbedtls_ssl_session_reset_int(mbedtls_ssl_context *ssl, int partial); - -#if defined(MBEDTLS_SSL_DTLS_ANTI_REPLAY) -void mbedtls_ssl_dtls_replay_reset(mbedtls_ssl_context *ssl); -#endif - -void mbedtls_ssl_handshake_wrapup_free_hs_transform(mbedtls_ssl_context *ssl); - -#if defined(MBEDTLS_SSL_RENEGOTIATION) -MBEDTLS_CHECK_RETURN_CRITICAL -int mbedtls_ssl_start_renegotiation(mbedtls_ssl_context *ssl); -#endif /* MBEDTLS_SSL_RENEGOTIATION */ - -#if defined(MBEDTLS_SSL_PROTO_DTLS) -size_t mbedtls_ssl_get_current_mtu(const mbedtls_ssl_context *ssl); -void mbedtls_ssl_buffering_free(mbedtls_ssl_context *ssl); -void mbedtls_ssl_flight_free(mbedtls_ssl_flight_item *flight); -#endif /* MBEDTLS_SSL_PROTO_DTLS */ - -#if defined(MBEDTLS_TEST_HOOKS) -int mbedtls_ssl_check_dtls_clihlo_cookie( - mbedtls_ssl_context *ssl, - const unsigned char *cli_id, size_t cli_id_len, - const unsigned char *in, size_t in_len, - unsigned char *obuf, size_t buf_len, size_t *olen); -#endif - -#endif /* ssl_internal.h */ diff --git a/vendor/mbedtls/include/mbedtls/ssl_ticket.h b/vendor/mbedtls/include/mbedtls/ssl_ticket.h index 401df7c854..2ee1400210 100644 --- a/vendor/mbedtls/include/mbedtls/ssl_ticket.h +++ b/vendor/mbedtls/include/mbedtls/ssl_ticket.h @@ -5,28 +5,13 @@ */ /* * Copyright The Mbed TLS Contributors - * SPDX-License-Identifier: Apache-2.0 - * - * Licensed under the Apache License, Version 2.0 (the "License"); you may - * not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT - * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. + * SPDX-License-Identifier: Apache-2.0 OR GPL-2.0-or-later */ #ifndef MBEDTLS_SSL_TICKET_H #define MBEDTLS_SSL_TICKET_H +#include "mbedtls/private_access.h" -#if !defined(MBEDTLS_CONFIG_FILE) -#include "mbedtls/config.h" -#else -#include MBEDTLS_CONFIG_FILE -#endif +#include "mbedtls/build_info.h" /* * This implementation of the session ticket callbacks includes key @@ -37,6 +22,14 @@ #include "mbedtls/ssl.h" #include "mbedtls/cipher.h" +#if defined(MBEDTLS_HAVE_TIME) +#include "mbedtls/platform_time.h" +#endif + +#if defined(MBEDTLS_USE_PSA_CRYPTO) +#include "psa/crypto.h" +#endif + #if defined(MBEDTLS_THREADING_C) #include "mbedtls/threading.h" #endif @@ -45,13 +38,30 @@ extern "C" { #endif +#define MBEDTLS_SSL_TICKET_MAX_KEY_BYTES 32 /*!< Max supported key length in bytes */ +#define MBEDTLS_SSL_TICKET_KEY_NAME_BYTES 4 /*!< key name length in bytes */ + /** * \brief Information for session ticket protection */ typedef struct mbedtls_ssl_ticket_key { - unsigned char name[4]; /*!< random key identifier */ - uint32_t generation_time; /*!< key generation timestamp (seconds) */ - mbedtls_cipher_context_t ctx; /*!< context for auth enc/decryption */ + unsigned char MBEDTLS_PRIVATE(name)[MBEDTLS_SSL_TICKET_KEY_NAME_BYTES]; + /*!< random key identifier */ +#if defined(MBEDTLS_HAVE_TIME) + mbedtls_time_t MBEDTLS_PRIVATE(generation_time); /*!< key generation timestamp (seconds) */ +#endif + /*! Lifetime of the key in seconds. This is also the lifetime of the + * tickets created under that key. + */ + uint32_t MBEDTLS_PRIVATE(lifetime); +#if !defined(MBEDTLS_USE_PSA_CRYPTO) + mbedtls_cipher_context_t MBEDTLS_PRIVATE(ctx); /*!< context for auth enc/decryption */ +#else + mbedtls_svc_key_id_t MBEDTLS_PRIVATE(key); /*!< key used for auth enc/decryption */ + psa_algorithm_t MBEDTLS_PRIVATE(alg); /*!< algorithm of auth enc/decryption */ + psa_key_type_t MBEDTLS_PRIVATE(key_type); /*!< key type */ + size_t MBEDTLS_PRIVATE(key_bits); /*!< key length in bits */ +#endif } mbedtls_ssl_ticket_key; @@ -59,17 +69,17 @@ mbedtls_ssl_ticket_key; * \brief Context for session ticket handling functions */ typedef struct mbedtls_ssl_ticket_context { - mbedtls_ssl_ticket_key keys[2]; /*!< ticket protection keys */ - unsigned char active; /*!< index of the currently active key */ + mbedtls_ssl_ticket_key MBEDTLS_PRIVATE(keys)[2]; /*!< ticket protection keys */ + unsigned char MBEDTLS_PRIVATE(active); /*!< index of the currently active key */ - uint32_t ticket_lifetime; /*!< lifetime of tickets in seconds */ + uint32_t MBEDTLS_PRIVATE(ticket_lifetime); /*!< lifetime of tickets in seconds */ /** Callback for getting (pseudo-)random numbers */ - int (*f_rng)(void *, unsigned char *, size_t); - void *p_rng; /*!< context for the RNG function */ + int(*MBEDTLS_PRIVATE(f_rng))(void *, unsigned char *, size_t); + void *MBEDTLS_PRIVATE(p_rng); /*!< context for the RNG function */ #if defined(MBEDTLS_THREADING_C) - mbedtls_threading_mutex_t mutex; + mbedtls_threading_mutex_t MBEDTLS_PRIVATE(mutex); #endif } mbedtls_ssl_ticket_context; @@ -87,7 +97,7 @@ void mbedtls_ssl_ticket_init(mbedtls_ssl_ticket_context *ctx); * \brief Prepare context to be actually used * * \param ctx Context to be set up - * \param f_rng RNG callback function + * \param f_rng RNG callback function (mandatory) * \param p_rng RNG callback context * \param cipher AEAD cipher to use for ticket protection. * Recommended value: MBEDTLS_CIPHER_AES_256_GCM. @@ -98,10 +108,16 @@ void mbedtls_ssl_ticket_init(mbedtls_ssl_ticket_context *ctx); * least as strong as the strongest ciphersuite * supported. Usually that means a 256-bit key. * - * \note The lifetime of the keys is twice the lifetime of tickets. - * It is recommended to pick a reasonable lifetime so as not + * \note It is recommended to pick a reasonable lifetime so as not * to negate the benefits of forward secrecy. * + * \note The TLS 1.3 specification states that ticket lifetime must + * be smaller than seven days. If ticket lifetime has been + * set to a value greater than seven days in this module then + * if the TLS 1.3 is configured to send tickets after the + * handshake it will fail the connection when trying to send + * the first ticket. + * * \return 0 if successful, * or a specific MBEDTLS_ERR_XXX error code */ @@ -110,6 +126,49 @@ int mbedtls_ssl_ticket_setup(mbedtls_ssl_ticket_context *ctx, mbedtls_cipher_type_t cipher, uint32_t lifetime); +/** + * \brief Rotate session ticket encryption key to new specified key. + * Provides for external control of session ticket encryption + * key rotation, e.g. for synchronization between different + * machines. If this function is not used, or if not called + * before ticket lifetime expires, then a new session ticket + * encryption key is generated internally in order to avoid + * unbounded session ticket encryption key lifetimes. + * + * \param ctx Context to be set up + * \param name Session ticket encryption key name + * \param nlength Session ticket encryption key name length in bytes + * \param k Session ticket encryption key + * \param klength Session ticket encryption key length in bytes + * \param lifetime Tickets lifetime in seconds + * Recommended value: 86400 (one day). + * + * \note \c name and \c k are recommended to be cryptographically + * random data. + * + * \note \c nlength must match sizeof( ctx->name ) + * + * \note \c klength must be sufficient for use by cipher specified + * to \c mbedtls_ssl_ticket_setup + * + * \note It is recommended to pick a reasonable lifetime so as not + * to negate the benefits of forward secrecy. + * + * \note The TLS 1.3 specification states that ticket lifetime must + * be smaller than seven days. If ticket lifetime has been + * set to a value greater than seven days in this module then + * if the TLS 1.3 is configured to send tickets after the + * handshake it will fail the connection when trying to send + * the first ticket. + * + * \return 0 if successful, + * or a specific MBEDTLS_ERR_XXX error code + */ +int mbedtls_ssl_ticket_rotate(mbedtls_ssl_ticket_context *ctx, + const unsigned char *name, size_t nlength, + const unsigned char *k, size_t klength, + uint32_t lifetime); + /** * \brief Implementation of the ticket write callback * diff --git a/vendor/mbedtls/include/mbedtls/threading.h b/vendor/mbedtls/include/mbedtls/threading.h index 5b5efca620..d50d04ead1 100644 --- a/vendor/mbedtls/include/mbedtls/threading.h +++ b/vendor/mbedtls/include/mbedtls/threading.h @@ -5,28 +5,13 @@ */ /* * Copyright The Mbed TLS Contributors - * SPDX-License-Identifier: Apache-2.0 - * - * Licensed under the Apache License, Version 2.0 (the "License"); you may - * not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT - * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. + * SPDX-License-Identifier: Apache-2.0 OR GPL-2.0-or-later */ #ifndef MBEDTLS_THREADING_H #define MBEDTLS_THREADING_H +#include "mbedtls/private_access.h" -#if !defined(MBEDTLS_CONFIG_FILE) -#include "mbedtls/config.h" -#else -#include MBEDTLS_CONFIG_FILE -#endif +#include "mbedtls/build_info.h" #include @@ -34,11 +19,6 @@ extern "C" { #endif -/* MBEDTLS_ERR_THREADING_FEATURE_UNAVAILABLE is deprecated and should not be - * used. */ -/** The selected feature is not available. */ -#define MBEDTLS_ERR_THREADING_FEATURE_UNAVAILABLE -0x001A - /** Bad input parameters to function. */ #define MBEDTLS_ERR_THREADING_BAD_INPUT_DATA -0x001C /** Locking / unlocking / free failed with error code. */ @@ -47,11 +27,15 @@ extern "C" { #if defined(MBEDTLS_THREADING_PTHREAD) #include typedef struct mbedtls_threading_mutex_t { - pthread_mutex_t mutex; - /* is_valid is 0 after a failed init or a free, and nonzero after a - * successful init. This field is not considered part of the public - * API of Mbed TLS and may change without notice. */ - char is_valid; + pthread_mutex_t MBEDTLS_PRIVATE(mutex); + + /* WARNING - state should only be accessed when holding the mutex lock in + * tests/src/threading_helpers.c, otherwise corruption can occur. + * state will be 0 after a failed init or a free, and nonzero after a + * successful init. This field is for testing only and thus not considered + * part of the public API of Mbed TLS and may change without notice.*/ + char MBEDTLS_PRIVATE(state); + } mbedtls_threading_mutex_t; #endif @@ -116,6 +100,34 @@ extern mbedtls_threading_mutex_t mbedtls_threading_readdir_mutex; extern mbedtls_threading_mutex_t mbedtls_threading_gmtime_mutex; #endif /* MBEDTLS_HAVE_TIME_DATE && !MBEDTLS_PLATFORM_GMTIME_R_ALT */ +#if defined(MBEDTLS_PSA_CRYPTO_C) +/* + * A mutex used to make the PSA subsystem thread safe. + * + * key_slot_mutex protects the registered_readers and + * state variable for all key slots in &global_data.key_slots. + * + * This mutex must be held when any read from or write to a state or + * registered_readers field is performed, i.e. when calling functions: + * psa_key_slot_state_transition(), psa_register_read(), psa_unregister_read(), + * psa_key_slot_has_readers() and psa_wipe_key_slot(). */ +extern mbedtls_threading_mutex_t mbedtls_threading_key_slot_mutex; + +/* + * A mutex used to make the non-rng PSA global_data struct members thread safe. + * + * This mutex must be held when reading or writing to any of the PSA global_data + * structure members, other than the rng_state or rng struct. */ +extern mbedtls_threading_mutex_t mbedtls_threading_psa_globaldata_mutex; + +/* + * A mutex used to make the PSA global_data rng data thread safe. + * + * This mutex must be held when reading or writing to the PSA + * global_data rng_state or rng struct members. */ +extern mbedtls_threading_mutex_t mbedtls_threading_psa_rngdata_mutex; +#endif + #endif /* MBEDTLS_THREADING_C */ #ifdef __cplusplus diff --git a/vendor/mbedtls/include/mbedtls/timing.h b/vendor/mbedtls/include/mbedtls/timing.h index 597ef75211..62ae1022d9 100644 --- a/vendor/mbedtls/include/mbedtls/timing.h +++ b/vendor/mbedtls/include/mbedtls/timing.h @@ -5,28 +5,13 @@ */ /* * Copyright The Mbed TLS Contributors - * SPDX-License-Identifier: Apache-2.0 - * - * Licensed under the Apache License, Version 2.0 (the "License"); you may - * not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT - * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. + * SPDX-License-Identifier: Apache-2.0 OR GPL-2.0-or-later */ #ifndef MBEDTLS_TIMING_H #define MBEDTLS_TIMING_H +#include "mbedtls/private_access.h" -#if !defined(MBEDTLS_CONFIG_FILE) -#include "mbedtls/config.h" -#else -#include MBEDTLS_CONFIG_FILE -#endif +#include "mbedtls/build_info.h" #include @@ -42,67 +27,25 @@ extern "C" { * \brief timer structure */ struct mbedtls_timing_hr_time { - unsigned char opaque[32]; + uint64_t MBEDTLS_PRIVATE(opaque)[4]; }; /** * \brief Context for mbedtls_timing_set/get_delay() */ typedef struct mbedtls_timing_delay_context { - struct mbedtls_timing_hr_time timer; - uint32_t int_ms; - uint32_t fin_ms; + struct mbedtls_timing_hr_time MBEDTLS_PRIVATE(timer); + uint32_t MBEDTLS_PRIVATE(int_ms); + uint32_t MBEDTLS_PRIVATE(fin_ms); } mbedtls_timing_delay_context; #else /* MBEDTLS_TIMING_ALT */ #include "timing_alt.h" #endif /* MBEDTLS_TIMING_ALT */ -extern volatile int mbedtls_timing_alarmed; - -/** - * \brief Return the CPU cycle counter value - * - * \warning This is only a best effort! Do not rely on this! - * In particular, it is known to be unreliable on virtual - * machines. - * - * \note This value starts at an unspecified origin and - * may wrap around. - */ -unsigned long mbedtls_timing_hardclock(void); - -/** - * \brief Return the elapsed time in milliseconds - * - * \param val points to a timer structure - * \param reset If 0, query the elapsed time. Otherwise (re)start the timer. - * - * \return Elapsed time since the previous reset in ms. When - * restarting, this is always 0. - * - * \note To initialize a timer, call this function with reset=1. - * - * Determining the elapsed time and resetting the timer is not - * atomic on all platforms, so after the sequence - * `{ get_timer(1); ...; time1 = get_timer(1); ...; time2 = - * get_timer(0) }` the value time1+time2 is only approximately - * the delay since the first reset. - */ +/* Internal use */ unsigned long mbedtls_timing_get_timer(struct mbedtls_timing_hr_time *val, int reset); -/** - * \brief Setup an alarm clock - * - * \param seconds delay before the "mbedtls_timing_alarmed" flag is set - * (must be >=0) - * - * \warning Only one alarm at a time is supported. In a threaded - * context, this means one for the whole process, not one per - * thread. - */ -void mbedtls_set_alarm(int seconds); - /** * \brief Set a pair of delays to watch * (See \c mbedtls_timing_get_delay().) @@ -133,14 +76,16 @@ void mbedtls_timing_set_delay(void *data, uint32_t int_ms, uint32_t fin_ms); */ int mbedtls_timing_get_delay(void *data); -#if defined(MBEDTLS_SELF_TEST) /** - * \brief Checkup routine + * \brief Get the final timing delay + * + * \param data Pointer to timing data + * Must point to a valid \c mbedtls_timing_delay_context struct. * - * \return 0 if successful, or 1 if a test failed + * \return Final timing delay in milliseconds. */ -int mbedtls_timing_self_test(int verbose); -#endif +uint32_t mbedtls_timing_get_final_delay( + const mbedtls_timing_delay_context *data); #ifdef __cplusplus } diff --git a/vendor/mbedtls/include/mbedtls/version.h b/vendor/mbedtls/include/mbedtls/version.h index 4fe37c2224..637f9d38bf 100644 --- a/vendor/mbedtls/include/mbedtls/version.h +++ b/vendor/mbedtls/include/mbedtls/version.h @@ -5,49 +5,17 @@ */ /* * Copyright The Mbed TLS Contributors - * SPDX-License-Identifier: Apache-2.0 - * - * Licensed under the Apache License, Version 2.0 (the "License"); you may - * not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT - * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. + * SPDX-License-Identifier: Apache-2.0 OR GPL-2.0-or-later */ /* - * This set of compile-time defines and run-time variables can be used to - * determine the version number of the Mbed TLS library used. + * This set of run-time variables can be used to determine the version number of + * the Mbed TLS library used. Compile-time version defines for the same can be + * found in build_info.h */ #ifndef MBEDTLS_VERSION_H #define MBEDTLS_VERSION_H -#if !defined(MBEDTLS_CONFIG_FILE) -#include "mbedtls/config.h" -#else -#include MBEDTLS_CONFIG_FILE -#endif - -/** - * The version number x.y.z is split into three parts. - * Major, Minor, Patchlevel - */ -#define MBEDTLS_VERSION_MAJOR 2 -#define MBEDTLS_VERSION_MINOR 28 -#define MBEDTLS_VERSION_PATCH 5 - -/** - * The single version number has the following structure: - * MMNNPP00 - * Major version | Minor version | Patch version - */ -#define MBEDTLS_VERSION_NUMBER 0x021C0500 -#define MBEDTLS_VERSION_STRING "2.28.5" -#define MBEDTLS_VERSION_STRING_FULL "Mbed TLS 2.28.5" +#include "mbedtls/build_info.h" #if defined(MBEDTLS_VERSION_C) @@ -90,7 +58,7 @@ void mbedtls_version_get_string_full(char *string); * * \note only checks against defines in the sections "System * support", "Mbed TLS modules" and "Mbed TLS feature - * support" in config.h + * support" in mbedtls_config.h * * \param feature The string for the define to check (e.g. "MBEDTLS_AES_C") * diff --git a/vendor/mbedtls/include/mbedtls/x509.h b/vendor/mbedtls/include/mbedtls/x509.h index f00f3a6679..453f598c74 100644 --- a/vendor/mbedtls/include/mbedtls/x509.h +++ b/vendor/mbedtls/include/mbedtls/x509.h @@ -5,28 +5,13 @@ */ /* * Copyright The Mbed TLS Contributors - * SPDX-License-Identifier: Apache-2.0 - * - * Licensed under the Apache License, Version 2.0 (the "License"); you may - * not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT - * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. + * SPDX-License-Identifier: Apache-2.0 OR GPL-2.0-or-later */ #ifndef MBEDTLS_X509_H #define MBEDTLS_X509_H +#include "mbedtls/private_access.h" -#if !defined(MBEDTLS_CONFIG_FILE) -#include "mbedtls/config.h" -#else -#include MBEDTLS_CONFIG_FILE -#endif +#include "mbedtls/build_info.h" #include "mbedtls/asn1.h" #include "mbedtls/pk.h" @@ -151,7 +136,7 @@ /* * X.509 v3 Key Usage Extension flags - * Reminder: update x509_info_key_usage() when adding new flags. + * Reminder: update mbedtls_x509_info_key_usage() when adding new flags. */ #define MBEDTLS_X509_KU_DIGITAL_SIGNATURE (0x80) /* bit 0 */ #define MBEDTLS_X509_KU_NON_REPUDIATION (0x40) /* bit 1 */ @@ -246,6 +231,17 @@ typedef mbedtls_asn1_named_data mbedtls_x509_name; */ typedef mbedtls_asn1_sequence mbedtls_x509_sequence; +/* + * Container for the fields of the Authority Key Identifier object + */ +typedef struct mbedtls_x509_authority { + mbedtls_x509_buf keyIdentifier; + mbedtls_x509_sequence authorityCertIssuer; + mbedtls_x509_buf authorityCertSerialNumber; + mbedtls_x509_buf raw; +} +mbedtls_x509_authority; + /** Container for date and time (precision in seconds). */ typedef struct mbedtls_x509_time { int year, mon, day; /**< Date. */ @@ -253,7 +249,65 @@ typedef struct mbedtls_x509_time { } mbedtls_x509_time; +/** + * From RFC 5280 section 4.2.1.6: + * OtherName ::= SEQUENCE { + * type-id OBJECT IDENTIFIER, + * value [0] EXPLICIT ANY DEFINED BY type-id } + * + * Future versions of the library may add new fields to this structure or + * to its embedded union and structure. + */ +typedef struct mbedtls_x509_san_other_name { + /** + * The type_id is an OID as defined in RFC 5280. + * To check the value of the type id, you should use + * \p MBEDTLS_OID_CMP with a known OID mbedtls_x509_buf. + */ + mbedtls_x509_buf type_id; /**< The type id. */ + union { + /** + * From RFC 4108 section 5: + * HardwareModuleName ::= SEQUENCE { + * hwType OBJECT IDENTIFIER, + * hwSerialNum OCTET STRING } + */ + struct { + mbedtls_x509_buf oid; /**< The object identifier. */ + mbedtls_x509_buf val; /**< The named value. */ + } + hardware_module_name; + } + value; +} +mbedtls_x509_san_other_name; + +/** + * A structure for holding the parsed Subject Alternative Name, + * according to type. + * + * Future versions of the library may add new fields to this structure or + * to its embedded union and structure. + */ +typedef struct mbedtls_x509_subject_alternative_name { + int type; /**< The SAN type, value of MBEDTLS_X509_SAN_XXX. */ + union { + mbedtls_x509_san_other_name other_name; + mbedtls_x509_name directory_name; + mbedtls_x509_buf unstructured_name; /**< The buffer for the unstructured types. rfc822Name, dnsName and uniformResourceIdentifier are currently supported. */ + } + san; /**< A union of the supported SAN types */ +} +mbedtls_x509_subject_alternative_name; + +typedef struct mbedtls_x509_san_list { + mbedtls_x509_subject_alternative_name node; + struct mbedtls_x509_san_list *next; +} +mbedtls_x509_san_list; + /** \} name Structures for parsing X.509 certificates, CRLs and CSRs */ +/** \} addtogroup x509_module */ /** * \brief Store the certificate DN in printable form into buf; @@ -268,6 +322,43 @@ mbedtls_x509_time; */ int mbedtls_x509_dn_gets(char *buf, size_t size, const mbedtls_x509_name *dn); +/** + * \brief Convert the certificate DN string \p name into + * a linked list of mbedtls_x509_name (equivalent to + * mbedtls_asn1_named_data). + * + * \note This function allocates a linked list, and places the head + * pointer in \p head. This list must later be freed by a + * call to mbedtls_asn1_free_named_data_list(). + * + * \param[out] head Address in which to store the pointer to the head of the + * allocated list of mbedtls_x509_name + * \param[in] name The string representation of a DN to convert + * + * \return 0 on success, or a negative error code. + */ +int mbedtls_x509_string_to_names(mbedtls_asn1_named_data **head, const char *name); + +/** + * \brief Return the next relative DN in an X509 name. + * + * \note Intended use is to compare function result to dn->next + * in order to detect boundaries of multi-valued RDNs. + * + * \param dn Current node in the X509 name + * + * \return Pointer to the first attribute-value pair of the + * next RDN in sequence, or NULL if end is reached. + */ +static inline mbedtls_x509_name *mbedtls_x509_dn_get_next( + mbedtls_x509_name *dn) +{ + while (dn->MBEDTLS_PRIVATE(next_merged) && dn->next != NULL) { + dn = dn->next; + } + return dn->next; +} + /** * \brief Store the certificate serial in printable form into buf; * no more than size characters will be written. @@ -281,6 +372,31 @@ int mbedtls_x509_dn_gets(char *buf, size_t size, const mbedtls_x509_name *dn); */ int mbedtls_x509_serial_gets(char *buf, size_t size, const mbedtls_x509_buf *serial); +/** + * \brief Compare pair of mbedtls_x509_time. + * + * \param t1 mbedtls_x509_time to compare + * \param t2 mbedtls_x509_time to compare + * + * \return < 0 if t1 is before t2 + * 0 if t1 equals t2 + * > 0 if t1 is after t2 + */ +int mbedtls_x509_time_cmp(const mbedtls_x509_time *t1, const mbedtls_x509_time *t2); + +#if defined(MBEDTLS_HAVE_TIME_DATE) +/** + * \brief Fill mbedtls_x509_time with provided mbedtls_time_t. + * + * \param tt mbedtls_time_t to convert + * \param now mbedtls_x509_time to fill with converted mbedtls_time_t + * + * \return \c 0 on success + * \return A non-zero return value on failure. + */ +int mbedtls_x509_time_gmtime(mbedtls_time_t tt, mbedtls_x509_time *now); +#endif /* MBEDTLS_HAVE_TIME_DATE */ + /** * \brief Check a given mbedtls_x509_time against the system time * and tell if it's in the past. @@ -309,60 +425,63 @@ int mbedtls_x509_time_is_past(const mbedtls_x509_time *to); */ int mbedtls_x509_time_is_future(const mbedtls_x509_time *from); -/** \} addtogroup x509_module */ - -#if defined(MBEDTLS_SELF_TEST) - /** - * \brief Checkup routine + * \brief This function parses an item in the SubjectAlternativeNames + * extension. Please note that this function might allocate + * additional memory for a subject alternative name, thus + * mbedtls_x509_free_subject_alt_name has to be called + * to dispose of this additional memory afterwards. * - * \return 0 if successful, or 1 if the test failed + * \param san_buf The buffer holding the raw data item of the subject + * alternative name. + * \param san The target structure to populate with the parsed presentation + * of the subject alternative name encoded in \p san_buf. + * + * \note Supported GeneralName types, as defined in RFC 5280: + * "rfc822Name", "dnsName", "directoryName", + * "uniformResourceIdentifier" and "hardware_module_name" + * of type "otherName", as defined in RFC 4108. + * + * \note This function should be called on a single raw data of + * subject alternative name. For example, after successful + * certificate parsing, one must iterate on every item in the + * \c crt->subject_alt_names sequence, and pass it to + * this function. + * + * \warning The target structure contains pointers to the raw data of the + * parsed certificate, and its lifetime is restricted by the + * lifetime of the certificate. + * + * \return \c 0 on success + * \return #MBEDTLS_ERR_X509_FEATURE_UNAVAILABLE for an unsupported + * SAN type. + * \return Another negative value for any other failure. */ -int mbedtls_x509_self_test(int verbose); - -#endif /* MBEDTLS_SELF_TEST */ +int mbedtls_x509_parse_subject_alt_name(const mbedtls_x509_buf *san_buf, + mbedtls_x509_subject_alternative_name *san); +/** + * \brief Unallocate all data related to subject alternative name + * + * \param san SAN structure - extra memory owned by this structure will be freed + */ +void mbedtls_x509_free_subject_alt_name(mbedtls_x509_subject_alternative_name *san); -/* - * Internal module functions. You probably do not want to use these unless you - * know you do. +/** + * \brief This function parses a CN string as an IP address. + * + * \param cn The CN string to parse. CN string MUST be null-terminated. + * \param dst The target buffer to populate with the binary IP address. + * The buffer MUST be 16 bytes to save IPv6, and should be + * 4-byte aligned if the result will be used as struct in_addr. + * e.g. uint32_t dst[4] + * + * \note \p cn is parsed as an IPv6 address if string contains ':', + * else \p cn is parsed as an IPv4 address. + * + * \return Length of binary IP address; num bytes written to target. + * \return \c 0 on failure to parse CN string as an IP address. */ -int mbedtls_x509_get_name(unsigned char **p, const unsigned char *end, - mbedtls_x509_name *cur); -int mbedtls_x509_get_alg_null(unsigned char **p, const unsigned char *end, - mbedtls_x509_buf *alg); -int mbedtls_x509_get_alg(unsigned char **p, const unsigned char *end, - mbedtls_x509_buf *alg, mbedtls_x509_buf *params); -#if defined(MBEDTLS_X509_RSASSA_PSS_SUPPORT) -int mbedtls_x509_get_rsassa_pss_params(const mbedtls_x509_buf *params, - mbedtls_md_type_t *md_alg, mbedtls_md_type_t *mgf_md, - int *salt_len); -#endif -int mbedtls_x509_get_sig(unsigned char **p, const unsigned char *end, mbedtls_x509_buf *sig); -int mbedtls_x509_get_sig_alg(const mbedtls_x509_buf *sig_oid, const mbedtls_x509_buf *sig_params, - mbedtls_md_type_t *md_alg, mbedtls_pk_type_t *pk_alg, - void **sig_opts); -int mbedtls_x509_get_time(unsigned char **p, const unsigned char *end, - mbedtls_x509_time *t); -int mbedtls_x509_get_serial(unsigned char **p, const unsigned char *end, - mbedtls_x509_buf *serial); -int mbedtls_x509_get_ext(unsigned char **p, const unsigned char *end, - mbedtls_x509_buf *ext, int tag); -int mbedtls_x509_sig_alg_gets(char *buf, size_t size, const mbedtls_x509_buf *sig_oid, - mbedtls_pk_type_t pk_alg, mbedtls_md_type_t md_alg, - const void *sig_opts); -int mbedtls_x509_key_size_helper(char *buf, size_t buf_size, const char *name); -int mbedtls_x509_string_to_names(mbedtls_asn1_named_data **head, const char *name); -int mbedtls_x509_set_extension(mbedtls_asn1_named_data **head, const char *oid, size_t oid_len, - int critical, const unsigned char *val, - size_t val_len); -int mbedtls_x509_write_extensions(unsigned char **p, unsigned char *start, - mbedtls_asn1_named_data *first); -int mbedtls_x509_write_names(unsigned char **p, unsigned char *start, - mbedtls_asn1_named_data *first); -int mbedtls_x509_write_sig(unsigned char **p, unsigned char *start, - const char *oid, size_t oid_len, - unsigned char *sig, size_t size, - mbedtls_pk_type_t pk_alg); +size_t mbedtls_x509_crt_parse_cn_inet_pton(const char *cn, void *dst); #define MBEDTLS_X509_SAFE_SNPRINTF \ do { \ @@ -377,4 +496,4 @@ int mbedtls_x509_write_sig(unsigned char **p, unsigned char *start, } #endif -#endif /* x509.h */ +#endif /* MBEDTLS_X509_H */ diff --git a/vendor/mbedtls/include/mbedtls/x509_crl.h b/vendor/mbedtls/include/mbedtls/x509_crl.h index 1405021407..6625a44f46 100644 --- a/vendor/mbedtls/include/mbedtls/x509_crl.h +++ b/vendor/mbedtls/include/mbedtls/x509_crl.h @@ -5,28 +5,13 @@ */ /* * Copyright The Mbed TLS Contributors - * SPDX-License-Identifier: Apache-2.0 - * - * Licensed under the Apache License, Version 2.0 (the "License"); you may - * not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT - * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. + * SPDX-License-Identifier: Apache-2.0 OR GPL-2.0-or-later */ #ifndef MBEDTLS_X509_CRL_H #define MBEDTLS_X509_CRL_H +#include "mbedtls/private_access.h" -#if !defined(MBEDTLS_CONFIG_FILE) -#include "mbedtls/config.h" -#else -#include MBEDTLS_CONFIG_FILE -#endif +#include "mbedtls/build_info.h" #include "mbedtls/x509.h" @@ -46,16 +31,28 @@ extern "C" { /** * Certificate revocation list entry. * Contains the CA-specific serial numbers and revocation dates. + * + * Some fields of this structure are publicly readable. Do not modify + * them except via Mbed TLS library functions: the effect of modifying + * those fields or the data that those fields points to is unspecified. */ typedef struct mbedtls_x509_crl_entry { + /** Direct access to the whole entry inside the containing buffer. */ mbedtls_x509_buf raw; - + /** The serial number of the revoked certificate. */ mbedtls_x509_buf serial; - + /** The revocation date of this entry. */ mbedtls_x509_time revocation_date; - + /** Direct access to the list of CRL entry extensions + * (an ASN.1 constructed sequence). + * + * If there are no extensions, `entry_ext.len == 0` and + * `entry_ext.p == NULL`. */ mbedtls_x509_buf entry_ext; + /** Next element in the linked list of entries. + * \p NULL indicates the end of the list. + * Do not modify this field directly. */ struct mbedtls_x509_crl_entry *next; } mbedtls_x509_crl_entry; @@ -82,12 +79,15 @@ typedef struct mbedtls_x509_crl { mbedtls_x509_buf crl_ext; - mbedtls_x509_buf sig_oid2; - mbedtls_x509_buf sig; - mbedtls_md_type_t sig_md; /**< Internal representation of the MD algorithm of the signature algorithm, e.g. MBEDTLS_MD_SHA256 */ - mbedtls_pk_type_t sig_pk; /**< Internal representation of the Public Key algorithm of the signature algorithm, e.g. MBEDTLS_PK_RSA */ - void *sig_opts; /**< Signature options to be passed to mbedtls_pk_verify_ext(), e.g. for RSASSA-PSS */ + mbedtls_x509_buf MBEDTLS_PRIVATE(sig_oid2); + mbedtls_x509_buf MBEDTLS_PRIVATE(sig); + mbedtls_md_type_t MBEDTLS_PRIVATE(sig_md); /**< Internal representation of the MD algorithm of the signature algorithm, e.g. MBEDTLS_MD_SHA256 */ + mbedtls_pk_type_t MBEDTLS_PRIVATE(sig_pk); /**< Internal representation of the Public Key algorithm of the signature algorithm, e.g. MBEDTLS_PK_RSA */ + void *MBEDTLS_PRIVATE(sig_opts); /**< Signature options to be passed to mbedtls_pk_verify_ext(), e.g. for RSASSA-PSS */ + /** Next element in the linked list of CRL. + * \p NULL indicates the end of the list. + * Do not modify this field directly. */ struct mbedtls_x509_crl *next; } mbedtls_x509_crl; @@ -144,6 +144,7 @@ int mbedtls_x509_crl_parse(mbedtls_x509_crl *chain, const unsigned char *buf, si int mbedtls_x509_crl_parse_file(mbedtls_x509_crl *chain, const char *path); #endif /* MBEDTLS_FS_IO */ +#if !defined(MBEDTLS_X509_REMOVE_INFO) /** * \brief Returns an informational string about the CRL. * @@ -157,6 +158,7 @@ int mbedtls_x509_crl_parse_file(mbedtls_x509_crl *chain, const char *path); */ int mbedtls_x509_crl_info(char *buf, size_t size, const char *prefix, const mbedtls_x509_crl *crl); +#endif /* !MBEDTLS_X509_REMOVE_INFO */ /** * \brief Initialize a CRL (chain) diff --git a/vendor/mbedtls/include/mbedtls/x509_crt.h b/vendor/mbedtls/include/mbedtls/x509_crt.h index bf883e8e96..1ce0d23619 100644 --- a/vendor/mbedtls/include/mbedtls/x509_crt.h +++ b/vendor/mbedtls/include/mbedtls/x509_crt.h @@ -5,28 +5,13 @@ */ /* * Copyright The Mbed TLS Contributors - * SPDX-License-Identifier: Apache-2.0 - * - * Licensed under the Apache License, Version 2.0 (the "License"); you may - * not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT - * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. + * SPDX-License-Identifier: Apache-2.0 OR GPL-2.0-or-later */ #ifndef MBEDTLS_X509_CRT_H #define MBEDTLS_X509_CRT_H +#include "mbedtls/private_access.h" -#if !defined(MBEDTLS_CONFIG_FILE) -#include "mbedtls/config.h" -#else -#include MBEDTLS_CONFIG_FILE -#endif +#include "mbedtls/build_info.h" #include "mbedtls/x509.h" #include "mbedtls/x509_crl.h" @@ -48,10 +33,14 @@ extern "C" { /** * Container for an X.509 certificate. The certificate may be chained. + * + * Some fields of this structure are publicly readable. Do not modify + * them except via Mbed TLS library functions: the effect of modifying + * those fields or the data that those fields points to is unspecified. */ typedef struct mbedtls_x509_crt { - int own_buffer; /**< Indicates if \c raw is owned - * by the structure or not. */ + int MBEDTLS_PRIVATE(own_buffer); /**< Indicates if \c raw is owned + * by the structure or not. */ mbedtls_x509_buf raw; /**< The raw certificate data (DER). */ mbedtls_x509_buf tbs; /**< The raw certificate body (DER). The part that is To Be Signed. */ @@ -74,72 +63,34 @@ typedef struct mbedtls_x509_crt { mbedtls_x509_buf issuer_id; /**< Optional X.509 v2/v3 issuer unique identifier. */ mbedtls_x509_buf subject_id; /**< Optional X.509 v2/v3 subject unique identifier. */ mbedtls_x509_buf v3_ext; /**< Optional X.509 v3 extensions. */ - mbedtls_x509_sequence subject_alt_names; /**< Optional list of raw entries of Subject Alternative Names extension (currently only dNSName and OtherName are listed). */ + mbedtls_x509_sequence subject_alt_names; /**< Optional list of raw entries of Subject Alternative Names extension. These can be later parsed by mbedtls_x509_parse_subject_alt_name. */ + mbedtls_x509_buf subject_key_id; /**< Optional X.509 v3 extension subject key identifier. */ + mbedtls_x509_authority authority_key_id; /**< Optional X.509 v3 extension authority key identifier. */ mbedtls_x509_sequence certificate_policies; /**< Optional list of certificate policies (Only anyPolicy is printed and enforced, however the rest of the policies are still listed). */ - int ext_types; /**< Bit string containing detected and parsed extensions */ - int ca_istrue; /**< Optional Basic Constraint extension value: 1 if this certificate belongs to a CA, 0 otherwise. */ - int max_pathlen; /**< Optional Basic Constraint extension value: The maximum path length to the root certificate. Path length is 1 higher than RFC 5280 'meaning', so 1+ */ + int MBEDTLS_PRIVATE(ext_types); /**< Bit string containing detected and parsed extensions */ + int MBEDTLS_PRIVATE(ca_istrue); /**< Optional Basic Constraint extension value: 1 if this certificate belongs to a CA, 0 otherwise. */ + int MBEDTLS_PRIVATE(max_pathlen); /**< Optional Basic Constraint extension value: The maximum path length to the root certificate. Path length is 1 higher than RFC 5280 'meaning', so 1+ */ - unsigned int key_usage; /**< Optional key usage extension value: See the values in x509.h */ + unsigned int MBEDTLS_PRIVATE(key_usage); /**< Optional key usage extension value: See the values in x509.h */ mbedtls_x509_sequence ext_key_usage; /**< Optional list of extended key usage OIDs. */ - unsigned char ns_cert_type; /**< Optional Netscape certificate type extension value: See the values in x509.h */ + unsigned char MBEDTLS_PRIVATE(ns_cert_type); /**< Optional Netscape certificate type extension value: See the values in x509.h */ - mbedtls_x509_buf sig; /**< Signature: hash of the tbs part signed with the private key. */ - mbedtls_md_type_t sig_md; /**< Internal representation of the MD algorithm of the signature algorithm, e.g. MBEDTLS_MD_SHA256 */ - mbedtls_pk_type_t sig_pk; /**< Internal representation of the Public Key algorithm of the signature algorithm, e.g. MBEDTLS_PK_RSA */ - void *sig_opts; /**< Signature options to be passed to mbedtls_pk_verify_ext(), e.g. for RSASSA-PSS */ + mbedtls_x509_buf MBEDTLS_PRIVATE(sig); /**< Signature: hash of the tbs part signed with the private key. */ + mbedtls_md_type_t MBEDTLS_PRIVATE(sig_md); /**< Internal representation of the MD algorithm of the signature algorithm, e.g. MBEDTLS_MD_SHA256 */ + mbedtls_pk_type_t MBEDTLS_PRIVATE(sig_pk); /**< Internal representation of the Public Key algorithm of the signature algorithm, e.g. MBEDTLS_PK_RSA */ + void *MBEDTLS_PRIVATE(sig_opts); /**< Signature options to be passed to mbedtls_pk_verify_ext(), e.g. for RSASSA-PSS */ - struct mbedtls_x509_crt *next; /**< Next certificate in the CA-chain. */ + /** Next certificate in the linked list that constitutes the CA chain. + * \p NULL indicates the end of the list. + * Do not modify this field directly. */ + struct mbedtls_x509_crt *next; } mbedtls_x509_crt; -/** - * From RFC 5280 section 4.2.1.6: - * OtherName ::= SEQUENCE { - * type-id OBJECT IDENTIFIER, - * value [0] EXPLICIT ANY DEFINED BY type-id } - */ -typedef struct mbedtls_x509_san_other_name { - /** - * The type_id is an OID as defined in RFC 5280. - * To check the value of the type id, you should use - * \p MBEDTLS_OID_CMP with a known OID mbedtls_x509_buf. - */ - mbedtls_x509_buf type_id; /**< The type id. */ - union { - /** - * From RFC 4108 section 5: - * HardwareModuleName ::= SEQUENCE { - * hwType OBJECT IDENTIFIER, - * hwSerialNum OCTET STRING } - */ - struct { - mbedtls_x509_buf oid; /**< The object identifier. */ - mbedtls_x509_buf val; /**< The named value. */ - } - hardware_module_name; - } - value; -} -mbedtls_x509_san_other_name; - -/** - * A structure for holding the parsed Subject Alternative Name, according to type - */ -typedef struct mbedtls_x509_subject_alternative_name { - int type; /**< The SAN type, value of MBEDTLS_X509_SAN_XXX. */ - union { - mbedtls_x509_san_other_name other_name; /**< The otherName supported type. */ - mbedtls_x509_buf unstructured_name; /**< The buffer for the un constructed types. Only dnsName currently supported */ - } - san; /**< A union of the supported SAN types */ -} -mbedtls_x509_subject_alternative_name; - /** * Build flag from an algorithm/curve identifier (pk, md, ecp) * Since 0 is always XXX_NONE, ignore it. @@ -150,6 +101,26 @@ mbedtls_x509_subject_alternative_name; * Security profile for certificate verification. * * All lists are bitfields, built by ORing flags from MBEDTLS_X509_ID_FLAG(). + * + * The fields of this structure are part of the public API and can be + * manipulated directly by applications. Future versions of the library may + * add extra fields or reorder existing fields. + * + * You can create custom profiles by starting from a copy of + * an existing profile, such as mbedtls_x509_crt_profile_default or + * mbedtls_x509_ctr_profile_none and then tune it to your needs. + * + * For example to allow SHA-224 in addition to the default: + * + * mbedtls_x509_crt_profile my_profile = mbedtls_x509_crt_profile_default; + * my_profile.allowed_mds |= MBEDTLS_X509_ID_FLAG( MBEDTLS_MD_SHA224 ); + * + * Or to allow only RSA-3072+ with SHA-256: + * + * mbedtls_x509_crt_profile my_profile = mbedtls_x509_crt_profile_none; + * my_profile.allowed_mds = MBEDTLS_X509_ID_FLAG( MBEDTLS_MD_SHA256 ); + * my_profile.allowed_pks = MBEDTLS_X509_ID_FLAG( MBEDTLS_PK_RSA ); + * my_profile.rsa_min_bitlen = 3072; */ typedef struct mbedtls_x509_crt_profile { uint32_t allowed_mds; /**< MDs for signatures */ @@ -165,36 +136,120 @@ mbedtls_x509_crt_profile; #define MBEDTLS_X509_CRT_VERSION_2 1 #define MBEDTLS_X509_CRT_VERSION_3 2 -#define MBEDTLS_X509_RFC5280_MAX_SERIAL_LEN 32 +#define MBEDTLS_X509_RFC5280_MAX_SERIAL_LEN 20 #define MBEDTLS_X509_RFC5280_UTC_TIME_LEN 15 #if !defined(MBEDTLS_X509_MAX_FILE_PATH_LEN) #define MBEDTLS_X509_MAX_FILE_PATH_LEN 512 #endif +/* This macro unfolds to the concatenation of macro invocations + * X509_CRT_ERROR_INFO( error code, + * error code as string, + * human readable description ) + * where X509_CRT_ERROR_INFO is defined by the user. + * See x509_crt.c for an example of how to use this. */ +#define MBEDTLS_X509_CRT_ERROR_INFO_LIST \ + X509_CRT_ERROR_INFO(MBEDTLS_X509_BADCERT_EXPIRED, \ + "MBEDTLS_X509_BADCERT_EXPIRED", \ + "The certificate validity has expired") \ + X509_CRT_ERROR_INFO(MBEDTLS_X509_BADCERT_REVOKED, \ + "MBEDTLS_X509_BADCERT_REVOKED", \ + "The certificate has been revoked (is on a CRL)") \ + X509_CRT_ERROR_INFO(MBEDTLS_X509_BADCERT_CN_MISMATCH, \ + "MBEDTLS_X509_BADCERT_CN_MISMATCH", \ + "The certificate Common Name (CN) does not match with the expected CN") \ + X509_CRT_ERROR_INFO(MBEDTLS_X509_BADCERT_NOT_TRUSTED, \ + "MBEDTLS_X509_BADCERT_NOT_TRUSTED", \ + "The certificate is not correctly signed by the trusted CA") \ + X509_CRT_ERROR_INFO(MBEDTLS_X509_BADCRL_NOT_TRUSTED, \ + "MBEDTLS_X509_BADCRL_NOT_TRUSTED", \ + "The CRL is not correctly signed by the trusted CA") \ + X509_CRT_ERROR_INFO(MBEDTLS_X509_BADCRL_EXPIRED, \ + "MBEDTLS_X509_BADCRL_EXPIRED", \ + "The CRL is expired") \ + X509_CRT_ERROR_INFO(MBEDTLS_X509_BADCERT_MISSING, \ + "MBEDTLS_X509_BADCERT_MISSING", \ + "Certificate was missing") \ + X509_CRT_ERROR_INFO(MBEDTLS_X509_BADCERT_SKIP_VERIFY, \ + "MBEDTLS_X509_BADCERT_SKIP_VERIFY", \ + "Certificate verification was skipped") \ + X509_CRT_ERROR_INFO(MBEDTLS_X509_BADCERT_OTHER, \ + "MBEDTLS_X509_BADCERT_OTHER", \ + "Other reason (can be used by verify callback)") \ + X509_CRT_ERROR_INFO(MBEDTLS_X509_BADCERT_FUTURE, \ + "MBEDTLS_X509_BADCERT_FUTURE", \ + "The certificate validity starts in the future") \ + X509_CRT_ERROR_INFO(MBEDTLS_X509_BADCRL_FUTURE, \ + "MBEDTLS_X509_BADCRL_FUTURE", \ + "The CRL is from the future") \ + X509_CRT_ERROR_INFO(MBEDTLS_X509_BADCERT_KEY_USAGE, \ + "MBEDTLS_X509_BADCERT_KEY_USAGE", \ + "Usage does not match the keyUsage extension") \ + X509_CRT_ERROR_INFO(MBEDTLS_X509_BADCERT_EXT_KEY_USAGE, \ + "MBEDTLS_X509_BADCERT_EXT_KEY_USAGE", \ + "Usage does not match the extendedKeyUsage extension") \ + X509_CRT_ERROR_INFO(MBEDTLS_X509_BADCERT_NS_CERT_TYPE, \ + "MBEDTLS_X509_BADCERT_NS_CERT_TYPE", \ + "Usage does not match the nsCertType extension") \ + X509_CRT_ERROR_INFO(MBEDTLS_X509_BADCERT_BAD_MD, \ + "MBEDTLS_X509_BADCERT_BAD_MD", \ + "The certificate is signed with an unacceptable hash.") \ + X509_CRT_ERROR_INFO(MBEDTLS_X509_BADCERT_BAD_PK, \ + "MBEDTLS_X509_BADCERT_BAD_PK", \ + "The certificate is signed with an unacceptable PK alg (eg RSA vs ECDSA).") \ + X509_CRT_ERROR_INFO(MBEDTLS_X509_BADCERT_BAD_KEY, \ + "MBEDTLS_X509_BADCERT_BAD_KEY", \ + "The certificate is signed with an unacceptable key (eg bad curve, RSA too short).") \ + X509_CRT_ERROR_INFO(MBEDTLS_X509_BADCRL_BAD_MD, \ + "MBEDTLS_X509_BADCRL_BAD_MD", \ + "The CRL is signed with an unacceptable hash.") \ + X509_CRT_ERROR_INFO(MBEDTLS_X509_BADCRL_BAD_PK, \ + "MBEDTLS_X509_BADCRL_BAD_PK", \ + "The CRL is signed with an unacceptable PK alg (eg RSA vs ECDSA).") \ + X509_CRT_ERROR_INFO(MBEDTLS_X509_BADCRL_BAD_KEY, \ + "MBEDTLS_X509_BADCRL_BAD_KEY", \ + "The CRL is signed with an unacceptable key (eg bad curve, RSA too short).") + /** * Container for writing a certificate (CRT) */ typedef struct mbedtls_x509write_cert { - int version; - mbedtls_mpi serial; - mbedtls_pk_context *subject_key; - mbedtls_pk_context *issuer_key; - mbedtls_asn1_named_data *subject; - mbedtls_asn1_named_data *issuer; - mbedtls_md_type_t md_alg; - char not_before[MBEDTLS_X509_RFC5280_UTC_TIME_LEN + 1]; - char not_after[MBEDTLS_X509_RFC5280_UTC_TIME_LEN + 1]; - mbedtls_asn1_named_data *extensions; + int MBEDTLS_PRIVATE(version); + unsigned char MBEDTLS_PRIVATE(serial)[MBEDTLS_X509_RFC5280_MAX_SERIAL_LEN]; + size_t MBEDTLS_PRIVATE(serial_len); + mbedtls_pk_context *MBEDTLS_PRIVATE(subject_key); + mbedtls_pk_context *MBEDTLS_PRIVATE(issuer_key); + mbedtls_asn1_named_data *MBEDTLS_PRIVATE(subject); + mbedtls_asn1_named_data *MBEDTLS_PRIVATE(issuer); + mbedtls_md_type_t MBEDTLS_PRIVATE(md_alg); + char MBEDTLS_PRIVATE(not_before)[MBEDTLS_X509_RFC5280_UTC_TIME_LEN + 1]; + char MBEDTLS_PRIVATE(not_after)[MBEDTLS_X509_RFC5280_UTC_TIME_LEN + 1]; + mbedtls_asn1_named_data *MBEDTLS_PRIVATE(extensions); } mbedtls_x509write_cert; +/** + * \brief Set Subject Alternative Name + * + * \param ctx Certificate context to use + * \param san_list List of SAN values + * + * \return 0 if successful, or MBEDTLS_ERR_X509_ALLOC_FAILED + * + * \note "dnsName", "uniformResourceIdentifier", "IP address", + * "otherName", and "DirectoryName", as defined in RFC 5280, + * are supported. + */ +int mbedtls_x509write_crt_set_subject_alternative_name(mbedtls_x509write_cert *ctx, + const mbedtls_x509_san_list *san_list); + /** * Item in a verification chain: cert and flags for it */ typedef struct { - mbedtls_x509_crt *crt; - uint32_t flags; + mbedtls_x509_crt *MBEDTLS_PRIVATE(crt); + uint32_t MBEDTLS_PRIVATE(flags); } mbedtls_x509_crt_verify_chain_item; /** @@ -206,15 +261,15 @@ typedef struct { * Verification chain as built by \c mbedtls_crt_verify_chain() */ typedef struct { - mbedtls_x509_crt_verify_chain_item items[MBEDTLS_X509_MAX_VERIFY_CHAIN_SIZE]; - unsigned len; + mbedtls_x509_crt_verify_chain_item MBEDTLS_PRIVATE(items)[MBEDTLS_X509_MAX_VERIFY_CHAIN_SIZE]; + unsigned MBEDTLS_PRIVATE(len); #if defined(MBEDTLS_X509_TRUSTED_CERTIFICATE_CALLBACK) /* This stores the list of potential trusted signers obtained from * the CA callback used for the CRT verification, if configured. * We must track it somewhere because the callback passes its * ownership to the caller. */ - mbedtls_x509_crt *trust_ca_cb_result; + mbedtls_x509_crt *MBEDTLS_PRIVATE(trust_ca_cb_result); #endif /* MBEDTLS_X509_TRUSTED_CERTIFICATE_CALLBACK */ } mbedtls_x509_crt_verify_chain; @@ -225,23 +280,23 @@ typedef struct { */ typedef struct { /* for check_signature() */ - mbedtls_pk_restart_ctx pk; + mbedtls_pk_restart_ctx MBEDTLS_PRIVATE(pk); /* for find_parent_in() */ - mbedtls_x509_crt *parent; /* non-null iff parent_in in progress */ - mbedtls_x509_crt *fallback_parent; - int fallback_signature_is_good; + mbedtls_x509_crt *MBEDTLS_PRIVATE(parent); /* non-null iff parent_in in progress */ + mbedtls_x509_crt *MBEDTLS_PRIVATE(fallback_parent); + int MBEDTLS_PRIVATE(fallback_signature_is_good); /* for find_parent() */ - int parent_is_trusted; /* -1 if find_parent is not in progress */ + int MBEDTLS_PRIVATE(parent_is_trusted); /* -1 if find_parent is not in progress */ /* for verify_chain() */ enum { x509_crt_rs_none, x509_crt_rs_find_parent, - } in_progress; /* none if no operation is in progress */ - int self_cnt; - mbedtls_x509_crt_verify_chain ver_chain; + } MBEDTLS_PRIVATE(in_progress); /* none if no operation is in progress */ + int MBEDTLS_PRIVATE(self_cnt); + mbedtls_x509_crt_verify_chain MBEDTLS_PRIVATE(ver_chain); } mbedtls_x509_crt_restart_ctx; @@ -258,12 +313,12 @@ typedef void mbedtls_x509_crt_restart_ctx; * and compatibility with current deployments. * * This profile permits: - * - SHA2 hashes. - * - All supported elliptic curves. + * - SHA2 hashes with at least 256 bits: SHA-256, SHA-384, SHA-512. + * - Elliptic curves with 255 bits and above except secp256k1. * - RSA with 2048 bits and above. * * New minor versions of Mbed TLS may extend this profile, for example if - * new curves are added to the library. New minor versions of Mbed TLS will + * new algorithms are added to the library. New minor versions of Mbed TLS will * not reduce this profile unless serious security concerns require it. */ extern const mbedtls_x509_crt_profile mbedtls_x509_crt_profile_default; @@ -271,6 +326,7 @@ extern const mbedtls_x509_crt_profile mbedtls_x509_crt_profile_default; /** * Expected next default profile. Recommended for new deployments. * Currently targets a 128-bit security level, except for allowing RSA-2048. + * This profile may change at any time. */ extern const mbedtls_x509_crt_profile mbedtls_x509_crt_profile_next; @@ -279,6 +335,12 @@ extern const mbedtls_x509_crt_profile mbedtls_x509_crt_profile_next; */ extern const mbedtls_x509_crt_profile mbedtls_x509_crt_profile_suiteb; +/** + * Empty profile that allows nothing. Useful as a basis for constructing + * custom profiles. + */ +extern const mbedtls_x509_crt_profile mbedtls_x509_crt_profile_none; + /** * \brief Parse a single DER formatted certificate and add it * to the end of the provided chained list. @@ -412,7 +474,7 @@ int mbedtls_x509_crt_parse_der_with_ext_cb(mbedtls_x509_crt *chain, * mbedtls_x509_crt_init(). * \param buf The address of the readable buffer holding the DER encoded * certificate to use. On success, this buffer must be - * retained and not be changed for the liftetime of the + * retained and not be changed for the lifetime of the * CRT chain \p chain, that is, until \p chain is destroyed * through a call to mbedtls_x509_crt_free(). * \param buflen The size in Bytes of \p buf. @@ -502,35 +564,8 @@ int mbedtls_x509_crt_parse_file(mbedtls_x509_crt *chain, const char *path); int mbedtls_x509_crt_parse_path(mbedtls_x509_crt *chain, const char *path); #endif /* MBEDTLS_FS_IO */ -/** - * \brief This function parses an item in the SubjectAlternativeNames - * extension. - * - * \param san_buf The buffer holding the raw data item of the subject - * alternative name. - * \param san The target structure to populate with the parsed presentation - * of the subject alternative name encoded in \p san_buf. - * - * \note Only "dnsName" and "otherName" of type hardware_module_name - * as defined in RFC 4180 is supported. - * - * \note This function should be called on a single raw data of - * subject alternative name. For example, after successful - * certificate parsing, one must iterate on every item in the - * \c crt->subject_alt_names sequence, and pass it to - * this function. - * - * \warning The target structure contains pointers to the raw data of the - * parsed certificate, and its lifetime is restricted by the - * lifetime of the certificate. - * - * \return \c 0 on success - * \return #MBEDTLS_ERR_X509_FEATURE_UNAVAILABLE for an unsupported - * SAN type. - * \return Another negative value for any other failure. - */ -int mbedtls_x509_parse_subject_alt_name(const mbedtls_x509_buf *san_buf, - mbedtls_x509_subject_alternative_name *san); + +#if !defined(MBEDTLS_X509_REMOVE_INFO) /** * \brief Returns an informational string about the * certificate. @@ -560,6 +595,7 @@ int mbedtls_x509_crt_info(char *buf, size_t size, const char *prefix, */ int mbedtls_x509_crt_verify_info(char *buf, size_t size, const char *prefix, uint32_t flags); +#endif /* !MBEDTLS_X509_REMOVE_INFO */ /** * \brief Verify a chain of certificates. @@ -608,8 +644,12 @@ int mbedtls_x509_crt_verify_info(char *buf, size_t size, const char *prefix, * \param cn The expected Common Name. This will be checked to be * present in the certificate's subjectAltNames extension or, * if this extension is absent, as a CN component in its - * Subject name. Currently only DNS names are supported. This - * may be \c NULL if the CN need not be verified. + * Subject name. DNS names and IP addresses are fully + * supported, while the URI subtype is partially supported: + * only exact matching, without any normalization procedures + * described in 7.4 of RFC5280, will result in a positive + * URI verification. + * This may be \c NULL if the CN need not be verified. * \param flags The address at which to store the result of the verification. * If the verification couldn't be completed, the flag value is * set to (uint32_t) -1. @@ -778,7 +818,6 @@ int mbedtls_x509_crt_verify_with_ca_cb(mbedtls_x509_crt *crt, #endif /* MBEDTLS_X509_TRUSTED_CERTIFICATE_CALLBACK */ -#if defined(MBEDTLS_X509_CHECK_KEY_USAGE) /** * \brief Check usage of certificate against keyUsage extension. * @@ -802,9 +841,7 @@ int mbedtls_x509_crt_verify_with_ca_cb(mbedtls_x509_crt *crt, */ int mbedtls_x509_crt_check_key_usage(const mbedtls_x509_crt *crt, unsigned int usage); -#endif /* MBEDTLS_X509_CHECK_KEY_USAGE) */ -#if defined(MBEDTLS_X509_CHECK_EXTENDED_KEY_USAGE) /** * \brief Check usage of certificate against extendedKeyUsage. * @@ -821,7 +858,6 @@ int mbedtls_x509_crt_check_key_usage(const mbedtls_x509_crt *crt, int mbedtls_x509_crt_check_extended_key_usage(const mbedtls_x509_crt *crt, const char *usage_oid, size_t usage_len); -#endif /* MBEDTLS_X509_CHECK_EXTENDED_KEY_USAGE */ #if defined(MBEDTLS_X509_CRL_PARSE_C) /** @@ -863,6 +899,35 @@ void mbedtls_x509_crt_restart_free(mbedtls_x509_crt_restart_ctx *ctx); #endif /* MBEDTLS_ECDSA_C && MBEDTLS_ECP_RESTARTABLE */ #endif /* MBEDTLS_X509_CRT_PARSE_C */ +/** + * \brief Query certificate for given extension type + * + * \param[in] ctx Certificate context to be queried, must not be \c NULL + * \param ext_type Extension type being queried for, must be a valid + * extension type. Must be one of the MBEDTLS_X509_EXT_XXX + * values + * + * \return 0 if the given extension type is not present, + * non-zero otherwise + */ +static inline int mbedtls_x509_crt_has_ext_type(const mbedtls_x509_crt *ctx, + int ext_type) +{ + return ctx->MBEDTLS_PRIVATE(ext_types) & ext_type; +} + +/** + * \brief Access the ca_istrue field + * + * \param[in] crt Certificate to be queried, must not be \c NULL + * + * \return \c 1 if this a CA certificate \c 0 otherwise. + * \return MBEDTLS_ERR_X509_INVALID_EXTENSIONS if the certificate does not contain + * the Optional Basic Constraint extension. + * + */ +int mbedtls_x509_crt_get_ca_istrue(const mbedtls_x509_crt *crt); + /** \} name Structures and functions for parsing and writing X.509 certificates */ #if defined(MBEDTLS_X509_CRT_WRITE_C) @@ -883,15 +948,43 @@ void mbedtls_x509write_crt_init(mbedtls_x509write_cert *ctx); */ void mbedtls_x509write_crt_set_version(mbedtls_x509write_cert *ctx, int version); +#if defined(MBEDTLS_BIGNUM_C) && !defined(MBEDTLS_DEPRECATED_REMOVED) /** * \brief Set the serial number for a Certificate. * + * \deprecated This function is deprecated and will be removed in a + * future version of the library. Please use + * mbedtls_x509write_crt_set_serial_raw() instead. + * + * \note Even though the MBEDTLS_BIGNUM_C guard looks redundant since + * X509 depends on PK and PK depends on BIGNUM, this emphasizes + * a direct dependency between X509 and BIGNUM which is going + * to be deprecated in the future. + * * \param ctx CRT context to use * \param serial serial number to set * * \return 0 if successful */ -int mbedtls_x509write_crt_set_serial(mbedtls_x509write_cert *ctx, const mbedtls_mpi *serial); +int MBEDTLS_DEPRECATED mbedtls_x509write_crt_set_serial( + mbedtls_x509write_cert *ctx, const mbedtls_mpi *serial); +#endif // MBEDTLS_BIGNUM_C && !MBEDTLS_DEPRECATED_REMOVED + +/** + * \brief Set the serial number for a Certificate. + * + * \param ctx CRT context to use + * \param serial A raw array of bytes containing the serial number in big + * endian format + * \param serial_len Length of valid bytes (expressed in bytes) in \p serial + * input buffer + * + * \return 0 if successful, or + * MBEDTLS_ERR_X509_BAD_INPUT_DATA if the provided input buffer + * is too big (longer than MBEDTLS_X509_RFC5280_MAX_SERIAL_LEN) + */ +int mbedtls_x509write_crt_set_serial_raw(mbedtls_x509write_cert *ctx, + unsigned char *serial, size_t serial_len); /** * \brief Set the validity period for a Certificate @@ -997,7 +1090,7 @@ int mbedtls_x509write_crt_set_extension(mbedtls_x509write_cert *ctx, int mbedtls_x509write_crt_set_basic_constraints(mbedtls_x509write_cert *ctx, int is_ca, int max_pathlen); -#if defined(MBEDTLS_SHA1_C) +#if defined(MBEDTLS_MD_CAN_SHA1) /** * \brief Set the subjectKeyIdentifier extension for a CRT * Requires that mbedtls_x509write_crt_set_subject_key() has been @@ -1019,7 +1112,7 @@ int mbedtls_x509write_crt_set_subject_key_identifier(mbedtls_x509write_cert *ctx * \return 0 if successful, or a MBEDTLS_ERR_X509_ALLOC_FAILED */ int mbedtls_x509write_crt_set_authority_key_identifier(mbedtls_x509write_cert *ctx); -#endif /* MBEDTLS_SHA1_C */ +#endif /* MBEDTLS_MD_CAN_SHA1 */ /** * \brief Set the Key Usage Extension flags @@ -1033,6 +1126,19 @@ int mbedtls_x509write_crt_set_authority_key_identifier(mbedtls_x509write_cert *c int mbedtls_x509write_crt_set_key_usage(mbedtls_x509write_cert *ctx, unsigned int key_usage); +/** + * \brief Set the Extended Key Usage Extension + * (e.g. MBEDTLS_OID_SERVER_AUTH) + * + * \param ctx CRT context to use + * \param exts extended key usage extensions to set, a sequence of + * MBEDTLS_ASN1_OID objects + * + * \return 0 if successful, or MBEDTLS_ERR_X509_ALLOC_FAILED + */ +int mbedtls_x509write_crt_set_ext_key_usage(mbedtls_x509write_cert *ctx, + const mbedtls_asn1_sequence *exts); + /** * \brief Set the Netscape Cert Type flags * (e.g. MBEDTLS_X509_NS_CERT_TYPE_SSL_CLIENT | MBEDTLS_X509_NS_CERT_TYPE_EMAIL) @@ -1061,16 +1167,13 @@ void mbedtls_x509write_crt_free(mbedtls_x509write_cert *ctx); * \param ctx certificate to write away * \param buf buffer to write to * \param size size of the buffer - * \param f_rng RNG function (for signature, see note) + * \param f_rng RNG function. This must not be \c NULL. * \param p_rng RNG parameter * * \return length of data written if successful, or a specific * error code * - * \note f_rng may be NULL if RSA is used for signature and the - * signature is made offline (otherwise f_rng is desirable - * for countermeasures against timing attacks). - * ECDSA signatures always require a non-NULL f_rng. + * \note \p f_rng is used for the signature operation. */ int mbedtls_x509write_crt_der(mbedtls_x509write_cert *ctx, unsigned char *buf, size_t size, int (*f_rng)(void *, unsigned char *, size_t), @@ -1083,15 +1186,12 @@ int mbedtls_x509write_crt_der(mbedtls_x509write_cert *ctx, unsigned char *buf, s * \param ctx certificate to write away * \param buf buffer to write to * \param size size of the buffer - * \param f_rng RNG function (for signature, see note) + * \param f_rng RNG function. This must not be \c NULL. * \param p_rng RNG parameter * * \return 0 if successful, or a specific error code * - * \note f_rng may be NULL if RSA is used for signature and the - * signature is made offline (otherwise f_rng is desirable - * for countermeasures against timing attacks). - * ECDSA signatures always require a non-NULL f_rng. + * \note \p f_rng is used for the signature operation. */ int mbedtls_x509write_crt_pem(mbedtls_x509write_cert *ctx, unsigned char *buf, size_t size, int (*f_rng)(void *, unsigned char *, size_t), diff --git a/vendor/mbedtls/include/mbedtls/x509_csr.h b/vendor/mbedtls/include/mbedtls/x509_csr.h index 6daf57b662..8c31c09af4 100644 --- a/vendor/mbedtls/include/mbedtls/x509_csr.h +++ b/vendor/mbedtls/include/mbedtls/x509_csr.h @@ -5,28 +5,13 @@ */ /* * Copyright The Mbed TLS Contributors - * SPDX-License-Identifier: Apache-2.0 - * - * Licensed under the Apache License, Version 2.0 (the "License"); you may - * not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT - * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. + * SPDX-License-Identifier: Apache-2.0 OR GPL-2.0-or-later */ #ifndef MBEDTLS_X509_CSR_H #define MBEDTLS_X509_CSR_H +#include "mbedtls/private_access.h" -#if !defined(MBEDTLS_CONFIG_FILE) -#include "mbedtls/config.h" -#else -#include MBEDTLS_CONFIG_FILE -#endif +#include "mbedtls/build_info.h" #include "mbedtls/x509.h" @@ -45,6 +30,10 @@ extern "C" { /** * Certificate Signing Request (CSR) structure. + * + * Some fields of this structure are publicly readable. Do not modify + * them except via Mbed TLS library functions: the effect of modifying + * those fields or the data that those fields point to is unspecified. */ typedef struct mbedtls_x509_csr { mbedtls_x509_buf raw; /**< The raw CSR data (DER). */ @@ -57,11 +46,17 @@ typedef struct mbedtls_x509_csr { mbedtls_pk_context pk; /**< Container for the public key context. */ + unsigned int key_usage; /**< Optional key usage extension value: See the values in x509.h */ + unsigned char ns_cert_type; /**< Optional Netscape certificate type extension value: See the values in x509.h */ + mbedtls_x509_sequence subject_alt_names; /**< Optional list of raw entries of Subject Alternative Names extension. These can be later parsed by mbedtls_x509_parse_subject_alt_name. */ + + int MBEDTLS_PRIVATE(ext_types); /**< Bit string containing detected and parsed extensions */ + mbedtls_x509_buf sig_oid; - mbedtls_x509_buf sig; - mbedtls_md_type_t sig_md; /**< Internal representation of the MD algorithm of the signature algorithm, e.g. MBEDTLS_MD_SHA256 */ - mbedtls_pk_type_t sig_pk; /**< Internal representation of the Public Key algorithm of the signature algorithm, e.g. MBEDTLS_PK_RSA */ - void *sig_opts; /**< Signature options to be passed to mbedtls_pk_verify_ext(), e.g. for RSASSA-PSS */ + mbedtls_x509_buf MBEDTLS_PRIVATE(sig); + mbedtls_md_type_t MBEDTLS_PRIVATE(sig_md); /**< Internal representation of the MD algorithm of the signature algorithm, e.g. MBEDTLS_MD_SHA256 */ + mbedtls_pk_type_t MBEDTLS_PRIVATE(sig_pk); /**< Internal representation of the Public Key algorithm of the signature algorithm, e.g. MBEDTLS_PK_RSA */ + void *MBEDTLS_PRIVATE(sig_opts); /**< Signature options to be passed to mbedtls_pk_verify_ext(), e.g. for RSASSA-PSS */ } mbedtls_x509_csr; @@ -69,10 +64,10 @@ mbedtls_x509_csr; * Container for writing a CSR */ typedef struct mbedtls_x509write_csr { - mbedtls_pk_context *key; - mbedtls_asn1_named_data *subject; - mbedtls_md_type_t md_alg; - mbedtls_asn1_named_data *extensions; + mbedtls_pk_context *MBEDTLS_PRIVATE(key); + mbedtls_asn1_named_data *MBEDTLS_PRIVATE(subject); + mbedtls_md_type_t MBEDTLS_PRIVATE(md_alg); + mbedtls_asn1_named_data *MBEDTLS_PRIVATE(extensions); } mbedtls_x509write_csr; @@ -80,7 +75,9 @@ mbedtls_x509write_csr; /** * \brief Load a Certificate Signing Request (CSR) in DER format * - * \note CSR attributes (if any) are currently silently ignored. + * \note Any unsupported requested extensions are silently + * ignored, unless the critical flag is set, in which case + * the CSR is rejected. * * \note If #MBEDTLS_USE_PSA_CRYPTO is enabled, the PSA crypto * subsystem must have been initialized by calling @@ -95,6 +92,67 @@ mbedtls_x509write_csr; int mbedtls_x509_csr_parse_der(mbedtls_x509_csr *csr, const unsigned char *buf, size_t buflen); +/** + * \brief The type of certificate extension callbacks. + * + * Callbacks of this type are passed to and used by the + * mbedtls_x509_csr_parse_der_with_ext_cb() routine when + * it encounters either an unsupported extension. + * Future versions of the library may invoke the callback + * in other cases, if and when the need arises. + * + * \param p_ctx An opaque context passed to the callback. + * \param csr The CSR being parsed. + * \param oid The OID of the extension. + * \param critical Whether the extension is critical. + * \param p Pointer to the start of the extension value + * (the content of the OCTET STRING). + * \param end End of extension value. + * + * \note The callback must fail and return a negative error code + * if it can not parse or does not support the extension. + * When the callback fails to parse a critical extension + * mbedtls_x509_csr_parse_der_with_ext_cb() also fails. + * When the callback fails to parse a non critical extension + * mbedtls_x509_csr_parse_der_with_ext_cb() simply skips + * the extension and continues parsing. + * + * \return \c 0 on success. + * \return A negative error code on failure. + */ +typedef int (*mbedtls_x509_csr_ext_cb_t)(void *p_ctx, + mbedtls_x509_csr const *csr, + mbedtls_x509_buf const *oid, + int critical, + const unsigned char *p, + const unsigned char *end); + +/** + * \brief Load a Certificate Signing Request (CSR) in DER format + * + * \note Any unsupported requested extensions are silently + * ignored, unless the critical flag is set, in which case + * the result of the callback function decides whether + * CSR is rejected. + * + * \note If #MBEDTLS_USE_PSA_CRYPTO is enabled, the PSA crypto + * subsystem must have been initialized by calling + * psa_crypto_init() before calling this function. + * + * \param csr CSR context to fill + * \param buf buffer holding the CRL data + * \param buflen size of the buffer + * \param cb A callback invoked for every unsupported certificate + * extension. + * \param p_ctx An opaque context passed to the callback. + * + * \return 0 if successful, or a specific X509 error code + */ +int mbedtls_x509_csr_parse_der_with_ext_cb(mbedtls_x509_csr *csr, + const unsigned char *buf, size_t buflen, + mbedtls_x509_csr_ext_cb_t cb, + void *p_ctx); + /** * \brief Load a Certificate Signing Request (CSR), DER or PEM format * @@ -127,6 +185,7 @@ int mbedtls_x509_csr_parse(mbedtls_x509_csr *csr, const unsigned char *buf, size int mbedtls_x509_csr_parse_file(mbedtls_x509_csr *csr, const char *path); #endif /* MBEDTLS_FS_IO */ +#if !defined(MBEDTLS_X509_REMOVE_INFO) /** * \brief Returns an informational string about the * CSR. @@ -141,6 +200,7 @@ int mbedtls_x509_csr_parse_file(mbedtls_x509_csr *csr, const char *path); */ int mbedtls_x509_csr_info(char *buf, size_t size, const char *prefix, const mbedtls_x509_csr *csr); +#endif /* !MBEDTLS_X509_REMOVE_INFO */ /** * \brief Initialize a CSR @@ -219,6 +279,20 @@ void mbedtls_x509write_csr_set_md_alg(mbedtls_x509write_csr *ctx, mbedtls_md_typ */ int mbedtls_x509write_csr_set_key_usage(mbedtls_x509write_csr *ctx, unsigned char key_usage); +/** + * \brief Set Subject Alternative Name + * + * \param ctx CSR context to use + * \param san_list List of SAN values + * + * \return 0 if successful, or MBEDTLS_ERR_X509_ALLOC_FAILED + * + * \note Only "dnsName", "uniformResourceIdentifier" and "otherName", + * as defined in RFC 5280, are supported. + */ +int mbedtls_x509write_csr_set_subject_alternative_name(mbedtls_x509write_csr *ctx, + const mbedtls_x509_san_list *san_list); + /** * \brief Set the Netscape Cert Type flags * (e.g. MBEDTLS_X509_NS_CERT_TYPE_SSL_CLIENT | MBEDTLS_X509_NS_CERT_TYPE_EMAIL) @@ -238,6 +312,7 @@ int mbedtls_x509write_csr_set_ns_cert_type(mbedtls_x509write_csr *ctx, * \param ctx CSR context to use * \param oid OID of the extension * \param oid_len length of the OID + * \param critical Set to 1 to mark the extension as critical, 0 otherwise. * \param val value of the extension OCTET STRING * \param val_len length of the value data * @@ -245,6 +320,7 @@ int mbedtls_x509write_csr_set_ns_cert_type(mbedtls_x509write_csr *ctx, */ int mbedtls_x509write_csr_set_extension(mbedtls_x509write_csr *ctx, const char *oid, size_t oid_len, + int critical, const unsigned char *val, size_t val_len); /** @@ -264,16 +340,13 @@ void mbedtls_x509write_csr_free(mbedtls_x509write_csr *ctx); * \param ctx CSR to write away * \param buf buffer to write to * \param size size of the buffer - * \param f_rng RNG function (for signature, see note) + * \param f_rng RNG function. This must not be \c NULL. * \param p_rng RNG parameter * * \return length of data written if successful, or a specific * error code * - * \note f_rng may be NULL if RSA is used for signature and the - * signature is made offline (otherwise f_rng is desirable - * for countermeasures against timing attacks). - * ECDSA signatures always require a non-NULL f_rng. + * \note \p f_rng is used for the signature operation. */ int mbedtls_x509write_csr_der(mbedtls_x509write_csr *ctx, unsigned char *buf, size_t size, int (*f_rng)(void *, unsigned char *, size_t), @@ -287,15 +360,12 @@ int mbedtls_x509write_csr_der(mbedtls_x509write_csr *ctx, unsigned char *buf, si * \param ctx CSR to write away * \param buf buffer to write to * \param size size of the buffer - * \param f_rng RNG function (for signature, see note) + * \param f_rng RNG function. This must not be \c NULL. * \param p_rng RNG parameter * * \return 0 if successful, or a specific error code * - * \note f_rng may be NULL if RSA is used for signature and the - * signature is made offline (otherwise f_rng is desirable - * for countermeasures against timing attacks). - * ECDSA signatures always require a non-NULL f_rng. + * \note \p f_rng is used for the signature operation. */ int mbedtls_x509write_csr_pem(mbedtls_x509write_csr *ctx, unsigned char *buf, size_t size, int (*f_rng)(void *, unsigned char *, size_t), diff --git a/vendor/mbedtls/include/mbedtls/xtea.h b/vendor/mbedtls/include/mbedtls/xtea.h deleted file mode 100644 index 9b12a1bb52..0000000000 --- a/vendor/mbedtls/include/mbedtls/xtea.h +++ /dev/null @@ -1,138 +0,0 @@ -/** - * \file xtea.h - * - * \brief XTEA block cipher (32-bit) - */ -/* - * Copyright The Mbed TLS Contributors - * SPDX-License-Identifier: Apache-2.0 - * - * Licensed under the Apache License, Version 2.0 (the "License"); you may - * not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT - * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ -#ifndef MBEDTLS_XTEA_H -#define MBEDTLS_XTEA_H - -#if !defined(MBEDTLS_CONFIG_FILE) -#include "mbedtls/config.h" -#else -#include MBEDTLS_CONFIG_FILE -#endif - -#include -#include - -#define MBEDTLS_XTEA_ENCRYPT 1 -#define MBEDTLS_XTEA_DECRYPT 0 - -/** The data input has an invalid length. */ -#define MBEDTLS_ERR_XTEA_INVALID_INPUT_LENGTH -0x0028 - -/* MBEDTLS_ERR_XTEA_HW_ACCEL_FAILED is deprecated and should not be used. */ -/** XTEA hardware accelerator failed. */ -#define MBEDTLS_ERR_XTEA_HW_ACCEL_FAILED -0x0029 - -#ifdef __cplusplus -extern "C" { -#endif - -#if !defined(MBEDTLS_XTEA_ALT) -// Regular implementation -// - -/** - * \brief XTEA context structure - */ -typedef struct mbedtls_xtea_context { - uint32_t k[4]; /*!< key */ -} -mbedtls_xtea_context; - -#else /* MBEDTLS_XTEA_ALT */ -#include "xtea_alt.h" -#endif /* MBEDTLS_XTEA_ALT */ - -/** - * \brief Initialize XTEA context - * - * \param ctx XTEA context to be initialized - */ -void mbedtls_xtea_init(mbedtls_xtea_context *ctx); - -/** - * \brief Clear XTEA context - * - * \param ctx XTEA context to be cleared - */ -void mbedtls_xtea_free(mbedtls_xtea_context *ctx); - -/** - * \brief XTEA key schedule - * - * \param ctx XTEA context to be initialized - * \param key the secret key - */ -void mbedtls_xtea_setup(mbedtls_xtea_context *ctx, const unsigned char key[16]); - -/** - * \brief XTEA cipher function - * - * \param ctx XTEA context - * \param mode MBEDTLS_XTEA_ENCRYPT or MBEDTLS_XTEA_DECRYPT - * \param input 8-byte input block - * \param output 8-byte output block - * - * \return 0 if successful - */ -int mbedtls_xtea_crypt_ecb(mbedtls_xtea_context *ctx, - int mode, - const unsigned char input[8], - unsigned char output[8]); - -#if defined(MBEDTLS_CIPHER_MODE_CBC) -/** - * \brief XTEA CBC cipher function - * - * \param ctx XTEA context - * \param mode MBEDTLS_XTEA_ENCRYPT or MBEDTLS_XTEA_DECRYPT - * \param length the length of input, multiple of 8 - * \param iv initialization vector for CBC mode - * \param input input block - * \param output output block - * - * \return 0 if successful, - * MBEDTLS_ERR_XTEA_INVALID_INPUT_LENGTH if the length % 8 != 0 - */ -int mbedtls_xtea_crypt_cbc(mbedtls_xtea_context *ctx, - int mode, - size_t length, - unsigned char iv[8], - const unsigned char *input, - unsigned char *output); -#endif /* MBEDTLS_CIPHER_MODE_CBC */ - -#if defined(MBEDTLS_SELF_TEST) - -/** - * \brief Checkup routine - * - * \return 0 if successful, or 1 if the test failed - */ -int mbedtls_xtea_self_test(int verbose); - -#endif /* MBEDTLS_SELF_TEST */ - -#ifdef __cplusplus -} -#endif - -#endif /* xtea.h */ diff --git a/vendor/mbedtls/include/psa/build_info.h b/vendor/mbedtls/include/psa/build_info.h new file mode 100644 index 0000000000..3ee6cd7b1b --- /dev/null +++ b/vendor/mbedtls/include/psa/build_info.h @@ -0,0 +1,20 @@ +/** + * \file psa/build_info.h + * + * \brief Build-time PSA configuration info + * + * Include this file if you need to depend on the + * configuration options defined in mbedtls_config.h or MBEDTLS_CONFIG_FILE + * in PSA cryptography core specific files. + */ +/* + * Copyright The Mbed TLS Contributors + * SPDX-License-Identifier: Apache-2.0 OR GPL-2.0-or-later + */ + +#ifndef PSA_CRYPTO_BUILD_INFO_H +#define PSA_CRYPTO_BUILD_INFO_H + +#include "mbedtls/build_info.h" + +#endif /* PSA_CRYPTO_BUILD_INFO_H */ diff --git a/vendor/mbedtls/include/psa/crypto.h b/vendor/mbedtls/include/psa/crypto.h index 3c1c109a94..7083bd911b 100644 --- a/vendor/mbedtls/include/psa/crypto.h +++ b/vendor/mbedtls/include/psa/crypto.h @@ -4,25 +4,17 @@ */ /* * Copyright The Mbed TLS Contributors - * SPDX-License-Identifier: Apache-2.0 - * - * Licensed under the Apache License, Version 2.0 (the "License"); you may - * not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT - * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. + * SPDX-License-Identifier: Apache-2.0 OR GPL-2.0-or-later */ #ifndef PSA_CRYPTO_H #define PSA_CRYPTO_H +#if defined(MBEDTLS_PSA_CRYPTO_PLATFORM_FILE) +#include MBEDTLS_PSA_CRYPTO_PLATFORM_FILE +#else #include "crypto_platform.h" +#endif #include @@ -112,12 +104,6 @@ psa_status_t psa_crypto_init(void); * This macro returns a suitable initializer for a key attribute structure * of type #psa_key_attributes_t. */ -#ifdef __DOXYGEN_ONLY__ -/* This is an example definition for documentation purposes. - * Implementations should define a suitable value in `crypto_struct.h`. - */ -#define PSA_KEY_ATTRIBUTES_INIT { 0 } -#endif /** Return an initial value for a key attributes structure. */ @@ -133,8 +119,9 @@ static psa_key_attributes_t psa_key_attributes_init(void); * value in the structure. * The persistent key will be written to storage when the attribute * structure is passed to a key creation function such as - * psa_import_key(), psa_generate_key(), - * psa_key_derivation_output_key() or psa_copy_key(). + * psa_import_key(), psa_generate_key(), psa_generate_key_ext(), + * psa_key_derivation_output_key(), psa_key_derivation_output_key_ext() + * or psa_copy_key(). * * This function may be declared as `static` (i.e. without external * linkage). This function may be provided as a function-like macro, @@ -177,8 +164,9 @@ static void mbedtls_set_key_owner_id(psa_key_attributes_t *attributes, * value in the structure. * The persistent key will be written to storage when the attribute * structure is passed to a key creation function such as - * psa_import_key(), psa_generate_key(), - * psa_key_derivation_output_key() or psa_copy_key(). + * psa_import_key(), psa_generate_key(), psa_generate_key_ext(), + * psa_key_derivation_output_key(), psa_key_derivation_output_key_ext() + * or psa_copy_key(). * * This function may be declared as `static` (i.e. without external * linkage). This function may be provided as a function-like macro, @@ -531,7 +519,7 @@ psa_status_t psa_copy_key(mbedtls_svc_key_id_t source_key, * * This function destroys a key from both volatile * memory and, if applicable, non-volatile storage. Implementations shall - * make a best effort to ensure that that the key material cannot be recovered. + * make a best effort to ensure that the key material cannot be recovered. * * This function also erases any metadata such as policies and frees * resources associated with the key. @@ -539,6 +527,11 @@ psa_status_t psa_copy_key(mbedtls_svc_key_id_t source_key, * If a key is currently in use in a multipart operation, then destroying the * key will cause the multipart operation to fail. * + * \warning We can only guarantee that the the key material will + * eventually be wiped from memory. With threading enabled + * and during concurrent execution, copies of the key material may + * still exist until all threads have finished using the key. + * * \param key Identifier of the key to erase. If this is \c 0, do nothing and * return #PSA_SUCCESS. * @@ -931,8 +924,8 @@ psa_status_t psa_hash_compare(psa_algorithm_t alg, * \endcode * * This is an implementation-defined \c struct. Applications should not - * make any assumptions about the content of this structure except - * as directed by the documentation of a specific implementation. */ + * make any assumptions about the content of this structure. + * Implementation details can change in future versions without notice. */ typedef struct psa_hash_operation_s psa_hash_operation_t; /** \def PSA_HASH_OPERATION_INIT @@ -940,12 +933,6 @@ typedef struct psa_hash_operation_s psa_hash_operation_t; * This macro returns a suitable initializer for a hash operation object * of type #psa_hash_operation_t. */ -#ifdef __DOXYGEN_ONLY__ -/* This is an example definition for documentation purposes. - * Implementations should define a suitable value in `crypto_struct.h`. - */ -#define PSA_HASH_OPERATION_INIT { 0 } -#endif /** Return an initial value for a hash operation object. */ @@ -1294,9 +1281,10 @@ psa_status_t psa_mac_verify(mbedtls_svc_key_id_t key, * operation = psa_mac_operation_init(); * \endcode * + * * This is an implementation-defined \c struct. Applications should not - * make any assumptions about the content of this structure except - * as directed by the documentation of a specific implementation. */ + * make any assumptions about the content of this structure. + * Implementation details can change in future versions without notice. */ typedef struct psa_mac_operation_s psa_mac_operation_t; /** \def PSA_MAC_OPERATION_INIT @@ -1304,12 +1292,6 @@ typedef struct psa_mac_operation_s psa_mac_operation_t; * This macro returns a suitable initializer for a MAC operation object of type * #psa_mac_operation_t. */ -#ifdef __DOXYGEN_ONLY__ -/* This is an example definition for documentation purposes. - * Implementations should define a suitable value in `crypto_struct.h`. - */ -#define PSA_MAC_OPERATION_INIT { 0 } -#endif /** Return an initial value for a MAC operation object. */ @@ -1714,8 +1696,8 @@ psa_status_t psa_cipher_decrypt(mbedtls_svc_key_id_t key, * \endcode * * This is an implementation-defined \c struct. Applications should not - * make any assumptions about the content of this structure except - * as directed by the documentation of a specific implementation. */ + * make any assumptions about the content of this structure. + * Implementation details can change in future versions without notice. */ typedef struct psa_cipher_operation_s psa_cipher_operation_t; /** \def PSA_CIPHER_OPERATION_INIT @@ -1723,12 +1705,6 @@ typedef struct psa_cipher_operation_s psa_cipher_operation_t; * This macro returns a suitable initializer for a cipher operation object of * type #psa_cipher_operation_t. */ -#ifdef __DOXYGEN_ONLY__ -/* This is an example definition for documentation purposes. - * Implementations should define a suitable value in `crypto_struct.h`. - */ -#define PSA_CIPHER_OPERATION_INIT { 0 } -#endif /** Return an initial value for a cipher operation object. */ @@ -2238,8 +2214,8 @@ psa_status_t psa_aead_decrypt(mbedtls_svc_key_id_t key, * \endcode * * This is an implementation-defined \c struct. Applications should not - * make any assumptions about the content of this structure except - * as directed by the documentation of a specific implementation. */ + * make any assumptions about the content of this structure. + * Implementation details can change in future versions without notice. */ typedef struct psa_aead_operation_s psa_aead_operation_t; /** \def PSA_AEAD_OPERATION_INIT @@ -2247,12 +2223,6 @@ typedef struct psa_aead_operation_s psa_aead_operation_t; * This macro returns a suitable initializer for an AEAD operation object of * type #psa_aead_operation_t. */ -#ifdef __DOXYGEN_ONLY__ -/* This is an example definition for documentation purposes. - * Implementations should define a suitable value in `crypto_struct.h`. - */ -#define PSA_AEAD_OPERATION_INIT { 0 } -#endif /** Return an initial value for an AEAD operation object. */ @@ -2861,7 +2831,7 @@ psa_status_t psa_aead_abort(psa_aead_operation_t *operation); * * \note To perform a multi-part hash-and-sign signature algorithm, first use * a multi-part hash operation and then pass the resulting hash to - * psa_sign_hash(). PSA_ALG_SIGN_GET_HASH(\p alg) can be used to determine the + * psa_sign_hash(). PSA_ALG_GET_HASH(\p alg) can be used to determine the * hash algorithm to use. * * \param[in] key Identifier of the key to use for the operation. @@ -2927,7 +2897,7 @@ psa_status_t psa_sign_message(mbedtls_svc_key_id_t key, * \note To perform a multi-part hash-and-sign signature verification * algorithm, first use a multi-part hash operation to hash the message * and then pass the resulting hash to psa_verify_hash(). - * PSA_ALG_SIGN_GET_HASH(\p alg) can be used to determine the hash algorithm + * PSA_ALG_GET_HASH(\p alg) can be used to determine the hash algorithm * to use. * * \param[in] key Identifier of the key to use for the operation. @@ -3230,8 +3200,8 @@ psa_status_t psa_asymmetric_decrypt(mbedtls_svc_key_id_t key, * \endcode * * This is an implementation-defined \c struct. Applications should not - * make any assumptions about the content of this structure except - * as directed by the documentation of a specific implementation. + * make any assumptions about the content of this structure. + * Implementation details can change in future versions without notice. */ typedef struct psa_key_derivation_s psa_key_derivation_operation_t; @@ -3240,12 +3210,6 @@ typedef struct psa_key_derivation_s psa_key_derivation_operation_t; * This macro returns a suitable initializer for a key derivation operation * object of type #psa_key_derivation_operation_t. */ -#ifdef __DOXYGEN_ONLY__ -/* This is an example definition for documentation purposes. - * Implementations should define a suitable value in `crypto_struct.h`. - */ -#define PSA_KEY_DERIVATION_OPERATION_INIT { 0 } -#endif /** Return an initial value for a key derivation operation object. */ @@ -3269,7 +3233,8 @@ static psa_key_derivation_operation_t psa_key_derivation_operation_init(void); * psa_key_derivation_set_capacity(). You may do this before, in the middle * of or after providing inputs. For some algorithms, this step is mandatory * because the output depends on the maximum capacity. - * -# To derive a key, call psa_key_derivation_output_key(). + * -# To derive a key, call psa_key_derivation_output_key() or + * psa_key_derivation_output_key_ext(). * To derive a byte string for a different purpose, call * psa_key_derivation_output_bytes(). * Successive calls to these functions use successive output bytes @@ -3419,6 +3384,48 @@ psa_status_t psa_key_derivation_input_bytes( const uint8_t *data, size_t data_length); +/** Provide a numeric input for key derivation or key agreement. + * + * Which inputs are required and in what order depends on the algorithm. + * However, when an algorithm requires a particular order, numeric inputs + * usually come first as they tend to be configuration parameters. + * Refer to the documentation of each key derivation or key agreement + * algorithm for information. + * + * This function is used for inputs which are fixed-size non-negative + * integers. + * + * If this function returns an error status, the operation enters an error + * state and must be aborted by calling psa_key_derivation_abort(). + * + * \param[in,out] operation The key derivation operation object to use. + * It must have been set up with + * psa_key_derivation_setup() and must not + * have produced any output yet. + * \param step Which step the input data is for. + * \param[in] value The value of the numeric input. + * + * \retval #PSA_SUCCESS + * Success. + * \retval #PSA_ERROR_INVALID_ARGUMENT + * \c step is not compatible with the operation's algorithm, or + * \c step does not allow numeric inputs. + * \retval #PSA_ERROR_INSUFFICIENT_MEMORY \emptydescription + * \retval #PSA_ERROR_COMMUNICATION_FAILURE \emptydescription + * \retval #PSA_ERROR_HARDWARE_FAILURE \emptydescription + * \retval #PSA_ERROR_CORRUPTION_DETECTED \emptydescription + * \retval #PSA_ERROR_STORAGE_FAILURE \emptydescription + * \retval #PSA_ERROR_BAD_STATE + * The operation state is not valid for this input \p step, or + * the library has not been previously initialized by psa_crypto_init(). + * It is implementation-dependent whether a failure to initialize + * results in this error code. + */ +psa_status_t psa_key_derivation_input_integer( + psa_key_derivation_operation_t *operation, + psa_key_derivation_step_t step, + uint64_t value); + /** Provide an input for key derivation in the form of a key. * * Which inputs are required and in what order depends on the algorithm. @@ -3443,12 +3450,30 @@ psa_status_t psa_key_derivation_input_bytes( * \param step Which step the input data is for. * \param key Identifier of the key. It must have an * appropriate type for step and must allow the - * usage #PSA_KEY_USAGE_DERIVE. + * usage #PSA_KEY_USAGE_DERIVE or + * #PSA_KEY_USAGE_VERIFY_DERIVATION (see note) + * and the algorithm used by the operation. + * + * \note Once all inputs steps are completed, the operations will allow: + * - psa_key_derivation_output_bytes() if each input was either a direct input + * or a key with #PSA_KEY_USAGE_DERIVE set; + * - psa_key_derivation_output_key() or psa_key_derivation_output_key_ext() + * if the input for step + * #PSA_KEY_DERIVATION_INPUT_SECRET or #PSA_KEY_DERIVATION_INPUT_PASSWORD + * was from a key slot with #PSA_KEY_USAGE_DERIVE and each other input was + * either a direct input or a key with #PSA_KEY_USAGE_DERIVE set; + * - psa_key_derivation_verify_bytes() if each input was either a direct input + * or a key with #PSA_KEY_USAGE_VERIFY_DERIVATION set; + * - psa_key_derivation_verify_key() under the same conditions as + * psa_key_derivation_verify_bytes(). * * \retval #PSA_SUCCESS * Success. * \retval #PSA_ERROR_INVALID_HANDLE \emptydescription - * \retval #PSA_ERROR_NOT_PERMITTED \emptydescription + * \retval #PSA_ERROR_NOT_PERMITTED + * The key allows neither #PSA_KEY_USAGE_DERIVE nor + * #PSA_KEY_USAGE_VERIFY_DERIVATION, or it doesn't allow this + * algorithm. * \retval #PSA_ERROR_INVALID_ARGUMENT * \c step is not compatible with the operation's algorithm, or * \c step does not allow key inputs of the given type @@ -3557,6 +3582,9 @@ psa_status_t psa_key_derivation_key_agreement( * \param output_length Number of bytes to output. * * \retval #PSA_SUCCESS \emptydescription + * \retval #PSA_ERROR_NOT_PERMITTED + * One of the inputs was a key whose policy didn't allow + * #PSA_KEY_USAGE_DERIVE. * \retval #PSA_ERROR_INSUFFICIENT_DATA * The operation's capacity was less than * \p output_length bytes. Note that in this case, @@ -3613,11 +3641,11 @@ psa_status_t psa_key_derivation_output_bytes( * The following key types defined in this specification follow this scheme: * * - #PSA_KEY_TYPE_AES; - * - #PSA_KEY_TYPE_ARC4; * - #PSA_KEY_TYPE_ARIA; * - #PSA_KEY_TYPE_CAMELLIA; * - #PSA_KEY_TYPE_DERIVE; - * - #PSA_KEY_TYPE_HMAC. + * - #PSA_KEY_TYPE_HMAC; + * - #PSA_KEY_TYPE_PASSWORD_HASH. * * - For ECC keys on a Montgomery elliptic curve * (#PSA_KEY_TYPE_ECC_KEY_PAIR(\c curve) where \c curve designates a @@ -3678,7 +3706,16 @@ psa_status_t psa_key_derivation_output_bytes( * Future versions of this specification may include additional restrictions * on the derived key based on the attributes and strength of the secret key. * + * \note This function is equivalent to calling + * psa_key_derivation_output_key_ext() + * with the production parameters #PSA_KEY_PRODUCTION_PARAMETERS_INIT + * and `params_data_length == 0` (i.e. `params->data` is empty). + * * \param[in] attributes The attributes for the new key. + * If the key type to be created is + * #PSA_KEY_TYPE_PASSWORD_HASH then the algorithm in + * the policy must be the same as in the current + * operation. * \param[in,out] operation The key derivation operation object to read from. * \param[out] key On success, an identifier for the newly created * key. For persistent keys, this is the key @@ -3703,8 +3740,10 @@ psa_status_t psa_key_derivation_output_bytes( * \retval #PSA_ERROR_INVALID_ARGUMENT * The provided key attributes are not valid for the operation. * \retval #PSA_ERROR_NOT_PERMITTED - * The #PSA_KEY_DERIVATION_INPUT_SECRET input was not provided through - * a key. + * The #PSA_KEY_DERIVATION_INPUT_SECRET or + * #PSA_KEY_DERIVATION_INPUT_PASSWORD input was not provided through a + * key; or one of the inputs was a key whose policy didn't allow + * #PSA_KEY_USAGE_DERIVE. * \retval #PSA_ERROR_INSUFFICIENT_MEMORY \emptydescription * \retval #PSA_ERROR_INSUFFICIENT_STORAGE \emptydescription * \retval #PSA_ERROR_COMMUNICATION_FAILURE \emptydescription @@ -3725,6 +3764,205 @@ psa_status_t psa_key_derivation_output_key( psa_key_derivation_operation_t *operation, mbedtls_svc_key_id_t *key); +/** Derive a key from an ongoing key derivation operation with custom + * production parameters. + * + * See the description of psa_key_derivation_out_key() for the operation of + * this function with the default production parameters. + * Mbed TLS currently does not currently support any non-default production + * parameters. + * + * \note This function is experimental and may change in future minor + * versions of Mbed TLS. + * + * \param[in] attributes The attributes for the new key. + * If the key type to be created is + * #PSA_KEY_TYPE_PASSWORD_HASH then the algorithm in + * the policy must be the same as in the current + * operation. + * \param[in,out] operation The key derivation operation object to read from. + * \param[in] params Customization parameters for the key derivation. + * When this is #PSA_KEY_PRODUCTION_PARAMETERS_INIT + * with \p params_data_length = 0, + * this function is equivalent to + * psa_key_derivation_output_key(). + * Mbed TLS currently only supports the default + * production parameters, i.e. + * #PSA_KEY_PRODUCTION_PARAMETERS_INIT, + * for all key types. + * \param params_data_length + * Length of `params->data` in bytes. + * \param[out] key On success, an identifier for the newly created + * key. For persistent keys, this is the key + * identifier defined in \p attributes. + * \c 0 on failure. + * + * \retval #PSA_SUCCESS + * Success. + * If the key is persistent, the key material and the key's metadata + * have been saved to persistent storage. + * \retval #PSA_ERROR_ALREADY_EXISTS + * This is an attempt to create a persistent key, and there is + * already a persistent key with the given identifier. + * \retval #PSA_ERROR_INSUFFICIENT_DATA + * There was not enough data to create the desired key. + * Note that in this case, no output is written to the output buffer. + * The operation's capacity is set to 0, thus subsequent calls to + * this function will not succeed, even with a smaller output buffer. + * \retval #PSA_ERROR_NOT_SUPPORTED + * The key type or key size is not supported, either by the + * implementation in general or in this particular location. + * \retval #PSA_ERROR_INVALID_ARGUMENT + * The provided key attributes are not valid for the operation. + * \retval #PSA_ERROR_NOT_PERMITTED + * The #PSA_KEY_DERIVATION_INPUT_SECRET or + * #PSA_KEY_DERIVATION_INPUT_PASSWORD input was not provided through a + * key; or one of the inputs was a key whose policy didn't allow + * #PSA_KEY_USAGE_DERIVE. + * \retval #PSA_ERROR_INSUFFICIENT_MEMORY \emptydescription + * \retval #PSA_ERROR_INSUFFICIENT_STORAGE \emptydescription + * \retval #PSA_ERROR_COMMUNICATION_FAILURE \emptydescription + * \retval #PSA_ERROR_HARDWARE_FAILURE \emptydescription + * \retval #PSA_ERROR_CORRUPTION_DETECTED \emptydescription + * \retval #PSA_ERROR_DATA_INVALID \emptydescription + * \retval #PSA_ERROR_DATA_CORRUPT \emptydescription + * \retval #PSA_ERROR_STORAGE_FAILURE \emptydescription + * \retval #PSA_ERROR_BAD_STATE + * The operation state is not valid (it must be active and completed + * all required input steps), or the library has not been previously + * initialized by psa_crypto_init(). + * It is implementation-dependent whether a failure to initialize + * results in this error code. + */ +psa_status_t psa_key_derivation_output_key_ext( + const psa_key_attributes_t *attributes, + psa_key_derivation_operation_t *operation, + const psa_key_production_parameters_t *params, + size_t params_data_length, + mbedtls_svc_key_id_t *key); + +/** Compare output data from a key derivation operation to an expected value. + * + * This function calculates output bytes from a key derivation algorithm and + * compares those bytes to an expected value in constant time. + * If you view the key derivation's output as a stream of bytes, this + * function destructively reads the expected number of bytes from the + * stream before comparing them. + * The operation's capacity decreases by the number of bytes read. + * + * This is functionally equivalent to the following code: + * \code + * psa_key_derivation_output_bytes(operation, tmp, output_length); + * if (memcmp(output, tmp, output_length) != 0) + * return PSA_ERROR_INVALID_SIGNATURE; + * \endcode + * except (1) it works even if the key's policy does not allow outputting the + * bytes, and (2) the comparison will be done in constant time. + * + * If this function returns an error status other than + * #PSA_ERROR_INSUFFICIENT_DATA or #PSA_ERROR_INVALID_SIGNATURE, + * the operation enters an error state and must be aborted by calling + * psa_key_derivation_abort(). + * + * \param[in,out] operation The key derivation operation object to read from. + * \param[in] expected_output Buffer containing the expected derivation output. + * \param output_length Length of the expected output; this is also the + * number of bytes that will be read. + * + * \retval #PSA_SUCCESS \emptydescription + * \retval #PSA_ERROR_INVALID_SIGNATURE + * The output was read successfully, but it differs from the expected + * output. + * \retval #PSA_ERROR_NOT_PERMITTED + * One of the inputs was a key whose policy didn't allow + * #PSA_KEY_USAGE_VERIFY_DERIVATION. + * \retval #PSA_ERROR_INSUFFICIENT_DATA + * The operation's capacity was less than + * \p output_length bytes. Note that in this case, + * the operation's capacity is set to 0, thus + * subsequent calls to this function will not + * succeed, even with a smaller expected output. + * \retval #PSA_ERROR_INSUFFICIENT_MEMORY \emptydescription + * \retval #PSA_ERROR_COMMUNICATION_FAILURE \emptydescription + * \retval #PSA_ERROR_HARDWARE_FAILURE \emptydescription + * \retval #PSA_ERROR_CORRUPTION_DETECTED \emptydescription + * \retval #PSA_ERROR_STORAGE_FAILURE \emptydescription + * \retval #PSA_ERROR_BAD_STATE + * The operation state is not valid (it must be active and completed + * all required input steps), or the library has not been previously + * initialized by psa_crypto_init(). + * It is implementation-dependent whether a failure to initialize + * results in this error code. + */ +psa_status_t psa_key_derivation_verify_bytes( + psa_key_derivation_operation_t *operation, + const uint8_t *expected_output, + size_t output_length); + +/** Compare output data from a key derivation operation to an expected value + * stored in a key object. + * + * This function calculates output bytes from a key derivation algorithm and + * compares those bytes to an expected value, provided as key of type + * #PSA_KEY_TYPE_PASSWORD_HASH. + * If you view the key derivation's output as a stream of bytes, this + * function destructively reads the number of bytes corresponding to the + * length of the expected value from the stream before comparing them. + * The operation's capacity decreases by the number of bytes read. + * + * This is functionally equivalent to exporting the key and calling + * psa_key_derivation_verify_bytes() on the result, except that it + * works even if the key cannot be exported. + * + * If this function returns an error status other than + * #PSA_ERROR_INSUFFICIENT_DATA or #PSA_ERROR_INVALID_SIGNATURE, + * the operation enters an error state and must be aborted by calling + * psa_key_derivation_abort(). + * + * \param[in,out] operation The key derivation operation object to read from. + * \param[in] expected A key of type #PSA_KEY_TYPE_PASSWORD_HASH + * containing the expected output. Its policy must + * include the #PSA_KEY_USAGE_VERIFY_DERIVATION flag + * and the permitted algorithm must match the + * operation. The value of this key was likely + * computed by a previous call to + * psa_key_derivation_output_key() or + * psa_key_derivation_output_key_ext(). + * + * \retval #PSA_SUCCESS \emptydescription + * \retval #PSA_ERROR_INVALID_SIGNATURE + * The output was read successfully, but if differs from the expected + * output. + * \retval #PSA_ERROR_INVALID_HANDLE + * The key passed as the expected value does not exist. + * \retval #PSA_ERROR_INVALID_ARGUMENT + * The key passed as the expected value has an invalid type. + * \retval #PSA_ERROR_NOT_PERMITTED + * The key passed as the expected value does not allow this usage or + * this algorithm; or one of the inputs was a key whose policy didn't + * allow #PSA_KEY_USAGE_VERIFY_DERIVATION. + * \retval #PSA_ERROR_INSUFFICIENT_DATA + * The operation's capacity was less than + * the length of the expected value. In this case, + * the operation's capacity is set to 0, thus + * subsequent calls to this function will not + * succeed, even with a smaller expected output. + * \retval #PSA_ERROR_INSUFFICIENT_MEMORY \emptydescription + * \retval #PSA_ERROR_COMMUNICATION_FAILURE \emptydescription + * \retval #PSA_ERROR_HARDWARE_FAILURE \emptydescription + * \retval #PSA_ERROR_CORRUPTION_DETECTED \emptydescription + * \retval #PSA_ERROR_STORAGE_FAILURE \emptydescription + * \retval #PSA_ERROR_BAD_STATE + * The operation state is not valid (it must be active and completed + * all required input steps), or the library has not been previously + * initialized by psa_crypto_init(). + * It is implementation-dependent whether a failure to initialize + * results in this error code. + */ +psa_status_t psa_key_derivation_verify_key( + psa_key_derivation_operation_t *operation, + psa_key_id_t expected); + /** Abort a key derivation operation. * * Aborting an operation frees all associated resources except for the \c @@ -3857,6 +4095,10 @@ psa_status_t psa_generate_random(uint8_t *output, * between 2^{n-1} and 2^n where n is the bit size specified in the * attributes. * + * \note This function is equivalent to calling psa_generate_key_ext() + * with the production parameters #PSA_KEY_PRODUCTION_PARAMETERS_INIT + * and `params_data_length == 0` (i.e. `params->data` is empty). + * * \param[in] attributes The attributes for the new key. * \param[out] key On success, an identifier for the newly created * key. For persistent keys, this is the key @@ -3889,6 +4131,685 @@ psa_status_t psa_generate_random(uint8_t *output, psa_status_t psa_generate_key(const psa_key_attributes_t *attributes, mbedtls_svc_key_id_t *key); +/** + * \brief Generate a key or key pair using custom production parameters. + * + * See the description of psa_generate_key() for the operation of this + * function with the default production parameters. In addition, this function + * supports the following production customizations, described in more detail + * in the documentation of ::psa_key_production_parameters_t: + * + * - RSA keys: generation with a custom public exponent. + * + * \note This function is experimental and may change in future minor + * versions of Mbed TLS. + * + * \param[in] attributes The attributes for the new key. + * \param[in] params Customization parameters for the key generation. + * When this is #PSA_KEY_PRODUCTION_PARAMETERS_INIT + * with \p params_data_length = 0, + * this function is equivalent to + * psa_generate_key(). + * \param params_data_length + * Length of `params->data` in bytes. + * \param[out] key On success, an identifier for the newly created + * key. For persistent keys, this is the key + * identifier defined in \p attributes. + * \c 0 on failure. + * + * \retval #PSA_SUCCESS + * Success. + * If the key is persistent, the key material and the key's metadata + * have been saved to persistent storage. + * \retval #PSA_ERROR_ALREADY_EXISTS + * This is an attempt to create a persistent key, and there is + * already a persistent key with the given identifier. + * \retval #PSA_ERROR_NOT_SUPPORTED \emptydescription + * \retval #PSA_ERROR_INVALID_ARGUMENT \emptydescription + * \retval #PSA_ERROR_INSUFFICIENT_MEMORY \emptydescription + * \retval #PSA_ERROR_INSUFFICIENT_ENTROPY \emptydescription + * \retval #PSA_ERROR_COMMUNICATION_FAILURE \emptydescription + * \retval #PSA_ERROR_HARDWARE_FAILURE \emptydescription + * \retval #PSA_ERROR_CORRUPTION_DETECTED \emptydescription + * \retval #PSA_ERROR_INSUFFICIENT_STORAGE \emptydescription + * \retval #PSA_ERROR_DATA_INVALID \emptydescription + * \retval #PSA_ERROR_DATA_CORRUPT \emptydescription + * \retval #PSA_ERROR_STORAGE_FAILURE \emptydescription + * \retval #PSA_ERROR_BAD_STATE + * The library has not been previously initialized by psa_crypto_init(). + * It is implementation-dependent whether a failure to initialize + * results in this error code. + */ +psa_status_t psa_generate_key_ext(const psa_key_attributes_t *attributes, + const psa_key_production_parameters_t *params, + size_t params_data_length, + mbedtls_svc_key_id_t *key); + +/**@}*/ + +/** \defgroup interruptible_hash Interruptible sign/verify hash + * @{ + */ + +/** The type of the state data structure for interruptible hash + * signing operations. + * + * Before calling any function on a sign hash operation object, the + * application must initialize it by any of the following means: + * - Set the structure to all-bits-zero, for example: + * \code + * psa_sign_hash_interruptible_operation_t operation; + * memset(&operation, 0, sizeof(operation)); + * \endcode + * - Initialize the structure to logical zero values, for example: + * \code + * psa_sign_hash_interruptible_operation_t operation = {0}; + * \endcode + * - Initialize the structure to the initializer + * #PSA_SIGN_HASH_INTERRUPTIBLE_OPERATION_INIT, for example: + * \code + * psa_sign_hash_interruptible_operation_t operation = + * PSA_SIGN_HASH_INTERRUPTIBLE_OPERATION_INIT; + * \endcode + * - Assign the result of the function + * psa_sign_hash_interruptible_operation_init() to the structure, for + * example: + * \code + * psa_sign_hash_interruptible_operation_t operation; + * operation = psa_sign_hash_interruptible_operation_init(); + * \endcode + * + * This is an implementation-defined \c struct. Applications should not + * make any assumptions about the content of this structure. + * Implementation details can change in future versions without notice. */ +typedef struct psa_sign_hash_interruptible_operation_s psa_sign_hash_interruptible_operation_t; + +/** The type of the state data structure for interruptible hash + * verification operations. + * + * Before calling any function on a sign hash operation object, the + * application must initialize it by any of the following means: + * - Set the structure to all-bits-zero, for example: + * \code + * psa_verify_hash_interruptible_operation_t operation; + * memset(&operation, 0, sizeof(operation)); + * \endcode + * - Initialize the structure to logical zero values, for example: + * \code + * psa_verify_hash_interruptible_operation_t operation = {0}; + * \endcode + * - Initialize the structure to the initializer + * #PSA_VERIFY_HASH_INTERRUPTIBLE_OPERATION_INIT, for example: + * \code + * psa_verify_hash_interruptible_operation_t operation = + * PSA_VERIFY_HASH_INTERRUPTIBLE_OPERATION_INIT; + * \endcode + * - Assign the result of the function + * psa_verify_hash_interruptible_operation_init() to the structure, for + * example: + * \code + * psa_verify_hash_interruptible_operation_t operation; + * operation = psa_verify_hash_interruptible_operation_init(); + * \endcode + * + * This is an implementation-defined \c struct. Applications should not + * make any assumptions about the content of this structure. + * Implementation details can change in future versions without notice. */ +typedef struct psa_verify_hash_interruptible_operation_s psa_verify_hash_interruptible_operation_t; + +/** + * \brief Set the maximum number of ops allowed to be + * executed by an interruptible function in a + * single call. + * + * \warning This is a beta API, and thus subject to change + * at any point. It is not bound by the usual + * interface stability promises. + * + * \note The time taken to execute a single op is + * implementation specific and depends on + * software, hardware, the algorithm, key type and + * curve chosen. Even within a single operation, + * successive ops can take differing amounts of + * time. The only guarantee is that lower values + * for \p max_ops means functions will block for a + * lesser maximum amount of time. The functions + * \c psa_sign_interruptible_get_num_ops() and + * \c psa_verify_interruptible_get_num_ops() are + * provided to help with tuning this value. + * + * \note This value defaults to + * #PSA_INTERRUPTIBLE_MAX_OPS_UNLIMITED, which + * means the whole operation will be done in one + * go, regardless of the number of ops required. + * + * \note If more ops are needed to complete a + * computation, #PSA_OPERATION_INCOMPLETE will be + * returned by the function performing the + * computation. It is then the caller's + * responsibility to either call again with the + * same operation context until it returns 0 or an + * error code; or to call the relevant abort + * function if the answer is no longer required. + * + * \note The interpretation of \p max_ops is also + * implementation defined. On a hard real time + * system, this can indicate a hard deadline, as a + * real-time system needs a guarantee of not + * spending more than X time, however care must be + * taken in such an implementation to avoid the + * situation whereby calls just return, not being + * able to do any actual work within the allotted + * time. On a non-real-time system, the + * implementation can be more relaxed, but again + * whether this number should be interpreted as as + * hard or soft limit or even whether a less than + * or equals as regards to ops executed in a + * single call is implementation defined. + * + * \note For keys in local storage when no accelerator + * driver applies, please see also the + * documentation for \c mbedtls_ecp_set_max_ops(), + * which is the internal implementation in these + * cases. + * + * \warning With implementations that interpret this number + * as a hard limit, setting this number too small + * may result in an infinite loop, whereby each + * call results in immediate return with no ops + * done (as there is not enough time to execute + * any), and thus no result will ever be achieved. + * + * \note This only applies to functions whose + * documentation mentions they may return + * #PSA_OPERATION_INCOMPLETE. + * + * \param max_ops The maximum number of ops to be executed in a + * single call. This can be a number from 0 to + * #PSA_INTERRUPTIBLE_MAX_OPS_UNLIMITED, where 0 + * is the least amount of work done per call. + */ +void psa_interruptible_set_max_ops(uint32_t max_ops); + +/** + * \brief Get the maximum number of ops allowed to be + * executed by an interruptible function in a + * single call. This will return the last + * value set by + * \c psa_interruptible_set_max_ops() or + * #PSA_INTERRUPTIBLE_MAX_OPS_UNLIMITED if + * that function has never been called. + * + * \warning This is a beta API, and thus subject to change + * at any point. It is not bound by the usual + * interface stability promises. + * + * \return Maximum number of ops allowed to be + * executed by an interruptible function in a + * single call. + */ +uint32_t psa_interruptible_get_max_ops(void); + +/** + * \brief Get the number of ops that a hash signing + * operation has taken so far. If the operation + * has completed, then this will represent the + * number of ops required for the entire + * operation. After initialization or calling + * \c psa_sign_hash_interruptible_abort() on + * the operation, a value of 0 will be returned. + * + * \note This interface is guaranteed re-entrant and + * thus may be called from driver code. + * + * \warning This is a beta API, and thus subject to change + * at any point. It is not bound by the usual + * interface stability promises. + * + * This is a helper provided to help you tune the + * value passed to \c + * psa_interruptible_set_max_ops(). + * + * \param operation The \c psa_sign_hash_interruptible_operation_t + * to use. This must be initialized first. + * + * \return Number of ops that the operation has taken so + * far. + */ +uint32_t psa_sign_hash_get_num_ops( + const psa_sign_hash_interruptible_operation_t *operation); + +/** + * \brief Get the number of ops that a hash verification + * operation has taken so far. If the operation + * has completed, then this will represent the + * number of ops required for the entire + * operation. After initialization or calling \c + * psa_verify_hash_interruptible_abort() on the + * operation, a value of 0 will be returned. + * + * \warning This is a beta API, and thus subject to change + * at any point. It is not bound by the usual + * interface stability promises. + * + * This is a helper provided to help you tune the + * value passed to \c + * psa_interruptible_set_max_ops(). + * + * \param operation The \c + * psa_verify_hash_interruptible_operation_t to + * use. This must be initialized first. + * + * \return Number of ops that the operation has taken so + * far. + */ +uint32_t psa_verify_hash_get_num_ops( + const psa_verify_hash_interruptible_operation_t *operation); + +/** + * \brief Start signing a hash or short message with a + * private key, in an interruptible manner. + * + * \see \c psa_sign_hash_complete() + * + * \warning This is a beta API, and thus subject to change + * at any point. It is not bound by the usual + * interface stability promises. + * + * \note This function combined with \c + * psa_sign_hash_complete() is equivalent to + * \c psa_sign_hash() but + * \c psa_sign_hash_complete() can return early and + * resume according to the limit set with \c + * psa_interruptible_set_max_ops() to reduce the + * maximum time spent in a function call. + * + * \note Users should call \c psa_sign_hash_complete() + * repeatedly on the same context after a + * successful call to this function until \c + * psa_sign_hash_complete() either returns 0 or an + * error. \c psa_sign_hash_complete() will return + * #PSA_OPERATION_INCOMPLETE if there is more work + * to do. Alternatively users can call + * \c psa_sign_hash_abort() at any point if they no + * longer want the result. + * + * \note If this function returns an error status, the + * operation enters an error state and must be + * aborted by calling \c psa_sign_hash_abort(). + * + * \param[in, out] operation The \c psa_sign_hash_interruptible_operation_t + * to use. This must be initialized first. + * + * \param key Identifier of the key to use for the operation. + * It must be an asymmetric key pair. The key must + * allow the usage #PSA_KEY_USAGE_SIGN_HASH. + * \param alg A signature algorithm (\c PSA_ALG_XXX + * value such that #PSA_ALG_IS_SIGN_HASH(\p alg) + * is true), that is compatible with + * the type of \p key. + * \param[in] hash The hash or message to sign. + * \param hash_length Size of the \p hash buffer in bytes. + * + * \retval #PSA_SUCCESS + * The operation started successfully - call \c psa_sign_hash_complete() + * with the same context to complete the operation + * + * \retval #PSA_ERROR_INVALID_HANDLE \emptydescription + * \retval #PSA_ERROR_NOT_PERMITTED + * The key does not have the #PSA_KEY_USAGE_SIGN_HASH flag, or it does + * not permit the requested algorithm. + * \retval #PSA_ERROR_BAD_STATE + * An operation has previously been started on this context, and is + * still in progress. + * \retval #PSA_ERROR_NOT_SUPPORTED \emptydescription + * \retval #PSA_ERROR_INVALID_ARGUMENT \emptydescription + * \retval #PSA_ERROR_INSUFFICIENT_MEMORY \emptydescription + * \retval #PSA_ERROR_COMMUNICATION_FAILURE \emptydescription + * \retval #PSA_ERROR_HARDWARE_FAILURE \emptydescription + * \retval #PSA_ERROR_CORRUPTION_DETECTED \emptydescription + * \retval #PSA_ERROR_STORAGE_FAILURE \emptydescription + * \retval #PSA_ERROR_DATA_CORRUPT \emptydescription + * \retval #PSA_ERROR_DATA_INVALID \emptydescription + * \retval #PSA_ERROR_INSUFFICIENT_ENTROPY \emptydescription + * \retval #PSA_ERROR_BAD_STATE + * The library has not been previously initialized by psa_crypto_init(). + * It is implementation-dependent whether a failure to initialize + * results in this error code. + */ +psa_status_t psa_sign_hash_start( + psa_sign_hash_interruptible_operation_t *operation, + mbedtls_svc_key_id_t key, psa_algorithm_t alg, + const uint8_t *hash, size_t hash_length); + +/** + * \brief Continue and eventually complete the action of + * signing a hash or short message with a private + * key, in an interruptible manner. + * + * \see \c psa_sign_hash_start() + * + * \warning This is a beta API, and thus subject to change + * at any point. It is not bound by the usual + * interface stability promises. + * + * \note This function combined with \c + * psa_sign_hash_start() is equivalent to + * \c psa_sign_hash() but this function can return + * early and resume according to the limit set with + * \c psa_interruptible_set_max_ops() to reduce the + * maximum time spent in a function call. + * + * \note Users should call this function on the same + * operation object repeatedly until it either + * returns 0 or an error. This function will return + * #PSA_OPERATION_INCOMPLETE if there is more work + * to do. Alternatively users can call + * \c psa_sign_hash_abort() at any point if they no + * longer want the result. + * + * \note When this function returns successfully, the + * operation becomes inactive. If this function + * returns an error status, the operation enters an + * error state and must be aborted by calling + * \c psa_sign_hash_abort(). + * + * \param[in, out] operation The \c psa_sign_hash_interruptible_operation_t + * to use. This must be initialized first, and have + * had \c psa_sign_hash_start() called with it + * first. + * + * \param[out] signature Buffer where the signature is to be written. + * \param signature_size Size of the \p signature buffer in bytes. This + * must be appropriate for the selected + * algorithm and key: + * - The required signature size is + * #PSA_SIGN_OUTPUT_SIZE(\c key_type, \c + * key_bits, \c alg) where \c key_type and \c + * key_bits are the type and bit-size + * respectively of key. + * - #PSA_SIGNATURE_MAX_SIZE evaluates to the + * maximum signature size of any supported + * signature algorithm. + * \param[out] signature_length On success, the number of bytes that make up + * the returned signature value. + * + * \retval #PSA_SUCCESS + * Operation completed successfully + * + * \retval #PSA_OPERATION_INCOMPLETE + * Operation was interrupted due to the setting of \c + * psa_interruptible_set_max_ops(). There is still work to be done. + * Call this function again with the same operation object. + * + * \retval #PSA_ERROR_BUFFER_TOO_SMALL + * The size of the \p signature buffer is too small. You can + * determine a sufficient buffer size by calling + * #PSA_SIGN_OUTPUT_SIZE(\c key_type, \c key_bits, \c alg) + * where \c key_type and \c key_bits are the type and bit-size + * respectively of \c key. + * + * \retval #PSA_ERROR_BAD_STATE + * An operation was not previously started on this context via + * \c psa_sign_hash_start(). + * + * \retval #PSA_ERROR_NOT_SUPPORTED \emptydescription + * \retval #PSA_ERROR_INVALID_ARGUMENT \emptydescription + * \retval #PSA_ERROR_INSUFFICIENT_MEMORY \emptydescription + * \retval #PSA_ERROR_COMMUNICATION_FAILURE \emptydescription + * \retval #PSA_ERROR_HARDWARE_FAILURE \emptydescription + * \retval #PSA_ERROR_CORRUPTION_DETECTED \emptydescription + * \retval #PSA_ERROR_STORAGE_FAILURE \emptydescription + * \retval #PSA_ERROR_DATA_CORRUPT \emptydescription + * \retval #PSA_ERROR_DATA_INVALID \emptydescription + * \retval #PSA_ERROR_INSUFFICIENT_ENTROPY \emptydescription + * \retval #PSA_ERROR_BAD_STATE + * The library has either not been previously initialized by + * psa_crypto_init() or you did not previously call + * psa_sign_hash_start() with this operation object. It is + * implementation-dependent whether a failure to initialize results in + * this error code. + */ +psa_status_t psa_sign_hash_complete( + psa_sign_hash_interruptible_operation_t *operation, + uint8_t *signature, size_t signature_size, + size_t *signature_length); + +/** + * \brief Abort a sign hash operation. + * + * \warning This is a beta API, and thus subject to change + * at any point. It is not bound by the usual + * interface stability promises. + * + * \note This function is the only function that clears + * the number of ops completed as part of the + * operation. Please ensure you copy this value via + * \c psa_sign_hash_get_num_ops() if required + * before calling. + * + * \note Aborting an operation frees all associated + * resources except for the \p operation structure + * itself. Once aborted, the operation object can + * be reused for another operation by calling \c + * psa_sign_hash_start() again. + * + * \note You may call this function any time after the + * operation object has been initialized. In + * particular, calling \c psa_sign_hash_abort() + * after the operation has already been terminated + * by a call to \c psa_sign_hash_abort() or + * psa_sign_hash_complete() is safe. + * + * \param[in,out] operation Initialized sign hash operation. + * + * \retval #PSA_SUCCESS + * The operation was aborted successfully. + * + * \retval #PSA_ERROR_NOT_SUPPORTED \emptydescription + * \retval #PSA_ERROR_BAD_STATE + * The library has not been previously initialized by psa_crypto_init(). + * It is implementation-dependent whether a failure to initialize + * results in this error code. + */ +psa_status_t psa_sign_hash_abort( + psa_sign_hash_interruptible_operation_t *operation); + +/** + * \brief Start reading and verifying a hash or short + * message, in an interruptible manner. + * + * \see \c psa_verify_hash_complete() + * + * \warning This is a beta API, and thus subject to change + * at any point. It is not bound by the usual + * interface stability promises. + * + * \note This function combined with \c + * psa_verify_hash_complete() is equivalent to + * \c psa_verify_hash() but \c + * psa_verify_hash_complete() can return early and + * resume according to the limit set with \c + * psa_interruptible_set_max_ops() to reduce the + * maximum time spent in a function. + * + * \note Users should call \c psa_verify_hash_complete() + * repeatedly on the same operation object after a + * successful call to this function until \c + * psa_verify_hash_complete() either returns 0 or + * an error. \c psa_verify_hash_complete() will + * return #PSA_OPERATION_INCOMPLETE if there is + * more work to do. Alternatively users can call + * \c psa_verify_hash_abort() at any point if they + * no longer want the result. + * + * \note If this function returns an error status, the + * operation enters an error state and must be + * aborted by calling \c psa_verify_hash_abort(). + * + * \param[in, out] operation The \c psa_verify_hash_interruptible_operation_t + * to use. This must be initialized first. + * + * \param key Identifier of the key to use for the operation. + * The key must allow the usage + * #PSA_KEY_USAGE_VERIFY_HASH. + * \param alg A signature algorithm (\c PSA_ALG_XXX + * value such that #PSA_ALG_IS_SIGN_HASH(\p alg) + * is true), that is compatible with + * the type of \p key. + * \param[in] hash The hash whose signature is to be verified. + * \param hash_length Size of the \p hash buffer in bytes. + * \param[in] signature Buffer containing the signature to verify. + * \param signature_length Size of the \p signature buffer in bytes. + * + * \retval #PSA_SUCCESS + * The operation started successfully - please call \c + * psa_verify_hash_complete() with the same context to complete the + * operation. + * + * \retval #PSA_ERROR_BAD_STATE + * Another operation has already been started on this context, and is + * still in progress. + * + * \retval #PSA_ERROR_NOT_PERMITTED + * The key does not have the #PSA_KEY_USAGE_VERIFY_HASH flag, or it does + * not permit the requested algorithm. + * + * \retval #PSA_ERROR_NOT_SUPPORTED \emptydescription + * \retval #PSA_ERROR_INVALID_ARGUMENT \emptydescription + * \retval #PSA_ERROR_INSUFFICIENT_MEMORY \emptydescription + * \retval #PSA_ERROR_COMMUNICATION_FAILURE \emptydescription + * \retval #PSA_ERROR_HARDWARE_FAILURE \emptydescription + * \retval #PSA_ERROR_CORRUPTION_DETECTED \emptydescription + * \retval #PSA_ERROR_STORAGE_FAILURE \emptydescription + * \retval PSA_ERROR_DATA_CORRUPT \emptydescription + * \retval PSA_ERROR_DATA_INVALID \emptydescription + * \retval #PSA_ERROR_BAD_STATE + * The library has not been previously initialized by psa_crypto_init(). + * It is implementation-dependent whether a failure to initialize + * results in this error code. + */ +psa_status_t psa_verify_hash_start( + psa_verify_hash_interruptible_operation_t *operation, + mbedtls_svc_key_id_t key, psa_algorithm_t alg, + const uint8_t *hash, size_t hash_length, + const uint8_t *signature, size_t signature_length); + +/** + * \brief Continue and eventually complete the action of + * reading and verifying a hash or short message + * signed with a private key, in an interruptible + * manner. + * + * \see \c psa_verify_hash_start() + * + * \warning This is a beta API, and thus subject to change + * at any point. It is not bound by the usual + * interface stability promises. + * + * \note This function combined with \c + * psa_verify_hash_start() is equivalent to + * \c psa_verify_hash() but this function can + * return early and resume according to the limit + * set with \c psa_interruptible_set_max_ops() to + * reduce the maximum time spent in a function + * call. + * + * \note Users should call this function on the same + * operation object repeatedly until it either + * returns 0 or an error. This function will return + * #PSA_OPERATION_INCOMPLETE if there is more work + * to do. Alternatively users can call + * \c psa_verify_hash_abort() at any point if they + * no longer want the result. + * + * \note When this function returns successfully, the + * operation becomes inactive. If this function + * returns an error status, the operation enters an + * error state and must be aborted by calling + * \c psa_verify_hash_abort(). + * + * \param[in, out] operation The \c psa_verify_hash_interruptible_operation_t + * to use. This must be initialized first, and have + * had \c psa_verify_hash_start() called with it + * first. + * + * \retval #PSA_SUCCESS + * Operation completed successfully, and the passed signature is valid. + * + * \retval #PSA_OPERATION_INCOMPLETE + * Operation was interrupted due to the setting of \c + * psa_interruptible_set_max_ops(). There is still work to be done. + * Call this function again with the same operation object. + * + * \retval #PSA_ERROR_INVALID_HANDLE \emptydescription + * \retval #PSA_ERROR_INVALID_SIGNATURE + * The calculation was performed successfully, but the passed + * signature is not a valid signature. + * \retval #PSA_ERROR_BAD_STATE + * An operation was not previously started on this context via + * \c psa_verify_hash_start(). + * \retval #PSA_ERROR_NOT_SUPPORTED \emptydescription + * \retval #PSA_ERROR_INVALID_ARGUMENT \emptydescription + * \retval #PSA_ERROR_INSUFFICIENT_MEMORY \emptydescription + * \retval #PSA_ERROR_COMMUNICATION_FAILURE \emptydescription + * \retval #PSA_ERROR_HARDWARE_FAILURE \emptydescription + * \retval #PSA_ERROR_CORRUPTION_DETECTED \emptydescription + * \retval #PSA_ERROR_STORAGE_FAILURE \emptydescription + * \retval #PSA_ERROR_DATA_CORRUPT \emptydescription + * \retval #PSA_ERROR_DATA_INVALID \emptydescription + * \retval #PSA_ERROR_INSUFFICIENT_ENTROPY \emptydescription + * \retval #PSA_ERROR_BAD_STATE + * The library has either not been previously initialized by + * psa_crypto_init() or you did not previously call + * psa_verify_hash_start() on this object. It is + * implementation-dependent whether a failure to initialize results in + * this error code. + */ +psa_status_t psa_verify_hash_complete( + psa_verify_hash_interruptible_operation_t *operation); + +/** + * \brief Abort a verify hash operation. + * + * \warning This is a beta API, and thus subject to change at + * any point. It is not bound by the usual interface + * stability promises. + * + * \note This function is the only function that clears the + * number of ops completed as part of the operation. + * Please ensure you copy this value via + * \c psa_verify_hash_get_num_ops() if required + * before calling. + * + * \note Aborting an operation frees all associated + * resources except for the operation structure + * itself. Once aborted, the operation object can be + * reused for another operation by calling \c + * psa_verify_hash_start() again. + * + * \note You may call this function any time after the + * operation object has been initialized. + * In particular, calling \c psa_verify_hash_abort() + * after the operation has already been terminated by + * a call to \c psa_verify_hash_abort() or + * psa_verify_hash_complete() is safe. + * + * \param[in,out] operation Initialized verify hash operation. + * + * \retval #PSA_SUCCESS + * The operation was aborted successfully. + * + * \retval #PSA_ERROR_NOT_SUPPORTED \emptydescription + * \retval #PSA_ERROR_BAD_STATE + * The library has not been previously initialized by psa_crypto_init(). + * It is implementation-dependent whether a failure to initialize + * results in this error code. + */ +psa_status_t psa_verify_hash_abort( + psa_verify_hash_interruptible_operation_t *operation); + + /**@}*/ #ifdef __cplusplus @@ -3901,7 +4822,11 @@ psa_status_t psa_generate_key(const psa_key_attributes_t *attributes, /* The file "crypto_struct.h" contains definitions for * implementation-specific structs that are declared above. */ +#if defined(MBEDTLS_PSA_CRYPTO_STRUCT_FILE) +#include MBEDTLS_PSA_CRYPTO_STRUCT_FILE +#else #include "crypto_struct.h" +#endif /* The file "crypto_extra.h" contains vendor-specific definitions. This * can include vendor-defined algorithms, extra functions, etc. */ diff --git a/vendor/mbedtls/include/psa/crypto_adjust_auto_enabled.h b/vendor/mbedtls/include/psa/crypto_adjust_auto_enabled.h new file mode 100644 index 0000000000..63fb29e85b --- /dev/null +++ b/vendor/mbedtls/include/psa/crypto_adjust_auto_enabled.h @@ -0,0 +1,21 @@ +/** + * \file psa/crypto_adjust_auto_enabled.h + * \brief Adjust PSA configuration: enable always-on features + * + * Always enable certain features which require a negligible amount of code + * to implement, to avoid some edge cases in the configuration combinatorics. + */ +/* + * Copyright The Mbed TLS Contributors + * SPDX-License-Identifier: Apache-2.0 OR GPL-2.0-or-later + */ + +#ifndef PSA_CRYPTO_ADJUST_AUTO_ENABLED_H +#define PSA_CRYPTO_ADJUST_AUTO_ENABLED_H + +#define PSA_WANT_KEY_TYPE_DERIVE 1 +#define PSA_WANT_KEY_TYPE_PASSWORD 1 +#define PSA_WANT_KEY_TYPE_PASSWORD_HASH 1 +#define PSA_WANT_KEY_TYPE_RAW_DATA 1 + +#endif /* PSA_CRYPTO_ADJUST_AUTO_ENABLED_H */ diff --git a/vendor/mbedtls/include/psa/crypto_adjust_config_key_pair_types.h b/vendor/mbedtls/include/psa/crypto_adjust_config_key_pair_types.h new file mode 100644 index 0000000000..63afc0e402 --- /dev/null +++ b/vendor/mbedtls/include/psa/crypto_adjust_config_key_pair_types.h @@ -0,0 +1,91 @@ +/** + * \file psa/crypto_adjust_config_key_pair_types.h + * \brief Adjust PSA configuration for key pair types. + * + * See docs/proposed/psa-conditional-inclusion-c.md. + * - Support non-basic operations in a keypair type implicitly enables basic + * support for that keypair type. + * - Support for a keypair type implicitly enables the corresponding public + * key type. + * - Basic support for a keypair type implicilty enables import/export support + * for that keypair type. Warning: this is implementation-specific (mainly + * for the benefit of testing) and may change in the future! + */ +/* + * Copyright The Mbed TLS Contributors + * SPDX-License-Identifier: Apache-2.0 OR GPL-2.0-or-later + */ + +#ifndef PSA_CRYPTO_ADJUST_KEYPAIR_TYPES_H +#define PSA_CRYPTO_ADJUST_KEYPAIR_TYPES_H + +/***************************************************************** + * ANYTHING -> BASIC + ****************************************************************/ + +#if defined(PSA_WANT_KEY_TYPE_ECC_KEY_PAIR_IMPORT) || \ + defined(PSA_WANT_KEY_TYPE_ECC_KEY_PAIR_EXPORT) || \ + defined(PSA_WANT_KEY_TYPE_ECC_KEY_PAIR_GENERATE) || \ + defined(PSA_WANT_KEY_TYPE_ECC_KEY_PAIR_DERIVE) +#define PSA_WANT_KEY_TYPE_ECC_KEY_PAIR_BASIC 1 +#endif + +#if defined(PSA_WANT_KEY_TYPE_RSA_KEY_PAIR_IMPORT) || \ + defined(PSA_WANT_KEY_TYPE_RSA_KEY_PAIR_EXPORT) || \ + defined(PSA_WANT_KEY_TYPE_RSA_KEY_PAIR_GENERATE) || \ + defined(PSA_WANT_KEY_TYPE_RSA_KEY_PAIR_DERIVE) +#define PSA_WANT_KEY_TYPE_RSA_KEY_PAIR_BASIC 1 +#endif + +#if defined(PSA_WANT_KEY_TYPE_DH_KEY_PAIR_IMPORT) || \ + defined(PSA_WANT_KEY_TYPE_DH_KEY_PAIR_EXPORT) || \ + defined(PSA_WANT_KEY_TYPE_DH_KEY_PAIR_GENERATE) || \ + defined(PSA_WANT_KEY_TYPE_DH_KEY_PAIR_DERIVE) +#define PSA_WANT_KEY_TYPE_DH_KEY_PAIR_BASIC 1 +#endif + +/***************************************************************** + * BASIC -> corresponding PUBLIC + ****************************************************************/ + +#if defined(PSA_WANT_KEY_TYPE_ECC_KEY_PAIR_BASIC) +#define PSA_WANT_KEY_TYPE_ECC_PUBLIC_KEY 1 +#endif + +#if defined(PSA_WANT_KEY_TYPE_RSA_KEY_PAIR_BASIC) +#define PSA_WANT_KEY_TYPE_RSA_PUBLIC_KEY 1 +#endif + +#if defined(PSA_WANT_KEY_TYPE_DH_KEY_PAIR_BASIC) +#define PSA_WANT_KEY_TYPE_DH_PUBLIC_KEY 1 +#endif + +/***************************************************************** + * BASIC -> IMPORT+EXPORT + * + * (Implementation-specific, may change in the future.) + ****************************************************************/ + +/* Even though KEY_PAIR symbols' feature several level of support (BASIC, IMPORT, + * EXPORT, GENERATE, DERIVE) we're not planning to have support only for BASIC + * without IMPORT/EXPORT since these last 2 features are strongly used in tests. + * In general it is allowed to include more feature than what is strictly + * requested. + * As a consequence IMPORT and EXPORT features will be automatically enabled + * as soon as the BASIC one is. */ +#if defined(PSA_WANT_KEY_TYPE_ECC_KEY_PAIR_BASIC) +#define PSA_WANT_KEY_TYPE_ECC_KEY_PAIR_IMPORT 1 +#define PSA_WANT_KEY_TYPE_ECC_KEY_PAIR_EXPORT 1 +#endif + +#if defined(PSA_WANT_KEY_TYPE_RSA_KEY_PAIR_BASIC) +#define PSA_WANT_KEY_TYPE_RSA_KEY_PAIR_IMPORT 1 +#define PSA_WANT_KEY_TYPE_RSA_KEY_PAIR_EXPORT 1 +#endif + +#if defined(PSA_WANT_KEY_TYPE_DH_KEY_PAIR_BASIC) +#define PSA_WANT_KEY_TYPE_DH_KEY_PAIR_IMPORT 1 +#define PSA_WANT_KEY_TYPE_DH_KEY_PAIR_EXPORT 1 +#endif + +#endif /* PSA_CRYPTO_ADJUST_KEYPAIR_TYPES_H */ diff --git a/vendor/mbedtls/include/psa/crypto_adjust_config_synonyms.h b/vendor/mbedtls/include/psa/crypto_adjust_config_synonyms.h new file mode 100644 index 0000000000..332b622c9b --- /dev/null +++ b/vendor/mbedtls/include/psa/crypto_adjust_config_synonyms.h @@ -0,0 +1,39 @@ +/** + * \file psa/crypto_adjust_config_synonyms.h + * \brief Adjust PSA configuration: enable quasi-synonyms + * + * When two features require almost the same code, we automatically enable + * both when either one is requested, to reduce the combinatorics of + * possible configurations. + */ +/* + * Copyright The Mbed TLS Contributors + * SPDX-License-Identifier: Apache-2.0 OR GPL-2.0-or-later + */ + +#ifndef PSA_CRYPTO_ADJUST_CONFIG_SYNONYMS_H +#define PSA_CRYPTO_ADJUST_CONFIG_SYNONYMS_H + +/****************************************************************/ +/* De facto synonyms */ +/****************************************************************/ + +#if defined(PSA_WANT_ALG_ECDSA_ANY) && !defined(PSA_WANT_ALG_ECDSA) +#define PSA_WANT_ALG_ECDSA PSA_WANT_ALG_ECDSA_ANY +#elif !defined(PSA_WANT_ALG_ECDSA_ANY) && defined(PSA_WANT_ALG_ECDSA) +#define PSA_WANT_ALG_ECDSA_ANY PSA_WANT_ALG_ECDSA +#endif + +#if defined(PSA_WANT_ALG_RSA_PKCS1V15_SIGN_RAW) && !defined(PSA_WANT_ALG_RSA_PKCS1V15_SIGN) +#define PSA_WANT_ALG_RSA_PKCS1V15_SIGN PSA_WANT_ALG_RSA_PKCS1V15_SIGN_RAW +#elif !defined(PSA_WANT_ALG_RSA_PKCS1V15_SIGN_RAW) && defined(PSA_WANT_ALG_RSA_PKCS1V15_SIGN) +#define PSA_WANT_ALG_RSA_PKCS1V15_SIGN_RAW PSA_WANT_ALG_RSA_PKCS1V15_SIGN +#endif + +#if defined(PSA_WANT_ALG_RSA_PSS_ANY_SALT) && !defined(PSA_WANT_ALG_RSA_PSS) +#define PSA_WANT_ALG_RSA_PSS PSA_WANT_ALG_RSA_PSS_ANY_SALT +#elif !defined(PSA_WANT_ALG_RSA_PSS_ANY_SALT) && defined(PSA_WANT_ALG_RSA_PSS) +#define PSA_WANT_ALG_RSA_PSS_ANY_SALT PSA_WANT_ALG_RSA_PSS +#endif + +#endif /* PSA_CRYPTO_ADJUST_CONFIG_SYNONYMS_H */ diff --git a/vendor/mbedtls/include/psa/crypto_builtin_composites.h b/vendor/mbedtls/include/psa/crypto_builtin_composites.h index 63cb17342f..c14f5dd110 100644 --- a/vendor/mbedtls/include/psa/crypto_builtin_composites.h +++ b/vendor/mbedtls/include/psa/crypto_builtin_composites.h @@ -7,34 +7,32 @@ * \note This file may not be included directly. Applications must * include psa/crypto.h. * - * \note This header and its content is not part of the Mbed TLS API and + * \note This header and its content are not part of the Mbed TLS API and * applications must not depend on it. Its main purpose is to define the * multi-part state objects of the Mbed TLS software-based PSA drivers. The - * definition of these objects are then used by crypto_struct.h to define the + * definitions of these objects are then used by crypto_struct.h to define the * implementation-defined types of PSA multi-part state objects. */ /* * Copyright The Mbed TLS Contributors - * SPDX-License-Identifier: Apache-2.0 - * - * Licensed under the Apache License, Version 2.0 (the "License"); you may - * not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT - * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. + * SPDX-License-Identifier: Apache-2.0 OR GPL-2.0-or-later */ #ifndef PSA_CRYPTO_BUILTIN_COMPOSITES_H #define PSA_CRYPTO_BUILTIN_COMPOSITES_H +#include "mbedtls/private_access.h" #include +#include "mbedtls/cmac.h" +#if defined(MBEDTLS_PSA_BUILTIN_ALG_GCM) +#include "mbedtls/gcm.h" +#endif +#if defined(MBEDTLS_PSA_BUILTIN_ALG_CCM) +#include "mbedtls/ccm.h" +#endif +#include "mbedtls/chachapoly.h" + /* * MAC multi-part operation definitions. */ @@ -43,40 +41,174 @@ #define MBEDTLS_PSA_BUILTIN_MAC #endif -#if defined(MBEDTLS_PSA_BUILTIN_ALG_GCM) || \ - defined(MBEDTLS_PSA_BUILTIN_ALG_CCM) || \ - defined(MBEDTLS_PSA_BUILTIN_ALG_CHACHA20_POLY1305) -#define MBEDTLS_PSA_BUILTIN_AEAD 1 -#endif - #if defined(MBEDTLS_PSA_BUILTIN_ALG_HMAC) || defined(PSA_CRYPTO_DRIVER_TEST) typedef struct { /** The HMAC algorithm in use */ - psa_algorithm_t alg; + psa_algorithm_t MBEDTLS_PRIVATE(alg); /** The hash context. */ struct psa_hash_operation_s hash_ctx; /** The HMAC part of the context. */ - uint8_t opad[PSA_HMAC_MAX_HASH_BLOCK_SIZE]; + uint8_t MBEDTLS_PRIVATE(opad)[PSA_HMAC_MAX_HASH_BLOCK_SIZE]; } mbedtls_psa_hmac_operation_t; #define MBEDTLS_PSA_HMAC_OPERATION_INIT { 0, PSA_HASH_OPERATION_INIT, { 0 } } #endif /* MBEDTLS_PSA_BUILTIN_ALG_HMAC */ -#include "mbedtls/cmac.h" - typedef struct { - psa_algorithm_t alg; + psa_algorithm_t MBEDTLS_PRIVATE(alg); union { - unsigned dummy; /* Make the union non-empty even with no supported algorithms. */ + unsigned MBEDTLS_PRIVATE(dummy); /* Make the union non-empty even with no supported algorithms. */ #if defined(MBEDTLS_PSA_BUILTIN_ALG_HMAC) || defined(PSA_CRYPTO_DRIVER_TEST) - mbedtls_psa_hmac_operation_t hmac; + mbedtls_psa_hmac_operation_t MBEDTLS_PRIVATE(hmac); #endif /* MBEDTLS_PSA_BUILTIN_ALG_HMAC */ #if defined(MBEDTLS_PSA_BUILTIN_ALG_CMAC) || defined(PSA_CRYPTO_DRIVER_TEST) - mbedtls_cipher_context_t cmac; + mbedtls_cipher_context_t MBEDTLS_PRIVATE(cmac); #endif /* MBEDTLS_PSA_BUILTIN_ALG_CMAC */ - } ctx; + } MBEDTLS_PRIVATE(ctx); } mbedtls_psa_mac_operation_t; #define MBEDTLS_PSA_MAC_OPERATION_INIT { 0, { 0 } } +#if defined(MBEDTLS_PSA_BUILTIN_ALG_GCM) || \ + defined(MBEDTLS_PSA_BUILTIN_ALG_CCM) || \ + defined(MBEDTLS_PSA_BUILTIN_ALG_CHACHA20_POLY1305) +#define MBEDTLS_PSA_BUILTIN_AEAD 1 +#endif + +/* Context structure for the Mbed TLS AEAD implementation. */ +typedef struct { + psa_algorithm_t MBEDTLS_PRIVATE(alg); + psa_key_type_t MBEDTLS_PRIVATE(key_type); + + unsigned int MBEDTLS_PRIVATE(is_encrypt) : 1; + + uint8_t MBEDTLS_PRIVATE(tag_length); + + union { + unsigned dummy; /* Enable easier initializing of the union. */ +#if defined(MBEDTLS_PSA_BUILTIN_ALG_CCM) + mbedtls_ccm_context MBEDTLS_PRIVATE(ccm); +#endif /* MBEDTLS_PSA_BUILTIN_ALG_CCM */ +#if defined(MBEDTLS_PSA_BUILTIN_ALG_GCM) + mbedtls_gcm_context MBEDTLS_PRIVATE(gcm); +#endif /* MBEDTLS_PSA_BUILTIN_ALG_GCM */ +#if defined(MBEDTLS_PSA_BUILTIN_ALG_CHACHA20_POLY1305) + mbedtls_chachapoly_context MBEDTLS_PRIVATE(chachapoly); +#endif /* MBEDTLS_PSA_BUILTIN_ALG_CHACHA20_POLY1305 */ + + } ctx; + +} mbedtls_psa_aead_operation_t; + +#define MBEDTLS_PSA_AEAD_OPERATION_INIT { 0, 0, 0, 0, { 0 } } + +#include "mbedtls/ecdsa.h" + +/* Context structure for the Mbed TLS interruptible sign hash implementation. */ +typedef struct { +#if (defined(MBEDTLS_PSA_BUILTIN_ALG_ECDSA) || \ + defined(MBEDTLS_PSA_BUILTIN_ALG_DETERMINISTIC_ECDSA)) && \ + defined(MBEDTLS_ECP_RESTARTABLE) + mbedtls_ecdsa_context *MBEDTLS_PRIVATE(ctx); + mbedtls_ecdsa_restart_ctx MBEDTLS_PRIVATE(restart_ctx); + + uint32_t MBEDTLS_PRIVATE(num_ops); + + size_t MBEDTLS_PRIVATE(coordinate_bytes); + psa_algorithm_t MBEDTLS_PRIVATE(alg); + mbedtls_md_type_t MBEDTLS_PRIVATE(md_alg); + uint8_t MBEDTLS_PRIVATE(hash)[PSA_BITS_TO_BYTES(PSA_VENDOR_ECC_MAX_CURVE_BITS)]; + size_t MBEDTLS_PRIVATE(hash_length); + +#else + /* Make the struct non-empty if algs not supported. */ + unsigned MBEDTLS_PRIVATE(dummy); + +#endif /* defined(MBEDTLS_PSA_BUILTIN_ALG_ECDSA) || + * defined(MBEDTLS_PSA_BUILTIN_ALG_DETERMINISTIC_ECDSA) && + * defined( MBEDTLS_ECP_RESTARTABLE ) */ +} mbedtls_psa_sign_hash_interruptible_operation_t; + +#if (defined(MBEDTLS_PSA_BUILTIN_ALG_ECDSA) || \ + defined(MBEDTLS_PSA_BUILTIN_ALG_DETERMINISTIC_ECDSA)) && \ + defined(MBEDTLS_ECP_RESTARTABLE) +#define MBEDTLS_PSA_SIGN_HASH_INTERRUPTIBLE_OPERATION_INIT { { 0 }, { 0 }, 0, 0, 0, 0, 0, 0 } +#else +#define MBEDTLS_PSA_SIGN_HASH_INTERRUPTIBLE_OPERATION_INIT { 0 } +#endif + +/* Context structure for the Mbed TLS interruptible verify hash + * implementation.*/ +typedef struct { +#if (defined(MBEDTLS_PSA_BUILTIN_ALG_ECDSA) || \ + defined(MBEDTLS_PSA_BUILTIN_ALG_DETERMINISTIC_ECDSA)) && \ + defined(MBEDTLS_ECP_RESTARTABLE) + + mbedtls_ecdsa_context *MBEDTLS_PRIVATE(ctx); + mbedtls_ecdsa_restart_ctx MBEDTLS_PRIVATE(restart_ctx); + + uint32_t MBEDTLS_PRIVATE(num_ops); + + uint8_t MBEDTLS_PRIVATE(hash)[PSA_BITS_TO_BYTES(PSA_VENDOR_ECC_MAX_CURVE_BITS)]; + size_t MBEDTLS_PRIVATE(hash_length); + + mbedtls_mpi MBEDTLS_PRIVATE(r); + mbedtls_mpi MBEDTLS_PRIVATE(s); + +#else + /* Make the struct non-empty if algs not supported. */ + unsigned MBEDTLS_PRIVATE(dummy); + +#endif /* defined(MBEDTLS_PSA_BUILTIN_ALG_ECDSA) || + * defined(MBEDTLS_PSA_BUILTIN_ALG_DETERMINISTIC_ECDSA) && + * defined( MBEDTLS_ECP_RESTARTABLE ) */ + +} mbedtls_psa_verify_hash_interruptible_operation_t; + +#if (defined(MBEDTLS_PSA_BUILTIN_ALG_ECDSA) || \ + defined(MBEDTLS_PSA_BUILTIN_ALG_DETERMINISTIC_ECDSA)) && \ + defined(MBEDTLS_ECP_RESTARTABLE) +#define MBEDTLS_VERIFY_SIGN_HASH_INTERRUPTIBLE_OPERATION_INIT { { 0 }, { 0 }, 0, 0, 0, 0, { 0 }, \ + { 0 } } +#else +#define MBEDTLS_VERIFY_SIGN_HASH_INTERRUPTIBLE_OPERATION_INIT { 0 } +#endif + + +/* EC-JPAKE operation definitions */ + +#include "mbedtls/ecjpake.h" + +#if defined(MBEDTLS_PSA_BUILTIN_ALG_JPAKE) +#define MBEDTLS_PSA_BUILTIN_PAKE 1 +#endif + +/* Note: the format for mbedtls_ecjpake_read/write function has an extra + * length byte for each step, plus an extra 3 bytes for ECParameters in the + * server's 2nd round. */ +#define MBEDTLS_PSA_JPAKE_BUFFER_SIZE ((3 + 1 + 65 + 1 + 65 + 1 + 32) * 2) + +typedef struct { + psa_algorithm_t MBEDTLS_PRIVATE(alg); + + uint8_t *MBEDTLS_PRIVATE(password); + size_t MBEDTLS_PRIVATE(password_len); +#if defined(MBEDTLS_PSA_BUILTIN_ALG_JPAKE) + mbedtls_ecjpake_role MBEDTLS_PRIVATE(role); + uint8_t MBEDTLS_PRIVATE(buffer[MBEDTLS_PSA_JPAKE_BUFFER_SIZE]); + size_t MBEDTLS_PRIVATE(buffer_length); + size_t MBEDTLS_PRIVATE(buffer_offset); +#endif + /* Context structure for the Mbed TLS EC-JPAKE implementation. */ + union { + unsigned int MBEDTLS_PRIVATE(dummy); +#if defined(MBEDTLS_PSA_BUILTIN_ALG_JPAKE) + mbedtls_ecjpake_context MBEDTLS_PRIVATE(jpake); +#endif + } MBEDTLS_PRIVATE(ctx); + +} mbedtls_psa_pake_operation_t; + +#define MBEDTLS_PSA_PAKE_OPERATION_INIT { { 0 } } + #endif /* PSA_CRYPTO_BUILTIN_COMPOSITES_H */ diff --git a/vendor/mbedtls/include/psa/crypto_builtin_key_derivation.h b/vendor/mbedtls/include/psa/crypto_builtin_key_derivation.h new file mode 100644 index 0000000000..6b91ae73f1 --- /dev/null +++ b/vendor/mbedtls/include/psa/crypto_builtin_key_derivation.h @@ -0,0 +1,118 @@ +/* + * Context structure declaration of the Mbed TLS software-based PSA drivers + * called through the PSA Crypto driver dispatch layer. + * This file contains the context structures of key derivation algorithms + * which need to rely on other algorithms. + * + * \note This file may not be included directly. Applications must + * include psa/crypto.h. + * + * \note This header and its content are not part of the Mbed TLS API and + * applications must not depend on it. Its main purpose is to define the + * multi-part state objects of the Mbed TLS software-based PSA drivers. The + * definitions of these objects are then used by crypto_struct.h to define the + * implementation-defined types of PSA multi-part state objects. + */ +/* + * Copyright The Mbed TLS Contributors + * SPDX-License-Identifier: Apache-2.0 OR GPL-2.0-or-later + */ + +#ifndef PSA_CRYPTO_BUILTIN_KEY_DERIVATION_H +#define PSA_CRYPTO_BUILTIN_KEY_DERIVATION_H +#include "mbedtls/private_access.h" + +#include + +#if defined(MBEDTLS_PSA_BUILTIN_ALG_HKDF) || \ + defined(MBEDTLS_PSA_BUILTIN_ALG_HKDF_EXTRACT) || \ + defined(MBEDTLS_PSA_BUILTIN_ALG_HKDF_EXPAND) +typedef struct { + uint8_t *MBEDTLS_PRIVATE(info); + size_t MBEDTLS_PRIVATE(info_length); +#if PSA_HASH_MAX_SIZE > 0xff +#error "PSA_HASH_MAX_SIZE does not fit in uint8_t" +#endif + uint8_t MBEDTLS_PRIVATE(offset_in_block); + uint8_t MBEDTLS_PRIVATE(block_number); + unsigned int MBEDTLS_PRIVATE(state) : 2; + unsigned int MBEDTLS_PRIVATE(info_set) : 1; + uint8_t MBEDTLS_PRIVATE(output_block)[PSA_HASH_MAX_SIZE]; + uint8_t MBEDTLS_PRIVATE(prk)[PSA_HASH_MAX_SIZE]; + struct psa_mac_operation_s MBEDTLS_PRIVATE(hmac); +} psa_hkdf_key_derivation_t; +#endif /* MBEDTLS_PSA_BUILTIN_ALG_HKDF || + MBEDTLS_PSA_BUILTIN_ALG_HKDF_EXTRACT || + MBEDTLS_PSA_BUILTIN_ALG_HKDF_EXPAND */ +#if defined(MBEDTLS_PSA_BUILTIN_ALG_TLS12_ECJPAKE_TO_PMS) +typedef struct { + uint8_t MBEDTLS_PRIVATE(data)[PSA_TLS12_ECJPAKE_TO_PMS_DATA_SIZE]; +} psa_tls12_ecjpake_to_pms_t; +#endif /* MBEDTLS_PSA_BUILTIN_ALG_TLS12_ECJPAKE_TO_PMS */ + +#if defined(MBEDTLS_PSA_BUILTIN_ALG_TLS12_PRF) || \ + defined(MBEDTLS_PSA_BUILTIN_ALG_TLS12_PSK_TO_MS) +typedef enum { + PSA_TLS12_PRF_STATE_INIT, /* no input provided */ + PSA_TLS12_PRF_STATE_SEED_SET, /* seed has been set */ + PSA_TLS12_PRF_STATE_OTHER_KEY_SET, /* other key has been set - optional */ + PSA_TLS12_PRF_STATE_KEY_SET, /* key has been set */ + PSA_TLS12_PRF_STATE_LABEL_SET, /* label has been set */ + PSA_TLS12_PRF_STATE_OUTPUT /* output has been started */ +} psa_tls12_prf_key_derivation_state_t; + +typedef struct psa_tls12_prf_key_derivation_s { +#if PSA_HASH_MAX_SIZE > 0xff +#error "PSA_HASH_MAX_SIZE does not fit in uint8_t" +#endif + + /* Indicates how many bytes in the current HMAC block have + * not yet been read by the user. */ + uint8_t MBEDTLS_PRIVATE(left_in_block); + + /* The 1-based number of the block. */ + uint8_t MBEDTLS_PRIVATE(block_number); + + psa_tls12_prf_key_derivation_state_t MBEDTLS_PRIVATE(state); + + uint8_t *MBEDTLS_PRIVATE(secret); + size_t MBEDTLS_PRIVATE(secret_length); + uint8_t *MBEDTLS_PRIVATE(seed); + size_t MBEDTLS_PRIVATE(seed_length); + uint8_t *MBEDTLS_PRIVATE(label); + size_t MBEDTLS_PRIVATE(label_length); +#if defined(MBEDTLS_PSA_BUILTIN_ALG_TLS12_PSK_TO_MS) + uint8_t *MBEDTLS_PRIVATE(other_secret); + size_t MBEDTLS_PRIVATE(other_secret_length); +#endif /* MBEDTLS_PSA_BUILTIN_ALG_TLS12_PSK_TO_MS */ + + uint8_t MBEDTLS_PRIVATE(Ai)[PSA_HASH_MAX_SIZE]; + + /* `HMAC_hash( prk, A( i ) + seed )` in the notation of RFC 5246, Sect. 5. */ + uint8_t MBEDTLS_PRIVATE(output_block)[PSA_HASH_MAX_SIZE]; +} psa_tls12_prf_key_derivation_t; +#endif /* MBEDTLS_PSA_BUILTIN_ALG_TLS12_PRF) || + * MBEDTLS_PSA_BUILTIN_ALG_TLS12_PSK_TO_MS */ +#if defined(PSA_HAVE_SOFT_PBKDF2) +typedef enum { + PSA_PBKDF2_STATE_INIT, /* no input provided */ + PSA_PBKDF2_STATE_INPUT_COST_SET, /* input cost has been set */ + PSA_PBKDF2_STATE_SALT_SET, /* salt has been set */ + PSA_PBKDF2_STATE_PASSWORD_SET, /* password has been set */ + PSA_PBKDF2_STATE_OUTPUT /* output has been started */ +} psa_pbkdf2_key_derivation_state_t; + +typedef struct { + psa_pbkdf2_key_derivation_state_t MBEDTLS_PRIVATE(state); + uint64_t MBEDTLS_PRIVATE(input_cost); + uint8_t *MBEDTLS_PRIVATE(salt); + size_t MBEDTLS_PRIVATE(salt_length); + uint8_t MBEDTLS_PRIVATE(password)[PSA_HMAC_MAX_HASH_BLOCK_SIZE]; + size_t MBEDTLS_PRIVATE(password_length); + uint8_t MBEDTLS_PRIVATE(output_block)[PSA_HASH_MAX_SIZE]; + uint8_t MBEDTLS_PRIVATE(bytes_used); + uint32_t MBEDTLS_PRIVATE(block_number); +} psa_pbkdf2_key_derivation_t; +#endif /* PSA_HAVE_SOFT_PBKDF2 */ + +#endif /* PSA_CRYPTO_BUILTIN_KEY_DERIVATION_H */ diff --git a/vendor/mbedtls/include/psa/crypto_builtin_primitives.h b/vendor/mbedtls/include/psa/crypto_builtin_primitives.h index 6989cfed69..98ab4d3339 100644 --- a/vendor/mbedtls/include/psa/crypto_builtin_primitives.h +++ b/vendor/mbedtls/include/psa/crypto_builtin_primitives.h @@ -7,31 +7,20 @@ * \note This file may not be included directly. Applications must * include psa/crypto.h. * - * \note This header and its content is not part of the Mbed TLS API and + * \note This header and its content are not part of the Mbed TLS API and * applications must not depend on it. Its main purpose is to define the * multi-part state objects of the Mbed TLS software-based PSA drivers. The - * definition of these objects are then used by crypto_struct.h to define the + * definitions of these objects are then used by crypto_struct.h to define the * implementation-defined types of PSA multi-part state objects. */ /* * Copyright The Mbed TLS Contributors - * SPDX-License-Identifier: Apache-2.0 - * - * Licensed under the Apache License, Version 2.0 (the "License"); you may - * not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT - * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. + * SPDX-License-Identifier: Apache-2.0 OR GPL-2.0-or-later */ #ifndef PSA_CRYPTO_BUILTIN_PRIMITIVES_H #define PSA_CRYPTO_BUILTIN_PRIMITIVES_H +#include "mbedtls/private_access.h" #include @@ -39,36 +28,31 @@ * Hash multi-part operation definitions. */ -#include "mbedtls/md2.h" -#include "mbedtls/md4.h" #include "mbedtls/md5.h" #include "mbedtls/ripemd160.h" #include "mbedtls/sha1.h" #include "mbedtls/sha256.h" #include "mbedtls/sha512.h" +#include "mbedtls/sha3.h" -#if defined(MBEDTLS_PSA_BUILTIN_ALG_MD2) || \ - defined(MBEDTLS_PSA_BUILTIN_ALG_MD4) || \ - defined(MBEDTLS_PSA_BUILTIN_ALG_MD5) || \ +#if defined(MBEDTLS_PSA_BUILTIN_ALG_MD5) || \ defined(MBEDTLS_PSA_BUILTIN_ALG_RIPEMD160) || \ defined(MBEDTLS_PSA_BUILTIN_ALG_SHA_1) || \ defined(MBEDTLS_PSA_BUILTIN_ALG_SHA_224) || \ defined(MBEDTLS_PSA_BUILTIN_ALG_SHA_256) || \ defined(MBEDTLS_PSA_BUILTIN_ALG_SHA_384) || \ - defined(MBEDTLS_PSA_BUILTIN_ALG_SHA_512) + defined(MBEDTLS_PSA_BUILTIN_ALG_SHA_512) || \ + defined(MBEDTLS_PSA_BUILTIN_ALG_SHA3_224) || \ + defined(MBEDTLS_PSA_BUILTIN_ALG_SHA3_256) || \ + defined(MBEDTLS_PSA_BUILTIN_ALG_SHA3_384) || \ + defined(MBEDTLS_PSA_BUILTIN_ALG_SHA3_512) #define MBEDTLS_PSA_BUILTIN_HASH #endif typedef struct { - psa_algorithm_t alg; + psa_algorithm_t MBEDTLS_PRIVATE(alg); union { unsigned dummy; /* Make the union non-empty even with no supported algorithms. */ -#if defined(MBEDTLS_PSA_BUILTIN_ALG_MD2) - mbedtls_md2_context md2; -#endif -#if defined(MBEDTLS_PSA_BUILTIN_ALG_MD4) - mbedtls_md4_context md4; -#endif #if defined(MBEDTLS_PSA_BUILTIN_ALG_MD5) mbedtls_md5_context md5; #endif @@ -86,7 +70,13 @@ typedef struct { defined(MBEDTLS_PSA_BUILTIN_ALG_SHA_384) mbedtls_sha512_context sha512; #endif - } ctx; +#if defined(MBEDTLS_PSA_BUILTIN_ALG_SHA3_224) || \ + defined(MBEDTLS_PSA_BUILTIN_ALG_SHA3_256) || \ + defined(MBEDTLS_PSA_BUILTIN_ALG_SHA3_384) || \ + defined(MBEDTLS_PSA_BUILTIN_ALG_SHA3_512) + mbedtls_sha3_context sha3; +#endif + } MBEDTLS_PRIVATE(ctx); } mbedtls_psa_hash_operation_t; #define MBEDTLS_PSA_HASH_OPERATION_INIT { 0, { 0 } } @@ -103,19 +93,20 @@ typedef struct { defined(MBEDTLS_PSA_BUILTIN_ALG_OFB) || \ defined(MBEDTLS_PSA_BUILTIN_ALG_ECB_NO_PADDING) || \ defined(MBEDTLS_PSA_BUILTIN_ALG_CBC_NO_PADDING) || \ - defined(MBEDTLS_PSA_BUILTIN_ALG_CBC_PKCS7) + defined(MBEDTLS_PSA_BUILTIN_ALG_CBC_PKCS7) || \ + defined(MBEDTLS_PSA_BUILTIN_ALG_CCM_STAR_NO_TAG) #define MBEDTLS_PSA_BUILTIN_CIPHER 1 #endif typedef struct { /* Context structure for the Mbed TLS cipher implementation. */ - psa_algorithm_t alg; - uint8_t iv_length; - uint8_t block_length; + psa_algorithm_t MBEDTLS_PRIVATE(alg); + uint8_t MBEDTLS_PRIVATE(iv_length); + uint8_t MBEDTLS_PRIVATE(block_length); union { - unsigned int dummy; - mbedtls_cipher_context_t cipher; - } ctx; + unsigned int MBEDTLS_PRIVATE(dummy); + mbedtls_cipher_context_t MBEDTLS_PRIVATE(cipher); + } MBEDTLS_PRIVATE(ctx); } mbedtls_psa_cipher_operation_t; #define MBEDTLS_PSA_CIPHER_OPERATION_INIT { 0, 0, 0, { 0 } } diff --git a/vendor/mbedtls/include/psa/crypto_compat.h b/vendor/mbedtls/include/psa/crypto_compat.h index 24239f5bbf..2a226c01a8 100644 --- a/vendor/mbedtls/include/psa/crypto_compat.h +++ b/vendor/mbedtls/include/psa/crypto_compat.h @@ -12,19 +12,7 @@ */ /* * Copyright The Mbed TLS Contributors - * SPDX-License-Identifier: Apache-2.0 - * - * Licensed under the Apache License, Version 2.0 (the "License"); you may - * not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT - * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. + * SPDX-License-Identifier: Apache-2.0 OR GPL-2.0-or-later */ #ifndef PSA_CRYPTO_COMPAT_H @@ -55,371 +43,6 @@ static inline int psa_key_handle_is_null(psa_key_handle_t handle) return mbedtls_svc_key_id_is_null(handle); } -#if !defined(MBEDTLS_DEPRECATED_REMOVED) - -/* - * Mechanism for declaring deprecated values - */ -#if defined(MBEDTLS_DEPRECATED_WARNING) && !defined(MBEDTLS_PSA_DEPRECATED) -#define MBEDTLS_PSA_DEPRECATED __attribute__((deprecated)) -#else -#define MBEDTLS_PSA_DEPRECATED -#endif - -typedef MBEDTLS_PSA_DEPRECATED size_t mbedtls_deprecated_size_t; -typedef MBEDTLS_PSA_DEPRECATED psa_status_t mbedtls_deprecated_psa_status_t; -typedef MBEDTLS_PSA_DEPRECATED psa_key_usage_t mbedtls_deprecated_psa_key_usage_t; -typedef MBEDTLS_PSA_DEPRECATED psa_ecc_family_t mbedtls_deprecated_psa_ecc_family_t; -typedef MBEDTLS_PSA_DEPRECATED psa_dh_family_t mbedtls_deprecated_psa_dh_family_t; -typedef MBEDTLS_PSA_DEPRECATED psa_ecc_family_t psa_ecc_curve_t; -typedef MBEDTLS_PSA_DEPRECATED psa_dh_family_t psa_dh_group_t; -typedef MBEDTLS_PSA_DEPRECATED psa_algorithm_t mbedtls_deprecated_psa_algorithm_t; - -#define PSA_KEY_TYPE_GET_CURVE PSA_KEY_TYPE_ECC_GET_FAMILY -#define PSA_KEY_TYPE_GET_GROUP PSA_KEY_TYPE_DH_GET_FAMILY - -#define MBEDTLS_DEPRECATED_CONSTANT(type, value) \ - ((mbedtls_deprecated_##type) (value)) - -/* - * Deprecated PSA Crypto error code definitions (PSA Crypto API <= 1.0 beta2) - */ -#define PSA_ERROR_UNKNOWN_ERROR \ - MBEDTLS_DEPRECATED_CONSTANT(psa_status_t, PSA_ERROR_GENERIC_ERROR) -#define PSA_ERROR_OCCUPIED_SLOT \ - MBEDTLS_DEPRECATED_CONSTANT(psa_status_t, PSA_ERROR_ALREADY_EXISTS) -#define PSA_ERROR_EMPTY_SLOT \ - MBEDTLS_DEPRECATED_CONSTANT(psa_status_t, PSA_ERROR_DOES_NOT_EXIST) -#define PSA_ERROR_INSUFFICIENT_CAPACITY \ - MBEDTLS_DEPRECATED_CONSTANT(psa_status_t, PSA_ERROR_INSUFFICIENT_DATA) -#define PSA_ERROR_TAMPERING_DETECTED \ - MBEDTLS_DEPRECATED_CONSTANT(psa_status_t, PSA_ERROR_CORRUPTION_DETECTED) - -/* - * Deprecated PSA Crypto numerical encodings (PSA Crypto API <= 1.0 beta3) - */ -#define PSA_KEY_USAGE_SIGN \ - MBEDTLS_DEPRECATED_CONSTANT(psa_key_usage_t, PSA_KEY_USAGE_SIGN_HASH) -#define PSA_KEY_USAGE_VERIFY \ - MBEDTLS_DEPRECATED_CONSTANT(psa_key_usage_t, PSA_KEY_USAGE_VERIFY_HASH) - -/* - * Deprecated PSA Crypto size calculation macros (PSA Crypto API <= 1.0 beta3) - */ -#define PSA_ASYMMETRIC_SIGNATURE_MAX_SIZE \ - MBEDTLS_DEPRECATED_CONSTANT(size_t, PSA_SIGNATURE_MAX_SIZE) -#define PSA_ASYMMETRIC_SIGN_OUTPUT_SIZE(key_type, key_bits, alg) \ - MBEDTLS_DEPRECATED_CONSTANT(size_t, PSA_SIGN_OUTPUT_SIZE(key_type, key_bits, alg)) -#define PSA_KEY_EXPORT_MAX_SIZE(key_type, key_bits) \ - MBEDTLS_DEPRECATED_CONSTANT(size_t, PSA_EXPORT_KEY_OUTPUT_SIZE(key_type, key_bits)) -#define PSA_BLOCK_CIPHER_BLOCK_SIZE(type) \ - MBEDTLS_DEPRECATED_CONSTANT(size_t, PSA_BLOCK_CIPHER_BLOCK_LENGTH(type)) -#define PSA_MAX_BLOCK_CIPHER_BLOCK_SIZE \ - MBEDTLS_DEPRECATED_CONSTANT(size_t, PSA_BLOCK_CIPHER_BLOCK_MAX_SIZE) -#define PSA_HASH_SIZE(alg) \ - MBEDTLS_DEPRECATED_CONSTANT(size_t, PSA_HASH_LENGTH(alg)) -#define PSA_MAC_FINAL_SIZE(key_type, key_bits, alg) \ - MBEDTLS_DEPRECATED_CONSTANT(size_t, PSA_MAC_LENGTH(key_type, key_bits, alg)) -#define PSA_ALG_TLS12_PSK_TO_MS_MAX_PSK_LEN \ - MBEDTLS_DEPRECATED_CONSTANT(size_t, PSA_TLS12_PSK_TO_MS_PSK_MAX_SIZE) - -/* - * Deprecated PSA Crypto function names (PSA Crypto API <= 1.0 beta3) - */ -MBEDTLS_PSA_DEPRECATED static inline psa_status_t psa_asymmetric_sign(psa_key_handle_t key, - psa_algorithm_t alg, - const uint8_t *hash, - size_t hash_length, - uint8_t *signature, - size_t signature_size, - size_t *signature_length) -{ - return psa_sign_hash(key, alg, hash, hash_length, signature, signature_size, signature_length); -} - -MBEDTLS_PSA_DEPRECATED static inline psa_status_t psa_asymmetric_verify(psa_key_handle_t key, - psa_algorithm_t alg, - const uint8_t *hash, - size_t hash_length, - const uint8_t *signature, - size_t signature_length) -{ - return psa_verify_hash(key, alg, hash, hash_length, signature, signature_length); -} - -/* - * Size-specific elliptic curve families. - */ -#define PSA_ECC_CURVE_SECP160K1 \ - MBEDTLS_DEPRECATED_CONSTANT(psa_ecc_family_t, PSA_ECC_FAMILY_SECP_K1) -#define PSA_ECC_CURVE_SECP192K1 \ - MBEDTLS_DEPRECATED_CONSTANT(psa_ecc_family_t, PSA_ECC_FAMILY_SECP_K1) -#define PSA_ECC_CURVE_SECP224K1 \ - MBEDTLS_DEPRECATED_CONSTANT(psa_ecc_family_t, PSA_ECC_FAMILY_SECP_K1) -#define PSA_ECC_CURVE_SECP256K1 \ - MBEDTLS_DEPRECATED_CONSTANT(psa_ecc_family_t, PSA_ECC_FAMILY_SECP_K1) -#define PSA_ECC_CURVE_SECP160R1 \ - MBEDTLS_DEPRECATED_CONSTANT(psa_ecc_family_t, PSA_ECC_FAMILY_SECP_R1) -#define PSA_ECC_CURVE_SECP192R1 \ - MBEDTLS_DEPRECATED_CONSTANT(psa_ecc_family_t, PSA_ECC_FAMILY_SECP_R1) -#define PSA_ECC_CURVE_SECP224R1 \ - MBEDTLS_DEPRECATED_CONSTANT(psa_ecc_family_t, PSA_ECC_FAMILY_SECP_R1) -#define PSA_ECC_CURVE_SECP256R1 \ - MBEDTLS_DEPRECATED_CONSTANT(psa_ecc_family_t, PSA_ECC_FAMILY_SECP_R1) -#define PSA_ECC_CURVE_SECP384R1 \ - MBEDTLS_DEPRECATED_CONSTANT(psa_ecc_family_t, PSA_ECC_FAMILY_SECP_R1) -#define PSA_ECC_CURVE_SECP521R1 \ - MBEDTLS_DEPRECATED_CONSTANT(psa_ecc_family_t, PSA_ECC_FAMILY_SECP_R1) -#define PSA_ECC_CURVE_SECP160R2 \ - MBEDTLS_DEPRECATED_CONSTANT(psa_ecc_family_t, PSA_ECC_FAMILY_SECP_R2) -#define PSA_ECC_CURVE_SECT163K1 \ - MBEDTLS_DEPRECATED_CONSTANT(psa_ecc_family_t, PSA_ECC_FAMILY_SECT_K1) -#define PSA_ECC_CURVE_SECT233K1 \ - MBEDTLS_DEPRECATED_CONSTANT(psa_ecc_family_t, PSA_ECC_FAMILY_SECT_K1) -#define PSA_ECC_CURVE_SECT239K1 \ - MBEDTLS_DEPRECATED_CONSTANT(psa_ecc_family_t, PSA_ECC_FAMILY_SECT_K1) -#define PSA_ECC_CURVE_SECT283K1 \ - MBEDTLS_DEPRECATED_CONSTANT(psa_ecc_family_t, PSA_ECC_FAMILY_SECT_K1) -#define PSA_ECC_CURVE_SECT409K1 \ - MBEDTLS_DEPRECATED_CONSTANT(psa_ecc_family_t, PSA_ECC_FAMILY_SECT_K1) -#define PSA_ECC_CURVE_SECT571K1 \ - MBEDTLS_DEPRECATED_CONSTANT(psa_ecc_family_t, PSA_ECC_FAMILY_SECT_K1) -#define PSA_ECC_CURVE_SECT163R1 \ - MBEDTLS_DEPRECATED_CONSTANT(psa_ecc_family_t, PSA_ECC_FAMILY_SECT_R1) -#define PSA_ECC_CURVE_SECT193R1 \ - MBEDTLS_DEPRECATED_CONSTANT(psa_ecc_family_t, PSA_ECC_FAMILY_SECT_R1) -#define PSA_ECC_CURVE_SECT233R1 \ - MBEDTLS_DEPRECATED_CONSTANT(psa_ecc_family_t, PSA_ECC_FAMILY_SECT_R1) -#define PSA_ECC_CURVE_SECT283R1 \ - MBEDTLS_DEPRECATED_CONSTANT(psa_ecc_family_t, PSA_ECC_FAMILY_SECT_R1) -#define PSA_ECC_CURVE_SECT409R1 \ - MBEDTLS_DEPRECATED_CONSTANT(psa_ecc_family_t, PSA_ECC_FAMILY_SECT_R1) -#define PSA_ECC_CURVE_SECT571R1 \ - MBEDTLS_DEPRECATED_CONSTANT(psa_ecc_family_t, PSA_ECC_FAMILY_SECT_R1) -#define PSA_ECC_CURVE_SECT163R2 \ - MBEDTLS_DEPRECATED_CONSTANT(psa_ecc_family_t, PSA_ECC_FAMILY_SECT_R2) -#define PSA_ECC_CURVE_SECT193R2 \ - MBEDTLS_DEPRECATED_CONSTANT(psa_ecc_family_t, PSA_ECC_FAMILY_SECT_R2) -#define PSA_ECC_CURVE_BRAINPOOL_P256R1 \ - MBEDTLS_DEPRECATED_CONSTANT(psa_ecc_family_t, PSA_ECC_FAMILY_BRAINPOOL_P_R1) -#define PSA_ECC_CURVE_BRAINPOOL_P384R1 \ - MBEDTLS_DEPRECATED_CONSTANT(psa_ecc_family_t, PSA_ECC_FAMILY_BRAINPOOL_P_R1) -#define PSA_ECC_CURVE_BRAINPOOL_P512R1 \ - MBEDTLS_DEPRECATED_CONSTANT(psa_ecc_family_t, PSA_ECC_FAMILY_BRAINPOOL_P_R1) -#define PSA_ECC_CURVE_CURVE25519 \ - MBEDTLS_DEPRECATED_CONSTANT(psa_ecc_family_t, PSA_ECC_FAMILY_MONTGOMERY) -#define PSA_ECC_CURVE_CURVE448 \ - MBEDTLS_DEPRECATED_CONSTANT(psa_ecc_family_t, PSA_ECC_FAMILY_MONTGOMERY) - -/* - * Curves that changed name due to PSA specification. - */ -#define PSA_ECC_CURVE_SECP_K1 \ - MBEDTLS_DEPRECATED_CONSTANT(psa_ecc_family_t, PSA_ECC_FAMILY_SECP_K1) -#define PSA_ECC_CURVE_SECP_R1 \ - MBEDTLS_DEPRECATED_CONSTANT(psa_ecc_family_t, PSA_ECC_FAMILY_SECP_R1) -#define PSA_ECC_CURVE_SECP_R2 \ - MBEDTLS_DEPRECATED_CONSTANT(psa_ecc_family_t, PSA_ECC_FAMILY_SECP_R2) -#define PSA_ECC_CURVE_SECT_K1 \ - MBEDTLS_DEPRECATED_CONSTANT(psa_ecc_family_t, PSA_ECC_FAMILY_SECT_K1) -#define PSA_ECC_CURVE_SECT_R1 \ - MBEDTLS_DEPRECATED_CONSTANT(psa_ecc_family_t, PSA_ECC_FAMILY_SECT_R1) -#define PSA_ECC_CURVE_SECT_R2 \ - MBEDTLS_DEPRECATED_CONSTANT(psa_ecc_family_t, PSA_ECC_FAMILY_SECT_R2) -#define PSA_ECC_CURVE_BRAINPOOL_P_R1 \ - MBEDTLS_DEPRECATED_CONSTANT(psa_ecc_family_t, PSA_ECC_FAMILY_BRAINPOOL_P_R1) -#define PSA_ECC_CURVE_MONTGOMERY \ - MBEDTLS_DEPRECATED_CONSTANT(psa_ecc_family_t, PSA_ECC_FAMILY_MONTGOMERY) - -/* - * Finite-field Diffie-Hellman families. - */ -#define PSA_DH_GROUP_FFDHE2048 \ - MBEDTLS_DEPRECATED_CONSTANT(psa_dh_family_t, PSA_DH_FAMILY_RFC7919) -#define PSA_DH_GROUP_FFDHE3072 \ - MBEDTLS_DEPRECATED_CONSTANT(psa_dh_family_t, PSA_DH_FAMILY_RFC7919) -#define PSA_DH_GROUP_FFDHE4096 \ - MBEDTLS_DEPRECATED_CONSTANT(psa_dh_family_t, PSA_DH_FAMILY_RFC7919) -#define PSA_DH_GROUP_FFDHE6144 \ - MBEDTLS_DEPRECATED_CONSTANT(psa_dh_family_t, PSA_DH_FAMILY_RFC7919) -#define PSA_DH_GROUP_FFDHE8192 \ - MBEDTLS_DEPRECATED_CONSTANT(psa_dh_family_t, PSA_DH_FAMILY_RFC7919) - -/* - * Diffie-Hellman families that changed name due to PSA specification. - */ -#define PSA_DH_GROUP_RFC7919 \ - MBEDTLS_DEPRECATED_CONSTANT(psa_dh_family_t, PSA_DH_FAMILY_RFC7919) -#define PSA_DH_GROUP_CUSTOM \ - MBEDTLS_DEPRECATED_CONSTANT(psa_dh_family_t, PSA_DH_FAMILY_CUSTOM) - -/* - * Deprecated PSA Crypto stream cipher algorithms (PSA Crypto API <= 1.0 beta3) - */ -#define PSA_ALG_ARC4 \ - MBEDTLS_DEPRECATED_CONSTANT(psa_algorithm_t, PSA_ALG_STREAM_CIPHER) -#define PSA_ALG_CHACHA20 \ - MBEDTLS_DEPRECATED_CONSTANT(psa_algorithm_t, PSA_ALG_STREAM_CIPHER) - -/* - * Renamed AEAD tag length macros (PSA Crypto API <= 1.0 beta3) - */ -#define PSA_ALG_AEAD_WITH_DEFAULT_TAG_LENGTH(aead_alg) \ - MBEDTLS_DEPRECATED_CONSTANT(psa_algorithm_t, PSA_ALG_AEAD_WITH_DEFAULT_LENGTH_TAG(aead_alg)) -#define PSA_ALG_AEAD_WITH_TAG_LENGTH(aead_alg, tag_length) \ - MBEDTLS_DEPRECATED_CONSTANT(psa_algorithm_t, \ - PSA_ALG_AEAD_WITH_SHORTENED_TAG(aead_alg, tag_length)) - -/* - * Deprecated PSA AEAD output size macros (PSA Crypto API <= 1.0 beta3) - */ - -/** The tag size for an AEAD algorithm, in bytes. - * - * \param alg An AEAD algorithm - * (\c PSA_ALG_XXX value such that - * #PSA_ALG_IS_AEAD(\p alg) is true). - * - * \return The tag size for the specified algorithm. - * If the AEAD algorithm does not have an identified - * tag that can be distinguished from the rest of - * the ciphertext, return 0. - * If the AEAD algorithm is not recognized, return 0. - */ -#define PSA_AEAD_TAG_LENGTH_1_ARG(alg) \ - MBEDTLS_DEPRECATED_CONSTANT(size_t, \ - PSA_ALG_IS_AEAD(alg) ? \ - PSA_ALG_AEAD_GET_TAG_LENGTH(alg) : \ - 0) - -/** The maximum size of the output of psa_aead_encrypt(), in bytes. - * - * If the size of the ciphertext buffer is at least this large, it is - * guaranteed that psa_aead_encrypt() will not fail due to an - * insufficient buffer size. Depending on the algorithm, the actual size of - * the ciphertext may be smaller. - * - * \warning This macro may evaluate its arguments multiple times or - * zero times, so you should not pass arguments that contain - * side effects. - * - * \param alg An AEAD algorithm - * (\c PSA_ALG_XXX value such that - * #PSA_ALG_IS_AEAD(\p alg) is true). - * \param plaintext_length Size of the plaintext in bytes. - * - * \return The AEAD ciphertext size for the specified - * algorithm. - * If the AEAD algorithm is not recognized, return 0. - */ -#define PSA_AEAD_ENCRYPT_OUTPUT_SIZE_2_ARG(alg, plaintext_length) \ - MBEDTLS_DEPRECATED_CONSTANT(size_t, \ - PSA_ALG_IS_AEAD(alg) ? \ - (plaintext_length) + PSA_ALG_AEAD_GET_TAG_LENGTH(alg) : \ - 0) - -/** The maximum size of the output of psa_aead_decrypt(), in bytes. - * - * If the size of the plaintext buffer is at least this large, it is - * guaranteed that psa_aead_decrypt() will not fail due to an - * insufficient buffer size. Depending on the algorithm, the actual size of - * the plaintext may be smaller. - * - * \warning This macro may evaluate its arguments multiple times or - * zero times, so you should not pass arguments that contain - * side effects. - * - * \param alg An AEAD algorithm - * (\c PSA_ALG_XXX value such that - * #PSA_ALG_IS_AEAD(\p alg) is true). - * \param ciphertext_length Size of the plaintext in bytes. - * - * \return The AEAD ciphertext size for the specified - * algorithm. - * If the AEAD algorithm is not recognized, return 0. - */ -#define PSA_AEAD_DECRYPT_OUTPUT_SIZE_2_ARG(alg, ciphertext_length) \ - MBEDTLS_DEPRECATED_CONSTANT(size_t, \ - PSA_ALG_IS_AEAD(alg) && \ - (ciphertext_length) > PSA_ALG_AEAD_GET_TAG_LENGTH(alg) ? \ - (ciphertext_length) - PSA_ALG_AEAD_GET_TAG_LENGTH(alg) : \ - 0) - -/** A sufficient output buffer size for psa_aead_update(). - * - * If the size of the output buffer is at least this large, it is - * guaranteed that psa_aead_update() will not fail due to an - * insufficient buffer size. The actual size of the output may be smaller - * in any given call. - * - * \warning This macro may evaluate its arguments multiple times or - * zero times, so you should not pass arguments that contain - * side effects. - * - * \param alg An AEAD algorithm - * (\c PSA_ALG_XXX value such that - * #PSA_ALG_IS_AEAD(\p alg) is true). - * \param input_length Size of the input in bytes. - * - * \return A sufficient output buffer size for the specified - * algorithm. - * If the AEAD algorithm is not recognized, return 0. - */ -/* For all the AEAD modes defined in this specification, it is possible - * to emit output without delay. However, hardware may not always be - * capable of this. So for modes based on a block cipher, allow the - * implementation to delay the output until it has a full block. */ -#define PSA_AEAD_UPDATE_OUTPUT_SIZE_2_ARG(alg, input_length) \ - MBEDTLS_DEPRECATED_CONSTANT(size_t, \ - PSA_ALG_IS_AEAD_ON_BLOCK_CIPHER(alg) ? \ - PSA_ROUND_UP_TO_MULTIPLE(PSA_BLOCK_CIPHER_BLOCK_MAX_SIZE, \ - (input_length)) : \ - (input_length)) - -/** A sufficient ciphertext buffer size for psa_aead_finish(). - * - * If the size of the ciphertext buffer is at least this large, it is - * guaranteed that psa_aead_finish() will not fail due to an - * insufficient ciphertext buffer size. The actual size of the output may - * be smaller in any given call. - * - * \param alg An AEAD algorithm - * (\c PSA_ALG_XXX value such that - * #PSA_ALG_IS_AEAD(\p alg) is true). - * - * \return A sufficient ciphertext buffer size for the - * specified algorithm. - * If the AEAD algorithm is not recognized, return 0. - */ -#define PSA_AEAD_FINISH_OUTPUT_SIZE_1_ARG(alg) \ - MBEDTLS_DEPRECATED_CONSTANT(size_t, \ - PSA_ALG_IS_AEAD_ON_BLOCK_CIPHER(alg) ? \ - PSA_BLOCK_CIPHER_BLOCK_MAX_SIZE : \ - 0) - -/** A sufficient plaintext buffer size for psa_aead_verify(). - * - * If the size of the plaintext buffer is at least this large, it is - * guaranteed that psa_aead_verify() will not fail due to an - * insufficient plaintext buffer size. The actual size of the output may - * be smaller in any given call. - * - * \param alg An AEAD algorithm - * (\c PSA_ALG_XXX value such that - * #PSA_ALG_IS_AEAD(\p alg) is true). - * - * \return A sufficient plaintext buffer size for the - * specified algorithm. - * If the AEAD algorithm is not recognized, return 0. - */ -#define PSA_AEAD_VERIFY_OUTPUT_SIZE_1_ARG(alg) \ - MBEDTLS_DEPRECATED_CONSTANT(size_t, \ - PSA_ALG_IS_AEAD_ON_BLOCK_CIPHER(alg) ? \ - PSA_BLOCK_CIPHER_BLOCK_MAX_SIZE : \ - 0) - -#endif /* MBEDTLS_DEPRECATED_REMOVED */ - /** Open a handle to an existing persistent key. * * Open a handle to a persistent key. A key is persistent if it was created @@ -523,6 +146,83 @@ psa_status_t psa_open_key(mbedtls_svc_key_id_t key, */ psa_status_t psa_close_key(psa_key_handle_t handle); +/** \addtogroup attributes + * @{ + */ + +#if !defined(MBEDTLS_DEPRECATED_REMOVED) +/** Custom Diffie-Hellman group. + * + * Mbed TLS does not support custom DH groups. + * + * \deprecated This value is not useful, so this macro will be removed in + * a future version of the library. + */ +#define PSA_DH_FAMILY_CUSTOM \ + ((psa_dh_family_t) MBEDTLS_DEPRECATED_NUMERIC_CONSTANT(0x7e)) + +/** + * \brief Set domain parameters for a key. + * + * \deprecated Mbed TLS no longer supports any domain parameters. + * This function only does the equivalent of + * psa_set_key_type() and will be removed in a future version + * of the library. + * + * \param[in,out] attributes Attribute structure where \p type will be set. + * \param type Key type (a \c PSA_KEY_TYPE_XXX value). + * \param[in] data Ignored. + * \param data_length Must be 0. + * + * \retval #PSA_SUCCESS \emptydescription + * \retval #PSA_ERROR_NOT_SUPPORTED \emptydescription + */ +static inline psa_status_t MBEDTLS_DEPRECATED psa_set_key_domain_parameters( + psa_key_attributes_t *attributes, + psa_key_type_t type, const uint8_t *data, size_t data_length) +{ + (void) data; + if (data_length != 0) { + return PSA_ERROR_NOT_SUPPORTED; + } + psa_set_key_type(attributes, type); + return PSA_SUCCESS; +} + +/** + * \brief Get domain parameters for a key. + * + * \deprecated Mbed TLS no longer supports any domain parameters. + * This function alwaya has an empty output and will be + * removed in a future version of the library. + + * \param[in] attributes Ignored. + * \param[out] data Ignored. + * \param data_size Ignored. + * \param[out] data_length Set to 0. + * + * \retval #PSA_SUCCESS \emptydescription + */ +static inline psa_status_t MBEDTLS_DEPRECATED psa_get_key_domain_parameters( + const psa_key_attributes_t *attributes, + uint8_t *data, size_t data_size, size_t *data_length) +{ + (void) attributes; + (void) data; + (void) data_size; + *data_length = 0; + return PSA_SUCCESS; +} + +/** Safe output buffer size for psa_get_key_domain_parameters(). + * + */ +#define PSA_KEY_DOMAIN_PARAMETERS_SIZE(key_type, key_bits) \ + MBEDTLS_DEPRECATED_NUMERIC_CONSTANT(1u) +#endif /* MBEDTLS_DEPRECATED_REMOVED */ + +/**@}*/ + #ifdef __cplusplus } #endif diff --git a/vendor/mbedtls/include/psa/crypto_config.h b/vendor/mbedtls/include/psa/crypto_config.h index f261e013e0..36e937ad35 100644 --- a/vendor/mbedtls/include/psa/crypto_config.h +++ b/vendor/mbedtls/include/psa/crypto_config.h @@ -5,7 +5,7 @@ */ #if defined(MBEDTLS_PSA_CRYPTO_CONFIG) /** - * When #MBEDTLS_PSA_CRYPTO_CONFIG is enabled in config.h, + * When #MBEDTLS_PSA_CRYPTO_CONFIG is enabled in mbedtls_config.h, * this file determines which cryptographic mechanisms are enabled * through the PSA Cryptography API (\c psa_xxx() functions). * @@ -24,7 +24,7 @@ */ #else /** - * When \c MBEDTLS_PSA_CRYPTO_CONFIG is disabled in config.h, + * When \c MBEDTLS_PSA_CRYPTO_CONFIG is disabled in mbedtls_config.h, * this file is not used, and cryptographic mechanisms are supported * through the PSA API if and only if they are supported through the * mbedtls_xxx API. @@ -32,19 +32,7 @@ #endif /* * Copyright The Mbed TLS Contributors - * SPDX-License-Identifier: Apache-2.0 - * - * Licensed under the Apache License, Version 2.0 (the "License"); you may - * not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT - * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. + * SPDX-License-Identifier: Apache-2.0 OR GPL-2.0-or-later */ #ifndef PSA_CRYPTO_CONFIG_H @@ -57,6 +45,7 @@ #define PSA_WANT_ALG_CBC_NO_PADDING 1 #define PSA_WANT_ALG_CBC_PKCS7 1 #define PSA_WANT_ALG_CCM 1 +#define PSA_WANT_ALG_CCM_STAR_NO_TAG 1 #define PSA_WANT_ALG_CMAC 1 #define PSA_WANT_ALG_CFB 1 #define PSA_WANT_ALG_CHACHA20_POLY1305 1 @@ -64,14 +53,18 @@ #define PSA_WANT_ALG_DETERMINISTIC_ECDSA 1 #define PSA_WANT_ALG_ECB_NO_PADDING 1 #define PSA_WANT_ALG_ECDH 1 +#define PSA_WANT_ALG_FFDH 1 #define PSA_WANT_ALG_ECDSA 1 +#define PSA_WANT_ALG_JPAKE 1 #define PSA_WANT_ALG_GCM 1 #define PSA_WANT_ALG_HKDF 1 +#define PSA_WANT_ALG_HKDF_EXTRACT 1 +#define PSA_WANT_ALG_HKDF_EXPAND 1 #define PSA_WANT_ALG_HMAC 1 -#define PSA_WANT_ALG_MD2 1 -#define PSA_WANT_ALG_MD4 1 #define PSA_WANT_ALG_MD5 1 #define PSA_WANT_ALG_OFB 1 +#define PSA_WANT_ALG_PBKDF2_HMAC 1 +#define PSA_WANT_ALG_PBKDF2_AES_CMAC_PRF_128 1 #define PSA_WANT_ALG_RIPEMD160 1 #define PSA_WANT_ALG_RSA_OAEP 1 #define PSA_WANT_ALG_RSA_PKCS1V15_CRYPT 1 @@ -82,10 +75,16 @@ #define PSA_WANT_ALG_SHA_256 1 #define PSA_WANT_ALG_SHA_384 1 #define PSA_WANT_ALG_SHA_512 1 +#define PSA_WANT_ALG_SHA3_224 1 +#define PSA_WANT_ALG_SHA3_256 1 +#define PSA_WANT_ALG_SHA3_384 1 +#define PSA_WANT_ALG_SHA3_512 1 #define PSA_WANT_ALG_STREAM_CIPHER 1 #define PSA_WANT_ALG_TLS12_PRF 1 #define PSA_WANT_ALG_TLS12_PSK_TO_MS 1 -/* PBKDF2-HMAC is not yet supported via the PSA API in Mbed TLS. +#define PSA_WANT_ALG_TLS12_ECJPAKE_TO_PMS 1 + +/* XTS is not yet supported via the PSA API in Mbed TLS. * Note: when adding support, also adjust include/mbedtls/config_psa.h */ //#define PSA_WANT_ALG_XTS 1 @@ -93,12 +92,7 @@ #define PSA_WANT_ECC_BRAINPOOL_P_R1_384 1 #define PSA_WANT_ECC_BRAINPOOL_P_R1_512 1 #define PSA_WANT_ECC_MONTGOMERY_255 1 -/* - * Curve448 is not yet supported via the PSA API in Mbed TLS - * (https://github.com/Mbed-TLS/mbedtls/issues/4249). Thus, do not enable it by - * default. - */ -//#define PSA_WANT_ECC_MONTGOMERY_448 1 +#define PSA_WANT_ECC_MONTGOMERY_448 1 #define PSA_WANT_ECC_SECP_K1_192 1 /* * SECP224K1 is buggy via the PSA API in Mbed TLS @@ -109,22 +103,57 @@ #define PSA_WANT_ECC_SECP_K1_256 1 #define PSA_WANT_ECC_SECP_R1_192 1 #define PSA_WANT_ECC_SECP_R1_224 1 +/* For secp256r1, consider enabling #MBEDTLS_PSA_P256M_DRIVER_ENABLED + * (see the description in mbedtls/mbedtls_config.h for details). */ #define PSA_WANT_ECC_SECP_R1_256 1 #define PSA_WANT_ECC_SECP_R1_384 1 #define PSA_WANT_ECC_SECP_R1_521 1 +#define PSA_WANT_DH_RFC7919_2048 1 +#define PSA_WANT_DH_RFC7919_3072 1 +#define PSA_WANT_DH_RFC7919_4096 1 +#define PSA_WANT_DH_RFC7919_6144 1 +#define PSA_WANT_DH_RFC7919_8192 1 + #define PSA_WANT_KEY_TYPE_DERIVE 1 +#define PSA_WANT_KEY_TYPE_PASSWORD 1 +#define PSA_WANT_KEY_TYPE_PASSWORD_HASH 1 #define PSA_WANT_KEY_TYPE_HMAC 1 #define PSA_WANT_KEY_TYPE_AES 1 -#define PSA_WANT_KEY_TYPE_ARC4 1 #define PSA_WANT_KEY_TYPE_ARIA 1 #define PSA_WANT_KEY_TYPE_CAMELLIA 1 #define PSA_WANT_KEY_TYPE_CHACHA20 1 #define PSA_WANT_KEY_TYPE_DES 1 -#define PSA_WANT_KEY_TYPE_ECC_KEY_PAIR 1 +//#define PSA_WANT_KEY_TYPE_ECC_KEY_PAIR 1 /* Deprecated */ #define PSA_WANT_KEY_TYPE_ECC_PUBLIC_KEY 1 +#define PSA_WANT_KEY_TYPE_DH_PUBLIC_KEY 1 #define PSA_WANT_KEY_TYPE_RAW_DATA 1 -#define PSA_WANT_KEY_TYPE_RSA_KEY_PAIR 1 +//#define PSA_WANT_KEY_TYPE_RSA_KEY_PAIR 1 /* Deprecated */ #define PSA_WANT_KEY_TYPE_RSA_PUBLIC_KEY 1 +/* + * The following symbols extend and deprecate the legacy + * PSA_WANT_KEY_TYPE_xxx_KEY_PAIR ones. They include the usage of that key in + * the name's suffix. "_USE" is the most generic and it can be used to describe + * a generic suport, whereas other ones add more features on top of that and + * they are more specific. + */ +#define PSA_WANT_KEY_TYPE_ECC_KEY_PAIR_BASIC 1 +#define PSA_WANT_KEY_TYPE_ECC_KEY_PAIR_IMPORT 1 +#define PSA_WANT_KEY_TYPE_ECC_KEY_PAIR_EXPORT 1 +#define PSA_WANT_KEY_TYPE_ECC_KEY_PAIR_GENERATE 1 +#define PSA_WANT_KEY_TYPE_ECC_KEY_PAIR_DERIVE 1 + +#define PSA_WANT_KEY_TYPE_RSA_KEY_PAIR_BASIC 1 +#define PSA_WANT_KEY_TYPE_RSA_KEY_PAIR_IMPORT 1 +#define PSA_WANT_KEY_TYPE_RSA_KEY_PAIR_EXPORT 1 +#define PSA_WANT_KEY_TYPE_RSA_KEY_PAIR_GENERATE 1 +//#define PSA_WANT_KEY_TYPE_RSA_KEY_PAIR_DERIVE 1 /* Not supported */ + +#define PSA_WANT_KEY_TYPE_DH_KEY_PAIR_BASIC 1 +#define PSA_WANT_KEY_TYPE_DH_KEY_PAIR_IMPORT 1 +#define PSA_WANT_KEY_TYPE_DH_KEY_PAIR_EXPORT 1 +#define PSA_WANT_KEY_TYPE_DH_KEY_PAIR_GENERATE 1 +//#define PSA_WANT_KEY_TYPE_DH_KEY_PAIR_DERIVE 1 /* Not supported */ + #endif /* PSA_CRYPTO_CONFIG_H */ diff --git a/vendor/mbedtls/include/psa/crypto_driver_common.h b/vendor/mbedtls/include/psa/crypto_driver_common.h index 26363c6b2f..cc11d3b9a2 100644 --- a/vendor/mbedtls/include/psa/crypto_driver_common.h +++ b/vendor/mbedtls/include/psa/crypto_driver_common.h @@ -17,19 +17,7 @@ /* * Copyright The Mbed TLS Contributors - * SPDX-License-Identifier: Apache-2.0 - * - * Licensed under the Apache License, Version 2.0 (the "License"); you may - * not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT - * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. + * SPDX-License-Identifier: Apache-2.0 OR GPL-2.0-or-later */ #ifndef PSA_CRYPTO_DRIVER_COMMON_H #define PSA_CRYPTO_DRIVER_COMMON_H diff --git a/vendor/mbedtls/include/psa/crypto_driver_contexts_composites.h b/vendor/mbedtls/include/psa/crypto_driver_contexts_composites.h index 34e6fd61c3..d717c51909 100644 --- a/vendor/mbedtls/include/psa/crypto_driver_contexts_composites.h +++ b/vendor/mbedtls/include/psa/crypto_driver_contexts_composites.h @@ -9,26 +9,14 @@ * \note This file may not be included directly. Applications must * include psa/crypto.h. * - * \note This header and its content is not part of the Mbed TLS API and + * \note This header and its content are not part of the Mbed TLS API and * applications must not depend on it. Its main purpose is to define the * multi-part state objects of the PSA drivers included in the cryptographic - * library. The definition of these objects are then used by crypto_struct.h + * library. The definitions of these objects are then used by crypto_struct.h * to define the implementation-defined types of PSA multi-part state objects. */ /* Copyright The Mbed TLS Contributors - * SPDX-License-Identifier: Apache-2.0 - * - * Licensed under the Apache License, Version 2.0 (the "License"); you may - * not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT - * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. + * SPDX-License-Identifier: Apache-2.0 OR GPL-2.0-or-later */ #ifndef PSA_CRYPTO_DRIVER_CONTEXTS_COMPOSITES_H @@ -70,7 +58,50 @@ typedef mbedtls_psa_mac_operation_t #define MBEDTLS_OPAQUE_TEST_DRIVER_MAC_OPERATION_INIT \ MBEDTLS_PSA_MAC_OPERATION_INIT -#endif /* MBEDTLS_TEST_LIBTESTDRIVER1 */ +#endif /* MBEDTLS_TEST_LIBTESTDRIVER1 && LIBTESTDRIVER1_MBEDTLS_PSA_BUILTIN_MAC */ + +#if defined(MBEDTLS_TEST_LIBTESTDRIVER1) && \ + defined(LIBTESTDRIVER1_MBEDTLS_PSA_BUILTIN_AEAD) +typedef libtestdriver1_mbedtls_psa_aead_operation_t + mbedtls_transparent_test_driver_aead_operation_t; + +#define MBEDTLS_TRANSPARENT_TEST_DRIVER_AEAD_OPERATION_INIT \ + LIBTESTDRIVER1_MBEDTLS_PSA_AEAD_OPERATION_INIT +#else +typedef mbedtls_psa_aead_operation_t + mbedtls_transparent_test_driver_aead_operation_t; + +#define MBEDTLS_TRANSPARENT_TEST_DRIVER_AEAD_OPERATION_INIT \ + MBEDTLS_PSA_AEAD_OPERATION_INIT + +#endif /* MBEDTLS_TEST_LIBTESTDRIVER1 && LIBTESTDRIVER1_MBEDTLS_PSA_BUILTIN_AEAD */ + +#if defined(MBEDTLS_TEST_LIBTESTDRIVER1) && \ + defined(LIBTESTDRIVER1_MBEDTLS_PSA_BUILTIN_PAKE) + +typedef libtestdriver1_mbedtls_psa_pake_operation_t + mbedtls_transparent_test_driver_pake_operation_t; +typedef libtestdriver1_mbedtls_psa_pake_operation_t + mbedtls_opaque_test_driver_pake_operation_t; + +#define MBEDTLS_TRANSPARENT_TEST_DRIVER_PAKE_OPERATION_INIT \ + LIBTESTDRIVER1_MBEDTLS_PSA_PAKE_OPERATION_INIT +#define MBEDTLS_OPAQUE_TEST_DRIVER_PAKE_OPERATION_INIT \ + LIBTESTDRIVER1_MBEDTLS_PSA_PAKE_OPERATION_INIT + +#else +typedef mbedtls_psa_pake_operation_t + mbedtls_transparent_test_driver_pake_operation_t; +typedef mbedtls_psa_pake_operation_t + mbedtls_opaque_test_driver_pake_operation_t; + +#define MBEDTLS_TRANSPARENT_TEST_DRIVER_PAKE_OPERATION_INIT \ + MBEDTLS_PSA_PAKE_OPERATION_INIT +#define MBEDTLS_OPAQUE_TEST_DRIVER_PAKE_OPERATION_INIT \ + MBEDTLS_PSA_PAKE_OPERATION_INIT + +#endif /* MBEDTLS_TEST_LIBTESTDRIVER1 && LIBTESTDRIVER1_MBEDTLS_PSA_BUILTIN_PAKE */ + #endif /* PSA_CRYPTO_DRIVER_TEST */ /* Define the context to be used for an operation that is executed through the @@ -78,7 +109,7 @@ typedef mbedtls_psa_mac_operation_t * * The union members are the driver's context structures, and the member names * are formatted as `'drivername'_ctx`. This allows for procedural generation - * of both this file and the content of psa_crypto_driver_wrappers.c */ + * of both this file and the content of psa_crypto_driver_wrappers.h */ typedef union { unsigned dummy; /* Make sure this union is always non-empty */ @@ -89,5 +120,32 @@ typedef union { #endif } psa_driver_mac_context_t; +typedef union { + unsigned dummy; /* Make sure this union is always non-empty */ + mbedtls_psa_aead_operation_t mbedtls_ctx; +#if defined(PSA_CRYPTO_DRIVER_TEST) + mbedtls_transparent_test_driver_aead_operation_t transparent_test_driver_ctx; +#endif +} psa_driver_aead_context_t; + +typedef union { + unsigned dummy; /* Make sure this union is always non-empty */ + mbedtls_psa_sign_hash_interruptible_operation_t mbedtls_ctx; +} psa_driver_sign_hash_interruptible_context_t; + +typedef union { + unsigned dummy; /* Make sure this union is always non-empty */ + mbedtls_psa_verify_hash_interruptible_operation_t mbedtls_ctx; +} psa_driver_verify_hash_interruptible_context_t; + +typedef union { + unsigned dummy; /* Make sure this union is always non-empty */ + mbedtls_psa_pake_operation_t mbedtls_ctx; +#if defined(PSA_CRYPTO_DRIVER_TEST) + mbedtls_transparent_test_driver_pake_operation_t transparent_test_driver_ctx; + mbedtls_opaque_test_driver_pake_operation_t opaque_test_driver_ctx; +#endif +} psa_driver_pake_context_t; + #endif /* PSA_CRYPTO_DRIVER_CONTEXTS_COMPOSITES_H */ /* End of automatically generated file. */ diff --git a/vendor/mbedtls/include/psa/crypto_driver_contexts_key_derivation.h b/vendor/mbedtls/include/psa/crypto_driver_contexts_key_derivation.h new file mode 100644 index 0000000000..21190515ce --- /dev/null +++ b/vendor/mbedtls/include/psa/crypto_driver_contexts_key_derivation.h @@ -0,0 +1,52 @@ +/* + * Declaration of context structures for use with the PSA driver wrapper + * interface. This file contains the context structures for key derivation + * operations. + * + * Warning: This file will be auto-generated in the future. + * + * \note This file may not be included directly. Applications must + * include psa/crypto.h. + * + * \note This header and its content are not part of the Mbed TLS API and + * applications must not depend on it. Its main purpose is to define the + * multi-part state objects of the PSA drivers included in the cryptographic + * library. The definitions of these objects are then used by crypto_struct.h + * to define the implementation-defined types of PSA multi-part state objects. + */ +/* Copyright The Mbed TLS Contributors + * SPDX-License-Identifier: Apache-2.0 OR GPL-2.0-or-later + */ + +#ifndef PSA_CRYPTO_DRIVER_CONTEXTS_KEY_DERIVATION_H +#define PSA_CRYPTO_DRIVER_CONTEXTS_KEY_DERIVATION_H + +#include "psa/crypto_driver_common.h" + +/* Include the context structure definitions for the Mbed TLS software drivers */ +#include "psa/crypto_builtin_key_derivation.h" + +/* Include the context structure definitions for those drivers that were + * declared during the autogeneration process. */ + +typedef union { + unsigned dummy; /* Make sure this union is always non-empty */ +#if defined(MBEDTLS_PSA_BUILTIN_ALG_HKDF) || \ + defined(MBEDTLS_PSA_BUILTIN_ALG_HKDF_EXTRACT) || \ + defined(MBEDTLS_PSA_BUILTIN_ALG_HKDF_EXPAND) + psa_hkdf_key_derivation_t MBEDTLS_PRIVATE(hkdf); +#endif +#if defined(MBEDTLS_PSA_BUILTIN_ALG_TLS12_PRF) || \ + defined(MBEDTLS_PSA_BUILTIN_ALG_TLS12_PSK_TO_MS) + psa_tls12_prf_key_derivation_t MBEDTLS_PRIVATE(tls12_prf); +#endif +#if defined(MBEDTLS_PSA_BUILTIN_ALG_TLS12_ECJPAKE_TO_PMS) + psa_tls12_ecjpake_to_pms_t MBEDTLS_PRIVATE(tls12_ecjpake_to_pms); +#endif +#if defined(PSA_HAVE_SOFT_PBKDF2) + psa_pbkdf2_key_derivation_t MBEDTLS_PRIVATE(pbkdf2); +#endif +} psa_driver_key_derivation_context_t; + +#endif /* PSA_CRYPTO_DRIVER_CONTEXTS_KEY_DERIVATION_H */ +/* End of automatically generated file. */ diff --git a/vendor/mbedtls/include/psa/crypto_driver_contexts_primitives.h b/vendor/mbedtls/include/psa/crypto_driver_contexts_primitives.h index 620a4b3a77..c90a5fbe74 100644 --- a/vendor/mbedtls/include/psa/crypto_driver_contexts_primitives.h +++ b/vendor/mbedtls/include/psa/crypto_driver_contexts_primitives.h @@ -8,26 +8,14 @@ * \note This file may not be included directly. Applications must * include psa/crypto.h. * - * \note This header and its content is not part of the Mbed TLS API and + * \note This header and its content are not part of the Mbed TLS API and * applications must not depend on it. Its main purpose is to define the * multi-part state objects of the PSA drivers included in the cryptographic - * library. The definition of these objects are then used by crypto_struct.h + * library. The definitions of these objects are then used by crypto_struct.h * to define the implementation-defined types of PSA multi-part state objects. */ /* Copyright The Mbed TLS Contributors - * SPDX-License-Identifier: Apache-2.0 - * - * Licensed under the Apache License, Version 2.0 (the "License"); you may - * not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT - * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. + * SPDX-License-Identifier: Apache-2.0 OR GPL-2.0-or-later */ #ifndef PSA_CRYPTO_DRIVER_CONTEXTS_PRIMITIVES_H @@ -94,7 +82,7 @@ typedef struct { * * The union members are the driver's context structures, and the member names * are formatted as `'drivername'_ctx`. This allows for procedural generation - * of both this file and the content of psa_crypto_driver_wrappers.c */ + * of both this file and the content of psa_crypto_driver_wrappers.h */ typedef union { unsigned dummy; /* Make sure this union is always non-empty */ diff --git a/vendor/mbedtls/include/psa/crypto_extra.h b/vendor/mbedtls/include/psa/crypto_extra.h index 92f0b6887b..6ed1f6c43a 100644 --- a/vendor/mbedtls/include/psa/crypto_extra.h +++ b/vendor/mbedtls/include/psa/crypto_extra.h @@ -10,25 +10,12 @@ */ /* * Copyright The Mbed TLS Contributors - * SPDX-License-Identifier: Apache-2.0 - * - * Licensed under the Apache License, Version 2.0 (the "License"); you may - * not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT - * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. + * SPDX-License-Identifier: Apache-2.0 OR GPL-2.0-or-later */ #ifndef PSA_CRYPTO_EXTRA_H #define PSA_CRYPTO_EXTRA_H - -#include "mbedtls/platform_util.h" +#include "mbedtls/private_access.h" #include "crypto_types.h" #include "crypto_compat.h" @@ -40,7 +27,7 @@ extern "C" { /* UID for secure storage seed */ #define PSA_CRYPTO_ITS_RANDOM_SEED_UID 0xFFFFFF52 -/* See config.h for definition */ +/* See mbedtls_config.h for definition */ #if !defined(MBEDTLS_PSA_KEY_SLOT_COUNT) #define MBEDTLS_PSA_KEY_SLOT_COUNT 32 #endif @@ -72,7 +59,7 @@ static inline void psa_set_key_enrollment_algorithm( psa_key_attributes_t *attributes, psa_algorithm_t alg2) { - attributes->core.policy.alg2 = alg2; + attributes->MBEDTLS_PRIVATE(policy).MBEDTLS_PRIVATE(alg2) = alg2; } /** Retrieve the enrollment algorithm policy from key attributes. @@ -84,7 +71,7 @@ static inline void psa_set_key_enrollment_algorithm( static inline psa_algorithm_t psa_get_key_enrollment_algorithm( const psa_key_attributes_t *attributes) { - return attributes->core.policy.alg2; + return attributes->MBEDTLS_PRIVATE(policy).MBEDTLS_PRIVATE(alg2); } #if defined(MBEDTLS_PSA_CRYPTO_SE_C) @@ -142,8 +129,8 @@ static inline void psa_set_key_slot_number( psa_key_attributes_t *attributes, psa_key_slot_number_t slot_number) { - attributes->core.flags |= MBEDTLS_PSA_KA_FLAG_HAS_SLOT_NUMBER; - attributes->slot_number = slot_number; + attributes->MBEDTLS_PRIVATE(has_slot_number) = 1; + attributes->MBEDTLS_PRIVATE(slot_number) = slot_number; } /** Remove the slot number attribute from a key attribute structure. @@ -155,7 +142,7 @@ static inline void psa_set_key_slot_number( static inline void psa_clear_key_slot_number( psa_key_attributes_t *attributes) { - attributes->core.flags &= ~MBEDTLS_PSA_KA_FLAG_HAS_SLOT_NUMBER; + attributes->MBEDTLS_PRIVATE(has_slot_number) = 0; } /** Register a key that is already present in a secure element. @@ -210,6 +197,8 @@ psa_status_t mbedtls_psa_register_se_key( * * This function clears all data associated with the PSA layer, * including the whole key store. + * This function is not thread safe, it wipes every key slot regardless of + * state and reader count. It should only be called when no slot is in use. * * This is an Mbed TLS extension. */ @@ -223,26 +212,26 @@ void mbedtls_psa_crypto_free(void); */ typedef struct mbedtls_psa_stats_s { /** Number of slots containing key material for a volatile key. */ - size_t volatile_slots; + size_t MBEDTLS_PRIVATE(volatile_slots); /** Number of slots containing key material for a key which is in * internal persistent storage. */ - size_t persistent_slots; + size_t MBEDTLS_PRIVATE(persistent_slots); /** Number of slots containing a reference to a key in a * secure element. */ - size_t external_slots; + size_t MBEDTLS_PRIVATE(external_slots); /** Number of slots which are occupied, but do not contain * key material yet. */ - size_t half_filled_slots; + size_t MBEDTLS_PRIVATE(half_filled_slots); /** Number of slots that contain cache data. */ - size_t cache_slots; + size_t MBEDTLS_PRIVATE(cache_slots); /** Number of slots that are not used for anything. */ - size_t empty_slots; + size_t MBEDTLS_PRIVATE(empty_slots); /** Number of slots that are locked. */ - size_t locked_slots; + size_t MBEDTLS_PRIVATE(locked_slots); /** Largest key id value among open keys in internal persistent storage. */ - psa_key_id_t max_open_internal_key_id; + psa_key_id_t MBEDTLS_PRIVATE(max_open_internal_key_id); /** Largest key id value among open keys in secure elements. */ - psa_key_id_t max_open_external_key_id; + psa_key_id_t MBEDTLS_PRIVATE(max_open_external_key_id); } mbedtls_psa_stats_t; /** \brief Get statistics about @@ -303,8 +292,10 @@ void mbedtls_psa_get_stats(mbedtls_psa_stats_t *stats); * \param[in] seed Buffer containing the seed value to inject. * \param[in] seed_size Size of the \p seed buffer. * The size of the seed in bytes must be greater - * or equal to both #MBEDTLS_ENTROPY_MIN_PLATFORM - * and #MBEDTLS_ENTROPY_BLOCK_SIZE. + * or equal to both #MBEDTLS_ENTROPY_BLOCK_SIZE + * and the value of \c MBEDTLS_ENTROPY_MIN_PLATFORM + * in `library/entropy_poll.h` in the Mbed TLS source + * code. * It must be less or equal to * #MBEDTLS_ENTROPY_MAX_SEED_SIZE. * @@ -417,246 +408,13 @@ psa_status_t mbedtls_psa_inject_entropy(const uint8_t *seed, * @{ */ -/** Custom Diffie-Hellman group. - * - * For keys of type #PSA_KEY_TYPE_DH_PUBLIC_KEY(#PSA_DH_FAMILY_CUSTOM) or - * #PSA_KEY_TYPE_DH_KEY_PAIR(#PSA_DH_FAMILY_CUSTOM), the group data comes - * from domain parameters set by psa_set_key_domain_parameters(). - */ -#define PSA_DH_FAMILY_CUSTOM ((psa_dh_family_t) 0x7e) - - -/** - * \brief Set domain parameters for a key. - * - * Some key types require additional domain parameters in addition to - * the key type identifier and the key size. Use this function instead - * of psa_set_key_type() when you need to specify domain parameters. - * - * The format for the required domain parameters varies based on the key type. - * - * - For RSA keys (#PSA_KEY_TYPE_RSA_PUBLIC_KEY or #PSA_KEY_TYPE_RSA_KEY_PAIR), - * the domain parameter data consists of the public exponent, - * represented as a big-endian integer with no leading zeros. - * This information is used when generating an RSA key pair. - * When importing a key, the public exponent is read from the imported - * key data and the exponent recorded in the attribute structure is ignored. - * As an exception, the public exponent 65537 is represented by an empty - * byte string. - * - For DSA keys (#PSA_KEY_TYPE_DSA_PUBLIC_KEY or #PSA_KEY_TYPE_DSA_KEY_PAIR), - * the `Dss-Params` format as defined by RFC 3279 §2.3.2. - * ``` - * Dss-Params ::= SEQUENCE { - * p INTEGER, - * q INTEGER, - * g INTEGER - * } - * ``` - * - For Diffie-Hellman key exchange keys - * (#PSA_KEY_TYPE_DH_PUBLIC_KEY(#PSA_DH_FAMILY_CUSTOM) or - * #PSA_KEY_TYPE_DH_KEY_PAIR(#PSA_DH_FAMILY_CUSTOM)), the - * `DomainParameters` format as defined by RFC 3279 §2.3.3. - * ``` - * DomainParameters ::= SEQUENCE { - * p INTEGER, -- odd prime, p=jq +1 - * g INTEGER, -- generator, g - * q INTEGER, -- factor of p-1 - * j INTEGER OPTIONAL, -- subgroup factor - * validationParams ValidationParams OPTIONAL - * } - * ValidationParams ::= SEQUENCE { - * seed BIT STRING, - * pgenCounter INTEGER - * } - * ``` - * - * \note This function may allocate memory or other resources. - * Once you have called this function on an attribute structure, - * you must call psa_reset_key_attributes() to free these resources. - * - * \note This is an experimental extension to the interface. It may change - * in future versions of the library. - * - * \param[in,out] attributes Attribute structure where the specified domain - * parameters will be stored. - * If this function fails, the content of - * \p attributes is not modified. - * \param type Key type (a \c PSA_KEY_TYPE_XXX value). - * \param[in] data Buffer containing the key domain parameters. - * The content of this buffer is interpreted - * according to \p type as described above. - * \param data_length Size of the \p data buffer in bytes. - * - * \retval #PSA_SUCCESS \emptydescription - * \retval #PSA_ERROR_INVALID_ARGUMENT \emptydescription - * \retval #PSA_ERROR_NOT_SUPPORTED \emptydescription - * \retval #PSA_ERROR_INSUFFICIENT_MEMORY \emptydescription - */ -psa_status_t psa_set_key_domain_parameters(psa_key_attributes_t *attributes, - psa_key_type_t type, - const uint8_t *data, - size_t data_length); - -/** - * \brief Get domain parameters for a key. - * - * Get the domain parameters for a key with this function, if any. The format - * of the domain parameters written to \p data is specified in the - * documentation for psa_set_key_domain_parameters(). - * - * \note This is an experimental extension to the interface. It may change - * in future versions of the library. - * - * \param[in] attributes The key attribute structure to query. - * \param[out] data On success, the key domain parameters. - * \param data_size Size of the \p data buffer in bytes. - * The buffer is guaranteed to be large - * enough if its size in bytes is at least - * the value given by - * PSA_KEY_DOMAIN_PARAMETERS_SIZE(). - * \param[out] data_length On success, the number of bytes - * that make up the key domain parameters data. - * - * \retval #PSA_SUCCESS \emptydescription - * \retval #PSA_ERROR_BUFFER_TOO_SMALL \emptydescription - */ -psa_status_t psa_get_key_domain_parameters( - const psa_key_attributes_t *attributes, - uint8_t *data, - size_t data_size, - size_t *data_length); - -/** Safe output buffer size for psa_get_key_domain_parameters(). - * - * This macro returns a compile-time constant if its arguments are - * compile-time constants. - * - * \warning This function may call its arguments multiple times or - * zero times, so you should not pass arguments that contain - * side effects. - * - * \note This is an experimental extension to the interface. It may change - * in future versions of the library. - * - * \param key_type A supported key type. - * \param key_bits The size of the key in bits. - * - * \return If the parameters are valid and supported, return - * a buffer size in bytes that guarantees that - * psa_get_key_domain_parameters() will not fail with - * #PSA_ERROR_BUFFER_TOO_SMALL. - * If the parameters are a valid combination that is not supported - * by the implementation, this macro shall return either a - * sensible size or 0. - * If the parameters are not valid, the - * return value is unspecified. - */ -#define PSA_KEY_DOMAIN_PARAMETERS_SIZE(key_type, key_bits) \ - (PSA_KEY_TYPE_IS_RSA(key_type) ? sizeof(int) : \ - PSA_KEY_TYPE_IS_DH(key_type) ? PSA_DH_KEY_DOMAIN_PARAMETERS_SIZE(key_bits) : \ - PSA_KEY_TYPE_IS_DSA(key_type) ? PSA_DSA_KEY_DOMAIN_PARAMETERS_SIZE(key_bits) : \ - 0) -#define PSA_DH_KEY_DOMAIN_PARAMETERS_SIZE(key_bits) \ - (4 + (PSA_BITS_TO_BYTES(key_bits) + 5) * 3 /*without optional parts*/) -#define PSA_DSA_KEY_DOMAIN_PARAMETERS_SIZE(key_bits) \ - (4 + (PSA_BITS_TO_BYTES(key_bits) + 5) * 2 /*p, g*/ + 34 /*q*/) +/** PAKE operation stages. */ +#define PSA_PAKE_OPERATION_STAGE_SETUP 0 +#define PSA_PAKE_OPERATION_STAGE_COLLECT_INPUTS 1 +#define PSA_PAKE_OPERATION_STAGE_COMPUTATION 2 /**@}*/ -/** \defgroup psa_tls_helpers TLS helper functions - * @{ - */ - -#if defined(MBEDTLS_ECP_C) -#include - -/** Convert an ECC curve identifier from the Mbed TLS encoding to PSA. - * - * \note This function is provided solely for the convenience of - * Mbed TLS and may be removed at any time without notice. - * - * \param grpid An Mbed TLS elliptic curve identifier - * (`MBEDTLS_ECP_DP_xxx`). - * \param[out] bits On success, the bit size of the curve. - * - * \return The corresponding PSA elliptic curve identifier - * (`PSA_ECC_FAMILY_xxx`). - * \return \c 0 on failure (\p grpid is not recognized). - */ -static inline psa_ecc_family_t mbedtls_ecc_group_to_psa(mbedtls_ecp_group_id grpid, - size_t *bits) -{ - switch (grpid) { - case MBEDTLS_ECP_DP_SECP192R1: - *bits = 192; - return PSA_ECC_FAMILY_SECP_R1; - case MBEDTLS_ECP_DP_SECP224R1: - *bits = 224; - return PSA_ECC_FAMILY_SECP_R1; - case MBEDTLS_ECP_DP_SECP256R1: - *bits = 256; - return PSA_ECC_FAMILY_SECP_R1; - case MBEDTLS_ECP_DP_SECP384R1: - *bits = 384; - return PSA_ECC_FAMILY_SECP_R1; - case MBEDTLS_ECP_DP_SECP521R1: - *bits = 521; - return PSA_ECC_FAMILY_SECP_R1; - case MBEDTLS_ECP_DP_BP256R1: - *bits = 256; - return PSA_ECC_FAMILY_BRAINPOOL_P_R1; - case MBEDTLS_ECP_DP_BP384R1: - *bits = 384; - return PSA_ECC_FAMILY_BRAINPOOL_P_R1; - case MBEDTLS_ECP_DP_BP512R1: - *bits = 512; - return PSA_ECC_FAMILY_BRAINPOOL_P_R1; - case MBEDTLS_ECP_DP_CURVE25519: - *bits = 255; - return PSA_ECC_FAMILY_MONTGOMERY; - case MBEDTLS_ECP_DP_SECP192K1: - *bits = 192; - return PSA_ECC_FAMILY_SECP_K1; - case MBEDTLS_ECP_DP_SECP224K1: - *bits = 224; - return PSA_ECC_FAMILY_SECP_K1; - case MBEDTLS_ECP_DP_SECP256K1: - *bits = 256; - return PSA_ECC_FAMILY_SECP_K1; - case MBEDTLS_ECP_DP_CURVE448: - *bits = 448; - return PSA_ECC_FAMILY_MONTGOMERY; - default: - *bits = 0; - return 0; - } -} - -/** Convert an ECC curve identifier from the PSA encoding to Mbed TLS. - * - * \note This function is provided solely for the convenience of - * Mbed TLS and may be removed at any time without notice. - * - * \param curve A PSA elliptic curve identifier - * (`PSA_ECC_FAMILY_xxx`). - * \param bits The bit-length of a private key on \p curve. - * \param bits_is_sloppy If true, \p bits may be the bit-length rounded up - * to the nearest multiple of 8. This allows the caller - * to infer the exact curve from the length of a key - * which is supplied as a byte string. - * - * \return The corresponding Mbed TLS elliptic curve identifier - * (`MBEDTLS_ECP_DP_xxx`). - * \return #MBEDTLS_ECP_DP_NONE if \c curve is not recognized. - * \return #MBEDTLS_ECP_DP_NONE if \p bits is not - * correct for \p curve. - */ -mbedtls_ecp_group_id mbedtls_ecc_group_of_psa(psa_ecc_family_t curve, - size_t bits, - int bits_is_sloppy); -#endif /* MBEDTLS_ECP_C */ - -/**@}*/ /** \defgroup psa_external_rng External random generator * @{ @@ -807,6 +565,1317 @@ psa_status_t mbedtls_psa_platform_get_builtin_key( /** @} */ +/** \addtogroup crypto_types + * @{ + */ + +#define PSA_ALG_CATEGORY_PAKE ((psa_algorithm_t) 0x0a000000) + +/** Whether the specified algorithm is a password-authenticated key exchange. + * + * \param alg An algorithm identifier (value of type #psa_algorithm_t). + * + * \return 1 if \p alg is a password-authenticated key exchange (PAKE) + * algorithm, 0 otherwise. + * This macro may return either 0 or 1 if \p alg is not a supported + * algorithm identifier. + */ +#define PSA_ALG_IS_PAKE(alg) \ + (((alg) & PSA_ALG_CATEGORY_MASK) == PSA_ALG_CATEGORY_PAKE) + +/** The Password-authenticated key exchange by juggling (J-PAKE) algorithm. + * + * This is J-PAKE as defined by RFC 8236, instantiated with the following + * parameters: + * + * - The group can be either an elliptic curve or defined over a finite field. + * - Schnorr NIZK proof as defined by RFC 8235 and using the same group as the + * J-PAKE algorithm. + * - A cryptographic hash function. + * + * To select these parameters and set up the cipher suite, call these functions + * in any order: + * + * \code + * psa_pake_cs_set_algorithm(cipher_suite, PSA_ALG_JPAKE); + * psa_pake_cs_set_primitive(cipher_suite, + * PSA_PAKE_PRIMITIVE(type, family, bits)); + * psa_pake_cs_set_hash(cipher_suite, hash); + * \endcode + * + * For more information on how to set a specific curve or field, refer to the + * documentation of the individual \c PSA_PAKE_PRIMITIVE_TYPE_XXX constants. + * + * After initializing a J-PAKE operation, call + * + * \code + * psa_pake_setup(operation, cipher_suite); + * psa_pake_set_user(operation, ...); + * psa_pake_set_peer(operation, ...); + * psa_pake_set_password_key(operation, ...); + * \endcode + * + * The password is provided as a key. This can be the password text itself, + * in an agreed character encoding, or some value derived from the password + * as required by a higher level protocol. + * + * (The implementation converts the key material to a number as described in + * Section 2.3.8 of _SEC 1: Elliptic Curve Cryptography_ + * (https://www.secg.org/sec1-v2.pdf), before reducing it modulo \c q. Here + * \c q is order of the group defined by the primitive set in the cipher suite. + * The \c psa_pake_set_password_key() function returns an error if the result + * of the reduction is 0.) + * + * The key exchange flow for J-PAKE is as follows: + * -# To get the first round data that needs to be sent to the peer, call + * \code + * // Get g1 + * psa_pake_output(operation, #PSA_PAKE_STEP_KEY_SHARE, ...); + * // Get the ZKP public key for x1 + * psa_pake_output(operation, #PSA_PAKE_STEP_ZK_PUBLIC, ...); + * // Get the ZKP proof for x1 + * psa_pake_output(operation, #PSA_PAKE_STEP_ZK_PROOF, ...); + * // Get g2 + * psa_pake_output(operation, #PSA_PAKE_STEP_KEY_SHARE, ...); + * // Get the ZKP public key for x2 + * psa_pake_output(operation, #PSA_PAKE_STEP_ZK_PUBLIC, ...); + * // Get the ZKP proof for x2 + * psa_pake_output(operation, #PSA_PAKE_STEP_ZK_PROOF, ...); + * \endcode + * -# To provide the first round data received from the peer to the operation, + * call + * \code + * // Set g3 + * psa_pake_input(operation, #PSA_PAKE_STEP_KEY_SHARE, ...); + * // Set the ZKP public key for x3 + * psa_pake_input(operation, #PSA_PAKE_STEP_ZK_PUBLIC, ...); + * // Set the ZKP proof for x3 + * psa_pake_input(operation, #PSA_PAKE_STEP_ZK_PROOF, ...); + * // Set g4 + * psa_pake_input(operation, #PSA_PAKE_STEP_KEY_SHARE, ...); + * // Set the ZKP public key for x4 + * psa_pake_input(operation, #PSA_PAKE_STEP_ZK_PUBLIC, ...); + * // Set the ZKP proof for x4 + * psa_pake_input(operation, #PSA_PAKE_STEP_ZK_PROOF, ...); + * \endcode + * -# To get the second round data that needs to be sent to the peer, call + * \code + * // Get A + * psa_pake_output(operation, #PSA_PAKE_STEP_KEY_SHARE, ...); + * // Get ZKP public key for x2*s + * psa_pake_output(operation, #PSA_PAKE_STEP_ZK_PUBLIC, ...); + * // Get ZKP proof for x2*s + * psa_pake_output(operation, #PSA_PAKE_STEP_ZK_PROOF, ...); + * \endcode + * -# To provide the second round data received from the peer to the operation, + * call + * \code + * // Set B + * psa_pake_input(operation, #PSA_PAKE_STEP_KEY_SHARE, ...); + * // Set ZKP public key for x4*s + * psa_pake_input(operation, #PSA_PAKE_STEP_ZK_PUBLIC, ...); + * // Set ZKP proof for x4*s + * psa_pake_input(operation, #PSA_PAKE_STEP_ZK_PROOF, ...); + * \endcode + * -# To access the shared secret call + * \code + * // Get Ka=Kb=K + * psa_pake_get_implicit_key() + * \endcode + * + * For more information consult the documentation of the individual + * \c PSA_PAKE_STEP_XXX constants. + * + * At this point there is a cryptographic guarantee that only the authenticated + * party who used the same password is able to compute the key. But there is no + * guarantee that the peer is the party it claims to be and was able to do so. + * + * That is, the authentication is only implicit (the peer is not authenticated + * at this point, and no action should be taken that assume that they are - like + * for example accessing restricted files). + * + * To make the authentication explicit there are various methods, see Section 5 + * of RFC 8236 for two examples. + * + */ +#define PSA_ALG_JPAKE ((psa_algorithm_t) 0x0a000100) + +/** @} */ + +/** \defgroup pake Password-authenticated key exchange (PAKE) + * + * This is a proposed PAKE interface for the PSA Crypto API. It is not part of + * the official PSA Crypto API yet. + * + * \note The content of this section is not part of the stable API and ABI + * of Mbed TLS and may change arbitrarily from version to version. + * Same holds for the corresponding macros #PSA_ALG_CATEGORY_PAKE and + * #PSA_ALG_JPAKE. + * @{ + */ + +/** \brief Encoding of the application role of PAKE + * + * Encodes the application's role in the algorithm is being executed. For more + * information see the documentation of individual \c PSA_PAKE_ROLE_XXX + * constants. + */ +typedef uint8_t psa_pake_role_t; + +/** Encoding of input and output indicators for PAKE. + * + * Some PAKE algorithms need to exchange more data than just a single key share. + * This type is for encoding additional input and output data for such + * algorithms. + */ +typedef uint8_t psa_pake_step_t; + +/** Encoding of the type of the PAKE's primitive. + * + * Values defined by this standard will never be in the range 0x80-0xff. + * Vendors who define additional types must use an encoding in this range. + * + * For more information see the documentation of individual + * \c PSA_PAKE_PRIMITIVE_TYPE_XXX constants. + */ +typedef uint8_t psa_pake_primitive_type_t; + +/** \brief Encoding of the family of the primitive associated with the PAKE. + * + * For more information see the documentation of individual + * \c PSA_PAKE_PRIMITIVE_TYPE_XXX constants. + */ +typedef uint8_t psa_pake_family_t; + +/** \brief Encoding of the primitive associated with the PAKE. + * + * For more information see the documentation of the #PSA_PAKE_PRIMITIVE macro. + */ +typedef uint32_t psa_pake_primitive_t; + +/** A value to indicate no role in a PAKE algorithm. + * This value can be used in a call to psa_pake_set_role() for symmetric PAKE + * algorithms which do not assign roles. + */ +#define PSA_PAKE_ROLE_NONE ((psa_pake_role_t) 0x00) + +/** The first peer in a balanced PAKE. + * + * Although balanced PAKE algorithms are symmetric, some of them needs an + * ordering of peers for the transcript calculations. If the algorithm does not + * need this, both #PSA_PAKE_ROLE_FIRST and #PSA_PAKE_ROLE_SECOND are + * accepted. + */ +#define PSA_PAKE_ROLE_FIRST ((psa_pake_role_t) 0x01) + +/** The second peer in a balanced PAKE. + * + * Although balanced PAKE algorithms are symmetric, some of them needs an + * ordering of peers for the transcript calculations. If the algorithm does not + * need this, either #PSA_PAKE_ROLE_FIRST or #PSA_PAKE_ROLE_SECOND are + * accepted. + */ +#define PSA_PAKE_ROLE_SECOND ((psa_pake_role_t) 0x02) + +/** The client in an augmented PAKE. + * + * Augmented PAKE algorithms need to differentiate between client and server. + */ +#define PSA_PAKE_ROLE_CLIENT ((psa_pake_role_t) 0x11) + +/** The server in an augmented PAKE. + * + * Augmented PAKE algorithms need to differentiate between client and server. + */ +#define PSA_PAKE_ROLE_SERVER ((psa_pake_role_t) 0x12) + +/** The PAKE primitive type indicating the use of elliptic curves. + * + * The values of the \c family and \c bits fields of the cipher suite identify a + * specific elliptic curve, using the same mapping that is used for ECC + * (::psa_ecc_family_t) keys. + * + * (Here \c family means the value returned by psa_pake_cs_get_family() and + * \c bits means the value returned by psa_pake_cs_get_bits().) + * + * Input and output during the operation can involve group elements and scalar + * values: + * -# The format for group elements is the same as for public keys on the + * specific curve would be. For more information, consult the documentation of + * psa_export_public_key(). + * -# The format for scalars is the same as for private keys on the specific + * curve would be. For more information, consult the documentation of + * psa_export_key(). + */ +#define PSA_PAKE_PRIMITIVE_TYPE_ECC ((psa_pake_primitive_type_t) 0x01) + +/** The PAKE primitive type indicating the use of Diffie-Hellman groups. + * + * The values of the \c family and \c bits fields of the cipher suite identify + * a specific Diffie-Hellman group, using the same mapping that is used for + * Diffie-Hellman (::psa_dh_family_t) keys. + * + * (Here \c family means the value returned by psa_pake_cs_get_family() and + * \c bits means the value returned by psa_pake_cs_get_bits().) + * + * Input and output during the operation can involve group elements and scalar + * values: + * -# The format for group elements is the same as for public keys on the + * specific group would be. For more information, consult the documentation of + * psa_export_public_key(). + * -# The format for scalars is the same as for private keys on the specific + * group would be. For more information, consult the documentation of + * psa_export_key(). + */ +#define PSA_PAKE_PRIMITIVE_TYPE_DH ((psa_pake_primitive_type_t) 0x02) + +/** Construct a PAKE primitive from type, family and bit-size. + * + * \param pake_type The type of the primitive + * (value of type ::psa_pake_primitive_type_t). + * \param pake_family The family of the primitive + * (the type and interpretation of this parameter depends + * on \p pake_type, for more information consult the + * documentation of individual ::psa_pake_primitive_type_t + * constants). + * \param pake_bits The bit-size of the primitive + * (Value of type \c size_t. The interpretation + * of this parameter depends on \p pake_family, for more + * information consult the documentation of individual + * ::psa_pake_primitive_type_t constants). + * + * \return The constructed primitive value of type ::psa_pake_primitive_t. + * Return 0 if the requested primitive can't be encoded as + * ::psa_pake_primitive_t. + */ +#define PSA_PAKE_PRIMITIVE(pake_type, pake_family, pake_bits) \ + ((pake_bits & 0xFFFF) != pake_bits) ? 0 : \ + ((psa_pake_primitive_t) (((pake_type) << 24 | \ + (pake_family) << 16) | (pake_bits))) + +/** The key share being sent to or received from the peer. + * + * The format for both input and output at this step is the same as for public + * keys on the group determined by the primitive (::psa_pake_primitive_t) would + * be. + * + * For more information on the format, consult the documentation of + * psa_export_public_key(). + * + * For information regarding how the group is determined, consult the + * documentation #PSA_PAKE_PRIMITIVE. + */ +#define PSA_PAKE_STEP_KEY_SHARE ((psa_pake_step_t) 0x01) + +/** A Schnorr NIZKP public key. + * + * This is the ephemeral public key in the Schnorr Non-Interactive + * Zero-Knowledge Proof (the value denoted by the letter 'V' in RFC 8235). + * + * The format for both input and output at this step is the same as for public + * keys on the group determined by the primitive (::psa_pake_primitive_t) would + * be. + * + * For more information on the format, consult the documentation of + * psa_export_public_key(). + * + * For information regarding how the group is determined, consult the + * documentation #PSA_PAKE_PRIMITIVE. + */ +#define PSA_PAKE_STEP_ZK_PUBLIC ((psa_pake_step_t) 0x02) + +/** A Schnorr NIZKP proof. + * + * This is the proof in the Schnorr Non-Interactive Zero-Knowledge Proof (the + * value denoted by the letter 'r' in RFC 8235). + * + * Both for input and output, the value at this step is an integer less than + * the order of the group selected in the cipher suite. The format depends on + * the group as well: + * + * - For Montgomery curves, the encoding is little endian. + * - For everything else the encoding is big endian (see Section 2.3.8 of + * _SEC 1: Elliptic Curve Cryptography_ at https://www.secg.org/sec1-v2.pdf). + * + * In both cases leading zeroes are allowed as long as the length in bytes does + * not exceed the byte length of the group order. + * + * For information regarding how the group is determined, consult the + * documentation #PSA_PAKE_PRIMITIVE. + */ +#define PSA_PAKE_STEP_ZK_PROOF ((psa_pake_step_t) 0x03) + +/** The type of the data structure for PAKE cipher suites. + * + * This is an implementation-defined \c struct. Applications should not + * make any assumptions about the content of this structure. + * Implementation details can change in future versions without notice. + */ +typedef struct psa_pake_cipher_suite_s psa_pake_cipher_suite_t; + +/** Return an initial value for a PAKE cipher suite object. + */ +static psa_pake_cipher_suite_t psa_pake_cipher_suite_init(void); + +/** Retrieve the PAKE algorithm from a PAKE cipher suite. + * + * \param[in] cipher_suite The cipher suite structure to query. + * + * \return The PAKE algorithm stored in the cipher suite structure. + */ +static psa_algorithm_t psa_pake_cs_get_algorithm( + const psa_pake_cipher_suite_t *cipher_suite); + +/** Declare the PAKE algorithm for the cipher suite. + * + * This function overwrites any PAKE algorithm + * previously set in \p cipher_suite. + * + * \param[out] cipher_suite The cipher suite structure to write to. + * \param algorithm The PAKE algorithm to write. + * (`PSA_ALG_XXX` values of type ::psa_algorithm_t + * such that #PSA_ALG_IS_PAKE(\c alg) is true.) + * If this is 0, the PAKE algorithm in + * \p cipher_suite becomes unspecified. + */ +static void psa_pake_cs_set_algorithm(psa_pake_cipher_suite_t *cipher_suite, + psa_algorithm_t algorithm); + +/** Retrieve the primitive from a PAKE cipher suite. + * + * \param[in] cipher_suite The cipher suite structure to query. + * + * \return The primitive stored in the cipher suite structure. + */ +static psa_pake_primitive_t psa_pake_cs_get_primitive( + const psa_pake_cipher_suite_t *cipher_suite); + +/** Declare the primitive for a PAKE cipher suite. + * + * This function overwrites any primitive previously set in \p cipher_suite. + * + * \param[out] cipher_suite The cipher suite structure to write to. + * \param primitive The primitive to write. If this is 0, the + * primitive type in \p cipher_suite becomes + * unspecified. + */ +static void psa_pake_cs_set_primitive(psa_pake_cipher_suite_t *cipher_suite, + psa_pake_primitive_t primitive); + +/** Retrieve the PAKE family from a PAKE cipher suite. + * + * \param[in] cipher_suite The cipher suite structure to query. + * + * \return The PAKE family stored in the cipher suite structure. + */ +static psa_pake_family_t psa_pake_cs_get_family( + const psa_pake_cipher_suite_t *cipher_suite); + +/** Retrieve the PAKE primitive bit-size from a PAKE cipher suite. + * + * \param[in] cipher_suite The cipher suite structure to query. + * + * \return The PAKE primitive bit-size stored in the cipher suite structure. + */ +static uint16_t psa_pake_cs_get_bits( + const psa_pake_cipher_suite_t *cipher_suite); + +/** Retrieve the hash algorithm from a PAKE cipher suite. + * + * \param[in] cipher_suite The cipher suite structure to query. + * + * \return The hash algorithm stored in the cipher suite structure. The return + * value is 0 if the PAKE is not parametrised by a hash algorithm or if + * the hash algorithm is not set. + */ +static psa_algorithm_t psa_pake_cs_get_hash( + const psa_pake_cipher_suite_t *cipher_suite); + +/** Declare the hash algorithm for a PAKE cipher suite. + * + * This function overwrites any hash algorithm + * previously set in \p cipher_suite. + * + * Refer to the documentation of individual PAKE algorithm types (`PSA_ALG_XXX` + * values of type ::psa_algorithm_t such that #PSA_ALG_IS_PAKE(\c alg) is true) + * for more information. + * + * \param[out] cipher_suite The cipher suite structure to write to. + * \param hash The hash involved in the cipher suite. + * (`PSA_ALG_XXX` values of type ::psa_algorithm_t + * such that #PSA_ALG_IS_HASH(\c alg) is true.) + * If this is 0, the hash algorithm in + * \p cipher_suite becomes unspecified. + */ +static void psa_pake_cs_set_hash(psa_pake_cipher_suite_t *cipher_suite, + psa_algorithm_t hash); + +/** The type of the state data structure for PAKE operations. + * + * Before calling any function on a PAKE operation object, the application + * must initialize it by any of the following means: + * - Set the structure to all-bits-zero, for example: + * \code + * psa_pake_operation_t operation; + * memset(&operation, 0, sizeof(operation)); + * \endcode + * - Initialize the structure to logical zero values, for example: + * \code + * psa_pake_operation_t operation = {0}; + * \endcode + * - Initialize the structure to the initializer #PSA_PAKE_OPERATION_INIT, + * for example: + * \code + * psa_pake_operation_t operation = PSA_PAKE_OPERATION_INIT; + * \endcode + * - Assign the result of the function psa_pake_operation_init() + * to the structure, for example: + * \code + * psa_pake_operation_t operation; + * operation = psa_pake_operation_init(); + * \endcode + * + * This is an implementation-defined \c struct. Applications should not + * make any assumptions about the content of this structure. + * Implementation details can change in future versions without notice. */ +typedef struct psa_pake_operation_s psa_pake_operation_t; + +/** The type of input values for PAKE operations. */ +typedef struct psa_crypto_driver_pake_inputs_s psa_crypto_driver_pake_inputs_t; + +/** The type of computation stage for J-PAKE operations. */ +typedef struct psa_jpake_computation_stage_s psa_jpake_computation_stage_t; + +/** Return an initial value for a PAKE operation object. + */ +static psa_pake_operation_t psa_pake_operation_init(void); + +/** Get the length of the password in bytes from given inputs. + * + * \param[in] inputs Operation inputs. + * \param[out] password_len Password length. + * + * \retval #PSA_SUCCESS + * Success. + * \retval #PSA_ERROR_BAD_STATE + * Password hasn't been set yet. + */ +psa_status_t psa_crypto_driver_pake_get_password_len( + const psa_crypto_driver_pake_inputs_t *inputs, + size_t *password_len); + +/** Get the password from given inputs. + * + * \param[in] inputs Operation inputs. + * \param[out] buffer Return buffer for password. + * \param buffer_size Size of the return buffer in bytes. + * \param[out] buffer_length Actual size of the password in bytes. + * + * \retval #PSA_SUCCESS + * Success. + * \retval #PSA_ERROR_BAD_STATE + * Password hasn't been set yet. + */ +psa_status_t psa_crypto_driver_pake_get_password( + const psa_crypto_driver_pake_inputs_t *inputs, + uint8_t *buffer, size_t buffer_size, size_t *buffer_length); + +/** Get the length of the user id in bytes from given inputs. + * + * \param[in] inputs Operation inputs. + * \param[out] user_len User id length. + * + * \retval #PSA_SUCCESS + * Success. + * \retval #PSA_ERROR_BAD_STATE + * User id hasn't been set yet. + */ +psa_status_t psa_crypto_driver_pake_get_user_len( + const psa_crypto_driver_pake_inputs_t *inputs, + size_t *user_len); + +/** Get the length of the peer id in bytes from given inputs. + * + * \param[in] inputs Operation inputs. + * \param[out] peer_len Peer id length. + * + * \retval #PSA_SUCCESS + * Success. + * \retval #PSA_ERROR_BAD_STATE + * Peer id hasn't been set yet. + */ +psa_status_t psa_crypto_driver_pake_get_peer_len( + const psa_crypto_driver_pake_inputs_t *inputs, + size_t *peer_len); + +/** Get the user id from given inputs. + * + * \param[in] inputs Operation inputs. + * \param[out] user_id User id. + * \param user_id_size Size of \p user_id in bytes. + * \param[out] user_id_len Size of the user id in bytes. + * + * \retval #PSA_SUCCESS + * Success. + * \retval #PSA_ERROR_BAD_STATE + * User id hasn't been set yet. + * \retval #PSA_ERROR_BUFFER_TOO_SMALL + * The size of the \p user_id is too small. + */ +psa_status_t psa_crypto_driver_pake_get_user( + const psa_crypto_driver_pake_inputs_t *inputs, + uint8_t *user_id, size_t user_id_size, size_t *user_id_len); + +/** Get the peer id from given inputs. + * + * \param[in] inputs Operation inputs. + * \param[out] peer_id Peer id. + * \param peer_id_size Size of \p peer_id in bytes. + * \param[out] peer_id_length Size of the peer id in bytes. + * + * \retval #PSA_SUCCESS + * Success. + * \retval #PSA_ERROR_BAD_STATE + * Peer id hasn't been set yet. + * \retval #PSA_ERROR_BUFFER_TOO_SMALL + * The size of the \p peer_id is too small. + */ +psa_status_t psa_crypto_driver_pake_get_peer( + const psa_crypto_driver_pake_inputs_t *inputs, + uint8_t *peer_id, size_t peer_id_size, size_t *peer_id_length); + +/** Get the cipher suite from given inputs. + * + * \param[in] inputs Operation inputs. + * \param[out] cipher_suite Return buffer for role. + * + * \retval #PSA_SUCCESS + * Success. + * \retval #PSA_ERROR_BAD_STATE + * Cipher_suite hasn't been set yet. + */ +psa_status_t psa_crypto_driver_pake_get_cipher_suite( + const psa_crypto_driver_pake_inputs_t *inputs, + psa_pake_cipher_suite_t *cipher_suite); + +/** Set the session information for a password-authenticated key exchange. + * + * The sequence of operations to set up a password-authenticated key exchange + * is as follows: + * -# Allocate an operation object which will be passed to all the functions + * listed here. + * -# Initialize the operation object with one of the methods described in the + * documentation for #psa_pake_operation_t, e.g. + * #PSA_PAKE_OPERATION_INIT. + * -# Call psa_pake_setup() to specify the cipher suite. + * -# Call \c psa_pake_set_xxx() functions on the operation to complete the + * setup. The exact sequence of \c psa_pake_set_xxx() functions that needs + * to be called depends on the algorithm in use. + * + * Refer to the documentation of individual PAKE algorithm types (`PSA_ALG_XXX` + * values of type ::psa_algorithm_t such that #PSA_ALG_IS_PAKE(\c alg) is true) + * for more information. + * + * A typical sequence of calls to perform a password-authenticated key + * exchange: + * -# Call psa_pake_output(operation, #PSA_PAKE_STEP_KEY_SHARE, ...) to get the + * key share that needs to be sent to the peer. + * -# Call psa_pake_input(operation, #PSA_PAKE_STEP_KEY_SHARE, ...) to provide + * the key share that was received from the peer. + * -# Depending on the algorithm additional calls to psa_pake_output() and + * psa_pake_input() might be necessary. + * -# Call psa_pake_get_implicit_key() for accessing the shared secret. + * + * Refer to the documentation of individual PAKE algorithm types (`PSA_ALG_XXX` + * values of type ::psa_algorithm_t such that #PSA_ALG_IS_PAKE(\c alg) is true) + * for more information. + * + * If an error occurs at any step after a call to psa_pake_setup(), + * the operation will need to be reset by a call to psa_pake_abort(). The + * application may call psa_pake_abort() at any time after the operation + * has been initialized. + * + * After a successful call to psa_pake_setup(), the application must + * eventually terminate the operation. The following events terminate an + * operation: + * - A call to psa_pake_abort(). + * - A successful call to psa_pake_get_implicit_key(). + * + * \param[in,out] operation The operation object to set up. It must have + * been initialized but not set up yet. + * \param[in] cipher_suite The cipher suite to use. (A cipher suite fully + * characterizes a PAKE algorithm and determines + * the algorithm as well.) + * + * \retval #PSA_SUCCESS + * Success. + * \retval #PSA_ERROR_INVALID_ARGUMENT + * The algorithm in \p cipher_suite is not a PAKE algorithm, or the + * PAKE primitive in \p cipher_suite is not compatible with the + * PAKE algorithm, or the hash algorithm in \p cipher_suite is invalid + * or not compatible with the PAKE algorithm and primitive. + * \retval #PSA_ERROR_NOT_SUPPORTED + * The algorithm in \p cipher_suite is not a supported PAKE algorithm, + * or the PAKE primitive in \p cipher_suite is not supported or not + * compatible with the PAKE algorithm, or the hash algorithm in + * \p cipher_suite is not supported or not compatible with the PAKE + * algorithm and primitive. + * \retval #PSA_ERROR_COMMUNICATION_FAILURE \emptydescription + * \retval #PSA_ERROR_CORRUPTION_DETECTED \emptydescription + * \retval #PSA_ERROR_BAD_STATE + * The operation state is not valid, or + * the library has not been previously initialized by psa_crypto_init(). + * It is implementation-dependent whether a failure to initialize + * results in this error code. + */ +psa_status_t psa_pake_setup(psa_pake_operation_t *operation, + const psa_pake_cipher_suite_t *cipher_suite); + +/** Set the password for a password-authenticated key exchange from key ID. + * + * Call this function when the password, or a value derived from the password, + * is already present in the key store. + * + * \param[in,out] operation The operation object to set the password for. It + * must have been set up by psa_pake_setup() and + * not yet in use (neither psa_pake_output() nor + * psa_pake_input() has been called yet). It must + * be on operation for which the password hasn't + * been set yet (psa_pake_set_password_key() + * hasn't been called yet). + * \param password Identifier of the key holding the password or a + * value derived from the password (eg. by a + * memory-hard function). It must remain valid + * until the operation terminates. It must be of + * type #PSA_KEY_TYPE_PASSWORD or + * #PSA_KEY_TYPE_PASSWORD_HASH. It has to allow + * the usage #PSA_KEY_USAGE_DERIVE. + * + * \retval #PSA_SUCCESS + * Success. + * \retval #PSA_ERROR_INVALID_HANDLE + * \p password is not a valid key identifier. + * \retval #PSA_ERROR_NOT_PERMITTED + * The key does not have the #PSA_KEY_USAGE_DERIVE flag, or it does not + * permit the \p operation's algorithm. + * \retval #PSA_ERROR_INVALID_ARGUMENT + * The key type for \p password is not #PSA_KEY_TYPE_PASSWORD or + * #PSA_KEY_TYPE_PASSWORD_HASH, or \p password is not compatible with + * the \p operation's cipher suite. + * \retval #PSA_ERROR_NOT_SUPPORTED + * The key type or key size of \p password is not supported with the + * \p operation's cipher suite. + * \retval #PSA_ERROR_COMMUNICATION_FAILURE \emptydescription + * \retval #PSA_ERROR_CORRUPTION_DETECTED \emptydescription + * \retval #PSA_ERROR_STORAGE_FAILURE \emptydescription + * \retval #PSA_ERROR_DATA_CORRUPT \emptydescription + * \retval #PSA_ERROR_DATA_INVALID \emptydescription + * \retval #PSA_ERROR_BAD_STATE + * The operation state is not valid (it must have been set up.), or + * the library has not been previously initialized by psa_crypto_init(). + * It is implementation-dependent whether a failure to initialize + * results in this error code. + */ +psa_status_t psa_pake_set_password_key(psa_pake_operation_t *operation, + mbedtls_svc_key_id_t password); + +/** Set the user ID for a password-authenticated key exchange. + * + * Call this function to set the user ID. For PAKE algorithms that associate a + * user identifier with each side of the session you need to call + * psa_pake_set_peer() as well. For PAKE algorithms that associate a single + * user identifier with the session, call psa_pake_set_user() only. + * + * Refer to the documentation of individual PAKE algorithm types (`PSA_ALG_XXX` + * values of type ::psa_algorithm_t such that #PSA_ALG_IS_PAKE(\c alg) is true) + * for more information. + * + * \param[in,out] operation The operation object to set the user ID for. It + * must have been set up by psa_pake_setup() and + * not yet in use (neither psa_pake_output() nor + * psa_pake_input() has been called yet). It must + * be on operation for which the user ID hasn't + * been set (psa_pake_set_user() hasn't been + * called yet). + * \param[in] user_id The user ID to authenticate with. + * \param user_id_len Size of the \p user_id buffer in bytes. + * + * \retval #PSA_SUCCESS + * Success. + * \retval #PSA_ERROR_INVALID_ARGUMENT + * \p user_id is not valid for the \p operation's algorithm and cipher + * suite. + * \retval #PSA_ERROR_NOT_SUPPORTED + * The value of \p user_id is not supported by the implementation. + * \retval #PSA_ERROR_INSUFFICIENT_MEMORY \emptydescription + * \retval #PSA_ERROR_COMMUNICATION_FAILURE \emptydescription + * \retval #PSA_ERROR_CORRUPTION_DETECTED \emptydescription + * \retval #PSA_ERROR_BAD_STATE + * The operation state is not valid, or + * the library has not been previously initialized by psa_crypto_init(). + * It is implementation-dependent whether a failure to initialize + * results in this error code. + */ +psa_status_t psa_pake_set_user(psa_pake_operation_t *operation, + const uint8_t *user_id, + size_t user_id_len); + +/** Set the peer ID for a password-authenticated key exchange. + * + * Call this function in addition to psa_pake_set_user() for PAKE algorithms + * that associate a user identifier with each side of the session. For PAKE + * algorithms that associate a single user identifier with the session, call + * psa_pake_set_user() only. + * + * Refer to the documentation of individual PAKE algorithm types (`PSA_ALG_XXX` + * values of type ::psa_algorithm_t such that #PSA_ALG_IS_PAKE(\c alg) is true) + * for more information. + * + * \param[in,out] operation The operation object to set the peer ID for. It + * must have been set up by psa_pake_setup() and + * not yet in use (neither psa_pake_output() nor + * psa_pake_input() has been called yet). It must + * be on operation for which the peer ID hasn't + * been set (psa_pake_set_peer() hasn't been + * called yet). + * \param[in] peer_id The peer's ID to authenticate. + * \param peer_id_len Size of the \p peer_id buffer in bytes. + * + * \retval #PSA_SUCCESS + * Success. + * \retval #PSA_ERROR_INVALID_ARGUMENT + * \p peer_id is not valid for the \p operation's algorithm and cipher + * suite. + * \retval #PSA_ERROR_NOT_SUPPORTED + * The algorithm doesn't associate a second identity with the session. + * \retval #PSA_ERROR_INSUFFICIENT_MEMORY \emptydescription + * \retval #PSA_ERROR_COMMUNICATION_FAILURE \emptydescription + * \retval #PSA_ERROR_CORRUPTION_DETECTED \emptydescription + * \retval #PSA_ERROR_BAD_STATE + * Calling psa_pake_set_peer() is invalid with the \p operation's + * algorithm, the operation state is not valid, or the library has not + * been previously initialized by psa_crypto_init(). + * It is implementation-dependent whether a failure to initialize + * results in this error code. + */ +psa_status_t psa_pake_set_peer(psa_pake_operation_t *operation, + const uint8_t *peer_id, + size_t peer_id_len); + +/** Set the application role for a password-authenticated key exchange. + * + * Not all PAKE algorithms need to differentiate the communicating entities. + * It is optional to call this function for PAKEs that don't require a role + * to be specified. For such PAKEs the application role parameter is ignored, + * or #PSA_PAKE_ROLE_NONE can be passed as \c role. + * + * Refer to the documentation of individual PAKE algorithm types (`PSA_ALG_XXX` + * values of type ::psa_algorithm_t such that #PSA_ALG_IS_PAKE(\c alg) is true) + * for more information. + * + * \param[in,out] operation The operation object to specify the + * application's role for. It must have been set up + * by psa_pake_setup() and not yet in use (neither + * psa_pake_output() nor psa_pake_input() has been + * called yet). It must be on operation for which + * the application's role hasn't been specified + * (psa_pake_set_role() hasn't been called yet). + * \param role A value of type ::psa_pake_role_t indicating the + * application's role in the PAKE the algorithm + * that is being set up. For more information see + * the documentation of \c PSA_PAKE_ROLE_XXX + * constants. + * + * \retval #PSA_SUCCESS + * Success. + * \retval #PSA_ERROR_INVALID_ARGUMENT + * The \p role is not a valid PAKE role in the \p operation’s algorithm. + * \retval #PSA_ERROR_NOT_SUPPORTED + * The \p role for this algorithm is not supported or is not valid. + * \retval #PSA_ERROR_COMMUNICATION_FAILURE \emptydescription + * \retval #PSA_ERROR_CORRUPTION_DETECTED \emptydescription + * \retval #PSA_ERROR_BAD_STATE + * The operation state is not valid, or + * the library has not been previously initialized by psa_crypto_init(). + * It is implementation-dependent whether a failure to initialize + * results in this error code. + */ +psa_status_t psa_pake_set_role(psa_pake_operation_t *operation, + psa_pake_role_t role); + +/** Get output for a step of a password-authenticated key exchange. + * + * Depending on the algorithm being executed, you might need to call this + * function several times or you might not need to call this at all. + * + * The exact sequence of calls to perform a password-authenticated key + * exchange depends on the algorithm in use. Refer to the documentation of + * individual PAKE algorithm types (`PSA_ALG_XXX` values of type + * ::psa_algorithm_t such that #PSA_ALG_IS_PAKE(\c alg) is true) for more + * information. + * + * If this function returns an error status, the operation enters an error + * state and must be aborted by calling psa_pake_abort(). + * + * \param[in,out] operation Active PAKE operation. + * \param step The step of the algorithm for which the output is + * requested. + * \param[out] output Buffer where the output is to be written in the + * format appropriate for this \p step. Refer to + * the documentation of the individual + * \c PSA_PAKE_STEP_XXX constants for more + * information. + * \param output_size Size of the \p output buffer in bytes. This must + * be at least #PSA_PAKE_OUTPUT_SIZE(\c alg, \c + * primitive, \p output_step) where \c alg and + * \p primitive are the PAKE algorithm and primitive + * in the operation's cipher suite, and \p step is + * the output step. + * + * \param[out] output_length On success, the number of bytes of the returned + * output. + * + * \retval #PSA_SUCCESS + * Success. + * \retval #PSA_ERROR_BUFFER_TOO_SMALL + * The size of the \p output buffer is too small. + * \retval #PSA_ERROR_INVALID_ARGUMENT + * \p step is not compatible with the operation's algorithm. + * \retval #PSA_ERROR_NOT_SUPPORTED + * \p step is not supported with the operation's algorithm. + * \retval #PSA_ERROR_INSUFFICIENT_ENTROPY \emptydescription + * \retval #PSA_ERROR_INSUFFICIENT_MEMORY \emptydescription + * \retval #PSA_ERROR_COMMUNICATION_FAILURE \emptydescription + * \retval #PSA_ERROR_CORRUPTION_DETECTED \emptydescription + * \retval #PSA_ERROR_STORAGE_FAILURE \emptydescription + * \retval #PSA_ERROR_DATA_CORRUPT \emptydescription + * \retval #PSA_ERROR_DATA_INVALID \emptydescription + * \retval #PSA_ERROR_BAD_STATE + * The operation state is not valid (it must be active, and fully set + * up, and this call must conform to the algorithm's requirements + * for ordering of input and output steps), or + * the library has not been previously initialized by psa_crypto_init(). + * It is implementation-dependent whether a failure to initialize + * results in this error code. + */ +psa_status_t psa_pake_output(psa_pake_operation_t *operation, + psa_pake_step_t step, + uint8_t *output, + size_t output_size, + size_t *output_length); + +/** Provide input for a step of a password-authenticated key exchange. + * + * Depending on the algorithm being executed, you might need to call this + * function several times or you might not need to call this at all. + * + * The exact sequence of calls to perform a password-authenticated key + * exchange depends on the algorithm in use. Refer to the documentation of + * individual PAKE algorithm types (`PSA_ALG_XXX` values of type + * ::psa_algorithm_t such that #PSA_ALG_IS_PAKE(\c alg) is true) for more + * information. + * + * If this function returns an error status, the operation enters an error + * state and must be aborted by calling psa_pake_abort(). + * + * \param[in,out] operation Active PAKE operation. + * \param step The step for which the input is provided. + * \param[in] input Buffer containing the input in the format + * appropriate for this \p step. Refer to the + * documentation of the individual + * \c PSA_PAKE_STEP_XXX constants for more + * information. + * \param input_length Size of the \p input buffer in bytes. + * + * \retval #PSA_SUCCESS + * Success. + * \retval #PSA_ERROR_INVALID_SIGNATURE + * The verification fails for a #PSA_PAKE_STEP_ZK_PROOF input step. + * \retval #PSA_ERROR_INVALID_ARGUMENT + * \p input_length is not compatible with the \p operation’s algorithm, + * or the \p input is not valid for the \p operation's algorithm, + * cipher suite or \p step. + * \retval #PSA_ERROR_NOT_SUPPORTED + * \p step p is not supported with the \p operation's algorithm, or the + * \p input is not supported for the \p operation's algorithm, cipher + * suite or \p step. + * \retval #PSA_ERROR_INSUFFICIENT_MEMORY \emptydescription + * \retval #PSA_ERROR_COMMUNICATION_FAILURE \emptydescription + * \retval #PSA_ERROR_CORRUPTION_DETECTED \emptydescription + * \retval #PSA_ERROR_STORAGE_FAILURE \emptydescription + * \retval #PSA_ERROR_DATA_CORRUPT \emptydescription + * \retval #PSA_ERROR_DATA_INVALID \emptydescription + * \retval #PSA_ERROR_BAD_STATE + * The operation state is not valid (it must be active, and fully set + * up, and this call must conform to the algorithm's requirements + * for ordering of input and output steps), or + * the library has not been previously initialized by psa_crypto_init(). + * It is implementation-dependent whether a failure to initialize + * results in this error code. + */ +psa_status_t psa_pake_input(psa_pake_operation_t *operation, + psa_pake_step_t step, + const uint8_t *input, + size_t input_length); + +/** Get implicitly confirmed shared secret from a PAKE. + * + * At this point there is a cryptographic guarantee that only the authenticated + * party who used the same password is able to compute the key. But there is no + * guarantee that the peer is the party it claims to be and was able to do so. + * + * That is, the authentication is only implicit. Since the peer is not + * authenticated yet, no action should be taken yet that assumes that the peer + * is who it claims to be. For example, do not access restricted files on the + * peer's behalf until an explicit authentication has succeeded. + * + * This function can be called after the key exchange phase of the operation + * has completed. It imports the shared secret output of the PAKE into the + * provided derivation operation. The input step + * #PSA_KEY_DERIVATION_INPUT_SECRET is used when placing the shared key + * material in the key derivation operation. + * + * The exact sequence of calls to perform a password-authenticated key + * exchange depends on the algorithm in use. Refer to the documentation of + * individual PAKE algorithm types (`PSA_ALG_XXX` values of type + * ::psa_algorithm_t such that #PSA_ALG_IS_PAKE(\c alg) is true) for more + * information. + * + * When this function returns successfully, \p operation becomes inactive. + * If this function returns an error status, both \p operation + * and \c key_derivation operations enter an error state and must be aborted by + * calling psa_pake_abort() and psa_key_derivation_abort() respectively. + * + * \param[in,out] operation Active PAKE operation. + * \param[out] output A key derivation operation that is ready + * for an input step of type + * #PSA_KEY_DERIVATION_INPUT_SECRET. + * + * \retval #PSA_SUCCESS + * Success. + * \retval #PSA_ERROR_INVALID_ARGUMENT + * #PSA_KEY_DERIVATION_INPUT_SECRET is not compatible with the + * algorithm in the \p output key derivation operation. + * \retval #PSA_ERROR_NOT_SUPPORTED + * Input from a PAKE is not supported by the algorithm in the \p output + * key derivation operation. + * \retval #PSA_ERROR_INSUFFICIENT_MEMORY \emptydescription + * \retval #PSA_ERROR_COMMUNICATION_FAILURE \emptydescription + * \retval #PSA_ERROR_CORRUPTION_DETECTED \emptydescription + * \retval #PSA_ERROR_STORAGE_FAILURE \emptydescription + * \retval #PSA_ERROR_DATA_CORRUPT \emptydescription + * \retval #PSA_ERROR_DATA_INVALID \emptydescription + * \retval #PSA_ERROR_BAD_STATE + * The PAKE operation state is not valid (it must be active, but beyond + * that validity is specific to the algorithm), or + * the library has not been previously initialized by psa_crypto_init(), + * or the state of \p output is not valid for + * the #PSA_KEY_DERIVATION_INPUT_SECRET step. This can happen if the + * step is out of order or the application has done this step already + * and it may not be repeated. + * It is implementation-dependent whether a failure to initialize + * results in this error code. + */ +psa_status_t psa_pake_get_implicit_key(psa_pake_operation_t *operation, + psa_key_derivation_operation_t *output); + +/** Abort a PAKE operation. + * + * Aborting an operation frees all associated resources except for the \c + * operation structure itself. Once aborted, the operation object can be reused + * for another operation by calling psa_pake_setup() again. + * + * This function may be called at any time after the operation + * object has been initialized as described in #psa_pake_operation_t. + * + * In particular, calling psa_pake_abort() after the operation has been + * terminated by a call to psa_pake_abort() or psa_pake_get_implicit_key() + * is safe and has no effect. + * + * \param[in,out] operation The operation to abort. + * + * \retval #PSA_SUCCESS + * Success. + * \retval #PSA_ERROR_COMMUNICATION_FAILURE \emptydescription + * \retval #PSA_ERROR_CORRUPTION_DETECTED \emptydescription + * \retval #PSA_ERROR_BAD_STATE + * The library has not been previously initialized by psa_crypto_init(). + * It is implementation-dependent whether a failure to initialize + * results in this error code. + */ +psa_status_t psa_pake_abort(psa_pake_operation_t *operation); + +/**@}*/ + +/** A sufficient output buffer size for psa_pake_output(). + * + * If the size of the output buffer is at least this large, it is guaranteed + * that psa_pake_output() will not fail due to an insufficient output buffer + * size. The actual size of the output might be smaller in any given call. + * + * See also #PSA_PAKE_OUTPUT_MAX_SIZE + * + * \param alg A PAKE algorithm (\c PSA_ALG_XXX value such that + * #PSA_ALG_IS_PAKE(\p alg) is true). + * \param primitive A primitive of type ::psa_pake_primitive_t that is + * compatible with algorithm \p alg. + * \param output_step A value of type ::psa_pake_step_t that is valid for the + * algorithm \p alg. + * \return A sufficient output buffer size for the specified + * PAKE algorithm, primitive, and output step. If the + * PAKE algorithm, primitive, or output step is not + * recognized, or the parameters are incompatible, + * return 0. + */ +#define PSA_PAKE_OUTPUT_SIZE(alg, primitive, output_step) \ + (alg == PSA_ALG_JPAKE && \ + primitive == PSA_PAKE_PRIMITIVE(PSA_PAKE_PRIMITIVE_TYPE_ECC, \ + PSA_ECC_FAMILY_SECP_R1, 256) ? \ + ( \ + output_step == PSA_PAKE_STEP_KEY_SHARE ? 65 : \ + output_step == PSA_PAKE_STEP_ZK_PUBLIC ? 65 : \ + 32 \ + ) : \ + 0) + +/** A sufficient input buffer size for psa_pake_input(). + * + * The value returned by this macro is guaranteed to be large enough for any + * valid input to psa_pake_input() in an operation with the specified + * parameters. + * + * See also #PSA_PAKE_INPUT_MAX_SIZE + * + * \param alg A PAKE algorithm (\c PSA_ALG_XXX value such that + * #PSA_ALG_IS_PAKE(\p alg) is true). + * \param primitive A primitive of type ::psa_pake_primitive_t that is + * compatible with algorithm \p alg. + * \param input_step A value of type ::psa_pake_step_t that is valid for the + * algorithm \p alg. + * \return A sufficient input buffer size for the specified + * input, cipher suite and algorithm. If the cipher suite, + * the input type or PAKE algorithm is not recognized, or + * the parameters are incompatible, return 0. + */ +#define PSA_PAKE_INPUT_SIZE(alg, primitive, input_step) \ + (alg == PSA_ALG_JPAKE && \ + primitive == PSA_PAKE_PRIMITIVE(PSA_PAKE_PRIMITIVE_TYPE_ECC, \ + PSA_ECC_FAMILY_SECP_R1, 256) ? \ + ( \ + input_step == PSA_PAKE_STEP_KEY_SHARE ? 65 : \ + input_step == PSA_PAKE_STEP_ZK_PUBLIC ? 65 : \ + 32 \ + ) : \ + 0) + +/** Output buffer size for psa_pake_output() for any of the supported PAKE + * algorithm and primitive suites and output step. + * + * This macro must expand to a compile-time constant integer. + * + * The value of this macro must be at least as large as the largest value + * returned by PSA_PAKE_OUTPUT_SIZE() + * + * See also #PSA_PAKE_OUTPUT_SIZE(\p alg, \p primitive, \p output_step). + */ +#define PSA_PAKE_OUTPUT_MAX_SIZE 65 + +/** Input buffer size for psa_pake_input() for any of the supported PAKE + * algorithm and primitive suites and input step. + * + * This macro must expand to a compile-time constant integer. + * + * The value of this macro must be at least as large as the largest value + * returned by PSA_PAKE_INPUT_SIZE() + * + * See also #PSA_PAKE_INPUT_SIZE(\p alg, \p primitive, \p output_step). + */ +#define PSA_PAKE_INPUT_MAX_SIZE 65 + +/** Returns a suitable initializer for a PAKE cipher suite object of type + * psa_pake_cipher_suite_t. + */ +#define PSA_PAKE_CIPHER_SUITE_INIT { PSA_ALG_NONE, 0, 0, 0, PSA_ALG_NONE } + +/** Returns a suitable initializer for a PAKE operation object of type + * psa_pake_operation_t. + */ +#if defined(MBEDTLS_PSA_CRYPTO_CLIENT) && !defined(MBEDTLS_PSA_CRYPTO_C) +#define PSA_PAKE_OPERATION_INIT { 0 } +#else +#define PSA_PAKE_OPERATION_INIT { 0, PSA_ALG_NONE, 0, PSA_PAKE_OPERATION_STAGE_SETUP, \ + { 0 }, { { 0 } } } +#endif + +struct psa_pake_cipher_suite_s { + psa_algorithm_t algorithm; + psa_pake_primitive_type_t type; + psa_pake_family_t family; + uint16_t bits; + psa_algorithm_t hash; +}; + +static inline psa_algorithm_t psa_pake_cs_get_algorithm( + const psa_pake_cipher_suite_t *cipher_suite) +{ + return cipher_suite->algorithm; +} + +static inline void psa_pake_cs_set_algorithm( + psa_pake_cipher_suite_t *cipher_suite, + psa_algorithm_t algorithm) +{ + if (!PSA_ALG_IS_PAKE(algorithm)) { + cipher_suite->algorithm = 0; + } else { + cipher_suite->algorithm = algorithm; + } +} + +static inline psa_pake_primitive_t psa_pake_cs_get_primitive( + const psa_pake_cipher_suite_t *cipher_suite) +{ + return PSA_PAKE_PRIMITIVE(cipher_suite->type, cipher_suite->family, + cipher_suite->bits); +} + +static inline void psa_pake_cs_set_primitive( + psa_pake_cipher_suite_t *cipher_suite, + psa_pake_primitive_t primitive) +{ + cipher_suite->type = (psa_pake_primitive_type_t) (primitive >> 24); + cipher_suite->family = (psa_pake_family_t) (0xFF & (primitive >> 16)); + cipher_suite->bits = (uint16_t) (0xFFFF & primitive); +} + +static inline psa_pake_family_t psa_pake_cs_get_family( + const psa_pake_cipher_suite_t *cipher_suite) +{ + return cipher_suite->family; +} + +static inline uint16_t psa_pake_cs_get_bits( + const psa_pake_cipher_suite_t *cipher_suite) +{ + return cipher_suite->bits; +} + +static inline psa_algorithm_t psa_pake_cs_get_hash( + const psa_pake_cipher_suite_t *cipher_suite) +{ + return cipher_suite->hash; +} + +static inline void psa_pake_cs_set_hash(psa_pake_cipher_suite_t *cipher_suite, + psa_algorithm_t hash) +{ + if (!PSA_ALG_IS_HASH(hash)) { + cipher_suite->hash = 0; + } else { + cipher_suite->hash = hash; + } +} + +struct psa_crypto_driver_pake_inputs_s { + uint8_t *MBEDTLS_PRIVATE(password); + size_t MBEDTLS_PRIVATE(password_len); + uint8_t *MBEDTLS_PRIVATE(user); + size_t MBEDTLS_PRIVATE(user_len); + uint8_t *MBEDTLS_PRIVATE(peer); + size_t MBEDTLS_PRIVATE(peer_len); + psa_key_attributes_t MBEDTLS_PRIVATE(attributes); + psa_pake_cipher_suite_t MBEDTLS_PRIVATE(cipher_suite); +}; + +typedef enum psa_crypto_driver_pake_step { + PSA_JPAKE_STEP_INVALID = 0, /* Invalid step */ + PSA_JPAKE_X1_STEP_KEY_SHARE = 1, /* Round 1: input/output key share (for ephemeral private key X1).*/ + PSA_JPAKE_X1_STEP_ZK_PUBLIC = 2, /* Round 1: input/output Schnorr NIZKP public key for the X1 key */ + PSA_JPAKE_X1_STEP_ZK_PROOF = 3, /* Round 1: input/output Schnorr NIZKP proof for the X1 key */ + PSA_JPAKE_X2_STEP_KEY_SHARE = 4, /* Round 1: input/output key share (for ephemeral private key X2).*/ + PSA_JPAKE_X2_STEP_ZK_PUBLIC = 5, /* Round 1: input/output Schnorr NIZKP public key for the X2 key */ + PSA_JPAKE_X2_STEP_ZK_PROOF = 6, /* Round 1: input/output Schnorr NIZKP proof for the X2 key */ + PSA_JPAKE_X2S_STEP_KEY_SHARE = 7, /* Round 2: output X2S key (our key) */ + PSA_JPAKE_X2S_STEP_ZK_PUBLIC = 8, /* Round 2: output Schnorr NIZKP public key for the X2S key (our key) */ + PSA_JPAKE_X2S_STEP_ZK_PROOF = 9, /* Round 2: output Schnorr NIZKP proof for the X2S key (our key) */ + PSA_JPAKE_X4S_STEP_KEY_SHARE = 10, /* Round 2: input X4S key (from peer) */ + PSA_JPAKE_X4S_STEP_ZK_PUBLIC = 11, /* Round 2: input Schnorr NIZKP public key for the X4S key (from peer) */ + PSA_JPAKE_X4S_STEP_ZK_PROOF = 12 /* Round 2: input Schnorr NIZKP proof for the X4S key (from peer) */ +} psa_crypto_driver_pake_step_t; + +typedef enum psa_jpake_round { + PSA_JPAKE_FIRST = 0, + PSA_JPAKE_SECOND = 1, + PSA_JPAKE_FINISHED = 2 +} psa_jpake_round_t; + +typedef enum psa_jpake_io_mode { + PSA_JPAKE_INPUT = 0, + PSA_JPAKE_OUTPUT = 1 +} psa_jpake_io_mode_t; + +struct psa_jpake_computation_stage_s { + /* The J-PAKE round we are currently on */ + psa_jpake_round_t MBEDTLS_PRIVATE(round); + /* The 'mode' we are currently in (inputting or outputting) */ + psa_jpake_io_mode_t MBEDTLS_PRIVATE(io_mode); + /* The number of completed inputs so far this round */ + uint8_t MBEDTLS_PRIVATE(inputs); + /* The number of completed outputs so far this round */ + uint8_t MBEDTLS_PRIVATE(outputs); + /* The next expected step (KEY_SHARE, ZK_PUBLIC or ZK_PROOF) */ + psa_pake_step_t MBEDTLS_PRIVATE(step); +}; + +#define PSA_JPAKE_EXPECTED_INPUTS(round) ((round) == PSA_JPAKE_FINISHED ? 0 : \ + ((round) == PSA_JPAKE_FIRST ? 2 : 1)) +#define PSA_JPAKE_EXPECTED_OUTPUTS(round) ((round) == PSA_JPAKE_FINISHED ? 0 : \ + ((round) == PSA_JPAKE_FIRST ? 2 : 1)) + +struct psa_pake_operation_s { +#if defined(MBEDTLS_PSA_CRYPTO_CLIENT) && !defined(MBEDTLS_PSA_CRYPTO_C) + mbedtls_psa_client_handle_t handle; +#else + /** Unique ID indicating which driver got assigned to do the + * operation. Since driver contexts are driver-specific, swapping + * drivers halfway through the operation is not supported. + * ID values are auto-generated in psa_crypto_driver_wrappers.h + * ID value zero means the context is not valid or not assigned to + * any driver (i.e. none of the driver contexts are active). */ + unsigned int MBEDTLS_PRIVATE(id); + /* Algorithm of the PAKE operation */ + psa_algorithm_t MBEDTLS_PRIVATE(alg); + /* A primitive of type compatible with algorithm */ + psa_pake_primitive_t MBEDTLS_PRIVATE(primitive); + /* Stage of the PAKE operation: waiting for the setup, collecting inputs + * or computing. */ + uint8_t MBEDTLS_PRIVATE(stage); + /* Holds computation stage of the PAKE algorithms. */ + union { + uint8_t MBEDTLS_PRIVATE(dummy); +#if defined(PSA_WANT_ALG_JPAKE) + psa_jpake_computation_stage_t MBEDTLS_PRIVATE(jpake); +#endif + } MBEDTLS_PRIVATE(computation_stage); + union { + psa_driver_pake_context_t MBEDTLS_PRIVATE(ctx); + psa_crypto_driver_pake_inputs_t MBEDTLS_PRIVATE(inputs); + } MBEDTLS_PRIVATE(data); +#endif +}; + +static inline struct psa_pake_cipher_suite_s psa_pake_cipher_suite_init(void) +{ + const struct psa_pake_cipher_suite_s v = PSA_PAKE_CIPHER_SUITE_INIT; + return v; +} + +static inline struct psa_pake_operation_s psa_pake_operation_init(void) +{ + const struct psa_pake_operation_s v = PSA_PAKE_OPERATION_INIT; + return v; +} + #ifdef __cplusplus } #endif diff --git a/vendor/mbedtls/include/psa/crypto_legacy.h b/vendor/mbedtls/include/psa/crypto_legacy.h new file mode 100644 index 0000000000..7df3614d6a --- /dev/null +++ b/vendor/mbedtls/include/psa/crypto_legacy.h @@ -0,0 +1,88 @@ +/** + * \file psa/crypto_legacy.h + * + * \brief Add temporary suppport for deprecated symbols before they are + * removed from the library. + * + * PSA_WANT_KEY_TYPE_xxx_KEY_PAIR and MBEDTLS_PSA_ACCEL_KEY_TYPE_xxx_KEY_PAIR + * symbols are deprecated. + * New symols add a suffix to that base name in order to clearly state what is + * the expected use for the key (use, import, export, generate, derive). + * Here we define some backward compatibility support for uses stil using + * the legacy symbols. + */ +/* + * Copyright The Mbed TLS Contributors + * SPDX-License-Identifier: Apache-2.0 OR GPL-2.0-or-later + */ + +#ifndef MBEDTLS_PSA_CRYPTO_LEGACY_H +#define MBEDTLS_PSA_CRYPTO_LEGACY_H + +#if defined(PSA_WANT_KEY_TYPE_ECC_KEY_PAIR) //no-check-names +#if !defined(PSA_WANT_KEY_TYPE_ECC_KEY_PAIR_BASIC) +#define PSA_WANT_KEY_TYPE_ECC_KEY_PAIR_BASIC 1 +#endif +#if !defined(PSA_WANT_KEY_TYPE_ECC_KEY_PAIR_IMPORT) +#define PSA_WANT_KEY_TYPE_ECC_KEY_PAIR_IMPORT 1 +#endif +#if !defined(PSA_WANT_KEY_TYPE_ECC_KEY_PAIR_EXPORT) +#define PSA_WANT_KEY_TYPE_ECC_KEY_PAIR_EXPORT 1 +#endif +#if !defined(PSA_WANT_KEY_TYPE_ECC_KEY_PAIR_GENERATE) +#define PSA_WANT_KEY_TYPE_ECC_KEY_PAIR_GENERATE 1 +#endif +#if !defined(PSA_WANT_KEY_TYPE_ECC_KEY_PAIR_DERIVE) +#define PSA_WANT_KEY_TYPE_ECC_KEY_PAIR_DERIVE 1 +#endif +#endif + +#if defined(PSA_WANT_KEY_TYPE_RSA_KEY_PAIR) //no-check-names +#if !defined(PSA_WANT_KEY_TYPE_RSA_KEY_PAIR_BASIC) +#define PSA_WANT_KEY_TYPE_RSA_KEY_PAIR_BASIC 1 +#endif +#if !defined(PSA_WANT_KEY_TYPE_RSA_KEY_PAIR_IMPORT) +#define PSA_WANT_KEY_TYPE_RSA_KEY_PAIR_IMPORT 1 +#endif +#if !defined(PSA_WANT_KEY_TYPE_RSA_KEY_PAIR_EXPORT) +#define PSA_WANT_KEY_TYPE_RSA_KEY_PAIR_EXPORT 1 +#endif +#if !defined(PSA_WANT_KEY_TYPE_RSA_KEY_PAIR_GENERATE) +#define PSA_WANT_KEY_TYPE_RSA_KEY_PAIR_GENERATE 1 +#endif +#endif + +#if defined(MBEDTLS_PSA_ACCEL_KEY_TYPE_ECC_KEY_PAIR) //no-check-names +#if !defined(MBEDTLS_PSA_ACCEL_KEY_TYPE_ECC_KEY_PAIR_BASIC) +#define MBEDTLS_PSA_ACCEL_KEY_TYPE_ECC_KEY_PAIR_BASIC +#endif +#if !defined(MBEDTLS_PSA_ACCEL_KEY_TYPE_ECC_KEY_PAIR_IMPORT) +#define MBEDTLS_PSA_ACCEL_KEY_TYPE_ECC_KEY_PAIR_IMPORT +#endif +#if !defined(MBEDTLS_PSA_ACCEL_KEY_TYPE_ECC_KEY_PAIR_EXPORT) +#define MBEDTLS_PSA_ACCEL_KEY_TYPE_ECC_KEY_PAIR_EXPORT +#endif +#if !defined(MBEDTLS_PSA_ACCEL_KEY_TYPE_ECC_KEY_PAIR_GENERATE) +#define MBEDTLS_PSA_ACCEL_KEY_TYPE_ECC_KEY_PAIR_GENERATE +#endif +#if !defined(MBEDTLS_PSA_ACCEL_KEY_TYPE_ECC_KEY_PAIR_DERIVE) +#define MBEDTLS_PSA_ACCEL_KEY_TYPE_ECC_KEY_PAIR_DERIVE +#endif +#endif + +#if defined(MBEDTLS_PSA_ACCEL_KEY_TYPE_RSA_KEY_PAIR) //no-check-names +#if !defined(MBEDTLS_PSA_ACCEL_KEY_TYPE_RSA_KEY_PAIR_BASIC) +#define MBEDTLS_PSA_ACCEL_KEY_TYPE_RSA_KEY_PAIR_BASIC +#endif +#if !defined(MBEDTLS_PSA_ACCEL_KEY_TYPE_RSA_KEY_PAIR_IMPORT) +#define MBEDTLS_PSA_ACCEL_KEY_TYPE_RSA_KEY_PAIR_IMPORT +#endif +#if !defined(MBEDTLS_PSA_ACCEL_KEY_TYPE_RSA_KEY_PAIR_EXPORT) +#define MBEDTLS_PSA_ACCEL_KEY_TYPE_RSA_KEY_PAIR_EXPORT +#endif +#if !defined(MBEDTLS_PSA_ACCEL_KEY_TYPE_RSA_KEY_PAIR_GENERATE) +#define MBEDTLS_PSA_ACCEL_KEY_TYPE_RSA_KEY_PAIR_GENERATE +#endif +#endif + +#endif /* MBEDTLS_PSA_CRYPTO_LEGACY_H */ diff --git a/vendor/mbedtls/include/psa/crypto_platform.h b/vendor/mbedtls/include/psa/crypto_platform.h index a173c78346..a871ee1246 100644 --- a/vendor/mbedtls/include/psa/crypto_platform.h +++ b/vendor/mbedtls/include/psa/crypto_platform.h @@ -15,44 +15,25 @@ */ /* * Copyright The Mbed TLS Contributors - * SPDX-License-Identifier: Apache-2.0 - * - * Licensed under the Apache License, Version 2.0 (the "License"); you may - * not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT - * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. + * SPDX-License-Identifier: Apache-2.0 OR GPL-2.0-or-later */ #ifndef PSA_CRYPTO_PLATFORM_H #define PSA_CRYPTO_PLATFORM_H +#include "mbedtls/private_access.h" -/* Include the Mbed TLS configuration file, the way Mbed TLS does it - * in each of its header files. */ -#if !defined(MBEDTLS_CONFIG_FILE) -#include "mbedtls/config.h" -#else -#include MBEDTLS_CONFIG_FILE -#endif - -/* Translate between classic MBEDTLS_xxx feature symbols and PSA_xxx - * feature symbols. */ -#include "mbedtls/config_psa.h" +/* + * Include the build-time configuration information header. Here, we do not + * include `"mbedtls/build_info.h"` directly but `"psa/build_info.h"`, which + * is basically just an alias to it. This is to ease the maintenance of the + * TF-PSA-Crypto repository which has a different build system and + * configuration. + */ +#include "psa/build_info.h" /* PSA requires several types which C99 provides in stdint.h. */ #include -#if (defined(__ARMCC_VERSION) || defined(_MSC_VER)) && \ - !defined(inline) && !defined(__cplusplus) -#define inline __inline -#endif - #if defined(MBEDTLS_PSA_CRYPTO_KEY_ID_ENCODES_OWNER) /* Building for the PSA Crypto service on a PSA platform, a key owner is a PSA @@ -104,8 +85,18 @@ static inline int mbedtls_key_owner_id_equal(mbedtls_key_owner_id_t id1, * are expected to replace it with a custom definition. */ typedef struct { - uintptr_t opaque[2]; + uintptr_t MBEDTLS_PRIVATE(opaque)[2]; } mbedtls_psa_external_random_context_t; #endif /* MBEDTLS_PSA_CRYPTO_EXTERNAL_RNG */ +#if defined(MBEDTLS_PSA_CRYPTO_CLIENT) && !defined(MBEDTLS_PSA_CRYPTO_C) +/** The type of the client handle used in context structures + * + * When a client view of the multipart context structures is required, + * this handle is used to keep a mapping with the service side of the + * context which contains the actual data. + */ +typedef uint32_t mbedtls_psa_client_handle_t; +#endif + #endif /* PSA_CRYPTO_PLATFORM_H */ diff --git a/vendor/mbedtls/include/psa/crypto_se_driver.h b/vendor/mbedtls/include/psa/crypto_se_driver.h index a7c42dc7ad..9ce14bba62 100644 --- a/vendor/mbedtls/include/psa/crypto_se_driver.h +++ b/vendor/mbedtls/include/psa/crypto_se_driver.h @@ -17,22 +17,11 @@ /* * Copyright The Mbed TLS Contributors - * SPDX-License-Identifier: Apache-2.0 - * - * Licensed under the Apache License, Version 2.0 (the "License"); you may - * not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT - * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. + * SPDX-License-Identifier: Apache-2.0 OR GPL-2.0-or-later */ #ifndef PSA_CRYPTO_SE_DRIVER_H #define PSA_CRYPTO_SE_DRIVER_H +#include "mbedtls/private_access.h" #include "crypto_driver_common.h" @@ -97,21 +86,21 @@ typedef struct { * - psa_destroy_key() causes a call to * psa_drv_se_key_management_t::p_destroy. */ - const void *const persistent_data; + const void *const MBEDTLS_PRIVATE(persistent_data); /** The size of \c persistent_data in bytes. * * This is always equal to the value of the `persistent_data_size` field * of the ::psa_drv_se_t structure when the driver is registered. */ - const size_t persistent_data_size; + const size_t MBEDTLS_PRIVATE(persistent_data_size); /** Driver transient data. * * The core initializes this value to 0 and does not read or modify it * afterwards. The driver may store whatever it wants in this field. */ - uintptr_t transient_data; + uintptr_t MBEDTLS_PRIVATE(transient_data); } psa_drv_se_context_t; /** \brief A driver initialization function. @@ -323,28 +312,28 @@ typedef struct { /**The size in bytes of the hardware-specific secure element MAC context * structure */ - size_t context_size; + size_t MBEDTLS_PRIVATE(context_size); /** Function that performs a MAC setup operation */ - psa_drv_se_mac_setup_t p_setup; + psa_drv_se_mac_setup_t MBEDTLS_PRIVATE(p_setup); /** Function that performs a MAC update operation */ - psa_drv_se_mac_update_t p_update; + psa_drv_se_mac_update_t MBEDTLS_PRIVATE(p_update); /** Function that completes a MAC operation */ - psa_drv_se_mac_finish_t p_finish; + psa_drv_se_mac_finish_t MBEDTLS_PRIVATE(p_finish); /** Function that completes a MAC operation with a verify check */ - psa_drv_se_mac_finish_verify_t p_finish_verify; + psa_drv_se_mac_finish_verify_t MBEDTLS_PRIVATE(p_finish_verify); /** Function that aborts a previously started MAC operation */ - psa_drv_se_mac_abort_t p_abort; + psa_drv_se_mac_abort_t MBEDTLS_PRIVATE(p_abort); /** Function that performs a MAC operation in one call */ - psa_drv_se_mac_generate_t p_mac; + psa_drv_se_mac_generate_t MBEDTLS_PRIVATE(p_mac); /** Function that performs a MAC and verify operation in one call */ - psa_drv_se_mac_verify_t p_mac_verify; + psa_drv_se_mac_verify_t MBEDTLS_PRIVATE(p_mac_verify); } psa_drv_se_mac_t; /**@}*/ @@ -510,22 +499,22 @@ typedef struct { /** The size in bytes of the hardware-specific secure element cipher * context structure */ - size_t context_size; + size_t MBEDTLS_PRIVATE(context_size); /** Function that performs a cipher setup operation */ - psa_drv_se_cipher_setup_t p_setup; + psa_drv_se_cipher_setup_t MBEDTLS_PRIVATE(p_setup); /** Function that sets a cipher IV (if necessary) */ - psa_drv_se_cipher_set_iv_t p_set_iv; + psa_drv_se_cipher_set_iv_t MBEDTLS_PRIVATE(p_set_iv); /** Function that performs a cipher update operation */ - psa_drv_se_cipher_update_t p_update; + psa_drv_se_cipher_update_t MBEDTLS_PRIVATE(p_update); /** Function that completes a cipher operation */ - psa_drv_se_cipher_finish_t p_finish; + psa_drv_se_cipher_finish_t MBEDTLS_PRIVATE(p_finish); /** Function that aborts a cipher operation */ - psa_drv_se_cipher_abort_t p_abort; + psa_drv_se_cipher_abort_t MBEDTLS_PRIVATE(p_abort); /** Function that performs ECB mode for a cipher operation * (Danger: ECB mode should not be used directly by clients of the PSA * Crypto Client API) */ - psa_drv_se_cipher_ecb_t p_ecb; + psa_drv_se_cipher_ecb_t MBEDTLS_PRIVATE(p_ecb); } psa_drv_se_cipher_t; /**@}*/ @@ -681,13 +670,13 @@ typedef psa_status_t (*psa_drv_se_asymmetric_decrypt_t)(psa_drv_se_context_t *dr */ typedef struct { /** Function that performs an asymmetric sign operation */ - psa_drv_se_asymmetric_sign_t p_sign; + psa_drv_se_asymmetric_sign_t MBEDTLS_PRIVATE(p_sign); /** Function that performs an asymmetric verify operation */ - psa_drv_se_asymmetric_verify_t p_verify; + psa_drv_se_asymmetric_verify_t MBEDTLS_PRIVATE(p_verify); /** Function that performs an asymmetric encrypt operation */ - psa_drv_se_asymmetric_encrypt_t p_encrypt; + psa_drv_se_asymmetric_encrypt_t MBEDTLS_PRIVATE(p_encrypt); /** Function that performs an asymmetric decrypt operation */ - psa_drv_se_asymmetric_decrypt_t p_decrypt; + psa_drv_se_asymmetric_decrypt_t MBEDTLS_PRIVATE(p_decrypt); } psa_drv_se_asymmetric_t; /**@}*/ @@ -798,9 +787,9 @@ typedef psa_status_t (*psa_drv_se_aead_decrypt_t)(psa_drv_se_context_t *drv_cont */ typedef struct { /** Function that performs the AEAD encrypt operation */ - psa_drv_se_aead_encrypt_t p_encrypt; + psa_drv_se_aead_encrypt_t MBEDTLS_PRIVATE(p_encrypt); /** Function that performs the AEAD decrypt operation */ - psa_drv_se_aead_decrypt_t p_decrypt; + psa_drv_se_aead_decrypt_t MBEDTLS_PRIVATE(p_decrypt); } psa_drv_se_aead_t; /**@}*/ @@ -1119,19 +1108,19 @@ typedef psa_status_t (*psa_drv_se_generate_key_t)( */ typedef struct { /** Function that allocates a slot for a key. */ - psa_drv_se_allocate_key_t p_allocate; + psa_drv_se_allocate_key_t MBEDTLS_PRIVATE(p_allocate); /** Function that checks the validity of a slot for a key. */ - psa_drv_se_validate_slot_number_t p_validate_slot_number; + psa_drv_se_validate_slot_number_t MBEDTLS_PRIVATE(p_validate_slot_number); /** Function that performs a key import operation */ - psa_drv_se_import_key_t p_import; + psa_drv_se_import_key_t MBEDTLS_PRIVATE(p_import); /** Function that performs a generation */ - psa_drv_se_generate_key_t p_generate; + psa_drv_se_generate_key_t MBEDTLS_PRIVATE(p_generate); /** Function that performs a key destroy operation */ - psa_drv_se_destroy_key_t p_destroy; + psa_drv_se_destroy_key_t MBEDTLS_PRIVATE(p_destroy); /** Function that performs a key export operation */ - psa_drv_se_export_key_t p_export; + psa_drv_se_export_key_t MBEDTLS_PRIVATE(p_export); /** Function that performs a public key export operation */ - psa_drv_se_export_key_t p_export_public; + psa_drv_se_export_key_t MBEDTLS_PRIVATE(p_export_public); } psa_drv_se_key_management_t; /**@}*/ @@ -1262,16 +1251,16 @@ typedef psa_status_t (*psa_drv_se_key_derivation_export_t)(void *op_context, */ typedef struct { /** The driver-specific size of the key derivation context */ - size_t context_size; + size_t MBEDTLS_PRIVATE(context_size); /** Function that performs a key derivation setup */ - psa_drv_se_key_derivation_setup_t p_setup; + psa_drv_se_key_derivation_setup_t MBEDTLS_PRIVATE(p_setup); /** Function that sets key derivation collateral */ - psa_drv_se_key_derivation_collateral_t p_collateral; + psa_drv_se_key_derivation_collateral_t MBEDTLS_PRIVATE(p_collateral); /** Function that performs a final key derivation step */ - psa_drv_se_key_derivation_derive_t p_derive; + psa_drv_se_key_derivation_derive_t MBEDTLS_PRIVATE(p_derive); /** Function that performs a final key derivation or agreement and * exports the key */ - psa_drv_se_key_derivation_export_t p_export; + psa_drv_se_key_derivation_export_t MBEDTLS_PRIVATE(p_export); } psa_drv_se_key_derivation_t; /**@}*/ @@ -1292,7 +1281,7 @@ typedef struct { * a different version of this specification. * Use #PSA_DRV_SE_HAL_VERSION. */ - uint32_t hal_version; + uint32_t MBEDTLS_PRIVATE(hal_version); /** The size of the driver's persistent data in bytes. * @@ -1302,7 +1291,7 @@ typedef struct { * for more information about why and how a driver can use * persistent data. */ - size_t persistent_data_size; + size_t MBEDTLS_PRIVATE(persistent_data_size); /** The driver initialization function. * @@ -1314,14 +1303,14 @@ typedef struct { * If this field is \c NULL, it is equivalent to a function that does * nothing and returns #PSA_SUCCESS. */ - psa_drv_se_init_t p_init; - - const psa_drv_se_key_management_t *key_management; - const psa_drv_se_mac_t *mac; - const psa_drv_se_cipher_t *cipher; - const psa_drv_se_aead_t *aead; - const psa_drv_se_asymmetric_t *asymmetric; - const psa_drv_se_key_derivation_t *derivation; + psa_drv_se_init_t MBEDTLS_PRIVATE(p_init); + + const psa_drv_se_key_management_t *MBEDTLS_PRIVATE(key_management); + const psa_drv_se_mac_t *MBEDTLS_PRIVATE(mac); + const psa_drv_se_cipher_t *MBEDTLS_PRIVATE(cipher); + const psa_drv_se_aead_t *MBEDTLS_PRIVATE(aead); + const psa_drv_se_asymmetric_t *MBEDTLS_PRIVATE(asymmetric); + const psa_drv_se_key_derivation_t *MBEDTLS_PRIVATE(derivation); } psa_drv_se_t; /** The current version of the secure element driver HAL. diff --git a/vendor/mbedtls/include/psa/crypto_sizes.h b/vendor/mbedtls/include/psa/crypto_sizes.h index 9f58c7fb5e..635ee98f80 100644 --- a/vendor/mbedtls/include/psa/crypto_sizes.h +++ b/vendor/mbedtls/include/psa/crypto_sizes.h @@ -22,34 +22,25 @@ */ /* * Copyright The Mbed TLS Contributors - * SPDX-License-Identifier: Apache-2.0 - * - * Licensed under the Apache License, Version 2.0 (the "License"); you may - * not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT - * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. + * SPDX-License-Identifier: Apache-2.0 OR GPL-2.0-or-later */ #ifndef PSA_CRYPTO_SIZES_H #define PSA_CRYPTO_SIZES_H -/* Include the Mbed TLS configuration file, the way Mbed TLS does it - * in each of its header files. */ -#if !defined(MBEDTLS_CONFIG_FILE) -#include "mbedtls/config.h" -#else -#include MBEDTLS_CONFIG_FILE -#endif +/* + * Include the build-time configuration information header. Here, we do not + * include `"mbedtls/build_info.h"` directly but `"psa/build_info.h"`, which + * is basically just an alias to it. This is to ease the maintenance of the + * TF-PSA-Crypto repository which has a different build system and + * configuration. + */ +#include "psa/build_info.h" -#define PSA_BITS_TO_BYTES(bits) (((bits) + 7) / 8) -#define PSA_BYTES_TO_BITS(bytes) ((bytes) * 8) +#define PSA_BITS_TO_BYTES(bits) (((bits) + 7u) / 8u) +#define PSA_BYTES_TO_BITS(bytes) ((bytes) * 8u) +#define PSA_MAX_OF_THREE(a, b, c) ((a) <= (b) ? (b) <= (c) ? \ + (c) : (b) : (a) <= (c) ? (c) : (a)) #define PSA_ROUND_UP_TO_MULTIPLE(block_size, length) \ (((length) + (block_size) - 1) / (block_size) * (block_size)) @@ -68,22 +59,20 @@ */ #define PSA_HASH_LENGTH(alg) \ ( \ - PSA_ALG_HMAC_GET_HASH(alg) == PSA_ALG_MD2 ? 16 : \ - PSA_ALG_HMAC_GET_HASH(alg) == PSA_ALG_MD4 ? 16 : \ - PSA_ALG_HMAC_GET_HASH(alg) == PSA_ALG_MD5 ? 16 : \ - PSA_ALG_HMAC_GET_HASH(alg) == PSA_ALG_RIPEMD160 ? 20 : \ - PSA_ALG_HMAC_GET_HASH(alg) == PSA_ALG_SHA_1 ? 20 : \ - PSA_ALG_HMAC_GET_HASH(alg) == PSA_ALG_SHA_224 ? 28 : \ - PSA_ALG_HMAC_GET_HASH(alg) == PSA_ALG_SHA_256 ? 32 : \ - PSA_ALG_HMAC_GET_HASH(alg) == PSA_ALG_SHA_384 ? 48 : \ - PSA_ALG_HMAC_GET_HASH(alg) == PSA_ALG_SHA_512 ? 64 : \ - PSA_ALG_HMAC_GET_HASH(alg) == PSA_ALG_SHA_512_224 ? 28 : \ - PSA_ALG_HMAC_GET_HASH(alg) == PSA_ALG_SHA_512_256 ? 32 : \ - PSA_ALG_HMAC_GET_HASH(alg) == PSA_ALG_SHA3_224 ? 28 : \ - PSA_ALG_HMAC_GET_HASH(alg) == PSA_ALG_SHA3_256 ? 32 : \ - PSA_ALG_HMAC_GET_HASH(alg) == PSA_ALG_SHA3_384 ? 48 : \ - PSA_ALG_HMAC_GET_HASH(alg) == PSA_ALG_SHA3_512 ? 64 : \ - 0) + PSA_ALG_HMAC_GET_HASH(alg) == PSA_ALG_MD5 ? 16u : \ + PSA_ALG_HMAC_GET_HASH(alg) == PSA_ALG_RIPEMD160 ? 20u : \ + PSA_ALG_HMAC_GET_HASH(alg) == PSA_ALG_SHA_1 ? 20u : \ + PSA_ALG_HMAC_GET_HASH(alg) == PSA_ALG_SHA_224 ? 28u : \ + PSA_ALG_HMAC_GET_HASH(alg) == PSA_ALG_SHA_256 ? 32u : \ + PSA_ALG_HMAC_GET_HASH(alg) == PSA_ALG_SHA_384 ? 48u : \ + PSA_ALG_HMAC_GET_HASH(alg) == PSA_ALG_SHA_512 ? 64u : \ + PSA_ALG_HMAC_GET_HASH(alg) == PSA_ALG_SHA_512_224 ? 28u : \ + PSA_ALG_HMAC_GET_HASH(alg) == PSA_ALG_SHA_512_256 ? 32u : \ + PSA_ALG_HMAC_GET_HASH(alg) == PSA_ALG_SHA3_224 ? 28u : \ + PSA_ALG_HMAC_GET_HASH(alg) == PSA_ALG_SHA3_256 ? 32u : \ + PSA_ALG_HMAC_GET_HASH(alg) == PSA_ALG_SHA3_384 ? 48u : \ + PSA_ALG_HMAC_GET_HASH(alg) == PSA_ALG_SHA3_512 ? 64u : \ + 0u) /** The input block size of a hash algorithm, in bytes. * @@ -102,22 +91,20 @@ */ #define PSA_HASH_BLOCK_LENGTH(alg) \ ( \ - PSA_ALG_HMAC_GET_HASH(alg) == PSA_ALG_MD2 ? 16 : \ - PSA_ALG_HMAC_GET_HASH(alg) == PSA_ALG_MD4 ? 64 : \ - PSA_ALG_HMAC_GET_HASH(alg) == PSA_ALG_MD5 ? 64 : \ - PSA_ALG_HMAC_GET_HASH(alg) == PSA_ALG_RIPEMD160 ? 64 : \ - PSA_ALG_HMAC_GET_HASH(alg) == PSA_ALG_SHA_1 ? 64 : \ - PSA_ALG_HMAC_GET_HASH(alg) == PSA_ALG_SHA_224 ? 64 : \ - PSA_ALG_HMAC_GET_HASH(alg) == PSA_ALG_SHA_256 ? 64 : \ - PSA_ALG_HMAC_GET_HASH(alg) == PSA_ALG_SHA_384 ? 128 : \ - PSA_ALG_HMAC_GET_HASH(alg) == PSA_ALG_SHA_512 ? 128 : \ - PSA_ALG_HMAC_GET_HASH(alg) == PSA_ALG_SHA_512_224 ? 128 : \ - PSA_ALG_HMAC_GET_HASH(alg) == PSA_ALG_SHA_512_256 ? 128 : \ - PSA_ALG_HMAC_GET_HASH(alg) == PSA_ALG_SHA3_224 ? 144 : \ - PSA_ALG_HMAC_GET_HASH(alg) == PSA_ALG_SHA3_256 ? 136 : \ - PSA_ALG_HMAC_GET_HASH(alg) == PSA_ALG_SHA3_384 ? 104 : \ - PSA_ALG_HMAC_GET_HASH(alg) == PSA_ALG_SHA3_512 ? 72 : \ - 0) + PSA_ALG_HMAC_GET_HASH(alg) == PSA_ALG_MD5 ? 64u : \ + PSA_ALG_HMAC_GET_HASH(alg) == PSA_ALG_RIPEMD160 ? 64u : \ + PSA_ALG_HMAC_GET_HASH(alg) == PSA_ALG_SHA_1 ? 64u : \ + PSA_ALG_HMAC_GET_HASH(alg) == PSA_ALG_SHA_224 ? 64u : \ + PSA_ALG_HMAC_GET_HASH(alg) == PSA_ALG_SHA_256 ? 64u : \ + PSA_ALG_HMAC_GET_HASH(alg) == PSA_ALG_SHA_384 ? 128u : \ + PSA_ALG_HMAC_GET_HASH(alg) == PSA_ALG_SHA_512 ? 128u : \ + PSA_ALG_HMAC_GET_HASH(alg) == PSA_ALG_SHA_512_224 ? 128u : \ + PSA_ALG_HMAC_GET_HASH(alg) == PSA_ALG_SHA_512_256 ? 128u : \ + PSA_ALG_HMAC_GET_HASH(alg) == PSA_ALG_SHA3_224 ? 144u : \ + PSA_ALG_HMAC_GET_HASH(alg) == PSA_ALG_SHA3_256 ? 136u : \ + PSA_ALG_HMAC_GET_HASH(alg) == PSA_ALG_SHA3_384 ? 104u : \ + PSA_ALG_HMAC_GET_HASH(alg) == PSA_ALG_SHA3_512 ? 72u : \ + 0u) /** \def PSA_HASH_MAX_SIZE * @@ -126,15 +113,41 @@ * This macro expands to a compile-time constant integer. This value * is the maximum size of a hash in bytes. */ -/* Note: for HMAC-SHA-3, the block size is 144 bytes for HMAC-SHA3-226, +/* Note: for HMAC-SHA-3, the block size is 144 bytes for HMAC-SHA3-224, * 136 bytes for HMAC-SHA3-256, 104 bytes for SHA3-384, 72 bytes for * HMAC-SHA3-512. */ -#if defined(PSA_WANT_ALG_SHA_512) || defined(PSA_WANT_ALG_SHA_384) -#define PSA_HASH_MAX_SIZE 64 -#define PSA_HMAC_MAX_HASH_BLOCK_SIZE 128 -#else -#define PSA_HASH_MAX_SIZE 32 -#define PSA_HMAC_MAX_HASH_BLOCK_SIZE 64 +/* Note: PSA_HASH_MAX_SIZE should be kept in sync with MBEDTLS_MD_MAX_SIZE, + * see the note on MBEDTLS_MD_MAX_SIZE for details. */ +#if defined(PSA_WANT_ALG_SHA3_224) +#define PSA_HMAC_MAX_HASH_BLOCK_SIZE 144u +#elif defined(PSA_WANT_ALG_SHA3_256) +#define PSA_HMAC_MAX_HASH_BLOCK_SIZE 136u +#elif defined(PSA_WANT_ALG_SHA_512) +#define PSA_HMAC_MAX_HASH_BLOCK_SIZE 128u +#elif defined(PSA_WANT_ALG_SHA_384) +#define PSA_HMAC_MAX_HASH_BLOCK_SIZE 128u +#elif defined(PSA_WANT_ALG_SHA3_384) +#define PSA_HMAC_MAX_HASH_BLOCK_SIZE 104u +#elif defined(PSA_WANT_ALG_SHA3_512) +#define PSA_HMAC_MAX_HASH_BLOCK_SIZE 72u +#elif defined(PSA_WANT_ALG_SHA_256) +#define PSA_HMAC_MAX_HASH_BLOCK_SIZE 64u +#elif defined(PSA_WANT_ALG_SHA_224) +#define PSA_HMAC_MAX_HASH_BLOCK_SIZE 64u +#else /* SHA-1 or smaller */ +#define PSA_HMAC_MAX_HASH_BLOCK_SIZE 64u +#endif + +#if defined(PSA_WANT_ALG_SHA_512) || defined(PSA_WANT_ALG_SHA3_512) +#define PSA_HASH_MAX_SIZE 64u +#elif defined(PSA_WANT_ALG_SHA_384) || defined(PSA_WANT_ALG_SHA3_384) +#define PSA_HASH_MAX_SIZE 48u +#elif defined(PSA_WANT_ALG_SHA_256) || defined(PSA_WANT_ALG_SHA3_256) +#define PSA_HASH_MAX_SIZE 32u +#elif defined(PSA_WANT_ALG_SHA_224) || defined(PSA_WANT_ALG_SHA3_224) +#define PSA_HASH_MAX_SIZE 28u +#else /* SHA-1 or smaller */ +#define PSA_HASH_MAX_SIZE 20u #endif /** \def PSA_MAC_MAX_SIZE @@ -175,13 +188,13 @@ #define PSA_AEAD_TAG_LENGTH(key_type, key_bits, alg) \ (PSA_AEAD_NONCE_LENGTH(key_type, alg) != 0 ? \ PSA_ALG_AEAD_GET_TAG_LENGTH(alg) : \ - ((void) (key_bits), 0)) + ((void) (key_bits), 0u)) /** The maximum tag size for all supported AEAD algorithms, in bytes. * * See also #PSA_AEAD_TAG_LENGTH(\p key_type, \p key_bits, \p alg). */ -#define PSA_AEAD_TAG_MAX_SIZE 16 +#define PSA_AEAD_TAG_MAX_SIZE 16u /* The maximum size of an RSA key on this implementation, in bits. * This is a vendor-specific macro. @@ -196,38 +209,66 @@ * * Note that an implementation may set different size limits for different * operations, and does not need to accept all key sizes up to the limit. */ -#define PSA_VENDOR_RSA_MAX_KEY_BITS 4096 +#define PSA_VENDOR_RSA_MAX_KEY_BITS 4096u + +/* The minimum size of an RSA key on this implementation, in bits. + * This is a vendor-specific macro. + * + * Limits RSA key generation to a minimum due to avoid accidental misuse. + * This value cannot be less than 128 bits. + */ +#if defined(MBEDTLS_RSA_GEN_KEY_MIN_BITS) +#define PSA_VENDOR_RSA_GENERATE_MIN_KEY_BITS MBEDTLS_RSA_GEN_KEY_MIN_BITS +#else +#define PSA_VENDOR_RSA_GENERATE_MIN_KEY_BITS 1024 +#endif + +/* The maximum size of an DH key on this implementation, in bits. + * This is a vendor-specific macro.*/ +#if defined(PSA_WANT_DH_RFC7919_8192) +#define PSA_VENDOR_FFDH_MAX_KEY_BITS 8192u +#elif defined(PSA_WANT_DH_RFC7919_6144) +#define PSA_VENDOR_FFDH_MAX_KEY_BITS 6144u +#elif defined(PSA_WANT_DH_RFC7919_4096) +#define PSA_VENDOR_FFDH_MAX_KEY_BITS 4096u +#elif defined(PSA_WANT_DH_RFC7919_3072) +#define PSA_VENDOR_FFDH_MAX_KEY_BITS 3072u +#elif defined(PSA_WANT_DH_RFC7919_2048) +#define PSA_VENDOR_FFDH_MAX_KEY_BITS 2048u +#else +#define PSA_VENDOR_FFDH_MAX_KEY_BITS 0u +#endif /* The maximum size of an ECC key on this implementation, in bits. * This is a vendor-specific macro. */ -#if defined(MBEDTLS_ECP_DP_SECP521R1_ENABLED) -#define PSA_VENDOR_ECC_MAX_CURVE_BITS 521 -#elif defined(MBEDTLS_ECP_DP_BP512R1_ENABLED) -#define PSA_VENDOR_ECC_MAX_CURVE_BITS 512 -#elif defined(MBEDTLS_ECP_DP_CURVE448_ENABLED) -#define PSA_VENDOR_ECC_MAX_CURVE_BITS 448 -#elif defined(MBEDTLS_ECP_DP_SECP384R1_ENABLED) -#define PSA_VENDOR_ECC_MAX_CURVE_BITS 384 -#elif defined(MBEDTLS_ECP_DP_BP384R1_ENABLED) -#define PSA_VENDOR_ECC_MAX_CURVE_BITS 384 -#elif defined(MBEDTLS_ECP_DP_SECP256R1_ENABLED) -#define PSA_VENDOR_ECC_MAX_CURVE_BITS 256 -#elif defined(MBEDTLS_ECP_DP_SECP256K1_ENABLED) -#define PSA_VENDOR_ECC_MAX_CURVE_BITS 256 -#elif defined(MBEDTLS_ECP_DP_BP256R1_ENABLED) -#define PSA_VENDOR_ECC_MAX_CURVE_BITS 256 -#elif defined(MBEDTLS_ECP_DP_CURVE25519_ENABLED) -#define PSA_VENDOR_ECC_MAX_CURVE_BITS 255 -#elif defined(MBEDTLS_ECP_DP_SECP224R1_ENABLED) -#define PSA_VENDOR_ECC_MAX_CURVE_BITS 224 -#elif defined(MBEDTLS_ECP_DP_SECP224K1_ENABLED) -#define PSA_VENDOR_ECC_MAX_CURVE_BITS 224 -#elif defined(MBEDTLS_ECP_DP_SECP192R1_ENABLED) -#define PSA_VENDOR_ECC_MAX_CURVE_BITS 192 -#elif defined(MBEDTLS_ECP_DP_SECP192K1_ENABLED) -#define PSA_VENDOR_ECC_MAX_CURVE_BITS 192 +#if defined(PSA_WANT_ECC_SECP_R1_521) +#define PSA_VENDOR_ECC_MAX_CURVE_BITS 521u +#elif defined(PSA_WANT_ECC_BRAINPOOL_P_R1_512) +#define PSA_VENDOR_ECC_MAX_CURVE_BITS 512u +#elif defined(PSA_WANT_ECC_MONTGOMERY_448) +#define PSA_VENDOR_ECC_MAX_CURVE_BITS 448u +#elif defined(PSA_WANT_ECC_SECP_R1_384) +#define PSA_VENDOR_ECC_MAX_CURVE_BITS 384u +#elif defined(PSA_WANT_ECC_BRAINPOOL_P_R1_384) +#define PSA_VENDOR_ECC_MAX_CURVE_BITS 384u +#elif defined(PSA_WANT_ECC_SECP_R1_256) +#define PSA_VENDOR_ECC_MAX_CURVE_BITS 256u +#elif defined(PSA_WANT_ECC_SECP_K1_256) +#define PSA_VENDOR_ECC_MAX_CURVE_BITS 256u +#elif defined(PSA_WANT_ECC_BRAINPOOL_P_R1_256) +#define PSA_VENDOR_ECC_MAX_CURVE_BITS 256u +#elif defined(PSA_WANT_ECC_MONTGOMERY_255) +#define PSA_VENDOR_ECC_MAX_CURVE_BITS 255u +#elif defined(PSA_WANT_ECC_SECP_R1_224) +#define PSA_VENDOR_ECC_MAX_CURVE_BITS 224u +#elif defined(PSA_WANT_ECC_SECP_K1_224) +#define PSA_VENDOR_ECC_MAX_CURVE_BITS 224u +#elif defined(PSA_WANT_ECC_SECP_R1_192) +#define PSA_VENDOR_ECC_MAX_CURVE_BITS 192u +#elif defined(PSA_WANT_ECC_SECP_K1_192) +#define PSA_VENDOR_ECC_MAX_CURVE_BITS 192u #else -#define PSA_VENDOR_ECC_MAX_CURVE_BITS 0 +#define PSA_VENDOR_ECC_MAX_CURVE_BITS 0u #endif /** This macro returns the maximum supported length of the PSK for the @@ -245,10 +286,23 @@ * Therefore, no implementation should define a value smaller than 64 * for #PSA_TLS12_PSK_TO_MS_PSK_MAX_SIZE. */ -#define PSA_TLS12_PSK_TO_MS_PSK_MAX_SIZE 128 +#define PSA_TLS12_PSK_TO_MS_PSK_MAX_SIZE 128u + +/* The expected size of input passed to psa_tls12_ecjpake_to_pms_input, + * which is expected to work with P-256 curve only. */ +#define PSA_TLS12_ECJPAKE_TO_PMS_INPUT_SIZE 65u + +/* The size of a serialized K.X coordinate to be used in + * psa_tls12_ecjpake_to_pms_input. This function only accepts the P-256 + * curve. */ +#define PSA_TLS12_ECJPAKE_TO_PMS_DATA_SIZE 32u + +/* The maximum number of iterations for PBKDF2 on this implementation, in bits. + * This is a vendor-specific macro. This can be configured if necessary */ +#define PSA_VENDOR_PBKDF2_MAX_ITERATIONS 0xffffffffU /** The maximum size of a block cipher. */ -#define PSA_BLOCK_CIPHER_BLOCK_MAX_SIZE 16 +#define PSA_BLOCK_CIPHER_BLOCK_MAX_SIZE 16u /** The size of the output of psa_mac_sign_finish(), in bytes. * @@ -275,7 +329,7 @@ ((alg) & PSA_ALG_MAC_TRUNCATION_MASK ? PSA_MAC_TRUNCATED_LENGTH(alg) : \ PSA_ALG_IS_HMAC(alg) ? PSA_HASH_LENGTH(PSA_ALG_HMAC_GET_HASH(alg)) : \ PSA_ALG_IS_BLOCK_CIPHER_MAC(alg) ? PSA_BLOCK_CIPHER_BLOCK_LENGTH(key_type) : \ - ((void) (key_type), (void) (key_bits), 0)) + ((void) (key_type), (void) (key_bits), 0u)) /** The maximum size of the output of psa_aead_encrypt(), in bytes. * @@ -306,7 +360,7 @@ #define PSA_AEAD_ENCRYPT_OUTPUT_SIZE(key_type, alg, plaintext_length) \ (PSA_AEAD_NONCE_LENGTH(key_type, alg) != 0 ? \ (plaintext_length) + PSA_ALG_AEAD_GET_TAG_LENGTH(alg) : \ - 0) + 0u) /** A sufficient output buffer size for psa_aead_encrypt(), for any of the * supported key types and AEAD algorithms. @@ -360,7 +414,7 @@ (PSA_AEAD_NONCE_LENGTH(key_type, alg) != 0 && \ (ciphertext_length) > PSA_ALG_AEAD_GET_TAG_LENGTH(alg) ? \ (ciphertext_length) - PSA_ALG_AEAD_GET_TAG_LENGTH(alg) : \ - 0) + 0u) /** A sufficient output buffer size for psa_aead_decrypt(), for any of the * supported key types and AEAD algorithms. @@ -410,12 +464,12 @@ */ #define PSA_AEAD_NONCE_LENGTH(key_type, alg) \ (PSA_BLOCK_CIPHER_BLOCK_LENGTH(key_type) == 16 ? \ - MBEDTLS_PSA_ALG_AEAD_EQUAL(alg, PSA_ALG_CCM) ? 13 : \ - MBEDTLS_PSA_ALG_AEAD_EQUAL(alg, PSA_ALG_GCM) ? 12 : \ - 0 : \ + MBEDTLS_PSA_ALG_AEAD_EQUAL(alg, PSA_ALG_CCM) ? 13u : \ + MBEDTLS_PSA_ALG_AEAD_EQUAL(alg, PSA_ALG_GCM) ? 12u : \ + 0u : \ (key_type) == PSA_KEY_TYPE_CHACHA20 && \ - MBEDTLS_PSA_ALG_AEAD_EQUAL(alg, PSA_ALG_CHACHA20_POLY1305) ? 12 : \ - 0) + MBEDTLS_PSA_ALG_AEAD_EQUAL(alg, PSA_ALG_CHACHA20_POLY1305) ? 12u : \ + 0u) /** The maximum default nonce size among all supported pairs of key types and * AEAD algorithms, in bytes. @@ -428,7 +482,7 @@ * just the largest size that may be generated by * #psa_aead_generate_nonce(). */ -#define PSA_AEAD_NONCE_MAX_SIZE 13 +#define PSA_AEAD_NONCE_MAX_SIZE 13u /** A sufficient output buffer size for psa_aead_update(). * @@ -465,7 +519,7 @@ PSA_ALG_IS_AEAD_ON_BLOCK_CIPHER(alg) ? \ PSA_ROUND_UP_TO_MULTIPLE(PSA_BLOCK_CIPHER_BLOCK_LENGTH(key_type), (input_length)) : \ (input_length) : \ - 0) + 0u) /** A sufficient output buffer size for psa_aead_update(), for any of the * supported key types and AEAD algorithms. @@ -505,7 +559,7 @@ (PSA_AEAD_NONCE_LENGTH(key_type, alg) != 0 && \ PSA_ALG_IS_AEAD_ON_BLOCK_CIPHER(alg) ? \ PSA_BLOCK_CIPHER_BLOCK_LENGTH(key_type) : \ - 0) + 0u) /** A sufficient ciphertext buffer size for psa_aead_finish(), for any of the * supported key types and AEAD algorithms. @@ -539,7 +593,7 @@ (PSA_AEAD_NONCE_LENGTH(key_type, alg) != 0 && \ PSA_ALG_IS_AEAD_ON_BLOCK_CIPHER(alg) ? \ PSA_BLOCK_CIPHER_BLOCK_LENGTH(key_type) : \ - 0) + 0u) /** A sufficient plaintext buffer size for psa_aead_verify(), for any of the * supported key types and AEAD algorithms. @@ -550,8 +604,8 @@ #define PSA_RSA_MINIMUM_PADDING_SIZE(alg) \ (PSA_ALG_IS_RSA_OAEP(alg) ? \ - 2 * PSA_HASH_LENGTH(PSA_ALG_RSA_OAEP_GET_HASH(alg)) + 1 : \ - 11 /*PKCS#1v1.5*/) + 2u * PSA_HASH_LENGTH(PSA_ALG_RSA_OAEP_GET_HASH(alg)) + 1u : \ + 11u /*PKCS#1v1.5*/) /** * \brief ECDSA signature size for a given curve bit size @@ -562,7 +616,7 @@ * \note This macro returns a compile-time constant if its argument is one. */ #define PSA_ECDSA_SIGNATURE_SIZE(curve_bits) \ - (PSA_BITS_TO_BYTES(curve_bits) * 2) + (PSA_BITS_TO_BYTES(curve_bits) * 2u) /** Sufficient signature buffer size for psa_sign_hash(). * @@ -592,7 +646,7 @@ #define PSA_SIGN_OUTPUT_SIZE(key_type, key_bits, alg) \ (PSA_KEY_TYPE_IS_RSA(key_type) ? ((void) alg, PSA_BITS_TO_BYTES(key_bits)) : \ PSA_KEY_TYPE_IS_ECC(key_type) ? PSA_ECDSA_SIGNATURE_SIZE(key_bits) : \ - ((void) alg, 0)) + ((void) alg, 0u)) #define PSA_VENDOR_ECDSA_SIGNATURE_MAX_SIZE \ PSA_ECDSA_SIGNATURE_SIZE(PSA_VENDOR_ECC_MAX_CURVE_BITS) @@ -604,10 +658,18 @@ * This macro expands to a compile-time constant integer. This value * is the maximum size of a signature in bytes. */ -#define PSA_SIGNATURE_MAX_SIZE \ - (PSA_BITS_TO_BYTES(PSA_VENDOR_RSA_MAX_KEY_BITS) > PSA_VENDOR_ECDSA_SIGNATURE_MAX_SIZE ? \ - PSA_BITS_TO_BYTES(PSA_VENDOR_RSA_MAX_KEY_BITS) : \ - PSA_VENDOR_ECDSA_SIGNATURE_MAX_SIZE) +#define PSA_SIGNATURE_MAX_SIZE 1 + +#if (defined(PSA_WANT_ALG_ECDSA) || defined(PSA_WANT_ALG_DETERMINISTIC_ECDSA)) && \ + (PSA_VENDOR_ECDSA_SIGNATURE_MAX_SIZE > PSA_SIGNATURE_MAX_SIZE) +#undef PSA_SIGNATURE_MAX_SIZE +#define PSA_SIGNATURE_MAX_SIZE PSA_VENDOR_ECDSA_SIGNATURE_MAX_SIZE +#endif +#if (defined(PSA_WANT_ALG_RSA_PKCS1V15_SIGN) || defined(PSA_WANT_ALG_RSA_PSS)) && \ + (PSA_BITS_TO_BYTES(PSA_VENDOR_RSA_MAX_KEY_BITS) > PSA_SIGNATURE_MAX_SIZE) +#undef PSA_SIGNATURE_MAX_SIZE +#define PSA_SIGNATURE_MAX_SIZE PSA_BITS_TO_BYTES(PSA_VENDOR_RSA_MAX_KEY_BITS) +#endif /** Sufficient output buffer size for psa_asymmetric_encrypt(). * @@ -637,7 +699,7 @@ #define PSA_ASYMMETRIC_ENCRYPT_OUTPUT_SIZE(key_type, key_bits, alg) \ (PSA_KEY_TYPE_IS_RSA(key_type) ? \ ((void) alg, PSA_BITS_TO_BYTES(key_bits)) : \ - 0) + 0u) /** A sufficient output buffer size for psa_asymmetric_encrypt(), for any * supported asymmetric encryption. @@ -676,7 +738,7 @@ #define PSA_ASYMMETRIC_DECRYPT_OUTPUT_SIZE(key_type, key_bits, alg) \ (PSA_KEY_TYPE_IS_RSA(key_type) ? \ PSA_BITS_TO_BYTES(key_bits) - PSA_RSA_MINIMUM_PADDING_SIZE(alg) : \ - 0) + 0u) /** A sufficient output buffer size for psa_asymmetric_decrypt(), for any * supported asymmetric decryption. @@ -699,7 +761,7 @@ * - 0 to 1 bytes of leading 0 due to the sign bit. */ #define PSA_KEY_EXPORT_ASN1_INTEGER_MAX_SIZE(bits) \ - ((bits) / 8 + 5) + ((bits) / 8u + 5u) /* Maximum size of the export encoding of an RSA public key. * Assumes that the public exponent is less than 2^32. @@ -713,7 +775,7 @@ * - 7 bytes for the public exponent. */ #define PSA_KEY_EXPORT_RSA_PUBLIC_KEY_MAX_SIZE(key_bits) \ - (PSA_KEY_EXPORT_ASN1_INTEGER_MAX_SIZE(key_bits) + 11) + (PSA_KEY_EXPORT_ASN1_INTEGER_MAX_SIZE(key_bits) + 11u) /* Maximum size of the export encoding of an RSA key pair. * Assumes that the public exponent is less than 2^32 and that the size @@ -738,7 +800,7 @@ * - 7 bytes for the public exponent. */ #define PSA_KEY_EXPORT_RSA_KEY_PAIR_MAX_SIZE(key_bits) \ - (9 * PSA_KEY_EXPORT_ASN1_INTEGER_MAX_SIZE((key_bits) / 2 + 1) + 14) + (9u * PSA_KEY_EXPORT_ASN1_INTEGER_MAX_SIZE((key_bits) / 2u + 1u) + 14u) /* Maximum size of the export encoding of a DSA public key. * @@ -757,7 +819,7 @@ * - 1 + 1 + 32 bytes for 1 sub-size INTEGER (q <= 256 bits). */ #define PSA_KEY_EXPORT_DSA_PUBLIC_KEY_MAX_SIZE(key_bits) \ - (PSA_KEY_EXPORT_ASN1_INTEGER_MAX_SIZE(key_bits) * 3 + 59) + (PSA_KEY_EXPORT_ASN1_INTEGER_MAX_SIZE(key_bits) * 3u + 59u) /* Maximum size of the export encoding of a DSA key pair. * @@ -776,7 +838,7 @@ * - 2 * (1 + 1 + 32) bytes for 2 sub-size INTEGERs (q, x <= 256 bits). */ #define PSA_KEY_EXPORT_DSA_KEY_PAIR_MAX_SIZE(key_bits) \ - (PSA_KEY_EXPORT_ASN1_INTEGER_MAX_SIZE(key_bits) * 3 + 75) + (PSA_KEY_EXPORT_ASN1_INTEGER_MAX_SIZE(key_bits) * 3u + 75u) /* Maximum size of the export encoding of an ECC public key. * @@ -789,7 +851,7 @@ * - 1 byte + 2 * point size. */ #define PSA_KEY_EXPORT_ECC_PUBLIC_KEY_MAX_SIZE(key_bits) \ - (2 * PSA_BITS_TO_BYTES(key_bits) + 1) + (2u * PSA_BITS_TO_BYTES(key_bits) + 1u) /* Maximum size of the export encoding of an ECC key pair. * @@ -798,6 +860,18 @@ #define PSA_KEY_EXPORT_ECC_KEY_PAIR_MAX_SIZE(key_bits) \ (PSA_BITS_TO_BYTES(key_bits)) +/* Maximum size of the export encoding of an DH key pair. + * + * An DH key pair is represented by the secret value. + */ +#define PSA_KEY_EXPORT_FFDH_KEY_PAIR_MAX_SIZE(key_bits) \ + (PSA_BITS_TO_BYTES(key_bits)) + +/* Maximum size of the export encoding of an DH public key. + */ +#define PSA_KEY_EXPORT_FFDH_PUBLIC_KEY_MAX_SIZE(key_bits) \ + (PSA_BITS_TO_BYTES(key_bits)) + /** Sufficient output buffer size for psa_export_key() or * psa_export_public_key(). * @@ -839,13 +913,14 @@ */ #define PSA_EXPORT_KEY_OUTPUT_SIZE(key_type, key_bits) \ (PSA_KEY_TYPE_IS_UNSTRUCTURED(key_type) ? PSA_BITS_TO_BYTES(key_bits) : \ + PSA_KEY_TYPE_IS_DH(key_type) ? PSA_BITS_TO_BYTES(key_bits) : \ (key_type) == PSA_KEY_TYPE_RSA_KEY_PAIR ? PSA_KEY_EXPORT_RSA_KEY_PAIR_MAX_SIZE(key_bits) : \ (key_type) == PSA_KEY_TYPE_RSA_PUBLIC_KEY ? PSA_KEY_EXPORT_RSA_PUBLIC_KEY_MAX_SIZE(key_bits) : \ (key_type) == PSA_KEY_TYPE_DSA_KEY_PAIR ? PSA_KEY_EXPORT_DSA_KEY_PAIR_MAX_SIZE(key_bits) : \ (key_type) == PSA_KEY_TYPE_DSA_PUBLIC_KEY ? PSA_KEY_EXPORT_DSA_PUBLIC_KEY_MAX_SIZE(key_bits) : \ PSA_KEY_TYPE_IS_ECC_KEY_PAIR(key_type) ? PSA_KEY_EXPORT_ECC_KEY_PAIR_MAX_SIZE(key_bits) : \ PSA_KEY_TYPE_IS_ECC_PUBLIC_KEY(key_type) ? PSA_KEY_EXPORT_ECC_PUBLIC_KEY_MAX_SIZE(key_bits) : \ - 0) + 0u) /** Sufficient output buffer size for psa_export_public_key(). * @@ -895,7 +970,8 @@ #define PSA_EXPORT_PUBLIC_KEY_OUTPUT_SIZE(key_type, key_bits) \ (PSA_KEY_TYPE_IS_RSA(key_type) ? PSA_KEY_EXPORT_RSA_PUBLIC_KEY_MAX_SIZE(key_bits) : \ PSA_KEY_TYPE_IS_ECC(key_type) ? PSA_KEY_EXPORT_ECC_PUBLIC_KEY_MAX_SIZE(key_bits) : \ - 0) + PSA_KEY_TYPE_IS_DH(key_type) ? PSA_BITS_TO_BYTES(key_bits) : \ + 0u) /** Sufficient buffer size for exporting any asymmetric key pair. * @@ -905,11 +981,29 @@ * * See also #PSA_EXPORT_KEY_OUTPUT_SIZE(\p key_type, \p key_bits). */ -#define PSA_EXPORT_KEY_PAIR_MAX_SIZE \ - (PSA_KEY_EXPORT_RSA_KEY_PAIR_MAX_SIZE(PSA_VENDOR_RSA_MAX_KEY_BITS) > \ - PSA_KEY_EXPORT_ECC_KEY_PAIR_MAX_SIZE(PSA_VENDOR_ECC_MAX_CURVE_BITS) ? \ - PSA_KEY_EXPORT_RSA_KEY_PAIR_MAX_SIZE(PSA_VENDOR_RSA_MAX_KEY_BITS) : \ - PSA_KEY_EXPORT_ECC_KEY_PAIR_MAX_SIZE(PSA_VENDOR_ECC_MAX_CURVE_BITS)) +#define PSA_EXPORT_KEY_PAIR_MAX_SIZE 1 + +#if defined(PSA_WANT_KEY_TYPE_ECC_KEY_PAIR_BASIC) && \ + (PSA_KEY_EXPORT_ECC_KEY_PAIR_MAX_SIZE(PSA_VENDOR_ECC_MAX_CURVE_BITS) > \ + PSA_EXPORT_KEY_PAIR_MAX_SIZE) +#undef PSA_EXPORT_KEY_PAIR_MAX_SIZE +#define PSA_EXPORT_KEY_PAIR_MAX_SIZE \ + PSA_KEY_EXPORT_ECC_KEY_PAIR_MAX_SIZE(PSA_VENDOR_ECC_MAX_CURVE_BITS) +#endif +#if defined(PSA_WANT_KEY_TYPE_RSA_KEY_PAIR_BASIC) && \ + (PSA_KEY_EXPORT_RSA_KEY_PAIR_MAX_SIZE(PSA_VENDOR_RSA_MAX_KEY_BITS) > \ + PSA_EXPORT_KEY_PAIR_MAX_SIZE) +#undef PSA_EXPORT_KEY_PAIR_MAX_SIZE +#define PSA_EXPORT_KEY_PAIR_MAX_SIZE \ + PSA_KEY_EXPORT_RSA_KEY_PAIR_MAX_SIZE(PSA_VENDOR_RSA_MAX_KEY_BITS) +#endif +#if defined(PSA_WANT_KEY_TYPE_DH_KEY_PAIR_BASIC) && \ + (PSA_KEY_EXPORT_FFDH_KEY_PAIR_MAX_SIZE(PSA_VENDOR_FFDH_MAX_KEY_BITS) > \ + PSA_EXPORT_KEY_PAIR_MAX_SIZE) +#undef PSA_EXPORT_KEY_PAIR_MAX_SIZE +#define PSA_EXPORT_KEY_PAIR_MAX_SIZE \ + PSA_KEY_EXPORT_FFDH_KEY_PAIR_MAX_SIZE(PSA_VENDOR_FFDH_MAX_KEY_BITS) +#endif /** Sufficient buffer size for exporting any asymmetric public key. * @@ -920,11 +1014,29 @@ * * See also #PSA_EXPORT_PUBLIC_KEY_OUTPUT_SIZE(\p key_type, \p key_bits). */ -#define PSA_EXPORT_PUBLIC_KEY_MAX_SIZE \ - (PSA_KEY_EXPORT_RSA_PUBLIC_KEY_MAX_SIZE(PSA_VENDOR_RSA_MAX_KEY_BITS) > \ - PSA_KEY_EXPORT_ECC_PUBLIC_KEY_MAX_SIZE(PSA_VENDOR_ECC_MAX_CURVE_BITS) ? \ - PSA_KEY_EXPORT_RSA_PUBLIC_KEY_MAX_SIZE(PSA_VENDOR_RSA_MAX_KEY_BITS) : \ - PSA_KEY_EXPORT_ECC_PUBLIC_KEY_MAX_SIZE(PSA_VENDOR_ECC_MAX_CURVE_BITS)) +#define PSA_EXPORT_PUBLIC_KEY_MAX_SIZE 1 + +#if defined(PSA_WANT_KEY_TYPE_ECC_PUBLIC_KEY) && \ + (PSA_KEY_EXPORT_ECC_PUBLIC_KEY_MAX_SIZE(PSA_VENDOR_ECC_MAX_CURVE_BITS) > \ + PSA_EXPORT_PUBLIC_KEY_MAX_SIZE) +#undef PSA_EXPORT_PUBLIC_KEY_MAX_SIZE +#define PSA_EXPORT_PUBLIC_KEY_MAX_SIZE \ + PSA_KEY_EXPORT_ECC_PUBLIC_KEY_MAX_SIZE(PSA_VENDOR_ECC_MAX_CURVE_BITS) +#endif +#if defined(PSA_WANT_KEY_TYPE_RSA_PUBLIC_KEY) && \ + (PSA_KEY_EXPORT_RSA_PUBLIC_KEY_MAX_SIZE(PSA_VENDOR_RSA_MAX_KEY_BITS) > \ + PSA_EXPORT_PUBLIC_KEY_MAX_SIZE) +#undef PSA_EXPORT_PUBLIC_KEY_MAX_SIZE +#define PSA_EXPORT_PUBLIC_KEY_MAX_SIZE \ + PSA_KEY_EXPORT_RSA_PUBLIC_KEY_MAX_SIZE(PSA_VENDOR_RSA_MAX_KEY_BITS) +#endif +#if defined(PSA_WANT_KEY_TYPE_DH_PUBLIC_KEY) && \ + (PSA_KEY_EXPORT_FFDH_PUBLIC_KEY_MAX_SIZE(PSA_VENDOR_FFDH_MAX_KEY_BITS) > \ + PSA_EXPORT_PUBLIC_KEY_MAX_SIZE) +#undef PSA_EXPORT_PUBLIC_KEY_MAX_SIZE +#define PSA_EXPORT_PUBLIC_KEY_MAX_SIZE \ + PSA_KEY_EXPORT_FFDH_PUBLIC_KEY_MAX_SIZE(PSA_VENDOR_FFDH_MAX_KEY_BITS) +#endif /** Sufficient output buffer size for psa_raw_key_agreement(). * @@ -949,11 +1061,9 @@ * If the parameters are not valid, * the return value is unspecified. */ -/* FFDH is not yet supported in PSA. */ #define PSA_RAW_KEY_AGREEMENT_OUTPUT_SIZE(key_type, key_bits) \ - (PSA_KEY_TYPE_IS_ECC_KEY_PAIR(key_type) ? \ - PSA_BITS_TO_BYTES(key_bits) : \ - 0) + ((PSA_KEY_TYPE_IS_ECC_KEY_PAIR(key_type) || \ + PSA_KEY_TYPE_IS_DH_KEY_PAIR(key_type)) ? PSA_BITS_TO_BYTES(key_bits) : 0u) /** Maximum size of the output from psa_raw_key_agreement(). * @@ -962,8 +1072,18 @@ * * See also #PSA_RAW_KEY_AGREEMENT_OUTPUT_SIZE(\p key_type, \p key_bits). */ -#define PSA_RAW_KEY_AGREEMENT_OUTPUT_MAX_SIZE \ - (PSA_BITS_TO_BYTES(PSA_VENDOR_ECC_MAX_CURVE_BITS)) +#define PSA_RAW_KEY_AGREEMENT_OUTPUT_MAX_SIZE 1 + +#if defined(PSA_WANT_ALG_ECDH) && \ + (PSA_BITS_TO_BYTES(PSA_VENDOR_ECC_MAX_CURVE_BITS) > PSA_RAW_KEY_AGREEMENT_OUTPUT_MAX_SIZE) +#undef PSA_RAW_KEY_AGREEMENT_OUTPUT_MAX_SIZE +#define PSA_RAW_KEY_AGREEMENT_OUTPUT_MAX_SIZE PSA_BITS_TO_BYTES(PSA_VENDOR_ECC_MAX_CURVE_BITS) +#endif +#if defined(PSA_WANT_ALG_FFDH) && \ + (PSA_BITS_TO_BYTES(PSA_VENDOR_FFDH_MAX_KEY_BITS) > PSA_RAW_KEY_AGREEMENT_OUTPUT_MAX_SIZE) +#undef PSA_RAW_KEY_AGREEMENT_OUTPUT_MAX_SIZE +#define PSA_RAW_KEY_AGREEMENT_OUTPUT_MAX_SIZE PSA_BITS_TO_BYTES(PSA_VENDOR_FFDH_MAX_KEY_BITS) +#endif /** The default IV size for a cipher algorithm, in bytes. * @@ -998,14 +1118,15 @@ (alg) == PSA_ALG_CBC_NO_PADDING || \ (alg) == PSA_ALG_CBC_PKCS7) ? PSA_BLOCK_CIPHER_BLOCK_LENGTH(key_type) : \ (key_type) == PSA_KEY_TYPE_CHACHA20 && \ - (alg) == PSA_ALG_STREAM_CIPHER ? 12 : \ - 0) + (alg) == PSA_ALG_STREAM_CIPHER ? 12u : \ + (alg) == PSA_ALG_CCM_STAR_NO_TAG ? 13u : \ + 0u) /** The maximum IV size for all supported cipher algorithms, in bytes. * * See also #PSA_CIPHER_IV_LENGTH(). */ -#define PSA_CIPHER_IV_MAX_SIZE 16 +#define PSA_CIPHER_IV_MAX_SIZE 16u /** The maximum size of the output of psa_cipher_encrypt(), in bytes. * @@ -1030,15 +1151,15 @@ * recognized, or the parameters are incompatible, * return 0. */ -#define PSA_CIPHER_ENCRYPT_OUTPUT_SIZE(key_type, alg, input_length) \ - (alg == PSA_ALG_CBC_PKCS7 ? \ - (PSA_BLOCK_CIPHER_BLOCK_LENGTH(key_type) != 0 ? \ - PSA_ROUND_UP_TO_MULTIPLE(PSA_BLOCK_CIPHER_BLOCK_LENGTH(key_type), \ - (input_length) + 1) + \ - PSA_CIPHER_IV_LENGTH((key_type), (alg)) : 0) : \ - (PSA_ALG_IS_CIPHER(alg) ? \ - (input_length) + PSA_CIPHER_IV_LENGTH((key_type), (alg)) : \ - 0)) +#define PSA_CIPHER_ENCRYPT_OUTPUT_SIZE(key_type, alg, input_length) \ + (alg == PSA_ALG_CBC_PKCS7 ? \ + (PSA_BLOCK_CIPHER_BLOCK_LENGTH(key_type) != 0 ? \ + PSA_ROUND_UP_TO_MULTIPLE(PSA_BLOCK_CIPHER_BLOCK_LENGTH(key_type), \ + (input_length) + 1u) + \ + PSA_CIPHER_IV_LENGTH((key_type), (alg)) : 0u) : \ + (PSA_ALG_IS_CIPHER(alg) ? \ + (input_length) + PSA_CIPHER_IV_LENGTH((key_type), (alg)) : \ + 0u)) /** A sufficient output buffer size for psa_cipher_encrypt(), for any of the * supported key types and cipher algorithms. @@ -1051,9 +1172,9 @@ * \param input_length Size of the input in bytes. * */ -#define PSA_CIPHER_ENCRYPT_OUTPUT_MAX_SIZE(input_length) \ - (PSA_ROUND_UP_TO_MULTIPLE(PSA_BLOCK_CIPHER_BLOCK_MAX_SIZE, \ - (input_length) + 1) + \ +#define PSA_CIPHER_ENCRYPT_OUTPUT_MAX_SIZE(input_length) \ + (PSA_ROUND_UP_TO_MULTIPLE(PSA_BLOCK_CIPHER_BLOCK_MAX_SIZE, \ + (input_length) + 1u) + \ PSA_CIPHER_IV_MAX_SIZE) /** The maximum size of the output of psa_cipher_decrypt(), in bytes. @@ -1075,11 +1196,11 @@ * recognized, or the parameters are incompatible, * return 0. */ -#define PSA_CIPHER_DECRYPT_OUTPUT_SIZE(key_type, alg, input_length) \ - (PSA_ALG_IS_CIPHER(alg) && \ +#define PSA_CIPHER_DECRYPT_OUTPUT_SIZE(key_type, alg, input_length) \ + (PSA_ALG_IS_CIPHER(alg) && \ ((key_type) & PSA_KEY_TYPE_CATEGORY_MASK) == PSA_KEY_TYPE_CATEGORY_SYMMETRIC ? \ - (input_length) : \ - 0) + (input_length) : \ + 0u) /** A sufficient output buffer size for psa_cipher_decrypt(), for any of the * supported key types and cipher algorithms. @@ -1112,16 +1233,16 @@ * algorithm. If the key type or cipher algorithm is not * recognized, or the parameters are incompatible, return 0. */ -#define PSA_CIPHER_UPDATE_OUTPUT_SIZE(key_type, alg, input_length) \ - (PSA_ALG_IS_CIPHER(alg) ? \ - (PSA_BLOCK_CIPHER_BLOCK_LENGTH(key_type) != 0 ? \ - (((alg) == PSA_ALG_CBC_PKCS7 || \ - (alg) == PSA_ALG_CBC_NO_PADDING || \ - (alg) == PSA_ALG_ECB_NO_PADDING) ? \ - PSA_ROUND_UP_TO_MULTIPLE(PSA_BLOCK_CIPHER_BLOCK_LENGTH(key_type), \ - input_length) : \ - (input_length)) : 0) : \ - 0) +#define PSA_CIPHER_UPDATE_OUTPUT_SIZE(key_type, alg, input_length) \ + (PSA_ALG_IS_CIPHER(alg) ? \ + (PSA_BLOCK_CIPHER_BLOCK_LENGTH(key_type) != 0 ? \ + (((alg) == PSA_ALG_CBC_PKCS7 || \ + (alg) == PSA_ALG_CBC_NO_PADDING || \ + (alg) == PSA_ALG_ECB_NO_PADDING) ? \ + PSA_ROUND_UP_TO_MULTIPLE(PSA_BLOCK_CIPHER_BLOCK_LENGTH(key_type), \ + input_length) : \ + (input_length)) : 0u) : \ + 0u) /** A sufficient output buffer size for psa_cipher_update(), for any of the * supported key types and cipher algorithms. @@ -1157,8 +1278,8 @@ (PSA_ALG_IS_CIPHER(alg) ? \ (alg == PSA_ALG_CBC_PKCS7 ? \ PSA_BLOCK_CIPHER_BLOCK_LENGTH(key_type) : \ - 0) : \ - 0) + 0u) : \ + 0u) /** A sufficient ciphertext buffer size for psa_cipher_finish(), for any of the * supported key types and cipher algorithms. diff --git a/vendor/mbedtls/include/psa/crypto_struct.h b/vendor/mbedtls/include/psa/crypto_struct.h index 18cbcf4644..3913551aa8 100644 --- a/vendor/mbedtls/include/psa/crypto_struct.h +++ b/vendor/mbedtls/include/psa/crypto_struct.h @@ -43,55 +43,49 @@ */ /* * Copyright The Mbed TLS Contributors - * SPDX-License-Identifier: Apache-2.0 - * - * Licensed under the Apache License, Version 2.0 (the "License"); you may - * not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT - * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. + * SPDX-License-Identifier: Apache-2.0 OR GPL-2.0-or-later */ #ifndef PSA_CRYPTO_STRUCT_H #define PSA_CRYPTO_STRUCT_H +#include "mbedtls/private_access.h" #ifdef __cplusplus extern "C" { #endif -/* Include the Mbed TLS configuration file, the way Mbed TLS does it - * in each of its header files. */ -#if !defined(MBEDTLS_CONFIG_FILE) -#include "mbedtls/config.h" -#else -#include MBEDTLS_CONFIG_FILE -#endif - -#include "mbedtls/cmac.h" -#include "mbedtls/gcm.h" +/* + * Include the build-time configuration information header. Here, we do not + * include `"mbedtls/build_info.h"` directly but `"psa/build_info.h"`, which + * is basically just an alias to it. This is to ease the maintenance of the + * TF-PSA-Crypto repository which has a different build system and + * configuration. + */ +#include "psa/build_info.h" /* Include the context definition for the compiled-in drivers for the primitive * algorithms. */ #include "psa/crypto_driver_contexts_primitives.h" struct psa_hash_operation_s { +#if defined(MBEDTLS_PSA_CRYPTO_CLIENT) && !defined(MBEDTLS_PSA_CRYPTO_C) + mbedtls_psa_client_handle_t handle; +#else /** Unique ID indicating which driver got assigned to do the * operation. Since driver contexts are driver-specific, swapping * drivers halfway through the operation is not supported. * ID values are auto-generated in psa_driver_wrappers.h. * ID value zero means the context is not valid or not assigned to * any driver (i.e. the driver context is not active, in use). */ - unsigned int id; - psa_driver_hash_context_t ctx; + unsigned int MBEDTLS_PRIVATE(id); + psa_driver_hash_context_t MBEDTLS_PRIVATE(ctx); +#endif }; - +#if defined(MBEDTLS_PSA_CRYPTO_CLIENT) && !defined(MBEDTLS_PSA_CRYPTO_C) +#define PSA_HASH_OPERATION_INIT { 0 } +#else #define PSA_HASH_OPERATION_INIT { 0, { 0 } } +#endif static inline struct psa_hash_operation_s psa_hash_operation_init(void) { const struct psa_hash_operation_s v = PSA_HASH_OPERATION_INIT; @@ -99,23 +93,31 @@ static inline struct psa_hash_operation_s psa_hash_operation_init(void) } struct psa_cipher_operation_s { +#if defined(MBEDTLS_PSA_CRYPTO_CLIENT) && !defined(MBEDTLS_PSA_CRYPTO_C) + mbedtls_psa_client_handle_t handle; +#else /** Unique ID indicating which driver got assigned to do the * operation. Since driver contexts are driver-specific, swapping * drivers halfway through the operation is not supported. * ID values are auto-generated in psa_crypto_driver_wrappers.h * ID value zero means the context is not valid or not assigned to * any driver (i.e. none of the driver contexts are active). */ - unsigned int id; + unsigned int MBEDTLS_PRIVATE(id); - unsigned int iv_required : 1; - unsigned int iv_set : 1; + unsigned int MBEDTLS_PRIVATE(iv_required) : 1; + unsigned int MBEDTLS_PRIVATE(iv_set) : 1; - uint8_t default_iv_length; + uint8_t MBEDTLS_PRIVATE(default_iv_length); - psa_driver_cipher_context_t ctx; + psa_driver_cipher_context_t MBEDTLS_PRIVATE(ctx); +#endif }; +#if defined(MBEDTLS_PSA_CRYPTO_CLIENT) && !defined(MBEDTLS_PSA_CRYPTO_C) +#define PSA_CIPHER_OPERATION_INIT { 0 } +#else #define PSA_CIPHER_OPERATION_INIT { 0, 0, 0, 0, { 0 } } +#endif static inline struct psa_cipher_operation_s psa_cipher_operation_init(void) { const struct psa_cipher_operation_s v = PSA_CIPHER_OPERATION_INIT; @@ -127,19 +129,27 @@ static inline struct psa_cipher_operation_s psa_cipher_operation_init(void) #include "psa/crypto_driver_contexts_composites.h" struct psa_mac_operation_s { +#if defined(MBEDTLS_PSA_CRYPTO_CLIENT) && !defined(MBEDTLS_PSA_CRYPTO_C) + mbedtls_psa_client_handle_t handle; +#else /** Unique ID indicating which driver got assigned to do the * operation. Since driver contexts are driver-specific, swapping * drivers halfway through the operation is not supported. * ID values are auto-generated in psa_driver_wrappers.h * ID value zero means the context is not valid or not assigned to * any driver (i.e. none of the driver contexts are active). */ - unsigned int id; - uint8_t mac_size; - unsigned int is_sign : 1; - psa_driver_mac_context_t ctx; + unsigned int MBEDTLS_PRIVATE(id); + uint8_t MBEDTLS_PRIVATE(mac_size); + unsigned int MBEDTLS_PRIVATE(is_sign) : 1; + psa_driver_mac_context_t MBEDTLS_PRIVATE(ctx); +#endif }; +#if defined(MBEDTLS_PSA_CRYPTO_CLIENT) && !defined(MBEDTLS_PSA_CRYPTO_C) +#define PSA_MAC_OPERATION_INIT { 0 } +#else #define PSA_MAC_OPERATION_INIT { 0, 0, 0, { 0 } } +#endif static inline struct psa_mac_operation_s psa_mac_operation_init(void) { const struct psa_mac_operation_s v = PSA_MAC_OPERATION_INIT; @@ -147,109 +157,92 @@ static inline struct psa_mac_operation_s psa_mac_operation_init(void) } struct psa_aead_operation_s { - psa_algorithm_t alg; - unsigned int key_set : 1; - unsigned int iv_set : 1; - uint8_t iv_size; - uint8_t block_size; - union { - unsigned dummy; /* Enable easier initializing of the union. */ - mbedtls_cipher_context_t cipher; - } ctx; +#if defined(MBEDTLS_PSA_CRYPTO_CLIENT) && !defined(MBEDTLS_PSA_CRYPTO_C) + mbedtls_psa_client_handle_t handle; +#else + /** Unique ID indicating which driver got assigned to do the + * operation. Since driver contexts are driver-specific, swapping + * drivers halfway through the operation is not supported. + * ID values are auto-generated in psa_crypto_driver_wrappers.h + * ID value zero means the context is not valid or not assigned to + * any driver (i.e. none of the driver contexts are active). */ + unsigned int MBEDTLS_PRIVATE(id); + + psa_algorithm_t MBEDTLS_PRIVATE(alg); + psa_key_type_t MBEDTLS_PRIVATE(key_type); + + size_t MBEDTLS_PRIVATE(ad_remaining); + size_t MBEDTLS_PRIVATE(body_remaining); + + unsigned int MBEDTLS_PRIVATE(nonce_set) : 1; + unsigned int MBEDTLS_PRIVATE(lengths_set) : 1; + unsigned int MBEDTLS_PRIVATE(ad_started) : 1; + unsigned int MBEDTLS_PRIVATE(body_started) : 1; + unsigned int MBEDTLS_PRIVATE(is_encrypt) : 1; + + psa_driver_aead_context_t MBEDTLS_PRIVATE(ctx); +#endif }; -#define PSA_AEAD_OPERATION_INIT { 0, 0, 0, 0, 0, { 0 } } +#if defined(MBEDTLS_PSA_CRYPTO_CLIENT) && !defined(MBEDTLS_PSA_CRYPTO_C) +#define PSA_AEAD_OPERATION_INIT { 0 } +#else +#define PSA_AEAD_OPERATION_INIT { 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, { 0 } } +#endif static inline struct psa_aead_operation_s psa_aead_operation_init(void) { const struct psa_aead_operation_s v = PSA_AEAD_OPERATION_INIT; return v; } -#if defined(MBEDTLS_PSA_BUILTIN_ALG_HKDF) -typedef struct { - uint8_t *info; - size_t info_length; -#if PSA_HASH_MAX_SIZE > 0xff -#error "PSA_HASH_MAX_SIZE does not fit in uint8_t" -#endif - uint8_t offset_in_block; - uint8_t block_number; - unsigned int state : 2; - unsigned int info_set : 1; - uint8_t output_block[PSA_HASH_MAX_SIZE]; - uint8_t prk[PSA_HASH_MAX_SIZE]; - struct psa_mac_operation_s hmac; -} psa_hkdf_key_derivation_t; -#endif /* MBEDTLS_PSA_BUILTIN_ALG_HKDF */ - -#if defined(MBEDTLS_PSA_BUILTIN_ALG_TLS12_PRF) || \ - defined(MBEDTLS_PSA_BUILTIN_ALG_TLS12_PSK_TO_MS) -typedef enum { - PSA_TLS12_PRF_STATE_INIT, /* no input provided */ - PSA_TLS12_PRF_STATE_SEED_SET, /* seed has been set */ - PSA_TLS12_PRF_STATE_KEY_SET, /* key has been set */ - PSA_TLS12_PRF_STATE_LABEL_SET, /* label has been set */ - PSA_TLS12_PRF_STATE_OUTPUT /* output has been started */ -} psa_tls12_prf_key_derivation_state_t; - -typedef struct psa_tls12_prf_key_derivation_s { -#if PSA_HASH_MAX_SIZE > 0xff -#error "PSA_HASH_MAX_SIZE does not fit in uint8_t" -#endif - - /* Indicates how many bytes in the current HMAC block have - * not yet been read by the user. */ - uint8_t left_in_block; - - /* The 1-based number of the block. */ - uint8_t block_number; - - psa_tls12_prf_key_derivation_state_t state; - - uint8_t *secret; - size_t secret_length; - uint8_t *seed; - size_t seed_length; - uint8_t *label; - size_t label_length; - - uint8_t Ai[PSA_HASH_MAX_SIZE]; - - /* `HMAC_hash( prk, A(i) + seed )` in the notation of RFC 5246, Sect. 5. */ - uint8_t output_block[PSA_HASH_MAX_SIZE]; -} psa_tls12_prf_key_derivation_t; -#endif /* MBEDTLS_PSA_BUILTIN_ALG_TLS12_PRF) || - * MBEDTLS_PSA_BUILTIN_ALG_TLS12_PSK_TO_MS */ +/* Include the context definition for the compiled-in drivers for the key + * derivation algorithms. */ +#include "psa/crypto_driver_contexts_key_derivation.h" struct psa_key_derivation_s { - psa_algorithm_t alg; - unsigned int can_output_key : 1; - size_t capacity; - union { - /* Make the union non-empty even with no supported algorithms. */ - uint8_t dummy; -#if defined(MBEDTLS_PSA_BUILTIN_ALG_HKDF) - psa_hkdf_key_derivation_t hkdf; -#endif -#if defined(MBEDTLS_PSA_BUILTIN_ALG_TLS12_PRF) || \ - defined(MBEDTLS_PSA_BUILTIN_ALG_TLS12_PSK_TO_MS) - psa_tls12_prf_key_derivation_t tls12_prf; +#if defined(MBEDTLS_PSA_CRYPTO_CLIENT) && !defined(MBEDTLS_PSA_CRYPTO_C) + mbedtls_psa_client_handle_t handle; +#else + psa_algorithm_t MBEDTLS_PRIVATE(alg); + unsigned int MBEDTLS_PRIVATE(can_output_key) : 1; + size_t MBEDTLS_PRIVATE(capacity); + psa_driver_key_derivation_context_t MBEDTLS_PRIVATE(ctx); #endif - } ctx; }; +#if defined(MBEDTLS_PSA_CRYPTO_CLIENT) && !defined(MBEDTLS_PSA_CRYPTO_C) +#define PSA_KEY_DERIVATION_OPERATION_INIT { 0 } +#else /* This only zeroes out the first byte in the union, the rest is unspecified. */ #define PSA_KEY_DERIVATION_OPERATION_INIT { 0, 0, 0, { 0 } } -static inline struct psa_key_derivation_s psa_key_derivation_operation_init(void) +#endif +static inline struct psa_key_derivation_s psa_key_derivation_operation_init( + void) { const struct psa_key_derivation_s v = PSA_KEY_DERIVATION_OPERATION_INIT; return v; } +struct psa_key_production_parameters_s { + /* Future versions may add other fields in this structure. */ + uint32_t flags; + uint8_t data[]; +}; + +/** The default production parameters for key generation or key derivation. + * + * Calling psa_generate_key_ext() or psa_key_derivation_output_key_ext() + * with `params=PSA_KEY_PRODUCTION_PARAMETERS_INIT` and + * `params_data_length == 0` is equivalent to + * calling psa_generate_key() or psa_key_derivation_output_key() + * respectively. + */ +#define PSA_KEY_PRODUCTION_PARAMETERS_INIT { 0 } + struct psa_key_policy_s { - psa_key_usage_t usage; - psa_algorithm_t alg; - psa_algorithm_t alg2; + psa_key_usage_t MBEDTLS_PRIVATE(usage); + psa_algorithm_t MBEDTLS_PRIVATE(alg); + psa_algorithm_t MBEDTLS_PRIVATE(alg2); }; typedef struct psa_key_policy_s psa_key_policy_t; @@ -265,7 +258,7 @@ static inline struct psa_key_policy_s psa_key_policy_init(void) typedef uint16_t psa_key_bits_t; /* The maximum value of the type used to represent bit-sizes. * This is used to mark an invalid key size. */ -#define PSA_KEY_BITS_TOO_LARGE ((psa_key_bits_t) (-1)) +#define PSA_KEY_BITS_TOO_LARGE ((psa_key_bits_t) -1) /* The maximum size of a key in bits. * Currently defined as the maximum that can be represented, rounded down * to a whole number of bytes. @@ -273,55 +266,39 @@ typedef uint16_t psa_key_bits_t; * conditionals. */ #define PSA_MAX_KEY_BITS 0xfff8 -/** A mask of flags that can be stored in key attributes. - * - * This type is also used internally to store flags in slots. Internal - * flags are defined in library/psa_crypto_core.h. Internal flags may have - * the same value as external flags if they are properly handled during - * key creation and in psa_get_key_attributes. - */ -typedef uint16_t psa_key_attributes_flag_t; - -#define MBEDTLS_PSA_KA_FLAG_HAS_SLOT_NUMBER \ - ((psa_key_attributes_flag_t) 0x0001) - -/* A mask of key attribute flags used externally only. - * Only meant for internal checks inside the library. */ -#define MBEDTLS_PSA_KA_MASK_EXTERNAL_ONLY ( \ - MBEDTLS_PSA_KA_FLAG_HAS_SLOT_NUMBER | \ - 0) - -/* A mask of key attribute flags used both internally and externally. - * Currently there aren't any. */ -#define MBEDTLS_PSA_KA_MASK_DUAL_USE ( \ - 0) - -typedef struct { - psa_key_type_t type; - psa_key_bits_t bits; - psa_key_lifetime_t lifetime; - mbedtls_svc_key_id_t id; - psa_key_policy_t policy; - psa_key_attributes_flag_t flags; -} psa_core_key_attributes_t; - -#define PSA_CORE_KEY_ATTRIBUTES_INIT { PSA_KEY_TYPE_NONE, 0, PSA_KEY_LIFETIME_VOLATILE, \ - MBEDTLS_SVC_KEY_ID_INIT, PSA_KEY_POLICY_INIT, 0 } - struct psa_key_attributes_s { - psa_core_key_attributes_t core; #if defined(MBEDTLS_PSA_CRYPTO_SE_C) - psa_key_slot_number_t slot_number; + psa_key_slot_number_t MBEDTLS_PRIVATE(slot_number); + int MBEDTLS_PRIVATE(has_slot_number); #endif /* MBEDTLS_PSA_CRYPTO_SE_C */ - void *domain_parameters; - size_t domain_parameters_size; + psa_key_type_t MBEDTLS_PRIVATE(type); + psa_key_bits_t MBEDTLS_PRIVATE(bits); + psa_key_lifetime_t MBEDTLS_PRIVATE(lifetime); + psa_key_policy_t MBEDTLS_PRIVATE(policy); + /* This type has a different layout in the client view wrt the + * service view of the key id, i.e. in service view usually is + * expected to have MBEDTLS_PSA_CRYPTO_KEY_ID_ENCODES_OWNER defined + * thus adding an owner field to the standard psa_key_id_t. For + * implementations with client/service separation, this means the + * object will be marshalled through a transport channel and + * interpreted differently at each side of the transport. Placing + * it at the end of structures allows to interpret the structure + * at the client without reorganizing the memory layout of the + * struct + */ + mbedtls_svc_key_id_t MBEDTLS_PRIVATE(id); }; #if defined(MBEDTLS_PSA_CRYPTO_SE_C) -#define PSA_KEY_ATTRIBUTES_INIT { PSA_CORE_KEY_ATTRIBUTES_INIT, 0, NULL, 0 } +#define PSA_KEY_ATTRIBUTES_MAYBE_SLOT_NUMBER 0, 0, #else -#define PSA_KEY_ATTRIBUTES_INIT { PSA_CORE_KEY_ATTRIBUTES_INIT, NULL, 0 } +#define PSA_KEY_ATTRIBUTES_MAYBE_SLOT_NUMBER #endif +#define PSA_KEY_ATTRIBUTES_INIT { PSA_KEY_ATTRIBUTES_MAYBE_SLOT_NUMBER \ + PSA_KEY_TYPE_NONE, 0, \ + PSA_KEY_LIFETIME_VOLATILE, \ + PSA_KEY_POLICY_INIT, \ + MBEDTLS_SVC_KEY_ID_INIT } static inline struct psa_key_attributes_s psa_key_attributes_init(void) { @@ -332,12 +309,12 @@ static inline struct psa_key_attributes_s psa_key_attributes_init(void) static inline void psa_set_key_id(psa_key_attributes_t *attributes, mbedtls_svc_key_id_t key) { - psa_key_lifetime_t lifetime = attributes->core.lifetime; + psa_key_lifetime_t lifetime = attributes->MBEDTLS_PRIVATE(lifetime); - attributes->core.id = key; + attributes->MBEDTLS_PRIVATE(id) = key; if (PSA_KEY_LIFETIME_IS_VOLATILE(lifetime)) { - attributes->core.lifetime = + attributes->MBEDTLS_PRIVATE(lifetime) = PSA_KEY_LIFETIME_FROM_PERSISTENCE_AND_LOCATION( PSA_KEY_LIFETIME_PERSISTENT, PSA_KEY_LIFETIME_GET_LOCATION(lifetime)); @@ -347,26 +324,26 @@ static inline void psa_set_key_id(psa_key_attributes_t *attributes, static inline mbedtls_svc_key_id_t psa_get_key_id( const psa_key_attributes_t *attributes) { - return attributes->core.id; + return attributes->MBEDTLS_PRIVATE(id); } #ifdef MBEDTLS_PSA_CRYPTO_KEY_ID_ENCODES_OWNER static inline void mbedtls_set_key_owner_id(psa_key_attributes_t *attributes, mbedtls_key_owner_id_t owner) { - attributes->core.id.owner = owner; + attributes->MBEDTLS_PRIVATE(id).MBEDTLS_PRIVATE(owner) = owner; } #endif static inline void psa_set_key_lifetime(psa_key_attributes_t *attributes, psa_key_lifetime_t lifetime) { - attributes->core.lifetime = lifetime; + attributes->MBEDTLS_PRIVATE(lifetime) = lifetime; if (PSA_KEY_LIFETIME_IS_VOLATILE(lifetime)) { #ifdef MBEDTLS_PSA_CRYPTO_KEY_ID_ENCODES_OWNER - attributes->core.id.key_id = 0; + attributes->MBEDTLS_PRIVATE(id).MBEDTLS_PRIVATE(key_id) = 0; #else - attributes->core.id = 0; + attributes->MBEDTLS_PRIVATE(id) = 0; #endif } } @@ -374,7 +351,7 @@ static inline void psa_set_key_lifetime(psa_key_attributes_t *attributes, static inline psa_key_lifetime_t psa_get_key_lifetime( const psa_key_attributes_t *attributes) { - return attributes->core.lifetime; + return attributes->MBEDTLS_PRIVATE(lifetime); } static inline void psa_extend_key_usage_flags(psa_key_usage_t *usage_flags) @@ -392,69 +369,129 @@ static inline void psa_set_key_usage_flags(psa_key_attributes_t *attributes, psa_key_usage_t usage_flags) { psa_extend_key_usage_flags(&usage_flags); - attributes->core.policy.usage = usage_flags; + attributes->MBEDTLS_PRIVATE(policy).MBEDTLS_PRIVATE(usage) = usage_flags; } static inline psa_key_usage_t psa_get_key_usage_flags( const psa_key_attributes_t *attributes) { - return attributes->core.policy.usage; + return attributes->MBEDTLS_PRIVATE(policy).MBEDTLS_PRIVATE(usage); } static inline void psa_set_key_algorithm(psa_key_attributes_t *attributes, psa_algorithm_t alg) { - attributes->core.policy.alg = alg; + attributes->MBEDTLS_PRIVATE(policy).MBEDTLS_PRIVATE(alg) = alg; } static inline psa_algorithm_t psa_get_key_algorithm( const psa_key_attributes_t *attributes) { - return attributes->core.policy.alg; + return attributes->MBEDTLS_PRIVATE(policy).MBEDTLS_PRIVATE(alg); } -/* This function is declared in crypto_extra.h, which comes after this - * header file, but we need the function here, so repeat the declaration. */ -psa_status_t psa_set_key_domain_parameters(psa_key_attributes_t *attributes, - psa_key_type_t type, - const uint8_t *data, - size_t data_length); - static inline void psa_set_key_type(psa_key_attributes_t *attributes, psa_key_type_t type) { - if (attributes->domain_parameters == NULL) { - /* Common case: quick path */ - attributes->core.type = type; - } else { - /* Call the bigger function to free the old domain parameters. - * Ignore any errors which may arise due to type requiring - * non-default domain parameters, since this function can't - * report errors. */ - (void) psa_set_key_domain_parameters(attributes, type, NULL, 0); - } + attributes->MBEDTLS_PRIVATE(type) = type; } static inline psa_key_type_t psa_get_key_type( const psa_key_attributes_t *attributes) { - return attributes->core.type; + return attributes->MBEDTLS_PRIVATE(type); } static inline void psa_set_key_bits(psa_key_attributes_t *attributes, size_t bits) { if (bits > PSA_MAX_KEY_BITS) { - attributes->core.bits = PSA_KEY_BITS_TOO_LARGE; + attributes->MBEDTLS_PRIVATE(bits) = PSA_KEY_BITS_TOO_LARGE; } else { - attributes->core.bits = (psa_key_bits_t) bits; + attributes->MBEDTLS_PRIVATE(bits) = (psa_key_bits_t) bits; } } static inline size_t psa_get_key_bits( const psa_key_attributes_t *attributes) { - return attributes->core.bits; + return attributes->MBEDTLS_PRIVATE(bits); +} + +/** + * \brief The context for PSA interruptible hash signing. + */ +struct psa_sign_hash_interruptible_operation_s { +#if defined(MBEDTLS_PSA_CRYPTO_CLIENT) && !defined(MBEDTLS_PSA_CRYPTO_C) + mbedtls_psa_client_handle_t handle; +#else + /** Unique ID indicating which driver got assigned to do the + * operation. Since driver contexts are driver-specific, swapping + * drivers halfway through the operation is not supported. + * ID values are auto-generated in psa_crypto_driver_wrappers.h + * ID value zero means the context is not valid or not assigned to + * any driver (i.e. none of the driver contexts are active). */ + unsigned int MBEDTLS_PRIVATE(id); + + psa_driver_sign_hash_interruptible_context_t MBEDTLS_PRIVATE(ctx); + + unsigned int MBEDTLS_PRIVATE(error_occurred) : 1; + + uint32_t MBEDTLS_PRIVATE(num_ops); +#endif +}; + +#if defined(MBEDTLS_PSA_CRYPTO_CLIENT) && !defined(MBEDTLS_PSA_CRYPTO_C) +#define PSA_SIGN_HASH_INTERRUPTIBLE_OPERATION_INIT { 0 } +#else +#define PSA_SIGN_HASH_INTERRUPTIBLE_OPERATION_INIT { 0, { 0 }, 0, 0 } +#endif + +static inline struct psa_sign_hash_interruptible_operation_s +psa_sign_hash_interruptible_operation_init(void) +{ + const struct psa_sign_hash_interruptible_operation_s v = + PSA_SIGN_HASH_INTERRUPTIBLE_OPERATION_INIT; + + return v; +} + +/** + * \brief The context for PSA interruptible hash verification. + */ +struct psa_verify_hash_interruptible_operation_s { +#if defined(MBEDTLS_PSA_CRYPTO_CLIENT) && !defined(MBEDTLS_PSA_CRYPTO_C) + mbedtls_psa_client_handle_t handle; +#else + /** Unique ID indicating which driver got assigned to do the + * operation. Since driver contexts are driver-specific, swapping + * drivers halfway through the operation is not supported. + * ID values are auto-generated in psa_crypto_driver_wrappers.h + * ID value zero means the context is not valid or not assigned to + * any driver (i.e. none of the driver contexts are active). */ + unsigned int MBEDTLS_PRIVATE(id); + + psa_driver_verify_hash_interruptible_context_t MBEDTLS_PRIVATE(ctx); + + unsigned int MBEDTLS_PRIVATE(error_occurred) : 1; + + uint32_t MBEDTLS_PRIVATE(num_ops); +#endif +}; + +#if defined(MBEDTLS_PSA_CRYPTO_CLIENT) && !defined(MBEDTLS_PSA_CRYPTO_C) +#define PSA_VERIFY_HASH_INTERRUPTIBLE_OPERATION_INIT { 0 } +#else +#define PSA_VERIFY_HASH_INTERRUPTIBLE_OPERATION_INIT { 0, { 0 }, 0, 0 } +#endif + +static inline struct psa_verify_hash_interruptible_operation_s +psa_verify_hash_interruptible_operation_init(void) +{ + const struct psa_verify_hash_interruptible_operation_s v = + PSA_VERIFY_HASH_INTERRUPTIBLE_OPERATION_INIT; + + return v; } #ifdef __cplusplus diff --git a/vendor/mbedtls/include/psa/crypto_types.h b/vendor/mbedtls/include/psa/crypto_types.h index d47d3ebf00..c21bad86cc 100644 --- a/vendor/mbedtls/include/psa/crypto_types.h +++ b/vendor/mbedtls/include/psa/crypto_types.h @@ -15,32 +15,29 @@ */ /* * Copyright The Mbed TLS Contributors - * SPDX-License-Identifier: Apache-2.0 - * - * Licensed under the Apache License, Version 2.0 (the "License"); you may - * not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT - * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. + * SPDX-License-Identifier: Apache-2.0 OR GPL-2.0-or-later */ #ifndef PSA_CRYPTO_TYPES_H #define PSA_CRYPTO_TYPES_H -#include "crypto_platform.h" - -/* If MBEDTLS_PSA_CRYPTO_C is defined, make sure MBEDTLS_PSA_CRYPTO_CLIENT - * is defined as well to include all PSA code. +/* + * Include the build-time configuration information header. Here, we do not + * include `"mbedtls/build_info.h"` directly but `"psa/build_info.h"`, which + * is basically just an alias to it. This is to ease the maintenance of the + * TF-PSA-Crypto repository which has a different build system and + * configuration. */ -#if defined(MBEDTLS_PSA_CRYPTO_C) -#define MBEDTLS_PSA_CRYPTO_CLIENT -#endif /* MBEDTLS_PSA_CRYPTO_C */ +#include "psa/build_info.h" + +/* Define the MBEDTLS_PRIVATE macro. */ +#include "mbedtls/private_access.h" + +#if defined(MBEDTLS_PSA_CRYPTO_PLATFORM_FILE) +#include MBEDTLS_PSA_CRYPTO_PLATFORM_FILE +#else +#include "crypto_platform.h" +#endif #include @@ -301,8 +298,8 @@ typedef psa_key_id_t mbedtls_svc_key_id_t; * functions such as psa_open_key(). */ typedef struct { - psa_key_id_t key_id; - mbedtls_key_owner_id_t owner; + psa_key_id_t MBEDTLS_PRIVATE(key_id); + mbedtls_key_owner_id_t MBEDTLS_PRIVATE(owner); } mbedtls_svc_key_id_t; #endif /* !MBEDTLS_PSA_CRYPTO_KEY_ID_ENCODES_OWNER */ @@ -458,6 +455,30 @@ typedef uint64_t psa_key_slot_number_t; */ typedef uint16_t psa_key_derivation_step_t; +/** \brief Custom parameters for key generation or key derivation. + * + * This is a structure type with at least the following fields: + * + * - \c flags: an unsigned integer type. 0 for the default production parameters. + * - \c data: a flexible array of bytes. + * + * The interpretation of this structure depend on the type of the + * created key. + * + * - #PSA_KEY_TYPE_RSA_KEY_PAIR: + * - \c flags: must be 0. + * - \c data: the public exponent, in little-endian order. + * This must be an odd integer and must not be 1. + * Implementations must support 65537, should support 3 and may + * support other values. + * When not using a driver, Mbed TLS supports values up to \c INT_MAX. + * If this is empty or if the custom production parameters are omitted + * altogether, the default value 65537 is used. + * - Other key types: reserved for future use. \c flags must be 0. + * + */ +typedef struct psa_key_production_parameters_s psa_key_production_parameters_t; + /**@}*/ #endif /* PSA_CRYPTO_TYPES_H */ diff --git a/vendor/mbedtls/include/psa/crypto_values.h b/vendor/mbedtls/include/psa/crypto_values.h index a6214bda98..1d678dbfc2 100644 --- a/vendor/mbedtls/include/psa/crypto_values.h +++ b/vendor/mbedtls/include/psa/crypto_values.h @@ -21,23 +21,12 @@ */ /* * Copyright The Mbed TLS Contributors - * SPDX-License-Identifier: Apache-2.0 - * - * Licensed under the Apache License, Version 2.0 (the "License"); you may - * not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT - * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. + * SPDX-License-Identifier: Apache-2.0 OR GPL-2.0-or-later */ #ifndef PSA_CRYPTO_VALUES_H #define PSA_CRYPTO_VALUES_H +#include "mbedtls/private_access.h" /** \defgroup error Error codes * @{ @@ -290,6 +279,11 @@ * to read from a resource. */ #define PSA_ERROR_INSUFFICIENT_DATA ((psa_status_t)-143) +/** This can be returned if a function can no longer operate correctly. + * For example, if an essential initialization operation failed or + * a mutex operation failed. */ +#define PSA_ERROR_SERVICE_FAILURE ((psa_status_t)-144) + /** The key identifier is not valid. See also :ref:\`key-handles\`. */ #define PSA_ERROR_INVALID_HANDLE ((psa_status_t)-136) @@ -334,6 +328,13 @@ */ #define PSA_ERROR_DATA_INVALID ((psa_status_t)-153) +/** The function that returns this status is defined as interruptible and + * still has work to do, thus the user should call the function again with the + * same operation context until it either returns #PSA_SUCCESS or any other + * error. This is not an error per se, more a notification of status. + */ +#define PSA_OPERATION_INCOMPLETE ((psa_status_t)-248) + /* *INDENT-ON* */ /**@}*/ @@ -412,7 +413,7 @@ ((type) | PSA_KEY_TYPE_CATEGORY_FLAG_PAIR) /** The public key type corresponding to a key pair type. * - * You may also pass a key pair type as \p type, it will be left unchanged. + * You may also pass a public key type as \p type, it will be left unchanged. * * \param type A public key type or key pair type. * @@ -440,12 +441,56 @@ #define PSA_KEY_TYPE_HMAC ((psa_key_type_t) 0x1100) /** A secret for key derivation. + * + * This key type is for high-entropy secrets only. For low-entropy secrets, + * #PSA_KEY_TYPE_PASSWORD should be used instead. + * + * These keys can be used as the #PSA_KEY_DERIVATION_INPUT_SECRET or + * #PSA_KEY_DERIVATION_INPUT_PASSWORD input of key derivation algorithms. * * The key policy determines which key derivation algorithm the key * can be used for. */ #define PSA_KEY_TYPE_DERIVE ((psa_key_type_t) 0x1200) +/** A low-entropy secret for password hashing or key derivation. + * + * This key type is suitable for passwords and passphrases which are typically + * intended to be memorizable by humans, and have a low entropy relative to + * their size. It can be used for randomly generated or derived keys with + * maximum or near-maximum entropy, but #PSA_KEY_TYPE_DERIVE is more suitable + * for such keys. It is not suitable for passwords with extremely low entropy, + * such as numerical PINs. + * + * These keys can be used as the #PSA_KEY_DERIVATION_INPUT_PASSWORD input of + * key derivation algorithms. Algorithms that accept such an input were + * designed to accept low-entropy secret and are known as password hashing or + * key stretching algorithms. + * + * These keys cannot be used as the #PSA_KEY_DERIVATION_INPUT_SECRET input of + * key derivation algorithms, as the algorithms that take such an input expect + * it to be high-entropy. + * + * The key policy determines which key derivation algorithm the key can be + * used for, among the permissible subset defined above. + */ +#define PSA_KEY_TYPE_PASSWORD ((psa_key_type_t) 0x1203) + +/** A secret value that can be used to verify a password hash. + * + * The key policy determines which key derivation algorithm the key + * can be used for, among the same permissible subset as for + * #PSA_KEY_TYPE_PASSWORD. + */ +#define PSA_KEY_TYPE_PASSWORD_HASH ((psa_key_type_t) 0x1205) + +/** A secret value that can be used in when computing a password hash. + * + * The key policy determines which key derivation algorithm the key + * can be used for, among the subset of algorithms that can use pepper. + */ +#define PSA_KEY_TYPE_PEPPER ((psa_key_type_t) 0x1206) + /** Key for a cipher, AEAD or MAC algorithm based on the AES block cipher. * * The size of the key can be 16 bytes (AES-128), 24 bytes (AES-192) or @@ -472,18 +517,16 @@ * Camellia block cipher. */ #define PSA_KEY_TYPE_CAMELLIA ((psa_key_type_t) 0x2403) -/** Key for the ARC4 stream cipher (also known as RC4 or ARCFOUR). - * - * Note that ARC4 is weak and deprecated and should only be used in - * legacy protocols. */ -#define PSA_KEY_TYPE_ARC4 ((psa_key_type_t) 0x2002) - /** Key for the ChaCha20 stream cipher or the Chacha20-Poly1305 AEAD algorithm. * * ChaCha20 and the ChaCha20_Poly1305 construction are defined in RFC 7539. * - * Implementations must support 12-byte nonces, may support 8-byte nonces, - * and should reject other sizes. + * \note For ChaCha20 and ChaCha20_Poly1305, Mbed TLS only supports + * 12-byte nonces. + * + * \note For ChaCha20, the initial counter value is 0. To encrypt or decrypt + * with the initial counter value 1, you can process and discard a + * 64-byte block before the real data. */ #define PSA_KEY_TYPE_CHACHA20 ((psa_key_type_t) 0x2004) @@ -546,6 +589,9 @@ ((type) & PSA_KEY_TYPE_ECC_CURVE_MASK) : \ 0)) +/** Check if the curve of given family is Weierstrass elliptic curve. */ +#define PSA_ECC_FAMILY_IS_WEIERSTRASS(family) ((family & 0xc0) == 0) + /** SEC Koblitz curves over prime fields. * * This family comprises the following curves: @@ -553,19 +599,23 @@ * They are defined in _Standards for Efficient Cryptography_, * _SEC 2: Recommended Elliptic Curve Domain Parameters_. * https://www.secg.org/sec2-v2.pdf + * + * \note For secp224k1, the bit-size is 225 (size of a private value). + * + * \note Mbed TLS only supports secp192k1 and secp256k1. */ #define PSA_ECC_FAMILY_SECP_K1 ((psa_ecc_family_t) 0x17) /** SEC random curves over prime fields. * * This family comprises the following curves: - * secp192k1, secp224r1, secp256r1, secp384r1, secp521r1. + * secp192r1, secp224r1, secp256r1, secp384r1, secp521r1. * They are defined in _Standards for Efficient Cryptography_, * _SEC 2: Recommended Elliptic Curve Domain Parameters_. * https://www.secg.org/sec2-v2.pdf */ #define PSA_ECC_FAMILY_SECP_R1 ((psa_ecc_family_t) 0x12) -/* SECP160R2 (SEC2 v1, obsolete) */ +/* SECP160R2 (SEC2 v1, obsolete, not supported in Mbed TLS) */ #define PSA_ECC_FAMILY_SECP_R2 ((psa_ecc_family_t) 0x1b) /** SEC Koblitz curves over binary fields. @@ -575,6 +625,8 @@ * They are defined in _Standards for Efficient Cryptography_, * _SEC 2: Recommended Elliptic Curve Domain Parameters_. * https://www.secg.org/sec2-v2.pdf + * + * \note Mbed TLS does not support any curve in this family. */ #define PSA_ECC_FAMILY_SECT_K1 ((psa_ecc_family_t) 0x27) @@ -585,6 +637,8 @@ * They are defined in _Standards for Efficient Cryptography_, * _SEC 2: Recommended Elliptic Curve Domain Parameters_. * https://www.secg.org/sec2-v2.pdf + * + * \note Mbed TLS does not support any curve in this family. */ #define PSA_ECC_FAMILY_SECT_R1 ((psa_ecc_family_t) 0x22) @@ -595,6 +649,8 @@ * It is defined in _Standards for Efficient Cryptography_, * _SEC 2: Recommended Elliptic Curve Domain Parameters_. * https://www.secg.org/sec2-v2.pdf + * + * \note Mbed TLS does not support any curve in this family. */ #define PSA_ECC_FAMILY_SECT_R2 ((psa_ecc_family_t) 0x2b) @@ -604,6 +660,9 @@ * brainpoolP160r1, brainpoolP192r1, brainpoolP224r1, brainpoolP256r1, * brainpoolP320r1, brainpoolP384r1, brainpoolP512r1. * It is defined in RFC 5639. + * + * \note Mbed TLS only supports the 256-bit, 384-bit and 512-bit curves + * in this family. */ #define PSA_ECC_FAMILY_BRAINPOOL_P_R1 ((psa_ecc_family_t) 0x30) @@ -632,6 +691,8 @@ * - 448-bit: Edwards448, the twisted Edwards curve birationally equivalent * to Curve448. * Hamburg, _Ed448-Goldilocks, a new elliptic curve_, NIST ECC Workshop, 2015. + * + * \note Mbed TLS does not support Edwards curves yet. */ #define PSA_ECC_FAMILY_TWISTED_EDWARDS ((psa_ecc_family_t) 0x42) @@ -827,16 +888,30 @@ #define PSA_ALG_IS_KEY_DERIVATION(alg) \ (((alg) & PSA_ALG_CATEGORY_MASK) == PSA_ALG_CATEGORY_KEY_DERIVATION) +/** Whether the specified algorithm is a key stretching / password hashing + * algorithm. + * + * A key stretching / password hashing algorithm is a key derivation algorithm + * that is suitable for use with a low-entropy secret such as a password. + * Equivalently, it's a key derivation algorithm that uses a + * #PSA_KEY_DERIVATION_INPUT_PASSWORD input step. + * + * \param alg An algorithm identifier (value of type #psa_algorithm_t). + * + * \return 1 if \p alg is a key stretching / password hashing algorithm, 0 + * otherwise. This macro may return either 0 or 1 if \p alg is not a + * supported algorithm identifier. + */ +#define PSA_ALG_IS_KEY_DERIVATION_STRETCHING(alg) \ + (PSA_ALG_IS_KEY_DERIVATION(alg) && \ + (alg) & PSA_ALG_KEY_DERIVATION_STRETCHING_FLAG) + /** An invalid algorithm identifier value. */ /* *INDENT-OFF* (https://github.com/ARM-software/psa-arch-tests/issues/337) */ #define PSA_ALG_NONE ((psa_algorithm_t)0) /* *INDENT-ON* */ #define PSA_ALG_HASH_MASK ((psa_algorithm_t) 0x000000ff) -/** MD2 */ -#define PSA_ALG_MD2 ((psa_algorithm_t) 0x02000001) -/** MD4 */ -#define PSA_ALG_MD4 ((psa_algorithm_t) 0x02000002) /** MD5 */ #define PSA_ALG_MD5 ((psa_algorithm_t) 0x02000003) /** PSA_ALG_RIPEMD160 */ @@ -1098,7 +1173,6 @@ * * The underlying stream cipher is determined by the key type. * - To use ChaCha20, use a key type of #PSA_KEY_TYPE_CHACHA20. - * - To use ARC4, use a key type of #PSA_KEY_TYPE_ARC4. */ #define PSA_ALG_STREAM_CIPHER ((psa_algorithm_t) 0x04800100) @@ -1189,6 +1263,17 @@ */ #define PSA_ALG_CCM ((psa_algorithm_t) 0x05500100) +/** The CCM* cipher mode without authentication. + * + * This is CCM* as specified in IEEE 802.15.4 §7, with a tag length of 0. + * For CCM* with a nonzero tag length, use the AEAD algorithm #PSA_ALG_CCM. + * + * The underlying block cipher is determined by the key type. + * + * Currently only 13-byte long IV's are supported. + */ +#define PSA_ALG_CCM_STAR_NO_TAG ((psa_algorithm_t) 0x04c01300) + /** The GCM authenticated encryption algorithm. * * The underlying block cipher is determined by the key type. @@ -1671,6 +1756,13 @@ 0) /** RSA PKCS#1 v1.5 encryption. + * + * \warning Calling psa_asymmetric_decrypt() with this algorithm as a + * parameter is considered an inherently dangerous function + * (CWE-242). Unless it is used in a side channel free and safe + * way (eg. implementing the TLS protocol as per 7.4.7.1 of + * RFC 5246), the calling code is vulnerable. + * */ #define PSA_ALG_RSA_PKCS1V15_CRYPT ((psa_algorithm_t) 0x07000200) @@ -1712,6 +1804,12 @@ * You may pass #PSA_KEY_DERIVATION_INPUT_INFO at any time after steup and before * starting to generate output. * + * \warning HKDF processes the salt as follows: first hash it with hash_alg + * if the salt is longer than the block size of the hash algorithm; then + * pad with null bytes up to the block size. As a result, it is possible + * for distinct salt inputs to result in the same outputs. To ensure + * unique outputs, it is recommended to use a fixed length for salt values. + * * \param hash_alg A hash algorithm (\c PSA_ALG_XXX value such that * #PSA_ALG_IS_HASH(\p hash_alg) is true). * @@ -1737,6 +1835,112 @@ #define PSA_ALG_HKDF_GET_HASH(hkdf_alg) \ (PSA_ALG_CATEGORY_HASH | ((hkdf_alg) & PSA_ALG_HASH_MASK)) +#define PSA_ALG_HKDF_EXTRACT_BASE ((psa_algorithm_t) 0x08000400) +/** Macro to build an HKDF-Extract algorithm. + * + * For example, `PSA_ALG_HKDF_EXTRACT(PSA_ALG_SHA_256)` is + * HKDF-Extract using HMAC-SHA-256. + * + * This key derivation algorithm uses the following inputs: + * - PSA_KEY_DERIVATION_INPUT_SALT is the salt. + * - PSA_KEY_DERIVATION_INPUT_SECRET is the input keying material used in the + * "extract" step. + * The inputs are mandatory and must be passed in the order above. + * Each input may only be passed once. + * + * \warning HKDF-Extract is not meant to be used on its own. PSA_ALG_HKDF + * should be used instead if possible. PSA_ALG_HKDF_EXTRACT is provided + * as a separate algorithm for the sake of protocols that use it as a + * building block. It may also be a slight performance optimization + * in applications that use HKDF with the same salt and key but many + * different info strings. + * + * \warning HKDF processes the salt as follows: first hash it with hash_alg + * if the salt is longer than the block size of the hash algorithm; then + * pad with null bytes up to the block size. As a result, it is possible + * for distinct salt inputs to result in the same outputs. To ensure + * unique outputs, it is recommended to use a fixed length for salt values. + * + * \param hash_alg A hash algorithm (\c PSA_ALG_XXX value such that + * #PSA_ALG_IS_HASH(\p hash_alg) is true). + * + * \return The corresponding HKDF-Extract algorithm. + * \return Unspecified if \p hash_alg is not a supported + * hash algorithm. + */ +#define PSA_ALG_HKDF_EXTRACT(hash_alg) \ + (PSA_ALG_HKDF_EXTRACT_BASE | ((hash_alg) & PSA_ALG_HASH_MASK)) +/** Whether the specified algorithm is an HKDF-Extract algorithm. + * + * HKDF-Extract is a family of key derivation algorithms that are based + * on a hash function and the HMAC construction. + * + * \param alg An algorithm identifier (value of type #psa_algorithm_t). + * + * \return 1 if \c alg is an HKDF-Extract algorithm, 0 otherwise. + * This macro may return either 0 or 1 if \c alg is not a supported + * key derivation algorithm identifier. + */ +#define PSA_ALG_IS_HKDF_EXTRACT(alg) \ + (((alg) & ~PSA_ALG_HASH_MASK) == PSA_ALG_HKDF_EXTRACT_BASE) + +#define PSA_ALG_HKDF_EXPAND_BASE ((psa_algorithm_t) 0x08000500) +/** Macro to build an HKDF-Expand algorithm. + * + * For example, `PSA_ALG_HKDF_EXPAND(PSA_ALG_SHA_256)` is + * HKDF-Expand using HMAC-SHA-256. + * + * This key derivation algorithm uses the following inputs: + * - PSA_KEY_DERIVATION_INPUT_SECRET is the pseudorandom key (PRK). + * - PSA_KEY_DERIVATION_INPUT_INFO is the info string. + * + * The inputs are mandatory and must be passed in the order above. + * Each input may only be passed once. + * + * \warning HKDF-Expand is not meant to be used on its own. `PSA_ALG_HKDF` + * should be used instead if possible. `PSA_ALG_HKDF_EXPAND` is provided as + * a separate algorithm for the sake of protocols that use it as a building + * block. It may also be a slight performance optimization in applications + * that use HKDF with the same salt and key but many different info strings. + * + * \param hash_alg A hash algorithm (\c PSA_ALG_XXX value such that + * #PSA_ALG_IS_HASH(\p hash_alg) is true). + * + * \return The corresponding HKDF-Expand algorithm. + * \return Unspecified if \p hash_alg is not a supported + * hash algorithm. + */ +#define PSA_ALG_HKDF_EXPAND(hash_alg) \ + (PSA_ALG_HKDF_EXPAND_BASE | ((hash_alg) & PSA_ALG_HASH_MASK)) +/** Whether the specified algorithm is an HKDF-Expand algorithm. + * + * HKDF-Expand is a family of key derivation algorithms that are based + * on a hash function and the HMAC construction. + * + * \param alg An algorithm identifier (value of type #psa_algorithm_t). + * + * \return 1 if \c alg is an HKDF-Expand algorithm, 0 otherwise. + * This macro may return either 0 or 1 if \c alg is not a supported + * key derivation algorithm identifier. + */ +#define PSA_ALG_IS_HKDF_EXPAND(alg) \ + (((alg) & ~PSA_ALG_HASH_MASK) == PSA_ALG_HKDF_EXPAND_BASE) + +/** Whether the specified algorithm is an HKDF or HKDF-Extract or + * HKDF-Expand algorithm. + * + * + * \param alg An algorithm identifier (value of type #psa_algorithm_t). + * + * \return 1 if \c alg is any HKDF type algorithm, 0 otherwise. + * This macro may return either 0 or 1 if \c alg is not a supported + * key derivation algorithm identifier. + */ +#define PSA_ALG_IS_ANY_HKDF(alg) \ + (((alg) & ~PSA_ALG_HASH_MASK) == PSA_ALG_HKDF_BASE || \ + ((alg) & ~PSA_ALG_HASH_MASK) == PSA_ALG_HKDF_EXTRACT_BASE || \ + ((alg) & ~PSA_ALG_HASH_MASK) == PSA_ALG_HKDF_EXPAND_BASE) + #define PSA_ALG_TLS12_PRF_BASE ((psa_algorithm_t) 0x08000200) /** Macro to build a TLS-1.2 PRF algorithm. * @@ -1792,13 +1996,37 @@ * This key derivation algorithm uses the following inputs, which must be * passed in the order given here: * - #PSA_KEY_DERIVATION_INPUT_SEED is the seed. + * - #PSA_KEY_DERIVATION_INPUT_OTHER_SECRET is the other secret for the + * computation of the premaster secret. This input is optional; + * if omitted, it defaults to a string of null bytes with the same length + * as the secret (PSK) input. * - #PSA_KEY_DERIVATION_INPUT_SECRET is the secret key. * - #PSA_KEY_DERIVATION_INPUT_LABEL is the label. * * For the application to TLS-1.2, the seed (which is * forwarded to the TLS-1.2 PRF) is the concatenation of the * ClientHello.Random + ServerHello.Random, - * and the label is "master secret" or "extended master secret". + * the label is "master secret" or "extended master secret" and + * the other secret depends on the key exchange specified in the cipher suite: + * - for a plain PSK cipher suite (RFC 4279, Section 2), omit + * PSA_KEY_DERIVATION_INPUT_OTHER_SECRET + * - for a DHE-PSK (RFC 4279, Section 3) or ECDHE-PSK cipher suite + * (RFC 5489, Section 2), the other secret should be the output of the + * PSA_ALG_FFDH or PSA_ALG_ECDH key agreement performed with the peer. + * The recommended way to pass this input is to use a key derivation + * algorithm constructed as + * PSA_ALG_KEY_AGREEMENT(ka_alg, PSA_ALG_TLS12_PSK_TO_MS(hash_alg)) + * and to call psa_key_derivation_key_agreement(). Alternatively, + * this input may be an output of `psa_raw_key_agreement()` passed with + * psa_key_derivation_input_bytes(), or an equivalent input passed with + * psa_key_derivation_input_bytes() or psa_key_derivation_input_key(). + * - for a RSA-PSK cipher suite (RFC 4279, Section 4), the other secret + * should be the 48-byte client challenge (the PreMasterSecret of + * (RFC 5246, Section 7.4.7.1)) concatenation of the TLS version and + * a 46-byte random string chosen by the client. On the server, this is + * typically an output of psa_asymmetric_decrypt() using + * PSA_ALG_RSA_PKCS1V15_CRYPT, passed to the key derivation operation + * with `psa_key_derivation_input_bytes()`. * * For example, `PSA_ALG_TLS12_PSK_TO_MS(PSA_ALG_SHA_256)` represents the * TLS-1.2 PSK to MasterSecret derivation PRF using HMAC-SHA-256. @@ -1826,6 +2054,86 @@ #define PSA_ALG_TLS12_PSK_TO_MS_GET_HASH(hkdf_alg) \ (PSA_ALG_CATEGORY_HASH | ((hkdf_alg) & PSA_ALG_HASH_MASK)) +/* The TLS 1.2 ECJPAKE-to-PMS KDF. It takes the shared secret K (an EC point + * in case of EC J-PAKE) and calculates SHA256(K.X) that the rest of TLS 1.2 + * will use to derive the session secret, as defined by step 2 of + * https://datatracker.ietf.org/doc/html/draft-cragie-tls-ecjpake-01#section-8.7. + * Uses PSA_ALG_SHA_256. + * This function takes a single input: + * #PSA_KEY_DERIVATION_INPUT_SECRET is the shared secret K from EC J-PAKE. + * The only supported curve is secp256r1 (the 256-bit curve in + * #PSA_ECC_FAMILY_SECP_R1), so the input must be exactly 65 bytes. + * The output has to be read as a single chunk of 32 bytes, defined as + * PSA_TLS12_ECJPAKE_TO_PMS_DATA_SIZE. + */ +#define PSA_ALG_TLS12_ECJPAKE_TO_PMS ((psa_algorithm_t) 0x08000609) + +/* This flag indicates whether the key derivation algorithm is suitable for + * use on low-entropy secrets such as password - these algorithms are also + * known as key stretching or password hashing schemes. These are also the + * algorithms that accepts inputs of type #PSA_KEY_DERIVATION_INPUT_PASSWORD. + * + * Those algorithms cannot be combined with a key agreement algorithm. + */ +#define PSA_ALG_KEY_DERIVATION_STRETCHING_FLAG ((psa_algorithm_t) 0x00800000) + +#define PSA_ALG_PBKDF2_HMAC_BASE ((psa_algorithm_t) 0x08800100) +/** Macro to build a PBKDF2-HMAC password hashing / key stretching algorithm. + * + * PBKDF2 is defined by PKCS#5, republished as RFC 8018 (section 5.2). + * This macro specifies the PBKDF2 algorithm constructed using a PRF based on + * HMAC with the specified hash. + * For example, `PSA_ALG_PBKDF2_HMAC(PSA_ALG_SHA_256)` specifies PBKDF2 + * using the PRF HMAC-SHA-256. + * + * This key derivation algorithm uses the following inputs, which must be + * provided in the following order: + * - #PSA_KEY_DERIVATION_INPUT_COST is the iteration count. + * This input step must be used exactly once. + * - #PSA_KEY_DERIVATION_INPUT_SALT is the salt. + * This input step must be used one or more times; if used several times, the + * inputs will be concatenated. This can be used to build the final salt + * from multiple sources, both public and secret (also known as pepper). + * - #PSA_KEY_DERIVATION_INPUT_PASSWORD is the password to be hashed. + * This input step must be used exactly once. + * + * \param hash_alg A hash algorithm (\c PSA_ALG_XXX value such that + * #PSA_ALG_IS_HASH(\p hash_alg) is true). + * + * \return The corresponding PBKDF2-HMAC-XXX algorithm. + * \return Unspecified if \p hash_alg is not a supported + * hash algorithm. + */ +#define PSA_ALG_PBKDF2_HMAC(hash_alg) \ + (PSA_ALG_PBKDF2_HMAC_BASE | ((hash_alg) & PSA_ALG_HASH_MASK)) + +/** Whether the specified algorithm is a PBKDF2-HMAC algorithm. + * + * \param alg An algorithm identifier (value of type #psa_algorithm_t). + * + * \return 1 if \c alg is a PBKDF2-HMAC algorithm, 0 otherwise. + * This macro may return either 0 or 1 if \c alg is not a supported + * key derivation algorithm identifier. + */ +#define PSA_ALG_IS_PBKDF2_HMAC(alg) \ + (((alg) & ~PSA_ALG_HASH_MASK) == PSA_ALG_PBKDF2_HMAC_BASE) +#define PSA_ALG_PBKDF2_HMAC_GET_HASH(pbkdf2_alg) \ + (PSA_ALG_CATEGORY_HASH | ((pbkdf2_alg) & PSA_ALG_HASH_MASK)) +/** The PBKDF2-AES-CMAC-PRF-128 password hashing / key stretching algorithm. + * + * PBKDF2 is defined by PKCS#5, republished as RFC 8018 (section 5.2). + * This macro specifies the PBKDF2 algorithm constructed using the + * AES-CMAC-PRF-128 PRF specified by RFC 4615. + * + * This key derivation algorithm uses the same inputs as + * #PSA_ALG_PBKDF2_HMAC() with the same constraints. + */ +#define PSA_ALG_PBKDF2_AES_CMAC_PRF_128 ((psa_algorithm_t) 0x08800200) + +#define PSA_ALG_IS_PBKDF2(kdf_alg) \ + (PSA_ALG_IS_PBKDF2_HMAC(kdf_alg) || \ + ((kdf_alg) == PSA_ALG_PBKDF2_AES_CMAC_PRF_128)) + #define PSA_ALG_KEY_DERIVATION_MASK ((psa_algorithm_t) 0xfe00ffff) #define PSA_ALG_KEY_AGREEMENT_MASK ((psa_algorithm_t) 0xffff0000) @@ -1963,6 +2271,18 @@ (alg & PSA_ALG_AEAD_AT_LEAST_THIS_LENGTH_FLAG) != 0 : \ (alg) == PSA_ALG_ANY_HASH) +/** Get the hash used by a composite algorithm. + * + * \param alg An algorithm identifier (value of type #psa_algorithm_t). + * + * \return The underlying hash algorithm if alg is a composite algorithm that + * uses a hash algorithm. + * + * \return \c 0 if alg is not a composite algorithm that uses a hash. + */ +#define PSA_ALG_GET_HASH(alg) \ + (((alg) & 0x000000ff) == 0 ? ((psa_algorithm_t) 0) : 0x02000000 | ((alg) & 0x000000ff)) + /**@}*/ /** \defgroup key_lifetimes Key lifetimes @@ -2159,8 +2479,8 @@ static inline int mbedtls_svc_key_id_is_null(mbedtls_svc_key_id_t key) #else /* MBEDTLS_PSA_CRYPTO_KEY_ID_ENCODES_OWNER */ #define MBEDTLS_SVC_KEY_ID_INIT ((mbedtls_svc_key_id_t){ 0, 0 }) -#define MBEDTLS_SVC_KEY_ID_GET_KEY_ID(id) ((id).key_id) -#define MBEDTLS_SVC_KEY_ID_GET_OWNER_ID(id) ((id).owner) +#define MBEDTLS_SVC_KEY_ID_GET_KEY_ID(id) ((id).MBEDTLS_PRIVATE(key_id)) +#define MBEDTLS_SVC_KEY_ID_GET_OWNER_ID(id) ((id).MBEDTLS_PRIVATE(owner)) /** Utility to initialize a key identifier at runtime. * @@ -2170,8 +2490,8 @@ static inline int mbedtls_svc_key_id_is_null(mbedtls_svc_key_id_t key) static inline mbedtls_svc_key_id_t mbedtls_svc_key_id_make( mbedtls_key_owner_id_t owner_id, psa_key_id_t key_id) { - return (mbedtls_svc_key_id_t){ .key_id = key_id, - .owner = owner_id }; + return (mbedtls_svc_key_id_t){ .MBEDTLS_PRIVATE(key_id) = key_id, + .MBEDTLS_PRIVATE(owner) = owner_id }; } /** Compare two key identifiers. @@ -2184,8 +2504,8 @@ static inline mbedtls_svc_key_id_t mbedtls_svc_key_id_make( static inline int mbedtls_svc_key_id_equal(mbedtls_svc_key_id_t id1, mbedtls_svc_key_id_t id2) { - return (id1.key_id == id2.key_id) && - mbedtls_key_owner_id_equal(id1.owner, id2.owner); + return (id1.MBEDTLS_PRIVATE(key_id) == id2.MBEDTLS_PRIVATE(key_id)) && + mbedtls_key_owner_id_equal(id1.MBEDTLS_PRIVATE(owner), id2.MBEDTLS_PRIVATE(owner)); } /** Check whether a key identifier is null. @@ -2196,7 +2516,7 @@ static inline int mbedtls_svc_key_id_equal(mbedtls_svc_key_id_t id1, */ static inline int mbedtls_svc_key_id_is_null(mbedtls_svc_key_id_t key) { - return key.key_id == 0; + return key.MBEDTLS_PRIVATE(key_id) == 0; } #endif /* !MBEDTLS_PSA_CRYPTO_KEY_ID_ENCODES_OWNER */ @@ -2297,16 +2617,41 @@ static inline int mbedtls_svc_key_id_is_null(mbedtls_svc_key_id_t key) * * This flag allows the key to be used for a MAC verification operation * or for an asymmetric signature verification operation, - * if otherwise permitted by by the key's type and policy. + * if otherwise permitted by the key's type and policy. * * For a key pair, this concerns the public key. */ #define PSA_KEY_USAGE_VERIFY_HASH ((psa_key_usage_t) 0x00002000) -/** Whether the key may be used to derive other keys. +/** Whether the key may be used to derive other keys or produce a password + * hash. + * + * This flag allows the key to be used for a key derivation operation or for + * a key agreement operation, if otherwise permitted by the key's type and + * policy. + * + * If this flag is present on all keys used in calls to + * psa_key_derivation_input_key() for a key derivation operation, then it + * permits calling psa_key_derivation_output_bytes() or + * psa_key_derivation_output_key() at the end of the operation. */ #define PSA_KEY_USAGE_DERIVE ((psa_key_usage_t) 0x00004000) +/** Whether the key may be used to verify the result of a key derivation, + * including password hashing. + * + * This flag allows the key to be used: + * + * This flag allows the key to be used in a key derivation operation, if + * otherwise permitted by the key's type and policy. + * + * If this flag is present on all keys used in calls to + * psa_key_derivation_input_key() for a key derivation operation, then it + * permits calling psa_key_derivation_verify_bytes() or + * psa_key_derivation_verify_key() at the end of the operation. + */ +#define PSA_KEY_USAGE_VERIFY_DERIVATION ((psa_key_usage_t) 0x00008000) + /**@}*/ /** \defgroup derivation Key derivation @@ -2326,10 +2671,41 @@ static inline int mbedtls_svc_key_id_is_null(mbedtls_svc_key_id_t key) * The secret can also be a direct input (passed to * key_derivation_input_bytes()). In this case, the derivation operation * may not be used to derive keys: the operation will only allow - * psa_key_derivation_output_bytes(), not psa_key_derivation_output_key(). + * psa_key_derivation_output_bytes(), + * psa_key_derivation_verify_bytes(), or + * psa_key_derivation_verify_key(), but not + * psa_key_derivation_output_key(). */ #define PSA_KEY_DERIVATION_INPUT_SECRET ((psa_key_derivation_step_t) 0x0101) +/** A low-entropy secret input for password hashing / key stretching. + * + * This is usually a key of type #PSA_KEY_TYPE_PASSWORD (passed to + * psa_key_derivation_input_key()) or a direct input (passed to + * psa_key_derivation_input_bytes()) that is a password or passphrase. It can + * also be high-entropy secret such as a key of type #PSA_KEY_TYPE_DERIVE or + * the shared secret resulting from a key agreement. + * + * The secret can also be a direct input (passed to + * key_derivation_input_bytes()). In this case, the derivation operation + * may not be used to derive keys: the operation will only allow + * psa_key_derivation_output_bytes(), + * psa_key_derivation_verify_bytes(), or + * psa_key_derivation_verify_key(), but not + * psa_key_derivation_output_key(). + */ +#define PSA_KEY_DERIVATION_INPUT_PASSWORD ((psa_key_derivation_step_t) 0x0102) + +/** A high-entropy additional secret input for key derivation. + * + * This is typically the shared secret resulting from a key agreement obtained + * via `psa_key_derivation_key_agreement()`. It may alternatively be a key of + * type `PSA_KEY_TYPE_DERIVE` passed to `psa_key_derivation_input_key()`, or + * a direct input passed to `psa_key_derivation_input_bytes()`. + */ +#define PSA_KEY_DERIVATION_INPUT_OTHER_SECRET \ + ((psa_key_derivation_step_t) 0x0103) + /** A label for key derivation. * * This should be a direct input. @@ -2340,7 +2716,8 @@ static inline int mbedtls_svc_key_id_is_null(mbedtls_svc_key_id_t key) /** A salt for key derivation. * * This should be a direct input. - * It can also be a key of type #PSA_KEY_TYPE_RAW_DATA. + * It can also be a key of type #PSA_KEY_TYPE_RAW_DATA or + * #PSA_KEY_TYPE_PEPPER. */ #define PSA_KEY_DERIVATION_INPUT_SALT ((psa_key_derivation_step_t) 0x0202) @@ -2358,6 +2735,12 @@ static inline int mbedtls_svc_key_id_is_null(mbedtls_svc_key_id_t key) */ #define PSA_KEY_DERIVATION_INPUT_SEED ((psa_key_derivation_step_t) 0x0204) +/** A cost parameter for password hashing / key stretching. + * + * This must be a direct input, passed to psa_key_derivation_input_integer(). + */ +#define PSA_KEY_DERIVATION_INPUT_COST ((psa_key_derivation_step_t) 0x0205) + /**@}*/ /** \defgroup helper_macros Helper macros @@ -2383,4 +2766,18 @@ static inline int mbedtls_svc_key_id_is_null(mbedtls_svc_key_id_t key) /**@}*/ +/**@}*/ + +/** \defgroup interruptible Interruptible operations + * @{ + */ + +/** Maximum value for use with \c psa_interruptible_set_max_ops() to determine + * the maximum number of ops allowed to be executed by an interruptible + * function in a single call. + */ +#define PSA_INTERRUPTIBLE_MAX_OPS_UNLIMITED UINT32_MAX + +/**@}*/ + #endif /* PSA_CRYPTO_VALUES_H */ diff --git a/vendor/mbedtls/library/aes.c b/vendor/mbedtls/library/aes.c index d2a3c8958e..b1a5c3ed10 100644 --- a/vendor/mbedtls/library/aes.c +++ b/vendor/mbedtls/library/aes.c @@ -2,19 +2,7 @@ * FIPS-197 compliant AES implementation * * Copyright The Mbed TLS Contributors - * SPDX-License-Identifier: Apache-2.0 - * - * Licensed under the Apache License, Version 2.0 (the "License"); you may - * not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT - * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. + * SPDX-License-Identifier: Apache-2.0 OR GPL-2.0-or-later */ /* * The AES block cipher was designed by Vincent Rijmen and Joan Daemen. @@ -33,22 +21,51 @@ #include "mbedtls/platform.h" #include "mbedtls/platform_util.h" #include "mbedtls/error.h" + +#if defined(MBEDTLS_AES_USE_HARDWARE_ONLY) +#if !((defined(MBEDTLS_ARCH_IS_ARMV8_A) && defined(MBEDTLS_AESCE_C)) || \ + (defined(MBEDTLS_ARCH_IS_X64) && defined(MBEDTLS_AESNI_C)) || \ + (defined(MBEDTLS_ARCH_IS_X86) && defined(MBEDTLS_AESNI_C))) +#error "MBEDTLS_AES_USE_HARDWARE_ONLY defined, but not all prerequisites" +#endif +#endif + +#if defined(MBEDTLS_ARCH_IS_X86) +#if defined(MBEDTLS_PADLOCK_C) +#if !defined(MBEDTLS_HAVE_ASM) +#error "MBEDTLS_PADLOCK_C defined, but not all prerequisites" +#endif +#if defined(MBEDTLS_AES_USE_HARDWARE_ONLY) +#error "MBEDTLS_AES_USE_HARDWARE_ONLY cannot be defined when " \ + "MBEDTLS_PADLOCK_C is set" +#endif +#endif +#endif + #if defined(MBEDTLS_PADLOCK_C) -#include "mbedtls/padlock.h" +#include "padlock.h" #endif #if defined(MBEDTLS_AESNI_C) -#include "mbedtls/aesni.h" +#include "aesni.h" +#endif +#if defined(MBEDTLS_AESCE_C) +#include "aesce.h" #endif #include "mbedtls/platform.h" +#include "ctr.h" -#if !defined(MBEDTLS_AES_ALT) +/* + * This is a convenience shorthand macro to check if we need reverse S-box and + * reverse tables. It's private and only defined in this file. + */ +#if (!defined(MBEDTLS_AES_DECRYPT_ALT) || \ + (!defined(MBEDTLS_AES_SETKEY_DEC_ALT) && !defined(MBEDTLS_AES_USE_HARDWARE_ONLY))) && \ + !defined(MBEDTLS_BLOCK_CIPHER_NO_DECRYPT) +#define MBEDTLS_AES_NEED_REVERSE_TABLES +#endif -/* Parameter validation macros based on platform_util.h */ -#define AES_VALIDATE_RET(cond) \ - MBEDTLS_INTERNAL_VALIDATE_RET(cond, MBEDTLS_ERR_AES_BAD_INPUT_DATA) -#define AES_VALIDATE(cond) \ - MBEDTLS_INTERNAL_VALIDATE(cond) +#if !defined(MBEDTLS_AES_ALT) #if defined(MBEDTLS_VIA_PADLOCK_HAVE_CODE) static int aes_padlock_ace = -1; @@ -58,9 +75,7 @@ static int aes_padlock_ace = -1; /* * Forward S-box */ -#if !defined(MBEDTLS_AES_ENCRYPT_ALT) || !defined(MBEDTLS_AES_SETKEY_ENC_ALT) || \ - !defined(MBEDTLS_AES_SETKEY_DEC_ALT) -static const unsigned char FSb[256] = +MBEDTLS_MAYBE_UNUSED static const unsigned char FSb[256] = { 0x63, 0x7C, 0x77, 0x7B, 0xF2, 0x6B, 0x6F, 0xC5, 0x30, 0x01, 0x67, 0x2B, 0xFE, 0xD7, 0xAB, 0x76, @@ -95,8 +110,6 @@ static const unsigned char FSb[256] = 0x8C, 0xA1, 0x89, 0x0D, 0xBF, 0xE6, 0x42, 0x68, 0x41, 0x99, 0x2D, 0x0F, 0xB0, 0x54, 0xBB, 0x16 }; -#endif /* !defined(MBEDTLS_AES_ENCRYPT_ALT) || !defined(MBEDTLS_AES_SETKEY_ENC_ALT) || \ - !defined(MBEDTLS_AES_SETKEY_DEC_ALT) */ /* * Forward tables @@ -168,36 +181,28 @@ static const unsigned char FSb[256] = V(C3, 41, 41, 82), V(B0, 99, 99, 29), V(77, 2D, 2D, 5A), V(11, 0F, 0F, 1E), \ V(CB, B0, B0, 7B), V(FC, 54, 54, A8), V(D6, BB, BB, 6D), V(3A, 16, 16, 2C) -#if !defined(MBEDTLS_AES_ENCRYPT_ALT) #define V(a, b, c, d) 0x##a##b##c##d -static const uint32_t FT0[256] = { FT }; +MBEDTLS_MAYBE_UNUSED static const uint32_t FT0[256] = { FT }; #undef V -#if !defined(MBEDTLS_AES_FEWER_TABLES) - #define V(a, b, c, d) 0x##b##c##d##a -static const uint32_t FT1[256] = { FT }; +MBEDTLS_MAYBE_UNUSED static const uint32_t FT1[256] = { FT }; #undef V #define V(a, b, c, d) 0x##c##d##a##b -static const uint32_t FT2[256] = { FT }; +MBEDTLS_MAYBE_UNUSED static const uint32_t FT2[256] = { FT }; #undef V #define V(a, b, c, d) 0x##d##a##b##c -static const uint32_t FT3[256] = { FT }; +MBEDTLS_MAYBE_UNUSED static const uint32_t FT3[256] = { FT }; #undef V -#endif /* !MBEDTLS_AES_FEWER_TABLES */ - -#endif /* !defined(MBEDTLS_AES_ENCRYPT_ALT) */ - #undef FT -#if !defined(MBEDTLS_AES_DECRYPT_ALT) /* * Reverse S-box */ -static const unsigned char RSb[256] = +MBEDTLS_MAYBE_UNUSED static const unsigned char RSb[256] = { 0x52, 0x09, 0x6A, 0xD5, 0x30, 0x36, 0xA5, 0x38, 0xBF, 0x40, 0xA3, 0x9E, 0x81, 0xF3, 0xD7, 0xFB, @@ -232,7 +237,6 @@ static const unsigned char RSb[256] = 0x17, 0x2B, 0x04, 0x7E, 0xBA, 0x77, 0xD6, 0x26, 0xE1, 0x69, 0x14, 0x63, 0x55, 0x21, 0x0C, 0x7D }; -#endif /* defined(MBEDTLS_AES_DECRYPT_ALT)) */ /* * Reverse tables @@ -304,84 +308,60 @@ static const unsigned char RSb[256] = V(71, 01, A8, 39), V(DE, B3, 0C, 08), V(9C, E4, B4, D8), V(90, C1, 56, 64), \ V(61, 84, CB, 7B), V(70, B6, 32, D5), V(74, 5C, 6C, 48), V(42, 57, B8, D0) -#if !defined(MBEDTLS_AES_DECRYPT_ALT) || !defined(MBEDTLS_AES_SETKEY_DEC_ALT) #define V(a, b, c, d) 0x##a##b##c##d -static const uint32_t RT0[256] = { RT }; +MBEDTLS_MAYBE_UNUSED static const uint32_t RT0[256] = { RT }; #undef V -#if !defined(MBEDTLS_AES_FEWER_TABLES) - #define V(a, b, c, d) 0x##b##c##d##a -static const uint32_t RT1[256] = { RT }; +MBEDTLS_MAYBE_UNUSED static const uint32_t RT1[256] = { RT }; #undef V #define V(a, b, c, d) 0x##c##d##a##b -static const uint32_t RT2[256] = { RT }; +MBEDTLS_MAYBE_UNUSED static const uint32_t RT2[256] = { RT }; #undef V #define V(a, b, c, d) 0x##d##a##b##c -static const uint32_t RT3[256] = { RT }; +MBEDTLS_MAYBE_UNUSED static const uint32_t RT3[256] = { RT }; #undef V -#endif /* !MBEDTLS_AES_FEWER_TABLES */ - -#endif /* !defined(MBEDTLS_AES_DECRYPT_ALT) || !defined(MBEDTLS_AES_SETKEY_DEC_ALT) */ - #undef RT -#if !defined(MBEDTLS_AES_SETKEY_ENC_ALT) /* * Round constants */ -static const uint32_t RCON[10] = +MBEDTLS_MAYBE_UNUSED static const uint32_t round_constants[10] = { 0x00000001, 0x00000002, 0x00000004, 0x00000008, 0x00000010, 0x00000020, 0x00000040, 0x00000080, 0x0000001B, 0x00000036 }; -#endif /* !defined(MBEDTLS_AES_SETKEY_ENC_ALT) */ #else /* MBEDTLS_AES_ROM_TABLES */ /* * Forward S-box & tables */ -#if !defined(MBEDTLS_AES_ENCRYPT_ALT) || !defined(MBEDTLS_AES_SETKEY_ENC_ALT) || \ - !defined(MBEDTLS_AES_SETKEY_DEC_ALT) -static unsigned char FSb[256]; -#endif /* !defined(MBEDTLS_AES_ENCRYPT_ALT) || !defined(MBEDTLS_AES_SETKEY_ENC_ALT) || \ - !defined(MBEDTLS_AES_SETKEY_DEC_ALT) */ -#if !defined(MBEDTLS_AES_ENCRYPT_ALT) || !defined(MBEDTLS_AES_SETKEY_ENC_ALT) -static uint32_t FT0[256]; -#if !defined(MBEDTLS_AES_FEWER_TABLES) -static uint32_t FT1[256]; -static uint32_t FT2[256]; -static uint32_t FT3[256]; -#endif /* !MBEDTLS_AES_FEWER_TABLES */ -#endif /* !defined(MBEDTLS_AES_ENCRYPT_ALT) || !defined(MBEDTLS_AES_SETKEY_ENC_ALT) */ +MBEDTLS_MAYBE_UNUSED static unsigned char FSb[256]; +MBEDTLS_MAYBE_UNUSED static uint32_t FT0[256]; +MBEDTLS_MAYBE_UNUSED static uint32_t FT1[256]; +MBEDTLS_MAYBE_UNUSED static uint32_t FT2[256]; +MBEDTLS_MAYBE_UNUSED static uint32_t FT3[256]; /* * Reverse S-box & tables */ -#if !(defined(MBEDTLS_AES_SETKEY_ENC_ALT) && defined(MBEDTLS_AES_DECRYPT_ALT)) -static unsigned char RSb[256]; -#endif /* !(defined(MBEDTLS_AES_SETKEY_ENC_ALT) && defined(MBEDTLS_AES_DECRYPT_ALT)) */ +MBEDTLS_MAYBE_UNUSED static unsigned char RSb[256]; -#if !defined(MBEDTLS_AES_DECRYPT_ALT) || !defined(MBEDTLS_AES_SETKEY_DEC_ALT) -static uint32_t RT0[256]; -#if !defined(MBEDTLS_AES_FEWER_TABLES) -static uint32_t RT1[256]; -static uint32_t RT2[256]; -static uint32_t RT3[256]; -#endif /* !MBEDTLS_AES_FEWER_TABLES */ -#endif /* !defined(MBEDTLS_AES_DECRYPT_ALT) || !defined(MBEDTLS_AES_SETKEY_DEC_ALT) */ +MBEDTLS_MAYBE_UNUSED static uint32_t RT0[256]; +MBEDTLS_MAYBE_UNUSED static uint32_t RT1[256]; +MBEDTLS_MAYBE_UNUSED static uint32_t RT2[256]; +MBEDTLS_MAYBE_UNUSED static uint32_t RT3[256]; -#if !defined(MBEDTLS_AES_SETKEY_ENC_ALT) /* * Round constants */ -static uint32_t RCON[10]; +MBEDTLS_MAYBE_UNUSED static uint32_t round_constants[10]; /* * Tables generation code @@ -390,48 +370,53 @@ static uint32_t RCON[10]; #define XTIME(x) (((x) << 1) ^ (((x) & 0x80) ? 0x1B : 0x00)) #define MUL(x, y) (((x) && (y)) ? pow[(log[(x)]+log[(y)]) % 255] : 0) -static int aes_init_done = 0; +MBEDTLS_MAYBE_UNUSED static int aes_init_done = 0; -static void aes_gen_tables(void) +MBEDTLS_MAYBE_UNUSED static void aes_gen_tables(void) { - int i, x, y, z; - int pow[256]; - int log[256]; + int i; + uint8_t x, y, z; + uint8_t pow[256]; + uint8_t log[256]; /* * compute pow and log tables over GF(2^8) */ for (i = 0, x = 1; i < 256; i++) { pow[i] = x; - log[x] = i; - x = MBEDTLS_BYTE_0(x ^ XTIME(x)); + log[x] = (uint8_t) i; + x ^= XTIME(x); } /* * calculate the round constants */ for (i = 0, x = 1; i < 10; i++) { - RCON[i] = (uint32_t) x; - x = MBEDTLS_BYTE_0(XTIME(x)); + round_constants[i] = x; + x = XTIME(x); } /* * generate the forward and reverse S-boxes */ FSb[0x00] = 0x63; +#if defined(MBEDTLS_AES_NEED_REVERSE_TABLES) RSb[0x63] = 0x00; +#endif for (i = 1; i < 256; i++) { x = pow[255 - log[i]]; - y = x; y = MBEDTLS_BYTE_0((y << 1) | (y >> 7)); - x ^= y; y = MBEDTLS_BYTE_0((y << 1) | (y >> 7)); - x ^= y; y = MBEDTLS_BYTE_0((y << 1) | (y >> 7)); - x ^= y; y = MBEDTLS_BYTE_0((y << 1) | (y >> 7)); + y = x; y = (y << 1) | (y >> 7); + x ^= y; y = (y << 1) | (y >> 7); + x ^= y; y = (y << 1) | (y >> 7); + x ^= y; y = (y << 1) | (y >> 7); x ^= y ^ 0x63; - FSb[i] = (unsigned char) x; + FSb[i] = x; +#if defined(MBEDTLS_AES_NEED_REVERSE_TABLES) RSb[x] = (unsigned char) i; +#endif } /* @@ -439,8 +424,8 @@ static void aes_gen_tables(void) */ for (i = 0; i < 256; i++) { x = FSb[i]; - y = MBEDTLS_BYTE_0(XTIME(x)); - z = MBEDTLS_BYTE_0(y ^ x); + y = XTIME(x); + z = y ^ x; FT0[i] = ((uint32_t) y) ^ ((uint32_t) x << 8) ^ @@ -453,9 +438,9 @@ static void aes_gen_tables(void) FT3[i] = ROTL8(FT2[i]); #endif /* !MBEDTLS_AES_FEWER_TABLES */ +#if defined(MBEDTLS_AES_NEED_REVERSE_TABLES) x = RSb[i]; -#if !defined(MBEDTLS_AES_DECRYPT_ALT) || !defined(MBEDTLS_AES_SETKEY_DEC_ALT) RT0[i] = ((uint32_t) MUL(0x0E, x)) ^ ((uint32_t) MUL(0x09, x) << 8) ^ ((uint32_t) MUL(0x0D, x) << 16) ^ @@ -466,12 +451,10 @@ static void aes_gen_tables(void) RT2[i] = ROTL8(RT1[i]); RT3[i] = ROTL8(RT2[i]); #endif /* !MBEDTLS_AES_FEWER_TABLES */ -#endif /* !defined(MBEDTLS_AES_DECRYPT_ALT) || !defined(MBEDTLS_AES_SETKEY_DEC_ALT) */ +#endif /* MBEDTLS_AES_NEED_REVERSE_TABLES */ } } -#endif /* !defined(MBEDTLS_AES_SETKEY_ENC_ALT) */ - #undef ROTL8 #endif /* MBEDTLS_AES_ROM_TABLES */ @@ -508,8 +491,6 @@ static void aes_gen_tables(void) void mbedtls_aes_init(mbedtls_aes_context *ctx) { - AES_VALIDATE(ctx != NULL); - memset(ctx, 0, sizeof(mbedtls_aes_context)); } @@ -525,8 +506,6 @@ void mbedtls_aes_free(mbedtls_aes_context *ctx) #if defined(MBEDTLS_CIPHER_MODE_XTS) void mbedtls_aes_xts_init(mbedtls_aes_xts_context *ctx) { - AES_VALIDATE(ctx != NULL); - mbedtls_aes_init(&ctx->crypt); mbedtls_aes_init(&ctx->tweak); } @@ -548,14 +527,12 @@ void mbedtls_aes_xts_free(mbedtls_aes_xts_context *ctx) * Note that the offset is in units of elements of buf, i.e. 32-bit words, * i.e. an offset of 1 means 4 bytes and so on. */ -#if defined(MBEDTLS_VIA_PADLOCK_HAVE_CODE) || \ +#if (defined(MBEDTLS_VIA_PADLOCK_HAVE_CODE)) || \ (defined(MBEDTLS_AESNI_C) && MBEDTLS_AESNI_HAVE_CODE == 2) #define MAY_NEED_TO_ALIGN #endif -#if defined(MAY_NEED_TO_ALIGN) || !defined(MBEDTLS_AES_SETKEY_DEC_ALT) || \ - !defined(MBEDTLS_AES_SETKEY_ENC_ALT) -static unsigned mbedtls_aes_rk_offset(uint32_t *buf) +MBEDTLS_MAYBE_UNUSED static unsigned mbedtls_aes_rk_offset(uint32_t *buf) { #if defined(MAY_NEED_TO_ALIGN) int align_16_bytes = 0; @@ -591,8 +568,6 @@ static unsigned mbedtls_aes_rk_offset(uint32_t *buf) return 0; } -#endif /* defined(MAY_NEED_TO_ALIGN) || !defined(MBEDTLS_AES_SETKEY_DEC_ALT) || \ - !defined(MBEDTLS_AES_SETKEY_ENC_ALT) */ /* * AES key schedule (encryption) @@ -601,16 +576,14 @@ static unsigned mbedtls_aes_rk_offset(uint32_t *buf) int mbedtls_aes_setkey_enc(mbedtls_aes_context *ctx, const unsigned char *key, unsigned int keybits) { - unsigned int i; uint32_t *RK; - AES_VALIDATE_RET(ctx != NULL); - AES_VALIDATE_RET(key != NULL); - switch (keybits) { case 128: ctx->nr = 10; break; +#if !defined(MBEDTLS_AES_ONLY_128_BIT_KEY_LENGTH) case 192: ctx->nr = 12; break; case 256: ctx->nr = 14; break; +#endif /* !MBEDTLS_AES_ONLY_128_BIT_KEY_LENGTH */ default: return MBEDTLS_ERR_AES_INVALID_KEY_LENGTH; } @@ -621,23 +594,31 @@ int mbedtls_aes_setkey_enc(mbedtls_aes_context *ctx, const unsigned char *key, } #endif - ctx->rk = RK = ctx->buf + mbedtls_aes_rk_offset(ctx->buf); + ctx->rk_offset = mbedtls_aes_rk_offset(ctx->buf); + RK = ctx->buf + ctx->rk_offset; #if defined(MBEDTLS_AESNI_HAVE_CODE) if (mbedtls_aesni_has_support(MBEDTLS_AESNI_AES)) { - return mbedtls_aesni_setkey_enc((unsigned char *) ctx->rk, key, keybits); + return mbedtls_aesni_setkey_enc((unsigned char *) RK, key, keybits); + } +#endif + +#if defined(MBEDTLS_AESCE_HAVE_CODE) + if (MBEDTLS_AESCE_HAS_SUPPORT()) { + return mbedtls_aesce_setkey_enc((unsigned char *) RK, key, keybits); } #endif - for (i = 0; i < (keybits >> 5); i++) { +#if !defined(MBEDTLS_AES_USE_HARDWARE_ONLY) + for (unsigned int i = 0; i < (keybits >> 5); i++) { RK[i] = MBEDTLS_GET_UINT32_LE(key, i << 2); } switch (ctx->nr) { case 10: - for (i = 0; i < 10; i++, RK += 4) { - RK[4] = RK[0] ^ RCON[i] ^ + for (unsigned int i = 0; i < 10; i++, RK += 4) { + RK[4] = RK[0] ^ round_constants[i] ^ ((uint32_t) FSb[MBEDTLS_BYTE_1(RK[3])]) ^ ((uint32_t) FSb[MBEDTLS_BYTE_2(RK[3])] << 8) ^ ((uint32_t) FSb[MBEDTLS_BYTE_3(RK[3])] << 16) ^ @@ -649,10 +630,11 @@ int mbedtls_aes_setkey_enc(mbedtls_aes_context *ctx, const unsigned char *key, } break; +#if !defined(MBEDTLS_AES_ONLY_128_BIT_KEY_LENGTH) case 12: - for (i = 0; i < 8; i++, RK += 6) { - RK[6] = RK[0] ^ RCON[i] ^ + for (unsigned int i = 0; i < 8; i++, RK += 6) { + RK[6] = RK[0] ^ round_constants[i] ^ ((uint32_t) FSb[MBEDTLS_BYTE_1(RK[5])]) ^ ((uint32_t) FSb[MBEDTLS_BYTE_2(RK[5])] << 8) ^ ((uint32_t) FSb[MBEDTLS_BYTE_3(RK[5])] << 16) ^ @@ -668,8 +650,8 @@ int mbedtls_aes_setkey_enc(mbedtls_aes_context *ctx, const unsigned char *key, case 14: - for (i = 0; i < 7; i++, RK += 8) { - RK[8] = RK[0] ^ RCON[i] ^ + for (unsigned int i = 0; i < 7; i++, RK += 8) { + RK[8] = RK[0] ^ round_constants[i] ^ ((uint32_t) FSb[MBEDTLS_BYTE_1(RK[7])]) ^ ((uint32_t) FSb[MBEDTLS_BYTE_2(RK[7])] << 8) ^ ((uint32_t) FSb[MBEDTLS_BYTE_3(RK[7])] << 16) ^ @@ -690,30 +672,33 @@ int mbedtls_aes_setkey_enc(mbedtls_aes_context *ctx, const unsigned char *key, RK[15] = RK[7] ^ RK[14]; } break; +#endif /* !MBEDTLS_AES_ONLY_128_BIT_KEY_LENGTH */ } return 0; +#endif /* !MBEDTLS_AES_USE_HARDWARE_ONLY */ } #endif /* !MBEDTLS_AES_SETKEY_ENC_ALT */ /* * AES key schedule (decryption) */ -#if !defined(MBEDTLS_AES_SETKEY_DEC_ALT) +#if !defined(MBEDTLS_AES_SETKEY_DEC_ALT) && !defined(MBEDTLS_BLOCK_CIPHER_NO_DECRYPT) int mbedtls_aes_setkey_dec(mbedtls_aes_context *ctx, const unsigned char *key, unsigned int keybits) { - int i, j, ret; +#if !defined(MBEDTLS_AES_USE_HARDWARE_ONLY) + uint32_t *SK; +#endif + int ret; mbedtls_aes_context cty; uint32_t *RK; - uint32_t *SK; - AES_VALIDATE_RET(ctx != NULL); - AES_VALIDATE_RET(key != NULL); mbedtls_aes_init(&cty); - ctx->rk = RK = ctx->buf + mbedtls_aes_rk_offset(ctx->buf); + ctx->rk_offset = mbedtls_aes_rk_offset(ctx->buf); + RK = ctx->buf + ctx->rk_offset; /* Also checks keybits */ if ((ret = mbedtls_aes_setkey_enc(&cty, key, keybits)) != 0) { @@ -724,21 +709,32 @@ int mbedtls_aes_setkey_dec(mbedtls_aes_context *ctx, const unsigned char *key, #if defined(MBEDTLS_AESNI_HAVE_CODE) if (mbedtls_aesni_has_support(MBEDTLS_AESNI_AES)) { - mbedtls_aesni_inverse_key((unsigned char *) ctx->rk, - (const unsigned char *) cty.rk, ctx->nr); + mbedtls_aesni_inverse_key((unsigned char *) RK, + (const unsigned char *) (cty.buf + cty.rk_offset), ctx->nr); goto exit; } #endif - SK = cty.rk + cty.nr * 4; +#if defined(MBEDTLS_AESCE_HAVE_CODE) + if (MBEDTLS_AESCE_HAS_SUPPORT()) { + mbedtls_aesce_inverse_key( + (unsigned char *) RK, + (const unsigned char *) (cty.buf + cty.rk_offset), + ctx->nr); + goto exit; + } +#endif + +#if !defined(MBEDTLS_AES_USE_HARDWARE_ONLY) + SK = cty.buf + cty.rk_offset + cty.nr * 4; *RK++ = *SK++; *RK++ = *SK++; *RK++ = *SK++; *RK++ = *SK++; - - for (i = ctx->nr - 1, SK -= 8; i > 0; i--, SK -= 8) { - for (j = 0; j < 4; j++, SK++) { + SK -= 8; + for (int i = ctx->nr - 1; i > 0; i--, SK -= 8) { + for (int j = 0; j < 4; j++, SK++) { *RK++ = AES_RT0(FSb[MBEDTLS_BYTE_0(*SK)]) ^ AES_RT1(FSb[MBEDTLS_BYTE_1(*SK)]) ^ AES_RT2(FSb[MBEDTLS_BYTE_2(*SK)]) ^ @@ -750,13 +746,13 @@ int mbedtls_aes_setkey_dec(mbedtls_aes_context *ctx, const unsigned char *key, *RK++ = *SK++; *RK++ = *SK++; *RK++ = *SK++; - +#endif /* !MBEDTLS_AES_USE_HARDWARE_ONLY */ exit: mbedtls_aes_free(&cty); return ret; } -#endif /* !MBEDTLS_AES_SETKEY_DEC_ALT */ +#endif /* !MBEDTLS_AES_SETKEY_DEC_ALT && !MBEDTLS_BLOCK_CIPHER_NO_DECRYPT */ #if defined(MBEDTLS_CIPHER_MODE_XTS) static int mbedtls_aes_xts_decode_keys(const unsigned char *key, @@ -791,9 +787,6 @@ int mbedtls_aes_xts_setkey_enc(mbedtls_aes_xts_context *ctx, const unsigned char *key1, *key2; unsigned int key1bits, key2bits; - AES_VALIDATE_RET(ctx != NULL); - AES_VALIDATE_RET(key != NULL); - ret = mbedtls_aes_xts_decode_keys(key, keybits, &key1, &key1bits, &key2, &key2bits); if (ret != 0) { @@ -818,9 +811,6 @@ int mbedtls_aes_xts_setkey_dec(mbedtls_aes_xts_context *ctx, const unsigned char *key1, *key2; unsigned int key1bits, key2bits; - AES_VALIDATE_RET(ctx != NULL); - AES_VALIDATE_RET(key != NULL); - ret = mbedtls_aes_xts_decode_keys(key, keybits, &key1, &key1bits, &key2, &key2bits); if (ret != 0) { @@ -895,7 +885,7 @@ int mbedtls_internal_aes_encrypt(mbedtls_aes_context *ctx, unsigned char output[16]) { int i; - uint32_t *RK = ctx->rk; + uint32_t *RK = ctx->buf + ctx->rk_offset; struct { uint32_t X[4]; uint32_t Y[4]; @@ -948,25 +938,16 @@ int mbedtls_internal_aes_encrypt(mbedtls_aes_context *ctx, } #endif /* !MBEDTLS_AES_ENCRYPT_ALT */ -#if !defined(MBEDTLS_DEPRECATED_REMOVED) -void mbedtls_aes_encrypt(mbedtls_aes_context *ctx, - const unsigned char input[16], - unsigned char output[16]) -{ - MBEDTLS_IGNORE_RETURN(mbedtls_internal_aes_encrypt(ctx, input, output)); -} -#endif /* !MBEDTLS_DEPRECATED_REMOVED */ - /* * AES-ECB block decryption */ -#if !defined(MBEDTLS_AES_DECRYPT_ALT) +#if !defined(MBEDTLS_AES_DECRYPT_ALT) && !defined(MBEDTLS_BLOCK_CIPHER_NO_DECRYPT) int mbedtls_internal_aes_decrypt(mbedtls_aes_context *ctx, const unsigned char input[16], unsigned char output[16]) { int i; - uint32_t *RK = ctx->rk; + uint32_t *RK = ctx->buf + ctx->rk_offset; struct { uint32_t X[4]; uint32_t Y[4]; @@ -1017,40 +998,25 @@ int mbedtls_internal_aes_decrypt(mbedtls_aes_context *ctx, return 0; } -#endif /* !MBEDTLS_AES_DECRYPT_ALT */ +#endif /* !MBEDTLS_AES_DECRYPT_ALT && !MBEDTLS_BLOCK_CIPHER_NO_DECRYPT */ -#if !defined(MBEDTLS_DEPRECATED_REMOVED) -void mbedtls_aes_decrypt(mbedtls_aes_context *ctx, - const unsigned char input[16], - unsigned char output[16]) -{ - MBEDTLS_IGNORE_RETURN(mbedtls_internal_aes_decrypt(ctx, input, output)); -} -#endif /* !MBEDTLS_DEPRECATED_REMOVED */ - -#if defined(MAY_NEED_TO_ALIGN) /* VIA Padlock and our intrinsics-based implementation of AESNI require * the round keys to be aligned on a 16-byte boundary. We take care of this * before creating them, but the AES context may have moved (this can happen * if the library is called from a language with managed memory), and in later * calls it might have a different alignment with respect to 16-byte memory. * So we may need to realign. - * NOTE: In the LTS branch, the context contains a pointer to within itself, - * so if it has been moved, things will probably go pear-shaped. We keep this - * code for compatibility with the development branch, in case of future changes. */ -static void aes_maybe_realign(mbedtls_aes_context *ctx) +MBEDTLS_MAYBE_UNUSED static void aes_maybe_realign(mbedtls_aes_context *ctx) { - unsigned current_offset = (unsigned) (ctx->rk - ctx->buf); unsigned new_offset = mbedtls_aes_rk_offset(ctx->buf); - if (new_offset != current_offset) { + if (new_offset != ctx->rk_offset) { memmove(ctx->buf + new_offset, // new address - ctx->buf + current_offset, // current address + ctx->buf + ctx->rk_offset, // current address (ctx->nr + 1) * 16); // number of round keys * bytes per rk - ctx->rk = ctx->buf + new_offset; + ctx->rk_offset = new_offset; } } -#endif /* * AES-ECB block encryption/decryption @@ -1060,11 +1026,9 @@ int mbedtls_aes_crypt_ecb(mbedtls_aes_context *ctx, const unsigned char input[16], unsigned char output[16]) { - AES_VALIDATE_RET(ctx != NULL); - AES_VALIDATE_RET(input != NULL); - AES_VALIDATE_RET(output != NULL); - AES_VALIDATE_RET(mode == MBEDTLS_AES_ENCRYPT || - mode == MBEDTLS_AES_DECRYPT); + if (mode != MBEDTLS_AES_ENCRYPT && mode != MBEDTLS_AES_DECRYPT) { + return MBEDTLS_ERR_AES_BAD_INPUT_DATA; + } #if defined(MAY_NEED_TO_ALIGN) aes_maybe_realign(ctx); @@ -1076,20 +1040,32 @@ int mbedtls_aes_crypt_ecb(mbedtls_aes_context *ctx, } #endif +#if defined(MBEDTLS_AESCE_HAVE_CODE) + if (MBEDTLS_AESCE_HAS_SUPPORT()) { + return mbedtls_aesce_crypt_ecb(ctx, mode, input, output); + } +#endif + #if defined(MBEDTLS_VIA_PADLOCK_HAVE_CODE) - if (aes_padlock_ace) { + if (aes_padlock_ace > 0) { return mbedtls_padlock_xcryptecb(ctx, mode, input, output); } #endif - if (mode == MBEDTLS_AES_ENCRYPT) { - return mbedtls_internal_aes_encrypt(ctx, input, output); - } else { +#if !defined(MBEDTLS_AES_USE_HARDWARE_ONLY) +#if !defined(MBEDTLS_BLOCK_CIPHER_NO_DECRYPT) + if (mode == MBEDTLS_AES_DECRYPT) { return mbedtls_internal_aes_decrypt(ctx, input, output); + } else +#endif + { + return mbedtls_internal_aes_encrypt(ctx, input, output); } +#endif /* !MBEDTLS_AES_USE_HARDWARE_ONLY */ } #if defined(MBEDTLS_CIPHER_MODE_CBC) + /* * AES-CBC buffer encryption/decryption */ @@ -1100,23 +1076,24 @@ int mbedtls_aes_crypt_cbc(mbedtls_aes_context *ctx, const unsigned char *input, unsigned char *output) { - int i; int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED; unsigned char temp[16]; - AES_VALIDATE_RET(ctx != NULL); - AES_VALIDATE_RET(mode == MBEDTLS_AES_ENCRYPT || - mode == MBEDTLS_AES_DECRYPT); - AES_VALIDATE_RET(iv != NULL); - AES_VALIDATE_RET(input != NULL); - AES_VALIDATE_RET(output != NULL); + if (mode != MBEDTLS_AES_ENCRYPT && mode != MBEDTLS_AES_DECRYPT) { + return MBEDTLS_ERR_AES_BAD_INPUT_DATA; + } + + /* Nothing to do if length is zero. */ + if (length == 0) { + return 0; + } if (length % 16) { return MBEDTLS_ERR_AES_INVALID_INPUT_LENGTH; } #if defined(MBEDTLS_VIA_PADLOCK_HAVE_CODE) - if (aes_padlock_ace) { + if (aes_padlock_ace > 0) { if (mbedtls_padlock_xcryptcbc(ctx, mode, length, iv, input, output) == 0) { return 0; } @@ -1127,6 +1104,8 @@ int mbedtls_aes_crypt_cbc(mbedtls_aes_context *ctx, } #endif + const unsigned char *ivp = iv; + if (mode == MBEDTLS_AES_DECRYPT) { while (length > 0) { memcpy(temp, input, 16); @@ -1134,10 +1113,10 @@ int mbedtls_aes_crypt_cbc(mbedtls_aes_context *ctx, if (ret != 0) { goto exit; } - - for (i = 0; i < 16; i++) { - output[i] = (unsigned char) (output[i] ^ iv[i]); - } + /* Avoid using the NEON implementation of mbedtls_xor. Because of the dependency on + * the result for the next block in CBC, and the cost of transferring that data from + * NEON registers, NEON is slower on aarch64. */ + mbedtls_xor_no_simd(output, output, iv, 16); memcpy(iv, temp, 16); @@ -1147,20 +1126,19 @@ int mbedtls_aes_crypt_cbc(mbedtls_aes_context *ctx, } } else { while (length > 0) { - for (i = 0; i < 16; i++) { - output[i] = (unsigned char) (input[i] ^ iv[i]); - } + mbedtls_xor_no_simd(output, input, ivp, 16); ret = mbedtls_aes_crypt_ecb(ctx, mode, output, output); if (ret != 0) { goto exit; } - memcpy(iv, output, 16); + ivp = output; input += 16; output += 16; length -= 16; } + memcpy(iv, ivp, 16); } ret = 0; @@ -1181,8 +1159,11 @@ typedef unsigned char mbedtls_be128[16]; * for machine endianness and hence works correctly on both big and little * endian machines. */ -static void mbedtls_gf128mul_x_ble(unsigned char r[16], - const unsigned char x[16]) +#if defined(MBEDTLS_AESCE_C) || defined(MBEDTLS_AESNI_C) +MBEDTLS_OPTIMIZE_FOR_PERFORMANCE +#endif +static inline void mbedtls_gf128mul_x_ble(unsigned char r[16], + const unsigned char x[16]) { uint64_t a, b, ra, rb; @@ -1198,7 +1179,13 @@ static void mbedtls_gf128mul_x_ble(unsigned char r[16], /* * AES-XTS buffer encryption/decryption + * + * Use of MBEDTLS_OPTIMIZE_FOR_PERFORMANCE here and for mbedtls_gf128mul_x_ble() + * is a 3x performance improvement for gcc -Os, if we have hardware AES support. */ +#if defined(MBEDTLS_AESCE_C) || defined(MBEDTLS_AESNI_C) +MBEDTLS_OPTIMIZE_FOR_PERFORMANCE +#endif int mbedtls_aes_crypt_xts(mbedtls_aes_xts_context *ctx, int mode, size_t length, @@ -1213,12 +1200,9 @@ int mbedtls_aes_crypt_xts(mbedtls_aes_xts_context *ctx, unsigned char prev_tweak[16]; unsigned char tmp[16]; - AES_VALIDATE_RET(ctx != NULL); - AES_VALIDATE_RET(mode == MBEDTLS_AES_ENCRYPT || - mode == MBEDTLS_AES_DECRYPT); - AES_VALIDATE_RET(data_unit != NULL); - AES_VALIDATE_RET(input != NULL); - AES_VALIDATE_RET(output != NULL); + if (mode != MBEDTLS_AES_ENCRYPT && mode != MBEDTLS_AES_DECRYPT) { + return MBEDTLS_ERR_AES_BAD_INPUT_DATA; + } /* Data units must be at least 16 bytes long. */ if (length < 16) { @@ -1238,9 +1222,7 @@ int mbedtls_aes_crypt_xts(mbedtls_aes_xts_context *ctx, } while (blocks--) { - size_t i; - - if (leftover && (mode == MBEDTLS_AES_DECRYPT) && blocks == 0) { + if (MBEDTLS_UNLIKELY(leftover && (mode == MBEDTLS_AES_DECRYPT) && blocks == 0)) { /* We are on the last block in a decrypt operation that has * leftover bytes, so we need to use the next tweak for this block, * and this tweak for the leftover bytes. Save the current tweak for @@ -1250,18 +1232,14 @@ int mbedtls_aes_crypt_xts(mbedtls_aes_xts_context *ctx, mbedtls_gf128mul_x_ble(tweak, tweak); } - for (i = 0; i < 16; i++) { - tmp[i] = input[i] ^ tweak[i]; - } + mbedtls_xor(tmp, input, tweak, 16); ret = mbedtls_aes_crypt_ecb(&ctx->crypt, mode, tmp, tmp); if (ret != 0) { return ret; } - for (i = 0; i < 16; i++) { - output[i] = tmp[i] ^ tweak[i]; - } + mbedtls_xor(output, tmp, tweak, 16); /* Update the tweak for the next block. */ mbedtls_gf128mul_x_ble(tweak, tweak); @@ -1281,19 +1259,17 @@ int mbedtls_aes_crypt_xts(mbedtls_aes_xts_context *ctx, unsigned char *prev_output = output - 16; /* Copy ciphertext bytes from the previous block to our output for each - * byte of ciphertext we won't steal. At the same time, copy the - * remainder of the input for this final round (since the loop bounds - * are the same). */ + * byte of ciphertext we won't steal. */ for (i = 0; i < leftover; i++) { output[i] = prev_output[i]; - tmp[i] = input[i] ^ t[i]; } + /* Copy the remainder of the input for this final round. */ + mbedtls_xor(tmp, input, t, leftover); + /* Copy ciphertext bytes from the previous block for input in this * round. */ - for (; i < 16; i++) { - tmp[i] = prev_output[i] ^ t[i]; - } + mbedtls_xor(tmp + i, prev_output + i, t + i, 16 - i); ret = mbedtls_aes_crypt_ecb(&ctx->crypt, mode, tmp, tmp); if (ret != 0) { @@ -1302,9 +1278,7 @@ int mbedtls_aes_crypt_xts(mbedtls_aes_xts_context *ctx, /* Write the result back to the previous block, overriding the previous * output we copied. */ - for (i = 0; i < 16; i++) { - prev_output[i] = tmp[i] ^ t[i]; - } + mbedtls_xor(prev_output, tmp, t, 16); } return 0; @@ -1327,13 +1301,9 @@ int mbedtls_aes_crypt_cfb128(mbedtls_aes_context *ctx, int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED; size_t n; - AES_VALIDATE_RET(ctx != NULL); - AES_VALIDATE_RET(mode == MBEDTLS_AES_ENCRYPT || - mode == MBEDTLS_AES_DECRYPT); - AES_VALIDATE_RET(iv_off != NULL); - AES_VALIDATE_RET(iv != NULL); - AES_VALIDATE_RET(input != NULL); - AES_VALIDATE_RET(output != NULL); + if (mode != MBEDTLS_AES_ENCRYPT && mode != MBEDTLS_AES_DECRYPT) { + return MBEDTLS_ERR_AES_BAD_INPUT_DATA; + } n = *iv_off; @@ -1392,12 +1362,9 @@ int mbedtls_aes_crypt_cfb8(mbedtls_aes_context *ctx, unsigned char c; unsigned char ov[17]; - AES_VALIDATE_RET(ctx != NULL); - AES_VALIDATE_RET(mode == MBEDTLS_AES_ENCRYPT || - mode == MBEDTLS_AES_DECRYPT); - AES_VALIDATE_RET(iv != NULL); - AES_VALIDATE_RET(input != NULL); - AES_VALIDATE_RET(output != NULL); + if (mode != MBEDTLS_AES_ENCRYPT && mode != MBEDTLS_AES_DECRYPT) { + return MBEDTLS_ERR_AES_BAD_INPUT_DATA; + } while (length--) { memcpy(ov, iv, 16); ret = mbedtls_aes_crypt_ecb(ctx, MBEDTLS_AES_ENCRYPT, iv, iv); @@ -1438,12 +1405,6 @@ int mbedtls_aes_crypt_ofb(mbedtls_aes_context *ctx, int ret = 0; size_t n; - AES_VALIDATE_RET(ctx != NULL); - AES_VALIDATE_RET(iv_off != NULL); - AES_VALIDATE_RET(iv != NULL); - AES_VALIDATE_RET(input != NULL); - AES_VALIDATE_RET(output != NULL); - n = *iv_off; if (n > 15) { @@ -1481,43 +1442,38 @@ int mbedtls_aes_crypt_ctr(mbedtls_aes_context *ctx, const unsigned char *input, unsigned char *output) { - int c, i; int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED; - size_t n; - - AES_VALIDATE_RET(ctx != NULL); - AES_VALIDATE_RET(nc_off != NULL); - AES_VALIDATE_RET(nonce_counter != NULL); - AES_VALIDATE_RET(stream_block != NULL); - AES_VALIDATE_RET(input != NULL); - AES_VALIDATE_RET(output != NULL); - n = *nc_off; + size_t offset = *nc_off; - if (n > 0x0F) { + if (offset > 0x0F) { return MBEDTLS_ERR_AES_BAD_INPUT_DATA; } - while (length--) { - if (n == 0) { + for (size_t i = 0; i < length;) { + size_t n = 16; + if (offset == 0) { ret = mbedtls_aes_crypt_ecb(ctx, MBEDTLS_AES_ENCRYPT, nonce_counter, stream_block); if (ret != 0) { goto exit; } - - for (i = 16; i > 0; i--) { - if (++nonce_counter[i - 1] != 0) { - break; - } - } + mbedtls_ctr_increment_counter(nonce_counter); + } else { + n -= offset; } - c = *input++; - *output++ = (unsigned char) (c ^ stream_block[n]); - n = (n + 1) & 0x0F; + if (n > (length - i)) { + n = (length - i); + } + mbedtls_xor(&output[i], &input[i], &stream_block[offset], n); + // offset might be non-zero for the last block, but in that case, we don't use it again + offset = 0; + i += n; } - *nc_off = n; + // capture offset for future resumption + *nc_off = (*nc_off + length) % 16; + ret = 0; exit: @@ -1533,45 +1489,55 @@ int mbedtls_aes_crypt_ctr(mbedtls_aes_context *ctx, * * http://csrc.nist.gov/archive/aes/rijndael/rijndael-vals.zip */ -static const unsigned char aes_test_ecb_dec[3][16] = +#if !defined(MBEDTLS_BLOCK_CIPHER_NO_DECRYPT) +static const unsigned char aes_test_ecb_dec[][16] = { { 0x44, 0x41, 0x6A, 0xC2, 0xD1, 0xF5, 0x3C, 0x58, 0x33, 0x03, 0x91, 0x7E, 0x6B, 0xE9, 0xEB, 0xE0 }, +#if !defined(MBEDTLS_AES_ONLY_128_BIT_KEY_LENGTH) { 0x48, 0xE3, 0x1E, 0x9E, 0x25, 0x67, 0x18, 0xF2, 0x92, 0x29, 0x31, 0x9C, 0x19, 0xF1, 0x5B, 0xA4 }, { 0x05, 0x8C, 0xCF, 0xFD, 0xBB, 0xCB, 0x38, 0x2D, 0x1F, 0x6F, 0x56, 0x58, 0x5D, 0x8A, 0x4A, 0xDE } +#endif }; +#endif -static const unsigned char aes_test_ecb_enc[3][16] = +static const unsigned char aes_test_ecb_enc[][16] = { { 0xC3, 0x4C, 0x05, 0x2C, 0xC0, 0xDA, 0x8D, 0x73, 0x45, 0x1A, 0xFE, 0x5F, 0x03, 0xBE, 0x29, 0x7F }, +#if !defined(MBEDTLS_AES_ONLY_128_BIT_KEY_LENGTH) { 0xF3, 0xF6, 0x75, 0x2A, 0xE8, 0xD7, 0x83, 0x11, 0x38, 0xF0, 0x41, 0x56, 0x06, 0x31, 0xB1, 0x14 }, { 0x8B, 0x79, 0xEE, 0xCC, 0x93, 0xA0, 0xEE, 0x5D, 0xFF, 0x30, 0xB4, 0xEA, 0x21, 0x63, 0x6D, 0xA4 } +#endif }; #if defined(MBEDTLS_CIPHER_MODE_CBC) -static const unsigned char aes_test_cbc_dec[3][16] = +static const unsigned char aes_test_cbc_dec[][16] = { { 0xFA, 0xCA, 0x37, 0xE0, 0xB0, 0xC8, 0x53, 0x73, 0xDF, 0x70, 0x6E, 0x73, 0xF7, 0xC9, 0xAF, 0x86 }, +#if !defined(MBEDTLS_AES_ONLY_128_BIT_KEY_LENGTH) { 0x5D, 0xF6, 0x78, 0xDD, 0x17, 0xBA, 0x4E, 0x75, 0xB6, 0x17, 0x68, 0xC6, 0xAD, 0xEF, 0x7C, 0x7B }, { 0x48, 0x04, 0xE1, 0x81, 0x8F, 0xE6, 0x29, 0x75, 0x19, 0xA3, 0xE8, 0x8C, 0x57, 0x31, 0x04, 0x13 } +#endif }; -static const unsigned char aes_test_cbc_enc[3][16] = +static const unsigned char aes_test_cbc_enc[][16] = { { 0x8A, 0x05, 0xFC, 0x5E, 0x09, 0x5A, 0xF4, 0x84, 0x8A, 0x08, 0xD3, 0x28, 0xD3, 0x68, 0x8E, 0x3D }, +#if !defined(MBEDTLS_AES_ONLY_128_BIT_KEY_LENGTH) { 0x7B, 0xD9, 0x66, 0xD5, 0x3A, 0xD8, 0xC1, 0xBB, 0x85, 0xD2, 0xAD, 0xFA, 0xE8, 0x7B, 0xB1, 0x04 }, { 0xFE, 0x3C, 0x53, 0x65, 0x3E, 0x2F, 0x45, 0xB5, 0x6F, 0xCD, 0x88, 0xB2, 0xCC, 0x89, 0x8F, 0xF0 } +#endif }; #endif /* MBEDTLS_CIPHER_MODE_CBC */ @@ -1581,10 +1547,11 @@ static const unsigned char aes_test_cbc_enc[3][16] = * * http://csrc.nist.gov/publications/nistpubs/800-38a/sp800-38a.pdf */ -static const unsigned char aes_test_cfb128_key[3][32] = +static const unsigned char aes_test_cfb128_key[][32] = { { 0x2B, 0x7E, 0x15, 0x16, 0x28, 0xAE, 0xD2, 0xA6, 0xAB, 0xF7, 0x15, 0x88, 0x09, 0xCF, 0x4F, 0x3C }, +#if !defined(MBEDTLS_AES_ONLY_128_BIT_KEY_LENGTH) { 0x8E, 0x73, 0xB0, 0xF7, 0xDA, 0x0E, 0x64, 0x52, 0xC8, 0x10, 0xF3, 0x2B, 0x80, 0x90, 0x79, 0xE5, 0x62, 0xF8, 0xEA, 0xD2, 0x52, 0x2C, 0x6B, 0x7B }, @@ -1592,6 +1559,7 @@ static const unsigned char aes_test_cfb128_key[3][32] = 0x2B, 0x73, 0xAE, 0xF0, 0x85, 0x7D, 0x77, 0x81, 0x1F, 0x35, 0x2C, 0x07, 0x3B, 0x61, 0x08, 0xD7, 0x2D, 0x98, 0x10, 0xA3, 0x09, 0x14, 0xDF, 0xF4 } +#endif }; static const unsigned char aes_test_cfb128_iv[16] = @@ -1612,7 +1580,7 @@ static const unsigned char aes_test_cfb128_pt[64] = 0xAD, 0x2B, 0x41, 0x7B, 0xE6, 0x6C, 0x37, 0x10 }; -static const unsigned char aes_test_cfb128_ct[3][64] = +static const unsigned char aes_test_cfb128_ct[][64] = { { 0x3B, 0x3F, 0xD9, 0x2E, 0xB7, 0x2D, 0xAD, 0x20, 0x33, 0x34, 0x49, 0xF8, 0xE8, 0x3C, 0xFB, 0x4A, @@ -1622,6 +1590,7 @@ static const unsigned char aes_test_cfb128_ct[3][64] = 0xB1, 0x80, 0x8C, 0xF1, 0x87, 0xA4, 0xF4, 0xDF, 0xC0, 0x4B, 0x05, 0x35, 0x7C, 0x5D, 0x1C, 0x0E, 0xEA, 0xC4, 0xC6, 0x6F, 0x9F, 0xF7, 0xF2, 0xE6 }, +#if !defined(MBEDTLS_AES_ONLY_128_BIT_KEY_LENGTH) { 0xCD, 0xC8, 0x0D, 0x6F, 0xDD, 0xF1, 0x8C, 0xAB, 0x34, 0xC2, 0x59, 0x09, 0xC9, 0x9A, 0x41, 0x74, 0x67, 0xCE, 0x7F, 0x7F, 0x81, 0x17, 0x36, 0x21, @@ -1638,6 +1607,7 @@ static const unsigned char aes_test_cfb128_ct[3][64] = 0xA1, 0x3E, 0xD0, 0xA8, 0x26, 0x7A, 0xE2, 0xF9, 0x75, 0xA3, 0x85, 0x74, 0x1A, 0xB9, 0xCE, 0xF8, 0x20, 0x31, 0x62, 0x3D, 0x55, 0xB1, 0xE4, 0x71 } +#endif }; #endif /* MBEDTLS_CIPHER_MODE_CFB */ @@ -1647,10 +1617,11 @@ static const unsigned char aes_test_cfb128_ct[3][64] = * * https://csrc.nist.gov/publications/detail/sp/800-38a/final */ -static const unsigned char aes_test_ofb_key[3][32] = +static const unsigned char aes_test_ofb_key[][32] = { { 0x2B, 0x7E, 0x15, 0x16, 0x28, 0xAE, 0xD2, 0xA6, 0xAB, 0xF7, 0x15, 0x88, 0x09, 0xCF, 0x4F, 0x3C }, +#if !defined(MBEDTLS_AES_ONLY_128_BIT_KEY_LENGTH) { 0x8E, 0x73, 0xB0, 0xF7, 0xDA, 0x0E, 0x64, 0x52, 0xC8, 0x10, 0xF3, 0x2B, 0x80, 0x90, 0x79, 0xE5, 0x62, 0xF8, 0xEA, 0xD2, 0x52, 0x2C, 0x6B, 0x7B }, @@ -1658,6 +1629,7 @@ static const unsigned char aes_test_ofb_key[3][32] = 0x2B, 0x73, 0xAE, 0xF0, 0x85, 0x7D, 0x77, 0x81, 0x1F, 0x35, 0x2C, 0x07, 0x3B, 0x61, 0x08, 0xD7, 0x2D, 0x98, 0x10, 0xA3, 0x09, 0x14, 0xDF, 0xF4 } +#endif }; static const unsigned char aes_test_ofb_iv[16] = @@ -1678,7 +1650,7 @@ static const unsigned char aes_test_ofb_pt[64] = 0xAD, 0x2B, 0x41, 0x7B, 0xE6, 0x6C, 0x37, 0x10 }; -static const unsigned char aes_test_ofb_ct[3][64] = +static const unsigned char aes_test_ofb_ct[][64] = { { 0x3B, 0x3F, 0xD9, 0x2E, 0xB7, 0x2D, 0xAD, 0x20, 0x33, 0x34, 0x49, 0xF8, 0xE8, 0x3C, 0xFB, 0x4A, @@ -1688,6 +1660,7 @@ static const unsigned char aes_test_ofb_ct[3][64] = 0x43, 0x44, 0xf7, 0xa8, 0x22, 0x60, 0xed, 0xcc, 0x30, 0x4c, 0x65, 0x28, 0xf6, 0x59, 0xc7, 0x78, 0x66, 0xa5, 0x10, 0xd9, 0xc1, 0xd6, 0xae, 0x5e }, +#if !defined(MBEDTLS_AES_ONLY_128_BIT_KEY_LENGTH) { 0xCD, 0xC8, 0x0D, 0x6F, 0xDD, 0xF1, 0x8C, 0xAB, 0x34, 0xC2, 0x59, 0x09, 0xC9, 0x9A, 0x41, 0x74, 0xfc, 0xc2, 0x8b, 0x8d, 0x4c, 0x63, 0x83, 0x7c, @@ -1704,6 +1677,7 @@ static const unsigned char aes_test_ofb_ct[3][64] = 0xf3, 0x9d, 0x1c, 0x5b, 0xba, 0x97, 0xc4, 0x08, 0x01, 0x26, 0x14, 0x1d, 0x67, 0xf3, 0x7b, 0xe8, 0x53, 0x8f, 0x5a, 0x8b, 0xe7, 0x40, 0xe4, 0x84 } +#endif }; #endif /* MBEDTLS_CIPHER_MODE_OFB */ @@ -1714,7 +1688,7 @@ static const unsigned char aes_test_ofb_ct[3][64] = * http://www.faqs.org/rfcs/rfc3686.html */ -static const unsigned char aes_test_ctr_key[3][16] = +static const unsigned char aes_test_ctr_key[][16] = { { 0xAE, 0x68, 0x52, 0xF8, 0x12, 0x10, 0x67, 0xCC, 0x4B, 0xF7, 0xA5, 0x76, 0x55, 0x77, 0xF3, 0x9E }, @@ -1724,7 +1698,7 @@ static const unsigned char aes_test_ctr_key[3][16] = 0xAC, 0x6E, 0x61, 0x85, 0x29, 0xF9, 0xA0, 0xDC } }; -static const unsigned char aes_test_ctr_nonce_counter[3][16] = +static const unsigned char aes_test_ctr_nonce_counter[][16] = { { 0x00, 0x00, 0x00, 0x30, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01 }, @@ -1734,11 +1708,10 @@ static const unsigned char aes_test_ctr_nonce_counter[3][16] = 0x4A, 0x17, 0x86, 0xF0, 0x00, 0x00, 0x00, 0x01 } }; -static const unsigned char aes_test_ctr_pt[3][48] = +static const unsigned char aes_test_ctr_pt[][48] = { { 0x53, 0x69, 0x6E, 0x67, 0x6C, 0x65, 0x20, 0x62, 0x6C, 0x6F, 0x63, 0x6B, 0x20, 0x6D, 0x73, 0x67 }, - { 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08, 0x09, 0x0A, 0x0B, 0x0C, 0x0D, 0x0E, 0x0F, 0x10, 0x11, 0x12, 0x13, 0x14, 0x15, 0x16, 0x17, @@ -1751,7 +1724,7 @@ static const unsigned char aes_test_ctr_pt[3][48] = 0x20, 0x21, 0x22, 0x23 } }; -static const unsigned char aes_test_ctr_ct[3][48] = +static const unsigned char aes_test_ctr_ct[][48] = { { 0xE4, 0x09, 0x5D, 0x4F, 0xB7, 0xA7, 0xB3, 0x79, 0x2D, 0x61, 0x75, 0xA3, 0x26, 0x13, 0x11, 0xB8 }, @@ -1875,315 +1848,359 @@ int mbedtls_aes_self_test(int verbose) #if defined(MBEDTLS_AES_ALT) mbedtls_printf(" AES note: alternative implementation.\n"); #else /* MBEDTLS_AES_ALT */ -#if defined(MBEDTLS_VIA_PADLOCK_HAVE_CODE) - if (mbedtls_padlock_has_support(MBEDTLS_PADLOCK_ACE)) { - mbedtls_printf(" AES note: using VIA Padlock.\n"); - } else -#endif #if defined(MBEDTLS_AESNI_HAVE_CODE) - if (mbedtls_aesni_has_support(MBEDTLS_AESNI_AES)) { - mbedtls_printf(" AES note: using AESNI via "); #if MBEDTLS_AESNI_HAVE_CODE == 1 - mbedtls_printf("assembly"); + mbedtls_printf(" AES note: AESNI code present (assembly implementation).\n"); #elif MBEDTLS_AESNI_HAVE_CODE == 2 - mbedtls_printf("intrinsics"); + mbedtls_printf(" AES note: AESNI code present (intrinsics implementation).\n"); #else - mbedtls_printf("(unknown)"); +#error "Unrecognised value for MBEDTLS_AESNI_HAVE_CODE" #endif - mbedtls_printf(".\n"); + if (mbedtls_aesni_has_support(MBEDTLS_AESNI_AES)) { + mbedtls_printf(" AES note: using AESNI.\n"); } else #endif - mbedtls_printf(" AES note: built-in implementation.\n"); +#if defined(MBEDTLS_VIA_PADLOCK_HAVE_CODE) + if (mbedtls_padlock_has_support(MBEDTLS_PADLOCK_ACE)) { + mbedtls_printf(" AES note: using VIA Padlock.\n"); + } else +#endif +#if defined(MBEDTLS_AESCE_HAVE_CODE) + if (MBEDTLS_AESCE_HAS_SUPPORT()) { + mbedtls_printf(" AES note: using AESCE.\n"); + } else +#endif + { +#if !defined(MBEDTLS_AES_USE_HARDWARE_ONLY) + mbedtls_printf(" AES note: built-in implementation.\n"); +#endif + } #endif /* MBEDTLS_AES_ALT */ } /* * ECB mode */ - for (i = 0; i < 6; i++) { - u = i >> 1; - keybits = 128 + u * 64; - mode = i & 1; + { + static const int num_tests = + sizeof(aes_test_ecb_enc) / sizeof(*aes_test_ecb_enc); - if (verbose != 0) { - mbedtls_printf(" AES-ECB-%3u (%s): ", keybits, - (mode == MBEDTLS_AES_DECRYPT) ? "dec" : "enc"); - } + for (i = 0; i < num_tests << 1; i++) { + u = i >> 1; + keybits = 128 + u * 64; + mode = i & 1; - memset(buf, 0, 16); + if (verbose != 0) { + mbedtls_printf(" AES-ECB-%3u (%s): ", keybits, + (mode == MBEDTLS_AES_DECRYPT) ? "dec" : "enc"); + } +#if defined(MBEDTLS_BLOCK_CIPHER_NO_DECRYPT) + if (mode == MBEDTLS_AES_DECRYPT) { + if (verbose != 0) { + mbedtls_printf("skipped\n"); + } + continue; + } +#endif - if (mode == MBEDTLS_AES_DECRYPT) { - ret = mbedtls_aes_setkey_dec(&ctx, key, keybits); - aes_tests = aes_test_ecb_dec[u]; - } else { - ret = mbedtls_aes_setkey_enc(&ctx, key, keybits); - aes_tests = aes_test_ecb_enc[u]; - } + memset(buf, 0, 16); - /* - * AES-192 is an optional feature that may be unavailable when - * there is an alternative underlying implementation i.e. when - * MBEDTLS_AES_ALT is defined. - */ - if (ret == MBEDTLS_ERR_PLATFORM_FEATURE_UNSUPPORTED && keybits == 192) { - mbedtls_printf("skipped\n"); - continue; - } else if (ret != 0) { - goto exit; - } +#if !defined(MBEDTLS_BLOCK_CIPHER_NO_DECRYPT) + if (mode == MBEDTLS_AES_DECRYPT) { + ret = mbedtls_aes_setkey_dec(&ctx, key, keybits); + aes_tests = aes_test_ecb_dec[u]; + } else +#endif + { + ret = mbedtls_aes_setkey_enc(&ctx, key, keybits); + aes_tests = aes_test_ecb_enc[u]; + } - for (j = 0; j < 10000; j++) { - ret = mbedtls_aes_crypt_ecb(&ctx, mode, buf, buf); - if (ret != 0) { + /* + * AES-192 is an optional feature that may be unavailable when + * there is an alternative underlying implementation i.e. when + * MBEDTLS_AES_ALT is defined. + */ + if (ret == MBEDTLS_ERR_PLATFORM_FEATURE_UNSUPPORTED && keybits == 192) { + mbedtls_printf("skipped\n"); + continue; + } else if (ret != 0) { goto exit; } - } - if (memcmp(buf, aes_tests, 16) != 0) { - ret = 1; - goto exit; + for (j = 0; j < 10000; j++) { + ret = mbedtls_aes_crypt_ecb(&ctx, mode, buf, buf); + if (ret != 0) { + goto exit; + } + } + + if (memcmp(buf, aes_tests, 16) != 0) { + ret = 1; + goto exit; + } + + if (verbose != 0) { + mbedtls_printf("passed\n"); + } } if (verbose != 0) { - mbedtls_printf("passed\n"); + mbedtls_printf("\n"); } } - if (verbose != 0) { - mbedtls_printf("\n"); - } - #if defined(MBEDTLS_CIPHER_MODE_CBC) /* * CBC mode */ - for (i = 0; i < 6; i++) { - u = i >> 1; - keybits = 128 + u * 64; - mode = i & 1; + { + static const int num_tests = + sizeof(aes_test_cbc_dec) / sizeof(*aes_test_cbc_dec); - if (verbose != 0) { - mbedtls_printf(" AES-CBC-%3u (%s): ", keybits, - (mode == MBEDTLS_AES_DECRYPT) ? "dec" : "enc"); - } + for (i = 0; i < num_tests << 1; i++) { + u = i >> 1; + keybits = 128 + u * 64; + mode = i & 1; - memset(iv, 0, 16); - memset(prv, 0, 16); - memset(buf, 0, 16); + if (verbose != 0) { + mbedtls_printf(" AES-CBC-%3u (%s): ", keybits, + (mode == MBEDTLS_AES_DECRYPT) ? "dec" : "enc"); + } - if (mode == MBEDTLS_AES_DECRYPT) { - ret = mbedtls_aes_setkey_dec(&ctx, key, keybits); - aes_tests = aes_test_cbc_dec[u]; - } else { - ret = mbedtls_aes_setkey_enc(&ctx, key, keybits); - aes_tests = aes_test_cbc_enc[u]; - } + memset(iv, 0, 16); + memset(prv, 0, 16); + memset(buf, 0, 16); - /* - * AES-192 is an optional feature that may be unavailable when - * there is an alternative underlying implementation i.e. when - * MBEDTLS_AES_ALT is defined. - */ - if (ret == MBEDTLS_ERR_PLATFORM_FEATURE_UNSUPPORTED && keybits == 192) { - mbedtls_printf("skipped\n"); - continue; - } else if (ret != 0) { - goto exit; - } + if (mode == MBEDTLS_AES_DECRYPT) { + ret = mbedtls_aes_setkey_dec(&ctx, key, keybits); + aes_tests = aes_test_cbc_dec[u]; + } else { + ret = mbedtls_aes_setkey_enc(&ctx, key, keybits); + aes_tests = aes_test_cbc_enc[u]; + } + + /* + * AES-192 is an optional feature that may be unavailable when + * there is an alternative underlying implementation i.e. when + * MBEDTLS_AES_ALT is defined. + */ + if (ret == MBEDTLS_ERR_PLATFORM_FEATURE_UNSUPPORTED && keybits == 192) { + mbedtls_printf("skipped\n"); + continue; + } else if (ret != 0) { + goto exit; + } + + for (j = 0; j < 10000; j++) { + if (mode == MBEDTLS_AES_ENCRYPT) { + unsigned char tmp[16]; - for (j = 0; j < 10000; j++) { - if (mode == MBEDTLS_AES_ENCRYPT) { - unsigned char tmp[16]; + memcpy(tmp, prv, 16); + memcpy(prv, buf, 16); + memcpy(buf, tmp, 16); + } + + ret = mbedtls_aes_crypt_cbc(&ctx, mode, 16, iv, buf, buf); + if (ret != 0) { + goto exit; + } - memcpy(tmp, prv, 16); - memcpy(prv, buf, 16); - memcpy(buf, tmp, 16); } - ret = mbedtls_aes_crypt_cbc(&ctx, mode, 16, iv, buf, buf); - if (ret != 0) { + if (memcmp(buf, aes_tests, 16) != 0) { + ret = 1; goto exit; } - } - - if (memcmp(buf, aes_tests, 16) != 0) { - ret = 1; - goto exit; + if (verbose != 0) { + mbedtls_printf("passed\n"); + } } if (verbose != 0) { - mbedtls_printf("passed\n"); + mbedtls_printf("\n"); } } - - if (verbose != 0) { - mbedtls_printf("\n"); - } #endif /* MBEDTLS_CIPHER_MODE_CBC */ #if defined(MBEDTLS_CIPHER_MODE_CFB) /* * CFB128 mode */ - for (i = 0; i < 6; i++) { - u = i >> 1; - keybits = 128 + u * 64; - mode = i & 1; + { + static const int num_tests = + sizeof(aes_test_cfb128_key) / sizeof(*aes_test_cfb128_key); - if (verbose != 0) { - mbedtls_printf(" AES-CFB128-%3u (%s): ", keybits, - (mode == MBEDTLS_AES_DECRYPT) ? "dec" : "enc"); - } + for (i = 0; i < num_tests << 1; i++) { + u = i >> 1; + keybits = 128 + u * 64; + mode = i & 1; - memcpy(iv, aes_test_cfb128_iv, 16); - memcpy(key, aes_test_cfb128_key[u], keybits / 8); + if (verbose != 0) { + mbedtls_printf(" AES-CFB128-%3u (%s): ", keybits, + (mode == MBEDTLS_AES_DECRYPT) ? "dec" : "enc"); + } - offset = 0; - ret = mbedtls_aes_setkey_enc(&ctx, key, keybits); - /* - * AES-192 is an optional feature that may be unavailable when - * there is an alternative underlying implementation i.e. when - * MBEDTLS_AES_ALT is defined. - */ - if (ret == MBEDTLS_ERR_PLATFORM_FEATURE_UNSUPPORTED && keybits == 192) { - mbedtls_printf("skipped\n"); - continue; - } else if (ret != 0) { - goto exit; - } + memcpy(iv, aes_test_cfb128_iv, 16); + memcpy(key, aes_test_cfb128_key[u], keybits / 8); - if (mode == MBEDTLS_AES_DECRYPT) { - memcpy(buf, aes_test_cfb128_ct[u], 64); - aes_tests = aes_test_cfb128_pt; - } else { - memcpy(buf, aes_test_cfb128_pt, 64); - aes_tests = aes_test_cfb128_ct[u]; - } + offset = 0; + ret = mbedtls_aes_setkey_enc(&ctx, key, keybits); + /* + * AES-192 is an optional feature that may be unavailable when + * there is an alternative underlying implementation i.e. when + * MBEDTLS_AES_ALT is defined. + */ + if (ret == MBEDTLS_ERR_PLATFORM_FEATURE_UNSUPPORTED && keybits == 192) { + mbedtls_printf("skipped\n"); + continue; + } else if (ret != 0) { + goto exit; + } - ret = mbedtls_aes_crypt_cfb128(&ctx, mode, 64, &offset, iv, buf, buf); - if (ret != 0) { - goto exit; - } + if (mode == MBEDTLS_AES_DECRYPT) { + memcpy(buf, aes_test_cfb128_ct[u], 64); + aes_tests = aes_test_cfb128_pt; + } else { + memcpy(buf, aes_test_cfb128_pt, 64); + aes_tests = aes_test_cfb128_ct[u]; + } - if (memcmp(buf, aes_tests, 64) != 0) { - ret = 1; - goto exit; + ret = mbedtls_aes_crypt_cfb128(&ctx, mode, 64, &offset, iv, buf, buf); + if (ret != 0) { + goto exit; + } + + if (memcmp(buf, aes_tests, 64) != 0) { + ret = 1; + goto exit; + } + + if (verbose != 0) { + mbedtls_printf("passed\n"); + } } if (verbose != 0) { - mbedtls_printf("passed\n"); + mbedtls_printf("\n"); } } - - if (verbose != 0) { - mbedtls_printf("\n"); - } #endif /* MBEDTLS_CIPHER_MODE_CFB */ #if defined(MBEDTLS_CIPHER_MODE_OFB) /* * OFB mode */ - for (i = 0; i < 6; i++) { - u = i >> 1; - keybits = 128 + u * 64; - mode = i & 1; + { + static const int num_tests = + sizeof(aes_test_ofb_key) / sizeof(*aes_test_ofb_key); - if (verbose != 0) { - mbedtls_printf(" AES-OFB-%3u (%s): ", keybits, - (mode == MBEDTLS_AES_DECRYPT) ? "dec" : "enc"); - } + for (i = 0; i < num_tests << 1; i++) { + u = i >> 1; + keybits = 128 + u * 64; + mode = i & 1; - memcpy(iv, aes_test_ofb_iv, 16); - memcpy(key, aes_test_ofb_key[u], keybits / 8); + if (verbose != 0) { + mbedtls_printf(" AES-OFB-%3u (%s): ", keybits, + (mode == MBEDTLS_AES_DECRYPT) ? "dec" : "enc"); + } - offset = 0; - ret = mbedtls_aes_setkey_enc(&ctx, key, keybits); - /* - * AES-192 is an optional feature that may be unavailable when - * there is an alternative underlying implementation i.e. when - * MBEDTLS_AES_ALT is defined. - */ - if (ret == MBEDTLS_ERR_PLATFORM_FEATURE_UNSUPPORTED && keybits == 192) { - mbedtls_printf("skipped\n"); - continue; - } else if (ret != 0) { - goto exit; - } + memcpy(iv, aes_test_ofb_iv, 16); + memcpy(key, aes_test_ofb_key[u], keybits / 8); - if (mode == MBEDTLS_AES_DECRYPT) { - memcpy(buf, aes_test_ofb_ct[u], 64); - aes_tests = aes_test_ofb_pt; - } else { - memcpy(buf, aes_test_ofb_pt, 64); - aes_tests = aes_test_ofb_ct[u]; - } + offset = 0; + ret = mbedtls_aes_setkey_enc(&ctx, key, keybits); + /* + * AES-192 is an optional feature that may be unavailable when + * there is an alternative underlying implementation i.e. when + * MBEDTLS_AES_ALT is defined. + */ + if (ret == MBEDTLS_ERR_PLATFORM_FEATURE_UNSUPPORTED && keybits == 192) { + mbedtls_printf("skipped\n"); + continue; + } else if (ret != 0) { + goto exit; + } - ret = mbedtls_aes_crypt_ofb(&ctx, 64, &offset, iv, buf, buf); - if (ret != 0) { - goto exit; - } + if (mode == MBEDTLS_AES_DECRYPT) { + memcpy(buf, aes_test_ofb_ct[u], 64); + aes_tests = aes_test_ofb_pt; + } else { + memcpy(buf, aes_test_ofb_pt, 64); + aes_tests = aes_test_ofb_ct[u]; + } - if (memcmp(buf, aes_tests, 64) != 0) { - ret = 1; - goto exit; + ret = mbedtls_aes_crypt_ofb(&ctx, 64, &offset, iv, buf, buf); + if (ret != 0) { + goto exit; + } + + if (memcmp(buf, aes_tests, 64) != 0) { + ret = 1; + goto exit; + } + + if (verbose != 0) { + mbedtls_printf("passed\n"); + } } if (verbose != 0) { - mbedtls_printf("passed\n"); + mbedtls_printf("\n"); } } - - if (verbose != 0) { - mbedtls_printf("\n"); - } #endif /* MBEDTLS_CIPHER_MODE_OFB */ #if defined(MBEDTLS_CIPHER_MODE_CTR) /* * CTR mode */ - for (i = 0; i < 6; i++) { - u = i >> 1; - mode = i & 1; + { + static const int num_tests = + sizeof(aes_test_ctr_key) / sizeof(*aes_test_ctr_key); - if (verbose != 0) { - mbedtls_printf(" AES-CTR-128 (%s): ", - (mode == MBEDTLS_AES_DECRYPT) ? "dec" : "enc"); - } + for (i = 0; i < num_tests << 1; i++) { + u = i >> 1; + mode = i & 1; - memcpy(nonce_counter, aes_test_ctr_nonce_counter[u], 16); - memcpy(key, aes_test_ctr_key[u], 16); + if (verbose != 0) { + mbedtls_printf(" AES-CTR-128 (%s): ", + (mode == MBEDTLS_AES_DECRYPT) ? "dec" : "enc"); + } - offset = 0; - if ((ret = mbedtls_aes_setkey_enc(&ctx, key, 128)) != 0) { - goto exit; - } + memcpy(nonce_counter, aes_test_ctr_nonce_counter[u], 16); + memcpy(key, aes_test_ctr_key[u], 16); - len = aes_test_ctr_len[u]; + offset = 0; + if ((ret = mbedtls_aes_setkey_enc(&ctx, key, 128)) != 0) { + goto exit; + } - if (mode == MBEDTLS_AES_DECRYPT) { - memcpy(buf, aes_test_ctr_ct[u], len); - aes_tests = aes_test_ctr_pt[u]; - } else { - memcpy(buf, aes_test_ctr_pt[u], len); - aes_tests = aes_test_ctr_ct[u]; - } + len = aes_test_ctr_len[u]; - ret = mbedtls_aes_crypt_ctr(&ctx, len, &offset, nonce_counter, - stream_block, buf, buf); - if (ret != 0) { - goto exit; - } + if (mode == MBEDTLS_AES_DECRYPT) { + memcpy(buf, aes_test_ctr_ct[u], len); + aes_tests = aes_test_ctr_pt[u]; + } else { + memcpy(buf, aes_test_ctr_pt[u], len); + aes_tests = aes_test_ctr_ct[u]; + } - if (memcmp(buf, aes_tests, len) != 0) { - ret = 1; - goto exit; - } + ret = mbedtls_aes_crypt_ctr(&ctx, len, &offset, nonce_counter, + stream_block, buf, buf); + if (ret != 0) { + goto exit; + } - if (verbose != 0) { - mbedtls_printf("passed\n"); + if (memcmp(buf, aes_tests, len) != 0) { + ret = 1; + goto exit; + } + + if (verbose != 0) { + mbedtls_printf("passed\n"); + } } } @@ -2193,14 +2210,14 @@ int mbedtls_aes_self_test(int verbose) #endif /* MBEDTLS_CIPHER_MODE_CTR */ #if defined(MBEDTLS_CIPHER_MODE_XTS) + /* + * XTS mode + */ { static const int num_tests = sizeof(aes_test_xts_key) / sizeof(*aes_test_xts_key); mbedtls_aes_xts_context ctx_xts; - /* - * XTS mode - */ mbedtls_aes_xts_init(&ctx_xts); for (i = 0; i < num_tests << 1; i++) { diff --git a/vendor/mbedtls/library/aesce.c b/vendor/mbedtls/library/aesce.c new file mode 100644 index 0000000000..6a9e0a1c6b --- /dev/null +++ b/vendor/mbedtls/library/aesce.c @@ -0,0 +1,618 @@ +/* + * Armv8-A Cryptographic Extension support functions for Aarch64 + * + * Copyright The Mbed TLS Contributors + * SPDX-License-Identifier: Apache-2.0 OR GPL-2.0-or-later + */ + +#if defined(__clang__) && (__clang_major__ >= 4) + +/* Ideally, we would simply use MBEDTLS_ARCH_IS_ARMV8_A in the following #if, + * but that is defined by build_info.h, and we need this block to happen first. */ +#if defined(__ARM_ARCH) +#if __ARM_ARCH >= 8 +#define MBEDTLS_AESCE_ARCH_IS_ARMV8_A +#endif +#endif + +#if defined(MBEDTLS_AESCE_ARCH_IS_ARMV8_A) && !defined(__ARM_FEATURE_CRYPTO) +/* TODO: Re-consider above after https://reviews.llvm.org/D131064 merged. + * + * The intrinsic declaration are guarded by predefined ACLE macros in clang: + * these are normally only enabled by the -march option on the command line. + * By defining the macros ourselves we gain access to those declarations without + * requiring -march on the command line. + * + * `arm_neon.h` is included by common.h, so we put these defines + * at the top of this file, before any includes. + */ +#define __ARM_FEATURE_CRYPTO 1 +/* See: https://arm-software.github.io/acle/main/acle.html#cryptographic-extensions + * + * `__ARM_FEATURE_CRYPTO` is deprecated, but we need to continue to specify it + * for older compilers. + */ +#define __ARM_FEATURE_AES 1 +#define MBEDTLS_ENABLE_ARM_CRYPTO_EXTENSIONS_COMPILER_FLAG +#endif + +#endif /* defined(__clang__) && (__clang_major__ >= 4) */ + +#include +#include "common.h" + +#if defined(MBEDTLS_AESCE_C) + +#include "aesce.h" + +#if defined(MBEDTLS_AESCE_HAVE_CODE) + +/* Compiler version checks. */ +#if defined(__clang__) +# if defined(MBEDTLS_ARCH_IS_ARM32) && (__clang_major__ < 11) +# error "Minimum version of Clang for MBEDTLS_AESCE_C on 32-bit Arm or Thumb is 11.0." +# elif defined(MBEDTLS_ARCH_IS_ARM64) && (__clang_major__ < 4) +# error "Minimum version of Clang for MBEDTLS_AESCE_C on aarch64 is 4.0." +# endif +#elif defined(__GNUC__) +# if __GNUC__ < 6 +# error "Minimum version of GCC for MBEDTLS_AESCE_C is 6.0." +# endif +#elif defined(_MSC_VER) +/* TODO: We haven't verified MSVC from 1920 to 1928. If someone verified that, + * please update this and document of `MBEDTLS_AESCE_C` in + * `mbedtls_config.h`. */ +# if _MSC_VER < 1929 +# error "Minimum version of MSVC for MBEDTLS_AESCE_C is 2019 version 16.11.2." +# endif +#elif defined(__ARMCC_VERSION) +# if defined(MBEDTLS_ARCH_IS_ARM32) && (__ARMCC_VERSION < 6200002) +/* TODO: We haven't verified armclang for 32-bit Arm/Thumb prior to 6.20. + * If someone verified that, please update this and document of + * `MBEDTLS_AESCE_C` in `mbedtls_config.h`. */ +# error "Minimum version of armclang for MBEDTLS_AESCE_C on 32-bit Arm is 6.20." +# elif defined(MBEDTLS_ARCH_IS_ARM64) && (__ARMCC_VERSION < 6060000) +# error "Minimum version of armclang for MBEDTLS_AESCE_C on aarch64 is 6.6." +# endif +#endif + +#if !(defined(__ARM_FEATURE_CRYPTO) || defined(__ARM_FEATURE_AES)) || \ + defined(MBEDTLS_ENABLE_ARM_CRYPTO_EXTENSIONS_COMPILER_FLAG) +# if defined(__ARMCOMPILER_VERSION) +# if __ARMCOMPILER_VERSION <= 6090000 +# error "Must use minimum -march=armv8-a+crypto for MBEDTLS_AESCE_C" +# else +# pragma clang attribute push (__attribute__((target("aes"))), apply_to=function) +# define MBEDTLS_POP_TARGET_PRAGMA +# endif +# elif defined(__clang__) +# pragma clang attribute push (__attribute__((target("aes"))), apply_to=function) +# define MBEDTLS_POP_TARGET_PRAGMA +# elif defined(__GNUC__) +# pragma GCC push_options +# pragma GCC target ("+crypto") +# define MBEDTLS_POP_TARGET_PRAGMA +# elif defined(_MSC_VER) +# error "Required feature(__ARM_FEATURE_AES) is not enabled." +# endif +#endif /* !(__ARM_FEATURE_CRYPTO || __ARM_FEATURE_AES) || + MBEDTLS_ENABLE_ARM_CRYPTO_EXTENSIONS_COMPILER_FLAG */ + +#if defined(__linux__) && !defined(MBEDTLS_AES_USE_HARDWARE_ONLY) + +#include +#if !defined(HWCAP_NEON) +#define HWCAP_NEON (1 << 12) +#endif +#if !defined(HWCAP2_AES) +#define HWCAP2_AES (1 << 0) +#endif +#if !defined(HWCAP_AES) +#define HWCAP_AES (1 << 3) +#endif +#if !defined(HWCAP_ASIMD) +#define HWCAP_ASIMD (1 << 1) +#endif + +signed char mbedtls_aesce_has_support_result = -1; + +#if !defined(MBEDTLS_AES_USE_HARDWARE_ONLY) +/* + * AES instruction support detection routine + */ +int mbedtls_aesce_has_support_impl(void) +{ + /* To avoid many calls to getauxval, cache the result. This is + * thread-safe, because we store the result in a char so cannot + * be vulnerable to non-atomic updates. + * It is possible that we could end up setting result more than + * once, but that is harmless. + */ + if (mbedtls_aesce_has_support_result == -1) { +#if defined(MBEDTLS_ARCH_IS_ARM32) + unsigned long auxval = getauxval(AT_HWCAP); + unsigned long auxval2 = getauxval(AT_HWCAP2); + if (((auxval & HWCAP_NEON) == HWCAP_NEON) && + ((auxval2 & HWCAP2_AES) == HWCAP2_AES)) { + mbedtls_aesce_has_support_result = 1; + } else { + mbedtls_aesce_has_support_result = 0; + } +#else + unsigned long auxval = getauxval(AT_HWCAP); + if ((auxval & (HWCAP_ASIMD | HWCAP_AES)) == + (HWCAP_ASIMD | HWCAP_AES)) { + mbedtls_aesce_has_support_result = 1; + } else { + mbedtls_aesce_has_support_result = 0; + } +#endif + } + return mbedtls_aesce_has_support_result; +} +#endif + +#endif /* defined(__linux__) && !defined(MBEDTLS_AES_USE_HARDWARE_ONLY) */ + +/* Single round of AESCE encryption */ +#define AESCE_ENCRYPT_ROUND \ + block = vaeseq_u8(block, vld1q_u8(keys)); \ + block = vaesmcq_u8(block); \ + keys += 16 +/* Two rounds of AESCE encryption */ +#define AESCE_ENCRYPT_ROUND_X2 AESCE_ENCRYPT_ROUND; AESCE_ENCRYPT_ROUND + +MBEDTLS_OPTIMIZE_FOR_PERFORMANCE +static uint8x16_t aesce_encrypt_block(uint8x16_t block, + unsigned char *keys, + int rounds) +{ + /* 10, 12 or 14 rounds. Unroll loop. */ + if (rounds == 10) { + goto rounds_10; + } + if (rounds == 12) { + goto rounds_12; + } + AESCE_ENCRYPT_ROUND_X2; +rounds_12: + AESCE_ENCRYPT_ROUND_X2; +rounds_10: + AESCE_ENCRYPT_ROUND_X2; + AESCE_ENCRYPT_ROUND_X2; + AESCE_ENCRYPT_ROUND_X2; + AESCE_ENCRYPT_ROUND_X2; + AESCE_ENCRYPT_ROUND; + + /* AES AddRoundKey for the previous round. + * SubBytes, ShiftRows for the final round. */ + block = vaeseq_u8(block, vld1q_u8(keys)); + keys += 16; + + /* Final round: no MixColumns */ + + /* Final AddRoundKey */ + block = veorq_u8(block, vld1q_u8(keys)); + + return block; +} + +/* Single round of AESCE decryption + * + * AES AddRoundKey, SubBytes, ShiftRows + * + * block = vaesdq_u8(block, vld1q_u8(keys)); + * + * AES inverse MixColumns for the next round. + * + * This means that we switch the order of the inverse AddRoundKey and + * inverse MixColumns operations. We have to do this as AddRoundKey is + * done in an atomic instruction together with the inverses of SubBytes + * and ShiftRows. + * + * It works because MixColumns is a linear operation over GF(2^8) and + * AddRoundKey is an exclusive or, which is equivalent to addition over + * GF(2^8). (The inverse of MixColumns needs to be applied to the + * affected round keys separately which has been done when the + * decryption round keys were calculated.) + * + * block = vaesimcq_u8(block); + */ +#define AESCE_DECRYPT_ROUND \ + block = vaesdq_u8(block, vld1q_u8(keys)); \ + block = vaesimcq_u8(block); \ + keys += 16 +/* Two rounds of AESCE decryption */ +#define AESCE_DECRYPT_ROUND_X2 AESCE_DECRYPT_ROUND; AESCE_DECRYPT_ROUND + +#if !defined(MBEDTLS_BLOCK_CIPHER_NO_DECRYPT) +static uint8x16_t aesce_decrypt_block(uint8x16_t block, + unsigned char *keys, + int rounds) +{ + /* 10, 12 or 14 rounds. Unroll loop. */ + if (rounds == 10) { + goto rounds_10; + } + if (rounds == 12) { + goto rounds_12; + } + AESCE_DECRYPT_ROUND_X2; +rounds_12: + AESCE_DECRYPT_ROUND_X2; +rounds_10: + AESCE_DECRYPT_ROUND_X2; + AESCE_DECRYPT_ROUND_X2; + AESCE_DECRYPT_ROUND_X2; + AESCE_DECRYPT_ROUND_X2; + AESCE_DECRYPT_ROUND; + + /* The inverses of AES AddRoundKey, SubBytes, ShiftRows finishing up the + * last full round. */ + block = vaesdq_u8(block, vld1q_u8(keys)); + keys += 16; + + /* Inverse AddRoundKey for inverting the initial round key addition. */ + block = veorq_u8(block, vld1q_u8(keys)); + + return block; +} +#endif + +/* + * AES-ECB block en(de)cryption + */ +int mbedtls_aesce_crypt_ecb(mbedtls_aes_context *ctx, + int mode, + const unsigned char input[16], + unsigned char output[16]) +{ + uint8x16_t block = vld1q_u8(&input[0]); + unsigned char *keys = (unsigned char *) (ctx->buf + ctx->rk_offset); + +#if !defined(MBEDTLS_BLOCK_CIPHER_NO_DECRYPT) + if (mode == MBEDTLS_AES_DECRYPT) { + block = aesce_decrypt_block(block, keys, ctx->nr); + } else +#else + (void) mode; +#endif + { + block = aesce_encrypt_block(block, keys, ctx->nr); + } + vst1q_u8(&output[0], block); + + return 0; +} + +/* + * Compute decryption round keys from encryption round keys + */ +#if !defined(MBEDTLS_BLOCK_CIPHER_NO_DECRYPT) +void mbedtls_aesce_inverse_key(unsigned char *invkey, + const unsigned char *fwdkey, + int nr) +{ + int i, j; + j = nr; + vst1q_u8(invkey, vld1q_u8(fwdkey + j * 16)); + for (i = 1, j--; j > 0; i++, j--) { + vst1q_u8(invkey + i * 16, + vaesimcq_u8(vld1q_u8(fwdkey + j * 16))); + } + vst1q_u8(invkey + i * 16, vld1q_u8(fwdkey + j * 16)); + +} +#endif + +static inline uint32_t aes_rot_word(uint32_t word) +{ + return (word << (32 - 8)) | (word >> 8); +} + +static inline uint32_t aes_sub_word(uint32_t in) +{ + uint8x16_t v = vreinterpretq_u8_u32(vdupq_n_u32(in)); + uint8x16_t zero = vdupq_n_u8(0); + + /* vaeseq_u8 does both SubBytes and ShiftRows. Taking the first row yields + * the correct result as ShiftRows doesn't change the first row. */ + v = vaeseq_u8(zero, v); + return vgetq_lane_u32(vreinterpretq_u32_u8(v), 0); +} + +/* + * Key expansion function + */ +static void aesce_setkey_enc(unsigned char *rk, + const unsigned char *key, + const size_t key_bit_length) +{ + static uint8_t const rcon[] = { 0x01, 0x02, 0x04, 0x08, 0x10, + 0x20, 0x40, 0x80, 0x1b, 0x36 }; + /* See https://nvlpubs.nist.gov/nistpubs/FIPS/NIST.FIPS.197.pdf + * - Section 5, Nr = Nk + 6 + * - Section 5.2, the length of round keys is Nb*(Nr+1) + */ + const size_t key_len_in_words = key_bit_length / 32; /* Nk */ + const size_t round_key_len_in_words = 4; /* Nb */ + const size_t rounds_needed = key_len_in_words + 6; /* Nr */ + const size_t round_keys_len_in_words = + round_key_len_in_words * (rounds_needed + 1); /* Nb*(Nr+1) */ + const uint32_t *rko_end = (uint32_t *) rk + round_keys_len_in_words; + + memcpy(rk, key, key_len_in_words * 4); + + for (uint32_t *rki = (uint32_t *) rk; + rki + key_len_in_words < rko_end; + rki += key_len_in_words) { + + size_t iteration = (size_t) (rki - (uint32_t *) rk) / key_len_in_words; + uint32_t *rko; + rko = rki + key_len_in_words; + rko[0] = aes_rot_word(aes_sub_word(rki[key_len_in_words - 1])); + rko[0] ^= rcon[iteration] ^ rki[0]; + rko[1] = rko[0] ^ rki[1]; + rko[2] = rko[1] ^ rki[2]; + rko[3] = rko[2] ^ rki[3]; + if (rko + key_len_in_words > rko_end) { + /* Do not write overflow words.*/ + continue; + } +#if !defined(MBEDTLS_AES_ONLY_128_BIT_KEY_LENGTH) + switch (key_bit_length) { + case 128: + break; + case 192: + rko[4] = rko[3] ^ rki[4]; + rko[5] = rko[4] ^ rki[5]; + break; + case 256: + rko[4] = aes_sub_word(rko[3]) ^ rki[4]; + rko[5] = rko[4] ^ rki[5]; + rko[6] = rko[5] ^ rki[6]; + rko[7] = rko[6] ^ rki[7]; + break; + } +#endif /* !MBEDTLS_AES_ONLY_128_BIT_KEY_LENGTH */ + } +} + +/* + * Key expansion, wrapper + */ +int mbedtls_aesce_setkey_enc(unsigned char *rk, + const unsigned char *key, + size_t bits) +{ + switch (bits) { + case 128: + case 192: + case 256: + aesce_setkey_enc(rk, key, bits); + break; + default: + return MBEDTLS_ERR_AES_INVALID_KEY_LENGTH; + } + + return 0; +} + +#if defined(MBEDTLS_GCM_C) + +#if defined(MBEDTLS_ARCH_IS_ARM32) + +#if defined(__clang__) +/* On clang for A32/T32, work around some missing intrinsics and types which are listed in + * [ACLE](https://arm-software.github.io/acle/neon_intrinsics/advsimd.html#polynomial-1) + * These are only required for GCM. + */ +#define vreinterpretq_u64_p64(a) ((uint64x2_t) a) + +typedef uint8x16_t poly128_t; + +static inline poly128_t vmull_p64(poly64_t a, poly64_t b) +{ + poly128_t r; + asm ("vmull.p64 %[r], %[a], %[b]" : [r] "=w" (r) : [a] "w" (a), [b] "w" (b) :); + return r; +} + +/* This is set to cause some more missing intrinsics to be defined below */ +#define COMMON_MISSING_INTRINSICS + +static inline poly128_t vmull_high_p64(poly64x2_t a, poly64x2_t b) +{ + return vmull_p64((poly64_t) (vget_high_u64((uint64x2_t) a)), + (poly64_t) (vget_high_u64((uint64x2_t) b))); +} + +#endif /* defined(__clang__) */ + +static inline uint8x16_t vrbitq_u8(uint8x16_t x) +{ + /* There is no vrbitq_u8 instruction in A32/T32, so provide + * an equivalent non-Neon implementation. Reverse bit order in each + * byte with 4x rbit, rev. */ + asm ("ldm %[p], { r2-r5 } \n\t" + "rbit r2, r2 \n\t" + "rev r2, r2 \n\t" + "rbit r3, r3 \n\t" + "rev r3, r3 \n\t" + "rbit r4, r4 \n\t" + "rev r4, r4 \n\t" + "rbit r5, r5 \n\t" + "rev r5, r5 \n\t" + "stm %[p], { r2-r5 } \n\t" + : + /* Output: 16 bytes of memory pointed to by &x */ + "+m" (*(uint8_t(*)[16]) &x) + : + [p] "r" (&x) + : + "r2", "r3", "r4", "r5" + ); + return x; +} + +#endif /* defined(MBEDTLS_ARCH_IS_ARM32) */ + +#if defined(MBEDTLS_COMPILER_IS_GCC) && __GNUC__ == 5 +/* Some intrinsics are not available for GCC 5.X. */ +#define COMMON_MISSING_INTRINSICS +#endif /* MBEDTLS_COMPILER_IS_GCC && __GNUC__ == 5 */ + + +#if defined(COMMON_MISSING_INTRINSICS) + +/* Missing intrinsics common to both GCC 5, and Clang on 32-bit */ + +#define vreinterpretq_p64_u8(a) ((poly64x2_t) a) +#define vreinterpretq_u8_p128(a) ((uint8x16_t) a) + +static inline poly64x1_t vget_low_p64(poly64x2_t a) +{ + uint64x1_t r = vget_low_u64(vreinterpretq_u64_p64(a)); + return (poly64x1_t) r; + +} + +#endif /* COMMON_MISSING_INTRINSICS */ + +/* vmull_p64/vmull_high_p64 wrappers. + * + * Older compilers miss some intrinsic functions for `poly*_t`. We use + * uint8x16_t and uint8x16x3_t as input/output parameters. + */ +#if defined(MBEDTLS_COMPILER_IS_GCC) +/* GCC reports incompatible type error without cast. GCC think poly64_t and + * poly64x1_t are different, that is different with MSVC and Clang. */ +#define MBEDTLS_VMULL_P64(a, b) vmull_p64((poly64_t) a, (poly64_t) b) +#else +/* MSVC reports `error C2440: 'type cast'` with cast. Clang does not report + * error with/without cast. And I think poly64_t and poly64x1_t are same, no + * cast for clang also. */ +#define MBEDTLS_VMULL_P64(a, b) vmull_p64(a, b) +#endif /* MBEDTLS_COMPILER_IS_GCC */ + +static inline uint8x16_t pmull_low(uint8x16_t a, uint8x16_t b) +{ + + return vreinterpretq_u8_p128( + MBEDTLS_VMULL_P64( + (poly64_t) vget_low_p64(vreinterpretq_p64_u8(a)), + (poly64_t) vget_low_p64(vreinterpretq_p64_u8(b)) + )); +} + +static inline uint8x16_t pmull_high(uint8x16_t a, uint8x16_t b) +{ + return vreinterpretq_u8_p128( + vmull_high_p64(vreinterpretq_p64_u8(a), + vreinterpretq_p64_u8(b))); +} + +/* GHASH does 128b polynomial multiplication on block in GF(2^128) defined by + * `x^128 + x^7 + x^2 + x + 1`. + * + * Arm64 only has 64b->128b polynomial multipliers, we need to do 4 64b + * multiplies to generate a 128b. + * + * `poly_mult_128` executes polynomial multiplication and outputs 256b that + * represented by 3 128b due to code size optimization. + * + * Output layout: + * | | | | + * |------------|-------------|-------------| + * | ret.val[0] | h3:h2:00:00 | high 128b | + * | ret.val[1] | :m2:m1:00 | middle 128b | + * | ret.val[2] | : :l1:l0 | low 128b | + */ +static inline uint8x16x3_t poly_mult_128(uint8x16_t a, uint8x16_t b) +{ + uint8x16x3_t ret; + uint8x16_t h, m, l; /* retval high/middle/low */ + uint8x16_t c, d, e; + + h = pmull_high(a, b); /* h3:h2:00:00 = a1*b1 */ + l = pmull_low(a, b); /* : :l1:l0 = a0*b0 */ + c = vextq_u8(b, b, 8); /* :c1:c0 = b0:b1 */ + d = pmull_high(a, c); /* :d2:d1:00 = a1*b0 */ + e = pmull_low(a, c); /* :e2:e1:00 = a0*b1 */ + m = veorq_u8(d, e); /* :m2:m1:00 = d + e */ + + ret.val[0] = h; + ret.val[1] = m; + ret.val[2] = l; + return ret; +} + +/* + * Modulo reduction. + * + * See: https://www.researchgate.net/publication/285612706_Implementing_GCM_on_ARMv8 + * + * Section 4.3 + * + * Modular reduction is slightly more complex. Write the GCM modulus as f(z) = + * z^128 +r(z), where r(z) = z^7+z^2+z+ 1. The well known approach is to + * consider that z^128 ≡r(z) (mod z^128 +r(z)), allowing us to write the 256-bit + * operand to be reduced as a(z) = h(z)z^128 +l(z)≡h(z)r(z) + l(z). That is, we + * simply multiply the higher part of the operand by r(z) and add it to l(z). If + * the result is still larger than 128 bits, we reduce again. + */ +static inline uint8x16_t poly_mult_reduce(uint8x16x3_t input) +{ + uint8x16_t const ZERO = vdupq_n_u8(0); + + uint64x2_t r = vreinterpretq_u64_u8(vdupq_n_u8(0x87)); +#if defined(__GNUC__) + /* use 'asm' as an optimisation barrier to prevent loading MODULO from + * memory. It is for GNUC compatible compilers. + */ + asm volatile ("" : "+w" (r)); +#endif + uint8x16_t const MODULO = vreinterpretq_u8_u64(vshrq_n_u64(r, 64 - 8)); + uint8x16_t h, m, l; /* input high/middle/low 128b */ + uint8x16_t c, d, e, f, g, n, o; + h = input.val[0]; /* h3:h2:00:00 */ + m = input.val[1]; /* :m2:m1:00 */ + l = input.val[2]; /* : :l1:l0 */ + c = pmull_high(h, MODULO); /* :c2:c1:00 = reduction of h3 */ + d = pmull_low(h, MODULO); /* : :d1:d0 = reduction of h2 */ + e = veorq_u8(c, m); /* :e2:e1:00 = m2:m1:00 + c2:c1:00 */ + f = pmull_high(e, MODULO); /* : :f1:f0 = reduction of e2 */ + g = vextq_u8(ZERO, e, 8); /* : :g1:00 = e1:00 */ + n = veorq_u8(d, l); /* : :n1:n0 = d1:d0 + l1:l0 */ + o = veorq_u8(n, f); /* o1:o0 = f1:f0 + n1:n0 */ + return veorq_u8(o, g); /* = o1:o0 + g1:00 */ +} + +/* + * GCM multiplication: c = a times b in GF(2^128) + */ +void mbedtls_aesce_gcm_mult(unsigned char c[16], + const unsigned char a[16], + const unsigned char b[16]) +{ + uint8x16_t va, vb, vc; + va = vrbitq_u8(vld1q_u8(&a[0])); + vb = vrbitq_u8(vld1q_u8(&b[0])); + vc = vrbitq_u8(poly_mult_reduce(poly_mult_128(va, vb))); + vst1q_u8(&c[0], vc); +} + +#endif /* MBEDTLS_GCM_C */ + +#if defined(MBEDTLS_POP_TARGET_PRAGMA) +#if defined(__clang__) +#pragma clang attribute pop +#elif defined(__GNUC__) +#pragma GCC pop_options +#endif +#undef MBEDTLS_POP_TARGET_PRAGMA +#endif + +#endif /* MBEDTLS_AESCE_HAVE_CODE */ + +#endif /* MBEDTLS_AESCE_C */ diff --git a/vendor/mbedtls/library/aesce.h b/vendor/mbedtls/library/aesce.h new file mode 100644 index 0000000000..a14d085efa --- /dev/null +++ b/vendor/mbedtls/library/aesce.h @@ -0,0 +1,136 @@ +/** + * \file aesce.h + * + * \brief Support hardware AES acceleration on Armv8-A processors with + * the Armv8-A Cryptographic Extension. + * + * \warning These functions are only for internal use by other library + * functions; you must not call them directly. + */ +/* + * Copyright The Mbed TLS Contributors + * SPDX-License-Identifier: Apache-2.0 OR GPL-2.0-or-later + */ +#ifndef MBEDTLS_AESCE_H +#define MBEDTLS_AESCE_H + +#include "mbedtls/build_info.h" +#include "common.h" + +#include "mbedtls/aes.h" + + +#if defined(MBEDTLS_AESCE_C) \ + && defined(MBEDTLS_ARCH_IS_ARMV8_A) && defined(MBEDTLS_HAVE_NEON_INTRINSICS) \ + && (defined(MBEDTLS_COMPILER_IS_GCC) || defined(__clang__) || defined(MSC_VER)) + +/* MBEDTLS_AESCE_HAVE_CODE is defined if we have a suitable target platform, and a + * potentially suitable compiler (compiler version & flags are not checked when defining + * this). */ +#define MBEDTLS_AESCE_HAVE_CODE + +#ifdef __cplusplus +extern "C" { +#endif + +#if defined(__linux__) && !defined(MBEDTLS_AES_USE_HARDWARE_ONLY) + +extern signed char mbedtls_aesce_has_support_result; + +/** + * \brief Internal function to detect the crypto extension in CPUs. + * + * \return 1 if CPU has support for the feature, 0 otherwise + */ +int mbedtls_aesce_has_support_impl(void); + +#define MBEDTLS_AESCE_HAS_SUPPORT() (mbedtls_aesce_has_support_result == -1 ? \ + mbedtls_aesce_has_support_impl() : \ + mbedtls_aesce_has_support_result) + +#else /* defined(__linux__) && !defined(MBEDTLS_AES_USE_HARDWARE_ONLY) */ + +/* If we are not on Linux, we can't detect support so assume that it's supported. + * Similarly, assume support if MBEDTLS_AES_USE_HARDWARE_ONLY is set. + */ +#define MBEDTLS_AESCE_HAS_SUPPORT() 1 + +#endif /* defined(__linux__) && !defined(MBEDTLS_AES_USE_HARDWARE_ONLY) */ + +/** + * \brief Internal AES-ECB block encryption and decryption + * + * \warning This assumes that the context specifies either 10, 12 or 14 + * rounds and will behave incorrectly if this is not the case. + * + * \param ctx AES context + * \param mode MBEDTLS_AES_ENCRYPT or MBEDTLS_AES_DECRYPT + * \param input 16-byte input block + * \param output 16-byte output block + * + * \return 0 on success (cannot fail) + */ +int mbedtls_aesce_crypt_ecb(mbedtls_aes_context *ctx, + int mode, + const unsigned char input[16], + unsigned char output[16]); + +/** + * \brief Internal GCM multiplication: c = a * b in GF(2^128) + * + * \note This function is only for internal use by other library + * functions; you must not call it directly. + * + * \param c Result + * \param a First operand + * \param b Second operand + * + * \note Both operands and result are bit strings interpreted as + * elements of GF(2^128) as per the GCM spec. + */ +void mbedtls_aesce_gcm_mult(unsigned char c[16], + const unsigned char a[16], + const unsigned char b[16]); + + +#if !defined(MBEDTLS_BLOCK_CIPHER_NO_DECRYPT) +/** + * \brief Internal round key inversion. This function computes + * decryption round keys from the encryption round keys. + * + * \param invkey Round keys for the equivalent inverse cipher + * \param fwdkey Original round keys (for encryption) + * \param nr Number of rounds (that is, number of round keys minus one) + */ +void mbedtls_aesce_inverse_key(unsigned char *invkey, + const unsigned char *fwdkey, + int nr); +#endif /* !MBEDTLS_BLOCK_CIPHER_NO_DECRYPT */ + +/** + * \brief Internal key expansion for encryption + * + * \param rk Destination buffer where the round keys are written + * \param key Encryption key + * \param bits Key size in bits (must be 128, 192 or 256) + * + * \return 0 if successful, or MBEDTLS_ERR_AES_INVALID_KEY_LENGTH + */ +int mbedtls_aesce_setkey_enc(unsigned char *rk, + const unsigned char *key, + size_t bits); + +#ifdef __cplusplus +} +#endif + +#else + +#if defined(MBEDTLS_AES_USE_HARDWARE_ONLY) && defined(MBEDTLS_ARCH_IS_ARMV8_A) +#error "AES hardware acceleration not supported on this platform / compiler" +#endif + +#endif /* MBEDTLS_AESCE_C && MBEDTLS_ARCH_IS_ARMV8_A && MBEDTLS_HAVE_NEON_INTRINSICS && + (MBEDTLS_COMPILER_IS_GCC || __clang__ || MSC_VER) */ + +#endif /* MBEDTLS_AESCE_H */ diff --git a/vendor/mbedtls/library/aesni.c b/vendor/mbedtls/library/aesni.c index 866b6cbfbf..8e5bd55ab9 100644 --- a/vendor/mbedtls/library/aesni.c +++ b/vendor/mbedtls/library/aesni.c @@ -2,19 +2,7 @@ * AES-NI support functions * * Copyright The Mbed TLS Contributors - * SPDX-License-Identifier: Apache-2.0 - * - * Licensed under the Apache License, Version 2.0 (the "License"); you may - * not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT - * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. + * SPDX-License-Identifier: Apache-2.0 OR GPL-2.0-or-later */ /* @@ -26,27 +14,35 @@ #if defined(MBEDTLS_AESNI_C) -#include "mbedtls/aesni.h" +#include "aesni.h" #include -/* *INDENT-OFF* */ -#ifndef asm -#define asm __asm -#endif -/* *INDENT-ON* */ - #if defined(MBEDTLS_AESNI_HAVE_CODE) #if MBEDTLS_AESNI_HAVE_CODE == 2 -#if !defined(_WIN32) +#if defined(__GNUC__) #include -#else +#elif defined(_MSC_VER) #include +#else +#error "`__cpuid` required by MBEDTLS_AESNI_C is not supported by the compiler" #endif #include #endif +#if defined(MBEDTLS_ARCH_IS_X86) +#if defined(MBEDTLS_COMPILER_IS_GCC) +#pragma GCC push_options +#pragma GCC target ("pclmul,sse2,aes") +#define MBEDTLS_POP_TARGET_PRAGMA +#elif defined(__clang__) && (__clang_major__ >= 5) +#pragma clang attribute push (__attribute__((target("pclmul,sse2,aes"))), apply_to=function) +#define MBEDTLS_POP_TARGET_PRAGMA +#endif +#endif + +#if !defined(MBEDTLS_AES_USE_HARDWARE_ONLY) /* * AES-NI support detection routine */ @@ -57,7 +53,7 @@ int mbedtls_aesni_has_support(unsigned int what) if (!done) { #if MBEDTLS_AESNI_HAVE_CODE == 2 - static unsigned info[4] = { 0, 0, 0, 0 }; + static int info[4] = { 0, 0, 0, 0 }; #if defined(_MSC_VER) __cpuid(info, 1); #else @@ -76,6 +72,7 @@ int mbedtls_aesni_has_support(unsigned int what) return (c & what) != 0; } +#endif /* !MBEDTLS_AES_USE_HARDWARE_ONLY */ #if MBEDTLS_AESNI_HAVE_CODE == 2 @@ -87,7 +84,7 @@ int mbedtls_aesni_crypt_ecb(mbedtls_aes_context *ctx, const unsigned char input[16], unsigned char output[16]) { - const __m128i *rk = (const __m128i *) (ctx->rk); + const __m128i *rk = (const __m128i *) (ctx->buf + ctx->rk_offset); unsigned nr = ctx->nr; // Number of remaining rounds // Load round key 0 @@ -97,14 +94,19 @@ int mbedtls_aesni_crypt_ecb(mbedtls_aes_context *ctx, ++rk; --nr; - if (mode == 0) { +#if !defined(MBEDTLS_BLOCK_CIPHER_NO_DECRYPT) + if (mode == MBEDTLS_AES_DECRYPT) { while (nr != 0) { state = _mm_aesdec_si128(state, *rk); ++rk; --nr; } state = _mm_aesdeclast_si128(state, *rk); - } else { + } else +#else + (void) mode; +#endif + { while (nr != 0) { state = _mm_aesenc_si128(state, *rk); ++rk; @@ -191,7 +193,7 @@ void mbedtls_aesni_gcm_mult(unsigned char c[16], const unsigned char a[16], const unsigned char b[16]) { - __m128i aa, bb, cc, dd; + __m128i aa = { 0 }, bb = { 0 }, cc, dd; /* The inputs are in big-endian order, so byte-reverse them */ for (size_t i = 0; i < 16; i++) { @@ -221,6 +223,7 @@ void mbedtls_aesni_gcm_mult(unsigned char c[16], /* * Compute decryption round keys from encryption round keys */ +#if !defined(MBEDTLS_BLOCK_CIPHER_NO_DECRYPT) void mbedtls_aesni_inverse_key(unsigned char *invkey, const unsigned char *fwdkey, int nr) { @@ -233,6 +236,7 @@ void mbedtls_aesni_inverse_key(unsigned char *invkey, } *ik = *fk; } +#endif /* * Key expansion, 128-bit case @@ -281,6 +285,7 @@ static void aesni_setkey_enc_128(unsigned char *rk_bytes, /* * Key expansion, 192-bit case */ +#if !defined(MBEDTLS_AES_ONLY_128_BIT_KEY_LENGTH) static void aesni_set_rk_192(__m128i *state0, __m128i *state1, __m128i xword, unsigned char *rk) { @@ -335,10 +340,12 @@ static void aesni_setkey_enc_192(unsigned char *rk, aesni_set_rk_192(&state0, &state1, _mm_aeskeygenassist_si128(state1, 0x40), rk + 24 * 7); aesni_set_rk_192(&state0, &state1, _mm_aeskeygenassist_si128(state1, 0x80), rk + 24 * 8); } +#endif /* !MBEDTLS_AES_ONLY_128_BIT_KEY_LENGTH */ /* * Key expansion, 256-bit case */ +#if !defined(MBEDTLS_AES_ONLY_128_BIT_KEY_LENGTH) static void aesni_set_rk_256(__m128i state0, __m128i state1, __m128i xword, __m128i *rk0, __m128i *rk1) { @@ -395,6 +402,16 @@ static void aesni_setkey_enc_256(unsigned char *rk_bytes, aesni_set_rk_256(rk[10], rk[11], _mm_aeskeygenassist_si128(rk[11], 0x20), &rk[12], &rk[13]); aesni_set_rk_256(rk[12], rk[13], _mm_aeskeygenassist_si128(rk[13], 0x40), &rk[14], &rk[15]); } +#endif /* !MBEDTLS_AES_ONLY_128_BIT_KEY_LENGTH */ + +#if defined(MBEDTLS_POP_TARGET_PRAGMA) +#if defined(__clang__) +#pragma clang attribute pop +#elif defined(__GNUC__) +#pragma GCC pop_options +#endif +#undef MBEDTLS_POP_TARGET_PRAGMA +#endif #else /* MBEDTLS_AESNI_HAVE_CODE == 1 */ @@ -455,6 +472,7 @@ int mbedtls_aesni_crypt_ecb(mbedtls_aes_context *ctx, "jnz 1b \n\t" "movdqu (%1), %%xmm1 \n\t" // load round key AESENCLAST(xmm1_xmm0) // last round +#if !defined(MBEDTLS_BLOCK_CIPHER_NO_DECRYPT) "jmp 3f \n\t" "2: \n\t" // decryption loop @@ -465,11 +483,12 @@ int mbedtls_aesni_crypt_ecb(mbedtls_aes_context *ctx, "jnz 2b \n\t" "movdqu (%1), %%xmm1 \n\t" // load round key AESDECLAST(xmm1_xmm0) // last round +#endif "3: \n\t" "movdqu %%xmm0, (%4) \n\t" // export output : - : "r" (ctx->nr), "r" (ctx->rk), "r" (mode), "r" (input), "r" (output) + : "r" (ctx->nr), "r" (ctx->buf + ctx->rk_offset), "r" (mode), "r" (input), "r" (output) : "memory", "cc", "xmm0", "xmm1"); @@ -591,6 +610,7 @@ void mbedtls_aesni_gcm_mult(unsigned char c[16], /* * Compute decryption round keys from encryption round keys */ +#if !defined(MBEDTLS_BLOCK_CIPHER_NO_DECRYPT) void mbedtls_aesni_inverse_key(unsigned char *invkey, const unsigned char *fwdkey, int nr) { @@ -610,6 +630,7 @@ void mbedtls_aesni_inverse_key(unsigned char *invkey, memcpy(ik, fk, 16); } +#endif /* * Key expansion, 128-bit case @@ -664,6 +685,7 @@ static void aesni_setkey_enc_128(unsigned char *rk, /* * Key expansion, 192-bit case */ +#if !defined(MBEDTLS_AES_ONLY_128_BIT_KEY_LENGTH) static void aesni_setkey_enc_192(unsigned char *rk, const unsigned char *key) { @@ -717,10 +739,12 @@ static void aesni_setkey_enc_192(unsigned char *rk, : "r" (rk), "r" (key) : "memory", "cc", "0"); } +#endif /* !MBEDTLS_AES_ONLY_128_BIT_KEY_LENGTH */ /* * Key expansion, 256-bit case */ +#if !defined(MBEDTLS_AES_ONLY_128_BIT_KEY_LENGTH) static void aesni_setkey_enc_256(unsigned char *rk, const unsigned char *key) { @@ -783,6 +807,7 @@ static void aesni_setkey_enc_256(unsigned char *rk, : "r" (rk), "r" (key) : "memory", "cc", "0"); } +#endif /* !MBEDTLS_AES_ONLY_128_BIT_KEY_LENGTH */ #endif /* MBEDTLS_AESNI_HAVE_CODE */ @@ -795,8 +820,10 @@ int mbedtls_aesni_setkey_enc(unsigned char *rk, { switch (bits) { case 128: aesni_setkey_enc_128(rk, key); break; +#if !defined(MBEDTLS_AES_ONLY_128_BIT_KEY_LENGTH) case 192: aesni_setkey_enc_192(rk, key); break; case 256: aesni_setkey_enc_256(rk, key); break; +#endif /* !MBEDTLS_AES_ONLY_128_BIT_KEY_LENGTH */ default: return MBEDTLS_ERR_AES_INVALID_KEY_LENGTH; } diff --git a/vendor/mbedtls/include/mbedtls/aesni.h b/vendor/mbedtls/library/aesni.h similarity index 70% rename from vendor/mbedtls/include/mbedtls/aesni.h rename to vendor/mbedtls/library/aesni.h index 0da40a0a3c..59e27afd3e 100644 --- a/vendor/mbedtls/include/mbedtls/aesni.h +++ b/vendor/mbedtls/library/aesni.h @@ -8,57 +8,26 @@ */ /* * Copyright The Mbed TLS Contributors - * SPDX-License-Identifier: Apache-2.0 - * - * Licensed under the Apache License, Version 2.0 (the "License"); you may - * not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT - * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. + * SPDX-License-Identifier: Apache-2.0 OR GPL-2.0-or-later */ #ifndef MBEDTLS_AESNI_H #define MBEDTLS_AESNI_H -#if !defined(MBEDTLS_CONFIG_FILE) -#include "mbedtls/config.h" -#else -#include MBEDTLS_CONFIG_FILE -#endif +#include "mbedtls/build_info.h" #include "mbedtls/aes.h" #define MBEDTLS_AESNI_AES 0x02000000u #define MBEDTLS_AESNI_CLMUL 0x00000002u -#if !defined(MBEDTLS_HAVE_X86_64) && \ - (defined(__amd64__) || defined(__x86_64__) || \ - defined(_M_X64) || defined(_M_AMD64)) && \ - !defined(_M_ARM64EC) -#define MBEDTLS_HAVE_X86_64 -#endif - -#if !defined(MBEDTLS_HAVE_X86) && \ - (defined(__i386__) || defined(_M_IX86)) -#define MBEDTLS_HAVE_X86 -#endif - #if defined(MBEDTLS_AESNI_C) && \ - (defined(MBEDTLS_HAVE_X86_64) || defined(MBEDTLS_HAVE_X86)) + (defined(MBEDTLS_ARCH_IS_X64) || defined(MBEDTLS_ARCH_IS_X86)) /* Can we do AESNI with intrinsics? * (Only implemented with certain compilers, only for certain targets.) - * - * NOTE: MBEDTLS_AESNI_HAVE_INTRINSICS and MBEDTLS_AESNI_HAVE_CODE are internal - * macros that may change in future releases. */ #undef MBEDTLS_AESNI_HAVE_INTRINSICS -#if defined(_MSC_VER) +#if defined(_MSC_VER) && !defined(__clang__) /* Visual Studio supports AESNI intrinsics since VS 2008 SP1. We only support * VS 2013 and up for other reasons anyway, so no need to check the version. */ #define MBEDTLS_AESNI_HAVE_INTRINSICS @@ -66,24 +35,30 @@ /* GCC-like compilers: currently, we only support intrinsics if the requisite * target flag is enabled when building the library (e.g. `gcc -mpclmul -msse2` * or `clang -maes -mpclmul`). */ -#if defined(__GNUC__) && defined(__AES__) && defined(__PCLMUL__) +#if (defined(__GNUC__) || defined(__clang__)) && defined(__AES__) && defined(__PCLMUL__) +#define MBEDTLS_AESNI_HAVE_INTRINSICS +#endif +/* For 32-bit, we only support intrinsics */ +#if defined(MBEDTLS_ARCH_IS_X86) && (defined(__GNUC__) || defined(__clang__)) #define MBEDTLS_AESNI_HAVE_INTRINSICS #endif -/* Choose the implementation of AESNI, if one is available. */ -#undef MBEDTLS_AESNI_HAVE_CODE -/* To minimize disruption when releasing the intrinsics-based implementation, - * favor the assembly-based implementation if it's available. We intend to - * revise this in a later release of Mbed TLS 3.x. In the long run, we will - * likely remove the assembly implementation. */ -#if defined(MBEDTLS_HAVE_ASM) && \ - defined(__GNUC__) && defined(MBEDTLS_HAVE_X86_64) +/* Choose the implementation of AESNI, if one is available. + * + * Favor the intrinsics-based implementation if it's available, for better + * maintainability. + * Performance is about the same (see #7380). + * In the long run, we will likely remove the assembly implementation. */ +#if defined(MBEDTLS_AESNI_HAVE_INTRINSICS) +#define MBEDTLS_AESNI_HAVE_CODE 2 // via intrinsics +#elif defined(MBEDTLS_HAVE_ASM) && \ + (defined(__GNUC__) || defined(__clang__)) && defined(MBEDTLS_ARCH_IS_X64) /* Can we do AESNI with inline assembly? * (Only implemented with gas syntax, only for 64-bit.) */ #define MBEDTLS_AESNI_HAVE_CODE 1 // via assembly -#elif defined(MBEDTLS_AESNI_HAVE_INTRINSICS) -#define MBEDTLS_AESNI_HAVE_CODE 2 // via intrinsics +#else +#error "MBEDTLS_AESNI_C defined, but neither intrinsics nor assembly available" #endif #if defined(MBEDTLS_AESNI_HAVE_CODE) @@ -103,7 +78,11 @@ extern "C" { * * \return 1 if CPU has support for the feature, 0 otherwise */ +#if !defined(MBEDTLS_AES_USE_HARDWARE_ONLY) int mbedtls_aesni_has_support(unsigned int what); +#else +#define mbedtls_aesni_has_support(what) 1 +#endif /** * \brief Internal AES-NI AES-ECB block encryption and decryption @@ -140,6 +119,7 @@ void mbedtls_aesni_gcm_mult(unsigned char c[16], const unsigned char a[16], const unsigned char b[16]); +#if !defined(MBEDTLS_BLOCK_CIPHER_NO_DECRYPT) /** * \brief Internal round key inversion. This function computes * decryption round keys from the encryption round keys. @@ -154,6 +134,7 @@ void mbedtls_aesni_gcm_mult(unsigned char c[16], void mbedtls_aesni_inverse_key(unsigned char *invkey, const unsigned char *fwdkey, int nr); +#endif /* !MBEDTLS_BLOCK_CIPHER_NO_DECRYPT */ /** * \brief Internal key expansion for encryption @@ -176,6 +157,6 @@ int mbedtls_aesni_setkey_enc(unsigned char *rk, #endif #endif /* MBEDTLS_AESNI_HAVE_CODE */ -#endif /* MBEDTLS_AESNI_C && (MBEDTLS_HAVE_X86_64 || MBEDTLS_HAVE_X86) */ +#endif /* MBEDTLS_AESNI_C && (MBEDTLS_ARCH_IS_X64 || MBEDTLS_ARCH_IS_X86) */ #endif /* MBEDTLS_AESNI_H */ diff --git a/vendor/mbedtls/library/alignment.h b/vendor/mbedtls/library/alignment.h new file mode 100644 index 0000000000..a17001dd91 --- /dev/null +++ b/vendor/mbedtls/library/alignment.h @@ -0,0 +1,684 @@ +/** + * \file alignment.h + * + * \brief Utility code for dealing with unaligned memory accesses + */ +/* + * Copyright The Mbed TLS Contributors + * SPDX-License-Identifier: Apache-2.0 OR GPL-2.0-or-later + */ + +#ifndef MBEDTLS_LIBRARY_ALIGNMENT_H +#define MBEDTLS_LIBRARY_ALIGNMENT_H + +#include +#include +#include + +/* + * Define MBEDTLS_EFFICIENT_UNALIGNED_ACCESS for architectures where unaligned memory + * accesses are known to be efficient. + * + * All functions defined here will behave correctly regardless, but might be less + * efficient when this is not defined. + */ +#if defined(__ARM_FEATURE_UNALIGNED) \ + || defined(MBEDTLS_ARCH_IS_X86) || defined(MBEDTLS_ARCH_IS_X64) \ + || defined(MBEDTLS_PLATFORM_IS_WINDOWS_ON_ARM64) +/* + * __ARM_FEATURE_UNALIGNED is defined where appropriate by armcc, gcc 7, clang 9 + * (and later versions) for Arm v7 and later; all x86 platforms should have + * efficient unaligned access. + * + * https://learn.microsoft.com/en-us/cpp/build/arm64-windows-abi-conventions?view=msvc-170#alignment + * specifies that on Windows-on-Arm64, unaligned access is safe (except for uncached + * device memory). + */ +#define MBEDTLS_EFFICIENT_UNALIGNED_ACCESS +#endif + +#if defined(__IAR_SYSTEMS_ICC__) && \ + (defined(MBEDTLS_ARCH_IS_ARM64) || defined(MBEDTLS_ARCH_IS_ARM32) \ + || defined(__ICCRX__) || defined(__ICCRL78__) || defined(__ICCRISCV__)) +#pragma language=save +#pragma language=extended +#define MBEDTLS_POP_IAR_LANGUAGE_PRAGMA +/* IAR recommend this technique for accessing unaligned data in + * https://www.iar.com/knowledge/support/technical-notes/compiler/accessing-unaligned-data + * This results in a single load / store instruction (if unaligned access is supported). + * According to that document, this is only supported on certain architectures. + */ + #define UINT_UNALIGNED +typedef uint16_t __packed mbedtls_uint16_unaligned_t; +typedef uint32_t __packed mbedtls_uint32_unaligned_t; +typedef uint64_t __packed mbedtls_uint64_unaligned_t; +#elif defined(MBEDTLS_COMPILER_IS_GCC) && (MBEDTLS_GCC_VERSION >= 40504) && \ + ((MBEDTLS_GCC_VERSION < 60300) || (!defined(MBEDTLS_EFFICIENT_UNALIGNED_ACCESS))) +/* + * gcc may generate a branch to memcpy for calls like `memcpy(dest, src, 4)` rather than + * generating some LDR or LDRB instructions (similar for stores). + * + * This is architecture dependent: x86-64 seems fine even with old gcc; 32-bit Arm + * is affected. To keep it simple, we enable for all architectures. + * + * For versions of gcc < 5.4.0 this issue always happens. + * For gcc < 6.3.0, this issue happens at -O0 + * For all versions, this issue happens iff unaligned access is not supported. + * + * For gcc 4.x, this implementation will generate byte-by-byte loads even if unaligned access is + * supported, which is correct but not optimal. + * + * For performance (and code size, in some cases), we want to avoid the branch and just generate + * some inline load/store instructions since the access is small and constant-size. + * + * The manual states: + * "The packed attribute specifies that a variable or structure field should have the smallest + * possible alignment—one byte for a variable" + * https://gcc.gnu.org/onlinedocs/gcc-4.5.4/gcc/Variable-Attributes.html + * + * Previous implementations used __attribute__((__aligned__(1)), but had issues with a gcc bug: + * https://gcc.gnu.org/bugzilla/show_bug.cgi?id=94662 + * + * Tested with several versions of GCC from 4.5.0 up to 13.2.0 + * We don't enable for older than 4.5.0 as this has not been tested. + */ + #define UINT_UNALIGNED_STRUCT +typedef struct { + uint16_t x; +} __attribute__((packed)) mbedtls_uint16_unaligned_t; +typedef struct { + uint32_t x; +} __attribute__((packed)) mbedtls_uint32_unaligned_t; +typedef struct { + uint64_t x; +} __attribute__((packed)) mbedtls_uint64_unaligned_t; + #endif + +/* + * We try to force mbedtls_(get|put)_unaligned_uintXX to be always inline, because this results + * in code that is both smaller and faster. IAR and gcc both benefit from this when optimising + * for size. + */ + +/** + * Read the unsigned 16 bits integer from the given address, which need not + * be aligned. + * + * \param p pointer to 2 bytes of data + * \return Data at the given address + */ +#if defined(__IAR_SYSTEMS_ICC__) +#pragma inline = forced +#elif defined(__GNUC__) +__attribute__((always_inline)) +#endif +static inline uint16_t mbedtls_get_unaligned_uint16(const void *p) +{ + uint16_t r; +#if defined(UINT_UNALIGNED) + mbedtls_uint16_unaligned_t *p16 = (mbedtls_uint16_unaligned_t *) p; + r = *p16; +#elif defined(UINT_UNALIGNED_STRUCT) + mbedtls_uint16_unaligned_t *p16 = (mbedtls_uint16_unaligned_t *) p; + r = p16->x; +#else + memcpy(&r, p, sizeof(r)); +#endif + return r; +} + +/** + * Write the unsigned 16 bits integer to the given address, which need not + * be aligned. + * + * \param p pointer to 2 bytes of data + * \param x data to write + */ +#if defined(__IAR_SYSTEMS_ICC__) +#pragma inline = forced +#elif defined(__GNUC__) +__attribute__((always_inline)) +#endif +static inline void mbedtls_put_unaligned_uint16(void *p, uint16_t x) +{ +#if defined(UINT_UNALIGNED) + mbedtls_uint16_unaligned_t *p16 = (mbedtls_uint16_unaligned_t *) p; + *p16 = x; +#elif defined(UINT_UNALIGNED_STRUCT) + mbedtls_uint16_unaligned_t *p16 = (mbedtls_uint16_unaligned_t *) p; + p16->x = x; +#else + memcpy(p, &x, sizeof(x)); +#endif +} + +/** + * Read the unsigned 32 bits integer from the given address, which need not + * be aligned. + * + * \param p pointer to 4 bytes of data + * \return Data at the given address + */ +#if defined(__IAR_SYSTEMS_ICC__) +#pragma inline = forced +#elif defined(__GNUC__) +__attribute__((always_inline)) +#endif +static inline uint32_t mbedtls_get_unaligned_uint32(const void *p) +{ + uint32_t r; +#if defined(UINT_UNALIGNED) + mbedtls_uint32_unaligned_t *p32 = (mbedtls_uint32_unaligned_t *) p; + r = *p32; +#elif defined(UINT_UNALIGNED_STRUCT) + mbedtls_uint32_unaligned_t *p32 = (mbedtls_uint32_unaligned_t *) p; + r = p32->x; +#else + memcpy(&r, p, sizeof(r)); +#endif + return r; +} + +/** + * Write the unsigned 32 bits integer to the given address, which need not + * be aligned. + * + * \param p pointer to 4 bytes of data + * \param x data to write + */ +#if defined(__IAR_SYSTEMS_ICC__) +#pragma inline = forced +#elif defined(__GNUC__) +__attribute__((always_inline)) +#endif +static inline void mbedtls_put_unaligned_uint32(void *p, uint32_t x) +{ +#if defined(UINT_UNALIGNED) + mbedtls_uint32_unaligned_t *p32 = (mbedtls_uint32_unaligned_t *) p; + *p32 = x; +#elif defined(UINT_UNALIGNED_STRUCT) + mbedtls_uint32_unaligned_t *p32 = (mbedtls_uint32_unaligned_t *) p; + p32->x = x; +#else + memcpy(p, &x, sizeof(x)); +#endif +} + +/** + * Read the unsigned 64 bits integer from the given address, which need not + * be aligned. + * + * \param p pointer to 8 bytes of data + * \return Data at the given address + */ +#if defined(__IAR_SYSTEMS_ICC__) +#pragma inline = forced +#elif defined(__GNUC__) +__attribute__((always_inline)) +#endif +static inline uint64_t mbedtls_get_unaligned_uint64(const void *p) +{ + uint64_t r; +#if defined(UINT_UNALIGNED) + mbedtls_uint64_unaligned_t *p64 = (mbedtls_uint64_unaligned_t *) p; + r = *p64; +#elif defined(UINT_UNALIGNED_STRUCT) + mbedtls_uint64_unaligned_t *p64 = (mbedtls_uint64_unaligned_t *) p; + r = p64->x; +#else + memcpy(&r, p, sizeof(r)); +#endif + return r; +} + +/** + * Write the unsigned 64 bits integer to the given address, which need not + * be aligned. + * + * \param p pointer to 8 bytes of data + * \param x data to write + */ +#if defined(__IAR_SYSTEMS_ICC__) +#pragma inline = forced +#elif defined(__GNUC__) +__attribute__((always_inline)) +#endif +static inline void mbedtls_put_unaligned_uint64(void *p, uint64_t x) +{ +#if defined(UINT_UNALIGNED) + mbedtls_uint64_unaligned_t *p64 = (mbedtls_uint64_unaligned_t *) p; + *p64 = x; +#elif defined(UINT_UNALIGNED_STRUCT) + mbedtls_uint64_unaligned_t *p64 = (mbedtls_uint64_unaligned_t *) p; + p64->x = x; +#else + memcpy(p, &x, sizeof(x)); +#endif +} + +#if defined(MBEDTLS_POP_IAR_LANGUAGE_PRAGMA) +#pragma language=restore +#endif + +/** Byte Reading Macros + * + * Given a multi-byte integer \p x, MBEDTLS_BYTE_n retrieves the n-th + * byte from x, where byte 0 is the least significant byte. + */ +#define MBEDTLS_BYTE_0(x) ((uint8_t) ((x) & 0xff)) +#define MBEDTLS_BYTE_1(x) ((uint8_t) (((x) >> 8) & 0xff)) +#define MBEDTLS_BYTE_2(x) ((uint8_t) (((x) >> 16) & 0xff)) +#define MBEDTLS_BYTE_3(x) ((uint8_t) (((x) >> 24) & 0xff)) +#define MBEDTLS_BYTE_4(x) ((uint8_t) (((x) >> 32) & 0xff)) +#define MBEDTLS_BYTE_5(x) ((uint8_t) (((x) >> 40) & 0xff)) +#define MBEDTLS_BYTE_6(x) ((uint8_t) (((x) >> 48) & 0xff)) +#define MBEDTLS_BYTE_7(x) ((uint8_t) (((x) >> 56) & 0xff)) + +/* + * Detect GCC built-in byteswap routines + */ +#if defined(__GNUC__) && defined(__GNUC_PREREQ) +#if __GNUC_PREREQ(4, 8) +#define MBEDTLS_BSWAP16 __builtin_bswap16 +#endif /* __GNUC_PREREQ(4,8) */ +#if __GNUC_PREREQ(4, 3) +#define MBEDTLS_BSWAP32 __builtin_bswap32 +#define MBEDTLS_BSWAP64 __builtin_bswap64 +#endif /* __GNUC_PREREQ(4,3) */ +#endif /* defined(__GNUC__) && defined(__GNUC_PREREQ) */ + +/* + * Detect Clang built-in byteswap routines + */ +#if defined(__clang__) && defined(__has_builtin) +#if __has_builtin(__builtin_bswap16) && !defined(MBEDTLS_BSWAP16) +#define MBEDTLS_BSWAP16 __builtin_bswap16 +#endif /* __has_builtin(__builtin_bswap16) */ +#if __has_builtin(__builtin_bswap32) && !defined(MBEDTLS_BSWAP32) +#define MBEDTLS_BSWAP32 __builtin_bswap32 +#endif /* __has_builtin(__builtin_bswap32) */ +#if __has_builtin(__builtin_bswap64) && !defined(MBEDTLS_BSWAP64) +#define MBEDTLS_BSWAP64 __builtin_bswap64 +#endif /* __has_builtin(__builtin_bswap64) */ +#endif /* defined(__clang__) && defined(__has_builtin) */ + +/* + * Detect MSVC built-in byteswap routines + */ +#if defined(_MSC_VER) +#if !defined(MBEDTLS_BSWAP16) +#define MBEDTLS_BSWAP16 _byteswap_ushort +#endif +#if !defined(MBEDTLS_BSWAP32) +#define MBEDTLS_BSWAP32 _byteswap_ulong +#endif +#if !defined(MBEDTLS_BSWAP64) +#define MBEDTLS_BSWAP64 _byteswap_uint64 +#endif +#endif /* defined(_MSC_VER) */ + +/* Detect armcc built-in byteswap routine */ +#if defined(__ARMCC_VERSION) && (__ARMCC_VERSION >= 410000) && !defined(MBEDTLS_BSWAP32) +#if defined(__ARM_ACLE) /* ARM Compiler 6 - earlier versions don't need a header */ +#include +#endif +#define MBEDTLS_BSWAP32 __rev +#endif + +/* Detect IAR built-in byteswap routine */ +#if defined(__IAR_SYSTEMS_ICC__) +#if defined(__ARM_ACLE) +#include +#define MBEDTLS_BSWAP16(x) ((uint16_t) __rev16((uint32_t) (x))) +#define MBEDTLS_BSWAP32 __rev +#define MBEDTLS_BSWAP64 __revll +#endif +#endif + +/* + * Where compiler built-ins are not present, fall back to C code that the + * compiler may be able to detect and transform into the relevant bswap or + * similar instruction. + */ +#if !defined(MBEDTLS_BSWAP16) +static inline uint16_t mbedtls_bswap16(uint16_t x) +{ + return + (x & 0x00ff) << 8 | + (x & 0xff00) >> 8; +} +#define MBEDTLS_BSWAP16 mbedtls_bswap16 +#endif /* !defined(MBEDTLS_BSWAP16) */ + +#if !defined(MBEDTLS_BSWAP32) +static inline uint32_t mbedtls_bswap32(uint32_t x) +{ + return + (x & 0x000000ff) << 24 | + (x & 0x0000ff00) << 8 | + (x & 0x00ff0000) >> 8 | + (x & 0xff000000) >> 24; +} +#define MBEDTLS_BSWAP32 mbedtls_bswap32 +#endif /* !defined(MBEDTLS_BSWAP32) */ + +#if !defined(MBEDTLS_BSWAP64) +static inline uint64_t mbedtls_bswap64(uint64_t x) +{ + return + (x & 0x00000000000000ffULL) << 56 | + (x & 0x000000000000ff00ULL) << 40 | + (x & 0x0000000000ff0000ULL) << 24 | + (x & 0x00000000ff000000ULL) << 8 | + (x & 0x000000ff00000000ULL) >> 8 | + (x & 0x0000ff0000000000ULL) >> 24 | + (x & 0x00ff000000000000ULL) >> 40 | + (x & 0xff00000000000000ULL) >> 56; +} +#define MBEDTLS_BSWAP64 mbedtls_bswap64 +#endif /* !defined(MBEDTLS_BSWAP64) */ + +#if !defined(__BYTE_ORDER__) + +#if defined(__LITTLE_ENDIAN__) +/* IAR defines __xxx_ENDIAN__, but not __BYTE_ORDER__ */ +#define MBEDTLS_IS_BIG_ENDIAN 0 +#elif defined(__BIG_ENDIAN__) +#define MBEDTLS_IS_BIG_ENDIAN 1 +#else +static const uint16_t mbedtls_byte_order_detector = { 0x100 }; +#define MBEDTLS_IS_BIG_ENDIAN (*((unsigned char *) (&mbedtls_byte_order_detector)) == 0x01) +#endif + +#else + +#if (__BYTE_ORDER__) == (__ORDER_BIG_ENDIAN__) +#define MBEDTLS_IS_BIG_ENDIAN 1 +#else +#define MBEDTLS_IS_BIG_ENDIAN 0 +#endif + +#endif /* !defined(__BYTE_ORDER__) */ + +/** + * Get the unsigned 32 bits integer corresponding to four bytes in + * big-endian order (MSB first). + * + * \param data Base address of the memory to get the four bytes from. + * \param offset Offset from \p data of the first and most significant + * byte of the four bytes to build the 32 bits unsigned + * integer from. + */ +#define MBEDTLS_GET_UINT32_BE(data, offset) \ + ((MBEDTLS_IS_BIG_ENDIAN) \ + ? mbedtls_get_unaligned_uint32((data) + (offset)) \ + : MBEDTLS_BSWAP32(mbedtls_get_unaligned_uint32((data) + (offset))) \ + ) + +/** + * Put in memory a 32 bits unsigned integer in big-endian order. + * + * \param n 32 bits unsigned integer to put in memory. + * \param data Base address of the memory where to put the 32 + * bits unsigned integer in. + * \param offset Offset from \p data where to put the most significant + * byte of the 32 bits unsigned integer \p n. + */ +#define MBEDTLS_PUT_UINT32_BE(n, data, offset) \ + { \ + if (MBEDTLS_IS_BIG_ENDIAN) \ + { \ + mbedtls_put_unaligned_uint32((data) + (offset), (uint32_t) (n)); \ + } \ + else \ + { \ + mbedtls_put_unaligned_uint32((data) + (offset), MBEDTLS_BSWAP32((uint32_t) (n))); \ + } \ + } + +/** + * Get the unsigned 32 bits integer corresponding to four bytes in + * little-endian order (LSB first). + * + * \param data Base address of the memory to get the four bytes from. + * \param offset Offset from \p data of the first and least significant + * byte of the four bytes to build the 32 bits unsigned + * integer from. + */ +#define MBEDTLS_GET_UINT32_LE(data, offset) \ + ((MBEDTLS_IS_BIG_ENDIAN) \ + ? MBEDTLS_BSWAP32(mbedtls_get_unaligned_uint32((data) + (offset))) \ + : mbedtls_get_unaligned_uint32((data) + (offset)) \ + ) + + +/** + * Put in memory a 32 bits unsigned integer in little-endian order. + * + * \param n 32 bits unsigned integer to put in memory. + * \param data Base address of the memory where to put the 32 + * bits unsigned integer in. + * \param offset Offset from \p data where to put the least significant + * byte of the 32 bits unsigned integer \p n. + */ +#define MBEDTLS_PUT_UINT32_LE(n, data, offset) \ + { \ + if (MBEDTLS_IS_BIG_ENDIAN) \ + { \ + mbedtls_put_unaligned_uint32((data) + (offset), MBEDTLS_BSWAP32((uint32_t) (n))); \ + } \ + else \ + { \ + mbedtls_put_unaligned_uint32((data) + (offset), ((uint32_t) (n))); \ + } \ + } + +/** + * Get the unsigned 16 bits integer corresponding to two bytes in + * little-endian order (LSB first). + * + * \param data Base address of the memory to get the two bytes from. + * \param offset Offset from \p data of the first and least significant + * byte of the two bytes to build the 16 bits unsigned + * integer from. + */ +#define MBEDTLS_GET_UINT16_LE(data, offset) \ + ((MBEDTLS_IS_BIG_ENDIAN) \ + ? MBEDTLS_BSWAP16(mbedtls_get_unaligned_uint16((data) + (offset))) \ + : mbedtls_get_unaligned_uint16((data) + (offset)) \ + ) + +/** + * Put in memory a 16 bits unsigned integer in little-endian order. + * + * \param n 16 bits unsigned integer to put in memory. + * \param data Base address of the memory where to put the 16 + * bits unsigned integer in. + * \param offset Offset from \p data where to put the least significant + * byte of the 16 bits unsigned integer \p n. + */ +#define MBEDTLS_PUT_UINT16_LE(n, data, offset) \ + { \ + if (MBEDTLS_IS_BIG_ENDIAN) \ + { \ + mbedtls_put_unaligned_uint16((data) + (offset), MBEDTLS_BSWAP16((uint16_t) (n))); \ + } \ + else \ + { \ + mbedtls_put_unaligned_uint16((data) + (offset), (uint16_t) (n)); \ + } \ + } + +/** + * Get the unsigned 16 bits integer corresponding to two bytes in + * big-endian order (MSB first). + * + * \param data Base address of the memory to get the two bytes from. + * \param offset Offset from \p data of the first and most significant + * byte of the two bytes to build the 16 bits unsigned + * integer from. + */ +#define MBEDTLS_GET_UINT16_BE(data, offset) \ + ((MBEDTLS_IS_BIG_ENDIAN) \ + ? mbedtls_get_unaligned_uint16((data) + (offset)) \ + : MBEDTLS_BSWAP16(mbedtls_get_unaligned_uint16((data) + (offset))) \ + ) + +/** + * Put in memory a 16 bits unsigned integer in big-endian order. + * + * \param n 16 bits unsigned integer to put in memory. + * \param data Base address of the memory where to put the 16 + * bits unsigned integer in. + * \param offset Offset from \p data where to put the most significant + * byte of the 16 bits unsigned integer \p n. + */ +#define MBEDTLS_PUT_UINT16_BE(n, data, offset) \ + { \ + if (MBEDTLS_IS_BIG_ENDIAN) \ + { \ + mbedtls_put_unaligned_uint16((data) + (offset), (uint16_t) (n)); \ + } \ + else \ + { \ + mbedtls_put_unaligned_uint16((data) + (offset), MBEDTLS_BSWAP16((uint16_t) (n))); \ + } \ + } + +/** + * Get the unsigned 24 bits integer corresponding to three bytes in + * big-endian order (MSB first). + * + * \param data Base address of the memory to get the three bytes from. + * \param offset Offset from \p data of the first and most significant + * byte of the three bytes to build the 24 bits unsigned + * integer from. + */ +#define MBEDTLS_GET_UINT24_BE(data, offset) \ + ( \ + ((uint32_t) (data)[(offset)] << 16) \ + | ((uint32_t) (data)[(offset) + 1] << 8) \ + | ((uint32_t) (data)[(offset) + 2]) \ + ) + +/** + * Put in memory a 24 bits unsigned integer in big-endian order. + * + * \param n 24 bits unsigned integer to put in memory. + * \param data Base address of the memory where to put the 24 + * bits unsigned integer in. + * \param offset Offset from \p data where to put the most significant + * byte of the 24 bits unsigned integer \p n. + */ +#define MBEDTLS_PUT_UINT24_BE(n, data, offset) \ + { \ + (data)[(offset)] = MBEDTLS_BYTE_2(n); \ + (data)[(offset) + 1] = MBEDTLS_BYTE_1(n); \ + (data)[(offset) + 2] = MBEDTLS_BYTE_0(n); \ + } + +/** + * Get the unsigned 24 bits integer corresponding to three bytes in + * little-endian order (LSB first). + * + * \param data Base address of the memory to get the three bytes from. + * \param offset Offset from \p data of the first and least significant + * byte of the three bytes to build the 24 bits unsigned + * integer from. + */ +#define MBEDTLS_GET_UINT24_LE(data, offset) \ + ( \ + ((uint32_t) (data)[(offset)]) \ + | ((uint32_t) (data)[(offset) + 1] << 8) \ + | ((uint32_t) (data)[(offset) + 2] << 16) \ + ) + +/** + * Put in memory a 24 bits unsigned integer in little-endian order. + * + * \param n 24 bits unsigned integer to put in memory. + * \param data Base address of the memory where to put the 24 + * bits unsigned integer in. + * \param offset Offset from \p data where to put the least significant + * byte of the 24 bits unsigned integer \p n. + */ +#define MBEDTLS_PUT_UINT24_LE(n, data, offset) \ + { \ + (data)[(offset)] = MBEDTLS_BYTE_0(n); \ + (data)[(offset) + 1] = MBEDTLS_BYTE_1(n); \ + (data)[(offset) + 2] = MBEDTLS_BYTE_2(n); \ + } + +/** + * Get the unsigned 64 bits integer corresponding to eight bytes in + * big-endian order (MSB first). + * + * \param data Base address of the memory to get the eight bytes from. + * \param offset Offset from \p data of the first and most significant + * byte of the eight bytes to build the 64 bits unsigned + * integer from. + */ +#define MBEDTLS_GET_UINT64_BE(data, offset) \ + ((MBEDTLS_IS_BIG_ENDIAN) \ + ? mbedtls_get_unaligned_uint64((data) + (offset)) \ + : MBEDTLS_BSWAP64(mbedtls_get_unaligned_uint64((data) + (offset))) \ + ) + +/** + * Put in memory a 64 bits unsigned integer in big-endian order. + * + * \param n 64 bits unsigned integer to put in memory. + * \param data Base address of the memory where to put the 64 + * bits unsigned integer in. + * \param offset Offset from \p data where to put the most significant + * byte of the 64 bits unsigned integer \p n. + */ +#define MBEDTLS_PUT_UINT64_BE(n, data, offset) \ + { \ + if (MBEDTLS_IS_BIG_ENDIAN) \ + { \ + mbedtls_put_unaligned_uint64((data) + (offset), (uint64_t) (n)); \ + } \ + else \ + { \ + mbedtls_put_unaligned_uint64((data) + (offset), MBEDTLS_BSWAP64((uint64_t) (n))); \ + } \ + } + +/** + * Get the unsigned 64 bits integer corresponding to eight bytes in + * little-endian order (LSB first). + * + * \param data Base address of the memory to get the eight bytes from. + * \param offset Offset from \p data of the first and least significant + * byte of the eight bytes to build the 64 bits unsigned + * integer from. + */ +#define MBEDTLS_GET_UINT64_LE(data, offset) \ + ((MBEDTLS_IS_BIG_ENDIAN) \ + ? MBEDTLS_BSWAP64(mbedtls_get_unaligned_uint64((data) + (offset))) \ + : mbedtls_get_unaligned_uint64((data) + (offset)) \ + ) + +/** + * Put in memory a 64 bits unsigned integer in little-endian order. + * + * \param n 64 bits unsigned integer to put in memory. + * \param data Base address of the memory where to put the 64 + * bits unsigned integer in. + * \param offset Offset from \p data where to put the least significant + * byte of the 64 bits unsigned integer \p n. + */ +#define MBEDTLS_PUT_UINT64_LE(n, data, offset) \ + { \ + if (MBEDTLS_IS_BIG_ENDIAN) \ + { \ + mbedtls_put_unaligned_uint64((data) + (offset), MBEDTLS_BSWAP64((uint64_t) (n))); \ + } \ + else \ + { \ + mbedtls_put_unaligned_uint64((data) + (offset), (uint64_t) (n)); \ + } \ + } + +#endif /* MBEDTLS_LIBRARY_ALIGNMENT_H */ diff --git a/vendor/mbedtls/library/arc4.c b/vendor/mbedtls/library/arc4.c deleted file mode 100644 index aa5e3a2b3a..0000000000 --- a/vendor/mbedtls/library/arc4.c +++ /dev/null @@ -1,192 +0,0 @@ -/* - * An implementation of the ARCFOUR algorithm - * - * Copyright The Mbed TLS Contributors - * SPDX-License-Identifier: Apache-2.0 - * - * Licensed under the Apache License, Version 2.0 (the "License"); you may - * not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT - * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ -/* - * The ARCFOUR algorithm was publicly disclosed on 94/09. - * - * http://groups.google.com/group/sci.crypt/msg/10a300c9d21afca0 - */ - -#include "common.h" - -#if defined(MBEDTLS_ARC4_C) - -#include "mbedtls/arc4.h" -#include "mbedtls/platform_util.h" - -#include - -#include "mbedtls/platform.h" - -#if !defined(MBEDTLS_ARC4_ALT) - -void mbedtls_arc4_init(mbedtls_arc4_context *ctx) -{ - memset(ctx, 0, sizeof(mbedtls_arc4_context)); -} - -void mbedtls_arc4_free(mbedtls_arc4_context *ctx) -{ - if (ctx == NULL) { - return; - } - - mbedtls_platform_zeroize(ctx, sizeof(mbedtls_arc4_context)); -} - -/* - * ARC4 key schedule - */ -void mbedtls_arc4_setup(mbedtls_arc4_context *ctx, const unsigned char *key, - unsigned int keylen) -{ - int i, j, a; - unsigned int k; - unsigned char *m; - - ctx->x = 0; - ctx->y = 0; - m = ctx->m; - - for (i = 0; i < 256; i++) { - m[i] = (unsigned char) i; - } - - j = k = 0; - - for (i = 0; i < 256; i++, k++) { - if (k >= keylen) { - k = 0; - } - - a = m[i]; - j = (j + a + key[k]) & 0xFF; - m[i] = m[j]; - m[j] = (unsigned char) a; - } -} - -/* - * ARC4 cipher function - */ -int mbedtls_arc4_crypt(mbedtls_arc4_context *ctx, size_t length, const unsigned char *input, - unsigned char *output) -{ - int x, y, a, b; - size_t i; - unsigned char *m; - - x = ctx->x; - y = ctx->y; - m = ctx->m; - - for (i = 0; i < length; i++) { - x = (x + 1) & 0xFF; a = m[x]; - y = (y + a) & 0xFF; b = m[y]; - - m[x] = (unsigned char) b; - m[y] = (unsigned char) a; - - output[i] = (unsigned char) - (input[i] ^ m[(unsigned char) (a + b)]); - } - - ctx->x = x; - ctx->y = y; - - return 0; -} - -#endif /* !MBEDTLS_ARC4_ALT */ - -#if defined(MBEDTLS_SELF_TEST) -/* - * ARC4 tests vectors as posted by Eric Rescorla in sep. 1994: - * - * http://groups.google.com/group/comp.security.misc/msg/10a300c9d21afca0 - */ -static const unsigned char arc4_test_key[3][8] = -{ - { 0x01, 0x23, 0x45, 0x67, 0x89, 0xAB, 0xCD, 0xEF }, - { 0x01, 0x23, 0x45, 0x67, 0x89, 0xAB, 0xCD, 0xEF }, - { 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 } -}; - -static const unsigned char arc4_test_pt[3][8] = -{ - { 0x01, 0x23, 0x45, 0x67, 0x89, 0xAB, 0xCD, 0xEF }, - { 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 }, - { 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 } -}; - -static const unsigned char arc4_test_ct[3][8] = -{ - { 0x75, 0xB7, 0x87, 0x80, 0x99, 0xE0, 0xC5, 0x96 }, - { 0x74, 0x94, 0xC2, 0xE7, 0x10, 0x4B, 0x08, 0x79 }, - { 0xDE, 0x18, 0x89, 0x41, 0xA3, 0x37, 0x5D, 0x3A } -}; - -/* - * Checkup routine - */ -int mbedtls_arc4_self_test(int verbose) -{ - int i, ret = 0; - unsigned char ibuf[8]; - unsigned char obuf[8]; - mbedtls_arc4_context ctx; - - mbedtls_arc4_init(&ctx); - - for (i = 0; i < 3; i++) { - if (verbose != 0) { - mbedtls_printf(" ARC4 test #%d: ", i + 1); - } - - memcpy(ibuf, arc4_test_pt[i], 8); - - mbedtls_arc4_setup(&ctx, arc4_test_key[i], 8); - mbedtls_arc4_crypt(&ctx, 8, ibuf, obuf); - - if (memcmp(obuf, arc4_test_ct[i], 8) != 0) { - if (verbose != 0) { - mbedtls_printf("failed\n"); - } - - ret = 1; - goto exit; - } - - if (verbose != 0) { - mbedtls_printf("passed\n"); - } - } - - if (verbose != 0) { - mbedtls_printf("\n"); - } - -exit: - mbedtls_arc4_free(&ctx); - - return ret; -} - -#endif /* MBEDTLS_SELF_TEST */ - -#endif /* MBEDTLS_ARC4_C */ diff --git a/vendor/mbedtls/library/aria.c b/vendor/mbedtls/library/aria.c index d958ef615d..d9f84cc59d 100644 --- a/vendor/mbedtls/library/aria.c +++ b/vendor/mbedtls/library/aria.c @@ -2,19 +2,7 @@ * ARIA implementation * * Copyright The Mbed TLS Contributors - * SPDX-License-Identifier: Apache-2.0 - * - * Licensed under the Apache License, Version 2.0 (the "License"); you may - * not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT - * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. + * SPDX-License-Identifier: Apache-2.0 OR GPL-2.0-or-later */ /* @@ -37,12 +25,6 @@ #include "mbedtls/platform_util.h" -/* Parameter validation macros */ -#define ARIA_VALIDATE_RET(cond) \ - MBEDTLS_INTERNAL_VALIDATE_RET(cond, MBEDTLS_ERR_ARIA_BAD_INPUT_DATA) -#define ARIA_VALIDATE(cond) \ - MBEDTLS_INTERNAL_VALIDATE(cond) - /* * modify byte order: ( A B C D ) -> ( B A D C ), i.e. swap pairs of bytes * @@ -98,47 +80,8 @@ static inline uint32_t aria_p1(uint32_t x) * modify byte order: ( A B C D ) -> ( D C B A ), i.e. change endianness * * This is submatrix P3 in [1] Appendix B.1 - * - * Some compilers fail to translate this to a single instruction, - * so let's provide asm versions for common platforms with C fallback. */ -#if defined(MBEDTLS_HAVE_ASM) -#if defined(__arm__) /* rev available from v6 up */ -/* armcc5 --gnu defines __GNUC__ but doesn't support GNU's extended asm */ -#if defined(__GNUC__) && \ - (!defined(__ARMCC_VERSION) || __ARMCC_VERSION >= 6000000) && \ - __ARM_ARCH >= 6 -static inline uint32_t aria_p3(uint32_t x) -{ - uint32_t r; - __asm("rev %0, %1" : "=l" (r) : "l" (x)); - return r; -} -#define ARIA_P3 aria_p3 -#elif defined(__ARMCC_VERSION) && __ARMCC_VERSION < 6000000 && \ - (__TARGET_ARCH_ARM >= 6 || __TARGET_ARCH_THUMB >= 3) -static inline uint32_t aria_p3(uint32_t x) -{ - uint32_t r; - __asm("rev r, x"); - return r; -} -#define ARIA_P3 aria_p3 -#endif -#endif /* arm */ -#if defined(__GNUC__) && \ - defined(__i386__) || defined(__amd64__) || defined(__x86_64__) -static inline uint32_t aria_p3(uint32_t x) -{ - __asm("bswap %0" : "=r" (x) : "0" (x)); - return x; -} -#define ARIA_P3 aria_p3 -#endif /* x86 gnuc */ -#endif /* MBEDTLS_HAVE_ASM && GNUC */ -#if !defined(ARIA_P3) -#define ARIA_P3(x) ARIA_P2(ARIA_P1(x)) -#endif +#define ARIA_P3(x) MBEDTLS_BSWAP32(x) /* * ARIA Affine Transform @@ -414,8 +357,6 @@ int mbedtls_aria_setkey_enc(mbedtls_aria_context *ctx, int i; uint32_t w[4][4], *w2; - ARIA_VALIDATE_RET(ctx != NULL); - ARIA_VALIDATE_RET(key != NULL); if (keybits != 128 && keybits != 192 && keybits != 256) { return MBEDTLS_ERR_ARIA_BAD_INPUT_DATA; @@ -464,12 +405,11 @@ int mbedtls_aria_setkey_enc(mbedtls_aria_context *ctx, /* * Set decryption key */ +#if !defined(MBEDTLS_BLOCK_CIPHER_NO_DECRYPT) int mbedtls_aria_setkey_dec(mbedtls_aria_context *ctx, const unsigned char *key, unsigned int keybits) { int i, j, k, ret; - ARIA_VALIDATE_RET(ctx != NULL); - ARIA_VALIDATE_RET(key != NULL); ret = mbedtls_aria_setkey_enc(ctx, key, keybits); if (ret != 0) { @@ -493,6 +433,7 @@ int mbedtls_aria_setkey_dec(mbedtls_aria_context *ctx, return 0; } +#endif /* !MBEDTLS_BLOCK_CIPHER_NO_DECRYPT */ /* * Encrypt a block @@ -504,9 +445,6 @@ int mbedtls_aria_crypt_ecb(mbedtls_aria_context *ctx, int i; uint32_t a, b, c, d; - ARIA_VALIDATE_RET(ctx != NULL); - ARIA_VALIDATE_RET(input != NULL); - ARIA_VALIDATE_RET(output != NULL); a = MBEDTLS_GET_UINT32_LE(input, 0); b = MBEDTLS_GET_UINT32_LE(input, 4); @@ -554,7 +492,6 @@ int mbedtls_aria_crypt_ecb(mbedtls_aria_context *ctx, /* Initialize context */ void mbedtls_aria_init(mbedtls_aria_context *ctx) { - ARIA_VALIDATE(ctx != NULL); memset(ctx, 0, sizeof(mbedtls_aria_context)); } @@ -579,15 +516,11 @@ int mbedtls_aria_crypt_cbc(mbedtls_aria_context *ctx, const unsigned char *input, unsigned char *output) { - int i; unsigned char temp[MBEDTLS_ARIA_BLOCKSIZE]; - ARIA_VALIDATE_RET(ctx != NULL); - ARIA_VALIDATE_RET(mode == MBEDTLS_ARIA_ENCRYPT || - mode == MBEDTLS_ARIA_DECRYPT); - ARIA_VALIDATE_RET(length == 0 || input != NULL); - ARIA_VALIDATE_RET(length == 0 || output != NULL); - ARIA_VALIDATE_RET(iv != NULL); + if ((mode != MBEDTLS_ARIA_ENCRYPT) && (mode != MBEDTLS_ARIA_DECRYPT)) { + return MBEDTLS_ERR_ARIA_BAD_INPUT_DATA; + } if (length % MBEDTLS_ARIA_BLOCKSIZE) { return MBEDTLS_ERR_ARIA_INVALID_INPUT_LENGTH; @@ -598,9 +531,7 @@ int mbedtls_aria_crypt_cbc(mbedtls_aria_context *ctx, memcpy(temp, input, MBEDTLS_ARIA_BLOCKSIZE); mbedtls_aria_crypt_ecb(ctx, input, output); - for (i = 0; i < MBEDTLS_ARIA_BLOCKSIZE; i++) { - output[i] = (unsigned char) (output[i] ^ iv[i]); - } + mbedtls_xor(output, output, iv, MBEDTLS_ARIA_BLOCKSIZE); memcpy(iv, temp, MBEDTLS_ARIA_BLOCKSIZE); @@ -610,9 +541,7 @@ int mbedtls_aria_crypt_cbc(mbedtls_aria_context *ctx, } } else { while (length > 0) { - for (i = 0; i < MBEDTLS_ARIA_BLOCKSIZE; i++) { - output[i] = (unsigned char) (input[i] ^ iv[i]); - } + mbedtls_xor(output, input, iv, MBEDTLS_ARIA_BLOCKSIZE); mbedtls_aria_crypt_ecb(ctx, output, output); memcpy(iv, output, MBEDTLS_ARIA_BLOCKSIZE); @@ -642,19 +571,14 @@ int mbedtls_aria_crypt_cfb128(mbedtls_aria_context *ctx, unsigned char c; size_t n; - ARIA_VALIDATE_RET(ctx != NULL); - ARIA_VALIDATE_RET(mode == MBEDTLS_ARIA_ENCRYPT || - mode == MBEDTLS_ARIA_DECRYPT); - ARIA_VALIDATE_RET(length == 0 || input != NULL); - ARIA_VALIDATE_RET(length == 0 || output != NULL); - ARIA_VALIDATE_RET(iv != NULL); - ARIA_VALIDATE_RET(iv_off != NULL); + if ((mode != MBEDTLS_ARIA_ENCRYPT) && (mode != MBEDTLS_ARIA_DECRYPT)) { + return MBEDTLS_ERR_ARIA_BAD_INPUT_DATA; + } n = *iv_off; /* An overly large value of n can lead to an unlimited - * buffer overflow. Therefore, guard against this - * outside of parameter validation. */ + * buffer overflow. */ if (n >= MBEDTLS_ARIA_BLOCKSIZE) { return MBEDTLS_ERR_ARIA_BAD_INPUT_DATA; } @@ -704,17 +628,9 @@ int mbedtls_aria_crypt_ctr(mbedtls_aria_context *ctx, int c, i; size_t n; - ARIA_VALIDATE_RET(ctx != NULL); - ARIA_VALIDATE_RET(length == 0 || input != NULL); - ARIA_VALIDATE_RET(length == 0 || output != NULL); - ARIA_VALIDATE_RET(nonce_counter != NULL); - ARIA_VALIDATE_RET(stream_block != NULL); - ARIA_VALIDATE_RET(nc_off != NULL); - n = *nc_off; /* An overly large value of n can lead to an unlimited - * buffer overflow. Therefore, guard against this - * outside of parameter validation. */ + * buffer overflow. */ if (n >= MBEDTLS_ARIA_BLOCKSIZE) { return MBEDTLS_ERR_ARIA_BAD_INPUT_DATA; } @@ -928,12 +844,18 @@ int mbedtls_aria_self_test(int verbose) /* test ECB decryption */ if (verbose) { mbedtls_printf(" ARIA-ECB-%d (dec): ", 128 + 64 * i); +#if defined(MBEDTLS_BLOCK_CIPHER_NO_DECRYPT) + mbedtls_printf("skipped\n"); +#endif } + +#if !defined(MBEDTLS_BLOCK_CIPHER_NO_DECRYPT) mbedtls_aria_setkey_dec(&ctx, aria_test1_ecb_key, 128 + 64 * i); mbedtls_aria_crypt_ecb(&ctx, aria_test1_ecb_ct[i], blk); ARIA_SELF_TEST_ASSERT( memcmp(blk, aria_test1_ecb_pt, MBEDTLS_ARIA_BLOCKSIZE) != 0); +#endif } if (verbose) { mbedtls_printf("\n"); diff --git a/vendor/mbedtls/library/asn1parse.c b/vendor/mbedtls/library/asn1parse.c index 6a8cd6c545..e33fdf71da 100644 --- a/vendor/mbedtls/library/asn1parse.c +++ b/vendor/mbedtls/library/asn1parse.c @@ -2,24 +2,13 @@ * Generic ASN.1 parsing * * Copyright The Mbed TLS Contributors - * SPDX-License-Identifier: Apache-2.0 - * - * Licensed under the Apache License, Version 2.0 (the "License"); you may - * not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT - * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. + * SPDX-License-Identifier: Apache-2.0 OR GPL-2.0-or-later */ #include "common.h" -#if defined(MBEDTLS_ASN1_PARSE_C) +#if defined(MBEDTLS_ASN1_PARSE_C) || defined(MBEDTLS_X509_CREATE_C) || \ + defined(MBEDTLS_PSA_UTIL_HAVE_ECDSA) #include "mbedtls/asn1.h" #include "mbedtls/platform_util.h" @@ -47,47 +36,18 @@ int mbedtls_asn1_get_len(unsigned char **p, if ((**p & 0x80) == 0) { *len = *(*p)++; } else { - switch (**p & 0x7F) { - case 1: - if ((end - *p) < 2) { - return MBEDTLS_ERR_ASN1_OUT_OF_DATA; - } - - *len = (*p)[1]; - (*p) += 2; - break; - - case 2: - if ((end - *p) < 3) { - return MBEDTLS_ERR_ASN1_OUT_OF_DATA; - } - - *len = ((size_t) (*p)[1] << 8) | (*p)[2]; - (*p) += 3; - break; - - case 3: - if ((end - *p) < 4) { - return MBEDTLS_ERR_ASN1_OUT_OF_DATA; - } - - *len = ((size_t) (*p)[1] << 16) | - ((size_t) (*p)[2] << 8) | (*p)[3]; - (*p) += 4; - break; - - case 4: - if ((end - *p) < 5) { - return MBEDTLS_ERR_ASN1_OUT_OF_DATA; - } - - *len = ((size_t) (*p)[1] << 24) | ((size_t) (*p)[2] << 16) | - ((size_t) (*p)[3] << 8) | (*p)[4]; - (*p) += 5; - break; - - default: - return MBEDTLS_ERR_ASN1_INVALID_LENGTH; + int n = (**p) & 0x7F; + if (n == 0 || n > 4) { + return MBEDTLS_ERR_ASN1_INVALID_LENGTH; + } + if ((end - *p) <= n) { + return MBEDTLS_ERR_ASN1_OUT_OF_DATA; + } + *len = 0; + (*p)++; + while (n--) { + *len = (*len << 8) | **p; + (*p)++; } } @@ -114,7 +74,9 @@ int mbedtls_asn1_get_tag(unsigned char **p, return mbedtls_asn1_get_len(p, end, len); } +#endif /* MBEDTLS_ASN1_PARSE_C || MBEDTLS_X509_CREATE_C || MBEDTLS_PSA_UTIL_HAVE_ECDSA */ +#if defined(MBEDTLS_ASN1_PARSE_C) int mbedtls_asn1_get_bool(unsigned char **p, const unsigned char *end, int *val) @@ -332,7 +294,6 @@ void mbedtls_asn1_sequence_free(mbedtls_asn1_sequence *seq) { while (seq != NULL) { mbedtls_asn1_sequence *next = seq->next; - mbedtls_platform_zeroize(seq, sizeof(*seq)); mbedtls_free(seq); seq = next; } @@ -455,6 +416,7 @@ int mbedtls_asn1_get_alg_null(unsigned char **p, return 0; } +#if !defined(MBEDTLS_DEPRECATED_REMOVED) void mbedtls_asn1_free_named_data(mbedtls_asn1_named_data *cur) { if (cur == NULL) { @@ -466,6 +428,7 @@ void mbedtls_asn1_free_named_data(mbedtls_asn1_named_data *cur) mbedtls_platform_zeroize(cur, sizeof(mbedtls_asn1_named_data)); } +#endif /* MBEDTLS_DEPRECATED_REMOVED */ void mbedtls_asn1_free_named_data_list(mbedtls_asn1_named_data **head) { @@ -473,13 +436,22 @@ void mbedtls_asn1_free_named_data_list(mbedtls_asn1_named_data **head) while ((cur = *head) != NULL) { *head = cur->next; - mbedtls_asn1_free_named_data(cur); + mbedtls_free(cur->oid.p); + mbedtls_free(cur->val.p); mbedtls_free(cur); } } -mbedtls_asn1_named_data *mbedtls_asn1_find_named_data(mbedtls_asn1_named_data *list, - const char *oid, size_t len) +void mbedtls_asn1_free_named_data_list_shallow(mbedtls_asn1_named_data *name) +{ + for (mbedtls_asn1_named_data *next; name != NULL; name = next) { + next = name->next; + mbedtls_free(name); + } +} + +const mbedtls_asn1_named_data *mbedtls_asn1_find_named_data(const mbedtls_asn1_named_data *list, + const char *oid, size_t len) { while (list != NULL) { if (list->oid.len == len && diff --git a/vendor/mbedtls/library/asn1write.c b/vendor/mbedtls/library/asn1write.c index a499bead45..775a9ef530 100644 --- a/vendor/mbedtls/library/asn1write.c +++ b/vendor/mbedtls/library/asn1write.c @@ -2,24 +2,13 @@ * ASN.1 buffer writing functionality * * Copyright The Mbed TLS Contributors - * SPDX-License-Identifier: Apache-2.0 - * - * Licensed under the Apache License, Version 2.0 (the "License"); you may - * not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT - * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. + * SPDX-License-Identifier: Apache-2.0 OR GPL-2.0-or-later */ #include "common.h" -#if defined(MBEDTLS_ASN1_WRITE_C) +#if defined(MBEDTLS_ASN1_WRITE_C) || defined(MBEDTLS_X509_USE_C) || \ + defined(MBEDTLS_PSA_UTIL_HAVE_ECDSA) #include "mbedtls/asn1write.h" #include "mbedtls/error.h" @@ -28,71 +17,43 @@ #include "mbedtls/platform.h" -int mbedtls_asn1_write_len(unsigned char **p, unsigned char *start, size_t len) -{ - if (len < 0x80) { - if (*p - start < 1) { - return MBEDTLS_ERR_ASN1_BUF_TOO_SMALL; - } +#if defined(MBEDTLS_ASN1_PARSE_C) +#include "mbedtls/asn1.h" +#endif - *--(*p) = (unsigned char) len; - return 1; +int mbedtls_asn1_write_len(unsigned char **p, const unsigned char *start, size_t len) +{ +#if SIZE_MAX > 0xFFFFFFFF + if (len > 0xFFFFFFFF) { + return MBEDTLS_ERR_ASN1_INVALID_LENGTH; } +#endif - if (len <= 0xFF) { - if (*p - start < 2) { - return MBEDTLS_ERR_ASN1_BUF_TOO_SMALL; - } + int required = 1; - *--(*p) = (unsigned char) len; - *--(*p) = 0x81; - return 2; - } - - if (len <= 0xFFFF) { - if (*p - start < 3) { - return MBEDTLS_ERR_ASN1_BUF_TOO_SMALL; + if (len >= 0x80) { + for (size_t l = len; l != 0; l >>= 8) { + required++; } - - *--(*p) = MBEDTLS_BYTE_0(len); - *--(*p) = MBEDTLS_BYTE_1(len); - *--(*p) = 0x82; - return 3; } - if (len <= 0xFFFFFF) { - if (*p - start < 4) { - return MBEDTLS_ERR_ASN1_BUF_TOO_SMALL; - } - - *--(*p) = MBEDTLS_BYTE_0(len); - *--(*p) = MBEDTLS_BYTE_1(len); - *--(*p) = MBEDTLS_BYTE_2(len); - *--(*p) = 0x83; - return 4; + if (required > (*p - start)) { + return MBEDTLS_ERR_ASN1_BUF_TOO_SMALL; } - int len_is_valid = 1; -#if SIZE_MAX > 0xFFFFFFFF - len_is_valid = (len <= 0xFFFFFFFF); -#endif - if (len_is_valid) { - if (*p - start < 5) { - return MBEDTLS_ERR_ASN1_BUF_TOO_SMALL; - } - + do { *--(*p) = MBEDTLS_BYTE_0(len); - *--(*p) = MBEDTLS_BYTE_1(len); - *--(*p) = MBEDTLS_BYTE_2(len); - *--(*p) = MBEDTLS_BYTE_3(len); - *--(*p) = 0x84; - return 5; + len >>= 8; + } while (len); + + if (required > 1) { + *--(*p) = (unsigned char) (0x80 + required - 1); } - return MBEDTLS_ERR_ASN1_INVALID_LENGTH; + return required; } -int mbedtls_asn1_write_tag(unsigned char **p, unsigned char *start, unsigned char tag) +int mbedtls_asn1_write_tag(unsigned char **p, const unsigned char *start, unsigned char tag) { if (*p - start < 1) { return MBEDTLS_ERR_ASN1_BUF_TOO_SMALL; @@ -102,8 +63,23 @@ int mbedtls_asn1_write_tag(unsigned char **p, unsigned char *start, unsigned cha return 1; } +#endif /* MBEDTLS_ASN1_WRITE_C || MBEDTLS_X509_USE_C || MBEDTLS_PSA_UTIL_HAVE_ECDSA */ + +#if defined(MBEDTLS_ASN1_WRITE_C) +static int mbedtls_asn1_write_len_and_tag(unsigned char **p, + const unsigned char *start, + size_t len, + unsigned char tag) +{ + int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED; + + MBEDTLS_ASN1_CHK_ADD(len, mbedtls_asn1_write_len(p, start, len)); + MBEDTLS_ASN1_CHK_ADD(len, mbedtls_asn1_write_tag(p, start, tag)); -int mbedtls_asn1_write_raw_buffer(unsigned char **p, unsigned char *start, + return (int) len; +} + +int mbedtls_asn1_write_raw_buffer(unsigned char **p, const unsigned char *start, const unsigned char *buf, size_t size) { size_t len = 0; @@ -120,7 +96,7 @@ int mbedtls_asn1_write_raw_buffer(unsigned char **p, unsigned char *start, } #if defined(MBEDTLS_BIGNUM_C) -int mbedtls_asn1_write_mpi(unsigned char **p, unsigned char *start, const mbedtls_mpi *X) +int mbedtls_asn1_write_mpi(unsigned char **p, const unsigned char *start, const mbedtls_mpi *X) { int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED; size_t len = 0; @@ -154,30 +130,21 @@ int mbedtls_asn1_write_mpi(unsigned char **p, unsigned char *start, const mbedtl len += 1; } - MBEDTLS_ASN1_CHK_ADD(len, mbedtls_asn1_write_len(p, start, len)); - MBEDTLS_ASN1_CHK_ADD(len, mbedtls_asn1_write_tag(p, start, MBEDTLS_ASN1_INTEGER)); - - ret = (int) len; + ret = mbedtls_asn1_write_len_and_tag(p, start, len, MBEDTLS_ASN1_INTEGER); cleanup: return ret; } #endif /* MBEDTLS_BIGNUM_C */ -int mbedtls_asn1_write_null(unsigned char **p, unsigned char *start) +int mbedtls_asn1_write_null(unsigned char **p, const unsigned char *start) { - int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED; - size_t len = 0; - // Write NULL // - MBEDTLS_ASN1_CHK_ADD(len, mbedtls_asn1_write_len(p, start, 0)); - MBEDTLS_ASN1_CHK_ADD(len, mbedtls_asn1_write_tag(p, start, MBEDTLS_ASN1_NULL)); - - return (int) len; + return mbedtls_asn1_write_len_and_tag(p, start, 0, MBEDTLS_ASN1_NULL); } -int mbedtls_asn1_write_oid(unsigned char **p, unsigned char *start, +int mbedtls_asn1_write_oid(unsigned char **p, const unsigned char *start, const char *oid, size_t oid_len) { int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED; @@ -185,20 +152,17 @@ int mbedtls_asn1_write_oid(unsigned char **p, unsigned char *start, MBEDTLS_ASN1_CHK_ADD(len, mbedtls_asn1_write_raw_buffer(p, start, (const unsigned char *) oid, oid_len)); - MBEDTLS_ASN1_CHK_ADD(len, mbedtls_asn1_write_len(p, start, len)); - MBEDTLS_ASN1_CHK_ADD(len, mbedtls_asn1_write_tag(p, start, MBEDTLS_ASN1_OID)); - - return (int) len; + return mbedtls_asn1_write_len_and_tag(p, start, len, MBEDTLS_ASN1_OID); } -int mbedtls_asn1_write_algorithm_identifier(unsigned char **p, unsigned char *start, +int mbedtls_asn1_write_algorithm_identifier(unsigned char **p, const unsigned char *start, const char *oid, size_t oid_len, size_t par_len) { return mbedtls_asn1_write_algorithm_identifier_ext(p, start, oid, oid_len, par_len, 1); } -int mbedtls_asn1_write_algorithm_identifier_ext(unsigned char **p, unsigned char *start, +int mbedtls_asn1_write_algorithm_identifier_ext(unsigned char **p, const unsigned char *start, const char *oid, size_t oid_len, size_t par_len, int has_par) { @@ -215,17 +179,12 @@ int mbedtls_asn1_write_algorithm_identifier_ext(unsigned char **p, unsigned char MBEDTLS_ASN1_CHK_ADD(len, mbedtls_asn1_write_oid(p, start, oid, oid_len)); - MBEDTLS_ASN1_CHK_ADD(len, mbedtls_asn1_write_len(p, start, len)); - MBEDTLS_ASN1_CHK_ADD(len, mbedtls_asn1_write_tag(p, start, - MBEDTLS_ASN1_CONSTRUCTED | - MBEDTLS_ASN1_SEQUENCE)); - - return (int) len; + return mbedtls_asn1_write_len_and_tag(p, start, len, + MBEDTLS_ASN1_CONSTRUCTED | MBEDTLS_ASN1_SEQUENCE); } -int mbedtls_asn1_write_bool(unsigned char **p, unsigned char *start, int boolean) +int mbedtls_asn1_write_bool(unsigned char **p, const unsigned char *start, int boolean) { - int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED; size_t len = 0; if (*p - start < 1) { @@ -235,15 +194,11 @@ int mbedtls_asn1_write_bool(unsigned char **p, unsigned char *start, int boolean *--(*p) = (boolean) ? 255 : 0; len++; - MBEDTLS_ASN1_CHK_ADD(len, mbedtls_asn1_write_len(p, start, len)); - MBEDTLS_ASN1_CHK_ADD(len, mbedtls_asn1_write_tag(p, start, MBEDTLS_ASN1_BOOLEAN)); - - return (int) len; + return mbedtls_asn1_write_len_and_tag(p, start, len, MBEDTLS_ASN1_BOOLEAN); } -static int asn1_write_tagged_int(unsigned char **p, unsigned char *start, int val, int tag) +static int asn1_write_tagged_int(unsigned char **p, const unsigned char *start, int val, int tag) { - int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED; size_t len = 0; do { @@ -263,23 +218,20 @@ static int asn1_write_tagged_int(unsigned char **p, unsigned char *start, int va len += 1; } - MBEDTLS_ASN1_CHK_ADD(len, mbedtls_asn1_write_len(p, start, len)); - MBEDTLS_ASN1_CHK_ADD(len, mbedtls_asn1_write_tag(p, start, tag)); - - return (int) len; + return mbedtls_asn1_write_len_and_tag(p, start, len, tag); } -int mbedtls_asn1_write_int(unsigned char **p, unsigned char *start, int val) +int mbedtls_asn1_write_int(unsigned char **p, const unsigned char *start, int val) { return asn1_write_tagged_int(p, start, val, MBEDTLS_ASN1_INTEGER); } -int mbedtls_asn1_write_enum(unsigned char **p, unsigned char *start, int val) +int mbedtls_asn1_write_enum(unsigned char **p, const unsigned char *start, int val) { return asn1_write_tagged_int(p, start, val, MBEDTLS_ASN1_ENUMERATED); } -int mbedtls_asn1_write_tagged_string(unsigned char **p, unsigned char *start, int tag, +int mbedtls_asn1_write_tagged_string(unsigned char **p, const unsigned char *start, int tag, const char *text, size_t text_len) { int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED; @@ -289,33 +241,30 @@ int mbedtls_asn1_write_tagged_string(unsigned char **p, unsigned char *start, in (const unsigned char *) text, text_len)); - MBEDTLS_ASN1_CHK_ADD(len, mbedtls_asn1_write_len(p, start, len)); - MBEDTLS_ASN1_CHK_ADD(len, mbedtls_asn1_write_tag(p, start, tag)); - - return (int) len; + return mbedtls_asn1_write_len_and_tag(p, start, len, tag); } -int mbedtls_asn1_write_utf8_string(unsigned char **p, unsigned char *start, +int mbedtls_asn1_write_utf8_string(unsigned char **p, const unsigned char *start, const char *text, size_t text_len) { return mbedtls_asn1_write_tagged_string(p, start, MBEDTLS_ASN1_UTF8_STRING, text, text_len); } -int mbedtls_asn1_write_printable_string(unsigned char **p, unsigned char *start, +int mbedtls_asn1_write_printable_string(unsigned char **p, const unsigned char *start, const char *text, size_t text_len) { return mbedtls_asn1_write_tagged_string(p, start, MBEDTLS_ASN1_PRINTABLE_STRING, text, text_len); } -int mbedtls_asn1_write_ia5_string(unsigned char **p, unsigned char *start, +int mbedtls_asn1_write_ia5_string(unsigned char **p, const unsigned char *start, const char *text, size_t text_len) { return mbedtls_asn1_write_tagged_string(p, start, MBEDTLS_ASN1_IA5_STRING, text, text_len); } int mbedtls_asn1_write_named_bitstring(unsigned char **p, - unsigned char *start, + const unsigned char *start, const unsigned char *buf, size_t bits) { @@ -358,10 +307,9 @@ int mbedtls_asn1_write_named_bitstring(unsigned char **p, return mbedtls_asn1_write_bitstring(p, start, buf, bits); } -int mbedtls_asn1_write_bitstring(unsigned char **p, unsigned char *start, +int mbedtls_asn1_write_bitstring(unsigned char **p, const unsigned char *start, const unsigned char *buf, size_t bits) { - int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED; size_t len = 0; size_t unused_bits, byte_len; @@ -385,13 +333,10 @@ int mbedtls_asn1_write_bitstring(unsigned char **p, unsigned char *start, /* Write unused bits */ *--(*p) = (unsigned char) unused_bits; - MBEDTLS_ASN1_CHK_ADD(len, mbedtls_asn1_write_len(p, start, len)); - MBEDTLS_ASN1_CHK_ADD(len, mbedtls_asn1_write_tag(p, start, MBEDTLS_ASN1_BIT_STRING)); - - return (int) len; + return mbedtls_asn1_write_len_and_tag(p, start, len, MBEDTLS_ASN1_BIT_STRING); } -int mbedtls_asn1_write_octet_string(unsigned char **p, unsigned char *start, +int mbedtls_asn1_write_octet_string(unsigned char **p, const unsigned char *start, const unsigned char *buf, size_t size) { int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED; @@ -399,13 +344,11 @@ int mbedtls_asn1_write_octet_string(unsigned char **p, unsigned char *start, MBEDTLS_ASN1_CHK_ADD(len, mbedtls_asn1_write_raw_buffer(p, start, buf, size)); - MBEDTLS_ASN1_CHK_ADD(len, mbedtls_asn1_write_len(p, start, len)); - MBEDTLS_ASN1_CHK_ADD(len, mbedtls_asn1_write_tag(p, start, MBEDTLS_ASN1_OCTET_STRING)); - - return (int) len; + return mbedtls_asn1_write_len_and_tag(p, start, len, MBEDTLS_ASN1_OCTET_STRING); } +#if !defined(MBEDTLS_ASN1_PARSE_C) /* This is a copy of the ASN.1 parsing function mbedtls_asn1_find_named_data(), * which is replicated to avoid a dependency ASN1_WRITE_C on ASN1_PARSE_C. */ static mbedtls_asn1_named_data *asn1_find_named_data( @@ -423,6 +366,10 @@ static mbedtls_asn1_named_data *asn1_find_named_data( return list; } +#else +#define asn1_find_named_data(list, oid, len) \ + ((mbedtls_asn1_named_data *) mbedtls_asn1_find_named_data(list, oid, len)) +#endif mbedtls_asn1_named_data *mbedtls_asn1_store_named_data( mbedtls_asn1_named_data **head, diff --git a/vendor/mbedtls/library/base64.c b/vendor/mbedtls/library/base64.c index 4170610642..9677dee5b2 100644 --- a/vendor/mbedtls/library/base64.c +++ b/vendor/mbedtls/library/base64.c @@ -2,26 +2,17 @@ * RFC 1521 base64 encoding/decoding * * Copyright The Mbed TLS Contributors - * SPDX-License-Identifier: Apache-2.0 - * - * Licensed under the Apache License, Version 2.0 (the "License"); you may - * not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT - * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. + * SPDX-License-Identifier: Apache-2.0 OR GPL-2.0-or-later */ +#include + #include "common.h" #if defined(MBEDTLS_BASE64_C) #include "mbedtls/base64.h" +#include "base64_internal.h" #include "constant_time_internal.h" #include @@ -31,7 +22,38 @@ #include "mbedtls/platform.h" #endif /* MBEDTLS_SELF_TEST */ -#define BASE64_SIZE_T_MAX ((size_t) -1) /* SIZE_T_MAX is not standard */ +MBEDTLS_STATIC_TESTABLE +unsigned char mbedtls_ct_base64_enc_char(unsigned char value) +{ + unsigned char digit = 0; + /* For each range of values, if value is in that range, mask digit with + * the corresponding value. Since value can only be in a single range, + * only at most one masking will change digit. */ + digit |= mbedtls_ct_uchar_in_range_if(0, 25, value, 'A' + value); + digit |= mbedtls_ct_uchar_in_range_if(26, 51, value, 'a' + value - 26); + digit |= mbedtls_ct_uchar_in_range_if(52, 61, value, '0' + value - 52); + digit |= mbedtls_ct_uchar_in_range_if(62, 62, value, '+'); + digit |= mbedtls_ct_uchar_in_range_if(63, 63, value, '/'); + return digit; +} + +MBEDTLS_STATIC_TESTABLE +signed char mbedtls_ct_base64_dec_value(unsigned char c) +{ + unsigned char val = 0; + /* For each range of digits, if c is in that range, mask val with + * the corresponding value. Since c can only be in a single range, + * only at most one masking will change val. Set val to one plus + * the desired value so that it stays 0 if c is in none of the ranges. */ + val |= mbedtls_ct_uchar_in_range_if('A', 'Z', c, c - 'A' + 0 + 1); + val |= mbedtls_ct_uchar_in_range_if('a', 'z', c, c - 'a' + 26 + 1); + val |= mbedtls_ct_uchar_in_range_if('0', '9', c, c - '0' + 52 + 1); + val |= mbedtls_ct_uchar_in_range_if('+', '+', c, c - '+' + 62 + 1); + val |= mbedtls_ct_uchar_in_range_if('/', '/', c, c - '/' + 63 + 1); + /* At this point, val is 0 if c is an invalid digit and v+1 if c is + * a digit with the value v. */ + return val - 1; +} /* * Encode a buffer into base64 format @@ -50,8 +72,8 @@ int mbedtls_base64_encode(unsigned char *dst, size_t dlen, size_t *olen, n = slen / 3 + (slen % 3 != 0); - if (n > (BASE64_SIZE_T_MAX - 1) / 4) { - *olen = BASE64_SIZE_T_MAX; + if (n > (SIZE_MAX - 1) / 4) { + *olen = SIZE_MAX; return MBEDTLS_ERR_BASE64_BUFFER_TOO_SMALL; } @@ -94,7 +116,7 @@ int mbedtls_base64_encode(unsigned char *dst, size_t dlen, size_t *olen, *p++ = '='; } - *olen = p - dst; + *olen = (size_t) (p - dst); *p = 0; return 0; @@ -203,7 +225,7 @@ int mbedtls_base64_decode(unsigned char *dst, size_t dlen, size_t *olen, } } - *olen = p - dst; + *olen = (size_t) (p - dst); return 0; } diff --git a/vendor/mbedtls/library/base64_internal.h b/vendor/mbedtls/library/base64_internal.h new file mode 100644 index 0000000000..a09bd23777 --- /dev/null +++ b/vendor/mbedtls/library/base64_internal.h @@ -0,0 +1,45 @@ +/** + * \file base64_internal.h + * + * \brief RFC 1521 base64 encoding/decoding: interfaces for invasive testing + */ +/* + * Copyright The Mbed TLS Contributors + * SPDX-License-Identifier: Apache-2.0 OR GPL-2.0-or-later + */ + +#ifndef MBEDTLS_BASE64_INTERNAL +#define MBEDTLS_BASE64_INTERNAL + +#include "common.h" + +#if defined(MBEDTLS_TEST_HOOKS) + +/** Given a value in the range 0..63, return the corresponding Base64 digit. + * + * The implementation assumes that letters are consecutive (e.g. ASCII + * but not EBCDIC). + * + * \param value A value in the range 0..63. + * + * \return A base64 digit converted from \p value. + */ +unsigned char mbedtls_ct_base64_enc_char(unsigned char value); + +/** Given a Base64 digit, return its value. + * + * If c is not a Base64 digit ('A'..'Z', 'a'..'z', '0'..'9', '+' or '/'), + * return -1. + * + * The implementation assumes that letters are consecutive (e.g. ASCII + * but not EBCDIC). + * + * \param c A base64 digit. + * + * \return The value of the base64 digit \p c. + */ +signed char mbedtls_ct_base64_dec_value(unsigned char c); + +#endif /* MBEDTLS_TEST_HOOKS */ + +#endif /* MBEDTLS_BASE64_INTERNAL */ diff --git a/vendor/mbedtls/library/bignum.c b/vendor/mbedtls/library/bignum.c index 384b9246b8..c45fd5bf24 100644 --- a/vendor/mbedtls/library/bignum.c +++ b/vendor/mbedtls/library/bignum.c @@ -2,19 +2,7 @@ * Multi-precision integer library * * Copyright The Mbed TLS Contributors - * SPDX-License-Identifier: Apache-2.0 - * - * Licensed under the Apache License, Version 2.0 (the "License"); you may - * not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT - * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. + * SPDX-License-Identifier: Apache-2.0 OR GPL-2.0-or-later */ /* @@ -38,7 +26,8 @@ #if defined(MBEDTLS_BIGNUM_C) #include "mbedtls/bignum.h" -#include "mbedtls/bn_mul.h" +#include "bignum_core.h" +#include "bn_mul.h" #include "mbedtls/platform_util.h" #include "mbedtls/error.h" #include "constant_time_internal.h" @@ -48,37 +37,148 @@ #include "mbedtls/platform.h" -#define MPI_VALIDATE_RET(cond) \ - MBEDTLS_INTERNAL_VALIDATE_RET(cond, MBEDTLS_ERR_MPI_BAD_INPUT_DATA) -#define MPI_VALIDATE(cond) \ - MBEDTLS_INTERNAL_VALIDATE(cond) -#define ciL (sizeof(mbedtls_mpi_uint)) /* chars in limb */ -#define biL (ciL << 3) /* bits in limb */ -#define biH (ciL << 2) /* half limb size */ -#define MPI_SIZE_T_MAX ((size_t) -1) /* SIZE_T_MAX is not standard */ +/* + * Conditionally select an MPI sign in constant time. + * (MPI sign is the field s in mbedtls_mpi. It is unsigned short and only 1 and -1 are valid + * values.) + */ +static inline signed short mbedtls_ct_mpi_sign_if(mbedtls_ct_condition_t cond, + signed short sign1, signed short sign2) +{ + return (signed short) mbedtls_ct_uint_if(cond, sign1 + 1, sign2 + 1) - 1; +} /* - * Convert between bits/chars and number of limbs - * Divide first in order to avoid potential overflows + * Compare signed values in constant time */ -#define BITS_TO_LIMBS(i) ((i) / biL + ((i) % biL != 0)) -#define CHARS_TO_LIMBS(i) ((i) / ciL + ((i) % ciL != 0)) +int mbedtls_mpi_lt_mpi_ct(const mbedtls_mpi *X, + const mbedtls_mpi *Y, + unsigned *ret) +{ + mbedtls_ct_condition_t different_sign, X_is_negative, Y_is_negative, result; -/* Implementation that should never be optimized out by the compiler */ -static void mbedtls_mpi_zeroize(mbedtls_mpi_uint *v, size_t n) + if (X->n != Y->n) { + return MBEDTLS_ERR_MPI_BAD_INPUT_DATA; + } + + /* + * Set N_is_negative to MBEDTLS_CT_FALSE if N >= 0, MBEDTLS_CT_TRUE if N < 0. + * We know that N->s == 1 if N >= 0 and N->s == -1 if N < 0. + */ + X_is_negative = mbedtls_ct_bool((X->s & 2) >> 1); + Y_is_negative = mbedtls_ct_bool((Y->s & 2) >> 1); + + /* + * If the signs are different, then the positive operand is the bigger. + * That is if X is negative (X_is_negative == 1), then X < Y is true and it + * is false if X is positive (X_is_negative == 0). + */ + different_sign = mbedtls_ct_bool_ne(X_is_negative, Y_is_negative); // true if different sign + result = mbedtls_ct_bool_and(different_sign, X_is_negative); + + /* + * Assuming signs are the same, compare X and Y. We switch the comparison + * order if they are negative so that we get the right result, regardles of + * sign. + */ + + /* This array is used to conditionally swap the pointers in const time */ + void * const p[2] = { X->p, Y->p }; + size_t i = mbedtls_ct_size_if_else_0(X_is_negative, 1); + mbedtls_ct_condition_t lt = mbedtls_mpi_core_lt_ct(p[i], p[i ^ 1], X->n); + + /* + * Store in result iff the signs are the same (i.e., iff different_sign == false). If + * the signs differ, result has already been set, so we don't change it. + */ + result = mbedtls_ct_bool_or(result, + mbedtls_ct_bool_and(mbedtls_ct_bool_not(different_sign), lt)); + + *ret = mbedtls_ct_uint_if_else_0(result, 1); + + return 0; +} + +/* + * Conditionally assign X = Y, without leaking information + * about whether the assignment was made or not. + * (Leaking information about the respective sizes of X and Y is ok however.) + */ +#if defined(_MSC_VER) && defined(MBEDTLS_PLATFORM_IS_WINDOWS_ON_ARM64) && \ + (_MSC_FULL_VER < 193131103) +/* + * MSVC miscompiles this function if it's inlined prior to Visual Studio 2022 version 17.1. See: + * https://developercommunity.visualstudio.com/t/c-compiler-miscompiles-part-of-mbedtls-library-on/1646989 + */ +__declspec(noinline) +#endif +int mbedtls_mpi_safe_cond_assign(mbedtls_mpi *X, + const mbedtls_mpi *Y, + unsigned char assign) { - mbedtls_platform_zeroize(v, ciL * n); + int ret = 0; + + MBEDTLS_MPI_CHK(mbedtls_mpi_grow(X, Y->n)); + + { + mbedtls_ct_condition_t do_assign = mbedtls_ct_bool(assign); + + X->s = mbedtls_ct_mpi_sign_if(do_assign, Y->s, X->s); + + mbedtls_mpi_core_cond_assign(X->p, Y->p, Y->n, do_assign); + + mbedtls_ct_condition_t do_not_assign = mbedtls_ct_bool_not(do_assign); + for (size_t i = Y->n; i < X->n; i++) { + X->p[i] = mbedtls_ct_mpi_uint_if_else_0(do_not_assign, X->p[i]); + } + } + +cleanup: + return ret; } +/* + * Conditionally swap X and Y, without leaking information + * about whether the swap was made or not. + * Here it is not ok to simply swap the pointers, which would lead to + * different memory access patterns when X and Y are used afterwards. + */ +int mbedtls_mpi_safe_cond_swap(mbedtls_mpi *X, + mbedtls_mpi *Y, + unsigned char swap) +{ + int ret = 0; + int s; + + if (X == Y) { + return 0; + } + + mbedtls_ct_condition_t do_swap = mbedtls_ct_bool(swap); + + MBEDTLS_MPI_CHK(mbedtls_mpi_grow(X, Y->n)); + MBEDTLS_MPI_CHK(mbedtls_mpi_grow(Y, X->n)); + + s = X->s; + X->s = mbedtls_ct_mpi_sign_if(do_swap, Y->s, X->s); + Y->s = mbedtls_ct_mpi_sign_if(do_swap, s, Y->s); + + mbedtls_mpi_core_cond_swap(X->p, Y->p, X->n, do_swap); + +cleanup: + return ret; +} + +/* Implementation that should never be optimized out by the compiler */ +#define mbedtls_mpi_zeroize_and_free(v, n) mbedtls_zeroize_and_free(v, ciL * (n)) + /* * Initialize one MPI */ void mbedtls_mpi_init(mbedtls_mpi *X) { - MPI_VALIDATE(X != NULL); - X->s = 1; X->n = 0; X->p = NULL; @@ -94,8 +194,7 @@ void mbedtls_mpi_free(mbedtls_mpi *X) } if (X->p != NULL) { - mbedtls_mpi_zeroize(X->p, X->n); - mbedtls_free(X->p); + mbedtls_mpi_zeroize_and_free(X->p, X->n); } X->s = 1; @@ -109,7 +208,6 @@ void mbedtls_mpi_free(mbedtls_mpi *X) int mbedtls_mpi_grow(mbedtls_mpi *X, size_t nblimbs) { mbedtls_mpi_uint *p; - MPI_VALIDATE_RET(X != NULL); if (nblimbs > MBEDTLS_MPI_MAX_LIMBS) { return MBEDTLS_ERR_MPI_ALLOC_FAILED; @@ -122,11 +220,12 @@ int mbedtls_mpi_grow(mbedtls_mpi *X, size_t nblimbs) if (X->p != NULL) { memcpy(p, X->p, X->n * ciL); - mbedtls_mpi_zeroize(X->p, X->n); - mbedtls_free(X->p); + mbedtls_mpi_zeroize_and_free(X->p, X->n); } - X->n = nblimbs; + /* nblimbs fits in n because we ensure that MBEDTLS_MPI_MAX_LIMBS + * fits, and we've checked that nblimbs <= MBEDTLS_MPI_MAX_LIMBS. */ + X->n = (unsigned short) nblimbs; X->p = p; } @@ -141,7 +240,6 @@ int mbedtls_mpi_shrink(mbedtls_mpi *X, size_t nblimbs) { mbedtls_mpi_uint *p; size_t i; - MPI_VALIDATE_RET(X != NULL); if (nblimbs > MBEDTLS_MPI_MAX_LIMBS) { return MBEDTLS_ERR_MPI_ALLOC_FAILED; @@ -170,11 +268,12 @@ int mbedtls_mpi_shrink(mbedtls_mpi *X, size_t nblimbs) if (X->p != NULL) { memcpy(p, X->p, i * ciL); - mbedtls_mpi_zeroize(X->p, X->n); - mbedtls_free(X->p); + mbedtls_mpi_zeroize_and_free(X->p, X->n); } - X->n = i; + /* i fits in n because we ensure that MBEDTLS_MPI_MAX_LIMBS + * fits, and we've checked that i <= nblimbs <= MBEDTLS_MPI_MAX_LIMBS. */ + X->n = (unsigned short) i; X->p = p; return 0; @@ -202,15 +301,12 @@ static int mbedtls_mpi_resize_clear(mbedtls_mpi *X, size_t limbs) * This function is not constant-time. Leading zeros in Y may be removed. * * Ensure that X does not shrink. This is not guaranteed by the public API, - * but some code in the bignum module relies on this property, for example - * in mbedtls_mpi_exp_mod(). + * but some code in the bignum module might still rely on this property. */ int mbedtls_mpi_copy(mbedtls_mpi *X, const mbedtls_mpi *Y) { int ret = 0; size_t i; - MPI_VALIDATE_RET(X != NULL); - MPI_VALIDATE_RET(Y != NULL); if (X == Y) { return 0; @@ -252,8 +348,6 @@ int mbedtls_mpi_copy(mbedtls_mpi *X, const mbedtls_mpi *Y) void mbedtls_mpi_swap(mbedtls_mpi *X, mbedtls_mpi *Y) { mbedtls_mpi T; - MPI_VALIDATE(X != NULL); - MPI_VALIDATE(Y != NULL); memcpy(&T, X, sizeof(mbedtls_mpi)); memcpy(X, Y, sizeof(mbedtls_mpi)); @@ -272,19 +366,22 @@ static inline mbedtls_mpi_uint mpi_sint_abs(mbedtls_mpi_sint z) return (mbedtls_mpi_uint) 0 - (mbedtls_mpi_uint) z; } +/* Convert x to a sign, i.e. to 1, if x is positive, or -1, if x is negative. + * This looks awkward but generates smaller code than (x < 0 ? -1 : 1) */ +#define TO_SIGN(x) ((mbedtls_mpi_sint) (((mbedtls_mpi_uint) x) >> (biL - 1)) * -2 + 1) + /* * Set value from integer */ int mbedtls_mpi_lset(mbedtls_mpi *X, mbedtls_mpi_sint z) { int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED; - MPI_VALIDATE_RET(X != NULL); MBEDTLS_MPI_CHK(mbedtls_mpi_grow(X, 1)); memset(X->p, 0, X->n * ciL); X->p[0] = mpi_sint_abs(z); - X->s = (z < 0) ? -1 : 1; + X->s = TO_SIGN(z); cleanup: @@ -296,8 +393,6 @@ int mbedtls_mpi_lset(mbedtls_mpi *X, mbedtls_mpi_sint z) */ int mbedtls_mpi_get_bit(const mbedtls_mpi *X, size_t pos) { - MPI_VALIDATE_RET(X != NULL); - if (X->n * biL <= pos) { return 0; } @@ -305,10 +400,6 @@ int mbedtls_mpi_get_bit(const mbedtls_mpi *X, size_t pos) return (X->p[pos / biL] >> (pos % biL)) & 0x01; } -/* Get a specific byte, without range checks. */ -#define GET_BYTE(X, i) \ - (((X)->p[(i) / ciL] >> (((i) % ciL) * 8)) & 0xff) - /* * Set a bit to a specific value of 0 or 1 */ @@ -317,7 +408,6 @@ int mbedtls_mpi_set_bit(mbedtls_mpi *X, size_t pos, unsigned char val) int ret = 0; size_t off = pos / biL; size_t idx = pos % biL; - MPI_VALIDATE_RET(X != NULL); if (val != 0 && val != 1) { return MBEDTLS_ERR_MPI_BAD_INPUT_DATA; @@ -344,59 +434,44 @@ int mbedtls_mpi_set_bit(mbedtls_mpi *X, size_t pos, unsigned char val) */ size_t mbedtls_mpi_lsb(const mbedtls_mpi *X) { - size_t i, j, count = 0; - MBEDTLS_INTERNAL_VALIDATE_RET(X != NULL, 0); + size_t i; + +#if defined(__has_builtin) +#if (MBEDTLS_MPI_UINT_MAX == UINT_MAX) && __has_builtin(__builtin_ctz) + #define mbedtls_mpi_uint_ctz __builtin_ctz +#elif (MBEDTLS_MPI_UINT_MAX == ULONG_MAX) && __has_builtin(__builtin_ctzl) + #define mbedtls_mpi_uint_ctz __builtin_ctzl +#elif (MBEDTLS_MPI_UINT_MAX == ULLONG_MAX) && __has_builtin(__builtin_ctzll) + #define mbedtls_mpi_uint_ctz __builtin_ctzll +#endif +#endif +#if defined(mbedtls_mpi_uint_ctz) for (i = 0; i < X->n; i++) { - for (j = 0; j < biL; j++, count++) { + if (X->p[i] != 0) { + return i * biL + mbedtls_mpi_uint_ctz(X->p[i]); + } + } +#else + size_t count = 0; + for (i = 0; i < X->n; i++) { + for (size_t j = 0; j < biL; j++, count++) { if (((X->p[i] >> j) & 1) != 0) { return count; } } } +#endif return 0; } -/* - * Count leading zero bits in a given integer - */ -static size_t mbedtls_clz(const mbedtls_mpi_uint x) -{ - size_t j; - mbedtls_mpi_uint mask = (mbedtls_mpi_uint) 1 << (biL - 1); - - for (j = 0; j < biL; j++) { - if (x & mask) { - break; - } - - mask >>= 1; - } - - return j; -} - /* * Return the number of bits */ size_t mbedtls_mpi_bitlen(const mbedtls_mpi *X) { - size_t i, j; - - if (X->n == 0) { - return 0; - } - - for (i = X->n - 1; i > 0; i--) { - if (X->p[i] != 0) { - break; - } - } - - j = biL - mbedtls_clz(X->p[i]); - - return (i * biL) + j; + return mbedtls_mpi_core_bitlen(X->p, X->n); } /* @@ -441,8 +516,6 @@ int mbedtls_mpi_read_string(mbedtls_mpi *X, int radix, const char *s) int sign = 1; mbedtls_mpi_uint d; mbedtls_mpi T; - MPI_VALIDATE_RET(X != NULL); - MPI_VALIDATE_RET(s != NULL); if (radix < 2 || radix > 16) { return MBEDTLS_ERR_MPI_BAD_INPUT_DATA; @@ -463,7 +536,7 @@ int mbedtls_mpi_read_string(mbedtls_mpi *X, int radix, const char *s) slen = strlen(s); if (radix == 16) { - if (slen > MPI_SIZE_T_MAX >> 2) { + if (slen > SIZE_MAX >> 2) { return MBEDTLS_ERR_MPI_BAD_INPUT_DATA; } @@ -545,9 +618,6 @@ int mbedtls_mpi_write_string(const mbedtls_mpi *X, int radix, size_t n; char *p; mbedtls_mpi T; - MPI_VALIDATE_RET(X != NULL); - MPI_VALIDATE_RET(olen != NULL); - MPI_VALIDATE_RET(buflen == 0 || buf != NULL); if (radix < 2 || radix > 16) { return MBEDTLS_ERR_MPI_BAD_INPUT_DATA; @@ -613,7 +683,7 @@ int mbedtls_mpi_write_string(const mbedtls_mpi *X, int radix, } *p++ = '\0'; - *olen = p - buf; + *olen = (size_t) (p - buf); cleanup: @@ -637,9 +707,6 @@ int mbedtls_mpi_read_file(mbedtls_mpi *X, int radix, FILE *fin) */ char s[MBEDTLS_MPI_RW_BUFFER_SIZE]; - MPI_VALIDATE_RET(X != NULL); - MPI_VALIDATE_RET(fin != NULL); - if (radix < 2 || radix > 16) { return MBEDTLS_ERR_MPI_BAD_INPUT_DATA; } @@ -683,7 +750,6 @@ int mbedtls_mpi_write_file(const char *p, const mbedtls_mpi *X, int radix, FILE * newline characters and '\0' */ char s[MBEDTLS_MPI_RW_BUFFER_SIZE]; - MPI_VALIDATE_RET(X != NULL); if (radix < 2 || radix > 16) { return MBEDTLS_ERR_MPI_BAD_INPUT_DATA; @@ -717,111 +783,22 @@ int mbedtls_mpi_write_file(const char *p, const mbedtls_mpi *X, int radix, FILE } #endif /* MBEDTLS_FS_IO */ - -/* Convert a big-endian byte array aligned to the size of mbedtls_mpi_uint - * into the storage form used by mbedtls_mpi. */ - -static mbedtls_mpi_uint mpi_uint_bigendian_to_host_c(mbedtls_mpi_uint x) -{ - uint8_t i; - unsigned char *x_ptr; - mbedtls_mpi_uint tmp = 0; - - for (i = 0, x_ptr = (unsigned char *) &x; i < ciL; i++, x_ptr++) { - tmp <<= CHAR_BIT; - tmp |= (mbedtls_mpi_uint) *x_ptr; - } - - return tmp; -} - -static mbedtls_mpi_uint mpi_uint_bigendian_to_host(mbedtls_mpi_uint x) -{ -#if defined(__BYTE_ORDER__) - -/* Nothing to do on bigendian systems. */ -#if (__BYTE_ORDER__ == __ORDER_BIG_ENDIAN__) - return x; -#endif /* __BYTE_ORDER__ == __ORDER_BIG_ENDIAN__ */ - -#if (__BYTE_ORDER__ == __ORDER_LITTLE_ENDIAN__) - -/* For GCC and Clang, have builtins for byte swapping. */ -#if defined(__GNUC__) && defined(__GNUC_PREREQ) -#if __GNUC_PREREQ(4, 3) -#define have_bswap -#endif -#endif - -#if defined(__clang__) && defined(__has_builtin) -#if __has_builtin(__builtin_bswap32) && \ - __has_builtin(__builtin_bswap64) -#define have_bswap -#endif -#endif - -#if defined(have_bswap) - /* The compiler is hopefully able to statically evaluate this! */ - switch (sizeof(mbedtls_mpi_uint)) { - case 4: - return __builtin_bswap32(x); - case 8: - return __builtin_bswap64(x); - } -#endif -#endif /* __BYTE_ORDER__ == __ORDER_LITTLE_ENDIAN__ */ -#endif /* __BYTE_ORDER__ */ - - /* Fall back to C-based reordering if we don't know the byte order - * or we couldn't use a compiler-specific builtin. */ - return mpi_uint_bigendian_to_host_c(x); -} - -static void mpi_bigendian_to_host(mbedtls_mpi_uint * const p, size_t limbs) -{ - mbedtls_mpi_uint *cur_limb_left; - mbedtls_mpi_uint *cur_limb_right; - if (limbs == 0) { - return; - } - - /* - * Traverse limbs and - * - adapt byte-order in each limb - * - swap the limbs themselves. - * For that, simultaneously traverse the limbs from left to right - * and from right to left, as long as the left index is not bigger - * than the right index (it's not a problem if limbs is odd and the - * indices coincide in the last iteration). - */ - for (cur_limb_left = p, cur_limb_right = p + (limbs - 1); - cur_limb_left <= cur_limb_right; - cur_limb_left++, cur_limb_right--) { - mbedtls_mpi_uint tmp; - /* Note that if cur_limb_left == cur_limb_right, - * this code effectively swaps the bytes only once. */ - tmp = mpi_uint_bigendian_to_host(*cur_limb_left); - *cur_limb_left = mpi_uint_bigendian_to_host(*cur_limb_right); - *cur_limb_right = tmp; - } -} - /* * Import X from unsigned binary data, little endian + * + * This function is guaranteed to return an MPI with exactly the necessary + * number of limbs (in particular, it does not skip 0s in the input). */ int mbedtls_mpi_read_binary_le(mbedtls_mpi *X, const unsigned char *buf, size_t buflen) { int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED; - size_t i; - size_t const limbs = CHARS_TO_LIMBS(buflen); + const size_t limbs = CHARS_TO_LIMBS(buflen); /* Ensure that target MPI has exactly the necessary number of limbs */ MBEDTLS_MPI_CHK(mbedtls_mpi_resize_clear(X, limbs)); - for (i = 0; i < buflen; i++) { - X->p[i / ciL] |= ((mbedtls_mpi_uint) buf[i]) << ((i % ciL) << 3); - } + MBEDTLS_MPI_CHK(mbedtls_mpi_core_read_le(X->p, X->n, buf, buflen)); cleanup: @@ -835,28 +812,19 @@ int mbedtls_mpi_read_binary_le(mbedtls_mpi *X, /* * Import X from unsigned binary data, big endian + * + * This function is guaranteed to return an MPI with exactly the necessary + * number of limbs (in particular, it does not skip 0s in the input). */ int mbedtls_mpi_read_binary(mbedtls_mpi *X, const unsigned char *buf, size_t buflen) { int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED; - size_t const limbs = CHARS_TO_LIMBS(buflen); - size_t const overhead = (limbs * ciL) - buflen; - unsigned char *Xp; - - MPI_VALIDATE_RET(X != NULL); - MPI_VALIDATE_RET(buflen == 0 || buf != NULL); + const size_t limbs = CHARS_TO_LIMBS(buflen); /* Ensure that target MPI has exactly the necessary number of limbs */ MBEDTLS_MPI_CHK(mbedtls_mpi_resize_clear(X, limbs)); - /* Avoid calling `memcpy` with NULL source or destination argument, - * even if buflen is 0. */ - if (buflen != 0) { - Xp = (unsigned char *) X->p; - memcpy(Xp + overhead, buf, buflen); - - mpi_bigendian_to_host(X->p, limbs); - } + MBEDTLS_MPI_CHK(mbedtls_mpi_core_read_be(X->p, X->n, buf, buflen)); cleanup: @@ -874,34 +842,7 @@ int mbedtls_mpi_read_binary(mbedtls_mpi *X, const unsigned char *buf, size_t buf int mbedtls_mpi_write_binary_le(const mbedtls_mpi *X, unsigned char *buf, size_t buflen) { - size_t stored_bytes = X->n * ciL; - size_t bytes_to_copy; - size_t i; - - if (stored_bytes < buflen) { - bytes_to_copy = stored_bytes; - } else { - bytes_to_copy = buflen; - - /* The output buffer is smaller than the allocated size of X. - * However X may fit if its leading bytes are zero. */ - for (i = bytes_to_copy; i < stored_bytes; i++) { - if (GET_BYTE(X, i) != 0) { - return MBEDTLS_ERR_MPI_BUFFER_TOO_SMALL; - } - } - } - - for (i = 0; i < bytes_to_copy; i++) { - buf[i] = GET_BYTE(X, i); - } - - if (stored_bytes < buflen) { - /* Write trailing 0 bytes */ - memset(buf + stored_bytes, 0, buflen - stored_bytes); - } - - return 0; + return mbedtls_mpi_core_write_le(X->p, X->n, buf, buflen); } /* @@ -910,42 +851,7 @@ int mbedtls_mpi_write_binary_le(const mbedtls_mpi *X, int mbedtls_mpi_write_binary(const mbedtls_mpi *X, unsigned char *buf, size_t buflen) { - size_t stored_bytes; - size_t bytes_to_copy; - unsigned char *p; - size_t i; - - MPI_VALIDATE_RET(X != NULL); - MPI_VALIDATE_RET(buflen == 0 || buf != NULL); - - stored_bytes = X->n * ciL; - - if (stored_bytes < buflen) { - /* There is enough space in the output buffer. Write initial - * null bytes and record the position at which to start - * writing the significant bytes. In this case, the execution - * trace of this function does not depend on the value of the - * number. */ - bytes_to_copy = stored_bytes; - p = buf + buflen - stored_bytes; - memset(buf, 0, buflen - stored_bytes); - } else { - /* The output buffer is smaller than the allocated size of X. - * However X may fit if its leading bytes are zero. */ - bytes_to_copy = buflen; - p = buf; - for (i = bytes_to_copy; i < stored_bytes; i++) { - if (GET_BYTE(X, i) != 0) { - return MBEDTLS_ERR_MPI_BUFFER_TOO_SMALL; - } - } - } - - for (i = 0; i < bytes_to_copy; i++) { - p[bytes_to_copy - i - 1] = GET_BYTE(X, i); - } - - return 0; + return mbedtls_mpi_core_write_be(X->p, X->n, buf, buflen); } /* @@ -954,12 +860,7 @@ int mbedtls_mpi_write_binary(const mbedtls_mpi *X, int mbedtls_mpi_shift_l(mbedtls_mpi *X, size_t count) { int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED; - size_t i, v0, t1; - mbedtls_mpi_uint r0 = 0, r1; - MPI_VALIDATE_RET(X != NULL); - - v0 = count / (biL); - t1 = count & (biL - 1); + size_t i; i = mbedtls_mpi_bitlen(X) + count; @@ -969,31 +870,7 @@ int mbedtls_mpi_shift_l(mbedtls_mpi *X, size_t count) ret = 0; - /* - * shift by count / limb_size - */ - if (v0 > 0) { - for (i = X->n; i > v0; i--) { - X->p[i - 1] = X->p[i - v0 - 1]; - } - - for (; i > 0; i--) { - X->p[i - 1] = 0; - } - } - - /* - * shift by count % limb_size - */ - if (t1 > 0) { - for (i = v0; i < X->n; i++) { - r1 = X->p[i] >> (biL - t1); - X->p[i] <<= t1; - X->p[i] |= r0; - r0 = r1; - } - } - + mbedtls_mpi_core_shift_l(X->p, X->n, count); cleanup: return ret; @@ -1004,42 +881,9 @@ int mbedtls_mpi_shift_l(mbedtls_mpi *X, size_t count) */ int mbedtls_mpi_shift_r(mbedtls_mpi *X, size_t count) { - size_t i, v0, v1; - mbedtls_mpi_uint r0 = 0, r1; - MPI_VALIDATE_RET(X != NULL); - - v0 = count / biL; - v1 = count & (biL - 1); - - if (v0 > X->n || (v0 == X->n && v1 > 0)) { - return mbedtls_mpi_lset(X, 0); + if (X->n != 0) { + mbedtls_mpi_core_shift_r(X->p, X->n, count); } - - /* - * shift by count / limb_size - */ - if (v0 > 0) { - for (i = 0; i < X->n - v0; i++) { - X->p[i] = X->p[i + v0]; - } - - for (; i < X->n; i++) { - X->p[i] = 0; - } - } - - /* - * shift by count % limb_size - */ - if (v1 > 0) { - for (i = X->n; i > 0; i--) { - r1 = X->p[i - 1] << (biL - v1); - X->p[i - 1] >>= v1; - X->p[i - 1] |= r0; - r0 = r1; - } - } - return 0; } @@ -1049,8 +893,6 @@ int mbedtls_mpi_shift_r(mbedtls_mpi *X, size_t count) int mbedtls_mpi_cmp_abs(const mbedtls_mpi *X, const mbedtls_mpi *Y) { size_t i, j; - MPI_VALIDATE_RET(X != NULL); - MPI_VALIDATE_RET(Y != NULL); for (i = X->n; i > 0; i--) { if (X->p[i - 1] != 0) { @@ -1064,9 +906,8 @@ int mbedtls_mpi_cmp_abs(const mbedtls_mpi *X, const mbedtls_mpi *Y) } } - if (i == 0 && j == 0) { - return 0; - } + /* If i == j == 0, i.e. abs(X) == abs(Y), + * we end up returning 0 at the end of the function. */ if (i > j) { return 1; @@ -1093,8 +934,6 @@ int mbedtls_mpi_cmp_abs(const mbedtls_mpi *X, const mbedtls_mpi *Y) int mbedtls_mpi_cmp_mpi(const mbedtls_mpi *X, const mbedtls_mpi *Y) { size_t i, j; - MPI_VALIDATE_RET(X != NULL); - MPI_VALIDATE_RET(Y != NULL); for (i = X->n; i > 0; i--) { if (X->p[i - 1] != 0) { @@ -1145,10 +984,9 @@ int mbedtls_mpi_cmp_int(const mbedtls_mpi *X, mbedtls_mpi_sint z) { mbedtls_mpi Y; mbedtls_mpi_uint p[1]; - MPI_VALIDATE_RET(X != NULL); *p = mpi_sint_abs(z); - Y.s = (z < 0) ? -1 : 1; + Y.s = TO_SIGN(z); Y.n = 1; Y.p = p; @@ -1161,11 +999,9 @@ int mbedtls_mpi_cmp_int(const mbedtls_mpi *X, mbedtls_mpi_sint z) int mbedtls_mpi_add_abs(mbedtls_mpi *X, const mbedtls_mpi *A, const mbedtls_mpi *B) { int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED; - size_t i, j; - mbedtls_mpi_uint *o, *p, c, tmp; - MPI_VALIDATE_RET(X != NULL); - MPI_VALIDATE_RET(A != NULL); - MPI_VALIDATE_RET(B != NULL); + size_t j; + mbedtls_mpi_uint *p; + mbedtls_mpi_uint c; if (X == B) { const mbedtls_mpi *T = A; A = X; B = T; @@ -1176,7 +1012,7 @@ int mbedtls_mpi_add_abs(mbedtls_mpi *X, const mbedtls_mpi *A, const mbedtls_mpi } /* - * X should always be positive as a result of unsigned additions. + * X must always be positive as a result of unsigned additions. */ X->s = 1; @@ -1194,24 +1030,23 @@ int mbedtls_mpi_add_abs(mbedtls_mpi *X, const mbedtls_mpi *A, const mbedtls_mpi MBEDTLS_MPI_CHK(mbedtls_mpi_grow(X, j)); - o = B->p; p = X->p; c = 0; + /* j is the number of non-zero limbs of B. Add those to X. */ - /* - * tmp is used because it might happen that p == o - */ - for (i = 0; i < j; i++, o++, p++) { - tmp = *o; - *p += c; c = (*p < c); - *p += tmp; c += (*p < tmp); - } + p = X->p; + + c = mbedtls_mpi_core_add(p, p, B->p, j); + + p += j; + + /* Now propagate any carry */ while (c != 0) { - if (i >= X->n) { - MBEDTLS_MPI_CHK(mbedtls_mpi_grow(X, i + 1)); - p = X->p + i; + if (j >= X->n) { + MBEDTLS_MPI_CHK(mbedtls_mpi_grow(X, j + 1)); + p = X->p + j; } - *p += c; c = (*p < c); i++; p++; + *p += c; c = (*p < c); j++; p++; } cleanup: @@ -1219,39 +1054,6 @@ int mbedtls_mpi_add_abs(mbedtls_mpi *X, const mbedtls_mpi *A, const mbedtls_mpi return ret; } -/** - * Helper for mbedtls_mpi subtraction. - * - * Calculate l - r where l and r have the same size. - * This function operates modulo (2^ciL)^n and returns the carry - * (1 if there was a wraparound, i.e. if `l < r`, and 0 otherwise). - * - * d may be aliased to l or r. - * - * \param n Number of limbs of \p d, \p l and \p r. - * \param[out] d The result of the subtraction. - * \param[in] l The left operand. - * \param[in] r The right operand. - * - * \return 1 if `l < r`. - * 0 if `l >= r`. - */ -static mbedtls_mpi_uint mpi_sub_hlp(size_t n, - mbedtls_mpi_uint *d, - const mbedtls_mpi_uint *l, - const mbedtls_mpi_uint *r) -{ - size_t i; - mbedtls_mpi_uint c = 0, t, z; - - for (i = 0; i < n; i++) { - z = (l[i] < c); t = l[i] - c; - c = (t < r[i]) + z; d[i] = t - r[i]; - } - - return c; -} - /* * Unsigned subtraction: X = |A| - |B| (HAC 14.9, 14.10) */ @@ -1260,9 +1062,6 @@ int mbedtls_mpi_sub_abs(mbedtls_mpi *X, const mbedtls_mpi *A, const mbedtls_mpi int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED; size_t n; mbedtls_mpi_uint carry; - MPI_VALIDATE_RET(X != NULL); - MPI_VALIDATE_RET(A != NULL); - MPI_VALIDATE_RET(B != NULL); for (n = B->n; n > 0; n--) { if (B->p[n - 1] != 0) { @@ -1287,19 +1086,16 @@ int mbedtls_mpi_sub_abs(mbedtls_mpi *X, const mbedtls_mpi *A, const mbedtls_mpi memset(X->p + A->n, 0, (X->n - A->n) * ciL); } - carry = mpi_sub_hlp(n, X->p, A->p, B->p); + carry = mbedtls_mpi_core_sub(X->p, A->p, B->p, n); if (carry != 0) { - /* Propagate the carry to the first nonzero limb of X. */ - for (; n < X->n && X->p[n] == 0; n++) { - --X->p[n]; - } - /* If we ran out of space for the carry, it means that the result - * is negative. */ - if (n == X->n) { + /* Propagate the carry through the rest of X. */ + carry = mbedtls_mpi_core_sub_int(X->p + n, X->p + n, carry, X->n - n); + + /* If we have further carry/borrow, the result is negative. */ + if (carry != 0) { ret = MBEDTLS_ERR_MPI_NEGATIVE_VALUE; goto cleanup; } - --X->p[n]; } /* X should always be positive as a result of unsigned subtractions. */ @@ -1317,9 +1113,6 @@ static int add_sub_mpi(mbedtls_mpi *X, int flip_B) { int ret, s; - MPI_VALIDATE_RET(X != NULL); - MPI_VALIDATE_RET(A != NULL); - MPI_VALIDATE_RET(B != NULL); s = A->s; if (A->s * B->s * flip_B < 0) { @@ -1368,11 +1161,9 @@ int mbedtls_mpi_add_int(mbedtls_mpi *X, const mbedtls_mpi *A, mbedtls_mpi_sint b { mbedtls_mpi B; mbedtls_mpi_uint p[1]; - MPI_VALIDATE_RET(X != NULL); - MPI_VALIDATE_RET(A != NULL); p[0] = mpi_sint_abs(b); - B.s = (b < 0) ? -1 : 1; + B.s = TO_SIGN(b); B.n = 1; B.p = p; @@ -1386,98 +1177,15 @@ int mbedtls_mpi_sub_int(mbedtls_mpi *X, const mbedtls_mpi *A, mbedtls_mpi_sint b { mbedtls_mpi B; mbedtls_mpi_uint p[1]; - MPI_VALIDATE_RET(X != NULL); - MPI_VALIDATE_RET(A != NULL); p[0] = mpi_sint_abs(b); - B.s = (b < 0) ? -1 : 1; + B.s = TO_SIGN(b); B.n = 1; B.p = p; return mbedtls_mpi_sub_mpi(X, A, &B); } -/** Helper for mbedtls_mpi multiplication. - * - * Add \p b * \p s to \p d. - * - * \param i The number of limbs of \p s. - * \param[in] s A bignum to multiply, of size \p i. - * It may overlap with \p d, but only if - * \p d <= \p s. - * Its leading limb must not be \c 0. - * \param[in,out] d The bignum to add to. - * It must be sufficiently large to store the - * result of the multiplication. This means - * \p i + 1 limbs if \p d[\p i - 1] started as 0 and \p b - * is not known a priori. - * \param b A scalar to multiply. - */ -static -#if defined(__APPLE__) && defined(__arm__) -/* - * Apple LLVM version 4.2 (clang-425.0.24) (based on LLVM 3.2svn) - * appears to need this to prevent bad ARM code generation at -O3. - */ -__attribute__((noinline)) -#endif -void mpi_mul_hlp(size_t i, - const mbedtls_mpi_uint *s, - mbedtls_mpi_uint *d, - mbedtls_mpi_uint b) -{ - mbedtls_mpi_uint c = 0, t = 0; - (void) t; /* Unused in some architectures */ - -#if defined(MULADDC_HUIT) - for (; i >= 8; i -= 8) { - MULADDC_INIT - MULADDC_HUIT - MULADDC_STOP - } - - for (; i > 0; i--) { - MULADDC_INIT - MULADDC_CORE - MULADDC_STOP - } -#else /* MULADDC_HUIT */ - for (; i >= 16; i -= 16) { - MULADDC_INIT - MULADDC_CORE MULADDC_CORE - MULADDC_CORE MULADDC_CORE - MULADDC_CORE MULADDC_CORE - MULADDC_CORE MULADDC_CORE - - MULADDC_CORE MULADDC_CORE - MULADDC_CORE MULADDC_CORE - MULADDC_CORE MULADDC_CORE - MULADDC_CORE MULADDC_CORE - MULADDC_STOP - } - - for (; i >= 8; i -= 8) { - MULADDC_INIT - MULADDC_CORE MULADDC_CORE - MULADDC_CORE MULADDC_CORE - - MULADDC_CORE MULADDC_CORE - MULADDC_CORE MULADDC_CORE - MULADDC_STOP - } - - for (; i > 0; i--) { - MULADDC_INIT - MULADDC_CORE - MULADDC_STOP - } -#endif /* MULADDC_HUIT */ - - while (c != 0) { - *d += c; c = (*d < c); d++; - } -} - /* * Baseline multiplication: X = A * B (HAC 14.12) */ @@ -1487,11 +1195,9 @@ int mbedtls_mpi_mul_mpi(mbedtls_mpi *X, const mbedtls_mpi *A, const mbedtls_mpi size_t i, j; mbedtls_mpi TA, TB; int result_is_zero = 0; - MPI_VALIDATE_RET(X != NULL); - MPI_VALIDATE_RET(A != NULL); - MPI_VALIDATE_RET(B != NULL); - mbedtls_mpi_init(&TA); mbedtls_mpi_init(&TB); + mbedtls_mpi_init(&TA); + mbedtls_mpi_init(&TB); if (X == A) { MBEDTLS_MPI_CHK(mbedtls_mpi_copy(&TA, A)); A = &TA; @@ -1521,9 +1227,7 @@ int mbedtls_mpi_mul_mpi(mbedtls_mpi *X, const mbedtls_mpi *A, const mbedtls_mpi MBEDTLS_MPI_CHK(mbedtls_mpi_grow(X, i + j)); MBEDTLS_MPI_CHK(mbedtls_mpi_lset(X, 0)); - for (; j > 0; j--) { - mpi_mul_hlp(i, A->p, X->p + j - 1, B->p[j - 1]); - } + mbedtls_mpi_core_mul(X->p, A->p, i, B->p, j); /* If the result is 0, we don't shortcut the operation, which reduces * but does not eliminate side channels leaking the zero-ness. We do @@ -1547,22 +1251,17 @@ int mbedtls_mpi_mul_mpi(mbedtls_mpi *X, const mbedtls_mpi *A, const mbedtls_mpi */ int mbedtls_mpi_mul_int(mbedtls_mpi *X, const mbedtls_mpi *A, mbedtls_mpi_uint b) { - MPI_VALIDATE_RET(X != NULL); - MPI_VALIDATE_RET(A != NULL); - - /* mpi_mul_hlp can't deal with a leading 0. */ size_t n = A->n; while (n > 0 && A->p[n - 1] == 0) { --n; } - /* The general method below doesn't work if n==0 or b==0. By chance - * calculating the result is trivial in those cases. */ + /* The general method below doesn't work if b==0. */ if (b == 0 || n == 0) { return mbedtls_mpi_lset(X, 0); } - /* Calculate A*b as A + A*(b-1) to take advantage of mpi_mul_hlp */ + /* Calculate A*b as A + A*(b-1) to take advantage of mbedtls_mpi_core_mla */ int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED; /* In general, A * b requires 1 limb more than b. If * A->p[n - 1] * b / b == A->p[n - 1], then A * b fits in the same @@ -1571,10 +1270,13 @@ int mbedtls_mpi_mul_int(mbedtls_mpi *X, const mbedtls_mpi *A, mbedtls_mpi_uint b * making the call to grow() unconditional causes slightly fewer * calls to calloc() in ECP code, presumably because it reuses the * same mpi for a while and this way the mpi is more likely to directly - * grow to its final size. */ + * grow to its final size. + * + * Note that calculating A*b as 0 + A*b doesn't work as-is because + * A,X can be the same. */ MBEDTLS_MPI_CHK(mbedtls_mpi_grow(X, n + 1)); MBEDTLS_MPI_CHK(mbedtls_mpi_copy(X, A)); - mpi_mul_hlp(n, A->p, X->p, b - 1); + mbedtls_mpi_core_mla(X->p, X->n, A->p, n, b - 1); cleanup: return ret; @@ -1633,7 +1335,7 @@ static mbedtls_mpi_uint mbedtls_int_div_int(mbedtls_mpi_uint u1, /* * Normalize the divisor, d, and dividend, u0, u1 */ - s = mbedtls_clz(d); + s = mbedtls_mpi_core_clz(d); d = d << s; u1 = u1 << s; @@ -1694,8 +1396,6 @@ int mbedtls_mpi_div_mpi(mbedtls_mpi *Q, mbedtls_mpi *R, const mbedtls_mpi *A, size_t i, n, t, k; mbedtls_mpi X, Y, Z, T1, T2; mbedtls_mpi_uint TP2[3]; - MPI_VALIDATE_RET(A != NULL); - MPI_VALIDATE_RET(B != NULL); if (mbedtls_mpi_cmp_int(B, 0) == 0) { return MBEDTLS_ERR_MPI_DIVISION_BY_ZERO; @@ -1818,10 +1518,9 @@ int mbedtls_mpi_div_int(mbedtls_mpi *Q, mbedtls_mpi *R, { mbedtls_mpi B; mbedtls_mpi_uint p[1]; - MPI_VALIDATE_RET(A != NULL); p[0] = mpi_sint_abs(b); - B.s = (b < 0) ? -1 : 1; + B.s = TO_SIGN(b); B.n = 1; B.p = p; @@ -1834,9 +1533,6 @@ int mbedtls_mpi_div_int(mbedtls_mpi *Q, mbedtls_mpi *R, int mbedtls_mpi_mod_mpi(mbedtls_mpi *R, const mbedtls_mpi *A, const mbedtls_mpi *B) { int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED; - MPI_VALIDATE_RET(R != NULL); - MPI_VALIDATE_RET(A != NULL); - MPI_VALIDATE_RET(B != NULL); if (mbedtls_mpi_cmp_int(B, 0) < 0) { return MBEDTLS_ERR_MPI_NEGATIVE_VALUE; @@ -1864,8 +1560,6 @@ int mbedtls_mpi_mod_int(mbedtls_mpi_uint *r, const mbedtls_mpi *A, mbedtls_mpi_s { size_t i; mbedtls_mpi_uint x, y, z; - MPI_VALIDATE_RET(r != NULL); - MPI_VALIDATE_RET(A != NULL); if (b == 0) { return MBEDTLS_ERR_MPI_DIVISION_BY_ZERO; @@ -1916,161 +1610,11 @@ int mbedtls_mpi_mod_int(mbedtls_mpi_uint *r, const mbedtls_mpi *A, mbedtls_mpi_s return 0; } -/* - * Fast Montgomery initialization (thanks to Tom St Denis) - */ -static void mpi_montg_init(mbedtls_mpi_uint *mm, const mbedtls_mpi *N) -{ - mbedtls_mpi_uint x, m0 = N->p[0]; - unsigned int i; - - x = m0; - x += ((m0 + 2) & 4) << 1; - - for (i = biL; i >= 8; i /= 2) { - x *= (2 - (m0 * x)); - } - - *mm = ~x + 1; -} - -/** Montgomery multiplication: A = A * B * R^-1 mod N (HAC 14.36) - * - * \param[in,out] A One of the numbers to multiply. - * It must have at least as many limbs as N - * (A->n >= N->n), and any limbs beyond n are ignored. - * On successful completion, A contains the result of - * the multiplication A * B * R^-1 mod N where - * R = (2^ciL)^n. - * \param[in] B One of the numbers to multiply. - * It must be nonzero and must not have more limbs than N - * (B->n <= N->n). - * \param[in] N The modulo. N must be odd. - * \param mm The value calculated by `mpi_montg_init(&mm, N)`. - * This is -N^-1 mod 2^ciL. - * \param[in,out] T A bignum for temporary storage. - * It must be at least twice the limb size of N plus 2 - * (T->n >= 2 * (N->n + 1)). - * Its initial content is unused and - * its final content is indeterminate. - * Note that unlike the usual convention in the library - * for `const mbedtls_mpi*`, the content of T can change. - */ -static void mpi_montmul(mbedtls_mpi *A, - const mbedtls_mpi *B, - const mbedtls_mpi *N, - mbedtls_mpi_uint mm, - const mbedtls_mpi *T) -{ - size_t i, n, m; - mbedtls_mpi_uint u0, u1, *d; - - memset(T->p, 0, T->n * ciL); - - d = T->p; - n = N->n; - m = (B->n < n) ? B->n : n; - - for (i = 0; i < n; i++) { - /* - * T = (T + u0*B + u1*N) / 2^biL - */ - u0 = A->p[i]; - u1 = (d[0] + u0 * B->p[0]) * mm; - - mpi_mul_hlp(m, B->p, d, u0); - mpi_mul_hlp(n, N->p, d, u1); - - *d++ = u0; d[n + 1] = 0; - } - - /* At this point, d is either the desired result or the desired result - * plus N. We now potentially subtract N, avoiding leaking whether the - * subtraction is performed through side channels. */ - - /* Copy the n least significant limbs of d to A, so that - * A = d if d < N (recall that N has n limbs). */ - memcpy(A->p, d, n * ciL); - /* If d >= N then we want to set A to d - N. To prevent timing attacks, - * do the calculation without using conditional tests. */ - /* Set d to d0 + (2^biL)^n - N where d0 is the current value of d. */ - d[n] += 1; - d[n] -= mpi_sub_hlp(n, d, d, N->p); - /* If d0 < N then d < (2^biL)^n - * so d[n] == 0 and we want to keep A as it is. - * If d0 >= N then d >= (2^biL)^n, and d <= (2^biL)^n + N < 2 * (2^biL)^n - * so d[n] == 1 and we want to set A to the result of the subtraction - * which is d - (2^biL)^n, i.e. the n least significant limbs of d. - * This exactly corresponds to a conditional assignment. */ - mbedtls_ct_mpi_uint_cond_assign(n, A->p, d, (unsigned char) d[n]); -} - -/* - * Montgomery reduction: A = A * R^-1 mod N - * - * See mpi_montmul() regarding constraints and guarantees on the parameters. - */ -static void mpi_montred(mbedtls_mpi *A, const mbedtls_mpi *N, - mbedtls_mpi_uint mm, const mbedtls_mpi *T) -{ - mbedtls_mpi_uint z = 1; - mbedtls_mpi U; - - U.n = U.s = (int) z; - U.p = &z; - - mpi_montmul(A, &U, N, mm, T); -} - -/** - * Select an MPI from a table without leaking the index. - * - * This is functionally equivalent to mbedtls_mpi_copy(R, T[idx]) except it - * reads the entire table in order to avoid leaking the value of idx to an - * attacker able to observe memory access patterns. - * - * \param[out] R Where to write the selected MPI. - * \param[in] T The table to read from. - * \param[in] T_size The number of elements in the table. - * \param[in] idx The index of the element to select; - * this must satisfy 0 <= idx < T_size. - * - * \return \c 0 on success, or a negative error code. - */ -static int mpi_select(mbedtls_mpi *R, const mbedtls_mpi *T, size_t T_size, size_t idx) -{ - int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED; - - for (size_t i = 0; i < T_size; i++) { - MBEDTLS_MPI_CHK(mbedtls_mpi_safe_cond_assign(R, &T[i], - (unsigned char) mbedtls_ct_size_bool_eq(i, - idx))); - } - -cleanup: - return ret; -} - -/* - * Sliding-window exponentiation: X = A^E mod N (HAC 14.85) - */ int mbedtls_mpi_exp_mod(mbedtls_mpi *X, const mbedtls_mpi *A, const mbedtls_mpi *E, const mbedtls_mpi *N, mbedtls_mpi *prec_RR) { int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED; - size_t window_bitsize; - size_t i, j, nblimbs; - size_t bufsize, nbits; - size_t exponent_bits_in_window = 0; - mbedtls_mpi_uint ei, mm, state; - mbedtls_mpi RR, T, W[(size_t) 1 << MBEDTLS_MPI_WINDOW_SIZE], WW, Apos; - int neg; - - MPI_VALIDATE_RET(X != NULL); - MPI_VALIDATE_RET(A != NULL); - MPI_VALIDATE_RET(E != NULL); - MPI_VALIDATE_RET(N != NULL); if (mbedtls_mpi_cmp_int(N, 0) <= 0 || (N->p[0] & 1) == 0) { return MBEDTLS_ERR_MPI_BAD_INPUT_DATA; @@ -2086,261 +1630,88 @@ int mbedtls_mpi_exp_mod(mbedtls_mpi *X, const mbedtls_mpi *A, } /* - * Init temps and window size + * Ensure that the exponent that we are passing to the core is not NULL. */ - mpi_montg_init(&mm, N); - mbedtls_mpi_init(&RR); mbedtls_mpi_init(&T); - mbedtls_mpi_init(&Apos); - mbedtls_mpi_init(&WW); - memset(W, 0, sizeof(W)); - - i = mbedtls_mpi_bitlen(E); - - window_bitsize = (i > 671) ? 6 : (i > 239) ? 5 : - (i > 79) ? 4 : (i > 23) ? 3 : 1; - -#if (MBEDTLS_MPI_WINDOW_SIZE < 6) - if (window_bitsize > MBEDTLS_MPI_WINDOW_SIZE) { - window_bitsize = MBEDTLS_MPI_WINDOW_SIZE; + if (E->n == 0) { + ret = mbedtls_mpi_lset(X, 1); + return ret; } -#endif - - const size_t w_table_used_size = (size_t) 1 << window_bitsize; - - /* - * This function is not constant-trace: its memory accesses depend on the - * exponent value. To defend against timing attacks, callers (such as RSA - * and DHM) should use exponent blinding. However this is not enough if the - * adversary can find the exponent in a single trace, so this function - * takes extra precautions against adversaries who can observe memory - * access patterns. - * - * This function performs a series of multiplications by table elements and - * squarings, and we want the prevent the adversary from finding out which - * table element was used, and from distinguishing between multiplications - * and squarings. Firstly, when multiplying by an element of the window - * W[i], we do a constant-trace table lookup to obfuscate i. This leaves - * squarings as having a different memory access patterns from other - * multiplications. So secondly, we put the accumulator in the table as - * well, and also do a constant-trace table lookup to multiply by the - * accumulator which is W[x_index]. - * - * This way, all multiplications take the form of a lookup-and-multiply. - * The number of lookup-and-multiply operations inside each iteration of - * the main loop still depends on the bits of the exponent, but since the - * other operations in the loop don't have an easily recognizable memory - * trace, an adversary is unlikely to be able to observe the exact - * patterns. - * - * An adversary may still be able to recover the exponent if they can - * observe both memory accesses and branches. However, branch prediction - * exploitation typically requires many traces of execution over the same - * data, which is defeated by randomized blinding. - */ - const size_t x_index = 0; - mbedtls_mpi_init(&W[x_index]); - - j = N->n + 1; - /* All W[i] including the accumulator must have at least N->n limbs for - * the mpi_montmul() and mpi_montred() calls later. Here we ensure that - * W[1] and the accumulator W[x_index] are large enough. later we'll grow - * other W[i] to the same length. They must not be shrunk midway through - * this function! - */ - MBEDTLS_MPI_CHK(mbedtls_mpi_grow(&W[x_index], j)); - MBEDTLS_MPI_CHK(mbedtls_mpi_grow(&W[1], j)); - MBEDTLS_MPI_CHK(mbedtls_mpi_grow(&T, j * 2)); /* - * Compensate for negative A (and correct at the end) + * Allocate working memory for mbedtls_mpi_core_exp_mod() */ - neg = (A->s == -1); - if (neg) { - MBEDTLS_MPI_CHK(mbedtls_mpi_copy(&Apos, A)); - Apos.s = 1; - A = &Apos; + size_t T_limbs = mbedtls_mpi_core_exp_mod_working_limbs(N->n, E->n); + mbedtls_mpi_uint *T = (mbedtls_mpi_uint *) mbedtls_calloc(T_limbs, sizeof(mbedtls_mpi_uint)); + if (T == NULL) { + return MBEDTLS_ERR_MPI_ALLOC_FAILED; } + mbedtls_mpi RR; + mbedtls_mpi_init(&RR); + /* * If 1st call, pre-compute R^2 mod N */ if (prec_RR == NULL || prec_RR->p == NULL) { - MBEDTLS_MPI_CHK(mbedtls_mpi_lset(&RR, 1)); - MBEDTLS_MPI_CHK(mbedtls_mpi_shift_l(&RR, N->n * 2 * biL)); - MBEDTLS_MPI_CHK(mbedtls_mpi_mod_mpi(&RR, &RR, N)); + MBEDTLS_MPI_CHK(mbedtls_mpi_core_get_mont_r2_unsafe(&RR, N)); if (prec_RR != NULL) { - memcpy(prec_RR, &RR, sizeof(mbedtls_mpi)); + *prec_RR = RR; } } else { - memcpy(&RR, prec_RR, sizeof(mbedtls_mpi)); + MBEDTLS_MPI_CHK(mbedtls_mpi_grow(prec_RR, N->n)); + RR = *prec_RR; } /* - * W[1] = A * R^2 * R^-1 mod N = A * R mod N + * To preserve constness we need to make a copy of A. Using X for this to + * save memory. */ - if (mbedtls_mpi_cmp_mpi(A, N) >= 0) { - MBEDTLS_MPI_CHK(mbedtls_mpi_mod_mpi(&W[1], A, N)); - /* This should be a no-op because W[1] is already that large before - * mbedtls_mpi_mod_mpi(), but it's necessary to avoid an overflow - * in mpi_montmul() below, so let's make sure. */ - MBEDTLS_MPI_CHK(mbedtls_mpi_grow(&W[1], N->n + 1)); - } else { - MBEDTLS_MPI_CHK(mbedtls_mpi_copy(&W[1], A)); - } - - /* Note that this is safe because W[1] always has at least N->n limbs - * (it grew above and was preserved by mbedtls_mpi_copy()). */ - mpi_montmul(&W[1], &RR, N, mm, &T); + MBEDTLS_MPI_CHK(mbedtls_mpi_copy(X, A)); /* - * W[x_index] = R^2 * R^-1 mod N = R mod N + * Compensate for negative A (and correct at the end). */ - MBEDTLS_MPI_CHK(mbedtls_mpi_copy(&W[x_index], &RR)); - mpi_montred(&W[x_index], N, mm, &T); - - - if (window_bitsize > 1) { - /* - * W[i] = W[1] ^ i - * - * The first bit of the sliding window is always 1 and therefore we - * only need to store the second half of the table. - * - * (There are two special elements in the table: W[0] for the - * accumulator/result and W[1] for A in Montgomery form. Both of these - * are already set at this point.) - */ - j = w_table_used_size / 2; - - MBEDTLS_MPI_CHK(mbedtls_mpi_grow(&W[j], N->n + 1)); - MBEDTLS_MPI_CHK(mbedtls_mpi_copy(&W[j], &W[1])); - - for (i = 0; i < window_bitsize - 1; i++) { - mpi_montmul(&W[j], &W[j], N, mm, &T); - } - - /* - * W[i] = W[i - 1] * W[1] - */ - for (i = j + 1; i < w_table_used_size; i++) { - MBEDTLS_MPI_CHK(mbedtls_mpi_grow(&W[i], N->n + 1)); - MBEDTLS_MPI_CHK(mbedtls_mpi_copy(&W[i], &W[i - 1])); - - mpi_montmul(&W[i], &W[1], N, mm, &T); - } - } - - nblimbs = E->n; - bufsize = 0; - nbits = 0; - state = 0; - - while (1) { - if (bufsize == 0) { - if (nblimbs == 0) { - break; - } - - nblimbs--; - - bufsize = sizeof(mbedtls_mpi_uint) << 3; - } - - bufsize--; - - ei = (E->p[nblimbs] >> bufsize) & 1; - - /* - * skip leading 0s - */ - if (ei == 0 && state == 0) { - continue; - } - - if (ei == 0 && state == 1) { - /* - * out of window, square W[x_index] - */ - MBEDTLS_MPI_CHK(mpi_select(&WW, W, w_table_used_size, x_index)); - mpi_montmul(&W[x_index], &WW, N, mm, &T); - continue; - } - - /* - * add ei to current window - */ - state = 2; - - nbits++; - exponent_bits_in_window |= (ei << (window_bitsize - nbits)); - - if (nbits == window_bitsize) { - /* - * W[x_index] = W[x_index]^window_bitsize R^-1 mod N - */ - for (i = 0; i < window_bitsize; i++) { - MBEDTLS_MPI_CHK(mpi_select(&WW, W, w_table_used_size, - x_index)); - mpi_montmul(&W[x_index], &WW, N, mm, &T); - } - - /* - * W[x_index] = W[x_index] * W[exponent_bits_in_window] R^-1 mod N - */ - MBEDTLS_MPI_CHK(mpi_select(&WW, W, w_table_used_size, - exponent_bits_in_window)); - mpi_montmul(&W[x_index], &WW, N, mm, &T); - - state--; - nbits = 0; - exponent_bits_in_window = 0; - } - } + X->s = 1; /* - * process the remaining bits + * Make sure that X is in a form that is safe for consumption by + * the core functions. + * + * - The core functions will not touch the limbs of X above N->n. The + * result will be correct if those limbs are 0, which the mod call + * ensures. + * - Also, X must have at least as many limbs as N for the calls to the + * core functions. */ - for (i = 0; i < nbits; i++) { - MBEDTLS_MPI_CHK(mpi_select(&WW, W, w_table_used_size, x_index)); - mpi_montmul(&W[x_index], &WW, N, mm, &T); - - exponent_bits_in_window <<= 1; - - if ((exponent_bits_in_window & ((size_t) 1 << window_bitsize)) != 0) { - MBEDTLS_MPI_CHK(mpi_select(&WW, W, w_table_used_size, 1)); - mpi_montmul(&W[x_index], &WW, N, mm, &T); - } + if (mbedtls_mpi_cmp_mpi(X, N) >= 0) { + MBEDTLS_MPI_CHK(mbedtls_mpi_mod_mpi(X, X, N)); } + MBEDTLS_MPI_CHK(mbedtls_mpi_grow(X, N->n)); /* - * W[x_index] = A^E * R * R^-1 mod N = A^E mod N + * Convert to and from Montgomery around mbedtls_mpi_core_exp_mod(). */ - mpi_montred(&W[x_index], N, mm, &T); - - if (neg && E->n != 0 && (E->p[0] & 1) != 0) { - W[x_index].s = -1; - MBEDTLS_MPI_CHK(mbedtls_mpi_add_mpi(&W[x_index], N, &W[x_index])); + { + mbedtls_mpi_uint mm = mbedtls_mpi_core_montmul_init(N->p); + mbedtls_mpi_core_to_mont_rep(X->p, X->p, N->p, N->n, mm, RR.p, T); + mbedtls_mpi_core_exp_mod(X->p, X->p, N->p, N->n, E->p, E->n, RR.p, T); + mbedtls_mpi_core_from_mont_rep(X->p, X->p, N->p, N->n, mm, T); } /* - * Load the result in the output variable. + * Correct for negative A. */ - MBEDTLS_MPI_CHK(mbedtls_mpi_copy(X, &W[x_index])); - -cleanup: + if (A->s == -1 && (E->p[0] & 1) != 0) { + mbedtls_ct_condition_t is_x_non_zero = mbedtls_mpi_core_check_zero_ct(X->p, X->n); + X->s = mbedtls_ct_mpi_sign_if(is_x_non_zero, -1, 1); - /* The first bit of the sliding window is always 1 and therefore the first - * half of the table was unused. */ - for (i = w_table_used_size/2; i < w_table_used_size; i++) { - mbedtls_mpi_free(&W[i]); + MBEDTLS_MPI_CHK(mbedtls_mpi_add_mpi(X, N, X)); } - mbedtls_mpi_free(&W[x_index]); - mbedtls_mpi_free(&W[1]); - mbedtls_mpi_free(&T); - mbedtls_mpi_free(&Apos); - mbedtls_mpi_free(&WW); +cleanup: + + mbedtls_mpi_zeroize_and_free(T, T_limbs); if (prec_RR == NULL || prec_RR->p == NULL) { mbedtls_mpi_free(&RR); @@ -2358,10 +1729,6 @@ int mbedtls_mpi_gcd(mbedtls_mpi *G, const mbedtls_mpi *A, const mbedtls_mpi *B) size_t lz, lzt; mbedtls_mpi TA, TB; - MPI_VALIDATE_RET(G != NULL); - MPI_VALIDATE_RET(A != NULL); - MPI_VALIDATE_RET(B != NULL); - mbedtls_mpi_init(&TA); mbedtls_mpi_init(&TB); MBEDTLS_MPI_CHK(mbedtls_mpi_copy(&TA, A)); @@ -2459,50 +1826,18 @@ int mbedtls_mpi_gcd(mbedtls_mpi *G, const mbedtls_mpi *A, const mbedtls_mpi *B) return ret; } -/* Fill X with n_bytes random bytes. - * X must already have room for those bytes. - * The ordering of the bytes returned from the RNG is suitable for - * deterministic ECDSA (see RFC 6979 §3.3 and mbedtls_mpi_random()). - * The size and sign of X are unchanged. - * n_bytes must not be 0. - */ -static int mpi_fill_random_internal( - mbedtls_mpi *X, size_t n_bytes, - int (*f_rng)(void *, unsigned char *, size_t), void *p_rng) -{ - int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED; - const size_t limbs = CHARS_TO_LIMBS(n_bytes); - const size_t overhead = (limbs * ciL) - n_bytes; - - if (X->n < limbs) { - return MBEDTLS_ERR_MPI_BAD_INPUT_DATA; - } - - memset(X->p, 0, overhead); - memset((unsigned char *) X->p + limbs * ciL, 0, (X->n - limbs) * ciL); - MBEDTLS_MPI_CHK(f_rng(p_rng, (unsigned char *) X->p + overhead, n_bytes)); - mpi_bigendian_to_host(X->p, limbs); - -cleanup: - return ret; -} - /* * Fill X with size bytes of random. - * - * Use a temporary bytes representation to make sure the result is the same - * regardless of the platform endianness (useful when f_rng is actually - * deterministic, eg for tests). + * The bytes returned from the RNG are used in a specific order which + * is suitable for deterministic ECDSA (see the specification of + * mbedtls_mpi_random() and the implementation in mbedtls_mpi_fill_random()). */ int mbedtls_mpi_fill_random(mbedtls_mpi *X, size_t size, int (*f_rng)(void *, unsigned char *, size_t), void *p_rng) { int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED; - size_t const limbs = CHARS_TO_LIMBS(size); - - MPI_VALIDATE_RET(X != NULL); - MPI_VALIDATE_RET(f_rng != NULL); + const size_t limbs = CHARS_TO_LIMBS(size); /* Ensure that target MPI has exactly the necessary number of limbs */ MBEDTLS_MPI_CHK(mbedtls_mpi_resize_clear(X, limbs)); @@ -2510,7 +1845,7 @@ int mbedtls_mpi_fill_random(mbedtls_mpi *X, size_t size, return 0; } - ret = mpi_fill_random_internal(X, size, f_rng, p_rng); + ret = mbedtls_mpi_core_fill_random(X->p, X->n, size, f_rng, p_rng); cleanup: return ret; @@ -2522,13 +1857,6 @@ int mbedtls_mpi_random(mbedtls_mpi *X, int (*f_rng)(void *, unsigned char *, size_t), void *p_rng) { - int ret = MBEDTLS_ERR_MPI_BAD_INPUT_DATA; - int count; - unsigned lt_lower = 1, lt_upper = 0; - size_t n_bits = mbedtls_mpi_bitlen(N); - size_t n_bytes = (n_bits + 7) / 8; - mbedtls_mpi lower_bound; - if (min < 0) { return MBEDTLS_ERR_MPI_BAD_INPUT_DATA; } @@ -2536,58 +1864,15 @@ int mbedtls_mpi_random(mbedtls_mpi *X, return MBEDTLS_ERR_MPI_BAD_INPUT_DATA; } - /* - * When min == 0, each try has at worst a probability 1/2 of failing - * (the msb has a probability 1/2 of being 0, and then the result will - * be < N), so after 30 tries failure probability is a most 2**(-30). - * - * When N is just below a power of 2, as is the case when generating - * a random scalar on most elliptic curves, 1 try is enough with - * overwhelming probability. When N is just above a power of 2, - * as when generating a random scalar on secp224k1, each try has - * a probability of failing that is almost 1/2. - * - * The probabilities are almost the same if min is nonzero but negligible - * compared to N. This is always the case when N is crypto-sized, but - * it's convenient to support small N for testing purposes. When N - * is small, use a higher repeat count, otherwise the probability of - * failure is macroscopic. - */ - count = (n_bytes > 4 ? 30 : 250); - - mbedtls_mpi_init(&lower_bound); - /* Ensure that target MPI has exactly the same number of limbs * as the upper bound, even if the upper bound has leading zeros. - * This is necessary for the mbedtls_mpi_lt_mpi_ct() check. */ - MBEDTLS_MPI_CHK(mbedtls_mpi_resize_clear(X, N->n)); - MBEDTLS_MPI_CHK(mbedtls_mpi_grow(&lower_bound, N->n)); - MBEDTLS_MPI_CHK(mbedtls_mpi_lset(&lower_bound, min)); - - /* - * Match the procedure given in RFC 6979 §3.3 (deterministic ECDSA) - * when f_rng is a suitably parametrized instance of HMAC_DRBG: - * - use the same byte ordering; - * - keep the leftmost n_bits bits of the generated octet string; - * - try until result is in the desired range. - * This also avoids any bias, which is especially important for ECDSA. - */ - do { - MBEDTLS_MPI_CHK(mpi_fill_random_internal(X, n_bytes, f_rng, p_rng)); - MBEDTLS_MPI_CHK(mbedtls_mpi_shift_r(X, 8 * n_bytes - n_bits)); - - if (--count == 0) { - ret = MBEDTLS_ERR_MPI_NOT_ACCEPTABLE; - goto cleanup; - } - - MBEDTLS_MPI_CHK(mbedtls_mpi_lt_mpi_ct(X, &lower_bound, <_lower)); - MBEDTLS_MPI_CHK(mbedtls_mpi_lt_mpi_ct(X, N, <_upper)); - } while (lt_lower != 0 || lt_upper == 0); + * This is necessary for mbedtls_mpi_core_random. */ + int ret = mbedtls_mpi_resize_clear(X, N->n); + if (ret != 0) { + return ret; + } -cleanup: - mbedtls_mpi_free(&lower_bound); - return ret; + return mbedtls_mpi_core_random(X->p, min, N->p, X->n, f_rng, p_rng); } /* @@ -2597,9 +1882,6 @@ int mbedtls_mpi_inv_mod(mbedtls_mpi *X, const mbedtls_mpi *A, const mbedtls_mpi { int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED; mbedtls_mpi G, TA, TU, U1, U2, TB, TV, V1, V2; - MPI_VALIDATE_RET(X != NULL); - MPI_VALIDATE_RET(A != NULL); - MPI_VALIDATE_RET(N != NULL); if (mbedtls_mpi_cmp_int(N, 1) <= 0) { return MBEDTLS_ERR_MPI_BAD_INPUT_DATA; @@ -2683,29 +1965,30 @@ int mbedtls_mpi_inv_mod(mbedtls_mpi *X, const mbedtls_mpi *A, const mbedtls_mpi #if defined(MBEDTLS_GENPRIME) -static const int small_prime[] = -{ - 3, 5, 7, 11, 13, 17, 19, 23, - 29, 31, 37, 41, 43, 47, 53, 59, - 61, 67, 71, 73, 79, 83, 89, 97, - 101, 103, 107, 109, 113, 127, 131, 137, - 139, 149, 151, 157, 163, 167, 173, 179, - 181, 191, 193, 197, 199, 211, 223, 227, - 229, 233, 239, 241, 251, 257, 263, 269, - 271, 277, 281, 283, 293, 307, 311, 313, - 317, 331, 337, 347, 349, 353, 359, 367, - 373, 379, 383, 389, 397, 401, 409, 419, - 421, 431, 433, 439, 443, 449, 457, 461, - 463, 467, 479, 487, 491, 499, 503, 509, - 521, 523, 541, 547, 557, 563, 569, 571, - 577, 587, 593, 599, 601, 607, 613, 617, - 619, 631, 641, 643, 647, 653, 659, 661, - 673, 677, 683, 691, 701, 709, 719, 727, - 733, 739, 743, 751, 757, 761, 769, 773, - 787, 797, 809, 811, 821, 823, 827, 829, - 839, 853, 857, 859, 863, 877, 881, 883, - 887, 907, 911, 919, 929, 937, 941, 947, - 953, 967, 971, 977, 983, 991, 997, -103 +/* Gaps between primes, starting at 3. https://oeis.org/A001223 */ +static const unsigned char small_prime_gaps[] = { + 2, 2, 4, 2, 4, 2, 4, 6, + 2, 6, 4, 2, 4, 6, 6, 2, + 6, 4, 2, 6, 4, 6, 8, 4, + 2, 4, 2, 4, 14, 4, 6, 2, + 10, 2, 6, 6, 4, 6, 6, 2, + 10, 2, 4, 2, 12, 12, 4, 2, + 4, 6, 2, 10, 6, 6, 6, 2, + 6, 4, 2, 10, 14, 4, 2, 4, + 14, 6, 10, 2, 4, 6, 8, 6, + 6, 4, 6, 8, 4, 8, 10, 2, + 10, 2, 6, 4, 6, 8, 4, 2, + 4, 12, 8, 4, 8, 4, 6, 12, + 2, 18, 6, 10, 6, 6, 2, 6, + 10, 6, 6, 2, 6, 6, 4, 2, + 12, 10, 2, 4, 6, 6, 2, 12, + 4, 6, 8, 10, 8, 10, 8, 6, + 6, 4, 8, 6, 4, 8, 4, 14, + 10, 12, 2, 10, 2, 4, 2, 10, + 14, 4, 2, 4, 14, 4, 2, 4, + 20, 4, 8, 10, 8, 4, 6, 6, + 14, 4, 6, 6, 8, 6, /*reaches 997*/ + 0 /* the last entry is effectively unused */ }; /* @@ -2722,20 +2005,20 @@ static int mpi_check_small_factors(const mbedtls_mpi *X) int ret = 0; size_t i; mbedtls_mpi_uint r; + unsigned p = 3; /* The first odd prime */ if ((X->p[0] & 1) == 0) { return MBEDTLS_ERR_MPI_NOT_ACCEPTABLE; } - for (i = 0; small_prime[i] > 0; i++) { - if (mbedtls_mpi_cmp_int(X, small_prime[i]) <= 0) { - return 1; - } - - MBEDTLS_MPI_CHK(mbedtls_mpi_mod_int(&r, X, small_prime[i])); - + for (i = 0; i < sizeof(small_prime_gaps); p += small_prime_gaps[i], i++) { + MBEDTLS_MPI_CHK(mbedtls_mpi_mod_int(&r, X, p)); if (r == 0) { - return MBEDTLS_ERR_MPI_NOT_ACCEPTABLE; + if (mbedtls_mpi_cmp_int(X, p) == 0) { + return 1; + } else { + return MBEDTLS_ERR_MPI_NOT_ACCEPTABLE; + } } } @@ -2754,9 +2037,6 @@ static int mpi_miller_rabin(const mbedtls_mpi *X, size_t rounds, size_t i, j, k, s; mbedtls_mpi W, R, T, A, RR; - MPI_VALIDATE_RET(X != NULL); - MPI_VALIDATE_RET(f_rng != NULL); - mbedtls_mpi_init(&W); mbedtls_mpi_init(&R); mbedtls_mpi_init(&T); mbedtls_mpi_init(&A); mbedtls_mpi_init(&RR); @@ -2844,8 +2124,6 @@ int mbedtls_mpi_is_prime_ext(const mbedtls_mpi *X, int rounds, { int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED; mbedtls_mpi XX; - MPI_VALIDATE_RET(X != NULL); - MPI_VALIDATE_RET(f_rng != NULL); XX.s = 1; XX.n = X->n; @@ -2871,26 +2149,6 @@ int mbedtls_mpi_is_prime_ext(const mbedtls_mpi *X, int rounds, return mpi_miller_rabin(&XX, rounds, f_rng, p_rng); } -#if !defined(MBEDTLS_DEPRECATED_REMOVED) -/* - * Pseudo-primality test, error probability 2^-80 - */ -int mbedtls_mpi_is_prime(const mbedtls_mpi *X, - int (*f_rng)(void *, unsigned char *, size_t), - void *p_rng) -{ - MPI_VALIDATE_RET(X != NULL); - MPI_VALIDATE_RET(f_rng != NULL); - - /* - * In the past our key generation aimed for an error rate of at most - * 2^-80. Since this function is deprecated, aim for the same certainty - * here as well. - */ - return mbedtls_mpi_is_prime_ext(X, 40, f_rng, p_rng); -} -#endif - /* * Prime number generation * @@ -2915,9 +2173,6 @@ int mbedtls_mpi_gen_prime(mbedtls_mpi *X, size_t nbits, int flags, mbedtls_mpi_uint r; mbedtls_mpi Y; - MPI_VALIDATE_RET(X != NULL); - MPI_VALIDATE_RET(f_rng != NULL); - if (nbits < 3 || nbits > MBEDTLS_MPI_MAX_BITS) { return MBEDTLS_ERR_MPI_BAD_INPUT_DATA; } diff --git a/vendor/mbedtls/library/bignum_core.c b/vendor/mbedtls/library/bignum_core.c new file mode 100644 index 0000000000..1a3e0b9b6f --- /dev/null +++ b/vendor/mbedtls/library/bignum_core.c @@ -0,0 +1,895 @@ +/* + * Core bignum functions + * + * Copyright The Mbed TLS Contributors + * SPDX-License-Identifier: Apache-2.0 OR GPL-2.0-or-later + */ + +#include "common.h" + +#if defined(MBEDTLS_BIGNUM_C) + +#include + +#include "mbedtls/error.h" +#include "mbedtls/platform_util.h" +#include "constant_time_internal.h" + +#include "mbedtls/platform.h" + +#include "bignum_core.h" +#include "bn_mul.h" +#include "constant_time_internal.h" + +size_t mbedtls_mpi_core_clz(mbedtls_mpi_uint a) +{ +#if defined(__has_builtin) +#if (MBEDTLS_MPI_UINT_MAX == UINT_MAX) && __has_builtin(__builtin_clz) + #define core_clz __builtin_clz +#elif (MBEDTLS_MPI_UINT_MAX == ULONG_MAX) && __has_builtin(__builtin_clzl) + #define core_clz __builtin_clzl +#elif (MBEDTLS_MPI_UINT_MAX == ULLONG_MAX) && __has_builtin(__builtin_clzll) + #define core_clz __builtin_clzll +#endif +#endif +#if defined(core_clz) + return (size_t) core_clz(a); +#else + size_t j; + mbedtls_mpi_uint mask = (mbedtls_mpi_uint) 1 << (biL - 1); + + for (j = 0; j < biL; j++) { + if (a & mask) { + break; + } + + mask >>= 1; + } + + return j; +#endif +} + +size_t mbedtls_mpi_core_bitlen(const mbedtls_mpi_uint *A, size_t A_limbs) +{ + int i; + size_t j; + + for (i = ((int) A_limbs) - 1; i >= 0; i--) { + if (A[i] != 0) { + j = biL - mbedtls_mpi_core_clz(A[i]); + return (i * biL) + j; + } + } + + return 0; +} + +static mbedtls_mpi_uint mpi_bigendian_to_host(mbedtls_mpi_uint a) +{ + if (MBEDTLS_IS_BIG_ENDIAN) { + /* Nothing to do on bigendian systems. */ + return a; + } else { +#if defined(MBEDTLS_HAVE_INT32) + return (mbedtls_mpi_uint) MBEDTLS_BSWAP32(a); +#elif defined(MBEDTLS_HAVE_INT64) + return (mbedtls_mpi_uint) MBEDTLS_BSWAP64(a); +#endif + } +} + +void mbedtls_mpi_core_bigendian_to_host(mbedtls_mpi_uint *A, + size_t A_limbs) +{ + mbedtls_mpi_uint *cur_limb_left; + mbedtls_mpi_uint *cur_limb_right; + if (A_limbs == 0) { + return; + } + + /* + * Traverse limbs and + * - adapt byte-order in each limb + * - swap the limbs themselves. + * For that, simultaneously traverse the limbs from left to right + * and from right to left, as long as the left index is not bigger + * than the right index (it's not a problem if limbs is odd and the + * indices coincide in the last iteration). + */ + for (cur_limb_left = A, cur_limb_right = A + (A_limbs - 1); + cur_limb_left <= cur_limb_right; + cur_limb_left++, cur_limb_right--) { + mbedtls_mpi_uint tmp; + /* Note that if cur_limb_left == cur_limb_right, + * this code effectively swaps the bytes only once. */ + tmp = mpi_bigendian_to_host(*cur_limb_left); + *cur_limb_left = mpi_bigendian_to_host(*cur_limb_right); + *cur_limb_right = tmp; + } +} + +/* Whether min <= A, in constant time. + * A_limbs must be at least 1. */ +mbedtls_ct_condition_t mbedtls_mpi_core_uint_le_mpi(mbedtls_mpi_uint min, + const mbedtls_mpi_uint *A, + size_t A_limbs) +{ + /* min <= least significant limb? */ + mbedtls_ct_condition_t min_le_lsl = mbedtls_ct_uint_ge(A[0], min); + + /* limbs other than the least significant one are all zero? */ + mbedtls_ct_condition_t msll_mask = MBEDTLS_CT_FALSE; + for (size_t i = 1; i < A_limbs; i++) { + msll_mask = mbedtls_ct_bool_or(msll_mask, mbedtls_ct_bool(A[i])); + } + + /* min <= A iff the lowest limb of A is >= min or the other limbs + * are not all zero. */ + return mbedtls_ct_bool_or(msll_mask, min_le_lsl); +} + +mbedtls_ct_condition_t mbedtls_mpi_core_lt_ct(const mbedtls_mpi_uint *A, + const mbedtls_mpi_uint *B, + size_t limbs) +{ + mbedtls_ct_condition_t ret = MBEDTLS_CT_FALSE, cond = MBEDTLS_CT_FALSE, done = MBEDTLS_CT_FALSE; + + for (size_t i = limbs; i > 0; i--) { + /* + * If B[i - 1] < A[i - 1] then A < B is false and the result must + * remain 0. + * + * Again even if we can make a decision, we just mark the result and + * the fact that we are done and continue looping. + */ + cond = mbedtls_ct_uint_lt(B[i - 1], A[i - 1]); + done = mbedtls_ct_bool_or(done, cond); + + /* + * If A[i - 1] < B[i - 1] then A < B is true. + * + * Again even if we can make a decision, we just mark the result and + * the fact that we are done and continue looping. + */ + cond = mbedtls_ct_uint_lt(A[i - 1], B[i - 1]); + ret = mbedtls_ct_bool_or(ret, mbedtls_ct_bool_and(cond, mbedtls_ct_bool_not(done))); + done = mbedtls_ct_bool_or(done, cond); + } + + /* + * If all the limbs were equal, then the numbers are equal, A < B is false + * and leaving the result 0 is correct. + */ + + return ret; +} + +void mbedtls_mpi_core_cond_assign(mbedtls_mpi_uint *X, + const mbedtls_mpi_uint *A, + size_t limbs, + mbedtls_ct_condition_t assign) +{ + if (X == A) { + return; + } + + /* This function is very performance-sensitive for RSA. For this reason + * we have the loop below, instead of calling mbedtls_ct_memcpy_if + * (this is more optimal since here we don't have to handle the case where + * we copy awkwardly sized data). + */ + for (size_t i = 0; i < limbs; i++) { + X[i] = mbedtls_ct_mpi_uint_if(assign, A[i], X[i]); + } +} + +void mbedtls_mpi_core_cond_swap(mbedtls_mpi_uint *X, + mbedtls_mpi_uint *Y, + size_t limbs, + mbedtls_ct_condition_t swap) +{ + if (X == Y) { + return; + } + + for (size_t i = 0; i < limbs; i++) { + mbedtls_mpi_uint tmp = X[i]; + X[i] = mbedtls_ct_mpi_uint_if(swap, Y[i], X[i]); + Y[i] = mbedtls_ct_mpi_uint_if(swap, tmp, Y[i]); + } +} + +int mbedtls_mpi_core_read_le(mbedtls_mpi_uint *X, + size_t X_limbs, + const unsigned char *input, + size_t input_length) +{ + const size_t limbs = CHARS_TO_LIMBS(input_length); + + if (X_limbs < limbs) { + return MBEDTLS_ERR_MPI_BUFFER_TOO_SMALL; + } + + if (X != NULL) { + memset(X, 0, X_limbs * ciL); + + for (size_t i = 0; i < input_length; i++) { + size_t offset = ((i % ciL) << 3); + X[i / ciL] |= ((mbedtls_mpi_uint) input[i]) << offset; + } + } + + return 0; +} + +int mbedtls_mpi_core_read_be(mbedtls_mpi_uint *X, + size_t X_limbs, + const unsigned char *input, + size_t input_length) +{ + const size_t limbs = CHARS_TO_LIMBS(input_length); + + if (X_limbs < limbs) { + return MBEDTLS_ERR_MPI_BUFFER_TOO_SMALL; + } + + /* If X_limbs is 0, input_length must also be 0 (from previous test). + * Nothing to do. */ + if (X_limbs == 0) { + return 0; + } + + memset(X, 0, X_limbs * ciL); + + /* memcpy() with (NULL, 0) is undefined behaviour */ + if (input_length != 0) { + size_t overhead = (X_limbs * ciL) - input_length; + unsigned char *Xp = (unsigned char *) X; + memcpy(Xp + overhead, input, input_length); + } + + mbedtls_mpi_core_bigendian_to_host(X, X_limbs); + + return 0; +} + +int mbedtls_mpi_core_write_le(const mbedtls_mpi_uint *A, + size_t A_limbs, + unsigned char *output, + size_t output_length) +{ + size_t stored_bytes = A_limbs * ciL; + size_t bytes_to_copy; + + if (stored_bytes < output_length) { + bytes_to_copy = stored_bytes; + } else { + bytes_to_copy = output_length; + + /* The output buffer is smaller than the allocated size of A. + * However A may fit if its leading bytes are zero. */ + for (size_t i = bytes_to_copy; i < stored_bytes; i++) { + if (GET_BYTE(A, i) != 0) { + return MBEDTLS_ERR_MPI_BUFFER_TOO_SMALL; + } + } + } + + for (size_t i = 0; i < bytes_to_copy; i++) { + output[i] = GET_BYTE(A, i); + } + + if (stored_bytes < output_length) { + /* Write trailing 0 bytes */ + memset(output + stored_bytes, 0, output_length - stored_bytes); + } + + return 0; +} + +int mbedtls_mpi_core_write_be(const mbedtls_mpi_uint *X, + size_t X_limbs, + unsigned char *output, + size_t output_length) +{ + size_t stored_bytes; + size_t bytes_to_copy; + unsigned char *p; + + stored_bytes = X_limbs * ciL; + + if (stored_bytes < output_length) { + /* There is enough space in the output buffer. Write initial + * null bytes and record the position at which to start + * writing the significant bytes. In this case, the execution + * trace of this function does not depend on the value of the + * number. */ + bytes_to_copy = stored_bytes; + p = output + output_length - stored_bytes; + memset(output, 0, output_length - stored_bytes); + } else { + /* The output buffer is smaller than the allocated size of X. + * However X may fit if its leading bytes are zero. */ + bytes_to_copy = output_length; + p = output; + for (size_t i = bytes_to_copy; i < stored_bytes; i++) { + if (GET_BYTE(X, i) != 0) { + return MBEDTLS_ERR_MPI_BUFFER_TOO_SMALL; + } + } + } + + for (size_t i = 0; i < bytes_to_copy; i++) { + p[bytes_to_copy - i - 1] = GET_BYTE(X, i); + } + + return 0; +} + +void mbedtls_mpi_core_shift_r(mbedtls_mpi_uint *X, size_t limbs, + size_t count) +{ + size_t i, v0, v1; + mbedtls_mpi_uint r0 = 0, r1; + + v0 = count / biL; + v1 = count & (biL - 1); + + if (v0 > limbs || (v0 == limbs && v1 > 0)) { + memset(X, 0, limbs * ciL); + return; + } + + /* + * shift by count / limb_size + */ + if (v0 > 0) { + for (i = 0; i < limbs - v0; i++) { + X[i] = X[i + v0]; + } + + for (; i < limbs; i++) { + X[i] = 0; + } + } + + /* + * shift by count % limb_size + */ + if (v1 > 0) { + for (i = limbs; i > 0; i--) { + r1 = X[i - 1] << (biL - v1); + X[i - 1] >>= v1; + X[i - 1] |= r0; + r0 = r1; + } + } +} + +void mbedtls_mpi_core_shift_l(mbedtls_mpi_uint *X, size_t limbs, + size_t count) +{ + size_t i, v0, v1; + mbedtls_mpi_uint r0 = 0, r1; + + v0 = count / (biL); + v1 = count & (biL - 1); + + /* + * shift by count / limb_size + */ + if (v0 > 0) { + for (i = limbs; i > v0; i--) { + X[i - 1] = X[i - v0 - 1]; + } + + for (; i > 0; i--) { + X[i - 1] = 0; + } + } + + /* + * shift by count % limb_size + */ + if (v1 > 0) { + for (i = v0; i < limbs; i++) { + r1 = X[i] >> (biL - v1); + X[i] <<= v1; + X[i] |= r0; + r0 = r1; + } + } +} + +mbedtls_mpi_uint mbedtls_mpi_core_add(mbedtls_mpi_uint *X, + const mbedtls_mpi_uint *A, + const mbedtls_mpi_uint *B, + size_t limbs) +{ + mbedtls_mpi_uint c = 0; + + for (size_t i = 0; i < limbs; i++) { + mbedtls_mpi_uint t = c + A[i]; + c = (t < A[i]); + t += B[i]; + c += (t < B[i]); + X[i] = t; + } + + return c; +} + +mbedtls_mpi_uint mbedtls_mpi_core_add_if(mbedtls_mpi_uint *X, + const mbedtls_mpi_uint *A, + size_t limbs, + unsigned cond) +{ + mbedtls_mpi_uint c = 0; + + mbedtls_ct_condition_t do_add = mbedtls_ct_bool(cond); + + for (size_t i = 0; i < limbs; i++) { + mbedtls_mpi_uint add = mbedtls_ct_mpi_uint_if_else_0(do_add, A[i]); + mbedtls_mpi_uint t = c + X[i]; + c = (t < X[i]); + t += add; + c += (t < add); + X[i] = t; + } + + return c; +} + +mbedtls_mpi_uint mbedtls_mpi_core_sub(mbedtls_mpi_uint *X, + const mbedtls_mpi_uint *A, + const mbedtls_mpi_uint *B, + size_t limbs) +{ + mbedtls_mpi_uint c = 0; + + for (size_t i = 0; i < limbs; i++) { + mbedtls_mpi_uint z = (A[i] < c); + mbedtls_mpi_uint t = A[i] - c; + c = (t < B[i]) + z; + X[i] = t - B[i]; + } + + return c; +} + +mbedtls_mpi_uint mbedtls_mpi_core_mla(mbedtls_mpi_uint *d, size_t d_len, + const mbedtls_mpi_uint *s, size_t s_len, + mbedtls_mpi_uint b) +{ + mbedtls_mpi_uint c = 0; /* carry */ + /* + * It is a documented precondition of this function that d_len >= s_len. + * If that's not the case, we swap these round: this turns what would be + * a buffer overflow into an incorrect result. + */ + if (d_len < s_len) { + s_len = d_len; + } + size_t excess_len = d_len - s_len; + size_t steps_x8 = s_len / 8; + size_t steps_x1 = s_len & 7; + + while (steps_x8--) { + MULADDC_X8_INIT + MULADDC_X8_CORE + MULADDC_X8_STOP + } + + while (steps_x1--) { + MULADDC_X1_INIT + MULADDC_X1_CORE + MULADDC_X1_STOP + } + + while (excess_len--) { + *d += c; + c = (*d < c); + d++; + } + + return c; +} + +void mbedtls_mpi_core_mul(mbedtls_mpi_uint *X, + const mbedtls_mpi_uint *A, size_t A_limbs, + const mbedtls_mpi_uint *B, size_t B_limbs) +{ + memset(X, 0, (A_limbs + B_limbs) * ciL); + + for (size_t i = 0; i < B_limbs; i++) { + (void) mbedtls_mpi_core_mla(X + i, A_limbs + 1, A, A_limbs, B[i]); + } +} + +/* + * Fast Montgomery initialization (thanks to Tom St Denis). + */ +mbedtls_mpi_uint mbedtls_mpi_core_montmul_init(const mbedtls_mpi_uint *N) +{ + mbedtls_mpi_uint x = N[0]; + + x += ((N[0] + 2) & 4) << 1; + + for (unsigned int i = biL; i >= 8; i /= 2) { + x *= (2 - (N[0] * x)); + } + + return ~x + 1; +} + +void mbedtls_mpi_core_montmul(mbedtls_mpi_uint *X, + const mbedtls_mpi_uint *A, + const mbedtls_mpi_uint *B, + size_t B_limbs, + const mbedtls_mpi_uint *N, + size_t AN_limbs, + mbedtls_mpi_uint mm, + mbedtls_mpi_uint *T) +{ + memset(T, 0, (2 * AN_limbs + 1) * ciL); + + for (size_t i = 0; i < AN_limbs; i++) { + /* T = (T + u0*B + u1*N) / 2^biL */ + mbedtls_mpi_uint u0 = A[i]; + mbedtls_mpi_uint u1 = (T[0] + u0 * B[0]) * mm; + + (void) mbedtls_mpi_core_mla(T, AN_limbs + 2, B, B_limbs, u0); + (void) mbedtls_mpi_core_mla(T, AN_limbs + 2, N, AN_limbs, u1); + + T++; + } + + /* + * The result we want is (T >= N) ? T - N : T. + * + * For better constant-time properties in this function, we always do the + * subtraction, with the result in X. + * + * We also look to see if there was any carry in the final additions in the + * loop above. + */ + + mbedtls_mpi_uint carry = T[AN_limbs]; + mbedtls_mpi_uint borrow = mbedtls_mpi_core_sub(X, T, N, AN_limbs); + + /* + * Using R as the Montgomery radix (auxiliary modulus) i.e. 2^(biL*AN_limbs): + * + * T can be in one of 3 ranges: + * + * 1) T < N : (carry, borrow) = (0, 1): we want T + * 2) N <= T < R : (carry, borrow) = (0, 0): we want X + * 3) T >= R : (carry, borrow) = (1, 1): we want X + * + * and (carry, borrow) = (1, 0) can't happen. + * + * So the correct return value is already in X if (carry ^ borrow) = 0, + * but is in (the lower AN_limbs limbs of) T if (carry ^ borrow) = 1. + */ + mbedtls_ct_memcpy_if(mbedtls_ct_bool(carry ^ borrow), + (unsigned char *) X, + (unsigned char *) T, + NULL, + AN_limbs * sizeof(mbedtls_mpi_uint)); +} + +int mbedtls_mpi_core_get_mont_r2_unsafe(mbedtls_mpi *X, + const mbedtls_mpi *N) +{ + int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED; + + MBEDTLS_MPI_CHK(mbedtls_mpi_lset(X, 1)); + MBEDTLS_MPI_CHK(mbedtls_mpi_shift_l(X, N->n * 2 * biL)); + MBEDTLS_MPI_CHK(mbedtls_mpi_mod_mpi(X, X, N)); + MBEDTLS_MPI_CHK(mbedtls_mpi_shrink(X, N->n)); + +cleanup: + return ret; +} + +MBEDTLS_STATIC_TESTABLE +void mbedtls_mpi_core_ct_uint_table_lookup(mbedtls_mpi_uint *dest, + const mbedtls_mpi_uint *table, + size_t limbs, + size_t count, + size_t index) +{ + for (size_t i = 0; i < count; i++, table += limbs) { + mbedtls_ct_condition_t assign = mbedtls_ct_uint_eq(i, index); + mbedtls_mpi_core_cond_assign(dest, table, limbs, assign); + } +} + +/* Fill X with n_bytes random bytes. + * X must already have room for those bytes. + * The ordering of the bytes returned from the RNG is suitable for + * deterministic ECDSA (see RFC 6979 §3.3 and the specification of + * mbedtls_mpi_core_random()). + */ +int mbedtls_mpi_core_fill_random( + mbedtls_mpi_uint *X, size_t X_limbs, + size_t n_bytes, + int (*f_rng)(void *, unsigned char *, size_t), void *p_rng) +{ + int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED; + const size_t limbs = CHARS_TO_LIMBS(n_bytes); + const size_t overhead = (limbs * ciL) - n_bytes; + + if (X_limbs < limbs) { + return MBEDTLS_ERR_MPI_BAD_INPUT_DATA; + } + + memset(X, 0, overhead); + memset((unsigned char *) X + limbs * ciL, 0, (X_limbs - limbs) * ciL); + MBEDTLS_MPI_CHK(f_rng(p_rng, (unsigned char *) X + overhead, n_bytes)); + mbedtls_mpi_core_bigendian_to_host(X, limbs); + +cleanup: + return ret; +} + +int mbedtls_mpi_core_random(mbedtls_mpi_uint *X, + mbedtls_mpi_uint min, + const mbedtls_mpi_uint *N, + size_t limbs, + int (*f_rng)(void *, unsigned char *, size_t), + void *p_rng) +{ + mbedtls_ct_condition_t ge_lower = MBEDTLS_CT_TRUE, lt_upper = MBEDTLS_CT_FALSE; + size_t n_bits = mbedtls_mpi_core_bitlen(N, limbs); + size_t n_bytes = (n_bits + 7) / 8; + int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED; + + /* + * When min == 0, each try has at worst a probability 1/2 of failing + * (the msb has a probability 1/2 of being 0, and then the result will + * be < N), so after 30 tries failure probability is a most 2**(-30). + * + * When N is just below a power of 2, as is the case when generating + * a random scalar on most elliptic curves, 1 try is enough with + * overwhelming probability. When N is just above a power of 2, + * as when generating a random scalar on secp224k1, each try has + * a probability of failing that is almost 1/2. + * + * The probabilities are almost the same if min is nonzero but negligible + * compared to N. This is always the case when N is crypto-sized, but + * it's convenient to support small N for testing purposes. When N + * is small, use a higher repeat count, otherwise the probability of + * failure is macroscopic. + */ + int count = (n_bytes > 4 ? 30 : 250); + + /* + * Match the procedure given in RFC 6979 §3.3 (deterministic ECDSA) + * when f_rng is a suitably parametrized instance of HMAC_DRBG: + * - use the same byte ordering; + * - keep the leftmost n_bits bits of the generated octet string; + * - try until result is in the desired range. + * This also avoids any bias, which is especially important for ECDSA. + */ + do { + MBEDTLS_MPI_CHK(mbedtls_mpi_core_fill_random(X, limbs, + n_bytes, + f_rng, p_rng)); + mbedtls_mpi_core_shift_r(X, limbs, 8 * n_bytes - n_bits); + + if (--count == 0) { + ret = MBEDTLS_ERR_MPI_NOT_ACCEPTABLE; + goto cleanup; + } + + ge_lower = mbedtls_mpi_core_uint_le_mpi(min, X, limbs); + lt_upper = mbedtls_mpi_core_lt_ct(X, N, limbs); + } while (mbedtls_ct_bool_and(ge_lower, lt_upper) == MBEDTLS_CT_FALSE); + +cleanup: + return ret; +} + +static size_t exp_mod_get_window_size(size_t Ebits) +{ +#if MBEDTLS_MPI_WINDOW_SIZE >= 6 + return (Ebits > 671) ? 6 : (Ebits > 239) ? 5 : (Ebits > 79) ? 4 : 1; +#elif MBEDTLS_MPI_WINDOW_SIZE == 5 + return (Ebits > 239) ? 5 : (Ebits > 79) ? 4 : 1; +#elif MBEDTLS_MPI_WINDOW_SIZE > 1 + return (Ebits > 79) ? MBEDTLS_MPI_WINDOW_SIZE : 1; +#else + (void) Ebits; + return 1; +#endif +} + +size_t mbedtls_mpi_core_exp_mod_working_limbs(size_t AN_limbs, size_t E_limbs) +{ + const size_t wsize = exp_mod_get_window_size(E_limbs * biL); + const size_t welem = ((size_t) 1) << wsize; + + /* How big does each part of the working memory pool need to be? */ + const size_t table_limbs = welem * AN_limbs; + const size_t select_limbs = AN_limbs; + const size_t temp_limbs = 2 * AN_limbs + 1; + + return table_limbs + select_limbs + temp_limbs; +} + +static void exp_mod_precompute_window(const mbedtls_mpi_uint *A, + const mbedtls_mpi_uint *N, + size_t AN_limbs, + mbedtls_mpi_uint mm, + const mbedtls_mpi_uint *RR, + size_t welem, + mbedtls_mpi_uint *Wtable, + mbedtls_mpi_uint *temp) +{ + /* W[0] = 1 (in Montgomery presentation) */ + memset(Wtable, 0, AN_limbs * ciL); + Wtable[0] = 1; + mbedtls_mpi_core_montmul(Wtable, Wtable, RR, AN_limbs, N, AN_limbs, mm, temp); + + /* W[1] = A (already in Montgomery presentation) */ + mbedtls_mpi_uint *W1 = Wtable + AN_limbs; + memcpy(W1, A, AN_limbs * ciL); + + /* W[i+1] = W[i] * W[1], i >= 2 */ + mbedtls_mpi_uint *Wprev = W1; + for (size_t i = 2; i < welem; i++) { + mbedtls_mpi_uint *Wcur = Wprev + AN_limbs; + mbedtls_mpi_core_montmul(Wcur, Wprev, W1, AN_limbs, N, AN_limbs, mm, temp); + Wprev = Wcur; + } +} + +/* Exponentiation: X := A^E mod N. + * + * A must already be in Montgomery form. + * + * As in other bignum functions, assume that AN_limbs and E_limbs are nonzero. + * + * RR must contain 2^{2*biL} mod N. + * + * The algorithm is a variant of Left-to-right k-ary exponentiation: HAC 14.82 + * (The difference is that the body in our loop processes a single bit instead + * of a full window.) + */ +void mbedtls_mpi_core_exp_mod(mbedtls_mpi_uint *X, + const mbedtls_mpi_uint *A, + const mbedtls_mpi_uint *N, + size_t AN_limbs, + const mbedtls_mpi_uint *E, + size_t E_limbs, + const mbedtls_mpi_uint *RR, + mbedtls_mpi_uint *T) +{ + const size_t wsize = exp_mod_get_window_size(E_limbs * biL); + const size_t welem = ((size_t) 1) << wsize; + + /* This is how we will use the temporary storage T, which must have space + * for table_limbs, select_limbs and (2 * AN_limbs + 1) for montmul. */ + const size_t table_limbs = welem * AN_limbs; + const size_t select_limbs = AN_limbs; + + /* Pointers to specific parts of the temporary working memory pool */ + mbedtls_mpi_uint *const Wtable = T; + mbedtls_mpi_uint *const Wselect = Wtable + table_limbs; + mbedtls_mpi_uint *const temp = Wselect + select_limbs; + + /* + * Window precomputation + */ + + const mbedtls_mpi_uint mm = mbedtls_mpi_core_montmul_init(N); + + /* Set Wtable[i] = A^(2^i) (in Montgomery representation) */ + exp_mod_precompute_window(A, N, AN_limbs, + mm, RR, + welem, Wtable, temp); + + /* + * Fixed window exponentiation + */ + + /* X = 1 (in Montgomery presentation) initially */ + memcpy(X, Wtable, AN_limbs * ciL); + + /* We'll process the bits of E from most significant + * (limb_index=E_limbs-1, E_bit_index=biL-1) to least significant + * (limb_index=0, E_bit_index=0). */ + size_t E_limb_index = E_limbs; + size_t E_bit_index = 0; + /* At any given time, window contains window_bits bits from E. + * window_bits can go up to wsize. */ + size_t window_bits = 0; + mbedtls_mpi_uint window = 0; + + do { + /* Square */ + mbedtls_mpi_core_montmul(X, X, X, AN_limbs, N, AN_limbs, mm, temp); + + /* Move to the next bit of the exponent */ + if (E_bit_index == 0) { + --E_limb_index; + E_bit_index = biL - 1; + } else { + --E_bit_index; + } + /* Insert next exponent bit into window */ + ++window_bits; + window <<= 1; + window |= (E[E_limb_index] >> E_bit_index) & 1; + + /* Clear window if it's full. Also clear the window at the end, + * when we've finished processing the exponent. */ + if (window_bits == wsize || + (E_bit_index == 0 && E_limb_index == 0)) { + /* Select Wtable[window] without leaking window through + * memory access patterns. */ + mbedtls_mpi_core_ct_uint_table_lookup(Wselect, Wtable, + AN_limbs, welem, window); + /* Multiply X by the selected element. */ + mbedtls_mpi_core_montmul(X, X, Wselect, AN_limbs, N, AN_limbs, mm, + temp); + window = 0; + window_bits = 0; + } + } while (!(E_bit_index == 0 && E_limb_index == 0)); +} + +mbedtls_mpi_uint mbedtls_mpi_core_sub_int(mbedtls_mpi_uint *X, + const mbedtls_mpi_uint *A, + mbedtls_mpi_uint c, /* doubles as carry */ + size_t limbs) +{ + for (size_t i = 0; i < limbs; i++) { + mbedtls_mpi_uint s = A[i]; + mbedtls_mpi_uint t = s - c; + c = (t > s); + X[i] = t; + } + + return c; +} + +mbedtls_ct_condition_t mbedtls_mpi_core_check_zero_ct(const mbedtls_mpi_uint *A, + size_t limbs) +{ + volatile const mbedtls_mpi_uint *force_read_A = A; + mbedtls_mpi_uint bits = 0; + + for (size_t i = 0; i < limbs; i++) { + bits |= force_read_A[i]; + } + + return mbedtls_ct_bool(bits); +} + +void mbedtls_mpi_core_to_mont_rep(mbedtls_mpi_uint *X, + const mbedtls_mpi_uint *A, + const mbedtls_mpi_uint *N, + size_t AN_limbs, + mbedtls_mpi_uint mm, + const mbedtls_mpi_uint *rr, + mbedtls_mpi_uint *T) +{ + mbedtls_mpi_core_montmul(X, A, rr, AN_limbs, N, AN_limbs, mm, T); +} + +void mbedtls_mpi_core_from_mont_rep(mbedtls_mpi_uint *X, + const mbedtls_mpi_uint *A, + const mbedtls_mpi_uint *N, + size_t AN_limbs, + mbedtls_mpi_uint mm, + mbedtls_mpi_uint *T) +{ + const mbedtls_mpi_uint Rinv = 1; /* 1/R in Mont. rep => 1 */ + + mbedtls_mpi_core_montmul(X, A, &Rinv, 1, N, AN_limbs, mm, T); +} + +#endif /* MBEDTLS_BIGNUM_C */ diff --git a/vendor/mbedtls/library/bignum_core.h b/vendor/mbedtls/library/bignum_core.h new file mode 100644 index 0000000000..92c8d47db5 --- /dev/null +++ b/vendor/mbedtls/library/bignum_core.h @@ -0,0 +1,763 @@ +/** + * Core bignum functions + * + * This interface should only be used by the legacy bignum module (bignum.h) + * and the modular bignum modules (bignum_mod.c, bignum_mod_raw.c). All other + * modules should use the high-level modular bignum interface (bignum_mod.h) + * or the legacy bignum interface (bignum.h). + * + * This module is about processing non-negative integers with a fixed upper + * bound that's of the form 2^n-1 where n is a multiple of #biL. + * These can be thought of integers written in base 2^#biL with a fixed + * number of digits. Digits in this base are called *limbs*. + * Many operations treat these numbers as the principal representation of + * a number modulo 2^n or a smaller bound. + * + * The functions in this module obey the following conventions unless + * explicitly indicated otherwise: + * + * - **Overflow**: some functions indicate overflow from the range + * [0, 2^n-1] by returning carry parameters, while others operate + * modulo and so cannot overflow. This should be clear from the function + * documentation. + * - **Bignum parameters**: Bignums are passed as pointers to an array of + * limbs. A limb has the type #mbedtls_mpi_uint. Unless otherwise specified: + * - Bignum parameters called \p A, \p B, ... are inputs, and are + * not modified by the function. + * - For operations modulo some number, the modulus is called \p N + * and is input-only. + * - Bignum parameters called \p X, \p Y are outputs or input-output. + * The initial content of output-only parameters is ignored. + * - Some functions use different names that reflect traditional + * naming of operands of certain operations (e.g. + * divisor/dividend/quotient/remainder). + * - \p T is a temporary storage area. The initial content of such + * parameter is ignored and the final content is unspecified. + * - **Bignum sizes**: bignum sizes are always expressed in limbs. + * Most functions work on bignums of a given size and take a single + * \p limbs parameter that applies to all parameters that are limb arrays. + * All bignum sizes must be at least 1 and must be significantly less than + * #SIZE_MAX. The behavior if a size is 0 is undefined. The behavior if the + * total size of all parameters overflows #SIZE_MAX is undefined. + * - **Parameter ordering**: for bignum parameters, outputs come before inputs. + * Temporaries come last. + * - **Aliasing**: in general, output bignums may be aliased to one or more + * inputs. As an exception, parameters that are documented as a modulus value + * may not be aliased to an output. Outputs may not be aliased to one another. + * Temporaries may not be aliased to any other parameter. + * - **Overlap**: apart from aliasing of limb array pointers (where two + * arguments are equal pointers), overlap is not supported and may result + * in undefined behavior. + * - **Error handling**: This is a low-level module. Functions generally do not + * try to protect against invalid arguments such as nonsensical sizes or + * null pointers. Note that some functions that operate on bignums of + * different sizes have constraints about their size, and violating those + * constraints may lead to buffer overflows. + * - **Modular representatives**: functions that operate modulo \p N expect + * all modular inputs to be in the range [0, \p N - 1] and guarantee outputs + * in the range [0, \p N - 1]. If an input is out of range, outputs are + * fully unspecified, though bignum values out of range should not cause + * buffer overflows (beware that this is not extensively tested). + */ + +/* + * Copyright The Mbed TLS Contributors + * SPDX-License-Identifier: Apache-2.0 OR GPL-2.0-or-later + */ + +#ifndef MBEDTLS_BIGNUM_CORE_H +#define MBEDTLS_BIGNUM_CORE_H + +#include "common.h" + +#if defined(MBEDTLS_BIGNUM_C) +#include "mbedtls/bignum.h" +#endif + +#include "constant_time_internal.h" + +#define ciL (sizeof(mbedtls_mpi_uint)) /** chars in limb */ +#define biL (ciL << 3) /** bits in limb */ +#define biH (ciL << 2) /** half limb size */ + +/* + * Convert between bits/chars and number of limbs + * Divide first in order to avoid potential overflows + */ +#define BITS_TO_LIMBS(i) ((i) / biL + ((i) % biL != 0)) +#define CHARS_TO_LIMBS(i) ((i) / ciL + ((i) % ciL != 0)) +/* Get a specific byte, without range checks. */ +#define GET_BYTE(X, i) \ + (((X)[(i) / ciL] >> (((i) % ciL) * 8)) & 0xff) + +/** Count leading zero bits in a given integer. + * + * \warning The result is undefined if \p a == 0 + * + * \param a Integer to count leading zero bits. + * + * \return The number of leading zero bits in \p a, if \p a != 0. + * If \p a == 0, the result is undefined. + */ +size_t mbedtls_mpi_core_clz(mbedtls_mpi_uint a); + +/** Return the minimum number of bits required to represent the value held + * in the MPI. + * + * \note This function returns 0 if all the limbs of \p A are 0. + * + * \param[in] A The address of the MPI. + * \param A_limbs The number of limbs of \p A. + * + * \return The number of bits in \p A. + */ +size_t mbedtls_mpi_core_bitlen(const mbedtls_mpi_uint *A, size_t A_limbs); + +/** Convert a big-endian byte array aligned to the size of mbedtls_mpi_uint + * into the storage form used by mbedtls_mpi. + * + * \param[in,out] A The address of the MPI. + * \param A_limbs The number of limbs of \p A. + */ +void mbedtls_mpi_core_bigendian_to_host(mbedtls_mpi_uint *A, + size_t A_limbs); + +/** \brief Compare a machine integer with an MPI. + * + * This function operates in constant time with respect + * to the values of \p min and \p A. + * + * \param min A machine integer. + * \param[in] A An MPI. + * \param A_limbs The number of limbs of \p A. + * This must be at least 1. + * + * \return MBEDTLS_CT_TRUE if \p min is less than or equal to \p A, otherwise MBEDTLS_CT_FALSE. + */ +mbedtls_ct_condition_t mbedtls_mpi_core_uint_le_mpi(mbedtls_mpi_uint min, + const mbedtls_mpi_uint *A, + size_t A_limbs); + +/** + * \brief Check if one unsigned MPI is less than another in constant + * time. + * + * \param A The left-hand MPI. This must point to an array of limbs + * with the same allocated length as \p B. + * \param B The right-hand MPI. This must point to an array of limbs + * with the same allocated length as \p A. + * \param limbs The number of limbs in \p A and \p B. + * This must not be 0. + * + * \return MBEDTLS_CT_TRUE if \p A is less than \p B. + * MBEDTLS_CT_FALSE if \p A is greater than or equal to \p B. + */ +mbedtls_ct_condition_t mbedtls_mpi_core_lt_ct(const mbedtls_mpi_uint *A, + const mbedtls_mpi_uint *B, + size_t limbs); + +/** + * \brief Perform a safe conditional copy of an MPI which doesn't reveal + * whether assignment was done or not. + * + * \param[out] X The address of the destination MPI. + * This must be initialized. Must have enough limbs to + * store the full value of \p A. + * \param[in] A The address of the source MPI. This must be initialized. + * \param limbs The number of limbs of \p A. + * \param assign The condition deciding whether to perform the + * assignment or not. Callers will need to use + * the constant time interface (e.g. `mbedtls_ct_bool()`) + * to construct this argument. + * + * \note This function avoids leaking any information about whether + * the assignment was done or not. + */ +void mbedtls_mpi_core_cond_assign(mbedtls_mpi_uint *X, + const mbedtls_mpi_uint *A, + size_t limbs, + mbedtls_ct_condition_t assign); + +/** + * \brief Perform a safe conditional swap of two MPIs which doesn't reveal + * whether the swap was done or not. + * + * \param[in,out] X The address of the first MPI. + * This must be initialized. + * \param[in,out] Y The address of the second MPI. + * This must be initialized. + * \param limbs The number of limbs of \p X and \p Y. + * \param swap The condition deciding whether to perform + * the swap or not. + * + * \note This function avoids leaking any information about whether + * the swap was done or not. + */ +void mbedtls_mpi_core_cond_swap(mbedtls_mpi_uint *X, + mbedtls_mpi_uint *Y, + size_t limbs, + mbedtls_ct_condition_t swap); + +/** Import X from unsigned binary data, little-endian. + * + * The MPI needs to have enough limbs to store the full value (including any + * most significant zero bytes in the input). + * + * \param[out] X The address of the MPI. + * \param X_limbs The number of limbs of \p X. + * \param[in] input The input buffer to import from. + * \param input_length The length bytes of \p input. + * + * \return \c 0 if successful. + * \return #MBEDTLS_ERR_MPI_BUFFER_TOO_SMALL if \p X isn't + * large enough to hold the value in \p input. + */ +int mbedtls_mpi_core_read_le(mbedtls_mpi_uint *X, + size_t X_limbs, + const unsigned char *input, + size_t input_length); + +/** Import X from unsigned binary data, big-endian. + * + * The MPI needs to have enough limbs to store the full value (including any + * most significant zero bytes in the input). + * + * \param[out] X The address of the MPI. + * May only be #NULL if \p X_limbs is 0 and \p input_length + * is 0. + * \param X_limbs The number of limbs of \p X. + * \param[in] input The input buffer to import from. + * May only be #NULL if \p input_length is 0. + * \param input_length The length in bytes of \p input. + * + * \return \c 0 if successful. + * \return #MBEDTLS_ERR_MPI_BUFFER_TOO_SMALL if \p X isn't + * large enough to hold the value in \p input. + */ +int mbedtls_mpi_core_read_be(mbedtls_mpi_uint *X, + size_t X_limbs, + const unsigned char *input, + size_t input_length); + +/** Export A into unsigned binary data, little-endian. + * + * \note If \p output is shorter than \p A the export is still successful if the + * value held in \p A fits in the buffer (that is, if enough of the most + * significant bytes of \p A are 0). + * + * \param[in] A The address of the MPI. + * \param A_limbs The number of limbs of \p A. + * \param[out] output The output buffer to export to. + * \param output_length The length in bytes of \p output. + * + * \return \c 0 if successful. + * \return #MBEDTLS_ERR_MPI_BUFFER_TOO_SMALL if \p output isn't + * large enough to hold the value of \p A. + */ +int mbedtls_mpi_core_write_le(const mbedtls_mpi_uint *A, + size_t A_limbs, + unsigned char *output, + size_t output_length); + +/** Export A into unsigned binary data, big-endian. + * + * \note If \p output is shorter than \p A the export is still successful if the + * value held in \p A fits in the buffer (that is, if enough of the most + * significant bytes of \p A are 0). + * + * \param[in] A The address of the MPI. + * \param A_limbs The number of limbs of \p A. + * \param[out] output The output buffer to export to. + * \param output_length The length in bytes of \p output. + * + * \return \c 0 if successful. + * \return #MBEDTLS_ERR_MPI_BUFFER_TOO_SMALL if \p output isn't + * large enough to hold the value of \p A. + */ +int mbedtls_mpi_core_write_be(const mbedtls_mpi_uint *A, + size_t A_limbs, + unsigned char *output, + size_t output_length); + +/** \brief Shift an MPI in-place right by a number of bits. + * + * Shifting by more bits than there are bit positions + * in \p X is valid and results in setting \p X to 0. + * + * This function's execution time depends on the value + * of \p count (and of course \p limbs). + * + * \param[in,out] X The number to shift. + * \param limbs The number of limbs of \p X. This must be at least 1. + * \param count The number of bits to shift by. + */ +void mbedtls_mpi_core_shift_r(mbedtls_mpi_uint *X, size_t limbs, + size_t count); + +/** + * \brief Shift an MPI in-place left by a number of bits. + * + * Shifting by more bits than there are bit positions + * in \p X will produce an unspecified result. + * + * This function's execution time depends on the value + * of \p count (and of course \p limbs). + * \param[in,out] X The number to shift. + * \param limbs The number of limbs of \p X. This must be at least 1. + * \param count The number of bits to shift by. + */ +void mbedtls_mpi_core_shift_l(mbedtls_mpi_uint *X, size_t limbs, + size_t count); + +/** + * \brief Add two fixed-size large unsigned integers, returning the carry. + * + * Calculates `A + B` where `A` and `B` have the same size. + * + * This function operates modulo `2^(biL*limbs)` and returns the carry + * (1 if there was a wraparound, and 0 otherwise). + * + * \p X may be aliased to \p A or \p B. + * + * \param[out] X The result of the addition. + * \param[in] A Little-endian presentation of the left operand. + * \param[in] B Little-endian presentation of the right operand. + * \param limbs Number of limbs of \p X, \p A and \p B. + * + * \return 1 if `A + B >= 2^(biL*limbs)`, 0 otherwise. + */ +mbedtls_mpi_uint mbedtls_mpi_core_add(mbedtls_mpi_uint *X, + const mbedtls_mpi_uint *A, + const mbedtls_mpi_uint *B, + size_t limbs); + +/** + * \brief Conditional addition of two fixed-size large unsigned integers, + * returning the carry. + * + * Functionally equivalent to + * + * ``` + * if( cond ) + * X += A; + * return carry; + * ``` + * + * This function operates modulo `2^(biL*limbs)`. + * + * \param[in,out] X The pointer to the (little-endian) array + * representing the bignum to accumulate onto. + * \param[in] A The pointer to the (little-endian) array + * representing the bignum to conditionally add + * to \p X. This may be aliased to \p X but may not + * overlap otherwise. + * \param limbs Number of limbs of \p X and \p A. + * \param cond Condition bit dictating whether addition should + * happen or not. This must be \c 0 or \c 1. + * + * \warning If \p cond is neither 0 nor 1, the result of this function + * is unspecified, and the resulting value in \p X might be + * neither its original value nor \p X + \p A. + * + * \return 1 if `X + cond * A >= 2^(biL*limbs)`, 0 otherwise. + */ +mbedtls_mpi_uint mbedtls_mpi_core_add_if(mbedtls_mpi_uint *X, + const mbedtls_mpi_uint *A, + size_t limbs, + unsigned cond); + +/** + * \brief Subtract two fixed-size large unsigned integers, returning the borrow. + * + * Calculate `A - B` where \p A and \p B have the same size. + * This function operates modulo `2^(biL*limbs)` and returns the carry + * (1 if there was a wraparound, i.e. if `A < B`, and 0 otherwise). + * + * \p X may be aliased to \p A or \p B, or even both, but may not overlap + * either otherwise. + * + * \param[out] X The result of the subtraction. + * \param[in] A Little-endian presentation of left operand. + * \param[in] B Little-endian presentation of right operand. + * \param limbs Number of limbs of \p X, \p A and \p B. + * + * \return 1 if `A < B`. + * 0 if `A >= B`. + */ +mbedtls_mpi_uint mbedtls_mpi_core_sub(mbedtls_mpi_uint *X, + const mbedtls_mpi_uint *A, + const mbedtls_mpi_uint *B, + size_t limbs); + +/** + * \brief Perform a fixed-size multiply accumulate operation: X += b * A + * + * \p X may be aliased to \p A (when \p X_limbs == \p A_limbs), but may not + * otherwise overlap. + * + * This function operates modulo `2^(biL*X_limbs)`. + * + * \param[in,out] X The pointer to the (little-endian) array + * representing the bignum to accumulate onto. + * \param X_limbs The number of limbs of \p X. This must be + * at least \p A_limbs. + * \param[in] A The pointer to the (little-endian) array + * representing the bignum to multiply with. + * This may be aliased to \p X but may not overlap + * otherwise. + * \param A_limbs The number of limbs of \p A. + * \param b X scalar to multiply with. + * + * \return The carry at the end of the operation. + */ +mbedtls_mpi_uint mbedtls_mpi_core_mla(mbedtls_mpi_uint *X, size_t X_limbs, + const mbedtls_mpi_uint *A, size_t A_limbs, + mbedtls_mpi_uint b); + +/** + * \brief Perform a known-size multiplication + * + * \p X may not be aliased to any of the inputs for this function. + * \p A may be aliased to \p B. + * + * \param[out] X The pointer to the (little-endian) array to receive + * the product of \p A_limbs and \p B_limbs. + * This must be of length \p A_limbs + \p B_limbs. + * \param[in] A The pointer to the (little-endian) array + * representing the first factor. + * \param A_limbs The number of limbs in \p A. + * \param[in] B The pointer to the (little-endian) array + * representing the second factor. + * \param B_limbs The number of limbs in \p B. + */ +void mbedtls_mpi_core_mul(mbedtls_mpi_uint *X, + const mbedtls_mpi_uint *A, size_t A_limbs, + const mbedtls_mpi_uint *B, size_t B_limbs); + +/** + * \brief Calculate initialisation value for fast Montgomery modular + * multiplication + * + * \param[in] N Little-endian presentation of the modulus. This must have + * at least one limb. + * + * \return The initialisation value for fast Montgomery modular multiplication + */ +mbedtls_mpi_uint mbedtls_mpi_core_montmul_init(const mbedtls_mpi_uint *N); + +/** + * \brief Montgomery multiplication: X = A * B * R^-1 mod N (HAC 14.36) + * + * \p A and \p B must be in canonical form. That is, < \p N. + * + * \p X may be aliased to \p A or \p N, or even \p B (if \p AN_limbs == + * \p B_limbs) but may not overlap any parameters otherwise. + * + * \p A and \p B may alias each other, if \p AN_limbs == \p B_limbs. They may + * not alias \p N (since they must be in canonical form, they cannot == \p N). + * + * \param[out] X The destination MPI, as a little-endian array of + * length \p AN_limbs. + * On successful completion, X contains the result of + * the multiplication `A * B * R^-1` mod N where + * `R = 2^(biL*AN_limbs)`. + * \param[in] A Little-endian presentation of first operand. + * Must have the same number of limbs as \p N. + * \param[in] B Little-endian presentation of second operand. + * \param[in] B_limbs The number of limbs in \p B. + * Must be <= \p AN_limbs. + * \param[in] N Little-endian presentation of the modulus. + * This must be odd, and have exactly the same number + * of limbs as \p A. + * It may alias \p X, but must not alias or otherwise + * overlap any of the other parameters. + * \param[in] AN_limbs The number of limbs in \p X, \p A and \p N. + * \param mm The Montgomery constant for \p N: -N^-1 mod 2^biL. + * This can be calculated by `mbedtls_mpi_core_montmul_init()`. + * \param[in,out] T Temporary storage of size at least 2*AN_limbs+1 limbs. + * Its initial content is unused and + * its final content is indeterminate. + * It must not alias or otherwise overlap any of the + * other parameters. + */ +void mbedtls_mpi_core_montmul(mbedtls_mpi_uint *X, + const mbedtls_mpi_uint *A, + const mbedtls_mpi_uint *B, size_t B_limbs, + const mbedtls_mpi_uint *N, size_t AN_limbs, + mbedtls_mpi_uint mm, mbedtls_mpi_uint *T); + +/** + * \brief Calculate the square of the Montgomery constant. (Needed + * for conversion and operations in Montgomery form.) + * + * \param[out] X A pointer to the result of the calculation of + * the square of the Montgomery constant: + * 2^{2*n*biL} mod N. + * \param[in] N Little-endian presentation of the modulus, which must be odd. + * + * \return 0 if successful. + * \return #MBEDTLS_ERR_MPI_ALLOC_FAILED if there is not enough space + * to store the value of Montgomery constant squared. + * \return #MBEDTLS_ERR_MPI_DIVISION_BY_ZERO if \p N modulus is zero. + * \return #MBEDTLS_ERR_MPI_NEGATIVE_VALUE if \p N modulus is negative. + */ +int mbedtls_mpi_core_get_mont_r2_unsafe(mbedtls_mpi *X, + const mbedtls_mpi *N); + +#if defined(MBEDTLS_TEST_HOOKS) +/** + * Copy an MPI from a table without leaking the index. + * + * \param dest The destination buffer. This must point to a writable + * buffer of at least \p limbs limbs. + * \param table The address of the table. This must point to a readable + * array of \p count elements of \p limbs limbs each. + * \param limbs The number of limbs in each table entry. + * \param count The number of entries in \p table. + * \param index The (secret) table index to look up. This must be in the + * range `0 .. count-1`. + */ +void mbedtls_mpi_core_ct_uint_table_lookup(mbedtls_mpi_uint *dest, + const mbedtls_mpi_uint *table, + size_t limbs, + size_t count, + size_t index); +#endif /* MBEDTLS_TEST_HOOKS */ + +/** + * \brief Fill an integer with a number of random bytes. + * + * \param X The destination MPI. + * \param X_limbs The number of limbs of \p X. + * \param bytes The number of random bytes to generate. + * \param f_rng The RNG function to use. This must not be \c NULL. + * \param p_rng The RNG parameter to be passed to \p f_rng. This may be + * \c NULL if \p f_rng doesn't need a context argument. + * + * \return \c 0 if successful. + * \return #MBEDTLS_ERR_MPI_BAD_INPUT_DATA if \p X does not have + * enough room for \p bytes bytes. + * \return A negative error code on RNG failure. + * + * \note The bytes obtained from the RNG are interpreted + * as a big-endian representation of an MPI; this can + * be relevant in applications like deterministic ECDSA. + */ +int mbedtls_mpi_core_fill_random(mbedtls_mpi_uint *X, size_t X_limbs, + size_t bytes, + int (*f_rng)(void *, unsigned char *, size_t), + void *p_rng); + +/** Generate a random number uniformly in a range. + * + * This function generates a random number between \p min inclusive and + * \p N exclusive. + * + * The procedure complies with RFC 6979 §3.3 (deterministic ECDSA) + * when the RNG is a suitably parametrized instance of HMAC_DRBG + * and \p min is \c 1. + * + * \note There are `N - min` possible outputs. The lower bound + * \p min can be reached, but the upper bound \p N cannot. + * + * \param X The destination MPI, with \p limbs limbs. + * It must not be aliased with \p N or otherwise overlap it. + * \param min The minimum value to return. + * \param N The upper bound of the range, exclusive, with \p limbs limbs. + * In other words, this is one plus the maximum value to return. + * \p N must be strictly larger than \p min. + * \param limbs The number of limbs of \p N and \p X. + * This must not be 0. + * \param f_rng The RNG function to use. This must not be \c NULL. + * \param p_rng The RNG parameter to be passed to \p f_rng. + * + * \return \c 0 if successful. + * \return #MBEDTLS_ERR_MPI_NOT_ACCEPTABLE if the implementation was + * unable to find a suitable value within a limited number + * of attempts. This has a negligible probability if \p N + * is significantly larger than \p min, which is the case + * for all usual cryptographic applications. + */ +int mbedtls_mpi_core_random(mbedtls_mpi_uint *X, + mbedtls_mpi_uint min, + const mbedtls_mpi_uint *N, + size_t limbs, + int (*f_rng)(void *, unsigned char *, size_t), + void *p_rng); + +/** + * \brief Returns the number of limbs of working memory required for + * a call to `mbedtls_mpi_core_exp_mod()`. + * + * \note This will always be at least + * `mbedtls_mpi_core_montmul_working_limbs(AN_limbs)`, + * i.e. sufficient for a call to `mbedtls_mpi_core_montmul()`. + * + * \param AN_limbs The number of limbs in the input `A` and the modulus `N` + * (they must be the same size) that will be given to + * `mbedtls_mpi_core_exp_mod()`. + * \param E_limbs The number of limbs in the exponent `E` that will be given + * to `mbedtls_mpi_core_exp_mod()`. + * + * \return The number of limbs of working memory required by + * `mbedtls_mpi_core_exp_mod()`. + */ +size_t mbedtls_mpi_core_exp_mod_working_limbs(size_t AN_limbs, size_t E_limbs); + +/** + * \brief Perform a modular exponentiation with secret exponent: + * X = A^E mod N, where \p A is already in Montgomery form. + * + * \p X may be aliased to \p A, but not to \p RR or \p E, even if \p E_limbs == + * \p AN_limbs. + * + * \param[out] X The destination MPI, as a little endian array of length + * \p AN_limbs. + * \param[in] A The base MPI, as a little endian array of length \p AN_limbs. + * Must be in Montgomery form. + * \param[in] N The modulus, as a little endian array of length \p AN_limbs. + * \param AN_limbs The number of limbs in \p X, \p A, \p N, \p RR. + * \param[in] E The exponent, as a little endian array of length \p E_limbs. + * \param E_limbs The number of limbs in \p E. + * \param[in] RR The precomputed residue of 2^{2*biL} modulo N, as a little + * endian array of length \p AN_limbs. + * \param[in,out] T Temporary storage of at least the number of limbs returned + * by `mbedtls_mpi_core_exp_mod_working_limbs()`. + * Its initial content is unused and its final content is + * indeterminate. + * It must not alias or otherwise overlap any of the other + * parameters. + * It is up to the caller to zeroize \p T when it is no + * longer needed, and before freeing it if it was dynamically + * allocated. + */ +void mbedtls_mpi_core_exp_mod(mbedtls_mpi_uint *X, + const mbedtls_mpi_uint *A, + const mbedtls_mpi_uint *N, size_t AN_limbs, + const mbedtls_mpi_uint *E, size_t E_limbs, + const mbedtls_mpi_uint *RR, + mbedtls_mpi_uint *T); + +/** + * \brief Subtract unsigned integer from known-size large unsigned integers. + * Return the borrow. + * + * \param[out] X The result of the subtraction. + * \param[in] A The left operand. + * \param b The unsigned scalar to subtract. + * \param limbs Number of limbs of \p X and \p A. + * + * \return 1 if `A < b`. + * 0 if `A >= b`. + */ +mbedtls_mpi_uint mbedtls_mpi_core_sub_int(mbedtls_mpi_uint *X, + const mbedtls_mpi_uint *A, + mbedtls_mpi_uint b, + size_t limbs); + +/** + * \brief Determine if a given MPI has the value \c 0 in constant time with + * respect to the value (but not with respect to the number of limbs). + * + * \param[in] A The MPI to test. + * \param limbs Number of limbs in \p A. + * + * \return MBEDTLS_CT_FALSE if `A == 0` + * MBEDTLS_CT_TRUE if `A != 0`. + */ +mbedtls_ct_condition_t mbedtls_mpi_core_check_zero_ct(const mbedtls_mpi_uint *A, + size_t limbs); + +/** + * \brief Returns the number of limbs of working memory required for + * a call to `mbedtls_mpi_core_montmul()`. + * + * \param AN_limbs The number of limbs in the input `A` and the modulus `N` + * (they must be the same size) that will be given to + * `mbedtls_mpi_core_montmul()` or one of the other functions + * that specifies this as the amount of working memory needed. + * + * \return The number of limbs of working memory required by + * `mbedtls_mpi_core_montmul()` (or other similar function). + */ +static inline size_t mbedtls_mpi_core_montmul_working_limbs(size_t AN_limbs) +{ + return 2 * AN_limbs + 1; +} + +/** Convert an MPI into Montgomery form. + * + * \p X may be aliased to \p A, but may not otherwise overlap it. + * + * \p X may not alias \p N (it is in canonical form, so must be strictly less + * than \p N). Nor may it alias or overlap \p rr (this is unlikely to be + * required in practice.) + * + * This function is a thin wrapper around `mbedtls_mpi_core_montmul()` that is + * an alternative to calling `mbedtls_mpi_mod_raw_to_mont_rep()` when we + * don't want to allocate memory. + * + * \param[out] X The result of the conversion. + * Must have the same number of limbs as \p A. + * \param[in] A The MPI to convert into Montgomery form. + * Must have the same number of limbs as the modulus. + * \param[in] N The address of the modulus, which gives the size of + * the base `R` = 2^(biL*N->limbs). + * \param[in] AN_limbs The number of limbs in \p X, \p A, \p N and \p rr. + * \param mm The Montgomery constant for \p N: -N^-1 mod 2^biL. + * This can be determined by calling + * `mbedtls_mpi_core_montmul_init()`. + * \param[in] rr The residue for `2^{2*n*biL} mod N`. + * \param[in,out] T Temporary storage of size at least + * `mbedtls_mpi_core_montmul_working_limbs(AN_limbs)` + * limbs. + * Its initial content is unused and + * its final content is indeterminate. + * It must not alias or otherwise overlap any of the + * other parameters. + */ +void mbedtls_mpi_core_to_mont_rep(mbedtls_mpi_uint *X, + const mbedtls_mpi_uint *A, + const mbedtls_mpi_uint *N, + size_t AN_limbs, + mbedtls_mpi_uint mm, + const mbedtls_mpi_uint *rr, + mbedtls_mpi_uint *T); + +/** Convert an MPI from Montgomery form. + * + * \p X may be aliased to \p A, but may not otherwise overlap it. + * + * \p X may not alias \p N (it is in canonical form, so must be strictly less + * than \p N). + * + * This function is a thin wrapper around `mbedtls_mpi_core_montmul()` that is + * an alternative to calling `mbedtls_mpi_mod_raw_from_mont_rep()` when we + * don't want to allocate memory. + * + * \param[out] X The result of the conversion. + * Must have the same number of limbs as \p A. + * \param[in] A The MPI to convert from Montgomery form. + * Must have the same number of limbs as the modulus. + * \param[in] N The address of the modulus, which gives the size of + * the base `R` = 2^(biL*N->limbs). + * \param[in] AN_limbs The number of limbs in \p X, \p A and \p N. + * \param mm The Montgomery constant for \p N: -N^-1 mod 2^biL. + * This can be determined by calling + * `mbedtls_mpi_core_montmul_init()`. + * \param[in,out] T Temporary storage of size at least + * `mbedtls_mpi_core_montmul_working_limbs(AN_limbs)` + * limbs. + * Its initial content is unused and + * its final content is indeterminate. + * It must not alias or otherwise overlap any of the + * other parameters. + */ +void mbedtls_mpi_core_from_mont_rep(mbedtls_mpi_uint *X, + const mbedtls_mpi_uint *A, + const mbedtls_mpi_uint *N, + size_t AN_limbs, + mbedtls_mpi_uint mm, + mbedtls_mpi_uint *T); + +#endif /* MBEDTLS_BIGNUM_CORE_H */ diff --git a/vendor/mbedtls/library/bignum_mod.c b/vendor/mbedtls/library/bignum_mod.c new file mode 100644 index 0000000000..dfd332a703 --- /dev/null +++ b/vendor/mbedtls/library/bignum_mod.c @@ -0,0 +1,394 @@ +/** + * Modular bignum functions + * + * Copyright The Mbed TLS Contributors + * SPDX-License-Identifier: Apache-2.0 OR GPL-2.0-or-later + */ + +#include "common.h" + +#if defined(MBEDTLS_BIGNUM_C) && defined(MBEDTLS_ECP_WITH_MPI_UINT) + +#include + +#include "mbedtls/platform_util.h" +#include "mbedtls/error.h" +#include "mbedtls/bignum.h" + +#include "mbedtls/platform.h" + +#include "bignum_core.h" +#include "bignum_mod.h" +#include "bignum_mod_raw.h" +#include "constant_time_internal.h" + +int mbedtls_mpi_mod_residue_setup(mbedtls_mpi_mod_residue *r, + const mbedtls_mpi_mod_modulus *N, + mbedtls_mpi_uint *p, + size_t p_limbs) +{ + if (p_limbs != N->limbs || !mbedtls_mpi_core_lt_ct(p, N->p, N->limbs)) { + return MBEDTLS_ERR_MPI_BAD_INPUT_DATA; + } + + r->limbs = N->limbs; + r->p = p; + + return 0; +} + +void mbedtls_mpi_mod_residue_release(mbedtls_mpi_mod_residue *r) +{ + if (r == NULL) { + return; + } + + r->limbs = 0; + r->p = NULL; +} + +void mbedtls_mpi_mod_modulus_init(mbedtls_mpi_mod_modulus *N) +{ + if (N == NULL) { + return; + } + + N->p = NULL; + N->limbs = 0; + N->bits = 0; + N->int_rep = MBEDTLS_MPI_MOD_REP_INVALID; +} + +void mbedtls_mpi_mod_modulus_free(mbedtls_mpi_mod_modulus *N) +{ + if (N == NULL) { + return; + } + + switch (N->int_rep) { + case MBEDTLS_MPI_MOD_REP_MONTGOMERY: + if (N->rep.mont.rr != NULL) { + mbedtls_zeroize_and_free((mbedtls_mpi_uint *) N->rep.mont.rr, + N->limbs * sizeof(mbedtls_mpi_uint)); + N->rep.mont.rr = NULL; + } + N->rep.mont.mm = 0; + break; + case MBEDTLS_MPI_MOD_REP_OPT_RED: + N->rep.ored.modp = NULL; + break; + case MBEDTLS_MPI_MOD_REP_INVALID: + break; + } + + N->p = NULL; + N->limbs = 0; + N->bits = 0; + N->int_rep = MBEDTLS_MPI_MOD_REP_INVALID; +} + +static int set_mont_const_square(const mbedtls_mpi_uint **X, + const mbedtls_mpi_uint *A, + size_t limbs) +{ + int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED; + mbedtls_mpi N; + mbedtls_mpi RR; + *X = NULL; + + mbedtls_mpi_init(&N); + mbedtls_mpi_init(&RR); + + if (A == NULL || limbs == 0 || limbs >= (MBEDTLS_MPI_MAX_LIMBS / 2) - 2) { + goto cleanup; + } + + if (mbedtls_mpi_grow(&N, limbs)) { + goto cleanup; + } + + memcpy(N.p, A, sizeof(mbedtls_mpi_uint) * limbs); + + ret = mbedtls_mpi_core_get_mont_r2_unsafe(&RR, &N); + + if (ret == 0) { + *X = RR.p; + RR.p = NULL; + } + +cleanup: + mbedtls_mpi_free(&N); + mbedtls_mpi_free(&RR); + ret = (ret != 0) ? MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED : 0; + return ret; +} + +static inline void standard_modulus_setup(mbedtls_mpi_mod_modulus *N, + const mbedtls_mpi_uint *p, + size_t p_limbs, + mbedtls_mpi_mod_rep_selector int_rep) +{ + N->p = p; + N->limbs = p_limbs; + N->bits = mbedtls_mpi_core_bitlen(p, p_limbs); + N->int_rep = int_rep; +} + +int mbedtls_mpi_mod_modulus_setup(mbedtls_mpi_mod_modulus *N, + const mbedtls_mpi_uint *p, + size_t p_limbs) +{ + int ret = 0; + standard_modulus_setup(N, p, p_limbs, MBEDTLS_MPI_MOD_REP_MONTGOMERY); + N->rep.mont.mm = mbedtls_mpi_core_montmul_init(N->p); + ret = set_mont_const_square(&N->rep.mont.rr, N->p, N->limbs); + + if (ret != 0) { + mbedtls_mpi_mod_modulus_free(N); + } + + return ret; +} + +int mbedtls_mpi_mod_optred_modulus_setup(mbedtls_mpi_mod_modulus *N, + const mbedtls_mpi_uint *p, + size_t p_limbs, + mbedtls_mpi_modp_fn modp) +{ + standard_modulus_setup(N, p, p_limbs, MBEDTLS_MPI_MOD_REP_OPT_RED); + N->rep.ored.modp = modp; + return 0; +} + +int mbedtls_mpi_mod_mul(mbedtls_mpi_mod_residue *X, + const mbedtls_mpi_mod_residue *A, + const mbedtls_mpi_mod_residue *B, + const mbedtls_mpi_mod_modulus *N) +{ + if (N->limbs == 0) { + return MBEDTLS_ERR_MPI_BAD_INPUT_DATA; + } + + if (X->limbs != N->limbs || A->limbs != N->limbs || B->limbs != N->limbs) { + return MBEDTLS_ERR_MPI_BAD_INPUT_DATA; + } + + mbedtls_mpi_uint *T = mbedtls_calloc(N->limbs * 2 + 1, ciL); + if (T == NULL) { + return MBEDTLS_ERR_MPI_ALLOC_FAILED; + } + + mbedtls_mpi_mod_raw_mul(X->p, A->p, B->p, N, T); + + mbedtls_free(T); + + return 0; +} + +int mbedtls_mpi_mod_sub(mbedtls_mpi_mod_residue *X, + const mbedtls_mpi_mod_residue *A, + const mbedtls_mpi_mod_residue *B, + const mbedtls_mpi_mod_modulus *N) +{ + if (X->limbs != N->limbs || A->limbs != N->limbs || B->limbs != N->limbs) { + return MBEDTLS_ERR_MPI_BAD_INPUT_DATA; + } + + mbedtls_mpi_mod_raw_sub(X->p, A->p, B->p, N); + + return 0; +} + +static int mbedtls_mpi_mod_inv_mont(mbedtls_mpi_mod_residue *X, + const mbedtls_mpi_mod_residue *A, + const mbedtls_mpi_mod_modulus *N, + mbedtls_mpi_uint *working_memory) +{ + /* Input already in Montgomery form, so there's little to do */ + mbedtls_mpi_mod_raw_inv_prime(X->p, A->p, + N->p, N->limbs, + N->rep.mont.rr, + working_memory); + return 0; +} + +static int mbedtls_mpi_mod_inv_non_mont(mbedtls_mpi_mod_residue *X, + const mbedtls_mpi_mod_residue *A, + const mbedtls_mpi_mod_modulus *N, + mbedtls_mpi_uint *working_memory) +{ + /* Need to convert input into Montgomery form */ + + int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED; + + mbedtls_mpi_mod_modulus Nmont; + mbedtls_mpi_mod_modulus_init(&Nmont); + + MBEDTLS_MPI_CHK(mbedtls_mpi_mod_modulus_setup(&Nmont, N->p, N->limbs)); + + /* We'll use X->p to hold the Montgomery form of the input A->p */ + mbedtls_mpi_core_to_mont_rep(X->p, A->p, Nmont.p, Nmont.limbs, + Nmont.rep.mont.mm, Nmont.rep.mont.rr, + working_memory); + + mbedtls_mpi_mod_raw_inv_prime(X->p, X->p, + Nmont.p, Nmont.limbs, + Nmont.rep.mont.rr, + working_memory); + + /* And convert back from Montgomery form */ + + mbedtls_mpi_core_from_mont_rep(X->p, X->p, Nmont.p, Nmont.limbs, + Nmont.rep.mont.mm, working_memory); + +cleanup: + mbedtls_mpi_mod_modulus_free(&Nmont); + return ret; +} + +int mbedtls_mpi_mod_inv(mbedtls_mpi_mod_residue *X, + const mbedtls_mpi_mod_residue *A, + const mbedtls_mpi_mod_modulus *N) +{ + if (X->limbs != N->limbs || A->limbs != N->limbs) { + return MBEDTLS_ERR_MPI_BAD_INPUT_DATA; + } + + /* Zero has the same value regardless of Montgomery form or not */ + if (mbedtls_mpi_core_check_zero_ct(A->p, A->limbs) == 0) { + return MBEDTLS_ERR_MPI_BAD_INPUT_DATA; + } + + size_t working_limbs = + mbedtls_mpi_mod_raw_inv_prime_working_limbs(N->limbs); + + mbedtls_mpi_uint *working_memory = mbedtls_calloc(working_limbs, + sizeof(mbedtls_mpi_uint)); + if (working_memory == NULL) { + return MBEDTLS_ERR_MPI_ALLOC_FAILED; + } + + int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED; + + switch (N->int_rep) { + case MBEDTLS_MPI_MOD_REP_MONTGOMERY: + ret = mbedtls_mpi_mod_inv_mont(X, A, N, working_memory); + break; + case MBEDTLS_MPI_MOD_REP_OPT_RED: + ret = mbedtls_mpi_mod_inv_non_mont(X, A, N, working_memory); + break; + default: + ret = MBEDTLS_ERR_MPI_BAD_INPUT_DATA; + break; + } + + mbedtls_zeroize_and_free(working_memory, + working_limbs * sizeof(mbedtls_mpi_uint)); + + return ret; +} + +int mbedtls_mpi_mod_add(mbedtls_mpi_mod_residue *X, + const mbedtls_mpi_mod_residue *A, + const mbedtls_mpi_mod_residue *B, + const mbedtls_mpi_mod_modulus *N) +{ + if (X->limbs != N->limbs || A->limbs != N->limbs || B->limbs != N->limbs) { + return MBEDTLS_ERR_MPI_BAD_INPUT_DATA; + } + + mbedtls_mpi_mod_raw_add(X->p, A->p, B->p, N); + + return 0; +} + +int mbedtls_mpi_mod_random(mbedtls_mpi_mod_residue *X, + mbedtls_mpi_uint min, + const mbedtls_mpi_mod_modulus *N, + int (*f_rng)(void *, unsigned char *, size_t), + void *p_rng) +{ + if (X->limbs != N->limbs) { + return MBEDTLS_ERR_MPI_BAD_INPUT_DATA; + } + return mbedtls_mpi_mod_raw_random(X->p, min, N, f_rng, p_rng); +} + +int mbedtls_mpi_mod_read(mbedtls_mpi_mod_residue *r, + const mbedtls_mpi_mod_modulus *N, + const unsigned char *buf, + size_t buflen, + mbedtls_mpi_mod_ext_rep ext_rep) +{ + int ret = MBEDTLS_ERR_MPI_BAD_INPUT_DATA; + + /* Do our best to check if r and m have been set up */ + if (r->limbs == 0 || N->limbs == 0) { + goto cleanup; + } + if (r->limbs != N->limbs) { + goto cleanup; + } + + ret = mbedtls_mpi_mod_raw_read(r->p, N, buf, buflen, ext_rep); + if (ret != 0) { + goto cleanup; + } + + r->limbs = N->limbs; + + ret = mbedtls_mpi_mod_raw_canonical_to_modulus_rep(r->p, N); + +cleanup: + return ret; +} + +int mbedtls_mpi_mod_write(const mbedtls_mpi_mod_residue *r, + const mbedtls_mpi_mod_modulus *N, + unsigned char *buf, + size_t buflen, + mbedtls_mpi_mod_ext_rep ext_rep) +{ + /* Do our best to check if r and m have been set up */ + if (r->limbs == 0 || N->limbs == 0) { + return MBEDTLS_ERR_MPI_BAD_INPUT_DATA; + } + if (r->limbs != N->limbs) { + return MBEDTLS_ERR_MPI_BAD_INPUT_DATA; + } + + int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED; + mbedtls_mpi_uint *working_memory = r->p; + size_t working_memory_len = sizeof(mbedtls_mpi_uint) * r->limbs; + + if (N->int_rep == MBEDTLS_MPI_MOD_REP_MONTGOMERY) { + + working_memory = mbedtls_calloc(r->limbs, sizeof(mbedtls_mpi_uint)); + + if (working_memory == NULL) { + ret = MBEDTLS_ERR_MPI_ALLOC_FAILED; + goto cleanup; + } + + memcpy(working_memory, r->p, working_memory_len); + + ret = mbedtls_mpi_mod_raw_from_mont_rep(working_memory, N); + if (ret != 0) { + goto cleanup; + } + } + + ret = mbedtls_mpi_mod_raw_write(working_memory, N, buf, buflen, ext_rep); + +cleanup: + + if (N->int_rep == MBEDTLS_MPI_MOD_REP_MONTGOMERY && + working_memory != NULL) { + + mbedtls_zeroize_and_free(working_memory, working_memory_len); + } + + return ret; +} + +#endif /* MBEDTLS_BIGNUM_C && MBEDTLS_ECP_WITH_MPI_UINT */ diff --git a/vendor/mbedtls/library/bignum_mod.h b/vendor/mbedtls/library/bignum_mod.h new file mode 100644 index 0000000000..963d8881ac --- /dev/null +++ b/vendor/mbedtls/library/bignum_mod.h @@ -0,0 +1,452 @@ +/** + * Modular bignum functions + * + * This module implements operations on integers modulo some fixed modulus. + * + * The functions in this module obey the following conventions unless + * explicitly indicated otherwise: + * + * - **Modulus parameters**: the modulus is passed as a pointer to a structure + * of type #mbedtls_mpi_mod_modulus. The structure must be set up with an + * array of limbs storing the bignum value of the modulus. The modulus must + * be odd and is assumed to have no leading zeroes. The modulus is usually + * named \c N and is usually input-only. Functions which take a parameter + * of type \c const #mbedtls_mpi_mod_modulus* must not modify its value. + * - **Bignum parameters**: Bignums are passed as pointers to an array of + * limbs or to a #mbedtls_mpi_mod_residue structure. A limb has the type + * #mbedtls_mpi_uint. Residues must be initialized before use, and must be + * associated with the modulus \c N. Unless otherwise specified: + * - Bignum parameters called \c A, \c B, ... are inputs and are not + * modified by the function. Functions which take a parameter of + * type \c const #mbedtls_mpi_mod_residue* must not modify its value. + * - Bignum parameters called \c X, \c Y, ... are outputs or input-output. + * The initial bignum value of output-only parameters is ignored, but + * they must be set up and associated with the modulus \c N. Some + * functions (typically constant-flow) require that the limbs in an + * output residue are initialized. + * - Bignum parameters called \c p are inputs used to set up a modulus or + * residue. These must be pointers to an array of limbs. + * - \c T is a temporary storage area. The initial content of such a + * parameter is ignored and the final content is unspecified. + * - Some functions use different names, such as \c r for the residue. + * - **Bignum sizes**: bignum sizes are always expressed in limbs. Both + * #mbedtls_mpi_mod_modulus and #mbedtls_mpi_mod_residue have a \c limbs + * member storing its size. All bignum parameters must have the same + * number of limbs as the modulus. All bignum sizes must be at least 1 and + * must be significantly less than #SIZE_MAX. The behavior if a size is 0 is + * undefined. + * - **Bignum representation**: the representation of inputs and outputs is + * specified by the \c int_rep field of the modulus. + * - **Parameter ordering**: for bignum parameters, outputs come before inputs. + * The modulus is passed after residues. Temporaries come last. + * - **Aliasing**: in general, output bignums may be aliased to one or more + * inputs. Modulus values may not be aliased to any other parameter. Outputs + * may not be aliased to one another. Temporaries may not be aliased to any + * other parameter. + * - **Overlap**: apart from aliasing of residue pointers (where two residue + * arguments are equal pointers), overlap is not supported and may result + * in undefined behavior. + * - **Error handling**: functions generally check compatibility of input + * sizes. Most functions will not check that input values are in canonical + * form (i.e. that \c A < \c N), this is only checked during setup of a + * residue structure. + * - **Modular representatives**: all functions expect inputs to be in the + * range [0, \c N - 1] and guarantee outputs in the range [0, \c N - 1]. + * Residues are set up with an associated modulus, and operations are only + * guaranteed to work if the modulus is associated with all residue + * parameters. If a residue is passed with a modulus other than the one it + * is associated with, then it may be out of range. If an input is out of + * range, outputs are fully unspecified, though bignum values out of range + * should not cause buffer overflows (beware that this is not extensively + * tested). + */ + +/* + * Copyright The Mbed TLS Contributors + * SPDX-License-Identifier: Apache-2.0 OR GPL-2.0-or-later + */ + +#ifndef MBEDTLS_BIGNUM_MOD_H +#define MBEDTLS_BIGNUM_MOD_H + +#include "common.h" + +#if defined(MBEDTLS_BIGNUM_C) +#include "mbedtls/bignum.h" +#endif + +/** How residues associated with a modulus are represented. + * + * This also determines which fields of the modulus structure are valid and + * what their contents are (see #mbedtls_mpi_mod_modulus). + */ +typedef enum { + /** Representation not chosen (makes the modulus structure invalid). */ + MBEDTLS_MPI_MOD_REP_INVALID = 0, + /* Skip 1 as it is slightly easier to accidentally pass to functions. */ + /** Montgomery representation. */ + MBEDTLS_MPI_MOD_REP_MONTGOMERY = 2, + /* Optimised reduction available. This indicates a coordinate modulus (P) + * and one or more of the following have been configured: + * - A nist curve (MBEDTLS_ECP_DP_SECPXXXR1_ENABLED) & MBEDTLS_ECP_NIST_OPTIM. + * - A Kobliz Curve. + * - A Fast Reduction Curve CURVE25519 or CURVE448. */ + MBEDTLS_MPI_MOD_REP_OPT_RED, +} mbedtls_mpi_mod_rep_selector; + +/* Make mbedtls_mpi_mod_rep_selector and mbedtls_mpi_mod_ext_rep disjoint to + * make it easier to catch when they are accidentally swapped. */ +typedef enum { + MBEDTLS_MPI_MOD_EXT_REP_INVALID = 0, + MBEDTLS_MPI_MOD_EXT_REP_LE = 8, + MBEDTLS_MPI_MOD_EXT_REP_BE +} mbedtls_mpi_mod_ext_rep; + +typedef struct { + mbedtls_mpi_uint *p; + size_t limbs; +} mbedtls_mpi_mod_residue; + +typedef struct { + mbedtls_mpi_uint const *rr; /* The residue for 2^{2*n*biL} mod N */ + mbedtls_mpi_uint mm; /* Montgomery const for -N^{-1} mod 2^{ciL} */ +} mbedtls_mpi_mont_struct; + +typedef int (*mbedtls_mpi_modp_fn)(mbedtls_mpi_uint *X, size_t X_limbs); + +typedef struct { + mbedtls_mpi_modp_fn modp; /* The optimised reduction function pointer */ +} mbedtls_mpi_opt_red_struct; + +typedef struct { + const mbedtls_mpi_uint *p; + size_t limbs; // number of limbs + size_t bits; // bitlen of p + mbedtls_mpi_mod_rep_selector int_rep; // selector to signal the active member of the union + union rep { + /* if int_rep == #MBEDTLS_MPI_MOD_REP_MONTGOMERY */ + mbedtls_mpi_mont_struct mont; + /* if int_rep == #MBEDTLS_MPI_MOD_REP_OPT_RED */ + mbedtls_mpi_opt_red_struct ored; + } rep; +} mbedtls_mpi_mod_modulus; + +/** Setup a residue structure. + * + * The residue will be set up with the buffer \p p and modulus \p N. + * + * The memory pointed to by \p p will be used by the resulting residue structure. + * The value at the pointed-to memory will be the initial value of \p r and must + * hold a value that is less than the modulus. This value will be used as-is + * and interpreted according to the value of the `N->int_rep` field. + * + * The modulus \p N will be the modulus associated with \p r. The residue \p r + * should only be used in operations where the modulus is \p N. + * + * \param[out] r The address of the residue to setup. + * \param[in] N The address of the modulus related to \p r. + * \param[in] p The address of the limb array containing the value of \p r. + * The memory pointed to by \p p will be used by \p r and must + * not be modified in any way until after + * mbedtls_mpi_mod_residue_release() is called. The data + * pointed to by \p p must be less than the modulus (the value + * pointed to by `N->p`) and already in the representation + * indicated by `N->int_rep`. + * \param p_limbs The number of limbs of \p p. Must be the same as the number + * of limbs in the modulus \p N. + * + * \return \c 0 if successful. + * \return #MBEDTLS_ERR_MPI_BAD_INPUT_DATA if \p p_limbs is less than the + * limbs in \p N or if \p p is not less than \p N. + */ +int mbedtls_mpi_mod_residue_setup(mbedtls_mpi_mod_residue *r, + const mbedtls_mpi_mod_modulus *N, + mbedtls_mpi_uint *p, + size_t p_limbs); + +/** Unbind elements of a residue structure. + * + * This function removes the reference to the limb array that was passed to + * mbedtls_mpi_mod_residue_setup() to make it safe to free or use again. + * + * This function invalidates \p r and it must not be used until after + * mbedtls_mpi_mod_residue_setup() is called on it again. + * + * \param[out] r The address of residue to release. + */ +void mbedtls_mpi_mod_residue_release(mbedtls_mpi_mod_residue *r); + +/** Initialize a modulus structure. + * + * \param[out] N The address of the modulus structure to initialize. + */ +void mbedtls_mpi_mod_modulus_init(mbedtls_mpi_mod_modulus *N); + +/** Setup a modulus structure. + * + * \param[out] N The address of the modulus structure to populate. + * \param[in] p The address of the limb array storing the value of \p N. + * The memory pointed to by \p p will be used by \p N and must + * not be modified in any way until after + * mbedtls_mpi_mod_modulus_free() is called. + * \param p_limbs The number of limbs of \p p. + * + * \return \c 0 if successful. + */ +int mbedtls_mpi_mod_modulus_setup(mbedtls_mpi_mod_modulus *N, + const mbedtls_mpi_uint *p, + size_t p_limbs); + +/** Setup an optimised-reduction compatible modulus structure. + * + * \param[out] N The address of the modulus structure to populate. + * \param[in] p The address of the limb array storing the value of \p N. + * The memory pointed to by \p p will be used by \p N and must + * not be modified in any way until after + * mbedtls_mpi_mod_modulus_free() is called. + * \param p_limbs The number of limbs of \p p. + * \param modp A pointer to the optimised reduction function to use. \p p. + * + * \return \c 0 if successful. + */ +int mbedtls_mpi_mod_optred_modulus_setup(mbedtls_mpi_mod_modulus *N, + const mbedtls_mpi_uint *p, + size_t p_limbs, + mbedtls_mpi_modp_fn modp); + +/** Free elements of a modulus structure. + * + * This function frees any memory allocated by mbedtls_mpi_mod_modulus_setup(). + * + * \warning This function does not free the limb array passed to + * mbedtls_mpi_mod_modulus_setup() only removes the reference to it, + * making it safe to free or to use it again. + * + * \param[in,out] N The address of the modulus structure to free. + */ +void mbedtls_mpi_mod_modulus_free(mbedtls_mpi_mod_modulus *N); + +/** \brief Multiply two residues, returning the residue modulo the specified + * modulus. + * + * \note Currently handles the case when `N->int_rep` is + * MBEDTLS_MPI_MOD_REP_MONTGOMERY. + * + * The size of the operation is determined by \p N. \p A, \p B and \p X must + * all be associated with the modulus \p N and must all have the same number + * of limbs as \p N. + * + * \p X may be aliased to \p A or \p B, or even both, but may not overlap + * either otherwise. They may not alias \p N (since they must be in canonical + * form, they cannot == \p N). + * + * \param[out] X The address of the result MPI. Must have the same + * number of limbs as \p N. + * On successful completion, \p X contains the result of + * the multiplication `A * B * R^-1` mod N where + * `R = 2^(biL * N->limbs)`. + * \param[in] A The address of the first MPI. + * \param[in] B The address of the second MPI. + * \param[in] N The address of the modulus. Used to perform a modulo + * operation on the result of the multiplication. + * + * \return \c 0 if successful. + * \return #MBEDTLS_ERR_MPI_BAD_INPUT_DATA if all the parameters do not + * have the same number of limbs or \p N is invalid. + * \return #MBEDTLS_ERR_MPI_ALLOC_FAILED on memory-allocation failure. + */ +int mbedtls_mpi_mod_mul(mbedtls_mpi_mod_residue *X, + const mbedtls_mpi_mod_residue *A, + const mbedtls_mpi_mod_residue *B, + const mbedtls_mpi_mod_modulus *N); + +/** + * \brief Perform a fixed-size modular subtraction. + * + * Calculate `A - B modulo N`. + * + * \p A, \p B and \p X must all have the same number of limbs as \p N. + * + * \p X may be aliased to \p A or \p B, or even both, but may not overlap + * either otherwise. + * + * \note This function does not check that \p A or \p B are in canonical + * form (that is, are < \p N) - that will have been done by + * mbedtls_mpi_mod_residue_setup(). + * + * \param[out] X The address of the result MPI. Must be initialized. + * Must have the same number of limbs as the modulus \p N. + * \param[in] A The address of the first MPI. + * \param[in] B The address of the second MPI. + * \param[in] N The address of the modulus. Used to perform a modulo + * operation on the result of the subtraction. + * + * \return \c 0 if successful. + * \return #MBEDTLS_ERR_MPI_BAD_INPUT_DATA if the given MPIs do not + * have the correct number of limbs. + */ +int mbedtls_mpi_mod_sub(mbedtls_mpi_mod_residue *X, + const mbedtls_mpi_mod_residue *A, + const mbedtls_mpi_mod_residue *B, + const mbedtls_mpi_mod_modulus *N); + +/** + * \brief Perform modular inversion of an MPI with respect to a modulus \p N. + * + * \p A and \p X must be associated with the modulus \p N and will therefore + * have the same number of limbs as \p N. + * + * \p X may be aliased to \p A. + * + * \warning Currently only supports prime moduli, but does not check for them. + * + * \param[out] X The modular inverse of \p A with respect to \p N. + * \param[in] A The number to calculate the modular inverse of. + * Must not be 0. + * \param[in] N The modulus to use. + * + * \return \c 0 if successful. + * \return #MBEDTLS_ERR_MPI_BAD_INPUT_DATA if \p A and \p N do not + * have the same number of limbs. + * \return #MBEDTLS_ERR_MPI_BAD_INPUT_DATA if \p A is zero. + * \return #MBEDTLS_ERR_MPI_ALLOC_FAILED if couldn't allocate enough + * memory (needed for conversion to and from Mongtomery form + * when not in Montgomery form already, and for temporary use + * by the inversion calculation itself). + */ + +int mbedtls_mpi_mod_inv(mbedtls_mpi_mod_residue *X, + const mbedtls_mpi_mod_residue *A, + const mbedtls_mpi_mod_modulus *N); +/** + * \brief Perform a fixed-size modular addition. + * + * Calculate `A + B modulo N`. + * + * \p A, \p B and \p X must all be associated with the modulus \p N and must + * all have the same number of limbs as \p N. + * + * \p X may be aliased to \p A or \p B, or even both, but may not overlap + * either otherwise. + * + * \note This function does not check that \p A or \p B are in canonical + * form (that is, are < \p N) - that will have been done by + * mbedtls_mpi_mod_residue_setup(). + * + * \param[out] X The address of the result residue. Must be initialized. + * Must have the same number of limbs as the modulus \p N. + * \param[in] A The address of the first input residue. + * \param[in] B The address of the second input residue. + * \param[in] N The address of the modulus. Used to perform a modulo + * operation on the result of the addition. + * + * \return \c 0 if successful. + * \return #MBEDTLS_ERR_MPI_BAD_INPUT_DATA if the given MPIs do not + * have the correct number of limbs. + */ +int mbedtls_mpi_mod_add(mbedtls_mpi_mod_residue *X, + const mbedtls_mpi_mod_residue *A, + const mbedtls_mpi_mod_residue *B, + const mbedtls_mpi_mod_modulus *N); + +/** Generate a random number uniformly in a range. + * + * This function generates a random number between \p min inclusive and + * \p N exclusive. + * + * The procedure complies with RFC 6979 §3.3 (deterministic ECDSA) + * when the RNG is a suitably parametrized instance of HMAC_DRBG + * and \p min is \c 1. + * + * \note There are `N - min` possible outputs. The lower bound + * \p min can be reached, but the upper bound \p N cannot. + * + * \param X The destination residue. + * \param min The minimum value to return. It must be strictly smaller + * than \b N. + * \param N The modulus. + * This is the upper bound of the output range, exclusive. + * \param f_rng The RNG function to use. This must not be \c NULL. + * \param p_rng The RNG parameter to be passed to \p f_rng. + * + * \return \c 0 if successful. + * \return #MBEDTLS_ERR_MPI_NOT_ACCEPTABLE if the implementation was + * unable to find a suitable value within a limited number + * of attempts. This has a negligible probability if \p N + * is significantly larger than \p min, which is the case + * for all usual cryptographic applications. + */ +int mbedtls_mpi_mod_random(mbedtls_mpi_mod_residue *X, + mbedtls_mpi_uint min, + const mbedtls_mpi_mod_modulus *N, + int (*f_rng)(void *, unsigned char *, size_t), + void *p_rng); + +/** Read a residue from a byte buffer. + * + * The residue will be automatically converted to the internal representation + * based on the value of the `N->int_rep` field. + * + * The modulus \p N will be the modulus associated with \p r. The residue \p r + * should only be used in operations where the modulus is \p N or a modulus + * equivalent to \p N (in the sense that all their fields or memory pointed by + * their fields hold the same value). + * + * \param[out] r The address of the residue. It must have exactly the same + * number of limbs as the modulus \p N. + * \param[in] N The address of the modulus. + * \param[in] buf The input buffer to import from. + * \param buflen The length in bytes of \p buf. + * \param ext_rep The endianness of the number in the input buffer. + * + * \return \c 0 if successful. + * \return #MBEDTLS_ERR_MPI_BUFFER_TOO_SMALL if \p r isn't + * large enough to hold the value in \p buf. + * \return #MBEDTLS_ERR_MPI_BAD_INPUT_DATA if \p ext_rep + * is invalid or the value in the buffer is not less than \p N. + */ +int mbedtls_mpi_mod_read(mbedtls_mpi_mod_residue *r, + const mbedtls_mpi_mod_modulus *N, + const unsigned char *buf, + size_t buflen, + mbedtls_mpi_mod_ext_rep ext_rep); + +/** Write a residue into a byte buffer. + * + * The modulus \p N must be the modulus associated with \p r (see + * mbedtls_mpi_mod_residue_setup() and mbedtls_mpi_mod_read()). + * + * The residue will be automatically converted from the internal representation + * based on the value of `N->int_rep` field. + * + * \warning If the buffer is smaller than `N->bits`, the number of + * leading zeroes is leaked through timing. If \p r is + * secret, the caller must ensure that \p buflen is at least + * (`N->bits`+7)/8. + * + * \param[in] r The address of the residue. It must have the same number of + * limbs as the modulus \p N. (\p r is an input parameter, but + * its value will be modified during execution and restored + * before the function returns.) + * \param[in] N The address of the modulus associated with \p r. + * \param[out] buf The output buffer to export to. + * \param buflen The length in bytes of \p buf. + * \param ext_rep The endianness in which the number should be written into + * the output buffer. + * + * \return \c 0 if successful. + * \return #MBEDTLS_ERR_MPI_BUFFER_TOO_SMALL if \p buf isn't + * large enough to hold the value of \p r (without leading + * zeroes). + * \return #MBEDTLS_ERR_MPI_BAD_INPUT_DATA if \p ext_rep is invalid. + * \return #MBEDTLS_ERR_MPI_ALLOC_FAILED if couldn't allocate enough + * memory for conversion. Can occur only for moduli with + * MBEDTLS_MPI_MOD_REP_MONTGOMERY. + */ +int mbedtls_mpi_mod_write(const mbedtls_mpi_mod_residue *r, + const mbedtls_mpi_mod_modulus *N, + unsigned char *buf, + size_t buflen, + mbedtls_mpi_mod_ext_rep ext_rep); + +#endif /* MBEDTLS_BIGNUM_MOD_H */ diff --git a/vendor/mbedtls/library/bignum_mod_raw.c b/vendor/mbedtls/library/bignum_mod_raw.c new file mode 100644 index 0000000000..5343bc650d --- /dev/null +++ b/vendor/mbedtls/library/bignum_mod_raw.c @@ -0,0 +1,276 @@ +/* + * Low-level modular bignum functions + * + * Copyright The Mbed TLS Contributors + * SPDX-License-Identifier: Apache-2.0 OR GPL-2.0-or-later + */ + +#include "common.h" + +#if defined(MBEDTLS_BIGNUM_C) && defined(MBEDTLS_ECP_WITH_MPI_UINT) + +#include + +#include "mbedtls/error.h" +#include "mbedtls/platform_util.h" + +#include "mbedtls/platform.h" + +#include "bignum_core.h" +#include "bignum_mod_raw.h" +#include "bignum_mod.h" +#include "constant_time_internal.h" + +#include "bignum_mod_raw_invasive.h" + +void mbedtls_mpi_mod_raw_cond_assign(mbedtls_mpi_uint *X, + const mbedtls_mpi_uint *A, + const mbedtls_mpi_mod_modulus *N, + unsigned char assign) +{ + mbedtls_mpi_core_cond_assign(X, A, N->limbs, mbedtls_ct_bool(assign)); +} + +void mbedtls_mpi_mod_raw_cond_swap(mbedtls_mpi_uint *X, + mbedtls_mpi_uint *Y, + const mbedtls_mpi_mod_modulus *N, + unsigned char swap) +{ + mbedtls_mpi_core_cond_swap(X, Y, N->limbs, mbedtls_ct_bool(swap)); +} + +int mbedtls_mpi_mod_raw_read(mbedtls_mpi_uint *X, + const mbedtls_mpi_mod_modulus *N, + const unsigned char *input, + size_t input_length, + mbedtls_mpi_mod_ext_rep ext_rep) +{ + int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED; + + switch (ext_rep) { + case MBEDTLS_MPI_MOD_EXT_REP_LE: + ret = mbedtls_mpi_core_read_le(X, N->limbs, + input, input_length); + break; + case MBEDTLS_MPI_MOD_EXT_REP_BE: + ret = mbedtls_mpi_core_read_be(X, N->limbs, + input, input_length); + break; + default: + return MBEDTLS_ERR_MPI_BAD_INPUT_DATA; + } + + if (ret != 0) { + goto cleanup; + } + + if (!mbedtls_mpi_core_lt_ct(X, N->p, N->limbs)) { + ret = MBEDTLS_ERR_MPI_BAD_INPUT_DATA; + goto cleanup; + } + +cleanup: + + return ret; +} + +int mbedtls_mpi_mod_raw_write(const mbedtls_mpi_uint *A, + const mbedtls_mpi_mod_modulus *N, + unsigned char *output, + size_t output_length, + mbedtls_mpi_mod_ext_rep ext_rep) +{ + switch (ext_rep) { + case MBEDTLS_MPI_MOD_EXT_REP_LE: + return mbedtls_mpi_core_write_le(A, N->limbs, + output, output_length); + case MBEDTLS_MPI_MOD_EXT_REP_BE: + return mbedtls_mpi_core_write_be(A, N->limbs, + output, output_length); + default: + return MBEDTLS_ERR_MPI_BAD_INPUT_DATA; + } +} + +void mbedtls_mpi_mod_raw_sub(mbedtls_mpi_uint *X, + const mbedtls_mpi_uint *A, + const mbedtls_mpi_uint *B, + const mbedtls_mpi_mod_modulus *N) +{ + mbedtls_mpi_uint c = mbedtls_mpi_core_sub(X, A, B, N->limbs); + + (void) mbedtls_mpi_core_add_if(X, N->p, N->limbs, (unsigned) c); +} + +MBEDTLS_STATIC_TESTABLE +void mbedtls_mpi_mod_raw_fix_quasi_reduction(mbedtls_mpi_uint *X, + const mbedtls_mpi_mod_modulus *N) +{ + mbedtls_mpi_uint c = mbedtls_mpi_core_sub(X, X, N->p, N->limbs); + + (void) mbedtls_mpi_core_add_if(X, N->p, N->limbs, (unsigned) c); +} + + +void mbedtls_mpi_mod_raw_mul(mbedtls_mpi_uint *X, + const mbedtls_mpi_uint *A, + const mbedtls_mpi_uint *B, + const mbedtls_mpi_mod_modulus *N, + mbedtls_mpi_uint *T) +{ + /* Standard (A * B) multiplication stored into pre-allocated T + * buffer of fixed limb size of (2N + 1). + * + * The space may not not fully filled by when + * MBEDTLS_MPI_MOD_REP_OPT_RED is used. */ + const size_t T_limbs = BITS_TO_LIMBS(N->bits) * 2; + switch (N->int_rep) { + case MBEDTLS_MPI_MOD_REP_MONTGOMERY: + mbedtls_mpi_core_montmul(X, A, B, N->limbs, N->p, N->limbs, + N->rep.mont.mm, T); + break; + case MBEDTLS_MPI_MOD_REP_OPT_RED: + mbedtls_mpi_core_mul(T, A, N->limbs, B, N->limbs); + + /* Optimised Reduction */ + (*N->rep.ored.modp)(T, T_limbs); + + /* Convert back to canonical representation */ + mbedtls_mpi_mod_raw_fix_quasi_reduction(T, N); + memcpy(X, T, N->limbs * sizeof(mbedtls_mpi_uint)); + break; + default: + break; + } + +} + +size_t mbedtls_mpi_mod_raw_inv_prime_working_limbs(size_t AN_limbs) +{ + /* mbedtls_mpi_mod_raw_inv_prime() needs a temporary for the exponent, + * which will be the same size as the modulus and input (AN_limbs), + * and additional space to pass to mbedtls_mpi_core_exp_mod(). */ + return AN_limbs + + mbedtls_mpi_core_exp_mod_working_limbs(AN_limbs, AN_limbs); +} + +void mbedtls_mpi_mod_raw_inv_prime(mbedtls_mpi_uint *X, + const mbedtls_mpi_uint *A, + const mbedtls_mpi_uint *N, + size_t AN_limbs, + const mbedtls_mpi_uint *RR, + mbedtls_mpi_uint *T) +{ + /* Inversion by power: g^|G| = 1 => g^(-1) = g^(|G|-1), and + * |G| = N - 1, so we want + * g^(|G|-1) = g^(N - 2) + */ + + /* Use the first AN_limbs of T to hold N - 2 */ + mbedtls_mpi_uint *Nminus2 = T; + (void) mbedtls_mpi_core_sub_int(Nminus2, N, 2, AN_limbs); + + /* Rest of T is given to exp_mod for its working space */ + mbedtls_mpi_core_exp_mod(X, + A, N, AN_limbs, Nminus2, AN_limbs, + RR, T + AN_limbs); +} + +void mbedtls_mpi_mod_raw_add(mbedtls_mpi_uint *X, + const mbedtls_mpi_uint *A, + const mbedtls_mpi_uint *B, + const mbedtls_mpi_mod_modulus *N) +{ + mbedtls_mpi_uint carry, borrow; + carry = mbedtls_mpi_core_add(X, A, B, N->limbs); + borrow = mbedtls_mpi_core_sub(X, X, N->p, N->limbs); + (void) mbedtls_mpi_core_add_if(X, N->p, N->limbs, (unsigned) (carry ^ borrow)); +} + +int mbedtls_mpi_mod_raw_canonical_to_modulus_rep( + mbedtls_mpi_uint *X, + const mbedtls_mpi_mod_modulus *N) +{ + switch (N->int_rep) { + case MBEDTLS_MPI_MOD_REP_MONTGOMERY: + return mbedtls_mpi_mod_raw_to_mont_rep(X, N); + case MBEDTLS_MPI_MOD_REP_OPT_RED: + return 0; + default: + return MBEDTLS_ERR_MPI_BAD_INPUT_DATA; + } +} + +int mbedtls_mpi_mod_raw_modulus_to_canonical_rep( + mbedtls_mpi_uint *X, + const mbedtls_mpi_mod_modulus *N) +{ + switch (N->int_rep) { + case MBEDTLS_MPI_MOD_REP_MONTGOMERY: + return mbedtls_mpi_mod_raw_from_mont_rep(X, N); + case MBEDTLS_MPI_MOD_REP_OPT_RED: + return 0; + default: + return MBEDTLS_ERR_MPI_BAD_INPUT_DATA; + } +} + +int mbedtls_mpi_mod_raw_random(mbedtls_mpi_uint *X, + mbedtls_mpi_uint min, + const mbedtls_mpi_mod_modulus *N, + int (*f_rng)(void *, unsigned char *, size_t), + void *p_rng) +{ + int ret = mbedtls_mpi_core_random(X, min, N->p, N->limbs, f_rng, p_rng); + if (ret != 0) { + return ret; + } + return mbedtls_mpi_mod_raw_canonical_to_modulus_rep(X, N); +} + +int mbedtls_mpi_mod_raw_to_mont_rep(mbedtls_mpi_uint *X, + const mbedtls_mpi_mod_modulus *N) +{ + mbedtls_mpi_uint *T; + const size_t t_limbs = mbedtls_mpi_core_montmul_working_limbs(N->limbs); + + if ((T = (mbedtls_mpi_uint *) mbedtls_calloc(t_limbs, ciL)) == NULL) { + return MBEDTLS_ERR_MPI_ALLOC_FAILED; + } + + mbedtls_mpi_core_to_mont_rep(X, X, N->p, N->limbs, + N->rep.mont.mm, N->rep.mont.rr, T); + + mbedtls_zeroize_and_free(T, t_limbs * ciL); + return 0; +} + +int mbedtls_mpi_mod_raw_from_mont_rep(mbedtls_mpi_uint *X, + const mbedtls_mpi_mod_modulus *N) +{ + const size_t t_limbs = mbedtls_mpi_core_montmul_working_limbs(N->limbs); + mbedtls_mpi_uint *T; + + if ((T = (mbedtls_mpi_uint *) mbedtls_calloc(t_limbs, ciL)) == NULL) { + return MBEDTLS_ERR_MPI_ALLOC_FAILED; + } + + mbedtls_mpi_core_from_mont_rep(X, X, N->p, N->limbs, N->rep.mont.mm, T); + + mbedtls_zeroize_and_free(T, t_limbs * ciL); + return 0; +} + +void mbedtls_mpi_mod_raw_neg(mbedtls_mpi_uint *X, + const mbedtls_mpi_uint *A, + const mbedtls_mpi_mod_modulus *N) +{ + mbedtls_mpi_core_sub(X, N->p, A, N->limbs); + + /* If A=0 initially, then X=N now. Detect this by + * subtracting N and catching the carry. */ + mbedtls_mpi_uint borrow = mbedtls_mpi_core_sub(X, X, N->p, N->limbs); + (void) mbedtls_mpi_core_add_if(X, N->p, N->limbs, (unsigned) borrow); +} + +#endif /* MBEDTLS_BIGNUM_C && MBEDTLS_ECP_WITH_MPI_UINT */ diff --git a/vendor/mbedtls/library/bignum_mod_raw.h b/vendor/mbedtls/library/bignum_mod_raw.h new file mode 100644 index 0000000000..7bb4ca3cf5 --- /dev/null +++ b/vendor/mbedtls/library/bignum_mod_raw.h @@ -0,0 +1,416 @@ +/** + * Low-level modular bignum functions + * + * This interface should only be used by the higher-level modular bignum + * module (bignum_mod.c) and the ECP module (ecp.c, ecp_curves.c). All other + * modules should use the high-level modular bignum interface (bignum_mod.h) + * or the legacy bignum interface (bignum.h). + * + * This is a low-level interface to operations on integers modulo which + * has no protection against passing invalid arguments such as arrays of + * the wrong size. The functions in bignum_mod.h provide a higher-level + * interface that includes protections against accidental misuse, at the + * expense of code size and sometimes more cumbersome memory management. + * + * The functions in this module obey the following conventions unless + * explicitly indicated otherwise: + * - **Modulus parameters**: the modulus is passed as a pointer to a structure + * of type #mbedtls_mpi_mod_modulus. The structure must be set up with an + * array of limbs storing the bignum value of the modulus. The modulus must + * be odd and is assumed to have no leading zeroes. The modulus is usually + * named \c N and is usually input-only. + * - **Bignum parameters**: Bignums are passed as pointers to an array of + * limbs. A limb has the type #mbedtls_mpi_uint. Unless otherwise specified: + * - Bignum parameters called \c A, \c B, ... are inputs, and are not + * modified by the function. + * - Bignum parameters called \c X, \c Y are outputs or input-output. + * The initial content of output-only parameters is ignored. + * - \c T is a temporary storage area. The initial content of such a + * parameter is ignored and the final content is unspecified. + * - **Bignum sizes**: bignum sizes are usually expressed by the \c limbs + * member of the modulus argument. All bignum parameters must have the same + * number of limbs as the modulus. All bignum sizes must be at least 1 and + * must be significantly less than #SIZE_MAX. The behavior if a size is 0 is + * undefined. + * - **Bignum representation**: the representation of inputs and outputs is + * specified by the \c int_rep field of the modulus for arithmetic + * functions. Utility functions may allow for different representation. + * - **Parameter ordering**: for bignum parameters, outputs come before inputs. + * The modulus is passed after other bignum input parameters. Temporaries + * come last. + * - **Aliasing**: in general, output bignums may be aliased to one or more + * inputs. Modulus values may not be aliased to any other parameter. Outputs + * may not be aliased to one another. Temporaries may not be aliased to any + * other parameter. + * - **Overlap**: apart from aliasing of limb array pointers (where two + * arguments are equal pointers), overlap is not supported and may result + * in undefined behavior. + * - **Error handling**: This is a low-level module. Functions generally do not + * try to protect against invalid arguments such as nonsensical sizes or + * null pointers. Note that passing bignums with a different size than the + * modulus may lead to buffer overflows. Some functions which allocate + * memory or handle reading/writing of bignums will return an error if + * memory allocation fails or if buffer sizes are invalid. + * - **Modular representatives**: all functions expect inputs to be in the + * range [0, \c N - 1] and guarantee outputs in the range [0, \c N - 1]. If + * an input is out of range, outputs are fully unspecified, though bignum + * values out of range should not cause buffer overflows (beware that this is + * not extensively tested). + */ + +/* + * Copyright The Mbed TLS Contributors + * SPDX-License-Identifier: Apache-2.0 OR GPL-2.0-or-later + */ + +#ifndef MBEDTLS_BIGNUM_MOD_RAW_H +#define MBEDTLS_BIGNUM_MOD_RAW_H + +#include "common.h" + +#if defined(MBEDTLS_BIGNUM_C) +#include "mbedtls/bignum.h" +#endif + +#include "bignum_mod.h" + +/** + * \brief Perform a safe conditional copy of an MPI which doesn't reveal + * whether the assignment was done or not. + * + * The size to copy is determined by \p N. + * + * \param[out] X The address of the destination MPI. + * This must be initialized. Must have enough limbs to + * store the full value of \p A. + * \param[in] A The address of the source MPI. This must be initialized. + * \param[in] N The address of the modulus related to \p X and \p A. + * \param assign The condition deciding whether to perform the + * assignment or not. Must be either 0 or 1: + * * \c 1: Perform the assignment `X = A`. + * * \c 0: Keep the original value of \p X. + * + * \note This function avoids leaking any information about whether + * the assignment was done or not. + * + * \warning If \p assign is neither 0 nor 1, the result of this function + * is indeterminate, and the resulting value in \p X might be + * neither its original value nor the value in \p A. + */ +void mbedtls_mpi_mod_raw_cond_assign(mbedtls_mpi_uint *X, + const mbedtls_mpi_uint *A, + const mbedtls_mpi_mod_modulus *N, + unsigned char assign); + +/** + * \brief Perform a safe conditional swap of two MPIs which doesn't reveal + * whether the swap was done or not. + * + * The size to swap is determined by \p N. + * + * \param[in,out] X The address of the first MPI. This must be initialized. + * \param[in,out] Y The address of the second MPI. This must be initialized. + * \param[in] N The address of the modulus related to \p X and \p Y. + * \param swap The condition deciding whether to perform + * the swap or not. Must be either 0 or 1: + * * \c 1: Swap the values of \p X and \p Y. + * * \c 0: Keep the original values of \p X and \p Y. + * + * \note This function avoids leaking any information about whether + * the swap was done or not. + * + * \warning If \p swap is neither 0 nor 1, the result of this function + * is indeterminate, and both \p X and \p Y might end up with + * values different to either of the original ones. + */ +void mbedtls_mpi_mod_raw_cond_swap(mbedtls_mpi_uint *X, + mbedtls_mpi_uint *Y, + const mbedtls_mpi_mod_modulus *N, + unsigned char swap); + +/** Import X from unsigned binary data. + * + * The MPI needs to have enough limbs to store the full value (including any + * most significant zero bytes in the input). + * + * \param[out] X The address of the MPI. The size is determined by \p N. + * (In particular, it must have at least as many limbs as + * the modulus \p N.) + * \param[in] N The address of the modulus related to \p X. + * \param[in] input The input buffer to import from. + * \param input_length The length in bytes of \p input. + * \param ext_rep The endianness of the number in the input buffer. + * + * \return \c 0 if successful. + * \return #MBEDTLS_ERR_MPI_BUFFER_TOO_SMALL if \p X isn't + * large enough to hold the value in \p input. + * \return #MBEDTLS_ERR_MPI_BAD_INPUT_DATA if the external representation + * of \p N is invalid or \p X is not less than \p N. + */ +int mbedtls_mpi_mod_raw_read(mbedtls_mpi_uint *X, + const mbedtls_mpi_mod_modulus *N, + const unsigned char *input, + size_t input_length, + mbedtls_mpi_mod_ext_rep ext_rep); + +/** Export A into unsigned binary data. + * + * \param[in] A The address of the MPI. The size is determined by \p N. + * (In particular, it must have at least as many limbs as + * the modulus \p N.) + * \param[in] N The address of the modulus related to \p A. + * \param[out] output The output buffer to export to. + * \param output_length The length in bytes of \p output. + * \param ext_rep The endianness in which the number should be written into the output buffer. + * + * \return \c 0 if successful. + * \return #MBEDTLS_ERR_MPI_BUFFER_TOO_SMALL if \p output isn't + * large enough to hold the value of \p A. + * \return #MBEDTLS_ERR_MPI_BAD_INPUT_DATA if the external representation + * of \p N is invalid. + */ +int mbedtls_mpi_mod_raw_write(const mbedtls_mpi_uint *A, + const mbedtls_mpi_mod_modulus *N, + unsigned char *output, + size_t output_length, + mbedtls_mpi_mod_ext_rep ext_rep); + +/** \brief Subtract two MPIs, returning the residue modulo the specified + * modulus. + * + * The size of the operation is determined by \p N. \p A and \p B must have + * the same number of limbs as \p N. + * + * \p X may be aliased to \p A or \p B, or even both, but may not overlap + * either otherwise. + * + * \param[out] X The address of the result MPI. + * This must be initialized. Must have enough limbs to + * store the full value of the result. + * \param[in] A The address of the first MPI. This must be initialized. + * \param[in] B The address of the second MPI. This must be initialized. + * \param[in] N The address of the modulus. Used to perform a modulo + * operation on the result of the subtraction. + */ +void mbedtls_mpi_mod_raw_sub(mbedtls_mpi_uint *X, + const mbedtls_mpi_uint *A, + const mbedtls_mpi_uint *B, + const mbedtls_mpi_mod_modulus *N); + +/** \brief Multiply two MPIs, returning the residue modulo the specified + * modulus. + * + * \note Currently handles the case when `N->int_rep` is + * MBEDTLS_MPI_MOD_REP_MONTGOMERY. + * + * The size of the operation is determined by \p N. \p A, \p B and \p X must + * all be associated with the modulus \p N and must all have the same number + * of limbs as \p N. + * + * \p X may be aliased to \p A or \p B, or even both, but may not overlap + * either otherwise. They may not alias \p N (since they must be in canonical + * form, they cannot == \p N). + * + * \param[out] X The address of the result MPI. Must have the same + * number of limbs as \p N. + * On successful completion, \p X contains the result of + * the multiplication `A * B * R^-1` mod N where + * `R = 2^(biL * N->limbs)`. + * \param[in] A The address of the first MPI. + * \param[in] B The address of the second MPI. + * \param[in] N The address of the modulus. Used to perform a modulo + * operation on the result of the multiplication. + * \param[in,out] T Temporary storage of size at least 2 * N->limbs + 1 + * limbs. Its initial content is unused and + * its final content is indeterminate. + * It must not alias or otherwise overlap any of the + * other parameters. + */ +void mbedtls_mpi_mod_raw_mul(mbedtls_mpi_uint *X, + const mbedtls_mpi_uint *A, + const mbedtls_mpi_uint *B, + const mbedtls_mpi_mod_modulus *N, + mbedtls_mpi_uint *T); + +/** + * \brief Returns the number of limbs of working memory required for + * a call to `mbedtls_mpi_mod_raw_inv_prime()`. + * + * \note This will always be at least + * `mbedtls_mpi_core_montmul_working_limbs(AN_limbs)`, + * i.e. sufficient for a call to `mbedtls_mpi_core_montmul()`. + * + * \param AN_limbs The number of limbs in the input `A` and the modulus `N` + * (they must be the same size) that will be given to + * `mbedtls_mpi_mod_raw_inv_prime()`. + * + * \return The number of limbs of working memory required by + * `mbedtls_mpi_mod_raw_inv_prime()`. + */ +size_t mbedtls_mpi_mod_raw_inv_prime_working_limbs(size_t AN_limbs); + +/** + * \brief Perform fixed-width modular inversion of a Montgomery-form MPI with + * respect to a modulus \p N that must be prime. + * + * \p X may be aliased to \p A, but not to \p N or \p RR. + * + * \param[out] X The modular inverse of \p A with respect to \p N. + * Will be in Montgomery form. + * \param[in] A The number to calculate the modular inverse of. + * Must be in Montgomery form. Must not be 0. + * \param[in] N The modulus, as a little-endian array of length \p AN_limbs. + * Must be prime. + * \param AN_limbs The number of limbs in \p A, \p N and \p RR. + * \param[in] RR The precomputed residue of 2^{2*biL} modulo N, as a little- + * endian array of length \p AN_limbs. + * \param[in,out] T Temporary storage of at least the number of limbs returned + * by `mbedtls_mpi_mod_raw_inv_prime_working_limbs()`. + * Its initial content is unused and its final content is + * indeterminate. + * It must not alias or otherwise overlap any of the other + * parameters. + * It is up to the caller to zeroize \p T when it is no + * longer needed, and before freeing it if it was dynamically + * allocated. + */ +void mbedtls_mpi_mod_raw_inv_prime(mbedtls_mpi_uint *X, + const mbedtls_mpi_uint *A, + const mbedtls_mpi_uint *N, + size_t AN_limbs, + const mbedtls_mpi_uint *RR, + mbedtls_mpi_uint *T); + +/** + * \brief Perform a known-size modular addition. + * + * Calculate `A + B modulo N`. + * + * The number of limbs in each operand, and the result, is given by the + * modulus \p N. + * + * \p X may be aliased to \p A or \p B, or even both, but may not overlap + * either otherwise. + * + * \param[out] X The result of the modular addition. + * \param[in] A Little-endian presentation of the left operand. This + * must be smaller than \p N. + * \param[in] B Little-endian presentation of the right operand. This + * must be smaller than \p N. + * \param[in] N The address of the modulus. + */ +void mbedtls_mpi_mod_raw_add(mbedtls_mpi_uint *X, + const mbedtls_mpi_uint *A, + const mbedtls_mpi_uint *B, + const mbedtls_mpi_mod_modulus *N); + +/** Convert an MPI from canonical representation (little-endian limb array) + * to the representation associated with the modulus. + * + * \param[in,out] X The limb array to convert. + * It must have as many limbs as \p N. + * It is converted in place. + * If this function returns an error, the content of \p X + * is unspecified. + * \param[in] N The modulus structure. + * + * \return \c 0 if successful. + * Otherwise an \c MBEDTLS_ERR_MPI_xxx error code. + */ +int mbedtls_mpi_mod_raw_canonical_to_modulus_rep( + mbedtls_mpi_uint *X, + const mbedtls_mpi_mod_modulus *N); + +/** Convert an MPI from the representation associated with the modulus + * to canonical representation (little-endian limb array). + * + * \param[in,out] X The limb array to convert. + * It must have as many limbs as \p N. + * It is converted in place. + * If this function returns an error, the content of \p X + * is unspecified. + * \param[in] N The modulus structure. + * + * \return \c 0 if successful. + * Otherwise an \c MBEDTLS_ERR_MPI_xxx error code. + */ +int mbedtls_mpi_mod_raw_modulus_to_canonical_rep( + mbedtls_mpi_uint *X, + const mbedtls_mpi_mod_modulus *N); + +/** Generate a random number uniformly in a range. + * + * This function generates a random number between \p min inclusive and + * \p N exclusive. + * + * The procedure complies with RFC 6979 §3.3 (deterministic ECDSA) + * when the RNG is a suitably parametrized instance of HMAC_DRBG + * and \p min is \c 1. + * + * \note There are `N - min` possible outputs. The lower bound + * \p min can be reached, but the upper bound \p N cannot. + * + * \param X The destination MPI, in canonical representation modulo \p N. + * It must not be aliased with \p N or otherwise overlap it. + * \param min The minimum value to return. It must be strictly smaller + * than \b N. + * \param N The modulus. + * This is the upper bound of the output range, exclusive. + * \param f_rng The RNG function to use. This must not be \c NULL. + * \param p_rng The RNG parameter to be passed to \p f_rng. + * + * \return \c 0 if successful. + * \return #MBEDTLS_ERR_MPI_NOT_ACCEPTABLE if the implementation was + * unable to find a suitable value within a limited number + * of attempts. This has a negligible probability if \p N + * is significantly larger than \p min, which is the case + * for all usual cryptographic applications. + */ +int mbedtls_mpi_mod_raw_random(mbedtls_mpi_uint *X, + mbedtls_mpi_uint min, + const mbedtls_mpi_mod_modulus *N, + int (*f_rng)(void *, unsigned char *, size_t), + void *p_rng); + +/** Convert an MPI into Montgomery form. + * + * \param X The address of the MPI. + * Must have the same number of limbs as \p N. + * \param N The address of the modulus, which gives the size of + * the base `R` = 2^(biL*N->limbs). + * + * \return \c 0 if successful. + */ +int mbedtls_mpi_mod_raw_to_mont_rep(mbedtls_mpi_uint *X, + const mbedtls_mpi_mod_modulus *N); + +/** Convert an MPI back from Montgomery representation. + * + * \param X The address of the MPI. + * Must have the same number of limbs as \p N. + * \param N The address of the modulus, which gives the size of + * the base `R`= 2^(biL*N->limbs). + * + * \return \c 0 if successful. + */ +int mbedtls_mpi_mod_raw_from_mont_rep(mbedtls_mpi_uint *X, + const mbedtls_mpi_mod_modulus *N); + +/** \brief Perform fixed width modular negation. + * + * The size of the operation is determined by \p N. \p A must have + * the same number of limbs as \p N. + * + * \p X may be aliased to \p A. + * + * \param[out] X The result of the modular negation. + * This must be initialized. + * \param[in] A Little-endian presentation of the input operand. This + * must be less than or equal to \p N. + * \param[in] N The modulus to use. + */ +void mbedtls_mpi_mod_raw_neg(mbedtls_mpi_uint *X, + const mbedtls_mpi_uint *A, + const mbedtls_mpi_mod_modulus *N); + +#endif /* MBEDTLS_BIGNUM_MOD_RAW_H */ diff --git a/vendor/mbedtls/library/bignum_mod_raw_invasive.h b/vendor/mbedtls/library/bignum_mod_raw_invasive.h new file mode 100644 index 0000000000..94a0d06cf0 --- /dev/null +++ b/vendor/mbedtls/library/bignum_mod_raw_invasive.h @@ -0,0 +1,34 @@ +/** + * \file bignum_mod_raw_invasive.h + * + * \brief Function declarations for invasive functions of Low-level + * modular bignum. + */ +/** + * Copyright The Mbed TLS Contributors + * SPDX-License-Identifier: Apache-2.0 OR GPL-2.0-or-later + */ + +#ifndef MBEDTLS_BIGNUM_MOD_RAW_INVASIVE_H +#define MBEDTLS_BIGNUM_MOD_RAW_INVASIVE_H + +#include "common.h" +#include "mbedtls/bignum.h" +#include "bignum_mod.h" + +#if defined(MBEDTLS_TEST_HOOKS) + +/** Convert the result of a quasi-reduction to its canonical representative. + * + * \param[in,out] X The address of the MPI to be converted. Must have the + * same number of limbs as \p N. The input value must + * be in range 0 <= X < 2N. + * \param[in] N The address of the modulus. + */ +MBEDTLS_STATIC_TESTABLE +void mbedtls_mpi_mod_raw_fix_quasi_reduction(mbedtls_mpi_uint *X, + const mbedtls_mpi_mod_modulus *N); + +#endif /* MBEDTLS_TEST_HOOKS */ + +#endif /* MBEDTLS_BIGNUM_MOD_RAW_INVASIVE_H */ diff --git a/vendor/mbedtls/library/block_cipher.c b/vendor/mbedtls/library/block_cipher.c new file mode 100644 index 0000000000..04cd7fb444 --- /dev/null +++ b/vendor/mbedtls/library/block_cipher.c @@ -0,0 +1,203 @@ +/** + * \file block_cipher.c + * + * \brief Lightweight abstraction layer for block ciphers with 128 bit blocks, + * for use by the GCM and CCM modules. + */ +/* + * Copyright The Mbed TLS Contributors + * SPDX-License-Identifier: Apache-2.0 OR GPL-2.0-or-later + */ + +#include "common.h" + +#if defined(MBEDTLS_BLOCK_CIPHER_SOME_PSA) +#include "psa/crypto.h" +#include "psa_crypto_core.h" +#include "psa_util_internal.h" +#endif + +#include "block_cipher_internal.h" + +#if defined(MBEDTLS_BLOCK_CIPHER_C) + +#if defined(MBEDTLS_BLOCK_CIPHER_SOME_PSA) +static psa_key_type_t psa_key_type_from_block_cipher_id(mbedtls_block_cipher_id_t cipher_id) +{ + switch (cipher_id) { +#if defined(MBEDTLS_BLOCK_CIPHER_AES_VIA_PSA) + case MBEDTLS_BLOCK_CIPHER_ID_AES: + return PSA_KEY_TYPE_AES; +#endif +#if defined(MBEDTLS_BLOCK_CIPHER_ARIA_VIA_PSA) + case MBEDTLS_BLOCK_CIPHER_ID_ARIA: + return PSA_KEY_TYPE_ARIA; +#endif +#if defined(MBEDTLS_BLOCK_CIPHER_CAMELLIA_VIA_PSA) + case MBEDTLS_BLOCK_CIPHER_ID_CAMELLIA: + return PSA_KEY_TYPE_CAMELLIA; +#endif + default: + return PSA_KEY_TYPE_NONE; + } +} + +static int mbedtls_cipher_error_from_psa(psa_status_t status) +{ + return PSA_TO_MBEDTLS_ERR_LIST(status, psa_to_cipher_errors, + psa_generic_status_to_mbedtls); +} +#endif /* MBEDTLS_BLOCK_CIPHER_SOME_PSA */ + +void mbedtls_block_cipher_free(mbedtls_block_cipher_context_t *ctx) +{ +#if defined(MBEDTLS_BLOCK_CIPHER_SOME_PSA) + if (ctx->engine == MBEDTLS_BLOCK_CIPHER_ENGINE_PSA) { + psa_destroy_key(ctx->psa_key_id); + return; + } +#endif + switch (ctx->id) { +#if defined(MBEDTLS_AES_C) + case MBEDTLS_BLOCK_CIPHER_ID_AES: + mbedtls_aes_free(&ctx->ctx.aes); + break; +#endif +#if defined(MBEDTLS_ARIA_C) + case MBEDTLS_BLOCK_CIPHER_ID_ARIA: + mbedtls_aria_free(&ctx->ctx.aria); + break; +#endif +#if defined(MBEDTLS_CAMELLIA_C) + case MBEDTLS_BLOCK_CIPHER_ID_CAMELLIA: + mbedtls_camellia_free(&ctx->ctx.camellia); + break; +#endif + default: + break; + } + ctx->id = MBEDTLS_BLOCK_CIPHER_ID_NONE; +} + +int mbedtls_block_cipher_setup(mbedtls_block_cipher_context_t *ctx, + mbedtls_cipher_id_t cipher_id) +{ + ctx->id = (cipher_id == MBEDTLS_CIPHER_ID_AES) ? MBEDTLS_BLOCK_CIPHER_ID_AES : + (cipher_id == MBEDTLS_CIPHER_ID_ARIA) ? MBEDTLS_BLOCK_CIPHER_ID_ARIA : + (cipher_id == MBEDTLS_CIPHER_ID_CAMELLIA) ? MBEDTLS_BLOCK_CIPHER_ID_CAMELLIA : + MBEDTLS_BLOCK_CIPHER_ID_NONE; + +#if defined(MBEDTLS_BLOCK_CIPHER_SOME_PSA) + psa_key_type_t psa_key_type = psa_key_type_from_block_cipher_id(ctx->id); + if (psa_key_type != PSA_KEY_TYPE_NONE && + psa_can_do_cipher(psa_key_type, PSA_ALG_ECB_NO_PADDING)) { + ctx->engine = MBEDTLS_BLOCK_CIPHER_ENGINE_PSA; + return 0; + } + ctx->engine = MBEDTLS_BLOCK_CIPHER_ENGINE_LEGACY; +#endif + + switch (ctx->id) { +#if defined(MBEDTLS_AES_C) + case MBEDTLS_BLOCK_CIPHER_ID_AES: + mbedtls_aes_init(&ctx->ctx.aes); + return 0; +#endif +#if defined(MBEDTLS_ARIA_C) + case MBEDTLS_BLOCK_CIPHER_ID_ARIA: + mbedtls_aria_init(&ctx->ctx.aria); + return 0; +#endif +#if defined(MBEDTLS_CAMELLIA_C) + case MBEDTLS_BLOCK_CIPHER_ID_CAMELLIA: + mbedtls_camellia_init(&ctx->ctx.camellia); + return 0; +#endif + default: + ctx->id = MBEDTLS_BLOCK_CIPHER_ID_NONE; + return MBEDTLS_ERR_CIPHER_BAD_INPUT_DATA; + } +} + +int mbedtls_block_cipher_setkey(mbedtls_block_cipher_context_t *ctx, + const unsigned char *key, + unsigned key_bitlen) +{ +#if defined(MBEDTLS_BLOCK_CIPHER_SOME_PSA) + if (ctx->engine == MBEDTLS_BLOCK_CIPHER_ENGINE_PSA) { + psa_key_attributes_t key_attr = PSA_KEY_ATTRIBUTES_INIT; + psa_status_t status; + + psa_set_key_type(&key_attr, psa_key_type_from_block_cipher_id(ctx->id)); + psa_set_key_bits(&key_attr, key_bitlen); + psa_set_key_algorithm(&key_attr, PSA_ALG_ECB_NO_PADDING); + psa_set_key_usage_flags(&key_attr, PSA_KEY_USAGE_ENCRYPT); + + status = psa_import_key(&key_attr, key, PSA_BITS_TO_BYTES(key_bitlen), &ctx->psa_key_id); + if (status != PSA_SUCCESS) { + return mbedtls_cipher_error_from_psa(status); + } + psa_reset_key_attributes(&key_attr); + + return 0; + } +#endif /* MBEDTLS_BLOCK_CIPHER_SOME_PSA */ + + switch (ctx->id) { +#if defined(MBEDTLS_AES_C) + case MBEDTLS_BLOCK_CIPHER_ID_AES: + return mbedtls_aes_setkey_enc(&ctx->ctx.aes, key, key_bitlen); +#endif +#if defined(MBEDTLS_ARIA_C) + case MBEDTLS_BLOCK_CIPHER_ID_ARIA: + return mbedtls_aria_setkey_enc(&ctx->ctx.aria, key, key_bitlen); +#endif +#if defined(MBEDTLS_CAMELLIA_C) + case MBEDTLS_BLOCK_CIPHER_ID_CAMELLIA: + return mbedtls_camellia_setkey_enc(&ctx->ctx.camellia, key, key_bitlen); +#endif + default: + return MBEDTLS_ERR_CIPHER_INVALID_CONTEXT; + } +} + +int mbedtls_block_cipher_encrypt(mbedtls_block_cipher_context_t *ctx, + const unsigned char input[16], + unsigned char output[16]) +{ +#if defined(MBEDTLS_BLOCK_CIPHER_SOME_PSA) + if (ctx->engine == MBEDTLS_BLOCK_CIPHER_ENGINE_PSA) { + psa_status_t status; + size_t olen; + + status = psa_cipher_encrypt(ctx->psa_key_id, PSA_ALG_ECB_NO_PADDING, + input, 16, output, 16, &olen); + if (status != PSA_SUCCESS) { + return mbedtls_cipher_error_from_psa(status); + } + return 0; + } +#endif /* MBEDTLS_BLOCK_CIPHER_SOME_PSA */ + + switch (ctx->id) { +#if defined(MBEDTLS_AES_C) + case MBEDTLS_BLOCK_CIPHER_ID_AES: + return mbedtls_aes_crypt_ecb(&ctx->ctx.aes, MBEDTLS_AES_ENCRYPT, + input, output); +#endif +#if defined(MBEDTLS_ARIA_C) + case MBEDTLS_BLOCK_CIPHER_ID_ARIA: + return mbedtls_aria_crypt_ecb(&ctx->ctx.aria, input, output); +#endif +#if defined(MBEDTLS_CAMELLIA_C) + case MBEDTLS_BLOCK_CIPHER_ID_CAMELLIA: + return mbedtls_camellia_crypt_ecb(&ctx->ctx.camellia, + MBEDTLS_CAMELLIA_ENCRYPT, + input, output); +#endif + default: + return MBEDTLS_ERR_CIPHER_INVALID_CONTEXT; + } +} + +#endif /* MBEDTLS_BLOCK_CIPHER_C */ diff --git a/vendor/mbedtls/library/block_cipher_internal.h b/vendor/mbedtls/library/block_cipher_internal.h new file mode 100644 index 0000000000..c57338b751 --- /dev/null +++ b/vendor/mbedtls/library/block_cipher_internal.h @@ -0,0 +1,99 @@ +/** + * \file block_cipher_internal.h + * + * \brief Lightweight abstraction layer for block ciphers with 128 bit blocks, + * for use by the GCM and CCM modules. + */ +/* + * Copyright The Mbed TLS Contributors + * SPDX-License-Identifier: Apache-2.0 OR GPL-2.0-or-later + */ +#ifndef MBEDTLS_BLOCK_CIPHER_INTERNAL_H +#define MBEDTLS_BLOCK_CIPHER_INTERNAL_H + +#include "mbedtls/build_info.h" + +#include "mbedtls/cipher.h" + +#include "mbedtls/block_cipher.h" + +#ifdef __cplusplus +extern "C" { +#endif + +/** + * \brief Initialize the context. + * This must be the first API call before using the context. + * + * \param ctx The context to initialize. + */ +static inline void mbedtls_block_cipher_init(mbedtls_block_cipher_context_t *ctx) +{ + memset(ctx, 0, sizeof(*ctx)); +} + +/** + * \brief Set the block cipher to use with this context. + * This must be called after mbedtls_block_cipher_init(). + * + * \param ctx The context to set up. + * \param cipher_id The identifier of the cipher to use. + * This must be either AES, ARIA or Camellia. + * Warning: this is a ::mbedtls_cipher_id_t, + * not a ::mbedtls_block_cipher_id_t! + * + * \retval \c 0 on success. + * \retval #MBEDTLS_ERR_CIPHER_BAD_INPUT_DATA if \p cipher_id was + * invalid. + */ +int mbedtls_block_cipher_setup(mbedtls_block_cipher_context_t *ctx, + mbedtls_cipher_id_t cipher_id); + +/** + * \brief Set the key into the context. + * + * \param ctx The context to configure. + * \param key The buffer holding the key material. + * \param key_bitlen The size of the key in bits. + * + * \retval \c 0 on success. + * \retval #MBEDTLS_ERR_CIPHER_INVALID_CONTEXT if the context was not + * properly set up before calling this function. + * \retval One of #MBEDTLS_ERR_AES_INVALID_KEY_LENGTH, + * #MBEDTLS_ERR_ARIA_BAD_INPUT_DATA, + * #MBEDTLS_ERR_CAMELLIA_BAD_INPUT_DATA if \p key_bitlen is + * invalid. + */ +int mbedtls_block_cipher_setkey(mbedtls_block_cipher_context_t *ctx, + const unsigned char *key, + unsigned key_bitlen); + +/** + * \brief Encrypt one block (16 bytes) with the configured key. + * + * \param ctx The context holding the key. + * \param input The buffer holding the input block. Must be 16 bytes. + * \param output The buffer to which the output block will be written. + * Must be writable and 16 bytes long. + * This must either not overlap with \p input, or be equal. + * + * \retval \c 0 on success. + * \retval #MBEDTLS_ERR_CIPHER_INVALID_CONTEXT if the context was not + * properly set up before calling this function. + * \retval Another negative value if encryption failed. + */ +int mbedtls_block_cipher_encrypt(mbedtls_block_cipher_context_t *ctx, + const unsigned char input[16], + unsigned char output[16]); +/** + * \brief Clear the context. + * + * \param ctx The context to clear. + */ +void mbedtls_block_cipher_free(mbedtls_block_cipher_context_t *ctx); + +#ifdef __cplusplus +} +#endif + +#endif /* MBEDTLS_BLOCK_CIPHER_INTERNAL_H */ diff --git a/vendor/mbedtls/library/blowfish.c b/vendor/mbedtls/library/blowfish.c deleted file mode 100644 index f56bb65bfd..0000000000 --- a/vendor/mbedtls/library/blowfish.c +++ /dev/null @@ -1,656 +0,0 @@ -/* - * Blowfish implementation - * - * Copyright The Mbed TLS Contributors - * SPDX-License-Identifier: Apache-2.0 - * - * Licensed under the Apache License, Version 2.0 (the "License"); you may - * not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT - * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ -/* - * The Blowfish block cipher was designed by Bruce Schneier in 1993. - * http://www.schneier.com/blowfish.html - * http://en.wikipedia.org/wiki/Blowfish_%28cipher%29 - * - */ - -#include "common.h" - -#if defined(MBEDTLS_BLOWFISH_C) - -#include "mbedtls/blowfish.h" -#include "mbedtls/platform_util.h" - -#include - -#if !defined(MBEDTLS_BLOWFISH_ALT) - -/* Parameter validation macros */ -#define BLOWFISH_VALIDATE_RET(cond) \ - MBEDTLS_INTERNAL_VALIDATE_RET(cond, MBEDTLS_ERR_BLOWFISH_BAD_INPUT_DATA) -#define BLOWFISH_VALIDATE(cond) \ - MBEDTLS_INTERNAL_VALIDATE(cond) - -static const uint32_t P[MBEDTLS_BLOWFISH_ROUNDS + 2] = { - 0x243F6A88L, 0x85A308D3L, 0x13198A2EL, 0x03707344L, - 0xA4093822L, 0x299F31D0L, 0x082EFA98L, 0xEC4E6C89L, - 0x452821E6L, 0x38D01377L, 0xBE5466CFL, 0x34E90C6CL, - 0xC0AC29B7L, 0xC97C50DDL, 0x3F84D5B5L, 0xB5470917L, - 0x9216D5D9L, 0x8979FB1BL -}; - -/* declarations of data at the end of this file */ -static const uint32_t S[4][256]; - -static uint32_t F(mbedtls_blowfish_context *ctx, uint32_t x) -{ - unsigned short a, b, c, d; - uint32_t y; - - d = MBEDTLS_BYTE_0(x); - x >>= 8; - c = MBEDTLS_BYTE_0(x); - x >>= 8; - b = MBEDTLS_BYTE_0(x); - x >>= 8; - a = MBEDTLS_BYTE_0(x); - y = ctx->S[0][a] + ctx->S[1][b]; - y = y ^ ctx->S[2][c]; - y = y + ctx->S[3][d]; - - return y; -} - -static void blowfish_enc(mbedtls_blowfish_context *ctx, uint32_t *xl, uint32_t *xr) -{ - uint32_t Xl, Xr, temp; - short i; - - Xl = *xl; - Xr = *xr; - - for (i = 0; i < MBEDTLS_BLOWFISH_ROUNDS; ++i) { - Xl = Xl ^ ctx->P[i]; - Xr = F(ctx, Xl) ^ Xr; - - temp = Xl; - Xl = Xr; - Xr = temp; - } - - temp = Xl; - Xl = Xr; - Xr = temp; - - Xr = Xr ^ ctx->P[MBEDTLS_BLOWFISH_ROUNDS]; - Xl = Xl ^ ctx->P[MBEDTLS_BLOWFISH_ROUNDS + 1]; - - *xl = Xl; - *xr = Xr; -} - -static void blowfish_dec(mbedtls_blowfish_context *ctx, uint32_t *xl, uint32_t *xr) -{ - uint32_t Xl, Xr, temp; - short i; - - Xl = *xl; - Xr = *xr; - - for (i = MBEDTLS_BLOWFISH_ROUNDS + 1; i > 1; --i) { - Xl = Xl ^ ctx->P[i]; - Xr = F(ctx, Xl) ^ Xr; - - temp = Xl; - Xl = Xr; - Xr = temp; - } - - temp = Xl; - Xl = Xr; - Xr = temp; - - Xr = Xr ^ ctx->P[1]; - Xl = Xl ^ ctx->P[0]; - - *xl = Xl; - *xr = Xr; -} - -void mbedtls_blowfish_init(mbedtls_blowfish_context *ctx) -{ - BLOWFISH_VALIDATE(ctx != NULL); - memset(ctx, 0, sizeof(mbedtls_blowfish_context)); -} - -void mbedtls_blowfish_free(mbedtls_blowfish_context *ctx) -{ - if (ctx == NULL) { - return; - } - - mbedtls_platform_zeroize(ctx, sizeof(mbedtls_blowfish_context)); -} - -/* - * Blowfish key schedule - */ -int mbedtls_blowfish_setkey(mbedtls_blowfish_context *ctx, - const unsigned char *key, - unsigned int keybits) -{ - unsigned int i, j, k; - uint32_t data, datal, datar; - BLOWFISH_VALIDATE_RET(ctx != NULL); - BLOWFISH_VALIDATE_RET(key != NULL); - - if (keybits < MBEDTLS_BLOWFISH_MIN_KEY_BITS || - keybits > MBEDTLS_BLOWFISH_MAX_KEY_BITS || - keybits % 8 != 0) { - return MBEDTLS_ERR_BLOWFISH_BAD_INPUT_DATA; - } - - keybits >>= 3; - - for (i = 0; i < 4; i++) { - for (j = 0; j < 256; j++) { - ctx->S[i][j] = S[i][j]; - } - } - - j = 0; - for (i = 0; i < MBEDTLS_BLOWFISH_ROUNDS + 2; ++i) { - data = 0x00000000; - for (k = 0; k < 4; ++k) { - data = (data << 8) | key[j++]; - if (j >= keybits) { - j = 0; - } - } - ctx->P[i] = P[i] ^ data; - } - - datal = 0x00000000; - datar = 0x00000000; - - for (i = 0; i < MBEDTLS_BLOWFISH_ROUNDS + 2; i += 2) { - blowfish_enc(ctx, &datal, &datar); - ctx->P[i] = datal; - ctx->P[i + 1] = datar; - } - - for (i = 0; i < 4; i++) { - for (j = 0; j < 256; j += 2) { - blowfish_enc(ctx, &datal, &datar); - ctx->S[i][j] = datal; - ctx->S[i][j + 1] = datar; - } - } - return 0; -} - -/* - * Blowfish-ECB block encryption/decryption - */ -int mbedtls_blowfish_crypt_ecb(mbedtls_blowfish_context *ctx, - int mode, - const unsigned char input[MBEDTLS_BLOWFISH_BLOCKSIZE], - unsigned char output[MBEDTLS_BLOWFISH_BLOCKSIZE]) -{ - uint32_t X0, X1; - BLOWFISH_VALIDATE_RET(ctx != NULL); - BLOWFISH_VALIDATE_RET(mode == MBEDTLS_BLOWFISH_ENCRYPT || - mode == MBEDTLS_BLOWFISH_DECRYPT); - BLOWFISH_VALIDATE_RET(input != NULL); - BLOWFISH_VALIDATE_RET(output != NULL); - - X0 = MBEDTLS_GET_UINT32_BE(input, 0); - X1 = MBEDTLS_GET_UINT32_BE(input, 4); - - if (mode == MBEDTLS_BLOWFISH_DECRYPT) { - blowfish_dec(ctx, &X0, &X1); - } else { /* MBEDTLS_BLOWFISH_ENCRYPT */ - blowfish_enc(ctx, &X0, &X1); - } - - MBEDTLS_PUT_UINT32_BE(X0, output, 0); - MBEDTLS_PUT_UINT32_BE(X1, output, 4); - - return 0; -} - -#if defined(MBEDTLS_CIPHER_MODE_CBC) -/* - * Blowfish-CBC buffer encryption/decryption - */ -int mbedtls_blowfish_crypt_cbc(mbedtls_blowfish_context *ctx, - int mode, - size_t length, - unsigned char iv[MBEDTLS_BLOWFISH_BLOCKSIZE], - const unsigned char *input, - unsigned char *output) -{ - int i; - unsigned char temp[MBEDTLS_BLOWFISH_BLOCKSIZE]; - BLOWFISH_VALIDATE_RET(ctx != NULL); - BLOWFISH_VALIDATE_RET(mode == MBEDTLS_BLOWFISH_ENCRYPT || - mode == MBEDTLS_BLOWFISH_DECRYPT); - BLOWFISH_VALIDATE_RET(iv != NULL); - BLOWFISH_VALIDATE_RET(length == 0 || input != NULL); - BLOWFISH_VALIDATE_RET(length == 0 || output != NULL); - - if (length % MBEDTLS_BLOWFISH_BLOCKSIZE) { - return MBEDTLS_ERR_BLOWFISH_INVALID_INPUT_LENGTH; - } - - if (mode == MBEDTLS_BLOWFISH_DECRYPT) { - while (length > 0) { - memcpy(temp, input, MBEDTLS_BLOWFISH_BLOCKSIZE); - mbedtls_blowfish_crypt_ecb(ctx, mode, input, output); - - for (i = 0; i < MBEDTLS_BLOWFISH_BLOCKSIZE; i++) { - output[i] = (unsigned char) (output[i] ^ iv[i]); - } - - memcpy(iv, temp, MBEDTLS_BLOWFISH_BLOCKSIZE); - - input += MBEDTLS_BLOWFISH_BLOCKSIZE; - output += MBEDTLS_BLOWFISH_BLOCKSIZE; - length -= MBEDTLS_BLOWFISH_BLOCKSIZE; - } - } else { - while (length > 0) { - for (i = 0; i < MBEDTLS_BLOWFISH_BLOCKSIZE; i++) { - output[i] = (unsigned char) (input[i] ^ iv[i]); - } - - mbedtls_blowfish_crypt_ecb(ctx, mode, output, output); - memcpy(iv, output, MBEDTLS_BLOWFISH_BLOCKSIZE); - - input += MBEDTLS_BLOWFISH_BLOCKSIZE; - output += MBEDTLS_BLOWFISH_BLOCKSIZE; - length -= MBEDTLS_BLOWFISH_BLOCKSIZE; - } - } - - return 0; -} -#endif /* MBEDTLS_CIPHER_MODE_CBC */ - -#if defined(MBEDTLS_CIPHER_MODE_CFB) -/* - * Blowfish CFB buffer encryption/decryption - */ -int mbedtls_blowfish_crypt_cfb64(mbedtls_blowfish_context *ctx, - int mode, - size_t length, - size_t *iv_off, - unsigned char iv[MBEDTLS_BLOWFISH_BLOCKSIZE], - const unsigned char *input, - unsigned char *output) -{ - int c; - size_t n; - - BLOWFISH_VALIDATE_RET(ctx != NULL); - BLOWFISH_VALIDATE_RET(mode == MBEDTLS_BLOWFISH_ENCRYPT || - mode == MBEDTLS_BLOWFISH_DECRYPT); - BLOWFISH_VALIDATE_RET(iv != NULL); - BLOWFISH_VALIDATE_RET(iv_off != NULL); - BLOWFISH_VALIDATE_RET(length == 0 || input != NULL); - BLOWFISH_VALIDATE_RET(length == 0 || output != NULL); - - n = *iv_off; - if (n >= 8) { - return MBEDTLS_ERR_BLOWFISH_BAD_INPUT_DATA; - } - - if (mode == MBEDTLS_BLOWFISH_DECRYPT) { - while (length--) { - if (n == 0) { - mbedtls_blowfish_crypt_ecb(ctx, MBEDTLS_BLOWFISH_ENCRYPT, iv, iv); - } - - c = *input++; - *output++ = (unsigned char) (c ^ iv[n]); - iv[n] = (unsigned char) c; - - n = (n + 1) % MBEDTLS_BLOWFISH_BLOCKSIZE; - } - } else { - while (length--) { - if (n == 0) { - mbedtls_blowfish_crypt_ecb(ctx, MBEDTLS_BLOWFISH_ENCRYPT, iv, iv); - } - - iv[n] = *output++ = (unsigned char) (iv[n] ^ *input++); - - n = (n + 1) % MBEDTLS_BLOWFISH_BLOCKSIZE; - } - } - - *iv_off = n; - - return 0; -} -#endif /*MBEDTLS_CIPHER_MODE_CFB */ - -#if defined(MBEDTLS_CIPHER_MODE_CTR) -/* - * Blowfish CTR buffer encryption/decryption - */ -int mbedtls_blowfish_crypt_ctr(mbedtls_blowfish_context *ctx, - size_t length, - size_t *nc_off, - unsigned char nonce_counter[MBEDTLS_BLOWFISH_BLOCKSIZE], - unsigned char stream_block[MBEDTLS_BLOWFISH_BLOCKSIZE], - const unsigned char *input, - unsigned char *output) -{ - int c, i; - size_t n; - BLOWFISH_VALIDATE_RET(ctx != NULL); - BLOWFISH_VALIDATE_RET(nonce_counter != NULL); - BLOWFISH_VALIDATE_RET(stream_block != NULL); - BLOWFISH_VALIDATE_RET(nc_off != NULL); - BLOWFISH_VALIDATE_RET(length == 0 || input != NULL); - BLOWFISH_VALIDATE_RET(length == 0 || output != NULL); - - n = *nc_off; - if (n >= 8) { - return MBEDTLS_ERR_BLOWFISH_BAD_INPUT_DATA; - } - - while (length--) { - if (n == 0) { - mbedtls_blowfish_crypt_ecb(ctx, MBEDTLS_BLOWFISH_ENCRYPT, nonce_counter, - stream_block); - - for (i = MBEDTLS_BLOWFISH_BLOCKSIZE; i > 0; i--) { - if (++nonce_counter[i - 1] != 0) { - break; - } - } - } - c = *input++; - *output++ = (unsigned char) (c ^ stream_block[n]); - - n = (n + 1) % MBEDTLS_BLOWFISH_BLOCKSIZE; - } - - *nc_off = n; - - return 0; -} -#endif /* MBEDTLS_CIPHER_MODE_CTR */ - -static const uint32_t S[4][256] = { - { 0xD1310BA6L, 0x98DFB5ACL, 0x2FFD72DBL, 0xD01ADFB7L, - 0xB8E1AFEDL, 0x6A267E96L, 0xBA7C9045L, 0xF12C7F99L, - 0x24A19947L, 0xB3916CF7L, 0x0801F2E2L, 0x858EFC16L, - 0x636920D8L, 0x71574E69L, 0xA458FEA3L, 0xF4933D7EL, - 0x0D95748FL, 0x728EB658L, 0x718BCD58L, 0x82154AEEL, - 0x7B54A41DL, 0xC25A59B5L, 0x9C30D539L, 0x2AF26013L, - 0xC5D1B023L, 0x286085F0L, 0xCA417918L, 0xB8DB38EFL, - 0x8E79DCB0L, 0x603A180EL, 0x6C9E0E8BL, 0xB01E8A3EL, - 0xD71577C1L, 0xBD314B27L, 0x78AF2FDAL, 0x55605C60L, - 0xE65525F3L, 0xAA55AB94L, 0x57489862L, 0x63E81440L, - 0x55CA396AL, 0x2AAB10B6L, 0xB4CC5C34L, 0x1141E8CEL, - 0xA15486AFL, 0x7C72E993L, 0xB3EE1411L, 0x636FBC2AL, - 0x2BA9C55DL, 0x741831F6L, 0xCE5C3E16L, 0x9B87931EL, - 0xAFD6BA33L, 0x6C24CF5CL, 0x7A325381L, 0x28958677L, - 0x3B8F4898L, 0x6B4BB9AFL, 0xC4BFE81BL, 0x66282193L, - 0x61D809CCL, 0xFB21A991L, 0x487CAC60L, 0x5DEC8032L, - 0xEF845D5DL, 0xE98575B1L, 0xDC262302L, 0xEB651B88L, - 0x23893E81L, 0xD396ACC5L, 0x0F6D6FF3L, 0x83F44239L, - 0x2E0B4482L, 0xA4842004L, 0x69C8F04AL, 0x9E1F9B5EL, - 0x21C66842L, 0xF6E96C9AL, 0x670C9C61L, 0xABD388F0L, - 0x6A51A0D2L, 0xD8542F68L, 0x960FA728L, 0xAB5133A3L, - 0x6EEF0B6CL, 0x137A3BE4L, 0xBA3BF050L, 0x7EFB2A98L, - 0xA1F1651DL, 0x39AF0176L, 0x66CA593EL, 0x82430E88L, - 0x8CEE8619L, 0x456F9FB4L, 0x7D84A5C3L, 0x3B8B5EBEL, - 0xE06F75D8L, 0x85C12073L, 0x401A449FL, 0x56C16AA6L, - 0x4ED3AA62L, 0x363F7706L, 0x1BFEDF72L, 0x429B023DL, - 0x37D0D724L, 0xD00A1248L, 0xDB0FEAD3L, 0x49F1C09BL, - 0x075372C9L, 0x80991B7BL, 0x25D479D8L, 0xF6E8DEF7L, - 0xE3FE501AL, 0xB6794C3BL, 0x976CE0BDL, 0x04C006BAL, - 0xC1A94FB6L, 0x409F60C4L, 0x5E5C9EC2L, 0x196A2463L, - 0x68FB6FAFL, 0x3E6C53B5L, 0x1339B2EBL, 0x3B52EC6FL, - 0x6DFC511FL, 0x9B30952CL, 0xCC814544L, 0xAF5EBD09L, - 0xBEE3D004L, 0xDE334AFDL, 0x660F2807L, 0x192E4BB3L, - 0xC0CBA857L, 0x45C8740FL, 0xD20B5F39L, 0xB9D3FBDBL, - 0x5579C0BDL, 0x1A60320AL, 0xD6A100C6L, 0x402C7279L, - 0x679F25FEL, 0xFB1FA3CCL, 0x8EA5E9F8L, 0xDB3222F8L, - 0x3C7516DFL, 0xFD616B15L, 0x2F501EC8L, 0xAD0552ABL, - 0x323DB5FAL, 0xFD238760L, 0x53317B48L, 0x3E00DF82L, - 0x9E5C57BBL, 0xCA6F8CA0L, 0x1A87562EL, 0xDF1769DBL, - 0xD542A8F6L, 0x287EFFC3L, 0xAC6732C6L, 0x8C4F5573L, - 0x695B27B0L, 0xBBCA58C8L, 0xE1FFA35DL, 0xB8F011A0L, - 0x10FA3D98L, 0xFD2183B8L, 0x4AFCB56CL, 0x2DD1D35BL, - 0x9A53E479L, 0xB6F84565L, 0xD28E49BCL, 0x4BFB9790L, - 0xE1DDF2DAL, 0xA4CB7E33L, 0x62FB1341L, 0xCEE4C6E8L, - 0xEF20CADAL, 0x36774C01L, 0xD07E9EFEL, 0x2BF11FB4L, - 0x95DBDA4DL, 0xAE909198L, 0xEAAD8E71L, 0x6B93D5A0L, - 0xD08ED1D0L, 0xAFC725E0L, 0x8E3C5B2FL, 0x8E7594B7L, - 0x8FF6E2FBL, 0xF2122B64L, 0x8888B812L, 0x900DF01CL, - 0x4FAD5EA0L, 0x688FC31CL, 0xD1CFF191L, 0xB3A8C1ADL, - 0x2F2F2218L, 0xBE0E1777L, 0xEA752DFEL, 0x8B021FA1L, - 0xE5A0CC0FL, 0xB56F74E8L, 0x18ACF3D6L, 0xCE89E299L, - 0xB4A84FE0L, 0xFD13E0B7L, 0x7CC43B81L, 0xD2ADA8D9L, - 0x165FA266L, 0x80957705L, 0x93CC7314L, 0x211A1477L, - 0xE6AD2065L, 0x77B5FA86L, 0xC75442F5L, 0xFB9D35CFL, - 0xEBCDAF0CL, 0x7B3E89A0L, 0xD6411BD3L, 0xAE1E7E49L, - 0x00250E2DL, 0x2071B35EL, 0x226800BBL, 0x57B8E0AFL, - 0x2464369BL, 0xF009B91EL, 0x5563911DL, 0x59DFA6AAL, - 0x78C14389L, 0xD95A537FL, 0x207D5BA2L, 0x02E5B9C5L, - 0x83260376L, 0x6295CFA9L, 0x11C81968L, 0x4E734A41L, - 0xB3472DCAL, 0x7B14A94AL, 0x1B510052L, 0x9A532915L, - 0xD60F573FL, 0xBC9BC6E4L, 0x2B60A476L, 0x81E67400L, - 0x08BA6FB5L, 0x571BE91FL, 0xF296EC6BL, 0x2A0DD915L, - 0xB6636521L, 0xE7B9F9B6L, 0xFF34052EL, 0xC5855664L, - 0x53B02D5DL, 0xA99F8FA1L, 0x08BA4799L, 0x6E85076AL }, - { 0x4B7A70E9L, 0xB5B32944L, 0xDB75092EL, 0xC4192623L, - 0xAD6EA6B0L, 0x49A7DF7DL, 0x9CEE60B8L, 0x8FEDB266L, - 0xECAA8C71L, 0x699A17FFL, 0x5664526CL, 0xC2B19EE1L, - 0x193602A5L, 0x75094C29L, 0xA0591340L, 0xE4183A3EL, - 0x3F54989AL, 0x5B429D65L, 0x6B8FE4D6L, 0x99F73FD6L, - 0xA1D29C07L, 0xEFE830F5L, 0x4D2D38E6L, 0xF0255DC1L, - 0x4CDD2086L, 0x8470EB26L, 0x6382E9C6L, 0x021ECC5EL, - 0x09686B3FL, 0x3EBAEFC9L, 0x3C971814L, 0x6B6A70A1L, - 0x687F3584L, 0x52A0E286L, 0xB79C5305L, 0xAA500737L, - 0x3E07841CL, 0x7FDEAE5CL, 0x8E7D44ECL, 0x5716F2B8L, - 0xB03ADA37L, 0xF0500C0DL, 0xF01C1F04L, 0x0200B3FFL, - 0xAE0CF51AL, 0x3CB574B2L, 0x25837A58L, 0xDC0921BDL, - 0xD19113F9L, 0x7CA92FF6L, 0x94324773L, 0x22F54701L, - 0x3AE5E581L, 0x37C2DADCL, 0xC8B57634L, 0x9AF3DDA7L, - 0xA9446146L, 0x0FD0030EL, 0xECC8C73EL, 0xA4751E41L, - 0xE238CD99L, 0x3BEA0E2FL, 0x3280BBA1L, 0x183EB331L, - 0x4E548B38L, 0x4F6DB908L, 0x6F420D03L, 0xF60A04BFL, - 0x2CB81290L, 0x24977C79L, 0x5679B072L, 0xBCAF89AFL, - 0xDE9A771FL, 0xD9930810L, 0xB38BAE12L, 0xDCCF3F2EL, - 0x5512721FL, 0x2E6B7124L, 0x501ADDE6L, 0x9F84CD87L, - 0x7A584718L, 0x7408DA17L, 0xBC9F9ABCL, 0xE94B7D8CL, - 0xEC7AEC3AL, 0xDB851DFAL, 0x63094366L, 0xC464C3D2L, - 0xEF1C1847L, 0x3215D908L, 0xDD433B37L, 0x24C2BA16L, - 0x12A14D43L, 0x2A65C451L, 0x50940002L, 0x133AE4DDL, - 0x71DFF89EL, 0x10314E55L, 0x81AC77D6L, 0x5F11199BL, - 0x043556F1L, 0xD7A3C76BL, 0x3C11183BL, 0x5924A509L, - 0xF28FE6EDL, 0x97F1FBFAL, 0x9EBABF2CL, 0x1E153C6EL, - 0x86E34570L, 0xEAE96FB1L, 0x860E5E0AL, 0x5A3E2AB3L, - 0x771FE71CL, 0x4E3D06FAL, 0x2965DCB9L, 0x99E71D0FL, - 0x803E89D6L, 0x5266C825L, 0x2E4CC978L, 0x9C10B36AL, - 0xC6150EBAL, 0x94E2EA78L, 0xA5FC3C53L, 0x1E0A2DF4L, - 0xF2F74EA7L, 0x361D2B3DL, 0x1939260FL, 0x19C27960L, - 0x5223A708L, 0xF71312B6L, 0xEBADFE6EL, 0xEAC31F66L, - 0xE3BC4595L, 0xA67BC883L, 0xB17F37D1L, 0x018CFF28L, - 0xC332DDEFL, 0xBE6C5AA5L, 0x65582185L, 0x68AB9802L, - 0xEECEA50FL, 0xDB2F953BL, 0x2AEF7DADL, 0x5B6E2F84L, - 0x1521B628L, 0x29076170L, 0xECDD4775L, 0x619F1510L, - 0x13CCA830L, 0xEB61BD96L, 0x0334FE1EL, 0xAA0363CFL, - 0xB5735C90L, 0x4C70A239L, 0xD59E9E0BL, 0xCBAADE14L, - 0xEECC86BCL, 0x60622CA7L, 0x9CAB5CABL, 0xB2F3846EL, - 0x648B1EAFL, 0x19BDF0CAL, 0xA02369B9L, 0x655ABB50L, - 0x40685A32L, 0x3C2AB4B3L, 0x319EE9D5L, 0xC021B8F7L, - 0x9B540B19L, 0x875FA099L, 0x95F7997EL, 0x623D7DA8L, - 0xF837889AL, 0x97E32D77L, 0x11ED935FL, 0x16681281L, - 0x0E358829L, 0xC7E61FD6L, 0x96DEDFA1L, 0x7858BA99L, - 0x57F584A5L, 0x1B227263L, 0x9B83C3FFL, 0x1AC24696L, - 0xCDB30AEBL, 0x532E3054L, 0x8FD948E4L, 0x6DBC3128L, - 0x58EBF2EFL, 0x34C6FFEAL, 0xFE28ED61L, 0xEE7C3C73L, - 0x5D4A14D9L, 0xE864B7E3L, 0x42105D14L, 0x203E13E0L, - 0x45EEE2B6L, 0xA3AAABEAL, 0xDB6C4F15L, 0xFACB4FD0L, - 0xC742F442L, 0xEF6ABBB5L, 0x654F3B1DL, 0x41CD2105L, - 0xD81E799EL, 0x86854DC7L, 0xE44B476AL, 0x3D816250L, - 0xCF62A1F2L, 0x5B8D2646L, 0xFC8883A0L, 0xC1C7B6A3L, - 0x7F1524C3L, 0x69CB7492L, 0x47848A0BL, 0x5692B285L, - 0x095BBF00L, 0xAD19489DL, 0x1462B174L, 0x23820E00L, - 0x58428D2AL, 0x0C55F5EAL, 0x1DADF43EL, 0x233F7061L, - 0x3372F092L, 0x8D937E41L, 0xD65FECF1L, 0x6C223BDBL, - 0x7CDE3759L, 0xCBEE7460L, 0x4085F2A7L, 0xCE77326EL, - 0xA6078084L, 0x19F8509EL, 0xE8EFD855L, 0x61D99735L, - 0xA969A7AAL, 0xC50C06C2L, 0x5A04ABFCL, 0x800BCADCL, - 0x9E447A2EL, 0xC3453484L, 0xFDD56705L, 0x0E1E9EC9L, - 0xDB73DBD3L, 0x105588CDL, 0x675FDA79L, 0xE3674340L, - 0xC5C43465L, 0x713E38D8L, 0x3D28F89EL, 0xF16DFF20L, - 0x153E21E7L, 0x8FB03D4AL, 0xE6E39F2BL, 0xDB83ADF7L }, - { 0xE93D5A68L, 0x948140F7L, 0xF64C261CL, 0x94692934L, - 0x411520F7L, 0x7602D4F7L, 0xBCF46B2EL, 0xD4A20068L, - 0xD4082471L, 0x3320F46AL, 0x43B7D4B7L, 0x500061AFL, - 0x1E39F62EL, 0x97244546L, 0x14214F74L, 0xBF8B8840L, - 0x4D95FC1DL, 0x96B591AFL, 0x70F4DDD3L, 0x66A02F45L, - 0xBFBC09ECL, 0x03BD9785L, 0x7FAC6DD0L, 0x31CB8504L, - 0x96EB27B3L, 0x55FD3941L, 0xDA2547E6L, 0xABCA0A9AL, - 0x28507825L, 0x530429F4L, 0x0A2C86DAL, 0xE9B66DFBL, - 0x68DC1462L, 0xD7486900L, 0x680EC0A4L, 0x27A18DEEL, - 0x4F3FFEA2L, 0xE887AD8CL, 0xB58CE006L, 0x7AF4D6B6L, - 0xAACE1E7CL, 0xD3375FECL, 0xCE78A399L, 0x406B2A42L, - 0x20FE9E35L, 0xD9F385B9L, 0xEE39D7ABL, 0x3B124E8BL, - 0x1DC9FAF7L, 0x4B6D1856L, 0x26A36631L, 0xEAE397B2L, - 0x3A6EFA74L, 0xDD5B4332L, 0x6841E7F7L, 0xCA7820FBL, - 0xFB0AF54EL, 0xD8FEB397L, 0x454056ACL, 0xBA489527L, - 0x55533A3AL, 0x20838D87L, 0xFE6BA9B7L, 0xD096954BL, - 0x55A867BCL, 0xA1159A58L, 0xCCA92963L, 0x99E1DB33L, - 0xA62A4A56L, 0x3F3125F9L, 0x5EF47E1CL, 0x9029317CL, - 0xFDF8E802L, 0x04272F70L, 0x80BB155CL, 0x05282CE3L, - 0x95C11548L, 0xE4C66D22L, 0x48C1133FL, 0xC70F86DCL, - 0x07F9C9EEL, 0x41041F0FL, 0x404779A4L, 0x5D886E17L, - 0x325F51EBL, 0xD59BC0D1L, 0xF2BCC18FL, 0x41113564L, - 0x257B7834L, 0x602A9C60L, 0xDFF8E8A3L, 0x1F636C1BL, - 0x0E12B4C2L, 0x02E1329EL, 0xAF664FD1L, 0xCAD18115L, - 0x6B2395E0L, 0x333E92E1L, 0x3B240B62L, 0xEEBEB922L, - 0x85B2A20EL, 0xE6BA0D99L, 0xDE720C8CL, 0x2DA2F728L, - 0xD0127845L, 0x95B794FDL, 0x647D0862L, 0xE7CCF5F0L, - 0x5449A36FL, 0x877D48FAL, 0xC39DFD27L, 0xF33E8D1EL, - 0x0A476341L, 0x992EFF74L, 0x3A6F6EABL, 0xF4F8FD37L, - 0xA812DC60L, 0xA1EBDDF8L, 0x991BE14CL, 0xDB6E6B0DL, - 0xC67B5510L, 0x6D672C37L, 0x2765D43BL, 0xDCD0E804L, - 0xF1290DC7L, 0xCC00FFA3L, 0xB5390F92L, 0x690FED0BL, - 0x667B9FFBL, 0xCEDB7D9CL, 0xA091CF0BL, 0xD9155EA3L, - 0xBB132F88L, 0x515BAD24L, 0x7B9479BFL, 0x763BD6EBL, - 0x37392EB3L, 0xCC115979L, 0x8026E297L, 0xF42E312DL, - 0x6842ADA7L, 0xC66A2B3BL, 0x12754CCCL, 0x782EF11CL, - 0x6A124237L, 0xB79251E7L, 0x06A1BBE6L, 0x4BFB6350L, - 0x1A6B1018L, 0x11CAEDFAL, 0x3D25BDD8L, 0xE2E1C3C9L, - 0x44421659L, 0x0A121386L, 0xD90CEC6EL, 0xD5ABEA2AL, - 0x64AF674EL, 0xDA86A85FL, 0xBEBFE988L, 0x64E4C3FEL, - 0x9DBC8057L, 0xF0F7C086L, 0x60787BF8L, 0x6003604DL, - 0xD1FD8346L, 0xF6381FB0L, 0x7745AE04L, 0xD736FCCCL, - 0x83426B33L, 0xF01EAB71L, 0xB0804187L, 0x3C005E5FL, - 0x77A057BEL, 0xBDE8AE24L, 0x55464299L, 0xBF582E61L, - 0x4E58F48FL, 0xF2DDFDA2L, 0xF474EF38L, 0x8789BDC2L, - 0x5366F9C3L, 0xC8B38E74L, 0xB475F255L, 0x46FCD9B9L, - 0x7AEB2661L, 0x8B1DDF84L, 0x846A0E79L, 0x915F95E2L, - 0x466E598EL, 0x20B45770L, 0x8CD55591L, 0xC902DE4CL, - 0xB90BACE1L, 0xBB8205D0L, 0x11A86248L, 0x7574A99EL, - 0xB77F19B6L, 0xE0A9DC09L, 0x662D09A1L, 0xC4324633L, - 0xE85A1F02L, 0x09F0BE8CL, 0x4A99A025L, 0x1D6EFE10L, - 0x1AB93D1DL, 0x0BA5A4DFL, 0xA186F20FL, 0x2868F169L, - 0xDCB7DA83L, 0x573906FEL, 0xA1E2CE9BL, 0x4FCD7F52L, - 0x50115E01L, 0xA70683FAL, 0xA002B5C4L, 0x0DE6D027L, - 0x9AF88C27L, 0x773F8641L, 0xC3604C06L, 0x61A806B5L, - 0xF0177A28L, 0xC0F586E0L, 0x006058AAL, 0x30DC7D62L, - 0x11E69ED7L, 0x2338EA63L, 0x53C2DD94L, 0xC2C21634L, - 0xBBCBEE56L, 0x90BCB6DEL, 0xEBFC7DA1L, 0xCE591D76L, - 0x6F05E409L, 0x4B7C0188L, 0x39720A3DL, 0x7C927C24L, - 0x86E3725FL, 0x724D9DB9L, 0x1AC15BB4L, 0xD39EB8FCL, - 0xED545578L, 0x08FCA5B5L, 0xD83D7CD3L, 0x4DAD0FC4L, - 0x1E50EF5EL, 0xB161E6F8L, 0xA28514D9L, 0x6C51133CL, - 0x6FD5C7E7L, 0x56E14EC4L, 0x362ABFCEL, 0xDDC6C837L, - 0xD79A3234L, 0x92638212L, 0x670EFA8EL, 0x406000E0L }, - { 0x3A39CE37L, 0xD3FAF5CFL, 0xABC27737L, 0x5AC52D1BL, - 0x5CB0679EL, 0x4FA33742L, 0xD3822740L, 0x99BC9BBEL, - 0xD5118E9DL, 0xBF0F7315L, 0xD62D1C7EL, 0xC700C47BL, - 0xB78C1B6BL, 0x21A19045L, 0xB26EB1BEL, 0x6A366EB4L, - 0x5748AB2FL, 0xBC946E79L, 0xC6A376D2L, 0x6549C2C8L, - 0x530FF8EEL, 0x468DDE7DL, 0xD5730A1DL, 0x4CD04DC6L, - 0x2939BBDBL, 0xA9BA4650L, 0xAC9526E8L, 0xBE5EE304L, - 0xA1FAD5F0L, 0x6A2D519AL, 0x63EF8CE2L, 0x9A86EE22L, - 0xC089C2B8L, 0x43242EF6L, 0xA51E03AAL, 0x9CF2D0A4L, - 0x83C061BAL, 0x9BE96A4DL, 0x8FE51550L, 0xBA645BD6L, - 0x2826A2F9L, 0xA73A3AE1L, 0x4BA99586L, 0xEF5562E9L, - 0xC72FEFD3L, 0xF752F7DAL, 0x3F046F69L, 0x77FA0A59L, - 0x80E4A915L, 0x87B08601L, 0x9B09E6ADL, 0x3B3EE593L, - 0xE990FD5AL, 0x9E34D797L, 0x2CF0B7D9L, 0x022B8B51L, - 0x96D5AC3AL, 0x017DA67DL, 0xD1CF3ED6L, 0x7C7D2D28L, - 0x1F9F25CFL, 0xADF2B89BL, 0x5AD6B472L, 0x5A88F54CL, - 0xE029AC71L, 0xE019A5E6L, 0x47B0ACFDL, 0xED93FA9BL, - 0xE8D3C48DL, 0x283B57CCL, 0xF8D56629L, 0x79132E28L, - 0x785F0191L, 0xED756055L, 0xF7960E44L, 0xE3D35E8CL, - 0x15056DD4L, 0x88F46DBAL, 0x03A16125L, 0x0564F0BDL, - 0xC3EB9E15L, 0x3C9057A2L, 0x97271AECL, 0xA93A072AL, - 0x1B3F6D9BL, 0x1E6321F5L, 0xF59C66FBL, 0x26DCF319L, - 0x7533D928L, 0xB155FDF5L, 0x03563482L, 0x8ABA3CBBL, - 0x28517711L, 0xC20AD9F8L, 0xABCC5167L, 0xCCAD925FL, - 0x4DE81751L, 0x3830DC8EL, 0x379D5862L, 0x9320F991L, - 0xEA7A90C2L, 0xFB3E7BCEL, 0x5121CE64L, 0x774FBE32L, - 0xA8B6E37EL, 0xC3293D46L, 0x48DE5369L, 0x6413E680L, - 0xA2AE0810L, 0xDD6DB224L, 0x69852DFDL, 0x09072166L, - 0xB39A460AL, 0x6445C0DDL, 0x586CDECFL, 0x1C20C8AEL, - 0x5BBEF7DDL, 0x1B588D40L, 0xCCD2017FL, 0x6BB4E3BBL, - 0xDDA26A7EL, 0x3A59FF45L, 0x3E350A44L, 0xBCB4CDD5L, - 0x72EACEA8L, 0xFA6484BBL, 0x8D6612AEL, 0xBF3C6F47L, - 0xD29BE463L, 0x542F5D9EL, 0xAEC2771BL, 0xF64E6370L, - 0x740E0D8DL, 0xE75B1357L, 0xF8721671L, 0xAF537D5DL, - 0x4040CB08L, 0x4EB4E2CCL, 0x34D2466AL, 0x0115AF84L, - 0xE1B00428L, 0x95983A1DL, 0x06B89FB4L, 0xCE6EA048L, - 0x6F3F3B82L, 0x3520AB82L, 0x011A1D4BL, 0x277227F8L, - 0x611560B1L, 0xE7933FDCL, 0xBB3A792BL, 0x344525BDL, - 0xA08839E1L, 0x51CE794BL, 0x2F32C9B7L, 0xA01FBAC9L, - 0xE01CC87EL, 0xBCC7D1F6L, 0xCF0111C3L, 0xA1E8AAC7L, - 0x1A908749L, 0xD44FBD9AL, 0xD0DADECBL, 0xD50ADA38L, - 0x0339C32AL, 0xC6913667L, 0x8DF9317CL, 0xE0B12B4FL, - 0xF79E59B7L, 0x43F5BB3AL, 0xF2D519FFL, 0x27D9459CL, - 0xBF97222CL, 0x15E6FC2AL, 0x0F91FC71L, 0x9B941525L, - 0xFAE59361L, 0xCEB69CEBL, 0xC2A86459L, 0x12BAA8D1L, - 0xB6C1075EL, 0xE3056A0CL, 0x10D25065L, 0xCB03A442L, - 0xE0EC6E0EL, 0x1698DB3BL, 0x4C98A0BEL, 0x3278E964L, - 0x9F1F9532L, 0xE0D392DFL, 0xD3A0342BL, 0x8971F21EL, - 0x1B0A7441L, 0x4BA3348CL, 0xC5BE7120L, 0xC37632D8L, - 0xDF359F8DL, 0x9B992F2EL, 0xE60B6F47L, 0x0FE3F11DL, - 0xE54CDA54L, 0x1EDAD891L, 0xCE6279CFL, 0xCD3E7E6FL, - 0x1618B166L, 0xFD2C1D05L, 0x848FD2C5L, 0xF6FB2299L, - 0xF523F357L, 0xA6327623L, 0x93A83531L, 0x56CCCD02L, - 0xACF08162L, 0x5A75EBB5L, 0x6E163697L, 0x88D273CCL, - 0xDE966292L, 0x81B949D0L, 0x4C50901BL, 0x71C65614L, - 0xE6C6C7BDL, 0x327A140AL, 0x45E1D006L, 0xC3F27B9AL, - 0xC9AA53FDL, 0x62A80F00L, 0xBB25BFE2L, 0x35BDD2F6L, - 0x71126905L, 0xB2040222L, 0xB6CBCF7CL, 0xCD769C2BL, - 0x53113EC0L, 0x1640E3D3L, 0x38ABBD60L, 0x2547ADF0L, - 0xBA38209CL, 0xF746CE76L, 0x77AFA1C5L, 0x20756060L, - 0x85CBFE4EL, 0x8AE88DD8L, 0x7AAAF9B0L, 0x4CF9AA7EL, - 0x1948C25CL, 0x02FB8A8CL, 0x01C36AE4L, 0xD6EBE1F9L, - 0x90D4F869L, 0xA65CDEA0L, 0x3F09252DL, 0xC208E69FL, - 0xB74E6132L, 0xCE77E25BL, 0x578FDFE3L, 0x3AC372E6L } -}; - -#endif /* !MBEDTLS_BLOWFISH_ALT */ -#endif /* MBEDTLS_BLOWFISH_C */ diff --git a/vendor/mbedtls/include/mbedtls/bn_mul.h b/vendor/mbedtls/library/bn_mul.h similarity index 75% rename from vendor/mbedtls/include/mbedtls/bn_mul.h rename to vendor/mbedtls/library/bn_mul.h index 6414e54291..0738469db4 100644 --- a/vendor/mbedtls/include/mbedtls/bn_mul.h +++ b/vendor/mbedtls/library/bn_mul.h @@ -5,19 +5,7 @@ */ /* * Copyright The Mbed TLS Contributors - * SPDX-License-Identifier: Apache-2.0 - * - * Licensed under the Apache License, Version 2.0 (the "License"); you may - * not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT - * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. + * SPDX-License-Identifier: Apache-2.0 OR GPL-2.0-or-later */ /* * Multiply source vector [s] with b, add result @@ -36,11 +24,7 @@ #ifndef MBEDTLS_BN_MUL_H #define MBEDTLS_BN_MUL_H -#if !defined(MBEDTLS_CONFIG_FILE) -#include "mbedtls/config.h" -#else -#include MBEDTLS_CONFIG_FILE -#endif +#include "mbedtls/build_info.h" #include "mbedtls/bignum.h" @@ -87,10 +71,6 @@ /* *INDENT-OFF* */ #if defined(MBEDTLS_HAVE_ASM) -#ifndef asm -#define asm __asm -#endif - /* armcc5 --gnu defines __GNUC__ but doesn't support GNU's extended asm */ #if defined(__GNUC__) && \ ( !defined(__ARMCC_VERSION) || __ARMCC_VERSION >= 6000000 ) @@ -119,7 +99,8 @@ */ #if defined(__i386__) && defined(__OPTIMIZE__) && !defined(MULADDC_CANNOT_USE_EBX) -#define MULADDC_INIT \ +#define MULADDC_X1_INIT \ + { mbedtls_mpi_uint t; \ asm( \ "movl %%ebx, %0 \n\t" \ "movl %5, %%esi \n\t" \ @@ -127,7 +108,7 @@ "movl %7, %%ecx \n\t" \ "movl %8, %%ebx \n\t" -#define MULADDC_CORE \ +#define MULADDC_X1_CORE \ "lodsl \n\t" \ "mull %%ebx \n\t" \ "addl %%ecx, %%eax \n\t" \ @@ -137,9 +118,21 @@ "movl %%edx, %%ecx \n\t" \ "stosl \n\t" +#define MULADDC_X1_STOP \ + "movl %4, %%ebx \n\t" \ + "movl %%ecx, %1 \n\t" \ + "movl %%edi, %2 \n\t" \ + "movl %%esi, %3 \n\t" \ + : "=m" (t), "=m" (c), "=m" (d), "=m" (s) \ + : "m" (t), "m" (s), "m" (d), "m" (c), "m" (b) \ + : "eax", "ebx", "ecx", "edx", "esi", "edi" \ + ); } + #if defined(MBEDTLS_HAVE_SSE2) -#define MULADDC_HUIT \ +#define MULADDC_X8_INIT MULADDC_X1_INIT + +#define MULADDC_X8_CORE \ "movd %%ecx, %%mm1 \n\t" \ "movd %%ebx, %%mm0 \n\t" \ "movd (%%edi), %%mm3 \n\t" \ @@ -202,7 +195,7 @@ "psrlq $32, %%mm1 \n\t" \ "movd %%mm1, %%ecx \n\t" -#define MULADDC_STOP \ +#define MULADDC_X8_STOP \ "emms \n\t" \ "movl %4, %%ebx \n\t" \ "movl %%ecx, %1 \n\t" \ @@ -211,29 +204,19 @@ : "=m" (t), "=m" (c), "=m" (d), "=m" (s) \ : "m" (t), "m" (s), "m" (d), "m" (c), "m" (b) \ : "eax", "ebx", "ecx", "edx", "esi", "edi" \ - ); + ); } \ -#else - -#define MULADDC_STOP \ - "movl %4, %%ebx \n\t" \ - "movl %%ecx, %1 \n\t" \ - "movl %%edi, %2 \n\t" \ - "movl %%esi, %3 \n\t" \ - : "=m" (t), "=m" (c), "=m" (d), "=m" (s) \ - : "m" (t), "m" (s), "m" (d), "m" (c), "m" (b) \ - : "eax", "ebx", "ecx", "edx", "esi", "edi" \ - ); #endif /* SSE2 */ + #endif /* i386 */ #if defined(__amd64__) || defined (__x86_64__) -#define MULADDC_INIT \ +#define MULADDC_X1_INIT \ asm( \ "xorq %%r8, %%r8\n" -#define MULADDC_CORE \ +#define MULADDC_X1_CORE \ "movq (%%rsi), %%rax\n" \ "mulq %%rbx\n" \ "addq $8, %%rsi\n" \ @@ -245,7 +228,7 @@ "adcq %%rdx, %%rcx\n" \ "addq $8, %%rdi\n" -#define MULADDC_STOP \ +#define MULADDC_X1_STOP \ : "+c" (c), "+D" (d), "+S" (s), "+m" (*(uint64_t (*)[16]) d) \ : "b" (b), "m" (*(const uint64_t (*)[16]) s) \ : "rax", "rdx", "r8" \ @@ -253,33 +236,45 @@ #endif /* AMD64 */ -#if defined(__aarch64__) +// The following assembly code assumes that a pointer will fit in a 64-bit register +// (including ILP32 __aarch64__ ABIs such as on watchOS, hence the 2^32 - 1) +#if defined(__aarch64__) && (UINTPTR_MAX == 0xfffffffful || UINTPTR_MAX == 0xfffffffffffffffful) -#define MULADDC_INIT \ - asm( +/* + * There are some issues around different compilers requiring different constraint + * syntax for updating pointers from assembly code (see notes for + * MBEDTLS_ASM_AARCH64_PTR_CONSTRAINT in common.h), especially on aarch64_32 (aka ILP32). + * + * For this reason we cast the pointers to/from uintptr_t here. + */ +#define MULADDC_X1_INIT \ + do { uintptr_t muladdc_d = (uintptr_t) d, muladdc_s = (uintptr_t) s; asm( -#define MULADDC_CORE \ - "ldr x4, [%2], #8 \n\t" \ - "ldr x5, [%1] \n\t" \ +#define MULADDC_X1_CORE \ + "ldr x4, [%x2], #8 \n\t" \ + "ldr x5, [%x1] \n\t" \ "mul x6, x4, %4 \n\t" \ "umulh x7, x4, %4 \n\t" \ "adds x5, x5, x6 \n\t" \ "adc x7, x7, xzr \n\t" \ "adds x5, x5, %0 \n\t" \ "adc %0, x7, xzr \n\t" \ - "str x5, [%1], #8 \n\t" + "str x5, [%x1], #8 \n\t" -#define MULADDC_STOP \ - : "+r" (c), "+r" (d), "+r" (s), "+m" (*(uint64_t (*)[16]) d) \ +#define MULADDC_X1_STOP \ + : "+r" (c), \ + "+r" (muladdc_d), \ + "+r" (muladdc_s), \ + "+m" (*(uint64_t (*)[16]) d) \ : "r" (b), "m" (*(const uint64_t (*)[16]) s) \ : "x4", "x5", "x6", "x7", "cc" \ - ); + ); d = (mbedtls_mpi_uint *)muladdc_d; s = (mbedtls_mpi_uint *)muladdc_s; } while (0); #endif /* Aarch64 */ #if defined(__mc68020__) || defined(__mcpu32__) -#define MULADDC_INIT \ +#define MULADDC_X1_INIT \ asm( \ "movl %3, %%a2 \n\t" \ "movl %4, %%a3 \n\t" \ @@ -287,7 +282,7 @@ "movl %6, %%d2 \n\t" \ "moveq #0, %%d0 \n\t" -#define MULADDC_CORE \ +#define MULADDC_X1_CORE \ "movel %%a2@+, %%d1 \n\t" \ "mulul %%d2, %%d4:%%d1 \n\t" \ "addl %%d3, %%d1 \n\t" \ @@ -296,7 +291,7 @@ "addl %%d1, %%a3@+ \n\t" \ "addxl %%d4, %%d3 \n\t" -#define MULADDC_STOP \ +#define MULADDC_X1_STOP \ "movl %%d3, %0 \n\t" \ "movl %%a3, %1 \n\t" \ "movl %%a2, %2 \n\t" \ @@ -305,7 +300,9 @@ : "d0", "d1", "d2", "d3", "d4", "a2", "a3" \ ); -#define MULADDC_HUIT \ +#define MULADDC_X8_INIT MULADDC_X1_INIT + +#define MULADDC_X8_CORE \ "movel %%a2@+, %%d1 \n\t" \ "mulul %%d2, %%d4:%%d1 \n\t" \ "addxl %%d3, %%d1 \n\t" \ @@ -348,13 +345,15 @@ "addl %%d1, %%a3@+ \n\t" \ "addxl %%d0, %%d3 \n\t" +#define MULADDC_X8_STOP MULADDC_X1_STOP + #endif /* MC68000 */ #if defined(__powerpc64__) || defined(__ppc64__) #if defined(__MACH__) && defined(__APPLE__) -#define MULADDC_INIT \ +#define MULADDC_X1_INIT \ asm( \ "ld r3, %3 \n\t" \ "ld r4, %4 \n\t" \ @@ -364,7 +363,7 @@ "addi r4, r4, -8 \n\t" \ "addic r5, r5, 0 \n\t" -#define MULADDC_CORE \ +#define MULADDC_X1_CORE \ "ldu r7, 8(r3) \n\t" \ "mulld r8, r7, r6 \n\t" \ "mulhdu r9, r7, r6 \n\t" \ @@ -374,7 +373,7 @@ "addc r8, r8, r7 \n\t" \ "stdu r8, 8(r4) \n\t" -#define MULADDC_STOP \ +#define MULADDC_X1_STOP \ "addze r5, r5 \n\t" \ "addi r4, r4, 8 \n\t" \ "addi r3, r3, 8 \n\t" \ @@ -389,7 +388,7 @@ #else /* __MACH__ && __APPLE__ */ -#define MULADDC_INIT \ +#define MULADDC_X1_INIT \ asm( \ "ld %%r3, %3 \n\t" \ "ld %%r4, %4 \n\t" \ @@ -399,7 +398,7 @@ "addi %%r4, %%r4, -8 \n\t" \ "addic %%r5, %%r5, 0 \n\t" -#define MULADDC_CORE \ +#define MULADDC_X1_CORE \ "ldu %%r7, 8(%%r3) \n\t" \ "mulld %%r8, %%r7, %%r6 \n\t" \ "mulhdu %%r9, %%r7, %%r6 \n\t" \ @@ -409,7 +408,7 @@ "addc %%r8, %%r8, %%r7 \n\t" \ "stdu %%r8, 8(%%r4) \n\t" -#define MULADDC_STOP \ +#define MULADDC_X1_STOP \ "addze %%r5, %%r5 \n\t" \ "addi %%r4, %%r4, 8 \n\t" \ "addi %%r3, %%r3, 8 \n\t" \ @@ -427,7 +426,7 @@ #if defined(__MACH__) && defined(__APPLE__) -#define MULADDC_INIT \ +#define MULADDC_X1_INIT \ asm( \ "lwz r3, %3 \n\t" \ "lwz r4, %4 \n\t" \ @@ -437,7 +436,7 @@ "addi r4, r4, -4 \n\t" \ "addic r5, r5, 0 \n\t" -#define MULADDC_CORE \ +#define MULADDC_X1_CORE \ "lwzu r7, 4(r3) \n\t" \ "mullw r8, r7, r6 \n\t" \ "mulhwu r9, r7, r6 \n\t" \ @@ -447,7 +446,7 @@ "addc r8, r8, r7 \n\t" \ "stwu r8, 4(r4) \n\t" -#define MULADDC_STOP \ +#define MULADDC_X1_STOP \ "addze r5, r5 \n\t" \ "addi r4, r4, 4 \n\t" \ "addi r3, r3, 4 \n\t" \ @@ -461,7 +460,7 @@ #else /* __MACH__ && __APPLE__ */ -#define MULADDC_INIT \ +#define MULADDC_X1_INIT \ asm( \ "lwz %%r3, %3 \n\t" \ "lwz %%r4, %4 \n\t" \ @@ -471,7 +470,7 @@ "addi %%r4, %%r4, -4 \n\t" \ "addic %%r5, %%r5, 0 \n\t" -#define MULADDC_CORE \ +#define MULADDC_X1_CORE \ "lwzu %%r7, 4(%%r3) \n\t" \ "mullw %%r8, %%r7, %%r6 \n\t" \ "mulhwu %%r9, %%r7, %%r6 \n\t" \ @@ -481,7 +480,7 @@ "addc %%r8, %%r8, %%r7 \n\t" \ "stwu %%r8, 4(%%r4) \n\t" -#define MULADDC_STOP \ +#define MULADDC_X1_STOP \ "addze %%r5, %%r5 \n\t" \ "addi %%r4, %%r4, 4 \n\t" \ "addi %%r3, %%r3, 4 \n\t" \ @@ -504,14 +503,14 @@ #if 0 && defined(__sparc__) #if defined(__sparc64__) -#define MULADDC_INIT \ +#define MULADDC_X1_INIT \ asm( \ "ldx %3, %%o0 \n\t" \ "ldx %4, %%o1 \n\t" \ "ld %5, %%o2 \n\t" \ "ld %6, %%o3 \n\t" -#define MULADDC_CORE \ +#define MULADDC_X1_CORE \ "ld [%%o0], %%o4 \n\t" \ "inc 4, %%o0 \n\t" \ "ld [%%o1], %%o5 \n\t" \ @@ -524,7 +523,7 @@ "addx %%g1, 0, %%o2 \n\t" \ "inc 4, %%o1 \n\t" - #define MULADDC_STOP \ +#define MULADDC_X1_STOP \ "st %%o2, %0 \n\t" \ "stx %%o1, %1 \n\t" \ "stx %%o0, %2 \n\t" \ @@ -536,14 +535,14 @@ #else /* __sparc64__ */ -#define MULADDC_INIT \ +#define MULADDC_X1_INIT \ asm( \ "ld %3, %%o0 \n\t" \ "ld %4, %%o1 \n\t" \ "ld %5, %%o2 \n\t" \ "ld %6, %%o3 \n\t" -#define MULADDC_CORE \ +#define MULADDC_X1_CORE \ "ld [%%o0], %%o4 \n\t" \ "inc 4, %%o0 \n\t" \ "ld [%%o1], %%o5 \n\t" \ @@ -556,7 +555,7 @@ "addx %%g1, 0, %%o2 \n\t" \ "inc 4, %%o1 \n\t" -#define MULADDC_STOP \ +#define MULADDC_X1_STOP \ "st %%o2, %0 \n\t" \ "st %%o1, %1 \n\t" \ "st %%o0, %2 \n\t" \ @@ -571,7 +570,7 @@ #if defined(__microblaze__) || defined(microblaze) -#define MULADDC_INIT \ +#define MULADDC_X1_INIT \ asm( \ "lwi r3, %3 \n\t" \ "lwi r4, %4 \n\t" \ @@ -592,7 +591,7 @@ "lhui r9, r3, 0 \n\t" #endif -#define MULADDC_CORE \ +#define MULADDC_X1_CORE \ MULADDC_LHUI \ "addi r3, r3, 2 \n\t" \ "mul r10, r9, r6 \n\t" \ @@ -617,7 +616,7 @@ "swi r12, r4, 0 \n\t" \ "addi r4, r4, 4 \n\t" -#define MULADDC_STOP \ +#define MULADDC_X1_STOP \ "swi r5, %0 \n\t" \ "swi r4, %1 \n\t" \ "swi r3, %2 \n\t" \ @@ -631,7 +630,7 @@ #if defined(__tricore__) -#define MULADDC_INIT \ +#define MULADDC_X1_INIT \ asm( \ "ld.a %%a2, %3 \n\t" \ "ld.a %%a3, %4 \n\t" \ @@ -639,7 +638,7 @@ "ld.w %%d1, %6 \n\t" \ "xor %%d5, %%d5 \n\t" -#define MULADDC_CORE \ +#define MULADDC_X1_CORE \ "ld.w %%d0, [%%a2+] \n\t" \ "madd.u %%e2, %%e4, %%d0, %%d1 \n\t" \ "ld.w %%d0, [%%a3] \n\t" \ @@ -648,7 +647,7 @@ "mov %%d4, %%d3 \n\t" \ "st.w [%%a3+], %%d2 \n\t" -#define MULADDC_STOP \ +#define MULADDC_X1_STOP \ "st.w %0, %%d4 \n\t" \ "st.a %1, %%a3 \n\t" \ "st.a %2, %%a2 \n\t" \ @@ -659,6 +658,16 @@ #endif /* TriCore */ +#if defined(__arm__) + +#if defined(__thumb__) && !defined(__thumb2__) +#if defined(MBEDTLS_COMPILER_IS_GCC) +/* + * Thumb 1 ISA. This code path has only been tested successfully on gcc; + * it does not compile on clang or armclang. + */ + +#if !defined(__OPTIMIZE__) && defined(__GNUC__) /* * Note, gcc -O0 by default uses r7 for the frame pointer, so it complains about * our use of r7 below, unless -fomit-frame-pointer is passed. @@ -667,41 +676,39 @@ * x !=0, which we can detect using __OPTIMIZE__ (which is also defined by * clang and armcc5 under the same conditions). * - * So, only use the optimized assembly below for optimized build, which avoids - * the build error and is pretty reasonable anyway. - */ -#if defined(__GNUC__) && !defined(__OPTIMIZE__) -#define MULADDC_CANNOT_USE_R7 -#endif - -#if defined(__arm__) && !defined(MULADDC_CANNOT_USE_R7) - -#if defined(__thumb__) && !defined(__thumb2__) -#if !defined(__ARMCC_VERSION) && !defined(__clang__) \ - && !defined(__llvm__) && !defined(__INTEL_COMPILER) -/* - * Thumb 1 ISA. This code path has only been tested successfully on gcc; - * it does not compile on clang or armclang. - * - * Other compilers which define __GNUC__ may not work. The above macro - * attempts to exclude these untested compilers. + * If gcc needs to use r7, we use r1 as a scratch register and have a few extra + * instructions to preserve/restore it; otherwise, we can use r7 and avoid + * the preserve/restore overhead. */ - -#define MULADDC_INIT \ +#define MULADDC_SCRATCH "RS .req r1 \n\t" +#define MULADDC_PRESERVE_SCRATCH "mov r10, r1 \n\t" +#define MULADDC_RESTORE_SCRATCH "mov r1, r10 \n\t" +#define MULADDC_SCRATCH_CLOBBER "r10" +#else /* !defined(__OPTIMIZE__) && defined(__GNUC__) */ +#define MULADDC_SCRATCH "RS .req r7 \n\t" +#define MULADDC_PRESERVE_SCRATCH "" +#define MULADDC_RESTORE_SCRATCH "" +#define MULADDC_SCRATCH_CLOBBER "r7" +#endif /* !defined(__OPTIMIZE__) && defined(__GNUC__) */ + +#define MULADDC_X1_INIT \ asm( \ + MULADDC_SCRATCH \ "ldr r0, %3 \n\t" \ "ldr r1, %4 \n\t" \ "ldr r2, %5 \n\t" \ "ldr r3, %6 \n\t" \ - "lsr r7, r3, #16 \n\t" \ - "mov r9, r7 \n\t" \ - "lsl r7, r3, #16 \n\t" \ - "lsr r7, r7, #16 \n\t" \ - "mov r8, r7 \n\t" + "lsr r4, r3, #16 \n\t" \ + "mov r9, r4 \n\t" \ + "lsl r4, r3, #16 \n\t" \ + "lsr r4, r4, #16 \n\t" \ + "mov r8, r4 \n\t" \ -#define MULADDC_CORE \ + +#define MULADDC_X1_CORE \ + MULADDC_PRESERVE_SCRATCH \ "ldmia r0!, {r6} \n\t" \ - "lsr r7, r6, #16 \n\t" \ + "lsr RS, r6, #16 \n\t" \ "lsl r6, r6, #16 \n\t" \ "lsr r6, r6, #16 \n\t" \ "mov r4, r8 \n\t" \ @@ -709,12 +716,12 @@ "mov r3, r9 \n\t" \ "mul r6, r3 \n\t" \ "mov r5, r9 \n\t" \ - "mul r5, r7 \n\t" \ + "mul r5, RS \n\t" \ "mov r3, r8 \n\t" \ - "mul r7, r3 \n\t" \ + "mul RS, r3 \n\t" \ "lsr r3, r6, #16 \n\t" \ "add r5, r5, r3 \n\t" \ - "lsr r3, r7, #16 \n\t" \ + "lsr r3, RS, #16 \n\t" \ "add r5, r5, r3 \n\t" \ "add r4, r4, r2 \n\t" \ "mov r2, #0 \n\t" \ @@ -722,86 +729,137 @@ "lsl r3, r6, #16 \n\t" \ "add r4, r4, r3 \n\t" \ "adc r5, r2 \n\t" \ - "lsl r3, r7, #16 \n\t" \ + "lsl r3, RS, #16 \n\t" \ "add r4, r4, r3 \n\t" \ "adc r5, r2 \n\t" \ + MULADDC_RESTORE_SCRATCH \ "ldr r3, [r1] \n\t" \ "add r4, r4, r3 \n\t" \ "adc r2, r5 \n\t" \ "stmia r1!, {r4} \n\t" -#define MULADDC_STOP \ +#define MULADDC_X1_STOP \ "str r2, %0 \n\t" \ "str r1, %1 \n\t" \ "str r0, %2 \n\t" \ : "=m" (c), "=m" (d), "=m" (s) \ : "m" (s), "m" (d), "m" (c), "m" (b) \ : "r0", "r1", "r2", "r3", "r4", "r5", \ - "r6", "r7", "r8", "r9", "cc" \ + "r6", MULADDC_SCRATCH_CLOBBER, "r8", "r9", "cc" \ ); - -#endif /* Compiler is gcc */ +#endif /* !defined(__ARMCC_VERSION) && !defined(__clang__) */ #elif (__ARM_ARCH >= 6) && \ defined (__ARM_FEATURE_DSP) && (__ARM_FEATURE_DSP == 1) +/* Armv6-M (or later) with DSP Instruction Set Extensions. + * Requires support for either Thumb 2 or Arm ISA. + */ -#define MULADDC_INIT \ - asm( - -#define MULADDC_CORE \ - "ldr r0, [%0], #4 \n\t" \ - "ldr r1, [%1] \n\t" \ - "umaal r1, %2, %3, r0 \n\t" \ - "str r1, [%1], #4 \n\t" - -#define MULADDC_STOP \ - : "=r" (s), "=r" (d), "=r" (c) \ - : "r" (b), "0" (s), "1" (d), "2" (c) \ - : "r0", "r1", "memory" \ - ); - -#else - -#define MULADDC_INIT \ +#define MULADDC_X1_INIT \ + { \ + mbedtls_mpi_uint tmp_a, tmp_b; \ + asm volatile ( + +#define MULADDC_X1_CORE \ + ".p2align 2 \n\t" \ + "ldr %[a], [%[in]], #4 \n\t" \ + "ldr %[b], [%[acc]] \n\t" \ + "umaal %[b], %[carry], %[scalar], %[a] \n\t" \ + "str %[b], [%[acc]], #4 \n\t" + +#define MULADDC_X1_STOP \ + : [a] "=&r" (tmp_a), \ + [b] "=&r" (tmp_b), \ + [in] "+r" (s), \ + [acc] "+r" (d), \ + [carry] "+l" (c) \ + : [scalar] "r" (b) \ + : "memory" \ + ); \ + } + +#define MULADDC_X2_INIT \ + { \ + mbedtls_mpi_uint tmp_a0, tmp_b0; \ + mbedtls_mpi_uint tmp_a1, tmp_b1; \ + asm volatile ( + + /* - Make sure loop is 4-byte aligned to avoid stalls + * upon repeated non-word aligned instructions in + * some microarchitectures. + * - Don't use ldm with post-increment or back-to-back + * loads with post-increment and same address register + * to avoid stalls on some microarchitectures. + * - Bunch loads and stores to reduce latency on some + * microarchitectures. E.g., on Cortex-M4, the first + * in a series of load/store operations has latency + * 2 cycles, while subsequent loads/stores are single-cycle. */ +#define MULADDC_X2_CORE \ + ".p2align 2 \n\t" \ + "ldr %[a0], [%[in]], #+8 \n\t" \ + "ldr %[b0], [%[acc]], #+8 \n\t" \ + "ldr %[a1], [%[in], #-4] \n\t" \ + "ldr %[b1], [%[acc], #-4] \n\t" \ + "umaal %[b0], %[carry], %[scalar], %[a0] \n\t" \ + "umaal %[b1], %[carry], %[scalar], %[a1] \n\t" \ + "str %[b0], [%[acc], #-8] \n\t" \ + "str %[b1], [%[acc], #-4] \n\t" + +#define MULADDC_X2_STOP \ + : [a0] "=&r" (tmp_a0), \ + [b0] "=&r" (tmp_b0), \ + [a1] "=&r" (tmp_a1), \ + [b1] "=&r" (tmp_b1), \ + [in] "+r" (s), \ + [acc] "+r" (d), \ + [carry] "+l" (c) \ + : [scalar] "r" (b) \ + : "memory" \ + ); \ + } + +#else /* Thumb 2 or Arm ISA, without DSP extensions */ + +#define MULADDC_X1_INIT \ asm( \ "ldr r0, %3 \n\t" \ "ldr r1, %4 \n\t" \ "ldr r2, %5 \n\t" \ "ldr r3, %6 \n\t" -#define MULADDC_CORE \ +#define MULADDC_X1_CORE \ "ldr r4, [r0], #4 \n\t" \ "mov r5, #0 \n\t" \ "ldr r6, [r1] \n\t" \ "umlal r2, r5, r3, r4 \n\t" \ - "adds r7, r6, r2 \n\t" \ + "adds r4, r6, r2 \n\t" \ "adc r2, r5, #0 \n\t" \ - "str r7, [r1], #4 \n\t" + "str r4, [r1], #4 \n\t" -#define MULADDC_STOP \ +#define MULADDC_X1_STOP \ "str r2, %0 \n\t" \ "str r1, %1 \n\t" \ "str r0, %2 \n\t" \ : "=m" (c), "=m" (d), "=m" (s) \ : "m" (s), "m" (d), "m" (c), "m" (b) \ : "r0", "r1", "r2", "r3", "r4", "r5", \ - "r6", "r7", "cc" \ + "r6", "cc" \ ); -#endif /* Thumb */ +#endif /* ISA codepath selection */ -#endif /* ARMv3 */ +#endif /* defined(__arm__) */ #if defined(__alpha__) -#define MULADDC_INIT \ +#define MULADDC_X1_INIT \ asm( \ "ldq $1, %3 \n\t" \ "ldq $2, %4 \n\t" \ "ldq $3, %5 \n\t" \ "ldq $4, %6 \n\t" -#define MULADDC_CORE \ +#define MULADDC_X1_CORE \ "ldq $6, 0($1) \n\t" \ "addq $1, 8, $1 \n\t" \ "mulq $6, $4, $7 \n\t" \ @@ -816,7 +874,7 @@ "addq $6, $3, $3 \n\t" \ "addq $5, $3, $3 \n\t" -#define MULADDC_STOP \ +#define MULADDC_X1_STOP \ "stq $3, %0 \n\t" \ "stq $2, %1 \n\t" \ "stq $1, %2 \n\t" \ @@ -828,14 +886,14 @@ #if defined(__mips__) && !defined(__mips64) -#define MULADDC_INIT \ +#define MULADDC_X1_INIT \ asm( \ "lw $10, %3 \n\t" \ "lw $11, %4 \n\t" \ "lw $12, %5 \n\t" \ "lw $13, %6 \n\t" -#define MULADDC_CORE \ +#define MULADDC_X1_CORE \ "lw $14, 0($10) \n\t" \ "multu $13, $14 \n\t" \ "addi $10, $10, 4 \n\t" \ @@ -851,7 +909,7 @@ "addu $12, $12, $14 \n\t" \ "addi $11, $11, 4 \n\t" -#define MULADDC_STOP \ +#define MULADDC_X1_STOP \ "sw $12, %0 \n\t" \ "sw $11, %1 \n\t" \ "sw $10, %2 \n\t" \ @@ -865,13 +923,13 @@ #if (defined(_MSC_VER) && defined(_M_IX86)) || defined(__WATCOMC__) -#define MULADDC_INIT \ +#define MULADDC_X1_INIT \ __asm mov esi, s \ __asm mov edi, d \ __asm mov ecx, c \ __asm mov ebx, b -#define MULADDC_CORE \ +#define MULADDC_X1_CORE \ __asm lodsd \ __asm mul ebx \ __asm add eax, ecx \ @@ -881,11 +939,18 @@ __asm mov ecx, edx \ __asm stosd +#define MULADDC_X1_STOP \ + __asm mov c, ecx \ + __asm mov d, edi \ + __asm mov s, esi + #if defined(MBEDTLS_HAVE_SSE2) #define EMIT __asm _emit -#define MULADDC_HUIT \ +#define MULADDC_X8_INIT MULADDC_X1_INIT + +#define MULADDC_X8_CORE \ EMIT 0x0F EMIT 0x6E EMIT 0xC9 \ EMIT 0x0F EMIT 0x6E EMIT 0xC3 \ EMIT 0x0F EMIT 0x6E EMIT 0x1F \ @@ -948,33 +1013,26 @@ EMIT 0x0F EMIT 0x73 EMIT 0xD1 EMIT 0x20 \ EMIT 0x0F EMIT 0x7E EMIT 0xC9 -#define MULADDC_STOP \ +#define MULADDC_X8_STOP \ EMIT 0x0F EMIT 0x77 \ __asm mov c, ecx \ __asm mov d, edi \ - __asm mov s, esi \ - -#else - -#define MULADDC_STOP \ - __asm mov c, ecx \ - __asm mov d, edi \ - __asm mov s, esi \ + __asm mov s, esi #endif /* SSE2 */ #endif /* MSVC */ #endif /* MBEDTLS_HAVE_ASM */ -#if !defined(MULADDC_CORE) +#if !defined(MULADDC_X1_CORE) #if defined(MBEDTLS_HAVE_UDBL) -#define MULADDC_INIT \ +#define MULADDC_X1_INIT \ { \ mbedtls_t_udbl r; \ mbedtls_mpi_uint r0, r1; -#define MULADDC_CORE \ +#define MULADDC_X1_CORE \ r = *(s++) * (mbedtls_t_udbl) b; \ r0 = (mbedtls_mpi_uint) r; \ r1 = (mbedtls_mpi_uint)( r >> biL ); \ @@ -982,18 +1040,19 @@ r0 += *d; r1 += (r0 < *d); \ c = r1; *(d++) = r0; -#define MULADDC_STOP \ +#define MULADDC_X1_STOP \ } -#else -#define MULADDC_INIT \ +#else /* MBEDTLS_HAVE_UDBL */ + +#define MULADDC_X1_INIT \ { \ mbedtls_mpi_uint s0, s1, b0, b1; \ mbedtls_mpi_uint r0, r1, rx, ry; \ b0 = ( b << biH ) >> biH; \ b1 = ( b >> biH ); -#define MULADDC_CORE \ +#define MULADDC_X1_CORE \ s0 = ( *s << biH ) >> biH; \ s1 = ( *s >> biH ); s++; \ rx = s0 * b1; r0 = s0 * b0; \ @@ -1007,11 +1066,29 @@ r0 += *d; r1 += (r0 < *d); \ c = r1; *(d++) = r0; -#define MULADDC_STOP \ +#define MULADDC_X1_STOP \ } -#endif /* C (generic) */ #endif /* C (longlong) */ +#endif /* C (generic) */ + +#if !defined(MULADDC_X2_CORE) +#define MULADDC_X2_INIT MULADDC_X1_INIT +#define MULADDC_X2_STOP MULADDC_X1_STOP +#define MULADDC_X2_CORE MULADDC_X1_CORE MULADDC_X1_CORE +#endif /* MULADDC_X2_CORE */ + +#if !defined(MULADDC_X4_CORE) +#define MULADDC_X4_INIT MULADDC_X2_INIT +#define MULADDC_X4_STOP MULADDC_X2_STOP +#define MULADDC_X4_CORE MULADDC_X2_CORE MULADDC_X2_CORE +#endif /* MULADDC_X4_CORE */ + +#if !defined(MULADDC_X8_CORE) +#define MULADDC_X8_INIT MULADDC_X4_INIT +#define MULADDC_X8_STOP MULADDC_X4_STOP +#define MULADDC_X8_CORE MULADDC_X4_CORE MULADDC_X4_CORE +#endif /* MULADDC_X8_CORE */ /* *INDENT-ON* */ #endif /* bn_mul.h */ diff --git a/vendor/mbedtls/library/camellia.c b/vendor/mbedtls/library/camellia.c index ce034d74fb..b1c0a08ca2 100644 --- a/vendor/mbedtls/library/camellia.c +++ b/vendor/mbedtls/library/camellia.c @@ -2,19 +2,7 @@ * Camellia implementation * * Copyright The Mbed TLS Contributors - * SPDX-License-Identifier: Apache-2.0 - * - * Licensed under the Apache License, Version 2.0 (the "License"); you may - * not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT - * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. + * SPDX-License-Identifier: Apache-2.0 OR GPL-2.0-or-later */ /* * The Camellia block cipher was designed by NTT and Mitsubishi Electric @@ -36,12 +24,6 @@ #if !defined(MBEDTLS_CAMELLIA_ALT) -/* Parameter validation macros */ -#define CAMELLIA_VALIDATE_RET(cond) \ - MBEDTLS_INTERNAL_VALIDATE_RET(cond, MBEDTLS_ERR_CAMELLIA_BAD_INPUT_DATA) -#define CAMELLIA_VALIDATE(cond) \ - MBEDTLS_INTERNAL_VALIDATE(cond) - static const unsigned char SIGMA_CHARS[6][8] = { { 0xa0, 0x9e, 0x66, 0x7f, 0x3b, 0xcc, 0x90, 0x8b }, @@ -291,7 +273,6 @@ static void camellia_feistel(const uint32_t x[2], const uint32_t k[2], void mbedtls_camellia_init(mbedtls_camellia_context *ctx) { - CAMELLIA_VALIDATE(ctx != NULL); memset(ctx, 0, sizeof(mbedtls_camellia_context)); } @@ -319,9 +300,6 @@ int mbedtls_camellia_setkey_enc(mbedtls_camellia_context *ctx, uint32_t KC[16]; uint32_t TK[20]; - CAMELLIA_VALIDATE_RET(ctx != NULL); - CAMELLIA_VALIDATE_RET(key != NULL); - RK = ctx->rk; memset(t, 0, 64); @@ -421,6 +399,7 @@ int mbedtls_camellia_setkey_enc(mbedtls_camellia_context *ctx, /* * Camellia key schedule (decryption) */ +#if !defined(MBEDTLS_BLOCK_CIPHER_NO_DECRYPT) int mbedtls_camellia_setkey_dec(mbedtls_camellia_context *ctx, const unsigned char *key, unsigned int keybits) @@ -430,8 +409,6 @@ int mbedtls_camellia_setkey_dec(mbedtls_camellia_context *ctx, mbedtls_camellia_context cty; uint32_t *RK; uint32_t *SK; - CAMELLIA_VALIDATE_RET(ctx != NULL); - CAMELLIA_VALIDATE_RET(key != NULL); mbedtls_camellia_init(&cty); @@ -468,6 +445,7 @@ int mbedtls_camellia_setkey_dec(mbedtls_camellia_context *ctx, return ret; } +#endif /* !MBEDTLS_BLOCK_CIPHER_NO_DECRYPT */ /* * Camellia-ECB block encryption/decryption @@ -479,11 +457,9 @@ int mbedtls_camellia_crypt_ecb(mbedtls_camellia_context *ctx, { int NR; uint32_t *RK, X[4]; - CAMELLIA_VALIDATE_RET(ctx != NULL); - CAMELLIA_VALIDATE_RET(mode == MBEDTLS_CAMELLIA_ENCRYPT || - mode == MBEDTLS_CAMELLIA_DECRYPT); - CAMELLIA_VALIDATE_RET(input != NULL); - CAMELLIA_VALIDATE_RET(output != NULL); + if (mode != MBEDTLS_CAMELLIA_ENCRYPT && mode != MBEDTLS_CAMELLIA_DECRYPT) { + return MBEDTLS_ERR_CAMELLIA_BAD_INPUT_DATA; + } ((void) mode); @@ -547,14 +523,10 @@ int mbedtls_camellia_crypt_cbc(mbedtls_camellia_context *ctx, const unsigned char *input, unsigned char *output) { - int i; unsigned char temp[16]; - CAMELLIA_VALIDATE_RET(ctx != NULL); - CAMELLIA_VALIDATE_RET(mode == MBEDTLS_CAMELLIA_ENCRYPT || - mode == MBEDTLS_CAMELLIA_DECRYPT); - CAMELLIA_VALIDATE_RET(iv != NULL); - CAMELLIA_VALIDATE_RET(length == 0 || input != NULL); - CAMELLIA_VALIDATE_RET(length == 0 || output != NULL); + if (mode != MBEDTLS_CAMELLIA_ENCRYPT && mode != MBEDTLS_CAMELLIA_DECRYPT) { + return MBEDTLS_ERR_CAMELLIA_BAD_INPUT_DATA; + } if (length % 16) { return MBEDTLS_ERR_CAMELLIA_INVALID_INPUT_LENGTH; @@ -565,9 +537,7 @@ int mbedtls_camellia_crypt_cbc(mbedtls_camellia_context *ctx, memcpy(temp, input, 16); mbedtls_camellia_crypt_ecb(ctx, mode, input, output); - for (i = 0; i < 16; i++) { - output[i] = (unsigned char) (output[i] ^ iv[i]); - } + mbedtls_xor(output, output, iv, 16); memcpy(iv, temp, 16); @@ -577,9 +547,7 @@ int mbedtls_camellia_crypt_cbc(mbedtls_camellia_context *ctx, } } else { while (length > 0) { - for (i = 0; i < 16; i++) { - output[i] = (unsigned char) (input[i] ^ iv[i]); - } + mbedtls_xor(output, input, iv, 16); mbedtls_camellia_crypt_ecb(ctx, mode, output, output); memcpy(iv, output, 16); @@ -608,13 +576,9 @@ int mbedtls_camellia_crypt_cfb128(mbedtls_camellia_context *ctx, { int c; size_t n; - CAMELLIA_VALIDATE_RET(ctx != NULL); - CAMELLIA_VALIDATE_RET(mode == MBEDTLS_CAMELLIA_ENCRYPT || - mode == MBEDTLS_CAMELLIA_DECRYPT); - CAMELLIA_VALIDATE_RET(iv != NULL); - CAMELLIA_VALIDATE_RET(iv_off != NULL); - CAMELLIA_VALIDATE_RET(length == 0 || input != NULL); - CAMELLIA_VALIDATE_RET(length == 0 || output != NULL); + if (mode != MBEDTLS_CAMELLIA_ENCRYPT && mode != MBEDTLS_CAMELLIA_DECRYPT) { + return MBEDTLS_ERR_CAMELLIA_BAD_INPUT_DATA; + } n = *iv_off; if (n >= 16) { @@ -665,12 +629,6 @@ int mbedtls_camellia_crypt_ctr(mbedtls_camellia_context *ctx, { int c, i; size_t n; - CAMELLIA_VALIDATE_RET(ctx != NULL); - CAMELLIA_VALIDATE_RET(nonce_counter != NULL); - CAMELLIA_VALIDATE_RET(stream_block != NULL); - CAMELLIA_VALIDATE_RET(nc_off != NULL); - CAMELLIA_VALIDATE_RET(length == 0 || input != NULL); - CAMELLIA_VALIDATE_RET(length == 0 || output != NULL); n = *nc_off; if (n >= 16) { @@ -932,14 +890,26 @@ int mbedtls_camellia_self_test(int verbose) (v == MBEDTLS_CAMELLIA_DECRYPT) ? "dec" : "enc"); } +#if defined(MBEDTLS_BLOCK_CIPHER_NO_DECRYPT) + if (v == MBEDTLS_CAMELLIA_DECRYPT) { + if (verbose != 0) { + mbedtls_printf("skipped\n"); + } + continue; + } +#endif + for (i = 0; i < CAMELLIA_TESTS_ECB; i++) { memcpy(key, camellia_test_ecb_key[u][i], 16 + 8 * u); +#if !defined(MBEDTLS_BLOCK_CIPHER_NO_DECRYPT) if (v == MBEDTLS_CAMELLIA_DECRYPT) { mbedtls_camellia_setkey_dec(&ctx, key, 128 + u * 64); memcpy(src, camellia_test_ecb_cipher[u][i], 16); memcpy(dst, camellia_test_ecb_plain[i], 16); - } else { /* MBEDTLS_CAMELLIA_ENCRYPT */ + } else +#endif + { /* MBEDTLS_CAMELLIA_ENCRYPT */ mbedtls_camellia_setkey_enc(&ctx, key, 128 + u * 64); memcpy(src, camellia_test_ecb_plain[i], 16); memcpy(dst, camellia_test_ecb_cipher[u][i], 16); diff --git a/vendor/mbedtls/library/ccm.c b/vendor/mbedtls/library/ccm.c index 79a04a275a..45ed697dd3 100644 --- a/vendor/mbedtls/library/ccm.c +++ b/vendor/mbedtls/library/ccm.c @@ -2,19 +2,7 @@ * NIST SP800-38C compliant CCM implementation * * Copyright The Mbed TLS Contributors - * SPDX-License-Identifier: Apache-2.0 - * - * Licensed under the Apache License, Version 2.0 (the "License"); you may - * not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT - * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. + * SPDX-License-Identifier: Apache-2.0 OR GPL-2.0-or-later */ /* @@ -35,26 +23,29 @@ #include "mbedtls/error.h" #include "mbedtls/constant_time.h" +#if defined(MBEDTLS_BLOCK_CIPHER_C) +#include "block_cipher_internal.h" +#endif + #include +#if defined(MBEDTLS_PLATFORM_C) #include "mbedtls/platform.h" +#else +#if defined(MBEDTLS_SELF_TEST) && defined(MBEDTLS_AES_C) +#include +#define mbedtls_printf printf +#endif /* MBEDTLS_SELF_TEST && MBEDTLS_AES_C */ +#endif /* MBEDTLS_PLATFORM_C */ #if !defined(MBEDTLS_CCM_ALT) -#define CCM_VALIDATE_RET(cond) \ - MBEDTLS_INTERNAL_VALIDATE_RET(cond, MBEDTLS_ERR_CCM_BAD_INPUT) -#define CCM_VALIDATE(cond) \ - MBEDTLS_INTERNAL_VALIDATE(cond) - -#define CCM_ENCRYPT 0 -#define CCM_DECRYPT 1 /* * Initialize context */ void mbedtls_ccm_init(mbedtls_ccm_context *ctx) { - CCM_VALIDATE(ctx != NULL); memset(ctx, 0, sizeof(mbedtls_ccm_context)); } @@ -64,10 +55,19 @@ int mbedtls_ccm_setkey(mbedtls_ccm_context *ctx, unsigned int keybits) { int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED; - const mbedtls_cipher_info_t *cipher_info; - CCM_VALIDATE_RET(ctx != NULL); - CCM_VALIDATE_RET(key != NULL); +#if defined(MBEDTLS_BLOCK_CIPHER_C) + mbedtls_block_cipher_free(&ctx->block_cipher_ctx); + + if ((ret = mbedtls_block_cipher_setup(&ctx->block_cipher_ctx, cipher)) != 0) { + return MBEDTLS_ERR_CCM_BAD_INPUT; + } + + if ((ret = mbedtls_block_cipher_setkey(&ctx->block_cipher_ctx, key, keybits)) != 0) { + return MBEDTLS_ERR_CCM_BAD_INPUT; + } +#else + const mbedtls_cipher_info_t *cipher_info; cipher_info = mbedtls_cipher_info_from_values(cipher, keybits, MBEDTLS_MODE_ECB); @@ -75,7 +75,7 @@ int mbedtls_ccm_setkey(mbedtls_ccm_context *ctx, return MBEDTLS_ERR_CCM_BAD_INPUT; } - if (cipher_info->block_size != 16) { + if (mbedtls_cipher_info_get_block_size(cipher_info) != 16) { return MBEDTLS_ERR_CCM_BAD_INPUT; } @@ -89,8 +89,9 @@ int mbedtls_ccm_setkey(mbedtls_ccm_context *ctx, MBEDTLS_ENCRYPT)) != 0) { return ret; } +#endif - return 0; + return ret; } /* @@ -101,89 +102,88 @@ void mbedtls_ccm_free(mbedtls_ccm_context *ctx) if (ctx == NULL) { return; } +#if defined(MBEDTLS_BLOCK_CIPHER_C) + mbedtls_block_cipher_free(&ctx->block_cipher_ctx); +#else mbedtls_cipher_free(&ctx->cipher_ctx); +#endif mbedtls_platform_zeroize(ctx, sizeof(mbedtls_ccm_context)); } -/* - * Macros for common operations. - * Results in smaller compiled code than static inline functions. - */ +#define CCM_STATE__CLEAR 0 +#define CCM_STATE__STARTED (1 << 0) +#define CCM_STATE__LENGTHS_SET (1 << 1) +#define CCM_STATE__AUTH_DATA_STARTED (1 << 2) +#define CCM_STATE__AUTH_DATA_FINISHED (1 << 3) +#define CCM_STATE__ERROR (1 << 4) /* - * Update the CBC-MAC state in y using a block in b - * (Always using b as the source helps the compiler optimise a bit better.) + * Encrypt or decrypt a partial block with CTR */ -#define UPDATE_CBC_MAC \ - for (i = 0; i < 16; i++) \ - y[i] ^= b[i]; \ - \ - if ((ret = mbedtls_cipher_update(&ctx->cipher_ctx, y, 16, y, &olen)) != 0) \ +static int mbedtls_ccm_crypt(mbedtls_ccm_context *ctx, + size_t offset, size_t use_len, + const unsigned char *input, + unsigned char *output) +{ + int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED; + unsigned char tmp_buf[16] = { 0 }; + +#if defined(MBEDTLS_BLOCK_CIPHER_C) + ret = mbedtls_block_cipher_encrypt(&ctx->block_cipher_ctx, ctx->ctr, tmp_buf); +#else + size_t olen = 0; + ret = mbedtls_cipher_update(&ctx->cipher_ctx, ctx->ctr, 16, tmp_buf, &olen); +#endif + if (ret != 0) { + ctx->state |= CCM_STATE__ERROR; + mbedtls_platform_zeroize(tmp_buf, sizeof(tmp_buf)); + return ret; + } + + mbedtls_xor(output, input, tmp_buf + offset, use_len); + + mbedtls_platform_zeroize(tmp_buf, sizeof(tmp_buf)); return ret; +} -/* - * Encrypt or decrypt a partial block with CTR - * Warning: using b for temporary storage! src and dst must not be b! - * This avoids allocating one more 16 bytes buffer while allowing src == dst. - */ -#define CTR_CRYPT(dst, src, len) \ - do \ - { \ - if ((ret = mbedtls_cipher_update(&ctx->cipher_ctx, ctr, \ - 16, b, &olen)) != 0) \ - { \ - return ret; \ - } \ - \ - for (i = 0; i < (len); i++) \ - (dst)[i] = (src)[i] ^ b[i]; \ - } while (0) +static void mbedtls_ccm_clear_state(mbedtls_ccm_context *ctx) +{ + ctx->state = CCM_STATE__CLEAR; + memset(ctx->y, 0, 16); + memset(ctx->ctr, 0, 16); +} -/* - * Authenticated encryption or decryption - */ -static int ccm_auth_crypt(mbedtls_ccm_context *ctx, int mode, size_t length, - const unsigned char *iv, size_t iv_len, - const unsigned char *add, size_t add_len, - const unsigned char *input, unsigned char *output, - unsigned char *tag, size_t tag_len) +static int ccm_calculate_first_block_if_ready(mbedtls_ccm_context *ctx) { int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED; unsigned char i; - unsigned char q; - size_t len_left, olen; - unsigned char b[16]; - unsigned char y[16]; - unsigned char ctr[16]; - const unsigned char *src; - unsigned char *dst; + size_t len_left; +#if !defined(MBEDTLS_BLOCK_CIPHER_C) + size_t olen; +#endif - /* - * Check length requirements: SP800-38C A.1 - * Additional requirement: a < 2^16 - 2^8 to simplify the code. - * 'length' checked later (when writing it to the first block) - * - * Also, loosen the requirements to enable support for CCM* (IEEE 802.15.4). + /* length calculation can be done only after both + * mbedtls_ccm_starts() and mbedtls_ccm_set_lengths() have been executed */ - if (tag_len == 2 || tag_len > 16 || tag_len % 2 != 0) { - return MBEDTLS_ERR_CCM_BAD_INPUT; - } - - /* Also implies q is within bounds */ - if (iv_len < 7 || iv_len > 13) { - return MBEDTLS_ERR_CCM_BAD_INPUT; + if (!(ctx->state & CCM_STATE__STARTED) || !(ctx->state & CCM_STATE__LENGTHS_SET)) { + return 0; } - if (add_len >= 0xFF00) { - return MBEDTLS_ERR_CCM_BAD_INPUT; + /* CCM expects non-empty tag. + * CCM* allows empty tag. For CCM* without tag, ignore plaintext length. + */ + if (ctx->tag_len == 0) { + if (ctx->mode == MBEDTLS_CCM_STAR_ENCRYPT || ctx->mode == MBEDTLS_CCM_STAR_DECRYPT) { + ctx->plaintext_len = 0; + } else { + return MBEDTLS_ERR_CCM_BAD_INPUT; + } } - q = 16 - 1 - (unsigned char) iv_len; - /* - * First block B_0: + * First block: * 0 .. 0 flags - * 1 .. iv_len nonce (aka iv) + * 1 .. iv_len nonce (aka iv) - set by: mbedtls_ccm_starts() * iv_len+1 .. 15 length * * With flags as (bits): @@ -192,57 +192,46 @@ static int ccm_auth_crypt(mbedtls_ccm_context *ctx, int mode, size_t length, * 5 .. 3 (t - 2) / 2 * 2 .. 0 q - 1 */ - b[0] = 0; - b[0] |= (add_len > 0) << 6; - b[0] |= ((tag_len - 2) / 2) << 3; - b[0] |= q - 1; - - memcpy(b + 1, iv, iv_len); + ctx->y[0] |= (ctx->add_len > 0) << 6; + ctx->y[0] |= ((ctx->tag_len - 2) / 2) << 3; + ctx->y[0] |= ctx->q - 1; - for (i = 0, len_left = length; i < q; i++, len_left >>= 8) { - b[15-i] = MBEDTLS_BYTE_0(len_left); + for (i = 0, len_left = ctx->plaintext_len; i < ctx->q; i++, len_left >>= 8) { + ctx->y[15-i] = MBEDTLS_BYTE_0(len_left); } if (len_left > 0) { + ctx->state |= CCM_STATE__ERROR; return MBEDTLS_ERR_CCM_BAD_INPUT; } + /* Start CBC-MAC with first block*/ +#if defined(MBEDTLS_BLOCK_CIPHER_C) + ret = mbedtls_block_cipher_encrypt(&ctx->block_cipher_ctx, ctx->y, ctx->y); +#else + ret = mbedtls_cipher_update(&ctx->cipher_ctx, ctx->y, 16, ctx->y, &olen); +#endif + if (ret != 0) { + ctx->state |= CCM_STATE__ERROR; + return ret; + } - /* Start CBC-MAC with first block */ - memset(y, 0, 16); - UPDATE_CBC_MAC; - - /* - * If there is additional data, update CBC-MAC with - * add_len, add, 0 (padding to a block boundary) - */ - if (add_len > 0) { - size_t use_len; - len_left = add_len; - src = add; - - memset(b, 0, 16); - MBEDTLS_PUT_UINT16_BE(add_len, b, 0); - - use_len = len_left < 16 - 2 ? len_left : 16 - 2; - memcpy(b + 2, src, use_len); - len_left -= use_len; - src += use_len; - - UPDATE_CBC_MAC; - - while (len_left > 0) { - use_len = len_left > 16 ? 16 : len_left; - - memset(b, 0, 16); - memcpy(b, src, use_len); - UPDATE_CBC_MAC; + return 0; +} - len_left -= use_len; - src += use_len; - } +int mbedtls_ccm_starts(mbedtls_ccm_context *ctx, + int mode, + const unsigned char *iv, + size_t iv_len) +{ + /* Also implies q is within bounds */ + if (iv_len < 7 || iv_len > 13) { + return MBEDTLS_ERR_CCM_BAD_INPUT; } + ctx->mode = mode; + ctx->q = 16 - 1 - (unsigned char) iv_len; + /* * Prepare counter block for encryption: * 0 .. 0 flags @@ -253,62 +242,302 @@ static int ccm_auth_crypt(mbedtls_ccm_context *ctx, int mode, size_t length, * 7 .. 3 0 * 2 .. 0 q - 1 */ - ctr[0] = q - 1; - memcpy(ctr + 1, iv, iv_len); - memset(ctr + 1 + iv_len, 0, q); - ctr[15] = 1; + memset(ctx->ctr, 0, 16); + ctx->ctr[0] = ctx->q - 1; + memcpy(ctx->ctr + 1, iv, iv_len); + memset(ctx->ctr + 1 + iv_len, 0, ctx->q); + ctx->ctr[15] = 1; /* - * Authenticate and {en,de}crypt the message. + * See ccm_calculate_first_block_if_ready() for block layout description + */ + memcpy(ctx->y + 1, iv, iv_len); + + ctx->state |= CCM_STATE__STARTED; + return ccm_calculate_first_block_if_ready(ctx); +} + +int mbedtls_ccm_set_lengths(mbedtls_ccm_context *ctx, + size_t total_ad_len, + size_t plaintext_len, + size_t tag_len) +{ + /* + * Check length requirements: SP800-38C A.1 + * Additional requirement: a < 2^16 - 2^8 to simplify the code. + * 'length' checked later (when writing it to the first block) * - * The only difference between encryption and decryption is - * the respective order of authentication and {en,de}cryption. + * Also, loosen the requirements to enable support for CCM* (IEEE 802.15.4). */ - len_left = length; - src = input; - dst = output; + if (tag_len == 2 || tag_len > 16 || tag_len % 2 != 0) { + return MBEDTLS_ERR_CCM_BAD_INPUT; + } + + if (total_ad_len >= 0xFF00) { + return MBEDTLS_ERR_CCM_BAD_INPUT; + } + + ctx->plaintext_len = plaintext_len; + ctx->add_len = total_ad_len; + ctx->tag_len = tag_len; + ctx->processed = 0; - while (len_left > 0) { - size_t use_len = len_left > 16 ? 16 : len_left; + ctx->state |= CCM_STATE__LENGTHS_SET; + return ccm_calculate_first_block_if_ready(ctx); +} - if (mode == CCM_ENCRYPT) { - memset(b, 0, 16); - memcpy(b, src, use_len); - UPDATE_CBC_MAC; +int mbedtls_ccm_update_ad(mbedtls_ccm_context *ctx, + const unsigned char *add, + size_t add_len) +{ + int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED; + size_t use_len, offset; +#if !defined(MBEDTLS_BLOCK_CIPHER_C) + size_t olen; +#endif + + if (ctx->state & CCM_STATE__ERROR) { + return MBEDTLS_ERR_CCM_BAD_INPUT; + } + + if (add_len > 0) { + if (ctx->state & CCM_STATE__AUTH_DATA_FINISHED) { + return MBEDTLS_ERR_CCM_BAD_INPUT; } - CTR_CRYPT(dst, src, use_len); + if (!(ctx->state & CCM_STATE__AUTH_DATA_STARTED)) { + if (add_len > ctx->add_len) { + return MBEDTLS_ERR_CCM_BAD_INPUT; + } - if (mode == CCM_DECRYPT) { - memset(b, 0, 16); - memcpy(b, dst, use_len); - UPDATE_CBC_MAC; + ctx->y[0] ^= (unsigned char) ((ctx->add_len >> 8) & 0xFF); + ctx->y[1] ^= (unsigned char) ((ctx->add_len) & 0xFF); + + ctx->state |= CCM_STATE__AUTH_DATA_STARTED; + } else if (ctx->processed + add_len > ctx->add_len) { + return MBEDTLS_ERR_CCM_BAD_INPUT; } - dst += use_len; - src += use_len; - len_left -= use_len; - - /* - * Increment counter. - * No need to check for overflow thanks to the length check above. - */ - for (i = 0; i < q; i++) { - if (++ctr[15-i] != 0) { - break; + while (add_len > 0) { + offset = (ctx->processed + 2) % 16; /* account for y[0] and y[1] + * holding total auth data length */ + use_len = 16 - offset; + + if (use_len > add_len) { + use_len = add_len; + } + + mbedtls_xor(ctx->y + offset, ctx->y + offset, add, use_len); + + ctx->processed += use_len; + add_len -= use_len; + add += use_len; + + if (use_len + offset == 16 || ctx->processed == ctx->add_len) { +#if defined(MBEDTLS_BLOCK_CIPHER_C) + ret = mbedtls_block_cipher_encrypt(&ctx->block_cipher_ctx, ctx->y, ctx->y); +#else + ret = mbedtls_cipher_update(&ctx->cipher_ctx, ctx->y, 16, ctx->y, &olen); +#endif + if (ret != 0) { + ctx->state |= CCM_STATE__ERROR; + return ret; + } } } + + if (ctx->processed == ctx->add_len) { + ctx->state |= CCM_STATE__AUTH_DATA_FINISHED; + ctx->processed = 0; // prepare for mbedtls_ccm_update() + } + } + + return 0; +} + +int mbedtls_ccm_update(mbedtls_ccm_context *ctx, + const unsigned char *input, size_t input_len, + unsigned char *output, size_t output_size, + size_t *output_len) +{ + int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED; + unsigned char i; + size_t use_len, offset; +#if !defined(MBEDTLS_BLOCK_CIPHER_C) + size_t olen; +#endif + + unsigned char local_output[16]; + + if (ctx->state & CCM_STATE__ERROR) { + return MBEDTLS_ERR_CCM_BAD_INPUT; + } + + /* Check against plaintext length only if performing operation with + * authentication + */ + if (ctx->tag_len != 0 && ctx->processed + input_len > ctx->plaintext_len) { + return MBEDTLS_ERR_CCM_BAD_INPUT; + } + + if (output_size < input_len) { + return MBEDTLS_ERR_CCM_BAD_INPUT; + } + *output_len = input_len; + + ret = 0; + + while (input_len > 0) { + offset = ctx->processed % 16; + + use_len = 16 - offset; + + if (use_len > input_len) { + use_len = input_len; + } + + ctx->processed += use_len; + + if (ctx->mode == MBEDTLS_CCM_ENCRYPT || \ + ctx->mode == MBEDTLS_CCM_STAR_ENCRYPT) { + mbedtls_xor(ctx->y + offset, ctx->y + offset, input, use_len); + + if (use_len + offset == 16 || ctx->processed == ctx->plaintext_len) { +#if defined(MBEDTLS_BLOCK_CIPHER_C) + ret = mbedtls_block_cipher_encrypt(&ctx->block_cipher_ctx, ctx->y, ctx->y); +#else + ret = mbedtls_cipher_update(&ctx->cipher_ctx, ctx->y, 16, ctx->y, &olen); +#endif + if (ret != 0) { + ctx->state |= CCM_STATE__ERROR; + goto exit; + } + } + + ret = mbedtls_ccm_crypt(ctx, offset, use_len, input, output); + if (ret != 0) { + goto exit; + } + } + + if (ctx->mode == MBEDTLS_CCM_DECRYPT || \ + ctx->mode == MBEDTLS_CCM_STAR_DECRYPT) { + /* Since output may be in shared memory, we cannot be sure that + * it will contain what we wrote to it. Therefore, we should avoid using + * it as input to any operations. + * Write decrypted data to local_output to avoid using output variable as + * input in the XOR operation for Y. + */ + ret = mbedtls_ccm_crypt(ctx, offset, use_len, input, local_output); + if (ret != 0) { + goto exit; + } + + mbedtls_xor(ctx->y + offset, ctx->y + offset, local_output, use_len); + + memcpy(output, local_output, use_len); + + if (use_len + offset == 16 || ctx->processed == ctx->plaintext_len) { +#if defined(MBEDTLS_BLOCK_CIPHER_C) + ret = mbedtls_block_cipher_encrypt(&ctx->block_cipher_ctx, ctx->y, ctx->y); +#else + ret = mbedtls_cipher_update(&ctx->cipher_ctx, ctx->y, 16, ctx->y, &olen); +#endif + if (ret != 0) { + ctx->state |= CCM_STATE__ERROR; + goto exit; + } + } + } + + if (use_len + offset == 16 || ctx->processed == ctx->plaintext_len) { + for (i = 0; i < ctx->q; i++) { + if (++(ctx->ctr)[15-i] != 0) { + break; + } + } + } + + input_len -= use_len; + input += use_len; + output += use_len; + } + +exit: + mbedtls_platform_zeroize(local_output, 16); + + return ret; +} + +int mbedtls_ccm_finish(mbedtls_ccm_context *ctx, + unsigned char *tag, size_t tag_len) +{ + int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED; + unsigned char i; + + if (ctx->state & CCM_STATE__ERROR) { + return MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED; + } + + if (ctx->add_len > 0 && !(ctx->state & CCM_STATE__AUTH_DATA_FINISHED)) { + return MBEDTLS_ERR_CCM_BAD_INPUT; + } + + if (ctx->plaintext_len > 0 && ctx->processed != ctx->plaintext_len) { + return MBEDTLS_ERR_CCM_BAD_INPUT; } /* * Authentication: reset counter and crypt/mask internal tag */ - for (i = 0; i < q; i++) { - ctr[15-i] = 0; + for (i = 0; i < ctx->q; i++) { + ctx->ctr[15-i] = 0; } - CTR_CRYPT(y, y, 16); - memcpy(tag, y, tag_len); + ret = mbedtls_ccm_crypt(ctx, 0, 16, ctx->y, ctx->y); + if (ret != 0) { + return ret; + } + if (tag != NULL) { + memcpy(tag, ctx->y, tag_len); + } + mbedtls_ccm_clear_state(ctx); + + return 0; +} + +/* + * Authenticated encryption or decryption + */ +static int ccm_auth_crypt(mbedtls_ccm_context *ctx, int mode, size_t length, + const unsigned char *iv, size_t iv_len, + const unsigned char *add, size_t add_len, + const unsigned char *input, unsigned char *output, + unsigned char *tag, size_t tag_len) +{ + int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED; + size_t olen; + + if ((ret = mbedtls_ccm_starts(ctx, mode, iv, iv_len)) != 0) { + return ret; + } + + if ((ret = mbedtls_ccm_set_lengths(ctx, add_len, length, tag_len)) != 0) { + return ret; + } + + if ((ret = mbedtls_ccm_update_ad(ctx, add, add_len)) != 0) { + return ret; + } + + if ((ret = mbedtls_ccm_update(ctx, input, length, + output, length, &olen)) != 0) { + return ret; + } + + if ((ret = mbedtls_ccm_finish(ctx, tag, tag_len)) != 0) { + return ret; + } return 0; } @@ -322,13 +551,7 @@ int mbedtls_ccm_star_encrypt_and_tag(mbedtls_ccm_context *ctx, size_t length, const unsigned char *input, unsigned char *output, unsigned char *tag, size_t tag_len) { - CCM_VALIDATE_RET(ctx != NULL); - CCM_VALIDATE_RET(iv != NULL); - CCM_VALIDATE_RET(add_len == 0 || add != NULL); - CCM_VALIDATE_RET(length == 0 || input != NULL); - CCM_VALIDATE_RET(length == 0 || output != NULL); - CCM_VALIDATE_RET(tag_len == 0 || tag != NULL); - return ccm_auth_crypt(ctx, CCM_ENCRYPT, length, iv, iv_len, + return ccm_auth_crypt(ctx, MBEDTLS_CCM_STAR_ENCRYPT, length, iv, iv_len, add, add_len, input, output, tag, tag_len); } @@ -338,80 +561,74 @@ int mbedtls_ccm_encrypt_and_tag(mbedtls_ccm_context *ctx, size_t length, const unsigned char *input, unsigned char *output, unsigned char *tag, size_t tag_len) { - CCM_VALIDATE_RET(ctx != NULL); - CCM_VALIDATE_RET(iv != NULL); - CCM_VALIDATE_RET(add_len == 0 || add != NULL); - CCM_VALIDATE_RET(length == 0 || input != NULL); - CCM_VALIDATE_RET(length == 0 || output != NULL); - CCM_VALIDATE_RET(tag_len == 0 || tag != NULL); - if (tag_len == 0) { - return MBEDTLS_ERR_CCM_BAD_INPUT; - } - - return mbedtls_ccm_star_encrypt_and_tag(ctx, length, iv, iv_len, add, - add_len, input, output, tag, tag_len); + return ccm_auth_crypt(ctx, MBEDTLS_CCM_ENCRYPT, length, iv, iv_len, + add, add_len, input, output, tag, tag_len); } /* * Authenticated decryption */ -int mbedtls_ccm_star_auth_decrypt(mbedtls_ccm_context *ctx, size_t length, - const unsigned char *iv, size_t iv_len, - const unsigned char *add, size_t add_len, - const unsigned char *input, unsigned char *output, - const unsigned char *tag, size_t tag_len) +static int mbedtls_ccm_compare_tags(const unsigned char *tag1, + const unsigned char *tag2, + size_t tag_len) +{ + /* Check tag in "constant-time" */ + int diff = mbedtls_ct_memcmp(tag1, tag2, tag_len); + + if (diff != 0) { + return MBEDTLS_ERR_CCM_AUTH_FAILED; + } + + return 0; +} + +static int ccm_auth_decrypt(mbedtls_ccm_context *ctx, int mode, size_t length, + const unsigned char *iv, size_t iv_len, + const unsigned char *add, size_t add_len, + const unsigned char *input, unsigned char *output, + const unsigned char *tag, size_t tag_len) { int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED; unsigned char check_tag[16]; - int diff; - - CCM_VALIDATE_RET(ctx != NULL); - CCM_VALIDATE_RET(iv != NULL); - CCM_VALIDATE_RET(add_len == 0 || add != NULL); - CCM_VALIDATE_RET(length == 0 || input != NULL); - CCM_VALIDATE_RET(length == 0 || output != NULL); - CCM_VALIDATE_RET(tag_len == 0 || tag != NULL); - if ((ret = ccm_auth_crypt(ctx, CCM_DECRYPT, length, + if ((ret = ccm_auth_crypt(ctx, mode, length, iv, iv_len, add, add_len, input, output, check_tag, tag_len)) != 0) { return ret; } - /* Check tag in "constant-time" */ - diff = mbedtls_ct_memcmp(tag, check_tag, tag_len); - - if (diff != 0) { + if ((ret = mbedtls_ccm_compare_tags(tag, check_tag, tag_len)) != 0) { mbedtls_platform_zeroize(output, length); - return MBEDTLS_ERR_CCM_AUTH_FAILED; + return ret; } return 0; } +int mbedtls_ccm_star_auth_decrypt(mbedtls_ccm_context *ctx, size_t length, + const unsigned char *iv, size_t iv_len, + const unsigned char *add, size_t add_len, + const unsigned char *input, unsigned char *output, + const unsigned char *tag, size_t tag_len) +{ + return ccm_auth_decrypt(ctx, MBEDTLS_CCM_STAR_DECRYPT, length, + iv, iv_len, add, add_len, + input, output, tag, tag_len); +} + int mbedtls_ccm_auth_decrypt(mbedtls_ccm_context *ctx, size_t length, const unsigned char *iv, size_t iv_len, const unsigned char *add, size_t add_len, const unsigned char *input, unsigned char *output, const unsigned char *tag, size_t tag_len) { - CCM_VALIDATE_RET(ctx != NULL); - CCM_VALIDATE_RET(iv != NULL); - CCM_VALIDATE_RET(add_len == 0 || add != NULL); - CCM_VALIDATE_RET(length == 0 || input != NULL); - CCM_VALIDATE_RET(length == 0 || output != NULL); - CCM_VALIDATE_RET(tag_len == 0 || tag != NULL); - - if (tag_len == 0) { - return MBEDTLS_ERR_CCM_BAD_INPUT; - } - - return mbedtls_ccm_star_auth_decrypt(ctx, length, iv, iv_len, add, - add_len, input, output, tag, tag_len); + return ccm_auth_decrypt(ctx, MBEDTLS_CCM_DECRYPT, length, + iv, iv_len, add, add_len, + input, output, tag, tag_len); } #endif /* !MBEDTLS_CCM_ALT */ -#if defined(MBEDTLS_SELF_TEST) && defined(MBEDTLS_AES_C) +#if defined(MBEDTLS_SELF_TEST) && defined(MBEDTLS_CCM_GCM_CAN_AES) /* * Examples 1 to 3 from SP800-38C Appendix C */ diff --git a/vendor/mbedtls/library/certs.c b/vendor/mbedtls/library/certs.c deleted file mode 100644 index 5b2948d652..0000000000 --- a/vendor/mbedtls/library/certs.c +++ /dev/null @@ -1,1746 +0,0 @@ -/* - * X.509 test certificates - * - * Copyright The Mbed TLS Contributors - * SPDX-License-Identifier: Apache-2.0 - * - * Licensed under the Apache License, Version 2.0 (the "License"); you may - * not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT - * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -#include "common.h" - -#include "mbedtls/certs.h" - -#if defined(MBEDTLS_CERTS_C) - -/* - * Test CA Certificates - * - * We define test CA certificates for each choice of the following parameters: - * - PEM or DER encoding - * - SHA-1 or SHA-256 hash - * - RSA or EC key - * - * Things to add: - * - multiple EC curve types - * - */ - -/* This is taken from tests/data_files/test-ca2.crt */ -/* BEGIN FILE string macro TEST_CA_CRT_EC_PEM tests/data_files/test-ca2.crt */ -#define TEST_CA_CRT_EC_PEM \ - "-----BEGIN CERTIFICATE-----\r\n" \ - "MIICBDCCAYigAwIBAgIJAMFD4n5iQ8zoMAwGCCqGSM49BAMCBQAwPjELMAkGA1UE\r\n" \ - "BhMCTkwxETAPBgNVBAoMCFBvbGFyU1NMMRwwGgYDVQQDDBNQb2xhcnNzbCBUZXN0\r\n" \ - "IEVDIENBMB4XDTE5MDIxMDE0NDQwMFoXDTI5MDIxMDE0NDQwMFowPjELMAkGA1UE\r\n" \ - "BhMCTkwxETAPBgNVBAoMCFBvbGFyU1NMMRwwGgYDVQQDDBNQb2xhcnNzbCBUZXN0\r\n" \ - "IEVDIENBMHYwEAYHKoZIzj0CAQYFK4EEACIDYgAEw9orNEE3WC+HVv78ibopQ0tO\r\n" \ - "4G7DDldTMzlY1FK0kZU5CyPfXxckYkj8GpUpziwth8KIUoCv1mqrId240xxuWLjK\r\n" \ - "6LJpjvNBrSnDtF91p0dv1RkpVWmaUzsgtGYWYDMeo1AwTjAMBgNVHRMEBTADAQH/\r\n" \ - "MB0GA1UdDgQWBBSdbSAkSQE/K8t4tRm8fiTJ2/s2fDAfBgNVHSMEGDAWgBSdbSAk\r\n" \ - "SQE/K8t4tRm8fiTJ2/s2fDAMBggqhkjOPQQDAgUAA2gAMGUCMFHKrjAPpHB0BN1a\r\n" \ - "LH8TwcJ3vh0AxeKZj30mRdOKBmg/jLS3rU3g8VQBHpn8sOTTBwIxANxPO5AerimZ\r\n" \ - "hCjMe0d4CTHf1gFZMF70+IqEP+o5VHsIp2Cqvflb0VGWFC5l9a4cQg==\r\n" \ - "-----END CERTIFICATE-----\r\n" -/* END FILE */ - -/* This is generated from tests/data_files/test-ca2.crt.der using `xxd -i`. */ -/* BEGIN FILE binary macro TEST_CA_CRT_EC_DER tests/data_files/test-ca2.crt.der */ -#define TEST_CA_CRT_EC_DER { \ - 0x30, 0x82, 0x02, 0x04, 0x30, 0x82, 0x01, 0x88, 0xa0, 0x03, 0x02, 0x01, \ - 0x02, 0x02, 0x09, 0x00, 0xc1, 0x43, 0xe2, 0x7e, 0x62, 0x43, 0xcc, 0xe8, \ - 0x30, 0x0c, 0x06, 0x08, 0x2a, 0x86, 0x48, 0xce, 0x3d, 0x04, 0x03, 0x02, \ - 0x05, 0x00, 0x30, 0x3e, 0x31, 0x0b, 0x30, 0x09, 0x06, 0x03, 0x55, 0x04, \ - 0x06, 0x13, 0x02, 0x4e, 0x4c, 0x31, 0x11, 0x30, 0x0f, 0x06, 0x03, 0x55, \ - 0x04, 0x0a, 0x0c, 0x08, 0x50, 0x6f, 0x6c, 0x61, 0x72, 0x53, 0x53, 0x4c, \ - 0x31, 0x1c, 0x30, 0x1a, 0x06, 0x03, 0x55, 0x04, 0x03, 0x0c, 0x13, 0x50, \ - 0x6f, 0x6c, 0x61, 0x72, 0x73, 0x73, 0x6c, 0x20, 0x54, 0x65, 0x73, 0x74, \ - 0x20, 0x45, 0x43, 0x20, 0x43, 0x41, 0x30, 0x1e, 0x17, 0x0d, 0x31, 0x39, \ - 0x30, 0x32, 0x31, 0x30, 0x31, 0x34, 0x34, 0x34, 0x30, 0x30, 0x5a, 0x17, \ - 0x0d, 0x32, 0x39, 0x30, 0x32, 0x31, 0x30, 0x31, 0x34, 0x34, 0x34, 0x30, \ - 0x30, 0x5a, 0x30, 0x3e, 0x31, 0x0b, 0x30, 0x09, 0x06, 0x03, 0x55, 0x04, \ - 0x06, 0x13, 0x02, 0x4e, 0x4c, 0x31, 0x11, 0x30, 0x0f, 0x06, 0x03, 0x55, \ - 0x04, 0x0a, 0x0c, 0x08, 0x50, 0x6f, 0x6c, 0x61, 0x72, 0x53, 0x53, 0x4c, \ - 0x31, 0x1c, 0x30, 0x1a, 0x06, 0x03, 0x55, 0x04, 0x03, 0x0c, 0x13, 0x50, \ - 0x6f, 0x6c, 0x61, 0x72, 0x73, 0x73, 0x6c, 0x20, 0x54, 0x65, 0x73, 0x74, \ - 0x20, 0x45, 0x43, 0x20, 0x43, 0x41, 0x30, 0x76, 0x30, 0x10, 0x06, 0x07, \ - 0x2a, 0x86, 0x48, 0xce, 0x3d, 0x02, 0x01, 0x06, 0x05, 0x2b, 0x81, 0x04, \ - 0x00, 0x22, 0x03, 0x62, 0x00, 0x04, 0xc3, 0xda, 0x2b, 0x34, 0x41, 0x37, \ - 0x58, 0x2f, 0x87, 0x56, 0xfe, 0xfc, 0x89, 0xba, 0x29, 0x43, 0x4b, 0x4e, \ - 0xe0, 0x6e, 0xc3, 0x0e, 0x57, 0x53, 0x33, 0x39, 0x58, 0xd4, 0x52, 0xb4, \ - 0x91, 0x95, 0x39, 0x0b, 0x23, 0xdf, 0x5f, 0x17, 0x24, 0x62, 0x48, 0xfc, \ - 0x1a, 0x95, 0x29, 0xce, 0x2c, 0x2d, 0x87, 0xc2, 0x88, 0x52, 0x80, 0xaf, \ - 0xd6, 0x6a, 0xab, 0x21, 0xdd, 0xb8, 0xd3, 0x1c, 0x6e, 0x58, 0xb8, 0xca, \ - 0xe8, 0xb2, 0x69, 0x8e, 0xf3, 0x41, 0xad, 0x29, 0xc3, 0xb4, 0x5f, 0x75, \ - 0xa7, 0x47, 0x6f, 0xd5, 0x19, 0x29, 0x55, 0x69, 0x9a, 0x53, 0x3b, 0x20, \ - 0xb4, 0x66, 0x16, 0x60, 0x33, 0x1e, 0xa3, 0x50, 0x30, 0x4e, 0x30, 0x0c, \ - 0x06, 0x03, 0x55, 0x1d, 0x13, 0x04, 0x05, 0x30, 0x03, 0x01, 0x01, 0xff, \ - 0x30, 0x1d, 0x06, 0x03, 0x55, 0x1d, 0x0e, 0x04, 0x16, 0x04, 0x14, 0x9d, \ - 0x6d, 0x20, 0x24, 0x49, 0x01, 0x3f, 0x2b, 0xcb, 0x78, 0xb5, 0x19, 0xbc, \ - 0x7e, 0x24, 0xc9, 0xdb, 0xfb, 0x36, 0x7c, 0x30, 0x1f, 0x06, 0x03, 0x55, \ - 0x1d, 0x23, 0x04, 0x18, 0x30, 0x16, 0x80, 0x14, 0x9d, 0x6d, 0x20, 0x24, \ - 0x49, 0x01, 0x3f, 0x2b, 0xcb, 0x78, 0xb5, 0x19, 0xbc, 0x7e, 0x24, 0xc9, \ - 0xdb, 0xfb, 0x36, 0x7c, 0x30, 0x0c, 0x06, 0x08, 0x2a, 0x86, 0x48, 0xce, \ - 0x3d, 0x04, 0x03, 0x02, 0x05, 0x00, 0x03, 0x68, 0x00, 0x30, 0x65, 0x02, \ - 0x30, 0x51, 0xca, 0xae, 0x30, 0x0f, 0xa4, 0x70, 0x74, 0x04, 0xdd, 0x5a, \ - 0x2c, 0x7f, 0x13, 0xc1, 0xc2, 0x77, 0xbe, 0x1d, 0x00, 0xc5, 0xe2, 0x99, \ - 0x8f, 0x7d, 0x26, 0x45, 0xd3, 0x8a, 0x06, 0x68, 0x3f, 0x8c, 0xb4, 0xb7, \ - 0xad, 0x4d, 0xe0, 0xf1, 0x54, 0x01, 0x1e, 0x99, 0xfc, 0xb0, 0xe4, 0xd3, \ - 0x07, 0x02, 0x31, 0x00, 0xdc, 0x4f, 0x3b, 0x90, 0x1e, 0xae, 0x29, 0x99, \ - 0x84, 0x28, 0xcc, 0x7b, 0x47, 0x78, 0x09, 0x31, 0xdf, 0xd6, 0x01, 0x59, \ - 0x30, 0x5e, 0xf4, 0xf8, 0x8a, 0x84, 0x3f, 0xea, 0x39, 0x54, 0x7b, 0x08, \ - 0xa7, 0x60, 0xaa, 0xbd, 0xf9, 0x5b, 0xd1, 0x51, 0x96, 0x14, 0x2e, 0x65, \ - 0xf5, 0xae, 0x1c, 0x42 \ -} -/* END FILE */ - -/* This is taken from tests/data_files/test-ca2.key.enc */ -/* BEGIN FILE string macro TEST_CA_KEY_EC_PEM tests/data_files/test-ca2.key.enc */ -#define TEST_CA_KEY_EC_PEM \ - "-----BEGIN EC PRIVATE KEY-----\r\n" \ - "Proc-Type: 4,ENCRYPTED\r\n" \ - "DEK-Info: DES-EDE3-CBC,307EAB469933D64E\r\n" \ - "\r\n" \ - "IxbrRmKcAzctJqPdTQLA4SWyBYYGYJVkYEna+F7Pa5t5Yg/gKADrFKcm6B72e7DG\r\n" \ - "ihExtZI648s0zdYw6qSJ74vrPSuWDe5qm93BqsfVH9svtCzWHW0pm1p0KTBCFfUq\r\n" \ - "UsuWTITwJImcnlAs1gaRZ3sAWm7cOUidL0fo2G0fYUFNcYoCSLffCFTEHBuPnagb\r\n" \ - "a77x/sY1Bvii8S9/XhDTb6pTMx06wzrm\r\n" \ - "-----END EC PRIVATE KEY-----\r\n" -/* END FILE */ - -#define TEST_CA_PWD_EC_PEM "PolarSSLTest" - -/* This is generated from tests/data_files/test-ca2.key.der using `xxd -i`. */ -/* BEGIN FILE binary macro TEST_CA_KEY_EC_DER tests/data_files/test-ca2.key.der */ -#define TEST_CA_KEY_EC_DER { \ - 0x30, 0x81, 0xa4, 0x02, 0x01, 0x01, 0x04, 0x30, 0x83, 0xd9, 0x15, 0x0e, \ - 0xa0, 0x71, 0xf0, 0x57, 0x10, 0x33, 0xa3, 0x38, 0xb8, 0x86, 0xc1, 0xa6, \ - 0x11, 0x5d, 0x6d, 0xb4, 0x03, 0xe1, 0x29, 0x76, 0x45, 0xd7, 0x87, 0x6f, \ - 0x23, 0xab, 0x44, 0x20, 0xea, 0x64, 0x7b, 0x85, 0xb1, 0x76, 0xe7, 0x85, \ - 0x95, 0xaa, 0x74, 0xd6, 0xd1, 0xa4, 0x5e, 0xea, 0xa0, 0x07, 0x06, 0x05, \ - 0x2b, 0x81, 0x04, 0x00, 0x22, 0xa1, 0x64, 0x03, 0x62, 0x00, 0x04, 0xc3, \ - 0xda, 0x2b, 0x34, 0x41, 0x37, 0x58, 0x2f, 0x87, 0x56, 0xfe, 0xfc, 0x89, \ - 0xba, 0x29, 0x43, 0x4b, 0x4e, 0xe0, 0x6e, 0xc3, 0x0e, 0x57, 0x53, 0x33, \ - 0x39, 0x58, 0xd4, 0x52, 0xb4, 0x91, 0x95, 0x39, 0x0b, 0x23, 0xdf, 0x5f, \ - 0x17, 0x24, 0x62, 0x48, 0xfc, 0x1a, 0x95, 0x29, 0xce, 0x2c, 0x2d, 0x87, \ - 0xc2, 0x88, 0x52, 0x80, 0xaf, 0xd6, 0x6a, 0xab, 0x21, 0xdd, 0xb8, 0xd3, \ - 0x1c, 0x6e, 0x58, 0xb8, 0xca, 0xe8, 0xb2, 0x69, 0x8e, 0xf3, 0x41, 0xad, \ - 0x29, 0xc3, 0xb4, 0x5f, 0x75, 0xa7, 0x47, 0x6f, 0xd5, 0x19, 0x29, 0x55, \ - 0x69, 0x9a, 0x53, 0x3b, 0x20, 0xb4, 0x66, 0x16, 0x60, 0x33, 0x1e \ -} -/* END FILE */ - -/* This is taken from tests/data_files/test-ca-sha256.crt. */ -/* BEGIN FILE string macro TEST_CA_CRT_RSA_SHA256_PEM tests/data_files/test-ca-sha256.crt */ -#define TEST_CA_CRT_RSA_SHA256_PEM \ - "-----BEGIN CERTIFICATE-----\r\n" \ - "MIIDQTCCAimgAwIBAgIBAzANBgkqhkiG9w0BAQsFADA7MQswCQYDVQQGEwJOTDER\r\n" \ - "MA8GA1UECgwIUG9sYXJTU0wxGTAXBgNVBAMMEFBvbGFyU1NMIFRlc3QgQ0EwHhcN\r\n" \ - "MTkwMjEwMTQ0NDAwWhcNMjkwMjEwMTQ0NDAwWjA7MQswCQYDVQQGEwJOTDERMA8G\r\n" \ - "A1UECgwIUG9sYXJTU0wxGTAXBgNVBAMMEFBvbGFyU1NMIFRlc3QgQ0EwggEiMA0G\r\n" \ - "CSqGSIb3DQEBAQUAA4IBDwAwggEKAoIBAQDA3zf8F7vglp0/ht6WMn1EpRagzSHx\r\n" \ - "mdTs6st8GFgIlKXsm8WL3xoemTiZhx57wI053zhdcHgH057Zk+i5clHFzqMwUqny\r\n" \ - "50BwFMtEonILwuVA+T7lpg6z+exKY8C4KQB0nFc7qKUEkHHxvYPZP9al4jwqj+8n\r\n" \ - "YMPGn8u67GB9t+aEMr5P+1gmIgNb1LTV+/Xjli5wwOQuvfwu7uJBVcA0Ln0kcmnL\r\n" \ - "R7EUQIN9Z/SG9jGr8XmksrUuEvmEF/Bibyc+E1ixVA0hmnM3oTDPb5Lc9un8rNsu\r\n" \ - "KNF+AksjoBXyOGVkCeoMbo4bF6BxyLObyavpw/LPh5aPgAIynplYb6LVAgMBAAGj\r\n" \ - "UDBOMAwGA1UdEwQFMAMBAf8wHQYDVR0OBBYEFLRa5KWz3tJS9rnVppUP6z68x/3/\r\n" \ - "MB8GA1UdIwQYMBaAFLRa5KWz3tJS9rnVppUP6z68x/3/MA0GCSqGSIb3DQEBCwUA\r\n" \ - "A4IBAQA4qFSCth2q22uJIdE4KGHJsJjVEfw2/xn+MkTvCMfxVrvmRvqCtjE4tKDl\r\n" \ - "oK4MxFOek07oDZwvtAT9ijn1hHftTNS7RH9zd/fxNpfcHnMZXVC4w4DNA1fSANtW\r\n" \ - "5sY1JB5Je9jScrsLSS+mAjyv0Ow3Hb2Bix8wu7xNNrV5fIf7Ubm+wt6SqEBxu3Kb\r\n" \ - "+EfObAT4huf3czznhH3C17ed6NSbXwoXfby7stWUDeRJv08RaFOykf/Aae7bY5PL\r\n" \ - "yTVrkAnikMntJ9YI+hNNYt3inqq11A5cN0+rVTst8UKCxzQ4GpvroSwPKTFkbMw4\r\n" \ - "/anT1dVxr/BtwJfiESoK3/4CeXR1\r\n" \ - "-----END CERTIFICATE-----\r\n" -/* END FILE */ - -/* This is generated from tests/data_files/test-ca-sha256.crt.der - * using `xxd -i`. */ -/* BEGIN FILE binary macro TEST_CA_CRT_RSA_SHA256_DER tests/data_files/test-ca-sha256.crt.der */ -#define TEST_CA_CRT_RSA_SHA256_DER { \ - 0x30, 0x82, 0x03, 0x41, 0x30, 0x82, 0x02, 0x29, 0xa0, 0x03, 0x02, 0x01, \ - 0x02, 0x02, 0x01, 0x03, 0x30, 0x0d, 0x06, 0x09, 0x2a, 0x86, 0x48, 0x86, \ - 0xf7, 0x0d, 0x01, 0x01, 0x0b, 0x05, 0x00, 0x30, 0x3b, 0x31, 0x0b, 0x30, \ - 0x09, 0x06, 0x03, 0x55, 0x04, 0x06, 0x13, 0x02, 0x4e, 0x4c, 0x31, 0x11, \ - 0x30, 0x0f, 0x06, 0x03, 0x55, 0x04, 0x0a, 0x0c, 0x08, 0x50, 0x6f, 0x6c, \ - 0x61, 0x72, 0x53, 0x53, 0x4c, 0x31, 0x19, 0x30, 0x17, 0x06, 0x03, 0x55, \ - 0x04, 0x03, 0x0c, 0x10, 0x50, 0x6f, 0x6c, 0x61, 0x72, 0x53, 0x53, 0x4c, \ - 0x20, 0x54, 0x65, 0x73, 0x74, 0x20, 0x43, 0x41, 0x30, 0x1e, 0x17, 0x0d, \ - 0x31, 0x39, 0x30, 0x32, 0x31, 0x30, 0x31, 0x34, 0x34, 0x34, 0x30, 0x30, \ - 0x5a, 0x17, 0x0d, 0x32, 0x39, 0x30, 0x32, 0x31, 0x30, 0x31, 0x34, 0x34, \ - 0x34, 0x30, 0x30, 0x5a, 0x30, 0x3b, 0x31, 0x0b, 0x30, 0x09, 0x06, 0x03, \ - 0x55, 0x04, 0x06, 0x13, 0x02, 0x4e, 0x4c, 0x31, 0x11, 0x30, 0x0f, 0x06, \ - 0x03, 0x55, 0x04, 0x0a, 0x0c, 0x08, 0x50, 0x6f, 0x6c, 0x61, 0x72, 0x53, \ - 0x53, 0x4c, 0x31, 0x19, 0x30, 0x17, 0x06, 0x03, 0x55, 0x04, 0x03, 0x0c, \ - 0x10, 0x50, 0x6f, 0x6c, 0x61, 0x72, 0x53, 0x53, 0x4c, 0x20, 0x54, 0x65, \ - 0x73, 0x74, 0x20, 0x43, 0x41, 0x30, 0x82, 0x01, 0x22, 0x30, 0x0d, 0x06, \ - 0x09, 0x2a, 0x86, 0x48, 0x86, 0xf7, 0x0d, 0x01, 0x01, 0x01, 0x05, 0x00, \ - 0x03, 0x82, 0x01, 0x0f, 0x00, 0x30, 0x82, 0x01, 0x0a, 0x02, 0x82, 0x01, \ - 0x01, 0x00, 0xc0, 0xdf, 0x37, 0xfc, 0x17, 0xbb, 0xe0, 0x96, 0x9d, 0x3f, \ - 0x86, 0xde, 0x96, 0x32, 0x7d, 0x44, 0xa5, 0x16, 0xa0, 0xcd, 0x21, 0xf1, \ - 0x99, 0xd4, 0xec, 0xea, 0xcb, 0x7c, 0x18, 0x58, 0x08, 0x94, 0xa5, 0xec, \ - 0x9b, 0xc5, 0x8b, 0xdf, 0x1a, 0x1e, 0x99, 0x38, 0x99, 0x87, 0x1e, 0x7b, \ - 0xc0, 0x8d, 0x39, 0xdf, 0x38, 0x5d, 0x70, 0x78, 0x07, 0xd3, 0x9e, 0xd9, \ - 0x93, 0xe8, 0xb9, 0x72, 0x51, 0xc5, 0xce, 0xa3, 0x30, 0x52, 0xa9, 0xf2, \ - 0xe7, 0x40, 0x70, 0x14, 0xcb, 0x44, 0xa2, 0x72, 0x0b, 0xc2, 0xe5, 0x40, \ - 0xf9, 0x3e, 0xe5, 0xa6, 0x0e, 0xb3, 0xf9, 0xec, 0x4a, 0x63, 0xc0, 0xb8, \ - 0x29, 0x00, 0x74, 0x9c, 0x57, 0x3b, 0xa8, 0xa5, 0x04, 0x90, 0x71, 0xf1, \ - 0xbd, 0x83, 0xd9, 0x3f, 0xd6, 0xa5, 0xe2, 0x3c, 0x2a, 0x8f, 0xef, 0x27, \ - 0x60, 0xc3, 0xc6, 0x9f, 0xcb, 0xba, 0xec, 0x60, 0x7d, 0xb7, 0xe6, 0x84, \ - 0x32, 0xbe, 0x4f, 0xfb, 0x58, 0x26, 0x22, 0x03, 0x5b, 0xd4, 0xb4, 0xd5, \ - 0xfb, 0xf5, 0xe3, 0x96, 0x2e, 0x70, 0xc0, 0xe4, 0x2e, 0xbd, 0xfc, 0x2e, \ - 0xee, 0xe2, 0x41, 0x55, 0xc0, 0x34, 0x2e, 0x7d, 0x24, 0x72, 0x69, 0xcb, \ - 0x47, 0xb1, 0x14, 0x40, 0x83, 0x7d, 0x67, 0xf4, 0x86, 0xf6, 0x31, 0xab, \ - 0xf1, 0x79, 0xa4, 0xb2, 0xb5, 0x2e, 0x12, 0xf9, 0x84, 0x17, 0xf0, 0x62, \ - 0x6f, 0x27, 0x3e, 0x13, 0x58, 0xb1, 0x54, 0x0d, 0x21, 0x9a, 0x73, 0x37, \ - 0xa1, 0x30, 0xcf, 0x6f, 0x92, 0xdc, 0xf6, 0xe9, 0xfc, 0xac, 0xdb, 0x2e, \ - 0x28, 0xd1, 0x7e, 0x02, 0x4b, 0x23, 0xa0, 0x15, 0xf2, 0x38, 0x65, 0x64, \ - 0x09, 0xea, 0x0c, 0x6e, 0x8e, 0x1b, 0x17, 0xa0, 0x71, 0xc8, 0xb3, 0x9b, \ - 0xc9, 0xab, 0xe9, 0xc3, 0xf2, 0xcf, 0x87, 0x96, 0x8f, 0x80, 0x02, 0x32, \ - 0x9e, 0x99, 0x58, 0x6f, 0xa2, 0xd5, 0x02, 0x03, 0x01, 0x00, 0x01, 0xa3, \ - 0x50, 0x30, 0x4e, 0x30, 0x0c, 0x06, 0x03, 0x55, 0x1d, 0x13, 0x04, 0x05, \ - 0x30, 0x03, 0x01, 0x01, 0xff, 0x30, 0x1d, 0x06, 0x03, 0x55, 0x1d, 0x0e, \ - 0x04, 0x16, 0x04, 0x14, 0xb4, 0x5a, 0xe4, 0xa5, 0xb3, 0xde, 0xd2, 0x52, \ - 0xf6, 0xb9, 0xd5, 0xa6, 0x95, 0x0f, 0xeb, 0x3e, 0xbc, 0xc7, 0xfd, 0xff, \ - 0x30, 0x1f, 0x06, 0x03, 0x55, 0x1d, 0x23, 0x04, 0x18, 0x30, 0x16, 0x80, \ - 0x14, 0xb4, 0x5a, 0xe4, 0xa5, 0xb3, 0xde, 0xd2, 0x52, 0xf6, 0xb9, 0xd5, \ - 0xa6, 0x95, 0x0f, 0xeb, 0x3e, 0xbc, 0xc7, 0xfd, 0xff, 0x30, 0x0d, 0x06, \ - 0x09, 0x2a, 0x86, 0x48, 0x86, 0xf7, 0x0d, 0x01, 0x01, 0x0b, 0x05, 0x00, \ - 0x03, 0x82, 0x01, 0x01, 0x00, 0x38, 0xa8, 0x54, 0x82, 0xb6, 0x1d, 0xaa, \ - 0xdb, 0x6b, 0x89, 0x21, 0xd1, 0x38, 0x28, 0x61, 0xc9, 0xb0, 0x98, 0xd5, \ - 0x11, 0xfc, 0x36, 0xff, 0x19, 0xfe, 0x32, 0x44, 0xef, 0x08, 0xc7, 0xf1, \ - 0x56, 0xbb, 0xe6, 0x46, 0xfa, 0x82, 0xb6, 0x31, 0x38, 0xb4, 0xa0, 0xe5, \ - 0xa0, 0xae, 0x0c, 0xc4, 0x53, 0x9e, 0x93, 0x4e, 0xe8, 0x0d, 0x9c, 0x2f, \ - 0xb4, 0x04, 0xfd, 0x8a, 0x39, 0xf5, 0x84, 0x77, 0xed, 0x4c, 0xd4, 0xbb, \ - 0x44, 0x7f, 0x73, 0x77, 0xf7, 0xf1, 0x36, 0x97, 0xdc, 0x1e, 0x73, 0x19, \ - 0x5d, 0x50, 0xb8, 0xc3, 0x80, 0xcd, 0x03, 0x57, 0xd2, 0x00, 0xdb, 0x56, \ - 0xe6, 0xc6, 0x35, 0x24, 0x1e, 0x49, 0x7b, 0xd8, 0xd2, 0x72, 0xbb, 0x0b, \ - 0x49, 0x2f, 0xa6, 0x02, 0x3c, 0xaf, 0xd0, 0xec, 0x37, 0x1d, 0xbd, 0x81, \ - 0x8b, 0x1f, 0x30, 0xbb, 0xbc, 0x4d, 0x36, 0xb5, 0x79, 0x7c, 0x87, 0xfb, \ - 0x51, 0xb9, 0xbe, 0xc2, 0xde, 0x92, 0xa8, 0x40, 0x71, 0xbb, 0x72, 0x9b, \ - 0xf8, 0x47, 0xce, 0x6c, 0x04, 0xf8, 0x86, 0xe7, 0xf7, 0x73, 0x3c, 0xe7, \ - 0x84, 0x7d, 0xc2, 0xd7, 0xb7, 0x9d, 0xe8, 0xd4, 0x9b, 0x5f, 0x0a, 0x17, \ - 0x7d, 0xbc, 0xbb, 0xb2, 0xd5, 0x94, 0x0d, 0xe4, 0x49, 0xbf, 0x4f, 0x11, \ - 0x68, 0x53, 0xb2, 0x91, 0xff, 0xc0, 0x69, 0xee, 0xdb, 0x63, 0x93, 0xcb, \ - 0xc9, 0x35, 0x6b, 0x90, 0x09, 0xe2, 0x90, 0xc9, 0xed, 0x27, 0xd6, 0x08, \ - 0xfa, 0x13, 0x4d, 0x62, 0xdd, 0xe2, 0x9e, 0xaa, 0xb5, 0xd4, 0x0e, 0x5c, \ - 0x37, 0x4f, 0xab, 0x55, 0x3b, 0x2d, 0xf1, 0x42, 0x82, 0xc7, 0x34, 0x38, \ - 0x1a, 0x9b, 0xeb, 0xa1, 0x2c, 0x0f, 0x29, 0x31, 0x64, 0x6c, 0xcc, 0x38, \ - 0xfd, 0xa9, 0xd3, 0xd5, 0xd5, 0x71, 0xaf, 0xf0, 0x6d, 0xc0, 0x97, 0xe2, \ - 0x11, 0x2a, 0x0a, 0xdf, 0xfe, 0x02, 0x79, 0x74, 0x75 \ -} -/* END FILE */ - -/* This is taken from tests/data_files/test-ca-sha1.crt. */ -/* BEGIN FILE string macro TEST_CA_CRT_RSA_SHA1_PEM tests/data_files/test-ca-sha1.crt */ -#define TEST_CA_CRT_RSA_SHA1_PEM \ - "-----BEGIN CERTIFICATE-----\r\n" \ - "MIIDQTCCAimgAwIBAgIBAzANBgkqhkiG9w0BAQUFADA7MQswCQYDVQQGEwJOTDER\r\n" \ - "MA8GA1UECgwIUG9sYXJTU0wxGTAXBgNVBAMMEFBvbGFyU1NMIFRlc3QgQ0EwHhcN\r\n" \ - "MTEwMjEyMTQ0NDAwWhcNMjEwMjEyMTQ0NDAwWjA7MQswCQYDVQQGEwJOTDERMA8G\r\n" \ - "A1UECgwIUG9sYXJTU0wxGTAXBgNVBAMMEFBvbGFyU1NMIFRlc3QgQ0EwggEiMA0G\r\n" \ - "CSqGSIb3DQEBAQUAA4IBDwAwggEKAoIBAQDA3zf8F7vglp0/ht6WMn1EpRagzSHx\r\n" \ - "mdTs6st8GFgIlKXsm8WL3xoemTiZhx57wI053zhdcHgH057Zk+i5clHFzqMwUqny\r\n" \ - "50BwFMtEonILwuVA+T7lpg6z+exKY8C4KQB0nFc7qKUEkHHxvYPZP9al4jwqj+8n\r\n" \ - "YMPGn8u67GB9t+aEMr5P+1gmIgNb1LTV+/Xjli5wwOQuvfwu7uJBVcA0Ln0kcmnL\r\n" \ - "R7EUQIN9Z/SG9jGr8XmksrUuEvmEF/Bibyc+E1ixVA0hmnM3oTDPb5Lc9un8rNsu\r\n" \ - "KNF+AksjoBXyOGVkCeoMbo4bF6BxyLObyavpw/LPh5aPgAIynplYb6LVAgMBAAGj\r\n" \ - "UDBOMAwGA1UdEwQFMAMBAf8wHQYDVR0OBBYEFLRa5KWz3tJS9rnVppUP6z68x/3/\r\n" \ - "MB8GA1UdIwQYMBaAFLRa5KWz3tJS9rnVppUP6z68x/3/MA0GCSqGSIb3DQEBBQUA\r\n" \ - "A4IBAQABE3OEPfEd/bcJW5ZdU3/VgPNS4tMzh8gnJP/V2FcvFtGylMpQq6YnEBYI\r\n" \ - "yBHAL4DRvlMY5rnXGBp3ODR8MpqHC6AquRTCLzjS57iYff//4QFQqW9n92zctspv\r\n" \ - "czkaPKgjqo1No3Uq0Xaz10rcxyTUPrf5wNVRZ2V0KvllvAAVSzbI4mpdUXztjhST\r\n" \ - "S5A2BeWQAAOr0zq1F7TSRVJpJs7jmB2ai/igkh1IAjcuwV6VwlP+sbw0gjQ0NpGM\r\n" \ - "iHpnlzRAi/tIbtOvMIGOBU2TIfax/5jq1agUx5aPmT5TWAiJPOOP6l5xXnDwxeYS\r\n" \ - "NWqiX9GyusBZjezaCaHabjDLU0qQ\r\n" \ - "-----END CERTIFICATE-----\r\n" -/* END FILE */ - -/* This is taken from tests/data_files/test-ca-sha1.crt.der. */ -/* BEGIN FILE binary macro TEST_CA_CRT_RSA_SHA1_DER tests/data_files/test-ca-sha1.crt.der */ -#define TEST_CA_CRT_RSA_SHA1_DER { \ - 0x30, 0x82, 0x03, 0x41, 0x30, 0x82, 0x02, 0x29, 0xa0, 0x03, 0x02, 0x01, \ - 0x02, 0x02, 0x01, 0x03, 0x30, 0x0d, 0x06, 0x09, 0x2a, 0x86, 0x48, 0x86, \ - 0xf7, 0x0d, 0x01, 0x01, 0x05, 0x05, 0x00, 0x30, 0x3b, 0x31, 0x0b, 0x30, \ - 0x09, 0x06, 0x03, 0x55, 0x04, 0x06, 0x13, 0x02, 0x4e, 0x4c, 0x31, 0x11, \ - 0x30, 0x0f, 0x06, 0x03, 0x55, 0x04, 0x0a, 0x0c, 0x08, 0x50, 0x6f, 0x6c, \ - 0x61, 0x72, 0x53, 0x53, 0x4c, 0x31, 0x19, 0x30, 0x17, 0x06, 0x03, 0x55, \ - 0x04, 0x03, 0x0c, 0x10, 0x50, 0x6f, 0x6c, 0x61, 0x72, 0x53, 0x53, 0x4c, \ - 0x20, 0x54, 0x65, 0x73, 0x74, 0x20, 0x43, 0x41, 0x30, 0x1e, 0x17, 0x0d, \ - 0x31, 0x31, 0x30, 0x32, 0x31, 0x32, 0x31, 0x34, 0x34, 0x34, 0x30, 0x30, \ - 0x5a, 0x17, 0x0d, 0x32, 0x31, 0x30, 0x32, 0x31, 0x32, 0x31, 0x34, 0x34, \ - 0x34, 0x30, 0x30, 0x5a, 0x30, 0x3b, 0x31, 0x0b, 0x30, 0x09, 0x06, 0x03, \ - 0x55, 0x04, 0x06, 0x13, 0x02, 0x4e, 0x4c, 0x31, 0x11, 0x30, 0x0f, 0x06, \ - 0x03, 0x55, 0x04, 0x0a, 0x0c, 0x08, 0x50, 0x6f, 0x6c, 0x61, 0x72, 0x53, \ - 0x53, 0x4c, 0x31, 0x19, 0x30, 0x17, 0x06, 0x03, 0x55, 0x04, 0x03, 0x0c, \ - 0x10, 0x50, 0x6f, 0x6c, 0x61, 0x72, 0x53, 0x53, 0x4c, 0x20, 0x54, 0x65, \ - 0x73, 0x74, 0x20, 0x43, 0x41, 0x30, 0x82, 0x01, 0x22, 0x30, 0x0d, 0x06, \ - 0x09, 0x2a, 0x86, 0x48, 0x86, 0xf7, 0x0d, 0x01, 0x01, 0x01, 0x05, 0x00, \ - 0x03, 0x82, 0x01, 0x0f, 0x00, 0x30, 0x82, 0x01, 0x0a, 0x02, 0x82, 0x01, \ - 0x01, 0x00, 0xc0, 0xdf, 0x37, 0xfc, 0x17, 0xbb, 0xe0, 0x96, 0x9d, 0x3f, \ - 0x86, 0xde, 0x96, 0x32, 0x7d, 0x44, 0xa5, 0x16, 0xa0, 0xcd, 0x21, 0xf1, \ - 0x99, 0xd4, 0xec, 0xea, 0xcb, 0x7c, 0x18, 0x58, 0x08, 0x94, 0xa5, 0xec, \ - 0x9b, 0xc5, 0x8b, 0xdf, 0x1a, 0x1e, 0x99, 0x38, 0x99, 0x87, 0x1e, 0x7b, \ - 0xc0, 0x8d, 0x39, 0xdf, 0x38, 0x5d, 0x70, 0x78, 0x07, 0xd3, 0x9e, 0xd9, \ - 0x93, 0xe8, 0xb9, 0x72, 0x51, 0xc5, 0xce, 0xa3, 0x30, 0x52, 0xa9, 0xf2, \ - 0xe7, 0x40, 0x70, 0x14, 0xcb, 0x44, 0xa2, 0x72, 0x0b, 0xc2, 0xe5, 0x40, \ - 0xf9, 0x3e, 0xe5, 0xa6, 0x0e, 0xb3, 0xf9, 0xec, 0x4a, 0x63, 0xc0, 0xb8, \ - 0x29, 0x00, 0x74, 0x9c, 0x57, 0x3b, 0xa8, 0xa5, 0x04, 0x90, 0x71, 0xf1, \ - 0xbd, 0x83, 0xd9, 0x3f, 0xd6, 0xa5, 0xe2, 0x3c, 0x2a, 0x8f, 0xef, 0x27, \ - 0x60, 0xc3, 0xc6, 0x9f, 0xcb, 0xba, 0xec, 0x60, 0x7d, 0xb7, 0xe6, 0x84, \ - 0x32, 0xbe, 0x4f, 0xfb, 0x58, 0x26, 0x22, 0x03, 0x5b, 0xd4, 0xb4, 0xd5, \ - 0xfb, 0xf5, 0xe3, 0x96, 0x2e, 0x70, 0xc0, 0xe4, 0x2e, 0xbd, 0xfc, 0x2e, \ - 0xee, 0xe2, 0x41, 0x55, 0xc0, 0x34, 0x2e, 0x7d, 0x24, 0x72, 0x69, 0xcb, \ - 0x47, 0xb1, 0x14, 0x40, 0x83, 0x7d, 0x67, 0xf4, 0x86, 0xf6, 0x31, 0xab, \ - 0xf1, 0x79, 0xa4, 0xb2, 0xb5, 0x2e, 0x12, 0xf9, 0x84, 0x17, 0xf0, 0x62, \ - 0x6f, 0x27, 0x3e, 0x13, 0x58, 0xb1, 0x54, 0x0d, 0x21, 0x9a, 0x73, 0x37, \ - 0xa1, 0x30, 0xcf, 0x6f, 0x92, 0xdc, 0xf6, 0xe9, 0xfc, 0xac, 0xdb, 0x2e, \ - 0x28, 0xd1, 0x7e, 0x02, 0x4b, 0x23, 0xa0, 0x15, 0xf2, 0x38, 0x65, 0x64, \ - 0x09, 0xea, 0x0c, 0x6e, 0x8e, 0x1b, 0x17, 0xa0, 0x71, 0xc8, 0xb3, 0x9b, \ - 0xc9, 0xab, 0xe9, 0xc3, 0xf2, 0xcf, 0x87, 0x96, 0x8f, 0x80, 0x02, 0x32, \ - 0x9e, 0x99, 0x58, 0x6f, 0xa2, 0xd5, 0x02, 0x03, 0x01, 0x00, 0x01, 0xa3, \ - 0x50, 0x30, 0x4e, 0x30, 0x0c, 0x06, 0x03, 0x55, 0x1d, 0x13, 0x04, 0x05, \ - 0x30, 0x03, 0x01, 0x01, 0xff, 0x30, 0x1d, 0x06, 0x03, 0x55, 0x1d, 0x0e, \ - 0x04, 0x16, 0x04, 0x14, 0xb4, 0x5a, 0xe4, 0xa5, 0xb3, 0xde, 0xd2, 0x52, \ - 0xf6, 0xb9, 0xd5, 0xa6, 0x95, 0x0f, 0xeb, 0x3e, 0xbc, 0xc7, 0xfd, 0xff, \ - 0x30, 0x1f, 0x06, 0x03, 0x55, 0x1d, 0x23, 0x04, 0x18, 0x30, 0x16, 0x80, \ - 0x14, 0xb4, 0x5a, 0xe4, 0xa5, 0xb3, 0xde, 0xd2, 0x52, 0xf6, 0xb9, 0xd5, \ - 0xa6, 0x95, 0x0f, 0xeb, 0x3e, 0xbc, 0xc7, 0xfd, 0xff, 0x30, 0x0d, 0x06, \ - 0x09, 0x2a, 0x86, 0x48, 0x86, 0xf7, 0x0d, 0x01, 0x01, 0x05, 0x05, 0x00, \ - 0x03, 0x82, 0x01, 0x01, 0x00, 0x01, 0x13, 0x73, 0x84, 0x3d, 0xf1, 0x1d, \ - 0xfd, 0xb7, 0x09, 0x5b, 0x96, 0x5d, 0x53, 0x7f, 0xd5, 0x80, 0xf3, 0x52, \ - 0xe2, 0xd3, 0x33, 0x87, 0xc8, 0x27, 0x24, 0xff, 0xd5, 0xd8, 0x57, 0x2f, \ - 0x16, 0xd1, 0xb2, 0x94, 0xca, 0x50, 0xab, 0xa6, 0x27, 0x10, 0x16, 0x08, \ - 0xc8, 0x11, 0xc0, 0x2f, 0x80, 0xd1, 0xbe, 0x53, 0x18, 0xe6, 0xb9, 0xd7, \ - 0x18, 0x1a, 0x77, 0x38, 0x34, 0x7c, 0x32, 0x9a, 0x87, 0x0b, 0xa0, 0x2a, \ - 0xb9, 0x14, 0xc2, 0x2f, 0x38, 0xd2, 0xe7, 0xb8, 0x98, 0x7d, 0xff, 0xff, \ - 0xe1, 0x01, 0x50, 0xa9, 0x6f, 0x67, 0xf7, 0x6c, 0xdc, 0xb6, 0xca, 0x6f, \ - 0x73, 0x39, 0x1a, 0x3c, 0xa8, 0x23, 0xaa, 0x8d, 0x4d, 0xa3, 0x75, 0x2a, \ - 0xd1, 0x76, 0xb3, 0xd7, 0x4a, 0xdc, 0xc7, 0x24, 0xd4, 0x3e, 0xb7, 0xf9, \ - 0xc0, 0xd5, 0x51, 0x67, 0x65, 0x74, 0x2a, 0xf9, 0x65, 0xbc, 0x00, 0x15, \ - 0x4b, 0x36, 0xc8, 0xe2, 0x6a, 0x5d, 0x51, 0x7c, 0xed, 0x8e, 0x14, 0x93, \ - 0x4b, 0x90, 0x36, 0x05, 0xe5, 0x90, 0x00, 0x03, 0xab, 0xd3, 0x3a, 0xb5, \ - 0x17, 0xb4, 0xd2, 0x45, 0x52, 0x69, 0x26, 0xce, 0xe3, 0x98, 0x1d, 0x9a, \ - 0x8b, 0xf8, 0xa0, 0x92, 0x1d, 0x48, 0x02, 0x37, 0x2e, 0xc1, 0x5e, 0x95, \ - 0xc2, 0x53, 0xfe, 0xb1, 0xbc, 0x34, 0x82, 0x34, 0x34, 0x36, 0x91, 0x8c, \ - 0x88, 0x7a, 0x67, 0x97, 0x34, 0x40, 0x8b, 0xfb, 0x48, 0x6e, 0xd3, 0xaf, \ - 0x30, 0x81, 0x8e, 0x05, 0x4d, 0x93, 0x21, 0xf6, 0xb1, 0xff, 0x98, 0xea, \ - 0xd5, 0xa8, 0x14, 0xc7, 0x96, 0x8f, 0x99, 0x3e, 0x53, 0x58, 0x08, 0x89, \ - 0x3c, 0xe3, 0x8f, 0xea, 0x5e, 0x71, 0x5e, 0x70, 0xf0, 0xc5, 0xe6, 0x12, \ - 0x35, 0x6a, 0xa2, 0x5f, 0xd1, 0xb2, 0xba, 0xc0, 0x59, 0x8d, 0xec, 0xda, \ - 0x09, 0xa1, 0xda, 0x6e, 0x30, 0xcb, 0x53, 0x4a, 0x90 \ -} -/* END FILE */ - -/* This is taken from tests/data_files/test-ca.key */ -/* BEGIN FILE string macro TEST_CA_KEY_RSA_PEM tests/data_files/test-ca.key */ -#define TEST_CA_KEY_RSA_PEM \ - "-----BEGIN RSA PRIVATE KEY-----\r\n" \ - "Proc-Type: 4,ENCRYPTED\r\n" \ - "AES-128-CBC,781840E6B804AE83D2AF71127C4CE314\r\n" \ - "\r\n" \ - "etQ3xgGLbuYF9vR1km03TH5fwfly1hOlix0PtfQ+t9HG065vTtSEHYc/OyHwdy79\r\n" \ - "NCLX5RUrPh06E/XlKzMNVHAXqkwFnIwNzRLsOozeP1L7iZEZb9QMeiN5Org+btCO\r\n" \ - "bylXPB4YirfuE7GSJalWY/pq3FQtD33zTIKmNhXfVj3sbwGI/8D9XjaKUb8PODOB\r\n" \ - "skOalmx6RvYRvg0lmRxB3+T3wejIsrrDPweYqte9B6dVHIVG1ZmvoA6/wnKZZZeV\r\n" \ - "sjj8OpL3OwUBrjuGSknE9Rs6kCuSCbHOYVK8VzcZmCYpie0TFnb3Sk8M6vjfW+45\r\n" \ - "U7WUMlSAPxKH6lJDzWdwHqLvsVJwuNnaAaBXg9/8U/rzQEWuq8Ar3s8fw2Jg3F1G\r\n" \ - "L6N5ZAEfCz3Sa0N9WKafR/RSQj+rq8Z3w4POAafhbzk249uo5K8B1Z3cQwLxeXIl\r\n" \ - "UbRQz1TZy4oNTfQzCahYruPNyvwgTkfwAFFvbLAdaiJd2ZtLBoqYE64TYakYnvcC\r\n" \ - "itim1bmySIKoxlMfBGFmMuF03epT0pSx701jlGzGi0l0m16NEjoVxDwo5j93SmiM\r\n" \ - "sQdjC1lOGk2iCLkphIQqHFjFJYWjvh1UUIqWZf+ZWOOxlf4x9a1pUVj6FvtECxNB\r\n" \ - "/mA/m4Iq4LAuVXHE1MpHeq067lJ6wWlrsb2WVmiNGfQ2AC7fMtpcPuunBVT9NV1m\r\n" \ - "1rbDzIgLIWAzqz/cy3N8Q8vfxnrFtmNUyM191Zyq+YF14hIKWX9J1qR4LXwWAzVV\r\n" \ - "UrC8IL4pA2mtRkW4qFsB0EmHAxO/cedDTPjVFty5WSzhNuvYZxX45HAkGIfK6d21\r\n" \ - "7WHPhHG+zaaUTWMUVixB0IcKp6RecjYPFzBHS0YeX88Ue2cyT/90jMiQ9ssOgRrG\r\n" \ - "ZJRJvZAc3TSCnY9sNPYoGrJPiZuCnlUj3ENNurYVy12ai0WFxwnNUZjRUhDS6hjm\r\n" \ - "cDHD5TlI9MZ6M+Mb/Bw4Ig8HuTHOtQBYD9vhtXsG+B7H/j6cS+1umaKjrnG/kK4W\r\n" \ - "R6YXwM2faAi+DwgjjoMXSzRqSTF8PdTIWbAXo3bc2qsXPTMBA8PEp4nb5scHZ4Ts\r\n" \ - "EcBNp2jv0j4gBkRmGIab17cWMrlagjFy89DhqZUFwKdeZs+yJ92A5xstWxOUfpEP\r\n" \ - "90T/bsp1G5d7WW5fl2TRJvYJNDM+djkKIh0zCkduiZ36oVM6nDdbjmXqjQXopeSD\r\n" \ - "gtOourBRF8g99W0fW8QT+yPhP0Pkyz6EG8eQO6Zwh439xdoVwu9jUzQAPmZ0uNeR\r\n" \ - "xTXXihYyv72z27rInjLiIPXL25K9eDVLlcSR3RyG7YYgjdQAL2VJDLcBz5jox1uQ\r\n" \ - "0guoD5wmfu2FWLqYE7HeTYntdY53lCflwq0GHRMjrrsVpx+5VDQ6Yi47Ny9SWLcp\r\n" \ - "fPI3iBkXuGRWupzs6N4pQdSO0dU28KfpMM5QvFoLIn67brCHEQij4dgFrCTYEyBX\r\n" \ - "9+jiNImUFYUhAFuxvUbfZt4O/ABLIElvHLfJs1oYCmI/nWpvLFqXB5rnzPNfEi0H\r\n" \ - "PGGe1Hj/t+CJIp/6ios3yNy2QtXO754TZH2UVu51Ykyig5PFjZVoUkbRvHQYcWfU\r\n" \ - "-----END RSA PRIVATE KEY-----\r\n" -/* END FILE */ - -#define TEST_CA_PWD_RSA_PEM "PolarSSLTest" - -/* This was generated from test-ca.key.der using `xxd -i`. */ -/* BEGIN FILE binary macro TEST_CA_KEY_RSA_DER tests/data_files/test-ca.key.der */ -#define TEST_CA_KEY_RSA_DER { \ - 0x30, 0x82, 0x04, 0xa4, 0x02, 0x01, 0x00, 0x02, 0x82, 0x01, 0x01, 0x00, \ - 0xc0, 0xdf, 0x37, 0xfc, 0x17, 0xbb, 0xe0, 0x96, 0x9d, 0x3f, 0x86, 0xde, \ - 0x96, 0x32, 0x7d, 0x44, 0xa5, 0x16, 0xa0, 0xcd, 0x21, 0xf1, 0x99, 0xd4, \ - 0xec, 0xea, 0xcb, 0x7c, 0x18, 0x58, 0x08, 0x94, 0xa5, 0xec, 0x9b, 0xc5, \ - 0x8b, 0xdf, 0x1a, 0x1e, 0x99, 0x38, 0x99, 0x87, 0x1e, 0x7b, 0xc0, 0x8d, \ - 0x39, 0xdf, 0x38, 0x5d, 0x70, 0x78, 0x07, 0xd3, 0x9e, 0xd9, 0x93, 0xe8, \ - 0xb9, 0x72, 0x51, 0xc5, 0xce, 0xa3, 0x30, 0x52, 0xa9, 0xf2, 0xe7, 0x40, \ - 0x70, 0x14, 0xcb, 0x44, 0xa2, 0x72, 0x0b, 0xc2, 0xe5, 0x40, 0xf9, 0x3e, \ - 0xe5, 0xa6, 0x0e, 0xb3, 0xf9, 0xec, 0x4a, 0x63, 0xc0, 0xb8, 0x29, 0x00, \ - 0x74, 0x9c, 0x57, 0x3b, 0xa8, 0xa5, 0x04, 0x90, 0x71, 0xf1, 0xbd, 0x83, \ - 0xd9, 0x3f, 0xd6, 0xa5, 0xe2, 0x3c, 0x2a, 0x8f, 0xef, 0x27, 0x60, 0xc3, \ - 0xc6, 0x9f, 0xcb, 0xba, 0xec, 0x60, 0x7d, 0xb7, 0xe6, 0x84, 0x32, 0xbe, \ - 0x4f, 0xfb, 0x58, 0x26, 0x22, 0x03, 0x5b, 0xd4, 0xb4, 0xd5, 0xfb, 0xf5, \ - 0xe3, 0x96, 0x2e, 0x70, 0xc0, 0xe4, 0x2e, 0xbd, 0xfc, 0x2e, 0xee, 0xe2, \ - 0x41, 0x55, 0xc0, 0x34, 0x2e, 0x7d, 0x24, 0x72, 0x69, 0xcb, 0x47, 0xb1, \ - 0x14, 0x40, 0x83, 0x7d, 0x67, 0xf4, 0x86, 0xf6, 0x31, 0xab, 0xf1, 0x79, \ - 0xa4, 0xb2, 0xb5, 0x2e, 0x12, 0xf9, 0x84, 0x17, 0xf0, 0x62, 0x6f, 0x27, \ - 0x3e, 0x13, 0x58, 0xb1, 0x54, 0x0d, 0x21, 0x9a, 0x73, 0x37, 0xa1, 0x30, \ - 0xcf, 0x6f, 0x92, 0xdc, 0xf6, 0xe9, 0xfc, 0xac, 0xdb, 0x2e, 0x28, 0xd1, \ - 0x7e, 0x02, 0x4b, 0x23, 0xa0, 0x15, 0xf2, 0x38, 0x65, 0x64, 0x09, 0xea, \ - 0x0c, 0x6e, 0x8e, 0x1b, 0x17, 0xa0, 0x71, 0xc8, 0xb3, 0x9b, 0xc9, 0xab, \ - 0xe9, 0xc3, 0xf2, 0xcf, 0x87, 0x96, 0x8f, 0x80, 0x02, 0x32, 0x9e, 0x99, \ - 0x58, 0x6f, 0xa2, 0xd5, 0x02, 0x03, 0x01, 0x00, 0x01, 0x02, 0x82, 0x01, \ - 0x00, 0x3f, 0xf7, 0x07, 0xd3, 0x34, 0x6f, 0xdb, 0xc9, 0x37, 0xb7, 0x84, \ - 0xdc, 0x37, 0x45, 0xe1, 0x63, 0xad, 0xb8, 0xb6, 0x75, 0xb1, 0xc7, 0x35, \ - 0xb4, 0x77, 0x2a, 0x5b, 0x77, 0xf9, 0x7e, 0xe0, 0xc1, 0xa3, 0xd1, 0xb7, \ - 0xcb, 0xa9, 0x5a, 0xc1, 0x87, 0xda, 0x5a, 0xfa, 0x17, 0xe4, 0xd5, 0x38, \ - 0x03, 0xde, 0x68, 0x98, 0x81, 0xec, 0xb5, 0xf2, 0x2a, 0x8d, 0xe9, 0x2c, \ - 0xf3, 0xa6, 0xe5, 0x32, 0x17, 0x7f, 0x33, 0x81, 0xe8, 0x38, 0x72, 0xd5, \ - 0x9c, 0xfa, 0x4e, 0xfb, 0x26, 0xf5, 0x15, 0x0b, 0xaf, 0x84, 0x66, 0xab, \ - 0x02, 0xe0, 0x18, 0xd5, 0x91, 0x7c, 0xd6, 0x8f, 0xc9, 0x4b, 0x76, 0x08, \ - 0x2b, 0x1d, 0x81, 0x68, 0x30, 0xe1, 0xfa, 0x70, 0x6c, 0x13, 0x4e, 0x10, \ - 0x03, 0x35, 0x3e, 0xc5, 0xca, 0x58, 0x20, 0x8a, 0x21, 0x18, 0x38, 0xa0, \ - 0x0f, 0xed, 0xc4, 0xbb, 0x45, 0x6f, 0xf5, 0x84, 0x5b, 0xb0, 0xcf, 0x4e, \ - 0x9d, 0x58, 0x13, 0x6b, 0x35, 0x35, 0x69, 0xa1, 0xd2, 0xc4, 0xf2, 0xc1, \ - 0x48, 0x04, 0x20, 0x51, 0xb9, 0x6b, 0xa4, 0x5d, 0xa5, 0x4b, 0x84, 0x88, \ - 0x43, 0x48, 0x99, 0x2c, 0xbb, 0xa4, 0x97, 0xd6, 0xd6, 0x18, 0xf6, 0xec, \ - 0x5c, 0xd1, 0x31, 0x49, 0xc9, 0xf2, 0x8f, 0x0b, 0x4d, 0xef, 0x09, 0x02, \ - 0xfe, 0x7d, 0xfd, 0xbb, 0xaf, 0x2b, 0x83, 0x94, 0x22, 0xc4, 0xa7, 0x3e, \ - 0x66, 0xf5, 0xe0, 0x57, 0xdc, 0xf2, 0xed, 0x2c, 0x3e, 0x81, 0x74, 0x76, \ - 0x1e, 0x96, 0x6f, 0x74, 0x1e, 0x32, 0x0e, 0x14, 0x31, 0xd0, 0x74, 0xf0, \ - 0xf4, 0x07, 0xbd, 0xc3, 0xd1, 0x22, 0xc2, 0xa8, 0x95, 0x92, 0x06, 0x7f, \ - 0x43, 0x02, 0x91, 0xbc, 0xdd, 0x23, 0x01, 0x89, 0x94, 0x20, 0x44, 0x64, \ - 0xf5, 0x1d, 0x67, 0xd2, 0x8f, 0xe8, 0x69, 0xa5, 0x29, 0x25, 0xe6, 0x50, \ - 0x9c, 0xe3, 0xe9, 0xcb, 0x75, 0x02, 0x81, 0x81, 0x00, 0xe2, 0x29, 0x3e, \ - 0xaa, 0x6b, 0xd5, 0x59, 0x1e, 0x9c, 0xe6, 0x47, 0xd5, 0xb6, 0xd7, 0xe3, \ - 0xf1, 0x8e, 0x9e, 0xe9, 0x83, 0x5f, 0x10, 0x9f, 0x63, 0xec, 0x04, 0x44, \ - 0xcc, 0x3f, 0xf8, 0xd9, 0x3a, 0x17, 0xe0, 0x4f, 0xfe, 0xd8, 0x4d, 0xcd, \ - 0x46, 0x54, 0x74, 0xbf, 0x0a, 0xc4, 0x67, 0x9c, 0xa7, 0xd8, 0x89, 0x65, \ - 0x4c, 0xfd, 0x58, 0x2a, 0x47, 0x0f, 0xf4, 0x37, 0xb6, 0x55, 0xb0, 0x1d, \ - 0xed, 0xa7, 0x39, 0xfc, 0x4f, 0xa3, 0xc4, 0x75, 0x3a, 0xa3, 0x98, 0xa7, \ - 0x45, 0xf5, 0x66, 0xcb, 0x7c, 0x65, 0xfb, 0x80, 0x23, 0xe6, 0xff, 0xfd, \ - 0x99, 0x1f, 0x8e, 0x6b, 0xff, 0x5e, 0x93, 0x66, 0xdf, 0x6c, 0x6f, 0xc3, \ - 0xf6, 0x38, 0x2e, 0xff, 0x69, 0xb5, 0xac, 0xae, 0xbb, 0xc6, 0x71, 0x16, \ - 0x6b, 0xd0, 0xf8, 0x22, 0xd9, 0xf8, 0xa2, 0x72, 0x20, 0xd2, 0xe2, 0x3a, \ - 0x70, 0x4b, 0xde, 0xab, 0x2f, 0x02, 0x81, 0x81, 0x00, 0xda, 0x51, 0x9b, \ - 0xb8, 0xb2, 0x2a, 0x14, 0x75, 0x58, 0x40, 0x8d, 0x27, 0x70, 0xfa, 0x31, \ - 0x48, 0xb0, 0x20, 0x21, 0x34, 0xfa, 0x4c, 0x57, 0xa8, 0x11, 0x88, 0xf3, \ - 0xa7, 0xae, 0x21, 0xe9, 0xb6, 0x2b, 0xd1, 0xcd, 0xa7, 0xf8, 0xd8, 0x0c, \ - 0x8a, 0x76, 0x22, 0x35, 0x44, 0xce, 0x3f, 0x25, 0x29, 0x83, 0x7d, 0x79, \ - 0xa7, 0x31, 0xd6, 0xec, 0xb2, 0xbf, 0xda, 0x34, 0xb6, 0xf6, 0xb2, 0x3b, \ - 0xf3, 0x78, 0x5a, 0x04, 0x83, 0x33, 0x3e, 0xa2, 0xe2, 0x81, 0x82, 0x13, \ - 0xd4, 0x35, 0x17, 0x63, 0x9b, 0x9e, 0xc4, 0x8d, 0x91, 0x4c, 0x03, 0x77, \ - 0xc7, 0x71, 0x5b, 0xee, 0x83, 0x6d, 0xd5, 0x78, 0x88, 0xf6, 0x2c, 0x79, \ - 0xc2, 0x4a, 0xb4, 0x79, 0x90, 0x70, 0xbf, 0xdf, 0x34, 0x56, 0x96, 0x71, \ - 0xe3, 0x0e, 0x68, 0x91, 0xbc, 0xea, 0xcb, 0x33, 0xc0, 0xbe, 0x45, 0xd7, \ - 0xfc, 0x30, 0xfd, 0x01, 0x3b, 0x02, 0x81, 0x81, 0x00, 0xd2, 0x9f, 0x2a, \ - 0xb7, 0x38, 0x19, 0xc7, 0x17, 0x95, 0x73, 0x78, 0xae, 0xf5, 0xcb, 0x75, \ - 0x83, 0x7f, 0x19, 0x4b, 0xcb, 0x86, 0xfb, 0x4a, 0x15, 0x9a, 0xb6, 0x17, \ - 0x04, 0x49, 0x07, 0x8d, 0xf6, 0x66, 0x4a, 0x06, 0xf6, 0x05, 0xa7, 0xdf, \ - 0x66, 0x82, 0x3c, 0xff, 0xb6, 0x1d, 0x57, 0x89, 0x33, 0x5f, 0x9c, 0x05, \ - 0x75, 0x7f, 0xf3, 0x5d, 0xdc, 0x34, 0x65, 0x72, 0x85, 0x22, 0xa4, 0x14, \ - 0x1b, 0x41, 0xc3, 0xe4, 0xd0, 0x9e, 0x69, 0xd5, 0xeb, 0x38, 0x74, 0x70, \ - 0x43, 0xdc, 0xd9, 0x50, 0xe4, 0x97, 0x6d, 0x73, 0xd6, 0xfb, 0xc8, 0xa7, \ - 0xfa, 0xb4, 0xc2, 0xc4, 0x9d, 0x5d, 0x0c, 0xd5, 0x9f, 0x79, 0xb3, 0x54, \ - 0xc2, 0xb7, 0x6c, 0x3d, 0x7d, 0xcb, 0x2d, 0xf8, 0xc4, 0xf3, 0x78, 0x5a, \ - 0x33, 0x2a, 0xb8, 0x0c, 0x6d, 0x06, 0xfa, 0xf2, 0x62, 0xd3, 0x42, 0xd0, \ - 0xbd, 0xc8, 0x4a, 0xa5, 0x0d, 0x02, 0x81, 0x81, 0x00, 0xd4, 0xa9, 0x90, \ - 0x15, 0xde, 0xbf, 0x2c, 0xc4, 0x8d, 0x9d, 0xfb, 0xa1, 0xc2, 0xe4, 0x83, \ - 0xe3, 0x79, 0x65, 0x22, 0xd3, 0xb7, 0x49, 0x6c, 0x4d, 0x94, 0x1f, 0x22, \ - 0xb1, 0x60, 0xe7, 0x3a, 0x00, 0xb1, 0x38, 0xa2, 0xab, 0x0f, 0xb4, 0x6c, \ - 0xaa, 0xe7, 0x9e, 0x34, 0xe3, 0x7c, 0x40, 0x78, 0x53, 0xb2, 0xf9, 0x23, \ - 0xea, 0xa0, 0x9a, 0xea, 0x60, 0xc8, 0x8f, 0xa6, 0xaf, 0xdf, 0x29, 0x09, \ - 0x4b, 0x06, 0x1e, 0x31, 0xad, 0x17, 0xda, 0xd8, 0xd1, 0xe9, 0x33, 0xab, \ - 0x5b, 0x18, 0x08, 0x5b, 0x87, 0xf8, 0xa5, 0x1f, 0xfd, 0xbb, 0xdc, 0xd8, \ - 0xed, 0x97, 0x57, 0xe4, 0xc3, 0x73, 0xd6, 0xf0, 0x9e, 0x01, 0xa6, 0x9b, \ - 0x48, 0x8e, 0x7a, 0xb4, 0xbb, 0xe5, 0x88, 0x91, 0xc5, 0x2a, 0xdf, 0x4b, \ - 0xba, 0xd0, 0x8b, 0x3e, 0x03, 0x97, 0x77, 0x2f, 0x47, 0x7e, 0x51, 0x0c, \ - 0xae, 0x65, 0x8d, 0xde, 0x87, 0x02, 0x81, 0x80, 0x20, 0x24, 0x0f, 0xd2, \ - 0xaf, 0xc2, 0x28, 0x3b, 0x97, 0x20, 0xb2, 0x92, 0x49, 0xeb, 0x09, 0x68, \ - 0x40, 0xb2, 0xbe, 0xd1, 0xc3, 0x83, 0x94, 0x34, 0x38, 0xd6, 0xc9, 0xec, \ - 0x34, 0x09, 0xf9, 0x41, 0x6d, 0x5c, 0x42, 0x94, 0xf7, 0x04, 0xfc, 0x32, \ - 0x39, 0x69, 0xbc, 0x1c, 0xfb, 0x3e, 0x61, 0x98, 0xc0, 0x80, 0xd8, 0x36, \ - 0x47, 0xc3, 0x6d, 0xc2, 0x2e, 0xe7, 0x81, 0x2a, 0x17, 0x34, 0x64, 0x30, \ - 0x4e, 0x96, 0xbb, 0x26, 0x16, 0xb9, 0x41, 0x36, 0xfe, 0x8a, 0xd6, 0x53, \ - 0x7c, 0xaa, 0xec, 0x39, 0x42, 0x50, 0xef, 0xe3, 0xb3, 0x01, 0x28, 0x32, \ - 0xca, 0x6d, 0xf5, 0x9a, 0x1e, 0x9f, 0x37, 0xbe, 0xfe, 0x38, 0x20, 0x22, \ - 0x91, 0x8c, 0xcd, 0x95, 0x02, 0xf2, 0x4d, 0x6f, 0x1a, 0xb4, 0x43, 0xf0, \ - 0x19, 0xdf, 0x65, 0xc0, 0x92, 0xe7, 0x9d, 0x2f, 0x09, 0xe7, 0xec, 0x69, \ - 0xa8, 0xc2, 0x8f, 0x0d \ -} -/* END FILE */ - -/* - * Test server Certificates - * - * Test server certificates are defined for each choice - * of the following parameters: - * - PEM or DER encoding - * - SHA-1 or SHA-256 hash - * - RSA or EC key - * - * Things to add: - * - multiple EC curve types - */ - -/* This is taken from tests/data_files/server5.crt. */ -/* BEGIN FILE string macro TEST_SRV_CRT_EC_PEM tests/data_files/server5.crt */ -#define TEST_SRV_CRT_EC_PEM \ - "-----BEGIN CERTIFICATE-----\r\n" \ - "MIICHzCCAaWgAwIBAgIBCTAKBggqhkjOPQQDAjA+MQswCQYDVQQGEwJOTDERMA8G\r\n" \ - "A1UECgwIUG9sYXJTU0wxHDAaBgNVBAMME1BvbGFyc3NsIFRlc3QgRUMgQ0EwHhcN\r\n" \ - "MjMwNjE1MDMzNDE4WhcNMzMwNjEyMDMzNDE4WjA0MQswCQYDVQQGEwJOTDERMA8G\r\n" \ - "A1UECgwIUG9sYXJTU0wxEjAQBgNVBAMMCWxvY2FsaG9zdDBZMBMGByqGSM49AgEG\r\n" \ - "CCqGSM49AwEHA0IABDfMVtl2CR5acj7HWS3/IG7ufPkGkXTQrRS192giWWKSTuUA\r\n" \ - "2CMR/+ov0jRdXRa9iojCa3cNVc2KKg76Aci07f+jgZ0wgZowCQYDVR0TBAIwADAd\r\n" \ - "BgNVHQ4EFgQUUGGlj9QH2deCAQzlZX+MY0anE74wbgYDVR0jBGcwZYAUnW0gJEkB\r\n" \ - "PyvLeLUZvH4kydv7NnyhQqRAMD4xCzAJBgNVBAYTAk5MMREwDwYDVQQKDAhQb2xh\r\n" \ - "clNTTDEcMBoGA1UEAwwTUG9sYXJzc2wgVGVzdCBFQyBDQYIJAMFD4n5iQ8zoMAoG\r\n" \ - "CCqGSM49BAMCA2gAMGUCMAHFbGEzx8dZaUlIltT5s1QO9FvKmvFer4uRY3ntEy9S\r\n" \ - "k7DCCozM86WWLjfzbJ78bwIxAJYRPF1CzNEiXPHb9O46ZPHKo2S5x//g/54RowAK\r\n" \ - "uZz+hKPuMi6YY6cIm81jfeaSZQ==\r\n" \ - "-----END CERTIFICATE-----\r\n" -/* END FILE */ - -/* This is generated from tests/data_files/server5.crt.der using `xxd -i`. */ -/* BEGIN FILE binary macro TEST_SRV_CRT_EC_DER tests/data_files/server5.crt.der */ -#define TEST_SRV_CRT_EC_DER { \ - 0x30, 0x82, 0x02, 0x1f, 0x30, 0x82, 0x01, 0xa5, 0xa0, 0x03, 0x02, 0x01, \ - 0x02, 0x02, 0x01, 0x09, 0x30, 0x0a, 0x06, 0x08, 0x2a, 0x86, 0x48, 0xce, \ - 0x3d, 0x04, 0x03, 0x02, 0x30, 0x3e, 0x31, 0x0b, 0x30, 0x09, 0x06, 0x03, \ - 0x55, 0x04, 0x06, 0x13, 0x02, 0x4e, 0x4c, 0x31, 0x11, 0x30, 0x0f, 0x06, \ - 0x03, 0x55, 0x04, 0x0a, 0x0c, 0x08, 0x50, 0x6f, 0x6c, 0x61, 0x72, 0x53, \ - 0x53, 0x4c, 0x31, 0x1c, 0x30, 0x1a, 0x06, 0x03, 0x55, 0x04, 0x03, 0x0c, \ - 0x13, 0x50, 0x6f, 0x6c, 0x61, 0x72, 0x73, 0x73, 0x6c, 0x20, 0x54, 0x65, \ - 0x73, 0x74, 0x20, 0x45, 0x43, 0x20, 0x43, 0x41, 0x30, 0x1e, 0x17, 0x0d, \ - 0x32, 0x33, 0x30, 0x36, 0x31, 0x35, 0x30, 0x33, 0x33, 0x34, 0x31, 0x38, \ - 0x5a, 0x17, 0x0d, 0x33, 0x33, 0x30, 0x36, 0x31, 0x32, 0x30, 0x33, 0x33, \ - 0x34, 0x31, 0x38, 0x5a, 0x30, 0x34, 0x31, 0x0b, 0x30, 0x09, 0x06, 0x03, \ - 0x55, 0x04, 0x06, 0x13, 0x02, 0x4e, 0x4c, 0x31, 0x11, 0x30, 0x0f, 0x06, \ - 0x03, 0x55, 0x04, 0x0a, 0x0c, 0x08, 0x50, 0x6f, 0x6c, 0x61, 0x72, 0x53, \ - 0x53, 0x4c, 0x31, 0x12, 0x30, 0x10, 0x06, 0x03, 0x55, 0x04, 0x03, 0x0c, \ - 0x09, 0x6c, 0x6f, 0x63, 0x61, 0x6c, 0x68, 0x6f, 0x73, 0x74, 0x30, 0x59, \ - 0x30, 0x13, 0x06, 0x07, 0x2a, 0x86, 0x48, 0xce, 0x3d, 0x02, 0x01, 0x06, \ - 0x08, 0x2a, 0x86, 0x48, 0xce, 0x3d, 0x03, 0x01, 0x07, 0x03, 0x42, 0x00, \ - 0x04, 0x37, 0xcc, 0x56, 0xd9, 0x76, 0x09, 0x1e, 0x5a, 0x72, 0x3e, 0xc7, \ - 0x59, 0x2d, 0xff, 0x20, 0x6e, 0xee, 0x7c, 0xf9, 0x06, 0x91, 0x74, 0xd0, \ - 0xad, 0x14, 0xb5, 0xf7, 0x68, 0x22, 0x59, 0x62, 0x92, 0x4e, 0xe5, 0x00, \ - 0xd8, 0x23, 0x11, 0xff, 0xea, 0x2f, 0xd2, 0x34, 0x5d, 0x5d, 0x16, 0xbd, \ - 0x8a, 0x88, 0xc2, 0x6b, 0x77, 0x0d, 0x55, 0xcd, 0x8a, 0x2a, 0x0e, 0xfa, \ - 0x01, 0xc8, 0xb4, 0xed, 0xff, 0xa3, 0x81, 0x9d, 0x30, 0x81, 0x9a, 0x30, \ - 0x09, 0x06, 0x03, 0x55, 0x1d, 0x13, 0x04, 0x02, 0x30, 0x00, 0x30, 0x1d, \ - 0x06, 0x03, 0x55, 0x1d, 0x0e, 0x04, 0x16, 0x04, 0x14, 0x50, 0x61, 0xa5, \ - 0x8f, 0xd4, 0x07, 0xd9, 0xd7, 0x82, 0x01, 0x0c, 0xe5, 0x65, 0x7f, 0x8c, \ - 0x63, 0x46, 0xa7, 0x13, 0xbe, 0x30, 0x6e, 0x06, 0x03, 0x55, 0x1d, 0x23, \ - 0x04, 0x67, 0x30, 0x65, 0x80, 0x14, 0x9d, 0x6d, 0x20, 0x24, 0x49, 0x01, \ - 0x3f, 0x2b, 0xcb, 0x78, 0xb5, 0x19, 0xbc, 0x7e, 0x24, 0xc9, 0xdb, 0xfb, \ - 0x36, 0x7c, 0xa1, 0x42, 0xa4, 0x40, 0x30, 0x3e, 0x31, 0x0b, 0x30, 0x09, \ - 0x06, 0x03, 0x55, 0x04, 0x06, 0x13, 0x02, 0x4e, 0x4c, 0x31, 0x11, 0x30, \ - 0x0f, 0x06, 0x03, 0x55, 0x04, 0x0a, 0x0c, 0x08, 0x50, 0x6f, 0x6c, 0x61, \ - 0x72, 0x53, 0x53, 0x4c, 0x31, 0x1c, 0x30, 0x1a, 0x06, 0x03, 0x55, 0x04, \ - 0x03, 0x0c, 0x13, 0x50, 0x6f, 0x6c, 0x61, 0x72, 0x73, 0x73, 0x6c, 0x20, \ - 0x54, 0x65, 0x73, 0x74, 0x20, 0x45, 0x43, 0x20, 0x43, 0x41, 0x82, 0x09, \ - 0x00, 0xc1, 0x43, 0xe2, 0x7e, 0x62, 0x43, 0xcc, 0xe8, 0x30, 0x0a, 0x06, \ - 0x08, 0x2a, 0x86, 0x48, 0xce, 0x3d, 0x04, 0x03, 0x02, 0x03, 0x68, 0x00, \ - 0x30, 0x65, 0x02, 0x30, 0x01, 0xc5, 0x6c, 0x61, 0x33, 0xc7, 0xc7, 0x59, \ - 0x69, 0x49, 0x48, 0x96, 0xd4, 0xf9, 0xb3, 0x54, 0x0e, 0xf4, 0x5b, 0xca, \ - 0x9a, 0xf1, 0x5e, 0xaf, 0x8b, 0x91, 0x63, 0x79, 0xed, 0x13, 0x2f, 0x52, \ - 0x93, 0xb0, 0xc2, 0x0a, 0x8c, 0xcc, 0xf3, 0xa5, 0x96, 0x2e, 0x37, 0xf3, \ - 0x6c, 0x9e, 0xfc, 0x6f, 0x02, 0x31, 0x00, 0x96, 0x11, 0x3c, 0x5d, 0x42, \ - 0xcc, 0xd1, 0x22, 0x5c, 0xf1, 0xdb, 0xf4, 0xee, 0x3a, 0x64, 0xf1, 0xca, \ - 0xa3, 0x64, 0xb9, 0xc7, 0xff, 0xe0, 0xff, 0x9e, 0x11, 0xa3, 0x00, 0x0a, \ - 0xb9, 0x9c, 0xfe, 0x84, 0xa3, 0xee, 0x32, 0x2e, 0x98, 0x63, 0xa7, 0x08, \ - 0x9b, 0xcd, 0x63, 0x7d, 0xe6, 0x92, 0x65 \ -} -/* END FILE */ - -/* This is taken from tests/data_files/server5.key. */ -/* BEGIN FILE string macro TEST_SRV_KEY_EC_PEM tests/data_files/server5.key */ -#define TEST_SRV_KEY_EC_PEM \ - "-----BEGIN EC PRIVATE KEY-----\r\n" \ - "MHcCAQEEIPEqEyB2AnCoPL/9U/YDHvdqXYbIogTywwyp6/UfDw6noAoGCCqGSM49\r\n" \ - "AwEHoUQDQgAEN8xW2XYJHlpyPsdZLf8gbu58+QaRdNCtFLX3aCJZYpJO5QDYIxH/\r\n" \ - "6i/SNF1dFr2KiMJrdw1VzYoqDvoByLTt/w==\r\n" \ - "-----END EC PRIVATE KEY-----\r\n" -/* END FILE */ - -/* This is generated from tests/data_files/server5.key.der using `xxd -i`. */ -/* BEGIN FILE binary macro TEST_SRV_KEY_EC_DER tests/data_files/server5.key.der */ -#define TEST_SRV_KEY_EC_DER { \ - 0x30, 0x77, 0x02, 0x01, 0x01, 0x04, 0x20, 0xf1, 0x2a, 0x13, 0x20, 0x76, \ - 0x02, 0x70, 0xa8, 0x3c, 0xbf, 0xfd, 0x53, 0xf6, 0x03, 0x1e, 0xf7, 0x6a, \ - 0x5d, 0x86, 0xc8, 0xa2, 0x04, 0xf2, 0xc3, 0x0c, 0xa9, 0xeb, 0xf5, 0x1f, \ - 0x0f, 0x0e, 0xa7, 0xa0, 0x0a, 0x06, 0x08, 0x2a, 0x86, 0x48, 0xce, 0x3d, \ - 0x03, 0x01, 0x07, 0xa1, 0x44, 0x03, 0x42, 0x00, 0x04, 0x37, 0xcc, 0x56, \ - 0xd9, 0x76, 0x09, 0x1e, 0x5a, 0x72, 0x3e, 0xc7, 0x59, 0x2d, 0xff, 0x20, \ - 0x6e, 0xee, 0x7c, 0xf9, 0x06, 0x91, 0x74, 0xd0, 0xad, 0x14, 0xb5, 0xf7, \ - 0x68, 0x22, 0x59, 0x62, 0x92, 0x4e, 0xe5, 0x00, 0xd8, 0x23, 0x11, 0xff, \ - 0xea, 0x2f, 0xd2, 0x34, 0x5d, 0x5d, 0x16, 0xbd, 0x8a, 0x88, 0xc2, 0x6b, \ - 0x77, 0x0d, 0x55, 0xcd, 0x8a, 0x2a, 0x0e, 0xfa, 0x01, 0xc8, 0xb4, 0xed, \ - 0xff \ -} -/* END FILE */ - -/* This is taken from tests/data_files/server2-sha256.crt. */ -/* BEGIN FILE string macro TEST_SRV_CRT_RSA_SHA256_PEM tests/data_files/server2-sha256.crt */ -#define TEST_SRV_CRT_RSA_SHA256_PEM \ - "-----BEGIN CERTIFICATE-----\r\n" \ - "MIIDNzCCAh+gAwIBAgIBAjANBgkqhkiG9w0BAQsFADA7MQswCQYDVQQGEwJOTDER\r\n" \ - "MA8GA1UECgwIUG9sYXJTU0wxGTAXBgNVBAMMEFBvbGFyU1NMIFRlc3QgQ0EwHhcN\r\n" \ - "MTkwMjEwMTQ0NDA2WhcNMjkwMjEwMTQ0NDA2WjA0MQswCQYDVQQGEwJOTDERMA8G\r\n" \ - "A1UECgwIUG9sYXJTU0wxEjAQBgNVBAMMCWxvY2FsaG9zdDCCASIwDQYJKoZIhvcN\r\n" \ - "AQEBBQADggEPADCCAQoCggEBAMFNo93nzR3RBNdJcriZrA545Do8Ss86ExbQWuTN\r\n" \ - "owCIp+4ea5anUrSQ7y1yej4kmvy2NKwk9XfgJmSMnLAofaHa6ozmyRyWvP7BBFKz\r\n" \ - "NtSj+uGxdtiQwWG0ZlI2oiZTqqt0Xgd9GYLbKtgfoNkNHC1JZvdbJXNG6AuKT2kM\r\n" \ - "tQCQ4dqCEGZ9rlQri2V5kaHiYcPNQEkI7mgM8YuG0ka/0LiqEQMef1aoGh5EGA8P\r\n" \ - "hYvai0Re4hjGYi/HZo36Xdh98yeJKQHFkA4/J/EwyEoO79bex8cna8cFPXrEAjya\r\n" \ - "HT4P6DSYW8tzS1KW2BGiLICIaTla0w+w3lkvEcf36hIBMJcCAwEAAaNNMEswCQYD\r\n" \ - "VR0TBAIwADAdBgNVHQ4EFgQUpQXoZLjc32APUBJNYKhkr02LQ5MwHwYDVR0jBBgw\r\n" \ - "FoAUtFrkpbPe0lL2udWmlQ/rPrzH/f8wDQYJKoZIhvcNAQELBQADggEBAC465FJh\r\n" \ - "Pqel7zJngHIHJrqj/wVAxGAFOTF396XKATGAp+HRCqJ81Ry60CNK1jDzk8dv6M6U\r\n" \ - "HoS7RIFiM/9rXQCbJfiPD5xMTejZp5n5UYHAmxsxDaazfA5FuBhkfokKK6jD4Eq9\r\n" \ - "1C94xGKb6X4/VkaPF7cqoBBw/bHxawXc0UEPjqayiBpCYU/rJoVZgLqFVP7Px3sv\r\n" \ - "a1nOrNx8rPPI1hJ+ZOg8maiPTxHZnBVLakSSLQy/sWeWyazO1RnrbxjrbgQtYKz0\r\n" \ - "e3nwGpu1w13vfckFmUSBhHXH7AAS/HpKC4IH7G2GAk3+n8iSSN71sZzpxonQwVbo\r\n" \ - "pMZqLmbBm/7WPLc=\r\n" \ - "-----END CERTIFICATE-----\r\n" -/* END FILE */ - -/* This is taken from tests/data_files/server2-sha256.crt.der. */ -/* BEGIN FILE binary macro TEST_SRV_CRT_RSA_SHA256_DER tests/data_files/server2-sha256.crt.der */ -#define TEST_SRV_CRT_RSA_SHA256_DER { \ - 0x30, 0x82, 0x03, 0x37, 0x30, 0x82, 0x02, 0x1f, 0xa0, 0x03, 0x02, 0x01, \ - 0x02, 0x02, 0x01, 0x02, 0x30, 0x0d, 0x06, 0x09, 0x2a, 0x86, 0x48, 0x86, \ - 0xf7, 0x0d, 0x01, 0x01, 0x0b, 0x05, 0x00, 0x30, 0x3b, 0x31, 0x0b, 0x30, \ - 0x09, 0x06, 0x03, 0x55, 0x04, 0x06, 0x13, 0x02, 0x4e, 0x4c, 0x31, 0x11, \ - 0x30, 0x0f, 0x06, 0x03, 0x55, 0x04, 0x0a, 0x0c, 0x08, 0x50, 0x6f, 0x6c, \ - 0x61, 0x72, 0x53, 0x53, 0x4c, 0x31, 0x19, 0x30, 0x17, 0x06, 0x03, 0x55, \ - 0x04, 0x03, 0x0c, 0x10, 0x50, 0x6f, 0x6c, 0x61, 0x72, 0x53, 0x53, 0x4c, \ - 0x20, 0x54, 0x65, 0x73, 0x74, 0x20, 0x43, 0x41, 0x30, 0x1e, 0x17, 0x0d, \ - 0x31, 0x39, 0x30, 0x32, 0x31, 0x30, 0x31, 0x34, 0x34, 0x34, 0x30, 0x36, \ - 0x5a, 0x17, 0x0d, 0x32, 0x39, 0x30, 0x32, 0x31, 0x30, 0x31, 0x34, 0x34, \ - 0x34, 0x30, 0x36, 0x5a, 0x30, 0x34, 0x31, 0x0b, 0x30, 0x09, 0x06, 0x03, \ - 0x55, 0x04, 0x06, 0x13, 0x02, 0x4e, 0x4c, 0x31, 0x11, 0x30, 0x0f, 0x06, \ - 0x03, 0x55, 0x04, 0x0a, 0x0c, 0x08, 0x50, 0x6f, 0x6c, 0x61, 0x72, 0x53, \ - 0x53, 0x4c, 0x31, 0x12, 0x30, 0x10, 0x06, 0x03, 0x55, 0x04, 0x03, 0x0c, \ - 0x09, 0x6c, 0x6f, 0x63, 0x61, 0x6c, 0x68, 0x6f, 0x73, 0x74, 0x30, 0x82, \ - 0x01, 0x22, 0x30, 0x0d, 0x06, 0x09, 0x2a, 0x86, 0x48, 0x86, 0xf7, 0x0d, \ - 0x01, 0x01, 0x01, 0x05, 0x00, 0x03, 0x82, 0x01, 0x0f, 0x00, 0x30, 0x82, \ - 0x01, 0x0a, 0x02, 0x82, 0x01, 0x01, 0x00, 0xc1, 0x4d, 0xa3, 0xdd, 0xe7, \ - 0xcd, 0x1d, 0xd1, 0x04, 0xd7, 0x49, 0x72, 0xb8, 0x99, 0xac, 0x0e, 0x78, \ - 0xe4, 0x3a, 0x3c, 0x4a, 0xcf, 0x3a, 0x13, 0x16, 0xd0, 0x5a, 0xe4, 0xcd, \ - 0xa3, 0x00, 0x88, 0xa7, 0xee, 0x1e, 0x6b, 0x96, 0xa7, 0x52, 0xb4, 0x90, \ - 0xef, 0x2d, 0x72, 0x7a, 0x3e, 0x24, 0x9a, 0xfc, 0xb6, 0x34, 0xac, 0x24, \ - 0xf5, 0x77, 0xe0, 0x26, 0x64, 0x8c, 0x9c, 0xb0, 0x28, 0x7d, 0xa1, 0xda, \ - 0xea, 0x8c, 0xe6, 0xc9, 0x1c, 0x96, 0xbc, 0xfe, 0xc1, 0x04, 0x52, 0xb3, \ - 0x36, 0xd4, 0xa3, 0xfa, 0xe1, 0xb1, 0x76, 0xd8, 0x90, 0xc1, 0x61, 0xb4, \ - 0x66, 0x52, 0x36, 0xa2, 0x26, 0x53, 0xaa, 0xab, 0x74, 0x5e, 0x07, 0x7d, \ - 0x19, 0x82, 0xdb, 0x2a, 0xd8, 0x1f, 0xa0, 0xd9, 0x0d, 0x1c, 0x2d, 0x49, \ - 0x66, 0xf7, 0x5b, 0x25, 0x73, 0x46, 0xe8, 0x0b, 0x8a, 0x4f, 0x69, 0x0c, \ - 0xb5, 0x00, 0x90, 0xe1, 0xda, 0x82, 0x10, 0x66, 0x7d, 0xae, 0x54, 0x2b, \ - 0x8b, 0x65, 0x79, 0x91, 0xa1, 0xe2, 0x61, 0xc3, 0xcd, 0x40, 0x49, 0x08, \ - 0xee, 0x68, 0x0c, 0xf1, 0x8b, 0x86, 0xd2, 0x46, 0xbf, 0xd0, 0xb8, 0xaa, \ - 0x11, 0x03, 0x1e, 0x7f, 0x56, 0xa8, 0x1a, 0x1e, 0x44, 0x18, 0x0f, 0x0f, \ - 0x85, 0x8b, 0xda, 0x8b, 0x44, 0x5e, 0xe2, 0x18, 0xc6, 0x62, 0x2f, 0xc7, \ - 0x66, 0x8d, 0xfa, 0x5d, 0xd8, 0x7d, 0xf3, 0x27, 0x89, 0x29, 0x01, 0xc5, \ - 0x90, 0x0e, 0x3f, 0x27, 0xf1, 0x30, 0xc8, 0x4a, 0x0e, 0xef, 0xd6, 0xde, \ - 0xc7, 0xc7, 0x27, 0x6b, 0xc7, 0x05, 0x3d, 0x7a, 0xc4, 0x02, 0x3c, 0x9a, \ - 0x1d, 0x3e, 0x0f, 0xe8, 0x34, 0x98, 0x5b, 0xcb, 0x73, 0x4b, 0x52, 0x96, \ - 0xd8, 0x11, 0xa2, 0x2c, 0x80, 0x88, 0x69, 0x39, 0x5a, 0xd3, 0x0f, 0xb0, \ - 0xde, 0x59, 0x2f, 0x11, 0xc7, 0xf7, 0xea, 0x12, 0x01, 0x30, 0x97, 0x02, \ - 0x03, 0x01, 0x00, 0x01, 0xa3, 0x4d, 0x30, 0x4b, 0x30, 0x09, 0x06, 0x03, \ - 0x55, 0x1d, 0x13, 0x04, 0x02, 0x30, 0x00, 0x30, 0x1d, 0x06, 0x03, 0x55, \ - 0x1d, 0x0e, 0x04, 0x16, 0x04, 0x14, 0xa5, 0x05, 0xe8, 0x64, 0xb8, 0xdc, \ - 0xdf, 0x60, 0x0f, 0x50, 0x12, 0x4d, 0x60, 0xa8, 0x64, 0xaf, 0x4d, 0x8b, \ - 0x43, 0x93, 0x30, 0x1f, 0x06, 0x03, 0x55, 0x1d, 0x23, 0x04, 0x18, 0x30, \ - 0x16, 0x80, 0x14, 0xb4, 0x5a, 0xe4, 0xa5, 0xb3, 0xde, 0xd2, 0x52, 0xf6, \ - 0xb9, 0xd5, 0xa6, 0x95, 0x0f, 0xeb, 0x3e, 0xbc, 0xc7, 0xfd, 0xff, 0x30, \ - 0x0d, 0x06, 0x09, 0x2a, 0x86, 0x48, 0x86, 0xf7, 0x0d, 0x01, 0x01, 0x0b, \ - 0x05, 0x00, 0x03, 0x82, 0x01, 0x01, 0x00, 0x2e, 0x3a, 0xe4, 0x52, 0x61, \ - 0x3e, 0xa7, 0xa5, 0xef, 0x32, 0x67, 0x80, 0x72, 0x07, 0x26, 0xba, 0xa3, \ - 0xff, 0x05, 0x40, 0xc4, 0x60, 0x05, 0x39, 0x31, 0x77, 0xf7, 0xa5, 0xca, \ - 0x01, 0x31, 0x80, 0xa7, 0xe1, 0xd1, 0x0a, 0xa2, 0x7c, 0xd5, 0x1c, 0xba, \ - 0xd0, 0x23, 0x4a, 0xd6, 0x30, 0xf3, 0x93, 0xc7, 0x6f, 0xe8, 0xce, 0x94, \ - 0x1e, 0x84, 0xbb, 0x44, 0x81, 0x62, 0x33, 0xff, 0x6b, 0x5d, 0x00, 0x9b, \ - 0x25, 0xf8, 0x8f, 0x0f, 0x9c, 0x4c, 0x4d, 0xe8, 0xd9, 0xa7, 0x99, 0xf9, \ - 0x51, 0x81, 0xc0, 0x9b, 0x1b, 0x31, 0x0d, 0xa6, 0xb3, 0x7c, 0x0e, 0x45, \ - 0xb8, 0x18, 0x64, 0x7e, 0x89, 0x0a, 0x2b, 0xa8, 0xc3, 0xe0, 0x4a, 0xbd, \ - 0xd4, 0x2f, 0x78, 0xc4, 0x62, 0x9b, 0xe9, 0x7e, 0x3f, 0x56, 0x46, 0x8f, \ - 0x17, 0xb7, 0x2a, 0xa0, 0x10, 0x70, 0xfd, 0xb1, 0xf1, 0x6b, 0x05, 0xdc, \ - 0xd1, 0x41, 0x0f, 0x8e, 0xa6, 0xb2, 0x88, 0x1a, 0x42, 0x61, 0x4f, 0xeb, \ - 0x26, 0x85, 0x59, 0x80, 0xba, 0x85, 0x54, 0xfe, 0xcf, 0xc7, 0x7b, 0x2f, \ - 0x6b, 0x59, 0xce, 0xac, 0xdc, 0x7c, 0xac, 0xf3, 0xc8, 0xd6, 0x12, 0x7e, \ - 0x64, 0xe8, 0x3c, 0x99, 0xa8, 0x8f, 0x4f, 0x11, 0xd9, 0x9c, 0x15, 0x4b, \ - 0x6a, 0x44, 0x92, 0x2d, 0x0c, 0xbf, 0xb1, 0x67, 0x96, 0xc9, 0xac, 0xce, \ - 0xd5, 0x19, 0xeb, 0x6f, 0x18, 0xeb, 0x6e, 0x04, 0x2d, 0x60, 0xac, 0xf4, \ - 0x7b, 0x79, 0xf0, 0x1a, 0x9b, 0xb5, 0xc3, 0x5d, 0xef, 0x7d, 0xc9, 0x05, \ - 0x99, 0x44, 0x81, 0x84, 0x75, 0xc7, 0xec, 0x00, 0x12, 0xfc, 0x7a, 0x4a, \ - 0x0b, 0x82, 0x07, 0xec, 0x6d, 0x86, 0x02, 0x4d, 0xfe, 0x9f, 0xc8, 0x92, \ - 0x48, 0xde, 0xf5, 0xb1, 0x9c, 0xe9, 0xc6, 0x89, 0xd0, 0xc1, 0x56, 0xe8, \ - 0xa4, 0xc6, 0x6a, 0x2e, 0x66, 0xc1, 0x9b, 0xfe, 0xd6, 0x3c, 0xb7 \ -} -/* END FILE */ - -/* This is taken from tests/data_files/server2.crt. */ -/* BEGIN FILE string macro TEST_SRV_CRT_RSA_SHA1_PEM tests/data_files/server2.crt */ -#define TEST_SRV_CRT_RSA_SHA1_PEM \ - "-----BEGIN CERTIFICATE-----\r\n" \ - "MIIDNzCCAh+gAwIBAgIBAjANBgkqhkiG9w0BAQUFADA7MQswCQYDVQQGEwJOTDER\r\n" \ - "MA8GA1UECgwIUG9sYXJTU0wxGTAXBgNVBAMMEFBvbGFyU1NMIFRlc3QgQ0EwHhcN\r\n" \ - "MTkwMjEwMTQ0NDA2WhcNMjkwMjEwMTQ0NDA2WjA0MQswCQYDVQQGEwJOTDERMA8G\r\n" \ - "A1UECgwIUG9sYXJTU0wxEjAQBgNVBAMMCWxvY2FsaG9zdDCCASIwDQYJKoZIhvcN\r\n" \ - "AQEBBQADggEPADCCAQoCggEBAMFNo93nzR3RBNdJcriZrA545Do8Ss86ExbQWuTN\r\n" \ - "owCIp+4ea5anUrSQ7y1yej4kmvy2NKwk9XfgJmSMnLAofaHa6ozmyRyWvP7BBFKz\r\n" \ - "NtSj+uGxdtiQwWG0ZlI2oiZTqqt0Xgd9GYLbKtgfoNkNHC1JZvdbJXNG6AuKT2kM\r\n" \ - "tQCQ4dqCEGZ9rlQri2V5kaHiYcPNQEkI7mgM8YuG0ka/0LiqEQMef1aoGh5EGA8P\r\n" \ - "hYvai0Re4hjGYi/HZo36Xdh98yeJKQHFkA4/J/EwyEoO79bex8cna8cFPXrEAjya\r\n" \ - "HT4P6DSYW8tzS1KW2BGiLICIaTla0w+w3lkvEcf36hIBMJcCAwEAAaNNMEswCQYD\r\n" \ - "VR0TBAIwADAdBgNVHQ4EFgQUpQXoZLjc32APUBJNYKhkr02LQ5MwHwYDVR0jBBgw\r\n" \ - "FoAUtFrkpbPe0lL2udWmlQ/rPrzH/f8wDQYJKoZIhvcNAQEFBQADggEBAJklg3Q4\r\n" \ - "cB7v7BzsxM/vLyKccO6op0/gZzM4ghuLq2Y32kl0sM6kSNUUmduuq3u/+GmUZN2A\r\n" \ - "O/7c+Hw7hDFEIvZk98aBGjCLqn3DmgHIv8ToQ67nellQxx2Uj309PdgjNi/r9HOc\r\n" \ - "KNAYPbBcg6MJGWWj2TI6vNaceios/DhOYx5V0j5nfqSJ/pnU0g9Ign2LAhgYpGJE\r\n" \ - "iEM9wW7hEMkwmk0h/sqZsrJsGH5YsF/VThSq/JVO1e2mZH2vruyZKJVBq+8tDNYp\r\n" \ - "HkK6tSyVYQhzIt3StMJWKMl/o5k2AYz6tSC164+1oG+ML3LWg8XrGKa91H4UOKap\r\n" \ - "Awgk0+4m0T25cNs=\r\n" \ - "-----END CERTIFICATE-----\r\n" -/* END FILE */ - -/* This is taken from tests/data_files/server2.crt.der. */ -/* BEGIN FILE binary macro TEST_SRV_CRT_RSA_SHA1_DER tests/data_files/server2.crt.der */ -#define TEST_SRV_CRT_RSA_SHA1_DER { \ - 0x30, 0x82, 0x03, 0x37, 0x30, 0x82, 0x02, 0x1f, 0xa0, 0x03, 0x02, 0x01, \ - 0x02, 0x02, 0x01, 0x02, 0x30, 0x0d, 0x06, 0x09, 0x2a, 0x86, 0x48, 0x86, \ - 0xf7, 0x0d, 0x01, 0x01, 0x05, 0x05, 0x00, 0x30, 0x3b, 0x31, 0x0b, 0x30, \ - 0x09, 0x06, 0x03, 0x55, 0x04, 0x06, 0x13, 0x02, 0x4e, 0x4c, 0x31, 0x11, \ - 0x30, 0x0f, 0x06, 0x03, 0x55, 0x04, 0x0a, 0x0c, 0x08, 0x50, 0x6f, 0x6c, \ - 0x61, 0x72, 0x53, 0x53, 0x4c, 0x31, 0x19, 0x30, 0x17, 0x06, 0x03, 0x55, \ - 0x04, 0x03, 0x0c, 0x10, 0x50, 0x6f, 0x6c, 0x61, 0x72, 0x53, 0x53, 0x4c, \ - 0x20, 0x54, 0x65, 0x73, 0x74, 0x20, 0x43, 0x41, 0x30, 0x1e, 0x17, 0x0d, \ - 0x31, 0x31, 0x30, 0x32, 0x31, 0x32, 0x31, 0x34, 0x34, 0x34, 0x30, 0x36, \ - 0x5a, 0x17, 0x0d, 0x32, 0x31, 0x30, 0x32, 0x31, 0x32, 0x31, 0x34, 0x34, \ - 0x34, 0x30, 0x36, 0x5a, 0x30, 0x34, 0x31, 0x0b, 0x30, 0x09, 0x06, 0x03, \ - 0x55, 0x04, 0x06, 0x13, 0x02, 0x4e, 0x4c, 0x31, 0x11, 0x30, 0x0f, 0x06, \ - 0x03, 0x55, 0x04, 0x0a, 0x0c, 0x08, 0x50, 0x6f, 0x6c, 0x61, 0x72, 0x53, \ - 0x53, 0x4c, 0x31, 0x12, 0x30, 0x10, 0x06, 0x03, 0x55, 0x04, 0x03, 0x0c, \ - 0x09, 0x6c, 0x6f, 0x63, 0x61, 0x6c, 0x68, 0x6f, 0x73, 0x74, 0x30, 0x82, \ - 0x01, 0x22, 0x30, 0x0d, 0x06, 0x09, 0x2a, 0x86, 0x48, 0x86, 0xf7, 0x0d, \ - 0x01, 0x01, 0x01, 0x05, 0x00, 0x03, 0x82, 0x01, 0x0f, 0x00, 0x30, 0x82, \ - 0x01, 0x0a, 0x02, 0x82, 0x01, 0x01, 0x00, 0xc1, 0x4d, 0xa3, 0xdd, 0xe7, \ - 0xcd, 0x1d, 0xd1, 0x04, 0xd7, 0x49, 0x72, 0xb8, 0x99, 0xac, 0x0e, 0x78, \ - 0xe4, 0x3a, 0x3c, 0x4a, 0xcf, 0x3a, 0x13, 0x16, 0xd0, 0x5a, 0xe4, 0xcd, \ - 0xa3, 0x00, 0x88, 0xa7, 0xee, 0x1e, 0x6b, 0x96, 0xa7, 0x52, 0xb4, 0x90, \ - 0xef, 0x2d, 0x72, 0x7a, 0x3e, 0x24, 0x9a, 0xfc, 0xb6, 0x34, 0xac, 0x24, \ - 0xf5, 0x77, 0xe0, 0x26, 0x64, 0x8c, 0x9c, 0xb0, 0x28, 0x7d, 0xa1, 0xda, \ - 0xea, 0x8c, 0xe6, 0xc9, 0x1c, 0x96, 0xbc, 0xfe, 0xc1, 0x04, 0x52, 0xb3, \ - 0x36, 0xd4, 0xa3, 0xfa, 0xe1, 0xb1, 0x76, 0xd8, 0x90, 0xc1, 0x61, 0xb4, \ - 0x66, 0x52, 0x36, 0xa2, 0x26, 0x53, 0xaa, 0xab, 0x74, 0x5e, 0x07, 0x7d, \ - 0x19, 0x82, 0xdb, 0x2a, 0xd8, 0x1f, 0xa0, 0xd9, 0x0d, 0x1c, 0x2d, 0x49, \ - 0x66, 0xf7, 0x5b, 0x25, 0x73, 0x46, 0xe8, 0x0b, 0x8a, 0x4f, 0x69, 0x0c, \ - 0xb5, 0x00, 0x90, 0xe1, 0xda, 0x82, 0x10, 0x66, 0x7d, 0xae, 0x54, 0x2b, \ - 0x8b, 0x65, 0x79, 0x91, 0xa1, 0xe2, 0x61, 0xc3, 0xcd, 0x40, 0x49, 0x08, \ - 0xee, 0x68, 0x0c, 0xf1, 0x8b, 0x86, 0xd2, 0x46, 0xbf, 0xd0, 0xb8, 0xaa, \ - 0x11, 0x03, 0x1e, 0x7f, 0x56, 0xa8, 0x1a, 0x1e, 0x44, 0x18, 0x0f, 0x0f, \ - 0x85, 0x8b, 0xda, 0x8b, 0x44, 0x5e, 0xe2, 0x18, 0xc6, 0x62, 0x2f, 0xc7, \ - 0x66, 0x8d, 0xfa, 0x5d, 0xd8, 0x7d, 0xf3, 0x27, 0x89, 0x29, 0x01, 0xc5, \ - 0x90, 0x0e, 0x3f, 0x27, 0xf1, 0x30, 0xc8, 0x4a, 0x0e, 0xef, 0xd6, 0xde, \ - 0xc7, 0xc7, 0x27, 0x6b, 0xc7, 0x05, 0x3d, 0x7a, 0xc4, 0x02, 0x3c, 0x9a, \ - 0x1d, 0x3e, 0x0f, 0xe8, 0x34, 0x98, 0x5b, 0xcb, 0x73, 0x4b, 0x52, 0x96, \ - 0xd8, 0x11, 0xa2, 0x2c, 0x80, 0x88, 0x69, 0x39, 0x5a, 0xd3, 0x0f, 0xb0, \ - 0xde, 0x59, 0x2f, 0x11, 0xc7, 0xf7, 0xea, 0x12, 0x01, 0x30, 0x97, 0x02, \ - 0x03, 0x01, 0x00, 0x01, 0xa3, 0x4d, 0x30, 0x4b, 0x30, 0x09, 0x06, 0x03, \ - 0x55, 0x1d, 0x13, 0x04, 0x02, 0x30, 0x00, 0x30, 0x1d, 0x06, 0x03, 0x55, \ - 0x1d, 0x0e, 0x04, 0x16, 0x04, 0x14, 0xa5, 0x05, 0xe8, 0x64, 0xb8, 0xdc, \ - 0xdf, 0x60, 0x0f, 0x50, 0x12, 0x4d, 0x60, 0xa8, 0x64, 0xaf, 0x4d, 0x8b, \ - 0x43, 0x93, 0x30, 0x1f, 0x06, 0x03, 0x55, 0x1d, 0x23, 0x04, 0x18, 0x30, \ - 0x16, 0x80, 0x14, 0xb4, 0x5a, 0xe4, 0xa5, 0xb3, 0xde, 0xd2, 0x52, 0xf6, \ - 0xb9, 0xd5, 0xa6, 0x95, 0x0f, 0xeb, 0x3e, 0xbc, 0xc7, 0xfd, 0xff, 0x30, \ - 0x0d, 0x06, 0x09, 0x2a, 0x86, 0x48, 0x86, 0xf7, 0x0d, 0x01, 0x01, 0x05, \ - 0x05, 0x00, 0x03, 0x82, 0x01, 0x01, 0x00, 0x01, 0x73, 0x0b, 0x4a, 0xc5, \ - 0xcb, 0xa0, 0xde, 0xf1, 0x63, 0x1c, 0x76, 0x04, 0x2b, 0x13, 0x0d, 0xc0, \ - 0x84, 0x11, 0xc5, 0x8f, 0x3a, 0xa7, 0xc5, 0x9c, 0x35, 0x7a, 0x77, 0xb8, \ - 0x20, 0x14, 0x82, 0xee, 0x54, 0xf0, 0xf2, 0xb0, 0x52, 0xcb, 0x78, 0xce, \ - 0x59, 0x07, 0x4f, 0x51, 0x69, 0xfe, 0xd3, 0x2f, 0xe9, 0x09, 0xe7, 0x85, \ - 0x92, 0xd8, 0xba, 0xb1, 0xeb, 0xc5, 0x76, 0x5d, 0x61, 0x2d, 0xe9, 0x86, \ - 0xb5, 0xde, 0x2a, 0xf9, 0x3f, 0x53, 0x28, 0x42, 0x86, 0x83, 0x73, 0x43, \ - 0xe0, 0x04, 0x5f, 0x07, 0x90, 0x14, 0x65, 0x9f, 0x6e, 0x10, 0x7a, 0xbc, \ - 0x58, 0x19, 0x22, 0xc2, 0xeb, 0x39, 0x72, 0x51, 0x92, 0xd7, 0xb4, 0x1d, \ - 0x75, 0x2f, 0xd3, 0x3a, 0x2b, 0x01, 0xe7, 0xdb, 0x50, 0xae, 0xe2, 0xf1, \ - 0xd4, 0x4d, 0x5b, 0x3c, 0xbb, 0x41, 0x2b, 0x2a, 0xa4, 0xe2, 0x4a, 0x02, \ - 0xe5, 0x60, 0x14, 0x2c, 0x9c, 0x1f, 0xa6, 0xcc, 0x06, 0x4b, 0x25, 0x89, \ - 0x4e, 0x96, 0x30, 0x22, 0x9c, 0x5c, 0x58, 0x4d, 0xc3, 0xda, 0xd0, 0x6e, \ - 0x50, 0x1e, 0x8c, 0x65, 0xf5, 0xd9, 0x17, 0x35, 0xa6, 0x58, 0x43, 0xb2, \ - 0x29, 0xb7, 0xa8, 0x5e, 0x35, 0xde, 0xf0, 0x60, 0x42, 0x1a, 0x01, 0xcb, \ - 0xcb, 0x0b, 0xd8, 0x0e, 0xc1, 0x90, 0xdf, 0xa1, 0xd2, 0x1a, 0xd1, 0x2c, \ - 0x02, 0xf4, 0x76, 0x41, 0xa4, 0xcb, 0x4b, 0x15, 0x98, 0x71, 0xf9, 0x35, \ - 0x7d, 0xb0, 0xe7, 0xe2, 0x34, 0x96, 0x91, 0xbe, 0x32, 0x67, 0x2d, 0x6b, \ - 0xd3, 0x55, 0x04, 0x8a, 0x01, 0x50, 0xb4, 0xe3, 0x62, 0x78, 0x6c, 0x11, \ - 0x15, 0xa5, 0x2a, 0x11, 0xc1, 0x49, 0x1c, 0x9b, 0xc4, 0x10, 0x65, 0x60, \ - 0x87, 0xd9, 0x1e, 0x69, 0x59, 0x4e, 0x8f, 0x6b, 0xeb, 0xc1, 0xfe, 0x6b, \ - 0xe2, 0x63, 0x78, 0x95, 0x6e, 0xe0, 0x2d, 0xd7, 0xa7, 0x37, 0xa8 \ -} -/* END FILE */ - -/* This is taken from tests/data_files/server2.key. */ -/* BEGIN FILE string macro TEST_SRV_KEY_RSA_PEM tests/data_files/server2.key */ -#define TEST_SRV_KEY_RSA_PEM \ - "-----BEGIN RSA PRIVATE KEY-----\r\n" \ - "MIIEpAIBAAKCAQEAwU2j3efNHdEE10lyuJmsDnjkOjxKzzoTFtBa5M2jAIin7h5r\r\n" \ - "lqdStJDvLXJ6PiSa/LY0rCT1d+AmZIycsCh9odrqjObJHJa8/sEEUrM21KP64bF2\r\n" \ - "2JDBYbRmUjaiJlOqq3ReB30Zgtsq2B+g2Q0cLUlm91slc0boC4pPaQy1AJDh2oIQ\r\n" \ - "Zn2uVCuLZXmRoeJhw81ASQjuaAzxi4bSRr/QuKoRAx5/VqgaHkQYDw+Fi9qLRF7i\r\n" \ - "GMZiL8dmjfpd2H3zJ4kpAcWQDj8n8TDISg7v1t7HxydrxwU9esQCPJodPg/oNJhb\r\n" \ - "y3NLUpbYEaIsgIhpOVrTD7DeWS8Rx/fqEgEwlwIDAQABAoIBAQCXR0S8EIHFGORZ\r\n" \ - "++AtOg6eENxD+xVs0f1IeGz57Tjo3QnXX7VBZNdj+p1ECvhCE/G7XnkgU5hLZX+G\r\n" \ - "Z0jkz/tqJOI0vRSdLBbipHnWouyBQ4e/A1yIJdlBtqXxJ1KE/ituHRbNc4j4kL8Z\r\n" \ - "/r6pvwnTI0PSx2Eqs048YdS92LT6qAv4flbNDxMn2uY7s4ycS4Q8w1JXnCeaAnYm\r\n" \ - "WYI5wxO+bvRELR2Mcz5DmVnL8jRyml6l6582bSv5oufReFIbyPZbQWlXgYnpu6He\r\n" \ - "GTc7E1zKYQGG/9+DQUl/1vQuCPqQwny0tQoX2w5tdYpdMdVm+zkLtbajzdTviJJa\r\n" \ - "TWzL6lt5AoGBAN86+SVeJDcmQJcv4Eq6UhtRr4QGMiQMz0Sod6ettYxYzMgxtw28\r\n" \ - "CIrgpozCc+UaZJLo7UxvC6an85r1b2nKPCLQFaggJ0H4Q0J/sZOhBIXaoBzWxveK\r\n" \ - "nupceKdVxGsFi8CDy86DBfiyFivfBj+47BbaQzPBj7C4rK7UlLjab2rDAoGBAN2u\r\n" \ - "AM2gchoFiu4v1HFL8D7lweEpi6ZnMJjnEu/dEgGQJFjwdpLnPbsj4c75odQ4Gz8g\r\n" \ - "sw9lao9VVzbusoRE/JGI4aTdO0pATXyG7eG1Qu+5Yc1YGXcCrliA2xM9xx+d7f+s\r\n" \ - "mPzN+WIEg5GJDYZDjAzHG5BNvi/FfM1C9dOtjv2dAoGAF0t5KmwbjWHBhcVqO4Ic\r\n" \ - "BVvN3BIlc1ue2YRXEDlxY5b0r8N4XceMgKmW18OHApZxfl8uPDauWZLXOgl4uepv\r\n" \ - "whZC3EuWrSyyICNhLY21Ah7hbIEBPF3L3ZsOwC+UErL+dXWLdB56Jgy3gZaBeW7b\r\n" \ - "vDrEnocJbqCm7IukhXHOBK8CgYEAwqdHB0hqyNSzIOGY7v9abzB6pUdA3BZiQvEs\r\n" \ - "3LjHVd4HPJ2x0N8CgrBIWOE0q8+0hSMmeE96WW/7jD3fPWwCR5zlXknxBQsfv0gP\r\n" \ - "3BC5PR0Qdypz+d+9zfMf625kyit4T/hzwhDveZUzHnk1Cf+IG7Q+TOEnLnWAWBED\r\n" \ - "ISOWmrUCgYAFEmRxgwAc/u+D6t0syCwAYh6POtscq9Y0i9GyWk89NzgC4NdwwbBH\r\n" \ - "4AgahOxIxXx2gxJnq3yfkJfIjwf0s2DyP0kY2y6Ua1OeomPeY9mrIS4tCuDQ6LrE\r\n" \ - "TB6l9VGoxJL4fyHnZb8L5gGvnB1bbD8cL6YPaDiOhcRseC9vBiEuVg==\r\n" \ - "-----END RSA PRIVATE KEY-----\r\n" -/* END FILE */ - -/* This was generated from tests/data_files/server2.key.der using `xxd -i`. */ -/* BEGIN FILE binary macro TEST_SRV_KEY_RSA_DER tests/data_files/server2.key.der */ -#define TEST_SRV_KEY_RSA_DER { \ - 0x30, 0x82, 0x04, 0xa4, 0x02, 0x01, 0x00, 0x02, 0x82, 0x01, 0x01, 0x00, \ - 0xc1, 0x4d, 0xa3, 0xdd, 0xe7, 0xcd, 0x1d, 0xd1, 0x04, 0xd7, 0x49, 0x72, \ - 0xb8, 0x99, 0xac, 0x0e, 0x78, 0xe4, 0x3a, 0x3c, 0x4a, 0xcf, 0x3a, 0x13, \ - 0x16, 0xd0, 0x5a, 0xe4, 0xcd, 0xa3, 0x00, 0x88, 0xa7, 0xee, 0x1e, 0x6b, \ - 0x96, 0xa7, 0x52, 0xb4, 0x90, 0xef, 0x2d, 0x72, 0x7a, 0x3e, 0x24, 0x9a, \ - 0xfc, 0xb6, 0x34, 0xac, 0x24, 0xf5, 0x77, 0xe0, 0x26, 0x64, 0x8c, 0x9c, \ - 0xb0, 0x28, 0x7d, 0xa1, 0xda, 0xea, 0x8c, 0xe6, 0xc9, 0x1c, 0x96, 0xbc, \ - 0xfe, 0xc1, 0x04, 0x52, 0xb3, 0x36, 0xd4, 0xa3, 0xfa, 0xe1, 0xb1, 0x76, \ - 0xd8, 0x90, 0xc1, 0x61, 0xb4, 0x66, 0x52, 0x36, 0xa2, 0x26, 0x53, 0xaa, \ - 0xab, 0x74, 0x5e, 0x07, 0x7d, 0x19, 0x82, 0xdb, 0x2a, 0xd8, 0x1f, 0xa0, \ - 0xd9, 0x0d, 0x1c, 0x2d, 0x49, 0x66, 0xf7, 0x5b, 0x25, 0x73, 0x46, 0xe8, \ - 0x0b, 0x8a, 0x4f, 0x69, 0x0c, 0xb5, 0x00, 0x90, 0xe1, 0xda, 0x82, 0x10, \ - 0x66, 0x7d, 0xae, 0x54, 0x2b, 0x8b, 0x65, 0x79, 0x91, 0xa1, 0xe2, 0x61, \ - 0xc3, 0xcd, 0x40, 0x49, 0x08, 0xee, 0x68, 0x0c, 0xf1, 0x8b, 0x86, 0xd2, \ - 0x46, 0xbf, 0xd0, 0xb8, 0xaa, 0x11, 0x03, 0x1e, 0x7f, 0x56, 0xa8, 0x1a, \ - 0x1e, 0x44, 0x18, 0x0f, 0x0f, 0x85, 0x8b, 0xda, 0x8b, 0x44, 0x5e, 0xe2, \ - 0x18, 0xc6, 0x62, 0x2f, 0xc7, 0x66, 0x8d, 0xfa, 0x5d, 0xd8, 0x7d, 0xf3, \ - 0x27, 0x89, 0x29, 0x01, 0xc5, 0x90, 0x0e, 0x3f, 0x27, 0xf1, 0x30, 0xc8, \ - 0x4a, 0x0e, 0xef, 0xd6, 0xde, 0xc7, 0xc7, 0x27, 0x6b, 0xc7, 0x05, 0x3d, \ - 0x7a, 0xc4, 0x02, 0x3c, 0x9a, 0x1d, 0x3e, 0x0f, 0xe8, 0x34, 0x98, 0x5b, \ - 0xcb, 0x73, 0x4b, 0x52, 0x96, 0xd8, 0x11, 0xa2, 0x2c, 0x80, 0x88, 0x69, \ - 0x39, 0x5a, 0xd3, 0x0f, 0xb0, 0xde, 0x59, 0x2f, 0x11, 0xc7, 0xf7, 0xea, \ - 0x12, 0x01, 0x30, 0x97, 0x02, 0x03, 0x01, 0x00, 0x01, 0x02, 0x82, 0x01, \ - 0x01, 0x00, 0x97, 0x47, 0x44, 0xbc, 0x10, 0x81, 0xc5, 0x18, 0xe4, 0x59, \ - 0xfb, 0xe0, 0x2d, 0x3a, 0x0e, 0x9e, 0x10, 0xdc, 0x43, 0xfb, 0x15, 0x6c, \ - 0xd1, 0xfd, 0x48, 0x78, 0x6c, 0xf9, 0xed, 0x38, 0xe8, 0xdd, 0x09, 0xd7, \ - 0x5f, 0xb5, 0x41, 0x64, 0xd7, 0x63, 0xfa, 0x9d, 0x44, 0x0a, 0xf8, 0x42, \ - 0x13, 0xf1, 0xbb, 0x5e, 0x79, 0x20, 0x53, 0x98, 0x4b, 0x65, 0x7f, 0x86, \ - 0x67, 0x48, 0xe4, 0xcf, 0xfb, 0x6a, 0x24, 0xe2, 0x34, 0xbd, 0x14, 0x9d, \ - 0x2c, 0x16, 0xe2, 0xa4, 0x79, 0xd6, 0xa2, 0xec, 0x81, 0x43, 0x87, 0xbf, \ - 0x03, 0x5c, 0x88, 0x25, 0xd9, 0x41, 0xb6, 0xa5, 0xf1, 0x27, 0x52, 0x84, \ - 0xfe, 0x2b, 0x6e, 0x1d, 0x16, 0xcd, 0x73, 0x88, 0xf8, 0x90, 0xbf, 0x19, \ - 0xfe, 0xbe, 0xa9, 0xbf, 0x09, 0xd3, 0x23, 0x43, 0xd2, 0xc7, 0x61, 0x2a, \ - 0xb3, 0x4e, 0x3c, 0x61, 0xd4, 0xbd, 0xd8, 0xb4, 0xfa, 0xa8, 0x0b, 0xf8, \ - 0x7e, 0x56, 0xcd, 0x0f, 0x13, 0x27, 0xda, 0xe6, 0x3b, 0xb3, 0x8c, 0x9c, \ - 0x4b, 0x84, 0x3c, 0xc3, 0x52, 0x57, 0x9c, 0x27, 0x9a, 0x02, 0x76, 0x26, \ - 0x59, 0x82, 0x39, 0xc3, 0x13, 0xbe, 0x6e, 0xf4, 0x44, 0x2d, 0x1d, 0x8c, \ - 0x73, 0x3e, 0x43, 0x99, 0x59, 0xcb, 0xf2, 0x34, 0x72, 0x9a, 0x5e, 0xa5, \ - 0xeb, 0x9f, 0x36, 0x6d, 0x2b, 0xf9, 0xa2, 0xe7, 0xd1, 0x78, 0x52, 0x1b, \ - 0xc8, 0xf6, 0x5b, 0x41, 0x69, 0x57, 0x81, 0x89, 0xe9, 0xbb, 0xa1, 0xde, \ - 0x19, 0x37, 0x3b, 0x13, 0x5c, 0xca, 0x61, 0x01, 0x86, 0xff, 0xdf, 0x83, \ - 0x41, 0x49, 0x7f, 0xd6, 0xf4, 0x2e, 0x08, 0xfa, 0x90, 0xc2, 0x7c, 0xb4, \ - 0xb5, 0x0a, 0x17, 0xdb, 0x0e, 0x6d, 0x75, 0x8a, 0x5d, 0x31, 0xd5, 0x66, \ - 0xfb, 0x39, 0x0b, 0xb5, 0xb6, 0xa3, 0xcd, 0xd4, 0xef, 0x88, 0x92, 0x5a, \ - 0x4d, 0x6c, 0xcb, 0xea, 0x5b, 0x79, 0x02, 0x81, 0x81, 0x00, 0xdf, 0x3a, \ - 0xf9, 0x25, 0x5e, 0x24, 0x37, 0x26, 0x40, 0x97, 0x2f, 0xe0, 0x4a, 0xba, \ - 0x52, 0x1b, 0x51, 0xaf, 0x84, 0x06, 0x32, 0x24, 0x0c, 0xcf, 0x44, 0xa8, \ - 0x77, 0xa7, 0xad, 0xb5, 0x8c, 0x58, 0xcc, 0xc8, 0x31, 0xb7, 0x0d, 0xbc, \ - 0x08, 0x8a, 0xe0, 0xa6, 0x8c, 0xc2, 0x73, 0xe5, 0x1a, 0x64, 0x92, 0xe8, \ - 0xed, 0x4c, 0x6f, 0x0b, 0xa6, 0xa7, 0xf3, 0x9a, 0xf5, 0x6f, 0x69, 0xca, \ - 0x3c, 0x22, 0xd0, 0x15, 0xa8, 0x20, 0x27, 0x41, 0xf8, 0x43, 0x42, 0x7f, \ - 0xb1, 0x93, 0xa1, 0x04, 0x85, 0xda, 0xa0, 0x1c, 0xd6, 0xc6, 0xf7, 0x8a, \ - 0x9e, 0xea, 0x5c, 0x78, 0xa7, 0x55, 0xc4, 0x6b, 0x05, 0x8b, 0xc0, 0x83, \ - 0xcb, 0xce, 0x83, 0x05, 0xf8, 0xb2, 0x16, 0x2b, 0xdf, 0x06, 0x3f, 0xb8, \ - 0xec, 0x16, 0xda, 0x43, 0x33, 0xc1, 0x8f, 0xb0, 0xb8, 0xac, 0xae, 0xd4, \ - 0x94, 0xb8, 0xda, 0x6f, 0x6a, 0xc3, 0x02, 0x81, 0x81, 0x00, 0xdd, 0xae, \ - 0x00, 0xcd, 0xa0, 0x72, 0x1a, 0x05, 0x8a, 0xee, 0x2f, 0xd4, 0x71, 0x4b, \ - 0xf0, 0x3e, 0xe5, 0xc1, 0xe1, 0x29, 0x8b, 0xa6, 0x67, 0x30, 0x98, 0xe7, \ - 0x12, 0xef, 0xdd, 0x12, 0x01, 0x90, 0x24, 0x58, 0xf0, 0x76, 0x92, 0xe7, \ - 0x3d, 0xbb, 0x23, 0xe1, 0xce, 0xf9, 0xa1, 0xd4, 0x38, 0x1b, 0x3f, 0x20, \ - 0xb3, 0x0f, 0x65, 0x6a, 0x8f, 0x55, 0x57, 0x36, 0xee, 0xb2, 0x84, 0x44, \ - 0xfc, 0x91, 0x88, 0xe1, 0xa4, 0xdd, 0x3b, 0x4a, 0x40, 0x4d, 0x7c, 0x86, \ - 0xed, 0xe1, 0xb5, 0x42, 0xef, 0xb9, 0x61, 0xcd, 0x58, 0x19, 0x77, 0x02, \ - 0xae, 0x58, 0x80, 0xdb, 0x13, 0x3d, 0xc7, 0x1f, 0x9d, 0xed, 0xff, 0xac, \ - 0x98, 0xfc, 0xcd, 0xf9, 0x62, 0x04, 0x83, 0x91, 0x89, 0x0d, 0x86, 0x43, \ - 0x8c, 0x0c, 0xc7, 0x1b, 0x90, 0x4d, 0xbe, 0x2f, 0xc5, 0x7c, 0xcd, 0x42, \ - 0xf5, 0xd3, 0xad, 0x8e, 0xfd, 0x9d, 0x02, 0x81, 0x80, 0x17, 0x4b, 0x79, \ - 0x2a, 0x6c, 0x1b, 0x8d, 0x61, 0xc1, 0x85, 0xc5, 0x6a, 0x3b, 0x82, 0x1c, \ - 0x05, 0x5b, 0xcd, 0xdc, 0x12, 0x25, 0x73, 0x5b, 0x9e, 0xd9, 0x84, 0x57, \ - 0x10, 0x39, 0x71, 0x63, 0x96, 0xf4, 0xaf, 0xc3, 0x78, 0x5d, 0xc7, 0x8c, \ - 0x80, 0xa9, 0x96, 0xd7, 0xc3, 0x87, 0x02, 0x96, 0x71, 0x7e, 0x5f, 0x2e, \ - 0x3c, 0x36, 0xae, 0x59, 0x92, 0xd7, 0x3a, 0x09, 0x78, 0xb9, 0xea, 0x6f, \ - 0xc2, 0x16, 0x42, 0xdc, 0x4b, 0x96, 0xad, 0x2c, 0xb2, 0x20, 0x23, 0x61, \ - 0x2d, 0x8d, 0xb5, 0x02, 0x1e, 0xe1, 0x6c, 0x81, 0x01, 0x3c, 0x5d, 0xcb, \ - 0xdd, 0x9b, 0x0e, 0xc0, 0x2f, 0x94, 0x12, 0xb2, 0xfe, 0x75, 0x75, 0x8b, \ - 0x74, 0x1e, 0x7a, 0x26, 0x0c, 0xb7, 0x81, 0x96, 0x81, 0x79, 0x6e, 0xdb, \ - 0xbc, 0x3a, 0xc4, 0x9e, 0x87, 0x09, 0x6e, 0xa0, 0xa6, 0xec, 0x8b, 0xa4, \ - 0x85, 0x71, 0xce, 0x04, 0xaf, 0x02, 0x81, 0x81, 0x00, 0xc2, 0xa7, 0x47, \ - 0x07, 0x48, 0x6a, 0xc8, 0xd4, 0xb3, 0x20, 0xe1, 0x98, 0xee, 0xff, 0x5a, \ - 0x6f, 0x30, 0x7a, 0xa5, 0x47, 0x40, 0xdc, 0x16, 0x62, 0x42, 0xf1, 0x2c, \ - 0xdc, 0xb8, 0xc7, 0x55, 0xde, 0x07, 0x3c, 0x9d, 0xb1, 0xd0, 0xdf, 0x02, \ - 0x82, 0xb0, 0x48, 0x58, 0xe1, 0x34, 0xab, 0xcf, 0xb4, 0x85, 0x23, 0x26, \ - 0x78, 0x4f, 0x7a, 0x59, 0x6f, 0xfb, 0x8c, 0x3d, 0xdf, 0x3d, 0x6c, 0x02, \ - 0x47, 0x9c, 0xe5, 0x5e, 0x49, 0xf1, 0x05, 0x0b, 0x1f, 0xbf, 0x48, 0x0f, \ - 0xdc, 0x10, 0xb9, 0x3d, 0x1d, 0x10, 0x77, 0x2a, 0x73, 0xf9, 0xdf, 0xbd, \ - 0xcd, 0xf3, 0x1f, 0xeb, 0x6e, 0x64, 0xca, 0x2b, 0x78, 0x4f, 0xf8, 0x73, \ - 0xc2, 0x10, 0xef, 0x79, 0x95, 0x33, 0x1e, 0x79, 0x35, 0x09, 0xff, 0x88, \ - 0x1b, 0xb4, 0x3e, 0x4c, 0xe1, 0x27, 0x2e, 0x75, 0x80, 0x58, 0x11, 0x03, \ - 0x21, 0x23, 0x96, 0x9a, 0xb5, 0x02, 0x81, 0x80, 0x05, 0x12, 0x64, 0x71, \ - 0x83, 0x00, 0x1c, 0xfe, 0xef, 0x83, 0xea, 0xdd, 0x2c, 0xc8, 0x2c, 0x00, \ - 0x62, 0x1e, 0x8f, 0x3a, 0xdb, 0x1c, 0xab, 0xd6, 0x34, 0x8b, 0xd1, 0xb2, \ - 0x5a, 0x4f, 0x3d, 0x37, 0x38, 0x02, 0xe0, 0xd7, 0x70, 0xc1, 0xb0, 0x47, \ - 0xe0, 0x08, 0x1a, 0x84, 0xec, 0x48, 0xc5, 0x7c, 0x76, 0x83, 0x12, 0x67, \ - 0xab, 0x7c, 0x9f, 0x90, 0x97, 0xc8, 0x8f, 0x07, 0xf4, 0xb3, 0x60, 0xf2, \ - 0x3f, 0x49, 0x18, 0xdb, 0x2e, 0x94, 0x6b, 0x53, 0x9e, 0xa2, 0x63, 0xde, \ - 0x63, 0xd9, 0xab, 0x21, 0x2e, 0x2d, 0x0a, 0xe0, 0xd0, 0xe8, 0xba, 0xc4, \ - 0x4c, 0x1e, 0xa5, 0xf5, 0x51, 0xa8, 0xc4, 0x92, 0xf8, 0x7f, 0x21, 0xe7, \ - 0x65, 0xbf, 0x0b, 0xe6, 0x01, 0xaf, 0x9c, 0x1d, 0x5b, 0x6c, 0x3f, 0x1c, \ - 0x2f, 0xa6, 0x0f, 0x68, 0x38, 0x8e, 0x85, 0xc4, 0x6c, 0x78, 0x2f, 0x6f, \ - 0x06, 0x21, 0x2e, 0x56 \ -} -/* END FILE */ - -/* - * Test client Certificates - * - * Test client certificates are defined for each choice - * of the following parameters: - * - PEM or DER encoding - * - RSA or EC key - * - * Things to add: - * - hash type - * - multiple EC curve types - */ - -/* This is taken from tests/data_files/cli2.crt. */ -/* BEGIN FILE string macro TEST_CLI_CRT_EC_PEM tests/data_files/cli2.crt */ -#define TEST_CLI_CRT_EC_PEM \ - "-----BEGIN CERTIFICATE-----\r\n" \ - "MIIB3zCCAWOgAwIBAgIBDTAMBggqhkjOPQQDAgUAMD4xCzAJBgNVBAYTAk5MMREw\r\n" \ - "DwYDVQQKDAhQb2xhclNTTDEcMBoGA1UEAwwTUG9sYXJTU0wgVGVzdCBFQyBDQTAe\r\n" \ - "Fw0xOTAyMTAxNDQ0MDBaFw0yOTAyMTAxNDQ0MDBaMEExCzAJBgNVBAYTAk5MMREw\r\n" \ - "DwYDVQQKDAhQb2xhclNTTDEfMB0GA1UEAwwWUG9sYXJTU0wgVGVzdCBDbGllbnQg\r\n" \ - "MjBZMBMGByqGSM49AgEGCCqGSM49AwEHA0IABFflrrFz39Osu5O4gf8Sru7mU6zO\r\n" \ - "VVP2NA7MLuNjJQvfmOLzXGA2lsDVGBRw5X+f1UtFGOWwbNVc+JaPh3Cj5MejTTBL\r\n" \ - "MAkGA1UdEwQCMAAwHQYDVR0OBBYEFHoAX4Zk/OBd5REQO7LmO8QmP8/iMB8GA1Ud\r\n" \ - "IwQYMBaAFJ1tICRJAT8ry3i1Gbx+JMnb+zZ8MAwGCCqGSM49BAMCBQADaAAwZQIx\r\n" \ - "AMqme4DKMldUlplDET9Q6Eptre7uUWKhsLOF+zPkKDlfzpIkJYEFgcloDHGYw80u\r\n" \ - "IgIwNftyPXsabTqMM7iEHgVpX/GRozKklY9yQI/5eoA6gGW7Y+imuGR/oao5ySOb\r\n" \ - "a9Vk\r\n" \ - "-----END CERTIFICATE-----\r\n" -/* END FILE */ - -/* This is generated from tests/data_files/cli2.crt.der using `xxd -i`. */ -/* BEGIN FILE binary macro TEST_CLI_CRT_EC_DER tests/data_files/cli2.crt.der */ -#define TEST_CLI_CRT_EC_DER { \ - 0x30, 0x82, 0x01, 0xdf, 0x30, 0x82, 0x01, 0x63, 0xa0, 0x03, 0x02, 0x01, \ - 0x02, 0x02, 0x01, 0x0d, 0x30, 0x0c, 0x06, 0x08, 0x2a, 0x86, 0x48, 0xce, \ - 0x3d, 0x04, 0x03, 0x02, 0x05, 0x00, 0x30, 0x3e, 0x31, 0x0b, 0x30, 0x09, \ - 0x06, 0x03, 0x55, 0x04, 0x06, 0x13, 0x02, 0x4e, 0x4c, 0x31, 0x11, 0x30, \ - 0x0f, 0x06, 0x03, 0x55, 0x04, 0x0a, 0x0c, 0x08, 0x50, 0x6f, 0x6c, 0x61, \ - 0x72, 0x53, 0x53, 0x4c, 0x31, 0x1c, 0x30, 0x1a, 0x06, 0x03, 0x55, 0x04, \ - 0x03, 0x0c, 0x13, 0x50, 0x6f, 0x6c, 0x61, 0x72, 0x53, 0x53, 0x4c, 0x20, \ - 0x54, 0x65, 0x73, 0x74, 0x20, 0x45, 0x43, 0x20, 0x43, 0x41, 0x30, 0x1e, \ - 0x17, 0x0d, 0x31, 0x39, 0x30, 0x32, 0x31, 0x30, 0x31, 0x34, 0x34, 0x34, \ - 0x30, 0x30, 0x5a, 0x17, 0x0d, 0x32, 0x39, 0x30, 0x32, 0x31, 0x30, 0x31, \ - 0x34, 0x34, 0x34, 0x30, 0x30, 0x5a, 0x30, 0x41, 0x31, 0x0b, 0x30, 0x09, \ - 0x06, 0x03, 0x55, 0x04, 0x06, 0x13, 0x02, 0x4e, 0x4c, 0x31, 0x11, 0x30, \ - 0x0f, 0x06, 0x03, 0x55, 0x04, 0x0a, 0x0c, 0x08, 0x50, 0x6f, 0x6c, 0x61, \ - 0x72, 0x53, 0x53, 0x4c, 0x31, 0x1f, 0x30, 0x1d, 0x06, 0x03, 0x55, 0x04, \ - 0x03, 0x0c, 0x16, 0x50, 0x6f, 0x6c, 0x61, 0x72, 0x53, 0x53, 0x4c, 0x20, \ - 0x54, 0x65, 0x73, 0x74, 0x20, 0x43, 0x6c, 0x69, 0x65, 0x6e, 0x74, 0x20, \ - 0x32, 0x30, 0x59, 0x30, 0x13, 0x06, 0x07, 0x2a, 0x86, 0x48, 0xce, 0x3d, \ - 0x02, 0x01, 0x06, 0x08, 0x2a, 0x86, 0x48, 0xce, 0x3d, 0x03, 0x01, 0x07, \ - 0x03, 0x42, 0x00, 0x04, 0x57, 0xe5, 0xae, 0xb1, 0x73, 0xdf, 0xd3, 0xac, \ - 0xbb, 0x93, 0xb8, 0x81, 0xff, 0x12, 0xae, 0xee, 0xe6, 0x53, 0xac, 0xce, \ - 0x55, 0x53, 0xf6, 0x34, 0x0e, 0xcc, 0x2e, 0xe3, 0x63, 0x25, 0x0b, 0xdf, \ - 0x98, 0xe2, 0xf3, 0x5c, 0x60, 0x36, 0x96, 0xc0, 0xd5, 0x18, 0x14, 0x70, \ - 0xe5, 0x7f, 0x9f, 0xd5, 0x4b, 0x45, 0x18, 0xe5, 0xb0, 0x6c, 0xd5, 0x5c, \ - 0xf8, 0x96, 0x8f, 0x87, 0x70, 0xa3, 0xe4, 0xc7, 0xa3, 0x4d, 0x30, 0x4b, \ - 0x30, 0x09, 0x06, 0x03, 0x55, 0x1d, 0x13, 0x04, 0x02, 0x30, 0x00, 0x30, \ - 0x1d, 0x06, 0x03, 0x55, 0x1d, 0x0e, 0x04, 0x16, 0x04, 0x14, 0x7a, 0x00, \ - 0x5f, 0x86, 0x64, 0xfc, 0xe0, 0x5d, 0xe5, 0x11, 0x10, 0x3b, 0xb2, 0xe6, \ - 0x3b, 0xc4, 0x26, 0x3f, 0xcf, 0xe2, 0x30, 0x1f, 0x06, 0x03, 0x55, 0x1d, \ - 0x23, 0x04, 0x18, 0x30, 0x16, 0x80, 0x14, 0x9d, 0x6d, 0x20, 0x24, 0x49, \ - 0x01, 0x3f, 0x2b, 0xcb, 0x78, 0xb5, 0x19, 0xbc, 0x7e, 0x24, 0xc9, 0xdb, \ - 0xfb, 0x36, 0x7c, 0x30, 0x0c, 0x06, 0x08, 0x2a, 0x86, 0x48, 0xce, 0x3d, \ - 0x04, 0x03, 0x02, 0x05, 0x00, 0x03, 0x68, 0x00, 0x30, 0x65, 0x02, 0x31, \ - 0x00, 0xca, 0xa6, 0x7b, 0x80, 0xca, 0x32, 0x57, 0x54, 0x96, 0x99, 0x43, \ - 0x11, 0x3f, 0x50, 0xe8, 0x4a, 0x6d, 0xad, 0xee, 0xee, 0x51, 0x62, 0xa1, \ - 0xb0, 0xb3, 0x85, 0xfb, 0x33, 0xe4, 0x28, 0x39, 0x5f, 0xce, 0x92, 0x24, \ - 0x25, 0x81, 0x05, 0x81, 0xc9, 0x68, 0x0c, 0x71, 0x98, 0xc3, 0xcd, 0x2e, \ - 0x22, 0x02, 0x30, 0x35, 0xfb, 0x72, 0x3d, 0x7b, 0x1a, 0x6d, 0x3a, 0x8c, \ - 0x33, 0xb8, 0x84, 0x1e, 0x05, 0x69, 0x5f, 0xf1, 0x91, 0xa3, 0x32, 0xa4, \ - 0x95, 0x8f, 0x72, 0x40, 0x8f, 0xf9, 0x7a, 0x80, 0x3a, 0x80, 0x65, 0xbb, \ - 0x63, 0xe8, 0xa6, 0xb8, 0x64, 0x7f, 0xa1, 0xaa, 0x39, 0xc9, 0x23, 0x9b, \ - 0x6b, 0xd5, 0x64 \ -} -/* END FILE */ - -/* This is taken from tests/data_files/cli2.key. */ -/* BEGIN FILE string macro TEST_CLI_KEY_EC_PEM tests/data_files/cli2.key */ -#define TEST_CLI_KEY_EC_PEM \ - "-----BEGIN EC PRIVATE KEY-----\r\n" \ - "MHcCAQEEIPb3hmTxZ3/mZI3vyk7p3U3wBf+WIop6hDhkFzJhmLcqoAoGCCqGSM49\r\n" \ - "AwEHoUQDQgAEV+WusXPf06y7k7iB/xKu7uZTrM5VU/Y0Dswu42MlC9+Y4vNcYDaW\r\n" \ - "wNUYFHDlf5/VS0UY5bBs1Vz4lo+HcKPkxw==\r\n" \ - "-----END EC PRIVATE KEY-----\r\n" -/* END FILE */ - -/* This is generated from tests/data_files/cli2.key.der using `xxd -i`. */ -/* BEGIN FILE binary macro TEST_CLI_KEY_EC_DER tests/data_files/cli2.key.der */ -#define TEST_CLI_KEY_EC_DER { \ - 0x30, 0x77, 0x02, 0x01, 0x01, 0x04, 0x20, 0xf6, 0xf7, 0x86, 0x64, 0xf1, \ - 0x67, 0x7f, 0xe6, 0x64, 0x8d, 0xef, 0xca, 0x4e, 0xe9, 0xdd, 0x4d, 0xf0, \ - 0x05, 0xff, 0x96, 0x22, 0x8a, 0x7a, 0x84, 0x38, 0x64, 0x17, 0x32, 0x61, \ - 0x98, 0xb7, 0x2a, 0xa0, 0x0a, 0x06, 0x08, 0x2a, 0x86, 0x48, 0xce, 0x3d, \ - 0x03, 0x01, 0x07, 0xa1, 0x44, 0x03, 0x42, 0x00, 0x04, 0x57, 0xe5, 0xae, \ - 0xb1, 0x73, 0xdf, 0xd3, 0xac, 0xbb, 0x93, 0xb8, 0x81, 0xff, 0x12, 0xae, \ - 0xee, 0xe6, 0x53, 0xac, 0xce, 0x55, 0x53, 0xf6, 0x34, 0x0e, 0xcc, 0x2e, \ - 0xe3, 0x63, 0x25, 0x0b, 0xdf, 0x98, 0xe2, 0xf3, 0x5c, 0x60, 0x36, 0x96, \ - 0xc0, 0xd5, 0x18, 0x14, 0x70, 0xe5, 0x7f, 0x9f, 0xd5, 0x4b, 0x45, 0x18, \ - 0xe5, 0xb0, 0x6c, 0xd5, 0x5c, 0xf8, 0x96, 0x8f, 0x87, 0x70, 0xa3, 0xe4, \ - 0xc7 \ -} -/* END FILE */ - -/* This is taken from tests/data_files/cli-rsa-sha256.crt. */ -/* BEGIN FILE string macro TEST_CLI_CRT_RSA_PEM tests/data_files/cli-rsa-sha256.crt */ -#define TEST_CLI_CRT_RSA_PEM \ - "-----BEGIN CERTIFICATE-----\r\n" \ - "MIIDPzCCAiegAwIBAgIBBDANBgkqhkiG9w0BAQsFADA7MQswCQYDVQQGEwJOTDER\r\n" \ - "MA8GA1UECgwIUG9sYXJTU0wxGTAXBgNVBAMMEFBvbGFyU1NMIFRlc3QgQ0EwHhcN\r\n" \ - "MTkwMjEwMTQ0NDA2WhcNMjkwMjEwMTQ0NDA2WjA8MQswCQYDVQQGEwJOTDERMA8G\r\n" \ - "A1UECgwIUG9sYXJTU0wxGjAYBgNVBAMMEVBvbGFyU1NMIENsaWVudCAyMIIBIjAN\r\n" \ - "BgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEAyHTEzLn5tXnpRdkUYLB9u5Pyax6f\r\n" \ - "M60Nj4o8VmXl3ETZzGaFB9X4J7BKNdBjngpuG7fa8H6r7gwQk4ZJGDTzqCrSV/Uu\r\n" \ - "1C93KYRhTYJQj6eVSHD1bk2y1RPD0hrt5kPqQhTrdOrA7R/UV06p86jt0uDBMHEw\r\n" \ - "MjDV0/YI0FZPRo7yX/k9Z5GIMC5Cst99++UMd//sMcB4j7/Cf8qtbCHWjdmLao5v\r\n" \ - "4Jv4EFbMs44TFeY0BGbH7vk2DmqV9gmaBmf0ZXH4yqSxJeD+PIs1BGe64E92hfx/\r\n" \ - "/DZrtenNLQNiTrM9AM+vdqBpVoNq0qjU51Bx5rU2BXcFbXvI5MT9TNUhXwIDAQAB\r\n" \ - "o00wSzAJBgNVHRMEAjAAMB0GA1UdDgQWBBRxoQBzckAvVHZeM/xSj7zx3WtGITAf\r\n" \ - "BgNVHSMEGDAWgBS0WuSls97SUva51aaVD+s+vMf9/zANBgkqhkiG9w0BAQsFAAOC\r\n" \ - "AQEAXidv1d4pLlBiKWED95rMycBdgDcgyNqJxakFkRfRyA2y1mlyTn7uBXRkNLY5\r\n" \ - "ZFzK82GCjk2Q2OD4RZSCPAJJqLpHHU34t71ciffvy2KK81YvrxczRhMAE64i+qna\r\n" \ - "yP3Td2XuWJR05PVPoSemsNELs9gWttdnYy3ce+EY2Y0n7Rsi7982EeLIAA7H6ca4\r\n" \ - "2Es/NUH//JZJT32OP0doMxeDRA+vplkKqTLLWf7dX26LIriBkBaRCgR5Yv9LBPFc\r\n" \ - "NOtpzu/LbrY7QFXKJMI+JXDudCsOn8KCmiA4d6Emisqfh3V3485l7HEQNcvLTxlD\r\n" \ - "6zDQyi0/ykYUYZkwQTK1N2Nvlw==\r\n" \ - "-----END CERTIFICATE-----\r\n" -/* END FILE */ - -/* This was generated from tests/data_files/cli-rsa-sha256.crt.der - using `xxd -i.` */ -/* BEGIN FILE binary macro TEST_CLI_CRT_RSA_DER tests/data_files/cli-rsa-sha256.crt.der */ -#define TEST_CLI_CRT_RSA_DER { \ - 0x30, 0x82, 0x03, 0x3f, 0x30, 0x82, 0x02, 0x27, 0xa0, 0x03, 0x02, 0x01, \ - 0x02, 0x02, 0x01, 0x04, 0x30, 0x0d, 0x06, 0x09, 0x2a, 0x86, 0x48, 0x86, \ - 0xf7, 0x0d, 0x01, 0x01, 0x0b, 0x05, 0x00, 0x30, 0x3b, 0x31, 0x0b, 0x30, \ - 0x09, 0x06, 0x03, 0x55, 0x04, 0x06, 0x13, 0x02, 0x4e, 0x4c, 0x31, 0x11, \ - 0x30, 0x0f, 0x06, 0x03, 0x55, 0x04, 0x0a, 0x0c, 0x08, 0x50, 0x6f, 0x6c, \ - 0x61, 0x72, 0x53, 0x53, 0x4c, 0x31, 0x19, 0x30, 0x17, 0x06, 0x03, 0x55, \ - 0x04, 0x03, 0x0c, 0x10, 0x50, 0x6f, 0x6c, 0x61, 0x72, 0x53, 0x53, 0x4c, \ - 0x20, 0x54, 0x65, 0x73, 0x74, 0x20, 0x43, 0x41, 0x30, 0x1e, 0x17, 0x0d, \ - 0x31, 0x39, 0x30, 0x32, 0x31, 0x30, 0x31, 0x34, 0x34, 0x34, 0x30, 0x36, \ - 0x5a, 0x17, 0x0d, 0x32, 0x39, 0x30, 0x32, 0x31, 0x30, 0x31, 0x34, 0x34, \ - 0x34, 0x30, 0x36, 0x5a, 0x30, 0x3c, 0x31, 0x0b, 0x30, 0x09, 0x06, 0x03, \ - 0x55, 0x04, 0x06, 0x13, 0x02, 0x4e, 0x4c, 0x31, 0x11, 0x30, 0x0f, 0x06, \ - 0x03, 0x55, 0x04, 0x0a, 0x0c, 0x08, 0x50, 0x6f, 0x6c, 0x61, 0x72, 0x53, \ - 0x53, 0x4c, 0x31, 0x1a, 0x30, 0x18, 0x06, 0x03, 0x55, 0x04, 0x03, 0x0c, \ - 0x11, 0x50, 0x6f, 0x6c, 0x61, 0x72, 0x53, 0x53, 0x4c, 0x20, 0x43, 0x6c, \ - 0x69, 0x65, 0x6e, 0x74, 0x20, 0x32, 0x30, 0x82, 0x01, 0x22, 0x30, 0x0d, \ - 0x06, 0x09, 0x2a, 0x86, 0x48, 0x86, 0xf7, 0x0d, 0x01, 0x01, 0x01, 0x05, \ - 0x00, 0x03, 0x82, 0x01, 0x0f, 0x00, 0x30, 0x82, 0x01, 0x0a, 0x02, 0x82, \ - 0x01, 0x01, 0x00, 0xc8, 0x74, 0xc4, 0xcc, 0xb9, 0xf9, 0xb5, 0x79, 0xe9, \ - 0x45, 0xd9, 0x14, 0x60, 0xb0, 0x7d, 0xbb, 0x93, 0xf2, 0x6b, 0x1e, 0x9f, \ - 0x33, 0xad, 0x0d, 0x8f, 0x8a, 0x3c, 0x56, 0x65, 0xe5, 0xdc, 0x44, 0xd9, \ - 0xcc, 0x66, 0x85, 0x07, 0xd5, 0xf8, 0x27, 0xb0, 0x4a, 0x35, 0xd0, 0x63, \ - 0x9e, 0x0a, 0x6e, 0x1b, 0xb7, 0xda, 0xf0, 0x7e, 0xab, 0xee, 0x0c, 0x10, \ - 0x93, 0x86, 0x49, 0x18, 0x34, 0xf3, 0xa8, 0x2a, 0xd2, 0x57, 0xf5, 0x2e, \ - 0xd4, 0x2f, 0x77, 0x29, 0x84, 0x61, 0x4d, 0x82, 0x50, 0x8f, 0xa7, 0x95, \ - 0x48, 0x70, 0xf5, 0x6e, 0x4d, 0xb2, 0xd5, 0x13, 0xc3, 0xd2, 0x1a, 0xed, \ - 0xe6, 0x43, 0xea, 0x42, 0x14, 0xeb, 0x74, 0xea, 0xc0, 0xed, 0x1f, 0xd4, \ - 0x57, 0x4e, 0xa9, 0xf3, 0xa8, 0xed, 0xd2, 0xe0, 0xc1, 0x30, 0x71, 0x30, \ - 0x32, 0x30, 0xd5, 0xd3, 0xf6, 0x08, 0xd0, 0x56, 0x4f, 0x46, 0x8e, 0xf2, \ - 0x5f, 0xf9, 0x3d, 0x67, 0x91, 0x88, 0x30, 0x2e, 0x42, 0xb2, 0xdf, 0x7d, \ - 0xfb, 0xe5, 0x0c, 0x77, 0xff, 0xec, 0x31, 0xc0, 0x78, 0x8f, 0xbf, 0xc2, \ - 0x7f, 0xca, 0xad, 0x6c, 0x21, 0xd6, 0x8d, 0xd9, 0x8b, 0x6a, 0x8e, 0x6f, \ - 0xe0, 0x9b, 0xf8, 0x10, 0x56, 0xcc, 0xb3, 0x8e, 0x13, 0x15, 0xe6, 0x34, \ - 0x04, 0x66, 0xc7, 0xee, 0xf9, 0x36, 0x0e, 0x6a, 0x95, 0xf6, 0x09, 0x9a, \ - 0x06, 0x67, 0xf4, 0x65, 0x71, 0xf8, 0xca, 0xa4, 0xb1, 0x25, 0xe0, 0xfe, \ - 0x3c, 0x8b, 0x35, 0x04, 0x67, 0xba, 0xe0, 0x4f, 0x76, 0x85, 0xfc, 0x7f, \ - 0xfc, 0x36, 0x6b, 0xb5, 0xe9, 0xcd, 0x2d, 0x03, 0x62, 0x4e, 0xb3, 0x3d, \ - 0x00, 0xcf, 0xaf, 0x76, 0xa0, 0x69, 0x56, 0x83, 0x6a, 0xd2, 0xa8, 0xd4, \ - 0xe7, 0x50, 0x71, 0xe6, 0xb5, 0x36, 0x05, 0x77, 0x05, 0x6d, 0x7b, 0xc8, \ - 0xe4, 0xc4, 0xfd, 0x4c, 0xd5, 0x21, 0x5f, 0x02, 0x03, 0x01, 0x00, 0x01, \ - 0xa3, 0x4d, 0x30, 0x4b, 0x30, 0x09, 0x06, 0x03, 0x55, 0x1d, 0x13, 0x04, \ - 0x02, 0x30, 0x00, 0x30, 0x1d, 0x06, 0x03, 0x55, 0x1d, 0x0e, 0x04, 0x16, \ - 0x04, 0x14, 0x71, 0xa1, 0x00, 0x73, 0x72, 0x40, 0x2f, 0x54, 0x76, 0x5e, \ - 0x33, 0xfc, 0x52, 0x8f, 0xbc, 0xf1, 0xdd, 0x6b, 0x46, 0x21, 0x30, 0x1f, \ - 0x06, 0x03, 0x55, 0x1d, 0x23, 0x04, 0x18, 0x30, 0x16, 0x80, 0x14, 0xb4, \ - 0x5a, 0xe4, 0xa5, 0xb3, 0xde, 0xd2, 0x52, 0xf6, 0xb9, 0xd5, 0xa6, 0x95, \ - 0x0f, 0xeb, 0x3e, 0xbc, 0xc7, 0xfd, 0xff, 0x30, 0x0d, 0x06, 0x09, 0x2a, \ - 0x86, 0x48, 0x86, 0xf7, 0x0d, 0x01, 0x01, 0x0b, 0x05, 0x00, 0x03, 0x82, \ - 0x01, 0x01, 0x00, 0x5e, 0x27, 0x6f, 0xd5, 0xde, 0x29, 0x2e, 0x50, 0x62, \ - 0x29, 0x61, 0x03, 0xf7, 0x9a, 0xcc, 0xc9, 0xc0, 0x5d, 0x80, 0x37, 0x20, \ - 0xc8, 0xda, 0x89, 0xc5, 0xa9, 0x05, 0x91, 0x17, 0xd1, 0xc8, 0x0d, 0xb2, \ - 0xd6, 0x69, 0x72, 0x4e, 0x7e, 0xee, 0x05, 0x74, 0x64, 0x34, 0xb6, 0x39, \ - 0x64, 0x5c, 0xca, 0xf3, 0x61, 0x82, 0x8e, 0x4d, 0x90, 0xd8, 0xe0, 0xf8, \ - 0x45, 0x94, 0x82, 0x3c, 0x02, 0x49, 0xa8, 0xba, 0x47, 0x1d, 0x4d, 0xf8, \ - 0xb7, 0xbd, 0x5c, 0x89, 0xf7, 0xef, 0xcb, 0x62, 0x8a, 0xf3, 0x56, 0x2f, \ - 0xaf, 0x17, 0x33, 0x46, 0x13, 0x00, 0x13, 0xae, 0x22, 0xfa, 0xa9, 0xda, \ - 0xc8, 0xfd, 0xd3, 0x77, 0x65, 0xee, 0x58, 0x94, 0x74, 0xe4, 0xf5, 0x4f, \ - 0xa1, 0x27, 0xa6, 0xb0, 0xd1, 0x0b, 0xb3, 0xd8, 0x16, 0xb6, 0xd7, 0x67, \ - 0x63, 0x2d, 0xdc, 0x7b, 0xe1, 0x18, 0xd9, 0x8d, 0x27, 0xed, 0x1b, 0x22, \ - 0xef, 0xdf, 0x36, 0x11, 0xe2, 0xc8, 0x00, 0x0e, 0xc7, 0xe9, 0xc6, 0xb8, \ - 0xd8, 0x4b, 0x3f, 0x35, 0x41, 0xff, 0xfc, 0x96, 0x49, 0x4f, 0x7d, 0x8e, \ - 0x3f, 0x47, 0x68, 0x33, 0x17, 0x83, 0x44, 0x0f, 0xaf, 0xa6, 0x59, 0x0a, \ - 0xa9, 0x32, 0xcb, 0x59, 0xfe, 0xdd, 0x5f, 0x6e, 0x8b, 0x22, 0xb8, 0x81, \ - 0x90, 0x16, 0x91, 0x0a, 0x04, 0x79, 0x62, 0xff, 0x4b, 0x04, 0xf1, 0x5c, \ - 0x34, 0xeb, 0x69, 0xce, 0xef, 0xcb, 0x6e, 0xb6, 0x3b, 0x40, 0x55, 0xca, \ - 0x24, 0xc2, 0x3e, 0x25, 0x70, 0xee, 0x74, 0x2b, 0x0e, 0x9f, 0xc2, 0x82, \ - 0x9a, 0x20, 0x38, 0x77, 0xa1, 0x26, 0x8a, 0xca, 0x9f, 0x87, 0x75, 0x77, \ - 0xe3, 0xce, 0x65, 0xec, 0x71, 0x10, 0x35, 0xcb, 0xcb, 0x4f, 0x19, 0x43, \ - 0xeb, 0x30, 0xd0, 0xca, 0x2d, 0x3f, 0xca, 0x46, 0x14, 0x61, 0x99, 0x30, \ - 0x41, 0x32, 0xb5, 0x37, 0x63, 0x6f, 0x97 \ -} -/* END FILE */ - -/* This is taken from tests/data_files/cli-rsa.key. */ -/* BEGIN FILE string macro TEST_CLI_KEY_RSA_PEM tests/data_files/cli-rsa.key */ -#define TEST_CLI_KEY_RSA_PEM \ - "-----BEGIN RSA PRIVATE KEY-----\r\n" \ - "MIIEpAIBAAKCAQEAyHTEzLn5tXnpRdkUYLB9u5Pyax6fM60Nj4o8VmXl3ETZzGaF\r\n" \ - "B9X4J7BKNdBjngpuG7fa8H6r7gwQk4ZJGDTzqCrSV/Uu1C93KYRhTYJQj6eVSHD1\r\n" \ - "bk2y1RPD0hrt5kPqQhTrdOrA7R/UV06p86jt0uDBMHEwMjDV0/YI0FZPRo7yX/k9\r\n" \ - "Z5GIMC5Cst99++UMd//sMcB4j7/Cf8qtbCHWjdmLao5v4Jv4EFbMs44TFeY0BGbH\r\n" \ - "7vk2DmqV9gmaBmf0ZXH4yqSxJeD+PIs1BGe64E92hfx//DZrtenNLQNiTrM9AM+v\r\n" \ - "dqBpVoNq0qjU51Bx5rU2BXcFbXvI5MT9TNUhXwIDAQABAoIBAGdNtfYDiap6bzst\r\n" \ - "yhCiI8m9TtrhZw4MisaEaN/ll3XSjaOG2dvV6xMZCMV+5TeXDHOAZnY18Yi18vzz\r\n" \ - "4Ut2TnNFzizCECYNaA2fST3WgInnxUkV3YXAyP6CNxJaCmv2aA0yFr2kFVSeaKGt\r\n" \ - "ymvljNp2NVkvm7Th8fBQBO7I7AXhz43k0mR7XmPgewe8ApZOG3hstkOaMvbWAvWA\r\n" \ - "zCZupdDjZYjOJqlA4eEA4H8/w7F83r5CugeBE8LgEREjLPiyejrU5H1fubEY+h0d\r\n" \ - "l5HZBJ68ybTXfQ5U9o/QKA3dd0toBEhhdRUDGzWtjvwkEQfqF1reGWj/tod/gCpf\r\n" \ - "DFi6X0ECgYEA4wOv/pjSC3ty6TuOvKX2rOUiBrLXXv2JSxZnMoMiWI5ipLQt+RYT\r\n" \ - "VPafL/m7Dn6MbwjayOkcZhBwk5CNz5A6Q4lJ64Mq/lqHznRCQQ2Mc1G8eyDF/fYL\r\n" \ - "Ze2pLvwP9VD5jTc2miDfw+MnvJhywRRLcemDFP8k4hQVtm8PMp3ZmNECgYEA4gz7\r\n" \ - "wzObR4gn8ibe617uQPZjWzUj9dUHYd+in1gwBCIrtNnaRn9I9U/Q6tegRYpii4ys\r\n" \ - "c176NmU+umy6XmuSKV5qD9bSpZWG2nLFnslrN15Lm3fhZxoeMNhBaEDTnLT26yoi\r\n" \ - "33gp0mSSWy94ZEqipms+ULF6sY1ZtFW6tpGFoy8CgYAQHhnnvJflIs2ky4q10B60\r\n" \ - "ZcxFp3rtDpkp0JxhFLhiizFrujMtZSjYNm5U7KkgPVHhLELEUvCmOnKTt4ap/vZ0\r\n" \ - "BxJNe1GZH3pW6SAvGDQpl9sG7uu/vTFP+lCxukmzxB0DrrDcvorEkKMom7ZCCRvW\r\n" \ - "KZsZ6YeH2Z81BauRj218kQKBgQCUV/DgKP2985xDTT79N08jUo3hTP5MVYCCuj/+\r\n" \ - "UeEw1TvZcx3LJby7P6Xad6a1/BqveaGyFKIfEFIaBUBItk801sDDpDaYc4gL00Xc\r\n" \ - "7lFuBHOZkxJYlss5QrGpuOEl9ZwUt5IrFLBdYaKqNHzNVC1pCPfb/JyH6Dr2HUxq\r\n" \ - "gxUwAQKBgQCcU6G2L8AG9d9c0UpOyL1tMvFe5Ttw0KjlQVdsh1MP6yigYo9DYuwu\r\n" \ - "bHFVW2r0dBTqegP2/KTOxKzaHfC1qf0RGDsUoJCNJrd1cwoCLG8P2EF4w3OBrKqv\r\n" \ - "8u4ytY0F+Vlanj5lm3TaoHSVF1+NWPyOTiwevIECGKwSxvlki4fDAA==\r\n" \ - "-----END RSA PRIVATE KEY-----\r\n"/* END FILE */ - -/* This was generated from tests/data_files/cli-rsa.key.der using `xxd -i`. */ -/* BEGIN FILE binary macro TEST_CLI_KEY_RSA_DER tests/data_files/cli-rsa.key.der */ -#define TEST_CLI_KEY_RSA_DER { \ - 0x30, 0x82, 0x04, 0xa4, 0x02, 0x01, 0x00, 0x02, 0x82, 0x01, 0x01, 0x00, \ - 0xc8, 0x74, 0xc4, 0xcc, 0xb9, 0xf9, 0xb5, 0x79, 0xe9, 0x45, 0xd9, 0x14, \ - 0x60, 0xb0, 0x7d, 0xbb, 0x93, 0xf2, 0x6b, 0x1e, 0x9f, 0x33, 0xad, 0x0d, \ - 0x8f, 0x8a, 0x3c, 0x56, 0x65, 0xe5, 0xdc, 0x44, 0xd9, 0xcc, 0x66, 0x85, \ - 0x07, 0xd5, 0xf8, 0x27, 0xb0, 0x4a, 0x35, 0xd0, 0x63, 0x9e, 0x0a, 0x6e, \ - 0x1b, 0xb7, 0xda, 0xf0, 0x7e, 0xab, 0xee, 0x0c, 0x10, 0x93, 0x86, 0x49, \ - 0x18, 0x34, 0xf3, 0xa8, 0x2a, 0xd2, 0x57, 0xf5, 0x2e, 0xd4, 0x2f, 0x77, \ - 0x29, 0x84, 0x61, 0x4d, 0x82, 0x50, 0x8f, 0xa7, 0x95, 0x48, 0x70, 0xf5, \ - 0x6e, 0x4d, 0xb2, 0xd5, 0x13, 0xc3, 0xd2, 0x1a, 0xed, 0xe6, 0x43, 0xea, \ - 0x42, 0x14, 0xeb, 0x74, 0xea, 0xc0, 0xed, 0x1f, 0xd4, 0x57, 0x4e, 0xa9, \ - 0xf3, 0xa8, 0xed, 0xd2, 0xe0, 0xc1, 0x30, 0x71, 0x30, 0x32, 0x30, 0xd5, \ - 0xd3, 0xf6, 0x08, 0xd0, 0x56, 0x4f, 0x46, 0x8e, 0xf2, 0x5f, 0xf9, 0x3d, \ - 0x67, 0x91, 0x88, 0x30, 0x2e, 0x42, 0xb2, 0xdf, 0x7d, 0xfb, 0xe5, 0x0c, \ - 0x77, 0xff, 0xec, 0x31, 0xc0, 0x78, 0x8f, 0xbf, 0xc2, 0x7f, 0xca, 0xad, \ - 0x6c, 0x21, 0xd6, 0x8d, 0xd9, 0x8b, 0x6a, 0x8e, 0x6f, 0xe0, 0x9b, 0xf8, \ - 0x10, 0x56, 0xcc, 0xb3, 0x8e, 0x13, 0x15, 0xe6, 0x34, 0x04, 0x66, 0xc7, \ - 0xee, 0xf9, 0x36, 0x0e, 0x6a, 0x95, 0xf6, 0x09, 0x9a, 0x06, 0x67, 0xf4, \ - 0x65, 0x71, 0xf8, 0xca, 0xa4, 0xb1, 0x25, 0xe0, 0xfe, 0x3c, 0x8b, 0x35, \ - 0x04, 0x67, 0xba, 0xe0, 0x4f, 0x76, 0x85, 0xfc, 0x7f, 0xfc, 0x36, 0x6b, \ - 0xb5, 0xe9, 0xcd, 0x2d, 0x03, 0x62, 0x4e, 0xb3, 0x3d, 0x00, 0xcf, 0xaf, \ - 0x76, 0xa0, 0x69, 0x56, 0x83, 0x6a, 0xd2, 0xa8, 0xd4, 0xe7, 0x50, 0x71, \ - 0xe6, 0xb5, 0x36, 0x05, 0x77, 0x05, 0x6d, 0x7b, 0xc8, 0xe4, 0xc4, 0xfd, \ - 0x4c, 0xd5, 0x21, 0x5f, 0x02, 0x03, 0x01, 0x00, 0x01, 0x02, 0x82, 0x01, \ - 0x00, 0x67, 0x4d, 0xb5, 0xf6, 0x03, 0x89, 0xaa, 0x7a, 0x6f, 0x3b, 0x2d, \ - 0xca, 0x10, 0xa2, 0x23, 0xc9, 0xbd, 0x4e, 0xda, 0xe1, 0x67, 0x0e, 0x0c, \ - 0x8a, 0xc6, 0x84, 0x68, 0xdf, 0xe5, 0x97, 0x75, 0xd2, 0x8d, 0xa3, 0x86, \ - 0xd9, 0xdb, 0xd5, 0xeb, 0x13, 0x19, 0x08, 0xc5, 0x7e, 0xe5, 0x37, 0x97, \ - 0x0c, 0x73, 0x80, 0x66, 0x76, 0x35, 0xf1, 0x88, 0xb5, 0xf2, 0xfc, 0xf3, \ - 0xe1, 0x4b, 0x76, 0x4e, 0x73, 0x45, 0xce, 0x2c, 0xc2, 0x10, 0x26, 0x0d, \ - 0x68, 0x0d, 0x9f, 0x49, 0x3d, 0xd6, 0x80, 0x89, 0xe7, 0xc5, 0x49, 0x15, \ - 0xdd, 0x85, 0xc0, 0xc8, 0xfe, 0x82, 0x37, 0x12, 0x5a, 0x0a, 0x6b, 0xf6, \ - 0x68, 0x0d, 0x32, 0x16, 0xbd, 0xa4, 0x15, 0x54, 0x9e, 0x68, 0xa1, 0xad, \ - 0xca, 0x6b, 0xe5, 0x8c, 0xda, 0x76, 0x35, 0x59, 0x2f, 0x9b, 0xb4, 0xe1, \ - 0xf1, 0xf0, 0x50, 0x04, 0xee, 0xc8, 0xec, 0x05, 0xe1, 0xcf, 0x8d, 0xe4, \ - 0xd2, 0x64, 0x7b, 0x5e, 0x63, 0xe0, 0x7b, 0x07, 0xbc, 0x02, 0x96, 0x4e, \ - 0x1b, 0x78, 0x6c, 0xb6, 0x43, 0x9a, 0x32, 0xf6, 0xd6, 0x02, 0xf5, 0x80, \ - 0xcc, 0x26, 0x6e, 0xa5, 0xd0, 0xe3, 0x65, 0x88, 0xce, 0x26, 0xa9, 0x40, \ - 0xe1, 0xe1, 0x00, 0xe0, 0x7f, 0x3f, 0xc3, 0xb1, 0x7c, 0xde, 0xbe, 0x42, \ - 0xba, 0x07, 0x81, 0x13, 0xc2, 0xe0, 0x11, 0x11, 0x23, 0x2c, 0xf8, 0xb2, \ - 0x7a, 0x3a, 0xd4, 0xe4, 0x7d, 0x5f, 0xb9, 0xb1, 0x18, 0xfa, 0x1d, 0x1d, \ - 0x97, 0x91, 0xd9, 0x04, 0x9e, 0xbc, 0xc9, 0xb4, 0xd7, 0x7d, 0x0e, 0x54, \ - 0xf6, 0x8f, 0xd0, 0x28, 0x0d, 0xdd, 0x77, 0x4b, 0x68, 0x04, 0x48, 0x61, \ - 0x75, 0x15, 0x03, 0x1b, 0x35, 0xad, 0x8e, 0xfc, 0x24, 0x11, 0x07, 0xea, \ - 0x17, 0x5a, 0xde, 0x19, 0x68, 0xff, 0xb6, 0x87, 0x7f, 0x80, 0x2a, 0x5f, \ - 0x0c, 0x58, 0xba, 0x5f, 0x41, 0x02, 0x81, 0x81, 0x00, 0xe3, 0x03, 0xaf, \ - 0xfe, 0x98, 0xd2, 0x0b, 0x7b, 0x72, 0xe9, 0x3b, 0x8e, 0xbc, 0xa5, 0xf6, \ - 0xac, 0xe5, 0x22, 0x06, 0xb2, 0xd7, 0x5e, 0xfd, 0x89, 0x4b, 0x16, 0x67, \ - 0x32, 0x83, 0x22, 0x58, 0x8e, 0x62, 0xa4, 0xb4, 0x2d, 0xf9, 0x16, 0x13, \ - 0x54, 0xf6, 0x9f, 0x2f, 0xf9, 0xbb, 0x0e, 0x7e, 0x8c, 0x6f, 0x08, 0xda, \ - 0xc8, 0xe9, 0x1c, 0x66, 0x10, 0x70, 0x93, 0x90, 0x8d, 0xcf, 0x90, 0x3a, \ - 0x43, 0x89, 0x49, 0xeb, 0x83, 0x2a, 0xfe, 0x5a, 0x87, 0xce, 0x74, 0x42, \ - 0x41, 0x0d, 0x8c, 0x73, 0x51, 0xbc, 0x7b, 0x20, 0xc5, 0xfd, 0xf6, 0x0b, \ - 0x65, 0xed, 0xa9, 0x2e, 0xfc, 0x0f, 0xf5, 0x50, 0xf9, 0x8d, 0x37, 0x36, \ - 0x9a, 0x20, 0xdf, 0xc3, 0xe3, 0x27, 0xbc, 0x98, 0x72, 0xc1, 0x14, 0x4b, \ - 0x71, 0xe9, 0x83, 0x14, 0xff, 0x24, 0xe2, 0x14, 0x15, 0xb6, 0x6f, 0x0f, \ - 0x32, 0x9d, 0xd9, 0x98, 0xd1, 0x02, 0x81, 0x81, 0x00, 0xe2, 0x0c, 0xfb, \ - 0xc3, 0x33, 0x9b, 0x47, 0x88, 0x27, 0xf2, 0x26, 0xde, 0xeb, 0x5e, 0xee, \ - 0x40, 0xf6, 0x63, 0x5b, 0x35, 0x23, 0xf5, 0xd5, 0x07, 0x61, 0xdf, 0xa2, \ - 0x9f, 0x58, 0x30, 0x04, 0x22, 0x2b, 0xb4, 0xd9, 0xda, 0x46, 0x7f, 0x48, \ - 0xf5, 0x4f, 0xd0, 0xea, 0xd7, 0xa0, 0x45, 0x8a, 0x62, 0x8b, 0x8c, 0xac, \ - 0x73, 0x5e, 0xfa, 0x36, 0x65, 0x3e, 0xba, 0x6c, 0xba, 0x5e, 0x6b, 0x92, \ - 0x29, 0x5e, 0x6a, 0x0f, 0xd6, 0xd2, 0xa5, 0x95, 0x86, 0xda, 0x72, 0xc5, \ - 0x9e, 0xc9, 0x6b, 0x37, 0x5e, 0x4b, 0x9b, 0x77, 0xe1, 0x67, 0x1a, 0x1e, \ - 0x30, 0xd8, 0x41, 0x68, 0x40, 0xd3, 0x9c, 0xb4, 0xf6, 0xeb, 0x2a, 0x22, \ - 0xdf, 0x78, 0x29, 0xd2, 0x64, 0x92, 0x5b, 0x2f, 0x78, 0x64, 0x4a, 0xa2, \ - 0xa6, 0x6b, 0x3e, 0x50, 0xb1, 0x7a, 0xb1, 0x8d, 0x59, 0xb4, 0x55, 0xba, \ - 0xb6, 0x91, 0x85, 0xa3, 0x2f, 0x02, 0x81, 0x80, 0x10, 0x1e, 0x19, 0xe7, \ - 0xbc, 0x97, 0xe5, 0x22, 0xcd, 0xa4, 0xcb, 0x8a, 0xb5, 0xd0, 0x1e, 0xb4, \ - 0x65, 0xcc, 0x45, 0xa7, 0x7a, 0xed, 0x0e, 0x99, 0x29, 0xd0, 0x9c, 0x61, \ - 0x14, 0xb8, 0x62, 0x8b, 0x31, 0x6b, 0xba, 0x33, 0x2d, 0x65, 0x28, 0xd8, \ - 0x36, 0x6e, 0x54, 0xec, 0xa9, 0x20, 0x3d, 0x51, 0xe1, 0x2c, 0x42, 0xc4, \ - 0x52, 0xf0, 0xa6, 0x3a, 0x72, 0x93, 0xb7, 0x86, 0xa9, 0xfe, 0xf6, 0x74, \ - 0x07, 0x12, 0x4d, 0x7b, 0x51, 0x99, 0x1f, 0x7a, 0x56, 0xe9, 0x20, 0x2f, \ - 0x18, 0x34, 0x29, 0x97, 0xdb, 0x06, 0xee, 0xeb, 0xbf, 0xbd, 0x31, 0x4f, \ - 0xfa, 0x50, 0xb1, 0xba, 0x49, 0xb3, 0xc4, 0x1d, 0x03, 0xae, 0xb0, 0xdc, \ - 0xbe, 0x8a, 0xc4, 0x90, 0xa3, 0x28, 0x9b, 0xb6, 0x42, 0x09, 0x1b, 0xd6, \ - 0x29, 0x9b, 0x19, 0xe9, 0x87, 0x87, 0xd9, 0x9f, 0x35, 0x05, 0xab, 0x91, \ - 0x8f, 0x6d, 0x7c, 0x91, 0x02, 0x81, 0x81, 0x00, 0x94, 0x57, 0xf0, 0xe0, \ - 0x28, 0xfd, 0xbd, 0xf3, 0x9c, 0x43, 0x4d, 0x3e, 0xfd, 0x37, 0x4f, 0x23, \ - 0x52, 0x8d, 0xe1, 0x4c, 0xfe, 0x4c, 0x55, 0x80, 0x82, 0xba, 0x3f, 0xfe, \ - 0x51, 0xe1, 0x30, 0xd5, 0x3b, 0xd9, 0x73, 0x1d, 0xcb, 0x25, 0xbc, 0xbb, \ - 0x3f, 0xa5, 0xda, 0x77, 0xa6, 0xb5, 0xfc, 0x1a, 0xaf, 0x79, 0xa1, 0xb2, \ - 0x14, 0xa2, 0x1f, 0x10, 0x52, 0x1a, 0x05, 0x40, 0x48, 0xb6, 0x4f, 0x34, \ - 0xd6, 0xc0, 0xc3, 0xa4, 0x36, 0x98, 0x73, 0x88, 0x0b, 0xd3, 0x45, 0xdc, \ - 0xee, 0x51, 0x6e, 0x04, 0x73, 0x99, 0x93, 0x12, 0x58, 0x96, 0xcb, 0x39, \ - 0x42, 0xb1, 0xa9, 0xb8, 0xe1, 0x25, 0xf5, 0x9c, 0x14, 0xb7, 0x92, 0x2b, \ - 0x14, 0xb0, 0x5d, 0x61, 0xa2, 0xaa, 0x34, 0x7c, 0xcd, 0x54, 0x2d, 0x69, \ - 0x08, 0xf7, 0xdb, 0xfc, 0x9c, 0x87, 0xe8, 0x3a, 0xf6, 0x1d, 0x4c, 0x6a, \ - 0x83, 0x15, 0x30, 0x01, 0x02, 0x81, 0x81, 0x00, 0x9c, 0x53, 0xa1, 0xb6, \ - 0x2f, 0xc0, 0x06, 0xf5, 0xdf, 0x5c, 0xd1, 0x4a, 0x4e, 0xc8, 0xbd, 0x6d, \ - 0x32, 0xf1, 0x5e, 0xe5, 0x3b, 0x70, 0xd0, 0xa8, 0xe5, 0x41, 0x57, 0x6c, \ - 0x87, 0x53, 0x0f, 0xeb, 0x28, 0xa0, 0x62, 0x8f, 0x43, 0x62, 0xec, 0x2e, \ - 0x6c, 0x71, 0x55, 0x5b, 0x6a, 0xf4, 0x74, 0x14, 0xea, 0x7a, 0x03, 0xf6, \ - 0xfc, 0xa4, 0xce, 0xc4, 0xac, 0xda, 0x1d, 0xf0, 0xb5, 0xa9, 0xfd, 0x11, \ - 0x18, 0x3b, 0x14, 0xa0, 0x90, 0x8d, 0x26, 0xb7, 0x75, 0x73, 0x0a, 0x02, \ - 0x2c, 0x6f, 0x0f, 0xd8, 0x41, 0x78, 0xc3, 0x73, 0x81, 0xac, 0xaa, 0xaf, \ - 0xf2, 0xee, 0x32, 0xb5, 0x8d, 0x05, 0xf9, 0x59, 0x5a, 0x9e, 0x3e, 0x65, \ - 0x9b, 0x74, 0xda, 0xa0, 0x74, 0x95, 0x17, 0x5f, 0x8d, 0x58, 0xfc, 0x8e, \ - 0x4e, 0x2c, 0x1e, 0xbc, 0x81, 0x02, 0x18, 0xac, 0x12, 0xc6, 0xf9, 0x64, \ - 0x8b, 0x87, 0xc3, 0x00 \ -} -/* END FILE */ - -/* - * - * Test certificates and keys as C variables - * - */ - -/* - * CA - */ - -const char mbedtls_test_ca_crt_ec_pem[] = TEST_CA_CRT_EC_PEM; -const char mbedtls_test_ca_key_ec_pem[] = TEST_CA_KEY_EC_PEM; -const char mbedtls_test_ca_pwd_ec_pem[] = TEST_CA_PWD_EC_PEM; -const char mbedtls_test_ca_key_rsa_pem[] = TEST_CA_KEY_RSA_PEM; -const char mbedtls_test_ca_pwd_rsa_pem[] = TEST_CA_PWD_RSA_PEM; -const char mbedtls_test_ca_crt_rsa_sha1_pem[] = TEST_CA_CRT_RSA_SHA1_PEM; -const char mbedtls_test_ca_crt_rsa_sha256_pem[] = TEST_CA_CRT_RSA_SHA256_PEM; - -const unsigned char mbedtls_test_ca_crt_ec_der[] = TEST_CA_CRT_EC_DER; -const unsigned char mbedtls_test_ca_key_ec_der[] = TEST_CA_KEY_EC_DER; -const unsigned char mbedtls_test_ca_key_rsa_der[] = TEST_CA_KEY_RSA_DER; -const unsigned char mbedtls_test_ca_crt_rsa_sha1_der[] = - TEST_CA_CRT_RSA_SHA1_DER; -const unsigned char mbedtls_test_ca_crt_rsa_sha256_der[] = - TEST_CA_CRT_RSA_SHA256_DER; - -const size_t mbedtls_test_ca_crt_ec_pem_len = - sizeof(mbedtls_test_ca_crt_ec_pem); -const size_t mbedtls_test_ca_key_ec_pem_len = - sizeof(mbedtls_test_ca_key_ec_pem); -const size_t mbedtls_test_ca_pwd_ec_pem_len = - sizeof(mbedtls_test_ca_pwd_ec_pem) - 1; -const size_t mbedtls_test_ca_key_rsa_pem_len = - sizeof(mbedtls_test_ca_key_rsa_pem); -const size_t mbedtls_test_ca_pwd_rsa_pem_len = - sizeof(mbedtls_test_ca_pwd_rsa_pem) - 1; -const size_t mbedtls_test_ca_crt_rsa_sha1_pem_len = - sizeof(mbedtls_test_ca_crt_rsa_sha1_pem); -const size_t mbedtls_test_ca_crt_rsa_sha256_pem_len = - sizeof(mbedtls_test_ca_crt_rsa_sha256_pem); - -const size_t mbedtls_test_ca_crt_ec_der_len = - sizeof(mbedtls_test_ca_crt_ec_der); -const size_t mbedtls_test_ca_key_ec_der_len = - sizeof(mbedtls_test_ca_key_ec_der); -const size_t mbedtls_test_ca_pwd_ec_der_len = 0; -const size_t mbedtls_test_ca_key_rsa_der_len = - sizeof(mbedtls_test_ca_key_rsa_der); -const size_t mbedtls_test_ca_pwd_rsa_der_len = 0; -const size_t mbedtls_test_ca_crt_rsa_sha1_der_len = - sizeof(mbedtls_test_ca_crt_rsa_sha1_der); -const size_t mbedtls_test_ca_crt_rsa_sha256_der_len = - sizeof(mbedtls_test_ca_crt_rsa_sha256_der); - -/* - * Server - */ - -const char mbedtls_test_srv_crt_ec_pem[] = TEST_SRV_CRT_EC_PEM; -const char mbedtls_test_srv_key_ec_pem[] = TEST_SRV_KEY_EC_PEM; -const char mbedtls_test_srv_pwd_ec_pem[] = ""; -const char mbedtls_test_srv_key_rsa_pem[] = TEST_SRV_KEY_RSA_PEM; -const char mbedtls_test_srv_pwd_rsa_pem[] = ""; -const char mbedtls_test_srv_crt_rsa_sha1_pem[] = TEST_SRV_CRT_RSA_SHA1_PEM; -const char mbedtls_test_srv_crt_rsa_sha256_pem[] = TEST_SRV_CRT_RSA_SHA256_PEM; - -const unsigned char mbedtls_test_srv_crt_ec_der[] = TEST_SRV_CRT_EC_DER; -const unsigned char mbedtls_test_srv_key_ec_der[] = TEST_SRV_KEY_EC_DER; -const unsigned char mbedtls_test_srv_key_rsa_der[] = TEST_SRV_KEY_RSA_DER; -const unsigned char mbedtls_test_srv_crt_rsa_sha1_der[] = - TEST_SRV_CRT_RSA_SHA1_DER; -const unsigned char mbedtls_test_srv_crt_rsa_sha256_der[] = - TEST_SRV_CRT_RSA_SHA256_DER; - -const size_t mbedtls_test_srv_crt_ec_pem_len = - sizeof(mbedtls_test_srv_crt_ec_pem); -const size_t mbedtls_test_srv_key_ec_pem_len = - sizeof(mbedtls_test_srv_key_ec_pem); -const size_t mbedtls_test_srv_pwd_ec_pem_len = - sizeof(mbedtls_test_srv_pwd_ec_pem) - 1; -const size_t mbedtls_test_srv_key_rsa_pem_len = - sizeof(mbedtls_test_srv_key_rsa_pem); -const size_t mbedtls_test_srv_pwd_rsa_pem_len = - sizeof(mbedtls_test_srv_pwd_rsa_pem) - 1; -const size_t mbedtls_test_srv_crt_rsa_sha1_pem_len = - sizeof(mbedtls_test_srv_crt_rsa_sha1_pem); -const size_t mbedtls_test_srv_crt_rsa_sha256_pem_len = - sizeof(mbedtls_test_srv_crt_rsa_sha256_pem); - -const size_t mbedtls_test_srv_crt_ec_der_len = - sizeof(mbedtls_test_srv_crt_ec_der); -const size_t mbedtls_test_srv_key_ec_der_len = - sizeof(mbedtls_test_srv_key_ec_der); -const size_t mbedtls_test_srv_pwd_ec_der_len = 0; -const size_t mbedtls_test_srv_key_rsa_der_len = - sizeof(mbedtls_test_srv_key_rsa_der); -const size_t mbedtls_test_srv_pwd_rsa_der_len = 0; -const size_t mbedtls_test_srv_crt_rsa_sha1_der_len = - sizeof(mbedtls_test_srv_crt_rsa_sha1_der); -const size_t mbedtls_test_srv_crt_rsa_sha256_der_len = - sizeof(mbedtls_test_srv_crt_rsa_sha256_der); - -/* - * Client - */ - -const char mbedtls_test_cli_crt_ec_pem[] = TEST_CLI_CRT_EC_PEM; -const char mbedtls_test_cli_key_ec_pem[] = TEST_CLI_KEY_EC_PEM; -const char mbedtls_test_cli_pwd_ec_pem[] = ""; -const char mbedtls_test_cli_key_rsa_pem[] = TEST_CLI_KEY_RSA_PEM; -const char mbedtls_test_cli_pwd_rsa_pem[] = ""; -const char mbedtls_test_cli_crt_rsa_pem[] = TEST_CLI_CRT_RSA_PEM; - -const unsigned char mbedtls_test_cli_crt_ec_der[] = TEST_CLI_CRT_EC_DER; -const unsigned char mbedtls_test_cli_key_ec_der[] = TEST_CLI_KEY_EC_DER; -const unsigned char mbedtls_test_cli_key_rsa_der[] = TEST_CLI_KEY_RSA_DER; -const unsigned char mbedtls_test_cli_crt_rsa_der[] = TEST_CLI_CRT_RSA_DER; - -const size_t mbedtls_test_cli_crt_ec_pem_len = - sizeof(mbedtls_test_cli_crt_ec_pem); -const size_t mbedtls_test_cli_key_ec_pem_len = - sizeof(mbedtls_test_cli_key_ec_pem); -const size_t mbedtls_test_cli_pwd_ec_pem_len = - sizeof(mbedtls_test_cli_pwd_ec_pem) - 1; -const size_t mbedtls_test_cli_key_rsa_pem_len = - sizeof(mbedtls_test_cli_key_rsa_pem); -const size_t mbedtls_test_cli_pwd_rsa_pem_len = - sizeof(mbedtls_test_cli_pwd_rsa_pem) - 1; -const size_t mbedtls_test_cli_crt_rsa_pem_len = - sizeof(mbedtls_test_cli_crt_rsa_pem); - -const size_t mbedtls_test_cli_crt_ec_der_len = - sizeof(mbedtls_test_cli_crt_ec_der); -const size_t mbedtls_test_cli_key_ec_der_len = - sizeof(mbedtls_test_cli_key_ec_der); -const size_t mbedtls_test_cli_key_rsa_der_len = - sizeof(mbedtls_test_cli_key_rsa_der); -const size_t mbedtls_test_cli_crt_rsa_der_len = - sizeof(mbedtls_test_cli_crt_rsa_der); - -/* - * - * Definitions of test CRTs without specification of all parameters, choosing - * them automatically according to the config. For example, mbedtls_test_ca_crt - * is one of mbedtls_test_ca_crt_{rsa|ec}_{sha1|sha256}_{pem|der}. - * - */ - -/* - * Dispatch between PEM and DER according to config - */ - -#if defined(MBEDTLS_PEM_PARSE_C) - -/* PEM encoded test CA certificates and keys */ - -#define TEST_CA_KEY_RSA TEST_CA_KEY_RSA_PEM -#define TEST_CA_PWD_RSA TEST_CA_PWD_RSA_PEM -#define TEST_CA_CRT_RSA_SHA256 TEST_CA_CRT_RSA_SHA256_PEM -#define TEST_CA_CRT_RSA_SHA1 TEST_CA_CRT_RSA_SHA1_PEM -#define TEST_CA_KEY_EC TEST_CA_KEY_EC_PEM -#define TEST_CA_PWD_EC TEST_CA_PWD_EC_PEM -#define TEST_CA_CRT_EC TEST_CA_CRT_EC_PEM - -/* PEM encoded test server certificates and keys */ - -#define TEST_SRV_KEY_RSA TEST_SRV_KEY_RSA_PEM -#define TEST_SRV_PWD_RSA "" -#define TEST_SRV_CRT_RSA_SHA256 TEST_SRV_CRT_RSA_SHA256_PEM -#define TEST_SRV_CRT_RSA_SHA1 TEST_SRV_CRT_RSA_SHA1_PEM -#define TEST_SRV_KEY_EC TEST_SRV_KEY_EC_PEM -#define TEST_SRV_PWD_EC "" -#define TEST_SRV_CRT_EC TEST_SRV_CRT_EC_PEM - -/* PEM encoded test client certificates and keys */ - -#define TEST_CLI_KEY_RSA TEST_CLI_KEY_RSA_PEM -#define TEST_CLI_PWD_RSA "" -#define TEST_CLI_CRT_RSA TEST_CLI_CRT_RSA_PEM -#define TEST_CLI_KEY_EC TEST_CLI_KEY_EC_PEM -#define TEST_CLI_PWD_EC "" -#define TEST_CLI_CRT_EC TEST_CLI_CRT_EC_PEM - -#else /* MBEDTLS_PEM_PARSE_C */ - -/* DER encoded test CA certificates and keys */ - -#define TEST_CA_KEY_RSA TEST_CA_KEY_RSA_DER -#define TEST_CA_PWD_RSA "" -#define TEST_CA_CRT_RSA_SHA256 TEST_CA_CRT_RSA_SHA256_DER -#define TEST_CA_CRT_RSA_SHA1 TEST_CA_CRT_RSA_SHA1_DER -#define TEST_CA_KEY_EC TEST_CA_KEY_EC_DER -#define TEST_CA_PWD_EC "" -#define TEST_CA_CRT_EC TEST_CA_CRT_EC_DER - -/* DER encoded test server certificates and keys */ - -#define TEST_SRV_KEY_RSA TEST_SRV_KEY_RSA_DER -#define TEST_SRV_PWD_RSA "" -#define TEST_SRV_CRT_RSA_SHA256 TEST_SRV_CRT_RSA_SHA256_DER -#define TEST_SRV_CRT_RSA_SHA1 TEST_SRV_CRT_RSA_SHA1_DER -#define TEST_SRV_KEY_EC TEST_SRV_KEY_EC_DER -#define TEST_SRV_PWD_EC "" -#define TEST_SRV_CRT_EC TEST_SRV_CRT_EC_DER - -/* DER encoded test client certificates and keys */ - -#define TEST_CLI_KEY_RSA TEST_CLI_KEY_RSA_DER -#define TEST_CLI_PWD_RSA "" -#define TEST_CLI_CRT_RSA TEST_CLI_CRT_RSA_DER -#define TEST_CLI_KEY_EC TEST_CLI_KEY_EC_DER -#define TEST_CLI_PWD_EC "" -#define TEST_CLI_CRT_EC TEST_CLI_CRT_EC_DER - -#endif /* MBEDTLS_PEM_PARSE_C */ - -const char mbedtls_test_ca_key_rsa[] = TEST_CA_KEY_RSA; -const char mbedtls_test_ca_pwd_rsa[] = TEST_CA_PWD_RSA; -const char mbedtls_test_ca_crt_rsa_sha256[] = TEST_CA_CRT_RSA_SHA256; -const char mbedtls_test_ca_crt_rsa_sha1[] = TEST_CA_CRT_RSA_SHA1; -const char mbedtls_test_ca_key_ec[] = TEST_CA_KEY_EC; -const char mbedtls_test_ca_pwd_ec[] = TEST_CA_PWD_EC; -const char mbedtls_test_ca_crt_ec[] = TEST_CA_CRT_EC; - -const char mbedtls_test_srv_key_rsa[] = TEST_SRV_KEY_RSA; -const char mbedtls_test_srv_pwd_rsa[] = TEST_SRV_PWD_RSA; -const char mbedtls_test_srv_crt_rsa_sha256[] = TEST_SRV_CRT_RSA_SHA256; -const char mbedtls_test_srv_crt_rsa_sha1[] = TEST_SRV_CRT_RSA_SHA1; -const char mbedtls_test_srv_key_ec[] = TEST_SRV_KEY_EC; -const char mbedtls_test_srv_pwd_ec[] = TEST_SRV_PWD_EC; -const char mbedtls_test_srv_crt_ec[] = TEST_SRV_CRT_EC; - -const char mbedtls_test_cli_key_rsa[] = TEST_CLI_KEY_RSA; -const char mbedtls_test_cli_pwd_rsa[] = TEST_CLI_PWD_RSA; -const char mbedtls_test_cli_crt_rsa[] = TEST_CLI_CRT_RSA; -const char mbedtls_test_cli_key_ec[] = TEST_CLI_KEY_EC; -const char mbedtls_test_cli_pwd_ec[] = TEST_CLI_PWD_EC; -const char mbedtls_test_cli_crt_ec[] = TEST_CLI_CRT_EC; - -const size_t mbedtls_test_ca_key_rsa_len = - sizeof(mbedtls_test_ca_key_rsa); -const size_t mbedtls_test_ca_pwd_rsa_len = - sizeof(mbedtls_test_ca_pwd_rsa) - 1; -const size_t mbedtls_test_ca_crt_rsa_sha256_len = - sizeof(mbedtls_test_ca_crt_rsa_sha256); -const size_t mbedtls_test_ca_crt_rsa_sha1_len = - sizeof(mbedtls_test_ca_crt_rsa_sha1); -const size_t mbedtls_test_ca_key_ec_len = - sizeof(mbedtls_test_ca_key_ec); -const size_t mbedtls_test_ca_pwd_ec_len = - sizeof(mbedtls_test_ca_pwd_ec) - 1; -const size_t mbedtls_test_ca_crt_ec_len = - sizeof(mbedtls_test_ca_crt_ec); - -const size_t mbedtls_test_srv_key_rsa_len = - sizeof(mbedtls_test_srv_key_rsa); -const size_t mbedtls_test_srv_pwd_rsa_len = - sizeof(mbedtls_test_srv_pwd_rsa) -1; -const size_t mbedtls_test_srv_crt_rsa_sha256_len = - sizeof(mbedtls_test_srv_crt_rsa_sha256); -const size_t mbedtls_test_srv_crt_rsa_sha1_len = - sizeof(mbedtls_test_srv_crt_rsa_sha1); -const size_t mbedtls_test_srv_key_ec_len = - sizeof(mbedtls_test_srv_key_ec); -const size_t mbedtls_test_srv_pwd_ec_len = - sizeof(mbedtls_test_srv_pwd_ec) - 1; -const size_t mbedtls_test_srv_crt_ec_len = - sizeof(mbedtls_test_srv_crt_ec); - -const size_t mbedtls_test_cli_key_rsa_len = - sizeof(mbedtls_test_cli_key_rsa); -const size_t mbedtls_test_cli_pwd_rsa_len = - sizeof(mbedtls_test_cli_pwd_rsa) - 1; -const size_t mbedtls_test_cli_crt_rsa_len = - sizeof(mbedtls_test_cli_crt_rsa); -const size_t mbedtls_test_cli_key_ec_len = - sizeof(mbedtls_test_cli_key_ec); -const size_t mbedtls_test_cli_pwd_ec_len = - sizeof(mbedtls_test_cli_pwd_ec) - 1; -const size_t mbedtls_test_cli_crt_ec_len = - sizeof(mbedtls_test_cli_crt_ec); - -/* - * Dispatch between SHA-1 and SHA-256 - */ - -#if defined(MBEDTLS_SHA256_C) -#define TEST_CA_CRT_RSA TEST_CA_CRT_RSA_SHA256 -#define TEST_SRV_CRT_RSA TEST_SRV_CRT_RSA_SHA256 -#else -#define TEST_CA_CRT_RSA TEST_CA_CRT_RSA_SHA1 -#define TEST_SRV_CRT_RSA TEST_SRV_CRT_RSA_SHA1 -#endif /* MBEDTLS_SHA256_C */ - -const char mbedtls_test_ca_crt_rsa[] = TEST_CA_CRT_RSA; -const char mbedtls_test_srv_crt_rsa[] = TEST_SRV_CRT_RSA; - -const size_t mbedtls_test_ca_crt_rsa_len = - sizeof(mbedtls_test_ca_crt_rsa); -const size_t mbedtls_test_srv_crt_rsa_len = - sizeof(mbedtls_test_srv_crt_rsa); - -/* - * Dispatch between RSA and EC - */ - -#if defined(MBEDTLS_RSA_C) - -#define TEST_CA_KEY TEST_CA_KEY_RSA -#define TEST_CA_PWD TEST_CA_PWD_RSA -#define TEST_CA_CRT TEST_CA_CRT_RSA - -#define TEST_SRV_KEY TEST_SRV_KEY_RSA -#define TEST_SRV_PWD TEST_SRV_PWD_RSA -#define TEST_SRV_CRT TEST_SRV_CRT_RSA - -#define TEST_CLI_KEY TEST_CLI_KEY_RSA -#define TEST_CLI_PWD TEST_CLI_PWD_RSA -#define TEST_CLI_CRT TEST_CLI_CRT_RSA - -#else /* no RSA, so assume ECDSA */ - -#define TEST_CA_KEY TEST_CA_KEY_EC -#define TEST_CA_PWD TEST_CA_PWD_EC -#define TEST_CA_CRT TEST_CA_CRT_EC - -#define TEST_SRV_KEY TEST_SRV_KEY_EC -#define TEST_SRV_PWD TEST_SRV_PWD_EC -#define TEST_SRV_CRT TEST_SRV_CRT_EC - -#define TEST_CLI_KEY TEST_CLI_KEY_EC -#define TEST_CLI_PWD TEST_CLI_PWD_EC -#define TEST_CLI_CRT TEST_CLI_CRT_EC -#endif /* MBEDTLS_RSA_C */ - -/* API stability forces us to declare - * mbedtls_test_{ca|srv|cli}_{key|pwd|crt} - * as pointers. */ -static const char test_ca_key[] = TEST_CA_KEY; -static const char test_ca_pwd[] = TEST_CA_PWD; -static const char test_ca_crt[] = TEST_CA_CRT; - -static const char test_srv_key[] = TEST_SRV_KEY; -static const char test_srv_pwd[] = TEST_SRV_PWD; -static const char test_srv_crt[] = TEST_SRV_CRT; - -static const char test_cli_key[] = TEST_CLI_KEY; -static const char test_cli_pwd[] = TEST_CLI_PWD; -static const char test_cli_crt[] = TEST_CLI_CRT; - -const char *mbedtls_test_ca_key = test_ca_key; -const char *mbedtls_test_ca_pwd = test_ca_pwd; -const char *mbedtls_test_ca_crt = test_ca_crt; - -const char *mbedtls_test_srv_key = test_srv_key; -const char *mbedtls_test_srv_pwd = test_srv_pwd; -const char *mbedtls_test_srv_crt = test_srv_crt; - -const char *mbedtls_test_cli_key = test_cli_key; -const char *mbedtls_test_cli_pwd = test_cli_pwd; -const char *mbedtls_test_cli_crt = test_cli_crt; - -const size_t mbedtls_test_ca_key_len = - sizeof(test_ca_key); -const size_t mbedtls_test_ca_pwd_len = - sizeof(test_ca_pwd) - 1; -const size_t mbedtls_test_ca_crt_len = - sizeof(test_ca_crt); - -const size_t mbedtls_test_srv_key_len = - sizeof(test_srv_key); -const size_t mbedtls_test_srv_pwd_len = - sizeof(test_srv_pwd) - 1; -const size_t mbedtls_test_srv_crt_len = - sizeof(test_srv_crt); - -const size_t mbedtls_test_cli_key_len = - sizeof(test_cli_key); -const size_t mbedtls_test_cli_pwd_len = - sizeof(test_cli_pwd) - 1; -const size_t mbedtls_test_cli_crt_len = - sizeof(test_cli_crt); - -/* - * - * Lists of certificates - * - */ - -/* List of CAs in PEM or DER, depending on config */ -const char *mbedtls_test_cas[] = { -#if defined(MBEDTLS_RSA_C) && defined(MBEDTLS_SHA1_C) - mbedtls_test_ca_crt_rsa_sha1, -#endif -#if defined(MBEDTLS_RSA_C) && defined(MBEDTLS_SHA256_C) - mbedtls_test_ca_crt_rsa_sha256, -#endif -#if defined(MBEDTLS_ECDSA_C) - mbedtls_test_ca_crt_ec, -#endif - NULL -}; -const size_t mbedtls_test_cas_len[] = { -#if defined(MBEDTLS_RSA_C) && defined(MBEDTLS_SHA1_C) - sizeof(mbedtls_test_ca_crt_rsa_sha1), -#endif -#if defined(MBEDTLS_RSA_C) && defined(MBEDTLS_SHA256_C) - sizeof(mbedtls_test_ca_crt_rsa_sha256), -#endif -#if defined(MBEDTLS_ECDSA_C) - sizeof(mbedtls_test_ca_crt_ec), -#endif - 0 -}; - -/* List of all available CA certificates in DER format */ -const unsigned char *mbedtls_test_cas_der[] = { -#if defined(MBEDTLS_RSA_C) -#if defined(MBEDTLS_SHA256_C) - mbedtls_test_ca_crt_rsa_sha256_der, -#endif /* MBEDTLS_SHA256_C */ -#if defined(MBEDTLS_SHA1_C) - mbedtls_test_ca_crt_rsa_sha1_der, -#endif /* MBEDTLS_SHA1_C */ -#endif /* MBEDTLS_RSA_C */ -#if defined(MBEDTLS_ECDSA_C) - mbedtls_test_ca_crt_ec_der, -#endif /* MBEDTLS_ECDSA_C */ - NULL -}; - -const size_t mbedtls_test_cas_der_len[] = { -#if defined(MBEDTLS_RSA_C) -#if defined(MBEDTLS_SHA256_C) - sizeof(mbedtls_test_ca_crt_rsa_sha256_der), -#endif /* MBEDTLS_SHA256_C */ -#if defined(MBEDTLS_SHA1_C) - sizeof(mbedtls_test_ca_crt_rsa_sha1_der), -#endif /* MBEDTLS_SHA1_C */ -#endif /* MBEDTLS_RSA_C */ -#if defined(MBEDTLS_ECDSA_C) - sizeof(mbedtls_test_ca_crt_ec_der), -#endif /* MBEDTLS_ECDSA_C */ - 0 -}; - -/* Concatenation of all available CA certificates in PEM format */ -#if defined(MBEDTLS_PEM_PARSE_C) -const char mbedtls_test_cas_pem[] = -#if defined(MBEDTLS_RSA_C) -#if defined(MBEDTLS_SHA256_C) - TEST_CA_CRT_RSA_SHA256_PEM -#endif /* MBEDTLS_SHA256_C */ -#if defined(MBEDTLS_SHA1_C) - TEST_CA_CRT_RSA_SHA1_PEM -#endif /* MBEDTLS_SHA1_C */ -#endif /* MBEDTLS_RSA_C */ -#if defined(MBEDTLS_ECDSA_C) - TEST_CA_CRT_EC_PEM -#endif /* MBEDTLS_ECDSA_C */ - ""; -const size_t mbedtls_test_cas_pem_len = sizeof(mbedtls_test_cas_pem); -#endif /* MBEDTLS_PEM_PARSE_C */ - -#endif /* MBEDTLS_CERTS_C */ diff --git a/vendor/mbedtls/library/chacha20.c b/vendor/mbedtls/library/chacha20.c index 53f1d3916c..acaae5b2e9 100644 --- a/vendor/mbedtls/library/chacha20.c +++ b/vendor/mbedtls/library/chacha20.c @@ -6,19 +6,7 @@ * \author Daniel King * * Copyright The Mbed TLS Contributors - * SPDX-License-Identifier: Apache-2.0 - * - * Licensed under the Apache License, Version 2.0 (the "License"); you may - * not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT - * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. + * SPDX-License-Identifier: Apache-2.0 OR GPL-2.0-or-later */ #include "common.h" @@ -36,12 +24,6 @@ #if !defined(MBEDTLS_CHACHA20_ALT) -/* Parameter validation macros */ -#define CHACHA20_VALIDATE_RET(cond) \ - MBEDTLS_INTERNAL_VALIDATE_RET(cond, MBEDTLS_ERR_CHACHA20_BAD_INPUT_DATA) -#define CHACHA20_VALIDATE(cond) \ - MBEDTLS_INTERNAL_VALIDATE(cond) - #define ROTL32(value, amount) \ ((uint32_t) ((value) << (amount)) | ((value) >> (32 - (amount)))) @@ -160,8 +142,6 @@ static void chacha20_block(const uint32_t initial_state[16], void mbedtls_chacha20_init(mbedtls_chacha20_context *ctx) { - CHACHA20_VALIDATE(ctx != NULL); - mbedtls_platform_zeroize(ctx->state, sizeof(ctx->state)); mbedtls_platform_zeroize(ctx->keystream8, sizeof(ctx->keystream8)); @@ -179,9 +159,6 @@ void mbedtls_chacha20_free(mbedtls_chacha20_context *ctx) int mbedtls_chacha20_setkey(mbedtls_chacha20_context *ctx, const unsigned char key[32]) { - CHACHA20_VALIDATE_RET(ctx != NULL); - CHACHA20_VALIDATE_RET(key != NULL); - /* ChaCha20 constants - the string "expand 32-byte k" */ ctx->state[0] = 0x61707865; ctx->state[1] = 0x3320646e; @@ -205,9 +182,6 @@ int mbedtls_chacha20_starts(mbedtls_chacha20_context *ctx, const unsigned char nonce[12], uint32_t counter) { - CHACHA20_VALIDATE_RET(ctx != NULL); - CHACHA20_VALIDATE_RET(nonce != NULL); - /* Counter */ ctx->state[12] = counter; @@ -230,11 +204,6 @@ int mbedtls_chacha20_update(mbedtls_chacha20_context *ctx, unsigned char *output) { size_t offset = 0U; - size_t i; - - CHACHA20_VALIDATE_RET(ctx != NULL); - CHACHA20_VALIDATE_RET(size == 0 || input != NULL); - CHACHA20_VALIDATE_RET(size == 0 || output != NULL); /* Use leftover keystream bytes, if available */ while (size > 0U && ctx->keystream_bytes_used < CHACHA20_BLOCK_SIZE_BYTES) { @@ -252,16 +221,7 @@ int mbedtls_chacha20_update(mbedtls_chacha20_context *ctx, chacha20_block(ctx->state, ctx->keystream8); ctx->state[CHACHA20_CTR_INDEX]++; - for (i = 0U; i < 64U; i += 8U) { - output[offset + i] = input[offset + i] ^ ctx->keystream8[i]; - output[offset + i+1] = input[offset + i+1] ^ ctx->keystream8[i+1]; - output[offset + i+2] = input[offset + i+2] ^ ctx->keystream8[i+2]; - output[offset + i+3] = input[offset + i+3] ^ ctx->keystream8[i+3]; - output[offset + i+4] = input[offset + i+4] ^ ctx->keystream8[i+4]; - output[offset + i+5] = input[offset + i+5] ^ ctx->keystream8[i+5]; - output[offset + i+6] = input[offset + i+6] ^ ctx->keystream8[i+6]; - output[offset + i+7] = input[offset + i+7] ^ ctx->keystream8[i+7]; - } + mbedtls_xor(output + offset, input + offset, ctx->keystream8, 64U); offset += CHACHA20_BLOCK_SIZE_BYTES; size -= CHACHA20_BLOCK_SIZE_BYTES; @@ -273,9 +233,7 @@ int mbedtls_chacha20_update(mbedtls_chacha20_context *ctx, chacha20_block(ctx->state, ctx->keystream8); ctx->state[CHACHA20_CTR_INDEX]++; - for (i = 0U; i < size; i++) { - output[offset + i] = input[offset + i] ^ ctx->keystream8[i]; - } + mbedtls_xor(output + offset, input + offset, ctx->keystream8, size); ctx->keystream_bytes_used = size; @@ -294,11 +252,6 @@ int mbedtls_chacha20_crypt(const unsigned char key[32], mbedtls_chacha20_context ctx; int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED; - CHACHA20_VALIDATE_RET(key != NULL); - CHACHA20_VALIDATE_RET(nonce != NULL); - CHACHA20_VALIDATE_RET(data_len == 0 || input != NULL); - CHACHA20_VALIDATE_RET(data_len == 0 || output != NULL); - mbedtls_chacha20_init(&ctx); ret = mbedtls_chacha20_setkey(&ctx, key); diff --git a/vendor/mbedtls/library/chachapoly.c b/vendor/mbedtls/library/chachapoly.c index 547ffb2ed2..a1314eab6d 100644 --- a/vendor/mbedtls/library/chachapoly.c +++ b/vendor/mbedtls/library/chachapoly.c @@ -4,19 +4,7 @@ * \brief ChaCha20-Poly1305 AEAD construction based on RFC 7539. * * Copyright The Mbed TLS Contributors - * SPDX-License-Identifier: Apache-2.0 - * - * Licensed under the Apache License, Version 2.0 (the "License"); you may - * not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT - * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. + * SPDX-License-Identifier: Apache-2.0 OR GPL-2.0-or-later */ #include "common.h" @@ -33,12 +21,6 @@ #if !defined(MBEDTLS_CHACHAPOLY_ALT) -/* Parameter validation macros */ -#define CHACHAPOLY_VALIDATE_RET(cond) \ - MBEDTLS_INTERNAL_VALIDATE_RET(cond, MBEDTLS_ERR_POLY1305_BAD_INPUT_DATA) -#define CHACHAPOLY_VALIDATE(cond) \ - MBEDTLS_INTERNAL_VALIDATE(cond) - #define CHACHAPOLY_STATE_INIT (0) #define CHACHAPOLY_STATE_AAD (1) #define CHACHAPOLY_STATE_CIPHERTEXT (2) /* Encrypting or decrypting */ @@ -87,8 +69,6 @@ static int chachapoly_pad_ciphertext(mbedtls_chachapoly_context *ctx) void mbedtls_chachapoly_init(mbedtls_chachapoly_context *ctx) { - CHACHAPOLY_VALIDATE(ctx != NULL); - mbedtls_chacha20_init(&ctx->chacha20_ctx); mbedtls_poly1305_init(&ctx->poly1305_ctx); ctx->aad_len = 0U; @@ -115,8 +95,6 @@ int mbedtls_chachapoly_setkey(mbedtls_chachapoly_context *ctx, const unsigned char key[32]) { int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED; - CHACHAPOLY_VALIDATE_RET(ctx != NULL); - CHACHAPOLY_VALIDATE_RET(key != NULL); ret = mbedtls_chacha20_setkey(&ctx->chacha20_ctx, key); @@ -129,8 +107,6 @@ int mbedtls_chachapoly_starts(mbedtls_chachapoly_context *ctx, { int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED; unsigned char poly1305_key[64]; - CHACHAPOLY_VALIDATE_RET(ctx != NULL); - CHACHAPOLY_VALIDATE_RET(nonce != NULL); /* Set counter = 0, will be update to 1 when generating Poly1305 key */ ret = mbedtls_chacha20_starts(&ctx->chacha20_ctx, nonce, 0U); @@ -168,9 +144,6 @@ int mbedtls_chachapoly_update_aad(mbedtls_chachapoly_context *ctx, const unsigned char *aad, size_t aad_len) { - CHACHAPOLY_VALIDATE_RET(ctx != NULL); - CHACHAPOLY_VALIDATE_RET(aad_len == 0 || aad != NULL); - if (ctx->state != CHACHAPOLY_STATE_AAD) { return MBEDTLS_ERR_CHACHAPOLY_BAD_STATE; } @@ -186,9 +159,6 @@ int mbedtls_chachapoly_update(mbedtls_chachapoly_context *ctx, unsigned char *output) { int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED; - CHACHAPOLY_VALIDATE_RET(ctx != NULL); - CHACHAPOLY_VALIDATE_RET(len == 0 || input != NULL); - CHACHAPOLY_VALIDATE_RET(len == 0 || output != NULL); if ((ctx->state != CHACHAPOLY_STATE_AAD) && (ctx->state != CHACHAPOLY_STATE_CIPHERTEXT)) { @@ -236,8 +206,6 @@ int mbedtls_chachapoly_finish(mbedtls_chachapoly_context *ctx, { int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED; unsigned char len_block[16]; - CHACHAPOLY_VALIDATE_RET(ctx != NULL); - CHACHAPOLY_VALIDATE_RET(mac != NULL); if (ctx->state == CHACHAPOLY_STATE_INIT) { return MBEDTLS_ERR_CHACHAPOLY_BAD_STATE; @@ -315,13 +283,6 @@ int mbedtls_chachapoly_encrypt_and_tag(mbedtls_chachapoly_context *ctx, unsigned char *output, unsigned char tag[16]) { - CHACHAPOLY_VALIDATE_RET(ctx != NULL); - CHACHAPOLY_VALIDATE_RET(nonce != NULL); - CHACHAPOLY_VALIDATE_RET(tag != NULL); - CHACHAPOLY_VALIDATE_RET(aad_len == 0 || aad != NULL); - CHACHAPOLY_VALIDATE_RET(length == 0 || input != NULL); - CHACHAPOLY_VALIDATE_RET(length == 0 || output != NULL); - return chachapoly_crypt_and_tag(ctx, MBEDTLS_CHACHAPOLY_ENCRYPT, length, nonce, aad, aad_len, input, output, tag); @@ -339,12 +300,6 @@ int mbedtls_chachapoly_auth_decrypt(mbedtls_chachapoly_context *ctx, int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED; unsigned char check_tag[16]; int diff; - CHACHAPOLY_VALIDATE_RET(ctx != NULL); - CHACHAPOLY_VALIDATE_RET(nonce != NULL); - CHACHAPOLY_VALIDATE_RET(tag != NULL); - CHACHAPOLY_VALIDATE_RET(aad_len == 0 || aad != NULL); - CHACHAPOLY_VALIDATE_RET(length == 0 || input != NULL); - CHACHAPOLY_VALIDATE_RET(length == 0 || output != NULL); if ((ret = chachapoly_crypt_and_tag(ctx, MBEDTLS_CHACHAPOLY_DECRYPT, length, nonce, diff --git a/vendor/mbedtls/library/check_crypto_config.h b/vendor/mbedtls/library/check_crypto_config.h index b72de80d0a..6469e9f439 100644 --- a/vendor/mbedtls/library/check_crypto_config.h +++ b/vendor/mbedtls/library/check_crypto_config.h @@ -5,19 +5,7 @@ */ /* * Copyright The Mbed TLS Contributors - * SPDX-License-Identifier: Apache-2.0 - * - * Licensed under the Apache License, Version 2.0 (the "License"); you may - * not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT - * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. + * SPDX-License-Identifier: Apache-2.0 OR GPL-2.0-or-later */ /* @@ -42,13 +30,13 @@ #endif #if defined(PSA_WANT_ALG_DETERMINISTIC_ECDSA) && \ - !(defined(PSA_WANT_KEY_TYPE_ECC_KEY_PAIR) || \ + !(defined(PSA_WANT_KEY_TYPE_ECC_KEY_PAIR_BASIC) || \ defined(PSA_WANT_KEY_TYPE_ECC_PUBLIC_KEY)) #error "PSA_WANT_ALG_DETERMINISTIC_ECDSA defined, but not all prerequisites" #endif #if defined(PSA_WANT_ALG_ECDSA) && \ - !(defined(PSA_WANT_KEY_TYPE_ECC_KEY_PAIR) || \ + !(defined(PSA_WANT_KEY_TYPE_ECC_KEY_PAIR_BASIC) || \ defined(PSA_WANT_KEY_TYPE_ECC_PUBLIC_KEY)) #error "PSA_WANT_ALG_ECDSA defined, but not all prerequisites" #endif @@ -60,32 +48,94 @@ #endif #if defined(PSA_WANT_ALG_RSA_PKCS1V15_CRYPT) && \ - !(defined(PSA_WANT_KEY_TYPE_RSA_KEY_PAIR) || \ + !(defined(PSA_WANT_KEY_TYPE_RSA_KEY_PAIR_BASIC) || \ defined(PSA_WANT_KEY_TYPE_RSA_PUBLIC_KEY)) #error "PSA_WANT_ALG_RSA_PKCS1V15_CRYPT defined, but not all prerequisites" #endif #if defined(PSA_WANT_ALG_RSA_PKCS1V15_SIGN) && \ - !(defined(PSA_WANT_KEY_TYPE_RSA_KEY_PAIR) || \ + !(defined(PSA_WANT_KEY_TYPE_RSA_KEY_PAIR_BASIC) || \ defined(PSA_WANT_KEY_TYPE_RSA_PUBLIC_KEY)) #error "PSA_WANT_ALG_RSA_PKCS1V15_SIGN defined, but not all prerequisites" #endif #if defined(PSA_WANT_ALG_RSA_OAEP) && \ - !(defined(PSA_WANT_KEY_TYPE_RSA_KEY_PAIR) || \ + !(defined(PSA_WANT_KEY_TYPE_RSA_KEY_PAIR_BASIC) || \ defined(PSA_WANT_KEY_TYPE_RSA_PUBLIC_KEY)) #error "PSA_WANT_ALG_RSA_OAEP defined, but not all prerequisites" #endif #if defined(PSA_WANT_ALG_RSA_PSS) && \ - !(defined(PSA_WANT_KEY_TYPE_RSA_KEY_PAIR) || \ + !(defined(PSA_WANT_KEY_TYPE_RSA_KEY_PAIR_BASIC) || \ defined(PSA_WANT_KEY_TYPE_RSA_PUBLIC_KEY)) #error "PSA_WANT_ALG_RSA_PSS defined, but not all prerequisites" #endif -#if defined(PSA_WANT_KEY_TYPE_ECC_KEY_PAIR) && \ +#if (defined(PSA_WANT_KEY_TYPE_ECC_KEY_PAIR_BASIC) || \ + defined(PSA_WANT_KEY_TYPE_ECC_KEY_PAIR_IMPORT) || \ + defined(PSA_WANT_KEY_TYPE_ECC_KEY_PAIR_EXPORT) || \ + defined(PSA_WANT_KEY_TYPE_ECC_KEY_PAIR_GENERATE) || \ + defined(PSA_WANT_KEY_TYPE_ECC_KEY_PAIR_DERIVE)) && \ !defined(PSA_WANT_KEY_TYPE_ECC_PUBLIC_KEY) -#error "PSA_WANT_KEY_TYPE_ECC_KEY_PAIR defined, but not all prerequisites" +#error "PSA_WANT_KEY_TYPE_ECC_KEY_PAIR_xxx defined, but not all prerequisites" +#endif + +#if (defined(PSA_WANT_KEY_TYPE_RSA_KEY_PAIR_BASIC) || \ + defined(PSA_WANT_KEY_TYPE_RSA_KEY_PAIR_IMPORT) || \ + defined(PSA_WANT_KEY_TYPE_RSA_KEY_PAIR_EXPORT) || \ + defined(PSA_WANT_KEY_TYPE_RSA_KEY_PAIR_GENERATE)) && \ + !defined(PSA_WANT_KEY_TYPE_RSA_PUBLIC_KEY) +#error "PSA_WANT_KEY_TYPE_RSA_KEY_PAIR_xxx defined, but not all prerequisites" +#endif + +#if (defined(PSA_WANT_KEY_TYPE_DH_KEY_PAIR_BASIC) || \ + defined(PSA_WANT_KEY_TYPE_DH_KEY_PAIR_IMPORT) || \ + defined(PSA_WANT_KEY_TYPE_DH_KEY_PAIR_EXPORT) || \ + defined(PSA_WANT_KEY_TYPE_DH_KEY_PAIR_GENERATE)) && \ + !defined(PSA_WANT_KEY_TYPE_DH_PUBLIC_KEY) +#error "PSA_WANT_KEY_TYPE_DH_KEY_PAIR_xxx defined, but not all prerequisites" +#endif + +#if defined(PSA_WANT_KEY_TYPE_ECC_KEY_PAIR) +#if defined(MBEDTLS_DEPRECATED_REMOVED) +#error "PSA_WANT_KEY_TYPE_ECC_KEY_PAIR is deprecated and will be removed in a \ + future version of Mbed TLS. Please switch to new PSA_WANT_KEY_TYPE_ECC_KEY_PAIR_xxx \ + symbols, where xxx can be: USE, IMPORT, EXPORT, GENERATE, DERIVE" +#elif defined(MBEDTLS_DEPRECATED_WARNING) +#warning "PSA_WANT_KEY_TYPE_ECC_KEY_PAIR is deprecated and will be removed in a \ + future version of Mbed TLS. Please switch to new PSA_WANT_KEY_TYPE_ECC_KEY_PAIR_xxx \ + symbols, where xxx can be: USE, IMPORT, EXPORT, GENERATE, DERIVE" +#endif /* MBEDTLS_DEPRECATED_WARNING */ +#endif /* PSA_WANT_KEY_TYPE_ECC_KEY_PAIR */ + +#if defined(PSA_WANT_KEY_TYPE_RSA_KEY_PAIR) +#if defined(MBEDTLS_DEPRECATED_REMOVED) +#error "PSA_WANT_KEY_TYPE_RSA_KEY_PAIR is deprecated and will be removed in a \ + future version of Mbed TLS. Please switch to new PSA_WANT_KEY_TYPE_RSA_KEY_PAIR_xxx \ + symbols, where xxx can be: USE, IMPORT, EXPORT, GENERATE, DERIVE" +#elif defined(MBEDTLS_DEPRECATED_WARNING) +#warning "PSA_WANT_KEY_TYPE_RSA_KEY_PAIR is deprecated and will be removed in a \ + future version of Mbed TLS. Please switch to new PSA_WANT_KEY_TYPE_RSA_KEY_PAIR_xxx \ + symbols, where xxx can be: USE, IMPORT, EXPORT, GENERATE, DERIVE" +#endif /* MBEDTLS_DEPRECATED_WARNING */ +#endif /* PSA_WANT_KEY_TYPE_RSA_KEY_PAIR */ + +#if defined(PSA_WANT_KEY_TYPE_RSA_KEY_PAIR_DERIVE) +#error "PSA_WANT_KEY_TYPE_RSA_KEY_PAIR_DERIVE defined, but feature is not supported" +#endif + +#if defined(PSA_WANT_KEY_TYPE_DH_KEY_PAIR_DERIVE) +#error "PSA_WANT_KEY_TYPE_DH_KEY_PAIR_DERIVE defined, but feature is not supported" +#endif + +#if defined(MBEDTLS_SSL_PROTO_TLS1_2) && defined(MBEDTLS_USE_PSA_CRYPTO) && \ + !(defined(PSA_WANT_ALG_SHA_1) || defined(PSA_WANT_ALG_SHA_256) || defined(PSA_WANT_ALG_SHA_512)) +#error "MBEDTLS_SSL_PROTO_TLS1_2 defined, but not all prerequisites" +#endif + +#if defined(PSA_WANT_ALG_TLS12_ECJPAKE_TO_PMS) && \ + !defined(PSA_WANT_ALG_SHA_256) +#error "PSA_WANT_ALG_TLS12_ECJPAKE_TO_PMS defined, but not all prerequisites" #endif #endif /* MBEDTLS_CHECK_CRYPTO_CONFIG_H */ diff --git a/vendor/mbedtls/library/cipher.c b/vendor/mbedtls/library/cipher.c index 09ca686d82..0683677eda 100644 --- a/vendor/mbedtls/library/cipher.c +++ b/vendor/mbedtls/library/cipher.c @@ -6,19 +6,7 @@ * \author Adriaan de Jong * * Copyright The Mbed TLS Contributors - * SPDX-License-Identifier: Apache-2.0 - * - * Licensed under the Apache License, Version 2.0 (the "License"); you may - * not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT - * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. + * SPDX-License-Identifier: Apache-2.0 OR GPL-2.0-or-later */ #include "common.h" @@ -26,7 +14,7 @@ #if defined(MBEDTLS_CIPHER_C) #include "mbedtls/cipher.h" -#include "mbedtls/cipher_internal.h" +#include "cipher_wrap.h" #include "mbedtls/platform_util.h" #include "mbedtls/error.h" #include "mbedtls/constant_time.h" @@ -55,10 +43,9 @@ #include "mbedtls/cmac.h" #endif -#if defined(MBEDTLS_USE_PSA_CRYPTO) +#if defined(MBEDTLS_USE_PSA_CRYPTO) && !defined(MBEDTLS_DEPRECATED_REMOVED) #include "psa/crypto.h" -#include "mbedtls/psa_util.h" -#endif /* MBEDTLS_USE_PSA_CRYPTO */ +#endif /* MBEDTLS_USE_PSA_CRYPTO && !MBEDTLS_DEPRECATED_REMOVED */ #if defined(MBEDTLS_NIST_KW_C) #include "mbedtls/nist_kw.h" @@ -66,13 +53,14 @@ #include "mbedtls/platform.h" -#define CIPHER_VALIDATE_RET(cond) \ - MBEDTLS_INTERNAL_VALIDATE_RET(cond, MBEDTLS_ERR_CIPHER_BAD_INPUT_DATA) -#define CIPHER_VALIDATE(cond) \ - MBEDTLS_INTERNAL_VALIDATE(cond) - static int supported_init = 0; +static inline const mbedtls_cipher_base_t *mbedtls_cipher_get_base( + const mbedtls_cipher_info_t *info) +{ + return mbedtls_cipher_base_lookup_table[info->base_idx]; +} + const int *mbedtls_cipher_list(void) { const mbedtls_cipher_definition_t *def; @@ -134,8 +122,8 @@ const mbedtls_cipher_info_t *mbedtls_cipher_info_from_values( const mbedtls_cipher_definition_t *def; for (def = mbedtls_cipher_definitions; def->info != NULL; def++) { - if (def->info->base->cipher == cipher_id && - def->info->key_bitlen == (unsigned) key_bitlen && + if (mbedtls_cipher_get_base(def->info)->cipher == cipher_id && + mbedtls_cipher_info_get_key_bitlen(def->info) == (unsigned) key_bitlen && def->info->mode == mode) { return def->info; } @@ -144,9 +132,74 @@ const mbedtls_cipher_info_t *mbedtls_cipher_info_from_values( return NULL; } +#if defined(MBEDTLS_USE_PSA_CRYPTO) && !defined(MBEDTLS_DEPRECATED_REMOVED) +static inline psa_key_type_t mbedtls_psa_translate_cipher_type( + mbedtls_cipher_type_t cipher) +{ + switch (cipher) { + case MBEDTLS_CIPHER_AES_128_CCM: + case MBEDTLS_CIPHER_AES_192_CCM: + case MBEDTLS_CIPHER_AES_256_CCM: + case MBEDTLS_CIPHER_AES_128_CCM_STAR_NO_TAG: + case MBEDTLS_CIPHER_AES_192_CCM_STAR_NO_TAG: + case MBEDTLS_CIPHER_AES_256_CCM_STAR_NO_TAG: + case MBEDTLS_CIPHER_AES_128_GCM: + case MBEDTLS_CIPHER_AES_192_GCM: + case MBEDTLS_CIPHER_AES_256_GCM: + case MBEDTLS_CIPHER_AES_128_CBC: + case MBEDTLS_CIPHER_AES_192_CBC: + case MBEDTLS_CIPHER_AES_256_CBC: + case MBEDTLS_CIPHER_AES_128_ECB: + case MBEDTLS_CIPHER_AES_192_ECB: + case MBEDTLS_CIPHER_AES_256_ECB: + return PSA_KEY_TYPE_AES; + + /* ARIA not yet supported in PSA. */ + /* case MBEDTLS_CIPHER_ARIA_128_CCM: + case MBEDTLS_CIPHER_ARIA_192_CCM: + case MBEDTLS_CIPHER_ARIA_256_CCM: + case MBEDTLS_CIPHER_ARIA_128_CCM_STAR_NO_TAG: + case MBEDTLS_CIPHER_ARIA_192_CCM_STAR_NO_TAG: + case MBEDTLS_CIPHER_ARIA_256_CCM_STAR_NO_TAG: + case MBEDTLS_CIPHER_ARIA_128_GCM: + case MBEDTLS_CIPHER_ARIA_192_GCM: + case MBEDTLS_CIPHER_ARIA_256_GCM: + case MBEDTLS_CIPHER_ARIA_128_CBC: + case MBEDTLS_CIPHER_ARIA_192_CBC: + case MBEDTLS_CIPHER_ARIA_256_CBC: + return( PSA_KEY_TYPE_ARIA ); */ + + default: + return 0; + } +} + +static inline psa_algorithm_t mbedtls_psa_translate_cipher_mode( + mbedtls_cipher_mode_t mode, size_t taglen) +{ + switch (mode) { + case MBEDTLS_MODE_ECB: + return PSA_ALG_ECB_NO_PADDING; + case MBEDTLS_MODE_GCM: + return PSA_ALG_AEAD_WITH_SHORTENED_TAG(PSA_ALG_GCM, taglen); + case MBEDTLS_MODE_CCM: + return PSA_ALG_AEAD_WITH_SHORTENED_TAG(PSA_ALG_CCM, taglen); + case MBEDTLS_MODE_CCM_STAR_NO_TAG: + return PSA_ALG_CCM_STAR_NO_TAG; + case MBEDTLS_MODE_CBC: + if (taglen == 0) { + return PSA_ALG_CBC_NO_PADDING; + } else { + return 0; + } + default: + return 0; + } +} +#endif /* MBEDTLS_USE_PSA_CRYPTO && !MBEDTLS_DEPRECATED_REMOVED */ + void mbedtls_cipher_init(mbedtls_cipher_context_t *ctx) { - CIPHER_VALIDATE(ctx != NULL); memset(ctx, 0, sizeof(mbedtls_cipher_context_t)); } @@ -156,7 +209,7 @@ void mbedtls_cipher_free(mbedtls_cipher_context_t *ctx) return; } -#if defined(MBEDTLS_USE_PSA_CRYPTO) +#if defined(MBEDTLS_USE_PSA_CRYPTO) && !defined(MBEDTLS_DEPRECATED_REMOVED) if (ctx->psa_enabled == 1) { if (ctx->cipher_ctx != NULL) { mbedtls_cipher_context_psa * const cipher_psa = @@ -167,25 +220,23 @@ void mbedtls_cipher_free(mbedtls_cipher_context_t *ctx) (void) psa_destroy_key(cipher_psa->slot); } - mbedtls_platform_zeroize(cipher_psa, sizeof(*cipher_psa)); - mbedtls_free(cipher_psa); + mbedtls_zeroize_and_free(cipher_psa, sizeof(*cipher_psa)); } mbedtls_platform_zeroize(ctx, sizeof(mbedtls_cipher_context_t)); return; } -#endif /* MBEDTLS_USE_PSA_CRYPTO */ +#endif /* MBEDTLS_USE_PSA_CRYPTO && !MBEDTLS_DEPRECATED_REMOVED */ #if defined(MBEDTLS_CMAC_C) if (ctx->cmac_ctx) { - mbedtls_platform_zeroize(ctx->cmac_ctx, + mbedtls_zeroize_and_free(ctx->cmac_ctx, sizeof(mbedtls_cmac_context_t)); - mbedtls_free(ctx->cmac_ctx); } #endif if (ctx->cipher_ctx) { - ctx->cipher_info->base->ctx_free_func(ctx->cipher_ctx); + mbedtls_cipher_get_base(ctx->cipher_info)->ctx_free_func(ctx->cipher_ctx); } mbedtls_platform_zeroize(ctx, sizeof(mbedtls_cipher_context_t)); @@ -194,34 +245,25 @@ void mbedtls_cipher_free(mbedtls_cipher_context_t *ctx) int mbedtls_cipher_setup(mbedtls_cipher_context_t *ctx, const mbedtls_cipher_info_t *cipher_info) { - CIPHER_VALIDATE_RET(ctx != NULL); if (cipher_info == NULL) { return MBEDTLS_ERR_CIPHER_BAD_INPUT_DATA; } memset(ctx, 0, sizeof(mbedtls_cipher_context_t)); - if (NULL == (ctx->cipher_ctx = cipher_info->base->ctx_alloc_func())) { - return MBEDTLS_ERR_CIPHER_ALLOC_FAILED; + if (mbedtls_cipher_get_base(cipher_info)->ctx_alloc_func != NULL) { + ctx->cipher_ctx = mbedtls_cipher_get_base(cipher_info)->ctx_alloc_func(); + if (ctx->cipher_ctx == NULL) { + return MBEDTLS_ERR_CIPHER_ALLOC_FAILED; + } } ctx->cipher_info = cipher_info; -#if defined(MBEDTLS_CIPHER_MODE_WITH_PADDING) - /* - * Ignore possible errors caused by a cipher mode that doesn't use padding - */ -#if defined(MBEDTLS_CIPHER_PADDING_PKCS7) - (void) mbedtls_cipher_set_padding_mode(ctx, MBEDTLS_PADDING_PKCS7); -#else - (void) mbedtls_cipher_set_padding_mode(ctx, MBEDTLS_PADDING_NONE); -#endif -#endif /* MBEDTLS_CIPHER_MODE_WITH_PADDING */ - return 0; } -#if defined(MBEDTLS_USE_PSA_CRYPTO) +#if defined(MBEDTLS_USE_PSA_CRYPTO) && !defined(MBEDTLS_DEPRECATED_REMOVED) int mbedtls_cipher_setup_psa(mbedtls_cipher_context_t *ctx, const mbedtls_cipher_info_t *cipher_info, size_t taglen) @@ -235,11 +277,11 @@ int mbedtls_cipher_setup_psa(mbedtls_cipher_context_t *ctx, /* Check that the underlying cipher mode and cipher type are * supported by the underlying PSA Crypto implementation. */ - alg = mbedtls_psa_translate_cipher_mode(cipher_info->mode, taglen); + alg = mbedtls_psa_translate_cipher_mode(((mbedtls_cipher_mode_t) cipher_info->mode), taglen); if (alg == 0) { return MBEDTLS_ERR_CIPHER_FEATURE_UNAVAILABLE; } - if (mbedtls_psa_translate_cipher_type(cipher_info->type) == 0) { + if (mbedtls_psa_translate_cipher_type(((mbedtls_cipher_type_t) cipher_info->type)) == 0) { return MBEDTLS_ERR_CIPHER_FEATURE_UNAVAILABLE; } @@ -255,22 +297,27 @@ int mbedtls_cipher_setup_psa(mbedtls_cipher_context_t *ctx, ctx->psa_enabled = 1; return 0; } -#endif /* MBEDTLS_USE_PSA_CRYPTO */ +#endif /* MBEDTLS_USE_PSA_CRYPTO && !MBEDTLS_DEPRECATED_REMOVED */ int mbedtls_cipher_setkey(mbedtls_cipher_context_t *ctx, const unsigned char *key, int key_bitlen, const mbedtls_operation_t operation) { - CIPHER_VALIDATE_RET(ctx != NULL); - CIPHER_VALIDATE_RET(key != NULL); - CIPHER_VALIDATE_RET(operation == MBEDTLS_ENCRYPT || - operation == MBEDTLS_DECRYPT); + if (operation != MBEDTLS_ENCRYPT && operation != MBEDTLS_DECRYPT) { + return MBEDTLS_ERR_CIPHER_BAD_INPUT_DATA; + } if (ctx->cipher_info == NULL) { return MBEDTLS_ERR_CIPHER_BAD_INPUT_DATA; } +#if defined(MBEDTLS_BLOCK_CIPHER_NO_DECRYPT) + if (MBEDTLS_MODE_ECB == ((mbedtls_cipher_mode_t) ctx->cipher_info->mode) && + MBEDTLS_DECRYPT == operation) { + return MBEDTLS_ERR_CIPHER_FEATURE_UNAVAILABLE; + } +#endif -#if defined(MBEDTLS_USE_PSA_CRYPTO) +#if defined(MBEDTLS_USE_PSA_CRYPTO) && !defined(MBEDTLS_DEPRECATED_REMOVED) if (ctx->psa_enabled == 1) { mbedtls_cipher_context_psa * const cipher_psa = (mbedtls_cipher_context_psa *) ctx->cipher_ctx; @@ -292,7 +339,7 @@ int mbedtls_cipher_setkey(mbedtls_cipher_context_t *ctx, } key_type = mbedtls_psa_translate_cipher_type( - ctx->cipher_info->type); + ((mbedtls_cipher_type_t) ctx->cipher_info->type)); if (key_type == 0) { return MBEDTLS_ERR_CIPHER_FEATURE_UNAVAILABLE; } @@ -303,7 +350,6 @@ int mbedtls_cipher_setkey(mbedtls_cipher_context_t *ctx, * and use it for AEAD decryption. Until tests relying on this * are changed, allow any usage in PSA. */ psa_set_key_usage_flags(&attributes, - /* mbedtls_psa_translate_cipher_operation( operation ); */ PSA_KEY_USAGE_ENCRYPT | PSA_KEY_USAGE_DECRYPT); psa_set_key_algorithm(&attributes, cipher_psa->alg); @@ -317,7 +363,7 @@ int mbedtls_cipher_setkey(mbedtls_cipher_context_t *ctx, case PSA_ERROR_NOT_SUPPORTED: return MBEDTLS_ERR_CIPHER_FEATURE_UNAVAILABLE; default: - return MBEDTLS_ERR_CIPHER_HW_ACCEL_FAILED; + return MBEDTLS_ERR_PLATFORM_HW_ACCEL_FAILED; } /* Indicate that we own the key slot and need to * destroy it in mbedtls_cipher_free(). */ @@ -327,31 +373,38 @@ int mbedtls_cipher_setkey(mbedtls_cipher_context_t *ctx, ctx->operation = operation; return 0; } -#endif /* MBEDTLS_USE_PSA_CRYPTO */ +#endif /* MBEDTLS_USE_PSA_CRYPTO && !MBEDTLS_DEPRECATED_REMOVED */ if ((ctx->cipher_info->flags & MBEDTLS_CIPHER_VARIABLE_KEY_LEN) == 0 && - (int) ctx->cipher_info->key_bitlen != key_bitlen) { + (int) mbedtls_cipher_info_get_key_bitlen(ctx->cipher_info) != key_bitlen) { return MBEDTLS_ERR_CIPHER_BAD_INPUT_DATA; } ctx->key_bitlen = key_bitlen; ctx->operation = operation; +#if !defined(MBEDTLS_BLOCK_CIPHER_NO_DECRYPT) /* * For OFB, CFB and CTR mode always use the encryption key schedule */ if (MBEDTLS_ENCRYPT == operation || - MBEDTLS_MODE_CFB == ctx->cipher_info->mode || - MBEDTLS_MODE_OFB == ctx->cipher_info->mode || - MBEDTLS_MODE_CTR == ctx->cipher_info->mode) { - return ctx->cipher_info->base->setkey_enc_func(ctx->cipher_ctx, key, - ctx->key_bitlen); + MBEDTLS_MODE_CFB == ((mbedtls_cipher_mode_t) ctx->cipher_info->mode) || + MBEDTLS_MODE_OFB == ((mbedtls_cipher_mode_t) ctx->cipher_info->mode) || + MBEDTLS_MODE_CTR == ((mbedtls_cipher_mode_t) ctx->cipher_info->mode)) { + return mbedtls_cipher_get_base(ctx->cipher_info)->setkey_enc_func(ctx->cipher_ctx, key, + ctx->key_bitlen); } if (MBEDTLS_DECRYPT == operation) { - return ctx->cipher_info->base->setkey_dec_func(ctx->cipher_ctx, key, - ctx->key_bitlen); + return mbedtls_cipher_get_base(ctx->cipher_info)->setkey_dec_func(ctx->cipher_ctx, key, + ctx->key_bitlen); } +#else + if (operation == MBEDTLS_ENCRYPT || operation == MBEDTLS_DECRYPT) { + return mbedtls_cipher_get_base(ctx->cipher_info)->setkey_enc_func(ctx->cipher_ctx, key, + ctx->key_bitlen); + } +#endif return MBEDTLS_ERR_CIPHER_BAD_INPUT_DATA; } @@ -362,19 +415,17 @@ int mbedtls_cipher_set_iv(mbedtls_cipher_context_t *ctx, { size_t actual_iv_size; - CIPHER_VALIDATE_RET(ctx != NULL); - CIPHER_VALIDATE_RET(iv_len == 0 || iv != NULL); if (ctx->cipher_info == NULL) { return MBEDTLS_ERR_CIPHER_BAD_INPUT_DATA; } -#if defined(MBEDTLS_USE_PSA_CRYPTO) +#if defined(MBEDTLS_USE_PSA_CRYPTO) && !defined(MBEDTLS_DEPRECATED_REMOVED) if (ctx->psa_enabled == 1) { /* While PSA Crypto has an API for multipart * operations, we currently don't make it * accessible through the cipher layer. */ return MBEDTLS_ERR_CIPHER_FEATURE_UNAVAILABLE; } -#endif /* MBEDTLS_USE_PSA_CRYPTO */ +#endif /* MBEDTLS_USE_PSA_CRYPTO && !MBEDTLS_DEPRECATED_REMOVED */ /* avoid buffer overflow in ctx->iv */ if (iv_len > MBEDTLS_MAX_IV_LENGTH) { @@ -384,7 +435,7 @@ int mbedtls_cipher_set_iv(mbedtls_cipher_context_t *ctx, if ((ctx->cipher_info->flags & MBEDTLS_CIPHER_VARIABLE_IV_LEN) != 0) { actual_iv_size = iv_len; } else { - actual_iv_size = ctx->cipher_info->iv_size; + actual_iv_size = mbedtls_cipher_info_get_iv_size(ctx->cipher_info); /* avoid reading past the end of input buffer */ if (actual_iv_size > iv_len) { @@ -393,7 +444,7 @@ int mbedtls_cipher_set_iv(mbedtls_cipher_context_t *ctx, } #if defined(MBEDTLS_CHACHA20_C) - if (ctx->cipher_info->type == MBEDTLS_CIPHER_CHACHA20) { + if (((mbedtls_cipher_type_t) ctx->cipher_info->type) == MBEDTLS_CIPHER_CHACHA20) { /* Even though the actual_iv_size is overwritten with a correct value * of 12 from the cipher info, return an error to indicate that * the input iv_len is wrong. */ @@ -408,13 +459,47 @@ int mbedtls_cipher_set_iv(mbedtls_cipher_context_t *ctx, } } #if defined(MBEDTLS_CHACHAPOLY_C) - if (ctx->cipher_info->type == MBEDTLS_CIPHER_CHACHA20_POLY1305 && + if (((mbedtls_cipher_type_t) ctx->cipher_info->type) == MBEDTLS_CIPHER_CHACHA20_POLY1305 && iv_len != 12) { return MBEDTLS_ERR_CIPHER_BAD_INPUT_DATA; } #endif #endif +#if defined(MBEDTLS_GCM_C) + if (MBEDTLS_MODE_GCM == ((mbedtls_cipher_mode_t) ctx->cipher_info->mode)) { + return mbedtls_gcm_starts((mbedtls_gcm_context *) ctx->cipher_ctx, + ctx->operation, + iv, iv_len); + } +#endif + +#if defined(MBEDTLS_CCM_C) + if (MBEDTLS_MODE_CCM_STAR_NO_TAG == ((mbedtls_cipher_mode_t) ctx->cipher_info->mode)) { + int set_lengths_result; + int ccm_star_mode; + + set_lengths_result = mbedtls_ccm_set_lengths( + (mbedtls_ccm_context *) ctx->cipher_ctx, + 0, 0, 0); + if (set_lengths_result != 0) { + return set_lengths_result; + } + + if (ctx->operation == MBEDTLS_DECRYPT) { + ccm_star_mode = MBEDTLS_CCM_STAR_DECRYPT; + } else if (ctx->operation == MBEDTLS_ENCRYPT) { + ccm_star_mode = MBEDTLS_CCM_STAR_ENCRYPT; + } else { + return MBEDTLS_ERR_CIPHER_BAD_INPUT_DATA; + } + + return mbedtls_ccm_starts((mbedtls_ccm_context *) ctx->cipher_ctx, + ccm_star_mode, + iv, iv_len); + } +#endif + if (actual_iv_size != 0) { memcpy(ctx->iv, iv, actual_iv_size); ctx->iv_size = actual_iv_size; @@ -425,18 +510,17 @@ int mbedtls_cipher_set_iv(mbedtls_cipher_context_t *ctx, int mbedtls_cipher_reset(mbedtls_cipher_context_t *ctx) { - CIPHER_VALIDATE_RET(ctx != NULL); if (ctx->cipher_info == NULL) { return MBEDTLS_ERR_CIPHER_BAD_INPUT_DATA; } -#if defined(MBEDTLS_USE_PSA_CRYPTO) +#if defined(MBEDTLS_USE_PSA_CRYPTO) && !defined(MBEDTLS_DEPRECATED_REMOVED) if (ctx->psa_enabled == 1) { /* We don't support resetting PSA-based * cipher contexts, yet. */ return MBEDTLS_ERR_CIPHER_FEATURE_UNAVAILABLE; } -#endif /* MBEDTLS_USE_PSA_CRYPTO */ +#endif /* MBEDTLS_USE_PSA_CRYPTO && !MBEDTLS_DEPRECATED_REMOVED */ ctx->unprocessed_len = 0; @@ -447,30 +531,28 @@ int mbedtls_cipher_reset(mbedtls_cipher_context_t *ctx) int mbedtls_cipher_update_ad(mbedtls_cipher_context_t *ctx, const unsigned char *ad, size_t ad_len) { - CIPHER_VALIDATE_RET(ctx != NULL); - CIPHER_VALIDATE_RET(ad_len == 0 || ad != NULL); if (ctx->cipher_info == NULL) { return MBEDTLS_ERR_CIPHER_BAD_INPUT_DATA; } -#if defined(MBEDTLS_USE_PSA_CRYPTO) +#if defined(MBEDTLS_USE_PSA_CRYPTO) && !defined(MBEDTLS_DEPRECATED_REMOVED) if (ctx->psa_enabled == 1) { /* While PSA Crypto has an API for multipart * operations, we currently don't make it * accessible through the cipher layer. */ return MBEDTLS_ERR_CIPHER_FEATURE_UNAVAILABLE; } -#endif /* MBEDTLS_USE_PSA_CRYPTO */ +#endif /* MBEDTLS_USE_PSA_CRYPTO && !MBEDTLS_DEPRECATED_REMOVED */ #if defined(MBEDTLS_GCM_C) - if (MBEDTLS_MODE_GCM == ctx->cipher_info->mode) { - return mbedtls_gcm_starts((mbedtls_gcm_context *) ctx->cipher_ctx, ctx->operation, - ctx->iv, ctx->iv_size, ad, ad_len); + if (MBEDTLS_MODE_GCM == ((mbedtls_cipher_mode_t) ctx->cipher_info->mode)) { + return mbedtls_gcm_update_ad((mbedtls_gcm_context *) ctx->cipher_ctx, + ad, ad_len); } #endif #if defined(MBEDTLS_CHACHAPOLY_C) - if (MBEDTLS_CIPHER_CHACHA20_POLY1305 == ctx->cipher_info->type) { + if (MBEDTLS_CIPHER_CHACHA20_POLY1305 == ((mbedtls_cipher_type_t) ctx->cipher_info->type)) { int result; mbedtls_chachapoly_mode_t mode; @@ -490,7 +572,7 @@ int mbedtls_cipher_update_ad(mbedtls_cipher_context_t *ctx, } #endif - return 0; + return MBEDTLS_ERR_CIPHER_FEATURE_UNAVAILABLE; } #endif /* MBEDTLS_GCM_C || MBEDTLS_CHACHAPOLY_C */ @@ -500,22 +582,18 @@ int mbedtls_cipher_update(mbedtls_cipher_context_t *ctx, const unsigned char *in int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED; size_t block_size; - CIPHER_VALIDATE_RET(ctx != NULL); - CIPHER_VALIDATE_RET(ilen == 0 || input != NULL); - CIPHER_VALIDATE_RET(output != NULL); - CIPHER_VALIDATE_RET(olen != NULL); if (ctx->cipher_info == NULL) { return MBEDTLS_ERR_CIPHER_BAD_INPUT_DATA; } -#if defined(MBEDTLS_USE_PSA_CRYPTO) +#if defined(MBEDTLS_USE_PSA_CRYPTO) && !defined(MBEDTLS_DEPRECATED_REMOVED) if (ctx->psa_enabled == 1) { /* While PSA Crypto has an API for multipart * operations, we currently don't make it * accessible through the cipher layer. */ return MBEDTLS_ERR_CIPHER_FEATURE_UNAVAILABLE; } -#endif /* MBEDTLS_USE_PSA_CRYPTO */ +#endif /* MBEDTLS_USE_PSA_CRYPTO && !MBEDTLS_DEPRECATED_REMOVED */ *olen = 0; block_size = mbedtls_cipher_get_block_size(ctx); @@ -523,15 +601,16 @@ int mbedtls_cipher_update(mbedtls_cipher_context_t *ctx, const unsigned char *in return MBEDTLS_ERR_CIPHER_INVALID_CONTEXT; } - if (ctx->cipher_info->mode == MBEDTLS_MODE_ECB) { + if (((mbedtls_cipher_mode_t) ctx->cipher_info->mode) == MBEDTLS_MODE_ECB) { if (ilen != block_size) { return MBEDTLS_ERR_CIPHER_FULL_BLOCK_EXPECTED; } *olen = ilen; - if (0 != (ret = ctx->cipher_info->base->ecb_func(ctx->cipher_ctx, - ctx->operation, input, output))) { + if (0 != (ret = mbedtls_cipher_get_base(ctx->cipher_info)->ecb_func(ctx->cipher_ctx, + ctx->operation, input, + output))) { return ret; } @@ -539,15 +618,23 @@ int mbedtls_cipher_update(mbedtls_cipher_context_t *ctx, const unsigned char *in } #if defined(MBEDTLS_GCM_C) - if (ctx->cipher_info->mode == MBEDTLS_MODE_GCM) { - *olen = ilen; - return mbedtls_gcm_update((mbedtls_gcm_context *) ctx->cipher_ctx, ilen, input, - output); + if (((mbedtls_cipher_mode_t) ctx->cipher_info->mode) == MBEDTLS_MODE_GCM) { + return mbedtls_gcm_update((mbedtls_gcm_context *) ctx->cipher_ctx, + input, ilen, + output, ilen, olen); + } +#endif + +#if defined(MBEDTLS_CCM_C) + if (((mbedtls_cipher_mode_t) ctx->cipher_info->mode) == MBEDTLS_MODE_CCM_STAR_NO_TAG) { + return mbedtls_ccm_update((mbedtls_ccm_context *) ctx->cipher_ctx, + input, ilen, + output, ilen, olen); } #endif #if defined(MBEDTLS_CHACHAPOLY_C) - if (ctx->cipher_info->type == MBEDTLS_CIPHER_CHACHA20_POLY1305) { + if (((mbedtls_cipher_type_t) ctx->cipher_info->type) == MBEDTLS_CIPHER_CHACHA20_POLY1305) { *olen = ilen; return mbedtls_chachapoly_update((mbedtls_chachapoly_context *) ctx->cipher_ctx, ilen, input, output); @@ -560,7 +647,7 @@ int mbedtls_cipher_update(mbedtls_cipher_context_t *ctx, const unsigned char *in } #if defined(MBEDTLS_CIPHER_MODE_CBC) - if (ctx->cipher_info->mode == MBEDTLS_MODE_CBC) { + if (((mbedtls_cipher_mode_t) ctx->cipher_info->mode) == MBEDTLS_MODE_CBC) { size_t copy_len = 0; /* @@ -588,9 +675,12 @@ int mbedtls_cipher_update(mbedtls_cipher_context_t *ctx, const unsigned char *in memcpy(&(ctx->unprocessed_data[ctx->unprocessed_len]), input, copy_len); - if (0 != (ret = ctx->cipher_info->base->cbc_func(ctx->cipher_ctx, - ctx->operation, block_size, ctx->iv, - ctx->unprocessed_data, output))) { + if (0 != (ret = mbedtls_cipher_get_base(ctx->cipher_info)->cbc_func(ctx->cipher_ctx, + ctx->operation, + block_size, ctx->iv, + ctx-> + unprocessed_data, + output))) { return ret; } @@ -628,9 +718,11 @@ int mbedtls_cipher_update(mbedtls_cipher_context_t *ctx, const unsigned char *in * Process remaining full blocks */ if (ilen) { - if (0 != (ret = ctx->cipher_info->base->cbc_func(ctx->cipher_ctx, - ctx->operation, ilen, ctx->iv, input, - output))) { + if (0 != (ret = mbedtls_cipher_get_base(ctx->cipher_info)->cbc_func(ctx->cipher_ctx, + ctx->operation, + ilen, ctx->iv, + input, + output))) { return ret; } @@ -642,11 +734,12 @@ int mbedtls_cipher_update(mbedtls_cipher_context_t *ctx, const unsigned char *in #endif /* MBEDTLS_CIPHER_MODE_CBC */ #if defined(MBEDTLS_CIPHER_MODE_CFB) - if (ctx->cipher_info->mode == MBEDTLS_MODE_CFB) { - if (0 != (ret = ctx->cipher_info->base->cfb_func(ctx->cipher_ctx, - ctx->operation, ilen, - &ctx->unprocessed_len, ctx->iv, - input, output))) { + if (((mbedtls_cipher_mode_t) ctx->cipher_info->mode) == MBEDTLS_MODE_CFB) { + if (0 != (ret = mbedtls_cipher_get_base(ctx->cipher_info)->cfb_func(ctx->cipher_ctx, + ctx->operation, ilen, + &ctx->unprocessed_len, + ctx->iv, + input, output))) { return ret; } @@ -657,10 +750,12 @@ int mbedtls_cipher_update(mbedtls_cipher_context_t *ctx, const unsigned char *in #endif /* MBEDTLS_CIPHER_MODE_CFB */ #if defined(MBEDTLS_CIPHER_MODE_OFB) - if (ctx->cipher_info->mode == MBEDTLS_MODE_OFB) { - if (0 != (ret = ctx->cipher_info->base->ofb_func(ctx->cipher_ctx, - ilen, &ctx->unprocessed_len, ctx->iv, - input, output))) { + if (((mbedtls_cipher_mode_t) ctx->cipher_info->mode) == MBEDTLS_MODE_OFB) { + if (0 != (ret = mbedtls_cipher_get_base(ctx->cipher_info)->ofb_func(ctx->cipher_ctx, + ilen, + &ctx->unprocessed_len, + ctx->iv, + input, output))) { return ret; } @@ -671,10 +766,13 @@ int mbedtls_cipher_update(mbedtls_cipher_context_t *ctx, const unsigned char *in #endif /* MBEDTLS_CIPHER_MODE_OFB */ #if defined(MBEDTLS_CIPHER_MODE_CTR) - if (ctx->cipher_info->mode == MBEDTLS_MODE_CTR) { - if (0 != (ret = ctx->cipher_info->base->ctr_func(ctx->cipher_ctx, - ilen, &ctx->unprocessed_len, ctx->iv, - ctx->unprocessed_data, input, output))) { + if (((mbedtls_cipher_mode_t) ctx->cipher_info->mode) == MBEDTLS_MODE_CTR) { + if (0 != (ret = mbedtls_cipher_get_base(ctx->cipher_info)->ctr_func(ctx->cipher_ctx, + ilen, + &ctx->unprocessed_len, + ctx->iv, + ctx->unprocessed_data, + input, output))) { return ret; } @@ -685,14 +783,18 @@ int mbedtls_cipher_update(mbedtls_cipher_context_t *ctx, const unsigned char *in #endif /* MBEDTLS_CIPHER_MODE_CTR */ #if defined(MBEDTLS_CIPHER_MODE_XTS) - if (ctx->cipher_info->mode == MBEDTLS_MODE_XTS) { + if (((mbedtls_cipher_mode_t) ctx->cipher_info->mode) == MBEDTLS_MODE_XTS) { if (ctx->unprocessed_len > 0) { /* We can only process an entire data unit at a time. */ return MBEDTLS_ERR_CIPHER_FEATURE_UNAVAILABLE; } - ret = ctx->cipher_info->base->xts_func(ctx->cipher_ctx, - ctx->operation, ilen, ctx->iv, input, output); + ret = mbedtls_cipher_get_base(ctx->cipher_info)->xts_func(ctx->cipher_ctx, + ctx->operation, + ilen, + ctx->iv, + input, + output); if (ret != 0) { return ret; } @@ -704,9 +806,10 @@ int mbedtls_cipher_update(mbedtls_cipher_context_t *ctx, const unsigned char *in #endif /* MBEDTLS_CIPHER_MODE_XTS */ #if defined(MBEDTLS_CIPHER_MODE_STREAM) - if (ctx->cipher_info->mode == MBEDTLS_MODE_STREAM) { - if (0 != (ret = ctx->cipher_info->base->stream_func(ctx->cipher_ctx, - ilen, input, output))) { + if (((mbedtls_cipher_mode_t) ctx->cipher_info->mode) == MBEDTLS_MODE_STREAM) { + if (0 != (ret = mbedtls_cipher_get_base(ctx->cipher_info)->stream_func(ctx->cipher_ctx, + ilen, input, + output))) { return ret; } @@ -739,7 +842,7 @@ static int get_pkcs_padding(unsigned char *input, size_t input_len, size_t *data_len) { size_t i, pad_idx; - unsigned char padding_len, bad = 0; + unsigned char padding_len; if (NULL == input || NULL == data_len) { return MBEDTLS_ERR_CIPHER_BAD_INPUT_DATA; @@ -748,18 +851,19 @@ static int get_pkcs_padding(unsigned char *input, size_t input_len, padding_len = input[input_len - 1]; *data_len = input_len - padding_len; - /* Avoid logical || since it results in a branch */ - bad |= ~mbedtls_ct_size_mask_ge(input_len, padding_len); - bad |= mbedtls_ct_size_bool_eq(padding_len, 0); + mbedtls_ct_condition_t bad = mbedtls_ct_uint_gt(padding_len, input_len); + bad = mbedtls_ct_bool_or(bad, mbedtls_ct_uint_eq(padding_len, 0)); /* The number of bytes checked must be independent of padding_len, * so pick input_len, which is usually 8 or 16 (one block) */ pad_idx = input_len - padding_len; for (i = 0; i < input_len; i++) { - size_t mask = mbedtls_ct_size_mask_ge(i, pad_idx); - bad |= (input[i] ^ padding_len) & mask; + mbedtls_ct_condition_t in_padding = mbedtls_ct_uint_ge(i, pad_idx); + mbedtls_ct_condition_t different = mbedtls_ct_uint_ne(input[i], padding_len); + bad = mbedtls_ct_bool_or(bad, mbedtls_ct_bool_and(in_padding, different)); } - return -(int) mbedtls_ct_uint_if(bad, -MBEDTLS_ERR_CIPHER_INVALID_PADDING, 0); + + return mbedtls_ct_error_if_else_0(bad, MBEDTLS_ERR_CIPHER_INVALID_PADDING); } #endif /* MBEDTLS_CIPHER_PADDING_PKCS7 */ @@ -782,29 +886,28 @@ static void add_one_and_zeros_padding(unsigned char *output, static int get_one_and_zeros_padding(unsigned char *input, size_t input_len, size_t *data_len) { - unsigned int bad = 1; - if (NULL == input || NULL == data_len) { return MBEDTLS_ERR_CIPHER_BAD_INPUT_DATA; } + mbedtls_ct_condition_t in_padding = MBEDTLS_CT_TRUE; + mbedtls_ct_condition_t bad = MBEDTLS_CT_TRUE; + *data_len = 0; - size_t in_padding = ~0; for (ptrdiff_t i = (ptrdiff_t) (input_len) - 1; i >= 0; i--) { - size_t is_nonzero = mbedtls_ct_uint_mask(input[i]); + mbedtls_ct_condition_t is_nonzero = mbedtls_ct_bool(input[i]); - size_t hit_first_nonzero = is_nonzero & in_padding; + mbedtls_ct_condition_t hit_first_nonzero = mbedtls_ct_bool_and(is_nonzero, in_padding); - *data_len = (*data_len & ~hit_first_nonzero) | ((size_t) i & hit_first_nonzero); + *data_len = mbedtls_ct_size_if(hit_first_nonzero, i, *data_len); - bad = mbedtls_ct_uint_if((unsigned int) hit_first_nonzero, - !mbedtls_ct_size_bool_eq(input[i], 0x80), bad); + bad = mbedtls_ct_bool_if(hit_first_nonzero, mbedtls_ct_uint_ne(input[i], 0x80), bad); - in_padding = in_padding & ~is_nonzero; + in_padding = mbedtls_ct_bool_and(in_padding, mbedtls_ct_bool_not(is_nonzero)); } - return -(int) mbedtls_ct_uint_if(bad, -MBEDTLS_ERR_CIPHER_INVALID_PADDING, 0); + return mbedtls_ct_error_if_else_0(bad, MBEDTLS_ERR_CIPHER_INVALID_PADDING); } #endif /* MBEDTLS_CIPHER_PADDING_ONE_AND_ZEROS */ @@ -828,7 +931,8 @@ static int get_zeros_and_len_padding(unsigned char *input, size_t input_len, size_t *data_len) { size_t i, pad_idx; - unsigned char padding_len, bad = 0; + unsigned char padding_len; + mbedtls_ct_condition_t bad; if (NULL == input || NULL == data_len) { return MBEDTLS_ERR_CIPHER_BAD_INPUT_DATA; @@ -838,17 +942,19 @@ static int get_zeros_and_len_padding(unsigned char *input, size_t input_len, *data_len = input_len - padding_len; /* Avoid logical || since it results in a branch */ - bad |= mbedtls_ct_size_mask_ge(padding_len, input_len + 1); - bad |= mbedtls_ct_size_bool_eq(padding_len, 0); + bad = mbedtls_ct_uint_gt(padding_len, input_len); + bad = mbedtls_ct_bool_or(bad, mbedtls_ct_uint_eq(padding_len, 0)); /* The number of bytes checked must be independent of padding_len */ pad_idx = input_len - padding_len; for (i = 0; i < input_len - 1; i++) { - size_t mask = mbedtls_ct_size_mask_ge(i, pad_idx); - bad |= input[i] & mask; + mbedtls_ct_condition_t is_padding = mbedtls_ct_uint_ge(i, pad_idx); + mbedtls_ct_condition_t nonzero_pad_byte; + nonzero_pad_byte = mbedtls_ct_bool_if_else_0(is_padding, mbedtls_ct_bool(input[i])); + bad = mbedtls_ct_bool_or(bad, nonzero_pad_byte); } - return -(int) mbedtls_ct_uint_if(bad, -MBEDTLS_ERR_CIPHER_INVALID_PADDING, 0); + return mbedtls_ct_error_if_else_0(bad, MBEDTLS_ERR_CIPHER_INVALID_PADDING); } #endif /* MBEDTLS_CIPHER_PADDING_ZEROS_AND_LEN */ @@ -859,18 +965,14 @@ static int get_zeros_and_len_padding(unsigned char *input, size_t input_len, static void add_zeros_padding(unsigned char *output, size_t output_len, size_t data_len) { - size_t i; - - for (i = data_len; i < output_len; i++) { - output[i] = 0x00; - } + memset(output + data_len, 0, output_len - data_len); } static int get_zeros_padding(unsigned char *input, size_t input_len, size_t *data_len) { size_t i; - unsigned char done = 0, prev_done; + mbedtls_ct_condition_t done = MBEDTLS_CT_FALSE, prev_done; if (NULL == input || NULL == data_len) { return MBEDTLS_ERR_CIPHER_BAD_INPUT_DATA; @@ -879,9 +981,8 @@ static int get_zeros_padding(unsigned char *input, size_t input_len, *data_len = 0; for (i = input_len; i > 0; i--) { prev_done = done; - done |= !mbedtls_ct_size_bool_eq(input[i-1], 0); - size_t mask = mbedtls_ct_size_mask(done ^ prev_done); - *data_len |= i & mask; + done = mbedtls_ct_bool_or(done, mbedtls_ct_uint_ne(input[i-1], 0)); + *data_len = mbedtls_ct_size_if(mbedtls_ct_bool_ne(done, prev_done), i, *data_len); } return 0; @@ -910,39 +1011,47 @@ static int get_no_padding(unsigned char *input, size_t input_len, int mbedtls_cipher_finish(mbedtls_cipher_context_t *ctx, unsigned char *output, size_t *olen) { - CIPHER_VALIDATE_RET(ctx != NULL); - CIPHER_VALIDATE_RET(output != NULL); - CIPHER_VALIDATE_RET(olen != NULL); if (ctx->cipher_info == NULL) { return MBEDTLS_ERR_CIPHER_BAD_INPUT_DATA; } -#if defined(MBEDTLS_USE_PSA_CRYPTO) +#if defined(MBEDTLS_USE_PSA_CRYPTO) && !defined(MBEDTLS_DEPRECATED_REMOVED) if (ctx->psa_enabled == 1) { /* While PSA Crypto has an API for multipart * operations, we currently don't make it * accessible through the cipher layer. */ return MBEDTLS_ERR_CIPHER_FEATURE_UNAVAILABLE; } -#endif /* MBEDTLS_USE_PSA_CRYPTO */ +#endif /* MBEDTLS_USE_PSA_CRYPTO && !MBEDTLS_DEPRECATED_REMOVED */ *olen = 0; - if (MBEDTLS_MODE_CFB == ctx->cipher_info->mode || - MBEDTLS_MODE_OFB == ctx->cipher_info->mode || - MBEDTLS_MODE_CTR == ctx->cipher_info->mode || - MBEDTLS_MODE_GCM == ctx->cipher_info->mode || - MBEDTLS_MODE_XTS == ctx->cipher_info->mode || - MBEDTLS_MODE_STREAM == ctx->cipher_info->mode) { +#if defined(MBEDTLS_CIPHER_MODE_WITH_PADDING) + /* CBC mode requires padding so we make sure a call to + * mbedtls_cipher_set_padding_mode has been done successfully. */ + if (MBEDTLS_MODE_CBC == ((mbedtls_cipher_mode_t) ctx->cipher_info->mode)) { + if (ctx->get_padding == NULL) { + return MBEDTLS_ERR_CIPHER_BAD_INPUT_DATA; + } + } +#endif + + if (MBEDTLS_MODE_CFB == ((mbedtls_cipher_mode_t) ctx->cipher_info->mode) || + MBEDTLS_MODE_OFB == ((mbedtls_cipher_mode_t) ctx->cipher_info->mode) || + MBEDTLS_MODE_CTR == ((mbedtls_cipher_mode_t) ctx->cipher_info->mode) || + MBEDTLS_MODE_GCM == ((mbedtls_cipher_mode_t) ctx->cipher_info->mode) || + MBEDTLS_MODE_CCM_STAR_NO_TAG == ((mbedtls_cipher_mode_t) ctx->cipher_info->mode) || + MBEDTLS_MODE_XTS == ((mbedtls_cipher_mode_t) ctx->cipher_info->mode) || + MBEDTLS_MODE_STREAM == ((mbedtls_cipher_mode_t) ctx->cipher_info->mode)) { return 0; } - if ((MBEDTLS_CIPHER_CHACHA20 == ctx->cipher_info->type) || - (MBEDTLS_CIPHER_CHACHA20_POLY1305 == ctx->cipher_info->type)) { + if ((MBEDTLS_CIPHER_CHACHA20 == ((mbedtls_cipher_type_t) ctx->cipher_info->type)) || + (MBEDTLS_CIPHER_CHACHA20_POLY1305 == ((mbedtls_cipher_type_t) ctx->cipher_info->type))) { return 0; } - if (MBEDTLS_MODE_ECB == ctx->cipher_info->mode) { + if (MBEDTLS_MODE_ECB == ((mbedtls_cipher_mode_t) ctx->cipher_info->mode)) { if (ctx->unprocessed_len != 0) { return MBEDTLS_ERR_CIPHER_FULL_BLOCK_EXPECTED; } @@ -951,7 +1060,7 @@ int mbedtls_cipher_finish(mbedtls_cipher_context_t *ctx, } #if defined(MBEDTLS_CIPHER_MODE_CBC) - if (MBEDTLS_MODE_CBC == ctx->cipher_info->mode) { + if (MBEDTLS_MODE_CBC == ((mbedtls_cipher_mode_t) ctx->cipher_info->mode)) { int ret = 0; if (MBEDTLS_ENCRYPT == ctx->operation) { @@ -979,11 +1088,13 @@ int mbedtls_cipher_finish(mbedtls_cipher_context_t *ctx, } /* cipher block */ - if (0 != (ret = ctx->cipher_info->base->cbc_func(ctx->cipher_ctx, - ctx->operation, - mbedtls_cipher_get_block_size(ctx), - ctx->iv, - ctx->unprocessed_data, output))) { + if (0 != (ret = mbedtls_cipher_get_base(ctx->cipher_info)->cbc_func(ctx->cipher_ctx, + ctx->operation, + mbedtls_cipher_get_block_size( + ctx), + ctx->iv, + ctx->unprocessed_data, + output))) { return ret; } @@ -1008,13 +1119,12 @@ int mbedtls_cipher_finish(mbedtls_cipher_context_t *ctx, int mbedtls_cipher_set_padding_mode(mbedtls_cipher_context_t *ctx, mbedtls_cipher_padding_t mode) { - CIPHER_VALIDATE_RET(ctx != NULL); - - if (NULL == ctx->cipher_info || MBEDTLS_MODE_CBC != ctx->cipher_info->mode) { + if (NULL == ctx->cipher_info || + MBEDTLS_MODE_CBC != ((mbedtls_cipher_mode_t) ctx->cipher_info->mode)) { return MBEDTLS_ERR_CIPHER_BAD_INPUT_DATA; } -#if defined(MBEDTLS_USE_PSA_CRYPTO) +#if defined(MBEDTLS_USE_PSA_CRYPTO) && !defined(MBEDTLS_DEPRECATED_REMOVED) if (ctx->psa_enabled == 1) { /* While PSA Crypto knows about CBC padding * schemes, we currently don't make them @@ -1025,7 +1135,7 @@ int mbedtls_cipher_set_padding_mode(mbedtls_cipher_context_t *ctx, return 0; } -#endif /* MBEDTLS_USE_PSA_CRYPTO */ +#endif /* MBEDTLS_USE_PSA_CRYPTO && !MBEDTLS_DEPRECATED_REMOVED */ switch (mode) { #if defined(MBEDTLS_CIPHER_PADDING_PKCS7) @@ -1069,8 +1179,6 @@ int mbedtls_cipher_set_padding_mode(mbedtls_cipher_context_t *ctx, int mbedtls_cipher_write_tag(mbedtls_cipher_context_t *ctx, unsigned char *tag, size_t tag_len) { - CIPHER_VALIDATE_RET(ctx != NULL); - CIPHER_VALIDATE_RET(tag_len == 0 || tag != NULL); if (ctx->cipher_info == NULL) { return MBEDTLS_ERR_CIPHER_BAD_INPUT_DATA; } @@ -1079,24 +1187,28 @@ int mbedtls_cipher_write_tag(mbedtls_cipher_context_t *ctx, return MBEDTLS_ERR_CIPHER_BAD_INPUT_DATA; } -#if defined(MBEDTLS_USE_PSA_CRYPTO) +#if defined(MBEDTLS_USE_PSA_CRYPTO) && !defined(MBEDTLS_DEPRECATED_REMOVED) if (ctx->psa_enabled == 1) { /* While PSA Crypto has an API for multipart * operations, we currently don't make it * accessible through the cipher layer. */ return MBEDTLS_ERR_CIPHER_FEATURE_UNAVAILABLE; } -#endif /* MBEDTLS_USE_PSA_CRYPTO */ +#endif /* MBEDTLS_USE_PSA_CRYPTO && !MBEDTLS_DEPRECATED_REMOVED */ #if defined(MBEDTLS_GCM_C) - if (MBEDTLS_MODE_GCM == ctx->cipher_info->mode) { + if (MBEDTLS_MODE_GCM == ((mbedtls_cipher_mode_t) ctx->cipher_info->mode)) { + size_t output_length; + /* The code here doesn't yet support alternative implementations + * that can delay up to a block of output. */ return mbedtls_gcm_finish((mbedtls_gcm_context *) ctx->cipher_ctx, + NULL, 0, &output_length, tag, tag_len); } #endif #if defined(MBEDTLS_CHACHAPOLY_C) - if (MBEDTLS_CIPHER_CHACHA20_POLY1305 == ctx->cipher_info->type) { + if (MBEDTLS_CIPHER_CHACHA20_POLY1305 == ((mbedtls_cipher_type_t) ctx->cipher_info->type)) { /* Don't allow truncated MAC for Poly1305 */ if (tag_len != 16U) { return MBEDTLS_ERR_CIPHER_BAD_INPUT_DATA; @@ -1107,7 +1219,7 @@ int mbedtls_cipher_write_tag(mbedtls_cipher_context_t *ctx, } #endif - return 0; + return MBEDTLS_ERR_CIPHER_FEATURE_UNAVAILABLE; } int mbedtls_cipher_check_tag(mbedtls_cipher_context_t *ctx, @@ -1116,8 +1228,6 @@ int mbedtls_cipher_check_tag(mbedtls_cipher_context_t *ctx, unsigned char check_tag[16]; int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED; - CIPHER_VALIDATE_RET(ctx != NULL); - CIPHER_VALIDATE_RET(tag_len == 0 || tag != NULL); if (ctx->cipher_info == NULL) { return MBEDTLS_ERR_CIPHER_BAD_INPUT_DATA; } @@ -1126,29 +1236,31 @@ int mbedtls_cipher_check_tag(mbedtls_cipher_context_t *ctx, return MBEDTLS_ERR_CIPHER_BAD_INPUT_DATA; } -#if defined(MBEDTLS_USE_PSA_CRYPTO) +#if defined(MBEDTLS_USE_PSA_CRYPTO) && !defined(MBEDTLS_DEPRECATED_REMOVED) if (ctx->psa_enabled == 1) { /* While PSA Crypto has an API for multipart * operations, we currently don't make it * accessible through the cipher layer. */ return MBEDTLS_ERR_CIPHER_FEATURE_UNAVAILABLE; } -#endif /* MBEDTLS_USE_PSA_CRYPTO */ +#endif /* MBEDTLS_USE_PSA_CRYPTO && !MBEDTLS_DEPRECATED_REMOVED */ - /* Status to return on a non-authenticated algorithm. It would make sense - * to return MBEDTLS_ERR_CIPHER_INVALID_CONTEXT or perhaps - * MBEDTLS_ERR_CIPHER_BAD_INPUT_DATA, but at the time I write this our - * unit tests assume 0. */ - ret = 0; + /* Status to return on a non-authenticated algorithm. */ + ret = MBEDTLS_ERR_CIPHER_FEATURE_UNAVAILABLE; #if defined(MBEDTLS_GCM_C) - if (MBEDTLS_MODE_GCM == ctx->cipher_info->mode) { + if (MBEDTLS_MODE_GCM == ((mbedtls_cipher_mode_t) ctx->cipher_info->mode)) { + size_t output_length; + /* The code here doesn't yet support alternative implementations + * that can delay up to a block of output. */ + if (tag_len > sizeof(check_tag)) { return MBEDTLS_ERR_CIPHER_BAD_INPUT_DATA; } if (0 != (ret = mbedtls_gcm_finish( (mbedtls_gcm_context *) ctx->cipher_ctx, + NULL, 0, &output_length, check_tag, tag_len))) { return ret; } @@ -1162,7 +1274,7 @@ int mbedtls_cipher_check_tag(mbedtls_cipher_context_t *ctx, #endif /* MBEDTLS_GCM_C */ #if defined(MBEDTLS_CHACHAPOLY_C) - if (MBEDTLS_CIPHER_CHACHA20_POLY1305 == ctx->cipher_info->type) { + if (MBEDTLS_CIPHER_CHACHA20_POLY1305 == ((mbedtls_cipher_type_t) ctx->cipher_info->type)) { /* Don't allow truncated MAC for Poly1305 */ if (tag_len != sizeof(check_tag)) { return MBEDTLS_ERR_CIPHER_BAD_INPUT_DATA; @@ -1199,13 +1311,7 @@ int mbedtls_cipher_crypt(mbedtls_cipher_context_t *ctx, int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED; size_t finish_olen; - CIPHER_VALIDATE_RET(ctx != NULL); - CIPHER_VALIDATE_RET(iv_len == 0 || iv != NULL); - CIPHER_VALIDATE_RET(ilen == 0 || input != NULL); - CIPHER_VALIDATE_RET(output != NULL); - CIPHER_VALIDATE_RET(olen != NULL); - -#if defined(MBEDTLS_USE_PSA_CRYPTO) +#if defined(MBEDTLS_USE_PSA_CRYPTO) && !defined(MBEDTLS_DEPRECATED_REMOVED) if (ctx->psa_enabled == 1) { /* As in the non-PSA case, we don't check that * a key has been set. If not, the key slot will @@ -1236,13 +1342,13 @@ int mbedtls_cipher_crypt(mbedtls_cipher_context_t *ctx, * are terminated by unsuccessful calls to psa_cipher_update(), * and by any call to psa_cipher_finish(). */ if (status != PSA_SUCCESS) { - return MBEDTLS_ERR_CIPHER_HW_ACCEL_FAILED; + return MBEDTLS_ERR_PLATFORM_HW_ACCEL_FAILED; } - if (ctx->cipher_info->mode != MBEDTLS_MODE_ECB) { + if (((mbedtls_cipher_mode_t) ctx->cipher_info->mode) != MBEDTLS_MODE_ECB) { status = psa_cipher_set_iv(&cipher_op, iv, iv_len); if (status != PSA_SUCCESS) { - return MBEDTLS_ERR_CIPHER_HW_ACCEL_FAILED; + return MBEDTLS_ERR_PLATFORM_HW_ACCEL_FAILED; } } @@ -1250,20 +1356,20 @@ int mbedtls_cipher_crypt(mbedtls_cipher_context_t *ctx, input, ilen, output, ilen, olen); if (status != PSA_SUCCESS) { - return MBEDTLS_ERR_CIPHER_HW_ACCEL_FAILED; + return MBEDTLS_ERR_PLATFORM_HW_ACCEL_FAILED; } status = psa_cipher_finish(&cipher_op, output + *olen, ilen - *olen, &part_len); if (status != PSA_SUCCESS) { - return MBEDTLS_ERR_CIPHER_HW_ACCEL_FAILED; + return MBEDTLS_ERR_PLATFORM_HW_ACCEL_FAILED; } *olen += part_len; return 0; } -#endif /* MBEDTLS_USE_PSA_CRYPTO */ +#endif /* MBEDTLS_USE_PSA_CRYPTO && !MBEDTLS_DEPRECATED_REMOVED */ if ((ret = mbedtls_cipher_set_iv(ctx, iv, iv_len)) != 0) { return ret; @@ -1290,8 +1396,8 @@ int mbedtls_cipher_crypt(mbedtls_cipher_context_t *ctx, #if defined(MBEDTLS_CIPHER_MODE_AEAD) /* - * Packet-oriented encryption for AEAD modes: internal function shared by - * mbedtls_cipher_auth_encrypt() and mbedtls_cipher_auth_encrypt_ext(). + * Packet-oriented encryption for AEAD modes: internal function used by + * mbedtls_cipher_auth_encrypt_ext(). */ static int mbedtls_cipher_aead_encrypt(mbedtls_cipher_context_t *ctx, const unsigned char *iv, size_t iv_len, @@ -1300,7 +1406,7 @@ static int mbedtls_cipher_aead_encrypt(mbedtls_cipher_context_t *ctx, unsigned char *output, size_t *olen, unsigned char *tag, size_t tag_len) { -#if defined(MBEDTLS_USE_PSA_CRYPTO) +#if defined(MBEDTLS_USE_PSA_CRYPTO) && !defined(MBEDTLS_DEPRECATED_REMOVED) if (ctx->psa_enabled == 1) { /* As in the non-PSA case, we don't check that * a key has been set. If not, the key slot will @@ -1325,16 +1431,16 @@ static int mbedtls_cipher_aead_encrypt(mbedtls_cipher_context_t *ctx, input, ilen, output, ilen + tag_len, olen); if (status != PSA_SUCCESS) { - return MBEDTLS_ERR_CIPHER_HW_ACCEL_FAILED; + return MBEDTLS_ERR_PLATFORM_HW_ACCEL_FAILED; } *olen -= tag_len; return 0; } -#endif /* MBEDTLS_USE_PSA_CRYPTO */ +#endif /* MBEDTLS_USE_PSA_CRYPTO && !MBEDTLS_DEPRECATED_REMOVED */ #if defined(MBEDTLS_GCM_C) - if (MBEDTLS_MODE_GCM == ctx->cipher_info->mode) { + if (MBEDTLS_MODE_GCM == ((mbedtls_cipher_mode_t) ctx->cipher_info->mode)) { *olen = ilen; return mbedtls_gcm_crypt_and_tag(ctx->cipher_ctx, MBEDTLS_GCM_ENCRYPT, ilen, iv, iv_len, ad, ad_len, @@ -1342,7 +1448,7 @@ static int mbedtls_cipher_aead_encrypt(mbedtls_cipher_context_t *ctx, } #endif /* MBEDTLS_GCM_C */ #if defined(MBEDTLS_CCM_C) - if (MBEDTLS_MODE_CCM == ctx->cipher_info->mode) { + if (MBEDTLS_MODE_CCM == ((mbedtls_cipher_mode_t) ctx->cipher_info->mode)) { *olen = ilen; return mbedtls_ccm_encrypt_and_tag(ctx->cipher_ctx, ilen, iv, iv_len, ad, ad_len, input, output, @@ -1350,9 +1456,9 @@ static int mbedtls_cipher_aead_encrypt(mbedtls_cipher_context_t *ctx, } #endif /* MBEDTLS_CCM_C */ #if defined(MBEDTLS_CHACHAPOLY_C) - if (MBEDTLS_CIPHER_CHACHA20_POLY1305 == ctx->cipher_info->type) { + if (MBEDTLS_CIPHER_CHACHA20_POLY1305 == ((mbedtls_cipher_type_t) ctx->cipher_info->type)) { /* ChachaPoly has fixed length nonce and MAC (tag) */ - if ((iv_len != ctx->cipher_info->iv_size) || + if ((iv_len != mbedtls_cipher_info_get_iv_size(ctx->cipher_info)) || (tag_len != 16U)) { return MBEDTLS_ERR_CIPHER_BAD_INPUT_DATA; } @@ -1367,8 +1473,8 @@ static int mbedtls_cipher_aead_encrypt(mbedtls_cipher_context_t *ctx, } /* - * Packet-oriented encryption for AEAD modes: internal function shared by - * mbedtls_cipher_auth_encrypt() and mbedtls_cipher_auth_encrypt_ext(). + * Packet-oriented encryption for AEAD modes: internal function used by + * mbedtls_cipher_auth_encrypt_ext(). */ static int mbedtls_cipher_aead_decrypt(mbedtls_cipher_context_t *ctx, const unsigned char *iv, size_t iv_len, @@ -1377,7 +1483,7 @@ static int mbedtls_cipher_aead_decrypt(mbedtls_cipher_context_t *ctx, unsigned char *output, size_t *olen, const unsigned char *tag, size_t tag_len) { -#if defined(MBEDTLS_USE_PSA_CRYPTO) +#if defined(MBEDTLS_USE_PSA_CRYPTO) && !defined(MBEDTLS_DEPRECATED_REMOVED) if (ctx->psa_enabled == 1) { /* As in the non-PSA case, we don't check that * a key has been set. If not, the key slot will @@ -1404,15 +1510,15 @@ static int mbedtls_cipher_aead_decrypt(mbedtls_cipher_context_t *ctx, if (status == PSA_ERROR_INVALID_SIGNATURE) { return MBEDTLS_ERR_CIPHER_AUTH_FAILED; } else if (status != PSA_SUCCESS) { - return MBEDTLS_ERR_CIPHER_HW_ACCEL_FAILED; + return MBEDTLS_ERR_PLATFORM_HW_ACCEL_FAILED; } return 0; } -#endif /* MBEDTLS_USE_PSA_CRYPTO */ +#endif /* MBEDTLS_USE_PSA_CRYPTO && !MBEDTLS_DEPRECATED_REMOVED */ #if defined(MBEDTLS_GCM_C) - if (MBEDTLS_MODE_GCM == ctx->cipher_info->mode) { + if (MBEDTLS_MODE_GCM == ((mbedtls_cipher_mode_t) ctx->cipher_info->mode)) { int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED; *olen = ilen; @@ -1428,7 +1534,7 @@ static int mbedtls_cipher_aead_decrypt(mbedtls_cipher_context_t *ctx, } #endif /* MBEDTLS_GCM_C */ #if defined(MBEDTLS_CCM_C) - if (MBEDTLS_MODE_CCM == ctx->cipher_info->mode) { + if (MBEDTLS_MODE_CCM == ((mbedtls_cipher_mode_t) ctx->cipher_info->mode)) { int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED; *olen = ilen; @@ -1444,11 +1550,11 @@ static int mbedtls_cipher_aead_decrypt(mbedtls_cipher_context_t *ctx, } #endif /* MBEDTLS_CCM_C */ #if defined(MBEDTLS_CHACHAPOLY_C) - if (MBEDTLS_CIPHER_CHACHA20_POLY1305 == ctx->cipher_info->type) { + if (MBEDTLS_CIPHER_CHACHA20_POLY1305 == ((mbedtls_cipher_type_t) ctx->cipher_info->type)) { int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED; /* ChachaPoly has fixed length nonce and MAC (tag) */ - if ((iv_len != ctx->cipher_info->iv_size) || + if ((iv_len != mbedtls_cipher_info_get_iv_size(ctx->cipher_info)) || (tag_len != 16U)) { return MBEDTLS_ERR_CIPHER_BAD_INPUT_DATA; } @@ -1467,54 +1573,6 @@ static int mbedtls_cipher_aead_decrypt(mbedtls_cipher_context_t *ctx, return MBEDTLS_ERR_CIPHER_FEATURE_UNAVAILABLE; } - -#if !defined(MBEDTLS_DEPRECATED_REMOVED) -/* - * Packet-oriented encryption for AEAD modes: public legacy function. - */ -int mbedtls_cipher_auth_encrypt(mbedtls_cipher_context_t *ctx, - const unsigned char *iv, size_t iv_len, - const unsigned char *ad, size_t ad_len, - const unsigned char *input, size_t ilen, - unsigned char *output, size_t *olen, - unsigned char *tag, size_t tag_len) -{ - CIPHER_VALIDATE_RET(ctx != NULL); - CIPHER_VALIDATE_RET(iv_len == 0 || iv != NULL); - CIPHER_VALIDATE_RET(ad_len == 0 || ad != NULL); - CIPHER_VALIDATE_RET(ilen == 0 || input != NULL); - CIPHER_VALIDATE_RET(ilen == 0 || output != NULL); - CIPHER_VALIDATE_RET(olen != NULL); - CIPHER_VALIDATE_RET(tag_len == 0 || tag != NULL); - - return mbedtls_cipher_aead_encrypt(ctx, iv, iv_len, ad, ad_len, - input, ilen, output, olen, - tag, tag_len); -} - -/* - * Packet-oriented decryption for AEAD modes: public legacy function. - */ -int mbedtls_cipher_auth_decrypt(mbedtls_cipher_context_t *ctx, - const unsigned char *iv, size_t iv_len, - const unsigned char *ad, size_t ad_len, - const unsigned char *input, size_t ilen, - unsigned char *output, size_t *olen, - const unsigned char *tag, size_t tag_len) -{ - CIPHER_VALIDATE_RET(ctx != NULL); - CIPHER_VALIDATE_RET(iv_len == 0 || iv != NULL); - CIPHER_VALIDATE_RET(ad_len == 0 || ad != NULL); - CIPHER_VALIDATE_RET(ilen == 0 || input != NULL); - CIPHER_VALIDATE_RET(ilen == 0 || output != NULL); - CIPHER_VALIDATE_RET(olen != NULL); - CIPHER_VALIDATE_RET(tag_len == 0 || tag != NULL); - - return mbedtls_cipher_aead_decrypt(ctx, iv, iv_len, ad, ad_len, - input, ilen, output, olen, - tag, tag_len); -} -#endif /* !MBEDTLS_DEPRECATED_REMOVED */ #endif /* MBEDTLS_CIPHER_MODE_AEAD */ #if defined(MBEDTLS_CIPHER_MODE_AEAD) || defined(MBEDTLS_NIST_KW_C) @@ -1528,22 +1586,16 @@ int mbedtls_cipher_auth_encrypt_ext(mbedtls_cipher_context_t *ctx, unsigned char *output, size_t output_len, size_t *olen, size_t tag_len) { - CIPHER_VALIDATE_RET(ctx != NULL); - CIPHER_VALIDATE_RET(iv_len == 0 || iv != NULL); - CIPHER_VALIDATE_RET(ad_len == 0 || ad != NULL); - CIPHER_VALIDATE_RET(ilen == 0 || input != NULL); - CIPHER_VALIDATE_RET(output != NULL); - CIPHER_VALIDATE_RET(olen != NULL); - #if defined(MBEDTLS_NIST_KW_C) if ( -#if defined(MBEDTLS_USE_PSA_CRYPTO) +#if defined(MBEDTLS_USE_PSA_CRYPTO) && !defined(MBEDTLS_DEPRECATED_REMOVED) ctx->psa_enabled == 0 && #endif - (MBEDTLS_MODE_KW == ctx->cipher_info->mode || - MBEDTLS_MODE_KWP == ctx->cipher_info->mode)) { - mbedtls_nist_kw_mode_t mode = (MBEDTLS_MODE_KW == ctx->cipher_info->mode) ? - MBEDTLS_KW_MODE_KW : MBEDTLS_KW_MODE_KWP; + (MBEDTLS_MODE_KW == ((mbedtls_cipher_mode_t) ctx->cipher_info->mode) || + MBEDTLS_MODE_KWP == ((mbedtls_cipher_mode_t) ctx->cipher_info->mode))) { + mbedtls_nist_kw_mode_t mode = + (MBEDTLS_MODE_KW == ((mbedtls_cipher_mode_t) ctx->cipher_info->mode)) ? + MBEDTLS_KW_MODE_KW : MBEDTLS_KW_MODE_KWP; /* There is no iv, tag or ad associated with KW and KWP, * so these length should be 0 as documented. */ @@ -1585,22 +1637,16 @@ int mbedtls_cipher_auth_decrypt_ext(mbedtls_cipher_context_t *ctx, unsigned char *output, size_t output_len, size_t *olen, size_t tag_len) { - CIPHER_VALIDATE_RET(ctx != NULL); - CIPHER_VALIDATE_RET(iv_len == 0 || iv != NULL); - CIPHER_VALIDATE_RET(ad_len == 0 || ad != NULL); - CIPHER_VALIDATE_RET(ilen == 0 || input != NULL); - CIPHER_VALIDATE_RET(output_len == 0 || output != NULL); - CIPHER_VALIDATE_RET(olen != NULL); - #if defined(MBEDTLS_NIST_KW_C) if ( -#if defined(MBEDTLS_USE_PSA_CRYPTO) +#if defined(MBEDTLS_USE_PSA_CRYPTO) && !defined(MBEDTLS_DEPRECATED_REMOVED) ctx->psa_enabled == 0 && #endif - (MBEDTLS_MODE_KW == ctx->cipher_info->mode || - MBEDTLS_MODE_KWP == ctx->cipher_info->mode)) { - mbedtls_nist_kw_mode_t mode = (MBEDTLS_MODE_KW == ctx->cipher_info->mode) ? - MBEDTLS_KW_MODE_KW : MBEDTLS_KW_MODE_KWP; + (MBEDTLS_MODE_KW == ((mbedtls_cipher_mode_t) ctx->cipher_info->mode) || + MBEDTLS_MODE_KWP == ((mbedtls_cipher_mode_t) ctx->cipher_info->mode))) { + mbedtls_nist_kw_mode_t mode = + (MBEDTLS_MODE_KW == ((mbedtls_cipher_mode_t) ctx->cipher_info->mode)) ? + MBEDTLS_KW_MODE_KW : MBEDTLS_KW_MODE_KWP; /* There is no iv, tag or ad associated with KW and KWP, * so these length should be 0 as documented. */ diff --git a/vendor/mbedtls/library/cipher_wrap.c b/vendor/mbedtls/library/cipher_wrap.c index f92d000380..d2fee22e2b 100644 --- a/vendor/mbedtls/library/cipher_wrap.c +++ b/vendor/mbedtls/library/cipher_wrap.c @@ -6,26 +6,14 @@ * \author Adriaan de Jong * * Copyright The Mbed TLS Contributors - * SPDX-License-Identifier: Apache-2.0 - * - * Licensed under the Apache License, Version 2.0 (the "License"); you may - * not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT - * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. + * SPDX-License-Identifier: Apache-2.0 OR GPL-2.0-or-later */ #include "common.h" #if defined(MBEDTLS_CIPHER_C) -#include "mbedtls/cipher_internal.h" +#include "cipher_wrap.h" #include "mbedtls/error.h" #if defined(MBEDTLS_CHACHAPOLY_C) @@ -36,10 +24,6 @@ #include "mbedtls/aes.h" #endif -#if defined(MBEDTLS_ARC4_C) -#include "mbedtls/arc4.h" -#endif - #if defined(MBEDTLS_CAMELLIA_C) #include "mbedtls/camellia.h" #endif @@ -52,10 +36,6 @@ #include "mbedtls/des.h" #endif -#if defined(MBEDTLS_BLOWFISH_C) -#include "mbedtls/blowfish.h" -#endif - #if defined(MBEDTLS_CHACHA20_C) #include "mbedtls/chacha20.h" #endif @@ -78,7 +58,65 @@ #include "mbedtls/platform.h" -#if defined(MBEDTLS_GCM_C) +enum mbedtls_cipher_base_index { +#if defined(MBEDTLS_AES_C) + MBEDTLS_CIPHER_BASE_INDEX_AES, +#endif +#if defined(MBEDTLS_ARIA_C) + MBEDTLS_CIPHER_BASE_INDEX_ARIA, +#endif +#if defined(MBEDTLS_CAMELLIA_C) + MBEDTLS_CIPHER_BASE_INDEX_CAMELLIA, +#endif +#if defined(MBEDTLS_CIPHER_HAVE_CCM_AES_VIA_LEGACY_OR_USE_PSA) + MBEDTLS_CIPHER_BASE_INDEX_CCM_AES, +#endif +#if defined(MBEDTLS_CCM_C) && defined(MBEDTLS_ARIA_C) + MBEDTLS_CIPHER_BASE_INDEX_CCM_ARIA, +#endif +#if defined(MBEDTLS_CCM_C) && defined(MBEDTLS_CAMELLIA_C) + MBEDTLS_CIPHER_BASE_INDEX_CCM_CAMELLIA, +#endif +#if defined(MBEDTLS_CHACHA20_C) + MBEDTLS_CIPHER_BASE_INDEX_CHACHA20_BASE, +#endif +#if defined(MBEDTLS_CHACHAPOLY_C) + MBEDTLS_CIPHER_BASE_INDEX_CHACHAPOLY_BASE, +#endif +#if defined(MBEDTLS_DES_C) + MBEDTLS_CIPHER_BASE_INDEX_DES_EDE3, +#endif +#if defined(MBEDTLS_DES_C) + MBEDTLS_CIPHER_BASE_INDEX_DES_EDE, +#endif +#if defined(MBEDTLS_DES_C) + MBEDTLS_CIPHER_BASE_INDEX_DES, +#endif +#if defined(MBEDTLS_CIPHER_HAVE_GCM_AES_VIA_LEGACY_OR_USE_PSA) + MBEDTLS_CIPHER_BASE_INDEX_GCM_AES, +#endif +#if defined(MBEDTLS_GCM_C) && defined(MBEDTLS_ARIA_C) + MBEDTLS_CIPHER_BASE_INDEX_GCM_ARIA, +#endif +#if defined(MBEDTLS_GCM_C) && defined(MBEDTLS_CAMELLIA_C) + MBEDTLS_CIPHER_BASE_INDEX_GCM_CAMELLIA, +#endif +#if defined(MBEDTLS_NIST_KW_C) + MBEDTLS_CIPHER_BASE_INDEX_KW_AES, +#endif +#if defined(MBEDTLS_CIPHER_NULL_CIPHER) + MBEDTLS_CIPHER_BASE_INDEX_NULL_BASE, +#endif +#if defined(MBEDTLS_CIPHER_MODE_XTS) && defined(MBEDTLS_AES_C) + MBEDTLS_CIPHER_BASE_INDEX_XTS_AES, +#endif + /* Prevent compile failure due to empty enum */ + MBEDTLS_CIPHER_BASE_PREVENT_EMPTY_ENUM +}; + +#if defined(MBEDTLS_GCM_C) && \ + (defined(MBEDTLS_CIPHER_HAVE_GCM_AES_VIA_LEGACY_OR_USE_PSA) || \ + defined(MBEDTLS_ARIA_C) || defined(MBEDTLS_CAMELLIA_C)) /* shared by all GCM ciphers */ static void *gcm_ctx_alloc(void) { @@ -98,7 +136,9 @@ static void gcm_ctx_free(void *ctx) } #endif /* MBEDTLS_GCM_C */ -#if defined(MBEDTLS_CCM_C) +#if defined(MBEDTLS_CCM_C) && \ + (defined(MBEDTLS_CIPHER_HAVE_CCM_AES_VIA_LEGACY_OR_USE_PSA) || \ + defined(MBEDTLS_ARIA_C) || defined(MBEDTLS_CAMELLIA_C)) /* shared by all CCM ciphers */ static void *ccm_ctx_alloc(void) { @@ -190,11 +230,13 @@ static int aes_crypt_xts_wrap(void *ctx, mbedtls_operation_t operation, } #endif /* MBEDTLS_CIPHER_MODE_XTS */ +#if !defined(MBEDTLS_BLOCK_CIPHER_NO_DECRYPT) static int aes_setkey_dec_wrap(void *ctx, const unsigned char *key, unsigned int key_bitlen) { return mbedtls_aes_setkey_dec((mbedtls_aes_context *) ctx, key, key_bitlen); } +#endif static int aes_setkey_enc_wrap(void *ctx, const unsigned char *key, unsigned int key_bitlen) @@ -243,182 +285,194 @@ static const mbedtls_cipher_base_t aes_info = { NULL, #endif aes_setkey_enc_wrap, +#if !defined(MBEDTLS_BLOCK_CIPHER_NO_DECRYPT) aes_setkey_dec_wrap, +#endif aes_ctx_alloc, aes_ctx_free }; static const mbedtls_cipher_info_t aes_128_ecb_info = { - MBEDTLS_CIPHER_AES_128_ECB, - MBEDTLS_MODE_ECB, - 128, "AES-128-ECB", - 0, - 0, 16, - &aes_info + 0 >> MBEDTLS_IV_SIZE_SHIFT, + 128 >> MBEDTLS_KEY_BITLEN_SHIFT, + MBEDTLS_MODE_ECB, + MBEDTLS_CIPHER_AES_128_ECB, + 0, + MBEDTLS_CIPHER_BASE_INDEX_AES }; +#if !defined(MBEDTLS_AES_ONLY_128_BIT_KEY_LENGTH) static const mbedtls_cipher_info_t aes_192_ecb_info = { - MBEDTLS_CIPHER_AES_192_ECB, - MBEDTLS_MODE_ECB, - 192, "AES-192-ECB", - 0, - 0, 16, - &aes_info + 0 >> MBEDTLS_IV_SIZE_SHIFT, + 192 >> MBEDTLS_KEY_BITLEN_SHIFT, + MBEDTLS_MODE_ECB, + MBEDTLS_CIPHER_AES_192_ECB, + 0, + MBEDTLS_CIPHER_BASE_INDEX_AES }; static const mbedtls_cipher_info_t aes_256_ecb_info = { - MBEDTLS_CIPHER_AES_256_ECB, - MBEDTLS_MODE_ECB, - 256, "AES-256-ECB", - 0, - 0, 16, - &aes_info + 0 >> MBEDTLS_IV_SIZE_SHIFT, + 256 >> MBEDTLS_KEY_BITLEN_SHIFT, + MBEDTLS_MODE_ECB, + MBEDTLS_CIPHER_AES_256_ECB, + 0, + MBEDTLS_CIPHER_BASE_INDEX_AES }; +#endif #if defined(MBEDTLS_CIPHER_MODE_CBC) static const mbedtls_cipher_info_t aes_128_cbc_info = { - MBEDTLS_CIPHER_AES_128_CBC, - MBEDTLS_MODE_CBC, - 128, "AES-128-CBC", 16, + 16 >> MBEDTLS_IV_SIZE_SHIFT, + 128 >> MBEDTLS_KEY_BITLEN_SHIFT, + MBEDTLS_MODE_CBC, + MBEDTLS_CIPHER_AES_128_CBC, 0, - 16, - &aes_info + MBEDTLS_CIPHER_BASE_INDEX_AES }; +#if !defined(MBEDTLS_AES_ONLY_128_BIT_KEY_LENGTH) static const mbedtls_cipher_info_t aes_192_cbc_info = { - MBEDTLS_CIPHER_AES_192_CBC, - MBEDTLS_MODE_CBC, - 192, "AES-192-CBC", 16, + 16 >> MBEDTLS_IV_SIZE_SHIFT, + 192 >> MBEDTLS_KEY_BITLEN_SHIFT, + MBEDTLS_MODE_CBC, + MBEDTLS_CIPHER_AES_192_CBC, 0, - 16, - &aes_info + MBEDTLS_CIPHER_BASE_INDEX_AES }; static const mbedtls_cipher_info_t aes_256_cbc_info = { - MBEDTLS_CIPHER_AES_256_CBC, - MBEDTLS_MODE_CBC, - 256, "AES-256-CBC", 16, + 16 >> MBEDTLS_IV_SIZE_SHIFT, + 256 >> MBEDTLS_KEY_BITLEN_SHIFT, + MBEDTLS_MODE_CBC, + MBEDTLS_CIPHER_AES_256_CBC, 0, - 16, - &aes_info + MBEDTLS_CIPHER_BASE_INDEX_AES }; +#endif #endif /* MBEDTLS_CIPHER_MODE_CBC */ #if defined(MBEDTLS_CIPHER_MODE_CFB) static const mbedtls_cipher_info_t aes_128_cfb128_info = { - MBEDTLS_CIPHER_AES_128_CFB128, - MBEDTLS_MODE_CFB, - 128, "AES-128-CFB128", 16, + 16 >> MBEDTLS_IV_SIZE_SHIFT, + 128 >> MBEDTLS_KEY_BITLEN_SHIFT, + MBEDTLS_MODE_CFB, + MBEDTLS_CIPHER_AES_128_CFB128, 0, - 16, - &aes_info + MBEDTLS_CIPHER_BASE_INDEX_AES }; +#if !defined(MBEDTLS_AES_ONLY_128_BIT_KEY_LENGTH) static const mbedtls_cipher_info_t aes_192_cfb128_info = { - MBEDTLS_CIPHER_AES_192_CFB128, - MBEDTLS_MODE_CFB, - 192, "AES-192-CFB128", 16, + 16 >> MBEDTLS_IV_SIZE_SHIFT, + 192 >> MBEDTLS_KEY_BITLEN_SHIFT, + MBEDTLS_MODE_CFB, + MBEDTLS_CIPHER_AES_192_CFB128, 0, - 16, - &aes_info + MBEDTLS_CIPHER_BASE_INDEX_AES }; static const mbedtls_cipher_info_t aes_256_cfb128_info = { - MBEDTLS_CIPHER_AES_256_CFB128, - MBEDTLS_MODE_CFB, - 256, "AES-256-CFB128", 16, + 16 >> MBEDTLS_IV_SIZE_SHIFT, + 256 >> MBEDTLS_KEY_BITLEN_SHIFT, + MBEDTLS_MODE_CFB, + MBEDTLS_CIPHER_AES_256_CFB128, 0, - 16, - &aes_info + MBEDTLS_CIPHER_BASE_INDEX_AES }; +#endif #endif /* MBEDTLS_CIPHER_MODE_CFB */ #if defined(MBEDTLS_CIPHER_MODE_OFB) static const mbedtls_cipher_info_t aes_128_ofb_info = { - MBEDTLS_CIPHER_AES_128_OFB, - MBEDTLS_MODE_OFB, - 128, "AES-128-OFB", 16, + 16 >> MBEDTLS_IV_SIZE_SHIFT, + 128 >> MBEDTLS_KEY_BITLEN_SHIFT, + MBEDTLS_MODE_OFB, + MBEDTLS_CIPHER_AES_128_OFB, 0, - 16, - &aes_info + MBEDTLS_CIPHER_BASE_INDEX_AES }; +#if !defined(MBEDTLS_AES_ONLY_128_BIT_KEY_LENGTH) static const mbedtls_cipher_info_t aes_192_ofb_info = { - MBEDTLS_CIPHER_AES_192_OFB, - MBEDTLS_MODE_OFB, - 192, "AES-192-OFB", 16, + 16 >> MBEDTLS_IV_SIZE_SHIFT, + 192 >> MBEDTLS_KEY_BITLEN_SHIFT, + MBEDTLS_MODE_OFB, + MBEDTLS_CIPHER_AES_192_OFB, 0, - 16, - &aes_info + MBEDTLS_CIPHER_BASE_INDEX_AES }; static const mbedtls_cipher_info_t aes_256_ofb_info = { - MBEDTLS_CIPHER_AES_256_OFB, - MBEDTLS_MODE_OFB, - 256, "AES-256-OFB", 16, + 16 >> MBEDTLS_IV_SIZE_SHIFT, + 256 >> MBEDTLS_KEY_BITLEN_SHIFT, + MBEDTLS_MODE_OFB, + MBEDTLS_CIPHER_AES_256_OFB, 0, - 16, - &aes_info + MBEDTLS_CIPHER_BASE_INDEX_AES }; +#endif #endif /* MBEDTLS_CIPHER_MODE_OFB */ #if defined(MBEDTLS_CIPHER_MODE_CTR) static const mbedtls_cipher_info_t aes_128_ctr_info = { - MBEDTLS_CIPHER_AES_128_CTR, - MBEDTLS_MODE_CTR, - 128, "AES-128-CTR", 16, + 16 >> MBEDTLS_IV_SIZE_SHIFT, + 128 >> MBEDTLS_KEY_BITLEN_SHIFT, + MBEDTLS_MODE_CTR, + MBEDTLS_CIPHER_AES_128_CTR, 0, - 16, - &aes_info + MBEDTLS_CIPHER_BASE_INDEX_AES }; +#if !defined(MBEDTLS_AES_ONLY_128_BIT_KEY_LENGTH) static const mbedtls_cipher_info_t aes_192_ctr_info = { - MBEDTLS_CIPHER_AES_192_CTR, - MBEDTLS_MODE_CTR, - 192, "AES-192-CTR", 16, + 16 >> MBEDTLS_IV_SIZE_SHIFT, + 192 >> MBEDTLS_KEY_BITLEN_SHIFT, + MBEDTLS_MODE_CTR, + MBEDTLS_CIPHER_AES_192_CTR, 0, - 16, - &aes_info + MBEDTLS_CIPHER_BASE_INDEX_AES }; static const mbedtls_cipher_info_t aes_256_ctr_info = { - MBEDTLS_CIPHER_AES_256_CTR, - MBEDTLS_MODE_CTR, - 256, "AES-256-CTR", 16, + 16 >> MBEDTLS_IV_SIZE_SHIFT, + 256 >> MBEDTLS_KEY_BITLEN_SHIFT, + MBEDTLS_MODE_CTR, + MBEDTLS_CIPHER_AES_256_CTR, 0, - 16, - &aes_info + MBEDTLS_CIPHER_BASE_INDEX_AES }; +#endif #endif /* MBEDTLS_CIPHER_MODE_CTR */ #if defined(MBEDTLS_CIPHER_MODE_XTS) @@ -487,36 +541,41 @@ static const mbedtls_cipher_base_t xts_aes_info = { }; static const mbedtls_cipher_info_t aes_128_xts_info = { - MBEDTLS_CIPHER_AES_128_XTS, - MBEDTLS_MODE_XTS, - 256, "AES-128-XTS", 16, + 16 >> MBEDTLS_IV_SIZE_SHIFT, + 256 >> MBEDTLS_KEY_BITLEN_SHIFT, + MBEDTLS_MODE_XTS, + MBEDTLS_CIPHER_AES_128_XTS, 0, - 16, - &xts_aes_info + MBEDTLS_CIPHER_BASE_INDEX_XTS_AES }; +#if !defined(MBEDTLS_AES_ONLY_128_BIT_KEY_LENGTH) static const mbedtls_cipher_info_t aes_256_xts_info = { - MBEDTLS_CIPHER_AES_256_XTS, - MBEDTLS_MODE_XTS, - 512, "AES-256-XTS", 16, + 16 >> MBEDTLS_IV_SIZE_SHIFT, + 512 >> MBEDTLS_KEY_BITLEN_SHIFT, + MBEDTLS_MODE_XTS, + MBEDTLS_CIPHER_AES_256_XTS, 0, - 16, - &xts_aes_info + MBEDTLS_CIPHER_BASE_INDEX_XTS_AES }; +#endif #endif /* MBEDTLS_CIPHER_MODE_XTS */ +#endif /* MBEDTLS_AES_C */ -#if defined(MBEDTLS_GCM_C) +#if defined(MBEDTLS_GCM_C) && defined(MBEDTLS_CCM_GCM_CAN_AES) static int gcm_aes_setkey_wrap(void *ctx, const unsigned char *key, unsigned int key_bitlen) { return mbedtls_gcm_setkey((mbedtls_gcm_context *) ctx, MBEDTLS_CIPHER_ID_AES, key, key_bitlen); } +#endif /* MBEDTLS_GCM_C && MBEDTLS_CCM_GCM_CAN_AES */ +#if defined(MBEDTLS_CIPHER_HAVE_GCM_AES_VIA_LEGACY_OR_USE_PSA) static const mbedtls_cipher_base_t gcm_aes_info = { MBEDTLS_CIPHER_ID_AES, NULL, @@ -538,54 +597,69 @@ static const mbedtls_cipher_base_t gcm_aes_info = { #if defined(MBEDTLS_CIPHER_MODE_STREAM) NULL, #endif +#if defined(MBEDTLS_GCM_C) gcm_aes_setkey_wrap, +#if !defined(MBEDTLS_BLOCK_CIPHER_NO_DECRYPT) gcm_aes_setkey_wrap, +#endif gcm_ctx_alloc, gcm_ctx_free, +#else + NULL, + NULL, + NULL, + NULL, +#endif /* MBEDTLS_GCM_C */ }; +#endif /* MBEDTLS_CIPHER_HAVE_GCM_AES_VIA_LEGACY_OR_USE_PSA */ +#if defined(MBEDTLS_CIPHER_HAVE_GCM_AES_VIA_LEGACY_OR_USE_PSA) static const mbedtls_cipher_info_t aes_128_gcm_info = { - MBEDTLS_CIPHER_AES_128_GCM, - MBEDTLS_MODE_GCM, - 128, "AES-128-GCM", - 12, - MBEDTLS_CIPHER_VARIABLE_IV_LEN, 16, - &gcm_aes_info + 12 >> MBEDTLS_IV_SIZE_SHIFT, + 128 >> MBEDTLS_KEY_BITLEN_SHIFT, + MBEDTLS_MODE_GCM, + MBEDTLS_CIPHER_AES_128_GCM, + MBEDTLS_CIPHER_VARIABLE_IV_LEN, + MBEDTLS_CIPHER_BASE_INDEX_GCM_AES }; +#if !defined(MBEDTLS_AES_ONLY_128_BIT_KEY_LENGTH) static const mbedtls_cipher_info_t aes_192_gcm_info = { - MBEDTLS_CIPHER_AES_192_GCM, - MBEDTLS_MODE_GCM, - 192, "AES-192-GCM", - 12, - MBEDTLS_CIPHER_VARIABLE_IV_LEN, 16, - &gcm_aes_info + 12 >> MBEDTLS_IV_SIZE_SHIFT, + 192 >> MBEDTLS_KEY_BITLEN_SHIFT, + MBEDTLS_MODE_GCM, + MBEDTLS_CIPHER_AES_192_GCM, + MBEDTLS_CIPHER_VARIABLE_IV_LEN, + MBEDTLS_CIPHER_BASE_INDEX_GCM_AES }; static const mbedtls_cipher_info_t aes_256_gcm_info = { - MBEDTLS_CIPHER_AES_256_GCM, - MBEDTLS_MODE_GCM, - 256, "AES-256-GCM", - 12, - MBEDTLS_CIPHER_VARIABLE_IV_LEN, 16, - &gcm_aes_info + 12 >> MBEDTLS_IV_SIZE_SHIFT, + 256 >> MBEDTLS_KEY_BITLEN_SHIFT, + MBEDTLS_MODE_GCM, + MBEDTLS_CIPHER_AES_256_GCM, + MBEDTLS_CIPHER_VARIABLE_IV_LEN, + MBEDTLS_CIPHER_BASE_INDEX_GCM_AES }; -#endif /* MBEDTLS_GCM_C */ +#endif +#endif /* MBEDTLS_CIPHER_HAVE_GCM_AES_VIA_LEGACY_OR_USE_PSA */ -#if defined(MBEDTLS_CCM_C) +#if defined(MBEDTLS_CCM_C) && defined(MBEDTLS_CCM_GCM_CAN_AES) static int ccm_aes_setkey_wrap(void *ctx, const unsigned char *key, unsigned int key_bitlen) { return mbedtls_ccm_setkey((mbedtls_ccm_context *) ctx, MBEDTLS_CIPHER_ID_AES, key, key_bitlen); } +#endif /* MBEDTLS_CCM_C && MBEDTLS_CCM_GCM_CAN_AES */ +#if defined(MBEDTLS_CIPHER_HAVE_CCM_AES_VIA_LEGACY_OR_USE_PSA) static const mbedtls_cipher_base_t ccm_aes_info = { MBEDTLS_CIPHER_ID_AES, NULL, @@ -607,47 +681,96 @@ static const mbedtls_cipher_base_t ccm_aes_info = { #if defined(MBEDTLS_CIPHER_MODE_STREAM) NULL, #endif +#if defined(MBEDTLS_CCM_C) ccm_aes_setkey_wrap, +#if !defined(MBEDTLS_BLOCK_CIPHER_NO_DECRYPT) ccm_aes_setkey_wrap, +#endif ccm_ctx_alloc, ccm_ctx_free, +#else + NULL, + NULL, + NULL, + NULL, +#endif }; +#endif /* MBEDTLS_CIPHER_HAVE_CCM_AES_VIA_LEGACY_OR_USE_PSA */ +#if defined(MBEDTLS_CIPHER_HAVE_CCM_AES_VIA_LEGACY_OR_USE_PSA) static const mbedtls_cipher_info_t aes_128_ccm_info = { - MBEDTLS_CIPHER_AES_128_CCM, - MBEDTLS_MODE_CCM, - 128, "AES-128-CCM", - 12, - MBEDTLS_CIPHER_VARIABLE_IV_LEN, 16, - &ccm_aes_info + 12 >> MBEDTLS_IV_SIZE_SHIFT, + 128 >> MBEDTLS_KEY_BITLEN_SHIFT, + MBEDTLS_MODE_CCM, + MBEDTLS_CIPHER_AES_128_CCM, + MBEDTLS_CIPHER_VARIABLE_IV_LEN, + MBEDTLS_CIPHER_BASE_INDEX_CCM_AES }; +#if !defined(MBEDTLS_AES_ONLY_128_BIT_KEY_LENGTH) static const mbedtls_cipher_info_t aes_192_ccm_info = { - MBEDTLS_CIPHER_AES_192_CCM, - MBEDTLS_MODE_CCM, - 192, "AES-192-CCM", - 12, - MBEDTLS_CIPHER_VARIABLE_IV_LEN, 16, - &ccm_aes_info + 12 >> MBEDTLS_IV_SIZE_SHIFT, + 192 >> MBEDTLS_KEY_BITLEN_SHIFT, + MBEDTLS_MODE_CCM, + MBEDTLS_CIPHER_AES_192_CCM, + MBEDTLS_CIPHER_VARIABLE_IV_LEN, + MBEDTLS_CIPHER_BASE_INDEX_CCM_AES }; static const mbedtls_cipher_info_t aes_256_ccm_info = { - MBEDTLS_CIPHER_AES_256_CCM, - MBEDTLS_MODE_CCM, - 256, "AES-256-CCM", - 12, + 16, + 12 >> MBEDTLS_IV_SIZE_SHIFT, + 256 >> MBEDTLS_KEY_BITLEN_SHIFT, + MBEDTLS_MODE_CCM, + MBEDTLS_CIPHER_AES_256_CCM, + MBEDTLS_CIPHER_VARIABLE_IV_LEN, + MBEDTLS_CIPHER_BASE_INDEX_CCM_AES +}; +#endif +#endif /* MBEDTLS_CIPHER_HAVE_CCM_AES_VIA_LEGACY_OR_USE_PSA */ + +#if defined(MBEDTLS_CIPHER_HAVE_CCM_STAR_NO_TAG_AES_VIA_LEGACY_OR_USE_PSA) +static const mbedtls_cipher_info_t aes_128_ccm_star_no_tag_info = { + "AES-128-CCM*-NO-TAG", + 16, + 12 >> MBEDTLS_IV_SIZE_SHIFT, + 128 >> MBEDTLS_KEY_BITLEN_SHIFT, + MBEDTLS_MODE_CCM_STAR_NO_TAG, + MBEDTLS_CIPHER_AES_128_CCM_STAR_NO_TAG, MBEDTLS_CIPHER_VARIABLE_IV_LEN, + MBEDTLS_CIPHER_BASE_INDEX_CCM_AES +}; + +#if !defined(MBEDTLS_AES_ONLY_128_BIT_KEY_LENGTH) +static const mbedtls_cipher_info_t aes_192_ccm_star_no_tag_info = { + "AES-192-CCM*-NO-TAG", 16, - &ccm_aes_info + 12 >> MBEDTLS_IV_SIZE_SHIFT, + 192 >> MBEDTLS_KEY_BITLEN_SHIFT, + MBEDTLS_MODE_CCM_STAR_NO_TAG, + MBEDTLS_CIPHER_AES_192_CCM_STAR_NO_TAG, + MBEDTLS_CIPHER_VARIABLE_IV_LEN, + MBEDTLS_CIPHER_BASE_INDEX_CCM_AES }; -#endif /* MBEDTLS_CCM_C */ -#endif /* MBEDTLS_AES_C */ +static const mbedtls_cipher_info_t aes_256_ccm_star_no_tag_info = { + "AES-256-CCM*-NO-TAG", + 16, + 12 >> MBEDTLS_IV_SIZE_SHIFT, + 256 >> MBEDTLS_KEY_BITLEN_SHIFT, + MBEDTLS_MODE_CCM_STAR_NO_TAG, + MBEDTLS_CIPHER_AES_256_CCM_STAR_NO_TAG, + MBEDTLS_CIPHER_VARIABLE_IV_LEN, + MBEDTLS_CIPHER_BASE_INDEX_CCM_AES +}; +#endif +#endif /* MBEDTLS_CIPHER_HAVE_CCM_STAR_NO_TAG_AES_VIA_LEGACY_OR_USE_PSA */ + #if defined(MBEDTLS_CAMELLIA_C) @@ -688,11 +811,13 @@ static int camellia_crypt_ctr_wrap(void *ctx, size_t length, size_t *nc_off, } #endif /* MBEDTLS_CIPHER_MODE_CTR */ +#if !defined(MBEDTLS_BLOCK_CIPHER_NO_DECRYPT) static int camellia_setkey_dec_wrap(void *ctx, const unsigned char *key, unsigned int key_bitlen) { return mbedtls_camellia_setkey_dec((mbedtls_camellia_context *) ctx, key, key_bitlen); } +#endif static int camellia_setkey_enc_wrap(void *ctx, const unsigned char *key, unsigned int key_bitlen) @@ -742,146 +867,148 @@ static const mbedtls_cipher_base_t camellia_info = { NULL, #endif camellia_setkey_enc_wrap, +#if !defined(MBEDTLS_BLOCK_CIPHER_NO_DECRYPT) camellia_setkey_dec_wrap, +#endif camellia_ctx_alloc, camellia_ctx_free }; static const mbedtls_cipher_info_t camellia_128_ecb_info = { - MBEDTLS_CIPHER_CAMELLIA_128_ECB, - MBEDTLS_MODE_ECB, - 128, "CAMELLIA-128-ECB", - 0, - 0, 16, - &camellia_info + 0 >> MBEDTLS_IV_SIZE_SHIFT, + 128 >> MBEDTLS_KEY_BITLEN_SHIFT, + MBEDTLS_MODE_ECB, + MBEDTLS_CIPHER_CAMELLIA_128_ECB, + 0, + MBEDTLS_CIPHER_BASE_INDEX_CAMELLIA }; static const mbedtls_cipher_info_t camellia_192_ecb_info = { - MBEDTLS_CIPHER_CAMELLIA_192_ECB, - MBEDTLS_MODE_ECB, - 192, "CAMELLIA-192-ECB", - 0, - 0, 16, - &camellia_info + 0 >> MBEDTLS_IV_SIZE_SHIFT, + 192 >> MBEDTLS_KEY_BITLEN_SHIFT, + MBEDTLS_MODE_ECB, + MBEDTLS_CIPHER_CAMELLIA_192_ECB, + 0, + MBEDTLS_CIPHER_BASE_INDEX_CAMELLIA }; static const mbedtls_cipher_info_t camellia_256_ecb_info = { - MBEDTLS_CIPHER_CAMELLIA_256_ECB, - MBEDTLS_MODE_ECB, - 256, "CAMELLIA-256-ECB", - 0, - 0, 16, - &camellia_info + 0 >> MBEDTLS_IV_SIZE_SHIFT, + 256 >> MBEDTLS_KEY_BITLEN_SHIFT, + MBEDTLS_MODE_ECB, + MBEDTLS_CIPHER_CAMELLIA_256_ECB, + 0, + MBEDTLS_CIPHER_BASE_INDEX_CAMELLIA }; #if defined(MBEDTLS_CIPHER_MODE_CBC) static const mbedtls_cipher_info_t camellia_128_cbc_info = { - MBEDTLS_CIPHER_CAMELLIA_128_CBC, - MBEDTLS_MODE_CBC, - 128, "CAMELLIA-128-CBC", 16, + 16 >> MBEDTLS_IV_SIZE_SHIFT, + 128 >> MBEDTLS_KEY_BITLEN_SHIFT, + MBEDTLS_MODE_CBC, + MBEDTLS_CIPHER_CAMELLIA_128_CBC, 0, - 16, - &camellia_info + MBEDTLS_CIPHER_BASE_INDEX_CAMELLIA }; static const mbedtls_cipher_info_t camellia_192_cbc_info = { - MBEDTLS_CIPHER_CAMELLIA_192_CBC, - MBEDTLS_MODE_CBC, - 192, "CAMELLIA-192-CBC", 16, + 16 >> MBEDTLS_IV_SIZE_SHIFT, + 192 >> MBEDTLS_KEY_BITLEN_SHIFT, + MBEDTLS_MODE_CBC, + MBEDTLS_CIPHER_CAMELLIA_192_CBC, 0, - 16, - &camellia_info + MBEDTLS_CIPHER_BASE_INDEX_CAMELLIA }; static const mbedtls_cipher_info_t camellia_256_cbc_info = { - MBEDTLS_CIPHER_CAMELLIA_256_CBC, - MBEDTLS_MODE_CBC, - 256, "CAMELLIA-256-CBC", 16, + 16 >> MBEDTLS_IV_SIZE_SHIFT, + 256 >> MBEDTLS_KEY_BITLEN_SHIFT, + MBEDTLS_MODE_CBC, + MBEDTLS_CIPHER_CAMELLIA_256_CBC, 0, - 16, - &camellia_info + MBEDTLS_CIPHER_BASE_INDEX_CAMELLIA }; #endif /* MBEDTLS_CIPHER_MODE_CBC */ #if defined(MBEDTLS_CIPHER_MODE_CFB) static const mbedtls_cipher_info_t camellia_128_cfb128_info = { - MBEDTLS_CIPHER_CAMELLIA_128_CFB128, - MBEDTLS_MODE_CFB, - 128, "CAMELLIA-128-CFB128", 16, + 16 >> MBEDTLS_IV_SIZE_SHIFT, + 128 >> MBEDTLS_KEY_BITLEN_SHIFT, + MBEDTLS_MODE_CFB, + MBEDTLS_CIPHER_CAMELLIA_128_CFB128, 0, - 16, - &camellia_info + MBEDTLS_CIPHER_BASE_INDEX_CAMELLIA }; static const mbedtls_cipher_info_t camellia_192_cfb128_info = { - MBEDTLS_CIPHER_CAMELLIA_192_CFB128, - MBEDTLS_MODE_CFB, - 192, "CAMELLIA-192-CFB128", 16, + 16 >> MBEDTLS_IV_SIZE_SHIFT, + 192 >> MBEDTLS_KEY_BITLEN_SHIFT, + MBEDTLS_MODE_CFB, + MBEDTLS_CIPHER_CAMELLIA_192_CFB128, 0, - 16, - &camellia_info + MBEDTLS_CIPHER_BASE_INDEX_CAMELLIA }; static const mbedtls_cipher_info_t camellia_256_cfb128_info = { - MBEDTLS_CIPHER_CAMELLIA_256_CFB128, - MBEDTLS_MODE_CFB, - 256, "CAMELLIA-256-CFB128", 16, + 16 >> MBEDTLS_IV_SIZE_SHIFT, + 256 >> MBEDTLS_KEY_BITLEN_SHIFT, + MBEDTLS_MODE_CFB, + MBEDTLS_CIPHER_CAMELLIA_256_CFB128, 0, - 16, - &camellia_info + MBEDTLS_CIPHER_BASE_INDEX_CAMELLIA }; #endif /* MBEDTLS_CIPHER_MODE_CFB */ #if defined(MBEDTLS_CIPHER_MODE_CTR) static const mbedtls_cipher_info_t camellia_128_ctr_info = { - MBEDTLS_CIPHER_CAMELLIA_128_CTR, - MBEDTLS_MODE_CTR, - 128, "CAMELLIA-128-CTR", 16, + 16 >> MBEDTLS_IV_SIZE_SHIFT, + 128 >> MBEDTLS_KEY_BITLEN_SHIFT, + MBEDTLS_MODE_CTR, + MBEDTLS_CIPHER_CAMELLIA_128_CTR, 0, - 16, - &camellia_info + MBEDTLS_CIPHER_BASE_INDEX_CAMELLIA }; static const mbedtls_cipher_info_t camellia_192_ctr_info = { - MBEDTLS_CIPHER_CAMELLIA_192_CTR, - MBEDTLS_MODE_CTR, - 192, "CAMELLIA-192-CTR", 16, + 16 >> MBEDTLS_IV_SIZE_SHIFT, + 192 >> MBEDTLS_KEY_BITLEN_SHIFT, + MBEDTLS_MODE_CTR, + MBEDTLS_CIPHER_CAMELLIA_192_CTR, 0, - 16, - &camellia_info + MBEDTLS_CIPHER_BASE_INDEX_CAMELLIA }; static const mbedtls_cipher_info_t camellia_256_ctr_info = { - MBEDTLS_CIPHER_CAMELLIA_256_CTR, - MBEDTLS_MODE_CTR, - 256, "CAMELLIA-256-CTR", 16, + 16 >> MBEDTLS_IV_SIZE_SHIFT, + 256 >> MBEDTLS_KEY_BITLEN_SHIFT, + MBEDTLS_MODE_CTR, + MBEDTLS_CIPHER_CAMELLIA_256_CTR, 0, - 16, - &camellia_info + MBEDTLS_CIPHER_BASE_INDEX_CAMELLIA }; #endif /* MBEDTLS_CIPHER_MODE_CTR */ @@ -915,42 +1042,44 @@ static const mbedtls_cipher_base_t gcm_camellia_info = { NULL, #endif gcm_camellia_setkey_wrap, +#if !defined(MBEDTLS_BLOCK_CIPHER_NO_DECRYPT) gcm_camellia_setkey_wrap, +#endif gcm_ctx_alloc, gcm_ctx_free, }; static const mbedtls_cipher_info_t camellia_128_gcm_info = { - MBEDTLS_CIPHER_CAMELLIA_128_GCM, - MBEDTLS_MODE_GCM, - 128, "CAMELLIA-128-GCM", - 12, - MBEDTLS_CIPHER_VARIABLE_IV_LEN, 16, - &gcm_camellia_info + 12 >> MBEDTLS_IV_SIZE_SHIFT, + 128 >> MBEDTLS_KEY_BITLEN_SHIFT, + MBEDTLS_MODE_GCM, + MBEDTLS_CIPHER_CAMELLIA_128_GCM, + MBEDTLS_CIPHER_VARIABLE_IV_LEN, + MBEDTLS_CIPHER_BASE_INDEX_GCM_CAMELLIA }; static const mbedtls_cipher_info_t camellia_192_gcm_info = { - MBEDTLS_CIPHER_CAMELLIA_192_GCM, - MBEDTLS_MODE_GCM, - 192, "CAMELLIA-192-GCM", - 12, - MBEDTLS_CIPHER_VARIABLE_IV_LEN, 16, - &gcm_camellia_info + 12 >> MBEDTLS_IV_SIZE_SHIFT, + 192 >> MBEDTLS_KEY_BITLEN_SHIFT, + MBEDTLS_MODE_GCM, + MBEDTLS_CIPHER_CAMELLIA_192_GCM, + MBEDTLS_CIPHER_VARIABLE_IV_LEN, + MBEDTLS_CIPHER_BASE_INDEX_GCM_CAMELLIA }; static const mbedtls_cipher_info_t camellia_256_gcm_info = { - MBEDTLS_CIPHER_CAMELLIA_256_GCM, - MBEDTLS_MODE_GCM, - 256, "CAMELLIA-256-GCM", - 12, - MBEDTLS_CIPHER_VARIABLE_IV_LEN, 16, - &gcm_camellia_info + 12 >> MBEDTLS_IV_SIZE_SHIFT, + 256 >> MBEDTLS_KEY_BITLEN_SHIFT, + MBEDTLS_MODE_GCM, + MBEDTLS_CIPHER_CAMELLIA_256_GCM, + MBEDTLS_CIPHER_VARIABLE_IV_LEN, + MBEDTLS_CIPHER_BASE_INDEX_GCM_CAMELLIA }; #endif /* MBEDTLS_GCM_C */ @@ -984,42 +1113,77 @@ static const mbedtls_cipher_base_t ccm_camellia_info = { NULL, #endif ccm_camellia_setkey_wrap, +#if !defined(MBEDTLS_BLOCK_CIPHER_NO_DECRYPT) ccm_camellia_setkey_wrap, +#endif ccm_ctx_alloc, ccm_ctx_free, }; static const mbedtls_cipher_info_t camellia_128_ccm_info = { - MBEDTLS_CIPHER_CAMELLIA_128_CCM, - MBEDTLS_MODE_CCM, - 128, "CAMELLIA-128-CCM", - 12, - MBEDTLS_CIPHER_VARIABLE_IV_LEN, 16, - &ccm_camellia_info + 12 >> MBEDTLS_IV_SIZE_SHIFT, + 128 >> MBEDTLS_KEY_BITLEN_SHIFT, + MBEDTLS_MODE_CCM, + MBEDTLS_CIPHER_CAMELLIA_128_CCM, + MBEDTLS_CIPHER_VARIABLE_IV_LEN, + MBEDTLS_CIPHER_BASE_INDEX_CCM_CAMELLIA }; static const mbedtls_cipher_info_t camellia_192_ccm_info = { - MBEDTLS_CIPHER_CAMELLIA_192_CCM, - MBEDTLS_MODE_CCM, - 192, "CAMELLIA-192-CCM", - 12, - MBEDTLS_CIPHER_VARIABLE_IV_LEN, 16, - &ccm_camellia_info + 12 >> MBEDTLS_IV_SIZE_SHIFT, + 192 >> MBEDTLS_KEY_BITLEN_SHIFT, + MBEDTLS_MODE_CCM, + MBEDTLS_CIPHER_CAMELLIA_192_CCM, + MBEDTLS_CIPHER_VARIABLE_IV_LEN, + MBEDTLS_CIPHER_BASE_INDEX_CCM_CAMELLIA }; static const mbedtls_cipher_info_t camellia_256_ccm_info = { - MBEDTLS_CIPHER_CAMELLIA_256_CCM, - MBEDTLS_MODE_CCM, - 256, "CAMELLIA-256-CCM", - 12, + 16, + 12 >> MBEDTLS_IV_SIZE_SHIFT, + 256 >> MBEDTLS_KEY_BITLEN_SHIFT, + MBEDTLS_MODE_CCM, + MBEDTLS_CIPHER_CAMELLIA_256_CCM, + MBEDTLS_CIPHER_VARIABLE_IV_LEN, + MBEDTLS_CIPHER_BASE_INDEX_CCM_CAMELLIA +}; + +static const mbedtls_cipher_info_t camellia_128_ccm_star_no_tag_info = { + "CAMELLIA-128-CCM*-NO-TAG", + 16, + 12 >> MBEDTLS_IV_SIZE_SHIFT, + 128 >> MBEDTLS_KEY_BITLEN_SHIFT, + MBEDTLS_MODE_CCM_STAR_NO_TAG, + MBEDTLS_CIPHER_CAMELLIA_128_CCM_STAR_NO_TAG, MBEDTLS_CIPHER_VARIABLE_IV_LEN, + MBEDTLS_CIPHER_BASE_INDEX_CCM_CAMELLIA +}; + +static const mbedtls_cipher_info_t camellia_192_ccm_star_no_tag_info = { + "CAMELLIA-192-CCM*-NO-TAG", + 16, + 12 >> MBEDTLS_IV_SIZE_SHIFT, + 192 >> MBEDTLS_KEY_BITLEN_SHIFT, + MBEDTLS_MODE_CCM_STAR_NO_TAG, + MBEDTLS_CIPHER_CAMELLIA_192_CCM_STAR_NO_TAG, + MBEDTLS_CIPHER_VARIABLE_IV_LEN, + MBEDTLS_CIPHER_BASE_INDEX_CCM_CAMELLIA +}; + +static const mbedtls_cipher_info_t camellia_256_ccm_star_no_tag_info = { + "CAMELLIA-256-CCM*-NO-TAG", 16, - &ccm_camellia_info + 12 >> MBEDTLS_IV_SIZE_SHIFT, + 256 >> MBEDTLS_KEY_BITLEN_SHIFT, + MBEDTLS_MODE_CCM_STAR_NO_TAG, + MBEDTLS_CIPHER_CAMELLIA_256_CCM_STAR_NO_TAG, + MBEDTLS_CIPHER_VARIABLE_IV_LEN, + MBEDTLS_CIPHER_BASE_INDEX_CCM_CAMELLIA }; #endif /* MBEDTLS_CCM_C */ @@ -1065,11 +1229,13 @@ static int aria_crypt_ctr_wrap(void *ctx, size_t length, size_t *nc_off, } #endif /* MBEDTLS_CIPHER_MODE_CTR */ +#if !defined(MBEDTLS_BLOCK_CIPHER_NO_DECRYPT) static int aria_setkey_dec_wrap(void *ctx, const unsigned char *key, unsigned int key_bitlen) { return mbedtls_aria_setkey_dec((mbedtls_aria_context *) ctx, key, key_bitlen); } +#endif static int aria_setkey_enc_wrap(void *ctx, const unsigned char *key, unsigned int key_bitlen) @@ -1119,146 +1285,148 @@ static const mbedtls_cipher_base_t aria_info = { NULL, #endif aria_setkey_enc_wrap, +#if !defined(MBEDTLS_BLOCK_CIPHER_NO_DECRYPT) aria_setkey_dec_wrap, +#endif aria_ctx_alloc, aria_ctx_free }; static const mbedtls_cipher_info_t aria_128_ecb_info = { - MBEDTLS_CIPHER_ARIA_128_ECB, - MBEDTLS_MODE_ECB, - 128, "ARIA-128-ECB", - 0, - 0, 16, - &aria_info + 0 >> MBEDTLS_IV_SIZE_SHIFT, + 128 >> MBEDTLS_KEY_BITLEN_SHIFT, + MBEDTLS_MODE_ECB, + MBEDTLS_CIPHER_ARIA_128_ECB, + 0, + MBEDTLS_CIPHER_BASE_INDEX_ARIA }; static const mbedtls_cipher_info_t aria_192_ecb_info = { - MBEDTLS_CIPHER_ARIA_192_ECB, - MBEDTLS_MODE_ECB, - 192, "ARIA-192-ECB", - 0, - 0, 16, - &aria_info + 0 >> MBEDTLS_IV_SIZE_SHIFT, + 192 >> MBEDTLS_KEY_BITLEN_SHIFT, + MBEDTLS_MODE_ECB, + MBEDTLS_CIPHER_ARIA_192_ECB, + 0, + MBEDTLS_CIPHER_BASE_INDEX_ARIA }; static const mbedtls_cipher_info_t aria_256_ecb_info = { - MBEDTLS_CIPHER_ARIA_256_ECB, - MBEDTLS_MODE_ECB, - 256, "ARIA-256-ECB", - 0, - 0, 16, - &aria_info + 0 >> MBEDTLS_IV_SIZE_SHIFT, + 256 >> MBEDTLS_KEY_BITLEN_SHIFT, + MBEDTLS_MODE_ECB, + MBEDTLS_CIPHER_ARIA_256_ECB, + 0, + MBEDTLS_CIPHER_BASE_INDEX_ARIA }; #if defined(MBEDTLS_CIPHER_MODE_CBC) static const mbedtls_cipher_info_t aria_128_cbc_info = { - MBEDTLS_CIPHER_ARIA_128_CBC, - MBEDTLS_MODE_CBC, - 128, "ARIA-128-CBC", 16, + 16 >> MBEDTLS_IV_SIZE_SHIFT, + 128 >> MBEDTLS_KEY_BITLEN_SHIFT, + MBEDTLS_MODE_CBC, + MBEDTLS_CIPHER_ARIA_128_CBC, 0, - 16, - &aria_info + MBEDTLS_CIPHER_BASE_INDEX_ARIA }; static const mbedtls_cipher_info_t aria_192_cbc_info = { - MBEDTLS_CIPHER_ARIA_192_CBC, - MBEDTLS_MODE_CBC, - 192, "ARIA-192-CBC", 16, + 16 >> MBEDTLS_IV_SIZE_SHIFT, + 192 >> MBEDTLS_KEY_BITLEN_SHIFT, + MBEDTLS_MODE_CBC, + MBEDTLS_CIPHER_ARIA_192_CBC, 0, - 16, - &aria_info + MBEDTLS_CIPHER_BASE_INDEX_ARIA }; static const mbedtls_cipher_info_t aria_256_cbc_info = { - MBEDTLS_CIPHER_ARIA_256_CBC, - MBEDTLS_MODE_CBC, - 256, "ARIA-256-CBC", 16, + 16 >> MBEDTLS_IV_SIZE_SHIFT, + 256 >> MBEDTLS_KEY_BITLEN_SHIFT, + MBEDTLS_MODE_CBC, + MBEDTLS_CIPHER_ARIA_256_CBC, 0, - 16, - &aria_info + MBEDTLS_CIPHER_BASE_INDEX_ARIA }; #endif /* MBEDTLS_CIPHER_MODE_CBC */ #if defined(MBEDTLS_CIPHER_MODE_CFB) static const mbedtls_cipher_info_t aria_128_cfb128_info = { - MBEDTLS_CIPHER_ARIA_128_CFB128, - MBEDTLS_MODE_CFB, - 128, "ARIA-128-CFB128", 16, + 16 >> MBEDTLS_IV_SIZE_SHIFT, + 128 >> MBEDTLS_KEY_BITLEN_SHIFT, + MBEDTLS_MODE_CFB, + MBEDTLS_CIPHER_ARIA_128_CFB128, 0, - 16, - &aria_info + MBEDTLS_CIPHER_BASE_INDEX_ARIA }; static const mbedtls_cipher_info_t aria_192_cfb128_info = { - MBEDTLS_CIPHER_ARIA_192_CFB128, - MBEDTLS_MODE_CFB, - 192, "ARIA-192-CFB128", 16, + 16 >> MBEDTLS_IV_SIZE_SHIFT, + 192 >> MBEDTLS_KEY_BITLEN_SHIFT, + MBEDTLS_MODE_CFB, + MBEDTLS_CIPHER_ARIA_192_CFB128, 0, - 16, - &aria_info + MBEDTLS_CIPHER_BASE_INDEX_ARIA }; static const mbedtls_cipher_info_t aria_256_cfb128_info = { - MBEDTLS_CIPHER_ARIA_256_CFB128, - MBEDTLS_MODE_CFB, - 256, "ARIA-256-CFB128", 16, + 16 >> MBEDTLS_IV_SIZE_SHIFT, + 256 >> MBEDTLS_KEY_BITLEN_SHIFT, + MBEDTLS_MODE_CFB, + MBEDTLS_CIPHER_ARIA_256_CFB128, 0, - 16, - &aria_info + MBEDTLS_CIPHER_BASE_INDEX_ARIA }; #endif /* MBEDTLS_CIPHER_MODE_CFB */ #if defined(MBEDTLS_CIPHER_MODE_CTR) static const mbedtls_cipher_info_t aria_128_ctr_info = { - MBEDTLS_CIPHER_ARIA_128_CTR, - MBEDTLS_MODE_CTR, - 128, "ARIA-128-CTR", 16, + 16 >> MBEDTLS_IV_SIZE_SHIFT, + 128 >> MBEDTLS_KEY_BITLEN_SHIFT, + MBEDTLS_MODE_CTR, + MBEDTLS_CIPHER_ARIA_128_CTR, 0, - 16, - &aria_info + MBEDTLS_CIPHER_BASE_INDEX_ARIA }; static const mbedtls_cipher_info_t aria_192_ctr_info = { - MBEDTLS_CIPHER_ARIA_192_CTR, - MBEDTLS_MODE_CTR, - 192, "ARIA-192-CTR", 16, + 16 >> MBEDTLS_IV_SIZE_SHIFT, + 192 >> MBEDTLS_KEY_BITLEN_SHIFT, + MBEDTLS_MODE_CTR, + MBEDTLS_CIPHER_ARIA_192_CTR, 0, - 16, - &aria_info + MBEDTLS_CIPHER_BASE_INDEX_ARIA }; static const mbedtls_cipher_info_t aria_256_ctr_info = { - MBEDTLS_CIPHER_ARIA_256_CTR, - MBEDTLS_MODE_CTR, - 256, "ARIA-256-CTR", 16, + 16 >> MBEDTLS_IV_SIZE_SHIFT, + 256 >> MBEDTLS_KEY_BITLEN_SHIFT, + MBEDTLS_MODE_CTR, + MBEDTLS_CIPHER_ARIA_256_CTR, 0, - 16, - &aria_info + MBEDTLS_CIPHER_BASE_INDEX_ARIA }; #endif /* MBEDTLS_CIPHER_MODE_CTR */ @@ -1292,42 +1460,44 @@ static const mbedtls_cipher_base_t gcm_aria_info = { NULL, #endif gcm_aria_setkey_wrap, +#if !defined(MBEDTLS_BLOCK_CIPHER_NO_DECRYPT) gcm_aria_setkey_wrap, +#endif gcm_ctx_alloc, gcm_ctx_free, }; static const mbedtls_cipher_info_t aria_128_gcm_info = { - MBEDTLS_CIPHER_ARIA_128_GCM, - MBEDTLS_MODE_GCM, - 128, "ARIA-128-GCM", - 12, - MBEDTLS_CIPHER_VARIABLE_IV_LEN, 16, - &gcm_aria_info + 12 >> MBEDTLS_IV_SIZE_SHIFT, + 128 >> MBEDTLS_KEY_BITLEN_SHIFT, + MBEDTLS_MODE_GCM, + MBEDTLS_CIPHER_ARIA_128_GCM, + MBEDTLS_CIPHER_VARIABLE_IV_LEN, + MBEDTLS_CIPHER_BASE_INDEX_GCM_ARIA }; static const mbedtls_cipher_info_t aria_192_gcm_info = { - MBEDTLS_CIPHER_ARIA_192_GCM, - MBEDTLS_MODE_GCM, - 192, "ARIA-192-GCM", - 12, - MBEDTLS_CIPHER_VARIABLE_IV_LEN, 16, - &gcm_aria_info + 12 >> MBEDTLS_IV_SIZE_SHIFT, + 192 >> MBEDTLS_KEY_BITLEN_SHIFT, + MBEDTLS_MODE_GCM, + MBEDTLS_CIPHER_ARIA_192_GCM, + MBEDTLS_CIPHER_VARIABLE_IV_LEN, + MBEDTLS_CIPHER_BASE_INDEX_GCM_ARIA }; static const mbedtls_cipher_info_t aria_256_gcm_info = { - MBEDTLS_CIPHER_ARIA_256_GCM, - MBEDTLS_MODE_GCM, - 256, "ARIA-256-GCM", - 12, - MBEDTLS_CIPHER_VARIABLE_IV_LEN, 16, - &gcm_aria_info + 12 >> MBEDTLS_IV_SIZE_SHIFT, + 256 >> MBEDTLS_KEY_BITLEN_SHIFT, + MBEDTLS_MODE_GCM, + MBEDTLS_CIPHER_ARIA_256_GCM, + MBEDTLS_CIPHER_VARIABLE_IV_LEN, + MBEDTLS_CIPHER_BASE_INDEX_GCM_ARIA }; #endif /* MBEDTLS_GCM_C */ @@ -1361,42 +1531,77 @@ static const mbedtls_cipher_base_t ccm_aria_info = { NULL, #endif ccm_aria_setkey_wrap, +#if !defined(MBEDTLS_BLOCK_CIPHER_NO_DECRYPT) ccm_aria_setkey_wrap, +#endif ccm_ctx_alloc, ccm_ctx_free, }; static const mbedtls_cipher_info_t aria_128_ccm_info = { - MBEDTLS_CIPHER_ARIA_128_CCM, - MBEDTLS_MODE_CCM, - 128, "ARIA-128-CCM", - 12, - MBEDTLS_CIPHER_VARIABLE_IV_LEN, 16, - &ccm_aria_info + 12 >> MBEDTLS_IV_SIZE_SHIFT, + 128 >> MBEDTLS_KEY_BITLEN_SHIFT, + MBEDTLS_MODE_CCM, + MBEDTLS_CIPHER_ARIA_128_CCM, + MBEDTLS_CIPHER_VARIABLE_IV_LEN, + MBEDTLS_CIPHER_BASE_INDEX_CCM_ARIA }; static const mbedtls_cipher_info_t aria_192_ccm_info = { - MBEDTLS_CIPHER_ARIA_192_CCM, - MBEDTLS_MODE_CCM, - 192, "ARIA-192-CCM", - 12, - MBEDTLS_CIPHER_VARIABLE_IV_LEN, 16, - &ccm_aria_info + 12 >> MBEDTLS_IV_SIZE_SHIFT, + 192 >> MBEDTLS_KEY_BITLEN_SHIFT, + MBEDTLS_MODE_CCM, + MBEDTLS_CIPHER_ARIA_192_CCM, + MBEDTLS_CIPHER_VARIABLE_IV_LEN, + MBEDTLS_CIPHER_BASE_INDEX_CCM_ARIA }; static const mbedtls_cipher_info_t aria_256_ccm_info = { - MBEDTLS_CIPHER_ARIA_256_CCM, - MBEDTLS_MODE_CCM, - 256, "ARIA-256-CCM", - 12, + 16, + 12 >> MBEDTLS_IV_SIZE_SHIFT, + 256 >> MBEDTLS_KEY_BITLEN_SHIFT, + MBEDTLS_MODE_CCM, + MBEDTLS_CIPHER_ARIA_256_CCM, MBEDTLS_CIPHER_VARIABLE_IV_LEN, + MBEDTLS_CIPHER_BASE_INDEX_CCM_ARIA +}; + +static const mbedtls_cipher_info_t aria_128_ccm_star_no_tag_info = { + "ARIA-128-CCM*-NO-TAG", 16, - &ccm_aria_info + 12 >> MBEDTLS_IV_SIZE_SHIFT, + 128 >> MBEDTLS_KEY_BITLEN_SHIFT, + MBEDTLS_MODE_CCM_STAR_NO_TAG, + MBEDTLS_CIPHER_ARIA_128_CCM_STAR_NO_TAG, + MBEDTLS_CIPHER_VARIABLE_IV_LEN, + MBEDTLS_CIPHER_BASE_INDEX_CCM_ARIA +}; + +static const mbedtls_cipher_info_t aria_192_ccm_star_no_tag_info = { + "ARIA-192-CCM*-NO-TAG", + 16, + 12 >> MBEDTLS_IV_SIZE_SHIFT, + 192 >> MBEDTLS_KEY_BITLEN_SHIFT, + MBEDTLS_MODE_CCM_STAR_NO_TAG, + MBEDTLS_CIPHER_ARIA_192_CCM_STAR_NO_TAG, + MBEDTLS_CIPHER_VARIABLE_IV_LEN, + MBEDTLS_CIPHER_BASE_INDEX_CCM_ARIA +}; + +static const mbedtls_cipher_info_t aria_256_ccm_star_no_tag_info = { + "ARIA-256-CCM*-NO-TAG", + 16, + 12 >> MBEDTLS_IV_SIZE_SHIFT, + 256 >> MBEDTLS_KEY_BITLEN_SHIFT, + MBEDTLS_MODE_CCM_STAR_NO_TAG, + MBEDTLS_CIPHER_ARIA_256_CCM_STAR_NO_TAG, + MBEDTLS_CIPHER_VARIABLE_IV_LEN, + MBEDTLS_CIPHER_BASE_INDEX_CCM_ARIA }; #endif /* MBEDTLS_CCM_C */ @@ -1551,26 +1756,26 @@ static const mbedtls_cipher_base_t des_info = { }; static const mbedtls_cipher_info_t des_ecb_info = { - MBEDTLS_CIPHER_DES_ECB, - MBEDTLS_MODE_ECB, - MBEDTLS_KEY_LENGTH_DES, "DES-ECB", - 0, - 0, 8, - &des_info + 0 >> MBEDTLS_IV_SIZE_SHIFT, + MBEDTLS_KEY_LENGTH_DES >> MBEDTLS_KEY_BITLEN_SHIFT, + MBEDTLS_MODE_ECB, + MBEDTLS_CIPHER_DES_ECB, + 0, + MBEDTLS_CIPHER_BASE_INDEX_DES }; #if defined(MBEDTLS_CIPHER_MODE_CBC) static const mbedtls_cipher_info_t des_cbc_info = { - MBEDTLS_CIPHER_DES_CBC, - MBEDTLS_MODE_CBC, - MBEDTLS_KEY_LENGTH_DES, "DES-CBC", 8, + 8 >> MBEDTLS_IV_SIZE_SHIFT, + MBEDTLS_KEY_LENGTH_DES >> MBEDTLS_KEY_BITLEN_SHIFT, + MBEDTLS_MODE_CBC, + MBEDTLS_CIPHER_DES_CBC, 0, - 8, - &des_info + MBEDTLS_CIPHER_BASE_INDEX_DES }; #endif /* MBEDTLS_CIPHER_MODE_CBC */ @@ -1602,26 +1807,26 @@ static const mbedtls_cipher_base_t des_ede_info = { }; static const mbedtls_cipher_info_t des_ede_ecb_info = { - MBEDTLS_CIPHER_DES_EDE_ECB, - MBEDTLS_MODE_ECB, - MBEDTLS_KEY_LENGTH_DES_EDE, "DES-EDE-ECB", - 0, - 0, 8, - &des_ede_info + 0 >> MBEDTLS_IV_SIZE_SHIFT, + MBEDTLS_KEY_LENGTH_DES_EDE >> MBEDTLS_KEY_BITLEN_SHIFT, + MBEDTLS_MODE_ECB, + MBEDTLS_CIPHER_DES_EDE_ECB, + 0, + MBEDTLS_CIPHER_BASE_INDEX_DES_EDE }; #if defined(MBEDTLS_CIPHER_MODE_CBC) static const mbedtls_cipher_info_t des_ede_cbc_info = { - MBEDTLS_CIPHER_DES_EDE_CBC, - MBEDTLS_MODE_CBC, - MBEDTLS_KEY_LENGTH_DES_EDE, "DES-EDE-CBC", 8, + 8 >> MBEDTLS_IV_SIZE_SHIFT, + MBEDTLS_KEY_LENGTH_DES_EDE >> MBEDTLS_KEY_BITLEN_SHIFT, + MBEDTLS_MODE_CBC, + MBEDTLS_CIPHER_DES_EDE_CBC, 0, - 8, - &des_ede_info + MBEDTLS_CIPHER_BASE_INDEX_DES_EDE }; #endif /* MBEDTLS_CIPHER_MODE_CBC */ @@ -1653,251 +1858,29 @@ static const mbedtls_cipher_base_t des_ede3_info = { }; static const mbedtls_cipher_info_t des_ede3_ecb_info = { - MBEDTLS_CIPHER_DES_EDE3_ECB, - MBEDTLS_MODE_ECB, - MBEDTLS_KEY_LENGTH_DES_EDE3, "DES-EDE3-ECB", - 0, - 0, 8, - &des_ede3_info + 0 >> MBEDTLS_IV_SIZE_SHIFT, + MBEDTLS_KEY_LENGTH_DES_EDE3 >> MBEDTLS_KEY_BITLEN_SHIFT, + MBEDTLS_MODE_ECB, + MBEDTLS_CIPHER_DES_EDE3_ECB, + 0, + MBEDTLS_CIPHER_BASE_INDEX_DES_EDE3 }; #if defined(MBEDTLS_CIPHER_MODE_CBC) static const mbedtls_cipher_info_t des_ede3_cbc_info = { - MBEDTLS_CIPHER_DES_EDE3_CBC, - MBEDTLS_MODE_CBC, - MBEDTLS_KEY_LENGTH_DES_EDE3, "DES-EDE3-CBC", 8, + 8 >> MBEDTLS_IV_SIZE_SHIFT, + MBEDTLS_KEY_LENGTH_DES_EDE3 >> MBEDTLS_KEY_BITLEN_SHIFT, + MBEDTLS_MODE_CBC, + MBEDTLS_CIPHER_DES_EDE3_CBC, 0, - 8, - &des_ede3_info + MBEDTLS_CIPHER_BASE_INDEX_DES_EDE3 }; #endif /* MBEDTLS_CIPHER_MODE_CBC */ #endif /* MBEDTLS_DES_C */ -#if defined(MBEDTLS_BLOWFISH_C) - -static int blowfish_crypt_ecb_wrap(void *ctx, mbedtls_operation_t operation, - const unsigned char *input, unsigned char *output) -{ - return mbedtls_blowfish_crypt_ecb((mbedtls_blowfish_context *) ctx, operation, input, - output); -} - -#if defined(MBEDTLS_CIPHER_MODE_CBC) -static int blowfish_crypt_cbc_wrap(void *ctx, mbedtls_operation_t operation, - size_t length, unsigned char *iv, const unsigned char *input, - unsigned char *output) -{ - return mbedtls_blowfish_crypt_cbc((mbedtls_blowfish_context *) ctx, operation, length, iv, - input, output); -} -#endif /* MBEDTLS_CIPHER_MODE_CBC */ - -#if defined(MBEDTLS_CIPHER_MODE_CFB) -static int blowfish_crypt_cfb64_wrap(void *ctx, mbedtls_operation_t operation, - size_t length, size_t *iv_off, unsigned char *iv, - const unsigned char *input, unsigned char *output) -{ - return mbedtls_blowfish_crypt_cfb64((mbedtls_blowfish_context *) ctx, operation, length, - iv_off, iv, input, output); -} -#endif /* MBEDTLS_CIPHER_MODE_CFB */ - -#if defined(MBEDTLS_CIPHER_MODE_CTR) -static int blowfish_crypt_ctr_wrap(void *ctx, size_t length, size_t *nc_off, - unsigned char *nonce_counter, unsigned char *stream_block, - const unsigned char *input, unsigned char *output) -{ - return mbedtls_blowfish_crypt_ctr((mbedtls_blowfish_context *) ctx, length, nc_off, - nonce_counter, stream_block, input, output); -} -#endif /* MBEDTLS_CIPHER_MODE_CTR */ - -static int blowfish_setkey_wrap(void *ctx, const unsigned char *key, - unsigned int key_bitlen) -{ - return mbedtls_blowfish_setkey((mbedtls_blowfish_context *) ctx, key, key_bitlen); -} - -static void *blowfish_ctx_alloc(void) -{ - mbedtls_blowfish_context *ctx; - ctx = mbedtls_calloc(1, sizeof(mbedtls_blowfish_context)); - - if (ctx == NULL) { - return NULL; - } - - mbedtls_blowfish_init(ctx); - - return ctx; -} - -static void blowfish_ctx_free(void *ctx) -{ - mbedtls_blowfish_free((mbedtls_blowfish_context *) ctx); - mbedtls_free(ctx); -} - -static const mbedtls_cipher_base_t blowfish_info = { - MBEDTLS_CIPHER_ID_BLOWFISH, - blowfish_crypt_ecb_wrap, -#if defined(MBEDTLS_CIPHER_MODE_CBC) - blowfish_crypt_cbc_wrap, -#endif -#if defined(MBEDTLS_CIPHER_MODE_CFB) - blowfish_crypt_cfb64_wrap, -#endif -#if defined(MBEDTLS_CIPHER_MODE_OFB) - NULL, -#endif -#if defined(MBEDTLS_CIPHER_MODE_CTR) - blowfish_crypt_ctr_wrap, -#endif -#if defined(MBEDTLS_CIPHER_MODE_XTS) - NULL, -#endif -#if defined(MBEDTLS_CIPHER_MODE_STREAM) - NULL, -#endif - blowfish_setkey_wrap, - blowfish_setkey_wrap, - blowfish_ctx_alloc, - blowfish_ctx_free -}; - -static const mbedtls_cipher_info_t blowfish_ecb_info = { - MBEDTLS_CIPHER_BLOWFISH_ECB, - MBEDTLS_MODE_ECB, - 128, - "BLOWFISH-ECB", - 0, - MBEDTLS_CIPHER_VARIABLE_KEY_LEN, - 8, - &blowfish_info -}; - -#if defined(MBEDTLS_CIPHER_MODE_CBC) -static const mbedtls_cipher_info_t blowfish_cbc_info = { - MBEDTLS_CIPHER_BLOWFISH_CBC, - MBEDTLS_MODE_CBC, - 128, - "BLOWFISH-CBC", - 8, - MBEDTLS_CIPHER_VARIABLE_KEY_LEN, - 8, - &blowfish_info -}; -#endif /* MBEDTLS_CIPHER_MODE_CBC */ - -#if defined(MBEDTLS_CIPHER_MODE_CFB) -static const mbedtls_cipher_info_t blowfish_cfb64_info = { - MBEDTLS_CIPHER_BLOWFISH_CFB64, - MBEDTLS_MODE_CFB, - 128, - "BLOWFISH-CFB64", - 8, - MBEDTLS_CIPHER_VARIABLE_KEY_LEN, - 8, - &blowfish_info -}; -#endif /* MBEDTLS_CIPHER_MODE_CFB */ - -#if defined(MBEDTLS_CIPHER_MODE_CTR) -static const mbedtls_cipher_info_t blowfish_ctr_info = { - MBEDTLS_CIPHER_BLOWFISH_CTR, - MBEDTLS_MODE_CTR, - 128, - "BLOWFISH-CTR", - 8, - MBEDTLS_CIPHER_VARIABLE_KEY_LEN, - 8, - &blowfish_info -}; -#endif /* MBEDTLS_CIPHER_MODE_CTR */ -#endif /* MBEDTLS_BLOWFISH_C */ - -#if defined(MBEDTLS_ARC4_C) -static int arc4_crypt_stream_wrap(void *ctx, size_t length, - const unsigned char *input, - unsigned char *output) -{ - return mbedtls_arc4_crypt((mbedtls_arc4_context *) ctx, length, input, output); -} - -static int arc4_setkey_wrap(void *ctx, const unsigned char *key, - unsigned int key_bitlen) -{ - /* we get key_bitlen in bits, arc4 expects it in bytes */ - if (key_bitlen % 8 != 0) { - return MBEDTLS_ERR_CIPHER_BAD_INPUT_DATA; - } - - mbedtls_arc4_setup((mbedtls_arc4_context *) ctx, key, key_bitlen / 8); - return 0; -} - -static void *arc4_ctx_alloc(void) -{ - mbedtls_arc4_context *ctx; - ctx = mbedtls_calloc(1, sizeof(mbedtls_arc4_context)); - - if (ctx == NULL) { - return NULL; - } - - mbedtls_arc4_init(ctx); - - return ctx; -} - -static void arc4_ctx_free(void *ctx) -{ - mbedtls_arc4_free((mbedtls_arc4_context *) ctx); - mbedtls_free(ctx); -} - -static const mbedtls_cipher_base_t arc4_base_info = { - MBEDTLS_CIPHER_ID_ARC4, - NULL, -#if defined(MBEDTLS_CIPHER_MODE_CBC) - NULL, -#endif -#if defined(MBEDTLS_CIPHER_MODE_CFB) - NULL, -#endif -#if defined(MBEDTLS_CIPHER_MODE_OFB) - NULL, -#endif -#if defined(MBEDTLS_CIPHER_MODE_CTR) - NULL, -#endif -#if defined(MBEDTLS_CIPHER_MODE_XTS) - NULL, -#endif -#if defined(MBEDTLS_CIPHER_MODE_STREAM) - arc4_crypt_stream_wrap, -#endif - arc4_setkey_wrap, - arc4_setkey_wrap, - arc4_ctx_alloc, - arc4_ctx_free -}; - -static const mbedtls_cipher_info_t arc4_128_info = { - MBEDTLS_CIPHER_ARC4_128, - MBEDTLS_MODE_STREAM, - 128, - "ARC4-128", - 0, - 0, - 1, - &arc4_base_info -}; -#endif /* MBEDTLS_ARC4_C */ - #if defined(MBEDTLS_CHACHA20_C) static int chacha20_setkey_wrap(void *ctx, const unsigned char *key, @@ -1970,19 +1953,21 @@ static const mbedtls_cipher_base_t chacha20_base_info = { chacha20_stream_wrap, #endif chacha20_setkey_wrap, +#if !defined(MBEDTLS_BLOCK_CIPHER_NO_DECRYPT) chacha20_setkey_wrap, +#endif chacha20_ctx_alloc, chacha20_ctx_free }; static const mbedtls_cipher_info_t chacha20_info = { - MBEDTLS_CIPHER_CHACHA20, - MBEDTLS_MODE_STREAM, - 256, "CHACHA20", - 12, - 0, 1, - &chacha20_base_info + 12 >> MBEDTLS_IV_SIZE_SHIFT, + 256 >> MBEDTLS_KEY_BITLEN_SHIFT, + MBEDTLS_MODE_STREAM, + MBEDTLS_CIPHER_CHACHA20, + 0, + MBEDTLS_CIPHER_BASE_INDEX_CHACHA20_BASE }; #endif /* MBEDTLS_CHACHA20_C */ @@ -2045,19 +2030,21 @@ static const mbedtls_cipher_base_t chachapoly_base_info = { NULL, #endif chachapoly_setkey_wrap, +#if !defined(MBEDTLS_BLOCK_CIPHER_NO_DECRYPT) chachapoly_setkey_wrap, +#endif chachapoly_ctx_alloc, chachapoly_ctx_free }; static const mbedtls_cipher_info_t chachapoly_info = { - MBEDTLS_CIPHER_CHACHA20_POLY1305, - MBEDTLS_MODE_CHACHAPOLY, - 256, "CHACHA20-POLY1305", - 12, - 0, 1, - &chachapoly_base_info + 12 >> MBEDTLS_IV_SIZE_SHIFT, + 256 >> MBEDTLS_KEY_BITLEN_SHIFT, + MBEDTLS_MODE_CHACHAPOLY, + MBEDTLS_CIPHER_CHACHA20_POLY1305, + 0, + MBEDTLS_CIPHER_BASE_INDEX_CHACHAPOLY_BASE }; #endif /* MBEDTLS_CHACHAPOLY_C */ @@ -2113,20 +2100,22 @@ static const mbedtls_cipher_base_t null_base_info = { null_crypt_stream, #endif null_setkey, +#if !defined(MBEDTLS_BLOCK_CIPHER_NO_DECRYPT) null_setkey, +#endif null_ctx_alloc, null_ctx_free }; static const mbedtls_cipher_info_t null_cipher_info = { - MBEDTLS_CIPHER_NULL, - MBEDTLS_MODE_STREAM, - 0, "NULL", - 0, - 0, 1, - &null_base_info + 0 >> MBEDTLS_IV_SIZE_SHIFT, + 0 >> MBEDTLS_KEY_BITLEN_SHIFT, + MBEDTLS_MODE_STREAM, + MBEDTLS_CIPHER_NULL, + 0, + MBEDTLS_CIPHER_BASE_INDEX_NULL_BASE }; #endif /* defined(MBEDTLS_CIPHER_NULL_CIPHER) */ @@ -2190,130 +2179,140 @@ static const mbedtls_cipher_base_t kw_aes_info = { }; static const mbedtls_cipher_info_t aes_128_nist_kw_info = { - MBEDTLS_CIPHER_AES_128_KW, - MBEDTLS_MODE_KW, - 128, "AES-128-KW", - 0, - 0, 16, - &kw_aes_info + 0 >> MBEDTLS_IV_SIZE_SHIFT, + 128 >> MBEDTLS_KEY_BITLEN_SHIFT, + MBEDTLS_MODE_KW, + MBEDTLS_CIPHER_AES_128_KW, + 0, + MBEDTLS_CIPHER_BASE_INDEX_KW_AES }; +#if !defined(MBEDTLS_AES_ONLY_128_BIT_KEY_LENGTH) static const mbedtls_cipher_info_t aes_192_nist_kw_info = { - MBEDTLS_CIPHER_AES_192_KW, - MBEDTLS_MODE_KW, - 192, "AES-192-KW", - 0, - 0, 16, - &kw_aes_info + 0 >> MBEDTLS_IV_SIZE_SHIFT, + 192 >> MBEDTLS_KEY_BITLEN_SHIFT, + MBEDTLS_MODE_KW, + MBEDTLS_CIPHER_AES_192_KW, + 0, + MBEDTLS_CIPHER_BASE_INDEX_KW_AES }; static const mbedtls_cipher_info_t aes_256_nist_kw_info = { - MBEDTLS_CIPHER_AES_256_KW, - MBEDTLS_MODE_KW, - 256, "AES-256-KW", - 0, - 0, 16, - &kw_aes_info + 0 >> MBEDTLS_IV_SIZE_SHIFT, + 256 >> MBEDTLS_KEY_BITLEN_SHIFT, + MBEDTLS_MODE_KW, + MBEDTLS_CIPHER_AES_256_KW, + 0, + MBEDTLS_CIPHER_BASE_INDEX_KW_AES }; +#endif static const mbedtls_cipher_info_t aes_128_nist_kwp_info = { - MBEDTLS_CIPHER_AES_128_KWP, - MBEDTLS_MODE_KWP, - 128, "AES-128-KWP", - 0, - 0, 16, - &kw_aes_info + 0 >> MBEDTLS_IV_SIZE_SHIFT, + 128 >> MBEDTLS_KEY_BITLEN_SHIFT, + MBEDTLS_MODE_KWP, + MBEDTLS_CIPHER_AES_128_KWP, + 0, + MBEDTLS_CIPHER_BASE_INDEX_KW_AES }; +#if !defined(MBEDTLS_AES_ONLY_128_BIT_KEY_LENGTH) static const mbedtls_cipher_info_t aes_192_nist_kwp_info = { - MBEDTLS_CIPHER_AES_192_KWP, - MBEDTLS_MODE_KWP, - 192, "AES-192-KWP", - 0, - 0, 16, - &kw_aes_info + 0 >> MBEDTLS_IV_SIZE_SHIFT, + 192 >> MBEDTLS_KEY_BITLEN_SHIFT, + MBEDTLS_MODE_KWP, + MBEDTLS_CIPHER_AES_192_KWP, + 0, + MBEDTLS_CIPHER_BASE_INDEX_KW_AES }; static const mbedtls_cipher_info_t aes_256_nist_kwp_info = { - MBEDTLS_CIPHER_AES_256_KWP, - MBEDTLS_MODE_KWP, - 256, "AES-256-KWP", - 0, - 0, 16, - &kw_aes_info + 0 >> MBEDTLS_IV_SIZE_SHIFT, + 256 >> MBEDTLS_KEY_BITLEN_SHIFT, + MBEDTLS_MODE_KWP, + MBEDTLS_CIPHER_AES_256_KWP, + 0, + MBEDTLS_CIPHER_BASE_INDEX_KW_AES }; +#endif #endif /* MBEDTLS_NIST_KW_C */ const mbedtls_cipher_definition_t mbedtls_cipher_definitions[] = { #if defined(MBEDTLS_AES_C) { MBEDTLS_CIPHER_AES_128_ECB, &aes_128_ecb_info }, +#if !defined(MBEDTLS_AES_ONLY_128_BIT_KEY_LENGTH) { MBEDTLS_CIPHER_AES_192_ECB, &aes_192_ecb_info }, { MBEDTLS_CIPHER_AES_256_ECB, &aes_256_ecb_info }, +#endif #if defined(MBEDTLS_CIPHER_MODE_CBC) { MBEDTLS_CIPHER_AES_128_CBC, &aes_128_cbc_info }, +#if !defined(MBEDTLS_AES_ONLY_128_BIT_KEY_LENGTH) { MBEDTLS_CIPHER_AES_192_CBC, &aes_192_cbc_info }, { MBEDTLS_CIPHER_AES_256_CBC, &aes_256_cbc_info }, #endif +#endif #if defined(MBEDTLS_CIPHER_MODE_CFB) { MBEDTLS_CIPHER_AES_128_CFB128, &aes_128_cfb128_info }, +#if !defined(MBEDTLS_AES_ONLY_128_BIT_KEY_LENGTH) { MBEDTLS_CIPHER_AES_192_CFB128, &aes_192_cfb128_info }, { MBEDTLS_CIPHER_AES_256_CFB128, &aes_256_cfb128_info }, #endif +#endif #if defined(MBEDTLS_CIPHER_MODE_OFB) { MBEDTLS_CIPHER_AES_128_OFB, &aes_128_ofb_info }, +#if !defined(MBEDTLS_AES_ONLY_128_BIT_KEY_LENGTH) { MBEDTLS_CIPHER_AES_192_OFB, &aes_192_ofb_info }, { MBEDTLS_CIPHER_AES_256_OFB, &aes_256_ofb_info }, #endif +#endif #if defined(MBEDTLS_CIPHER_MODE_CTR) { MBEDTLS_CIPHER_AES_128_CTR, &aes_128_ctr_info }, +#if !defined(MBEDTLS_AES_ONLY_128_BIT_KEY_LENGTH) { MBEDTLS_CIPHER_AES_192_CTR, &aes_192_ctr_info }, { MBEDTLS_CIPHER_AES_256_CTR, &aes_256_ctr_info }, #endif +#endif #if defined(MBEDTLS_CIPHER_MODE_XTS) { MBEDTLS_CIPHER_AES_128_XTS, &aes_128_xts_info }, +#if !defined(MBEDTLS_AES_ONLY_128_BIT_KEY_LENGTH) { MBEDTLS_CIPHER_AES_256_XTS, &aes_256_xts_info }, #endif -#if defined(MBEDTLS_GCM_C) +#endif +#endif /* MBEDTLS_AES_C */ +#if defined(MBEDTLS_CIPHER_HAVE_GCM_AES_VIA_LEGACY_OR_USE_PSA) { MBEDTLS_CIPHER_AES_128_GCM, &aes_128_gcm_info }, +#if !defined(MBEDTLS_AES_ONLY_128_BIT_KEY_LENGTH) { MBEDTLS_CIPHER_AES_192_GCM, &aes_192_gcm_info }, { MBEDTLS_CIPHER_AES_256_GCM, &aes_256_gcm_info }, #endif -#if defined(MBEDTLS_CCM_C) +#endif +#if defined(MBEDTLS_CIPHER_HAVE_CCM_AES_VIA_LEGACY_OR_USE_PSA) { MBEDTLS_CIPHER_AES_128_CCM, &aes_128_ccm_info }, +#if !defined(MBEDTLS_AES_ONLY_128_BIT_KEY_LENGTH) { MBEDTLS_CIPHER_AES_192_CCM, &aes_192_ccm_info }, { MBEDTLS_CIPHER_AES_256_CCM, &aes_256_ccm_info }, #endif -#endif /* MBEDTLS_AES_C */ - -#if defined(MBEDTLS_ARC4_C) - { MBEDTLS_CIPHER_ARC4_128, &arc4_128_info }, -#endif - -#if defined(MBEDTLS_BLOWFISH_C) - { MBEDTLS_CIPHER_BLOWFISH_ECB, &blowfish_ecb_info }, -#if defined(MBEDTLS_CIPHER_MODE_CBC) - { MBEDTLS_CIPHER_BLOWFISH_CBC, &blowfish_cbc_info }, #endif -#if defined(MBEDTLS_CIPHER_MODE_CFB) - { MBEDTLS_CIPHER_BLOWFISH_CFB64, &blowfish_cfb64_info }, +#if defined(MBEDTLS_CIPHER_HAVE_CCM_STAR_NO_TAG_AES_VIA_LEGACY_OR_USE_PSA) + { MBEDTLS_CIPHER_AES_128_CCM_STAR_NO_TAG, &aes_128_ccm_star_no_tag_info }, +#if !defined(MBEDTLS_AES_ONLY_128_BIT_KEY_LENGTH) + { MBEDTLS_CIPHER_AES_192_CCM_STAR_NO_TAG, &aes_192_ccm_star_no_tag_info }, + { MBEDTLS_CIPHER_AES_256_CCM_STAR_NO_TAG, &aes_256_ccm_star_no_tag_info }, #endif -#if defined(MBEDTLS_CIPHER_MODE_CTR) - { MBEDTLS_CIPHER_BLOWFISH_CTR, &blowfish_ctr_info }, #endif -#endif /* MBEDTLS_BLOWFISH_C */ #if defined(MBEDTLS_CAMELLIA_C) { MBEDTLS_CIPHER_CAMELLIA_128_ECB, &camellia_128_ecb_info }, @@ -2343,6 +2342,9 @@ const mbedtls_cipher_definition_t mbedtls_cipher_definitions[] = { MBEDTLS_CIPHER_CAMELLIA_128_CCM, &camellia_128_ccm_info }, { MBEDTLS_CIPHER_CAMELLIA_192_CCM, &camellia_192_ccm_info }, { MBEDTLS_CIPHER_CAMELLIA_256_CCM, &camellia_256_ccm_info }, + { MBEDTLS_CIPHER_CAMELLIA_128_CCM_STAR_NO_TAG, &camellia_128_ccm_star_no_tag_info }, + { MBEDTLS_CIPHER_CAMELLIA_192_CCM_STAR_NO_TAG, &camellia_192_ccm_star_no_tag_info }, + { MBEDTLS_CIPHER_CAMELLIA_256_CCM_STAR_NO_TAG, &camellia_256_ccm_star_no_tag_info }, #endif #endif /* MBEDTLS_CAMELLIA_C */ @@ -2374,6 +2376,9 @@ const mbedtls_cipher_definition_t mbedtls_cipher_definitions[] = { MBEDTLS_CIPHER_ARIA_128_CCM, &aria_128_ccm_info }, { MBEDTLS_CIPHER_ARIA_192_CCM, &aria_192_ccm_info }, { MBEDTLS_CIPHER_ARIA_256_CCM, &aria_256_ccm_info }, + { MBEDTLS_CIPHER_ARIA_128_CCM_STAR_NO_TAG, &aria_128_ccm_star_no_tag_info }, + { MBEDTLS_CIPHER_ARIA_192_CCM_STAR_NO_TAG, &aria_192_ccm_star_no_tag_info }, + { MBEDTLS_CIPHER_ARIA_256_CCM_STAR_NO_TAG, &aria_256_ccm_star_no_tag_info }, #endif #endif /* MBEDTLS_ARIA_C */ @@ -2398,12 +2403,16 @@ const mbedtls_cipher_definition_t mbedtls_cipher_definitions[] = #if defined(MBEDTLS_NIST_KW_C) { MBEDTLS_CIPHER_AES_128_KW, &aes_128_nist_kw_info }, +#if !defined(MBEDTLS_AES_ONLY_128_BIT_KEY_LENGTH) { MBEDTLS_CIPHER_AES_192_KW, &aes_192_nist_kw_info }, { MBEDTLS_CIPHER_AES_256_KW, &aes_256_nist_kw_info }, +#endif { MBEDTLS_CIPHER_AES_128_KWP, &aes_128_nist_kwp_info }, +#if !defined(MBEDTLS_AES_ONLY_128_BIT_KEY_LENGTH) { MBEDTLS_CIPHER_AES_192_KWP, &aes_192_nist_kwp_info }, { MBEDTLS_CIPHER_AES_256_KWP, &aes_256_nist_kwp_info }, #endif +#endif #if defined(MBEDTLS_CIPHER_NULL_CIPHER) { MBEDTLS_CIPHER_NULL, &null_cipher_info }, @@ -2416,4 +2425,58 @@ const mbedtls_cipher_definition_t mbedtls_cipher_definitions[] = sizeof(mbedtls_cipher_definitions[0])) int mbedtls_cipher_supported[NUM_CIPHERS]; +const mbedtls_cipher_base_t *mbedtls_cipher_base_lookup_table[] = { +#if defined(MBEDTLS_AES_C) + [MBEDTLS_CIPHER_BASE_INDEX_AES] = &aes_info, +#endif +#if defined(MBEDTLS_ARIA_C) + [MBEDTLS_CIPHER_BASE_INDEX_ARIA] = &aria_info, +#endif +#if defined(MBEDTLS_CAMELLIA_C) + [MBEDTLS_CIPHER_BASE_INDEX_CAMELLIA] = &camellia_info, +#endif +#if defined(MBEDTLS_CIPHER_HAVE_CCM_AES_VIA_LEGACY_OR_USE_PSA) + [MBEDTLS_CIPHER_BASE_INDEX_CCM_AES] = &ccm_aes_info, +#endif +#if defined(MBEDTLS_CCM_C) && defined(MBEDTLS_ARIA_C) + [MBEDTLS_CIPHER_BASE_INDEX_CCM_ARIA] = &ccm_aria_info, +#endif +#if defined(MBEDTLS_CCM_C) && defined(MBEDTLS_CAMELLIA_C) + [MBEDTLS_CIPHER_BASE_INDEX_CCM_CAMELLIA] = &ccm_camellia_info, +#endif +#if defined(MBEDTLS_CHACHA20_C) + [MBEDTLS_CIPHER_BASE_INDEX_CHACHA20_BASE] = &chacha20_base_info, +#endif +#if defined(MBEDTLS_CHACHAPOLY_C) + [MBEDTLS_CIPHER_BASE_INDEX_CHACHAPOLY_BASE] = &chachapoly_base_info, +#endif +#if defined(MBEDTLS_DES_C) + [MBEDTLS_CIPHER_BASE_INDEX_DES_EDE3] = &des_ede3_info, +#endif +#if defined(MBEDTLS_DES_C) + [MBEDTLS_CIPHER_BASE_INDEX_DES_EDE] = &des_ede_info, +#endif +#if defined(MBEDTLS_DES_C) + [MBEDTLS_CIPHER_BASE_INDEX_DES] = &des_info, +#endif +#if defined(MBEDTLS_CIPHER_HAVE_GCM_AES_VIA_LEGACY_OR_USE_PSA) + [MBEDTLS_CIPHER_BASE_INDEX_GCM_AES] = &gcm_aes_info, +#endif +#if defined(MBEDTLS_GCM_C) && defined(MBEDTLS_ARIA_C) + [MBEDTLS_CIPHER_BASE_INDEX_GCM_ARIA] = &gcm_aria_info, +#endif +#if defined(MBEDTLS_GCM_C) && defined(MBEDTLS_CAMELLIA_C) + [MBEDTLS_CIPHER_BASE_INDEX_GCM_CAMELLIA] = &gcm_camellia_info, +#endif +#if defined(MBEDTLS_NIST_KW_C) + [MBEDTLS_CIPHER_BASE_INDEX_KW_AES] = &kw_aes_info, +#endif +#if defined(MBEDTLS_CIPHER_NULL_CIPHER) + [MBEDTLS_CIPHER_BASE_INDEX_NULL_BASE] = &null_base_info, +#endif +#if defined(MBEDTLS_CIPHER_MODE_XTS) && defined(MBEDTLS_AES_C) + [MBEDTLS_CIPHER_BASE_INDEX_XTS_AES] = &xts_aes_info +#endif +}; + #endif /* MBEDTLS_CIPHER_C */ diff --git a/vendor/mbedtls/include/mbedtls/cipher_internal.h b/vendor/mbedtls/library/cipher_wrap.h similarity index 66% rename from vendor/mbedtls/include/mbedtls/cipher_internal.h rename to vendor/mbedtls/library/cipher_wrap.h index c77bb8cc9f..f22915120d 100644 --- a/vendor/mbedtls/include/mbedtls/cipher_internal.h +++ b/vendor/mbedtls/library/cipher_wrap.h @@ -1,5 +1,5 @@ /** - * \file cipher_internal.h + * \file cipher_wrap.h * * \brief Cipher wrappers. * @@ -7,28 +7,12 @@ */ /* * Copyright The Mbed TLS Contributors - * SPDX-License-Identifier: Apache-2.0 - * - * Licensed under the Apache License, Version 2.0 (the "License"); you may - * not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT - * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. + * SPDX-License-Identifier: Apache-2.0 OR GPL-2.0-or-later */ #ifndef MBEDTLS_CIPHER_WRAP_H #define MBEDTLS_CIPHER_WRAP_H -#if !defined(MBEDTLS_CONFIG_FILE) -#include "mbedtls/config.h" -#else -#include MBEDTLS_CONFIG_FILE -#endif +#include "mbedtls/build_info.h" #include "mbedtls/cipher.h" @@ -40,6 +24,50 @@ extern "C" { #endif +/* Support for GCM either through Mbed TLS SW implementation or PSA */ +#if defined(MBEDTLS_GCM_C) || \ + (defined(MBEDTLS_USE_PSA_CRYPTO) && defined(PSA_WANT_ALG_GCM)) +#define MBEDTLS_CIPHER_HAVE_GCM_VIA_LEGACY_OR_USE_PSA +#endif + +#if (defined(MBEDTLS_GCM_C) && defined(MBEDTLS_AES_C)) || \ + (defined(MBEDTLS_USE_PSA_CRYPTO) && defined(PSA_WANT_ALG_GCM) && defined(PSA_WANT_KEY_TYPE_AES)) +#define MBEDTLS_CIPHER_HAVE_GCM_AES_VIA_LEGACY_OR_USE_PSA +#endif + +#if defined(MBEDTLS_CCM_C) || \ + (defined(MBEDTLS_USE_PSA_CRYPTO) && defined(PSA_WANT_ALG_CCM)) +#define MBEDTLS_CIPHER_HAVE_CCM_VIA_LEGACY_OR_USE_PSA +#endif + +#if (defined(MBEDTLS_CCM_C) && defined(MBEDTLS_AES_C)) || \ + (defined(MBEDTLS_USE_PSA_CRYPTO) && defined(PSA_WANT_ALG_CCM) && defined(PSA_WANT_KEY_TYPE_AES)) +#define MBEDTLS_CIPHER_HAVE_CCM_AES_VIA_LEGACY_OR_USE_PSA +#endif + +#if defined(MBEDTLS_CCM_C) || \ + (defined(MBEDTLS_USE_PSA_CRYPTO) && defined(PSA_WANT_ALG_CCM_STAR_NO_TAG)) +#define MBEDTLS_CIPHER_HAVE_CCM_STAR_NO_TAG_VIA_LEGACY_OR_USE_PSA +#endif + +#if (defined(MBEDTLS_CCM_C) && defined(MBEDTLS_AES_C)) || \ + (defined(MBEDTLS_USE_PSA_CRYPTO) && defined(PSA_WANT_ALG_CCM_STAR_NO_TAG) && \ + defined(PSA_WANT_KEY_TYPE_AES)) +#define MBEDTLS_CIPHER_HAVE_CCM_STAR_NO_TAG_AES_VIA_LEGACY_OR_USE_PSA +#endif + +#if defined(MBEDTLS_CHACHAPOLY_C) || \ + (defined(MBEDTLS_USE_PSA_CRYPTO) && defined(PSA_WANT_ALG_CHACHA20_POLY1305)) +#define MBEDTLS_CIPHER_HAVE_CHACHAPOLY_VIA_LEGACY_OR_USE_PSA +#endif + +#if defined(MBEDTLS_CIPHER_HAVE_GCM_VIA_LEGACY_OR_USE_PSA) || \ + defined(MBEDTLS_CIPHER_HAVE_CCM_VIA_LEGACY_OR_USE_PSA) || \ + defined(MBEDTLS_CIPHER_HAVE_CCM_STAR_NO_TAG_VIA_LEGACY_OR_USE_PSA) || \ + defined(MBEDTLS_CIPHER_HAVE_CHACHAPOLY_VIA_LEGACY_OR_USE_PSA) +#define MBEDTLS_CIPHER_HAVE_SOME_AEAD_VIA_LEGACY_OR_USE_PSA +#endif + /** * Base cipher information. The non-mode specific functions and values. */ @@ -97,9 +125,11 @@ struct mbedtls_cipher_base_t { int (*setkey_enc_func)(void *ctx, const unsigned char *key, unsigned int key_bitlen); +#if !defined(MBEDTLS_BLOCK_CIPHER_NO_DECRYPT) /** Set key for decryption purposes */ int (*setkey_dec_func)(void *ctx, const unsigned char *key, unsigned int key_bitlen); +#endif /** Allocate a new context */ void * (*ctx_alloc_func)(void); @@ -130,7 +160,7 @@ typedef enum { typedef struct { psa_algorithm_t alg; - psa_key_id_t slot; + mbedtls_svc_key_id_t slot; mbedtls_cipher_psa_key_ownership slot_state; } mbedtls_cipher_context_psa; #endif /* MBEDTLS_USE_PSA_CRYPTO */ @@ -139,6 +169,8 @@ extern const mbedtls_cipher_definition_t mbedtls_cipher_definitions[]; extern int mbedtls_cipher_supported[]; +extern const mbedtls_cipher_base_t *mbedtls_cipher_base_lookup_table[]; + #ifdef __cplusplus } #endif diff --git a/vendor/mbedtls/library/cmac.c b/vendor/mbedtls/library/cmac.c index 0c07de6f2f..eda10d0b3d 100644 --- a/vendor/mbedtls/library/cmac.c +++ b/vendor/mbedtls/library/cmac.c @@ -4,19 +4,7 @@ * \brief NIST SP800-38B compliant CMAC implementation for AES and 3DES * * Copyright The Mbed TLS Contributors - * SPDX-License-Identifier: Apache-2.0 - * - * Licensed under the Apache License, Version 2.0 (the "License"); you may - * not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT - * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. + * SPDX-License-Identifier: Apache-2.0 OR GPL-2.0-or-later */ /* @@ -46,6 +34,7 @@ #include "mbedtls/platform_util.h" #include "mbedtls/error.h" #include "mbedtls/platform.h" +#include "constant_time_internal.h" #include @@ -68,39 +57,33 @@ static int cmac_multiply_by_u(unsigned char *output, size_t blocksize) { const unsigned char R_128 = 0x87; - const unsigned char R_64 = 0x1B; - unsigned char R_n, mask; - unsigned char overflow = 0x00; + unsigned char R_n; + uint32_t overflow = 0x00; int i; if (blocksize == MBEDTLS_AES_BLOCK_SIZE) { R_n = R_128; - } else if (blocksize == MBEDTLS_DES3_BLOCK_SIZE) { + } +#if defined(MBEDTLS_DES_C) + else if (blocksize == MBEDTLS_DES3_BLOCK_SIZE) { + const unsigned char R_64 = 0x1B; R_n = R_64; - } else { + } +#endif + else { return MBEDTLS_ERR_CIPHER_BAD_INPUT_DATA; } - for (i = (int) blocksize - 1; i >= 0; i--) { - output[i] = input[i] << 1 | overflow; - overflow = input[i] >> 7; + for (i = (int) blocksize - 4; i >= 0; i -= 4) { + uint32_t i32 = MBEDTLS_GET_UINT32_BE(&input[i], 0); + uint32_t new_overflow = i32 >> 31; + i32 = (i32 << 1) | overflow; + MBEDTLS_PUT_UINT32_BE(i32, &output[i], 0); + overflow = new_overflow; } - /* mask = ( input[0] >> 7 ) ? 0xff : 0x00 - * using bit operations to avoid branches */ - - /* MSVC has a warning about unary minus on unsigned, but this is - * well-defined and precisely what we want to do here */ -#if defined(_MSC_VER) -#pragma warning( push ) -#pragma warning( disable : 4146 ) -#endif - mask = -(input[0] >> 7); -#if defined(_MSC_VER) -#pragma warning( pop ) -#endif - - output[blocksize - 1] ^= R_n & mask; + R_n = (unsigned char) mbedtls_ct_uint_if_else_0(mbedtls_ct_bool(input[0] >> 7), R_n); + output[blocksize - 1] ^= R_n; return 0; } @@ -114,12 +97,12 @@ static int cmac_generate_subkeys(mbedtls_cipher_context_t *ctx, unsigned char *K1, unsigned char *K2) { int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED; - unsigned char L[MBEDTLS_CIPHER_BLKSIZE_MAX]; + unsigned char L[MBEDTLS_CMAC_MAX_BLOCK_SIZE]; size_t olen, block_size; mbedtls_platform_zeroize(L, sizeof(L)); - block_size = ctx->cipher_info->block_size; + block_size = mbedtls_cipher_info_get_block_size(ctx->cipher_info); /* Calculate Ek(0) */ if ((ret = mbedtls_cipher_update(ctx, L, block_size, L, &olen)) != 0) { @@ -145,16 +128,6 @@ static int cmac_generate_subkeys(mbedtls_cipher_context_t *ctx, #endif /* !defined(MBEDTLS_CMAC_ALT) || defined(MBEDTLS_SELF_TEST) */ #if !defined(MBEDTLS_CMAC_ALT) -static void cmac_xor_block(unsigned char *output, const unsigned char *input1, - const unsigned char *input2, - const size_t block_size) -{ - size_t idx; - - for (idx = 0; idx < block_size; idx++) { - output[idx] = input1[idx] ^ input2[idx]; - } -} /* * Create padded last block from (partial) last block. @@ -162,7 +135,7 @@ static void cmac_xor_block(unsigned char *output, const unsigned char *input1, * We can't use the padding option from the cipher layer, as it only works for * CBC and we use ECB mode, and anyway we need to XOR K1 or K2 in addition. */ -static void cmac_pad(unsigned char padded_block[MBEDTLS_CIPHER_BLKSIZE_MAX], +static void cmac_pad(unsigned char padded_block[MBEDTLS_CMAC_MAX_BLOCK_SIZE], size_t padded_block_len, const unsigned char *last_block, size_t last_block_len) @@ -196,7 +169,7 @@ int mbedtls_cipher_cmac_starts(mbedtls_cipher_context_t *ctx, return retval; } - type = ctx->cipher_info->type; + type = mbedtls_cipher_info_get_type(ctx->cipher_info); switch (type) { case MBEDTLS_CIPHER_AES_128_ECB: @@ -236,9 +209,13 @@ int mbedtls_cipher_cmac_update(mbedtls_cipher_context_t *ctx, } cmac_ctx = ctx->cmac_ctx; - block_size = ctx->cipher_info->block_size; + block_size = mbedtls_cipher_info_get_block_size(ctx->cipher_info); state = ctx->cmac_ctx->state; + /* Without the MBEDTLS_ASSUME below, gcc -O3 will generate a warning of the form + * error: writing 16 bytes into a region of size 0 [-Werror=stringop-overflow=] */ + MBEDTLS_ASSUME(block_size <= MBEDTLS_CMAC_MAX_BLOCK_SIZE); + /* Is there data still to process from the last call, that's greater in * size than a block? */ if (cmac_ctx->unprocessed_len > 0 && @@ -247,7 +224,7 @@ int mbedtls_cipher_cmac_update(mbedtls_cipher_context_t *ctx, input, block_size - cmac_ctx->unprocessed_len); - cmac_xor_block(state, cmac_ctx->unprocessed_block, state, block_size); + mbedtls_xor_no_simd(state, cmac_ctx->unprocessed_block, state, block_size); if ((ret = mbedtls_cipher_update(ctx, state, block_size, state, &olen)) != 0) { @@ -265,7 +242,7 @@ int mbedtls_cipher_cmac_update(mbedtls_cipher_context_t *ctx, /* Iterate across the input data in block sized chunks, excluding any * final partial or complete block */ for (j = 1; j < n; j++) { - cmac_xor_block(state, input, state, block_size); + mbedtls_xor_no_simd(state, input, state, block_size); if ((ret = mbedtls_cipher_update(ctx, state, block_size, state, &olen)) != 0) { @@ -293,9 +270,9 @@ int mbedtls_cipher_cmac_finish(mbedtls_cipher_context_t *ctx, { mbedtls_cmac_context_t *cmac_ctx; unsigned char *state, *last_block; - unsigned char K1[MBEDTLS_CIPHER_BLKSIZE_MAX]; - unsigned char K2[MBEDTLS_CIPHER_BLKSIZE_MAX]; - unsigned char M_last[MBEDTLS_CIPHER_BLKSIZE_MAX]; + unsigned char K1[MBEDTLS_CMAC_MAX_BLOCK_SIZE]; + unsigned char K2[MBEDTLS_CMAC_MAX_BLOCK_SIZE]; + unsigned char M_last[MBEDTLS_CMAC_MAX_BLOCK_SIZE]; int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED; size_t olen, block_size; @@ -305,7 +282,8 @@ int mbedtls_cipher_cmac_finish(mbedtls_cipher_context_t *ctx, } cmac_ctx = ctx->cmac_ctx; - block_size = ctx->cipher_info->block_size; + block_size = mbedtls_cipher_info_get_block_size(ctx->cipher_info); + MBEDTLS_ASSUME(block_size <= MBEDTLS_CMAC_MAX_BLOCK_SIZE); // silence GCC warning state = cmac_ctx->state; mbedtls_platform_zeroize(K1, sizeof(K1)); @@ -317,14 +295,14 @@ int mbedtls_cipher_cmac_finish(mbedtls_cipher_context_t *ctx, /* Calculate last block */ if (cmac_ctx->unprocessed_len < block_size) { cmac_pad(M_last, block_size, last_block, cmac_ctx->unprocessed_len); - cmac_xor_block(M_last, M_last, K2, block_size); + mbedtls_xor(M_last, M_last, K2, block_size); } else { /* Last block is complete block */ - cmac_xor_block(M_last, last_block, K1, block_size); + mbedtls_xor(M_last, last_block, K1, block_size); } - cmac_xor_block(state, M_last, state, block_size); + mbedtls_xor(state, M_last, state, block_size); if ((ret = mbedtls_cipher_update(ctx, state, block_size, state, &olen)) != 0) { goto exit; @@ -342,7 +320,7 @@ int mbedtls_cipher_cmac_finish(mbedtls_cipher_context_t *ctx, mbedtls_platform_zeroize(cmac_ctx->unprocessed_block, sizeof(cmac_ctx->unprocessed_block)); - mbedtls_platform_zeroize(state, MBEDTLS_CIPHER_BLKSIZE_MAX); + mbedtls_platform_zeroize(state, MBEDTLS_CMAC_MAX_BLOCK_SIZE); return ret; } @@ -531,6 +509,7 @@ static const unsigned char aes_128_expected_result[NB_CMAC_TESTS_PER_KEY][MBEDTL }; /* CMAC-AES192 Test Data */ +#if !defined(MBEDTLS_AES_ONLY_128_BIT_KEY_LENGTH) static const unsigned char aes_192_key[24] = { 0x8e, 0x73, 0xb0, 0xf7, 0xda, 0x0e, 0x64, 0x52, 0xc8, 0x10, 0xf3, 0x2b, 0x80, 0x90, 0x79, 0xe5, @@ -571,8 +550,10 @@ static const unsigned char aes_192_expected_result[NB_CMAC_TESTS_PER_KEY][MBEDTL 0x4d, 0x77, 0x58, 0x96, 0x59, 0xf3, 0x9a, 0x11 } }; +#endif /* !MBEDTLS_AES_ONLY_128_BIT_KEY_LENGTH */ /* CMAC-AES256 Test Data */ +#if !defined(MBEDTLS_AES_ONLY_128_BIT_KEY_LENGTH) static const unsigned char aes_256_key[32] = { 0x60, 0x3d, 0xeb, 0x10, 0x15, 0xca, 0x71, 0xbe, 0x2b, 0x73, 0xae, 0xf0, 0x85, 0x7d, 0x77, 0x81, @@ -614,6 +595,7 @@ static const unsigned char aes_256_expected_result[NB_CMAC_TESTS_PER_KEY][MBEDTL 0x69, 0x6a, 0x2c, 0x05, 0x6c, 0x31, 0x54, 0x10 } }; +#endif /* !MBEDTLS_AES_ONLY_128_BIT_KEY_LENGTH */ #endif /* MBEDTLS_AES_C */ #if defined(MBEDTLS_DES_C) @@ -756,8 +738,8 @@ static int cmac_test_subkeys(int verbose, int i, ret = 0; mbedtls_cipher_context_t ctx; const mbedtls_cipher_info_t *cipher_info; - unsigned char K1[MBEDTLS_CIPHER_BLKSIZE_MAX]; - unsigned char K2[MBEDTLS_CIPHER_BLKSIZE_MAX]; + unsigned char K1[MBEDTLS_CMAC_MAX_BLOCK_SIZE]; + unsigned char K2[MBEDTLS_CMAC_MAX_BLOCK_SIZE]; cipher_info = mbedtls_cipher_info_from_type(cipher_type); if (cipher_info == NULL) { @@ -851,7 +833,7 @@ static int cmac_test_wth_cipher(int verbose, { const mbedtls_cipher_info_t *cipher_info; int i, ret = 0; - unsigned char output[MBEDTLS_CIPHER_BLKSIZE_MAX]; + unsigned char output[MBEDTLS_CMAC_MAX_BLOCK_SIZE]; cipher_info = mbedtls_cipher_info_from_type(cipher_type); if (cipher_info == NULL) { @@ -961,6 +943,7 @@ int mbedtls_cmac_self_test(int verbose) } /* AES-192 */ +#if !defined(MBEDTLS_AES_ONLY_128_BIT_KEY_LENGTH) if ((ret = cmac_test_subkeys(verbose, "AES 192", aes_192_key, @@ -984,8 +967,10 @@ int mbedtls_cmac_self_test(int verbose) NB_CMAC_TESTS_PER_KEY)) != 0) { return ret; } +#endif /* !MBEDTLS_AES_ONLY_128_BIT_KEY_LENGTH */ /* AES-256 */ +#if !defined(MBEDTLS_AES_ONLY_128_BIT_KEY_LENGTH) if ((ret = cmac_test_subkeys(verbose, "AES 256", aes_256_key, @@ -1009,6 +994,7 @@ int mbedtls_cmac_self_test(int verbose) NB_CMAC_TESTS_PER_KEY)) != 0) { return ret; } +#endif /* !MBEDTLS_AES_ONLY_128_BIT_KEY_LENGTH */ #endif /* MBEDTLS_AES_C */ #if defined(MBEDTLS_DES_C) diff --git a/vendor/mbedtls/library/common.h b/vendor/mbedtls/library/common.h index e162aa3cff..3936ffdfe1 100644 --- a/vendor/mbedtls/library/common.h +++ b/vendor/mbedtls/library/common.h @@ -5,38 +5,26 @@ */ /* * Copyright The Mbed TLS Contributors - * SPDX-License-Identifier: Apache-2.0 - * - * Licensed under the Apache License, Version 2.0 (the "License"); you may - * not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT - * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. + * SPDX-License-Identifier: Apache-2.0 OR GPL-2.0-or-later */ #ifndef MBEDTLS_LIBRARY_COMMON_H #define MBEDTLS_LIBRARY_COMMON_H -#if defined(MBEDTLS_CONFIG_FILE) -#include MBEDTLS_CONFIG_FILE -#else -#include "mbedtls/config.h" -#endif +#include "mbedtls/build_info.h" +#include "alignment.h" #include #include #include +#include -/* Define `inline` on some non-C99-compliant compilers. */ -#if (defined(__ARMCC_VERSION) || defined(_MSC_VER)) && \ - !defined(inline) && !defined(__cplusplus) -#define inline __inline +#if defined(__ARM_NEON) +#include +#define MBEDTLS_HAVE_NEON_INTRINSICS +#elif defined(MBEDTLS_PLATFORM_IS_WINDOWS_ON_ARM64) +#include +#define MBEDTLS_HAVE_NEON_INTRINSICS #endif /** Helper to define a function as static except when building invasive tests. @@ -60,6 +48,78 @@ #define MBEDTLS_STATIC_TESTABLE static #endif +#if defined(MBEDTLS_TEST_HOOKS) +extern void (*mbedtls_test_hook_test_fail)(const char *test, int line, const char *file); +#define MBEDTLS_TEST_HOOK_TEST_ASSERT(TEST) \ + do { \ + if ((!(TEST)) && ((*mbedtls_test_hook_test_fail) != NULL)) \ + { \ + (*mbedtls_test_hook_test_fail)( #TEST, __LINE__, __FILE__); \ + } \ + } while (0) +#else +#define MBEDTLS_TEST_HOOK_TEST_ASSERT(TEST) +#endif /* defined(MBEDTLS_TEST_HOOKS) */ + +/** \def ARRAY_LENGTH + * Return the number of elements of a static or stack array. + * + * \param array A value of array (not pointer) type. + * + * \return The number of elements of the array. + */ +/* A correct implementation of ARRAY_LENGTH, but which silently gives + * a nonsensical result if called with a pointer rather than an array. */ +#define ARRAY_LENGTH_UNSAFE(array) \ + (sizeof(array) / sizeof(*(array))) + +#if defined(__GNUC__) +/* Test if arg and &(arg)[0] have the same type. This is true if arg is + * an array but not if it's a pointer. */ +#define IS_ARRAY_NOT_POINTER(arg) \ + (!__builtin_types_compatible_p(__typeof__(arg), \ + __typeof__(&(arg)[0]))) +/* A compile-time constant with the value 0. If `const_expr` is not a + * compile-time constant with a nonzero value, cause a compile-time error. */ +#define STATIC_ASSERT_EXPR(const_expr) \ + (0 && sizeof(struct { unsigned int STATIC_ASSERT : 1 - 2 * !(const_expr); })) + +/* Return the scalar value `value` (possibly promoted). This is a compile-time + * constant if `value` is. `condition` must be a compile-time constant. + * If `condition` is false, arrange to cause a compile-time error. */ +#define STATIC_ASSERT_THEN_RETURN(condition, value) \ + (STATIC_ASSERT_EXPR(condition) ? 0 : (value)) + +#define ARRAY_LENGTH(array) \ + (STATIC_ASSERT_THEN_RETURN(IS_ARRAY_NOT_POINTER(array), \ + ARRAY_LENGTH_UNSAFE(array))) + +#else +/* If we aren't sure the compiler supports our non-standard tricks, + * fall back to the unsafe implementation. */ +#define ARRAY_LENGTH(array) ARRAY_LENGTH_UNSAFE(array) +#endif +/** Allow library to access its structs' private members. + * + * Although structs defined in header files are publicly available, + * their members are private and should not be accessed by the user. + */ +#define MBEDTLS_ALLOW_PRIVATE_ACCESS + +/** + * \brief Securely zeroize a buffer then free it. + * + * Similar to making consecutive calls to + * \c mbedtls_platform_zeroize() and \c mbedtls_free(), but has + * code size savings, and potential for optimisation in the future. + * + * Guaranteed to be a no-op if \p buf is \c NULL and \p len is 0. + * + * \param buf Buffer to be zeroized then freed. + * \param len Length of the buffer in bytes + */ +void mbedtls_zeroize_and_free(void *buf, size_t len); + /** Return an offset into a buffer. * * This is just the addition of an offset to a pointer, except that this @@ -98,254 +158,197 @@ static inline const unsigned char *mbedtls_buffer_offset_const( return p == NULL ? NULL : p + n; } -/** Byte Reading Macros - * - * Given a multi-byte integer \p x, MBEDTLS_BYTE_n retrieves the n-th - * byte from x, where byte 0 is the least significant byte. - */ -#define MBEDTLS_BYTE_0(x) ((uint8_t) ((x) & 0xff)) -#define MBEDTLS_BYTE_1(x) ((uint8_t) (((x) >> 8) & 0xff)) -#define MBEDTLS_BYTE_2(x) ((uint8_t) (((x) >> 16) & 0xff)) -#define MBEDTLS_BYTE_3(x) ((uint8_t) (((x) >> 24) & 0xff)) -#define MBEDTLS_BYTE_4(x) ((uint8_t) (((x) >> 32) & 0xff)) -#define MBEDTLS_BYTE_5(x) ((uint8_t) (((x) >> 40) & 0xff)) -#define MBEDTLS_BYTE_6(x) ((uint8_t) (((x) >> 48) & 0xff)) -#define MBEDTLS_BYTE_7(x) ((uint8_t) (((x) >> 56) & 0xff)) - -/** - * Get the unsigned 32 bits integer corresponding to four bytes in - * big-endian order (MSB first). - * - * \param data Base address of the memory to get the four bytes from. - * \param offset Offset from \p base of the first and most significant - * byte of the four bytes to build the 32 bits unsigned - * integer from. - */ -#ifndef MBEDTLS_GET_UINT32_BE -#define MBEDTLS_GET_UINT32_BE(data, offset) \ - ( \ - ((uint32_t) (data)[(offset)] << 24) \ - | ((uint32_t) (data)[(offset) + 1] << 16) \ - | ((uint32_t) (data)[(offset) + 2] << 8) \ - | ((uint32_t) (data)[(offset) + 3]) \ - ) +/* Always inline mbedtls_xor() for similar reasons as mbedtls_xor_no_simd(). */ +#if defined(__IAR_SYSTEMS_ICC__) +#pragma inline = forced +#elif defined(__GNUC__) +__attribute__((always_inline)) #endif - /** - * Put in memory a 32 bits unsigned integer in big-endian order. + * Perform a fast block XOR operation, such that + * r[i] = a[i] ^ b[i] where 0 <= i < n + * + * \param r Pointer to result (buffer of at least \p n bytes). \p r + * may be equal to either \p a or \p b, but behaviour when + * it overlaps in other ways is undefined. + * \param a Pointer to input (buffer of at least \p n bytes) + * \param b Pointer to input (buffer of at least \p n bytes) + * \param n Number of bytes to process. * - * \param n 32 bits unsigned integer to put in memory. - * \param data Base address of the memory where to put the 32 - * bits unsigned integer in. - * \param offset Offset from \p base where to put the most significant - * byte of the 32 bits unsigned integer \p n. + * \note Depending on the situation, it may be faster to use either mbedtls_xor() or + * mbedtls_xor_no_simd() (these are functionally equivalent). + * If the result is used immediately after the xor operation in non-SIMD code (e.g, in + * AES-CBC), there may be additional latency to transfer the data from SIMD to scalar + * registers, and in this case, mbedtls_xor_no_simd() may be faster. In other cases where + * the result is not used immediately (e.g., in AES-CTR), mbedtls_xor() may be faster. + * For targets without SIMD support, they will behave the same. */ -#ifndef MBEDTLS_PUT_UINT32_BE -#define MBEDTLS_PUT_UINT32_BE(n, data, offset) \ - { \ - (data)[(offset)] = MBEDTLS_BYTE_3(n); \ - (data)[(offset) + 1] = MBEDTLS_BYTE_2(n); \ - (data)[(offset) + 2] = MBEDTLS_BYTE_1(n); \ - (data)[(offset) + 3] = MBEDTLS_BYTE_0(n); \ +static inline void mbedtls_xor(unsigned char *r, + const unsigned char *a, + const unsigned char *b, + size_t n) +{ + size_t i = 0; +#if defined(MBEDTLS_EFFICIENT_UNALIGNED_ACCESS) +#if defined(MBEDTLS_HAVE_NEON_INTRINSICS) && \ + (!(defined(MBEDTLS_COMPILER_IS_GCC) && MBEDTLS_GCC_VERSION < 70300)) + /* Old GCC versions generate a warning here, so disable the NEON path for these compilers */ + for (; (i + 16) <= n; i += 16) { + uint8x16_t v1 = vld1q_u8(a + i); + uint8x16_t v2 = vld1q_u8(b + i); + uint8x16_t x = veorq_u8(v1, v2); + vst1q_u8(r + i, x); + } +#if defined(__IAR_SYSTEMS_ICC__) + /* This if statement helps some compilers (e.g., IAR) optimise out the byte-by-byte tail case + * where n is a constant multiple of 16. + * For other compilers (e.g. recent gcc and clang) it makes no difference if n is a compile-time + * constant, and is a very small perf regression if n is not a compile-time constant. */ + if (n % 16 == 0) { + return; } #endif - -/** - * Get the unsigned 32 bits integer corresponding to four bytes in - * little-endian order (LSB first). - * - * \param data Base address of the memory to get the four bytes from. - * \param offset Offset from \p base of the first and least significant - * byte of the four bytes to build the 32 bits unsigned - * integer from. - */ -#ifndef MBEDTLS_GET_UINT32_LE -#define MBEDTLS_GET_UINT32_LE(data, offset) \ - ( \ - ((uint32_t) (data)[(offset)]) \ - | ((uint32_t) (data)[(offset) + 1] << 8) \ - | ((uint32_t) (data)[(offset) + 2] << 16) \ - | ((uint32_t) (data)[(offset) + 3] << 24) \ - ) +#elif defined(MBEDTLS_ARCH_IS_X64) || defined(MBEDTLS_ARCH_IS_ARM64) + /* This codepath probably only makes sense on architectures with 64-bit registers */ + for (; (i + 8) <= n; i += 8) { + uint64_t x = mbedtls_get_unaligned_uint64(a + i) ^ mbedtls_get_unaligned_uint64(b + i); + mbedtls_put_unaligned_uint64(r + i, x); + } +#if defined(__IAR_SYSTEMS_ICC__) + if (n % 8 == 0) { + return; + } #endif - -/** - * Put in memory a 32 bits unsigned integer in little-endian order. - * - * \param n 32 bits unsigned integer to put in memory. - * \param data Base address of the memory where to put the 32 - * bits unsigned integer in. - * \param offset Offset from \p base where to put the least significant - * byte of the 32 bits unsigned integer \p n. - */ -#ifndef MBEDTLS_PUT_UINT32_LE -#define MBEDTLS_PUT_UINT32_LE(n, data, offset) \ - { \ - (data)[(offset)] = MBEDTLS_BYTE_0(n); \ - (data)[(offset) + 1] = MBEDTLS_BYTE_1(n); \ - (data)[(offset) + 2] = MBEDTLS_BYTE_2(n); \ - (data)[(offset) + 3] = MBEDTLS_BYTE_3(n); \ +#else + for (; (i + 4) <= n; i += 4) { + uint32_t x = mbedtls_get_unaligned_uint32(a + i) ^ mbedtls_get_unaligned_uint32(b + i); + mbedtls_put_unaligned_uint32(r + i, x); + } +#if defined(__IAR_SYSTEMS_ICC__) + if (n % 4 == 0) { + return; } #endif - -/** - * Get the unsigned 16 bits integer corresponding to two bytes in - * little-endian order (LSB first). - * - * \param data Base address of the memory to get the two bytes from. - * \param offset Offset from \p base of the first and least significant - * byte of the two bytes to build the 16 bits unsigned - * integer from. - */ -#ifndef MBEDTLS_GET_UINT16_LE -#define MBEDTLS_GET_UINT16_LE(data, offset) \ - ( \ - ((uint16_t) (data)[(offset)]) \ - | ((uint16_t) (data)[(offset) + 1] << 8) \ - ) #endif - -/** - * Put in memory a 16 bits unsigned integer in little-endian order. - * - * \param n 16 bits unsigned integer to put in memory. - * \param data Base address of the memory where to put the 16 - * bits unsigned integer in. - * \param offset Offset from \p base where to put the least significant - * byte of the 16 bits unsigned integer \p n. - */ -#ifndef MBEDTLS_PUT_UINT16_LE -#define MBEDTLS_PUT_UINT16_LE(n, data, offset) \ - { \ - (data)[(offset)] = MBEDTLS_BYTE_0(n); \ - (data)[(offset) + 1] = MBEDTLS_BYTE_1(n); \ - } #endif + for (; i < n; i++) { + r[i] = a[i] ^ b[i]; + } +} -/** - * Get the unsigned 16 bits integer corresponding to two bytes in - * big-endian order (MSB first). - * - * \param data Base address of the memory to get the two bytes from. - * \param offset Offset from \p base of the first and most significant - * byte of the two bytes to build the 16 bits unsigned - * integer from. - */ -#ifndef MBEDTLS_GET_UINT16_BE -#define MBEDTLS_GET_UINT16_BE(data, offset) \ - ( \ - ((uint16_t) (data)[(offset)] << 8) \ - | ((uint16_t) (data)[(offset) + 1]) \ - ) +/* Always inline mbedtls_xor_no_simd() as we see significant perf regressions when it does not get + * inlined (e.g., observed about 3x perf difference in gcm_mult_largetable with gcc 7 - 12) */ +#if defined(__IAR_SYSTEMS_ICC__) +#pragma inline = forced +#elif defined(__GNUC__) +__attribute__((always_inline)) #endif - /** - * Put in memory a 16 bits unsigned integer in big-endian order. + * Perform a fast block XOR operation, such that + * r[i] = a[i] ^ b[i] where 0 <= i < n + * + * In some situations, this can perform better than mbedtls_xor() (e.g., it's about 5% + * better in AES-CBC). + * + * \param r Pointer to result (buffer of at least \p n bytes). \p r + * may be equal to either \p a or \p b, but behaviour when + * it overlaps in other ways is undefined. + * \param a Pointer to input (buffer of at least \p n bytes) + * \param b Pointer to input (buffer of at least \p n bytes) + * \param n Number of bytes to process. * - * \param n 16 bits unsigned integer to put in memory. - * \param data Base address of the memory where to put the 16 - * bits unsigned integer in. - * \param offset Offset from \p base where to put the most significant - * byte of the 16 bits unsigned integer \p n. + * \note Depending on the situation, it may be faster to use either mbedtls_xor() or + * mbedtls_xor_no_simd() (these are functionally equivalent). + * If the result is used immediately after the xor operation in non-SIMD code (e.g, in + * AES-CBC), there may be additional latency to transfer the data from SIMD to scalar + * registers, and in this case, mbedtls_xor_no_simd() may be faster. In other cases where + * the result is not used immediately (e.g., in AES-CTR), mbedtls_xor() may be faster. + * For targets without SIMD support, they will behave the same. */ -#ifndef MBEDTLS_PUT_UINT16_BE -#define MBEDTLS_PUT_UINT16_BE(n, data, offset) \ - { \ - (data)[(offset)] = MBEDTLS_BYTE_1(n); \ - (data)[(offset) + 1] = MBEDTLS_BYTE_0(n); \ +static inline void mbedtls_xor_no_simd(unsigned char *r, + const unsigned char *a, + const unsigned char *b, + size_t n) +{ + size_t i = 0; +#if defined(MBEDTLS_EFFICIENT_UNALIGNED_ACCESS) +#if defined(MBEDTLS_ARCH_IS_X64) || defined(MBEDTLS_ARCH_IS_ARM64) + /* This codepath probably only makes sense on architectures with 64-bit registers */ + for (; (i + 8) <= n; i += 8) { + uint64_t x = mbedtls_get_unaligned_uint64(a + i) ^ mbedtls_get_unaligned_uint64(b + i); + mbedtls_put_unaligned_uint64(r + i, x); + } +#if defined(__IAR_SYSTEMS_ICC__) + /* This if statement helps some compilers (e.g., IAR) optimise out the byte-by-byte tail case + * where n is a constant multiple of 8. + * For other compilers (e.g. recent gcc and clang) it makes no difference if n is a compile-time + * constant, and is a very small perf regression if n is not a compile-time constant. */ + if (n % 8 == 0) { + return; } #endif - -/** - * Get the unsigned 64 bits integer corresponding to eight bytes in - * big-endian order (MSB first). - * - * \param data Base address of the memory to get the eight bytes from. - * \param offset Offset from \p base of the first and most significant - * byte of the eight bytes to build the 64 bits unsigned - * integer from. - */ -#ifndef MBEDTLS_GET_UINT64_BE -#define MBEDTLS_GET_UINT64_BE(data, offset) \ - ( \ - ((uint64_t) (data)[(offset)] << 56) \ - | ((uint64_t) (data)[(offset) + 1] << 48) \ - | ((uint64_t) (data)[(offset) + 2] << 40) \ - | ((uint64_t) (data)[(offset) + 3] << 32) \ - | ((uint64_t) (data)[(offset) + 4] << 24) \ - | ((uint64_t) (data)[(offset) + 5] << 16) \ - | ((uint64_t) (data)[(offset) + 6] << 8) \ - | ((uint64_t) (data)[(offset) + 7]) \ - ) +#else + for (; (i + 4) <= n; i += 4) { + uint32_t x = mbedtls_get_unaligned_uint32(a + i) ^ mbedtls_get_unaligned_uint32(b + i); + mbedtls_put_unaligned_uint32(r + i, x); + } +#if defined(__IAR_SYSTEMS_ICC__) + if (n % 4 == 0) { + return; + } +#endif +#endif #endif + for (; i < n; i++) { + r[i] = a[i] ^ b[i]; + } +} -/** - * Put in memory a 64 bits unsigned integer in big-endian order. - * - * \param n 64 bits unsigned integer to put in memory. - * \param data Base address of the memory where to put the 64 - * bits unsigned integer in. - * \param offset Offset from \p base where to put the most significant - * byte of the 64 bits unsigned integer \p n. +/* Fix MSVC C99 compatible issue + * MSVC support __func__ from visual studio 2015( 1900 ) + * Use MSVC predefine macro to avoid name check fail. */ -#ifndef MBEDTLS_PUT_UINT64_BE -#define MBEDTLS_PUT_UINT64_BE(n, data, offset) \ - { \ - (data)[(offset)] = MBEDTLS_BYTE_7(n); \ - (data)[(offset) + 1] = MBEDTLS_BYTE_6(n); \ - (data)[(offset) + 2] = MBEDTLS_BYTE_5(n); \ - (data)[(offset) + 3] = MBEDTLS_BYTE_4(n); \ - (data)[(offset) + 4] = MBEDTLS_BYTE_3(n); \ - (data)[(offset) + 5] = MBEDTLS_BYTE_2(n); \ - (data)[(offset) + 6] = MBEDTLS_BYTE_1(n); \ - (data)[(offset) + 7] = MBEDTLS_BYTE_0(n); \ - } +#if (defined(_MSC_VER) && (_MSC_VER <= 1900)) +#define /*no-check-names*/ __func__ __FUNCTION__ #endif -/** - * Get the unsigned 64 bits integer corresponding to eight bytes in - * little-endian order (LSB first). - * - * \param data Base address of the memory to get the eight bytes from. - * \param offset Offset from \p base of the first and least significant - * byte of the eight bytes to build the 64 bits unsigned - * integer from. - */ -#ifndef MBEDTLS_GET_UINT64_LE -#define MBEDTLS_GET_UINT64_LE(data, offset) \ - ( \ - ((uint64_t) (data)[(offset) + 7] << 56) \ - | ((uint64_t) (data)[(offset) + 6] << 48) \ - | ((uint64_t) (data)[(offset) + 5] << 40) \ - | ((uint64_t) (data)[(offset) + 4] << 32) \ - | ((uint64_t) (data)[(offset) + 3] << 24) \ - | ((uint64_t) (data)[(offset) + 2] << 16) \ - | ((uint64_t) (data)[(offset) + 1] << 8) \ - | ((uint64_t) (data)[(offset)]) \ - ) +/* Define `asm` for compilers which don't define it. */ +/* *INDENT-OFF* */ +#ifndef asm +#if defined(__IAR_SYSTEMS_ICC__) +#define asm __asm +#else +#define asm __asm__ +#endif #endif +/* *INDENT-ON* */ -/** - * Put in memory a 64 bits unsigned integer in little-endian order. +/* + * Define the constraint used for read-only pointer operands to aarch64 asm. + * + * This is normally the usual "r", but for aarch64_32 (aka ILP32, + * as found in watchos), "p" is required to avoid warnings from clang. + * + * Note that clang does not recognise '+p' or '=p', and armclang + * does not recognise 'p' at all. Therefore, to update a pointer from + * aarch64 assembly, it is necessary to use something like: * - * \param n 64 bits unsigned integer to put in memory. - * \param data Base address of the memory where to put the 64 - * bits unsigned integer in. - * \param offset Offset from \p base where to put the least significant - * byte of the 64 bits unsigned integer \p n. + * uintptr_t uptr = (uintptr_t) ptr; + * asm( "ldr x4, [%x0], #8" ... : "+r" (uptr) : : ) + * ptr = (void*) uptr; + * + * Note that the "x" in "%x0" is neccessary; writing "%0" will cause warnings. */ -#ifndef MBEDTLS_PUT_UINT64_LE -#define MBEDTLS_PUT_UINT64_LE(n, data, offset) \ - { \ - (data)[(offset)] = MBEDTLS_BYTE_0(n); \ - (data)[(offset) + 1] = MBEDTLS_BYTE_1(n); \ - (data)[(offset) + 2] = MBEDTLS_BYTE_2(n); \ - (data)[(offset) + 3] = MBEDTLS_BYTE_3(n); \ - (data)[(offset) + 4] = MBEDTLS_BYTE_4(n); \ - (data)[(offset) + 5] = MBEDTLS_BYTE_5(n); \ - (data)[(offset) + 6] = MBEDTLS_BYTE_6(n); \ - (data)[(offset) + 7] = MBEDTLS_BYTE_7(n); \ - } +#if defined(__aarch64__) && defined(MBEDTLS_HAVE_ASM) +#if UINTPTR_MAX == 0xfffffffful +/* ILP32: Specify the pointer operand slightly differently, as per #7787. */ +#define MBEDTLS_ASM_AARCH64_PTR_CONSTRAINT "p" +#elif UINTPTR_MAX == 0xfffffffffffffffful +/* Normal case (64-bit pointers): use "r" as the constraint for pointer operands to asm */ +#define MBEDTLS_ASM_AARCH64_PTR_CONSTRAINT "r" +#else +#error "Unrecognised pointer size for aarch64" +#endif #endif /* Always provide a static assert macro, so it can be used unconditionally. @@ -362,4 +365,71 @@ static inline const unsigned char *mbedtls_buffer_offset_const( #define MBEDTLS_STATIC_ASSERT(expr, msg) #endif +#if defined(__has_builtin) +#define MBEDTLS_HAS_BUILTIN(x) __has_builtin(x) +#else +#define MBEDTLS_HAS_BUILTIN(x) 0 +#endif + +/* Define compiler branch hints */ +#if MBEDTLS_HAS_BUILTIN(__builtin_expect) +#define MBEDTLS_LIKELY(x) __builtin_expect(!!(x), 1) +#define MBEDTLS_UNLIKELY(x) __builtin_expect(!!(x), 0) +#else +#define MBEDTLS_LIKELY(x) x +#define MBEDTLS_UNLIKELY(x) x +#endif + +/* MBEDTLS_ASSUME may be used to provide additional information to the compiler + * which can result in smaller code-size. */ +#if MBEDTLS_HAS_BUILTIN(__builtin_assume) +/* clang provides __builtin_assume */ +#define MBEDTLS_ASSUME(x) __builtin_assume(x) +#elif MBEDTLS_HAS_BUILTIN(__builtin_unreachable) +/* gcc and IAR can use __builtin_unreachable */ +#define MBEDTLS_ASSUME(x) do { if (!(x)) __builtin_unreachable(); } while (0) +#elif defined(_MSC_VER) +/* Supported by MSVC since VS 2005 */ +#define MBEDTLS_ASSUME(x) __assume(x) +#else +#define MBEDTLS_ASSUME(x) do { } while (0) +#endif + +/* For gcc -Os, override with -O2 for a given function. + * + * This will not affect behaviour for other optimisation settings, e.g. -O0. + */ +#if defined(MBEDTLS_COMPILER_IS_GCC) && defined(__OPTIMIZE_SIZE__) +#define MBEDTLS_OPTIMIZE_FOR_PERFORMANCE __attribute__((optimize("-O2"))) +#else +#define MBEDTLS_OPTIMIZE_FOR_PERFORMANCE +#endif + +/* Suppress compiler warnings for unused functions and variables. */ +#if !defined(MBEDTLS_MAYBE_UNUSED) && defined(__has_attribute) +# if __has_attribute(unused) +# define MBEDTLS_MAYBE_UNUSED __attribute__((unused)) +# endif +#endif +#if !defined(MBEDTLS_MAYBE_UNUSED) && defined(__GNUC__) +# define MBEDTLS_MAYBE_UNUSED __attribute__((unused)) +#endif +#if !defined(MBEDTLS_MAYBE_UNUSED) && defined(__IAR_SYSTEMS_ICC__) && defined(__VER__) +/* IAR does support __attribute__((unused)), but only if the -e flag (extended language support) + * is given; the pragma always works. + * Unfortunately the pragma affects the rest of the file where it is used, but this is harmless. + * Check for version 5.2 or later - this pragma may be supported by earlier versions, but I wasn't + * able to find documentation). + */ +# if (__VER__ >= 5020000) +# define MBEDTLS_MAYBE_UNUSED _Pragma("diag_suppress=Pe177") +# endif +#endif +#if !defined(MBEDTLS_MAYBE_UNUSED) && defined(_MSC_VER) +# define MBEDTLS_MAYBE_UNUSED __pragma(warning(suppress:4189)) +#endif +#if !defined(MBEDTLS_MAYBE_UNUSED) +# define MBEDTLS_MAYBE_UNUSED +#endif + #endif /* MBEDTLS_LIBRARY_COMMON_H */ diff --git a/vendor/mbedtls/library/constant_time.c b/vendor/mbedtls/library/constant_time.c index 2307ed53b5..d212ddfd81 100644 --- a/vendor/mbedtls/library/constant_time.c +++ b/vendor/mbedtls/library/constant_time.c @@ -2,19 +2,7 @@ * Constant-time functions * * Copyright The Mbed TLS Contributors - * SPDX-License-Identifier: Apache-2.0 - * - * Licensed under the Apache License, Version 2.0 (the "License"); you may - * not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT - * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. + * SPDX-License-Identifier: Apache-2.0 OR GPL-2.0-or-later */ /* @@ -22,40 +10,85 @@ * might be translated to branches by some compilers on some platforms. */ +#include +#include + #include "common.h" #include "constant_time_internal.h" #include "mbedtls/constant_time.h" #include "mbedtls/error.h" #include "mbedtls/platform_util.h" -#if defined(MBEDTLS_BIGNUM_C) -#include "mbedtls/bignum.h" -#endif +#include -#if defined(MBEDTLS_SSL_TLS_C) -#include "mbedtls/ssl_internal.h" +#if !defined(MBEDTLS_CT_ASM) +/* + * Define an object with the value zero, such that the compiler cannot prove that it + * has the value zero (because it is volatile, it "may be modified in ways unknown to + * the implementation"). + */ +volatile mbedtls_ct_uint_t mbedtls_ct_zero = 0; #endif -#if defined(MBEDTLS_RSA_C) -#include "mbedtls/rsa.h" -#endif +/* + * Define MBEDTLS_EFFICIENT_UNALIGNED_VOLATILE_ACCESS where assembly is present to + * perform fast unaligned access to volatile data. + * + * This is needed because mbedtls_get_unaligned_uintXX etc don't support volatile + * memory accesses. + * + * Some of these definitions could be moved into alignment.h but for now they are + * only used here. + */ +#if defined(MBEDTLS_EFFICIENT_UNALIGNED_ACCESS) && \ + ((defined(MBEDTLS_CT_ARM_ASM) && (UINTPTR_MAX == 0xfffffffful)) || \ + defined(MBEDTLS_CT_AARCH64_ASM)) +/* We check pointer sizes to avoid issues with them not matching register size requirements */ +#define MBEDTLS_EFFICIENT_UNALIGNED_VOLATILE_ACCESS -#if defined(MBEDTLS_BASE64_C) -#include "constant_time_invasive.h" +static inline uint32_t mbedtls_get_unaligned_volatile_uint32(volatile const unsigned char *p) +{ + /* This is UB, even where it's safe: + * return *((volatile uint32_t*)p); + * so instead the same thing is expressed in assembly below. + */ + uint32_t r; +#if defined(MBEDTLS_CT_ARM_ASM) + asm volatile ("ldr %0, [%1]" : "=r" (r) : "r" (p) :); +#elif defined(MBEDTLS_CT_AARCH64_ASM) + asm volatile ("ldr %w0, [%1]" : "=r" (r) : MBEDTLS_ASM_AARCH64_PTR_CONSTRAINT(p) :); +#else +#error "No assembly defined for mbedtls_get_unaligned_volatile_uint32" #endif - -#include + return r; +} +#endif /* defined(MBEDTLS_EFFICIENT_UNALIGNED_ACCESS) && + (defined(MBEDTLS_CT_ARM_ASM) || defined(MBEDTLS_CT_AARCH64_ASM)) */ int mbedtls_ct_memcmp(const void *a, const void *b, size_t n) { - size_t i; + size_t i = 0; + /* + * `A` and `B` are cast to volatile to ensure that the compiler + * generates code that always fully reads both buffers. + * Otherwise it could generate a test to exit early if `diff` has all + * bits set early in the loop. + */ volatile const unsigned char *A = (volatile const unsigned char *) a; volatile const unsigned char *B = (volatile const unsigned char *) b; - volatile unsigned char diff = 0; + uint32_t diff = 0; + +#if defined(MBEDTLS_EFFICIENT_UNALIGNED_VOLATILE_ACCESS) + for (; (i + 4) <= n; i += 4) { + uint32_t x = mbedtls_get_unaligned_volatile_uint32(A + i); + uint32_t y = mbedtls_get_unaligned_volatile_uint32(B + i); + diff |= x ^ y; + } +#endif - for (i = 0; i < n; i++) { + for (; i < n; i++) { /* Read volatile data in order before computing diff. * This avoids IAR compiler warning: * 'the order of volatile accesses is undefined ..' */ @@ -63,330 +96,119 @@ int mbedtls_ct_memcmp(const void *a, diff |= x ^ y; } - return (int) diff; -} - -unsigned mbedtls_ct_uint_mask(unsigned value) -{ - /* MSVC has a warning about unary minus on unsigned, but this is - * well-defined and precisely what we want to do here */ -#if defined(_MSC_VER) -#pragma warning( push ) -#pragma warning( disable : 4146 ) -#endif - return -((value | -value) >> (sizeof(value) * 8 - 1)); -#if defined(_MSC_VER) -#pragma warning( pop ) -#endif -} - -#if defined(MBEDTLS_SSL_SOME_MODES_USE_MAC) || defined(MBEDTLS_SSL_SOME_SUITES_USE_TLS_CBC) || \ - defined(MBEDTLS_NIST_KW_C) || defined(MBEDTLS_CIPHER_MODE_CBC) - -size_t mbedtls_ct_size_mask(size_t value) -{ - /* MSVC has a warning about unary minus on unsigned integer types, - * but this is well-defined and precisely what we want to do here. */ -#if defined(_MSC_VER) -#pragma warning( push ) -#pragma warning( disable : 4146 ) -#endif - return -((value | -value) >> (sizeof(value) * 8 - 1)); -#if defined(_MSC_VER) -#pragma warning( pop ) -#endif -} - -#endif /* defined(MBEDTLS_SSL_SOME_MODES_USE_MAC) || defined(MBEDTLS_SSL_SOME_SUITES_USE_TLS_CBC) || - defined(MBEDTLS_NIST_KW_C) || defined(MBEDTLS_CIPHER_MODE_CBC) */ - -#if defined(MBEDTLS_BIGNUM_C) - -mbedtls_mpi_uint mbedtls_ct_mpi_uint_mask(mbedtls_mpi_uint value) -{ - /* MSVC has a warning about unary minus on unsigned, but this is - * well-defined and precisely what we want to do here */ -#if defined(_MSC_VER) -#pragma warning( push ) -#pragma warning( disable : 4146 ) -#endif - return -((value | -value) >> (sizeof(value) * 8 - 1)); -#if defined(_MSC_VER) -#pragma warning( pop ) -#endif -} - -#endif /* MBEDTLS_BIGNUM_C */ - -#if defined(MBEDTLS_SSL_SOME_SUITES_USE_TLS_CBC) || defined(MBEDTLS_NIST_KW_C) || \ - defined(MBEDTLS_CIPHER_MODE_CBC) - -/** Constant-flow mask generation for "less than" comparison: - * - if \p x < \p y, return all-bits 1, that is (size_t) -1 - * - otherwise, return all bits 0, that is 0 - * - * This function can be used to write constant-time code by replacing branches - * with bit operations using masks. - * - * \param x The first value to analyze. - * \param y The second value to analyze. - * - * \return All-bits-one if \p x is less than \p y, otherwise zero. - */ -static size_t mbedtls_ct_size_mask_lt(size_t x, - size_t y) -{ - /* This has the most significant bit set if and only if x < y */ - const size_t sub = x - y; - - /* sub1 = (x < y) ? 1 : 0 */ - const size_t sub1 = sub >> (sizeof(sub) * 8 - 1); - - /* mask = (x < y) ? 0xff... : 0x00... */ - const size_t mask = mbedtls_ct_size_mask(sub1); - - return mask; -} - -size_t mbedtls_ct_size_mask_ge(size_t x, - size_t y) -{ - return ~mbedtls_ct_size_mask_lt(x, y); -} - -#endif /* defined(MBEDTLS_SSL_SOME_SUITES_USE_TLS_CBC) || defined(MBEDTLS_NIST_KW_C) || - defined(MBEDTLS_CIPHER_MODE_CBC) */ - -#if defined(MBEDTLS_BASE64_C) - -/* Return 0xff if low <= c <= high, 0 otherwise. - * - * Constant flow with respect to c. - */ -MBEDTLS_STATIC_TESTABLE -unsigned char mbedtls_ct_uchar_mask_of_range(unsigned char low, - unsigned char high, - unsigned char c) -{ - /* low_mask is: 0 if low <= c, 0x...ff if low > c */ - unsigned low_mask = ((unsigned) c - low) >> 8; - /* high_mask is: 0 if c <= high, 0x...ff if c > high */ - unsigned high_mask = ((unsigned) high - c) >> 8; - return ~(low_mask | high_mask) & 0xff; -} - -#endif /* MBEDTLS_BASE64_C */ - -unsigned mbedtls_ct_size_bool_eq(size_t x, - size_t y) -{ - /* diff = 0 if x == y, non-zero otherwise */ - const size_t diff = x ^ y; - - /* MSVC has a warning about unary minus on unsigned integer types, - * but this is well-defined and precisely what we want to do here. */ -#if defined(_MSC_VER) -#pragma warning( push ) -#pragma warning( disable : 4146 ) -#endif - - /* diff_msb's most significant bit is equal to x != y */ - const size_t diff_msb = (diff | (size_t) -diff); - -#if defined(_MSC_VER) -#pragma warning( pop ) -#endif - - /* diff1 = (x != y) ? 1 : 0 */ - const unsigned diff1 = diff_msb >> (sizeof(diff_msb) * 8 - 1); - - return 1 ^ diff1; -} - -#if defined(MBEDTLS_PKCS1_V15) && defined(MBEDTLS_RSA_C) && !defined(MBEDTLS_RSA_ALT) - -/** Constant-flow "greater than" comparison: - * return x > y - * - * This is equivalent to \p x > \p y, but is likely to be compiled - * to code using bitwise operation rather than a branch. - * - * \param x The first value to analyze. - * \param y The second value to analyze. - * - * \return 1 if \p x greater than \p y, otherwise 0. - */ -static unsigned mbedtls_ct_size_gt(size_t x, - size_t y) -{ - /* Return the sign bit (1 for negative) of (y - x). */ - return (y - x) >> (sizeof(size_t) * 8 - 1); -} - -#endif /* MBEDTLS_PKCS1_V15 && MBEDTLS_RSA_C && ! MBEDTLS_RSA_ALT */ - -#if defined(MBEDTLS_BIGNUM_C) - -unsigned mbedtls_ct_mpi_uint_lt(const mbedtls_mpi_uint x, - const mbedtls_mpi_uint y) -{ - mbedtls_mpi_uint ret; - mbedtls_mpi_uint cond; - /* - * Check if the most significant bits (MSB) of the operands are different. - */ - cond = (x ^ y); - /* - * If the MSB are the same then the difference x-y will be negative (and - * have its MSB set to 1 during conversion to unsigned) if and only if x> (sizeof(mbedtls_mpi_uint) * 8 - 1); - - return (unsigned) ret; -} - -#endif /* MBEDTLS_BIGNUM_C */ - -unsigned mbedtls_ct_uint_if(unsigned condition, - unsigned if1, - unsigned if0) -{ - unsigned mask = mbedtls_ct_uint_mask(condition); - return (mask & if1) | (~mask & if0); + return (int) ((diff & 0xffff) | (diff >> 16)); +#endif } -#if defined(MBEDTLS_BIGNUM_C) +#if defined(MBEDTLS_NIST_KW_C) -void mbedtls_ct_mpi_uint_cond_assign(size_t n, - mbedtls_mpi_uint *dest, - const mbedtls_mpi_uint *src, - unsigned char condition) +int mbedtls_ct_memcmp_partial(const void *a, + const void *b, + size_t n, + size_t skip_head, + size_t skip_tail) { - size_t i; + unsigned int diff = 0; - /* MSVC has a warning about unary minus on unsigned integer types, - * but this is well-defined and precisely what we want to do here. */ -#if defined(_MSC_VER) -#pragma warning( push ) -#pragma warning( disable : 4146 ) -#endif - - /* all-bits 1 if condition is 1, all-bits 0 if condition is 0 */ - const mbedtls_mpi_uint mask = -condition; + volatile const unsigned char *A = (volatile const unsigned char *) a; + volatile const unsigned char *B = (volatile const unsigned char *) b; -#if defined(_MSC_VER) -#pragma warning( pop ) -#endif + size_t valid_end = n - skip_tail; - for (i = 0; i < n; i++) { - dest[i] = (src[i] & mask) | (dest[i] & ~mask); + for (size_t i = 0; i < n; i++) { + unsigned char x = A[i], y = B[i]; + unsigned int d = x ^ y; + mbedtls_ct_condition_t valid = mbedtls_ct_bool_and(mbedtls_ct_uint_ge(i, skip_head), + mbedtls_ct_uint_lt(i, valid_end)); + diff |= mbedtls_ct_uint_if_else_0(valid, d); } -} - -#endif /* MBEDTLS_BIGNUM_C */ -#if defined(MBEDTLS_BASE64_C) - -unsigned char mbedtls_ct_base64_enc_char(unsigned char value) -{ - unsigned char digit = 0; - /* For each range of values, if value is in that range, mask digit with - * the corresponding value. Since value can only be in a single range, - * only at most one masking will change digit. */ - digit |= mbedtls_ct_uchar_mask_of_range(0, 25, value) & ('A' + value); - digit |= mbedtls_ct_uchar_mask_of_range(26, 51, value) & ('a' + value - 26); - digit |= mbedtls_ct_uchar_mask_of_range(52, 61, value) & ('0' + value - 52); - digit |= mbedtls_ct_uchar_mask_of_range(62, 62, value) & '+'; - digit |= mbedtls_ct_uchar_mask_of_range(63, 63, value) & '/'; - return digit; -} - -signed char mbedtls_ct_base64_dec_value(unsigned char c) -{ - unsigned char val = 0; - /* For each range of digits, if c is in that range, mask val with - * the corresponding value. Since c can only be in a single range, - * only at most one masking will change val. Set val to one plus - * the desired value so that it stays 0 if c is in none of the ranges. */ - val |= mbedtls_ct_uchar_mask_of_range('A', 'Z', c) & (c - 'A' + 0 + 1); - val |= mbedtls_ct_uchar_mask_of_range('a', 'z', c) & (c - 'a' + 26 + 1); - val |= mbedtls_ct_uchar_mask_of_range('0', '9', c) & (c - '0' + 52 + 1); - val |= mbedtls_ct_uchar_mask_of_range('+', '+', c) & (c - '+' + 62 + 1); - val |= mbedtls_ct_uchar_mask_of_range('/', '/', c) & (c - '/' + 63 + 1); - /* At this point, val is 0 if c is an invalid digit and v+1 if c is - * a digit with the value v. */ - return val - 1; + /* Since we go byte-by-byte, the only bits set will be in the bottom 8 bits, so the + * cast from uint to int is safe. */ + return (int) diff; } -#endif /* MBEDTLS_BASE64_C */ +#endif #if defined(MBEDTLS_PKCS1_V15) && defined(MBEDTLS_RSA_C) && !defined(MBEDTLS_RSA_ALT) -/** Shift some data towards the left inside a buffer. - * - * `mbedtls_ct_mem_move_to_left(start, total, offset)` is functionally - * equivalent to - * ``` - * memmove(start, start + offset, total - offset); - * memset(start + offset, 0, total - offset); - * ``` - * but it strives to use a memory access pattern (and thus total timing) - * that does not depend on \p offset. This timing independence comes at - * the expense of performance. - * - * \param start Pointer to the start of the buffer. - * \param total Total size of the buffer. - * \param offset Offset from which to copy \p total - \p offset bytes. - */ -static void mbedtls_ct_mem_move_to_left(void *start, - size_t total, - size_t offset) +void mbedtls_ct_memmove_left(void *start, size_t total, size_t offset) { volatile unsigned char *buf = start; - size_t i, n; - if (total == 0) { - return; - } - for (i = 0; i < total; i++) { - unsigned no_op = mbedtls_ct_size_gt(total - offset, i); + for (size_t i = 0; i < total; i++) { + mbedtls_ct_condition_t no_op = mbedtls_ct_uint_gt(total - offset, i); /* The first `total - offset` passes are a no-op. The last * `offset` passes shift the data one byte to the left and * zero out the last byte. */ - for (n = 0; n < total - 1; n++) { + for (size_t n = 0; n < total - 1; n++) { unsigned char current = buf[n]; - unsigned char next = buf[n+1]; + unsigned char next = buf[n+1]; buf[n] = mbedtls_ct_uint_if(no_op, current, next); } - buf[total-1] = mbedtls_ct_uint_if(no_op, buf[total-1], 0); + buf[total-1] = mbedtls_ct_uint_if_else_0(no_op, buf[total-1]); } } #endif /* MBEDTLS_PKCS1_V15 && MBEDTLS_RSA_C && ! MBEDTLS_RSA_ALT */ -#if defined(MBEDTLS_SSL_SOME_MODES_USE_MAC) -void mbedtls_ct_memcpy_if_eq(unsigned char *dest, - const unsigned char *src, - size_t len, - size_t c1, - size_t c2) -{ - /* mask = c1 == c2 ? 0xff : 0x00 */ - const size_t equal = mbedtls_ct_size_bool_eq(c1, c2); - const unsigned char mask = (unsigned char) mbedtls_ct_size_mask(equal); +void mbedtls_ct_memcpy_if(mbedtls_ct_condition_t condition, + unsigned char *dest, + const unsigned char *src1, + const unsigned char *src2, + size_t len) +{ +#if defined(MBEDTLS_CT_SIZE_64) + const uint64_t mask = (uint64_t) condition; + const uint64_t not_mask = (uint64_t) ~mbedtls_ct_compiler_opaque(condition); +#else + const uint32_t mask = (uint32_t) condition; + const uint32_t not_mask = (uint32_t) ~mbedtls_ct_compiler_opaque(condition); +#endif + + /* If src2 is NULL, setup src2 so that we read from the destination address. + * + * This means that if src2 == NULL && condition is false, the result will be a + * no-op because we read from dest and write the same data back into dest. + */ + if (src2 == NULL) { + src2 = dest; + } /* dest[i] = c1 == c2 ? src[i] : dest[i] */ - for (size_t i = 0; i < len; i++) { - dest[i] = (src[i] & mask) | (dest[i] & ~mask); + size_t i = 0; +#if defined(MBEDTLS_EFFICIENT_UNALIGNED_ACCESS) +#if defined(MBEDTLS_CT_SIZE_64) + for (; (i + 8) <= len; i += 8) { + uint64_t a = mbedtls_get_unaligned_uint64(src1 + i) & mask; + uint64_t b = mbedtls_get_unaligned_uint64(src2 + i) & not_mask; + mbedtls_put_unaligned_uint64(dest + i, a | b); + } +#else + for (; (i + 4) <= len; i += 4) { + uint32_t a = mbedtls_get_unaligned_uint32(src1 + i) & mask; + uint32_t b = mbedtls_get_unaligned_uint32(src2 + i) & not_mask; + mbedtls_put_unaligned_uint32(dest + i, a | b); + } +#endif /* defined(MBEDTLS_CT_SIZE_64) */ +#endif /* MBEDTLS_EFFICIENT_UNALIGNED_ACCESS */ + for (; i < len; i++) { + dest[i] = (src1[i] & mask) | (src2[i] & not_mask); } } @@ -400,399 +222,27 @@ void mbedtls_ct_memcpy_offset(unsigned char *dest, size_t offsetval; for (offsetval = offset_min; offsetval <= offset_max; offsetval++) { - mbedtls_ct_memcpy_if_eq(dest, src + offsetval, len, - offsetval, offset); - } -} - -int mbedtls_ct_hmac(mbedtls_md_context_t *ctx, - const unsigned char *add_data, - size_t add_data_len, - const unsigned char *data, - size_t data_len_secret, - size_t min_data_len, - size_t max_data_len, - unsigned char *output) -{ - /* - * This function breaks the HMAC abstraction and uses the md_clone() - * extension to the MD API in order to get constant-flow behaviour. - * - * HMAC(msg) is defined as HASH(okey + HASH(ikey + msg)) where + means - * concatenation, and okey/ikey are the XOR of the key with some fixed bit - * patterns (see RFC 2104, sec. 2), which are stored in ctx->hmac_ctx. - * - * We'll first compute inner_hash = HASH(ikey + msg) by hashing up to - * minlen, then cloning the context, and for each byte up to maxlen - * finishing up the hash computation, keeping only the correct result. - * - * Then we only need to compute HASH(okey + inner_hash) and we're done. - */ - const mbedtls_md_type_t md_alg = mbedtls_md_get_type(ctx->md_info); - /* TLS 1.0-1.2 only support SHA-384, SHA-256, SHA-1, MD-5, - * all of which have the same block size except SHA-384. */ - const size_t block_size = md_alg == MBEDTLS_MD_SHA384 ? 128 : 64; - const unsigned char * const ikey = ctx->hmac_ctx; - const unsigned char * const okey = ikey + block_size; - const size_t hash_size = mbedtls_md_get_size(ctx->md_info); - - unsigned char aux_out[MBEDTLS_MD_MAX_SIZE]; - mbedtls_md_context_t aux; - size_t offset; - int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED; - - mbedtls_md_init(&aux); - -#define MD_CHK(func_call) \ - do { \ - ret = (func_call); \ - if (ret != 0) \ - goto cleanup; \ - } while (0) - - MD_CHK(mbedtls_md_setup(&aux, ctx->md_info, 0)); - - /* After hmac_start() of hmac_reset(), ikey has already been hashed, - * so we can start directly with the message */ - MD_CHK(mbedtls_md_update(ctx, add_data, add_data_len)); - MD_CHK(mbedtls_md_update(ctx, data, min_data_len)); - - /* Fill the hash buffer in advance with something that is - * not a valid hash (barring an attack on the hash and - * deliberately-crafted input), in case the caller doesn't - * check the return status properly. */ - memset(output, '!', hash_size); - - /* For each possible length, compute the hash up to that point */ - for (offset = min_data_len; offset <= max_data_len; offset++) { - MD_CHK(mbedtls_md_clone(&aux, ctx)); - MD_CHK(mbedtls_md_finish(&aux, aux_out)); - /* Keep only the correct inner_hash in the output buffer */ - mbedtls_ct_memcpy_if_eq(output, aux_out, hash_size, - offset, data_len_secret); - - if (offset < max_data_len) { - MD_CHK(mbedtls_md_update(ctx, data + offset, 1)); - } + mbedtls_ct_memcpy_if(mbedtls_ct_uint_eq(offsetval, offset), dest, src + offsetval, NULL, + len); } - - /* The context needs to finish() before it starts() again */ - MD_CHK(mbedtls_md_finish(ctx, aux_out)); - - /* Now compute HASH(okey + inner_hash) */ - MD_CHK(mbedtls_md_starts(ctx)); - MD_CHK(mbedtls_md_update(ctx, okey, block_size)); - MD_CHK(mbedtls_md_update(ctx, output, hash_size)); - MD_CHK(mbedtls_md_finish(ctx, output)); - - /* Done, get ready for next time */ - MD_CHK(mbedtls_md_hmac_reset(ctx)); - -#undef MD_CHK - -cleanup: - mbedtls_md_free(&aux); - return ret; } -#endif /* MBEDTLS_SSL_SOME_MODES_USE_MAC */ - -#if defined(MBEDTLS_BIGNUM_C) - -#define MPI_VALIDATE_RET(cond) \ - MBEDTLS_INTERNAL_VALIDATE_RET(cond, MBEDTLS_ERR_MPI_BAD_INPUT_DATA) - -/* - * Conditionally assign X = Y, without leaking information - * about whether the assignment was made or not. - * (Leaking information about the respective sizes of X and Y is ok however.) - */ -#if defined(_MSC_VER) && defined(_M_ARM64) && (_MSC_FULL_VER < 193131103) -/* - * MSVC miscompiles this function if it's inlined prior to Visual Studio 2022 version 17.1. See: - * https://developercommunity.visualstudio.com/t/c-compiler-miscompiles-part-of-mbedtls-library-on/1646989 - */ -__declspec(noinline) -#endif -int mbedtls_mpi_safe_cond_assign(mbedtls_mpi *X, - const mbedtls_mpi *Y, - unsigned char assign) -{ - int ret = 0; - size_t i; - mbedtls_mpi_uint limb_mask; - MPI_VALIDATE_RET(X != NULL); - MPI_VALIDATE_RET(Y != NULL); - - /* all-bits 1 if assign is 1, all-bits 0 if assign is 0 */ - limb_mask = mbedtls_ct_mpi_uint_mask(assign);; - - MBEDTLS_MPI_CHK(mbedtls_mpi_grow(X, Y->n)); - - X->s = (int) mbedtls_ct_uint_if(assign, Y->s, X->s); - - mbedtls_ct_mpi_uint_cond_assign(Y->n, X->p, Y->p, assign); - - for (i = Y->n; i < X->n; i++) { - X->p[i] &= ~limb_mask; - } - -cleanup: - return ret; -} - -/* - * Conditionally swap X and Y, without leaking information - * about whether the swap was made or not. - * Here it is not ok to simply swap the pointers, which would lead to - * different memory access patterns when X and Y are used afterwards. - */ -int mbedtls_mpi_safe_cond_swap(mbedtls_mpi *X, - mbedtls_mpi *Y, - unsigned char swap) -{ - int ret, s; - size_t i; - mbedtls_mpi_uint limb_mask; - mbedtls_mpi_uint tmp; - MPI_VALIDATE_RET(X != NULL); - MPI_VALIDATE_RET(Y != NULL); - - if (X == Y) { - return 0; - } - - /* all-bits 1 if swap is 1, all-bits 0 if swap is 0 */ - limb_mask = mbedtls_ct_mpi_uint_mask(swap); - - MBEDTLS_MPI_CHK(mbedtls_mpi_grow(X, Y->n)); - MBEDTLS_MPI_CHK(mbedtls_mpi_grow(Y, X->n)); - - s = X->s; - X->s = (int) mbedtls_ct_uint_if(swap, Y->s, X->s); - Y->s = (int) mbedtls_ct_uint_if(swap, s, Y->s); - - - for (i = 0; i < X->n; i++) { - tmp = X->p[i]; - X->p[i] = (X->p[i] & ~limb_mask) | (Y->p[i] & limb_mask); - Y->p[i] = (Y->p[i] & ~limb_mask) | (tmp & limb_mask); - } - -cleanup: - return ret; -} - -/* - * Compare signed values in constant time - */ -int mbedtls_mpi_lt_mpi_ct(const mbedtls_mpi *X, - const mbedtls_mpi *Y, - unsigned *ret) -{ - size_t i; - /* The value of any of these variables is either 0 or 1 at all times. */ - unsigned cond, done, X_is_negative, Y_is_negative; - - MPI_VALIDATE_RET(X != NULL); - MPI_VALIDATE_RET(Y != NULL); - MPI_VALIDATE_RET(ret != NULL); - - if (X->n != Y->n) { - return MBEDTLS_ERR_MPI_BAD_INPUT_DATA; - } - - /* - * Set sign_N to 1 if N >= 0, 0 if N < 0. - * We know that N->s == 1 if N >= 0 and N->s == -1 if N < 0. - */ - X_is_negative = (X->s & 2) >> 1; - Y_is_negative = (Y->s & 2) >> 1; - - /* - * If the signs are different, then the positive operand is the bigger. - * That is if X is negative (X_is_negative == 1), then X < Y is true and it - * is false if X is positive (X_is_negative == 0). - */ - cond = (X_is_negative ^ Y_is_negative); - *ret = cond & X_is_negative; - - /* - * This is a constant-time function. We might have the result, but we still - * need to go through the loop. Record if we have the result already. - */ - done = cond; - - for (i = X->n; i > 0; i--) { - /* - * If Y->p[i - 1] < X->p[i - 1] then X < Y is true if and only if both - * X and Y are negative. - * - * Again even if we can make a decision, we just mark the result and - * the fact that we are done and continue looping. - */ - cond = mbedtls_ct_mpi_uint_lt(Y->p[i - 1], X->p[i - 1]); - *ret |= cond & (1 - done) & X_is_negative; - done |= cond; - - /* - * If X->p[i - 1] < Y->p[i - 1] then X < Y is true if and only if both - * X and Y are positive. - * - * Again even if we can make a decision, we just mark the result and - * the fact that we are done and continue looping. - */ - cond = mbedtls_ct_mpi_uint_lt(X->p[i - 1], Y->p[i - 1]); - *ret |= cond & (1 - done) & (1 - X_is_negative); - done |= cond; - } - - return 0; -} - -#endif /* MBEDTLS_BIGNUM_C */ - #if defined(MBEDTLS_PKCS1_V15) && defined(MBEDTLS_RSA_C) && !defined(MBEDTLS_RSA_ALT) -int mbedtls_ct_rsaes_pkcs1_v15_unpadding(int mode, - unsigned char *input, - size_t ilen, - unsigned char *output, - size_t output_max_len, - size_t *olen) +void mbedtls_ct_zeroize_if(mbedtls_ct_condition_t condition, void *buf, size_t len) { - int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED; - size_t i, plaintext_max_size; - - /* The following variables take sensitive values: their value must - * not leak into the observable behavior of the function other than - * the designated outputs (output, olen, return value). Otherwise - * this would open the execution of the function to - * side-channel-based variants of the Bleichenbacher padding oracle - * attack. Potential side channels include overall timing, memory - * access patterns (especially visible to an adversary who has access - * to a shared memory cache), and branches (especially visible to - * an adversary who has access to a shared code cache or to a shared - * branch predictor). */ - size_t pad_count = 0; - unsigned bad = 0; - unsigned char pad_done = 0; - size_t plaintext_size = 0; - unsigned output_too_large; - - plaintext_max_size = (output_max_len > ilen - 11) ? ilen - 11 - : output_max_len; - - /* Check and get padding length in constant time and constant - * memory trace. The first byte must be 0. */ - bad |= input[0]; - - if (mode == MBEDTLS_RSA_PRIVATE) { - /* Decode EME-PKCS1-v1_5 padding: 0x00 || 0x02 || PS || 0x00 - * where PS must be at least 8 nonzero bytes. */ - bad |= input[1] ^ MBEDTLS_RSA_CRYPT; - - /* Read the whole buffer. Set pad_done to nonzero if we find - * the 0x00 byte and remember the padding length in pad_count. */ - for (i = 2; i < ilen; i++) { - pad_done |= ((input[i] | (unsigned char) -input[i]) >> 7) ^ 1; - pad_count += ((pad_done | (unsigned char) -pad_done) >> 7) ^ 1; - } - } else { - /* Decode EMSA-PKCS1-v1_5 padding: 0x00 || 0x01 || PS || 0x00 - * where PS must be at least 8 bytes with the value 0xFF. */ - bad |= input[1] ^ MBEDTLS_RSA_SIGN; - - /* Read the whole buffer. Set pad_done to nonzero if we find - * the 0x00 byte and remember the padding length in pad_count. - * If there's a non-0xff byte in the padding, the padding is bad. */ - for (i = 2; i < ilen; i++) { - pad_done |= mbedtls_ct_uint_if(input[i], 0, 1); - pad_count += mbedtls_ct_uint_if(pad_done, 0, 1); - bad |= mbedtls_ct_uint_if(pad_done, 0, input[i] ^ 0xFF); - } + uint32_t mask = (uint32_t) ~condition; + uint8_t *p = (uint8_t *) buf; + size_t i = 0; +#if defined(MBEDTLS_EFFICIENT_UNALIGNED_ACCESS) + for (; (i + 4) <= len; i += 4) { + mbedtls_put_unaligned_uint32((void *) (p + i), + mbedtls_get_unaligned_uint32((void *) (p + i)) & mask); } - - /* If pad_done is still zero, there's no data, only unfinished padding. */ - bad |= mbedtls_ct_uint_if(pad_done, 0, 1); - - /* There must be at least 8 bytes of padding. */ - bad |= mbedtls_ct_size_gt(8, pad_count); - - /* If the padding is valid, set plaintext_size to the number of - * remaining bytes after stripping the padding. If the padding - * is invalid, avoid leaking this fact through the size of the - * output: use the maximum message size that fits in the output - * buffer. Do it without branches to avoid leaking the padding - * validity through timing. RSA keys are small enough that all the - * size_t values involved fit in unsigned int. */ - plaintext_size = mbedtls_ct_uint_if( - bad, (unsigned) plaintext_max_size, - (unsigned) (ilen - pad_count - 3)); - - /* Set output_too_large to 0 if the plaintext fits in the output - * buffer and to 1 otherwise. */ - output_too_large = mbedtls_ct_size_gt(plaintext_size, - plaintext_max_size); - - /* Set ret without branches to avoid timing attacks. Return: - * - INVALID_PADDING if the padding is bad (bad != 0). - * - OUTPUT_TOO_LARGE if the padding is good but the decrypted - * plaintext does not fit in the output buffer. - * - 0 if the padding is correct. */ - ret = -(int) mbedtls_ct_uint_if( - bad, -MBEDTLS_ERR_RSA_INVALID_PADDING, - mbedtls_ct_uint_if(output_too_large, - -MBEDTLS_ERR_RSA_OUTPUT_TOO_LARGE, - 0)); - - /* If the padding is bad or the plaintext is too large, zero the - * data that we're about to copy to the output buffer. - * We need to copy the same amount of data - * from the same buffer whether the padding is good or not to - * avoid leaking the padding validity through overall timing or - * through memory or cache access patterns. */ - bad = mbedtls_ct_uint_mask(bad | output_too_large); - for (i = 11; i < ilen; i++) { - input[i] &= ~bad; - } - - /* If the plaintext is too large, truncate it to the buffer size. - * Copy anyway to avoid revealing the length through timing, because - * revealing the length is as bad as revealing the padding validity - * for a Bleichenbacher attack. */ - plaintext_size = mbedtls_ct_uint_if(output_too_large, - (unsigned) plaintext_max_size, - (unsigned) plaintext_size); - - /* Move the plaintext to the leftmost position where it can start in - * the working buffer, i.e. make it start plaintext_max_size from - * the end of the buffer. Do this with a memory access trace that - * does not depend on the plaintext size. After this move, the - * starting location of the plaintext is no longer sensitive - * information. */ - mbedtls_ct_mem_move_to_left(input + ilen - plaintext_max_size, - plaintext_max_size, - plaintext_max_size - plaintext_size); - - /* Finally copy the decrypted plaintext plus trailing zeros into the output - * buffer. If output_max_len is 0, then output may be an invalid pointer - * and the result of memcpy() would be undefined; prevent undefined - * behavior making sure to depend only on output_max_len (the size of the - * user-provided output buffer), which is independent from plaintext - * length, validity of padding, success of the decryption, and other - * secrets. */ - if (output_max_len != 0) { - memcpy(output, input + ilen - plaintext_max_size, plaintext_max_size); +#endif + for (; i < len; i++) { + p[i] = p[i] & mask; } - - /* Report the amount of data we copied to the output buffer. In case - * of errors (bad padding or output too large), the value of *olen - * when this function returns is not specified. Making it equivalent - * to the good case limits the risks of leaking the padding validity. */ - *olen = plaintext_size; - - return ret; } -#endif /* MBEDTLS_PKCS1_V15 && MBEDTLS_RSA_C && ! MBEDTLS_RSA_ALT */ +#endif /* defined(MBEDTLS_PKCS1_V15) && defined(MBEDTLS_RSA_C) && !defined(MBEDTLS_RSA_ALT) */ diff --git a/vendor/mbedtls/library/constant_time_impl.h b/vendor/mbedtls/library/constant_time_impl.h new file mode 100644 index 0000000000..2a4574ba68 --- /dev/null +++ b/vendor/mbedtls/library/constant_time_impl.h @@ -0,0 +1,556 @@ +/** + * Constant-time functions + * + * Copyright The Mbed TLS Contributors + * SPDX-License-Identifier: Apache-2.0 OR GPL-2.0-or-later + */ + +#ifndef MBEDTLS_CONSTANT_TIME_IMPL_H +#define MBEDTLS_CONSTANT_TIME_IMPL_H + +#include + +#include "common.h" + +#if defined(MBEDTLS_BIGNUM_C) +#include "mbedtls/bignum.h" +#endif + +/* + * To improve readability of constant_time_internal.h, the static inline + * definitions are here, and constant_time_internal.h has only the declarations. + * + * This results in duplicate declarations of the form: + * static inline void f(); // from constant_time_internal.h + * static inline void f() { ... } // from constant_time_impl.h + * when constant_time_internal.h is included. + * + * This appears to behave as if the declaration-without-definition was not present + * (except for warnings if gcc -Wredundant-decls or similar is used). + * + * Disable -Wredundant-decls so that gcc does not warn about this. This is re-enabled + * at the bottom of this file. + */ +#if defined(MBEDTLS_COMPILER_IS_GCC) && (__GNUC__ > 4) + #pragma GCC diagnostic push + #pragma GCC diagnostic ignored "-Wredundant-decls" +#endif + +/* Disable asm under Memsan because it confuses Memsan and generates false errors. + * + * We also disable under Valgrind by default, because it's more useful + * for Valgrind to test the plain C implementation. MBEDTLS_TEST_CONSTANT_FLOW_ASM //no-check-names + * may be set to permit building asm under Valgrind. + */ +#if defined(MBEDTLS_TEST_CONSTANT_FLOW_MEMSAN) || \ + (defined(MBEDTLS_TEST_CONSTANT_FLOW_VALGRIND) && !defined(MBEDTLS_TEST_CONSTANT_FLOW_ASM)) //no-check-names +#define MBEDTLS_CT_NO_ASM +#elif defined(__has_feature) +#if __has_feature(memory_sanitizer) +#define MBEDTLS_CT_NO_ASM +#endif +#endif + +/* armcc5 --gnu defines __GNUC__ but doesn't support GNU's extended asm */ +#if defined(MBEDTLS_HAVE_ASM) && defined(__GNUC__) && (!defined(__ARMCC_VERSION) || \ + __ARMCC_VERSION >= 6000000) && !defined(MBEDTLS_CT_NO_ASM) +#define MBEDTLS_CT_ASM +#if (defined(__arm__) || defined(__thumb__) || defined(__thumb2__)) +#define MBEDTLS_CT_ARM_ASM +#elif defined(__aarch64__) +#define MBEDTLS_CT_AARCH64_ASM +#elif defined(__amd64__) || defined(__x86_64__) +#define MBEDTLS_CT_X86_64_ASM +#elif defined(__i386__) +#define MBEDTLS_CT_X86_ASM +#endif +#endif + +#define MBEDTLS_CT_SIZE (sizeof(mbedtls_ct_uint_t) * 8) + + +/* ============================================================================ + * Core const-time primitives + */ + +/* Ensure that the compiler cannot know the value of x (i.e., cannot optimise + * based on its value) after this function is called. + * + * If we are not using assembly, this will be fairly inefficient, so its use + * should be minimised. + */ + +#if !defined(MBEDTLS_CT_ASM) +extern volatile mbedtls_ct_uint_t mbedtls_ct_zero; +#endif + +/** + * \brief Ensure that a value cannot be known at compile time. + * + * \param x The value to hide from the compiler. + * \return The same value that was passed in, such that the compiler + * cannot prove its value (even for calls of the form + * x = mbedtls_ct_compiler_opaque(1), x will be unknown). + * + * \note This is mainly used in constructing mbedtls_ct_condition_t + * values and performing operations over them, to ensure that + * there is no way for the compiler to ever know anything about + * the value of an mbedtls_ct_condition_t. + */ +static inline mbedtls_ct_uint_t mbedtls_ct_compiler_opaque(mbedtls_ct_uint_t x) +{ +#if defined(MBEDTLS_CT_ASM) + asm volatile ("" : [x] "+r" (x) :); + return x; +#else + return x ^ mbedtls_ct_zero; +#endif +} + +/* + * Selecting unified syntax is needed for gcc, and harmless on clang. + * + * This is needed because on Thumb 1, condition flags are always set, so + * e.g. "negs" is supported but "neg" is not (on Thumb 2, both exist). + * + * Under Thumb 1 unified syntax, only the "negs" form is accepted, and + * under divided syntax, only the "neg" form is accepted. clang only + * supports unified syntax. + * + * On Thumb 2 and Arm, both compilers are happy with the "s" suffix, + * although we don't actually care about setting the flags. + * + * For old versions of gcc (see #8516 for details), restore divided + * syntax afterwards - otherwise old versions of gcc seem to apply + * unified syntax globally, which breaks other asm code. + */ +#if defined(MBEDTLS_COMPILER_IS_GCC) && defined(__thumb__) && !defined(__thumb2__) && \ + (__GNUC__ < 11) && !defined(__ARM_ARCH_2__) +#define RESTORE_ASM_SYNTAX ".syntax divided \n\t" +#else +#define RESTORE_ASM_SYNTAX +#endif + +/* Convert a number into a condition in constant time. */ +static inline mbedtls_ct_condition_t mbedtls_ct_bool(mbedtls_ct_uint_t x) +{ + /* + * Define mask-generation code that, as far as possible, will not use branches or conditional instructions. + * + * For some platforms / type sizes, we define assembly to assure this. + * + * Otherwise, we define a plain C fallback which (in May 2023) does not get optimised into + * conditional instructions or branches by trunk clang, gcc, or MSVC v19. + */ +#if defined(MBEDTLS_CT_AARCH64_ASM) && (defined(MBEDTLS_CT_SIZE_32) || defined(MBEDTLS_CT_SIZE_64)) + mbedtls_ct_uint_t s; + asm volatile ("neg %x[s], %x[x] \n\t" + "orr %x[x], %x[s], %x[x] \n\t" + "asr %x[x], %x[x], 63 \n\t" + : + [s] "=&r" (s), + [x] "+&r" (x) + : + : + ); + return (mbedtls_ct_condition_t) x; +#elif defined(MBEDTLS_CT_ARM_ASM) && defined(MBEDTLS_CT_SIZE_32) + uint32_t s; + asm volatile (".syntax unified \n\t" + "negs %[s], %[x] \n\t" + "orrs %[x], %[x], %[s] \n\t" + "asrs %[x], %[x], #31 \n\t" + RESTORE_ASM_SYNTAX + : + [s] "=&l" (s), + [x] "+&l" (x) + : + : + "cc" /* clobbers flag bits */ + ); + return (mbedtls_ct_condition_t) x; +#elif defined(MBEDTLS_CT_X86_64_ASM) && (defined(MBEDTLS_CT_SIZE_32) || defined(MBEDTLS_CT_SIZE_64)) + uint64_t s; + asm volatile ("mov %[x], %[s] \n\t" + "neg %[s] \n\t" + "or %[x], %[s] \n\t" + "sar $63, %[s] \n\t" + : + [s] "=&a" (s) + : + [x] "D" (x) + : + ); + return (mbedtls_ct_condition_t) s; +#elif defined(MBEDTLS_CT_X86_ASM) && defined(MBEDTLS_CT_SIZE_32) + uint32_t s; + asm volatile ("mov %[x], %[s] \n\t" + "neg %[s] \n\t" + "or %[s], %[x] \n\t" + "sar $31, %[x] \n\t" + : + [s] "=&c" (s), + [x] "+&a" (x) + : + : + ); + return (mbedtls_ct_condition_t) x; +#else + const mbedtls_ct_uint_t xo = mbedtls_ct_compiler_opaque(x); +#if defined(_MSC_VER) + /* MSVC has a warning about unary minus on unsigned, but this is + * well-defined and precisely what we want to do here */ +#pragma warning( push ) +#pragma warning( disable : 4146 ) +#endif + // y is negative (i.e., top bit set) iff x is non-zero + mbedtls_ct_int_t y = (-xo) | -(xo >> 1); + + // extract only the sign bit of y so that y == 1 (if x is non-zero) or 0 (if x is zero) + y = (((mbedtls_ct_uint_t) y) >> (MBEDTLS_CT_SIZE - 1)); + + // -y has all bits set (if x is non-zero), or all bits clear (if x is zero) + return (mbedtls_ct_condition_t) (-y); +#if defined(_MSC_VER) +#pragma warning( pop ) +#endif +#endif +} + +static inline mbedtls_ct_uint_t mbedtls_ct_if(mbedtls_ct_condition_t condition, + mbedtls_ct_uint_t if1, + mbedtls_ct_uint_t if0) +{ +#if defined(MBEDTLS_CT_AARCH64_ASM) && (defined(MBEDTLS_CT_SIZE_32) || defined(MBEDTLS_CT_SIZE_64)) + asm volatile ("and %x[if1], %x[if1], %x[condition] \n\t" + "mvn %x[condition], %x[condition] \n\t" + "and %x[condition], %x[condition], %x[if0] \n\t" + "orr %x[condition], %x[if1], %x[condition]" + : + [condition] "+&r" (condition), + [if1] "+&r" (if1) + : + [if0] "r" (if0) + : + ); + return (mbedtls_ct_uint_t) condition; +#elif defined(MBEDTLS_CT_ARM_ASM) && defined(MBEDTLS_CT_SIZE_32) + asm volatile (".syntax unified \n\t" + "ands %[if1], %[if1], %[condition] \n\t" + "mvns %[condition], %[condition] \n\t" + "ands %[condition], %[condition], %[if0] \n\t" + "orrs %[condition], %[if1], %[condition] \n\t" + RESTORE_ASM_SYNTAX + : + [condition] "+&l" (condition), + [if1] "+&l" (if1) + : + [if0] "l" (if0) + : + "cc" + ); + return (mbedtls_ct_uint_t) condition; +#elif defined(MBEDTLS_CT_X86_64_ASM) && (defined(MBEDTLS_CT_SIZE_32) || defined(MBEDTLS_CT_SIZE_64)) + asm volatile ("and %[condition], %[if1] \n\t" + "not %[condition] \n\t" + "and %[condition], %[if0] \n\t" + "or %[if1], %[if0] \n\t" + : + [condition] "+&D" (condition), + [if1] "+&S" (if1), + [if0] "+&a" (if0) + : + : + ); + return if0; +#elif defined(MBEDTLS_CT_X86_ASM) && defined(MBEDTLS_CT_SIZE_32) + asm volatile ("and %[condition], %[if1] \n\t" + "not %[condition] \n\t" + "and %[if0], %[condition] \n\t" + "or %[condition], %[if1] \n\t" + : + [condition] "+&c" (condition), + [if1] "+&a" (if1) + : + [if0] "b" (if0) + : + ); + return if1; +#else + mbedtls_ct_condition_t not_cond = + (mbedtls_ct_condition_t) (~mbedtls_ct_compiler_opaque(condition)); + return (mbedtls_ct_uint_t) ((condition & if1) | (not_cond & if0)); +#endif +} + +static inline mbedtls_ct_condition_t mbedtls_ct_uint_lt(mbedtls_ct_uint_t x, mbedtls_ct_uint_t y) +{ +#if defined(MBEDTLS_CT_AARCH64_ASM) && (defined(MBEDTLS_CT_SIZE_32) || defined(MBEDTLS_CT_SIZE_64)) + uint64_t s1; + asm volatile ("eor %x[s1], %x[y], %x[x] \n\t" + "sub %x[x], %x[x], %x[y] \n\t" + "bic %x[x], %x[x], %x[s1] \n\t" + "and %x[s1], %x[s1], %x[y] \n\t" + "orr %x[s1], %x[x], %x[s1] \n\t" + "asr %x[x], %x[s1], 63" + : + [s1] "=&r" (s1), + [x] "+&r" (x) + : + [y] "r" (y) + : + ); + return (mbedtls_ct_condition_t) x; +#elif defined(MBEDTLS_CT_ARM_ASM) && defined(MBEDTLS_CT_SIZE_32) + uint32_t s1; + asm volatile ( + ".syntax unified \n\t" +#if defined(__thumb__) && !defined(__thumb2__) + "movs %[s1], %[x] \n\t" + "eors %[s1], %[s1], %[y] \n\t" +#else + "eors %[s1], %[x], %[y] \n\t" +#endif + "subs %[x], %[x], %[y] \n\t" + "bics %[x], %[x], %[s1] \n\t" + "ands %[y], %[s1], %[y] \n\t" + "orrs %[x], %[x], %[y] \n\t" + "asrs %[x], %[x], #31 \n\t" + RESTORE_ASM_SYNTAX + : + [s1] "=&l" (s1), + [x] "+&l" (x), + [y] "+&l" (y) + : + : + "cc" + ); + return (mbedtls_ct_condition_t) x; +#elif defined(MBEDTLS_CT_X86_64_ASM) && (defined(MBEDTLS_CT_SIZE_32) || defined(MBEDTLS_CT_SIZE_64)) + uint64_t s; + asm volatile ("mov %[x], %[s] \n\t" + "xor %[y], %[s] \n\t" + "sub %[y], %[x] \n\t" + "and %[s], %[y] \n\t" + "not %[s] \n\t" + "and %[s], %[x] \n\t" + "or %[y], %[x] \n\t" + "sar $63, %[x] \n\t" + : + [s] "=&a" (s), + [x] "+&D" (x), + [y] "+&S" (y) + : + : + ); + return (mbedtls_ct_condition_t) x; +#elif defined(MBEDTLS_CT_X86_ASM) && defined(MBEDTLS_CT_SIZE_32) + uint32_t s; + asm volatile ("mov %[x], %[s] \n\t" + "xor %[y], %[s] \n\t" + "sub %[y], %[x] \n\t" + "and %[s], %[y] \n\t" + "not %[s] \n\t" + "and %[s], %[x] \n\t" + "or %[y], %[x] \n\t" + "sar $31, %[x] \n\t" + : + [s] "=&b" (s), + [x] "+&a" (x), + [y] "+&c" (y) + : + : + ); + return (mbedtls_ct_condition_t) x; +#else + /* Ensure that the compiler cannot optimise the following operations over x and y, + * even if it knows the value of x and y. + */ + const mbedtls_ct_uint_t xo = mbedtls_ct_compiler_opaque(x); + const mbedtls_ct_uint_t yo = mbedtls_ct_compiler_opaque(y); + /* + * Check if the most significant bits (MSB) of the operands are different. + * cond is true iff the MSBs differ. + */ + mbedtls_ct_condition_t cond = mbedtls_ct_bool((xo ^ yo) >> (MBEDTLS_CT_SIZE - 1)); + + /* + * If the MSB are the same then the difference x-y will be negative (and + * have its MSB set to 1 during conversion to unsigned) if and only if x> (MBEDTLS_CT_SIZE - 1); + + // Convert to a condition (i.e., all bits set iff non-zero) + return mbedtls_ct_bool(ret); +#endif +} + +static inline mbedtls_ct_condition_t mbedtls_ct_uint_ne(mbedtls_ct_uint_t x, mbedtls_ct_uint_t y) +{ + /* diff = 0 if x == y, non-zero otherwise */ + const mbedtls_ct_uint_t diff = mbedtls_ct_compiler_opaque(x) ^ mbedtls_ct_compiler_opaque(y); + + /* all ones if x != y, 0 otherwise */ + return mbedtls_ct_bool(diff); +} + +static inline unsigned char mbedtls_ct_uchar_in_range_if(unsigned char low, + unsigned char high, + unsigned char c, + unsigned char t) +{ + const unsigned char co = (unsigned char) mbedtls_ct_compiler_opaque(c); + const unsigned char to = (unsigned char) mbedtls_ct_compiler_opaque(t); + + /* low_mask is: 0 if low <= c, 0x...ff if low > c */ + unsigned low_mask = ((unsigned) co - low) >> 8; + /* high_mask is: 0 if c <= high, 0x...ff if c > high */ + unsigned high_mask = ((unsigned) high - co) >> 8; + + return (unsigned char) (~(low_mask | high_mask)) & to; +} + +/* ============================================================================ + * Everything below here is trivial wrapper functions + */ + +static inline size_t mbedtls_ct_size_if(mbedtls_ct_condition_t condition, + size_t if1, + size_t if0) +{ + return (size_t) mbedtls_ct_if(condition, (mbedtls_ct_uint_t) if1, (mbedtls_ct_uint_t) if0); +} + +static inline unsigned mbedtls_ct_uint_if(mbedtls_ct_condition_t condition, + unsigned if1, + unsigned if0) +{ + return (unsigned) mbedtls_ct_if(condition, (mbedtls_ct_uint_t) if1, (mbedtls_ct_uint_t) if0); +} + +static inline mbedtls_ct_condition_t mbedtls_ct_bool_if(mbedtls_ct_condition_t condition, + mbedtls_ct_condition_t if1, + mbedtls_ct_condition_t if0) +{ + return (mbedtls_ct_condition_t) mbedtls_ct_if(condition, (mbedtls_ct_uint_t) if1, + (mbedtls_ct_uint_t) if0); +} + +#if defined(MBEDTLS_BIGNUM_C) + +static inline mbedtls_mpi_uint mbedtls_ct_mpi_uint_if(mbedtls_ct_condition_t condition, + mbedtls_mpi_uint if1, + mbedtls_mpi_uint if0) +{ + return (mbedtls_mpi_uint) mbedtls_ct_if(condition, + (mbedtls_ct_uint_t) if1, + (mbedtls_ct_uint_t) if0); +} + +#endif + +static inline size_t mbedtls_ct_size_if_else_0(mbedtls_ct_condition_t condition, size_t if1) +{ + return (size_t) (condition & if1); +} + +static inline unsigned mbedtls_ct_uint_if_else_0(mbedtls_ct_condition_t condition, unsigned if1) +{ + return (unsigned) (condition & if1); +} + +static inline mbedtls_ct_condition_t mbedtls_ct_bool_if_else_0(mbedtls_ct_condition_t condition, + mbedtls_ct_condition_t if1) +{ + return (mbedtls_ct_condition_t) (condition & if1); +} + +#if defined(MBEDTLS_BIGNUM_C) + +static inline mbedtls_mpi_uint mbedtls_ct_mpi_uint_if_else_0(mbedtls_ct_condition_t condition, + mbedtls_mpi_uint if1) +{ + return (mbedtls_mpi_uint) (condition & if1); +} + +#endif /* MBEDTLS_BIGNUM_C */ + +static inline int mbedtls_ct_error_if(mbedtls_ct_condition_t condition, int if1, int if0) +{ + /* Coverting int -> uint -> int here is safe, because we require if1 and if0 to be + * in the range -32767..0, and we require 32-bit int and uint types. + * + * This means that (0 <= -if0 < INT_MAX), so negating if0 is safe, and similarly for + * converting back to int. + */ + return -((int) mbedtls_ct_if(condition, (mbedtls_ct_uint_t) (-if1), + (mbedtls_ct_uint_t) (-if0))); +} + +static inline int mbedtls_ct_error_if_else_0(mbedtls_ct_condition_t condition, int if1) +{ + return -((int) (condition & (-if1))); +} + +static inline mbedtls_ct_condition_t mbedtls_ct_uint_eq(mbedtls_ct_uint_t x, + mbedtls_ct_uint_t y) +{ + return ~mbedtls_ct_uint_ne(x, y); +} + +static inline mbedtls_ct_condition_t mbedtls_ct_uint_gt(mbedtls_ct_uint_t x, + mbedtls_ct_uint_t y) +{ + return mbedtls_ct_uint_lt(y, x); +} + +static inline mbedtls_ct_condition_t mbedtls_ct_uint_ge(mbedtls_ct_uint_t x, + mbedtls_ct_uint_t y) +{ + return ~mbedtls_ct_uint_lt(x, y); +} + +static inline mbedtls_ct_condition_t mbedtls_ct_uint_le(mbedtls_ct_uint_t x, + mbedtls_ct_uint_t y) +{ + return ~mbedtls_ct_uint_gt(x, y); +} + +static inline mbedtls_ct_condition_t mbedtls_ct_bool_ne(mbedtls_ct_condition_t x, + mbedtls_ct_condition_t y) +{ + return (mbedtls_ct_condition_t) (x ^ y); +} + +static inline mbedtls_ct_condition_t mbedtls_ct_bool_and(mbedtls_ct_condition_t x, + mbedtls_ct_condition_t y) +{ + return (mbedtls_ct_condition_t) (x & y); +} + +static inline mbedtls_ct_condition_t mbedtls_ct_bool_or(mbedtls_ct_condition_t x, + mbedtls_ct_condition_t y) +{ + return (mbedtls_ct_condition_t) (x | y); +} + +static inline mbedtls_ct_condition_t mbedtls_ct_bool_not(mbedtls_ct_condition_t x) +{ + return (mbedtls_ct_condition_t) (~x); +} + +#if defined(MBEDTLS_COMPILER_IS_GCC) && (__GNUC__ > 4) +/* Restore warnings for -Wredundant-decls on gcc */ + #pragma GCC diagnostic pop +#endif + +#endif /* MBEDTLS_CONSTANT_TIME_IMPL_H */ diff --git a/vendor/mbedtls/library/constant_time_internal.h b/vendor/mbedtls/library/constant_time_internal.h index 0ba8a7a0b5..61a5c6d4e9 100644 --- a/vendor/mbedtls/library/constant_time_internal.h +++ b/vendor/mbedtls/library/constant_time_internal.h @@ -2,227 +2,512 @@ * Constant-time functions * * Copyright The Mbed TLS Contributors - * SPDX-License-Identifier: Apache-2.0 - * - * Licensed under the Apache License, Version 2.0 (the "License"); you may - * not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT - * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. + * SPDX-License-Identifier: Apache-2.0 OR GPL-2.0-or-later */ #ifndef MBEDTLS_CONSTANT_TIME_INTERNAL_H #define MBEDTLS_CONSTANT_TIME_INTERNAL_H +#include +#include + #include "common.h" #if defined(MBEDTLS_BIGNUM_C) #include "mbedtls/bignum.h" #endif -#if defined(MBEDTLS_SSL_TLS_C) -#include "mbedtls/ssl_internal.h" +/* The constant-time interface provides various operations that are likely + * to result in constant-time code that does not branch or use conditional + * instructions for secret data (for secret pointers, this also applies to + * the data pointed to). + * + * It has three main parts: + * + * - boolean operations + * These are all named mbedtls_ct__. + * They operate over and return mbedtls_ct_condition_t. + * All arguments are considered secret. + * example: bool x = y | z => x = mbedtls_ct_bool_or(y, z) + * example: bool x = y == z => x = mbedtls_ct_uint_eq(y, z) + * + * - conditional data selection + * These are all named mbedtls_ct__if and mbedtls_ct__if_else_0 + * All arguments are considered secret. + * example: size_t a = x ? b : c => a = mbedtls_ct_size_if(x, b, c) + * example: unsigned a = x ? b : 0 => a = mbedtls_ct_uint_if_else_0(x, b) + * + * - block memory operations + * Only some arguments are considered secret, as documented for each + * function. + * example: if (x) memcpy(...) => mbedtls_ct_memcpy_if(x, ...) + * + * mbedtls_ct_condition_t must be treated as opaque and only created and + * manipulated via the functions in this header. The compiler should never + * be able to prove anything about its value at compile-time. + * + * mbedtls_ct_uint_t is an unsigned integer type over which constant time + * operations may be performed via the functions in this header. It is as big + * as the larger of size_t and mbedtls_mpi_uint, i.e. it is safe to cast + * to/from "unsigned int", "size_t", and "mbedtls_mpi_uint" (and any other + * not-larger integer types). + * + * For Arm (32-bit, 64-bit and Thumb), x86 and x86-64, assembly implementations + * are used to ensure that the generated code is constant time. For other + * architectures, it uses a plain C fallback designed to yield constant-time code + * (this has been observed to be constant-time on latest gcc, clang and MSVC + * as of May 2023). + * + * For readability, the static inline definitions are separated out into + * constant_time_impl.h. + */ + +#if (SIZE_MAX > 0xffffffffffffffffULL) +/* Pointer size > 64-bit */ +typedef size_t mbedtls_ct_condition_t; +typedef size_t mbedtls_ct_uint_t; +typedef ptrdiff_t mbedtls_ct_int_t; +#define MBEDTLS_CT_TRUE ((mbedtls_ct_condition_t) mbedtls_ct_compiler_opaque(SIZE_MAX)) +#elif (SIZE_MAX > 0xffffffff) || defined(MBEDTLS_HAVE_INT64) +/* 32-bit < pointer size <= 64-bit, or 64-bit MPI */ +typedef uint64_t mbedtls_ct_condition_t; +typedef uint64_t mbedtls_ct_uint_t; +typedef int64_t mbedtls_ct_int_t; +#define MBEDTLS_CT_SIZE_64 +#define MBEDTLS_CT_TRUE ((mbedtls_ct_condition_t) mbedtls_ct_compiler_opaque(UINT64_MAX)) +#else +/* Pointer size <= 32-bit, and no 64-bit MPIs */ +typedef uint32_t mbedtls_ct_condition_t; +typedef uint32_t mbedtls_ct_uint_t; +typedef int32_t mbedtls_ct_int_t; +#define MBEDTLS_CT_SIZE_32 +#define MBEDTLS_CT_TRUE ((mbedtls_ct_condition_t) mbedtls_ct_compiler_opaque(UINT32_MAX)) #endif +#define MBEDTLS_CT_FALSE ((mbedtls_ct_condition_t) mbedtls_ct_compiler_opaque(0)) -#include +/* ============================================================================ + * Boolean operations + */ -/** Turn a value into a mask: - * - if \p value == 0, return the all-bits 0 mask, aka 0 - * - otherwise, return the all-bits 1 mask, aka (unsigned) -1 +/** Convert a number into a mbedtls_ct_condition_t. * - * This function can be used to write constant-time code by replacing branches - * with bit operations using masks. + * \param x Number to convert. * - * \param value The value to analyze. + * \return MBEDTLS_CT_TRUE if \p x != 0, or MBEDTLS_CT_FALSE if \p x == 0 * - * \return Zero if \p value is zero, otherwise all-bits-one. */ -unsigned mbedtls_ct_uint_mask(unsigned value); - -#if defined(MBEDTLS_SSL_SOME_MODES_USE_MAC) || defined(MBEDTLS_SSL_SOME_SUITES_USE_TLS_CBC) || \ - defined(MBEDTLS_NIST_KW_C) || defined(MBEDTLS_CIPHER_MODE_CBC) +static inline mbedtls_ct_condition_t mbedtls_ct_bool(mbedtls_ct_uint_t x); -/** Turn a value into a mask: - * - if \p value == 0, return the all-bits 0 mask, aka 0 - * - otherwise, return the all-bits 1 mask, aka (size_t) -1 +/** Boolean "not equal" operation. * - * This function can be used to write constant-time code by replacing branches - * with bit operations using masks. + * Functionally equivalent to: * - * \param value The value to analyze. + * \p x != \p y * - * \return Zero if \p value is zero, otherwise all-bits-one. + * \param x The first value to analyze. + * \param y The second value to analyze. + * + * \return MBEDTLS_CT_TRUE if \p x != \p y, otherwise MBEDTLS_CT_FALSE. */ -size_t mbedtls_ct_size_mask(size_t value); +static inline mbedtls_ct_condition_t mbedtls_ct_uint_ne(mbedtls_ct_uint_t x, mbedtls_ct_uint_t y); -#endif /* defined(MBEDTLS_SSL_SOME_MODES_USE_MAC) || defined(MBEDTLS_SSL_SOME_SUITES_USE_TLS_CBC) || - defined(MBEDTLS_NIST_KW_C) || defined(MBEDTLS_CIPHER_MODE_CBC) */ +/** Boolean "equals" operation. + * + * Functionally equivalent to: + * + * \p x == \p y + * + * \param x The first value to analyze. + * \param y The second value to analyze. + * + * \return MBEDTLS_CT_TRUE if \p x == \p y, otherwise MBEDTLS_CT_FALSE. + */ +static inline mbedtls_ct_condition_t mbedtls_ct_uint_eq(mbedtls_ct_uint_t x, + mbedtls_ct_uint_t y); -#if defined(MBEDTLS_BIGNUM_C) +/** Boolean "less than" operation. + * + * Functionally equivalent to: + * + * \p x < \p y + * + * \param x The first value to analyze. + * \param y The second value to analyze. + * + * \return MBEDTLS_CT_TRUE if \p x < \p y, otherwise MBEDTLS_CT_FALSE. + */ +static inline mbedtls_ct_condition_t mbedtls_ct_uint_lt(mbedtls_ct_uint_t x, mbedtls_ct_uint_t y); -/** Turn a value into a mask: - * - if \p value == 0, return the all-bits 0 mask, aka 0 - * - otherwise, return the all-bits 1 mask, aka (mbedtls_mpi_uint) -1 +/** Boolean "greater than" operation. * - * This function can be used to write constant-time code by replacing branches - * with bit operations using masks. + * Functionally equivalent to: * - * \param value The value to analyze. + * \p x > \p y * - * \return Zero if \p value is zero, otherwise all-bits-one. + * \param x The first value to analyze. + * \param y The second value to analyze. + * + * \return MBEDTLS_CT_TRUE if \p x > \p y, otherwise MBEDTLS_CT_FALSE. */ -mbedtls_mpi_uint mbedtls_ct_mpi_uint_mask(mbedtls_mpi_uint value); +static inline mbedtls_ct_condition_t mbedtls_ct_uint_gt(mbedtls_ct_uint_t x, + mbedtls_ct_uint_t y); -#endif /* MBEDTLS_BIGNUM_C */ +/** Boolean "greater or equal" operation. + * + * Functionally equivalent to: + * + * \p x >= \p y + * + * \param x The first value to analyze. + * \param y The second value to analyze. + * + * \return MBEDTLS_CT_TRUE if \p x >= \p y, + * otherwise MBEDTLS_CT_FALSE. + */ +static inline mbedtls_ct_condition_t mbedtls_ct_uint_ge(mbedtls_ct_uint_t x, + mbedtls_ct_uint_t y); -#if defined(MBEDTLS_SSL_SOME_SUITES_USE_TLS_CBC) || defined(MBEDTLS_NIST_KW_C) || \ - defined(MBEDTLS_CIPHER_MODE_CBC) +/** Boolean "less than or equal" operation. + * + * Functionally equivalent to: + * + * \p x <= \p y + * + * \param x The first value to analyze. + * \param y The second value to analyze. + * + * \return MBEDTLS_CT_TRUE if \p x <= \p y, + * otherwise MBEDTLS_CT_FALSE. + */ +static inline mbedtls_ct_condition_t mbedtls_ct_uint_le(mbedtls_ct_uint_t x, + mbedtls_ct_uint_t y); -/** Constant-flow mask generation for "greater or equal" comparison: - * - if \p x >= \p y, return all-bits 1, that is (size_t) -1 - * - otherwise, return all bits 0, that is 0 +/** Boolean not-equals operation. + * + * Functionally equivalent to: * - * This function can be used to write constant-time code by replacing branches - * with bit operations using masks. + * \p x != \p y * * \param x The first value to analyze. * \param y The second value to analyze. * - * \return All-bits-one if \p x is greater or equal than \p y, - * otherwise zero. + * \note This is more efficient than mbedtls_ct_uint_ne if both arguments are + * mbedtls_ct_condition_t. + * + * \return MBEDTLS_CT_TRUE if \p x != \p y, + * otherwise MBEDTLS_CT_FALSE. */ -size_t mbedtls_ct_size_mask_ge(size_t x, - size_t y); +static inline mbedtls_ct_condition_t mbedtls_ct_bool_ne(mbedtls_ct_condition_t x, + mbedtls_ct_condition_t y); -#endif /* defined(MBEDTLS_SSL_SOME_SUITES_USE_TLS_CBC) || defined(MBEDTLS_NIST_KW_C) || - defined(MBEDTLS_CIPHER_MODE_CBC) */ +/** Boolean "and" operation. + * + * Functionally equivalent to: + * + * \p x && \p y + * + * \param x The first value to analyze. + * \param y The second value to analyze. + * + * \return MBEDTLS_CT_TRUE if \p x && \p y, + * otherwise MBEDTLS_CT_FALSE. + */ +static inline mbedtls_ct_condition_t mbedtls_ct_bool_and(mbedtls_ct_condition_t x, + mbedtls_ct_condition_t y); -/** Constant-flow boolean "equal" comparison: - * return x == y +/** Boolean "or" operation. + * + * Functionally equivalent to: * - * This is equivalent to \p x == \p y, but is likely to be compiled - * to code using bitwise operation rather than a branch. + * \p x || \p y * * \param x The first value to analyze. * \param y The second value to analyze. * - * \return 1 if \p x equals to \p y, otherwise 0. + * \return MBEDTLS_CT_TRUE if \p x || \p y, + * otherwise MBEDTLS_CT_FALSE. */ -unsigned mbedtls_ct_size_bool_eq(size_t x, - size_t y); +static inline mbedtls_ct_condition_t mbedtls_ct_bool_or(mbedtls_ct_condition_t x, + mbedtls_ct_condition_t y); + +/** Boolean "not" operation. + * + * Functionally equivalent to: + * + * ! \p x + * + * \param x The value to invert + * + * \return MBEDTLS_CT_FALSE if \p x, otherwise MBEDTLS_CT_TRUE. + */ +static inline mbedtls_ct_condition_t mbedtls_ct_bool_not(mbedtls_ct_condition_t x); + + +/* ============================================================================ + * Data selection operations + */ + +/** Choose between two size_t values. + * + * Functionally equivalent to: + * + * condition ? if1 : if0. + * + * \param condition Condition to test. + * \param if1 Value to use if \p condition == MBEDTLS_CT_TRUE. + * \param if0 Value to use if \p condition == MBEDTLS_CT_FALSE. + * + * \return \c if1 if \p condition == MBEDTLS_CT_TRUE, otherwise \c if0. + */ +static inline size_t mbedtls_ct_size_if(mbedtls_ct_condition_t condition, + size_t if1, + size_t if0); + +/** Choose between two unsigned values. + * + * Functionally equivalent to: + * + * condition ? if1 : if0. + * + * \param condition Condition to test. + * \param if1 Value to use if \p condition == MBEDTLS_CT_TRUE. + * \param if0 Value to use if \p condition == MBEDTLS_CT_FALSE. + * + * \return \c if1 if \p condition == MBEDTLS_CT_TRUE, otherwise \c if0. + */ +static inline unsigned mbedtls_ct_uint_if(mbedtls_ct_condition_t condition, + unsigned if1, + unsigned if0); + +/** Choose between two mbedtls_ct_condition_t values. + * + * Functionally equivalent to: + * + * condition ? if1 : if0. + * + * \param condition Condition to test. + * \param if1 Value to use if \p condition == MBEDTLS_CT_TRUE. + * \param if0 Value to use if \p condition == MBEDTLS_CT_FALSE. + * + * \return \c if1 if \p condition == MBEDTLS_CT_TRUE, otherwise \c if0. + */ +static inline mbedtls_ct_condition_t mbedtls_ct_bool_if(mbedtls_ct_condition_t condition, + mbedtls_ct_condition_t if1, + mbedtls_ct_condition_t if0); #if defined(MBEDTLS_BIGNUM_C) -/** Decide if an integer is less than the other, without branches. +/** Choose between two mbedtls_mpi_uint values. * - * This is equivalent to \p x < \p y, but is likely to be compiled - * to code using bitwise operation rather than a branch. + * Functionally equivalent to: * - * \param x The first value to analyze. - * \param y The second value to analyze. + * condition ? if1 : if0. + * + * \param condition Condition to test. + * \param if1 Value to use if \p condition == MBEDTLS_CT_TRUE. + * \param if0 Value to use if \p condition == MBEDTLS_CT_FALSE. + * + * \return \c if1 if \p condition == MBEDTLS_CT_TRUE, otherwise \c if0. + */ +static inline mbedtls_mpi_uint mbedtls_ct_mpi_uint_if(mbedtls_ct_condition_t condition, \ + mbedtls_mpi_uint if1, \ + mbedtls_mpi_uint if0); + +#endif + +/** Choose between an unsigned value and 0. + * + * Functionally equivalent to: + * + * condition ? if1 : 0. * - * \return 1 if \p x is less than \p y, otherwise 0. + * Functionally equivalent to mbedtls_ct_uint_if(condition, if1, 0) but + * results in smaller code size. + * + * \param condition Condition to test. + * \param if1 Value to use if \p condition == MBEDTLS_CT_TRUE. + * + * \return \c if1 if \p condition == MBEDTLS_CT_TRUE, otherwise 0. */ -unsigned mbedtls_ct_mpi_uint_lt(const mbedtls_mpi_uint x, - const mbedtls_mpi_uint y); +static inline unsigned mbedtls_ct_uint_if_else_0(mbedtls_ct_condition_t condition, unsigned if1); -#endif /* MBEDTLS_BIGNUM_C */ +/** Choose between an mbedtls_ct_condition_t and 0. + * + * Functionally equivalent to: + * + * condition ? if1 : 0. + * + * Functionally equivalent to mbedtls_ct_bool_if(condition, if1, 0) but + * results in smaller code size. + * + * \param condition Condition to test. + * \param if1 Value to use if \p condition == MBEDTLS_CT_TRUE. + * + * \return \c if1 if \p condition == MBEDTLS_CT_TRUE, otherwise 0. + */ +static inline mbedtls_ct_condition_t mbedtls_ct_bool_if_else_0(mbedtls_ct_condition_t condition, + mbedtls_ct_condition_t if1); -/** Choose between two integer values without branches. +/** Choose between a size_t value and 0. + * + * Functionally equivalent to: * - * This is equivalent to `condition ? if1 : if0`, but is likely to be compiled - * to code using bitwise operation rather than a branch. + * condition ? if1 : 0. + * + * Functionally equivalent to mbedtls_ct_size_if(condition, if1, 0) but + * results in smaller code size. * * \param condition Condition to test. - * \param if1 Value to use if \p condition is nonzero. - * \param if0 Value to use if \p condition is zero. + * \param if1 Value to use if \p condition == MBEDTLS_CT_TRUE. * - * \return \c if1 if \p condition is nonzero, otherwise \c if0. + * \return \c if1 if \p condition == MBEDTLS_CT_TRUE, otherwise 0. */ -unsigned mbedtls_ct_uint_if(unsigned condition, - unsigned if1, - unsigned if0); +static inline size_t mbedtls_ct_size_if_else_0(mbedtls_ct_condition_t condition, size_t if1); #if defined(MBEDTLS_BIGNUM_C) -/** Conditionally assign a value without branches. +/** Choose between an mbedtls_mpi_uint value and 0. + * + * Functionally equivalent to: * - * This is equivalent to `if ( condition ) dest = src`, but is likely - * to be compiled to code using bitwise operation rather than a branch. + * condition ? if1 : 0. * - * \param n \p dest and \p src must be arrays of limbs of size n. - * \param dest The MPI to conditionally assign to. This must point - * to an initialized MPI. - * \param src The MPI to be assigned from. This must point to an - * initialized MPI. - * \param condition Condition to test, must be 0 or 1. + * Functionally equivalent to mbedtls_ct_mpi_uint_if(condition, if1, 0) but + * results in smaller code size. + * + * \param condition Condition to test. + * \param if1 Value to use if \p condition == MBEDTLS_CT_TRUE. + * + * \return \c if1 if \p condition == MBEDTLS_CT_TRUE, otherwise 0. */ -void mbedtls_ct_mpi_uint_cond_assign(size_t n, - mbedtls_mpi_uint *dest, - const mbedtls_mpi_uint *src, - unsigned char condition); +static inline mbedtls_mpi_uint mbedtls_ct_mpi_uint_if_else_0(mbedtls_ct_condition_t condition, + mbedtls_mpi_uint if1); -#endif /* MBEDTLS_BIGNUM_C */ +#endif -#if defined(MBEDTLS_BASE64_C) +/** Constant-flow char selection + * + * \param low Secret. Bottom of range + * \param high Secret. Top of range + * \param c Secret. Value to compare to range + * \param t Secret. Value to return, if in range + * + * \return \p t if \p low <= \p c <= \p high, 0 otherwise. + */ +static inline unsigned char mbedtls_ct_uchar_in_range_if(unsigned char low, + unsigned char high, + unsigned char c, + unsigned char t); -/** Given a value in the range 0..63, return the corresponding Base64 digit. +/** Choose between two error values. The values must be in the range [-32767..0]. * - * The implementation assumes that letters are consecutive (e.g. ASCII - * but not EBCDIC). + * Functionally equivalent to: * - * \param value A value in the range 0..63. + * condition ? if1 : if0. + * + * \param condition Condition to test. + * \param if1 Value to use if \p condition == MBEDTLS_CT_TRUE. + * \param if0 Value to use if \p condition == MBEDTLS_CT_FALSE. * - * \return A base64 digit converted from \p value. + * \return \c if1 if \p condition == MBEDTLS_CT_TRUE, otherwise \c if0. */ -unsigned char mbedtls_ct_base64_enc_char(unsigned char value); +static inline int mbedtls_ct_error_if(mbedtls_ct_condition_t condition, int if1, int if0); -/** Given a Base64 digit, return its value. +/** Choose between an error value and 0. The error value must be in the range [-32767..0]. * - * If c is not a Base64 digit ('A'..'Z', 'a'..'z', '0'..'9', '+' or '/'), - * return -1. + * Functionally equivalent to: * - * The implementation assumes that letters are consecutive (e.g. ASCII - * but not EBCDIC). + * condition ? if1 : 0. * - * \param c A base64 digit. + * Functionally equivalent to mbedtls_ct_error_if(condition, if1, 0) but + * results in smaller code size. * - * \return The value of the base64 digit \p c. + * \param condition Condition to test. + * \param if1 Value to use if \p condition == MBEDTLS_CT_TRUE. + * + * \return \c if1 if \p condition == MBEDTLS_CT_TRUE, otherwise 0. */ -signed char mbedtls_ct_base64_dec_value(unsigned char c); +static inline int mbedtls_ct_error_if_else_0(mbedtls_ct_condition_t condition, int if1); -#endif /* MBEDTLS_BASE64_C */ +/* ============================================================================ + * Block memory operations + */ + +#if defined(MBEDTLS_PKCS1_V15) && defined(MBEDTLS_RSA_C) && !defined(MBEDTLS_RSA_ALT) -#if defined(MBEDTLS_SSL_SOME_MODES_USE_MAC) +/** Conditionally set a block of memory to zero. + * + * Regardless of the condition, every byte will be read once and written to + * once. + * + * \param condition Secret. Condition to test. + * \param buf Secret. Pointer to the start of the buffer. + * \param len Number of bytes to set to zero. + * + * \warning Unlike mbedtls_platform_zeroize, this does not have the same guarantees + * about not being optimised away if the memory is never read again. + */ +void mbedtls_ct_zeroize_if(mbedtls_ct_condition_t condition, void *buf, size_t len); -/** Conditional memcpy without branches. +/** Shift some data towards the left inside a buffer. * - * This is equivalent to `if ( c1 == c2 ) memcpy(dest, src, len)`, but is likely - * to be compiled to code using bitwise operation rather than a branch. + * Functionally equivalent to: * - * \param dest The pointer to conditionally copy to. - * \param src The pointer to copy from. Shouldn't overlap with \p dest. - * \param len The number of bytes to copy. - * \param c1 The first value to analyze in the condition. - * \param c2 The second value to analyze in the condition. + * memmove(start, start + offset, total - offset); + * memset(start + (total - offset), 0, offset); + * + * Timing independence comes at the expense of performance. + * + * \param start Secret. Pointer to the start of the buffer. + * \param total Total size of the buffer. + * \param offset Secret. Offset from which to copy \p total - \p offset bytes. + */ +void mbedtls_ct_memmove_left(void *start, + size_t total, + size_t offset); + +#endif /* defined(MBEDTLS_PKCS1_V15) && defined(MBEDTLS_RSA_C) && !defined(MBEDTLS_RSA_ALT) */ + +/** Conditional memcpy. + * + * Functionally equivalent to: + * + * if (condition) { + * memcpy(dest, src1, len); + * } else { + * if (src2 != NULL) + * memcpy(dest, src2, len); + * } + * + * It will always read len bytes from src1. + * If src2 != NULL, it will always read len bytes from src2. + * If src2 == NULL, it will instead read len bytes from dest (as if src2 == dest). + * + * \param condition The condition + * \param dest Secret. Destination pointer. + * \param src1 Secret. Pointer to copy from (if \p condition == MBEDTLS_CT_TRUE). + * This may be equal to \p dest, but may not overlap in other ways. + * \param src2 Secret (contents only - may branch to determine if this parameter is NULL). + * Pointer to copy from (if \p condition == MBEDTLS_CT_FALSE and \p src2 is not NULL). May be NULL. + * This may be equal to \p dest, but may not overlap it in other ways. It may overlap with \p src1. + * \param len Number of bytes to copy. */ -void mbedtls_ct_memcpy_if_eq(unsigned char *dest, - const unsigned char *src, - size_t len, - size_t c1, size_t c2); +void mbedtls_ct_memcpy_if(mbedtls_ct_condition_t condition, + unsigned char *dest, + const unsigned char *src1, + const unsigned char *src2, + size_t len + ); -/** Copy data from a secret position with constant flow. +/** Copy data from a secret position. + * + * Functionally equivalent to: + * + * memcpy(dst, src + offset, len) * - * This function copies \p len bytes from \p src_base + \p offset_secret to \p - * dst, with a code flow and memory access pattern that does not depend on \p - * offset_secret, but only on \p offset_min, \p offset_max and \p len. - * Functionally equivalent to `memcpy(dst, src + offset_secret, len)`. + * This function copies \p len bytes from \p src + \p offset to + * \p dst, with a code flow and memory access pattern that does not depend on + * \p offset, but only on \p offset_min, \p offset_max and \p len. * * \note This function reads from \p dest, but the value that * is read does not influence the result and this @@ -231,12 +516,12 @@ void mbedtls_ct_memcpy_if_eq(unsigned char *dest, * positives from static or dynamic analyzers, especially * if \p dest is not initialized. * - * \param dest The destination buffer. This must point to a writable + * \param dest Secret. The destination buffer. This must point to a writable * buffer of at least \p len bytes. - * \param src The base of the source buffer. This must point to a + * \param src Secret. The base of the source buffer. This must point to a * readable buffer of at least \p offset_max + \p len - * bytes. Shouldn't overlap with \p dest. - * \param offset The offset in the source buffer from which to copy. + * bytes. Shouldn't overlap with \p dest + * \param offset Secret. The offset in the source buffer from which to copy. * This must be no less than \p offset_min and no greater * than \p offset_max. * \param offset_min The minimal value of \p offset. @@ -250,90 +535,45 @@ void mbedtls_ct_memcpy_offset(unsigned char *dest, size_t offset_max, size_t len); -/** Compute the HMAC of variable-length data with constant flow. - * - * This function computes the HMAC of the concatenation of \p add_data and \p - * data, and does with a code flow and memory access pattern that does not - * depend on \p data_len_secret, but only on \p min_data_len and \p - * max_data_len. In particular, this function always reads exactly \p - * max_data_len bytes from \p data. - * - * \param ctx The HMAC context. It must have keys configured - * with mbedtls_md_hmac_starts() and use one of the - * following hashes: SHA-384, SHA-256, SHA-1 or MD-5. - * It is reset using mbedtls_md_hmac_reset() after - * the computation is complete to prepare for the - * next computation. - * \param add_data The first part of the message whose HMAC is being - * calculated. This must point to a readable buffer - * of \p add_data_len bytes. - * \param add_data_len The length of \p add_data in bytes. - * \param data The buffer containing the second part of the - * message. This must point to a readable buffer - * of \p max_data_len bytes. - * \param data_len_secret The length of the data to process in \p data. - * This must be no less than \p min_data_len and no - * greater than \p max_data_len. - * \param min_data_len The minimal length of the second part of the - * message, read from \p data. - * \param max_data_len The maximal length of the second part of the - * message, read from \p data. - * \param output The HMAC will be written here. This must point to - * a writable buffer of sufficient size to hold the - * HMAC value. - * - * \retval 0 on success. - * \retval #MBEDTLS_ERR_PLATFORM_HW_ACCEL_FAILED - * The hardware accelerator failed. - */ -int mbedtls_ct_hmac(mbedtls_md_context_t *ctx, - const unsigned char *add_data, - size_t add_data_len, - const unsigned char *data, - size_t data_len_secret, - size_t min_data_len, - size_t max_data_len, - unsigned char *output); - -#endif /* MBEDTLS_SSL_SOME_MODES_USE_MAC */ +/* Documented in include/mbedtls/constant_time.h. a and b are secret. -#if defined(MBEDTLS_PKCS1_V15) && defined(MBEDTLS_RSA_C) && !defined(MBEDTLS_RSA_ALT) + int mbedtls_ct_memcmp(const void *a, + const void *b, + size_t n); + */ + +#if defined(MBEDTLS_NIST_KW_C) + +/** Constant-time buffer comparison without branches. + * + * Similar to mbedtls_ct_memcmp, except that the result only depends on part of + * the input data - differences in the head or tail are ignored. Functionally equivalent to: + * + * memcmp(a + skip_head, b + skip_head, size - skip_head - skip_tail) + * + * Time taken depends on \p n, but not on \p skip_head or \p skip_tail . + * + * Behaviour is undefined if ( \p skip_head + \p skip_tail) > \p n. + * + * \param a Secret. Pointer to the first buffer, containing at least \p n bytes. May not be NULL. + * \param b Secret. Pointer to the second buffer, containing at least \p n bytes. May not be NULL. + * \param n The number of bytes to examine (total size of the buffers). + * \param skip_head Secret. The number of bytes to treat as non-significant at the start of the buffer. + * These bytes will still be read. + * \param skip_tail Secret. The number of bytes to treat as non-significant at the end of the buffer. + * These bytes will still be read. + * + * \return Zero if the contents of the two buffers are the same, otherwise non-zero. + */ +int mbedtls_ct_memcmp_partial(const void *a, + const void *b, + size_t n, + size_t skip_head, + size_t skip_tail); + +#endif -/** This function performs the unpadding part of a PKCS#1 v1.5 decryption - * operation (EME-PKCS1-v1_5 decoding). - * - * \note The return value from this function is a sensitive value - * (this is unusual). #MBEDTLS_ERR_RSA_OUTPUT_TOO_LARGE shouldn't happen - * in a well-written application, but 0 vs #MBEDTLS_ERR_RSA_INVALID_PADDING - * is often a situation that an attacker can provoke and leaking which - * one is the result is precisely the information the attacker wants. - * - * \param mode The mode of operation. This must be either - * #MBEDTLS_RSA_PRIVATE or #MBEDTLS_RSA_PUBLIC (deprecated). - * \param input The input buffer which is the payload inside PKCS#1v1.5 - * encryption padding, called the "encoded message EM" - * by the terminology. - * \param ilen The length of the payload in the \p input buffer. - * \param output The buffer for the payload, called "message M" by the - * PKCS#1 terminology. This must be a writable buffer of - * length \p output_max_len bytes. - * \param olen The address at which to store the length of - * the payload. This must not be \c NULL. - * \param output_max_len The length in bytes of the output buffer \p output. - * - * \return \c 0 on success. - * \return #MBEDTLS_ERR_RSA_OUTPUT_TOO_LARGE - * The output buffer is too small for the unpadded payload. - * \return #MBEDTLS_ERR_RSA_INVALID_PADDING - * The input doesn't contain properly formatted padding. - */ -int mbedtls_ct_rsaes_pkcs1_v15_unpadding(int mode, - unsigned char *input, - size_t ilen, - unsigned char *output, - size_t output_max_len, - size_t *olen); - -#endif /* MBEDTLS_PKCS1_V15 && MBEDTLS_RSA_C && ! MBEDTLS_RSA_ALT */ +/* Include the implementation of static inline functions above. */ +#include "constant_time_impl.h" #endif /* MBEDTLS_CONSTANT_TIME_INTERNAL_H */ diff --git a/vendor/mbedtls/library/constant_time_invasive.h b/vendor/mbedtls/library/constant_time_invasive.h deleted file mode 100644 index c176b28ffd..0000000000 --- a/vendor/mbedtls/library/constant_time_invasive.h +++ /dev/null @@ -1,51 +0,0 @@ -/** - * \file constant_time_invasive.h - * - * \brief Constant-time module: interfaces for invasive testing only. - * - * The interfaces in this file are intended for testing purposes only. - * They SHOULD NOT be made available in library integrations except when - * building the library for testing. - */ -/* - * Copyright The Mbed TLS Contributors - * SPDX-License-Identifier: Apache-2.0 - * - * Licensed under the Apache License, Version 2.0 (the "License"); you may - * not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT - * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -#ifndef MBEDTLS_CONSTANT_TIME_INVASIVE_H -#define MBEDTLS_CONSTANT_TIME_INVASIVE_H - -#include "common.h" - -#if defined(MBEDTLS_TEST_HOOKS) - -/** Turn a value into a mask: - * - if \p low <= \p c <= \p high, - * return the all-bits 1 mask, aka (unsigned) -1 - * - otherwise, return the all-bits 0 mask, aka 0 - * - * \param low The value to analyze. - * \param high The value to analyze. - * \param c The value to analyze. - * - * \return All-bits-one if \p low <= \p c <= \p high, otherwise zero. - */ -unsigned char mbedtls_ct_uchar_mask_of_range(unsigned char low, - unsigned char high, - unsigned char c); - -#endif /* MBEDTLS_TEST_HOOKS */ - -#endif /* MBEDTLS_CONSTANT_TIME_INVASIVE_H */ diff --git a/vendor/mbedtls/library/ctr.h b/vendor/mbedtls/library/ctr.h new file mode 100644 index 0000000000..aa48fb9e70 --- /dev/null +++ b/vendor/mbedtls/library/ctr.h @@ -0,0 +1,35 @@ +/** + * \file ctr.h + * + * \brief This file contains common functionality for counter algorithms. + * + * Copyright The Mbed TLS Contributors + * SPDX-License-Identifier: Apache-2.0 OR GPL-2.0-or-later + */ + +#ifndef MBEDTLS_CTR_H +#define MBEDTLS_CTR_H + +#include "common.h" + +/** + * \brief Increment a big-endian 16-byte value. + * This is quite performance-sensitive for AES-CTR and CTR-DRBG. + * + * \param n A 16-byte value to be incremented. + */ +static inline void mbedtls_ctr_increment_counter(uint8_t n[16]) +{ + // The 32-bit version seems to perform about the same as a 64-bit version + // on 64-bit architectures, so no need to define a 64-bit version. + for (int i = 3;; i--) { + uint32_t x = MBEDTLS_GET_UINT32_BE(n, i << 2); + x += 1; + MBEDTLS_PUT_UINT32_BE(x, n, i << 2); + if (x != 0 || i == 0) { + break; + } + } +} + +#endif /* MBEDTLS_CTR_H */ diff --git a/vendor/mbedtls/library/ctr_drbg.c b/vendor/mbedtls/library/ctr_drbg.c index 6f553dca66..66d9d28c58 100644 --- a/vendor/mbedtls/library/ctr_drbg.c +++ b/vendor/mbedtls/library/ctr_drbg.c @@ -2,19 +2,7 @@ * CTR_DRBG implementation based on AES-256 (NIST SP 800-90) * * Copyright The Mbed TLS Contributors - * SPDX-License-Identifier: Apache-2.0 - * - * Licensed under the Apache License, Version 2.0 (the "License"); you may - * not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT - * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. + * SPDX-License-Identifier: Apache-2.0 OR GPL-2.0-or-later */ /* * The NIST SP 800-90 DRBGs are described in the following publication. @@ -26,25 +14,71 @@ #if defined(MBEDTLS_CTR_DRBG_C) +#include "ctr.h" #include "mbedtls/ctr_drbg.h" #include "mbedtls/platform_util.h" #include "mbedtls/error.h" -#include #include #if defined(MBEDTLS_FS_IO) #include #endif +/* Using error translation functions from PSA to MbedTLS */ +#if !defined(MBEDTLS_AES_C) +#include "psa_util_internal.h" +#endif + #include "mbedtls/platform.h" +#if !defined(MBEDTLS_AES_C) +static psa_status_t ctr_drbg_setup_psa_context(mbedtls_ctr_drbg_psa_context *psa_ctx, + unsigned char *key, size_t key_len) +{ + psa_key_attributes_t key_attr = PSA_KEY_ATTRIBUTES_INIT; + psa_status_t status; + + psa_set_key_usage_flags(&key_attr, PSA_KEY_USAGE_ENCRYPT); + psa_set_key_algorithm(&key_attr, PSA_ALG_ECB_NO_PADDING); + psa_set_key_type(&key_attr, PSA_KEY_TYPE_AES); + status = psa_import_key(&key_attr, key, key_len, &psa_ctx->key_id); + if (status != PSA_SUCCESS) { + goto exit; + } + + status = psa_cipher_encrypt_setup(&psa_ctx->operation, psa_ctx->key_id, PSA_ALG_ECB_NO_PADDING); + if (status != PSA_SUCCESS) { + goto exit; + } + +exit: + psa_reset_key_attributes(&key_attr); + return status; +} + +static void ctr_drbg_destroy_psa_contex(mbedtls_ctr_drbg_psa_context *psa_ctx) +{ + psa_cipher_abort(&psa_ctx->operation); + psa_destroy_key(psa_ctx->key_id); + + psa_ctx->operation = psa_cipher_operation_init(); + psa_ctx->key_id = MBEDTLS_SVC_KEY_ID_INIT; +} +#endif + /* * CTR_DRBG context initialization */ void mbedtls_ctr_drbg_init(mbedtls_ctr_drbg_context *ctx) { memset(ctx, 0, sizeof(mbedtls_ctr_drbg_context)); +#if defined(MBEDTLS_AES_C) + mbedtls_aes_init(&ctx->aes_ctx); +#else + ctx->psa_ctx.key_id = MBEDTLS_SVC_KEY_ID_INIT; + ctx->psa_ctx.operation = psa_cipher_operation_init(); +#endif /* Indicate that the entropy nonce length is not set explicitly. * See mbedtls_ctr_drbg_set_nonce_len(). */ ctx->reseed_counter = -1; @@ -68,7 +102,11 @@ void mbedtls_ctr_drbg_free(mbedtls_ctr_drbg_context *ctx) mbedtls_mutex_free(&ctx->mutex); } #endif +#if defined(MBEDTLS_AES_C) mbedtls_aes_free(&ctx->aes_ctx); +#else + ctr_drbg_destroy_psa_contex(&ctx->psa_ctx); +#endif mbedtls_platform_zeroize(ctx, sizeof(mbedtls_ctr_drbg_context)); ctx->reseed_interval = MBEDTLS_CTR_DRBG_RESEED_INTERVAL; ctx->reseed_counter = -1; @@ -98,14 +136,13 @@ int mbedtls_ctr_drbg_set_nonce_len(mbedtls_ctr_drbg_context *ctx, if (len > MBEDTLS_CTR_DRBG_MAX_SEED_INPUT) { return MBEDTLS_ERR_CTR_DRBG_INPUT_TOO_BIG; } -#if SIZE_MAX > INT_MAX + /* This shouldn't be an issue because * MBEDTLS_CTR_DRBG_MAX_SEED_INPUT < INT_MAX in any sensible * configuration, but make sure anyway. */ if (len > INT_MAX) { return MBEDTLS_ERR_CTR_DRBG_INPUT_TOO_BIG; } -#endif /* For backward compatibility with Mbed TLS <= 2.19, store the * entropy nonce length in a field that already exists, but isn't @@ -130,8 +167,17 @@ static int block_cipher_df(unsigned char *output, unsigned char key[MBEDTLS_CTR_DRBG_KEYSIZE]; unsigned char chain[MBEDTLS_CTR_DRBG_BLOCKSIZE]; unsigned char *p, *iv; - mbedtls_aes_context aes_ctx; int ret = 0; +#if defined(MBEDTLS_AES_C) + mbedtls_aes_context aes_ctx; +#else + psa_status_t status; + size_t tmp_len; + mbedtls_ctr_drbg_psa_context psa_ctx; + + psa_ctx.key_id = MBEDTLS_SVC_KEY_ID_INIT; + psa_ctx.operation = psa_cipher_operation_init(); +#endif int i, j; size_t buf_len, use_len; @@ -142,7 +188,6 @@ static int block_cipher_df(unsigned char *output, memset(buf, 0, MBEDTLS_CTR_DRBG_MAX_SEED_INPUT + MBEDTLS_CTR_DRBG_BLOCKSIZE + 16); - mbedtls_aes_init(&aes_ctx); /* * Construct IV (16 bytes) and S in buffer @@ -164,10 +209,20 @@ static int block_cipher_df(unsigned char *output, key[i] = i; } +#if defined(MBEDTLS_AES_C) + mbedtls_aes_init(&aes_ctx); + if ((ret = mbedtls_aes_setkey_enc(&aes_ctx, key, MBEDTLS_CTR_DRBG_KEYBITS)) != 0) { goto exit; } +#else + status = ctr_drbg_setup_psa_context(&psa_ctx, key, sizeof(key)); + if (status != PSA_SUCCESS) { + ret = psa_generic_status_to_mbedtls(status); + goto exit; + } +#endif /* * Reduce data to MBEDTLS_CTR_DRBG_SEEDLEN bytes of data @@ -178,17 +233,24 @@ static int block_cipher_df(unsigned char *output, use_len = buf_len; while (use_len > 0) { - for (i = 0; i < MBEDTLS_CTR_DRBG_BLOCKSIZE; i++) { - chain[i] ^= p[i]; - } + mbedtls_xor(chain, chain, p, MBEDTLS_CTR_DRBG_BLOCKSIZE); p += MBEDTLS_CTR_DRBG_BLOCKSIZE; use_len -= (use_len >= MBEDTLS_CTR_DRBG_BLOCKSIZE) ? MBEDTLS_CTR_DRBG_BLOCKSIZE : use_len; +#if defined(MBEDTLS_AES_C) if ((ret = mbedtls_aes_crypt_ecb(&aes_ctx, MBEDTLS_AES_ENCRYPT, chain, chain)) != 0) { goto exit; } +#else + status = psa_cipher_update(&psa_ctx.operation, chain, MBEDTLS_CTR_DRBG_BLOCKSIZE, + chain, MBEDTLS_CTR_DRBG_BLOCKSIZE, &tmp_len); + if (status != PSA_SUCCESS) { + ret = psa_generic_status_to_mbedtls(status); + goto exit; + } +#endif } memcpy(tmp + j, chain, MBEDTLS_CTR_DRBG_BLOCKSIZE); @@ -202,23 +264,46 @@ static int block_cipher_df(unsigned char *output, /* * Do final encryption with reduced data */ +#if defined(MBEDTLS_AES_C) if ((ret = mbedtls_aes_setkey_enc(&aes_ctx, tmp, MBEDTLS_CTR_DRBG_KEYBITS)) != 0) { goto exit; } +#else + ctr_drbg_destroy_psa_contex(&psa_ctx); + + status = ctr_drbg_setup_psa_context(&psa_ctx, tmp, MBEDTLS_CTR_DRBG_KEYSIZE); + if (status != PSA_SUCCESS) { + ret = psa_generic_status_to_mbedtls(status); + goto exit; + } +#endif iv = tmp + MBEDTLS_CTR_DRBG_KEYSIZE; p = output; for (j = 0; j < MBEDTLS_CTR_DRBG_SEEDLEN; j += MBEDTLS_CTR_DRBG_BLOCKSIZE) { +#if defined(MBEDTLS_AES_C) if ((ret = mbedtls_aes_crypt_ecb(&aes_ctx, MBEDTLS_AES_ENCRYPT, iv, iv)) != 0) { goto exit; } +#else + status = psa_cipher_update(&psa_ctx.operation, iv, MBEDTLS_CTR_DRBG_BLOCKSIZE, + iv, MBEDTLS_CTR_DRBG_BLOCKSIZE, &tmp_len); + if (status != PSA_SUCCESS) { + ret = psa_generic_status_to_mbedtls(status); + goto exit; + } +#endif memcpy(p, iv, MBEDTLS_CTR_DRBG_BLOCKSIZE); p += MBEDTLS_CTR_DRBG_BLOCKSIZE; } exit: +#if defined(MBEDTLS_AES_C) mbedtls_aes_free(&aes_ctx); +#else + ctr_drbg_destroy_psa_contex(&psa_ctx); +#endif /* * tidy up the stack */ @@ -249,8 +334,12 @@ static int ctr_drbg_update_internal(mbedtls_ctr_drbg_context *ctx, { unsigned char tmp[MBEDTLS_CTR_DRBG_SEEDLEN]; unsigned char *p = tmp; - int i, j; + int j; int ret = 0; +#if !defined(MBEDTLS_AES_C) + psa_status_t status; + size_t tmp_len; +#endif memset(tmp, 0, MBEDTLS_CTR_DRBG_SEEDLEN); @@ -258,34 +347,47 @@ static int ctr_drbg_update_internal(mbedtls_ctr_drbg_context *ctx, /* * Increase counter */ - for (i = MBEDTLS_CTR_DRBG_BLOCKSIZE; i > 0; i--) { - if (++ctx->counter[i - 1] != 0) { - break; - } - } + mbedtls_ctr_increment_counter(ctx->counter); /* * Crypt counter block */ +#if defined(MBEDTLS_AES_C) if ((ret = mbedtls_aes_crypt_ecb(&ctx->aes_ctx, MBEDTLS_AES_ENCRYPT, ctx->counter, p)) != 0) { goto exit; } +#else + status = psa_cipher_update(&ctx->psa_ctx.operation, ctx->counter, sizeof(ctx->counter), + p, MBEDTLS_CTR_DRBG_BLOCKSIZE, &tmp_len); + if (status != PSA_SUCCESS) { + ret = psa_generic_status_to_mbedtls(status); + goto exit; + } +#endif p += MBEDTLS_CTR_DRBG_BLOCKSIZE; } - for (i = 0; i < MBEDTLS_CTR_DRBG_SEEDLEN; i++) { - tmp[i] ^= data[i]; - } + mbedtls_xor(tmp, tmp, data, MBEDTLS_CTR_DRBG_SEEDLEN); /* * Update key and counter */ +#if defined(MBEDTLS_AES_C) if ((ret = mbedtls_aes_setkey_enc(&ctx->aes_ctx, tmp, MBEDTLS_CTR_DRBG_KEYBITS)) != 0) { goto exit; } +#else + ctr_drbg_destroy_psa_contex(&ctx->psa_ctx); + + status = ctr_drbg_setup_psa_context(&ctx->psa_ctx, tmp, MBEDTLS_CTR_DRBG_KEYSIZE); + if (status != PSA_SUCCESS) { + ret = psa_generic_status_to_mbedtls(status); + goto exit; + } +#endif memcpy(ctx->counter, tmp + MBEDTLS_CTR_DRBG_KEYSIZE, MBEDTLS_CTR_DRBG_BLOCKSIZE); @@ -306,9 +408,9 @@ static int ctr_drbg_update_internal(mbedtls_ctr_drbg_context *ctx, * and with outputs * ctx = initial_working_state */ -int mbedtls_ctr_drbg_update_ret(mbedtls_ctr_drbg_context *ctx, - const unsigned char *additional, - size_t add_len) +int mbedtls_ctr_drbg_update(mbedtls_ctr_drbg_context *ctx, + const unsigned char *additional, + size_t add_len) { unsigned char add_input[MBEDTLS_CTR_DRBG_SEEDLEN]; int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED; @@ -329,20 +431,6 @@ int mbedtls_ctr_drbg_update_ret(mbedtls_ctr_drbg_context *ctx, return ret; } -#if !defined(MBEDTLS_DEPRECATED_REMOVED) -void mbedtls_ctr_drbg_update(mbedtls_ctr_drbg_context *ctx, - const unsigned char *additional, - size_t add_len) -{ - /* MAX_INPUT would be more logical here, but we have to match - * block_cipher_df()'s limits since we can't propagate errors */ - if (add_len > MBEDTLS_CTR_DRBG_MAX_SEED_INPUT) { - add_len = MBEDTLS_CTR_DRBG_MAX_SEED_INPUT; - } - (void) mbedtls_ctr_drbg_update_ret(ctx, additional, add_len); -} -#endif /* MBEDTLS_DEPRECATED_REMOVED */ - /* CTR_DRBG_Reseed with derivation function (SP 800-90A §10.2.1.4.2) * mbedtls_ctr_drbg_reseed(ctx, additional, len, nonce_len) * implements @@ -461,8 +549,6 @@ int mbedtls_ctr_drbg_seed(mbedtls_ctr_drbg_context *ctx, mbedtls_mutex_init(&ctx->mutex); #endif - mbedtls_aes_init(&ctx->aes_ctx); - ctx->f_entropy = f_entropy; ctx->p_entropy = p_entropy; @@ -478,10 +564,20 @@ int mbedtls_ctr_drbg_seed(mbedtls_ctr_drbg_context *ctx, good_nonce_len(ctx->entropy_len)); /* Initialize with an empty key. */ +#if defined(MBEDTLS_AES_C) if ((ret = mbedtls_aes_setkey_enc(&ctx->aes_ctx, key, MBEDTLS_CTR_DRBG_KEYBITS)) != 0) { return ret; } +#else + psa_status_t status; + + status = ctr_drbg_setup_psa_context(&ctx->psa_ctx, key, MBEDTLS_CTR_DRBG_KEYSIZE); + if (status != PSA_SUCCESS) { + ret = psa_generic_status_to_mbedtls(status); + return status; + } +#endif /* Do the initial seeding. */ if ((ret = mbedtls_ctr_drbg_reseed_internal(ctx, custom, len, @@ -516,10 +612,11 @@ int mbedtls_ctr_drbg_random_with_add(void *p_rng, { int ret = 0; mbedtls_ctr_drbg_context *ctx = (mbedtls_ctr_drbg_context *) p_rng; - unsigned char add_input[MBEDTLS_CTR_DRBG_SEEDLEN]; unsigned char *p = output; - unsigned char tmp[MBEDTLS_CTR_DRBG_BLOCKSIZE]; - int i; + struct { + unsigned char add_input[MBEDTLS_CTR_DRBG_SEEDLEN]; + unsigned char tmp[MBEDTLS_CTR_DRBG_BLOCKSIZE]; + } locals; size_t use_len; if (output_len > MBEDTLS_CTR_DRBG_MAX_REQUEST) { @@ -530,7 +627,7 @@ int mbedtls_ctr_drbg_random_with_add(void *p_rng, return MBEDTLS_ERR_CTR_DRBG_INPUT_TOO_BIG; } - memset(add_input, 0, MBEDTLS_CTR_DRBG_SEEDLEN); + memset(locals.add_input, 0, MBEDTLS_CTR_DRBG_SEEDLEN); if (ctx->reseed_counter > ctx->reseed_interval || ctx->prediction_resistance) { @@ -541,51 +638,58 @@ int mbedtls_ctr_drbg_random_with_add(void *p_rng, } if (add_len > 0) { - if ((ret = block_cipher_df(add_input, additional, add_len)) != 0) { + if ((ret = block_cipher_df(locals.add_input, additional, add_len)) != 0) { goto exit; } - if ((ret = ctr_drbg_update_internal(ctx, add_input)) != 0) { + if ((ret = ctr_drbg_update_internal(ctx, locals.add_input)) != 0) { goto exit; } } while (output_len > 0) { /* - * Increase counter + * Increase counter (treat it as a 128-bit big-endian integer). */ - for (i = MBEDTLS_CTR_DRBG_BLOCKSIZE; i > 0; i--) { - if (++ctx->counter[i - 1] != 0) { - break; - } - } + mbedtls_ctr_increment_counter(ctx->counter); /* * Crypt counter block */ +#if defined(MBEDTLS_AES_C) if ((ret = mbedtls_aes_crypt_ecb(&ctx->aes_ctx, MBEDTLS_AES_ENCRYPT, - ctx->counter, tmp)) != 0) { + ctx->counter, locals.tmp)) != 0) { goto exit; } +#else + psa_status_t status; + size_t tmp_len; + + status = psa_cipher_update(&ctx->psa_ctx.operation, ctx->counter, sizeof(ctx->counter), + locals.tmp, MBEDTLS_CTR_DRBG_BLOCKSIZE, &tmp_len); + if (status != PSA_SUCCESS) { + ret = psa_generic_status_to_mbedtls(status); + goto exit; + } +#endif use_len = (output_len > MBEDTLS_CTR_DRBG_BLOCKSIZE) ? MBEDTLS_CTR_DRBG_BLOCKSIZE : output_len; /* * Copy random block to destination */ - memcpy(p, tmp, use_len); + memcpy(p, locals.tmp, use_len); p += use_len; output_len -= use_len; } - if ((ret = ctr_drbg_update_internal(ctx, add_input)) != 0) { + if ((ret = ctr_drbg_update_internal(ctx, locals.add_input)) != 0) { goto exit; } ctx->reseed_counter++; exit: - mbedtls_platform_zeroize(add_input, sizeof(add_input)); - mbedtls_platform_zeroize(tmp, sizeof(tmp)); + mbedtls_platform_zeroize(&locals, sizeof(locals)); return ret; } @@ -624,6 +728,9 @@ int mbedtls_ctr_drbg_write_seed_file(mbedtls_ctr_drbg_context *ctx, return MBEDTLS_ERR_CTR_DRBG_FILE_IO_ERROR; } + /* Ensure no stdio buffering of secrets, as such buffers cannot be wiped. */ + mbedtls_setbuf(f, NULL); + if ((ret = mbedtls_ctr_drbg_random(ctx, buf, MBEDTLS_CTR_DRBG_MAX_INPUT)) != 0) { goto exit; @@ -656,6 +763,9 @@ int mbedtls_ctr_drbg_update_seed_file(mbedtls_ctr_drbg_context *ctx, return MBEDTLS_ERR_CTR_DRBG_FILE_IO_ERROR; } + /* Ensure no stdio buffering of secrets, as such buffers cannot be wiped. */ + mbedtls_setbuf(f, NULL); + n = fread(buf, 1, sizeof(buf), f); if (fread(&c, 1, 1, f) != 0) { ret = MBEDTLS_ERR_CTR_DRBG_INPUT_TOO_BIG; @@ -668,7 +778,7 @@ int mbedtls_ctr_drbg_update_seed_file(mbedtls_ctr_drbg_context *ctx, fclose(f); f = NULL; - ret = mbedtls_ctr_drbg_update_ret(ctx, buf, n); + ret = mbedtls_ctr_drbg_update(ctx, buf, n); exit: mbedtls_platform_zeroize(buf, sizeof(buf)); diff --git a/vendor/mbedtls/library/debug.c b/vendor/mbedtls/library/debug.c index 3e794b5565..c36ed3c5c2 100644 --- a/vendor/mbedtls/library/debug.c +++ b/vendor/mbedtls/library/debug.c @@ -2,19 +2,7 @@ * Debugging routines * * Copyright The Mbed TLS Contributors - * SPDX-License-Identifier: Apache-2.0 - * - * Licensed under the Apache License, Version 2.0 (the "License"); you may - * not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT - * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. + * SPDX-License-Identifier: Apache-2.0 OR GPL-2.0-or-later */ #include "common.h" @@ -23,7 +11,7 @@ #include "mbedtls/platform.h" -#include "mbedtls/debug.h" +#include "debug_internal.h" #include "mbedtls/error.h" #include @@ -112,7 +100,7 @@ void mbedtls_debug_print_ret(const mbedtls_ssl_context *ssl, int level, /* * With non-blocking I/O and examples that just retry immediately, * the logs would be quickly flooded with WANT_READ, so ignore that. - * Don't ignore WANT_WRITE however, since is is usually rare. + * Don't ignore WANT_WRITE however, since it is usually rare. */ if (ret == MBEDTLS_ERR_SSL_WANT_READ) { return; @@ -144,7 +132,6 @@ void mbedtls_debug_print_buf(const mbedtls_ssl_context *ssl, int level, debug_send_line(ssl, level, file, line, str); - idx = 0; memset(txt, 0, sizeof(txt)); for (i = 0; i < len; i++) { if (i >= 4096) { @@ -180,7 +167,7 @@ void mbedtls_debug_print_buf(const mbedtls_ssl_context *ssl, int level, } } -#if defined(MBEDTLS_ECP_C) +#if defined(MBEDTLS_ECP_LIGHT) void mbedtls_debug_print_ecp(const mbedtls_ssl_context *ssl, int level, const char *file, int line, const char *text, const mbedtls_ecp_point *X) @@ -200,7 +187,79 @@ void mbedtls_debug_print_ecp(const mbedtls_ssl_context *ssl, int level, mbedtls_snprintf(str, sizeof(str), "%s(Y)", text); mbedtls_debug_print_mpi(ssl, level, file, line, str, &X->Y); } -#endif /* MBEDTLS_ECP_C */ +#endif /* MBEDTLS_ECP_LIGHT */ + +#if defined(MBEDTLS_PK_USE_PSA_EC_DATA) +static void mbedtls_debug_print_ec_coord(const mbedtls_ssl_context *ssl, int level, + const char *file, int line, const char *text, + const unsigned char *buf, size_t len) +{ + char str[DEBUG_BUF_SIZE]; + size_t i, idx = 0; + + mbedtls_snprintf(str + idx, sizeof(str) - idx, "value of '%s' (%u bits) is:\n", + text, (unsigned int) len * 8); + + debug_send_line(ssl, level, file, line, str); + + for (i = 0; i < len; i++) { + if (i >= 4096) { + break; + } + + if (i % 16 == 0) { + if (i > 0) { + mbedtls_snprintf(str + idx, sizeof(str) - idx, "\n"); + debug_send_line(ssl, level, file, line, str); + + idx = 0; + } + } + + idx += mbedtls_snprintf(str + idx, sizeof(str) - idx, " %02x", + (unsigned int) buf[i]); + } + + if (len > 0) { + for (/* i = i */; i % 16 != 0; i++) { + idx += mbedtls_snprintf(str + idx, sizeof(str) - idx, " "); + } + + mbedtls_snprintf(str + idx, sizeof(str) - idx, "\n"); + debug_send_line(ssl, level, file, line, str); + } +} + +void mbedtls_debug_print_psa_ec(const mbedtls_ssl_context *ssl, int level, + const char *file, int line, + const char *text, const mbedtls_pk_context *pk) +{ + char str[DEBUG_BUF_SIZE]; + const uint8_t *coord_start; + size_t coord_len; + + if (NULL == ssl || + NULL == ssl->conf || + NULL == ssl->conf->f_dbg || + level > debug_threshold) { + return; + } + + /* For the description of pk->pk_raw content please refer to the description + * psa_export_public_key() function. */ + coord_len = (pk->pub_raw_len - 1)/2; + + /* X coordinate */ + coord_start = pk->pub_raw + 1; + mbedtls_snprintf(str, sizeof(str), "%s(X)", text); + mbedtls_debug_print_ec_coord(ssl, level, file, line, str, coord_start, coord_len); + + /* Y coordinate */ + coord_start = coord_start + coord_len; + mbedtls_snprintf(str, sizeof(str), "%s(Y)", text); + mbedtls_debug_print_ec_coord(ssl, level, file, line, str, coord_start, coord_len); +} +#endif /* MBEDTLS_PK_USE_PSA_EC_DATA */ #if defined(MBEDTLS_BIGNUM_C) void mbedtls_debug_print_mpi(const mbedtls_ssl_context *ssl, int level, @@ -253,7 +312,7 @@ void mbedtls_debug_print_mpi(const mbedtls_ssl_context *ssl, int level, } #endif /* MBEDTLS_BIGNUM_C */ -#if defined(MBEDTLS_X509_CRT_PARSE_C) +#if defined(MBEDTLS_X509_CRT_PARSE_C) && !defined(MBEDTLS_X509_REMOVE_INFO) static void debug_print_pk(const mbedtls_ssl_context *ssl, int level, const char *file, int line, const char *text, const mbedtls_pk_context *pk) @@ -278,14 +337,21 @@ static void debug_print_pk(const mbedtls_ssl_context *ssl, int level, mbedtls_snprintf(name, sizeof(name), "%s%s", text, items[i].name); name[sizeof(name) - 1] = '\0'; +#if defined(MBEDTLS_RSA_C) if (items[i].type == MBEDTLS_PK_DEBUG_MPI) { mbedtls_debug_print_mpi(ssl, level, file, line, name, items[i].value); } else -#if defined(MBEDTLS_ECP_C) +#endif /* MBEDTLS_RSA_C */ +#if defined(MBEDTLS_ECP_LIGHT) if (items[i].type == MBEDTLS_PK_DEBUG_ECP) { mbedtls_debug_print_ecp(ssl, level, file, line, name, items[i].value); } else -#endif +#endif /* MBEDTLS_ECP_LIGHT */ +#if defined(MBEDTLS_PK_USE_PSA_EC_DATA) + if (items[i].type == MBEDTLS_PK_DEBUG_PSA_EC) { + mbedtls_debug_print_psa_ec(ssl, level, file, line, name, items[i].value); + } else +#endif /* MBEDTLS_PK_USE_PSA_EC_DATA */ { debug_send_line(ssl, level, file, line, "should not happen\n"); } } @@ -300,7 +366,7 @@ static void debug_print_line_by_line(const mbedtls_ssl_context *ssl, int level, start = text; for (cur = text; *cur != '\0'; cur++) { if (*cur == '\n') { - size_t len = cur - start + 1; + size_t len = (size_t) (cur - start) + 1; if (len > DEBUG_BUF_SIZE - 1) { len = DEBUG_BUF_SIZE - 1; } @@ -344,9 +410,10 @@ void mbedtls_debug_print_crt(const mbedtls_ssl_context *ssl, int level, crt = crt->next; } } -#endif /* MBEDTLS_X509_CRT_PARSE_C */ +#endif /* MBEDTLS_X509_CRT_PARSE_C && MBEDTLS_X509_REMOVE_INFO */ -#if defined(MBEDTLS_ECDH_C) +#if defined(MBEDTLS_KEY_EXCHANGE_SOME_ECDH_OR_ECDHE_ANY_ENABLED) && \ + defined(MBEDTLS_ECDH_C) static void mbedtls_debug_printf_ecdh_internal(const mbedtls_ssl_context *ssl, int level, const char *file, int line, @@ -392,6 +459,7 @@ void mbedtls_debug_printf_ecdh(const mbedtls_ssl_context *ssl, int level, } #endif } -#endif /* MBEDTLS_ECDH_C */ +#endif /* MBEDTLS_KEY_EXCHANGE_SOME_ECDH_OR_ECDHE_ANY_ENABLED && + MBEDTLS_ECDH_C */ #endif /* MBEDTLS_DEBUG_C */ diff --git a/vendor/mbedtls/library/debug_internal.h b/vendor/mbedtls/library/debug_internal.h new file mode 100644 index 0000000000..4523b4633a --- /dev/null +++ b/vendor/mbedtls/library/debug_internal.h @@ -0,0 +1,172 @@ +/** + * \file debug_internal.h + * + * \brief Internal part of the public "debug.h". + */ +/* + * Copyright The Mbed TLS Contributors + * SPDX-License-Identifier: Apache-2.0 OR GPL-2.0-or-later + */ +#ifndef MBEDTLS_DEBUG_INTERNAL_H +#define MBEDTLS_DEBUG_INTERNAL_H + +#include "mbedtls/debug.h" + +/** + * \brief Print a message to the debug output. This function is always used + * through the MBEDTLS_SSL_DEBUG_MSG() macro, which supplies the ssl + * context, file and line number parameters. + * + * \param ssl SSL context + * \param level error level of the debug message + * \param file file the message has occurred in + * \param line line number the message has occurred at + * \param format format specifier, in printf format + * \param ... variables used by the format specifier + * + * \attention This function is intended for INTERNAL usage within the + * library only. + */ +void mbedtls_debug_print_msg(const mbedtls_ssl_context *ssl, int level, + const char *file, int line, + const char *format, ...) MBEDTLS_PRINTF_ATTRIBUTE(5, 6); + +/** + * \brief Print the return value of a function to the debug output. This + * function is always used through the MBEDTLS_SSL_DEBUG_RET() macro, + * which supplies the ssl context, file and line number parameters. + * + * \param ssl SSL context + * \param level error level of the debug message + * \param file file the error has occurred in + * \param line line number the error has occurred in + * \param text the name of the function that returned the error + * \param ret the return code value + * + * \attention This function is intended for INTERNAL usage within the + * library only. + */ +void mbedtls_debug_print_ret(const mbedtls_ssl_context *ssl, int level, + const char *file, int line, + const char *text, int ret); + +/** + * \brief Output a buffer of size len bytes to the debug output. This function + * is always used through the MBEDTLS_SSL_DEBUG_BUF() macro, + * which supplies the ssl context, file and line number parameters. + * + * \param ssl SSL context + * \param level error level of the debug message + * \param file file the error has occurred in + * \param line line number the error has occurred in + * \param text a name or label for the buffer being dumped. Normally the + * variable or buffer name + * \param buf the buffer to be outputted + * \param len length of the buffer + * + * \attention This function is intended for INTERNAL usage within the + * library only. + */ +void mbedtls_debug_print_buf(const mbedtls_ssl_context *ssl, int level, + const char *file, int line, const char *text, + const unsigned char *buf, size_t len); + +#if defined(MBEDTLS_BIGNUM_C) +/** + * \brief Print a MPI variable to the debug output. This function is always + * used through the MBEDTLS_SSL_DEBUG_MPI() macro, which supplies the + * ssl context, file and line number parameters. + * + * \param ssl SSL context + * \param level error level of the debug message + * \param file file the error has occurred in + * \param line line number the error has occurred in + * \param text a name or label for the MPI being output. Normally the + * variable name + * \param X the MPI variable + * + * \attention This function is intended for INTERNAL usage within the + * library only. + */ +void mbedtls_debug_print_mpi(const mbedtls_ssl_context *ssl, int level, + const char *file, int line, + const char *text, const mbedtls_mpi *X); +#endif + +#if defined(MBEDTLS_ECP_LIGHT) +/** + * \brief Print an ECP point to the debug output. This function is always + * used through the MBEDTLS_SSL_DEBUG_ECP() macro, which supplies the + * ssl context, file and line number parameters. + * + * \param ssl SSL context + * \param level error level of the debug message + * \param file file the error has occurred in + * \param line line number the error has occurred in + * \param text a name or label for the ECP point being output. Normally the + * variable name + * \param X the ECP point + * + * \attention This function is intended for INTERNAL usage within the + * library only. + */ +void mbedtls_debug_print_ecp(const mbedtls_ssl_context *ssl, int level, + const char *file, int line, + const char *text, const mbedtls_ecp_point *X); +#endif + +#if defined(MBEDTLS_X509_CRT_PARSE_C) && !defined(MBEDTLS_X509_REMOVE_INFO) +/** + * \brief Print a X.509 certificate structure to the debug output. This + * function is always used through the MBEDTLS_SSL_DEBUG_CRT() macro, + * which supplies the ssl context, file and line number parameters. + * + * \param ssl SSL context + * \param level error level of the debug message + * \param file file the error has occurred in + * \param line line number the error has occurred in + * \param text a name or label for the certificate being output + * \param crt X.509 certificate structure + * + * \attention This function is intended for INTERNAL usage within the + * library only. + */ +void mbedtls_debug_print_crt(const mbedtls_ssl_context *ssl, int level, + const char *file, int line, + const char *text, const mbedtls_x509_crt *crt); +#endif + +/* Note: the MBEDTLS_ECDH_C guard here is mandatory because this debug function + only works for the built-in implementation. */ +#if defined(MBEDTLS_KEY_EXCHANGE_SOME_ECDH_OR_ECDHE_ANY_ENABLED) && \ + defined(MBEDTLS_ECDH_C) +typedef enum { + MBEDTLS_DEBUG_ECDH_Q, + MBEDTLS_DEBUG_ECDH_QP, + MBEDTLS_DEBUG_ECDH_Z, +} mbedtls_debug_ecdh_attr; + +/** + * \brief Print a field of the ECDH structure in the SSL context to the debug + * output. This function is always used through the + * MBEDTLS_SSL_DEBUG_ECDH() macro, which supplies the ssl context, file + * and line number parameters. + * + * \param ssl SSL context + * \param level error level of the debug message + * \param file file the error has occurred in + * \param line line number the error has occurred in + * \param ecdh the ECDH context + * \param attr the identifier of the attribute being output + * + * \attention This function is intended for INTERNAL usage within the + * library only. + */ +void mbedtls_debug_printf_ecdh(const mbedtls_ssl_context *ssl, int level, + const char *file, int line, + const mbedtls_ecdh_context *ecdh, + mbedtls_debug_ecdh_attr attr); +#endif /* MBEDTLS_KEY_EXCHANGE_SOME_ECDH_OR_ECDHE_ANY_ENABLED && + MBEDTLS_ECDH_C */ + +#endif /* MBEDTLS_DEBUG_INTERNAL_H */ diff --git a/vendor/mbedtls/library/des.c b/vendor/mbedtls/library/des.c index 8cf346f81b..f0032b3b56 100644 --- a/vendor/mbedtls/library/des.c +++ b/vendor/mbedtls/library/des.c @@ -2,19 +2,7 @@ * FIPS-46-3 compliant Triple-DES implementation * * Copyright The Mbed TLS Contributors - * SPDX-License-Identifier: Apache-2.0 - * - * Licensed under the Apache License, Version 2.0 (the "License"); you may - * not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT - * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. + * SPDX-License-Identifier: Apache-2.0 OR GPL-2.0-or-later */ /* * DES, on which TDES is based, was originally designed by Horst Feistel @@ -642,7 +630,6 @@ int mbedtls_des_crypt_cbc(mbedtls_des_context *ctx, const unsigned char *input, unsigned char *output) { - int i; int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED; unsigned char temp[8]; @@ -652,9 +639,7 @@ int mbedtls_des_crypt_cbc(mbedtls_des_context *ctx, if (mode == MBEDTLS_DES_ENCRYPT) { while (length > 0) { - for (i = 0; i < 8; i++) { - output[i] = (unsigned char) (input[i] ^ iv[i]); - } + mbedtls_xor(output, input, iv, 8); ret = mbedtls_des_crypt_ecb(ctx, output, output); if (ret != 0) { @@ -674,9 +659,7 @@ int mbedtls_des_crypt_cbc(mbedtls_des_context *ctx, goto exit; } - for (i = 0; i < 8; i++) { - output[i] = (unsigned char) (output[i] ^ iv[i]); - } + mbedtls_xor(output, output, iv, 8); memcpy(iv, temp, 8); @@ -745,7 +728,6 @@ int mbedtls_des3_crypt_cbc(mbedtls_des3_context *ctx, const unsigned char *input, unsigned char *output) { - int i; int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED; unsigned char temp[8]; @@ -755,9 +737,7 @@ int mbedtls_des3_crypt_cbc(mbedtls_des3_context *ctx, if (mode == MBEDTLS_DES_ENCRYPT) { while (length > 0) { - for (i = 0; i < 8; i++) { - output[i] = (unsigned char) (input[i] ^ iv[i]); - } + mbedtls_xor(output, input, iv, 8); ret = mbedtls_des3_crypt_ecb(ctx, output, output); if (ret != 0) { @@ -777,9 +757,7 @@ int mbedtls_des3_crypt_cbc(mbedtls_des3_context *ctx, goto exit; } - for (i = 0; i < 8; i++) { - output[i] = (unsigned char) (output[i] ^ iv[i]); - } + mbedtls_xor(output, output, iv, 8); memcpy(iv, temp, 8); diff --git a/vendor/mbedtls/library/dhm.c b/vendor/mbedtls/library/dhm.c index c6f955ee42..bcc07f5441 100644 --- a/vendor/mbedtls/library/dhm.c +++ b/vendor/mbedtls/library/dhm.c @@ -2,19 +2,7 @@ * Diffie-Hellman-Merkle key exchange * * Copyright The Mbed TLS Contributors - * SPDX-License-Identifier: Apache-2.0 - * - * Licensed under the Apache License, Version 2.0 (the "License"); you may - * not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT - * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. + * SPDX-License-Identifier: Apache-2.0 OR GPL-2.0-or-later */ /* * The following sources were referenced in the design of this implementation @@ -47,11 +35,6 @@ #if !defined(MBEDTLS_DHM_ALT) -#define DHM_VALIDATE_RET(cond) \ - MBEDTLS_INTERNAL_VALIDATE_RET(cond, MBEDTLS_ERR_DHM_BAD_INPUT_DATA) -#define DHM_VALIDATE(cond) \ - MBEDTLS_INTERNAL_VALIDATE(cond) - /* * helper to validate the mbedtls_mpi size and import it */ @@ -65,10 +48,10 @@ static int dhm_read_bignum(mbedtls_mpi *X, return MBEDTLS_ERR_DHM_BAD_INPUT_DATA; } - n = ((*p)[0] << 8) | (*p)[1]; + n = MBEDTLS_GET_UINT16_BE(*p, 0); (*p) += 2; - if ((int) (end - *p) < n) { + if ((size_t) (end - *p) < (size_t) n) { return MBEDTLS_ERR_DHM_BAD_INPUT_DATA; } @@ -114,10 +97,49 @@ static int dhm_check_range(const mbedtls_mpi *param, const mbedtls_mpi *P) void mbedtls_dhm_init(mbedtls_dhm_context *ctx) { - DHM_VALIDATE(ctx != NULL); memset(ctx, 0, sizeof(mbedtls_dhm_context)); } +size_t mbedtls_dhm_get_bitlen(const mbedtls_dhm_context *ctx) +{ + return mbedtls_mpi_bitlen(&ctx->P); +} + +size_t mbedtls_dhm_get_len(const mbedtls_dhm_context *ctx) +{ + return mbedtls_mpi_size(&ctx->P); +} + +int mbedtls_dhm_get_value(const mbedtls_dhm_context *ctx, + mbedtls_dhm_parameter param, + mbedtls_mpi *dest) +{ + const mbedtls_mpi *src = NULL; + switch (param) { + case MBEDTLS_DHM_PARAM_P: + src = &ctx->P; + break; + case MBEDTLS_DHM_PARAM_G: + src = &ctx->G; + break; + case MBEDTLS_DHM_PARAM_X: + src = &ctx->X; + break; + case MBEDTLS_DHM_PARAM_GX: + src = &ctx->GX; + break; + case MBEDTLS_DHM_PARAM_GY: + src = &ctx->GY; + break; + case MBEDTLS_DHM_PARAM_K: + src = &ctx->K; + break; + default: + return MBEDTLS_ERR_DHM_BAD_INPUT_DATA; + } + return mbedtls_mpi_copy(dest, src); +} + /* * Parse the ServerKeyExchange parameters */ @@ -126,9 +148,6 @@ int mbedtls_dhm_read_params(mbedtls_dhm_context *ctx, const unsigned char *end) { int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED; - DHM_VALIDATE_RET(ctx != NULL); - DHM_VALIDATE_RET(p != NULL && *p != NULL); - DHM_VALIDATE_RET(end != NULL); if ((ret = dhm_read_bignum(&ctx->P, p, end)) != 0 || (ret = dhm_read_bignum(&ctx->G, p, end)) != 0 || @@ -140,8 +159,6 @@ int mbedtls_dhm_read_params(mbedtls_dhm_context *ctx, return ret; } - ctx->len = mbedtls_mpi_size(&ctx->P); - return 0; } @@ -211,10 +228,6 @@ int mbedtls_dhm_make_params(mbedtls_dhm_context *ctx, int x_size, int ret; size_t n1, n2, n3; unsigned char *p; - DHM_VALIDATE_RET(ctx != NULL); - DHM_VALIDATE_RET(output != NULL); - DHM_VALIDATE_RET(olen != NULL); - DHM_VALIDATE_RET(f_rng != NULL); ret = dhm_make_common(ctx, x_size, f_rng, p_rng); if (ret != 0) { @@ -244,9 +257,7 @@ int mbedtls_dhm_make_params(mbedtls_dhm_context *ctx, int x_size, DHM_MPI_EXPORT(&ctx->G, n2); DHM_MPI_EXPORT(&ctx->GX, n3); - *olen = p - output; - - ctx->len = n1; + *olen = (size_t) (p - output); cleanup: if (ret != 0 && ret > -128) { @@ -263,16 +274,12 @@ int mbedtls_dhm_set_group(mbedtls_dhm_context *ctx, const mbedtls_mpi *G) { int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED; - DHM_VALIDATE_RET(ctx != NULL); - DHM_VALIDATE_RET(P != NULL); - DHM_VALIDATE_RET(G != NULL); if ((ret = mbedtls_mpi_copy(&ctx->P, P)) != 0 || (ret = mbedtls_mpi_copy(&ctx->G, G)) != 0) { return MBEDTLS_ERROR_ADD(MBEDTLS_ERR_DHM_SET_GROUP_FAILED, ret); } - ctx->len = mbedtls_mpi_size(&ctx->P); return 0; } @@ -283,10 +290,8 @@ int mbedtls_dhm_read_public(mbedtls_dhm_context *ctx, const unsigned char *input, size_t ilen) { int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED; - DHM_VALIDATE_RET(ctx != NULL); - DHM_VALIDATE_RET(input != NULL); - if (ilen < 1 || ilen > ctx->len) { + if (ilen < 1 || ilen > mbedtls_dhm_get_len(ctx)) { return MBEDTLS_ERR_DHM_BAD_INPUT_DATA; } @@ -306,11 +311,8 @@ int mbedtls_dhm_make_public(mbedtls_dhm_context *ctx, int x_size, void *p_rng) { int ret; - DHM_VALIDATE_RET(ctx != NULL); - DHM_VALIDATE_RET(output != NULL); - DHM_VALIDATE_RET(f_rng != NULL); - if (olen < 1 || olen > ctx->len) { + if (olen < 1 || olen > mbedtls_dhm_get_len(ctx)) { return MBEDTLS_ERR_DHM_BAD_INPUT_DATA; } @@ -407,11 +409,12 @@ int mbedtls_dhm_calc_secret(mbedtls_dhm_context *ctx, { int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED; mbedtls_mpi GYb; - DHM_VALIDATE_RET(ctx != NULL); - DHM_VALIDATE_RET(output != NULL); - DHM_VALIDATE_RET(olen != NULL); - if (output_size < ctx->len) { + if (f_rng == NULL) { + return MBEDTLS_ERR_DHM_BAD_INPUT_DATA; + } + + if (output_size < mbedtls_dhm_get_len(ctx)) { return MBEDTLS_ERR_DHM_BAD_INPUT_DATA; } @@ -422,23 +425,17 @@ int mbedtls_dhm_calc_secret(mbedtls_dhm_context *ctx, mbedtls_mpi_init(&GYb); /* Blind peer's value */ - if (f_rng != NULL) { - MBEDTLS_MPI_CHK(dhm_update_blinding(ctx, f_rng, p_rng)); - MBEDTLS_MPI_CHK(mbedtls_mpi_mul_mpi(&GYb, &ctx->GY, &ctx->Vi)); - MBEDTLS_MPI_CHK(mbedtls_mpi_mod_mpi(&GYb, &GYb, &ctx->P)); - } else { - MBEDTLS_MPI_CHK(mbedtls_mpi_copy(&GYb, &ctx->GY)); - } + MBEDTLS_MPI_CHK(dhm_update_blinding(ctx, f_rng, p_rng)); + MBEDTLS_MPI_CHK(mbedtls_mpi_mul_mpi(&GYb, &ctx->GY, &ctx->Vi)); + MBEDTLS_MPI_CHK(mbedtls_mpi_mod_mpi(&GYb, &GYb, &ctx->P)); /* Do modular exponentiation */ MBEDTLS_MPI_CHK(mbedtls_mpi_exp_mod(&ctx->K, &GYb, &ctx->X, &ctx->P, &ctx->RP)); /* Unblind secret value */ - if (f_rng != NULL) { - MBEDTLS_MPI_CHK(mbedtls_mpi_mul_mpi(&ctx->K, &ctx->K, &ctx->Vf)); - MBEDTLS_MPI_CHK(mbedtls_mpi_mod_mpi(&ctx->K, &ctx->K, &ctx->P)); - } + MBEDTLS_MPI_CHK(mbedtls_mpi_mul_mpi(&ctx->K, &ctx->K, &ctx->Vf)); + MBEDTLS_MPI_CHK(mbedtls_mpi_mod_mpi(&ctx->K, &ctx->K, &ctx->P)); /* Output the secret without any leading zero byte. This is mandatory * for TLS per RFC 5246 §8.1.2. */ @@ -492,9 +489,6 @@ int mbedtls_dhm_parse_dhm(mbedtls_dhm_context *dhm, const unsigned char *dhmin, mbedtls_pem_context pem; #endif /* MBEDTLS_PEM_PARSE_C */ - DHM_VALIDATE_RET(dhm != NULL); - DHM_VALIDATE_RET(dhmin != NULL); - #if defined(MBEDTLS_PEM_PARSE_C) mbedtls_pem_init(&pem); @@ -564,8 +558,6 @@ int mbedtls_dhm_parse_dhm(mbedtls_dhm_context *dhm, const unsigned char *dhmin, ret = 0; - dhm->len = mbedtls_mpi_size(&dhm->P); - exit: #if defined(MBEDTLS_PEM_PARSE_C) mbedtls_pem_free(&pem); @@ -593,6 +585,7 @@ static int load_file(const char *path, unsigned char **buf, size_t *n) if ((f = fopen(path, "rb")) == NULL) { return MBEDTLS_ERR_DHM_FILE_IO_ERROR; } + /* The data loaded here is public, so don't bother disabling buffering. */ fseek(f, 0, SEEK_END); if ((size = ftell(f)) == -1) { @@ -612,8 +605,7 @@ static int load_file(const char *path, unsigned char **buf, size_t *n) if (fread(*buf, 1, *n, f) != *n) { fclose(f); - mbedtls_platform_zeroize(*buf, *n + 1); - mbedtls_free(*buf); + mbedtls_zeroize_and_free(*buf, *n + 1); return MBEDTLS_ERR_DHM_FILE_IO_ERROR; } @@ -637,8 +629,6 @@ int mbedtls_dhm_parse_dhmfile(mbedtls_dhm_context *dhm, const char *path) int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED; size_t n; unsigned char *buf; - DHM_VALIDATE_RET(dhm != NULL); - DHM_VALIDATE_RET(path != NULL); if ((ret = load_file(path, &buf, &n)) != 0) { return ret; @@ -646,8 +636,7 @@ int mbedtls_dhm_parse_dhmfile(mbedtls_dhm_context *dhm, const char *path) ret = mbedtls_dhm_parse_dhm(dhm, buf, n); - mbedtls_platform_zeroize(buf, n); - mbedtls_free(buf); + mbedtls_zeroize_and_free(buf, n); return ret; } diff --git a/vendor/mbedtls/library/ecdh.c b/vendor/mbedtls/library/ecdh.c index 9f002d9682..b276c6adad 100644 --- a/vendor/mbedtls/library/ecdh.c +++ b/vendor/mbedtls/library/ecdh.c @@ -2,19 +2,7 @@ * Elliptic curve Diffie-Hellman * * Copyright The Mbed TLS Contributors - * SPDX-License-Identifier: Apache-2.0 - * - * Licensed under the Apache License, Version 2.0 (the "License"); you may - * not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT - * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. + * SPDX-License-Identifier: Apache-2.0 OR GPL-2.0-or-later */ /* @@ -34,12 +22,6 @@ #include -/* Parameter validation macros based on platform_util.h */ -#define ECDH_VALIDATE_RET(cond) \ - MBEDTLS_INTERNAL_VALIDATE_RET(cond, MBEDTLS_ERR_ECP_BAD_INPUT_DATA) -#define ECDH_VALIDATE(cond) \ - MBEDTLS_INTERNAL_VALIDATE(cond) - #if defined(MBEDTLS_ECDH_LEGACY_CONTEXT) typedef mbedtls_ecdh_context mbedtls_ecdh_context_mbed; #endif @@ -100,10 +82,6 @@ int mbedtls_ecdh_gen_public(mbedtls_ecp_group *grp, mbedtls_mpi *d, mbedtls_ecp_ int (*f_rng)(void *, unsigned char *, size_t), void *p_rng) { - ECDH_VALIDATE_RET(grp != NULL); - ECDH_VALIDATE_RET(d != NULL); - ECDH_VALIDATE_RET(Q != NULL); - ECDH_VALIDATE_RET(f_rng != NULL); return ecdh_gen_public_restartable(grp, d, Q, f_rng, p_rng, NULL); } #endif /* !MBEDTLS_ECDH_GEN_PUBLIC_ALT */ @@ -148,10 +126,6 @@ int mbedtls_ecdh_compute_shared(mbedtls_ecp_group *grp, mbedtls_mpi *z, int (*f_rng)(void *, unsigned char *, size_t), void *p_rng) { - ECDH_VALIDATE_RET(grp != NULL); - ECDH_VALIDATE_RET(Q != NULL); - ECDH_VALIDATE_RET(d != NULL); - ECDH_VALIDATE_RET(z != NULL); return ecdh_compute_shared_restartable(grp, z, Q, d, f_rng, p_rng, NULL); } @@ -170,13 +144,20 @@ static void ecdh_init_internal(mbedtls_ecdh_context_mbed *ctx) #endif } +mbedtls_ecp_group_id mbedtls_ecdh_get_grp_id(mbedtls_ecdh_context *ctx) +{ +#if defined(MBEDTLS_ECDH_LEGACY_CONTEXT) + return ctx->MBEDTLS_PRIVATE(grp).id; +#else + return ctx->MBEDTLS_PRIVATE(grp_id); +#endif +} + /* * Initialize context */ void mbedtls_ecdh_init(mbedtls_ecdh_context *ctx) { - ECDH_VALIDATE(ctx != NULL); - #if defined(MBEDTLS_ECDH_LEGACY_CONTEXT) ecdh_init_internal(ctx); mbedtls_ecp_point_init(&ctx->Vi); @@ -211,8 +192,6 @@ static int ecdh_setup_internal(mbedtls_ecdh_context_mbed *ctx, */ int mbedtls_ecdh_setup(mbedtls_ecdh_context *ctx, mbedtls_ecp_group_id grp_id) { - ECDH_VALIDATE_RET(ctx != NULL); - #if defined(MBEDTLS_ECDH_LEGACY_CONTEXT) return ecdh_setup_internal(ctx, grp_id); #else @@ -253,8 +232,6 @@ static void ecdh_free_internal(mbedtls_ecdh_context_mbed *ctx) */ void mbedtls_ecdh_enable_restart(mbedtls_ecdh_context *ctx) { - ECDH_VALIDATE(ctx != NULL); - ctx->restart_enabled = 1; } #endif @@ -363,11 +340,6 @@ int mbedtls_ecdh_make_params(mbedtls_ecdh_context *ctx, size_t *olen, void *p_rng) { int restart_enabled = 0; - ECDH_VALIDATE_RET(ctx != NULL); - ECDH_VALIDATE_RET(olen != NULL); - ECDH_VALIDATE_RET(buf != NULL); - ECDH_VALIDATE_RET(f_rng != NULL); - #if defined(MBEDTLS_ECP_RESTARTABLE) restart_enabled = ctx->restart_enabled; #else @@ -400,7 +372,7 @@ static int ecdh_read_params_internal(mbedtls_ecdh_context_mbed *ctx, const unsigned char *end) { return mbedtls_ecp_tls_read_point(&ctx->grp, &ctx->Qp, buf, - end - *buf); + (size_t) (end - *buf)); } /* @@ -416,12 +388,7 @@ int mbedtls_ecdh_read_params(mbedtls_ecdh_context *ctx, { int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED; mbedtls_ecp_group_id grp_id; - ECDH_VALIDATE_RET(ctx != NULL); - ECDH_VALIDATE_RET(buf != NULL); - ECDH_VALIDATE_RET(*buf != NULL); - ECDH_VALIDATE_RET(end != NULL); - - if ((ret = mbedtls_ecp_tls_read_group_id(&grp_id, buf, end - *buf)) + if ((ret = mbedtls_ecp_tls_read_group_id(&grp_id, buf, (size_t) (end - *buf))) != 0) { return ret; } @@ -480,10 +447,9 @@ int mbedtls_ecdh_get_params(mbedtls_ecdh_context *ctx, mbedtls_ecdh_side side) { int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED; - ECDH_VALIDATE_RET(ctx != NULL); - ECDH_VALIDATE_RET(key != NULL); - ECDH_VALIDATE_RET(side == MBEDTLS_ECDH_OURS || - side == MBEDTLS_ECDH_THEIRS); + if (side != MBEDTLS_ECDH_OURS && side != MBEDTLS_ECDH_THEIRS) { + return MBEDTLS_ERR_ECP_BAD_INPUT_DATA; + } if (mbedtls_ecdh_grp_id(ctx) == MBEDTLS_ECP_DP_NONE) { /* This is the first call to get_params(). Set up the context @@ -574,11 +540,6 @@ int mbedtls_ecdh_make_public(mbedtls_ecdh_context *ctx, size_t *olen, void *p_rng) { int restart_enabled = 0; - ECDH_VALIDATE_RET(ctx != NULL); - ECDH_VALIDATE_RET(olen != NULL); - ECDH_VALIDATE_RET(buf != NULL); - ECDH_VALIDATE_RET(f_rng != NULL); - #if defined(MBEDTLS_ECP_RESTARTABLE) restart_enabled = ctx->restart_enabled; #endif @@ -628,9 +589,6 @@ static int ecdh_read_public_internal(mbedtls_ecdh_context_mbed *ctx, int mbedtls_ecdh_read_public(mbedtls_ecdh_context *ctx, const unsigned char *buf, size_t blen) { - ECDH_VALIDATE_RET(ctx != NULL); - ECDH_VALIDATE_RET(buf != NULL); - #if defined(MBEDTLS_ECDH_LEGACY_CONTEXT) return ecdh_read_public_internal(ctx, buf, blen); #else @@ -710,10 +668,6 @@ int mbedtls_ecdh_calc_secret(mbedtls_ecdh_context *ctx, size_t *olen, void *p_rng) { int restart_enabled = 0; - ECDH_VALIDATE_RET(ctx != NULL); - ECDH_VALIDATE_RET(olen != NULL); - ECDH_VALIDATE_RET(buf != NULL); - #if defined(MBEDTLS_ECP_RESTARTABLE) restart_enabled = ctx->restart_enabled; #endif @@ -737,5 +691,4 @@ int mbedtls_ecdh_calc_secret(mbedtls_ecdh_context *ctx, size_t *olen, } #endif } - #endif /* MBEDTLS_ECDH_C */ diff --git a/vendor/mbedtls/library/ecdsa.c b/vendor/mbedtls/library/ecdsa.c index 2fcb2fbc01..2f7a996a7e 100644 --- a/vendor/mbedtls/library/ecdsa.c +++ b/vendor/mbedtls/library/ecdsa.c @@ -2,19 +2,7 @@ * Elliptic curve DSA * * Copyright The Mbed TLS Contributors - * SPDX-License-Identifier: Apache-2.0 - * - * Licensed under the Apache License, Version 2.0 (the "License"); you may - * not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT - * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. + * SPDX-License-Identifier: Apache-2.0 OR GPL-2.0-or-later */ /* @@ -41,12 +29,6 @@ #include "mbedtls/platform_util.h" #include "mbedtls/error.h" -/* Parameter validation macros based on platform_util.h */ -#define ECDSA_VALIDATE_RET(cond) \ - MBEDTLS_INTERNAL_VALIDATE_RET(cond, MBEDTLS_ERR_ECP_BAD_INPUT_DATA) -#define ECDSA_VALIDATE(cond) \ - MBEDTLS_INTERNAL_VALIDATE(cond) - #if defined(MBEDTLS_ECP_RESTARTABLE) /* @@ -258,13 +240,13 @@ int mbedtls_ecdsa_can_do(mbedtls_ecp_group_id gid) * Compute ECDSA signature of a hashed message (SEC1 4.1.3) * Obviously, compared to SEC1 4.1.3, we skip step 4 (hash message) */ -static int ecdsa_sign_restartable(mbedtls_ecp_group *grp, - mbedtls_mpi *r, mbedtls_mpi *s, - const mbedtls_mpi *d, const unsigned char *buf, size_t blen, - int (*f_rng)(void *, unsigned char *, size_t), void *p_rng, - int (*f_rng_blind)(void *, unsigned char *, size_t), - void *p_rng_blind, - mbedtls_ecdsa_restart_ctx *rs_ctx) +int mbedtls_ecdsa_sign_restartable(mbedtls_ecp_group *grp, + mbedtls_mpi *r, mbedtls_mpi *s, + const mbedtls_mpi *d, const unsigned char *buf, size_t blen, + int (*f_rng)(void *, unsigned char *, size_t), void *p_rng, + int (*f_rng_blind)(void *, unsigned char *, size_t), + void *p_rng_blind, + mbedtls_ecdsa_restart_ctx *rs_ctx) { int ret, key_tries, sign_tries; int *p_sign_tries = &sign_tries, *p_key_tries = &key_tries; @@ -399,30 +381,26 @@ int mbedtls_ecdsa_sign(mbedtls_ecp_group *grp, mbedtls_mpi *r, mbedtls_mpi *s, const mbedtls_mpi *d, const unsigned char *buf, size_t blen, int (*f_rng)(void *, unsigned char *, size_t), void *p_rng) { - ECDSA_VALIDATE_RET(grp != NULL); - ECDSA_VALIDATE_RET(r != NULL); - ECDSA_VALIDATE_RET(s != NULL); - ECDSA_VALIDATE_RET(d != NULL); - ECDSA_VALIDATE_RET(f_rng != NULL); - ECDSA_VALIDATE_RET(buf != NULL || blen == 0); - /* Use the same RNG for both blinding and ephemeral key generation */ - return ecdsa_sign_restartable(grp, r, s, d, buf, blen, - f_rng, p_rng, f_rng, p_rng, NULL); + return mbedtls_ecdsa_sign_restartable(grp, r, s, d, buf, blen, + f_rng, p_rng, f_rng, p_rng, NULL); } #endif /* !MBEDTLS_ECDSA_SIGN_ALT */ #if defined(MBEDTLS_ECDSA_DETERMINISTIC) /* * Deterministic signature wrapper + * + * note: The f_rng_blind parameter must not be NULL. + * */ -static int ecdsa_sign_det_restartable(mbedtls_ecp_group *grp, - mbedtls_mpi *r, mbedtls_mpi *s, - const mbedtls_mpi *d, const unsigned char *buf, size_t blen, - mbedtls_md_type_t md_alg, - int (*f_rng_blind)(void *, unsigned char *, size_t), - void *p_rng_blind, - mbedtls_ecdsa_restart_ctx *rs_ctx) +int mbedtls_ecdsa_sign_det_restartable(mbedtls_ecp_group *grp, + mbedtls_mpi *r, mbedtls_mpi *s, + const mbedtls_mpi *d, const unsigned char *buf, size_t blen, + mbedtls_md_type_t md_alg, + int (*f_rng_blind)(void *, unsigned char *, size_t), + void *p_rng_blind, + mbedtls_ecdsa_restart_ctx *rs_ctx) { int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED; mbedtls_hmac_drbg_context rng_ctx; @@ -472,67 +450,9 @@ static int ecdsa_sign_det_restartable(mbedtls_ecp_group *grp, ret = mbedtls_ecdsa_sign(grp, r, s, d, buf, blen, mbedtls_hmac_drbg_random, p_rng); #else - if (f_rng_blind != NULL) { - ret = ecdsa_sign_restartable(grp, r, s, d, buf, blen, - mbedtls_hmac_drbg_random, p_rng, - f_rng_blind, p_rng_blind, rs_ctx); - } else { - mbedtls_hmac_drbg_context *p_rng_blind_det; - -#if !defined(MBEDTLS_ECP_RESTARTABLE) - /* - * To avoid reusing rng_ctx and risking incorrect behavior we seed a - * second HMAC-DRBG with the same seed. We also apply a label to avoid - * reusing the bits of the ephemeral key for blinding and eliminate the - * risk that they leak this way. - */ - const char *blind_label = "BLINDING CONTEXT"; - mbedtls_hmac_drbg_context rng_ctx_blind; - - mbedtls_hmac_drbg_init(&rng_ctx_blind); - p_rng_blind_det = &rng_ctx_blind; - mbedtls_hmac_drbg_seed_buf(p_rng_blind_det, md_info, - data, 2 * grp_len); - ret = mbedtls_hmac_drbg_update_ret(p_rng_blind_det, - (const unsigned char *) blind_label, - strlen(blind_label)); - if (ret != 0) { - mbedtls_hmac_drbg_free(&rng_ctx_blind); - goto cleanup; - } -#else - /* - * In the case of restartable computations we would either need to store - * the second RNG in the restart context too or set it up at every - * restart. The first option would penalize the correct application of - * the function and the second would defeat the purpose of the - * restartable feature. - * - * Therefore in this case we reuse the original RNG. This comes with the - * price that the resulting signature might not be a valid deterministic - * ECDSA signature with a very low probability (same magnitude as - * successfully guessing the private key). However even then it is still - * a valid ECDSA signature. - */ - p_rng_blind_det = p_rng; -#endif /* MBEDTLS_ECP_RESTARTABLE */ - - /* - * Since the output of the RNGs is always the same for the same key and - * message, this limits the efficiency of blinding and leaks information - * through side channels. After mbedtls_ecdsa_sign_det() is removed NULL - * won't be a valid value for f_rng_blind anymore. Therefore it should - * be checked by the caller and this branch and check can be removed. - */ - ret = ecdsa_sign_restartable(grp, r, s, d, buf, blen, - mbedtls_hmac_drbg_random, p_rng, - mbedtls_hmac_drbg_random, p_rng_blind_det, - rs_ctx); - -#if !defined(MBEDTLS_ECP_RESTARTABLE) - mbedtls_hmac_drbg_free(&rng_ctx_blind); -#endif - } + ret = mbedtls_ecdsa_sign_restartable(grp, r, s, d, buf, blen, + mbedtls_hmac_drbg_random, p_rng, + f_rng_blind, p_rng_blind, rs_ctx); #endif /* MBEDTLS_ECDSA_SIGN_ALT */ cleanup: @@ -545,26 +465,8 @@ static int ecdsa_sign_det_restartable(mbedtls_ecp_group *grp, } /* - * Deterministic signature wrappers + * Deterministic signature wrapper */ - -#if !defined(MBEDTLS_DEPRECATED_REMOVED) -int mbedtls_ecdsa_sign_det(mbedtls_ecp_group *grp, mbedtls_mpi *r, - mbedtls_mpi *s, const mbedtls_mpi *d, - const unsigned char *buf, size_t blen, - mbedtls_md_type_t md_alg) -{ - ECDSA_VALIDATE_RET(grp != NULL); - ECDSA_VALIDATE_RET(r != NULL); - ECDSA_VALIDATE_RET(s != NULL); - ECDSA_VALIDATE_RET(d != NULL); - ECDSA_VALIDATE_RET(buf != NULL || blen == 0); - - return ecdsa_sign_det_restartable(grp, r, s, d, buf, blen, md_alg, - NULL, NULL, NULL); -} -#endif /* MBEDTLS_DEPRECATED_REMOVED */ - int mbedtls_ecdsa_sign_det_ext(mbedtls_ecp_group *grp, mbedtls_mpi *r, mbedtls_mpi *s, const mbedtls_mpi *d, const unsigned char *buf, size_t blen, @@ -573,15 +475,8 @@ int mbedtls_ecdsa_sign_det_ext(mbedtls_ecp_group *grp, mbedtls_mpi *r, size_t), void *p_rng_blind) { - ECDSA_VALIDATE_RET(grp != NULL); - ECDSA_VALIDATE_RET(r != NULL); - ECDSA_VALIDATE_RET(s != NULL); - ECDSA_VALIDATE_RET(d != NULL); - ECDSA_VALIDATE_RET(buf != NULL || blen == 0); - ECDSA_VALIDATE_RET(f_rng_blind != NULL); - - return ecdsa_sign_det_restartable(grp, r, s, d, buf, blen, md_alg, - f_rng_blind, p_rng_blind, NULL); + return mbedtls_ecdsa_sign_det_restartable(grp, r, s, d, buf, blen, md_alg, + f_rng_blind, p_rng_blind, NULL); } #endif /* MBEDTLS_ECDSA_DETERMINISTIC */ @@ -590,11 +485,12 @@ int mbedtls_ecdsa_sign_det_ext(mbedtls_ecp_group *grp, mbedtls_mpi *r, * Verify ECDSA signature of hashed message (SEC1 4.1.4) * Obviously, compared to SEC1 4.1.3, we skip step 2 (hash message) */ -static int ecdsa_verify_restartable(mbedtls_ecp_group *grp, - const unsigned char *buf, size_t blen, - const mbedtls_ecp_point *Q, - const mbedtls_mpi *r, const mbedtls_mpi *s, - mbedtls_ecdsa_restart_ctx *rs_ctx) +int mbedtls_ecdsa_verify_restartable(mbedtls_ecp_group *grp, + const unsigned char *buf, size_t blen, + const mbedtls_ecp_point *Q, + const mbedtls_mpi *r, + const mbedtls_mpi *s, + mbedtls_ecdsa_restart_ctx *rs_ctx) { int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED; mbedtls_mpi e, s_inv, u1, u2; @@ -703,13 +599,7 @@ int mbedtls_ecdsa_verify(mbedtls_ecp_group *grp, const mbedtls_mpi *r, const mbedtls_mpi *s) { - ECDSA_VALIDATE_RET(grp != NULL); - ECDSA_VALIDATE_RET(Q != NULL); - ECDSA_VALIDATE_RET(r != NULL); - ECDSA_VALIDATE_RET(s != NULL); - ECDSA_VALIDATE_RET(buf != NULL || blen == 0); - - return ecdsa_verify_restartable(grp, buf, blen, Q, r, s, NULL); + return mbedtls_ecdsa_verify_restartable(grp, buf, blen, Q, r, s, NULL); } #endif /* !MBEDTLS_ECDSA_VERIFY_ALT */ @@ -717,7 +607,8 @@ int mbedtls_ecdsa_verify(mbedtls_ecp_group *grp, * Convert a signature (given by context) to ASN.1 */ static int ecdsa_signature_to_asn1(const mbedtls_mpi *r, const mbedtls_mpi *s, - unsigned char *sig, size_t *slen) + unsigned char *sig, size_t sig_size, + size_t *slen) { int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED; unsigned char buf[MBEDTLS_ECDSA_MAX_LEN] = { 0 }; @@ -732,6 +623,10 @@ static int ecdsa_signature_to_asn1(const mbedtls_mpi *r, const mbedtls_mpi *s, MBEDTLS_ASN1_CONSTRUCTED | MBEDTLS_ASN1_SEQUENCE)); + if (len > sig_size) { + return MBEDTLS_ERR_ECP_BUFFER_TOO_SMALL; + } + memcpy(sig, p, len); *slen = len; @@ -744,25 +639,24 @@ static int ecdsa_signature_to_asn1(const mbedtls_mpi *r, const mbedtls_mpi *s, int mbedtls_ecdsa_write_signature_restartable(mbedtls_ecdsa_context *ctx, mbedtls_md_type_t md_alg, const unsigned char *hash, size_t hlen, - unsigned char *sig, size_t *slen, + unsigned char *sig, size_t sig_size, size_t *slen, int (*f_rng)(void *, unsigned char *, size_t), void *p_rng, mbedtls_ecdsa_restart_ctx *rs_ctx) { int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED; mbedtls_mpi r, s; - ECDSA_VALIDATE_RET(ctx != NULL); - ECDSA_VALIDATE_RET(hash != NULL); - ECDSA_VALIDATE_RET(sig != NULL); - ECDSA_VALIDATE_RET(slen != NULL); + if (f_rng == NULL) { + return MBEDTLS_ERR_ECP_BAD_INPUT_DATA; + } mbedtls_mpi_init(&r); mbedtls_mpi_init(&s); #if defined(MBEDTLS_ECDSA_DETERMINISTIC) - MBEDTLS_MPI_CHK(ecdsa_sign_det_restartable(&ctx->grp, &r, &s, &ctx->d, - hash, hlen, md_alg, f_rng, - p_rng, rs_ctx)); + MBEDTLS_MPI_CHK(mbedtls_ecdsa_sign_det_restartable(&ctx->grp, &r, &s, &ctx->d, + hash, hlen, md_alg, f_rng, + p_rng, rs_ctx)); #else (void) md_alg; @@ -773,13 +667,13 @@ int mbedtls_ecdsa_write_signature_restartable(mbedtls_ecdsa_context *ctx, hash, hlen, f_rng, p_rng)); #else /* Use the same RNG for both blinding and ephemeral key generation */ - MBEDTLS_MPI_CHK(ecdsa_sign_restartable(&ctx->grp, &r, &s, &ctx->d, - hash, hlen, f_rng, p_rng, f_rng, - p_rng, rs_ctx)); + MBEDTLS_MPI_CHK(mbedtls_ecdsa_sign_restartable(&ctx->grp, &r, &s, &ctx->d, + hash, hlen, f_rng, p_rng, f_rng, + p_rng, rs_ctx)); #endif /* MBEDTLS_ECDSA_SIGN_ALT */ #endif /* MBEDTLS_ECDSA_DETERMINISTIC */ - MBEDTLS_MPI_CHK(ecdsa_signature_to_asn1(&r, &s, sig, slen)); + MBEDTLS_MPI_CHK(ecdsa_signature_to_asn1(&r, &s, sig, sig_size, slen)); cleanup: mbedtls_mpi_free(&r); @@ -794,34 +688,15 @@ int mbedtls_ecdsa_write_signature_restartable(mbedtls_ecdsa_context *ctx, int mbedtls_ecdsa_write_signature(mbedtls_ecdsa_context *ctx, mbedtls_md_type_t md_alg, const unsigned char *hash, size_t hlen, - unsigned char *sig, size_t *slen, + unsigned char *sig, size_t sig_size, size_t *slen, int (*f_rng)(void *, unsigned char *, size_t), void *p_rng) { - ECDSA_VALIDATE_RET(ctx != NULL); - ECDSA_VALIDATE_RET(hash != NULL); - ECDSA_VALIDATE_RET(sig != NULL); - ECDSA_VALIDATE_RET(slen != NULL); return mbedtls_ecdsa_write_signature_restartable( - ctx, md_alg, hash, hlen, sig, slen, f_rng, p_rng, NULL); + ctx, md_alg, hash, hlen, sig, sig_size, slen, + f_rng, p_rng, NULL); } -#if !defined(MBEDTLS_DEPRECATED_REMOVED) && \ - defined(MBEDTLS_ECDSA_DETERMINISTIC) -int mbedtls_ecdsa_write_signature_det(mbedtls_ecdsa_context *ctx, - const unsigned char *hash, size_t hlen, - unsigned char *sig, size_t *slen, - mbedtls_md_type_t md_alg) -{ - ECDSA_VALIDATE_RET(ctx != NULL); - ECDSA_VALIDATE_RET(hash != NULL); - ECDSA_VALIDATE_RET(sig != NULL); - ECDSA_VALIDATE_RET(slen != NULL); - return mbedtls_ecdsa_write_signature(ctx, md_alg, hash, hlen, sig, slen, - NULL, NULL); -} -#endif - /* * Read and check signature */ @@ -829,9 +704,6 @@ int mbedtls_ecdsa_read_signature(mbedtls_ecdsa_context *ctx, const unsigned char *hash, size_t hlen, const unsigned char *sig, size_t slen) { - ECDSA_VALIDATE_RET(ctx != NULL); - ECDSA_VALIDATE_RET(hash != NULL); - ECDSA_VALIDATE_RET(sig != NULL); return mbedtls_ecdsa_read_signature_restartable( ctx, hash, hlen, sig, slen, NULL); } @@ -849,10 +721,6 @@ int mbedtls_ecdsa_read_signature_restartable(mbedtls_ecdsa_context *ctx, const unsigned char *end = sig + slen; size_t len; mbedtls_mpi r, s; - ECDSA_VALIDATE_RET(ctx != NULL); - ECDSA_VALIDATE_RET(hash != NULL); - ECDSA_VALIDATE_RET(sig != NULL); - mbedtls_mpi_init(&r); mbedtls_mpi_init(&s); @@ -881,8 +749,8 @@ int mbedtls_ecdsa_read_signature_restartable(mbedtls_ecdsa_context *ctx, goto cleanup; } #else - if ((ret = ecdsa_verify_restartable(&ctx->grp, hash, hlen, - &ctx->Q, &r, &s, rs_ctx)) != 0) { + if ((ret = mbedtls_ecdsa_verify_restartable(&ctx->grp, hash, hlen, + &ctx->Q, &r, &s, rs_ctx)) != 0) { goto cleanup; } #endif /* MBEDTLS_ECDSA_VERIFY_ALT */ @@ -909,9 +777,6 @@ int mbedtls_ecdsa_genkey(mbedtls_ecdsa_context *ctx, mbedtls_ecp_group_id gid, int (*f_rng)(void *, unsigned char *, size_t), void *p_rng) { int ret = 0; - ECDSA_VALIDATE_RET(ctx != NULL); - ECDSA_VALIDATE_RET(f_rng != NULL); - ret = mbedtls_ecp_group_load(&ctx->grp, gid); if (ret != 0) { return ret; @@ -928,9 +793,6 @@ int mbedtls_ecdsa_genkey(mbedtls_ecdsa_context *ctx, mbedtls_ecp_group_id gid, int mbedtls_ecdsa_from_keypair(mbedtls_ecdsa_context *ctx, const mbedtls_ecp_keypair *key) { int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED; - ECDSA_VALIDATE_RET(ctx != NULL); - ECDSA_VALIDATE_RET(key != NULL); - if ((ret = mbedtls_ecp_group_copy(&ctx->grp, &key->grp)) != 0 || (ret = mbedtls_mpi_copy(&ctx->d, &key->d)) != 0 || (ret = mbedtls_ecp_copy(&ctx->Q, &key->Q)) != 0) { @@ -945,8 +807,6 @@ int mbedtls_ecdsa_from_keypair(mbedtls_ecdsa_context *ctx, const mbedtls_ecp_key */ void mbedtls_ecdsa_init(mbedtls_ecdsa_context *ctx) { - ECDSA_VALIDATE(ctx != NULL); - mbedtls_ecp_keypair_init(ctx); } @@ -968,8 +828,6 @@ void mbedtls_ecdsa_free(mbedtls_ecdsa_context *ctx) */ void mbedtls_ecdsa_restart_init(mbedtls_ecdsa_restart_ctx *ctx) { - ECDSA_VALIDATE(ctx != NULL); - mbedtls_ecp_restart_init(&ctx->ecp); ctx->ver = NULL; diff --git a/vendor/mbedtls/library/ecjpake.c b/vendor/mbedtls/library/ecjpake.c index 17fa6983d8..cdf5d7ea46 100644 --- a/vendor/mbedtls/library/ecjpake.c +++ b/vendor/mbedtls/library/ecjpake.c @@ -2,19 +2,7 @@ * Elliptic curve J-PAKE * * Copyright The Mbed TLS Contributors - * SPDX-License-Identifier: Apache-2.0 - * - * Licensed under the Apache License, Version 2.0 (the "License"); you may - * not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT - * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. + * SPDX-License-Identifier: Apache-2.0 OR GPL-2.0-or-later */ /* @@ -34,12 +22,6 @@ #if !defined(MBEDTLS_ECJPAKE_ALT) -/* Parameter validation macros based on platform_util.h */ -#define ECJPAKE_VALIDATE_RET(cond) \ - MBEDTLS_INTERNAL_VALIDATE_RET(cond, MBEDTLS_ERR_ECP_BAD_INPUT_DATA) -#define ECJPAKE_VALIDATE(cond) \ - MBEDTLS_INTERNAL_VALIDATE(cond) - /* * Convert a mbedtls_ecjpake_role to identifier string */ @@ -51,14 +33,23 @@ static const char * const ecjpake_id[] = { #define ID_MINE (ecjpake_id[ctx->role]) #define ID_PEER (ecjpake_id[1 - ctx->role]) +/** + * Helper to Compute a hash from md_type + */ +static int mbedtls_ecjpake_compute_hash(mbedtls_md_type_t md_type, + const unsigned char *input, size_t ilen, + unsigned char *output) +{ + return mbedtls_md(mbedtls_md_info_from_type(md_type), + input, ilen, output); +} + /* * Initialize context */ void mbedtls_ecjpake_init(mbedtls_ecjpake_context *ctx) { - ECJPAKE_VALIDATE(ctx != NULL); - - ctx->md_info = NULL; + ctx->md_type = MBEDTLS_MD_NONE; mbedtls_ecp_group_init(&ctx->grp); ctx->point_format = MBEDTLS_ECP_PF_UNCOMPRESSED; @@ -82,7 +73,7 @@ void mbedtls_ecjpake_free(mbedtls_ecjpake_context *ctx) return; } - ctx->md_info = NULL; + ctx->md_type = MBEDTLS_MD_NONE; mbedtls_ecp_group_free(&ctx->grp); mbedtls_ecp_point_free(&ctx->Xm1); @@ -108,17 +99,18 @@ int mbedtls_ecjpake_setup(mbedtls_ecjpake_context *ctx, { int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED; - ECJPAKE_VALIDATE_RET(ctx != NULL); - ECJPAKE_VALIDATE_RET(role == MBEDTLS_ECJPAKE_CLIENT || - role == MBEDTLS_ECJPAKE_SERVER); - ECJPAKE_VALIDATE_RET(secret != NULL || len == 0); + if (role != MBEDTLS_ECJPAKE_CLIENT && role != MBEDTLS_ECJPAKE_SERVER) { + return MBEDTLS_ERR_ECP_BAD_INPUT_DATA; + } ctx->role = role; - if ((ctx->md_info = mbedtls_md_info_from_type(hash)) == NULL) { + if ((mbedtls_md_info_from_type(hash)) == NULL) { return MBEDTLS_ERR_MD_FEATURE_UNAVAILABLE; } + ctx->md_type = hash; + MBEDTLS_MPI_CHK(mbedtls_ecp_group_load(&ctx->grp, curve)); MBEDTLS_MPI_CHK(mbedtls_mpi_read_binary(&ctx->s, secret, len)); @@ -131,14 +123,25 @@ int mbedtls_ecjpake_setup(mbedtls_ecjpake_context *ctx, return ret; } +int mbedtls_ecjpake_set_point_format(mbedtls_ecjpake_context *ctx, + int point_format) +{ + switch (point_format) { + case MBEDTLS_ECP_PF_UNCOMPRESSED: + case MBEDTLS_ECP_PF_COMPRESSED: + ctx->point_format = point_format; + return 0; + default: + return MBEDTLS_ERR_ECP_BAD_INPUT_DATA; + } +} + /* * Check if context is ready for use */ int mbedtls_ecjpake_check(const mbedtls_ecjpake_context *ctx) { - ECJPAKE_VALIDATE_RET(ctx != NULL); - - if (ctx->md_info == NULL || + if (ctx->md_type == MBEDTLS_MD_NONE || ctx->grp.id == MBEDTLS_ECP_DP_NONE || ctx->s.p == NULL) { return MBEDTLS_ERR_ECP_BAD_INPUT_DATA; @@ -165,7 +168,7 @@ static int ecjpake_write_len_point(unsigned char **p, } ret = mbedtls_ecp_point_write_binary(grp, P, pf, - &len, *p + 4, end - (*p + 4)); + &len, *p + 4, (size_t) (end - (*p + 4))); if (ret != 0) { return ret; } @@ -186,7 +189,7 @@ static int ecjpake_write_len_point(unsigned char **p, /* * Compute hash for ZKP (7.4.2.2.2.1) */ -static int ecjpake_hash(const mbedtls_md_info_t *md_info, +static int ecjpake_hash(const mbedtls_md_type_t md_type, const mbedtls_ecp_group *grp, const int pf, const mbedtls_ecp_point *G, @@ -222,11 +225,12 @@ static int ecjpake_hash(const mbedtls_md_info_t *md_info, p += id_len; /* Compute hash */ - MBEDTLS_MPI_CHK(mbedtls_md(md_info, buf, p - buf, hash)); + MBEDTLS_MPI_CHK(mbedtls_ecjpake_compute_hash(md_type, + buf, (size_t) (p - buf), hash)); /* Turn it into an integer mod n */ MBEDTLS_MPI_CHK(mbedtls_mpi_read_binary(h, hash, - mbedtls_md_get_size(md_info))); + mbedtls_md_get_size_from_type(md_type))); MBEDTLS_MPI_CHK(mbedtls_mpi_mod_mpi(h, h, &grp->N)); cleanup: @@ -236,7 +240,7 @@ static int ecjpake_hash(const mbedtls_md_info_t *md_info, /* * Parse a ECShnorrZKP (7.4.2.2.2) and verify it (7.4.2.3.3) */ -static int ecjpake_zkp_read(const mbedtls_md_info_t *md_info, +static int ecjpake_zkp_read(const mbedtls_md_type_t md_type, const mbedtls_ecp_group *grp, const int pf, const mbedtls_ecp_point *G, @@ -265,7 +269,7 @@ static int ecjpake_zkp_read(const mbedtls_md_info_t *md_info, return MBEDTLS_ERR_ECP_BAD_INPUT_DATA; } - MBEDTLS_MPI_CHK(mbedtls_ecp_tls_read_point(grp, &V, p, end - *p)); + MBEDTLS_MPI_CHK(mbedtls_ecp_tls_read_point(grp, &V, p, (size_t) (end - *p))); if (end < *p || (size_t) (end - *p) < 1) { ret = MBEDTLS_ERR_ECP_BAD_INPUT_DATA; @@ -285,7 +289,7 @@ static int ecjpake_zkp_read(const mbedtls_md_info_t *md_info, /* * Verification */ - MBEDTLS_MPI_CHK(ecjpake_hash(md_info, grp, pf, G, &V, X, id, &h)); + MBEDTLS_MPI_CHK(ecjpake_hash(md_type, grp, pf, G, &V, X, id, &h)); MBEDTLS_MPI_CHK(mbedtls_ecp_muladd((mbedtls_ecp_group *) grp, &VV, &h, X, &r, G)); @@ -306,7 +310,7 @@ static int ecjpake_zkp_read(const mbedtls_md_info_t *md_info, /* * Generate ZKP (7.4.2.3.2) and write it as ECSchnorrZKP (7.4.2.2.2) */ -static int ecjpake_zkp_write(const mbedtls_md_info_t *md_info, +static int ecjpake_zkp_write(const mbedtls_md_type_t md_type, const mbedtls_ecp_group *grp, const int pf, const mbedtls_ecp_point *G, @@ -335,14 +339,14 @@ static int ecjpake_zkp_write(const mbedtls_md_info_t *md_info, /* Compute signature */ MBEDTLS_MPI_CHK(mbedtls_ecp_gen_keypair_base((mbedtls_ecp_group *) grp, G, &v, &V, f_rng, p_rng)); - MBEDTLS_MPI_CHK(ecjpake_hash(md_info, grp, pf, G, &V, X, id, &h)); + MBEDTLS_MPI_CHK(ecjpake_hash(md_type, grp, pf, G, &V, X, id, &h)); MBEDTLS_MPI_CHK(mbedtls_mpi_mul_mpi(&h, &h, x)); /* x*h */ MBEDTLS_MPI_CHK(mbedtls_mpi_sub_mpi(&h, &v, &h)); /* v - x*h */ MBEDTLS_MPI_CHK(mbedtls_mpi_mod_mpi(&h, &h, &grp->N)); /* r */ /* Write it out */ MBEDTLS_MPI_CHK(mbedtls_ecp_tls_write_point(grp, &V, - pf, &len, *p, end - *p)); + pf, &len, *p, (size_t) (end - *p))); *p += len; len = mbedtls_mpi_size(&h); /* actually r */ @@ -367,7 +371,7 @@ static int ecjpake_zkp_write(const mbedtls_md_info_t *md_info, * Parse a ECJPAKEKeyKP (7.4.2.2.1) and check proof * Output: verified public key X */ -static int ecjpake_kkp_read(const mbedtls_md_info_t *md_info, +static int ecjpake_kkp_read(const mbedtls_md_type_t md_type, const mbedtls_ecp_group *grp, const int pf, const mbedtls_ecp_point *G, @@ -388,13 +392,13 @@ static int ecjpake_kkp_read(const mbedtls_md_info_t *md_info, * ECSchnorrZKP zkp; * } ECJPAKEKeyKP; */ - MBEDTLS_MPI_CHK(mbedtls_ecp_tls_read_point(grp, X, p, end - *p)); + MBEDTLS_MPI_CHK(mbedtls_ecp_tls_read_point(grp, X, p, (size_t) (end - *p))); if (mbedtls_ecp_is_zero(X)) { ret = MBEDTLS_ERR_ECP_INVALID_KEY; goto cleanup; } - MBEDTLS_MPI_CHK(ecjpake_zkp_read(md_info, grp, pf, G, X, id, p, end)); + MBEDTLS_MPI_CHK(ecjpake_zkp_read(md_type, grp, pf, G, X, id, p, end)); cleanup: return ret; @@ -404,7 +408,7 @@ static int ecjpake_kkp_read(const mbedtls_md_info_t *md_info, * Generate an ECJPAKEKeyKP * Output: the serialized structure, plus private/public key pair */ -static int ecjpake_kkp_write(const mbedtls_md_info_t *md_info, +static int ecjpake_kkp_write(const mbedtls_md_type_t md_type, const mbedtls_ecp_group *grp, const int pf, const mbedtls_ecp_point *G, @@ -427,11 +431,11 @@ static int ecjpake_kkp_write(const mbedtls_md_info_t *md_info, MBEDTLS_MPI_CHK(mbedtls_ecp_gen_keypair_base((mbedtls_ecp_group *) grp, G, x, X, f_rng, p_rng)); MBEDTLS_MPI_CHK(mbedtls_ecp_tls_write_point(grp, X, - pf, &len, *p, end - *p)); + pf, &len, *p, (size_t) (end - *p))); *p += len; /* Generate and write proof */ - MBEDTLS_MPI_CHK(ecjpake_zkp_write(md_info, grp, pf, G, x, X, id, + MBEDTLS_MPI_CHK(ecjpake_zkp_write(md_type, grp, pf, G, x, X, id, p, end, f_rng, p_rng)); cleanup: @@ -442,7 +446,7 @@ static int ecjpake_kkp_write(const mbedtls_md_info_t *md_info, * Read a ECJPAKEKeyKPPairList (7.4.2.3) and check proofs * Outputs: verified peer public keys Xa, Xb */ -static int ecjpake_kkpp_read(const mbedtls_md_info_t *md_info, +static int ecjpake_kkpp_read(const mbedtls_md_type_t md_type, const mbedtls_ecp_group *grp, const int pf, const mbedtls_ecp_point *G, @@ -461,8 +465,8 @@ static int ecjpake_kkpp_read(const mbedtls_md_info_t *md_info, * ECJPAKEKeyKP ecjpake_key_kp_pair_list[2]; * } ECJPAKEKeyKPPairList; */ - MBEDTLS_MPI_CHK(ecjpake_kkp_read(md_info, grp, pf, G, Xa, id, &p, end)); - MBEDTLS_MPI_CHK(ecjpake_kkp_read(md_info, grp, pf, G, Xb, id, &p, end)); + MBEDTLS_MPI_CHK(ecjpake_kkp_read(md_type, grp, pf, G, Xa, id, &p, end)); + MBEDTLS_MPI_CHK(ecjpake_kkp_read(md_type, grp, pf, G, Xb, id, &p, end)); if (p != end) { ret = MBEDTLS_ERR_ECP_BAD_INPUT_DATA; @@ -476,7 +480,7 @@ static int ecjpake_kkpp_read(const mbedtls_md_info_t *md_info, * Generate a ECJPAKEKeyKPPairList * Outputs: the serialized structure, plus two private/public key pairs */ -static int ecjpake_kkpp_write(const mbedtls_md_info_t *md_info, +static int ecjpake_kkpp_write(const mbedtls_md_type_t md_type, const mbedtls_ecp_group *grp, const int pf, const mbedtls_ecp_point *G, @@ -495,12 +499,12 @@ static int ecjpake_kkpp_write(const mbedtls_md_info_t *md_info, unsigned char *p = buf; const unsigned char *end = buf + len; - MBEDTLS_MPI_CHK(ecjpake_kkp_write(md_info, grp, pf, G, xm1, Xa, id, + MBEDTLS_MPI_CHK(ecjpake_kkp_write(md_type, grp, pf, G, xm1, Xa, id, &p, end, f_rng, p_rng)); - MBEDTLS_MPI_CHK(ecjpake_kkp_write(md_info, grp, pf, G, xm2, Xb, id, + MBEDTLS_MPI_CHK(ecjpake_kkp_write(md_type, grp, pf, G, xm2, Xb, id, &p, end, f_rng, p_rng)); - *olen = p - buf; + *olen = (size_t) (p - buf); cleanup: return ret; @@ -513,10 +517,7 @@ int mbedtls_ecjpake_read_round_one(mbedtls_ecjpake_context *ctx, const unsigned char *buf, size_t len) { - ECJPAKE_VALIDATE_RET(ctx != NULL); - ECJPAKE_VALIDATE_RET(buf != NULL); - - return ecjpake_kkpp_read(ctx->md_info, &ctx->grp, ctx->point_format, + return ecjpake_kkpp_read(ctx->md_type, &ctx->grp, ctx->point_format, &ctx->grp.G, &ctx->Xp1, &ctx->Xp2, ID_PEER, buf, len); @@ -530,12 +531,7 @@ int mbedtls_ecjpake_write_round_one(mbedtls_ecjpake_context *ctx, int (*f_rng)(void *, unsigned char *, size_t), void *p_rng) { - ECJPAKE_VALIDATE_RET(ctx != NULL); - ECJPAKE_VALIDATE_RET(buf != NULL); - ECJPAKE_VALIDATE_RET(olen != NULL); - ECJPAKE_VALIDATE_RET(f_rng != NULL); - - return ecjpake_kkpp_write(ctx->md_info, &ctx->grp, ctx->point_format, + return ecjpake_kkpp_write(ctx->md_type, &ctx->grp, ctx->point_format, &ctx->grp.G, &ctx->xm1, &ctx->Xm1, &ctx->xm2, &ctx->Xm2, ID_MINE, buf, len, olen, f_rng, p_rng); @@ -577,9 +573,6 @@ int mbedtls_ecjpake_read_round_two(mbedtls_ecjpake_context *ctx, mbedtls_ecp_group grp; mbedtls_ecp_point G; /* C: GB, S: GA */ - ECJPAKE_VALIDATE_RET(ctx != NULL); - ECJPAKE_VALIDATE_RET(buf != NULL); - mbedtls_ecp_group_init(&grp); mbedtls_ecp_point_init(&G); @@ -606,7 +599,7 @@ int mbedtls_ecjpake_read_round_two(mbedtls_ecjpake_context *ctx, } } - MBEDTLS_MPI_CHK(ecjpake_kkp_read(ctx->md_info, &ctx->grp, + MBEDTLS_MPI_CHK(ecjpake_kkp_read(ctx->md_type, &ctx->grp, ctx->point_format, &G, &ctx->Xp, ID_PEER, &p, end)); @@ -669,11 +662,6 @@ int mbedtls_ecjpake_write_round_two(mbedtls_ecjpake_context *ctx, const unsigned char *end = buf + len; size_t ec_len; - ECJPAKE_VALIDATE_RET(ctx != NULL); - ECJPAKE_VALIDATE_RET(buf != NULL); - ECJPAKE_VALIDATE_RET(olen != NULL); - ECJPAKE_VALIDATE_RET(f_rng != NULL); - mbedtls_ecp_point_init(&G); mbedtls_ecp_point_init(&Xm); mbedtls_mpi_init(&xm); @@ -705,7 +693,7 @@ int mbedtls_ecjpake_write_round_two(mbedtls_ecjpake_context *ctx, goto cleanup; } MBEDTLS_MPI_CHK(mbedtls_ecp_tls_write_group(&ctx->grp, &ec_len, - p, end - p)); + p, (size_t) (end - p))); p += ec_len; } @@ -714,15 +702,15 @@ int mbedtls_ecjpake_write_round_two(mbedtls_ecjpake_context *ctx, goto cleanup; } MBEDTLS_MPI_CHK(mbedtls_ecp_tls_write_point(&ctx->grp, &Xm, - ctx->point_format, &ec_len, p, end - p)); + ctx->point_format, &ec_len, p, (size_t) (end - p))); p += ec_len; - MBEDTLS_MPI_CHK(ecjpake_zkp_write(ctx->md_info, &ctx->grp, + MBEDTLS_MPI_CHK(ecjpake_zkp_write(ctx->md_type, &ctx->grp, ctx->point_format, &G, &xm, &Xm, ID_MINE, &p, end, f_rng, p_rng)); - *olen = p - buf; + *olen = (size_t) (p - buf); cleanup: mbedtls_ecp_point_free(&G); @@ -735,28 +723,14 @@ int mbedtls_ecjpake_write_round_two(mbedtls_ecjpake_context *ctx, /* * Derive PMS (7.4.2.7 / 7.4.2.8) */ -int mbedtls_ecjpake_derive_secret(mbedtls_ecjpake_context *ctx, - unsigned char *buf, size_t len, size_t *olen, - int (*f_rng)(void *, unsigned char *, size_t), - void *p_rng) +static int mbedtls_ecjpake_derive_k(mbedtls_ecjpake_context *ctx, + mbedtls_ecp_point *K, + int (*f_rng)(void *, unsigned char *, size_t), + void *p_rng) { int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED; - mbedtls_ecp_point K; mbedtls_mpi m_xm2_s, one; - unsigned char kx[MBEDTLS_ECP_MAX_BYTES]; - size_t x_bytes; - - ECJPAKE_VALIDATE_RET(ctx != NULL); - ECJPAKE_VALIDATE_RET(buf != NULL); - ECJPAKE_VALIDATE_RET(olen != NULL); - ECJPAKE_VALIDATE_RET(f_rng != NULL); - *olen = mbedtls_md_get_size(ctx->md_info); - if (len < *olen) { - return MBEDTLS_ERR_ECP_BUFFER_TOO_SMALL; - } - - mbedtls_ecp_point_init(&K); mbedtls_mpi_init(&m_xm2_s); mbedtls_mpi_init(&one); @@ -769,21 +743,76 @@ int mbedtls_ecjpake_derive_secret(mbedtls_ecjpake_context *ctx, */ MBEDTLS_MPI_CHK(ecjpake_mul_secret(&m_xm2_s, -1, &ctx->xm2, &ctx->s, &ctx->grp.N, f_rng, p_rng)); - MBEDTLS_MPI_CHK(mbedtls_ecp_muladd(&ctx->grp, &K, + MBEDTLS_MPI_CHK(mbedtls_ecp_muladd(&ctx->grp, K, &one, &ctx->Xp, &m_xm2_s, &ctx->Xp2)); - MBEDTLS_MPI_CHK(mbedtls_ecp_mul(&ctx->grp, &K, &ctx->xm2, &K, + MBEDTLS_MPI_CHK(mbedtls_ecp_mul(&ctx->grp, K, &ctx->xm2, K, f_rng, p_rng)); +cleanup: + mbedtls_mpi_free(&m_xm2_s); + mbedtls_mpi_free(&one); + + return ret; +} + +int mbedtls_ecjpake_derive_secret(mbedtls_ecjpake_context *ctx, + unsigned char *buf, size_t len, size_t *olen, + int (*f_rng)(void *, unsigned char *, size_t), + void *p_rng) +{ + int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED; + mbedtls_ecp_point K; + unsigned char kx[MBEDTLS_ECP_MAX_BYTES]; + size_t x_bytes; + + *olen = mbedtls_md_get_size_from_type(ctx->md_type); + if (len < *olen) { + return MBEDTLS_ERR_ECP_BUFFER_TOO_SMALL; + } + + mbedtls_ecp_point_init(&K); + + ret = mbedtls_ecjpake_derive_k(ctx, &K, f_rng, p_rng); + if (ret) { + goto cleanup; + } + /* PMS = SHA-256( K.X ) */ x_bytes = (ctx->grp.pbits + 7) / 8; MBEDTLS_MPI_CHK(mbedtls_mpi_write_binary(&K.X, kx, x_bytes)); - MBEDTLS_MPI_CHK(mbedtls_md(ctx->md_info, kx, x_bytes, buf)); + MBEDTLS_MPI_CHK(mbedtls_ecjpake_compute_hash(ctx->md_type, + kx, x_bytes, buf)); + +cleanup: + mbedtls_ecp_point_free(&K); + + return ret; +} + +int mbedtls_ecjpake_write_shared_key(mbedtls_ecjpake_context *ctx, + unsigned char *buf, size_t len, size_t *olen, + int (*f_rng)(void *, unsigned char *, size_t), + void *p_rng) +{ + int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED; + mbedtls_ecp_point K; + + mbedtls_ecp_point_init(&K); + + ret = mbedtls_ecjpake_derive_k(ctx, &K, f_rng, p_rng); + if (ret) { + goto cleanup; + } + + ret = mbedtls_ecp_point_write_binary(&ctx->grp, &K, ctx->point_format, + olen, buf, len); + if (ret != 0) { + goto cleanup; + } cleanup: mbedtls_ecp_point_free(&K); - mbedtls_mpi_free(&m_xm2_s); - mbedtls_mpi_free(&one); return ret; } @@ -798,7 +827,7 @@ int mbedtls_ecjpake_derive_secret(mbedtls_ecjpake_context *ctx, #include "mbedtls/platform.h" #if !defined(MBEDTLS_ECP_DP_SECP256R1_ENABLED) || \ - !defined(MBEDTLS_SHA256_C) + !defined(MBEDTLS_MD_CAN_SHA256) int mbedtls_ecjpake_self_test(int verbose) { (void) verbose; @@ -933,12 +962,42 @@ static const unsigned char ecjpake_test_cli_two[] = { 0xcc, 0x38, 0xdb, 0xdc, 0xae, 0x60, 0xd9, 0xc5, 0x4c }; +static const unsigned char ecjpake_test_shared_key[] = { + 0x04, 0x01, 0xab, 0xe9, 0xf2, 0xc7, 0x3a, 0x99, 0x14, 0xcb, 0x1f, 0x80, + 0xfb, 0x9d, 0xdb, 0x7e, 0x00, 0x12, 0xa8, 0x9c, 0x2f, 0x39, 0x27, 0x79, + 0xf9, 0x64, 0x40, 0x14, 0x75, 0xea, 0xc1, 0x31, 0x28, 0x43, 0x8f, 0xe1, + 0x12, 0x41, 0xd6, 0xc1, 0xe5, 0x5f, 0x7b, 0x80, 0x88, 0x94, 0xc9, 0xc0, + 0x27, 0xa3, 0x34, 0x41, 0xf5, 0xcb, 0xa1, 0xfe, 0x6c, 0xc7, 0xe6, 0x12, + 0x17, 0xc3, 0xde, 0x27, 0xb4, +}; + static const unsigned char ecjpake_test_pms[] = { 0xf3, 0xd4, 0x7f, 0x59, 0x98, 0x44, 0xdb, 0x92, 0xa5, 0x69, 0xbb, 0xe7, 0x98, 0x1e, 0x39, 0xd9, 0x31, 0xfd, 0x74, 0x3b, 0xf2, 0x2e, 0x98, 0xf9, 0xb4, 0x38, 0xf7, 0x19, 0xd3, 0xc4, 0xf3, 0x51 }; +/* + * PRNG for test - !!!INSECURE NEVER USE IN PRODUCTION!!! + * + * This is the linear congruential generator from numerical recipes, + * except we only use the low byte as the output. See + * https://en.wikipedia.org/wiki/Linear_congruential_generator#Parameters_in_common_use + */ +static int self_test_rng(void *ctx, unsigned char *out, size_t len) +{ + static uint32_t state = 42; + + (void) ctx; + + for (size_t i = 0; i < len; i++) { + state = state * 1664525u + 1013904223u; + out[i] = (unsigned char) state; + } + + return 0; +} + /* Load my private keys and generate the corresponding public keys */ static int ecjpake_test_load(mbedtls_ecjpake_context *ctx, const unsigned char *xm1, size_t len1, @@ -949,9 +1008,9 @@ static int ecjpake_test_load(mbedtls_ecjpake_context *ctx, MBEDTLS_MPI_CHK(mbedtls_mpi_read_binary(&ctx->xm1, xm1, len1)); MBEDTLS_MPI_CHK(mbedtls_mpi_read_binary(&ctx->xm2, xm2, len2)); MBEDTLS_MPI_CHK(mbedtls_ecp_mul(&ctx->grp, &ctx->Xm1, &ctx->xm1, - &ctx->grp.G, NULL, NULL)); + &ctx->grp.G, self_test_rng, NULL)); MBEDTLS_MPI_CHK(mbedtls_ecp_mul(&ctx->grp, &ctx->Xm2, &ctx->xm2, - &ctx->grp.G, NULL, NULL)); + &ctx->grp.G, self_test_rng, NULL)); cleanup: return ret; @@ -1101,6 +1160,13 @@ int mbedtls_ecjpake_self_test(int verbose) TEST_ASSERT(len == sizeof(ecjpake_test_pms)); TEST_ASSERT(memcmp(buf, ecjpake_test_pms, len) == 0); + /* Server derives K as unsigned binary data */ + TEST_ASSERT(mbedtls_ecjpake_write_shared_key(&srv, + buf, sizeof(buf), &len, ecjpake_lgc, NULL) == 0); + + TEST_ASSERT(len == sizeof(ecjpake_test_shared_key)); + TEST_ASSERT(memcmp(buf, ecjpake_test_shared_key, len) == 0); + memset(buf, 0, len); /* Avoid interferences with next step */ /* Client derives PMS */ @@ -1110,6 +1176,13 @@ int mbedtls_ecjpake_self_test(int verbose) TEST_ASSERT(len == sizeof(ecjpake_test_pms)); TEST_ASSERT(memcmp(buf, ecjpake_test_pms, len) == 0); + /* Client derives K as unsigned binary data */ + TEST_ASSERT(mbedtls_ecjpake_write_shared_key(&cli, + buf, sizeof(buf), &len, ecjpake_lgc, NULL) == 0); + + TEST_ASSERT(len == sizeof(ecjpake_test_shared_key)); + TEST_ASSERT(memcmp(buf, ecjpake_test_shared_key, len) == 0); + if (verbose != 0) { mbedtls_printf("passed\n"); } @@ -1136,7 +1209,7 @@ int mbedtls_ecjpake_self_test(int verbose) #undef TEST_ASSERT -#endif /* MBEDTLS_ECP_DP_SECP256R1_ENABLED && MBEDTLS_SHA256_C */ +#endif /* MBEDTLS_ECP_DP_SECP256R1_ENABLED && MBEDTLS_MD_CAN_SHA256 */ #endif /* MBEDTLS_SELF_TEST */ diff --git a/vendor/mbedtls/library/ecp.c b/vendor/mbedtls/library/ecp.c index dc8e27991e..427059bb53 100644 --- a/vendor/mbedtls/library/ecp.c +++ b/vendor/mbedtls/library/ecp.c @@ -2,19 +2,7 @@ * Elliptic curves over GF(p): generic functions * * Copyright The Mbed TLS Contributors - * SPDX-License-Identifier: Apache-2.0 - * - * Licensed under the Apache License, Version 2.0 (the "License"); you may - * not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT - * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. + * SPDX-License-Identifier: Apache-2.0 OR GPL-2.0-or-later */ /* @@ -72,187 +60,35 @@ #if defined(MBEDTLS_ECP_INTERNAL_ALT) #endif -#if defined(MBEDTLS_ECP_C) +#if defined(MBEDTLS_ECP_LIGHT) #include "mbedtls/ecp.h" #include "mbedtls/threading.h" #include "mbedtls/platform_util.h" #include "mbedtls/error.h" -#include "mbedtls/bn_mul.h" +#include "bn_mul.h" #include "ecp_invasive.h" #include #if !defined(MBEDTLS_ECP_ALT) -/* Parameter validation macros based on platform_util.h */ -#define ECP_VALIDATE_RET(cond) \ - MBEDTLS_INTERNAL_VALIDATE_RET(cond, MBEDTLS_ERR_ECP_BAD_INPUT_DATA) -#define ECP_VALIDATE(cond) \ - MBEDTLS_INTERNAL_VALIDATE(cond) - #include "mbedtls/platform.h" -#include "mbedtls/ecp_internal.h" - -#if !defined(MBEDTLS_ECP_NO_INTERNAL_RNG) -#if defined(MBEDTLS_HMAC_DRBG_C) -#include "mbedtls/hmac_drbg.h" -#elif defined(MBEDTLS_CTR_DRBG_C) -#include "mbedtls/ctr_drbg.h" -#else -#error \ - "Invalid configuration detected. Include check_config.h to ensure that the configuration is valid." -#endif -#endif /* MBEDTLS_ECP_NO_INTERNAL_RNG */ +#include "ecp_internal_alt.h" #if defined(MBEDTLS_SELF_TEST) /* * Counts of point addition and doubling, and field multiplications. * Used to test resistance of point multiplication to simple timing attacks. */ -static unsigned long add_count, dbl_count, mul_count; +#if defined(MBEDTLS_ECP_C) +static unsigned long add_count, dbl_count; +#endif /* MBEDTLS_ECP_C */ +static unsigned long mul_count; #endif -#if !defined(MBEDTLS_ECP_NO_INTERNAL_RNG) -/* - * Currently ecp_mul() takes a RNG function as an argument, used for - * side-channel protection, but it can be NULL. The initial reasoning was - * that people will pass non-NULL RNG when they care about side-channels, but - * unfortunately we have some APIs that call ecp_mul() with a NULL RNG, with - * no opportunity for the user to do anything about it. - * - * The obvious strategies for addressing that include: - * - change those APIs so that they take RNG arguments; - * - require a global RNG to be available to all crypto modules. - * - * Unfortunately those would break compatibility. So what we do instead is - * have our own internal DRBG instance, seeded from the secret scalar. - * - * The following is a light-weight abstraction layer for doing that with - * HMAC_DRBG (first choice) or CTR_DRBG. - */ - -#if defined(MBEDTLS_HMAC_DRBG_C) - -/* DRBG context type */ -typedef mbedtls_hmac_drbg_context ecp_drbg_context; - -/* DRBG context init */ -static inline void ecp_drbg_init(ecp_drbg_context *ctx) -{ - mbedtls_hmac_drbg_init(ctx); -} - -/* DRBG context free */ -static inline void ecp_drbg_free(ecp_drbg_context *ctx) -{ - mbedtls_hmac_drbg_free(ctx); -} - -/* DRBG function */ -static inline int ecp_drbg_random(void *p_rng, - unsigned char *output, size_t output_len) -{ - return mbedtls_hmac_drbg_random(p_rng, output, output_len); -} - -/* DRBG context seeding */ -static int ecp_drbg_seed(ecp_drbg_context *ctx, - const mbedtls_mpi *secret, size_t secret_len) -{ - int ret; - unsigned char secret_bytes[MBEDTLS_ECP_MAX_BYTES]; - /* The list starts with strong hashes */ - const mbedtls_md_type_t md_type = - (mbedtls_md_type_t) (mbedtls_md_list()[0]); - const mbedtls_md_info_t *md_info = mbedtls_md_info_from_type(md_type); - - if (secret_len > MBEDTLS_ECP_MAX_BYTES) { - ret = MBEDTLS_ERR_ECP_RANDOM_FAILED; - goto cleanup; - } - - MBEDTLS_MPI_CHK(mbedtls_mpi_write_binary(secret, - secret_bytes, secret_len)); - - ret = mbedtls_hmac_drbg_seed_buf(ctx, md_info, secret_bytes, secret_len); - -cleanup: - mbedtls_platform_zeroize(secret_bytes, secret_len); - - return ret; -} - -#elif defined(MBEDTLS_CTR_DRBG_C) - -/* DRBG context type */ -typedef mbedtls_ctr_drbg_context ecp_drbg_context; - -/* DRBG context init */ -static inline void ecp_drbg_init(ecp_drbg_context *ctx) -{ - mbedtls_ctr_drbg_init(ctx); -} - -/* DRBG context free */ -static inline void ecp_drbg_free(ecp_drbg_context *ctx) -{ - mbedtls_ctr_drbg_free(ctx); -} - -/* DRBG function */ -static inline int ecp_drbg_random(void *p_rng, - unsigned char *output, size_t output_len) -{ - return mbedtls_ctr_drbg_random(p_rng, output, output_len); -} - -/* - * Since CTR_DRBG doesn't have a seed_buf() function the way HMAC_DRBG does, - * we need to pass an entropy function when seeding. So we use a dummy - * function for that, and pass the actual entropy as customisation string. - * (During seeding of CTR_DRBG the entropy input and customisation string are - * concatenated before being used to update the secret state.) - */ -static int ecp_ctr_drbg_null_entropy(void *ctx, unsigned char *out, size_t len) -{ - (void) ctx; - memset(out, 0, len); - return 0; -} - -/* DRBG context seeding */ -static int ecp_drbg_seed(ecp_drbg_context *ctx, - const mbedtls_mpi *secret, size_t secret_len) -{ - int ret; - unsigned char secret_bytes[MBEDTLS_ECP_MAX_BYTES]; - - if (secret_len > MBEDTLS_ECP_MAX_BYTES) { - ret = MBEDTLS_ERR_ECP_RANDOM_FAILED; - goto cleanup; - } - - MBEDTLS_MPI_CHK(mbedtls_mpi_write_binary(secret, - secret_bytes, secret_len)); - - ret = mbedtls_ctr_drbg_seed(ctx, ecp_ctr_drbg_null_entropy, NULL, - secret_bytes, secret_len); - -cleanup: - mbedtls_platform_zeroize(secret_bytes, secret_len); - - return ret; -} - -#else -#error \ - "Invalid configuration detected. Include check_config.h to ensure that the configuration is valid." -#endif /* DRBG modules */ -#endif /* MBEDTLS_ECP_NO_INTERNAL_RNG */ - #if defined(MBEDTLS_ECP_RESTARTABLE) /* * Maximum number of "basic operations" to be done in a row. @@ -299,10 +135,6 @@ struct mbedtls_ecp_restart_mul { ecp_rsm_comb_core, /* ecp_mul_comb_core() */ ecp_rsm_final_norm, /* do the final normalization */ } state; -#if !defined(MBEDTLS_ECP_NO_INTERNAL_RNG) - ecp_drbg_context drbg_ctx; - unsigned char drbg_seeded; -#endif }; /* @@ -315,10 +147,6 @@ static void ecp_restart_rsm_init(mbedtls_ecp_restart_mul_ctx *ctx) ctx->T = NULL; ctx->T_size = 0; ctx->state = ecp_rsm_init; -#if !defined(MBEDTLS_ECP_NO_INTERNAL_RNG) - ecp_drbg_init(&ctx->drbg_ctx); - ctx->drbg_seeded = 0; -#endif } /* @@ -341,10 +169,6 @@ static void ecp_restart_rsm_free(mbedtls_ecp_restart_mul_ctx *ctx) mbedtls_free(ctx->T); } -#if !defined(MBEDTLS_ECP_NO_INTERNAL_RNG) - ecp_drbg_free(&ctx->drbg_ctx); -#endif - ecp_restart_rsm_init(ctx); } @@ -392,7 +216,6 @@ static void ecp_restart_ma_free(mbedtls_ecp_restart_muladd_ctx *ctx) */ void mbedtls_ecp_restart_init(mbedtls_ecp_restart_ctx *ctx) { - ECP_VALIDATE(ctx != NULL); ctx->ops_done = 0; ctx->depth = 0; ctx->rsm = NULL; @@ -424,8 +247,6 @@ int mbedtls_ecp_check_budget(const mbedtls_ecp_group *grp, mbedtls_ecp_restart_ctx *rs_ctx, unsigned ops) { - ECP_VALIDATE_RET(grp != NULL); - if (rs_ctx != NULL && ecp_max_ops != 0) { /* scale depending on curve size: the chosen reference is 256-bit, * and multiplication is quadratic. Round to the closest integer. */ @@ -492,6 +313,22 @@ int mbedtls_ecp_check_budget(const mbedtls_ecp_group *grp, #endif /* MBEDTLS_ECP_RESTARTABLE */ +#if defined(MBEDTLS_ECP_C) +static void mpi_init_many(mbedtls_mpi *arr, size_t size) +{ + while (size--) { + mbedtls_mpi_init(arr++); + } +} + +static void mpi_free_many(mbedtls_mpi *arr, size_t size) +{ + while (size--) { + mbedtls_mpi_free(arr++); + } +} +#endif /* MBEDTLS_ECP_C */ + /* * List of supported curves: * - internal ID @@ -500,9 +337,9 @@ int mbedtls_ecp_check_budget(const mbedtls_ecp_group *grp, * - readable name * * Curves are listed in order: largest curves first, and for a given size, - * fastest curves first. This provides the default order for the SSL module. + * fastest curves first. * - * Reminder: update profiles in x509_crt.c when adding a new curves! + * Reminder: update profiles in x509_crt.c and ssl_tls.c when adding a new curve! */ static const mbedtls_ecp_curve_info ecp_supported_curves[] = { @@ -664,8 +501,6 @@ mbedtls_ecp_curve_type mbedtls_ecp_get_type(const mbedtls_ecp_group *grp) */ void mbedtls_ecp_point_init(mbedtls_ecp_point *pt) { - ECP_VALIDATE(pt != NULL); - mbedtls_mpi_init(&pt->X); mbedtls_mpi_init(&pt->Y); mbedtls_mpi_init(&pt->Z); @@ -676,8 +511,6 @@ void mbedtls_ecp_point_init(mbedtls_ecp_point *pt) */ void mbedtls_ecp_group_init(mbedtls_ecp_group *grp) { - ECP_VALIDATE(grp != NULL); - grp->id = MBEDTLS_ECP_DP_NONE; mbedtls_mpi_init(&grp->P); mbedtls_mpi_init(&grp->A); @@ -700,8 +533,6 @@ void mbedtls_ecp_group_init(mbedtls_ecp_group *grp) */ void mbedtls_ecp_keypair_init(mbedtls_ecp_keypair *key) { - ECP_VALIDATE(key != NULL); - mbedtls_ecp_group_init(&key->grp); mbedtls_mpi_init(&key->d); mbedtls_ecp_point_init(&key->Q); @@ -721,6 +552,19 @@ void mbedtls_ecp_point_free(mbedtls_ecp_point *pt) mbedtls_mpi_free(&(pt->Z)); } +/* + * Check that the comb table (grp->T) is static initialized. + */ +static int ecp_group_is_static_comb_table(const mbedtls_ecp_group *grp) +{ +#if MBEDTLS_ECP_FIXED_POINT_OPTIM == 1 + return grp->T != NULL && grp->T_size == 0; +#else + (void) grp; + return 0; +#endif +} + /* * Unallocate (the components of) a group */ @@ -733,14 +577,17 @@ void mbedtls_ecp_group_free(mbedtls_ecp_group *grp) } if (grp->h != 1) { - mbedtls_mpi_free(&grp->P); mbedtls_mpi_free(&grp->A); mbedtls_mpi_free(&grp->B); mbedtls_ecp_point_free(&grp->G); + +#if !defined(MBEDTLS_ECP_WITH_MPI_UINT) mbedtls_mpi_free(&grp->N); + mbedtls_mpi_free(&grp->P); +#endif } - if (grp->T != NULL) { + if (!ecp_group_is_static_comb_table(grp) && grp->T != NULL) { for (i = 0; i < grp->T_size; i++) { mbedtls_ecp_point_free(&grp->T[i]); } @@ -770,9 +617,6 @@ void mbedtls_ecp_keypair_free(mbedtls_ecp_keypair *key) int mbedtls_ecp_copy(mbedtls_ecp_point *P, const mbedtls_ecp_point *Q) { int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED; - ECP_VALIDATE_RET(P != NULL); - ECP_VALIDATE_RET(Q != NULL); - MBEDTLS_MPI_CHK(mbedtls_mpi_copy(&P->X, &Q->X)); MBEDTLS_MPI_CHK(mbedtls_mpi_copy(&P->Y, &Q->Y)); MBEDTLS_MPI_CHK(mbedtls_mpi_copy(&P->Z, &Q->Z)); @@ -786,9 +630,6 @@ int mbedtls_ecp_copy(mbedtls_ecp_point *P, const mbedtls_ecp_point *Q) */ int mbedtls_ecp_group_copy(mbedtls_ecp_group *dst, const mbedtls_ecp_group *src) { - ECP_VALIDATE_RET(dst != NULL); - ECP_VALIDATE_RET(src != NULL); - return mbedtls_ecp_group_load(dst, src->id); } @@ -798,8 +639,6 @@ int mbedtls_ecp_group_copy(mbedtls_ecp_group *dst, const mbedtls_ecp_group *src) int mbedtls_ecp_set_zero(mbedtls_ecp_point *pt) { int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED; - ECP_VALIDATE_RET(pt != NULL); - MBEDTLS_MPI_CHK(mbedtls_mpi_lset(&pt->X, 1)); MBEDTLS_MPI_CHK(mbedtls_mpi_lset(&pt->Y, 1)); MBEDTLS_MPI_CHK(mbedtls_mpi_lset(&pt->Z, 0)); @@ -813,8 +652,6 @@ int mbedtls_ecp_set_zero(mbedtls_ecp_point *pt) */ int mbedtls_ecp_is_zero(mbedtls_ecp_point *pt) { - ECP_VALIDATE_RET(pt != NULL); - return mbedtls_mpi_cmp_int(&pt->Z, 0) == 0; } @@ -824,9 +661,6 @@ int mbedtls_ecp_is_zero(mbedtls_ecp_point *pt) int mbedtls_ecp_point_cmp(const mbedtls_ecp_point *P, const mbedtls_ecp_point *Q) { - ECP_VALIDATE_RET(P != NULL); - ECP_VALIDATE_RET(Q != NULL); - if (mbedtls_mpi_cmp_mpi(&P->X, &Q->X) == 0 && mbedtls_mpi_cmp_mpi(&P->Y, &Q->Y) == 0 && mbedtls_mpi_cmp_mpi(&P->Z, &Q->Z) == 0) { @@ -843,10 +677,6 @@ int mbedtls_ecp_point_read_string(mbedtls_ecp_point *P, int radix, const char *x, const char *y) { int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED; - ECP_VALIDATE_RET(P != NULL); - ECP_VALIDATE_RET(x != NULL); - ECP_VALIDATE_RET(y != NULL); - MBEDTLS_MPI_CHK(mbedtls_mpi_read_string(&P->X, radix, x)); MBEDTLS_MPI_CHK(mbedtls_mpi_read_string(&P->Y, radix, y)); MBEDTLS_MPI_CHK(mbedtls_mpi_lset(&P->Z, 1)); @@ -865,12 +695,10 @@ int mbedtls_ecp_point_write_binary(const mbedtls_ecp_group *grp, { int ret = MBEDTLS_ERR_ECP_FEATURE_UNAVAILABLE; size_t plen; - ECP_VALIDATE_RET(grp != NULL); - ECP_VALIDATE_RET(P != NULL); - ECP_VALIDATE_RET(olen != NULL); - ECP_VALIDATE_RET(buf != NULL); - ECP_VALIDATE_RET(format == MBEDTLS_ECP_PF_UNCOMPRESSED || - format == MBEDTLS_ECP_PF_COMPRESSED); + if (format != MBEDTLS_ECP_PF_UNCOMPRESSED && + format != MBEDTLS_ECP_PF_COMPRESSED) { + return MBEDTLS_ERR_ECP_BAD_INPUT_DATA; + } plen = mbedtls_mpi_size(&grp->P); @@ -928,6 +756,13 @@ int mbedtls_ecp_point_write_binary(const mbedtls_ecp_group *grp, return ret; } +#if defined(MBEDTLS_ECP_SHORT_WEIERSTRASS_ENABLED) +static int mbedtls_ecp_sw_derive_y(const mbedtls_ecp_group *grp, + const mbedtls_mpi *X, + mbedtls_mpi *Y, + int parity_bit); +#endif /* MBEDTLS_ECP_SHORT_WEIERSTRASS_ENABLED */ + /* * Import a point from unsigned binary data (SEC1 2.3.4 and RFC7748) */ @@ -937,10 +772,6 @@ int mbedtls_ecp_point_read_binary(const mbedtls_ecp_group *grp, { int ret = MBEDTLS_ERR_ECP_FEATURE_UNAVAILABLE; size_t plen; - ECP_VALIDATE_RET(grp != NULL); - ECP_VALIDATE_RET(pt != NULL); - ECP_VALIDATE_RET(buf != NULL); - if (ilen < 1) { return MBEDTLS_ERR_ECP_BAD_INPUT_DATA; } @@ -974,18 +805,29 @@ int mbedtls_ecp_point_read_binary(const mbedtls_ecp_group *grp, } } - if (buf[0] != 0x04) { - return MBEDTLS_ERR_ECP_FEATURE_UNAVAILABLE; - } - - if (ilen != 2 * plen + 1) { + if (ilen < 1 + plen) { return MBEDTLS_ERR_ECP_BAD_INPUT_DATA; } MBEDTLS_MPI_CHK(mbedtls_mpi_read_binary(&pt->X, buf + 1, plen)); - MBEDTLS_MPI_CHK(mbedtls_mpi_read_binary(&pt->Y, - buf + 1 + plen, plen)); MBEDTLS_MPI_CHK(mbedtls_mpi_lset(&pt->Z, 1)); + + if (buf[0] == 0x04) { + /* format == MBEDTLS_ECP_PF_UNCOMPRESSED */ + if (ilen != 1 + plen * 2) { + return MBEDTLS_ERR_ECP_BAD_INPUT_DATA; + } + return mbedtls_mpi_read_binary(&pt->Y, buf + 1 + plen, plen); + } else if (buf[0] == 0x02 || buf[0] == 0x03) { + /* format == MBEDTLS_ECP_PF_COMPRESSED */ + if (ilen != 1 + plen) { + return MBEDTLS_ERR_ECP_BAD_INPUT_DATA; + } + return mbedtls_ecp_sw_derive_y(grp, &pt->X, &pt->Y, + (buf[0] & 1)); + } else { + return MBEDTLS_ERR_ECP_BAD_INPUT_DATA; + } } #endif @@ -1005,11 +847,6 @@ int mbedtls_ecp_tls_read_point(const mbedtls_ecp_group *grp, { unsigned char data_len; const unsigned char *buf_start; - ECP_VALIDATE_RET(grp != NULL); - ECP_VALIDATE_RET(pt != NULL); - ECP_VALIDATE_RET(buf != NULL); - ECP_VALIDATE_RET(*buf != NULL); - /* * We must have at least two bytes (1 for length, at least one for data) */ @@ -1042,12 +879,10 @@ int mbedtls_ecp_tls_write_point(const mbedtls_ecp_group *grp, const mbedtls_ecp_ unsigned char *buf, size_t blen) { int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED; - ECP_VALIDATE_RET(grp != NULL); - ECP_VALIDATE_RET(pt != NULL); - ECP_VALIDATE_RET(olen != NULL); - ECP_VALIDATE_RET(buf != NULL); - ECP_VALIDATE_RET(format == MBEDTLS_ECP_PF_UNCOMPRESSED || - format == MBEDTLS_ECP_PF_COMPRESSED); + if (format != MBEDTLS_ECP_PF_UNCOMPRESSED && + format != MBEDTLS_ECP_PF_COMPRESSED) { + return MBEDTLS_ERR_ECP_BAD_INPUT_DATA; + } /* * buffer length must be at least one, for our length byte @@ -1078,10 +913,6 @@ int mbedtls_ecp_tls_read_group(mbedtls_ecp_group *grp, { int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED; mbedtls_ecp_group_id grp_id; - ECP_VALIDATE_RET(grp != NULL); - ECP_VALIDATE_RET(buf != NULL); - ECP_VALIDATE_RET(*buf != NULL); - if ((ret = mbedtls_ecp_tls_read_group_id(&grp_id, buf, len)) != 0) { return ret; } @@ -1098,10 +929,6 @@ int mbedtls_ecp_tls_read_group_id(mbedtls_ecp_group_id *grp, { uint16_t tls_id; const mbedtls_ecp_curve_info *curve_info; - ECP_VALIDATE_RET(grp != NULL); - ECP_VALIDATE_RET(buf != NULL); - ECP_VALIDATE_RET(*buf != NULL); - /* * We expect at least three bytes (see below) */ @@ -1119,9 +946,8 @@ int mbedtls_ecp_tls_read_group_id(mbedtls_ecp_group_id *grp, /* * Next two bytes are the namedcurve value */ - tls_id = *(*buf)++; - tls_id <<= 8; - tls_id |= *(*buf)++; + tls_id = MBEDTLS_GET_UINT16_BE(*buf, 0); + *buf += 2; if ((curve_info = mbedtls_ecp_curve_info_from_tls_id(tls_id)) == NULL) { return MBEDTLS_ERR_ECP_FEATURE_UNAVAILABLE; @@ -1139,10 +965,6 @@ int mbedtls_ecp_tls_write_group(const mbedtls_ecp_group *grp, size_t *olen, unsigned char *buf, size_t blen) { const mbedtls_ecp_curve_info *curve_info; - ECP_VALIDATE_RET(grp != NULL); - ECP_VALIDATE_RET(buf != NULL); - ECP_VALIDATE_RET(olen != NULL); - if ((curve_info = mbedtls_ecp_curve_info_from_grp_id(grp->id)) == NULL) { return MBEDTLS_ERR_ECP_BAD_INPUT_DATA; } @@ -1246,17 +1068,13 @@ static inline int mbedtls_mpi_mul_mod(const mbedtls_ecp_group *grp, * Reduce a mbedtls_mpi mod p in-place, to use after mbedtls_mpi_sub_mpi * N->s < 0 is a very fast test, which fails only if N is 0 */ -#define MOD_SUB(N) \ - while ((N).s < 0 && mbedtls_mpi_cmp_int(&(N), 0) != 0) \ - MBEDTLS_MPI_CHK(mbedtls_mpi_add_mpi(&(N), &(N), &grp->P)) - -#if (defined(MBEDTLS_ECP_SHORT_WEIERSTRASS_ENABLED) && \ - !(defined(MBEDTLS_ECP_NO_FALLBACK) && \ - defined(MBEDTLS_ECP_DOUBLE_JAC_ALT) && \ - defined(MBEDTLS_ECP_ADD_MIXED_ALT))) || \ - (defined(MBEDTLS_ECP_MONTGOMERY_ENABLED) && \ - !(defined(MBEDTLS_ECP_NO_FALLBACK) && \ - defined(MBEDTLS_ECP_DOUBLE_ADD_MXZ_ALT))) +#define MOD_SUB(N) \ + do { \ + while ((N)->s < 0 && mbedtls_mpi_cmp_int((N), 0) != 0) \ + MBEDTLS_MPI_CHK(mbedtls_mpi_add_mpi((N), (N), &grp->P)); \ + } while (0) + +MBEDTLS_MAYBE_UNUSED static inline int mbedtls_mpi_sub_mod(const mbedtls_ecp_group *grp, mbedtls_mpi *X, const mbedtls_mpi *A, @@ -1264,20 +1082,19 @@ static inline int mbedtls_mpi_sub_mod(const mbedtls_ecp_group *grp, { int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED; MBEDTLS_MPI_CHK(mbedtls_mpi_sub_mpi(X, A, B)); - MOD_SUB(*X); + MOD_SUB(X); cleanup: return ret; } -#endif /* All functions referencing mbedtls_mpi_sub_mod() are alt-implemented without fallback */ /* * Reduce a mbedtls_mpi mod p in-place, to use after mbedtls_mpi_add_mpi and mbedtls_mpi_mul_int. * We known P, N and the result are positive, so sub_abs is correct, and * a bit faster. */ -#define MOD_ADD(N) \ - while (mbedtls_mpi_cmp_mpi(&(N), &grp->P) >= 0) \ - MBEDTLS_MPI_CHK(mbedtls_mpi_sub_abs(&(N), &(N), &grp->P)) +#define MOD_ADD(N) \ + while (mbedtls_mpi_cmp_mpi((N), &grp->P) >= 0) \ + MBEDTLS_MPI_CHK(mbedtls_mpi_sub_abs((N), (N), &grp->P)) static inline int mbedtls_mpi_add_mod(const mbedtls_ecp_group *grp, mbedtls_mpi *X, @@ -1286,29 +1103,202 @@ static inline int mbedtls_mpi_add_mod(const mbedtls_ecp_group *grp, { int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED; MBEDTLS_MPI_CHK(mbedtls_mpi_add_mpi(X, A, B)); - MOD_ADD(*X); + MOD_ADD(X); +cleanup: + return ret; +} + +MBEDTLS_MAYBE_UNUSED +static inline int mbedtls_mpi_mul_int_mod(const mbedtls_ecp_group *grp, + mbedtls_mpi *X, + const mbedtls_mpi *A, + mbedtls_mpi_uint c) +{ + int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED; + + MBEDTLS_MPI_CHK(mbedtls_mpi_mul_int(X, A, c)); + MOD_ADD(X); +cleanup: + return ret; +} + +MBEDTLS_MAYBE_UNUSED +static inline int mbedtls_mpi_sub_int_mod(const mbedtls_ecp_group *grp, + mbedtls_mpi *X, + const mbedtls_mpi *A, + mbedtls_mpi_uint c) +{ + int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED; + + MBEDTLS_MPI_CHK(mbedtls_mpi_sub_int(X, A, c)); + MOD_SUB(X); cleanup: return ret; } -#if defined(MBEDTLS_ECP_SHORT_WEIERSTRASS_ENABLED) && \ - !(defined(MBEDTLS_ECP_NO_FALLBACK) && \ - defined(MBEDTLS_ECP_DOUBLE_JAC_ALT) && \ - defined(MBEDTLS_ECP_ADD_MIXED_ALT)) +#define MPI_ECP_SUB_INT(X, A, c) \ + MBEDTLS_MPI_CHK(mbedtls_mpi_sub_int_mod(grp, X, A, c)) + +MBEDTLS_MAYBE_UNUSED static inline int mbedtls_mpi_shift_l_mod(const mbedtls_ecp_group *grp, mbedtls_mpi *X, size_t count) { int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED; MBEDTLS_MPI_CHK(mbedtls_mpi_shift_l(X, count)); - MOD_ADD(*X); + MOD_ADD(X); cleanup: return ret; } -#endif \ - /* All functions referencing mbedtls_mpi_shift_l_mod() are alt-implemented without fallback */ + +/* + * Macro wrappers around ECP modular arithmetic + * + * Currently, these wrappers are defined via the bignum module. + */ + +#define MPI_ECP_ADD(X, A, B) \ + MBEDTLS_MPI_CHK(mbedtls_mpi_add_mod(grp, X, A, B)) + +#define MPI_ECP_SUB(X, A, B) \ + MBEDTLS_MPI_CHK(mbedtls_mpi_sub_mod(grp, X, A, B)) + +#define MPI_ECP_MUL(X, A, B) \ + MBEDTLS_MPI_CHK(mbedtls_mpi_mul_mod(grp, X, A, B)) + +#define MPI_ECP_SQR(X, A) \ + MBEDTLS_MPI_CHK(mbedtls_mpi_mul_mod(grp, X, A, A)) + +#define MPI_ECP_MUL_INT(X, A, c) \ + MBEDTLS_MPI_CHK(mbedtls_mpi_mul_int_mod(grp, X, A, c)) + +#define MPI_ECP_INV(dst, src) \ + MBEDTLS_MPI_CHK(mbedtls_mpi_inv_mod((dst), (src), &grp->P)) + +#define MPI_ECP_MOV(X, A) \ + MBEDTLS_MPI_CHK(mbedtls_mpi_copy(X, A)) + +#define MPI_ECP_SHIFT_L(X, count) \ + MBEDTLS_MPI_CHK(mbedtls_mpi_shift_l_mod(grp, X, count)) + +#define MPI_ECP_LSET(X, c) \ + MBEDTLS_MPI_CHK(mbedtls_mpi_lset(X, c)) + +#define MPI_ECP_CMP_INT(X, c) \ + mbedtls_mpi_cmp_int(X, c) + +#define MPI_ECP_CMP(X, Y) \ + mbedtls_mpi_cmp_mpi(X, Y) + +/* Needs f_rng, p_rng to be defined. */ +#define MPI_ECP_RAND(X) \ + MBEDTLS_MPI_CHK(mbedtls_mpi_random((X), 2, &grp->P, f_rng, p_rng)) + +/* Conditional negation + * Needs grp and a temporary MPI tmp to be defined. */ +#define MPI_ECP_COND_NEG(X, cond) \ + do \ + { \ + unsigned char nonzero = mbedtls_mpi_cmp_int((X), 0) != 0; \ + MBEDTLS_MPI_CHK(mbedtls_mpi_sub_mpi(&tmp, &grp->P, (X))); \ + MBEDTLS_MPI_CHK(mbedtls_mpi_safe_cond_assign((X), &tmp, \ + nonzero & cond)); \ + } while (0) + +#define MPI_ECP_NEG(X) MPI_ECP_COND_NEG((X), 1) + +#define MPI_ECP_VALID(X) \ + ((X)->p != NULL) + +#define MPI_ECP_COND_ASSIGN(X, Y, cond) \ + MBEDTLS_MPI_CHK(mbedtls_mpi_safe_cond_assign((X), (Y), (cond))) + +#define MPI_ECP_COND_SWAP(X, Y, cond) \ + MBEDTLS_MPI_CHK(mbedtls_mpi_safe_cond_swap((X), (Y), (cond))) #if defined(MBEDTLS_ECP_SHORT_WEIERSTRASS_ENABLED) + +/* + * Computes the right-hand side of the Short Weierstrass equation + * RHS = X^3 + A X + B + */ +static int ecp_sw_rhs(const mbedtls_ecp_group *grp, + mbedtls_mpi *rhs, + const mbedtls_mpi *X) +{ + int ret; + + /* Compute X^3 + A X + B as X (X^2 + A) + B */ + MPI_ECP_SQR(rhs, X); + + /* Special case for A = -3 */ + if (mbedtls_ecp_group_a_is_minus_3(grp)) { + MPI_ECP_SUB_INT(rhs, rhs, 3); + } else { + MPI_ECP_ADD(rhs, rhs, &grp->A); + } + + MPI_ECP_MUL(rhs, rhs, X); + MPI_ECP_ADD(rhs, rhs, &grp->B); + +cleanup: + return ret; +} + +/* + * Derive Y from X and a parity bit + */ +static int mbedtls_ecp_sw_derive_y(const mbedtls_ecp_group *grp, + const mbedtls_mpi *X, + mbedtls_mpi *Y, + int parity_bit) +{ + /* w = y^2 = x^3 + ax + b + * y = sqrt(w) = w^((p+1)/4) mod p (for prime p where p = 3 mod 4) + * + * Note: this method for extracting square root does not validate that w + * was indeed a square so this function will return garbage in Y if X + * does not correspond to a point on the curve. + */ + + /* Check prerequisite p = 3 mod 4 */ + if (mbedtls_mpi_get_bit(&grp->P, 0) != 1 || + mbedtls_mpi_get_bit(&grp->P, 1) != 1) { + return MBEDTLS_ERR_ECP_FEATURE_UNAVAILABLE; + } + + int ret; + mbedtls_mpi exp; + mbedtls_mpi_init(&exp); + + /* use Y to store intermediate result, actually w above */ + MBEDTLS_MPI_CHK(ecp_sw_rhs(grp, Y, X)); + + /* w = y^2 */ /* Y contains y^2 intermediate result */ + /* exp = ((p+1)/4) */ + MBEDTLS_MPI_CHK(mbedtls_mpi_add_int(&exp, &grp->P, 1)); + MBEDTLS_MPI_CHK(mbedtls_mpi_shift_r(&exp, 2)); + /* sqrt(w) = w^((p+1)/4) mod p (for prime p where p = 3 mod 4) */ + MBEDTLS_MPI_CHK(mbedtls_mpi_exp_mod(Y, Y /*y^2*/, &exp, &grp->P, NULL)); + + /* check parity bit match or else invert Y */ + /* This quick inversion implementation is valid because Y != 0 for all + * Short Weierstrass curves supported by mbedtls, as each supported curve + * has an order that is a large prime, so each supported curve does not + * have any point of order 2, and a point with Y == 0 would be of order 2 */ + if (mbedtls_mpi_get_bit(Y, 0) != parity_bit) { + MBEDTLS_MPI_CHK(mbedtls_mpi_sub_mpi(Y, &grp->P, Y)); + } + +cleanup: + + mbedtls_mpi_free(&exp); + return ret; +} +#endif /* MBEDTLS_ECP_SHORT_WEIERSTRASS_ENABLED */ + +#if defined(MBEDTLS_ECP_C) +#if defined(MBEDTLS_ECP_SHORT_WEIERSTRASS_ENABLED) /* * For curves in short Weierstrass form, we do all the internal operations in * Jacobian coordinates. @@ -1323,7 +1313,7 @@ static inline int mbedtls_mpi_shift_l_mod(const mbedtls_ecp_group *grp, */ static int ecp_normalize_jac(const mbedtls_ecp_group *grp, mbedtls_ecp_point *pt) { - if (mbedtls_mpi_cmp_int(&pt->Z, 0) == 0) { + if (MPI_ECP_CMP_INT(&pt->Z, 0) == 0) { return 0; } @@ -1337,30 +1327,20 @@ static int ecp_normalize_jac(const mbedtls_ecp_group *grp, mbedtls_ecp_point *pt return MBEDTLS_ERR_ECP_FEATURE_UNAVAILABLE; #else int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED; - mbedtls_mpi Zi, ZZi; - mbedtls_mpi_init(&Zi); mbedtls_mpi_init(&ZZi); + mbedtls_mpi T; + mbedtls_mpi_init(&T); - /* - * X = X / Z^2 mod p - */ - MBEDTLS_MPI_CHK(mbedtls_mpi_inv_mod(&Zi, &pt->Z, &grp->P)); - MBEDTLS_MPI_CHK(mbedtls_mpi_mul_mod(grp, &ZZi, &Zi, &Zi)); - MBEDTLS_MPI_CHK(mbedtls_mpi_mul_mod(grp, &pt->X, &pt->X, &ZZi)); + MPI_ECP_INV(&T, &pt->Z); /* T <- 1 / Z */ + MPI_ECP_MUL(&pt->Y, &pt->Y, &T); /* Y' <- Y*T = Y / Z */ + MPI_ECP_SQR(&T, &T); /* T <- T^2 = 1 / Z^2 */ + MPI_ECP_MUL(&pt->X, &pt->X, &T); /* X <- X * T = X / Z^2 */ + MPI_ECP_MUL(&pt->Y, &pt->Y, &T); /* Y'' <- Y' * T = Y / Z^3 */ - /* - * Y = Y / Z^3 mod p - */ - MBEDTLS_MPI_CHK(mbedtls_mpi_mul_mod(grp, &pt->Y, &pt->Y, &ZZi)); - MBEDTLS_MPI_CHK(mbedtls_mpi_mul_mod(grp, &pt->Y, &pt->Y, &Zi)); - - /* - * Z = 1 - */ - MBEDTLS_MPI_CHK(mbedtls_mpi_lset(&pt->Z, 1)); + MPI_ECP_LSET(&pt->Z, 1); cleanup: - mbedtls_mpi_free(&Zi); mbedtls_mpi_free(&ZZi); + mbedtls_mpi_free(&T); return ret; #endif /* !defined(MBEDTLS_ECP_NO_FALLBACK) || !defined(MBEDTLS_ECP_NORMALIZE_JAC_ALT) */ @@ -1395,50 +1375,54 @@ static int ecp_normalize_jac_many(const mbedtls_ecp_group *grp, #else int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED; size_t i; - mbedtls_mpi *c, u, Zi, ZZi; + mbedtls_mpi *c, t; if ((c = mbedtls_calloc(T_size, sizeof(mbedtls_mpi))) == NULL) { return MBEDTLS_ERR_ECP_ALLOC_FAILED; } - for (i = 0; i < T_size; i++) { - mbedtls_mpi_init(&c[i]); - } - - mbedtls_mpi_init(&u); mbedtls_mpi_init(&Zi); mbedtls_mpi_init(&ZZi); + mbedtls_mpi_init(&t); + mpi_init_many(c, T_size); /* - * c[i] = Z_0 * ... * Z_i + * c[i] = Z_0 * ... * Z_i, i = 0,..,n := T_size-1 */ - MBEDTLS_MPI_CHK(mbedtls_mpi_copy(&c[0], &T[0]->Z)); + MPI_ECP_MOV(&c[0], &T[0]->Z); for (i = 1; i < T_size; i++) { - MBEDTLS_MPI_CHK(mbedtls_mpi_mul_mod(grp, &c[i], &c[i-1], &T[i]->Z)); + MPI_ECP_MUL(&c[i], &c[i-1], &T[i]->Z); } /* - * u = 1 / (Z_0 * ... * Z_n) mod P + * c[n] = 1 / (Z_0 * ... * Z_n) mod P */ - MBEDTLS_MPI_CHK(mbedtls_mpi_inv_mod(&u, &c[T_size-1], &grp->P)); + MPI_ECP_INV(&c[T_size-1], &c[T_size-1]); for (i = T_size - 1;; i--) { - /* - * Zi = 1 / Z_i mod p - * u = 1 / (Z_0 * ... * Z_i) mod P + /* At the start of iteration i (note that i decrements), we have + * - c[j] = Z_0 * .... * Z_j for j < i, + * - c[j] = 1 / (Z_0 * .... * Z_j) for j == i, + * + * This is maintained via + * - c[i-1] <- c[i] * Z_i + * + * We also derive 1/Z_i = c[i] * c[i-1] for i>0 and use that + * to do the actual normalization. For i==0, we already have + * c[0] = 1 / Z_0. */ - if (i == 0) { - MBEDTLS_MPI_CHK(mbedtls_mpi_copy(&Zi, &u)); + + if (i > 0) { + /* Compute 1/Z_i and establish invariant for the next iteration. */ + MPI_ECP_MUL(&t, &c[i], &c[i-1]); + MPI_ECP_MUL(&c[i-1], &c[i], &T[i]->Z); } else { - MBEDTLS_MPI_CHK(mbedtls_mpi_mul_mod(grp, &Zi, &u, &c[i-1])); - MBEDTLS_MPI_CHK(mbedtls_mpi_mul_mod(grp, &u, &u, &T[i]->Z)); + MPI_ECP_MOV(&t, &c[0]); } - /* - * proceed as in normalize() - */ - MBEDTLS_MPI_CHK(mbedtls_mpi_mul_mod(grp, &ZZi, &Zi, &Zi)); - MBEDTLS_MPI_CHK(mbedtls_mpi_mul_mod(grp, &T[i]->X, &T[i]->X, &ZZi)); - MBEDTLS_MPI_CHK(mbedtls_mpi_mul_mod(grp, &T[i]->Y, &T[i]->Y, &ZZi)); - MBEDTLS_MPI_CHK(mbedtls_mpi_mul_mod(grp, &T[i]->Y, &T[i]->Y, &Zi)); + /* Now t holds 1 / Z_i; normalize as in ecp_normalize_jac() */ + MPI_ECP_MUL(&T[i]->Y, &T[i]->Y, &t); + MPI_ECP_SQR(&t, &t); + MPI_ECP_MUL(&T[i]->X, &T[i]->X, &t); + MPI_ECP_MUL(&T[i]->Y, &T[i]->Y, &t); /* * Post-precessing: reclaim some memory by shrinking coordinates @@ -1448,7 +1432,8 @@ static int ecp_normalize_jac_many(const mbedtls_ecp_group *grp, */ MBEDTLS_MPI_CHK(mbedtls_mpi_shrink(&T[i]->X, grp->P.n)); MBEDTLS_MPI_CHK(mbedtls_mpi_shrink(&T[i]->Y, grp->P.n)); - mbedtls_mpi_free(&T[i]->Z); + + MPI_ECP_LSET(&T[i]->Z, 1); if (i == 0) { break; @@ -1457,10 +1442,8 @@ static int ecp_normalize_jac_many(const mbedtls_ecp_group *grp, cleanup: - mbedtls_mpi_free(&u); mbedtls_mpi_free(&Zi); mbedtls_mpi_free(&ZZi); - for (i = 0; i < T_size; i++) { - mbedtls_mpi_free(&c[i]); - } + mbedtls_mpi_free(&t); + mpi_free_many(c, T_size); mbedtls_free(c); return ret; @@ -1476,19 +1459,13 @@ static int ecp_safe_invert_jac(const mbedtls_ecp_group *grp, unsigned char inv) { int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED; - unsigned char nonzero; - mbedtls_mpi mQY; - - mbedtls_mpi_init(&mQY); + mbedtls_mpi tmp; + mbedtls_mpi_init(&tmp); - /* Use the fact that -Q.Y mod P = P - Q.Y unless Q.Y == 0 */ - MBEDTLS_MPI_CHK(mbedtls_mpi_sub_mpi(&mQY, &grp->P, &Q->Y)); - nonzero = mbedtls_mpi_cmp_int(&Q->Y, 0) != 0; - MBEDTLS_MPI_CHK(mbedtls_mpi_safe_cond_assign(&Q->Y, &mQY, inv & nonzero)); + MPI_ECP_COND_NEG(&Q->Y, inv); cleanup: - mbedtls_mpi_free(&mQY); - + mbedtls_mpi_free(&tmp); return ret; } @@ -1507,7 +1484,8 @@ static int ecp_safe_invert_jac(const mbedtls_ecp_group *grp, * 3M + 6S + 1a otherwise */ static int ecp_double_jac(const mbedtls_ecp_group *grp, mbedtls_ecp_point *R, - const mbedtls_ecp_point *P) + const mbedtls_ecp_point *P, + mbedtls_mpi tmp[4]) { #if defined(MBEDTLS_SELF_TEST) dbl_count++; @@ -1523,63 +1501,60 @@ static int ecp_double_jac(const mbedtls_ecp_group *grp, mbedtls_ecp_point *R, return MBEDTLS_ERR_ECP_FEATURE_UNAVAILABLE; #else int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED; - mbedtls_mpi M, S, T, U; - - mbedtls_mpi_init(&M); mbedtls_mpi_init(&S); mbedtls_mpi_init(&T); mbedtls_mpi_init(&U); /* Special case for A = -3 */ - if (grp->A.p == NULL) { - /* M = 3(X + Z^2)(X - Z^2) */ - MBEDTLS_MPI_CHK(mbedtls_mpi_mul_mod(grp, &S, &P->Z, &P->Z)); - MBEDTLS_MPI_CHK(mbedtls_mpi_add_mod(grp, &T, &P->X, &S)); - MBEDTLS_MPI_CHK(mbedtls_mpi_sub_mod(grp, &U, &P->X, &S)); - MBEDTLS_MPI_CHK(mbedtls_mpi_mul_mod(grp, &S, &T, &U)); - MBEDTLS_MPI_CHK(mbedtls_mpi_mul_int(&M, &S, 3)); MOD_ADD(M); + if (mbedtls_ecp_group_a_is_minus_3(grp)) { + /* tmp[0] <- M = 3(X + Z^2)(X - Z^2) */ + MPI_ECP_SQR(&tmp[1], &P->Z); + MPI_ECP_ADD(&tmp[2], &P->X, &tmp[1]); + MPI_ECP_SUB(&tmp[3], &P->X, &tmp[1]); + MPI_ECP_MUL(&tmp[1], &tmp[2], &tmp[3]); + MPI_ECP_MUL_INT(&tmp[0], &tmp[1], 3); } else { - /* M = 3.X^2 */ - MBEDTLS_MPI_CHK(mbedtls_mpi_mul_mod(grp, &S, &P->X, &P->X)); - MBEDTLS_MPI_CHK(mbedtls_mpi_mul_int(&M, &S, 3)); MOD_ADD(M); + /* tmp[0] <- M = 3.X^2 + A.Z^4 */ + MPI_ECP_SQR(&tmp[1], &P->X); + MPI_ECP_MUL_INT(&tmp[0], &tmp[1], 3); /* Optimize away for "koblitz" curves with A = 0 */ - if (mbedtls_mpi_cmp_int(&grp->A, 0) != 0) { + if (MPI_ECP_CMP_INT(&grp->A, 0) != 0) { /* M += A.Z^4 */ - MBEDTLS_MPI_CHK(mbedtls_mpi_mul_mod(grp, &S, &P->Z, &P->Z)); - MBEDTLS_MPI_CHK(mbedtls_mpi_mul_mod(grp, &T, &S, &S)); - MBEDTLS_MPI_CHK(mbedtls_mpi_mul_mod(grp, &S, &T, &grp->A)); - MBEDTLS_MPI_CHK(mbedtls_mpi_add_mod(grp, &M, &M, &S)); + MPI_ECP_SQR(&tmp[1], &P->Z); + MPI_ECP_SQR(&tmp[2], &tmp[1]); + MPI_ECP_MUL(&tmp[1], &tmp[2], &grp->A); + MPI_ECP_ADD(&tmp[0], &tmp[0], &tmp[1]); } } - /* S = 4.X.Y^2 */ - MBEDTLS_MPI_CHK(mbedtls_mpi_mul_mod(grp, &T, &P->Y, &P->Y)); - MBEDTLS_MPI_CHK(mbedtls_mpi_shift_l_mod(grp, &T, 1)); - MBEDTLS_MPI_CHK(mbedtls_mpi_mul_mod(grp, &S, &P->X, &T)); - MBEDTLS_MPI_CHK(mbedtls_mpi_shift_l_mod(grp, &S, 1)); + /* tmp[1] <- S = 4.X.Y^2 */ + MPI_ECP_SQR(&tmp[2], &P->Y); + MPI_ECP_SHIFT_L(&tmp[2], 1); + MPI_ECP_MUL(&tmp[1], &P->X, &tmp[2]); + MPI_ECP_SHIFT_L(&tmp[1], 1); - /* U = 8.Y^4 */ - MBEDTLS_MPI_CHK(mbedtls_mpi_mul_mod(grp, &U, &T, &T)); - MBEDTLS_MPI_CHK(mbedtls_mpi_shift_l_mod(grp, &U, 1)); + /* tmp[3] <- U = 8.Y^4 */ + MPI_ECP_SQR(&tmp[3], &tmp[2]); + MPI_ECP_SHIFT_L(&tmp[3], 1); - /* T = M^2 - 2.S */ - MBEDTLS_MPI_CHK(mbedtls_mpi_mul_mod(grp, &T, &M, &M)); - MBEDTLS_MPI_CHK(mbedtls_mpi_sub_mod(grp, &T, &T, &S)); - MBEDTLS_MPI_CHK(mbedtls_mpi_sub_mod(grp, &T, &T, &S)); + /* tmp[2] <- T = M^2 - 2.S */ + MPI_ECP_SQR(&tmp[2], &tmp[0]); + MPI_ECP_SUB(&tmp[2], &tmp[2], &tmp[1]); + MPI_ECP_SUB(&tmp[2], &tmp[2], &tmp[1]); - /* S = M(S - T) - U */ - MBEDTLS_MPI_CHK(mbedtls_mpi_sub_mod(grp, &S, &S, &T)); - MBEDTLS_MPI_CHK(mbedtls_mpi_mul_mod(grp, &S, &S, &M)); - MBEDTLS_MPI_CHK(mbedtls_mpi_sub_mod(grp, &S, &S, &U)); + /* tmp[1] <- S = M(S - T) - U */ + MPI_ECP_SUB(&tmp[1], &tmp[1], &tmp[2]); + MPI_ECP_MUL(&tmp[1], &tmp[1], &tmp[0]); + MPI_ECP_SUB(&tmp[1], &tmp[1], &tmp[3]); - /* U = 2.Y.Z */ - MBEDTLS_MPI_CHK(mbedtls_mpi_mul_mod(grp, &U, &P->Y, &P->Z)); - MBEDTLS_MPI_CHK(mbedtls_mpi_shift_l_mod(grp, &U, 1)); + /* tmp[3] <- U = 2.Y.Z */ + MPI_ECP_MUL(&tmp[3], &P->Y, &P->Z); + MPI_ECP_SHIFT_L(&tmp[3], 1); - MBEDTLS_MPI_CHK(mbedtls_mpi_copy(&R->X, &T)); - MBEDTLS_MPI_CHK(mbedtls_mpi_copy(&R->Y, &S)); - MBEDTLS_MPI_CHK(mbedtls_mpi_copy(&R->Z, &U)); + /* Store results */ + MPI_ECP_MOV(&R->X, &tmp[2]); + MPI_ECP_MOV(&R->Y, &tmp[1]); + MPI_ECP_MOV(&R->Z, &tmp[3]); cleanup: - mbedtls_mpi_free(&M); mbedtls_mpi_free(&S); mbedtls_mpi_free(&T); mbedtls_mpi_free(&U); return ret; #endif /* !defined(MBEDTLS_ECP_NO_FALLBACK) || !defined(MBEDTLS_ECP_DOUBLE_JAC_ALT) */ @@ -1591,6 +1566,10 @@ static int ecp_double_jac(const mbedtls_ecp_group *grp, mbedtls_ecp_point *R, * The coordinates of Q must be normalized (= affine), * but those of P don't need to. R is not normalized. * + * P,Q,R may alias, but only at the level of EC points: they must be either + * equal as pointers, or disjoint (including the coordinate data buffers). + * Fine-grained aliasing at the level of coordinates is not supported. + * * Special cases: (1) P or Q is zero, (2) R is zero, (3) P == Q. * None of these cases can happen as intermediate step in ecp_mul_comb(): * - at each step, P, Q and R are multiples of the base point, the factor @@ -1599,12 +1578,11 @@ static int ecp_double_jac(const mbedtls_ecp_group *grp, mbedtls_ecp_point *R, * due to the choice of precomputed points in the modified comb method. * So branches for these cases do not leak secret information. * - * We accept Q->Z being unset (saving memory in tables) as meaning 1. - * * Cost: 1A := 8M + 3S */ static int ecp_add_mixed(const mbedtls_ecp_group *grp, mbedtls_ecp_point *R, - const mbedtls_ecp_point *P, const mbedtls_ecp_point *Q) + const mbedtls_ecp_point *P, const mbedtls_ecp_point *Q, + mbedtls_mpi tmp[4]) { #if defined(MBEDTLS_SELF_TEST) add_count++; @@ -1620,40 +1598,47 @@ static int ecp_add_mixed(const mbedtls_ecp_group *grp, mbedtls_ecp_point *R, return MBEDTLS_ERR_ECP_FEATURE_UNAVAILABLE; #else int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED; - mbedtls_mpi T1, T2, T3, T4, X, Y, Z; + + /* NOTE: Aliasing between input and output is allowed, so one has to make + * sure that at the point X,Y,Z are written, {P,Q}->{X,Y,Z} are no + * longer read from. */ + mbedtls_mpi * const X = &R->X; + mbedtls_mpi * const Y = &R->Y; + mbedtls_mpi * const Z = &R->Z; + + if (!MPI_ECP_VALID(&Q->Z)) { + return MBEDTLS_ERR_ECP_BAD_INPUT_DATA; + } /* * Trivial cases: P == 0 or Q == 0 (case 1) */ - if (mbedtls_mpi_cmp_int(&P->Z, 0) == 0) { + if (MPI_ECP_CMP_INT(&P->Z, 0) == 0) { return mbedtls_ecp_copy(R, Q); } - if (Q->Z.p != NULL && mbedtls_mpi_cmp_int(&Q->Z, 0) == 0) { + if (MPI_ECP_CMP_INT(&Q->Z, 0) == 0) { return mbedtls_ecp_copy(R, P); } /* * Make sure Q coordinates are normalized */ - if (Q->Z.p != NULL && mbedtls_mpi_cmp_int(&Q->Z, 1) != 0) { + if (MPI_ECP_CMP_INT(&Q->Z, 1) != 0) { return MBEDTLS_ERR_ECP_BAD_INPUT_DATA; } - mbedtls_mpi_init(&T1); mbedtls_mpi_init(&T2); mbedtls_mpi_init(&T3); mbedtls_mpi_init(&T4); - mbedtls_mpi_init(&X); mbedtls_mpi_init(&Y); mbedtls_mpi_init(&Z); - - MBEDTLS_MPI_CHK(mbedtls_mpi_mul_mod(grp, &T1, &P->Z, &P->Z)); - MBEDTLS_MPI_CHK(mbedtls_mpi_mul_mod(grp, &T2, &T1, &P->Z)); - MBEDTLS_MPI_CHK(mbedtls_mpi_mul_mod(grp, &T1, &T1, &Q->X)); - MBEDTLS_MPI_CHK(mbedtls_mpi_mul_mod(grp, &T2, &T2, &Q->Y)); - MBEDTLS_MPI_CHK(mbedtls_mpi_sub_mod(grp, &T1, &T1, &P->X)); - MBEDTLS_MPI_CHK(mbedtls_mpi_sub_mod(grp, &T2, &T2, &P->Y)); + MPI_ECP_SQR(&tmp[0], &P->Z); + MPI_ECP_MUL(&tmp[1], &tmp[0], &P->Z); + MPI_ECP_MUL(&tmp[0], &tmp[0], &Q->X); + MPI_ECP_MUL(&tmp[1], &tmp[1], &Q->Y); + MPI_ECP_SUB(&tmp[0], &tmp[0], &P->X); + MPI_ECP_SUB(&tmp[1], &tmp[1], &P->Y); /* Special cases (2) and (3) */ - if (mbedtls_mpi_cmp_int(&T1, 0) == 0) { - if (mbedtls_mpi_cmp_int(&T2, 0) == 0) { - ret = ecp_double_jac(grp, R, P); + if (MPI_ECP_CMP_INT(&tmp[0], 0) == 0) { + if (MPI_ECP_CMP_INT(&tmp[1], 0) == 0) { + ret = ecp_double_jac(grp, R, P, tmp); goto cleanup; } else { ret = mbedtls_ecp_set_zero(R); @@ -1661,28 +1646,26 @@ static int ecp_add_mixed(const mbedtls_ecp_group *grp, mbedtls_ecp_point *R, } } - MBEDTLS_MPI_CHK(mbedtls_mpi_mul_mod(grp, &Z, &P->Z, &T1)); - MBEDTLS_MPI_CHK(mbedtls_mpi_mul_mod(grp, &T3, &T1, &T1)); - MBEDTLS_MPI_CHK(mbedtls_mpi_mul_mod(grp, &T4, &T3, &T1)); - MBEDTLS_MPI_CHK(mbedtls_mpi_mul_mod(grp, &T3, &T3, &P->X)); - MBEDTLS_MPI_CHK(mbedtls_mpi_copy(&T1, &T3)); - MBEDTLS_MPI_CHK(mbedtls_mpi_shift_l_mod(grp, &T1, 1)); - MBEDTLS_MPI_CHK(mbedtls_mpi_mul_mod(grp, &X, &T2, &T2)); - MBEDTLS_MPI_CHK(mbedtls_mpi_sub_mod(grp, &X, &X, &T1)); - MBEDTLS_MPI_CHK(mbedtls_mpi_sub_mod(grp, &X, &X, &T4)); - MBEDTLS_MPI_CHK(mbedtls_mpi_sub_mod(grp, &T3, &T3, &X)); - MBEDTLS_MPI_CHK(mbedtls_mpi_mul_mod(grp, &T3, &T3, &T2)); - MBEDTLS_MPI_CHK(mbedtls_mpi_mul_mod(grp, &T4, &T4, &P->Y)); - MBEDTLS_MPI_CHK(mbedtls_mpi_sub_mod(grp, &Y, &T3, &T4)); - - MBEDTLS_MPI_CHK(mbedtls_mpi_copy(&R->X, &X)); - MBEDTLS_MPI_CHK(mbedtls_mpi_copy(&R->Y, &Y)); - MBEDTLS_MPI_CHK(mbedtls_mpi_copy(&R->Z, &Z)); + /* {P,Q}->Z no longer used, so OK to write to Z even if there's aliasing. */ + MPI_ECP_MUL(Z, &P->Z, &tmp[0]); + MPI_ECP_SQR(&tmp[2], &tmp[0]); + MPI_ECP_MUL(&tmp[3], &tmp[2], &tmp[0]); + MPI_ECP_MUL(&tmp[2], &tmp[2], &P->X); -cleanup: + MPI_ECP_MOV(&tmp[0], &tmp[2]); + MPI_ECP_SHIFT_L(&tmp[0], 1); - mbedtls_mpi_free(&T1); mbedtls_mpi_free(&T2); mbedtls_mpi_free(&T3); mbedtls_mpi_free(&T4); - mbedtls_mpi_free(&X); mbedtls_mpi_free(&Y); mbedtls_mpi_free(&Z); + /* {P,Q}->X no longer used, so OK to write to X even if there's aliasing. */ + MPI_ECP_SQR(X, &tmp[1]); + MPI_ECP_SUB(X, X, &tmp[0]); + MPI_ECP_SUB(X, X, &tmp[3]); + MPI_ECP_SUB(&tmp[2], &tmp[2], X); + MPI_ECP_MUL(&tmp[2], &tmp[2], &tmp[1]); + MPI_ECP_MUL(&tmp[3], &tmp[3], &P->Y); + /* {P,Q}->Y no longer used, so OK to write to Y even if there's aliasing. */ + MPI_ECP_SUB(Y, &tmp[2], &tmp[3]); + +cleanup: return ret; #endif /* !defined(MBEDTLS_ECP_NO_FALLBACK) || !defined(MBEDTLS_ECP_ADD_MIXED_ALT) */ @@ -1708,26 +1691,28 @@ static int ecp_randomize_jac(const mbedtls_ecp_group *grp, mbedtls_ecp_point *pt return MBEDTLS_ERR_ECP_FEATURE_UNAVAILABLE; #else int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED; - mbedtls_mpi l, ll; + mbedtls_mpi l; - mbedtls_mpi_init(&l); mbedtls_mpi_init(&ll); + mbedtls_mpi_init(&l); /* Generate l such that 1 < l < p */ - MBEDTLS_MPI_CHK(mbedtls_mpi_random(&l, 2, &grp->P, f_rng, p_rng)); + MPI_ECP_RAND(&l); - /* Z = l * Z */ - MBEDTLS_MPI_CHK(mbedtls_mpi_mul_mod(grp, &pt->Z, &pt->Z, &l)); + /* Z' = l * Z */ + MPI_ECP_MUL(&pt->Z, &pt->Z, &l); - /* X = l^2 * X */ - MBEDTLS_MPI_CHK(mbedtls_mpi_mul_mod(grp, &ll, &l, &l)); - MBEDTLS_MPI_CHK(mbedtls_mpi_mul_mod(grp, &pt->X, &pt->X, &ll)); + /* Y' = l * Y */ + MPI_ECP_MUL(&pt->Y, &pt->Y, &l); - /* Y = l^3 * Y */ - MBEDTLS_MPI_CHK(mbedtls_mpi_mul_mod(grp, &ll, &ll, &l)); - MBEDTLS_MPI_CHK(mbedtls_mpi_mul_mod(grp, &pt->Y, &pt->Y, &ll)); + /* X' = l^2 * X */ + MPI_ECP_SQR(&l, &l); + MPI_ECP_MUL(&pt->X, &pt->X, &l); + + /* Y'' = l^2 * Y' = l^3 * Y */ + MPI_ECP_MUL(&pt->Y, &pt->Y, &l); cleanup: - mbedtls_mpi_free(&l); mbedtls_mpi_free(&ll); + mbedtls_mpi_free(&l); if (ret == MBEDTLS_ERR_MPI_NOT_ACCEPTABLE) { ret = MBEDTLS_ERR_ECP_RANDOM_FAILED; @@ -1870,7 +1855,11 @@ static int ecp_precompute_comb(const mbedtls_ecp_group *grp, unsigned char i; size_t j = 0; const unsigned char T_size = 1U << (w - 1); - mbedtls_ecp_point *cur, *TT[COMB_MAX_PRE - 1]; + mbedtls_ecp_point *cur, *TT[COMB_MAX_PRE - 1] = { NULL }; + + mbedtls_mpi tmp[4]; + + mpi_init_many(tmp, sizeof(tmp) / sizeof(mbedtls_mpi)); #if defined(MBEDTLS_ECP_RESTARTABLE) if (rs_ctx != NULL && rs_ctx->rsm != NULL) { @@ -1924,7 +1913,7 @@ static int ecp_precompute_comb(const mbedtls_ecp_group *grp, MBEDTLS_MPI_CHK(mbedtls_ecp_copy(cur, T + (i >> 1))); } - MBEDTLS_MPI_CHK(ecp_double_jac(grp, cur, cur)); + MBEDTLS_MPI_CHK(ecp_double_jac(grp, cur, cur, tmp)); } #if defined(MBEDTLS_ECP_RESTARTABLE) @@ -1935,8 +1924,11 @@ static int ecp_precompute_comb(const mbedtls_ecp_group *grp, norm_dbl: #endif /* - * Normalize current elements in T. As T has holes, - * use an auxiliary array of pointers to elements in T. + * Normalize current elements in T to allow them to be used in + * ecp_add_mixed() below, which requires one normalized input. + * + * As T has holes, use an auxiliary array of pointers to elements in T. + * */ j = 0; for (i = 1; i < T_size; i <<= 1) { @@ -1963,7 +1955,7 @@ static int ecp_precompute_comb(const mbedtls_ecp_group *grp, for (i = 1; i < T_size; i <<= 1) { j = i; while (j--) { - MBEDTLS_MPI_CHK(ecp_add_mixed(grp, &T[i + j], &T[j], &T[i])); + MBEDTLS_MPI_CHK(ecp_add_mixed(grp, &T[i + j], &T[j], &T[i], tmp)); } } @@ -1987,7 +1979,19 @@ static int ecp_precompute_comb(const mbedtls_ecp_group *grp, MBEDTLS_MPI_CHK(ecp_normalize_jac_many(grp, TT, j)); + /* Free Z coordinate (=1 after normalization) to save RAM. + * This makes T[i] invalid as mbedtls_ecp_points, but this is OK + * since from this point onwards, they are only accessed indirectly + * via the getter function ecp_select_comb() which does set the + * target's Z coordinate to 1. */ + for (i = 0; i < T_size; i++) { + mbedtls_mpi_free(&T[i].Z); + } + cleanup: + + mpi_free_many(tmp, sizeof(tmp) / sizeof(mbedtls_mpi)); + #if defined(MBEDTLS_ECP_RESTARTABLE) if (rs_ctx != NULL && rs_ctx->rsm != NULL && ret == MBEDTLS_ERR_ECP_IN_PROGRESS) { @@ -2017,13 +2021,15 @@ static int ecp_select_comb(const mbedtls_ecp_group *grp, mbedtls_ecp_point *R, /* Read the whole table to thwart cache-based timing attacks */ for (j = 0; j < T_size; j++) { - MBEDTLS_MPI_CHK(mbedtls_mpi_safe_cond_assign(&R->X, &T[j].X, j == ii)); - MBEDTLS_MPI_CHK(mbedtls_mpi_safe_cond_assign(&R->Y, &T[j].Y, j == ii)); + MPI_ECP_COND_ASSIGN(&R->X, &T[j].X, j == ii); + MPI_ECP_COND_ASSIGN(&R->Y, &T[j].Y, j == ii); } /* Safely invert result if i is "negative" */ MBEDTLS_MPI_CHK(ecp_safe_invert_jac(grp, R, i >> 7)); + MPI_ECP_LSET(&R->Z, 1); + cleanup: return ret; } @@ -2043,9 +2049,11 @@ static int ecp_mul_comb_core(const mbedtls_ecp_group *grp, mbedtls_ecp_point *R, { int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED; mbedtls_ecp_point Txi; + mbedtls_mpi tmp[4]; size_t i; mbedtls_ecp_point_init(&Txi); + mpi_init_many(tmp, sizeof(tmp) / sizeof(mbedtls_mpi)); #if !defined(MBEDTLS_ECP_RESTARTABLE) (void) rs_ctx; @@ -2065,19 +2073,10 @@ static int ecp_mul_comb_core(const mbedtls_ecp_group *grp, mbedtls_ecp_point *R, } else #endif { - int have_rng = 1; - /* Start with a non-zero point and randomize its coordinates */ i = d; MBEDTLS_MPI_CHK(ecp_select_comb(grp, R, T, T_size, x[i])); - MBEDTLS_MPI_CHK(mbedtls_mpi_lset(&R->Z, 1)); - -#if defined(MBEDTLS_ECP_NO_INTERNAL_RNG) - if (f_rng == NULL) { - have_rng = 0; - } -#endif - if (have_rng) { + if (f_rng != 0) { MBEDTLS_MPI_CHK(ecp_randomize_jac(grp, R, f_rng, p_rng)); } } @@ -2086,14 +2085,15 @@ static int ecp_mul_comb_core(const mbedtls_ecp_group *grp, mbedtls_ecp_point *R, MBEDTLS_ECP_BUDGET(MBEDTLS_ECP_OPS_DBL + MBEDTLS_ECP_OPS_ADD); --i; - MBEDTLS_MPI_CHK(ecp_double_jac(grp, R, R)); + MBEDTLS_MPI_CHK(ecp_double_jac(grp, R, R, tmp)); MBEDTLS_MPI_CHK(ecp_select_comb(grp, &Txi, T, T_size, x[i])); - MBEDTLS_MPI_CHK(ecp_add_mixed(grp, R, R, &Txi)); + MBEDTLS_MPI_CHK(ecp_add_mixed(grp, R, R, &Txi, tmp)); } cleanup: mbedtls_ecp_point_free(&Txi); + mpi_free_many(tmp, sizeof(tmp) / sizeof(mbedtls_mpi)); #if defined(MBEDTLS_ECP_RESTARTABLE) if (rs_ctx != NULL && rs_ctx->rsm != NULL && @@ -2176,7 +2176,6 @@ static int ecp_mul_comb_after_precomp(const mbedtls_ecp_group *grp, unsigned char parity_trick; unsigned char k[COMB_MAX_D + 1]; mbedtls_ecp_point *RR = R; - int have_rng = 1; #if defined(MBEDTLS_ECP_RESTARTABLE) if (rs_ctx != NULL && rs_ctx->rsm != NULL) { @@ -2213,12 +2212,7 @@ static int ecp_mul_comb_after_precomp(const mbedtls_ecp_group *grp, * * Avoid the leak by randomizing coordinates before we normalize them. */ -#if defined(MBEDTLS_ECP_NO_INTERNAL_RNG) - if (f_rng == NULL) { - have_rng = 0; - } -#endif - if (have_rng) { + if (f_rng != 0) { MBEDTLS_MPI_CHK(ecp_randomize_jac(grp, RR, f_rng, p_rng)); } @@ -2259,11 +2253,16 @@ static unsigned char ecp_pick_window_size(const mbedtls_ecp_group *grp, } /* - * Make sure w is within bounds. + * If static comb table may not be used (!p_eq_g) or static comb table does + * not exists, make sure w is within bounds. * (The last test is useful only for very small curves in the test suite.) + * + * The user reduces MBEDTLS_ECP_WINDOW_SIZE does not changes the size of + * static comb table, because the size of static comb table is fixed when + * it is generated. */ #if (MBEDTLS_ECP_WINDOW_SIZE < 6) - if (w > MBEDTLS_ECP_WINDOW_SIZE) { + if ((!p_eq_g || !ecp_group_is_static_comb_table(grp)) && w > MBEDTLS_ECP_WINDOW_SIZE) { w = MBEDTLS_ECP_WINDOW_SIZE; } #endif @@ -2298,46 +2297,13 @@ static int ecp_mul_comb(mbedtls_ecp_group *grp, mbedtls_ecp_point *R, size_t d; unsigned char T_size = 0, T_ok = 0; mbedtls_ecp_point *T = NULL; -#if !defined(MBEDTLS_ECP_NO_INTERNAL_RNG) - ecp_drbg_context drbg_ctx; - - ecp_drbg_init(&drbg_ctx); -#endif ECP_RS_ENTER(rsm); -#if !defined(MBEDTLS_ECP_NO_INTERNAL_RNG) - if (f_rng == NULL) { - /* Adjust pointers */ - f_rng = &ecp_drbg_random; -#if defined(MBEDTLS_ECP_RESTARTABLE) - if (rs_ctx != NULL && rs_ctx->rsm != NULL) { - p_rng = &rs_ctx->rsm->drbg_ctx; - } else -#endif - p_rng = &drbg_ctx; - - /* Initialize internal DRBG if necessary */ -#if defined(MBEDTLS_ECP_RESTARTABLE) - if (rs_ctx == NULL || rs_ctx->rsm == NULL || - rs_ctx->rsm->drbg_seeded == 0) -#endif - { - const size_t m_len = (grp->nbits + 7) / 8; - MBEDTLS_MPI_CHK(ecp_drbg_seed(p_rng, m, m_len)); - } -#if defined(MBEDTLS_ECP_RESTARTABLE) - if (rs_ctx != NULL && rs_ctx->rsm != NULL) { - rs_ctx->rsm->drbg_seeded = 1; - } -#endif - } -#endif /* !MBEDTLS_ECP_NO_INTERNAL_RNG */ - /* Is P the base point ? */ #if MBEDTLS_ECP_FIXED_POINT_OPTIM == 1 - p_eq_g = (mbedtls_mpi_cmp_mpi(&P->Y, &grp->G.Y) == 0 && - mbedtls_mpi_cmp_mpi(&P->X, &grp->G.X) == 0); + p_eq_g = (MPI_ECP_CMP(&P->Y, &grp->G.Y) == 0 && + MPI_ECP_CMP(&P->X, &grp->G.X) == 0); #else p_eq_g = 0; #endif @@ -2399,10 +2365,6 @@ static int ecp_mul_comb(mbedtls_ecp_group *grp, mbedtls_ecp_point *R, cleanup: -#if !defined(MBEDTLS_ECP_NO_INTERNAL_RNG) - ecp_drbg_free(&drbg_ctx); -#endif - /* does T belong to the group? */ if (T == grp->T) { T = NULL; @@ -2470,9 +2432,9 @@ static int ecp_normalize_mxz(const mbedtls_ecp_group *grp, mbedtls_ecp_point *P) return MBEDTLS_ERR_ECP_FEATURE_UNAVAILABLE; #else int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED; - MBEDTLS_MPI_CHK(mbedtls_mpi_inv_mod(&P->Z, &P->Z, &grp->P)); - MBEDTLS_MPI_CHK(mbedtls_mpi_mul_mod(grp, &P->X, &P->X, &P->Z)); - MBEDTLS_MPI_CHK(mbedtls_mpi_lset(&P->Z, 1)); + MPI_ECP_INV(&P->Z, &P->Z); + MPI_ECP_MUL(&P->X, &P->X, &P->Z); + MPI_ECP_LSET(&P->Z, 1); cleanup: return ret; @@ -2504,10 +2466,10 @@ static int ecp_randomize_mxz(const mbedtls_ecp_group *grp, mbedtls_ecp_point *P, mbedtls_mpi_init(&l); /* Generate l such that 1 < l < p */ - MBEDTLS_MPI_CHK(mbedtls_mpi_random(&l, 2, &grp->P, f_rng, p_rng)); + MPI_ECP_RAND(&l); - MBEDTLS_MPI_CHK(mbedtls_mpi_mul_mod(grp, &P->X, &P->X, &l)); - MBEDTLS_MPI_CHK(mbedtls_mpi_mul_mod(grp, &P->Z, &P->Z, &l)); + MPI_ECP_MUL(&P->X, &P->X, &l); + MPI_ECP_MUL(&P->Z, &P->Z, &l); cleanup: mbedtls_mpi_free(&l); @@ -2537,7 +2499,8 @@ static int ecp_randomize_mxz(const mbedtls_ecp_group *grp, mbedtls_ecp_point *P, static int ecp_double_add_mxz(const mbedtls_ecp_group *grp, mbedtls_ecp_point *R, mbedtls_ecp_point *S, const mbedtls_ecp_point *P, const mbedtls_ecp_point *Q, - const mbedtls_mpi *d) + const mbedtls_mpi *d, + mbedtls_mpi T[4]) { #if defined(MBEDTLS_ECP_DOUBLE_ADD_MXZ_ALT) if (mbedtls_internal_ecp_grp_capable(grp)) { @@ -2549,35 +2512,27 @@ static int ecp_double_add_mxz(const mbedtls_ecp_group *grp, return MBEDTLS_ERR_ECP_FEATURE_UNAVAILABLE; #else int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED; - mbedtls_mpi A, AA, B, BB, E, C, D, DA, CB; - - mbedtls_mpi_init(&A); mbedtls_mpi_init(&AA); mbedtls_mpi_init(&B); - mbedtls_mpi_init(&BB); mbedtls_mpi_init(&E); mbedtls_mpi_init(&C); - mbedtls_mpi_init(&D); mbedtls_mpi_init(&DA); mbedtls_mpi_init(&CB); - - MBEDTLS_MPI_CHK(mbedtls_mpi_add_mod(grp, &A, &P->X, &P->Z)); - MBEDTLS_MPI_CHK(mbedtls_mpi_mul_mod(grp, &AA, &A, &A)); - MBEDTLS_MPI_CHK(mbedtls_mpi_sub_mod(grp, &B, &P->X, &P->Z)); - MBEDTLS_MPI_CHK(mbedtls_mpi_mul_mod(grp, &BB, &B, &B)); - MBEDTLS_MPI_CHK(mbedtls_mpi_sub_mod(grp, &E, &AA, &BB)); - MBEDTLS_MPI_CHK(mbedtls_mpi_add_mod(grp, &C, &Q->X, &Q->Z)); - MBEDTLS_MPI_CHK(mbedtls_mpi_sub_mod(grp, &D, &Q->X, &Q->Z)); - MBEDTLS_MPI_CHK(mbedtls_mpi_mul_mod(grp, &DA, &D, &A)); - MBEDTLS_MPI_CHK(mbedtls_mpi_mul_mod(grp, &CB, &C, &B)); - MBEDTLS_MPI_CHK(mbedtls_mpi_add_mod(grp, &S->X, &DA, &CB)); - MBEDTLS_MPI_CHK(mbedtls_mpi_mul_mod(grp, &S->X, &S->X, &S->X)); - MBEDTLS_MPI_CHK(mbedtls_mpi_sub_mod(grp, &S->Z, &DA, &CB)); - MBEDTLS_MPI_CHK(mbedtls_mpi_mul_mod(grp, &S->Z, &S->Z, &S->Z)); - MBEDTLS_MPI_CHK(mbedtls_mpi_mul_mod(grp, &S->Z, d, &S->Z)); - MBEDTLS_MPI_CHK(mbedtls_mpi_mul_mod(grp, &R->X, &AA, &BB)); - MBEDTLS_MPI_CHK(mbedtls_mpi_mul_mod(grp, &R->Z, &grp->A, &E)); - MBEDTLS_MPI_CHK(mbedtls_mpi_add_mod(grp, &R->Z, &BB, &R->Z)); - MBEDTLS_MPI_CHK(mbedtls_mpi_mul_mod(grp, &R->Z, &E, &R->Z)); + + MPI_ECP_ADD(&T[0], &P->X, &P->Z); /* Pp := PX + PZ */ + MPI_ECP_SUB(&T[1], &P->X, &P->Z); /* Pm := PX - PZ */ + MPI_ECP_ADD(&T[2], &Q->X, &Q->Z); /* Qp := QX + XZ */ + MPI_ECP_SUB(&T[3], &Q->X, &Q->Z); /* Qm := QX - QZ */ + MPI_ECP_MUL(&T[3], &T[3], &T[0]); /* Qm * Pp */ + MPI_ECP_MUL(&T[2], &T[2], &T[1]); /* Qp * Pm */ + MPI_ECP_SQR(&T[0], &T[0]); /* Pp^2 */ + MPI_ECP_SQR(&T[1], &T[1]); /* Pm^2 */ + MPI_ECP_MUL(&R->X, &T[0], &T[1]); /* Pp^2 * Pm^2 */ + MPI_ECP_SUB(&T[0], &T[0], &T[1]); /* Pp^2 - Pm^2 */ + MPI_ECP_MUL(&R->Z, &grp->A, &T[0]); /* A * (Pp^2 - Pm^2) */ + MPI_ECP_ADD(&R->Z, &T[1], &R->Z); /* [ A * (Pp^2-Pm^2) ] + Pm^2 */ + MPI_ECP_ADD(&S->X, &T[3], &T[2]); /* Qm*Pp + Qp*Pm */ + MPI_ECP_SQR(&S->X, &S->X); /* (Qm*Pp + Qp*Pm)^2 */ + MPI_ECP_SUB(&S->Z, &T[3], &T[2]); /* Qm*Pp - Qp*Pm */ + MPI_ECP_SQR(&S->Z, &S->Z); /* (Qm*Pp - Qp*Pm)^2 */ + MPI_ECP_MUL(&S->Z, d, &S->Z); /* d * ( Qm*Pp - Qp*Pm )^2 */ + MPI_ECP_MUL(&R->Z, &T[0], &R->Z); /* [A*(Pp^2-Pm^2)+Pm^2]*(Pp^2-Pm^2) */ cleanup: - mbedtls_mpi_free(&A); mbedtls_mpi_free(&AA); mbedtls_mpi_free(&B); - mbedtls_mpi_free(&BB); mbedtls_mpi_free(&E); mbedtls_mpi_free(&C); - mbedtls_mpi_free(&D); mbedtls_mpi_free(&DA); mbedtls_mpi_free(&CB); return ret; #endif /* !defined(MBEDTLS_ECP_NO_FALLBACK) || !defined(MBEDTLS_ECP_DOUBLE_ADD_MXZ_ALT) */ @@ -2593,48 +2548,33 @@ static int ecp_mul_mxz(mbedtls_ecp_group *grp, mbedtls_ecp_point *R, void *p_rng) { int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED; - int have_rng = 1; size_t i; unsigned char b; mbedtls_ecp_point RP; mbedtls_mpi PX; -#if !defined(MBEDTLS_ECP_NO_INTERNAL_RNG) - ecp_drbg_context drbg_ctx; - - ecp_drbg_init(&drbg_ctx); -#endif + mbedtls_mpi tmp[4]; mbedtls_ecp_point_init(&RP); mbedtls_mpi_init(&PX); -#if !defined(MBEDTLS_ECP_NO_INTERNAL_RNG) + mpi_init_many(tmp, sizeof(tmp) / sizeof(mbedtls_mpi)); + if (f_rng == NULL) { - const size_t m_len = (grp->nbits + 7) / 8; - MBEDTLS_MPI_CHK(ecp_drbg_seed(&drbg_ctx, m, m_len)); - f_rng = &ecp_drbg_random; - p_rng = &drbg_ctx; + return MBEDTLS_ERR_ECP_BAD_INPUT_DATA; } -#endif /* !MBEDTLS_ECP_NO_INTERNAL_RNG */ /* Save PX and read from P before writing to R, in case P == R */ - MBEDTLS_MPI_CHK(mbedtls_mpi_copy(&PX, &P->X)); + MPI_ECP_MOV(&PX, &P->X); MBEDTLS_MPI_CHK(mbedtls_ecp_copy(&RP, P)); /* Set R to zero in modified x/z coordinates */ - MBEDTLS_MPI_CHK(mbedtls_mpi_lset(&R->X, 1)); - MBEDTLS_MPI_CHK(mbedtls_mpi_lset(&R->Z, 0)); + MPI_ECP_LSET(&R->X, 1); + MPI_ECP_LSET(&R->Z, 0); mbedtls_mpi_free(&R->Y); /* RP.X might be slightly larger than P, so reduce it */ - MOD_ADD(RP.X); + MOD_ADD(&RP.X); -#if defined(MBEDTLS_ECP_NO_INTERNAL_RNG) - /* Derandomize coordinates of the starting point */ - if (f_rng == NULL) { - have_rng = 0; - } -#endif - if (have_rng) { - MBEDTLS_MPI_CHK(ecp_randomize_mxz(grp, &RP, f_rng, p_rng)); - } + /* Randomize coordinates of the starting point */ + MBEDTLS_MPI_CHK(ecp_randomize_mxz(grp, &RP, f_rng, p_rng)); /* Loop invariant: R = result so far, RP = R + P */ i = grp->nbits + 1; /* one past the (zero-based) required msb for private keys */ @@ -2647,11 +2587,11 @@ static int ecp_mul_mxz(mbedtls_ecp_group *grp, mbedtls_ecp_point *R, * else double_add( R, RP, R, RP ) * but using safe conditional swaps to avoid leaks */ - MBEDTLS_MPI_CHK(mbedtls_mpi_safe_cond_swap(&R->X, &RP.X, b)); - MBEDTLS_MPI_CHK(mbedtls_mpi_safe_cond_swap(&R->Z, &RP.Z, b)); - MBEDTLS_MPI_CHK(ecp_double_add_mxz(grp, R, &RP, R, &RP, &PX)); - MBEDTLS_MPI_CHK(mbedtls_mpi_safe_cond_swap(&R->X, &RP.X, b)); - MBEDTLS_MPI_CHK(mbedtls_mpi_safe_cond_swap(&R->Z, &RP.Z, b)); + MPI_ECP_COND_SWAP(&R->X, &RP.X, b); + MPI_ECP_COND_SWAP(&R->Z, &RP.Z, b); + MBEDTLS_MPI_CHK(ecp_double_add_mxz(grp, R, &RP, R, &RP, &PX, tmp)); + MPI_ECP_COND_SWAP(&R->X, &RP.X, b); + MPI_ECP_COND_SWAP(&R->Z, &RP.Z, b); } /* @@ -2665,25 +2605,13 @@ static int ecp_mul_mxz(mbedtls_ecp_group *grp, mbedtls_ecp_point *R, * * Avoid the leak by randomizing coordinates before we normalize them. */ - have_rng = 1; -#if defined(MBEDTLS_ECP_NO_INTERNAL_RNG) - if (f_rng == NULL) { - have_rng = 0; - } -#endif - if (have_rng) { - MBEDTLS_MPI_CHK(ecp_randomize_mxz(grp, R, f_rng, p_rng)); - } - + MBEDTLS_MPI_CHK(ecp_randomize_mxz(grp, R, f_rng, p_rng)); MBEDTLS_MPI_CHK(ecp_normalize_mxz(grp, R)); cleanup: -#if !defined(MBEDTLS_ECP_NO_INTERNAL_RNG) - ecp_drbg_free(&drbg_ctx); -#endif - mbedtls_ecp_point_free(&RP); mbedtls_mpi_free(&PX); + mpi_free_many(tmp, sizeof(tmp) / sizeof(mbedtls_mpi)); return ret; } @@ -2691,20 +2619,19 @@ static int ecp_mul_mxz(mbedtls_ecp_group *grp, mbedtls_ecp_point *R, /* * Restartable multiplication R = m * P + * + * This internal function can be called without an RNG in case where we know + * the inputs are not sensitive. */ -int mbedtls_ecp_mul_restartable(mbedtls_ecp_group *grp, mbedtls_ecp_point *R, - const mbedtls_mpi *m, const mbedtls_ecp_point *P, - int (*f_rng)(void *, unsigned char *, size_t), void *p_rng, - mbedtls_ecp_restart_ctx *rs_ctx) +static int ecp_mul_restartable_internal(mbedtls_ecp_group *grp, mbedtls_ecp_point *R, + const mbedtls_mpi *m, const mbedtls_ecp_point *P, + int (*f_rng)(void *, unsigned char *, size_t), void *p_rng, + mbedtls_ecp_restart_ctx *rs_ctx) { int ret = MBEDTLS_ERR_ECP_BAD_INPUT_DATA; #if defined(MBEDTLS_ECP_INTERNAL_ALT) char is_grp_capable = 0; #endif - ECP_VALIDATE_RET(grp != NULL); - ECP_VALIDATE_RET(R != NULL); - ECP_VALIDATE_RET(m != NULL); - ECP_VALIDATE_RET(P != NULL); #if defined(MBEDTLS_ECP_RESTARTABLE) /* reset ops count for this call if top-level */ @@ -2764,6 +2691,21 @@ int mbedtls_ecp_mul_restartable(mbedtls_ecp_group *grp, mbedtls_ecp_point *R, return ret; } +/* + * Restartable multiplication R = m * P + */ +int mbedtls_ecp_mul_restartable(mbedtls_ecp_group *grp, mbedtls_ecp_point *R, + const mbedtls_mpi *m, const mbedtls_ecp_point *P, + int (*f_rng)(void *, unsigned char *, size_t), void *p_rng, + mbedtls_ecp_restart_ctx *rs_ctx) +{ + if (f_rng == NULL) { + return MBEDTLS_ERR_ECP_BAD_INPUT_DATA; + } + + return ecp_mul_restartable_internal(grp, R, m, P, f_rng, p_rng, rs_ctx); +} + /* * Multiplication R = m * P */ @@ -2771,12 +2713,9 @@ int mbedtls_ecp_mul(mbedtls_ecp_group *grp, mbedtls_ecp_point *R, const mbedtls_mpi *m, const mbedtls_ecp_point *P, int (*f_rng)(void *, unsigned char *, size_t), void *p_rng) { - ECP_VALIDATE_RET(grp != NULL); - ECP_VALIDATE_RET(R != NULL); - ECP_VALIDATE_RET(m != NULL); - ECP_VALIDATE_RET(P != NULL); return mbedtls_ecp_mul_restartable(grp, R, m, P, f_rng, p_rng, NULL); } +#endif /* MBEDTLS_ECP_C */ #if defined(MBEDTLS_ECP_SHORT_WEIERSTRASS_ENABLED) /* @@ -2800,22 +2739,12 @@ static int ecp_check_pubkey_sw(const mbedtls_ecp_group *grp, const mbedtls_ecp_p /* * YY = Y^2 - * RHS = X (X^2 + A) + B = X^3 + A X + B + * RHS = X^3 + A X + B */ - MBEDTLS_MPI_CHK(mbedtls_mpi_mul_mod(grp, &YY, &pt->Y, &pt->Y)); - MBEDTLS_MPI_CHK(mbedtls_mpi_mul_mod(grp, &RHS, &pt->X, &pt->X)); + MPI_ECP_SQR(&YY, &pt->Y); + MBEDTLS_MPI_CHK(ecp_sw_rhs(grp, &RHS, &pt->X)); - /* Special case for A = -3 */ - if (grp->A.p == NULL) { - MBEDTLS_MPI_CHK(mbedtls_mpi_sub_int(&RHS, &RHS, 3)); MOD_SUB(RHS); - } else { - MBEDTLS_MPI_CHK(mbedtls_mpi_add_mod(grp, &RHS, &RHS, &grp->A)); - } - - MBEDTLS_MPI_CHK(mbedtls_mpi_mul_mod(grp, &RHS, &RHS, &pt->X)); - MBEDTLS_MPI_CHK(mbedtls_mpi_add_mod(grp, &RHS, &RHS, &grp->B)); - - if (mbedtls_mpi_cmp_mpi(&YY, &RHS) != 0) { + if (MPI_ECP_CMP(&YY, &RHS) != 0) { ret = MBEDTLS_ERR_ECP_INVALID_KEY; } @@ -2827,6 +2756,7 @@ static int ecp_check_pubkey_sw(const mbedtls_ecp_group *grp, const mbedtls_ecp_p } #endif /* MBEDTLS_ECP_SHORT_WEIERSTRASS_ENABLED */ +#if defined(MBEDTLS_ECP_C) #if defined(MBEDTLS_ECP_SHORT_WEIERSTRASS_ENABLED) /* * R = m * P with shortcuts for m == 0, m == 1 and m == -1 @@ -2839,6 +2769,8 @@ static int mbedtls_ecp_mul_shortcuts(mbedtls_ecp_group *grp, mbedtls_ecp_restart_ctx *rs_ctx) { int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED; + mbedtls_mpi tmp; + mbedtls_mpi_init(&tmp); if (mbedtls_mpi_cmp_int(m, 0) == 0) { MBEDTLS_MPI_CHK(mbedtls_ecp_check_pubkey(grp, P)); @@ -2849,15 +2781,15 @@ static int mbedtls_ecp_mul_shortcuts(mbedtls_ecp_group *grp, } else if (mbedtls_mpi_cmp_int(m, -1) == 0) { MBEDTLS_MPI_CHK(mbedtls_ecp_check_pubkey(grp, P)); MBEDTLS_MPI_CHK(mbedtls_ecp_copy(R, P)); - if (mbedtls_mpi_cmp_int(&R->Y, 0) != 0) { - MBEDTLS_MPI_CHK(mbedtls_mpi_sub_mpi(&R->Y, &grp->P, &R->Y)); - } + MPI_ECP_NEG(&R->Y); } else { - MBEDTLS_MPI_CHK(mbedtls_ecp_mul_restartable(grp, R, m, P, - NULL, NULL, rs_ctx)); + MBEDTLS_MPI_CHK(ecp_mul_restartable_internal(grp, R, m, P, + NULL, NULL, rs_ctx)); } cleanup: + mbedtls_mpi_free(&tmp); + return ret; } @@ -2875,21 +2807,16 @@ int mbedtls_ecp_muladd_restartable( mbedtls_ecp_point mP; mbedtls_ecp_point *pmP = &mP; mbedtls_ecp_point *pR = R; + mbedtls_mpi tmp[4]; #if defined(MBEDTLS_ECP_INTERNAL_ALT) char is_grp_capable = 0; #endif - ECP_VALIDATE_RET(grp != NULL); - ECP_VALIDATE_RET(R != NULL); - ECP_VALIDATE_RET(m != NULL); - ECP_VALIDATE_RET(P != NULL); - ECP_VALIDATE_RET(n != NULL); - ECP_VALIDATE_RET(Q != NULL); - if (mbedtls_ecp_get_type(grp) != MBEDTLS_ECP_TYPE_SHORT_WEIERSTRASS) { return MBEDTLS_ERR_ECP_FEATURE_UNAVAILABLE; } mbedtls_ecp_point_init(&mP); + mpi_init_many(tmp, sizeof(tmp) / sizeof(mbedtls_mpi)); ECP_RS_ENTER(ma); @@ -2936,7 +2863,7 @@ int mbedtls_ecp_muladd_restartable( add: #endif MBEDTLS_ECP_BUDGET(MBEDTLS_ECP_OPS_ADD); - MBEDTLS_MPI_CHK(ecp_add_mixed(grp, pR, pmP, pR)); + MBEDTLS_MPI_CHK(ecp_add_mixed(grp, pR, pmP, pR, tmp)); #if defined(MBEDTLS_ECP_RESTARTABLE) if (rs_ctx != NULL && rs_ctx->ma != NULL) { rs_ctx->ma->state = ecp_rsma_norm; @@ -2954,6 +2881,9 @@ int mbedtls_ecp_muladd_restartable( #endif cleanup: + + mpi_free_many(tmp, sizeof(tmp) / sizeof(mbedtls_mpi)); + #if defined(MBEDTLS_ECP_INTERNAL_ALT) if (is_grp_capable) { mbedtls_internal_ecp_free(grp); @@ -2975,21 +2905,16 @@ int mbedtls_ecp_muladd(mbedtls_ecp_group *grp, mbedtls_ecp_point *R, const mbedtls_mpi *m, const mbedtls_ecp_point *P, const mbedtls_mpi *n, const mbedtls_ecp_point *Q) { - ECP_VALIDATE_RET(grp != NULL); - ECP_VALIDATE_RET(R != NULL); - ECP_VALIDATE_RET(m != NULL); - ECP_VALIDATE_RET(P != NULL); - ECP_VALIDATE_RET(n != NULL); - ECP_VALIDATE_RET(Q != NULL); return mbedtls_ecp_muladd_restartable(grp, R, m, P, n, Q, NULL); } #endif /* MBEDTLS_ECP_SHORT_WEIERSTRASS_ENABLED */ +#endif /* MBEDTLS_ECP_C */ #if defined(MBEDTLS_ECP_MONTGOMERY_ENABLED) #if defined(MBEDTLS_ECP_DP_CURVE25519_ENABLED) -#define ECP_MPI_INIT(s, n, p) { s, (n), (mbedtls_mpi_uint *) (p) } +#define ECP_MPI_INIT(_p, _n) { .p = (mbedtls_mpi_uint *) (_p), .s = 1, .n = (_n) } #define ECP_MPI_INIT_ARRAY(x) \ - ECP_MPI_INIT(1, sizeof(x) / sizeof(mbedtls_mpi_uint), x) + ECP_MPI_INIT(x, sizeof(x) / sizeof(mbedtls_mpi_uint)) /* * Constants for the two points other than 0, 1, -1 (mod p) in * https://cr.yp.to/ecdh.html#validate @@ -3102,9 +3027,6 @@ static int ecp_check_pubkey_mx(const mbedtls_ecp_group *grp, const mbedtls_ecp_p int mbedtls_ecp_check_pubkey(const mbedtls_ecp_group *grp, const mbedtls_ecp_point *pt) { - ECP_VALIDATE_RET(grp != NULL); - ECP_VALIDATE_RET(pt != NULL); - /* Must use affine coordinates */ if (mbedtls_mpi_cmp_int(&pt->Z, 1) != 0) { return MBEDTLS_ERR_ECP_INVALID_KEY; @@ -3129,9 +3051,6 @@ int mbedtls_ecp_check_pubkey(const mbedtls_ecp_group *grp, int mbedtls_ecp_check_privkey(const mbedtls_ecp_group *grp, const mbedtls_mpi *d) { - ECP_VALIDATE_RET(grp != NULL); - ECP_VALIDATE_RET(d != NULL); - #if defined(MBEDTLS_ECP_MONTGOMERY_ENABLED) if (mbedtls_ecp_get_type(grp) == MBEDTLS_ECP_TYPE_MONTGOMERY) { /* see RFC 7748 sec. 5 para. 5 */ @@ -3220,10 +3139,6 @@ int mbedtls_ecp_gen_privkey(const mbedtls_ecp_group *grp, int (*f_rng)(void *, unsigned char *, size_t), void *p_rng) { - ECP_VALIDATE_RET(grp != NULL); - ECP_VALIDATE_RET(d != NULL); - ECP_VALIDATE_RET(f_rng != NULL); - #if defined(MBEDTLS_ECP_MONTGOMERY_ENABLED) if (mbedtls_ecp_get_type(grp) == MBEDTLS_ECP_TYPE_MONTGOMERY) { return mbedtls_ecp_gen_privkey_mx(grp->nbits, d, f_rng, p_rng); @@ -3239,6 +3154,7 @@ int mbedtls_ecp_gen_privkey(const mbedtls_ecp_group *grp, return MBEDTLS_ERR_ECP_BAD_INPUT_DATA; } +#if defined(MBEDTLS_ECP_C) /* * Generate a keypair with configurable base point */ @@ -3249,12 +3165,6 @@ int mbedtls_ecp_gen_keypair_base(mbedtls_ecp_group *grp, void *p_rng) { int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED; - ECP_VALIDATE_RET(grp != NULL); - ECP_VALIDATE_RET(d != NULL); - ECP_VALIDATE_RET(G != NULL); - ECP_VALIDATE_RET(Q != NULL); - ECP_VALIDATE_RET(f_rng != NULL); - MBEDTLS_MPI_CHK(mbedtls_ecp_gen_privkey(grp, d, f_rng, p_rng)); MBEDTLS_MPI_CHK(mbedtls_ecp_mul(grp, Q, d, G, f_rng, p_rng)); @@ -3270,11 +3180,6 @@ int mbedtls_ecp_gen_keypair(mbedtls_ecp_group *grp, int (*f_rng)(void *, unsigned char *, size_t), void *p_rng) { - ECP_VALIDATE_RET(grp != NULL); - ECP_VALIDATE_RET(d != NULL); - ECP_VALIDATE_RET(Q != NULL); - ECP_VALIDATE_RET(f_rng != NULL); - return mbedtls_ecp_gen_keypair_base(grp, &grp->G, d, Q, f_rng, p_rng); } @@ -3285,17 +3190,35 @@ int mbedtls_ecp_gen_key(mbedtls_ecp_group_id grp_id, mbedtls_ecp_keypair *key, int (*f_rng)(void *, unsigned char *, size_t), void *p_rng) { int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED; - ECP_VALIDATE_RET(key != NULL); - ECP_VALIDATE_RET(f_rng != NULL); - if ((ret = mbedtls_ecp_group_load(&key->grp, grp_id)) != 0) { return ret; } return mbedtls_ecp_gen_keypair(&key->grp, &key->d, &key->Q, f_rng, p_rng); } +#endif /* MBEDTLS_ECP_C */ + +int mbedtls_ecp_set_public_key(mbedtls_ecp_group_id grp_id, + mbedtls_ecp_keypair *key, + const mbedtls_ecp_point *Q) +{ + int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED; + + if (key->grp.id == MBEDTLS_ECP_DP_NONE) { + /* Group not set yet */ + if ((ret = mbedtls_ecp_group_load(&key->grp, grp_id)) != 0) { + return ret; + } + } else if (key->grp.id != grp_id) { + /* Group mismatch */ + return MBEDTLS_ERR_ECP_BAD_INPUT_DATA; + } + return mbedtls_ecp_copy(&key->Q, Q); +} + #define ECP_CURVE25519_KEY_SIZE 32 +#define ECP_CURVE448_KEY_SIZE 56 /* * Read a private key. */ @@ -3304,9 +3227,6 @@ int mbedtls_ecp_read_key(mbedtls_ecp_group_id grp_id, mbedtls_ecp_keypair *key, { int ret = 0; - ECP_VALIDATE_RET(key != NULL); - ECP_VALIDATE_RET(buf != NULL); - if ((ret = mbedtls_ecp_group_load(&key->grp, grp_id)) != 0) { return ret; } @@ -3316,7 +3236,7 @@ int mbedtls_ecp_read_key(mbedtls_ecp_group_id grp_id, mbedtls_ecp_keypair *key, #if defined(MBEDTLS_ECP_MONTGOMERY_ENABLED) if (mbedtls_ecp_get_type(&key->grp) == MBEDTLS_ECP_TYPE_MONTGOMERY) { /* - * If it is Curve25519 curve then mask the key as mandated by RFC7748 + * Mask the key as mandated by RFC7748 for Curve25519 and Curve448. */ if (grp_id == MBEDTLS_ECP_DP_CURVE25519) { if (buflen != ECP_CURVE25519_KEY_SIZE) { @@ -3341,20 +3261,35 @@ int mbedtls_ecp_read_key(mbedtls_ecp_group_id grp_id, mbedtls_ecp_keypair *key, mbedtls_mpi_set_bit(&key->d, ECP_CURVE25519_KEY_SIZE * 8 - 2, 1) ); - } else { - ret = MBEDTLS_ERR_ECP_FEATURE_UNAVAILABLE; + } else if (grp_id == MBEDTLS_ECP_DP_CURVE448) { + if (buflen != ECP_CURVE448_KEY_SIZE) { + return MBEDTLS_ERR_ECP_INVALID_KEY; + } + + MBEDTLS_MPI_CHK(mbedtls_mpi_read_binary_le(&key->d, buf, buflen)); + + /* Set the two least significant bits to 0 */ + MBEDTLS_MPI_CHK(mbedtls_mpi_set_bit(&key->d, 0, 0)); + MBEDTLS_MPI_CHK(mbedtls_mpi_set_bit(&key->d, 1, 0)); + + /* Set the most significant bit to 1 */ + MBEDTLS_MPI_CHK( + mbedtls_mpi_set_bit(&key->d, + ECP_CURVE448_KEY_SIZE * 8 - 1, 1) + ); } } - #endif #if defined(MBEDTLS_ECP_SHORT_WEIERSTRASS_ENABLED) if (mbedtls_ecp_get_type(&key->grp) == MBEDTLS_ECP_TYPE_SHORT_WEIERSTRASS) { MBEDTLS_MPI_CHK(mbedtls_mpi_read_binary(&key->d, buf, buflen)); + } +#endif + if (ret == 0) { MBEDTLS_MPI_CHK(mbedtls_ecp_check_privkey(&key->grp, &key->d)); } -#endif cleanup: if (ret != 0) { @@ -3367,13 +3302,11 @@ int mbedtls_ecp_read_key(mbedtls_ecp_group_id grp_id, mbedtls_ecp_keypair *key, /* * Write a private key. */ +#if !defined MBEDTLS_DEPRECATED_REMOVED int mbedtls_ecp_write_key(mbedtls_ecp_keypair *key, unsigned char *buf, size_t buflen) { - int ret = MBEDTLS_ERR_ECP_FEATURE_UNAVAILABLE; - - ECP_VALIDATE_RET(key != NULL); - ECP_VALIDATE_RET(buf != NULL); + int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED; #if defined(MBEDTLS_ECP_MONTGOMERY_ENABLED) if (mbedtls_ecp_get_type(&key->grp) == MBEDTLS_ECP_TYPE_MONTGOMERY) { @@ -3382,12 +3315,13 @@ int mbedtls_ecp_write_key(mbedtls_ecp_keypair *key, return MBEDTLS_ERR_ECP_BUFFER_TOO_SMALL; } - MBEDTLS_MPI_CHK(mbedtls_mpi_write_binary_le(&key->d, buf, buflen)); - } else { - ret = MBEDTLS_ERR_ECP_FEATURE_UNAVAILABLE; + } else if (key->grp.id == MBEDTLS_ECP_DP_CURVE448) { + if (buflen < ECP_CURVE448_KEY_SIZE) { + return MBEDTLS_ERR_ECP_BUFFER_TOO_SMALL; + } } + MBEDTLS_MPI_CHK(mbedtls_mpi_write_binary_le(&key->d, buf, buflen)); } - #endif #if defined(MBEDTLS_ECP_SHORT_WEIERSTRASS_ENABLED) if (mbedtls_ecp_get_type(&key->grp) == MBEDTLS_ECP_TYPE_SHORT_WEIERSTRASS) { @@ -3399,19 +3333,63 @@ int mbedtls_ecp_write_key(mbedtls_ecp_keypair *key, return ret; } +#endif /* MBEDTLS_DEPRECATED_REMOVED */ +int mbedtls_ecp_write_key_ext(const mbedtls_ecp_keypair *key, + size_t *olen, unsigned char *buf, size_t buflen) +{ + size_t len = (key->grp.nbits + 7) / 8; + if (len > buflen) { + /* For robustness, ensure *olen <= buflen even on error. */ + *olen = 0; + return MBEDTLS_ERR_ECP_BUFFER_TOO_SMALL; + } + *olen = len; + + /* Private key not set */ + if (key->d.n == 0) { + return MBEDTLS_ERR_ECP_BAD_INPUT_DATA; + } + +#if defined(MBEDTLS_ECP_MONTGOMERY_ENABLED) + if (mbedtls_ecp_get_type(&key->grp) == MBEDTLS_ECP_TYPE_MONTGOMERY) { + return mbedtls_mpi_write_binary_le(&key->d, buf, len); + } +#endif +#if defined(MBEDTLS_ECP_SHORT_WEIERSTRASS_ENABLED) + if (mbedtls_ecp_get_type(&key->grp) == MBEDTLS_ECP_TYPE_SHORT_WEIERSTRASS) { + return mbedtls_mpi_write_binary(&key->d, buf, len); + } +#endif + + /* Private key set but no recognized curve type? This shouldn't happen. */ + return MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED; +} + +/* + * Write a public key. + */ +int mbedtls_ecp_write_public_key(const mbedtls_ecp_keypair *key, + int format, size_t *olen, + unsigned char *buf, size_t buflen) +{ + return mbedtls_ecp_point_write_binary(&key->grp, &key->Q, + format, olen, buf, buflen); +} + + +#if defined(MBEDTLS_ECP_C) /* * Check a public-private key pair */ -int mbedtls_ecp_check_pub_priv(const mbedtls_ecp_keypair *pub, const mbedtls_ecp_keypair *prv) +int mbedtls_ecp_check_pub_priv( + const mbedtls_ecp_keypair *pub, const mbedtls_ecp_keypair *prv, + int (*f_rng)(void *, unsigned char *, size_t), void *p_rng) { int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED; mbedtls_ecp_point Q; mbedtls_ecp_group grp; - ECP_VALIDATE_RET(pub != NULL); - ECP_VALIDATE_RET(prv != NULL); - if (pub->grp.id == MBEDTLS_ECP_DP_NONE || pub->grp.id != prv->grp.id || mbedtls_mpi_cmp_mpi(&pub->Q.X, &prv->Q.X) || @@ -3427,7 +3405,7 @@ int mbedtls_ecp_check_pub_priv(const mbedtls_ecp_keypair *pub, const mbedtls_ecp mbedtls_ecp_group_copy(&grp, &prv->grp); /* Also checks d is valid */ - MBEDTLS_MPI_CHK(mbedtls_ecp_mul(&grp, &Q, &prv->d, &prv->grp.G, NULL, NULL)); + MBEDTLS_MPI_CHK(mbedtls_ecp_mul(&grp, &Q, &prv->d, &prv->grp.G, f_rng, p_rng)); if (mbedtls_mpi_cmp_mpi(&Q.X, &prv->Q.X) || mbedtls_mpi_cmp_mpi(&Q.Y, &prv->Q.Y) || @@ -3443,8 +3421,68 @@ int mbedtls_ecp_check_pub_priv(const mbedtls_ecp_keypair *pub, const mbedtls_ecp return ret; } +int mbedtls_ecp_keypair_calc_public(mbedtls_ecp_keypair *key, + int (*f_rng)(void *, unsigned char *, size_t), + void *p_rng) +{ + return mbedtls_ecp_mul(&key->grp, &key->Q, &key->d, &key->grp.G, + f_rng, p_rng); +} +#endif /* MBEDTLS_ECP_C */ + +mbedtls_ecp_group_id mbedtls_ecp_keypair_get_group_id( + const mbedtls_ecp_keypair *key) +{ + return key->grp.id; +} + +/* + * Export generic key-pair parameters. + */ +int mbedtls_ecp_export(const mbedtls_ecp_keypair *key, mbedtls_ecp_group *grp, + mbedtls_mpi *d, mbedtls_ecp_point *Q) +{ + int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED; + + if (grp != NULL && (ret = mbedtls_ecp_group_copy(grp, &key->grp)) != 0) { + return ret; + } + + if (d != NULL && (ret = mbedtls_mpi_copy(d, &key->d)) != 0) { + return ret; + } + + if (Q != NULL && (ret = mbedtls_ecp_copy(Q, &key->Q)) != 0) { + return ret; + } + + return 0; +} + #if defined(MBEDTLS_SELF_TEST) +#if defined(MBEDTLS_ECP_C) +/* + * PRNG for test - !!!INSECURE NEVER USE IN PRODUCTION!!! + * + * This is the linear congruential generator from numerical recipes, + * except we only use the low byte as the output. See + * https://en.wikipedia.org/wiki/Linear_congruential_generator#Parameters_in_common_use + */ +static int self_test_rng(void *ctx, unsigned char *out, size_t len) +{ + static uint32_t state = 42; + + (void) ctx; + + for (size_t i = 0; i < len; i++) { + state = state * 1664525u + 1013904223u; + out[i] = (unsigned char) state; + } + + return 0; +} + /* Adjust the exponent to be a valid private point for the specified curve. * This is sometimes necessary because we use a single set of exponents * for all curves but the validity of values depends on the curve. */ @@ -3499,7 +3537,7 @@ static int self_test_point(int verbose, MBEDTLS_MPI_CHK(mbedtls_mpi_read_string(m, 16, exponents[0])); MBEDTLS_MPI_CHK(self_test_adjust_exponent(grp, m)); - MBEDTLS_MPI_CHK(mbedtls_ecp_mul(grp, R, m, P, NULL, NULL)); + MBEDTLS_MPI_CHK(mbedtls_ecp_mul(grp, R, m, P, self_test_rng, NULL)); for (i = 1; i < n_exponents; i++) { add_c_prev = add_count; @@ -3511,7 +3549,7 @@ static int self_test_point(int verbose, MBEDTLS_MPI_CHK(mbedtls_mpi_read_string(m, 16, exponents[i])); MBEDTLS_MPI_CHK(self_test_adjust_exponent(grp, m)); - MBEDTLS_MPI_CHK(mbedtls_ecp_mul(grp, R, m, P, NULL, NULL)); + MBEDTLS_MPI_CHK(mbedtls_ecp_mul(grp, R, m, P, self_test_rng, NULL)); if (add_count != add_c_prev || dbl_count != dbl_c_prev || @@ -3531,12 +3569,14 @@ static int self_test_point(int verbose, } return ret; } +#endif /* MBEDTLS_ECP_C */ /* * Checkup routine */ int mbedtls_ecp_self_test(int verbose) { +#if defined(MBEDTLS_ECP_C) int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED; mbedtls_ecp_group grp; mbedtls_ecp_point R, P; @@ -3589,7 +3629,7 @@ int mbedtls_ecp_self_test(int verbose) } /* Do a dummy multiplication first to trigger precomputation */ MBEDTLS_MPI_CHK(mbedtls_mpi_lset(&m, 2)); - MBEDTLS_MPI_CHK(mbedtls_ecp_mul(&grp, &P, &m, &grp.G, NULL, NULL)); + MBEDTLS_MPI_CHK(mbedtls_ecp_mul(&grp, &P, &m, &grp.G, self_test_rng, NULL)); ret = self_test_point(verbose, &grp, &R, &m, &grp.G, sw_exponents, @@ -3650,10 +3690,14 @@ int mbedtls_ecp_self_test(int verbose) } return ret; +#else /* MBEDTLS_ECP_C */ + (void) verbose; + return 0; +#endif /* MBEDTLS_ECP_C */ } #endif /* MBEDTLS_SELF_TEST */ #endif /* !MBEDTLS_ECP_ALT */ -#endif /* MBEDTLS_ECP_C */ +#endif /* MBEDTLS_ECP_LIGHT */ diff --git a/vendor/mbedtls/library/ecp_curves.c b/vendor/mbedtls/library/ecp_curves.c index 6ce4f64c16..c3cd33f47a 100644 --- a/vendor/mbedtls/library/ecp_curves.c +++ b/vendor/mbedtls/library/ecp_curves.c @@ -2,46 +2,52 @@ * Elliptic curves over GF(p): curve-specific data and functions * * Copyright The Mbed TLS Contributors - * SPDX-License-Identifier: Apache-2.0 - * - * Licensed under the Apache License, Version 2.0 (the "License"); you may - * not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT - * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. + * SPDX-License-Identifier: Apache-2.0 OR GPL-2.0-or-later */ #include "common.h" -#if defined(MBEDTLS_ECP_C) +#if !defined(MBEDTLS_ECP_WITH_MPI_UINT) + +#if defined(MBEDTLS_ECP_LIGHT) #include "mbedtls/ecp.h" #include "mbedtls/platform_util.h" #include "mbedtls/error.h" -#include "mbedtls/bn_mul.h" +#include "bn_mul.h" +#include "bignum_core.h" #include "ecp_invasive.h" #include #if !defined(MBEDTLS_ECP_ALT) -/* Parameter validation macros based on platform_util.h */ -#define ECP_VALIDATE_RET(cond) \ - MBEDTLS_INTERNAL_VALIDATE_RET(cond, MBEDTLS_ERR_ECP_BAD_INPUT_DATA) -#define ECP_VALIDATE(cond) \ - MBEDTLS_INTERNAL_VALIDATE(cond) - -#define ECP_MPI_INIT(s, n, p) { s, (n), (mbedtls_mpi_uint *) (p) } +#define ECP_MPI_INIT(_p, _n) { .p = (mbedtls_mpi_uint *) (_p), .s = 1, .n = (_n) } #define ECP_MPI_INIT_ARRAY(x) \ - ECP_MPI_INIT(1, sizeof(x) / sizeof(mbedtls_mpi_uint), x) + ECP_MPI_INIT(x, sizeof(x) / sizeof(mbedtls_mpi_uint)) + +#define ECP_POINT_INIT_XY_Z0(x, y) { \ + ECP_MPI_INIT_ARRAY(x), ECP_MPI_INIT_ARRAY(y), ECP_MPI_INIT(NULL, 0) } +#define ECP_POINT_INIT_XY_Z1(x, y) { \ + ECP_MPI_INIT_ARRAY(x), ECP_MPI_INIT_ARRAY(y), ECP_MPI_INIT(mpi_one, 1) } + +#if defined(MBEDTLS_ECP_DP_SECP192R1_ENABLED) || \ + defined(MBEDTLS_ECP_DP_SECP224R1_ENABLED) || \ + defined(MBEDTLS_ECP_DP_SECP256R1_ENABLED) || \ + defined(MBEDTLS_ECP_DP_SECP384R1_ENABLED) || \ + defined(MBEDTLS_ECP_DP_SECP521R1_ENABLED) || \ + defined(MBEDTLS_ECP_DP_BP256R1_ENABLED) || \ + defined(MBEDTLS_ECP_DP_BP384R1_ENABLED) || \ + defined(MBEDTLS_ECP_DP_BP512R1_ENABLED) || \ + defined(MBEDTLS_ECP_DP_SECP192K1_ENABLED) || \ + defined(MBEDTLS_ECP_DP_SECP224K1_ENABLED) || \ + defined(MBEDTLS_ECP_DP_SECP256K1_ENABLED) +/* For these curves, we build the group parameters dynamically. */ +#define ECP_LOAD_GROUP +static const mbedtls_mpi_uint mpi_one[] = { 1 }; +#endif /* * Note: the constants are in little-endian order @@ -77,6 +83,188 @@ static const mbedtls_mpi_uint secp192r1_n[] = { MBEDTLS_BYTES_TO_T_UINT_8(0x36, 0xF8, 0xDE, 0x99, 0xFF, 0xFF, 0xFF, 0xFF), MBEDTLS_BYTES_TO_T_UINT_8(0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF), }; +#if MBEDTLS_ECP_FIXED_POINT_OPTIM == 1 +static const mbedtls_mpi_uint secp192r1_T_0_X[] = { + MBEDTLS_BYTES_TO_T_UINT_8(0x12, 0x10, 0xFF, 0x82, 0xFD, 0x0A, 0xFF, 0xF4), + MBEDTLS_BYTES_TO_T_UINT_8(0x00, 0x88, 0xA1, 0x43, 0xEB, 0x20, 0xBF, 0x7C), + MBEDTLS_BYTES_TO_T_UINT_8(0xF6, 0x90, 0x30, 0xB0, 0x0E, 0xA8, 0x8D, 0x18), +}; +static const mbedtls_mpi_uint secp192r1_T_0_Y[] = { + MBEDTLS_BYTES_TO_T_UINT_8(0x11, 0x48, 0x79, 0x1E, 0xA1, 0x77, 0xF9, 0x73), + MBEDTLS_BYTES_TO_T_UINT_8(0xD5, 0xCD, 0x24, 0x6B, 0xED, 0x11, 0x10, 0x63), + MBEDTLS_BYTES_TO_T_UINT_8(0x78, 0xDA, 0xC8, 0xFF, 0x95, 0x2B, 0x19, 0x07), +}; +static const mbedtls_mpi_uint secp192r1_T_1_X[] = { + MBEDTLS_BYTES_TO_T_UINT_8(0x97, 0x9E, 0xE3, 0x60, 0x59, 0xD1, 0xC4, 0xC2), + MBEDTLS_BYTES_TO_T_UINT_8(0x91, 0xBD, 0x22, 0xD7, 0x2D, 0x07, 0xBD, 0xB6), + MBEDTLS_BYTES_TO_T_UINT_8(0x74, 0x2A, 0xCF, 0x33, 0xF0, 0xBE, 0xD1, 0xED), +}; +static const mbedtls_mpi_uint secp192r1_T_1_Y[] = { + MBEDTLS_BYTES_TO_T_UINT_8(0x88, 0x71, 0x4B, 0xA8, 0xED, 0x7E, 0xC9, 0x1A), + MBEDTLS_BYTES_TO_T_UINT_8(0x8E, 0x2A, 0xF6, 0xDF, 0x0E, 0xE8, 0x4C, 0x0F), + MBEDTLS_BYTES_TO_T_UINT_8(0xC5, 0x35, 0xF7, 0x8A, 0xC3, 0xEC, 0xDE, 0x1E), +}; +static const mbedtls_mpi_uint secp192r1_T_2_X[] = { + MBEDTLS_BYTES_TO_T_UINT_8(0x00, 0x67, 0xC2, 0x1D, 0x32, 0x8F, 0x10, 0xFB), + MBEDTLS_BYTES_TO_T_UINT_8(0xBB, 0x2D, 0x17, 0xF3, 0xE4, 0xFE, 0xD8, 0x13), + MBEDTLS_BYTES_TO_T_UINT_8(0x55, 0x45, 0x10, 0x70, 0x2C, 0x3E, 0x52, 0x3E), +}; +static const mbedtls_mpi_uint secp192r1_T_2_Y[] = { + MBEDTLS_BYTES_TO_T_UINT_8(0x61, 0xF1, 0x04, 0x5D, 0xEE, 0xD4, 0x56, 0xE6), + MBEDTLS_BYTES_TO_T_UINT_8(0x78, 0xB7, 0x38, 0x27, 0x61, 0xAA, 0x81, 0x87), + MBEDTLS_BYTES_TO_T_UINT_8(0x71, 0x37, 0xD7, 0x0E, 0x29, 0x0E, 0x11, 0x14), +}; +static const mbedtls_mpi_uint secp192r1_T_3_X[] = { + MBEDTLS_BYTES_TO_T_UINT_8(0x1E, 0x35, 0x52, 0xC6, 0x31, 0xB7, 0x27, 0xF5), + MBEDTLS_BYTES_TO_T_UINT_8(0x3D, 0xD4, 0x15, 0x98, 0x0F, 0xE7, 0xF3, 0x6A), + MBEDTLS_BYTES_TO_T_UINT_8(0xD3, 0x31, 0x70, 0x35, 0x09, 0xA0, 0x2B, 0xC2), +}; +static const mbedtls_mpi_uint secp192r1_T_3_Y[] = { + MBEDTLS_BYTES_TO_T_UINT_8(0x21, 0x75, 0xA7, 0x4C, 0x88, 0xCF, 0x5B, 0xE4), + MBEDTLS_BYTES_TO_T_UINT_8(0x17, 0x17, 0x48, 0x8D, 0xF2, 0xF0, 0x86, 0xED), + MBEDTLS_BYTES_TO_T_UINT_8(0x49, 0xCF, 0xFE, 0x6B, 0xB0, 0xA5, 0x06, 0xAB), +}; +static const mbedtls_mpi_uint secp192r1_T_4_X[] = { + MBEDTLS_BYTES_TO_T_UINT_8(0x18, 0x6A, 0xDC, 0x9A, 0x6D, 0x7B, 0x47, 0x2E), + MBEDTLS_BYTES_TO_T_UINT_8(0x12, 0xFC, 0x51, 0x12, 0x62, 0x66, 0x0B, 0x59), + MBEDTLS_BYTES_TO_T_UINT_8(0xCD, 0x40, 0x93, 0xA0, 0xB5, 0x5A, 0x58, 0xD7), +}; +static const mbedtls_mpi_uint secp192r1_T_4_Y[] = { + MBEDTLS_BYTES_TO_T_UINT_8(0xEF, 0xCB, 0xAF, 0xDC, 0x0B, 0xA1, 0x26, 0xFB), + MBEDTLS_BYTES_TO_T_UINT_8(0xDA, 0x36, 0x9D, 0xA3, 0xD7, 0x3B, 0xAD, 0x39), + MBEDTLS_BYTES_TO_T_UINT_8(0xB4, 0x3B, 0x05, 0x9A, 0xA8, 0xAA, 0x69, 0xB2), +}; +static const mbedtls_mpi_uint secp192r1_T_5_X[] = { + MBEDTLS_BYTES_TO_T_UINT_8(0x6D, 0xD9, 0xD1, 0x4D, 0x4A, 0x6E, 0x96, 0x1E), + MBEDTLS_BYTES_TO_T_UINT_8(0x17, 0x66, 0x32, 0x39, 0xC6, 0x57, 0x7D, 0xE6), + MBEDTLS_BYTES_TO_T_UINT_8(0x92, 0xA0, 0x36, 0xC2, 0x45, 0xF9, 0x00, 0x62), +}; +static const mbedtls_mpi_uint secp192r1_T_5_Y[] = { + MBEDTLS_BYTES_TO_T_UINT_8(0xB4, 0xEF, 0x59, 0x46, 0xDC, 0x60, 0xD9, 0x8F), + MBEDTLS_BYTES_TO_T_UINT_8(0x24, 0xB0, 0xE9, 0x41, 0xA4, 0x87, 0x76, 0x89), + MBEDTLS_BYTES_TO_T_UINT_8(0x13, 0xD4, 0x0E, 0xB2, 0xFA, 0x16, 0x56, 0xDC), +}; +static const mbedtls_mpi_uint secp192r1_T_6_X[] = { + MBEDTLS_BYTES_TO_T_UINT_8(0x0A, 0x62, 0xD2, 0xB1, 0x34, 0xB2, 0xF1, 0x06), + MBEDTLS_BYTES_TO_T_UINT_8(0xB2, 0xED, 0x55, 0xC5, 0x47, 0xB5, 0x07, 0x15), + MBEDTLS_BYTES_TO_T_UINT_8(0x17, 0xF6, 0x2F, 0x94, 0xC3, 0xDD, 0x54, 0x2F), +}; +static const mbedtls_mpi_uint secp192r1_T_6_Y[] = { + MBEDTLS_BYTES_TO_T_UINT_8(0xFD, 0xA6, 0xD4, 0x8C, 0xA9, 0xCE, 0x4D, 0x2E), + MBEDTLS_BYTES_TO_T_UINT_8(0xB9, 0x4B, 0x46, 0xCC, 0xB2, 0x55, 0xC8, 0xB2), + MBEDTLS_BYTES_TO_T_UINT_8(0x3A, 0xAE, 0x31, 0xED, 0x89, 0x65, 0x59, 0x55), +}; +static const mbedtls_mpi_uint secp192r1_T_7_X[] = { + MBEDTLS_BYTES_TO_T_UINT_8(0xCC, 0x0A, 0xD1, 0x1A, 0xC5, 0xF6, 0xEA, 0x43), + MBEDTLS_BYTES_TO_T_UINT_8(0x0C, 0xFC, 0x0C, 0x1A, 0xFB, 0xA0, 0xC8, 0x70), + MBEDTLS_BYTES_TO_T_UINT_8(0xEA, 0xFD, 0x53, 0x6F, 0x6D, 0xBF, 0xBA, 0xAF), +}; +static const mbedtls_mpi_uint secp192r1_T_7_Y[] = { + MBEDTLS_BYTES_TO_T_UINT_8(0x2D, 0xB0, 0x7D, 0x83, 0x96, 0xE3, 0xCB, 0x9D), + MBEDTLS_BYTES_TO_T_UINT_8(0x6F, 0x6E, 0x55, 0x2C, 0x20, 0x53, 0x2F, 0x46), + MBEDTLS_BYTES_TO_T_UINT_8(0xA6, 0x66, 0x00, 0x17, 0x08, 0xFE, 0xAC, 0x31), +}; +static const mbedtls_mpi_uint secp192r1_T_8_X[] = { + MBEDTLS_BYTES_TO_T_UINT_8(0x09, 0x12, 0x97, 0x3A, 0xC7, 0x57, 0x45, 0xCD), + MBEDTLS_BYTES_TO_T_UINT_8(0x38, 0x25, 0x99, 0x00, 0xF6, 0x97, 0xB4, 0x64), + MBEDTLS_BYTES_TO_T_UINT_8(0x9B, 0x74, 0xE6, 0xE6, 0xA3, 0xDF, 0x9C, 0xCC), +}; +static const mbedtls_mpi_uint secp192r1_T_8_Y[] = { + MBEDTLS_BYTES_TO_T_UINT_8(0x32, 0xF4, 0x76, 0xD5, 0x5F, 0x2A, 0xFD, 0x85), + MBEDTLS_BYTES_TO_T_UINT_8(0x62, 0x80, 0x7E, 0x3E, 0xE5, 0xE8, 0xD6, 0x63), + MBEDTLS_BYTES_TO_T_UINT_8(0xE2, 0xAD, 0x1E, 0x70, 0x79, 0x3E, 0x3D, 0x83), +}; +static const mbedtls_mpi_uint secp192r1_T_9_X[] = { + MBEDTLS_BYTES_TO_T_UINT_8(0x8E, 0x15, 0xBB, 0xB3, 0x42, 0x6A, 0xA1, 0x7C), + MBEDTLS_BYTES_TO_T_UINT_8(0x9B, 0x58, 0xCB, 0x43, 0x25, 0x00, 0x14, 0x68), + MBEDTLS_BYTES_TO_T_UINT_8(0x06, 0x4E, 0x93, 0x11, 0xE0, 0x32, 0x54, 0x98), +}; +static const mbedtls_mpi_uint secp192r1_T_9_Y[] = { + MBEDTLS_BYTES_TO_T_UINT_8(0xA7, 0x52, 0xA2, 0xB4, 0x57, 0x32, 0xB9, 0x11), + MBEDTLS_BYTES_TO_T_UINT_8(0x7D, 0x43, 0xA1, 0xB1, 0xFB, 0x01, 0xE1, 0xE7), + MBEDTLS_BYTES_TO_T_UINT_8(0xA6, 0xFB, 0x5A, 0x11, 0xB8, 0xC2, 0x03, 0xE5), +}; +static const mbedtls_mpi_uint secp192r1_T_10_X[] = { + MBEDTLS_BYTES_TO_T_UINT_8(0x1C, 0x2B, 0x71, 0x26, 0x4E, 0x7C, 0xC5, 0x32), + MBEDTLS_BYTES_TO_T_UINT_8(0x1F, 0xF5, 0xD3, 0xA8, 0xE4, 0x95, 0x48, 0x65), + MBEDTLS_BYTES_TO_T_UINT_8(0x55, 0xAE, 0xD9, 0x5D, 0x9F, 0x6A, 0x22, 0xAD), +}; +static const mbedtls_mpi_uint secp192r1_T_10_Y[] = { + MBEDTLS_BYTES_TO_T_UINT_8(0xD9, 0xCC, 0xA3, 0x4D, 0xA0, 0x1C, 0x34, 0xEF), + MBEDTLS_BYTES_TO_T_UINT_8(0xA3, 0x3C, 0x62, 0xF8, 0x5E, 0xA6, 0x58, 0x7D), + MBEDTLS_BYTES_TO_T_UINT_8(0x6D, 0x6E, 0x66, 0x8A, 0x3D, 0x17, 0xFF, 0x0F), +}; +static const mbedtls_mpi_uint secp192r1_T_11_X[] = { + MBEDTLS_BYTES_TO_T_UINT_8(0xF7, 0xCD, 0xA8, 0xDD, 0xD1, 0x20, 0x5C, 0xEA), + MBEDTLS_BYTES_TO_T_UINT_8(0xBF, 0xFE, 0x17, 0xE2, 0xCF, 0xEA, 0x63, 0xDE), + MBEDTLS_BYTES_TO_T_UINT_8(0x74, 0x51, 0xC9, 0x16, 0xDE, 0xB4, 0xB2, 0xDD), +}; +static const mbedtls_mpi_uint secp192r1_T_11_Y[] = { + MBEDTLS_BYTES_TO_T_UINT_8(0x59, 0xBE, 0x12, 0xD7, 0xA3, 0x0A, 0x50, 0x33), + MBEDTLS_BYTES_TO_T_UINT_8(0x53, 0x87, 0xC5, 0x8A, 0x76, 0x57, 0x07, 0x60), + MBEDTLS_BYTES_TO_T_UINT_8(0xE5, 0x1F, 0xC6, 0x1B, 0x66, 0xC4, 0x3D, 0x8A), +}; +static const mbedtls_mpi_uint secp192r1_T_12_X[] = { + MBEDTLS_BYTES_TO_T_UINT_8(0x28, 0xA4, 0x85, 0x13, 0x8F, 0xA7, 0x35, 0x19), + MBEDTLS_BYTES_TO_T_UINT_8(0x58, 0x0D, 0xFD, 0xFF, 0x1B, 0xD1, 0xD6, 0xEF), + MBEDTLS_BYTES_TO_T_UINT_8(0xBA, 0x7A, 0xD0, 0xC3, 0xB4, 0xEF, 0x39, 0x66), +}; +static const mbedtls_mpi_uint secp192r1_T_12_Y[] = { + MBEDTLS_BYTES_TO_T_UINT_8(0x3A, 0xFE, 0xA5, 0x9C, 0x34, 0x30, 0x49, 0x40), + MBEDTLS_BYTES_TO_T_UINT_8(0xDE, 0xC5, 0x39, 0x26, 0x06, 0xE3, 0x01, 0x17), + MBEDTLS_BYTES_TO_T_UINT_8(0xE2, 0x2B, 0x66, 0xFC, 0x95, 0x5F, 0x35, 0xF7), +}; +static const mbedtls_mpi_uint secp192r1_T_13_X[] = { + MBEDTLS_BYTES_TO_T_UINT_8(0x58, 0xCF, 0x54, 0x63, 0x99, 0x57, 0x05, 0x45), + MBEDTLS_BYTES_TO_T_UINT_8(0x71, 0x6F, 0x00, 0x5F, 0x65, 0x08, 0x47, 0x98), + MBEDTLS_BYTES_TO_T_UINT_8(0x62, 0x2A, 0x90, 0x6D, 0x67, 0xC6, 0xBC, 0x45), +}; +static const mbedtls_mpi_uint secp192r1_T_13_Y[] = { + MBEDTLS_BYTES_TO_T_UINT_8(0x8A, 0x4D, 0x88, 0x0A, 0x35, 0x9E, 0x33, 0x9C), + MBEDTLS_BYTES_TO_T_UINT_8(0x7C, 0x17, 0x0C, 0xF8, 0xE1, 0x7A, 0x49, 0x02), + MBEDTLS_BYTES_TO_T_UINT_8(0xA4, 0x44, 0x06, 0x8F, 0x0B, 0x70, 0x2F, 0x71), +}; +static const mbedtls_mpi_uint secp192r1_T_14_X[] = { + MBEDTLS_BYTES_TO_T_UINT_8(0x85, 0x4B, 0xCB, 0xF9, 0x8E, 0x6A, 0xDA, 0x1B), + MBEDTLS_BYTES_TO_T_UINT_8(0x29, 0x43, 0xA1, 0x3F, 0xCE, 0x17, 0xD2, 0x32), + MBEDTLS_BYTES_TO_T_UINT_8(0x5D, 0x0D, 0xD2, 0x6C, 0x82, 0x37, 0xE5, 0xFC), +}; +static const mbedtls_mpi_uint secp192r1_T_14_Y[] = { + MBEDTLS_BYTES_TO_T_UINT_8(0x4A, 0x3C, 0xF4, 0x92, 0xB4, 0x8A, 0x95, 0x85), + MBEDTLS_BYTES_TO_T_UINT_8(0x85, 0x96, 0xF1, 0x0A, 0x34, 0x2F, 0x74, 0x7E), + MBEDTLS_BYTES_TO_T_UINT_8(0x7B, 0xA1, 0xAA, 0xBA, 0x86, 0x77, 0x4F, 0xA2), +}; +static const mbedtls_mpi_uint secp192r1_T_15_X[] = { + MBEDTLS_BYTES_TO_T_UINT_8(0xE5, 0x7F, 0xEF, 0x60, 0x50, 0x80, 0xD7, 0xD4), + MBEDTLS_BYTES_TO_T_UINT_8(0x31, 0xAC, 0xC9, 0xFE, 0xEC, 0x0A, 0x1A, 0x9F), + MBEDTLS_BYTES_TO_T_UINT_8(0x6B, 0x2F, 0xBE, 0x91, 0xD7, 0xB7, 0x38, 0x48), +}; +static const mbedtls_mpi_uint secp192r1_T_15_Y[] = { + MBEDTLS_BYTES_TO_T_UINT_8(0xB1, 0xAE, 0x85, 0x98, 0xFE, 0x05, 0x7F, 0x9F), + MBEDTLS_BYTES_TO_T_UINT_8(0x91, 0xBE, 0xFD, 0x11, 0x31, 0x3D, 0x14, 0x13), + MBEDTLS_BYTES_TO_T_UINT_8(0x59, 0x75, 0xE8, 0x30, 0x01, 0xCB, 0x9B, 0x1C), +}; +static const mbedtls_ecp_point secp192r1_T[16] = { + ECP_POINT_INIT_XY_Z1(secp192r1_T_0_X, secp192r1_T_0_Y), + ECP_POINT_INIT_XY_Z0(secp192r1_T_1_X, secp192r1_T_1_Y), + ECP_POINT_INIT_XY_Z0(secp192r1_T_2_X, secp192r1_T_2_Y), + ECP_POINT_INIT_XY_Z0(secp192r1_T_3_X, secp192r1_T_3_Y), + ECP_POINT_INIT_XY_Z0(secp192r1_T_4_X, secp192r1_T_4_Y), + ECP_POINT_INIT_XY_Z0(secp192r1_T_5_X, secp192r1_T_5_Y), + ECP_POINT_INIT_XY_Z0(secp192r1_T_6_X, secp192r1_T_6_Y), + ECP_POINT_INIT_XY_Z0(secp192r1_T_7_X, secp192r1_T_7_Y), + ECP_POINT_INIT_XY_Z0(secp192r1_T_8_X, secp192r1_T_8_Y), + ECP_POINT_INIT_XY_Z0(secp192r1_T_9_X, secp192r1_T_9_Y), + ECP_POINT_INIT_XY_Z0(secp192r1_T_10_X, secp192r1_T_10_Y), + ECP_POINT_INIT_XY_Z0(secp192r1_T_11_X, secp192r1_T_11_Y), + ECP_POINT_INIT_XY_Z0(secp192r1_T_12_X, secp192r1_T_12_Y), + ECP_POINT_INIT_XY_Z0(secp192r1_T_13_X, secp192r1_T_13_Y), + ECP_POINT_INIT_XY_Z0(secp192r1_T_14_X, secp192r1_T_14_Y), + ECP_POINT_INIT_XY_Z0(secp192r1_T_15_X, secp192r1_T_15_Y), +}; +#else +#define secp192r1_T NULL +#endif #endif /* MBEDTLS_ECP_DP_SECP192R1_ENABLED */ /* @@ -113,6 +301,220 @@ static const mbedtls_mpi_uint secp224r1_n[] = { MBEDTLS_BYTES_TO_T_UINT_8(0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF), MBEDTLS_BYTES_TO_T_UINT_4(0xFF, 0xFF, 0xFF, 0xFF), }; +#if MBEDTLS_ECP_FIXED_POINT_OPTIM == 1 +static const mbedtls_mpi_uint secp224r1_T_0_X[] = { + MBEDTLS_BYTES_TO_T_UINT_8(0x21, 0x1D, 0x5C, 0x11, 0xD6, 0x80, 0x32, 0x34), + MBEDTLS_BYTES_TO_T_UINT_8(0x22, 0x11, 0xC2, 0x56, 0xD3, 0xC1, 0x03, 0x4A), + MBEDTLS_BYTES_TO_T_UINT_8(0xB9, 0x90, 0x13, 0x32, 0x7F, 0xBF, 0xB4, 0x6B), + MBEDTLS_BYTES_TO_T_UINT_8(0xBD, 0x0C, 0x0E, 0xB7, 0x00, 0x00, 0x00, 0x00), +}; +static const mbedtls_mpi_uint secp224r1_T_0_Y[] = { + MBEDTLS_BYTES_TO_T_UINT_8(0x34, 0x7E, 0x00, 0x85, 0x99, 0x81, 0xD5, 0x44), + MBEDTLS_BYTES_TO_T_UINT_8(0x64, 0x47, 0x07, 0x5A, 0xA0, 0x75, 0x43, 0xCD), + MBEDTLS_BYTES_TO_T_UINT_8(0xE6, 0xDF, 0x22, 0x4C, 0xFB, 0x23, 0xF7, 0xB5), + MBEDTLS_BYTES_TO_T_UINT_8(0x88, 0x63, 0x37, 0xBD, 0x00, 0x00, 0x00, 0x00), +}; +static const mbedtls_mpi_uint secp224r1_T_1_X[] = { + MBEDTLS_BYTES_TO_T_UINT_8(0xE0, 0xF9, 0xB8, 0xD0, 0x3D, 0xD2, 0xD3, 0xFA), + MBEDTLS_BYTES_TO_T_UINT_8(0x1E, 0xFD, 0x99, 0x26, 0x19, 0xFE, 0x13, 0x6E), + MBEDTLS_BYTES_TO_T_UINT_8(0x1C, 0x0E, 0x4C, 0x48, 0x7C, 0xA2, 0x17, 0x01), + MBEDTLS_BYTES_TO_T_UINT_8(0x3D, 0xA3, 0x13, 0x57, 0x00, 0x00, 0x00, 0x00), +}; +static const mbedtls_mpi_uint secp224r1_T_1_Y[] = { + MBEDTLS_BYTES_TO_T_UINT_8(0x9F, 0x16, 0x5C, 0x8F, 0xAA, 0xED, 0x0F, 0x58), + MBEDTLS_BYTES_TO_T_UINT_8(0xBF, 0xC5, 0x43, 0x34, 0x93, 0x05, 0x2A, 0x4C), + MBEDTLS_BYTES_TO_T_UINT_8(0xE4, 0xE3, 0x6C, 0xCA, 0xC6, 0x14, 0xC2, 0x25), + MBEDTLS_BYTES_TO_T_UINT_8(0xD3, 0x43, 0x6C, 0xD7, 0x00, 0x00, 0x00, 0x00), +}; +static const mbedtls_mpi_uint secp224r1_T_2_X[] = { + MBEDTLS_BYTES_TO_T_UINT_8(0xC3, 0x5A, 0x98, 0x1E, 0xC8, 0xA5, 0x42, 0xA3), + MBEDTLS_BYTES_TO_T_UINT_8(0x98, 0x49, 0x56, 0x78, 0xF8, 0xEF, 0xED, 0x65), + MBEDTLS_BYTES_TO_T_UINT_8(0x1B, 0xBB, 0x64, 0xB6, 0x4C, 0x54, 0x5F, 0xD1), + MBEDTLS_BYTES_TO_T_UINT_8(0x2F, 0x0C, 0x33, 0xCC, 0x00, 0x00, 0x00, 0x00), +}; +static const mbedtls_mpi_uint secp224r1_T_2_Y[] = { + MBEDTLS_BYTES_TO_T_UINT_8(0xFA, 0x79, 0xCB, 0x2E, 0x08, 0xFF, 0xD8, 0xE6), + MBEDTLS_BYTES_TO_T_UINT_8(0x2E, 0x1F, 0xD4, 0xD7, 0x57, 0xE9, 0x39, 0x45), + MBEDTLS_BYTES_TO_T_UINT_8(0xD8, 0xD6, 0x3B, 0x0A, 0x1C, 0x87, 0xB7, 0x6A), + MBEDTLS_BYTES_TO_T_UINT_8(0xEB, 0x30, 0xD8, 0x05, 0x00, 0x00, 0x00, 0x00), +}; +static const mbedtls_mpi_uint secp224r1_T_3_X[] = { + MBEDTLS_BYTES_TO_T_UINT_8(0xAD, 0x79, 0x74, 0x9A, 0xE6, 0xBB, 0xC2, 0xC2), + MBEDTLS_BYTES_TO_T_UINT_8(0xB4, 0x5B, 0xA6, 0x67, 0xC1, 0x91, 0xE7, 0x64), + MBEDTLS_BYTES_TO_T_UINT_8(0xF0, 0xDF, 0x38, 0x82, 0x19, 0x2C, 0x4C, 0xCA), + MBEDTLS_BYTES_TO_T_UINT_8(0xD1, 0x2E, 0x39, 0xC5, 0x00, 0x00, 0x00, 0x00), +}; +static const mbedtls_mpi_uint secp224r1_T_3_Y[] = { + MBEDTLS_BYTES_TO_T_UINT_8(0x99, 0x36, 0x78, 0x4E, 0xAE, 0x5B, 0x02, 0x76), + MBEDTLS_BYTES_TO_T_UINT_8(0x14, 0xF6, 0x8B, 0xF8, 0xF4, 0x92, 0x6B, 0x42), + MBEDTLS_BYTES_TO_T_UINT_8(0xBA, 0x4D, 0x71, 0x35, 0xE7, 0x0C, 0x2C, 0x98), + MBEDTLS_BYTES_TO_T_UINT_8(0x9B, 0xA5, 0x1F, 0xAE, 0x00, 0x00, 0x00, 0x00), +}; +static const mbedtls_mpi_uint secp224r1_T_4_X[] = { + MBEDTLS_BYTES_TO_T_UINT_8(0xAF, 0x1C, 0x4B, 0xDF, 0x5B, 0xF2, 0x51, 0xB7), + MBEDTLS_BYTES_TO_T_UINT_8(0x05, 0x74, 0xB1, 0x5A, 0xC6, 0x0F, 0x0E, 0x61), + MBEDTLS_BYTES_TO_T_UINT_8(0xE8, 0x24, 0x09, 0x62, 0xAF, 0xFC, 0xDB, 0x45), + MBEDTLS_BYTES_TO_T_UINT_8(0x43, 0xE1, 0x80, 0x55, 0x00, 0x00, 0x00, 0x00), +}; +static const mbedtls_mpi_uint secp224r1_T_4_Y[] = { + MBEDTLS_BYTES_TO_T_UINT_8(0x3C, 0x82, 0xFE, 0xAD, 0xC3, 0xE5, 0xCF, 0xD8), + MBEDTLS_BYTES_TO_T_UINT_8(0x24, 0xA2, 0x62, 0x17, 0x76, 0xF0, 0x5A, 0xFA), + MBEDTLS_BYTES_TO_T_UINT_8(0x3E, 0xB8, 0xE5, 0xAC, 0xB7, 0x66, 0x38, 0xAA), + MBEDTLS_BYTES_TO_T_UINT_8(0x97, 0xFD, 0x86, 0x05, 0x00, 0x00, 0x00, 0x00), +}; +static const mbedtls_mpi_uint secp224r1_T_5_X[] = { + MBEDTLS_BYTES_TO_T_UINT_8(0x59, 0xD3, 0x0C, 0x3C, 0xD1, 0x66, 0xB0, 0xF1), + MBEDTLS_BYTES_TO_T_UINT_8(0xBC, 0x59, 0xB4, 0x8D, 0x90, 0x10, 0xB7, 0xA2), + MBEDTLS_BYTES_TO_T_UINT_8(0x96, 0x47, 0x9B, 0xE6, 0x55, 0x8A, 0xE4, 0xEE), + MBEDTLS_BYTES_TO_T_UINT_8(0xB1, 0x49, 0xDB, 0x78, 0x00, 0x00, 0x00, 0x00), +}; +static const mbedtls_mpi_uint secp224r1_T_5_Y[] = { + MBEDTLS_BYTES_TO_T_UINT_8(0x41, 0x97, 0xED, 0xDE, 0xFF, 0xB3, 0xDF, 0x48), + MBEDTLS_BYTES_TO_T_UINT_8(0x10, 0xB9, 0x83, 0xB7, 0xEB, 0xBE, 0x40, 0x8D), + MBEDTLS_BYTES_TO_T_UINT_8(0xAF, 0xD3, 0xD3, 0xCD, 0x0E, 0x82, 0x79, 0x3D), + MBEDTLS_BYTES_TO_T_UINT_8(0x9B, 0x83, 0x1B, 0xF0, 0x00, 0x00, 0x00, 0x00), +}; +static const mbedtls_mpi_uint secp224r1_T_6_X[] = { + MBEDTLS_BYTES_TO_T_UINT_8(0x3F, 0x22, 0xBB, 0x54, 0xD3, 0x31, 0x56, 0xFC), + MBEDTLS_BYTES_TO_T_UINT_8(0x80, 0x36, 0xE5, 0xE0, 0x89, 0x96, 0x8E, 0x71), + MBEDTLS_BYTES_TO_T_UINT_8(0xE1, 0xEF, 0x0A, 0xED, 0xD0, 0x11, 0x4A, 0xFF), + MBEDTLS_BYTES_TO_T_UINT_8(0x15, 0x00, 0x57, 0x27, 0x00, 0x00, 0x00, 0x00), +}; +static const mbedtls_mpi_uint secp224r1_T_6_Y[] = { + MBEDTLS_BYTES_TO_T_UINT_8(0x13, 0xCA, 0x3D, 0xF7, 0x64, 0x9B, 0x6E, 0x85), + MBEDTLS_BYTES_TO_T_UINT_8(0x90, 0xE3, 0x70, 0x6B, 0x41, 0xD7, 0xED, 0x8F), + MBEDTLS_BYTES_TO_T_UINT_8(0x02, 0x44, 0x44, 0x80, 0xCE, 0x13, 0x37, 0x92), + MBEDTLS_BYTES_TO_T_UINT_8(0x94, 0x73, 0x80, 0x79, 0x00, 0x00, 0x00, 0x00), +}; +static const mbedtls_mpi_uint secp224r1_T_7_X[] = { + MBEDTLS_BYTES_TO_T_UINT_8(0xB7, 0x4D, 0x70, 0x7D, 0x31, 0x0F, 0x1C, 0x58), + MBEDTLS_BYTES_TO_T_UINT_8(0x6D, 0x35, 0x88, 0x47, 0xC4, 0x24, 0x78, 0x3F), + MBEDTLS_BYTES_TO_T_UINT_8(0xBA, 0xF0, 0xCD, 0x91, 0x81, 0xB3, 0xDE, 0xB6), + MBEDTLS_BYTES_TO_T_UINT_8(0x04, 0xCE, 0xC6, 0xF7, 0x00, 0x00, 0x00, 0x00), +}; +static const mbedtls_mpi_uint secp224r1_T_7_Y[] = { + MBEDTLS_BYTES_TO_T_UINT_8(0xE9, 0x9C, 0x2D, 0xE8, 0xD2, 0x00, 0x8F, 0x10), + MBEDTLS_BYTES_TO_T_UINT_8(0xD5, 0x5E, 0x7C, 0x0E, 0x0C, 0x6E, 0x58, 0x02), + MBEDTLS_BYTES_TO_T_UINT_8(0xAE, 0x81, 0x21, 0xCE, 0x43, 0xF4, 0x24, 0x3D), + MBEDTLS_BYTES_TO_T_UINT_8(0x9E, 0xBC, 0xF0, 0xF4, 0x00, 0x00, 0x00, 0x00), +}; +static const mbedtls_mpi_uint secp224r1_T_8_X[] = { + MBEDTLS_BYTES_TO_T_UINT_8(0xD6, 0x10, 0xC2, 0x74, 0x4A, 0x8F, 0x8A, 0xCF), + MBEDTLS_BYTES_TO_T_UINT_8(0x89, 0x67, 0xF4, 0x2B, 0x38, 0x2B, 0x35, 0x17), + MBEDTLS_BYTES_TO_T_UINT_8(0xF5, 0xE7, 0x0C, 0xA9, 0xFA, 0x77, 0x5C, 0xBD), + MBEDTLS_BYTES_TO_T_UINT_8(0xE0, 0x33, 0x19, 0x2B, 0x00, 0x00, 0x00, 0x00), +}; +static const mbedtls_mpi_uint secp224r1_T_8_Y[] = { + MBEDTLS_BYTES_TO_T_UINT_8(0xE7, 0x3E, 0x96, 0x22, 0x53, 0xE1, 0xE9, 0xBE), + MBEDTLS_BYTES_TO_T_UINT_8(0xE0, 0x13, 0xBC, 0xA1, 0x16, 0xEC, 0x01, 0x1A), + MBEDTLS_BYTES_TO_T_UINT_8(0x9A, 0x00, 0xC9, 0x7A, 0xC3, 0x73, 0xA5, 0x45), + MBEDTLS_BYTES_TO_T_UINT_8(0xE1, 0xF4, 0x5E, 0xC1, 0x00, 0x00, 0x00, 0x00), +}; +static const mbedtls_mpi_uint secp224r1_T_9_X[] = { + MBEDTLS_BYTES_TO_T_UINT_8(0xA8, 0x95, 0xD6, 0xD9, 0x32, 0x30, 0x2B, 0xD0), + MBEDTLS_BYTES_TO_T_UINT_8(0x77, 0x42, 0x09, 0x05, 0x61, 0x2A, 0x7E, 0x82), + MBEDTLS_BYTES_TO_T_UINT_8(0x73, 0x84, 0xA2, 0x05, 0x88, 0x64, 0x65, 0xF9), + MBEDTLS_BYTES_TO_T_UINT_8(0x03, 0x2D, 0x90, 0xB3, 0x00, 0x00, 0x00, 0x00), +}; +static const mbedtls_mpi_uint secp224r1_T_9_Y[] = { + MBEDTLS_BYTES_TO_T_UINT_8(0x0A, 0xE7, 0x2E, 0x85, 0x55, 0x80, 0x7C, 0x79), + MBEDTLS_BYTES_TO_T_UINT_8(0x0F, 0xC1, 0xAC, 0x78, 0xB4, 0xAF, 0xFB, 0x6E), + MBEDTLS_BYTES_TO_T_UINT_8(0xD3, 0xC3, 0x28, 0x8E, 0x79, 0x18, 0x1F, 0x58), + MBEDTLS_BYTES_TO_T_UINT_8(0x34, 0x46, 0xCF, 0x49, 0x00, 0x00, 0x00, 0x00), +}; +static const mbedtls_mpi_uint secp224r1_T_10_X[] = { + MBEDTLS_BYTES_TO_T_UINT_8(0x63, 0x5F, 0xA8, 0x6C, 0x46, 0x83, 0x43, 0xFA), + MBEDTLS_BYTES_TO_T_UINT_8(0xFA, 0xA9, 0x93, 0x11, 0xB6, 0x07, 0x57, 0x74), + MBEDTLS_BYTES_TO_T_UINT_8(0x77, 0x2A, 0x9D, 0x03, 0x89, 0x7E, 0xD7, 0x3C), + MBEDTLS_BYTES_TO_T_UINT_8(0x7B, 0x8C, 0x62, 0xCF, 0x00, 0x00, 0x00, 0x00), +}; +static const mbedtls_mpi_uint secp224r1_T_10_Y[] = { + MBEDTLS_BYTES_TO_T_UINT_8(0x44, 0x2C, 0x13, 0x59, 0xCC, 0xFA, 0x84, 0x9E), + MBEDTLS_BYTES_TO_T_UINT_8(0x51, 0xB9, 0x48, 0xBC, 0x57, 0xC7, 0xB3, 0x7C), + MBEDTLS_BYTES_TO_T_UINT_8(0xFC, 0x0A, 0x38, 0x24, 0x2E, 0x3A, 0x28, 0x25), + MBEDTLS_BYTES_TO_T_UINT_8(0xBC, 0x0A, 0x43, 0xB8, 0x00, 0x00, 0x00, 0x00), +}; +static const mbedtls_mpi_uint secp224r1_T_11_X[] = { + MBEDTLS_BYTES_TO_T_UINT_8(0x59, 0x25, 0xAB, 0xC1, 0xEE, 0x70, 0x3C, 0xE1), + MBEDTLS_BYTES_TO_T_UINT_8(0xF3, 0xDB, 0x45, 0x1D, 0x4A, 0x80, 0x75, 0x35), + MBEDTLS_BYTES_TO_T_UINT_8(0xE8, 0x1F, 0x4D, 0x2D, 0x9A, 0x05, 0xF4, 0xCB), + MBEDTLS_BYTES_TO_T_UINT_8(0x6B, 0x10, 0xF0, 0x5A, 0x00, 0x00, 0x00, 0x00), +}; +static const mbedtls_mpi_uint secp224r1_T_11_Y[] = { + MBEDTLS_BYTES_TO_T_UINT_8(0x35, 0x95, 0xE1, 0xDC, 0x15, 0x86, 0xC3, 0x7B), + MBEDTLS_BYTES_TO_T_UINT_8(0xEC, 0xDC, 0x27, 0xD1, 0x56, 0xA1, 0x14, 0x0D), + MBEDTLS_BYTES_TO_T_UINT_8(0x59, 0x0B, 0xD6, 0x77, 0x4E, 0x44, 0xA2, 0xF8), + MBEDTLS_BYTES_TO_T_UINT_8(0x94, 0x42, 0x71, 0x1F, 0x00, 0x00, 0x00, 0x00), +}; +static const mbedtls_mpi_uint secp224r1_T_12_X[] = { + MBEDTLS_BYTES_TO_T_UINT_8(0x30, 0x86, 0xB2, 0xB0, 0xC8, 0x2F, 0x7B, 0xFE), + MBEDTLS_BYTES_TO_T_UINT_8(0x96, 0xEF, 0xCB, 0xDB, 0xBC, 0x9E, 0x3B, 0xC5), + MBEDTLS_BYTES_TO_T_UINT_8(0x1B, 0x03, 0x86, 0xDD, 0x5B, 0xF5, 0x8D, 0x46), + MBEDTLS_BYTES_TO_T_UINT_8(0x58, 0x95, 0x79, 0xD6, 0x00, 0x00, 0x00, 0x00), +}; +static const mbedtls_mpi_uint secp224r1_T_12_Y[] = { + MBEDTLS_BYTES_TO_T_UINT_8(0x84, 0x32, 0x14, 0xDA, 0x9B, 0x4F, 0x07, 0x39), + MBEDTLS_BYTES_TO_T_UINT_8(0xB5, 0x3E, 0xFB, 0x06, 0xEE, 0xA7, 0x40, 0x40), + MBEDTLS_BYTES_TO_T_UINT_8(0x76, 0x1F, 0xDF, 0x71, 0x61, 0xFD, 0x8B, 0xBE), + MBEDTLS_BYTES_TO_T_UINT_8(0x80, 0x8B, 0xAB, 0x8B, 0x00, 0x00, 0x00, 0x00), +}; +static const mbedtls_mpi_uint secp224r1_T_13_X[] = { + MBEDTLS_BYTES_TO_T_UINT_8(0xC9, 0x34, 0xB3, 0xB4, 0xBC, 0x9F, 0xB0, 0x5E), + MBEDTLS_BYTES_TO_T_UINT_8(0xE6, 0x58, 0x48, 0xA8, 0x77, 0xBB, 0x13, 0x2F), + MBEDTLS_BYTES_TO_T_UINT_8(0x41, 0xC6, 0xF7, 0x34, 0xCC, 0x89, 0x21, 0x0A), + MBEDTLS_BYTES_TO_T_UINT_8(0xCA, 0x33, 0xDD, 0x1F, 0x00, 0x00, 0x00, 0x00), +}; +static const mbedtls_mpi_uint secp224r1_T_13_Y[] = { + MBEDTLS_BYTES_TO_T_UINT_8(0xCC, 0x81, 0xEF, 0xA4, 0xF2, 0x10, 0x0B, 0xCD), + MBEDTLS_BYTES_TO_T_UINT_8(0x83, 0xF7, 0x6E, 0x72, 0x4A, 0xDF, 0xDD, 0xE8), + MBEDTLS_BYTES_TO_T_UINT_8(0x67, 0x23, 0x0A, 0x53, 0x03, 0x16, 0x62, 0xD2), + MBEDTLS_BYTES_TO_T_UINT_8(0x0B, 0x76, 0xFD, 0x3C, 0x00, 0x00, 0x00, 0x00), +}; +static const mbedtls_mpi_uint secp224r1_T_14_X[] = { + MBEDTLS_BYTES_TO_T_UINT_8(0xCB, 0x14, 0xA1, 0xFA, 0xA0, 0x18, 0xBE, 0x07), + MBEDTLS_BYTES_TO_T_UINT_8(0x03, 0x2A, 0xE1, 0xD7, 0xB0, 0x6C, 0xA0, 0xDE), + MBEDTLS_BYTES_TO_T_UINT_8(0xD1, 0xC0, 0xB0, 0xC6, 0x63, 0x24, 0xCD, 0x4E), + MBEDTLS_BYTES_TO_T_UINT_8(0x33, 0x38, 0x2C, 0xB1, 0x00, 0x00, 0x00, 0x00), +}; +static const mbedtls_mpi_uint secp224r1_T_14_Y[] = { + MBEDTLS_BYTES_TO_T_UINT_8(0xEE, 0xCD, 0x7D, 0x20, 0x0C, 0xFE, 0xAC, 0xC3), + MBEDTLS_BYTES_TO_T_UINT_8(0x09, 0x97, 0x9F, 0xA2, 0xB6, 0x45, 0xF7, 0x7B), + MBEDTLS_BYTES_TO_T_UINT_8(0xCA, 0x99, 0xF3, 0xD2, 0x20, 0x02, 0xEB, 0x04), + MBEDTLS_BYTES_TO_T_UINT_8(0x43, 0x18, 0x5B, 0x7B, 0x00, 0x00, 0x00, 0x00), +}; +static const mbedtls_mpi_uint secp224r1_T_15_X[] = { + MBEDTLS_BYTES_TO_T_UINT_8(0x2B, 0xDD, 0x77, 0x91, 0x60, 0xEA, 0xFD, 0xD3), + MBEDTLS_BYTES_TO_T_UINT_8(0x7D, 0xD3, 0xB5, 0xD6, 0x90, 0x17, 0x0E, 0x1A), + MBEDTLS_BYTES_TO_T_UINT_8(0x00, 0xF4, 0x28, 0xC1, 0xF2, 0x53, 0xF6, 0x63), + MBEDTLS_BYTES_TO_T_UINT_8(0x49, 0x58, 0xDC, 0x61, 0x00, 0x00, 0x00, 0x00), +}; +static const mbedtls_mpi_uint secp224r1_T_15_Y[] = { + MBEDTLS_BYTES_TO_T_UINT_8(0xA8, 0x20, 0x01, 0xFB, 0xF1, 0xBD, 0x5F, 0x45), + MBEDTLS_BYTES_TO_T_UINT_8(0xD0, 0x7F, 0x06, 0xDA, 0x11, 0xCB, 0xBA, 0xA6), + MBEDTLS_BYTES_TO_T_UINT_8(0xA7, 0x41, 0x00, 0xA4, 0x1B, 0x30, 0x33, 0x79), + MBEDTLS_BYTES_TO_T_UINT_8(0xF4, 0xFF, 0x27, 0xCA, 0x00, 0x00, 0x00, 0x00), +}; +static const mbedtls_ecp_point secp224r1_T[16] = { + ECP_POINT_INIT_XY_Z1(secp224r1_T_0_X, secp224r1_T_0_Y), + ECP_POINT_INIT_XY_Z0(secp224r1_T_1_X, secp224r1_T_1_Y), + ECP_POINT_INIT_XY_Z0(secp224r1_T_2_X, secp224r1_T_2_Y), + ECP_POINT_INIT_XY_Z0(secp224r1_T_3_X, secp224r1_T_3_Y), + ECP_POINT_INIT_XY_Z0(secp224r1_T_4_X, secp224r1_T_4_Y), + ECP_POINT_INIT_XY_Z0(secp224r1_T_5_X, secp224r1_T_5_Y), + ECP_POINT_INIT_XY_Z0(secp224r1_T_6_X, secp224r1_T_6_Y), + ECP_POINT_INIT_XY_Z0(secp224r1_T_7_X, secp224r1_T_7_Y), + ECP_POINT_INIT_XY_Z0(secp224r1_T_8_X, secp224r1_T_8_Y), + ECP_POINT_INIT_XY_Z0(secp224r1_T_9_X, secp224r1_T_9_Y), + ECP_POINT_INIT_XY_Z0(secp224r1_T_10_X, secp224r1_T_10_Y), + ECP_POINT_INIT_XY_Z0(secp224r1_T_11_X, secp224r1_T_11_Y), + ECP_POINT_INIT_XY_Z0(secp224r1_T_12_X, secp224r1_T_12_Y), + ECP_POINT_INIT_XY_Z0(secp224r1_T_13_X, secp224r1_T_13_Y), + ECP_POINT_INIT_XY_Z0(secp224r1_T_14_X, secp224r1_T_14_Y), + ECP_POINT_INIT_XY_Z0(secp224r1_T_15_X, secp224r1_T_15_Y), +}; +#else +#define secp224r1_T NULL +#endif #endif /* MBEDTLS_ECP_DP_SECP224R1_ENABLED */ /* @@ -149,6 +551,221 @@ static const mbedtls_mpi_uint secp256r1_n[] = { MBEDTLS_BYTES_TO_T_UINT_8(0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF), MBEDTLS_BYTES_TO_T_UINT_8(0x00, 0x00, 0x00, 0x00, 0xFF, 0xFF, 0xFF, 0xFF), }; +#if MBEDTLS_ECP_FIXED_POINT_OPTIM == 1 +static const mbedtls_mpi_uint secp256r1_T_0_X[] = { + MBEDTLS_BYTES_TO_T_UINT_8(0x96, 0xC2, 0x98, 0xD8, 0x45, 0x39, 0xA1, 0xF4), + MBEDTLS_BYTES_TO_T_UINT_8(0xA0, 0x33, 0xEB, 0x2D, 0x81, 0x7D, 0x03, 0x77), + MBEDTLS_BYTES_TO_T_UINT_8(0xF2, 0x40, 0xA4, 0x63, 0xE5, 0xE6, 0xBC, 0xF8), + MBEDTLS_BYTES_TO_T_UINT_8(0x47, 0x42, 0x2C, 0xE1, 0xF2, 0xD1, 0x17, 0x6B), +}; +static const mbedtls_mpi_uint secp256r1_T_0_Y[] = { + MBEDTLS_BYTES_TO_T_UINT_8(0xF5, 0x51, 0xBF, 0x37, 0x68, 0x40, 0xB6, 0xCB), + MBEDTLS_BYTES_TO_T_UINT_8(0xCE, 0x5E, 0x31, 0x6B, 0x57, 0x33, 0xCE, 0x2B), + MBEDTLS_BYTES_TO_T_UINT_8(0x16, 0x9E, 0x0F, 0x7C, 0x4A, 0xEB, 0xE7, 0x8E), + MBEDTLS_BYTES_TO_T_UINT_8(0x9B, 0x7F, 0x1A, 0xFE, 0xE2, 0x42, 0xE3, 0x4F), +}; +static const mbedtls_mpi_uint secp256r1_T_1_X[] = { + MBEDTLS_BYTES_TO_T_UINT_8(0x70, 0xC8, 0xBA, 0x04, 0xB7, 0x4B, 0xD2, 0xF7), + MBEDTLS_BYTES_TO_T_UINT_8(0xAB, 0xC6, 0x23, 0x3A, 0xA0, 0x09, 0x3A, 0x59), + MBEDTLS_BYTES_TO_T_UINT_8(0x1D, 0x9D, 0x4C, 0xF9, 0x58, 0x23, 0xCC, 0xDF), + MBEDTLS_BYTES_TO_T_UINT_8(0x02, 0xED, 0x7B, 0x29, 0x87, 0x0F, 0xFA, 0x3C), +}; +static const mbedtls_mpi_uint secp256r1_T_1_Y[] = { + MBEDTLS_BYTES_TO_T_UINT_8(0x40, 0x69, 0xF2, 0x40, 0x0B, 0xA3, 0x98, 0xCE), + MBEDTLS_BYTES_TO_T_UINT_8(0xAF, 0xA8, 0x48, 0x02, 0x0D, 0x1C, 0x12, 0x62), + MBEDTLS_BYTES_TO_T_UINT_8(0x9B, 0xAF, 0x09, 0x83, 0x80, 0xAA, 0x58, 0xA7), + MBEDTLS_BYTES_TO_T_UINT_8(0xC6, 0x12, 0xBE, 0x70, 0x94, 0x76, 0xE3, 0xE4), +}; +static const mbedtls_mpi_uint secp256r1_T_2_X[] = { + MBEDTLS_BYTES_TO_T_UINT_8(0x7D, 0x7D, 0xEF, 0x86, 0xFF, 0xE3, 0x37, 0xDD), + MBEDTLS_BYTES_TO_T_UINT_8(0xDB, 0x86, 0x8B, 0x08, 0x27, 0x7C, 0xD7, 0xF6), + MBEDTLS_BYTES_TO_T_UINT_8(0x91, 0x54, 0x4C, 0x25, 0x4F, 0x9A, 0xFE, 0x28), + MBEDTLS_BYTES_TO_T_UINT_8(0x5E, 0xFD, 0xF0, 0x6D, 0x37, 0x03, 0x69, 0xD6), +}; +static const mbedtls_mpi_uint secp256r1_T_2_Y[] = { + MBEDTLS_BYTES_TO_T_UINT_8(0x96, 0xD5, 0xDA, 0xAD, 0x92, 0x49, 0xF0, 0x9F), + MBEDTLS_BYTES_TO_T_UINT_8(0xF9, 0x73, 0x43, 0x9E, 0xAF, 0xA7, 0xD1, 0xF3), + MBEDTLS_BYTES_TO_T_UINT_8(0x67, 0x41, 0x07, 0xDF, 0x78, 0x95, 0x3E, 0xA1), + MBEDTLS_BYTES_TO_T_UINT_8(0x22, 0x3D, 0xD1, 0xE6, 0x3C, 0xA5, 0xE2, 0x20), +}; +static const mbedtls_mpi_uint secp256r1_T_3_X[] = { + MBEDTLS_BYTES_TO_T_UINT_8(0xBF, 0x6A, 0x5D, 0x52, 0x35, 0xD7, 0xBF, 0xAE), + MBEDTLS_BYTES_TO_T_UINT_8(0x5A, 0xA2, 0xBE, 0x96, 0xF4, 0xF8, 0x02, 0xC3), + MBEDTLS_BYTES_TO_T_UINT_8(0xA4, 0x20, 0x49, 0x54, 0xEA, 0xB3, 0x82, 0xDB), + MBEDTLS_BYTES_TO_T_UINT_8(0x2E, 0xDB, 0xEA, 0x02, 0xD1, 0x75, 0x1C, 0x62), +}; +static const mbedtls_mpi_uint secp256r1_T_3_Y[] = { + MBEDTLS_BYTES_TO_T_UINT_8(0xF0, 0x85, 0xF4, 0x9E, 0x4C, 0xDC, 0x39, 0x89), + MBEDTLS_BYTES_TO_T_UINT_8(0x63, 0x6D, 0xC4, 0x57, 0xD8, 0x03, 0x5D, 0x22), + MBEDTLS_BYTES_TO_T_UINT_8(0x70, 0x7F, 0x2D, 0x52, 0x6F, 0xC9, 0xDA, 0x4F), + MBEDTLS_BYTES_TO_T_UINT_8(0x9D, 0x64, 0xFA, 0xB4, 0xFE, 0xA4, 0xC4, 0xD7), +}; +static const mbedtls_mpi_uint secp256r1_T_4_X[] = { + MBEDTLS_BYTES_TO_T_UINT_8(0x2A, 0x37, 0xB9, 0xC0, 0xAA, 0x59, 0xC6, 0x8B), + MBEDTLS_BYTES_TO_T_UINT_8(0x3F, 0x58, 0xD9, 0xED, 0x58, 0x99, 0x65, 0xF7), + MBEDTLS_BYTES_TO_T_UINT_8(0x88, 0x7D, 0x26, 0x8C, 0x4A, 0xF9, 0x05, 0x9F), + MBEDTLS_BYTES_TO_T_UINT_8(0x9D, 0x73, 0x9A, 0xC9, 0xE7, 0x46, 0xDC, 0x00), +}; +static const mbedtls_mpi_uint secp256r1_T_4_Y[] = { + MBEDTLS_BYTES_TO_T_UINT_8(0xF2, 0xD0, 0x55, 0xDF, 0x00, 0x0A, 0xF5, 0x4A), + MBEDTLS_BYTES_TO_T_UINT_8(0x6A, 0xBF, 0x56, 0x81, 0x2D, 0x20, 0xEB, 0xB5), + MBEDTLS_BYTES_TO_T_UINT_8(0x11, 0xC1, 0x28, 0x52, 0xAB, 0xE3, 0xD1, 0x40), + MBEDTLS_BYTES_TO_T_UINT_8(0x24, 0x34, 0x79, 0x45, 0x57, 0xA5, 0x12, 0x03), +}; +static const mbedtls_mpi_uint secp256r1_T_5_X[] = { + MBEDTLS_BYTES_TO_T_UINT_8(0xEE, 0xCF, 0xB8, 0x7E, 0xF7, 0x92, 0x96, 0x8D), + MBEDTLS_BYTES_TO_T_UINT_8(0x3D, 0x01, 0x8C, 0x0D, 0x23, 0xF2, 0xE3, 0x05), + MBEDTLS_BYTES_TO_T_UINT_8(0x59, 0x2E, 0xE3, 0x84, 0x52, 0x7A, 0x34, 0x76), + MBEDTLS_BYTES_TO_T_UINT_8(0xE5, 0xA1, 0xB0, 0x15, 0x90, 0xE2, 0x53, 0x3C), +}; +static const mbedtls_mpi_uint secp256r1_T_5_Y[] = { + MBEDTLS_BYTES_TO_T_UINT_8(0xD4, 0x98, 0xE7, 0xFA, 0xA5, 0x7D, 0x8B, 0x53), + MBEDTLS_BYTES_TO_T_UINT_8(0x91, 0x35, 0xD2, 0x00, 0xD1, 0x1B, 0x9F, 0x1B), + MBEDTLS_BYTES_TO_T_UINT_8(0x3F, 0x69, 0x08, 0x9A, 0x72, 0xF0, 0xA9, 0x11), + MBEDTLS_BYTES_TO_T_UINT_8(0xB3, 0xFE, 0x0E, 0x14, 0xDA, 0x7C, 0x0E, 0xD3), +}; +static const mbedtls_mpi_uint secp256r1_T_6_X[] = { + MBEDTLS_BYTES_TO_T_UINT_8(0x83, 0xF6, 0xE8, 0xF8, 0x87, 0xF7, 0xFC, 0x6D), + MBEDTLS_BYTES_TO_T_UINT_8(0x90, 0xBE, 0x7F, 0x3F, 0x7A, 0x2B, 0xD7, 0x13), + MBEDTLS_BYTES_TO_T_UINT_8(0xCF, 0x32, 0xF2, 0x2D, 0x94, 0x6D, 0x42, 0xFD), + MBEDTLS_BYTES_TO_T_UINT_8(0xAD, 0x9A, 0xE3, 0x5F, 0x42, 0xBB, 0x84, 0xED), +}; +static const mbedtls_mpi_uint secp256r1_T_6_Y[] = { + MBEDTLS_BYTES_TO_T_UINT_8(0xFC, 0x95, 0x29, 0x73, 0xA1, 0x67, 0x3E, 0x02), + MBEDTLS_BYTES_TO_T_UINT_8(0xE3, 0x30, 0x54, 0x35, 0x8E, 0x0A, 0xDD, 0x67), + MBEDTLS_BYTES_TO_T_UINT_8(0x03, 0xD7, 0xA1, 0x97, 0x61, 0x3B, 0xF8, 0x0C), + MBEDTLS_BYTES_TO_T_UINT_8(0xF2, 0x33, 0x3C, 0x58, 0x55, 0x34, 0x23, 0xA3), +}; +static const mbedtls_mpi_uint secp256r1_T_7_X[] = { + MBEDTLS_BYTES_TO_T_UINT_8(0x99, 0x5D, 0x16, 0x5F, 0x7B, 0xBC, 0xBB, 0xCE), + MBEDTLS_BYTES_TO_T_UINT_8(0x61, 0xEE, 0x4E, 0x8A, 0xC1, 0x51, 0xCC, 0x50), + MBEDTLS_BYTES_TO_T_UINT_8(0x1F, 0x0D, 0x4D, 0x1B, 0x53, 0x23, 0x1D, 0xB3), + MBEDTLS_BYTES_TO_T_UINT_8(0xDA, 0x2A, 0x38, 0x66, 0x52, 0x84, 0xE1, 0x95), +}; +static const mbedtls_mpi_uint secp256r1_T_7_Y[] = { + MBEDTLS_BYTES_TO_T_UINT_8(0x5B, 0x9B, 0x83, 0x0A, 0x81, 0x4F, 0xAD, 0xAC), + MBEDTLS_BYTES_TO_T_UINT_8(0x0F, 0xFF, 0x42, 0x41, 0x6E, 0xA9, 0xA2, 0xA0), + MBEDTLS_BYTES_TO_T_UINT_8(0x2F, 0xA1, 0x4F, 0x1F, 0x89, 0x82, 0xAA, 0x3E), + MBEDTLS_BYTES_TO_T_UINT_8(0xF3, 0xB8, 0x0F, 0x6B, 0x8F, 0x8C, 0xD6, 0x68), +}; +static const mbedtls_mpi_uint secp256r1_T_8_X[] = { + MBEDTLS_BYTES_TO_T_UINT_8(0xF1, 0xB3, 0xBB, 0x51, 0x69, 0xA2, 0x11, 0x93), + MBEDTLS_BYTES_TO_T_UINT_8(0x65, 0x4F, 0x0F, 0x8D, 0xBD, 0x26, 0x0F, 0xE8), + MBEDTLS_BYTES_TO_T_UINT_8(0xB9, 0xCB, 0xEC, 0x6B, 0x34, 0xC3, 0x3D, 0x9D), + MBEDTLS_BYTES_TO_T_UINT_8(0xE4, 0x5D, 0x1E, 0x10, 0xD5, 0x44, 0xE2, 0x54), +}; +static const mbedtls_mpi_uint secp256r1_T_8_Y[] = { + MBEDTLS_BYTES_TO_T_UINT_8(0x28, 0x9E, 0xB1, 0xF1, 0x6E, 0x4C, 0xAD, 0xB3), + MBEDTLS_BYTES_TO_T_UINT_8(0xB7, 0xE3, 0xC2, 0x58, 0xC0, 0xFB, 0x34, 0x43), + MBEDTLS_BYTES_TO_T_UINT_8(0x25, 0x9C, 0xDF, 0x35, 0x07, 0x41, 0xBD, 0x19), + MBEDTLS_BYTES_TO_T_UINT_8(0xB6, 0x6E, 0x10, 0xEC, 0x0E, 0xEC, 0xBB, 0xD6), +}; +static const mbedtls_mpi_uint secp256r1_T_9_X[] = { + MBEDTLS_BYTES_TO_T_UINT_8(0xC8, 0xCF, 0xEF, 0x3F, 0x83, 0x1A, 0x88, 0xE8), + MBEDTLS_BYTES_TO_T_UINT_8(0x0B, 0x29, 0xB5, 0xB9, 0xE0, 0xC9, 0xA3, 0xAE), + MBEDTLS_BYTES_TO_T_UINT_8(0x88, 0x46, 0x1E, 0x77, 0xCD, 0x7E, 0xB3, 0x10), + MBEDTLS_BYTES_TO_T_UINT_8(0xB6, 0x21, 0xD0, 0xD4, 0xA3, 0x16, 0x08, 0xEE), +}; +static const mbedtls_mpi_uint secp256r1_T_9_Y[] = { + MBEDTLS_BYTES_TO_T_UINT_8(0xA1, 0xCA, 0xA8, 0xB3, 0xBF, 0x29, 0x99, 0x8E), + MBEDTLS_BYTES_TO_T_UINT_8(0xD1, 0xF2, 0x05, 0xC1, 0xCF, 0x5D, 0x91, 0x48), + MBEDTLS_BYTES_TO_T_UINT_8(0x9F, 0x01, 0x49, 0xDB, 0x82, 0xDF, 0x5F, 0x3A), + MBEDTLS_BYTES_TO_T_UINT_8(0xE1, 0x06, 0x90, 0xAD, 0xE3, 0x38, 0xA4, 0xC4), +}; +static const mbedtls_mpi_uint secp256r1_T_10_X[] = { + MBEDTLS_BYTES_TO_T_UINT_8(0xC9, 0xD2, 0x3A, 0xE8, 0x03, 0xC5, 0x6D, 0x5D), + MBEDTLS_BYTES_TO_T_UINT_8(0xBE, 0x35, 0xD0, 0xAE, 0x1D, 0x7A, 0x9F, 0xCA), + MBEDTLS_BYTES_TO_T_UINT_8(0x33, 0x1E, 0xD2, 0xCB, 0xAC, 0x88, 0x27, 0x55), + MBEDTLS_BYTES_TO_T_UINT_8(0xF0, 0xB9, 0x9C, 0xE0, 0x31, 0xDD, 0x99, 0x86), +}; +static const mbedtls_mpi_uint secp256r1_T_10_Y[] = { + MBEDTLS_BYTES_TO_T_UINT_8(0x61, 0xF9, 0x9B, 0x32, 0x96, 0x41, 0x58, 0x38), + MBEDTLS_BYTES_TO_T_UINT_8(0xF9, 0x5A, 0x2A, 0xB8, 0x96, 0x0E, 0xB2, 0x4C), + MBEDTLS_BYTES_TO_T_UINT_8(0xC1, 0x78, 0x2C, 0xC7, 0x08, 0x99, 0x19, 0x24), + MBEDTLS_BYTES_TO_T_UINT_8(0xB7, 0x59, 0x28, 0xE9, 0x84, 0x54, 0xE6, 0x16), +}; +static const mbedtls_mpi_uint secp256r1_T_11_X[] = { + MBEDTLS_BYTES_TO_T_UINT_8(0xDD, 0x38, 0x30, 0xDB, 0x70, 0x2C, 0x0A, 0xA2), + MBEDTLS_BYTES_TO_T_UINT_8(0x7C, 0x5C, 0x9D, 0xE9, 0xD5, 0x46, 0x0B, 0x5F), + MBEDTLS_BYTES_TO_T_UINT_8(0x83, 0x0B, 0x60, 0x4B, 0x37, 0x7D, 0xB9, 0xC9), + MBEDTLS_BYTES_TO_T_UINT_8(0x5E, 0x24, 0xF3, 0x3D, 0x79, 0x7F, 0x6C, 0x18), +}; +static const mbedtls_mpi_uint secp256r1_T_11_Y[] = { + MBEDTLS_BYTES_TO_T_UINT_8(0x7F, 0xE5, 0x1C, 0x4F, 0x60, 0x24, 0xF7, 0x2A), + MBEDTLS_BYTES_TO_T_UINT_8(0xED, 0xD8, 0xE2, 0x91, 0x7F, 0x89, 0x49, 0x92), + MBEDTLS_BYTES_TO_T_UINT_8(0x97, 0xA7, 0x2E, 0x8D, 0x6A, 0xB3, 0x39, 0x81), + MBEDTLS_BYTES_TO_T_UINT_8(0x13, 0x89, 0xB5, 0x9A, 0xB8, 0x8D, 0x42, 0x9C), +}; +static const mbedtls_mpi_uint secp256r1_T_12_X[] = { + MBEDTLS_BYTES_TO_T_UINT_8(0x8D, 0x45, 0xE6, 0x4B, 0x3F, 0x4F, 0x1E, 0x1F), + MBEDTLS_BYTES_TO_T_UINT_8(0x47, 0x65, 0x5E, 0x59, 0x22, 0xCC, 0x72, 0x5F), + MBEDTLS_BYTES_TO_T_UINT_8(0xF1, 0x93, 0x1A, 0x27, 0x1E, 0x34, 0xC5, 0x5B), + MBEDTLS_BYTES_TO_T_UINT_8(0x63, 0xF2, 0xA5, 0x58, 0x5C, 0x15, 0x2E, 0xC6), +}; +static const mbedtls_mpi_uint secp256r1_T_12_Y[] = { + MBEDTLS_BYTES_TO_T_UINT_8(0xF4, 0x7F, 0xBA, 0x58, 0x5A, 0x84, 0x6F, 0x5F), + MBEDTLS_BYTES_TO_T_UINT_8(0xAD, 0xA6, 0x36, 0x7E, 0xDC, 0xF7, 0xE1, 0x67), + MBEDTLS_BYTES_TO_T_UINT_8(0x04, 0x4D, 0xAA, 0xEE, 0x57, 0x76, 0x3A, 0xD3), + MBEDTLS_BYTES_TO_T_UINT_8(0x4E, 0x7E, 0x26, 0x18, 0x22, 0x23, 0x9F, 0xFF), +}; +static const mbedtls_mpi_uint secp256r1_T_13_X[] = { + MBEDTLS_BYTES_TO_T_UINT_8(0x1D, 0x4C, 0x64, 0xC7, 0x55, 0x02, 0x3F, 0xE3), + MBEDTLS_BYTES_TO_T_UINT_8(0xD8, 0x02, 0x90, 0xBB, 0xC3, 0xEC, 0x30, 0x40), + MBEDTLS_BYTES_TO_T_UINT_8(0x9F, 0x6F, 0x64, 0xF4, 0x16, 0x69, 0x48, 0xA4), + MBEDTLS_BYTES_TO_T_UINT_8(0xFA, 0x44, 0x9C, 0x95, 0x0C, 0x7D, 0x67, 0x5E), +}; +static const mbedtls_mpi_uint secp256r1_T_13_Y[] = { + MBEDTLS_BYTES_TO_T_UINT_8(0x44, 0x91, 0x8B, 0xD8, 0xD0, 0xD7, 0xE7, 0xE2), + MBEDTLS_BYTES_TO_T_UINT_8(0x1F, 0xF9, 0x48, 0x62, 0x6F, 0xA8, 0x93, 0x5D), + MBEDTLS_BYTES_TO_T_UINT_8(0xEA, 0x3A, 0x99, 0x02, 0xD5, 0x0B, 0x3D, 0xE3), + MBEDTLS_BYTES_TO_T_UINT_8(0x1E, 0xD3, 0x00, 0x31, 0xE6, 0x0C, 0x9F, 0x44), +}; +static const mbedtls_mpi_uint secp256r1_T_14_X[] = { + MBEDTLS_BYTES_TO_T_UINT_8(0x56, 0xB2, 0xAA, 0xFD, 0x88, 0x15, 0xDF, 0x52), + MBEDTLS_BYTES_TO_T_UINT_8(0x4C, 0x35, 0x27, 0x31, 0x44, 0xCD, 0xC0, 0x68), + MBEDTLS_BYTES_TO_T_UINT_8(0x53, 0xF8, 0x91, 0xA5, 0x71, 0x94, 0x84, 0x2A), + MBEDTLS_BYTES_TO_T_UINT_8(0x92, 0xCB, 0xD0, 0x93, 0xE9, 0x88, 0xDA, 0xE4), +}; +static const mbedtls_mpi_uint secp256r1_T_14_Y[] = { + MBEDTLS_BYTES_TO_T_UINT_8(0x24, 0xC6, 0x39, 0x16, 0x5D, 0xA3, 0x1E, 0x6D), + MBEDTLS_BYTES_TO_T_UINT_8(0xBA, 0x07, 0x37, 0x26, 0x36, 0x2A, 0xFE, 0x60), + MBEDTLS_BYTES_TO_T_UINT_8(0x51, 0xBC, 0xF3, 0xD0, 0xDE, 0x50, 0xFC, 0x97), + MBEDTLS_BYTES_TO_T_UINT_8(0x80, 0x2E, 0x06, 0x10, 0x15, 0x4D, 0xFA, 0xF7), +}; +static const mbedtls_mpi_uint secp256r1_T_15_X[] = { + MBEDTLS_BYTES_TO_T_UINT_8(0x27, 0x65, 0x69, 0x5B, 0x66, 0xA2, 0x75, 0x2E), + MBEDTLS_BYTES_TO_T_UINT_8(0x9C, 0x16, 0x00, 0x5A, 0xB0, 0x30, 0x25, 0x1A), + MBEDTLS_BYTES_TO_T_UINT_8(0x42, 0xFB, 0x86, 0x42, 0x80, 0xC1, 0xC4, 0x76), + MBEDTLS_BYTES_TO_T_UINT_8(0x5B, 0x1D, 0x83, 0x8E, 0x94, 0x01, 0x5F, 0x82), +}; +static const mbedtls_mpi_uint secp256r1_T_15_Y[] = { + MBEDTLS_BYTES_TO_T_UINT_8(0x39, 0x37, 0x70, 0xEF, 0x1F, 0xA1, 0xF0, 0xDB), + MBEDTLS_BYTES_TO_T_UINT_8(0x6A, 0x10, 0x5B, 0xCE, 0xC4, 0x9B, 0x6F, 0x10), + MBEDTLS_BYTES_TO_T_UINT_8(0x50, 0x11, 0x11, 0x24, 0x4F, 0x4C, 0x79, 0x61), + MBEDTLS_BYTES_TO_T_UINT_8(0x17, 0x3A, 0x72, 0xBC, 0xFE, 0x72, 0x58, 0x43), +}; +static const mbedtls_ecp_point secp256r1_T[16] = { + ECP_POINT_INIT_XY_Z1(secp256r1_T_0_X, secp256r1_T_0_Y), + ECP_POINT_INIT_XY_Z0(secp256r1_T_1_X, secp256r1_T_1_Y), + ECP_POINT_INIT_XY_Z0(secp256r1_T_2_X, secp256r1_T_2_Y), + ECP_POINT_INIT_XY_Z0(secp256r1_T_3_X, secp256r1_T_3_Y), + ECP_POINT_INIT_XY_Z0(secp256r1_T_4_X, secp256r1_T_4_Y), + ECP_POINT_INIT_XY_Z0(secp256r1_T_5_X, secp256r1_T_5_Y), + ECP_POINT_INIT_XY_Z0(secp256r1_T_6_X, secp256r1_T_6_Y), + ECP_POINT_INIT_XY_Z0(secp256r1_T_7_X, secp256r1_T_7_Y), + ECP_POINT_INIT_XY_Z0(secp256r1_T_8_X, secp256r1_T_8_Y), + ECP_POINT_INIT_XY_Z0(secp256r1_T_9_X, secp256r1_T_9_Y), + ECP_POINT_INIT_XY_Z0(secp256r1_T_10_X, secp256r1_T_10_Y), + ECP_POINT_INIT_XY_Z0(secp256r1_T_11_X, secp256r1_T_11_Y), + ECP_POINT_INIT_XY_Z0(secp256r1_T_12_X, secp256r1_T_12_Y), + ECP_POINT_INIT_XY_Z0(secp256r1_T_13_X, secp256r1_T_13_Y), + ECP_POINT_INIT_XY_Z0(secp256r1_T_14_X, secp256r1_T_14_Y), + ECP_POINT_INIT_XY_Z0(secp256r1_T_15_X, secp256r1_T_15_Y), +}; +#else +#define secp256r1_T NULL +#endif + #endif /* MBEDTLS_ECP_DP_SECP256R1_ENABLED */ /* @@ -195,6 +812,557 @@ static const mbedtls_mpi_uint secp384r1_n[] = { MBEDTLS_BYTES_TO_T_UINT_8(0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF), MBEDTLS_BYTES_TO_T_UINT_8(0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF), }; +#if MBEDTLS_ECP_FIXED_POINT_OPTIM == 1 +static const mbedtls_mpi_uint secp384r1_T_0_X[] = { + MBEDTLS_BYTES_TO_T_UINT_8(0xB7, 0x0A, 0x76, 0x72, 0x38, 0x5E, 0x54, 0x3A), + MBEDTLS_BYTES_TO_T_UINT_8(0x6C, 0x29, 0x55, 0xBF, 0x5D, 0xF2, 0x02, 0x55), + MBEDTLS_BYTES_TO_T_UINT_8(0x38, 0x2A, 0x54, 0x82, 0xE0, 0x41, 0xF7, 0x59), + MBEDTLS_BYTES_TO_T_UINT_8(0x98, 0x9B, 0xA7, 0x8B, 0x62, 0x3B, 0x1D, 0x6E), + MBEDTLS_BYTES_TO_T_UINT_8(0x74, 0xAD, 0x20, 0xF3, 0x1E, 0xC7, 0xB1, 0x8E), + MBEDTLS_BYTES_TO_T_UINT_8(0x37, 0x05, 0x8B, 0xBE, 0x22, 0xCA, 0x87, 0xAA), +}; +static const mbedtls_mpi_uint secp384r1_T_0_Y[] = { + MBEDTLS_BYTES_TO_T_UINT_8(0x5F, 0x0E, 0xEA, 0x90, 0x7C, 0x1D, 0x43, 0x7A), + MBEDTLS_BYTES_TO_T_UINT_8(0x9D, 0x81, 0x7E, 0x1D, 0xCE, 0xB1, 0x60, 0x0A), + MBEDTLS_BYTES_TO_T_UINT_8(0xC0, 0xB8, 0xF0, 0xB5, 0x13, 0x31, 0xDA, 0xE9), + MBEDTLS_BYTES_TO_T_UINT_8(0x7C, 0x14, 0x9A, 0x28, 0xBD, 0x1D, 0xF4, 0xF8), + MBEDTLS_BYTES_TO_T_UINT_8(0x29, 0xDC, 0x92, 0x92, 0xBF, 0x98, 0x9E, 0x5D), + MBEDTLS_BYTES_TO_T_UINT_8(0x6F, 0x2C, 0x26, 0x96, 0x4A, 0xDE, 0x17, 0x36), +}; +static const mbedtls_mpi_uint secp384r1_T_1_X[] = { + MBEDTLS_BYTES_TO_T_UINT_8(0x46, 0x92, 0x00, 0x2C, 0x78, 0xDB, 0x1F, 0x37), + MBEDTLS_BYTES_TO_T_UINT_8(0x17, 0xF3, 0xEB, 0xB7, 0x06, 0xF7, 0xB6, 0xBC), + MBEDTLS_BYTES_TO_T_UINT_8(0x3D, 0xBC, 0x2C, 0xCF, 0xD8, 0xED, 0x53, 0xE7), + MBEDTLS_BYTES_TO_T_UINT_8(0x52, 0x75, 0x7B, 0xA3, 0xAB, 0xC3, 0x2C, 0x85), + MBEDTLS_BYTES_TO_T_UINT_8(0xE5, 0x9D, 0x78, 0x41, 0xF6, 0x76, 0x84, 0xAC), + MBEDTLS_BYTES_TO_T_UINT_8(0x54, 0x56, 0xE8, 0x52, 0xB3, 0xCB, 0xA8, 0xBD), +}; +static const mbedtls_mpi_uint secp384r1_T_1_Y[] = { + MBEDTLS_BYTES_TO_T_UINT_8(0x6D, 0xF2, 0xAE, 0xA4, 0xB6, 0x89, 0x1B, 0xDA), + MBEDTLS_BYTES_TO_T_UINT_8(0x01, 0x0F, 0xCE, 0x1C, 0x7C, 0xF6, 0x50, 0x4C), + MBEDTLS_BYTES_TO_T_UINT_8(0x4C, 0xEB, 0x90, 0xE6, 0x4D, 0xC7, 0xD4, 0x7A), + MBEDTLS_BYTES_TO_T_UINT_8(0xD1, 0x49, 0x2D, 0x8A, 0x01, 0x99, 0x60, 0x94), + MBEDTLS_BYTES_TO_T_UINT_8(0x5F, 0x80, 0x9B, 0x9B, 0x6A, 0xB0, 0x07, 0xD9), + MBEDTLS_BYTES_TO_T_UINT_8(0xC2, 0xA2, 0xEE, 0x59, 0xBE, 0x95, 0xBC, 0x23), +}; +static const mbedtls_mpi_uint secp384r1_T_2_X[] = { + MBEDTLS_BYTES_TO_T_UINT_8(0xE6, 0x9D, 0x56, 0xAE, 0x59, 0xFB, 0x1F, 0x98), + MBEDTLS_BYTES_TO_T_UINT_8(0xCF, 0xAC, 0x91, 0x80, 0x87, 0xA8, 0x6E, 0x58), + MBEDTLS_BYTES_TO_T_UINT_8(0x30, 0x08, 0xA7, 0x08, 0x94, 0x32, 0xFC, 0x67), + MBEDTLS_BYTES_TO_T_UINT_8(0x9F, 0x29, 0x9E, 0x84, 0xF4, 0xE5, 0x6E, 0x7E), + MBEDTLS_BYTES_TO_T_UINT_8(0x55, 0x21, 0xB9, 0x50, 0x24, 0xF8, 0x9C, 0xC7), + MBEDTLS_BYTES_TO_T_UINT_8(0x34, 0x04, 0x01, 0xC2, 0xFB, 0x77, 0x3E, 0xDE), +}; +static const mbedtls_mpi_uint secp384r1_T_2_Y[] = { + MBEDTLS_BYTES_TO_T_UINT_8(0x00, 0x38, 0xEE, 0xE3, 0xC7, 0x9D, 0xEC, 0xA6), + MBEDTLS_BYTES_TO_T_UINT_8(0xB6, 0x88, 0xCF, 0x43, 0xFA, 0x92, 0x5E, 0x8E), + MBEDTLS_BYTES_TO_T_UINT_8(0xE9, 0xCA, 0x43, 0xF8, 0x3B, 0x49, 0x7E, 0x75), + MBEDTLS_BYTES_TO_T_UINT_8(0x1C, 0xE7, 0xEB, 0x17, 0x45, 0x86, 0xC2, 0xE1), + MBEDTLS_BYTES_TO_T_UINT_8(0x92, 0x69, 0x57, 0x32, 0xE0, 0x9C, 0xD1, 0x00), + MBEDTLS_BYTES_TO_T_UINT_8(0xD9, 0x10, 0xB8, 0x4D, 0xB8, 0xF4, 0x0D, 0xE3), +}; +static const mbedtls_mpi_uint secp384r1_T_3_X[] = { + MBEDTLS_BYTES_TO_T_UINT_8(0x60, 0xDC, 0x9A, 0xB2, 0x79, 0x39, 0x27, 0x16), + MBEDTLS_BYTES_TO_T_UINT_8(0x4F, 0x71, 0xE4, 0x3B, 0x4D, 0x60, 0x0C, 0xA3), + MBEDTLS_BYTES_TO_T_UINT_8(0x55, 0xBD, 0x19, 0x40, 0xFA, 0x19, 0x2A, 0x5A), + MBEDTLS_BYTES_TO_T_UINT_8(0x4D, 0xF8, 0x1E, 0x43, 0xA1, 0x50, 0x8D, 0xEF), + MBEDTLS_BYTES_TO_T_UINT_8(0xA3, 0x18, 0x7C, 0x41, 0xFA, 0x7C, 0x1B, 0x58), + MBEDTLS_BYTES_TO_T_UINT_8(0x00, 0x59, 0x24, 0xC4, 0xE9, 0xB7, 0xD3, 0xAD), +}; +static const mbedtls_mpi_uint secp384r1_T_3_Y[] = { + MBEDTLS_BYTES_TO_T_UINT_8(0xBB, 0x01, 0x3D, 0x63, 0x54, 0x45, 0x6F, 0xB7), + MBEDTLS_BYTES_TO_T_UINT_8(0x7B, 0xB2, 0x19, 0xA3, 0x86, 0x1D, 0x42, 0x34), + MBEDTLS_BYTES_TO_T_UINT_8(0x84, 0x02, 0x87, 0x18, 0x92, 0x52, 0x1A, 0x71), + MBEDTLS_BYTES_TO_T_UINT_8(0x6C, 0x18, 0xB1, 0x5D, 0x18, 0x1B, 0x37, 0xFE), + MBEDTLS_BYTES_TO_T_UINT_8(0xF4, 0x74, 0x61, 0xBA, 0x18, 0xAF, 0x40, 0x30), + MBEDTLS_BYTES_TO_T_UINT_8(0xDA, 0x7D, 0x3C, 0x52, 0x0F, 0x07, 0xB0, 0x6F), +}; +static const mbedtls_mpi_uint secp384r1_T_4_X[] = { + MBEDTLS_BYTES_TO_T_UINT_8(0x09, 0x39, 0x13, 0xAA, 0x60, 0x15, 0x99, 0x30), + MBEDTLS_BYTES_TO_T_UINT_8(0x17, 0x00, 0xCB, 0xC6, 0xB1, 0xDB, 0x97, 0x90), + MBEDTLS_BYTES_TO_T_UINT_8(0xE6, 0xFA, 0x60, 0xB8, 0x24, 0xE4, 0x7D, 0xD3), + MBEDTLS_BYTES_TO_T_UINT_8(0xDD, 0x75, 0xB3, 0x70, 0xB2, 0x83, 0xB1, 0x9B), + MBEDTLS_BYTES_TO_T_UINT_8(0xA3, 0xE3, 0x6C, 0xCD, 0x33, 0x62, 0x7A, 0x56), + MBEDTLS_BYTES_TO_T_UINT_8(0x88, 0x30, 0xDC, 0x0F, 0x9F, 0xBB, 0xB8, 0xAA), +}; +static const mbedtls_mpi_uint secp384r1_T_4_Y[] = { + MBEDTLS_BYTES_TO_T_UINT_8(0xA6, 0xD5, 0x0A, 0x60, 0x81, 0xB9, 0xC5, 0x16), + MBEDTLS_BYTES_TO_T_UINT_8(0x44, 0xAA, 0x2F, 0xD6, 0xF2, 0x73, 0xDF, 0xEB), + MBEDTLS_BYTES_TO_T_UINT_8(0xF3, 0x7B, 0x74, 0xC9, 0xB3, 0x5B, 0x95, 0x6D), + MBEDTLS_BYTES_TO_T_UINT_8(0xAC, 0x04, 0xEB, 0x15, 0xC8, 0x5F, 0x00, 0xF6), + MBEDTLS_BYTES_TO_T_UINT_8(0xB5, 0x50, 0x20, 0x28, 0xD1, 0x01, 0xAF, 0xF0), + MBEDTLS_BYTES_TO_T_UINT_8(0x28, 0x6D, 0x4F, 0x31, 0x81, 0x2F, 0x94, 0x48), +}; +static const mbedtls_mpi_uint secp384r1_T_5_X[] = { + MBEDTLS_BYTES_TO_T_UINT_8(0x46, 0x2F, 0xD8, 0xB6, 0x63, 0x7C, 0xE9, 0x50), + MBEDTLS_BYTES_TO_T_UINT_8(0xD9, 0x8C, 0xB9, 0x14, 0xD9, 0x37, 0x63, 0xDE), + MBEDTLS_BYTES_TO_T_UINT_8(0x10, 0x02, 0xB8, 0x46, 0xAD, 0xCE, 0x7B, 0x38), + MBEDTLS_BYTES_TO_T_UINT_8(0x82, 0x47, 0x2D, 0x66, 0xA7, 0xE9, 0x33, 0x23), + MBEDTLS_BYTES_TO_T_UINT_8(0x92, 0xF9, 0x93, 0x94, 0xA8, 0x48, 0xB3, 0x4F), + MBEDTLS_BYTES_TO_T_UINT_8(0xE9, 0x4A, 0xAC, 0x51, 0x08, 0x72, 0x2F, 0x1A), +}; +static const mbedtls_mpi_uint secp384r1_T_5_Y[] = { + MBEDTLS_BYTES_TO_T_UINT_8(0xDA, 0xAD, 0xA0, 0xF9, 0x81, 0xE1, 0x78, 0x97), + MBEDTLS_BYTES_TO_T_UINT_8(0x3A, 0x9A, 0x63, 0xD8, 0xBA, 0x79, 0x1A, 0x17), + MBEDTLS_BYTES_TO_T_UINT_8(0x34, 0x31, 0x7B, 0x7A, 0x5A, 0x5D, 0x7D, 0x2D), + MBEDTLS_BYTES_TO_T_UINT_8(0x83, 0x96, 0x12, 0x4B, 0x19, 0x09, 0xE0, 0xB7), + MBEDTLS_BYTES_TO_T_UINT_8(0x55, 0x8A, 0x57, 0xEE, 0x4E, 0x6E, 0x7E, 0xEC), + MBEDTLS_BYTES_TO_T_UINT_8(0x11, 0x9D, 0x69, 0xDC, 0xB3, 0xDA, 0xD8, 0x08), +}; +static const mbedtls_mpi_uint secp384r1_T_6_X[] = { + MBEDTLS_BYTES_TO_T_UINT_8(0x68, 0x49, 0x03, 0x03, 0x33, 0x6F, 0x28, 0x4A), + MBEDTLS_BYTES_TO_T_UINT_8(0x5D, 0xDB, 0xA7, 0x05, 0x8C, 0xF3, 0x4D, 0xFB), + MBEDTLS_BYTES_TO_T_UINT_8(0x8E, 0x92, 0xB1, 0xA8, 0xEC, 0x0D, 0x64, 0x3B), + MBEDTLS_BYTES_TO_T_UINT_8(0x4E, 0xFC, 0xFD, 0xD0, 0x4B, 0x88, 0x1B, 0x5D), + MBEDTLS_BYTES_TO_T_UINT_8(0x83, 0x9C, 0x51, 0x69, 0xCE, 0x71, 0x73, 0xF5), + MBEDTLS_BYTES_TO_T_UINT_8(0xB8, 0x5A, 0x14, 0x23, 0x1A, 0x46, 0x63, 0x5F), +}; +static const mbedtls_mpi_uint secp384r1_T_6_Y[] = { + MBEDTLS_BYTES_TO_T_UINT_8(0xBC, 0x4C, 0x70, 0x44, 0x18, 0xCD, 0xEF, 0xED), + MBEDTLS_BYTES_TO_T_UINT_8(0xC2, 0x49, 0xDD, 0x64, 0x7E, 0x7E, 0x4D, 0x92), + MBEDTLS_BYTES_TO_T_UINT_8(0xA2, 0x32, 0x7C, 0x09, 0xD0, 0x3F, 0xD6, 0x2C), + MBEDTLS_BYTES_TO_T_UINT_8(0x6D, 0xE0, 0x4F, 0x65, 0x0C, 0x7A, 0x54, 0x3E), + MBEDTLS_BYTES_TO_T_UINT_8(0x16, 0xFA, 0xFB, 0x4A, 0xB4, 0x79, 0x5A, 0x8C), + MBEDTLS_BYTES_TO_T_UINT_8(0x04, 0x5D, 0x1B, 0x2B, 0xDA, 0xBC, 0x9A, 0x74), +}; +static const mbedtls_mpi_uint secp384r1_T_7_X[] = { + MBEDTLS_BYTES_TO_T_UINT_8(0x51, 0xAC, 0x56, 0xF7, 0x5F, 0x51, 0x68, 0x0B), + MBEDTLS_BYTES_TO_T_UINT_8(0xC6, 0xE0, 0x1D, 0xBC, 0x13, 0x4E, 0xAC, 0x03), + MBEDTLS_BYTES_TO_T_UINT_8(0xB7, 0xF5, 0xC5, 0xE6, 0xD2, 0x88, 0xBA, 0xCB), + MBEDTLS_BYTES_TO_T_UINT_8(0xFA, 0x0E, 0x28, 0x23, 0x58, 0x67, 0xFA, 0xEE), + MBEDTLS_BYTES_TO_T_UINT_8(0x9E, 0x80, 0x4B, 0xD8, 0xC4, 0xDF, 0x15, 0xE4), + MBEDTLS_BYTES_TO_T_UINT_8(0xF1, 0x0E, 0x58, 0xE6, 0x2C, 0x59, 0xC2, 0x03), +}; +static const mbedtls_mpi_uint secp384r1_T_7_Y[] = { + MBEDTLS_BYTES_TO_T_UINT_8(0x9B, 0x26, 0x27, 0x99, 0x16, 0x2B, 0x22, 0x0B), + MBEDTLS_BYTES_TO_T_UINT_8(0xBA, 0xF3, 0x8F, 0xC3, 0x2A, 0x9B, 0xFC, 0x38), + MBEDTLS_BYTES_TO_T_UINT_8(0xFC, 0x2E, 0x83, 0x3D, 0xFE, 0x9E, 0x3C, 0x1B), + MBEDTLS_BYTES_TO_T_UINT_8(0x08, 0x57, 0xCD, 0x2D, 0xC1, 0x49, 0x38, 0xB5), + MBEDTLS_BYTES_TO_T_UINT_8(0x95, 0x42, 0x8B, 0x33, 0x89, 0x1F, 0xEA, 0x01), + MBEDTLS_BYTES_TO_T_UINT_8(0xAA, 0x1D, 0x13, 0xD7, 0x50, 0xBB, 0x3E, 0xEB), +}; +static const mbedtls_mpi_uint secp384r1_T_8_X[] = { + MBEDTLS_BYTES_TO_T_UINT_8(0xD2, 0x9A, 0x52, 0xD2, 0x54, 0x7C, 0x97, 0xF2), + MBEDTLS_BYTES_TO_T_UINT_8(0xE0, 0x33, 0x6E, 0xED, 0xD9, 0x87, 0x50, 0xC5), + MBEDTLS_BYTES_TO_T_UINT_8(0x5A, 0x35, 0x7E, 0x16, 0x40, 0x15, 0x83, 0xB8), + MBEDTLS_BYTES_TO_T_UINT_8(0x33, 0x2B, 0xA4, 0xAB, 0x03, 0x91, 0xEA, 0xFE), + MBEDTLS_BYTES_TO_T_UINT_8(0xC1, 0x47, 0x39, 0xEF, 0x05, 0x59, 0xD0, 0x90), + MBEDTLS_BYTES_TO_T_UINT_8(0xBF, 0x24, 0x0D, 0x76, 0x11, 0x53, 0x08, 0xAF), +}; +static const mbedtls_mpi_uint secp384r1_T_8_Y[] = { + MBEDTLS_BYTES_TO_T_UINT_8(0x1F, 0x2F, 0xDD, 0xBD, 0x50, 0x48, 0xB1, 0xE5), + MBEDTLS_BYTES_TO_T_UINT_8(0x80, 0x1C, 0x84, 0x55, 0x78, 0x14, 0xEB, 0xF6), + MBEDTLS_BYTES_TO_T_UINT_8(0xD9, 0x5E, 0x3E, 0xA6, 0xAF, 0xF6, 0xC7, 0x04), + MBEDTLS_BYTES_TO_T_UINT_8(0xE7, 0x11, 0xE2, 0x65, 0xCA, 0x41, 0x95, 0x3B), + MBEDTLS_BYTES_TO_T_UINT_8(0xAE, 0x83, 0xD8, 0xE6, 0x4D, 0x22, 0x06, 0x2D), + MBEDTLS_BYTES_TO_T_UINT_8(0xFA, 0x7F, 0x25, 0x2A, 0xAA, 0x28, 0x46, 0x97), +}; +static const mbedtls_mpi_uint secp384r1_T_9_X[] = { + MBEDTLS_BYTES_TO_T_UINT_8(0x79, 0xDB, 0x15, 0x56, 0x84, 0xCB, 0xC0, 0x56), + MBEDTLS_BYTES_TO_T_UINT_8(0x56, 0xDB, 0x0E, 0x08, 0xC9, 0xF5, 0xD4, 0x9E), + MBEDTLS_BYTES_TO_T_UINT_8(0xE6, 0x62, 0xD0, 0x1A, 0x7C, 0x13, 0xD5, 0x07), + MBEDTLS_BYTES_TO_T_UINT_8(0x7D, 0xAD, 0x53, 0xE0, 0x32, 0x21, 0xA0, 0xC0), + MBEDTLS_BYTES_TO_T_UINT_8(0xC5, 0x38, 0x81, 0x21, 0x23, 0x0E, 0xD2, 0xBB), + MBEDTLS_BYTES_TO_T_UINT_8(0x1C, 0x51, 0x05, 0xD0, 0x1E, 0x82, 0xA9, 0x71), +}; +static const mbedtls_mpi_uint secp384r1_T_9_Y[] = { + MBEDTLS_BYTES_TO_T_UINT_8(0xA7, 0xC3, 0x27, 0xBF, 0xC6, 0xAA, 0xB7, 0xB9), + MBEDTLS_BYTES_TO_T_UINT_8(0xCB, 0x65, 0x45, 0xDF, 0xB9, 0x46, 0x17, 0x46), + MBEDTLS_BYTES_TO_T_UINT_8(0xF5, 0x38, 0x3F, 0xB2, 0xB1, 0x5D, 0xCA, 0x1C), + MBEDTLS_BYTES_TO_T_UINT_8(0x88, 0x29, 0x6C, 0x63, 0xE9, 0xD7, 0x48, 0xB8), + MBEDTLS_BYTES_TO_T_UINT_8(0xBC, 0xF1, 0xD7, 0x99, 0x8C, 0xC2, 0x05, 0x99), + MBEDTLS_BYTES_TO_T_UINT_8(0x6D, 0xE6, 0x5E, 0x82, 0x6D, 0xE5, 0x7E, 0xD5), +}; +static const mbedtls_mpi_uint secp384r1_T_10_X[] = { + MBEDTLS_BYTES_TO_T_UINT_8(0x7B, 0x61, 0xFA, 0x7D, 0x01, 0xDB, 0xB6, 0x63), + MBEDTLS_BYTES_TO_T_UINT_8(0x11, 0xC6, 0x58, 0x39, 0xF4, 0xC6, 0x82, 0x23), + MBEDTLS_BYTES_TO_T_UINT_8(0x47, 0x5A, 0x7A, 0x80, 0x08, 0xCD, 0xAA, 0xD8), + MBEDTLS_BYTES_TO_T_UINT_8(0xDA, 0x8C, 0xC6, 0x3F, 0x3C, 0xA5, 0x68, 0xF4), + MBEDTLS_BYTES_TO_T_UINT_8(0xBB, 0xF5, 0xD5, 0x17, 0xAE, 0x36, 0xD8, 0x8A), + MBEDTLS_BYTES_TO_T_UINT_8(0xC7, 0xAD, 0x92, 0xC5, 0x57, 0x6C, 0xDA, 0x91), +}; +static const mbedtls_mpi_uint secp384r1_T_10_Y[] = { + MBEDTLS_BYTES_TO_T_UINT_8(0xE8, 0x67, 0x17, 0xC0, 0x40, 0x78, 0x8C, 0x84), + MBEDTLS_BYTES_TO_T_UINT_8(0x7E, 0x9F, 0xF4, 0xAA, 0xDA, 0x5C, 0x7E, 0xB2), + MBEDTLS_BYTES_TO_T_UINT_8(0x96, 0xDB, 0x42, 0x3E, 0x72, 0x64, 0xA0, 0x67), + MBEDTLS_BYTES_TO_T_UINT_8(0x27, 0xF9, 0x41, 0x17, 0x43, 0xE3, 0xE8, 0xA8), + MBEDTLS_BYTES_TO_T_UINT_8(0x66, 0xDD, 0xCC, 0x43, 0x7E, 0x16, 0x05, 0x03), + MBEDTLS_BYTES_TO_T_UINT_8(0x36, 0x4B, 0xCF, 0x48, 0x8F, 0x41, 0x90, 0xE5), +}; +static const mbedtls_mpi_uint secp384r1_T_11_X[] = { + MBEDTLS_BYTES_TO_T_UINT_8(0x98, 0x0C, 0x6B, 0x9D, 0x22, 0x04, 0xBC, 0x5C), + MBEDTLS_BYTES_TO_T_UINT_8(0x86, 0x63, 0x79, 0x2F, 0x6A, 0x0E, 0x8A, 0xDE), + MBEDTLS_BYTES_TO_T_UINT_8(0x29, 0x67, 0x3F, 0x02, 0xB8, 0x91, 0x7F, 0x74), + MBEDTLS_BYTES_TO_T_UINT_8(0xFC, 0x14, 0x64, 0xA0, 0x33, 0xF4, 0x6B, 0x50), + MBEDTLS_BYTES_TO_T_UINT_8(0x1C, 0x44, 0x71, 0x87, 0xB8, 0x88, 0x3F, 0x45), + MBEDTLS_BYTES_TO_T_UINT_8(0x1B, 0x2B, 0x85, 0x05, 0xC5, 0x44, 0x53, 0x15), +}; +static const mbedtls_mpi_uint secp384r1_T_11_Y[] = { + MBEDTLS_BYTES_TO_T_UINT_8(0x3E, 0x2B, 0xFE, 0xD1, 0x1C, 0x73, 0xE3, 0x2E), + MBEDTLS_BYTES_TO_T_UINT_8(0x66, 0x33, 0xA1, 0xD3, 0x69, 0x1C, 0x9D, 0xD2), + MBEDTLS_BYTES_TO_T_UINT_8(0xE0, 0x5A, 0xBA, 0xB6, 0xAE, 0x1B, 0x94, 0x04), + MBEDTLS_BYTES_TO_T_UINT_8(0xAF, 0x74, 0x90, 0x5C, 0x57, 0xB0, 0x3A, 0x45), + MBEDTLS_BYTES_TO_T_UINT_8(0xDD, 0x2F, 0x93, 0x20, 0x24, 0x54, 0x1D, 0x8D), + MBEDTLS_BYTES_TO_T_UINT_8(0xFA, 0x78, 0x9D, 0x71, 0x67, 0x5D, 0x49, 0x98), +}; +static const mbedtls_mpi_uint secp384r1_T_12_X[] = { + MBEDTLS_BYTES_TO_T_UINT_8(0x12, 0xC8, 0x0E, 0x11, 0x8D, 0xE0, 0x8F, 0x69), + MBEDTLS_BYTES_TO_T_UINT_8(0x59, 0x7F, 0x79, 0x6C, 0x5F, 0xB7, 0xBC, 0xB1), + MBEDTLS_BYTES_TO_T_UINT_8(0x88, 0xE1, 0x83, 0x3C, 0x12, 0xBB, 0xEE, 0x96), + MBEDTLS_BYTES_TO_T_UINT_8(0x2A, 0xC2, 0xC4, 0x1B, 0x41, 0x71, 0xB9, 0x17), + MBEDTLS_BYTES_TO_T_UINT_8(0xB0, 0xEE, 0xBB, 0x1D, 0x89, 0x50, 0x88, 0xF2), + MBEDTLS_BYTES_TO_T_UINT_8(0xFC, 0x1C, 0x55, 0x74, 0xEB, 0xDE, 0x92, 0x3F), +}; +static const mbedtls_mpi_uint secp384r1_T_12_Y[] = { + MBEDTLS_BYTES_TO_T_UINT_8(0x9C, 0x38, 0x92, 0x06, 0x19, 0xD0, 0xB3, 0xB2), + MBEDTLS_BYTES_TO_T_UINT_8(0x2A, 0x99, 0x26, 0xA3, 0x5F, 0xE2, 0xC1, 0x81), + MBEDTLS_BYTES_TO_T_UINT_8(0x75, 0xFC, 0xFD, 0xC3, 0xB6, 0x26, 0x24, 0x8F), + MBEDTLS_BYTES_TO_T_UINT_8(0xAF, 0xAD, 0xE7, 0x49, 0xB7, 0x64, 0x4B, 0x96), + MBEDTLS_BYTES_TO_T_UINT_8(0x6C, 0x4E, 0x95, 0xAD, 0x07, 0xFE, 0xB6, 0x30), + MBEDTLS_BYTES_TO_T_UINT_8(0x4F, 0x15, 0xE7, 0x2D, 0x19, 0xA9, 0x08, 0x10), +}; +static const mbedtls_mpi_uint secp384r1_T_13_X[] = { + MBEDTLS_BYTES_TO_T_UINT_8(0xBE, 0xBD, 0xAC, 0x0A, 0x3F, 0x6B, 0xFF, 0xFA), + MBEDTLS_BYTES_TO_T_UINT_8(0xE0, 0xE4, 0x74, 0x14, 0xD9, 0x70, 0x1D, 0x71), + MBEDTLS_BYTES_TO_T_UINT_8(0xF2, 0xB0, 0x71, 0xBB, 0xD8, 0x18, 0x96, 0x2B), + MBEDTLS_BYTES_TO_T_UINT_8(0xDA, 0xB8, 0x19, 0x90, 0x80, 0xB5, 0xEE, 0x01), + MBEDTLS_BYTES_TO_T_UINT_8(0x91, 0x21, 0x20, 0xA6, 0x17, 0x48, 0x03, 0x6F), + MBEDTLS_BYTES_TO_T_UINT_8(0xE3, 0x1D, 0xBB, 0x6D, 0x94, 0x20, 0x34, 0xF1), +}; +static const mbedtls_mpi_uint secp384r1_T_13_Y[] = { + MBEDTLS_BYTES_TO_T_UINT_8(0x59, 0x82, 0x67, 0x4B, 0x8E, 0x4E, 0xBE, 0xE2), + MBEDTLS_BYTES_TO_T_UINT_8(0xBE, 0xDA, 0x77, 0xF8, 0x23, 0x55, 0x2B, 0x2D), + MBEDTLS_BYTES_TO_T_UINT_8(0x5C, 0x02, 0xDE, 0x25, 0x35, 0x2D, 0x74, 0x51), + MBEDTLS_BYTES_TO_T_UINT_8(0xD0, 0x0C, 0xB8, 0x0B, 0x39, 0xBA, 0xAD, 0x04), + MBEDTLS_BYTES_TO_T_UINT_8(0xA6, 0x0E, 0x28, 0x4D, 0xE1, 0x3D, 0xE4, 0x1B), + MBEDTLS_BYTES_TO_T_UINT_8(0x5D, 0xEC, 0x0A, 0xD4, 0xB8, 0xC4, 0x8D, 0xB0), +}; +static const mbedtls_mpi_uint secp384r1_T_14_X[] = { + MBEDTLS_BYTES_TO_T_UINT_8(0x3E, 0x68, 0xCE, 0xC2, 0x55, 0x4D, 0x0C, 0x6D), + MBEDTLS_BYTES_TO_T_UINT_8(0x9B, 0x20, 0x93, 0x32, 0x90, 0xD6, 0xAE, 0x47), + MBEDTLS_BYTES_TO_T_UINT_8(0xDD, 0x78, 0xAB, 0x43, 0x9E, 0xEB, 0x73, 0xAE), + MBEDTLS_BYTES_TO_T_UINT_8(0xED, 0x97, 0xC3, 0x83, 0xA6, 0x3C, 0xF1, 0xBF), + MBEDTLS_BYTES_TO_T_UINT_8(0x0F, 0x25, 0x25, 0x66, 0x08, 0x26, 0xFA, 0x4B), + MBEDTLS_BYTES_TO_T_UINT_8(0x41, 0xFB, 0x44, 0x5D, 0x82, 0xEC, 0x3B, 0xAC), +}; +static const mbedtls_mpi_uint secp384r1_T_14_Y[] = { + MBEDTLS_BYTES_TO_T_UINT_8(0x58, 0x90, 0xEA, 0xB5, 0x04, 0x99, 0xD0, 0x69), + MBEDTLS_BYTES_TO_T_UINT_8(0x4A, 0xF2, 0x22, 0xA0, 0xEB, 0xFD, 0x45, 0x87), + MBEDTLS_BYTES_TO_T_UINT_8(0x5D, 0xA4, 0x81, 0x32, 0xFC, 0xFA, 0xEE, 0x5B), + MBEDTLS_BYTES_TO_T_UINT_8(0x27, 0xBB, 0xA4, 0x6A, 0x77, 0x41, 0x5C, 0x1D), + MBEDTLS_BYTES_TO_T_UINT_8(0xA1, 0x1E, 0xAA, 0x4F, 0xF0, 0x10, 0xB3, 0x50), + MBEDTLS_BYTES_TO_T_UINT_8(0x09, 0x74, 0x13, 0x14, 0x9E, 0x90, 0xD7, 0xE6), +}; +static const mbedtls_mpi_uint secp384r1_T_15_X[] = { + MBEDTLS_BYTES_TO_T_UINT_8(0xDB, 0xBD, 0x70, 0x4F, 0xA8, 0xD1, 0x06, 0x2C), + MBEDTLS_BYTES_TO_T_UINT_8(0x19, 0x4E, 0x2E, 0x68, 0xFC, 0x35, 0xFA, 0x50), + MBEDTLS_BYTES_TO_T_UINT_8(0x60, 0x53, 0x75, 0xED, 0xF2, 0x5F, 0xC2, 0xEB), + MBEDTLS_BYTES_TO_T_UINT_8(0x39, 0x87, 0x6B, 0x9F, 0x05, 0xE2, 0x22, 0x93), + MBEDTLS_BYTES_TO_T_UINT_8(0x4F, 0x1A, 0xA8, 0xB7, 0x03, 0x9E, 0x6D, 0x7C), + MBEDTLS_BYTES_TO_T_UINT_8(0xCB, 0xD0, 0x69, 0x88, 0xA8, 0x39, 0x9E, 0x3A), +}; +static const mbedtls_mpi_uint secp384r1_T_15_Y[] = { + MBEDTLS_BYTES_TO_T_UINT_8(0xF8, 0xEF, 0x68, 0xFE, 0xEC, 0x24, 0x08, 0x15), + MBEDTLS_BYTES_TO_T_UINT_8(0xA1, 0x06, 0x4B, 0x92, 0x0D, 0xB7, 0x34, 0x74), + MBEDTLS_BYTES_TO_T_UINT_8(0x3E, 0xF4, 0xDD, 0x1A, 0xA0, 0x4A, 0xE4, 0x45), + MBEDTLS_BYTES_TO_T_UINT_8(0xC3, 0x63, 0x4F, 0x4F, 0xCE, 0xBB, 0xD6, 0xD3), + MBEDTLS_BYTES_TO_T_UINT_8(0xCD, 0xEE, 0x8D, 0xDF, 0x3F, 0x73, 0xB7, 0xAC), + MBEDTLS_BYTES_TO_T_UINT_8(0xDF, 0x06, 0xB6, 0x80, 0x4D, 0x81, 0xD9, 0x53), +}; +static const mbedtls_mpi_uint secp384r1_T_16_X[] = { + MBEDTLS_BYTES_TO_T_UINT_8(0x15, 0xF5, 0x13, 0xDF, 0x13, 0x19, 0x97, 0x94), + MBEDTLS_BYTES_TO_T_UINT_8(0x08, 0xF9, 0xB3, 0x33, 0x66, 0x82, 0x21, 0xFE), + MBEDTLS_BYTES_TO_T_UINT_8(0xF5, 0xFC, 0x39, 0x16, 0x23, 0x43, 0x76, 0x0E), + MBEDTLS_BYTES_TO_T_UINT_8(0x09, 0x48, 0x25, 0xA1, 0x64, 0x95, 0x1C, 0x2F), + MBEDTLS_BYTES_TO_T_UINT_8(0x43, 0xAC, 0x15, 0x57, 0xD9, 0xDE, 0xA0, 0x28), + MBEDTLS_BYTES_TO_T_UINT_8(0x16, 0x5F, 0xB8, 0x3D, 0x48, 0x91, 0x24, 0xCC), +}; +static const mbedtls_mpi_uint secp384r1_T_16_Y[] = { + MBEDTLS_BYTES_TO_T_UINT_8(0x2D, 0xF2, 0xC8, 0x54, 0xD1, 0x32, 0xBD, 0xC4), + MBEDTLS_BYTES_TO_T_UINT_8(0x8A, 0x3B, 0xF0, 0xAA, 0x9D, 0xD8, 0xF4, 0x20), + MBEDTLS_BYTES_TO_T_UINT_8(0x4F, 0xC3, 0xBB, 0x6C, 0x66, 0xAC, 0x25, 0x2D), + MBEDTLS_BYTES_TO_T_UINT_8(0x6F, 0x25, 0x10, 0xB2, 0xE1, 0x41, 0xDE, 0x1D), + MBEDTLS_BYTES_TO_T_UINT_8(0x3C, 0xE8, 0x30, 0xB8, 0x37, 0xBC, 0x2A, 0x98), + MBEDTLS_BYTES_TO_T_UINT_8(0xBA, 0x57, 0x01, 0x4A, 0x1E, 0x78, 0x9F, 0x85), +}; +static const mbedtls_mpi_uint secp384r1_T_17_X[] = { + MBEDTLS_BYTES_TO_T_UINT_8(0xBD, 0x19, 0xCD, 0x12, 0x0B, 0x51, 0x4F, 0x56), + MBEDTLS_BYTES_TO_T_UINT_8(0x30, 0x4B, 0x3D, 0x24, 0xA4, 0x16, 0x59, 0x05), + MBEDTLS_BYTES_TO_T_UINT_8(0xAC, 0xEB, 0xD3, 0x59, 0x2E, 0x75, 0x7C, 0x01), + MBEDTLS_BYTES_TO_T_UINT_8(0x8C, 0xB9, 0xB4, 0xA5, 0xD9, 0x2E, 0x29, 0x4C), + MBEDTLS_BYTES_TO_T_UINT_8(0x86, 0x16, 0x05, 0x75, 0x02, 0xB3, 0x06, 0xEE), + MBEDTLS_BYTES_TO_T_UINT_8(0xAB, 0x7C, 0x9F, 0x79, 0x91, 0xF1, 0x4F, 0x23), +}; +static const mbedtls_mpi_uint secp384r1_T_17_Y[] = { + MBEDTLS_BYTES_TO_T_UINT_8(0x65, 0x98, 0x7C, 0x84, 0xE1, 0xFF, 0x30, 0x77), + MBEDTLS_BYTES_TO_T_UINT_8(0x71, 0xE2, 0xC2, 0x5F, 0x55, 0x40, 0xBD, 0xCD), + MBEDTLS_BYTES_TO_T_UINT_8(0x69, 0x65, 0x87, 0x3F, 0xC4, 0xC2, 0x24, 0x57), + MBEDTLS_BYTES_TO_T_UINT_8(0x0E, 0x30, 0x0A, 0x60, 0x15, 0xD1, 0x24, 0x48), + MBEDTLS_BYTES_TO_T_UINT_8(0x57, 0x99, 0xD9, 0xB6, 0xAE, 0xB1, 0xAF, 0x1D), + MBEDTLS_BYTES_TO_T_UINT_8(0x9B, 0x80, 0xEE, 0xA2, 0x0F, 0x74, 0xB9, 0xF3), +}; +static const mbedtls_mpi_uint secp384r1_T_18_X[] = { + MBEDTLS_BYTES_TO_T_UINT_8(0x03, 0xE6, 0x0F, 0x37, 0xC1, 0x10, 0x99, 0x1E), + MBEDTLS_BYTES_TO_T_UINT_8(0x61, 0xAD, 0x9D, 0x5D, 0x80, 0x01, 0xA6, 0xFE), + MBEDTLS_BYTES_TO_T_UINT_8(0xB0, 0x0F, 0x10, 0x2A, 0x9D, 0x20, 0x38, 0xEB), + MBEDTLS_BYTES_TO_T_UINT_8(0x6C, 0x60, 0xCB, 0xCE, 0x5A, 0xA0, 0xA7, 0x32), + MBEDTLS_BYTES_TO_T_UINT_8(0xBA, 0xCF, 0x14, 0xDF, 0xBF, 0xE5, 0x74, 0x2D), + MBEDTLS_BYTES_TO_T_UINT_8(0xB5, 0x12, 0x1A, 0xDD, 0x59, 0x02, 0x5D, 0xC6), +}; +static const mbedtls_mpi_uint secp384r1_T_18_Y[] = { + MBEDTLS_BYTES_TO_T_UINT_8(0xC8, 0xC9, 0xF8, 0xF5, 0xB6, 0x13, 0x4D, 0x7B), + MBEDTLS_BYTES_TO_T_UINT_8(0xED, 0x45, 0xB1, 0x93, 0xB3, 0xA2, 0x79, 0xDC), + MBEDTLS_BYTES_TO_T_UINT_8(0x74, 0xF6, 0xCF, 0xF7, 0xE6, 0x29, 0x9C, 0xCC), + MBEDTLS_BYTES_TO_T_UINT_8(0x87, 0x50, 0x65, 0x80, 0xBC, 0x59, 0x0A, 0x59), + MBEDTLS_BYTES_TO_T_UINT_8(0x0E, 0xF0, 0x24, 0x35, 0xA2, 0x46, 0xF0, 0x0C), + MBEDTLS_BYTES_TO_T_UINT_8(0xBD, 0x26, 0xC0, 0x9D, 0x61, 0x56, 0x62, 0x67), +}; +static const mbedtls_mpi_uint secp384r1_T_19_X[] = { + MBEDTLS_BYTES_TO_T_UINT_8(0x10, 0xBB, 0xC2, 0x24, 0x43, 0x2E, 0x37, 0x54), + MBEDTLS_BYTES_TO_T_UINT_8(0x8A, 0xF7, 0xCE, 0x35, 0xFC, 0x77, 0xF3, 0x3F), + MBEDTLS_BYTES_TO_T_UINT_8(0x75, 0x34, 0x96, 0xD5, 0x4A, 0x76, 0x9D, 0x6B), + MBEDTLS_BYTES_TO_T_UINT_8(0xB8, 0x3B, 0x0F, 0xEA, 0xA8, 0x12, 0x0B, 0x22), + MBEDTLS_BYTES_TO_T_UINT_8(0x66, 0x3F, 0x5D, 0x2D, 0x1C, 0xD4, 0x9E, 0xFB), + MBEDTLS_BYTES_TO_T_UINT_8(0x7D, 0x2E, 0xDD, 0xC7, 0x6E, 0xAB, 0xAF, 0xDC), +}; +static const mbedtls_mpi_uint secp384r1_T_19_Y[] = { + MBEDTLS_BYTES_TO_T_UINT_8(0x8C, 0xB2, 0x7B, 0x0C, 0x9A, 0x83, 0x8E, 0x59), + MBEDTLS_BYTES_TO_T_UINT_8(0x30, 0x51, 0x90, 0x92, 0x79, 0x32, 0x19, 0xC3), + MBEDTLS_BYTES_TO_T_UINT_8(0xEE, 0x89, 0xF9, 0xD0, 0xCF, 0x2C, 0xA5, 0x8F), + MBEDTLS_BYTES_TO_T_UINT_8(0x7B, 0x50, 0x21, 0xDE, 0x50, 0x41, 0x9D, 0x81), + MBEDTLS_BYTES_TO_T_UINT_8(0xE0, 0x7D, 0x2B, 0x9E, 0x9D, 0x95, 0xA8, 0xE3), + MBEDTLS_BYTES_TO_T_UINT_8(0xD8, 0xA5, 0x20, 0x87, 0x88, 0x97, 0x5F, 0xAA), +}; +static const mbedtls_mpi_uint secp384r1_T_20_X[] = { + MBEDTLS_BYTES_TO_T_UINT_8(0x64, 0x59, 0xB4, 0x66, 0x7E, 0xE8, 0x5A, 0x60), + MBEDTLS_BYTES_TO_T_UINT_8(0xA5, 0x5C, 0x7E, 0xB2, 0xAD, 0xD9, 0xC9, 0xDA), + MBEDTLS_BYTES_TO_T_UINT_8(0x82, 0x97, 0x49, 0xA3, 0x13, 0x83, 0x07, 0x2E), + MBEDTLS_BYTES_TO_T_UINT_8(0x5A, 0x26, 0xC7, 0x13, 0x35, 0x0D, 0xB0, 0x6B), + MBEDTLS_BYTES_TO_T_UINT_8(0x1E, 0x60, 0xAB, 0xFA, 0x4B, 0x93, 0x18, 0x2C), + MBEDTLS_BYTES_TO_T_UINT_8(0x54, 0x2D, 0x1C, 0x31, 0x4C, 0xE4, 0x61, 0xAE), +}; +static const mbedtls_mpi_uint secp384r1_T_20_Y[] = { + MBEDTLS_BYTES_TO_T_UINT_8(0xDE, 0x4D, 0x1E, 0x51, 0x59, 0x6E, 0x91, 0xC5), + MBEDTLS_BYTES_TO_T_UINT_8(0x38, 0x54, 0x4D, 0x51, 0xED, 0x36, 0xCC, 0x60), + MBEDTLS_BYTES_TO_T_UINT_8(0x18, 0xA8, 0x56, 0xC7, 0x78, 0x27, 0x33, 0xC5), + MBEDTLS_BYTES_TO_T_UINT_8(0x42, 0xB7, 0x95, 0xC9, 0x8B, 0xC8, 0x6A, 0xBC), + MBEDTLS_BYTES_TO_T_UINT_8(0x5E, 0xE9, 0x13, 0x96, 0xB3, 0xE1, 0xF9, 0xEE), + MBEDTLS_BYTES_TO_T_UINT_8(0xF5, 0x46, 0xB0, 0x5E, 0xC3, 0x94, 0x03, 0x05), +}; +static const mbedtls_mpi_uint secp384r1_T_21_X[] = { + MBEDTLS_BYTES_TO_T_UINT_8(0x6D, 0x5B, 0x29, 0x30, 0x41, 0x1A, 0x9E, 0xB6), + MBEDTLS_BYTES_TO_T_UINT_8(0x76, 0xCA, 0x83, 0x31, 0x5B, 0xA7, 0xCB, 0x42), + MBEDTLS_BYTES_TO_T_UINT_8(0x21, 0x41, 0x50, 0x44, 0x4D, 0x64, 0x31, 0x89), + MBEDTLS_BYTES_TO_T_UINT_8(0xCF, 0x84, 0xC2, 0x5D, 0x97, 0xA5, 0x3C, 0x18), + MBEDTLS_BYTES_TO_T_UINT_8(0xF0, 0x0F, 0xA5, 0xFD, 0x8E, 0x5A, 0x47, 0x2C), + MBEDTLS_BYTES_TO_T_UINT_8(0x7C, 0x58, 0x02, 0x2D, 0x40, 0xB1, 0x0B, 0xBA), +}; +static const mbedtls_mpi_uint secp384r1_T_21_Y[] = { + MBEDTLS_BYTES_TO_T_UINT_8(0xDA, 0x33, 0x8C, 0x67, 0xCE, 0x23, 0x43, 0x99), + MBEDTLS_BYTES_TO_T_UINT_8(0x84, 0x53, 0x47, 0x72, 0x44, 0x1F, 0x5B, 0x2A), + MBEDTLS_BYTES_TO_T_UINT_8(0xAE, 0xC1, 0xD9, 0xA4, 0x50, 0x88, 0x63, 0x18), + MBEDTLS_BYTES_TO_T_UINT_8(0x7C, 0xF2, 0x75, 0x69, 0x73, 0x00, 0xC4, 0x31), + MBEDTLS_BYTES_TO_T_UINT_8(0x4B, 0x90, 0x1D, 0xDF, 0x1A, 0x00, 0xD8, 0x69), + MBEDTLS_BYTES_TO_T_UINT_8(0x05, 0xB1, 0x89, 0x48, 0xA8, 0x70, 0x62, 0xEF), +}; +static const mbedtls_mpi_uint secp384r1_T_22_X[] = { + MBEDTLS_BYTES_TO_T_UINT_8(0x7E, 0x8A, 0x55, 0x50, 0x7B, 0xEF, 0x8A, 0x3C), + MBEDTLS_BYTES_TO_T_UINT_8(0xFE, 0x1B, 0x23, 0x48, 0x23, 0x63, 0x91, 0xB6), + MBEDTLS_BYTES_TO_T_UINT_8(0x0D, 0x04, 0x54, 0x3C, 0x24, 0x9B, 0xC7, 0x9A), + MBEDTLS_BYTES_TO_T_UINT_8(0x25, 0x38, 0xC3, 0x84, 0xFB, 0xFF, 0x9F, 0x49), + MBEDTLS_BYTES_TO_T_UINT_8(0x66, 0x2A, 0xE0, 0x6D, 0x68, 0x8A, 0x5C, 0xCB), + MBEDTLS_BYTES_TO_T_UINT_8(0xC4, 0x93, 0x53, 0x85, 0xA1, 0x0D, 0xAF, 0x63), +}; +static const mbedtls_mpi_uint secp384r1_T_22_Y[] = { + MBEDTLS_BYTES_TO_T_UINT_8(0x1B, 0x88, 0x95, 0x4C, 0x0B, 0xD0, 0x06, 0x51), + MBEDTLS_BYTES_TO_T_UINT_8(0x92, 0xAF, 0x8D, 0x49, 0xA2, 0xC8, 0xB4, 0xE0), + MBEDTLS_BYTES_TO_T_UINT_8(0x75, 0x76, 0x53, 0x09, 0x88, 0x43, 0x87, 0xCA), + MBEDTLS_BYTES_TO_T_UINT_8(0x90, 0xA4, 0x77, 0x3F, 0x5E, 0x21, 0xB4, 0x0A), + MBEDTLS_BYTES_TO_T_UINT_8(0x35, 0x9E, 0x86, 0x64, 0xCC, 0x91, 0xC1, 0x77), + MBEDTLS_BYTES_TO_T_UINT_8(0xC1, 0x17, 0x56, 0xCB, 0xC3, 0x7D, 0x5B, 0xB1), +}; +static const mbedtls_mpi_uint secp384r1_T_23_X[] = { + MBEDTLS_BYTES_TO_T_UINT_8(0x64, 0x74, 0x9F, 0xB5, 0x91, 0x21, 0xB1, 0x1C), + MBEDTLS_BYTES_TO_T_UINT_8(0x1E, 0xED, 0xE1, 0x11, 0xEF, 0x45, 0xAF, 0xC1), + MBEDTLS_BYTES_TO_T_UINT_8(0xE0, 0x31, 0xBE, 0xB2, 0xBC, 0x72, 0x65, 0x1F), + MBEDTLS_BYTES_TO_T_UINT_8(0xB1, 0x4B, 0x8C, 0x77, 0xCE, 0x1E, 0x42, 0xB5), + MBEDTLS_BYTES_TO_T_UINT_8(0xFF, 0xC9, 0xAA, 0xB9, 0xD9, 0x86, 0x99, 0x55), + MBEDTLS_BYTES_TO_T_UINT_8(0x65, 0x23, 0x80, 0xC6, 0x4E, 0x35, 0x0B, 0x6D), +}; +static const mbedtls_mpi_uint secp384r1_T_23_Y[] = { + MBEDTLS_BYTES_TO_T_UINT_8(0x47, 0xD8, 0xA2, 0x0A, 0x39, 0x32, 0x1D, 0x23), + MBEDTLS_BYTES_TO_T_UINT_8(0x61, 0xC8, 0x86, 0xF1, 0x12, 0x9A, 0x4A, 0x05), + MBEDTLS_BYTES_TO_T_UINT_8(0x8D, 0xF1, 0x7C, 0xAA, 0x70, 0x8E, 0xBC, 0x01), + MBEDTLS_BYTES_TO_T_UINT_8(0x62, 0x01, 0x47, 0x8F, 0xDD, 0x8B, 0xA5, 0xC8), + MBEDTLS_BYTES_TO_T_UINT_8(0xDB, 0x08, 0x21, 0xF4, 0xAB, 0xC7, 0xF5, 0x96), + MBEDTLS_BYTES_TO_T_UINT_8(0x0A, 0x76, 0xA5, 0x95, 0xC4, 0x0F, 0x88, 0x1D), +}; +static const mbedtls_mpi_uint secp384r1_T_24_X[] = { + MBEDTLS_BYTES_TO_T_UINT_8(0x3F, 0x42, 0x2A, 0x52, 0xCD, 0x75, 0x51, 0x49), + MBEDTLS_BYTES_TO_T_UINT_8(0x90, 0x36, 0xE5, 0x04, 0x2B, 0x44, 0xC6, 0xEF), + MBEDTLS_BYTES_TO_T_UINT_8(0x5C, 0xEE, 0x16, 0x13, 0x07, 0x83, 0xB5, 0x30), + MBEDTLS_BYTES_TO_T_UINT_8(0x76, 0x59, 0xC6, 0xA2, 0x19, 0x05, 0xD3, 0xC6), + MBEDTLS_BYTES_TO_T_UINT_8(0xB6, 0x8B, 0xA8, 0x16, 0x09, 0xB7, 0xEA, 0xD6), + MBEDTLS_BYTES_TO_T_UINT_8(0x70, 0xEE, 0x14, 0xAF, 0xB5, 0xFD, 0xD0, 0xEF), +}; +static const mbedtls_mpi_uint secp384r1_T_24_Y[] = { + MBEDTLS_BYTES_TO_T_UINT_8(0x18, 0x7C, 0xCA, 0x71, 0x3E, 0x6E, 0x66, 0x75), + MBEDTLS_BYTES_TO_T_UINT_8(0xBE, 0x31, 0x0E, 0x3F, 0xE5, 0x91, 0xC4, 0x7F), + MBEDTLS_BYTES_TO_T_UINT_8(0x8E, 0x3D, 0xC2, 0x3E, 0x95, 0x37, 0x58, 0x2B), + MBEDTLS_BYTES_TO_T_UINT_8(0x01, 0x1F, 0x02, 0x03, 0xF3, 0xEF, 0xEE, 0x66), + MBEDTLS_BYTES_TO_T_UINT_8(0x28, 0x5B, 0x1A, 0xFC, 0x38, 0xCD, 0xE8, 0x24), + MBEDTLS_BYTES_TO_T_UINT_8(0x12, 0x57, 0x42, 0x85, 0xC6, 0x21, 0x68, 0x71), +}; +static const mbedtls_mpi_uint secp384r1_T_25_X[] = { + MBEDTLS_BYTES_TO_T_UINT_8(0x8D, 0xA2, 0x4A, 0x66, 0xB1, 0x0A, 0xE6, 0xC0), + MBEDTLS_BYTES_TO_T_UINT_8(0x86, 0x0C, 0x94, 0x9D, 0x5E, 0x99, 0xB2, 0xCE), + MBEDTLS_BYTES_TO_T_UINT_8(0xAD, 0x03, 0x40, 0xCA, 0xB2, 0xB3, 0x30, 0x55), + MBEDTLS_BYTES_TO_T_UINT_8(0x74, 0x78, 0x48, 0x27, 0x34, 0x1E, 0xE2, 0x42), + MBEDTLS_BYTES_TO_T_UINT_8(0xAE, 0x72, 0x5B, 0xAC, 0xC1, 0x6D, 0xE3, 0x82), + MBEDTLS_BYTES_TO_T_UINT_8(0x57, 0xAB, 0x46, 0xCB, 0xEA, 0x5E, 0x4B, 0x0B), +}; +static const mbedtls_mpi_uint secp384r1_T_25_Y[] = { + MBEDTLS_BYTES_TO_T_UINT_8(0xFC, 0x08, 0xAD, 0x4E, 0x51, 0x9F, 0x2A, 0x52), + MBEDTLS_BYTES_TO_T_UINT_8(0x68, 0x5C, 0x7D, 0x4C, 0xD6, 0xCF, 0xDD, 0x02), + MBEDTLS_BYTES_TO_T_UINT_8(0xD8, 0x76, 0x26, 0xE0, 0x8B, 0x10, 0xD9, 0x7C), + MBEDTLS_BYTES_TO_T_UINT_8(0x30, 0xA7, 0x23, 0x4E, 0x5F, 0xD2, 0x42, 0x17), + MBEDTLS_BYTES_TO_T_UINT_8(0xD1, 0xE5, 0xA4, 0xEC, 0x77, 0x21, 0x34, 0x28), + MBEDTLS_BYTES_TO_T_UINT_8(0x5C, 0x14, 0x65, 0xEA, 0x4A, 0x85, 0xC3, 0x2F), +}; +static const mbedtls_mpi_uint secp384r1_T_26_X[] = { + MBEDTLS_BYTES_TO_T_UINT_8(0x19, 0xD8, 0x40, 0x27, 0x73, 0x15, 0x7E, 0x65), + MBEDTLS_BYTES_TO_T_UINT_8(0xF6, 0xBB, 0x53, 0x7E, 0x0F, 0x40, 0xC8, 0xD4), + MBEDTLS_BYTES_TO_T_UINT_8(0xEA, 0x37, 0x19, 0x73, 0xEF, 0x5A, 0x5E, 0x04), + MBEDTLS_BYTES_TO_T_UINT_8(0x9C, 0x73, 0x2B, 0x49, 0x7E, 0xAC, 0x97, 0x5C), + MBEDTLS_BYTES_TO_T_UINT_8(0x15, 0xB2, 0xC3, 0x1E, 0x0E, 0xE7, 0xD2, 0x21), + MBEDTLS_BYTES_TO_T_UINT_8(0x8A, 0x08, 0xD6, 0xDD, 0xAC, 0x21, 0xD6, 0x3E), +}; +static const mbedtls_mpi_uint secp384r1_T_26_Y[] = { + MBEDTLS_BYTES_TO_T_UINT_8(0xA9, 0x26, 0xBE, 0x6D, 0x6D, 0xF2, 0x38, 0x3F), + MBEDTLS_BYTES_TO_T_UINT_8(0x08, 0x6C, 0x31, 0xA7, 0x49, 0x50, 0x3A, 0x89), + MBEDTLS_BYTES_TO_T_UINT_8(0xC3, 0x99, 0xC6, 0xF5, 0xD2, 0xC2, 0x30, 0x5A), + MBEDTLS_BYTES_TO_T_UINT_8(0x2A, 0xE4, 0xF6, 0x8B, 0x8B, 0x97, 0xE9, 0xB2), + MBEDTLS_BYTES_TO_T_UINT_8(0xDD, 0x21, 0xB7, 0x0D, 0xFC, 0x15, 0x54, 0x0B), + MBEDTLS_BYTES_TO_T_UINT_8(0x65, 0x83, 0x1C, 0xA4, 0xCD, 0x6B, 0x9D, 0xF2), +}; +static const mbedtls_mpi_uint secp384r1_T_27_X[] = { + MBEDTLS_BYTES_TO_T_UINT_8(0xD6, 0xE8, 0x4C, 0x48, 0xE4, 0xAA, 0x69, 0x93), + MBEDTLS_BYTES_TO_T_UINT_8(0x27, 0x7A, 0x27, 0xFC, 0x37, 0x96, 0x1A, 0x7B), + MBEDTLS_BYTES_TO_T_UINT_8(0x6F, 0xE7, 0x30, 0xA5, 0xCF, 0x13, 0x46, 0x5C), + MBEDTLS_BYTES_TO_T_UINT_8(0x8C, 0xD8, 0xAF, 0x74, 0x23, 0x4D, 0x56, 0x84), + MBEDTLS_BYTES_TO_T_UINT_8(0x32, 0x3D, 0x44, 0x14, 0x1B, 0x97, 0x83, 0xF0), + MBEDTLS_BYTES_TO_T_UINT_8(0xFA, 0x47, 0xD7, 0x5F, 0xFD, 0x98, 0x38, 0xF7), +}; +static const mbedtls_mpi_uint secp384r1_T_27_Y[] = { + MBEDTLS_BYTES_TO_T_UINT_8(0xA3, 0x73, 0x64, 0x36, 0xFD, 0x7B, 0xC1, 0x15), + MBEDTLS_BYTES_TO_T_UINT_8(0xEA, 0x5D, 0x32, 0xD2, 0x47, 0x94, 0x89, 0x2D), + MBEDTLS_BYTES_TO_T_UINT_8(0x51, 0xE9, 0x30, 0xAC, 0x06, 0xC8, 0x65, 0x04), + MBEDTLS_BYTES_TO_T_UINT_8(0xFA, 0x6C, 0xB9, 0x1B, 0xF7, 0x61, 0x49, 0x53), + MBEDTLS_BYTES_TO_T_UINT_8(0xD7, 0xFF, 0x32, 0x43, 0x80, 0xDA, 0xA6, 0xB1), + MBEDTLS_BYTES_TO_T_UINT_8(0xAC, 0xF8, 0x04, 0x01, 0x95, 0x35, 0xCE, 0x21), +}; +static const mbedtls_mpi_uint secp384r1_T_28_X[] = { + MBEDTLS_BYTES_TO_T_UINT_8(0x6D, 0x06, 0x46, 0x0D, 0x51, 0xE2, 0xD8, 0xAC), + MBEDTLS_BYTES_TO_T_UINT_8(0x14, 0x57, 0x1D, 0x6F, 0x79, 0xA0, 0xCD, 0xA6), + MBEDTLS_BYTES_TO_T_UINT_8(0xDF, 0xFB, 0x36, 0xCA, 0xAD, 0xF5, 0x9E, 0x41), + MBEDTLS_BYTES_TO_T_UINT_8(0x6F, 0x7A, 0x1D, 0x9E, 0x1D, 0x95, 0x48, 0xDC), + MBEDTLS_BYTES_TO_T_UINT_8(0x81, 0x26, 0xA5, 0xB7, 0x15, 0x2C, 0xC2, 0xC6), + MBEDTLS_BYTES_TO_T_UINT_8(0x86, 0x42, 0x72, 0xAA, 0x11, 0xDC, 0xC9, 0xB6), +}; +static const mbedtls_mpi_uint secp384r1_T_28_Y[] = { + MBEDTLS_BYTES_TO_T_UINT_8(0x3F, 0x6C, 0x64, 0xA7, 0x62, 0x3C, 0xAB, 0xD4), + MBEDTLS_BYTES_TO_T_UINT_8(0x48, 0x6A, 0x44, 0xD8, 0x60, 0xC0, 0xA8, 0x80), + MBEDTLS_BYTES_TO_T_UINT_8(0x82, 0x76, 0x58, 0x12, 0x57, 0x3C, 0x89, 0x46), + MBEDTLS_BYTES_TO_T_UINT_8(0x82, 0x4F, 0x83, 0xCE, 0xCB, 0xB8, 0xD0, 0x2C), + MBEDTLS_BYTES_TO_T_UINT_8(0x9A, 0x84, 0x04, 0xB0, 0xAD, 0xEB, 0xFA, 0xDF), + MBEDTLS_BYTES_TO_T_UINT_8(0x34, 0xA4, 0xC3, 0x41, 0x44, 0x4E, 0x65, 0x3E), +}; +static const mbedtls_mpi_uint secp384r1_T_29_X[] = { + MBEDTLS_BYTES_TO_T_UINT_8(0xB6, 0x16, 0xA9, 0x1C, 0xE7, 0x65, 0x20, 0xC1), + MBEDTLS_BYTES_TO_T_UINT_8(0x58, 0x53, 0x32, 0xF8, 0xC0, 0xA6, 0xBD, 0x2C), + MBEDTLS_BYTES_TO_T_UINT_8(0xB7, 0xF0, 0xE6, 0x57, 0x31, 0xCC, 0x26, 0x6F), + MBEDTLS_BYTES_TO_T_UINT_8(0x27, 0xE3, 0x54, 0x1C, 0x34, 0xD3, 0x17, 0xBC), + MBEDTLS_BYTES_TO_T_UINT_8(0xF5, 0xAE, 0xED, 0xFB, 0xCD, 0xE7, 0x1E, 0x9F), + MBEDTLS_BYTES_TO_T_UINT_8(0x5A, 0x16, 0x1C, 0x34, 0x40, 0x00, 0x1F, 0xB6), +}; +static const mbedtls_mpi_uint secp384r1_T_29_Y[] = { + MBEDTLS_BYTES_TO_T_UINT_8(0x6A, 0x32, 0x00, 0xC2, 0xD4, 0x3B, 0x1A, 0x09), + MBEDTLS_BYTES_TO_T_UINT_8(0x34, 0xE0, 0x99, 0x8F, 0x0C, 0x4A, 0x16, 0x44), + MBEDTLS_BYTES_TO_T_UINT_8(0x83, 0x73, 0x18, 0x1B, 0xD4, 0x94, 0x29, 0x62), + MBEDTLS_BYTES_TO_T_UINT_8(0x29, 0xA4, 0x2D, 0xB1, 0x9D, 0x74, 0x32, 0x67), + MBEDTLS_BYTES_TO_T_UINT_8(0xBF, 0xF4, 0xB1, 0x0C, 0x37, 0x62, 0x8B, 0x66), + MBEDTLS_BYTES_TO_T_UINT_8(0xC9, 0xFF, 0xDA, 0xE2, 0x35, 0xA3, 0xB6, 0x42), +}; +static const mbedtls_mpi_uint secp384r1_T_30_X[] = { + MBEDTLS_BYTES_TO_T_UINT_8(0x91, 0x49, 0x99, 0x65, 0xC5, 0xED, 0x16, 0xEF), + MBEDTLS_BYTES_TO_T_UINT_8(0x79, 0x42, 0x9A, 0xF3, 0xA7, 0x4E, 0x6F, 0x2B), + MBEDTLS_BYTES_TO_T_UINT_8(0x7B, 0x0A, 0x7E, 0xC0, 0xD7, 0x4E, 0x07, 0x55), + MBEDTLS_BYTES_TO_T_UINT_8(0xD6, 0x7A, 0x31, 0x69, 0xA6, 0xB9, 0x15, 0x34), + MBEDTLS_BYTES_TO_T_UINT_8(0xA8, 0xE0, 0x72, 0xA4, 0x3F, 0xB9, 0xF8, 0x0C), + MBEDTLS_BYTES_TO_T_UINT_8(0x2B, 0x75, 0x32, 0x85, 0xA2, 0xDE, 0x37, 0x12), +}; +static const mbedtls_mpi_uint secp384r1_T_30_Y[] = { + MBEDTLS_BYTES_TO_T_UINT_8(0xBC, 0xC0, 0x0D, 0xCF, 0x25, 0x41, 0xA4, 0xF4), + MBEDTLS_BYTES_TO_T_UINT_8(0x9B, 0xFC, 0xB2, 0x48, 0xC3, 0x85, 0x83, 0x4B), + MBEDTLS_BYTES_TO_T_UINT_8(0x2B, 0xBE, 0x0B, 0x58, 0x2D, 0x7A, 0x9A, 0x62), + MBEDTLS_BYTES_TO_T_UINT_8(0xC5, 0xF3, 0x81, 0x18, 0x1B, 0x74, 0x4F, 0x2C), + MBEDTLS_BYTES_TO_T_UINT_8(0xE2, 0x43, 0xA3, 0x0A, 0x16, 0x8B, 0xA3, 0x1E), + MBEDTLS_BYTES_TO_T_UINT_8(0x4A, 0x18, 0x81, 0x7B, 0x8D, 0xA2, 0x35, 0x77), +}; +static const mbedtls_mpi_uint secp384r1_T_31_X[] = { + MBEDTLS_BYTES_TO_T_UINT_8(0x86, 0xC4, 0x3F, 0x2C, 0xE7, 0x5F, 0x99, 0x03), + MBEDTLS_BYTES_TO_T_UINT_8(0xF0, 0x2B, 0xB7, 0xB6, 0xAD, 0x5A, 0x56, 0xFF), + MBEDTLS_BYTES_TO_T_UINT_8(0x04, 0x00, 0xA4, 0x48, 0xC8, 0xE8, 0xBA, 0xBF), + MBEDTLS_BYTES_TO_T_UINT_8(0xE8, 0xA1, 0xB5, 0x13, 0x5A, 0xCD, 0x99, 0x9C), + MBEDTLS_BYTES_TO_T_UINT_8(0xB0, 0x95, 0xAD, 0xFC, 0xE2, 0x7E, 0xE7, 0xFE), + MBEDTLS_BYTES_TO_T_UINT_8(0x96, 0x6B, 0xD1, 0x34, 0x99, 0x53, 0x63, 0x0B), +}; +static const mbedtls_mpi_uint secp384r1_T_31_Y[] = { + MBEDTLS_BYTES_TO_T_UINT_8(0x19, 0x8A, 0x77, 0x5D, 0x2B, 0xAB, 0x01, 0x28), + MBEDTLS_BYTES_TO_T_UINT_8(0x4E, 0x85, 0xD0, 0xD5, 0x49, 0x83, 0x4D, 0x60), + MBEDTLS_BYTES_TO_T_UINT_8(0x81, 0xC6, 0x91, 0x30, 0x3B, 0x00, 0xAF, 0x7A), + MBEDTLS_BYTES_TO_T_UINT_8(0x3A, 0xAE, 0x61, 0x07, 0xE1, 0xB6, 0xE2, 0xC9), + MBEDTLS_BYTES_TO_T_UINT_8(0x95, 0x43, 0x41, 0xFE, 0x9B, 0xB6, 0xF0, 0xA5), + MBEDTLS_BYTES_TO_T_UINT_8(0xB4, 0x97, 0xAE, 0xAD, 0x89, 0x88, 0x9E, 0x41), +}; +static const mbedtls_ecp_point secp384r1_T[32] = { + ECP_POINT_INIT_XY_Z1(secp384r1_T_0_X, secp384r1_T_0_Y), + ECP_POINT_INIT_XY_Z0(secp384r1_T_1_X, secp384r1_T_1_Y), + ECP_POINT_INIT_XY_Z0(secp384r1_T_2_X, secp384r1_T_2_Y), + ECP_POINT_INIT_XY_Z0(secp384r1_T_3_X, secp384r1_T_3_Y), + ECP_POINT_INIT_XY_Z0(secp384r1_T_4_X, secp384r1_T_4_Y), + ECP_POINT_INIT_XY_Z0(secp384r1_T_5_X, secp384r1_T_5_Y), + ECP_POINT_INIT_XY_Z0(secp384r1_T_6_X, secp384r1_T_6_Y), + ECP_POINT_INIT_XY_Z0(secp384r1_T_7_X, secp384r1_T_7_Y), + ECP_POINT_INIT_XY_Z0(secp384r1_T_8_X, secp384r1_T_8_Y), + ECP_POINT_INIT_XY_Z0(secp384r1_T_9_X, secp384r1_T_9_Y), + ECP_POINT_INIT_XY_Z0(secp384r1_T_10_X, secp384r1_T_10_Y), + ECP_POINT_INIT_XY_Z0(secp384r1_T_11_X, secp384r1_T_11_Y), + ECP_POINT_INIT_XY_Z0(secp384r1_T_12_X, secp384r1_T_12_Y), + ECP_POINT_INIT_XY_Z0(secp384r1_T_13_X, secp384r1_T_13_Y), + ECP_POINT_INIT_XY_Z0(secp384r1_T_14_X, secp384r1_T_14_Y), + ECP_POINT_INIT_XY_Z0(secp384r1_T_15_X, secp384r1_T_15_Y), + ECP_POINT_INIT_XY_Z0(secp384r1_T_16_X, secp384r1_T_16_Y), + ECP_POINT_INIT_XY_Z0(secp384r1_T_17_X, secp384r1_T_17_Y), + ECP_POINT_INIT_XY_Z0(secp384r1_T_18_X, secp384r1_T_18_Y), + ECP_POINT_INIT_XY_Z0(secp384r1_T_19_X, secp384r1_T_19_Y), + ECP_POINT_INIT_XY_Z0(secp384r1_T_20_X, secp384r1_T_20_Y), + ECP_POINT_INIT_XY_Z0(secp384r1_T_21_X, secp384r1_T_21_Y), + ECP_POINT_INIT_XY_Z0(secp384r1_T_22_X, secp384r1_T_22_Y), + ECP_POINT_INIT_XY_Z0(secp384r1_T_23_X, secp384r1_T_23_Y), + ECP_POINT_INIT_XY_Z0(secp384r1_T_24_X, secp384r1_T_24_Y), + ECP_POINT_INIT_XY_Z0(secp384r1_T_25_X, secp384r1_T_25_Y), + ECP_POINT_INIT_XY_Z0(secp384r1_T_26_X, secp384r1_T_26_Y), + ECP_POINT_INIT_XY_Z0(secp384r1_T_27_X, secp384r1_T_27_Y), + ECP_POINT_INIT_XY_Z0(secp384r1_T_28_X, secp384r1_T_28_Y), + ECP_POINT_INIT_XY_Z0(secp384r1_T_29_X, secp384r1_T_29_Y), + ECP_POINT_INIT_XY_Z0(secp384r1_T_30_X, secp384r1_T_30_Y), + ECP_POINT_INIT_XY_Z0(secp384r1_T_31_X, secp384r1_T_31_Y), +}; +#else +#define secp384r1_T NULL +#endif + #endif /* MBEDTLS_ECP_DP_SECP384R1_ENABLED */ /* @@ -256,6 +1424,748 @@ static const mbedtls_mpi_uint secp521r1_n[] = { MBEDTLS_BYTES_TO_T_UINT_8(0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF), MBEDTLS_BYTES_TO_T_UINT_2(0xFF, 0x01), }; +#if MBEDTLS_ECP_FIXED_POINT_OPTIM == 1 +static const mbedtls_mpi_uint secp521r1_T_0_X[] = { + MBEDTLS_BYTES_TO_T_UINT_8(0x66, 0xBD, 0xE5, 0xC2, 0x31, 0x7E, 0x7E, 0xF9), + MBEDTLS_BYTES_TO_T_UINT_8(0x9B, 0x42, 0x6A, 0x85, 0xC1, 0xB3, 0x48, 0x33), + MBEDTLS_BYTES_TO_T_UINT_8(0xDE, 0xA8, 0xFF, 0xA2, 0x27, 0xC1, 0x1D, 0xFE), + MBEDTLS_BYTES_TO_T_UINT_8(0x28, 0x59, 0xE7, 0xEF, 0x77, 0x5E, 0x4B, 0xA1), + MBEDTLS_BYTES_TO_T_UINT_8(0xBA, 0x3D, 0x4D, 0x6B, 0x60, 0xAF, 0x28, 0xF8), + MBEDTLS_BYTES_TO_T_UINT_8(0x21, 0xB5, 0x3F, 0x05, 0x39, 0x81, 0x64, 0x9C), + MBEDTLS_BYTES_TO_T_UINT_8(0x42, 0xB4, 0x95, 0x23, 0x66, 0xCB, 0x3E, 0x9E), + MBEDTLS_BYTES_TO_T_UINT_8(0xCD, 0xE9, 0x04, 0x04, 0xB7, 0x06, 0x8E, 0x85), + MBEDTLS_BYTES_TO_T_UINT_8(0xC6, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00), +}; +static const mbedtls_mpi_uint secp521r1_T_0_Y[] = { + MBEDTLS_BYTES_TO_T_UINT_8(0x50, 0x66, 0xD1, 0x9F, 0x76, 0x94, 0xBE, 0x88), + MBEDTLS_BYTES_TO_T_UINT_8(0x40, 0xC2, 0x72, 0xA2, 0x86, 0x70, 0x3C, 0x35), + MBEDTLS_BYTES_TO_T_UINT_8(0x61, 0x07, 0xAD, 0x3F, 0x01, 0xB9, 0x50, 0xC5), + MBEDTLS_BYTES_TO_T_UINT_8(0x40, 0x26, 0xF4, 0x5E, 0x99, 0x72, 0xEE, 0x97), + MBEDTLS_BYTES_TO_T_UINT_8(0x2C, 0x66, 0x3E, 0x27, 0x17, 0xBD, 0xAF, 0x17), + MBEDTLS_BYTES_TO_T_UINT_8(0x68, 0x44, 0x9B, 0x57, 0x49, 0x44, 0xF5, 0x98), + MBEDTLS_BYTES_TO_T_UINT_8(0xD9, 0x1B, 0x7D, 0x2C, 0xB4, 0x5F, 0x8A, 0x5C), + MBEDTLS_BYTES_TO_T_UINT_8(0x04, 0xC0, 0x3B, 0x9A, 0x78, 0x6A, 0x29, 0x39), + MBEDTLS_BYTES_TO_T_UINT_8(0x18, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00), +}; +static const mbedtls_mpi_uint secp521r1_T_1_X[] = { + MBEDTLS_BYTES_TO_T_UINT_8(0x2F, 0xB1, 0x2D, 0xEB, 0x27, 0x2F, 0xE8, 0xDA), + MBEDTLS_BYTES_TO_T_UINT_8(0x98, 0x4B, 0x44, 0x25, 0xDB, 0x5C, 0x5F, 0x67), + MBEDTLS_BYTES_TO_T_UINT_8(0x13, 0x85, 0x28, 0x78, 0x2E, 0x75, 0x34, 0x32), + MBEDTLS_BYTES_TO_T_UINT_8(0x69, 0x57, 0x0F, 0x73, 0x78, 0x7A, 0xE3, 0x53), + MBEDTLS_BYTES_TO_T_UINT_8(0x8D, 0xD8, 0xEC, 0xDC, 0xDA, 0x04, 0xAD, 0xAB), + MBEDTLS_BYTES_TO_T_UINT_8(0x34, 0x8A, 0x09, 0xF3, 0x58, 0x79, 0xD8, 0x29), + MBEDTLS_BYTES_TO_T_UINT_8(0x63, 0x03, 0xCB, 0x50, 0x1A, 0x7F, 0x56, 0x00), + MBEDTLS_BYTES_TO_T_UINT_8(0xF6, 0xA6, 0x78, 0x38, 0x85, 0x67, 0x0B, 0x40), + MBEDTLS_BYTES_TO_T_UINT_8(0x83, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00), +}; +static const mbedtls_mpi_uint secp521r1_T_1_Y[] = { + MBEDTLS_BYTES_TO_T_UINT_8(0x8A, 0xD5, 0xD2, 0x22, 0xC4, 0x00, 0x3B, 0xBA), + MBEDTLS_BYTES_TO_T_UINT_8(0xD5, 0x93, 0x0E, 0x7B, 0x85, 0x51, 0xC3, 0x06), + MBEDTLS_BYTES_TO_T_UINT_8(0x3D, 0xA6, 0x5F, 0x54, 0x49, 0x02, 0x81, 0x78), + MBEDTLS_BYTES_TO_T_UINT_8(0x22, 0xE9, 0x6B, 0x3A, 0x92, 0xE7, 0x72, 0x1D), + MBEDTLS_BYTES_TO_T_UINT_8(0x6F, 0x5F, 0x28, 0x9E, 0x91, 0x27, 0x88, 0xE3), + MBEDTLS_BYTES_TO_T_UINT_8(0xEF, 0x28, 0x31, 0xB3, 0x84, 0xCA, 0x12, 0x32), + MBEDTLS_BYTES_TO_T_UINT_8(0x3D, 0xF9, 0xAC, 0x22, 0x10, 0x0A, 0x64, 0x41), + MBEDTLS_BYTES_TO_T_UINT_8(0xE9, 0xC6, 0x33, 0x1F, 0x69, 0x19, 0x18, 0xBF), + MBEDTLS_BYTES_TO_T_UINT_8(0xBE, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00), +}; +static const mbedtls_mpi_uint secp521r1_T_2_X[] = { + MBEDTLS_BYTES_TO_T_UINT_8(0xA0, 0x48, 0xB8, 0xC7, 0x37, 0x5A, 0x00, 0x36), + MBEDTLS_BYTES_TO_T_UINT_8(0x07, 0xCC, 0x32, 0xE0, 0xEE, 0x03, 0xC2, 0xBA), + MBEDTLS_BYTES_TO_T_UINT_8(0xC4, 0x29, 0xC2, 0xE4, 0x6E, 0x24, 0x20, 0x8D), + MBEDTLS_BYTES_TO_T_UINT_8(0x06, 0x6B, 0x7F, 0x7B, 0xF9, 0xB0, 0xB8, 0x13), + MBEDTLS_BYTES_TO_T_UINT_8(0x1D, 0x7B, 0x3C, 0xE1, 0x19, 0xA1, 0x23, 0x02), + MBEDTLS_BYTES_TO_T_UINT_8(0x2A, 0xE3, 0xC2, 0x53, 0xC0, 0x07, 0x13, 0xA9), + MBEDTLS_BYTES_TO_T_UINT_8(0x07, 0xFE, 0x36, 0x35, 0x9F, 0x5E, 0x59, 0xCE), + MBEDTLS_BYTES_TO_T_UINT_8(0x1D, 0x55, 0x89, 0x84, 0xBC, 0xEF, 0xA2, 0xC2), + MBEDTLS_BYTES_TO_T_UINT_8(0x19, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00), +}; +static const mbedtls_mpi_uint secp521r1_T_2_Y[] = { + MBEDTLS_BYTES_TO_T_UINT_8(0xFD, 0x1A, 0x08, 0x67, 0xB4, 0xE7, 0x22, 0xED), + MBEDTLS_BYTES_TO_T_UINT_8(0x76, 0x26, 0xDF, 0x81, 0x3C, 0x5F, 0x1C, 0xDA), + MBEDTLS_BYTES_TO_T_UINT_8(0xE0, 0x4D, 0xD0, 0x0A, 0x48, 0x06, 0xF4, 0x48), + MBEDTLS_BYTES_TO_T_UINT_8(0x73, 0x18, 0x39, 0xF7, 0xD1, 0x20, 0x77, 0x8D), + MBEDTLS_BYTES_TO_T_UINT_8(0x78, 0x8F, 0x44, 0x13, 0xCB, 0x78, 0x11, 0x11), + MBEDTLS_BYTES_TO_T_UINT_8(0x33, 0xE2, 0x49, 0xEA, 0x43, 0x79, 0x08, 0x39), + MBEDTLS_BYTES_TO_T_UINT_8(0x01, 0xD1, 0xD8, 0x73, 0x2C, 0x71, 0x2F, 0x69), + MBEDTLS_BYTES_TO_T_UINT_8(0x21, 0xE5, 0xE7, 0xF4, 0x46, 0xAB, 0x20, 0xCA), + MBEDTLS_BYTES_TO_T_UINT_8(0x5A, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00), +}; +static const mbedtls_mpi_uint secp521r1_T_3_X[] = { + MBEDTLS_BYTES_TO_T_UINT_8(0x8C, 0x0B, 0xB9, 0x71, 0x1A, 0x27, 0xB7, 0xA7), + MBEDTLS_BYTES_TO_T_UINT_8(0x2A, 0xA2, 0x2C, 0xD1, 0xDA, 0xBC, 0xC1, 0xBD), + MBEDTLS_BYTES_TO_T_UINT_8(0x10, 0xA3, 0x10, 0x1F, 0x90, 0xF2, 0xA5, 0x52), + MBEDTLS_BYTES_TO_T_UINT_8(0x28, 0xFB, 0x20, 0xF4, 0xC0, 0x70, 0xC0, 0xF5), + MBEDTLS_BYTES_TO_T_UINT_8(0x8F, 0xA7, 0x99, 0xF0, 0xA5, 0xD3, 0x09, 0xDD), + MBEDTLS_BYTES_TO_T_UINT_8(0x26, 0xE8, 0x14, 0x39, 0xBE, 0xCB, 0x60, 0xAF), + MBEDTLS_BYTES_TO_T_UINT_8(0x9F, 0xD6, 0x14, 0xA9, 0xC9, 0x20, 0xC3, 0xEA), + MBEDTLS_BYTES_TO_T_UINT_8(0x5D, 0xA8, 0x5B, 0xFD, 0x2D, 0x96, 0xBC, 0x78), + MBEDTLS_BYTES_TO_T_UINT_8(0xC0, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00), +}; +static const mbedtls_mpi_uint secp521r1_T_3_Y[] = { + MBEDTLS_BYTES_TO_T_UINT_8(0x9D, 0x04, 0x45, 0xBE, 0xCE, 0x75, 0x95, 0xF6), + MBEDTLS_BYTES_TO_T_UINT_8(0xCC, 0xDA, 0x58, 0x49, 0x35, 0x09, 0x8D, 0x41), + MBEDTLS_BYTES_TO_T_UINT_8(0x76, 0xF0, 0xC0, 0x36, 0xF2, 0xA6, 0x2D, 0x14), + MBEDTLS_BYTES_TO_T_UINT_8(0xE7, 0xFC, 0x3D, 0xA8, 0xFB, 0x3C, 0xD2, 0x51), + MBEDTLS_BYTES_TO_T_UINT_8(0x01, 0x4D, 0x71, 0x09, 0x18, 0x42, 0xF0, 0x2D), + MBEDTLS_BYTES_TO_T_UINT_8(0x8D, 0xC1, 0xCE, 0x9E, 0x6A, 0x49, 0x60, 0x12), + MBEDTLS_BYTES_TO_T_UINT_8(0xAD, 0xB1, 0x00, 0xF7, 0xA1, 0x7A, 0x31, 0xB4), + MBEDTLS_BYTES_TO_T_UINT_8(0x41, 0xC3, 0x86, 0xCD, 0x20, 0x4A, 0x17, 0x86), + MBEDTLS_BYTES_TO_T_UINT_8(0x6C, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00), +}; +static const mbedtls_mpi_uint secp521r1_T_4_X[] = { + MBEDTLS_BYTES_TO_T_UINT_8(0x98, 0xAB, 0x8B, 0x47, 0x8D, 0xAA, 0xA6, 0x5B), + MBEDTLS_BYTES_TO_T_UINT_8(0xC4, 0x97, 0xF0, 0xBC, 0x2D, 0xDC, 0x9D, 0x84), + MBEDTLS_BYTES_TO_T_UINT_8(0x01, 0x86, 0xB0, 0x74, 0xB2, 0xF4, 0xF6, 0x67), + MBEDTLS_BYTES_TO_T_UINT_8(0xAC, 0xBD, 0xAC, 0xE3, 0x8F, 0x43, 0x5C, 0xB1), + MBEDTLS_BYTES_TO_T_UINT_8(0x37, 0xC3, 0xE2, 0x6E, 0x25, 0x49, 0xCD, 0x0B), + MBEDTLS_BYTES_TO_T_UINT_8(0x64, 0x5E, 0x08, 0xB3, 0xB9, 0xAC, 0x5F, 0xD1), + MBEDTLS_BYTES_TO_T_UINT_8(0x08, 0xB7, 0xD1, 0xF4, 0xDC, 0x19, 0xE9, 0xC8), + MBEDTLS_BYTES_TO_T_UINT_8(0x49, 0xE4, 0xFA, 0xE1, 0x36, 0x3E, 0xED, 0x6E), + MBEDTLS_BYTES_TO_T_UINT_8(0x0A, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00), +}; +static const mbedtls_mpi_uint secp521r1_T_4_Y[] = { + MBEDTLS_BYTES_TO_T_UINT_8(0x00, 0x67, 0x92, 0x84, 0x6E, 0x48, 0x03, 0x51), + MBEDTLS_BYTES_TO_T_UINT_8(0x9E, 0x95, 0xEF, 0x8F, 0xB2, 0x82, 0x6B, 0x1C), + MBEDTLS_BYTES_TO_T_UINT_8(0x8D, 0xFA, 0xB9, 0x55, 0x23, 0xFE, 0x09, 0xB3), + MBEDTLS_BYTES_TO_T_UINT_8(0xEF, 0x79, 0x85, 0x4B, 0x0E, 0xD4, 0x35, 0xDB), + MBEDTLS_BYTES_TO_T_UINT_8(0x9A, 0x27, 0x45, 0x81, 0xE0, 0x88, 0x52, 0xAD), + MBEDTLS_BYTES_TO_T_UINT_8(0x17, 0x63, 0xA2, 0x4B, 0xBC, 0x5D, 0xB1, 0x92), + MBEDTLS_BYTES_TO_T_UINT_8(0x28, 0x8C, 0x83, 0xD9, 0x3E, 0xD3, 0x42, 0xDA), + MBEDTLS_BYTES_TO_T_UINT_8(0x99, 0x03, 0x3A, 0x31, 0xBA, 0xE9, 0x3A, 0xD1), + MBEDTLS_BYTES_TO_T_UINT_8(0x47, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00), +}; +static const mbedtls_mpi_uint secp521r1_T_5_X[] = { + MBEDTLS_BYTES_TO_T_UINT_8(0x35, 0x10, 0xCD, 0x2D, 0x00, 0xFE, 0x32, 0xA7), + MBEDTLS_BYTES_TO_T_UINT_8(0xE4, 0x6E, 0x1F, 0xDA, 0xF8, 0x6F, 0x4D, 0x03), + MBEDTLS_BYTES_TO_T_UINT_8(0x09, 0x79, 0x7D, 0x09, 0xE5, 0xD3, 0x03, 0x21), + MBEDTLS_BYTES_TO_T_UINT_8(0x58, 0xC3, 0xBE, 0xDF, 0x07, 0x65, 0x49, 0xCC), + MBEDTLS_BYTES_TO_T_UINT_8(0x08, 0x57, 0x33, 0xEF, 0xAE, 0x4F, 0x04, 0x27), + MBEDTLS_BYTES_TO_T_UINT_8(0x9A, 0xE9, 0x9B, 0xFE, 0xBF, 0xE6, 0x85, 0xF6), + MBEDTLS_BYTES_TO_T_UINT_8(0xBD, 0xBA, 0xAA, 0x06, 0xC4, 0xC6, 0xB8, 0x57), + MBEDTLS_BYTES_TO_T_UINT_8(0x0C, 0x83, 0x01, 0xA9, 0xF6, 0x51, 0xE7, 0xB8), + MBEDTLS_BYTES_TO_T_UINT_8(0x1B, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00), +}; +static const mbedtls_mpi_uint secp521r1_T_5_Y[] = { + MBEDTLS_BYTES_TO_T_UINT_8(0xB9, 0xA6, 0x15, 0x8E, 0xAB, 0x1F, 0x10, 0x87), + MBEDTLS_BYTES_TO_T_UINT_8(0x74, 0x08, 0x27, 0x1A, 0xA1, 0x21, 0xAD, 0xF5), + MBEDTLS_BYTES_TO_T_UINT_8(0x02, 0x09, 0x90, 0x6E, 0x50, 0x90, 0x9A, 0x5D), + MBEDTLS_BYTES_TO_T_UINT_8(0x86, 0x9A, 0xFE, 0xD7, 0xA1, 0xF5, 0xA2, 0x15), + MBEDTLS_BYTES_TO_T_UINT_8(0xE8, 0x7D, 0xE3, 0xDC, 0x21, 0xFB, 0xA4, 0x7B), + MBEDTLS_BYTES_TO_T_UINT_8(0xB9, 0xBF, 0x07, 0xFF, 0x45, 0xDF, 0x51, 0x77), + MBEDTLS_BYTES_TO_T_UINT_8(0x0B, 0x5C, 0x34, 0x02, 0x62, 0x9B, 0x08, 0x12), + MBEDTLS_BYTES_TO_T_UINT_8(0x86, 0xCE, 0x9A, 0x6A, 0xEC, 0x75, 0xF6, 0x46), + MBEDTLS_BYTES_TO_T_UINT_8(0x6D, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00), +}; +static const mbedtls_mpi_uint secp521r1_T_6_X[] = { + MBEDTLS_BYTES_TO_T_UINT_8(0xE6, 0x59, 0xF4, 0x78, 0x3C, 0x60, 0xB1, 0x4A), + MBEDTLS_BYTES_TO_T_UINT_8(0x3E, 0x37, 0x84, 0x6A, 0xDC, 0xF2, 0x9A, 0x7D), + MBEDTLS_BYTES_TO_T_UINT_8(0x40, 0x9A, 0x9A, 0x15, 0x36, 0xE0, 0x2B, 0x2D), + MBEDTLS_BYTES_TO_T_UINT_8(0xEC, 0x38, 0x9C, 0x50, 0x3D, 0x1E, 0x37, 0x82), + MBEDTLS_BYTES_TO_T_UINT_8(0xB7, 0x79, 0xF0, 0x92, 0xF2, 0x8B, 0x18, 0x82), + MBEDTLS_BYTES_TO_T_UINT_8(0x17, 0xE0, 0x82, 0x1E, 0x80, 0x82, 0x4B, 0xD7), + MBEDTLS_BYTES_TO_T_UINT_8(0xFA, 0xBB, 0x59, 0x6B, 0x8A, 0x77, 0x41, 0x40), + MBEDTLS_BYTES_TO_T_UINT_8(0xA7, 0xF9, 0xD4, 0xB8, 0x4A, 0x82, 0xCF, 0x40), + MBEDTLS_BYTES_TO_T_UINT_8(0x5D, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00), +}; +static const mbedtls_mpi_uint secp521r1_T_6_Y[] = { + MBEDTLS_BYTES_TO_T_UINT_8(0x1E, 0x8C, 0xC8, 0x9B, 0x72, 0x9E, 0xF7, 0xF9), + MBEDTLS_BYTES_TO_T_UINT_8(0xB8, 0xCE, 0xE9, 0x77, 0x0A, 0x19, 0x59, 0x84), + MBEDTLS_BYTES_TO_T_UINT_8(0x9D, 0xA1, 0x41, 0x6A, 0x72, 0x4B, 0xB4, 0xDC), + MBEDTLS_BYTES_TO_T_UINT_8(0x0B, 0x35, 0x43, 0xE2, 0x8C, 0xBE, 0x0D, 0xE3), + MBEDTLS_BYTES_TO_T_UINT_8(0xC1, 0xEB, 0xAD, 0xF3, 0xA9, 0xA6, 0x68, 0xA1), + MBEDTLS_BYTES_TO_T_UINT_8(0x81, 0x2F, 0xE2, 0x48, 0x0C, 0xDB, 0x1F, 0x42), + MBEDTLS_BYTES_TO_T_UINT_8(0xD1, 0x1E, 0x60, 0x9B, 0x2A, 0xD2, 0xC1, 0x3C), + MBEDTLS_BYTES_TO_T_UINT_8(0xC0, 0x64, 0xB5, 0xD2, 0xF6, 0xF6, 0x6E, 0x22), + MBEDTLS_BYTES_TO_T_UINT_8(0x70, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00), +}; +static const mbedtls_mpi_uint secp521r1_T_7_X[] = { + MBEDTLS_BYTES_TO_T_UINT_8(0xC6, 0x3D, 0x30, 0x78, 0x10, 0x18, 0x41, 0x51), + MBEDTLS_BYTES_TO_T_UINT_8(0x96, 0x1D, 0x1C, 0xE0, 0x6D, 0x83, 0xD1, 0x93), + MBEDTLS_BYTES_TO_T_UINT_8(0x7B, 0x03, 0x0B, 0xF5, 0x2F, 0x6C, 0x04, 0x98), + MBEDTLS_BYTES_TO_T_UINT_8(0x6C, 0x3E, 0xD5, 0xFC, 0x31, 0x5B, 0x3A, 0xEB), + MBEDTLS_BYTES_TO_T_UINT_8(0x50, 0x82, 0x2F, 0xFB, 0xFE, 0xF8, 0x76, 0x39), + MBEDTLS_BYTES_TO_T_UINT_8(0x85, 0x26, 0xDA, 0x9C, 0x36, 0xF5, 0x93, 0xD1), + MBEDTLS_BYTES_TO_T_UINT_8(0x4C, 0xE7, 0x6E, 0xD2, 0x7D, 0x81, 0x09, 0xC6), + MBEDTLS_BYTES_TO_T_UINT_8(0xD3, 0x03, 0xF9, 0x58, 0x48, 0x24, 0xA2, 0xEE), + MBEDTLS_BYTES_TO_T_UINT_8(0xE9, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00), +}; +static const mbedtls_mpi_uint secp521r1_T_7_Y[] = { + MBEDTLS_BYTES_TO_T_UINT_8(0x1B, 0x79, 0x0C, 0x8E, 0x6B, 0x95, 0xF3, 0xC4), + MBEDTLS_BYTES_TO_T_UINT_8(0xF4, 0x10, 0x5C, 0x87, 0x03, 0x39, 0xCF, 0x68), + MBEDTLS_BYTES_TO_T_UINT_8(0xAD, 0xF0, 0xF7, 0xC1, 0x07, 0xA4, 0xF4, 0x3F), + MBEDTLS_BYTES_TO_T_UINT_8(0x32, 0xE8, 0x02, 0x89, 0x65, 0xC4, 0x72, 0x36), + MBEDTLS_BYTES_TO_T_UINT_8(0xB4, 0x88, 0xEA, 0x96, 0x67, 0x0B, 0x5D, 0xDF), + MBEDTLS_BYTES_TO_T_UINT_8(0xA8, 0x75, 0x60, 0xA8, 0xBD, 0x74, 0xDF, 0x68), + MBEDTLS_BYTES_TO_T_UINT_8(0x6E, 0xE5, 0x71, 0x50, 0x67, 0xD0, 0xD2, 0xE6), + MBEDTLS_BYTES_TO_T_UINT_8(0xD5, 0xFC, 0xE5, 0xC7, 0x77, 0xB0, 0x7F, 0x8C), + MBEDTLS_BYTES_TO_T_UINT_8(0xF1, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00), +}; +static const mbedtls_mpi_uint secp521r1_T_8_X[] = { + MBEDTLS_BYTES_TO_T_UINT_8(0x97, 0x86, 0x69, 0xCD, 0x0D, 0x9A, 0xBD, 0x66), + MBEDTLS_BYTES_TO_T_UINT_8(0x58, 0x17, 0xBC, 0xBB, 0x59, 0x85, 0x7D, 0x0E), + MBEDTLS_BYTES_TO_T_UINT_8(0x8D, 0xA8, 0x76, 0xAC, 0x80, 0xA9, 0x72, 0xE0), + MBEDTLS_BYTES_TO_T_UINT_8(0x74, 0x78, 0xC1, 0xE2, 0x4D, 0xAF, 0xF9, 0x3C), + MBEDTLS_BYTES_TO_T_UINT_8(0xAD, 0x97, 0x8E, 0x74, 0xC4, 0x4B, 0xB2, 0x85), + MBEDTLS_BYTES_TO_T_UINT_8(0xEA, 0xD8, 0xF6, 0xF3, 0xAF, 0x2F, 0x52, 0xE5), + MBEDTLS_BYTES_TO_T_UINT_8(0x95, 0x57, 0xF4, 0xCE, 0xEE, 0x43, 0xED, 0x60), + MBEDTLS_BYTES_TO_T_UINT_8(0x7D, 0x46, 0x38, 0xDE, 0x20, 0xFD, 0x59, 0x18), + MBEDTLS_BYTES_TO_T_UINT_8(0xD7, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00), +}; +static const mbedtls_mpi_uint secp521r1_T_8_Y[] = { + MBEDTLS_BYTES_TO_T_UINT_8(0x1C, 0x18, 0xE8, 0x58, 0xB9, 0x76, 0x2C, 0xE6), + MBEDTLS_BYTES_TO_T_UINT_8(0xED, 0x54, 0xE4, 0xFE, 0xC7, 0xBC, 0x31, 0x37), + MBEDTLS_BYTES_TO_T_UINT_8(0xF5, 0xF8, 0x89, 0xEE, 0x70, 0xB5, 0xB0, 0x2C), + MBEDTLS_BYTES_TO_T_UINT_8(0x83, 0x22, 0x26, 0x9A, 0x53, 0xB9, 0x38, 0x0A), + MBEDTLS_BYTES_TO_T_UINT_8(0x74, 0xA7, 0x19, 0x8C, 0x74, 0x7E, 0x88, 0x46), + MBEDTLS_BYTES_TO_T_UINT_8(0xB4, 0xDA, 0x0A, 0xE8, 0xDA, 0xA5, 0xBE, 0x1D), + MBEDTLS_BYTES_TO_T_UINT_8(0x90, 0x5C, 0xF7, 0xB1, 0x0C, 0x72, 0xFB, 0x09), + MBEDTLS_BYTES_TO_T_UINT_8(0x78, 0xE2, 0x23, 0xE7, 0x46, 0xB7, 0xE0, 0x91), + MBEDTLS_BYTES_TO_T_UINT_8(0xC5, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00), +}; +static const mbedtls_mpi_uint secp521r1_T_9_X[] = { + MBEDTLS_BYTES_TO_T_UINT_8(0x3A, 0x36, 0xBC, 0xBD, 0x48, 0x11, 0x8E, 0x72), + MBEDTLS_BYTES_TO_T_UINT_8(0xAB, 0xBB, 0xA1, 0xF7, 0x0B, 0x9E, 0xBF, 0xDF), + MBEDTLS_BYTES_TO_T_UINT_8(0x68, 0x28, 0xE1, 0xA2, 0x8F, 0xFC, 0xFC, 0xD6), + MBEDTLS_BYTES_TO_T_UINT_8(0x81, 0xFE, 0x19, 0x0A, 0xE5, 0xE7, 0x69, 0x39), + MBEDTLS_BYTES_TO_T_UINT_8(0x5E, 0xCD, 0x12, 0xF5, 0xBE, 0xD3, 0x04, 0xF1), + MBEDTLS_BYTES_TO_T_UINT_8(0xF5, 0xA8, 0x0D, 0x81, 0x59, 0xC4, 0x79, 0x98), + MBEDTLS_BYTES_TO_T_UINT_8(0xA3, 0xF3, 0x4B, 0x92, 0x65, 0xC3, 0x31, 0xAD), + MBEDTLS_BYTES_TO_T_UINT_8(0x75, 0xB5, 0x4F, 0x4D, 0x91, 0xD4, 0xE2, 0xB2), + MBEDTLS_BYTES_TO_T_UINT_8(0x51, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00), +}; +static const mbedtls_mpi_uint secp521r1_T_9_Y[] = { + MBEDTLS_BYTES_TO_T_UINT_8(0x72, 0x09, 0x41, 0x79, 0x1D, 0x4D, 0x0D, 0x33), + MBEDTLS_BYTES_TO_T_UINT_8(0xBB, 0x31, 0x18, 0xBA, 0xA0, 0xF2, 0x6E, 0x7E), + MBEDTLS_BYTES_TO_T_UINT_8(0x93, 0x5B, 0x4D, 0x4F, 0xAF, 0xC9, 0x8C, 0xA1), + MBEDTLS_BYTES_TO_T_UINT_8(0x48, 0x99, 0x9C, 0x06, 0x68, 0xDE, 0xD8, 0x29), + MBEDTLS_BYTES_TO_T_UINT_8(0xA0, 0x04, 0xE1, 0xB5, 0x9D, 0x00, 0xBC, 0xB8), + MBEDTLS_BYTES_TO_T_UINT_8(0x61, 0x95, 0x92, 0x8D, 0x72, 0xD3, 0x37, 0x42), + MBEDTLS_BYTES_TO_T_UINT_8(0xAB, 0x4B, 0x27, 0xA2, 0xE8, 0xA4, 0x26, 0xA1), + MBEDTLS_BYTES_TO_T_UINT_8(0x4F, 0x45, 0x9C, 0xA9, 0xCB, 0x9F, 0xBA, 0x85), + MBEDTLS_BYTES_TO_T_UINT_8(0xCB, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00), +}; +static const mbedtls_mpi_uint secp521r1_T_10_X[] = { + MBEDTLS_BYTES_TO_T_UINT_8(0x08, 0x7E, 0x1B, 0x64, 0xF4, 0xE8, 0xA5, 0x55), + MBEDTLS_BYTES_TO_T_UINT_8(0xF7, 0x20, 0xA9, 0xCA, 0xF3, 0x89, 0xE5, 0xE1), + MBEDTLS_BYTES_TO_T_UINT_8(0x83, 0xED, 0xFC, 0xAB, 0xD9, 0x0A, 0xB9, 0x07), + MBEDTLS_BYTES_TO_T_UINT_8(0x08, 0x6F, 0x46, 0x7C, 0xCD, 0x78, 0xFF, 0x05), + MBEDTLS_BYTES_TO_T_UINT_8(0x69, 0xAB, 0x71, 0x5A, 0x94, 0xAB, 0x20, 0x20), + MBEDTLS_BYTES_TO_T_UINT_8(0xC2, 0x2E, 0xEE, 0x87, 0x57, 0x1F, 0xAD, 0xD3), + MBEDTLS_BYTES_TO_T_UINT_8(0x91, 0x4C, 0x3D, 0xFB, 0x7E, 0xA1, 0x8B, 0x07), + MBEDTLS_BYTES_TO_T_UINT_8(0x69, 0xCF, 0x07, 0x86, 0xBA, 0x53, 0x37, 0xCF), + MBEDTLS_BYTES_TO_T_UINT_8(0x38, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00), +}; +static const mbedtls_mpi_uint secp521r1_T_10_Y[] = { + MBEDTLS_BYTES_TO_T_UINT_8(0x00, 0x26, 0xB2, 0xB9, 0xE2, 0x91, 0xE3, 0xB5), + MBEDTLS_BYTES_TO_T_UINT_8(0x79, 0xC9, 0x54, 0x84, 0x08, 0x3D, 0x0B, 0xD2), + MBEDTLS_BYTES_TO_T_UINT_8(0x5D, 0xA8, 0x77, 0x2F, 0x64, 0x45, 0x99, 0x4C), + MBEDTLS_BYTES_TO_T_UINT_8(0x87, 0x96, 0x16, 0x1F, 0xDB, 0x96, 0x28, 0x97), + MBEDTLS_BYTES_TO_T_UINT_8(0x83, 0x2B, 0x8D, 0xFF, 0xA2, 0x4F, 0x55, 0xD3), + MBEDTLS_BYTES_TO_T_UINT_8(0x71, 0xE6, 0x48, 0xBD, 0x99, 0x3D, 0x12, 0x57), + MBEDTLS_BYTES_TO_T_UINT_8(0x3F, 0x84, 0x59, 0xDA, 0xB9, 0xB6, 0x66, 0x12), + MBEDTLS_BYTES_TO_T_UINT_8(0x6D, 0x78, 0x41, 0x92, 0xDF, 0xF4, 0x3F, 0x63), + MBEDTLS_BYTES_TO_T_UINT_8(0x1F, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00), +}; +static const mbedtls_mpi_uint secp521r1_T_11_X[] = { + MBEDTLS_BYTES_TO_T_UINT_8(0x7E, 0x86, 0x6F, 0x4F, 0xBF, 0x67, 0xDF, 0x2F), + MBEDTLS_BYTES_TO_T_UINT_8(0xF2, 0x2B, 0x1E, 0x5F, 0x00, 0xEA, 0xF6, 0x56), + MBEDTLS_BYTES_TO_T_UINT_8(0x90, 0xB9, 0x6A, 0x89, 0xD8, 0xC0, 0xD7, 0xA7), + MBEDTLS_BYTES_TO_T_UINT_8(0xCB, 0x9A, 0x32, 0x23, 0xA0, 0x02, 0x91, 0x58), + MBEDTLS_BYTES_TO_T_UINT_8(0x42, 0x7F, 0x6A, 0x15, 0x64, 0x6A, 0x8B, 0xBB), + MBEDTLS_BYTES_TO_T_UINT_8(0x8A, 0x57, 0x82, 0x58, 0xA9, 0x56, 0xB5, 0xFB), + MBEDTLS_BYTES_TO_T_UINT_8(0xDD, 0x50, 0x92, 0x60, 0xCC, 0x81, 0x24, 0xA8), + MBEDTLS_BYTES_TO_T_UINT_8(0x36, 0x3D, 0xAD, 0xDA, 0xD9, 0x51, 0x3E, 0x57), + MBEDTLS_BYTES_TO_T_UINT_8(0x5D, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00), +}; +static const mbedtls_mpi_uint secp521r1_T_11_Y[] = { + MBEDTLS_BYTES_TO_T_UINT_8(0xEC, 0xFE, 0x8F, 0xB0, 0x0B, 0xDE, 0x2E, 0x7E), + MBEDTLS_BYTES_TO_T_UINT_8(0x79, 0xD2, 0xBE, 0xEF, 0xAC, 0x76, 0x71, 0xA3), + MBEDTLS_BYTES_TO_T_UINT_8(0x55, 0xE8, 0x72, 0x0B, 0xAC, 0xFE, 0xCA, 0x5A), + MBEDTLS_BYTES_TO_T_UINT_8(0xAD, 0x5B, 0xC7, 0xFC, 0xE3, 0x3C, 0x7C, 0x4C), + MBEDTLS_BYTES_TO_T_UINT_8(0xA1, 0x04, 0xA7, 0xB9, 0x9B, 0x93, 0xC0, 0x2F), + MBEDTLS_BYTES_TO_T_UINT_8(0x41, 0x48, 0x4B, 0x8E, 0x32, 0xC5, 0xF0, 0x6B), + MBEDTLS_BYTES_TO_T_UINT_8(0xB0, 0x42, 0x07, 0xC1, 0xF2, 0xF1, 0x72, 0x5B), + MBEDTLS_BYTES_TO_T_UINT_8(0x1E, 0x37, 0x54, 0x9C, 0x88, 0xD2, 0x62, 0xAA), + MBEDTLS_BYTES_TO_T_UINT_8(0xC1, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00), +}; +static const mbedtls_mpi_uint secp521r1_T_12_X[] = { + MBEDTLS_BYTES_TO_T_UINT_8(0xC2, 0x19, 0x8A, 0x89, 0x58, 0xA2, 0x0F, 0xDB), + MBEDTLS_BYTES_TO_T_UINT_8(0x01, 0xCC, 0x4C, 0x97, 0x30, 0x66, 0x34, 0x26), + MBEDTLS_BYTES_TO_T_UINT_8(0x83, 0x6A, 0x1E, 0x1F, 0xDB, 0xC9, 0x5E, 0x13), + MBEDTLS_BYTES_TO_T_UINT_8(0x1B, 0x4D, 0x49, 0xFF, 0x9B, 0x9C, 0xAC, 0x9B), + MBEDTLS_BYTES_TO_T_UINT_8(0xD7, 0xE4, 0x4B, 0xF2, 0xD4, 0x1A, 0xD2, 0x78), + MBEDTLS_BYTES_TO_T_UINT_8(0xCD, 0xDA, 0xE8, 0x61, 0x9F, 0xC8, 0x49, 0x32), + MBEDTLS_BYTES_TO_T_UINT_8(0x51, 0xCB, 0xF2, 0x2D, 0x85, 0xF6, 0x8D, 0x52), + MBEDTLS_BYTES_TO_T_UINT_8(0xB7, 0xC5, 0xCD, 0x2C, 0x79, 0xC6, 0x0E, 0x4F), + MBEDTLS_BYTES_TO_T_UINT_8(0xDB, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00), +}; +static const mbedtls_mpi_uint secp521r1_T_12_Y[] = { + MBEDTLS_BYTES_TO_T_UINT_8(0x73, 0x1D, 0x55, 0x0F, 0xF8, 0x22, 0x9F, 0x78), + MBEDTLS_BYTES_TO_T_UINT_8(0x76, 0x56, 0xBA, 0xE7, 0x57, 0x32, 0xEC, 0x42), + MBEDTLS_BYTES_TO_T_UINT_8(0x65, 0x9A, 0xC6, 0x4C, 0x09, 0xC4, 0x52, 0x3F), + MBEDTLS_BYTES_TO_T_UINT_8(0xB6, 0x1E, 0x6F, 0xF4, 0x7D, 0x27, 0xDD, 0xAF), + MBEDTLS_BYTES_TO_T_UINT_8(0x94, 0x11, 0x16, 0xEC, 0x79, 0x83, 0xAD, 0xAE), + MBEDTLS_BYTES_TO_T_UINT_8(0x46, 0x4E, 0x92, 0x1F, 0x19, 0x7D, 0x65, 0xDC), + MBEDTLS_BYTES_TO_T_UINT_8(0x09, 0xFF, 0x78, 0x15, 0x45, 0x63, 0x32, 0xE4), + MBEDTLS_BYTES_TO_T_UINT_8(0xBF, 0x91, 0xD0, 0x78, 0x58, 0xDA, 0x50, 0x47), + MBEDTLS_BYTES_TO_T_UINT_8(0x73, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00), +}; +static const mbedtls_mpi_uint secp521r1_T_13_X[] = { + MBEDTLS_BYTES_TO_T_UINT_8(0x23, 0xDE, 0x40, 0xF6, 0x41, 0xB4, 0x3B, 0x95), + MBEDTLS_BYTES_TO_T_UINT_8(0xC6, 0x8D, 0xE0, 0xE1, 0xA9, 0xF0, 0x35, 0x5D), + MBEDTLS_BYTES_TO_T_UINT_8(0xE6, 0xD4, 0xBA, 0x7B, 0xCC, 0x1B, 0x3A, 0x32), + MBEDTLS_BYTES_TO_T_UINT_8(0xD0, 0x5A, 0x2E, 0x74, 0x47, 0x14, 0xC3, 0x4D), + MBEDTLS_BYTES_TO_T_UINT_8(0x7D, 0xF0, 0x8B, 0x06, 0x15, 0x8E, 0x0E, 0xCA), + MBEDTLS_BYTES_TO_T_UINT_8(0xB5, 0xD2, 0xEB, 0x97, 0x50, 0x7D, 0x31, 0xFC), + MBEDTLS_BYTES_TO_T_UINT_8(0x42, 0x93, 0x4C, 0xDB, 0x97, 0x79, 0x44, 0xF5), + MBEDTLS_BYTES_TO_T_UINT_8(0x9C, 0xA2, 0xA0, 0x0B, 0xC8, 0x3A, 0x8A, 0xF9), + MBEDTLS_BYTES_TO_T_UINT_8(0x61, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00), +}; +static const mbedtls_mpi_uint secp521r1_T_13_Y[] = { + MBEDTLS_BYTES_TO_T_UINT_8(0x79, 0x50, 0x92, 0x9E, 0x24, 0x1F, 0xCB, 0x4C), + MBEDTLS_BYTES_TO_T_UINT_8(0xD3, 0x16, 0xC9, 0xC5, 0x3D, 0x5A, 0xAF, 0x97), + MBEDTLS_BYTES_TO_T_UINT_8(0x18, 0xE3, 0x97, 0xE4, 0xA8, 0x50, 0xF6, 0x7E), + MBEDTLS_BYTES_TO_T_UINT_8(0x45, 0x57, 0x97, 0x42, 0x78, 0x92, 0x49, 0x0D), + MBEDTLS_BYTES_TO_T_UINT_8(0xA5, 0xEB, 0x62, 0x24, 0xFB, 0x8F, 0x32, 0xCF), + MBEDTLS_BYTES_TO_T_UINT_8(0xF3, 0x0C, 0x36, 0x6E, 0x8F, 0xE8, 0xE8, 0x8E), + MBEDTLS_BYTES_TO_T_UINT_8(0xC2, 0xD3, 0x7C, 0xC7, 0x8D, 0x3F, 0x5C, 0xE1), + MBEDTLS_BYTES_TO_T_UINT_8(0x6A, 0x64, 0x6A, 0x73, 0x10, 0x79, 0xB8, 0x5A), + MBEDTLS_BYTES_TO_T_UINT_8(0xCB, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00), +}; +static const mbedtls_mpi_uint secp521r1_T_14_X[] = { + MBEDTLS_BYTES_TO_T_UINT_8(0x51, 0xF9, 0xEF, 0xA5, 0x20, 0x4A, 0x5C, 0xA1), + MBEDTLS_BYTES_TO_T_UINT_8(0x2F, 0xF3, 0xF4, 0x49, 0x5B, 0x73, 0xAA, 0x1B), + MBEDTLS_BYTES_TO_T_UINT_8(0xC6, 0xF2, 0xEA, 0x0F, 0x00, 0xAD, 0x53, 0xAB), + MBEDTLS_BYTES_TO_T_UINT_8(0x03, 0xB8, 0x66, 0xED, 0xC4, 0x2B, 0x4C, 0x35), + MBEDTLS_BYTES_TO_T_UINT_8(0x3A, 0x2F, 0xC1, 0x9A, 0x37, 0xD2, 0x7F, 0x58), + MBEDTLS_BYTES_TO_T_UINT_8(0x29, 0xA7, 0x81, 0x38, 0x64, 0xC9, 0x37, 0x38), + MBEDTLS_BYTES_TO_T_UINT_8(0xBE, 0x3B, 0x6C, 0x9F, 0x5B, 0xD9, 0x8B, 0x1D), + MBEDTLS_BYTES_TO_T_UINT_8(0xB6, 0x14, 0xD9, 0x08, 0xD8, 0xD2, 0x7E, 0x23), + MBEDTLS_BYTES_TO_T_UINT_8(0x1C, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00), +}; +static const mbedtls_mpi_uint secp521r1_T_14_Y[] = { + MBEDTLS_BYTES_TO_T_UINT_8(0x15, 0x71, 0xE6, 0x3D, 0xD1, 0xB0, 0xE7, 0xCD), + MBEDTLS_BYTES_TO_T_UINT_8(0x5B, 0x81, 0x23, 0xEC, 0x2D, 0x42, 0x45, 0xE6), + MBEDTLS_BYTES_TO_T_UINT_8(0x51, 0x5B, 0x44, 0x6B, 0x89, 0x03, 0x67, 0x28), + MBEDTLS_BYTES_TO_T_UINT_8(0x84, 0x27, 0xAE, 0x80, 0x5A, 0x33, 0xBE, 0x11), + MBEDTLS_BYTES_TO_T_UINT_8(0xE3, 0xB6, 0x64, 0x1A, 0xDF, 0xD3, 0x85, 0x91), + MBEDTLS_BYTES_TO_T_UINT_8(0x67, 0x8C, 0x22, 0xBA, 0xD0, 0xBD, 0xCC, 0xA0), + MBEDTLS_BYTES_TO_T_UINT_8(0xF7, 0x3C, 0x01, 0x3A, 0xFF, 0x9D, 0xC7, 0x6B), + MBEDTLS_BYTES_TO_T_UINT_8(0x0C, 0xC7, 0x64, 0xB4, 0x59, 0x4E, 0x9F, 0x22), + MBEDTLS_BYTES_TO_T_UINT_8(0x85, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00), +}; +static const mbedtls_mpi_uint secp521r1_T_15_X[] = { + MBEDTLS_BYTES_TO_T_UINT_8(0xA1, 0x34, 0x0A, 0x41, 0x94, 0xA8, 0xF2, 0xB7), + MBEDTLS_BYTES_TO_T_UINT_8(0xF6, 0xD4, 0xE4, 0xF0, 0x97, 0x45, 0x6D, 0xCA), + MBEDTLS_BYTES_TO_T_UINT_8(0x8F, 0x1F, 0x4D, 0x6D, 0xFE, 0xA0, 0xC4, 0x84), + MBEDTLS_BYTES_TO_T_UINT_8(0x1D, 0x28, 0x5C, 0x40, 0xBB, 0x65, 0xD4, 0x42), + MBEDTLS_BYTES_TO_T_UINT_8(0x98, 0xA8, 0x87, 0x35, 0x20, 0x3A, 0x89, 0x44), + MBEDTLS_BYTES_TO_T_UINT_8(0xD6, 0xFD, 0x4F, 0xAB, 0x2D, 0xD1, 0xD0, 0xC0), + MBEDTLS_BYTES_TO_T_UINT_8(0x86, 0xE8, 0x00, 0xFC, 0x69, 0x52, 0xF8, 0xD5), + MBEDTLS_BYTES_TO_T_UINT_8(0xE1, 0x9A, 0x99, 0xE1, 0xDC, 0x9C, 0x3F, 0xD9), + MBEDTLS_BYTES_TO_T_UINT_8(0x99, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00), +}; +static const mbedtls_mpi_uint secp521r1_T_15_Y[] = { + MBEDTLS_BYTES_TO_T_UINT_8(0x12, 0x08, 0x98, 0xD9, 0xCA, 0x73, 0xD5, 0xA9), + MBEDTLS_BYTES_TO_T_UINT_8(0xB9, 0x2C, 0xE0, 0xA7, 0x3E, 0x91, 0xD7, 0x87), + MBEDTLS_BYTES_TO_T_UINT_8(0x68, 0x04, 0xB0, 0x54, 0x09, 0xF4, 0x72, 0xB7), + MBEDTLS_BYTES_TO_T_UINT_8(0xC8, 0xEE, 0x28, 0xCC, 0xE8, 0x50, 0x78, 0x20), + MBEDTLS_BYTES_TO_T_UINT_8(0x0D, 0x91, 0x03, 0x76, 0xDB, 0x68, 0x24, 0x77), + MBEDTLS_BYTES_TO_T_UINT_8(0x7A, 0xE0, 0x56, 0xB2, 0x5D, 0x12, 0xD3, 0xB5), + MBEDTLS_BYTES_TO_T_UINT_8(0x0D, 0x42, 0x59, 0x8B, 0xDF, 0x67, 0xB5, 0xBE), + MBEDTLS_BYTES_TO_T_UINT_8(0xD1, 0xCC, 0xE5, 0x31, 0x53, 0x7A, 0x46, 0xB3), + MBEDTLS_BYTES_TO_T_UINT_8(0xDA, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00), +}; +static const mbedtls_mpi_uint secp521r1_T_16_X[] = { + MBEDTLS_BYTES_TO_T_UINT_8(0xCC, 0x8D, 0x59, 0xB5, 0x1B, 0x0F, 0xF4, 0xAF), + MBEDTLS_BYTES_TO_T_UINT_8(0xD9, 0x2F, 0xD1, 0x2C, 0xE0, 0xD8, 0x04, 0xEF), + MBEDTLS_BYTES_TO_T_UINT_8(0xAC, 0xF4, 0xD7, 0xBA, 0xB0, 0xA3, 0x7E, 0xC9), + MBEDTLS_BYTES_TO_T_UINT_8(0xCD, 0x08, 0x51, 0x56, 0xA6, 0x76, 0x67, 0x33), + MBEDTLS_BYTES_TO_T_UINT_8(0x8C, 0x17, 0x63, 0xFE, 0x56, 0xD0, 0xD9, 0x71), + MBEDTLS_BYTES_TO_T_UINT_8(0xAA, 0xF6, 0xC3, 0x14, 0x47, 0xC5, 0xA7, 0x31), + MBEDTLS_BYTES_TO_T_UINT_8(0x72, 0x4C, 0x80, 0xF6, 0xA2, 0x57, 0xA7, 0x5D), + MBEDTLS_BYTES_TO_T_UINT_8(0x11, 0xB3, 0x7B, 0xF8, 0x2F, 0xE1, 0x3E, 0x7B), + MBEDTLS_BYTES_TO_T_UINT_8(0xFA, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00), +}; +static const mbedtls_mpi_uint secp521r1_T_16_Y[] = { + MBEDTLS_BYTES_TO_T_UINT_8(0x26, 0xF4, 0xF9, 0x6B, 0x7B, 0x90, 0xDF, 0x30), + MBEDTLS_BYTES_TO_T_UINT_8(0x1F, 0x82, 0xEF, 0x62, 0xA1, 0x4C, 0x53, 0xCA), + MBEDTLS_BYTES_TO_T_UINT_8(0xE6, 0x99, 0x76, 0x01, 0xBA, 0x8D, 0x0F, 0x54), + MBEDTLS_BYTES_TO_T_UINT_8(0xAF, 0xF4, 0x58, 0x73, 0x56, 0xFE, 0xDD, 0x7C), + MBEDTLS_BYTES_TO_T_UINT_8(0xF6, 0xCE, 0xF9, 0xE8, 0xA1, 0x34, 0xC3, 0x5B), + MBEDTLS_BYTES_TO_T_UINT_8(0x09, 0x5F, 0xDC, 0x6A, 0x3D, 0xD8, 0x7F, 0x42), + MBEDTLS_BYTES_TO_T_UINT_8(0xC2, 0xF4, 0x51, 0xB8, 0xB8, 0xC1, 0xD7, 0x2F), + MBEDTLS_BYTES_TO_T_UINT_8(0xAE, 0x7D, 0x58, 0xD1, 0xD4, 0x1B, 0x4D, 0x23), + MBEDTLS_BYTES_TO_T_UINT_8(0xD3, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00), +}; +static const mbedtls_mpi_uint secp521r1_T_17_X[] = { + MBEDTLS_BYTES_TO_T_UINT_8(0xB9, 0x95, 0xDF, 0x00, 0xD8, 0x21, 0xDE, 0x94), + MBEDTLS_BYTES_TO_T_UINT_8(0xF7, 0x47, 0x3C, 0xC3, 0xB2, 0x01, 0x53, 0x5D), + MBEDTLS_BYTES_TO_T_UINT_8(0x1E, 0x17, 0x43, 0x23, 0xBD, 0xCA, 0x71, 0xF2), + MBEDTLS_BYTES_TO_T_UINT_8(0x70, 0xBA, 0x0F, 0x4F, 0xDC, 0x41, 0x54, 0xBE), + MBEDTLS_BYTES_TO_T_UINT_8(0xD6, 0x39, 0x26, 0x70, 0x53, 0x32, 0x18, 0x11), + MBEDTLS_BYTES_TO_T_UINT_8(0x32, 0x46, 0x07, 0x97, 0x3A, 0x57, 0xE0, 0x01), + MBEDTLS_BYTES_TO_T_UINT_8(0xD6, 0x92, 0x4F, 0xCE, 0xDF, 0x25, 0x80, 0x26), + MBEDTLS_BYTES_TO_T_UINT_8(0x5B, 0x6F, 0x9A, 0x03, 0x05, 0x4B, 0xD1, 0x47), + MBEDTLS_BYTES_TO_T_UINT_8(0x5D, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00), +}; +static const mbedtls_mpi_uint secp521r1_T_17_Y[] = { + MBEDTLS_BYTES_TO_T_UINT_8(0x25, 0x01, 0x72, 0x30, 0x90, 0x17, 0x51, 0x20), + MBEDTLS_BYTES_TO_T_UINT_8(0x74, 0xFB, 0x41, 0x65, 0x5C, 0xB4, 0x2D, 0xEE), + MBEDTLS_BYTES_TO_T_UINT_8(0x66, 0xCD, 0xCD, 0xAA, 0x41, 0xCC, 0xBB, 0x07), + MBEDTLS_BYTES_TO_T_UINT_8(0xD4, 0xCE, 0x08, 0x0A, 0x63, 0xE9, 0xA2, 0xFF), + MBEDTLS_BYTES_TO_T_UINT_8(0x3D, 0xA8, 0x21, 0x7F, 0x7A, 0x5B, 0x9B, 0x81), + MBEDTLS_BYTES_TO_T_UINT_8(0x10, 0x6B, 0x89, 0x44, 0x0A, 0x7F, 0x85, 0x5F), + MBEDTLS_BYTES_TO_T_UINT_8(0x7D, 0xDE, 0x7C, 0x19, 0x5C, 0x65, 0x26, 0x61), + MBEDTLS_BYTES_TO_T_UINT_8(0xD7, 0xAC, 0x62, 0x29, 0x4A, 0xF1, 0xD0, 0x81), + MBEDTLS_BYTES_TO_T_UINT_8(0x38, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00), +}; +static const mbedtls_mpi_uint secp521r1_T_18_X[] = { + MBEDTLS_BYTES_TO_T_UINT_8(0x32, 0x00, 0x40, 0x87, 0xEB, 0xA9, 0x58, 0x56), + MBEDTLS_BYTES_TO_T_UINT_8(0xAF, 0x51, 0x0B, 0xFF, 0x56, 0x35, 0x51, 0xB3), + MBEDTLS_BYTES_TO_T_UINT_8(0x7B, 0xAC, 0x08, 0x94, 0x71, 0xDA, 0xEC, 0x99), + MBEDTLS_BYTES_TO_T_UINT_8(0x5F, 0x4D, 0xC5, 0x7B, 0x31, 0x8B, 0x8D, 0x5E), + MBEDTLS_BYTES_TO_T_UINT_8(0x15, 0x05, 0xF1, 0x3E, 0x9E, 0x8F, 0x17, 0x8F), + MBEDTLS_BYTES_TO_T_UINT_8(0xF0, 0x9C, 0x4B, 0x62, 0x94, 0xAD, 0x49, 0xFC), + MBEDTLS_BYTES_TO_T_UINT_8(0x0F, 0xC9, 0xC6, 0x8F, 0xFD, 0x33, 0x44, 0x34), + MBEDTLS_BYTES_TO_T_UINT_8(0x5F, 0x96, 0x17, 0x7F, 0x42, 0xBE, 0xF7, 0x0D), + MBEDTLS_BYTES_TO_T_UINT_8(0xD4, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00), +}; +static const mbedtls_mpi_uint secp521r1_T_18_Y[] = { + MBEDTLS_BYTES_TO_T_UINT_8(0xFB, 0x29, 0x39, 0x13, 0x08, 0x8D, 0x91, 0x47), + MBEDTLS_BYTES_TO_T_UINT_8(0xF6, 0x79, 0xF9, 0x2F, 0xA9, 0x0A, 0xCF, 0xD6), + MBEDTLS_BYTES_TO_T_UINT_8(0xAB, 0x87, 0x7A, 0xA3, 0x19, 0xAB, 0x55, 0xAD), + MBEDTLS_BYTES_TO_T_UINT_8(0xE8, 0x0B, 0x01, 0xC5, 0x56, 0x19, 0x9D, 0x9E), + MBEDTLS_BYTES_TO_T_UINT_8(0x19, 0xDE, 0x82, 0x3B, 0xEA, 0xD3, 0x0B, 0x8C), + MBEDTLS_BYTES_TO_T_UINT_8(0x65, 0x6B, 0xC7, 0xF3, 0x0F, 0x82, 0x87, 0x6C), + MBEDTLS_BYTES_TO_T_UINT_8(0xD8, 0x2E, 0x23, 0xF2, 0x39, 0x9D, 0x49, 0x70), + MBEDTLS_BYTES_TO_T_UINT_8(0x31, 0xDE, 0xAF, 0x7A, 0xEE, 0xB0, 0xDA, 0x70), + MBEDTLS_BYTES_TO_T_UINT_8(0x63, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00), +}; +static const mbedtls_mpi_uint secp521r1_T_19_X[] = { + MBEDTLS_BYTES_TO_T_UINT_8(0x76, 0x4E, 0x2A, 0x50, 0xFD, 0x8E, 0xC0, 0xEB), + MBEDTLS_BYTES_TO_T_UINT_8(0x52, 0x0F, 0x7C, 0x76, 0x63, 0xD8, 0x89, 0x45), + MBEDTLS_BYTES_TO_T_UINT_8(0xEC, 0x2D, 0xB9, 0x4E, 0xF4, 0xEE, 0x85, 0xCF), + MBEDTLS_BYTES_TO_T_UINT_8(0xC1, 0x95, 0x5C, 0x96, 0x5D, 0xAA, 0x59, 0x0B), + MBEDTLS_BYTES_TO_T_UINT_8(0xCA, 0xDB, 0xD2, 0x68, 0x8E, 0x5A, 0x94, 0x60), + MBEDTLS_BYTES_TO_T_UINT_8(0xD9, 0x02, 0xBF, 0x77, 0x9F, 0xB9, 0x4C, 0xC9), + MBEDTLS_BYTES_TO_T_UINT_8(0x2D, 0xDC, 0xC0, 0xCF, 0x81, 0x1E, 0xC4, 0x6C), + MBEDTLS_BYTES_TO_T_UINT_8(0x2B, 0xCC, 0x37, 0x86, 0xDC, 0xE2, 0x64, 0x72), + MBEDTLS_BYTES_TO_T_UINT_8(0xD5, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00), +}; +static const mbedtls_mpi_uint secp521r1_T_19_Y[] = { + MBEDTLS_BYTES_TO_T_UINT_8(0x2C, 0x30, 0xB1, 0x59, 0x20, 0x9D, 0x98, 0x28), + MBEDTLS_BYTES_TO_T_UINT_8(0x77, 0x0C, 0x9D, 0xF8, 0x20, 0xDC, 0x90, 0xBA), + MBEDTLS_BYTES_TO_T_UINT_8(0xB1, 0xA0, 0xF4, 0xE7, 0x3E, 0x9C, 0x9E, 0xA2), + MBEDTLS_BYTES_TO_T_UINT_8(0xB5, 0x25, 0xA2, 0xB0, 0x54, 0xCD, 0x2E, 0x33), + MBEDTLS_BYTES_TO_T_UINT_8(0xEA, 0xD9, 0x42, 0xB0, 0x80, 0xB0, 0xA3, 0x38), + MBEDTLS_BYTES_TO_T_UINT_8(0x9F, 0xFE, 0x9D, 0x8D, 0x40, 0xFF, 0x27, 0x6D), + MBEDTLS_BYTES_TO_T_UINT_8(0x3A, 0x9D, 0xA6, 0x88, 0x3A, 0x8B, 0x6F, 0x14), + MBEDTLS_BYTES_TO_T_UINT_8(0xB6, 0x39, 0xEE, 0x1F, 0x3F, 0xB1, 0x4F, 0x63), + MBEDTLS_BYTES_TO_T_UINT_8(0x31, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00), +}; +static const mbedtls_mpi_uint secp521r1_T_20_X[] = { + MBEDTLS_BYTES_TO_T_UINT_8(0x6D, 0xD7, 0x9E, 0xFF, 0xD2, 0x35, 0x67, 0x03), + MBEDTLS_BYTES_TO_T_UINT_8(0xCA, 0x4F, 0x15, 0x5D, 0xE3, 0xE8, 0x53, 0x86), + MBEDTLS_BYTES_TO_T_UINT_8(0x92, 0xF7, 0x24, 0x98, 0xA2, 0xCB, 0x11, 0x68), + MBEDTLS_BYTES_TO_T_UINT_8(0x06, 0x2E, 0x25, 0xE1, 0x94, 0xC5, 0xA3, 0x96), + MBEDTLS_BYTES_TO_T_UINT_8(0xE0, 0x82, 0x6E, 0xBA, 0xE7, 0x43, 0x25, 0xB0), + MBEDTLS_BYTES_TO_T_UINT_8(0x18, 0x65, 0xB4, 0x49, 0x73, 0x18, 0x35, 0x54), + MBEDTLS_BYTES_TO_T_UINT_8(0x59, 0x5B, 0xBC, 0x62, 0x86, 0x4C, 0xC1, 0xB7), + MBEDTLS_BYTES_TO_T_UINT_8(0x9B, 0xF2, 0x95, 0xA2, 0xBB, 0xA2, 0x35, 0x65), + MBEDTLS_BYTES_TO_T_UINT_8(0xBF, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00), +}; +static const mbedtls_mpi_uint secp521r1_T_20_Y[] = { + MBEDTLS_BYTES_TO_T_UINT_8(0x72, 0x59, 0x62, 0xB0, 0x4B, 0x1E, 0xB4, 0xD8), + MBEDTLS_BYTES_TO_T_UINT_8(0x0D, 0x55, 0xCE, 0xB0, 0x69, 0xBA, 0x63, 0x10), + MBEDTLS_BYTES_TO_T_UINT_8(0x6E, 0x69, 0x86, 0xDB, 0x34, 0x7D, 0x68, 0x64), + MBEDTLS_BYTES_TO_T_UINT_8(0xDA, 0x06, 0xCA, 0x55, 0x44, 0x36, 0x2B, 0xBA), + MBEDTLS_BYTES_TO_T_UINT_8(0x6C, 0xD4, 0xC4, 0x3D, 0xCD, 0x9E, 0x69, 0xA4), + MBEDTLS_BYTES_TO_T_UINT_8(0x3F, 0x44, 0xE4, 0xBF, 0x31, 0xE6, 0x40, 0x9F), + MBEDTLS_BYTES_TO_T_UINT_8(0x7E, 0x4F, 0xFA, 0x75, 0xE3, 0xFB, 0x97, 0x0E), + MBEDTLS_BYTES_TO_T_UINT_8(0x08, 0xC0, 0xBD, 0x1C, 0x48, 0xB0, 0x26, 0xD0), + MBEDTLS_BYTES_TO_T_UINT_8(0xD2, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00), +}; +static const mbedtls_mpi_uint secp521r1_T_21_X[] = { + MBEDTLS_BYTES_TO_T_UINT_8(0x1C, 0x7B, 0x32, 0xFA, 0xF2, 0x6D, 0x84, 0x8E), + MBEDTLS_BYTES_TO_T_UINT_8(0xA0, 0x21, 0x03, 0x1D, 0x0D, 0x22, 0x55, 0x67), + MBEDTLS_BYTES_TO_T_UINT_8(0x18, 0xF9, 0x42, 0x03, 0x9C, 0xC2, 0xCB, 0xBA), + MBEDTLS_BYTES_TO_T_UINT_8(0xF8, 0xA1, 0x96, 0xD9, 0x9D, 0x11, 0x6F, 0xBE), + MBEDTLS_BYTES_TO_T_UINT_8(0xFF, 0x40, 0x57, 0xEB, 0x40, 0x2D, 0xC0, 0x11), + MBEDTLS_BYTES_TO_T_UINT_8(0x2F, 0x96, 0xBB, 0x4F, 0x2F, 0x23, 0xA8, 0x28), + MBEDTLS_BYTES_TO_T_UINT_8(0x3A, 0x29, 0x85, 0x21, 0xA5, 0x50, 0x62, 0x06), + MBEDTLS_BYTES_TO_T_UINT_8(0xC9, 0x7D, 0x92, 0xCF, 0x87, 0x0C, 0x22, 0xF9), + MBEDTLS_BYTES_TO_T_UINT_8(0xC9, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00), +}; +static const mbedtls_mpi_uint secp521r1_T_21_Y[] = { + MBEDTLS_BYTES_TO_T_UINT_8(0x5A, 0x0E, 0xA5, 0x32, 0x5B, 0xDF, 0x9C, 0xD5), + MBEDTLS_BYTES_TO_T_UINT_8(0x27, 0x96, 0x37, 0x2C, 0x88, 0x35, 0x30, 0xA1), + MBEDTLS_BYTES_TO_T_UINT_8(0x40, 0xB4, 0x69, 0xFF, 0xEB, 0xC6, 0x94, 0x08), + MBEDTLS_BYTES_TO_T_UINT_8(0xC9, 0x55, 0x60, 0xAD, 0xAA, 0x58, 0x14, 0x88), + MBEDTLS_BYTES_TO_T_UINT_8(0x3C, 0xFF, 0xF2, 0xB2, 0xD5, 0xA7, 0xD9, 0x27), + MBEDTLS_BYTES_TO_T_UINT_8(0x2D, 0xAE, 0x54, 0xD2, 0x60, 0x31, 0xF3, 0x15), + MBEDTLS_BYTES_TO_T_UINT_8(0xBB, 0x92, 0x83, 0xE3, 0xF1, 0x42, 0x83, 0x6E), + MBEDTLS_BYTES_TO_T_UINT_8(0x49, 0xD2, 0xC8, 0xB7, 0x76, 0x45, 0x7F, 0x7D), + MBEDTLS_BYTES_TO_T_UINT_8(0x04, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00), +}; +static const mbedtls_mpi_uint secp521r1_T_22_X[] = { + MBEDTLS_BYTES_TO_T_UINT_8(0x4A, 0x11, 0xA4, 0xFB, 0x7A, 0x01, 0xBC, 0xC8), + MBEDTLS_BYTES_TO_T_UINT_8(0xCD, 0x27, 0x73, 0x8D, 0x02, 0x91, 0x27, 0x8E), + MBEDTLS_BYTES_TO_T_UINT_8(0xA4, 0x62, 0xF6, 0xDD, 0x6B, 0xFA, 0x5B, 0xB9), + MBEDTLS_BYTES_TO_T_UINT_8(0xEF, 0xCA, 0xA2, 0x44, 0x2C, 0xF0, 0x28, 0xD8), + MBEDTLS_BYTES_TO_T_UINT_8(0x3C, 0xF1, 0x7A, 0xA2, 0x42, 0x4C, 0x50, 0xC6), + MBEDTLS_BYTES_TO_T_UINT_8(0x2D, 0x83, 0x3E, 0x50, 0xAB, 0x9C, 0xF7, 0x67), + MBEDTLS_BYTES_TO_T_UINT_8(0x1D, 0xED, 0x78, 0xCB, 0x76, 0x69, 0xDA, 0x42), + MBEDTLS_BYTES_TO_T_UINT_8(0xDB, 0x01, 0x1E, 0x43, 0x27, 0x47, 0x6E, 0xDA), + MBEDTLS_BYTES_TO_T_UINT_8(0x94, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00), +}; +static const mbedtls_mpi_uint secp521r1_T_22_Y[] = { + MBEDTLS_BYTES_TO_T_UINT_8(0xD3, 0x4F, 0x54, 0xB9, 0x3E, 0xBD, 0xD5, 0x44), + MBEDTLS_BYTES_TO_T_UINT_8(0xC9, 0x35, 0x40, 0x69, 0x7F, 0x74, 0x9D, 0x32), + MBEDTLS_BYTES_TO_T_UINT_8(0x5A, 0x06, 0x6F, 0x67, 0x68, 0x2B, 0x4D, 0x10), + MBEDTLS_BYTES_TO_T_UINT_8(0xC6, 0x65, 0x41, 0xFC, 0x7C, 0x1E, 0xE8, 0xC8), + MBEDTLS_BYTES_TO_T_UINT_8(0xF2, 0x79, 0x37, 0xAF, 0xFD, 0xD2, 0xDA, 0x4C), + MBEDTLS_BYTES_TO_T_UINT_8(0x33, 0xA8, 0x69, 0x56, 0x62, 0xA4, 0xE4, 0xA3), + MBEDTLS_BYTES_TO_T_UINT_8(0x42, 0x71, 0x73, 0x21, 0x8A, 0x17, 0x81, 0xA2), + MBEDTLS_BYTES_TO_T_UINT_8(0x14, 0x55, 0x8F, 0x7B, 0xB8, 0xAF, 0xF7, 0x86), + MBEDTLS_BYTES_TO_T_UINT_8(0xAA, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00), +}; +static const mbedtls_mpi_uint secp521r1_T_23_X[] = { + MBEDTLS_BYTES_TO_T_UINT_8(0x4B, 0xD1, 0xBD, 0xBE, 0x8C, 0xBC, 0x60, 0x6E), + MBEDTLS_BYTES_TO_T_UINT_8(0x62, 0xA6, 0x57, 0x8C, 0xAE, 0x5C, 0x19, 0xFE), + MBEDTLS_BYTES_TO_T_UINT_8(0x7A, 0x43, 0xE4, 0xD9, 0xD8, 0x7B, 0xE7, 0x41), + MBEDTLS_BYTES_TO_T_UINT_8(0xED, 0xB9, 0xE4, 0x85, 0x7C, 0x2E, 0xFC, 0x20), + MBEDTLS_BYTES_TO_T_UINT_8(0x02, 0x2E, 0x01, 0x2A, 0x6D, 0x56, 0xBE, 0x97), + MBEDTLS_BYTES_TO_T_UINT_8(0x6A, 0x0C, 0x25, 0x9B, 0xAE, 0x86, 0x37, 0x43), + MBEDTLS_BYTES_TO_T_UINT_8(0x4A, 0x22, 0xB3, 0xCB, 0x99, 0x66, 0xB7, 0x9E), + MBEDTLS_BYTES_TO_T_UINT_8(0x56, 0xF7, 0x90, 0xF0, 0x1B, 0x09, 0x27, 0xF7), + MBEDTLS_BYTES_TO_T_UINT_8(0xC8, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00), +}; +static const mbedtls_mpi_uint secp521r1_T_23_Y[] = { + MBEDTLS_BYTES_TO_T_UINT_8(0x1C, 0x16, 0x08, 0xEF, 0x39, 0x64, 0x49, 0x31), + MBEDTLS_BYTES_TO_T_UINT_8(0x08, 0xA0, 0xE3, 0x97, 0xA9, 0x07, 0x54, 0x26), + MBEDTLS_BYTES_TO_T_UINT_8(0xCD, 0xFF, 0xE2, 0x00, 0x07, 0x21, 0x88, 0x20), + MBEDTLS_BYTES_TO_T_UINT_8(0x16, 0xFD, 0x59, 0x53, 0x05, 0x6C, 0x42, 0x27), + MBEDTLS_BYTES_TO_T_UINT_8(0x8F, 0xF7, 0x39, 0x5C, 0x82, 0x36, 0xE8, 0x03), + MBEDTLS_BYTES_TO_T_UINT_8(0x2E, 0x83, 0xA8, 0xE2, 0xA8, 0x43, 0x07, 0x38), + MBEDTLS_BYTES_TO_T_UINT_8(0xE6, 0xAF, 0x2B, 0x79, 0xED, 0xD8, 0x39, 0x87), + MBEDTLS_BYTES_TO_T_UINT_8(0x15, 0x20, 0x91, 0x7A, 0xC4, 0x07, 0xEF, 0x6C), + MBEDTLS_BYTES_TO_T_UINT_8(0x28, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00), +}; +static const mbedtls_mpi_uint secp521r1_T_24_X[] = { + MBEDTLS_BYTES_TO_T_UINT_8(0x6A, 0x10, 0x2F, 0xAA, 0x0C, 0x94, 0x0E, 0x5A), + MBEDTLS_BYTES_TO_T_UINT_8(0xB7, 0x81, 0x87, 0x41, 0x23, 0xEB, 0x55, 0x7C), + MBEDTLS_BYTES_TO_T_UINT_8(0xB8, 0x53, 0xCC, 0x79, 0xB6, 0xEB, 0x6C, 0xCC), + MBEDTLS_BYTES_TO_T_UINT_8(0xF4, 0x77, 0x73, 0x9D, 0xFC, 0x64, 0x6F, 0x7F), + MBEDTLS_BYTES_TO_T_UINT_8(0x3C, 0x40, 0xE3, 0x6D, 0x1C, 0x16, 0x71, 0x15), + MBEDTLS_BYTES_TO_T_UINT_8(0x5A, 0xF4, 0x1B, 0xFF, 0x1C, 0x2F, 0xA5, 0xD7), + MBEDTLS_BYTES_TO_T_UINT_8(0x06, 0x0E, 0x0B, 0x11, 0xF4, 0x8D, 0x93, 0xAF), + MBEDTLS_BYTES_TO_T_UINT_8(0x58, 0xC5, 0x64, 0x6F, 0x24, 0x19, 0xF2, 0x9B), + MBEDTLS_BYTES_TO_T_UINT_8(0x1C, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00), +}; +static const mbedtls_mpi_uint secp521r1_T_24_Y[] = { + MBEDTLS_BYTES_TO_T_UINT_8(0x52, 0xB3, 0xAF, 0xA5, 0x0E, 0x4F, 0x5E, 0xE1), + MBEDTLS_BYTES_TO_T_UINT_8(0x0F, 0x77, 0xCA, 0xF2, 0x6D, 0xC5, 0xF6, 0x9F), + MBEDTLS_BYTES_TO_T_UINT_8(0x90, 0x18, 0x8E, 0x33, 0x68, 0x6C, 0xE8, 0xE0), + MBEDTLS_BYTES_TO_T_UINT_8(0xFC, 0x8B, 0x80, 0x90, 0x19, 0x7F, 0x90, 0x96), + MBEDTLS_BYTES_TO_T_UINT_8(0x5B, 0x80, 0x6B, 0x68, 0xE2, 0x7D, 0xD4, 0xD0), + MBEDTLS_BYTES_TO_T_UINT_8(0x2A, 0xC1, 0x67, 0xB3, 0x72, 0xCB, 0xBF, 0x2F), + MBEDTLS_BYTES_TO_T_UINT_8(0x4F, 0xD5, 0xD3, 0x1D, 0x14, 0x58, 0x0A, 0x80), + MBEDTLS_BYTES_TO_T_UINT_8(0x79, 0x7A, 0x65, 0x98, 0xB3, 0x07, 0x4B, 0x2F), + MBEDTLS_BYTES_TO_T_UINT_8(0xF3, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00), +}; +static const mbedtls_mpi_uint secp521r1_T_25_X[] = { + MBEDTLS_BYTES_TO_T_UINT_8(0x2A, 0x87, 0x0F, 0x5F, 0xCF, 0xA2, 0x01, 0x08), + MBEDTLS_BYTES_TO_T_UINT_8(0x0C, 0xC9, 0xC8, 0x6E, 0x35, 0x87, 0xA5, 0x67), + MBEDTLS_BYTES_TO_T_UINT_8(0x94, 0x3E, 0x91, 0xA0, 0xAB, 0x24, 0x1E, 0xF2), + MBEDTLS_BYTES_TO_T_UINT_8(0xB9, 0xBC, 0x02, 0x35, 0x70, 0xC1, 0x5F, 0x98), + MBEDTLS_BYTES_TO_T_UINT_8(0x26, 0x59, 0xA0, 0x50, 0x04, 0x80, 0x52, 0x85), + MBEDTLS_BYTES_TO_T_UINT_8(0xF8, 0x56, 0x6E, 0x42, 0x8F, 0x8C, 0x91, 0x65), + MBEDTLS_BYTES_TO_T_UINT_8(0xAC, 0xA2, 0xCB, 0xA5, 0xDE, 0x14, 0x24, 0x38), + MBEDTLS_BYTES_TO_T_UINT_8(0x00, 0xCB, 0x74, 0x28, 0xE6, 0xA7, 0xE7, 0xC3), + MBEDTLS_BYTES_TO_T_UINT_8(0x5F, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00), +}; +static const mbedtls_mpi_uint secp521r1_T_25_Y[] = { + MBEDTLS_BYTES_TO_T_UINT_8(0x35, 0x73, 0xA8, 0x8F, 0x9E, 0x0E, 0x63, 0x96), + MBEDTLS_BYTES_TO_T_UINT_8(0xC8, 0x1B, 0x77, 0xC7, 0xC1, 0x38, 0xF9, 0xDC), + MBEDTLS_BYTES_TO_T_UINT_8(0xD8, 0x3C, 0xCF, 0xA8, 0x7A, 0xD7, 0xF3, 0xC4), + MBEDTLS_BYTES_TO_T_UINT_8(0xDD, 0x5F, 0x9A, 0xC9, 0xAD, 0xE9, 0x1A, 0x93), + MBEDTLS_BYTES_TO_T_UINT_8(0xFC, 0xCF, 0x2B, 0x5E, 0xD5, 0x81, 0x95, 0xA8), + MBEDTLS_BYTES_TO_T_UINT_8(0x19, 0x88, 0x75, 0x29, 0x1F, 0xC7, 0xC7, 0xD0), + MBEDTLS_BYTES_TO_T_UINT_8(0xD8, 0xA9, 0x5A, 0x4D, 0x63, 0x95, 0xF9, 0x4E), + MBEDTLS_BYTES_TO_T_UINT_8(0xEB, 0xCD, 0x04, 0x8F, 0xCD, 0x91, 0xDE, 0xC6), + MBEDTLS_BYTES_TO_T_UINT_8(0x71, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00), +}; +static const mbedtls_mpi_uint secp521r1_T_26_X[] = { + MBEDTLS_BYTES_TO_T_UINT_8(0x88, 0xD4, 0xFD, 0x25, 0x11, 0x99, 0x6E, 0xEA), + MBEDTLS_BYTES_TO_T_UINT_8(0xB0, 0x83, 0x01, 0x3D, 0xFB, 0x56, 0xA5, 0x4E), + MBEDTLS_BYTES_TO_T_UINT_8(0xC2, 0x3A, 0xDC, 0x74, 0xC2, 0xD7, 0xCF, 0xE8), + MBEDTLS_BYTES_TO_T_UINT_8(0x8F, 0xBD, 0xF1, 0xDD, 0xA3, 0x07, 0x03, 0xE2), + MBEDTLS_BYTES_TO_T_UINT_8(0x7B, 0xBE, 0xE9, 0x2E, 0x58, 0x84, 0x66, 0xFC), + MBEDTLS_BYTES_TO_T_UINT_8(0x71, 0x20, 0x78, 0x37, 0x79, 0x0B, 0xA6, 0x64), + MBEDTLS_BYTES_TO_T_UINT_8(0xE3, 0xF2, 0xAC, 0x65, 0xC8, 0xC9, 0x2F, 0x61), + MBEDTLS_BYTES_TO_T_UINT_8(0x26, 0x93, 0xE5, 0x0D, 0x0C, 0xC6, 0xB8, 0xCB), + MBEDTLS_BYTES_TO_T_UINT_8(0x9C, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00), +}; +static const mbedtls_mpi_uint secp521r1_T_26_Y[] = { + MBEDTLS_BYTES_TO_T_UINT_8(0x69, 0xAD, 0x5C, 0x19, 0x12, 0x61, 0x0E, 0x25), + MBEDTLS_BYTES_TO_T_UINT_8(0x39, 0x4F, 0x0B, 0x1F, 0x49, 0x7E, 0xCD, 0x81), + MBEDTLS_BYTES_TO_T_UINT_8(0x46, 0x2E, 0x30, 0x61, 0xDB, 0x08, 0x68, 0x9B), + MBEDTLS_BYTES_TO_T_UINT_8(0x41, 0x78, 0xAF, 0xB3, 0x08, 0xC1, 0x69, 0xE5), + MBEDTLS_BYTES_TO_T_UINT_8(0xC4, 0x5F, 0x5D, 0xC1, 0x57, 0x6F, 0xD8, 0x34), + MBEDTLS_BYTES_TO_T_UINT_8(0x38, 0xD3, 0x6A, 0xF7, 0xFD, 0x86, 0xE5, 0xB3), + MBEDTLS_BYTES_TO_T_UINT_8(0xA8, 0x63, 0xBD, 0x70, 0x7B, 0x47, 0xE8, 0x6D), + MBEDTLS_BYTES_TO_T_UINT_8(0x18, 0x62, 0xC8, 0x7E, 0x9D, 0x11, 0x2B, 0xA5), + MBEDTLS_BYTES_TO_T_UINT_8(0xB6, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00), +}; +static const mbedtls_mpi_uint secp521r1_T_27_X[] = { + MBEDTLS_BYTES_TO_T_UINT_8(0xE2, 0x84, 0xFD, 0xD5, 0x9A, 0x56, 0x7F, 0x5C), + MBEDTLS_BYTES_TO_T_UINT_8(0x7C, 0xBB, 0xA4, 0x6F, 0x12, 0x6E, 0x4D, 0xF8), + MBEDTLS_BYTES_TO_T_UINT_8(0x1D, 0x08, 0xA1, 0x82, 0x9C, 0x62, 0x74, 0x7B), + MBEDTLS_BYTES_TO_T_UINT_8(0x9E, 0x58, 0x22, 0x05, 0x1D, 0x15, 0x35, 0x79), + MBEDTLS_BYTES_TO_T_UINT_8(0x9A, 0x88, 0xCF, 0x5C, 0x05, 0x78, 0xFB, 0x94), + MBEDTLS_BYTES_TO_T_UINT_8(0xAC, 0x6B, 0x2F, 0x79, 0x09, 0x73, 0x67, 0xEC), + MBEDTLS_BYTES_TO_T_UINT_8(0xD8, 0xA0, 0x80, 0xD8, 0xE8, 0xEC, 0xFB, 0x42), + MBEDTLS_BYTES_TO_T_UINT_8(0xF5, 0xE7, 0x0B, 0xB7, 0x81, 0x48, 0x7B, 0xD9), + MBEDTLS_BYTES_TO_T_UINT_8(0xE3, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00), +}; +static const mbedtls_mpi_uint secp521r1_T_27_Y[] = { + MBEDTLS_BYTES_TO_T_UINT_8(0xE8, 0x53, 0xA9, 0xED, 0x61, 0x92, 0xD7, 0x85), + MBEDTLS_BYTES_TO_T_UINT_8(0x26, 0x49, 0xD9, 0x5D, 0x9B, 0x4E, 0x89, 0x35), + MBEDTLS_BYTES_TO_T_UINT_8(0xB8, 0x12, 0xEB, 0x9A, 0xC9, 0xCB, 0xC1, 0x95), + MBEDTLS_BYTES_TO_T_UINT_8(0x35, 0xDC, 0x95, 0x16, 0xFE, 0x29, 0x70, 0x01), + MBEDTLS_BYTES_TO_T_UINT_8(0x64, 0x33, 0xB1, 0xD6, 0x78, 0xB9, 0xE2, 0x36), + MBEDTLS_BYTES_TO_T_UINT_8(0x34, 0xCE, 0x88, 0xC3, 0xFD, 0x7A, 0x6B, 0xB8), + MBEDTLS_BYTES_TO_T_UINT_8(0x40, 0x1E, 0x50, 0x1E, 0xAF, 0xB1, 0x25, 0x2D), + MBEDTLS_BYTES_TO_T_UINT_8(0xC1, 0xE7, 0xD7, 0xD5, 0xBD, 0x7A, 0x12, 0xF9), + MBEDTLS_BYTES_TO_T_UINT_8(0x31, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00), +}; +static const mbedtls_mpi_uint secp521r1_T_28_X[] = { + MBEDTLS_BYTES_TO_T_UINT_8(0x22, 0xAA, 0xA2, 0x80, 0x5D, 0x8F, 0xCD, 0xC8), + MBEDTLS_BYTES_TO_T_UINT_8(0x48, 0x39, 0x79, 0x64, 0xA1, 0x67, 0x3C, 0xB7), + MBEDTLS_BYTES_TO_T_UINT_8(0x3D, 0xC7, 0x49, 0xFF, 0x7F, 0xAC, 0xAB, 0x55), + MBEDTLS_BYTES_TO_T_UINT_8(0x81, 0x54, 0x3E, 0x83, 0xF0, 0x3D, 0xBC, 0xB5), + MBEDTLS_BYTES_TO_T_UINT_8(0x87, 0x92, 0x4A, 0x38, 0x42, 0x8A, 0xAB, 0xF6), + MBEDTLS_BYTES_TO_T_UINT_8(0xE7, 0x0B, 0x4F, 0xEE, 0x9E, 0x92, 0xA5, 0xBE), + MBEDTLS_BYTES_TO_T_UINT_8(0xBA, 0xDD, 0x19, 0x96, 0xF2, 0xF0, 0x6B, 0x2E), + MBEDTLS_BYTES_TO_T_UINT_8(0xBE, 0xFC, 0xDD, 0xB2, 0x8A, 0xE5, 0x4C, 0x22), + MBEDTLS_BYTES_TO_T_UINT_8(0xD4, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00), +}; +static const mbedtls_mpi_uint secp521r1_T_28_Y[] = { + MBEDTLS_BYTES_TO_T_UINT_8(0xB7, 0x06, 0x49, 0xAC, 0x99, 0x7E, 0xF8, 0x12), + MBEDTLS_BYTES_TO_T_UINT_8(0x76, 0xC8, 0x01, 0x51, 0xEA, 0xF6, 0x52, 0xE7), + MBEDTLS_BYTES_TO_T_UINT_8(0x43, 0x89, 0x66, 0x2B, 0x1F, 0x9B, 0x2A, 0xA3), + MBEDTLS_BYTES_TO_T_UINT_8(0xDF, 0x0F, 0x95, 0x07, 0x2B, 0x6C, 0x6E, 0x9E), + MBEDTLS_BYTES_TO_T_UINT_8(0x24, 0xC3, 0xB4, 0xBB, 0x91, 0x1F, 0xA3, 0x72), + MBEDTLS_BYTES_TO_T_UINT_8(0x5F, 0x6E, 0x54, 0x28, 0x7B, 0x9C, 0x79, 0x2E), + MBEDTLS_BYTES_TO_T_UINT_8(0x03, 0x45, 0xFF, 0xA6, 0xDA, 0xA2, 0x83, 0x71), + MBEDTLS_BYTES_TO_T_UINT_8(0xEB, 0xDE, 0x8F, 0x17, 0x37, 0x82, 0xCB, 0xE2), + MBEDTLS_BYTES_TO_T_UINT_8(0x30, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00), +}; +static const mbedtls_mpi_uint secp521r1_T_29_X[] = { + MBEDTLS_BYTES_TO_T_UINT_8(0xD8, 0x94, 0x3F, 0x26, 0xC9, 0x1D, 0xD9, 0xAE), + MBEDTLS_BYTES_TO_T_UINT_8(0x09, 0x97, 0x28, 0x20, 0xCD, 0xC1, 0xF3, 0x40), + MBEDTLS_BYTES_TO_T_UINT_8(0x95, 0xC9, 0xB5, 0x60, 0x9B, 0x1E, 0xDC, 0x74), + MBEDTLS_BYTES_TO_T_UINT_8(0x5B, 0xB9, 0x5B, 0x7D, 0xA0, 0xB2, 0x8C, 0xF0), + MBEDTLS_BYTES_TO_T_UINT_8(0x33, 0xD1, 0x42, 0xE6, 0x39, 0x33, 0x6D, 0xBB), + MBEDTLS_BYTES_TO_T_UINT_8(0x5D, 0xC0, 0xFC, 0xD2, 0x14, 0x5D, 0x3E, 0x3C), + MBEDTLS_BYTES_TO_T_UINT_8(0x78, 0x4A, 0x3E, 0x40, 0x16, 0x93, 0x15, 0xCF), + MBEDTLS_BYTES_TO_T_UINT_8(0xFA, 0x24, 0xC1, 0x27, 0x27, 0xE5, 0x4B, 0xD8), + MBEDTLS_BYTES_TO_T_UINT_8(0xD4, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00), +}; +static const mbedtls_mpi_uint secp521r1_T_29_Y[] = { + MBEDTLS_BYTES_TO_T_UINT_8(0x1D, 0x50, 0xD8, 0xBC, 0xC1, 0x46, 0x22, 0xBB), + MBEDTLS_BYTES_TO_T_UINT_8(0xAD, 0x0E, 0x60, 0xA1, 0xB3, 0x50, 0xD4, 0x86), + MBEDTLS_BYTES_TO_T_UINT_8(0x80, 0xB1, 0x26, 0xB6, 0x6D, 0x47, 0x5A, 0x6F), + MBEDTLS_BYTES_TO_T_UINT_8(0x45, 0xAC, 0x11, 0x35, 0x3E, 0xB9, 0xF4, 0x01), + MBEDTLS_BYTES_TO_T_UINT_8(0x58, 0x97, 0xFA, 0xBB, 0x6B, 0x39, 0x13, 0xD8), + MBEDTLS_BYTES_TO_T_UINT_8(0x15, 0x7B, 0x34, 0x12, 0x75, 0x8E, 0x9B, 0xC6), + MBEDTLS_BYTES_TO_T_UINT_8(0x2C, 0x9E, 0xCD, 0x29, 0xB6, 0xEF, 0x8D, 0x10), + MBEDTLS_BYTES_TO_T_UINT_8(0x47, 0xAC, 0xE9, 0x25, 0x27, 0xBB, 0x78, 0x47), + MBEDTLS_BYTES_TO_T_UINT_8(0x2F, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00), +}; +static const mbedtls_mpi_uint secp521r1_T_30_X[] = { + MBEDTLS_BYTES_TO_T_UINT_8(0x30, 0x7A, 0xA8, 0xD3, 0xE3, 0x66, 0xE5, 0x66), + MBEDTLS_BYTES_TO_T_UINT_8(0x2F, 0x4C, 0xC4, 0x2C, 0x76, 0x81, 0x50, 0x32), + MBEDTLS_BYTES_TO_T_UINT_8(0xEE, 0x71, 0x08, 0xB8, 0x52, 0x7C, 0xAF, 0xDC), + MBEDTLS_BYTES_TO_T_UINT_8(0x45, 0x59, 0x24, 0xDD, 0xFB, 0x2F, 0xD0, 0xDA), + MBEDTLS_BYTES_TO_T_UINT_8(0xB7, 0xCD, 0x56, 0xE9, 0xAC, 0x91, 0xE6, 0xB9), + MBEDTLS_BYTES_TO_T_UINT_8(0xE5, 0x64, 0x20, 0xC6, 0x9F, 0xE4, 0xEF, 0xDF), + MBEDTLS_BYTES_TO_T_UINT_8(0x6D, 0x2C, 0x8F, 0x8C, 0x97, 0xF6, 0x22, 0xC3), + MBEDTLS_BYTES_TO_T_UINT_8(0xAC, 0xF4, 0x88, 0xAA, 0xA8, 0xD7, 0xA5, 0x68), + MBEDTLS_BYTES_TO_T_UINT_8(0xDE, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00), +}; +static const mbedtls_mpi_uint secp521r1_T_30_Y[] = { + MBEDTLS_BYTES_TO_T_UINT_8(0x21, 0x6C, 0xAE, 0x83, 0xB1, 0x55, 0x55, 0xEE), + MBEDTLS_BYTES_TO_T_UINT_8(0xB0, 0x67, 0x84, 0x47, 0x7C, 0x83, 0x5C, 0x89), + MBEDTLS_BYTES_TO_T_UINT_8(0x5B, 0x10, 0x4D, 0xDD, 0x30, 0x60, 0xB0, 0xE6), + MBEDTLS_BYTES_TO_T_UINT_8(0x59, 0xA7, 0x36, 0x76, 0x24, 0x32, 0x9F, 0x9D), + MBEDTLS_BYTES_TO_T_UINT_8(0xDD, 0x42, 0x81, 0xFB, 0xA4, 0x2E, 0x13, 0x68), + MBEDTLS_BYTES_TO_T_UINT_8(0x87, 0x94, 0x91, 0xFF, 0x99, 0xA0, 0x09, 0x61), + MBEDTLS_BYTES_TO_T_UINT_8(0x5D, 0x83, 0xA1, 0x76, 0xAF, 0x37, 0x5C, 0x77), + MBEDTLS_BYTES_TO_T_UINT_8(0x1E, 0xA8, 0x04, 0x86, 0xC4, 0xA9, 0x79, 0x42), + MBEDTLS_BYTES_TO_T_UINT_8(0x93, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00), +}; +static const mbedtls_mpi_uint secp521r1_T_31_X[] = { + MBEDTLS_BYTES_TO_T_UINT_8(0xB6, 0x8C, 0xC2, 0x34, 0xFB, 0x83, 0x28, 0x27), + MBEDTLS_BYTES_TO_T_UINT_8(0xA4, 0x03, 0x7D, 0x5E, 0x9E, 0x0E, 0xB0, 0x22), + MBEDTLS_BYTES_TO_T_UINT_8(0xA2, 0x02, 0x46, 0x7F, 0xB9, 0xAC, 0xBB, 0x23), + MBEDTLS_BYTES_TO_T_UINT_8(0x06, 0xED, 0x48, 0xC2, 0x96, 0x4D, 0x56, 0x27), + MBEDTLS_BYTES_TO_T_UINT_8(0x44, 0xB5, 0xC5, 0xD1, 0xE6, 0x1C, 0x7E, 0x9B), + MBEDTLS_BYTES_TO_T_UINT_8(0x92, 0x2E, 0x18, 0x71, 0x2D, 0x7B, 0xD7, 0xB3), + MBEDTLS_BYTES_TO_T_UINT_8(0xAB, 0x46, 0x9D, 0xDE, 0xAA, 0x78, 0x8E, 0xB1), + MBEDTLS_BYTES_TO_T_UINT_8(0x4D, 0xD7, 0x69, 0x2E, 0xE1, 0xD9, 0x48, 0xDE), + MBEDTLS_BYTES_TO_T_UINT_8(0xFB, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00), +}; +static const mbedtls_mpi_uint secp521r1_T_31_Y[] = { + MBEDTLS_BYTES_TO_T_UINT_8(0xAF, 0xFF, 0x9E, 0x09, 0x22, 0x22, 0xE6, 0x8D), + MBEDTLS_BYTES_TO_T_UINT_8(0x6C, 0x14, 0x28, 0x13, 0x1B, 0x62, 0x12, 0x22), + MBEDTLS_BYTES_TO_T_UINT_8(0xCC, 0x7F, 0x67, 0x03, 0xB0, 0xC0, 0xF3, 0x05), + MBEDTLS_BYTES_TO_T_UINT_8(0xC0, 0xC3, 0x0F, 0xFB, 0x25, 0x48, 0x3E, 0xF4), + MBEDTLS_BYTES_TO_T_UINT_8(0x0B, 0x6E, 0x53, 0x98, 0x36, 0xB3, 0xD3, 0x94), + MBEDTLS_BYTES_TO_T_UINT_8(0xEB, 0x81, 0x54, 0x22, 0xA4, 0xCC, 0xC1, 0x22), + MBEDTLS_BYTES_TO_T_UINT_8(0xF5, 0xBA, 0xFC, 0xA9, 0xDF, 0x68, 0x86, 0x2B), + MBEDTLS_BYTES_TO_T_UINT_8(0x71, 0x92, 0x0E, 0xC3, 0xF2, 0x58, 0xE8, 0x51), + MBEDTLS_BYTES_TO_T_UINT_8(0xE9, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00), +}; +static const mbedtls_ecp_point secp521r1_T[32] = { + ECP_POINT_INIT_XY_Z1(secp521r1_T_0_X, secp521r1_T_0_Y), + ECP_POINT_INIT_XY_Z0(secp521r1_T_1_X, secp521r1_T_1_Y), + ECP_POINT_INIT_XY_Z0(secp521r1_T_2_X, secp521r1_T_2_Y), + ECP_POINT_INIT_XY_Z0(secp521r1_T_3_X, secp521r1_T_3_Y), + ECP_POINT_INIT_XY_Z0(secp521r1_T_4_X, secp521r1_T_4_Y), + ECP_POINT_INIT_XY_Z0(secp521r1_T_5_X, secp521r1_T_5_Y), + ECP_POINT_INIT_XY_Z0(secp521r1_T_6_X, secp521r1_T_6_Y), + ECP_POINT_INIT_XY_Z0(secp521r1_T_7_X, secp521r1_T_7_Y), + ECP_POINT_INIT_XY_Z0(secp521r1_T_8_X, secp521r1_T_8_Y), + ECP_POINT_INIT_XY_Z0(secp521r1_T_9_X, secp521r1_T_9_Y), + ECP_POINT_INIT_XY_Z0(secp521r1_T_10_X, secp521r1_T_10_Y), + ECP_POINT_INIT_XY_Z0(secp521r1_T_11_X, secp521r1_T_11_Y), + ECP_POINT_INIT_XY_Z0(secp521r1_T_12_X, secp521r1_T_12_Y), + ECP_POINT_INIT_XY_Z0(secp521r1_T_13_X, secp521r1_T_13_Y), + ECP_POINT_INIT_XY_Z0(secp521r1_T_14_X, secp521r1_T_14_Y), + ECP_POINT_INIT_XY_Z0(secp521r1_T_15_X, secp521r1_T_15_Y), + ECP_POINT_INIT_XY_Z0(secp521r1_T_16_X, secp521r1_T_16_Y), + ECP_POINT_INIT_XY_Z0(secp521r1_T_17_X, secp521r1_T_17_Y), + ECP_POINT_INIT_XY_Z0(secp521r1_T_18_X, secp521r1_T_18_Y), + ECP_POINT_INIT_XY_Z0(secp521r1_T_19_X, secp521r1_T_19_Y), + ECP_POINT_INIT_XY_Z0(secp521r1_T_20_X, secp521r1_T_20_Y), + ECP_POINT_INIT_XY_Z0(secp521r1_T_21_X, secp521r1_T_21_Y), + ECP_POINT_INIT_XY_Z0(secp521r1_T_22_X, secp521r1_T_22_Y), + ECP_POINT_INIT_XY_Z0(secp521r1_T_23_X, secp521r1_T_23_Y), + ECP_POINT_INIT_XY_Z0(secp521r1_T_24_X, secp521r1_T_24_Y), + ECP_POINT_INIT_XY_Z0(secp521r1_T_25_X, secp521r1_T_25_Y), + ECP_POINT_INIT_XY_Z0(secp521r1_T_26_X, secp521r1_T_26_Y), + ECP_POINT_INIT_XY_Z0(secp521r1_T_27_X, secp521r1_T_27_Y), + ECP_POINT_INIT_XY_Z0(secp521r1_T_28_X, secp521r1_T_28_Y), + ECP_POINT_INIT_XY_Z0(secp521r1_T_29_X, secp521r1_T_29_Y), + ECP_POINT_INIT_XY_Z0(secp521r1_T_30_X, secp521r1_T_30_Y), + ECP_POINT_INIT_XY_Z0(secp521r1_T_31_X, secp521r1_T_31_Y), +}; +#else +#define secp521r1_T NULL +#endif #endif /* MBEDTLS_ECP_DP_SECP521R1_ENABLED */ #if defined(MBEDTLS_ECP_DP_SECP192K1_ENABLED) @@ -285,6 +2195,190 @@ static const mbedtls_mpi_uint secp192k1_n[] = { MBEDTLS_BYTES_TO_T_UINT_8(0x17, 0xFC, 0xF2, 0x26, 0xFE, 0xFF, 0xFF, 0xFF), MBEDTLS_BYTES_TO_T_UINT_8(0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF), }; + +#if MBEDTLS_ECP_FIXED_POINT_OPTIM == 1 +static const mbedtls_mpi_uint secp192k1_T_0_X[] = { + MBEDTLS_BYTES_TO_T_UINT_8(0x7D, 0x6C, 0xE0, 0xEA, 0xB1, 0xD1, 0xA5, 0x1D), + MBEDTLS_BYTES_TO_T_UINT_8(0x34, 0xF4, 0xB7, 0x80, 0x02, 0x7D, 0xB0, 0x26), + MBEDTLS_BYTES_TO_T_UINT_8(0xAE, 0xE9, 0x57, 0xC0, 0x0E, 0xF1, 0x4F, 0xDB), +}; +static const mbedtls_mpi_uint secp192k1_T_0_Y[] = { + MBEDTLS_BYTES_TO_T_UINT_8(0x9D, 0x2F, 0x5E, 0xD9, 0x88, 0xAA, 0x82, 0x40), + MBEDTLS_BYTES_TO_T_UINT_8(0x34, 0x86, 0xBE, 0x15, 0xD0, 0x63, 0x41, 0x84), + MBEDTLS_BYTES_TO_T_UINT_8(0xA7, 0x28, 0x56, 0x9C, 0x6D, 0x2F, 0x2F, 0x9B), +}; +static const mbedtls_mpi_uint secp192k1_T_1_X[] = { + MBEDTLS_BYTES_TO_T_UINT_8(0x6F, 0x77, 0x3D, 0x0D, 0x85, 0x48, 0xA8, 0xA9), + MBEDTLS_BYTES_TO_T_UINT_8(0x62, 0x07, 0xDF, 0x1D, 0xB3, 0xB3, 0x01, 0x54), + MBEDTLS_BYTES_TO_T_UINT_8(0x05, 0x86, 0xF6, 0xAF, 0x19, 0x2A, 0x88, 0x2E), +}; +static const mbedtls_mpi_uint secp192k1_T_1_Y[] = { + MBEDTLS_BYTES_TO_T_UINT_8(0x33, 0x90, 0xB6, 0x2F, 0x48, 0x36, 0x4C, 0x5B), + MBEDTLS_BYTES_TO_T_UINT_8(0xDB, 0x11, 0x14, 0xA6, 0xCB, 0xBA, 0x15, 0xD9), + MBEDTLS_BYTES_TO_T_UINT_8(0x7E, 0xB0, 0xF2, 0xD4, 0xC9, 0xDA, 0xBA, 0xD7), +}; +static const mbedtls_mpi_uint secp192k1_T_2_X[] = { + MBEDTLS_BYTES_TO_T_UINT_8(0xE4, 0xC1, 0x9C, 0xE6, 0xBB, 0xFB, 0xCF, 0x23), + MBEDTLS_BYTES_TO_T_UINT_8(0x93, 0x19, 0xAC, 0x5A, 0xC9, 0x8A, 0x1C, 0x75), + MBEDTLS_BYTES_TO_T_UINT_8(0xC1, 0xF6, 0x76, 0x86, 0x89, 0x27, 0x8D, 0x28), +}; +static const mbedtls_mpi_uint secp192k1_T_2_Y[] = { + MBEDTLS_BYTES_TO_T_UINT_8(0x4B, 0xE0, 0x6F, 0x34, 0xBA, 0x5E, 0xD3, 0x96), + MBEDTLS_BYTES_TO_T_UINT_8(0x6A, 0xDC, 0xA6, 0x87, 0xC9, 0x9D, 0xC0, 0x82), + MBEDTLS_BYTES_TO_T_UINT_8(0x09, 0x11, 0x7E, 0xD6, 0xF7, 0x33, 0xFC, 0xE4), +}; +static const mbedtls_mpi_uint secp192k1_T_3_X[] = { + MBEDTLS_BYTES_TO_T_UINT_8(0xC2, 0x37, 0x3E, 0xC0, 0x7F, 0x62, 0xE7, 0x54), + MBEDTLS_BYTES_TO_T_UINT_8(0xA5, 0x3B, 0x69, 0x9D, 0x44, 0xBC, 0x82, 0x99), + MBEDTLS_BYTES_TO_T_UINT_8(0xD4, 0x84, 0xB3, 0x5F, 0x2B, 0xA5, 0x9E, 0x2C), +}; +static const mbedtls_mpi_uint secp192k1_T_3_Y[] = { + MBEDTLS_BYTES_TO_T_UINT_8(0x1D, 0x95, 0xEB, 0x4C, 0x04, 0xB4, 0xF4, 0x75), + MBEDTLS_BYTES_TO_T_UINT_8(0x55, 0xAD, 0x4B, 0xD5, 0x9A, 0xEB, 0xC4, 0x4E), + MBEDTLS_BYTES_TO_T_UINT_8(0xC9, 0xB1, 0xC5, 0x59, 0xE3, 0xD5, 0x16, 0x2A), +}; +static const mbedtls_mpi_uint secp192k1_T_4_X[] = { + MBEDTLS_BYTES_TO_T_UINT_8(0x48, 0x2A, 0xCC, 0xAC, 0xD0, 0xEE, 0x50, 0xEC), + MBEDTLS_BYTES_TO_T_UINT_8(0x99, 0x83, 0xE0, 0x5B, 0x14, 0x44, 0x52, 0x20), + MBEDTLS_BYTES_TO_T_UINT_8(0xD6, 0x15, 0x2D, 0x78, 0xF6, 0x51, 0x32, 0xCF), +}; +static const mbedtls_mpi_uint secp192k1_T_4_Y[] = { + MBEDTLS_BYTES_TO_T_UINT_8(0x86, 0x36, 0x9B, 0xDD, 0xF8, 0xDD, 0xEF, 0xB2), + MBEDTLS_BYTES_TO_T_UINT_8(0x0B, 0xB1, 0x6A, 0x2B, 0xAF, 0xEB, 0x2B, 0xB1), + MBEDTLS_BYTES_TO_T_UINT_8(0xC9, 0x87, 0x7A, 0x66, 0x5D, 0x5B, 0xDF, 0x8F), +}; +static const mbedtls_mpi_uint secp192k1_T_5_X[] = { + MBEDTLS_BYTES_TO_T_UINT_8(0x62, 0x45, 0xE5, 0x81, 0x9B, 0xEB, 0x37, 0x23), + MBEDTLS_BYTES_TO_T_UINT_8(0xB3, 0x29, 0xE2, 0x20, 0x64, 0x23, 0x6B, 0x6E), + MBEDTLS_BYTES_TO_T_UINT_8(0xFE, 0x1D, 0x41, 0xE1, 0x9B, 0x61, 0x7B, 0xD9), +}; +static const mbedtls_mpi_uint secp192k1_T_5_Y[] = { + MBEDTLS_BYTES_TO_T_UINT_8(0x75, 0x57, 0xA3, 0x0A, 0x13, 0xE4, 0x59, 0x15), + MBEDTLS_BYTES_TO_T_UINT_8(0x79, 0x6E, 0x4A, 0x48, 0x84, 0x90, 0xAC, 0xC7), + MBEDTLS_BYTES_TO_T_UINT_8(0x9C, 0xB8, 0xF5, 0xF3, 0xDE, 0xA0, 0xA1, 0x1D), +}; +static const mbedtls_mpi_uint secp192k1_T_6_X[] = { + MBEDTLS_BYTES_TO_T_UINT_8(0xA3, 0x32, 0x81, 0xA9, 0x91, 0x5A, 0x4E, 0x33), + MBEDTLS_BYTES_TO_T_UINT_8(0xCB, 0xA8, 0x90, 0xBE, 0x0F, 0xEC, 0xC0, 0x85), + MBEDTLS_BYTES_TO_T_UINT_8(0x80, 0x30, 0xD7, 0x08, 0xAE, 0xC4, 0x3A, 0xA5), +}; +static const mbedtls_mpi_uint secp192k1_T_6_Y[] = { + MBEDTLS_BYTES_TO_T_UINT_8(0xBC, 0x55, 0xE3, 0x76, 0xB3, 0x64, 0x74, 0x9F), + MBEDTLS_BYTES_TO_T_UINT_8(0x3F, 0x75, 0xD4, 0xDB, 0x98, 0xD7, 0x39, 0xAE), + MBEDTLS_BYTES_TO_T_UINT_8(0xD4, 0xEB, 0x8A, 0xAB, 0x16, 0xD9, 0xD4, 0x0B), +}; +static const mbedtls_mpi_uint secp192k1_T_7_X[] = { + MBEDTLS_BYTES_TO_T_UINT_8(0x41, 0xBE, 0xF9, 0xC7, 0xC7, 0xBA, 0xF3, 0xA1), + MBEDTLS_BYTES_TO_T_UINT_8(0xC2, 0x85, 0x59, 0xF3, 0x60, 0x41, 0x02, 0xD2), + MBEDTLS_BYTES_TO_T_UINT_8(0x46, 0x1C, 0x4A, 0xA4, 0xC7, 0xED, 0x66, 0xBC), +}; +static const mbedtls_mpi_uint secp192k1_T_7_Y[] = { + MBEDTLS_BYTES_TO_T_UINT_8(0xC3, 0x9C, 0x2E, 0x46, 0x52, 0x18, 0x87, 0x14), + MBEDTLS_BYTES_TO_T_UINT_8(0xFF, 0x35, 0x5A, 0x75, 0xAC, 0x4D, 0x75, 0x91), + MBEDTLS_BYTES_TO_T_UINT_8(0xCE, 0x2F, 0xAC, 0xFC, 0xBC, 0xE6, 0x93, 0x5E), +}; +static const mbedtls_mpi_uint secp192k1_T_8_X[] = { + MBEDTLS_BYTES_TO_T_UINT_8(0x87, 0x4D, 0xC9, 0x18, 0xE9, 0x00, 0xEB, 0x33), + MBEDTLS_BYTES_TO_T_UINT_8(0x1A, 0x69, 0x72, 0x07, 0x5A, 0x59, 0xA8, 0x26), + MBEDTLS_BYTES_TO_T_UINT_8(0xB6, 0x65, 0x83, 0x20, 0x10, 0xF9, 0x69, 0x82), +}; +static const mbedtls_mpi_uint secp192k1_T_8_Y[] = { + MBEDTLS_BYTES_TO_T_UINT_8(0x8B, 0x56, 0x7F, 0x9F, 0xBF, 0x46, 0x0C, 0x7E), + MBEDTLS_BYTES_TO_T_UINT_8(0xFC, 0xCF, 0xF0, 0xDC, 0xDF, 0x2D, 0xE6, 0xE5), + MBEDTLS_BYTES_TO_T_UINT_8(0x09, 0xF0, 0x72, 0x3A, 0x7A, 0x03, 0xE5, 0x22), +}; +static const mbedtls_mpi_uint secp192k1_T_9_X[] = { + MBEDTLS_BYTES_TO_T_UINT_8(0x3E, 0xAA, 0x57, 0x13, 0x37, 0xA7, 0x2C, 0xD4), + MBEDTLS_BYTES_TO_T_UINT_8(0xA3, 0xAC, 0xA2, 0x23, 0xF9, 0x84, 0x60, 0xD3), + MBEDTLS_BYTES_TO_T_UINT_8(0x32, 0xEB, 0x51, 0x70, 0x64, 0x78, 0xCA, 0x05), +}; +static const mbedtls_mpi_uint secp192k1_T_9_Y[] = { + MBEDTLS_BYTES_TO_T_UINT_8(0x91, 0xCC, 0x30, 0x62, 0x93, 0x46, 0x13, 0xE9), + MBEDTLS_BYTES_TO_T_UINT_8(0x21, 0x26, 0xCC, 0x6C, 0x3D, 0x5C, 0xDA, 0x2C), + MBEDTLS_BYTES_TO_T_UINT_8(0xD5, 0xAA, 0xB8, 0x03, 0xA4, 0x1A, 0x00, 0x96), +}; +static const mbedtls_mpi_uint secp192k1_T_10_X[] = { + MBEDTLS_BYTES_TO_T_UINT_8(0xF9, 0x9D, 0xE6, 0xCC, 0x4E, 0x2E, 0xC2, 0xD5), + MBEDTLS_BYTES_TO_T_UINT_8(0xB4, 0xC3, 0x8A, 0xAE, 0x6F, 0x40, 0x05, 0xEB), + MBEDTLS_BYTES_TO_T_UINT_8(0x9D, 0x8F, 0x4A, 0x4D, 0x35, 0xD3, 0x50, 0x9D), +}; +static const mbedtls_mpi_uint secp192k1_T_10_Y[] = { + MBEDTLS_BYTES_TO_T_UINT_8(0x1F, 0xFD, 0x98, 0xAB, 0xC7, 0x03, 0xB4, 0x55), + MBEDTLS_BYTES_TO_T_UINT_8(0x40, 0x40, 0xD2, 0x9F, 0xCA, 0xD0, 0x53, 0x00), + MBEDTLS_BYTES_TO_T_UINT_8(0x1A, 0x84, 0x00, 0x6F, 0xC8, 0xAD, 0xED, 0x8D), +}; +static const mbedtls_mpi_uint secp192k1_T_11_X[] = { + MBEDTLS_BYTES_TO_T_UINT_8(0xCE, 0xD3, 0x57, 0xD7, 0xC3, 0x07, 0xBD, 0xD7), + MBEDTLS_BYTES_TO_T_UINT_8(0x67, 0xBA, 0x47, 0x1D, 0x3D, 0xEF, 0x98, 0x6C), + MBEDTLS_BYTES_TO_T_UINT_8(0x6D, 0xC0, 0x6C, 0x7F, 0x12, 0xEE, 0x9F, 0x67), +}; +static const mbedtls_mpi_uint secp192k1_T_11_Y[] = { + MBEDTLS_BYTES_TO_T_UINT_8(0xCA, 0x02, 0xDA, 0x79, 0xAA, 0xC9, 0x27, 0xC4), + MBEDTLS_BYTES_TO_T_UINT_8(0x21, 0x79, 0xC7, 0x71, 0x84, 0xCB, 0xE5, 0x5A), + MBEDTLS_BYTES_TO_T_UINT_8(0x15, 0x37, 0x06, 0xBA, 0xB5, 0xD5, 0x18, 0x4C), +}; +static const mbedtls_mpi_uint secp192k1_T_12_X[] = { + MBEDTLS_BYTES_TO_T_UINT_8(0xA1, 0x65, 0x72, 0x6C, 0xF2, 0x63, 0x27, 0x6A), + MBEDTLS_BYTES_TO_T_UINT_8(0x69, 0xBC, 0x71, 0xDF, 0x75, 0xF8, 0x98, 0x4D), + MBEDTLS_BYTES_TO_T_UINT_8(0x70, 0x70, 0x9B, 0xDC, 0xE7, 0x18, 0x71, 0xFF), +}; +static const mbedtls_mpi_uint secp192k1_T_12_Y[] = { + MBEDTLS_BYTES_TO_T_UINT_8(0x15, 0x5B, 0x9F, 0x00, 0x5A, 0xB6, 0x80, 0x7A), + MBEDTLS_BYTES_TO_T_UINT_8(0xB7, 0xE0, 0xBB, 0xFC, 0x5E, 0x78, 0x9C, 0x89), + MBEDTLS_BYTES_TO_T_UINT_8(0x60, 0x03, 0x68, 0x83, 0x3D, 0x2E, 0x4C, 0xDD), +}; +static const mbedtls_mpi_uint secp192k1_T_13_X[] = { + MBEDTLS_BYTES_TO_T_UINT_8(0x3B, 0x49, 0x23, 0xA8, 0xCB, 0x3B, 0x1A, 0xF6), + MBEDTLS_BYTES_TO_T_UINT_8(0x8B, 0x3D, 0xA7, 0x46, 0xCF, 0x75, 0xB6, 0x2C), + MBEDTLS_BYTES_TO_T_UINT_8(0x92, 0xFD, 0x30, 0x01, 0xB6, 0xEF, 0xF9, 0xE8), +}; +static const mbedtls_mpi_uint secp192k1_T_13_Y[] = { + MBEDTLS_BYTES_TO_T_UINT_8(0xDC, 0xFA, 0xDA, 0xB8, 0x29, 0x42, 0xC9, 0xC7), + MBEDTLS_BYTES_TO_T_UINT_8(0x06, 0xD7, 0xA0, 0xE6, 0x6B, 0x86, 0x61, 0x39), + MBEDTLS_BYTES_TO_T_UINT_8(0xDB, 0xE9, 0xD3, 0x37, 0xD8, 0xE7, 0x35, 0xA9), +}; +static const mbedtls_mpi_uint secp192k1_T_14_X[] = { + MBEDTLS_BYTES_TO_T_UINT_8(0xFD, 0xC8, 0x8E, 0xB1, 0xCB, 0xB1, 0xB5, 0x4D), + MBEDTLS_BYTES_TO_T_UINT_8(0x16, 0xD7, 0x46, 0x7D, 0xAF, 0xE2, 0xDC, 0xBB), + MBEDTLS_BYTES_TO_T_UINT_8(0xD0, 0x46, 0xE7, 0xD8, 0x76, 0x31, 0x90, 0x76), +}; +static const mbedtls_mpi_uint secp192k1_T_14_Y[] = { + MBEDTLS_BYTES_TO_T_UINT_8(0xEB, 0xD3, 0xF4, 0x74, 0xE1, 0x67, 0xD8, 0x66), + MBEDTLS_BYTES_TO_T_UINT_8(0xE7, 0x70, 0x3C, 0xC8, 0xAF, 0x5F, 0xF4, 0x58), + MBEDTLS_BYTES_TO_T_UINT_8(0x24, 0x4E, 0xED, 0x5C, 0x43, 0xB3, 0x16, 0x35), +}; +static const mbedtls_mpi_uint secp192k1_T_15_X[] = { + MBEDTLS_BYTES_TO_T_UINT_8(0x57, 0xAE, 0xD1, 0xDD, 0x31, 0x14, 0xD3, 0xF0), + MBEDTLS_BYTES_TO_T_UINT_8(0xE8, 0x14, 0x06, 0x13, 0x12, 0x1C, 0x81, 0xF5), + MBEDTLS_BYTES_TO_T_UINT_8(0xA6, 0xF9, 0x0C, 0x91, 0xF7, 0x67, 0x59, 0x63), +}; +static const mbedtls_mpi_uint secp192k1_T_15_Y[] = { + MBEDTLS_BYTES_TO_T_UINT_8(0xAB, 0x91, 0xE2, 0xF4, 0x9D, 0xEB, 0x88, 0x87), + MBEDTLS_BYTES_TO_T_UINT_8(0xDB, 0x82, 0x30, 0x9C, 0xAE, 0x18, 0x4D, 0xB7), + MBEDTLS_BYTES_TO_T_UINT_8(0x3C, 0x79, 0xCF, 0x17, 0xA5, 0x1E, 0xE8, 0xC8), +}; +static const mbedtls_ecp_point secp192k1_T[16] = { + ECP_POINT_INIT_XY_Z1(secp192k1_T_0_X, secp192k1_T_0_Y), + ECP_POINT_INIT_XY_Z0(secp192k1_T_1_X, secp192k1_T_1_Y), + ECP_POINT_INIT_XY_Z0(secp192k1_T_2_X, secp192k1_T_2_Y), + ECP_POINT_INIT_XY_Z0(secp192k1_T_3_X, secp192k1_T_3_Y), + ECP_POINT_INIT_XY_Z0(secp192k1_T_4_X, secp192k1_T_4_Y), + ECP_POINT_INIT_XY_Z0(secp192k1_T_5_X, secp192k1_T_5_Y), + ECP_POINT_INIT_XY_Z0(secp192k1_T_6_X, secp192k1_T_6_Y), + ECP_POINT_INIT_XY_Z0(secp192k1_T_7_X, secp192k1_T_7_Y), + ECP_POINT_INIT_XY_Z0(secp192k1_T_8_X, secp192k1_T_8_Y), + ECP_POINT_INIT_XY_Z0(secp192k1_T_9_X, secp192k1_T_9_Y), + ECP_POINT_INIT_XY_Z0(secp192k1_T_10_X, secp192k1_T_10_Y), + ECP_POINT_INIT_XY_Z0(secp192k1_T_11_X, secp192k1_T_11_Y), + ECP_POINT_INIT_XY_Z0(secp192k1_T_12_X, secp192k1_T_12_Y), + ECP_POINT_INIT_XY_Z0(secp192k1_T_13_X, secp192k1_T_13_Y), + ECP_POINT_INIT_XY_Z0(secp192k1_T_14_X, secp192k1_T_14_Y), + ECP_POINT_INIT_XY_Z0(secp192k1_T_15_X, secp192k1_T_15_Y), +}; +#else +#define secp192k1_T NULL +#endif + #endif /* MBEDTLS_ECP_DP_SECP192K1_ENABLED */ #if defined(MBEDTLS_ECP_DP_SECP224K1_ENABLED) @@ -318,6 +2412,221 @@ static const mbedtls_mpi_uint secp224k1_n[] = { MBEDTLS_BYTES_TO_T_UINT_8(0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00), MBEDTLS_BYTES_TO_T_UINT_8(0x00, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00), }; + +#if MBEDTLS_ECP_FIXED_POINT_OPTIM == 1 +static const mbedtls_mpi_uint secp224k1_T_0_X[] = { + MBEDTLS_BYTES_TO_T_UINT_8(0x5C, 0xA4, 0xB7, 0xB6, 0x0E, 0x65, 0x7E, 0x0F), + MBEDTLS_BYTES_TO_T_UINT_8(0xA9, 0x75, 0x70, 0xE4, 0xE9, 0x67, 0xA4, 0x69), + MBEDTLS_BYTES_TO_T_UINT_8(0xA1, 0x28, 0xFC, 0x30, 0xDF, 0x99, 0xF0, 0x4D), + MBEDTLS_BYTES_TO_T_UINT_8(0x33, 0x5B, 0x45, 0xA1, 0x00, 0x00, 0x00, 0x00), +}; +static const mbedtls_mpi_uint secp224k1_T_0_Y[] = { + MBEDTLS_BYTES_TO_T_UINT_8(0xA5, 0x61, 0x6D, 0x55, 0xDB, 0x4B, 0xCA, 0xE2), + MBEDTLS_BYTES_TO_T_UINT_8(0x59, 0xBD, 0xB0, 0xC0, 0xF7, 0x19, 0xE3, 0xF7), + MBEDTLS_BYTES_TO_T_UINT_8(0xD6, 0xFB, 0xCA, 0x82, 0x42, 0x34, 0xBA, 0x7F), + MBEDTLS_BYTES_TO_T_UINT_8(0xED, 0x9F, 0x08, 0x7E, 0x00, 0x00, 0x00, 0x00), +}; +static const mbedtls_mpi_uint secp224k1_T_1_X[] = { + MBEDTLS_BYTES_TO_T_UINT_8(0x99, 0x6C, 0x22, 0x22, 0x40, 0x89, 0xAE, 0x7A), + MBEDTLS_BYTES_TO_T_UINT_8(0x2F, 0x92, 0xE1, 0x87, 0x56, 0x35, 0xAF, 0x9B), + MBEDTLS_BYTES_TO_T_UINT_8(0x88, 0xAF, 0x08, 0x35, 0x27, 0xEA, 0x04, 0xED), + MBEDTLS_BYTES_TO_T_UINT_8(0xF0, 0x53, 0xFD, 0xCF, 0x00, 0x00, 0x00, 0x00), +}; +static const mbedtls_mpi_uint secp224k1_T_1_Y[] = { + MBEDTLS_BYTES_TO_T_UINT_8(0xC1, 0xD0, 0x9F, 0x8D, 0xF3, 0x63, 0x54, 0x30), + MBEDTLS_BYTES_TO_T_UINT_8(0x39, 0xDB, 0x0F, 0x61, 0x54, 0x26, 0xD1, 0x98), + MBEDTLS_BYTES_TO_T_UINT_8(0xF5, 0x21, 0xF7, 0x1B, 0xB5, 0x1D, 0xF6, 0x7E), + MBEDTLS_BYTES_TO_T_UINT_8(0xFF, 0x05, 0xDA, 0x8F, 0x00, 0x00, 0x00, 0x00), +}; +static const mbedtls_mpi_uint secp224k1_T_2_X[] = { + MBEDTLS_BYTES_TO_T_UINT_8(0x10, 0x26, 0x73, 0xBC, 0xE4, 0x29, 0x62, 0x56), + MBEDTLS_BYTES_TO_T_UINT_8(0x37, 0x95, 0x17, 0x8B, 0xC3, 0x9B, 0xAC, 0xCC), + MBEDTLS_BYTES_TO_T_UINT_8(0xB1, 0xDB, 0x77, 0xDF, 0xDD, 0x13, 0x04, 0x98), + MBEDTLS_BYTES_TO_T_UINT_8(0x02, 0xFC, 0x22, 0x93, 0x00, 0x00, 0x00, 0x00), +}; +static const mbedtls_mpi_uint secp224k1_T_2_Y[] = { + MBEDTLS_BYTES_TO_T_UINT_8(0xAC, 0x65, 0xF1, 0x5A, 0x37, 0xEF, 0x79, 0xAD), + MBEDTLS_BYTES_TO_T_UINT_8(0x99, 0x01, 0x37, 0xAC, 0x9A, 0x5B, 0x51, 0x65), + MBEDTLS_BYTES_TO_T_UINT_8(0xFA, 0x75, 0x13, 0xA9, 0x4A, 0xAD, 0xFE, 0x9B), + MBEDTLS_BYTES_TO_T_UINT_8(0x32, 0x82, 0x6F, 0x66, 0x00, 0x00, 0x00, 0x00), +}; +static const mbedtls_mpi_uint secp224k1_T_3_X[] = { + MBEDTLS_BYTES_TO_T_UINT_8(0x4D, 0x5E, 0xF0, 0x40, 0xC3, 0xA6, 0xE2, 0x1E), + MBEDTLS_BYTES_TO_T_UINT_8(0x34, 0x9A, 0x6F, 0xCF, 0x11, 0x26, 0x66, 0x85), + MBEDTLS_BYTES_TO_T_UINT_8(0x79, 0x73, 0xA8, 0xCF, 0x2B, 0x12, 0x36, 0x37), + MBEDTLS_BYTES_TO_T_UINT_8(0xB9, 0xB3, 0x0A, 0x58, 0x00, 0x00, 0x00, 0x00), +}; +static const mbedtls_mpi_uint secp224k1_T_3_Y[] = { + MBEDTLS_BYTES_TO_T_UINT_8(0xD3, 0x79, 0x00, 0x55, 0x04, 0x34, 0x90, 0x1A), + MBEDTLS_BYTES_TO_T_UINT_8(0x0A, 0x54, 0x1C, 0xC2, 0x45, 0x0C, 0x1B, 0x23), + MBEDTLS_BYTES_TO_T_UINT_8(0x86, 0x19, 0xAB, 0xA8, 0xFC, 0x73, 0xDC, 0xEE), + MBEDTLS_BYTES_TO_T_UINT_8(0x72, 0xFB, 0x93, 0xCE, 0x00, 0x00, 0x00, 0x00), +}; +static const mbedtls_mpi_uint secp224k1_T_4_X[] = { + MBEDTLS_BYTES_TO_T_UINT_8(0xF8, 0x75, 0xD0, 0x66, 0x95, 0x86, 0xCA, 0x66), + MBEDTLS_BYTES_TO_T_UINT_8(0x17, 0xEA, 0x29, 0x16, 0x6A, 0x38, 0xDF, 0x41), + MBEDTLS_BYTES_TO_T_UINT_8(0xD8, 0xA2, 0x36, 0x2F, 0xDC, 0xBB, 0x5E, 0xF7), + MBEDTLS_BYTES_TO_T_UINT_8(0xD4, 0x89, 0x59, 0x49, 0x00, 0x00, 0x00, 0x00), +}; +static const mbedtls_mpi_uint secp224k1_T_4_Y[] = { + MBEDTLS_BYTES_TO_T_UINT_8(0xCA, 0xA3, 0x99, 0x9D, 0xB8, 0x77, 0x9D, 0x1D), + MBEDTLS_BYTES_TO_T_UINT_8(0x0A, 0x93, 0x43, 0x47, 0xC6, 0x5C, 0xF9, 0xFD), + MBEDTLS_BYTES_TO_T_UINT_8(0xAA, 0x00, 0x79, 0x42, 0x64, 0xB8, 0x25, 0x3E), + MBEDTLS_BYTES_TO_T_UINT_8(0x29, 0x54, 0xB4, 0x33, 0x00, 0x00, 0x00, 0x00), +}; +static const mbedtls_mpi_uint secp224k1_T_5_X[] = { + MBEDTLS_BYTES_TO_T_UINT_8(0xD9, 0x0C, 0x42, 0x90, 0x83, 0x0B, 0x31, 0x5F), + MBEDTLS_BYTES_TO_T_UINT_8(0x54, 0x2E, 0xAE, 0xC8, 0xC7, 0x5F, 0xD2, 0x70), + MBEDTLS_BYTES_TO_T_UINT_8(0xA9, 0xBC, 0xAD, 0x41, 0xE7, 0x32, 0x3A, 0x81), + MBEDTLS_BYTES_TO_T_UINT_8(0x8A, 0x97, 0x52, 0x83, 0x00, 0x00, 0x00, 0x00), +}; +static const mbedtls_mpi_uint secp224k1_T_5_Y[] = { + MBEDTLS_BYTES_TO_T_UINT_8(0x1A, 0x13, 0x7A, 0xBD, 0xAE, 0x94, 0x60, 0xFD), + MBEDTLS_BYTES_TO_T_UINT_8(0x92, 0x9B, 0x95, 0xB4, 0x6E, 0x68, 0xB2, 0x1F), + MBEDTLS_BYTES_TO_T_UINT_8(0x15, 0x49, 0xBE, 0x51, 0xFE, 0x66, 0x15, 0x74), + MBEDTLS_BYTES_TO_T_UINT_8(0xE6, 0x37, 0xE4, 0xFE, 0x00, 0x00, 0x00, 0x00), +}; +static const mbedtls_mpi_uint secp224k1_T_6_X[] = { + MBEDTLS_BYTES_TO_T_UINT_8(0xF6, 0x9B, 0xEE, 0x64, 0xC9, 0x1B, 0xBD, 0x77), + MBEDTLS_BYTES_TO_T_UINT_8(0xDA, 0x5F, 0x34, 0xA9, 0x0B, 0xB7, 0x25, 0x52), + MBEDTLS_BYTES_TO_T_UINT_8(0x90, 0x13, 0xB1, 0x38, 0xFB, 0x9D, 0x78, 0xED), + MBEDTLS_BYTES_TO_T_UINT_8(0x39, 0xE7, 0x1B, 0xFA, 0x00, 0x00, 0x00, 0x00), +}; +static const mbedtls_mpi_uint secp224k1_T_6_Y[] = { + MBEDTLS_BYTES_TO_T_UINT_8(0xFB, 0xB3, 0xB7, 0x44, 0x92, 0x6B, 0x00, 0x82), + MBEDTLS_BYTES_TO_T_UINT_8(0x97, 0x82, 0x44, 0x3E, 0x18, 0x1A, 0x58, 0x6A), + MBEDTLS_BYTES_TO_T_UINT_8(0x15, 0xF8, 0xC0, 0xE4, 0xEE, 0xC1, 0xBF, 0x44), + MBEDTLS_BYTES_TO_T_UINT_8(0x7E, 0x32, 0x27, 0xB2, 0x00, 0x00, 0x00, 0x00), +}; +static const mbedtls_mpi_uint secp224k1_T_7_X[] = { + MBEDTLS_BYTES_TO_T_UINT_8(0xF4, 0x9A, 0x42, 0x62, 0x8B, 0x26, 0x54, 0x21), + MBEDTLS_BYTES_TO_T_UINT_8(0x24, 0x85, 0x74, 0xA0, 0x79, 0xA8, 0xEE, 0xBE), + MBEDTLS_BYTES_TO_T_UINT_8(0x80, 0x36, 0x60, 0xB3, 0x28, 0x4D, 0x55, 0xBE), + MBEDTLS_BYTES_TO_T_UINT_8(0x32, 0x27, 0x82, 0x29, 0x00, 0x00, 0x00, 0x00), +}; +static const mbedtls_mpi_uint secp224k1_T_7_Y[] = { + MBEDTLS_BYTES_TO_T_UINT_8(0x0D, 0xFC, 0x73, 0x77, 0xAF, 0x5C, 0xAC, 0x78), + MBEDTLS_BYTES_TO_T_UINT_8(0xCC, 0xED, 0xE5, 0xF6, 0x1D, 0xA8, 0x67, 0x43), + MBEDTLS_BYTES_TO_T_UINT_8(0xF8, 0xDE, 0x33, 0x1C, 0xF1, 0x80, 0x73, 0xF8), + MBEDTLS_BYTES_TO_T_UINT_8(0x2A, 0xE2, 0xDE, 0x3C, 0x00, 0x00, 0x00, 0x00), +}; +static const mbedtls_mpi_uint secp224k1_T_8_X[] = { + MBEDTLS_BYTES_TO_T_UINT_8(0x57, 0x3E, 0x6B, 0xFE, 0xF0, 0x04, 0x28, 0x01), + MBEDTLS_BYTES_TO_T_UINT_8(0xBB, 0xB2, 0x14, 0x9D, 0x18, 0x11, 0x7D, 0x9D), + MBEDTLS_BYTES_TO_T_UINT_8(0x96, 0xC4, 0xD6, 0x2E, 0x6E, 0x57, 0x4D, 0xE1), + MBEDTLS_BYTES_TO_T_UINT_8(0xEA, 0x55, 0x1B, 0xDE, 0x00, 0x00, 0x00, 0x00), +}; +static const mbedtls_mpi_uint secp224k1_T_8_Y[] = { + MBEDTLS_BYTES_TO_T_UINT_8(0x07, 0xF7, 0x17, 0xBC, 0x45, 0xAB, 0x16, 0xAB), + MBEDTLS_BYTES_TO_T_UINT_8(0xCD, 0xB0, 0xEF, 0x61, 0xE3, 0x20, 0x7C, 0xF8), + MBEDTLS_BYTES_TO_T_UINT_8(0x6C, 0x85, 0x41, 0x4D, 0xF1, 0x7E, 0x4D, 0x41), + MBEDTLS_BYTES_TO_T_UINT_8(0x99, 0xC2, 0x9B, 0x5E, 0x00, 0x00, 0x00, 0x00), +}; +static const mbedtls_mpi_uint secp224k1_T_9_X[] = { + MBEDTLS_BYTES_TO_T_UINT_8(0x70, 0x2E, 0x49, 0x3D, 0x3E, 0x4B, 0xD3, 0x32), + MBEDTLS_BYTES_TO_T_UINT_8(0xC8, 0x2B, 0x9D, 0xD5, 0x27, 0xFA, 0xCA, 0xE0), + MBEDTLS_BYTES_TO_T_UINT_8(0xB3, 0xB3, 0x6A, 0xE0, 0x79, 0x14, 0x28, 0x0F), + MBEDTLS_BYTES_TO_T_UINT_8(0x6C, 0x1E, 0xDC, 0xF5, 0x00, 0x00, 0x00, 0x00), +}; +static const mbedtls_mpi_uint secp224k1_T_9_Y[] = { + MBEDTLS_BYTES_TO_T_UINT_8(0xCA, 0x44, 0x56, 0xCD, 0xFC, 0x9F, 0x09, 0xFF), + MBEDTLS_BYTES_TO_T_UINT_8(0x5C, 0x8C, 0x59, 0xA4, 0x64, 0x2A, 0x3A, 0xED), + MBEDTLS_BYTES_TO_T_UINT_8(0x40, 0xA0, 0xB5, 0x86, 0x4E, 0x69, 0xDA, 0x06), + MBEDTLS_BYTES_TO_T_UINT_8(0x08, 0x8B, 0x11, 0x38, 0x00, 0x00, 0x00, 0x00), +}; +static const mbedtls_mpi_uint secp224k1_T_10_X[] = { + MBEDTLS_BYTES_TO_T_UINT_8(0xA0, 0x17, 0x16, 0x12, 0x17, 0xDC, 0x00, 0x7E), + MBEDTLS_BYTES_TO_T_UINT_8(0xE7, 0x76, 0x24, 0x6C, 0x97, 0x2C, 0xB5, 0xF9), + MBEDTLS_BYTES_TO_T_UINT_8(0x82, 0x71, 0xE3, 0xB0, 0xBB, 0x4E, 0x50, 0x52), + MBEDTLS_BYTES_TO_T_UINT_8(0x6E, 0x48, 0x26, 0xD5, 0x00, 0x00, 0x00, 0x00), +}; +static const mbedtls_mpi_uint secp224k1_T_10_Y[] = { + MBEDTLS_BYTES_TO_T_UINT_8(0x06, 0x5F, 0x28, 0xF6, 0x01, 0x5A, 0x60, 0x41), + MBEDTLS_BYTES_TO_T_UINT_8(0xAE, 0x95, 0xFE, 0xD0, 0xAD, 0x15, 0xD4, 0xD9), + MBEDTLS_BYTES_TO_T_UINT_8(0xAD, 0x5B, 0x7A, 0xFD, 0x80, 0xF7, 0x9F, 0x64), + MBEDTLS_BYTES_TO_T_UINT_8(0x32, 0xBC, 0x1B, 0xDF, 0x00, 0x00, 0x00, 0x00), +}; +static const mbedtls_mpi_uint secp224k1_T_11_X[] = { + MBEDTLS_BYTES_TO_T_UINT_8(0xBB, 0xE6, 0xDF, 0x14, 0x29, 0xF4, 0xD4, 0x14), + MBEDTLS_BYTES_TO_T_UINT_8(0xE5, 0x12, 0xDD, 0xEC, 0x5B, 0x8A, 0x59, 0xE5), + MBEDTLS_BYTES_TO_T_UINT_8(0x26, 0x92, 0x3E, 0x35, 0x08, 0xE9, 0xCF, 0x0E), + MBEDTLS_BYTES_TO_T_UINT_8(0xE0, 0x35, 0x29, 0x97, 0x00, 0x00, 0x00, 0x00), +}; +static const mbedtls_mpi_uint secp224k1_T_11_Y[] = { + MBEDTLS_BYTES_TO_T_UINT_8(0x11, 0xDB, 0xD6, 0x6A, 0xC5, 0x43, 0xA4, 0xA1), + MBEDTLS_BYTES_TO_T_UINT_8(0x61, 0x33, 0x50, 0x61, 0x70, 0xA1, 0xE9, 0xCE), + MBEDTLS_BYTES_TO_T_UINT_8(0x15, 0x15, 0x6E, 0x5F, 0x01, 0x0C, 0x8C, 0xFA), + MBEDTLS_BYTES_TO_T_UINT_8(0x85, 0xA1, 0x9A, 0x9D, 0x00, 0x00, 0x00, 0x00), +}; +static const mbedtls_mpi_uint secp224k1_T_12_X[] = { + MBEDTLS_BYTES_TO_T_UINT_8(0x6E, 0xC6, 0xF7, 0xE2, 0x4A, 0xCD, 0x9B, 0x61), + MBEDTLS_BYTES_TO_T_UINT_8(0x34, 0x4D, 0x5A, 0xB8, 0xE2, 0x6D, 0xA6, 0x50), + MBEDTLS_BYTES_TO_T_UINT_8(0x32, 0x3F, 0xB6, 0x17, 0xE3, 0x2C, 0x6F, 0x65), + MBEDTLS_BYTES_TO_T_UINT_8(0x1E, 0xA4, 0x59, 0x51, 0x00, 0x00, 0x00, 0x00), +}; +static const mbedtls_mpi_uint secp224k1_T_12_Y[] = { + MBEDTLS_BYTES_TO_T_UINT_8(0x77, 0x4F, 0x7C, 0x49, 0xCD, 0x6E, 0xEB, 0x3C), + MBEDTLS_BYTES_TO_T_UINT_8(0x05, 0xC9, 0x1F, 0xB7, 0x4D, 0x98, 0xC7, 0x67), + MBEDTLS_BYTES_TO_T_UINT_8(0x4C, 0xFD, 0x98, 0x20, 0x95, 0xBB, 0x20, 0x3A), + MBEDTLS_BYTES_TO_T_UINT_8(0xE0, 0xF2, 0x73, 0x92, 0x00, 0x00, 0x00, 0x00), +}; +static const mbedtls_mpi_uint secp224k1_T_13_X[] = { + MBEDTLS_BYTES_TO_T_UINT_8(0xE2, 0xEF, 0xFB, 0x30, 0xFA, 0x12, 0x1A, 0xB0), + MBEDTLS_BYTES_TO_T_UINT_8(0x7A, 0x4C, 0x24, 0xB4, 0x5B, 0xC9, 0x4C, 0x0F), + MBEDTLS_BYTES_TO_T_UINT_8(0x7A, 0xDD, 0x5E, 0x84, 0x95, 0x4D, 0x26, 0xED), + MBEDTLS_BYTES_TO_T_UINT_8(0xE3, 0xFA, 0xF9, 0x3A, 0x00, 0x00, 0x00, 0x00), +}; +static const mbedtls_mpi_uint secp224k1_T_13_Y[] = { + MBEDTLS_BYTES_TO_T_UINT_8(0x6A, 0xA3, 0x2E, 0x7A, 0xDC, 0xA7, 0x53, 0xA9), + MBEDTLS_BYTES_TO_T_UINT_8(0x7C, 0x9F, 0x81, 0x84, 0xB2, 0x0D, 0xFE, 0x31), + MBEDTLS_BYTES_TO_T_UINT_8(0x61, 0x89, 0x1B, 0x77, 0x0C, 0x89, 0x71, 0xEC), + MBEDTLS_BYTES_TO_T_UINT_8(0xFA, 0xFF, 0x7F, 0xB2, 0x00, 0x00, 0x00, 0x00), +}; +static const mbedtls_mpi_uint secp224k1_T_14_X[] = { + MBEDTLS_BYTES_TO_T_UINT_8(0x28, 0xE9, 0x2C, 0x79, 0xA6, 0x3C, 0xAD, 0x93), + MBEDTLS_BYTES_TO_T_UINT_8(0xD6, 0xE0, 0x23, 0x02, 0x86, 0x0F, 0x77, 0x2A), + MBEDTLS_BYTES_TO_T_UINT_8(0x13, 0x93, 0x6D, 0xE9, 0xF9, 0x3C, 0xBE, 0xB9), + MBEDTLS_BYTES_TO_T_UINT_8(0x04, 0xE7, 0x24, 0x92, 0x00, 0x00, 0x00, 0x00), +}; +static const mbedtls_mpi_uint secp224k1_T_14_Y[] = { + MBEDTLS_BYTES_TO_T_UINT_8(0xBB, 0x3C, 0x5B, 0x4B, 0x1B, 0x25, 0x37, 0xD6), + MBEDTLS_BYTES_TO_T_UINT_8(0xC9, 0xE8, 0x38, 0x1B, 0xA1, 0x5A, 0x2E, 0x68), + MBEDTLS_BYTES_TO_T_UINT_8(0x03, 0x19, 0xFD, 0xF4, 0x78, 0x01, 0x6B, 0x44), + MBEDTLS_BYTES_TO_T_UINT_8(0x0F, 0x69, 0x37, 0x4F, 0x00, 0x00, 0x00, 0x00), +}; +static const mbedtls_mpi_uint secp224k1_T_15_X[] = { + MBEDTLS_BYTES_TO_T_UINT_8(0x1A, 0xE2, 0xBF, 0xD3, 0xEC, 0x95, 0x9C, 0x03), + MBEDTLS_BYTES_TO_T_UINT_8(0xC2, 0x7B, 0xFC, 0xD5, 0xD3, 0x25, 0x5E, 0x0F), + MBEDTLS_BYTES_TO_T_UINT_8(0x39, 0x55, 0x09, 0xA2, 0x58, 0x6A, 0xC9, 0xFF), + MBEDTLS_BYTES_TO_T_UINT_8(0x80, 0xCC, 0x3B, 0xD9, 0x00, 0x00, 0x00, 0x00), +}; +static const mbedtls_mpi_uint secp224k1_T_15_Y[] = { + MBEDTLS_BYTES_TO_T_UINT_8(0x8F, 0x08, 0x65, 0x5E, 0xCB, 0xAB, 0x48, 0xC8), + MBEDTLS_BYTES_TO_T_UINT_8(0xEE, 0x79, 0x8B, 0xC0, 0x11, 0xC0, 0x69, 0x38), + MBEDTLS_BYTES_TO_T_UINT_8(0xE6, 0xE8, 0x8C, 0x4C, 0xC5, 0x28, 0xE4, 0xAE), + MBEDTLS_BYTES_TO_T_UINT_8(0xA5, 0x1F, 0x34, 0x5C, 0x00, 0x00, 0x00, 0x00), +}; +static const mbedtls_ecp_point secp224k1_T[16] = { + ECP_POINT_INIT_XY_Z1(secp224k1_T_0_X, secp224k1_T_0_Y), + ECP_POINT_INIT_XY_Z0(secp224k1_T_1_X, secp224k1_T_1_Y), + ECP_POINT_INIT_XY_Z0(secp224k1_T_2_X, secp224k1_T_2_Y), + ECP_POINT_INIT_XY_Z0(secp224k1_T_3_X, secp224k1_T_3_Y), + ECP_POINT_INIT_XY_Z0(secp224k1_T_4_X, secp224k1_T_4_Y), + ECP_POINT_INIT_XY_Z0(secp224k1_T_5_X, secp224k1_T_5_Y), + ECP_POINT_INIT_XY_Z0(secp224k1_T_6_X, secp224k1_T_6_Y), + ECP_POINT_INIT_XY_Z0(secp224k1_T_7_X, secp224k1_T_7_Y), + ECP_POINT_INIT_XY_Z0(secp224k1_T_8_X, secp224k1_T_8_Y), + ECP_POINT_INIT_XY_Z0(secp224k1_T_9_X, secp224k1_T_9_Y), + ECP_POINT_INIT_XY_Z0(secp224k1_T_10_X, secp224k1_T_10_Y), + ECP_POINT_INIT_XY_Z0(secp224k1_T_11_X, secp224k1_T_11_Y), + ECP_POINT_INIT_XY_Z0(secp224k1_T_12_X, secp224k1_T_12_Y), + ECP_POINT_INIT_XY_Z0(secp224k1_T_13_X, secp224k1_T_13_Y), + ECP_POINT_INIT_XY_Z0(secp224k1_T_14_X, secp224k1_T_14_Y), + ECP_POINT_INIT_XY_Z0(secp224k1_T_15_X, secp224k1_T_15_Y), +}; +#else +#define secp224k1_T NULL +#endif #endif /* MBEDTLS_ECP_DP_SECP224K1_ENABLED */ #if defined(MBEDTLS_ECP_DP_SECP256K1_ENABLED) @@ -345,12 +2654,227 @@ static const mbedtls_mpi_uint secp256k1_gy[] = { MBEDTLS_BYTES_TO_T_UINT_8(0xA8, 0x08, 0x11, 0x0E, 0xFC, 0xFB, 0xA4, 0x5D), MBEDTLS_BYTES_TO_T_UINT_8(0x65, 0xC4, 0xA3, 0x26, 0x77, 0xDA, 0x3A, 0x48), }; -static const mbedtls_mpi_uint secp256k1_n[] = { - MBEDTLS_BYTES_TO_T_UINT_8(0x41, 0x41, 0x36, 0xD0, 0x8C, 0x5E, 0xD2, 0xBF), - MBEDTLS_BYTES_TO_T_UINT_8(0x3B, 0xA0, 0x48, 0xAF, 0xE6, 0xDC, 0xAE, 0xBA), - MBEDTLS_BYTES_TO_T_UINT_8(0xFE, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF), - MBEDTLS_BYTES_TO_T_UINT_8(0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF), +static const mbedtls_mpi_uint secp256k1_n[] = { + MBEDTLS_BYTES_TO_T_UINT_8(0x41, 0x41, 0x36, 0xD0, 0x8C, 0x5E, 0xD2, 0xBF), + MBEDTLS_BYTES_TO_T_UINT_8(0x3B, 0xA0, 0x48, 0xAF, 0xE6, 0xDC, 0xAE, 0xBA), + MBEDTLS_BYTES_TO_T_UINT_8(0xFE, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF), + MBEDTLS_BYTES_TO_T_UINT_8(0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF), +}; + +#if MBEDTLS_ECP_FIXED_POINT_OPTIM == 1 +static const mbedtls_mpi_uint secp256k1_T_0_X[] = { + MBEDTLS_BYTES_TO_T_UINT_8(0x98, 0x17, 0xF8, 0x16, 0x5B, 0x81, 0xF2, 0x59), + MBEDTLS_BYTES_TO_T_UINT_8(0xD9, 0x28, 0xCE, 0x2D, 0xDB, 0xFC, 0x9B, 0x02), + MBEDTLS_BYTES_TO_T_UINT_8(0x07, 0x0B, 0x87, 0xCE, 0x95, 0x62, 0xA0, 0x55), + MBEDTLS_BYTES_TO_T_UINT_8(0xAC, 0xBB, 0xDC, 0xF9, 0x7E, 0x66, 0xBE, 0x79), +}; +static const mbedtls_mpi_uint secp256k1_T_0_Y[] = { + MBEDTLS_BYTES_TO_T_UINT_8(0xB8, 0xD4, 0x10, 0xFB, 0x8F, 0xD0, 0x47, 0x9C), + MBEDTLS_BYTES_TO_T_UINT_8(0x19, 0x54, 0x85, 0xA6, 0x48, 0xB4, 0x17, 0xFD), + MBEDTLS_BYTES_TO_T_UINT_8(0xA8, 0x08, 0x11, 0x0E, 0xFC, 0xFB, 0xA4, 0x5D), + MBEDTLS_BYTES_TO_T_UINT_8(0x65, 0xC4, 0xA3, 0x26, 0x77, 0xDA, 0x3A, 0x48), +}; +static const mbedtls_mpi_uint secp256k1_T_1_X[] = { + MBEDTLS_BYTES_TO_T_UINT_8(0xE7, 0xEE, 0xD7, 0x1E, 0x67, 0x86, 0x32, 0x74), + MBEDTLS_BYTES_TO_T_UINT_8(0x23, 0x73, 0xB1, 0xA9, 0xD5, 0xCC, 0x27, 0x78), + MBEDTLS_BYTES_TO_T_UINT_8(0x1F, 0x0E, 0x11, 0x01, 0x71, 0xFE, 0x92, 0x73), + MBEDTLS_BYTES_TO_T_UINT_8(0xC6, 0x28, 0x63, 0x6D, 0x72, 0x09, 0xA6, 0xC0), +}; +static const mbedtls_mpi_uint secp256k1_T_1_Y[] = { + MBEDTLS_BYTES_TO_T_UINT_8(0xCE, 0xE1, 0x69, 0xDC, 0x3E, 0x2C, 0x75, 0xC3), + MBEDTLS_BYTES_TO_T_UINT_8(0xE5, 0xB7, 0x3F, 0x30, 0x26, 0x3C, 0xDF, 0x8E), + MBEDTLS_BYTES_TO_T_UINT_8(0x3D, 0xBE, 0xB9, 0x5D, 0x0E, 0xE8, 0x5E, 0x14), + MBEDTLS_BYTES_TO_T_UINT_8(0x01, 0xC3, 0x05, 0xD6, 0xB7, 0xD5, 0x24, 0xFC), +}; +static const mbedtls_mpi_uint secp256k1_T_2_X[] = { + MBEDTLS_BYTES_TO_T_UINT_8(0x13, 0xCF, 0x7B, 0xDC, 0xCD, 0xC3, 0x39, 0x9D), + MBEDTLS_BYTES_TO_T_UINT_8(0x42, 0xDA, 0xB9, 0xE5, 0x64, 0xA7, 0x47, 0x91), + MBEDTLS_BYTES_TO_T_UINT_8(0x76, 0x46, 0xA8, 0x61, 0xF6, 0x23, 0xEB, 0x58), + MBEDTLS_BYTES_TO_T_UINT_8(0x5C, 0xC1, 0xFF, 0xE4, 0x55, 0xD5, 0xC2, 0xBF), +}; +static const mbedtls_mpi_uint secp256k1_T_2_Y[] = { + MBEDTLS_BYTES_TO_T_UINT_8(0xC9, 0xBE, 0xB9, 0x59, 0x24, 0x13, 0x4A, 0x2A), + MBEDTLS_BYTES_TO_T_UINT_8(0x64, 0x45, 0x12, 0xDE, 0xBA, 0x4F, 0xEF, 0x56), + MBEDTLS_BYTES_TO_T_UINT_8(0xBE, 0x08, 0xBF, 0xC1, 0x66, 0xAA, 0x0A, 0xBC), + MBEDTLS_BYTES_TO_T_UINT_8(0x36, 0xFE, 0x30, 0x55, 0x31, 0x86, 0xA7, 0xB4), +}; +static const mbedtls_mpi_uint secp256k1_T_3_X[] = { + MBEDTLS_BYTES_TO_T_UINT_8(0x1D, 0xBF, 0x18, 0x81, 0x67, 0x27, 0x42, 0xBD), + MBEDTLS_BYTES_TO_T_UINT_8(0x08, 0x05, 0x83, 0xA4, 0xDD, 0x57, 0xD3, 0x50), + MBEDTLS_BYTES_TO_T_UINT_8(0x20, 0x63, 0xAB, 0xE4, 0x90, 0x70, 0xD0, 0x7C), + MBEDTLS_BYTES_TO_T_UINT_8(0x71, 0x5D, 0xFD, 0xA0, 0xEF, 0xCF, 0x1C, 0x54), +}; +static const mbedtls_mpi_uint secp256k1_T_3_Y[] = { + MBEDTLS_BYTES_TO_T_UINT_8(0x13, 0x80, 0xE4, 0xF6, 0x09, 0xBC, 0x57, 0x90), + MBEDTLS_BYTES_TO_T_UINT_8(0x21, 0x9F, 0x6E, 0x88, 0x54, 0x6E, 0x51, 0xF2), + MBEDTLS_BYTES_TO_T_UINT_8(0xF5, 0x5F, 0x85, 0xFB, 0x84, 0x3E, 0x4A, 0xAA), + MBEDTLS_BYTES_TO_T_UINT_8(0xA8, 0x19, 0xF5, 0x55, 0xC9, 0x07, 0xD8, 0xCE), +}; +static const mbedtls_mpi_uint secp256k1_T_4_X[] = { + MBEDTLS_BYTES_TO_T_UINT_8(0x1A, 0xB4, 0xC3, 0xD9, 0x5C, 0xA0, 0xD4, 0x90), + MBEDTLS_BYTES_TO_T_UINT_8(0x0D, 0x30, 0xAF, 0x59, 0x9B, 0xF8, 0x04, 0x85), + MBEDTLS_BYTES_TO_T_UINT_8(0x4D, 0xA6, 0xFD, 0x66, 0x7B, 0xC3, 0x39, 0x85), + MBEDTLS_BYTES_TO_T_UINT_8(0xE0, 0xBF, 0xF0, 0xC2, 0xE9, 0x71, 0xA4, 0x9E), +}; +static const mbedtls_mpi_uint secp256k1_T_4_Y[] = { + MBEDTLS_BYTES_TO_T_UINT_8(0x14, 0x2D, 0xB9, 0x88, 0x28, 0xF1, 0xBE, 0x78), + MBEDTLS_BYTES_TO_T_UINT_8(0x14, 0xF3, 0x1A, 0x0E, 0xB9, 0x01, 0x66, 0x34), + MBEDTLS_BYTES_TO_T_UINT_8(0x77, 0xA7, 0xA4, 0xF4, 0x05, 0xD0, 0xAA, 0x53), + MBEDTLS_BYTES_TO_T_UINT_8(0x00, 0x39, 0x1E, 0x47, 0xE5, 0x68, 0xC8, 0xC0), +}; +static const mbedtls_mpi_uint secp256k1_T_5_X[] = { + MBEDTLS_BYTES_TO_T_UINT_8(0xDD, 0xB9, 0xFC, 0xE0, 0x33, 0x8A, 0x7D, 0x96), + MBEDTLS_BYTES_TO_T_UINT_8(0x4F, 0x93, 0xA5, 0x53, 0x55, 0x16, 0xB4, 0x6E), + MBEDTLS_BYTES_TO_T_UINT_8(0xE9, 0x5F, 0xEA, 0x9B, 0x29, 0x52, 0x71, 0xDA), + MBEDTLS_BYTES_TO_T_UINT_8(0xB2, 0xF0, 0x24, 0xB8, 0x7D, 0xB7, 0xA0, 0x9B), +}; +static const mbedtls_mpi_uint secp256k1_T_5_Y[] = { + MBEDTLS_BYTES_TO_T_UINT_8(0xC2, 0x00, 0x27, 0xB2, 0xDF, 0x73, 0xA2, 0xE0), + MBEDTLS_BYTES_TO_T_UINT_8(0x1D, 0x2E, 0x4D, 0x7C, 0xDE, 0x7A, 0x23, 0x32), + MBEDTLS_BYTES_TO_T_UINT_8(0xAC, 0x65, 0x60, 0xC7, 0x97, 0x1E, 0xA4, 0x22), + MBEDTLS_BYTES_TO_T_UINT_8(0xCD, 0x13, 0x5B, 0x77, 0x59, 0xCB, 0x36, 0xE1), +}; +static const mbedtls_mpi_uint secp256k1_T_6_X[] = { + MBEDTLS_BYTES_TO_T_UINT_8(0x99, 0xBC, 0x9F, 0x9E, 0x2D, 0x53, 0x2A, 0xA8), + MBEDTLS_BYTES_TO_T_UINT_8(0x87, 0x5F, 0x64, 0x9F, 0x1A, 0x19, 0xE6, 0x77), + MBEDTLS_BYTES_TO_T_UINT_8(0x9E, 0x7B, 0x39, 0xD2, 0xDB, 0x85, 0x84, 0xD5), + MBEDTLS_BYTES_TO_T_UINT_8(0x83, 0xC7, 0x0D, 0x58, 0x6E, 0x3F, 0x52, 0x15), +}; +static const mbedtls_mpi_uint secp256k1_T_6_Y[] = { + MBEDTLS_BYTES_TO_T_UINT_8(0x21, 0x68, 0x19, 0x0B, 0x68, 0xC9, 0x1E, 0xFB), + MBEDTLS_BYTES_TO_T_UINT_8(0xD2, 0x4E, 0x21, 0x49, 0x3D, 0x55, 0xCC, 0x25), + MBEDTLS_BYTES_TO_T_UINT_8(0xF5, 0xF9, 0x25, 0x45, 0x54, 0x45, 0xB1, 0x0F), + MBEDTLS_BYTES_TO_T_UINT_8(0xA9, 0xB3, 0xF7, 0xCD, 0x80, 0xA4, 0x04, 0x05), +}; +static const mbedtls_mpi_uint secp256k1_T_7_X[] = { + MBEDTLS_BYTES_TO_T_UINT_8(0xD4, 0x1E, 0x88, 0xC4, 0xAA, 0x18, 0x7E, 0x45), + MBEDTLS_BYTES_TO_T_UINT_8(0x4B, 0xAC, 0xD9, 0xB2, 0xA1, 0xC0, 0x71, 0x5D), + MBEDTLS_BYTES_TO_T_UINT_8(0xA9, 0xA2, 0xF1, 0x15, 0xA6, 0x5F, 0x6C, 0x86), + MBEDTLS_BYTES_TO_T_UINT_8(0x4F, 0x5B, 0x05, 0xBC, 0xB7, 0xC6, 0x4E, 0x72), +}; +static const mbedtls_mpi_uint secp256k1_T_7_Y[] = { + MBEDTLS_BYTES_TO_T_UINT_8(0x1D, 0x80, 0xF8, 0x5C, 0x20, 0x2A, 0xE1, 0xE2), + MBEDTLS_BYTES_TO_T_UINT_8(0x7C, 0x48, 0x2E, 0x68, 0x82, 0x7F, 0xEB, 0x5F), + MBEDTLS_BYTES_TO_T_UINT_8(0xA2, 0x3B, 0x25, 0xDB, 0x32, 0x4D, 0x88, 0x42), + MBEDTLS_BYTES_TO_T_UINT_8(0xEE, 0x6E, 0xA6, 0xB6, 0x6D, 0x62, 0x78, 0x22), +}; +static const mbedtls_mpi_uint secp256k1_T_8_X[] = { + MBEDTLS_BYTES_TO_T_UINT_8(0x1F, 0x4D, 0x3E, 0x86, 0x58, 0xC3, 0xEB, 0xBA), + MBEDTLS_BYTES_TO_T_UINT_8(0x1A, 0x89, 0x33, 0x18, 0x21, 0x1D, 0x9B, 0xE7), + MBEDTLS_BYTES_TO_T_UINT_8(0x0B, 0x9D, 0xFF, 0xC3, 0x79, 0xC1, 0x88, 0xF8), + MBEDTLS_BYTES_TO_T_UINT_8(0x28, 0xD4, 0x48, 0x53, 0xE8, 0xAD, 0x21, 0x16), +}; +static const mbedtls_mpi_uint secp256k1_T_8_Y[] = { + MBEDTLS_BYTES_TO_T_UINT_8(0xF5, 0x7B, 0xDE, 0xCB, 0xD8, 0x39, 0x17, 0x7C), + MBEDTLS_BYTES_TO_T_UINT_8(0xD3, 0xF3, 0x03, 0xF2, 0x5C, 0xBC, 0xC8, 0x8A), + MBEDTLS_BYTES_TO_T_UINT_8(0x27, 0xAE, 0x4C, 0xB0, 0x16, 0xA4, 0x93, 0x86), + MBEDTLS_BYTES_TO_T_UINT_8(0x71, 0x8B, 0x6B, 0xDC, 0xD7, 0x9A, 0x3E, 0x7E), +}; +static const mbedtls_mpi_uint secp256k1_T_9_X[] = { + MBEDTLS_BYTES_TO_T_UINT_8(0xD6, 0x2D, 0x7A, 0xD2, 0x59, 0x05, 0xA2, 0x82), + MBEDTLS_BYTES_TO_T_UINT_8(0x57, 0x56, 0x09, 0x32, 0xF1, 0xE8, 0xE3, 0x72), + MBEDTLS_BYTES_TO_T_UINT_8(0x03, 0xCA, 0xE5, 0x2E, 0xF0, 0xFB, 0x18, 0x19), + MBEDTLS_BYTES_TO_T_UINT_8(0xBA, 0x85, 0xA9, 0x23, 0x15, 0x31, 0x1F, 0x0E), +}; +static const mbedtls_mpi_uint secp256k1_T_9_Y[] = { + MBEDTLS_BYTES_TO_T_UINT_8(0x76, 0xE5, 0xB1, 0x86, 0xB9, 0x6E, 0x8D, 0xD3), + MBEDTLS_BYTES_TO_T_UINT_8(0x6C, 0x77, 0xFC, 0xC9, 0xA3, 0x3F, 0x89, 0xD2), + MBEDTLS_BYTES_TO_T_UINT_8(0xDB, 0x6A, 0xDC, 0x25, 0xB0, 0xC7, 0x41, 0x54), + MBEDTLS_BYTES_TO_T_UINT_8(0x02, 0x11, 0x6B, 0xA6, 0x11, 0x62, 0xD4, 0x2D), +}; +static const mbedtls_mpi_uint secp256k1_T_10_X[] = { + MBEDTLS_BYTES_TO_T_UINT_8(0x19, 0x7D, 0x34, 0xB3, 0x20, 0x7F, 0x37, 0xAA), + MBEDTLS_BYTES_TO_T_UINT_8(0xBD, 0xD4, 0x45, 0xE8, 0xC2, 0xE9, 0xC5, 0xEA), + MBEDTLS_BYTES_TO_T_UINT_8(0x5A, 0x32, 0x3B, 0x25, 0x7E, 0x79, 0xAF, 0xE7), + MBEDTLS_BYTES_TO_T_UINT_8(0x3F, 0xE4, 0x54, 0x71, 0xBE, 0x35, 0x4E, 0xD0), +}; +static const mbedtls_mpi_uint secp256k1_T_10_Y[] = { + MBEDTLS_BYTES_TO_T_UINT_8(0xB0, 0x94, 0xDD, 0x8F, 0xB5, 0xC2, 0xDD, 0x75), + MBEDTLS_BYTES_TO_T_UINT_8(0x07, 0x49, 0xE9, 0x1C, 0x2F, 0x08, 0x49, 0xC6), + MBEDTLS_BYTES_TO_T_UINT_8(0x77, 0xB6, 0x03, 0x88, 0x6F, 0xB8, 0x15, 0x67), + MBEDTLS_BYTES_TO_T_UINT_8(0xA4, 0xD3, 0x1C, 0xF3, 0xA5, 0xEB, 0x79, 0x01), +}; +static const mbedtls_mpi_uint secp256k1_T_11_X[] = { + MBEDTLS_BYTES_TO_T_UINT_8(0x25, 0xF9, 0x43, 0x88, 0x89, 0x0D, 0x06, 0xEA), + MBEDTLS_BYTES_TO_T_UINT_8(0x02, 0x2D, 0xF5, 0x98, 0x32, 0xF6, 0xB1, 0x05), + MBEDTLS_BYTES_TO_T_UINT_8(0x23, 0x73, 0x8F, 0x2B, 0x50, 0x27, 0x0A, 0xE7), + MBEDTLS_BYTES_TO_T_UINT_8(0xA7, 0xE3, 0xBD, 0x16, 0x05, 0xC8, 0x93, 0x12), +}; +static const mbedtls_mpi_uint secp256k1_T_11_Y[] = { + MBEDTLS_BYTES_TO_T_UINT_8(0x0A, 0x6A, 0xF7, 0xE3, 0x3D, 0xDE, 0x5F, 0x2F), + MBEDTLS_BYTES_TO_T_UINT_8(0x47, 0xA3, 0x9C, 0x22, 0x3C, 0x33, 0x36, 0x5D), + MBEDTLS_BYTES_TO_T_UINT_8(0x20, 0x24, 0x4C, 0x69, 0x45, 0x78, 0x14, 0xAE), + MBEDTLS_BYTES_TO_T_UINT_8(0x59, 0xF8, 0xD4, 0xBF, 0xB8, 0xC0, 0xA1, 0x25), +}; +static const mbedtls_mpi_uint secp256k1_T_12_X[] = { + MBEDTLS_BYTES_TO_T_UINT_8(0x7E, 0x88, 0xE1, 0x91, 0x03, 0xEB, 0xB3, 0x2B), + MBEDTLS_BYTES_TO_T_UINT_8(0x5C, 0x11, 0xA1, 0xEF, 0x14, 0x0D, 0xC4, 0x7D), + MBEDTLS_BYTES_TO_T_UINT_8(0xFE, 0xD4, 0x0D, 0x1D, 0x96, 0x33, 0x5C, 0x19), + MBEDTLS_BYTES_TO_T_UINT_8(0x70, 0x45, 0x2A, 0x1A, 0xE6, 0x57, 0x04, 0x9B), +}; +static const mbedtls_mpi_uint secp256k1_T_12_Y[] = { + MBEDTLS_BYTES_TO_T_UINT_8(0x70, 0xB5, 0xA7, 0x80, 0xE9, 0x93, 0x97, 0x8D), + MBEDTLS_BYTES_TO_T_UINT_8(0x5D, 0xB9, 0x7C, 0xA0, 0xC9, 0x57, 0x26, 0x43), + MBEDTLS_BYTES_TO_T_UINT_8(0x9E, 0xEF, 0x56, 0xDA, 0x66, 0xF6, 0x1B, 0x9A), + MBEDTLS_BYTES_TO_T_UINT_8(0x1F, 0x89, 0x6B, 0x91, 0xE0, 0xA9, 0x65, 0x2B), +}; +static const mbedtls_mpi_uint secp256k1_T_13_X[] = { + MBEDTLS_BYTES_TO_T_UINT_8(0x91, 0x98, 0x96, 0x9B, 0x06, 0x7D, 0x5E, 0x5A), + MBEDTLS_BYTES_TO_T_UINT_8(0x0A, 0xFA, 0xC1, 0x5F, 0x19, 0x37, 0x94, 0x9D), + MBEDTLS_BYTES_TO_T_UINT_8(0xCF, 0xBE, 0x6B, 0x1A, 0x05, 0xE4, 0xBF, 0x9F), + MBEDTLS_BYTES_TO_T_UINT_8(0x84, 0xCD, 0x5D, 0x35, 0xB4, 0x51, 0xF7, 0x64), +}; +static const mbedtls_mpi_uint secp256k1_T_13_Y[] = { + MBEDTLS_BYTES_TO_T_UINT_8(0x6C, 0xEF, 0x96, 0xDB, 0xF2, 0x61, 0x63, 0x59), + MBEDTLS_BYTES_TO_T_UINT_8(0xCB, 0x04, 0x88, 0xC9, 0x9F, 0x1B, 0x94, 0xB9), + MBEDTLS_BYTES_TO_T_UINT_8(0xDB, 0x30, 0x79, 0x7E, 0x24, 0xE7, 0x5F, 0xB8), + MBEDTLS_BYTES_TO_T_UINT_8(0x3F, 0xB8, 0x90, 0xB7, 0x94, 0x25, 0xBB, 0x0F), +}; +static const mbedtls_mpi_uint secp256k1_T_14_X[] = { + MBEDTLS_BYTES_TO_T_UINT_8(0x62, 0x79, 0xEA, 0xAD, 0xC0, 0x6D, 0x18, 0x57), + MBEDTLS_BYTES_TO_T_UINT_8(0xE9, 0xA4, 0x58, 0x2A, 0x8D, 0x95, 0xB3, 0xE6), + MBEDTLS_BYTES_TO_T_UINT_8(0xC8, 0xC4, 0xC2, 0x12, 0x0D, 0x79, 0xE2, 0x2B), + MBEDTLS_BYTES_TO_T_UINT_8(0x02, 0x6F, 0xBE, 0x97, 0x4D, 0xA4, 0x20, 0x07), +}; +static const mbedtls_mpi_uint secp256k1_T_14_Y[] = { + MBEDTLS_BYTES_TO_T_UINT_8(0xCA, 0x31, 0x71, 0xC6, 0xA6, 0x91, 0xEB, 0x1F), + MBEDTLS_BYTES_TO_T_UINT_8(0xB4, 0x9B, 0xA8, 0x4A, 0xE7, 0x77, 0xE1, 0xAA), + MBEDTLS_BYTES_TO_T_UINT_8(0xA9, 0x06, 0xD3, 0x3D, 0x94, 0x30, 0xEF, 0x8C), + MBEDTLS_BYTES_TO_T_UINT_8(0xE7, 0xDF, 0xCA, 0xFA, 0xF5, 0x28, 0xF8, 0xC9), +}; +static const mbedtls_mpi_uint secp256k1_T_15_X[] = { + MBEDTLS_BYTES_TO_T_UINT_8(0xCC, 0xE1, 0x32, 0xFD, 0x3E, 0x81, 0xF8, 0x11), + MBEDTLS_BYTES_TO_T_UINT_8(0xCD, 0xF2, 0x4B, 0x1D, 0x19, 0xC9, 0x0F, 0xCC), + MBEDTLS_BYTES_TO_T_UINT_8(0x59, 0xB1, 0x8A, 0x22, 0x8B, 0x05, 0x6B, 0x56), + MBEDTLS_BYTES_TO_T_UINT_8(0x35, 0x21, 0xEF, 0x30, 0xEC, 0x09, 0x2A, 0x89), +}; +static const mbedtls_mpi_uint secp256k1_T_15_Y[] = { + MBEDTLS_BYTES_TO_T_UINT_8(0x15, 0x84, 0x4A, 0x46, 0x07, 0x6C, 0x3C, 0x4C), + MBEDTLS_BYTES_TO_T_UINT_8(0xDD, 0x18, 0x3A, 0xF4, 0xCC, 0xF5, 0xB2, 0xF2), + MBEDTLS_BYTES_TO_T_UINT_8(0x4F, 0x8F, 0xCD, 0x0A, 0x9C, 0xF4, 0xBD, 0x95), + MBEDTLS_BYTES_TO_T_UINT_8(0x37, 0x89, 0x7F, 0x8A, 0xB1, 0x52, 0x3A, 0xAB), }; +static const mbedtls_ecp_point secp256k1_T[16] = { + ECP_POINT_INIT_XY_Z1(secp256k1_T_0_X, secp256k1_T_0_Y), + ECP_POINT_INIT_XY_Z0(secp256k1_T_1_X, secp256k1_T_1_Y), + ECP_POINT_INIT_XY_Z0(secp256k1_T_2_X, secp256k1_T_2_Y), + ECP_POINT_INIT_XY_Z0(secp256k1_T_3_X, secp256k1_T_3_Y), + ECP_POINT_INIT_XY_Z0(secp256k1_T_4_X, secp256k1_T_4_Y), + ECP_POINT_INIT_XY_Z0(secp256k1_T_5_X, secp256k1_T_5_Y), + ECP_POINT_INIT_XY_Z0(secp256k1_T_6_X, secp256k1_T_6_Y), + ECP_POINT_INIT_XY_Z0(secp256k1_T_7_X, secp256k1_T_7_Y), + ECP_POINT_INIT_XY_Z0(secp256k1_T_8_X, secp256k1_T_8_Y), + ECP_POINT_INIT_XY_Z0(secp256k1_T_9_X, secp256k1_T_9_Y), + ECP_POINT_INIT_XY_Z0(secp256k1_T_10_X, secp256k1_T_10_Y), + ECP_POINT_INIT_XY_Z0(secp256k1_T_11_X, secp256k1_T_11_Y), + ECP_POINT_INIT_XY_Z0(secp256k1_T_12_X, secp256k1_T_12_Y), + ECP_POINT_INIT_XY_Z0(secp256k1_T_13_X, secp256k1_T_13_Y), + ECP_POINT_INIT_XY_Z0(secp256k1_T_14_X, secp256k1_T_14_Y), + ECP_POINT_INIT_XY_Z0(secp256k1_T_15_X, secp256k1_T_15_Y), +}; +#else +#define secp256k1_T NULL +#endif #endif /* MBEDTLS_ECP_DP_SECP256K1_ENABLED */ /* @@ -393,6 +2917,222 @@ static const mbedtls_mpi_uint brainpoolP256r1_n[] = { MBEDTLS_BYTES_TO_T_UINT_8(0x71, 0x8D, 0x83, 0x9D, 0x90, 0x0A, 0x66, 0x3E), MBEDTLS_BYTES_TO_T_UINT_8(0xBC, 0xA9, 0xEE, 0xA1, 0xDB, 0x57, 0xFB, 0xA9), }; + +#if MBEDTLS_ECP_FIXED_POINT_OPTIM == 1 +static const mbedtls_mpi_uint brainpoolP256r1_T_0_X[] = { + MBEDTLS_BYTES_TO_T_UINT_8(0x62, 0x32, 0xCE, 0x9A, 0xBD, 0x53, 0x44, 0x3A), + MBEDTLS_BYTES_TO_T_UINT_8(0xC2, 0x23, 0xBD, 0xE3, 0xE1, 0x27, 0xDE, 0xB9), + MBEDTLS_BYTES_TO_T_UINT_8(0xAF, 0xB7, 0x81, 0xFC, 0x2F, 0x48, 0x4B, 0x2C), + MBEDTLS_BYTES_TO_T_UINT_8(0xCB, 0x57, 0x7E, 0xCB, 0xB9, 0xAE, 0xD2, 0x8B), +}; +static const mbedtls_mpi_uint brainpoolP256r1_T_0_Y[] = { + MBEDTLS_BYTES_TO_T_UINT_8(0x97, 0x69, 0x04, 0x2F, 0xC7, 0x54, 0x1D, 0x5C), + MBEDTLS_BYTES_TO_T_UINT_8(0x54, 0x8E, 0xED, 0x2D, 0x13, 0x45, 0x77, 0xC2), + MBEDTLS_BYTES_TO_T_UINT_8(0xC9, 0x1D, 0x61, 0x14, 0x1A, 0x46, 0xF8, 0x97), + MBEDTLS_BYTES_TO_T_UINT_8(0xFD, 0xC4, 0xDA, 0xC3, 0x35, 0xF8, 0x7E, 0x54), +}; +static const mbedtls_mpi_uint brainpoolP256r1_T_1_X[] = { + MBEDTLS_BYTES_TO_T_UINT_8(0x3C, 0xA2, 0xED, 0x52, 0xC9, 0x8C, 0xE3, 0xA5), + MBEDTLS_BYTES_TO_T_UINT_8(0x72, 0xC9, 0xC4, 0x87, 0x3F, 0x93, 0x7A, 0xD1), + MBEDTLS_BYTES_TO_T_UINT_8(0x96, 0x12, 0x53, 0x61, 0x3E, 0x76, 0x08, 0xCB), + MBEDTLS_BYTES_TO_T_UINT_8(0x09, 0x8C, 0x74, 0xF4, 0x08, 0xC3, 0x76, 0x80), +}; +static const mbedtls_mpi_uint brainpoolP256r1_T_1_Y[] = { + MBEDTLS_BYTES_TO_T_UINT_8(0x05, 0xDD, 0x09, 0xA6, 0xED, 0xEE, 0xC4, 0x38), + MBEDTLS_BYTES_TO_T_UINT_8(0x74, 0xD9, 0xBE, 0x4B, 0xA5, 0xB7, 0x2B, 0x6E), + MBEDTLS_BYTES_TO_T_UINT_8(0x42, 0x20, 0x12, 0xCA, 0x0A, 0x38, 0x24, 0xAB), + MBEDTLS_BYTES_TO_T_UINT_8(0x00, 0x72, 0x71, 0x90, 0x7A, 0x2E, 0xB7, 0x23), +}; +static const mbedtls_mpi_uint brainpoolP256r1_T_2_X[] = { + MBEDTLS_BYTES_TO_T_UINT_8(0x2C, 0x66, 0xA1, 0x93, 0x10, 0x2A, 0x51, 0x17), + MBEDTLS_BYTES_TO_T_UINT_8(0x88, 0x10, 0x11, 0x12, 0xBC, 0xB0, 0xB6, 0x93), + MBEDTLS_BYTES_TO_T_UINT_8(0x3C, 0x58, 0xD7, 0x0A, 0x84, 0x05, 0xA3, 0x9C), + MBEDTLS_BYTES_TO_T_UINT_8(0xF7, 0x8E, 0x95, 0x61, 0xD3, 0x0B, 0xDF, 0x36), +}; +static const mbedtls_mpi_uint brainpoolP256r1_T_2_Y[] = { + MBEDTLS_BYTES_TO_T_UINT_8(0xF9, 0x92, 0x12, 0x0F, 0x5E, 0x87, 0x70, 0x1B), + MBEDTLS_BYTES_TO_T_UINT_8(0x38, 0xE9, 0x9B, 0xEB, 0x3A, 0xFB, 0xCF, 0xC4), + MBEDTLS_BYTES_TO_T_UINT_8(0xDC, 0x92, 0xB9, 0xF7, 0x45, 0xD3, 0x06, 0xB6), + MBEDTLS_BYTES_TO_T_UINT_8(0x82, 0x28, 0x65, 0xE1, 0xC5, 0x6C, 0x57, 0x18), +}; +static const mbedtls_mpi_uint brainpoolP256r1_T_3_X[] = { + MBEDTLS_BYTES_TO_T_UINT_8(0x28, 0x0E, 0x77, 0x01, 0x81, 0x9E, 0x38, 0x5C), + MBEDTLS_BYTES_TO_T_UINT_8(0x71, 0xF0, 0xD5, 0xA5, 0x91, 0x2B, 0xDF, 0xC0), + MBEDTLS_BYTES_TO_T_UINT_8(0xD8, 0xEE, 0xB6, 0x25, 0xD6, 0x98, 0xDE, 0x2D), + MBEDTLS_BYTES_TO_T_UINT_8(0x7B, 0xA1, 0x55, 0x63, 0x39, 0xEB, 0xB5, 0x47), +}; +static const mbedtls_mpi_uint brainpoolP256r1_T_3_Y[] = { + MBEDTLS_BYTES_TO_T_UINT_8(0xB6, 0xD6, 0xB8, 0xE3, 0x13, 0xED, 0x7F, 0xA3), + MBEDTLS_BYTES_TO_T_UINT_8(0x6C, 0xE8, 0xAE, 0x36, 0xB8, 0xCD, 0x19, 0x02), + MBEDTLS_BYTES_TO_T_UINT_8(0xF9, 0x82, 0x83, 0x7A, 0x7B, 0x46, 0x56, 0xE8), + MBEDTLS_BYTES_TO_T_UINT_8(0x4E, 0x60, 0x46, 0x15, 0x5A, 0xAC, 0x99, 0x30), +}; +static const mbedtls_mpi_uint brainpoolP256r1_T_4_X[] = { + MBEDTLS_BYTES_TO_T_UINT_8(0xBF, 0x61, 0x50, 0xC6, 0xFF, 0x10, 0x7D, 0x04), + MBEDTLS_BYTES_TO_T_UINT_8(0x92, 0x51, 0xDF, 0xA9, 0x7D, 0x78, 0x26, 0x74), + MBEDTLS_BYTES_TO_T_UINT_8(0x56, 0x15, 0x9A, 0xF7, 0x01, 0xC1, 0xBB, 0x40), + MBEDTLS_BYTES_TO_T_UINT_8(0x26, 0x0F, 0xE6, 0x2A, 0xBD, 0x4A, 0x9E, 0x87), +}; +static const mbedtls_mpi_uint brainpoolP256r1_T_4_Y[] = { + MBEDTLS_BYTES_TO_T_UINT_8(0x57, 0xF8, 0xD1, 0x77, 0xD2, 0x49, 0xB3, 0xDD), + MBEDTLS_BYTES_TO_T_UINT_8(0x36, 0x86, 0xFB, 0x9E, 0x1F, 0x5A, 0x60, 0x47), + MBEDTLS_BYTES_TO_T_UINT_8(0x98, 0xC4, 0x8D, 0xCD, 0x86, 0x61, 0x2F, 0xF9), + MBEDTLS_BYTES_TO_T_UINT_8(0x41, 0xF6, 0xB9, 0xAC, 0x37, 0x9D, 0xE9, 0x28), +}; +static const mbedtls_mpi_uint brainpoolP256r1_T_5_X[] = { + MBEDTLS_BYTES_TO_T_UINT_8(0xFA, 0x77, 0xAA, 0x97, 0x9C, 0x0B, 0x04, 0x20), + MBEDTLS_BYTES_TO_T_UINT_8(0x80, 0xA6, 0x60, 0x81, 0xCE, 0x25, 0x13, 0x3E), + MBEDTLS_BYTES_TO_T_UINT_8(0x24, 0x00, 0xF3, 0xBB, 0x82, 0x99, 0x95, 0xB7), + MBEDTLS_BYTES_TO_T_UINT_8(0x47, 0x5A, 0xCE, 0x90, 0x71, 0x38, 0x2F, 0x10), +}; +static const mbedtls_mpi_uint brainpoolP256r1_T_5_Y[] = { + MBEDTLS_BYTES_TO_T_UINT_8(0xA7, 0x1A, 0xC0, 0x84, 0x27, 0xD6, 0x9D, 0xB7), + MBEDTLS_BYTES_TO_T_UINT_8(0x34, 0x37, 0x52, 0x16, 0x13, 0x0E, 0xCE, 0x92), + MBEDTLS_BYTES_TO_T_UINT_8(0x1E, 0xBF, 0x5A, 0xDB, 0xDB, 0x6E, 0x1E, 0x69), + MBEDTLS_BYTES_TO_T_UINT_8(0x3E, 0xB7, 0x5E, 0xF9, 0x86, 0xDD, 0x8A, 0x5C), +}; +static const mbedtls_mpi_uint brainpoolP256r1_T_6_X[] = { + MBEDTLS_BYTES_TO_T_UINT_8(0x3D, 0xAB, 0x5C, 0x8D, 0x1D, 0xF2, 0x2D, 0x1E), + MBEDTLS_BYTES_TO_T_UINT_8(0x65, 0xC5, 0xF8, 0xF7, 0x1D, 0x96, 0x0B, 0x4D), + MBEDTLS_BYTES_TO_T_UINT_8(0xAC, 0x4C, 0xA7, 0x45, 0x20, 0x6A, 0x1E, 0x5B), + MBEDTLS_BYTES_TO_T_UINT_8(0x21, 0x5D, 0xEF, 0xDE, 0xEE, 0x39, 0x44, 0x19), +}; +static const mbedtls_mpi_uint brainpoolP256r1_T_6_Y[] = { + MBEDTLS_BYTES_TO_T_UINT_8(0x4B, 0x2F, 0x6D, 0x52, 0xC9, 0x58, 0x60, 0xE8), + MBEDTLS_BYTES_TO_T_UINT_8(0xC3, 0xC9, 0x62, 0xCB, 0x38, 0x3C, 0x55, 0xCA), + MBEDTLS_BYTES_TO_T_UINT_8(0xFF, 0xA5, 0x09, 0x10, 0x88, 0xDB, 0xE3, 0xBD), + MBEDTLS_BYTES_TO_T_UINT_8(0x52, 0xE0, 0x3C, 0xCE, 0x06, 0x0B, 0x4B, 0x5D), +}; +static const mbedtls_mpi_uint brainpoolP256r1_T_7_X[] = { + MBEDTLS_BYTES_TO_T_UINT_8(0xB1, 0x1D, 0xB4, 0x10, 0x76, 0x8F, 0xBA, 0x09), + MBEDTLS_BYTES_TO_T_UINT_8(0x57, 0x70, 0x5A, 0x07, 0xF5, 0x1A, 0x74, 0xC7), + MBEDTLS_BYTES_TO_T_UINT_8(0x0B, 0xE9, 0x94, 0xA8, 0xC0, 0xD5, 0x4A, 0x4A), + MBEDTLS_BYTES_TO_T_UINT_8(0x3E, 0x6D, 0xD4, 0xE8, 0x9B, 0xE9, 0x6D, 0x0E), +}; +static const mbedtls_mpi_uint brainpoolP256r1_T_7_Y[] = { + MBEDTLS_BYTES_TO_T_UINT_8(0x65, 0x00, 0x32, 0x41, 0x57, 0x84, 0x89, 0x52), + MBEDTLS_BYTES_TO_T_UINT_8(0xEE, 0xC7, 0x14, 0xEC, 0xE9, 0x27, 0xFF, 0xF3), + MBEDTLS_BYTES_TO_T_UINT_8(0x9A, 0x67, 0x9E, 0xFB, 0xB6, 0xB8, 0x96, 0xF3), + MBEDTLS_BYTES_TO_T_UINT_8(0xE5, 0x4A, 0xE3, 0x97, 0x4B, 0x58, 0xDE, 0x30), +}; +static const mbedtls_mpi_uint brainpoolP256r1_T_8_X[] = { + MBEDTLS_BYTES_TO_T_UINT_8(0xA6, 0x1E, 0x5C, 0xF5, 0x7F, 0xD5, 0xD4, 0xAA), + MBEDTLS_BYTES_TO_T_UINT_8(0x5D, 0x08, 0x7A, 0xF1, 0xBD, 0x89, 0xC7, 0x1E), + MBEDTLS_BYTES_TO_T_UINT_8(0x3A, 0xF9, 0x11, 0x1B, 0xF5, 0x3C, 0x6D, 0x8C), + MBEDTLS_BYTES_TO_T_UINT_8(0x19, 0x50, 0xE5, 0x69, 0x1D, 0x59, 0xFC, 0x0C), +}; +static const mbedtls_mpi_uint brainpoolP256r1_T_8_Y[] = { + MBEDTLS_BYTES_TO_T_UINT_8(0xF1, 0x2F, 0xF8, 0x3F, 0xEC, 0x55, 0x99, 0x57), + MBEDTLS_BYTES_TO_T_UINT_8(0x41, 0xA7, 0x29, 0x90, 0x43, 0x81, 0x31, 0x4C), + MBEDTLS_BYTES_TO_T_UINT_8(0xC3, 0x18, 0x44, 0x50, 0x5D, 0x76, 0xCB, 0xDD), + MBEDTLS_BYTES_TO_T_UINT_8(0xF0, 0xC5, 0x5B, 0x9A, 0x03, 0xE6, 0x17, 0x39), +}; +static const mbedtls_mpi_uint brainpoolP256r1_T_9_X[] = { + MBEDTLS_BYTES_TO_T_UINT_8(0x21, 0x89, 0xFC, 0x55, 0x94, 0x91, 0x6A, 0xA2), + MBEDTLS_BYTES_TO_T_UINT_8(0x74, 0x46, 0x35, 0xF2, 0x3A, 0x42, 0x08, 0x2F), + MBEDTLS_BYTES_TO_T_UINT_8(0xD3, 0xD2, 0x76, 0x49, 0x42, 0x87, 0xD3, 0x7F), + MBEDTLS_BYTES_TO_T_UINT_8(0x90, 0xEA, 0xA0, 0x52, 0xF1, 0x6A, 0x30, 0x57), +}; +static const mbedtls_mpi_uint brainpoolP256r1_T_9_Y[] = { + MBEDTLS_BYTES_TO_T_UINT_8(0x00, 0xB2, 0x57, 0xA3, 0x8A, 0x4D, 0x1B, 0x3C), + MBEDTLS_BYTES_TO_T_UINT_8(0xFC, 0xA3, 0x99, 0x94, 0xB5, 0x3D, 0x64, 0x09), + MBEDTLS_BYTES_TO_T_UINT_8(0x35, 0xC3, 0xD7, 0x53, 0xF6, 0x49, 0x1C, 0x60), + MBEDTLS_BYTES_TO_T_UINT_8(0x27, 0x23, 0x41, 0x4D, 0xFB, 0x7A, 0x5C, 0x53), +}; +static const mbedtls_mpi_uint brainpoolP256r1_T_10_X[] = { + MBEDTLS_BYTES_TO_T_UINT_8(0xCA, 0xB8, 0x15, 0x65, 0x5C, 0x85, 0x94, 0xD7), + MBEDTLS_BYTES_TO_T_UINT_8(0xAC, 0x37, 0xC7, 0xF8, 0x7E, 0xAE, 0x6C, 0x10), + MBEDTLS_BYTES_TO_T_UINT_8(0x53, 0xD8, 0x11, 0x54, 0x98, 0x44, 0xE3, 0xF1), + MBEDTLS_BYTES_TO_T_UINT_8(0xE4, 0x4D, 0xA6, 0x4B, 0x28, 0xF2, 0x57, 0x9E), +}; +static const mbedtls_mpi_uint brainpoolP256r1_T_10_Y[] = { + MBEDTLS_BYTES_TO_T_UINT_8(0xF6, 0xD0, 0xEB, 0x1E, 0xAA, 0x30, 0xD3, 0x6A), + MBEDTLS_BYTES_TO_T_UINT_8(0x58, 0x9B, 0x4D, 0xA7, 0x73, 0x6E, 0xB6, 0x45), + MBEDTLS_BYTES_TO_T_UINT_8(0x5D, 0x47, 0xF6, 0xED, 0x37, 0xEF, 0x71, 0x4D), + MBEDTLS_BYTES_TO_T_UINT_8(0xA8, 0xB5, 0x49, 0x61, 0x5E, 0x45, 0xF6, 0x4A), +}; +static const mbedtls_mpi_uint brainpoolP256r1_T_11_X[] = { + MBEDTLS_BYTES_TO_T_UINT_8(0xEF, 0x0E, 0xB3, 0x84, 0x3A, 0x63, 0x72, 0x84), + MBEDTLS_BYTES_TO_T_UINT_8(0x6D, 0x53, 0x5C, 0xA7, 0xC6, 0x2E, 0xAB, 0x9E), + MBEDTLS_BYTES_TO_T_UINT_8(0xEB, 0x0F, 0x8F, 0x87, 0x50, 0x28, 0xB4, 0xAE), + MBEDTLS_BYTES_TO_T_UINT_8(0x5C, 0x98, 0x4A, 0x98, 0x31, 0x86, 0xCA, 0x51), +}; +static const mbedtls_mpi_uint brainpoolP256r1_T_11_Y[] = { + MBEDTLS_BYTES_TO_T_UINT_8(0xBE, 0xC9, 0xE2, 0xFD, 0x5D, 0x1F, 0xE8, 0xC2), + MBEDTLS_BYTES_TO_T_UINT_8(0xD5, 0x90, 0x91, 0xC4, 0x84, 0xF0, 0xBA, 0xC5), + MBEDTLS_BYTES_TO_T_UINT_8(0x6C, 0x5A, 0xB3, 0x4E, 0xFB, 0xE0, 0x57, 0xE8), + MBEDTLS_BYTES_TO_T_UINT_8(0x6B, 0x0B, 0x90, 0xA6, 0xFD, 0x9D, 0x8E, 0x02), +}; +static const mbedtls_mpi_uint brainpoolP256r1_T_12_X[] = { + MBEDTLS_BYTES_TO_T_UINT_8(0xF8, 0x41, 0x8F, 0x31, 0xFA, 0x5A, 0xF6, 0x33), + MBEDTLS_BYTES_TO_T_UINT_8(0xAC, 0xE9, 0xE3, 0xF6, 0xE0, 0x4A, 0xE7, 0xD2), + MBEDTLS_BYTES_TO_T_UINT_8(0x84, 0x4E, 0xCD, 0xA2, 0x22, 0x14, 0xD4, 0x12), + MBEDTLS_BYTES_TO_T_UINT_8(0x7C, 0xED, 0x21, 0xB7, 0x0F, 0x53, 0x10, 0x17), +}; +static const mbedtls_mpi_uint brainpoolP256r1_T_12_Y[] = { + MBEDTLS_BYTES_TO_T_UINT_8(0x05, 0x06, 0x24, 0x2C, 0x4E, 0xD1, 0x1E, 0x9F), + MBEDTLS_BYTES_TO_T_UINT_8(0xD7, 0x3F, 0xC1, 0x9F, 0xAB, 0xF0, 0x37, 0x95), + MBEDTLS_BYTES_TO_T_UINT_8(0x03, 0x5E, 0x12, 0xCE, 0x83, 0x1B, 0x2A, 0x18), + MBEDTLS_BYTES_TO_T_UINT_8(0x61, 0x65, 0xCF, 0xE8, 0x5C, 0xA5, 0xA2, 0x70), +}; +static const mbedtls_mpi_uint brainpoolP256r1_T_13_X[] = { + MBEDTLS_BYTES_TO_T_UINT_8(0xB8, 0x86, 0x76, 0x3A, 0x94, 0xF6, 0x1D, 0xC1), + MBEDTLS_BYTES_TO_T_UINT_8(0x1D, 0xDA, 0xC9, 0xA6, 0x29, 0x93, 0x15, 0x10), + MBEDTLS_BYTES_TO_T_UINT_8(0x6D, 0x61, 0x6A, 0x7D, 0xC7, 0xA9, 0xF3, 0x76), + MBEDTLS_BYTES_TO_T_UINT_8(0x4A, 0x03, 0x71, 0xA2, 0x15, 0xCE, 0x50, 0x72), +}; +static const mbedtls_mpi_uint brainpoolP256r1_T_13_Y[] = { + MBEDTLS_BYTES_TO_T_UINT_8(0xB6, 0xD0, 0xA8, 0x1E, 0x91, 0xC4, 0x4F, 0x24), + MBEDTLS_BYTES_TO_T_UINT_8(0x2D, 0x4B, 0x7E, 0xD7, 0x71, 0x58, 0x7E, 0x1E), + MBEDTLS_BYTES_TO_T_UINT_8(0x93, 0x45, 0xAF, 0x2A, 0x18, 0x93, 0x95, 0x3B), + MBEDTLS_BYTES_TO_T_UINT_8(0x1B, 0x8F, 0xC7, 0xFA, 0x4C, 0x7A, 0x86, 0x54), +}; +static const mbedtls_mpi_uint brainpoolP256r1_T_14_X[] = { + MBEDTLS_BYTES_TO_T_UINT_8(0x97, 0xAF, 0x68, 0x3A, 0x23, 0xC1, 0x2E, 0xBF), + MBEDTLS_BYTES_TO_T_UINT_8(0x89, 0x50, 0x11, 0x67, 0x39, 0xB9, 0xAF, 0x48), + MBEDTLS_BYTES_TO_T_UINT_8(0x19, 0x86, 0xAA, 0x1E, 0x88, 0x21, 0x29, 0x8B), + MBEDTLS_BYTES_TO_T_UINT_8(0xCD, 0x28, 0xA4, 0x9D, 0x89, 0xA9, 0x9A, 0x10), +}; +static const mbedtls_mpi_uint brainpoolP256r1_T_14_Y[] = { + MBEDTLS_BYTES_TO_T_UINT_8(0x91, 0xBA, 0x04, 0x67, 0xB7, 0x01, 0x40, 0x38), + MBEDTLS_BYTES_TO_T_UINT_8(0x08, 0xE9, 0x09, 0xA3, 0xCA, 0xA6, 0x37, 0xF6), + MBEDTLS_BYTES_TO_T_UINT_8(0x6C, 0x97, 0xA8, 0xB6, 0x3C, 0xEE, 0x90, 0x3D), + MBEDTLS_BYTES_TO_T_UINT_8(0xDC, 0xED, 0xC4, 0xF7, 0xC3, 0x95, 0xEC, 0x85), +}; +static const mbedtls_mpi_uint brainpoolP256r1_T_15_X[] = { + MBEDTLS_BYTES_TO_T_UINT_8(0xF5, 0x84, 0xBD, 0xEB, 0xD5, 0x64, 0xBB, 0x9D), + MBEDTLS_BYTES_TO_T_UINT_8(0xDB, 0x9B, 0xE2, 0x28, 0x50, 0xC2, 0x72, 0x40), + MBEDTLS_BYTES_TO_T_UINT_8(0x39, 0xF2, 0x74, 0xD1, 0x26, 0xBF, 0x32, 0x68), + MBEDTLS_BYTES_TO_T_UINT_8(0x36, 0xCB, 0xAF, 0x72, 0xDB, 0x6D, 0x30, 0x98), +}; +static const mbedtls_mpi_uint brainpoolP256r1_T_15_Y[] = { + MBEDTLS_BYTES_TO_T_UINT_8(0xB3, 0x50, 0x85, 0xF4, 0x2B, 0x48, 0xC1, 0xAD), + MBEDTLS_BYTES_TO_T_UINT_8(0xC0, 0x28, 0xBB, 0x11, 0xBA, 0x5B, 0x22, 0x6C), + MBEDTLS_BYTES_TO_T_UINT_8(0xAD, 0xA1, 0xE5, 0x5C, 0xC9, 0x1D, 0x44, 0x45), + MBEDTLS_BYTES_TO_T_UINT_8(0xD4, 0xE8, 0xE6, 0x6F, 0xBB, 0xC1, 0x81, 0x7F), +}; +static const mbedtls_ecp_point brainpoolP256r1_T[16] = { + ECP_POINT_INIT_XY_Z1(brainpoolP256r1_T_0_X, brainpoolP256r1_T_0_Y), + ECP_POINT_INIT_XY_Z0(brainpoolP256r1_T_1_X, brainpoolP256r1_T_1_Y), + ECP_POINT_INIT_XY_Z0(brainpoolP256r1_T_2_X, brainpoolP256r1_T_2_Y), + ECP_POINT_INIT_XY_Z0(brainpoolP256r1_T_3_X, brainpoolP256r1_T_3_Y), + ECP_POINT_INIT_XY_Z0(brainpoolP256r1_T_4_X, brainpoolP256r1_T_4_Y), + ECP_POINT_INIT_XY_Z0(brainpoolP256r1_T_5_X, brainpoolP256r1_T_5_Y), + ECP_POINT_INIT_XY_Z0(brainpoolP256r1_T_6_X, brainpoolP256r1_T_6_Y), + ECP_POINT_INIT_XY_Z0(brainpoolP256r1_T_7_X, brainpoolP256r1_T_7_Y), + ECP_POINT_INIT_XY_Z0(brainpoolP256r1_T_8_X, brainpoolP256r1_T_8_Y), + ECP_POINT_INIT_XY_Z0(brainpoolP256r1_T_9_X, brainpoolP256r1_T_9_Y), + ECP_POINT_INIT_XY_Z0(brainpoolP256r1_T_10_X, brainpoolP256r1_T_10_Y), + ECP_POINT_INIT_XY_Z0(brainpoolP256r1_T_11_X, brainpoolP256r1_T_11_Y), + ECP_POINT_INIT_XY_Z0(brainpoolP256r1_T_12_X, brainpoolP256r1_T_12_Y), + ECP_POINT_INIT_XY_Z0(brainpoolP256r1_T_13_X, brainpoolP256r1_T_13_Y), + ECP_POINT_INIT_XY_Z0(brainpoolP256r1_T_14_X, brainpoolP256r1_T_14_Y), + ECP_POINT_INIT_XY_Z0(brainpoolP256r1_T_15_X, brainpoolP256r1_T_15_Y), +}; +#else +#define brainpoolP256r1_T NULL +#endif + #endif /* MBEDTLS_ECP_DP_BP256R1_ENABLED */ /* @@ -447,6 +3187,558 @@ static const mbedtls_mpi_uint brainpoolP384r1_n[] = { MBEDTLS_BYTES_TO_T_UINT_8(0xDF, 0x41, 0xE6, 0x50, 0x7E, 0x6F, 0x5D, 0x0F), MBEDTLS_BYTES_TO_T_UINT_8(0x28, 0x6D, 0x38, 0xA3, 0x82, 0x1E, 0xB9, 0x8C), }; + +#if MBEDTLS_ECP_FIXED_POINT_OPTIM == 1 +static const mbedtls_mpi_uint brainpoolP384r1_T_0_X[] = { + MBEDTLS_BYTES_TO_T_UINT_8(0x1E, 0xAF, 0xD4, 0x47, 0xE2, 0xB2, 0x87, 0xEF), + MBEDTLS_BYTES_TO_T_UINT_8(0xAA, 0x46, 0xD6, 0x36, 0x34, 0xE0, 0x26, 0xE8), + MBEDTLS_BYTES_TO_T_UINT_8(0xE8, 0x10, 0xBD, 0x0C, 0xFE, 0xCA, 0x7F, 0xDB), + MBEDTLS_BYTES_TO_T_UINT_8(0xE3, 0x4F, 0xF1, 0x7E, 0xE7, 0xA3, 0x47, 0x88), + MBEDTLS_BYTES_TO_T_UINT_8(0x6B, 0x3F, 0xC1, 0xB7, 0x81, 0x3A, 0xA6, 0xA2), + MBEDTLS_BYTES_TO_T_UINT_8(0xFF, 0x45, 0xCF, 0x68, 0xF0, 0x64, 0x1C, 0x1D), +}; +static const mbedtls_mpi_uint brainpoolP384r1_T_0_Y[] = { + MBEDTLS_BYTES_TO_T_UINT_8(0x15, 0x53, 0x3C, 0x26, 0x41, 0x03, 0x82, 0x42), + MBEDTLS_BYTES_TO_T_UINT_8(0x11, 0x81, 0x91, 0x77, 0x21, 0x46, 0x46, 0x0E), + MBEDTLS_BYTES_TO_T_UINT_8(0x28, 0x29, 0x91, 0xF9, 0x4F, 0x05, 0x9C, 0xE1), + MBEDTLS_BYTES_TO_T_UINT_8(0x64, 0x58, 0xEC, 0xFE, 0x29, 0x0B, 0xB7, 0x62), + MBEDTLS_BYTES_TO_T_UINT_8(0x52, 0xD5, 0xCF, 0x95, 0x8E, 0xEB, 0xB1, 0x5C), + MBEDTLS_BYTES_TO_T_UINT_8(0xA4, 0xC2, 0xF9, 0x20, 0x75, 0x1D, 0xBE, 0x8A), +}; +static const mbedtls_mpi_uint brainpoolP384r1_T_1_X[] = { + MBEDTLS_BYTES_TO_T_UINT_8(0x93, 0xD8, 0x8A, 0x54, 0x41, 0xD6, 0x6B, 0x1D), + MBEDTLS_BYTES_TO_T_UINT_8(0xE2, 0x3B, 0xF1, 0x22, 0xFD, 0x2D, 0x4B, 0x03), + MBEDTLS_BYTES_TO_T_UINT_8(0x01, 0x55, 0xE3, 0x33, 0xF0, 0x73, 0x52, 0x5A), + MBEDTLS_BYTES_TO_T_UINT_8(0xC1, 0x3F, 0x30, 0x26, 0xCA, 0x7F, 0x52, 0xA3), + MBEDTLS_BYTES_TO_T_UINT_8(0xD3, 0x6E, 0x17, 0x9B, 0xD5, 0x2A, 0x4A, 0x31), + MBEDTLS_BYTES_TO_T_UINT_8(0x86, 0xDA, 0x6B, 0xE5, 0x03, 0x07, 0x1D, 0x2E), +}; +static const mbedtls_mpi_uint brainpoolP384r1_T_1_Y[] = { + MBEDTLS_BYTES_TO_T_UINT_8(0x51, 0x7A, 0xAF, 0x98, 0xE3, 0xA4, 0xF6, 0x19), + MBEDTLS_BYTES_TO_T_UINT_8(0xEC, 0x7D, 0xFE, 0x51, 0x40, 0x3B, 0x47, 0xD2), + MBEDTLS_BYTES_TO_T_UINT_8(0xFC, 0x88, 0xEC, 0xC4, 0xE2, 0x8F, 0xCB, 0xA4), + MBEDTLS_BYTES_TO_T_UINT_8(0x30, 0xE2, 0x88, 0x2D, 0x4E, 0x50, 0xEB, 0x9A), + MBEDTLS_BYTES_TO_T_UINT_8(0x13, 0x54, 0x94, 0x5E, 0xF4, 0x7F, 0x3A, 0x04), + MBEDTLS_BYTES_TO_T_UINT_8(0xCD, 0x07, 0x1C, 0xE1, 0xBD, 0x0F, 0xF8, 0x63), +}; +static const mbedtls_mpi_uint brainpoolP384r1_T_2_X[] = { + MBEDTLS_BYTES_TO_T_UINT_8(0x94, 0x92, 0x28, 0x2E, 0x32, 0x04, 0xB1, 0x4D), + MBEDTLS_BYTES_TO_T_UINT_8(0x25, 0x82, 0x44, 0x43, 0x76, 0x0D, 0x55, 0xBF), + MBEDTLS_BYTES_TO_T_UINT_8(0x5B, 0xE3, 0xFF, 0x89, 0x46, 0xDE, 0x4E, 0xFE), + MBEDTLS_BYTES_TO_T_UINT_8(0x5B, 0x22, 0xBB, 0x67, 0x1A, 0x81, 0xEE, 0x27), + MBEDTLS_BYTES_TO_T_UINT_8(0xC8, 0x54, 0xE2, 0x7A, 0xAE, 0xDA, 0x2C, 0xD0), + MBEDTLS_BYTES_TO_T_UINT_8(0x74, 0x9A, 0x90, 0xAA, 0x6E, 0x8B, 0xCC, 0x5F), +}; +static const mbedtls_mpi_uint brainpoolP384r1_T_2_Y[] = { + MBEDTLS_BYTES_TO_T_UINT_8(0x16, 0x40, 0xAC, 0xED, 0x7D, 0x37, 0x87, 0xAC), + MBEDTLS_BYTES_TO_T_UINT_8(0x98, 0xF8, 0xB1, 0x80, 0x4C, 0x8C, 0x04, 0x42), + MBEDTLS_BYTES_TO_T_UINT_8(0xC2, 0x98, 0x2C, 0xAD, 0x30, 0x69, 0x35, 0xC0), + MBEDTLS_BYTES_TO_T_UINT_8(0x32, 0x2E, 0x00, 0x2F, 0x44, 0x8C, 0xF0, 0xC0), + MBEDTLS_BYTES_TO_T_UINT_8(0x16, 0x58, 0x07, 0xD7, 0xCD, 0x60, 0xA1, 0x5B), + MBEDTLS_BYTES_TO_T_UINT_8(0xAF, 0xFB, 0x7B, 0x03, 0x05, 0x5E, 0x79, 0x73), +}; +static const mbedtls_mpi_uint brainpoolP384r1_T_3_X[] = { + MBEDTLS_BYTES_TO_T_UINT_8(0xC8, 0x17, 0xCE, 0x38, 0x4B, 0x5E, 0x5B, 0xC8), + MBEDTLS_BYTES_TO_T_UINT_8(0x60, 0x0E, 0x0A, 0x61, 0x9D, 0x7C, 0x62, 0x08), + MBEDTLS_BYTES_TO_T_UINT_8(0x25, 0xF0, 0x98, 0x71, 0x7F, 0x17, 0x26, 0xD7), + MBEDTLS_BYTES_TO_T_UINT_8(0x83, 0xD3, 0xFA, 0x3C, 0xF0, 0x70, 0x07, 0x82), + MBEDTLS_BYTES_TO_T_UINT_8(0x29, 0x47, 0x5C, 0x09, 0x43, 0xB7, 0x65, 0x15), + MBEDTLS_BYTES_TO_T_UINT_8(0x0E, 0xA9, 0xA7, 0x3E, 0xFA, 0xF3, 0xEC, 0x22), +}; +static const mbedtls_mpi_uint brainpoolP384r1_T_3_Y[] = { + MBEDTLS_BYTES_TO_T_UINT_8(0xDA, 0x78, 0x22, 0x2B, 0x58, 0x71, 0xFA, 0xAA), + MBEDTLS_BYTES_TO_T_UINT_8(0x00, 0x30, 0xCE, 0x6A, 0xB3, 0xB0, 0x4F, 0x83), + MBEDTLS_BYTES_TO_T_UINT_8(0xCF, 0x95, 0x20, 0xA9, 0x23, 0xC2, 0x65, 0xE7), + MBEDTLS_BYTES_TO_T_UINT_8(0x55, 0xCF, 0x03, 0x5B, 0x8A, 0x80, 0x44, 0xBB), + MBEDTLS_BYTES_TO_T_UINT_8(0x5C, 0xF8, 0x91, 0xF7, 0xD5, 0xED, 0xEA, 0x81), + MBEDTLS_BYTES_TO_T_UINT_8(0x40, 0x5B, 0x16, 0x10, 0x25, 0xAC, 0x2A, 0x17), +}; +static const mbedtls_mpi_uint brainpoolP384r1_T_4_X[] = { + MBEDTLS_BYTES_TO_T_UINT_8(0xF2, 0xEC, 0xDC, 0xC4, 0x7B, 0x8C, 0x6B, 0xE9), + MBEDTLS_BYTES_TO_T_UINT_8(0x2B, 0xBB, 0x1C, 0xD3, 0x5A, 0xEE, 0xD9, 0x97), + MBEDTLS_BYTES_TO_T_UINT_8(0x64, 0x5D, 0x30, 0x5E, 0xF7, 0xB2, 0x41, 0x9D), + MBEDTLS_BYTES_TO_T_UINT_8(0xED, 0xCE, 0x0F, 0x1A, 0xC6, 0x41, 0x64, 0x62), + MBEDTLS_BYTES_TO_T_UINT_8(0xF2, 0x18, 0xE1, 0xE3, 0x82, 0x15, 0x66, 0x4B), + MBEDTLS_BYTES_TO_T_UINT_8(0x9B, 0xE2, 0x24, 0x04, 0x72, 0x39, 0xA0, 0x7C), +}; +static const mbedtls_mpi_uint brainpoolP384r1_T_4_Y[] = { + MBEDTLS_BYTES_TO_T_UINT_8(0x2B, 0x51, 0xA2, 0x58, 0x88, 0x62, 0xE1, 0x02), + MBEDTLS_BYTES_TO_T_UINT_8(0x58, 0xD2, 0x65, 0x14, 0xE9, 0x4C, 0x82, 0x30), + MBEDTLS_BYTES_TO_T_UINT_8(0xDC, 0xE1, 0xAC, 0x87, 0xAE, 0x31, 0x1A, 0x7A), + MBEDTLS_BYTES_TO_T_UINT_8(0x85, 0x4F, 0x96, 0x1E, 0x85, 0x7A, 0xC3, 0x2B), + MBEDTLS_BYTES_TO_T_UINT_8(0xF0, 0x86, 0xBB, 0xF0, 0xC0, 0x9D, 0x08, 0x7B), + MBEDTLS_BYTES_TO_T_UINT_8(0xBD, 0x53, 0x03, 0x09, 0x80, 0x91, 0xEF, 0x68), +}; +static const mbedtls_mpi_uint brainpoolP384r1_T_5_X[] = { + MBEDTLS_BYTES_TO_T_UINT_8(0x2D, 0xD7, 0xAF, 0x6F, 0x69, 0x7B, 0x88, 0xA1), + MBEDTLS_BYTES_TO_T_UINT_8(0xAF, 0x13, 0xE4, 0x30, 0xA2, 0x47, 0xB5, 0xC1), + MBEDTLS_BYTES_TO_T_UINT_8(0x0F, 0xD2, 0xC0, 0xDD, 0x8A, 0x1C, 0x3C, 0xF2), + MBEDTLS_BYTES_TO_T_UINT_8(0xF9, 0x8C, 0xB3, 0x4C, 0xBA, 0x8B, 0x6D, 0xCF), + MBEDTLS_BYTES_TO_T_UINT_8(0x6B, 0xC7, 0xA1, 0xA8, 0x6E, 0x3C, 0x4F, 0xF1), + MBEDTLS_BYTES_TO_T_UINT_8(0x94, 0x4A, 0x97, 0xC8, 0x03, 0x6F, 0x01, 0x82), +}; +static const mbedtls_mpi_uint brainpoolP384r1_T_5_Y[] = { + MBEDTLS_BYTES_TO_T_UINT_8(0x74, 0x18, 0x12, 0xA9, 0x39, 0xD5, 0x22, 0x26), + MBEDTLS_BYTES_TO_T_UINT_8(0x47, 0xA7, 0xC0, 0xBD, 0x9D, 0x8D, 0x78, 0x38), + MBEDTLS_BYTES_TO_T_UINT_8(0xA9, 0xB3, 0xD0, 0x7F, 0xDF, 0xD0, 0x30, 0xDE), + MBEDTLS_BYTES_TO_T_UINT_8(0x37, 0x25, 0x73, 0x96, 0xEC, 0xA8, 0x1D, 0x7C), + MBEDTLS_BYTES_TO_T_UINT_8(0x91, 0xD1, 0x65, 0x66, 0xDC, 0xD9, 0xCF, 0xDF), + MBEDTLS_BYTES_TO_T_UINT_8(0x95, 0xED, 0x7B, 0x37, 0xAD, 0xE2, 0xBE, 0x2D), +}; +static const mbedtls_mpi_uint brainpoolP384r1_T_6_X[] = { + MBEDTLS_BYTES_TO_T_UINT_8(0x50, 0x79, 0x42, 0x6A, 0x07, 0x66, 0xB1, 0xBD), + MBEDTLS_BYTES_TO_T_UINT_8(0x45, 0x53, 0x62, 0x65, 0x92, 0x09, 0x4C, 0xA1), + MBEDTLS_BYTES_TO_T_UINT_8(0x06, 0xAF, 0xC3, 0x03, 0xF6, 0xF4, 0x2D, 0x9B), + MBEDTLS_BYTES_TO_T_UINT_8(0xE8, 0xCA, 0x41, 0xD9, 0xA2, 0x69, 0x9B, 0xC9), + MBEDTLS_BYTES_TO_T_UINT_8(0x4B, 0xB2, 0xA6, 0x8D, 0xE1, 0xAA, 0x61, 0x76), + MBEDTLS_BYTES_TO_T_UINT_8(0x11, 0xBA, 0x4D, 0x12, 0xB6, 0xBE, 0xF3, 0x7E), +}; +static const mbedtls_mpi_uint brainpoolP384r1_T_6_Y[] = { + MBEDTLS_BYTES_TO_T_UINT_8(0xCA, 0xD9, 0x92, 0x22, 0x07, 0xCE, 0xC9, 0x26), + MBEDTLS_BYTES_TO_T_UINT_8(0x62, 0xA1, 0x7C, 0x91, 0xDB, 0x32, 0xF7, 0xE5), + MBEDTLS_BYTES_TO_T_UINT_8(0x6D, 0x49, 0x4B, 0x6D, 0xFB, 0xD9, 0x70, 0x3B), + MBEDTLS_BYTES_TO_T_UINT_8(0x1C, 0xFB, 0x4E, 0x4C, 0x5E, 0x66, 0x81, 0x1D), + MBEDTLS_BYTES_TO_T_UINT_8(0xA5, 0xB3, 0xE1, 0x00, 0xB7, 0xD9, 0xCC, 0x58), + MBEDTLS_BYTES_TO_T_UINT_8(0xF3, 0x36, 0x8B, 0xC4, 0x39, 0x20, 0xFD, 0x30), +}; +static const mbedtls_mpi_uint brainpoolP384r1_T_7_X[] = { + MBEDTLS_BYTES_TO_T_UINT_8(0x94, 0x1F, 0x60, 0x03, 0xBB, 0xD7, 0x60, 0x57), + MBEDTLS_BYTES_TO_T_UINT_8(0x72, 0x3C, 0x62, 0xDD, 0x71, 0x95, 0xE9, 0x61), + MBEDTLS_BYTES_TO_T_UINT_8(0xB0, 0x5B, 0x7A, 0x5F, 0x68, 0x81, 0xC5, 0x90), + MBEDTLS_BYTES_TO_T_UINT_8(0x1E, 0xAF, 0xB5, 0xB9, 0x98, 0x42, 0x28, 0xA5), + MBEDTLS_BYTES_TO_T_UINT_8(0x0C, 0x29, 0x8E, 0x11, 0x49, 0xB4, 0xD7, 0x20), + MBEDTLS_BYTES_TO_T_UINT_8(0x9B, 0x3E, 0xD2, 0x30, 0xA1, 0xBA, 0xCA, 0x03), +}; +static const mbedtls_mpi_uint brainpoolP384r1_T_7_Y[] = { + MBEDTLS_BYTES_TO_T_UINT_8(0x29, 0x37, 0x64, 0x44, 0x2F, 0x03, 0xE5, 0x41), + MBEDTLS_BYTES_TO_T_UINT_8(0x4A, 0x42, 0xBC, 0xFF, 0xA2, 0x1A, 0x5F, 0x06), + MBEDTLS_BYTES_TO_T_UINT_8(0x1D, 0x04, 0xAB, 0x04, 0xE0, 0x24, 0xAD, 0x2A), + MBEDTLS_BYTES_TO_T_UINT_8(0x3D, 0x45, 0x17, 0x67, 0x1F, 0x3E, 0x53, 0xF8), + MBEDTLS_BYTES_TO_T_UINT_8(0xED, 0x0F, 0xB3, 0x1B, 0x57, 0x54, 0xC2, 0x03), + MBEDTLS_BYTES_TO_T_UINT_8(0x59, 0xD3, 0xF8, 0xC4, 0x1B, 0x9B, 0xFA, 0x30), +}; +static const mbedtls_mpi_uint brainpoolP384r1_T_8_X[] = { + MBEDTLS_BYTES_TO_T_UINT_8(0x37, 0x90, 0xFD, 0xFB, 0xCA, 0x49, 0x38, 0x4E), + MBEDTLS_BYTES_TO_T_UINT_8(0xC3, 0xCF, 0xC6, 0xDD, 0xF0, 0xFF, 0x8C, 0x11), + MBEDTLS_BYTES_TO_T_UINT_8(0xD7, 0x69, 0x9D, 0xBD, 0x5F, 0x33, 0xE9, 0xB4), + MBEDTLS_BYTES_TO_T_UINT_8(0x47, 0x19, 0x82, 0x3D, 0xAC, 0x1C, 0x40, 0x23), + MBEDTLS_BYTES_TO_T_UINT_8(0x40, 0xC7, 0x02, 0x46, 0x14, 0x77, 0x00, 0xBE), + MBEDTLS_BYTES_TO_T_UINT_8(0xC9, 0x05, 0xF2, 0x77, 0x3A, 0x66, 0x5C, 0x39), +}; +static const mbedtls_mpi_uint brainpoolP384r1_T_8_Y[] = { + MBEDTLS_BYTES_TO_T_UINT_8(0x1E, 0xE6, 0x17, 0xDE, 0xB2, 0xA1, 0xE5, 0xB8), + MBEDTLS_BYTES_TO_T_UINT_8(0xC7, 0x71, 0xEC, 0x9D, 0xD8, 0xF5, 0xD4, 0x66), + MBEDTLS_BYTES_TO_T_UINT_8(0xAA, 0xC6, 0x42, 0x5E, 0xE7, 0x18, 0xBA, 0xD0), + MBEDTLS_BYTES_TO_T_UINT_8(0xC5, 0x21, 0x68, 0x5A, 0x26, 0xFB, 0xD7, 0x17), + MBEDTLS_BYTES_TO_T_UINT_8(0x26, 0x00, 0x5C, 0xBA, 0x8A, 0x34, 0xEC, 0x75), + MBEDTLS_BYTES_TO_T_UINT_8(0xC3, 0x9C, 0x3C, 0xAF, 0x53, 0xE8, 0x65, 0x35), +}; +static const mbedtls_mpi_uint brainpoolP384r1_T_9_X[] = { + MBEDTLS_BYTES_TO_T_UINT_8(0xBE, 0xEF, 0x28, 0xDC, 0x67, 0x05, 0xC8, 0xDF), + MBEDTLS_BYTES_TO_T_UINT_8(0x0B, 0x78, 0xC3, 0x85, 0x49, 0xA0, 0xBC, 0x0F), + MBEDTLS_BYTES_TO_T_UINT_8(0x10, 0x3E, 0x2D, 0xA0, 0xCF, 0xD4, 0x7A, 0xF5), + MBEDTLS_BYTES_TO_T_UINT_8(0x36, 0x93, 0xFE, 0x60, 0xB3, 0x6E, 0x99, 0xE2), + MBEDTLS_BYTES_TO_T_UINT_8(0x62, 0xAD, 0x04, 0xE7, 0x49, 0xAF, 0x5E, 0xE3), + MBEDTLS_BYTES_TO_T_UINT_8(0x54, 0x7A, 0xED, 0xA6, 0x9E, 0x18, 0x09, 0x31), +}; +static const mbedtls_mpi_uint brainpoolP384r1_T_9_Y[] = { + MBEDTLS_BYTES_TO_T_UINT_8(0xE8, 0x05, 0x94, 0x44, 0xDC, 0xB8, 0x85, 0x94), + MBEDTLS_BYTES_TO_T_UINT_8(0x14, 0xB7, 0x37, 0xC2, 0x50, 0x75, 0x15, 0xDA), + MBEDTLS_BYTES_TO_T_UINT_8(0xD6, 0xC6, 0x0F, 0xB2, 0xA9, 0x91, 0x3E, 0xE8), + MBEDTLS_BYTES_TO_T_UINT_8(0xB9, 0x81, 0xAD, 0x25, 0xA1, 0x26, 0x73, 0x15), + MBEDTLS_BYTES_TO_T_UINT_8(0xFD, 0xF1, 0xD1, 0x61, 0x7C, 0x76, 0x8F, 0x13), + MBEDTLS_BYTES_TO_T_UINT_8(0x06, 0xDB, 0x4A, 0xFF, 0x14, 0xA7, 0x48, 0x0B), +}; +static const mbedtls_mpi_uint brainpoolP384r1_T_10_X[] = { + MBEDTLS_BYTES_TO_T_UINT_8(0x2A, 0x73, 0xC6, 0xC2, 0xCC, 0xF1, 0x57, 0x04), + MBEDTLS_BYTES_TO_T_UINT_8(0xB6, 0xED, 0x73, 0x27, 0x70, 0x82, 0xB6, 0x5E), + MBEDTLS_BYTES_TO_T_UINT_8(0x0B, 0xBA, 0xAC, 0x3A, 0xCF, 0xF4, 0xEA, 0xA6), + MBEDTLS_BYTES_TO_T_UINT_8(0x99, 0xD6, 0xB1, 0x8F, 0x0E, 0x08, 0x2C, 0x5E), + MBEDTLS_BYTES_TO_T_UINT_8(0x17, 0xE3, 0x8F, 0x2F, 0x0E, 0xA1, 0xF3, 0x07), + MBEDTLS_BYTES_TO_T_UINT_8(0x1A, 0xF5, 0x7C, 0x9B, 0x29, 0x0A, 0xF6, 0x28), +}; +static const mbedtls_mpi_uint brainpoolP384r1_T_10_Y[] = { + MBEDTLS_BYTES_TO_T_UINT_8(0xBD, 0xEE, 0x17, 0x47, 0x34, 0x15, 0xA3, 0xAF), + MBEDTLS_BYTES_TO_T_UINT_8(0xFB, 0xBE, 0x88, 0x48, 0xE7, 0xA2, 0xBB, 0xDE), + MBEDTLS_BYTES_TO_T_UINT_8(0xC5, 0xAD, 0xDC, 0x65, 0x61, 0x37, 0x0F, 0xC1), + MBEDTLS_BYTES_TO_T_UINT_8(0xFA, 0x67, 0xAD, 0xA2, 0x3A, 0x1C, 0x91, 0x78), + MBEDTLS_BYTES_TO_T_UINT_8(0x55, 0x07, 0x0C, 0x3A, 0x41, 0x6E, 0x13, 0x28), + MBEDTLS_BYTES_TO_T_UINT_8(0x73, 0xBD, 0x7E, 0xED, 0xAA, 0x14, 0xDD, 0x61), +}; +static const mbedtls_mpi_uint brainpoolP384r1_T_11_X[] = { + MBEDTLS_BYTES_TO_T_UINT_8(0xC3, 0xDC, 0x20, 0x01, 0x72, 0x11, 0x48, 0x55), + MBEDTLS_BYTES_TO_T_UINT_8(0x1E, 0xC4, 0x7B, 0xF8, 0x62, 0x3D, 0xF0, 0x9F), + MBEDTLS_BYTES_TO_T_UINT_8(0xE8, 0xC2, 0x3D, 0x2E, 0x52, 0xA3, 0x4A, 0x89), + MBEDTLS_BYTES_TO_T_UINT_8(0xCE, 0xE2, 0x53, 0x46, 0x5E, 0x21, 0xF8, 0xCE), + MBEDTLS_BYTES_TO_T_UINT_8(0xC2, 0xC7, 0x8F, 0xA9, 0x26, 0x42, 0x32, 0x3A), + MBEDTLS_BYTES_TO_T_UINT_8(0xFB, 0xA6, 0xA0, 0x8D, 0x4B, 0x9A, 0x19, 0x03), +}; +static const mbedtls_mpi_uint brainpoolP384r1_T_11_Y[] = { + MBEDTLS_BYTES_TO_T_UINT_8(0xEA, 0xAB, 0x6D, 0x1E, 0xFB, 0xEE, 0x60, 0x0C), + MBEDTLS_BYTES_TO_T_UINT_8(0xB6, 0x56, 0x3C, 0xC5, 0x5D, 0x10, 0x79, 0x1C), + MBEDTLS_BYTES_TO_T_UINT_8(0x25, 0xBC, 0x41, 0x9F, 0x71, 0xEF, 0x02, 0xF9), + MBEDTLS_BYTES_TO_T_UINT_8(0xA2, 0x36, 0xC4, 0xD0, 0x88, 0x9B, 0x32, 0xFC), + MBEDTLS_BYTES_TO_T_UINT_8(0x9C, 0xD4, 0x5D, 0x17, 0x39, 0xE6, 0x22, 0x2C), + MBEDTLS_BYTES_TO_T_UINT_8(0x7B, 0x26, 0x01, 0xCE, 0xBE, 0x4A, 0x9C, 0x27), +}; +static const mbedtls_mpi_uint brainpoolP384r1_T_12_X[] = { + MBEDTLS_BYTES_TO_T_UINT_8(0xEF, 0x6D, 0x11, 0xCA, 0x6C, 0x5A, 0x93, 0x0C), + MBEDTLS_BYTES_TO_T_UINT_8(0xEB, 0x96, 0x26, 0xAF, 0x2F, 0xE4, 0x30, 0x98), + MBEDTLS_BYTES_TO_T_UINT_8(0x35, 0xC1, 0x4C, 0xC6, 0x30, 0x1F, 0x5C, 0x04), + MBEDTLS_BYTES_TO_T_UINT_8(0x59, 0xB3, 0xE8, 0xFC, 0x35, 0xEB, 0x63, 0x6C), + MBEDTLS_BYTES_TO_T_UINT_8(0x9C, 0x1D, 0xCA, 0xFC, 0x50, 0x36, 0x4B, 0x96), + MBEDTLS_BYTES_TO_T_UINT_8(0xE4, 0x0E, 0x23, 0x5B, 0xAF, 0xEB, 0x2D, 0x31), +}; +static const mbedtls_mpi_uint brainpoolP384r1_T_12_Y[] = { + MBEDTLS_BYTES_TO_T_UINT_8(0xC6, 0x88, 0xB6, 0xD7, 0x74, 0x4A, 0x23, 0xB6), + MBEDTLS_BYTES_TO_T_UINT_8(0xEF, 0x66, 0xE2, 0xBB, 0x29, 0xA6, 0x4F, 0x55), + MBEDTLS_BYTES_TO_T_UINT_8(0xE9, 0x6F, 0x7E, 0x68, 0x6E, 0xA0, 0x14, 0x94), + MBEDTLS_BYTES_TO_T_UINT_8(0x3B, 0x73, 0xD4, 0xE8, 0xAB, 0x5B, 0xF6, 0x0D), + MBEDTLS_BYTES_TO_T_UINT_8(0x46, 0xE0, 0x3C, 0x24, 0x00, 0x95, 0xE9, 0xAD), + MBEDTLS_BYTES_TO_T_UINT_8(0x37, 0x0D, 0x4F, 0x81, 0xD0, 0xF2, 0x3F, 0x00), +}; +static const mbedtls_mpi_uint brainpoolP384r1_T_13_X[] = { + MBEDTLS_BYTES_TO_T_UINT_8(0x99, 0x1D, 0xCD, 0x78, 0x39, 0xC4, 0x6B, 0xD9), + MBEDTLS_BYTES_TO_T_UINT_8(0x81, 0x45, 0xC7, 0xB8, 0x2F, 0xAA, 0x5D, 0xE3), + MBEDTLS_BYTES_TO_T_UINT_8(0x33, 0x8C, 0x6E, 0xA3, 0x24, 0xB2, 0xDB, 0x4B), + MBEDTLS_BYTES_TO_T_UINT_8(0x69, 0x2D, 0xD9, 0xF1, 0xC7, 0x9B, 0x8A, 0xAF), + MBEDTLS_BYTES_TO_T_UINT_8(0x67, 0xE1, 0x2C, 0xB9, 0x40, 0x37, 0x91, 0x75), + MBEDTLS_BYTES_TO_T_UINT_8(0x81, 0x2C, 0xB5, 0x23, 0x03, 0x2B, 0xAF, 0x2F), +}; +static const mbedtls_mpi_uint brainpoolP384r1_T_13_Y[] = { + MBEDTLS_BYTES_TO_T_UINT_8(0x2F, 0x9D, 0x5A, 0x20, 0x10, 0xA9, 0x84, 0xDA), + MBEDTLS_BYTES_TO_T_UINT_8(0x61, 0x30, 0x89, 0x20, 0x13, 0xE9, 0xB2, 0xCA), + MBEDTLS_BYTES_TO_T_UINT_8(0xB6, 0x6E, 0x52, 0xEB, 0x03, 0x18, 0x1F, 0xA6), + MBEDTLS_BYTES_TO_T_UINT_8(0x6C, 0x9E, 0x1C, 0x35, 0x87, 0x92, 0x69, 0xC7), + MBEDTLS_BYTES_TO_T_UINT_8(0xA1, 0xC9, 0x88, 0xAF, 0xC6, 0x6C, 0x83, 0x72), + MBEDTLS_BYTES_TO_T_UINT_8(0xCB, 0xD5, 0x7A, 0x54, 0x34, 0x99, 0xB6, 0x6F), +}; +static const mbedtls_mpi_uint brainpoolP384r1_T_14_X[] = { + MBEDTLS_BYTES_TO_T_UINT_8(0xDF, 0xAD, 0x45, 0x9B, 0x4B, 0x41, 0x4D, 0x50), + MBEDTLS_BYTES_TO_T_UINT_8(0x1B, 0x5D, 0xAB, 0x7F, 0x35, 0x34, 0xE9, 0x29), + MBEDTLS_BYTES_TO_T_UINT_8(0x73, 0xBE, 0x78, 0x34, 0x44, 0xF3, 0x4A, 0x87), + MBEDTLS_BYTES_TO_T_UINT_8(0xFB, 0xDE, 0xE3, 0xC4, 0xEE, 0x0B, 0xF9, 0xEB), + MBEDTLS_BYTES_TO_T_UINT_8(0x5E, 0x86, 0x16, 0x48, 0x32, 0xB8, 0x74, 0x41), + MBEDTLS_BYTES_TO_T_UINT_8(0xF2, 0xEE, 0x7C, 0xBA, 0xBD, 0x81, 0xE3, 0x55), +}; +static const mbedtls_mpi_uint brainpoolP384r1_T_14_Y[] = { + MBEDTLS_BYTES_TO_T_UINT_8(0xF8, 0x6A, 0xFA, 0x84, 0xDA, 0xB8, 0xD5, 0x14), + MBEDTLS_BYTES_TO_T_UINT_8(0xB2, 0x9F, 0x8A, 0xD5, 0x1B, 0x2E, 0x1A, 0x0B), + MBEDTLS_BYTES_TO_T_UINT_8(0x5F, 0x0C, 0x61, 0xE2, 0xFF, 0x5B, 0xE6, 0xD5), + MBEDTLS_BYTES_TO_T_UINT_8(0x0E, 0x62, 0xC1, 0x87, 0x53, 0x1B, 0x92, 0xA3), + MBEDTLS_BYTES_TO_T_UINT_8(0x54, 0x90, 0x00, 0xD1, 0x6A, 0x0C, 0x0E, 0x28), + MBEDTLS_BYTES_TO_T_UINT_8(0x8B, 0x2E, 0xB5, 0x3B, 0x44, 0xB5, 0xA0, 0x78), +}; +static const mbedtls_mpi_uint brainpoolP384r1_T_15_X[] = { + MBEDTLS_BYTES_TO_T_UINT_8(0xB8, 0x5D, 0x02, 0x58, 0xB5, 0xBE, 0x45, 0x14), + MBEDTLS_BYTES_TO_T_UINT_8(0xAD, 0xEF, 0x8E, 0x90, 0x4D, 0x2A, 0x32, 0xAC), + MBEDTLS_BYTES_TO_T_UINT_8(0x48, 0x99, 0x75, 0x5C, 0x0A, 0x33, 0x8F, 0x36), + MBEDTLS_BYTES_TO_T_UINT_8(0xC8, 0x6C, 0x95, 0xD4, 0x1F, 0xF3, 0xEB, 0xDA), + MBEDTLS_BYTES_TO_T_UINT_8(0xC2, 0xE4, 0x4C, 0x91, 0x20, 0xF3, 0x25, 0xEB), + MBEDTLS_BYTES_TO_T_UINT_8(0xF1, 0x95, 0xEB, 0x29, 0x6F, 0x20, 0x34, 0x81), +}; +static const mbedtls_mpi_uint brainpoolP384r1_T_15_Y[] = { + MBEDTLS_BYTES_TO_T_UINT_8(0x2D, 0x15, 0xE5, 0x13, 0x7E, 0x64, 0x8B, 0xAD), + MBEDTLS_BYTES_TO_T_UINT_8(0xA7, 0xBC, 0x0D, 0x18, 0x7E, 0x37, 0x9E, 0xFA), + MBEDTLS_BYTES_TO_T_UINT_8(0xE8, 0x82, 0x20, 0xF7, 0x2D, 0x7A, 0x77, 0x52), + MBEDTLS_BYTES_TO_T_UINT_8(0xCB, 0x29, 0xA2, 0xDB, 0x7A, 0xE6, 0x6F, 0xA5), + MBEDTLS_BYTES_TO_T_UINT_8(0xA0, 0xC6, 0x50, 0x5C, 0xBC, 0xE6, 0x4F, 0xBD), + MBEDTLS_BYTES_TO_T_UINT_8(0x1E, 0x9F, 0xD5, 0xE8, 0xC5, 0x3D, 0xB7, 0x30), +}; +static const mbedtls_mpi_uint brainpoolP384r1_T_16_X[] = { + MBEDTLS_BYTES_TO_T_UINT_8(0x45, 0x03, 0x55, 0x10, 0xDB, 0xA6, 0x8B, 0x22), + MBEDTLS_BYTES_TO_T_UINT_8(0x4E, 0x17, 0xAE, 0x78, 0xC9, 0x1D, 0x43, 0xCA), + MBEDTLS_BYTES_TO_T_UINT_8(0x4E, 0x35, 0x49, 0xD4, 0x47, 0x84, 0x8D, 0x20), + MBEDTLS_BYTES_TO_T_UINT_8(0xF3, 0x95, 0x2F, 0xEA, 0xBC, 0xB4, 0x18, 0xB3), + MBEDTLS_BYTES_TO_T_UINT_8(0xD4, 0x48, 0xAE, 0x89, 0xF5, 0x65, 0x3D, 0x89), + MBEDTLS_BYTES_TO_T_UINT_8(0x86, 0xF2, 0x2B, 0x20, 0xD1, 0x75, 0x50, 0x63), +}; +static const mbedtls_mpi_uint brainpoolP384r1_T_16_Y[] = { + MBEDTLS_BYTES_TO_T_UINT_8(0xAD, 0xE6, 0x5C, 0x2C, 0xE0, 0x7D, 0xDF, 0x2D), + MBEDTLS_BYTES_TO_T_UINT_8(0x3E, 0x07, 0x3E, 0xCE, 0x9F, 0x18, 0xB6, 0x05), + MBEDTLS_BYTES_TO_T_UINT_8(0x9A, 0xF8, 0xF0, 0xD5, 0xFA, 0x42, 0x1D, 0x6D), + MBEDTLS_BYTES_TO_T_UINT_8(0x41, 0x6C, 0x1D, 0x03, 0xC9, 0x0E, 0x2B, 0x2F), + MBEDTLS_BYTES_TO_T_UINT_8(0x43, 0x18, 0x52, 0xA5, 0xB4, 0x63, 0xE1, 0x06), + MBEDTLS_BYTES_TO_T_UINT_8(0xB7, 0x0A, 0xD9, 0xC4, 0xFD, 0x16, 0x60, 0x54), +}; +static const mbedtls_mpi_uint brainpoolP384r1_T_17_X[] = { + MBEDTLS_BYTES_TO_T_UINT_8(0x43, 0x7D, 0xDE, 0xDF, 0x4B, 0x4A, 0xB0, 0xCB), + MBEDTLS_BYTES_TO_T_UINT_8(0xB0, 0x4E, 0x8C, 0x94, 0xC1, 0xE2, 0x85, 0xDF), + MBEDTLS_BYTES_TO_T_UINT_8(0x4F, 0xF0, 0xEA, 0xB5, 0x9B, 0x70, 0xEF, 0x10), + MBEDTLS_BYTES_TO_T_UINT_8(0x56, 0xC2, 0x39, 0x5D, 0xF3, 0x2C, 0xD9, 0x2C), + MBEDTLS_BYTES_TO_T_UINT_8(0x0D, 0x1C, 0x2E, 0xCC, 0x2F, 0x54, 0x87, 0x80), + MBEDTLS_BYTES_TO_T_UINT_8(0xB0, 0x72, 0xC7, 0xB5, 0x50, 0xA3, 0x84, 0x77), +}; +static const mbedtls_mpi_uint brainpoolP384r1_T_17_Y[] = { + MBEDTLS_BYTES_TO_T_UINT_8(0xB7, 0xD1, 0xAF, 0xA9, 0xB4, 0x8B, 0x5D, 0xFA), + MBEDTLS_BYTES_TO_T_UINT_8(0xC8, 0xF6, 0x52, 0x8A, 0xC3, 0x56, 0xA5, 0x5E), + MBEDTLS_BYTES_TO_T_UINT_8(0x3B, 0x52, 0xFF, 0xEA, 0x05, 0x42, 0x77, 0x83), + MBEDTLS_BYTES_TO_T_UINT_8(0x29, 0x08, 0x90, 0x72, 0x86, 0xC4, 0xC3, 0xB8), + MBEDTLS_BYTES_TO_T_UINT_8(0x4D, 0x15, 0xF8, 0xF1, 0x16, 0x67, 0xC6, 0xD5), + MBEDTLS_BYTES_TO_T_UINT_8(0x75, 0x87, 0xAC, 0x8F, 0x71, 0xEC, 0x83, 0x81), +}; +static const mbedtls_mpi_uint brainpoolP384r1_T_18_X[] = { + MBEDTLS_BYTES_TO_T_UINT_8(0x91, 0xE1, 0xE6, 0x2D, 0x0E, 0x11, 0xA1, 0x62), + MBEDTLS_BYTES_TO_T_UINT_8(0x74, 0xE2, 0xA8, 0x32, 0xE6, 0xE3, 0x83, 0xD1), + MBEDTLS_BYTES_TO_T_UINT_8(0x50, 0x56, 0xE5, 0xCD, 0xB7, 0x2B, 0x67, 0x6F), + MBEDTLS_BYTES_TO_T_UINT_8(0xE5, 0xED, 0xC9, 0x65, 0x6D, 0x87, 0xE1, 0x8E), + MBEDTLS_BYTES_TO_T_UINT_8(0x50, 0x8E, 0xFD, 0x9A, 0x53, 0x0E, 0xFA, 0xA3), + MBEDTLS_BYTES_TO_T_UINT_8(0x49, 0x4C, 0x4A, 0xE2, 0x23, 0x84, 0xFA, 0x01), +}; +static const mbedtls_mpi_uint brainpoolP384r1_T_18_Y[] = { + MBEDTLS_BYTES_TO_T_UINT_8(0xB4, 0xFE, 0x49, 0x81, 0xD1, 0x3E, 0xF4, 0x7C), + MBEDTLS_BYTES_TO_T_UINT_8(0x45, 0x72, 0xE0, 0xEF, 0x0D, 0xB8, 0x3E, 0x6F), + MBEDTLS_BYTES_TO_T_UINT_8(0x3C, 0x00, 0x0F, 0x5F, 0xCE, 0x60, 0x72, 0x2C), + MBEDTLS_BYTES_TO_T_UINT_8(0xB7, 0xCC, 0xD8, 0x03, 0x07, 0x6E, 0x5A, 0xCD), + MBEDTLS_BYTES_TO_T_UINT_8(0x27, 0x3A, 0x35, 0x50, 0x4E, 0x1F, 0xCA, 0x5F), + MBEDTLS_BYTES_TO_T_UINT_8(0x58, 0xEA, 0x88, 0x55, 0xBD, 0x6E, 0x05, 0x7F), +}; +static const mbedtls_mpi_uint brainpoolP384r1_T_19_X[] = { + MBEDTLS_BYTES_TO_T_UINT_8(0xB1, 0x6D, 0xF1, 0x97, 0xA6, 0x69, 0x39, 0x24), + MBEDTLS_BYTES_TO_T_UINT_8(0x0B, 0x41, 0x99, 0xFF, 0x3B, 0xA1, 0x26, 0xEC), + MBEDTLS_BYTES_TO_T_UINT_8(0x95, 0x2F, 0x95, 0x80, 0x12, 0x4A, 0x1B, 0xCB), + MBEDTLS_BYTES_TO_T_UINT_8(0xEA, 0xBF, 0x51, 0xAA, 0xAE, 0x2D, 0xDA, 0xCF), + MBEDTLS_BYTES_TO_T_UINT_8(0x0C, 0x1C, 0xB3, 0x52, 0x36, 0x49, 0xD4, 0x86), + MBEDTLS_BYTES_TO_T_UINT_8(0x99, 0xC1, 0x1F, 0x3A, 0xD3, 0x3E, 0x5C, 0x1A), +}; +static const mbedtls_mpi_uint brainpoolP384r1_T_19_Y[] = { + MBEDTLS_BYTES_TO_T_UINT_8(0x73, 0x51, 0xF7, 0x2B, 0xC8, 0xA9, 0xA7, 0x15), + MBEDTLS_BYTES_TO_T_UINT_8(0x12, 0x4E, 0x7F, 0x98, 0x41, 0x66, 0xB0, 0x03), + MBEDTLS_BYTES_TO_T_UINT_8(0x91, 0x1D, 0xC0, 0x42, 0xCD, 0xF8, 0xC3, 0x2B), + MBEDTLS_BYTES_TO_T_UINT_8(0xCC, 0x41, 0x91, 0x7D, 0xCC, 0x8B, 0xCC, 0x41), + MBEDTLS_BYTES_TO_T_UINT_8(0x2A, 0xAE, 0x76, 0xED, 0x56, 0x18, 0xC5, 0xAB), + MBEDTLS_BYTES_TO_T_UINT_8(0xAB, 0x6A, 0x06, 0xA3, 0x7F, 0x65, 0x10, 0x1F), +}; +static const mbedtls_mpi_uint brainpoolP384r1_T_20_X[] = { + MBEDTLS_BYTES_TO_T_UINT_8(0x0C, 0xEC, 0x3C, 0x05, 0x05, 0xCA, 0xF6, 0xED), + MBEDTLS_BYTES_TO_T_UINT_8(0x48, 0xCD, 0x02, 0x51, 0x12, 0x16, 0x3C, 0x63), + MBEDTLS_BYTES_TO_T_UINT_8(0xA8, 0xEB, 0xB3, 0x43, 0x7B, 0xDD, 0xB2, 0x7C), + MBEDTLS_BYTES_TO_T_UINT_8(0x00, 0x59, 0x90, 0x41, 0xDB, 0xE4, 0xF5, 0x91), + MBEDTLS_BYTES_TO_T_UINT_8(0xD0, 0x0E, 0x18, 0x2A, 0x5A, 0x83, 0x7C, 0x2F), + MBEDTLS_BYTES_TO_T_UINT_8(0xE1, 0x37, 0xA1, 0x0D, 0xF1, 0x2F, 0x63, 0x79), +}; +static const mbedtls_mpi_uint brainpoolP384r1_T_20_Y[] = { + MBEDTLS_BYTES_TO_T_UINT_8(0x21, 0xC0, 0xFA, 0x6F, 0x1F, 0x67, 0xCF, 0xEC), + MBEDTLS_BYTES_TO_T_UINT_8(0x98, 0x34, 0x45, 0xBB, 0xF4, 0xF9, 0x9B, 0x89), + MBEDTLS_BYTES_TO_T_UINT_8(0xF5, 0x69, 0xFE, 0x67, 0x1D, 0x64, 0x8F, 0xB9), + MBEDTLS_BYTES_TO_T_UINT_8(0xDB, 0x39, 0xBF, 0xD8, 0xB3, 0xC7, 0xAD, 0x8A), + MBEDTLS_BYTES_TO_T_UINT_8(0x8C, 0x93, 0xFF, 0xF3, 0x28, 0xFA, 0x39, 0xF6), + MBEDTLS_BYTES_TO_T_UINT_8(0xFA, 0xF9, 0xC3, 0x85, 0x26, 0x7A, 0x88, 0x89), +}; +static const mbedtls_mpi_uint brainpoolP384r1_T_21_X[] = { + MBEDTLS_BYTES_TO_T_UINT_8(0x4D, 0xD5, 0x79, 0xD8, 0x11, 0xDE, 0xEB, 0x4E), + MBEDTLS_BYTES_TO_T_UINT_8(0x1C, 0x46, 0xA4, 0x6A, 0xDA, 0x74, 0x34, 0xA8), + MBEDTLS_BYTES_TO_T_UINT_8(0x1E, 0xBD, 0xD3, 0xF5, 0x14, 0xEE, 0xFE, 0xAE), + MBEDTLS_BYTES_TO_T_UINT_8(0x19, 0x4C, 0xA3, 0x71, 0x43, 0x65, 0xF8, 0x94), + MBEDTLS_BYTES_TO_T_UINT_8(0x72, 0x6C, 0x35, 0xFA, 0x90, 0x25, 0xD8, 0xE2), + MBEDTLS_BYTES_TO_T_UINT_8(0xBB, 0x34, 0x84, 0x96, 0xA1, 0x43, 0x03, 0x4D), +}; +static const mbedtls_mpi_uint brainpoolP384r1_T_21_Y[] = { + MBEDTLS_BYTES_TO_T_UINT_8(0xF1, 0x3B, 0x3B, 0x2F, 0xCA, 0x59, 0xF2, 0x42), + MBEDTLS_BYTES_TO_T_UINT_8(0xCD, 0x48, 0x24, 0x74, 0xD8, 0x72, 0x90, 0xA3), + MBEDTLS_BYTES_TO_T_UINT_8(0x83, 0x42, 0x74, 0x8C, 0x6F, 0x52, 0x19, 0x3D), + MBEDTLS_BYTES_TO_T_UINT_8(0x40, 0x9E, 0x41, 0x63, 0x68, 0x78, 0x4C, 0x2F), + MBEDTLS_BYTES_TO_T_UINT_8(0x53, 0x94, 0xB6, 0x6B, 0x38, 0x52, 0xA8, 0x9F), + MBEDTLS_BYTES_TO_T_UINT_8(0x81, 0x30, 0x25, 0x93, 0xA1, 0x6F, 0x6E, 0x68), +}; +static const mbedtls_mpi_uint brainpoolP384r1_T_22_X[] = { + MBEDTLS_BYTES_TO_T_UINT_8(0xFC, 0x2F, 0x4B, 0x64, 0x79, 0x50, 0xFF, 0x01), + MBEDTLS_BYTES_TO_T_UINT_8(0xD4, 0x36, 0xED, 0x57, 0x39, 0x3B, 0xE7, 0xF3), + MBEDTLS_BYTES_TO_T_UINT_8(0xF1, 0x85, 0xEA, 0x35, 0xD6, 0xC0, 0xA0, 0x52), + MBEDTLS_BYTES_TO_T_UINT_8(0xBA, 0x89, 0x3A, 0xCC, 0x22, 0x1C, 0x46, 0x02), + MBEDTLS_BYTES_TO_T_UINT_8(0x6C, 0x7A, 0xB0, 0xA1, 0x1B, 0x69, 0x62, 0x55), + MBEDTLS_BYTES_TO_T_UINT_8(0x57, 0xB8, 0x8A, 0x6C, 0x18, 0x85, 0x0D, 0x88), +}; +static const mbedtls_mpi_uint brainpoolP384r1_T_22_Y[] = { + MBEDTLS_BYTES_TO_T_UINT_8(0xFD, 0xB6, 0x50, 0xE9, 0x4E, 0x7F, 0xE8, 0x07), + MBEDTLS_BYTES_TO_T_UINT_8(0x92, 0x5B, 0x5C, 0xD1, 0x4B, 0x11, 0x9A, 0xD8), + MBEDTLS_BYTES_TO_T_UINT_8(0x96, 0x25, 0x56, 0x74, 0x51, 0x9C, 0xEC, 0x9C), + MBEDTLS_BYTES_TO_T_UINT_8(0x55, 0x7F, 0xB6, 0x8A, 0xCB, 0x3A, 0x10, 0x6A), + MBEDTLS_BYTES_TO_T_UINT_8(0x60, 0x33, 0x07, 0x01, 0xE9, 0x49, 0x59, 0xE6), + MBEDTLS_BYTES_TO_T_UINT_8(0xC6, 0xA5, 0x2E, 0xF2, 0xBA, 0x32, 0x63, 0x44), +}; +static const mbedtls_mpi_uint brainpoolP384r1_T_23_X[] = { + MBEDTLS_BYTES_TO_T_UINT_8(0xF8, 0x06, 0x0B, 0xA5, 0x44, 0x27, 0x7F, 0x22), + MBEDTLS_BYTES_TO_T_UINT_8(0x30, 0x74, 0xAC, 0x0F, 0xCC, 0x4F, 0x13, 0x61), + MBEDTLS_BYTES_TO_T_UINT_8(0xFD, 0xB1, 0xBF, 0x97, 0x49, 0xA5, 0x1C, 0x1D), + MBEDTLS_BYTES_TO_T_UINT_8(0x8A, 0x64, 0x68, 0x7B, 0x0F, 0xCC, 0x77, 0xF8), + MBEDTLS_BYTES_TO_T_UINT_8(0xBB, 0x39, 0xF9, 0x4E, 0x84, 0x9C, 0xF6, 0x96), + MBEDTLS_BYTES_TO_T_UINT_8(0xBC, 0xCF, 0x6D, 0xE2, 0xA1, 0x2D, 0xF9, 0x2B), +}; +static const mbedtls_mpi_uint brainpoolP384r1_T_23_Y[] = { + MBEDTLS_BYTES_TO_T_UINT_8(0x95, 0xC4, 0x90, 0x57, 0x31, 0x01, 0x05, 0x5E), + MBEDTLS_BYTES_TO_T_UINT_8(0xCC, 0x1E, 0xBB, 0xBF, 0x98, 0xA4, 0x7C, 0xE3), + MBEDTLS_BYTES_TO_T_UINT_8(0x89, 0xE3, 0xA0, 0xB2, 0xCD, 0x39, 0x9A, 0x3F), + MBEDTLS_BYTES_TO_T_UINT_8(0x92, 0x34, 0x60, 0x7A, 0x89, 0x98, 0xB5, 0x52), + MBEDTLS_BYTES_TO_T_UINT_8(0x8D, 0x20, 0x3D, 0x3A, 0x04, 0x8F, 0x5A, 0xAC), + MBEDTLS_BYTES_TO_T_UINT_8(0xA3, 0x26, 0xB6, 0x49, 0x09, 0x9C, 0x0F, 0x59), +}; +static const mbedtls_mpi_uint brainpoolP384r1_T_24_X[] = { + MBEDTLS_BYTES_TO_T_UINT_8(0x72, 0x66, 0xD2, 0x38, 0x2A, 0x62, 0x81, 0xCA), + MBEDTLS_BYTES_TO_T_UINT_8(0xC5, 0xC8, 0x20, 0x5E, 0x28, 0xA3, 0x81, 0xA7), + MBEDTLS_BYTES_TO_T_UINT_8(0x20, 0x31, 0xA4, 0xF1, 0xEA, 0x7D, 0x87, 0x45), + MBEDTLS_BYTES_TO_T_UINT_8(0x8F, 0x2C, 0x99, 0x09, 0x6F, 0x63, 0xEB, 0x2F), + MBEDTLS_BYTES_TO_T_UINT_8(0x73, 0x76, 0xDA, 0x1A, 0x06, 0xBE, 0xDE, 0xA2), + MBEDTLS_BYTES_TO_T_UINT_8(0x29, 0x09, 0x2E, 0x75, 0x39, 0x30, 0x2D, 0x42), +}; +static const mbedtls_mpi_uint brainpoolP384r1_T_24_Y[] = { + MBEDTLS_BYTES_TO_T_UINT_8(0x41, 0x9B, 0xC1, 0x5A, 0x17, 0xC3, 0x8C, 0x31), + MBEDTLS_BYTES_TO_T_UINT_8(0x58, 0x8D, 0x94, 0x4D, 0x3D, 0xAB, 0x60, 0xD4), + MBEDTLS_BYTES_TO_T_UINT_8(0xFF, 0xFD, 0x1E, 0x0F, 0x43, 0xAE, 0x9D, 0x62), + MBEDTLS_BYTES_TO_T_UINT_8(0x8E, 0xF2, 0xF3, 0x20, 0x1B, 0xAA, 0xB7, 0x41), + MBEDTLS_BYTES_TO_T_UINT_8(0x9D, 0x5B, 0xA4, 0xF4, 0x90, 0x3B, 0xE3, 0x71), + MBEDTLS_BYTES_TO_T_UINT_8(0xF7, 0x78, 0x72, 0xBD, 0x65, 0x09, 0x0B, 0x01), +}; +static const mbedtls_mpi_uint brainpoolP384r1_T_25_X[] = { + MBEDTLS_BYTES_TO_T_UINT_8(0xCA, 0x37, 0x2A, 0x6C, 0x16, 0x4F, 0x64, 0x59), + MBEDTLS_BYTES_TO_T_UINT_8(0x5A, 0xCE, 0xA3, 0x90, 0xB4, 0x9A, 0xBC, 0xF7), + MBEDTLS_BYTES_TO_T_UINT_8(0x27, 0x38, 0x55, 0x63, 0x1D, 0x3A, 0x6E, 0x18), + MBEDTLS_BYTES_TO_T_UINT_8(0x37, 0xB4, 0xAA, 0x99, 0x22, 0x45, 0x89, 0x2C), + MBEDTLS_BYTES_TO_T_UINT_8(0xB7, 0x7C, 0x8C, 0xA6, 0x3D, 0xA7, 0x3E, 0xE8), + MBEDTLS_BYTES_TO_T_UINT_8(0x70, 0x06, 0x42, 0xDC, 0xA6, 0xE3, 0xC6, 0x12), +}; +static const mbedtls_mpi_uint brainpoolP384r1_T_25_Y[] = { + MBEDTLS_BYTES_TO_T_UINT_8(0x55, 0x8C, 0x3D, 0x5D, 0x47, 0x31, 0x7C, 0xEB), + MBEDTLS_BYTES_TO_T_UINT_8(0x46, 0x85, 0xEE, 0x46, 0x7E, 0x13, 0x04, 0x41), + MBEDTLS_BYTES_TO_T_UINT_8(0x9E, 0x3C, 0x8B, 0x43, 0x2E, 0x74, 0xF5, 0xF6), + MBEDTLS_BYTES_TO_T_UINT_8(0xBA, 0x88, 0x8E, 0x07, 0x29, 0x08, 0x03, 0x26), + MBEDTLS_BYTES_TO_T_UINT_8(0xEA, 0x9B, 0x89, 0xEB, 0x08, 0xE8, 0x43, 0xB5), + MBEDTLS_BYTES_TO_T_UINT_8(0x17, 0x07, 0x67, 0xFD, 0xD9, 0x73, 0x6F, 0x18), +}; +static const mbedtls_mpi_uint brainpoolP384r1_T_26_X[] = { + MBEDTLS_BYTES_TO_T_UINT_8(0x29, 0xEB, 0x21, 0x8D, 0x98, 0x43, 0x74, 0x98), + MBEDTLS_BYTES_TO_T_UINT_8(0x88, 0xCC, 0x14, 0xD8, 0x08, 0xBB, 0xA6, 0xE3), + MBEDTLS_BYTES_TO_T_UINT_8(0xC4, 0x98, 0xF2, 0x6A, 0x18, 0xC3, 0xDD, 0x9E), + MBEDTLS_BYTES_TO_T_UINT_8(0xC7, 0x38, 0x91, 0xA0, 0x03, 0xF2, 0x04, 0x62), + MBEDTLS_BYTES_TO_T_UINT_8(0x7A, 0xAF, 0xE8, 0xFD, 0xFB, 0x13, 0x70, 0x74), + MBEDTLS_BYTES_TO_T_UINT_8(0xD0, 0x93, 0x87, 0x98, 0x4A, 0xE0, 0x00, 0x12), +}; +static const mbedtls_mpi_uint brainpoolP384r1_T_26_Y[] = { + MBEDTLS_BYTES_TO_T_UINT_8(0x97, 0x2E, 0x69, 0x9C, 0xA2, 0x2D, 0x03, 0x3F), + MBEDTLS_BYTES_TO_T_UINT_8(0x79, 0xFE, 0xF3, 0xB9, 0xC1, 0x85, 0x2A, 0xEE), + MBEDTLS_BYTES_TO_T_UINT_8(0xCE, 0xFD, 0x86, 0xB1, 0xCD, 0xBF, 0x41, 0xB7), + MBEDTLS_BYTES_TO_T_UINT_8(0xA0, 0xD8, 0x9A, 0x21, 0xF3, 0xFE, 0xCB, 0xF1), + MBEDTLS_BYTES_TO_T_UINT_8(0x95, 0x78, 0x04, 0x60, 0xB7, 0xA9, 0xA2, 0x84), + MBEDTLS_BYTES_TO_T_UINT_8(0xE8, 0x1E, 0x66, 0x2A, 0x54, 0x51, 0xBD, 0x8B), +}; +static const mbedtls_mpi_uint brainpoolP384r1_T_27_X[] = { + MBEDTLS_BYTES_TO_T_UINT_8(0x8E, 0x16, 0x36, 0xEF, 0x61, 0x2D, 0xEE, 0x3B), + MBEDTLS_BYTES_TO_T_UINT_8(0x45, 0x5F, 0x88, 0xA0, 0x13, 0x12, 0xF7, 0x23), + MBEDTLS_BYTES_TO_T_UINT_8(0xA9, 0xC6, 0xAD, 0x4A, 0x4A, 0x07, 0x01, 0x5B), + MBEDTLS_BYTES_TO_T_UINT_8(0xB8, 0x74, 0xB1, 0x4F, 0xEB, 0xBD, 0xD5, 0x6B), + MBEDTLS_BYTES_TO_T_UINT_8(0x57, 0xF9, 0x71, 0xA2, 0x06, 0x4F, 0xD7, 0xBC), + MBEDTLS_BYTES_TO_T_UINT_8(0xFF, 0x8B, 0x4D, 0x48, 0xE0, 0x98, 0xFB, 0x6A), +}; +static const mbedtls_mpi_uint brainpoolP384r1_T_27_Y[] = { + MBEDTLS_BYTES_TO_T_UINT_8(0xC4, 0xBA, 0x10, 0xA3, 0x0D, 0x52, 0xAC, 0x3A), + MBEDTLS_BYTES_TO_T_UINT_8(0x11, 0xD0, 0xE0, 0x36, 0xE6, 0x07, 0x3A, 0x30), + MBEDTLS_BYTES_TO_T_UINT_8(0x7E, 0x80, 0xF0, 0xAA, 0x49, 0x22, 0x4B, 0xDD), + MBEDTLS_BYTES_TO_T_UINT_8(0xFF, 0xC7, 0xAB, 0x1C, 0x89, 0xCD, 0x24, 0x40), + MBEDTLS_BYTES_TO_T_UINT_8(0x82, 0x2A, 0xFC, 0xB3, 0x6D, 0x45, 0x96, 0x49), + MBEDTLS_BYTES_TO_T_UINT_8(0x63, 0xE4, 0xDB, 0x52, 0x3F, 0xC4, 0xB4, 0x19), +}; +static const mbedtls_mpi_uint brainpoolP384r1_T_28_X[] = { + MBEDTLS_BYTES_TO_T_UINT_8(0x5B, 0xCC, 0xC8, 0x7F, 0xBB, 0x6B, 0x87, 0x47), + MBEDTLS_BYTES_TO_T_UINT_8(0xC0, 0x21, 0x3C, 0x69, 0x7D, 0x38, 0x57, 0x50), + MBEDTLS_BYTES_TO_T_UINT_8(0x52, 0x4C, 0x18, 0x3C, 0x53, 0xA5, 0x48, 0x6D), + MBEDTLS_BYTES_TO_T_UINT_8(0x21, 0xC3, 0x64, 0x45, 0xDB, 0xC4, 0x6D, 0x15), + MBEDTLS_BYTES_TO_T_UINT_8(0x49, 0xCC, 0xD1, 0xBB, 0x17, 0xB8, 0x34, 0x2D), + MBEDTLS_BYTES_TO_T_UINT_8(0x6C, 0x69, 0x71, 0xFA, 0xA0, 0x28, 0x4A, 0x3D), +}; +static const mbedtls_mpi_uint brainpoolP384r1_T_28_Y[] = { + MBEDTLS_BYTES_TO_T_UINT_8(0xED, 0xE8, 0x9E, 0x39, 0xEA, 0x8D, 0x38, 0xDB), + MBEDTLS_BYTES_TO_T_UINT_8(0xCC, 0x9C, 0xBB, 0xCD, 0x80, 0x1A, 0xEE, 0xB7), + MBEDTLS_BYTES_TO_T_UINT_8(0xBC, 0xA0, 0x45, 0xBF, 0xD9, 0x22, 0x11, 0x32), + MBEDTLS_BYTES_TO_T_UINT_8(0xDA, 0x7C, 0x5C, 0xD9, 0xC0, 0x9F, 0x69, 0xF5), + MBEDTLS_BYTES_TO_T_UINT_8(0xBC, 0x8A, 0xA6, 0x79, 0x4E, 0x35, 0xB9, 0xD5), + MBEDTLS_BYTES_TO_T_UINT_8(0xCC, 0x8B, 0x9A, 0x3E, 0xA1, 0xB8, 0x28, 0x10), +}; +static const mbedtls_mpi_uint brainpoolP384r1_T_29_X[] = { + MBEDTLS_BYTES_TO_T_UINT_8(0x55, 0x2F, 0xEF, 0xBB, 0xA9, 0x72, 0x7F, 0xEA), + MBEDTLS_BYTES_TO_T_UINT_8(0xB5, 0x34, 0xB7, 0x12, 0xB9, 0xE7, 0xC3, 0x2A), + MBEDTLS_BYTES_TO_T_UINT_8(0xF8, 0x1D, 0xD9, 0x42, 0x77, 0x0C, 0x71, 0x6E), + MBEDTLS_BYTES_TO_T_UINT_8(0xEC, 0x01, 0x59, 0xA7, 0x56, 0x03, 0x91, 0x8D), + MBEDTLS_BYTES_TO_T_UINT_8(0x6C, 0x91, 0x99, 0x33, 0x30, 0x3E, 0xEF, 0x13), + MBEDTLS_BYTES_TO_T_UINT_8(0x87, 0xC9, 0x5A, 0x9A, 0x54, 0x66, 0xF1, 0x70), +}; +static const mbedtls_mpi_uint brainpoolP384r1_T_29_Y[] = { + MBEDTLS_BYTES_TO_T_UINT_8(0x64, 0x2C, 0xB7, 0x6E, 0x71, 0x7D, 0x35, 0x30), + MBEDTLS_BYTES_TO_T_UINT_8(0x1A, 0x0D, 0xEF, 0xD1, 0x2D, 0x99, 0x63, 0x2F), + MBEDTLS_BYTES_TO_T_UINT_8(0xE4, 0x31, 0xAF, 0x2D, 0xC9, 0xC6, 0xC2, 0xAE), + MBEDTLS_BYTES_TO_T_UINT_8(0x19, 0xC0, 0xDF, 0x80, 0x54, 0xC4, 0xAC, 0xF3), + MBEDTLS_BYTES_TO_T_UINT_8(0xE3, 0x6B, 0xA0, 0x84, 0x96, 0xF7, 0x31, 0xC8), + MBEDTLS_BYTES_TO_T_UINT_8(0x93, 0xE2, 0x7C, 0x7A, 0x41, 0x45, 0x75, 0x6A), +}; +static const mbedtls_mpi_uint brainpoolP384r1_T_30_X[] = { + MBEDTLS_BYTES_TO_T_UINT_8(0xAE, 0xEE, 0x58, 0x31, 0xE8, 0x68, 0xD6, 0x76), + MBEDTLS_BYTES_TO_T_UINT_8(0xD2, 0x2E, 0x48, 0xB7, 0x09, 0x9F, 0xD4, 0xCA), + MBEDTLS_BYTES_TO_T_UINT_8(0x34, 0xA9, 0x5C, 0xE7, 0x64, 0x43, 0x5D, 0xC9), + MBEDTLS_BYTES_TO_T_UINT_8(0x9E, 0x58, 0x9F, 0x50, 0xAB, 0x68, 0xFF, 0x6D), + MBEDTLS_BYTES_TO_T_UINT_8(0x87, 0x88, 0x2D, 0xBA, 0x12, 0xBF, 0x8D, 0x7D), + MBEDTLS_BYTES_TO_T_UINT_8(0xD4, 0xDF, 0x6F, 0xB3, 0x75, 0xA4, 0x55, 0x73), +}; +static const mbedtls_mpi_uint brainpoolP384r1_T_30_Y[] = { + MBEDTLS_BYTES_TO_T_UINT_8(0x6D, 0x17, 0x92, 0x39, 0xB7, 0x13, 0x37, 0x6F), + MBEDTLS_BYTES_TO_T_UINT_8(0x5E, 0x43, 0x71, 0xA7, 0xCA, 0x17, 0x1B, 0x32), + MBEDTLS_BYTES_TO_T_UINT_8(0xE7, 0xB9, 0xB0, 0x78, 0xEF, 0xA0, 0xDA, 0x83), + MBEDTLS_BYTES_TO_T_UINT_8(0x9A, 0x84, 0xF2, 0x0F, 0x85, 0xA2, 0xB6, 0x1F), + MBEDTLS_BYTES_TO_T_UINT_8(0x72, 0x65, 0x2E, 0x6E, 0x45, 0xB9, 0x4C, 0x3C), + MBEDTLS_BYTES_TO_T_UINT_8(0xFE, 0x6A, 0x8C, 0x2B, 0x77, 0x96, 0x36, 0x22), +}; +static const mbedtls_mpi_uint brainpoolP384r1_T_31_X[] = { + MBEDTLS_BYTES_TO_T_UINT_8(0x68, 0x7A, 0x13, 0x4A, 0x97, 0x63, 0x02, 0x10), + MBEDTLS_BYTES_TO_T_UINT_8(0xBC, 0x1E, 0x06, 0x03, 0x8F, 0xB9, 0xEE, 0x64), + MBEDTLS_BYTES_TO_T_UINT_8(0x68, 0xEE, 0x8B, 0x89, 0xA9, 0x70, 0xDB, 0xCE), + MBEDTLS_BYTES_TO_T_UINT_8(0x15, 0x7B, 0x81, 0xC9, 0x70, 0x8D, 0x62, 0x32), + MBEDTLS_BYTES_TO_T_UINT_8(0x75, 0xDA, 0x46, 0xF8, 0xF9, 0x3A, 0xBE, 0x55), + MBEDTLS_BYTES_TO_T_UINT_8(0x9F, 0x9C, 0x7A, 0x97, 0x62, 0xEB, 0xFA, 0x0F), +}; +static const mbedtls_mpi_uint brainpoolP384r1_T_31_Y[] = { + MBEDTLS_BYTES_TO_T_UINT_8(0xB2, 0x03, 0x3D, 0x3C, 0x46, 0x27, 0x9E, 0x65), + MBEDTLS_BYTES_TO_T_UINT_8(0xA4, 0x08, 0x1C, 0xD5, 0x25, 0xAF, 0xE9, 0x40), + MBEDTLS_BYTES_TO_T_UINT_8(0xFE, 0x69, 0xDC, 0x59, 0xF4, 0x8A, 0x7C, 0x1F), + MBEDTLS_BYTES_TO_T_UINT_8(0xFC, 0x9A, 0x7A, 0x99, 0x21, 0x0C, 0x4E, 0xE3), + MBEDTLS_BYTES_TO_T_UINT_8(0xF5, 0xCE, 0x85, 0x5F, 0xAC, 0xAA, 0x82, 0x10), + MBEDTLS_BYTES_TO_T_UINT_8(0x83, 0x57, 0x69, 0x90, 0x76, 0xF3, 0x53, 0x3F), +}; +static const mbedtls_ecp_point brainpoolP384r1_T[32] = { + ECP_POINT_INIT_XY_Z1(brainpoolP384r1_T_0_X, brainpoolP384r1_T_0_Y), + ECP_POINT_INIT_XY_Z0(brainpoolP384r1_T_1_X, brainpoolP384r1_T_1_Y), + ECP_POINT_INIT_XY_Z0(brainpoolP384r1_T_2_X, brainpoolP384r1_T_2_Y), + ECP_POINT_INIT_XY_Z0(brainpoolP384r1_T_3_X, brainpoolP384r1_T_3_Y), + ECP_POINT_INIT_XY_Z0(brainpoolP384r1_T_4_X, brainpoolP384r1_T_4_Y), + ECP_POINT_INIT_XY_Z0(brainpoolP384r1_T_5_X, brainpoolP384r1_T_5_Y), + ECP_POINT_INIT_XY_Z0(brainpoolP384r1_T_6_X, brainpoolP384r1_T_6_Y), + ECP_POINT_INIT_XY_Z0(brainpoolP384r1_T_7_X, brainpoolP384r1_T_7_Y), + ECP_POINT_INIT_XY_Z0(brainpoolP384r1_T_8_X, brainpoolP384r1_T_8_Y), + ECP_POINT_INIT_XY_Z0(brainpoolP384r1_T_9_X, brainpoolP384r1_T_9_Y), + ECP_POINT_INIT_XY_Z0(brainpoolP384r1_T_10_X, brainpoolP384r1_T_10_Y), + ECP_POINT_INIT_XY_Z0(brainpoolP384r1_T_11_X, brainpoolP384r1_T_11_Y), + ECP_POINT_INIT_XY_Z0(brainpoolP384r1_T_12_X, brainpoolP384r1_T_12_Y), + ECP_POINT_INIT_XY_Z0(brainpoolP384r1_T_13_X, brainpoolP384r1_T_13_Y), + ECP_POINT_INIT_XY_Z0(brainpoolP384r1_T_14_X, brainpoolP384r1_T_14_Y), + ECP_POINT_INIT_XY_Z0(brainpoolP384r1_T_15_X, brainpoolP384r1_T_15_Y), + ECP_POINT_INIT_XY_Z0(brainpoolP384r1_T_16_X, brainpoolP384r1_T_16_Y), + ECP_POINT_INIT_XY_Z0(brainpoolP384r1_T_17_X, brainpoolP384r1_T_17_Y), + ECP_POINT_INIT_XY_Z0(brainpoolP384r1_T_18_X, brainpoolP384r1_T_18_Y), + ECP_POINT_INIT_XY_Z0(brainpoolP384r1_T_19_X, brainpoolP384r1_T_19_Y), + ECP_POINT_INIT_XY_Z0(brainpoolP384r1_T_20_X, brainpoolP384r1_T_20_Y), + ECP_POINT_INIT_XY_Z0(brainpoolP384r1_T_21_X, brainpoolP384r1_T_21_Y), + ECP_POINT_INIT_XY_Z0(brainpoolP384r1_T_22_X, brainpoolP384r1_T_22_Y), + ECP_POINT_INIT_XY_Z0(brainpoolP384r1_T_23_X, brainpoolP384r1_T_23_Y), + ECP_POINT_INIT_XY_Z0(brainpoolP384r1_T_24_X, brainpoolP384r1_T_24_Y), + ECP_POINT_INIT_XY_Z0(brainpoolP384r1_T_25_X, brainpoolP384r1_T_25_Y), + ECP_POINT_INIT_XY_Z0(brainpoolP384r1_T_26_X, brainpoolP384r1_T_26_Y), + ECP_POINT_INIT_XY_Z0(brainpoolP384r1_T_27_X, brainpoolP384r1_T_27_Y), + ECP_POINT_INIT_XY_Z0(brainpoolP384r1_T_28_X, brainpoolP384r1_T_28_Y), + ECP_POINT_INIT_XY_Z0(brainpoolP384r1_T_29_X, brainpoolP384r1_T_29_Y), + ECP_POINT_INIT_XY_Z0(brainpoolP384r1_T_30_X, brainpoolP384r1_T_30_Y), + ECP_POINT_INIT_XY_Z0(brainpoolP384r1_T_31_X, brainpoolP384r1_T_31_Y), +}; +#else +#define brainpoolP384r1_T NULL +#endif + #endif /* MBEDTLS_ECP_DP_BP384R1_ENABLED */ /* @@ -513,22 +3805,686 @@ static const mbedtls_mpi_uint brainpoolP512r1_n[] = { MBEDTLS_BYTES_TO_T_UINT_8(0x07, 0xFC, 0xC9, 0x33, 0xAE, 0xE6, 0xD4, 0x3F), MBEDTLS_BYTES_TO_T_UINT_8(0x8B, 0xC4, 0xE9, 0xDB, 0xB8, 0x9D, 0xDD, 0xAA), }; -#endif /* MBEDTLS_ECP_DP_BP512R1_ENABLED */ -#if defined(MBEDTLS_ECP_DP_SECP192R1_ENABLED) || \ - defined(MBEDTLS_ECP_DP_SECP224R1_ENABLED) || \ - defined(MBEDTLS_ECP_DP_SECP256R1_ENABLED) || \ - defined(MBEDTLS_ECP_DP_SECP384R1_ENABLED) || \ - defined(MBEDTLS_ECP_DP_SECP521R1_ENABLED) || \ - defined(MBEDTLS_ECP_DP_BP256R1_ENABLED) || \ - defined(MBEDTLS_ECP_DP_BP384R1_ENABLED) || \ - defined(MBEDTLS_ECP_DP_BP512R1_ENABLED) || \ - defined(MBEDTLS_ECP_DP_SECP192K1_ENABLED) || \ - defined(MBEDTLS_ECP_DP_SECP224K1_ENABLED) || \ - defined(MBEDTLS_ECP_DP_SECP256K1_ENABLED) -/* For these curves, we build the group parameters dynamically. */ -#define ECP_LOAD_GROUP +#if MBEDTLS_ECP_FIXED_POINT_OPTIM == 1 +static const mbedtls_mpi_uint brainpoolP512r1_T_0_X[] = { + MBEDTLS_BYTES_TO_T_UINT_8(0x22, 0xF8, 0xB9, 0xBC, 0x09, 0x22, 0x35, 0x8B), + MBEDTLS_BYTES_TO_T_UINT_8(0x68, 0x5E, 0x6A, 0x40, 0x47, 0x50, 0x6D, 0x7C), + MBEDTLS_BYTES_TO_T_UINT_8(0x5F, 0x7D, 0xB9, 0x93, 0x7B, 0x68, 0xD1, 0x50), + MBEDTLS_BYTES_TO_T_UINT_8(0x8D, 0xD4, 0xD0, 0xE2, 0x78, 0x1F, 0x3B, 0xFF), + MBEDTLS_BYTES_TO_T_UINT_8(0x8E, 0x09, 0xD0, 0xF4, 0xEE, 0x62, 0x3B, 0xB4), + MBEDTLS_BYTES_TO_T_UINT_8(0xC1, 0x16, 0xD9, 0xB5, 0x70, 0x9F, 0xED, 0x85), + MBEDTLS_BYTES_TO_T_UINT_8(0x93, 0x6A, 0x4C, 0x9C, 0x2E, 0x32, 0x21, 0x5A), + MBEDTLS_BYTES_TO_T_UINT_8(0x64, 0xD9, 0x2E, 0xD8, 0xBD, 0xE4, 0xAE, 0x81), +}; +static const mbedtls_mpi_uint brainpoolP512r1_T_0_Y[] = { + MBEDTLS_BYTES_TO_T_UINT_8(0x92, 0x08, 0xD8, 0x3A, 0x0F, 0x1E, 0xCD, 0x78), + MBEDTLS_BYTES_TO_T_UINT_8(0x06, 0x54, 0xF0, 0xA8, 0x2F, 0x2B, 0xCA, 0xD1), + MBEDTLS_BYTES_TO_T_UINT_8(0xAE, 0x63, 0x27, 0x8A, 0xD8, 0x4B, 0xCA, 0x5B), + MBEDTLS_BYTES_TO_T_UINT_8(0x5E, 0x48, 0x5F, 0x4A, 0x49, 0xDE, 0xDC, 0xB2), + MBEDTLS_BYTES_TO_T_UINT_8(0x11, 0x81, 0x1F, 0x88, 0x5B, 0xC5, 0x00, 0xA0), + MBEDTLS_BYTES_TO_T_UINT_8(0x1A, 0x7B, 0xA5, 0x24, 0x00, 0xF7, 0x09, 0xF2), + MBEDTLS_BYTES_TO_T_UINT_8(0xFD, 0x22, 0x78, 0xCF, 0xA9, 0xBF, 0xEA, 0xC0), + MBEDTLS_BYTES_TO_T_UINT_8(0xEC, 0x32, 0x63, 0x56, 0x5D, 0x38, 0xDE, 0x7D), +}; +static const mbedtls_mpi_uint brainpoolP512r1_T_1_X[] = { + MBEDTLS_BYTES_TO_T_UINT_8(0xEA, 0xE9, 0x6B, 0x8C, 0x6F, 0x9D, 0x88, 0x43), + MBEDTLS_BYTES_TO_T_UINT_8(0xBB, 0x4F, 0x86, 0x96, 0xA7, 0x56, 0xD1, 0x37), + MBEDTLS_BYTES_TO_T_UINT_8(0x9D, 0xAB, 0xFA, 0xEE, 0xA7, 0xF5, 0x0E, 0xA6), + MBEDTLS_BYTES_TO_T_UINT_8(0xE3, 0x40, 0xEF, 0x9E, 0x6D, 0xD6, 0x32, 0x33), + MBEDTLS_BYTES_TO_T_UINT_8(0xE3, 0xED, 0x56, 0x14, 0x57, 0x1A, 0x8D, 0x69), + MBEDTLS_BYTES_TO_T_UINT_8(0xA4, 0xED, 0x4D, 0x3A, 0xFA, 0x71, 0x75, 0x6B), + MBEDTLS_BYTES_TO_T_UINT_8(0x66, 0xC5, 0x76, 0x1C, 0x14, 0xBE, 0xB5, 0xCD), + MBEDTLS_BYTES_TO_T_UINT_8(0xE1, 0x5A, 0xCB, 0xE7, 0x36, 0x1D, 0x52, 0x1C), +}; +static const mbedtls_mpi_uint brainpoolP512r1_T_1_Y[] = { + MBEDTLS_BYTES_TO_T_UINT_8(0x6B, 0x8D, 0x7A, 0xEB, 0xA3, 0x8B, 0xD5, 0xB0), + MBEDTLS_BYTES_TO_T_UINT_8(0x1F, 0xA3, 0x41, 0xF8, 0xAC, 0x9E, 0xAB, 0x74), + MBEDTLS_BYTES_TO_T_UINT_8(0x12, 0xE3, 0x65, 0x0D, 0x1C, 0xFE, 0x09, 0x2B), + MBEDTLS_BYTES_TO_T_UINT_8(0x3F, 0xCA, 0x13, 0x3F, 0xC5, 0xF9, 0x7E, 0xEC), + MBEDTLS_BYTES_TO_T_UINT_8(0x2C, 0x5D, 0x63, 0x28, 0xA6, 0x89, 0xD3, 0x91), + MBEDTLS_BYTES_TO_T_UINT_8(0xC9, 0x95, 0x3F, 0x7A, 0x82, 0xD4, 0x77, 0xE3), + MBEDTLS_BYTES_TO_T_UINT_8(0x34, 0xBB, 0x92, 0x32, 0x00, 0xF4, 0x66, 0x42), + MBEDTLS_BYTES_TO_T_UINT_8(0xBA, 0x58, 0x31, 0xD1, 0x17, 0x9F, 0x2A, 0x22), +}; +static const mbedtls_mpi_uint brainpoolP512r1_T_2_X[] = { + MBEDTLS_BYTES_TO_T_UINT_8(0x52, 0x36, 0xA9, 0xCD, 0x80, 0xA5, 0x2D, 0x78), + MBEDTLS_BYTES_TO_T_UINT_8(0x91, 0x44, 0xAB, 0xCE, 0x71, 0xFF, 0x0C, 0x9B), + MBEDTLS_BYTES_TO_T_UINT_8(0x18, 0x24, 0x58, 0x35, 0x5A, 0x21, 0x32, 0x93), + MBEDTLS_BYTES_TO_T_UINT_8(0x1B, 0xA6, 0x28, 0xF8, 0x7A, 0x97, 0xAE, 0x8B), + MBEDTLS_BYTES_TO_T_UINT_8(0x84, 0xE7, 0x08, 0xFA, 0x47, 0xC9, 0x55, 0x09), + MBEDTLS_BYTES_TO_T_UINT_8(0x8D, 0xAC, 0x2E, 0x84, 0xA4, 0xF5, 0x52, 0xC4), + MBEDTLS_BYTES_TO_T_UINT_8(0xD9, 0x58, 0x05, 0x9D, 0xA7, 0xC8, 0x71, 0xBF), + MBEDTLS_BYTES_TO_T_UINT_8(0xB3, 0x92, 0xB4, 0x92, 0xC1, 0x92, 0xEC, 0x6B), +}; +static const mbedtls_mpi_uint brainpoolP512r1_T_2_Y[] = { + MBEDTLS_BYTES_TO_T_UINT_8(0x4A, 0x48, 0x2D, 0x79, 0x5E, 0x58, 0xE5, 0x69), + MBEDTLS_BYTES_TO_T_UINT_8(0xB4, 0x85, 0x26, 0xEC, 0xE9, 0x6E, 0xD4, 0x06), + MBEDTLS_BYTES_TO_T_UINT_8(0x98, 0x68, 0x26, 0x87, 0x38, 0xA2, 0xD2, 0x0B), + MBEDTLS_BYTES_TO_T_UINT_8(0xF7, 0x17, 0x60, 0xCE, 0x75, 0xF8, 0xA5, 0x6F), + MBEDTLS_BYTES_TO_T_UINT_8(0x20, 0x51, 0xDB, 0xA9, 0xAE, 0x87, 0xF1, 0x15), + MBEDTLS_BYTES_TO_T_UINT_8(0xDD, 0x49, 0x92, 0x3B, 0x19, 0x96, 0xF5, 0xB0), + MBEDTLS_BYTES_TO_T_UINT_8(0xC4, 0xD5, 0x52, 0x52, 0x8C, 0xCE, 0xFD, 0xFA), + MBEDTLS_BYTES_TO_T_UINT_8(0x24, 0x18, 0x0A, 0xE6, 0xF6, 0xAE, 0x08, 0x41), +}; +static const mbedtls_mpi_uint brainpoolP512r1_T_3_X[] = { + MBEDTLS_BYTES_TO_T_UINT_8(0x7E, 0x2B, 0xD8, 0x54, 0xCE, 0xB0, 0x57, 0xFE), + MBEDTLS_BYTES_TO_T_UINT_8(0x8A, 0xB0, 0xF8, 0x9E, 0x03, 0x03, 0x3C, 0x5D), + MBEDTLS_BYTES_TO_T_UINT_8(0x93, 0x0E, 0x29, 0x29, 0x00, 0xF3, 0x70, 0xBF), + MBEDTLS_BYTES_TO_T_UINT_8(0x54, 0x33, 0x99, 0x0E, 0x00, 0x5D, 0xFE, 0x4B), + MBEDTLS_BYTES_TO_T_UINT_8(0x46, 0x2D, 0xF2, 0x59, 0x32, 0xCF, 0x03, 0xF4), + MBEDTLS_BYTES_TO_T_UINT_8(0x3B, 0xC9, 0x72, 0xAE, 0x0C, 0xEF, 0xD1, 0x5B), + MBEDTLS_BYTES_TO_T_UINT_8(0xB6, 0x5A, 0x27, 0xBF, 0x2F, 0x45, 0xF9, 0x51), + MBEDTLS_BYTES_TO_T_UINT_8(0xD4, 0xBE, 0xE5, 0x2C, 0xFF, 0x5B, 0x1E, 0x88), +}; +static const mbedtls_mpi_uint brainpoolP512r1_T_3_Y[] = { + MBEDTLS_BYTES_TO_T_UINT_8(0xAA, 0xAC, 0xBB, 0xD8, 0x83, 0xC2, 0x46, 0xF6), + MBEDTLS_BYTES_TO_T_UINT_8(0xCF, 0xDC, 0xCE, 0x15, 0xB4, 0xEF, 0xCF, 0x46), + MBEDTLS_BYTES_TO_T_UINT_8(0x46, 0xDB, 0x5E, 0x94, 0x31, 0x0B, 0xB2, 0x7A), + MBEDTLS_BYTES_TO_T_UINT_8(0x3C, 0xB9, 0xE3, 0xE3, 0x11, 0x71, 0x41, 0x1E), + MBEDTLS_BYTES_TO_T_UINT_8(0x36, 0xE3, 0x01, 0xB7, 0x7D, 0xBC, 0x65, 0xBE), + MBEDTLS_BYTES_TO_T_UINT_8(0xFC, 0x07, 0x65, 0x87, 0xA7, 0xE8, 0x48, 0xE3), + MBEDTLS_BYTES_TO_T_UINT_8(0x66, 0x48, 0x8F, 0xD4, 0x30, 0x8E, 0xB4, 0x6C), + MBEDTLS_BYTES_TO_T_UINT_8(0x86, 0xE0, 0x73, 0xBE, 0x1E, 0xBF, 0x56, 0x36), +}; +static const mbedtls_mpi_uint brainpoolP512r1_T_4_X[] = { + MBEDTLS_BYTES_TO_T_UINT_8(0xFE, 0x0E, 0x5E, 0x87, 0xC5, 0xAB, 0x0E, 0x3C), + MBEDTLS_BYTES_TO_T_UINT_8(0xB9, 0xF9, 0x5F, 0x80, 0x24, 0x4C, 0x2A, 0xF1), + MBEDTLS_BYTES_TO_T_UINT_8(0xDE, 0x15, 0x21, 0x54, 0x92, 0x84, 0x8D, 0x6A), + MBEDTLS_BYTES_TO_T_UINT_8(0xA8, 0x8A, 0x47, 0x74, 0xDC, 0x42, 0xB1, 0xF8), + MBEDTLS_BYTES_TO_T_UINT_8(0x81, 0xF7, 0x30, 0xFD, 0xC1, 0x9B, 0x0C, 0x5B), + MBEDTLS_BYTES_TO_T_UINT_8(0x4E, 0x6C, 0xCC, 0xDF, 0xC5, 0xE3, 0xA9, 0xD5), + MBEDTLS_BYTES_TO_T_UINT_8(0xD6, 0x67, 0x59, 0x10, 0x5C, 0x51, 0x54, 0x40), + MBEDTLS_BYTES_TO_T_UINT_8(0xA0, 0x37, 0xFB, 0x6E, 0xB0, 0x78, 0x63, 0x8E), +}; +static const mbedtls_mpi_uint brainpoolP512r1_T_4_Y[] = { + MBEDTLS_BYTES_TO_T_UINT_8(0xA5, 0xEF, 0xC4, 0x39, 0x20, 0xF1, 0x46, 0x66), + MBEDTLS_BYTES_TO_T_UINT_8(0xE2, 0x62, 0xAE, 0xFF, 0x10, 0xE4, 0xE2, 0xE9), + MBEDTLS_BYTES_TO_T_UINT_8(0xFF, 0x5C, 0xF5, 0x2E, 0x22, 0x89, 0xE5, 0x82), + MBEDTLS_BYTES_TO_T_UINT_8(0x89, 0x0C, 0x29, 0xA8, 0x62, 0xAE, 0xDB, 0x65), + MBEDTLS_BYTES_TO_T_UINT_8(0xD7, 0x9E, 0x0F, 0xCA, 0x87, 0x2A, 0x6F, 0x7B), + MBEDTLS_BYTES_TO_T_UINT_8(0xCE, 0xDC, 0x9B, 0x9F, 0x65, 0xD4, 0xAD, 0x27), + MBEDTLS_BYTES_TO_T_UINT_8(0xED, 0xC3, 0x08, 0x0F, 0xCF, 0x67, 0xE9, 0xF4), + MBEDTLS_BYTES_TO_T_UINT_8(0x92, 0x5C, 0xD7, 0xFF, 0x41, 0x9C, 0xCB, 0x26), +}; +static const mbedtls_mpi_uint brainpoolP512r1_T_5_X[] = { + MBEDTLS_BYTES_TO_T_UINT_8(0x37, 0x25, 0x05, 0x12, 0xAD, 0x73, 0x63, 0x90), + MBEDTLS_BYTES_TO_T_UINT_8(0xC7, 0x99, 0x07, 0x86, 0x57, 0xE7, 0x94, 0xB1), + MBEDTLS_BYTES_TO_T_UINT_8(0x00, 0x4B, 0xA5, 0xBF, 0x18, 0xA9, 0xEF, 0x6A), + MBEDTLS_BYTES_TO_T_UINT_8(0xFA, 0x4C, 0xC4, 0x09, 0xF2, 0x2F, 0x0C, 0xAA), + MBEDTLS_BYTES_TO_T_UINT_8(0x8C, 0x3A, 0x04, 0xEA, 0x89, 0x6C, 0x91, 0xB9), + MBEDTLS_BYTES_TO_T_UINT_8(0x7D, 0x6C, 0x3A, 0xE7, 0xA3, 0xEC, 0x24, 0x7B), + MBEDTLS_BYTES_TO_T_UINT_8(0x16, 0xA1, 0x26, 0x21, 0x04, 0xE3, 0xB9, 0x40), + MBEDTLS_BYTES_TO_T_UINT_8(0x53, 0x71, 0x4B, 0x7B, 0xC2, 0x89, 0xCD, 0xA2), +}; +static const mbedtls_mpi_uint brainpoolP512r1_T_5_Y[] = { + MBEDTLS_BYTES_TO_T_UINT_8(0xB7, 0xB9, 0xA8, 0x9D, 0xFD, 0x00, 0x3A, 0x1F), + MBEDTLS_BYTES_TO_T_UINT_8(0x63, 0x41, 0x6C, 0xBB, 0x5A, 0xCA, 0x1F, 0x74), + MBEDTLS_BYTES_TO_T_UINT_8(0x2A, 0xD7, 0xE2, 0x6C, 0x6B, 0xA7, 0x48, 0xC9), + MBEDTLS_BYTES_TO_T_UINT_8(0x1E, 0x19, 0xAD, 0xA7, 0xC1, 0x7E, 0x4F, 0x6E), + MBEDTLS_BYTES_TO_T_UINT_8(0xD1, 0xF7, 0x19, 0x3C, 0x06, 0x74, 0x2C, 0x3A), + MBEDTLS_BYTES_TO_T_UINT_8(0xC5, 0x23, 0x4F, 0x0C, 0x09, 0xB0, 0x80, 0x4A), + MBEDTLS_BYTES_TO_T_UINT_8(0x4E, 0x74, 0x34, 0x08, 0x44, 0x7E, 0xA3, 0xDD), + MBEDTLS_BYTES_TO_T_UINT_8(0xFB, 0xCC, 0x8D, 0x12, 0x6E, 0xE1, 0x3D, 0x0B), +}; +static const mbedtls_mpi_uint brainpoolP512r1_T_6_X[] = { + MBEDTLS_BYTES_TO_T_UINT_8(0x38, 0x18, 0xB1, 0x71, 0x02, 0x93, 0xC2, 0xA4), + MBEDTLS_BYTES_TO_T_UINT_8(0xC9, 0x89, 0x40, 0xE2, 0x1F, 0xE7, 0x5E, 0x68), + MBEDTLS_BYTES_TO_T_UINT_8(0x50, 0x8E, 0xAE, 0x89, 0x01, 0xD4, 0x0C, 0xEB), + MBEDTLS_BYTES_TO_T_UINT_8(0xAE, 0xDA, 0x58, 0x70, 0x24, 0xF2, 0xE4, 0x5F), + MBEDTLS_BYTES_TO_T_UINT_8(0x6F, 0xC7, 0x1D, 0xD6, 0x4A, 0x6F, 0x66, 0x4F), + MBEDTLS_BYTES_TO_T_UINT_8(0x92, 0x1D, 0x7E, 0x4A, 0x2C, 0xCA, 0xEC, 0x3B), + MBEDTLS_BYTES_TO_T_UINT_8(0xA1, 0x06, 0x7F, 0xA8, 0x99, 0xE4, 0xD3, 0x4E), + MBEDTLS_BYTES_TO_T_UINT_8(0x2A, 0x1D, 0x5A, 0xDF, 0x5E, 0x58, 0x36, 0x49), +}; +static const mbedtls_mpi_uint brainpoolP512r1_T_6_Y[] = { + MBEDTLS_BYTES_TO_T_UINT_8(0x9C, 0xB9, 0x32, 0x69, 0x1F, 0x72, 0x2A, 0xB3), + MBEDTLS_BYTES_TO_T_UINT_8(0x1C, 0x73, 0xE2, 0x03, 0x39, 0x35, 0xAA, 0xA8), + MBEDTLS_BYTES_TO_T_UINT_8(0xEB, 0x5E, 0x5D, 0x48, 0xEF, 0xAE, 0x30, 0xF5), + MBEDTLS_BYTES_TO_T_UINT_8(0x77, 0x7F, 0x60, 0x19, 0xAF, 0xEC, 0x9D, 0xFC), + MBEDTLS_BYTES_TO_T_UINT_8(0xCA, 0xD9, 0x19, 0xE4, 0x1B, 0x56, 0x15, 0x5F), + MBEDTLS_BYTES_TO_T_UINT_8(0xBC, 0xD7, 0x33, 0x59, 0x1F, 0x43, 0x59, 0x2C), + MBEDTLS_BYTES_TO_T_UINT_8(0xC6, 0xCE, 0xEE, 0xCA, 0xA4, 0x7F, 0x63, 0xD4), + MBEDTLS_BYTES_TO_T_UINT_8(0xBD, 0x40, 0xC0, 0xF6, 0x19, 0x89, 0x43, 0x20), +}; +static const mbedtls_mpi_uint brainpoolP512r1_T_7_X[] = { + MBEDTLS_BYTES_TO_T_UINT_8(0xEB, 0x92, 0xEA, 0x07, 0x65, 0x79, 0x86, 0xD3), + MBEDTLS_BYTES_TO_T_UINT_8(0xFF, 0xB7, 0x13, 0x75, 0xD3, 0xC5, 0x0A, 0xC9), + MBEDTLS_BYTES_TO_T_UINT_8(0x26, 0x9E, 0xFA, 0xE1, 0x1F, 0x0C, 0xF9, 0x74), + MBEDTLS_BYTES_TO_T_UINT_8(0xB4, 0x8C, 0xED, 0x5C, 0x21, 0xE9, 0x09, 0xDD), + MBEDTLS_BYTES_TO_T_UINT_8(0xF4, 0x4D, 0xD8, 0x18, 0xC4, 0xF6, 0x36, 0x39), + MBEDTLS_BYTES_TO_T_UINT_8(0xC7, 0xC9, 0xAC, 0x5C, 0xFA, 0x69, 0xA4, 0xA0), + MBEDTLS_BYTES_TO_T_UINT_8(0x6B, 0x8C, 0x94, 0x1C, 0x7B, 0x71, 0x36, 0x58), + MBEDTLS_BYTES_TO_T_UINT_8(0x7C, 0xBD, 0x46, 0xCE, 0xB7, 0x1D, 0x9C, 0x5E), +}; +static const mbedtls_mpi_uint brainpoolP512r1_T_7_Y[] = { + MBEDTLS_BYTES_TO_T_UINT_8(0xEA, 0xD6, 0x96, 0x4B, 0xA6, 0x47, 0xEB, 0xE5), + MBEDTLS_BYTES_TO_T_UINT_8(0x5F, 0xF1, 0x5F, 0x15, 0xDE, 0x99, 0x6F, 0x66), + MBEDTLS_BYTES_TO_T_UINT_8(0x21, 0xBD, 0xE5, 0x04, 0xB8, 0xE6, 0xC0, 0x0B), + MBEDTLS_BYTES_TO_T_UINT_8(0x49, 0xD3, 0xF0, 0x04, 0x00, 0xE4, 0x05, 0xDB), + MBEDTLS_BYTES_TO_T_UINT_8(0x96, 0xF3, 0x06, 0xA3, 0x1A, 0xFF, 0xEA, 0x73), + MBEDTLS_BYTES_TO_T_UINT_8(0x08, 0x32, 0xAA, 0x99, 0x33, 0x09, 0xB6, 0x34), + MBEDTLS_BYTES_TO_T_UINT_8(0x6E, 0xEF, 0xFC, 0x61, 0x10, 0x42, 0x31, 0x94), + MBEDTLS_BYTES_TO_T_UINT_8(0x34, 0xF1, 0xF4, 0x33, 0xCF, 0x28, 0x90, 0x9C), +}; +static const mbedtls_mpi_uint brainpoolP512r1_T_8_X[] = { + MBEDTLS_BYTES_TO_T_UINT_8(0x10, 0xDE, 0xF9, 0x88, 0x87, 0x7B, 0xEB, 0xC9), + MBEDTLS_BYTES_TO_T_UINT_8(0x66, 0xB8, 0xDA, 0xFA, 0xDA, 0x3D, 0xA6, 0x17), + MBEDTLS_BYTES_TO_T_UINT_8(0xA0, 0xF0, 0x62, 0x82, 0x53, 0x32, 0x55, 0x03), + MBEDTLS_BYTES_TO_T_UINT_8(0x2F, 0xA5, 0x32, 0x4A, 0x19, 0x11, 0x9C, 0x10), + MBEDTLS_BYTES_TO_T_UINT_8(0x16, 0xB3, 0x27, 0xE9, 0x75, 0x90, 0x05, 0x2D), + MBEDTLS_BYTES_TO_T_UINT_8(0x63, 0x1C, 0x90, 0x48, 0x77, 0x01, 0x85, 0x1B), + MBEDTLS_BYTES_TO_T_UINT_8(0xC7, 0xD6, 0x9B, 0x84, 0xA8, 0xD7, 0xC5, 0x28), + MBEDTLS_BYTES_TO_T_UINT_8(0xE1, 0x7A, 0xCB, 0xB3, 0x11, 0x46, 0xD7, 0x99), +}; +static const mbedtls_mpi_uint brainpoolP512r1_T_8_Y[] = { + MBEDTLS_BYTES_TO_T_UINT_8(0x8B, 0x23, 0xBF, 0x75, 0x75, 0xA1, 0x95, 0x90), + MBEDTLS_BYTES_TO_T_UINT_8(0x4B, 0x66, 0x5D, 0x34, 0x13, 0xA9, 0x03, 0xBE), + MBEDTLS_BYTES_TO_T_UINT_8(0x29, 0x80, 0x9D, 0x5F, 0xD2, 0x44, 0xE1, 0x62), + MBEDTLS_BYTES_TO_T_UINT_8(0x96, 0x5D, 0xBD, 0xA8, 0xBF, 0xB4, 0x25, 0x1F), + MBEDTLS_BYTES_TO_T_UINT_8(0x6A, 0x99, 0x1F, 0x53, 0xF1, 0x57, 0xDB, 0xE7), + MBEDTLS_BYTES_TO_T_UINT_8(0x21, 0x7C, 0xE5, 0xC5, 0x51, 0x0B, 0x4C, 0x9B), + MBEDTLS_BYTES_TO_T_UINT_8(0x6B, 0xB0, 0x1A, 0x9C, 0x16, 0xB0, 0x32, 0x1F), + MBEDTLS_BYTES_TO_T_UINT_8(0xF4, 0xE3, 0xCF, 0xDD, 0x48, 0xB4, 0x7B, 0x33), +}; +static const mbedtls_mpi_uint brainpoolP512r1_T_9_X[] = { + MBEDTLS_BYTES_TO_T_UINT_8(0xC0, 0xDD, 0x9E, 0x3C, 0x98, 0x0E, 0x77, 0x65), + MBEDTLS_BYTES_TO_T_UINT_8(0x6C, 0xAB, 0x01, 0xD3, 0x87, 0x74, 0x25, 0x4A), + MBEDTLS_BYTES_TO_T_UINT_8(0x87, 0xA3, 0xE3, 0x76, 0x43, 0x87, 0x12, 0xBD), + MBEDTLS_BYTES_TO_T_UINT_8(0x54, 0xB1, 0x3B, 0x60, 0x66, 0xEB, 0x98, 0x54), + MBEDTLS_BYTES_TO_T_UINT_8(0xD2, 0x78, 0xC8, 0xD7, 0x4E, 0x75, 0xCA, 0x69), + MBEDTLS_BYTES_TO_T_UINT_8(0x07, 0xDF, 0x71, 0x19, 0xE7, 0x07, 0x36, 0xB5), + MBEDTLS_BYTES_TO_T_UINT_8(0x6D, 0xC9, 0xA8, 0x5F, 0x91, 0xBF, 0x47, 0xB2), + MBEDTLS_BYTES_TO_T_UINT_8(0x80, 0x96, 0x58, 0x96, 0x18, 0xB6, 0xFA, 0x01), +}; +static const mbedtls_mpi_uint brainpoolP512r1_T_9_Y[] = { + MBEDTLS_BYTES_TO_T_UINT_8(0xD0, 0x2D, 0xA9, 0x9B, 0x86, 0xDB, 0x0C, 0x4C), + MBEDTLS_BYTES_TO_T_UINT_8(0xE4, 0x0B, 0x2D, 0x56, 0x4A, 0xD3, 0x93, 0x8A), + MBEDTLS_BYTES_TO_T_UINT_8(0xB5, 0x15, 0xE2, 0x65, 0x12, 0x86, 0x0E, 0xB2), + MBEDTLS_BYTES_TO_T_UINT_8(0xB4, 0x41, 0x4D, 0xC1, 0xCB, 0xE4, 0xC3, 0xD7), + MBEDTLS_BYTES_TO_T_UINT_8(0x6A, 0x53, 0x10, 0xCA, 0xA3, 0xAC, 0x83, 0x26), + MBEDTLS_BYTES_TO_T_UINT_8(0x3E, 0x01, 0x22, 0x96, 0x10, 0xAD, 0x69, 0xDB), + MBEDTLS_BYTES_TO_T_UINT_8(0x42, 0x46, 0x4E, 0xD8, 0xEA, 0xD6, 0x9D, 0xF3), + MBEDTLS_BYTES_TO_T_UINT_8(0x43, 0x2F, 0x7F, 0x62, 0x62, 0x80, 0xD0, 0x14), +}; +static const mbedtls_mpi_uint brainpoolP512r1_T_10_X[] = { + MBEDTLS_BYTES_TO_T_UINT_8(0xB2, 0xDA, 0x00, 0x63, 0x09, 0xBD, 0x6A, 0x83), + MBEDTLS_BYTES_TO_T_UINT_8(0x0F, 0xD4, 0x6E, 0x48, 0x05, 0xB7, 0xF7, 0x17), + MBEDTLS_BYTES_TO_T_UINT_8(0x14, 0x4D, 0xD7, 0x00, 0x4A, 0x15, 0x27, 0x7A), + MBEDTLS_BYTES_TO_T_UINT_8(0x3A, 0x15, 0xAA, 0x37, 0x27, 0x34, 0x18, 0x24), + MBEDTLS_BYTES_TO_T_UINT_8(0x3A, 0x20, 0x2C, 0x84, 0x1B, 0x88, 0xBA, 0x05), + MBEDTLS_BYTES_TO_T_UINT_8(0xAC, 0x09, 0xD6, 0x04, 0xA2, 0x60, 0x84, 0x72), + MBEDTLS_BYTES_TO_T_UINT_8(0xC8, 0x04, 0x94, 0x08, 0xD4, 0xED, 0x47, 0xDB), + MBEDTLS_BYTES_TO_T_UINT_8(0x8B, 0xF3, 0xE4, 0x3E, 0xB9, 0x5B, 0x35, 0x42), +}; +static const mbedtls_mpi_uint brainpoolP512r1_T_10_Y[] = { + MBEDTLS_BYTES_TO_T_UINT_8(0x5F, 0xD8, 0xB6, 0x80, 0xD6, 0xF1, 0x30, 0xDD), + MBEDTLS_BYTES_TO_T_UINT_8(0xD6, 0x14, 0xA6, 0x85, 0xEE, 0xA7, 0xD8, 0x61), + MBEDTLS_BYTES_TO_T_UINT_8(0xE4, 0x49, 0x2A, 0x1E, 0x7C, 0xE9, 0x2D, 0xEC), + MBEDTLS_BYTES_TO_T_UINT_8(0x3A, 0x87, 0x56, 0x91, 0x03, 0x77, 0x4D, 0x55), + MBEDTLS_BYTES_TO_T_UINT_8(0x0E, 0x52, 0xD4, 0xAA, 0xF7, 0xFA, 0xB0, 0xC5), + MBEDTLS_BYTES_TO_T_UINT_8(0x04, 0x5D, 0x11, 0x39, 0xB1, 0xE7, 0x76, 0xAD), + MBEDTLS_BYTES_TO_T_UINT_8(0xD6, 0x13, 0xBC, 0x37, 0x5D, 0x74, 0xCD, 0xC2), + MBEDTLS_BYTES_TO_T_UINT_8(0xC9, 0x48, 0x14, 0x23, 0x30, 0xF8, 0x46, 0x37), +}; +static const mbedtls_mpi_uint brainpoolP512r1_T_11_X[] = { + MBEDTLS_BYTES_TO_T_UINT_8(0xAC, 0x27, 0xB0, 0xD9, 0xB2, 0x74, 0xB4, 0xC0), + MBEDTLS_BYTES_TO_T_UINT_8(0xEA, 0xA6, 0xB9, 0x6F, 0x9F, 0x64, 0x36, 0x92), + MBEDTLS_BYTES_TO_T_UINT_8(0x2E, 0x2B, 0x78, 0x40, 0x05, 0x2B, 0x7B, 0xA9), + MBEDTLS_BYTES_TO_T_UINT_8(0xB3, 0x68, 0x3A, 0xB6, 0x4A, 0xE2, 0xDB, 0xB8), + MBEDTLS_BYTES_TO_T_UINT_8(0x1E, 0x33, 0xD7, 0x34, 0x8B, 0x25, 0x45, 0xEF), + MBEDTLS_BYTES_TO_T_UINT_8(0x89, 0xCE, 0xA8, 0xC9, 0x01, 0xFB, 0x0E, 0x7B), + MBEDTLS_BYTES_TO_T_UINT_8(0xE2, 0xF9, 0x51, 0x4C, 0x12, 0x9F, 0x60, 0xE4), + MBEDTLS_BYTES_TO_T_UINT_8(0x67, 0x85, 0xBD, 0x30, 0x37, 0x84, 0x39, 0x44), +}; +static const mbedtls_mpi_uint brainpoolP512r1_T_11_Y[] = { + MBEDTLS_BYTES_TO_T_UINT_8(0x26, 0x33, 0xAF, 0x2E, 0xB8, 0x2E, 0xCC, 0x3C), + MBEDTLS_BYTES_TO_T_UINT_8(0xA4, 0xB1, 0x73, 0x59, 0x4E, 0x0C, 0x09, 0x4A), + MBEDTLS_BYTES_TO_T_UINT_8(0x8A, 0x24, 0x89, 0x81, 0x12, 0xFF, 0xBB, 0x6E), + MBEDTLS_BYTES_TO_T_UINT_8(0x71, 0x37, 0x1A, 0x66, 0xEE, 0xED, 0xB6, 0x9B), + MBEDTLS_BYTES_TO_T_UINT_8(0x16, 0xBD, 0x04, 0x20, 0x5D, 0xFB, 0xBF, 0x95), + MBEDTLS_BYTES_TO_T_UINT_8(0xA0, 0xF8, 0x34, 0xA3, 0xFF, 0x45, 0xDE, 0x92), + MBEDTLS_BYTES_TO_T_UINT_8(0x9B, 0x18, 0x73, 0xF1, 0x32, 0x25, 0x58, 0xEB), + MBEDTLS_BYTES_TO_T_UINT_8(0x63, 0xC1, 0x14, 0xE3, 0x9E, 0x40, 0x0F, 0x12), +}; +static const mbedtls_mpi_uint brainpoolP512r1_T_12_X[] = { + MBEDTLS_BYTES_TO_T_UINT_8(0x61, 0x07, 0x9D, 0x9C, 0x00, 0xF7, 0x56, 0x19), + MBEDTLS_BYTES_TO_T_UINT_8(0xFB, 0xBA, 0x87, 0xF9, 0x15, 0x0C, 0x66, 0x5D), + MBEDTLS_BYTES_TO_T_UINT_8(0x7E, 0x1F, 0xC1, 0x28, 0xB0, 0x47, 0x0D, 0xF5), + MBEDTLS_BYTES_TO_T_UINT_8(0x96, 0xCA, 0x27, 0xEE, 0x4B, 0x23, 0x2B, 0x89), + MBEDTLS_BYTES_TO_T_UINT_8(0x7E, 0xB5, 0x68, 0xC8, 0x17, 0x5D, 0xC3, 0xAA), + MBEDTLS_BYTES_TO_T_UINT_8(0x17, 0x02, 0x08, 0xEE, 0x20, 0x9D, 0xEA, 0x64), + MBEDTLS_BYTES_TO_T_UINT_8(0xA7, 0x14, 0x50, 0xD4, 0x7D, 0x5F, 0xCF, 0xA0), + MBEDTLS_BYTES_TO_T_UINT_8(0xD5, 0xFA, 0xF8, 0xA7, 0xC6, 0xDC, 0x14, 0x8C), +}; +static const mbedtls_mpi_uint brainpoolP512r1_T_12_Y[] = { + MBEDTLS_BYTES_TO_T_UINT_8(0x76, 0xBD, 0x0A, 0x1A, 0x18, 0x98, 0xDC, 0xB0), + MBEDTLS_BYTES_TO_T_UINT_8(0x63, 0x63, 0x02, 0xB7, 0xD5, 0x5B, 0x5A, 0xC6), + MBEDTLS_BYTES_TO_T_UINT_8(0x51, 0xB1, 0xD7, 0x4B, 0x15, 0x39, 0x61, 0x5D), + MBEDTLS_BYTES_TO_T_UINT_8(0x5C, 0x32, 0xE1, 0x9E, 0x70, 0x1B, 0xCE, 0x51), + MBEDTLS_BYTES_TO_T_UINT_8(0x64, 0xD8, 0x18, 0x83, 0x52, 0x9B, 0x6D, 0xA2), + MBEDTLS_BYTES_TO_T_UINT_8(0xA4, 0x55, 0x56, 0x19, 0x34, 0xA4, 0xEA, 0xFC), + MBEDTLS_BYTES_TO_T_UINT_8(0x30, 0xA9, 0x55, 0x80, 0xE3, 0x15, 0x36, 0x8B), + MBEDTLS_BYTES_TO_T_UINT_8(0xBB, 0x06, 0xC8, 0x1D, 0x17, 0x0D, 0xAD, 0x16), +}; +static const mbedtls_mpi_uint brainpoolP512r1_T_13_X[] = { + MBEDTLS_BYTES_TO_T_UINT_8(0x20, 0xD6, 0xF0, 0xCC, 0xF3, 0x63, 0x53, 0xD2), + MBEDTLS_BYTES_TO_T_UINT_8(0x27, 0x5A, 0xDC, 0x46, 0xBD, 0x0D, 0xAD, 0x96), + MBEDTLS_BYTES_TO_T_UINT_8(0x21, 0x2F, 0x11, 0x60, 0x15, 0x51, 0x4A, 0xEA), + MBEDTLS_BYTES_TO_T_UINT_8(0x33, 0xE3, 0x93, 0x38, 0xD5, 0x83, 0xAA, 0x0D), + MBEDTLS_BYTES_TO_T_UINT_8(0x90, 0xA6, 0xCC, 0xB1, 0xFD, 0xBB, 0x1A, 0x0F), + MBEDTLS_BYTES_TO_T_UINT_8(0x3B, 0x54, 0xC8, 0x54, 0x6F, 0x79, 0x1A, 0x59), + MBEDTLS_BYTES_TO_T_UINT_8(0x3F, 0x4A, 0xDA, 0x28, 0x92, 0x97, 0x9D, 0x7F), + MBEDTLS_BYTES_TO_T_UINT_8(0xD6, 0x4B, 0xDB, 0xC7, 0x52, 0xC5, 0x66, 0x34), +}; +static const mbedtls_mpi_uint brainpoolP512r1_T_13_Y[] = { + MBEDTLS_BYTES_TO_T_UINT_8(0x05, 0x7E, 0x92, 0x53, 0x30, 0x93, 0xFD, 0xFF), + MBEDTLS_BYTES_TO_T_UINT_8(0xA0, 0x16, 0x6A, 0xB1, 0x91, 0x0A, 0xB4, 0x52), + MBEDTLS_BYTES_TO_T_UINT_8(0x6D, 0x9D, 0x40, 0x3F, 0xE3, 0xF1, 0x01, 0x46), + MBEDTLS_BYTES_TO_T_UINT_8(0x13, 0x0E, 0xD8, 0xED, 0x11, 0x8E, 0x4C, 0xED), + MBEDTLS_BYTES_TO_T_UINT_8(0x86, 0x4A, 0x1B, 0x88, 0xDF, 0x8D, 0x29, 0xE7), + MBEDTLS_BYTES_TO_T_UINT_8(0x97, 0x23, 0x21, 0x11, 0xAB, 0x77, 0x81, 0x62), + MBEDTLS_BYTES_TO_T_UINT_8(0x0B, 0xAF, 0x11, 0xFA, 0xBA, 0x40, 0x63, 0xE7), + MBEDTLS_BYTES_TO_T_UINT_8(0x2B, 0x6F, 0x8D, 0x80, 0xDF, 0x67, 0xF5, 0x44), +}; +static const mbedtls_mpi_uint brainpoolP512r1_T_14_X[] = { + MBEDTLS_BYTES_TO_T_UINT_8(0xB2, 0x8B, 0xB7, 0x08, 0xF4, 0xD7, 0x2D, 0xA8), + MBEDTLS_BYTES_TO_T_UINT_8(0xC7, 0x2B, 0x30, 0x02, 0x45, 0x71, 0x08, 0x49), + MBEDTLS_BYTES_TO_T_UINT_8(0x97, 0x3A, 0xCA, 0x50, 0xF6, 0xC2, 0x19, 0x8C), + MBEDTLS_BYTES_TO_T_UINT_8(0x17, 0xB9, 0x9B, 0x3E, 0x73, 0x95, 0x1D, 0x49), + MBEDTLS_BYTES_TO_T_UINT_8(0xB6, 0x60, 0x59, 0x48, 0xCB, 0xD8, 0xD6, 0xAA), + MBEDTLS_BYTES_TO_T_UINT_8(0xF0, 0xB9, 0x6C, 0x89, 0xAB, 0x99, 0xA8, 0xF8), + MBEDTLS_BYTES_TO_T_UINT_8(0xEF, 0xA1, 0x8B, 0x4E, 0x06, 0x19, 0xEC, 0x99), + MBEDTLS_BYTES_TO_T_UINT_8(0x70, 0x95, 0x04, 0xCF, 0xD5, 0x94, 0xB3, 0x02), +}; +static const mbedtls_mpi_uint brainpoolP512r1_T_14_Y[] = { + MBEDTLS_BYTES_TO_T_UINT_8(0x29, 0x35, 0x93, 0x7C, 0xB3, 0xB8, 0x9E, 0x1B), + MBEDTLS_BYTES_TO_T_UINT_8(0xC4, 0x45, 0x5C, 0x7E, 0xBF, 0x75, 0x81, 0x0F), + MBEDTLS_BYTES_TO_T_UINT_8(0xDC, 0xE8, 0x24, 0xDF, 0xEC, 0x2F, 0x7D, 0xB9), + MBEDTLS_BYTES_TO_T_UINT_8(0xF2, 0x8B, 0xD5, 0x6A, 0x9B, 0xA0, 0xE0, 0x4F), + MBEDTLS_BYTES_TO_T_UINT_8(0x32, 0xE3, 0x27, 0x82, 0xDE, 0xDD, 0xCA, 0x4B), + MBEDTLS_BYTES_TO_T_UINT_8(0xA7, 0x57, 0x56, 0x46, 0x05, 0x06, 0x01, 0x2E), + MBEDTLS_BYTES_TO_T_UINT_8(0x74, 0x35, 0xA7, 0x47, 0xE2, 0x6B, 0x2C, 0x4F), + MBEDTLS_BYTES_TO_T_UINT_8(0x38, 0x9D, 0x4C, 0xEC, 0x1F, 0x11, 0x75, 0x2B), +}; +static const mbedtls_mpi_uint brainpoolP512r1_T_15_X[] = { + MBEDTLS_BYTES_TO_T_UINT_8(0xAC, 0xAA, 0x41, 0xC1, 0xE9, 0x0E, 0xE9, 0xAA), + MBEDTLS_BYTES_TO_T_UINT_8(0x0A, 0xCF, 0x9C, 0x4B, 0xE8, 0xED, 0x0A, 0x49), + MBEDTLS_BYTES_TO_T_UINT_8(0x3D, 0x73, 0xCA, 0x0C, 0x46, 0x0A, 0x9C, 0xE4), + MBEDTLS_BYTES_TO_T_UINT_8(0x99, 0xE1, 0x9E, 0xBC, 0xFE, 0x44, 0x63, 0x6D), + MBEDTLS_BYTES_TO_T_UINT_8(0x31, 0x43, 0x71, 0xEE, 0xF8, 0xC1, 0x8C, 0x5C), + MBEDTLS_BYTES_TO_T_UINT_8(0x6A, 0x4B, 0xF0, 0x69, 0x25, 0xBD, 0x71, 0x1A), + MBEDTLS_BYTES_TO_T_UINT_8(0xFD, 0x9A, 0xFE, 0x82, 0xE7, 0xC1, 0xC1, 0xEE), + MBEDTLS_BYTES_TO_T_UINT_8(0xFC, 0x5A, 0x6E, 0x5E, 0x97, 0x6A, 0x35, 0x8D), +}; +static const mbedtls_mpi_uint brainpoolP512r1_T_15_Y[] = { + MBEDTLS_BYTES_TO_T_UINT_8(0xA2, 0x18, 0x6C, 0x7E, 0xB8, 0x9E, 0x57, 0x32), + MBEDTLS_BYTES_TO_T_UINT_8(0x35, 0xB9, 0xC1, 0xD0, 0xFE, 0x78, 0xFB, 0x32), + MBEDTLS_BYTES_TO_T_UINT_8(0x7C, 0x08, 0xAE, 0x46, 0x34, 0xEA, 0x7A, 0x7F), + MBEDTLS_BYTES_TO_T_UINT_8(0xE8, 0x1C, 0x56, 0xA9, 0x18, 0x37, 0xD4, 0x9E), + MBEDTLS_BYTES_TO_T_UINT_8(0x28, 0x63, 0xE9, 0x0A, 0xB6, 0x38, 0x3C, 0xC1), + MBEDTLS_BYTES_TO_T_UINT_8(0x3E, 0x4F, 0xA4, 0x6E, 0x85, 0x31, 0x23, 0x52), + MBEDTLS_BYTES_TO_T_UINT_8(0x0D, 0xAD, 0xC4, 0xC3, 0xB1, 0x4B, 0x1C, 0x82), + MBEDTLS_BYTES_TO_T_UINT_8(0x30, 0x56, 0x4A, 0x38, 0xB3, 0x6B, 0x6F, 0x2C), +}; +static const mbedtls_mpi_uint brainpoolP512r1_T_16_X[] = { + MBEDTLS_BYTES_TO_T_UINT_8(0x67, 0xC7, 0x19, 0xDE, 0x21, 0xED, 0x89, 0xD0), + MBEDTLS_BYTES_TO_T_UINT_8(0x2F, 0xBE, 0xA6, 0xAE, 0xEB, 0x9D, 0xA7, 0x2A), + MBEDTLS_BYTES_TO_T_UINT_8(0x04, 0x0E, 0x13, 0x1E, 0x86, 0x57, 0xC3, 0x3B), + MBEDTLS_BYTES_TO_T_UINT_8(0x1F, 0x4B, 0x30, 0x46, 0x52, 0xC1, 0xEC, 0x52), + MBEDTLS_BYTES_TO_T_UINT_8(0x6E, 0xD5, 0x44, 0x31, 0x96, 0x3B, 0x26, 0x27), + MBEDTLS_BYTES_TO_T_UINT_8(0x77, 0x68, 0xA8, 0x67, 0x78, 0x39, 0xE8, 0x68), + MBEDTLS_BYTES_TO_T_UINT_8(0x8E, 0x78, 0xB7, 0xDD, 0xF2, 0x58, 0xB6, 0x3D), + MBEDTLS_BYTES_TO_T_UINT_8(0x81, 0x3C, 0xB3, 0x26, 0xC4, 0x2C, 0x8C, 0xA5), +}; +static const mbedtls_mpi_uint brainpoolP512r1_T_16_Y[] = { + MBEDTLS_BYTES_TO_T_UINT_8(0xB9, 0x24, 0xE5, 0x73, 0xEE, 0x9A, 0x02, 0xA9), + MBEDTLS_BYTES_TO_T_UINT_8(0xD9, 0x6A, 0x65, 0x60, 0xF3, 0x62, 0xE3, 0xE9), + MBEDTLS_BYTES_TO_T_UINT_8(0xFB, 0x07, 0x84, 0xE6, 0x3B, 0x46, 0x65, 0x9F), + MBEDTLS_BYTES_TO_T_UINT_8(0xE1, 0x8F, 0x0C, 0xB0, 0xE1, 0x04, 0x82, 0x9D), + MBEDTLS_BYTES_TO_T_UINT_8(0xEB, 0x13, 0xBF, 0x3D, 0xA0, 0x48, 0xA2, 0x74), + MBEDTLS_BYTES_TO_T_UINT_8(0x08, 0x26, 0x76, 0x74, 0xAB, 0x0B, 0x29, 0xE8), + MBEDTLS_BYTES_TO_T_UINT_8(0x30, 0x6E, 0x5F, 0x03, 0x34, 0x7C, 0x38, 0xCE), + MBEDTLS_BYTES_TO_T_UINT_8(0x4D, 0x72, 0xF9, 0x3B, 0x3C, 0xA4, 0xBC, 0x7C), +}; +static const mbedtls_mpi_uint brainpoolP512r1_T_17_X[] = { + MBEDTLS_BYTES_TO_T_UINT_8(0x5C, 0xCE, 0x18, 0x80, 0xB8, 0x24, 0x45, 0x81), + MBEDTLS_BYTES_TO_T_UINT_8(0xF1, 0x09, 0x03, 0xB8, 0x06, 0x64, 0xF7, 0xEC), + MBEDTLS_BYTES_TO_T_UINT_8(0xF1, 0x26, 0xB1, 0x10, 0x6D, 0x71, 0x12, 0x2E), + MBEDTLS_BYTES_TO_T_UINT_8(0xAD, 0x12, 0xC6, 0x6E, 0x1E, 0x6A, 0xC3, 0x80), + MBEDTLS_BYTES_TO_T_UINT_8(0xE5, 0xD3, 0x0A, 0xDE, 0xD8, 0x6B, 0x04, 0x5C), + MBEDTLS_BYTES_TO_T_UINT_8(0x96, 0x87, 0x5B, 0xAE, 0xDB, 0x3C, 0xC0, 0xC5), + MBEDTLS_BYTES_TO_T_UINT_8(0x8E, 0xF5, 0xF9, 0xC1, 0x9A, 0x89, 0xBB, 0x7E), + MBEDTLS_BYTES_TO_T_UINT_8(0xED, 0x69, 0x72, 0x8B, 0xAE, 0x32, 0x13, 0x11), +}; +static const mbedtls_mpi_uint brainpoolP512r1_T_17_Y[] = { + MBEDTLS_BYTES_TO_T_UINT_8(0xF9, 0x16, 0x07, 0x50, 0xFA, 0x4C, 0xCF, 0xE8), + MBEDTLS_BYTES_TO_T_UINT_8(0xF8, 0x50, 0x21, 0xE9, 0xDE, 0xEC, 0x7E, 0xDF), + MBEDTLS_BYTES_TO_T_UINT_8(0x7C, 0x2F, 0xE8, 0x83, 0x30, 0x0B, 0x65, 0x0E), + MBEDTLS_BYTES_TO_T_UINT_8(0xA5, 0x0B, 0x99, 0xAC, 0xC9, 0xBA, 0x6C, 0x2A), + MBEDTLS_BYTES_TO_T_UINT_8(0xA7, 0x59, 0x5A, 0x0D, 0x7B, 0x9E, 0x08, 0xAD), + MBEDTLS_BYTES_TO_T_UINT_8(0x34, 0x91, 0xB2, 0xDC, 0x90, 0xCE, 0x67, 0xED), + MBEDTLS_BYTES_TO_T_UINT_8(0xE3, 0x93, 0x60, 0x0C, 0xD7, 0x1F, 0x2F, 0x17), + MBEDTLS_BYTES_TO_T_UINT_8(0x19, 0x7F, 0x9D, 0x40, 0xF8, 0x78, 0x7A, 0x54), +}; +static const mbedtls_mpi_uint brainpoolP512r1_T_18_X[] = { + MBEDTLS_BYTES_TO_T_UINT_8(0x13, 0x22, 0x95, 0xE8, 0xEF, 0x31, 0x57, 0x35), + MBEDTLS_BYTES_TO_T_UINT_8(0x2D, 0x88, 0x53, 0xFE, 0xAF, 0x7C, 0x47, 0x14), + MBEDTLS_BYTES_TO_T_UINT_8(0x0E, 0xCE, 0xCC, 0x79, 0xE8, 0x9F, 0x8C, 0xC4), + MBEDTLS_BYTES_TO_T_UINT_8(0xDB, 0x16, 0xDD, 0x77, 0x6E, 0x8A, 0x73, 0x97), + MBEDTLS_BYTES_TO_T_UINT_8(0xC0, 0x07, 0x97, 0x21, 0x3B, 0xF8, 0x5F, 0xA8), + MBEDTLS_BYTES_TO_T_UINT_8(0xC6, 0xB5, 0xD2, 0x81, 0x84, 0xF0, 0xE7, 0x9F), + MBEDTLS_BYTES_TO_T_UINT_8(0xCB, 0x8F, 0x75, 0x09, 0x6A, 0x0E, 0x53, 0xAD), + MBEDTLS_BYTES_TO_T_UINT_8(0xE6, 0x4F, 0x70, 0x97, 0xC7, 0xAC, 0x7D, 0x3F), +}; +static const mbedtls_mpi_uint brainpoolP512r1_T_18_Y[] = { + MBEDTLS_BYTES_TO_T_UINT_8(0xF9, 0x3C, 0x6A, 0xB4, 0x10, 0xA9, 0xC8, 0x1D), + MBEDTLS_BYTES_TO_T_UINT_8(0xEE, 0xC5, 0xD6, 0x69, 0x16, 0xB8, 0xAC, 0x25), + MBEDTLS_BYTES_TO_T_UINT_8(0xAC, 0x44, 0xDC, 0xEB, 0x48, 0x54, 0x5D, 0x5F), + MBEDTLS_BYTES_TO_T_UINT_8(0x6F, 0x48, 0x9B, 0xD7, 0x72, 0x69, 0xA4, 0x8A), + MBEDTLS_BYTES_TO_T_UINT_8(0xB4, 0x0D, 0x36, 0x9A, 0x66, 0x0B, 0xEC, 0x24), + MBEDTLS_BYTES_TO_T_UINT_8(0xBE, 0xC6, 0xD4, 0xB6, 0x60, 0xE5, 0xC3, 0x3A), + MBEDTLS_BYTES_TO_T_UINT_8(0xBA, 0x29, 0x42, 0xE0, 0x9D, 0xFD, 0x7C, 0x3E), + MBEDTLS_BYTES_TO_T_UINT_8(0x43, 0x10, 0xBA, 0x55, 0xBC, 0x3B, 0x38, 0x5D), +}; +static const mbedtls_mpi_uint brainpoolP512r1_T_19_X[] = { + MBEDTLS_BYTES_TO_T_UINT_8(0x25, 0x66, 0xFA, 0x05, 0x73, 0x03, 0x1B, 0x69), + MBEDTLS_BYTES_TO_T_UINT_8(0x11, 0xA4, 0x66, 0x12, 0x96, 0x7B, 0x02, 0x4C), + MBEDTLS_BYTES_TO_T_UINT_8(0x44, 0xB5, 0xDE, 0x6D, 0x98, 0xD1, 0xD5, 0xA8), + MBEDTLS_BYTES_TO_T_UINT_8(0xE2, 0xF5, 0x44, 0xB8, 0x8E, 0xF6, 0x8C, 0x05), + MBEDTLS_BYTES_TO_T_UINT_8(0x68, 0x15, 0x2B, 0x72, 0xBC, 0x49, 0xE5, 0xDF), + MBEDTLS_BYTES_TO_T_UINT_8(0x6C, 0x44, 0xD7, 0xDF, 0x8F, 0xEB, 0x8D, 0x80), + MBEDTLS_BYTES_TO_T_UINT_8(0x05, 0x64, 0x88, 0xAA, 0xB7, 0xE4, 0x70, 0x1D), + MBEDTLS_BYTES_TO_T_UINT_8(0x9C, 0x14, 0xBB, 0xE9, 0x9B, 0xB9, 0x65, 0x5D), +}; +static const mbedtls_mpi_uint brainpoolP512r1_T_19_Y[] = { + MBEDTLS_BYTES_TO_T_UINT_8(0x66, 0x8E, 0x88, 0xF5, 0xF1, 0xC1, 0x89, 0xA2), + MBEDTLS_BYTES_TO_T_UINT_8(0x16, 0x30, 0x53, 0xE6, 0xFB, 0x2D, 0x82, 0xB4), + MBEDTLS_BYTES_TO_T_UINT_8(0xA7, 0xE4, 0xFF, 0xBA, 0x31, 0x79, 0xAB, 0xC2), + MBEDTLS_BYTES_TO_T_UINT_8(0x45, 0x09, 0xF7, 0xB7, 0x09, 0x78, 0x4C, 0x90), + MBEDTLS_BYTES_TO_T_UINT_8(0x10, 0xAE, 0xC2, 0x44, 0xDC, 0x17, 0x78, 0x47), + MBEDTLS_BYTES_TO_T_UINT_8(0xC7, 0xD4, 0x17, 0x43, 0x19, 0x74, 0x9E, 0x23), + MBEDTLS_BYTES_TO_T_UINT_8(0x15, 0x64, 0x3B, 0x73, 0xA2, 0x99, 0x27, 0x76), + MBEDTLS_BYTES_TO_T_UINT_8(0x05, 0x74, 0x36, 0x5F, 0xD3, 0x14, 0xB1, 0x31), +}; +static const mbedtls_mpi_uint brainpoolP512r1_T_20_X[] = { + MBEDTLS_BYTES_TO_T_UINT_8(0xAC, 0x07, 0xAB, 0xFD, 0x9B, 0x03, 0xC5, 0xD5), + MBEDTLS_BYTES_TO_T_UINT_8(0xC7, 0xBE, 0xB0, 0x1D, 0xF2, 0x0C, 0x73, 0x73), + MBEDTLS_BYTES_TO_T_UINT_8(0x99, 0xE7, 0x7B, 0x87, 0xD3, 0x34, 0xFD, 0xE2), + MBEDTLS_BYTES_TO_T_UINT_8(0x9A, 0x25, 0x3D, 0xC7, 0x36, 0x83, 0x53, 0xDC), + MBEDTLS_BYTES_TO_T_UINT_8(0x22, 0x7C, 0xCF, 0x63, 0x55, 0x12, 0x11, 0xB0), + MBEDTLS_BYTES_TO_T_UINT_8(0xC0, 0x34, 0x4D, 0x27, 0x92, 0xAC, 0x18, 0x16), + MBEDTLS_BYTES_TO_T_UINT_8(0x98, 0x42, 0x61, 0x9D, 0x2E, 0xFF, 0x13, 0x16), + MBEDTLS_BYTES_TO_T_UINT_8(0xF4, 0xDE, 0x92, 0x65, 0x57, 0x0D, 0xBC, 0x0A), +}; +static const mbedtls_mpi_uint brainpoolP512r1_T_20_Y[] = { + MBEDTLS_BYTES_TO_T_UINT_8(0xEF, 0x7B, 0x6E, 0xC6, 0x2A, 0x21, 0x74, 0x0A), + MBEDTLS_BYTES_TO_T_UINT_8(0x37, 0xA7, 0x53, 0x4D, 0x29, 0x36, 0xEF, 0xE5), + MBEDTLS_BYTES_TO_T_UINT_8(0xE1, 0xD6, 0x41, 0xC7, 0x99, 0xAD, 0x50, 0x53), + MBEDTLS_BYTES_TO_T_UINT_8(0x99, 0xAC, 0x41, 0x9F, 0xFB, 0x4C, 0x86, 0xF1), + MBEDTLS_BYTES_TO_T_UINT_8(0x8B, 0xBB, 0xE6, 0x25, 0x28, 0xAA, 0xEB, 0x1E), + MBEDTLS_BYTES_TO_T_UINT_8(0x92, 0x04, 0xA2, 0xC3, 0xAA, 0x08, 0x8A, 0xCC), + MBEDTLS_BYTES_TO_T_UINT_8(0x5A, 0x2B, 0x5B, 0xE2, 0x8D, 0x76, 0xEA, 0x34), + MBEDTLS_BYTES_TO_T_UINT_8(0xB3, 0x33, 0xD2, 0x21, 0x4D, 0x62, 0xE3, 0x8E), +}; +static const mbedtls_mpi_uint brainpoolP512r1_T_21_X[] = { + MBEDTLS_BYTES_TO_T_UINT_8(0xF6, 0x06, 0x8B, 0x2B, 0xC2, 0xC4, 0xB1, 0xD2), + MBEDTLS_BYTES_TO_T_UINT_8(0xFA, 0xF5, 0xA1, 0xC0, 0x03, 0x6A, 0x29, 0x12), + MBEDTLS_BYTES_TO_T_UINT_8(0xF5, 0xA9, 0xEF, 0x55, 0xB6, 0x1A, 0x9F, 0x6B), + MBEDTLS_BYTES_TO_T_UINT_8(0x9B, 0x54, 0x32, 0xBE, 0x06, 0x43, 0xB5, 0xFD), + MBEDTLS_BYTES_TO_T_UINT_8(0xF7, 0xD6, 0xD9, 0x20, 0x89, 0xBE, 0xD4, 0x1B), + MBEDTLS_BYTES_TO_T_UINT_8(0xE8, 0x26, 0x95, 0x10, 0xCE, 0xB4, 0x88, 0x79), + MBEDTLS_BYTES_TO_T_UINT_8(0xE6, 0xA6, 0x27, 0xAC, 0x32, 0xBA, 0xBD, 0xC7), + MBEDTLS_BYTES_TO_T_UINT_8(0xA3, 0xA6, 0xAE, 0x9C, 0x7B, 0xBE, 0xA1, 0x63), +}; +static const mbedtls_mpi_uint brainpoolP512r1_T_21_Y[] = { + MBEDTLS_BYTES_TO_T_UINT_8(0x8B, 0xCD, 0x4D, 0x3D, 0xDF, 0x96, 0xBB, 0x7D), + MBEDTLS_BYTES_TO_T_UINT_8(0x77, 0xA7, 0x11, 0x06, 0xCC, 0x0E, 0x31, 0x81), + MBEDTLS_BYTES_TO_T_UINT_8(0x20, 0xE4, 0xF4, 0xAD, 0x7B, 0x5F, 0xF1, 0xEF), + MBEDTLS_BYTES_TO_T_UINT_8(0xE4, 0x54, 0xBE, 0xF4, 0x8A, 0x03, 0x47, 0xDF), + MBEDTLS_BYTES_TO_T_UINT_8(0xB4, 0x53, 0x00, 0x7F, 0xB0, 0x8A, 0x68, 0xA6), + MBEDTLS_BYTES_TO_T_UINT_8(0xA0, 0x16, 0xB1, 0x73, 0x6F, 0x5B, 0x0E, 0xC3), + MBEDTLS_BYTES_TO_T_UINT_8(0x2A, 0x32, 0xE3, 0x43, 0x64, 0x75, 0xFB, 0xFB), + MBEDTLS_BYTES_TO_T_UINT_8(0xA0, 0x18, 0x55, 0x8A, 0x4E, 0x6E, 0x35, 0x54), +}; +static const mbedtls_mpi_uint brainpoolP512r1_T_22_X[] = { + MBEDTLS_BYTES_TO_T_UINT_8(0x80, 0x97, 0x15, 0x1E, 0xCB, 0xF2, 0x9C, 0xA5), + MBEDTLS_BYTES_TO_T_UINT_8(0x2B, 0xD1, 0xBB, 0xF3, 0x70, 0xAD, 0x13, 0xAD), + MBEDTLS_BYTES_TO_T_UINT_8(0xD8, 0x96, 0xA4, 0xC5, 0x5E, 0xDA, 0xD5, 0x57), + MBEDTLS_BYTES_TO_T_UINT_8(0x07, 0x81, 0xE9, 0x65, 0x66, 0x76, 0x47, 0x45), + MBEDTLS_BYTES_TO_T_UINT_8(0xC9, 0x35, 0x87, 0x06, 0x73, 0xCF, 0x34, 0xD2), + MBEDTLS_BYTES_TO_T_UINT_8(0x5A, 0x81, 0x15, 0x42, 0xA2, 0x79, 0x5B, 0x42), + MBEDTLS_BYTES_TO_T_UINT_8(0x08, 0xA2, 0x7D, 0x09, 0x14, 0x64, 0xC6, 0xAE), + MBEDTLS_BYTES_TO_T_UINT_8(0x5E, 0x6D, 0xC4, 0xED, 0xF1, 0xD6, 0xE9, 0x24), +}; +static const mbedtls_mpi_uint brainpoolP512r1_T_22_Y[] = { + MBEDTLS_BYTES_TO_T_UINT_8(0xB4, 0xD5, 0xBB, 0x25, 0xA3, 0xDD, 0xA3, 0x88), + MBEDTLS_BYTES_TO_T_UINT_8(0x46, 0xF2, 0x68, 0x67, 0x39, 0x8F, 0x73, 0x93), + MBEDTLS_BYTES_TO_T_UINT_8(0xF0, 0x76, 0x28, 0x89, 0xAD, 0x32, 0xE0, 0xDF), + MBEDTLS_BYTES_TO_T_UINT_8(0xF8, 0x90, 0xCC, 0x57, 0x58, 0xAA, 0xC9, 0x75), + MBEDTLS_BYTES_TO_T_UINT_8(0x5E, 0xD7, 0x43, 0xD2, 0xCE, 0x5E, 0xA0, 0x08), + MBEDTLS_BYTES_TO_T_UINT_8(0x33, 0xB0, 0xB8, 0xA4, 0x9E, 0x96, 0x26, 0x86), + MBEDTLS_BYTES_TO_T_UINT_8(0x94, 0x61, 0x1D, 0xF3, 0x65, 0x5E, 0x60, 0xCA), + MBEDTLS_BYTES_TO_T_UINT_8(0xC7, 0x1E, 0x65, 0xED, 0xCF, 0x07, 0x60, 0x20), +}; +static const mbedtls_mpi_uint brainpoolP512r1_T_23_X[] = { + MBEDTLS_BYTES_TO_T_UINT_8(0xA4, 0x30, 0x17, 0x8A, 0x91, 0x88, 0x0A, 0xA4), + MBEDTLS_BYTES_TO_T_UINT_8(0x05, 0x7D, 0x18, 0xA4, 0xAC, 0x59, 0xFC, 0x5F), + MBEDTLS_BYTES_TO_T_UINT_8(0xA4, 0x31, 0x8B, 0x25, 0x65, 0x39, 0x9A, 0xDC), + MBEDTLS_BYTES_TO_T_UINT_8(0x15, 0x16, 0x4B, 0x68, 0xBA, 0x59, 0x13, 0x2F), + MBEDTLS_BYTES_TO_T_UINT_8(0x8D, 0xFD, 0xD3, 0xC5, 0x56, 0xC9, 0x8C, 0x5E), + MBEDTLS_BYTES_TO_T_UINT_8(0xBC, 0xC6, 0x9F, 0xF4, 0xE6, 0xF7, 0xB4, 0x01), + MBEDTLS_BYTES_TO_T_UINT_8(0x2D, 0x7C, 0x03, 0x00, 0x26, 0x9F, 0xD8, 0x7B), + MBEDTLS_BYTES_TO_T_UINT_8(0x24, 0x1D, 0x6E, 0x00, 0xB9, 0x00, 0x6E, 0x93), +}; +static const mbedtls_mpi_uint brainpoolP512r1_T_23_Y[] = { + MBEDTLS_BYTES_TO_T_UINT_8(0x75, 0x63, 0xDA, 0x03, 0x2B, 0xD5, 0x0B, 0xFE), + MBEDTLS_BYTES_TO_T_UINT_8(0x46, 0xFC, 0xE2, 0xC8, 0x47, 0xF0, 0xAE, 0xF2), + MBEDTLS_BYTES_TO_T_UINT_8(0x51, 0x4C, 0xF7, 0x50, 0x0C, 0x48, 0x06, 0x2A), + MBEDTLS_BYTES_TO_T_UINT_8(0xDF, 0x2B, 0x32, 0x98, 0x0E, 0x7E, 0x61, 0x41), + MBEDTLS_BYTES_TO_T_UINT_8(0x5D, 0x02, 0x27, 0xFE, 0x75, 0x86, 0xDF, 0x24), + MBEDTLS_BYTES_TO_T_UINT_8(0x2B, 0x30, 0xB1, 0x22, 0x32, 0x1B, 0xFE, 0x24), + MBEDTLS_BYTES_TO_T_UINT_8(0xC2, 0x27, 0xF7, 0x78, 0x6F, 0xD7, 0xFD, 0xE4), + MBEDTLS_BYTES_TO_T_UINT_8(0xA0, 0x78, 0xCC, 0xEA, 0xC0, 0x50, 0x24, 0x44), +}; +static const mbedtls_mpi_uint brainpoolP512r1_T_24_X[] = { + MBEDTLS_BYTES_TO_T_UINT_8(0x37, 0x2B, 0x4F, 0x7F, 0x58, 0xE6, 0xC2, 0x70), + MBEDTLS_BYTES_TO_T_UINT_8(0x37, 0x43, 0xD5, 0xA7, 0x35, 0x3C, 0x80, 0xB8), + MBEDTLS_BYTES_TO_T_UINT_8(0x1A, 0x6D, 0x4B, 0x12, 0x00, 0x7B, 0xE6, 0xA6), + MBEDTLS_BYTES_TO_T_UINT_8(0x37, 0x15, 0xBD, 0xD0, 0x9B, 0xCA, 0xAA, 0x81), + MBEDTLS_BYTES_TO_T_UINT_8(0xCF, 0xCE, 0x9C, 0xE3, 0x8B, 0x60, 0x7A, 0x53), + MBEDTLS_BYTES_TO_T_UINT_8(0x0C, 0xDA, 0x4B, 0x03, 0xA7, 0x8D, 0x43, 0x22), + MBEDTLS_BYTES_TO_T_UINT_8(0x57, 0xAF, 0x00, 0x2B, 0x32, 0xF0, 0x22, 0x68), + MBEDTLS_BYTES_TO_T_UINT_8(0xDC, 0xD9, 0x99, 0x99, 0xBE, 0x43, 0x99, 0x3E), +}; +static const mbedtls_mpi_uint brainpoolP512r1_T_24_Y[] = { + MBEDTLS_BYTES_TO_T_UINT_8(0x1F, 0x71, 0x41, 0xF4, 0xB5, 0xFD, 0xDD, 0x36), + MBEDTLS_BYTES_TO_T_UINT_8(0x9D, 0xE2, 0x20, 0x4C, 0xD1, 0x2E, 0x1F, 0x06), + MBEDTLS_BYTES_TO_T_UINT_8(0x96, 0x43, 0x48, 0x76, 0x8A, 0x49, 0xAC, 0x87), + MBEDTLS_BYTES_TO_T_UINT_8(0x0C, 0x1A, 0x55, 0xA8, 0xA3, 0xD4, 0x57, 0x75), + MBEDTLS_BYTES_TO_T_UINT_8(0x7C, 0xA6, 0x84, 0x39, 0xC9, 0x13, 0xBB, 0x60), + MBEDTLS_BYTES_TO_T_UINT_8(0xD9, 0xFA, 0xA9, 0x70, 0xDE, 0x83, 0xDD, 0xC9), + MBEDTLS_BYTES_TO_T_UINT_8(0xEC, 0xC9, 0xD9, 0x3E, 0x44, 0x91, 0x68, 0x7B), + MBEDTLS_BYTES_TO_T_UINT_8(0xB6, 0x9F, 0x85, 0x6D, 0xF7, 0x54, 0x36, 0x82), +}; +static const mbedtls_mpi_uint brainpoolP512r1_T_25_X[] = { + MBEDTLS_BYTES_TO_T_UINT_8(0x68, 0x6B, 0xA6, 0xA3, 0xE5, 0xD4, 0x46, 0xDB), + MBEDTLS_BYTES_TO_T_UINT_8(0x23, 0x3E, 0xDC, 0x84, 0x7C, 0x7B, 0x24, 0x34), + MBEDTLS_BYTES_TO_T_UINT_8(0x14, 0xED, 0x7F, 0x86, 0x07, 0x6C, 0x57, 0xCA), + MBEDTLS_BYTES_TO_T_UINT_8(0x95, 0x06, 0xFE, 0x52, 0x12, 0x79, 0x69, 0x56), + MBEDTLS_BYTES_TO_T_UINT_8(0x84, 0xD1, 0x44, 0x5F, 0x21, 0x3A, 0xC3, 0x84), + MBEDTLS_BYTES_TO_T_UINT_8(0x5E, 0xD9, 0x4A, 0xC0, 0x75, 0xAB, 0x17, 0xAC), + MBEDTLS_BYTES_TO_T_UINT_8(0xFF, 0x81, 0x94, 0xB6, 0x80, 0x6B, 0x6F, 0xC3), + MBEDTLS_BYTES_TO_T_UINT_8(0x07, 0xBE, 0x8E, 0xA5, 0xAA, 0xBC, 0x1E, 0x3E), +}; +static const mbedtls_mpi_uint brainpoolP512r1_T_25_Y[] = { + MBEDTLS_BYTES_TO_T_UINT_8(0x89, 0xC7, 0x85, 0xA6, 0x59, 0x9B, 0xB1, 0x52), + MBEDTLS_BYTES_TO_T_UINT_8(0x1C, 0xCE, 0x40, 0xD1, 0xFB, 0xDF, 0x94, 0xF7), + MBEDTLS_BYTES_TO_T_UINT_8(0x18, 0xB8, 0x5E, 0xBF, 0x45, 0xA8, 0x2D, 0x2D), + MBEDTLS_BYTES_TO_T_UINT_8(0x98, 0x9C, 0x06, 0x1B, 0xA9, 0x57, 0xB9, 0x79), + MBEDTLS_BYTES_TO_T_UINT_8(0x53, 0xE9, 0xCE, 0xA2, 0xD3, 0x74, 0xA1, 0x3C), + MBEDTLS_BYTES_TO_T_UINT_8(0xAA, 0x5F, 0x34, 0x78, 0xDB, 0xAE, 0x3A, 0x14), + MBEDTLS_BYTES_TO_T_UINT_8(0x7D, 0x32, 0x84, 0x3E, 0x68, 0x6A, 0x43, 0x0F), + MBEDTLS_BYTES_TO_T_UINT_8(0x8C, 0xBC, 0x39, 0x36, 0xA4, 0xC5, 0xBB, 0x11), +}; +static const mbedtls_mpi_uint brainpoolP512r1_T_26_X[] = { + MBEDTLS_BYTES_TO_T_UINT_8(0x8C, 0x07, 0xA2, 0xB5, 0xC9, 0x0F, 0x4D, 0x0F), + MBEDTLS_BYTES_TO_T_UINT_8(0xE3, 0x1D, 0x67, 0xE6, 0xF1, 0x46, 0xEB, 0x71), + MBEDTLS_BYTES_TO_T_UINT_8(0xD7, 0x41, 0x23, 0x95, 0xE7, 0xE0, 0x10, 0xDD), + MBEDTLS_BYTES_TO_T_UINT_8(0xBE, 0x69, 0xFE, 0x68, 0x8C, 0xC6, 0x5F, 0xB6), + MBEDTLS_BYTES_TO_T_UINT_8(0xE3, 0xB9, 0x2B, 0x3D, 0xD2, 0x4F, 0xD8, 0x1A), + MBEDTLS_BYTES_TO_T_UINT_8(0xA3, 0x09, 0xF5, 0x5F, 0xCF, 0xF6, 0x91, 0x57), + MBEDTLS_BYTES_TO_T_UINT_8(0x65, 0x15, 0x42, 0x6B, 0x6D, 0xB5, 0xF3, 0xB6), + MBEDTLS_BYTES_TO_T_UINT_8(0xBF, 0x56, 0x9D, 0xC5, 0xFF, 0xCA, 0x13, 0x9B), +}; +static const mbedtls_mpi_uint brainpoolP512r1_T_26_Y[] = { + MBEDTLS_BYTES_TO_T_UINT_8(0x4D, 0x38, 0xE6, 0x23, 0x63, 0x48, 0x3C, 0xCA), + MBEDTLS_BYTES_TO_T_UINT_8(0xD2, 0x68, 0x3C, 0xD1, 0x3B, 0xE9, 0x3B, 0x82), + MBEDTLS_BYTES_TO_T_UINT_8(0xB5, 0x08, 0x54, 0x49, 0xD1, 0x46, 0x45, 0x13), + MBEDTLS_BYTES_TO_T_UINT_8(0x07, 0x70, 0x52, 0x6E, 0x79, 0xC4, 0x5E, 0x95), + MBEDTLS_BYTES_TO_T_UINT_8(0x36, 0xDF, 0xE8, 0x5A, 0x32, 0x81, 0xDA, 0xD3), + MBEDTLS_BYTES_TO_T_UINT_8(0x3C, 0x2D, 0x94, 0x5B, 0xB5, 0x35, 0x9F, 0x0A), + MBEDTLS_BYTES_TO_T_UINT_8(0x2A, 0x12, 0x8D, 0xC3, 0x36, 0x36, 0xB2, 0x2A), + MBEDTLS_BYTES_TO_T_UINT_8(0x39, 0x2F, 0x22, 0x38, 0x5B, 0x18, 0x4C, 0x35), +}; +static const mbedtls_mpi_uint brainpoolP512r1_T_27_X[] = { + MBEDTLS_BYTES_TO_T_UINT_8(0x10, 0xC1, 0x22, 0x0E, 0xF0, 0x73, 0x11, 0x05), + MBEDTLS_BYTES_TO_T_UINT_8(0xB2, 0xAE, 0xA4, 0x56, 0x18, 0x61, 0x66, 0x12), + MBEDTLS_BYTES_TO_T_UINT_8(0x79, 0xFB, 0x72, 0x08, 0x84, 0x38, 0x51, 0xB0), + MBEDTLS_BYTES_TO_T_UINT_8(0xDA, 0x86, 0xA8, 0xB9, 0x31, 0x99, 0x29, 0xC3), + MBEDTLS_BYTES_TO_T_UINT_8(0x8A, 0xFB, 0xC3, 0x42, 0xB3, 0xC7, 0x6F, 0x3A), + MBEDTLS_BYTES_TO_T_UINT_8(0xD8, 0xF8, 0xE1, 0x09, 0xBE, 0x75, 0xB0, 0x22), + MBEDTLS_BYTES_TO_T_UINT_8(0x5A, 0x7D, 0xFF, 0xF4, 0x99, 0xFC, 0x13, 0xAB), + MBEDTLS_BYTES_TO_T_UINT_8(0xE6, 0x1B, 0x84, 0x81, 0x42, 0x22, 0xC6, 0x3D), +}; +static const mbedtls_mpi_uint brainpoolP512r1_T_27_Y[] = { + MBEDTLS_BYTES_TO_T_UINT_8(0x21, 0xE0, 0x37, 0xA4, 0xA0, 0x2F, 0x38, 0x7F), + MBEDTLS_BYTES_TO_T_UINT_8(0xD0, 0x3D, 0xB7, 0x40, 0x2F, 0x39, 0x3C, 0x7A), + MBEDTLS_BYTES_TO_T_UINT_8(0x7A, 0x3B, 0x8A, 0x51, 0xAE, 0x40, 0x49, 0x7A), + MBEDTLS_BYTES_TO_T_UINT_8(0x36, 0x20, 0x9F, 0xDD, 0xA9, 0xD0, 0x77, 0xC7), + MBEDTLS_BYTES_TO_T_UINT_8(0x78, 0x1D, 0x64, 0xDA, 0xA0, 0x53, 0xC7, 0x7D), + MBEDTLS_BYTES_TO_T_UINT_8(0x37, 0x7B, 0x66, 0x55, 0x94, 0xD1, 0x51, 0x44), + MBEDTLS_BYTES_TO_T_UINT_8(0x0E, 0xA9, 0xB5, 0x5B, 0x38, 0x35, 0x40, 0xC0), + MBEDTLS_BYTES_TO_T_UINT_8(0xC8, 0xC9, 0x0F, 0xF0, 0x73, 0x79, 0x43, 0x61), +}; +static const mbedtls_mpi_uint brainpoolP512r1_T_28_X[] = { + MBEDTLS_BYTES_TO_T_UINT_8(0x10, 0x47, 0x45, 0x69, 0x80, 0x72, 0x72, 0x42), + MBEDTLS_BYTES_TO_T_UINT_8(0x70, 0x11, 0x99, 0x59, 0xDB, 0x48, 0x80, 0x39), + MBEDTLS_BYTES_TO_T_UINT_8(0x75, 0x6E, 0x3D, 0xFC, 0x37, 0x15, 0xF4, 0xBF), + MBEDTLS_BYTES_TO_T_UINT_8(0x17, 0xBB, 0x5B, 0xA6, 0x35, 0x8D, 0x28, 0x20), + MBEDTLS_BYTES_TO_T_UINT_8(0xAB, 0x1A, 0x3B, 0x2C, 0x8F, 0xD3, 0xAA, 0x2D), + MBEDTLS_BYTES_TO_T_UINT_8(0x55, 0x1C, 0x1A, 0xF8, 0x02, 0xD9, 0x7B, 0x41), + MBEDTLS_BYTES_TO_T_UINT_8(0xAF, 0x69, 0xAC, 0xF8, 0x54, 0x31, 0x14, 0xA1), + MBEDTLS_BYTES_TO_T_UINT_8(0x41, 0x8A, 0xE6, 0xDE, 0x58, 0xB9, 0xC4, 0x7A), +}; +static const mbedtls_mpi_uint brainpoolP512r1_T_28_Y[] = { + MBEDTLS_BYTES_TO_T_UINT_8(0x57, 0x83, 0x52, 0xFE, 0xF9, 0x7B, 0xE9, 0x1F), + MBEDTLS_BYTES_TO_T_UINT_8(0x07, 0xA2, 0x55, 0x46, 0x15, 0x49, 0xC1, 0x3A), + MBEDTLS_BYTES_TO_T_UINT_8(0x1D, 0xBC, 0x5C, 0x91, 0xBD, 0xB9, 0x9C, 0xF4), + MBEDTLS_BYTES_TO_T_UINT_8(0xBB, 0xFD, 0xB1, 0x4E, 0x5F, 0x74, 0xEE, 0x53), + MBEDTLS_BYTES_TO_T_UINT_8(0xB1, 0x8B, 0xD8, 0x8B, 0x17, 0x73, 0x1B, 0x96), + MBEDTLS_BYTES_TO_T_UINT_8(0x22, 0x92, 0xD7, 0x67, 0x06, 0xAD, 0x25, 0xCD), + MBEDTLS_BYTES_TO_T_UINT_8(0x01, 0x0F, 0x80, 0x24, 0xE2, 0x27, 0x5F, 0x8B), + MBEDTLS_BYTES_TO_T_UINT_8(0x61, 0x1C, 0xCE, 0xD0, 0x67, 0xCA, 0xD4, 0x0B), +}; +static const mbedtls_mpi_uint brainpoolP512r1_T_29_X[] = { + MBEDTLS_BYTES_TO_T_UINT_8(0x87, 0xF1, 0xDD, 0x33, 0x66, 0xF9, 0x05, 0xD6), + MBEDTLS_BYTES_TO_T_UINT_8(0x1D, 0xE5, 0x6B, 0x79, 0xBD, 0x48, 0x42, 0xAA), + MBEDTLS_BYTES_TO_T_UINT_8(0xD1, 0x14, 0x52, 0xE3, 0x53, 0xB4, 0x50, 0xD4), + MBEDTLS_BYTES_TO_T_UINT_8(0x32, 0x84, 0x6C, 0xCF, 0xDA, 0xB2, 0x20, 0x0A), + MBEDTLS_BYTES_TO_T_UINT_8(0x70, 0xD6, 0x1A, 0xE5, 0xE2, 0x29, 0x70, 0xCE), + MBEDTLS_BYTES_TO_T_UINT_8(0xD5, 0x61, 0xFE, 0xBB, 0x21, 0x82, 0xD1, 0xFE), + MBEDTLS_BYTES_TO_T_UINT_8(0x2C, 0xF0, 0x9C, 0x8B, 0x1A, 0x42, 0x30, 0x06), + MBEDTLS_BYTES_TO_T_UINT_8(0x43, 0xD6, 0x49, 0x81, 0x92, 0xF1, 0xD0, 0x90), +}; +static const mbedtls_mpi_uint brainpoolP512r1_T_29_Y[] = { + MBEDTLS_BYTES_TO_T_UINT_8(0xC9, 0x91, 0x93, 0x6A, 0xA6, 0x22, 0xE9, 0xD6), + MBEDTLS_BYTES_TO_T_UINT_8(0x09, 0xDC, 0xC3, 0x69, 0x11, 0x95, 0x7D, 0xEC), + MBEDTLS_BYTES_TO_T_UINT_8(0x1C, 0xA3, 0x9D, 0x87, 0x5E, 0x64, 0x41, 0xA2), + MBEDTLS_BYTES_TO_T_UINT_8(0xBE, 0x87, 0x5A, 0x15, 0xBD, 0x6E, 0x3C, 0x8D), + MBEDTLS_BYTES_TO_T_UINT_8(0xD0, 0x8D, 0x50, 0xCC, 0xCF, 0xB7, 0x8F, 0x0B), + MBEDTLS_BYTES_TO_T_UINT_8(0x38, 0x65, 0xCD, 0x31, 0x30, 0xF1, 0x68, 0x13), + MBEDTLS_BYTES_TO_T_UINT_8(0x10, 0x5C, 0x66, 0x67, 0x92, 0x30, 0x57, 0x95), + MBEDTLS_BYTES_TO_T_UINT_8(0x23, 0x9B, 0x01, 0x3D, 0x20, 0x8B, 0xD1, 0x0D), +}; +static const mbedtls_mpi_uint brainpoolP512r1_T_30_X[] = { + MBEDTLS_BYTES_TO_T_UINT_8(0xAB, 0xC0, 0xE6, 0x4F, 0xDE, 0x62, 0xAB, 0xB3), + MBEDTLS_BYTES_TO_T_UINT_8(0xA4, 0x48, 0xB3, 0x1C, 0x0F, 0x16, 0x93, 0x45), + MBEDTLS_BYTES_TO_T_UINT_8(0x77, 0x63, 0xBD, 0x1F, 0x16, 0x50, 0x56, 0x98), + MBEDTLS_BYTES_TO_T_UINT_8(0x5D, 0x06, 0xBC, 0xE9, 0x27, 0x1C, 0x9A, 0x7B), + MBEDTLS_BYTES_TO_T_UINT_8(0xF8, 0xFE, 0x21, 0xC5, 0x39, 0x55, 0xE1, 0xFD), + MBEDTLS_BYTES_TO_T_UINT_8(0xF6, 0xA8, 0xD0, 0x96, 0x0E, 0xB5, 0xB2, 0x84), + MBEDTLS_BYTES_TO_T_UINT_8(0x3D, 0xE7, 0x4B, 0xF3, 0x11, 0x0C, 0xC9, 0x5B), + MBEDTLS_BYTES_TO_T_UINT_8(0x43, 0x3A, 0xC4, 0x87, 0x71, 0xEE, 0xFA, 0x18), +}; +static const mbedtls_mpi_uint brainpoolP512r1_T_30_Y[] = { + MBEDTLS_BYTES_TO_T_UINT_8(0xA7, 0x77, 0xEE, 0x81, 0x5E, 0x96, 0xEA, 0x4B), + MBEDTLS_BYTES_TO_T_UINT_8(0xEE, 0xDF, 0xA9, 0xF4, 0x4F, 0x7C, 0xB2, 0x43), + MBEDTLS_BYTES_TO_T_UINT_8(0x9F, 0xD4, 0xDF, 0x35, 0x63, 0x47, 0x25, 0x8A), + MBEDTLS_BYTES_TO_T_UINT_8(0xA5, 0x3D, 0xFF, 0xA4, 0x02, 0xC3, 0x95, 0x11), + MBEDTLS_BYTES_TO_T_UINT_8(0xD5, 0x10, 0x78, 0xD1, 0x2B, 0xB7, 0xBE, 0x0E), + MBEDTLS_BYTES_TO_T_UINT_8(0x0A, 0xE9, 0x57, 0xF9, 0xE0, 0xD8, 0xFC, 0xBC), + MBEDTLS_BYTES_TO_T_UINT_8(0xF3, 0xC4, 0x01, 0xD6, 0xB4, 0xE7, 0x78, 0xE2), + MBEDTLS_BYTES_TO_T_UINT_8(0x02, 0x6C, 0xB9, 0x13, 0xA4, 0xE8, 0x6D, 0x6F), +}; +static const mbedtls_mpi_uint brainpoolP512r1_T_31_X[] = { + MBEDTLS_BYTES_TO_T_UINT_8(0xE8, 0xB0, 0xC9, 0xCD, 0xBF, 0xA2, 0x1E, 0x63), + MBEDTLS_BYTES_TO_T_UINT_8(0xDD, 0x4F, 0x86, 0x22, 0x9B, 0xEA, 0xE8, 0xBB), + MBEDTLS_BYTES_TO_T_UINT_8(0x50, 0x46, 0xDF, 0x43, 0xB9, 0x82, 0x2D, 0x0A), + MBEDTLS_BYTES_TO_T_UINT_8(0x07, 0x32, 0xF1, 0x4E, 0x95, 0x41, 0xAE, 0x8E), + MBEDTLS_BYTES_TO_T_UINT_8(0x52, 0x93, 0x26, 0xFC, 0xD3, 0x90, 0xDC, 0xEB), + MBEDTLS_BYTES_TO_T_UINT_8(0x04, 0x05, 0x45, 0xCA, 0xF9, 0x5A, 0x89, 0x93), + MBEDTLS_BYTES_TO_T_UINT_8(0xC5, 0x82, 0x63, 0x4E, 0x55, 0x1D, 0x3A, 0x08), + MBEDTLS_BYTES_TO_T_UINT_8(0x7C, 0x69, 0x52, 0x49, 0xE9, 0xED, 0x57, 0x34), +}; +static const mbedtls_mpi_uint brainpoolP512r1_T_31_Y[] = { + MBEDTLS_BYTES_TO_T_UINT_8(0x70, 0x64, 0xE9, 0xAC, 0x4C, 0x4A, 0xEA, 0x25), + MBEDTLS_BYTES_TO_T_UINT_8(0xE9, 0xE9, 0x0B, 0x99, 0xE7, 0xF9, 0xA9, 0x2C), + MBEDTLS_BYTES_TO_T_UINT_8(0x24, 0x0C, 0xC1, 0xF4, 0x8D, 0x07, 0xB6, 0xB1), + MBEDTLS_BYTES_TO_T_UINT_8(0xAD, 0x68, 0xFA, 0x35, 0xE4, 0x9E, 0xAE, 0xD9), + MBEDTLS_BYTES_TO_T_UINT_8(0xF0, 0x2D, 0x1A, 0x13, 0x8E, 0x02, 0xE2, 0x63), + MBEDTLS_BYTES_TO_T_UINT_8(0x27, 0x38, 0x28, 0x86, 0x46, 0x7B, 0x3A, 0xE1), + MBEDTLS_BYTES_TO_T_UINT_8(0x3F, 0x4C, 0x64, 0x59, 0x0A, 0xF9, 0x02, 0xC4), + MBEDTLS_BYTES_TO_T_UINT_8(0x41, 0x4F, 0x23, 0xA2, 0xC3, 0xD5, 0xEF, 0x42), +}; +static const mbedtls_ecp_point brainpoolP512r1_T[32] = { + ECP_POINT_INIT_XY_Z1(brainpoolP512r1_T_0_X, brainpoolP512r1_T_0_Y), + ECP_POINT_INIT_XY_Z0(brainpoolP512r1_T_1_X, brainpoolP512r1_T_1_Y), + ECP_POINT_INIT_XY_Z0(brainpoolP512r1_T_2_X, brainpoolP512r1_T_2_Y), + ECP_POINT_INIT_XY_Z0(brainpoolP512r1_T_3_X, brainpoolP512r1_T_3_Y), + ECP_POINT_INIT_XY_Z0(brainpoolP512r1_T_4_X, brainpoolP512r1_T_4_Y), + ECP_POINT_INIT_XY_Z0(brainpoolP512r1_T_5_X, brainpoolP512r1_T_5_Y), + ECP_POINT_INIT_XY_Z0(brainpoolP512r1_T_6_X, brainpoolP512r1_T_6_Y), + ECP_POINT_INIT_XY_Z0(brainpoolP512r1_T_7_X, brainpoolP512r1_T_7_Y), + ECP_POINT_INIT_XY_Z0(brainpoolP512r1_T_8_X, brainpoolP512r1_T_8_Y), + ECP_POINT_INIT_XY_Z0(brainpoolP512r1_T_9_X, brainpoolP512r1_T_9_Y), + ECP_POINT_INIT_XY_Z0(brainpoolP512r1_T_10_X, brainpoolP512r1_T_10_Y), + ECP_POINT_INIT_XY_Z0(brainpoolP512r1_T_11_X, brainpoolP512r1_T_11_Y), + ECP_POINT_INIT_XY_Z0(brainpoolP512r1_T_12_X, brainpoolP512r1_T_12_Y), + ECP_POINT_INIT_XY_Z0(brainpoolP512r1_T_13_X, brainpoolP512r1_T_13_Y), + ECP_POINT_INIT_XY_Z0(brainpoolP512r1_T_14_X, brainpoolP512r1_T_14_Y), + ECP_POINT_INIT_XY_Z0(brainpoolP512r1_T_15_X, brainpoolP512r1_T_15_Y), + ECP_POINT_INIT_XY_Z0(brainpoolP512r1_T_16_X, brainpoolP512r1_T_16_Y), + ECP_POINT_INIT_XY_Z0(brainpoolP512r1_T_17_X, brainpoolP512r1_T_17_Y), + ECP_POINT_INIT_XY_Z0(brainpoolP512r1_T_18_X, brainpoolP512r1_T_18_Y), + ECP_POINT_INIT_XY_Z0(brainpoolP512r1_T_19_X, brainpoolP512r1_T_19_Y), + ECP_POINT_INIT_XY_Z0(brainpoolP512r1_T_20_X, brainpoolP512r1_T_20_Y), + ECP_POINT_INIT_XY_Z0(brainpoolP512r1_T_21_X, brainpoolP512r1_T_21_Y), + ECP_POINT_INIT_XY_Z0(brainpoolP512r1_T_22_X, brainpoolP512r1_T_22_Y), + ECP_POINT_INIT_XY_Z0(brainpoolP512r1_T_23_X, brainpoolP512r1_T_23_Y), + ECP_POINT_INIT_XY_Z0(brainpoolP512r1_T_24_X, brainpoolP512r1_T_24_Y), + ECP_POINT_INIT_XY_Z0(brainpoolP512r1_T_25_X, brainpoolP512r1_T_25_Y), + ECP_POINT_INIT_XY_Z0(brainpoolP512r1_T_26_X, brainpoolP512r1_T_26_Y), + ECP_POINT_INIT_XY_Z0(brainpoolP512r1_T_27_X, brainpoolP512r1_T_27_Y), + ECP_POINT_INIT_XY_Z0(brainpoolP512r1_T_28_X, brainpoolP512r1_T_28_Y), + ECP_POINT_INIT_XY_Z0(brainpoolP512r1_T_29_X, brainpoolP512r1_T_29_Y), + ECP_POINT_INIT_XY_Z0(brainpoolP512r1_T_30_X, brainpoolP512r1_T_30_Y), + ECP_POINT_INIT_XY_Z0(brainpoolP512r1_T_31_X, brainpoolP512r1_T_31_Y), +}; +#else +#define brainpoolP512r1_T NULL #endif +#endif /* MBEDTLS_ECP_DP_BP512R1_ENABLED */ #if defined(ECP_LOAD_GROUP) /* @@ -538,7 +4494,7 @@ static const mbedtls_mpi_uint brainpoolP512r1_n[] = { static inline void ecp_mpi_load(mbedtls_mpi *X, const mbedtls_mpi_uint *p, size_t len) { X->s = 1; - X->n = len / sizeof(mbedtls_mpi_uint); + X->n = (unsigned short) (len / sizeof(mbedtls_mpi_uint)); X->p = (mbedtls_mpi_uint *) p; } @@ -547,10 +4503,9 @@ static inline void ecp_mpi_load(mbedtls_mpi *X, const mbedtls_mpi_uint *p, size_ */ static inline void ecp_mpi_set1(mbedtls_mpi *X) { - static mbedtls_mpi_uint one[] = { 1 }; X->s = 1; X->n = 1; - X->p = one; + X->p = (mbedtls_mpi_uint *) mpi_one; /* X->p will not be modified so the cast is safe */ } /* @@ -562,7 +4517,8 @@ static int ecp_group_load(mbedtls_ecp_group *grp, const mbedtls_mpi_uint *b, size_t blen, const mbedtls_mpi_uint *gx, size_t gxlen, const mbedtls_mpi_uint *gy, size_t gylen, - const mbedtls_mpi_uint *n, size_t nlen) + const mbedtls_mpi_uint *n, size_t nlen, + const mbedtls_ecp_point *T) { ecp_mpi_load(&grp->P, p, plen); if (a != NULL) { @@ -580,6 +4536,12 @@ static int ecp_group_load(mbedtls_ecp_group *grp, grp->h = 1; + grp->T = (mbedtls_ecp_point *) T; + /* + * Set T_size to 0 to prevent T free by mbedtls_ecp_group_free. + */ + grp->T_size = 0; + return 0; } #endif /* ECP_LOAD_GROUP */ @@ -631,7 +4593,9 @@ static int ecp_mod_p256k1(mbedtls_mpi *); G ## _b, sizeof(G ## _b), \ G ## _gx, sizeof(G ## _gx), \ G ## _gy, sizeof(G ## _gy), \ - G ## _n, sizeof(G ## _n)) + G ## _n, sizeof(G ## _n), \ + G ## _T \ + ) #define LOAD_GROUP(G) ecp_group_load(grp, \ G ## _p, sizeof(G ## _p), \ @@ -639,7 +4603,9 @@ static int ecp_mod_p256k1(mbedtls_mpi *); G ## _b, sizeof(G ## _b), \ G ## _gx, sizeof(G ## _gx), \ G ## _gy, sizeof(G ## _gy), \ - G ## _n, sizeof(G ## _n)) + G ## _n, sizeof(G ## _n), \ + G ## _T \ + ) #endif /* ECP_LOAD_GROUP */ #if defined(MBEDTLS_ECP_DP_CURVE25519_ENABLED) @@ -750,7 +4716,6 @@ static int ecp_use_curve448(mbedtls_ecp_group *grp) */ int mbedtls_ecp_group_load(mbedtls_ecp_group *grp, mbedtls_ecp_group_id id) { - ECP_VALIDATE_RET(grp != NULL); mbedtls_ecp_group_free(grp); mbedtls_ecp_group_init(grp); @@ -982,9 +4947,6 @@ static inline void sub32(uint32_t *dst, uint32_t src, signed char *carry) #define ADD(j) add32(&cur, A(j), &c); #define SUB(j) sub32(&cur, A(j), &c); -#define ciL (sizeof(mbedtls_mpi_uint)) /* chars in limb */ -#define biL (ciL << 3) /* bits in limb */ - /* * Helpers for the main 'loop' */ @@ -1016,8 +4978,7 @@ static inline void sub32(uint32_t *dst, uint32_t src, signed char *carry) * If the result is negative, we get it in the form * c * 2^bits + N, with c negative and N positive shorter than 'bits' */ -MBEDTLS_STATIC_TESTABLE -void mbedtls_ecp_fix_negative(mbedtls_mpi *N, signed char c, size_t bits) +static void mbedtls_ecp_fix_negative(mbedtls_mpi *N, signed char c, size_t bits) { size_t i; @@ -1232,43 +5193,32 @@ static int ecp_mod_p521(mbedtls_mpi *N) /* * Fast quasi-reduction modulo p255 = 2^255 - 19 - * Write N as A0 + 2^255 A1, return A0 + 19 * A1 + * Write N as A0 + 2^256 A1, return A0 + 38 * A1 */ static int ecp_mod_p255(mbedtls_mpi *N) { - int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED; - size_t i; - mbedtls_mpi M; - mbedtls_mpi_uint Mp[P255_WIDTH + 2]; + mbedtls_mpi_uint Mp[P255_WIDTH]; - if (N->n < P255_WIDTH) { + /* Helper references for top part of N */ + mbedtls_mpi_uint * const NT_p = N->p + P255_WIDTH; + const size_t NT_n = N->n - P255_WIDTH; + if (N->n <= P255_WIDTH) { return 0; } - - /* M = A1 */ - M.s = 1; - M.n = N->n - (P255_WIDTH - 1); - if (M.n > P255_WIDTH + 1) { + if (NT_n > P255_WIDTH) { return MBEDTLS_ERR_ECP_BAD_INPUT_DATA; } - M.p = Mp; - memset(Mp, 0, sizeof(Mp)); - memcpy(Mp, N->p + P255_WIDTH - 1, M.n * sizeof(mbedtls_mpi_uint)); - MBEDTLS_MPI_CHK(mbedtls_mpi_shift_r(&M, 255 % (8 * sizeof(mbedtls_mpi_uint)))); - M.n++; /* Make room for multiplication by 19 */ - /* N = A0 */ - MBEDTLS_MPI_CHK(mbedtls_mpi_set_bit(N, 255, 0)); - for (i = P255_WIDTH; i < N->n; i++) { - N->p[i] = 0; - } + /* Split N as N + 2^256 M */ + memcpy(Mp, NT_p, sizeof(mbedtls_mpi_uint) * NT_n); + memset(NT_p, 0, sizeof(mbedtls_mpi_uint) * NT_n); - /* N = A0 + 19 * A1 */ - MBEDTLS_MPI_CHK(mbedtls_mpi_mul_int(&M, &M, 19)); - MBEDTLS_MPI_CHK(mbedtls_mpi_add_abs(N, N, &M)); + /* N = A0 + 38 * A1 */ + mbedtls_mpi_core_mla(N->p, P255_WIDTH + 1, + Mp, NT_n, + 38); -cleanup: - return ret; + return 0; } #endif /* MBEDTLS_ECP_DP_CURVE25519_ENABLED */ @@ -1279,8 +5229,9 @@ static int ecp_mod_p255(mbedtls_mpi *N) /* Number of limbs fully occupied by 2^224 (max), and limbs used by it (min) */ #define DIV_ROUND_UP(X, Y) (((X) + (Y) -1) / (Y)) -#define P224_WIDTH_MIN (28 / sizeof(mbedtls_mpi_uint)) -#define P224_WIDTH_MAX DIV_ROUND_UP(28, sizeof(mbedtls_mpi_uint)) +#define P224_SIZE (224 / 8) +#define P224_WIDTH_MIN (P224_SIZE / sizeof(mbedtls_mpi_uint)) +#define P224_WIDTH_MAX DIV_ROUND_UP(P224_SIZE, sizeof(mbedtls_mpi_uint)) #define P224_UNUSED_BITS ((P224_WIDTH_MAX * sizeof(mbedtls_mpi_uint) * 8) - 224) /* @@ -1360,7 +5311,7 @@ static int ecp_mod_p448(mbedtls_mpi *N) */ #define P_KOBLITZ_MAX (256 / 8 / sizeof(mbedtls_mpi_uint)) // Max limbs in P #define P_KOBLITZ_R (8 / sizeof(mbedtls_mpi_uint)) // Limbs in R -static inline int ecp_mod_koblitz(mbedtls_mpi *N, mbedtls_mpi_uint *Rp, size_t p_limbs, +static inline int ecp_mod_koblitz(mbedtls_mpi *N, const mbedtls_mpi_uint *Rp, size_t p_limbs, size_t adjust, size_t shift, mbedtls_mpi_uint mask) { int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED; @@ -1374,7 +5325,7 @@ static inline int ecp_mod_koblitz(mbedtls_mpi *N, mbedtls_mpi_uint *Rp, size_t p /* Init R */ R.s = 1; - R.p = Rp; + R.p = (mbedtls_mpi_uint *) Rp; /* R.p will not be modified so the cast is safe */ R.n = P_KOBLITZ_R; /* Common setup for M */ @@ -1382,9 +5333,9 @@ static inline int ecp_mod_koblitz(mbedtls_mpi *N, mbedtls_mpi_uint *Rp, size_t p M.p = Mp; /* M = A1 */ - M.n = N->n - (p_limbs - adjust); + M.n = (unsigned short) (N->n - (p_limbs - adjust)); if (M.n > p_limbs + adjust) { - M.n = p_limbs + adjust; + M.n = (unsigned short) (p_limbs + adjust); } memset(Mp, 0, sizeof(Mp)); memcpy(Mp, N->p + p_limbs - adjust, M.n * sizeof(mbedtls_mpi_uint)); @@ -1408,9 +5359,9 @@ static inline int ecp_mod_koblitz(mbedtls_mpi *N, mbedtls_mpi_uint *Rp, size_t p /* Second pass */ /* M = A1 */ - M.n = N->n - (p_limbs - adjust); + M.n = (unsigned short) (N->n - (p_limbs - adjust)); if (M.n > p_limbs + adjust) { - M.n = p_limbs + adjust; + M.n = (unsigned short) (p_limbs + adjust); } memset(Mp, 0, sizeof(Mp)); memcpy(Mp, N->p + p_limbs - adjust, M.n * sizeof(mbedtls_mpi_uint)); @@ -1441,11 +5392,11 @@ static inline int ecp_mod_koblitz(mbedtls_mpi *N, mbedtls_mpi_uint *Rp, size_t p #if defined(MBEDTLS_ECP_DP_SECP192K1_ENABLED) /* * Fast quasi-reduction modulo p192k1 = 2^192 - R, - * with R = 2^32 + 2^12 + 2^8 + 2^7 + 2^6 + 2^3 + 1 = 0x0100001119 + * with R = 2^32 + 2^12 + 2^8 + 2^7 + 2^6 + 2^3 + 1 = 0x01000011C9 */ static int ecp_mod_p192k1(mbedtls_mpi *N) { - static mbedtls_mpi_uint Rp[] = { + static const mbedtls_mpi_uint Rp[] = { MBEDTLS_BYTES_TO_T_UINT_8(0xC9, 0x11, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00) }; @@ -1462,7 +5413,7 @@ static int ecp_mod_p192k1(mbedtls_mpi *N) */ static int ecp_mod_p224k1(mbedtls_mpi *N) { - static mbedtls_mpi_uint Rp[] = { + static const mbedtls_mpi_uint Rp[] = { MBEDTLS_BYTES_TO_T_UINT_8(0x93, 0x1A, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00) }; @@ -1484,7 +5435,7 @@ static int ecp_mod_p224k1(mbedtls_mpi *N) */ static int ecp_mod_p256k1(mbedtls_mpi *N) { - static mbedtls_mpi_uint Rp[] = { + static const mbedtls_mpi_uint Rp[] = { MBEDTLS_BYTES_TO_T_UINT_8(0xD1, 0x03, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00) }; @@ -1493,6 +5444,17 @@ static int ecp_mod_p256k1(mbedtls_mpi *N) } #endif /* MBEDTLS_ECP_DP_SECP256K1_ENABLED */ +#if defined(MBEDTLS_TEST_HOOKS) + +MBEDTLS_STATIC_TESTABLE +mbedtls_ecp_variant mbedtls_ecp_get_variant(void) +{ + return MBEDTLS_ECP_VARIANT_WITH_MPI_STRUCT; +} + +#endif /* MBEDTLS_TEST_HOOKS */ + #endif /* !MBEDTLS_ECP_ALT */ -#endif /* MBEDTLS_ECP_C */ +#endif /* MBEDTLS_ECP_LIGHT */ +#endif /* MBEDTLS_ECP_WITH_MPI_UINT */ diff --git a/vendor/mbedtls/library/ecp_curves_new.c b/vendor/mbedtls/library/ecp_curves_new.c new file mode 100644 index 0000000000..035b23a1b4 --- /dev/null +++ b/vendor/mbedtls/library/ecp_curves_new.c @@ -0,0 +1,6036 @@ +/* + * Elliptic curves over GF(p): curve-specific data and functions + * + * Copyright The Mbed TLS Contributors + * SPDX-License-Identifier: Apache-2.0 OR GPL-2.0-or-later + */ + +#include "common.h" + +#if defined(MBEDTLS_ECP_WITH_MPI_UINT) + +#if defined(MBEDTLS_ECP_LIGHT) + +#include "mbedtls/ecp.h" +#include "mbedtls/platform.h" +#include "mbedtls/platform_util.h" +#include "mbedtls/error.h" + +#include "mbedtls/platform.h" + +#include "constant_time_internal.h" + +#include "bn_mul.h" +#include "bignum_core.h" +#include "ecp_invasive.h" + +#include + +#if !defined(MBEDTLS_ECP_ALT) + +#define ECP_MPI_INIT(_p, _n) { .p = (mbedtls_mpi_uint *) (_p), .s = 1, .n = (_n) } + +#define ECP_MPI_INIT_ARRAY(x) \ + ECP_MPI_INIT(x, sizeof(x) / sizeof(mbedtls_mpi_uint)) + +#define ECP_POINT_INIT_XY_Z0(x, y) { \ + ECP_MPI_INIT_ARRAY(x), ECP_MPI_INIT_ARRAY(y), ECP_MPI_INIT(NULL, 0) } +#define ECP_POINT_INIT_XY_Z1(x, y) { \ + ECP_MPI_INIT_ARRAY(x), ECP_MPI_INIT_ARRAY(y), ECP_MPI_INIT(mpi_one, 1) } + +#if defined(MBEDTLS_ECP_DP_SECP192R1_ENABLED) || \ + defined(MBEDTLS_ECP_DP_SECP224R1_ENABLED) || \ + defined(MBEDTLS_ECP_DP_SECP256R1_ENABLED) || \ + defined(MBEDTLS_ECP_DP_SECP384R1_ENABLED) || \ + defined(MBEDTLS_ECP_DP_SECP521R1_ENABLED) || \ + defined(MBEDTLS_ECP_DP_BP256R1_ENABLED) || \ + defined(MBEDTLS_ECP_DP_BP384R1_ENABLED) || \ + defined(MBEDTLS_ECP_DP_BP512R1_ENABLED) || \ + defined(MBEDTLS_ECP_DP_SECP192K1_ENABLED) || \ + defined(MBEDTLS_ECP_DP_SECP224K1_ENABLED) || \ + defined(MBEDTLS_ECP_DP_SECP256K1_ENABLED) +/* For these curves, we build the group parameters dynamically. */ +#define ECP_LOAD_GROUP +static mbedtls_mpi_uint mpi_one[] = { 1 }; +#endif + +/* + * Note: the constants are in little-endian order + * to be directly usable in MPIs + */ + +/* + * Domain parameters for secp192r1 + */ +#if defined(MBEDTLS_ECP_DP_SECP192R1_ENABLED) +static const mbedtls_mpi_uint secp192r1_p[] = { + MBEDTLS_BYTES_TO_T_UINT_8(0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF), + MBEDTLS_BYTES_TO_T_UINT_8(0xFE, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF), + MBEDTLS_BYTES_TO_T_UINT_8(0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF), +}; +static const mbedtls_mpi_uint secp192r1_b[] = { + MBEDTLS_BYTES_TO_T_UINT_8(0xB1, 0xB9, 0x46, 0xC1, 0xEC, 0xDE, 0xB8, 0xFE), + MBEDTLS_BYTES_TO_T_UINT_8(0x49, 0x30, 0x24, 0x72, 0xAB, 0xE9, 0xA7, 0x0F), + MBEDTLS_BYTES_TO_T_UINT_8(0xE7, 0x80, 0x9C, 0xE5, 0x19, 0x05, 0x21, 0x64), +}; +static const mbedtls_mpi_uint secp192r1_gx[] = { + MBEDTLS_BYTES_TO_T_UINT_8(0x12, 0x10, 0xFF, 0x82, 0xFD, 0x0A, 0xFF, 0xF4), + MBEDTLS_BYTES_TO_T_UINT_8(0x00, 0x88, 0xA1, 0x43, 0xEB, 0x20, 0xBF, 0x7C), + MBEDTLS_BYTES_TO_T_UINT_8(0xF6, 0x90, 0x30, 0xB0, 0x0E, 0xA8, 0x8D, 0x18), +}; +static const mbedtls_mpi_uint secp192r1_gy[] = { + MBEDTLS_BYTES_TO_T_UINT_8(0x11, 0x48, 0x79, 0x1E, 0xA1, 0x77, 0xF9, 0x73), + MBEDTLS_BYTES_TO_T_UINT_8(0xD5, 0xCD, 0x24, 0x6B, 0xED, 0x11, 0x10, 0x63), + MBEDTLS_BYTES_TO_T_UINT_8(0x78, 0xDA, 0xC8, 0xFF, 0x95, 0x2B, 0x19, 0x07), +}; +static const mbedtls_mpi_uint secp192r1_n[] = { + MBEDTLS_BYTES_TO_T_UINT_8(0x31, 0x28, 0xD2, 0xB4, 0xB1, 0xC9, 0x6B, 0x14), + MBEDTLS_BYTES_TO_T_UINT_8(0x36, 0xF8, 0xDE, 0x99, 0xFF, 0xFF, 0xFF, 0xFF), + MBEDTLS_BYTES_TO_T_UINT_8(0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF), +}; +#if MBEDTLS_ECP_FIXED_POINT_OPTIM == 1 +static const mbedtls_mpi_uint secp192r1_T_0_X[] = { + MBEDTLS_BYTES_TO_T_UINT_8(0x12, 0x10, 0xFF, 0x82, 0xFD, 0x0A, 0xFF, 0xF4), + MBEDTLS_BYTES_TO_T_UINT_8(0x00, 0x88, 0xA1, 0x43, 0xEB, 0x20, 0xBF, 0x7C), + MBEDTLS_BYTES_TO_T_UINT_8(0xF6, 0x90, 0x30, 0xB0, 0x0E, 0xA8, 0x8D, 0x18), +}; +static const mbedtls_mpi_uint secp192r1_T_0_Y[] = { + MBEDTLS_BYTES_TO_T_UINT_8(0x11, 0x48, 0x79, 0x1E, 0xA1, 0x77, 0xF9, 0x73), + MBEDTLS_BYTES_TO_T_UINT_8(0xD5, 0xCD, 0x24, 0x6B, 0xED, 0x11, 0x10, 0x63), + MBEDTLS_BYTES_TO_T_UINT_8(0x78, 0xDA, 0xC8, 0xFF, 0x95, 0x2B, 0x19, 0x07), +}; +static const mbedtls_mpi_uint secp192r1_T_1_X[] = { + MBEDTLS_BYTES_TO_T_UINT_8(0x97, 0x9E, 0xE3, 0x60, 0x59, 0xD1, 0xC4, 0xC2), + MBEDTLS_BYTES_TO_T_UINT_8(0x91, 0xBD, 0x22, 0xD7, 0x2D, 0x07, 0xBD, 0xB6), + MBEDTLS_BYTES_TO_T_UINT_8(0x74, 0x2A, 0xCF, 0x33, 0xF0, 0xBE, 0xD1, 0xED), +}; +static const mbedtls_mpi_uint secp192r1_T_1_Y[] = { + MBEDTLS_BYTES_TO_T_UINT_8(0x88, 0x71, 0x4B, 0xA8, 0xED, 0x7E, 0xC9, 0x1A), + MBEDTLS_BYTES_TO_T_UINT_8(0x8E, 0x2A, 0xF6, 0xDF, 0x0E, 0xE8, 0x4C, 0x0F), + MBEDTLS_BYTES_TO_T_UINT_8(0xC5, 0x35, 0xF7, 0x8A, 0xC3, 0xEC, 0xDE, 0x1E), +}; +static const mbedtls_mpi_uint secp192r1_T_2_X[] = { + MBEDTLS_BYTES_TO_T_UINT_8(0x00, 0x67, 0xC2, 0x1D, 0x32, 0x8F, 0x10, 0xFB), + MBEDTLS_BYTES_TO_T_UINT_8(0xBB, 0x2D, 0x17, 0xF3, 0xE4, 0xFE, 0xD8, 0x13), + MBEDTLS_BYTES_TO_T_UINT_8(0x55, 0x45, 0x10, 0x70, 0x2C, 0x3E, 0x52, 0x3E), +}; +static const mbedtls_mpi_uint secp192r1_T_2_Y[] = { + MBEDTLS_BYTES_TO_T_UINT_8(0x61, 0xF1, 0x04, 0x5D, 0xEE, 0xD4, 0x56, 0xE6), + MBEDTLS_BYTES_TO_T_UINT_8(0x78, 0xB7, 0x38, 0x27, 0x61, 0xAA, 0x81, 0x87), + MBEDTLS_BYTES_TO_T_UINT_8(0x71, 0x37, 0xD7, 0x0E, 0x29, 0x0E, 0x11, 0x14), +}; +static const mbedtls_mpi_uint secp192r1_T_3_X[] = { + MBEDTLS_BYTES_TO_T_UINT_8(0x1E, 0x35, 0x52, 0xC6, 0x31, 0xB7, 0x27, 0xF5), + MBEDTLS_BYTES_TO_T_UINT_8(0x3D, 0xD4, 0x15, 0x98, 0x0F, 0xE7, 0xF3, 0x6A), + MBEDTLS_BYTES_TO_T_UINT_8(0xD3, 0x31, 0x70, 0x35, 0x09, 0xA0, 0x2B, 0xC2), +}; +static const mbedtls_mpi_uint secp192r1_T_3_Y[] = { + MBEDTLS_BYTES_TO_T_UINT_8(0x21, 0x75, 0xA7, 0x4C, 0x88, 0xCF, 0x5B, 0xE4), + MBEDTLS_BYTES_TO_T_UINT_8(0x17, 0x17, 0x48, 0x8D, 0xF2, 0xF0, 0x86, 0xED), + MBEDTLS_BYTES_TO_T_UINT_8(0x49, 0xCF, 0xFE, 0x6B, 0xB0, 0xA5, 0x06, 0xAB), +}; +static const mbedtls_mpi_uint secp192r1_T_4_X[] = { + MBEDTLS_BYTES_TO_T_UINT_8(0x18, 0x6A, 0xDC, 0x9A, 0x6D, 0x7B, 0x47, 0x2E), + MBEDTLS_BYTES_TO_T_UINT_8(0x12, 0xFC, 0x51, 0x12, 0x62, 0x66, 0x0B, 0x59), + MBEDTLS_BYTES_TO_T_UINT_8(0xCD, 0x40, 0x93, 0xA0, 0xB5, 0x5A, 0x58, 0xD7), +}; +static const mbedtls_mpi_uint secp192r1_T_4_Y[] = { + MBEDTLS_BYTES_TO_T_UINT_8(0xEF, 0xCB, 0xAF, 0xDC, 0x0B, 0xA1, 0x26, 0xFB), + MBEDTLS_BYTES_TO_T_UINT_8(0xDA, 0x36, 0x9D, 0xA3, 0xD7, 0x3B, 0xAD, 0x39), + MBEDTLS_BYTES_TO_T_UINT_8(0xB4, 0x3B, 0x05, 0x9A, 0xA8, 0xAA, 0x69, 0xB2), +}; +static const mbedtls_mpi_uint secp192r1_T_5_X[] = { + MBEDTLS_BYTES_TO_T_UINT_8(0x6D, 0xD9, 0xD1, 0x4D, 0x4A, 0x6E, 0x96, 0x1E), + MBEDTLS_BYTES_TO_T_UINT_8(0x17, 0x66, 0x32, 0x39, 0xC6, 0x57, 0x7D, 0xE6), + MBEDTLS_BYTES_TO_T_UINT_8(0x92, 0xA0, 0x36, 0xC2, 0x45, 0xF9, 0x00, 0x62), +}; +static const mbedtls_mpi_uint secp192r1_T_5_Y[] = { + MBEDTLS_BYTES_TO_T_UINT_8(0xB4, 0xEF, 0x59, 0x46, 0xDC, 0x60, 0xD9, 0x8F), + MBEDTLS_BYTES_TO_T_UINT_8(0x24, 0xB0, 0xE9, 0x41, 0xA4, 0x87, 0x76, 0x89), + MBEDTLS_BYTES_TO_T_UINT_8(0x13, 0xD4, 0x0E, 0xB2, 0xFA, 0x16, 0x56, 0xDC), +}; +static const mbedtls_mpi_uint secp192r1_T_6_X[] = { + MBEDTLS_BYTES_TO_T_UINT_8(0x0A, 0x62, 0xD2, 0xB1, 0x34, 0xB2, 0xF1, 0x06), + MBEDTLS_BYTES_TO_T_UINT_8(0xB2, 0xED, 0x55, 0xC5, 0x47, 0xB5, 0x07, 0x15), + MBEDTLS_BYTES_TO_T_UINT_8(0x17, 0xF6, 0x2F, 0x94, 0xC3, 0xDD, 0x54, 0x2F), +}; +static const mbedtls_mpi_uint secp192r1_T_6_Y[] = { + MBEDTLS_BYTES_TO_T_UINT_8(0xFD, 0xA6, 0xD4, 0x8C, 0xA9, 0xCE, 0x4D, 0x2E), + MBEDTLS_BYTES_TO_T_UINT_8(0xB9, 0x4B, 0x46, 0xCC, 0xB2, 0x55, 0xC8, 0xB2), + MBEDTLS_BYTES_TO_T_UINT_8(0x3A, 0xAE, 0x31, 0xED, 0x89, 0x65, 0x59, 0x55), +}; +static const mbedtls_mpi_uint secp192r1_T_7_X[] = { + MBEDTLS_BYTES_TO_T_UINT_8(0xCC, 0x0A, 0xD1, 0x1A, 0xC5, 0xF6, 0xEA, 0x43), + MBEDTLS_BYTES_TO_T_UINT_8(0x0C, 0xFC, 0x0C, 0x1A, 0xFB, 0xA0, 0xC8, 0x70), + MBEDTLS_BYTES_TO_T_UINT_8(0xEA, 0xFD, 0x53, 0x6F, 0x6D, 0xBF, 0xBA, 0xAF), +}; +static const mbedtls_mpi_uint secp192r1_T_7_Y[] = { + MBEDTLS_BYTES_TO_T_UINT_8(0x2D, 0xB0, 0x7D, 0x83, 0x96, 0xE3, 0xCB, 0x9D), + MBEDTLS_BYTES_TO_T_UINT_8(0x6F, 0x6E, 0x55, 0x2C, 0x20, 0x53, 0x2F, 0x46), + MBEDTLS_BYTES_TO_T_UINT_8(0xA6, 0x66, 0x00, 0x17, 0x08, 0xFE, 0xAC, 0x31), +}; +static const mbedtls_mpi_uint secp192r1_T_8_X[] = { + MBEDTLS_BYTES_TO_T_UINT_8(0x09, 0x12, 0x97, 0x3A, 0xC7, 0x57, 0x45, 0xCD), + MBEDTLS_BYTES_TO_T_UINT_8(0x38, 0x25, 0x99, 0x00, 0xF6, 0x97, 0xB4, 0x64), + MBEDTLS_BYTES_TO_T_UINT_8(0x9B, 0x74, 0xE6, 0xE6, 0xA3, 0xDF, 0x9C, 0xCC), +}; +static const mbedtls_mpi_uint secp192r1_T_8_Y[] = { + MBEDTLS_BYTES_TO_T_UINT_8(0x32, 0xF4, 0x76, 0xD5, 0x5F, 0x2A, 0xFD, 0x85), + MBEDTLS_BYTES_TO_T_UINT_8(0x62, 0x80, 0x7E, 0x3E, 0xE5, 0xE8, 0xD6, 0x63), + MBEDTLS_BYTES_TO_T_UINT_8(0xE2, 0xAD, 0x1E, 0x70, 0x79, 0x3E, 0x3D, 0x83), +}; +static const mbedtls_mpi_uint secp192r1_T_9_X[] = { + MBEDTLS_BYTES_TO_T_UINT_8(0x8E, 0x15, 0xBB, 0xB3, 0x42, 0x6A, 0xA1, 0x7C), + MBEDTLS_BYTES_TO_T_UINT_8(0x9B, 0x58, 0xCB, 0x43, 0x25, 0x00, 0x14, 0x68), + MBEDTLS_BYTES_TO_T_UINT_8(0x06, 0x4E, 0x93, 0x11, 0xE0, 0x32, 0x54, 0x98), +}; +static const mbedtls_mpi_uint secp192r1_T_9_Y[] = { + MBEDTLS_BYTES_TO_T_UINT_8(0xA7, 0x52, 0xA2, 0xB4, 0x57, 0x32, 0xB9, 0x11), + MBEDTLS_BYTES_TO_T_UINT_8(0x7D, 0x43, 0xA1, 0xB1, 0xFB, 0x01, 0xE1, 0xE7), + MBEDTLS_BYTES_TO_T_UINT_8(0xA6, 0xFB, 0x5A, 0x11, 0xB8, 0xC2, 0x03, 0xE5), +}; +static const mbedtls_mpi_uint secp192r1_T_10_X[] = { + MBEDTLS_BYTES_TO_T_UINT_8(0x1C, 0x2B, 0x71, 0x26, 0x4E, 0x7C, 0xC5, 0x32), + MBEDTLS_BYTES_TO_T_UINT_8(0x1F, 0xF5, 0xD3, 0xA8, 0xE4, 0x95, 0x48, 0x65), + MBEDTLS_BYTES_TO_T_UINT_8(0x55, 0xAE, 0xD9, 0x5D, 0x9F, 0x6A, 0x22, 0xAD), +}; +static const mbedtls_mpi_uint secp192r1_T_10_Y[] = { + MBEDTLS_BYTES_TO_T_UINT_8(0xD9, 0xCC, 0xA3, 0x4D, 0xA0, 0x1C, 0x34, 0xEF), + MBEDTLS_BYTES_TO_T_UINT_8(0xA3, 0x3C, 0x62, 0xF8, 0x5E, 0xA6, 0x58, 0x7D), + MBEDTLS_BYTES_TO_T_UINT_8(0x6D, 0x6E, 0x66, 0x8A, 0x3D, 0x17, 0xFF, 0x0F), +}; +static const mbedtls_mpi_uint secp192r1_T_11_X[] = { + MBEDTLS_BYTES_TO_T_UINT_8(0xF7, 0xCD, 0xA8, 0xDD, 0xD1, 0x20, 0x5C, 0xEA), + MBEDTLS_BYTES_TO_T_UINT_8(0xBF, 0xFE, 0x17, 0xE2, 0xCF, 0xEA, 0x63, 0xDE), + MBEDTLS_BYTES_TO_T_UINT_8(0x74, 0x51, 0xC9, 0x16, 0xDE, 0xB4, 0xB2, 0xDD), +}; +static const mbedtls_mpi_uint secp192r1_T_11_Y[] = { + MBEDTLS_BYTES_TO_T_UINT_8(0x59, 0xBE, 0x12, 0xD7, 0xA3, 0x0A, 0x50, 0x33), + MBEDTLS_BYTES_TO_T_UINT_8(0x53, 0x87, 0xC5, 0x8A, 0x76, 0x57, 0x07, 0x60), + MBEDTLS_BYTES_TO_T_UINT_8(0xE5, 0x1F, 0xC6, 0x1B, 0x66, 0xC4, 0x3D, 0x8A), +}; +static const mbedtls_mpi_uint secp192r1_T_12_X[] = { + MBEDTLS_BYTES_TO_T_UINT_8(0x28, 0xA4, 0x85, 0x13, 0x8F, 0xA7, 0x35, 0x19), + MBEDTLS_BYTES_TO_T_UINT_8(0x58, 0x0D, 0xFD, 0xFF, 0x1B, 0xD1, 0xD6, 0xEF), + MBEDTLS_BYTES_TO_T_UINT_8(0xBA, 0x7A, 0xD0, 0xC3, 0xB4, 0xEF, 0x39, 0x66), +}; +static const mbedtls_mpi_uint secp192r1_T_12_Y[] = { + MBEDTLS_BYTES_TO_T_UINT_8(0x3A, 0xFE, 0xA5, 0x9C, 0x34, 0x30, 0x49, 0x40), + MBEDTLS_BYTES_TO_T_UINT_8(0xDE, 0xC5, 0x39, 0x26, 0x06, 0xE3, 0x01, 0x17), + MBEDTLS_BYTES_TO_T_UINT_8(0xE2, 0x2B, 0x66, 0xFC, 0x95, 0x5F, 0x35, 0xF7), +}; +static const mbedtls_mpi_uint secp192r1_T_13_X[] = { + MBEDTLS_BYTES_TO_T_UINT_8(0x58, 0xCF, 0x54, 0x63, 0x99, 0x57, 0x05, 0x45), + MBEDTLS_BYTES_TO_T_UINT_8(0x71, 0x6F, 0x00, 0x5F, 0x65, 0x08, 0x47, 0x98), + MBEDTLS_BYTES_TO_T_UINT_8(0x62, 0x2A, 0x90, 0x6D, 0x67, 0xC6, 0xBC, 0x45), +}; +static const mbedtls_mpi_uint secp192r1_T_13_Y[] = { + MBEDTLS_BYTES_TO_T_UINT_8(0x8A, 0x4D, 0x88, 0x0A, 0x35, 0x9E, 0x33, 0x9C), + MBEDTLS_BYTES_TO_T_UINT_8(0x7C, 0x17, 0x0C, 0xF8, 0xE1, 0x7A, 0x49, 0x02), + MBEDTLS_BYTES_TO_T_UINT_8(0xA4, 0x44, 0x06, 0x8F, 0x0B, 0x70, 0x2F, 0x71), +}; +static const mbedtls_mpi_uint secp192r1_T_14_X[] = { + MBEDTLS_BYTES_TO_T_UINT_8(0x85, 0x4B, 0xCB, 0xF9, 0x8E, 0x6A, 0xDA, 0x1B), + MBEDTLS_BYTES_TO_T_UINT_8(0x29, 0x43, 0xA1, 0x3F, 0xCE, 0x17, 0xD2, 0x32), + MBEDTLS_BYTES_TO_T_UINT_8(0x5D, 0x0D, 0xD2, 0x6C, 0x82, 0x37, 0xE5, 0xFC), +}; +static const mbedtls_mpi_uint secp192r1_T_14_Y[] = { + MBEDTLS_BYTES_TO_T_UINT_8(0x4A, 0x3C, 0xF4, 0x92, 0xB4, 0x8A, 0x95, 0x85), + MBEDTLS_BYTES_TO_T_UINT_8(0x85, 0x96, 0xF1, 0x0A, 0x34, 0x2F, 0x74, 0x7E), + MBEDTLS_BYTES_TO_T_UINT_8(0x7B, 0xA1, 0xAA, 0xBA, 0x86, 0x77, 0x4F, 0xA2), +}; +static const mbedtls_mpi_uint secp192r1_T_15_X[] = { + MBEDTLS_BYTES_TO_T_UINT_8(0xE5, 0x7F, 0xEF, 0x60, 0x50, 0x80, 0xD7, 0xD4), + MBEDTLS_BYTES_TO_T_UINT_8(0x31, 0xAC, 0xC9, 0xFE, 0xEC, 0x0A, 0x1A, 0x9F), + MBEDTLS_BYTES_TO_T_UINT_8(0x6B, 0x2F, 0xBE, 0x91, 0xD7, 0xB7, 0x38, 0x48), +}; +static const mbedtls_mpi_uint secp192r1_T_15_Y[] = { + MBEDTLS_BYTES_TO_T_UINT_8(0xB1, 0xAE, 0x85, 0x98, 0xFE, 0x05, 0x7F, 0x9F), + MBEDTLS_BYTES_TO_T_UINT_8(0x91, 0xBE, 0xFD, 0x11, 0x31, 0x3D, 0x14, 0x13), + MBEDTLS_BYTES_TO_T_UINT_8(0x59, 0x75, 0xE8, 0x30, 0x01, 0xCB, 0x9B, 0x1C), +}; +static const mbedtls_ecp_point secp192r1_T[16] = { + ECP_POINT_INIT_XY_Z1(secp192r1_T_0_X, secp192r1_T_0_Y), + ECP_POINT_INIT_XY_Z0(secp192r1_T_1_X, secp192r1_T_1_Y), + ECP_POINT_INIT_XY_Z0(secp192r1_T_2_X, secp192r1_T_2_Y), + ECP_POINT_INIT_XY_Z0(secp192r1_T_3_X, secp192r1_T_3_Y), + ECP_POINT_INIT_XY_Z0(secp192r1_T_4_X, secp192r1_T_4_Y), + ECP_POINT_INIT_XY_Z0(secp192r1_T_5_X, secp192r1_T_5_Y), + ECP_POINT_INIT_XY_Z0(secp192r1_T_6_X, secp192r1_T_6_Y), + ECP_POINT_INIT_XY_Z0(secp192r1_T_7_X, secp192r1_T_7_Y), + ECP_POINT_INIT_XY_Z0(secp192r1_T_8_X, secp192r1_T_8_Y), + ECP_POINT_INIT_XY_Z0(secp192r1_T_9_X, secp192r1_T_9_Y), + ECP_POINT_INIT_XY_Z0(secp192r1_T_10_X, secp192r1_T_10_Y), + ECP_POINT_INIT_XY_Z0(secp192r1_T_11_X, secp192r1_T_11_Y), + ECP_POINT_INIT_XY_Z0(secp192r1_T_12_X, secp192r1_T_12_Y), + ECP_POINT_INIT_XY_Z0(secp192r1_T_13_X, secp192r1_T_13_Y), + ECP_POINT_INIT_XY_Z0(secp192r1_T_14_X, secp192r1_T_14_Y), + ECP_POINT_INIT_XY_Z0(secp192r1_T_15_X, secp192r1_T_15_Y), +}; +#else +#define secp192r1_T NULL +#endif +#endif /* MBEDTLS_ECP_DP_SECP192R1_ENABLED */ + +/* + * Domain parameters for secp224r1 + */ +#if defined(MBEDTLS_ECP_DP_SECP224R1_ENABLED) +static const mbedtls_mpi_uint secp224r1_p[] = { + MBEDTLS_BYTES_TO_T_UINT_8(0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00), + MBEDTLS_BYTES_TO_T_UINT_8(0x00, 0x00, 0x00, 0x00, 0xFF, 0xFF, 0xFF, 0xFF), + MBEDTLS_BYTES_TO_T_UINT_8(0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF), + MBEDTLS_BYTES_TO_T_UINT_8(0xFF, 0xFF, 0xFF, 0xFF, 0x00, 0x00, 0x00, 0x00), +}; +static const mbedtls_mpi_uint secp224r1_b[] = { + MBEDTLS_BYTES_TO_T_UINT_8(0xB4, 0xFF, 0x55, 0x23, 0x43, 0x39, 0x0B, 0x27), + MBEDTLS_BYTES_TO_T_UINT_8(0xBA, 0xD8, 0xBF, 0xD7, 0xB7, 0xB0, 0x44, 0x50), + MBEDTLS_BYTES_TO_T_UINT_8(0x56, 0x32, 0x41, 0xF5, 0xAB, 0xB3, 0x04, 0x0C), + MBEDTLS_BYTES_TO_T_UINT_4(0x85, 0x0A, 0x05, 0xB4), +}; +static const mbedtls_mpi_uint secp224r1_gx[] = { + MBEDTLS_BYTES_TO_T_UINT_8(0x21, 0x1D, 0x5C, 0x11, 0xD6, 0x80, 0x32, 0x34), + MBEDTLS_BYTES_TO_T_UINT_8(0x22, 0x11, 0xC2, 0x56, 0xD3, 0xC1, 0x03, 0x4A), + MBEDTLS_BYTES_TO_T_UINT_8(0xB9, 0x90, 0x13, 0x32, 0x7F, 0xBF, 0xB4, 0x6B), + MBEDTLS_BYTES_TO_T_UINT_4(0xBD, 0x0C, 0x0E, 0xB7), +}; +static const mbedtls_mpi_uint secp224r1_gy[] = { + MBEDTLS_BYTES_TO_T_UINT_8(0x34, 0x7E, 0x00, 0x85, 0x99, 0x81, 0xD5, 0x44), + MBEDTLS_BYTES_TO_T_UINT_8(0x64, 0x47, 0x07, 0x5A, 0xA0, 0x75, 0x43, 0xCD), + MBEDTLS_BYTES_TO_T_UINT_8(0xE6, 0xDF, 0x22, 0x4C, 0xFB, 0x23, 0xF7, 0xB5), + MBEDTLS_BYTES_TO_T_UINT_4(0x88, 0x63, 0x37, 0xBD), +}; +static const mbedtls_mpi_uint secp224r1_n[] = { + MBEDTLS_BYTES_TO_T_UINT_8(0x3D, 0x2A, 0x5C, 0x5C, 0x45, 0x29, 0xDD, 0x13), + MBEDTLS_BYTES_TO_T_UINT_8(0x3E, 0xF0, 0xB8, 0xE0, 0xA2, 0x16, 0xFF, 0xFF), + MBEDTLS_BYTES_TO_T_UINT_8(0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF), + MBEDTLS_BYTES_TO_T_UINT_4(0xFF, 0xFF, 0xFF, 0xFF), +}; +#if MBEDTLS_ECP_FIXED_POINT_OPTIM == 1 +static const mbedtls_mpi_uint secp224r1_T_0_X[] = { + MBEDTLS_BYTES_TO_T_UINT_8(0x21, 0x1D, 0x5C, 0x11, 0xD6, 0x80, 0x32, 0x34), + MBEDTLS_BYTES_TO_T_UINT_8(0x22, 0x11, 0xC2, 0x56, 0xD3, 0xC1, 0x03, 0x4A), + MBEDTLS_BYTES_TO_T_UINT_8(0xB9, 0x90, 0x13, 0x32, 0x7F, 0xBF, 0xB4, 0x6B), + MBEDTLS_BYTES_TO_T_UINT_8(0xBD, 0x0C, 0x0E, 0xB7, 0x00, 0x00, 0x00, 0x00), +}; +static const mbedtls_mpi_uint secp224r1_T_0_Y[] = { + MBEDTLS_BYTES_TO_T_UINT_8(0x34, 0x7E, 0x00, 0x85, 0x99, 0x81, 0xD5, 0x44), + MBEDTLS_BYTES_TO_T_UINT_8(0x64, 0x47, 0x07, 0x5A, 0xA0, 0x75, 0x43, 0xCD), + MBEDTLS_BYTES_TO_T_UINT_8(0xE6, 0xDF, 0x22, 0x4C, 0xFB, 0x23, 0xF7, 0xB5), + MBEDTLS_BYTES_TO_T_UINT_8(0x88, 0x63, 0x37, 0xBD, 0x00, 0x00, 0x00, 0x00), +}; +static const mbedtls_mpi_uint secp224r1_T_1_X[] = { + MBEDTLS_BYTES_TO_T_UINT_8(0xE0, 0xF9, 0xB8, 0xD0, 0x3D, 0xD2, 0xD3, 0xFA), + MBEDTLS_BYTES_TO_T_UINT_8(0x1E, 0xFD, 0x99, 0x26, 0x19, 0xFE, 0x13, 0x6E), + MBEDTLS_BYTES_TO_T_UINT_8(0x1C, 0x0E, 0x4C, 0x48, 0x7C, 0xA2, 0x17, 0x01), + MBEDTLS_BYTES_TO_T_UINT_8(0x3D, 0xA3, 0x13, 0x57, 0x00, 0x00, 0x00, 0x00), +}; +static const mbedtls_mpi_uint secp224r1_T_1_Y[] = { + MBEDTLS_BYTES_TO_T_UINT_8(0x9F, 0x16, 0x5C, 0x8F, 0xAA, 0xED, 0x0F, 0x58), + MBEDTLS_BYTES_TO_T_UINT_8(0xBF, 0xC5, 0x43, 0x34, 0x93, 0x05, 0x2A, 0x4C), + MBEDTLS_BYTES_TO_T_UINT_8(0xE4, 0xE3, 0x6C, 0xCA, 0xC6, 0x14, 0xC2, 0x25), + MBEDTLS_BYTES_TO_T_UINT_8(0xD3, 0x43, 0x6C, 0xD7, 0x00, 0x00, 0x00, 0x00), +}; +static const mbedtls_mpi_uint secp224r1_T_2_X[] = { + MBEDTLS_BYTES_TO_T_UINT_8(0xC3, 0x5A, 0x98, 0x1E, 0xC8, 0xA5, 0x42, 0xA3), + MBEDTLS_BYTES_TO_T_UINT_8(0x98, 0x49, 0x56, 0x78, 0xF8, 0xEF, 0xED, 0x65), + MBEDTLS_BYTES_TO_T_UINT_8(0x1B, 0xBB, 0x64, 0xB6, 0x4C, 0x54, 0x5F, 0xD1), + MBEDTLS_BYTES_TO_T_UINT_8(0x2F, 0x0C, 0x33, 0xCC, 0x00, 0x00, 0x00, 0x00), +}; +static const mbedtls_mpi_uint secp224r1_T_2_Y[] = { + MBEDTLS_BYTES_TO_T_UINT_8(0xFA, 0x79, 0xCB, 0x2E, 0x08, 0xFF, 0xD8, 0xE6), + MBEDTLS_BYTES_TO_T_UINT_8(0x2E, 0x1F, 0xD4, 0xD7, 0x57, 0xE9, 0x39, 0x45), + MBEDTLS_BYTES_TO_T_UINT_8(0xD8, 0xD6, 0x3B, 0x0A, 0x1C, 0x87, 0xB7, 0x6A), + MBEDTLS_BYTES_TO_T_UINT_8(0xEB, 0x30, 0xD8, 0x05, 0x00, 0x00, 0x00, 0x00), +}; +static const mbedtls_mpi_uint secp224r1_T_3_X[] = { + MBEDTLS_BYTES_TO_T_UINT_8(0xAD, 0x79, 0x74, 0x9A, 0xE6, 0xBB, 0xC2, 0xC2), + MBEDTLS_BYTES_TO_T_UINT_8(0xB4, 0x5B, 0xA6, 0x67, 0xC1, 0x91, 0xE7, 0x64), + MBEDTLS_BYTES_TO_T_UINT_8(0xF0, 0xDF, 0x38, 0x82, 0x19, 0x2C, 0x4C, 0xCA), + MBEDTLS_BYTES_TO_T_UINT_8(0xD1, 0x2E, 0x39, 0xC5, 0x00, 0x00, 0x00, 0x00), +}; +static const mbedtls_mpi_uint secp224r1_T_3_Y[] = { + MBEDTLS_BYTES_TO_T_UINT_8(0x99, 0x36, 0x78, 0x4E, 0xAE, 0x5B, 0x02, 0x76), + MBEDTLS_BYTES_TO_T_UINT_8(0x14, 0xF6, 0x8B, 0xF8, 0xF4, 0x92, 0x6B, 0x42), + MBEDTLS_BYTES_TO_T_UINT_8(0xBA, 0x4D, 0x71, 0x35, 0xE7, 0x0C, 0x2C, 0x98), + MBEDTLS_BYTES_TO_T_UINT_8(0x9B, 0xA5, 0x1F, 0xAE, 0x00, 0x00, 0x00, 0x00), +}; +static const mbedtls_mpi_uint secp224r1_T_4_X[] = { + MBEDTLS_BYTES_TO_T_UINT_8(0xAF, 0x1C, 0x4B, 0xDF, 0x5B, 0xF2, 0x51, 0xB7), + MBEDTLS_BYTES_TO_T_UINT_8(0x05, 0x74, 0xB1, 0x5A, 0xC6, 0x0F, 0x0E, 0x61), + MBEDTLS_BYTES_TO_T_UINT_8(0xE8, 0x24, 0x09, 0x62, 0xAF, 0xFC, 0xDB, 0x45), + MBEDTLS_BYTES_TO_T_UINT_8(0x43, 0xE1, 0x80, 0x55, 0x00, 0x00, 0x00, 0x00), +}; +static const mbedtls_mpi_uint secp224r1_T_4_Y[] = { + MBEDTLS_BYTES_TO_T_UINT_8(0x3C, 0x82, 0xFE, 0xAD, 0xC3, 0xE5, 0xCF, 0xD8), + MBEDTLS_BYTES_TO_T_UINT_8(0x24, 0xA2, 0x62, 0x17, 0x76, 0xF0, 0x5A, 0xFA), + MBEDTLS_BYTES_TO_T_UINT_8(0x3E, 0xB8, 0xE5, 0xAC, 0xB7, 0x66, 0x38, 0xAA), + MBEDTLS_BYTES_TO_T_UINT_8(0x97, 0xFD, 0x86, 0x05, 0x00, 0x00, 0x00, 0x00), +}; +static const mbedtls_mpi_uint secp224r1_T_5_X[] = { + MBEDTLS_BYTES_TO_T_UINT_8(0x59, 0xD3, 0x0C, 0x3C, 0xD1, 0x66, 0xB0, 0xF1), + MBEDTLS_BYTES_TO_T_UINT_8(0xBC, 0x59, 0xB4, 0x8D, 0x90, 0x10, 0xB7, 0xA2), + MBEDTLS_BYTES_TO_T_UINT_8(0x96, 0x47, 0x9B, 0xE6, 0x55, 0x8A, 0xE4, 0xEE), + MBEDTLS_BYTES_TO_T_UINT_8(0xB1, 0x49, 0xDB, 0x78, 0x00, 0x00, 0x00, 0x00), +}; +static const mbedtls_mpi_uint secp224r1_T_5_Y[] = { + MBEDTLS_BYTES_TO_T_UINT_8(0x41, 0x97, 0xED, 0xDE, 0xFF, 0xB3, 0xDF, 0x48), + MBEDTLS_BYTES_TO_T_UINT_8(0x10, 0xB9, 0x83, 0xB7, 0xEB, 0xBE, 0x40, 0x8D), + MBEDTLS_BYTES_TO_T_UINT_8(0xAF, 0xD3, 0xD3, 0xCD, 0x0E, 0x82, 0x79, 0x3D), + MBEDTLS_BYTES_TO_T_UINT_8(0x9B, 0x83, 0x1B, 0xF0, 0x00, 0x00, 0x00, 0x00), +}; +static const mbedtls_mpi_uint secp224r1_T_6_X[] = { + MBEDTLS_BYTES_TO_T_UINT_8(0x3F, 0x22, 0xBB, 0x54, 0xD3, 0x31, 0x56, 0xFC), + MBEDTLS_BYTES_TO_T_UINT_8(0x80, 0x36, 0xE5, 0xE0, 0x89, 0x96, 0x8E, 0x71), + MBEDTLS_BYTES_TO_T_UINT_8(0xE1, 0xEF, 0x0A, 0xED, 0xD0, 0x11, 0x4A, 0xFF), + MBEDTLS_BYTES_TO_T_UINT_8(0x15, 0x00, 0x57, 0x27, 0x00, 0x00, 0x00, 0x00), +}; +static const mbedtls_mpi_uint secp224r1_T_6_Y[] = { + MBEDTLS_BYTES_TO_T_UINT_8(0x13, 0xCA, 0x3D, 0xF7, 0x64, 0x9B, 0x6E, 0x85), + MBEDTLS_BYTES_TO_T_UINT_8(0x90, 0xE3, 0x70, 0x6B, 0x41, 0xD7, 0xED, 0x8F), + MBEDTLS_BYTES_TO_T_UINT_8(0x02, 0x44, 0x44, 0x80, 0xCE, 0x13, 0x37, 0x92), + MBEDTLS_BYTES_TO_T_UINT_8(0x94, 0x73, 0x80, 0x79, 0x00, 0x00, 0x00, 0x00), +}; +static const mbedtls_mpi_uint secp224r1_T_7_X[] = { + MBEDTLS_BYTES_TO_T_UINT_8(0xB7, 0x4D, 0x70, 0x7D, 0x31, 0x0F, 0x1C, 0x58), + MBEDTLS_BYTES_TO_T_UINT_8(0x6D, 0x35, 0x88, 0x47, 0xC4, 0x24, 0x78, 0x3F), + MBEDTLS_BYTES_TO_T_UINT_8(0xBA, 0xF0, 0xCD, 0x91, 0x81, 0xB3, 0xDE, 0xB6), + MBEDTLS_BYTES_TO_T_UINT_8(0x04, 0xCE, 0xC6, 0xF7, 0x00, 0x00, 0x00, 0x00), +}; +static const mbedtls_mpi_uint secp224r1_T_7_Y[] = { + MBEDTLS_BYTES_TO_T_UINT_8(0xE9, 0x9C, 0x2D, 0xE8, 0xD2, 0x00, 0x8F, 0x10), + MBEDTLS_BYTES_TO_T_UINT_8(0xD5, 0x5E, 0x7C, 0x0E, 0x0C, 0x6E, 0x58, 0x02), + MBEDTLS_BYTES_TO_T_UINT_8(0xAE, 0x81, 0x21, 0xCE, 0x43, 0xF4, 0x24, 0x3D), + MBEDTLS_BYTES_TO_T_UINT_8(0x9E, 0xBC, 0xF0, 0xF4, 0x00, 0x00, 0x00, 0x00), +}; +static const mbedtls_mpi_uint secp224r1_T_8_X[] = { + MBEDTLS_BYTES_TO_T_UINT_8(0xD6, 0x10, 0xC2, 0x74, 0x4A, 0x8F, 0x8A, 0xCF), + MBEDTLS_BYTES_TO_T_UINT_8(0x89, 0x67, 0xF4, 0x2B, 0x38, 0x2B, 0x35, 0x17), + MBEDTLS_BYTES_TO_T_UINT_8(0xF5, 0xE7, 0x0C, 0xA9, 0xFA, 0x77, 0x5C, 0xBD), + MBEDTLS_BYTES_TO_T_UINT_8(0xE0, 0x33, 0x19, 0x2B, 0x00, 0x00, 0x00, 0x00), +}; +static const mbedtls_mpi_uint secp224r1_T_8_Y[] = { + MBEDTLS_BYTES_TO_T_UINT_8(0xE7, 0x3E, 0x96, 0x22, 0x53, 0xE1, 0xE9, 0xBE), + MBEDTLS_BYTES_TO_T_UINT_8(0xE0, 0x13, 0xBC, 0xA1, 0x16, 0xEC, 0x01, 0x1A), + MBEDTLS_BYTES_TO_T_UINT_8(0x9A, 0x00, 0xC9, 0x7A, 0xC3, 0x73, 0xA5, 0x45), + MBEDTLS_BYTES_TO_T_UINT_8(0xE1, 0xF4, 0x5E, 0xC1, 0x00, 0x00, 0x00, 0x00), +}; +static const mbedtls_mpi_uint secp224r1_T_9_X[] = { + MBEDTLS_BYTES_TO_T_UINT_8(0xA8, 0x95, 0xD6, 0xD9, 0x32, 0x30, 0x2B, 0xD0), + MBEDTLS_BYTES_TO_T_UINT_8(0x77, 0x42, 0x09, 0x05, 0x61, 0x2A, 0x7E, 0x82), + MBEDTLS_BYTES_TO_T_UINT_8(0x73, 0x84, 0xA2, 0x05, 0x88, 0x64, 0x65, 0xF9), + MBEDTLS_BYTES_TO_T_UINT_8(0x03, 0x2D, 0x90, 0xB3, 0x00, 0x00, 0x00, 0x00), +}; +static const mbedtls_mpi_uint secp224r1_T_9_Y[] = { + MBEDTLS_BYTES_TO_T_UINT_8(0x0A, 0xE7, 0x2E, 0x85, 0x55, 0x80, 0x7C, 0x79), + MBEDTLS_BYTES_TO_T_UINT_8(0x0F, 0xC1, 0xAC, 0x78, 0xB4, 0xAF, 0xFB, 0x6E), + MBEDTLS_BYTES_TO_T_UINT_8(0xD3, 0xC3, 0x28, 0x8E, 0x79, 0x18, 0x1F, 0x58), + MBEDTLS_BYTES_TO_T_UINT_8(0x34, 0x46, 0xCF, 0x49, 0x00, 0x00, 0x00, 0x00), +}; +static const mbedtls_mpi_uint secp224r1_T_10_X[] = { + MBEDTLS_BYTES_TO_T_UINT_8(0x63, 0x5F, 0xA8, 0x6C, 0x46, 0x83, 0x43, 0xFA), + MBEDTLS_BYTES_TO_T_UINT_8(0xFA, 0xA9, 0x93, 0x11, 0xB6, 0x07, 0x57, 0x74), + MBEDTLS_BYTES_TO_T_UINT_8(0x77, 0x2A, 0x9D, 0x03, 0x89, 0x7E, 0xD7, 0x3C), + MBEDTLS_BYTES_TO_T_UINT_8(0x7B, 0x8C, 0x62, 0xCF, 0x00, 0x00, 0x00, 0x00), +}; +static const mbedtls_mpi_uint secp224r1_T_10_Y[] = { + MBEDTLS_BYTES_TO_T_UINT_8(0x44, 0x2C, 0x13, 0x59, 0xCC, 0xFA, 0x84, 0x9E), + MBEDTLS_BYTES_TO_T_UINT_8(0x51, 0xB9, 0x48, 0xBC, 0x57, 0xC7, 0xB3, 0x7C), + MBEDTLS_BYTES_TO_T_UINT_8(0xFC, 0x0A, 0x38, 0x24, 0x2E, 0x3A, 0x28, 0x25), + MBEDTLS_BYTES_TO_T_UINT_8(0xBC, 0x0A, 0x43, 0xB8, 0x00, 0x00, 0x00, 0x00), +}; +static const mbedtls_mpi_uint secp224r1_T_11_X[] = { + MBEDTLS_BYTES_TO_T_UINT_8(0x59, 0x25, 0xAB, 0xC1, 0xEE, 0x70, 0x3C, 0xE1), + MBEDTLS_BYTES_TO_T_UINT_8(0xF3, 0xDB, 0x45, 0x1D, 0x4A, 0x80, 0x75, 0x35), + MBEDTLS_BYTES_TO_T_UINT_8(0xE8, 0x1F, 0x4D, 0x2D, 0x9A, 0x05, 0xF4, 0xCB), + MBEDTLS_BYTES_TO_T_UINT_8(0x6B, 0x10, 0xF0, 0x5A, 0x00, 0x00, 0x00, 0x00), +}; +static const mbedtls_mpi_uint secp224r1_T_11_Y[] = { + MBEDTLS_BYTES_TO_T_UINT_8(0x35, 0x95, 0xE1, 0xDC, 0x15, 0x86, 0xC3, 0x7B), + MBEDTLS_BYTES_TO_T_UINT_8(0xEC, 0xDC, 0x27, 0xD1, 0x56, 0xA1, 0x14, 0x0D), + MBEDTLS_BYTES_TO_T_UINT_8(0x59, 0x0B, 0xD6, 0x77, 0x4E, 0x44, 0xA2, 0xF8), + MBEDTLS_BYTES_TO_T_UINT_8(0x94, 0x42, 0x71, 0x1F, 0x00, 0x00, 0x00, 0x00), +}; +static const mbedtls_mpi_uint secp224r1_T_12_X[] = { + MBEDTLS_BYTES_TO_T_UINT_8(0x30, 0x86, 0xB2, 0xB0, 0xC8, 0x2F, 0x7B, 0xFE), + MBEDTLS_BYTES_TO_T_UINT_8(0x96, 0xEF, 0xCB, 0xDB, 0xBC, 0x9E, 0x3B, 0xC5), + MBEDTLS_BYTES_TO_T_UINT_8(0x1B, 0x03, 0x86, 0xDD, 0x5B, 0xF5, 0x8D, 0x46), + MBEDTLS_BYTES_TO_T_UINT_8(0x58, 0x95, 0x79, 0xD6, 0x00, 0x00, 0x00, 0x00), +}; +static const mbedtls_mpi_uint secp224r1_T_12_Y[] = { + MBEDTLS_BYTES_TO_T_UINT_8(0x84, 0x32, 0x14, 0xDA, 0x9B, 0x4F, 0x07, 0x39), + MBEDTLS_BYTES_TO_T_UINT_8(0xB5, 0x3E, 0xFB, 0x06, 0xEE, 0xA7, 0x40, 0x40), + MBEDTLS_BYTES_TO_T_UINT_8(0x76, 0x1F, 0xDF, 0x71, 0x61, 0xFD, 0x8B, 0xBE), + MBEDTLS_BYTES_TO_T_UINT_8(0x80, 0x8B, 0xAB, 0x8B, 0x00, 0x00, 0x00, 0x00), +}; +static const mbedtls_mpi_uint secp224r1_T_13_X[] = { + MBEDTLS_BYTES_TO_T_UINT_8(0xC9, 0x34, 0xB3, 0xB4, 0xBC, 0x9F, 0xB0, 0x5E), + MBEDTLS_BYTES_TO_T_UINT_8(0xE6, 0x58, 0x48, 0xA8, 0x77, 0xBB, 0x13, 0x2F), + MBEDTLS_BYTES_TO_T_UINT_8(0x41, 0xC6, 0xF7, 0x34, 0xCC, 0x89, 0x21, 0x0A), + MBEDTLS_BYTES_TO_T_UINT_8(0xCA, 0x33, 0xDD, 0x1F, 0x00, 0x00, 0x00, 0x00), +}; +static const mbedtls_mpi_uint secp224r1_T_13_Y[] = { + MBEDTLS_BYTES_TO_T_UINT_8(0xCC, 0x81, 0xEF, 0xA4, 0xF2, 0x10, 0x0B, 0xCD), + MBEDTLS_BYTES_TO_T_UINT_8(0x83, 0xF7, 0x6E, 0x72, 0x4A, 0xDF, 0xDD, 0xE8), + MBEDTLS_BYTES_TO_T_UINT_8(0x67, 0x23, 0x0A, 0x53, 0x03, 0x16, 0x62, 0xD2), + MBEDTLS_BYTES_TO_T_UINT_8(0x0B, 0x76, 0xFD, 0x3C, 0x00, 0x00, 0x00, 0x00), +}; +static const mbedtls_mpi_uint secp224r1_T_14_X[] = { + MBEDTLS_BYTES_TO_T_UINT_8(0xCB, 0x14, 0xA1, 0xFA, 0xA0, 0x18, 0xBE, 0x07), + MBEDTLS_BYTES_TO_T_UINT_8(0x03, 0x2A, 0xE1, 0xD7, 0xB0, 0x6C, 0xA0, 0xDE), + MBEDTLS_BYTES_TO_T_UINT_8(0xD1, 0xC0, 0xB0, 0xC6, 0x63, 0x24, 0xCD, 0x4E), + MBEDTLS_BYTES_TO_T_UINT_8(0x33, 0x38, 0x2C, 0xB1, 0x00, 0x00, 0x00, 0x00), +}; +static const mbedtls_mpi_uint secp224r1_T_14_Y[] = { + MBEDTLS_BYTES_TO_T_UINT_8(0xEE, 0xCD, 0x7D, 0x20, 0x0C, 0xFE, 0xAC, 0xC3), + MBEDTLS_BYTES_TO_T_UINT_8(0x09, 0x97, 0x9F, 0xA2, 0xB6, 0x45, 0xF7, 0x7B), + MBEDTLS_BYTES_TO_T_UINT_8(0xCA, 0x99, 0xF3, 0xD2, 0x20, 0x02, 0xEB, 0x04), + MBEDTLS_BYTES_TO_T_UINT_8(0x43, 0x18, 0x5B, 0x7B, 0x00, 0x00, 0x00, 0x00), +}; +static const mbedtls_mpi_uint secp224r1_T_15_X[] = { + MBEDTLS_BYTES_TO_T_UINT_8(0x2B, 0xDD, 0x77, 0x91, 0x60, 0xEA, 0xFD, 0xD3), + MBEDTLS_BYTES_TO_T_UINT_8(0x7D, 0xD3, 0xB5, 0xD6, 0x90, 0x17, 0x0E, 0x1A), + MBEDTLS_BYTES_TO_T_UINT_8(0x00, 0xF4, 0x28, 0xC1, 0xF2, 0x53, 0xF6, 0x63), + MBEDTLS_BYTES_TO_T_UINT_8(0x49, 0x58, 0xDC, 0x61, 0x00, 0x00, 0x00, 0x00), +}; +static const mbedtls_mpi_uint secp224r1_T_15_Y[] = { + MBEDTLS_BYTES_TO_T_UINT_8(0xA8, 0x20, 0x01, 0xFB, 0xF1, 0xBD, 0x5F, 0x45), + MBEDTLS_BYTES_TO_T_UINT_8(0xD0, 0x7F, 0x06, 0xDA, 0x11, 0xCB, 0xBA, 0xA6), + MBEDTLS_BYTES_TO_T_UINT_8(0xA7, 0x41, 0x00, 0xA4, 0x1B, 0x30, 0x33, 0x79), + MBEDTLS_BYTES_TO_T_UINT_8(0xF4, 0xFF, 0x27, 0xCA, 0x00, 0x00, 0x00, 0x00), +}; +static const mbedtls_ecp_point secp224r1_T[16] = { + ECP_POINT_INIT_XY_Z1(secp224r1_T_0_X, secp224r1_T_0_Y), + ECP_POINT_INIT_XY_Z0(secp224r1_T_1_X, secp224r1_T_1_Y), + ECP_POINT_INIT_XY_Z0(secp224r1_T_2_X, secp224r1_T_2_Y), + ECP_POINT_INIT_XY_Z0(secp224r1_T_3_X, secp224r1_T_3_Y), + ECP_POINT_INIT_XY_Z0(secp224r1_T_4_X, secp224r1_T_4_Y), + ECP_POINT_INIT_XY_Z0(secp224r1_T_5_X, secp224r1_T_5_Y), + ECP_POINT_INIT_XY_Z0(secp224r1_T_6_X, secp224r1_T_6_Y), + ECP_POINT_INIT_XY_Z0(secp224r1_T_7_X, secp224r1_T_7_Y), + ECP_POINT_INIT_XY_Z0(secp224r1_T_8_X, secp224r1_T_8_Y), + ECP_POINT_INIT_XY_Z0(secp224r1_T_9_X, secp224r1_T_9_Y), + ECP_POINT_INIT_XY_Z0(secp224r1_T_10_X, secp224r1_T_10_Y), + ECP_POINT_INIT_XY_Z0(secp224r1_T_11_X, secp224r1_T_11_Y), + ECP_POINT_INIT_XY_Z0(secp224r1_T_12_X, secp224r1_T_12_Y), + ECP_POINT_INIT_XY_Z0(secp224r1_T_13_X, secp224r1_T_13_Y), + ECP_POINT_INIT_XY_Z0(secp224r1_T_14_X, secp224r1_T_14_Y), + ECP_POINT_INIT_XY_Z0(secp224r1_T_15_X, secp224r1_T_15_Y), +}; +#else +#define secp224r1_T NULL +#endif +#endif /* MBEDTLS_ECP_DP_SECP224R1_ENABLED */ + +/* + * Domain parameters for secp256r1 + */ +#if defined(MBEDTLS_ECP_DP_SECP256R1_ENABLED) +static const mbedtls_mpi_uint secp256r1_p[] = { + MBEDTLS_BYTES_TO_T_UINT_8(0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF), + MBEDTLS_BYTES_TO_T_UINT_8(0xFF, 0xFF, 0xFF, 0xFF, 0x00, 0x00, 0x00, 0x00), + MBEDTLS_BYTES_TO_T_UINT_8(0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00), + MBEDTLS_BYTES_TO_T_UINT_8(0x01, 0x00, 0x00, 0x00, 0xFF, 0xFF, 0xFF, 0xFF), +}; +static const mbedtls_mpi_uint secp256r1_b[] = { + MBEDTLS_BYTES_TO_T_UINT_8(0x4B, 0x60, 0xD2, 0x27, 0x3E, 0x3C, 0xCE, 0x3B), + MBEDTLS_BYTES_TO_T_UINT_8(0xF6, 0xB0, 0x53, 0xCC, 0xB0, 0x06, 0x1D, 0x65), + MBEDTLS_BYTES_TO_T_UINT_8(0xBC, 0x86, 0x98, 0x76, 0x55, 0xBD, 0xEB, 0xB3), + MBEDTLS_BYTES_TO_T_UINT_8(0xE7, 0x93, 0x3A, 0xAA, 0xD8, 0x35, 0xC6, 0x5A), +}; +static const mbedtls_mpi_uint secp256r1_gx[] = { + MBEDTLS_BYTES_TO_T_UINT_8(0x96, 0xC2, 0x98, 0xD8, 0x45, 0x39, 0xA1, 0xF4), + MBEDTLS_BYTES_TO_T_UINT_8(0xA0, 0x33, 0xEB, 0x2D, 0x81, 0x7D, 0x03, 0x77), + MBEDTLS_BYTES_TO_T_UINT_8(0xF2, 0x40, 0xA4, 0x63, 0xE5, 0xE6, 0xBC, 0xF8), + MBEDTLS_BYTES_TO_T_UINT_8(0x47, 0x42, 0x2C, 0xE1, 0xF2, 0xD1, 0x17, 0x6B), +}; +static const mbedtls_mpi_uint secp256r1_gy[] = { + MBEDTLS_BYTES_TO_T_UINT_8(0xF5, 0x51, 0xBF, 0x37, 0x68, 0x40, 0xB6, 0xCB), + MBEDTLS_BYTES_TO_T_UINT_8(0xCE, 0x5E, 0x31, 0x6B, 0x57, 0x33, 0xCE, 0x2B), + MBEDTLS_BYTES_TO_T_UINT_8(0x16, 0x9E, 0x0F, 0x7C, 0x4A, 0xEB, 0xE7, 0x8E), + MBEDTLS_BYTES_TO_T_UINT_8(0x9B, 0x7F, 0x1A, 0xFE, 0xE2, 0x42, 0xE3, 0x4F), +}; +static const mbedtls_mpi_uint secp256r1_n[] = { + MBEDTLS_BYTES_TO_T_UINT_8(0x51, 0x25, 0x63, 0xFC, 0xC2, 0xCA, 0xB9, 0xF3), + MBEDTLS_BYTES_TO_T_UINT_8(0x84, 0x9E, 0x17, 0xA7, 0xAD, 0xFA, 0xE6, 0xBC), + MBEDTLS_BYTES_TO_T_UINT_8(0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF), + MBEDTLS_BYTES_TO_T_UINT_8(0x00, 0x00, 0x00, 0x00, 0xFF, 0xFF, 0xFF, 0xFF), +}; +#if MBEDTLS_ECP_FIXED_POINT_OPTIM == 1 +static const mbedtls_mpi_uint secp256r1_T_0_X[] = { + MBEDTLS_BYTES_TO_T_UINT_8(0x96, 0xC2, 0x98, 0xD8, 0x45, 0x39, 0xA1, 0xF4), + MBEDTLS_BYTES_TO_T_UINT_8(0xA0, 0x33, 0xEB, 0x2D, 0x81, 0x7D, 0x03, 0x77), + MBEDTLS_BYTES_TO_T_UINT_8(0xF2, 0x40, 0xA4, 0x63, 0xE5, 0xE6, 0xBC, 0xF8), + MBEDTLS_BYTES_TO_T_UINT_8(0x47, 0x42, 0x2C, 0xE1, 0xF2, 0xD1, 0x17, 0x6B), +}; +static const mbedtls_mpi_uint secp256r1_T_0_Y[] = { + MBEDTLS_BYTES_TO_T_UINT_8(0xF5, 0x51, 0xBF, 0x37, 0x68, 0x40, 0xB6, 0xCB), + MBEDTLS_BYTES_TO_T_UINT_8(0xCE, 0x5E, 0x31, 0x6B, 0x57, 0x33, 0xCE, 0x2B), + MBEDTLS_BYTES_TO_T_UINT_8(0x16, 0x9E, 0x0F, 0x7C, 0x4A, 0xEB, 0xE7, 0x8E), + MBEDTLS_BYTES_TO_T_UINT_8(0x9B, 0x7F, 0x1A, 0xFE, 0xE2, 0x42, 0xE3, 0x4F), +}; +static const mbedtls_mpi_uint secp256r1_T_1_X[] = { + MBEDTLS_BYTES_TO_T_UINT_8(0x70, 0xC8, 0xBA, 0x04, 0xB7, 0x4B, 0xD2, 0xF7), + MBEDTLS_BYTES_TO_T_UINT_8(0xAB, 0xC6, 0x23, 0x3A, 0xA0, 0x09, 0x3A, 0x59), + MBEDTLS_BYTES_TO_T_UINT_8(0x1D, 0x9D, 0x4C, 0xF9, 0x58, 0x23, 0xCC, 0xDF), + MBEDTLS_BYTES_TO_T_UINT_8(0x02, 0xED, 0x7B, 0x29, 0x87, 0x0F, 0xFA, 0x3C), +}; +static const mbedtls_mpi_uint secp256r1_T_1_Y[] = { + MBEDTLS_BYTES_TO_T_UINT_8(0x40, 0x69, 0xF2, 0x40, 0x0B, 0xA3, 0x98, 0xCE), + MBEDTLS_BYTES_TO_T_UINT_8(0xAF, 0xA8, 0x48, 0x02, 0x0D, 0x1C, 0x12, 0x62), + MBEDTLS_BYTES_TO_T_UINT_8(0x9B, 0xAF, 0x09, 0x83, 0x80, 0xAA, 0x58, 0xA7), + MBEDTLS_BYTES_TO_T_UINT_8(0xC6, 0x12, 0xBE, 0x70, 0x94, 0x76, 0xE3, 0xE4), +}; +static const mbedtls_mpi_uint secp256r1_T_2_X[] = { + MBEDTLS_BYTES_TO_T_UINT_8(0x7D, 0x7D, 0xEF, 0x86, 0xFF, 0xE3, 0x37, 0xDD), + MBEDTLS_BYTES_TO_T_UINT_8(0xDB, 0x86, 0x8B, 0x08, 0x27, 0x7C, 0xD7, 0xF6), + MBEDTLS_BYTES_TO_T_UINT_8(0x91, 0x54, 0x4C, 0x25, 0x4F, 0x9A, 0xFE, 0x28), + MBEDTLS_BYTES_TO_T_UINT_8(0x5E, 0xFD, 0xF0, 0x6D, 0x37, 0x03, 0x69, 0xD6), +}; +static const mbedtls_mpi_uint secp256r1_T_2_Y[] = { + MBEDTLS_BYTES_TO_T_UINT_8(0x96, 0xD5, 0xDA, 0xAD, 0x92, 0x49, 0xF0, 0x9F), + MBEDTLS_BYTES_TO_T_UINT_8(0xF9, 0x73, 0x43, 0x9E, 0xAF, 0xA7, 0xD1, 0xF3), + MBEDTLS_BYTES_TO_T_UINT_8(0x67, 0x41, 0x07, 0xDF, 0x78, 0x95, 0x3E, 0xA1), + MBEDTLS_BYTES_TO_T_UINT_8(0x22, 0x3D, 0xD1, 0xE6, 0x3C, 0xA5, 0xE2, 0x20), +}; +static const mbedtls_mpi_uint secp256r1_T_3_X[] = { + MBEDTLS_BYTES_TO_T_UINT_8(0xBF, 0x6A, 0x5D, 0x52, 0x35, 0xD7, 0xBF, 0xAE), + MBEDTLS_BYTES_TO_T_UINT_8(0x5A, 0xA2, 0xBE, 0x96, 0xF4, 0xF8, 0x02, 0xC3), + MBEDTLS_BYTES_TO_T_UINT_8(0xA4, 0x20, 0x49, 0x54, 0xEA, 0xB3, 0x82, 0xDB), + MBEDTLS_BYTES_TO_T_UINT_8(0x2E, 0xDB, 0xEA, 0x02, 0xD1, 0x75, 0x1C, 0x62), +}; +static const mbedtls_mpi_uint secp256r1_T_3_Y[] = { + MBEDTLS_BYTES_TO_T_UINT_8(0xF0, 0x85, 0xF4, 0x9E, 0x4C, 0xDC, 0x39, 0x89), + MBEDTLS_BYTES_TO_T_UINT_8(0x63, 0x6D, 0xC4, 0x57, 0xD8, 0x03, 0x5D, 0x22), + MBEDTLS_BYTES_TO_T_UINT_8(0x70, 0x7F, 0x2D, 0x52, 0x6F, 0xC9, 0xDA, 0x4F), + MBEDTLS_BYTES_TO_T_UINT_8(0x9D, 0x64, 0xFA, 0xB4, 0xFE, 0xA4, 0xC4, 0xD7), +}; +static const mbedtls_mpi_uint secp256r1_T_4_X[] = { + MBEDTLS_BYTES_TO_T_UINT_8(0x2A, 0x37, 0xB9, 0xC0, 0xAA, 0x59, 0xC6, 0x8B), + MBEDTLS_BYTES_TO_T_UINT_8(0x3F, 0x58, 0xD9, 0xED, 0x58, 0x99, 0x65, 0xF7), + MBEDTLS_BYTES_TO_T_UINT_8(0x88, 0x7D, 0x26, 0x8C, 0x4A, 0xF9, 0x05, 0x9F), + MBEDTLS_BYTES_TO_T_UINT_8(0x9D, 0x73, 0x9A, 0xC9, 0xE7, 0x46, 0xDC, 0x00), +}; +static const mbedtls_mpi_uint secp256r1_T_4_Y[] = { + MBEDTLS_BYTES_TO_T_UINT_8(0xF2, 0xD0, 0x55, 0xDF, 0x00, 0x0A, 0xF5, 0x4A), + MBEDTLS_BYTES_TO_T_UINT_8(0x6A, 0xBF, 0x56, 0x81, 0x2D, 0x20, 0xEB, 0xB5), + MBEDTLS_BYTES_TO_T_UINT_8(0x11, 0xC1, 0x28, 0x52, 0xAB, 0xE3, 0xD1, 0x40), + MBEDTLS_BYTES_TO_T_UINT_8(0x24, 0x34, 0x79, 0x45, 0x57, 0xA5, 0x12, 0x03), +}; +static const mbedtls_mpi_uint secp256r1_T_5_X[] = { + MBEDTLS_BYTES_TO_T_UINT_8(0xEE, 0xCF, 0xB8, 0x7E, 0xF7, 0x92, 0x96, 0x8D), + MBEDTLS_BYTES_TO_T_UINT_8(0x3D, 0x01, 0x8C, 0x0D, 0x23, 0xF2, 0xE3, 0x05), + MBEDTLS_BYTES_TO_T_UINT_8(0x59, 0x2E, 0xE3, 0x84, 0x52, 0x7A, 0x34, 0x76), + MBEDTLS_BYTES_TO_T_UINT_8(0xE5, 0xA1, 0xB0, 0x15, 0x90, 0xE2, 0x53, 0x3C), +}; +static const mbedtls_mpi_uint secp256r1_T_5_Y[] = { + MBEDTLS_BYTES_TO_T_UINT_8(0xD4, 0x98, 0xE7, 0xFA, 0xA5, 0x7D, 0x8B, 0x53), + MBEDTLS_BYTES_TO_T_UINT_8(0x91, 0x35, 0xD2, 0x00, 0xD1, 0x1B, 0x9F, 0x1B), + MBEDTLS_BYTES_TO_T_UINT_8(0x3F, 0x69, 0x08, 0x9A, 0x72, 0xF0, 0xA9, 0x11), + MBEDTLS_BYTES_TO_T_UINT_8(0xB3, 0xFE, 0x0E, 0x14, 0xDA, 0x7C, 0x0E, 0xD3), +}; +static const mbedtls_mpi_uint secp256r1_T_6_X[] = { + MBEDTLS_BYTES_TO_T_UINT_8(0x83, 0xF6, 0xE8, 0xF8, 0x87, 0xF7, 0xFC, 0x6D), + MBEDTLS_BYTES_TO_T_UINT_8(0x90, 0xBE, 0x7F, 0x3F, 0x7A, 0x2B, 0xD7, 0x13), + MBEDTLS_BYTES_TO_T_UINT_8(0xCF, 0x32, 0xF2, 0x2D, 0x94, 0x6D, 0x42, 0xFD), + MBEDTLS_BYTES_TO_T_UINT_8(0xAD, 0x9A, 0xE3, 0x5F, 0x42, 0xBB, 0x84, 0xED), +}; +static const mbedtls_mpi_uint secp256r1_T_6_Y[] = { + MBEDTLS_BYTES_TO_T_UINT_8(0xFC, 0x95, 0x29, 0x73, 0xA1, 0x67, 0x3E, 0x02), + MBEDTLS_BYTES_TO_T_UINT_8(0xE3, 0x30, 0x54, 0x35, 0x8E, 0x0A, 0xDD, 0x67), + MBEDTLS_BYTES_TO_T_UINT_8(0x03, 0xD7, 0xA1, 0x97, 0x61, 0x3B, 0xF8, 0x0C), + MBEDTLS_BYTES_TO_T_UINT_8(0xF2, 0x33, 0x3C, 0x58, 0x55, 0x34, 0x23, 0xA3), +}; +static const mbedtls_mpi_uint secp256r1_T_7_X[] = { + MBEDTLS_BYTES_TO_T_UINT_8(0x99, 0x5D, 0x16, 0x5F, 0x7B, 0xBC, 0xBB, 0xCE), + MBEDTLS_BYTES_TO_T_UINT_8(0x61, 0xEE, 0x4E, 0x8A, 0xC1, 0x51, 0xCC, 0x50), + MBEDTLS_BYTES_TO_T_UINT_8(0x1F, 0x0D, 0x4D, 0x1B, 0x53, 0x23, 0x1D, 0xB3), + MBEDTLS_BYTES_TO_T_UINT_8(0xDA, 0x2A, 0x38, 0x66, 0x52, 0x84, 0xE1, 0x95), +}; +static const mbedtls_mpi_uint secp256r1_T_7_Y[] = { + MBEDTLS_BYTES_TO_T_UINT_8(0x5B, 0x9B, 0x83, 0x0A, 0x81, 0x4F, 0xAD, 0xAC), + MBEDTLS_BYTES_TO_T_UINT_8(0x0F, 0xFF, 0x42, 0x41, 0x6E, 0xA9, 0xA2, 0xA0), + MBEDTLS_BYTES_TO_T_UINT_8(0x2F, 0xA1, 0x4F, 0x1F, 0x89, 0x82, 0xAA, 0x3E), + MBEDTLS_BYTES_TO_T_UINT_8(0xF3, 0xB8, 0x0F, 0x6B, 0x8F, 0x8C, 0xD6, 0x68), +}; +static const mbedtls_mpi_uint secp256r1_T_8_X[] = { + MBEDTLS_BYTES_TO_T_UINT_8(0xF1, 0xB3, 0xBB, 0x51, 0x69, 0xA2, 0x11, 0x93), + MBEDTLS_BYTES_TO_T_UINT_8(0x65, 0x4F, 0x0F, 0x8D, 0xBD, 0x26, 0x0F, 0xE8), + MBEDTLS_BYTES_TO_T_UINT_8(0xB9, 0xCB, 0xEC, 0x6B, 0x34, 0xC3, 0x3D, 0x9D), + MBEDTLS_BYTES_TO_T_UINT_8(0xE4, 0x5D, 0x1E, 0x10, 0xD5, 0x44, 0xE2, 0x54), +}; +static const mbedtls_mpi_uint secp256r1_T_8_Y[] = { + MBEDTLS_BYTES_TO_T_UINT_8(0x28, 0x9E, 0xB1, 0xF1, 0x6E, 0x4C, 0xAD, 0xB3), + MBEDTLS_BYTES_TO_T_UINT_8(0xB7, 0xE3, 0xC2, 0x58, 0xC0, 0xFB, 0x34, 0x43), + MBEDTLS_BYTES_TO_T_UINT_8(0x25, 0x9C, 0xDF, 0x35, 0x07, 0x41, 0xBD, 0x19), + MBEDTLS_BYTES_TO_T_UINT_8(0xB6, 0x6E, 0x10, 0xEC, 0x0E, 0xEC, 0xBB, 0xD6), +}; +static const mbedtls_mpi_uint secp256r1_T_9_X[] = { + MBEDTLS_BYTES_TO_T_UINT_8(0xC8, 0xCF, 0xEF, 0x3F, 0x83, 0x1A, 0x88, 0xE8), + MBEDTLS_BYTES_TO_T_UINT_8(0x0B, 0x29, 0xB5, 0xB9, 0xE0, 0xC9, 0xA3, 0xAE), + MBEDTLS_BYTES_TO_T_UINT_8(0x88, 0x46, 0x1E, 0x77, 0xCD, 0x7E, 0xB3, 0x10), + MBEDTLS_BYTES_TO_T_UINT_8(0xB6, 0x21, 0xD0, 0xD4, 0xA3, 0x16, 0x08, 0xEE), +}; +static const mbedtls_mpi_uint secp256r1_T_9_Y[] = { + MBEDTLS_BYTES_TO_T_UINT_8(0xA1, 0xCA, 0xA8, 0xB3, 0xBF, 0x29, 0x99, 0x8E), + MBEDTLS_BYTES_TO_T_UINT_8(0xD1, 0xF2, 0x05, 0xC1, 0xCF, 0x5D, 0x91, 0x48), + MBEDTLS_BYTES_TO_T_UINT_8(0x9F, 0x01, 0x49, 0xDB, 0x82, 0xDF, 0x5F, 0x3A), + MBEDTLS_BYTES_TO_T_UINT_8(0xE1, 0x06, 0x90, 0xAD, 0xE3, 0x38, 0xA4, 0xC4), +}; +static const mbedtls_mpi_uint secp256r1_T_10_X[] = { + MBEDTLS_BYTES_TO_T_UINT_8(0xC9, 0xD2, 0x3A, 0xE8, 0x03, 0xC5, 0x6D, 0x5D), + MBEDTLS_BYTES_TO_T_UINT_8(0xBE, 0x35, 0xD0, 0xAE, 0x1D, 0x7A, 0x9F, 0xCA), + MBEDTLS_BYTES_TO_T_UINT_8(0x33, 0x1E, 0xD2, 0xCB, 0xAC, 0x88, 0x27, 0x55), + MBEDTLS_BYTES_TO_T_UINT_8(0xF0, 0xB9, 0x9C, 0xE0, 0x31, 0xDD, 0x99, 0x86), +}; +static const mbedtls_mpi_uint secp256r1_T_10_Y[] = { + MBEDTLS_BYTES_TO_T_UINT_8(0x61, 0xF9, 0x9B, 0x32, 0x96, 0x41, 0x58, 0x38), + MBEDTLS_BYTES_TO_T_UINT_8(0xF9, 0x5A, 0x2A, 0xB8, 0x96, 0x0E, 0xB2, 0x4C), + MBEDTLS_BYTES_TO_T_UINT_8(0xC1, 0x78, 0x2C, 0xC7, 0x08, 0x99, 0x19, 0x24), + MBEDTLS_BYTES_TO_T_UINT_8(0xB7, 0x59, 0x28, 0xE9, 0x84, 0x54, 0xE6, 0x16), +}; +static const mbedtls_mpi_uint secp256r1_T_11_X[] = { + MBEDTLS_BYTES_TO_T_UINT_8(0xDD, 0x38, 0x30, 0xDB, 0x70, 0x2C, 0x0A, 0xA2), + MBEDTLS_BYTES_TO_T_UINT_8(0x7C, 0x5C, 0x9D, 0xE9, 0xD5, 0x46, 0x0B, 0x5F), + MBEDTLS_BYTES_TO_T_UINT_8(0x83, 0x0B, 0x60, 0x4B, 0x37, 0x7D, 0xB9, 0xC9), + MBEDTLS_BYTES_TO_T_UINT_8(0x5E, 0x24, 0xF3, 0x3D, 0x79, 0x7F, 0x6C, 0x18), +}; +static const mbedtls_mpi_uint secp256r1_T_11_Y[] = { + MBEDTLS_BYTES_TO_T_UINT_8(0x7F, 0xE5, 0x1C, 0x4F, 0x60, 0x24, 0xF7, 0x2A), + MBEDTLS_BYTES_TO_T_UINT_8(0xED, 0xD8, 0xE2, 0x91, 0x7F, 0x89, 0x49, 0x92), + MBEDTLS_BYTES_TO_T_UINT_8(0x97, 0xA7, 0x2E, 0x8D, 0x6A, 0xB3, 0x39, 0x81), + MBEDTLS_BYTES_TO_T_UINT_8(0x13, 0x89, 0xB5, 0x9A, 0xB8, 0x8D, 0x42, 0x9C), +}; +static const mbedtls_mpi_uint secp256r1_T_12_X[] = { + MBEDTLS_BYTES_TO_T_UINT_8(0x8D, 0x45, 0xE6, 0x4B, 0x3F, 0x4F, 0x1E, 0x1F), + MBEDTLS_BYTES_TO_T_UINT_8(0x47, 0x65, 0x5E, 0x59, 0x22, 0xCC, 0x72, 0x5F), + MBEDTLS_BYTES_TO_T_UINT_8(0xF1, 0x93, 0x1A, 0x27, 0x1E, 0x34, 0xC5, 0x5B), + MBEDTLS_BYTES_TO_T_UINT_8(0x63, 0xF2, 0xA5, 0x58, 0x5C, 0x15, 0x2E, 0xC6), +}; +static const mbedtls_mpi_uint secp256r1_T_12_Y[] = { + MBEDTLS_BYTES_TO_T_UINT_8(0xF4, 0x7F, 0xBA, 0x58, 0x5A, 0x84, 0x6F, 0x5F), + MBEDTLS_BYTES_TO_T_UINT_8(0xAD, 0xA6, 0x36, 0x7E, 0xDC, 0xF7, 0xE1, 0x67), + MBEDTLS_BYTES_TO_T_UINT_8(0x04, 0x4D, 0xAA, 0xEE, 0x57, 0x76, 0x3A, 0xD3), + MBEDTLS_BYTES_TO_T_UINT_8(0x4E, 0x7E, 0x26, 0x18, 0x22, 0x23, 0x9F, 0xFF), +}; +static const mbedtls_mpi_uint secp256r1_T_13_X[] = { + MBEDTLS_BYTES_TO_T_UINT_8(0x1D, 0x4C, 0x64, 0xC7, 0x55, 0x02, 0x3F, 0xE3), + MBEDTLS_BYTES_TO_T_UINT_8(0xD8, 0x02, 0x90, 0xBB, 0xC3, 0xEC, 0x30, 0x40), + MBEDTLS_BYTES_TO_T_UINT_8(0x9F, 0x6F, 0x64, 0xF4, 0x16, 0x69, 0x48, 0xA4), + MBEDTLS_BYTES_TO_T_UINT_8(0xFA, 0x44, 0x9C, 0x95, 0x0C, 0x7D, 0x67, 0x5E), +}; +static const mbedtls_mpi_uint secp256r1_T_13_Y[] = { + MBEDTLS_BYTES_TO_T_UINT_8(0x44, 0x91, 0x8B, 0xD8, 0xD0, 0xD7, 0xE7, 0xE2), + MBEDTLS_BYTES_TO_T_UINT_8(0x1F, 0xF9, 0x48, 0x62, 0x6F, 0xA8, 0x93, 0x5D), + MBEDTLS_BYTES_TO_T_UINT_8(0xEA, 0x3A, 0x99, 0x02, 0xD5, 0x0B, 0x3D, 0xE3), + MBEDTLS_BYTES_TO_T_UINT_8(0x1E, 0xD3, 0x00, 0x31, 0xE6, 0x0C, 0x9F, 0x44), +}; +static const mbedtls_mpi_uint secp256r1_T_14_X[] = { + MBEDTLS_BYTES_TO_T_UINT_8(0x56, 0xB2, 0xAA, 0xFD, 0x88, 0x15, 0xDF, 0x52), + MBEDTLS_BYTES_TO_T_UINT_8(0x4C, 0x35, 0x27, 0x31, 0x44, 0xCD, 0xC0, 0x68), + MBEDTLS_BYTES_TO_T_UINT_8(0x53, 0xF8, 0x91, 0xA5, 0x71, 0x94, 0x84, 0x2A), + MBEDTLS_BYTES_TO_T_UINT_8(0x92, 0xCB, 0xD0, 0x93, 0xE9, 0x88, 0xDA, 0xE4), +}; +static const mbedtls_mpi_uint secp256r1_T_14_Y[] = { + MBEDTLS_BYTES_TO_T_UINT_8(0x24, 0xC6, 0x39, 0x16, 0x5D, 0xA3, 0x1E, 0x6D), + MBEDTLS_BYTES_TO_T_UINT_8(0xBA, 0x07, 0x37, 0x26, 0x36, 0x2A, 0xFE, 0x60), + MBEDTLS_BYTES_TO_T_UINT_8(0x51, 0xBC, 0xF3, 0xD0, 0xDE, 0x50, 0xFC, 0x97), + MBEDTLS_BYTES_TO_T_UINT_8(0x80, 0x2E, 0x06, 0x10, 0x15, 0x4D, 0xFA, 0xF7), +}; +static const mbedtls_mpi_uint secp256r1_T_15_X[] = { + MBEDTLS_BYTES_TO_T_UINT_8(0x27, 0x65, 0x69, 0x5B, 0x66, 0xA2, 0x75, 0x2E), + MBEDTLS_BYTES_TO_T_UINT_8(0x9C, 0x16, 0x00, 0x5A, 0xB0, 0x30, 0x25, 0x1A), + MBEDTLS_BYTES_TO_T_UINT_8(0x42, 0xFB, 0x86, 0x42, 0x80, 0xC1, 0xC4, 0x76), + MBEDTLS_BYTES_TO_T_UINT_8(0x5B, 0x1D, 0x83, 0x8E, 0x94, 0x01, 0x5F, 0x82), +}; +static const mbedtls_mpi_uint secp256r1_T_15_Y[] = { + MBEDTLS_BYTES_TO_T_UINT_8(0x39, 0x37, 0x70, 0xEF, 0x1F, 0xA1, 0xF0, 0xDB), + MBEDTLS_BYTES_TO_T_UINT_8(0x6A, 0x10, 0x5B, 0xCE, 0xC4, 0x9B, 0x6F, 0x10), + MBEDTLS_BYTES_TO_T_UINT_8(0x50, 0x11, 0x11, 0x24, 0x4F, 0x4C, 0x79, 0x61), + MBEDTLS_BYTES_TO_T_UINT_8(0x17, 0x3A, 0x72, 0xBC, 0xFE, 0x72, 0x58, 0x43), +}; +static const mbedtls_ecp_point secp256r1_T[16] = { + ECP_POINT_INIT_XY_Z1(secp256r1_T_0_X, secp256r1_T_0_Y), + ECP_POINT_INIT_XY_Z0(secp256r1_T_1_X, secp256r1_T_1_Y), + ECP_POINT_INIT_XY_Z0(secp256r1_T_2_X, secp256r1_T_2_Y), + ECP_POINT_INIT_XY_Z0(secp256r1_T_3_X, secp256r1_T_3_Y), + ECP_POINT_INIT_XY_Z0(secp256r1_T_4_X, secp256r1_T_4_Y), + ECP_POINT_INIT_XY_Z0(secp256r1_T_5_X, secp256r1_T_5_Y), + ECP_POINT_INIT_XY_Z0(secp256r1_T_6_X, secp256r1_T_6_Y), + ECP_POINT_INIT_XY_Z0(secp256r1_T_7_X, secp256r1_T_7_Y), + ECP_POINT_INIT_XY_Z0(secp256r1_T_8_X, secp256r1_T_8_Y), + ECP_POINT_INIT_XY_Z0(secp256r1_T_9_X, secp256r1_T_9_Y), + ECP_POINT_INIT_XY_Z0(secp256r1_T_10_X, secp256r1_T_10_Y), + ECP_POINT_INIT_XY_Z0(secp256r1_T_11_X, secp256r1_T_11_Y), + ECP_POINT_INIT_XY_Z0(secp256r1_T_12_X, secp256r1_T_12_Y), + ECP_POINT_INIT_XY_Z0(secp256r1_T_13_X, secp256r1_T_13_Y), + ECP_POINT_INIT_XY_Z0(secp256r1_T_14_X, secp256r1_T_14_Y), + ECP_POINT_INIT_XY_Z0(secp256r1_T_15_X, secp256r1_T_15_Y), +}; +#else +#define secp256r1_T NULL +#endif + +#endif /* MBEDTLS_ECP_DP_SECP256R1_ENABLED */ + +/* + * Domain parameters for secp384r1 + */ +#if defined(MBEDTLS_ECP_DP_SECP384R1_ENABLED) +static const mbedtls_mpi_uint secp384r1_p[] = { + MBEDTLS_BYTES_TO_T_UINT_8(0xFF, 0xFF, 0xFF, 0xFF, 0x00, 0x00, 0x00, 0x00), + MBEDTLS_BYTES_TO_T_UINT_8(0x00, 0x00, 0x00, 0x00, 0xFF, 0xFF, 0xFF, 0xFF), + MBEDTLS_BYTES_TO_T_UINT_8(0xFE, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF), + MBEDTLS_BYTES_TO_T_UINT_8(0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF), + MBEDTLS_BYTES_TO_T_UINT_8(0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF), + MBEDTLS_BYTES_TO_T_UINT_8(0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF), +}; +static const mbedtls_mpi_uint secp384r1_b[] = { + MBEDTLS_BYTES_TO_T_UINT_8(0xEF, 0x2A, 0xEC, 0xD3, 0xED, 0xC8, 0x85, 0x2A), + MBEDTLS_BYTES_TO_T_UINT_8(0x9D, 0xD1, 0x2E, 0x8A, 0x8D, 0x39, 0x56, 0xC6), + MBEDTLS_BYTES_TO_T_UINT_8(0x5A, 0x87, 0x13, 0x50, 0x8F, 0x08, 0x14, 0x03), + MBEDTLS_BYTES_TO_T_UINT_8(0x12, 0x41, 0x81, 0xFE, 0x6E, 0x9C, 0x1D, 0x18), + MBEDTLS_BYTES_TO_T_UINT_8(0x19, 0x2D, 0xF8, 0xE3, 0x6B, 0x05, 0x8E, 0x98), + MBEDTLS_BYTES_TO_T_UINT_8(0xE4, 0xE7, 0x3E, 0xE2, 0xA7, 0x2F, 0x31, 0xB3), +}; +static const mbedtls_mpi_uint secp384r1_gx[] = { + MBEDTLS_BYTES_TO_T_UINT_8(0xB7, 0x0A, 0x76, 0x72, 0x38, 0x5E, 0x54, 0x3A), + MBEDTLS_BYTES_TO_T_UINT_8(0x6C, 0x29, 0x55, 0xBF, 0x5D, 0xF2, 0x02, 0x55), + MBEDTLS_BYTES_TO_T_UINT_8(0x38, 0x2A, 0x54, 0x82, 0xE0, 0x41, 0xF7, 0x59), + MBEDTLS_BYTES_TO_T_UINT_8(0x98, 0x9B, 0xA7, 0x8B, 0x62, 0x3B, 0x1D, 0x6E), + MBEDTLS_BYTES_TO_T_UINT_8(0x74, 0xAD, 0x20, 0xF3, 0x1E, 0xC7, 0xB1, 0x8E), + MBEDTLS_BYTES_TO_T_UINT_8(0x37, 0x05, 0x8B, 0xBE, 0x22, 0xCA, 0x87, 0xAA), +}; +static const mbedtls_mpi_uint secp384r1_gy[] = { + MBEDTLS_BYTES_TO_T_UINT_8(0x5F, 0x0E, 0xEA, 0x90, 0x7C, 0x1D, 0x43, 0x7A), + MBEDTLS_BYTES_TO_T_UINT_8(0x9D, 0x81, 0x7E, 0x1D, 0xCE, 0xB1, 0x60, 0x0A), + MBEDTLS_BYTES_TO_T_UINT_8(0xC0, 0xB8, 0xF0, 0xB5, 0x13, 0x31, 0xDA, 0xE9), + MBEDTLS_BYTES_TO_T_UINT_8(0x7C, 0x14, 0x9A, 0x28, 0xBD, 0x1D, 0xF4, 0xF8), + MBEDTLS_BYTES_TO_T_UINT_8(0x29, 0xDC, 0x92, 0x92, 0xBF, 0x98, 0x9E, 0x5D), + MBEDTLS_BYTES_TO_T_UINT_8(0x6F, 0x2C, 0x26, 0x96, 0x4A, 0xDE, 0x17, 0x36), +}; +static const mbedtls_mpi_uint secp384r1_n[] = { + MBEDTLS_BYTES_TO_T_UINT_8(0x73, 0x29, 0xC5, 0xCC, 0x6A, 0x19, 0xEC, 0xEC), + MBEDTLS_BYTES_TO_T_UINT_8(0x7A, 0xA7, 0xB0, 0x48, 0xB2, 0x0D, 0x1A, 0x58), + MBEDTLS_BYTES_TO_T_UINT_8(0xDF, 0x2D, 0x37, 0xF4, 0x81, 0x4D, 0x63, 0xC7), + MBEDTLS_BYTES_TO_T_UINT_8(0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF), + MBEDTLS_BYTES_TO_T_UINT_8(0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF), + MBEDTLS_BYTES_TO_T_UINT_8(0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF), +}; +#if MBEDTLS_ECP_FIXED_POINT_OPTIM == 1 +static const mbedtls_mpi_uint secp384r1_T_0_X[] = { + MBEDTLS_BYTES_TO_T_UINT_8(0xB7, 0x0A, 0x76, 0x72, 0x38, 0x5E, 0x54, 0x3A), + MBEDTLS_BYTES_TO_T_UINT_8(0x6C, 0x29, 0x55, 0xBF, 0x5D, 0xF2, 0x02, 0x55), + MBEDTLS_BYTES_TO_T_UINT_8(0x38, 0x2A, 0x54, 0x82, 0xE0, 0x41, 0xF7, 0x59), + MBEDTLS_BYTES_TO_T_UINT_8(0x98, 0x9B, 0xA7, 0x8B, 0x62, 0x3B, 0x1D, 0x6E), + MBEDTLS_BYTES_TO_T_UINT_8(0x74, 0xAD, 0x20, 0xF3, 0x1E, 0xC7, 0xB1, 0x8E), + MBEDTLS_BYTES_TO_T_UINT_8(0x37, 0x05, 0x8B, 0xBE, 0x22, 0xCA, 0x87, 0xAA), +}; +static const mbedtls_mpi_uint secp384r1_T_0_Y[] = { + MBEDTLS_BYTES_TO_T_UINT_8(0x5F, 0x0E, 0xEA, 0x90, 0x7C, 0x1D, 0x43, 0x7A), + MBEDTLS_BYTES_TO_T_UINT_8(0x9D, 0x81, 0x7E, 0x1D, 0xCE, 0xB1, 0x60, 0x0A), + MBEDTLS_BYTES_TO_T_UINT_8(0xC0, 0xB8, 0xF0, 0xB5, 0x13, 0x31, 0xDA, 0xE9), + MBEDTLS_BYTES_TO_T_UINT_8(0x7C, 0x14, 0x9A, 0x28, 0xBD, 0x1D, 0xF4, 0xF8), + MBEDTLS_BYTES_TO_T_UINT_8(0x29, 0xDC, 0x92, 0x92, 0xBF, 0x98, 0x9E, 0x5D), + MBEDTLS_BYTES_TO_T_UINT_8(0x6F, 0x2C, 0x26, 0x96, 0x4A, 0xDE, 0x17, 0x36), +}; +static const mbedtls_mpi_uint secp384r1_T_1_X[] = { + MBEDTLS_BYTES_TO_T_UINT_8(0x46, 0x92, 0x00, 0x2C, 0x78, 0xDB, 0x1F, 0x37), + MBEDTLS_BYTES_TO_T_UINT_8(0x17, 0xF3, 0xEB, 0xB7, 0x06, 0xF7, 0xB6, 0xBC), + MBEDTLS_BYTES_TO_T_UINT_8(0x3D, 0xBC, 0x2C, 0xCF, 0xD8, 0xED, 0x53, 0xE7), + MBEDTLS_BYTES_TO_T_UINT_8(0x52, 0x75, 0x7B, 0xA3, 0xAB, 0xC3, 0x2C, 0x85), + MBEDTLS_BYTES_TO_T_UINT_8(0xE5, 0x9D, 0x78, 0x41, 0xF6, 0x76, 0x84, 0xAC), + MBEDTLS_BYTES_TO_T_UINT_8(0x54, 0x56, 0xE8, 0x52, 0xB3, 0xCB, 0xA8, 0xBD), +}; +static const mbedtls_mpi_uint secp384r1_T_1_Y[] = { + MBEDTLS_BYTES_TO_T_UINT_8(0x6D, 0xF2, 0xAE, 0xA4, 0xB6, 0x89, 0x1B, 0xDA), + MBEDTLS_BYTES_TO_T_UINT_8(0x01, 0x0F, 0xCE, 0x1C, 0x7C, 0xF6, 0x50, 0x4C), + MBEDTLS_BYTES_TO_T_UINT_8(0x4C, 0xEB, 0x90, 0xE6, 0x4D, 0xC7, 0xD4, 0x7A), + MBEDTLS_BYTES_TO_T_UINT_8(0xD1, 0x49, 0x2D, 0x8A, 0x01, 0x99, 0x60, 0x94), + MBEDTLS_BYTES_TO_T_UINT_8(0x5F, 0x80, 0x9B, 0x9B, 0x6A, 0xB0, 0x07, 0xD9), + MBEDTLS_BYTES_TO_T_UINT_8(0xC2, 0xA2, 0xEE, 0x59, 0xBE, 0x95, 0xBC, 0x23), +}; +static const mbedtls_mpi_uint secp384r1_T_2_X[] = { + MBEDTLS_BYTES_TO_T_UINT_8(0xE6, 0x9D, 0x56, 0xAE, 0x59, 0xFB, 0x1F, 0x98), + MBEDTLS_BYTES_TO_T_UINT_8(0xCF, 0xAC, 0x91, 0x80, 0x87, 0xA8, 0x6E, 0x58), + MBEDTLS_BYTES_TO_T_UINT_8(0x30, 0x08, 0xA7, 0x08, 0x94, 0x32, 0xFC, 0x67), + MBEDTLS_BYTES_TO_T_UINT_8(0x9F, 0x29, 0x9E, 0x84, 0xF4, 0xE5, 0x6E, 0x7E), + MBEDTLS_BYTES_TO_T_UINT_8(0x55, 0x21, 0xB9, 0x50, 0x24, 0xF8, 0x9C, 0xC7), + MBEDTLS_BYTES_TO_T_UINT_8(0x34, 0x04, 0x01, 0xC2, 0xFB, 0x77, 0x3E, 0xDE), +}; +static const mbedtls_mpi_uint secp384r1_T_2_Y[] = { + MBEDTLS_BYTES_TO_T_UINT_8(0x00, 0x38, 0xEE, 0xE3, 0xC7, 0x9D, 0xEC, 0xA6), + MBEDTLS_BYTES_TO_T_UINT_8(0xB6, 0x88, 0xCF, 0x43, 0xFA, 0x92, 0x5E, 0x8E), + MBEDTLS_BYTES_TO_T_UINT_8(0xE9, 0xCA, 0x43, 0xF8, 0x3B, 0x49, 0x7E, 0x75), + MBEDTLS_BYTES_TO_T_UINT_8(0x1C, 0xE7, 0xEB, 0x17, 0x45, 0x86, 0xC2, 0xE1), + MBEDTLS_BYTES_TO_T_UINT_8(0x92, 0x69, 0x57, 0x32, 0xE0, 0x9C, 0xD1, 0x00), + MBEDTLS_BYTES_TO_T_UINT_8(0xD9, 0x10, 0xB8, 0x4D, 0xB8, 0xF4, 0x0D, 0xE3), +}; +static const mbedtls_mpi_uint secp384r1_T_3_X[] = { + MBEDTLS_BYTES_TO_T_UINT_8(0x60, 0xDC, 0x9A, 0xB2, 0x79, 0x39, 0x27, 0x16), + MBEDTLS_BYTES_TO_T_UINT_8(0x4F, 0x71, 0xE4, 0x3B, 0x4D, 0x60, 0x0C, 0xA3), + MBEDTLS_BYTES_TO_T_UINT_8(0x55, 0xBD, 0x19, 0x40, 0xFA, 0x19, 0x2A, 0x5A), + MBEDTLS_BYTES_TO_T_UINT_8(0x4D, 0xF8, 0x1E, 0x43, 0xA1, 0x50, 0x8D, 0xEF), + MBEDTLS_BYTES_TO_T_UINT_8(0xA3, 0x18, 0x7C, 0x41, 0xFA, 0x7C, 0x1B, 0x58), + MBEDTLS_BYTES_TO_T_UINT_8(0x00, 0x59, 0x24, 0xC4, 0xE9, 0xB7, 0xD3, 0xAD), +}; +static const mbedtls_mpi_uint secp384r1_T_3_Y[] = { + MBEDTLS_BYTES_TO_T_UINT_8(0xBB, 0x01, 0x3D, 0x63, 0x54, 0x45, 0x6F, 0xB7), + MBEDTLS_BYTES_TO_T_UINT_8(0x7B, 0xB2, 0x19, 0xA3, 0x86, 0x1D, 0x42, 0x34), + MBEDTLS_BYTES_TO_T_UINT_8(0x84, 0x02, 0x87, 0x18, 0x92, 0x52, 0x1A, 0x71), + MBEDTLS_BYTES_TO_T_UINT_8(0x6C, 0x18, 0xB1, 0x5D, 0x18, 0x1B, 0x37, 0xFE), + MBEDTLS_BYTES_TO_T_UINT_8(0xF4, 0x74, 0x61, 0xBA, 0x18, 0xAF, 0x40, 0x30), + MBEDTLS_BYTES_TO_T_UINT_8(0xDA, 0x7D, 0x3C, 0x52, 0x0F, 0x07, 0xB0, 0x6F), +}; +static const mbedtls_mpi_uint secp384r1_T_4_X[] = { + MBEDTLS_BYTES_TO_T_UINT_8(0x09, 0x39, 0x13, 0xAA, 0x60, 0x15, 0x99, 0x30), + MBEDTLS_BYTES_TO_T_UINT_8(0x17, 0x00, 0xCB, 0xC6, 0xB1, 0xDB, 0x97, 0x90), + MBEDTLS_BYTES_TO_T_UINT_8(0xE6, 0xFA, 0x60, 0xB8, 0x24, 0xE4, 0x7D, 0xD3), + MBEDTLS_BYTES_TO_T_UINT_8(0xDD, 0x75, 0xB3, 0x70, 0xB2, 0x83, 0xB1, 0x9B), + MBEDTLS_BYTES_TO_T_UINT_8(0xA3, 0xE3, 0x6C, 0xCD, 0x33, 0x62, 0x7A, 0x56), + MBEDTLS_BYTES_TO_T_UINT_8(0x88, 0x30, 0xDC, 0x0F, 0x9F, 0xBB, 0xB8, 0xAA), +}; +static const mbedtls_mpi_uint secp384r1_T_4_Y[] = { + MBEDTLS_BYTES_TO_T_UINT_8(0xA6, 0xD5, 0x0A, 0x60, 0x81, 0xB9, 0xC5, 0x16), + MBEDTLS_BYTES_TO_T_UINT_8(0x44, 0xAA, 0x2F, 0xD6, 0xF2, 0x73, 0xDF, 0xEB), + MBEDTLS_BYTES_TO_T_UINT_8(0xF3, 0x7B, 0x74, 0xC9, 0xB3, 0x5B, 0x95, 0x6D), + MBEDTLS_BYTES_TO_T_UINT_8(0xAC, 0x04, 0xEB, 0x15, 0xC8, 0x5F, 0x00, 0xF6), + MBEDTLS_BYTES_TO_T_UINT_8(0xB5, 0x50, 0x20, 0x28, 0xD1, 0x01, 0xAF, 0xF0), + MBEDTLS_BYTES_TO_T_UINT_8(0x28, 0x6D, 0x4F, 0x31, 0x81, 0x2F, 0x94, 0x48), +}; +static const mbedtls_mpi_uint secp384r1_T_5_X[] = { + MBEDTLS_BYTES_TO_T_UINT_8(0x46, 0x2F, 0xD8, 0xB6, 0x63, 0x7C, 0xE9, 0x50), + MBEDTLS_BYTES_TO_T_UINT_8(0xD9, 0x8C, 0xB9, 0x14, 0xD9, 0x37, 0x63, 0xDE), + MBEDTLS_BYTES_TO_T_UINT_8(0x10, 0x02, 0xB8, 0x46, 0xAD, 0xCE, 0x7B, 0x38), + MBEDTLS_BYTES_TO_T_UINT_8(0x82, 0x47, 0x2D, 0x66, 0xA7, 0xE9, 0x33, 0x23), + MBEDTLS_BYTES_TO_T_UINT_8(0x92, 0xF9, 0x93, 0x94, 0xA8, 0x48, 0xB3, 0x4F), + MBEDTLS_BYTES_TO_T_UINT_8(0xE9, 0x4A, 0xAC, 0x51, 0x08, 0x72, 0x2F, 0x1A), +}; +static const mbedtls_mpi_uint secp384r1_T_5_Y[] = { + MBEDTLS_BYTES_TO_T_UINT_8(0xDA, 0xAD, 0xA0, 0xF9, 0x81, 0xE1, 0x78, 0x97), + MBEDTLS_BYTES_TO_T_UINT_8(0x3A, 0x9A, 0x63, 0xD8, 0xBA, 0x79, 0x1A, 0x17), + MBEDTLS_BYTES_TO_T_UINT_8(0x34, 0x31, 0x7B, 0x7A, 0x5A, 0x5D, 0x7D, 0x2D), + MBEDTLS_BYTES_TO_T_UINT_8(0x83, 0x96, 0x12, 0x4B, 0x19, 0x09, 0xE0, 0xB7), + MBEDTLS_BYTES_TO_T_UINT_8(0x55, 0x8A, 0x57, 0xEE, 0x4E, 0x6E, 0x7E, 0xEC), + MBEDTLS_BYTES_TO_T_UINT_8(0x11, 0x9D, 0x69, 0xDC, 0xB3, 0xDA, 0xD8, 0x08), +}; +static const mbedtls_mpi_uint secp384r1_T_6_X[] = { + MBEDTLS_BYTES_TO_T_UINT_8(0x68, 0x49, 0x03, 0x03, 0x33, 0x6F, 0x28, 0x4A), + MBEDTLS_BYTES_TO_T_UINT_8(0x5D, 0xDB, 0xA7, 0x05, 0x8C, 0xF3, 0x4D, 0xFB), + MBEDTLS_BYTES_TO_T_UINT_8(0x8E, 0x92, 0xB1, 0xA8, 0xEC, 0x0D, 0x64, 0x3B), + MBEDTLS_BYTES_TO_T_UINT_8(0x4E, 0xFC, 0xFD, 0xD0, 0x4B, 0x88, 0x1B, 0x5D), + MBEDTLS_BYTES_TO_T_UINT_8(0x83, 0x9C, 0x51, 0x69, 0xCE, 0x71, 0x73, 0xF5), + MBEDTLS_BYTES_TO_T_UINT_8(0xB8, 0x5A, 0x14, 0x23, 0x1A, 0x46, 0x63, 0x5F), +}; +static const mbedtls_mpi_uint secp384r1_T_6_Y[] = { + MBEDTLS_BYTES_TO_T_UINT_8(0xBC, 0x4C, 0x70, 0x44, 0x18, 0xCD, 0xEF, 0xED), + MBEDTLS_BYTES_TO_T_UINT_8(0xC2, 0x49, 0xDD, 0x64, 0x7E, 0x7E, 0x4D, 0x92), + MBEDTLS_BYTES_TO_T_UINT_8(0xA2, 0x32, 0x7C, 0x09, 0xD0, 0x3F, 0xD6, 0x2C), + MBEDTLS_BYTES_TO_T_UINT_8(0x6D, 0xE0, 0x4F, 0x65, 0x0C, 0x7A, 0x54, 0x3E), + MBEDTLS_BYTES_TO_T_UINT_8(0x16, 0xFA, 0xFB, 0x4A, 0xB4, 0x79, 0x5A, 0x8C), + MBEDTLS_BYTES_TO_T_UINT_8(0x04, 0x5D, 0x1B, 0x2B, 0xDA, 0xBC, 0x9A, 0x74), +}; +static const mbedtls_mpi_uint secp384r1_T_7_X[] = { + MBEDTLS_BYTES_TO_T_UINT_8(0x51, 0xAC, 0x56, 0xF7, 0x5F, 0x51, 0x68, 0x0B), + MBEDTLS_BYTES_TO_T_UINT_8(0xC6, 0xE0, 0x1D, 0xBC, 0x13, 0x4E, 0xAC, 0x03), + MBEDTLS_BYTES_TO_T_UINT_8(0xB7, 0xF5, 0xC5, 0xE6, 0xD2, 0x88, 0xBA, 0xCB), + MBEDTLS_BYTES_TO_T_UINT_8(0xFA, 0x0E, 0x28, 0x23, 0x58, 0x67, 0xFA, 0xEE), + MBEDTLS_BYTES_TO_T_UINT_8(0x9E, 0x80, 0x4B, 0xD8, 0xC4, 0xDF, 0x15, 0xE4), + MBEDTLS_BYTES_TO_T_UINT_8(0xF1, 0x0E, 0x58, 0xE6, 0x2C, 0x59, 0xC2, 0x03), +}; +static const mbedtls_mpi_uint secp384r1_T_7_Y[] = { + MBEDTLS_BYTES_TO_T_UINT_8(0x9B, 0x26, 0x27, 0x99, 0x16, 0x2B, 0x22, 0x0B), + MBEDTLS_BYTES_TO_T_UINT_8(0xBA, 0xF3, 0x8F, 0xC3, 0x2A, 0x9B, 0xFC, 0x38), + MBEDTLS_BYTES_TO_T_UINT_8(0xFC, 0x2E, 0x83, 0x3D, 0xFE, 0x9E, 0x3C, 0x1B), + MBEDTLS_BYTES_TO_T_UINT_8(0x08, 0x57, 0xCD, 0x2D, 0xC1, 0x49, 0x38, 0xB5), + MBEDTLS_BYTES_TO_T_UINT_8(0x95, 0x42, 0x8B, 0x33, 0x89, 0x1F, 0xEA, 0x01), + MBEDTLS_BYTES_TO_T_UINT_8(0xAA, 0x1D, 0x13, 0xD7, 0x50, 0xBB, 0x3E, 0xEB), +}; +static const mbedtls_mpi_uint secp384r1_T_8_X[] = { + MBEDTLS_BYTES_TO_T_UINT_8(0xD2, 0x9A, 0x52, 0xD2, 0x54, 0x7C, 0x97, 0xF2), + MBEDTLS_BYTES_TO_T_UINT_8(0xE0, 0x33, 0x6E, 0xED, 0xD9, 0x87, 0x50, 0xC5), + MBEDTLS_BYTES_TO_T_UINT_8(0x5A, 0x35, 0x7E, 0x16, 0x40, 0x15, 0x83, 0xB8), + MBEDTLS_BYTES_TO_T_UINT_8(0x33, 0x2B, 0xA4, 0xAB, 0x03, 0x91, 0xEA, 0xFE), + MBEDTLS_BYTES_TO_T_UINT_8(0xC1, 0x47, 0x39, 0xEF, 0x05, 0x59, 0xD0, 0x90), + MBEDTLS_BYTES_TO_T_UINT_8(0xBF, 0x24, 0x0D, 0x76, 0x11, 0x53, 0x08, 0xAF), +}; +static const mbedtls_mpi_uint secp384r1_T_8_Y[] = { + MBEDTLS_BYTES_TO_T_UINT_8(0x1F, 0x2F, 0xDD, 0xBD, 0x50, 0x48, 0xB1, 0xE5), + MBEDTLS_BYTES_TO_T_UINT_8(0x80, 0x1C, 0x84, 0x55, 0x78, 0x14, 0xEB, 0xF6), + MBEDTLS_BYTES_TO_T_UINT_8(0xD9, 0x5E, 0x3E, 0xA6, 0xAF, 0xF6, 0xC7, 0x04), + MBEDTLS_BYTES_TO_T_UINT_8(0xE7, 0x11, 0xE2, 0x65, 0xCA, 0x41, 0x95, 0x3B), + MBEDTLS_BYTES_TO_T_UINT_8(0xAE, 0x83, 0xD8, 0xE6, 0x4D, 0x22, 0x06, 0x2D), + MBEDTLS_BYTES_TO_T_UINT_8(0xFA, 0x7F, 0x25, 0x2A, 0xAA, 0x28, 0x46, 0x97), +}; +static const mbedtls_mpi_uint secp384r1_T_9_X[] = { + MBEDTLS_BYTES_TO_T_UINT_8(0x79, 0xDB, 0x15, 0x56, 0x84, 0xCB, 0xC0, 0x56), + MBEDTLS_BYTES_TO_T_UINT_8(0x56, 0xDB, 0x0E, 0x08, 0xC9, 0xF5, 0xD4, 0x9E), + MBEDTLS_BYTES_TO_T_UINT_8(0xE6, 0x62, 0xD0, 0x1A, 0x7C, 0x13, 0xD5, 0x07), + MBEDTLS_BYTES_TO_T_UINT_8(0x7D, 0xAD, 0x53, 0xE0, 0x32, 0x21, 0xA0, 0xC0), + MBEDTLS_BYTES_TO_T_UINT_8(0xC5, 0x38, 0x81, 0x21, 0x23, 0x0E, 0xD2, 0xBB), + MBEDTLS_BYTES_TO_T_UINT_8(0x1C, 0x51, 0x05, 0xD0, 0x1E, 0x82, 0xA9, 0x71), +}; +static const mbedtls_mpi_uint secp384r1_T_9_Y[] = { + MBEDTLS_BYTES_TO_T_UINT_8(0xA7, 0xC3, 0x27, 0xBF, 0xC6, 0xAA, 0xB7, 0xB9), + MBEDTLS_BYTES_TO_T_UINT_8(0xCB, 0x65, 0x45, 0xDF, 0xB9, 0x46, 0x17, 0x46), + MBEDTLS_BYTES_TO_T_UINT_8(0xF5, 0x38, 0x3F, 0xB2, 0xB1, 0x5D, 0xCA, 0x1C), + MBEDTLS_BYTES_TO_T_UINT_8(0x88, 0x29, 0x6C, 0x63, 0xE9, 0xD7, 0x48, 0xB8), + MBEDTLS_BYTES_TO_T_UINT_8(0xBC, 0xF1, 0xD7, 0x99, 0x8C, 0xC2, 0x05, 0x99), + MBEDTLS_BYTES_TO_T_UINT_8(0x6D, 0xE6, 0x5E, 0x82, 0x6D, 0xE5, 0x7E, 0xD5), +}; +static const mbedtls_mpi_uint secp384r1_T_10_X[] = { + MBEDTLS_BYTES_TO_T_UINT_8(0x7B, 0x61, 0xFA, 0x7D, 0x01, 0xDB, 0xB6, 0x63), + MBEDTLS_BYTES_TO_T_UINT_8(0x11, 0xC6, 0x58, 0x39, 0xF4, 0xC6, 0x82, 0x23), + MBEDTLS_BYTES_TO_T_UINT_8(0x47, 0x5A, 0x7A, 0x80, 0x08, 0xCD, 0xAA, 0xD8), + MBEDTLS_BYTES_TO_T_UINT_8(0xDA, 0x8C, 0xC6, 0x3F, 0x3C, 0xA5, 0x68, 0xF4), + MBEDTLS_BYTES_TO_T_UINT_8(0xBB, 0xF5, 0xD5, 0x17, 0xAE, 0x36, 0xD8, 0x8A), + MBEDTLS_BYTES_TO_T_UINT_8(0xC7, 0xAD, 0x92, 0xC5, 0x57, 0x6C, 0xDA, 0x91), +}; +static const mbedtls_mpi_uint secp384r1_T_10_Y[] = { + MBEDTLS_BYTES_TO_T_UINT_8(0xE8, 0x67, 0x17, 0xC0, 0x40, 0x78, 0x8C, 0x84), + MBEDTLS_BYTES_TO_T_UINT_8(0x7E, 0x9F, 0xF4, 0xAA, 0xDA, 0x5C, 0x7E, 0xB2), + MBEDTLS_BYTES_TO_T_UINT_8(0x96, 0xDB, 0x42, 0x3E, 0x72, 0x64, 0xA0, 0x67), + MBEDTLS_BYTES_TO_T_UINT_8(0x27, 0xF9, 0x41, 0x17, 0x43, 0xE3, 0xE8, 0xA8), + MBEDTLS_BYTES_TO_T_UINT_8(0x66, 0xDD, 0xCC, 0x43, 0x7E, 0x16, 0x05, 0x03), + MBEDTLS_BYTES_TO_T_UINT_8(0x36, 0x4B, 0xCF, 0x48, 0x8F, 0x41, 0x90, 0xE5), +}; +static const mbedtls_mpi_uint secp384r1_T_11_X[] = { + MBEDTLS_BYTES_TO_T_UINT_8(0x98, 0x0C, 0x6B, 0x9D, 0x22, 0x04, 0xBC, 0x5C), + MBEDTLS_BYTES_TO_T_UINT_8(0x86, 0x63, 0x79, 0x2F, 0x6A, 0x0E, 0x8A, 0xDE), + MBEDTLS_BYTES_TO_T_UINT_8(0x29, 0x67, 0x3F, 0x02, 0xB8, 0x91, 0x7F, 0x74), + MBEDTLS_BYTES_TO_T_UINT_8(0xFC, 0x14, 0x64, 0xA0, 0x33, 0xF4, 0x6B, 0x50), + MBEDTLS_BYTES_TO_T_UINT_8(0x1C, 0x44, 0x71, 0x87, 0xB8, 0x88, 0x3F, 0x45), + MBEDTLS_BYTES_TO_T_UINT_8(0x1B, 0x2B, 0x85, 0x05, 0xC5, 0x44, 0x53, 0x15), +}; +static const mbedtls_mpi_uint secp384r1_T_11_Y[] = { + MBEDTLS_BYTES_TO_T_UINT_8(0x3E, 0x2B, 0xFE, 0xD1, 0x1C, 0x73, 0xE3, 0x2E), + MBEDTLS_BYTES_TO_T_UINT_8(0x66, 0x33, 0xA1, 0xD3, 0x69, 0x1C, 0x9D, 0xD2), + MBEDTLS_BYTES_TO_T_UINT_8(0xE0, 0x5A, 0xBA, 0xB6, 0xAE, 0x1B, 0x94, 0x04), + MBEDTLS_BYTES_TO_T_UINT_8(0xAF, 0x74, 0x90, 0x5C, 0x57, 0xB0, 0x3A, 0x45), + MBEDTLS_BYTES_TO_T_UINT_8(0xDD, 0x2F, 0x93, 0x20, 0x24, 0x54, 0x1D, 0x8D), + MBEDTLS_BYTES_TO_T_UINT_8(0xFA, 0x78, 0x9D, 0x71, 0x67, 0x5D, 0x49, 0x98), +}; +static const mbedtls_mpi_uint secp384r1_T_12_X[] = { + MBEDTLS_BYTES_TO_T_UINT_8(0x12, 0xC8, 0x0E, 0x11, 0x8D, 0xE0, 0x8F, 0x69), + MBEDTLS_BYTES_TO_T_UINT_8(0x59, 0x7F, 0x79, 0x6C, 0x5F, 0xB7, 0xBC, 0xB1), + MBEDTLS_BYTES_TO_T_UINT_8(0x88, 0xE1, 0x83, 0x3C, 0x12, 0xBB, 0xEE, 0x96), + MBEDTLS_BYTES_TO_T_UINT_8(0x2A, 0xC2, 0xC4, 0x1B, 0x41, 0x71, 0xB9, 0x17), + MBEDTLS_BYTES_TO_T_UINT_8(0xB0, 0xEE, 0xBB, 0x1D, 0x89, 0x50, 0x88, 0xF2), + MBEDTLS_BYTES_TO_T_UINT_8(0xFC, 0x1C, 0x55, 0x74, 0xEB, 0xDE, 0x92, 0x3F), +}; +static const mbedtls_mpi_uint secp384r1_T_12_Y[] = { + MBEDTLS_BYTES_TO_T_UINT_8(0x9C, 0x38, 0x92, 0x06, 0x19, 0xD0, 0xB3, 0xB2), + MBEDTLS_BYTES_TO_T_UINT_8(0x2A, 0x99, 0x26, 0xA3, 0x5F, 0xE2, 0xC1, 0x81), + MBEDTLS_BYTES_TO_T_UINT_8(0x75, 0xFC, 0xFD, 0xC3, 0xB6, 0x26, 0x24, 0x8F), + MBEDTLS_BYTES_TO_T_UINT_8(0xAF, 0xAD, 0xE7, 0x49, 0xB7, 0x64, 0x4B, 0x96), + MBEDTLS_BYTES_TO_T_UINT_8(0x6C, 0x4E, 0x95, 0xAD, 0x07, 0xFE, 0xB6, 0x30), + MBEDTLS_BYTES_TO_T_UINT_8(0x4F, 0x15, 0xE7, 0x2D, 0x19, 0xA9, 0x08, 0x10), +}; +static const mbedtls_mpi_uint secp384r1_T_13_X[] = { + MBEDTLS_BYTES_TO_T_UINT_8(0xBE, 0xBD, 0xAC, 0x0A, 0x3F, 0x6B, 0xFF, 0xFA), + MBEDTLS_BYTES_TO_T_UINT_8(0xE0, 0xE4, 0x74, 0x14, 0xD9, 0x70, 0x1D, 0x71), + MBEDTLS_BYTES_TO_T_UINT_8(0xF2, 0xB0, 0x71, 0xBB, 0xD8, 0x18, 0x96, 0x2B), + MBEDTLS_BYTES_TO_T_UINT_8(0xDA, 0xB8, 0x19, 0x90, 0x80, 0xB5, 0xEE, 0x01), + MBEDTLS_BYTES_TO_T_UINT_8(0x91, 0x21, 0x20, 0xA6, 0x17, 0x48, 0x03, 0x6F), + MBEDTLS_BYTES_TO_T_UINT_8(0xE3, 0x1D, 0xBB, 0x6D, 0x94, 0x20, 0x34, 0xF1), +}; +static const mbedtls_mpi_uint secp384r1_T_13_Y[] = { + MBEDTLS_BYTES_TO_T_UINT_8(0x59, 0x82, 0x67, 0x4B, 0x8E, 0x4E, 0xBE, 0xE2), + MBEDTLS_BYTES_TO_T_UINT_8(0xBE, 0xDA, 0x77, 0xF8, 0x23, 0x55, 0x2B, 0x2D), + MBEDTLS_BYTES_TO_T_UINT_8(0x5C, 0x02, 0xDE, 0x25, 0x35, 0x2D, 0x74, 0x51), + MBEDTLS_BYTES_TO_T_UINT_8(0xD0, 0x0C, 0xB8, 0x0B, 0x39, 0xBA, 0xAD, 0x04), + MBEDTLS_BYTES_TO_T_UINT_8(0xA6, 0x0E, 0x28, 0x4D, 0xE1, 0x3D, 0xE4, 0x1B), + MBEDTLS_BYTES_TO_T_UINT_8(0x5D, 0xEC, 0x0A, 0xD4, 0xB8, 0xC4, 0x8D, 0xB0), +}; +static const mbedtls_mpi_uint secp384r1_T_14_X[] = { + MBEDTLS_BYTES_TO_T_UINT_8(0x3E, 0x68, 0xCE, 0xC2, 0x55, 0x4D, 0x0C, 0x6D), + MBEDTLS_BYTES_TO_T_UINT_8(0x9B, 0x20, 0x93, 0x32, 0x90, 0xD6, 0xAE, 0x47), + MBEDTLS_BYTES_TO_T_UINT_8(0xDD, 0x78, 0xAB, 0x43, 0x9E, 0xEB, 0x73, 0xAE), + MBEDTLS_BYTES_TO_T_UINT_8(0xED, 0x97, 0xC3, 0x83, 0xA6, 0x3C, 0xF1, 0xBF), + MBEDTLS_BYTES_TO_T_UINT_8(0x0F, 0x25, 0x25, 0x66, 0x08, 0x26, 0xFA, 0x4B), + MBEDTLS_BYTES_TO_T_UINT_8(0x41, 0xFB, 0x44, 0x5D, 0x82, 0xEC, 0x3B, 0xAC), +}; +static const mbedtls_mpi_uint secp384r1_T_14_Y[] = { + MBEDTLS_BYTES_TO_T_UINT_8(0x58, 0x90, 0xEA, 0xB5, 0x04, 0x99, 0xD0, 0x69), + MBEDTLS_BYTES_TO_T_UINT_8(0x4A, 0xF2, 0x22, 0xA0, 0xEB, 0xFD, 0x45, 0x87), + MBEDTLS_BYTES_TO_T_UINT_8(0x5D, 0xA4, 0x81, 0x32, 0xFC, 0xFA, 0xEE, 0x5B), + MBEDTLS_BYTES_TO_T_UINT_8(0x27, 0xBB, 0xA4, 0x6A, 0x77, 0x41, 0x5C, 0x1D), + MBEDTLS_BYTES_TO_T_UINT_8(0xA1, 0x1E, 0xAA, 0x4F, 0xF0, 0x10, 0xB3, 0x50), + MBEDTLS_BYTES_TO_T_UINT_8(0x09, 0x74, 0x13, 0x14, 0x9E, 0x90, 0xD7, 0xE6), +}; +static const mbedtls_mpi_uint secp384r1_T_15_X[] = { + MBEDTLS_BYTES_TO_T_UINT_8(0xDB, 0xBD, 0x70, 0x4F, 0xA8, 0xD1, 0x06, 0x2C), + MBEDTLS_BYTES_TO_T_UINT_8(0x19, 0x4E, 0x2E, 0x68, 0xFC, 0x35, 0xFA, 0x50), + MBEDTLS_BYTES_TO_T_UINT_8(0x60, 0x53, 0x75, 0xED, 0xF2, 0x5F, 0xC2, 0xEB), + MBEDTLS_BYTES_TO_T_UINT_8(0x39, 0x87, 0x6B, 0x9F, 0x05, 0xE2, 0x22, 0x93), + MBEDTLS_BYTES_TO_T_UINT_8(0x4F, 0x1A, 0xA8, 0xB7, 0x03, 0x9E, 0x6D, 0x7C), + MBEDTLS_BYTES_TO_T_UINT_8(0xCB, 0xD0, 0x69, 0x88, 0xA8, 0x39, 0x9E, 0x3A), +}; +static const mbedtls_mpi_uint secp384r1_T_15_Y[] = { + MBEDTLS_BYTES_TO_T_UINT_8(0xF8, 0xEF, 0x68, 0xFE, 0xEC, 0x24, 0x08, 0x15), + MBEDTLS_BYTES_TO_T_UINT_8(0xA1, 0x06, 0x4B, 0x92, 0x0D, 0xB7, 0x34, 0x74), + MBEDTLS_BYTES_TO_T_UINT_8(0x3E, 0xF4, 0xDD, 0x1A, 0xA0, 0x4A, 0xE4, 0x45), + MBEDTLS_BYTES_TO_T_UINT_8(0xC3, 0x63, 0x4F, 0x4F, 0xCE, 0xBB, 0xD6, 0xD3), + MBEDTLS_BYTES_TO_T_UINT_8(0xCD, 0xEE, 0x8D, 0xDF, 0x3F, 0x73, 0xB7, 0xAC), + MBEDTLS_BYTES_TO_T_UINT_8(0xDF, 0x06, 0xB6, 0x80, 0x4D, 0x81, 0xD9, 0x53), +}; +static const mbedtls_mpi_uint secp384r1_T_16_X[] = { + MBEDTLS_BYTES_TO_T_UINT_8(0x15, 0xF5, 0x13, 0xDF, 0x13, 0x19, 0x97, 0x94), + MBEDTLS_BYTES_TO_T_UINT_8(0x08, 0xF9, 0xB3, 0x33, 0x66, 0x82, 0x21, 0xFE), + MBEDTLS_BYTES_TO_T_UINT_8(0xF5, 0xFC, 0x39, 0x16, 0x23, 0x43, 0x76, 0x0E), + MBEDTLS_BYTES_TO_T_UINT_8(0x09, 0x48, 0x25, 0xA1, 0x64, 0x95, 0x1C, 0x2F), + MBEDTLS_BYTES_TO_T_UINT_8(0x43, 0xAC, 0x15, 0x57, 0xD9, 0xDE, 0xA0, 0x28), + MBEDTLS_BYTES_TO_T_UINT_8(0x16, 0x5F, 0xB8, 0x3D, 0x48, 0x91, 0x24, 0xCC), +}; +static const mbedtls_mpi_uint secp384r1_T_16_Y[] = { + MBEDTLS_BYTES_TO_T_UINT_8(0x2D, 0xF2, 0xC8, 0x54, 0xD1, 0x32, 0xBD, 0xC4), + MBEDTLS_BYTES_TO_T_UINT_8(0x8A, 0x3B, 0xF0, 0xAA, 0x9D, 0xD8, 0xF4, 0x20), + MBEDTLS_BYTES_TO_T_UINT_8(0x4F, 0xC3, 0xBB, 0x6C, 0x66, 0xAC, 0x25, 0x2D), + MBEDTLS_BYTES_TO_T_UINT_8(0x6F, 0x25, 0x10, 0xB2, 0xE1, 0x41, 0xDE, 0x1D), + MBEDTLS_BYTES_TO_T_UINT_8(0x3C, 0xE8, 0x30, 0xB8, 0x37, 0xBC, 0x2A, 0x98), + MBEDTLS_BYTES_TO_T_UINT_8(0xBA, 0x57, 0x01, 0x4A, 0x1E, 0x78, 0x9F, 0x85), +}; +static const mbedtls_mpi_uint secp384r1_T_17_X[] = { + MBEDTLS_BYTES_TO_T_UINT_8(0xBD, 0x19, 0xCD, 0x12, 0x0B, 0x51, 0x4F, 0x56), + MBEDTLS_BYTES_TO_T_UINT_8(0x30, 0x4B, 0x3D, 0x24, 0xA4, 0x16, 0x59, 0x05), + MBEDTLS_BYTES_TO_T_UINT_8(0xAC, 0xEB, 0xD3, 0x59, 0x2E, 0x75, 0x7C, 0x01), + MBEDTLS_BYTES_TO_T_UINT_8(0x8C, 0xB9, 0xB4, 0xA5, 0xD9, 0x2E, 0x29, 0x4C), + MBEDTLS_BYTES_TO_T_UINT_8(0x86, 0x16, 0x05, 0x75, 0x02, 0xB3, 0x06, 0xEE), + MBEDTLS_BYTES_TO_T_UINT_8(0xAB, 0x7C, 0x9F, 0x79, 0x91, 0xF1, 0x4F, 0x23), +}; +static const mbedtls_mpi_uint secp384r1_T_17_Y[] = { + MBEDTLS_BYTES_TO_T_UINT_8(0x65, 0x98, 0x7C, 0x84, 0xE1, 0xFF, 0x30, 0x77), + MBEDTLS_BYTES_TO_T_UINT_8(0x71, 0xE2, 0xC2, 0x5F, 0x55, 0x40, 0xBD, 0xCD), + MBEDTLS_BYTES_TO_T_UINT_8(0x69, 0x65, 0x87, 0x3F, 0xC4, 0xC2, 0x24, 0x57), + MBEDTLS_BYTES_TO_T_UINT_8(0x0E, 0x30, 0x0A, 0x60, 0x15, 0xD1, 0x24, 0x48), + MBEDTLS_BYTES_TO_T_UINT_8(0x57, 0x99, 0xD9, 0xB6, 0xAE, 0xB1, 0xAF, 0x1D), + MBEDTLS_BYTES_TO_T_UINT_8(0x9B, 0x80, 0xEE, 0xA2, 0x0F, 0x74, 0xB9, 0xF3), +}; +static const mbedtls_mpi_uint secp384r1_T_18_X[] = { + MBEDTLS_BYTES_TO_T_UINT_8(0x03, 0xE6, 0x0F, 0x37, 0xC1, 0x10, 0x99, 0x1E), + MBEDTLS_BYTES_TO_T_UINT_8(0x61, 0xAD, 0x9D, 0x5D, 0x80, 0x01, 0xA6, 0xFE), + MBEDTLS_BYTES_TO_T_UINT_8(0xB0, 0x0F, 0x10, 0x2A, 0x9D, 0x20, 0x38, 0xEB), + MBEDTLS_BYTES_TO_T_UINT_8(0x6C, 0x60, 0xCB, 0xCE, 0x5A, 0xA0, 0xA7, 0x32), + MBEDTLS_BYTES_TO_T_UINT_8(0xBA, 0xCF, 0x14, 0xDF, 0xBF, 0xE5, 0x74, 0x2D), + MBEDTLS_BYTES_TO_T_UINT_8(0xB5, 0x12, 0x1A, 0xDD, 0x59, 0x02, 0x5D, 0xC6), +}; +static const mbedtls_mpi_uint secp384r1_T_18_Y[] = { + MBEDTLS_BYTES_TO_T_UINT_8(0xC8, 0xC9, 0xF8, 0xF5, 0xB6, 0x13, 0x4D, 0x7B), + MBEDTLS_BYTES_TO_T_UINT_8(0xED, 0x45, 0xB1, 0x93, 0xB3, 0xA2, 0x79, 0xDC), + MBEDTLS_BYTES_TO_T_UINT_8(0x74, 0xF6, 0xCF, 0xF7, 0xE6, 0x29, 0x9C, 0xCC), + MBEDTLS_BYTES_TO_T_UINT_8(0x87, 0x50, 0x65, 0x80, 0xBC, 0x59, 0x0A, 0x59), + MBEDTLS_BYTES_TO_T_UINT_8(0x0E, 0xF0, 0x24, 0x35, 0xA2, 0x46, 0xF0, 0x0C), + MBEDTLS_BYTES_TO_T_UINT_8(0xBD, 0x26, 0xC0, 0x9D, 0x61, 0x56, 0x62, 0x67), +}; +static const mbedtls_mpi_uint secp384r1_T_19_X[] = { + MBEDTLS_BYTES_TO_T_UINT_8(0x10, 0xBB, 0xC2, 0x24, 0x43, 0x2E, 0x37, 0x54), + MBEDTLS_BYTES_TO_T_UINT_8(0x8A, 0xF7, 0xCE, 0x35, 0xFC, 0x77, 0xF3, 0x3F), + MBEDTLS_BYTES_TO_T_UINT_8(0x75, 0x34, 0x96, 0xD5, 0x4A, 0x76, 0x9D, 0x6B), + MBEDTLS_BYTES_TO_T_UINT_8(0xB8, 0x3B, 0x0F, 0xEA, 0xA8, 0x12, 0x0B, 0x22), + MBEDTLS_BYTES_TO_T_UINT_8(0x66, 0x3F, 0x5D, 0x2D, 0x1C, 0xD4, 0x9E, 0xFB), + MBEDTLS_BYTES_TO_T_UINT_8(0x7D, 0x2E, 0xDD, 0xC7, 0x6E, 0xAB, 0xAF, 0xDC), +}; +static const mbedtls_mpi_uint secp384r1_T_19_Y[] = { + MBEDTLS_BYTES_TO_T_UINT_8(0x8C, 0xB2, 0x7B, 0x0C, 0x9A, 0x83, 0x8E, 0x59), + MBEDTLS_BYTES_TO_T_UINT_8(0x30, 0x51, 0x90, 0x92, 0x79, 0x32, 0x19, 0xC3), + MBEDTLS_BYTES_TO_T_UINT_8(0xEE, 0x89, 0xF9, 0xD0, 0xCF, 0x2C, 0xA5, 0x8F), + MBEDTLS_BYTES_TO_T_UINT_8(0x7B, 0x50, 0x21, 0xDE, 0x50, 0x41, 0x9D, 0x81), + MBEDTLS_BYTES_TO_T_UINT_8(0xE0, 0x7D, 0x2B, 0x9E, 0x9D, 0x95, 0xA8, 0xE3), + MBEDTLS_BYTES_TO_T_UINT_8(0xD8, 0xA5, 0x20, 0x87, 0x88, 0x97, 0x5F, 0xAA), +}; +static const mbedtls_mpi_uint secp384r1_T_20_X[] = { + MBEDTLS_BYTES_TO_T_UINT_8(0x64, 0x59, 0xB4, 0x66, 0x7E, 0xE8, 0x5A, 0x60), + MBEDTLS_BYTES_TO_T_UINT_8(0xA5, 0x5C, 0x7E, 0xB2, 0xAD, 0xD9, 0xC9, 0xDA), + MBEDTLS_BYTES_TO_T_UINT_8(0x82, 0x97, 0x49, 0xA3, 0x13, 0x83, 0x07, 0x2E), + MBEDTLS_BYTES_TO_T_UINT_8(0x5A, 0x26, 0xC7, 0x13, 0x35, 0x0D, 0xB0, 0x6B), + MBEDTLS_BYTES_TO_T_UINT_8(0x1E, 0x60, 0xAB, 0xFA, 0x4B, 0x93, 0x18, 0x2C), + MBEDTLS_BYTES_TO_T_UINT_8(0x54, 0x2D, 0x1C, 0x31, 0x4C, 0xE4, 0x61, 0xAE), +}; +static const mbedtls_mpi_uint secp384r1_T_20_Y[] = { + MBEDTLS_BYTES_TO_T_UINT_8(0xDE, 0x4D, 0x1E, 0x51, 0x59, 0x6E, 0x91, 0xC5), + MBEDTLS_BYTES_TO_T_UINT_8(0x38, 0x54, 0x4D, 0x51, 0xED, 0x36, 0xCC, 0x60), + MBEDTLS_BYTES_TO_T_UINT_8(0x18, 0xA8, 0x56, 0xC7, 0x78, 0x27, 0x33, 0xC5), + MBEDTLS_BYTES_TO_T_UINT_8(0x42, 0xB7, 0x95, 0xC9, 0x8B, 0xC8, 0x6A, 0xBC), + MBEDTLS_BYTES_TO_T_UINT_8(0x5E, 0xE9, 0x13, 0x96, 0xB3, 0xE1, 0xF9, 0xEE), + MBEDTLS_BYTES_TO_T_UINT_8(0xF5, 0x46, 0xB0, 0x5E, 0xC3, 0x94, 0x03, 0x05), +}; +static const mbedtls_mpi_uint secp384r1_T_21_X[] = { + MBEDTLS_BYTES_TO_T_UINT_8(0x6D, 0x5B, 0x29, 0x30, 0x41, 0x1A, 0x9E, 0xB6), + MBEDTLS_BYTES_TO_T_UINT_8(0x76, 0xCA, 0x83, 0x31, 0x5B, 0xA7, 0xCB, 0x42), + MBEDTLS_BYTES_TO_T_UINT_8(0x21, 0x41, 0x50, 0x44, 0x4D, 0x64, 0x31, 0x89), + MBEDTLS_BYTES_TO_T_UINT_8(0xCF, 0x84, 0xC2, 0x5D, 0x97, 0xA5, 0x3C, 0x18), + MBEDTLS_BYTES_TO_T_UINT_8(0xF0, 0x0F, 0xA5, 0xFD, 0x8E, 0x5A, 0x47, 0x2C), + MBEDTLS_BYTES_TO_T_UINT_8(0x7C, 0x58, 0x02, 0x2D, 0x40, 0xB1, 0x0B, 0xBA), +}; +static const mbedtls_mpi_uint secp384r1_T_21_Y[] = { + MBEDTLS_BYTES_TO_T_UINT_8(0xDA, 0x33, 0x8C, 0x67, 0xCE, 0x23, 0x43, 0x99), + MBEDTLS_BYTES_TO_T_UINT_8(0x84, 0x53, 0x47, 0x72, 0x44, 0x1F, 0x5B, 0x2A), + MBEDTLS_BYTES_TO_T_UINT_8(0xAE, 0xC1, 0xD9, 0xA4, 0x50, 0x88, 0x63, 0x18), + MBEDTLS_BYTES_TO_T_UINT_8(0x7C, 0xF2, 0x75, 0x69, 0x73, 0x00, 0xC4, 0x31), + MBEDTLS_BYTES_TO_T_UINT_8(0x4B, 0x90, 0x1D, 0xDF, 0x1A, 0x00, 0xD8, 0x69), + MBEDTLS_BYTES_TO_T_UINT_8(0x05, 0xB1, 0x89, 0x48, 0xA8, 0x70, 0x62, 0xEF), +}; +static const mbedtls_mpi_uint secp384r1_T_22_X[] = { + MBEDTLS_BYTES_TO_T_UINT_8(0x7E, 0x8A, 0x55, 0x50, 0x7B, 0xEF, 0x8A, 0x3C), + MBEDTLS_BYTES_TO_T_UINT_8(0xFE, 0x1B, 0x23, 0x48, 0x23, 0x63, 0x91, 0xB6), + MBEDTLS_BYTES_TO_T_UINT_8(0x0D, 0x04, 0x54, 0x3C, 0x24, 0x9B, 0xC7, 0x9A), + MBEDTLS_BYTES_TO_T_UINT_8(0x25, 0x38, 0xC3, 0x84, 0xFB, 0xFF, 0x9F, 0x49), + MBEDTLS_BYTES_TO_T_UINT_8(0x66, 0x2A, 0xE0, 0x6D, 0x68, 0x8A, 0x5C, 0xCB), + MBEDTLS_BYTES_TO_T_UINT_8(0xC4, 0x93, 0x53, 0x85, 0xA1, 0x0D, 0xAF, 0x63), +}; +static const mbedtls_mpi_uint secp384r1_T_22_Y[] = { + MBEDTLS_BYTES_TO_T_UINT_8(0x1B, 0x88, 0x95, 0x4C, 0x0B, 0xD0, 0x06, 0x51), + MBEDTLS_BYTES_TO_T_UINT_8(0x92, 0xAF, 0x8D, 0x49, 0xA2, 0xC8, 0xB4, 0xE0), + MBEDTLS_BYTES_TO_T_UINT_8(0x75, 0x76, 0x53, 0x09, 0x88, 0x43, 0x87, 0xCA), + MBEDTLS_BYTES_TO_T_UINT_8(0x90, 0xA4, 0x77, 0x3F, 0x5E, 0x21, 0xB4, 0x0A), + MBEDTLS_BYTES_TO_T_UINT_8(0x35, 0x9E, 0x86, 0x64, 0xCC, 0x91, 0xC1, 0x77), + MBEDTLS_BYTES_TO_T_UINT_8(0xC1, 0x17, 0x56, 0xCB, 0xC3, 0x7D, 0x5B, 0xB1), +}; +static const mbedtls_mpi_uint secp384r1_T_23_X[] = { + MBEDTLS_BYTES_TO_T_UINT_8(0x64, 0x74, 0x9F, 0xB5, 0x91, 0x21, 0xB1, 0x1C), + MBEDTLS_BYTES_TO_T_UINT_8(0x1E, 0xED, 0xE1, 0x11, 0xEF, 0x45, 0xAF, 0xC1), + MBEDTLS_BYTES_TO_T_UINT_8(0xE0, 0x31, 0xBE, 0xB2, 0xBC, 0x72, 0x65, 0x1F), + MBEDTLS_BYTES_TO_T_UINT_8(0xB1, 0x4B, 0x8C, 0x77, 0xCE, 0x1E, 0x42, 0xB5), + MBEDTLS_BYTES_TO_T_UINT_8(0xFF, 0xC9, 0xAA, 0xB9, 0xD9, 0x86, 0x99, 0x55), + MBEDTLS_BYTES_TO_T_UINT_8(0x65, 0x23, 0x80, 0xC6, 0x4E, 0x35, 0x0B, 0x6D), +}; +static const mbedtls_mpi_uint secp384r1_T_23_Y[] = { + MBEDTLS_BYTES_TO_T_UINT_8(0x47, 0xD8, 0xA2, 0x0A, 0x39, 0x32, 0x1D, 0x23), + MBEDTLS_BYTES_TO_T_UINT_8(0x61, 0xC8, 0x86, 0xF1, 0x12, 0x9A, 0x4A, 0x05), + MBEDTLS_BYTES_TO_T_UINT_8(0x8D, 0xF1, 0x7C, 0xAA, 0x70, 0x8E, 0xBC, 0x01), + MBEDTLS_BYTES_TO_T_UINT_8(0x62, 0x01, 0x47, 0x8F, 0xDD, 0x8B, 0xA5, 0xC8), + MBEDTLS_BYTES_TO_T_UINT_8(0xDB, 0x08, 0x21, 0xF4, 0xAB, 0xC7, 0xF5, 0x96), + MBEDTLS_BYTES_TO_T_UINT_8(0x0A, 0x76, 0xA5, 0x95, 0xC4, 0x0F, 0x88, 0x1D), +}; +static const mbedtls_mpi_uint secp384r1_T_24_X[] = { + MBEDTLS_BYTES_TO_T_UINT_8(0x3F, 0x42, 0x2A, 0x52, 0xCD, 0x75, 0x51, 0x49), + MBEDTLS_BYTES_TO_T_UINT_8(0x90, 0x36, 0xE5, 0x04, 0x2B, 0x44, 0xC6, 0xEF), + MBEDTLS_BYTES_TO_T_UINT_8(0x5C, 0xEE, 0x16, 0x13, 0x07, 0x83, 0xB5, 0x30), + MBEDTLS_BYTES_TO_T_UINT_8(0x76, 0x59, 0xC6, 0xA2, 0x19, 0x05, 0xD3, 0xC6), + MBEDTLS_BYTES_TO_T_UINT_8(0xB6, 0x8B, 0xA8, 0x16, 0x09, 0xB7, 0xEA, 0xD6), + MBEDTLS_BYTES_TO_T_UINT_8(0x70, 0xEE, 0x14, 0xAF, 0xB5, 0xFD, 0xD0, 0xEF), +}; +static const mbedtls_mpi_uint secp384r1_T_24_Y[] = { + MBEDTLS_BYTES_TO_T_UINT_8(0x18, 0x7C, 0xCA, 0x71, 0x3E, 0x6E, 0x66, 0x75), + MBEDTLS_BYTES_TO_T_UINT_8(0xBE, 0x31, 0x0E, 0x3F, 0xE5, 0x91, 0xC4, 0x7F), + MBEDTLS_BYTES_TO_T_UINT_8(0x8E, 0x3D, 0xC2, 0x3E, 0x95, 0x37, 0x58, 0x2B), + MBEDTLS_BYTES_TO_T_UINT_8(0x01, 0x1F, 0x02, 0x03, 0xF3, 0xEF, 0xEE, 0x66), + MBEDTLS_BYTES_TO_T_UINT_8(0x28, 0x5B, 0x1A, 0xFC, 0x38, 0xCD, 0xE8, 0x24), + MBEDTLS_BYTES_TO_T_UINT_8(0x12, 0x57, 0x42, 0x85, 0xC6, 0x21, 0x68, 0x71), +}; +static const mbedtls_mpi_uint secp384r1_T_25_X[] = { + MBEDTLS_BYTES_TO_T_UINT_8(0x8D, 0xA2, 0x4A, 0x66, 0xB1, 0x0A, 0xE6, 0xC0), + MBEDTLS_BYTES_TO_T_UINT_8(0x86, 0x0C, 0x94, 0x9D, 0x5E, 0x99, 0xB2, 0xCE), + MBEDTLS_BYTES_TO_T_UINT_8(0xAD, 0x03, 0x40, 0xCA, 0xB2, 0xB3, 0x30, 0x55), + MBEDTLS_BYTES_TO_T_UINT_8(0x74, 0x78, 0x48, 0x27, 0x34, 0x1E, 0xE2, 0x42), + MBEDTLS_BYTES_TO_T_UINT_8(0xAE, 0x72, 0x5B, 0xAC, 0xC1, 0x6D, 0xE3, 0x82), + MBEDTLS_BYTES_TO_T_UINT_8(0x57, 0xAB, 0x46, 0xCB, 0xEA, 0x5E, 0x4B, 0x0B), +}; +static const mbedtls_mpi_uint secp384r1_T_25_Y[] = { + MBEDTLS_BYTES_TO_T_UINT_8(0xFC, 0x08, 0xAD, 0x4E, 0x51, 0x9F, 0x2A, 0x52), + MBEDTLS_BYTES_TO_T_UINT_8(0x68, 0x5C, 0x7D, 0x4C, 0xD6, 0xCF, 0xDD, 0x02), + MBEDTLS_BYTES_TO_T_UINT_8(0xD8, 0x76, 0x26, 0xE0, 0x8B, 0x10, 0xD9, 0x7C), + MBEDTLS_BYTES_TO_T_UINT_8(0x30, 0xA7, 0x23, 0x4E, 0x5F, 0xD2, 0x42, 0x17), + MBEDTLS_BYTES_TO_T_UINT_8(0xD1, 0xE5, 0xA4, 0xEC, 0x77, 0x21, 0x34, 0x28), + MBEDTLS_BYTES_TO_T_UINT_8(0x5C, 0x14, 0x65, 0xEA, 0x4A, 0x85, 0xC3, 0x2F), +}; +static const mbedtls_mpi_uint secp384r1_T_26_X[] = { + MBEDTLS_BYTES_TO_T_UINT_8(0x19, 0xD8, 0x40, 0x27, 0x73, 0x15, 0x7E, 0x65), + MBEDTLS_BYTES_TO_T_UINT_8(0xF6, 0xBB, 0x53, 0x7E, 0x0F, 0x40, 0xC8, 0xD4), + MBEDTLS_BYTES_TO_T_UINT_8(0xEA, 0x37, 0x19, 0x73, 0xEF, 0x5A, 0x5E, 0x04), + MBEDTLS_BYTES_TO_T_UINT_8(0x9C, 0x73, 0x2B, 0x49, 0x7E, 0xAC, 0x97, 0x5C), + MBEDTLS_BYTES_TO_T_UINT_8(0x15, 0xB2, 0xC3, 0x1E, 0x0E, 0xE7, 0xD2, 0x21), + MBEDTLS_BYTES_TO_T_UINT_8(0x8A, 0x08, 0xD6, 0xDD, 0xAC, 0x21, 0xD6, 0x3E), +}; +static const mbedtls_mpi_uint secp384r1_T_26_Y[] = { + MBEDTLS_BYTES_TO_T_UINT_8(0xA9, 0x26, 0xBE, 0x6D, 0x6D, 0xF2, 0x38, 0x3F), + MBEDTLS_BYTES_TO_T_UINT_8(0x08, 0x6C, 0x31, 0xA7, 0x49, 0x50, 0x3A, 0x89), + MBEDTLS_BYTES_TO_T_UINT_8(0xC3, 0x99, 0xC6, 0xF5, 0xD2, 0xC2, 0x30, 0x5A), + MBEDTLS_BYTES_TO_T_UINT_8(0x2A, 0xE4, 0xF6, 0x8B, 0x8B, 0x97, 0xE9, 0xB2), + MBEDTLS_BYTES_TO_T_UINT_8(0xDD, 0x21, 0xB7, 0x0D, 0xFC, 0x15, 0x54, 0x0B), + MBEDTLS_BYTES_TO_T_UINT_8(0x65, 0x83, 0x1C, 0xA4, 0xCD, 0x6B, 0x9D, 0xF2), +}; +static const mbedtls_mpi_uint secp384r1_T_27_X[] = { + MBEDTLS_BYTES_TO_T_UINT_8(0xD6, 0xE8, 0x4C, 0x48, 0xE4, 0xAA, 0x69, 0x93), + MBEDTLS_BYTES_TO_T_UINT_8(0x27, 0x7A, 0x27, 0xFC, 0x37, 0x96, 0x1A, 0x7B), + MBEDTLS_BYTES_TO_T_UINT_8(0x6F, 0xE7, 0x30, 0xA5, 0xCF, 0x13, 0x46, 0x5C), + MBEDTLS_BYTES_TO_T_UINT_8(0x8C, 0xD8, 0xAF, 0x74, 0x23, 0x4D, 0x56, 0x84), + MBEDTLS_BYTES_TO_T_UINT_8(0x32, 0x3D, 0x44, 0x14, 0x1B, 0x97, 0x83, 0xF0), + MBEDTLS_BYTES_TO_T_UINT_8(0xFA, 0x47, 0xD7, 0x5F, 0xFD, 0x98, 0x38, 0xF7), +}; +static const mbedtls_mpi_uint secp384r1_T_27_Y[] = { + MBEDTLS_BYTES_TO_T_UINT_8(0xA3, 0x73, 0x64, 0x36, 0xFD, 0x7B, 0xC1, 0x15), + MBEDTLS_BYTES_TO_T_UINT_8(0xEA, 0x5D, 0x32, 0xD2, 0x47, 0x94, 0x89, 0x2D), + MBEDTLS_BYTES_TO_T_UINT_8(0x51, 0xE9, 0x30, 0xAC, 0x06, 0xC8, 0x65, 0x04), + MBEDTLS_BYTES_TO_T_UINT_8(0xFA, 0x6C, 0xB9, 0x1B, 0xF7, 0x61, 0x49, 0x53), + MBEDTLS_BYTES_TO_T_UINT_8(0xD7, 0xFF, 0x32, 0x43, 0x80, 0xDA, 0xA6, 0xB1), + MBEDTLS_BYTES_TO_T_UINT_8(0xAC, 0xF8, 0x04, 0x01, 0x95, 0x35, 0xCE, 0x21), +}; +static const mbedtls_mpi_uint secp384r1_T_28_X[] = { + MBEDTLS_BYTES_TO_T_UINT_8(0x6D, 0x06, 0x46, 0x0D, 0x51, 0xE2, 0xD8, 0xAC), + MBEDTLS_BYTES_TO_T_UINT_8(0x14, 0x57, 0x1D, 0x6F, 0x79, 0xA0, 0xCD, 0xA6), + MBEDTLS_BYTES_TO_T_UINT_8(0xDF, 0xFB, 0x36, 0xCA, 0xAD, 0xF5, 0x9E, 0x41), + MBEDTLS_BYTES_TO_T_UINT_8(0x6F, 0x7A, 0x1D, 0x9E, 0x1D, 0x95, 0x48, 0xDC), + MBEDTLS_BYTES_TO_T_UINT_8(0x81, 0x26, 0xA5, 0xB7, 0x15, 0x2C, 0xC2, 0xC6), + MBEDTLS_BYTES_TO_T_UINT_8(0x86, 0x42, 0x72, 0xAA, 0x11, 0xDC, 0xC9, 0xB6), +}; +static const mbedtls_mpi_uint secp384r1_T_28_Y[] = { + MBEDTLS_BYTES_TO_T_UINT_8(0x3F, 0x6C, 0x64, 0xA7, 0x62, 0x3C, 0xAB, 0xD4), + MBEDTLS_BYTES_TO_T_UINT_8(0x48, 0x6A, 0x44, 0xD8, 0x60, 0xC0, 0xA8, 0x80), + MBEDTLS_BYTES_TO_T_UINT_8(0x82, 0x76, 0x58, 0x12, 0x57, 0x3C, 0x89, 0x46), + MBEDTLS_BYTES_TO_T_UINT_8(0x82, 0x4F, 0x83, 0xCE, 0xCB, 0xB8, 0xD0, 0x2C), + MBEDTLS_BYTES_TO_T_UINT_8(0x9A, 0x84, 0x04, 0xB0, 0xAD, 0xEB, 0xFA, 0xDF), + MBEDTLS_BYTES_TO_T_UINT_8(0x34, 0xA4, 0xC3, 0x41, 0x44, 0x4E, 0x65, 0x3E), +}; +static const mbedtls_mpi_uint secp384r1_T_29_X[] = { + MBEDTLS_BYTES_TO_T_UINT_8(0xB6, 0x16, 0xA9, 0x1C, 0xE7, 0x65, 0x20, 0xC1), + MBEDTLS_BYTES_TO_T_UINT_8(0x58, 0x53, 0x32, 0xF8, 0xC0, 0xA6, 0xBD, 0x2C), + MBEDTLS_BYTES_TO_T_UINT_8(0xB7, 0xF0, 0xE6, 0x57, 0x31, 0xCC, 0x26, 0x6F), + MBEDTLS_BYTES_TO_T_UINT_8(0x27, 0xE3, 0x54, 0x1C, 0x34, 0xD3, 0x17, 0xBC), + MBEDTLS_BYTES_TO_T_UINT_8(0xF5, 0xAE, 0xED, 0xFB, 0xCD, 0xE7, 0x1E, 0x9F), + MBEDTLS_BYTES_TO_T_UINT_8(0x5A, 0x16, 0x1C, 0x34, 0x40, 0x00, 0x1F, 0xB6), +}; +static const mbedtls_mpi_uint secp384r1_T_29_Y[] = { + MBEDTLS_BYTES_TO_T_UINT_8(0x6A, 0x32, 0x00, 0xC2, 0xD4, 0x3B, 0x1A, 0x09), + MBEDTLS_BYTES_TO_T_UINT_8(0x34, 0xE0, 0x99, 0x8F, 0x0C, 0x4A, 0x16, 0x44), + MBEDTLS_BYTES_TO_T_UINT_8(0x83, 0x73, 0x18, 0x1B, 0xD4, 0x94, 0x29, 0x62), + MBEDTLS_BYTES_TO_T_UINT_8(0x29, 0xA4, 0x2D, 0xB1, 0x9D, 0x74, 0x32, 0x67), + MBEDTLS_BYTES_TO_T_UINT_8(0xBF, 0xF4, 0xB1, 0x0C, 0x37, 0x62, 0x8B, 0x66), + MBEDTLS_BYTES_TO_T_UINT_8(0xC9, 0xFF, 0xDA, 0xE2, 0x35, 0xA3, 0xB6, 0x42), +}; +static const mbedtls_mpi_uint secp384r1_T_30_X[] = { + MBEDTLS_BYTES_TO_T_UINT_8(0x91, 0x49, 0x99, 0x65, 0xC5, 0xED, 0x16, 0xEF), + MBEDTLS_BYTES_TO_T_UINT_8(0x79, 0x42, 0x9A, 0xF3, 0xA7, 0x4E, 0x6F, 0x2B), + MBEDTLS_BYTES_TO_T_UINT_8(0x7B, 0x0A, 0x7E, 0xC0, 0xD7, 0x4E, 0x07, 0x55), + MBEDTLS_BYTES_TO_T_UINT_8(0xD6, 0x7A, 0x31, 0x69, 0xA6, 0xB9, 0x15, 0x34), + MBEDTLS_BYTES_TO_T_UINT_8(0xA8, 0xE0, 0x72, 0xA4, 0x3F, 0xB9, 0xF8, 0x0C), + MBEDTLS_BYTES_TO_T_UINT_8(0x2B, 0x75, 0x32, 0x85, 0xA2, 0xDE, 0x37, 0x12), +}; +static const mbedtls_mpi_uint secp384r1_T_30_Y[] = { + MBEDTLS_BYTES_TO_T_UINT_8(0xBC, 0xC0, 0x0D, 0xCF, 0x25, 0x41, 0xA4, 0xF4), + MBEDTLS_BYTES_TO_T_UINT_8(0x9B, 0xFC, 0xB2, 0x48, 0xC3, 0x85, 0x83, 0x4B), + MBEDTLS_BYTES_TO_T_UINT_8(0x2B, 0xBE, 0x0B, 0x58, 0x2D, 0x7A, 0x9A, 0x62), + MBEDTLS_BYTES_TO_T_UINT_8(0xC5, 0xF3, 0x81, 0x18, 0x1B, 0x74, 0x4F, 0x2C), + MBEDTLS_BYTES_TO_T_UINT_8(0xE2, 0x43, 0xA3, 0x0A, 0x16, 0x8B, 0xA3, 0x1E), + MBEDTLS_BYTES_TO_T_UINT_8(0x4A, 0x18, 0x81, 0x7B, 0x8D, 0xA2, 0x35, 0x77), +}; +static const mbedtls_mpi_uint secp384r1_T_31_X[] = { + MBEDTLS_BYTES_TO_T_UINT_8(0x86, 0xC4, 0x3F, 0x2C, 0xE7, 0x5F, 0x99, 0x03), + MBEDTLS_BYTES_TO_T_UINT_8(0xF0, 0x2B, 0xB7, 0xB6, 0xAD, 0x5A, 0x56, 0xFF), + MBEDTLS_BYTES_TO_T_UINT_8(0x04, 0x00, 0xA4, 0x48, 0xC8, 0xE8, 0xBA, 0xBF), + MBEDTLS_BYTES_TO_T_UINT_8(0xE8, 0xA1, 0xB5, 0x13, 0x5A, 0xCD, 0x99, 0x9C), + MBEDTLS_BYTES_TO_T_UINT_8(0xB0, 0x95, 0xAD, 0xFC, 0xE2, 0x7E, 0xE7, 0xFE), + MBEDTLS_BYTES_TO_T_UINT_8(0x96, 0x6B, 0xD1, 0x34, 0x99, 0x53, 0x63, 0x0B), +}; +static const mbedtls_mpi_uint secp384r1_T_31_Y[] = { + MBEDTLS_BYTES_TO_T_UINT_8(0x19, 0x8A, 0x77, 0x5D, 0x2B, 0xAB, 0x01, 0x28), + MBEDTLS_BYTES_TO_T_UINT_8(0x4E, 0x85, 0xD0, 0xD5, 0x49, 0x83, 0x4D, 0x60), + MBEDTLS_BYTES_TO_T_UINT_8(0x81, 0xC6, 0x91, 0x30, 0x3B, 0x00, 0xAF, 0x7A), + MBEDTLS_BYTES_TO_T_UINT_8(0x3A, 0xAE, 0x61, 0x07, 0xE1, 0xB6, 0xE2, 0xC9), + MBEDTLS_BYTES_TO_T_UINT_8(0x95, 0x43, 0x41, 0xFE, 0x9B, 0xB6, 0xF0, 0xA5), + MBEDTLS_BYTES_TO_T_UINT_8(0xB4, 0x97, 0xAE, 0xAD, 0x89, 0x88, 0x9E, 0x41), +}; +static const mbedtls_ecp_point secp384r1_T[32] = { + ECP_POINT_INIT_XY_Z1(secp384r1_T_0_X, secp384r1_T_0_Y), + ECP_POINT_INIT_XY_Z0(secp384r1_T_1_X, secp384r1_T_1_Y), + ECP_POINT_INIT_XY_Z0(secp384r1_T_2_X, secp384r1_T_2_Y), + ECP_POINT_INIT_XY_Z0(secp384r1_T_3_X, secp384r1_T_3_Y), + ECP_POINT_INIT_XY_Z0(secp384r1_T_4_X, secp384r1_T_4_Y), + ECP_POINT_INIT_XY_Z0(secp384r1_T_5_X, secp384r1_T_5_Y), + ECP_POINT_INIT_XY_Z0(secp384r1_T_6_X, secp384r1_T_6_Y), + ECP_POINT_INIT_XY_Z0(secp384r1_T_7_X, secp384r1_T_7_Y), + ECP_POINT_INIT_XY_Z0(secp384r1_T_8_X, secp384r1_T_8_Y), + ECP_POINT_INIT_XY_Z0(secp384r1_T_9_X, secp384r1_T_9_Y), + ECP_POINT_INIT_XY_Z0(secp384r1_T_10_X, secp384r1_T_10_Y), + ECP_POINT_INIT_XY_Z0(secp384r1_T_11_X, secp384r1_T_11_Y), + ECP_POINT_INIT_XY_Z0(secp384r1_T_12_X, secp384r1_T_12_Y), + ECP_POINT_INIT_XY_Z0(secp384r1_T_13_X, secp384r1_T_13_Y), + ECP_POINT_INIT_XY_Z0(secp384r1_T_14_X, secp384r1_T_14_Y), + ECP_POINT_INIT_XY_Z0(secp384r1_T_15_X, secp384r1_T_15_Y), + ECP_POINT_INIT_XY_Z0(secp384r1_T_16_X, secp384r1_T_16_Y), + ECP_POINT_INIT_XY_Z0(secp384r1_T_17_X, secp384r1_T_17_Y), + ECP_POINT_INIT_XY_Z0(secp384r1_T_18_X, secp384r1_T_18_Y), + ECP_POINT_INIT_XY_Z0(secp384r1_T_19_X, secp384r1_T_19_Y), + ECP_POINT_INIT_XY_Z0(secp384r1_T_20_X, secp384r1_T_20_Y), + ECP_POINT_INIT_XY_Z0(secp384r1_T_21_X, secp384r1_T_21_Y), + ECP_POINT_INIT_XY_Z0(secp384r1_T_22_X, secp384r1_T_22_Y), + ECP_POINT_INIT_XY_Z0(secp384r1_T_23_X, secp384r1_T_23_Y), + ECP_POINT_INIT_XY_Z0(secp384r1_T_24_X, secp384r1_T_24_Y), + ECP_POINT_INIT_XY_Z0(secp384r1_T_25_X, secp384r1_T_25_Y), + ECP_POINT_INIT_XY_Z0(secp384r1_T_26_X, secp384r1_T_26_Y), + ECP_POINT_INIT_XY_Z0(secp384r1_T_27_X, secp384r1_T_27_Y), + ECP_POINT_INIT_XY_Z0(secp384r1_T_28_X, secp384r1_T_28_Y), + ECP_POINT_INIT_XY_Z0(secp384r1_T_29_X, secp384r1_T_29_Y), + ECP_POINT_INIT_XY_Z0(secp384r1_T_30_X, secp384r1_T_30_Y), + ECP_POINT_INIT_XY_Z0(secp384r1_T_31_X, secp384r1_T_31_Y), +}; +#else +#define secp384r1_T NULL +#endif + +#endif /* MBEDTLS_ECP_DP_SECP384R1_ENABLED */ + +/* + * Domain parameters for secp521r1 + */ +#if defined(MBEDTLS_ECP_DP_SECP521R1_ENABLED) +static const mbedtls_mpi_uint secp521r1_p[] = { + MBEDTLS_BYTES_TO_T_UINT_8(0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF), + MBEDTLS_BYTES_TO_T_UINT_8(0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF), + MBEDTLS_BYTES_TO_T_UINT_8(0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF), + MBEDTLS_BYTES_TO_T_UINT_8(0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF), + MBEDTLS_BYTES_TO_T_UINT_8(0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF), + MBEDTLS_BYTES_TO_T_UINT_8(0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF), + MBEDTLS_BYTES_TO_T_UINT_8(0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF), + MBEDTLS_BYTES_TO_T_UINT_8(0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF), + MBEDTLS_BYTES_TO_T_UINT_2(0xFF, 0x01), +}; +static const mbedtls_mpi_uint secp521r1_b[] = { + MBEDTLS_BYTES_TO_T_UINT_8(0x00, 0x3F, 0x50, 0x6B, 0xD4, 0x1F, 0x45, 0xEF), + MBEDTLS_BYTES_TO_T_UINT_8(0xF1, 0x34, 0x2C, 0x3D, 0x88, 0xDF, 0x73, 0x35), + MBEDTLS_BYTES_TO_T_UINT_8(0x07, 0xBF, 0xB1, 0x3B, 0xBD, 0xC0, 0x52, 0x16), + MBEDTLS_BYTES_TO_T_UINT_8(0x7B, 0x93, 0x7E, 0xEC, 0x51, 0x39, 0x19, 0x56), + MBEDTLS_BYTES_TO_T_UINT_8(0xE1, 0x09, 0xF1, 0x8E, 0x91, 0x89, 0xB4, 0xB8), + MBEDTLS_BYTES_TO_T_UINT_8(0xF3, 0x15, 0xB3, 0x99, 0x5B, 0x72, 0xDA, 0xA2), + MBEDTLS_BYTES_TO_T_UINT_8(0xEE, 0x40, 0x85, 0xB6, 0xA0, 0x21, 0x9A, 0x92), + MBEDTLS_BYTES_TO_T_UINT_8(0x1F, 0x9A, 0x1C, 0x8E, 0x61, 0xB9, 0x3E, 0x95), + MBEDTLS_BYTES_TO_T_UINT_2(0x51, 0x00), +}; +static const mbedtls_mpi_uint secp521r1_gx[] = { + MBEDTLS_BYTES_TO_T_UINT_8(0x66, 0xBD, 0xE5, 0xC2, 0x31, 0x7E, 0x7E, 0xF9), + MBEDTLS_BYTES_TO_T_UINT_8(0x9B, 0x42, 0x6A, 0x85, 0xC1, 0xB3, 0x48, 0x33), + MBEDTLS_BYTES_TO_T_UINT_8(0xDE, 0xA8, 0xFF, 0xA2, 0x27, 0xC1, 0x1D, 0xFE), + MBEDTLS_BYTES_TO_T_UINT_8(0x28, 0x59, 0xE7, 0xEF, 0x77, 0x5E, 0x4B, 0xA1), + MBEDTLS_BYTES_TO_T_UINT_8(0xBA, 0x3D, 0x4D, 0x6B, 0x60, 0xAF, 0x28, 0xF8), + MBEDTLS_BYTES_TO_T_UINT_8(0x21, 0xB5, 0x3F, 0x05, 0x39, 0x81, 0x64, 0x9C), + MBEDTLS_BYTES_TO_T_UINT_8(0x42, 0xB4, 0x95, 0x23, 0x66, 0xCB, 0x3E, 0x9E), + MBEDTLS_BYTES_TO_T_UINT_8(0xCD, 0xE9, 0x04, 0x04, 0xB7, 0x06, 0x8E, 0x85), + MBEDTLS_BYTES_TO_T_UINT_2(0xC6, 0x00), +}; +static const mbedtls_mpi_uint secp521r1_gy[] = { + MBEDTLS_BYTES_TO_T_UINT_8(0x50, 0x66, 0xD1, 0x9F, 0x76, 0x94, 0xBE, 0x88), + MBEDTLS_BYTES_TO_T_UINT_8(0x40, 0xC2, 0x72, 0xA2, 0x86, 0x70, 0x3C, 0x35), + MBEDTLS_BYTES_TO_T_UINT_8(0x61, 0x07, 0xAD, 0x3F, 0x01, 0xB9, 0x50, 0xC5), + MBEDTLS_BYTES_TO_T_UINT_8(0x40, 0x26, 0xF4, 0x5E, 0x99, 0x72, 0xEE, 0x97), + MBEDTLS_BYTES_TO_T_UINT_8(0x2C, 0x66, 0x3E, 0x27, 0x17, 0xBD, 0xAF, 0x17), + MBEDTLS_BYTES_TO_T_UINT_8(0x68, 0x44, 0x9B, 0x57, 0x49, 0x44, 0xF5, 0x98), + MBEDTLS_BYTES_TO_T_UINT_8(0xD9, 0x1B, 0x7D, 0x2C, 0xB4, 0x5F, 0x8A, 0x5C), + MBEDTLS_BYTES_TO_T_UINT_8(0x04, 0xC0, 0x3B, 0x9A, 0x78, 0x6A, 0x29, 0x39), + MBEDTLS_BYTES_TO_T_UINT_2(0x18, 0x01), +}; +static const mbedtls_mpi_uint secp521r1_n[] = { + MBEDTLS_BYTES_TO_T_UINT_8(0x09, 0x64, 0x38, 0x91, 0x1E, 0xB7, 0x6F, 0xBB), + MBEDTLS_BYTES_TO_T_UINT_8(0xAE, 0x47, 0x9C, 0x89, 0xB8, 0xC9, 0xB5, 0x3B), + MBEDTLS_BYTES_TO_T_UINT_8(0xD0, 0xA5, 0x09, 0xF7, 0x48, 0x01, 0xCC, 0x7F), + MBEDTLS_BYTES_TO_T_UINT_8(0x6B, 0x96, 0x2F, 0xBF, 0x83, 0x87, 0x86, 0x51), + MBEDTLS_BYTES_TO_T_UINT_8(0xFA, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF), + MBEDTLS_BYTES_TO_T_UINT_8(0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF), + MBEDTLS_BYTES_TO_T_UINT_8(0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF), + MBEDTLS_BYTES_TO_T_UINT_8(0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF), + MBEDTLS_BYTES_TO_T_UINT_2(0xFF, 0x01), +}; +#if MBEDTLS_ECP_FIXED_POINT_OPTIM == 1 +static const mbedtls_mpi_uint secp521r1_T_0_X[] = { + MBEDTLS_BYTES_TO_T_UINT_8(0x66, 0xBD, 0xE5, 0xC2, 0x31, 0x7E, 0x7E, 0xF9), + MBEDTLS_BYTES_TO_T_UINT_8(0x9B, 0x42, 0x6A, 0x85, 0xC1, 0xB3, 0x48, 0x33), + MBEDTLS_BYTES_TO_T_UINT_8(0xDE, 0xA8, 0xFF, 0xA2, 0x27, 0xC1, 0x1D, 0xFE), + MBEDTLS_BYTES_TO_T_UINT_8(0x28, 0x59, 0xE7, 0xEF, 0x77, 0x5E, 0x4B, 0xA1), + MBEDTLS_BYTES_TO_T_UINT_8(0xBA, 0x3D, 0x4D, 0x6B, 0x60, 0xAF, 0x28, 0xF8), + MBEDTLS_BYTES_TO_T_UINT_8(0x21, 0xB5, 0x3F, 0x05, 0x39, 0x81, 0x64, 0x9C), + MBEDTLS_BYTES_TO_T_UINT_8(0x42, 0xB4, 0x95, 0x23, 0x66, 0xCB, 0x3E, 0x9E), + MBEDTLS_BYTES_TO_T_UINT_8(0xCD, 0xE9, 0x04, 0x04, 0xB7, 0x06, 0x8E, 0x85), + MBEDTLS_BYTES_TO_T_UINT_8(0xC6, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00), +}; +static const mbedtls_mpi_uint secp521r1_T_0_Y[] = { + MBEDTLS_BYTES_TO_T_UINT_8(0x50, 0x66, 0xD1, 0x9F, 0x76, 0x94, 0xBE, 0x88), + MBEDTLS_BYTES_TO_T_UINT_8(0x40, 0xC2, 0x72, 0xA2, 0x86, 0x70, 0x3C, 0x35), + MBEDTLS_BYTES_TO_T_UINT_8(0x61, 0x07, 0xAD, 0x3F, 0x01, 0xB9, 0x50, 0xC5), + MBEDTLS_BYTES_TO_T_UINT_8(0x40, 0x26, 0xF4, 0x5E, 0x99, 0x72, 0xEE, 0x97), + MBEDTLS_BYTES_TO_T_UINT_8(0x2C, 0x66, 0x3E, 0x27, 0x17, 0xBD, 0xAF, 0x17), + MBEDTLS_BYTES_TO_T_UINT_8(0x68, 0x44, 0x9B, 0x57, 0x49, 0x44, 0xF5, 0x98), + MBEDTLS_BYTES_TO_T_UINT_8(0xD9, 0x1B, 0x7D, 0x2C, 0xB4, 0x5F, 0x8A, 0x5C), + MBEDTLS_BYTES_TO_T_UINT_8(0x04, 0xC0, 0x3B, 0x9A, 0x78, 0x6A, 0x29, 0x39), + MBEDTLS_BYTES_TO_T_UINT_8(0x18, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00), +}; +static const mbedtls_mpi_uint secp521r1_T_1_X[] = { + MBEDTLS_BYTES_TO_T_UINT_8(0x2F, 0xB1, 0x2D, 0xEB, 0x27, 0x2F, 0xE8, 0xDA), + MBEDTLS_BYTES_TO_T_UINT_8(0x98, 0x4B, 0x44, 0x25, 0xDB, 0x5C, 0x5F, 0x67), + MBEDTLS_BYTES_TO_T_UINT_8(0x13, 0x85, 0x28, 0x78, 0x2E, 0x75, 0x34, 0x32), + MBEDTLS_BYTES_TO_T_UINT_8(0x69, 0x57, 0x0F, 0x73, 0x78, 0x7A, 0xE3, 0x53), + MBEDTLS_BYTES_TO_T_UINT_8(0x8D, 0xD8, 0xEC, 0xDC, 0xDA, 0x04, 0xAD, 0xAB), + MBEDTLS_BYTES_TO_T_UINT_8(0x34, 0x8A, 0x09, 0xF3, 0x58, 0x79, 0xD8, 0x29), + MBEDTLS_BYTES_TO_T_UINT_8(0x63, 0x03, 0xCB, 0x50, 0x1A, 0x7F, 0x56, 0x00), + MBEDTLS_BYTES_TO_T_UINT_8(0xF6, 0xA6, 0x78, 0x38, 0x85, 0x67, 0x0B, 0x40), + MBEDTLS_BYTES_TO_T_UINT_8(0x83, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00), +}; +static const mbedtls_mpi_uint secp521r1_T_1_Y[] = { + MBEDTLS_BYTES_TO_T_UINT_8(0x8A, 0xD5, 0xD2, 0x22, 0xC4, 0x00, 0x3B, 0xBA), + MBEDTLS_BYTES_TO_T_UINT_8(0xD5, 0x93, 0x0E, 0x7B, 0x85, 0x51, 0xC3, 0x06), + MBEDTLS_BYTES_TO_T_UINT_8(0x3D, 0xA6, 0x5F, 0x54, 0x49, 0x02, 0x81, 0x78), + MBEDTLS_BYTES_TO_T_UINT_8(0x22, 0xE9, 0x6B, 0x3A, 0x92, 0xE7, 0x72, 0x1D), + MBEDTLS_BYTES_TO_T_UINT_8(0x6F, 0x5F, 0x28, 0x9E, 0x91, 0x27, 0x88, 0xE3), + MBEDTLS_BYTES_TO_T_UINT_8(0xEF, 0x28, 0x31, 0xB3, 0x84, 0xCA, 0x12, 0x32), + MBEDTLS_BYTES_TO_T_UINT_8(0x3D, 0xF9, 0xAC, 0x22, 0x10, 0x0A, 0x64, 0x41), + MBEDTLS_BYTES_TO_T_UINT_8(0xE9, 0xC6, 0x33, 0x1F, 0x69, 0x19, 0x18, 0xBF), + MBEDTLS_BYTES_TO_T_UINT_8(0xBE, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00), +}; +static const mbedtls_mpi_uint secp521r1_T_2_X[] = { + MBEDTLS_BYTES_TO_T_UINT_8(0xA0, 0x48, 0xB8, 0xC7, 0x37, 0x5A, 0x00, 0x36), + MBEDTLS_BYTES_TO_T_UINT_8(0x07, 0xCC, 0x32, 0xE0, 0xEE, 0x03, 0xC2, 0xBA), + MBEDTLS_BYTES_TO_T_UINT_8(0xC4, 0x29, 0xC2, 0xE4, 0x6E, 0x24, 0x20, 0x8D), + MBEDTLS_BYTES_TO_T_UINT_8(0x06, 0x6B, 0x7F, 0x7B, 0xF9, 0xB0, 0xB8, 0x13), + MBEDTLS_BYTES_TO_T_UINT_8(0x1D, 0x7B, 0x3C, 0xE1, 0x19, 0xA1, 0x23, 0x02), + MBEDTLS_BYTES_TO_T_UINT_8(0x2A, 0xE3, 0xC2, 0x53, 0xC0, 0x07, 0x13, 0xA9), + MBEDTLS_BYTES_TO_T_UINT_8(0x07, 0xFE, 0x36, 0x35, 0x9F, 0x5E, 0x59, 0xCE), + MBEDTLS_BYTES_TO_T_UINT_8(0x1D, 0x55, 0x89, 0x84, 0xBC, 0xEF, 0xA2, 0xC2), + MBEDTLS_BYTES_TO_T_UINT_8(0x19, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00), +}; +static const mbedtls_mpi_uint secp521r1_T_2_Y[] = { + MBEDTLS_BYTES_TO_T_UINT_8(0xFD, 0x1A, 0x08, 0x67, 0xB4, 0xE7, 0x22, 0xED), + MBEDTLS_BYTES_TO_T_UINT_8(0x76, 0x26, 0xDF, 0x81, 0x3C, 0x5F, 0x1C, 0xDA), + MBEDTLS_BYTES_TO_T_UINT_8(0xE0, 0x4D, 0xD0, 0x0A, 0x48, 0x06, 0xF4, 0x48), + MBEDTLS_BYTES_TO_T_UINT_8(0x73, 0x18, 0x39, 0xF7, 0xD1, 0x20, 0x77, 0x8D), + MBEDTLS_BYTES_TO_T_UINT_8(0x78, 0x8F, 0x44, 0x13, 0xCB, 0x78, 0x11, 0x11), + MBEDTLS_BYTES_TO_T_UINT_8(0x33, 0xE2, 0x49, 0xEA, 0x43, 0x79, 0x08, 0x39), + MBEDTLS_BYTES_TO_T_UINT_8(0x01, 0xD1, 0xD8, 0x73, 0x2C, 0x71, 0x2F, 0x69), + MBEDTLS_BYTES_TO_T_UINT_8(0x21, 0xE5, 0xE7, 0xF4, 0x46, 0xAB, 0x20, 0xCA), + MBEDTLS_BYTES_TO_T_UINT_8(0x5A, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00), +}; +static const mbedtls_mpi_uint secp521r1_T_3_X[] = { + MBEDTLS_BYTES_TO_T_UINT_8(0x8C, 0x0B, 0xB9, 0x71, 0x1A, 0x27, 0xB7, 0xA7), + MBEDTLS_BYTES_TO_T_UINT_8(0x2A, 0xA2, 0x2C, 0xD1, 0xDA, 0xBC, 0xC1, 0xBD), + MBEDTLS_BYTES_TO_T_UINT_8(0x10, 0xA3, 0x10, 0x1F, 0x90, 0xF2, 0xA5, 0x52), + MBEDTLS_BYTES_TO_T_UINT_8(0x28, 0xFB, 0x20, 0xF4, 0xC0, 0x70, 0xC0, 0xF5), + MBEDTLS_BYTES_TO_T_UINT_8(0x8F, 0xA7, 0x99, 0xF0, 0xA5, 0xD3, 0x09, 0xDD), + MBEDTLS_BYTES_TO_T_UINT_8(0x26, 0xE8, 0x14, 0x39, 0xBE, 0xCB, 0x60, 0xAF), + MBEDTLS_BYTES_TO_T_UINT_8(0x9F, 0xD6, 0x14, 0xA9, 0xC9, 0x20, 0xC3, 0xEA), + MBEDTLS_BYTES_TO_T_UINT_8(0x5D, 0xA8, 0x5B, 0xFD, 0x2D, 0x96, 0xBC, 0x78), + MBEDTLS_BYTES_TO_T_UINT_8(0xC0, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00), +}; +static const mbedtls_mpi_uint secp521r1_T_3_Y[] = { + MBEDTLS_BYTES_TO_T_UINT_8(0x9D, 0x04, 0x45, 0xBE, 0xCE, 0x75, 0x95, 0xF6), + MBEDTLS_BYTES_TO_T_UINT_8(0xCC, 0xDA, 0x58, 0x49, 0x35, 0x09, 0x8D, 0x41), + MBEDTLS_BYTES_TO_T_UINT_8(0x76, 0xF0, 0xC0, 0x36, 0xF2, 0xA6, 0x2D, 0x14), + MBEDTLS_BYTES_TO_T_UINT_8(0xE7, 0xFC, 0x3D, 0xA8, 0xFB, 0x3C, 0xD2, 0x51), + MBEDTLS_BYTES_TO_T_UINT_8(0x01, 0x4D, 0x71, 0x09, 0x18, 0x42, 0xF0, 0x2D), + MBEDTLS_BYTES_TO_T_UINT_8(0x8D, 0xC1, 0xCE, 0x9E, 0x6A, 0x49, 0x60, 0x12), + MBEDTLS_BYTES_TO_T_UINT_8(0xAD, 0xB1, 0x00, 0xF7, 0xA1, 0x7A, 0x31, 0xB4), + MBEDTLS_BYTES_TO_T_UINT_8(0x41, 0xC3, 0x86, 0xCD, 0x20, 0x4A, 0x17, 0x86), + MBEDTLS_BYTES_TO_T_UINT_8(0x6C, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00), +}; +static const mbedtls_mpi_uint secp521r1_T_4_X[] = { + MBEDTLS_BYTES_TO_T_UINT_8(0x98, 0xAB, 0x8B, 0x47, 0x8D, 0xAA, 0xA6, 0x5B), + MBEDTLS_BYTES_TO_T_UINT_8(0xC4, 0x97, 0xF0, 0xBC, 0x2D, 0xDC, 0x9D, 0x84), + MBEDTLS_BYTES_TO_T_UINT_8(0x01, 0x86, 0xB0, 0x74, 0xB2, 0xF4, 0xF6, 0x67), + MBEDTLS_BYTES_TO_T_UINT_8(0xAC, 0xBD, 0xAC, 0xE3, 0x8F, 0x43, 0x5C, 0xB1), + MBEDTLS_BYTES_TO_T_UINT_8(0x37, 0xC3, 0xE2, 0x6E, 0x25, 0x49, 0xCD, 0x0B), + MBEDTLS_BYTES_TO_T_UINT_8(0x64, 0x5E, 0x08, 0xB3, 0xB9, 0xAC, 0x5F, 0xD1), + MBEDTLS_BYTES_TO_T_UINT_8(0x08, 0xB7, 0xD1, 0xF4, 0xDC, 0x19, 0xE9, 0xC8), + MBEDTLS_BYTES_TO_T_UINT_8(0x49, 0xE4, 0xFA, 0xE1, 0x36, 0x3E, 0xED, 0x6E), + MBEDTLS_BYTES_TO_T_UINT_8(0x0A, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00), +}; +static const mbedtls_mpi_uint secp521r1_T_4_Y[] = { + MBEDTLS_BYTES_TO_T_UINT_8(0x00, 0x67, 0x92, 0x84, 0x6E, 0x48, 0x03, 0x51), + MBEDTLS_BYTES_TO_T_UINT_8(0x9E, 0x95, 0xEF, 0x8F, 0xB2, 0x82, 0x6B, 0x1C), + MBEDTLS_BYTES_TO_T_UINT_8(0x8D, 0xFA, 0xB9, 0x55, 0x23, 0xFE, 0x09, 0xB3), + MBEDTLS_BYTES_TO_T_UINT_8(0xEF, 0x79, 0x85, 0x4B, 0x0E, 0xD4, 0x35, 0xDB), + MBEDTLS_BYTES_TO_T_UINT_8(0x9A, 0x27, 0x45, 0x81, 0xE0, 0x88, 0x52, 0xAD), + MBEDTLS_BYTES_TO_T_UINT_8(0x17, 0x63, 0xA2, 0x4B, 0xBC, 0x5D, 0xB1, 0x92), + MBEDTLS_BYTES_TO_T_UINT_8(0x28, 0x8C, 0x83, 0xD9, 0x3E, 0xD3, 0x42, 0xDA), + MBEDTLS_BYTES_TO_T_UINT_8(0x99, 0x03, 0x3A, 0x31, 0xBA, 0xE9, 0x3A, 0xD1), + MBEDTLS_BYTES_TO_T_UINT_8(0x47, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00), +}; +static const mbedtls_mpi_uint secp521r1_T_5_X[] = { + MBEDTLS_BYTES_TO_T_UINT_8(0x35, 0x10, 0xCD, 0x2D, 0x00, 0xFE, 0x32, 0xA7), + MBEDTLS_BYTES_TO_T_UINT_8(0xE4, 0x6E, 0x1F, 0xDA, 0xF8, 0x6F, 0x4D, 0x03), + MBEDTLS_BYTES_TO_T_UINT_8(0x09, 0x79, 0x7D, 0x09, 0xE5, 0xD3, 0x03, 0x21), + MBEDTLS_BYTES_TO_T_UINT_8(0x58, 0xC3, 0xBE, 0xDF, 0x07, 0x65, 0x49, 0xCC), + MBEDTLS_BYTES_TO_T_UINT_8(0x08, 0x57, 0x33, 0xEF, 0xAE, 0x4F, 0x04, 0x27), + MBEDTLS_BYTES_TO_T_UINT_8(0x9A, 0xE9, 0x9B, 0xFE, 0xBF, 0xE6, 0x85, 0xF6), + MBEDTLS_BYTES_TO_T_UINT_8(0xBD, 0xBA, 0xAA, 0x06, 0xC4, 0xC6, 0xB8, 0x57), + MBEDTLS_BYTES_TO_T_UINT_8(0x0C, 0x83, 0x01, 0xA9, 0xF6, 0x51, 0xE7, 0xB8), + MBEDTLS_BYTES_TO_T_UINT_8(0x1B, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00), +}; +static const mbedtls_mpi_uint secp521r1_T_5_Y[] = { + MBEDTLS_BYTES_TO_T_UINT_8(0xB9, 0xA6, 0x15, 0x8E, 0xAB, 0x1F, 0x10, 0x87), + MBEDTLS_BYTES_TO_T_UINT_8(0x74, 0x08, 0x27, 0x1A, 0xA1, 0x21, 0xAD, 0xF5), + MBEDTLS_BYTES_TO_T_UINT_8(0x02, 0x09, 0x90, 0x6E, 0x50, 0x90, 0x9A, 0x5D), + MBEDTLS_BYTES_TO_T_UINT_8(0x86, 0x9A, 0xFE, 0xD7, 0xA1, 0xF5, 0xA2, 0x15), + MBEDTLS_BYTES_TO_T_UINT_8(0xE8, 0x7D, 0xE3, 0xDC, 0x21, 0xFB, 0xA4, 0x7B), + MBEDTLS_BYTES_TO_T_UINT_8(0xB9, 0xBF, 0x07, 0xFF, 0x45, 0xDF, 0x51, 0x77), + MBEDTLS_BYTES_TO_T_UINT_8(0x0B, 0x5C, 0x34, 0x02, 0x62, 0x9B, 0x08, 0x12), + MBEDTLS_BYTES_TO_T_UINT_8(0x86, 0xCE, 0x9A, 0x6A, 0xEC, 0x75, 0xF6, 0x46), + MBEDTLS_BYTES_TO_T_UINT_8(0x6D, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00), +}; +static const mbedtls_mpi_uint secp521r1_T_6_X[] = { + MBEDTLS_BYTES_TO_T_UINT_8(0xE6, 0x59, 0xF4, 0x78, 0x3C, 0x60, 0xB1, 0x4A), + MBEDTLS_BYTES_TO_T_UINT_8(0x3E, 0x37, 0x84, 0x6A, 0xDC, 0xF2, 0x9A, 0x7D), + MBEDTLS_BYTES_TO_T_UINT_8(0x40, 0x9A, 0x9A, 0x15, 0x36, 0xE0, 0x2B, 0x2D), + MBEDTLS_BYTES_TO_T_UINT_8(0xEC, 0x38, 0x9C, 0x50, 0x3D, 0x1E, 0x37, 0x82), + MBEDTLS_BYTES_TO_T_UINT_8(0xB7, 0x79, 0xF0, 0x92, 0xF2, 0x8B, 0x18, 0x82), + MBEDTLS_BYTES_TO_T_UINT_8(0x17, 0xE0, 0x82, 0x1E, 0x80, 0x82, 0x4B, 0xD7), + MBEDTLS_BYTES_TO_T_UINT_8(0xFA, 0xBB, 0x59, 0x6B, 0x8A, 0x77, 0x41, 0x40), + MBEDTLS_BYTES_TO_T_UINT_8(0xA7, 0xF9, 0xD4, 0xB8, 0x4A, 0x82, 0xCF, 0x40), + MBEDTLS_BYTES_TO_T_UINT_8(0x5D, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00), +}; +static const mbedtls_mpi_uint secp521r1_T_6_Y[] = { + MBEDTLS_BYTES_TO_T_UINT_8(0x1E, 0x8C, 0xC8, 0x9B, 0x72, 0x9E, 0xF7, 0xF9), + MBEDTLS_BYTES_TO_T_UINT_8(0xB8, 0xCE, 0xE9, 0x77, 0x0A, 0x19, 0x59, 0x84), + MBEDTLS_BYTES_TO_T_UINT_8(0x9D, 0xA1, 0x41, 0x6A, 0x72, 0x4B, 0xB4, 0xDC), + MBEDTLS_BYTES_TO_T_UINT_8(0x0B, 0x35, 0x43, 0xE2, 0x8C, 0xBE, 0x0D, 0xE3), + MBEDTLS_BYTES_TO_T_UINT_8(0xC1, 0xEB, 0xAD, 0xF3, 0xA9, 0xA6, 0x68, 0xA1), + MBEDTLS_BYTES_TO_T_UINT_8(0x81, 0x2F, 0xE2, 0x48, 0x0C, 0xDB, 0x1F, 0x42), + MBEDTLS_BYTES_TO_T_UINT_8(0xD1, 0x1E, 0x60, 0x9B, 0x2A, 0xD2, 0xC1, 0x3C), + MBEDTLS_BYTES_TO_T_UINT_8(0xC0, 0x64, 0xB5, 0xD2, 0xF6, 0xF6, 0x6E, 0x22), + MBEDTLS_BYTES_TO_T_UINT_8(0x70, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00), +}; +static const mbedtls_mpi_uint secp521r1_T_7_X[] = { + MBEDTLS_BYTES_TO_T_UINT_8(0xC6, 0x3D, 0x30, 0x78, 0x10, 0x18, 0x41, 0x51), + MBEDTLS_BYTES_TO_T_UINT_8(0x96, 0x1D, 0x1C, 0xE0, 0x6D, 0x83, 0xD1, 0x93), + MBEDTLS_BYTES_TO_T_UINT_8(0x7B, 0x03, 0x0B, 0xF5, 0x2F, 0x6C, 0x04, 0x98), + MBEDTLS_BYTES_TO_T_UINT_8(0x6C, 0x3E, 0xD5, 0xFC, 0x31, 0x5B, 0x3A, 0xEB), + MBEDTLS_BYTES_TO_T_UINT_8(0x50, 0x82, 0x2F, 0xFB, 0xFE, 0xF8, 0x76, 0x39), + MBEDTLS_BYTES_TO_T_UINT_8(0x85, 0x26, 0xDA, 0x9C, 0x36, 0xF5, 0x93, 0xD1), + MBEDTLS_BYTES_TO_T_UINT_8(0x4C, 0xE7, 0x6E, 0xD2, 0x7D, 0x81, 0x09, 0xC6), + MBEDTLS_BYTES_TO_T_UINT_8(0xD3, 0x03, 0xF9, 0x58, 0x48, 0x24, 0xA2, 0xEE), + MBEDTLS_BYTES_TO_T_UINT_8(0xE9, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00), +}; +static const mbedtls_mpi_uint secp521r1_T_7_Y[] = { + MBEDTLS_BYTES_TO_T_UINT_8(0x1B, 0x79, 0x0C, 0x8E, 0x6B, 0x95, 0xF3, 0xC4), + MBEDTLS_BYTES_TO_T_UINT_8(0xF4, 0x10, 0x5C, 0x87, 0x03, 0x39, 0xCF, 0x68), + MBEDTLS_BYTES_TO_T_UINT_8(0xAD, 0xF0, 0xF7, 0xC1, 0x07, 0xA4, 0xF4, 0x3F), + MBEDTLS_BYTES_TO_T_UINT_8(0x32, 0xE8, 0x02, 0x89, 0x65, 0xC4, 0x72, 0x36), + MBEDTLS_BYTES_TO_T_UINT_8(0xB4, 0x88, 0xEA, 0x96, 0x67, 0x0B, 0x5D, 0xDF), + MBEDTLS_BYTES_TO_T_UINT_8(0xA8, 0x75, 0x60, 0xA8, 0xBD, 0x74, 0xDF, 0x68), + MBEDTLS_BYTES_TO_T_UINT_8(0x6E, 0xE5, 0x71, 0x50, 0x67, 0xD0, 0xD2, 0xE6), + MBEDTLS_BYTES_TO_T_UINT_8(0xD5, 0xFC, 0xE5, 0xC7, 0x77, 0xB0, 0x7F, 0x8C), + MBEDTLS_BYTES_TO_T_UINT_8(0xF1, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00), +}; +static const mbedtls_mpi_uint secp521r1_T_8_X[] = { + MBEDTLS_BYTES_TO_T_UINT_8(0x97, 0x86, 0x69, 0xCD, 0x0D, 0x9A, 0xBD, 0x66), + MBEDTLS_BYTES_TO_T_UINT_8(0x58, 0x17, 0xBC, 0xBB, 0x59, 0x85, 0x7D, 0x0E), + MBEDTLS_BYTES_TO_T_UINT_8(0x8D, 0xA8, 0x76, 0xAC, 0x80, 0xA9, 0x72, 0xE0), + MBEDTLS_BYTES_TO_T_UINT_8(0x74, 0x78, 0xC1, 0xE2, 0x4D, 0xAF, 0xF9, 0x3C), + MBEDTLS_BYTES_TO_T_UINT_8(0xAD, 0x97, 0x8E, 0x74, 0xC4, 0x4B, 0xB2, 0x85), + MBEDTLS_BYTES_TO_T_UINT_8(0xEA, 0xD8, 0xF6, 0xF3, 0xAF, 0x2F, 0x52, 0xE5), + MBEDTLS_BYTES_TO_T_UINT_8(0x95, 0x57, 0xF4, 0xCE, 0xEE, 0x43, 0xED, 0x60), + MBEDTLS_BYTES_TO_T_UINT_8(0x7D, 0x46, 0x38, 0xDE, 0x20, 0xFD, 0x59, 0x18), + MBEDTLS_BYTES_TO_T_UINT_8(0xD7, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00), +}; +static const mbedtls_mpi_uint secp521r1_T_8_Y[] = { + MBEDTLS_BYTES_TO_T_UINT_8(0x1C, 0x18, 0xE8, 0x58, 0xB9, 0x76, 0x2C, 0xE6), + MBEDTLS_BYTES_TO_T_UINT_8(0xED, 0x54, 0xE4, 0xFE, 0xC7, 0xBC, 0x31, 0x37), + MBEDTLS_BYTES_TO_T_UINT_8(0xF5, 0xF8, 0x89, 0xEE, 0x70, 0xB5, 0xB0, 0x2C), + MBEDTLS_BYTES_TO_T_UINT_8(0x83, 0x22, 0x26, 0x9A, 0x53, 0xB9, 0x38, 0x0A), + MBEDTLS_BYTES_TO_T_UINT_8(0x74, 0xA7, 0x19, 0x8C, 0x74, 0x7E, 0x88, 0x46), + MBEDTLS_BYTES_TO_T_UINT_8(0xB4, 0xDA, 0x0A, 0xE8, 0xDA, 0xA5, 0xBE, 0x1D), + MBEDTLS_BYTES_TO_T_UINT_8(0x90, 0x5C, 0xF7, 0xB1, 0x0C, 0x72, 0xFB, 0x09), + MBEDTLS_BYTES_TO_T_UINT_8(0x78, 0xE2, 0x23, 0xE7, 0x46, 0xB7, 0xE0, 0x91), + MBEDTLS_BYTES_TO_T_UINT_8(0xC5, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00), +}; +static const mbedtls_mpi_uint secp521r1_T_9_X[] = { + MBEDTLS_BYTES_TO_T_UINT_8(0x3A, 0x36, 0xBC, 0xBD, 0x48, 0x11, 0x8E, 0x72), + MBEDTLS_BYTES_TO_T_UINT_8(0xAB, 0xBB, 0xA1, 0xF7, 0x0B, 0x9E, 0xBF, 0xDF), + MBEDTLS_BYTES_TO_T_UINT_8(0x68, 0x28, 0xE1, 0xA2, 0x8F, 0xFC, 0xFC, 0xD6), + MBEDTLS_BYTES_TO_T_UINT_8(0x81, 0xFE, 0x19, 0x0A, 0xE5, 0xE7, 0x69, 0x39), + MBEDTLS_BYTES_TO_T_UINT_8(0x5E, 0xCD, 0x12, 0xF5, 0xBE, 0xD3, 0x04, 0xF1), + MBEDTLS_BYTES_TO_T_UINT_8(0xF5, 0xA8, 0x0D, 0x81, 0x59, 0xC4, 0x79, 0x98), + MBEDTLS_BYTES_TO_T_UINT_8(0xA3, 0xF3, 0x4B, 0x92, 0x65, 0xC3, 0x31, 0xAD), + MBEDTLS_BYTES_TO_T_UINT_8(0x75, 0xB5, 0x4F, 0x4D, 0x91, 0xD4, 0xE2, 0xB2), + MBEDTLS_BYTES_TO_T_UINT_8(0x51, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00), +}; +static const mbedtls_mpi_uint secp521r1_T_9_Y[] = { + MBEDTLS_BYTES_TO_T_UINT_8(0x72, 0x09, 0x41, 0x79, 0x1D, 0x4D, 0x0D, 0x33), + MBEDTLS_BYTES_TO_T_UINT_8(0xBB, 0x31, 0x18, 0xBA, 0xA0, 0xF2, 0x6E, 0x7E), + MBEDTLS_BYTES_TO_T_UINT_8(0x93, 0x5B, 0x4D, 0x4F, 0xAF, 0xC9, 0x8C, 0xA1), + MBEDTLS_BYTES_TO_T_UINT_8(0x48, 0x99, 0x9C, 0x06, 0x68, 0xDE, 0xD8, 0x29), + MBEDTLS_BYTES_TO_T_UINT_8(0xA0, 0x04, 0xE1, 0xB5, 0x9D, 0x00, 0xBC, 0xB8), + MBEDTLS_BYTES_TO_T_UINT_8(0x61, 0x95, 0x92, 0x8D, 0x72, 0xD3, 0x37, 0x42), + MBEDTLS_BYTES_TO_T_UINT_8(0xAB, 0x4B, 0x27, 0xA2, 0xE8, 0xA4, 0x26, 0xA1), + MBEDTLS_BYTES_TO_T_UINT_8(0x4F, 0x45, 0x9C, 0xA9, 0xCB, 0x9F, 0xBA, 0x85), + MBEDTLS_BYTES_TO_T_UINT_8(0xCB, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00), +}; +static const mbedtls_mpi_uint secp521r1_T_10_X[] = { + MBEDTLS_BYTES_TO_T_UINT_8(0x08, 0x7E, 0x1B, 0x64, 0xF4, 0xE8, 0xA5, 0x55), + MBEDTLS_BYTES_TO_T_UINT_8(0xF7, 0x20, 0xA9, 0xCA, 0xF3, 0x89, 0xE5, 0xE1), + MBEDTLS_BYTES_TO_T_UINT_8(0x83, 0xED, 0xFC, 0xAB, 0xD9, 0x0A, 0xB9, 0x07), + MBEDTLS_BYTES_TO_T_UINT_8(0x08, 0x6F, 0x46, 0x7C, 0xCD, 0x78, 0xFF, 0x05), + MBEDTLS_BYTES_TO_T_UINT_8(0x69, 0xAB, 0x71, 0x5A, 0x94, 0xAB, 0x20, 0x20), + MBEDTLS_BYTES_TO_T_UINT_8(0xC2, 0x2E, 0xEE, 0x87, 0x57, 0x1F, 0xAD, 0xD3), + MBEDTLS_BYTES_TO_T_UINT_8(0x91, 0x4C, 0x3D, 0xFB, 0x7E, 0xA1, 0x8B, 0x07), + MBEDTLS_BYTES_TO_T_UINT_8(0x69, 0xCF, 0x07, 0x86, 0xBA, 0x53, 0x37, 0xCF), + MBEDTLS_BYTES_TO_T_UINT_8(0x38, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00), +}; +static const mbedtls_mpi_uint secp521r1_T_10_Y[] = { + MBEDTLS_BYTES_TO_T_UINT_8(0x00, 0x26, 0xB2, 0xB9, 0xE2, 0x91, 0xE3, 0xB5), + MBEDTLS_BYTES_TO_T_UINT_8(0x79, 0xC9, 0x54, 0x84, 0x08, 0x3D, 0x0B, 0xD2), + MBEDTLS_BYTES_TO_T_UINT_8(0x5D, 0xA8, 0x77, 0x2F, 0x64, 0x45, 0x99, 0x4C), + MBEDTLS_BYTES_TO_T_UINT_8(0x87, 0x96, 0x16, 0x1F, 0xDB, 0x96, 0x28, 0x97), + MBEDTLS_BYTES_TO_T_UINT_8(0x83, 0x2B, 0x8D, 0xFF, 0xA2, 0x4F, 0x55, 0xD3), + MBEDTLS_BYTES_TO_T_UINT_8(0x71, 0xE6, 0x48, 0xBD, 0x99, 0x3D, 0x12, 0x57), + MBEDTLS_BYTES_TO_T_UINT_8(0x3F, 0x84, 0x59, 0xDA, 0xB9, 0xB6, 0x66, 0x12), + MBEDTLS_BYTES_TO_T_UINT_8(0x6D, 0x78, 0x41, 0x92, 0xDF, 0xF4, 0x3F, 0x63), + MBEDTLS_BYTES_TO_T_UINT_8(0x1F, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00), +}; +static const mbedtls_mpi_uint secp521r1_T_11_X[] = { + MBEDTLS_BYTES_TO_T_UINT_8(0x7E, 0x86, 0x6F, 0x4F, 0xBF, 0x67, 0xDF, 0x2F), + MBEDTLS_BYTES_TO_T_UINT_8(0xF2, 0x2B, 0x1E, 0x5F, 0x00, 0xEA, 0xF6, 0x56), + MBEDTLS_BYTES_TO_T_UINT_8(0x90, 0xB9, 0x6A, 0x89, 0xD8, 0xC0, 0xD7, 0xA7), + MBEDTLS_BYTES_TO_T_UINT_8(0xCB, 0x9A, 0x32, 0x23, 0xA0, 0x02, 0x91, 0x58), + MBEDTLS_BYTES_TO_T_UINT_8(0x42, 0x7F, 0x6A, 0x15, 0x64, 0x6A, 0x8B, 0xBB), + MBEDTLS_BYTES_TO_T_UINT_8(0x8A, 0x57, 0x82, 0x58, 0xA9, 0x56, 0xB5, 0xFB), + MBEDTLS_BYTES_TO_T_UINT_8(0xDD, 0x50, 0x92, 0x60, 0xCC, 0x81, 0x24, 0xA8), + MBEDTLS_BYTES_TO_T_UINT_8(0x36, 0x3D, 0xAD, 0xDA, 0xD9, 0x51, 0x3E, 0x57), + MBEDTLS_BYTES_TO_T_UINT_8(0x5D, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00), +}; +static const mbedtls_mpi_uint secp521r1_T_11_Y[] = { + MBEDTLS_BYTES_TO_T_UINT_8(0xEC, 0xFE, 0x8F, 0xB0, 0x0B, 0xDE, 0x2E, 0x7E), + MBEDTLS_BYTES_TO_T_UINT_8(0x79, 0xD2, 0xBE, 0xEF, 0xAC, 0x76, 0x71, 0xA3), + MBEDTLS_BYTES_TO_T_UINT_8(0x55, 0xE8, 0x72, 0x0B, 0xAC, 0xFE, 0xCA, 0x5A), + MBEDTLS_BYTES_TO_T_UINT_8(0xAD, 0x5B, 0xC7, 0xFC, 0xE3, 0x3C, 0x7C, 0x4C), + MBEDTLS_BYTES_TO_T_UINT_8(0xA1, 0x04, 0xA7, 0xB9, 0x9B, 0x93, 0xC0, 0x2F), + MBEDTLS_BYTES_TO_T_UINT_8(0x41, 0x48, 0x4B, 0x8E, 0x32, 0xC5, 0xF0, 0x6B), + MBEDTLS_BYTES_TO_T_UINT_8(0xB0, 0x42, 0x07, 0xC1, 0xF2, 0xF1, 0x72, 0x5B), + MBEDTLS_BYTES_TO_T_UINT_8(0x1E, 0x37, 0x54, 0x9C, 0x88, 0xD2, 0x62, 0xAA), + MBEDTLS_BYTES_TO_T_UINT_8(0xC1, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00), +}; +static const mbedtls_mpi_uint secp521r1_T_12_X[] = { + MBEDTLS_BYTES_TO_T_UINT_8(0xC2, 0x19, 0x8A, 0x89, 0x58, 0xA2, 0x0F, 0xDB), + MBEDTLS_BYTES_TO_T_UINT_8(0x01, 0xCC, 0x4C, 0x97, 0x30, 0x66, 0x34, 0x26), + MBEDTLS_BYTES_TO_T_UINT_8(0x83, 0x6A, 0x1E, 0x1F, 0xDB, 0xC9, 0x5E, 0x13), + MBEDTLS_BYTES_TO_T_UINT_8(0x1B, 0x4D, 0x49, 0xFF, 0x9B, 0x9C, 0xAC, 0x9B), + MBEDTLS_BYTES_TO_T_UINT_8(0xD7, 0xE4, 0x4B, 0xF2, 0xD4, 0x1A, 0xD2, 0x78), + MBEDTLS_BYTES_TO_T_UINT_8(0xCD, 0xDA, 0xE8, 0x61, 0x9F, 0xC8, 0x49, 0x32), + MBEDTLS_BYTES_TO_T_UINT_8(0x51, 0xCB, 0xF2, 0x2D, 0x85, 0xF6, 0x8D, 0x52), + MBEDTLS_BYTES_TO_T_UINT_8(0xB7, 0xC5, 0xCD, 0x2C, 0x79, 0xC6, 0x0E, 0x4F), + MBEDTLS_BYTES_TO_T_UINT_8(0xDB, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00), +}; +static const mbedtls_mpi_uint secp521r1_T_12_Y[] = { + MBEDTLS_BYTES_TO_T_UINT_8(0x73, 0x1D, 0x55, 0x0F, 0xF8, 0x22, 0x9F, 0x78), + MBEDTLS_BYTES_TO_T_UINT_8(0x76, 0x56, 0xBA, 0xE7, 0x57, 0x32, 0xEC, 0x42), + MBEDTLS_BYTES_TO_T_UINT_8(0x65, 0x9A, 0xC6, 0x4C, 0x09, 0xC4, 0x52, 0x3F), + MBEDTLS_BYTES_TO_T_UINT_8(0xB6, 0x1E, 0x6F, 0xF4, 0x7D, 0x27, 0xDD, 0xAF), + MBEDTLS_BYTES_TO_T_UINT_8(0x94, 0x11, 0x16, 0xEC, 0x79, 0x83, 0xAD, 0xAE), + MBEDTLS_BYTES_TO_T_UINT_8(0x46, 0x4E, 0x92, 0x1F, 0x19, 0x7D, 0x65, 0xDC), + MBEDTLS_BYTES_TO_T_UINT_8(0x09, 0xFF, 0x78, 0x15, 0x45, 0x63, 0x32, 0xE4), + MBEDTLS_BYTES_TO_T_UINT_8(0xBF, 0x91, 0xD0, 0x78, 0x58, 0xDA, 0x50, 0x47), + MBEDTLS_BYTES_TO_T_UINT_8(0x73, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00), +}; +static const mbedtls_mpi_uint secp521r1_T_13_X[] = { + MBEDTLS_BYTES_TO_T_UINT_8(0x23, 0xDE, 0x40, 0xF6, 0x41, 0xB4, 0x3B, 0x95), + MBEDTLS_BYTES_TO_T_UINT_8(0xC6, 0x8D, 0xE0, 0xE1, 0xA9, 0xF0, 0x35, 0x5D), + MBEDTLS_BYTES_TO_T_UINT_8(0xE6, 0xD4, 0xBA, 0x7B, 0xCC, 0x1B, 0x3A, 0x32), + MBEDTLS_BYTES_TO_T_UINT_8(0xD0, 0x5A, 0x2E, 0x74, 0x47, 0x14, 0xC3, 0x4D), + MBEDTLS_BYTES_TO_T_UINT_8(0x7D, 0xF0, 0x8B, 0x06, 0x15, 0x8E, 0x0E, 0xCA), + MBEDTLS_BYTES_TO_T_UINT_8(0xB5, 0xD2, 0xEB, 0x97, 0x50, 0x7D, 0x31, 0xFC), + MBEDTLS_BYTES_TO_T_UINT_8(0x42, 0x93, 0x4C, 0xDB, 0x97, 0x79, 0x44, 0xF5), + MBEDTLS_BYTES_TO_T_UINT_8(0x9C, 0xA2, 0xA0, 0x0B, 0xC8, 0x3A, 0x8A, 0xF9), + MBEDTLS_BYTES_TO_T_UINT_8(0x61, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00), +}; +static const mbedtls_mpi_uint secp521r1_T_13_Y[] = { + MBEDTLS_BYTES_TO_T_UINT_8(0x79, 0x50, 0x92, 0x9E, 0x24, 0x1F, 0xCB, 0x4C), + MBEDTLS_BYTES_TO_T_UINT_8(0xD3, 0x16, 0xC9, 0xC5, 0x3D, 0x5A, 0xAF, 0x97), + MBEDTLS_BYTES_TO_T_UINT_8(0x18, 0xE3, 0x97, 0xE4, 0xA8, 0x50, 0xF6, 0x7E), + MBEDTLS_BYTES_TO_T_UINT_8(0x45, 0x57, 0x97, 0x42, 0x78, 0x92, 0x49, 0x0D), + MBEDTLS_BYTES_TO_T_UINT_8(0xA5, 0xEB, 0x62, 0x24, 0xFB, 0x8F, 0x32, 0xCF), + MBEDTLS_BYTES_TO_T_UINT_8(0xF3, 0x0C, 0x36, 0x6E, 0x8F, 0xE8, 0xE8, 0x8E), + MBEDTLS_BYTES_TO_T_UINT_8(0xC2, 0xD3, 0x7C, 0xC7, 0x8D, 0x3F, 0x5C, 0xE1), + MBEDTLS_BYTES_TO_T_UINT_8(0x6A, 0x64, 0x6A, 0x73, 0x10, 0x79, 0xB8, 0x5A), + MBEDTLS_BYTES_TO_T_UINT_8(0xCB, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00), +}; +static const mbedtls_mpi_uint secp521r1_T_14_X[] = { + MBEDTLS_BYTES_TO_T_UINT_8(0x51, 0xF9, 0xEF, 0xA5, 0x20, 0x4A, 0x5C, 0xA1), + MBEDTLS_BYTES_TO_T_UINT_8(0x2F, 0xF3, 0xF4, 0x49, 0x5B, 0x73, 0xAA, 0x1B), + MBEDTLS_BYTES_TO_T_UINT_8(0xC6, 0xF2, 0xEA, 0x0F, 0x00, 0xAD, 0x53, 0xAB), + MBEDTLS_BYTES_TO_T_UINT_8(0x03, 0xB8, 0x66, 0xED, 0xC4, 0x2B, 0x4C, 0x35), + MBEDTLS_BYTES_TO_T_UINT_8(0x3A, 0x2F, 0xC1, 0x9A, 0x37, 0xD2, 0x7F, 0x58), + MBEDTLS_BYTES_TO_T_UINT_8(0x29, 0xA7, 0x81, 0x38, 0x64, 0xC9, 0x37, 0x38), + MBEDTLS_BYTES_TO_T_UINT_8(0xBE, 0x3B, 0x6C, 0x9F, 0x5B, 0xD9, 0x8B, 0x1D), + MBEDTLS_BYTES_TO_T_UINT_8(0xB6, 0x14, 0xD9, 0x08, 0xD8, 0xD2, 0x7E, 0x23), + MBEDTLS_BYTES_TO_T_UINT_8(0x1C, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00), +}; +static const mbedtls_mpi_uint secp521r1_T_14_Y[] = { + MBEDTLS_BYTES_TO_T_UINT_8(0x15, 0x71, 0xE6, 0x3D, 0xD1, 0xB0, 0xE7, 0xCD), + MBEDTLS_BYTES_TO_T_UINT_8(0x5B, 0x81, 0x23, 0xEC, 0x2D, 0x42, 0x45, 0xE6), + MBEDTLS_BYTES_TO_T_UINT_8(0x51, 0x5B, 0x44, 0x6B, 0x89, 0x03, 0x67, 0x28), + MBEDTLS_BYTES_TO_T_UINT_8(0x84, 0x27, 0xAE, 0x80, 0x5A, 0x33, 0xBE, 0x11), + MBEDTLS_BYTES_TO_T_UINT_8(0xE3, 0xB6, 0x64, 0x1A, 0xDF, 0xD3, 0x85, 0x91), + MBEDTLS_BYTES_TO_T_UINT_8(0x67, 0x8C, 0x22, 0xBA, 0xD0, 0xBD, 0xCC, 0xA0), + MBEDTLS_BYTES_TO_T_UINT_8(0xF7, 0x3C, 0x01, 0x3A, 0xFF, 0x9D, 0xC7, 0x6B), + MBEDTLS_BYTES_TO_T_UINT_8(0x0C, 0xC7, 0x64, 0xB4, 0x59, 0x4E, 0x9F, 0x22), + MBEDTLS_BYTES_TO_T_UINT_8(0x85, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00), +}; +static const mbedtls_mpi_uint secp521r1_T_15_X[] = { + MBEDTLS_BYTES_TO_T_UINT_8(0xA1, 0x34, 0x0A, 0x41, 0x94, 0xA8, 0xF2, 0xB7), + MBEDTLS_BYTES_TO_T_UINT_8(0xF6, 0xD4, 0xE4, 0xF0, 0x97, 0x45, 0x6D, 0xCA), + MBEDTLS_BYTES_TO_T_UINT_8(0x8F, 0x1F, 0x4D, 0x6D, 0xFE, 0xA0, 0xC4, 0x84), + MBEDTLS_BYTES_TO_T_UINT_8(0x1D, 0x28, 0x5C, 0x40, 0xBB, 0x65, 0xD4, 0x42), + MBEDTLS_BYTES_TO_T_UINT_8(0x98, 0xA8, 0x87, 0x35, 0x20, 0x3A, 0x89, 0x44), + MBEDTLS_BYTES_TO_T_UINT_8(0xD6, 0xFD, 0x4F, 0xAB, 0x2D, 0xD1, 0xD0, 0xC0), + MBEDTLS_BYTES_TO_T_UINT_8(0x86, 0xE8, 0x00, 0xFC, 0x69, 0x52, 0xF8, 0xD5), + MBEDTLS_BYTES_TO_T_UINT_8(0xE1, 0x9A, 0x99, 0xE1, 0xDC, 0x9C, 0x3F, 0xD9), + MBEDTLS_BYTES_TO_T_UINT_8(0x99, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00), +}; +static const mbedtls_mpi_uint secp521r1_T_15_Y[] = { + MBEDTLS_BYTES_TO_T_UINT_8(0x12, 0x08, 0x98, 0xD9, 0xCA, 0x73, 0xD5, 0xA9), + MBEDTLS_BYTES_TO_T_UINT_8(0xB9, 0x2C, 0xE0, 0xA7, 0x3E, 0x91, 0xD7, 0x87), + MBEDTLS_BYTES_TO_T_UINT_8(0x68, 0x04, 0xB0, 0x54, 0x09, 0xF4, 0x72, 0xB7), + MBEDTLS_BYTES_TO_T_UINT_8(0xC8, 0xEE, 0x28, 0xCC, 0xE8, 0x50, 0x78, 0x20), + MBEDTLS_BYTES_TO_T_UINT_8(0x0D, 0x91, 0x03, 0x76, 0xDB, 0x68, 0x24, 0x77), + MBEDTLS_BYTES_TO_T_UINT_8(0x7A, 0xE0, 0x56, 0xB2, 0x5D, 0x12, 0xD3, 0xB5), + MBEDTLS_BYTES_TO_T_UINT_8(0x0D, 0x42, 0x59, 0x8B, 0xDF, 0x67, 0xB5, 0xBE), + MBEDTLS_BYTES_TO_T_UINT_8(0xD1, 0xCC, 0xE5, 0x31, 0x53, 0x7A, 0x46, 0xB3), + MBEDTLS_BYTES_TO_T_UINT_8(0xDA, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00), +}; +static const mbedtls_mpi_uint secp521r1_T_16_X[] = { + MBEDTLS_BYTES_TO_T_UINT_8(0xCC, 0x8D, 0x59, 0xB5, 0x1B, 0x0F, 0xF4, 0xAF), + MBEDTLS_BYTES_TO_T_UINT_8(0xD9, 0x2F, 0xD1, 0x2C, 0xE0, 0xD8, 0x04, 0xEF), + MBEDTLS_BYTES_TO_T_UINT_8(0xAC, 0xF4, 0xD7, 0xBA, 0xB0, 0xA3, 0x7E, 0xC9), + MBEDTLS_BYTES_TO_T_UINT_8(0xCD, 0x08, 0x51, 0x56, 0xA6, 0x76, 0x67, 0x33), + MBEDTLS_BYTES_TO_T_UINT_8(0x8C, 0x17, 0x63, 0xFE, 0x56, 0xD0, 0xD9, 0x71), + MBEDTLS_BYTES_TO_T_UINT_8(0xAA, 0xF6, 0xC3, 0x14, 0x47, 0xC5, 0xA7, 0x31), + MBEDTLS_BYTES_TO_T_UINT_8(0x72, 0x4C, 0x80, 0xF6, 0xA2, 0x57, 0xA7, 0x5D), + MBEDTLS_BYTES_TO_T_UINT_8(0x11, 0xB3, 0x7B, 0xF8, 0x2F, 0xE1, 0x3E, 0x7B), + MBEDTLS_BYTES_TO_T_UINT_8(0xFA, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00), +}; +static const mbedtls_mpi_uint secp521r1_T_16_Y[] = { + MBEDTLS_BYTES_TO_T_UINT_8(0x26, 0xF4, 0xF9, 0x6B, 0x7B, 0x90, 0xDF, 0x30), + MBEDTLS_BYTES_TO_T_UINT_8(0x1F, 0x82, 0xEF, 0x62, 0xA1, 0x4C, 0x53, 0xCA), + MBEDTLS_BYTES_TO_T_UINT_8(0xE6, 0x99, 0x76, 0x01, 0xBA, 0x8D, 0x0F, 0x54), + MBEDTLS_BYTES_TO_T_UINT_8(0xAF, 0xF4, 0x58, 0x73, 0x56, 0xFE, 0xDD, 0x7C), + MBEDTLS_BYTES_TO_T_UINT_8(0xF6, 0xCE, 0xF9, 0xE8, 0xA1, 0x34, 0xC3, 0x5B), + MBEDTLS_BYTES_TO_T_UINT_8(0x09, 0x5F, 0xDC, 0x6A, 0x3D, 0xD8, 0x7F, 0x42), + MBEDTLS_BYTES_TO_T_UINT_8(0xC2, 0xF4, 0x51, 0xB8, 0xB8, 0xC1, 0xD7, 0x2F), + MBEDTLS_BYTES_TO_T_UINT_8(0xAE, 0x7D, 0x58, 0xD1, 0xD4, 0x1B, 0x4D, 0x23), + MBEDTLS_BYTES_TO_T_UINT_8(0xD3, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00), +}; +static const mbedtls_mpi_uint secp521r1_T_17_X[] = { + MBEDTLS_BYTES_TO_T_UINT_8(0xB9, 0x95, 0xDF, 0x00, 0xD8, 0x21, 0xDE, 0x94), + MBEDTLS_BYTES_TO_T_UINT_8(0xF7, 0x47, 0x3C, 0xC3, 0xB2, 0x01, 0x53, 0x5D), + MBEDTLS_BYTES_TO_T_UINT_8(0x1E, 0x17, 0x43, 0x23, 0xBD, 0xCA, 0x71, 0xF2), + MBEDTLS_BYTES_TO_T_UINT_8(0x70, 0xBA, 0x0F, 0x4F, 0xDC, 0x41, 0x54, 0xBE), + MBEDTLS_BYTES_TO_T_UINT_8(0xD6, 0x39, 0x26, 0x70, 0x53, 0x32, 0x18, 0x11), + MBEDTLS_BYTES_TO_T_UINT_8(0x32, 0x46, 0x07, 0x97, 0x3A, 0x57, 0xE0, 0x01), + MBEDTLS_BYTES_TO_T_UINT_8(0xD6, 0x92, 0x4F, 0xCE, 0xDF, 0x25, 0x80, 0x26), + MBEDTLS_BYTES_TO_T_UINT_8(0x5B, 0x6F, 0x9A, 0x03, 0x05, 0x4B, 0xD1, 0x47), + MBEDTLS_BYTES_TO_T_UINT_8(0x5D, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00), +}; +static const mbedtls_mpi_uint secp521r1_T_17_Y[] = { + MBEDTLS_BYTES_TO_T_UINT_8(0x25, 0x01, 0x72, 0x30, 0x90, 0x17, 0x51, 0x20), + MBEDTLS_BYTES_TO_T_UINT_8(0x74, 0xFB, 0x41, 0x65, 0x5C, 0xB4, 0x2D, 0xEE), + MBEDTLS_BYTES_TO_T_UINT_8(0x66, 0xCD, 0xCD, 0xAA, 0x41, 0xCC, 0xBB, 0x07), + MBEDTLS_BYTES_TO_T_UINT_8(0xD4, 0xCE, 0x08, 0x0A, 0x63, 0xE9, 0xA2, 0xFF), + MBEDTLS_BYTES_TO_T_UINT_8(0x3D, 0xA8, 0x21, 0x7F, 0x7A, 0x5B, 0x9B, 0x81), + MBEDTLS_BYTES_TO_T_UINT_8(0x10, 0x6B, 0x89, 0x44, 0x0A, 0x7F, 0x85, 0x5F), + MBEDTLS_BYTES_TO_T_UINT_8(0x7D, 0xDE, 0x7C, 0x19, 0x5C, 0x65, 0x26, 0x61), + MBEDTLS_BYTES_TO_T_UINT_8(0xD7, 0xAC, 0x62, 0x29, 0x4A, 0xF1, 0xD0, 0x81), + MBEDTLS_BYTES_TO_T_UINT_8(0x38, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00), +}; +static const mbedtls_mpi_uint secp521r1_T_18_X[] = { + MBEDTLS_BYTES_TO_T_UINT_8(0x32, 0x00, 0x40, 0x87, 0xEB, 0xA9, 0x58, 0x56), + MBEDTLS_BYTES_TO_T_UINT_8(0xAF, 0x51, 0x0B, 0xFF, 0x56, 0x35, 0x51, 0xB3), + MBEDTLS_BYTES_TO_T_UINT_8(0x7B, 0xAC, 0x08, 0x94, 0x71, 0xDA, 0xEC, 0x99), + MBEDTLS_BYTES_TO_T_UINT_8(0x5F, 0x4D, 0xC5, 0x7B, 0x31, 0x8B, 0x8D, 0x5E), + MBEDTLS_BYTES_TO_T_UINT_8(0x15, 0x05, 0xF1, 0x3E, 0x9E, 0x8F, 0x17, 0x8F), + MBEDTLS_BYTES_TO_T_UINT_8(0xF0, 0x9C, 0x4B, 0x62, 0x94, 0xAD, 0x49, 0xFC), + MBEDTLS_BYTES_TO_T_UINT_8(0x0F, 0xC9, 0xC6, 0x8F, 0xFD, 0x33, 0x44, 0x34), + MBEDTLS_BYTES_TO_T_UINT_8(0x5F, 0x96, 0x17, 0x7F, 0x42, 0xBE, 0xF7, 0x0D), + MBEDTLS_BYTES_TO_T_UINT_8(0xD4, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00), +}; +static const mbedtls_mpi_uint secp521r1_T_18_Y[] = { + MBEDTLS_BYTES_TO_T_UINT_8(0xFB, 0x29, 0x39, 0x13, 0x08, 0x8D, 0x91, 0x47), + MBEDTLS_BYTES_TO_T_UINT_8(0xF6, 0x79, 0xF9, 0x2F, 0xA9, 0x0A, 0xCF, 0xD6), + MBEDTLS_BYTES_TO_T_UINT_8(0xAB, 0x87, 0x7A, 0xA3, 0x19, 0xAB, 0x55, 0xAD), + MBEDTLS_BYTES_TO_T_UINT_8(0xE8, 0x0B, 0x01, 0xC5, 0x56, 0x19, 0x9D, 0x9E), + MBEDTLS_BYTES_TO_T_UINT_8(0x19, 0xDE, 0x82, 0x3B, 0xEA, 0xD3, 0x0B, 0x8C), + MBEDTLS_BYTES_TO_T_UINT_8(0x65, 0x6B, 0xC7, 0xF3, 0x0F, 0x82, 0x87, 0x6C), + MBEDTLS_BYTES_TO_T_UINT_8(0xD8, 0x2E, 0x23, 0xF2, 0x39, 0x9D, 0x49, 0x70), + MBEDTLS_BYTES_TO_T_UINT_8(0x31, 0xDE, 0xAF, 0x7A, 0xEE, 0xB0, 0xDA, 0x70), + MBEDTLS_BYTES_TO_T_UINT_8(0x63, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00), +}; +static const mbedtls_mpi_uint secp521r1_T_19_X[] = { + MBEDTLS_BYTES_TO_T_UINT_8(0x76, 0x4E, 0x2A, 0x50, 0xFD, 0x8E, 0xC0, 0xEB), + MBEDTLS_BYTES_TO_T_UINT_8(0x52, 0x0F, 0x7C, 0x76, 0x63, 0xD8, 0x89, 0x45), + MBEDTLS_BYTES_TO_T_UINT_8(0xEC, 0x2D, 0xB9, 0x4E, 0xF4, 0xEE, 0x85, 0xCF), + MBEDTLS_BYTES_TO_T_UINT_8(0xC1, 0x95, 0x5C, 0x96, 0x5D, 0xAA, 0x59, 0x0B), + MBEDTLS_BYTES_TO_T_UINT_8(0xCA, 0xDB, 0xD2, 0x68, 0x8E, 0x5A, 0x94, 0x60), + MBEDTLS_BYTES_TO_T_UINT_8(0xD9, 0x02, 0xBF, 0x77, 0x9F, 0xB9, 0x4C, 0xC9), + MBEDTLS_BYTES_TO_T_UINT_8(0x2D, 0xDC, 0xC0, 0xCF, 0x81, 0x1E, 0xC4, 0x6C), + MBEDTLS_BYTES_TO_T_UINT_8(0x2B, 0xCC, 0x37, 0x86, 0xDC, 0xE2, 0x64, 0x72), + MBEDTLS_BYTES_TO_T_UINT_8(0xD5, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00), +}; +static const mbedtls_mpi_uint secp521r1_T_19_Y[] = { + MBEDTLS_BYTES_TO_T_UINT_8(0x2C, 0x30, 0xB1, 0x59, 0x20, 0x9D, 0x98, 0x28), + MBEDTLS_BYTES_TO_T_UINT_8(0x77, 0x0C, 0x9D, 0xF8, 0x20, 0xDC, 0x90, 0xBA), + MBEDTLS_BYTES_TO_T_UINT_8(0xB1, 0xA0, 0xF4, 0xE7, 0x3E, 0x9C, 0x9E, 0xA2), + MBEDTLS_BYTES_TO_T_UINT_8(0xB5, 0x25, 0xA2, 0xB0, 0x54, 0xCD, 0x2E, 0x33), + MBEDTLS_BYTES_TO_T_UINT_8(0xEA, 0xD9, 0x42, 0xB0, 0x80, 0xB0, 0xA3, 0x38), + MBEDTLS_BYTES_TO_T_UINT_8(0x9F, 0xFE, 0x9D, 0x8D, 0x40, 0xFF, 0x27, 0x6D), + MBEDTLS_BYTES_TO_T_UINT_8(0x3A, 0x9D, 0xA6, 0x88, 0x3A, 0x8B, 0x6F, 0x14), + MBEDTLS_BYTES_TO_T_UINT_8(0xB6, 0x39, 0xEE, 0x1F, 0x3F, 0xB1, 0x4F, 0x63), + MBEDTLS_BYTES_TO_T_UINT_8(0x31, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00), +}; +static const mbedtls_mpi_uint secp521r1_T_20_X[] = { + MBEDTLS_BYTES_TO_T_UINT_8(0x6D, 0xD7, 0x9E, 0xFF, 0xD2, 0x35, 0x67, 0x03), + MBEDTLS_BYTES_TO_T_UINT_8(0xCA, 0x4F, 0x15, 0x5D, 0xE3, 0xE8, 0x53, 0x86), + MBEDTLS_BYTES_TO_T_UINT_8(0x92, 0xF7, 0x24, 0x98, 0xA2, 0xCB, 0x11, 0x68), + MBEDTLS_BYTES_TO_T_UINT_8(0x06, 0x2E, 0x25, 0xE1, 0x94, 0xC5, 0xA3, 0x96), + MBEDTLS_BYTES_TO_T_UINT_8(0xE0, 0x82, 0x6E, 0xBA, 0xE7, 0x43, 0x25, 0xB0), + MBEDTLS_BYTES_TO_T_UINT_8(0x18, 0x65, 0xB4, 0x49, 0x73, 0x18, 0x35, 0x54), + MBEDTLS_BYTES_TO_T_UINT_8(0x59, 0x5B, 0xBC, 0x62, 0x86, 0x4C, 0xC1, 0xB7), + MBEDTLS_BYTES_TO_T_UINT_8(0x9B, 0xF2, 0x95, 0xA2, 0xBB, 0xA2, 0x35, 0x65), + MBEDTLS_BYTES_TO_T_UINT_8(0xBF, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00), +}; +static const mbedtls_mpi_uint secp521r1_T_20_Y[] = { + MBEDTLS_BYTES_TO_T_UINT_8(0x72, 0x59, 0x62, 0xB0, 0x4B, 0x1E, 0xB4, 0xD8), + MBEDTLS_BYTES_TO_T_UINT_8(0x0D, 0x55, 0xCE, 0xB0, 0x69, 0xBA, 0x63, 0x10), + MBEDTLS_BYTES_TO_T_UINT_8(0x6E, 0x69, 0x86, 0xDB, 0x34, 0x7D, 0x68, 0x64), + MBEDTLS_BYTES_TO_T_UINT_8(0xDA, 0x06, 0xCA, 0x55, 0x44, 0x36, 0x2B, 0xBA), + MBEDTLS_BYTES_TO_T_UINT_8(0x6C, 0xD4, 0xC4, 0x3D, 0xCD, 0x9E, 0x69, 0xA4), + MBEDTLS_BYTES_TO_T_UINT_8(0x3F, 0x44, 0xE4, 0xBF, 0x31, 0xE6, 0x40, 0x9F), + MBEDTLS_BYTES_TO_T_UINT_8(0x7E, 0x4F, 0xFA, 0x75, 0xE3, 0xFB, 0x97, 0x0E), + MBEDTLS_BYTES_TO_T_UINT_8(0x08, 0xC0, 0xBD, 0x1C, 0x48, 0xB0, 0x26, 0xD0), + MBEDTLS_BYTES_TO_T_UINT_8(0xD2, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00), +}; +static const mbedtls_mpi_uint secp521r1_T_21_X[] = { + MBEDTLS_BYTES_TO_T_UINT_8(0x1C, 0x7B, 0x32, 0xFA, 0xF2, 0x6D, 0x84, 0x8E), + MBEDTLS_BYTES_TO_T_UINT_8(0xA0, 0x21, 0x03, 0x1D, 0x0D, 0x22, 0x55, 0x67), + MBEDTLS_BYTES_TO_T_UINT_8(0x18, 0xF9, 0x42, 0x03, 0x9C, 0xC2, 0xCB, 0xBA), + MBEDTLS_BYTES_TO_T_UINT_8(0xF8, 0xA1, 0x96, 0xD9, 0x9D, 0x11, 0x6F, 0xBE), + MBEDTLS_BYTES_TO_T_UINT_8(0xFF, 0x40, 0x57, 0xEB, 0x40, 0x2D, 0xC0, 0x11), + MBEDTLS_BYTES_TO_T_UINT_8(0x2F, 0x96, 0xBB, 0x4F, 0x2F, 0x23, 0xA8, 0x28), + MBEDTLS_BYTES_TO_T_UINT_8(0x3A, 0x29, 0x85, 0x21, 0xA5, 0x50, 0x62, 0x06), + MBEDTLS_BYTES_TO_T_UINT_8(0xC9, 0x7D, 0x92, 0xCF, 0x87, 0x0C, 0x22, 0xF9), + MBEDTLS_BYTES_TO_T_UINT_8(0xC9, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00), +}; +static const mbedtls_mpi_uint secp521r1_T_21_Y[] = { + MBEDTLS_BYTES_TO_T_UINT_8(0x5A, 0x0E, 0xA5, 0x32, 0x5B, 0xDF, 0x9C, 0xD5), + MBEDTLS_BYTES_TO_T_UINT_8(0x27, 0x96, 0x37, 0x2C, 0x88, 0x35, 0x30, 0xA1), + MBEDTLS_BYTES_TO_T_UINT_8(0x40, 0xB4, 0x69, 0xFF, 0xEB, 0xC6, 0x94, 0x08), + MBEDTLS_BYTES_TO_T_UINT_8(0xC9, 0x55, 0x60, 0xAD, 0xAA, 0x58, 0x14, 0x88), + MBEDTLS_BYTES_TO_T_UINT_8(0x3C, 0xFF, 0xF2, 0xB2, 0xD5, 0xA7, 0xD9, 0x27), + MBEDTLS_BYTES_TO_T_UINT_8(0x2D, 0xAE, 0x54, 0xD2, 0x60, 0x31, 0xF3, 0x15), + MBEDTLS_BYTES_TO_T_UINT_8(0xBB, 0x92, 0x83, 0xE3, 0xF1, 0x42, 0x83, 0x6E), + MBEDTLS_BYTES_TO_T_UINT_8(0x49, 0xD2, 0xC8, 0xB7, 0x76, 0x45, 0x7F, 0x7D), + MBEDTLS_BYTES_TO_T_UINT_8(0x04, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00), +}; +static const mbedtls_mpi_uint secp521r1_T_22_X[] = { + MBEDTLS_BYTES_TO_T_UINT_8(0x4A, 0x11, 0xA4, 0xFB, 0x7A, 0x01, 0xBC, 0xC8), + MBEDTLS_BYTES_TO_T_UINT_8(0xCD, 0x27, 0x73, 0x8D, 0x02, 0x91, 0x27, 0x8E), + MBEDTLS_BYTES_TO_T_UINT_8(0xA4, 0x62, 0xF6, 0xDD, 0x6B, 0xFA, 0x5B, 0xB9), + MBEDTLS_BYTES_TO_T_UINT_8(0xEF, 0xCA, 0xA2, 0x44, 0x2C, 0xF0, 0x28, 0xD8), + MBEDTLS_BYTES_TO_T_UINT_8(0x3C, 0xF1, 0x7A, 0xA2, 0x42, 0x4C, 0x50, 0xC6), + MBEDTLS_BYTES_TO_T_UINT_8(0x2D, 0x83, 0x3E, 0x50, 0xAB, 0x9C, 0xF7, 0x67), + MBEDTLS_BYTES_TO_T_UINT_8(0x1D, 0xED, 0x78, 0xCB, 0x76, 0x69, 0xDA, 0x42), + MBEDTLS_BYTES_TO_T_UINT_8(0xDB, 0x01, 0x1E, 0x43, 0x27, 0x47, 0x6E, 0xDA), + MBEDTLS_BYTES_TO_T_UINT_8(0x94, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00), +}; +static const mbedtls_mpi_uint secp521r1_T_22_Y[] = { + MBEDTLS_BYTES_TO_T_UINT_8(0xD3, 0x4F, 0x54, 0xB9, 0x3E, 0xBD, 0xD5, 0x44), + MBEDTLS_BYTES_TO_T_UINT_8(0xC9, 0x35, 0x40, 0x69, 0x7F, 0x74, 0x9D, 0x32), + MBEDTLS_BYTES_TO_T_UINT_8(0x5A, 0x06, 0x6F, 0x67, 0x68, 0x2B, 0x4D, 0x10), + MBEDTLS_BYTES_TO_T_UINT_8(0xC6, 0x65, 0x41, 0xFC, 0x7C, 0x1E, 0xE8, 0xC8), + MBEDTLS_BYTES_TO_T_UINT_8(0xF2, 0x79, 0x37, 0xAF, 0xFD, 0xD2, 0xDA, 0x4C), + MBEDTLS_BYTES_TO_T_UINT_8(0x33, 0xA8, 0x69, 0x56, 0x62, 0xA4, 0xE4, 0xA3), + MBEDTLS_BYTES_TO_T_UINT_8(0x42, 0x71, 0x73, 0x21, 0x8A, 0x17, 0x81, 0xA2), + MBEDTLS_BYTES_TO_T_UINT_8(0x14, 0x55, 0x8F, 0x7B, 0xB8, 0xAF, 0xF7, 0x86), + MBEDTLS_BYTES_TO_T_UINT_8(0xAA, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00), +}; +static const mbedtls_mpi_uint secp521r1_T_23_X[] = { + MBEDTLS_BYTES_TO_T_UINT_8(0x4B, 0xD1, 0xBD, 0xBE, 0x8C, 0xBC, 0x60, 0x6E), + MBEDTLS_BYTES_TO_T_UINT_8(0x62, 0xA6, 0x57, 0x8C, 0xAE, 0x5C, 0x19, 0xFE), + MBEDTLS_BYTES_TO_T_UINT_8(0x7A, 0x43, 0xE4, 0xD9, 0xD8, 0x7B, 0xE7, 0x41), + MBEDTLS_BYTES_TO_T_UINT_8(0xED, 0xB9, 0xE4, 0x85, 0x7C, 0x2E, 0xFC, 0x20), + MBEDTLS_BYTES_TO_T_UINT_8(0x02, 0x2E, 0x01, 0x2A, 0x6D, 0x56, 0xBE, 0x97), + MBEDTLS_BYTES_TO_T_UINT_8(0x6A, 0x0C, 0x25, 0x9B, 0xAE, 0x86, 0x37, 0x43), + MBEDTLS_BYTES_TO_T_UINT_8(0x4A, 0x22, 0xB3, 0xCB, 0x99, 0x66, 0xB7, 0x9E), + MBEDTLS_BYTES_TO_T_UINT_8(0x56, 0xF7, 0x90, 0xF0, 0x1B, 0x09, 0x27, 0xF7), + MBEDTLS_BYTES_TO_T_UINT_8(0xC8, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00), +}; +static const mbedtls_mpi_uint secp521r1_T_23_Y[] = { + MBEDTLS_BYTES_TO_T_UINT_8(0x1C, 0x16, 0x08, 0xEF, 0x39, 0x64, 0x49, 0x31), + MBEDTLS_BYTES_TO_T_UINT_8(0x08, 0xA0, 0xE3, 0x97, 0xA9, 0x07, 0x54, 0x26), + MBEDTLS_BYTES_TO_T_UINT_8(0xCD, 0xFF, 0xE2, 0x00, 0x07, 0x21, 0x88, 0x20), + MBEDTLS_BYTES_TO_T_UINT_8(0x16, 0xFD, 0x59, 0x53, 0x05, 0x6C, 0x42, 0x27), + MBEDTLS_BYTES_TO_T_UINT_8(0x8F, 0xF7, 0x39, 0x5C, 0x82, 0x36, 0xE8, 0x03), + MBEDTLS_BYTES_TO_T_UINT_8(0x2E, 0x83, 0xA8, 0xE2, 0xA8, 0x43, 0x07, 0x38), + MBEDTLS_BYTES_TO_T_UINT_8(0xE6, 0xAF, 0x2B, 0x79, 0xED, 0xD8, 0x39, 0x87), + MBEDTLS_BYTES_TO_T_UINT_8(0x15, 0x20, 0x91, 0x7A, 0xC4, 0x07, 0xEF, 0x6C), + MBEDTLS_BYTES_TO_T_UINT_8(0x28, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00), +}; +static const mbedtls_mpi_uint secp521r1_T_24_X[] = { + MBEDTLS_BYTES_TO_T_UINT_8(0x6A, 0x10, 0x2F, 0xAA, 0x0C, 0x94, 0x0E, 0x5A), + MBEDTLS_BYTES_TO_T_UINT_8(0xB7, 0x81, 0x87, 0x41, 0x23, 0xEB, 0x55, 0x7C), + MBEDTLS_BYTES_TO_T_UINT_8(0xB8, 0x53, 0xCC, 0x79, 0xB6, 0xEB, 0x6C, 0xCC), + MBEDTLS_BYTES_TO_T_UINT_8(0xF4, 0x77, 0x73, 0x9D, 0xFC, 0x64, 0x6F, 0x7F), + MBEDTLS_BYTES_TO_T_UINT_8(0x3C, 0x40, 0xE3, 0x6D, 0x1C, 0x16, 0x71, 0x15), + MBEDTLS_BYTES_TO_T_UINT_8(0x5A, 0xF4, 0x1B, 0xFF, 0x1C, 0x2F, 0xA5, 0xD7), + MBEDTLS_BYTES_TO_T_UINT_8(0x06, 0x0E, 0x0B, 0x11, 0xF4, 0x8D, 0x93, 0xAF), + MBEDTLS_BYTES_TO_T_UINT_8(0x58, 0xC5, 0x64, 0x6F, 0x24, 0x19, 0xF2, 0x9B), + MBEDTLS_BYTES_TO_T_UINT_8(0x1C, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00), +}; +static const mbedtls_mpi_uint secp521r1_T_24_Y[] = { + MBEDTLS_BYTES_TO_T_UINT_8(0x52, 0xB3, 0xAF, 0xA5, 0x0E, 0x4F, 0x5E, 0xE1), + MBEDTLS_BYTES_TO_T_UINT_8(0x0F, 0x77, 0xCA, 0xF2, 0x6D, 0xC5, 0xF6, 0x9F), + MBEDTLS_BYTES_TO_T_UINT_8(0x90, 0x18, 0x8E, 0x33, 0x68, 0x6C, 0xE8, 0xE0), + MBEDTLS_BYTES_TO_T_UINT_8(0xFC, 0x8B, 0x80, 0x90, 0x19, 0x7F, 0x90, 0x96), + MBEDTLS_BYTES_TO_T_UINT_8(0x5B, 0x80, 0x6B, 0x68, 0xE2, 0x7D, 0xD4, 0xD0), + MBEDTLS_BYTES_TO_T_UINT_8(0x2A, 0xC1, 0x67, 0xB3, 0x72, 0xCB, 0xBF, 0x2F), + MBEDTLS_BYTES_TO_T_UINT_8(0x4F, 0xD5, 0xD3, 0x1D, 0x14, 0x58, 0x0A, 0x80), + MBEDTLS_BYTES_TO_T_UINT_8(0x79, 0x7A, 0x65, 0x98, 0xB3, 0x07, 0x4B, 0x2F), + MBEDTLS_BYTES_TO_T_UINT_8(0xF3, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00), +}; +static const mbedtls_mpi_uint secp521r1_T_25_X[] = { + MBEDTLS_BYTES_TO_T_UINT_8(0x2A, 0x87, 0x0F, 0x5F, 0xCF, 0xA2, 0x01, 0x08), + MBEDTLS_BYTES_TO_T_UINT_8(0x0C, 0xC9, 0xC8, 0x6E, 0x35, 0x87, 0xA5, 0x67), + MBEDTLS_BYTES_TO_T_UINT_8(0x94, 0x3E, 0x91, 0xA0, 0xAB, 0x24, 0x1E, 0xF2), + MBEDTLS_BYTES_TO_T_UINT_8(0xB9, 0xBC, 0x02, 0x35, 0x70, 0xC1, 0x5F, 0x98), + MBEDTLS_BYTES_TO_T_UINT_8(0x26, 0x59, 0xA0, 0x50, 0x04, 0x80, 0x52, 0x85), + MBEDTLS_BYTES_TO_T_UINT_8(0xF8, 0x56, 0x6E, 0x42, 0x8F, 0x8C, 0x91, 0x65), + MBEDTLS_BYTES_TO_T_UINT_8(0xAC, 0xA2, 0xCB, 0xA5, 0xDE, 0x14, 0x24, 0x38), + MBEDTLS_BYTES_TO_T_UINT_8(0x00, 0xCB, 0x74, 0x28, 0xE6, 0xA7, 0xE7, 0xC3), + MBEDTLS_BYTES_TO_T_UINT_8(0x5F, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00), +}; +static const mbedtls_mpi_uint secp521r1_T_25_Y[] = { + MBEDTLS_BYTES_TO_T_UINT_8(0x35, 0x73, 0xA8, 0x8F, 0x9E, 0x0E, 0x63, 0x96), + MBEDTLS_BYTES_TO_T_UINT_8(0xC8, 0x1B, 0x77, 0xC7, 0xC1, 0x38, 0xF9, 0xDC), + MBEDTLS_BYTES_TO_T_UINT_8(0xD8, 0x3C, 0xCF, 0xA8, 0x7A, 0xD7, 0xF3, 0xC4), + MBEDTLS_BYTES_TO_T_UINT_8(0xDD, 0x5F, 0x9A, 0xC9, 0xAD, 0xE9, 0x1A, 0x93), + MBEDTLS_BYTES_TO_T_UINT_8(0xFC, 0xCF, 0x2B, 0x5E, 0xD5, 0x81, 0x95, 0xA8), + MBEDTLS_BYTES_TO_T_UINT_8(0x19, 0x88, 0x75, 0x29, 0x1F, 0xC7, 0xC7, 0xD0), + MBEDTLS_BYTES_TO_T_UINT_8(0xD8, 0xA9, 0x5A, 0x4D, 0x63, 0x95, 0xF9, 0x4E), + MBEDTLS_BYTES_TO_T_UINT_8(0xEB, 0xCD, 0x04, 0x8F, 0xCD, 0x91, 0xDE, 0xC6), + MBEDTLS_BYTES_TO_T_UINT_8(0x71, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00), +}; +static const mbedtls_mpi_uint secp521r1_T_26_X[] = { + MBEDTLS_BYTES_TO_T_UINT_8(0x88, 0xD4, 0xFD, 0x25, 0x11, 0x99, 0x6E, 0xEA), + MBEDTLS_BYTES_TO_T_UINT_8(0xB0, 0x83, 0x01, 0x3D, 0xFB, 0x56, 0xA5, 0x4E), + MBEDTLS_BYTES_TO_T_UINT_8(0xC2, 0x3A, 0xDC, 0x74, 0xC2, 0xD7, 0xCF, 0xE8), + MBEDTLS_BYTES_TO_T_UINT_8(0x8F, 0xBD, 0xF1, 0xDD, 0xA3, 0x07, 0x03, 0xE2), + MBEDTLS_BYTES_TO_T_UINT_8(0x7B, 0xBE, 0xE9, 0x2E, 0x58, 0x84, 0x66, 0xFC), + MBEDTLS_BYTES_TO_T_UINT_8(0x71, 0x20, 0x78, 0x37, 0x79, 0x0B, 0xA6, 0x64), + MBEDTLS_BYTES_TO_T_UINT_8(0xE3, 0xF2, 0xAC, 0x65, 0xC8, 0xC9, 0x2F, 0x61), + MBEDTLS_BYTES_TO_T_UINT_8(0x26, 0x93, 0xE5, 0x0D, 0x0C, 0xC6, 0xB8, 0xCB), + MBEDTLS_BYTES_TO_T_UINT_8(0x9C, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00), +}; +static const mbedtls_mpi_uint secp521r1_T_26_Y[] = { + MBEDTLS_BYTES_TO_T_UINT_8(0x69, 0xAD, 0x5C, 0x19, 0x12, 0x61, 0x0E, 0x25), + MBEDTLS_BYTES_TO_T_UINT_8(0x39, 0x4F, 0x0B, 0x1F, 0x49, 0x7E, 0xCD, 0x81), + MBEDTLS_BYTES_TO_T_UINT_8(0x46, 0x2E, 0x30, 0x61, 0xDB, 0x08, 0x68, 0x9B), + MBEDTLS_BYTES_TO_T_UINT_8(0x41, 0x78, 0xAF, 0xB3, 0x08, 0xC1, 0x69, 0xE5), + MBEDTLS_BYTES_TO_T_UINT_8(0xC4, 0x5F, 0x5D, 0xC1, 0x57, 0x6F, 0xD8, 0x34), + MBEDTLS_BYTES_TO_T_UINT_8(0x38, 0xD3, 0x6A, 0xF7, 0xFD, 0x86, 0xE5, 0xB3), + MBEDTLS_BYTES_TO_T_UINT_8(0xA8, 0x63, 0xBD, 0x70, 0x7B, 0x47, 0xE8, 0x6D), + MBEDTLS_BYTES_TO_T_UINT_8(0x18, 0x62, 0xC8, 0x7E, 0x9D, 0x11, 0x2B, 0xA5), + MBEDTLS_BYTES_TO_T_UINT_8(0xB6, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00), +}; +static const mbedtls_mpi_uint secp521r1_T_27_X[] = { + MBEDTLS_BYTES_TO_T_UINT_8(0xE2, 0x84, 0xFD, 0xD5, 0x9A, 0x56, 0x7F, 0x5C), + MBEDTLS_BYTES_TO_T_UINT_8(0x7C, 0xBB, 0xA4, 0x6F, 0x12, 0x6E, 0x4D, 0xF8), + MBEDTLS_BYTES_TO_T_UINT_8(0x1D, 0x08, 0xA1, 0x82, 0x9C, 0x62, 0x74, 0x7B), + MBEDTLS_BYTES_TO_T_UINT_8(0x9E, 0x58, 0x22, 0x05, 0x1D, 0x15, 0x35, 0x79), + MBEDTLS_BYTES_TO_T_UINT_8(0x9A, 0x88, 0xCF, 0x5C, 0x05, 0x78, 0xFB, 0x94), + MBEDTLS_BYTES_TO_T_UINT_8(0xAC, 0x6B, 0x2F, 0x79, 0x09, 0x73, 0x67, 0xEC), + MBEDTLS_BYTES_TO_T_UINT_8(0xD8, 0xA0, 0x80, 0xD8, 0xE8, 0xEC, 0xFB, 0x42), + MBEDTLS_BYTES_TO_T_UINT_8(0xF5, 0xE7, 0x0B, 0xB7, 0x81, 0x48, 0x7B, 0xD9), + MBEDTLS_BYTES_TO_T_UINT_8(0xE3, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00), +}; +static const mbedtls_mpi_uint secp521r1_T_27_Y[] = { + MBEDTLS_BYTES_TO_T_UINT_8(0xE8, 0x53, 0xA9, 0xED, 0x61, 0x92, 0xD7, 0x85), + MBEDTLS_BYTES_TO_T_UINT_8(0x26, 0x49, 0xD9, 0x5D, 0x9B, 0x4E, 0x89, 0x35), + MBEDTLS_BYTES_TO_T_UINT_8(0xB8, 0x12, 0xEB, 0x9A, 0xC9, 0xCB, 0xC1, 0x95), + MBEDTLS_BYTES_TO_T_UINT_8(0x35, 0xDC, 0x95, 0x16, 0xFE, 0x29, 0x70, 0x01), + MBEDTLS_BYTES_TO_T_UINT_8(0x64, 0x33, 0xB1, 0xD6, 0x78, 0xB9, 0xE2, 0x36), + MBEDTLS_BYTES_TO_T_UINT_8(0x34, 0xCE, 0x88, 0xC3, 0xFD, 0x7A, 0x6B, 0xB8), + MBEDTLS_BYTES_TO_T_UINT_8(0x40, 0x1E, 0x50, 0x1E, 0xAF, 0xB1, 0x25, 0x2D), + MBEDTLS_BYTES_TO_T_UINT_8(0xC1, 0xE7, 0xD7, 0xD5, 0xBD, 0x7A, 0x12, 0xF9), + MBEDTLS_BYTES_TO_T_UINT_8(0x31, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00), +}; +static const mbedtls_mpi_uint secp521r1_T_28_X[] = { + MBEDTLS_BYTES_TO_T_UINT_8(0x22, 0xAA, 0xA2, 0x80, 0x5D, 0x8F, 0xCD, 0xC8), + MBEDTLS_BYTES_TO_T_UINT_8(0x48, 0x39, 0x79, 0x64, 0xA1, 0x67, 0x3C, 0xB7), + MBEDTLS_BYTES_TO_T_UINT_8(0x3D, 0xC7, 0x49, 0xFF, 0x7F, 0xAC, 0xAB, 0x55), + MBEDTLS_BYTES_TO_T_UINT_8(0x81, 0x54, 0x3E, 0x83, 0xF0, 0x3D, 0xBC, 0xB5), + MBEDTLS_BYTES_TO_T_UINT_8(0x87, 0x92, 0x4A, 0x38, 0x42, 0x8A, 0xAB, 0xF6), + MBEDTLS_BYTES_TO_T_UINT_8(0xE7, 0x0B, 0x4F, 0xEE, 0x9E, 0x92, 0xA5, 0xBE), + MBEDTLS_BYTES_TO_T_UINT_8(0xBA, 0xDD, 0x19, 0x96, 0xF2, 0xF0, 0x6B, 0x2E), + MBEDTLS_BYTES_TO_T_UINT_8(0xBE, 0xFC, 0xDD, 0xB2, 0x8A, 0xE5, 0x4C, 0x22), + MBEDTLS_BYTES_TO_T_UINT_8(0xD4, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00), +}; +static const mbedtls_mpi_uint secp521r1_T_28_Y[] = { + MBEDTLS_BYTES_TO_T_UINT_8(0xB7, 0x06, 0x49, 0xAC, 0x99, 0x7E, 0xF8, 0x12), + MBEDTLS_BYTES_TO_T_UINT_8(0x76, 0xC8, 0x01, 0x51, 0xEA, 0xF6, 0x52, 0xE7), + MBEDTLS_BYTES_TO_T_UINT_8(0x43, 0x89, 0x66, 0x2B, 0x1F, 0x9B, 0x2A, 0xA3), + MBEDTLS_BYTES_TO_T_UINT_8(0xDF, 0x0F, 0x95, 0x07, 0x2B, 0x6C, 0x6E, 0x9E), + MBEDTLS_BYTES_TO_T_UINT_8(0x24, 0xC3, 0xB4, 0xBB, 0x91, 0x1F, 0xA3, 0x72), + MBEDTLS_BYTES_TO_T_UINT_8(0x5F, 0x6E, 0x54, 0x28, 0x7B, 0x9C, 0x79, 0x2E), + MBEDTLS_BYTES_TO_T_UINT_8(0x03, 0x45, 0xFF, 0xA6, 0xDA, 0xA2, 0x83, 0x71), + MBEDTLS_BYTES_TO_T_UINT_8(0xEB, 0xDE, 0x8F, 0x17, 0x37, 0x82, 0xCB, 0xE2), + MBEDTLS_BYTES_TO_T_UINT_8(0x30, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00), +}; +static const mbedtls_mpi_uint secp521r1_T_29_X[] = { + MBEDTLS_BYTES_TO_T_UINT_8(0xD8, 0x94, 0x3F, 0x26, 0xC9, 0x1D, 0xD9, 0xAE), + MBEDTLS_BYTES_TO_T_UINT_8(0x09, 0x97, 0x28, 0x20, 0xCD, 0xC1, 0xF3, 0x40), + MBEDTLS_BYTES_TO_T_UINT_8(0x95, 0xC9, 0xB5, 0x60, 0x9B, 0x1E, 0xDC, 0x74), + MBEDTLS_BYTES_TO_T_UINT_8(0x5B, 0xB9, 0x5B, 0x7D, 0xA0, 0xB2, 0x8C, 0xF0), + MBEDTLS_BYTES_TO_T_UINT_8(0x33, 0xD1, 0x42, 0xE6, 0x39, 0x33, 0x6D, 0xBB), + MBEDTLS_BYTES_TO_T_UINT_8(0x5D, 0xC0, 0xFC, 0xD2, 0x14, 0x5D, 0x3E, 0x3C), + MBEDTLS_BYTES_TO_T_UINT_8(0x78, 0x4A, 0x3E, 0x40, 0x16, 0x93, 0x15, 0xCF), + MBEDTLS_BYTES_TO_T_UINT_8(0xFA, 0x24, 0xC1, 0x27, 0x27, 0xE5, 0x4B, 0xD8), + MBEDTLS_BYTES_TO_T_UINT_8(0xD4, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00), +}; +static const mbedtls_mpi_uint secp521r1_T_29_Y[] = { + MBEDTLS_BYTES_TO_T_UINT_8(0x1D, 0x50, 0xD8, 0xBC, 0xC1, 0x46, 0x22, 0xBB), + MBEDTLS_BYTES_TO_T_UINT_8(0xAD, 0x0E, 0x60, 0xA1, 0xB3, 0x50, 0xD4, 0x86), + MBEDTLS_BYTES_TO_T_UINT_8(0x80, 0xB1, 0x26, 0xB6, 0x6D, 0x47, 0x5A, 0x6F), + MBEDTLS_BYTES_TO_T_UINT_8(0x45, 0xAC, 0x11, 0x35, 0x3E, 0xB9, 0xF4, 0x01), + MBEDTLS_BYTES_TO_T_UINT_8(0x58, 0x97, 0xFA, 0xBB, 0x6B, 0x39, 0x13, 0xD8), + MBEDTLS_BYTES_TO_T_UINT_8(0x15, 0x7B, 0x34, 0x12, 0x75, 0x8E, 0x9B, 0xC6), + MBEDTLS_BYTES_TO_T_UINT_8(0x2C, 0x9E, 0xCD, 0x29, 0xB6, 0xEF, 0x8D, 0x10), + MBEDTLS_BYTES_TO_T_UINT_8(0x47, 0xAC, 0xE9, 0x25, 0x27, 0xBB, 0x78, 0x47), + MBEDTLS_BYTES_TO_T_UINT_8(0x2F, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00), +}; +static const mbedtls_mpi_uint secp521r1_T_30_X[] = { + MBEDTLS_BYTES_TO_T_UINT_8(0x30, 0x7A, 0xA8, 0xD3, 0xE3, 0x66, 0xE5, 0x66), + MBEDTLS_BYTES_TO_T_UINT_8(0x2F, 0x4C, 0xC4, 0x2C, 0x76, 0x81, 0x50, 0x32), + MBEDTLS_BYTES_TO_T_UINT_8(0xEE, 0x71, 0x08, 0xB8, 0x52, 0x7C, 0xAF, 0xDC), + MBEDTLS_BYTES_TO_T_UINT_8(0x45, 0x59, 0x24, 0xDD, 0xFB, 0x2F, 0xD0, 0xDA), + MBEDTLS_BYTES_TO_T_UINT_8(0xB7, 0xCD, 0x56, 0xE9, 0xAC, 0x91, 0xE6, 0xB9), + MBEDTLS_BYTES_TO_T_UINT_8(0xE5, 0x64, 0x20, 0xC6, 0x9F, 0xE4, 0xEF, 0xDF), + MBEDTLS_BYTES_TO_T_UINT_8(0x6D, 0x2C, 0x8F, 0x8C, 0x97, 0xF6, 0x22, 0xC3), + MBEDTLS_BYTES_TO_T_UINT_8(0xAC, 0xF4, 0x88, 0xAA, 0xA8, 0xD7, 0xA5, 0x68), + MBEDTLS_BYTES_TO_T_UINT_8(0xDE, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00), +}; +static const mbedtls_mpi_uint secp521r1_T_30_Y[] = { + MBEDTLS_BYTES_TO_T_UINT_8(0x21, 0x6C, 0xAE, 0x83, 0xB1, 0x55, 0x55, 0xEE), + MBEDTLS_BYTES_TO_T_UINT_8(0xB0, 0x67, 0x84, 0x47, 0x7C, 0x83, 0x5C, 0x89), + MBEDTLS_BYTES_TO_T_UINT_8(0x5B, 0x10, 0x4D, 0xDD, 0x30, 0x60, 0xB0, 0xE6), + MBEDTLS_BYTES_TO_T_UINT_8(0x59, 0xA7, 0x36, 0x76, 0x24, 0x32, 0x9F, 0x9D), + MBEDTLS_BYTES_TO_T_UINT_8(0xDD, 0x42, 0x81, 0xFB, 0xA4, 0x2E, 0x13, 0x68), + MBEDTLS_BYTES_TO_T_UINT_8(0x87, 0x94, 0x91, 0xFF, 0x99, 0xA0, 0x09, 0x61), + MBEDTLS_BYTES_TO_T_UINT_8(0x5D, 0x83, 0xA1, 0x76, 0xAF, 0x37, 0x5C, 0x77), + MBEDTLS_BYTES_TO_T_UINT_8(0x1E, 0xA8, 0x04, 0x86, 0xC4, 0xA9, 0x79, 0x42), + MBEDTLS_BYTES_TO_T_UINT_8(0x93, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00), +}; +static const mbedtls_mpi_uint secp521r1_T_31_X[] = { + MBEDTLS_BYTES_TO_T_UINT_8(0xB6, 0x8C, 0xC2, 0x34, 0xFB, 0x83, 0x28, 0x27), + MBEDTLS_BYTES_TO_T_UINT_8(0xA4, 0x03, 0x7D, 0x5E, 0x9E, 0x0E, 0xB0, 0x22), + MBEDTLS_BYTES_TO_T_UINT_8(0xA2, 0x02, 0x46, 0x7F, 0xB9, 0xAC, 0xBB, 0x23), + MBEDTLS_BYTES_TO_T_UINT_8(0x06, 0xED, 0x48, 0xC2, 0x96, 0x4D, 0x56, 0x27), + MBEDTLS_BYTES_TO_T_UINT_8(0x44, 0xB5, 0xC5, 0xD1, 0xE6, 0x1C, 0x7E, 0x9B), + MBEDTLS_BYTES_TO_T_UINT_8(0x92, 0x2E, 0x18, 0x71, 0x2D, 0x7B, 0xD7, 0xB3), + MBEDTLS_BYTES_TO_T_UINT_8(0xAB, 0x46, 0x9D, 0xDE, 0xAA, 0x78, 0x8E, 0xB1), + MBEDTLS_BYTES_TO_T_UINT_8(0x4D, 0xD7, 0x69, 0x2E, 0xE1, 0xD9, 0x48, 0xDE), + MBEDTLS_BYTES_TO_T_UINT_8(0xFB, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00), +}; +static const mbedtls_mpi_uint secp521r1_T_31_Y[] = { + MBEDTLS_BYTES_TO_T_UINT_8(0xAF, 0xFF, 0x9E, 0x09, 0x22, 0x22, 0xE6, 0x8D), + MBEDTLS_BYTES_TO_T_UINT_8(0x6C, 0x14, 0x28, 0x13, 0x1B, 0x62, 0x12, 0x22), + MBEDTLS_BYTES_TO_T_UINT_8(0xCC, 0x7F, 0x67, 0x03, 0xB0, 0xC0, 0xF3, 0x05), + MBEDTLS_BYTES_TO_T_UINT_8(0xC0, 0xC3, 0x0F, 0xFB, 0x25, 0x48, 0x3E, 0xF4), + MBEDTLS_BYTES_TO_T_UINT_8(0x0B, 0x6E, 0x53, 0x98, 0x36, 0xB3, 0xD3, 0x94), + MBEDTLS_BYTES_TO_T_UINT_8(0xEB, 0x81, 0x54, 0x22, 0xA4, 0xCC, 0xC1, 0x22), + MBEDTLS_BYTES_TO_T_UINT_8(0xF5, 0xBA, 0xFC, 0xA9, 0xDF, 0x68, 0x86, 0x2B), + MBEDTLS_BYTES_TO_T_UINT_8(0x71, 0x92, 0x0E, 0xC3, 0xF2, 0x58, 0xE8, 0x51), + MBEDTLS_BYTES_TO_T_UINT_8(0xE9, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00), +}; +static const mbedtls_ecp_point secp521r1_T[32] = { + ECP_POINT_INIT_XY_Z1(secp521r1_T_0_X, secp521r1_T_0_Y), + ECP_POINT_INIT_XY_Z0(secp521r1_T_1_X, secp521r1_T_1_Y), + ECP_POINT_INIT_XY_Z0(secp521r1_T_2_X, secp521r1_T_2_Y), + ECP_POINT_INIT_XY_Z0(secp521r1_T_3_X, secp521r1_T_3_Y), + ECP_POINT_INIT_XY_Z0(secp521r1_T_4_X, secp521r1_T_4_Y), + ECP_POINT_INIT_XY_Z0(secp521r1_T_5_X, secp521r1_T_5_Y), + ECP_POINT_INIT_XY_Z0(secp521r1_T_6_X, secp521r1_T_6_Y), + ECP_POINT_INIT_XY_Z0(secp521r1_T_7_X, secp521r1_T_7_Y), + ECP_POINT_INIT_XY_Z0(secp521r1_T_8_X, secp521r1_T_8_Y), + ECP_POINT_INIT_XY_Z0(secp521r1_T_9_X, secp521r1_T_9_Y), + ECP_POINT_INIT_XY_Z0(secp521r1_T_10_X, secp521r1_T_10_Y), + ECP_POINT_INIT_XY_Z0(secp521r1_T_11_X, secp521r1_T_11_Y), + ECP_POINT_INIT_XY_Z0(secp521r1_T_12_X, secp521r1_T_12_Y), + ECP_POINT_INIT_XY_Z0(secp521r1_T_13_X, secp521r1_T_13_Y), + ECP_POINT_INIT_XY_Z0(secp521r1_T_14_X, secp521r1_T_14_Y), + ECP_POINT_INIT_XY_Z0(secp521r1_T_15_X, secp521r1_T_15_Y), + ECP_POINT_INIT_XY_Z0(secp521r1_T_16_X, secp521r1_T_16_Y), + ECP_POINT_INIT_XY_Z0(secp521r1_T_17_X, secp521r1_T_17_Y), + ECP_POINT_INIT_XY_Z0(secp521r1_T_18_X, secp521r1_T_18_Y), + ECP_POINT_INIT_XY_Z0(secp521r1_T_19_X, secp521r1_T_19_Y), + ECP_POINT_INIT_XY_Z0(secp521r1_T_20_X, secp521r1_T_20_Y), + ECP_POINT_INIT_XY_Z0(secp521r1_T_21_X, secp521r1_T_21_Y), + ECP_POINT_INIT_XY_Z0(secp521r1_T_22_X, secp521r1_T_22_Y), + ECP_POINT_INIT_XY_Z0(secp521r1_T_23_X, secp521r1_T_23_Y), + ECP_POINT_INIT_XY_Z0(secp521r1_T_24_X, secp521r1_T_24_Y), + ECP_POINT_INIT_XY_Z0(secp521r1_T_25_X, secp521r1_T_25_Y), + ECP_POINT_INIT_XY_Z0(secp521r1_T_26_X, secp521r1_T_26_Y), + ECP_POINT_INIT_XY_Z0(secp521r1_T_27_X, secp521r1_T_27_Y), + ECP_POINT_INIT_XY_Z0(secp521r1_T_28_X, secp521r1_T_28_Y), + ECP_POINT_INIT_XY_Z0(secp521r1_T_29_X, secp521r1_T_29_Y), + ECP_POINT_INIT_XY_Z0(secp521r1_T_30_X, secp521r1_T_30_Y), + ECP_POINT_INIT_XY_Z0(secp521r1_T_31_X, secp521r1_T_31_Y), +}; +#else +#define secp521r1_T NULL +#endif +#endif /* MBEDTLS_ECP_DP_SECP521R1_ENABLED */ + +#if defined(MBEDTLS_ECP_DP_SECP192K1_ENABLED) +static const mbedtls_mpi_uint secp192k1_p[] = { + MBEDTLS_BYTES_TO_T_UINT_8(0x37, 0xEE, 0xFF, 0xFF, 0xFE, 0xFF, 0xFF, 0xFF), + MBEDTLS_BYTES_TO_T_UINT_8(0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF), + MBEDTLS_BYTES_TO_T_UINT_8(0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF), +}; +static const mbedtls_mpi_uint secp192k1_a[] = { + MBEDTLS_BYTES_TO_T_UINT_2(0x00, 0x00), +}; +static const mbedtls_mpi_uint secp192k1_b[] = { + MBEDTLS_BYTES_TO_T_UINT_2(0x03, 0x00), +}; +static const mbedtls_mpi_uint secp192k1_gx[] = { + MBEDTLS_BYTES_TO_T_UINT_8(0x7D, 0x6C, 0xE0, 0xEA, 0xB1, 0xD1, 0xA5, 0x1D), + MBEDTLS_BYTES_TO_T_UINT_8(0x34, 0xF4, 0xB7, 0x80, 0x02, 0x7D, 0xB0, 0x26), + MBEDTLS_BYTES_TO_T_UINT_8(0xAE, 0xE9, 0x57, 0xC0, 0x0E, 0xF1, 0x4F, 0xDB), +}; +static const mbedtls_mpi_uint secp192k1_gy[] = { + MBEDTLS_BYTES_TO_T_UINT_8(0x9D, 0x2F, 0x5E, 0xD9, 0x88, 0xAA, 0x82, 0x40), + MBEDTLS_BYTES_TO_T_UINT_8(0x34, 0x86, 0xBE, 0x15, 0xD0, 0x63, 0x41, 0x84), + MBEDTLS_BYTES_TO_T_UINT_8(0xA7, 0x28, 0x56, 0x9C, 0x6D, 0x2F, 0x2F, 0x9B), +}; +static const mbedtls_mpi_uint secp192k1_n[] = { + MBEDTLS_BYTES_TO_T_UINT_8(0x8D, 0xFD, 0xDE, 0x74, 0x6A, 0x46, 0x69, 0x0F), + MBEDTLS_BYTES_TO_T_UINT_8(0x17, 0xFC, 0xF2, 0x26, 0xFE, 0xFF, 0xFF, 0xFF), + MBEDTLS_BYTES_TO_T_UINT_8(0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF), +}; + +#if MBEDTLS_ECP_FIXED_POINT_OPTIM == 1 +static const mbedtls_mpi_uint secp192k1_T_0_X[] = { + MBEDTLS_BYTES_TO_T_UINT_8(0x7D, 0x6C, 0xE0, 0xEA, 0xB1, 0xD1, 0xA5, 0x1D), + MBEDTLS_BYTES_TO_T_UINT_8(0x34, 0xF4, 0xB7, 0x80, 0x02, 0x7D, 0xB0, 0x26), + MBEDTLS_BYTES_TO_T_UINT_8(0xAE, 0xE9, 0x57, 0xC0, 0x0E, 0xF1, 0x4F, 0xDB), +}; +static const mbedtls_mpi_uint secp192k1_T_0_Y[] = { + MBEDTLS_BYTES_TO_T_UINT_8(0x9D, 0x2F, 0x5E, 0xD9, 0x88, 0xAA, 0x82, 0x40), + MBEDTLS_BYTES_TO_T_UINT_8(0x34, 0x86, 0xBE, 0x15, 0xD0, 0x63, 0x41, 0x84), + MBEDTLS_BYTES_TO_T_UINT_8(0xA7, 0x28, 0x56, 0x9C, 0x6D, 0x2F, 0x2F, 0x9B), +}; +static const mbedtls_mpi_uint secp192k1_T_1_X[] = { + MBEDTLS_BYTES_TO_T_UINT_8(0x6F, 0x77, 0x3D, 0x0D, 0x85, 0x48, 0xA8, 0xA9), + MBEDTLS_BYTES_TO_T_UINT_8(0x62, 0x07, 0xDF, 0x1D, 0xB3, 0xB3, 0x01, 0x54), + MBEDTLS_BYTES_TO_T_UINT_8(0x05, 0x86, 0xF6, 0xAF, 0x19, 0x2A, 0x88, 0x2E), +}; +static const mbedtls_mpi_uint secp192k1_T_1_Y[] = { + MBEDTLS_BYTES_TO_T_UINT_8(0x33, 0x90, 0xB6, 0x2F, 0x48, 0x36, 0x4C, 0x5B), + MBEDTLS_BYTES_TO_T_UINT_8(0xDB, 0x11, 0x14, 0xA6, 0xCB, 0xBA, 0x15, 0xD9), + MBEDTLS_BYTES_TO_T_UINT_8(0x7E, 0xB0, 0xF2, 0xD4, 0xC9, 0xDA, 0xBA, 0xD7), +}; +static const mbedtls_mpi_uint secp192k1_T_2_X[] = { + MBEDTLS_BYTES_TO_T_UINT_8(0xE4, 0xC1, 0x9C, 0xE6, 0xBB, 0xFB, 0xCF, 0x23), + MBEDTLS_BYTES_TO_T_UINT_8(0x93, 0x19, 0xAC, 0x5A, 0xC9, 0x8A, 0x1C, 0x75), + MBEDTLS_BYTES_TO_T_UINT_8(0xC1, 0xF6, 0x76, 0x86, 0x89, 0x27, 0x8D, 0x28), +}; +static const mbedtls_mpi_uint secp192k1_T_2_Y[] = { + MBEDTLS_BYTES_TO_T_UINT_8(0x4B, 0xE0, 0x6F, 0x34, 0xBA, 0x5E, 0xD3, 0x96), + MBEDTLS_BYTES_TO_T_UINT_8(0x6A, 0xDC, 0xA6, 0x87, 0xC9, 0x9D, 0xC0, 0x82), + MBEDTLS_BYTES_TO_T_UINT_8(0x09, 0x11, 0x7E, 0xD6, 0xF7, 0x33, 0xFC, 0xE4), +}; +static const mbedtls_mpi_uint secp192k1_T_3_X[] = { + MBEDTLS_BYTES_TO_T_UINT_8(0xC2, 0x37, 0x3E, 0xC0, 0x7F, 0x62, 0xE7, 0x54), + MBEDTLS_BYTES_TO_T_UINT_8(0xA5, 0x3B, 0x69, 0x9D, 0x44, 0xBC, 0x82, 0x99), + MBEDTLS_BYTES_TO_T_UINT_8(0xD4, 0x84, 0xB3, 0x5F, 0x2B, 0xA5, 0x9E, 0x2C), +}; +static const mbedtls_mpi_uint secp192k1_T_3_Y[] = { + MBEDTLS_BYTES_TO_T_UINT_8(0x1D, 0x95, 0xEB, 0x4C, 0x04, 0xB4, 0xF4, 0x75), + MBEDTLS_BYTES_TO_T_UINT_8(0x55, 0xAD, 0x4B, 0xD5, 0x9A, 0xEB, 0xC4, 0x4E), + MBEDTLS_BYTES_TO_T_UINT_8(0xC9, 0xB1, 0xC5, 0x59, 0xE3, 0xD5, 0x16, 0x2A), +}; +static const mbedtls_mpi_uint secp192k1_T_4_X[] = { + MBEDTLS_BYTES_TO_T_UINT_8(0x48, 0x2A, 0xCC, 0xAC, 0xD0, 0xEE, 0x50, 0xEC), + MBEDTLS_BYTES_TO_T_UINT_8(0x99, 0x83, 0xE0, 0x5B, 0x14, 0x44, 0x52, 0x20), + MBEDTLS_BYTES_TO_T_UINT_8(0xD6, 0x15, 0x2D, 0x78, 0xF6, 0x51, 0x32, 0xCF), +}; +static const mbedtls_mpi_uint secp192k1_T_4_Y[] = { + MBEDTLS_BYTES_TO_T_UINT_8(0x86, 0x36, 0x9B, 0xDD, 0xF8, 0xDD, 0xEF, 0xB2), + MBEDTLS_BYTES_TO_T_UINT_8(0x0B, 0xB1, 0x6A, 0x2B, 0xAF, 0xEB, 0x2B, 0xB1), + MBEDTLS_BYTES_TO_T_UINT_8(0xC9, 0x87, 0x7A, 0x66, 0x5D, 0x5B, 0xDF, 0x8F), +}; +static const mbedtls_mpi_uint secp192k1_T_5_X[] = { + MBEDTLS_BYTES_TO_T_UINT_8(0x62, 0x45, 0xE5, 0x81, 0x9B, 0xEB, 0x37, 0x23), + MBEDTLS_BYTES_TO_T_UINT_8(0xB3, 0x29, 0xE2, 0x20, 0x64, 0x23, 0x6B, 0x6E), + MBEDTLS_BYTES_TO_T_UINT_8(0xFE, 0x1D, 0x41, 0xE1, 0x9B, 0x61, 0x7B, 0xD9), +}; +static const mbedtls_mpi_uint secp192k1_T_5_Y[] = { + MBEDTLS_BYTES_TO_T_UINT_8(0x75, 0x57, 0xA3, 0x0A, 0x13, 0xE4, 0x59, 0x15), + MBEDTLS_BYTES_TO_T_UINT_8(0x79, 0x6E, 0x4A, 0x48, 0x84, 0x90, 0xAC, 0xC7), + MBEDTLS_BYTES_TO_T_UINT_8(0x9C, 0xB8, 0xF5, 0xF3, 0xDE, 0xA0, 0xA1, 0x1D), +}; +static const mbedtls_mpi_uint secp192k1_T_6_X[] = { + MBEDTLS_BYTES_TO_T_UINT_8(0xA3, 0x32, 0x81, 0xA9, 0x91, 0x5A, 0x4E, 0x33), + MBEDTLS_BYTES_TO_T_UINT_8(0xCB, 0xA8, 0x90, 0xBE, 0x0F, 0xEC, 0xC0, 0x85), + MBEDTLS_BYTES_TO_T_UINT_8(0x80, 0x30, 0xD7, 0x08, 0xAE, 0xC4, 0x3A, 0xA5), +}; +static const mbedtls_mpi_uint secp192k1_T_6_Y[] = { + MBEDTLS_BYTES_TO_T_UINT_8(0xBC, 0x55, 0xE3, 0x76, 0xB3, 0x64, 0x74, 0x9F), + MBEDTLS_BYTES_TO_T_UINT_8(0x3F, 0x75, 0xD4, 0xDB, 0x98, 0xD7, 0x39, 0xAE), + MBEDTLS_BYTES_TO_T_UINT_8(0xD4, 0xEB, 0x8A, 0xAB, 0x16, 0xD9, 0xD4, 0x0B), +}; +static const mbedtls_mpi_uint secp192k1_T_7_X[] = { + MBEDTLS_BYTES_TO_T_UINT_8(0x41, 0xBE, 0xF9, 0xC7, 0xC7, 0xBA, 0xF3, 0xA1), + MBEDTLS_BYTES_TO_T_UINT_8(0xC2, 0x85, 0x59, 0xF3, 0x60, 0x41, 0x02, 0xD2), + MBEDTLS_BYTES_TO_T_UINT_8(0x46, 0x1C, 0x4A, 0xA4, 0xC7, 0xED, 0x66, 0xBC), +}; +static const mbedtls_mpi_uint secp192k1_T_7_Y[] = { + MBEDTLS_BYTES_TO_T_UINT_8(0xC3, 0x9C, 0x2E, 0x46, 0x52, 0x18, 0x87, 0x14), + MBEDTLS_BYTES_TO_T_UINT_8(0xFF, 0x35, 0x5A, 0x75, 0xAC, 0x4D, 0x75, 0x91), + MBEDTLS_BYTES_TO_T_UINT_8(0xCE, 0x2F, 0xAC, 0xFC, 0xBC, 0xE6, 0x93, 0x5E), +}; +static const mbedtls_mpi_uint secp192k1_T_8_X[] = { + MBEDTLS_BYTES_TO_T_UINT_8(0x87, 0x4D, 0xC9, 0x18, 0xE9, 0x00, 0xEB, 0x33), + MBEDTLS_BYTES_TO_T_UINT_8(0x1A, 0x69, 0x72, 0x07, 0x5A, 0x59, 0xA8, 0x26), + MBEDTLS_BYTES_TO_T_UINT_8(0xB6, 0x65, 0x83, 0x20, 0x10, 0xF9, 0x69, 0x82), +}; +static const mbedtls_mpi_uint secp192k1_T_8_Y[] = { + MBEDTLS_BYTES_TO_T_UINT_8(0x8B, 0x56, 0x7F, 0x9F, 0xBF, 0x46, 0x0C, 0x7E), + MBEDTLS_BYTES_TO_T_UINT_8(0xFC, 0xCF, 0xF0, 0xDC, 0xDF, 0x2D, 0xE6, 0xE5), + MBEDTLS_BYTES_TO_T_UINT_8(0x09, 0xF0, 0x72, 0x3A, 0x7A, 0x03, 0xE5, 0x22), +}; +static const mbedtls_mpi_uint secp192k1_T_9_X[] = { + MBEDTLS_BYTES_TO_T_UINT_8(0x3E, 0xAA, 0x57, 0x13, 0x37, 0xA7, 0x2C, 0xD4), + MBEDTLS_BYTES_TO_T_UINT_8(0xA3, 0xAC, 0xA2, 0x23, 0xF9, 0x84, 0x60, 0xD3), + MBEDTLS_BYTES_TO_T_UINT_8(0x32, 0xEB, 0x51, 0x70, 0x64, 0x78, 0xCA, 0x05), +}; +static const mbedtls_mpi_uint secp192k1_T_9_Y[] = { + MBEDTLS_BYTES_TO_T_UINT_8(0x91, 0xCC, 0x30, 0x62, 0x93, 0x46, 0x13, 0xE9), + MBEDTLS_BYTES_TO_T_UINT_8(0x21, 0x26, 0xCC, 0x6C, 0x3D, 0x5C, 0xDA, 0x2C), + MBEDTLS_BYTES_TO_T_UINT_8(0xD5, 0xAA, 0xB8, 0x03, 0xA4, 0x1A, 0x00, 0x96), +}; +static const mbedtls_mpi_uint secp192k1_T_10_X[] = { + MBEDTLS_BYTES_TO_T_UINT_8(0xF9, 0x9D, 0xE6, 0xCC, 0x4E, 0x2E, 0xC2, 0xD5), + MBEDTLS_BYTES_TO_T_UINT_8(0xB4, 0xC3, 0x8A, 0xAE, 0x6F, 0x40, 0x05, 0xEB), + MBEDTLS_BYTES_TO_T_UINT_8(0x9D, 0x8F, 0x4A, 0x4D, 0x35, 0xD3, 0x50, 0x9D), +}; +static const mbedtls_mpi_uint secp192k1_T_10_Y[] = { + MBEDTLS_BYTES_TO_T_UINT_8(0x1F, 0xFD, 0x98, 0xAB, 0xC7, 0x03, 0xB4, 0x55), + MBEDTLS_BYTES_TO_T_UINT_8(0x40, 0x40, 0xD2, 0x9F, 0xCA, 0xD0, 0x53, 0x00), + MBEDTLS_BYTES_TO_T_UINT_8(0x1A, 0x84, 0x00, 0x6F, 0xC8, 0xAD, 0xED, 0x8D), +}; +static const mbedtls_mpi_uint secp192k1_T_11_X[] = { + MBEDTLS_BYTES_TO_T_UINT_8(0xCE, 0xD3, 0x57, 0xD7, 0xC3, 0x07, 0xBD, 0xD7), + MBEDTLS_BYTES_TO_T_UINT_8(0x67, 0xBA, 0x47, 0x1D, 0x3D, 0xEF, 0x98, 0x6C), + MBEDTLS_BYTES_TO_T_UINT_8(0x6D, 0xC0, 0x6C, 0x7F, 0x12, 0xEE, 0x9F, 0x67), +}; +static const mbedtls_mpi_uint secp192k1_T_11_Y[] = { + MBEDTLS_BYTES_TO_T_UINT_8(0xCA, 0x02, 0xDA, 0x79, 0xAA, 0xC9, 0x27, 0xC4), + MBEDTLS_BYTES_TO_T_UINT_8(0x21, 0x79, 0xC7, 0x71, 0x84, 0xCB, 0xE5, 0x5A), + MBEDTLS_BYTES_TO_T_UINT_8(0x15, 0x37, 0x06, 0xBA, 0xB5, 0xD5, 0x18, 0x4C), +}; +static const mbedtls_mpi_uint secp192k1_T_12_X[] = { + MBEDTLS_BYTES_TO_T_UINT_8(0xA1, 0x65, 0x72, 0x6C, 0xF2, 0x63, 0x27, 0x6A), + MBEDTLS_BYTES_TO_T_UINT_8(0x69, 0xBC, 0x71, 0xDF, 0x75, 0xF8, 0x98, 0x4D), + MBEDTLS_BYTES_TO_T_UINT_8(0x70, 0x70, 0x9B, 0xDC, 0xE7, 0x18, 0x71, 0xFF), +}; +static const mbedtls_mpi_uint secp192k1_T_12_Y[] = { + MBEDTLS_BYTES_TO_T_UINT_8(0x15, 0x5B, 0x9F, 0x00, 0x5A, 0xB6, 0x80, 0x7A), + MBEDTLS_BYTES_TO_T_UINT_8(0xB7, 0xE0, 0xBB, 0xFC, 0x5E, 0x78, 0x9C, 0x89), + MBEDTLS_BYTES_TO_T_UINT_8(0x60, 0x03, 0x68, 0x83, 0x3D, 0x2E, 0x4C, 0xDD), +}; +static const mbedtls_mpi_uint secp192k1_T_13_X[] = { + MBEDTLS_BYTES_TO_T_UINT_8(0x3B, 0x49, 0x23, 0xA8, 0xCB, 0x3B, 0x1A, 0xF6), + MBEDTLS_BYTES_TO_T_UINT_8(0x8B, 0x3D, 0xA7, 0x46, 0xCF, 0x75, 0xB6, 0x2C), + MBEDTLS_BYTES_TO_T_UINT_8(0x92, 0xFD, 0x30, 0x01, 0xB6, 0xEF, 0xF9, 0xE8), +}; +static const mbedtls_mpi_uint secp192k1_T_13_Y[] = { + MBEDTLS_BYTES_TO_T_UINT_8(0xDC, 0xFA, 0xDA, 0xB8, 0x29, 0x42, 0xC9, 0xC7), + MBEDTLS_BYTES_TO_T_UINT_8(0x06, 0xD7, 0xA0, 0xE6, 0x6B, 0x86, 0x61, 0x39), + MBEDTLS_BYTES_TO_T_UINT_8(0xDB, 0xE9, 0xD3, 0x37, 0xD8, 0xE7, 0x35, 0xA9), +}; +static const mbedtls_mpi_uint secp192k1_T_14_X[] = { + MBEDTLS_BYTES_TO_T_UINT_8(0xFD, 0xC8, 0x8E, 0xB1, 0xCB, 0xB1, 0xB5, 0x4D), + MBEDTLS_BYTES_TO_T_UINT_8(0x16, 0xD7, 0x46, 0x7D, 0xAF, 0xE2, 0xDC, 0xBB), + MBEDTLS_BYTES_TO_T_UINT_8(0xD0, 0x46, 0xE7, 0xD8, 0x76, 0x31, 0x90, 0x76), +}; +static const mbedtls_mpi_uint secp192k1_T_14_Y[] = { + MBEDTLS_BYTES_TO_T_UINT_8(0xEB, 0xD3, 0xF4, 0x74, 0xE1, 0x67, 0xD8, 0x66), + MBEDTLS_BYTES_TO_T_UINT_8(0xE7, 0x70, 0x3C, 0xC8, 0xAF, 0x5F, 0xF4, 0x58), + MBEDTLS_BYTES_TO_T_UINT_8(0x24, 0x4E, 0xED, 0x5C, 0x43, 0xB3, 0x16, 0x35), +}; +static const mbedtls_mpi_uint secp192k1_T_15_X[] = { + MBEDTLS_BYTES_TO_T_UINT_8(0x57, 0xAE, 0xD1, 0xDD, 0x31, 0x14, 0xD3, 0xF0), + MBEDTLS_BYTES_TO_T_UINT_8(0xE8, 0x14, 0x06, 0x13, 0x12, 0x1C, 0x81, 0xF5), + MBEDTLS_BYTES_TO_T_UINT_8(0xA6, 0xF9, 0x0C, 0x91, 0xF7, 0x67, 0x59, 0x63), +}; +static const mbedtls_mpi_uint secp192k1_T_15_Y[] = { + MBEDTLS_BYTES_TO_T_UINT_8(0xAB, 0x91, 0xE2, 0xF4, 0x9D, 0xEB, 0x88, 0x87), + MBEDTLS_BYTES_TO_T_UINT_8(0xDB, 0x82, 0x30, 0x9C, 0xAE, 0x18, 0x4D, 0xB7), + MBEDTLS_BYTES_TO_T_UINT_8(0x3C, 0x79, 0xCF, 0x17, 0xA5, 0x1E, 0xE8, 0xC8), +}; +static const mbedtls_ecp_point secp192k1_T[16] = { + ECP_POINT_INIT_XY_Z1(secp192k1_T_0_X, secp192k1_T_0_Y), + ECP_POINT_INIT_XY_Z0(secp192k1_T_1_X, secp192k1_T_1_Y), + ECP_POINT_INIT_XY_Z0(secp192k1_T_2_X, secp192k1_T_2_Y), + ECP_POINT_INIT_XY_Z0(secp192k1_T_3_X, secp192k1_T_3_Y), + ECP_POINT_INIT_XY_Z0(secp192k1_T_4_X, secp192k1_T_4_Y), + ECP_POINT_INIT_XY_Z0(secp192k1_T_5_X, secp192k1_T_5_Y), + ECP_POINT_INIT_XY_Z0(secp192k1_T_6_X, secp192k1_T_6_Y), + ECP_POINT_INIT_XY_Z0(secp192k1_T_7_X, secp192k1_T_7_Y), + ECP_POINT_INIT_XY_Z0(secp192k1_T_8_X, secp192k1_T_8_Y), + ECP_POINT_INIT_XY_Z0(secp192k1_T_9_X, secp192k1_T_9_Y), + ECP_POINT_INIT_XY_Z0(secp192k1_T_10_X, secp192k1_T_10_Y), + ECP_POINT_INIT_XY_Z0(secp192k1_T_11_X, secp192k1_T_11_Y), + ECP_POINT_INIT_XY_Z0(secp192k1_T_12_X, secp192k1_T_12_Y), + ECP_POINT_INIT_XY_Z0(secp192k1_T_13_X, secp192k1_T_13_Y), + ECP_POINT_INIT_XY_Z0(secp192k1_T_14_X, secp192k1_T_14_Y), + ECP_POINT_INIT_XY_Z0(secp192k1_T_15_X, secp192k1_T_15_Y), +}; +#else +#define secp192k1_T NULL +#endif + +#endif /* MBEDTLS_ECP_DP_SECP192K1_ENABLED */ + +#if defined(MBEDTLS_ECP_DP_SECP224K1_ENABLED) +static const mbedtls_mpi_uint secp224k1_p[] = { + MBEDTLS_BYTES_TO_T_UINT_8(0x6D, 0xE5, 0xFF, 0xFF, 0xFE, 0xFF, 0xFF, 0xFF), + MBEDTLS_BYTES_TO_T_UINT_8(0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF), + MBEDTLS_BYTES_TO_T_UINT_8(0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF), + MBEDTLS_BYTES_TO_T_UINT_4(0xFF, 0xFF, 0xFF, 0xFF), +}; +static const mbedtls_mpi_uint secp224k1_a[] = { + MBEDTLS_BYTES_TO_T_UINT_2(0x00, 0x00), +}; +static const mbedtls_mpi_uint secp224k1_b[] = { + MBEDTLS_BYTES_TO_T_UINT_2(0x05, 0x00), +}; +static const mbedtls_mpi_uint secp224k1_gx[] = { + MBEDTLS_BYTES_TO_T_UINT_8(0x5C, 0xA4, 0xB7, 0xB6, 0x0E, 0x65, 0x7E, 0x0F), + MBEDTLS_BYTES_TO_T_UINT_8(0xA9, 0x75, 0x70, 0xE4, 0xE9, 0x67, 0xA4, 0x69), + MBEDTLS_BYTES_TO_T_UINT_8(0xA1, 0x28, 0xFC, 0x30, 0xDF, 0x99, 0xF0, 0x4D), + MBEDTLS_BYTES_TO_T_UINT_4(0x33, 0x5B, 0x45, 0xA1), +}; +static const mbedtls_mpi_uint secp224k1_gy[] = { + MBEDTLS_BYTES_TO_T_UINT_8(0xA5, 0x61, 0x6D, 0x55, 0xDB, 0x4B, 0xCA, 0xE2), + MBEDTLS_BYTES_TO_T_UINT_8(0x59, 0xBD, 0xB0, 0xC0, 0xF7, 0x19, 0xE3, 0xF7), + MBEDTLS_BYTES_TO_T_UINT_8(0xD6, 0xFB, 0xCA, 0x82, 0x42, 0x34, 0xBA, 0x7F), + MBEDTLS_BYTES_TO_T_UINT_4(0xED, 0x9F, 0x08, 0x7E), +}; +static const mbedtls_mpi_uint secp224k1_n[] = { + MBEDTLS_BYTES_TO_T_UINT_8(0xF7, 0xB1, 0x9F, 0x76, 0x71, 0xA9, 0xF0, 0xCA), + MBEDTLS_BYTES_TO_T_UINT_8(0x84, 0x61, 0xEC, 0xD2, 0xE8, 0xDC, 0x01, 0x00), + MBEDTLS_BYTES_TO_T_UINT_8(0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00), + MBEDTLS_BYTES_TO_T_UINT_8(0x00, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00), +}; + +#if MBEDTLS_ECP_FIXED_POINT_OPTIM == 1 +static const mbedtls_mpi_uint secp224k1_T_0_X[] = { + MBEDTLS_BYTES_TO_T_UINT_8(0x5C, 0xA4, 0xB7, 0xB6, 0x0E, 0x65, 0x7E, 0x0F), + MBEDTLS_BYTES_TO_T_UINT_8(0xA9, 0x75, 0x70, 0xE4, 0xE9, 0x67, 0xA4, 0x69), + MBEDTLS_BYTES_TO_T_UINT_8(0xA1, 0x28, 0xFC, 0x30, 0xDF, 0x99, 0xF0, 0x4D), + MBEDTLS_BYTES_TO_T_UINT_8(0x33, 0x5B, 0x45, 0xA1, 0x00, 0x00, 0x00, 0x00), +}; +static const mbedtls_mpi_uint secp224k1_T_0_Y[] = { + MBEDTLS_BYTES_TO_T_UINT_8(0xA5, 0x61, 0x6D, 0x55, 0xDB, 0x4B, 0xCA, 0xE2), + MBEDTLS_BYTES_TO_T_UINT_8(0x59, 0xBD, 0xB0, 0xC0, 0xF7, 0x19, 0xE3, 0xF7), + MBEDTLS_BYTES_TO_T_UINT_8(0xD6, 0xFB, 0xCA, 0x82, 0x42, 0x34, 0xBA, 0x7F), + MBEDTLS_BYTES_TO_T_UINT_8(0xED, 0x9F, 0x08, 0x7E, 0x00, 0x00, 0x00, 0x00), +}; +static const mbedtls_mpi_uint secp224k1_T_1_X[] = { + MBEDTLS_BYTES_TO_T_UINT_8(0x99, 0x6C, 0x22, 0x22, 0x40, 0x89, 0xAE, 0x7A), + MBEDTLS_BYTES_TO_T_UINT_8(0x2F, 0x92, 0xE1, 0x87, 0x56, 0x35, 0xAF, 0x9B), + MBEDTLS_BYTES_TO_T_UINT_8(0x88, 0xAF, 0x08, 0x35, 0x27, 0xEA, 0x04, 0xED), + MBEDTLS_BYTES_TO_T_UINT_8(0xF0, 0x53, 0xFD, 0xCF, 0x00, 0x00, 0x00, 0x00), +}; +static const mbedtls_mpi_uint secp224k1_T_1_Y[] = { + MBEDTLS_BYTES_TO_T_UINT_8(0xC1, 0xD0, 0x9F, 0x8D, 0xF3, 0x63, 0x54, 0x30), + MBEDTLS_BYTES_TO_T_UINT_8(0x39, 0xDB, 0x0F, 0x61, 0x54, 0x26, 0xD1, 0x98), + MBEDTLS_BYTES_TO_T_UINT_8(0xF5, 0x21, 0xF7, 0x1B, 0xB5, 0x1D, 0xF6, 0x7E), + MBEDTLS_BYTES_TO_T_UINT_8(0xFF, 0x05, 0xDA, 0x8F, 0x00, 0x00, 0x00, 0x00), +}; +static const mbedtls_mpi_uint secp224k1_T_2_X[] = { + MBEDTLS_BYTES_TO_T_UINT_8(0x10, 0x26, 0x73, 0xBC, 0xE4, 0x29, 0x62, 0x56), + MBEDTLS_BYTES_TO_T_UINT_8(0x37, 0x95, 0x17, 0x8B, 0xC3, 0x9B, 0xAC, 0xCC), + MBEDTLS_BYTES_TO_T_UINT_8(0xB1, 0xDB, 0x77, 0xDF, 0xDD, 0x13, 0x04, 0x98), + MBEDTLS_BYTES_TO_T_UINT_8(0x02, 0xFC, 0x22, 0x93, 0x00, 0x00, 0x00, 0x00), +}; +static const mbedtls_mpi_uint secp224k1_T_2_Y[] = { + MBEDTLS_BYTES_TO_T_UINT_8(0xAC, 0x65, 0xF1, 0x5A, 0x37, 0xEF, 0x79, 0xAD), + MBEDTLS_BYTES_TO_T_UINT_8(0x99, 0x01, 0x37, 0xAC, 0x9A, 0x5B, 0x51, 0x65), + MBEDTLS_BYTES_TO_T_UINT_8(0xFA, 0x75, 0x13, 0xA9, 0x4A, 0xAD, 0xFE, 0x9B), + MBEDTLS_BYTES_TO_T_UINT_8(0x32, 0x82, 0x6F, 0x66, 0x00, 0x00, 0x00, 0x00), +}; +static const mbedtls_mpi_uint secp224k1_T_3_X[] = { + MBEDTLS_BYTES_TO_T_UINT_8(0x4D, 0x5E, 0xF0, 0x40, 0xC3, 0xA6, 0xE2, 0x1E), + MBEDTLS_BYTES_TO_T_UINT_8(0x34, 0x9A, 0x6F, 0xCF, 0x11, 0x26, 0x66, 0x85), + MBEDTLS_BYTES_TO_T_UINT_8(0x79, 0x73, 0xA8, 0xCF, 0x2B, 0x12, 0x36, 0x37), + MBEDTLS_BYTES_TO_T_UINT_8(0xB9, 0xB3, 0x0A, 0x58, 0x00, 0x00, 0x00, 0x00), +}; +static const mbedtls_mpi_uint secp224k1_T_3_Y[] = { + MBEDTLS_BYTES_TO_T_UINT_8(0xD3, 0x79, 0x00, 0x55, 0x04, 0x34, 0x90, 0x1A), + MBEDTLS_BYTES_TO_T_UINT_8(0x0A, 0x54, 0x1C, 0xC2, 0x45, 0x0C, 0x1B, 0x23), + MBEDTLS_BYTES_TO_T_UINT_8(0x86, 0x19, 0xAB, 0xA8, 0xFC, 0x73, 0xDC, 0xEE), + MBEDTLS_BYTES_TO_T_UINT_8(0x72, 0xFB, 0x93, 0xCE, 0x00, 0x00, 0x00, 0x00), +}; +static const mbedtls_mpi_uint secp224k1_T_4_X[] = { + MBEDTLS_BYTES_TO_T_UINT_8(0xF8, 0x75, 0xD0, 0x66, 0x95, 0x86, 0xCA, 0x66), + MBEDTLS_BYTES_TO_T_UINT_8(0x17, 0xEA, 0x29, 0x16, 0x6A, 0x38, 0xDF, 0x41), + MBEDTLS_BYTES_TO_T_UINT_8(0xD8, 0xA2, 0x36, 0x2F, 0xDC, 0xBB, 0x5E, 0xF7), + MBEDTLS_BYTES_TO_T_UINT_8(0xD4, 0x89, 0x59, 0x49, 0x00, 0x00, 0x00, 0x00), +}; +static const mbedtls_mpi_uint secp224k1_T_4_Y[] = { + MBEDTLS_BYTES_TO_T_UINT_8(0xCA, 0xA3, 0x99, 0x9D, 0xB8, 0x77, 0x9D, 0x1D), + MBEDTLS_BYTES_TO_T_UINT_8(0x0A, 0x93, 0x43, 0x47, 0xC6, 0x5C, 0xF9, 0xFD), + MBEDTLS_BYTES_TO_T_UINT_8(0xAA, 0x00, 0x79, 0x42, 0x64, 0xB8, 0x25, 0x3E), + MBEDTLS_BYTES_TO_T_UINT_8(0x29, 0x54, 0xB4, 0x33, 0x00, 0x00, 0x00, 0x00), +}; +static const mbedtls_mpi_uint secp224k1_T_5_X[] = { + MBEDTLS_BYTES_TO_T_UINT_8(0xD9, 0x0C, 0x42, 0x90, 0x83, 0x0B, 0x31, 0x5F), + MBEDTLS_BYTES_TO_T_UINT_8(0x54, 0x2E, 0xAE, 0xC8, 0xC7, 0x5F, 0xD2, 0x70), + MBEDTLS_BYTES_TO_T_UINT_8(0xA9, 0xBC, 0xAD, 0x41, 0xE7, 0x32, 0x3A, 0x81), + MBEDTLS_BYTES_TO_T_UINT_8(0x8A, 0x97, 0x52, 0x83, 0x00, 0x00, 0x00, 0x00), +}; +static const mbedtls_mpi_uint secp224k1_T_5_Y[] = { + MBEDTLS_BYTES_TO_T_UINT_8(0x1A, 0x13, 0x7A, 0xBD, 0xAE, 0x94, 0x60, 0xFD), + MBEDTLS_BYTES_TO_T_UINT_8(0x92, 0x9B, 0x95, 0xB4, 0x6E, 0x68, 0xB2, 0x1F), + MBEDTLS_BYTES_TO_T_UINT_8(0x15, 0x49, 0xBE, 0x51, 0xFE, 0x66, 0x15, 0x74), + MBEDTLS_BYTES_TO_T_UINT_8(0xE6, 0x37, 0xE4, 0xFE, 0x00, 0x00, 0x00, 0x00), +}; +static const mbedtls_mpi_uint secp224k1_T_6_X[] = { + MBEDTLS_BYTES_TO_T_UINT_8(0xF6, 0x9B, 0xEE, 0x64, 0xC9, 0x1B, 0xBD, 0x77), + MBEDTLS_BYTES_TO_T_UINT_8(0xDA, 0x5F, 0x34, 0xA9, 0x0B, 0xB7, 0x25, 0x52), + MBEDTLS_BYTES_TO_T_UINT_8(0x90, 0x13, 0xB1, 0x38, 0xFB, 0x9D, 0x78, 0xED), + MBEDTLS_BYTES_TO_T_UINT_8(0x39, 0xE7, 0x1B, 0xFA, 0x00, 0x00, 0x00, 0x00), +}; +static const mbedtls_mpi_uint secp224k1_T_6_Y[] = { + MBEDTLS_BYTES_TO_T_UINT_8(0xFB, 0xB3, 0xB7, 0x44, 0x92, 0x6B, 0x00, 0x82), + MBEDTLS_BYTES_TO_T_UINT_8(0x97, 0x82, 0x44, 0x3E, 0x18, 0x1A, 0x58, 0x6A), + MBEDTLS_BYTES_TO_T_UINT_8(0x15, 0xF8, 0xC0, 0xE4, 0xEE, 0xC1, 0xBF, 0x44), + MBEDTLS_BYTES_TO_T_UINT_8(0x7E, 0x32, 0x27, 0xB2, 0x00, 0x00, 0x00, 0x00), +}; +static const mbedtls_mpi_uint secp224k1_T_7_X[] = { + MBEDTLS_BYTES_TO_T_UINT_8(0xF4, 0x9A, 0x42, 0x62, 0x8B, 0x26, 0x54, 0x21), + MBEDTLS_BYTES_TO_T_UINT_8(0x24, 0x85, 0x74, 0xA0, 0x79, 0xA8, 0xEE, 0xBE), + MBEDTLS_BYTES_TO_T_UINT_8(0x80, 0x36, 0x60, 0xB3, 0x28, 0x4D, 0x55, 0xBE), + MBEDTLS_BYTES_TO_T_UINT_8(0x32, 0x27, 0x82, 0x29, 0x00, 0x00, 0x00, 0x00), +}; +static const mbedtls_mpi_uint secp224k1_T_7_Y[] = { + MBEDTLS_BYTES_TO_T_UINT_8(0x0D, 0xFC, 0x73, 0x77, 0xAF, 0x5C, 0xAC, 0x78), + MBEDTLS_BYTES_TO_T_UINT_8(0xCC, 0xED, 0xE5, 0xF6, 0x1D, 0xA8, 0x67, 0x43), + MBEDTLS_BYTES_TO_T_UINT_8(0xF8, 0xDE, 0x33, 0x1C, 0xF1, 0x80, 0x73, 0xF8), + MBEDTLS_BYTES_TO_T_UINT_8(0x2A, 0xE2, 0xDE, 0x3C, 0x00, 0x00, 0x00, 0x00), +}; +static const mbedtls_mpi_uint secp224k1_T_8_X[] = { + MBEDTLS_BYTES_TO_T_UINT_8(0x57, 0x3E, 0x6B, 0xFE, 0xF0, 0x04, 0x28, 0x01), + MBEDTLS_BYTES_TO_T_UINT_8(0xBB, 0xB2, 0x14, 0x9D, 0x18, 0x11, 0x7D, 0x9D), + MBEDTLS_BYTES_TO_T_UINT_8(0x96, 0xC4, 0xD6, 0x2E, 0x6E, 0x57, 0x4D, 0xE1), + MBEDTLS_BYTES_TO_T_UINT_8(0xEA, 0x55, 0x1B, 0xDE, 0x00, 0x00, 0x00, 0x00), +}; +static const mbedtls_mpi_uint secp224k1_T_8_Y[] = { + MBEDTLS_BYTES_TO_T_UINT_8(0x07, 0xF7, 0x17, 0xBC, 0x45, 0xAB, 0x16, 0xAB), + MBEDTLS_BYTES_TO_T_UINT_8(0xCD, 0xB0, 0xEF, 0x61, 0xE3, 0x20, 0x7C, 0xF8), + MBEDTLS_BYTES_TO_T_UINT_8(0x6C, 0x85, 0x41, 0x4D, 0xF1, 0x7E, 0x4D, 0x41), + MBEDTLS_BYTES_TO_T_UINT_8(0x99, 0xC2, 0x9B, 0x5E, 0x00, 0x00, 0x00, 0x00), +}; +static const mbedtls_mpi_uint secp224k1_T_9_X[] = { + MBEDTLS_BYTES_TO_T_UINT_8(0x70, 0x2E, 0x49, 0x3D, 0x3E, 0x4B, 0xD3, 0x32), + MBEDTLS_BYTES_TO_T_UINT_8(0xC8, 0x2B, 0x9D, 0xD5, 0x27, 0xFA, 0xCA, 0xE0), + MBEDTLS_BYTES_TO_T_UINT_8(0xB3, 0xB3, 0x6A, 0xE0, 0x79, 0x14, 0x28, 0x0F), + MBEDTLS_BYTES_TO_T_UINT_8(0x6C, 0x1E, 0xDC, 0xF5, 0x00, 0x00, 0x00, 0x00), +}; +static const mbedtls_mpi_uint secp224k1_T_9_Y[] = { + MBEDTLS_BYTES_TO_T_UINT_8(0xCA, 0x44, 0x56, 0xCD, 0xFC, 0x9F, 0x09, 0xFF), + MBEDTLS_BYTES_TO_T_UINT_8(0x5C, 0x8C, 0x59, 0xA4, 0x64, 0x2A, 0x3A, 0xED), + MBEDTLS_BYTES_TO_T_UINT_8(0x40, 0xA0, 0xB5, 0x86, 0x4E, 0x69, 0xDA, 0x06), + MBEDTLS_BYTES_TO_T_UINT_8(0x08, 0x8B, 0x11, 0x38, 0x00, 0x00, 0x00, 0x00), +}; +static const mbedtls_mpi_uint secp224k1_T_10_X[] = { + MBEDTLS_BYTES_TO_T_UINT_8(0xA0, 0x17, 0x16, 0x12, 0x17, 0xDC, 0x00, 0x7E), + MBEDTLS_BYTES_TO_T_UINT_8(0xE7, 0x76, 0x24, 0x6C, 0x97, 0x2C, 0xB5, 0xF9), + MBEDTLS_BYTES_TO_T_UINT_8(0x82, 0x71, 0xE3, 0xB0, 0xBB, 0x4E, 0x50, 0x52), + MBEDTLS_BYTES_TO_T_UINT_8(0x6E, 0x48, 0x26, 0xD5, 0x00, 0x00, 0x00, 0x00), +}; +static const mbedtls_mpi_uint secp224k1_T_10_Y[] = { + MBEDTLS_BYTES_TO_T_UINT_8(0x06, 0x5F, 0x28, 0xF6, 0x01, 0x5A, 0x60, 0x41), + MBEDTLS_BYTES_TO_T_UINT_8(0xAE, 0x95, 0xFE, 0xD0, 0xAD, 0x15, 0xD4, 0xD9), + MBEDTLS_BYTES_TO_T_UINT_8(0xAD, 0x5B, 0x7A, 0xFD, 0x80, 0xF7, 0x9F, 0x64), + MBEDTLS_BYTES_TO_T_UINT_8(0x32, 0xBC, 0x1B, 0xDF, 0x00, 0x00, 0x00, 0x00), +}; +static const mbedtls_mpi_uint secp224k1_T_11_X[] = { + MBEDTLS_BYTES_TO_T_UINT_8(0xBB, 0xE6, 0xDF, 0x14, 0x29, 0xF4, 0xD4, 0x14), + MBEDTLS_BYTES_TO_T_UINT_8(0xE5, 0x12, 0xDD, 0xEC, 0x5B, 0x8A, 0x59, 0xE5), + MBEDTLS_BYTES_TO_T_UINT_8(0x26, 0x92, 0x3E, 0x35, 0x08, 0xE9, 0xCF, 0x0E), + MBEDTLS_BYTES_TO_T_UINT_8(0xE0, 0x35, 0x29, 0x97, 0x00, 0x00, 0x00, 0x00), +}; +static const mbedtls_mpi_uint secp224k1_T_11_Y[] = { + MBEDTLS_BYTES_TO_T_UINT_8(0x11, 0xDB, 0xD6, 0x6A, 0xC5, 0x43, 0xA4, 0xA1), + MBEDTLS_BYTES_TO_T_UINT_8(0x61, 0x33, 0x50, 0x61, 0x70, 0xA1, 0xE9, 0xCE), + MBEDTLS_BYTES_TO_T_UINT_8(0x15, 0x15, 0x6E, 0x5F, 0x01, 0x0C, 0x8C, 0xFA), + MBEDTLS_BYTES_TO_T_UINT_8(0x85, 0xA1, 0x9A, 0x9D, 0x00, 0x00, 0x00, 0x00), +}; +static const mbedtls_mpi_uint secp224k1_T_12_X[] = { + MBEDTLS_BYTES_TO_T_UINT_8(0x6E, 0xC6, 0xF7, 0xE2, 0x4A, 0xCD, 0x9B, 0x61), + MBEDTLS_BYTES_TO_T_UINT_8(0x34, 0x4D, 0x5A, 0xB8, 0xE2, 0x6D, 0xA6, 0x50), + MBEDTLS_BYTES_TO_T_UINT_8(0x32, 0x3F, 0xB6, 0x17, 0xE3, 0x2C, 0x6F, 0x65), + MBEDTLS_BYTES_TO_T_UINT_8(0x1E, 0xA4, 0x59, 0x51, 0x00, 0x00, 0x00, 0x00), +}; +static const mbedtls_mpi_uint secp224k1_T_12_Y[] = { + MBEDTLS_BYTES_TO_T_UINT_8(0x77, 0x4F, 0x7C, 0x49, 0xCD, 0x6E, 0xEB, 0x3C), + MBEDTLS_BYTES_TO_T_UINT_8(0x05, 0xC9, 0x1F, 0xB7, 0x4D, 0x98, 0xC7, 0x67), + MBEDTLS_BYTES_TO_T_UINT_8(0x4C, 0xFD, 0x98, 0x20, 0x95, 0xBB, 0x20, 0x3A), + MBEDTLS_BYTES_TO_T_UINT_8(0xE0, 0xF2, 0x73, 0x92, 0x00, 0x00, 0x00, 0x00), +}; +static const mbedtls_mpi_uint secp224k1_T_13_X[] = { + MBEDTLS_BYTES_TO_T_UINT_8(0xE2, 0xEF, 0xFB, 0x30, 0xFA, 0x12, 0x1A, 0xB0), + MBEDTLS_BYTES_TO_T_UINT_8(0x7A, 0x4C, 0x24, 0xB4, 0x5B, 0xC9, 0x4C, 0x0F), + MBEDTLS_BYTES_TO_T_UINT_8(0x7A, 0xDD, 0x5E, 0x84, 0x95, 0x4D, 0x26, 0xED), + MBEDTLS_BYTES_TO_T_UINT_8(0xE3, 0xFA, 0xF9, 0x3A, 0x00, 0x00, 0x00, 0x00), +}; +static const mbedtls_mpi_uint secp224k1_T_13_Y[] = { + MBEDTLS_BYTES_TO_T_UINT_8(0x6A, 0xA3, 0x2E, 0x7A, 0xDC, 0xA7, 0x53, 0xA9), + MBEDTLS_BYTES_TO_T_UINT_8(0x7C, 0x9F, 0x81, 0x84, 0xB2, 0x0D, 0xFE, 0x31), + MBEDTLS_BYTES_TO_T_UINT_8(0x61, 0x89, 0x1B, 0x77, 0x0C, 0x89, 0x71, 0xEC), + MBEDTLS_BYTES_TO_T_UINT_8(0xFA, 0xFF, 0x7F, 0xB2, 0x00, 0x00, 0x00, 0x00), +}; +static const mbedtls_mpi_uint secp224k1_T_14_X[] = { + MBEDTLS_BYTES_TO_T_UINT_8(0x28, 0xE9, 0x2C, 0x79, 0xA6, 0x3C, 0xAD, 0x93), + MBEDTLS_BYTES_TO_T_UINT_8(0xD6, 0xE0, 0x23, 0x02, 0x86, 0x0F, 0x77, 0x2A), + MBEDTLS_BYTES_TO_T_UINT_8(0x13, 0x93, 0x6D, 0xE9, 0xF9, 0x3C, 0xBE, 0xB9), + MBEDTLS_BYTES_TO_T_UINT_8(0x04, 0xE7, 0x24, 0x92, 0x00, 0x00, 0x00, 0x00), +}; +static const mbedtls_mpi_uint secp224k1_T_14_Y[] = { + MBEDTLS_BYTES_TO_T_UINT_8(0xBB, 0x3C, 0x5B, 0x4B, 0x1B, 0x25, 0x37, 0xD6), + MBEDTLS_BYTES_TO_T_UINT_8(0xC9, 0xE8, 0x38, 0x1B, 0xA1, 0x5A, 0x2E, 0x68), + MBEDTLS_BYTES_TO_T_UINT_8(0x03, 0x19, 0xFD, 0xF4, 0x78, 0x01, 0x6B, 0x44), + MBEDTLS_BYTES_TO_T_UINT_8(0x0F, 0x69, 0x37, 0x4F, 0x00, 0x00, 0x00, 0x00), +}; +static const mbedtls_mpi_uint secp224k1_T_15_X[] = { + MBEDTLS_BYTES_TO_T_UINT_8(0x1A, 0xE2, 0xBF, 0xD3, 0xEC, 0x95, 0x9C, 0x03), + MBEDTLS_BYTES_TO_T_UINT_8(0xC2, 0x7B, 0xFC, 0xD5, 0xD3, 0x25, 0x5E, 0x0F), + MBEDTLS_BYTES_TO_T_UINT_8(0x39, 0x55, 0x09, 0xA2, 0x58, 0x6A, 0xC9, 0xFF), + MBEDTLS_BYTES_TO_T_UINT_8(0x80, 0xCC, 0x3B, 0xD9, 0x00, 0x00, 0x00, 0x00), +}; +static const mbedtls_mpi_uint secp224k1_T_15_Y[] = { + MBEDTLS_BYTES_TO_T_UINT_8(0x8F, 0x08, 0x65, 0x5E, 0xCB, 0xAB, 0x48, 0xC8), + MBEDTLS_BYTES_TO_T_UINT_8(0xEE, 0x79, 0x8B, 0xC0, 0x11, 0xC0, 0x69, 0x38), + MBEDTLS_BYTES_TO_T_UINT_8(0xE6, 0xE8, 0x8C, 0x4C, 0xC5, 0x28, 0xE4, 0xAE), + MBEDTLS_BYTES_TO_T_UINT_8(0xA5, 0x1F, 0x34, 0x5C, 0x00, 0x00, 0x00, 0x00), +}; +static const mbedtls_ecp_point secp224k1_T[16] = { + ECP_POINT_INIT_XY_Z1(secp224k1_T_0_X, secp224k1_T_0_Y), + ECP_POINT_INIT_XY_Z0(secp224k1_T_1_X, secp224k1_T_1_Y), + ECP_POINT_INIT_XY_Z0(secp224k1_T_2_X, secp224k1_T_2_Y), + ECP_POINT_INIT_XY_Z0(secp224k1_T_3_X, secp224k1_T_3_Y), + ECP_POINT_INIT_XY_Z0(secp224k1_T_4_X, secp224k1_T_4_Y), + ECP_POINT_INIT_XY_Z0(secp224k1_T_5_X, secp224k1_T_5_Y), + ECP_POINT_INIT_XY_Z0(secp224k1_T_6_X, secp224k1_T_6_Y), + ECP_POINT_INIT_XY_Z0(secp224k1_T_7_X, secp224k1_T_7_Y), + ECP_POINT_INIT_XY_Z0(secp224k1_T_8_X, secp224k1_T_8_Y), + ECP_POINT_INIT_XY_Z0(secp224k1_T_9_X, secp224k1_T_9_Y), + ECP_POINT_INIT_XY_Z0(secp224k1_T_10_X, secp224k1_T_10_Y), + ECP_POINT_INIT_XY_Z0(secp224k1_T_11_X, secp224k1_T_11_Y), + ECP_POINT_INIT_XY_Z0(secp224k1_T_12_X, secp224k1_T_12_Y), + ECP_POINT_INIT_XY_Z0(secp224k1_T_13_X, secp224k1_T_13_Y), + ECP_POINT_INIT_XY_Z0(secp224k1_T_14_X, secp224k1_T_14_Y), + ECP_POINT_INIT_XY_Z0(secp224k1_T_15_X, secp224k1_T_15_Y), +}; +#else +#define secp224k1_T NULL +#endif +#endif /* MBEDTLS_ECP_DP_SECP224K1_ENABLED */ + +#if defined(MBEDTLS_ECP_DP_SECP256K1_ENABLED) +static const mbedtls_mpi_uint secp256k1_p[] = { + MBEDTLS_BYTES_TO_T_UINT_8(0x2F, 0xFC, 0xFF, 0xFF, 0xFE, 0xFF, 0xFF, 0xFF), + MBEDTLS_BYTES_TO_T_UINT_8(0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF), + MBEDTLS_BYTES_TO_T_UINT_8(0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF), + MBEDTLS_BYTES_TO_T_UINT_8(0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF), +}; +static const mbedtls_mpi_uint secp256k1_a[] = { + MBEDTLS_BYTES_TO_T_UINT_2(0x00, 0x00), +}; +static const mbedtls_mpi_uint secp256k1_b[] = { + MBEDTLS_BYTES_TO_T_UINT_2(0x07, 0x00), +}; +static const mbedtls_mpi_uint secp256k1_gx[] = { + MBEDTLS_BYTES_TO_T_UINT_8(0x98, 0x17, 0xF8, 0x16, 0x5B, 0x81, 0xF2, 0x59), + MBEDTLS_BYTES_TO_T_UINT_8(0xD9, 0x28, 0xCE, 0x2D, 0xDB, 0xFC, 0x9B, 0x02), + MBEDTLS_BYTES_TO_T_UINT_8(0x07, 0x0B, 0x87, 0xCE, 0x95, 0x62, 0xA0, 0x55), + MBEDTLS_BYTES_TO_T_UINT_8(0xAC, 0xBB, 0xDC, 0xF9, 0x7E, 0x66, 0xBE, 0x79), +}; +static const mbedtls_mpi_uint secp256k1_gy[] = { + MBEDTLS_BYTES_TO_T_UINT_8(0xB8, 0xD4, 0x10, 0xFB, 0x8F, 0xD0, 0x47, 0x9C), + MBEDTLS_BYTES_TO_T_UINT_8(0x19, 0x54, 0x85, 0xA6, 0x48, 0xB4, 0x17, 0xFD), + MBEDTLS_BYTES_TO_T_UINT_8(0xA8, 0x08, 0x11, 0x0E, 0xFC, 0xFB, 0xA4, 0x5D), + MBEDTLS_BYTES_TO_T_UINT_8(0x65, 0xC4, 0xA3, 0x26, 0x77, 0xDA, 0x3A, 0x48), +}; +static const mbedtls_mpi_uint secp256k1_n[] = { + MBEDTLS_BYTES_TO_T_UINT_8(0x41, 0x41, 0x36, 0xD0, 0x8C, 0x5E, 0xD2, 0xBF), + MBEDTLS_BYTES_TO_T_UINT_8(0x3B, 0xA0, 0x48, 0xAF, 0xE6, 0xDC, 0xAE, 0xBA), + MBEDTLS_BYTES_TO_T_UINT_8(0xFE, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF), + MBEDTLS_BYTES_TO_T_UINT_8(0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF), +}; + +#if MBEDTLS_ECP_FIXED_POINT_OPTIM == 1 +static const mbedtls_mpi_uint secp256k1_T_0_X[] = { + MBEDTLS_BYTES_TO_T_UINT_8(0x98, 0x17, 0xF8, 0x16, 0x5B, 0x81, 0xF2, 0x59), + MBEDTLS_BYTES_TO_T_UINT_8(0xD9, 0x28, 0xCE, 0x2D, 0xDB, 0xFC, 0x9B, 0x02), + MBEDTLS_BYTES_TO_T_UINT_8(0x07, 0x0B, 0x87, 0xCE, 0x95, 0x62, 0xA0, 0x55), + MBEDTLS_BYTES_TO_T_UINT_8(0xAC, 0xBB, 0xDC, 0xF9, 0x7E, 0x66, 0xBE, 0x79), +}; +static const mbedtls_mpi_uint secp256k1_T_0_Y[] = { + MBEDTLS_BYTES_TO_T_UINT_8(0xB8, 0xD4, 0x10, 0xFB, 0x8F, 0xD0, 0x47, 0x9C), + MBEDTLS_BYTES_TO_T_UINT_8(0x19, 0x54, 0x85, 0xA6, 0x48, 0xB4, 0x17, 0xFD), + MBEDTLS_BYTES_TO_T_UINT_8(0xA8, 0x08, 0x11, 0x0E, 0xFC, 0xFB, 0xA4, 0x5D), + MBEDTLS_BYTES_TO_T_UINT_8(0x65, 0xC4, 0xA3, 0x26, 0x77, 0xDA, 0x3A, 0x48), +}; +static const mbedtls_mpi_uint secp256k1_T_1_X[] = { + MBEDTLS_BYTES_TO_T_UINT_8(0xE7, 0xEE, 0xD7, 0x1E, 0x67, 0x86, 0x32, 0x74), + MBEDTLS_BYTES_TO_T_UINT_8(0x23, 0x73, 0xB1, 0xA9, 0xD5, 0xCC, 0x27, 0x78), + MBEDTLS_BYTES_TO_T_UINT_8(0x1F, 0x0E, 0x11, 0x01, 0x71, 0xFE, 0x92, 0x73), + MBEDTLS_BYTES_TO_T_UINT_8(0xC6, 0x28, 0x63, 0x6D, 0x72, 0x09, 0xA6, 0xC0), +}; +static const mbedtls_mpi_uint secp256k1_T_1_Y[] = { + MBEDTLS_BYTES_TO_T_UINT_8(0xCE, 0xE1, 0x69, 0xDC, 0x3E, 0x2C, 0x75, 0xC3), + MBEDTLS_BYTES_TO_T_UINT_8(0xE5, 0xB7, 0x3F, 0x30, 0x26, 0x3C, 0xDF, 0x8E), + MBEDTLS_BYTES_TO_T_UINT_8(0x3D, 0xBE, 0xB9, 0x5D, 0x0E, 0xE8, 0x5E, 0x14), + MBEDTLS_BYTES_TO_T_UINT_8(0x01, 0xC3, 0x05, 0xD6, 0xB7, 0xD5, 0x24, 0xFC), +}; +static const mbedtls_mpi_uint secp256k1_T_2_X[] = { + MBEDTLS_BYTES_TO_T_UINT_8(0x13, 0xCF, 0x7B, 0xDC, 0xCD, 0xC3, 0x39, 0x9D), + MBEDTLS_BYTES_TO_T_UINT_8(0x42, 0xDA, 0xB9, 0xE5, 0x64, 0xA7, 0x47, 0x91), + MBEDTLS_BYTES_TO_T_UINT_8(0x76, 0x46, 0xA8, 0x61, 0xF6, 0x23, 0xEB, 0x58), + MBEDTLS_BYTES_TO_T_UINT_8(0x5C, 0xC1, 0xFF, 0xE4, 0x55, 0xD5, 0xC2, 0xBF), +}; +static const mbedtls_mpi_uint secp256k1_T_2_Y[] = { + MBEDTLS_BYTES_TO_T_UINT_8(0xC9, 0xBE, 0xB9, 0x59, 0x24, 0x13, 0x4A, 0x2A), + MBEDTLS_BYTES_TO_T_UINT_8(0x64, 0x45, 0x12, 0xDE, 0xBA, 0x4F, 0xEF, 0x56), + MBEDTLS_BYTES_TO_T_UINT_8(0xBE, 0x08, 0xBF, 0xC1, 0x66, 0xAA, 0x0A, 0xBC), + MBEDTLS_BYTES_TO_T_UINT_8(0x36, 0xFE, 0x30, 0x55, 0x31, 0x86, 0xA7, 0xB4), +}; +static const mbedtls_mpi_uint secp256k1_T_3_X[] = { + MBEDTLS_BYTES_TO_T_UINT_8(0x1D, 0xBF, 0x18, 0x81, 0x67, 0x27, 0x42, 0xBD), + MBEDTLS_BYTES_TO_T_UINT_8(0x08, 0x05, 0x83, 0xA4, 0xDD, 0x57, 0xD3, 0x50), + MBEDTLS_BYTES_TO_T_UINT_8(0x20, 0x63, 0xAB, 0xE4, 0x90, 0x70, 0xD0, 0x7C), + MBEDTLS_BYTES_TO_T_UINT_8(0x71, 0x5D, 0xFD, 0xA0, 0xEF, 0xCF, 0x1C, 0x54), +}; +static const mbedtls_mpi_uint secp256k1_T_3_Y[] = { + MBEDTLS_BYTES_TO_T_UINT_8(0x13, 0x80, 0xE4, 0xF6, 0x09, 0xBC, 0x57, 0x90), + MBEDTLS_BYTES_TO_T_UINT_8(0x21, 0x9F, 0x6E, 0x88, 0x54, 0x6E, 0x51, 0xF2), + MBEDTLS_BYTES_TO_T_UINT_8(0xF5, 0x5F, 0x85, 0xFB, 0x84, 0x3E, 0x4A, 0xAA), + MBEDTLS_BYTES_TO_T_UINT_8(0xA8, 0x19, 0xF5, 0x55, 0xC9, 0x07, 0xD8, 0xCE), +}; +static const mbedtls_mpi_uint secp256k1_T_4_X[] = { + MBEDTLS_BYTES_TO_T_UINT_8(0x1A, 0xB4, 0xC3, 0xD9, 0x5C, 0xA0, 0xD4, 0x90), + MBEDTLS_BYTES_TO_T_UINT_8(0x0D, 0x30, 0xAF, 0x59, 0x9B, 0xF8, 0x04, 0x85), + MBEDTLS_BYTES_TO_T_UINT_8(0x4D, 0xA6, 0xFD, 0x66, 0x7B, 0xC3, 0x39, 0x85), + MBEDTLS_BYTES_TO_T_UINT_8(0xE0, 0xBF, 0xF0, 0xC2, 0xE9, 0x71, 0xA4, 0x9E), +}; +static const mbedtls_mpi_uint secp256k1_T_4_Y[] = { + MBEDTLS_BYTES_TO_T_UINT_8(0x14, 0x2D, 0xB9, 0x88, 0x28, 0xF1, 0xBE, 0x78), + MBEDTLS_BYTES_TO_T_UINT_8(0x14, 0xF3, 0x1A, 0x0E, 0xB9, 0x01, 0x66, 0x34), + MBEDTLS_BYTES_TO_T_UINT_8(0x77, 0xA7, 0xA4, 0xF4, 0x05, 0xD0, 0xAA, 0x53), + MBEDTLS_BYTES_TO_T_UINT_8(0x00, 0x39, 0x1E, 0x47, 0xE5, 0x68, 0xC8, 0xC0), +}; +static const mbedtls_mpi_uint secp256k1_T_5_X[] = { + MBEDTLS_BYTES_TO_T_UINT_8(0xDD, 0xB9, 0xFC, 0xE0, 0x33, 0x8A, 0x7D, 0x96), + MBEDTLS_BYTES_TO_T_UINT_8(0x4F, 0x93, 0xA5, 0x53, 0x55, 0x16, 0xB4, 0x6E), + MBEDTLS_BYTES_TO_T_UINT_8(0xE9, 0x5F, 0xEA, 0x9B, 0x29, 0x52, 0x71, 0xDA), + MBEDTLS_BYTES_TO_T_UINT_8(0xB2, 0xF0, 0x24, 0xB8, 0x7D, 0xB7, 0xA0, 0x9B), +}; +static const mbedtls_mpi_uint secp256k1_T_5_Y[] = { + MBEDTLS_BYTES_TO_T_UINT_8(0xC2, 0x00, 0x27, 0xB2, 0xDF, 0x73, 0xA2, 0xE0), + MBEDTLS_BYTES_TO_T_UINT_8(0x1D, 0x2E, 0x4D, 0x7C, 0xDE, 0x7A, 0x23, 0x32), + MBEDTLS_BYTES_TO_T_UINT_8(0xAC, 0x65, 0x60, 0xC7, 0x97, 0x1E, 0xA4, 0x22), + MBEDTLS_BYTES_TO_T_UINT_8(0xCD, 0x13, 0x5B, 0x77, 0x59, 0xCB, 0x36, 0xE1), +}; +static const mbedtls_mpi_uint secp256k1_T_6_X[] = { + MBEDTLS_BYTES_TO_T_UINT_8(0x99, 0xBC, 0x9F, 0x9E, 0x2D, 0x53, 0x2A, 0xA8), + MBEDTLS_BYTES_TO_T_UINT_8(0x87, 0x5F, 0x64, 0x9F, 0x1A, 0x19, 0xE6, 0x77), + MBEDTLS_BYTES_TO_T_UINT_8(0x9E, 0x7B, 0x39, 0xD2, 0xDB, 0x85, 0x84, 0xD5), + MBEDTLS_BYTES_TO_T_UINT_8(0x83, 0xC7, 0x0D, 0x58, 0x6E, 0x3F, 0x52, 0x15), +}; +static const mbedtls_mpi_uint secp256k1_T_6_Y[] = { + MBEDTLS_BYTES_TO_T_UINT_8(0x21, 0x68, 0x19, 0x0B, 0x68, 0xC9, 0x1E, 0xFB), + MBEDTLS_BYTES_TO_T_UINT_8(0xD2, 0x4E, 0x21, 0x49, 0x3D, 0x55, 0xCC, 0x25), + MBEDTLS_BYTES_TO_T_UINT_8(0xF5, 0xF9, 0x25, 0x45, 0x54, 0x45, 0xB1, 0x0F), + MBEDTLS_BYTES_TO_T_UINT_8(0xA9, 0xB3, 0xF7, 0xCD, 0x80, 0xA4, 0x04, 0x05), +}; +static const mbedtls_mpi_uint secp256k1_T_7_X[] = { + MBEDTLS_BYTES_TO_T_UINT_8(0xD4, 0x1E, 0x88, 0xC4, 0xAA, 0x18, 0x7E, 0x45), + MBEDTLS_BYTES_TO_T_UINT_8(0x4B, 0xAC, 0xD9, 0xB2, 0xA1, 0xC0, 0x71, 0x5D), + MBEDTLS_BYTES_TO_T_UINT_8(0xA9, 0xA2, 0xF1, 0x15, 0xA6, 0x5F, 0x6C, 0x86), + MBEDTLS_BYTES_TO_T_UINT_8(0x4F, 0x5B, 0x05, 0xBC, 0xB7, 0xC6, 0x4E, 0x72), +}; +static const mbedtls_mpi_uint secp256k1_T_7_Y[] = { + MBEDTLS_BYTES_TO_T_UINT_8(0x1D, 0x80, 0xF8, 0x5C, 0x20, 0x2A, 0xE1, 0xE2), + MBEDTLS_BYTES_TO_T_UINT_8(0x7C, 0x48, 0x2E, 0x68, 0x82, 0x7F, 0xEB, 0x5F), + MBEDTLS_BYTES_TO_T_UINT_8(0xA2, 0x3B, 0x25, 0xDB, 0x32, 0x4D, 0x88, 0x42), + MBEDTLS_BYTES_TO_T_UINT_8(0xEE, 0x6E, 0xA6, 0xB6, 0x6D, 0x62, 0x78, 0x22), +}; +static const mbedtls_mpi_uint secp256k1_T_8_X[] = { + MBEDTLS_BYTES_TO_T_UINT_8(0x1F, 0x4D, 0x3E, 0x86, 0x58, 0xC3, 0xEB, 0xBA), + MBEDTLS_BYTES_TO_T_UINT_8(0x1A, 0x89, 0x33, 0x18, 0x21, 0x1D, 0x9B, 0xE7), + MBEDTLS_BYTES_TO_T_UINT_8(0x0B, 0x9D, 0xFF, 0xC3, 0x79, 0xC1, 0x88, 0xF8), + MBEDTLS_BYTES_TO_T_UINT_8(0x28, 0xD4, 0x48, 0x53, 0xE8, 0xAD, 0x21, 0x16), +}; +static const mbedtls_mpi_uint secp256k1_T_8_Y[] = { + MBEDTLS_BYTES_TO_T_UINT_8(0xF5, 0x7B, 0xDE, 0xCB, 0xD8, 0x39, 0x17, 0x7C), + MBEDTLS_BYTES_TO_T_UINT_8(0xD3, 0xF3, 0x03, 0xF2, 0x5C, 0xBC, 0xC8, 0x8A), + MBEDTLS_BYTES_TO_T_UINT_8(0x27, 0xAE, 0x4C, 0xB0, 0x16, 0xA4, 0x93, 0x86), + MBEDTLS_BYTES_TO_T_UINT_8(0x71, 0x8B, 0x6B, 0xDC, 0xD7, 0x9A, 0x3E, 0x7E), +}; +static const mbedtls_mpi_uint secp256k1_T_9_X[] = { + MBEDTLS_BYTES_TO_T_UINT_8(0xD6, 0x2D, 0x7A, 0xD2, 0x59, 0x05, 0xA2, 0x82), + MBEDTLS_BYTES_TO_T_UINT_8(0x57, 0x56, 0x09, 0x32, 0xF1, 0xE8, 0xE3, 0x72), + MBEDTLS_BYTES_TO_T_UINT_8(0x03, 0xCA, 0xE5, 0x2E, 0xF0, 0xFB, 0x18, 0x19), + MBEDTLS_BYTES_TO_T_UINT_8(0xBA, 0x85, 0xA9, 0x23, 0x15, 0x31, 0x1F, 0x0E), +}; +static const mbedtls_mpi_uint secp256k1_T_9_Y[] = { + MBEDTLS_BYTES_TO_T_UINT_8(0x76, 0xE5, 0xB1, 0x86, 0xB9, 0x6E, 0x8D, 0xD3), + MBEDTLS_BYTES_TO_T_UINT_8(0x6C, 0x77, 0xFC, 0xC9, 0xA3, 0x3F, 0x89, 0xD2), + MBEDTLS_BYTES_TO_T_UINT_8(0xDB, 0x6A, 0xDC, 0x25, 0xB0, 0xC7, 0x41, 0x54), + MBEDTLS_BYTES_TO_T_UINT_8(0x02, 0x11, 0x6B, 0xA6, 0x11, 0x62, 0xD4, 0x2D), +}; +static const mbedtls_mpi_uint secp256k1_T_10_X[] = { + MBEDTLS_BYTES_TO_T_UINT_8(0x19, 0x7D, 0x34, 0xB3, 0x20, 0x7F, 0x37, 0xAA), + MBEDTLS_BYTES_TO_T_UINT_8(0xBD, 0xD4, 0x45, 0xE8, 0xC2, 0xE9, 0xC5, 0xEA), + MBEDTLS_BYTES_TO_T_UINT_8(0x5A, 0x32, 0x3B, 0x25, 0x7E, 0x79, 0xAF, 0xE7), + MBEDTLS_BYTES_TO_T_UINT_8(0x3F, 0xE4, 0x54, 0x71, 0xBE, 0x35, 0x4E, 0xD0), +}; +static const mbedtls_mpi_uint secp256k1_T_10_Y[] = { + MBEDTLS_BYTES_TO_T_UINT_8(0xB0, 0x94, 0xDD, 0x8F, 0xB5, 0xC2, 0xDD, 0x75), + MBEDTLS_BYTES_TO_T_UINT_8(0x07, 0x49, 0xE9, 0x1C, 0x2F, 0x08, 0x49, 0xC6), + MBEDTLS_BYTES_TO_T_UINT_8(0x77, 0xB6, 0x03, 0x88, 0x6F, 0xB8, 0x15, 0x67), + MBEDTLS_BYTES_TO_T_UINT_8(0xA4, 0xD3, 0x1C, 0xF3, 0xA5, 0xEB, 0x79, 0x01), +}; +static const mbedtls_mpi_uint secp256k1_T_11_X[] = { + MBEDTLS_BYTES_TO_T_UINT_8(0x25, 0xF9, 0x43, 0x88, 0x89, 0x0D, 0x06, 0xEA), + MBEDTLS_BYTES_TO_T_UINT_8(0x02, 0x2D, 0xF5, 0x98, 0x32, 0xF6, 0xB1, 0x05), + MBEDTLS_BYTES_TO_T_UINT_8(0x23, 0x73, 0x8F, 0x2B, 0x50, 0x27, 0x0A, 0xE7), + MBEDTLS_BYTES_TO_T_UINT_8(0xA7, 0xE3, 0xBD, 0x16, 0x05, 0xC8, 0x93, 0x12), +}; +static const mbedtls_mpi_uint secp256k1_T_11_Y[] = { + MBEDTLS_BYTES_TO_T_UINT_8(0x0A, 0x6A, 0xF7, 0xE3, 0x3D, 0xDE, 0x5F, 0x2F), + MBEDTLS_BYTES_TO_T_UINT_8(0x47, 0xA3, 0x9C, 0x22, 0x3C, 0x33, 0x36, 0x5D), + MBEDTLS_BYTES_TO_T_UINT_8(0x20, 0x24, 0x4C, 0x69, 0x45, 0x78, 0x14, 0xAE), + MBEDTLS_BYTES_TO_T_UINT_8(0x59, 0xF8, 0xD4, 0xBF, 0xB8, 0xC0, 0xA1, 0x25), +}; +static const mbedtls_mpi_uint secp256k1_T_12_X[] = { + MBEDTLS_BYTES_TO_T_UINT_8(0x7E, 0x88, 0xE1, 0x91, 0x03, 0xEB, 0xB3, 0x2B), + MBEDTLS_BYTES_TO_T_UINT_8(0x5C, 0x11, 0xA1, 0xEF, 0x14, 0x0D, 0xC4, 0x7D), + MBEDTLS_BYTES_TO_T_UINT_8(0xFE, 0xD4, 0x0D, 0x1D, 0x96, 0x33, 0x5C, 0x19), + MBEDTLS_BYTES_TO_T_UINT_8(0x70, 0x45, 0x2A, 0x1A, 0xE6, 0x57, 0x04, 0x9B), +}; +static const mbedtls_mpi_uint secp256k1_T_12_Y[] = { + MBEDTLS_BYTES_TO_T_UINT_8(0x70, 0xB5, 0xA7, 0x80, 0xE9, 0x93, 0x97, 0x8D), + MBEDTLS_BYTES_TO_T_UINT_8(0x5D, 0xB9, 0x7C, 0xA0, 0xC9, 0x57, 0x26, 0x43), + MBEDTLS_BYTES_TO_T_UINT_8(0x9E, 0xEF, 0x56, 0xDA, 0x66, 0xF6, 0x1B, 0x9A), + MBEDTLS_BYTES_TO_T_UINT_8(0x1F, 0x89, 0x6B, 0x91, 0xE0, 0xA9, 0x65, 0x2B), +}; +static const mbedtls_mpi_uint secp256k1_T_13_X[] = { + MBEDTLS_BYTES_TO_T_UINT_8(0x91, 0x98, 0x96, 0x9B, 0x06, 0x7D, 0x5E, 0x5A), + MBEDTLS_BYTES_TO_T_UINT_8(0x0A, 0xFA, 0xC1, 0x5F, 0x19, 0x37, 0x94, 0x9D), + MBEDTLS_BYTES_TO_T_UINT_8(0xCF, 0xBE, 0x6B, 0x1A, 0x05, 0xE4, 0xBF, 0x9F), + MBEDTLS_BYTES_TO_T_UINT_8(0x84, 0xCD, 0x5D, 0x35, 0xB4, 0x51, 0xF7, 0x64), +}; +static const mbedtls_mpi_uint secp256k1_T_13_Y[] = { + MBEDTLS_BYTES_TO_T_UINT_8(0x6C, 0xEF, 0x96, 0xDB, 0xF2, 0x61, 0x63, 0x59), + MBEDTLS_BYTES_TO_T_UINT_8(0xCB, 0x04, 0x88, 0xC9, 0x9F, 0x1B, 0x94, 0xB9), + MBEDTLS_BYTES_TO_T_UINT_8(0xDB, 0x30, 0x79, 0x7E, 0x24, 0xE7, 0x5F, 0xB8), + MBEDTLS_BYTES_TO_T_UINT_8(0x3F, 0xB8, 0x90, 0xB7, 0x94, 0x25, 0xBB, 0x0F), +}; +static const mbedtls_mpi_uint secp256k1_T_14_X[] = { + MBEDTLS_BYTES_TO_T_UINT_8(0x62, 0x79, 0xEA, 0xAD, 0xC0, 0x6D, 0x18, 0x57), + MBEDTLS_BYTES_TO_T_UINT_8(0xE9, 0xA4, 0x58, 0x2A, 0x8D, 0x95, 0xB3, 0xE6), + MBEDTLS_BYTES_TO_T_UINT_8(0xC8, 0xC4, 0xC2, 0x12, 0x0D, 0x79, 0xE2, 0x2B), + MBEDTLS_BYTES_TO_T_UINT_8(0x02, 0x6F, 0xBE, 0x97, 0x4D, 0xA4, 0x20, 0x07), +}; +static const mbedtls_mpi_uint secp256k1_T_14_Y[] = { + MBEDTLS_BYTES_TO_T_UINT_8(0xCA, 0x31, 0x71, 0xC6, 0xA6, 0x91, 0xEB, 0x1F), + MBEDTLS_BYTES_TO_T_UINT_8(0xB4, 0x9B, 0xA8, 0x4A, 0xE7, 0x77, 0xE1, 0xAA), + MBEDTLS_BYTES_TO_T_UINT_8(0xA9, 0x06, 0xD3, 0x3D, 0x94, 0x30, 0xEF, 0x8C), + MBEDTLS_BYTES_TO_T_UINT_8(0xE7, 0xDF, 0xCA, 0xFA, 0xF5, 0x28, 0xF8, 0xC9), +}; +static const mbedtls_mpi_uint secp256k1_T_15_X[] = { + MBEDTLS_BYTES_TO_T_UINT_8(0xCC, 0xE1, 0x32, 0xFD, 0x3E, 0x81, 0xF8, 0x11), + MBEDTLS_BYTES_TO_T_UINT_8(0xCD, 0xF2, 0x4B, 0x1D, 0x19, 0xC9, 0x0F, 0xCC), + MBEDTLS_BYTES_TO_T_UINT_8(0x59, 0xB1, 0x8A, 0x22, 0x8B, 0x05, 0x6B, 0x56), + MBEDTLS_BYTES_TO_T_UINT_8(0x35, 0x21, 0xEF, 0x30, 0xEC, 0x09, 0x2A, 0x89), +}; +static const mbedtls_mpi_uint secp256k1_T_15_Y[] = { + MBEDTLS_BYTES_TO_T_UINT_8(0x15, 0x84, 0x4A, 0x46, 0x07, 0x6C, 0x3C, 0x4C), + MBEDTLS_BYTES_TO_T_UINT_8(0xDD, 0x18, 0x3A, 0xF4, 0xCC, 0xF5, 0xB2, 0xF2), + MBEDTLS_BYTES_TO_T_UINT_8(0x4F, 0x8F, 0xCD, 0x0A, 0x9C, 0xF4, 0xBD, 0x95), + MBEDTLS_BYTES_TO_T_UINT_8(0x37, 0x89, 0x7F, 0x8A, 0xB1, 0x52, 0x3A, 0xAB), +}; +static const mbedtls_ecp_point secp256k1_T[16] = { + ECP_POINT_INIT_XY_Z1(secp256k1_T_0_X, secp256k1_T_0_Y), + ECP_POINT_INIT_XY_Z0(secp256k1_T_1_X, secp256k1_T_1_Y), + ECP_POINT_INIT_XY_Z0(secp256k1_T_2_X, secp256k1_T_2_Y), + ECP_POINT_INIT_XY_Z0(secp256k1_T_3_X, secp256k1_T_3_Y), + ECP_POINT_INIT_XY_Z0(secp256k1_T_4_X, secp256k1_T_4_Y), + ECP_POINT_INIT_XY_Z0(secp256k1_T_5_X, secp256k1_T_5_Y), + ECP_POINT_INIT_XY_Z0(secp256k1_T_6_X, secp256k1_T_6_Y), + ECP_POINT_INIT_XY_Z0(secp256k1_T_7_X, secp256k1_T_7_Y), + ECP_POINT_INIT_XY_Z0(secp256k1_T_8_X, secp256k1_T_8_Y), + ECP_POINT_INIT_XY_Z0(secp256k1_T_9_X, secp256k1_T_9_Y), + ECP_POINT_INIT_XY_Z0(secp256k1_T_10_X, secp256k1_T_10_Y), + ECP_POINT_INIT_XY_Z0(secp256k1_T_11_X, secp256k1_T_11_Y), + ECP_POINT_INIT_XY_Z0(secp256k1_T_12_X, secp256k1_T_12_Y), + ECP_POINT_INIT_XY_Z0(secp256k1_T_13_X, secp256k1_T_13_Y), + ECP_POINT_INIT_XY_Z0(secp256k1_T_14_X, secp256k1_T_14_Y), + ECP_POINT_INIT_XY_Z0(secp256k1_T_15_X, secp256k1_T_15_Y), +}; +#else +#define secp256k1_T NULL +#endif +#endif /* MBEDTLS_ECP_DP_SECP256K1_ENABLED */ + +/* + * Domain parameters for brainpoolP256r1 (RFC 5639 3.4) + */ +#if defined(MBEDTLS_ECP_DP_BP256R1_ENABLED) +static const mbedtls_mpi_uint brainpoolP256r1_p[] = { + MBEDTLS_BYTES_TO_T_UINT_8(0x77, 0x53, 0x6E, 0x1F, 0x1D, 0x48, 0x13, 0x20), + MBEDTLS_BYTES_TO_T_UINT_8(0x28, 0x20, 0x26, 0xD5, 0x23, 0xF6, 0x3B, 0x6E), + MBEDTLS_BYTES_TO_T_UINT_8(0x72, 0x8D, 0x83, 0x9D, 0x90, 0x0A, 0x66, 0x3E), + MBEDTLS_BYTES_TO_T_UINT_8(0xBC, 0xA9, 0xEE, 0xA1, 0xDB, 0x57, 0xFB, 0xA9), +}; +static const mbedtls_mpi_uint brainpoolP256r1_a[] = { + MBEDTLS_BYTES_TO_T_UINT_8(0xD9, 0xB5, 0x30, 0xF3, 0x44, 0x4B, 0x4A, 0xE9), + MBEDTLS_BYTES_TO_T_UINT_8(0x6C, 0x5C, 0xDC, 0x26, 0xC1, 0x55, 0x80, 0xFB), + MBEDTLS_BYTES_TO_T_UINT_8(0xE7, 0xFF, 0x7A, 0x41, 0x30, 0x75, 0xF6, 0xEE), + MBEDTLS_BYTES_TO_T_UINT_8(0x57, 0x30, 0x2C, 0xFC, 0x75, 0x09, 0x5A, 0x7D), +}; +static const mbedtls_mpi_uint brainpoolP256r1_b[] = { + MBEDTLS_BYTES_TO_T_UINT_8(0xB6, 0x07, 0x8C, 0xFF, 0x18, 0xDC, 0xCC, 0x6B), + MBEDTLS_BYTES_TO_T_UINT_8(0xCE, 0xE1, 0xF7, 0x5C, 0x29, 0x16, 0x84, 0x95), + MBEDTLS_BYTES_TO_T_UINT_8(0xBF, 0x7C, 0xD7, 0xBB, 0xD9, 0xB5, 0x30, 0xF3), + MBEDTLS_BYTES_TO_T_UINT_8(0x44, 0x4B, 0x4A, 0xE9, 0x6C, 0x5C, 0xDC, 0x26), +}; +static const mbedtls_mpi_uint brainpoolP256r1_gx[] = { + MBEDTLS_BYTES_TO_T_UINT_8(0x62, 0x32, 0xCE, 0x9A, 0xBD, 0x53, 0x44, 0x3A), + MBEDTLS_BYTES_TO_T_UINT_8(0xC2, 0x23, 0xBD, 0xE3, 0xE1, 0x27, 0xDE, 0xB9), + MBEDTLS_BYTES_TO_T_UINT_8(0xAF, 0xB7, 0x81, 0xFC, 0x2F, 0x48, 0x4B, 0x2C), + MBEDTLS_BYTES_TO_T_UINT_8(0xCB, 0x57, 0x7E, 0xCB, 0xB9, 0xAE, 0xD2, 0x8B), +}; +static const mbedtls_mpi_uint brainpoolP256r1_gy[] = { + MBEDTLS_BYTES_TO_T_UINT_8(0x97, 0x69, 0x04, 0x2F, 0xC7, 0x54, 0x1D, 0x5C), + MBEDTLS_BYTES_TO_T_UINT_8(0x54, 0x8E, 0xED, 0x2D, 0x13, 0x45, 0x77, 0xC2), + MBEDTLS_BYTES_TO_T_UINT_8(0xC9, 0x1D, 0x61, 0x14, 0x1A, 0x46, 0xF8, 0x97), + MBEDTLS_BYTES_TO_T_UINT_8(0xFD, 0xC4, 0xDA, 0xC3, 0x35, 0xF8, 0x7E, 0x54), +}; +static const mbedtls_mpi_uint brainpoolP256r1_n[] = { + MBEDTLS_BYTES_TO_T_UINT_8(0xA7, 0x56, 0x48, 0x97, 0x82, 0x0E, 0x1E, 0x90), + MBEDTLS_BYTES_TO_T_UINT_8(0xF7, 0xA6, 0x61, 0xB5, 0xA3, 0x7A, 0x39, 0x8C), + MBEDTLS_BYTES_TO_T_UINT_8(0x71, 0x8D, 0x83, 0x9D, 0x90, 0x0A, 0x66, 0x3E), + MBEDTLS_BYTES_TO_T_UINT_8(0xBC, 0xA9, 0xEE, 0xA1, 0xDB, 0x57, 0xFB, 0xA9), +}; + +#if MBEDTLS_ECP_FIXED_POINT_OPTIM == 1 +static const mbedtls_mpi_uint brainpoolP256r1_T_0_X[] = { + MBEDTLS_BYTES_TO_T_UINT_8(0x62, 0x32, 0xCE, 0x9A, 0xBD, 0x53, 0x44, 0x3A), + MBEDTLS_BYTES_TO_T_UINT_8(0xC2, 0x23, 0xBD, 0xE3, 0xE1, 0x27, 0xDE, 0xB9), + MBEDTLS_BYTES_TO_T_UINT_8(0xAF, 0xB7, 0x81, 0xFC, 0x2F, 0x48, 0x4B, 0x2C), + MBEDTLS_BYTES_TO_T_UINT_8(0xCB, 0x57, 0x7E, 0xCB, 0xB9, 0xAE, 0xD2, 0x8B), +}; +static const mbedtls_mpi_uint brainpoolP256r1_T_0_Y[] = { + MBEDTLS_BYTES_TO_T_UINT_8(0x97, 0x69, 0x04, 0x2F, 0xC7, 0x54, 0x1D, 0x5C), + MBEDTLS_BYTES_TO_T_UINT_8(0x54, 0x8E, 0xED, 0x2D, 0x13, 0x45, 0x77, 0xC2), + MBEDTLS_BYTES_TO_T_UINT_8(0xC9, 0x1D, 0x61, 0x14, 0x1A, 0x46, 0xF8, 0x97), + MBEDTLS_BYTES_TO_T_UINT_8(0xFD, 0xC4, 0xDA, 0xC3, 0x35, 0xF8, 0x7E, 0x54), +}; +static const mbedtls_mpi_uint brainpoolP256r1_T_1_X[] = { + MBEDTLS_BYTES_TO_T_UINT_8(0x3C, 0xA2, 0xED, 0x52, 0xC9, 0x8C, 0xE3, 0xA5), + MBEDTLS_BYTES_TO_T_UINT_8(0x72, 0xC9, 0xC4, 0x87, 0x3F, 0x93, 0x7A, 0xD1), + MBEDTLS_BYTES_TO_T_UINT_8(0x96, 0x12, 0x53, 0x61, 0x3E, 0x76, 0x08, 0xCB), + MBEDTLS_BYTES_TO_T_UINT_8(0x09, 0x8C, 0x74, 0xF4, 0x08, 0xC3, 0x76, 0x80), +}; +static const mbedtls_mpi_uint brainpoolP256r1_T_1_Y[] = { + MBEDTLS_BYTES_TO_T_UINT_8(0x05, 0xDD, 0x09, 0xA6, 0xED, 0xEE, 0xC4, 0x38), + MBEDTLS_BYTES_TO_T_UINT_8(0x74, 0xD9, 0xBE, 0x4B, 0xA5, 0xB7, 0x2B, 0x6E), + MBEDTLS_BYTES_TO_T_UINT_8(0x42, 0x20, 0x12, 0xCA, 0x0A, 0x38, 0x24, 0xAB), + MBEDTLS_BYTES_TO_T_UINT_8(0x00, 0x72, 0x71, 0x90, 0x7A, 0x2E, 0xB7, 0x23), +}; +static const mbedtls_mpi_uint brainpoolP256r1_T_2_X[] = { + MBEDTLS_BYTES_TO_T_UINT_8(0x2C, 0x66, 0xA1, 0x93, 0x10, 0x2A, 0x51, 0x17), + MBEDTLS_BYTES_TO_T_UINT_8(0x88, 0x10, 0x11, 0x12, 0xBC, 0xB0, 0xB6, 0x93), + MBEDTLS_BYTES_TO_T_UINT_8(0x3C, 0x58, 0xD7, 0x0A, 0x84, 0x05, 0xA3, 0x9C), + MBEDTLS_BYTES_TO_T_UINT_8(0xF7, 0x8E, 0x95, 0x61, 0xD3, 0x0B, 0xDF, 0x36), +}; +static const mbedtls_mpi_uint brainpoolP256r1_T_2_Y[] = { + MBEDTLS_BYTES_TO_T_UINT_8(0xF9, 0x92, 0x12, 0x0F, 0x5E, 0x87, 0x70, 0x1B), + MBEDTLS_BYTES_TO_T_UINT_8(0x38, 0xE9, 0x9B, 0xEB, 0x3A, 0xFB, 0xCF, 0xC4), + MBEDTLS_BYTES_TO_T_UINT_8(0xDC, 0x92, 0xB9, 0xF7, 0x45, 0xD3, 0x06, 0xB6), + MBEDTLS_BYTES_TO_T_UINT_8(0x82, 0x28, 0x65, 0xE1, 0xC5, 0x6C, 0x57, 0x18), +}; +static const mbedtls_mpi_uint brainpoolP256r1_T_3_X[] = { + MBEDTLS_BYTES_TO_T_UINT_8(0x28, 0x0E, 0x77, 0x01, 0x81, 0x9E, 0x38, 0x5C), + MBEDTLS_BYTES_TO_T_UINT_8(0x71, 0xF0, 0xD5, 0xA5, 0x91, 0x2B, 0xDF, 0xC0), + MBEDTLS_BYTES_TO_T_UINT_8(0xD8, 0xEE, 0xB6, 0x25, 0xD6, 0x98, 0xDE, 0x2D), + MBEDTLS_BYTES_TO_T_UINT_8(0x7B, 0xA1, 0x55, 0x63, 0x39, 0xEB, 0xB5, 0x47), +}; +static const mbedtls_mpi_uint brainpoolP256r1_T_3_Y[] = { + MBEDTLS_BYTES_TO_T_UINT_8(0xB6, 0xD6, 0xB8, 0xE3, 0x13, 0xED, 0x7F, 0xA3), + MBEDTLS_BYTES_TO_T_UINT_8(0x6C, 0xE8, 0xAE, 0x36, 0xB8, 0xCD, 0x19, 0x02), + MBEDTLS_BYTES_TO_T_UINT_8(0xF9, 0x82, 0x83, 0x7A, 0x7B, 0x46, 0x56, 0xE8), + MBEDTLS_BYTES_TO_T_UINT_8(0x4E, 0x60, 0x46, 0x15, 0x5A, 0xAC, 0x99, 0x30), +}; +static const mbedtls_mpi_uint brainpoolP256r1_T_4_X[] = { + MBEDTLS_BYTES_TO_T_UINT_8(0xBF, 0x61, 0x50, 0xC6, 0xFF, 0x10, 0x7D, 0x04), + MBEDTLS_BYTES_TO_T_UINT_8(0x92, 0x51, 0xDF, 0xA9, 0x7D, 0x78, 0x26, 0x74), + MBEDTLS_BYTES_TO_T_UINT_8(0x56, 0x15, 0x9A, 0xF7, 0x01, 0xC1, 0xBB, 0x40), + MBEDTLS_BYTES_TO_T_UINT_8(0x26, 0x0F, 0xE6, 0x2A, 0xBD, 0x4A, 0x9E, 0x87), +}; +static const mbedtls_mpi_uint brainpoolP256r1_T_4_Y[] = { + MBEDTLS_BYTES_TO_T_UINT_8(0x57, 0xF8, 0xD1, 0x77, 0xD2, 0x49, 0xB3, 0xDD), + MBEDTLS_BYTES_TO_T_UINT_8(0x36, 0x86, 0xFB, 0x9E, 0x1F, 0x5A, 0x60, 0x47), + MBEDTLS_BYTES_TO_T_UINT_8(0x98, 0xC4, 0x8D, 0xCD, 0x86, 0x61, 0x2F, 0xF9), + MBEDTLS_BYTES_TO_T_UINT_8(0x41, 0xF6, 0xB9, 0xAC, 0x37, 0x9D, 0xE9, 0x28), +}; +static const mbedtls_mpi_uint brainpoolP256r1_T_5_X[] = { + MBEDTLS_BYTES_TO_T_UINT_8(0xFA, 0x77, 0xAA, 0x97, 0x9C, 0x0B, 0x04, 0x20), + MBEDTLS_BYTES_TO_T_UINT_8(0x80, 0xA6, 0x60, 0x81, 0xCE, 0x25, 0x13, 0x3E), + MBEDTLS_BYTES_TO_T_UINT_8(0x24, 0x00, 0xF3, 0xBB, 0x82, 0x99, 0x95, 0xB7), + MBEDTLS_BYTES_TO_T_UINT_8(0x47, 0x5A, 0xCE, 0x90, 0x71, 0x38, 0x2F, 0x10), +}; +static const mbedtls_mpi_uint brainpoolP256r1_T_5_Y[] = { + MBEDTLS_BYTES_TO_T_UINT_8(0xA7, 0x1A, 0xC0, 0x84, 0x27, 0xD6, 0x9D, 0xB7), + MBEDTLS_BYTES_TO_T_UINT_8(0x34, 0x37, 0x52, 0x16, 0x13, 0x0E, 0xCE, 0x92), + MBEDTLS_BYTES_TO_T_UINT_8(0x1E, 0xBF, 0x5A, 0xDB, 0xDB, 0x6E, 0x1E, 0x69), + MBEDTLS_BYTES_TO_T_UINT_8(0x3E, 0xB7, 0x5E, 0xF9, 0x86, 0xDD, 0x8A, 0x5C), +}; +static const mbedtls_mpi_uint brainpoolP256r1_T_6_X[] = { + MBEDTLS_BYTES_TO_T_UINT_8(0x3D, 0xAB, 0x5C, 0x8D, 0x1D, 0xF2, 0x2D, 0x1E), + MBEDTLS_BYTES_TO_T_UINT_8(0x65, 0xC5, 0xF8, 0xF7, 0x1D, 0x96, 0x0B, 0x4D), + MBEDTLS_BYTES_TO_T_UINT_8(0xAC, 0x4C, 0xA7, 0x45, 0x20, 0x6A, 0x1E, 0x5B), + MBEDTLS_BYTES_TO_T_UINT_8(0x21, 0x5D, 0xEF, 0xDE, 0xEE, 0x39, 0x44, 0x19), +}; +static const mbedtls_mpi_uint brainpoolP256r1_T_6_Y[] = { + MBEDTLS_BYTES_TO_T_UINT_8(0x4B, 0x2F, 0x6D, 0x52, 0xC9, 0x58, 0x60, 0xE8), + MBEDTLS_BYTES_TO_T_UINT_8(0xC3, 0xC9, 0x62, 0xCB, 0x38, 0x3C, 0x55, 0xCA), + MBEDTLS_BYTES_TO_T_UINT_8(0xFF, 0xA5, 0x09, 0x10, 0x88, 0xDB, 0xE3, 0xBD), + MBEDTLS_BYTES_TO_T_UINT_8(0x52, 0xE0, 0x3C, 0xCE, 0x06, 0x0B, 0x4B, 0x5D), +}; +static const mbedtls_mpi_uint brainpoolP256r1_T_7_X[] = { + MBEDTLS_BYTES_TO_T_UINT_8(0xB1, 0x1D, 0xB4, 0x10, 0x76, 0x8F, 0xBA, 0x09), + MBEDTLS_BYTES_TO_T_UINT_8(0x57, 0x70, 0x5A, 0x07, 0xF5, 0x1A, 0x74, 0xC7), + MBEDTLS_BYTES_TO_T_UINT_8(0x0B, 0xE9, 0x94, 0xA8, 0xC0, 0xD5, 0x4A, 0x4A), + MBEDTLS_BYTES_TO_T_UINT_8(0x3E, 0x6D, 0xD4, 0xE8, 0x9B, 0xE9, 0x6D, 0x0E), +}; +static const mbedtls_mpi_uint brainpoolP256r1_T_7_Y[] = { + MBEDTLS_BYTES_TO_T_UINT_8(0x65, 0x00, 0x32, 0x41, 0x57, 0x84, 0x89, 0x52), + MBEDTLS_BYTES_TO_T_UINT_8(0xEE, 0xC7, 0x14, 0xEC, 0xE9, 0x27, 0xFF, 0xF3), + MBEDTLS_BYTES_TO_T_UINT_8(0x9A, 0x67, 0x9E, 0xFB, 0xB6, 0xB8, 0x96, 0xF3), + MBEDTLS_BYTES_TO_T_UINT_8(0xE5, 0x4A, 0xE3, 0x97, 0x4B, 0x58, 0xDE, 0x30), +}; +static const mbedtls_mpi_uint brainpoolP256r1_T_8_X[] = { + MBEDTLS_BYTES_TO_T_UINT_8(0xA6, 0x1E, 0x5C, 0xF5, 0x7F, 0xD5, 0xD4, 0xAA), + MBEDTLS_BYTES_TO_T_UINT_8(0x5D, 0x08, 0x7A, 0xF1, 0xBD, 0x89, 0xC7, 0x1E), + MBEDTLS_BYTES_TO_T_UINT_8(0x3A, 0xF9, 0x11, 0x1B, 0xF5, 0x3C, 0x6D, 0x8C), + MBEDTLS_BYTES_TO_T_UINT_8(0x19, 0x50, 0xE5, 0x69, 0x1D, 0x59, 0xFC, 0x0C), +}; +static const mbedtls_mpi_uint brainpoolP256r1_T_8_Y[] = { + MBEDTLS_BYTES_TO_T_UINT_8(0xF1, 0x2F, 0xF8, 0x3F, 0xEC, 0x55, 0x99, 0x57), + MBEDTLS_BYTES_TO_T_UINT_8(0x41, 0xA7, 0x29, 0x90, 0x43, 0x81, 0x31, 0x4C), + MBEDTLS_BYTES_TO_T_UINT_8(0xC3, 0x18, 0x44, 0x50, 0x5D, 0x76, 0xCB, 0xDD), + MBEDTLS_BYTES_TO_T_UINT_8(0xF0, 0xC5, 0x5B, 0x9A, 0x03, 0xE6, 0x17, 0x39), +}; +static const mbedtls_mpi_uint brainpoolP256r1_T_9_X[] = { + MBEDTLS_BYTES_TO_T_UINT_8(0x21, 0x89, 0xFC, 0x55, 0x94, 0x91, 0x6A, 0xA2), + MBEDTLS_BYTES_TO_T_UINT_8(0x74, 0x46, 0x35, 0xF2, 0x3A, 0x42, 0x08, 0x2F), + MBEDTLS_BYTES_TO_T_UINT_8(0xD3, 0xD2, 0x76, 0x49, 0x42, 0x87, 0xD3, 0x7F), + MBEDTLS_BYTES_TO_T_UINT_8(0x90, 0xEA, 0xA0, 0x52, 0xF1, 0x6A, 0x30, 0x57), +}; +static const mbedtls_mpi_uint brainpoolP256r1_T_9_Y[] = { + MBEDTLS_BYTES_TO_T_UINT_8(0x00, 0xB2, 0x57, 0xA3, 0x8A, 0x4D, 0x1B, 0x3C), + MBEDTLS_BYTES_TO_T_UINT_8(0xFC, 0xA3, 0x99, 0x94, 0xB5, 0x3D, 0x64, 0x09), + MBEDTLS_BYTES_TO_T_UINT_8(0x35, 0xC3, 0xD7, 0x53, 0xF6, 0x49, 0x1C, 0x60), + MBEDTLS_BYTES_TO_T_UINT_8(0x27, 0x23, 0x41, 0x4D, 0xFB, 0x7A, 0x5C, 0x53), +}; +static const mbedtls_mpi_uint brainpoolP256r1_T_10_X[] = { + MBEDTLS_BYTES_TO_T_UINT_8(0xCA, 0xB8, 0x15, 0x65, 0x5C, 0x85, 0x94, 0xD7), + MBEDTLS_BYTES_TO_T_UINT_8(0xAC, 0x37, 0xC7, 0xF8, 0x7E, 0xAE, 0x6C, 0x10), + MBEDTLS_BYTES_TO_T_UINT_8(0x53, 0xD8, 0x11, 0x54, 0x98, 0x44, 0xE3, 0xF1), + MBEDTLS_BYTES_TO_T_UINT_8(0xE4, 0x4D, 0xA6, 0x4B, 0x28, 0xF2, 0x57, 0x9E), +}; +static const mbedtls_mpi_uint brainpoolP256r1_T_10_Y[] = { + MBEDTLS_BYTES_TO_T_UINT_8(0xF6, 0xD0, 0xEB, 0x1E, 0xAA, 0x30, 0xD3, 0x6A), + MBEDTLS_BYTES_TO_T_UINT_8(0x58, 0x9B, 0x4D, 0xA7, 0x73, 0x6E, 0xB6, 0x45), + MBEDTLS_BYTES_TO_T_UINT_8(0x5D, 0x47, 0xF6, 0xED, 0x37, 0xEF, 0x71, 0x4D), + MBEDTLS_BYTES_TO_T_UINT_8(0xA8, 0xB5, 0x49, 0x61, 0x5E, 0x45, 0xF6, 0x4A), +}; +static const mbedtls_mpi_uint brainpoolP256r1_T_11_X[] = { + MBEDTLS_BYTES_TO_T_UINT_8(0xEF, 0x0E, 0xB3, 0x84, 0x3A, 0x63, 0x72, 0x84), + MBEDTLS_BYTES_TO_T_UINT_8(0x6D, 0x53, 0x5C, 0xA7, 0xC6, 0x2E, 0xAB, 0x9E), + MBEDTLS_BYTES_TO_T_UINT_8(0xEB, 0x0F, 0x8F, 0x87, 0x50, 0x28, 0xB4, 0xAE), + MBEDTLS_BYTES_TO_T_UINT_8(0x5C, 0x98, 0x4A, 0x98, 0x31, 0x86, 0xCA, 0x51), +}; +static const mbedtls_mpi_uint brainpoolP256r1_T_11_Y[] = { + MBEDTLS_BYTES_TO_T_UINT_8(0xBE, 0xC9, 0xE2, 0xFD, 0x5D, 0x1F, 0xE8, 0xC2), + MBEDTLS_BYTES_TO_T_UINT_8(0xD5, 0x90, 0x91, 0xC4, 0x84, 0xF0, 0xBA, 0xC5), + MBEDTLS_BYTES_TO_T_UINT_8(0x6C, 0x5A, 0xB3, 0x4E, 0xFB, 0xE0, 0x57, 0xE8), + MBEDTLS_BYTES_TO_T_UINT_8(0x6B, 0x0B, 0x90, 0xA6, 0xFD, 0x9D, 0x8E, 0x02), +}; +static const mbedtls_mpi_uint brainpoolP256r1_T_12_X[] = { + MBEDTLS_BYTES_TO_T_UINT_8(0xF8, 0x41, 0x8F, 0x31, 0xFA, 0x5A, 0xF6, 0x33), + MBEDTLS_BYTES_TO_T_UINT_8(0xAC, 0xE9, 0xE3, 0xF6, 0xE0, 0x4A, 0xE7, 0xD2), + MBEDTLS_BYTES_TO_T_UINT_8(0x84, 0x4E, 0xCD, 0xA2, 0x22, 0x14, 0xD4, 0x12), + MBEDTLS_BYTES_TO_T_UINT_8(0x7C, 0xED, 0x21, 0xB7, 0x0F, 0x53, 0x10, 0x17), +}; +static const mbedtls_mpi_uint brainpoolP256r1_T_12_Y[] = { + MBEDTLS_BYTES_TO_T_UINT_8(0x05, 0x06, 0x24, 0x2C, 0x4E, 0xD1, 0x1E, 0x9F), + MBEDTLS_BYTES_TO_T_UINT_8(0xD7, 0x3F, 0xC1, 0x9F, 0xAB, 0xF0, 0x37, 0x95), + MBEDTLS_BYTES_TO_T_UINT_8(0x03, 0x5E, 0x12, 0xCE, 0x83, 0x1B, 0x2A, 0x18), + MBEDTLS_BYTES_TO_T_UINT_8(0x61, 0x65, 0xCF, 0xE8, 0x5C, 0xA5, 0xA2, 0x70), +}; +static const mbedtls_mpi_uint brainpoolP256r1_T_13_X[] = { + MBEDTLS_BYTES_TO_T_UINT_8(0xB8, 0x86, 0x76, 0x3A, 0x94, 0xF6, 0x1D, 0xC1), + MBEDTLS_BYTES_TO_T_UINT_8(0x1D, 0xDA, 0xC9, 0xA6, 0x29, 0x93, 0x15, 0x10), + MBEDTLS_BYTES_TO_T_UINT_8(0x6D, 0x61, 0x6A, 0x7D, 0xC7, 0xA9, 0xF3, 0x76), + MBEDTLS_BYTES_TO_T_UINT_8(0x4A, 0x03, 0x71, 0xA2, 0x15, 0xCE, 0x50, 0x72), +}; +static const mbedtls_mpi_uint brainpoolP256r1_T_13_Y[] = { + MBEDTLS_BYTES_TO_T_UINT_8(0xB6, 0xD0, 0xA8, 0x1E, 0x91, 0xC4, 0x4F, 0x24), + MBEDTLS_BYTES_TO_T_UINT_8(0x2D, 0x4B, 0x7E, 0xD7, 0x71, 0x58, 0x7E, 0x1E), + MBEDTLS_BYTES_TO_T_UINT_8(0x93, 0x45, 0xAF, 0x2A, 0x18, 0x93, 0x95, 0x3B), + MBEDTLS_BYTES_TO_T_UINT_8(0x1B, 0x8F, 0xC7, 0xFA, 0x4C, 0x7A, 0x86, 0x54), +}; +static const mbedtls_mpi_uint brainpoolP256r1_T_14_X[] = { + MBEDTLS_BYTES_TO_T_UINT_8(0x97, 0xAF, 0x68, 0x3A, 0x23, 0xC1, 0x2E, 0xBF), + MBEDTLS_BYTES_TO_T_UINT_8(0x89, 0x50, 0x11, 0x67, 0x39, 0xB9, 0xAF, 0x48), + MBEDTLS_BYTES_TO_T_UINT_8(0x19, 0x86, 0xAA, 0x1E, 0x88, 0x21, 0x29, 0x8B), + MBEDTLS_BYTES_TO_T_UINT_8(0xCD, 0x28, 0xA4, 0x9D, 0x89, 0xA9, 0x9A, 0x10), +}; +static const mbedtls_mpi_uint brainpoolP256r1_T_14_Y[] = { + MBEDTLS_BYTES_TO_T_UINT_8(0x91, 0xBA, 0x04, 0x67, 0xB7, 0x01, 0x40, 0x38), + MBEDTLS_BYTES_TO_T_UINT_8(0x08, 0xE9, 0x09, 0xA3, 0xCA, 0xA6, 0x37, 0xF6), + MBEDTLS_BYTES_TO_T_UINT_8(0x6C, 0x97, 0xA8, 0xB6, 0x3C, 0xEE, 0x90, 0x3D), + MBEDTLS_BYTES_TO_T_UINT_8(0xDC, 0xED, 0xC4, 0xF7, 0xC3, 0x95, 0xEC, 0x85), +}; +static const mbedtls_mpi_uint brainpoolP256r1_T_15_X[] = { + MBEDTLS_BYTES_TO_T_UINT_8(0xF5, 0x84, 0xBD, 0xEB, 0xD5, 0x64, 0xBB, 0x9D), + MBEDTLS_BYTES_TO_T_UINT_8(0xDB, 0x9B, 0xE2, 0x28, 0x50, 0xC2, 0x72, 0x40), + MBEDTLS_BYTES_TO_T_UINT_8(0x39, 0xF2, 0x74, 0xD1, 0x26, 0xBF, 0x32, 0x68), + MBEDTLS_BYTES_TO_T_UINT_8(0x36, 0xCB, 0xAF, 0x72, 0xDB, 0x6D, 0x30, 0x98), +}; +static const mbedtls_mpi_uint brainpoolP256r1_T_15_Y[] = { + MBEDTLS_BYTES_TO_T_UINT_8(0xB3, 0x50, 0x85, 0xF4, 0x2B, 0x48, 0xC1, 0xAD), + MBEDTLS_BYTES_TO_T_UINT_8(0xC0, 0x28, 0xBB, 0x11, 0xBA, 0x5B, 0x22, 0x6C), + MBEDTLS_BYTES_TO_T_UINT_8(0xAD, 0xA1, 0xE5, 0x5C, 0xC9, 0x1D, 0x44, 0x45), + MBEDTLS_BYTES_TO_T_UINT_8(0xD4, 0xE8, 0xE6, 0x6F, 0xBB, 0xC1, 0x81, 0x7F), +}; +static const mbedtls_ecp_point brainpoolP256r1_T[16] = { + ECP_POINT_INIT_XY_Z1(brainpoolP256r1_T_0_X, brainpoolP256r1_T_0_Y), + ECP_POINT_INIT_XY_Z0(brainpoolP256r1_T_1_X, brainpoolP256r1_T_1_Y), + ECP_POINT_INIT_XY_Z0(brainpoolP256r1_T_2_X, brainpoolP256r1_T_2_Y), + ECP_POINT_INIT_XY_Z0(brainpoolP256r1_T_3_X, brainpoolP256r1_T_3_Y), + ECP_POINT_INIT_XY_Z0(brainpoolP256r1_T_4_X, brainpoolP256r1_T_4_Y), + ECP_POINT_INIT_XY_Z0(brainpoolP256r1_T_5_X, brainpoolP256r1_T_5_Y), + ECP_POINT_INIT_XY_Z0(brainpoolP256r1_T_6_X, brainpoolP256r1_T_6_Y), + ECP_POINT_INIT_XY_Z0(brainpoolP256r1_T_7_X, brainpoolP256r1_T_7_Y), + ECP_POINT_INIT_XY_Z0(brainpoolP256r1_T_8_X, brainpoolP256r1_T_8_Y), + ECP_POINT_INIT_XY_Z0(brainpoolP256r1_T_9_X, brainpoolP256r1_T_9_Y), + ECP_POINT_INIT_XY_Z0(brainpoolP256r1_T_10_X, brainpoolP256r1_T_10_Y), + ECP_POINT_INIT_XY_Z0(brainpoolP256r1_T_11_X, brainpoolP256r1_T_11_Y), + ECP_POINT_INIT_XY_Z0(brainpoolP256r1_T_12_X, brainpoolP256r1_T_12_Y), + ECP_POINT_INIT_XY_Z0(brainpoolP256r1_T_13_X, brainpoolP256r1_T_13_Y), + ECP_POINT_INIT_XY_Z0(brainpoolP256r1_T_14_X, brainpoolP256r1_T_14_Y), + ECP_POINT_INIT_XY_Z0(brainpoolP256r1_T_15_X, brainpoolP256r1_T_15_Y), +}; +#else +#define brainpoolP256r1_T NULL +#endif + +#endif /* MBEDTLS_ECP_DP_BP256R1_ENABLED */ + +/* + * Domain parameters for brainpoolP384r1 (RFC 5639 3.6) + */ +#if defined(MBEDTLS_ECP_DP_BP384R1_ENABLED) +static const mbedtls_mpi_uint brainpoolP384r1_p[] = { + MBEDTLS_BYTES_TO_T_UINT_8(0x53, 0xEC, 0x07, 0x31, 0x13, 0x00, 0x47, 0x87), + MBEDTLS_BYTES_TO_T_UINT_8(0x71, 0x1A, 0x1D, 0x90, 0x29, 0xA7, 0xD3, 0xAC), + MBEDTLS_BYTES_TO_T_UINT_8(0x23, 0x11, 0xB7, 0x7F, 0x19, 0xDA, 0xB1, 0x12), + MBEDTLS_BYTES_TO_T_UINT_8(0xB4, 0x56, 0x54, 0xED, 0x09, 0x71, 0x2F, 0x15), + MBEDTLS_BYTES_TO_T_UINT_8(0xDF, 0x41, 0xE6, 0x50, 0x7E, 0x6F, 0x5D, 0x0F), + MBEDTLS_BYTES_TO_T_UINT_8(0x28, 0x6D, 0x38, 0xA3, 0x82, 0x1E, 0xB9, 0x8C), +}; +static const mbedtls_mpi_uint brainpoolP384r1_a[] = { + MBEDTLS_BYTES_TO_T_UINT_8(0x26, 0x28, 0xCE, 0x22, 0xDD, 0xC7, 0xA8, 0x04), + MBEDTLS_BYTES_TO_T_UINT_8(0xEB, 0xD4, 0x3A, 0x50, 0x4A, 0x81, 0xA5, 0x8A), + MBEDTLS_BYTES_TO_T_UINT_8(0x0F, 0xF9, 0x91, 0xBA, 0xEF, 0x65, 0x91, 0x13), + MBEDTLS_BYTES_TO_T_UINT_8(0x87, 0x27, 0xB2, 0x4F, 0x8E, 0xA2, 0xBE, 0xC2), + MBEDTLS_BYTES_TO_T_UINT_8(0xA0, 0xAF, 0x05, 0xCE, 0x0A, 0x08, 0x72, 0x3C), + MBEDTLS_BYTES_TO_T_UINT_8(0x0C, 0x15, 0x8C, 0x3D, 0xC6, 0x82, 0xC3, 0x7B), +}; +static const mbedtls_mpi_uint brainpoolP384r1_b[] = { + MBEDTLS_BYTES_TO_T_UINT_8(0x11, 0x4C, 0x50, 0xFA, 0x96, 0x86, 0xB7, 0x3A), + MBEDTLS_BYTES_TO_T_UINT_8(0x94, 0xC9, 0xDB, 0x95, 0x02, 0x39, 0xB4, 0x7C), + MBEDTLS_BYTES_TO_T_UINT_8(0xD5, 0x62, 0xEB, 0x3E, 0xA5, 0x0E, 0x88, 0x2E), + MBEDTLS_BYTES_TO_T_UINT_8(0xA6, 0xD2, 0xDC, 0x07, 0xE1, 0x7D, 0xB7, 0x2F), + MBEDTLS_BYTES_TO_T_UINT_8(0x7C, 0x44, 0xF0, 0x16, 0x54, 0xB5, 0x39, 0x8B), + MBEDTLS_BYTES_TO_T_UINT_8(0x26, 0x28, 0xCE, 0x22, 0xDD, 0xC7, 0xA8, 0x04), +}; +static const mbedtls_mpi_uint brainpoolP384r1_gx[] = { + MBEDTLS_BYTES_TO_T_UINT_8(0x1E, 0xAF, 0xD4, 0x47, 0xE2, 0xB2, 0x87, 0xEF), + MBEDTLS_BYTES_TO_T_UINT_8(0xAA, 0x46, 0xD6, 0x36, 0x34, 0xE0, 0x26, 0xE8), + MBEDTLS_BYTES_TO_T_UINT_8(0xE8, 0x10, 0xBD, 0x0C, 0xFE, 0xCA, 0x7F, 0xDB), + MBEDTLS_BYTES_TO_T_UINT_8(0xE3, 0x4F, 0xF1, 0x7E, 0xE7, 0xA3, 0x47, 0x88), + MBEDTLS_BYTES_TO_T_UINT_8(0x6B, 0x3F, 0xC1, 0xB7, 0x81, 0x3A, 0xA6, 0xA2), + MBEDTLS_BYTES_TO_T_UINT_8(0xFF, 0x45, 0xCF, 0x68, 0xF0, 0x64, 0x1C, 0x1D), +}; +static const mbedtls_mpi_uint brainpoolP384r1_gy[] = { + MBEDTLS_BYTES_TO_T_UINT_8(0x15, 0x53, 0x3C, 0x26, 0x41, 0x03, 0x82, 0x42), + MBEDTLS_BYTES_TO_T_UINT_8(0x11, 0x81, 0x91, 0x77, 0x21, 0x46, 0x46, 0x0E), + MBEDTLS_BYTES_TO_T_UINT_8(0x28, 0x29, 0x91, 0xF9, 0x4F, 0x05, 0x9C, 0xE1), + MBEDTLS_BYTES_TO_T_UINT_8(0x64, 0x58, 0xEC, 0xFE, 0x29, 0x0B, 0xB7, 0x62), + MBEDTLS_BYTES_TO_T_UINT_8(0x52, 0xD5, 0xCF, 0x95, 0x8E, 0xEB, 0xB1, 0x5C), + MBEDTLS_BYTES_TO_T_UINT_8(0xA4, 0xC2, 0xF9, 0x20, 0x75, 0x1D, 0xBE, 0x8A), +}; +static const mbedtls_mpi_uint brainpoolP384r1_n[] = { + MBEDTLS_BYTES_TO_T_UINT_8(0x65, 0x65, 0x04, 0xE9, 0x02, 0x32, 0x88, 0x3B), + MBEDTLS_BYTES_TO_T_UINT_8(0x10, 0xC3, 0x7F, 0x6B, 0xAF, 0xB6, 0x3A, 0xCF), + MBEDTLS_BYTES_TO_T_UINT_8(0xA7, 0x25, 0x04, 0xAC, 0x6C, 0x6E, 0x16, 0x1F), + MBEDTLS_BYTES_TO_T_UINT_8(0xB3, 0x56, 0x54, 0xED, 0x09, 0x71, 0x2F, 0x15), + MBEDTLS_BYTES_TO_T_UINT_8(0xDF, 0x41, 0xE6, 0x50, 0x7E, 0x6F, 0x5D, 0x0F), + MBEDTLS_BYTES_TO_T_UINT_8(0x28, 0x6D, 0x38, 0xA3, 0x82, 0x1E, 0xB9, 0x8C), +}; + +#if MBEDTLS_ECP_FIXED_POINT_OPTIM == 1 +static const mbedtls_mpi_uint brainpoolP384r1_T_0_X[] = { + MBEDTLS_BYTES_TO_T_UINT_8(0x1E, 0xAF, 0xD4, 0x47, 0xE2, 0xB2, 0x87, 0xEF), + MBEDTLS_BYTES_TO_T_UINT_8(0xAA, 0x46, 0xD6, 0x36, 0x34, 0xE0, 0x26, 0xE8), + MBEDTLS_BYTES_TO_T_UINT_8(0xE8, 0x10, 0xBD, 0x0C, 0xFE, 0xCA, 0x7F, 0xDB), + MBEDTLS_BYTES_TO_T_UINT_8(0xE3, 0x4F, 0xF1, 0x7E, 0xE7, 0xA3, 0x47, 0x88), + MBEDTLS_BYTES_TO_T_UINT_8(0x6B, 0x3F, 0xC1, 0xB7, 0x81, 0x3A, 0xA6, 0xA2), + MBEDTLS_BYTES_TO_T_UINT_8(0xFF, 0x45, 0xCF, 0x68, 0xF0, 0x64, 0x1C, 0x1D), +}; +static const mbedtls_mpi_uint brainpoolP384r1_T_0_Y[] = { + MBEDTLS_BYTES_TO_T_UINT_8(0x15, 0x53, 0x3C, 0x26, 0x41, 0x03, 0x82, 0x42), + MBEDTLS_BYTES_TO_T_UINT_8(0x11, 0x81, 0x91, 0x77, 0x21, 0x46, 0x46, 0x0E), + MBEDTLS_BYTES_TO_T_UINT_8(0x28, 0x29, 0x91, 0xF9, 0x4F, 0x05, 0x9C, 0xE1), + MBEDTLS_BYTES_TO_T_UINT_8(0x64, 0x58, 0xEC, 0xFE, 0x29, 0x0B, 0xB7, 0x62), + MBEDTLS_BYTES_TO_T_UINT_8(0x52, 0xD5, 0xCF, 0x95, 0x8E, 0xEB, 0xB1, 0x5C), + MBEDTLS_BYTES_TO_T_UINT_8(0xA4, 0xC2, 0xF9, 0x20, 0x75, 0x1D, 0xBE, 0x8A), +}; +static const mbedtls_mpi_uint brainpoolP384r1_T_1_X[] = { + MBEDTLS_BYTES_TO_T_UINT_8(0x93, 0xD8, 0x8A, 0x54, 0x41, 0xD6, 0x6B, 0x1D), + MBEDTLS_BYTES_TO_T_UINT_8(0xE2, 0x3B, 0xF1, 0x22, 0xFD, 0x2D, 0x4B, 0x03), + MBEDTLS_BYTES_TO_T_UINT_8(0x01, 0x55, 0xE3, 0x33, 0xF0, 0x73, 0x52, 0x5A), + MBEDTLS_BYTES_TO_T_UINT_8(0xC1, 0x3F, 0x30, 0x26, 0xCA, 0x7F, 0x52, 0xA3), + MBEDTLS_BYTES_TO_T_UINT_8(0xD3, 0x6E, 0x17, 0x9B, 0xD5, 0x2A, 0x4A, 0x31), + MBEDTLS_BYTES_TO_T_UINT_8(0x86, 0xDA, 0x6B, 0xE5, 0x03, 0x07, 0x1D, 0x2E), +}; +static const mbedtls_mpi_uint brainpoolP384r1_T_1_Y[] = { + MBEDTLS_BYTES_TO_T_UINT_8(0x51, 0x7A, 0xAF, 0x98, 0xE3, 0xA4, 0xF6, 0x19), + MBEDTLS_BYTES_TO_T_UINT_8(0xEC, 0x7D, 0xFE, 0x51, 0x40, 0x3B, 0x47, 0xD2), + MBEDTLS_BYTES_TO_T_UINT_8(0xFC, 0x88, 0xEC, 0xC4, 0xE2, 0x8F, 0xCB, 0xA4), + MBEDTLS_BYTES_TO_T_UINT_8(0x30, 0xE2, 0x88, 0x2D, 0x4E, 0x50, 0xEB, 0x9A), + MBEDTLS_BYTES_TO_T_UINT_8(0x13, 0x54, 0x94, 0x5E, 0xF4, 0x7F, 0x3A, 0x04), + MBEDTLS_BYTES_TO_T_UINT_8(0xCD, 0x07, 0x1C, 0xE1, 0xBD, 0x0F, 0xF8, 0x63), +}; +static const mbedtls_mpi_uint brainpoolP384r1_T_2_X[] = { + MBEDTLS_BYTES_TO_T_UINT_8(0x94, 0x92, 0x28, 0x2E, 0x32, 0x04, 0xB1, 0x4D), + MBEDTLS_BYTES_TO_T_UINT_8(0x25, 0x82, 0x44, 0x43, 0x76, 0x0D, 0x55, 0xBF), + MBEDTLS_BYTES_TO_T_UINT_8(0x5B, 0xE3, 0xFF, 0x89, 0x46, 0xDE, 0x4E, 0xFE), + MBEDTLS_BYTES_TO_T_UINT_8(0x5B, 0x22, 0xBB, 0x67, 0x1A, 0x81, 0xEE, 0x27), + MBEDTLS_BYTES_TO_T_UINT_8(0xC8, 0x54, 0xE2, 0x7A, 0xAE, 0xDA, 0x2C, 0xD0), + MBEDTLS_BYTES_TO_T_UINT_8(0x74, 0x9A, 0x90, 0xAA, 0x6E, 0x8B, 0xCC, 0x5F), +}; +static const mbedtls_mpi_uint brainpoolP384r1_T_2_Y[] = { + MBEDTLS_BYTES_TO_T_UINT_8(0x16, 0x40, 0xAC, 0xED, 0x7D, 0x37, 0x87, 0xAC), + MBEDTLS_BYTES_TO_T_UINT_8(0x98, 0xF8, 0xB1, 0x80, 0x4C, 0x8C, 0x04, 0x42), + MBEDTLS_BYTES_TO_T_UINT_8(0xC2, 0x98, 0x2C, 0xAD, 0x30, 0x69, 0x35, 0xC0), + MBEDTLS_BYTES_TO_T_UINT_8(0x32, 0x2E, 0x00, 0x2F, 0x44, 0x8C, 0xF0, 0xC0), + MBEDTLS_BYTES_TO_T_UINT_8(0x16, 0x58, 0x07, 0xD7, 0xCD, 0x60, 0xA1, 0x5B), + MBEDTLS_BYTES_TO_T_UINT_8(0xAF, 0xFB, 0x7B, 0x03, 0x05, 0x5E, 0x79, 0x73), +}; +static const mbedtls_mpi_uint brainpoolP384r1_T_3_X[] = { + MBEDTLS_BYTES_TO_T_UINT_8(0xC8, 0x17, 0xCE, 0x38, 0x4B, 0x5E, 0x5B, 0xC8), + MBEDTLS_BYTES_TO_T_UINT_8(0x60, 0x0E, 0x0A, 0x61, 0x9D, 0x7C, 0x62, 0x08), + MBEDTLS_BYTES_TO_T_UINT_8(0x25, 0xF0, 0x98, 0x71, 0x7F, 0x17, 0x26, 0xD7), + MBEDTLS_BYTES_TO_T_UINT_8(0x83, 0xD3, 0xFA, 0x3C, 0xF0, 0x70, 0x07, 0x82), + MBEDTLS_BYTES_TO_T_UINT_8(0x29, 0x47, 0x5C, 0x09, 0x43, 0xB7, 0x65, 0x15), + MBEDTLS_BYTES_TO_T_UINT_8(0x0E, 0xA9, 0xA7, 0x3E, 0xFA, 0xF3, 0xEC, 0x22), +}; +static const mbedtls_mpi_uint brainpoolP384r1_T_3_Y[] = { + MBEDTLS_BYTES_TO_T_UINT_8(0xDA, 0x78, 0x22, 0x2B, 0x58, 0x71, 0xFA, 0xAA), + MBEDTLS_BYTES_TO_T_UINT_8(0x00, 0x30, 0xCE, 0x6A, 0xB3, 0xB0, 0x4F, 0x83), + MBEDTLS_BYTES_TO_T_UINT_8(0xCF, 0x95, 0x20, 0xA9, 0x23, 0xC2, 0x65, 0xE7), + MBEDTLS_BYTES_TO_T_UINT_8(0x55, 0xCF, 0x03, 0x5B, 0x8A, 0x80, 0x44, 0xBB), + MBEDTLS_BYTES_TO_T_UINT_8(0x5C, 0xF8, 0x91, 0xF7, 0xD5, 0xED, 0xEA, 0x81), + MBEDTLS_BYTES_TO_T_UINT_8(0x40, 0x5B, 0x16, 0x10, 0x25, 0xAC, 0x2A, 0x17), +}; +static const mbedtls_mpi_uint brainpoolP384r1_T_4_X[] = { + MBEDTLS_BYTES_TO_T_UINT_8(0xF2, 0xEC, 0xDC, 0xC4, 0x7B, 0x8C, 0x6B, 0xE9), + MBEDTLS_BYTES_TO_T_UINT_8(0x2B, 0xBB, 0x1C, 0xD3, 0x5A, 0xEE, 0xD9, 0x97), + MBEDTLS_BYTES_TO_T_UINT_8(0x64, 0x5D, 0x30, 0x5E, 0xF7, 0xB2, 0x41, 0x9D), + MBEDTLS_BYTES_TO_T_UINT_8(0xED, 0xCE, 0x0F, 0x1A, 0xC6, 0x41, 0x64, 0x62), + MBEDTLS_BYTES_TO_T_UINT_8(0xF2, 0x18, 0xE1, 0xE3, 0x82, 0x15, 0x66, 0x4B), + MBEDTLS_BYTES_TO_T_UINT_8(0x9B, 0xE2, 0x24, 0x04, 0x72, 0x39, 0xA0, 0x7C), +}; +static const mbedtls_mpi_uint brainpoolP384r1_T_4_Y[] = { + MBEDTLS_BYTES_TO_T_UINT_8(0x2B, 0x51, 0xA2, 0x58, 0x88, 0x62, 0xE1, 0x02), + MBEDTLS_BYTES_TO_T_UINT_8(0x58, 0xD2, 0x65, 0x14, 0xE9, 0x4C, 0x82, 0x30), + MBEDTLS_BYTES_TO_T_UINT_8(0xDC, 0xE1, 0xAC, 0x87, 0xAE, 0x31, 0x1A, 0x7A), + MBEDTLS_BYTES_TO_T_UINT_8(0x85, 0x4F, 0x96, 0x1E, 0x85, 0x7A, 0xC3, 0x2B), + MBEDTLS_BYTES_TO_T_UINT_8(0xF0, 0x86, 0xBB, 0xF0, 0xC0, 0x9D, 0x08, 0x7B), + MBEDTLS_BYTES_TO_T_UINT_8(0xBD, 0x53, 0x03, 0x09, 0x80, 0x91, 0xEF, 0x68), +}; +static const mbedtls_mpi_uint brainpoolP384r1_T_5_X[] = { + MBEDTLS_BYTES_TO_T_UINT_8(0x2D, 0xD7, 0xAF, 0x6F, 0x69, 0x7B, 0x88, 0xA1), + MBEDTLS_BYTES_TO_T_UINT_8(0xAF, 0x13, 0xE4, 0x30, 0xA2, 0x47, 0xB5, 0xC1), + MBEDTLS_BYTES_TO_T_UINT_8(0x0F, 0xD2, 0xC0, 0xDD, 0x8A, 0x1C, 0x3C, 0xF2), + MBEDTLS_BYTES_TO_T_UINT_8(0xF9, 0x8C, 0xB3, 0x4C, 0xBA, 0x8B, 0x6D, 0xCF), + MBEDTLS_BYTES_TO_T_UINT_8(0x6B, 0xC7, 0xA1, 0xA8, 0x6E, 0x3C, 0x4F, 0xF1), + MBEDTLS_BYTES_TO_T_UINT_8(0x94, 0x4A, 0x97, 0xC8, 0x03, 0x6F, 0x01, 0x82), +}; +static const mbedtls_mpi_uint brainpoolP384r1_T_5_Y[] = { + MBEDTLS_BYTES_TO_T_UINT_8(0x74, 0x18, 0x12, 0xA9, 0x39, 0xD5, 0x22, 0x26), + MBEDTLS_BYTES_TO_T_UINT_8(0x47, 0xA7, 0xC0, 0xBD, 0x9D, 0x8D, 0x78, 0x38), + MBEDTLS_BYTES_TO_T_UINT_8(0xA9, 0xB3, 0xD0, 0x7F, 0xDF, 0xD0, 0x30, 0xDE), + MBEDTLS_BYTES_TO_T_UINT_8(0x37, 0x25, 0x73, 0x96, 0xEC, 0xA8, 0x1D, 0x7C), + MBEDTLS_BYTES_TO_T_UINT_8(0x91, 0xD1, 0x65, 0x66, 0xDC, 0xD9, 0xCF, 0xDF), + MBEDTLS_BYTES_TO_T_UINT_8(0x95, 0xED, 0x7B, 0x37, 0xAD, 0xE2, 0xBE, 0x2D), +}; +static const mbedtls_mpi_uint brainpoolP384r1_T_6_X[] = { + MBEDTLS_BYTES_TO_T_UINT_8(0x50, 0x79, 0x42, 0x6A, 0x07, 0x66, 0xB1, 0xBD), + MBEDTLS_BYTES_TO_T_UINT_8(0x45, 0x53, 0x62, 0x65, 0x92, 0x09, 0x4C, 0xA1), + MBEDTLS_BYTES_TO_T_UINT_8(0x06, 0xAF, 0xC3, 0x03, 0xF6, 0xF4, 0x2D, 0x9B), + MBEDTLS_BYTES_TO_T_UINT_8(0xE8, 0xCA, 0x41, 0xD9, 0xA2, 0x69, 0x9B, 0xC9), + MBEDTLS_BYTES_TO_T_UINT_8(0x4B, 0xB2, 0xA6, 0x8D, 0xE1, 0xAA, 0x61, 0x76), + MBEDTLS_BYTES_TO_T_UINT_8(0x11, 0xBA, 0x4D, 0x12, 0xB6, 0xBE, 0xF3, 0x7E), +}; +static const mbedtls_mpi_uint brainpoolP384r1_T_6_Y[] = { + MBEDTLS_BYTES_TO_T_UINT_8(0xCA, 0xD9, 0x92, 0x22, 0x07, 0xCE, 0xC9, 0x26), + MBEDTLS_BYTES_TO_T_UINT_8(0x62, 0xA1, 0x7C, 0x91, 0xDB, 0x32, 0xF7, 0xE5), + MBEDTLS_BYTES_TO_T_UINT_8(0x6D, 0x49, 0x4B, 0x6D, 0xFB, 0xD9, 0x70, 0x3B), + MBEDTLS_BYTES_TO_T_UINT_8(0x1C, 0xFB, 0x4E, 0x4C, 0x5E, 0x66, 0x81, 0x1D), + MBEDTLS_BYTES_TO_T_UINT_8(0xA5, 0xB3, 0xE1, 0x00, 0xB7, 0xD9, 0xCC, 0x58), + MBEDTLS_BYTES_TO_T_UINT_8(0xF3, 0x36, 0x8B, 0xC4, 0x39, 0x20, 0xFD, 0x30), +}; +static const mbedtls_mpi_uint brainpoolP384r1_T_7_X[] = { + MBEDTLS_BYTES_TO_T_UINT_8(0x94, 0x1F, 0x60, 0x03, 0xBB, 0xD7, 0x60, 0x57), + MBEDTLS_BYTES_TO_T_UINT_8(0x72, 0x3C, 0x62, 0xDD, 0x71, 0x95, 0xE9, 0x61), + MBEDTLS_BYTES_TO_T_UINT_8(0xB0, 0x5B, 0x7A, 0x5F, 0x68, 0x81, 0xC5, 0x90), + MBEDTLS_BYTES_TO_T_UINT_8(0x1E, 0xAF, 0xB5, 0xB9, 0x98, 0x42, 0x28, 0xA5), + MBEDTLS_BYTES_TO_T_UINT_8(0x0C, 0x29, 0x8E, 0x11, 0x49, 0xB4, 0xD7, 0x20), + MBEDTLS_BYTES_TO_T_UINT_8(0x9B, 0x3E, 0xD2, 0x30, 0xA1, 0xBA, 0xCA, 0x03), +}; +static const mbedtls_mpi_uint brainpoolP384r1_T_7_Y[] = { + MBEDTLS_BYTES_TO_T_UINT_8(0x29, 0x37, 0x64, 0x44, 0x2F, 0x03, 0xE5, 0x41), + MBEDTLS_BYTES_TO_T_UINT_8(0x4A, 0x42, 0xBC, 0xFF, 0xA2, 0x1A, 0x5F, 0x06), + MBEDTLS_BYTES_TO_T_UINT_8(0x1D, 0x04, 0xAB, 0x04, 0xE0, 0x24, 0xAD, 0x2A), + MBEDTLS_BYTES_TO_T_UINT_8(0x3D, 0x45, 0x17, 0x67, 0x1F, 0x3E, 0x53, 0xF8), + MBEDTLS_BYTES_TO_T_UINT_8(0xED, 0x0F, 0xB3, 0x1B, 0x57, 0x54, 0xC2, 0x03), + MBEDTLS_BYTES_TO_T_UINT_8(0x59, 0xD3, 0xF8, 0xC4, 0x1B, 0x9B, 0xFA, 0x30), +}; +static const mbedtls_mpi_uint brainpoolP384r1_T_8_X[] = { + MBEDTLS_BYTES_TO_T_UINT_8(0x37, 0x90, 0xFD, 0xFB, 0xCA, 0x49, 0x38, 0x4E), + MBEDTLS_BYTES_TO_T_UINT_8(0xC3, 0xCF, 0xC6, 0xDD, 0xF0, 0xFF, 0x8C, 0x11), + MBEDTLS_BYTES_TO_T_UINT_8(0xD7, 0x69, 0x9D, 0xBD, 0x5F, 0x33, 0xE9, 0xB4), + MBEDTLS_BYTES_TO_T_UINT_8(0x47, 0x19, 0x82, 0x3D, 0xAC, 0x1C, 0x40, 0x23), + MBEDTLS_BYTES_TO_T_UINT_8(0x40, 0xC7, 0x02, 0x46, 0x14, 0x77, 0x00, 0xBE), + MBEDTLS_BYTES_TO_T_UINT_8(0xC9, 0x05, 0xF2, 0x77, 0x3A, 0x66, 0x5C, 0x39), +}; +static const mbedtls_mpi_uint brainpoolP384r1_T_8_Y[] = { + MBEDTLS_BYTES_TO_T_UINT_8(0x1E, 0xE6, 0x17, 0xDE, 0xB2, 0xA1, 0xE5, 0xB8), + MBEDTLS_BYTES_TO_T_UINT_8(0xC7, 0x71, 0xEC, 0x9D, 0xD8, 0xF5, 0xD4, 0x66), + MBEDTLS_BYTES_TO_T_UINT_8(0xAA, 0xC6, 0x42, 0x5E, 0xE7, 0x18, 0xBA, 0xD0), + MBEDTLS_BYTES_TO_T_UINT_8(0xC5, 0x21, 0x68, 0x5A, 0x26, 0xFB, 0xD7, 0x17), + MBEDTLS_BYTES_TO_T_UINT_8(0x26, 0x00, 0x5C, 0xBA, 0x8A, 0x34, 0xEC, 0x75), + MBEDTLS_BYTES_TO_T_UINT_8(0xC3, 0x9C, 0x3C, 0xAF, 0x53, 0xE8, 0x65, 0x35), +}; +static const mbedtls_mpi_uint brainpoolP384r1_T_9_X[] = { + MBEDTLS_BYTES_TO_T_UINT_8(0xBE, 0xEF, 0x28, 0xDC, 0x67, 0x05, 0xC8, 0xDF), + MBEDTLS_BYTES_TO_T_UINT_8(0x0B, 0x78, 0xC3, 0x85, 0x49, 0xA0, 0xBC, 0x0F), + MBEDTLS_BYTES_TO_T_UINT_8(0x10, 0x3E, 0x2D, 0xA0, 0xCF, 0xD4, 0x7A, 0xF5), + MBEDTLS_BYTES_TO_T_UINT_8(0x36, 0x93, 0xFE, 0x60, 0xB3, 0x6E, 0x99, 0xE2), + MBEDTLS_BYTES_TO_T_UINT_8(0x62, 0xAD, 0x04, 0xE7, 0x49, 0xAF, 0x5E, 0xE3), + MBEDTLS_BYTES_TO_T_UINT_8(0x54, 0x7A, 0xED, 0xA6, 0x9E, 0x18, 0x09, 0x31), +}; +static const mbedtls_mpi_uint brainpoolP384r1_T_9_Y[] = { + MBEDTLS_BYTES_TO_T_UINT_8(0xE8, 0x05, 0x94, 0x44, 0xDC, 0xB8, 0x85, 0x94), + MBEDTLS_BYTES_TO_T_UINT_8(0x14, 0xB7, 0x37, 0xC2, 0x50, 0x75, 0x15, 0xDA), + MBEDTLS_BYTES_TO_T_UINT_8(0xD6, 0xC6, 0x0F, 0xB2, 0xA9, 0x91, 0x3E, 0xE8), + MBEDTLS_BYTES_TO_T_UINT_8(0xB9, 0x81, 0xAD, 0x25, 0xA1, 0x26, 0x73, 0x15), + MBEDTLS_BYTES_TO_T_UINT_8(0xFD, 0xF1, 0xD1, 0x61, 0x7C, 0x76, 0x8F, 0x13), + MBEDTLS_BYTES_TO_T_UINT_8(0x06, 0xDB, 0x4A, 0xFF, 0x14, 0xA7, 0x48, 0x0B), +}; +static const mbedtls_mpi_uint brainpoolP384r1_T_10_X[] = { + MBEDTLS_BYTES_TO_T_UINT_8(0x2A, 0x73, 0xC6, 0xC2, 0xCC, 0xF1, 0x57, 0x04), + MBEDTLS_BYTES_TO_T_UINT_8(0xB6, 0xED, 0x73, 0x27, 0x70, 0x82, 0xB6, 0x5E), + MBEDTLS_BYTES_TO_T_UINT_8(0x0B, 0xBA, 0xAC, 0x3A, 0xCF, 0xF4, 0xEA, 0xA6), + MBEDTLS_BYTES_TO_T_UINT_8(0x99, 0xD6, 0xB1, 0x8F, 0x0E, 0x08, 0x2C, 0x5E), + MBEDTLS_BYTES_TO_T_UINT_8(0x17, 0xE3, 0x8F, 0x2F, 0x0E, 0xA1, 0xF3, 0x07), + MBEDTLS_BYTES_TO_T_UINT_8(0x1A, 0xF5, 0x7C, 0x9B, 0x29, 0x0A, 0xF6, 0x28), +}; +static const mbedtls_mpi_uint brainpoolP384r1_T_10_Y[] = { + MBEDTLS_BYTES_TO_T_UINT_8(0xBD, 0xEE, 0x17, 0x47, 0x34, 0x15, 0xA3, 0xAF), + MBEDTLS_BYTES_TO_T_UINT_8(0xFB, 0xBE, 0x88, 0x48, 0xE7, 0xA2, 0xBB, 0xDE), + MBEDTLS_BYTES_TO_T_UINT_8(0xC5, 0xAD, 0xDC, 0x65, 0x61, 0x37, 0x0F, 0xC1), + MBEDTLS_BYTES_TO_T_UINT_8(0xFA, 0x67, 0xAD, 0xA2, 0x3A, 0x1C, 0x91, 0x78), + MBEDTLS_BYTES_TO_T_UINT_8(0x55, 0x07, 0x0C, 0x3A, 0x41, 0x6E, 0x13, 0x28), + MBEDTLS_BYTES_TO_T_UINT_8(0x73, 0xBD, 0x7E, 0xED, 0xAA, 0x14, 0xDD, 0x61), +}; +static const mbedtls_mpi_uint brainpoolP384r1_T_11_X[] = { + MBEDTLS_BYTES_TO_T_UINT_8(0xC3, 0xDC, 0x20, 0x01, 0x72, 0x11, 0x48, 0x55), + MBEDTLS_BYTES_TO_T_UINT_8(0x1E, 0xC4, 0x7B, 0xF8, 0x62, 0x3D, 0xF0, 0x9F), + MBEDTLS_BYTES_TO_T_UINT_8(0xE8, 0xC2, 0x3D, 0x2E, 0x52, 0xA3, 0x4A, 0x89), + MBEDTLS_BYTES_TO_T_UINT_8(0xCE, 0xE2, 0x53, 0x46, 0x5E, 0x21, 0xF8, 0xCE), + MBEDTLS_BYTES_TO_T_UINT_8(0xC2, 0xC7, 0x8F, 0xA9, 0x26, 0x42, 0x32, 0x3A), + MBEDTLS_BYTES_TO_T_UINT_8(0xFB, 0xA6, 0xA0, 0x8D, 0x4B, 0x9A, 0x19, 0x03), +}; +static const mbedtls_mpi_uint brainpoolP384r1_T_11_Y[] = { + MBEDTLS_BYTES_TO_T_UINT_8(0xEA, 0xAB, 0x6D, 0x1E, 0xFB, 0xEE, 0x60, 0x0C), + MBEDTLS_BYTES_TO_T_UINT_8(0xB6, 0x56, 0x3C, 0xC5, 0x5D, 0x10, 0x79, 0x1C), + MBEDTLS_BYTES_TO_T_UINT_8(0x25, 0xBC, 0x41, 0x9F, 0x71, 0xEF, 0x02, 0xF9), + MBEDTLS_BYTES_TO_T_UINT_8(0xA2, 0x36, 0xC4, 0xD0, 0x88, 0x9B, 0x32, 0xFC), + MBEDTLS_BYTES_TO_T_UINT_8(0x9C, 0xD4, 0x5D, 0x17, 0x39, 0xE6, 0x22, 0x2C), + MBEDTLS_BYTES_TO_T_UINT_8(0x7B, 0x26, 0x01, 0xCE, 0xBE, 0x4A, 0x9C, 0x27), +}; +static const mbedtls_mpi_uint brainpoolP384r1_T_12_X[] = { + MBEDTLS_BYTES_TO_T_UINT_8(0xEF, 0x6D, 0x11, 0xCA, 0x6C, 0x5A, 0x93, 0x0C), + MBEDTLS_BYTES_TO_T_UINT_8(0xEB, 0x96, 0x26, 0xAF, 0x2F, 0xE4, 0x30, 0x98), + MBEDTLS_BYTES_TO_T_UINT_8(0x35, 0xC1, 0x4C, 0xC6, 0x30, 0x1F, 0x5C, 0x04), + MBEDTLS_BYTES_TO_T_UINT_8(0x59, 0xB3, 0xE8, 0xFC, 0x35, 0xEB, 0x63, 0x6C), + MBEDTLS_BYTES_TO_T_UINT_8(0x9C, 0x1D, 0xCA, 0xFC, 0x50, 0x36, 0x4B, 0x96), + MBEDTLS_BYTES_TO_T_UINT_8(0xE4, 0x0E, 0x23, 0x5B, 0xAF, 0xEB, 0x2D, 0x31), +}; +static const mbedtls_mpi_uint brainpoolP384r1_T_12_Y[] = { + MBEDTLS_BYTES_TO_T_UINT_8(0xC6, 0x88, 0xB6, 0xD7, 0x74, 0x4A, 0x23, 0xB6), + MBEDTLS_BYTES_TO_T_UINT_8(0xEF, 0x66, 0xE2, 0xBB, 0x29, 0xA6, 0x4F, 0x55), + MBEDTLS_BYTES_TO_T_UINT_8(0xE9, 0x6F, 0x7E, 0x68, 0x6E, 0xA0, 0x14, 0x94), + MBEDTLS_BYTES_TO_T_UINT_8(0x3B, 0x73, 0xD4, 0xE8, 0xAB, 0x5B, 0xF6, 0x0D), + MBEDTLS_BYTES_TO_T_UINT_8(0x46, 0xE0, 0x3C, 0x24, 0x00, 0x95, 0xE9, 0xAD), + MBEDTLS_BYTES_TO_T_UINT_8(0x37, 0x0D, 0x4F, 0x81, 0xD0, 0xF2, 0x3F, 0x00), +}; +static const mbedtls_mpi_uint brainpoolP384r1_T_13_X[] = { + MBEDTLS_BYTES_TO_T_UINT_8(0x99, 0x1D, 0xCD, 0x78, 0x39, 0xC4, 0x6B, 0xD9), + MBEDTLS_BYTES_TO_T_UINT_8(0x81, 0x45, 0xC7, 0xB8, 0x2F, 0xAA, 0x5D, 0xE3), + MBEDTLS_BYTES_TO_T_UINT_8(0x33, 0x8C, 0x6E, 0xA3, 0x24, 0xB2, 0xDB, 0x4B), + MBEDTLS_BYTES_TO_T_UINT_8(0x69, 0x2D, 0xD9, 0xF1, 0xC7, 0x9B, 0x8A, 0xAF), + MBEDTLS_BYTES_TO_T_UINT_8(0x67, 0xE1, 0x2C, 0xB9, 0x40, 0x37, 0x91, 0x75), + MBEDTLS_BYTES_TO_T_UINT_8(0x81, 0x2C, 0xB5, 0x23, 0x03, 0x2B, 0xAF, 0x2F), +}; +static const mbedtls_mpi_uint brainpoolP384r1_T_13_Y[] = { + MBEDTLS_BYTES_TO_T_UINT_8(0x2F, 0x9D, 0x5A, 0x20, 0x10, 0xA9, 0x84, 0xDA), + MBEDTLS_BYTES_TO_T_UINT_8(0x61, 0x30, 0x89, 0x20, 0x13, 0xE9, 0xB2, 0xCA), + MBEDTLS_BYTES_TO_T_UINT_8(0xB6, 0x6E, 0x52, 0xEB, 0x03, 0x18, 0x1F, 0xA6), + MBEDTLS_BYTES_TO_T_UINT_8(0x6C, 0x9E, 0x1C, 0x35, 0x87, 0x92, 0x69, 0xC7), + MBEDTLS_BYTES_TO_T_UINT_8(0xA1, 0xC9, 0x88, 0xAF, 0xC6, 0x6C, 0x83, 0x72), + MBEDTLS_BYTES_TO_T_UINT_8(0xCB, 0xD5, 0x7A, 0x54, 0x34, 0x99, 0xB6, 0x6F), +}; +static const mbedtls_mpi_uint brainpoolP384r1_T_14_X[] = { + MBEDTLS_BYTES_TO_T_UINT_8(0xDF, 0xAD, 0x45, 0x9B, 0x4B, 0x41, 0x4D, 0x50), + MBEDTLS_BYTES_TO_T_UINT_8(0x1B, 0x5D, 0xAB, 0x7F, 0x35, 0x34, 0xE9, 0x29), + MBEDTLS_BYTES_TO_T_UINT_8(0x73, 0xBE, 0x78, 0x34, 0x44, 0xF3, 0x4A, 0x87), + MBEDTLS_BYTES_TO_T_UINT_8(0xFB, 0xDE, 0xE3, 0xC4, 0xEE, 0x0B, 0xF9, 0xEB), + MBEDTLS_BYTES_TO_T_UINT_8(0x5E, 0x86, 0x16, 0x48, 0x32, 0xB8, 0x74, 0x41), + MBEDTLS_BYTES_TO_T_UINT_8(0xF2, 0xEE, 0x7C, 0xBA, 0xBD, 0x81, 0xE3, 0x55), +}; +static const mbedtls_mpi_uint brainpoolP384r1_T_14_Y[] = { + MBEDTLS_BYTES_TO_T_UINT_8(0xF8, 0x6A, 0xFA, 0x84, 0xDA, 0xB8, 0xD5, 0x14), + MBEDTLS_BYTES_TO_T_UINT_8(0xB2, 0x9F, 0x8A, 0xD5, 0x1B, 0x2E, 0x1A, 0x0B), + MBEDTLS_BYTES_TO_T_UINT_8(0x5F, 0x0C, 0x61, 0xE2, 0xFF, 0x5B, 0xE6, 0xD5), + MBEDTLS_BYTES_TO_T_UINT_8(0x0E, 0x62, 0xC1, 0x87, 0x53, 0x1B, 0x92, 0xA3), + MBEDTLS_BYTES_TO_T_UINT_8(0x54, 0x90, 0x00, 0xD1, 0x6A, 0x0C, 0x0E, 0x28), + MBEDTLS_BYTES_TO_T_UINT_8(0x8B, 0x2E, 0xB5, 0x3B, 0x44, 0xB5, 0xA0, 0x78), +}; +static const mbedtls_mpi_uint brainpoolP384r1_T_15_X[] = { + MBEDTLS_BYTES_TO_T_UINT_8(0xB8, 0x5D, 0x02, 0x58, 0xB5, 0xBE, 0x45, 0x14), + MBEDTLS_BYTES_TO_T_UINT_8(0xAD, 0xEF, 0x8E, 0x90, 0x4D, 0x2A, 0x32, 0xAC), + MBEDTLS_BYTES_TO_T_UINT_8(0x48, 0x99, 0x75, 0x5C, 0x0A, 0x33, 0x8F, 0x36), + MBEDTLS_BYTES_TO_T_UINT_8(0xC8, 0x6C, 0x95, 0xD4, 0x1F, 0xF3, 0xEB, 0xDA), + MBEDTLS_BYTES_TO_T_UINT_8(0xC2, 0xE4, 0x4C, 0x91, 0x20, 0xF3, 0x25, 0xEB), + MBEDTLS_BYTES_TO_T_UINT_8(0xF1, 0x95, 0xEB, 0x29, 0x6F, 0x20, 0x34, 0x81), +}; +static const mbedtls_mpi_uint brainpoolP384r1_T_15_Y[] = { + MBEDTLS_BYTES_TO_T_UINT_8(0x2D, 0x15, 0xE5, 0x13, 0x7E, 0x64, 0x8B, 0xAD), + MBEDTLS_BYTES_TO_T_UINT_8(0xA7, 0xBC, 0x0D, 0x18, 0x7E, 0x37, 0x9E, 0xFA), + MBEDTLS_BYTES_TO_T_UINT_8(0xE8, 0x82, 0x20, 0xF7, 0x2D, 0x7A, 0x77, 0x52), + MBEDTLS_BYTES_TO_T_UINT_8(0xCB, 0x29, 0xA2, 0xDB, 0x7A, 0xE6, 0x6F, 0xA5), + MBEDTLS_BYTES_TO_T_UINT_8(0xA0, 0xC6, 0x50, 0x5C, 0xBC, 0xE6, 0x4F, 0xBD), + MBEDTLS_BYTES_TO_T_UINT_8(0x1E, 0x9F, 0xD5, 0xE8, 0xC5, 0x3D, 0xB7, 0x30), +}; +static const mbedtls_mpi_uint brainpoolP384r1_T_16_X[] = { + MBEDTLS_BYTES_TO_T_UINT_8(0x45, 0x03, 0x55, 0x10, 0xDB, 0xA6, 0x8B, 0x22), + MBEDTLS_BYTES_TO_T_UINT_8(0x4E, 0x17, 0xAE, 0x78, 0xC9, 0x1D, 0x43, 0xCA), + MBEDTLS_BYTES_TO_T_UINT_8(0x4E, 0x35, 0x49, 0xD4, 0x47, 0x84, 0x8D, 0x20), + MBEDTLS_BYTES_TO_T_UINT_8(0xF3, 0x95, 0x2F, 0xEA, 0xBC, 0xB4, 0x18, 0xB3), + MBEDTLS_BYTES_TO_T_UINT_8(0xD4, 0x48, 0xAE, 0x89, 0xF5, 0x65, 0x3D, 0x89), + MBEDTLS_BYTES_TO_T_UINT_8(0x86, 0xF2, 0x2B, 0x20, 0xD1, 0x75, 0x50, 0x63), +}; +static const mbedtls_mpi_uint brainpoolP384r1_T_16_Y[] = { + MBEDTLS_BYTES_TO_T_UINT_8(0xAD, 0xE6, 0x5C, 0x2C, 0xE0, 0x7D, 0xDF, 0x2D), + MBEDTLS_BYTES_TO_T_UINT_8(0x3E, 0x07, 0x3E, 0xCE, 0x9F, 0x18, 0xB6, 0x05), + MBEDTLS_BYTES_TO_T_UINT_8(0x9A, 0xF8, 0xF0, 0xD5, 0xFA, 0x42, 0x1D, 0x6D), + MBEDTLS_BYTES_TO_T_UINT_8(0x41, 0x6C, 0x1D, 0x03, 0xC9, 0x0E, 0x2B, 0x2F), + MBEDTLS_BYTES_TO_T_UINT_8(0x43, 0x18, 0x52, 0xA5, 0xB4, 0x63, 0xE1, 0x06), + MBEDTLS_BYTES_TO_T_UINT_8(0xB7, 0x0A, 0xD9, 0xC4, 0xFD, 0x16, 0x60, 0x54), +}; +static const mbedtls_mpi_uint brainpoolP384r1_T_17_X[] = { + MBEDTLS_BYTES_TO_T_UINT_8(0x43, 0x7D, 0xDE, 0xDF, 0x4B, 0x4A, 0xB0, 0xCB), + MBEDTLS_BYTES_TO_T_UINT_8(0xB0, 0x4E, 0x8C, 0x94, 0xC1, 0xE2, 0x85, 0xDF), + MBEDTLS_BYTES_TO_T_UINT_8(0x4F, 0xF0, 0xEA, 0xB5, 0x9B, 0x70, 0xEF, 0x10), + MBEDTLS_BYTES_TO_T_UINT_8(0x56, 0xC2, 0x39, 0x5D, 0xF3, 0x2C, 0xD9, 0x2C), + MBEDTLS_BYTES_TO_T_UINT_8(0x0D, 0x1C, 0x2E, 0xCC, 0x2F, 0x54, 0x87, 0x80), + MBEDTLS_BYTES_TO_T_UINT_8(0xB0, 0x72, 0xC7, 0xB5, 0x50, 0xA3, 0x84, 0x77), +}; +static const mbedtls_mpi_uint brainpoolP384r1_T_17_Y[] = { + MBEDTLS_BYTES_TO_T_UINT_8(0xB7, 0xD1, 0xAF, 0xA9, 0xB4, 0x8B, 0x5D, 0xFA), + MBEDTLS_BYTES_TO_T_UINT_8(0xC8, 0xF6, 0x52, 0x8A, 0xC3, 0x56, 0xA5, 0x5E), + MBEDTLS_BYTES_TO_T_UINT_8(0x3B, 0x52, 0xFF, 0xEA, 0x05, 0x42, 0x77, 0x83), + MBEDTLS_BYTES_TO_T_UINT_8(0x29, 0x08, 0x90, 0x72, 0x86, 0xC4, 0xC3, 0xB8), + MBEDTLS_BYTES_TO_T_UINT_8(0x4D, 0x15, 0xF8, 0xF1, 0x16, 0x67, 0xC6, 0xD5), + MBEDTLS_BYTES_TO_T_UINT_8(0x75, 0x87, 0xAC, 0x8F, 0x71, 0xEC, 0x83, 0x81), +}; +static const mbedtls_mpi_uint brainpoolP384r1_T_18_X[] = { + MBEDTLS_BYTES_TO_T_UINT_8(0x91, 0xE1, 0xE6, 0x2D, 0x0E, 0x11, 0xA1, 0x62), + MBEDTLS_BYTES_TO_T_UINT_8(0x74, 0xE2, 0xA8, 0x32, 0xE6, 0xE3, 0x83, 0xD1), + MBEDTLS_BYTES_TO_T_UINT_8(0x50, 0x56, 0xE5, 0xCD, 0xB7, 0x2B, 0x67, 0x6F), + MBEDTLS_BYTES_TO_T_UINT_8(0xE5, 0xED, 0xC9, 0x65, 0x6D, 0x87, 0xE1, 0x8E), + MBEDTLS_BYTES_TO_T_UINT_8(0x50, 0x8E, 0xFD, 0x9A, 0x53, 0x0E, 0xFA, 0xA3), + MBEDTLS_BYTES_TO_T_UINT_8(0x49, 0x4C, 0x4A, 0xE2, 0x23, 0x84, 0xFA, 0x01), +}; +static const mbedtls_mpi_uint brainpoolP384r1_T_18_Y[] = { + MBEDTLS_BYTES_TO_T_UINT_8(0xB4, 0xFE, 0x49, 0x81, 0xD1, 0x3E, 0xF4, 0x7C), + MBEDTLS_BYTES_TO_T_UINT_8(0x45, 0x72, 0xE0, 0xEF, 0x0D, 0xB8, 0x3E, 0x6F), + MBEDTLS_BYTES_TO_T_UINT_8(0x3C, 0x00, 0x0F, 0x5F, 0xCE, 0x60, 0x72, 0x2C), + MBEDTLS_BYTES_TO_T_UINT_8(0xB7, 0xCC, 0xD8, 0x03, 0x07, 0x6E, 0x5A, 0xCD), + MBEDTLS_BYTES_TO_T_UINT_8(0x27, 0x3A, 0x35, 0x50, 0x4E, 0x1F, 0xCA, 0x5F), + MBEDTLS_BYTES_TO_T_UINT_8(0x58, 0xEA, 0x88, 0x55, 0xBD, 0x6E, 0x05, 0x7F), +}; +static const mbedtls_mpi_uint brainpoolP384r1_T_19_X[] = { + MBEDTLS_BYTES_TO_T_UINT_8(0xB1, 0x6D, 0xF1, 0x97, 0xA6, 0x69, 0x39, 0x24), + MBEDTLS_BYTES_TO_T_UINT_8(0x0B, 0x41, 0x99, 0xFF, 0x3B, 0xA1, 0x26, 0xEC), + MBEDTLS_BYTES_TO_T_UINT_8(0x95, 0x2F, 0x95, 0x80, 0x12, 0x4A, 0x1B, 0xCB), + MBEDTLS_BYTES_TO_T_UINT_8(0xEA, 0xBF, 0x51, 0xAA, 0xAE, 0x2D, 0xDA, 0xCF), + MBEDTLS_BYTES_TO_T_UINT_8(0x0C, 0x1C, 0xB3, 0x52, 0x36, 0x49, 0xD4, 0x86), + MBEDTLS_BYTES_TO_T_UINT_8(0x99, 0xC1, 0x1F, 0x3A, 0xD3, 0x3E, 0x5C, 0x1A), +}; +static const mbedtls_mpi_uint brainpoolP384r1_T_19_Y[] = { + MBEDTLS_BYTES_TO_T_UINT_8(0x73, 0x51, 0xF7, 0x2B, 0xC8, 0xA9, 0xA7, 0x15), + MBEDTLS_BYTES_TO_T_UINT_8(0x12, 0x4E, 0x7F, 0x98, 0x41, 0x66, 0xB0, 0x03), + MBEDTLS_BYTES_TO_T_UINT_8(0x91, 0x1D, 0xC0, 0x42, 0xCD, 0xF8, 0xC3, 0x2B), + MBEDTLS_BYTES_TO_T_UINT_8(0xCC, 0x41, 0x91, 0x7D, 0xCC, 0x8B, 0xCC, 0x41), + MBEDTLS_BYTES_TO_T_UINT_8(0x2A, 0xAE, 0x76, 0xED, 0x56, 0x18, 0xC5, 0xAB), + MBEDTLS_BYTES_TO_T_UINT_8(0xAB, 0x6A, 0x06, 0xA3, 0x7F, 0x65, 0x10, 0x1F), +}; +static const mbedtls_mpi_uint brainpoolP384r1_T_20_X[] = { + MBEDTLS_BYTES_TO_T_UINT_8(0x0C, 0xEC, 0x3C, 0x05, 0x05, 0xCA, 0xF6, 0xED), + MBEDTLS_BYTES_TO_T_UINT_8(0x48, 0xCD, 0x02, 0x51, 0x12, 0x16, 0x3C, 0x63), + MBEDTLS_BYTES_TO_T_UINT_8(0xA8, 0xEB, 0xB3, 0x43, 0x7B, 0xDD, 0xB2, 0x7C), + MBEDTLS_BYTES_TO_T_UINT_8(0x00, 0x59, 0x90, 0x41, 0xDB, 0xE4, 0xF5, 0x91), + MBEDTLS_BYTES_TO_T_UINT_8(0xD0, 0x0E, 0x18, 0x2A, 0x5A, 0x83, 0x7C, 0x2F), + MBEDTLS_BYTES_TO_T_UINT_8(0xE1, 0x37, 0xA1, 0x0D, 0xF1, 0x2F, 0x63, 0x79), +}; +static const mbedtls_mpi_uint brainpoolP384r1_T_20_Y[] = { + MBEDTLS_BYTES_TO_T_UINT_8(0x21, 0xC0, 0xFA, 0x6F, 0x1F, 0x67, 0xCF, 0xEC), + MBEDTLS_BYTES_TO_T_UINT_8(0x98, 0x34, 0x45, 0xBB, 0xF4, 0xF9, 0x9B, 0x89), + MBEDTLS_BYTES_TO_T_UINT_8(0xF5, 0x69, 0xFE, 0x67, 0x1D, 0x64, 0x8F, 0xB9), + MBEDTLS_BYTES_TO_T_UINT_8(0xDB, 0x39, 0xBF, 0xD8, 0xB3, 0xC7, 0xAD, 0x8A), + MBEDTLS_BYTES_TO_T_UINT_8(0x8C, 0x93, 0xFF, 0xF3, 0x28, 0xFA, 0x39, 0xF6), + MBEDTLS_BYTES_TO_T_UINT_8(0xFA, 0xF9, 0xC3, 0x85, 0x26, 0x7A, 0x88, 0x89), +}; +static const mbedtls_mpi_uint brainpoolP384r1_T_21_X[] = { + MBEDTLS_BYTES_TO_T_UINT_8(0x4D, 0xD5, 0x79, 0xD8, 0x11, 0xDE, 0xEB, 0x4E), + MBEDTLS_BYTES_TO_T_UINT_8(0x1C, 0x46, 0xA4, 0x6A, 0xDA, 0x74, 0x34, 0xA8), + MBEDTLS_BYTES_TO_T_UINT_8(0x1E, 0xBD, 0xD3, 0xF5, 0x14, 0xEE, 0xFE, 0xAE), + MBEDTLS_BYTES_TO_T_UINT_8(0x19, 0x4C, 0xA3, 0x71, 0x43, 0x65, 0xF8, 0x94), + MBEDTLS_BYTES_TO_T_UINT_8(0x72, 0x6C, 0x35, 0xFA, 0x90, 0x25, 0xD8, 0xE2), + MBEDTLS_BYTES_TO_T_UINT_8(0xBB, 0x34, 0x84, 0x96, 0xA1, 0x43, 0x03, 0x4D), +}; +static const mbedtls_mpi_uint brainpoolP384r1_T_21_Y[] = { + MBEDTLS_BYTES_TO_T_UINT_8(0xF1, 0x3B, 0x3B, 0x2F, 0xCA, 0x59, 0xF2, 0x42), + MBEDTLS_BYTES_TO_T_UINT_8(0xCD, 0x48, 0x24, 0x74, 0xD8, 0x72, 0x90, 0xA3), + MBEDTLS_BYTES_TO_T_UINT_8(0x83, 0x42, 0x74, 0x8C, 0x6F, 0x52, 0x19, 0x3D), + MBEDTLS_BYTES_TO_T_UINT_8(0x40, 0x9E, 0x41, 0x63, 0x68, 0x78, 0x4C, 0x2F), + MBEDTLS_BYTES_TO_T_UINT_8(0x53, 0x94, 0xB6, 0x6B, 0x38, 0x52, 0xA8, 0x9F), + MBEDTLS_BYTES_TO_T_UINT_8(0x81, 0x30, 0x25, 0x93, 0xA1, 0x6F, 0x6E, 0x68), +}; +static const mbedtls_mpi_uint brainpoolP384r1_T_22_X[] = { + MBEDTLS_BYTES_TO_T_UINT_8(0xFC, 0x2F, 0x4B, 0x64, 0x79, 0x50, 0xFF, 0x01), + MBEDTLS_BYTES_TO_T_UINT_8(0xD4, 0x36, 0xED, 0x57, 0x39, 0x3B, 0xE7, 0xF3), + MBEDTLS_BYTES_TO_T_UINT_8(0xF1, 0x85, 0xEA, 0x35, 0xD6, 0xC0, 0xA0, 0x52), + MBEDTLS_BYTES_TO_T_UINT_8(0xBA, 0x89, 0x3A, 0xCC, 0x22, 0x1C, 0x46, 0x02), + MBEDTLS_BYTES_TO_T_UINT_8(0x6C, 0x7A, 0xB0, 0xA1, 0x1B, 0x69, 0x62, 0x55), + MBEDTLS_BYTES_TO_T_UINT_8(0x57, 0xB8, 0x8A, 0x6C, 0x18, 0x85, 0x0D, 0x88), +}; +static const mbedtls_mpi_uint brainpoolP384r1_T_22_Y[] = { + MBEDTLS_BYTES_TO_T_UINT_8(0xFD, 0xB6, 0x50, 0xE9, 0x4E, 0x7F, 0xE8, 0x07), + MBEDTLS_BYTES_TO_T_UINT_8(0x92, 0x5B, 0x5C, 0xD1, 0x4B, 0x11, 0x9A, 0xD8), + MBEDTLS_BYTES_TO_T_UINT_8(0x96, 0x25, 0x56, 0x74, 0x51, 0x9C, 0xEC, 0x9C), + MBEDTLS_BYTES_TO_T_UINT_8(0x55, 0x7F, 0xB6, 0x8A, 0xCB, 0x3A, 0x10, 0x6A), + MBEDTLS_BYTES_TO_T_UINT_8(0x60, 0x33, 0x07, 0x01, 0xE9, 0x49, 0x59, 0xE6), + MBEDTLS_BYTES_TO_T_UINT_8(0xC6, 0xA5, 0x2E, 0xF2, 0xBA, 0x32, 0x63, 0x44), +}; +static const mbedtls_mpi_uint brainpoolP384r1_T_23_X[] = { + MBEDTLS_BYTES_TO_T_UINT_8(0xF8, 0x06, 0x0B, 0xA5, 0x44, 0x27, 0x7F, 0x22), + MBEDTLS_BYTES_TO_T_UINT_8(0x30, 0x74, 0xAC, 0x0F, 0xCC, 0x4F, 0x13, 0x61), + MBEDTLS_BYTES_TO_T_UINT_8(0xFD, 0xB1, 0xBF, 0x97, 0x49, 0xA5, 0x1C, 0x1D), + MBEDTLS_BYTES_TO_T_UINT_8(0x8A, 0x64, 0x68, 0x7B, 0x0F, 0xCC, 0x77, 0xF8), + MBEDTLS_BYTES_TO_T_UINT_8(0xBB, 0x39, 0xF9, 0x4E, 0x84, 0x9C, 0xF6, 0x96), + MBEDTLS_BYTES_TO_T_UINT_8(0xBC, 0xCF, 0x6D, 0xE2, 0xA1, 0x2D, 0xF9, 0x2B), +}; +static const mbedtls_mpi_uint brainpoolP384r1_T_23_Y[] = { + MBEDTLS_BYTES_TO_T_UINT_8(0x95, 0xC4, 0x90, 0x57, 0x31, 0x01, 0x05, 0x5E), + MBEDTLS_BYTES_TO_T_UINT_8(0xCC, 0x1E, 0xBB, 0xBF, 0x98, 0xA4, 0x7C, 0xE3), + MBEDTLS_BYTES_TO_T_UINT_8(0x89, 0xE3, 0xA0, 0xB2, 0xCD, 0x39, 0x9A, 0x3F), + MBEDTLS_BYTES_TO_T_UINT_8(0x92, 0x34, 0x60, 0x7A, 0x89, 0x98, 0xB5, 0x52), + MBEDTLS_BYTES_TO_T_UINT_8(0x8D, 0x20, 0x3D, 0x3A, 0x04, 0x8F, 0x5A, 0xAC), + MBEDTLS_BYTES_TO_T_UINT_8(0xA3, 0x26, 0xB6, 0x49, 0x09, 0x9C, 0x0F, 0x59), +}; +static const mbedtls_mpi_uint brainpoolP384r1_T_24_X[] = { + MBEDTLS_BYTES_TO_T_UINT_8(0x72, 0x66, 0xD2, 0x38, 0x2A, 0x62, 0x81, 0xCA), + MBEDTLS_BYTES_TO_T_UINT_8(0xC5, 0xC8, 0x20, 0x5E, 0x28, 0xA3, 0x81, 0xA7), + MBEDTLS_BYTES_TO_T_UINT_8(0x20, 0x31, 0xA4, 0xF1, 0xEA, 0x7D, 0x87, 0x45), + MBEDTLS_BYTES_TO_T_UINT_8(0x8F, 0x2C, 0x99, 0x09, 0x6F, 0x63, 0xEB, 0x2F), + MBEDTLS_BYTES_TO_T_UINT_8(0x73, 0x76, 0xDA, 0x1A, 0x06, 0xBE, 0xDE, 0xA2), + MBEDTLS_BYTES_TO_T_UINT_8(0x29, 0x09, 0x2E, 0x75, 0x39, 0x30, 0x2D, 0x42), +}; +static const mbedtls_mpi_uint brainpoolP384r1_T_24_Y[] = { + MBEDTLS_BYTES_TO_T_UINT_8(0x41, 0x9B, 0xC1, 0x5A, 0x17, 0xC3, 0x8C, 0x31), + MBEDTLS_BYTES_TO_T_UINT_8(0x58, 0x8D, 0x94, 0x4D, 0x3D, 0xAB, 0x60, 0xD4), + MBEDTLS_BYTES_TO_T_UINT_8(0xFF, 0xFD, 0x1E, 0x0F, 0x43, 0xAE, 0x9D, 0x62), + MBEDTLS_BYTES_TO_T_UINT_8(0x8E, 0xF2, 0xF3, 0x20, 0x1B, 0xAA, 0xB7, 0x41), + MBEDTLS_BYTES_TO_T_UINT_8(0x9D, 0x5B, 0xA4, 0xF4, 0x90, 0x3B, 0xE3, 0x71), + MBEDTLS_BYTES_TO_T_UINT_8(0xF7, 0x78, 0x72, 0xBD, 0x65, 0x09, 0x0B, 0x01), +}; +static const mbedtls_mpi_uint brainpoolP384r1_T_25_X[] = { + MBEDTLS_BYTES_TO_T_UINT_8(0xCA, 0x37, 0x2A, 0x6C, 0x16, 0x4F, 0x64, 0x59), + MBEDTLS_BYTES_TO_T_UINT_8(0x5A, 0xCE, 0xA3, 0x90, 0xB4, 0x9A, 0xBC, 0xF7), + MBEDTLS_BYTES_TO_T_UINT_8(0x27, 0x38, 0x55, 0x63, 0x1D, 0x3A, 0x6E, 0x18), + MBEDTLS_BYTES_TO_T_UINT_8(0x37, 0xB4, 0xAA, 0x99, 0x22, 0x45, 0x89, 0x2C), + MBEDTLS_BYTES_TO_T_UINT_8(0xB7, 0x7C, 0x8C, 0xA6, 0x3D, 0xA7, 0x3E, 0xE8), + MBEDTLS_BYTES_TO_T_UINT_8(0x70, 0x06, 0x42, 0xDC, 0xA6, 0xE3, 0xC6, 0x12), +}; +static const mbedtls_mpi_uint brainpoolP384r1_T_25_Y[] = { + MBEDTLS_BYTES_TO_T_UINT_8(0x55, 0x8C, 0x3D, 0x5D, 0x47, 0x31, 0x7C, 0xEB), + MBEDTLS_BYTES_TO_T_UINT_8(0x46, 0x85, 0xEE, 0x46, 0x7E, 0x13, 0x04, 0x41), + MBEDTLS_BYTES_TO_T_UINT_8(0x9E, 0x3C, 0x8B, 0x43, 0x2E, 0x74, 0xF5, 0xF6), + MBEDTLS_BYTES_TO_T_UINT_8(0xBA, 0x88, 0x8E, 0x07, 0x29, 0x08, 0x03, 0x26), + MBEDTLS_BYTES_TO_T_UINT_8(0xEA, 0x9B, 0x89, 0xEB, 0x08, 0xE8, 0x43, 0xB5), + MBEDTLS_BYTES_TO_T_UINT_8(0x17, 0x07, 0x67, 0xFD, 0xD9, 0x73, 0x6F, 0x18), +}; +static const mbedtls_mpi_uint brainpoolP384r1_T_26_X[] = { + MBEDTLS_BYTES_TO_T_UINT_8(0x29, 0xEB, 0x21, 0x8D, 0x98, 0x43, 0x74, 0x98), + MBEDTLS_BYTES_TO_T_UINT_8(0x88, 0xCC, 0x14, 0xD8, 0x08, 0xBB, 0xA6, 0xE3), + MBEDTLS_BYTES_TO_T_UINT_8(0xC4, 0x98, 0xF2, 0x6A, 0x18, 0xC3, 0xDD, 0x9E), + MBEDTLS_BYTES_TO_T_UINT_8(0xC7, 0x38, 0x91, 0xA0, 0x03, 0xF2, 0x04, 0x62), + MBEDTLS_BYTES_TO_T_UINT_8(0x7A, 0xAF, 0xE8, 0xFD, 0xFB, 0x13, 0x70, 0x74), + MBEDTLS_BYTES_TO_T_UINT_8(0xD0, 0x93, 0x87, 0x98, 0x4A, 0xE0, 0x00, 0x12), +}; +static const mbedtls_mpi_uint brainpoolP384r1_T_26_Y[] = { + MBEDTLS_BYTES_TO_T_UINT_8(0x97, 0x2E, 0x69, 0x9C, 0xA2, 0x2D, 0x03, 0x3F), + MBEDTLS_BYTES_TO_T_UINT_8(0x79, 0xFE, 0xF3, 0xB9, 0xC1, 0x85, 0x2A, 0xEE), + MBEDTLS_BYTES_TO_T_UINT_8(0xCE, 0xFD, 0x86, 0xB1, 0xCD, 0xBF, 0x41, 0xB7), + MBEDTLS_BYTES_TO_T_UINT_8(0xA0, 0xD8, 0x9A, 0x21, 0xF3, 0xFE, 0xCB, 0xF1), + MBEDTLS_BYTES_TO_T_UINT_8(0x95, 0x78, 0x04, 0x60, 0xB7, 0xA9, 0xA2, 0x84), + MBEDTLS_BYTES_TO_T_UINT_8(0xE8, 0x1E, 0x66, 0x2A, 0x54, 0x51, 0xBD, 0x8B), +}; +static const mbedtls_mpi_uint brainpoolP384r1_T_27_X[] = { + MBEDTLS_BYTES_TO_T_UINT_8(0x8E, 0x16, 0x36, 0xEF, 0x61, 0x2D, 0xEE, 0x3B), + MBEDTLS_BYTES_TO_T_UINT_8(0x45, 0x5F, 0x88, 0xA0, 0x13, 0x12, 0xF7, 0x23), + MBEDTLS_BYTES_TO_T_UINT_8(0xA9, 0xC6, 0xAD, 0x4A, 0x4A, 0x07, 0x01, 0x5B), + MBEDTLS_BYTES_TO_T_UINT_8(0xB8, 0x74, 0xB1, 0x4F, 0xEB, 0xBD, 0xD5, 0x6B), + MBEDTLS_BYTES_TO_T_UINT_8(0x57, 0xF9, 0x71, 0xA2, 0x06, 0x4F, 0xD7, 0xBC), + MBEDTLS_BYTES_TO_T_UINT_8(0xFF, 0x8B, 0x4D, 0x48, 0xE0, 0x98, 0xFB, 0x6A), +}; +static const mbedtls_mpi_uint brainpoolP384r1_T_27_Y[] = { + MBEDTLS_BYTES_TO_T_UINT_8(0xC4, 0xBA, 0x10, 0xA3, 0x0D, 0x52, 0xAC, 0x3A), + MBEDTLS_BYTES_TO_T_UINT_8(0x11, 0xD0, 0xE0, 0x36, 0xE6, 0x07, 0x3A, 0x30), + MBEDTLS_BYTES_TO_T_UINT_8(0x7E, 0x80, 0xF0, 0xAA, 0x49, 0x22, 0x4B, 0xDD), + MBEDTLS_BYTES_TO_T_UINT_8(0xFF, 0xC7, 0xAB, 0x1C, 0x89, 0xCD, 0x24, 0x40), + MBEDTLS_BYTES_TO_T_UINT_8(0x82, 0x2A, 0xFC, 0xB3, 0x6D, 0x45, 0x96, 0x49), + MBEDTLS_BYTES_TO_T_UINT_8(0x63, 0xE4, 0xDB, 0x52, 0x3F, 0xC4, 0xB4, 0x19), +}; +static const mbedtls_mpi_uint brainpoolP384r1_T_28_X[] = { + MBEDTLS_BYTES_TO_T_UINT_8(0x5B, 0xCC, 0xC8, 0x7F, 0xBB, 0x6B, 0x87, 0x47), + MBEDTLS_BYTES_TO_T_UINT_8(0xC0, 0x21, 0x3C, 0x69, 0x7D, 0x38, 0x57, 0x50), + MBEDTLS_BYTES_TO_T_UINT_8(0x52, 0x4C, 0x18, 0x3C, 0x53, 0xA5, 0x48, 0x6D), + MBEDTLS_BYTES_TO_T_UINT_8(0x21, 0xC3, 0x64, 0x45, 0xDB, 0xC4, 0x6D, 0x15), + MBEDTLS_BYTES_TO_T_UINT_8(0x49, 0xCC, 0xD1, 0xBB, 0x17, 0xB8, 0x34, 0x2D), + MBEDTLS_BYTES_TO_T_UINT_8(0x6C, 0x69, 0x71, 0xFA, 0xA0, 0x28, 0x4A, 0x3D), +}; +static const mbedtls_mpi_uint brainpoolP384r1_T_28_Y[] = { + MBEDTLS_BYTES_TO_T_UINT_8(0xED, 0xE8, 0x9E, 0x39, 0xEA, 0x8D, 0x38, 0xDB), + MBEDTLS_BYTES_TO_T_UINT_8(0xCC, 0x9C, 0xBB, 0xCD, 0x80, 0x1A, 0xEE, 0xB7), + MBEDTLS_BYTES_TO_T_UINT_8(0xBC, 0xA0, 0x45, 0xBF, 0xD9, 0x22, 0x11, 0x32), + MBEDTLS_BYTES_TO_T_UINT_8(0xDA, 0x7C, 0x5C, 0xD9, 0xC0, 0x9F, 0x69, 0xF5), + MBEDTLS_BYTES_TO_T_UINT_8(0xBC, 0x8A, 0xA6, 0x79, 0x4E, 0x35, 0xB9, 0xD5), + MBEDTLS_BYTES_TO_T_UINT_8(0xCC, 0x8B, 0x9A, 0x3E, 0xA1, 0xB8, 0x28, 0x10), +}; +static const mbedtls_mpi_uint brainpoolP384r1_T_29_X[] = { + MBEDTLS_BYTES_TO_T_UINT_8(0x55, 0x2F, 0xEF, 0xBB, 0xA9, 0x72, 0x7F, 0xEA), + MBEDTLS_BYTES_TO_T_UINT_8(0xB5, 0x34, 0xB7, 0x12, 0xB9, 0xE7, 0xC3, 0x2A), + MBEDTLS_BYTES_TO_T_UINT_8(0xF8, 0x1D, 0xD9, 0x42, 0x77, 0x0C, 0x71, 0x6E), + MBEDTLS_BYTES_TO_T_UINT_8(0xEC, 0x01, 0x59, 0xA7, 0x56, 0x03, 0x91, 0x8D), + MBEDTLS_BYTES_TO_T_UINT_8(0x6C, 0x91, 0x99, 0x33, 0x30, 0x3E, 0xEF, 0x13), + MBEDTLS_BYTES_TO_T_UINT_8(0x87, 0xC9, 0x5A, 0x9A, 0x54, 0x66, 0xF1, 0x70), +}; +static const mbedtls_mpi_uint brainpoolP384r1_T_29_Y[] = { + MBEDTLS_BYTES_TO_T_UINT_8(0x64, 0x2C, 0xB7, 0x6E, 0x71, 0x7D, 0x35, 0x30), + MBEDTLS_BYTES_TO_T_UINT_8(0x1A, 0x0D, 0xEF, 0xD1, 0x2D, 0x99, 0x63, 0x2F), + MBEDTLS_BYTES_TO_T_UINT_8(0xE4, 0x31, 0xAF, 0x2D, 0xC9, 0xC6, 0xC2, 0xAE), + MBEDTLS_BYTES_TO_T_UINT_8(0x19, 0xC0, 0xDF, 0x80, 0x54, 0xC4, 0xAC, 0xF3), + MBEDTLS_BYTES_TO_T_UINT_8(0xE3, 0x6B, 0xA0, 0x84, 0x96, 0xF7, 0x31, 0xC8), + MBEDTLS_BYTES_TO_T_UINT_8(0x93, 0xE2, 0x7C, 0x7A, 0x41, 0x45, 0x75, 0x6A), +}; +static const mbedtls_mpi_uint brainpoolP384r1_T_30_X[] = { + MBEDTLS_BYTES_TO_T_UINT_8(0xAE, 0xEE, 0x58, 0x31, 0xE8, 0x68, 0xD6, 0x76), + MBEDTLS_BYTES_TO_T_UINT_8(0xD2, 0x2E, 0x48, 0xB7, 0x09, 0x9F, 0xD4, 0xCA), + MBEDTLS_BYTES_TO_T_UINT_8(0x34, 0xA9, 0x5C, 0xE7, 0x64, 0x43, 0x5D, 0xC9), + MBEDTLS_BYTES_TO_T_UINT_8(0x9E, 0x58, 0x9F, 0x50, 0xAB, 0x68, 0xFF, 0x6D), + MBEDTLS_BYTES_TO_T_UINT_8(0x87, 0x88, 0x2D, 0xBA, 0x12, 0xBF, 0x8D, 0x7D), + MBEDTLS_BYTES_TO_T_UINT_8(0xD4, 0xDF, 0x6F, 0xB3, 0x75, 0xA4, 0x55, 0x73), +}; +static const mbedtls_mpi_uint brainpoolP384r1_T_30_Y[] = { + MBEDTLS_BYTES_TO_T_UINT_8(0x6D, 0x17, 0x92, 0x39, 0xB7, 0x13, 0x37, 0x6F), + MBEDTLS_BYTES_TO_T_UINT_8(0x5E, 0x43, 0x71, 0xA7, 0xCA, 0x17, 0x1B, 0x32), + MBEDTLS_BYTES_TO_T_UINT_8(0xE7, 0xB9, 0xB0, 0x78, 0xEF, 0xA0, 0xDA, 0x83), + MBEDTLS_BYTES_TO_T_UINT_8(0x9A, 0x84, 0xF2, 0x0F, 0x85, 0xA2, 0xB6, 0x1F), + MBEDTLS_BYTES_TO_T_UINT_8(0x72, 0x65, 0x2E, 0x6E, 0x45, 0xB9, 0x4C, 0x3C), + MBEDTLS_BYTES_TO_T_UINT_8(0xFE, 0x6A, 0x8C, 0x2B, 0x77, 0x96, 0x36, 0x22), +}; +static const mbedtls_mpi_uint brainpoolP384r1_T_31_X[] = { + MBEDTLS_BYTES_TO_T_UINT_8(0x68, 0x7A, 0x13, 0x4A, 0x97, 0x63, 0x02, 0x10), + MBEDTLS_BYTES_TO_T_UINT_8(0xBC, 0x1E, 0x06, 0x03, 0x8F, 0xB9, 0xEE, 0x64), + MBEDTLS_BYTES_TO_T_UINT_8(0x68, 0xEE, 0x8B, 0x89, 0xA9, 0x70, 0xDB, 0xCE), + MBEDTLS_BYTES_TO_T_UINT_8(0x15, 0x7B, 0x81, 0xC9, 0x70, 0x8D, 0x62, 0x32), + MBEDTLS_BYTES_TO_T_UINT_8(0x75, 0xDA, 0x46, 0xF8, 0xF9, 0x3A, 0xBE, 0x55), + MBEDTLS_BYTES_TO_T_UINT_8(0x9F, 0x9C, 0x7A, 0x97, 0x62, 0xEB, 0xFA, 0x0F), +}; +static const mbedtls_mpi_uint brainpoolP384r1_T_31_Y[] = { + MBEDTLS_BYTES_TO_T_UINT_8(0xB2, 0x03, 0x3D, 0x3C, 0x46, 0x27, 0x9E, 0x65), + MBEDTLS_BYTES_TO_T_UINT_8(0xA4, 0x08, 0x1C, 0xD5, 0x25, 0xAF, 0xE9, 0x40), + MBEDTLS_BYTES_TO_T_UINT_8(0xFE, 0x69, 0xDC, 0x59, 0xF4, 0x8A, 0x7C, 0x1F), + MBEDTLS_BYTES_TO_T_UINT_8(0xFC, 0x9A, 0x7A, 0x99, 0x21, 0x0C, 0x4E, 0xE3), + MBEDTLS_BYTES_TO_T_UINT_8(0xF5, 0xCE, 0x85, 0x5F, 0xAC, 0xAA, 0x82, 0x10), + MBEDTLS_BYTES_TO_T_UINT_8(0x83, 0x57, 0x69, 0x90, 0x76, 0xF3, 0x53, 0x3F), +}; +static const mbedtls_ecp_point brainpoolP384r1_T[32] = { + ECP_POINT_INIT_XY_Z1(brainpoolP384r1_T_0_X, brainpoolP384r1_T_0_Y), + ECP_POINT_INIT_XY_Z0(brainpoolP384r1_T_1_X, brainpoolP384r1_T_1_Y), + ECP_POINT_INIT_XY_Z0(brainpoolP384r1_T_2_X, brainpoolP384r1_T_2_Y), + ECP_POINT_INIT_XY_Z0(brainpoolP384r1_T_3_X, brainpoolP384r1_T_3_Y), + ECP_POINT_INIT_XY_Z0(brainpoolP384r1_T_4_X, brainpoolP384r1_T_4_Y), + ECP_POINT_INIT_XY_Z0(brainpoolP384r1_T_5_X, brainpoolP384r1_T_5_Y), + ECP_POINT_INIT_XY_Z0(brainpoolP384r1_T_6_X, brainpoolP384r1_T_6_Y), + ECP_POINT_INIT_XY_Z0(brainpoolP384r1_T_7_X, brainpoolP384r1_T_7_Y), + ECP_POINT_INIT_XY_Z0(brainpoolP384r1_T_8_X, brainpoolP384r1_T_8_Y), + ECP_POINT_INIT_XY_Z0(brainpoolP384r1_T_9_X, brainpoolP384r1_T_9_Y), + ECP_POINT_INIT_XY_Z0(brainpoolP384r1_T_10_X, brainpoolP384r1_T_10_Y), + ECP_POINT_INIT_XY_Z0(brainpoolP384r1_T_11_X, brainpoolP384r1_T_11_Y), + ECP_POINT_INIT_XY_Z0(brainpoolP384r1_T_12_X, brainpoolP384r1_T_12_Y), + ECP_POINT_INIT_XY_Z0(brainpoolP384r1_T_13_X, brainpoolP384r1_T_13_Y), + ECP_POINT_INIT_XY_Z0(brainpoolP384r1_T_14_X, brainpoolP384r1_T_14_Y), + ECP_POINT_INIT_XY_Z0(brainpoolP384r1_T_15_X, brainpoolP384r1_T_15_Y), + ECP_POINT_INIT_XY_Z0(brainpoolP384r1_T_16_X, brainpoolP384r1_T_16_Y), + ECP_POINT_INIT_XY_Z0(brainpoolP384r1_T_17_X, brainpoolP384r1_T_17_Y), + ECP_POINT_INIT_XY_Z0(brainpoolP384r1_T_18_X, brainpoolP384r1_T_18_Y), + ECP_POINT_INIT_XY_Z0(brainpoolP384r1_T_19_X, brainpoolP384r1_T_19_Y), + ECP_POINT_INIT_XY_Z0(brainpoolP384r1_T_20_X, brainpoolP384r1_T_20_Y), + ECP_POINT_INIT_XY_Z0(brainpoolP384r1_T_21_X, brainpoolP384r1_T_21_Y), + ECP_POINT_INIT_XY_Z0(brainpoolP384r1_T_22_X, brainpoolP384r1_T_22_Y), + ECP_POINT_INIT_XY_Z0(brainpoolP384r1_T_23_X, brainpoolP384r1_T_23_Y), + ECP_POINT_INIT_XY_Z0(brainpoolP384r1_T_24_X, brainpoolP384r1_T_24_Y), + ECP_POINT_INIT_XY_Z0(brainpoolP384r1_T_25_X, brainpoolP384r1_T_25_Y), + ECP_POINT_INIT_XY_Z0(brainpoolP384r1_T_26_X, brainpoolP384r1_T_26_Y), + ECP_POINT_INIT_XY_Z0(brainpoolP384r1_T_27_X, brainpoolP384r1_T_27_Y), + ECP_POINT_INIT_XY_Z0(brainpoolP384r1_T_28_X, brainpoolP384r1_T_28_Y), + ECP_POINT_INIT_XY_Z0(brainpoolP384r1_T_29_X, brainpoolP384r1_T_29_Y), + ECP_POINT_INIT_XY_Z0(brainpoolP384r1_T_30_X, brainpoolP384r1_T_30_Y), + ECP_POINT_INIT_XY_Z0(brainpoolP384r1_T_31_X, brainpoolP384r1_T_31_Y), +}; +#else +#define brainpoolP384r1_T NULL +#endif + +#endif /* MBEDTLS_ECP_DP_BP384R1_ENABLED */ + +/* + * Domain parameters for brainpoolP512r1 (RFC 5639 3.7) + */ +#if defined(MBEDTLS_ECP_DP_BP512R1_ENABLED) +static const mbedtls_mpi_uint brainpoolP512r1_p[] = { + MBEDTLS_BYTES_TO_T_UINT_8(0xF3, 0x48, 0x3A, 0x58, 0x56, 0x60, 0xAA, 0x28), + MBEDTLS_BYTES_TO_T_UINT_8(0x85, 0xC6, 0x82, 0x2D, 0x2F, 0xFF, 0x81, 0x28), + MBEDTLS_BYTES_TO_T_UINT_8(0xE6, 0x80, 0xA3, 0xE6, 0x2A, 0xA1, 0xCD, 0xAE), + MBEDTLS_BYTES_TO_T_UINT_8(0x42, 0x68, 0xC6, 0x9B, 0x00, 0x9B, 0x4D, 0x7D), + MBEDTLS_BYTES_TO_T_UINT_8(0x71, 0x08, 0x33, 0x70, 0xCA, 0x9C, 0x63, 0xD6), + MBEDTLS_BYTES_TO_T_UINT_8(0x0E, 0xD2, 0xC9, 0xB3, 0xB3, 0x8D, 0x30, 0xCB), + MBEDTLS_BYTES_TO_T_UINT_8(0x07, 0xFC, 0xC9, 0x33, 0xAE, 0xE6, 0xD4, 0x3F), + MBEDTLS_BYTES_TO_T_UINT_8(0x8B, 0xC4, 0xE9, 0xDB, 0xB8, 0x9D, 0xDD, 0xAA), +}; +static const mbedtls_mpi_uint brainpoolP512r1_a[] = { + MBEDTLS_BYTES_TO_T_UINT_8(0xCA, 0x94, 0xFC, 0x77, 0x4D, 0xAC, 0xC1, 0xE7), + MBEDTLS_BYTES_TO_T_UINT_8(0xB9, 0xC7, 0xF2, 0x2B, 0xA7, 0x17, 0x11, 0x7F), + MBEDTLS_BYTES_TO_T_UINT_8(0xB5, 0xC8, 0x9A, 0x8B, 0xC9, 0xF1, 0x2E, 0x0A), + MBEDTLS_BYTES_TO_T_UINT_8(0xA1, 0x3A, 0x25, 0xA8, 0x5A, 0x5D, 0xED, 0x2D), + MBEDTLS_BYTES_TO_T_UINT_8(0xBC, 0x63, 0x98, 0xEA, 0xCA, 0x41, 0x34, 0xA8), + MBEDTLS_BYTES_TO_T_UINT_8(0x10, 0x16, 0xF9, 0x3D, 0x8D, 0xDD, 0xCB, 0x94), + MBEDTLS_BYTES_TO_T_UINT_8(0xC5, 0x4C, 0x23, 0xAC, 0x45, 0x71, 0x32, 0xE2), + MBEDTLS_BYTES_TO_T_UINT_8(0x89, 0x3B, 0x60, 0x8B, 0x31, 0xA3, 0x30, 0x78), +}; +static const mbedtls_mpi_uint brainpoolP512r1_b[] = { + MBEDTLS_BYTES_TO_T_UINT_8(0x23, 0xF7, 0x16, 0x80, 0x63, 0xBD, 0x09, 0x28), + MBEDTLS_BYTES_TO_T_UINT_8(0xDD, 0xE5, 0xBA, 0x5E, 0xB7, 0x50, 0x40, 0x98), + MBEDTLS_BYTES_TO_T_UINT_8(0x67, 0x3E, 0x08, 0xDC, 0xCA, 0x94, 0xFC, 0x77), + MBEDTLS_BYTES_TO_T_UINT_8(0x4D, 0xAC, 0xC1, 0xE7, 0xB9, 0xC7, 0xF2, 0x2B), + MBEDTLS_BYTES_TO_T_UINT_8(0xA7, 0x17, 0x11, 0x7F, 0xB5, 0xC8, 0x9A, 0x8B), + MBEDTLS_BYTES_TO_T_UINT_8(0xC9, 0xF1, 0x2E, 0x0A, 0xA1, 0x3A, 0x25, 0xA8), + MBEDTLS_BYTES_TO_T_UINT_8(0x5A, 0x5D, 0xED, 0x2D, 0xBC, 0x63, 0x98, 0xEA), + MBEDTLS_BYTES_TO_T_UINT_8(0xCA, 0x41, 0x34, 0xA8, 0x10, 0x16, 0xF9, 0x3D), +}; +static const mbedtls_mpi_uint brainpoolP512r1_gx[] = { + MBEDTLS_BYTES_TO_T_UINT_8(0x22, 0xF8, 0xB9, 0xBC, 0x09, 0x22, 0x35, 0x8B), + MBEDTLS_BYTES_TO_T_UINT_8(0x68, 0x5E, 0x6A, 0x40, 0x47, 0x50, 0x6D, 0x7C), + MBEDTLS_BYTES_TO_T_UINT_8(0x5F, 0x7D, 0xB9, 0x93, 0x7B, 0x68, 0xD1, 0x50), + MBEDTLS_BYTES_TO_T_UINT_8(0x8D, 0xD4, 0xD0, 0xE2, 0x78, 0x1F, 0x3B, 0xFF), + MBEDTLS_BYTES_TO_T_UINT_8(0x8E, 0x09, 0xD0, 0xF4, 0xEE, 0x62, 0x3B, 0xB4), + MBEDTLS_BYTES_TO_T_UINT_8(0xC1, 0x16, 0xD9, 0xB5, 0x70, 0x9F, 0xED, 0x85), + MBEDTLS_BYTES_TO_T_UINT_8(0x93, 0x6A, 0x4C, 0x9C, 0x2E, 0x32, 0x21, 0x5A), + MBEDTLS_BYTES_TO_T_UINT_8(0x64, 0xD9, 0x2E, 0xD8, 0xBD, 0xE4, 0xAE, 0x81), +}; +static const mbedtls_mpi_uint brainpoolP512r1_gy[] = { + MBEDTLS_BYTES_TO_T_UINT_8(0x92, 0x08, 0xD8, 0x3A, 0x0F, 0x1E, 0xCD, 0x78), + MBEDTLS_BYTES_TO_T_UINT_8(0x06, 0x54, 0xF0, 0xA8, 0x2F, 0x2B, 0xCA, 0xD1), + MBEDTLS_BYTES_TO_T_UINT_8(0xAE, 0x63, 0x27, 0x8A, 0xD8, 0x4B, 0xCA, 0x5B), + MBEDTLS_BYTES_TO_T_UINT_8(0x5E, 0x48, 0x5F, 0x4A, 0x49, 0xDE, 0xDC, 0xB2), + MBEDTLS_BYTES_TO_T_UINT_8(0x11, 0x81, 0x1F, 0x88, 0x5B, 0xC5, 0x00, 0xA0), + MBEDTLS_BYTES_TO_T_UINT_8(0x1A, 0x7B, 0xA5, 0x24, 0x00, 0xF7, 0x09, 0xF2), + MBEDTLS_BYTES_TO_T_UINT_8(0xFD, 0x22, 0x78, 0xCF, 0xA9, 0xBF, 0xEA, 0xC0), + MBEDTLS_BYTES_TO_T_UINT_8(0xEC, 0x32, 0x63, 0x56, 0x5D, 0x38, 0xDE, 0x7D), +}; +static const mbedtls_mpi_uint brainpoolP512r1_n[] = { + MBEDTLS_BYTES_TO_T_UINT_8(0x69, 0x00, 0xA9, 0x9C, 0x82, 0x96, 0x87, 0xB5), + MBEDTLS_BYTES_TO_T_UINT_8(0xDD, 0xDA, 0x5D, 0x08, 0x81, 0xD3, 0xB1, 0x1D), + MBEDTLS_BYTES_TO_T_UINT_8(0x47, 0x10, 0xAC, 0x7F, 0x19, 0x61, 0x86, 0x41), + MBEDTLS_BYTES_TO_T_UINT_8(0x19, 0x26, 0xA9, 0x4C, 0x41, 0x5C, 0x3E, 0x55), + MBEDTLS_BYTES_TO_T_UINT_8(0x70, 0x08, 0x33, 0x70, 0xCA, 0x9C, 0x63, 0xD6), + MBEDTLS_BYTES_TO_T_UINT_8(0x0E, 0xD2, 0xC9, 0xB3, 0xB3, 0x8D, 0x30, 0xCB), + MBEDTLS_BYTES_TO_T_UINT_8(0x07, 0xFC, 0xC9, 0x33, 0xAE, 0xE6, 0xD4, 0x3F), + MBEDTLS_BYTES_TO_T_UINT_8(0x8B, 0xC4, 0xE9, 0xDB, 0xB8, 0x9D, 0xDD, 0xAA), +}; + +#if MBEDTLS_ECP_FIXED_POINT_OPTIM == 1 +static const mbedtls_mpi_uint brainpoolP512r1_T_0_X[] = { + MBEDTLS_BYTES_TO_T_UINT_8(0x22, 0xF8, 0xB9, 0xBC, 0x09, 0x22, 0x35, 0x8B), + MBEDTLS_BYTES_TO_T_UINT_8(0x68, 0x5E, 0x6A, 0x40, 0x47, 0x50, 0x6D, 0x7C), + MBEDTLS_BYTES_TO_T_UINT_8(0x5F, 0x7D, 0xB9, 0x93, 0x7B, 0x68, 0xD1, 0x50), + MBEDTLS_BYTES_TO_T_UINT_8(0x8D, 0xD4, 0xD0, 0xE2, 0x78, 0x1F, 0x3B, 0xFF), + MBEDTLS_BYTES_TO_T_UINT_8(0x8E, 0x09, 0xD0, 0xF4, 0xEE, 0x62, 0x3B, 0xB4), + MBEDTLS_BYTES_TO_T_UINT_8(0xC1, 0x16, 0xD9, 0xB5, 0x70, 0x9F, 0xED, 0x85), + MBEDTLS_BYTES_TO_T_UINT_8(0x93, 0x6A, 0x4C, 0x9C, 0x2E, 0x32, 0x21, 0x5A), + MBEDTLS_BYTES_TO_T_UINT_8(0x64, 0xD9, 0x2E, 0xD8, 0xBD, 0xE4, 0xAE, 0x81), +}; +static const mbedtls_mpi_uint brainpoolP512r1_T_0_Y[] = { + MBEDTLS_BYTES_TO_T_UINT_8(0x92, 0x08, 0xD8, 0x3A, 0x0F, 0x1E, 0xCD, 0x78), + MBEDTLS_BYTES_TO_T_UINT_8(0x06, 0x54, 0xF0, 0xA8, 0x2F, 0x2B, 0xCA, 0xD1), + MBEDTLS_BYTES_TO_T_UINT_8(0xAE, 0x63, 0x27, 0x8A, 0xD8, 0x4B, 0xCA, 0x5B), + MBEDTLS_BYTES_TO_T_UINT_8(0x5E, 0x48, 0x5F, 0x4A, 0x49, 0xDE, 0xDC, 0xB2), + MBEDTLS_BYTES_TO_T_UINT_8(0x11, 0x81, 0x1F, 0x88, 0x5B, 0xC5, 0x00, 0xA0), + MBEDTLS_BYTES_TO_T_UINT_8(0x1A, 0x7B, 0xA5, 0x24, 0x00, 0xF7, 0x09, 0xF2), + MBEDTLS_BYTES_TO_T_UINT_8(0xFD, 0x22, 0x78, 0xCF, 0xA9, 0xBF, 0xEA, 0xC0), + MBEDTLS_BYTES_TO_T_UINT_8(0xEC, 0x32, 0x63, 0x56, 0x5D, 0x38, 0xDE, 0x7D), +}; +static const mbedtls_mpi_uint brainpoolP512r1_T_1_X[] = { + MBEDTLS_BYTES_TO_T_UINT_8(0xEA, 0xE9, 0x6B, 0x8C, 0x6F, 0x9D, 0x88, 0x43), + MBEDTLS_BYTES_TO_T_UINT_8(0xBB, 0x4F, 0x86, 0x96, 0xA7, 0x56, 0xD1, 0x37), + MBEDTLS_BYTES_TO_T_UINT_8(0x9D, 0xAB, 0xFA, 0xEE, 0xA7, 0xF5, 0x0E, 0xA6), + MBEDTLS_BYTES_TO_T_UINT_8(0xE3, 0x40, 0xEF, 0x9E, 0x6D, 0xD6, 0x32, 0x33), + MBEDTLS_BYTES_TO_T_UINT_8(0xE3, 0xED, 0x56, 0x14, 0x57, 0x1A, 0x8D, 0x69), + MBEDTLS_BYTES_TO_T_UINT_8(0xA4, 0xED, 0x4D, 0x3A, 0xFA, 0x71, 0x75, 0x6B), + MBEDTLS_BYTES_TO_T_UINT_8(0x66, 0xC5, 0x76, 0x1C, 0x14, 0xBE, 0xB5, 0xCD), + MBEDTLS_BYTES_TO_T_UINT_8(0xE1, 0x5A, 0xCB, 0xE7, 0x36, 0x1D, 0x52, 0x1C), +}; +static const mbedtls_mpi_uint brainpoolP512r1_T_1_Y[] = { + MBEDTLS_BYTES_TO_T_UINT_8(0x6B, 0x8D, 0x7A, 0xEB, 0xA3, 0x8B, 0xD5, 0xB0), + MBEDTLS_BYTES_TO_T_UINT_8(0x1F, 0xA3, 0x41, 0xF8, 0xAC, 0x9E, 0xAB, 0x74), + MBEDTLS_BYTES_TO_T_UINT_8(0x12, 0xE3, 0x65, 0x0D, 0x1C, 0xFE, 0x09, 0x2B), + MBEDTLS_BYTES_TO_T_UINT_8(0x3F, 0xCA, 0x13, 0x3F, 0xC5, 0xF9, 0x7E, 0xEC), + MBEDTLS_BYTES_TO_T_UINT_8(0x2C, 0x5D, 0x63, 0x28, 0xA6, 0x89, 0xD3, 0x91), + MBEDTLS_BYTES_TO_T_UINT_8(0xC9, 0x95, 0x3F, 0x7A, 0x82, 0xD4, 0x77, 0xE3), + MBEDTLS_BYTES_TO_T_UINT_8(0x34, 0xBB, 0x92, 0x32, 0x00, 0xF4, 0x66, 0x42), + MBEDTLS_BYTES_TO_T_UINT_8(0xBA, 0x58, 0x31, 0xD1, 0x17, 0x9F, 0x2A, 0x22), +}; +static const mbedtls_mpi_uint brainpoolP512r1_T_2_X[] = { + MBEDTLS_BYTES_TO_T_UINT_8(0x52, 0x36, 0xA9, 0xCD, 0x80, 0xA5, 0x2D, 0x78), + MBEDTLS_BYTES_TO_T_UINT_8(0x91, 0x44, 0xAB, 0xCE, 0x71, 0xFF, 0x0C, 0x9B), + MBEDTLS_BYTES_TO_T_UINT_8(0x18, 0x24, 0x58, 0x35, 0x5A, 0x21, 0x32, 0x93), + MBEDTLS_BYTES_TO_T_UINT_8(0x1B, 0xA6, 0x28, 0xF8, 0x7A, 0x97, 0xAE, 0x8B), + MBEDTLS_BYTES_TO_T_UINT_8(0x84, 0xE7, 0x08, 0xFA, 0x47, 0xC9, 0x55, 0x09), + MBEDTLS_BYTES_TO_T_UINT_8(0x8D, 0xAC, 0x2E, 0x84, 0xA4, 0xF5, 0x52, 0xC4), + MBEDTLS_BYTES_TO_T_UINT_8(0xD9, 0x58, 0x05, 0x9D, 0xA7, 0xC8, 0x71, 0xBF), + MBEDTLS_BYTES_TO_T_UINT_8(0xB3, 0x92, 0xB4, 0x92, 0xC1, 0x92, 0xEC, 0x6B), +}; +static const mbedtls_mpi_uint brainpoolP512r1_T_2_Y[] = { + MBEDTLS_BYTES_TO_T_UINT_8(0x4A, 0x48, 0x2D, 0x79, 0x5E, 0x58, 0xE5, 0x69), + MBEDTLS_BYTES_TO_T_UINT_8(0xB4, 0x85, 0x26, 0xEC, 0xE9, 0x6E, 0xD4, 0x06), + MBEDTLS_BYTES_TO_T_UINT_8(0x98, 0x68, 0x26, 0x87, 0x38, 0xA2, 0xD2, 0x0B), + MBEDTLS_BYTES_TO_T_UINT_8(0xF7, 0x17, 0x60, 0xCE, 0x75, 0xF8, 0xA5, 0x6F), + MBEDTLS_BYTES_TO_T_UINT_8(0x20, 0x51, 0xDB, 0xA9, 0xAE, 0x87, 0xF1, 0x15), + MBEDTLS_BYTES_TO_T_UINT_8(0xDD, 0x49, 0x92, 0x3B, 0x19, 0x96, 0xF5, 0xB0), + MBEDTLS_BYTES_TO_T_UINT_8(0xC4, 0xD5, 0x52, 0x52, 0x8C, 0xCE, 0xFD, 0xFA), + MBEDTLS_BYTES_TO_T_UINT_8(0x24, 0x18, 0x0A, 0xE6, 0xF6, 0xAE, 0x08, 0x41), +}; +static const mbedtls_mpi_uint brainpoolP512r1_T_3_X[] = { + MBEDTLS_BYTES_TO_T_UINT_8(0x7E, 0x2B, 0xD8, 0x54, 0xCE, 0xB0, 0x57, 0xFE), + MBEDTLS_BYTES_TO_T_UINT_8(0x8A, 0xB0, 0xF8, 0x9E, 0x03, 0x03, 0x3C, 0x5D), + MBEDTLS_BYTES_TO_T_UINT_8(0x93, 0x0E, 0x29, 0x29, 0x00, 0xF3, 0x70, 0xBF), + MBEDTLS_BYTES_TO_T_UINT_8(0x54, 0x33, 0x99, 0x0E, 0x00, 0x5D, 0xFE, 0x4B), + MBEDTLS_BYTES_TO_T_UINT_8(0x46, 0x2D, 0xF2, 0x59, 0x32, 0xCF, 0x03, 0xF4), + MBEDTLS_BYTES_TO_T_UINT_8(0x3B, 0xC9, 0x72, 0xAE, 0x0C, 0xEF, 0xD1, 0x5B), + MBEDTLS_BYTES_TO_T_UINT_8(0xB6, 0x5A, 0x27, 0xBF, 0x2F, 0x45, 0xF9, 0x51), + MBEDTLS_BYTES_TO_T_UINT_8(0xD4, 0xBE, 0xE5, 0x2C, 0xFF, 0x5B, 0x1E, 0x88), +}; +static const mbedtls_mpi_uint brainpoolP512r1_T_3_Y[] = { + MBEDTLS_BYTES_TO_T_UINT_8(0xAA, 0xAC, 0xBB, 0xD8, 0x83, 0xC2, 0x46, 0xF6), + MBEDTLS_BYTES_TO_T_UINT_8(0xCF, 0xDC, 0xCE, 0x15, 0xB4, 0xEF, 0xCF, 0x46), + MBEDTLS_BYTES_TO_T_UINT_8(0x46, 0xDB, 0x5E, 0x94, 0x31, 0x0B, 0xB2, 0x7A), + MBEDTLS_BYTES_TO_T_UINT_8(0x3C, 0xB9, 0xE3, 0xE3, 0x11, 0x71, 0x41, 0x1E), + MBEDTLS_BYTES_TO_T_UINT_8(0x36, 0xE3, 0x01, 0xB7, 0x7D, 0xBC, 0x65, 0xBE), + MBEDTLS_BYTES_TO_T_UINT_8(0xFC, 0x07, 0x65, 0x87, 0xA7, 0xE8, 0x48, 0xE3), + MBEDTLS_BYTES_TO_T_UINT_8(0x66, 0x48, 0x8F, 0xD4, 0x30, 0x8E, 0xB4, 0x6C), + MBEDTLS_BYTES_TO_T_UINT_8(0x86, 0xE0, 0x73, 0xBE, 0x1E, 0xBF, 0x56, 0x36), +}; +static const mbedtls_mpi_uint brainpoolP512r1_T_4_X[] = { + MBEDTLS_BYTES_TO_T_UINT_8(0xFE, 0x0E, 0x5E, 0x87, 0xC5, 0xAB, 0x0E, 0x3C), + MBEDTLS_BYTES_TO_T_UINT_8(0xB9, 0xF9, 0x5F, 0x80, 0x24, 0x4C, 0x2A, 0xF1), + MBEDTLS_BYTES_TO_T_UINT_8(0xDE, 0x15, 0x21, 0x54, 0x92, 0x84, 0x8D, 0x6A), + MBEDTLS_BYTES_TO_T_UINT_8(0xA8, 0x8A, 0x47, 0x74, 0xDC, 0x42, 0xB1, 0xF8), + MBEDTLS_BYTES_TO_T_UINT_8(0x81, 0xF7, 0x30, 0xFD, 0xC1, 0x9B, 0x0C, 0x5B), + MBEDTLS_BYTES_TO_T_UINT_8(0x4E, 0x6C, 0xCC, 0xDF, 0xC5, 0xE3, 0xA9, 0xD5), + MBEDTLS_BYTES_TO_T_UINT_8(0xD6, 0x67, 0x59, 0x10, 0x5C, 0x51, 0x54, 0x40), + MBEDTLS_BYTES_TO_T_UINT_8(0xA0, 0x37, 0xFB, 0x6E, 0xB0, 0x78, 0x63, 0x8E), +}; +static const mbedtls_mpi_uint brainpoolP512r1_T_4_Y[] = { + MBEDTLS_BYTES_TO_T_UINT_8(0xA5, 0xEF, 0xC4, 0x39, 0x20, 0xF1, 0x46, 0x66), + MBEDTLS_BYTES_TO_T_UINT_8(0xE2, 0x62, 0xAE, 0xFF, 0x10, 0xE4, 0xE2, 0xE9), + MBEDTLS_BYTES_TO_T_UINT_8(0xFF, 0x5C, 0xF5, 0x2E, 0x22, 0x89, 0xE5, 0x82), + MBEDTLS_BYTES_TO_T_UINT_8(0x89, 0x0C, 0x29, 0xA8, 0x62, 0xAE, 0xDB, 0x65), + MBEDTLS_BYTES_TO_T_UINT_8(0xD7, 0x9E, 0x0F, 0xCA, 0x87, 0x2A, 0x6F, 0x7B), + MBEDTLS_BYTES_TO_T_UINT_8(0xCE, 0xDC, 0x9B, 0x9F, 0x65, 0xD4, 0xAD, 0x27), + MBEDTLS_BYTES_TO_T_UINT_8(0xED, 0xC3, 0x08, 0x0F, 0xCF, 0x67, 0xE9, 0xF4), + MBEDTLS_BYTES_TO_T_UINT_8(0x92, 0x5C, 0xD7, 0xFF, 0x41, 0x9C, 0xCB, 0x26), +}; +static const mbedtls_mpi_uint brainpoolP512r1_T_5_X[] = { + MBEDTLS_BYTES_TO_T_UINT_8(0x37, 0x25, 0x05, 0x12, 0xAD, 0x73, 0x63, 0x90), + MBEDTLS_BYTES_TO_T_UINT_8(0xC7, 0x99, 0x07, 0x86, 0x57, 0xE7, 0x94, 0xB1), + MBEDTLS_BYTES_TO_T_UINT_8(0x00, 0x4B, 0xA5, 0xBF, 0x18, 0xA9, 0xEF, 0x6A), + MBEDTLS_BYTES_TO_T_UINT_8(0xFA, 0x4C, 0xC4, 0x09, 0xF2, 0x2F, 0x0C, 0xAA), + MBEDTLS_BYTES_TO_T_UINT_8(0x8C, 0x3A, 0x04, 0xEA, 0x89, 0x6C, 0x91, 0xB9), + MBEDTLS_BYTES_TO_T_UINT_8(0x7D, 0x6C, 0x3A, 0xE7, 0xA3, 0xEC, 0x24, 0x7B), + MBEDTLS_BYTES_TO_T_UINT_8(0x16, 0xA1, 0x26, 0x21, 0x04, 0xE3, 0xB9, 0x40), + MBEDTLS_BYTES_TO_T_UINT_8(0x53, 0x71, 0x4B, 0x7B, 0xC2, 0x89, 0xCD, 0xA2), +}; +static const mbedtls_mpi_uint brainpoolP512r1_T_5_Y[] = { + MBEDTLS_BYTES_TO_T_UINT_8(0xB7, 0xB9, 0xA8, 0x9D, 0xFD, 0x00, 0x3A, 0x1F), + MBEDTLS_BYTES_TO_T_UINT_8(0x63, 0x41, 0x6C, 0xBB, 0x5A, 0xCA, 0x1F, 0x74), + MBEDTLS_BYTES_TO_T_UINT_8(0x2A, 0xD7, 0xE2, 0x6C, 0x6B, 0xA7, 0x48, 0xC9), + MBEDTLS_BYTES_TO_T_UINT_8(0x1E, 0x19, 0xAD, 0xA7, 0xC1, 0x7E, 0x4F, 0x6E), + MBEDTLS_BYTES_TO_T_UINT_8(0xD1, 0xF7, 0x19, 0x3C, 0x06, 0x74, 0x2C, 0x3A), + MBEDTLS_BYTES_TO_T_UINT_8(0xC5, 0x23, 0x4F, 0x0C, 0x09, 0xB0, 0x80, 0x4A), + MBEDTLS_BYTES_TO_T_UINT_8(0x4E, 0x74, 0x34, 0x08, 0x44, 0x7E, 0xA3, 0xDD), + MBEDTLS_BYTES_TO_T_UINT_8(0xFB, 0xCC, 0x8D, 0x12, 0x6E, 0xE1, 0x3D, 0x0B), +}; +static const mbedtls_mpi_uint brainpoolP512r1_T_6_X[] = { + MBEDTLS_BYTES_TO_T_UINT_8(0x38, 0x18, 0xB1, 0x71, 0x02, 0x93, 0xC2, 0xA4), + MBEDTLS_BYTES_TO_T_UINT_8(0xC9, 0x89, 0x40, 0xE2, 0x1F, 0xE7, 0x5E, 0x68), + MBEDTLS_BYTES_TO_T_UINT_8(0x50, 0x8E, 0xAE, 0x89, 0x01, 0xD4, 0x0C, 0xEB), + MBEDTLS_BYTES_TO_T_UINT_8(0xAE, 0xDA, 0x58, 0x70, 0x24, 0xF2, 0xE4, 0x5F), + MBEDTLS_BYTES_TO_T_UINT_8(0x6F, 0xC7, 0x1D, 0xD6, 0x4A, 0x6F, 0x66, 0x4F), + MBEDTLS_BYTES_TO_T_UINT_8(0x92, 0x1D, 0x7E, 0x4A, 0x2C, 0xCA, 0xEC, 0x3B), + MBEDTLS_BYTES_TO_T_UINT_8(0xA1, 0x06, 0x7F, 0xA8, 0x99, 0xE4, 0xD3, 0x4E), + MBEDTLS_BYTES_TO_T_UINT_8(0x2A, 0x1D, 0x5A, 0xDF, 0x5E, 0x58, 0x36, 0x49), +}; +static const mbedtls_mpi_uint brainpoolP512r1_T_6_Y[] = { + MBEDTLS_BYTES_TO_T_UINT_8(0x9C, 0xB9, 0x32, 0x69, 0x1F, 0x72, 0x2A, 0xB3), + MBEDTLS_BYTES_TO_T_UINT_8(0x1C, 0x73, 0xE2, 0x03, 0x39, 0x35, 0xAA, 0xA8), + MBEDTLS_BYTES_TO_T_UINT_8(0xEB, 0x5E, 0x5D, 0x48, 0xEF, 0xAE, 0x30, 0xF5), + MBEDTLS_BYTES_TO_T_UINT_8(0x77, 0x7F, 0x60, 0x19, 0xAF, 0xEC, 0x9D, 0xFC), + MBEDTLS_BYTES_TO_T_UINT_8(0xCA, 0xD9, 0x19, 0xE4, 0x1B, 0x56, 0x15, 0x5F), + MBEDTLS_BYTES_TO_T_UINT_8(0xBC, 0xD7, 0x33, 0x59, 0x1F, 0x43, 0x59, 0x2C), + MBEDTLS_BYTES_TO_T_UINT_8(0xC6, 0xCE, 0xEE, 0xCA, 0xA4, 0x7F, 0x63, 0xD4), + MBEDTLS_BYTES_TO_T_UINT_8(0xBD, 0x40, 0xC0, 0xF6, 0x19, 0x89, 0x43, 0x20), +}; +static const mbedtls_mpi_uint brainpoolP512r1_T_7_X[] = { + MBEDTLS_BYTES_TO_T_UINT_8(0xEB, 0x92, 0xEA, 0x07, 0x65, 0x79, 0x86, 0xD3), + MBEDTLS_BYTES_TO_T_UINT_8(0xFF, 0xB7, 0x13, 0x75, 0xD3, 0xC5, 0x0A, 0xC9), + MBEDTLS_BYTES_TO_T_UINT_8(0x26, 0x9E, 0xFA, 0xE1, 0x1F, 0x0C, 0xF9, 0x74), + MBEDTLS_BYTES_TO_T_UINT_8(0xB4, 0x8C, 0xED, 0x5C, 0x21, 0xE9, 0x09, 0xDD), + MBEDTLS_BYTES_TO_T_UINT_8(0xF4, 0x4D, 0xD8, 0x18, 0xC4, 0xF6, 0x36, 0x39), + MBEDTLS_BYTES_TO_T_UINT_8(0xC7, 0xC9, 0xAC, 0x5C, 0xFA, 0x69, 0xA4, 0xA0), + MBEDTLS_BYTES_TO_T_UINT_8(0x6B, 0x8C, 0x94, 0x1C, 0x7B, 0x71, 0x36, 0x58), + MBEDTLS_BYTES_TO_T_UINT_8(0x7C, 0xBD, 0x46, 0xCE, 0xB7, 0x1D, 0x9C, 0x5E), +}; +static const mbedtls_mpi_uint brainpoolP512r1_T_7_Y[] = { + MBEDTLS_BYTES_TO_T_UINT_8(0xEA, 0xD6, 0x96, 0x4B, 0xA6, 0x47, 0xEB, 0xE5), + MBEDTLS_BYTES_TO_T_UINT_8(0x5F, 0xF1, 0x5F, 0x15, 0xDE, 0x99, 0x6F, 0x66), + MBEDTLS_BYTES_TO_T_UINT_8(0x21, 0xBD, 0xE5, 0x04, 0xB8, 0xE6, 0xC0, 0x0B), + MBEDTLS_BYTES_TO_T_UINT_8(0x49, 0xD3, 0xF0, 0x04, 0x00, 0xE4, 0x05, 0xDB), + MBEDTLS_BYTES_TO_T_UINT_8(0x96, 0xF3, 0x06, 0xA3, 0x1A, 0xFF, 0xEA, 0x73), + MBEDTLS_BYTES_TO_T_UINT_8(0x08, 0x32, 0xAA, 0x99, 0x33, 0x09, 0xB6, 0x34), + MBEDTLS_BYTES_TO_T_UINT_8(0x6E, 0xEF, 0xFC, 0x61, 0x10, 0x42, 0x31, 0x94), + MBEDTLS_BYTES_TO_T_UINT_8(0x34, 0xF1, 0xF4, 0x33, 0xCF, 0x28, 0x90, 0x9C), +}; +static const mbedtls_mpi_uint brainpoolP512r1_T_8_X[] = { + MBEDTLS_BYTES_TO_T_UINT_8(0x10, 0xDE, 0xF9, 0x88, 0x87, 0x7B, 0xEB, 0xC9), + MBEDTLS_BYTES_TO_T_UINT_8(0x66, 0xB8, 0xDA, 0xFA, 0xDA, 0x3D, 0xA6, 0x17), + MBEDTLS_BYTES_TO_T_UINT_8(0xA0, 0xF0, 0x62, 0x82, 0x53, 0x32, 0x55, 0x03), + MBEDTLS_BYTES_TO_T_UINT_8(0x2F, 0xA5, 0x32, 0x4A, 0x19, 0x11, 0x9C, 0x10), + MBEDTLS_BYTES_TO_T_UINT_8(0x16, 0xB3, 0x27, 0xE9, 0x75, 0x90, 0x05, 0x2D), + MBEDTLS_BYTES_TO_T_UINT_8(0x63, 0x1C, 0x90, 0x48, 0x77, 0x01, 0x85, 0x1B), + MBEDTLS_BYTES_TO_T_UINT_8(0xC7, 0xD6, 0x9B, 0x84, 0xA8, 0xD7, 0xC5, 0x28), + MBEDTLS_BYTES_TO_T_UINT_8(0xE1, 0x7A, 0xCB, 0xB3, 0x11, 0x46, 0xD7, 0x99), +}; +static const mbedtls_mpi_uint brainpoolP512r1_T_8_Y[] = { + MBEDTLS_BYTES_TO_T_UINT_8(0x8B, 0x23, 0xBF, 0x75, 0x75, 0xA1, 0x95, 0x90), + MBEDTLS_BYTES_TO_T_UINT_8(0x4B, 0x66, 0x5D, 0x34, 0x13, 0xA9, 0x03, 0xBE), + MBEDTLS_BYTES_TO_T_UINT_8(0x29, 0x80, 0x9D, 0x5F, 0xD2, 0x44, 0xE1, 0x62), + MBEDTLS_BYTES_TO_T_UINT_8(0x96, 0x5D, 0xBD, 0xA8, 0xBF, 0xB4, 0x25, 0x1F), + MBEDTLS_BYTES_TO_T_UINT_8(0x6A, 0x99, 0x1F, 0x53, 0xF1, 0x57, 0xDB, 0xE7), + MBEDTLS_BYTES_TO_T_UINT_8(0x21, 0x7C, 0xE5, 0xC5, 0x51, 0x0B, 0x4C, 0x9B), + MBEDTLS_BYTES_TO_T_UINT_8(0x6B, 0xB0, 0x1A, 0x9C, 0x16, 0xB0, 0x32, 0x1F), + MBEDTLS_BYTES_TO_T_UINT_8(0xF4, 0xE3, 0xCF, 0xDD, 0x48, 0xB4, 0x7B, 0x33), +}; +static const mbedtls_mpi_uint brainpoolP512r1_T_9_X[] = { + MBEDTLS_BYTES_TO_T_UINT_8(0xC0, 0xDD, 0x9E, 0x3C, 0x98, 0x0E, 0x77, 0x65), + MBEDTLS_BYTES_TO_T_UINT_8(0x6C, 0xAB, 0x01, 0xD3, 0x87, 0x74, 0x25, 0x4A), + MBEDTLS_BYTES_TO_T_UINT_8(0x87, 0xA3, 0xE3, 0x76, 0x43, 0x87, 0x12, 0xBD), + MBEDTLS_BYTES_TO_T_UINT_8(0x54, 0xB1, 0x3B, 0x60, 0x66, 0xEB, 0x98, 0x54), + MBEDTLS_BYTES_TO_T_UINT_8(0xD2, 0x78, 0xC8, 0xD7, 0x4E, 0x75, 0xCA, 0x69), + MBEDTLS_BYTES_TO_T_UINT_8(0x07, 0xDF, 0x71, 0x19, 0xE7, 0x07, 0x36, 0xB5), + MBEDTLS_BYTES_TO_T_UINT_8(0x6D, 0xC9, 0xA8, 0x5F, 0x91, 0xBF, 0x47, 0xB2), + MBEDTLS_BYTES_TO_T_UINT_8(0x80, 0x96, 0x58, 0x96, 0x18, 0xB6, 0xFA, 0x01), +}; +static const mbedtls_mpi_uint brainpoolP512r1_T_9_Y[] = { + MBEDTLS_BYTES_TO_T_UINT_8(0xD0, 0x2D, 0xA9, 0x9B, 0x86, 0xDB, 0x0C, 0x4C), + MBEDTLS_BYTES_TO_T_UINT_8(0xE4, 0x0B, 0x2D, 0x56, 0x4A, 0xD3, 0x93, 0x8A), + MBEDTLS_BYTES_TO_T_UINT_8(0xB5, 0x15, 0xE2, 0x65, 0x12, 0x86, 0x0E, 0xB2), + MBEDTLS_BYTES_TO_T_UINT_8(0xB4, 0x41, 0x4D, 0xC1, 0xCB, 0xE4, 0xC3, 0xD7), + MBEDTLS_BYTES_TO_T_UINT_8(0x6A, 0x53, 0x10, 0xCA, 0xA3, 0xAC, 0x83, 0x26), + MBEDTLS_BYTES_TO_T_UINT_8(0x3E, 0x01, 0x22, 0x96, 0x10, 0xAD, 0x69, 0xDB), + MBEDTLS_BYTES_TO_T_UINT_8(0x42, 0x46, 0x4E, 0xD8, 0xEA, 0xD6, 0x9D, 0xF3), + MBEDTLS_BYTES_TO_T_UINT_8(0x43, 0x2F, 0x7F, 0x62, 0x62, 0x80, 0xD0, 0x14), +}; +static const mbedtls_mpi_uint brainpoolP512r1_T_10_X[] = { + MBEDTLS_BYTES_TO_T_UINT_8(0xB2, 0xDA, 0x00, 0x63, 0x09, 0xBD, 0x6A, 0x83), + MBEDTLS_BYTES_TO_T_UINT_8(0x0F, 0xD4, 0x6E, 0x48, 0x05, 0xB7, 0xF7, 0x17), + MBEDTLS_BYTES_TO_T_UINT_8(0x14, 0x4D, 0xD7, 0x00, 0x4A, 0x15, 0x27, 0x7A), + MBEDTLS_BYTES_TO_T_UINT_8(0x3A, 0x15, 0xAA, 0x37, 0x27, 0x34, 0x18, 0x24), + MBEDTLS_BYTES_TO_T_UINT_8(0x3A, 0x20, 0x2C, 0x84, 0x1B, 0x88, 0xBA, 0x05), + MBEDTLS_BYTES_TO_T_UINT_8(0xAC, 0x09, 0xD6, 0x04, 0xA2, 0x60, 0x84, 0x72), + MBEDTLS_BYTES_TO_T_UINT_8(0xC8, 0x04, 0x94, 0x08, 0xD4, 0xED, 0x47, 0xDB), + MBEDTLS_BYTES_TO_T_UINT_8(0x8B, 0xF3, 0xE4, 0x3E, 0xB9, 0x5B, 0x35, 0x42), +}; +static const mbedtls_mpi_uint brainpoolP512r1_T_10_Y[] = { + MBEDTLS_BYTES_TO_T_UINT_8(0x5F, 0xD8, 0xB6, 0x80, 0xD6, 0xF1, 0x30, 0xDD), + MBEDTLS_BYTES_TO_T_UINT_8(0xD6, 0x14, 0xA6, 0x85, 0xEE, 0xA7, 0xD8, 0x61), + MBEDTLS_BYTES_TO_T_UINT_8(0xE4, 0x49, 0x2A, 0x1E, 0x7C, 0xE9, 0x2D, 0xEC), + MBEDTLS_BYTES_TO_T_UINT_8(0x3A, 0x87, 0x56, 0x91, 0x03, 0x77, 0x4D, 0x55), + MBEDTLS_BYTES_TO_T_UINT_8(0x0E, 0x52, 0xD4, 0xAA, 0xF7, 0xFA, 0xB0, 0xC5), + MBEDTLS_BYTES_TO_T_UINT_8(0x04, 0x5D, 0x11, 0x39, 0xB1, 0xE7, 0x76, 0xAD), + MBEDTLS_BYTES_TO_T_UINT_8(0xD6, 0x13, 0xBC, 0x37, 0x5D, 0x74, 0xCD, 0xC2), + MBEDTLS_BYTES_TO_T_UINT_8(0xC9, 0x48, 0x14, 0x23, 0x30, 0xF8, 0x46, 0x37), +}; +static const mbedtls_mpi_uint brainpoolP512r1_T_11_X[] = { + MBEDTLS_BYTES_TO_T_UINT_8(0xAC, 0x27, 0xB0, 0xD9, 0xB2, 0x74, 0xB4, 0xC0), + MBEDTLS_BYTES_TO_T_UINT_8(0xEA, 0xA6, 0xB9, 0x6F, 0x9F, 0x64, 0x36, 0x92), + MBEDTLS_BYTES_TO_T_UINT_8(0x2E, 0x2B, 0x78, 0x40, 0x05, 0x2B, 0x7B, 0xA9), + MBEDTLS_BYTES_TO_T_UINT_8(0xB3, 0x68, 0x3A, 0xB6, 0x4A, 0xE2, 0xDB, 0xB8), + MBEDTLS_BYTES_TO_T_UINT_8(0x1E, 0x33, 0xD7, 0x34, 0x8B, 0x25, 0x45, 0xEF), + MBEDTLS_BYTES_TO_T_UINT_8(0x89, 0xCE, 0xA8, 0xC9, 0x01, 0xFB, 0x0E, 0x7B), + MBEDTLS_BYTES_TO_T_UINT_8(0xE2, 0xF9, 0x51, 0x4C, 0x12, 0x9F, 0x60, 0xE4), + MBEDTLS_BYTES_TO_T_UINT_8(0x67, 0x85, 0xBD, 0x30, 0x37, 0x84, 0x39, 0x44), +}; +static const mbedtls_mpi_uint brainpoolP512r1_T_11_Y[] = { + MBEDTLS_BYTES_TO_T_UINT_8(0x26, 0x33, 0xAF, 0x2E, 0xB8, 0x2E, 0xCC, 0x3C), + MBEDTLS_BYTES_TO_T_UINT_8(0xA4, 0xB1, 0x73, 0x59, 0x4E, 0x0C, 0x09, 0x4A), + MBEDTLS_BYTES_TO_T_UINT_8(0x8A, 0x24, 0x89, 0x81, 0x12, 0xFF, 0xBB, 0x6E), + MBEDTLS_BYTES_TO_T_UINT_8(0x71, 0x37, 0x1A, 0x66, 0xEE, 0xED, 0xB6, 0x9B), + MBEDTLS_BYTES_TO_T_UINT_8(0x16, 0xBD, 0x04, 0x20, 0x5D, 0xFB, 0xBF, 0x95), + MBEDTLS_BYTES_TO_T_UINT_8(0xA0, 0xF8, 0x34, 0xA3, 0xFF, 0x45, 0xDE, 0x92), + MBEDTLS_BYTES_TO_T_UINT_8(0x9B, 0x18, 0x73, 0xF1, 0x32, 0x25, 0x58, 0xEB), + MBEDTLS_BYTES_TO_T_UINT_8(0x63, 0xC1, 0x14, 0xE3, 0x9E, 0x40, 0x0F, 0x12), +}; +static const mbedtls_mpi_uint brainpoolP512r1_T_12_X[] = { + MBEDTLS_BYTES_TO_T_UINT_8(0x61, 0x07, 0x9D, 0x9C, 0x00, 0xF7, 0x56, 0x19), + MBEDTLS_BYTES_TO_T_UINT_8(0xFB, 0xBA, 0x87, 0xF9, 0x15, 0x0C, 0x66, 0x5D), + MBEDTLS_BYTES_TO_T_UINT_8(0x7E, 0x1F, 0xC1, 0x28, 0xB0, 0x47, 0x0D, 0xF5), + MBEDTLS_BYTES_TO_T_UINT_8(0x96, 0xCA, 0x27, 0xEE, 0x4B, 0x23, 0x2B, 0x89), + MBEDTLS_BYTES_TO_T_UINT_8(0x7E, 0xB5, 0x68, 0xC8, 0x17, 0x5D, 0xC3, 0xAA), + MBEDTLS_BYTES_TO_T_UINT_8(0x17, 0x02, 0x08, 0xEE, 0x20, 0x9D, 0xEA, 0x64), + MBEDTLS_BYTES_TO_T_UINT_8(0xA7, 0x14, 0x50, 0xD4, 0x7D, 0x5F, 0xCF, 0xA0), + MBEDTLS_BYTES_TO_T_UINT_8(0xD5, 0xFA, 0xF8, 0xA7, 0xC6, 0xDC, 0x14, 0x8C), +}; +static const mbedtls_mpi_uint brainpoolP512r1_T_12_Y[] = { + MBEDTLS_BYTES_TO_T_UINT_8(0x76, 0xBD, 0x0A, 0x1A, 0x18, 0x98, 0xDC, 0xB0), + MBEDTLS_BYTES_TO_T_UINT_8(0x63, 0x63, 0x02, 0xB7, 0xD5, 0x5B, 0x5A, 0xC6), + MBEDTLS_BYTES_TO_T_UINT_8(0x51, 0xB1, 0xD7, 0x4B, 0x15, 0x39, 0x61, 0x5D), + MBEDTLS_BYTES_TO_T_UINT_8(0x5C, 0x32, 0xE1, 0x9E, 0x70, 0x1B, 0xCE, 0x51), + MBEDTLS_BYTES_TO_T_UINT_8(0x64, 0xD8, 0x18, 0x83, 0x52, 0x9B, 0x6D, 0xA2), + MBEDTLS_BYTES_TO_T_UINT_8(0xA4, 0x55, 0x56, 0x19, 0x34, 0xA4, 0xEA, 0xFC), + MBEDTLS_BYTES_TO_T_UINT_8(0x30, 0xA9, 0x55, 0x80, 0xE3, 0x15, 0x36, 0x8B), + MBEDTLS_BYTES_TO_T_UINT_8(0xBB, 0x06, 0xC8, 0x1D, 0x17, 0x0D, 0xAD, 0x16), +}; +static const mbedtls_mpi_uint brainpoolP512r1_T_13_X[] = { + MBEDTLS_BYTES_TO_T_UINT_8(0x20, 0xD6, 0xF0, 0xCC, 0xF3, 0x63, 0x53, 0xD2), + MBEDTLS_BYTES_TO_T_UINT_8(0x27, 0x5A, 0xDC, 0x46, 0xBD, 0x0D, 0xAD, 0x96), + MBEDTLS_BYTES_TO_T_UINT_8(0x21, 0x2F, 0x11, 0x60, 0x15, 0x51, 0x4A, 0xEA), + MBEDTLS_BYTES_TO_T_UINT_8(0x33, 0xE3, 0x93, 0x38, 0xD5, 0x83, 0xAA, 0x0D), + MBEDTLS_BYTES_TO_T_UINT_8(0x90, 0xA6, 0xCC, 0xB1, 0xFD, 0xBB, 0x1A, 0x0F), + MBEDTLS_BYTES_TO_T_UINT_8(0x3B, 0x54, 0xC8, 0x54, 0x6F, 0x79, 0x1A, 0x59), + MBEDTLS_BYTES_TO_T_UINT_8(0x3F, 0x4A, 0xDA, 0x28, 0x92, 0x97, 0x9D, 0x7F), + MBEDTLS_BYTES_TO_T_UINT_8(0xD6, 0x4B, 0xDB, 0xC7, 0x52, 0xC5, 0x66, 0x34), +}; +static const mbedtls_mpi_uint brainpoolP512r1_T_13_Y[] = { + MBEDTLS_BYTES_TO_T_UINT_8(0x05, 0x7E, 0x92, 0x53, 0x30, 0x93, 0xFD, 0xFF), + MBEDTLS_BYTES_TO_T_UINT_8(0xA0, 0x16, 0x6A, 0xB1, 0x91, 0x0A, 0xB4, 0x52), + MBEDTLS_BYTES_TO_T_UINT_8(0x6D, 0x9D, 0x40, 0x3F, 0xE3, 0xF1, 0x01, 0x46), + MBEDTLS_BYTES_TO_T_UINT_8(0x13, 0x0E, 0xD8, 0xED, 0x11, 0x8E, 0x4C, 0xED), + MBEDTLS_BYTES_TO_T_UINT_8(0x86, 0x4A, 0x1B, 0x88, 0xDF, 0x8D, 0x29, 0xE7), + MBEDTLS_BYTES_TO_T_UINT_8(0x97, 0x23, 0x21, 0x11, 0xAB, 0x77, 0x81, 0x62), + MBEDTLS_BYTES_TO_T_UINT_8(0x0B, 0xAF, 0x11, 0xFA, 0xBA, 0x40, 0x63, 0xE7), + MBEDTLS_BYTES_TO_T_UINT_8(0x2B, 0x6F, 0x8D, 0x80, 0xDF, 0x67, 0xF5, 0x44), +}; +static const mbedtls_mpi_uint brainpoolP512r1_T_14_X[] = { + MBEDTLS_BYTES_TO_T_UINT_8(0xB2, 0x8B, 0xB7, 0x08, 0xF4, 0xD7, 0x2D, 0xA8), + MBEDTLS_BYTES_TO_T_UINT_8(0xC7, 0x2B, 0x30, 0x02, 0x45, 0x71, 0x08, 0x49), + MBEDTLS_BYTES_TO_T_UINT_8(0x97, 0x3A, 0xCA, 0x50, 0xF6, 0xC2, 0x19, 0x8C), + MBEDTLS_BYTES_TO_T_UINT_8(0x17, 0xB9, 0x9B, 0x3E, 0x73, 0x95, 0x1D, 0x49), + MBEDTLS_BYTES_TO_T_UINT_8(0xB6, 0x60, 0x59, 0x48, 0xCB, 0xD8, 0xD6, 0xAA), + MBEDTLS_BYTES_TO_T_UINT_8(0xF0, 0xB9, 0x6C, 0x89, 0xAB, 0x99, 0xA8, 0xF8), + MBEDTLS_BYTES_TO_T_UINT_8(0xEF, 0xA1, 0x8B, 0x4E, 0x06, 0x19, 0xEC, 0x99), + MBEDTLS_BYTES_TO_T_UINT_8(0x70, 0x95, 0x04, 0xCF, 0xD5, 0x94, 0xB3, 0x02), +}; +static const mbedtls_mpi_uint brainpoolP512r1_T_14_Y[] = { + MBEDTLS_BYTES_TO_T_UINT_8(0x29, 0x35, 0x93, 0x7C, 0xB3, 0xB8, 0x9E, 0x1B), + MBEDTLS_BYTES_TO_T_UINT_8(0xC4, 0x45, 0x5C, 0x7E, 0xBF, 0x75, 0x81, 0x0F), + MBEDTLS_BYTES_TO_T_UINT_8(0xDC, 0xE8, 0x24, 0xDF, 0xEC, 0x2F, 0x7D, 0xB9), + MBEDTLS_BYTES_TO_T_UINT_8(0xF2, 0x8B, 0xD5, 0x6A, 0x9B, 0xA0, 0xE0, 0x4F), + MBEDTLS_BYTES_TO_T_UINT_8(0x32, 0xE3, 0x27, 0x82, 0xDE, 0xDD, 0xCA, 0x4B), + MBEDTLS_BYTES_TO_T_UINT_8(0xA7, 0x57, 0x56, 0x46, 0x05, 0x06, 0x01, 0x2E), + MBEDTLS_BYTES_TO_T_UINT_8(0x74, 0x35, 0xA7, 0x47, 0xE2, 0x6B, 0x2C, 0x4F), + MBEDTLS_BYTES_TO_T_UINT_8(0x38, 0x9D, 0x4C, 0xEC, 0x1F, 0x11, 0x75, 0x2B), +}; +static const mbedtls_mpi_uint brainpoolP512r1_T_15_X[] = { + MBEDTLS_BYTES_TO_T_UINT_8(0xAC, 0xAA, 0x41, 0xC1, 0xE9, 0x0E, 0xE9, 0xAA), + MBEDTLS_BYTES_TO_T_UINT_8(0x0A, 0xCF, 0x9C, 0x4B, 0xE8, 0xED, 0x0A, 0x49), + MBEDTLS_BYTES_TO_T_UINT_8(0x3D, 0x73, 0xCA, 0x0C, 0x46, 0x0A, 0x9C, 0xE4), + MBEDTLS_BYTES_TO_T_UINT_8(0x99, 0xE1, 0x9E, 0xBC, 0xFE, 0x44, 0x63, 0x6D), + MBEDTLS_BYTES_TO_T_UINT_8(0x31, 0x43, 0x71, 0xEE, 0xF8, 0xC1, 0x8C, 0x5C), + MBEDTLS_BYTES_TO_T_UINT_8(0x6A, 0x4B, 0xF0, 0x69, 0x25, 0xBD, 0x71, 0x1A), + MBEDTLS_BYTES_TO_T_UINT_8(0xFD, 0x9A, 0xFE, 0x82, 0xE7, 0xC1, 0xC1, 0xEE), + MBEDTLS_BYTES_TO_T_UINT_8(0xFC, 0x5A, 0x6E, 0x5E, 0x97, 0x6A, 0x35, 0x8D), +}; +static const mbedtls_mpi_uint brainpoolP512r1_T_15_Y[] = { + MBEDTLS_BYTES_TO_T_UINT_8(0xA2, 0x18, 0x6C, 0x7E, 0xB8, 0x9E, 0x57, 0x32), + MBEDTLS_BYTES_TO_T_UINT_8(0x35, 0xB9, 0xC1, 0xD0, 0xFE, 0x78, 0xFB, 0x32), + MBEDTLS_BYTES_TO_T_UINT_8(0x7C, 0x08, 0xAE, 0x46, 0x34, 0xEA, 0x7A, 0x7F), + MBEDTLS_BYTES_TO_T_UINT_8(0xE8, 0x1C, 0x56, 0xA9, 0x18, 0x37, 0xD4, 0x9E), + MBEDTLS_BYTES_TO_T_UINT_8(0x28, 0x63, 0xE9, 0x0A, 0xB6, 0x38, 0x3C, 0xC1), + MBEDTLS_BYTES_TO_T_UINT_8(0x3E, 0x4F, 0xA4, 0x6E, 0x85, 0x31, 0x23, 0x52), + MBEDTLS_BYTES_TO_T_UINT_8(0x0D, 0xAD, 0xC4, 0xC3, 0xB1, 0x4B, 0x1C, 0x82), + MBEDTLS_BYTES_TO_T_UINT_8(0x30, 0x56, 0x4A, 0x38, 0xB3, 0x6B, 0x6F, 0x2C), +}; +static const mbedtls_mpi_uint brainpoolP512r1_T_16_X[] = { + MBEDTLS_BYTES_TO_T_UINT_8(0x67, 0xC7, 0x19, 0xDE, 0x21, 0xED, 0x89, 0xD0), + MBEDTLS_BYTES_TO_T_UINT_8(0x2F, 0xBE, 0xA6, 0xAE, 0xEB, 0x9D, 0xA7, 0x2A), + MBEDTLS_BYTES_TO_T_UINT_8(0x04, 0x0E, 0x13, 0x1E, 0x86, 0x57, 0xC3, 0x3B), + MBEDTLS_BYTES_TO_T_UINT_8(0x1F, 0x4B, 0x30, 0x46, 0x52, 0xC1, 0xEC, 0x52), + MBEDTLS_BYTES_TO_T_UINT_8(0x6E, 0xD5, 0x44, 0x31, 0x96, 0x3B, 0x26, 0x27), + MBEDTLS_BYTES_TO_T_UINT_8(0x77, 0x68, 0xA8, 0x67, 0x78, 0x39, 0xE8, 0x68), + MBEDTLS_BYTES_TO_T_UINT_8(0x8E, 0x78, 0xB7, 0xDD, 0xF2, 0x58, 0xB6, 0x3D), + MBEDTLS_BYTES_TO_T_UINT_8(0x81, 0x3C, 0xB3, 0x26, 0xC4, 0x2C, 0x8C, 0xA5), +}; +static const mbedtls_mpi_uint brainpoolP512r1_T_16_Y[] = { + MBEDTLS_BYTES_TO_T_UINT_8(0xB9, 0x24, 0xE5, 0x73, 0xEE, 0x9A, 0x02, 0xA9), + MBEDTLS_BYTES_TO_T_UINT_8(0xD9, 0x6A, 0x65, 0x60, 0xF3, 0x62, 0xE3, 0xE9), + MBEDTLS_BYTES_TO_T_UINT_8(0xFB, 0x07, 0x84, 0xE6, 0x3B, 0x46, 0x65, 0x9F), + MBEDTLS_BYTES_TO_T_UINT_8(0xE1, 0x8F, 0x0C, 0xB0, 0xE1, 0x04, 0x82, 0x9D), + MBEDTLS_BYTES_TO_T_UINT_8(0xEB, 0x13, 0xBF, 0x3D, 0xA0, 0x48, 0xA2, 0x74), + MBEDTLS_BYTES_TO_T_UINT_8(0x08, 0x26, 0x76, 0x74, 0xAB, 0x0B, 0x29, 0xE8), + MBEDTLS_BYTES_TO_T_UINT_8(0x30, 0x6E, 0x5F, 0x03, 0x34, 0x7C, 0x38, 0xCE), + MBEDTLS_BYTES_TO_T_UINT_8(0x4D, 0x72, 0xF9, 0x3B, 0x3C, 0xA4, 0xBC, 0x7C), +}; +static const mbedtls_mpi_uint brainpoolP512r1_T_17_X[] = { + MBEDTLS_BYTES_TO_T_UINT_8(0x5C, 0xCE, 0x18, 0x80, 0xB8, 0x24, 0x45, 0x81), + MBEDTLS_BYTES_TO_T_UINT_8(0xF1, 0x09, 0x03, 0xB8, 0x06, 0x64, 0xF7, 0xEC), + MBEDTLS_BYTES_TO_T_UINT_8(0xF1, 0x26, 0xB1, 0x10, 0x6D, 0x71, 0x12, 0x2E), + MBEDTLS_BYTES_TO_T_UINT_8(0xAD, 0x12, 0xC6, 0x6E, 0x1E, 0x6A, 0xC3, 0x80), + MBEDTLS_BYTES_TO_T_UINT_8(0xE5, 0xD3, 0x0A, 0xDE, 0xD8, 0x6B, 0x04, 0x5C), + MBEDTLS_BYTES_TO_T_UINT_8(0x96, 0x87, 0x5B, 0xAE, 0xDB, 0x3C, 0xC0, 0xC5), + MBEDTLS_BYTES_TO_T_UINT_8(0x8E, 0xF5, 0xF9, 0xC1, 0x9A, 0x89, 0xBB, 0x7E), + MBEDTLS_BYTES_TO_T_UINT_8(0xED, 0x69, 0x72, 0x8B, 0xAE, 0x32, 0x13, 0x11), +}; +static const mbedtls_mpi_uint brainpoolP512r1_T_17_Y[] = { + MBEDTLS_BYTES_TO_T_UINT_8(0xF9, 0x16, 0x07, 0x50, 0xFA, 0x4C, 0xCF, 0xE8), + MBEDTLS_BYTES_TO_T_UINT_8(0xF8, 0x50, 0x21, 0xE9, 0xDE, 0xEC, 0x7E, 0xDF), + MBEDTLS_BYTES_TO_T_UINT_8(0x7C, 0x2F, 0xE8, 0x83, 0x30, 0x0B, 0x65, 0x0E), + MBEDTLS_BYTES_TO_T_UINT_8(0xA5, 0x0B, 0x99, 0xAC, 0xC9, 0xBA, 0x6C, 0x2A), + MBEDTLS_BYTES_TO_T_UINT_8(0xA7, 0x59, 0x5A, 0x0D, 0x7B, 0x9E, 0x08, 0xAD), + MBEDTLS_BYTES_TO_T_UINT_8(0x34, 0x91, 0xB2, 0xDC, 0x90, 0xCE, 0x67, 0xED), + MBEDTLS_BYTES_TO_T_UINT_8(0xE3, 0x93, 0x60, 0x0C, 0xD7, 0x1F, 0x2F, 0x17), + MBEDTLS_BYTES_TO_T_UINT_8(0x19, 0x7F, 0x9D, 0x40, 0xF8, 0x78, 0x7A, 0x54), +}; +static const mbedtls_mpi_uint brainpoolP512r1_T_18_X[] = { + MBEDTLS_BYTES_TO_T_UINT_8(0x13, 0x22, 0x95, 0xE8, 0xEF, 0x31, 0x57, 0x35), + MBEDTLS_BYTES_TO_T_UINT_8(0x2D, 0x88, 0x53, 0xFE, 0xAF, 0x7C, 0x47, 0x14), + MBEDTLS_BYTES_TO_T_UINT_8(0x0E, 0xCE, 0xCC, 0x79, 0xE8, 0x9F, 0x8C, 0xC4), + MBEDTLS_BYTES_TO_T_UINT_8(0xDB, 0x16, 0xDD, 0x77, 0x6E, 0x8A, 0x73, 0x97), + MBEDTLS_BYTES_TO_T_UINT_8(0xC0, 0x07, 0x97, 0x21, 0x3B, 0xF8, 0x5F, 0xA8), + MBEDTLS_BYTES_TO_T_UINT_8(0xC6, 0xB5, 0xD2, 0x81, 0x84, 0xF0, 0xE7, 0x9F), + MBEDTLS_BYTES_TO_T_UINT_8(0xCB, 0x8F, 0x75, 0x09, 0x6A, 0x0E, 0x53, 0xAD), + MBEDTLS_BYTES_TO_T_UINT_8(0xE6, 0x4F, 0x70, 0x97, 0xC7, 0xAC, 0x7D, 0x3F), +}; +static const mbedtls_mpi_uint brainpoolP512r1_T_18_Y[] = { + MBEDTLS_BYTES_TO_T_UINT_8(0xF9, 0x3C, 0x6A, 0xB4, 0x10, 0xA9, 0xC8, 0x1D), + MBEDTLS_BYTES_TO_T_UINT_8(0xEE, 0xC5, 0xD6, 0x69, 0x16, 0xB8, 0xAC, 0x25), + MBEDTLS_BYTES_TO_T_UINT_8(0xAC, 0x44, 0xDC, 0xEB, 0x48, 0x54, 0x5D, 0x5F), + MBEDTLS_BYTES_TO_T_UINT_8(0x6F, 0x48, 0x9B, 0xD7, 0x72, 0x69, 0xA4, 0x8A), + MBEDTLS_BYTES_TO_T_UINT_8(0xB4, 0x0D, 0x36, 0x9A, 0x66, 0x0B, 0xEC, 0x24), + MBEDTLS_BYTES_TO_T_UINT_8(0xBE, 0xC6, 0xD4, 0xB6, 0x60, 0xE5, 0xC3, 0x3A), + MBEDTLS_BYTES_TO_T_UINT_8(0xBA, 0x29, 0x42, 0xE0, 0x9D, 0xFD, 0x7C, 0x3E), + MBEDTLS_BYTES_TO_T_UINT_8(0x43, 0x10, 0xBA, 0x55, 0xBC, 0x3B, 0x38, 0x5D), +}; +static const mbedtls_mpi_uint brainpoolP512r1_T_19_X[] = { + MBEDTLS_BYTES_TO_T_UINT_8(0x25, 0x66, 0xFA, 0x05, 0x73, 0x03, 0x1B, 0x69), + MBEDTLS_BYTES_TO_T_UINT_8(0x11, 0xA4, 0x66, 0x12, 0x96, 0x7B, 0x02, 0x4C), + MBEDTLS_BYTES_TO_T_UINT_8(0x44, 0xB5, 0xDE, 0x6D, 0x98, 0xD1, 0xD5, 0xA8), + MBEDTLS_BYTES_TO_T_UINT_8(0xE2, 0xF5, 0x44, 0xB8, 0x8E, 0xF6, 0x8C, 0x05), + MBEDTLS_BYTES_TO_T_UINT_8(0x68, 0x15, 0x2B, 0x72, 0xBC, 0x49, 0xE5, 0xDF), + MBEDTLS_BYTES_TO_T_UINT_8(0x6C, 0x44, 0xD7, 0xDF, 0x8F, 0xEB, 0x8D, 0x80), + MBEDTLS_BYTES_TO_T_UINT_8(0x05, 0x64, 0x88, 0xAA, 0xB7, 0xE4, 0x70, 0x1D), + MBEDTLS_BYTES_TO_T_UINT_8(0x9C, 0x14, 0xBB, 0xE9, 0x9B, 0xB9, 0x65, 0x5D), +}; +static const mbedtls_mpi_uint brainpoolP512r1_T_19_Y[] = { + MBEDTLS_BYTES_TO_T_UINT_8(0x66, 0x8E, 0x88, 0xF5, 0xF1, 0xC1, 0x89, 0xA2), + MBEDTLS_BYTES_TO_T_UINT_8(0x16, 0x30, 0x53, 0xE6, 0xFB, 0x2D, 0x82, 0xB4), + MBEDTLS_BYTES_TO_T_UINT_8(0xA7, 0xE4, 0xFF, 0xBA, 0x31, 0x79, 0xAB, 0xC2), + MBEDTLS_BYTES_TO_T_UINT_8(0x45, 0x09, 0xF7, 0xB7, 0x09, 0x78, 0x4C, 0x90), + MBEDTLS_BYTES_TO_T_UINT_8(0x10, 0xAE, 0xC2, 0x44, 0xDC, 0x17, 0x78, 0x47), + MBEDTLS_BYTES_TO_T_UINT_8(0xC7, 0xD4, 0x17, 0x43, 0x19, 0x74, 0x9E, 0x23), + MBEDTLS_BYTES_TO_T_UINT_8(0x15, 0x64, 0x3B, 0x73, 0xA2, 0x99, 0x27, 0x76), + MBEDTLS_BYTES_TO_T_UINT_8(0x05, 0x74, 0x36, 0x5F, 0xD3, 0x14, 0xB1, 0x31), +}; +static const mbedtls_mpi_uint brainpoolP512r1_T_20_X[] = { + MBEDTLS_BYTES_TO_T_UINT_8(0xAC, 0x07, 0xAB, 0xFD, 0x9B, 0x03, 0xC5, 0xD5), + MBEDTLS_BYTES_TO_T_UINT_8(0xC7, 0xBE, 0xB0, 0x1D, 0xF2, 0x0C, 0x73, 0x73), + MBEDTLS_BYTES_TO_T_UINT_8(0x99, 0xE7, 0x7B, 0x87, 0xD3, 0x34, 0xFD, 0xE2), + MBEDTLS_BYTES_TO_T_UINT_8(0x9A, 0x25, 0x3D, 0xC7, 0x36, 0x83, 0x53, 0xDC), + MBEDTLS_BYTES_TO_T_UINT_8(0x22, 0x7C, 0xCF, 0x63, 0x55, 0x12, 0x11, 0xB0), + MBEDTLS_BYTES_TO_T_UINT_8(0xC0, 0x34, 0x4D, 0x27, 0x92, 0xAC, 0x18, 0x16), + MBEDTLS_BYTES_TO_T_UINT_8(0x98, 0x42, 0x61, 0x9D, 0x2E, 0xFF, 0x13, 0x16), + MBEDTLS_BYTES_TO_T_UINT_8(0xF4, 0xDE, 0x92, 0x65, 0x57, 0x0D, 0xBC, 0x0A), +}; +static const mbedtls_mpi_uint brainpoolP512r1_T_20_Y[] = { + MBEDTLS_BYTES_TO_T_UINT_8(0xEF, 0x7B, 0x6E, 0xC6, 0x2A, 0x21, 0x74, 0x0A), + MBEDTLS_BYTES_TO_T_UINT_8(0x37, 0xA7, 0x53, 0x4D, 0x29, 0x36, 0xEF, 0xE5), + MBEDTLS_BYTES_TO_T_UINT_8(0xE1, 0xD6, 0x41, 0xC7, 0x99, 0xAD, 0x50, 0x53), + MBEDTLS_BYTES_TO_T_UINT_8(0x99, 0xAC, 0x41, 0x9F, 0xFB, 0x4C, 0x86, 0xF1), + MBEDTLS_BYTES_TO_T_UINT_8(0x8B, 0xBB, 0xE6, 0x25, 0x28, 0xAA, 0xEB, 0x1E), + MBEDTLS_BYTES_TO_T_UINT_8(0x92, 0x04, 0xA2, 0xC3, 0xAA, 0x08, 0x8A, 0xCC), + MBEDTLS_BYTES_TO_T_UINT_8(0x5A, 0x2B, 0x5B, 0xE2, 0x8D, 0x76, 0xEA, 0x34), + MBEDTLS_BYTES_TO_T_UINT_8(0xB3, 0x33, 0xD2, 0x21, 0x4D, 0x62, 0xE3, 0x8E), +}; +static const mbedtls_mpi_uint brainpoolP512r1_T_21_X[] = { + MBEDTLS_BYTES_TO_T_UINT_8(0xF6, 0x06, 0x8B, 0x2B, 0xC2, 0xC4, 0xB1, 0xD2), + MBEDTLS_BYTES_TO_T_UINT_8(0xFA, 0xF5, 0xA1, 0xC0, 0x03, 0x6A, 0x29, 0x12), + MBEDTLS_BYTES_TO_T_UINT_8(0xF5, 0xA9, 0xEF, 0x55, 0xB6, 0x1A, 0x9F, 0x6B), + MBEDTLS_BYTES_TO_T_UINT_8(0x9B, 0x54, 0x32, 0xBE, 0x06, 0x43, 0xB5, 0xFD), + MBEDTLS_BYTES_TO_T_UINT_8(0xF7, 0xD6, 0xD9, 0x20, 0x89, 0xBE, 0xD4, 0x1B), + MBEDTLS_BYTES_TO_T_UINT_8(0xE8, 0x26, 0x95, 0x10, 0xCE, 0xB4, 0x88, 0x79), + MBEDTLS_BYTES_TO_T_UINT_8(0xE6, 0xA6, 0x27, 0xAC, 0x32, 0xBA, 0xBD, 0xC7), + MBEDTLS_BYTES_TO_T_UINT_8(0xA3, 0xA6, 0xAE, 0x9C, 0x7B, 0xBE, 0xA1, 0x63), +}; +static const mbedtls_mpi_uint brainpoolP512r1_T_21_Y[] = { + MBEDTLS_BYTES_TO_T_UINT_8(0x8B, 0xCD, 0x4D, 0x3D, 0xDF, 0x96, 0xBB, 0x7D), + MBEDTLS_BYTES_TO_T_UINT_8(0x77, 0xA7, 0x11, 0x06, 0xCC, 0x0E, 0x31, 0x81), + MBEDTLS_BYTES_TO_T_UINT_8(0x20, 0xE4, 0xF4, 0xAD, 0x7B, 0x5F, 0xF1, 0xEF), + MBEDTLS_BYTES_TO_T_UINT_8(0xE4, 0x54, 0xBE, 0xF4, 0x8A, 0x03, 0x47, 0xDF), + MBEDTLS_BYTES_TO_T_UINT_8(0xB4, 0x53, 0x00, 0x7F, 0xB0, 0x8A, 0x68, 0xA6), + MBEDTLS_BYTES_TO_T_UINT_8(0xA0, 0x16, 0xB1, 0x73, 0x6F, 0x5B, 0x0E, 0xC3), + MBEDTLS_BYTES_TO_T_UINT_8(0x2A, 0x32, 0xE3, 0x43, 0x64, 0x75, 0xFB, 0xFB), + MBEDTLS_BYTES_TO_T_UINT_8(0xA0, 0x18, 0x55, 0x8A, 0x4E, 0x6E, 0x35, 0x54), +}; +static const mbedtls_mpi_uint brainpoolP512r1_T_22_X[] = { + MBEDTLS_BYTES_TO_T_UINT_8(0x80, 0x97, 0x15, 0x1E, 0xCB, 0xF2, 0x9C, 0xA5), + MBEDTLS_BYTES_TO_T_UINT_8(0x2B, 0xD1, 0xBB, 0xF3, 0x70, 0xAD, 0x13, 0xAD), + MBEDTLS_BYTES_TO_T_UINT_8(0xD8, 0x96, 0xA4, 0xC5, 0x5E, 0xDA, 0xD5, 0x57), + MBEDTLS_BYTES_TO_T_UINT_8(0x07, 0x81, 0xE9, 0x65, 0x66, 0x76, 0x47, 0x45), + MBEDTLS_BYTES_TO_T_UINT_8(0xC9, 0x35, 0x87, 0x06, 0x73, 0xCF, 0x34, 0xD2), + MBEDTLS_BYTES_TO_T_UINT_8(0x5A, 0x81, 0x15, 0x42, 0xA2, 0x79, 0x5B, 0x42), + MBEDTLS_BYTES_TO_T_UINT_8(0x08, 0xA2, 0x7D, 0x09, 0x14, 0x64, 0xC6, 0xAE), + MBEDTLS_BYTES_TO_T_UINT_8(0x5E, 0x6D, 0xC4, 0xED, 0xF1, 0xD6, 0xE9, 0x24), +}; +static const mbedtls_mpi_uint brainpoolP512r1_T_22_Y[] = { + MBEDTLS_BYTES_TO_T_UINT_8(0xB4, 0xD5, 0xBB, 0x25, 0xA3, 0xDD, 0xA3, 0x88), + MBEDTLS_BYTES_TO_T_UINT_8(0x46, 0xF2, 0x68, 0x67, 0x39, 0x8F, 0x73, 0x93), + MBEDTLS_BYTES_TO_T_UINT_8(0xF0, 0x76, 0x28, 0x89, 0xAD, 0x32, 0xE0, 0xDF), + MBEDTLS_BYTES_TO_T_UINT_8(0xF8, 0x90, 0xCC, 0x57, 0x58, 0xAA, 0xC9, 0x75), + MBEDTLS_BYTES_TO_T_UINT_8(0x5E, 0xD7, 0x43, 0xD2, 0xCE, 0x5E, 0xA0, 0x08), + MBEDTLS_BYTES_TO_T_UINT_8(0x33, 0xB0, 0xB8, 0xA4, 0x9E, 0x96, 0x26, 0x86), + MBEDTLS_BYTES_TO_T_UINT_8(0x94, 0x61, 0x1D, 0xF3, 0x65, 0x5E, 0x60, 0xCA), + MBEDTLS_BYTES_TO_T_UINT_8(0xC7, 0x1E, 0x65, 0xED, 0xCF, 0x07, 0x60, 0x20), +}; +static const mbedtls_mpi_uint brainpoolP512r1_T_23_X[] = { + MBEDTLS_BYTES_TO_T_UINT_8(0xA4, 0x30, 0x17, 0x8A, 0x91, 0x88, 0x0A, 0xA4), + MBEDTLS_BYTES_TO_T_UINT_8(0x05, 0x7D, 0x18, 0xA4, 0xAC, 0x59, 0xFC, 0x5F), + MBEDTLS_BYTES_TO_T_UINT_8(0xA4, 0x31, 0x8B, 0x25, 0x65, 0x39, 0x9A, 0xDC), + MBEDTLS_BYTES_TO_T_UINT_8(0x15, 0x16, 0x4B, 0x68, 0xBA, 0x59, 0x13, 0x2F), + MBEDTLS_BYTES_TO_T_UINT_8(0x8D, 0xFD, 0xD3, 0xC5, 0x56, 0xC9, 0x8C, 0x5E), + MBEDTLS_BYTES_TO_T_UINT_8(0xBC, 0xC6, 0x9F, 0xF4, 0xE6, 0xF7, 0xB4, 0x01), + MBEDTLS_BYTES_TO_T_UINT_8(0x2D, 0x7C, 0x03, 0x00, 0x26, 0x9F, 0xD8, 0x7B), + MBEDTLS_BYTES_TO_T_UINT_8(0x24, 0x1D, 0x6E, 0x00, 0xB9, 0x00, 0x6E, 0x93), +}; +static const mbedtls_mpi_uint brainpoolP512r1_T_23_Y[] = { + MBEDTLS_BYTES_TO_T_UINT_8(0x75, 0x63, 0xDA, 0x03, 0x2B, 0xD5, 0x0B, 0xFE), + MBEDTLS_BYTES_TO_T_UINT_8(0x46, 0xFC, 0xE2, 0xC8, 0x47, 0xF0, 0xAE, 0xF2), + MBEDTLS_BYTES_TO_T_UINT_8(0x51, 0x4C, 0xF7, 0x50, 0x0C, 0x48, 0x06, 0x2A), + MBEDTLS_BYTES_TO_T_UINT_8(0xDF, 0x2B, 0x32, 0x98, 0x0E, 0x7E, 0x61, 0x41), + MBEDTLS_BYTES_TO_T_UINT_8(0x5D, 0x02, 0x27, 0xFE, 0x75, 0x86, 0xDF, 0x24), + MBEDTLS_BYTES_TO_T_UINT_8(0x2B, 0x30, 0xB1, 0x22, 0x32, 0x1B, 0xFE, 0x24), + MBEDTLS_BYTES_TO_T_UINT_8(0xC2, 0x27, 0xF7, 0x78, 0x6F, 0xD7, 0xFD, 0xE4), + MBEDTLS_BYTES_TO_T_UINT_8(0xA0, 0x78, 0xCC, 0xEA, 0xC0, 0x50, 0x24, 0x44), +}; +static const mbedtls_mpi_uint brainpoolP512r1_T_24_X[] = { + MBEDTLS_BYTES_TO_T_UINT_8(0x37, 0x2B, 0x4F, 0x7F, 0x58, 0xE6, 0xC2, 0x70), + MBEDTLS_BYTES_TO_T_UINT_8(0x37, 0x43, 0xD5, 0xA7, 0x35, 0x3C, 0x80, 0xB8), + MBEDTLS_BYTES_TO_T_UINT_8(0x1A, 0x6D, 0x4B, 0x12, 0x00, 0x7B, 0xE6, 0xA6), + MBEDTLS_BYTES_TO_T_UINT_8(0x37, 0x15, 0xBD, 0xD0, 0x9B, 0xCA, 0xAA, 0x81), + MBEDTLS_BYTES_TO_T_UINT_8(0xCF, 0xCE, 0x9C, 0xE3, 0x8B, 0x60, 0x7A, 0x53), + MBEDTLS_BYTES_TO_T_UINT_8(0x0C, 0xDA, 0x4B, 0x03, 0xA7, 0x8D, 0x43, 0x22), + MBEDTLS_BYTES_TO_T_UINT_8(0x57, 0xAF, 0x00, 0x2B, 0x32, 0xF0, 0x22, 0x68), + MBEDTLS_BYTES_TO_T_UINT_8(0xDC, 0xD9, 0x99, 0x99, 0xBE, 0x43, 0x99, 0x3E), +}; +static const mbedtls_mpi_uint brainpoolP512r1_T_24_Y[] = { + MBEDTLS_BYTES_TO_T_UINT_8(0x1F, 0x71, 0x41, 0xF4, 0xB5, 0xFD, 0xDD, 0x36), + MBEDTLS_BYTES_TO_T_UINT_8(0x9D, 0xE2, 0x20, 0x4C, 0xD1, 0x2E, 0x1F, 0x06), + MBEDTLS_BYTES_TO_T_UINT_8(0x96, 0x43, 0x48, 0x76, 0x8A, 0x49, 0xAC, 0x87), + MBEDTLS_BYTES_TO_T_UINT_8(0x0C, 0x1A, 0x55, 0xA8, 0xA3, 0xD4, 0x57, 0x75), + MBEDTLS_BYTES_TO_T_UINT_8(0x7C, 0xA6, 0x84, 0x39, 0xC9, 0x13, 0xBB, 0x60), + MBEDTLS_BYTES_TO_T_UINT_8(0xD9, 0xFA, 0xA9, 0x70, 0xDE, 0x83, 0xDD, 0xC9), + MBEDTLS_BYTES_TO_T_UINT_8(0xEC, 0xC9, 0xD9, 0x3E, 0x44, 0x91, 0x68, 0x7B), + MBEDTLS_BYTES_TO_T_UINT_8(0xB6, 0x9F, 0x85, 0x6D, 0xF7, 0x54, 0x36, 0x82), +}; +static const mbedtls_mpi_uint brainpoolP512r1_T_25_X[] = { + MBEDTLS_BYTES_TO_T_UINT_8(0x68, 0x6B, 0xA6, 0xA3, 0xE5, 0xD4, 0x46, 0xDB), + MBEDTLS_BYTES_TO_T_UINT_8(0x23, 0x3E, 0xDC, 0x84, 0x7C, 0x7B, 0x24, 0x34), + MBEDTLS_BYTES_TO_T_UINT_8(0x14, 0xED, 0x7F, 0x86, 0x07, 0x6C, 0x57, 0xCA), + MBEDTLS_BYTES_TO_T_UINT_8(0x95, 0x06, 0xFE, 0x52, 0x12, 0x79, 0x69, 0x56), + MBEDTLS_BYTES_TO_T_UINT_8(0x84, 0xD1, 0x44, 0x5F, 0x21, 0x3A, 0xC3, 0x84), + MBEDTLS_BYTES_TO_T_UINT_8(0x5E, 0xD9, 0x4A, 0xC0, 0x75, 0xAB, 0x17, 0xAC), + MBEDTLS_BYTES_TO_T_UINT_8(0xFF, 0x81, 0x94, 0xB6, 0x80, 0x6B, 0x6F, 0xC3), + MBEDTLS_BYTES_TO_T_UINT_8(0x07, 0xBE, 0x8E, 0xA5, 0xAA, 0xBC, 0x1E, 0x3E), +}; +static const mbedtls_mpi_uint brainpoolP512r1_T_25_Y[] = { + MBEDTLS_BYTES_TO_T_UINT_8(0x89, 0xC7, 0x85, 0xA6, 0x59, 0x9B, 0xB1, 0x52), + MBEDTLS_BYTES_TO_T_UINT_8(0x1C, 0xCE, 0x40, 0xD1, 0xFB, 0xDF, 0x94, 0xF7), + MBEDTLS_BYTES_TO_T_UINT_8(0x18, 0xB8, 0x5E, 0xBF, 0x45, 0xA8, 0x2D, 0x2D), + MBEDTLS_BYTES_TO_T_UINT_8(0x98, 0x9C, 0x06, 0x1B, 0xA9, 0x57, 0xB9, 0x79), + MBEDTLS_BYTES_TO_T_UINT_8(0x53, 0xE9, 0xCE, 0xA2, 0xD3, 0x74, 0xA1, 0x3C), + MBEDTLS_BYTES_TO_T_UINT_8(0xAA, 0x5F, 0x34, 0x78, 0xDB, 0xAE, 0x3A, 0x14), + MBEDTLS_BYTES_TO_T_UINT_8(0x7D, 0x32, 0x84, 0x3E, 0x68, 0x6A, 0x43, 0x0F), + MBEDTLS_BYTES_TO_T_UINT_8(0x8C, 0xBC, 0x39, 0x36, 0xA4, 0xC5, 0xBB, 0x11), +}; +static const mbedtls_mpi_uint brainpoolP512r1_T_26_X[] = { + MBEDTLS_BYTES_TO_T_UINT_8(0x8C, 0x07, 0xA2, 0xB5, 0xC9, 0x0F, 0x4D, 0x0F), + MBEDTLS_BYTES_TO_T_UINT_8(0xE3, 0x1D, 0x67, 0xE6, 0xF1, 0x46, 0xEB, 0x71), + MBEDTLS_BYTES_TO_T_UINT_8(0xD7, 0x41, 0x23, 0x95, 0xE7, 0xE0, 0x10, 0xDD), + MBEDTLS_BYTES_TO_T_UINT_8(0xBE, 0x69, 0xFE, 0x68, 0x8C, 0xC6, 0x5F, 0xB6), + MBEDTLS_BYTES_TO_T_UINT_8(0xE3, 0xB9, 0x2B, 0x3D, 0xD2, 0x4F, 0xD8, 0x1A), + MBEDTLS_BYTES_TO_T_UINT_8(0xA3, 0x09, 0xF5, 0x5F, 0xCF, 0xF6, 0x91, 0x57), + MBEDTLS_BYTES_TO_T_UINT_8(0x65, 0x15, 0x42, 0x6B, 0x6D, 0xB5, 0xF3, 0xB6), + MBEDTLS_BYTES_TO_T_UINT_8(0xBF, 0x56, 0x9D, 0xC5, 0xFF, 0xCA, 0x13, 0x9B), +}; +static const mbedtls_mpi_uint brainpoolP512r1_T_26_Y[] = { + MBEDTLS_BYTES_TO_T_UINT_8(0x4D, 0x38, 0xE6, 0x23, 0x63, 0x48, 0x3C, 0xCA), + MBEDTLS_BYTES_TO_T_UINT_8(0xD2, 0x68, 0x3C, 0xD1, 0x3B, 0xE9, 0x3B, 0x82), + MBEDTLS_BYTES_TO_T_UINT_8(0xB5, 0x08, 0x54, 0x49, 0xD1, 0x46, 0x45, 0x13), + MBEDTLS_BYTES_TO_T_UINT_8(0x07, 0x70, 0x52, 0x6E, 0x79, 0xC4, 0x5E, 0x95), + MBEDTLS_BYTES_TO_T_UINT_8(0x36, 0xDF, 0xE8, 0x5A, 0x32, 0x81, 0xDA, 0xD3), + MBEDTLS_BYTES_TO_T_UINT_8(0x3C, 0x2D, 0x94, 0x5B, 0xB5, 0x35, 0x9F, 0x0A), + MBEDTLS_BYTES_TO_T_UINT_8(0x2A, 0x12, 0x8D, 0xC3, 0x36, 0x36, 0xB2, 0x2A), + MBEDTLS_BYTES_TO_T_UINT_8(0x39, 0x2F, 0x22, 0x38, 0x5B, 0x18, 0x4C, 0x35), +}; +static const mbedtls_mpi_uint brainpoolP512r1_T_27_X[] = { + MBEDTLS_BYTES_TO_T_UINT_8(0x10, 0xC1, 0x22, 0x0E, 0xF0, 0x73, 0x11, 0x05), + MBEDTLS_BYTES_TO_T_UINT_8(0xB2, 0xAE, 0xA4, 0x56, 0x18, 0x61, 0x66, 0x12), + MBEDTLS_BYTES_TO_T_UINT_8(0x79, 0xFB, 0x72, 0x08, 0x84, 0x38, 0x51, 0xB0), + MBEDTLS_BYTES_TO_T_UINT_8(0xDA, 0x86, 0xA8, 0xB9, 0x31, 0x99, 0x29, 0xC3), + MBEDTLS_BYTES_TO_T_UINT_8(0x8A, 0xFB, 0xC3, 0x42, 0xB3, 0xC7, 0x6F, 0x3A), + MBEDTLS_BYTES_TO_T_UINT_8(0xD8, 0xF8, 0xE1, 0x09, 0xBE, 0x75, 0xB0, 0x22), + MBEDTLS_BYTES_TO_T_UINT_8(0x5A, 0x7D, 0xFF, 0xF4, 0x99, 0xFC, 0x13, 0xAB), + MBEDTLS_BYTES_TO_T_UINT_8(0xE6, 0x1B, 0x84, 0x81, 0x42, 0x22, 0xC6, 0x3D), +}; +static const mbedtls_mpi_uint brainpoolP512r1_T_27_Y[] = { + MBEDTLS_BYTES_TO_T_UINT_8(0x21, 0xE0, 0x37, 0xA4, 0xA0, 0x2F, 0x38, 0x7F), + MBEDTLS_BYTES_TO_T_UINT_8(0xD0, 0x3D, 0xB7, 0x40, 0x2F, 0x39, 0x3C, 0x7A), + MBEDTLS_BYTES_TO_T_UINT_8(0x7A, 0x3B, 0x8A, 0x51, 0xAE, 0x40, 0x49, 0x7A), + MBEDTLS_BYTES_TO_T_UINT_8(0x36, 0x20, 0x9F, 0xDD, 0xA9, 0xD0, 0x77, 0xC7), + MBEDTLS_BYTES_TO_T_UINT_8(0x78, 0x1D, 0x64, 0xDA, 0xA0, 0x53, 0xC7, 0x7D), + MBEDTLS_BYTES_TO_T_UINT_8(0x37, 0x7B, 0x66, 0x55, 0x94, 0xD1, 0x51, 0x44), + MBEDTLS_BYTES_TO_T_UINT_8(0x0E, 0xA9, 0xB5, 0x5B, 0x38, 0x35, 0x40, 0xC0), + MBEDTLS_BYTES_TO_T_UINT_8(0xC8, 0xC9, 0x0F, 0xF0, 0x73, 0x79, 0x43, 0x61), +}; +static const mbedtls_mpi_uint brainpoolP512r1_T_28_X[] = { + MBEDTLS_BYTES_TO_T_UINT_8(0x10, 0x47, 0x45, 0x69, 0x80, 0x72, 0x72, 0x42), + MBEDTLS_BYTES_TO_T_UINT_8(0x70, 0x11, 0x99, 0x59, 0xDB, 0x48, 0x80, 0x39), + MBEDTLS_BYTES_TO_T_UINT_8(0x75, 0x6E, 0x3D, 0xFC, 0x37, 0x15, 0xF4, 0xBF), + MBEDTLS_BYTES_TO_T_UINT_8(0x17, 0xBB, 0x5B, 0xA6, 0x35, 0x8D, 0x28, 0x20), + MBEDTLS_BYTES_TO_T_UINT_8(0xAB, 0x1A, 0x3B, 0x2C, 0x8F, 0xD3, 0xAA, 0x2D), + MBEDTLS_BYTES_TO_T_UINT_8(0x55, 0x1C, 0x1A, 0xF8, 0x02, 0xD9, 0x7B, 0x41), + MBEDTLS_BYTES_TO_T_UINT_8(0xAF, 0x69, 0xAC, 0xF8, 0x54, 0x31, 0x14, 0xA1), + MBEDTLS_BYTES_TO_T_UINT_8(0x41, 0x8A, 0xE6, 0xDE, 0x58, 0xB9, 0xC4, 0x7A), +}; +static const mbedtls_mpi_uint brainpoolP512r1_T_28_Y[] = { + MBEDTLS_BYTES_TO_T_UINT_8(0x57, 0x83, 0x52, 0xFE, 0xF9, 0x7B, 0xE9, 0x1F), + MBEDTLS_BYTES_TO_T_UINT_8(0x07, 0xA2, 0x55, 0x46, 0x15, 0x49, 0xC1, 0x3A), + MBEDTLS_BYTES_TO_T_UINT_8(0x1D, 0xBC, 0x5C, 0x91, 0xBD, 0xB9, 0x9C, 0xF4), + MBEDTLS_BYTES_TO_T_UINT_8(0xBB, 0xFD, 0xB1, 0x4E, 0x5F, 0x74, 0xEE, 0x53), + MBEDTLS_BYTES_TO_T_UINT_8(0xB1, 0x8B, 0xD8, 0x8B, 0x17, 0x73, 0x1B, 0x96), + MBEDTLS_BYTES_TO_T_UINT_8(0x22, 0x92, 0xD7, 0x67, 0x06, 0xAD, 0x25, 0xCD), + MBEDTLS_BYTES_TO_T_UINT_8(0x01, 0x0F, 0x80, 0x24, 0xE2, 0x27, 0x5F, 0x8B), + MBEDTLS_BYTES_TO_T_UINT_8(0x61, 0x1C, 0xCE, 0xD0, 0x67, 0xCA, 0xD4, 0x0B), +}; +static const mbedtls_mpi_uint brainpoolP512r1_T_29_X[] = { + MBEDTLS_BYTES_TO_T_UINT_8(0x87, 0xF1, 0xDD, 0x33, 0x66, 0xF9, 0x05, 0xD6), + MBEDTLS_BYTES_TO_T_UINT_8(0x1D, 0xE5, 0x6B, 0x79, 0xBD, 0x48, 0x42, 0xAA), + MBEDTLS_BYTES_TO_T_UINT_8(0xD1, 0x14, 0x52, 0xE3, 0x53, 0xB4, 0x50, 0xD4), + MBEDTLS_BYTES_TO_T_UINT_8(0x32, 0x84, 0x6C, 0xCF, 0xDA, 0xB2, 0x20, 0x0A), + MBEDTLS_BYTES_TO_T_UINT_8(0x70, 0xD6, 0x1A, 0xE5, 0xE2, 0x29, 0x70, 0xCE), + MBEDTLS_BYTES_TO_T_UINT_8(0xD5, 0x61, 0xFE, 0xBB, 0x21, 0x82, 0xD1, 0xFE), + MBEDTLS_BYTES_TO_T_UINT_8(0x2C, 0xF0, 0x9C, 0x8B, 0x1A, 0x42, 0x30, 0x06), + MBEDTLS_BYTES_TO_T_UINT_8(0x43, 0xD6, 0x49, 0x81, 0x92, 0xF1, 0xD0, 0x90), +}; +static const mbedtls_mpi_uint brainpoolP512r1_T_29_Y[] = { + MBEDTLS_BYTES_TO_T_UINT_8(0xC9, 0x91, 0x93, 0x6A, 0xA6, 0x22, 0xE9, 0xD6), + MBEDTLS_BYTES_TO_T_UINT_8(0x09, 0xDC, 0xC3, 0x69, 0x11, 0x95, 0x7D, 0xEC), + MBEDTLS_BYTES_TO_T_UINT_8(0x1C, 0xA3, 0x9D, 0x87, 0x5E, 0x64, 0x41, 0xA2), + MBEDTLS_BYTES_TO_T_UINT_8(0xBE, 0x87, 0x5A, 0x15, 0xBD, 0x6E, 0x3C, 0x8D), + MBEDTLS_BYTES_TO_T_UINT_8(0xD0, 0x8D, 0x50, 0xCC, 0xCF, 0xB7, 0x8F, 0x0B), + MBEDTLS_BYTES_TO_T_UINT_8(0x38, 0x65, 0xCD, 0x31, 0x30, 0xF1, 0x68, 0x13), + MBEDTLS_BYTES_TO_T_UINT_8(0x10, 0x5C, 0x66, 0x67, 0x92, 0x30, 0x57, 0x95), + MBEDTLS_BYTES_TO_T_UINT_8(0x23, 0x9B, 0x01, 0x3D, 0x20, 0x8B, 0xD1, 0x0D), +}; +static const mbedtls_mpi_uint brainpoolP512r1_T_30_X[] = { + MBEDTLS_BYTES_TO_T_UINT_8(0xAB, 0xC0, 0xE6, 0x4F, 0xDE, 0x62, 0xAB, 0xB3), + MBEDTLS_BYTES_TO_T_UINT_8(0xA4, 0x48, 0xB3, 0x1C, 0x0F, 0x16, 0x93, 0x45), + MBEDTLS_BYTES_TO_T_UINT_8(0x77, 0x63, 0xBD, 0x1F, 0x16, 0x50, 0x56, 0x98), + MBEDTLS_BYTES_TO_T_UINT_8(0x5D, 0x06, 0xBC, 0xE9, 0x27, 0x1C, 0x9A, 0x7B), + MBEDTLS_BYTES_TO_T_UINT_8(0xF8, 0xFE, 0x21, 0xC5, 0x39, 0x55, 0xE1, 0xFD), + MBEDTLS_BYTES_TO_T_UINT_8(0xF6, 0xA8, 0xD0, 0x96, 0x0E, 0xB5, 0xB2, 0x84), + MBEDTLS_BYTES_TO_T_UINT_8(0x3D, 0xE7, 0x4B, 0xF3, 0x11, 0x0C, 0xC9, 0x5B), + MBEDTLS_BYTES_TO_T_UINT_8(0x43, 0x3A, 0xC4, 0x87, 0x71, 0xEE, 0xFA, 0x18), +}; +static const mbedtls_mpi_uint brainpoolP512r1_T_30_Y[] = { + MBEDTLS_BYTES_TO_T_UINT_8(0xA7, 0x77, 0xEE, 0x81, 0x5E, 0x96, 0xEA, 0x4B), + MBEDTLS_BYTES_TO_T_UINT_8(0xEE, 0xDF, 0xA9, 0xF4, 0x4F, 0x7C, 0xB2, 0x43), + MBEDTLS_BYTES_TO_T_UINT_8(0x9F, 0xD4, 0xDF, 0x35, 0x63, 0x47, 0x25, 0x8A), + MBEDTLS_BYTES_TO_T_UINT_8(0xA5, 0x3D, 0xFF, 0xA4, 0x02, 0xC3, 0x95, 0x11), + MBEDTLS_BYTES_TO_T_UINT_8(0xD5, 0x10, 0x78, 0xD1, 0x2B, 0xB7, 0xBE, 0x0E), + MBEDTLS_BYTES_TO_T_UINT_8(0x0A, 0xE9, 0x57, 0xF9, 0xE0, 0xD8, 0xFC, 0xBC), + MBEDTLS_BYTES_TO_T_UINT_8(0xF3, 0xC4, 0x01, 0xD6, 0xB4, 0xE7, 0x78, 0xE2), + MBEDTLS_BYTES_TO_T_UINT_8(0x02, 0x6C, 0xB9, 0x13, 0xA4, 0xE8, 0x6D, 0x6F), +}; +static const mbedtls_mpi_uint brainpoolP512r1_T_31_X[] = { + MBEDTLS_BYTES_TO_T_UINT_8(0xE8, 0xB0, 0xC9, 0xCD, 0xBF, 0xA2, 0x1E, 0x63), + MBEDTLS_BYTES_TO_T_UINT_8(0xDD, 0x4F, 0x86, 0x22, 0x9B, 0xEA, 0xE8, 0xBB), + MBEDTLS_BYTES_TO_T_UINT_8(0x50, 0x46, 0xDF, 0x43, 0xB9, 0x82, 0x2D, 0x0A), + MBEDTLS_BYTES_TO_T_UINT_8(0x07, 0x32, 0xF1, 0x4E, 0x95, 0x41, 0xAE, 0x8E), + MBEDTLS_BYTES_TO_T_UINT_8(0x52, 0x93, 0x26, 0xFC, 0xD3, 0x90, 0xDC, 0xEB), + MBEDTLS_BYTES_TO_T_UINT_8(0x04, 0x05, 0x45, 0xCA, 0xF9, 0x5A, 0x89, 0x93), + MBEDTLS_BYTES_TO_T_UINT_8(0xC5, 0x82, 0x63, 0x4E, 0x55, 0x1D, 0x3A, 0x08), + MBEDTLS_BYTES_TO_T_UINT_8(0x7C, 0x69, 0x52, 0x49, 0xE9, 0xED, 0x57, 0x34), +}; +static const mbedtls_mpi_uint brainpoolP512r1_T_31_Y[] = { + MBEDTLS_BYTES_TO_T_UINT_8(0x70, 0x64, 0xE9, 0xAC, 0x4C, 0x4A, 0xEA, 0x25), + MBEDTLS_BYTES_TO_T_UINT_8(0xE9, 0xE9, 0x0B, 0x99, 0xE7, 0xF9, 0xA9, 0x2C), + MBEDTLS_BYTES_TO_T_UINT_8(0x24, 0x0C, 0xC1, 0xF4, 0x8D, 0x07, 0xB6, 0xB1), + MBEDTLS_BYTES_TO_T_UINT_8(0xAD, 0x68, 0xFA, 0x35, 0xE4, 0x9E, 0xAE, 0xD9), + MBEDTLS_BYTES_TO_T_UINT_8(0xF0, 0x2D, 0x1A, 0x13, 0x8E, 0x02, 0xE2, 0x63), + MBEDTLS_BYTES_TO_T_UINT_8(0x27, 0x38, 0x28, 0x86, 0x46, 0x7B, 0x3A, 0xE1), + MBEDTLS_BYTES_TO_T_UINT_8(0x3F, 0x4C, 0x64, 0x59, 0x0A, 0xF9, 0x02, 0xC4), + MBEDTLS_BYTES_TO_T_UINT_8(0x41, 0x4F, 0x23, 0xA2, 0xC3, 0xD5, 0xEF, 0x42), +}; +static const mbedtls_ecp_point brainpoolP512r1_T[32] = { + ECP_POINT_INIT_XY_Z1(brainpoolP512r1_T_0_X, brainpoolP512r1_T_0_Y), + ECP_POINT_INIT_XY_Z0(brainpoolP512r1_T_1_X, brainpoolP512r1_T_1_Y), + ECP_POINT_INIT_XY_Z0(brainpoolP512r1_T_2_X, brainpoolP512r1_T_2_Y), + ECP_POINT_INIT_XY_Z0(brainpoolP512r1_T_3_X, brainpoolP512r1_T_3_Y), + ECP_POINT_INIT_XY_Z0(brainpoolP512r1_T_4_X, brainpoolP512r1_T_4_Y), + ECP_POINT_INIT_XY_Z0(brainpoolP512r1_T_5_X, brainpoolP512r1_T_5_Y), + ECP_POINT_INIT_XY_Z0(brainpoolP512r1_T_6_X, brainpoolP512r1_T_6_Y), + ECP_POINT_INIT_XY_Z0(brainpoolP512r1_T_7_X, brainpoolP512r1_T_7_Y), + ECP_POINT_INIT_XY_Z0(brainpoolP512r1_T_8_X, brainpoolP512r1_T_8_Y), + ECP_POINT_INIT_XY_Z0(brainpoolP512r1_T_9_X, brainpoolP512r1_T_9_Y), + ECP_POINT_INIT_XY_Z0(brainpoolP512r1_T_10_X, brainpoolP512r1_T_10_Y), + ECP_POINT_INIT_XY_Z0(brainpoolP512r1_T_11_X, brainpoolP512r1_T_11_Y), + ECP_POINT_INIT_XY_Z0(brainpoolP512r1_T_12_X, brainpoolP512r1_T_12_Y), + ECP_POINT_INIT_XY_Z0(brainpoolP512r1_T_13_X, brainpoolP512r1_T_13_Y), + ECP_POINT_INIT_XY_Z0(brainpoolP512r1_T_14_X, brainpoolP512r1_T_14_Y), + ECP_POINT_INIT_XY_Z0(brainpoolP512r1_T_15_X, brainpoolP512r1_T_15_Y), + ECP_POINT_INIT_XY_Z0(brainpoolP512r1_T_16_X, brainpoolP512r1_T_16_Y), + ECP_POINT_INIT_XY_Z0(brainpoolP512r1_T_17_X, brainpoolP512r1_T_17_Y), + ECP_POINT_INIT_XY_Z0(brainpoolP512r1_T_18_X, brainpoolP512r1_T_18_Y), + ECP_POINT_INIT_XY_Z0(brainpoolP512r1_T_19_X, brainpoolP512r1_T_19_Y), + ECP_POINT_INIT_XY_Z0(brainpoolP512r1_T_20_X, brainpoolP512r1_T_20_Y), + ECP_POINT_INIT_XY_Z0(brainpoolP512r1_T_21_X, brainpoolP512r1_T_21_Y), + ECP_POINT_INIT_XY_Z0(brainpoolP512r1_T_22_X, brainpoolP512r1_T_22_Y), + ECP_POINT_INIT_XY_Z0(brainpoolP512r1_T_23_X, brainpoolP512r1_T_23_Y), + ECP_POINT_INIT_XY_Z0(brainpoolP512r1_T_24_X, brainpoolP512r1_T_24_Y), + ECP_POINT_INIT_XY_Z0(brainpoolP512r1_T_25_X, brainpoolP512r1_T_25_Y), + ECP_POINT_INIT_XY_Z0(brainpoolP512r1_T_26_X, brainpoolP512r1_T_26_Y), + ECP_POINT_INIT_XY_Z0(brainpoolP512r1_T_27_X, brainpoolP512r1_T_27_Y), + ECP_POINT_INIT_XY_Z0(brainpoolP512r1_T_28_X, brainpoolP512r1_T_28_Y), + ECP_POINT_INIT_XY_Z0(brainpoolP512r1_T_29_X, brainpoolP512r1_T_29_Y), + ECP_POINT_INIT_XY_Z0(brainpoolP512r1_T_30_X, brainpoolP512r1_T_30_Y), + ECP_POINT_INIT_XY_Z0(brainpoolP512r1_T_31_X, brainpoolP512r1_T_31_Y), +}; +#else +#define brainpoolP512r1_T NULL +#endif +#endif /* MBEDTLS_ECP_DP_BP512R1_ENABLED */ + + +#if defined(ECP_LOAD_GROUP) || defined(MBEDTLS_ECP_DP_CURVE25519_ENABLED) || \ + defined(MBEDTLS_ECP_DP_CURVE448_ENABLED) +/* + * Create an MPI from embedded constants + * (assumes len is an exact multiple of sizeof(mbedtls_mpi_uint) and + * len < 1048576) + */ +static inline void ecp_mpi_load(mbedtls_mpi *X, const mbedtls_mpi_uint *p, size_t len) +{ + X->s = 1; + X->n = (unsigned short) (len / sizeof(mbedtls_mpi_uint)); + X->p = (mbedtls_mpi_uint *) p; +} +#endif + +#if defined(ECP_LOAD_GROUP) +/* + * Set an MPI to static value 1 + */ +static inline void ecp_mpi_set1(mbedtls_mpi *X) +{ + X->s = 1; + X->n = 1; + X->p = mpi_one; +} + +/* + * Make group available from embedded constants + */ +static int ecp_group_load(mbedtls_ecp_group *grp, + const mbedtls_mpi_uint *p, size_t plen, + const mbedtls_mpi_uint *a, size_t alen, + const mbedtls_mpi_uint *b, size_t blen, + const mbedtls_mpi_uint *gx, size_t gxlen, + const mbedtls_mpi_uint *gy, size_t gylen, + const mbedtls_mpi_uint *n, size_t nlen, + const mbedtls_ecp_point *T) +{ + ecp_mpi_load(&grp->P, p, plen); + if (a != NULL) { + ecp_mpi_load(&grp->A, a, alen); + } + ecp_mpi_load(&grp->B, b, blen); + ecp_mpi_load(&grp->N, n, nlen); + + ecp_mpi_load(&grp->G.X, gx, gxlen); + ecp_mpi_load(&grp->G.Y, gy, gylen); + ecp_mpi_set1(&grp->G.Z); + + grp->pbits = mbedtls_mpi_bitlen(&grp->P); + grp->nbits = mbedtls_mpi_bitlen(&grp->N); + + grp->h = 1; + + grp->T = (mbedtls_ecp_point *) T; + /* + * Set T_size to 0 to prevent T free by mbedtls_ecp_group_free. + */ + grp->T_size = 0; + + return 0; +} +#endif /* ECP_LOAD_GROUP */ + +#if defined(MBEDTLS_ECP_NIST_OPTIM) +/* Forward declarations */ +#if defined(MBEDTLS_ECP_DP_SECP192R1_ENABLED) +static int ecp_mod_p192(mbedtls_mpi *); +MBEDTLS_STATIC_TESTABLE +int mbedtls_ecp_mod_p192_raw(mbedtls_mpi_uint *Np, size_t Nn); +#endif +#if defined(MBEDTLS_ECP_DP_SECP224R1_ENABLED) +static int ecp_mod_p224(mbedtls_mpi *); +MBEDTLS_STATIC_TESTABLE +int mbedtls_ecp_mod_p224_raw(mbedtls_mpi_uint *X, size_t X_limbs); +#endif +#if defined(MBEDTLS_ECP_DP_SECP256R1_ENABLED) +static int ecp_mod_p256(mbedtls_mpi *); +MBEDTLS_STATIC_TESTABLE +int mbedtls_ecp_mod_p256_raw(mbedtls_mpi_uint *X, size_t X_limbs); +#endif +#if defined(MBEDTLS_ECP_DP_SECP384R1_ENABLED) +static int ecp_mod_p384(mbedtls_mpi *); +MBEDTLS_STATIC_TESTABLE +int mbedtls_ecp_mod_p384_raw(mbedtls_mpi_uint *X, size_t X_limbs); +#endif +#if defined(MBEDTLS_ECP_DP_SECP521R1_ENABLED) +static int ecp_mod_p521(mbedtls_mpi *); +MBEDTLS_STATIC_TESTABLE +int mbedtls_ecp_mod_p521_raw(mbedtls_mpi_uint *N_p, size_t N_n); +#endif + +#define NIST_MODP(P) grp->modp = ecp_mod_ ## P; +#else +#define NIST_MODP(P) +#endif /* MBEDTLS_ECP_NIST_OPTIM */ + +/* Additional forward declarations */ +#if defined(MBEDTLS_ECP_DP_CURVE25519_ENABLED) +static int ecp_mod_p255(mbedtls_mpi *); +MBEDTLS_STATIC_TESTABLE +int mbedtls_ecp_mod_p255_raw(mbedtls_mpi_uint *X, size_t X_limbs); +#endif +#if defined(MBEDTLS_ECP_DP_CURVE448_ENABLED) +static int ecp_mod_p448(mbedtls_mpi *); +MBEDTLS_STATIC_TESTABLE +int mbedtls_ecp_mod_p448_raw(mbedtls_mpi_uint *, size_t); +#endif +#if defined(MBEDTLS_ECP_DP_SECP192K1_ENABLED) +static int ecp_mod_p192k1(mbedtls_mpi *); +MBEDTLS_STATIC_TESTABLE +int mbedtls_ecp_mod_p192k1_raw(mbedtls_mpi_uint *X, size_t X_limbs); +#endif +#if defined(MBEDTLS_ECP_DP_SECP224K1_ENABLED) +static int ecp_mod_p224k1(mbedtls_mpi *); +MBEDTLS_STATIC_TESTABLE +int mbedtls_ecp_mod_p224k1_raw(mbedtls_mpi_uint *X, size_t X_limbs); +#endif +#if defined(MBEDTLS_ECP_DP_SECP256K1_ENABLED) +static int ecp_mod_p256k1(mbedtls_mpi *); +MBEDTLS_STATIC_TESTABLE +int mbedtls_ecp_mod_p256k1_raw(mbedtls_mpi_uint *X, size_t X_limbs); +#endif + +#if defined(ECP_LOAD_GROUP) +#define LOAD_GROUP_A(G) ecp_group_load(grp, \ + G ## _p, sizeof(G ## _p), \ + G ## _a, sizeof(G ## _a), \ + G ## _b, sizeof(G ## _b), \ + G ## _gx, sizeof(G ## _gx), \ + G ## _gy, sizeof(G ## _gy), \ + G ## _n, sizeof(G ## _n), \ + G ## _T \ + ) + +#define LOAD_GROUP(G) ecp_group_load(grp, \ + G ## _p, sizeof(G ## _p), \ + NULL, 0, \ + G ## _b, sizeof(G ## _b), \ + G ## _gx, sizeof(G ## _gx), \ + G ## _gy, sizeof(G ## _gy), \ + G ## _n, sizeof(G ## _n), \ + G ## _T \ + ) +#endif /* ECP_LOAD_GROUP */ + +#if defined(MBEDTLS_ECP_DP_CURVE25519_ENABLED) +/* Constants used by ecp_use_curve25519() */ +static const mbedtls_mpi_sint curve25519_a24 = 0x01DB42; + +/* P = 2^255 - 19 */ +static const mbedtls_mpi_uint curve25519_p[] = { + MBEDTLS_BYTES_TO_T_UINT_8(0xED, 0XFF, 0XFF, 0XFF, 0XFF, 0XFF, 0XFF, 0XFF), + MBEDTLS_BYTES_TO_T_UINT_8(0XFF, 0XFF, 0XFF, 0XFF, 0XFF, 0XFF, 0XFF, 0XFF), + MBEDTLS_BYTES_TO_T_UINT_8(0XFF, 0XFF, 0XFF, 0XFF, 0XFF, 0XFF, 0XFF, 0XFF), + MBEDTLS_BYTES_TO_T_UINT_8(0XFF, 0XFF, 0XFF, 0XFF, 0XFF, 0XFF, 0XFF, 0X7F) +}; + +/* N = 2^252 + 27742317777372353535851937790883648493 */ +static const mbedtls_mpi_uint curve25519_n[] = { + MBEDTLS_BYTES_TO_T_UINT_8(0XED, 0XD3, 0XF5, 0X5C, 0X1A, 0X63, 0X12, 0X58), + MBEDTLS_BYTES_TO_T_UINT_8(0XD6, 0X9C, 0XF7, 0XA2, 0XDE, 0XF9, 0XDE, 0X14), + MBEDTLS_BYTES_TO_T_UINT_8(0X00, 0X00, 0X00, 0X00, 0x00, 0x00, 0x00, 0x00), + MBEDTLS_BYTES_TO_T_UINT_8(0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x10) +}; + +/* + * Specialized function for creating the Curve25519 group + */ +static int ecp_use_curve25519(mbedtls_ecp_group *grp) +{ + int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED; + + /* Actually ( A + 2 ) / 4 */ + MBEDTLS_MPI_CHK(mbedtls_mpi_lset(&grp->A, curve25519_a24)); + + ecp_mpi_load(&grp->P, curve25519_p, sizeof(curve25519_p)); + + grp->pbits = mbedtls_mpi_bitlen(&grp->P); + + ecp_mpi_load(&grp->N, curve25519_n, sizeof(curve25519_n)); + + /* Y intentionally not set, since we use x/z coordinates. + * This is used as a marker to identify Montgomery curves! */ + MBEDTLS_MPI_CHK(mbedtls_mpi_lset(&grp->G.X, 9)); + MBEDTLS_MPI_CHK(mbedtls_mpi_lset(&grp->G.Z, 1)); + mbedtls_mpi_free(&grp->G.Y); + + /* Actually, the required msb for private keys */ + grp->nbits = 254; + +cleanup: + if (ret != 0) { + mbedtls_ecp_group_free(grp); + } + + return ret; +} +#endif /* MBEDTLS_ECP_DP_CURVE25519_ENABLED */ + +#if defined(MBEDTLS_ECP_DP_CURVE448_ENABLED) +/* Constants used by ecp_use_curve448() */ +static const mbedtls_mpi_sint curve448_a24 = 0x98AA; + +/* P = 2^448 - 2^224 - 1 */ +static const mbedtls_mpi_uint curve448_p[] = { + MBEDTLS_BYTES_TO_T_UINT_8(0XFF, 0XFF, 0XFF, 0XFF, 0XFF, 0XFF, 0XFF, 0XFF), + MBEDTLS_BYTES_TO_T_UINT_8(0XFF, 0XFF, 0XFF, 0XFF, 0XFF, 0XFF, 0XFF, 0XFF), + MBEDTLS_BYTES_TO_T_UINT_8(0XFF, 0XFF, 0XFF, 0XFF, 0XFF, 0XFF, 0XFF, 0XFF), + MBEDTLS_BYTES_TO_T_UINT_8(0XFF, 0XFF, 0XFF, 0XFF, 0XFE, 0XFF, 0XFF, 0XFF), + MBEDTLS_BYTES_TO_T_UINT_8(0XFF, 0XFF, 0XFF, 0XFF, 0XFF, 0XFF, 0XFF, 0XFF), + MBEDTLS_BYTES_TO_T_UINT_8(0XFF, 0XFF, 0XFF, 0XFF, 0XFF, 0XFF, 0XFF, 0XFF), + MBEDTLS_BYTES_TO_T_UINT_8(0XFF, 0XFF, 0XFF, 0XFF, 0XFF, 0XFF, 0XFF, 0XFF), + MBEDTLS_BYTES_TO_T_UINT_8(0X00, 0X00, 0X00, 0X00, 0X00, 0X00, 0X00, 0X00) +}; + +/* N = 2^446 - 13818066809895115352007386748515426880336692474882178609894547503885 */ +static const mbedtls_mpi_uint curve448_n[] = { + MBEDTLS_BYTES_TO_T_UINT_8(0XF3, 0X44, 0X58, 0XAB, 0X92, 0XC2, 0X78, 0X23), + MBEDTLS_BYTES_TO_T_UINT_8(0X55, 0X8F, 0XC5, 0X8D, 0X72, 0XC2, 0X6C, 0X21), + MBEDTLS_BYTES_TO_T_UINT_8(0X90, 0X36, 0XD6, 0XAE, 0X49, 0XDB, 0X4E, 0XC4), + MBEDTLS_BYTES_TO_T_UINT_8(0XE9, 0X23, 0XCA, 0X7C, 0XFF, 0XFF, 0XFF, 0XFF), + MBEDTLS_BYTES_TO_T_UINT_8(0XFF, 0XFF, 0XFF, 0XFF, 0XFF, 0XFF, 0XFF, 0XFF), + MBEDTLS_BYTES_TO_T_UINT_8(0XFF, 0XFF, 0XFF, 0XFF, 0XFF, 0XFF, 0XFF, 0XFF), + MBEDTLS_BYTES_TO_T_UINT_8(0XFF, 0XFF, 0XFF, 0XFF, 0XFF, 0XFF, 0XFF, 0X3F), + MBEDTLS_BYTES_TO_T_UINT_8(0X00, 0X00, 0X00, 0X00, 0X00, 0X00, 0X00, 0X00) +}; + +/* + * Specialized function for creating the Curve448 group + */ +static int ecp_use_curve448(mbedtls_ecp_group *grp) +{ + int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED; + + /* Actually ( A + 2 ) / 4 */ + MBEDTLS_MPI_CHK(mbedtls_mpi_lset(&grp->A, curve448_a24)); + + ecp_mpi_load(&grp->P, curve448_p, sizeof(curve448_p)); + grp->pbits = mbedtls_mpi_bitlen(&grp->P); + + /* Y intentionally not set, since we use x/z coordinates. + * This is used as a marker to identify Montgomery curves! */ + MBEDTLS_MPI_CHK(mbedtls_mpi_lset(&grp->G.X, 5)); + MBEDTLS_MPI_CHK(mbedtls_mpi_lset(&grp->G.Z, 1)); + mbedtls_mpi_free(&grp->G.Y); + + ecp_mpi_load(&grp->N, curve448_n, sizeof(curve448_n)); + + /* Actually, the required msb for private keys */ + grp->nbits = 447; + +cleanup: + if (ret != 0) { + mbedtls_ecp_group_free(grp); + } + + return ret; +} +#endif /* MBEDTLS_ECP_DP_CURVE448_ENABLED */ + +/* + * Set a group using well-known domain parameters + */ +int mbedtls_ecp_group_load(mbedtls_ecp_group *grp, mbedtls_ecp_group_id id) +{ + mbedtls_ecp_group_free(grp); + + mbedtls_ecp_group_init(grp); + + grp->id = id; + + switch (id) { +#if defined(MBEDTLS_ECP_DP_SECP192R1_ENABLED) + case MBEDTLS_ECP_DP_SECP192R1: + NIST_MODP(p192); + return LOAD_GROUP(secp192r1); +#endif /* MBEDTLS_ECP_DP_SECP192R1_ENABLED */ + +#if defined(MBEDTLS_ECP_DP_SECP224R1_ENABLED) + case MBEDTLS_ECP_DP_SECP224R1: + NIST_MODP(p224); + return LOAD_GROUP(secp224r1); +#endif /* MBEDTLS_ECP_DP_SECP224R1_ENABLED */ + +#if defined(MBEDTLS_ECP_DP_SECP256R1_ENABLED) + case MBEDTLS_ECP_DP_SECP256R1: + NIST_MODP(p256); + return LOAD_GROUP(secp256r1); +#endif /* MBEDTLS_ECP_DP_SECP256R1_ENABLED */ + +#if defined(MBEDTLS_ECP_DP_SECP384R1_ENABLED) + case MBEDTLS_ECP_DP_SECP384R1: + NIST_MODP(p384); + return LOAD_GROUP(secp384r1); +#endif /* MBEDTLS_ECP_DP_SECP384R1_ENABLED */ + +#if defined(MBEDTLS_ECP_DP_SECP521R1_ENABLED) + case MBEDTLS_ECP_DP_SECP521R1: + NIST_MODP(p521); + return LOAD_GROUP(secp521r1); +#endif /* MBEDTLS_ECP_DP_SECP521R1_ENABLED */ + +#if defined(MBEDTLS_ECP_DP_SECP192K1_ENABLED) + case MBEDTLS_ECP_DP_SECP192K1: + grp->modp = ecp_mod_p192k1; + return LOAD_GROUP_A(secp192k1); +#endif /* MBEDTLS_ECP_DP_SECP192K1_ENABLED */ + +#if defined(MBEDTLS_ECP_DP_SECP224K1_ENABLED) + case MBEDTLS_ECP_DP_SECP224K1: + grp->modp = ecp_mod_p224k1; + return LOAD_GROUP_A(secp224k1); +#endif /* MBEDTLS_ECP_DP_SECP224K1_ENABLED */ + +#if defined(MBEDTLS_ECP_DP_SECP256K1_ENABLED) + case MBEDTLS_ECP_DP_SECP256K1: + grp->modp = ecp_mod_p256k1; + return LOAD_GROUP_A(secp256k1); +#endif /* MBEDTLS_ECP_DP_SECP256K1_ENABLED */ + +#if defined(MBEDTLS_ECP_DP_BP256R1_ENABLED) + case MBEDTLS_ECP_DP_BP256R1: + return LOAD_GROUP_A(brainpoolP256r1); +#endif /* MBEDTLS_ECP_DP_BP256R1_ENABLED */ + +#if defined(MBEDTLS_ECP_DP_BP384R1_ENABLED) + case MBEDTLS_ECP_DP_BP384R1: + return LOAD_GROUP_A(brainpoolP384r1); +#endif /* MBEDTLS_ECP_DP_BP384R1_ENABLED */ + +#if defined(MBEDTLS_ECP_DP_BP512R1_ENABLED) + case MBEDTLS_ECP_DP_BP512R1: + return LOAD_GROUP_A(brainpoolP512r1); +#endif /* MBEDTLS_ECP_DP_BP512R1_ENABLED */ + +#if defined(MBEDTLS_ECP_DP_CURVE25519_ENABLED) + case MBEDTLS_ECP_DP_CURVE25519: + grp->modp = ecp_mod_p255; + return ecp_use_curve25519(grp); +#endif /* MBEDTLS_ECP_DP_CURVE25519_ENABLED */ + +#if defined(MBEDTLS_ECP_DP_CURVE448_ENABLED) + case MBEDTLS_ECP_DP_CURVE448: + grp->modp = ecp_mod_p448; + return ecp_use_curve448(grp); +#endif /* MBEDTLS_ECP_DP_CURVE448_ENABLED */ + + default: + grp->id = MBEDTLS_ECP_DP_NONE; + return MBEDTLS_ERR_ECP_FEATURE_UNAVAILABLE; + } +} + +#if defined(MBEDTLS_ECP_NIST_OPTIM) +/* + * Fast reduction modulo the primes used by the NIST curves. + * + * These functions are critical for speed, but not needed for correct + * operations. So, we make the choice to heavily rely on the internals of our + * bignum library, which creates a tight coupling between these functions and + * our MPI implementation. However, the coupling between the ECP module and + * MPI remains loose, since these functions can be deactivated at will. + */ + +#if defined(MBEDTLS_ECP_DP_SECP192R1_ENABLED) +/* + * Compared to the way things are presented in FIPS 186-3 D.2, + * we proceed in columns, from right (least significant chunk) to left, + * adding chunks to N in place, and keeping a carry for the next chunk. + * This avoids moving things around in memory, and uselessly adding zeros, + * compared to the more straightforward, line-oriented approach. + * + * For this prime we need to handle data in chunks of 64 bits. + * Since this is always a multiple of our basic mbedtls_mpi_uint, we can + * use a mbedtls_mpi_uint * to designate such a chunk, and small loops to handle it. + */ + +/* Add 64-bit chunks (dst += src) and update carry */ +static inline void add64(mbedtls_mpi_uint *dst, mbedtls_mpi_uint *src, mbedtls_mpi_uint *carry) +{ + unsigned char i; + mbedtls_mpi_uint c = 0; + for (i = 0; i < 8 / sizeof(mbedtls_mpi_uint); i++, dst++, src++) { + *dst += c; c = (*dst < c); + *dst += *src; c += (*dst < *src); + } + *carry += c; +} + +/* Add carry to a 64-bit chunk and update carry */ +static inline void carry64(mbedtls_mpi_uint *dst, mbedtls_mpi_uint *carry) +{ + unsigned char i; + for (i = 0; i < 8 / sizeof(mbedtls_mpi_uint); i++, dst++) { + *dst += *carry; + *carry = (*dst < *carry); + } +} + +#define WIDTH 8 / sizeof(mbedtls_mpi_uint) +#define A(i) Np + (i) * WIDTH +#define ADD(i) add64(p, A(i), &c) +#define NEXT p += WIDTH; carry64(p, &c) +#define LAST p += WIDTH; do *p = 0; while (++p < end) +#define RESET last_carry[0] = c; c = 0; p = Np +#define ADD_LAST add64(p, last_carry, &c) + +/* + * Fast quasi-reduction modulo p192 (FIPS 186-3 D.2.1) + */ +static int ecp_mod_p192(mbedtls_mpi *N) +{ + int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED; + size_t expected_width = BITS_TO_LIMBS(192) * 2; + MBEDTLS_MPI_CHK(mbedtls_mpi_grow(N, expected_width)); + ret = mbedtls_ecp_mod_p192_raw(N->p, expected_width); + +cleanup: + return ret; +} + +MBEDTLS_STATIC_TESTABLE +int mbedtls_ecp_mod_p192_raw(mbedtls_mpi_uint *Np, size_t Nn) +{ + mbedtls_mpi_uint c = 0, last_carry[WIDTH] = { 0 }; + mbedtls_mpi_uint *p, *end; + + if (Nn != BITS_TO_LIMBS(192) * 2) { + return MBEDTLS_ERR_ECP_BAD_INPUT_DATA; + } + + p = Np; + end = p + Nn; + + ADD(3); ADD(5); NEXT; // A0 += A3 + A5 + ADD(3); ADD(4); ADD(5); NEXT; // A1 += A3 + A4 + A5 + ADD(4); ADD(5); // A2 += A4 + A5 + + RESET; + + /* Use the reduction for the carry as well: + * 2^192 * last_carry = 2^64 * last_carry + last_carry mod P192 + * It can generate a carry. */ + ADD_LAST; NEXT; // A0 += last_carry + ADD_LAST; NEXT; // A1 += last_carry + // A2 += carry + + RESET; + + /* Use the reduction for the carry as well: + * 2^192 * last_carry = 2^64 * last_carry + last_carry mod P192 + */ + ADD_LAST; NEXT; // A0 += last_carry + ADD_LAST; NEXT; // A1 += last_carry + // A2 += carry + + LAST; + + return 0; +} + +#undef WIDTH +#undef A +#undef ADD +#undef NEXT +#undef LAST +#undef RESET +#undef ADD_LAST +#endif /* MBEDTLS_ECP_DP_SECP192R1_ENABLED */ + +#if defined(MBEDTLS_ECP_DP_SECP224R1_ENABLED) || \ + defined(MBEDTLS_ECP_DP_SECP256R1_ENABLED) || \ + defined(MBEDTLS_ECP_DP_SECP384R1_ENABLED) + +/* + * The reader is advised to first understand ecp_mod_p192() since the same + * general structure is used here, but with additional complications: + * (1) chunks of 32 bits, and (2) subtractions. + */ + +/* + * For these primes, we need to handle data in chunks of 32 bits. + * This makes it more complicated if we use 64 bits limbs in MPI, + * which prevents us from using a uniform access method as for p192. + * + * So, we define a mini abstraction layer to access 32 bit chunks, + * load them in 'cur' for work, and store them back from 'cur' when done. + * + * While at it, also define the size of N in terms of 32-bit chunks. + */ +#define LOAD32 cur = A(i); + +#if defined(MBEDTLS_HAVE_INT32) /* 32 bit */ + +#define MAX32 X_limbs +#define A(j) X[j] +#define STORE32 X[i] = (mbedtls_mpi_uint) cur; +#define STORE0 X[i] = 0; + +#else /* 64 bit */ + +#define MAX32 X_limbs * 2 +#define A(j) \ + (j) % 2 ? \ + (uint32_t) (X[(j) / 2] >> 32) : \ + (uint32_t) (X[(j) / 2]) +#define STORE32 \ + if (i % 2) { \ + X[i/2] &= 0x00000000FFFFFFFF; \ + X[i/2] |= (uint64_t) (cur) << 32; \ + } else { \ + X[i/2] &= 0xFFFFFFFF00000000; \ + X[i/2] |= (uint32_t) cur; \ + } + +#define STORE0 \ + if (i % 2) { \ + X[i/2] &= 0x00000000FFFFFFFF; \ + } else { \ + X[i/2] &= 0xFFFFFFFF00000000; \ + } + +#endif + +static inline int8_t extract_carry(int64_t cur) +{ + return (int8_t) (cur >> 32); +} + +#define ADD(j) cur += A(j) +#define SUB(j) cur -= A(j) + +#define ADD_CARRY(cc) cur += (cc) +#define SUB_CARRY(cc) cur -= (cc) + +#define ADD_LAST ADD_CARRY(last_c) +#define SUB_LAST SUB_CARRY(last_c) + +/* + * Helpers for the main 'loop' + */ +#define INIT(b) \ + int8_t c = 0, last_c; \ + int64_t cur; \ + size_t i = 0; \ + LOAD32; + +#define NEXT \ + c = extract_carry(cur); \ + STORE32; i++; LOAD32; \ + ADD_CARRY(c); + +#define RESET \ + c = extract_carry(cur); \ + last_c = c; \ + STORE32; i = 0; LOAD32; \ + c = 0; \ + +#define LAST \ + c = extract_carry(cur); \ + STORE32; i++; \ + if (c != 0) \ + return MBEDTLS_ERR_ECP_BAD_INPUT_DATA; \ + while (i < MAX32) { STORE0; i++; } + +#if defined(MBEDTLS_ECP_DP_SECP224R1_ENABLED) + +/* + * Fast quasi-reduction modulo p224 (FIPS 186-3 D.2.2) + */ +static int ecp_mod_p224(mbedtls_mpi *N) +{ + int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED; + size_t expected_width = BITS_TO_LIMBS(224) * 2; + MBEDTLS_MPI_CHK(mbedtls_mpi_grow(N, expected_width)); + ret = mbedtls_ecp_mod_p224_raw(N->p, expected_width); +cleanup: + return ret; +} + +MBEDTLS_STATIC_TESTABLE +int mbedtls_ecp_mod_p224_raw(mbedtls_mpi_uint *X, size_t X_limbs) +{ + if (X_limbs != BITS_TO_LIMBS(224) * 2) { + return MBEDTLS_ERR_ECP_BAD_INPUT_DATA; + } + + INIT(224); + + SUB(7); SUB(11); NEXT; // A0 += -A7 - A11 + SUB(8); SUB(12); NEXT; // A1 += -A8 - A12 + SUB(9); SUB(13); NEXT; // A2 += -A9 - A13 + SUB(10); ADD(7); ADD(11); NEXT; // A3 += -A10 + A7 + A11 + SUB(11); ADD(8); ADD(12); NEXT; // A4 += -A11 + A8 + A12 + SUB(12); ADD(9); ADD(13); NEXT; // A5 += -A12 + A9 + A13 + SUB(13); ADD(10); // A6 += -A13 + A10 + + RESET; + + /* Use 2^224 = P + 2^96 - 1 to modulo reduce the final carry */ + SUB_LAST; NEXT; // A0 -= last_c + ; NEXT; // A1 + ; NEXT; // A2 + ADD_LAST; NEXT; // A3 += last_c + ; NEXT; // A4 + ; NEXT; // A5 + // A6 + + /* The carry reduction cannot generate a carry + * (see commit 73e8553 for details)*/ + + LAST; + + return 0; +} + +#endif /* MBEDTLS_ECP_DP_SECP224R1_ENABLED */ + +#if defined(MBEDTLS_ECP_DP_SECP256R1_ENABLED) + +/* + * Fast quasi-reduction modulo p256 (FIPS 186-3 D.2.3) + */ +static int ecp_mod_p256(mbedtls_mpi *N) +{ + int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED; + size_t expected_width = BITS_TO_LIMBS(256) * 2; + MBEDTLS_MPI_CHK(mbedtls_mpi_grow(N, expected_width)); + ret = mbedtls_ecp_mod_p256_raw(N->p, expected_width); +cleanup: + return ret; +} + +MBEDTLS_STATIC_TESTABLE +int mbedtls_ecp_mod_p256_raw(mbedtls_mpi_uint *X, size_t X_limbs) +{ + if (X_limbs != BITS_TO_LIMBS(256) * 2) { + return MBEDTLS_ERR_ECP_BAD_INPUT_DATA; + } + + INIT(256); + + ADD(8); ADD(9); + SUB(11); SUB(12); SUB(13); SUB(14); NEXT; // A0 + + ADD(9); ADD(10); + SUB(12); SUB(13); SUB(14); SUB(15); NEXT; // A1 + + ADD(10); ADD(11); + SUB(13); SUB(14); SUB(15); NEXT; // A2 + + ADD(11); ADD(11); ADD(12); ADD(12); ADD(13); + SUB(15); SUB(8); SUB(9); NEXT; // A3 + + ADD(12); ADD(12); ADD(13); ADD(13); ADD(14); + SUB(9); SUB(10); NEXT; // A4 + + ADD(13); ADD(13); ADD(14); ADD(14); ADD(15); + SUB(10); SUB(11); NEXT; // A5 + + ADD(14); ADD(14); ADD(15); ADD(15); ADD(14); ADD(13); + SUB(8); SUB(9); NEXT; // A6 + + ADD(15); ADD(15); ADD(15); ADD(8); + SUB(10); SUB(11); SUB(12); SUB(13); // A7 + + RESET; + + /* Use 2^224 * (2^32 - 1) + 2^192 + 2^96 - 1 + * to modulo reduce the final carry. */ + ADD_LAST; NEXT; // A0 + ; NEXT; // A1 + ; NEXT; // A2 + SUB_LAST; NEXT; // A3 + ; NEXT; // A4 + ; NEXT; // A5 + SUB_LAST; NEXT; // A6 + ADD_LAST; // A7 + + RESET; + + /* Use 2^224 * (2^32 - 1) + 2^192 + 2^96 - 1 + * to modulo reduce the carry generated by the previous reduction. */ + ADD_LAST; NEXT; // A0 + ; NEXT; // A1 + ; NEXT; // A2 + SUB_LAST; NEXT; // A3 + ; NEXT; // A4 + ; NEXT; // A5 + SUB_LAST; NEXT; // A6 + ADD_LAST; // A7 + + LAST; + + return 0; +} + +#endif /* MBEDTLS_ECP_DP_SECP256R1_ENABLED */ + +#if defined(MBEDTLS_ECP_DP_SECP384R1_ENABLED) +/* + * Fast quasi-reduction modulo p384 (FIPS 186-3 D.2.4) + */ +static int ecp_mod_p384(mbedtls_mpi *N) +{ + int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED; + size_t expected_width = BITS_TO_LIMBS(384) * 2; + MBEDTLS_MPI_CHK(mbedtls_mpi_grow(N, expected_width)); + ret = mbedtls_ecp_mod_p384_raw(N->p, expected_width); +cleanup: + return ret; +} + +MBEDTLS_STATIC_TESTABLE +int mbedtls_ecp_mod_p384_raw(mbedtls_mpi_uint *X, size_t X_limbs) +{ + if (X_limbs != BITS_TO_LIMBS(384) * 2) { + return MBEDTLS_ERR_ECP_BAD_INPUT_DATA; + } + + INIT(384); + + ADD(12); ADD(21); ADD(20); + SUB(23); NEXT; // A0 + + ADD(13); ADD(22); ADD(23); + SUB(12); SUB(20); NEXT; // A1 + + ADD(14); ADD(23); + SUB(13); SUB(21); NEXT; // A2 + + ADD(15); ADD(12); ADD(20); ADD(21); + SUB(14); SUB(22); SUB(23); NEXT; // A3 + + ADD(21); ADD(21); ADD(16); ADD(13); ADD(12); ADD(20); ADD(22); + SUB(15); SUB(23); SUB(23); NEXT; // A4 + + ADD(22); ADD(22); ADD(17); ADD(14); ADD(13); ADD(21); ADD(23); + SUB(16); NEXT; // A5 + + ADD(23); ADD(23); ADD(18); ADD(15); ADD(14); ADD(22); + SUB(17); NEXT; // A6 + + ADD(19); ADD(16); ADD(15); ADD(23); + SUB(18); NEXT; // A7 + + ADD(20); ADD(17); ADD(16); + SUB(19); NEXT; // A8 + + ADD(21); ADD(18); ADD(17); + SUB(20); NEXT; // A9 + + ADD(22); ADD(19); ADD(18); + SUB(21); NEXT; // A10 + + ADD(23); ADD(20); ADD(19); + SUB(22); // A11 + + RESET; + + /* Use 2^384 = P + 2^128 + 2^96 - 2^32 + 1 to modulo reduce the final carry */ + ADD_LAST; NEXT; // A0 + SUB_LAST; NEXT; // A1 + ; NEXT; // A2 + ADD_LAST; NEXT; // A3 + ADD_LAST; NEXT; // A4 + ; NEXT; // A5 + ; NEXT; // A6 + ; NEXT; // A7 + ; NEXT; // A8 + ; NEXT; // A9 + ; NEXT; // A10 + // A11 + + RESET; + + ADD_LAST; NEXT; // A0 + SUB_LAST; NEXT; // A1 + ; NEXT; // A2 + ADD_LAST; NEXT; // A3 + ADD_LAST; NEXT; // A4 + ; NEXT; // A5 + ; NEXT; // A6 + ; NEXT; // A7 + ; NEXT; // A8 + ; NEXT; // A9 + ; NEXT; // A10 + // A11 + + LAST; + + return 0; +} +#endif /* MBEDTLS_ECP_DP_SECP384R1_ENABLED */ + +#undef LOAD32 +#undef MAX32 +#undef A +#undef STORE32 +#undef STORE0 +#undef ADD +#undef SUB +#undef ADD_CARRY +#undef SUB_CARRY +#undef ADD_LAST +#undef SUB_LAST +#undef INIT +#undef NEXT +#undef RESET +#undef LAST + +#endif /* MBEDTLS_ECP_DP_SECP224R1_ENABLED || + MBEDTLS_ECP_DP_SECP256R1_ENABLED || + MBEDTLS_ECP_DP_SECP384R1_ENABLED */ + +#if defined(MBEDTLS_ECP_DP_SECP521R1_ENABLED) +/* Size of p521 in terms of mbedtls_mpi_uint */ +#define P521_WIDTH (521 / 8 / sizeof(mbedtls_mpi_uint) + 1) + +/* Bits to keep in the most significant mbedtls_mpi_uint */ +#define P521_MASK 0x01FF + +/* + * Fast quasi-reduction modulo p521 = 2^521 - 1 (FIPS 186-3 D.2.5) + */ +static int ecp_mod_p521(mbedtls_mpi *N) +{ + int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED; + size_t expected_width = BITS_TO_LIMBS(521) * 2; + MBEDTLS_MPI_CHK(mbedtls_mpi_grow(N, expected_width)); + ret = mbedtls_ecp_mod_p521_raw(N->p, expected_width); +cleanup: + return ret; +} + +MBEDTLS_STATIC_TESTABLE +int mbedtls_ecp_mod_p521_raw(mbedtls_mpi_uint *X, size_t X_limbs) +{ + mbedtls_mpi_uint carry = 0; + + if (X_limbs != BITS_TO_LIMBS(521) * 2) { + return MBEDTLS_ERR_ECP_BAD_INPUT_DATA; + } + + /* Step 1: Reduction to P521_WIDTH limbs */ + /* Helper references for bottom part of X */ + mbedtls_mpi_uint *X0 = X; + size_t X0_limbs = P521_WIDTH; + /* Helper references for top part of X */ + mbedtls_mpi_uint *X1 = X + X0_limbs; + size_t X1_limbs = X_limbs - X0_limbs; + /* Split X as X0 + 2^P521_WIDTH X1 and compute X0 + 2^(biL - 9) X1. + * (We are using that 2^P521_WIDTH = 2^(512 + biL) and that + * 2^(512 + biL) X1 = 2^(biL - 9) X1 mod P521.) + * The high order limb of the result will be held in carry and the rest + * in X0 (that is the result will be represented as + * 2^P521_WIDTH carry + X0). + * + * Also, note that the resulting carry is either 0 or 1: + * X0 < 2^P521_WIDTH = 2^(512 + biL) and X1 < 2^(P521_WIDTH-biL) = 2^512 + * therefore + * X0 + 2^(biL - 9) X1 < 2^(512 + biL) + 2^(512 + biL - 9) + * which in turn is less than 2 * 2^(512 + biL). + */ + mbedtls_mpi_uint shift = ((mbedtls_mpi_uint) 1u) << (biL - 9); + carry = mbedtls_mpi_core_mla(X0, X0_limbs, X1, X1_limbs, shift); + /* Set X to X0 (by clearing the top part). */ + memset(X1, 0, X1_limbs * sizeof(mbedtls_mpi_uint)); + + /* Step 2: Reduction modulo P521 + * + * At this point X is reduced to P521_WIDTH limbs. What remains is to add + * the carry (that is 2^P521_WIDTH carry) and to reduce mod P521. */ + + /* 2^P521_WIDTH carry = 2^(512 + biL) carry = 2^(biL - 9) carry mod P521. + * Also, recall that carry is either 0 or 1. */ + mbedtls_mpi_uint addend = carry << (biL - 9); + /* Keep the top 9 bits and reduce the rest, using 2^521 = 1 mod P521. */ + addend += (X[P521_WIDTH - 1] >> 9); + X[P521_WIDTH - 1] &= P521_MASK; + + /* Reuse the top part of X (already zeroed) as a helper array for + * carrying out the addition. */ + mbedtls_mpi_uint *addend_arr = X + P521_WIDTH; + addend_arr[0] = addend; + (void) mbedtls_mpi_core_add(X, X, addend_arr, P521_WIDTH); + /* Both addends were less than P521 therefore X < 2 * P521. (This also means + * that the result fit in P521_WIDTH limbs and there won't be any carry.) */ + + /* Clear the reused part of X. */ + addend_arr[0] = 0; + + return 0; +} + +#undef P521_WIDTH +#undef P521_MASK + +#endif /* MBEDTLS_ECP_DP_SECP521R1_ENABLED */ + +#endif /* MBEDTLS_ECP_NIST_OPTIM */ + +#if defined(MBEDTLS_ECP_DP_CURVE25519_ENABLED) + +/* Size of p255 in terms of mbedtls_mpi_uint */ +#define P255_WIDTH (255 / 8 / sizeof(mbedtls_mpi_uint) + 1) + +/* + * Fast quasi-reduction modulo p255 = 2^255 - 19 + * Write N as A0 + 2^256 A1, return A0 + 38 * A1 + */ +static int ecp_mod_p255(mbedtls_mpi *N) +{ + int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED; + size_t expected_width = BITS_TO_LIMBS(255) * 2; + MBEDTLS_MPI_CHK(mbedtls_mpi_grow(N, expected_width)); + ret = mbedtls_ecp_mod_p255_raw(N->p, expected_width); +cleanup: + return ret; +} + +MBEDTLS_STATIC_TESTABLE +int mbedtls_ecp_mod_p255_raw(mbedtls_mpi_uint *X, size_t X_Limbs) +{ + + if (X_Limbs != BITS_TO_LIMBS(255) * 2) { + return MBEDTLS_ERR_ECP_BAD_INPUT_DATA; + } + + mbedtls_mpi_uint *carry = mbedtls_calloc(P255_WIDTH, ciL); + if (carry == NULL) { + return MBEDTLS_ERR_ECP_ALLOC_FAILED; + } + + /* Step 1: Reduction to P255_WIDTH limbs */ + if (X_Limbs > P255_WIDTH) { + /* Helper references for top part of X */ + mbedtls_mpi_uint * const A1 = X + P255_WIDTH; + const size_t A1_limbs = X_Limbs - P255_WIDTH; + + /* X = A0 + 38 * A1, capture carry out */ + *carry = mbedtls_mpi_core_mla(X, P255_WIDTH, A1, A1_limbs, 38); + /* Clear top part */ + memset(A1, 0, sizeof(mbedtls_mpi_uint) * A1_limbs); + } + + /* Step 2: Reduce to <2p + * Split as A0 + 2^255*c, with c a scalar, and compute A0 + 19*c */ + *carry <<= 1; + *carry += (X[P255_WIDTH - 1] >> (biL - 1)); + *carry *= 19; + + /* Clear top bit */ + X[P255_WIDTH - 1] <<= 1; X[P255_WIDTH - 1] >>= 1; + /* Since the top bit for X has been cleared 0 + 0 + Carry + * will not overflow. + * + * Furthermore for 2p = 2^256-38. When a carry propagation on the highest + * limb occurs, X > 2^255 and all the remaining bits on the limb are zero. + * - If X < 2^255 ==> X < 2p + * - If X > 2^255 ==> X < 2^256 - 2^255 < 2p */ + (void) mbedtls_mpi_core_add(X, X, carry, P255_WIDTH); + + mbedtls_free(carry); + return 0; +} +#endif /* MBEDTLS_ECP_DP_CURVE25519_ENABLED */ + +#if defined(MBEDTLS_ECP_DP_CURVE448_ENABLED) + +/* Size of p448 in terms of mbedtls_mpi_uint */ +#define P448_WIDTH (448 / 8 / sizeof(mbedtls_mpi_uint)) + +/* Number of limbs fully occupied by 2^224 (max), and limbs used by it (min) */ +#define DIV_ROUND_UP(X, Y) (((X) + (Y) -1) / (Y)) +#define P224_SIZE (224 / 8) +#define P224_WIDTH_MIN (P224_SIZE / sizeof(mbedtls_mpi_uint)) +#define P224_WIDTH_MAX DIV_ROUND_UP(P224_SIZE, sizeof(mbedtls_mpi_uint)) +#define P224_UNUSED_BITS ((P224_WIDTH_MAX * sizeof(mbedtls_mpi_uint) * 8) - 224) + +static int ecp_mod_p448(mbedtls_mpi *N) +{ + int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED; + size_t expected_width = BITS_TO_LIMBS(448) * 2; + + /* This is required as some tests and use cases do not pass in a Bignum of + * the correct size, and expect the growth to be done automatically, which + * will no longer happen. */ + MBEDTLS_MPI_CHK(mbedtls_mpi_grow(N, expected_width)); + + ret = mbedtls_ecp_mod_p448_raw(N->p, N->n); + +cleanup: + return ret; +} + +/* + * Fast quasi-reduction modulo p448 = 2^448 - 2^224 - 1 + * Write X as A0 + 2^448 A1 and A1 as B0 + 2^224 B1, and return A0 + A1 + B1 + + * (B0 + B1) * 2^224. This is different to the reference implementation of + * Curve448, which uses its own special 56-bit limbs rather than a generic + * bignum library. We could squeeze some extra speed out on 32-bit machines by + * splitting N up into 32-bit limbs and doing the arithmetic using the limbs + * directly as we do for the NIST primes above, but for 64-bit targets it should + * use half the number of operations if we do the reduction with 224-bit limbs, + * since mpi_core_add will then use 64-bit adds. + */ +MBEDTLS_STATIC_TESTABLE +int mbedtls_ecp_mod_p448_raw(mbedtls_mpi_uint *X, size_t X_limbs) +{ + size_t round; + int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED; + + if (X_limbs != BITS_TO_LIMBS(448) * 2) { + return 0; + } + + size_t M_limbs = X_limbs - (P448_WIDTH); + + if (M_limbs > P448_WIDTH) { + /* Shouldn't be called with X larger than 2^896! */ + return MBEDTLS_ERR_ECP_BAD_INPUT_DATA; + } + + /* Both M and Q require an extra limb to catch carries. */ + M_limbs++; + + const size_t Q_limbs = M_limbs; + mbedtls_mpi_uint *M = NULL; + mbedtls_mpi_uint *Q = NULL; + + M = mbedtls_calloc(M_limbs, ciL); + + if (M == NULL) { + return MBEDTLS_ERR_ECP_ALLOC_FAILED; + } + + Q = mbedtls_calloc(Q_limbs, ciL); + + if (Q == NULL) { + ret = MBEDTLS_ERR_ECP_ALLOC_FAILED; + goto cleanup; + } + + /* M = A1 */ + memset(M, 0, (M_limbs * ciL)); + /* Do not copy into the overflow limb, as this would read past the end of + * X. */ + memcpy(M, X + P448_WIDTH, ((M_limbs - 1) * ciL)); + + /* X = A0 */ + memset(X + P448_WIDTH, 0, ((M_limbs - 1) * ciL)); + + /* X = X + M = A0 + A1 */ + /* Carry here fits in oversize X. Oversize M means it will get + * added in, not returned as carry. */ + (void) mbedtls_mpi_core_add(X, X, M, M_limbs); + + /* Q = B1 = M >> 224 */ + memcpy(Q, (char *) M + P224_SIZE, P224_SIZE); + memset((char *) Q + P224_SIZE, 0, P224_SIZE); + + /* X = X + Q = (A0 + A1) + B1 + * Oversize Q catches potential carry here when X is already max 448 bits. + */ + (void) mbedtls_mpi_core_add(X, X, Q, Q_limbs); + + /* M = B0 */ +#ifdef MBEDTLS_HAVE_INT64 + M[P224_WIDTH_MIN] &= ((mbedtls_mpi_uint)-1) >> (P224_UNUSED_BITS); + #endif + memset(M + P224_WIDTH_MAX, 0, ((M_limbs - P224_WIDTH_MAX) * ciL)); + + /* M = M + Q = B0 + B1 */ + (void) mbedtls_mpi_core_add(M, M, Q, Q_limbs); + + /* M = (B0 + B1) * 2^224 */ + /* Shifted carry bit from the addition fits in oversize M. */ + memmove((char *) M + P224_SIZE, M, P224_SIZE + ciL); + memset(M, 0, P224_SIZE); + + /* X = X + M = (A0 + A1 + B1) + (B0 + B1) * 2^224 */ + (void) mbedtls_mpi_core_add(X, X, M, M_limbs); + + /* In the second and third rounds A1 and B0 have at most 1 non-zero limb and + * B1=0. + * Using this we need to calculate: + * A0 + A1 + B1 + (B0 + B1) * 2^224 = A0 + A1 + B0 * 2^224. */ + for (round = 0; round < 2; ++round) { + + /* M = A1 */ + memset(M, 0, (M_limbs * ciL)); + memcpy(M, X + P448_WIDTH, ((M_limbs - 1) * ciL)); + + /* X = A0 */ + memset(X + P448_WIDTH, 0, ((M_limbs - 1) * ciL)); + + /* M = A1 + B0 * 2^224 + * We know that only one limb of A1 will be non-zero and that it will be + * limb 0. We also know that B0 is the bottom 224 bits of A1 (which is + * then shifted up 224 bits), so, given M is currently A1 this turns + * into: + * M = M + (M << 224) + * As the single non-zero limb in B0 will be A1 limb 0 shifted up by 224 + * bits, we can just move that into the right place, shifted up + * accordingly.*/ + M[P224_WIDTH_MIN] = M[0] << (224 & (biL - 1)); + + /* X = A0 + (A1 + B0 * 2^224) */ + (void) mbedtls_mpi_core_add(X, X, M, M_limbs); + } + + ret = 0; + +cleanup: + mbedtls_free(M); + mbedtls_free(Q); + + return ret; +} +#endif /* MBEDTLS_ECP_DP_CURVE448_ENABLED */ + +#if defined(MBEDTLS_ECP_DP_SECP192K1_ENABLED) || \ + defined(MBEDTLS_ECP_DP_SECP224K1_ENABLED) || \ + defined(MBEDTLS_ECP_DP_SECP256K1_ENABLED) + +/* + * Fast quasi-reduction modulo P = 2^s - R, + * with R about 33 bits, used by the Koblitz curves. + * + * Write X as A0 + 2^224 A1, return A0 + R * A1. + */ +#define P_KOBLITZ_R (8 / sizeof(mbedtls_mpi_uint)) // Limbs in R + +static inline int ecp_mod_koblitz(mbedtls_mpi_uint *X, + size_t X_limbs, + mbedtls_mpi_uint *R, + size_t bits) +{ + int ret = 0; + + /* Determine if A1 is aligned to limb bitsize. If not then the used limbs + * of P, A0 and A1 must be set accordingly and there is a middle limb + * which is shared by A0 and A1 and need to handle accordingly. + */ + size_t shift = bits % biL; + size_t adjust = (shift + biL - 1) / biL; + size_t P_limbs = bits / biL + adjust; + + mbedtls_mpi_uint *A1 = mbedtls_calloc(P_limbs, ciL); + if (A1 == NULL) { + return MBEDTLS_ERR_ECP_ALLOC_FAILED; + } + + /* Create a buffer to store the value of `R * A1` */ + size_t R_limbs = P_KOBLITZ_R; + size_t M_limbs = P_limbs + R_limbs; + mbedtls_mpi_uint *M = mbedtls_calloc(M_limbs, ciL); + if (M == NULL) { + ret = MBEDTLS_ERR_ECP_ALLOC_FAILED; + goto cleanup; + } + + mbedtls_mpi_uint mask = 0; + if (adjust != 0) { + mask = ((mbedtls_mpi_uint) 1 << shift) - 1; + } + + /* Two passes are needed to reduce the value of `A0 + R * A1` and then + * we need an additional one to reduce the possible overflow during + * the addition. + */ + for (size_t pass = 0; pass < 3; pass++) { + /* Copy A1 */ + memcpy(A1, X + P_limbs - adjust, P_limbs * ciL); + + /* Shift A1 to be aligned */ + if (shift != 0) { + mbedtls_mpi_core_shift_r(A1, P_limbs, shift); + } + + /* Zeroize the A1 part of the shared limb */ + if (mask != 0) { + X[P_limbs - 1] &= mask; + } + + /* X = A0 + * Zeroize the A1 part of X to keep only the A0 part. + */ + for (size_t i = P_limbs; i < X_limbs; i++) { + X[i] = 0; + } + + /* X = A0 + R * A1 */ + mbedtls_mpi_core_mul(M, A1, P_limbs, R, R_limbs); + (void) mbedtls_mpi_core_add(X, X, M, P_limbs + R_limbs); + + /* Carry can not be generated since R is a 33-bit value and stored in + * 64 bits. The result value of the multiplication is at most + * P length + 33 bits in length and the result value of the addition + * is at most P length + 34 bits in length. So the result of the + * addition always fits in P length + 64 bits. + */ + } + +cleanup: + mbedtls_free(M); + mbedtls_free(A1); + + return ret; +} + +#endif /* MBEDTLS_ECP_DP_SECP192K1_ENABLED) || + MBEDTLS_ECP_DP_SECP224K1_ENABLED) || + MBEDTLS_ECP_DP_SECP256K1_ENABLED) */ + +#if defined(MBEDTLS_ECP_DP_SECP192K1_ENABLED) + +/* + * Fast quasi-reduction modulo p192k1 = 2^192 - R, + * with R = 2^32 + 2^12 + 2^8 + 2^7 + 2^6 + 2^3 + 1 = 0x01000011C9 + */ +static int ecp_mod_p192k1(mbedtls_mpi *N) +{ + int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED; + size_t expected_width = BITS_TO_LIMBS(192) * 2; + MBEDTLS_MPI_CHK(mbedtls_mpi_grow(N, expected_width)); + ret = mbedtls_ecp_mod_p192k1_raw(N->p, expected_width); + +cleanup: + return ret; +} + +MBEDTLS_STATIC_TESTABLE +int mbedtls_ecp_mod_p192k1_raw(mbedtls_mpi_uint *X, size_t X_limbs) +{ + static mbedtls_mpi_uint Rp[] = { + MBEDTLS_BYTES_TO_T_UINT_8(0xC9, 0x11, 0x00, 0x00, + 0x01, 0x00, 0x00, 0x00) + }; + + if (X_limbs != BITS_TO_LIMBS(192) * 2) { + return MBEDTLS_ERR_ECP_BAD_INPUT_DATA; + } + + return ecp_mod_koblitz(X, X_limbs, Rp, 192); +} + +#endif /* MBEDTLS_ECP_DP_SECP192K1_ENABLED */ + +#if defined(MBEDTLS_ECP_DP_SECP224K1_ENABLED) + +/* + * Fast quasi-reduction modulo p224k1 = 2^224 - R, + * with R = 2^32 + 2^12 + 2^11 + 2^9 + 2^7 + 2^4 + 2 + 1 = 0x0100001A93 + */ +static int ecp_mod_p224k1(mbedtls_mpi *N) +{ + int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED; + size_t expected_width = BITS_TO_LIMBS(224) * 2; + MBEDTLS_MPI_CHK(mbedtls_mpi_grow(N, expected_width)); + ret = mbedtls_ecp_mod_p224k1_raw(N->p, expected_width); + +cleanup: + return ret; +} + +MBEDTLS_STATIC_TESTABLE +int mbedtls_ecp_mod_p224k1_raw(mbedtls_mpi_uint *X, size_t X_limbs) +{ + static mbedtls_mpi_uint Rp[] = { + MBEDTLS_BYTES_TO_T_UINT_8(0x93, 0x1A, 0x00, 0x00, + 0x01, 0x00, 0x00, 0x00) + }; + + if (X_limbs != BITS_TO_LIMBS(224) * 2) { + return MBEDTLS_ERR_ECP_BAD_INPUT_DATA; + } + + return ecp_mod_koblitz(X, X_limbs, Rp, 224); +} + +#endif /* MBEDTLS_ECP_DP_SECP224K1_ENABLED */ + +#if defined(MBEDTLS_ECP_DP_SECP256K1_ENABLED) + +/* + * Fast quasi-reduction modulo p256k1 = 2^256 - R, + * with R = 2^32 + 2^9 + 2^8 + 2^7 + 2^6 + 2^4 + 1 = 0x01000003D1 + */ +static int ecp_mod_p256k1(mbedtls_mpi *N) +{ + int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED; + size_t expected_width = BITS_TO_LIMBS(256) * 2; + MBEDTLS_MPI_CHK(mbedtls_mpi_grow(N, expected_width)); + ret = mbedtls_ecp_mod_p256k1_raw(N->p, expected_width); + +cleanup: + return ret; +} + +MBEDTLS_STATIC_TESTABLE +int mbedtls_ecp_mod_p256k1_raw(mbedtls_mpi_uint *X, size_t X_limbs) +{ + static mbedtls_mpi_uint Rp[] = { + MBEDTLS_BYTES_TO_T_UINT_8(0xD1, 0x03, 0x00, 0x00, + 0x01, 0x00, 0x00, 0x00) + }; + + if (X_limbs != BITS_TO_LIMBS(256) * 2) { + return MBEDTLS_ERR_ECP_BAD_INPUT_DATA; + } + + return ecp_mod_koblitz(X, X_limbs, Rp, 256); +} + +#endif /* MBEDTLS_ECP_DP_SECP256K1_ENABLED */ + +#if defined(MBEDTLS_TEST_HOOKS) +MBEDTLS_STATIC_TESTABLE +int mbedtls_ecp_modulus_setup(mbedtls_mpi_mod_modulus *N, + const mbedtls_ecp_group_id id, + const mbedtls_ecp_modulus_type ctype) +{ + mbedtls_mpi_modp_fn modp = NULL; + mbedtls_mpi_uint *p = NULL; + size_t p_limbs; + + if (!(ctype == (mbedtls_ecp_modulus_type) MBEDTLS_ECP_MOD_COORDINATE || \ + ctype == (mbedtls_ecp_modulus_type) MBEDTLS_ECP_MOD_SCALAR)) { + return MBEDTLS_ERR_ECP_BAD_INPUT_DATA; + } + + switch (id) { +#if defined(MBEDTLS_ECP_DP_SECP192R1_ENABLED) + case MBEDTLS_ECP_DP_SECP192R1: + if (ctype == (mbedtls_ecp_modulus_type) MBEDTLS_ECP_MOD_COORDINATE) { +#if defined(MBEDTLS_ECP_NIST_OPTIM) + modp = &mbedtls_ecp_mod_p192_raw; +#endif + p = (mbedtls_mpi_uint *) secp192r1_p; + p_limbs = CHARS_TO_LIMBS(sizeof(secp192r1_p)); + } else { + p = (mbedtls_mpi_uint *) secp192r1_n; + p_limbs = CHARS_TO_LIMBS(sizeof(secp192r1_n)); + } + break; +#endif + +#if defined(MBEDTLS_ECP_DP_SECP224R1_ENABLED) + case MBEDTLS_ECP_DP_SECP224R1: + if (ctype == (mbedtls_ecp_modulus_type) MBEDTLS_ECP_MOD_COORDINATE) { +#if defined(MBEDTLS_ECP_NIST_OPTIM) + modp = &mbedtls_ecp_mod_p224_raw; +#endif + p = (mbedtls_mpi_uint *) secp224r1_p; + p_limbs = CHARS_TO_LIMBS(sizeof(secp224r1_p)); + } else { + p = (mbedtls_mpi_uint *) secp224r1_n; + p_limbs = CHARS_TO_LIMBS(sizeof(secp224r1_n)); + } + break; +#endif + +#if defined(MBEDTLS_ECP_DP_SECP256R1_ENABLED) + case MBEDTLS_ECP_DP_SECP256R1: + if (ctype == (mbedtls_ecp_modulus_type) MBEDTLS_ECP_MOD_COORDINATE) { +#if defined(MBEDTLS_ECP_NIST_OPTIM) + modp = &mbedtls_ecp_mod_p256_raw; +#endif + p = (mbedtls_mpi_uint *) secp256r1_p; + p_limbs = CHARS_TO_LIMBS(sizeof(secp256r1_p)); + } else { + p = (mbedtls_mpi_uint *) secp256r1_n; + p_limbs = CHARS_TO_LIMBS(sizeof(secp256r1_n)); + } + break; +#endif + +#if defined(MBEDTLS_ECP_DP_SECP384R1_ENABLED) + case MBEDTLS_ECP_DP_SECP384R1: + if (ctype == (mbedtls_ecp_modulus_type) MBEDTLS_ECP_MOD_COORDINATE) { +#if defined(MBEDTLS_ECP_NIST_OPTIM) + modp = &mbedtls_ecp_mod_p384_raw; +#endif + p = (mbedtls_mpi_uint *) secp384r1_p; + p_limbs = CHARS_TO_LIMBS(sizeof(secp384r1_p)); + } else { + p = (mbedtls_mpi_uint *) secp384r1_n; + p_limbs = CHARS_TO_LIMBS(sizeof(secp384r1_n)); + } + break; +#endif + +#if defined(MBEDTLS_ECP_DP_SECP521R1_ENABLED) + case MBEDTLS_ECP_DP_SECP521R1: + if (ctype == (mbedtls_ecp_modulus_type) MBEDTLS_ECP_MOD_COORDINATE) { +#if defined(MBEDTLS_ECP_NIST_OPTIM) + modp = &mbedtls_ecp_mod_p521_raw; +#endif + p = (mbedtls_mpi_uint *) secp521r1_p; + p_limbs = CHARS_TO_LIMBS(sizeof(secp521r1_p)); + } else { + p = (mbedtls_mpi_uint *) secp521r1_n; + p_limbs = CHARS_TO_LIMBS(sizeof(secp521r1_n)); + } + break; +#endif + +#if defined(MBEDTLS_ECP_DP_BP256R1_ENABLED) + case MBEDTLS_ECP_DP_BP256R1: + if (ctype == (mbedtls_ecp_modulus_type) MBEDTLS_ECP_MOD_COORDINATE) { + p = (mbedtls_mpi_uint *) brainpoolP256r1_p; + p_limbs = CHARS_TO_LIMBS(sizeof(brainpoolP256r1_p)); + } else { + p = (mbedtls_mpi_uint *) brainpoolP256r1_n; + p_limbs = CHARS_TO_LIMBS(sizeof(brainpoolP256r1_n)); + } + break; +#endif + +#if defined(MBEDTLS_ECP_DP_BP384R1_ENABLED) + case MBEDTLS_ECP_DP_BP384R1: + if (ctype == (mbedtls_ecp_modulus_type) MBEDTLS_ECP_MOD_COORDINATE) { + p = (mbedtls_mpi_uint *) brainpoolP384r1_p; + p_limbs = CHARS_TO_LIMBS(sizeof(brainpoolP384r1_p)); + } else { + p = (mbedtls_mpi_uint *) brainpoolP384r1_n; + p_limbs = CHARS_TO_LIMBS(sizeof(brainpoolP384r1_n)); + } + break; +#endif + +#if defined(MBEDTLS_ECP_DP_BP512R1_ENABLED) + case MBEDTLS_ECP_DP_BP512R1: + if (ctype == (mbedtls_ecp_modulus_type) MBEDTLS_ECP_MOD_COORDINATE) { + p = (mbedtls_mpi_uint *) brainpoolP512r1_p; + p_limbs = CHARS_TO_LIMBS(sizeof(brainpoolP512r1_p)); + } else { + p = (mbedtls_mpi_uint *) brainpoolP512r1_n; + p_limbs = CHARS_TO_LIMBS(sizeof(brainpoolP512r1_n)); + } + break; +#endif + +#if defined(MBEDTLS_ECP_DP_CURVE25519_ENABLED) + case MBEDTLS_ECP_DP_CURVE25519: + if (ctype == (mbedtls_ecp_modulus_type) MBEDTLS_ECP_MOD_COORDINATE) { + modp = &mbedtls_ecp_mod_p255_raw; + p = (mbedtls_mpi_uint *) curve25519_p; + p_limbs = CHARS_TO_LIMBS(sizeof(curve25519_p)); + } else { + p = (mbedtls_mpi_uint *) curve25519_n; + p_limbs = CHARS_TO_LIMBS(sizeof(curve25519_n)); + } + break; +#endif + +#if defined(MBEDTLS_ECP_DP_SECP192K1_ENABLED) + case MBEDTLS_ECP_DP_SECP192K1: + if (ctype == (mbedtls_ecp_modulus_type) MBEDTLS_ECP_MOD_COORDINATE) { + modp = &mbedtls_ecp_mod_p192k1_raw; + p = (mbedtls_mpi_uint *) secp192k1_p; + p_limbs = CHARS_TO_LIMBS(sizeof(secp192k1_p)); + } else { + p = (mbedtls_mpi_uint *) secp192k1_n; + p_limbs = CHARS_TO_LIMBS(sizeof(secp192k1_n)); + } + break; +#endif + +#if defined(MBEDTLS_ECP_DP_SECP224K1_ENABLED) + case MBEDTLS_ECP_DP_SECP224K1: + if (ctype == (mbedtls_ecp_modulus_type) MBEDTLS_ECP_MOD_COORDINATE) { + modp = &mbedtls_ecp_mod_p224k1_raw; + p = (mbedtls_mpi_uint *) secp224k1_p; + p_limbs = CHARS_TO_LIMBS(sizeof(secp224k1_p)); + } else { + p = (mbedtls_mpi_uint *) secp224k1_n; + p_limbs = CHARS_TO_LIMBS(sizeof(secp224k1_n)); + } + break; +#endif + +#if defined(MBEDTLS_ECP_DP_SECP256K1_ENABLED) + case MBEDTLS_ECP_DP_SECP256K1: + if (ctype == (mbedtls_ecp_modulus_type) MBEDTLS_ECP_MOD_COORDINATE) { + modp = &mbedtls_ecp_mod_p256k1_raw; + p = (mbedtls_mpi_uint *) secp256k1_p; + p_limbs = CHARS_TO_LIMBS(sizeof(secp256k1_p)); + } else { + p = (mbedtls_mpi_uint *) secp256k1_n; + p_limbs = CHARS_TO_LIMBS(sizeof(secp256k1_n)); + } + break; +#endif + +#if defined(MBEDTLS_ECP_DP_CURVE448_ENABLED) + case MBEDTLS_ECP_DP_CURVE448: + if (ctype == (mbedtls_ecp_modulus_type) MBEDTLS_ECP_MOD_COORDINATE) { + modp = &mbedtls_ecp_mod_p448_raw; + p = (mbedtls_mpi_uint *) curve448_p; + p_limbs = CHARS_TO_LIMBS(sizeof(curve448_p)); + } else { + p = (mbedtls_mpi_uint *) curve448_n; + p_limbs = CHARS_TO_LIMBS(sizeof(curve448_n)); + } + break; +#endif + + default: + case MBEDTLS_ECP_DP_NONE: + return MBEDTLS_ERR_ECP_BAD_INPUT_DATA; + } + + if (modp != NULL) { + if (mbedtls_mpi_mod_optred_modulus_setup(N, p, p_limbs, modp)) { + return MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED; + } + } else { + if (mbedtls_mpi_mod_modulus_setup(N, p, p_limbs)) { + return MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED; + } + } + return 0; +} +#endif /* MBEDTLS_TEST_HOOKS */ + +#if defined(MBEDTLS_TEST_HOOKS) + +MBEDTLS_STATIC_TESTABLE +mbedtls_ecp_variant mbedtls_ecp_get_variant(void) +{ + return MBEDTLS_ECP_VARIANT_WITH_MPI_UINT; +} + +#endif /* MBEDTLS_TEST_HOOKS */ + +#endif /* !MBEDTLS_ECP_ALT */ +#endif /* MBEDTLS_ECP_LIGHT */ +#endif /* MBEDTLS_ECP_WITH_MPI_UINT */ diff --git a/vendor/mbedtls/include/mbedtls/ecp_internal.h b/vendor/mbedtls/library/ecp_internal_alt.h similarity index 93% rename from vendor/mbedtls/include/mbedtls/ecp_internal.h rename to vendor/mbedtls/library/ecp_internal_alt.h index acaaa087d6..668edc74c9 100644 --- a/vendor/mbedtls/include/mbedtls/ecp_internal.h +++ b/vendor/mbedtls/library/ecp_internal_alt.h @@ -1,24 +1,12 @@ /** - * \file ecp_internal.h + * \file ecp_internal_alt.h * * \brief Function declarations for alternative implementation of elliptic curve * point arithmetic. */ /* * Copyright The Mbed TLS Contributors - * SPDX-License-Identifier: Apache-2.0 - * - * Licensed under the Apache License, Version 2.0 (the "License"); you may - * not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT - * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. + * SPDX-License-Identifier: Apache-2.0 OR GPL-2.0-or-later */ /* @@ -59,11 +47,7 @@ #ifndef MBEDTLS_ECP_INTERNAL_H #define MBEDTLS_ECP_INTERNAL_H -#if !defined(MBEDTLS_CONFIG_FILE) -#include "mbedtls/config.h" -#else -#include MBEDTLS_CONFIG_FILE -#endif +#include "mbedtls/build_info.h" #if defined(MBEDTLS_ECP_INTERNAL_ALT) @@ -300,4 +284,4 @@ int mbedtls_internal_ecp_normalize_mxz(const mbedtls_ecp_group *grp, #endif /* MBEDTLS_ECP_INTERNAL_ALT */ -#endif /* ecp_internal.h */ +#endif /* ecp_internal_alt.h */ diff --git a/vendor/mbedtls/library/ecp_invasive.h b/vendor/mbedtls/library/ecp_invasive.h index d6f6f9565e..ff9f9ecf1d 100644 --- a/vendor/mbedtls/library/ecp_invasive.h +++ b/vendor/mbedtls/library/ecp_invasive.h @@ -9,43 +9,39 @@ */ /* * Copyright The Mbed TLS Contributors - * SPDX-License-Identifier: Apache-2.0 - * - * Licensed under the Apache License, Version 2.0 (the "License"); you may - * not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT - * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. + * SPDX-License-Identifier: Apache-2.0 OR GPL-2.0-or-later */ #ifndef MBEDTLS_ECP_INVASIVE_H #define MBEDTLS_ECP_INVASIVE_H #include "common.h" #include "mbedtls/bignum.h" +#include "bignum_mod.h" #include "mbedtls/ecp.h" -#if defined(MBEDTLS_TEST_HOOKS) && defined(MBEDTLS_ECP_C) +/* + * Curve modulus types + */ +typedef enum { + MBEDTLS_ECP_MOD_NONE = 0, + MBEDTLS_ECP_MOD_COORDINATE, + MBEDTLS_ECP_MOD_SCALAR +} mbedtls_ecp_modulus_type; + +typedef enum { + MBEDTLS_ECP_VARIANT_NONE = 0, + MBEDTLS_ECP_VARIANT_WITH_MPI_STRUCT, + MBEDTLS_ECP_VARIANT_WITH_MPI_UINT +} mbedtls_ecp_variant; -#if defined(MBEDTLS_ECP_DP_SECP224R1_ENABLED) || \ - defined(MBEDTLS_ECP_DP_SECP256R1_ENABLED) || \ - defined(MBEDTLS_ECP_DP_SECP384R1_ENABLED) -/* Preconditions: - * - bits is a multiple of 64 or is 224 - * - c is -1 or -2 - * - 0 <= N < 2^bits - * - N has room for bits plus one limb +#if defined(MBEDTLS_TEST_HOOKS) && defined(MBEDTLS_ECP_LIGHT) + +/** Queries the ecp variant. * - * Behavior: - * Set N to c * 2^bits + old_value_of_N. + * \return The id of the ecp variant. */ -void mbedtls_ecp_fix_negative(mbedtls_mpi *N, signed char c, size_t bits); -#endif +MBEDTLS_STATIC_TESTABLE +mbedtls_ecp_variant mbedtls_ecp_get_variant(void); #if defined(MBEDTLS_ECP_MONTGOMERY_ENABLED) /** Generate a private key on a Montgomery curve (Curve25519 or Curve448). @@ -76,6 +72,254 @@ int mbedtls_ecp_gen_privkey_mx(size_t high_bit, #endif /* MBEDTLS_ECP_MONTGOMERY_ENABLED */ +#if defined(MBEDTLS_ECP_DP_SECP192R1_ENABLED) + +/** Fast quasi-reduction modulo p192 (FIPS 186-3 D.2.1) + * + * This operation expects a 384 bit MPI and the result of the reduction + * is a 192 bit MPI. + * + * \param[in,out] Np The address of the MPI to be converted. + * Must have twice as many limbs as the modulus. + * Upon return this holds the reduced value. The bitlength + * of the reduced value is the same as that of the modulus + * (192 bits). + * \param[in] Nn The length of \p Np in limbs. + */ +MBEDTLS_STATIC_TESTABLE +int mbedtls_ecp_mod_p192_raw(mbedtls_mpi_uint *Np, size_t Nn); + +#endif /* MBEDTLS_ECP_DP_SECP192R1_ENABLED */ + +#if defined(MBEDTLS_ECP_DP_SECP224R1_ENABLED) + +/** Fast quasi-reduction modulo p224 (FIPS 186-3 D.2.2) + * + * \param[in,out] X The address of the MPI to be converted. + * Must have exact limb size that stores a 448-bit MPI + * (double the bitlength of the modulus). + * Upon return holds the reduced value which is + * in range `0 <= X < 2 * N` (where N is the modulus). + * The bitlength of the reduced value is the same as + * that of the modulus (224 bits). + * \param[in] X_limbs The length of \p X in limbs. + * + * \return \c 0 on success. + * \return #MBEDTLS_ERR_ECP_BAD_INPUT_DATA if \p X_limbs is not the + * limb size that sores a 448-bit MPI. + */ +MBEDTLS_STATIC_TESTABLE +int mbedtls_ecp_mod_p224_raw(mbedtls_mpi_uint *X, size_t X_limbs); + +#endif /* MBEDTLS_ECP_DP_SECP224R1_ENABLED */ + +#if defined(MBEDTLS_ECP_DP_SECP256R1_ENABLED) + +/** Fast quasi-reduction modulo p256 (FIPS 186-3 D.2.3) + * + * \param[in,out] X The address of the MPI to be converted. + * Must have exact limb size that stores a 512-bit MPI + * (double the bitlength of the modulus). + * Upon return holds the reduced value which is + * in range `0 <= X < 2 * N` (where N is the modulus). + * The bitlength of the reduced value is the same as + * that of the modulus (256 bits). + * \param[in] X_limbs The length of \p X in limbs. + * + * \return \c 0 on success. + * \return #MBEDTLS_ERR_ECP_BAD_INPUT_DATA if \p X_limbs is not the + * limb size that sores a 512-bit MPI. + */ +MBEDTLS_STATIC_TESTABLE +int mbedtls_ecp_mod_p256_raw(mbedtls_mpi_uint *X, size_t X_limbs); + +#endif + +#if defined(MBEDTLS_ECP_DP_SECP521R1_ENABLED) + +/** Fast quasi-reduction modulo p521 = 2^521 - 1 (FIPS 186-3 D.2.5) + * + * \param[in,out] X The address of the MPI to be converted. + * Must have twice as many limbs as the modulus + * (the modulus is 521 bits long). Upon return this + * holds the reduced value. The reduced value is + * in range `0 <= X < 2 * N` (where N is the modulus). + * and its the bitlength is one plus the bitlength + * of the modulus. + * \param[in] X_limbs The length of \p X in limbs. + * + * \return \c 0 on success. + * \return #MBEDTLS_ERR_ECP_BAD_INPUT_DATA if \p X_limbs does not have + * twice as many limbs as the modulus. + */ +MBEDTLS_STATIC_TESTABLE +int mbedtls_ecp_mod_p521_raw(mbedtls_mpi_uint *X, size_t X_limbs); + +#endif /* MBEDTLS_ECP_DP_SECP521R1_ENABLED */ + +#if defined(MBEDTLS_ECP_DP_SECP384R1_ENABLED) + +/** Fast quasi-reduction modulo p384 (FIPS 186-3 D.2.4) + * + * \param[in,out] X The address of the MPI to be converted. + * Must have exact limb size that stores a 768-bit MPI + * (double the bitlength of the modulus). + * Upon return holds the reduced value which is + * in range `0 <= X < 2 * N` (where N is the modulus). + * The bitlength of the reduced value is the same as + * that of the modulus (384 bits). + * \param[in] X_limbs The length of \p N in limbs. + * + * \return \c 0 on success. + * \return #MBEDTLS_ERR_ECP_BAD_INPUT_DATA if \p N_n does not have + * twice as many limbs as the modulus. + */ +MBEDTLS_STATIC_TESTABLE +int mbedtls_ecp_mod_p384_raw(mbedtls_mpi_uint *X, size_t X_limbs); + +#endif /* MBEDTLS_ECP_DP_SECP384R1_ENABLED */ + +#if defined(MBEDTLS_ECP_DP_SECP192K1_ENABLED) + +/** Fast quasi-reduction modulo p192k1 = 2^192 - R, + * with R = 2^32 + 2^12 + 2^8 + 2^7 + 2^6 + 2^3 + 1 = 0x01000011C9 + * + * \param[in,out] X The address of the MPI to be converted. + * Must have exact limb size that stores a 384-bit MPI + * (double the bitlength of the modulus). + * Upon return holds the reduced value which is + * in range `0 <= X < 2 * N` (where N is the modulus). + * The bitlength of the reduced value is the same as + * that of the modulus (192 bits). + * \param[in] X_limbs The length of \p X in limbs. + * + * \return \c 0 on success. + * \return #MBEDTLS_ERR_ECP_BAD_INPUT_DATA if \p X does not have + * twice as many limbs as the modulus. + * \return #MBEDTLS_ERR_ECP_ALLOC_FAILED if memory allocation failed. + */ +MBEDTLS_STATIC_TESTABLE +int mbedtls_ecp_mod_p192k1_raw(mbedtls_mpi_uint *X, size_t X_limbs); + +#endif /* MBEDTLS_ECP_DP_SECP192K1_ENABLED */ + +#if defined(MBEDTLS_ECP_DP_SECP224K1_ENABLED) + +/** Fast quasi-reduction modulo p224k1 = 2^224 - R, + * with R = 2^32 + 2^12 + 2^11 + 2^9 + 2^7 + 2^4 + 2 + 1 = 0x0100001A93 + * + * \param[in,out] X The address of the MPI to be converted. + * Must have exact limb size that stores a 448-bit MPI + * (double the bitlength of the modulus). + * Upon return holds the reduced value which is + * in range `0 <= X < 2 * N` (where N is the modulus). + * The bitlength of the reduced value is the same as + * that of the modulus (224 bits). + * \param[in] X_limbs The length of \p X in limbs. + * + * \return \c 0 on success. + * \return #MBEDTLS_ERR_ECP_BAD_INPUT_DATA if \p X does not have + * twice as many limbs as the modulus. + * \return #MBEDTLS_ERR_ECP_ALLOC_FAILED if memory allocation failed. + */ +MBEDTLS_STATIC_TESTABLE +int mbedtls_ecp_mod_p224k1_raw(mbedtls_mpi_uint *X, size_t X_limbs); + +#endif /* MBEDTLS_ECP_DP_SECP224K1_ENABLED */ + +#if defined(MBEDTLS_ECP_DP_SECP256K1_ENABLED) + +/** Fast quasi-reduction modulo p256k1 = 2^256 - R, + * with R = 2^32 + 2^9 + 2^8 + 2^7 + 2^6 + 2^4 + 1 = 0x01000003D1 + * + * \param[in,out] X The address of the MPI to be converted. + * Must have exact limb size that stores a 512-bit MPI + * (double the bitlength of the modulus). + * Upon return holds the reduced value which is + * in range `0 <= X < 2 * N` (where N is the modulus). + * The bitlength of the reduced value is the same as + * that of the modulus (256 bits). + * \param[in] X_limbs The length of \p X in limbs. + * + * \return \c 0 on success. + * \return #MBEDTLS_ERR_ECP_BAD_INPUT_DATA if \p X does not have + * twice as many limbs as the modulus. + * \return #MBEDTLS_ERR_ECP_ALLOC_FAILED if memory allocation failed. + */ +MBEDTLS_STATIC_TESTABLE +int mbedtls_ecp_mod_p256k1_raw(mbedtls_mpi_uint *X, size_t X_limbs); + +#endif /* MBEDTLS_ECP_DP_SECP256K1_ENABLED */ + +#if defined(MBEDTLS_ECP_DP_CURVE25519_ENABLED) + +/** Fast quasi-reduction modulo p255 = 2^255 - 19 + * + * \param[in,out] X The address of the MPI to be converted. + * Must have exact limb size that stores a 510-bit MPI + * (double the bitlength of the modulus). + * Upon return holds the reduced value which is + * in range `0 <= X < 2 * N` (where N is the modulus). + * \param[in] X_limbs The length of \p X in limbs. + * + * \return \c 0 on success. + * \return #MBEDTLS_ERR_ECP_BAD_INPUT_DATA if \p X does not have + * twice as many limbs as the modulus. + * \return #MBEDTLS_ERR_ECP_ALLOC_FAILED if memory allocation failed. + */ +MBEDTLS_STATIC_TESTABLE +int mbedtls_ecp_mod_p255_raw(mbedtls_mpi_uint *X, size_t X_limbs); + +#endif /* MBEDTLS_ECP_DP_CURVE25519_ENABLED */ + +#if defined(MBEDTLS_ECP_DP_CURVE448_ENABLED) + +/** Fast quasi-reduction modulo p448 = 2^448 - 2^224 - 1 + * Write X as A0 + 2^448 A1 and A1 as B0 + 2^224 B1, and return A0 + A1 + B1 + + * (B0 + B1) * 2^224. + * + * \param[in,out] X The address of the MPI to be converted. + * Must have exact limb size that stores a 896-bit MPI + * (double the bitlength of the modulus). Upon return + * holds the reduced value which is in range `0 <= X < + * N` (where N is the modulus). The bitlength of the + * reduced value is the same as that of the modulus + * (448 bits). + * \param[in] X_limbs The length of \p X in limbs. + * + * \return \c 0 on Success. + * \return #MBEDTLS_ERR_ECP_BAD_INPUT_DATA if \p X does not have + * twice as many limbs as the modulus. + * \return #MBEDTLS_ERR_ECP_ALLOC_FAILED if memory allocation + * failed. + */ +MBEDTLS_STATIC_TESTABLE +int mbedtls_ecp_mod_p448_raw(mbedtls_mpi_uint *X, size_t X_limbs); + +#endif /* MBEDTLS_ECP_DP_CURVE448_ENABLED */ + +/** Initialise a modulus with hard-coded const curve data. + * + * \note The caller is responsible for the \p N modulus' memory. + * mbedtls_mpi_mod_modulus_free(&N) should be invoked at the + * end of its lifecycle. + * + * \param[in,out] N The address of the modulus structure to populate. + * Must be initialized. + * \param[in] id The mbedtls_ecp_group_id for which to initialise the modulus. + * \param[in] ctype The mbedtls_ecp_modulus_type identifier for a coordinate modulus (P) + * or a scalar modulus (N). + * + * \return \c 0 if successful. + * \return #MBEDTLS_ERR_ECP_BAD_INPUT_DATA if the given MPIs do not + * have the correct number of limbs. + * + */ +MBEDTLS_STATIC_TESTABLE +int mbedtls_ecp_modulus_setup(mbedtls_mpi_mod_modulus *N, + const mbedtls_ecp_group_id id, + const mbedtls_ecp_modulus_type ctype); + #endif /* MBEDTLS_TEST_HOOKS && MBEDTLS_ECP_C */ #endif /* MBEDTLS_ECP_INVASIVE_H */ diff --git a/vendor/mbedtls/library/entropy.c b/vendor/mbedtls/library/entropy.c index e9a7ae63d3..e3bc8516e2 100644 --- a/vendor/mbedtls/library/entropy.c +++ b/vendor/mbedtls/library/entropy.c @@ -2,37 +2,17 @@ * Entropy accumulator implementation * * Copyright The Mbed TLS Contributors - * SPDX-License-Identifier: Apache-2.0 - * - * Licensed under the Apache License, Version 2.0 (the "License"); you may - * not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT - * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. + * SPDX-License-Identifier: Apache-2.0 OR GPL-2.0-or-later */ #include "common.h" #if defined(MBEDTLS_ENTROPY_C) -#if defined(MBEDTLS_TEST_NULL_ENTROPY) -#warning "**** WARNING! MBEDTLS_TEST_NULL_ENTROPY defined! " -#warning "**** THIS BUILD HAS NO DEFINED ENTROPY SOURCES " -#warning "**** THIS BUILD IS *NOT* SUITABLE FOR PRODUCTION USE " -#endif - #include "mbedtls/entropy.h" -#include "mbedtls/entropy_poll.h" +#include "entropy_poll.h" #include "mbedtls/platform_util.h" #include "mbedtls/error.h" -#include "mbedtls/sha256.h" -#include "mbedtls/sha512.h" #include @@ -42,12 +22,6 @@ #include "mbedtls/platform.h" -#include "mbedtls/platform.h" - -#if defined(MBEDTLS_HAVEGE_C) -#include "mbedtls/havege.h" -#endif - #define ENTROPY_MAX_LOOP 256 /**< Maximum amount to loop before error */ void mbedtls_entropy_init(mbedtls_entropy_context *ctx) @@ -60,39 +34,17 @@ void mbedtls_entropy_init(mbedtls_entropy_context *ctx) #endif ctx->accumulator_started = 0; -#if defined(MBEDTLS_ENTROPY_SHA512_ACCUMULATOR) - mbedtls_sha512_init(&ctx->accumulator); -#else - mbedtls_sha256_init(&ctx->accumulator); -#endif -#if defined(MBEDTLS_HAVEGE_C) - mbedtls_havege_init(&ctx->havege_data); -#endif + mbedtls_md_init(&ctx->accumulator); /* Reminder: Update ENTROPY_HAVE_STRONG in the test files * when adding more strong entropy sources here. */ -#if defined(MBEDTLS_TEST_NULL_ENTROPY) - mbedtls_entropy_add_source(ctx, mbedtls_null_entropy_poll, NULL, - 1, MBEDTLS_ENTROPY_SOURCE_STRONG); -#endif - #if !defined(MBEDTLS_NO_DEFAULT_ENTROPY_SOURCES) #if !defined(MBEDTLS_NO_PLATFORM_ENTROPY) mbedtls_entropy_add_source(ctx, mbedtls_platform_entropy_poll, NULL, MBEDTLS_ENTROPY_MIN_PLATFORM, MBEDTLS_ENTROPY_SOURCE_STRONG); #endif -#if defined(MBEDTLS_TIMING_C) - mbedtls_entropy_add_source(ctx, mbedtls_hardclock_poll, NULL, - MBEDTLS_ENTROPY_MIN_HARDCLOCK, - MBEDTLS_ENTROPY_SOURCE_WEAK); -#endif -#if defined(MBEDTLS_HAVEGE_C) - mbedtls_entropy_add_source(ctx, mbedtls_havege_poll, &ctx->havege_data, - MBEDTLS_ENTROPY_MIN_HAVEGE, - MBEDTLS_ENTROPY_SOURCE_STRONG); -#endif #if defined(MBEDTLS_ENTROPY_HARDWARE_ALT) mbedtls_entropy_add_source(ctx, mbedtls_hardware_poll, NULL, MBEDTLS_ENTROPY_MIN_HARDWARE, @@ -115,17 +67,10 @@ void mbedtls_entropy_free(mbedtls_entropy_context *ctx) return; } -#if defined(MBEDTLS_HAVEGE_C) - mbedtls_havege_free(&ctx->havege_data); -#endif #if defined(MBEDTLS_THREADING_C) mbedtls_mutex_free(&ctx->mutex); #endif -#if defined(MBEDTLS_ENTROPY_SHA512_ACCUMULATOR) - mbedtls_sha512_free(&ctx->accumulator); -#else - mbedtls_sha256_free(&ctx->accumulator); -#endif + mbedtls_md_free(&ctx->accumulator); #if defined(MBEDTLS_ENTROPY_NV_SEED) ctx->initial_entropy_run = 0; #endif @@ -182,15 +127,10 @@ static int entropy_update(mbedtls_entropy_context *ctx, unsigned char source_id, int ret = 0; if (use_len > MBEDTLS_ENTROPY_BLOCK_SIZE) { -#if defined(MBEDTLS_ENTROPY_SHA512_ACCUMULATOR) - if ((ret = mbedtls_sha512_ret(data, len, tmp, 0)) != 0) { + if ((ret = mbedtls_md(mbedtls_md_info_from_type(MBEDTLS_ENTROPY_MD), + data, len, tmp)) != 0) { goto cleanup; } -#else - if ((ret = mbedtls_sha256_ret(data, len, tmp, 0)) != 0) { - goto cleanup; - } -#endif p = tmp; use_len = MBEDTLS_ENTROPY_BLOCK_SIZE; } @@ -203,29 +143,22 @@ static int entropy_update(mbedtls_entropy_context *ctx, unsigned char source_id, * it is sufficient to start the accumulator here only because all calls to * gather entropy eventually execute this code. */ -#if defined(MBEDTLS_ENTROPY_SHA512_ACCUMULATOR) - if (ctx->accumulator_started == 0 && - (ret = mbedtls_sha512_starts_ret(&ctx->accumulator, 0)) != 0) { - goto cleanup; - } else { - ctx->accumulator_started = 1; - } - if ((ret = mbedtls_sha512_update_ret(&ctx->accumulator, header, 2)) != 0) { - goto cleanup; - } - ret = mbedtls_sha512_update_ret(&ctx->accumulator, p, use_len); -#else - if (ctx->accumulator_started == 0 && - (ret = mbedtls_sha256_starts_ret(&ctx->accumulator, 0)) != 0) { - goto cleanup; - } else { + if (ctx->accumulator_started == 0) { + ret = mbedtls_md_setup(&ctx->accumulator, + mbedtls_md_info_from_type(MBEDTLS_ENTROPY_MD), 0); + if (ret != 0) { + goto cleanup; + } + ret = mbedtls_md_starts(&ctx->accumulator); + if (ret != 0) { + goto cleanup; + } ctx->accumulator_started = 1; } - if ((ret = mbedtls_sha256_update_ret(&ctx->accumulator, header, 2)) != 0) { + if ((ret = mbedtls_md_update(&ctx->accumulator, header, 2)) != 0) { goto cleanup; } - ret = mbedtls_sha256_update_ret(&ctx->accumulator, p, use_len); -#endif + ret = mbedtls_md_update(&ctx->accumulator, p, use_len); cleanup: mbedtls_platform_zeroize(tmp, sizeof(tmp)); @@ -386,62 +319,41 @@ int mbedtls_entropy_func(void *data, unsigned char *output, size_t len) memset(buf, 0, MBEDTLS_ENTROPY_BLOCK_SIZE); -#if defined(MBEDTLS_ENTROPY_SHA512_ACCUMULATOR) /* * Note that at this stage it is assumed that the accumulator was started * in a previous call to entropy_update(). If this is not guaranteed, the * code below will fail. */ - if ((ret = mbedtls_sha512_finish_ret(&ctx->accumulator, buf)) != 0) { + if ((ret = mbedtls_md_finish(&ctx->accumulator, buf)) != 0) { goto exit; } /* * Reset accumulator and counters and recycle existing entropy */ - mbedtls_sha512_free(&ctx->accumulator); - mbedtls_sha512_init(&ctx->accumulator); - if ((ret = mbedtls_sha512_starts_ret(&ctx->accumulator, 0)) != 0) { - goto exit; - } - if ((ret = mbedtls_sha512_update_ret(&ctx->accumulator, buf, - MBEDTLS_ENTROPY_BLOCK_SIZE)) != 0) { - goto exit; - } - - /* - * Perform second SHA-512 on entropy - */ - if ((ret = mbedtls_sha512_ret(buf, MBEDTLS_ENTROPY_BLOCK_SIZE, - buf, 0)) != 0) { - goto exit; - } -#else /* MBEDTLS_ENTROPY_SHA512_ACCUMULATOR */ - if ((ret = mbedtls_sha256_finish_ret(&ctx->accumulator, buf)) != 0) { + mbedtls_md_free(&ctx->accumulator); + mbedtls_md_init(&ctx->accumulator); + ret = mbedtls_md_setup(&ctx->accumulator, + mbedtls_md_info_from_type(MBEDTLS_ENTROPY_MD), 0); + if (ret != 0) { goto exit; } - - /* - * Reset accumulator and counters and recycle existing entropy - */ - mbedtls_sha256_free(&ctx->accumulator); - mbedtls_sha256_init(&ctx->accumulator); - if ((ret = mbedtls_sha256_starts_ret(&ctx->accumulator, 0)) != 0) { + ret = mbedtls_md_starts(&ctx->accumulator); + if (ret != 0) { goto exit; } - if ((ret = mbedtls_sha256_update_ret(&ctx->accumulator, buf, - MBEDTLS_ENTROPY_BLOCK_SIZE)) != 0) { + if ((ret = mbedtls_md_update(&ctx->accumulator, buf, + MBEDTLS_ENTROPY_BLOCK_SIZE)) != 0) { goto exit; } /* - * Perform second SHA-256 on entropy + * Perform second hashing on entropy */ - if ((ret = mbedtls_sha256_ret(buf, MBEDTLS_ENTROPY_BLOCK_SIZE, - buf, 0)) != 0) { + if ((ret = mbedtls_md(mbedtls_md_info_from_type(MBEDTLS_ENTROPY_MD), + buf, MBEDTLS_ENTROPY_BLOCK_SIZE, buf)) != 0) { goto exit; } -#endif /* MBEDTLS_ENTROPY_SHA512_ACCUMULATOR */ for (i = 0; i < ctx->source_count; i++) { ctx->source[i].size = 0; @@ -503,6 +415,9 @@ int mbedtls_entropy_write_seed_file(mbedtls_entropy_context *ctx, const char *pa goto exit; } + /* Ensure no stdio buffering of secrets, as such buffers cannot be wiped. */ + mbedtls_setbuf(f, NULL); + if (fwrite(buf, 1, MBEDTLS_ENTROPY_BLOCK_SIZE, f) != MBEDTLS_ENTROPY_BLOCK_SIZE) { ret = MBEDTLS_ERR_ENTROPY_FILE_IO_ERROR; goto exit; @@ -531,6 +446,9 @@ int mbedtls_entropy_update_seed_file(mbedtls_entropy_context *ctx, const char *p return MBEDTLS_ERR_ENTROPY_FILE_IO_ERROR; } + /* Ensure no stdio buffering of secrets, as such buffers cannot be wiped. */ + mbedtls_setbuf(f, NULL); + fseek(f, 0, SEEK_END); n = (size_t) ftell(f); fseek(f, 0, SEEK_SET); @@ -558,7 +476,6 @@ int mbedtls_entropy_update_seed_file(mbedtls_entropy_context *ctx, const char *p #endif /* MBEDTLS_FS_IO */ #if defined(MBEDTLS_SELF_TEST) -#if !defined(MBEDTLS_TEST_NULL_ENTROPY) /* * Dummy source function */ @@ -572,7 +489,6 @@ static int entropy_dummy_source(void *data, unsigned char *output, return 0; } -#endif /* !MBEDTLS_TEST_NULL_ENTROPY */ #if defined(MBEDTLS_ENTROPY_HARDWARE_ALT) @@ -683,18 +599,15 @@ int mbedtls_entropy_source_self_test(int verbose) int mbedtls_entropy_self_test(int verbose) { int ret = 1; -#if !defined(MBEDTLS_TEST_NULL_ENTROPY) mbedtls_entropy_context ctx; unsigned char buf[MBEDTLS_ENTROPY_BLOCK_SIZE] = { 0 }; unsigned char acc[MBEDTLS_ENTROPY_BLOCK_SIZE] = { 0 }; size_t i, j; -#endif /* !MBEDTLS_TEST_NULL_ENTROPY */ if (verbose != 0) { mbedtls_printf(" ENTROPY test: "); } -#if !defined(MBEDTLS_TEST_NULL_ENTROPY) mbedtls_entropy_init(&ctx); /* First do a gather to make sure we have default sources */ @@ -745,7 +658,6 @@ int mbedtls_entropy_self_test(int verbose) cleanup: mbedtls_entropy_free(&ctx); -#endif /* !MBEDTLS_TEST_NULL_ENTROPY */ if (verbose != 0) { if (ret != 0) { diff --git a/vendor/mbedtls/library/entropy_poll.c b/vendor/mbedtls/library/entropy_poll.c index 3420616a06..794ee03a83 100644 --- a/vendor/mbedtls/library/entropy_poll.c +++ b/vendor/mbedtls/library/entropy_poll.c @@ -2,22 +2,10 @@ * Platform-specific and custom entropy polling functions * * Copyright The Mbed TLS Contributors - * SPDX-License-Identifier: Apache-2.0 - * - * Licensed under the Apache License, Version 2.0 (the "License"); you may - * not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT - * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. + * SPDX-License-Identifier: Apache-2.0 OR GPL-2.0-or-later */ -#if defined(__linux__) && !defined(_GNU_SOURCE) +#if defined(__linux__) || defined(__midipix__) && !defined(_GNU_SOURCE) /* Ensure that syscall() is available even when compiling with -std=c99 */ #define _GNU_SOURCE #endif @@ -29,54 +17,53 @@ #if defined(MBEDTLS_ENTROPY_C) #include "mbedtls/entropy.h" -#include "mbedtls/entropy_poll.h" +#include "entropy_poll.h" #include "mbedtls/error.h" #if defined(MBEDTLS_TIMING_C) #include "mbedtls/timing.h" #endif -#if defined(MBEDTLS_HAVEGE_C) -#include "mbedtls/havege.h" -#endif #include "mbedtls/platform.h" #if !defined(MBEDTLS_NO_PLATFORM_ENTROPY) #if !defined(unix) && !defined(__unix__) && !defined(__unix) && \ !defined(__APPLE__) && !defined(_WIN32) && !defined(__QNXNTO__) && \ - !defined(__HAIKU__) && !defined(__midipix__) + !defined(__HAIKU__) && !defined(__midipix__) && !defined(__MVS__) #error \ - "Platform entropy sources only work on Unix and Windows, see MBEDTLS_NO_PLATFORM_ENTROPY in config.h" + "Platform entropy sources only work on Unix and Windows, see MBEDTLS_NO_PLATFORM_ENTROPY in mbedtls_config.h" #endif #if defined(_WIN32) && !defined(EFIX64) && !defined(EFI32) -#if !defined(_WIN32_WINNT) -#define _WIN32_WINNT 0x0400 -#endif #include -#include +#include +#include int mbedtls_platform_entropy_poll(void *data, unsigned char *output, size_t len, size_t *olen) { - HCRYPTPROV provider; ((void) data); *olen = 0; - if (CryptAcquireContext(&provider, NULL, NULL, - PROV_RSA_FULL, CRYPT_VERIFYCONTEXT) == FALSE) { - return MBEDTLS_ERR_ENTROPY_SOURCE_FAILED; - } + /* + * BCryptGenRandom takes ULONG for size, which is smaller than size_t on + * 64-bit Windows platforms. Extract entropy in chunks of len (dependent + * on ULONG_MAX) size. + */ + while (len != 0) { + unsigned long ulong_bytes = + (len > ULONG_MAX) ? ULONG_MAX : (unsigned long) len; + + if (!BCRYPT_SUCCESS(BCryptGenRandom(NULL, output, ulong_bytes, + BCRYPT_USE_SYSTEM_PREFERRED_RNG))) { + return MBEDTLS_ERR_ENTROPY_SOURCE_FAILED; + } - if (CryptGenRandom(provider, (DWORD) len, output) == FALSE) { - CryptReleaseContext(provider, 0); - return MBEDTLS_ERR_ENTROPY_SOURCE_FAILED; + *olen += ulong_bytes; + len -= ulong_bytes; } - CryptReleaseContext(provider, 0); - *olen = len; - return 0; } #else /* _WIN32 && !EFIX64 && !EFI32 */ @@ -101,7 +88,7 @@ static int getrandom_wrapper(void *buf, size_t buflen, unsigned int flags) memset(buf, 0, buflen); #endif #endif - return syscall(SYS_getrandom, buf, buflen, flags); + return (int) syscall(SYS_getrandom, buf, buflen, flags); } #endif /* SYS_getrandom */ #endif /* __linux__ || __midipix__ */ @@ -115,7 +102,7 @@ static int getrandom_wrapper(void *buf, size_t buflen, unsigned int flags) #define HAVE_GETRANDOM static int getrandom_wrapper(void *buf, size_t buflen, unsigned int flags) { - return getrandom(buf, buflen, flags); + return (int) getrandom(buf, buflen, flags); } #endif /* (__FreeBSD__ && __FreeBSD_version >= 1200000) || (__DragonFly__ && __DragonFly_version >= 500700) */ @@ -169,7 +156,7 @@ int mbedtls_platform_entropy_poll(void *data, #if defined(HAVE_GETRANDOM) ret = getrandom_wrapper(output, len, 0); if (ret >= 0) { - *olen = ret; + *olen = (size_t) ret; return 0; } else if (errno != ENOSYS) { return MBEDTLS_ERR_ENTROPY_SOURCE_FAILED; @@ -196,6 +183,9 @@ int mbedtls_platform_entropy_poll(void *data, return MBEDTLS_ERR_ENTROPY_SOURCE_FAILED; } + /* Ensure no stdio buffering of secrets, as such buffers cannot be wiped. */ + mbedtls_setbuf(file, NULL); + read_len = fread(output, 1, len, file); if (read_len != len) { fclose(file); @@ -211,60 +201,6 @@ int mbedtls_platform_entropy_poll(void *data, #endif /* _WIN32 && !EFIX64 && !EFI32 */ #endif /* !MBEDTLS_NO_PLATFORM_ENTROPY */ -#if defined(MBEDTLS_TEST_NULL_ENTROPY) -int mbedtls_null_entropy_poll(void *data, - unsigned char *output, size_t len, size_t *olen) -{ - ((void) data); - ((void) output); - - *olen = 0; - if (len < sizeof(unsigned char)) { - return 0; - } - - output[0] = 0; - *olen = sizeof(unsigned char); - return 0; -} -#endif - -#if defined(MBEDTLS_TIMING_C) -int mbedtls_hardclock_poll(void *data, - unsigned char *output, size_t len, size_t *olen) -{ - unsigned long timer = mbedtls_timing_hardclock(); - ((void) data); - *olen = 0; - - if (len < sizeof(unsigned long)) { - return 0; - } - - memcpy(output, &timer, sizeof(unsigned long)); - *olen = sizeof(unsigned long); - - return 0; -} -#endif /* MBEDTLS_TIMING_C */ - -#if defined(MBEDTLS_HAVEGE_C) -int mbedtls_havege_poll(void *data, - unsigned char *output, size_t len, size_t *olen) -{ - mbedtls_havege_state *hs = (mbedtls_havege_state *) data; - *olen = 0; - - if (mbedtls_havege_random(hs, output, len) != 0) { - return MBEDTLS_ERR_ENTROPY_SOURCE_FAILED; - } - - *olen = len; - - return 0; -} -#endif /* MBEDTLS_HAVEGE_C */ - #if defined(MBEDTLS_ENTROPY_NV_SEED) int mbedtls_nv_seed_poll(void *data, unsigned char *output, size_t len, size_t *olen) diff --git a/vendor/mbedtls/library/entropy_poll.h b/vendor/mbedtls/library/entropy_poll.h new file mode 100644 index 0000000000..6b4aec03e1 --- /dev/null +++ b/vendor/mbedtls/library/entropy_poll.h @@ -0,0 +1,64 @@ +/** + * \file entropy_poll.h + * + * \brief Platform-specific and custom entropy polling functions + */ +/* + * Copyright The Mbed TLS Contributors + * SPDX-License-Identifier: Apache-2.0 OR GPL-2.0-or-later + */ +#ifndef MBEDTLS_ENTROPY_POLL_H +#define MBEDTLS_ENTROPY_POLL_H + +#include "mbedtls/build_info.h" + +#include + +#ifdef __cplusplus +extern "C" { +#endif + +/* + * Default thresholds for built-in sources, in bytes + */ +#define MBEDTLS_ENTROPY_MIN_PLATFORM 32 /**< Minimum for platform source */ +#if !defined(MBEDTLS_ENTROPY_MIN_HARDWARE) +#define MBEDTLS_ENTROPY_MIN_HARDWARE 32 /**< Minimum for the hardware source */ +#endif + +#if !defined(MBEDTLS_NO_PLATFORM_ENTROPY) +/** + * \brief Platform-specific entropy poll callback + */ +int mbedtls_platform_entropy_poll(void *data, + unsigned char *output, size_t len, size_t *olen); +#endif + +#if defined(MBEDTLS_ENTROPY_HARDWARE_ALT) +/** + * \brief Entropy poll callback for a hardware source + * + * \warning This is not provided by Mbed TLS! + * See \c MBEDTLS_ENTROPY_HARDWARE_ALT in mbedtls_config.h. + * + * \note This must accept NULL as its first argument. + */ +int mbedtls_hardware_poll(void *data, + unsigned char *output, size_t len, size_t *olen); +#endif + +#if defined(MBEDTLS_ENTROPY_NV_SEED) +/** + * \brief Entropy poll callback for a non-volatile seed file + * + * \note This must accept NULL as its first argument. + */ +int mbedtls_nv_seed_poll(void *data, + unsigned char *output, size_t len, size_t *olen); +#endif + +#ifdef __cplusplus +} +#endif + +#endif /* entropy_poll.h */ diff --git a/vendor/mbedtls/library/error.c b/vendor/mbedtls/library/error.c index 6aa4b92198..84b637aeb2 100644 --- a/vendor/mbedtls/library/error.c +++ b/vendor/mbedtls/library/error.c @@ -2,19 +2,7 @@ * Error message information * * Copyright The Mbed TLS Contributors - * SPDX-License-Identifier: Apache-2.0 - * - * Licensed under the Apache License, Version 2.0 (the "License"); you may - * not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT - * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. + * SPDX-License-Identifier: Apache-2.0 OR GPL-2.0-or-later */ #include "common.h" @@ -34,10 +22,6 @@ #include "mbedtls/aes.h" #endif -#if defined(MBEDTLS_ARC4_C) -#include "mbedtls/arc4.h" -#endif - #if defined(MBEDTLS_ARIA_C) #include "mbedtls/aria.h" #endif @@ -54,10 +38,6 @@ #include "mbedtls/bignum.h" #endif -#if defined(MBEDTLS_BLOWFISH_C) -#include "mbedtls/blowfish.h" -#endif - #if defined(MBEDTLS_CAMELLIA_C) #include "mbedtls/camellia.h" #endif @@ -78,10 +58,6 @@ #include "mbedtls/cipher.h" #endif -#if defined(MBEDTLS_CMAC_C) -#include "mbedtls/cmac.h" -#endif - #if defined(MBEDTLS_CTR_DRBG_C) #include "mbedtls/ctr_drbg.h" #endif @@ -106,6 +82,10 @@ #include "mbedtls/error.h" #endif +#if defined(MBEDTLS_PLATFORM_C) +#include "mbedtls/platform.h" +#endif + #if defined(MBEDTLS_GCM_C) #include "mbedtls/gcm.h" #endif @@ -118,20 +98,12 @@ #include "mbedtls/hmac_drbg.h" #endif -#if defined(MBEDTLS_MD_C) -#include "mbedtls/md.h" -#endif - -#if defined(MBEDTLS_MD2_C) -#include "mbedtls/md2.h" -#endif - -#if defined(MBEDTLS_MD4_C) -#include "mbedtls/md4.h" +#if defined(MBEDTLS_LMS_C) +#include "mbedtls/lms.h" #endif -#if defined(MBEDTLS_MD5_C) -#include "mbedtls/md5.h" +#if defined(MBEDTLS_MD_C) +#include "mbedtls/md.h" #endif #if defined(MBEDTLS_NET_C) @@ -142,10 +114,6 @@ #include "mbedtls/oid.h" #endif -#if defined(MBEDTLS_PADLOCK_C) -#include "mbedtls/padlock.h" -#endif - #if defined(MBEDTLS_PEM_PARSE_C) || defined(MBEDTLS_PEM_WRITE_C) #include "mbedtls/pem.h" #endif @@ -162,18 +130,14 @@ #include "mbedtls/pkcs5.h" #endif -#if defined(MBEDTLS_PLATFORM_C) -#include "mbedtls/platform.h" +#if defined(MBEDTLS_PKCS7_C) +#include "mbedtls/pkcs7.h" #endif #if defined(MBEDTLS_POLY1305_C) #include "mbedtls/poly1305.h" #endif -#if defined(MBEDTLS_RIPEMD160_C) -#include "mbedtls/ripemd160.h" -#endif - #if defined(MBEDTLS_RSA_C) #include "mbedtls/rsa.h" #endif @@ -186,6 +150,10 @@ #include "mbedtls/sha256.h" #endif +#if defined(MBEDTLS_SHA3_C) +#include "mbedtls/sha3.h" +#endif + #if defined(MBEDTLS_SHA512_C) #include "mbedtls/sha512.h" #endif @@ -202,10 +170,6 @@ #include "mbedtls/x509.h" #endif -#if defined(MBEDTLS_XTEA_C) -#include "mbedtls/xtea.h" -#endif - const char *mbedtls_high_level_strerr(int error_code) { @@ -235,8 +199,6 @@ const char *mbedtls_high_level_strerr(int error_code) return( "CIPHER - Authentication failed (for AEAD modes)" ); case -(MBEDTLS_ERR_CIPHER_INVALID_CONTEXT): return( "CIPHER - The context is invalid. For example, because it was freed" ); - case -(MBEDTLS_ERR_CIPHER_HW_ACCEL_FAILED): - return( "CIPHER - Cipher hardware accelerator failed" ); #endif /* MBEDTLS_CIPHER_C */ #if defined(MBEDTLS_DHM_C) @@ -258,8 +220,6 @@ const char *mbedtls_high_level_strerr(int error_code) return( "DHM - Allocation of memory failed" ); case -(MBEDTLS_ERR_DHM_FILE_IO_ERROR): return( "DHM - Read or write of file failed" ); - case -(MBEDTLS_ERR_DHM_HW_ACCEL_FAILED): - return( "DHM - DHM hardware accelerator failed" ); case -(MBEDTLS_ERR_DHM_SET_GROUP_FAILED): return( "DHM - Setting the modulus and generator failed" ); #endif /* MBEDTLS_DHM_C */ @@ -281,8 +241,6 @@ const char *mbedtls_high_level_strerr(int error_code) return( "ECP - Invalid private or public key" ); case -(MBEDTLS_ERR_ECP_SIG_LEN_MISMATCH): return( "ECP - The buffer contains a valid signature followed by more data" ); - case -(MBEDTLS_ERR_ECP_HW_ACCEL_FAILED): - return( "ECP - The ECP hardware accelerator failed" ); case -(MBEDTLS_ERR_ECP_IN_PROGRESS): return( "ECP - Operation in progress, call again with the same parameters to continue" ); #endif /* MBEDTLS_ECP_C */ @@ -296,8 +254,6 @@ const char *mbedtls_high_level_strerr(int error_code) return( "MD - Failed to allocate memory" ); case -(MBEDTLS_ERR_MD_FILE_IO_ERROR): return( "MD - Opening or reading of file failed" ); - case -(MBEDTLS_ERR_MD_HW_ACCEL_FAILED): - return( "MD - MD hardware accelerator failed" ); #endif /* MBEDTLS_MD_C */ #if defined(MBEDTLS_PEM_PARSE_C) || defined(MBEDTLS_PEM_WRITE_C) @@ -350,8 +306,8 @@ const char *mbedtls_high_level_strerr(int error_code) return( "PK - Unavailable feature, e.g. RSA disabled for RSA key" ); case -(MBEDTLS_ERR_PK_SIG_LEN_MISMATCH): return( "PK - The buffer contains a valid signature followed by more data" ); - case -(MBEDTLS_ERR_PK_HW_ACCEL_FAILED): - return( "PK - PK hardware accelerator failed" ); + case -(MBEDTLS_ERR_PK_BUFFER_TOO_SMALL): + return( "PK - The output buffer is too small" ); #endif /* MBEDTLS_PK_C */ #if defined(MBEDTLS_PKCS12_C) @@ -376,6 +332,33 @@ const char *mbedtls_high_level_strerr(int error_code) return( "PKCS5 - Given private key password does not allow for correct decryption" ); #endif /* MBEDTLS_PKCS5_C */ +#if defined(MBEDTLS_PKCS7_C) + case -(MBEDTLS_ERR_PKCS7_INVALID_FORMAT): + return( "PKCS7 - The format is invalid, e.g. different type expected" ); + case -(MBEDTLS_ERR_PKCS7_FEATURE_UNAVAILABLE): + return( "PKCS7 - Unavailable feature, e.g. anything other than signed data" ); + case -(MBEDTLS_ERR_PKCS7_INVALID_VERSION): + return( "PKCS7 - The PKCS #7 version element is invalid or cannot be parsed" ); + case -(MBEDTLS_ERR_PKCS7_INVALID_CONTENT_INFO): + return( "PKCS7 - The PKCS #7 content info is invalid or cannot be parsed" ); + case -(MBEDTLS_ERR_PKCS7_INVALID_ALG): + return( "PKCS7 - The algorithm tag or value is invalid or cannot be parsed" ); + case -(MBEDTLS_ERR_PKCS7_INVALID_CERT): + return( "PKCS7 - The certificate tag or value is invalid or cannot be parsed" ); + case -(MBEDTLS_ERR_PKCS7_INVALID_SIGNATURE): + return( "PKCS7 - Error parsing the signature" ); + case -(MBEDTLS_ERR_PKCS7_INVALID_SIGNER_INFO): + return( "PKCS7 - Error parsing the signer's info" ); + case -(MBEDTLS_ERR_PKCS7_BAD_INPUT_DATA): + return( "PKCS7 - Input invalid" ); + case -(MBEDTLS_ERR_PKCS7_ALLOC_FAILED): + return( "PKCS7 - Allocation of memory failed" ); + case -(MBEDTLS_ERR_PKCS7_VERIFY_FAIL): + return( "PKCS7 - Verification Failed" ); + case -(MBEDTLS_ERR_PKCS7_CERT_DATE_INVALID): + return( "PKCS7 - The PKCS #7 date issued/expired dates are invalid" ); +#endif /* MBEDTLS_PKCS7_C */ + #if defined(MBEDTLS_RSA_C) case -(MBEDTLS_ERR_RSA_BAD_INPUT_DATA): return( "RSA - Bad input parameters to function" ); @@ -395,13 +378,11 @@ const char *mbedtls_high_level_strerr(int error_code) return( "RSA - The output buffer for decryption is not large enough" ); case -(MBEDTLS_ERR_RSA_RNG_FAILED): return( "RSA - The random generator failed to generate non-zeros" ); - case -(MBEDTLS_ERR_RSA_UNSUPPORTED_OPERATION): - return( "RSA - The implementation does not offer the requested operation, for example, because of security violations or lack of functionality" ); - case -(MBEDTLS_ERR_RSA_HW_ACCEL_FAILED): - return( "RSA - RSA hardware accelerator failed" ); #endif /* MBEDTLS_RSA_C */ #if defined(MBEDTLS_SSL_TLS_C) + case -(MBEDTLS_ERR_SSL_CRYPTO_IN_PROGRESS): + return( "SSL - A cryptographic operation is in progress. Try again later" ); case -(MBEDTLS_ERR_SSL_FEATURE_UNAVAILABLE): return( "SSL - The requested feature is not available" ); case -(MBEDTLS_ERR_SSL_BAD_INPUT_DATA): @@ -412,18 +393,16 @@ const char *mbedtls_high_level_strerr(int error_code) return( "SSL - An invalid SSL record was received" ); case -(MBEDTLS_ERR_SSL_CONN_EOF): return( "SSL - The connection indicated an EOF" ); - case -(MBEDTLS_ERR_SSL_UNKNOWN_CIPHER): - return( "SSL - An unknown cipher was received" ); - case -(MBEDTLS_ERR_SSL_NO_CIPHER_CHOSEN): - return( "SSL - The server has no ciphersuites in common with the client" ); + case -(MBEDTLS_ERR_SSL_DECODE_ERROR): + return( "SSL - A message could not be parsed due to a syntactic error" ); case -(MBEDTLS_ERR_SSL_NO_RNG): return( "SSL - No RNG was provided to the SSL module" ); case -(MBEDTLS_ERR_SSL_NO_CLIENT_CERTIFICATE): return( "SSL - No client certification received from the client, but required by the authentication mode" ); - case -(MBEDTLS_ERR_SSL_CERTIFICATE_TOO_LARGE): - return( "SSL - Our own certificate(s) is/are too large to send in an SSL message" ); - case -(MBEDTLS_ERR_SSL_CERTIFICATE_REQUIRED): - return( "SSL - The own certificate is not set, but needed by the server" ); + case -(MBEDTLS_ERR_SSL_UNSUPPORTED_EXTENSION): + return( "SSL - Client received an extended server hello containing an unsupported extension" ); + case -(MBEDTLS_ERR_SSL_NO_APPLICATION_PROTOCOL): + return( "SSL - No ALPN protocols supported that the client advertises" ); case -(MBEDTLS_ERR_SSL_PRIVATE_KEY_REQUIRED): return( "SSL - The own private key or pre-shared key is not set, but needed" ); case -(MBEDTLS_ERR_SSL_CA_CHAIN_REQUIRED): @@ -432,46 +411,32 @@ const char *mbedtls_high_level_strerr(int error_code) return( "SSL - An unexpected message was received from our peer" ); case -(MBEDTLS_ERR_SSL_FATAL_ALERT_MESSAGE): return( "SSL - A fatal alert message was received from our peer" ); - case -(MBEDTLS_ERR_SSL_PEER_VERIFY_FAILED): - return( "SSL - Verification of our peer failed" ); + case -(MBEDTLS_ERR_SSL_UNRECOGNIZED_NAME): + return( "SSL - No server could be identified matching the client's SNI" ); case -(MBEDTLS_ERR_SSL_PEER_CLOSE_NOTIFY): return( "SSL - The peer notified us that the connection is going to be closed" ); - case -(MBEDTLS_ERR_SSL_BAD_HS_CLIENT_HELLO): - return( "SSL - Processing of the ClientHello handshake message failed" ); - case -(MBEDTLS_ERR_SSL_BAD_HS_SERVER_HELLO): - return( "SSL - Processing of the ServerHello handshake message failed" ); - case -(MBEDTLS_ERR_SSL_BAD_HS_CERTIFICATE): + case -(MBEDTLS_ERR_SSL_BAD_CERTIFICATE): return( "SSL - Processing of the Certificate handshake message failed" ); - case -(MBEDTLS_ERR_SSL_BAD_HS_CERTIFICATE_REQUEST): - return( "SSL - Processing of the CertificateRequest handshake message failed" ); - case -(MBEDTLS_ERR_SSL_BAD_HS_SERVER_KEY_EXCHANGE): - return( "SSL - Processing of the ServerKeyExchange handshake message failed" ); - case -(MBEDTLS_ERR_SSL_BAD_HS_SERVER_HELLO_DONE): - return( "SSL - Processing of the ServerHelloDone handshake message failed" ); - case -(MBEDTLS_ERR_SSL_BAD_HS_CLIENT_KEY_EXCHANGE): - return( "SSL - Processing of the ClientKeyExchange handshake message failed" ); - case -(MBEDTLS_ERR_SSL_BAD_HS_CLIENT_KEY_EXCHANGE_RP): - return( "SSL - Processing of the ClientKeyExchange handshake message failed in DHM / ECDH Read Public" ); - case -(MBEDTLS_ERR_SSL_BAD_HS_CLIENT_KEY_EXCHANGE_CS): - return( "SSL - Processing of the ClientKeyExchange handshake message failed in DHM / ECDH Calculate Secret" ); - case -(MBEDTLS_ERR_SSL_BAD_HS_CERTIFICATE_VERIFY): - return( "SSL - Processing of the CertificateVerify handshake message failed" ); - case -(MBEDTLS_ERR_SSL_BAD_HS_CHANGE_CIPHER_SPEC): - return( "SSL - Processing of the ChangeCipherSpec handshake message failed" ); - case -(MBEDTLS_ERR_SSL_BAD_HS_FINISHED): - return( "SSL - Processing of the Finished handshake message failed" ); + case -(MBEDTLS_ERR_SSL_RECEIVED_NEW_SESSION_TICKET): + return( "SSL - * Received NewSessionTicket Post Handshake Message. This error code is experimental and may be changed or removed without notice" ); + case -(MBEDTLS_ERR_SSL_CANNOT_READ_EARLY_DATA): + return( "SSL - Not possible to read early data" ); + case -(MBEDTLS_ERR_SSL_RECEIVED_EARLY_DATA): + return( "SSL - * Early data has been received as part of an on-going handshake. This error code can be returned only on server side if and only if early data has been enabled by means of the mbedtls_ssl_conf_early_data() API. This error code can then be returned by mbedtls_ssl_handshake(), mbedtls_ssl_handshake_step(), mbedtls_ssl_read() or mbedtls_ssl_write() if early data has been received as part of the handshake sequence they triggered. To read the early data, call mbedtls_ssl_read_early_data()" ); + case -(MBEDTLS_ERR_SSL_CANNOT_WRITE_EARLY_DATA): + return( "SSL - Not possible to write early data" ); + case -(MBEDTLS_ERR_SSL_CACHE_ENTRY_NOT_FOUND): + return( "SSL - Cache entry not found" ); case -(MBEDTLS_ERR_SSL_ALLOC_FAILED): return( "SSL - Memory allocation failed" ); case -(MBEDTLS_ERR_SSL_HW_ACCEL_FAILED): return( "SSL - Hardware acceleration function returned with error" ); case -(MBEDTLS_ERR_SSL_HW_ACCEL_FALLTHROUGH): return( "SSL - Hardware acceleration function skipped / left alone data" ); - case -(MBEDTLS_ERR_SSL_COMPRESSION_FAILED): - return( "SSL - Processing of the compression / decompression failed" ); - case -(MBEDTLS_ERR_SSL_BAD_HS_PROTOCOL_VERSION): + case -(MBEDTLS_ERR_SSL_BAD_PROTOCOL_VERSION): return( "SSL - Handshake protocol not within min/max boundaries" ); - case -(MBEDTLS_ERR_SSL_BAD_HS_NEW_SESSION_TICKET): - return( "SSL - Processing of the NewSessionTicket handshake message failed" ); + case -(MBEDTLS_ERR_SSL_HANDSHAKE_FAILURE): + return( "SSL - The handshake negotiation failed" ); case -(MBEDTLS_ERR_SSL_SESSION_TICKET_EXPIRED): return( "SSL - Session ticket has expired" ); case -(MBEDTLS_ERR_SSL_PK_TYPE_MISMATCH): @@ -488,8 +453,6 @@ const char *mbedtls_high_level_strerr(int error_code) return( "SSL - DTLS client must retry for hello verification" ); case -(MBEDTLS_ERR_SSL_BUFFER_TOO_SMALL): return( "SSL - A buffer is too small to receive or write a message" ); - case -(MBEDTLS_ERR_SSL_NO_USABLE_CIPHERSUITE): - return( "SSL - None of the common ciphersuites is usable (eg, no suitable certificate, see debug messages)" ); case -(MBEDTLS_ERR_SSL_WANT_READ): return( "SSL - No data of requested type currently available on underlying transport" ); case -(MBEDTLS_ERR_SSL_WANT_WRITE): @@ -502,8 +465,8 @@ const char *mbedtls_high_level_strerr(int error_code) return( "SSL - Record header looks valid but is not expected" ); case -(MBEDTLS_ERR_SSL_NON_FATAL): return( "SSL - The alert message received indicates a non-fatal error" ); - case -(MBEDTLS_ERR_SSL_INVALID_VERIFY_HASH): - return( "SSL - Couldn't set the hash for verifying CertificateVerify" ); + case -(MBEDTLS_ERR_SSL_ILLEGAL_PARAMETER): + return( "SSL - A field in a message was incorrect or inconsistent with other fields" ); case -(MBEDTLS_ERR_SSL_CONTINUE_PROCESSING): return( "SSL - Internal-only message signaling that further message-processing should be done" ); case -(MBEDTLS_ERR_SSL_ASYNC_IN_PROGRESS): @@ -514,12 +477,8 @@ const char *mbedtls_high_level_strerr(int error_code) return( "SSL - An encrypted DTLS-frame with an unexpected CID was received" ); case -(MBEDTLS_ERR_SSL_VERSION_MISMATCH): return( "SSL - An operation failed due to an unexpected version or configuration" ); - case -(MBEDTLS_ERR_SSL_CRYPTO_IN_PROGRESS): - return( "SSL - A cryptographic operation is in progress. Try again later" ); case -(MBEDTLS_ERR_SSL_BAD_CONFIG): return( "SSL - Invalid value in SSL config" ); - case -(MBEDTLS_ERR_SSL_CACHE_ENTRY_NOT_FOUND): - return( "SSL - Cache entry not found" ); #endif /* MBEDTLS_SSL_TLS_C */ #if defined(MBEDTLS_X509_USE_C) || defined(MBEDTLS_X509_CREATE_C) @@ -593,26 +552,13 @@ const char *mbedtls_low_level_strerr(int error_code) return( "AES - Invalid data input length" ); case -(MBEDTLS_ERR_AES_BAD_INPUT_DATA): return( "AES - Invalid input data" ); - case -(MBEDTLS_ERR_AES_FEATURE_UNAVAILABLE): - return( "AES - Feature not available. For example, an unsupported AES key size" ); - case -(MBEDTLS_ERR_AES_HW_ACCEL_FAILED): - return( "AES - AES hardware accelerator failed" ); #endif /* MBEDTLS_AES_C */ -#if defined(MBEDTLS_ARC4_C) - case -(MBEDTLS_ERR_ARC4_HW_ACCEL_FAILED): - return( "ARC4 - ARC4 hardware accelerator failed" ); -#endif /* MBEDTLS_ARC4_C */ - #if defined(MBEDTLS_ARIA_C) case -(MBEDTLS_ERR_ARIA_BAD_INPUT_DATA): return( "ARIA - Bad input data" ); case -(MBEDTLS_ERR_ARIA_INVALID_INPUT_LENGTH): return( "ARIA - Invalid data input length" ); - case -(MBEDTLS_ERR_ARIA_FEATURE_UNAVAILABLE): - return( "ARIA - Feature not available. For example, an unsupported ARIA key size" ); - case -(MBEDTLS_ERR_ARIA_HW_ACCEL_FAILED): - return( "ARIA - ARIA hardware accelerator failed" ); #endif /* MBEDTLS_ARIA_C */ #if defined(MBEDTLS_ASN1_PARSE_C) @@ -658,22 +604,11 @@ const char *mbedtls_low_level_strerr(int error_code) return( "BIGNUM - Memory allocation failed" ); #endif /* MBEDTLS_BIGNUM_C */ -#if defined(MBEDTLS_BLOWFISH_C) - case -(MBEDTLS_ERR_BLOWFISH_BAD_INPUT_DATA): - return( "BLOWFISH - Bad input data" ); - case -(MBEDTLS_ERR_BLOWFISH_INVALID_INPUT_LENGTH): - return( "BLOWFISH - Invalid data input length" ); - case -(MBEDTLS_ERR_BLOWFISH_HW_ACCEL_FAILED): - return( "BLOWFISH - Blowfish hardware accelerator failed" ); -#endif /* MBEDTLS_BLOWFISH_C */ - #if defined(MBEDTLS_CAMELLIA_C) case -(MBEDTLS_ERR_CAMELLIA_BAD_INPUT_DATA): return( "CAMELLIA - Bad input data" ); case -(MBEDTLS_ERR_CAMELLIA_INVALID_INPUT_LENGTH): return( "CAMELLIA - Invalid data input length" ); - case -(MBEDTLS_ERR_CAMELLIA_HW_ACCEL_FAILED): - return( "CAMELLIA - Camellia hardware accelerator failed" ); #endif /* MBEDTLS_CAMELLIA_C */ #if defined(MBEDTLS_CCM_C) @@ -681,17 +616,11 @@ const char *mbedtls_low_level_strerr(int error_code) return( "CCM - Bad input parameters to the function" ); case -(MBEDTLS_ERR_CCM_AUTH_FAILED): return( "CCM - Authenticated decryption failed" ); - case -(MBEDTLS_ERR_CCM_HW_ACCEL_FAILED): - return( "CCM - CCM hardware accelerator failed" ); #endif /* MBEDTLS_CCM_C */ #if defined(MBEDTLS_CHACHA20_C) case -(MBEDTLS_ERR_CHACHA20_BAD_INPUT_DATA): return( "CHACHA20 - Invalid input parameter(s)" ); - case -(MBEDTLS_ERR_CHACHA20_FEATURE_UNAVAILABLE): - return( "CHACHA20 - Feature not available. For example, s part of the API is not implemented" ); - case -(MBEDTLS_ERR_CHACHA20_HW_ACCEL_FAILED): - return( "CHACHA20 - Chacha20 hardware accelerator failed" ); #endif /* MBEDTLS_CHACHA20_C */ #if defined(MBEDTLS_CHACHAPOLY_C) @@ -701,11 +630,6 @@ const char *mbedtls_low_level_strerr(int error_code) return( "CHACHAPOLY - Authenticated decryption failed: data was not authentic" ); #endif /* MBEDTLS_CHACHAPOLY_C */ -#if defined(MBEDTLS_CMAC_C) - case -(MBEDTLS_ERR_CMAC_HW_ACCEL_FAILED): - return( "CMAC - CMAC hardware accelerator failed" ); -#endif /* MBEDTLS_CMAC_C */ - #if defined(MBEDTLS_CTR_DRBG_C) case -(MBEDTLS_ERR_CTR_DRBG_ENTROPY_SOURCE_FAILED): return( "CTR_DRBG - The entropy source failed" ); @@ -720,8 +644,6 @@ const char *mbedtls_low_level_strerr(int error_code) #if defined(MBEDTLS_DES_C) case -(MBEDTLS_ERR_DES_INVALID_INPUT_LENGTH): return( "DES - The data input has an invalid length" ); - case -(MBEDTLS_ERR_DES_HW_ACCEL_FAILED): - return( "DES - DES hardware accelerator failed" ); #endif /* MBEDTLS_DES_C */ #if defined(MBEDTLS_ENTROPY_C) @@ -744,13 +666,20 @@ const char *mbedtls_low_level_strerr(int error_code) return( "ERROR - This is a bug in the library" ); #endif /* MBEDTLS_ERROR_C */ +#if defined(MBEDTLS_PLATFORM_C) + case -(MBEDTLS_ERR_PLATFORM_HW_ACCEL_FAILED): + return( "PLATFORM - Hardware accelerator failed" ); + case -(MBEDTLS_ERR_PLATFORM_FEATURE_UNSUPPORTED): + return( "PLATFORM - The requested feature is not supported by the platform" ); +#endif /* MBEDTLS_PLATFORM_C */ + #if defined(MBEDTLS_GCM_C) case -(MBEDTLS_ERR_GCM_AUTH_FAILED): return( "GCM - Authenticated decryption failed" ); - case -(MBEDTLS_ERR_GCM_HW_ACCEL_FAILED): - return( "GCM - GCM hardware accelerator failed" ); case -(MBEDTLS_ERR_GCM_BAD_INPUT): return( "GCM - Bad input parameters to function" ); + case -(MBEDTLS_ERR_GCM_BUFFER_TOO_SMALL): + return( "GCM - An output buffer is too small" ); #endif /* MBEDTLS_GCM_C */ #if defined(MBEDTLS_HKDF_C) @@ -769,20 +698,18 @@ const char *mbedtls_low_level_strerr(int error_code) return( "HMAC_DRBG - The entropy source failed" ); #endif /* MBEDTLS_HMAC_DRBG_C */ -#if defined(MBEDTLS_MD2_C) - case -(MBEDTLS_ERR_MD2_HW_ACCEL_FAILED): - return( "MD2 - MD2 hardware accelerator failed" ); -#endif /* MBEDTLS_MD2_C */ - -#if defined(MBEDTLS_MD4_C) - case -(MBEDTLS_ERR_MD4_HW_ACCEL_FAILED): - return( "MD4 - MD4 hardware accelerator failed" ); -#endif /* MBEDTLS_MD4_C */ - -#if defined(MBEDTLS_MD5_C) - case -(MBEDTLS_ERR_MD5_HW_ACCEL_FAILED): - return( "MD5 - MD5 hardware accelerator failed" ); -#endif /* MBEDTLS_MD5_C */ +#if defined(MBEDTLS_LMS_C) + case -(MBEDTLS_ERR_LMS_BAD_INPUT_DATA): + return( "LMS - Bad data has been input to an LMS function" ); + case -(MBEDTLS_ERR_LMS_OUT_OF_PRIVATE_KEYS): + return( "LMS - Specified LMS key has utilised all of its private keys" ); + case -(MBEDTLS_ERR_LMS_VERIFY_FAILED): + return( "LMS - LMS signature verification failed" ); + case -(MBEDTLS_ERR_LMS_ALLOC_FAILED): + return( "LMS - LMS failed to allocate space for a private key" ); + case -(MBEDTLS_ERR_LMS_BUFFER_TOO_SMALL): + return( "LMS - Input/output buffer is too small to contain requited data" ); +#endif /* MBEDTLS_LMS_C */ #if defined(MBEDTLS_NET_C) case -(MBEDTLS_ERR_NET_SOCKET_FAILED): @@ -820,68 +747,37 @@ const char *mbedtls_low_level_strerr(int error_code) return( "OID - output buffer is too small" ); #endif /* MBEDTLS_OID_C */ -#if defined(MBEDTLS_PADLOCK_C) - case -(MBEDTLS_ERR_PADLOCK_DATA_MISALIGNED): - return( "PADLOCK - Input data should be aligned" ); -#endif /* MBEDTLS_PADLOCK_C */ - -#if defined(MBEDTLS_PLATFORM_C) - case -(MBEDTLS_ERR_PLATFORM_HW_ACCEL_FAILED): - return( "PLATFORM - Hardware accelerator failed" ); - case -(MBEDTLS_ERR_PLATFORM_FEATURE_UNSUPPORTED): - return( "PLATFORM - The requested feature is not supported by the platform" ); -#endif /* MBEDTLS_PLATFORM_C */ - #if defined(MBEDTLS_POLY1305_C) case -(MBEDTLS_ERR_POLY1305_BAD_INPUT_DATA): return( "POLY1305 - Invalid input parameter(s)" ); - case -(MBEDTLS_ERR_POLY1305_FEATURE_UNAVAILABLE): - return( "POLY1305 - Feature not available. For example, s part of the API is not implemented" ); - case -(MBEDTLS_ERR_POLY1305_HW_ACCEL_FAILED): - return( "POLY1305 - Poly1305 hardware accelerator failed" ); #endif /* MBEDTLS_POLY1305_C */ -#if defined(MBEDTLS_RIPEMD160_C) - case -(MBEDTLS_ERR_RIPEMD160_HW_ACCEL_FAILED): - return( "RIPEMD160 - RIPEMD160 hardware accelerator failed" ); -#endif /* MBEDTLS_RIPEMD160_C */ - #if defined(MBEDTLS_SHA1_C) - case -(MBEDTLS_ERR_SHA1_HW_ACCEL_FAILED): - return( "SHA1 - SHA-1 hardware accelerator failed" ); case -(MBEDTLS_ERR_SHA1_BAD_INPUT_DATA): return( "SHA1 - SHA-1 input data was malformed" ); #endif /* MBEDTLS_SHA1_C */ #if defined(MBEDTLS_SHA256_C) - case -(MBEDTLS_ERR_SHA256_HW_ACCEL_FAILED): - return( "SHA256 - SHA-256 hardware accelerator failed" ); case -(MBEDTLS_ERR_SHA256_BAD_INPUT_DATA): return( "SHA256 - SHA-256 input data was malformed" ); #endif /* MBEDTLS_SHA256_C */ +#if defined(MBEDTLS_SHA3_C) + case -(MBEDTLS_ERR_SHA3_BAD_INPUT_DATA): + return( "SHA3 - SHA-3 input data was malformed" ); +#endif /* MBEDTLS_SHA3_C */ + #if defined(MBEDTLS_SHA512_C) - case -(MBEDTLS_ERR_SHA512_HW_ACCEL_FAILED): - return( "SHA512 - SHA-512 hardware accelerator failed" ); case -(MBEDTLS_ERR_SHA512_BAD_INPUT_DATA): return( "SHA512 - SHA-512 input data was malformed" ); #endif /* MBEDTLS_SHA512_C */ #if defined(MBEDTLS_THREADING_C) - case -(MBEDTLS_ERR_THREADING_FEATURE_UNAVAILABLE): - return( "THREADING - The selected feature is not available" ); case -(MBEDTLS_ERR_THREADING_BAD_INPUT_DATA): return( "THREADING - Bad input parameters to function" ); case -(MBEDTLS_ERR_THREADING_MUTEX_ERROR): return( "THREADING - Locking / unlocking / free failed with error code" ); #endif /* MBEDTLS_THREADING_C */ - -#if defined(MBEDTLS_XTEA_C) - case -(MBEDTLS_ERR_XTEA_INVALID_INPUT_LENGTH): - return( "XTEA - The data input has an invalid length" ); - case -(MBEDTLS_ERR_XTEA_HW_ACCEL_FAILED): - return( "XTEA - XTEA hardware accelerator failed" ); -#endif /* MBEDTLS_XTEA_C */ /* End Auto-Generated Code. */ default: diff --git a/vendor/mbedtls/library/gcm.c b/vendor/mbedtls/library/gcm.c index 71e7b2e9bc..5dfac2349c 100644 --- a/vendor/mbedtls/library/gcm.c +++ b/vendor/mbedtls/library/gcm.c @@ -2,19 +2,7 @@ * NIST SP800-38D compliant GCM implementation * * Copyright The Mbed TLS Contributors - * SPDX-License-Identifier: Apache-2.0 - * - * Licensed under the Apache License, Version 2.0 (the "License"); you may - * not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT - * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. + * SPDX-License-Identifier: Apache-2.0 OR GPL-2.0-or-later */ /* @@ -37,29 +25,69 @@ #include "mbedtls/error.h" #include "mbedtls/constant_time.h" +#if defined(MBEDTLS_BLOCK_CIPHER_C) +#include "block_cipher_internal.h" +#endif + #include #if defined(MBEDTLS_AESNI_C) -#include "mbedtls/aesni.h" +#include "aesni.h" +#endif + +#if defined(MBEDTLS_AESCE_C) +#include "aesce.h" #endif #if !defined(MBEDTLS_GCM_ALT) -/* Parameter validation macros */ -#define GCM_VALIDATE_RET(cond) \ - MBEDTLS_INTERNAL_VALIDATE_RET(cond, MBEDTLS_ERR_GCM_BAD_INPUT) -#define GCM_VALIDATE(cond) \ - MBEDTLS_INTERNAL_VALIDATE(cond) +/* Used to select the acceleration mechanism */ +#define MBEDTLS_GCM_ACC_SMALLTABLE 0 +#define MBEDTLS_GCM_ACC_LARGETABLE 1 +#define MBEDTLS_GCM_ACC_AESNI 2 +#define MBEDTLS_GCM_ACC_AESCE 3 /* * Initialize a context */ void mbedtls_gcm_init(mbedtls_gcm_context *ctx) { - GCM_VALIDATE(ctx != NULL); memset(ctx, 0, sizeof(mbedtls_gcm_context)); } +static inline void gcm_set_acceleration(mbedtls_gcm_context *ctx) +{ +#if defined(MBEDTLS_GCM_LARGE_TABLE) + ctx->acceleration = MBEDTLS_GCM_ACC_LARGETABLE; +#else + ctx->acceleration = MBEDTLS_GCM_ACC_SMALLTABLE; +#endif + +#if defined(MBEDTLS_AESNI_HAVE_CODE) + /* With CLMUL support, we need only h, not the rest of the table */ + if (mbedtls_aesni_has_support(MBEDTLS_AESNI_CLMUL)) { + ctx->acceleration = MBEDTLS_GCM_ACC_AESNI; + } +#endif + +#if defined(MBEDTLS_AESCE_HAVE_CODE) + if (MBEDTLS_AESCE_HAS_SUPPORT()) { + ctx->acceleration = MBEDTLS_GCM_ACC_AESCE; + } +#endif +} + +static inline void gcm_gen_table_rightshift(uint64_t dst[2], const uint64_t src[2]) +{ + uint8_t *u8Dst = (uint8_t *) dst; + uint8_t *u8Src = (uint8_t *) src; + + MBEDTLS_PUT_UINT64_BE(MBEDTLS_GET_UINT64_BE(&src[1], 0) >> 1, &dst[1], 0); + u8Dst[8] |= (u8Src[7] & 0x01) << 7; + MBEDTLS_PUT_UINT64_BE(MBEDTLS_GET_UINT64_BE(&src[0], 0) >> 1, &dst[0], 0); + u8Dst[0] ^= (u8Src[15] & 0x01) ? 0xE1 : 0; +} + /* * Precompute small multiples of H, that is set * HH[i] || HL[i] = H times i, @@ -71,57 +99,61 @@ void mbedtls_gcm_init(mbedtls_gcm_context *ctx) static int gcm_gen_table(mbedtls_gcm_context *ctx) { int ret, i, j; - uint64_t hi, lo; - uint64_t vl, vh; - unsigned char h[16]; - size_t olen = 0; + uint64_t u64h[2] = { 0 }; + uint8_t *h = (uint8_t *) u64h; - memset(h, 0, 16); - if ((ret = mbedtls_cipher_update(&ctx->cipher_ctx, h, 16, h, &olen)) != 0) { +#if defined(MBEDTLS_BLOCK_CIPHER_C) + ret = mbedtls_block_cipher_encrypt(&ctx->block_cipher_ctx, h, h); +#else + size_t olen = 0; + ret = mbedtls_cipher_update(&ctx->cipher_ctx, h, 16, h, &olen); +#endif + if (ret != 0) { return ret; } - /* pack h as two 64-bits ints, big-endian */ - hi = MBEDTLS_GET_UINT32_BE(h, 0); - lo = MBEDTLS_GET_UINT32_BE(h, 4); - vh = (uint64_t) hi << 32 | lo; - - hi = MBEDTLS_GET_UINT32_BE(h, 8); - lo = MBEDTLS_GET_UINT32_BE(h, 12); - vl = (uint64_t) hi << 32 | lo; + gcm_set_acceleration(ctx); - /* 8 = 1000 corresponds to 1 in GF(2^128) */ - ctx->HL[8] = vl; - ctx->HH[8] = vh; + /* MBEDTLS_GCM_HTABLE_SIZE/2 = 1000 corresponds to 1 in GF(2^128) */ + ctx->H[MBEDTLS_GCM_HTABLE_SIZE/2][0] = u64h[0]; + ctx->H[MBEDTLS_GCM_HTABLE_SIZE/2][1] = u64h[1]; + switch (ctx->acceleration) { #if defined(MBEDTLS_AESNI_HAVE_CODE) - /* With CLMUL support, we need only h, not the rest of the table */ - if (mbedtls_aesni_has_support(MBEDTLS_AESNI_CLMUL)) { - return 0; - } + case MBEDTLS_GCM_ACC_AESNI: + return 0; #endif - /* 0 corresponds to 0 in GF(2^128) */ - ctx->HH[0] = 0; - ctx->HL[0] = 0; +#if defined(MBEDTLS_AESCE_HAVE_CODE) + case MBEDTLS_GCM_ACC_AESCE: + return 0; +#endif - for (i = 4; i > 0; i >>= 1) { - uint32_t T = (vl & 1) * 0xe1000000U; - vl = (vh << 63) | (vl >> 1); - vh = (vh >> 1) ^ ((uint64_t) T << 32); + default: + /* 0 corresponds to 0 in GF(2^128) */ + ctx->H[0][0] = 0; + ctx->H[0][1] = 0; - ctx->HL[i] = vl; - ctx->HH[i] = vh; - } + for (i = MBEDTLS_GCM_HTABLE_SIZE/4; i > 0; i >>= 1) { + gcm_gen_table_rightshift(ctx->H[i], ctx->H[i*2]); + } - for (i = 2; i <= 8; i *= 2) { - uint64_t *HiL = ctx->HL + i, *HiH = ctx->HH + i; - vh = *HiH; - vl = *HiL; - for (j = 1; j < i; j++) { - HiH[j] = vh ^ ctx->HH[j]; - HiL[j] = vl ^ ctx->HL[j]; - } +#if !defined(MBEDTLS_GCM_LARGE_TABLE) + /* pack elements of H as 64-bits ints, big-endian */ + for (i = MBEDTLS_GCM_HTABLE_SIZE/2; i > 0; i >>= 1) { + MBEDTLS_PUT_UINT64_BE(ctx->H[i][0], &ctx->H[i][0], 0); + MBEDTLS_PUT_UINT64_BE(ctx->H[i][1], &ctx->H[i][1], 0); + } +#endif + + for (i = 2; i < MBEDTLS_GCM_HTABLE_SIZE; i <<= 1) { + for (j = 1; j < i; j++) { + mbedtls_xor_no_simd((unsigned char *) ctx->H[i+j], + (unsigned char *) ctx->H[i], + (unsigned char *) ctx->H[j], + 16); + } + } } return 0; @@ -133,11 +165,23 @@ int mbedtls_gcm_setkey(mbedtls_gcm_context *ctx, unsigned int keybits) { int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED; - const mbedtls_cipher_info_t *cipher_info; - GCM_VALIDATE_RET(ctx != NULL); - GCM_VALIDATE_RET(key != NULL); - GCM_VALIDATE_RET(keybits == 128 || keybits == 192 || keybits == 256); + if (keybits != 128 && keybits != 192 && keybits != 256) { + return MBEDTLS_ERR_GCM_BAD_INPUT; + } + +#if defined(MBEDTLS_BLOCK_CIPHER_C) + mbedtls_block_cipher_free(&ctx->block_cipher_ctx); + + if ((ret = mbedtls_block_cipher_setup(&ctx->block_cipher_ctx, cipher)) != 0) { + return ret; + } + + if ((ret = mbedtls_block_cipher_setkey(&ctx->block_cipher_ctx, key, keybits)) != 0) { + return ret; + } +#else + const mbedtls_cipher_info_t *cipher_info; cipher_info = mbedtls_cipher_info_from_values(cipher, keybits, MBEDTLS_MODE_ECB); @@ -145,7 +189,7 @@ int mbedtls_gcm_setkey(mbedtls_gcm_context *ctx, return MBEDTLS_ERR_GCM_BAD_INPUT; } - if (cipher_info->block_size != 16) { + if (mbedtls_cipher_info_get_block_size(cipher_info) != 16) { return MBEDTLS_ERR_GCM_BAD_INPUT; } @@ -159,6 +203,7 @@ int mbedtls_gcm_setkey(mbedtls_gcm_context *ctx, MBEDTLS_ENCRYPT)) != 0) { return ret; } +#endif if ((ret = gcm_gen_table(ctx)) != 0) { return ret; @@ -167,12 +212,86 @@ int mbedtls_gcm_setkey(mbedtls_gcm_context *ctx, return 0; } +#if defined(MBEDTLS_GCM_LARGE_TABLE) +static const uint16_t last8[256] = { + 0x0000, 0xc201, 0x8403, 0x4602, 0x0807, 0xca06, 0x8c04, 0x4e05, + 0x100e, 0xd20f, 0x940d, 0x560c, 0x1809, 0xda08, 0x9c0a, 0x5e0b, + 0x201c, 0xe21d, 0xa41f, 0x661e, 0x281b, 0xea1a, 0xac18, 0x6e19, + 0x3012, 0xf213, 0xb411, 0x7610, 0x3815, 0xfa14, 0xbc16, 0x7e17, + 0x4038, 0x8239, 0xc43b, 0x063a, 0x483f, 0x8a3e, 0xcc3c, 0x0e3d, + 0x5036, 0x9237, 0xd435, 0x1634, 0x5831, 0x9a30, 0xdc32, 0x1e33, + 0x6024, 0xa225, 0xe427, 0x2626, 0x6823, 0xaa22, 0xec20, 0x2e21, + 0x702a, 0xb22b, 0xf429, 0x3628, 0x782d, 0xba2c, 0xfc2e, 0x3e2f, + 0x8070, 0x4271, 0x0473, 0xc672, 0x8877, 0x4a76, 0x0c74, 0xce75, + 0x907e, 0x527f, 0x147d, 0xd67c, 0x9879, 0x5a78, 0x1c7a, 0xde7b, + 0xa06c, 0x626d, 0x246f, 0xe66e, 0xa86b, 0x6a6a, 0x2c68, 0xee69, + 0xb062, 0x7263, 0x3461, 0xf660, 0xb865, 0x7a64, 0x3c66, 0xfe67, + 0xc048, 0x0249, 0x444b, 0x864a, 0xc84f, 0x0a4e, 0x4c4c, 0x8e4d, + 0xd046, 0x1247, 0x5445, 0x9644, 0xd841, 0x1a40, 0x5c42, 0x9e43, + 0xe054, 0x2255, 0x6457, 0xa656, 0xe853, 0x2a52, 0x6c50, 0xae51, + 0xf05a, 0x325b, 0x7459, 0xb658, 0xf85d, 0x3a5c, 0x7c5e, 0xbe5f, + 0x00e1, 0xc2e0, 0x84e2, 0x46e3, 0x08e6, 0xcae7, 0x8ce5, 0x4ee4, + 0x10ef, 0xd2ee, 0x94ec, 0x56ed, 0x18e8, 0xdae9, 0x9ceb, 0x5eea, + 0x20fd, 0xe2fc, 0xa4fe, 0x66ff, 0x28fa, 0xeafb, 0xacf9, 0x6ef8, + 0x30f3, 0xf2f2, 0xb4f0, 0x76f1, 0x38f4, 0xfaf5, 0xbcf7, 0x7ef6, + 0x40d9, 0x82d8, 0xc4da, 0x06db, 0x48de, 0x8adf, 0xccdd, 0x0edc, + 0x50d7, 0x92d6, 0xd4d4, 0x16d5, 0x58d0, 0x9ad1, 0xdcd3, 0x1ed2, + 0x60c5, 0xa2c4, 0xe4c6, 0x26c7, 0x68c2, 0xaac3, 0xecc1, 0x2ec0, + 0x70cb, 0xb2ca, 0xf4c8, 0x36c9, 0x78cc, 0xbacd, 0xfccf, 0x3ece, + 0x8091, 0x4290, 0x0492, 0xc693, 0x8896, 0x4a97, 0x0c95, 0xce94, + 0x909f, 0x529e, 0x149c, 0xd69d, 0x9898, 0x5a99, 0x1c9b, 0xde9a, + 0xa08d, 0x628c, 0x248e, 0xe68f, 0xa88a, 0x6a8b, 0x2c89, 0xee88, + 0xb083, 0x7282, 0x3480, 0xf681, 0xb884, 0x7a85, 0x3c87, 0xfe86, + 0xc0a9, 0x02a8, 0x44aa, 0x86ab, 0xc8ae, 0x0aaf, 0x4cad, 0x8eac, + 0xd0a7, 0x12a6, 0x54a4, 0x96a5, 0xd8a0, 0x1aa1, 0x5ca3, 0x9ea2, + 0xe0b5, 0x22b4, 0x64b6, 0xa6b7, 0xe8b2, 0x2ab3, 0x6cb1, 0xaeb0, + 0xf0bb, 0x32ba, 0x74b8, 0xb6b9, 0xf8bc, 0x3abd, 0x7cbf, 0xbebe +}; + +static void gcm_mult_largetable(uint8_t *output, const uint8_t *x, uint64_t H[256][2]) +{ + int i; + uint64_t u64z[2]; + uint16_t *u16z = (uint16_t *) u64z; + uint8_t *u8z = (uint8_t *) u64z; + uint8_t rem; + + u64z[0] = 0; + u64z[1] = 0; + + if (MBEDTLS_IS_BIG_ENDIAN) { + for (i = 15; i > 0; i--) { + mbedtls_xor_no_simd(u8z, u8z, (uint8_t *) H[x[i]], 16); + rem = u8z[15]; + + u64z[1] >>= 8; + u8z[8] = u8z[7]; + u64z[0] >>= 8; + + u16z[0] ^= MBEDTLS_GET_UINT16_LE(&last8[rem], 0); + } + } else { + for (i = 15; i > 0; i--) { + mbedtls_xor_no_simd(u8z, u8z, (uint8_t *) H[x[i]], 16); + rem = u8z[15]; + + u64z[1] <<= 8; + u8z[8] = u8z[7]; + u64z[0] <<= 8; + + u16z[0] ^= last8[rem]; + } + } + + mbedtls_xor_no_simd(output, u8z, (uint8_t *) H[x[0]], 16); +} +#else /* * Shoup's method for multiplication use this table with * last4[x] = x times P^128 * where x and last4[x] are seen as elements of GF(2^128) as in [MGV] */ -static const uint64_t last4[16] = +static const uint16_t last4[16] = { 0x0000, 0x1c20, 0x3840, 0x2460, 0x7080, 0x6ca0, 0x48c0, 0x54e0, @@ -180,87 +299,97 @@ static const uint64_t last4[16] = 0x9180, 0x8da0, 0xa9c0, 0xb5e0 }; -/* - * Sets output to x times H using the precomputed tables. - * x and output are seen as elements of GF(2^128) as in [MGV]. - */ -static void gcm_mult(mbedtls_gcm_context *ctx, const unsigned char x[16], - unsigned char output[16]) +static void gcm_mult_smalltable(uint8_t *output, const uint8_t *x, uint64_t H[16][2]) { int i = 0; unsigned char lo, hi, rem; - uint64_t zh, zl; - -#if defined(MBEDTLS_AESNI_HAVE_CODE) - if (mbedtls_aesni_has_support(MBEDTLS_AESNI_CLMUL)) { - unsigned char h[16]; - - MBEDTLS_PUT_UINT32_BE(ctx->HH[8] >> 32, h, 0); - MBEDTLS_PUT_UINT32_BE(ctx->HH[8], h, 4); - MBEDTLS_PUT_UINT32_BE(ctx->HL[8] >> 32, h, 8); - MBEDTLS_PUT_UINT32_BE(ctx->HL[8], h, 12); - - mbedtls_aesni_gcm_mult(output, x, h); - return; - } -#endif /* MBEDTLS_AESNI_HAVE_CODE */ + uint64_t u64z[2]; + const uint64_t *pu64z = NULL; + uint8_t *u8z = (uint8_t *) u64z; lo = x[15] & 0xf; + hi = (x[15] >> 4) & 0xf; + + pu64z = H[lo]; - zh = ctx->HH[lo]; - zl = ctx->HL[lo]; + rem = (unsigned char) pu64z[1] & 0xf; + u64z[1] = (pu64z[0] << 60) | (pu64z[1] >> 4); + u64z[0] = (pu64z[0] >> 4); + u64z[0] ^= (uint64_t) last4[rem] << 48; + mbedtls_xor_no_simd(u8z, u8z, (uint8_t *) H[hi], 16); - for (i = 15; i >= 0; i--) { + for (i = 14; i >= 0; i--) { lo = x[i] & 0xf; hi = (x[i] >> 4) & 0xf; - if (i != 15) { - rem = (unsigned char) zl & 0xf; - zl = (zh << 60) | (zl >> 4); - zh = (zh >> 4); - zh ^= (uint64_t) last4[rem] << 48; - zh ^= ctx->HH[lo]; - zl ^= ctx->HL[lo]; + rem = (unsigned char) u64z[1] & 0xf; + u64z[1] = (u64z[0] << 60) | (u64z[1] >> 4); + u64z[0] = (u64z[0] >> 4); + u64z[0] ^= (uint64_t) last4[rem] << 48; + mbedtls_xor_no_simd(u8z, u8z, (uint8_t *) H[lo], 16); + + rem = (unsigned char) u64z[1] & 0xf; + u64z[1] = (u64z[0] << 60) | (u64z[1] >> 4); + u64z[0] = (u64z[0] >> 4); + u64z[0] ^= (uint64_t) last4[rem] << 48; + mbedtls_xor_no_simd(u8z, u8z, (uint8_t *) H[hi], 16); + } - } + MBEDTLS_PUT_UINT64_BE(u64z[0], output, 0); + MBEDTLS_PUT_UINT64_BE(u64z[1], output, 8); +} +#endif + +/* + * Sets output to x times H using the precomputed tables. + * x and output are seen as elements of GF(2^128) as in [MGV]. + */ +static void gcm_mult(mbedtls_gcm_context *ctx, const unsigned char x[16], + unsigned char output[16]) +{ + switch (ctx->acceleration) { +#if defined(MBEDTLS_AESNI_HAVE_CODE) + case MBEDTLS_GCM_ACC_AESNI: + mbedtls_aesni_gcm_mult(output, x, (uint8_t *) ctx->H[MBEDTLS_GCM_HTABLE_SIZE/2]); + break; +#endif - rem = (unsigned char) zl & 0xf; - zl = (zh << 60) | (zl >> 4); - zh = (zh >> 4); - zh ^= (uint64_t) last4[rem] << 48; - zh ^= ctx->HH[hi]; - zl ^= ctx->HL[hi]; +#if defined(MBEDTLS_AESCE_HAVE_CODE) + case MBEDTLS_GCM_ACC_AESCE: + mbedtls_aesce_gcm_mult(output, x, (uint8_t *) ctx->H[MBEDTLS_GCM_HTABLE_SIZE/2]); + break; +#endif + +#if defined(MBEDTLS_GCM_LARGE_TABLE) + case MBEDTLS_GCM_ACC_LARGETABLE: + gcm_mult_largetable(output, x, ctx->H); + break; +#else + case MBEDTLS_GCM_ACC_SMALLTABLE: + gcm_mult_smalltable(output, x, ctx->H); + break; +#endif } - MBEDTLS_PUT_UINT32_BE(zh >> 32, output, 0); - MBEDTLS_PUT_UINT32_BE(zh, output, 4); - MBEDTLS_PUT_UINT32_BE(zl >> 32, output, 8); - MBEDTLS_PUT_UINT32_BE(zl, output, 12); + return; } int mbedtls_gcm_starts(mbedtls_gcm_context *ctx, int mode, - const unsigned char *iv, - size_t iv_len, - const unsigned char *add, - size_t add_len) + const unsigned char *iv, size_t iv_len) { int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED; unsigned char work_buf[16]; - size_t i; const unsigned char *p; - size_t use_len, olen = 0; + size_t use_len; uint64_t iv_bits; +#if !defined(MBEDTLS_BLOCK_CIPHER_C) + size_t olen = 0; +#endif - GCM_VALIDATE_RET(ctx != NULL); - GCM_VALIDATE_RET(iv != NULL); - GCM_VALIDATE_RET(add_len == 0 || add != NULL); - - /* IV and AD are limited to 2^64 bits, so 2^61 bytes */ + /* IV is limited to 2^64 bits, so 2^61 bytes */ /* IV is not allowed to be zero length */ - if (iv_len == 0 || - ((uint64_t) iv_len) >> 61 != 0 || - ((uint64_t) add_len) >> 61 != 0) { + if (iv_len == 0 || (uint64_t) iv_len >> 61 != 0) { return MBEDTLS_ERR_GCM_BAD_INPUT; } @@ -283,9 +412,16 @@ int mbedtls_gcm_starts(mbedtls_gcm_context *ctx, while (iv_len > 0) { use_len = (iv_len < 16) ? iv_len : 16; - for (i = 0; i < use_len; i++) { - ctx->y[i] ^= p[i]; - } +#if defined(MBEDTLS_COMPILER_IS_GCC) && (MBEDTLS_GCC_VERSION >= 70110) +#pragma GCC diagnostic push +#pragma GCC diagnostic warning "-Wstringop-overflow=0" +#endif + + mbedtls_xor(ctx->y, ctx->y, p, use_len); + +#if defined(MBEDTLS_COMPILER_IS_GCC) && (MBEDTLS_GCC_VERSION >= 70110) +#pragma GCC diagnostic pop +#endif gcm_mult(ctx, ctx->y, ctx->y); @@ -293,119 +429,257 @@ int mbedtls_gcm_starts(mbedtls_gcm_context *ctx, p += use_len; } - for (i = 0; i < 16; i++) { - ctx->y[i] ^= work_buf[i]; - } + mbedtls_xor(ctx->y, ctx->y, work_buf, 16); gcm_mult(ctx, ctx->y, ctx->y); } - if ((ret = mbedtls_cipher_update(&ctx->cipher_ctx, ctx->y, 16, - ctx->base_ectr, &olen)) != 0) { + +#if defined(MBEDTLS_BLOCK_CIPHER_C) + ret = mbedtls_block_cipher_encrypt(&ctx->block_cipher_ctx, ctx->y, ctx->base_ectr); +#else + ret = mbedtls_cipher_update(&ctx->cipher_ctx, ctx->y, 16, ctx->base_ectr, &olen); +#endif + if (ret != 0) { return ret; } - ctx->add_len = add_len; + return 0; +} + +/** + * mbedtls_gcm_context::buf contains the partial state of the computation of + * the authentication tag. + * mbedtls_gcm_context::add_len and mbedtls_gcm_context::len indicate + * different stages of the computation: + * * len == 0 && add_len == 0: initial state + * * len == 0 && add_len % 16 != 0: the first `add_len % 16` bytes have + * a partial block of AD that has been + * xored in but not yet multiplied in. + * * len == 0 && add_len % 16 == 0: the authentication tag is correct if + * the data ends now. + * * len % 16 != 0: the first `len % 16` bytes have + * a partial block of ciphertext that has + * been xored in but not yet multiplied in. + * * len > 0 && len % 16 == 0: the authentication tag is correct if + * the data ends now. + */ +int mbedtls_gcm_update_ad(mbedtls_gcm_context *ctx, + const unsigned char *add, size_t add_len) +{ + const unsigned char *p; + size_t use_len, offset; + uint64_t new_add_len; + + /* AD is limited to 2^64 bits, ie 2^61 bytes + * Also check for possible overflow */ +#if SIZE_MAX > 0xFFFFFFFFFFFFFFFFULL + if (add_len > 0xFFFFFFFFFFFFFFFFULL) { + return MBEDTLS_ERR_GCM_BAD_INPUT; + } +#endif + new_add_len = ctx->add_len + (uint64_t) add_len; + if (new_add_len < ctx->add_len || new_add_len >> 61 != 0) { + return MBEDTLS_ERR_GCM_BAD_INPUT; + } + + offset = ctx->add_len % 16; p = add; - while (add_len > 0) { - use_len = (add_len < 16) ? add_len : 16; - for (i = 0; i < use_len; i++) { - ctx->buf[i] ^= p[i]; + if (offset != 0) { + use_len = 16 - offset; + if (use_len > add_len) { + use_len = add_len; } - gcm_mult(ctx, ctx->buf, ctx->buf); + mbedtls_xor(ctx->buf + offset, ctx->buf + offset, p, use_len); + if (offset + use_len == 16) { + gcm_mult(ctx, ctx->buf, ctx->buf); + } + + ctx->add_len += use_len; add_len -= use_len; p += use_len; } + ctx->add_len += add_len; + + while (add_len >= 16) { + mbedtls_xor(ctx->buf, ctx->buf, p, 16); + + gcm_mult(ctx, ctx->buf, ctx->buf); + + add_len -= 16; + p += 16; + } + + if (add_len > 0) { + mbedtls_xor(ctx->buf, ctx->buf, p, add_len); + } + + return 0; +} + +/* Increment the counter. */ +static void gcm_incr(unsigned char y[16]) +{ + uint32_t x = MBEDTLS_GET_UINT32_BE(y, 12); + x++; + MBEDTLS_PUT_UINT32_BE(x, y, 12); +} + +/* Calculate and apply the encryption mask. Process use_len bytes of data, + * starting at position offset in the mask block. */ +static int gcm_mask(mbedtls_gcm_context *ctx, + unsigned char ectr[16], + size_t offset, size_t use_len, + const unsigned char *input, + unsigned char *output) +{ + int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED; + +#if defined(MBEDTLS_BLOCK_CIPHER_C) + ret = mbedtls_block_cipher_encrypt(&ctx->block_cipher_ctx, ctx->y, ectr); +#else + size_t olen = 0; + ret = mbedtls_cipher_update(&ctx->cipher_ctx, ctx->y, 16, ectr, &olen); +#endif + if (ret != 0) { + mbedtls_platform_zeroize(ectr, 16); + return ret; + } + + if (ctx->mode == MBEDTLS_GCM_DECRYPT) { + mbedtls_xor(ctx->buf + offset, ctx->buf + offset, input, use_len); + } + mbedtls_xor(output, ectr + offset, input, use_len); + if (ctx->mode == MBEDTLS_GCM_ENCRYPT) { + mbedtls_xor(ctx->buf + offset, ctx->buf + offset, output, use_len); + } + return 0; } int mbedtls_gcm_update(mbedtls_gcm_context *ctx, - size_t length, - const unsigned char *input, - unsigned char *output) + const unsigned char *input, size_t input_length, + unsigned char *output, size_t output_size, + size_t *output_length) { int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED; - unsigned char ectr[16]; - size_t i; - const unsigned char *p; + const unsigned char *p = input; unsigned char *out_p = output; - size_t use_len, olen = 0; + size_t offset; + unsigned char ectr[16] = { 0 }; - GCM_VALIDATE_RET(ctx != NULL); - GCM_VALIDATE_RET(length == 0 || input != NULL); - GCM_VALIDATE_RET(length == 0 || output != NULL); + if (output_size < input_length) { + return MBEDTLS_ERR_GCM_BUFFER_TOO_SMALL; + } + *output_length = input_length; + + /* Exit early if input_length==0 so that we don't do any pointer arithmetic + * on a potentially null pointer. + * Returning early also means that the last partial block of AD remains + * untouched for mbedtls_gcm_finish */ + if (input_length == 0) { + return 0; + } - if (output > input && (size_t) (output - input) < length) { + if (output > input && (size_t) (output - input) < input_length) { return MBEDTLS_ERR_GCM_BAD_INPUT; } /* Total length is restricted to 2^39 - 256 bits, ie 2^36 - 2^5 bytes * Also check for possible overflow */ - if (ctx->len + length < ctx->len || - (uint64_t) ctx->len + length > 0xFFFFFFFE0ull) { + if (ctx->len + input_length < ctx->len || + (uint64_t) ctx->len + input_length > 0xFFFFFFFE0ull) { return MBEDTLS_ERR_GCM_BAD_INPUT; } - ctx->len += length; - - p = input; - while (length > 0) { - use_len = (length < 16) ? length : 16; + if (ctx->len == 0 && ctx->add_len % 16 != 0) { + gcm_mult(ctx, ctx->buf, ctx->buf); + } - for (i = 16; i > 12; i--) { - if (++ctx->y[i - 1] != 0) { - break; - } + offset = ctx->len % 16; + if (offset != 0) { + size_t use_len = 16 - offset; + if (use_len > input_length) { + use_len = input_length; } - if ((ret = mbedtls_cipher_update(&ctx->cipher_ctx, ctx->y, 16, ectr, - &olen)) != 0) { + if ((ret = gcm_mask(ctx, ectr, offset, use_len, p, out_p)) != 0) { return ret; } - for (i = 0; i < use_len; i++) { - if (ctx->mode == MBEDTLS_GCM_DECRYPT) { - ctx->buf[i] ^= p[i]; - } - out_p[i] = ectr[i] ^ p[i]; - if (ctx->mode == MBEDTLS_GCM_ENCRYPT) { - ctx->buf[i] ^= out_p[i]; - } + if (offset + use_len == 16) { + gcm_mult(ctx, ctx->buf, ctx->buf); } - gcm_mult(ctx, ctx->buf, ctx->buf); - - length -= use_len; + ctx->len += use_len; + input_length -= use_len; p += use_len; out_p += use_len; } + ctx->len += input_length; + + while (input_length >= 16) { + gcm_incr(ctx->y); + if ((ret = gcm_mask(ctx, ectr, 0, 16, p, out_p)) != 0) { + return ret; + } + + gcm_mult(ctx, ctx->buf, ctx->buf); + + input_length -= 16; + p += 16; + out_p += 16; + } + + if (input_length > 0) { + gcm_incr(ctx->y); + if ((ret = gcm_mask(ctx, ectr, 0, input_length, p, out_p)) != 0) { + return ret; + } + } + + mbedtls_platform_zeroize(ectr, sizeof(ectr)); return 0; } int mbedtls_gcm_finish(mbedtls_gcm_context *ctx, - unsigned char *tag, - size_t tag_len) + unsigned char *output, size_t output_size, + size_t *output_length, + unsigned char *tag, size_t tag_len) { unsigned char work_buf[16]; - size_t i; uint64_t orig_len; uint64_t orig_add_len; - GCM_VALIDATE_RET(ctx != NULL); - GCM_VALIDATE_RET(tag != NULL); + /* We never pass any output in finish(). The output parameter exists only + * for the sake of alternative implementations. */ + (void) output; + (void) output_size; + *output_length = 0; + /* Total length is restricted to 2^39 - 256 bits, ie 2^36 - 2^5 bytes + * and AD length is restricted to 2^64 bits, ie 2^61 bytes so neither of + * the two multiplications would overflow. */ orig_len = ctx->len * 8; orig_add_len = ctx->add_len * 8; + if (ctx->len == 0 && ctx->add_len % 16 != 0) { + gcm_mult(ctx, ctx->buf, ctx->buf); + } + if (tag_len > 16 || tag_len < 4) { return MBEDTLS_ERR_GCM_BAD_INPUT; } + if (ctx->len % 16 != 0) { + gcm_mult(ctx, ctx->buf, ctx->buf); + } + memcpy(tag, ctx->base_ectr, tag_len); if (orig_len || orig_add_len) { @@ -416,15 +690,11 @@ int mbedtls_gcm_finish(mbedtls_gcm_context *ctx, MBEDTLS_PUT_UINT32_BE((orig_len >> 32), work_buf, 8); MBEDTLS_PUT_UINT32_BE((orig_len), work_buf, 12); - for (i = 0; i < 16; i++) { - ctx->buf[i] ^= work_buf[i]; - } + mbedtls_xor(ctx->buf, ctx->buf, work_buf, 16); gcm_mult(ctx, ctx->buf, ctx->buf); - for (i = 0; i < tag_len; i++) { - tag[i] ^= ctx->buf[i]; - } + mbedtls_xor(tag, tag, ctx->buf, tag_len); } return 0; @@ -443,23 +713,22 @@ int mbedtls_gcm_crypt_and_tag(mbedtls_gcm_context *ctx, unsigned char *tag) { int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED; + size_t olen; - GCM_VALIDATE_RET(ctx != NULL); - GCM_VALIDATE_RET(iv != NULL); - GCM_VALIDATE_RET(add_len == 0 || add != NULL); - GCM_VALIDATE_RET(length == 0 || input != NULL); - GCM_VALIDATE_RET(length == 0 || output != NULL); - GCM_VALIDATE_RET(tag != NULL); + if ((ret = mbedtls_gcm_starts(ctx, mode, iv, iv_len)) != 0) { + return ret; + } - if ((ret = mbedtls_gcm_starts(ctx, mode, iv, iv_len, add, add_len)) != 0) { + if ((ret = mbedtls_gcm_update_ad(ctx, add, add_len)) != 0) { return ret; } - if ((ret = mbedtls_gcm_update(ctx, length, input, output)) != 0) { + if ((ret = mbedtls_gcm_update(ctx, input, length, + output, length, &olen)) != 0) { return ret; } - if ((ret = mbedtls_gcm_finish(ctx, tag, tag_len)) != 0) { + if ((ret = mbedtls_gcm_finish(ctx, NULL, 0, &olen, tag, tag_len)) != 0) { return ret; } @@ -481,13 +750,6 @@ int mbedtls_gcm_auth_decrypt(mbedtls_gcm_context *ctx, unsigned char check_tag[16]; int diff; - GCM_VALIDATE_RET(ctx != NULL); - GCM_VALIDATE_RET(iv != NULL); - GCM_VALIDATE_RET(add_len == 0 || add != NULL); - GCM_VALIDATE_RET(tag != NULL); - GCM_VALIDATE_RET(length == 0 || input != NULL); - GCM_VALIDATE_RET(length == 0 || output != NULL); - if ((ret = mbedtls_gcm_crypt_and_tag(ctx, MBEDTLS_GCM_DECRYPT, length, iv, iv_len, add, add_len, input, output, tag_len, check_tag)) != 0) { @@ -510,13 +772,17 @@ void mbedtls_gcm_free(mbedtls_gcm_context *ctx) if (ctx == NULL) { return; } +#if defined(MBEDTLS_BLOCK_CIPHER_C) + mbedtls_block_cipher_free(&ctx->block_cipher_ctx); +#else mbedtls_cipher_free(&ctx->cipher_ctx); +#endif mbedtls_platform_zeroize(ctx, sizeof(mbedtls_gcm_context)); } #endif /* !MBEDTLS_GCM_ALT */ -#if defined(MBEDTLS_SELF_TEST) && defined(MBEDTLS_AES_C) +#if defined(MBEDTLS_SELF_TEST) && defined(MBEDTLS_CCM_GCM_CAN_AES) /* * AES-GCM test vectors from: * @@ -527,7 +793,7 @@ void mbedtls_gcm_free(mbedtls_gcm_context *ctx) static const int key_index_test_data[MAX_TESTS] = { 0, 0, 1, 1, 1, 1 }; -static const unsigned char key_test_data[MAX_TESTS][32] = +static const unsigned char key_test_data[][32] = { { 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, @@ -545,7 +811,7 @@ static const size_t iv_len_test_data[MAX_TESTS] = static const int iv_index_test_data[MAX_TESTS] = { 0, 0, 1, 1, 1, 2 }; -static const unsigned char iv_test_data[MAX_TESTS][64] = +static const unsigned char iv_test_data[][64] = { { 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 }, @@ -567,7 +833,7 @@ static const size_t add_len_test_data[MAX_TESTS] = static const int add_index_test_data[MAX_TESTS] = { 0, 0, 0, 1, 1, 1 }; -static const unsigned char additional_test_data[MAX_TESTS][64] = +static const unsigned char additional_test_data[][64] = { { 0x00 }, { 0xfe, 0xed, 0xfa, 0xce, 0xde, 0xad, 0xbe, 0xef, @@ -581,7 +847,7 @@ static const size_t pt_len_test_data[MAX_TESTS] = static const int pt_index_test_data[MAX_TESTS] = { 0, 0, 1, 1, 1, 1 }; -static const unsigned char pt_test_data[MAX_TESTS][64] = +static const unsigned char pt_test_data[][64] = { { 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 }, @@ -595,7 +861,7 @@ static const unsigned char pt_test_data[MAX_TESTS][64] = 0xba, 0x63, 0x7b, 0x39, 0x1a, 0xaf, 0xd2, 0x55 }, }; -static const unsigned char ct_test_data[MAX_TESTS * 3][64] = +static const unsigned char ct_test_data[][64] = { { 0x00 }, { 0x03, 0x88, 0xda, 0xce, 0x60, 0xb6, 0xa3, 0x92, @@ -632,6 +898,7 @@ static const unsigned char ct_test_data[MAX_TESTS * 3][64] = 0xcc, 0xdc, 0xb2, 0x81, 0xd4, 0x8c, 0x7c, 0x6f, 0xd6, 0x28, 0x75, 0xd2, 0xac, 0xa4, 0x17, 0x03, 0x4c, 0x34, 0xae, 0xe5 }, +#if !defined(MBEDTLS_AES_ONLY_128_BIT_KEY_LENGTH) { 0x00 }, { 0x98, 0xe7, 0x24, 0x7c, 0x07, 0xf0, 0xfe, 0x41, 0x1c, 0x26, 0x7e, 0x43, 0x84, 0xb0, 0xf6, 0x00 }, @@ -702,9 +969,10 @@ static const unsigned char ct_test_data[MAX_TESTS * 3][64] = 0x2d, 0xa3, 0xeb, 0xf1, 0xc5, 0xd8, 0x2c, 0xde, 0xa2, 0x41, 0x89, 0x97, 0x20, 0x0e, 0xf8, 0x2e, 0x44, 0xae, 0x7e, 0x3f }, +#endif /* !MBEDTLS_AES_ONLY_128_BIT_KEY_LENGTH */ }; -static const unsigned char tag_test_data[MAX_TESTS * 3][16] = +static const unsigned char tag_test_data[][16] = { { 0x58, 0xe2, 0xfc, 0xce, 0xfa, 0x7e, 0x30, 0x61, 0x36, 0x7f, 0x1d, 0x57, 0xa4, 0xe7, 0x45, 0x5a }, @@ -718,6 +986,7 @@ static const unsigned char tag_test_data[MAX_TESTS * 3][16] = 0x56, 0x1b, 0xe1, 0x4a, 0xac, 0xa2, 0xfc, 0xcb }, { 0x61, 0x9c, 0xc5, 0xae, 0xff, 0xfe, 0x0b, 0xfa, 0x46, 0x2a, 0xf4, 0x3c, 0x16, 0x99, 0xd0, 0x50 }, +#if !defined(MBEDTLS_AES_ONLY_128_BIT_KEY_LENGTH) { 0xcd, 0x33, 0xb2, 0x8a, 0xc7, 0x73, 0xf7, 0x4b, 0xa0, 0x0e, 0xd1, 0xf3, 0x12, 0x57, 0x24, 0x35 }, { 0x2f, 0xf5, 0x8d, 0x80, 0x03, 0x39, 0x27, 0xab, @@ -742,6 +1011,7 @@ static const unsigned char tag_test_data[MAX_TESTS * 3][16] = 0x5e, 0x45, 0x49, 0x13, 0xfe, 0x2e, 0xa8, 0xf2 }, { 0xa4, 0x4a, 0x82, 0x66, 0xee, 0x1c, 0x8e, 0xb0, 0xc8, 0xb5, 0xd4, 0xcf, 0x5a, 0xe9, 0xf1, 0x9a }, +#endif /* !MBEDTLS_AES_ONLY_128_BIT_KEY_LENGTH */ }; int mbedtls_gcm_self_test(int verbose) @@ -751,6 +1021,7 @@ int mbedtls_gcm_self_test(int verbose) unsigned char tag_buf[16]; int i, j, ret; mbedtls_cipher_id_t cipher = MBEDTLS_CIPHER_ID_AES; + size_t olen; if (verbose != 0) { #if defined(MBEDTLS_GCM_ALT) @@ -758,32 +1029,34 @@ int mbedtls_gcm_self_test(int verbose) #else /* MBEDTLS_GCM_ALT */ #if defined(MBEDTLS_AESNI_HAVE_CODE) if (mbedtls_aesni_has_support(MBEDTLS_AESNI_CLMUL)) { - mbedtls_printf(" GCM note: using AESNI via "); -#if MBEDTLS_AESNI_HAVE_CODE == 1 - mbedtls_printf("assembly"); -#elif MBEDTLS_AESNI_HAVE_CODE == 2 - mbedtls_printf("intrinsics"); -#else - mbedtls_printf("(unknown)"); + mbedtls_printf(" GCM note: using AESNI.\n"); + } else #endif - mbedtls_printf(".\n"); + +#if defined(MBEDTLS_AESCE_HAVE_CODE) + if (MBEDTLS_AESCE_HAS_SUPPORT()) { + mbedtls_printf(" GCM note: using AESCE.\n"); } else #endif + mbedtls_printf(" GCM note: built-in implementation.\n"); #endif /* MBEDTLS_GCM_ALT */ } - for (j = 0; j < 3; j++) { + static const int loop_limit = + (sizeof(ct_test_data) / sizeof(*ct_test_data)) / MAX_TESTS; + + for (j = 0; j < loop_limit; j++) { int key_len = 128 + 64 * j; for (i = 0; i < MAX_TESTS; i++) { - mbedtls_gcm_init(&ctx); - if (verbose != 0) { mbedtls_printf(" AES-GCM-%3d #%d (%s): ", key_len, i, "enc"); } + mbedtls_gcm_init(&ctx); + ret = mbedtls_gcm_setkey(&ctx, cipher, key_test_data[key_index_test_data[i]], key_len); @@ -887,38 +1160,55 @@ int mbedtls_gcm_self_test(int verbose) ret = mbedtls_gcm_starts(&ctx, MBEDTLS_GCM_ENCRYPT, iv_test_data[iv_index_test_data[i]], - iv_len_test_data[i], - additional_test_data[add_index_test_data[i]], - add_len_test_data[i]); + iv_len_test_data[i]); + if (ret != 0) { + goto exit; + } + + ret = mbedtls_gcm_update_ad(&ctx, + additional_test_data[add_index_test_data[i]], + add_len_test_data[i]); if (ret != 0) { goto exit; } if (pt_len_test_data[i] > 32) { size_t rest_len = pt_len_test_data[i] - 32; - ret = mbedtls_gcm_update(&ctx, 32, + ret = mbedtls_gcm_update(&ctx, pt_test_data[pt_index_test_data[i]], - buf); + 32, + buf, sizeof(buf), &olen); if (ret != 0) { goto exit; } + if (olen != 32) { + goto exit; + } - ret = mbedtls_gcm_update(&ctx, rest_len, + ret = mbedtls_gcm_update(&ctx, pt_test_data[pt_index_test_data[i]] + 32, - buf + 32); + rest_len, + buf + 32, sizeof(buf) - 32, &olen); if (ret != 0) { goto exit; } + if (olen != rest_len) { + goto exit; + } } else { - ret = mbedtls_gcm_update(&ctx, pt_len_test_data[i], + ret = mbedtls_gcm_update(&ctx, pt_test_data[pt_index_test_data[i]], - buf); + pt_len_test_data[i], + buf, sizeof(buf), &olen); if (ret != 0) { goto exit; } + if (olen != pt_len_test_data[i]) { + goto exit; + } } - ret = mbedtls_gcm_finish(&ctx, tag_buf, 16); + ret = mbedtls_gcm_finish(&ctx, NULL, 0, &olen, tag_buf, 16); if (ret != 0) { goto exit; } @@ -952,37 +1242,53 @@ int mbedtls_gcm_self_test(int verbose) ret = mbedtls_gcm_starts(&ctx, MBEDTLS_GCM_DECRYPT, iv_test_data[iv_index_test_data[i]], - iv_len_test_data[i], - additional_test_data[add_index_test_data[i]], - add_len_test_data[i]); + iv_len_test_data[i]); + if (ret != 0) { + goto exit; + } + ret = mbedtls_gcm_update_ad(&ctx, + additional_test_data[add_index_test_data[i]], + add_len_test_data[i]); if (ret != 0) { goto exit; } if (pt_len_test_data[i] > 32) { size_t rest_len = pt_len_test_data[i] - 32; - ret = mbedtls_gcm_update(&ctx, 32, ct_test_data[j * 6 + i], - buf); + ret = mbedtls_gcm_update(&ctx, + ct_test_data[j * 6 + i], 32, + buf, sizeof(buf), &olen); if (ret != 0) { goto exit; } + if (olen != 32) { + goto exit; + } - ret = mbedtls_gcm_update(&ctx, rest_len, + ret = mbedtls_gcm_update(&ctx, ct_test_data[j * 6 + i] + 32, - buf + 32); + rest_len, + buf + 32, sizeof(buf) - 32, &olen); if (ret != 0) { goto exit; } + if (olen != rest_len) { + goto exit; + } } else { - ret = mbedtls_gcm_update(&ctx, pt_len_test_data[i], + ret = mbedtls_gcm_update(&ctx, ct_test_data[j * 6 + i], - buf); + pt_len_test_data[i], + buf, sizeof(buf), &olen); if (ret != 0) { goto exit; } + if (olen != pt_len_test_data[i]) { + goto exit; + } } - ret = mbedtls_gcm_finish(&ctx, tag_buf, 16); + ret = mbedtls_gcm_finish(&ctx, NULL, 0, &olen, tag_buf, 16); if (ret != 0) { goto exit; } diff --git a/vendor/mbedtls/library/havege.c b/vendor/mbedtls/library/havege.c deleted file mode 100644 index c23cdad9a5..0000000000 --- a/vendor/mbedtls/library/havege.c +++ /dev/null @@ -1,238 +0,0 @@ -/** - * \brief HAVEGE: HArdware Volatile Entropy Gathering and Expansion - * - * Copyright The Mbed TLS Contributors - * SPDX-License-Identifier: Apache-2.0 - * - * Licensed under the Apache License, Version 2.0 (the "License"); you may - * not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT - * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ -/* - * The HAVEGE RNG was designed by Andre Seznec in 2002. - * - * http://www.irisa.fr/caps/projects/hipsor/publi.php - * - * Contact: seznec(at)irisa_dot_fr - orocheco(at)irisa_dot_fr - */ - -#include "common.h" - -#if defined(MBEDTLS_HAVEGE_C) - -#include "mbedtls/havege.h" -#include "mbedtls/timing.h" -#include "mbedtls/platform_util.h" - -#include -#include - -/* ------------------------------------------------------------------------ - * On average, one iteration accesses two 8-word blocks in the havege WALK - * table, and generates 16 words in the RES array. - * - * The data read in the WALK table is updated and permuted after each use. - * The result of the hardware clock counter read is used for this update. - * - * 25 conditional tests are present. The conditional tests are grouped in - * two nested groups of 12 conditional tests and 1 test that controls the - * permutation; on average, there should be 6 tests executed and 3 of them - * should be mispredicted. - * ------------------------------------------------------------------------ - */ - -#define SWAP(X, Y) { uint32_t *T = (X); (X) = (Y); (Y) = T; } - -#define TST1_ENTER if (PTEST & 1) { PTEST ^= 3; PTEST >>= 1; -#define TST2_ENTER if (PTEST & 1) { PTEST ^= 3; PTEST >>= 1; - -#define TST1_LEAVE U1++; } -#define TST2_LEAVE U2++; } - -#define ONE_ITERATION \ - \ - PTEST = PT1 >> 20; \ - \ - TST1_ENTER TST1_ENTER TST1_ENTER TST1_ENTER \ - TST1_ENTER TST1_ENTER TST1_ENTER TST1_ENTER \ - TST1_ENTER TST1_ENTER TST1_ENTER TST1_ENTER \ - \ - TST1_LEAVE TST1_LEAVE TST1_LEAVE TST1_LEAVE \ - TST1_LEAVE TST1_LEAVE TST1_LEAVE TST1_LEAVE \ - TST1_LEAVE TST1_LEAVE TST1_LEAVE TST1_LEAVE \ - \ - PTX = (PT1 >> 18) & 7; \ - PT1 &= 0x1FFF; \ - PT2 &= 0x1FFF; \ - CLK = (uint32_t) mbedtls_timing_hardclock(); \ - \ - i = 0; \ - A = &WALK[PT1]; RES[i++] ^= *A; \ - B = &WALK[PT2]; RES[i++] ^= *B; \ - C = &WALK[PT1 ^ 1]; RES[i++] ^= *C; \ - D = &WALK[PT2 ^ 4]; RES[i++] ^= *D; \ - \ - IN = (*A >> (1)) ^ (*A << (31)) ^ CLK; \ - *A = (*B >> (2)) ^ (*B << (30)) ^ CLK; \ - *B = IN ^ U1; \ - *C = (*C >> (3)) ^ (*C << (29)) ^ CLK; \ - *D = (*D >> (4)) ^ (*D << (28)) ^ CLK; \ - \ - A = &WALK[PT1 ^ 2]; RES[i++] ^= *A; \ - B = &WALK[PT2 ^ 2]; RES[i++] ^= *B; \ - C = &WALK[PT1 ^ 3]; RES[i++] ^= *C; \ - D = &WALK[PT2 ^ 6]; RES[i++] ^= *D; \ - \ - if (PTEST & 1) SWAP(A, C); \ - \ - IN = (*A >> (5)) ^ (*A << (27)) ^ CLK; \ - *A = (*B >> (6)) ^ (*B << (26)) ^ CLK; \ - *B = IN; CLK = (uint32_t) mbedtls_timing_hardclock(); \ - *C = (*C >> (7)) ^ (*C << (25)) ^ CLK; \ - *D = (*D >> (8)) ^ (*D << (24)) ^ CLK; \ - \ - A = &WALK[PT1 ^ 4]; \ - B = &WALK[PT2 ^ 1]; \ - \ - PTEST = PT2 >> 1; \ - \ - PT2 = (RES[(i - 8) ^ PTY] ^ WALK[PT2 ^ PTY ^ 7]); \ - PT2 = ((PT2 & 0x1FFF) & (~8)) ^ ((PT1 ^ 8) & 0x8); \ - PTY = (PT2 >> 10) & 7; \ - \ - TST2_ENTER TST2_ENTER TST2_ENTER TST2_ENTER \ - TST2_ENTER TST2_ENTER TST2_ENTER TST2_ENTER \ - TST2_ENTER TST2_ENTER TST2_ENTER TST2_ENTER \ - \ - TST2_LEAVE TST2_LEAVE TST2_LEAVE TST2_LEAVE \ - TST2_LEAVE TST2_LEAVE TST2_LEAVE TST2_LEAVE \ - TST2_LEAVE TST2_LEAVE TST2_LEAVE TST2_LEAVE \ - \ - C = &WALK[PT1 ^ 5]; \ - D = &WALK[PT2 ^ 5]; \ - \ - RES[i++] ^= *A; \ - RES[i++] ^= *B; \ - RES[i++] ^= *C; \ - RES[i++] ^= *D; \ - \ - IN = (*A >> (9)) ^ (*A << (23)) ^ CLK; \ - *A = (*B >> (10)) ^ (*B << (22)) ^ CLK; \ - *B = IN ^ U2; \ - *C = (*C >> (11)) ^ (*C << (21)) ^ CLK; \ - *D = (*D >> (12)) ^ (*D << (20)) ^ CLK; \ - \ - A = &WALK[PT1 ^ 6]; RES[i++] ^= *A; \ - B = &WALK[PT2 ^ 3]; RES[i++] ^= *B; \ - C = &WALK[PT1 ^ 7]; RES[i++] ^= *C; \ - D = &WALK[PT2 ^ 7]; RES[i++] ^= *D; \ - \ - IN = (*A >> (13)) ^ (*A << (19)) ^ CLK; \ - *A = (*B >> (14)) ^ (*B << (18)) ^ CLK; \ - *B = IN; \ - *C = (*C >> (15)) ^ (*C << (17)) ^ CLK; \ - *D = (*D >> (16)) ^ (*D << (16)) ^ CLK; \ - \ - PT1 = (RES[(i - 8) ^ PTX] ^ \ - WALK[PT1 ^ PTX ^ 7]) & (~1); \ - PT1 ^= (PT2 ^ 0x10) & 0x10; \ - \ - for (n++, i = 0; i < 16; i++) \ - hs->pool[n % MBEDTLS_HAVEGE_COLLECT_SIZE] ^= RES[i]; - -/* - * Entropy gathering function - */ -static void havege_fill(mbedtls_havege_state *hs) -{ - size_t n = 0; - size_t i; - uint32_t U1, U2, *A, *B, *C, *D; - uint32_t PT1, PT2, *WALK, RES[16]; - uint32_t PTX, PTY, CLK, PTEST, IN; - - WALK = hs->WALK; - PT1 = hs->PT1; - PT2 = hs->PT2; - - PTX = U1 = 0; - PTY = U2 = 0; - - (void) PTX; - - memset(RES, 0, sizeof(RES)); - - while (n < MBEDTLS_HAVEGE_COLLECT_SIZE * 4) { - ONE_ITERATION - ONE_ITERATION - ONE_ITERATION - ONE_ITERATION - } - - hs->PT1 = PT1; - hs->PT2 = PT2; - - hs->offset[0] = 0; - hs->offset[1] = MBEDTLS_HAVEGE_COLLECT_SIZE / 2; -} - -/* - * HAVEGE initialization - */ -void mbedtls_havege_init(mbedtls_havege_state *hs) -{ - memset(hs, 0, sizeof(mbedtls_havege_state)); - - havege_fill(hs); -} - -void mbedtls_havege_free(mbedtls_havege_state *hs) -{ - if (hs == NULL) { - return; - } - - mbedtls_platform_zeroize(hs, sizeof(mbedtls_havege_state)); -} - -/* - * HAVEGE rand function - */ -int mbedtls_havege_random(void *p_rng, unsigned char *buf, size_t len) -{ - uint32_t val; - size_t use_len; - mbedtls_havege_state *hs = (mbedtls_havege_state *) p_rng; - unsigned char *p = buf; - - while (len > 0) { - use_len = len; - if (use_len > sizeof(val)) { - use_len = sizeof(val); - } - - if (hs->offset[1] >= MBEDTLS_HAVEGE_COLLECT_SIZE) { - havege_fill(hs); - } - - val = hs->pool[hs->offset[0]++]; - val ^= hs->pool[hs->offset[1]++]; - - memcpy(p, &val, use_len); - - len -= use_len; - p += use_len; - } - - return 0; -} - -#endif /* MBEDTLS_HAVEGE_C */ diff --git a/vendor/mbedtls/library/hkdf.c b/vendor/mbedtls/library/hkdf.c index a3f071ecef..631ac24e53 100644 --- a/vendor/mbedtls/library/hkdf.c +++ b/vendor/mbedtls/library/hkdf.c @@ -2,19 +2,7 @@ * HKDF implementation -- RFC 5869 * * Copyright The Mbed TLS Contributors - * SPDX-License-Identifier: Apache-2.0 - * - * Licensed under the Apache License, Version 2.0 (the "License"); you may - * not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT - * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. + * SPDX-License-Identifier: Apache-2.0 OR GPL-2.0-or-later */ #include "common.h" diff --git a/vendor/mbedtls/library/hmac_drbg.c b/vendor/mbedtls/library/hmac_drbg.c index fabe00252a..90174d5d17 100644 --- a/vendor/mbedtls/library/hmac_drbg.c +++ b/vendor/mbedtls/library/hmac_drbg.c @@ -2,19 +2,7 @@ * HMAC_DRBG implementation (NIST SP 800-90) * * Copyright The Mbed TLS Contributors - * SPDX-License-Identifier: Apache-2.0 - * - * Licensed under the Apache License, Version 2.0 (the "License"); you may - * not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT - * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. + * SPDX-License-Identifier: Apache-2.0 OR GPL-2.0-or-later */ /* @@ -52,9 +40,9 @@ void mbedtls_hmac_drbg_init(mbedtls_hmac_drbg_context *ctx) /* * HMAC_DRBG update, using optional additional data (10.1.2.2) */ -int mbedtls_hmac_drbg_update_ret(mbedtls_hmac_drbg_context *ctx, - const unsigned char *additional, - size_t add_len) +int mbedtls_hmac_drbg_update(mbedtls_hmac_drbg_context *ctx, + const unsigned char *additional, + size_t add_len) { size_t md_len = mbedtls_md_get_size(ctx->md_ctx.md_info); unsigned char rounds = (additional != NULL && add_len != 0) ? 2 : 1; @@ -103,15 +91,6 @@ int mbedtls_hmac_drbg_update_ret(mbedtls_hmac_drbg_context *ctx, return ret; } -#if !defined(MBEDTLS_DEPRECATED_REMOVED) -void mbedtls_hmac_drbg_update(mbedtls_hmac_drbg_context *ctx, - const unsigned char *additional, - size_t add_len) -{ - (void) mbedtls_hmac_drbg_update_ret(ctx, additional, add_len); -} -#endif /* MBEDTLS_DEPRECATED_REMOVED */ - /* * Simplified HMAC_DRBG initialisation (for use with deterministic ECDSA) */ @@ -140,7 +119,7 @@ int mbedtls_hmac_drbg_seed_buf(mbedtls_hmac_drbg_context *ctx, } memset(ctx->V, 0x01, mbedtls_md_get_size(md_info)); - if ((ret = mbedtls_hmac_drbg_update_ret(ctx, data, data_len)) != 0) { + if ((ret = mbedtls_hmac_drbg_update(ctx, data, data_len)) != 0) { return ret; } @@ -212,7 +191,7 @@ static int hmac_drbg_reseed_core(mbedtls_hmac_drbg_context *ctx, } /* 2. Update state */ - if ((ret = mbedtls_hmac_drbg_update_ret(ctx, seed, seedlen)) != 0) { + if ((ret = mbedtls_hmac_drbg_update(ctx, seed, seedlen)) != 0) { goto exit; } @@ -357,8 +336,8 @@ int mbedtls_hmac_drbg_random_with_add(void *p_rng, /* 2. Use additional data if any */ if (additional != NULL && add_len != 0) { - if ((ret = mbedtls_hmac_drbg_update_ret(ctx, - additional, add_len)) != 0) { + if ((ret = mbedtls_hmac_drbg_update(ctx, + additional, add_len)) != 0) { goto exit; } } @@ -384,8 +363,8 @@ int mbedtls_hmac_drbg_random_with_add(void *p_rng, } /* 6. Update */ - if ((ret = mbedtls_hmac_drbg_update_ret(ctx, - additional, add_len)) != 0) { + if ((ret = mbedtls_hmac_drbg_update(ctx, + additional, add_len)) != 0) { goto exit; } @@ -454,6 +433,9 @@ int mbedtls_hmac_drbg_write_seed_file(mbedtls_hmac_drbg_context *ctx, const char return MBEDTLS_ERR_HMAC_DRBG_FILE_IO_ERROR; } + /* Ensure no stdio buffering of secrets, as such buffers cannot be wiped. */ + mbedtls_setbuf(f, NULL); + if ((ret = mbedtls_hmac_drbg_random(ctx, buf, sizeof(buf))) != 0) { goto exit; } @@ -484,6 +466,9 @@ int mbedtls_hmac_drbg_update_seed_file(mbedtls_hmac_drbg_context *ctx, const cha return MBEDTLS_ERR_HMAC_DRBG_FILE_IO_ERROR; } + /* Ensure no stdio buffering of secrets, as such buffers cannot be wiped. */ + mbedtls_setbuf(f, NULL); + n = fread(buf, 1, sizeof(buf), f); if (fread(&c, 1, 1, f) != 0) { ret = MBEDTLS_ERR_HMAC_DRBG_INPUT_TOO_BIG; @@ -496,7 +481,7 @@ int mbedtls_hmac_drbg_update_seed_file(mbedtls_hmac_drbg_context *ctx, const cha fclose(f); f = NULL; - ret = mbedtls_hmac_drbg_update_ret(ctx, buf, n); + ret = mbedtls_hmac_drbg_update(ctx, buf, n); exit: mbedtls_platform_zeroize(buf, sizeof(buf)); @@ -513,7 +498,7 @@ int mbedtls_hmac_drbg_update_seed_file(mbedtls_hmac_drbg_context *ctx, const cha #if defined(MBEDTLS_SELF_TEST) -#if !defined(MBEDTLS_SHA1_C) +#if !defined(MBEDTLS_MD_CAN_SHA1) /* Dummy checkup routine */ int mbedtls_hmac_drbg_self_test(int verbose) { @@ -642,7 +627,7 @@ int mbedtls_hmac_drbg_self_test(int verbose) return 0; } -#endif /* MBEDTLS_SHA1_C */ +#endif /* MBEDTLS_MD_CAN_SHA1 */ #endif /* MBEDTLS_SELF_TEST */ #endif /* MBEDTLS_HMAC_DRBG_C */ diff --git a/vendor/mbedtls/library/lmots.c b/vendor/mbedtls/library/lmots.c new file mode 100644 index 0000000000..c7091b49e1 --- /dev/null +++ b/vendor/mbedtls/library/lmots.c @@ -0,0 +1,778 @@ +/* + * The LM-OTS one-time public-key signature scheme + * + * Copyright The Mbed TLS Contributors + * SPDX-License-Identifier: Apache-2.0 OR GPL-2.0-or-later + */ + +/* + * The following sources were referenced in the design of this implementation + * of the LM-OTS algorithm: + * + * [1] IETF RFC8554 + * D. McGrew, M. Curcio, S.Fluhrer + * https://datatracker.ietf.org/doc/html/rfc8554 + * + * [2] NIST Special Publication 800-208 + * David A. Cooper et. al. + * https://nvlpubs.nist.gov/nistpubs/SpecialPublications/NIST.SP.800-208.pdf + */ + +#include "common.h" + +#if defined(MBEDTLS_LMS_C) + +#include + +#include "lmots.h" + +#include "mbedtls/lms.h" +#include "mbedtls/platform_util.h" +#include "mbedtls/error.h" +#include "psa_util_internal.h" + +#include "psa/crypto.h" + +/* Define a local translating function to save code size by not using too many + * arguments in each translating place. */ +static int local_err_translation(psa_status_t status) +{ + return psa_status_to_mbedtls(status, psa_to_lms_errors, + ARRAY_LENGTH(psa_to_lms_errors), + psa_generic_status_to_mbedtls); +} +#define PSA_TO_MBEDTLS_ERR(status) local_err_translation(status) + +#define PUBLIC_KEY_TYPE_OFFSET (0) +#define PUBLIC_KEY_I_KEY_ID_OFFSET (PUBLIC_KEY_TYPE_OFFSET + \ + MBEDTLS_LMOTS_TYPE_LEN) +#define PUBLIC_KEY_Q_LEAF_ID_OFFSET (PUBLIC_KEY_I_KEY_ID_OFFSET + \ + MBEDTLS_LMOTS_I_KEY_ID_LEN) +#define PUBLIC_KEY_KEY_HASH_OFFSET (PUBLIC_KEY_Q_LEAF_ID_OFFSET + \ + MBEDTLS_LMOTS_Q_LEAF_ID_LEN) + +/* We only support parameter sets that use 8-bit digits, as it does not require + * translation logic between digits and bytes */ +#define W_WINTERNITZ_PARAMETER (8u) +#define CHECKSUM_LEN (2) +#define I_DIGIT_IDX_LEN (2) +#define J_HASH_IDX_LEN (1) +#define D_CONST_LEN (2) + +#define DIGIT_MAX_VALUE ((1u << W_WINTERNITZ_PARAMETER) - 1u) + +#define D_CONST_LEN (2) +static const unsigned char D_PUBLIC_CONSTANT_BYTES[D_CONST_LEN] = { 0x80, 0x80 }; +static const unsigned char D_MESSAGE_CONSTANT_BYTES[D_CONST_LEN] = { 0x81, 0x81 }; + +#if defined(MBEDTLS_TEST_HOOKS) +int (*mbedtls_lmots_sign_private_key_invalidated_hook)(unsigned char *) = NULL; +#endif /* defined(MBEDTLS_TEST_HOOKS) */ + +/* Calculate the checksum digits that are appended to the end of the LMOTS digit + * string. See NIST SP800-208 section 3.1 or RFC8554 Algorithm 2 for details of + * the checksum algorithm. + * + * params The LMOTS parameter set, I and q values which + * describe the key being used. + * + * digest The digit string to create the digest from. As + * this does not contain a checksum, it is the same + * size as a hash output. + */ +static unsigned short lmots_checksum_calculate(const mbedtls_lmots_parameters_t *params, + const unsigned char *digest) +{ + size_t idx; + unsigned sum = 0; + + for (idx = 0; idx < MBEDTLS_LMOTS_N_HASH_LEN(params->type); idx++) { + sum += DIGIT_MAX_VALUE - digest[idx]; + } + + return sum; +} + +/* Create the string of digest digits (in the base determined by the Winternitz + * parameter with the checksum appended to the end (Q || cksm(Q)). See NIST + * SP800-208 section 3.1 or RFC8554 Algorithm 3 step 5 (also used in Algorithm + * 4b step 3) for details. + * + * params The LMOTS parameter set, I and q values which + * describe the key being used. + * + * msg The message that will be hashed to create the + * digest. + * + * msg_size The size of the message. + * + * C_random_value The random value that will be combined with the + * message digest. This is always the same size as a + * hash output for whichever hash algorithm is + * determined by the parameter set. + * + * output An output containing the digit string (+ + * checksum) of length P digits (in the case of + * MBEDTLS_LMOTS_SHA256_N32_W8, this means it is of + * size P bytes). + */ +static int create_digit_array_with_checksum(const mbedtls_lmots_parameters_t *params, + const unsigned char *msg, + size_t msg_len, + const unsigned char *C_random_value, + unsigned char *out) +{ + psa_hash_operation_t op = PSA_HASH_OPERATION_INIT; + psa_status_t status = PSA_ERROR_CORRUPTION_DETECTED; + size_t output_hash_len; + unsigned short checksum; + + status = psa_hash_setup(&op, PSA_ALG_SHA_256); + if (status != PSA_SUCCESS) { + goto exit; + } + + status = psa_hash_update(&op, params->I_key_identifier, + MBEDTLS_LMOTS_I_KEY_ID_LEN); + if (status != PSA_SUCCESS) { + goto exit; + } + + status = psa_hash_update(&op, params->q_leaf_identifier, + MBEDTLS_LMOTS_Q_LEAF_ID_LEN); + if (status != PSA_SUCCESS) { + goto exit; + } + + status = psa_hash_update(&op, D_MESSAGE_CONSTANT_BYTES, D_CONST_LEN); + if (status != PSA_SUCCESS) { + goto exit; + } + + status = psa_hash_update(&op, C_random_value, + MBEDTLS_LMOTS_C_RANDOM_VALUE_LEN(params->type)); + if (status != PSA_SUCCESS) { + goto exit; + } + + status = psa_hash_update(&op, msg, msg_len); + if (status != PSA_SUCCESS) { + goto exit; + } + + status = psa_hash_finish(&op, out, + MBEDTLS_LMOTS_N_HASH_LEN(params->type), + &output_hash_len); + if (status != PSA_SUCCESS) { + goto exit; + } + + checksum = lmots_checksum_calculate(params, out); + MBEDTLS_PUT_UINT16_BE(checksum, out, MBEDTLS_LMOTS_N_HASH_LEN(params->type)); + +exit: + psa_hash_abort(&op); + + return PSA_TO_MBEDTLS_ERR(status); +} + +/* Hash each element of the string of digits (+ checksum), producing a hash + * output for each element. This is used in several places (by varying the + * hash_idx_min/max_values) in order to calculate a public key from a private + * key (RFC8554 Algorithm 1 step 4), in order to sign a message (RFC8554 + * Algorithm 3 step 5), and to calculate a public key candidate from a + * signature and message (RFC8554 Algorithm 4b step 3). + * + * params The LMOTS parameter set, I and q values which + * describe the key being used. + * + * x_digit_array The array of digits (of size P, 34 in the case of + * MBEDTLS_LMOTS_SHA256_N32_W8). + * + * hash_idx_min_values An array of the starting values of the j iterator + * for each of the members of the digit array. If + * this value in NULL, then all iterators will start + * at 0. + * + * hash_idx_max_values An array of the upper bound values of the j + * iterator for each of the members of the digit + * array. If this value in NULL, then iterator is + * bounded to be less than 2^w - 1 (255 in the case + * of MBEDTLS_LMOTS_SHA256_N32_W8) + * + * output An array containing a hash output for each member + * of the digit string P. In the case of + * MBEDTLS_LMOTS_SHA256_N32_W8, this is of size 32 * + * 34. + */ +static int hash_digit_array(const mbedtls_lmots_parameters_t *params, + const unsigned char *x_digit_array, + const unsigned char *hash_idx_min_values, + const unsigned char *hash_idx_max_values, + unsigned char *output) +{ + unsigned int i_digit_idx; + unsigned char i_digit_idx_bytes[I_DIGIT_IDX_LEN]; + unsigned int j_hash_idx; + unsigned char j_hash_idx_bytes[J_HASH_IDX_LEN]; + unsigned int j_hash_idx_min; + unsigned int j_hash_idx_max; + psa_hash_operation_t op = PSA_HASH_OPERATION_INIT; + psa_status_t status = PSA_ERROR_CORRUPTION_DETECTED; + size_t output_hash_len; + unsigned char tmp_hash[MBEDTLS_LMOTS_N_HASH_LEN_MAX]; + + for (i_digit_idx = 0; + i_digit_idx < MBEDTLS_LMOTS_P_SIG_DIGIT_COUNT(params->type); + i_digit_idx++) { + + memcpy(tmp_hash, + &x_digit_array[i_digit_idx * MBEDTLS_LMOTS_N_HASH_LEN(params->type)], + MBEDTLS_LMOTS_N_HASH_LEN(params->type)); + + j_hash_idx_min = hash_idx_min_values != NULL ? + hash_idx_min_values[i_digit_idx] : 0; + j_hash_idx_max = hash_idx_max_values != NULL ? + hash_idx_max_values[i_digit_idx] : DIGIT_MAX_VALUE; + + for (j_hash_idx = j_hash_idx_min; + j_hash_idx < j_hash_idx_max; + j_hash_idx++) { + status = psa_hash_setup(&op, PSA_ALG_SHA_256); + if (status != PSA_SUCCESS) { + goto exit; + } + + status = psa_hash_update(&op, + params->I_key_identifier, + MBEDTLS_LMOTS_I_KEY_ID_LEN); + if (status != PSA_SUCCESS) { + goto exit; + } + + status = psa_hash_update(&op, + params->q_leaf_identifier, + MBEDTLS_LMOTS_Q_LEAF_ID_LEN); + if (status != PSA_SUCCESS) { + goto exit; + } + + MBEDTLS_PUT_UINT16_BE(i_digit_idx, i_digit_idx_bytes, 0); + status = psa_hash_update(&op, i_digit_idx_bytes, I_DIGIT_IDX_LEN); + if (status != PSA_SUCCESS) { + goto exit; + } + + j_hash_idx_bytes[0] = (uint8_t) j_hash_idx; + status = psa_hash_update(&op, j_hash_idx_bytes, J_HASH_IDX_LEN); + if (status != PSA_SUCCESS) { + goto exit; + } + + status = psa_hash_update(&op, tmp_hash, + MBEDTLS_LMOTS_N_HASH_LEN(params->type)); + if (status != PSA_SUCCESS) { + goto exit; + } + + status = psa_hash_finish(&op, tmp_hash, sizeof(tmp_hash), + &output_hash_len); + if (status != PSA_SUCCESS) { + goto exit; + } + + psa_hash_abort(&op); + } + + memcpy(&output[i_digit_idx * MBEDTLS_LMOTS_N_HASH_LEN(params->type)], + tmp_hash, MBEDTLS_LMOTS_N_HASH_LEN(params->type)); + } + +exit: + psa_hash_abort(&op); + mbedtls_platform_zeroize(tmp_hash, sizeof(tmp_hash)); + + return PSA_TO_MBEDTLS_ERR(status); +} + +/* Combine the hashes of the digit array into a public key. This is used in + * in order to calculate a public key from a private key (RFC8554 Algorithm 1 + * step 4), and to calculate a public key candidate from a signature and message + * (RFC8554 Algorithm 4b step 3). + * + * params The LMOTS parameter set, I and q values which describe + * the key being used. + * y_hashed_digits The array of hashes, one hash for each digit of the + * symbol array (which is of size P, 34 in the case of + * MBEDTLS_LMOTS_SHA256_N32_W8) + * + * pub_key The output public key (or candidate public key in + * case this is being run as part of signature + * verification), in the form of a hash output. + */ +static int public_key_from_hashed_digit_array(const mbedtls_lmots_parameters_t *params, + const unsigned char *y_hashed_digits, + unsigned char *pub_key) +{ + psa_hash_operation_t op = PSA_HASH_OPERATION_INIT; + psa_status_t status = PSA_ERROR_CORRUPTION_DETECTED; + size_t output_hash_len; + + status = psa_hash_setup(&op, PSA_ALG_SHA_256); + if (status != PSA_SUCCESS) { + goto exit; + } + + status = psa_hash_update(&op, + params->I_key_identifier, + MBEDTLS_LMOTS_I_KEY_ID_LEN); + if (status != PSA_SUCCESS) { + goto exit; + } + + status = psa_hash_update(&op, params->q_leaf_identifier, + MBEDTLS_LMOTS_Q_LEAF_ID_LEN); + if (status != PSA_SUCCESS) { + goto exit; + } + + status = psa_hash_update(&op, D_PUBLIC_CONSTANT_BYTES, D_CONST_LEN); + if (status != PSA_SUCCESS) { + goto exit; + } + + status = psa_hash_update(&op, y_hashed_digits, + MBEDTLS_LMOTS_P_SIG_DIGIT_COUNT(params->type) * + MBEDTLS_LMOTS_N_HASH_LEN(params->type)); + if (status != PSA_SUCCESS) { + goto exit; + } + + status = psa_hash_finish(&op, pub_key, + MBEDTLS_LMOTS_N_HASH_LEN(params->type), + &output_hash_len); + if (status != PSA_SUCCESS) { + +exit: + psa_hash_abort(&op); + } + + return PSA_TO_MBEDTLS_ERR(status); +} + +#if !defined(MBEDTLS_DEPRECATED_REMOVED) +int mbedtls_lms_error_from_psa(psa_status_t status) +{ + switch (status) { + case PSA_SUCCESS: + return 0; + case PSA_ERROR_HARDWARE_FAILURE: + return MBEDTLS_ERR_PLATFORM_HW_ACCEL_FAILED; + case PSA_ERROR_NOT_SUPPORTED: + return MBEDTLS_ERR_PLATFORM_FEATURE_UNSUPPORTED; + case PSA_ERROR_BUFFER_TOO_SMALL: + return MBEDTLS_ERR_LMS_BUFFER_TOO_SMALL; + case PSA_ERROR_INVALID_ARGUMENT: + return MBEDTLS_ERR_LMS_BAD_INPUT_DATA; + default: + return MBEDTLS_ERR_ERROR_GENERIC_ERROR; + } +} +#endif /* !MBEDTLS_DEPRECATED_REMOVED */ + +void mbedtls_lmots_public_init(mbedtls_lmots_public_t *ctx) +{ + memset(ctx, 0, sizeof(*ctx)); +} + +void mbedtls_lmots_public_free(mbedtls_lmots_public_t *ctx) +{ + mbedtls_platform_zeroize(ctx, sizeof(*ctx)); +} + +int mbedtls_lmots_import_public_key(mbedtls_lmots_public_t *ctx, + const unsigned char *key, size_t key_len) +{ + if (key_len < MBEDTLS_LMOTS_SIG_TYPE_OFFSET + MBEDTLS_LMOTS_TYPE_LEN) { + return MBEDTLS_ERR_LMS_BAD_INPUT_DATA; + } + + ctx->params.type = (mbedtls_lmots_algorithm_type_t) + MBEDTLS_GET_UINT32_BE(key, MBEDTLS_LMOTS_SIG_TYPE_OFFSET); + + if (key_len != MBEDTLS_LMOTS_PUBLIC_KEY_LEN(ctx->params.type)) { + return MBEDTLS_ERR_LMS_BAD_INPUT_DATA; + } + + memcpy(ctx->params.I_key_identifier, + key + PUBLIC_KEY_I_KEY_ID_OFFSET, + MBEDTLS_LMOTS_I_KEY_ID_LEN); + + memcpy(ctx->params.q_leaf_identifier, + key + PUBLIC_KEY_Q_LEAF_ID_OFFSET, + MBEDTLS_LMOTS_Q_LEAF_ID_LEN); + + memcpy(ctx->public_key, + key + PUBLIC_KEY_KEY_HASH_OFFSET, + MBEDTLS_LMOTS_N_HASH_LEN(ctx->params.type)); + + ctx->have_public_key = 1; + + return 0; +} + +int mbedtls_lmots_export_public_key(const mbedtls_lmots_public_t *ctx, + unsigned char *key, size_t key_size, + size_t *key_len) +{ + if (key_size < MBEDTLS_LMOTS_PUBLIC_KEY_LEN(ctx->params.type)) { + return MBEDTLS_ERR_LMS_BUFFER_TOO_SMALL; + } + + if (!ctx->have_public_key) { + return MBEDTLS_ERR_LMS_BAD_INPUT_DATA; + } + + MBEDTLS_PUT_UINT32_BE(ctx->params.type, key, MBEDTLS_LMOTS_SIG_TYPE_OFFSET); + + memcpy(key + PUBLIC_KEY_I_KEY_ID_OFFSET, + ctx->params.I_key_identifier, + MBEDTLS_LMOTS_I_KEY_ID_LEN); + + memcpy(key + PUBLIC_KEY_Q_LEAF_ID_OFFSET, + ctx->params.q_leaf_identifier, + MBEDTLS_LMOTS_Q_LEAF_ID_LEN); + + memcpy(key + PUBLIC_KEY_KEY_HASH_OFFSET, ctx->public_key, + MBEDTLS_LMOTS_N_HASH_LEN(ctx->params.type)); + + if (key_len != NULL) { + *key_len = MBEDTLS_LMOTS_PUBLIC_KEY_LEN(ctx->params.type); + } + + return 0; +} + +int mbedtls_lmots_calculate_public_key_candidate(const mbedtls_lmots_parameters_t *params, + const unsigned char *msg, + size_t msg_size, + const unsigned char *sig, + size_t sig_size, + unsigned char *out, + size_t out_size, + size_t *out_len) +{ + unsigned char tmp_digit_array[MBEDTLS_LMOTS_P_SIG_DIGIT_COUNT_MAX]; + unsigned char y_hashed_digits[MBEDTLS_LMOTS_P_SIG_DIGIT_COUNT_MAX][MBEDTLS_LMOTS_N_HASH_LEN_MAX]; + int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED; + + if (msg == NULL && msg_size != 0) { + return MBEDTLS_ERR_LMS_BAD_INPUT_DATA; + } + + if (sig_size != MBEDTLS_LMOTS_SIG_LEN(params->type) || + out_size < MBEDTLS_LMOTS_N_HASH_LEN(params->type)) { + return MBEDTLS_ERR_LMS_BAD_INPUT_DATA; + } + + ret = create_digit_array_with_checksum(params, msg, msg_size, + sig + MBEDTLS_LMOTS_SIG_C_RANDOM_OFFSET, + tmp_digit_array); + if (ret) { + return ret; + } + + ret = hash_digit_array(params, + sig + MBEDTLS_LMOTS_SIG_SIGNATURE_OFFSET(params->type), + tmp_digit_array, NULL, (unsigned char *) y_hashed_digits); + if (ret) { + return ret; + } + + ret = public_key_from_hashed_digit_array(params, + (unsigned char *) y_hashed_digits, + out); + if (ret) { + return ret; + } + + if (out_len != NULL) { + *out_len = MBEDTLS_LMOTS_N_HASH_LEN(params->type); + } + + return 0; +} + +int mbedtls_lmots_verify(const mbedtls_lmots_public_t *ctx, + const unsigned char *msg, size_t msg_size, + const unsigned char *sig, size_t sig_size) +{ + unsigned char Kc_public_key_candidate[MBEDTLS_LMOTS_N_HASH_LEN_MAX]; + int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED; + + if (msg == NULL && msg_size != 0) { + return MBEDTLS_ERR_LMS_BAD_INPUT_DATA; + } + + if (!ctx->have_public_key) { + return MBEDTLS_ERR_LMS_BAD_INPUT_DATA; + } + + if (ctx->params.type != MBEDTLS_LMOTS_SHA256_N32_W8) { + return MBEDTLS_ERR_LMS_BAD_INPUT_DATA; + } + + if (sig_size < MBEDTLS_LMOTS_SIG_TYPE_OFFSET + MBEDTLS_LMOTS_TYPE_LEN) { + return MBEDTLS_ERR_LMS_VERIFY_FAILED; + } + + if (MBEDTLS_GET_UINT32_BE(sig, MBEDTLS_LMOTS_SIG_TYPE_OFFSET) != MBEDTLS_LMOTS_SHA256_N32_W8) { + return MBEDTLS_ERR_LMS_VERIFY_FAILED; + } + + ret = mbedtls_lmots_calculate_public_key_candidate(&ctx->params, + msg, msg_size, sig, sig_size, + Kc_public_key_candidate, + MBEDTLS_LMOTS_N_HASH_LEN(ctx->params.type), + NULL); + if (ret) { + return MBEDTLS_ERR_LMS_VERIFY_FAILED; + } + + if (memcmp(&Kc_public_key_candidate, ctx->public_key, + sizeof(ctx->public_key))) { + return MBEDTLS_ERR_LMS_VERIFY_FAILED; + } + + return 0; +} + +#if defined(MBEDTLS_LMS_PRIVATE) + +void mbedtls_lmots_private_init(mbedtls_lmots_private_t *ctx) +{ + memset(ctx, 0, sizeof(*ctx)); +} + +void mbedtls_lmots_private_free(mbedtls_lmots_private_t *ctx) +{ + mbedtls_platform_zeroize(ctx, + sizeof(*ctx)); +} + +int mbedtls_lmots_generate_private_key(mbedtls_lmots_private_t *ctx, + mbedtls_lmots_algorithm_type_t type, + const unsigned char I_key_identifier[MBEDTLS_LMOTS_I_KEY_ID_LEN], + uint32_t q_leaf_identifier, + const unsigned char *seed, + size_t seed_size) +{ + psa_hash_operation_t op = PSA_HASH_OPERATION_INIT; + psa_status_t status = PSA_ERROR_CORRUPTION_DETECTED; + size_t output_hash_len; + unsigned int i_digit_idx; + unsigned char i_digit_idx_bytes[2]; + unsigned char const_bytes[1] = { 0xFF }; + + if (ctx->have_private_key) { + return MBEDTLS_ERR_LMS_BAD_INPUT_DATA; + } + + if (type != MBEDTLS_LMOTS_SHA256_N32_W8) { + return MBEDTLS_ERR_LMS_BAD_INPUT_DATA; + } + + ctx->params.type = type; + + memcpy(ctx->params.I_key_identifier, + I_key_identifier, + sizeof(ctx->params.I_key_identifier)); + + MBEDTLS_PUT_UINT32_BE(q_leaf_identifier, ctx->params.q_leaf_identifier, 0); + + for (i_digit_idx = 0; + i_digit_idx < MBEDTLS_LMOTS_P_SIG_DIGIT_COUNT(ctx->params.type); + i_digit_idx++) { + status = psa_hash_setup(&op, PSA_ALG_SHA_256); + if (status != PSA_SUCCESS) { + goto exit; + } + + status = psa_hash_update(&op, + ctx->params.I_key_identifier, + sizeof(ctx->params.I_key_identifier)); + if (status != PSA_SUCCESS) { + goto exit; + } + + status = psa_hash_update(&op, + ctx->params.q_leaf_identifier, + MBEDTLS_LMOTS_Q_LEAF_ID_LEN); + if (status != PSA_SUCCESS) { + goto exit; + } + + MBEDTLS_PUT_UINT16_BE(i_digit_idx, i_digit_idx_bytes, 0); + status = psa_hash_update(&op, i_digit_idx_bytes, I_DIGIT_IDX_LEN); + if (status != PSA_SUCCESS) { + goto exit; + } + + status = psa_hash_update(&op, const_bytes, sizeof(const_bytes)); + if (status != PSA_SUCCESS) { + goto exit; + } + + status = psa_hash_update(&op, seed, seed_size); + if (status != PSA_SUCCESS) { + goto exit; + } + + status = psa_hash_finish(&op, + ctx->private_key[i_digit_idx], + MBEDTLS_LMOTS_N_HASH_LEN(ctx->params.type), + &output_hash_len); + if (status != PSA_SUCCESS) { + goto exit; + } + + psa_hash_abort(&op); + } + + ctx->have_private_key = 1; + +exit: + psa_hash_abort(&op); + + return PSA_TO_MBEDTLS_ERR(status); +} + +int mbedtls_lmots_calculate_public_key(mbedtls_lmots_public_t *ctx, + const mbedtls_lmots_private_t *priv_ctx) +{ + unsigned char y_hashed_digits[MBEDTLS_LMOTS_P_SIG_DIGIT_COUNT_MAX][MBEDTLS_LMOTS_N_HASH_LEN_MAX]; + int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED; + + /* Check that a private key is loaded */ + if (!priv_ctx->have_private_key) { + return MBEDTLS_ERR_LMS_BAD_INPUT_DATA; + } + + ret = hash_digit_array(&priv_ctx->params, + (unsigned char *) priv_ctx->private_key, NULL, + NULL, (unsigned char *) y_hashed_digits); + if (ret) { + goto exit; + } + + ret = public_key_from_hashed_digit_array(&priv_ctx->params, + (unsigned char *) y_hashed_digits, + ctx->public_key); + if (ret) { + goto exit; + } + + memcpy(&ctx->params, &priv_ctx->params, + sizeof(ctx->params)); + + ctx->have_public_key = 1; + +exit: + mbedtls_platform_zeroize(y_hashed_digits, sizeof(y_hashed_digits)); + + return ret; +} + +int mbedtls_lmots_sign(mbedtls_lmots_private_t *ctx, + int (*f_rng)(void *, unsigned char *, size_t), + void *p_rng, const unsigned char *msg, size_t msg_size, + unsigned char *sig, size_t sig_size, size_t *sig_len) +{ + unsigned char tmp_digit_array[MBEDTLS_LMOTS_P_SIG_DIGIT_COUNT_MAX]; + /* Create a temporary buffer to prepare the signature in. This allows us to + * finish creating a signature (ensuring the process doesn't fail), and then + * erase the private key **before** writing any data into the sig parameter + * buffer. If data were directly written into the sig buffer, it might leak + * a partial signature on failure, which effectively compromises the private + * key. + */ + unsigned char tmp_sig[MBEDTLS_LMOTS_P_SIG_DIGIT_COUNT_MAX][MBEDTLS_LMOTS_N_HASH_LEN_MAX]; + unsigned char tmp_c_random[MBEDTLS_LMOTS_N_HASH_LEN_MAX]; + int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED; + + if (msg == NULL && msg_size != 0) { + return MBEDTLS_ERR_LMS_BAD_INPUT_DATA; + } + + if (sig_size < MBEDTLS_LMOTS_SIG_LEN(ctx->params.type)) { + return MBEDTLS_ERR_LMS_BUFFER_TOO_SMALL; + } + + /* Check that a private key is loaded */ + if (!ctx->have_private_key) { + return MBEDTLS_ERR_LMS_BAD_INPUT_DATA; + } + + ret = f_rng(p_rng, tmp_c_random, + MBEDTLS_LMOTS_N_HASH_LEN(ctx->params.type)); + if (ret) { + return ret; + } + + ret = create_digit_array_with_checksum(&ctx->params, + msg, msg_size, + tmp_c_random, + tmp_digit_array); + if (ret) { + goto exit; + } + + ret = hash_digit_array(&ctx->params, (unsigned char *) ctx->private_key, + NULL, tmp_digit_array, (unsigned char *) tmp_sig); + if (ret) { + goto exit; + } + + MBEDTLS_PUT_UINT32_BE(ctx->params.type, sig, MBEDTLS_LMOTS_SIG_TYPE_OFFSET); + + /* Test hook to check if sig is being written to before we invalidate the + * private key. + */ +#if defined(MBEDTLS_TEST_HOOKS) + if (mbedtls_lmots_sign_private_key_invalidated_hook != NULL) { + ret = (*mbedtls_lmots_sign_private_key_invalidated_hook)(sig); + if (ret != 0) { + return ret; + } + } +#endif /* defined(MBEDTLS_TEST_HOOKS) */ + + /* We've got a valid signature now, so it's time to make sure the private + * key can't be reused. + */ + ctx->have_private_key = 0; + mbedtls_platform_zeroize(ctx->private_key, + sizeof(ctx->private_key)); + + memcpy(sig + MBEDTLS_LMOTS_SIG_C_RANDOM_OFFSET, tmp_c_random, + MBEDTLS_LMOTS_C_RANDOM_VALUE_LEN(ctx->params.type)); + + memcpy(sig + MBEDTLS_LMOTS_SIG_SIGNATURE_OFFSET(ctx->params.type), tmp_sig, + MBEDTLS_LMOTS_P_SIG_DIGIT_COUNT(ctx->params.type) + * MBEDTLS_LMOTS_N_HASH_LEN(ctx->params.type)); + + if (sig_len != NULL) { + *sig_len = MBEDTLS_LMOTS_SIG_LEN(ctx->params.type); + } + + ret = 0; + +exit: + mbedtls_platform_zeroize(tmp_digit_array, sizeof(tmp_digit_array)); + mbedtls_platform_zeroize(tmp_sig, sizeof(tmp_sig)); + + return ret; +} + +#endif /* defined(MBEDTLS_LMS_PRIVATE) */ +#endif /* defined(MBEDTLS_LMS_C) */ diff --git a/vendor/mbedtls/library/lmots.h b/vendor/mbedtls/library/lmots.h new file mode 100644 index 0000000000..cf92d326c9 --- /dev/null +++ b/vendor/mbedtls/library/lmots.h @@ -0,0 +1,288 @@ +/** + * \file lmots.h + * + * \brief This file provides an API for the LM-OTS post-quantum-safe one-time + * public-key signature scheme as defined in RFC8554 and NIST.SP.200-208. + * This implementation currently only supports a single parameter set + * MBEDTLS_LMOTS_SHA256_N32_W8 in order to reduce complexity. + */ +/* + * Copyright The Mbed TLS Contributors + * SPDX-License-Identifier: Apache-2.0 OR GPL-2.0-or-later + */ + +#ifndef MBEDTLS_LMOTS_H +#define MBEDTLS_LMOTS_H + +#include "mbedtls/build_info.h" + +#include "psa/crypto.h" + +#include "mbedtls/lms.h" + +#include +#include + + +#define MBEDTLS_LMOTS_PUBLIC_KEY_LEN(type) (MBEDTLS_LMOTS_TYPE_LEN + \ + MBEDTLS_LMOTS_I_KEY_ID_LEN + \ + MBEDTLS_LMOTS_Q_LEAF_ID_LEN + \ + MBEDTLS_LMOTS_N_HASH_LEN(type)) + +#define MBEDTLS_LMOTS_SIG_TYPE_OFFSET (0) +#define MBEDTLS_LMOTS_SIG_C_RANDOM_OFFSET (MBEDTLS_LMOTS_SIG_TYPE_OFFSET + \ + MBEDTLS_LMOTS_TYPE_LEN) +#define MBEDTLS_LMOTS_SIG_SIGNATURE_OFFSET(type) (MBEDTLS_LMOTS_SIG_C_RANDOM_OFFSET + \ + MBEDTLS_LMOTS_C_RANDOM_VALUE_LEN(type)) + +#ifdef __cplusplus +extern "C" { +#endif + + +#if defined(MBEDTLS_TEST_HOOKS) +extern int (*mbedtls_lmots_sign_private_key_invalidated_hook)(unsigned char *); +#endif /* defined(MBEDTLS_TEST_HOOKS) */ + +#if !defined(MBEDTLS_DEPRECATED_REMOVED) +/** + * \brief This function converts a \ref psa_status_t to a + * low-level LMS error code. + * + * \param status The psa_status_t to convert + * + * \return The corresponding LMS error code. + */ +int MBEDTLS_DEPRECATED mbedtls_lms_error_from_psa(psa_status_t status); +#endif + +/** + * \brief This function initializes a public LMOTS context + * + * \param ctx The uninitialized LMOTS context that will then be + * initialized. + */ +void mbedtls_lmots_public_init(mbedtls_lmots_public_t *ctx); + +/** + * \brief This function uninitializes a public LMOTS context + * + * \param ctx The initialized LMOTS context that will then be + * uninitialized. + */ +void mbedtls_lmots_public_free(mbedtls_lmots_public_t *ctx); + +/** + * \brief This function imports an LMOTS public key into a + * LMOTS context. + * + * \note Before this function is called, the context must + * have been initialized. + * + * \note See IETF RFC8554 for details of the encoding of + * this public key. + * + * \param ctx The initialized LMOTS context store the key in. + * \param key The buffer from which the key will be read. + * #MBEDTLS_LMOTS_PUBLIC_KEY_LEN bytes will be read + * from this. + * + * \return \c 0 on success. + * \return A non-zero error code on failure. + */ +int mbedtls_lmots_import_public_key(mbedtls_lmots_public_t *ctx, + const unsigned char *key, size_t key_size); + +/** + * \brief This function exports an LMOTS public key from a + * LMOTS context that already contains a public key. + * + * \note Before this function is called, the context must + * have been initialized and the context must contain + * a public key. + * + * \note See IETF RFC8554 for details of the encoding of + * this public key. + * + * \param ctx The initialized LMOTS context that contains the + * public key. + * \param key The buffer into which the key will be output. Must + * be at least #MBEDTLS_LMOTS_PUBLIC_KEY_LEN in size. + * + * \return \c 0 on success. + * \return A non-zero error code on failure. + */ +int mbedtls_lmots_export_public_key(const mbedtls_lmots_public_t *ctx, + unsigned char *key, size_t key_size, + size_t *key_len); + +/** + * \brief This function creates a candidate public key from + * an LMOTS signature. This can then be compared to + * the real public key to determine the validity of + * the signature. + * + * \note This function is exposed publicly to be used in LMS + * signature verification, it is expected that + * mbedtls_lmots_verify will be used for LMOTS + * signature verification. + * + * \param params The LMOTS parameter set, q and I values as an + * mbedtls_lmots_parameters_t struct. + * \param msg The buffer from which the message will be read. + * \param msg_size The size of the message that will be read. + * \param sig The buffer from which the signature will be read. + * #MBEDTLS_LMOTS_SIG_LEN bytes will be read from + * this. + * \param out The buffer where the candidate public key will be + * stored. Must be at least #MBEDTLS_LMOTS_N_HASH_LEN + * bytes in size. + * + * \return \c 0 on success. + * \return A non-zero error code on failure. + */ +int mbedtls_lmots_calculate_public_key_candidate(const mbedtls_lmots_parameters_t *params, + const unsigned char *msg, + size_t msg_size, + const unsigned char *sig, + size_t sig_size, + unsigned char *out, + size_t out_size, + size_t *out_len); + +/** + * \brief This function verifies a LMOTS signature, using a + * LMOTS context that contains a public key. + * + * \warning This function is **not intended for use in + * production**, due to as-yet unsolved problems with + * handling stateful keys. The API for this function + * may change considerably in future versions. + * + * \note Before this function is called, the context must + * have been initialized and must contain a public key + * (either by import or calculation from a private + * key). + * + * \param ctx The initialized LMOTS context from which the public + * key will be read. + * \param msg The buffer from which the message will be read. + * \param msg_size The size of the message that will be read. + * \param sig The buf from which the signature will be read. + * #MBEDTLS_LMOTS_SIG_LEN bytes will be read from + * this. + * + * \return \c 0 on successful verification. + * \return A non-zero error code on failure. + */ +int mbedtls_lmots_verify(const mbedtls_lmots_public_t *ctx, + const unsigned char *msg, + size_t msg_size, const unsigned char *sig, + size_t sig_size); + +#if defined(MBEDTLS_LMS_PRIVATE) + +/** + * \brief This function initializes a private LMOTS context + * + * \param ctx The uninitialized LMOTS context that will then be + * initialized. + */ +void mbedtls_lmots_private_init(mbedtls_lmots_private_t *ctx); + +/** + * \brief This function uninitializes a private LMOTS context + * + * \param ctx The initialized LMOTS context that will then be + * uninitialized. + */ +void mbedtls_lmots_private_free(mbedtls_lmots_private_t *ctx); + +/** + * \brief This function calculates an LMOTS private key, and + * stores in into an LMOTS context. + * + * \warning This function is **not intended for use in + * production**, due to as-yet unsolved problems with + * handling stateful keys. The API for this function + * may change considerably in future versions. + * + * \note The seed must have at least 256 bits of entropy. + * + * \param ctx The initialized LMOTS context to generate the key + * into. + * \param I_key_identifier The key identifier of the key, as a 16-byte string. + * \param q_leaf_identifier The leaf identifier of key. If this LMOTS key is + * not being used as part of an LMS key, this should + * be set to 0. + * \param seed The seed used to deterministically generate the + * key. + * \param seed_size The length of the seed. + * + * \return \c 0 on success. + * \return A non-zero error code on failure. + */ +int mbedtls_lmots_generate_private_key(mbedtls_lmots_private_t *ctx, + mbedtls_lmots_algorithm_type_t type, + const unsigned char I_key_identifier[MBEDTLS_LMOTS_I_KEY_ID_LEN], + uint32_t q_leaf_identifier, + const unsigned char *seed, + size_t seed_size); + +/** + * \brief This function generates an LMOTS public key from a + * LMOTS context that already contains a private key. + * + * \note Before this function is called, the context must + * have been initialized and the context must contain + * a private key. + * + * \param ctx The initialized LMOTS context to generate the key + * from and store it into. + * + * \return \c 0 on success. + * \return A non-zero error code on failure. + */ +int mbedtls_lmots_calculate_public_key(mbedtls_lmots_public_t *ctx, + const mbedtls_lmots_private_t *priv_ctx); + +/** + * \brief This function creates a LMOTS signature, using a + * LMOTS context that contains a private key. + * + * \note Before this function is called, the context must + * have been initialized and must contain a private + * key. + * + * \note LMOTS private keys can only be used once, otherwise + * attackers may be able to create forged signatures. + * If the signing operation is successful, the private + * key in the context will be erased, and no further + * signing will be possible until another private key + * is loaded + * + * \param ctx The initialized LMOTS context from which the + * private key will be read. + * \param f_rng The RNG function to be used for signature + * generation. + * \param p_rng The RNG context to be passed to f_rng + * \param msg The buffer from which the message will be read. + * \param msg_size The size of the message that will be read. + * \param sig The buf into which the signature will be stored. + * Must be at least #MBEDTLS_LMOTS_SIG_LEN in size. + * + * \return \c 0 on success. + * \return A non-zero error code on failure. + */ +int mbedtls_lmots_sign(mbedtls_lmots_private_t *ctx, + int (*f_rng)(void *, unsigned char *, size_t), + void *p_rng, const unsigned char *msg, size_t msg_size, + unsigned char *sig, size_t sig_size, size_t *sig_len); + +#endif /* defined(MBEDTLS_LMS_PRIVATE) */ + +#ifdef __cplusplus +} +#endif + +#endif /* MBEDTLS_LMOTS_H */ diff --git a/vendor/mbedtls/library/lms.c b/vendor/mbedtls/library/lms.c new file mode 100644 index 0000000000..8d3cae0524 --- /dev/null +++ b/vendor/mbedtls/library/lms.c @@ -0,0 +1,761 @@ +/* + * The LMS stateful-hash public-key signature scheme + * + * Copyright The Mbed TLS Contributors + * SPDX-License-Identifier: Apache-2.0 OR GPL-2.0-or-later + */ + +/* + * The following sources were referenced in the design of this implementation + * of the LMS algorithm: + * + * [1] IETF RFC8554 + * D. McGrew, M. Curcio, S.Fluhrer + * https://datatracker.ietf.org/doc/html/rfc8554 + * + * [2] NIST Special Publication 800-208 + * David A. Cooper et. al. + * https://nvlpubs.nist.gov/nistpubs/SpecialPublications/NIST.SP.800-208.pdf + */ + +#include "common.h" + +#if defined(MBEDTLS_LMS_C) + +#include + +#include "lmots.h" + +#include "psa/crypto.h" +#include "psa_util_internal.h" +#include "mbedtls/lms.h" +#include "mbedtls/error.h" +#include "mbedtls/platform_util.h" + +#include "mbedtls/platform.h" + +/* Define a local translating function to save code size by not using too many + * arguments in each translating place. */ +static int local_err_translation(psa_status_t status) +{ + return psa_status_to_mbedtls(status, psa_to_lms_errors, + ARRAY_LENGTH(psa_to_lms_errors), + psa_generic_status_to_mbedtls); +} +#define PSA_TO_MBEDTLS_ERR(status) local_err_translation(status) + +#define SIG_Q_LEAF_ID_OFFSET (0) +#define SIG_OTS_SIG_OFFSET (SIG_Q_LEAF_ID_OFFSET + \ + MBEDTLS_LMOTS_Q_LEAF_ID_LEN) +#define SIG_TYPE_OFFSET(otstype) (SIG_OTS_SIG_OFFSET + \ + MBEDTLS_LMOTS_SIG_LEN(otstype)) +#define SIG_PATH_OFFSET(otstype) (SIG_TYPE_OFFSET(otstype) + \ + MBEDTLS_LMS_TYPE_LEN) + +#define PUBLIC_KEY_TYPE_OFFSET (0) +#define PUBLIC_KEY_OTSTYPE_OFFSET (PUBLIC_KEY_TYPE_OFFSET + \ + MBEDTLS_LMS_TYPE_LEN) +#define PUBLIC_KEY_I_KEY_ID_OFFSET (PUBLIC_KEY_OTSTYPE_OFFSET + \ + MBEDTLS_LMOTS_TYPE_LEN) +#define PUBLIC_KEY_ROOT_NODE_OFFSET (PUBLIC_KEY_I_KEY_ID_OFFSET + \ + MBEDTLS_LMOTS_I_KEY_ID_LEN) + + +/* Currently only support H=10 */ +#define H_TREE_HEIGHT_MAX 10 +#define MERKLE_TREE_NODE_AM(type) ((size_t) 1 << (MBEDTLS_LMS_H_TREE_HEIGHT(type) + 1u)) +#define MERKLE_TREE_LEAF_NODE_AM(type) ((size_t) 1 << MBEDTLS_LMS_H_TREE_HEIGHT(type)) +#define MERKLE_TREE_INTERNAL_NODE_AM(type) ((unsigned int) \ + (1u << MBEDTLS_LMS_H_TREE_HEIGHT(type))) + +#define D_CONST_LEN (2) +static const unsigned char D_LEAF_CONSTANT_BYTES[D_CONST_LEN] = { 0x82, 0x82 }; +static const unsigned char D_INTR_CONSTANT_BYTES[D_CONST_LEN] = { 0x83, 0x83 }; + + +/* Calculate the value of a leaf node of the Merkle tree (which is a hash of a + * public key and some other parameters like the leaf index). This function + * implements RFC8554 section 5.3, in the case where r >= 2^h. + * + * params The LMS parameter set, the underlying LMOTS + * parameter set, and I value which describe the key + * being used. + * + * pub_key The public key of the private whose index + * corresponds to the index of this leaf node. This + * is a hash output. + * + * r_node_idx The index of this node in the Merkle tree. Note + * that the root node of the Merkle tree is + * 1-indexed. + * + * out The output node value, which is a hash output. + */ +static int create_merkle_leaf_value(const mbedtls_lms_parameters_t *params, + unsigned char *pub_key, + unsigned int r_node_idx, + unsigned char *out) +{ + psa_hash_operation_t op; + psa_status_t status = PSA_ERROR_CORRUPTION_DETECTED; + size_t output_hash_len; + unsigned char r_node_idx_bytes[4]; + + op = psa_hash_operation_init(); + status = psa_hash_setup(&op, PSA_ALG_SHA_256); + if (status != PSA_SUCCESS) { + goto exit; + } + + status = psa_hash_update(&op, params->I_key_identifier, + MBEDTLS_LMOTS_I_KEY_ID_LEN); + if (status != PSA_SUCCESS) { + goto exit; + } + + MBEDTLS_PUT_UINT32_BE(r_node_idx, r_node_idx_bytes, 0); + status = psa_hash_update(&op, r_node_idx_bytes, 4); + if (status != PSA_SUCCESS) { + goto exit; + } + + status = psa_hash_update(&op, D_LEAF_CONSTANT_BYTES, D_CONST_LEN); + if (status != PSA_SUCCESS) { + goto exit; + } + + status = psa_hash_update(&op, pub_key, + MBEDTLS_LMOTS_N_HASH_LEN(params->otstype)); + if (status != PSA_SUCCESS) { + goto exit; + } + + status = psa_hash_finish(&op, out, MBEDTLS_LMS_M_NODE_BYTES(params->type), + &output_hash_len); + if (status != PSA_SUCCESS) { + goto exit; + } + +exit: + psa_hash_abort(&op); + + return PSA_TO_MBEDTLS_ERR(status); +} + +/* Calculate the value of an internal node of the Merkle tree (which is a hash + * of a public key and some other parameters like the node index). This function + * implements RFC8554 section 5.3, in the case where r < 2^h. + * + * params The LMS parameter set, the underlying LMOTS + * parameter set, and I value which describe the key + * being used. + * + * left_node The value of the child of this node which is on + * the left-hand side. As with all nodes on the + * Merkle tree, this is a hash output. + * + * right_node The value of the child of this node which is on + * the right-hand side. As with all nodes on the + * Merkle tree, this is a hash output. + * + * r_node_idx The index of this node in the Merkle tree. Note + * that the root node of the Merkle tree is + * 1-indexed. + * + * out The output node value, which is a hash output. + */ +static int create_merkle_internal_value(const mbedtls_lms_parameters_t *params, + const unsigned char *left_node, + const unsigned char *right_node, + unsigned int r_node_idx, + unsigned char *out) +{ + psa_hash_operation_t op; + psa_status_t status = PSA_ERROR_CORRUPTION_DETECTED; + size_t output_hash_len; + unsigned char r_node_idx_bytes[4]; + + op = psa_hash_operation_init(); + status = psa_hash_setup(&op, PSA_ALG_SHA_256); + if (status != PSA_SUCCESS) { + goto exit; + } + + status = psa_hash_update(&op, params->I_key_identifier, + MBEDTLS_LMOTS_I_KEY_ID_LEN); + if (status != PSA_SUCCESS) { + goto exit; + } + + MBEDTLS_PUT_UINT32_BE(r_node_idx, r_node_idx_bytes, 0); + status = psa_hash_update(&op, r_node_idx_bytes, 4); + if (status != PSA_SUCCESS) { + goto exit; + } + + status = psa_hash_update(&op, D_INTR_CONSTANT_BYTES, D_CONST_LEN); + if (status != PSA_SUCCESS) { + goto exit; + } + + status = psa_hash_update(&op, left_node, + MBEDTLS_LMS_M_NODE_BYTES(params->type)); + if (status != PSA_SUCCESS) { + goto exit; + } + + status = psa_hash_update(&op, right_node, + MBEDTLS_LMS_M_NODE_BYTES(params->type)); + if (status != PSA_SUCCESS) { + goto exit; + } + + status = psa_hash_finish(&op, out, MBEDTLS_LMS_M_NODE_BYTES(params->type), + &output_hash_len); + if (status != PSA_SUCCESS) { + goto exit; + } + +exit: + psa_hash_abort(&op); + + return PSA_TO_MBEDTLS_ERR(status); +} + +void mbedtls_lms_public_init(mbedtls_lms_public_t *ctx) +{ + memset(ctx, 0, sizeof(*ctx)); +} + +void mbedtls_lms_public_free(mbedtls_lms_public_t *ctx) +{ + mbedtls_platform_zeroize(ctx, sizeof(*ctx)); +} + +int mbedtls_lms_import_public_key(mbedtls_lms_public_t *ctx, + const unsigned char *key, size_t key_size) +{ + mbedtls_lms_algorithm_type_t type; + mbedtls_lmots_algorithm_type_t otstype; + + type = (mbedtls_lms_algorithm_type_t) MBEDTLS_GET_UINT32_BE(key, PUBLIC_KEY_TYPE_OFFSET); + if (type != MBEDTLS_LMS_SHA256_M32_H10) { + return MBEDTLS_ERR_LMS_BAD_INPUT_DATA; + } + ctx->params.type = type; + + if (key_size != MBEDTLS_LMS_PUBLIC_KEY_LEN(ctx->params.type)) { + return MBEDTLS_ERR_LMS_BAD_INPUT_DATA; + } + + otstype = (mbedtls_lmots_algorithm_type_t) + MBEDTLS_GET_UINT32_BE(key, PUBLIC_KEY_OTSTYPE_OFFSET); + if (otstype != MBEDTLS_LMOTS_SHA256_N32_W8) { + return MBEDTLS_ERR_LMS_BAD_INPUT_DATA; + } + ctx->params.otstype = otstype; + + memcpy(ctx->params.I_key_identifier, + key + PUBLIC_KEY_I_KEY_ID_OFFSET, + MBEDTLS_LMOTS_I_KEY_ID_LEN); + memcpy(ctx->T_1_pub_key, key + PUBLIC_KEY_ROOT_NODE_OFFSET, + MBEDTLS_LMS_M_NODE_BYTES(ctx->params.type)); + + ctx->have_public_key = 1; + + return 0; +} + +int mbedtls_lms_export_public_key(const mbedtls_lms_public_t *ctx, + unsigned char *key, + size_t key_size, size_t *key_len) +{ + if (key_size < MBEDTLS_LMS_PUBLIC_KEY_LEN(ctx->params.type)) { + return MBEDTLS_ERR_LMS_BUFFER_TOO_SMALL; + } + + if (!ctx->have_public_key) { + return MBEDTLS_ERR_LMS_BAD_INPUT_DATA; + } + + MBEDTLS_PUT_UINT32_BE(ctx->params.type, key, PUBLIC_KEY_TYPE_OFFSET); + MBEDTLS_PUT_UINT32_BE(ctx->params.otstype, key, PUBLIC_KEY_OTSTYPE_OFFSET); + memcpy(key + PUBLIC_KEY_I_KEY_ID_OFFSET, + ctx->params.I_key_identifier, + MBEDTLS_LMOTS_I_KEY_ID_LEN); + memcpy(key +PUBLIC_KEY_ROOT_NODE_OFFSET, + ctx->T_1_pub_key, + MBEDTLS_LMS_M_NODE_BYTES(ctx->params.type)); + + if (key_len != NULL) { + *key_len = MBEDTLS_LMS_PUBLIC_KEY_LEN(ctx->params.type); + } + + return 0; +} + +int mbedtls_lms_verify(const mbedtls_lms_public_t *ctx, + const unsigned char *msg, size_t msg_size, + const unsigned char *sig, size_t sig_size) +{ + unsigned int q_leaf_identifier; + unsigned char Kc_candidate_ots_pub_key[MBEDTLS_LMOTS_N_HASH_LEN_MAX]; + unsigned char Tc_candidate_root_node[MBEDTLS_LMS_M_NODE_BYTES_MAX]; + unsigned int height; + unsigned int curr_node_id; + unsigned int parent_node_id; + const unsigned char *left_node; + const unsigned char *right_node; + mbedtls_lmots_parameters_t ots_params; + int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED; + + if (!ctx->have_public_key) { + return MBEDTLS_ERR_LMS_BAD_INPUT_DATA; + } + + if (ctx->params.type + != MBEDTLS_LMS_SHA256_M32_H10) { + return MBEDTLS_ERR_LMS_BAD_INPUT_DATA; + } + + if (ctx->params.otstype + != MBEDTLS_LMOTS_SHA256_N32_W8) { + return MBEDTLS_ERR_LMS_BAD_INPUT_DATA; + } + + if (sig_size != MBEDTLS_LMS_SIG_LEN(ctx->params.type, ctx->params.otstype)) { + return MBEDTLS_ERR_LMS_VERIFY_FAILED; + } + + if (sig_size < SIG_OTS_SIG_OFFSET + MBEDTLS_LMOTS_TYPE_LEN) { + return MBEDTLS_ERR_LMS_VERIFY_FAILED; + } + + if (MBEDTLS_GET_UINT32_BE(sig, SIG_OTS_SIG_OFFSET + MBEDTLS_LMOTS_SIG_TYPE_OFFSET) + != MBEDTLS_LMOTS_SHA256_N32_W8) { + return MBEDTLS_ERR_LMS_VERIFY_FAILED; + } + + if (sig_size < SIG_TYPE_OFFSET(ctx->params.otstype) + MBEDTLS_LMS_TYPE_LEN) { + return MBEDTLS_ERR_LMS_VERIFY_FAILED; + } + + if (MBEDTLS_GET_UINT32_BE(sig, SIG_TYPE_OFFSET(ctx->params.otstype)) + != MBEDTLS_LMS_SHA256_M32_H10) { + return MBEDTLS_ERR_LMS_VERIFY_FAILED; + } + + + q_leaf_identifier = MBEDTLS_GET_UINT32_BE(sig, SIG_Q_LEAF_ID_OFFSET); + + if (q_leaf_identifier >= MERKLE_TREE_LEAF_NODE_AM(ctx->params.type)) { + return MBEDTLS_ERR_LMS_VERIFY_FAILED; + } + + memcpy(ots_params.I_key_identifier, + ctx->params.I_key_identifier, + MBEDTLS_LMOTS_I_KEY_ID_LEN); + MBEDTLS_PUT_UINT32_BE(q_leaf_identifier, ots_params.q_leaf_identifier, 0); + ots_params.type = ctx->params.otstype; + + ret = mbedtls_lmots_calculate_public_key_candidate(&ots_params, + msg, + msg_size, + sig + SIG_OTS_SIG_OFFSET, + MBEDTLS_LMOTS_SIG_LEN(ctx->params.otstype), + Kc_candidate_ots_pub_key, + sizeof(Kc_candidate_ots_pub_key), + NULL); + if (ret != 0) { + return MBEDTLS_ERR_LMS_VERIFY_FAILED; + } + + create_merkle_leaf_value( + &ctx->params, + Kc_candidate_ots_pub_key, + MERKLE_TREE_INTERNAL_NODE_AM(ctx->params.type) + q_leaf_identifier, + Tc_candidate_root_node); + + curr_node_id = MERKLE_TREE_INTERNAL_NODE_AM(ctx->params.type) + + q_leaf_identifier; + + for (height = 0; height < MBEDTLS_LMS_H_TREE_HEIGHT(ctx->params.type); + height++) { + parent_node_id = curr_node_id / 2; + + /* Left/right node ordering matters for the hash */ + if (curr_node_id & 1) { + left_node = sig + SIG_PATH_OFFSET(ctx->params.otstype) + + height * MBEDTLS_LMS_M_NODE_BYTES(ctx->params.type); + right_node = Tc_candidate_root_node; + } else { + left_node = Tc_candidate_root_node; + right_node = sig + SIG_PATH_OFFSET(ctx->params.otstype) + + height * MBEDTLS_LMS_M_NODE_BYTES(ctx->params.type); + } + + create_merkle_internal_value(&ctx->params, left_node, right_node, + parent_node_id, Tc_candidate_root_node); + + curr_node_id /= 2; + } + + if (memcmp(Tc_candidate_root_node, ctx->T_1_pub_key, + MBEDTLS_LMS_M_NODE_BYTES(ctx->params.type))) { + return MBEDTLS_ERR_LMS_VERIFY_FAILED; + } + + return 0; +} + +#if defined(MBEDTLS_LMS_PRIVATE) + +/* Calculate a full Merkle tree based on a private key. This function + * implements RFC8554 section 5.3, and is used to generate a public key (as the + * public key is the root node of the Merkle tree). + * + * ctx The LMS private context, containing a parameter + * set and private key material consisting of both + * public and private OTS. + * + * tree The output tree, which is 2^(H + 1) hash outputs. + * In the case of H=10 we have 2048 tree nodes (of + * which 1024 of them are leaf nodes). Note that + * because the Merkle tree root is 1-indexed, the 0 + * index tree node is never used. + */ +static int calculate_merkle_tree(const mbedtls_lms_private_t *ctx, + unsigned char *tree) +{ + unsigned int priv_key_idx; + unsigned int r_node_idx; + int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED; + + /* First create the leaf nodes, in ascending order */ + for (priv_key_idx = 0; + priv_key_idx < MERKLE_TREE_INTERNAL_NODE_AM(ctx->params.type); + priv_key_idx++) { + r_node_idx = MERKLE_TREE_INTERNAL_NODE_AM(ctx->params.type) + priv_key_idx; + + ret = create_merkle_leaf_value(&ctx->params, + ctx->ots_public_keys[priv_key_idx].public_key, + r_node_idx, + &tree[r_node_idx * MBEDTLS_LMS_M_NODE_BYTES( + ctx->params.type)]); + if (ret != 0) { + return ret; + } + } + + /* Then the internal nodes, in reverse order so that we can guarantee the + * parent has been created */ + for (r_node_idx = MERKLE_TREE_INTERNAL_NODE_AM(ctx->params.type) - 1; + r_node_idx > 0; + r_node_idx--) { + ret = create_merkle_internal_value(&ctx->params, + &tree[(r_node_idx * 2) * + MBEDTLS_LMS_M_NODE_BYTES(ctx->params.type)], + &tree[(r_node_idx * 2 + 1) * + MBEDTLS_LMS_M_NODE_BYTES(ctx->params.type)], + r_node_idx, + &tree[r_node_idx * + MBEDTLS_LMS_M_NODE_BYTES(ctx->params.type)]); + if (ret != 0) { + return ret; + } + } + + return 0; +} + +/* Calculate a path from a leaf node of the Merkle tree to the root of the tree, + * and return the full path. This function implements RFC8554 section 5.4.1, as + * the Merkle path is the main component of an LMS signature. + * + * ctx The LMS private context, containing a parameter + * set and private key material consisting of both + * public and private OTS. + * + * leaf_node_id Which leaf node to calculate the path from. + * + * path The output path, which is H hash outputs. + */ +static int get_merkle_path(mbedtls_lms_private_t *ctx, + unsigned int leaf_node_id, + unsigned char *path) +{ + const size_t node_bytes = MBEDTLS_LMS_M_NODE_BYTES(ctx->params.type); + unsigned int curr_node_id = leaf_node_id; + unsigned int adjacent_node_id; + unsigned char *tree = NULL; + unsigned int height; + int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED; + + tree = mbedtls_calloc((size_t) MERKLE_TREE_NODE_AM(ctx->params.type), + node_bytes); + if (tree == NULL) { + return MBEDTLS_ERR_LMS_ALLOC_FAILED; + } + + ret = calculate_merkle_tree(ctx, tree); + if (ret != 0) { + goto exit; + } + + for (height = 0; height < MBEDTLS_LMS_H_TREE_HEIGHT(ctx->params.type); + height++) { + adjacent_node_id = curr_node_id ^ 1; + + memcpy(&path[height * node_bytes], + &tree[adjacent_node_id * node_bytes], node_bytes); + + curr_node_id >>= 1; + } + + ret = 0; + +exit: + mbedtls_zeroize_and_free(tree, node_bytes * + (size_t) MERKLE_TREE_NODE_AM(ctx->params.type)); + + return ret; +} + +void mbedtls_lms_private_init(mbedtls_lms_private_t *ctx) +{ + memset(ctx, 0, sizeof(*ctx)); +} + +void mbedtls_lms_private_free(mbedtls_lms_private_t *ctx) +{ + unsigned int idx; + + if (ctx->have_private_key) { + if (ctx->ots_private_keys != NULL) { + for (idx = 0; idx < MERKLE_TREE_LEAF_NODE_AM(ctx->params.type); idx++) { + mbedtls_lmots_private_free(&ctx->ots_private_keys[idx]); + } + } + + if (ctx->ots_public_keys != NULL) { + for (idx = 0; idx < MERKLE_TREE_LEAF_NODE_AM(ctx->params.type); idx++) { + mbedtls_lmots_public_free(&ctx->ots_public_keys[idx]); + } + } + + mbedtls_free(ctx->ots_private_keys); + mbedtls_free(ctx->ots_public_keys); + } + + mbedtls_platform_zeroize(ctx, sizeof(*ctx)); +} + + +int mbedtls_lms_generate_private_key(mbedtls_lms_private_t *ctx, + mbedtls_lms_algorithm_type_t type, + mbedtls_lmots_algorithm_type_t otstype, + int (*f_rng)(void *, unsigned char *, size_t), + void *p_rng, const unsigned char *seed, + size_t seed_size) +{ + unsigned int idx = 0; + int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED; + + if (type != MBEDTLS_LMS_SHA256_M32_H10) { + return MBEDTLS_ERR_LMS_BAD_INPUT_DATA; + } + + if (otstype != MBEDTLS_LMOTS_SHA256_N32_W8) { + return MBEDTLS_ERR_LMS_BAD_INPUT_DATA; + } + + if (ctx->have_private_key) { + return MBEDTLS_ERR_LMS_BAD_INPUT_DATA; + } + + ctx->params.type = type; + ctx->params.otstype = otstype; + ctx->have_private_key = 1; + + ret = f_rng(p_rng, + ctx->params.I_key_identifier, + MBEDTLS_LMOTS_I_KEY_ID_LEN); + if (ret != 0) { + goto exit; + } + + /* Requires a cast to size_t to avoid an implicit cast warning on certain + * platforms (particularly Windows) */ + ctx->ots_private_keys = mbedtls_calloc((size_t) MERKLE_TREE_LEAF_NODE_AM(ctx->params.type), + sizeof(*ctx->ots_private_keys)); + if (ctx->ots_private_keys == NULL) { + ret = MBEDTLS_ERR_LMS_ALLOC_FAILED; + goto exit; + } + + /* Requires a cast to size_t to avoid an implicit cast warning on certain + * platforms (particularly Windows) */ + ctx->ots_public_keys = mbedtls_calloc((size_t) MERKLE_TREE_LEAF_NODE_AM(ctx->params.type), + sizeof(*ctx->ots_public_keys)); + if (ctx->ots_public_keys == NULL) { + ret = MBEDTLS_ERR_LMS_ALLOC_FAILED; + goto exit; + } + + for (idx = 0; idx < MERKLE_TREE_LEAF_NODE_AM(ctx->params.type); idx++) { + mbedtls_lmots_private_init(&ctx->ots_private_keys[idx]); + mbedtls_lmots_public_init(&ctx->ots_public_keys[idx]); + } + + + for (idx = 0; idx < MERKLE_TREE_LEAF_NODE_AM(ctx->params.type); idx++) { + ret = mbedtls_lmots_generate_private_key(&ctx->ots_private_keys[idx], + otstype, + ctx->params.I_key_identifier, + idx, seed, seed_size); + if (ret != 0) { + goto exit; + } + + ret = mbedtls_lmots_calculate_public_key(&ctx->ots_public_keys[idx], + &ctx->ots_private_keys[idx]); + if (ret != 0) { + goto exit; + } + } + + ctx->q_next_usable_key = 0; + +exit: + if (ret != 0) { + mbedtls_lms_private_free(ctx); + } + + return ret; +} + +int mbedtls_lms_calculate_public_key(mbedtls_lms_public_t *ctx, + const mbedtls_lms_private_t *priv_ctx) +{ + const size_t node_bytes = MBEDTLS_LMS_M_NODE_BYTES(priv_ctx->params.type); + int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED; + unsigned char *tree = NULL; + + if (!priv_ctx->have_private_key) { + return MBEDTLS_ERR_LMS_BAD_INPUT_DATA; + } + + if (priv_ctx->params.type + != MBEDTLS_LMS_SHA256_M32_H10) { + return MBEDTLS_ERR_LMS_BAD_INPUT_DATA; + } + + if (priv_ctx->params.otstype + != MBEDTLS_LMOTS_SHA256_N32_W8) { + return MBEDTLS_ERR_LMS_BAD_INPUT_DATA; + } + + tree = mbedtls_calloc((size_t) MERKLE_TREE_NODE_AM(priv_ctx->params.type), + node_bytes); + if (tree == NULL) { + return MBEDTLS_ERR_LMS_ALLOC_FAILED; + } + + memcpy(&ctx->params, &priv_ctx->params, + sizeof(mbedtls_lmots_parameters_t)); + + ret = calculate_merkle_tree(priv_ctx, tree); + if (ret != 0) { + goto exit; + } + + /* Root node is always at position 1, due to 1-based indexing */ + memcpy(ctx->T_1_pub_key, &tree[node_bytes], node_bytes); + + ctx->have_public_key = 1; + + ret = 0; + +exit: + mbedtls_zeroize_and_free(tree, node_bytes * + (size_t) MERKLE_TREE_NODE_AM(priv_ctx->params.type)); + + return ret; +} + + +int mbedtls_lms_sign(mbedtls_lms_private_t *ctx, + int (*f_rng)(void *, unsigned char *, size_t), + void *p_rng, const unsigned char *msg, + unsigned int msg_size, unsigned char *sig, size_t sig_size, + size_t *sig_len) +{ + uint32_t q_leaf_identifier; + int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED; + + if (!ctx->have_private_key) { + return MBEDTLS_ERR_LMS_BAD_INPUT_DATA; + } + + if (sig_size < MBEDTLS_LMS_SIG_LEN(ctx->params.type, ctx->params.otstype)) { + return MBEDTLS_ERR_LMS_BUFFER_TOO_SMALL; + } + + if (ctx->params.type != MBEDTLS_LMS_SHA256_M32_H10) { + return MBEDTLS_ERR_LMS_BAD_INPUT_DATA; + } + + if (ctx->params.otstype + != MBEDTLS_LMOTS_SHA256_N32_W8) { + return MBEDTLS_ERR_LMS_BAD_INPUT_DATA; + } + + if (ctx->q_next_usable_key >= MERKLE_TREE_LEAF_NODE_AM(ctx->params.type)) { + return MBEDTLS_ERR_LMS_OUT_OF_PRIVATE_KEYS; + } + + + q_leaf_identifier = ctx->q_next_usable_key; + /* This new value must _always_ be written back to the disk before the + * signature is returned. + */ + ctx->q_next_usable_key += 1; + + if (MBEDTLS_LMS_SIG_LEN(ctx->params.type, ctx->params.otstype) + < SIG_OTS_SIG_OFFSET) { + return MBEDTLS_ERR_LMS_BAD_INPUT_DATA; + } + + ret = mbedtls_lmots_sign(&ctx->ots_private_keys[q_leaf_identifier], + f_rng, + p_rng, + msg, + msg_size, + sig + SIG_OTS_SIG_OFFSET, + MBEDTLS_LMS_SIG_LEN(ctx->params.type, + ctx->params.otstype) - SIG_OTS_SIG_OFFSET, + NULL); + if (ret != 0) { + return ret; + } + + MBEDTLS_PUT_UINT32_BE(ctx->params.type, sig, SIG_TYPE_OFFSET(ctx->params.otstype)); + MBEDTLS_PUT_UINT32_BE(q_leaf_identifier, sig, SIG_Q_LEAF_ID_OFFSET); + + ret = get_merkle_path(ctx, + MERKLE_TREE_INTERNAL_NODE_AM(ctx->params.type) + q_leaf_identifier, + sig + SIG_PATH_OFFSET(ctx->params.otstype)); + if (ret != 0) { + return ret; + } + + if (sig_len != NULL) { + *sig_len = MBEDTLS_LMS_SIG_LEN(ctx->params.type, ctx->params.otstype); + } + + + return 0; +} + +#endif /* defined(MBEDTLS_LMS_PRIVATE) */ +#endif /* defined(MBEDTLS_LMS_C) */ diff --git a/vendor/mbedtls/library/md.c b/vendor/mbedtls/library/md.c index 45563781d5..12a3ea2374 100644 --- a/vendor/mbedtls/library/md.c +++ b/vendor/mbedtls/library/md.c @@ -6,37 +6,50 @@ * \author Adriaan de Jong * * Copyright The Mbed TLS Contributors - * SPDX-License-Identifier: Apache-2.0 - * - * Licensed under the Apache License, Version 2.0 (the "License"); you may - * not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT - * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. + * SPDX-License-Identifier: Apache-2.0 OR GPL-2.0-or-later */ #include "common.h" -#if defined(MBEDTLS_MD_C) +/* + * Availability of functions in this module is controlled by two + * feature macros: + * - MBEDTLS_MD_C enables the whole module; + * - MBEDTLS_MD_LIGHT enables only functions for hashing and accessing + * most hash metadata (everything except string names); is it + * automatically set whenever MBEDTLS_MD_C is defined. + * + * In this file, functions from MD_LIGHT are at the top, MD_C at the end. + * + * In the future we may want to change the contract of some functions + * (behaviour with NULL arguments) depending on whether MD_C is defined or + * only MD_LIGHT. Also, the exact scope of MD_LIGHT might vary. + * + * For these reasons, we're keeping MD_LIGHT internal for now. + */ +#if defined(MBEDTLS_MD_LIGHT) #include "mbedtls/md.h" -#include "mbedtls/md_internal.h" +#include "md_wrap.h" #include "mbedtls/platform_util.h" #include "mbedtls/error.h" -#include "mbedtls/md2.h" -#include "mbedtls/md4.h" #include "mbedtls/md5.h" #include "mbedtls/ripemd160.h" #include "mbedtls/sha1.h" #include "mbedtls/sha256.h" #include "mbedtls/sha512.h" +#include "mbedtls/sha3.h" + +#if defined(MBEDTLS_PSA_CRYPTO_C) +#include +#include "md_psa.h" +#include "psa_util_internal.h" +#endif + +#if defined(MBEDTLS_MD_SOME_PSA) +#include "psa_crypto_core.h" +#endif #include "mbedtls/platform.h" @@ -46,227 +59,202 @@ #include #endif -#if defined(MBEDTLS_MD2_C) -const mbedtls_md_info_t mbedtls_md2_info = { - "MD2", - MBEDTLS_MD_MD2, - 16, - 16, -}; +/* See comment above MBEDTLS_MD_MAX_SIZE in md.h */ +#if defined(MBEDTLS_PSA_CRYPTO_C) && MBEDTLS_MD_MAX_SIZE < PSA_HASH_MAX_SIZE +#error "Internal error: MBEDTLS_MD_MAX_SIZE < PSA_HASH_MAX_SIZE" #endif -#if defined(MBEDTLS_MD4_C) -const mbedtls_md_info_t mbedtls_md4_info = { - "MD4", - MBEDTLS_MD_MD4, - 16, - 64, -}; +#if defined(MBEDTLS_MD_C) +#define MD_INFO(type, out_size, block_size) type, out_size, block_size, +#else +#define MD_INFO(type, out_size, block_size) type, out_size, #endif -#if defined(MBEDTLS_MD5_C) -const mbedtls_md_info_t mbedtls_md5_info = { - "MD5", - MBEDTLS_MD_MD5, - 16, - 64, +#if defined(MBEDTLS_MD_CAN_MD5) +static const mbedtls_md_info_t mbedtls_md5_info = { + MD_INFO(MBEDTLS_MD_MD5, 16, 64) }; #endif -#if defined(MBEDTLS_RIPEMD160_C) -const mbedtls_md_info_t mbedtls_ripemd160_info = { - "RIPEMD160", - MBEDTLS_MD_RIPEMD160, - 20, - 64, +#if defined(MBEDTLS_MD_CAN_RIPEMD160) +static const mbedtls_md_info_t mbedtls_ripemd160_info = { + MD_INFO(MBEDTLS_MD_RIPEMD160, 20, 64) }; #endif -#if defined(MBEDTLS_SHA1_C) -const mbedtls_md_info_t mbedtls_sha1_info = { - "SHA1", - MBEDTLS_MD_SHA1, - 20, - 64, +#if defined(MBEDTLS_MD_CAN_SHA1) +static const mbedtls_md_info_t mbedtls_sha1_info = { + MD_INFO(MBEDTLS_MD_SHA1, 20, 64) }; #endif -#if defined(MBEDTLS_SHA256_C) -const mbedtls_md_info_t mbedtls_sha224_info = { - "SHA224", - MBEDTLS_MD_SHA224, - 28, - 64, +#if defined(MBEDTLS_MD_CAN_SHA224) +static const mbedtls_md_info_t mbedtls_sha224_info = { + MD_INFO(MBEDTLS_MD_SHA224, 28, 64) }; +#endif -const mbedtls_md_info_t mbedtls_sha256_info = { - "SHA256", - MBEDTLS_MD_SHA256, - 32, - 64, +#if defined(MBEDTLS_MD_CAN_SHA256) +static const mbedtls_md_info_t mbedtls_sha256_info = { + MD_INFO(MBEDTLS_MD_SHA256, 32, 64) }; #endif -#if defined(MBEDTLS_SHA512_C) -#if !defined(MBEDTLS_SHA512_NO_SHA384) -const mbedtls_md_info_t mbedtls_sha384_info = { - "SHA384", - MBEDTLS_MD_SHA384, - 48, - 128, +#if defined(MBEDTLS_MD_CAN_SHA384) +static const mbedtls_md_info_t mbedtls_sha384_info = { + MD_INFO(MBEDTLS_MD_SHA384, 48, 128) }; #endif -const mbedtls_md_info_t mbedtls_sha512_info = { - "SHA512", - MBEDTLS_MD_SHA512, - 64, - 128, +#if defined(MBEDTLS_MD_CAN_SHA512) +static const mbedtls_md_info_t mbedtls_sha512_info = { + MD_INFO(MBEDTLS_MD_SHA512, 64, 128) }; #endif -/* - * Reminder: update profiles in x509_crt.c when adding a new hash! - */ -static const int supported_digests[] = { - -#if defined(MBEDTLS_SHA512_C) - MBEDTLS_MD_SHA512, -#if !defined(MBEDTLS_SHA512_NO_SHA384) - MBEDTLS_MD_SHA384, -#endif +#if defined(MBEDTLS_MD_CAN_SHA3_224) +static const mbedtls_md_info_t mbedtls_sha3_224_info = { + MD_INFO(MBEDTLS_MD_SHA3_224, 28, 144) +}; #endif -#if defined(MBEDTLS_SHA256_C) - MBEDTLS_MD_SHA256, - MBEDTLS_MD_SHA224, +#if defined(MBEDTLS_MD_CAN_SHA3_256) +static const mbedtls_md_info_t mbedtls_sha3_256_info = { + MD_INFO(MBEDTLS_MD_SHA3_256, 32, 136) +}; #endif -#if defined(MBEDTLS_SHA1_C) - MBEDTLS_MD_SHA1, +#if defined(MBEDTLS_MD_CAN_SHA3_384) +static const mbedtls_md_info_t mbedtls_sha3_384_info = { + MD_INFO(MBEDTLS_MD_SHA3_384, 48, 104) +}; #endif -#if defined(MBEDTLS_RIPEMD160_C) - MBEDTLS_MD_RIPEMD160, +#if defined(MBEDTLS_MD_CAN_SHA3_512) +static const mbedtls_md_info_t mbedtls_sha3_512_info = { + MD_INFO(MBEDTLS_MD_SHA3_512, 64, 72) +}; #endif -#if defined(MBEDTLS_MD5_C) - MBEDTLS_MD_MD5, +const mbedtls_md_info_t *mbedtls_md_info_from_type(mbedtls_md_type_t md_type) +{ + switch (md_type) { +#if defined(MBEDTLS_MD_CAN_MD5) + case MBEDTLS_MD_MD5: + return &mbedtls_md5_info; #endif - -#if defined(MBEDTLS_MD4_C) - MBEDTLS_MD_MD4, +#if defined(MBEDTLS_MD_CAN_RIPEMD160) + case MBEDTLS_MD_RIPEMD160: + return &mbedtls_ripemd160_info; #endif - -#if defined(MBEDTLS_MD2_C) - MBEDTLS_MD_MD2, +#if defined(MBEDTLS_MD_CAN_SHA1) + case MBEDTLS_MD_SHA1: + return &mbedtls_sha1_info; #endif - - MBEDTLS_MD_NONE -}; - -const int *mbedtls_md_list(void) -{ - return supported_digests; -} - -const mbedtls_md_info_t *mbedtls_md_info_from_string(const char *md_name) -{ - if (NULL == md_name) { - return NULL; - } - - /* Get the appropriate digest information */ -#if defined(MBEDTLS_MD2_C) - if (!strcmp("MD2", md_name)) { - return mbedtls_md_info_from_type(MBEDTLS_MD_MD2); - } +#if defined(MBEDTLS_MD_CAN_SHA224) + case MBEDTLS_MD_SHA224: + return &mbedtls_sha224_info; #endif -#if defined(MBEDTLS_MD4_C) - if (!strcmp("MD4", md_name)) { - return mbedtls_md_info_from_type(MBEDTLS_MD_MD4); - } +#if defined(MBEDTLS_MD_CAN_SHA256) + case MBEDTLS_MD_SHA256: + return &mbedtls_sha256_info; #endif -#if defined(MBEDTLS_MD5_C) - if (!strcmp("MD5", md_name)) { - return mbedtls_md_info_from_type(MBEDTLS_MD_MD5); - } +#if defined(MBEDTLS_MD_CAN_SHA384) + case MBEDTLS_MD_SHA384: + return &mbedtls_sha384_info; #endif -#if defined(MBEDTLS_RIPEMD160_C) - if (!strcmp("RIPEMD160", md_name)) { - return mbedtls_md_info_from_type(MBEDTLS_MD_RIPEMD160); - } +#if defined(MBEDTLS_MD_CAN_SHA512) + case MBEDTLS_MD_SHA512: + return &mbedtls_sha512_info; #endif -#if defined(MBEDTLS_SHA1_C) - if (!strcmp("SHA1", md_name) || !strcmp("SHA", md_name)) { - return mbedtls_md_info_from_type(MBEDTLS_MD_SHA1); - } +#if defined(MBEDTLS_MD_CAN_SHA3_224) + case MBEDTLS_MD_SHA3_224: + return &mbedtls_sha3_224_info; #endif -#if defined(MBEDTLS_SHA256_C) - if (!strcmp("SHA224", md_name)) { - return mbedtls_md_info_from_type(MBEDTLS_MD_SHA224); - } - if (!strcmp("SHA256", md_name)) { - return mbedtls_md_info_from_type(MBEDTLS_MD_SHA256); - } +#if defined(MBEDTLS_MD_CAN_SHA3_256) + case MBEDTLS_MD_SHA3_256: + return &mbedtls_sha3_256_info; #endif -#if defined(MBEDTLS_SHA512_C) -#if !defined(MBEDTLS_SHA512_NO_SHA384) - if (!strcmp("SHA384", md_name)) { - return mbedtls_md_info_from_type(MBEDTLS_MD_SHA384); - } +#if defined(MBEDTLS_MD_CAN_SHA3_384) + case MBEDTLS_MD_SHA3_384: + return &mbedtls_sha3_384_info; #endif - if (!strcmp("SHA512", md_name)) { - return mbedtls_md_info_from_type(MBEDTLS_MD_SHA512); - } +#if defined(MBEDTLS_MD_CAN_SHA3_512) + case MBEDTLS_MD_SHA3_512: + return &mbedtls_sha3_512_info; #endif - return NULL; + default: + return NULL; + } } -const mbedtls_md_info_t *mbedtls_md_info_from_type(mbedtls_md_type_t md_type) +#if defined(MBEDTLS_MD_SOME_PSA) +static psa_algorithm_t psa_alg_of_md(const mbedtls_md_info_t *info) { - switch (md_type) { -#if defined(MBEDTLS_MD2_C) - case MBEDTLS_MD_MD2: - return &mbedtls_md2_info; -#endif -#if defined(MBEDTLS_MD4_C) - case MBEDTLS_MD_MD4: - return &mbedtls_md4_info; -#endif -#if defined(MBEDTLS_MD5_C) + switch (info->type) { +#if defined(MBEDTLS_MD_MD5_VIA_PSA) case MBEDTLS_MD_MD5: - return &mbedtls_md5_info; + return PSA_ALG_MD5; #endif -#if defined(MBEDTLS_RIPEMD160_C) +#if defined(MBEDTLS_MD_RIPEMD160_VIA_PSA) case MBEDTLS_MD_RIPEMD160: - return &mbedtls_ripemd160_info; + return PSA_ALG_RIPEMD160; #endif -#if defined(MBEDTLS_SHA1_C) +#if defined(MBEDTLS_MD_SHA1_VIA_PSA) case MBEDTLS_MD_SHA1: - return &mbedtls_sha1_info; + return PSA_ALG_SHA_1; #endif -#if defined(MBEDTLS_SHA256_C) +#if defined(MBEDTLS_MD_SHA224_VIA_PSA) case MBEDTLS_MD_SHA224: - return &mbedtls_sha224_info; + return PSA_ALG_SHA_224; +#endif +#if defined(MBEDTLS_MD_SHA256_VIA_PSA) case MBEDTLS_MD_SHA256: - return &mbedtls_sha256_info; + return PSA_ALG_SHA_256; #endif -#if defined(MBEDTLS_SHA512_C) -#if !defined(MBEDTLS_SHA512_NO_SHA384) +#if defined(MBEDTLS_MD_SHA384_VIA_PSA) case MBEDTLS_MD_SHA384: - return &mbedtls_sha384_info; + return PSA_ALG_SHA_384; #endif +#if defined(MBEDTLS_MD_SHA512_VIA_PSA) case MBEDTLS_MD_SHA512: - return &mbedtls_sha512_info; + return PSA_ALG_SHA_512; +#endif +#if defined(MBEDTLS_MD_SHA3_224_VIA_PSA) + case MBEDTLS_MD_SHA3_224: + return PSA_ALG_SHA3_224; +#endif +#if defined(MBEDTLS_MD_SHA3_256_VIA_PSA) + case MBEDTLS_MD_SHA3_256: + return PSA_ALG_SHA3_256; +#endif +#if defined(MBEDTLS_MD_SHA3_384_VIA_PSA) + case MBEDTLS_MD_SHA3_384: + return PSA_ALG_SHA3_384; +#endif +#if defined(MBEDTLS_MD_SHA3_512_VIA_PSA) + case MBEDTLS_MD_SHA3_512: + return PSA_ALG_SHA3_512; #endif default: - return NULL; + return PSA_ALG_NONE; } } +static int md_can_use_psa(const mbedtls_md_info_t *info) +{ + psa_algorithm_t alg = psa_alg_of_md(info); + if (alg == PSA_ALG_NONE) { + return 0; + } + + return psa_can_do_hash(alg); +} +#endif /* MBEDTLS_MD_SOME_PSA */ + void mbedtls_md_init(mbedtls_md_context_t *ctx) { + /* Note: this sets engine (if present) to MBEDTLS_MD_ENGINE_LEGACY */ memset(ctx, 0, sizeof(mbedtls_md_context_t)); } @@ -277,17 +265,12 @@ void mbedtls_md_free(mbedtls_md_context_t *ctx) } if (ctx->md_ctx != NULL) { - switch (ctx->md_info->type) { -#if defined(MBEDTLS_MD2_C) - case MBEDTLS_MD_MD2: - mbedtls_md2_free(ctx->md_ctx); - break; -#endif -#if defined(MBEDTLS_MD4_C) - case MBEDTLS_MD_MD4: - mbedtls_md4_free(ctx->md_ctx); - break; +#if defined(MBEDTLS_MD_SOME_PSA) + if (ctx->engine == MBEDTLS_MD_ENGINE_PSA) { + psa_hash_abort(ctx->md_ctx); + } else #endif + switch (ctx->md_info->type) { #if defined(MBEDTLS_MD5_C) case MBEDTLS_MD_MD5: mbedtls_md5_free(ctx->md_ctx); @@ -303,19 +286,33 @@ void mbedtls_md_free(mbedtls_md_context_t *ctx) mbedtls_sha1_free(ctx->md_ctx); break; #endif -#if defined(MBEDTLS_SHA256_C) +#if defined(MBEDTLS_SHA224_C) case MBEDTLS_MD_SHA224: + mbedtls_sha256_free(ctx->md_ctx); + break; +#endif +#if defined(MBEDTLS_SHA256_C) case MBEDTLS_MD_SHA256: mbedtls_sha256_free(ctx->md_ctx); break; #endif -#if defined(MBEDTLS_SHA512_C) -#if !defined(MBEDTLS_SHA512_NO_SHA384) +#if defined(MBEDTLS_SHA384_C) case MBEDTLS_MD_SHA384: + mbedtls_sha512_free(ctx->md_ctx); + break; #endif +#if defined(MBEDTLS_SHA512_C) case MBEDTLS_MD_SHA512: mbedtls_sha512_free(ctx->md_ctx); break; +#endif +#if defined(MBEDTLS_SHA3_C) + case MBEDTLS_MD_SHA3_224: + case MBEDTLS_MD_SHA3_256: + case MBEDTLS_MD_SHA3_384: + case MBEDTLS_MD_SHA3_512: + mbedtls_sha3_free(ctx->md_ctx); + break; #endif default: /* Shouldn't happen */ @@ -324,11 +321,12 @@ void mbedtls_md_free(mbedtls_md_context_t *ctx) mbedtls_free(ctx->md_ctx); } +#if defined(MBEDTLS_MD_C) if (ctx->hmac_ctx != NULL) { - mbedtls_platform_zeroize(ctx->hmac_ctx, + mbedtls_zeroize_and_free(ctx->hmac_ctx, 2 * ctx->md_info->block_size); - mbedtls_free(ctx->hmac_ctx); } +#endif mbedtls_platform_zeroize(ctx, sizeof(mbedtls_md_context_t)); } @@ -342,17 +340,22 @@ int mbedtls_md_clone(mbedtls_md_context_t *dst, return MBEDTLS_ERR_MD_BAD_INPUT_DATA; } - switch (src->md_info->type) { -#if defined(MBEDTLS_MD2_C) - case MBEDTLS_MD_MD2: - mbedtls_md2_clone(dst->md_ctx, src->md_ctx); - break; -#endif -#if defined(MBEDTLS_MD4_C) - case MBEDTLS_MD_MD4: - mbedtls_md4_clone(dst->md_ctx, src->md_ctx); - break; +#if defined(MBEDTLS_MD_SOME_PSA) + if (src->engine != dst->engine) { + /* This can happen with src set to legacy because PSA wasn't ready + * yet, and dst to PSA because it became ready in the meantime. + * We currently don't support that case (we'd need to re-allocate + * md_ctx to the size of the appropriate MD context). */ + return MBEDTLS_ERR_MD_FEATURE_UNAVAILABLE; + } + + if (src->engine == MBEDTLS_MD_ENGINE_PSA) { + psa_status_t status = psa_hash_clone(src->md_ctx, dst->md_ctx); + return mbedtls_md_error_from_psa(status); + } #endif + + switch (src->md_info->type) { #if defined(MBEDTLS_MD5_C) case MBEDTLS_MD_MD5: mbedtls_md5_clone(dst->md_ctx, src->md_ctx); @@ -368,19 +371,33 @@ int mbedtls_md_clone(mbedtls_md_context_t *dst, mbedtls_sha1_clone(dst->md_ctx, src->md_ctx); break; #endif -#if defined(MBEDTLS_SHA256_C) +#if defined(MBEDTLS_SHA224_C) case MBEDTLS_MD_SHA224: + mbedtls_sha256_clone(dst->md_ctx, src->md_ctx); + break; +#endif +#if defined(MBEDTLS_SHA256_C) case MBEDTLS_MD_SHA256: mbedtls_sha256_clone(dst->md_ctx, src->md_ctx); break; #endif -#if defined(MBEDTLS_SHA512_C) -#if !defined(MBEDTLS_SHA512_NO_SHA384) +#if defined(MBEDTLS_SHA384_C) case MBEDTLS_MD_SHA384: + mbedtls_sha512_clone(dst->md_ctx, src->md_ctx); + break; #endif +#if defined(MBEDTLS_SHA512_C) case MBEDTLS_MD_SHA512: mbedtls_sha512_clone(dst->md_ctx, src->md_ctx); break; +#endif +#if defined(MBEDTLS_SHA3_C) + case MBEDTLS_MD_SHA3_224: + case MBEDTLS_MD_SHA3_256: + case MBEDTLS_MD_SHA3_384: + case MBEDTLS_MD_SHA3_512: + mbedtls_sha3_clone(dst->md_ctx, src->md_ctx); + break; #endif default: return MBEDTLS_ERR_MD_BAD_INPUT_DATA; @@ -389,13 +406,6 @@ int mbedtls_md_clone(mbedtls_md_context_t *dst, return 0; } -#if !defined(MBEDTLS_DEPRECATED_REMOVED) -int mbedtls_md_init_ctx(mbedtls_md_context_t *ctx, const mbedtls_md_info_t *md_info) -{ - return mbedtls_md_setup(ctx, md_info, 1); -} -#endif - #define ALLOC(type) \ do { \ ctx->md_ctx = mbedtls_calloc(1, sizeof(mbedtls_##type##_context)); \ @@ -407,25 +417,35 @@ int mbedtls_md_init_ctx(mbedtls_md_context_t *ctx, const mbedtls_md_info_t *md_i int mbedtls_md_setup(mbedtls_md_context_t *ctx, const mbedtls_md_info_t *md_info, int hmac) { - if (md_info == NULL || ctx == NULL) { +#if defined(MBEDTLS_MD_C) + if (ctx == NULL) { + return MBEDTLS_ERR_MD_BAD_INPUT_DATA; + } +#endif + if (md_info == NULL) { return MBEDTLS_ERR_MD_BAD_INPUT_DATA; } ctx->md_info = md_info; ctx->md_ctx = NULL; +#if defined(MBEDTLS_MD_C) ctx->hmac_ctx = NULL; - - switch (md_info->type) { -#if defined(MBEDTLS_MD2_C) - case MBEDTLS_MD_MD2: - ALLOC(md2); - break; +#else + if (hmac != 0) { + return MBEDTLS_ERR_MD_BAD_INPUT_DATA; + } #endif -#if defined(MBEDTLS_MD4_C) - case MBEDTLS_MD_MD4: - ALLOC(md4); - break; + +#if defined(MBEDTLS_MD_SOME_PSA) + if (md_can_use_psa(ctx->md_info)) { + ctx->md_ctx = mbedtls_calloc(1, sizeof(psa_hash_operation_t)); + if (ctx->md_ctx == NULL) { + return MBEDTLS_ERR_MD_ALLOC_FAILED; + } + ctx->engine = MBEDTLS_MD_ENGINE_PSA; + } else #endif + switch (md_info->type) { #if defined(MBEDTLS_MD5_C) case MBEDTLS_MD_MD5: ALLOC(md5); @@ -441,24 +461,39 @@ int mbedtls_md_setup(mbedtls_md_context_t *ctx, const mbedtls_md_info_t *md_info ALLOC(sha1); break; #endif -#if defined(MBEDTLS_SHA256_C) +#if defined(MBEDTLS_SHA224_C) case MBEDTLS_MD_SHA224: + ALLOC(sha256); + break; +#endif +#if defined(MBEDTLS_SHA256_C) case MBEDTLS_MD_SHA256: ALLOC(sha256); break; #endif -#if defined(MBEDTLS_SHA512_C) -#if !defined(MBEDTLS_SHA512_NO_SHA384) +#if defined(MBEDTLS_SHA384_C) case MBEDTLS_MD_SHA384: + ALLOC(sha512); + break; #endif +#if defined(MBEDTLS_SHA512_C) case MBEDTLS_MD_SHA512: ALLOC(sha512); break; +#endif +#if defined(MBEDTLS_SHA3_C) + case MBEDTLS_MD_SHA3_224: + case MBEDTLS_MD_SHA3_256: + case MBEDTLS_MD_SHA3_384: + case MBEDTLS_MD_SHA3_512: + ALLOC(sha3); + break; #endif default: return MBEDTLS_ERR_MD_BAD_INPUT_DATA; } +#if defined(MBEDTLS_MD_C) if (hmac != 0) { ctx->hmac_ctx = mbedtls_calloc(2, md_info->block_size); if (ctx->hmac_ctx == NULL) { @@ -466,6 +501,7 @@ int mbedtls_md_setup(mbedtls_md_context_t *ctx, const mbedtls_md_info_t *md_info return MBEDTLS_ERR_MD_ALLOC_FAILED; } } +#endif return 0; } @@ -473,44 +509,59 @@ int mbedtls_md_setup(mbedtls_md_context_t *ctx, const mbedtls_md_info_t *md_info int mbedtls_md_starts(mbedtls_md_context_t *ctx) { +#if defined(MBEDTLS_MD_C) if (ctx == NULL || ctx->md_info == NULL) { return MBEDTLS_ERR_MD_BAD_INPUT_DATA; } - - switch (ctx->md_info->type) { -#if defined(MBEDTLS_MD2_C) - case MBEDTLS_MD_MD2: - return mbedtls_md2_starts_ret(ctx->md_ctx); #endif -#if defined(MBEDTLS_MD4_C) - case MBEDTLS_MD_MD4: - return mbedtls_md4_starts_ret(ctx->md_ctx); + +#if defined(MBEDTLS_MD_SOME_PSA) + if (ctx->engine == MBEDTLS_MD_ENGINE_PSA) { + psa_algorithm_t alg = psa_alg_of_md(ctx->md_info); + psa_hash_abort(ctx->md_ctx); + psa_status_t status = psa_hash_setup(ctx->md_ctx, alg); + return mbedtls_md_error_from_psa(status); + } #endif + + switch (ctx->md_info->type) { #if defined(MBEDTLS_MD5_C) case MBEDTLS_MD_MD5: - return mbedtls_md5_starts_ret(ctx->md_ctx); + return mbedtls_md5_starts(ctx->md_ctx); #endif #if defined(MBEDTLS_RIPEMD160_C) case MBEDTLS_MD_RIPEMD160: - return mbedtls_ripemd160_starts_ret(ctx->md_ctx); + return mbedtls_ripemd160_starts(ctx->md_ctx); #endif #if defined(MBEDTLS_SHA1_C) case MBEDTLS_MD_SHA1: - return mbedtls_sha1_starts_ret(ctx->md_ctx); + return mbedtls_sha1_starts(ctx->md_ctx); #endif -#if defined(MBEDTLS_SHA256_C) +#if defined(MBEDTLS_SHA224_C) case MBEDTLS_MD_SHA224: - return mbedtls_sha256_starts_ret(ctx->md_ctx, 1); + return mbedtls_sha256_starts(ctx->md_ctx, 1); +#endif +#if defined(MBEDTLS_SHA256_C) case MBEDTLS_MD_SHA256: - return mbedtls_sha256_starts_ret(ctx->md_ctx, 0); + return mbedtls_sha256_starts(ctx->md_ctx, 0); #endif -#if defined(MBEDTLS_SHA512_C) -#if !defined(MBEDTLS_SHA512_NO_SHA384) +#if defined(MBEDTLS_SHA384_C) case MBEDTLS_MD_SHA384: - return mbedtls_sha512_starts_ret(ctx->md_ctx, 1); + return mbedtls_sha512_starts(ctx->md_ctx, 1); #endif +#if defined(MBEDTLS_SHA512_C) case MBEDTLS_MD_SHA512: - return mbedtls_sha512_starts_ret(ctx->md_ctx, 0); + return mbedtls_sha512_starts(ctx->md_ctx, 0); +#endif +#if defined(MBEDTLS_SHA3_C) + case MBEDTLS_MD_SHA3_224: + return mbedtls_sha3_starts(ctx->md_ctx, MBEDTLS_SHA3_224); + case MBEDTLS_MD_SHA3_256: + return mbedtls_sha3_starts(ctx->md_ctx, MBEDTLS_SHA3_256); + case MBEDTLS_MD_SHA3_384: + return mbedtls_sha3_starts(ctx->md_ctx, MBEDTLS_SHA3_384); + case MBEDTLS_MD_SHA3_512: + return mbedtls_sha3_starts(ctx->md_ctx, MBEDTLS_SHA3_512); #endif default: return MBEDTLS_ERR_MD_BAD_INPUT_DATA; @@ -519,42 +570,54 @@ int mbedtls_md_starts(mbedtls_md_context_t *ctx) int mbedtls_md_update(mbedtls_md_context_t *ctx, const unsigned char *input, size_t ilen) { +#if defined(MBEDTLS_MD_C) if (ctx == NULL || ctx->md_info == NULL) { return MBEDTLS_ERR_MD_BAD_INPUT_DATA; } - - switch (ctx->md_info->type) { -#if defined(MBEDTLS_MD2_C) - case MBEDTLS_MD_MD2: - return mbedtls_md2_update_ret(ctx->md_ctx, input, ilen); #endif -#if defined(MBEDTLS_MD4_C) - case MBEDTLS_MD_MD4: - return mbedtls_md4_update_ret(ctx->md_ctx, input, ilen); + +#if defined(MBEDTLS_MD_SOME_PSA) + if (ctx->engine == MBEDTLS_MD_ENGINE_PSA) { + psa_status_t status = psa_hash_update(ctx->md_ctx, input, ilen); + return mbedtls_md_error_from_psa(status); + } #endif + + switch (ctx->md_info->type) { #if defined(MBEDTLS_MD5_C) case MBEDTLS_MD_MD5: - return mbedtls_md5_update_ret(ctx->md_ctx, input, ilen); + return mbedtls_md5_update(ctx->md_ctx, input, ilen); #endif #if defined(MBEDTLS_RIPEMD160_C) case MBEDTLS_MD_RIPEMD160: - return mbedtls_ripemd160_update_ret(ctx->md_ctx, input, ilen); + return mbedtls_ripemd160_update(ctx->md_ctx, input, ilen); #endif #if defined(MBEDTLS_SHA1_C) case MBEDTLS_MD_SHA1: - return mbedtls_sha1_update_ret(ctx->md_ctx, input, ilen); + return mbedtls_sha1_update(ctx->md_ctx, input, ilen); #endif -#if defined(MBEDTLS_SHA256_C) +#if defined(MBEDTLS_SHA224_C) case MBEDTLS_MD_SHA224: + return mbedtls_sha256_update(ctx->md_ctx, input, ilen); +#endif +#if defined(MBEDTLS_SHA256_C) case MBEDTLS_MD_SHA256: - return mbedtls_sha256_update_ret(ctx->md_ctx, input, ilen); + return mbedtls_sha256_update(ctx->md_ctx, input, ilen); #endif -#if defined(MBEDTLS_SHA512_C) -#if !defined(MBEDTLS_SHA512_NO_SHA384) +#if defined(MBEDTLS_SHA384_C) case MBEDTLS_MD_SHA384: + return mbedtls_sha512_update(ctx->md_ctx, input, ilen); #endif +#if defined(MBEDTLS_SHA512_C) case MBEDTLS_MD_SHA512: - return mbedtls_sha512_update_ret(ctx->md_ctx, input, ilen); + return mbedtls_sha512_update(ctx->md_ctx, input, ilen); +#endif +#if defined(MBEDTLS_SHA3_C) + case MBEDTLS_MD_SHA3_224: + case MBEDTLS_MD_SHA3_256: + case MBEDTLS_MD_SHA3_384: + case MBEDTLS_MD_SHA3_512: + return mbedtls_sha3_update(ctx->md_ctx, input, ilen); #endif default: return MBEDTLS_ERR_MD_BAD_INPUT_DATA; @@ -563,42 +626,56 @@ int mbedtls_md_update(mbedtls_md_context_t *ctx, const unsigned char *input, siz int mbedtls_md_finish(mbedtls_md_context_t *ctx, unsigned char *output) { +#if defined(MBEDTLS_MD_C) if (ctx == NULL || ctx->md_info == NULL) { return MBEDTLS_ERR_MD_BAD_INPUT_DATA; } - - switch (ctx->md_info->type) { -#if defined(MBEDTLS_MD2_C) - case MBEDTLS_MD_MD2: - return mbedtls_md2_finish_ret(ctx->md_ctx, output); #endif -#if defined(MBEDTLS_MD4_C) - case MBEDTLS_MD_MD4: - return mbedtls_md4_finish_ret(ctx->md_ctx, output); + +#if defined(MBEDTLS_MD_SOME_PSA) + if (ctx->engine == MBEDTLS_MD_ENGINE_PSA) { + size_t size = ctx->md_info->size; + psa_status_t status = psa_hash_finish(ctx->md_ctx, + output, size, &size); + return mbedtls_md_error_from_psa(status); + } #endif + + switch (ctx->md_info->type) { #if defined(MBEDTLS_MD5_C) case MBEDTLS_MD_MD5: - return mbedtls_md5_finish_ret(ctx->md_ctx, output); + return mbedtls_md5_finish(ctx->md_ctx, output); #endif #if defined(MBEDTLS_RIPEMD160_C) case MBEDTLS_MD_RIPEMD160: - return mbedtls_ripemd160_finish_ret(ctx->md_ctx, output); + return mbedtls_ripemd160_finish(ctx->md_ctx, output); #endif #if defined(MBEDTLS_SHA1_C) case MBEDTLS_MD_SHA1: - return mbedtls_sha1_finish_ret(ctx->md_ctx, output); + return mbedtls_sha1_finish(ctx->md_ctx, output); #endif -#if defined(MBEDTLS_SHA256_C) +#if defined(MBEDTLS_SHA224_C) case MBEDTLS_MD_SHA224: + return mbedtls_sha256_finish(ctx->md_ctx, output); +#endif +#if defined(MBEDTLS_SHA256_C) case MBEDTLS_MD_SHA256: - return mbedtls_sha256_finish_ret(ctx->md_ctx, output); + return mbedtls_sha256_finish(ctx->md_ctx, output); #endif -#if defined(MBEDTLS_SHA512_C) -#if !defined(MBEDTLS_SHA512_NO_SHA384) +#if defined(MBEDTLS_SHA384_C) case MBEDTLS_MD_SHA384: + return mbedtls_sha512_finish(ctx->md_ctx, output); #endif +#if defined(MBEDTLS_SHA512_C) case MBEDTLS_MD_SHA512: - return mbedtls_sha512_finish_ret(ctx->md_ctx, output); + return mbedtls_sha512_finish(ctx->md_ctx, output); +#endif +#if defined(MBEDTLS_SHA3_C) + case MBEDTLS_MD_SHA3_224: + case MBEDTLS_MD_SHA3_256: + case MBEDTLS_MD_SHA3_384: + case MBEDTLS_MD_SHA3_512: + return mbedtls_sha3_finish(ctx->md_ctx, output, ctx->md_info->size); #endif default: return MBEDTLS_ERR_MD_BAD_INPUT_DATA; @@ -612,46 +689,232 @@ int mbedtls_md(const mbedtls_md_info_t *md_info, const unsigned char *input, siz return MBEDTLS_ERR_MD_BAD_INPUT_DATA; } - switch (md_info->type) { -#if defined(MBEDTLS_MD2_C) - case MBEDTLS_MD_MD2: - return mbedtls_md2_ret(input, ilen, output); -#endif -#if defined(MBEDTLS_MD4_C) - case MBEDTLS_MD_MD4: - return mbedtls_md4_ret(input, ilen, output); +#if defined(MBEDTLS_MD_SOME_PSA) + if (md_can_use_psa(md_info)) { + size_t size = md_info->size; + psa_status_t status = psa_hash_compute(psa_alg_of_md(md_info), + input, ilen, + output, size, &size); + return mbedtls_md_error_from_psa(status); + } #endif + + switch (md_info->type) { #if defined(MBEDTLS_MD5_C) case MBEDTLS_MD_MD5: - return mbedtls_md5_ret(input, ilen, output); + return mbedtls_md5(input, ilen, output); #endif #if defined(MBEDTLS_RIPEMD160_C) case MBEDTLS_MD_RIPEMD160: - return mbedtls_ripemd160_ret(input, ilen, output); + return mbedtls_ripemd160(input, ilen, output); #endif #if defined(MBEDTLS_SHA1_C) case MBEDTLS_MD_SHA1: - return mbedtls_sha1_ret(input, ilen, output); + return mbedtls_sha1(input, ilen, output); #endif -#if defined(MBEDTLS_SHA256_C) +#if defined(MBEDTLS_SHA224_C) case MBEDTLS_MD_SHA224: - return mbedtls_sha256_ret(input, ilen, output, 1); + return mbedtls_sha256(input, ilen, output, 1); +#endif +#if defined(MBEDTLS_SHA256_C) case MBEDTLS_MD_SHA256: - return mbedtls_sha256_ret(input, ilen, output, 0); + return mbedtls_sha256(input, ilen, output, 0); #endif -#if defined(MBEDTLS_SHA512_C) -#if !defined(MBEDTLS_SHA512_NO_SHA384) +#if defined(MBEDTLS_SHA384_C) case MBEDTLS_MD_SHA384: - return mbedtls_sha512_ret(input, ilen, output, 1); + return mbedtls_sha512(input, ilen, output, 1); #endif +#if defined(MBEDTLS_SHA512_C) case MBEDTLS_MD_SHA512: - return mbedtls_sha512_ret(input, ilen, output, 0); + return mbedtls_sha512(input, ilen, output, 0); +#endif +#if defined(MBEDTLS_SHA3_C) + case MBEDTLS_MD_SHA3_224: + return mbedtls_sha3(MBEDTLS_SHA3_224, input, ilen, output, md_info->size); + case MBEDTLS_MD_SHA3_256: + return mbedtls_sha3(MBEDTLS_SHA3_256, input, ilen, output, md_info->size); + case MBEDTLS_MD_SHA3_384: + return mbedtls_sha3(MBEDTLS_SHA3_384, input, ilen, output, md_info->size); + case MBEDTLS_MD_SHA3_512: + return mbedtls_sha3(MBEDTLS_SHA3_512, input, ilen, output, md_info->size); #endif default: return MBEDTLS_ERR_MD_BAD_INPUT_DATA; } } +unsigned char mbedtls_md_get_size(const mbedtls_md_info_t *md_info) +{ + if (md_info == NULL) { + return 0; + } + + return md_info->size; +} + +mbedtls_md_type_t mbedtls_md_get_type(const mbedtls_md_info_t *md_info) +{ + if (md_info == NULL) { + return MBEDTLS_MD_NONE; + } + + return md_info->type; +} + +#if defined(MBEDTLS_PSA_CRYPTO_C) +int mbedtls_md_error_from_psa(psa_status_t status) +{ + return PSA_TO_MBEDTLS_ERR_LIST(status, psa_to_md_errors, + psa_generic_status_to_mbedtls); +} +#endif /* MBEDTLS_PSA_CRYPTO_C */ + + +/************************************************************************ + * Functions above this separator are part of MBEDTLS_MD_LIGHT, * + * functions below are only available when MBEDTLS_MD_C is set. * + ************************************************************************/ +#if defined(MBEDTLS_MD_C) + +/* + * Reminder: update profiles in x509_crt.c when adding a new hash! + */ +static const int supported_digests[] = { + +#if defined(MBEDTLS_MD_CAN_SHA512) + MBEDTLS_MD_SHA512, +#endif + +#if defined(MBEDTLS_MD_CAN_SHA384) + MBEDTLS_MD_SHA384, +#endif + +#if defined(MBEDTLS_MD_CAN_SHA256) + MBEDTLS_MD_SHA256, +#endif +#if defined(MBEDTLS_MD_CAN_SHA224) + MBEDTLS_MD_SHA224, +#endif + +#if defined(MBEDTLS_MD_CAN_SHA1) + MBEDTLS_MD_SHA1, +#endif + +#if defined(MBEDTLS_MD_CAN_RIPEMD160) + MBEDTLS_MD_RIPEMD160, +#endif + +#if defined(MBEDTLS_MD_CAN_MD5) + MBEDTLS_MD_MD5, +#endif + +#if defined(MBEDTLS_MD_CAN_SHA3_224) + MBEDTLS_MD_SHA3_224, +#endif + +#if defined(MBEDTLS_MD_CAN_SHA3_256) + MBEDTLS_MD_SHA3_256, +#endif + +#if defined(MBEDTLS_MD_CAN_SHA3_384) + MBEDTLS_MD_SHA3_384, +#endif + +#if defined(MBEDTLS_MD_CAN_SHA3_512) + MBEDTLS_MD_SHA3_512, +#endif + + MBEDTLS_MD_NONE +}; + +const int *mbedtls_md_list(void) +{ + return supported_digests; +} + +typedef struct { + const char *md_name; + mbedtls_md_type_t md_type; +} md_name_entry; + +static const md_name_entry md_names[] = { +#if defined(MBEDTLS_MD_CAN_MD5) + { "MD5", MBEDTLS_MD_MD5 }, +#endif +#if defined(MBEDTLS_MD_CAN_RIPEMD160) + { "RIPEMD160", MBEDTLS_MD_RIPEMD160 }, +#endif +#if defined(MBEDTLS_MD_CAN_SHA1) + { "SHA1", MBEDTLS_MD_SHA1 }, + { "SHA", MBEDTLS_MD_SHA1 }, // compatibility fallback +#endif +#if defined(MBEDTLS_MD_CAN_SHA224) + { "SHA224", MBEDTLS_MD_SHA224 }, +#endif +#if defined(MBEDTLS_MD_CAN_SHA256) + { "SHA256", MBEDTLS_MD_SHA256 }, +#endif +#if defined(MBEDTLS_MD_CAN_SHA384) + { "SHA384", MBEDTLS_MD_SHA384 }, +#endif +#if defined(MBEDTLS_MD_CAN_SHA512) + { "SHA512", MBEDTLS_MD_SHA512 }, +#endif +#if defined(MBEDTLS_MD_CAN_SHA3_224) + { "SHA3-224", MBEDTLS_MD_SHA3_224 }, +#endif +#if defined(MBEDTLS_MD_CAN_SHA3_256) + { "SHA3-256", MBEDTLS_MD_SHA3_256 }, +#endif +#if defined(MBEDTLS_MD_CAN_SHA3_384) + { "SHA3-384", MBEDTLS_MD_SHA3_384 }, +#endif +#if defined(MBEDTLS_MD_CAN_SHA3_512) + { "SHA3-512", MBEDTLS_MD_SHA3_512 }, +#endif + { NULL, MBEDTLS_MD_NONE }, +}; + +const mbedtls_md_info_t *mbedtls_md_info_from_string(const char *md_name) +{ + if (NULL == md_name) { + return NULL; + } + + const md_name_entry *entry = md_names; + while (entry->md_name != NULL && + strcmp(entry->md_name, md_name) != 0) { + ++entry; + } + + return mbedtls_md_info_from_type(entry->md_type); +} + +const char *mbedtls_md_get_name(const mbedtls_md_info_t *md_info) +{ + if (md_info == NULL) { + return NULL; + } + + const md_name_entry *entry = md_names; + while (entry->md_type != MBEDTLS_MD_NONE && + entry->md_type != md_info->type) { + ++entry; + } + + return entry->md_name; +} + +const mbedtls_md_info_t *mbedtls_md_info_from_ctx( + const mbedtls_md_context_t *ctx) +{ + if (ctx == NULL) { + return NULL; + } + + return ctx->MBEDTLS_PRIVATE(md_info); +} + #if defined(MBEDTLS_FS_IO) int mbedtls_md_file(const mbedtls_md_info_t *md_info, const char *path, unsigned char *output) { @@ -669,6 +932,9 @@ int mbedtls_md_file(const mbedtls_md_info_t *md_info, const char *path, unsigned return MBEDTLS_ERR_MD_FILE_IO_ERROR; } + /* Ensure no stdio buffering of secrets, as such buffers cannot be wiped. */ + mbedtls_setbuf(f, NULL); + mbedtls_md_init(&ctx); if ((ret = mbedtls_md_setup(&ctx, md_info, 0)) != 0) { @@ -705,7 +971,6 @@ int mbedtls_md_hmac_starts(mbedtls_md_context_t *ctx, const unsigned char *key, int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED; unsigned char sum[MBEDTLS_MD_MAX_SIZE]; unsigned char *ipad, *opad; - size_t i; if (ctx == NULL || ctx->md_info == NULL || ctx->hmac_ctx == NULL) { return MBEDTLS_ERR_MD_BAD_INPUT_DATA; @@ -732,10 +997,8 @@ int mbedtls_md_hmac_starts(mbedtls_md_context_t *ctx, const unsigned char *key, memset(ipad, 0x36, ctx->md_info->block_size); memset(opad, 0x5C, ctx->md_info->block_size); - for (i = 0; i < keylen; i++) { - ipad[i] = (unsigned char) (ipad[i] ^ key[i]); - opad[i] = (unsigned char) (opad[i] ^ key[i]); - } + mbedtls_xor(ipad, ipad, key, keylen); + mbedtls_xor(opad, opad, key, keylen); if ((ret = mbedtls_md_starts(ctx)) != 0) { goto cleanup; @@ -840,75 +1103,6 @@ int mbedtls_md_hmac(const mbedtls_md_info_t *md_info, return ret; } -int mbedtls_md_process(mbedtls_md_context_t *ctx, const unsigned char *data) -{ - if (ctx == NULL || ctx->md_info == NULL) { - return MBEDTLS_ERR_MD_BAD_INPUT_DATA; - } - - switch (ctx->md_info->type) { -#if defined(MBEDTLS_MD2_C) - case MBEDTLS_MD_MD2: - return mbedtls_internal_md2_process(ctx->md_ctx); -#endif -#if defined(MBEDTLS_MD4_C) - case MBEDTLS_MD_MD4: - return mbedtls_internal_md4_process(ctx->md_ctx, data); -#endif -#if defined(MBEDTLS_MD5_C) - case MBEDTLS_MD_MD5: - return mbedtls_internal_md5_process(ctx->md_ctx, data); -#endif -#if defined(MBEDTLS_RIPEMD160_C) - case MBEDTLS_MD_RIPEMD160: - return mbedtls_internal_ripemd160_process(ctx->md_ctx, data); -#endif -#if defined(MBEDTLS_SHA1_C) - case MBEDTLS_MD_SHA1: - return mbedtls_internal_sha1_process(ctx->md_ctx, data); -#endif -#if defined(MBEDTLS_SHA256_C) - case MBEDTLS_MD_SHA224: - case MBEDTLS_MD_SHA256: - return mbedtls_internal_sha256_process(ctx->md_ctx, data); -#endif -#if defined(MBEDTLS_SHA512_C) -#if !defined(MBEDTLS_SHA512_NO_SHA384) - case MBEDTLS_MD_SHA384: -#endif - case MBEDTLS_MD_SHA512: - return mbedtls_internal_sha512_process(ctx->md_ctx, data); -#endif - default: - return MBEDTLS_ERR_MD_BAD_INPUT_DATA; - } -} - -unsigned char mbedtls_md_get_size(const mbedtls_md_info_t *md_info) -{ - if (md_info == NULL) { - return 0; - } - - return md_info->size; -} - -mbedtls_md_type_t mbedtls_md_get_type(const mbedtls_md_info_t *md_info) -{ - if (md_info == NULL) { - return MBEDTLS_MD_NONE; - } - - return md_info->type; -} - -const char *mbedtls_md_get_name(const mbedtls_md_info_t *md_info) -{ - if (md_info == NULL) { - return NULL; - } - - return md_info->name; -} - #endif /* MBEDTLS_MD_C */ + +#endif /* MBEDTLS_MD_LIGHT */ diff --git a/vendor/mbedtls/library/md2.c b/vendor/mbedtls/library/md2.c deleted file mode 100644 index f009498c48..0000000000 --- a/vendor/mbedtls/library/md2.c +++ /dev/null @@ -1,359 +0,0 @@ -/* - * RFC 1115/1319 compliant MD2 implementation - * - * Copyright The Mbed TLS Contributors - * SPDX-License-Identifier: Apache-2.0 - * - * Licensed under the Apache License, Version 2.0 (the "License"); you may - * not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT - * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ -/* - * The MD2 algorithm was designed by Ron Rivest in 1989. - * - * http://www.ietf.org/rfc/rfc1115.txt - * http://www.ietf.org/rfc/rfc1319.txt - */ - -#include "common.h" - -#if defined(MBEDTLS_MD2_C) - -#include "mbedtls/md2.h" -#include "mbedtls/platform_util.h" -#include "mbedtls/error.h" - -#include - -#include "mbedtls/platform.h" - -#if !defined(MBEDTLS_MD2_ALT) - -static const unsigned char PI_SUBST[256] = -{ - 0x29, 0x2E, 0x43, 0xC9, 0xA2, 0xD8, 0x7C, 0x01, 0x3D, 0x36, - 0x54, 0xA1, 0xEC, 0xF0, 0x06, 0x13, 0x62, 0xA7, 0x05, 0xF3, - 0xC0, 0xC7, 0x73, 0x8C, 0x98, 0x93, 0x2B, 0xD9, 0xBC, 0x4C, - 0x82, 0xCA, 0x1E, 0x9B, 0x57, 0x3C, 0xFD, 0xD4, 0xE0, 0x16, - 0x67, 0x42, 0x6F, 0x18, 0x8A, 0x17, 0xE5, 0x12, 0xBE, 0x4E, - 0xC4, 0xD6, 0xDA, 0x9E, 0xDE, 0x49, 0xA0, 0xFB, 0xF5, 0x8E, - 0xBB, 0x2F, 0xEE, 0x7A, 0xA9, 0x68, 0x79, 0x91, 0x15, 0xB2, - 0x07, 0x3F, 0x94, 0xC2, 0x10, 0x89, 0x0B, 0x22, 0x5F, 0x21, - 0x80, 0x7F, 0x5D, 0x9A, 0x5A, 0x90, 0x32, 0x27, 0x35, 0x3E, - 0xCC, 0xE7, 0xBF, 0xF7, 0x97, 0x03, 0xFF, 0x19, 0x30, 0xB3, - 0x48, 0xA5, 0xB5, 0xD1, 0xD7, 0x5E, 0x92, 0x2A, 0xAC, 0x56, - 0xAA, 0xC6, 0x4F, 0xB8, 0x38, 0xD2, 0x96, 0xA4, 0x7D, 0xB6, - 0x76, 0xFC, 0x6B, 0xE2, 0x9C, 0x74, 0x04, 0xF1, 0x45, 0x9D, - 0x70, 0x59, 0x64, 0x71, 0x87, 0x20, 0x86, 0x5B, 0xCF, 0x65, - 0xE6, 0x2D, 0xA8, 0x02, 0x1B, 0x60, 0x25, 0xAD, 0xAE, 0xB0, - 0xB9, 0xF6, 0x1C, 0x46, 0x61, 0x69, 0x34, 0x40, 0x7E, 0x0F, - 0x55, 0x47, 0xA3, 0x23, 0xDD, 0x51, 0xAF, 0x3A, 0xC3, 0x5C, - 0xF9, 0xCE, 0xBA, 0xC5, 0xEA, 0x26, 0x2C, 0x53, 0x0D, 0x6E, - 0x85, 0x28, 0x84, 0x09, 0xD3, 0xDF, 0xCD, 0xF4, 0x41, 0x81, - 0x4D, 0x52, 0x6A, 0xDC, 0x37, 0xC8, 0x6C, 0xC1, 0xAB, 0xFA, - 0x24, 0xE1, 0x7B, 0x08, 0x0C, 0xBD, 0xB1, 0x4A, 0x78, 0x88, - 0x95, 0x8B, 0xE3, 0x63, 0xE8, 0x6D, 0xE9, 0xCB, 0xD5, 0xFE, - 0x3B, 0x00, 0x1D, 0x39, 0xF2, 0xEF, 0xB7, 0x0E, 0x66, 0x58, - 0xD0, 0xE4, 0xA6, 0x77, 0x72, 0xF8, 0xEB, 0x75, 0x4B, 0x0A, - 0x31, 0x44, 0x50, 0xB4, 0x8F, 0xED, 0x1F, 0x1A, 0xDB, 0x99, - 0x8D, 0x33, 0x9F, 0x11, 0x83, 0x14 -}; - -void mbedtls_md2_init(mbedtls_md2_context *ctx) -{ - memset(ctx, 0, sizeof(mbedtls_md2_context)); -} - -void mbedtls_md2_free(mbedtls_md2_context *ctx) -{ - if (ctx == NULL) { - return; - } - - mbedtls_platform_zeroize(ctx, sizeof(mbedtls_md2_context)); -} - -void mbedtls_md2_clone(mbedtls_md2_context *dst, - const mbedtls_md2_context *src) -{ - *dst = *src; -} - -/* - * MD2 context setup - */ -int mbedtls_md2_starts_ret(mbedtls_md2_context *ctx) -{ - memset(ctx->cksum, 0, 16); - memset(ctx->state, 0, 46); - memset(ctx->buffer, 0, 16); - ctx->left = 0; - - return 0; -} - -#if !defined(MBEDTLS_DEPRECATED_REMOVED) -void mbedtls_md2_starts(mbedtls_md2_context *ctx) -{ - mbedtls_md2_starts_ret(ctx); -} -#endif - -#if !defined(MBEDTLS_MD2_PROCESS_ALT) -int mbedtls_internal_md2_process(mbedtls_md2_context *ctx) -{ - int i, j; - unsigned char t = 0; - - for (i = 0; i < 16; i++) { - ctx->state[i + 16] = ctx->buffer[i]; - ctx->state[i + 32] = - (unsigned char) (ctx->buffer[i] ^ ctx->state[i]); - } - - for (i = 0; i < 18; i++) { - for (j = 0; j < 48; j++) { - ctx->state[j] = (unsigned char) - (ctx->state[j] ^ PI_SUBST[t]); - t = ctx->state[j]; - } - - t = (unsigned char) (t + i); - } - - t = ctx->cksum[15]; - - for (i = 0; i < 16; i++) { - ctx->cksum[i] = (unsigned char) - (ctx->cksum[i] ^ PI_SUBST[ctx->buffer[i] ^ t]); - t = ctx->cksum[i]; - } - - /* Zeroise variables to clear sensitive data from memory. */ - mbedtls_platform_zeroize(&t, sizeof(t)); - - return 0; -} - -#if !defined(MBEDTLS_DEPRECATED_REMOVED) -void mbedtls_md2_process(mbedtls_md2_context *ctx) -{ - mbedtls_internal_md2_process(ctx); -} -#endif -#endif /* !MBEDTLS_MD2_PROCESS_ALT */ - -/* - * MD2 process buffer - */ -int mbedtls_md2_update_ret(mbedtls_md2_context *ctx, - const unsigned char *input, - size_t ilen) -{ - int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED; - size_t fill; - - while (ilen > 0) { - if (ilen > 16 - ctx->left) { - fill = 16 - ctx->left; - } else { - fill = ilen; - } - - memcpy(ctx->buffer + ctx->left, input, fill); - - ctx->left += fill; - input += fill; - ilen -= fill; - - if (ctx->left == 16) { - ctx->left = 0; - if ((ret = mbedtls_internal_md2_process(ctx)) != 0) { - return ret; - } - } - } - - return 0; -} - -#if !defined(MBEDTLS_DEPRECATED_REMOVED) -void mbedtls_md2_update(mbedtls_md2_context *ctx, - const unsigned char *input, - size_t ilen) -{ - mbedtls_md2_update_ret(ctx, input, ilen); -} -#endif - -/* - * MD2 final digest - */ -int mbedtls_md2_finish_ret(mbedtls_md2_context *ctx, - unsigned char output[16]) -{ - int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED; - size_t i; - unsigned char x; - - x = (unsigned char) (16 - ctx->left); - - for (i = ctx->left; i < 16; i++) { - ctx->buffer[i] = x; - } - - if ((ret = mbedtls_internal_md2_process(ctx)) != 0) { - return ret; - } - - memcpy(ctx->buffer, ctx->cksum, 16); - if ((ret = mbedtls_internal_md2_process(ctx)) != 0) { - return ret; - } - - memcpy(output, ctx->state, 16); - - return 0; -} - -#if !defined(MBEDTLS_DEPRECATED_REMOVED) -void mbedtls_md2_finish(mbedtls_md2_context *ctx, - unsigned char output[16]) -{ - mbedtls_md2_finish_ret(ctx, output); -} -#endif - -#endif /* !MBEDTLS_MD2_ALT */ - -/* - * output = MD2( input buffer ) - */ -int mbedtls_md2_ret(const unsigned char *input, - size_t ilen, - unsigned char output[16]) -{ - int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED; - mbedtls_md2_context ctx; - - mbedtls_md2_init(&ctx); - - if ((ret = mbedtls_md2_starts_ret(&ctx)) != 0) { - goto exit; - } - - if ((ret = mbedtls_md2_update_ret(&ctx, input, ilen)) != 0) { - goto exit; - } - - if ((ret = mbedtls_md2_finish_ret(&ctx, output)) != 0) { - goto exit; - } - -exit: - mbedtls_md2_free(&ctx); - - return ret; -} - -#if !defined(MBEDTLS_DEPRECATED_REMOVED) -void mbedtls_md2(const unsigned char *input, - size_t ilen, - unsigned char output[16]) -{ - mbedtls_md2_ret(input, ilen, output); -} -#endif - -#if defined(MBEDTLS_SELF_TEST) - -/* - * RFC 1319 test vectors - */ -static const unsigned char md2_test_str[7][81] = -{ - { "" }, - { "a" }, - { "abc" }, - { "message digest" }, - { "abcdefghijklmnopqrstuvwxyz" }, - { "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789" }, - { "12345678901234567890123456789012345678901234567890123456789012345678901234567890" } -}; - -static const size_t md2_test_strlen[7] = -{ - 0, 1, 3, 14, 26, 62, 80 -}; - -static const unsigned char md2_test_sum[7][16] = -{ - { 0x83, 0x50, 0xE5, 0xA3, 0xE2, 0x4C, 0x15, 0x3D, - 0xF2, 0x27, 0x5C, 0x9F, 0x80, 0x69, 0x27, 0x73 }, - { 0x32, 0xEC, 0x01, 0xEC, 0x4A, 0x6D, 0xAC, 0x72, - 0xC0, 0xAB, 0x96, 0xFB, 0x34, 0xC0, 0xB5, 0xD1 }, - { 0xDA, 0x85, 0x3B, 0x0D, 0x3F, 0x88, 0xD9, 0x9B, - 0x30, 0x28, 0x3A, 0x69, 0xE6, 0xDE, 0xD6, 0xBB }, - { 0xAB, 0x4F, 0x49, 0x6B, 0xFB, 0x2A, 0x53, 0x0B, - 0x21, 0x9F, 0xF3, 0x30, 0x31, 0xFE, 0x06, 0xB0 }, - { 0x4E, 0x8D, 0xDF, 0xF3, 0x65, 0x02, 0x92, 0xAB, - 0x5A, 0x41, 0x08, 0xC3, 0xAA, 0x47, 0x94, 0x0B }, - { 0xDA, 0x33, 0xDE, 0xF2, 0xA4, 0x2D, 0xF1, 0x39, - 0x75, 0x35, 0x28, 0x46, 0xC3, 0x03, 0x38, 0xCD }, - { 0xD5, 0x97, 0x6F, 0x79, 0xD8, 0x3D, 0x3A, 0x0D, - 0xC9, 0x80, 0x6C, 0x3C, 0x66, 0xF3, 0xEF, 0xD8 } -}; - -/* - * Checkup routine - */ -int mbedtls_md2_self_test(int verbose) -{ - int i, ret = 0; - unsigned char md2sum[16]; - - for (i = 0; i < 7; i++) { - if (verbose != 0) { - mbedtls_printf(" MD2 test #%d: ", i + 1); - } - - ret = mbedtls_md2_ret(md2_test_str[i], md2_test_strlen[i], md2sum); - if (ret != 0) { - goto fail; - } - - if (memcmp(md2sum, md2_test_sum[i], 16) != 0) { - ret = 1; - goto fail; - } - - if (verbose != 0) { - mbedtls_printf("passed\n"); - } - } - - if (verbose != 0) { - mbedtls_printf("\n"); - } - - return 0; - -fail: - if (verbose != 0) { - mbedtls_printf("failed\n"); - } - - return ret; -} - -#endif /* MBEDTLS_SELF_TEST */ - -#endif /* MBEDTLS_MD2_C */ diff --git a/vendor/mbedtls/library/md4.c b/vendor/mbedtls/library/md4.c deleted file mode 100644 index 163afb1ddb..0000000000 --- a/vendor/mbedtls/library/md4.c +++ /dev/null @@ -1,463 +0,0 @@ -/* - * RFC 1186/1320 compliant MD4 implementation - * - * Copyright The Mbed TLS Contributors - * SPDX-License-Identifier: Apache-2.0 - * - * Licensed under the Apache License, Version 2.0 (the "License"); you may - * not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT - * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ -/* - * The MD4 algorithm was designed by Ron Rivest in 1990. - * - * http://www.ietf.org/rfc/rfc1186.txt - * http://www.ietf.org/rfc/rfc1320.txt - */ - -#include "common.h" - -#if defined(MBEDTLS_MD4_C) - -#include "mbedtls/md4.h" -#include "mbedtls/platform_util.h" -#include "mbedtls/error.h" - -#include - -#include "mbedtls/platform.h" - -#if !defined(MBEDTLS_MD4_ALT) - -void mbedtls_md4_init(mbedtls_md4_context *ctx) -{ - memset(ctx, 0, sizeof(mbedtls_md4_context)); -} - -void mbedtls_md4_free(mbedtls_md4_context *ctx) -{ - if (ctx == NULL) { - return; - } - - mbedtls_platform_zeroize(ctx, sizeof(mbedtls_md4_context)); -} - -void mbedtls_md4_clone(mbedtls_md4_context *dst, - const mbedtls_md4_context *src) -{ - *dst = *src; -} - -/* - * MD4 context setup - */ -int mbedtls_md4_starts_ret(mbedtls_md4_context *ctx) -{ - ctx->total[0] = 0; - ctx->total[1] = 0; - - ctx->state[0] = 0x67452301; - ctx->state[1] = 0xEFCDAB89; - ctx->state[2] = 0x98BADCFE; - ctx->state[3] = 0x10325476; - - return 0; -} - -#if !defined(MBEDTLS_DEPRECATED_REMOVED) -void mbedtls_md4_starts(mbedtls_md4_context *ctx) -{ - mbedtls_md4_starts_ret(ctx); -} -#endif - -#if !defined(MBEDTLS_MD4_PROCESS_ALT) -int mbedtls_internal_md4_process(mbedtls_md4_context *ctx, - const unsigned char data[64]) -{ - struct { - uint32_t X[16], A, B, C, D; - } local; - - local.X[0] = MBEDTLS_GET_UINT32_LE(data, 0); - local.X[1] = MBEDTLS_GET_UINT32_LE(data, 4); - local.X[2] = MBEDTLS_GET_UINT32_LE(data, 8); - local.X[3] = MBEDTLS_GET_UINT32_LE(data, 12); - local.X[4] = MBEDTLS_GET_UINT32_LE(data, 16); - local.X[5] = MBEDTLS_GET_UINT32_LE(data, 20); - local.X[6] = MBEDTLS_GET_UINT32_LE(data, 24); - local.X[7] = MBEDTLS_GET_UINT32_LE(data, 28); - local.X[8] = MBEDTLS_GET_UINT32_LE(data, 32); - local.X[9] = MBEDTLS_GET_UINT32_LE(data, 36); - local.X[10] = MBEDTLS_GET_UINT32_LE(data, 40); - local.X[11] = MBEDTLS_GET_UINT32_LE(data, 44); - local.X[12] = MBEDTLS_GET_UINT32_LE(data, 48); - local.X[13] = MBEDTLS_GET_UINT32_LE(data, 52); - local.X[14] = MBEDTLS_GET_UINT32_LE(data, 56); - local.X[15] = MBEDTLS_GET_UINT32_LE(data, 60); - -#define S(x, n) (((x) << (n)) | (((x) & 0xFFFFFFFF) >> (32 - (n)))) - - local.A = ctx->state[0]; - local.B = ctx->state[1]; - local.C = ctx->state[2]; - local.D = ctx->state[3]; - -#define F(x, y, z) (((x) & (y)) | ((~(x)) & (z))) -#define P(a, b, c, d, x, s) \ - do \ - { \ - (a) += F((b), (c), (d)) + (x); \ - (a) = S((a), (s)); \ - } while (0) - - - P(local.A, local.B, local.C, local.D, local.X[0], 3); - P(local.D, local.A, local.B, local.C, local.X[1], 7); - P(local.C, local.D, local.A, local.B, local.X[2], 11); - P(local.B, local.C, local.D, local.A, local.X[3], 19); - P(local.A, local.B, local.C, local.D, local.X[4], 3); - P(local.D, local.A, local.B, local.C, local.X[5], 7); - P(local.C, local.D, local.A, local.B, local.X[6], 11); - P(local.B, local.C, local.D, local.A, local.X[7], 19); - P(local.A, local.B, local.C, local.D, local.X[8], 3); - P(local.D, local.A, local.B, local.C, local.X[9], 7); - P(local.C, local.D, local.A, local.B, local.X[10], 11); - P(local.B, local.C, local.D, local.A, local.X[11], 19); - P(local.A, local.B, local.C, local.D, local.X[12], 3); - P(local.D, local.A, local.B, local.C, local.X[13], 7); - P(local.C, local.D, local.A, local.B, local.X[14], 11); - P(local.B, local.C, local.D, local.A, local.X[15], 19); - -#undef P -#undef F - -#define F(x, y, z) (((x) & (y)) | ((x) & (z)) | ((y) & (z))) -#define P(a, b, c, d, x, s) \ - do \ - { \ - (a) += F((b), (c), (d)) + (x) + 0x5A827999; \ - (a) = S((a), (s)); \ - } while (0) - - P(local.A, local.B, local.C, local.D, local.X[0], 3); - P(local.D, local.A, local.B, local.C, local.X[4], 5); - P(local.C, local.D, local.A, local.B, local.X[8], 9); - P(local.B, local.C, local.D, local.A, local.X[12], 13); - P(local.A, local.B, local.C, local.D, local.X[1], 3); - P(local.D, local.A, local.B, local.C, local.X[5], 5); - P(local.C, local.D, local.A, local.B, local.X[9], 9); - P(local.B, local.C, local.D, local.A, local.X[13], 13); - P(local.A, local.B, local.C, local.D, local.X[2], 3); - P(local.D, local.A, local.B, local.C, local.X[6], 5); - P(local.C, local.D, local.A, local.B, local.X[10], 9); - P(local.B, local.C, local.D, local.A, local.X[14], 13); - P(local.A, local.B, local.C, local.D, local.X[3], 3); - P(local.D, local.A, local.B, local.C, local.X[7], 5); - P(local.C, local.D, local.A, local.B, local.X[11], 9); - P(local.B, local.C, local.D, local.A, local.X[15], 13); - -#undef P -#undef F - -#define F(x, y, z) ((x) ^ (y) ^ (z)) -#define P(a, b, c, d, x, s) \ - do \ - { \ - (a) += F((b), (c), (d)) + (x) + 0x6ED9EBA1; \ - (a) = S((a), (s)); \ - } while (0) - - P(local.A, local.B, local.C, local.D, local.X[0], 3); - P(local.D, local.A, local.B, local.C, local.X[8], 9); - P(local.C, local.D, local.A, local.B, local.X[4], 11); - P(local.B, local.C, local.D, local.A, local.X[12], 15); - P(local.A, local.B, local.C, local.D, local.X[2], 3); - P(local.D, local.A, local.B, local.C, local.X[10], 9); - P(local.C, local.D, local.A, local.B, local.X[6], 11); - P(local.B, local.C, local.D, local.A, local.X[14], 15); - P(local.A, local.B, local.C, local.D, local.X[1], 3); - P(local.D, local.A, local.B, local.C, local.X[9], 9); - P(local.C, local.D, local.A, local.B, local.X[5], 11); - P(local.B, local.C, local.D, local.A, local.X[13], 15); - P(local.A, local.B, local.C, local.D, local.X[3], 3); - P(local.D, local.A, local.B, local.C, local.X[11], 9); - P(local.C, local.D, local.A, local.B, local.X[7], 11); - P(local.B, local.C, local.D, local.A, local.X[15], 15); - -#undef F -#undef P - - ctx->state[0] += local.A; - ctx->state[1] += local.B; - ctx->state[2] += local.C; - ctx->state[3] += local.D; - - /* Zeroise variables to clear sensitive data from memory. */ - mbedtls_platform_zeroize(&local, sizeof(local)); - - return 0; -} - -#if !defined(MBEDTLS_DEPRECATED_REMOVED) -void mbedtls_md4_process(mbedtls_md4_context *ctx, - const unsigned char data[64]) -{ - mbedtls_internal_md4_process(ctx, data); -} -#endif -#endif /* !MBEDTLS_MD4_PROCESS_ALT */ - -/* - * MD4 process buffer - */ -int mbedtls_md4_update_ret(mbedtls_md4_context *ctx, - const unsigned char *input, - size_t ilen) -{ - int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED; - size_t fill; - uint32_t left; - - if (ilen == 0) { - return 0; - } - - left = ctx->total[0] & 0x3F; - fill = 64 - left; - - ctx->total[0] += (uint32_t) ilen; - ctx->total[0] &= 0xFFFFFFFF; - - if (ctx->total[0] < (uint32_t) ilen) { - ctx->total[1]++; - } - - if (left && ilen >= fill) { - memcpy((void *) (ctx->buffer + left), - (void *) input, fill); - - if ((ret = mbedtls_internal_md4_process(ctx, ctx->buffer)) != 0) { - return ret; - } - - input += fill; - ilen -= fill; - left = 0; - } - - while (ilen >= 64) { - if ((ret = mbedtls_internal_md4_process(ctx, input)) != 0) { - return ret; - } - - input += 64; - ilen -= 64; - } - - if (ilen > 0) { - memcpy((void *) (ctx->buffer + left), - (void *) input, ilen); - } - - return 0; -} - -#if !defined(MBEDTLS_DEPRECATED_REMOVED) -void mbedtls_md4_update(mbedtls_md4_context *ctx, - const unsigned char *input, - size_t ilen) -{ - mbedtls_md4_update_ret(ctx, input, ilen); -} -#endif - -static const unsigned char md4_padding[64] = -{ - 0x80, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 -}; - -/* - * MD4 final digest - */ -int mbedtls_md4_finish_ret(mbedtls_md4_context *ctx, - unsigned char output[16]) -{ - int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED; - uint32_t last, padn; - uint32_t high, low; - unsigned char msglen[8]; - - high = (ctx->total[0] >> 29) - | (ctx->total[1] << 3); - low = (ctx->total[0] << 3); - - MBEDTLS_PUT_UINT32_LE(low, msglen, 0); - MBEDTLS_PUT_UINT32_LE(high, msglen, 4); - - last = ctx->total[0] & 0x3F; - padn = (last < 56) ? (56 - last) : (120 - last); - - ret = mbedtls_md4_update_ret(ctx, (unsigned char *) md4_padding, padn); - if (ret != 0) { - return ret; - } - - if ((ret = mbedtls_md4_update_ret(ctx, msglen, 8)) != 0) { - return ret; - } - - - MBEDTLS_PUT_UINT32_LE(ctx->state[0], output, 0); - MBEDTLS_PUT_UINT32_LE(ctx->state[1], output, 4); - MBEDTLS_PUT_UINT32_LE(ctx->state[2], output, 8); - MBEDTLS_PUT_UINT32_LE(ctx->state[3], output, 12); - - return 0; -} - -#if !defined(MBEDTLS_DEPRECATED_REMOVED) -void mbedtls_md4_finish(mbedtls_md4_context *ctx, - unsigned char output[16]) -{ - mbedtls_md4_finish_ret(ctx, output); -} -#endif - -#endif /* !MBEDTLS_MD4_ALT */ - -/* - * output = MD4( input buffer ) - */ -int mbedtls_md4_ret(const unsigned char *input, - size_t ilen, - unsigned char output[16]) -{ - int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED; - mbedtls_md4_context ctx; - - mbedtls_md4_init(&ctx); - - if ((ret = mbedtls_md4_starts_ret(&ctx)) != 0) { - goto exit; - } - - if ((ret = mbedtls_md4_update_ret(&ctx, input, ilen)) != 0) { - goto exit; - } - - if ((ret = mbedtls_md4_finish_ret(&ctx, output)) != 0) { - goto exit; - } - -exit: - mbedtls_md4_free(&ctx); - - return ret; -} - -#if !defined(MBEDTLS_DEPRECATED_REMOVED) -void mbedtls_md4(const unsigned char *input, - size_t ilen, - unsigned char output[16]) -{ - mbedtls_md4_ret(input, ilen, output); -} -#endif - -#if defined(MBEDTLS_SELF_TEST) - -/* - * RFC 1320 test vectors - */ -static const unsigned char md4_test_str[7][81] = -{ - { "" }, - { "a" }, - { "abc" }, - { "message digest" }, - { "abcdefghijklmnopqrstuvwxyz" }, - { "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789" }, - { "12345678901234567890123456789012345678901234567890123456789012345678901234567890" } -}; - -static const size_t md4_test_strlen[7] = -{ - 0, 1, 3, 14, 26, 62, 80 -}; - -static const unsigned char md4_test_sum[7][16] = -{ - { 0x31, 0xD6, 0xCF, 0xE0, 0xD1, 0x6A, 0xE9, 0x31, - 0xB7, 0x3C, 0x59, 0xD7, 0xE0, 0xC0, 0x89, 0xC0 }, - { 0xBD, 0xE5, 0x2C, 0xB3, 0x1D, 0xE3, 0x3E, 0x46, - 0x24, 0x5E, 0x05, 0xFB, 0xDB, 0xD6, 0xFB, 0x24 }, - { 0xA4, 0x48, 0x01, 0x7A, 0xAF, 0x21, 0xD8, 0x52, - 0x5F, 0xC1, 0x0A, 0xE8, 0x7A, 0xA6, 0x72, 0x9D }, - { 0xD9, 0x13, 0x0A, 0x81, 0x64, 0x54, 0x9F, 0xE8, - 0x18, 0x87, 0x48, 0x06, 0xE1, 0xC7, 0x01, 0x4B }, - { 0xD7, 0x9E, 0x1C, 0x30, 0x8A, 0xA5, 0xBB, 0xCD, - 0xEE, 0xA8, 0xED, 0x63, 0xDF, 0x41, 0x2D, 0xA9 }, - { 0x04, 0x3F, 0x85, 0x82, 0xF2, 0x41, 0xDB, 0x35, - 0x1C, 0xE6, 0x27, 0xE1, 0x53, 0xE7, 0xF0, 0xE4 }, - { 0xE3, 0x3B, 0x4D, 0xDC, 0x9C, 0x38, 0xF2, 0x19, - 0x9C, 0x3E, 0x7B, 0x16, 0x4F, 0xCC, 0x05, 0x36 } -}; - -/* - * Checkup routine - */ -int mbedtls_md4_self_test(int verbose) -{ - int i, ret = 0; - unsigned char md4sum[16]; - - for (i = 0; i < 7; i++) { - if (verbose != 0) { - mbedtls_printf(" MD4 test #%d: ", i + 1); - } - - ret = mbedtls_md4_ret(md4_test_str[i], md4_test_strlen[i], md4sum); - if (ret != 0) { - goto fail; - } - - if (memcmp(md4sum, md4_test_sum[i], 16) != 0) { - ret = 1; - goto fail; - } - - if (verbose != 0) { - mbedtls_printf("passed\n"); - } - } - - if (verbose != 0) { - mbedtls_printf("\n"); - } - - return 0; - -fail: - if (verbose != 0) { - mbedtls_printf("failed\n"); - } - - return ret; -} - -#endif /* MBEDTLS_SELF_TEST */ - -#endif /* MBEDTLS_MD4_C */ diff --git a/vendor/mbedtls/library/md5.c b/vendor/mbedtls/library/md5.c index fb47486fe1..e4a87a2e09 100644 --- a/vendor/mbedtls/library/md5.c +++ b/vendor/mbedtls/library/md5.c @@ -2,19 +2,7 @@ * RFC 1321 compliant MD5 implementation * * Copyright The Mbed TLS Contributors - * SPDX-License-Identifier: Apache-2.0 - * - * Licensed under the Apache License, Version 2.0 (the "License"); you may - * not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT - * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. + * SPDX-License-Identifier: Apache-2.0 OR GPL-2.0-or-later */ /* * The MD5 algorithm was designed by Ron Rivest in 1991. @@ -59,7 +47,7 @@ void mbedtls_md5_clone(mbedtls_md5_context *dst, /* * MD5 context setup */ -int mbedtls_md5_starts_ret(mbedtls_md5_context *ctx) +int mbedtls_md5_starts(mbedtls_md5_context *ctx) { ctx->total[0] = 0; ctx->total[1] = 0; @@ -72,13 +60,6 @@ int mbedtls_md5_starts_ret(mbedtls_md5_context *ctx) return 0; } -#if !defined(MBEDTLS_DEPRECATED_REMOVED) -void mbedtls_md5_starts(mbedtls_md5_context *ctx) -{ - mbedtls_md5_starts_ret(ctx); -} -#endif - #if !defined(MBEDTLS_MD5_PROCESS_ALT) int mbedtls_internal_md5_process(mbedtls_md5_context *ctx, const unsigned char data[64]) @@ -214,21 +195,14 @@ int mbedtls_internal_md5_process(mbedtls_md5_context *ctx, return 0; } -#if !defined(MBEDTLS_DEPRECATED_REMOVED) -void mbedtls_md5_process(mbedtls_md5_context *ctx, - const unsigned char data[64]) -{ - mbedtls_internal_md5_process(ctx, data); -} -#endif #endif /* !MBEDTLS_MD5_PROCESS_ALT */ /* * MD5 process buffer */ -int mbedtls_md5_update_ret(mbedtls_md5_context *ctx, - const unsigned char *input, - size_t ilen) +int mbedtls_md5_update(mbedtls_md5_context *ctx, + const unsigned char *input, + size_t ilen) { int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED; size_t fill; @@ -275,20 +249,11 @@ int mbedtls_md5_update_ret(mbedtls_md5_context *ctx, return 0; } -#if !defined(MBEDTLS_DEPRECATED_REMOVED) -void mbedtls_md5_update(mbedtls_md5_context *ctx, - const unsigned char *input, - size_t ilen) -{ - mbedtls_md5_update_ret(ctx, input, ilen); -} -#endif - /* * MD5 final digest */ -int mbedtls_md5_finish_ret(mbedtls_md5_context *ctx, - unsigned char output[16]) +int mbedtls_md5_finish(mbedtls_md5_context *ctx, + unsigned char output[16]) { int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED; uint32_t used; @@ -309,7 +274,7 @@ int mbedtls_md5_finish_ret(mbedtls_md5_context *ctx, memset(ctx->buffer + used, 0, 64 - used); if ((ret = mbedtls_internal_md5_process(ctx, ctx->buffer)) != 0) { - return ret; + goto exit; } memset(ctx->buffer, 0, 56); @@ -326,7 +291,7 @@ int mbedtls_md5_finish_ret(mbedtls_md5_context *ctx, MBEDTLS_PUT_UINT32_LE(high, ctx->buffer, 60); if ((ret = mbedtls_internal_md5_process(ctx, ctx->buffer)) != 0) { - return ret; + goto exit; } /* @@ -337,40 +302,36 @@ int mbedtls_md5_finish_ret(mbedtls_md5_context *ctx, MBEDTLS_PUT_UINT32_LE(ctx->state[2], output, 8); MBEDTLS_PUT_UINT32_LE(ctx->state[3], output, 12); - return 0; -} + ret = 0; -#if !defined(MBEDTLS_DEPRECATED_REMOVED) -void mbedtls_md5_finish(mbedtls_md5_context *ctx, - unsigned char output[16]) -{ - mbedtls_md5_finish_ret(ctx, output); +exit: + mbedtls_md5_free(ctx); + return ret; } -#endif #endif /* !MBEDTLS_MD5_ALT */ /* * output = MD5( input buffer ) */ -int mbedtls_md5_ret(const unsigned char *input, - size_t ilen, - unsigned char output[16]) +int mbedtls_md5(const unsigned char *input, + size_t ilen, + unsigned char output[16]) { int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED; mbedtls_md5_context ctx; mbedtls_md5_init(&ctx); - if ((ret = mbedtls_md5_starts_ret(&ctx)) != 0) { + if ((ret = mbedtls_md5_starts(&ctx)) != 0) { goto exit; } - if ((ret = mbedtls_md5_update_ret(&ctx, input, ilen)) != 0) { + if ((ret = mbedtls_md5_update(&ctx, input, ilen)) != 0) { goto exit; } - if ((ret = mbedtls_md5_finish_ret(&ctx, output)) != 0) { + if ((ret = mbedtls_md5_finish(&ctx, output)) != 0) { goto exit; } @@ -380,15 +341,6 @@ int mbedtls_md5_ret(const unsigned char *input, return ret; } -#if !defined(MBEDTLS_DEPRECATED_REMOVED) -void mbedtls_md5(const unsigned char *input, - size_t ilen, - unsigned char output[16]) -{ - mbedtls_md5_ret(input, ilen, output); -} -#endif - #if defined(MBEDTLS_SELF_TEST) /* * RFC 1321 test vectors @@ -440,7 +392,7 @@ int mbedtls_md5_self_test(int verbose) mbedtls_printf(" MD5 test #%d: ", i + 1); } - ret = mbedtls_md5_ret(md5_test_buf[i], md5_test_buflen[i], md5sum); + ret = mbedtls_md5(md5_test_buf[i], md5_test_buflen[i], md5sum); if (ret != 0) { goto fail; } diff --git a/vendor/mbedtls/library/md_psa.h b/vendor/mbedtls/library/md_psa.h new file mode 100644 index 0000000000..028ba2409c --- /dev/null +++ b/vendor/mbedtls/library/md_psa.h @@ -0,0 +1,26 @@ +/** + * Translation between MD and PSA identifiers (algorithms, errors). + * + * Note: this internal module will go away when everything becomes based on + * PSA Crypto; it is a helper for the transition period. + * + * Copyright The Mbed TLS Contributors + * SPDX-License-Identifier: Apache-2.0 OR GPL-2.0-or-later + */ +#ifndef MBEDTLS_MD_PSA_H +#define MBEDTLS_MD_PSA_H + +#include "common.h" + +#include "mbedtls/md.h" +#include "psa/crypto.h" + +/** Convert PSA status to MD error code. + * + * \param status PSA status. + * + * \return The corresponding MD error code, + */ +int mbedtls_md_error_from_psa(psa_status_t status); + +#endif /* MBEDTLS_MD_PSA_H */ diff --git a/vendor/mbedtls/library/md_wrap.h b/vendor/mbedtls/library/md_wrap.h new file mode 100644 index 0000000000..dad123540a --- /dev/null +++ b/vendor/mbedtls/library/md_wrap.h @@ -0,0 +1,46 @@ +/** + * \file md_wrap.h + * + * \brief Message digest wrappers. + * + * \warning This in an internal header. Do not include directly. + * + * \author Adriaan de Jong + */ +/* + * Copyright The Mbed TLS Contributors + * SPDX-License-Identifier: Apache-2.0 OR GPL-2.0-or-later + */ +#ifndef MBEDTLS_MD_WRAP_H +#define MBEDTLS_MD_WRAP_H + +#include "mbedtls/build_info.h" + +#include "mbedtls/md.h" + +#ifdef __cplusplus +extern "C" { +#endif + +/** + * Message digest information. + * Allows message digest functions to be called in a generic way. + */ +struct mbedtls_md_info_t { + /** Digest identifier */ + mbedtls_md_type_t type; + + /** Output length of the digest function in bytes */ + unsigned char size; + +#if defined(MBEDTLS_MD_C) + /** Block length of the digest function in bytes */ + unsigned char block_size; +#endif +}; + +#ifdef __cplusplus +} +#endif + +#endif /* MBEDTLS_MD_WRAP_H */ diff --git a/vendor/mbedtls/library/memory_buffer_alloc.c b/vendor/mbedtls/library/memory_buffer_alloc.c index bdde4e0ba4..79b0a8b8fa 100644 --- a/vendor/mbedtls/library/memory_buffer_alloc.c +++ b/vendor/mbedtls/library/memory_buffer_alloc.c @@ -2,19 +2,7 @@ * Buffer-based memory allocator * * Copyright The Mbed TLS Contributors - * SPDX-License-Identifier: Apache-2.0 - * - * Licensed under the Apache License, Version 2.0 (the "License"); you may - * not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT - * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. + * SPDX-License-Identifier: Apache-2.0 OR GPL-2.0-or-later */ #include "common.h" @@ -520,6 +508,12 @@ void mbedtls_memory_buffer_alloc_status(void) } } +void mbedtls_memory_buffer_alloc_count_get(size_t *alloc_count, size_t *free_count) +{ + *alloc_count = heap.alloc_count; + *free_count = heap.free_count; +} + void mbedtls_memory_buffer_alloc_max_get(size_t *max_used, size_t *max_blocks) { *max_used = heap.maximum_used; diff --git a/vendor/mbedtls/library/mps_common.h b/vendor/mbedtls/library/mps_common.h index 80e3133a59..f9fe099880 100644 --- a/vendor/mbedtls/library/mps_common.h +++ b/vendor/mbedtls/library/mps_common.h @@ -1,20 +1,6 @@ /* * Copyright The Mbed TLS Contributors - * SPDX-License-Identifier: Apache-2.0 - * - * Licensed under the Apache License, Version 2.0 (the "License"); you may - * not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT - * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - * - * This file is part of Mbed TLS (https://tls.mbed.org) + * SPDX-License-Identifier: Apache-2.0 OR GPL-2.0-or-later */ /** @@ -169,7 +155,7 @@ * */ typedef size_t mbedtls_mps_stored_size_t; -#define MBEDTLS_MPS_STORED_SIZE_MAX ((mbedtls_mps_stored_size_t) -1) +#define MBEDTLS_MPS_STORED_SIZE_MAX (SIZE_MAX) /** \brief The type of buffer sizes and offsets used in the MPS API * and implementation. @@ -183,7 +169,7 @@ typedef size_t mbedtls_mps_stored_size_t; * so almost 10%. */ typedef size_t mbedtls_mps_size_t; -#define MBEDTLS_MPS_SIZE_MAX ((mbedtls_mps_size_t) -1) +#define MBEDTLS_MPS_SIZE_MAX (SIZE_MAX) #if MBEDTLS_MPS_STORED_SIZE_MAX > MBEDTLS_MPS_SIZE_MAX #error "Misconfiguration of mbedtls_mps_size_t and mbedtls_mps_stored_size_t." diff --git a/vendor/mbedtls/library/mps_error.h b/vendor/mbedtls/library/mps_error.h index 5113959beb..016a84ce49 100644 --- a/vendor/mbedtls/library/mps_error.h +++ b/vendor/mbedtls/library/mps_error.h @@ -1,20 +1,6 @@ /* * Copyright The Mbed TLS Contributors - * SPDX-License-Identifier: Apache-2.0 - * - * Licensed under the Apache License, Version 2.0 (the "License"); you may - * not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT - * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - * - * This file is part of Mbed TLS (https://tls.mbed.org) + * SPDX-License-Identifier: Apache-2.0 OR GPL-2.0-or-later */ /** diff --git a/vendor/mbedtls/library/mps_reader.c b/vendor/mbedtls/library/mps_reader.c index 75c563add2..27d0c04c10 100644 --- a/vendor/mbedtls/library/mps_reader.c +++ b/vendor/mbedtls/library/mps_reader.c @@ -2,26 +2,12 @@ * Message Processing Stack, Reader implementation * * Copyright The Mbed TLS Contributors - * SPDX-License-Identifier: Apache-2.0 - * - * Licensed under the Apache License, Version 2.0 (the "License"); you may - * not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT - * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - * - * This file is part of Mbed TLS (https://tls.mbed.org) + * SPDX-License-Identifier: Apache-2.0 OR GPL-2.0-or-later */ #include "common.h" -#if defined(MBEDTLS_SSL_PROTO_TLS1_3_EXPERIMENTAL) +#if defined(MBEDTLS_SSL_PROTO_TLS1_3) #include "mps_reader.h" #include "mps_common.h" @@ -549,4 +535,4 @@ int mbedtls_mps_reader_reclaim(mbedtls_mps_reader *rd, MBEDTLS_MPS_TRACE_RETURN(0); } -#endif /* MBEDTLS_SSL_PROTO_TLS1_3_EXPERIMENTAL */ +#endif /* MBEDTLS_SSL_PROTO_TLS1_3 */ diff --git a/vendor/mbedtls/library/mps_reader.h b/vendor/mbedtls/library/mps_reader.h index bb912ec17f..3193a5e334 100644 --- a/vendor/mbedtls/library/mps_reader.h +++ b/vendor/mbedtls/library/mps_reader.h @@ -1,20 +1,6 @@ /* * Copyright The Mbed TLS Contributors - * SPDX-License-Identifier: Apache-2.0 - * - * Licensed under the Apache License, Version 2.0 (the "License"); you may - * not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT - * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - * - * This file is part of Mbed TLS (https://tls.mbed.org) + * SPDX-License-Identifier: Apache-2.0 OR GPL-2.0-or-later */ /** diff --git a/vendor/mbedtls/library/mps_trace.c b/vendor/mbedtls/library/mps_trace.c index ccd944f533..69f6e5a0f9 100644 --- a/vendor/mbedtls/library/mps_trace.c +++ b/vendor/mbedtls/library/mps_trace.c @@ -2,26 +2,12 @@ * Message Processing Stack, Trace module * * Copyright The Mbed TLS Contributors - * SPDX-License-Identifier: Apache-2.0 - * - * Licensed under the Apache License, Version 2.0 (the "License"); you may - * not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT - * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - * - * This file is part of Mbed TLS (https://tls.mbed.org) + * SPDX-License-Identifier: Apache-2.0 OR GPL-2.0-or-later */ #include "common.h" -#if defined(MBEDTLS_SSL_PROTO_TLS1_3_EXPERIMENTAL) +#if defined(MBEDTLS_SSL_PROTO_TLS1_3) #include "mps_common.h" @@ -123,4 +109,4 @@ void mbedtls_mps_trace_indent(int level, mbedtls_mps_trace_type ty) } #endif /* MBEDTLS_MPS_ENABLE_TRACE */ -#endif /* MBEDTLS_SSL_PROTO_TLS1_3_EXPERIMENTAL */ +#endif /* MBEDTLS_SSL_PROTO_TLS1_3 */ diff --git a/vendor/mbedtls/library/mps_trace.h b/vendor/mbedtls/library/mps_trace.h index f8e0a5d807..b456b2ffdd 100644 --- a/vendor/mbedtls/library/mps_trace.h +++ b/vendor/mbedtls/library/mps_trace.h @@ -1,20 +1,6 @@ /* * Copyright The Mbed TLS Contributors - * SPDX-License-Identifier: Apache-2.0 - * - * Licensed under the Apache License, Version 2.0 (the "License"); you may - * not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT - * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - * - * This file is part of Mbed TLS (https://tls.mbed.org) + * SPDX-License-Identifier: Apache-2.0 OR GPL-2.0-or-later */ /** diff --git a/vendor/mbedtls/library/net_sockets.c b/vendor/mbedtls/library/net_sockets.c index 2c2a876b02..edec5876ad 100644 --- a/vendor/mbedtls/library/net_sockets.c +++ b/vendor/mbedtls/library/net_sockets.c @@ -2,23 +2,11 @@ * TCP/IP or UDP/IP networking functions * * Copyright The Mbed TLS Contributors - * SPDX-License-Identifier: Apache-2.0 - * - * Licensed under the Apache License, Version 2.0 (the "License"); you may - * not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT - * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. + * SPDX-License-Identifier: Apache-2.0 OR GPL-2.0-or-later */ /* Enable definition of getaddrinfo() even when compiling with -std=c99. Must - * be set before config.h, which pulls in glibc's features.h indirectly. + * be set before mbedtls_config.h, which pulls in glibc's features.h indirectly. * Harmless on other platforms. */ #ifndef _POSIX_C_SOURCE #define _POSIX_C_SOURCE 200112L @@ -34,7 +22,7 @@ #if !defined(unix) && !defined(__unix__) && !defined(__unix) && \ !defined(__APPLE__) && !defined(_WIN32) && !defined(__QNXNTO__) && \ !defined(__HAIKU__) && !defined(__midipix__) -#error "This module only works on Unix and Windows, see MBEDTLS_NET_C in config.h" +#error "This module only works on Unix and Windows, see MBEDTLS_NET_C in mbedtls_config.h" #endif #include "mbedtls/platform.h" @@ -49,11 +37,6 @@ #define IS_EINTR(ret) ((ret) == WSAEINTR) -#if !defined(_WIN32_WINNT) -/* Enables getaddrinfo() & Co */ -#define _WIN32_WINNT 0x0501 -#endif - #include #include @@ -333,7 +316,7 @@ static int net_would_block(const mbedtls_net_context *ctx) */ int mbedtls_net_accept(mbedtls_net_context *bind_ctx, mbedtls_net_context *client_ctx, - void *client_ip, size_t buf_size, size_t *ip_len) + void *client_ip, size_t buf_size, size_t *cip_len) { int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED; int type; @@ -416,22 +399,22 @@ int mbedtls_net_accept(mbedtls_net_context *bind_ctx, if (client_ip != NULL) { if (client_addr.ss_family == AF_INET) { struct sockaddr_in *addr4 = (struct sockaddr_in *) &client_addr; - *ip_len = sizeof(addr4->sin_addr.s_addr); + *cip_len = sizeof(addr4->sin_addr.s_addr); - if (buf_size < *ip_len) { + if (buf_size < *cip_len) { return MBEDTLS_ERR_NET_BUFFER_TOO_SMALL; } - memcpy(client_ip, &addr4->sin_addr.s_addr, *ip_len); + memcpy(client_ip, &addr4->sin_addr.s_addr, *cip_len); } else { struct sockaddr_in6 *addr6 = (struct sockaddr_in6 *) &client_addr; - *ip_len = sizeof(addr6->sin6_addr.s6_addr); + *cip_len = sizeof(addr6->sin6_addr.s6_addr); - if (buf_size < *ip_len) { + if (buf_size < *cip_len) { return MBEDTLS_ERR_NET_BUFFER_TOO_SMALL; } - memcpy(client_ip, &addr6->sin6_addr.s6_addr, *ip_len); + memcpy(client_ip, &addr6->sin6_addr.s6_addr, *cip_len); } } diff --git a/vendor/mbedtls/library/nist_kw.c b/vendor/mbedtls/library/nist_kw.c index 4ff5e41b46..f15425b8bd 100644 --- a/vendor/mbedtls/library/nist_kw.c +++ b/vendor/mbedtls/library/nist_kw.c @@ -3,19 +3,7 @@ * only * * Copyright The Mbed TLS Contributors - * SPDX-License-Identifier: Apache-2.0 - * - * Licensed under the Apache License, Version 2.0 (the "License"); you may - * not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT - * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. + * SPDX-License-Identifier: Apache-2.0 OR GPL-2.0-or-later */ /* * Definition of Key Wrapping: @@ -76,7 +64,7 @@ int mbedtls_nist_kw_setkey(mbedtls_nist_kw_context *ctx, return MBEDTLS_ERR_CIPHER_BAD_INPUT_DATA; } - if (cipher_info->block_size != 16) { + if (mbedtls_cipher_info_get_block_size(cipher_info) != 16) { return MBEDTLS_ERR_CIPHER_BAD_INPUT_DATA; } @@ -334,9 +322,9 @@ int mbedtls_nist_kw_unwrap(mbedtls_nist_kw_context *ctx, unsigned char *output, size_t *out_len, size_t out_size) { int ret = 0; - size_t i, olen; + size_t olen; unsigned char A[KW_SEMIBLOCK_LENGTH]; - unsigned char diff; + int diff; *out_len = 0; if (out_size < in_len - KW_SEMIBLOCK_LENGTH) { @@ -421,14 +409,15 @@ int mbedtls_nist_kw_unwrap(mbedtls_nist_kw_context *ctx, * larger than 8, because of the type wrap around. */ padlen = in_len - KW_SEMIBLOCK_LENGTH - Plen; - ret = -(int) mbedtls_ct_uint_if(padlen & ~7, -MBEDTLS_ERR_CIPHER_AUTH_FAILED, -ret); + ret = mbedtls_ct_error_if(mbedtls_ct_uint_gt(padlen, 7), + MBEDTLS_ERR_CIPHER_AUTH_FAILED, ret); padlen &= 7; /* Check padding in "constant-time" */ - for (diff = 0, i = 0; i < KW_SEMIBLOCK_LENGTH; i++) { - size_t mask = mbedtls_ct_size_mask_ge(i, KW_SEMIBLOCK_LENGTH - padlen); - diff |= (unsigned char) (mask & output[*out_len - KW_SEMIBLOCK_LENGTH + i]); - } + const uint8_t zero[KW_SEMIBLOCK_LENGTH] = { 0 }; + diff = mbedtls_ct_memcmp_partial( + &output[*out_len - KW_SEMIBLOCK_LENGTH], zero, + KW_SEMIBLOCK_LENGTH, KW_SEMIBLOCK_LENGTH - padlen, 0); if (diff != 0) { ret = MBEDTLS_ERR_CIPHER_AUTH_FAILED; @@ -460,17 +449,22 @@ int mbedtls_nist_kw_unwrap(mbedtls_nist_kw_context *ctx, #if defined(MBEDTLS_SELF_TEST) && defined(MBEDTLS_AES_C) -#define KW_TESTS 3 - /* * Test vectors taken from NIST * https://csrc.nist.gov/Projects/Cryptographic-Algorithm-Validation-Program/CAVP-TESTING-BLOCK-CIPHER-MODES#KW */ -static const unsigned int key_len[KW_TESTS] = { 16, 24, 32 }; +static const unsigned int key_len[] = { + 16, +#if !defined(MBEDTLS_AES_ONLY_128_BIT_KEY_LENGTH) + 24, + 32 +#endif +}; -static const unsigned char kw_key[KW_TESTS][32] = { +static const unsigned char kw_key[][32] = { { 0x75, 0x75, 0xda, 0x3a, 0x93, 0x60, 0x7c, 0xc2, 0xbf, 0xd8, 0xce, 0xc7, 0xaa, 0xdf, 0xd9, 0xa6 }, +#if !defined(MBEDTLS_AES_ONLY_128_BIT_KEY_LENGTH) { 0x2d, 0x85, 0x26, 0x08, 0x1d, 0x02, 0xfb, 0x5b, 0x85, 0xf6, 0x9a, 0xc2, 0x86, 0xec, 0xd5, 0x7d, 0x40, 0xdf, 0x5d, 0xf3, 0x49, 0x47, 0x44, 0xd3 }, @@ -478,11 +472,13 @@ static const unsigned char kw_key[KW_TESTS][32] = { 0x4a, 0x98, 0x48, 0xd3, 0x0f, 0xdd, 0x78, 0x33, 0x5b, 0x03, 0x9a, 0x48, 0xa8, 0x96, 0x2c, 0x4d, 0x1c, 0xb7, 0x8e, 0xab, 0xd5, 0xda, 0xd7, 0x88 } +#endif }; -static const unsigned char kw_msg[KW_TESTS][40] = { +static const unsigned char kw_msg[][40] = { { 0x42, 0x13, 0x6d, 0x3c, 0x38, 0x4a, 0x3e, 0xea, 0xc9, 0x5a, 0x06, 0x6f, 0xd2, 0x8f, 0xed, 0x3f }, +#if !defined(MBEDTLS_AES_ONLY_128_BIT_KEY_LENGTH) { 0x95, 0xc1, 0x1b, 0xf5, 0x35, 0x3a, 0xfe, 0xdb, 0x98, 0xfd, 0xd6, 0xc8, 0xca, 0x6f, 0xdb, 0x6d, 0xa5, 0x4b, 0x74, 0xb4, 0x99, 0x0f, 0xdc, 0x45, @@ -491,14 +487,28 @@ static const unsigned char kw_msg[KW_TESTS][40] = { { 0x1b, 0x20, 0xbf, 0x19, 0x90, 0xb0, 0x65, 0xd7, 0x98, 0xe1, 0xb3, 0x22, 0x64, 0xad, 0x50, 0xa8, 0x74, 0x74, 0x92, 0xba, 0x09, 0xa0, 0x4d, 0xd1 } +#endif }; -static const size_t kw_msg_len[KW_TESTS] = { 16, 40, 24 }; -static const size_t kw_out_len[KW_TESTS] = { 24, 48, 32 }; -static const unsigned char kw_res[KW_TESTS][48] = { +static const size_t kw_msg_len[] = { + 16, +#if !defined(MBEDTLS_AES_ONLY_128_BIT_KEY_LENGTH) + 40, + 24 +#endif +}; +static const size_t kw_out_len[] = { + 24, +#if !defined(MBEDTLS_AES_ONLY_128_BIT_KEY_LENGTH) + 48, + 32 +#endif +}; +static const unsigned char kw_res[][48] = { { 0x03, 0x1f, 0x6b, 0xd7, 0xe6, 0x1e, 0x64, 0x3d, 0xf6, 0x85, 0x94, 0x81, 0x6f, 0x64, 0xca, 0xa3, 0xf5, 0x6f, 0xab, 0xea, 0x25, 0x48, 0xf5, 0xfb }, +#if !defined(MBEDTLS_AES_ONLY_128_BIT_KEY_LENGTH) { 0x44, 0x3c, 0x6f, 0x15, 0x09, 0x83, 0x71, 0x91, 0x3e, 0x5c, 0x81, 0x4c, 0xa1, 0xa0, 0x42, 0xec, 0x68, 0x2f, 0x7b, 0x13, 0x6d, 0x24, 0x3a, 0x4d, @@ -509,11 +519,13 @@ static const unsigned char kw_res[KW_TESTS][48] = { 0xd5, 0xd5, 0x40, 0xec, 0x25, 0xd4, 0x3d, 0x87, 0x20, 0x0f, 0xda, 0xdc, 0x6d, 0x1f, 0x05, 0xd9, 0x16, 0x58, 0x4f, 0xa9, 0xf6, 0xcb, 0xf5, 0x12 } +#endif }; -static const unsigned char kwp_key[KW_TESTS][32] = { +static const unsigned char kwp_key[][32] = { { 0x78, 0x65, 0xe2, 0x0f, 0x3c, 0x21, 0x65, 0x9a, 0xb4, 0x69, 0x0b, 0x62, 0x9c, 0xdf, 0x3c, 0xc4 }, +#if !defined(MBEDTLS_AES_ONLY_128_BIT_KEY_LENGTH) { 0xf5, 0xf8, 0x96, 0xa3, 0xbd, 0x2f, 0x4a, 0x98, 0x23, 0xef, 0x16, 0x2b, 0x00, 0xb8, 0x05, 0xd7, 0xde, 0x1e, 0xa4, 0x66, 0x26, 0x96, 0xa2, 0x58 }, @@ -521,23 +533,33 @@ static const unsigned char kwp_key[KW_TESTS][32] = { 0x25, 0x54, 0xee, 0x2a, 0x8d, 0xf1, 0x38, 0x6f, 0x5b, 0x94, 0xa1, 0xa6, 0x0e, 0xd8, 0xa4, 0xae, 0xf6, 0x0a, 0x8d, 0x61, 0xab, 0x5f, 0x22, 0x5a } +#endif }; -static const unsigned char kwp_msg[KW_TESTS][31] = { +static const unsigned char kwp_msg[][31] = { { 0xbd, 0x68, 0x43, 0xd4, 0x20, 0x37, 0x8d, 0xc8, 0x96 }, +#if !defined(MBEDTLS_AES_ONLY_128_BIT_KEY_LENGTH) { 0x6c, 0xcd, 0xd5, 0x85, 0x18, 0x40, 0x97, 0xeb, 0xd5, 0xc3, 0xaf, 0x3e, 0x47, 0xd0, 0x2c, 0x19, 0x14, 0x7b, 0x4d, 0x99, 0x5f, 0x96, 0x43, 0x66, 0x91, 0x56, 0x75, 0x8c, 0x13, 0x16, 0x8f }, { 0xd1 } +#endif +}; +static const size_t kwp_msg_len[] = { + 9, +#if !defined(MBEDTLS_AES_ONLY_128_BIT_KEY_LENGTH) + 31, + 1 +#endif }; -static const size_t kwp_msg_len[KW_TESTS] = { 9, 31, 1 }; -static const unsigned char kwp_res[KW_TESTS][48] = { +static const unsigned char kwp_res[][48] = { { 0x41, 0xec, 0xa9, 0x56, 0xd4, 0xaa, 0x04, 0x7e, 0xb5, 0xcf, 0x4e, 0xfe, 0x65, 0x96, 0x61, 0xe7, 0x4d, 0xb6, 0xf8, 0xc5, 0x64, 0xe2, 0x35, 0x00 }, +#if !defined(MBEDTLS_AES_ONLY_128_BIT_KEY_LENGTH) { 0x4e, 0x9b, 0xc2, 0xbc, 0xbc, 0x6c, 0x1e, 0x13, 0xd3, 0x35, 0xbc, 0xc0, 0xf7, 0x73, 0x6a, 0x88, 0xfa, 0x87, 0x53, 0x66, 0x15, 0xbb, 0x8e, 0x63, @@ -545,8 +567,15 @@ static const unsigned char kwp_res[KW_TESTS][48] = { 0x67, 0xcf, 0xa9, 0x8a, 0x9d, 0x0e, 0x33, 0x26 }, { 0x06, 0xba, 0x7a, 0xe6, 0xf3, 0x24, 0x8c, 0xfd, 0xcf, 0x26, 0x75, 0x07, 0xfa, 0x00, 0x1b, 0xc4 } +#endif +}; +static const size_t kwp_out_len[] = { + 24, +#if !defined(MBEDTLS_AES_ONLY_128_BIT_KEY_LENGTH) + 40, + 16 +#endif }; -static const size_t kwp_out_len[KW_TESTS] = { 24, 40, 16 }; int mbedtls_nist_kw_self_test(int verbose) { @@ -557,114 +586,128 @@ int mbedtls_nist_kw_self_test(int verbose) int ret = 0; mbedtls_nist_kw_init(&ctx); - for (i = 0; i < KW_TESTS; i++) { - if (verbose != 0) { - mbedtls_printf(" KW-AES-%u ", (unsigned int) key_len[i] * 8); - } + /* + * KW mode + */ + { + static const int num_tests = sizeof(kw_key) / sizeof(*kw_key); - ret = mbedtls_nist_kw_setkey(&ctx, MBEDTLS_CIPHER_ID_AES, - kw_key[i], key_len[i] * 8, 1); - if (ret != 0) { + for (i = 0; i < num_tests; i++) { if (verbose != 0) { - mbedtls_printf(" KW: setup failed "); + mbedtls_printf(" KW-AES-%u ", (unsigned int) key_len[i] * 8); } - goto end; - } + ret = mbedtls_nist_kw_setkey(&ctx, MBEDTLS_CIPHER_ID_AES, + kw_key[i], key_len[i] * 8, 1); + if (ret != 0) { + if (verbose != 0) { + mbedtls_printf(" KW: setup failed "); + } - ret = mbedtls_nist_kw_wrap(&ctx, MBEDTLS_KW_MODE_KW, kw_msg[i], - kw_msg_len[i], out, &olen, sizeof(out)); - if (ret != 0 || kw_out_len[i] != olen || - memcmp(out, kw_res[i], kw_out_len[i]) != 0) { - if (verbose != 0) { - mbedtls_printf("failed. "); + goto end; } - ret = 1; - goto end; - } + ret = mbedtls_nist_kw_wrap(&ctx, MBEDTLS_KW_MODE_KW, kw_msg[i], + kw_msg_len[i], out, &olen, sizeof(out)); + if (ret != 0 || kw_out_len[i] != olen || + memcmp(out, kw_res[i], kw_out_len[i]) != 0) { + if (verbose != 0) { + mbedtls_printf("failed. "); + } - if ((ret = mbedtls_nist_kw_setkey(&ctx, MBEDTLS_CIPHER_ID_AES, - kw_key[i], key_len[i] * 8, 0)) - != 0) { - if (verbose != 0) { - mbedtls_printf(" KW: setup failed "); + ret = 1; + goto end; } - goto end; - } + if ((ret = mbedtls_nist_kw_setkey(&ctx, MBEDTLS_CIPHER_ID_AES, + kw_key[i], key_len[i] * 8, 0)) + != 0) { + if (verbose != 0) { + mbedtls_printf(" KW: setup failed "); + } - ret = mbedtls_nist_kw_unwrap(&ctx, MBEDTLS_KW_MODE_KW, - out, olen, out, &olen, sizeof(out)); - - if (ret != 0 || olen != kw_msg_len[i] || - memcmp(out, kw_msg[i], kw_msg_len[i]) != 0) { - if (verbose != 0) { - mbedtls_printf("failed\n"); + goto end; } - ret = 1; - goto end; - } + ret = mbedtls_nist_kw_unwrap(&ctx, MBEDTLS_KW_MODE_KW, + out, olen, out, &olen, sizeof(out)); - if (verbose != 0) { - mbedtls_printf(" passed\n"); - } - } + if (ret != 0 || olen != kw_msg_len[i] || + memcmp(out, kw_msg[i], kw_msg_len[i]) != 0) { + if (verbose != 0) { + mbedtls_printf("failed\n"); + } - for (i = 0; i < KW_TESTS; i++) { - olen = sizeof(out); - if (verbose != 0) { - mbedtls_printf(" KWP-AES-%u ", (unsigned int) key_len[i] * 8); - } + ret = 1; + goto end; + } - ret = mbedtls_nist_kw_setkey(&ctx, MBEDTLS_CIPHER_ID_AES, kwp_key[i], - key_len[i] * 8, 1); - if (ret != 0) { if (verbose != 0) { - mbedtls_printf(" KWP: setup failed "); + mbedtls_printf(" passed\n"); } - - goto end; } - ret = mbedtls_nist_kw_wrap(&ctx, MBEDTLS_KW_MODE_KWP, kwp_msg[i], - kwp_msg_len[i], out, &olen, sizeof(out)); + } + + /* + * KWP mode + */ + { + static const int num_tests = sizeof(kwp_key) / sizeof(*kwp_key); - if (ret != 0 || kwp_out_len[i] != olen || - memcmp(out, kwp_res[i], kwp_out_len[i]) != 0) { + for (i = 0; i < num_tests; i++) { + olen = sizeof(out); if (verbose != 0) { - mbedtls_printf("failed. "); + mbedtls_printf(" KWP-AES-%u ", (unsigned int) key_len[i] * 8); } - ret = 1; - goto end; - } + ret = mbedtls_nist_kw_setkey(&ctx, MBEDTLS_CIPHER_ID_AES, kwp_key[i], + key_len[i] * 8, 1); + if (ret != 0) { + if (verbose != 0) { + mbedtls_printf(" KWP: setup failed "); + } - if ((ret = mbedtls_nist_kw_setkey(&ctx, MBEDTLS_CIPHER_ID_AES, - kwp_key[i], key_len[i] * 8, 0)) - != 0) { - if (verbose != 0) { - mbedtls_printf(" KWP: setup failed "); + goto end; } + ret = mbedtls_nist_kw_wrap(&ctx, MBEDTLS_KW_MODE_KWP, kwp_msg[i], + kwp_msg_len[i], out, &olen, sizeof(out)); - goto end; - } + if (ret != 0 || kwp_out_len[i] != olen || + memcmp(out, kwp_res[i], kwp_out_len[i]) != 0) { + if (verbose != 0) { + mbedtls_printf("failed. "); + } - ret = mbedtls_nist_kw_unwrap(&ctx, MBEDTLS_KW_MODE_KWP, out, - olen, out, &olen, sizeof(out)); + ret = 1; + goto end; + } - if (ret != 0 || olen != kwp_msg_len[i] || - memcmp(out, kwp_msg[i], kwp_msg_len[i]) != 0) { - if (verbose != 0) { - mbedtls_printf("failed. "); + if ((ret = mbedtls_nist_kw_setkey(&ctx, MBEDTLS_CIPHER_ID_AES, + kwp_key[i], key_len[i] * 8, 0)) + != 0) { + if (verbose != 0) { + mbedtls_printf(" KWP: setup failed "); + } + + goto end; } - ret = 1; - goto end; - } + ret = mbedtls_nist_kw_unwrap(&ctx, MBEDTLS_KW_MODE_KWP, out, + olen, out, &olen, sizeof(out)); - if (verbose != 0) { - mbedtls_printf(" passed\n"); + if (ret != 0 || olen != kwp_msg_len[i] || + memcmp(out, kwp_msg[i], kwp_msg_len[i]) != 0) { + if (verbose != 0) { + mbedtls_printf("failed. "); + } + + ret = 1; + goto end; + } + + if (verbose != 0) { + mbedtls_printf(" passed\n"); + } } } end: diff --git a/vendor/mbedtls/library/oid.c b/vendor/mbedtls/library/oid.c index 12a96503bd..1d6b1eb866 100644 --- a/vendor/mbedtls/library/oid.c +++ b/vendor/mbedtls/library/oid.c @@ -4,19 +4,7 @@ * \brief Object Identifier (OID) database * * Copyright The Mbed TLS Contributors - * SPDX-License-Identifier: Apache-2.0 - * - * Licensed under the Apache License, Version 2.0 (the "License"); you may - * not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT - * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. + * SPDX-License-Identifier: Apache-2.0 OR GPL-2.0-or-later */ #include "common.h" @@ -26,6 +14,7 @@ #include "mbedtls/oid.h" #include "mbedtls/rsa.h" #include "mbedtls/error.h" +#include "mbedtls/pk.h" #include #include @@ -37,6 +26,17 @@ */ #define ADD_LEN(s) s, MBEDTLS_OID_SIZE(s) +/* + * Macro to generate mbedtls_oid_descriptor_t + */ +#if !defined(MBEDTLS_X509_REMOVE_INFO) +#define OID_DESCRIPTOR(s, name, description) { ADD_LEN(s), name, description } +#define NULL_OID_DESCRIPTOR { NULL, 0, NULL, NULL } +#else +#define OID_DESCRIPTOR(s, name, description) { ADD_LEN(s) } +#define NULL_OID_DESCRIPTOR { NULL, 0 } +#endif + /* * Macro to generate an internal function for oid_XXX_from_asn1() (used by * the other functions) @@ -60,6 +60,7 @@ return NULL; \ } +#if !defined(MBEDTLS_X509_REMOVE_INFO) /* * Macro to generate a function for retrieving a single attribute from the * descriptor of an mbedtls_oid_descriptor_t wrapper. @@ -72,6 +73,7 @@ *ATTR1 = data->descriptor.ATTR1; \ return 0; \ } +#endif /* MBEDTLS_X509_REMOVE_INFO */ /* * Macro to generate a function for retrieving a single attribute from an @@ -153,88 +155,102 @@ typedef struct { static const oid_x520_attr_t oid_x520_attr_type[] = { { - { ADD_LEN(MBEDTLS_OID_AT_CN), "id-at-commonName", "Common Name" }, + OID_DESCRIPTOR(MBEDTLS_OID_AT_CN, "id-at-commonName", "Common Name"), "CN", }, { - { ADD_LEN(MBEDTLS_OID_AT_COUNTRY), "id-at-countryName", "Country" }, + OID_DESCRIPTOR(MBEDTLS_OID_AT_COUNTRY, "id-at-countryName", "Country"), "C", }, { - { ADD_LEN(MBEDTLS_OID_AT_LOCALITY), "id-at-locality", "Locality" }, + OID_DESCRIPTOR(MBEDTLS_OID_AT_LOCALITY, "id-at-locality", "Locality"), "L", }, { - { ADD_LEN(MBEDTLS_OID_AT_STATE), "id-at-state", "State" }, + OID_DESCRIPTOR(MBEDTLS_OID_AT_STATE, "id-at-state", "State"), "ST", }, { - { ADD_LEN(MBEDTLS_OID_AT_ORGANIZATION), "id-at-organizationName", "Organization" }, + OID_DESCRIPTOR(MBEDTLS_OID_AT_ORGANIZATION, "id-at-organizationName", + "Organization"), "O", }, { - { ADD_LEN(MBEDTLS_OID_AT_ORG_UNIT), "id-at-organizationalUnitName", "Org Unit" }, + OID_DESCRIPTOR(MBEDTLS_OID_AT_ORG_UNIT, "id-at-organizationalUnitName", "Org Unit"), "OU", }, { - { ADD_LEN(MBEDTLS_OID_PKCS9_EMAIL), "emailAddress", "E-mail address" }, + OID_DESCRIPTOR(MBEDTLS_OID_PKCS9_EMAIL, + "emailAddress", + "E-mail address"), "emailAddress", }, { - { ADD_LEN(MBEDTLS_OID_AT_SERIAL_NUMBER), "id-at-serialNumber", "Serial number" }, + OID_DESCRIPTOR(MBEDTLS_OID_AT_SERIAL_NUMBER, + "id-at-serialNumber", + "Serial number"), "serialNumber", }, { - { ADD_LEN(MBEDTLS_OID_AT_POSTAL_ADDRESS), "id-at-postalAddress", - "Postal address" }, + OID_DESCRIPTOR(MBEDTLS_OID_AT_POSTAL_ADDRESS, + "id-at-postalAddress", + "Postal address"), "postalAddress", }, { - { ADD_LEN(MBEDTLS_OID_AT_POSTAL_CODE), "id-at-postalCode", "Postal code" }, + OID_DESCRIPTOR(MBEDTLS_OID_AT_POSTAL_CODE, "id-at-postalCode", "Postal code"), "postalCode", }, { - { ADD_LEN(MBEDTLS_OID_AT_SUR_NAME), "id-at-surName", "Surname" }, + OID_DESCRIPTOR(MBEDTLS_OID_AT_SUR_NAME, "id-at-surName", "Surname"), "SN", }, { - { ADD_LEN(MBEDTLS_OID_AT_GIVEN_NAME), "id-at-givenName", "Given name" }, + OID_DESCRIPTOR(MBEDTLS_OID_AT_GIVEN_NAME, "id-at-givenName", "Given name"), "GN", }, { - { ADD_LEN(MBEDTLS_OID_AT_INITIALS), "id-at-initials", "Initials" }, + OID_DESCRIPTOR(MBEDTLS_OID_AT_INITIALS, "id-at-initials", "Initials"), "initials", }, { - { ADD_LEN(MBEDTLS_OID_AT_GENERATION_QUALIFIER), "id-at-generationQualifier", - "Generation qualifier" }, + OID_DESCRIPTOR(MBEDTLS_OID_AT_GENERATION_QUALIFIER, + "id-at-generationQualifier", + "Generation qualifier"), "generationQualifier", }, { - { ADD_LEN(MBEDTLS_OID_AT_TITLE), "id-at-title", "Title" }, + OID_DESCRIPTOR(MBEDTLS_OID_AT_TITLE, "id-at-title", "Title"), "title", }, { - { ADD_LEN(MBEDTLS_OID_AT_DN_QUALIFIER), "id-at-dnQualifier", - "Distinguished Name qualifier" }, + OID_DESCRIPTOR(MBEDTLS_OID_AT_DN_QUALIFIER, + "id-at-dnQualifier", + "Distinguished Name qualifier"), "dnQualifier", }, { - { ADD_LEN(MBEDTLS_OID_AT_PSEUDONYM), "id-at-pseudonym", "Pseudonym" }, + OID_DESCRIPTOR(MBEDTLS_OID_AT_PSEUDONYM, "id-at-pseudonym", "Pseudonym"), "pseudonym", }, { - { ADD_LEN(MBEDTLS_OID_DOMAIN_COMPONENT), "id-domainComponent", - "Domain component" }, + OID_DESCRIPTOR(MBEDTLS_OID_UID, "id-uid", "User Id"), + "uid", + }, + { + OID_DESCRIPTOR(MBEDTLS_OID_DOMAIN_COMPONENT, + "id-domainComponent", + "Domain component"), "DC", }, { - { ADD_LEN(MBEDTLS_OID_AT_UNIQUE_IDENTIFIER), "id-at-uniqueIdentifier", - "Unique Identifier" }, + OID_DESCRIPTOR(MBEDTLS_OID_AT_UNIQUE_IDENTIFIER, + "id-at-uniqueIdentifier", + "Unique Identifier"), "uniqueIdentifier", }, { - { NULL, 0, NULL, NULL }, + NULL_OID_DESCRIPTOR, NULL, } }; @@ -257,36 +273,53 @@ typedef struct { static const oid_x509_ext_t oid_x509_ext[] = { { - { ADD_LEN(MBEDTLS_OID_BASIC_CONSTRAINTS), "id-ce-basicConstraints", - "Basic Constraints" }, + OID_DESCRIPTOR(MBEDTLS_OID_BASIC_CONSTRAINTS, + "id-ce-basicConstraints", + "Basic Constraints"), MBEDTLS_OID_X509_EXT_BASIC_CONSTRAINTS, }, { - { ADD_LEN(MBEDTLS_OID_KEY_USAGE), "id-ce-keyUsage", "Key Usage" }, + OID_DESCRIPTOR(MBEDTLS_OID_KEY_USAGE, "id-ce-keyUsage", "Key Usage"), MBEDTLS_OID_X509_EXT_KEY_USAGE, }, { - { ADD_LEN(MBEDTLS_OID_EXTENDED_KEY_USAGE), "id-ce-extKeyUsage", - "Extended Key Usage" }, + OID_DESCRIPTOR(MBEDTLS_OID_EXTENDED_KEY_USAGE, + "id-ce-extKeyUsage", + "Extended Key Usage"), MBEDTLS_OID_X509_EXT_EXTENDED_KEY_USAGE, }, { - { ADD_LEN(MBEDTLS_OID_SUBJECT_ALT_NAME), "id-ce-subjectAltName", - "Subject Alt Name" }, + OID_DESCRIPTOR(MBEDTLS_OID_SUBJECT_ALT_NAME, + "id-ce-subjectAltName", + "Subject Alt Name"), MBEDTLS_OID_X509_EXT_SUBJECT_ALT_NAME, }, { - { ADD_LEN(MBEDTLS_OID_NS_CERT_TYPE), "id-netscape-certtype", - "Netscape Certificate Type" }, + OID_DESCRIPTOR(MBEDTLS_OID_NS_CERT_TYPE, + "id-netscape-certtype", + "Netscape Certificate Type"), MBEDTLS_OID_X509_EXT_NS_CERT_TYPE, }, { - { ADD_LEN(MBEDTLS_OID_CERTIFICATE_POLICIES), "id-ce-certificatePolicies", - "Certificate Policies" }, + OID_DESCRIPTOR(MBEDTLS_OID_CERTIFICATE_POLICIES, + "id-ce-certificatePolicies", + "Certificate Policies"), MBEDTLS_OID_X509_EXT_CERTIFICATE_POLICIES, }, { - { NULL, 0, NULL, NULL }, + OID_DESCRIPTOR(MBEDTLS_OID_SUBJECT_KEY_IDENTIFIER, + "id-ce-subjectKeyIdentifier", + "Subject Key Identifier"), + MBEDTLS_OID_X509_EXT_SUBJECT_KEY_IDENTIFIER, + }, + { + OID_DESCRIPTOR(MBEDTLS_OID_AUTHORITY_KEY_IDENTIFIER, + "id-ce-authorityKeyIdentifier", + "Authority Key Identifier"), + MBEDTLS_OID_X509_EXT_AUTHORITY_KEY_IDENTIFIER, + }, + { + NULL_OID_DESCRIPTOR, 0, }, }; @@ -294,19 +327,23 @@ static const oid_x509_ext_t oid_x509_ext[] = FN_OID_TYPED_FROM_ASN1(oid_x509_ext_t, x509_ext, oid_x509_ext) FN_OID_GET_ATTR1(mbedtls_oid_get_x509_ext_type, oid_x509_ext_t, x509_ext, int, ext_type) +#if !defined(MBEDTLS_X509_REMOVE_INFO) static const mbedtls_oid_descriptor_t oid_ext_key_usage[] = { - { ADD_LEN(MBEDTLS_OID_SERVER_AUTH), "id-kp-serverAuth", - "TLS Web Server Authentication" }, - { ADD_LEN(MBEDTLS_OID_CLIENT_AUTH), "id-kp-clientAuth", - "TLS Web Client Authentication" }, - { ADD_LEN(MBEDTLS_OID_CODE_SIGNING), "id-kp-codeSigning", "Code Signing" }, - { ADD_LEN(MBEDTLS_OID_EMAIL_PROTECTION), "id-kp-emailProtection", "E-mail Protection" }, - { ADD_LEN(MBEDTLS_OID_TIME_STAMPING), "id-kp-timeStamping", "Time Stamping" }, - { ADD_LEN(MBEDTLS_OID_OCSP_SIGNING), "id-kp-OCSPSigning", "OCSP Signing" }, - { ADD_LEN(MBEDTLS_OID_WISUN_FAN), "id-kp-wisun-fan-device", - "Wi-SUN Alliance Field Area Network (FAN)" }, - { NULL, 0, NULL, NULL }, + OID_DESCRIPTOR(MBEDTLS_OID_SERVER_AUTH, + "id-kp-serverAuth", + "TLS Web Server Authentication"), + OID_DESCRIPTOR(MBEDTLS_OID_CLIENT_AUTH, + "id-kp-clientAuth", + "TLS Web Client Authentication"), + OID_DESCRIPTOR(MBEDTLS_OID_CODE_SIGNING, "id-kp-codeSigning", "Code Signing"), + OID_DESCRIPTOR(MBEDTLS_OID_EMAIL_PROTECTION, "id-kp-emailProtection", "E-mail Protection"), + OID_DESCRIPTOR(MBEDTLS_OID_TIME_STAMPING, "id-kp-timeStamping", "Time Stamping"), + OID_DESCRIPTOR(MBEDTLS_OID_OCSP_SIGNING, "id-kp-OCSPSigning", "OCSP Signing"), + OID_DESCRIPTOR(MBEDTLS_OID_WISUN_FAN, + "id-kp-wisun-fan-device", + "Wi-SUN Alliance Field Area Network (FAN)"), + NULL_OID_DESCRIPTOR, }; FN_OID_TYPED_FROM_ASN1(mbedtls_oid_descriptor_t, ext_key_usage, oid_ext_key_usage) @@ -318,8 +355,8 @@ FN_OID_GET_ATTR1(mbedtls_oid_get_extended_key_usage, static const mbedtls_oid_descriptor_t oid_certificate_policies[] = { - { ADD_LEN(MBEDTLS_OID_ANY_POLICY), "anyPolicy", "Any Policy" }, - { NULL, 0, NULL, NULL }, + OID_DESCRIPTOR(MBEDTLS_OID_ANY_POLICY, "anyPolicy", "Any Policy"), + NULL_OID_DESCRIPTOR, }; FN_OID_TYPED_FROM_ASN1(mbedtls_oid_descriptor_t, certificate_policies, oid_certificate_policies) @@ -328,8 +365,8 @@ FN_OID_GET_ATTR1(mbedtls_oid_get_certificate_policies, certificate_policies, const char *, description) +#endif /* MBEDTLS_X509_REMOVE_INFO */ -#if defined(MBEDTLS_MD_C) /* * For SignatureAlgorithmIdentifier */ @@ -342,103 +379,107 @@ typedef struct { static const oid_sig_alg_t oid_sig_alg[] = { #if defined(MBEDTLS_RSA_C) -#if defined(MBEDTLS_MD2_C) - { - { ADD_LEN(MBEDTLS_OID_PKCS1_MD2), "md2WithRSAEncryption", "RSA with MD2" }, - MBEDTLS_MD_MD2, MBEDTLS_PK_RSA, - }, -#endif /* MBEDTLS_MD2_C */ -#if defined(MBEDTLS_MD4_C) - { - { ADD_LEN(MBEDTLS_OID_PKCS1_MD4), "md4WithRSAEncryption", "RSA with MD4" }, - MBEDTLS_MD_MD4, MBEDTLS_PK_RSA, - }, -#endif /* MBEDTLS_MD4_C */ -#if defined(MBEDTLS_MD5_C) +#if defined(MBEDTLS_MD_CAN_MD5) { - { ADD_LEN(MBEDTLS_OID_PKCS1_MD5), "md5WithRSAEncryption", "RSA with MD5" }, + OID_DESCRIPTOR(MBEDTLS_OID_PKCS1_MD5, "md5WithRSAEncryption", "RSA with MD5"), MBEDTLS_MD_MD5, MBEDTLS_PK_RSA, }, -#endif /* MBEDTLS_MD5_C */ -#if defined(MBEDTLS_SHA1_C) +#endif /* MBEDTLS_MD_CAN_MD5 */ +#if defined(MBEDTLS_MD_CAN_SHA1) { - { ADD_LEN(MBEDTLS_OID_PKCS1_SHA1), "sha-1WithRSAEncryption", "RSA with SHA1" }, + OID_DESCRIPTOR(MBEDTLS_OID_PKCS1_SHA1, "sha-1WithRSAEncryption", "RSA with SHA1"), MBEDTLS_MD_SHA1, MBEDTLS_PK_RSA, }, -#endif /* MBEDTLS_SHA1_C */ -#if defined(MBEDTLS_SHA256_C) +#endif /* MBEDTLS_MD_CAN_SHA1 */ +#if defined(MBEDTLS_MD_CAN_SHA224) { - { ADD_LEN(MBEDTLS_OID_PKCS1_SHA224), "sha224WithRSAEncryption", "RSA with SHA-224" }, + OID_DESCRIPTOR(MBEDTLS_OID_PKCS1_SHA224, "sha224WithRSAEncryption", + "RSA with SHA-224"), MBEDTLS_MD_SHA224, MBEDTLS_PK_RSA, }, +#endif /* MBEDTLS_MD_CAN_SHA224 */ +#if defined(MBEDTLS_MD_CAN_SHA256) { - { ADD_LEN(MBEDTLS_OID_PKCS1_SHA256), "sha256WithRSAEncryption", "RSA with SHA-256" }, + OID_DESCRIPTOR(MBEDTLS_OID_PKCS1_SHA256, "sha256WithRSAEncryption", + "RSA with SHA-256"), MBEDTLS_MD_SHA256, MBEDTLS_PK_RSA, }, -#endif /* MBEDTLS_SHA256_C */ -#if defined(MBEDTLS_SHA512_C) +#endif /* MBEDTLS_MD_CAN_SHA256 */ +#if defined(MBEDTLS_MD_CAN_SHA384) { - { ADD_LEN(MBEDTLS_OID_PKCS1_SHA384), "sha384WithRSAEncryption", "RSA with SHA-384" }, + OID_DESCRIPTOR(MBEDTLS_OID_PKCS1_SHA384, "sha384WithRSAEncryption", + "RSA with SHA-384"), MBEDTLS_MD_SHA384, MBEDTLS_PK_RSA, }, +#endif /* MBEDTLS_MD_CAN_SHA384 */ +#if defined(MBEDTLS_MD_CAN_SHA512) { - { ADD_LEN(MBEDTLS_OID_PKCS1_SHA512), "sha512WithRSAEncryption", "RSA with SHA-512" }, + OID_DESCRIPTOR(MBEDTLS_OID_PKCS1_SHA512, "sha512WithRSAEncryption", + "RSA with SHA-512"), MBEDTLS_MD_SHA512, MBEDTLS_PK_RSA, }, -#endif /* MBEDTLS_SHA512_C */ -#if defined(MBEDTLS_SHA1_C) +#endif /* MBEDTLS_MD_CAN_SHA512 */ +#if defined(MBEDTLS_MD_CAN_SHA1) { - { ADD_LEN(MBEDTLS_OID_RSA_SHA_OBS), "sha-1WithRSAEncryption", "RSA with SHA1" }, + OID_DESCRIPTOR(MBEDTLS_OID_RSA_SHA_OBS, "sha-1WithRSAEncryption", "RSA with SHA1"), MBEDTLS_MD_SHA1, MBEDTLS_PK_RSA, }, -#endif /* MBEDTLS_SHA1_C */ +#endif /* MBEDTLS_MD_CAN_SHA1 */ #endif /* MBEDTLS_RSA_C */ -#if defined(MBEDTLS_ECDSA_C) -#if defined(MBEDTLS_SHA1_C) +#if defined(MBEDTLS_PK_CAN_ECDSA_SOME) +#if defined(MBEDTLS_MD_CAN_SHA1) { - { ADD_LEN(MBEDTLS_OID_ECDSA_SHA1), "ecdsa-with-SHA1", "ECDSA with SHA1" }, + OID_DESCRIPTOR(MBEDTLS_OID_ECDSA_SHA1, "ecdsa-with-SHA1", "ECDSA with SHA1"), MBEDTLS_MD_SHA1, MBEDTLS_PK_ECDSA, }, -#endif /* MBEDTLS_SHA1_C */ -#if defined(MBEDTLS_SHA256_C) +#endif /* MBEDTLS_MD_CAN_SHA1 */ +#if defined(MBEDTLS_MD_CAN_SHA224) { - { ADD_LEN(MBEDTLS_OID_ECDSA_SHA224), "ecdsa-with-SHA224", "ECDSA with SHA224" }, + OID_DESCRIPTOR(MBEDTLS_OID_ECDSA_SHA224, "ecdsa-with-SHA224", "ECDSA with SHA224"), MBEDTLS_MD_SHA224, MBEDTLS_PK_ECDSA, }, +#endif +#if defined(MBEDTLS_MD_CAN_SHA256) { - { ADD_LEN(MBEDTLS_OID_ECDSA_SHA256), "ecdsa-with-SHA256", "ECDSA with SHA256" }, + OID_DESCRIPTOR(MBEDTLS_OID_ECDSA_SHA256, "ecdsa-with-SHA256", "ECDSA with SHA256"), MBEDTLS_MD_SHA256, MBEDTLS_PK_ECDSA, }, -#endif /* MBEDTLS_SHA256_C */ -#if defined(MBEDTLS_SHA512_C) +#endif /* MBEDTLS_MD_CAN_SHA256 */ +#if defined(MBEDTLS_MD_CAN_SHA384) { - { ADD_LEN(MBEDTLS_OID_ECDSA_SHA384), "ecdsa-with-SHA384", "ECDSA with SHA384" }, + OID_DESCRIPTOR(MBEDTLS_OID_ECDSA_SHA384, "ecdsa-with-SHA384", "ECDSA with SHA384"), MBEDTLS_MD_SHA384, MBEDTLS_PK_ECDSA, }, +#endif /* MBEDTLS_MD_CAN_SHA384 */ +#if defined(MBEDTLS_MD_CAN_SHA512) { - { ADD_LEN(MBEDTLS_OID_ECDSA_SHA512), "ecdsa-with-SHA512", "ECDSA with SHA512" }, + OID_DESCRIPTOR(MBEDTLS_OID_ECDSA_SHA512, "ecdsa-with-SHA512", "ECDSA with SHA512"), MBEDTLS_MD_SHA512, MBEDTLS_PK_ECDSA, }, -#endif /* MBEDTLS_SHA512_C */ -#endif /* MBEDTLS_ECDSA_C */ +#endif /* MBEDTLS_MD_CAN_SHA512 */ +#endif /* MBEDTLS_PK_CAN_ECDSA_SOME */ #if defined(MBEDTLS_RSA_C) { - { ADD_LEN(MBEDTLS_OID_RSASSA_PSS), "RSASSA-PSS", "RSASSA-PSS" }, + OID_DESCRIPTOR(MBEDTLS_OID_RSASSA_PSS, "RSASSA-PSS", "RSASSA-PSS"), MBEDTLS_MD_NONE, MBEDTLS_PK_RSASSA_PSS, }, #endif /* MBEDTLS_RSA_C */ { - { NULL, 0, NULL, NULL }, + NULL_OID_DESCRIPTOR, MBEDTLS_MD_NONE, MBEDTLS_PK_NONE, }, }; FN_OID_TYPED_FROM_ASN1(oid_sig_alg_t, sig_alg, oid_sig_alg) + +#if !defined(MBEDTLS_X509_REMOVE_INFO) FN_OID_GET_DESCRIPTOR_ATTR1(mbedtls_oid_get_sig_alg_desc, oid_sig_alg_t, sig_alg, const char *, description) +#endif + FN_OID_GET_ATTR2(mbedtls_oid_get_sig_alg, oid_sig_alg_t, sig_alg, @@ -453,7 +494,6 @@ FN_OID_GET_OID_BY_ATTR2(mbedtls_oid_get_oid_by_sig_alg, pk_alg, mbedtls_md_type_t, md_alg) -#endif /* MBEDTLS_MD_C */ /* * For PublicKeyInfo (PKCS1, RFC 5480) @@ -466,19 +506,19 @@ typedef struct { static const oid_pk_alg_t oid_pk_alg[] = { { - { ADD_LEN(MBEDTLS_OID_PKCS1_RSA), "rsaEncryption", "RSA" }, + OID_DESCRIPTOR(MBEDTLS_OID_PKCS1_RSA, "rsaEncryption", "RSA"), MBEDTLS_PK_RSA, }, { - { ADD_LEN(MBEDTLS_OID_EC_ALG_UNRESTRICTED), "id-ecPublicKey", "Generic EC key" }, + OID_DESCRIPTOR(MBEDTLS_OID_EC_ALG_UNRESTRICTED, "id-ecPublicKey", "Generic EC key"), MBEDTLS_PK_ECKEY, }, { - { ADD_LEN(MBEDTLS_OID_EC_ALG_ECDH), "id-ecDH", "EC key for ECDH" }, + OID_DESCRIPTOR(MBEDTLS_OID_EC_ALG_ECDH, "id-ecDH", "EC key for ECDH"), MBEDTLS_PK_ECKEY_DH, }, { - { NULL, 0, NULL, NULL }, + NULL_OID_DESCRIPTOR, MBEDTLS_PK_NONE, }, }; @@ -491,9 +531,9 @@ FN_OID_GET_OID_BY_ATTR1(mbedtls_oid_get_oid_by_pk_alg, mbedtls_pk_type_t, pk_alg) -#if defined(MBEDTLS_ECP_C) +#if defined(MBEDTLS_PK_HAVE_ECC_KEYS) /* - * For namedCurve (RFC 5480) + * For elliptic curves that use namedCurve inside ECParams (RFC 5480) */ typedef struct { mbedtls_oid_descriptor_t descriptor; @@ -502,74 +542,74 @@ typedef struct { static const oid_ecp_grp_t oid_ecp_grp[] = { -#if defined(MBEDTLS_ECP_DP_SECP192R1_ENABLED) +#if defined(MBEDTLS_ECP_HAVE_SECP192R1) { - { ADD_LEN(MBEDTLS_OID_EC_GRP_SECP192R1), "secp192r1", "secp192r1" }, + OID_DESCRIPTOR(MBEDTLS_OID_EC_GRP_SECP192R1, "secp192r1", "secp192r1"), MBEDTLS_ECP_DP_SECP192R1, }, -#endif /* MBEDTLS_ECP_DP_SECP192R1_ENABLED */ -#if defined(MBEDTLS_ECP_DP_SECP224R1_ENABLED) +#endif /* MBEDTLS_ECP_HAVE_SECP192R1 */ +#if defined(MBEDTLS_ECP_HAVE_SECP224R1) { - { ADD_LEN(MBEDTLS_OID_EC_GRP_SECP224R1), "secp224r1", "secp224r1" }, + OID_DESCRIPTOR(MBEDTLS_OID_EC_GRP_SECP224R1, "secp224r1", "secp224r1"), MBEDTLS_ECP_DP_SECP224R1, }, -#endif /* MBEDTLS_ECP_DP_SECP224R1_ENABLED */ -#if defined(MBEDTLS_ECP_DP_SECP256R1_ENABLED) +#endif /* MBEDTLS_ECP_HAVE_SECP224R1 */ +#if defined(MBEDTLS_ECP_HAVE_SECP256R1) { - { ADD_LEN(MBEDTLS_OID_EC_GRP_SECP256R1), "secp256r1", "secp256r1" }, + OID_DESCRIPTOR(MBEDTLS_OID_EC_GRP_SECP256R1, "secp256r1", "secp256r1"), MBEDTLS_ECP_DP_SECP256R1, }, -#endif /* MBEDTLS_ECP_DP_SECP256R1_ENABLED */ -#if defined(MBEDTLS_ECP_DP_SECP384R1_ENABLED) +#endif /* MBEDTLS_ECP_HAVE_SECP256R1 */ +#if defined(MBEDTLS_ECP_HAVE_SECP384R1) { - { ADD_LEN(MBEDTLS_OID_EC_GRP_SECP384R1), "secp384r1", "secp384r1" }, + OID_DESCRIPTOR(MBEDTLS_OID_EC_GRP_SECP384R1, "secp384r1", "secp384r1"), MBEDTLS_ECP_DP_SECP384R1, }, -#endif /* MBEDTLS_ECP_DP_SECP384R1_ENABLED */ -#if defined(MBEDTLS_ECP_DP_SECP521R1_ENABLED) +#endif /* MBEDTLS_ECP_HAVE_SECP384R1 */ +#if defined(MBEDTLS_ECP_HAVE_SECP521R1) { - { ADD_LEN(MBEDTLS_OID_EC_GRP_SECP521R1), "secp521r1", "secp521r1" }, + OID_DESCRIPTOR(MBEDTLS_OID_EC_GRP_SECP521R1, "secp521r1", "secp521r1"), MBEDTLS_ECP_DP_SECP521R1, }, -#endif /* MBEDTLS_ECP_DP_SECP521R1_ENABLED */ -#if defined(MBEDTLS_ECP_DP_SECP192K1_ENABLED) +#endif /* MBEDTLS_ECP_HAVE_SECP521R1 */ +#if defined(MBEDTLS_ECP_HAVE_SECP192K1) { - { ADD_LEN(MBEDTLS_OID_EC_GRP_SECP192K1), "secp192k1", "secp192k1" }, + OID_DESCRIPTOR(MBEDTLS_OID_EC_GRP_SECP192K1, "secp192k1", "secp192k1"), MBEDTLS_ECP_DP_SECP192K1, }, -#endif /* MBEDTLS_ECP_DP_SECP192K1_ENABLED */ -#if defined(MBEDTLS_ECP_DP_SECP224K1_ENABLED) +#endif /* MBEDTLS_ECP_HAVE_SECP192K1 */ +#if defined(MBEDTLS_ECP_HAVE_SECP224K1) { - { ADD_LEN(MBEDTLS_OID_EC_GRP_SECP224K1), "secp224k1", "secp224k1" }, + OID_DESCRIPTOR(MBEDTLS_OID_EC_GRP_SECP224K1, "secp224k1", "secp224k1"), MBEDTLS_ECP_DP_SECP224K1, }, -#endif /* MBEDTLS_ECP_DP_SECP224K1_ENABLED */ -#if defined(MBEDTLS_ECP_DP_SECP256K1_ENABLED) +#endif /* MBEDTLS_ECP_HAVE_SECP224K1 */ +#if defined(MBEDTLS_ECP_HAVE_SECP256K1) { - { ADD_LEN(MBEDTLS_OID_EC_GRP_SECP256K1), "secp256k1", "secp256k1" }, + OID_DESCRIPTOR(MBEDTLS_OID_EC_GRP_SECP256K1, "secp256k1", "secp256k1"), MBEDTLS_ECP_DP_SECP256K1, }, -#endif /* MBEDTLS_ECP_DP_SECP256K1_ENABLED */ -#if defined(MBEDTLS_ECP_DP_BP256R1_ENABLED) +#endif /* MBEDTLS_ECP_HAVE_SECP256K1 */ +#if defined(MBEDTLS_ECP_HAVE_BP256R1) { - { ADD_LEN(MBEDTLS_OID_EC_GRP_BP256R1), "brainpoolP256r1", "brainpool256r1" }, + OID_DESCRIPTOR(MBEDTLS_OID_EC_GRP_BP256R1, "brainpoolP256r1", "brainpool256r1"), MBEDTLS_ECP_DP_BP256R1, }, -#endif /* MBEDTLS_ECP_DP_BP256R1_ENABLED */ -#if defined(MBEDTLS_ECP_DP_BP384R1_ENABLED) +#endif /* MBEDTLS_ECP_HAVE_BP256R1 */ +#if defined(MBEDTLS_ECP_HAVE_BP384R1) { - { ADD_LEN(MBEDTLS_OID_EC_GRP_BP384R1), "brainpoolP384r1", "brainpool384r1" }, + OID_DESCRIPTOR(MBEDTLS_OID_EC_GRP_BP384R1, "brainpoolP384r1", "brainpool384r1"), MBEDTLS_ECP_DP_BP384R1, }, -#endif /* MBEDTLS_ECP_DP_BP384R1_ENABLED */ -#if defined(MBEDTLS_ECP_DP_BP512R1_ENABLED) +#endif /* MBEDTLS_ECP_HAVE_BP384R1 */ +#if defined(MBEDTLS_ECP_HAVE_BP512R1) { - { ADD_LEN(MBEDTLS_OID_EC_GRP_BP512R1), "brainpoolP512r1", "brainpool512r1" }, + OID_DESCRIPTOR(MBEDTLS_OID_EC_GRP_BP512R1, "brainpoolP512r1", "brainpool512r1"), MBEDTLS_ECP_DP_BP512R1, }, -#endif /* MBEDTLS_ECP_DP_BP512R1_ENABLED */ +#endif /* MBEDTLS_ECP_HAVE_BP512R1 */ { - { NULL, 0, NULL, NULL }, + NULL_OID_DESCRIPTOR, MBEDTLS_ECP_DP_NONE, }, }; @@ -581,7 +621,48 @@ FN_OID_GET_OID_BY_ATTR1(mbedtls_oid_get_oid_by_ec_grp, oid_ecp_grp, mbedtls_ecp_group_id, grp_id) -#endif /* MBEDTLS_ECP_C */ + +/* + * For Elliptic Curve algorithms that are directly + * encoded in the AlgorithmIdentifier (RFC 8410) + */ +typedef struct { + mbedtls_oid_descriptor_t descriptor; + mbedtls_ecp_group_id grp_id; +} oid_ecp_grp_algid_t; + +static const oid_ecp_grp_algid_t oid_ecp_grp_algid[] = +{ +#if defined(MBEDTLS_ECP_HAVE_CURVE25519) + { + OID_DESCRIPTOR(MBEDTLS_OID_X25519, "X25519", "X25519"), + MBEDTLS_ECP_DP_CURVE25519, + }, +#endif /* MBEDTLS_ECP_HAVE_CURVE25519 */ +#if defined(MBEDTLS_ECP_HAVE_CURVE448) + { + OID_DESCRIPTOR(MBEDTLS_OID_X448, "X448", "X448"), + MBEDTLS_ECP_DP_CURVE448, + }, +#endif /* MBEDTLS_ECP_HAVE_CURVE448 */ + { + NULL_OID_DESCRIPTOR, + MBEDTLS_ECP_DP_NONE, + }, +}; + +FN_OID_TYPED_FROM_ASN1(oid_ecp_grp_algid_t, grp_id_algid, oid_ecp_grp_algid) +FN_OID_GET_ATTR1(mbedtls_oid_get_ec_grp_algid, + oid_ecp_grp_algid_t, + grp_id_algid, + mbedtls_ecp_group_id, + grp_id) +FN_OID_GET_OID_BY_ATTR1(mbedtls_oid_get_oid_by_ec_grp_algid, + oid_ecp_grp_algid_t, + oid_ecp_grp_algid, + mbedtls_ecp_group_id, + grp_id) +#endif /* MBEDTLS_PK_HAVE_ECC_KEYS */ #if defined(MBEDTLS_CIPHER_C) /* @@ -595,15 +676,27 @@ typedef struct { static const oid_cipher_alg_t oid_cipher_alg[] = { { - { ADD_LEN(MBEDTLS_OID_DES_CBC), "desCBC", "DES-CBC" }, + OID_DESCRIPTOR(MBEDTLS_OID_DES_CBC, "desCBC", "DES-CBC"), MBEDTLS_CIPHER_DES_CBC, }, { - { ADD_LEN(MBEDTLS_OID_DES_EDE3_CBC), "des-ede3-cbc", "DES-EDE3-CBC" }, + OID_DESCRIPTOR(MBEDTLS_OID_DES_EDE3_CBC, "des-ede3-cbc", "DES-EDE3-CBC"), MBEDTLS_CIPHER_DES_EDE3_CBC, }, { - { NULL, 0, NULL, NULL }, + OID_DESCRIPTOR(MBEDTLS_OID_AES_128_CBC, "aes128-cbc", "AES128-CBC"), + MBEDTLS_CIPHER_AES_128_CBC, + }, + { + OID_DESCRIPTOR(MBEDTLS_OID_AES_192_CBC, "aes192-cbc", "AES192-CBC"), + MBEDTLS_CIPHER_AES_192_CBC, + }, + { + OID_DESCRIPTOR(MBEDTLS_OID_AES_256_CBC, "aes256-cbc", "AES256-CBC"), + MBEDTLS_CIPHER_AES_256_CBC, + }, + { + NULL_OID_DESCRIPTOR, MBEDTLS_CIPHER_NONE, }, }; @@ -616,7 +709,6 @@ FN_OID_GET_ATTR1(mbedtls_oid_get_cipher_alg, cipher_alg) #endif /* MBEDTLS_CIPHER_C */ -#if defined(MBEDTLS_MD_C) /* * For digestAlgorithm */ @@ -627,58 +719,74 @@ typedef struct { static const oid_md_alg_t oid_md_alg[] = { -#if defined(MBEDTLS_MD2_C) - { - { ADD_LEN(MBEDTLS_OID_DIGEST_ALG_MD2), "id-md2", "MD2" }, - MBEDTLS_MD_MD2, - }, -#endif /* MBEDTLS_MD2_C */ -#if defined(MBEDTLS_MD4_C) +#if defined(MBEDTLS_MD_CAN_MD5) { - { ADD_LEN(MBEDTLS_OID_DIGEST_ALG_MD4), "id-md4", "MD4" }, - MBEDTLS_MD_MD4, - }, -#endif /* MBEDTLS_MD4_C */ -#if defined(MBEDTLS_MD5_C) - { - { ADD_LEN(MBEDTLS_OID_DIGEST_ALG_MD5), "id-md5", "MD5" }, + OID_DESCRIPTOR(MBEDTLS_OID_DIGEST_ALG_MD5, "id-md5", "MD5"), MBEDTLS_MD_MD5, }, -#endif /* MBEDTLS_MD5_C */ -#if defined(MBEDTLS_SHA1_C) +#endif +#if defined(MBEDTLS_MD_CAN_SHA1) { - { ADD_LEN(MBEDTLS_OID_DIGEST_ALG_SHA1), "id-sha1", "SHA-1" }, + OID_DESCRIPTOR(MBEDTLS_OID_DIGEST_ALG_SHA1, "id-sha1", "SHA-1"), MBEDTLS_MD_SHA1, }, -#endif /* MBEDTLS_SHA1_C */ -#if defined(MBEDTLS_SHA256_C) +#endif +#if defined(MBEDTLS_MD_CAN_SHA224) { - { ADD_LEN(MBEDTLS_OID_DIGEST_ALG_SHA224), "id-sha224", "SHA-224" }, + OID_DESCRIPTOR(MBEDTLS_OID_DIGEST_ALG_SHA224, "id-sha224", "SHA-224"), MBEDTLS_MD_SHA224, }, +#endif +#if defined(MBEDTLS_MD_CAN_SHA256) { - { ADD_LEN(MBEDTLS_OID_DIGEST_ALG_SHA256), "id-sha256", "SHA-256" }, + OID_DESCRIPTOR(MBEDTLS_OID_DIGEST_ALG_SHA256, "id-sha256", "SHA-256"), MBEDTLS_MD_SHA256, }, -#endif /* MBEDTLS_SHA256_C */ -#if defined(MBEDTLS_SHA512_C) +#endif +#if defined(MBEDTLS_MD_CAN_SHA384) { - { ADD_LEN(MBEDTLS_OID_DIGEST_ALG_SHA384), "id-sha384", "SHA-384" }, + OID_DESCRIPTOR(MBEDTLS_OID_DIGEST_ALG_SHA384, "id-sha384", "SHA-384"), MBEDTLS_MD_SHA384, }, +#endif +#if defined(MBEDTLS_MD_CAN_SHA512) { - { ADD_LEN(MBEDTLS_OID_DIGEST_ALG_SHA512), "id-sha512", "SHA-512" }, + OID_DESCRIPTOR(MBEDTLS_OID_DIGEST_ALG_SHA512, "id-sha512", "SHA-512"), MBEDTLS_MD_SHA512, }, -#endif /* MBEDTLS_SHA512_C */ -#if defined(MBEDTLS_RIPEMD160_C) +#endif +#if defined(MBEDTLS_MD_CAN_RIPEMD160) { - { ADD_LEN(MBEDTLS_OID_DIGEST_ALG_RIPEMD160), "id-ripemd160", "RIPEMD-160" }, + OID_DESCRIPTOR(MBEDTLS_OID_DIGEST_ALG_RIPEMD160, "id-ripemd160", "RIPEMD-160"), MBEDTLS_MD_RIPEMD160, }, -#endif /* MBEDTLS_RIPEMD160_C */ +#endif +#if defined(MBEDTLS_MD_CAN_SHA3_224) + { + OID_DESCRIPTOR(MBEDTLS_OID_DIGEST_ALG_SHA3_224, "id-sha3-224", "SHA-3-224"), + MBEDTLS_MD_SHA3_224, + }, +#endif +#if defined(MBEDTLS_MD_CAN_SHA3_256) + { + OID_DESCRIPTOR(MBEDTLS_OID_DIGEST_ALG_SHA3_256, "id-sha3-256", "SHA-3-256"), + MBEDTLS_MD_SHA3_256, + }, +#endif +#if defined(MBEDTLS_MD_CAN_SHA3_384) + { + OID_DESCRIPTOR(MBEDTLS_OID_DIGEST_ALG_SHA3_384, "id-sha3-384", "SHA-3-384"), + MBEDTLS_MD_SHA3_384, + }, +#endif +#if defined(MBEDTLS_MD_CAN_SHA3_512) { - { NULL, 0, NULL, NULL }, + OID_DESCRIPTOR(MBEDTLS_OID_DIGEST_ALG_SHA3_512, "id-sha3-512", "SHA-3-512"), + MBEDTLS_MD_SHA3_512, + }, +#endif + { + NULL_OID_DESCRIPTOR, MBEDTLS_MD_NONE, }, }; @@ -701,43 +809,76 @@ typedef struct { static const oid_md_hmac_t oid_md_hmac[] = { -#if defined(MBEDTLS_SHA1_C) +#if defined(MBEDTLS_MD_CAN_SHA1) { - { ADD_LEN(MBEDTLS_OID_HMAC_SHA1), "hmacSHA1", "HMAC-SHA-1" }, + OID_DESCRIPTOR(MBEDTLS_OID_HMAC_SHA1, "hmacSHA1", "HMAC-SHA-1"), MBEDTLS_MD_SHA1, }, -#endif /* MBEDTLS_SHA1_C */ -#if defined(MBEDTLS_SHA256_C) +#endif /* MBEDTLS_MD_CAN_SHA1 */ +#if defined(MBEDTLS_MD_CAN_SHA224) { - { ADD_LEN(MBEDTLS_OID_HMAC_SHA224), "hmacSHA224", "HMAC-SHA-224" }, + OID_DESCRIPTOR(MBEDTLS_OID_HMAC_SHA224, "hmacSHA224", "HMAC-SHA-224"), MBEDTLS_MD_SHA224, }, +#endif /* MBEDTLS_MD_CAN_SHA224 */ +#if defined(MBEDTLS_MD_CAN_SHA256) { - { ADD_LEN(MBEDTLS_OID_HMAC_SHA256), "hmacSHA256", "HMAC-SHA-256" }, + OID_DESCRIPTOR(MBEDTLS_OID_HMAC_SHA256, "hmacSHA256", "HMAC-SHA-256"), MBEDTLS_MD_SHA256, }, -#endif /* MBEDTLS_SHA256_C */ -#if defined(MBEDTLS_SHA512_C) +#endif /* MBEDTLS_MD_CAN_SHA256 */ +#if defined(MBEDTLS_MD_CAN_SHA384) { - { ADD_LEN(MBEDTLS_OID_HMAC_SHA384), "hmacSHA384", "HMAC-SHA-384" }, + OID_DESCRIPTOR(MBEDTLS_OID_HMAC_SHA384, "hmacSHA384", "HMAC-SHA-384"), MBEDTLS_MD_SHA384, }, +#endif /* MBEDTLS_MD_CAN_SHA384 */ +#if defined(MBEDTLS_MD_CAN_SHA512) { - { ADD_LEN(MBEDTLS_OID_HMAC_SHA512), "hmacSHA512", "HMAC-SHA-512" }, + OID_DESCRIPTOR(MBEDTLS_OID_HMAC_SHA512, "hmacSHA512", "HMAC-SHA-512"), MBEDTLS_MD_SHA512, }, -#endif /* MBEDTLS_SHA512_C */ +#endif /* MBEDTLS_MD_CAN_SHA512 */ +#if defined(MBEDTLS_MD_CAN_SHA3_224) + { + OID_DESCRIPTOR(MBEDTLS_OID_HMAC_SHA3_224, "hmacSHA3-224", "HMAC-SHA3-224"), + MBEDTLS_MD_SHA3_224, + }, +#endif /* MBEDTLS_MD_CAN_SHA3_224 */ +#if defined(MBEDTLS_MD_CAN_SHA3_256) + { + OID_DESCRIPTOR(MBEDTLS_OID_HMAC_SHA3_256, "hmacSHA3-256", "HMAC-SHA3-256"), + MBEDTLS_MD_SHA3_256, + }, +#endif /* MBEDTLS_MD_CAN_SHA3_256 */ +#if defined(MBEDTLS_MD_CAN_SHA3_384) + { + OID_DESCRIPTOR(MBEDTLS_OID_HMAC_SHA3_384, "hmacSHA3-384", "HMAC-SHA3-384"), + MBEDTLS_MD_SHA3_384, + }, +#endif /* MBEDTLS_MD_CAN_SHA3_384 */ +#if defined(MBEDTLS_MD_CAN_SHA3_512) + { + OID_DESCRIPTOR(MBEDTLS_OID_HMAC_SHA3_512, "hmacSHA3-512", "HMAC-SHA3-512"), + MBEDTLS_MD_SHA3_512, + }, +#endif /* MBEDTLS_MD_CAN_SHA3_512 */ +#if defined(MBEDTLS_MD_CAN_RIPEMD160) + { + OID_DESCRIPTOR(MBEDTLS_OID_HMAC_RIPEMD160, "hmacRIPEMD160", "HMAC-RIPEMD160"), + MBEDTLS_MD_RIPEMD160, + }, +#endif /* MBEDTLS_MD_CAN_RIPEMD160 */ { - { NULL, 0, NULL, NULL }, + NULL_OID_DESCRIPTOR, MBEDTLS_MD_NONE, }, }; FN_OID_TYPED_FROM_ASN1(oid_md_hmac_t, md_hmac, oid_md_hmac) FN_OID_GET_ATTR1(mbedtls_oid_get_md_hmac, oid_md_hmac_t, md_hmac, mbedtls_md_type_t, md_hmac) -#endif /* MBEDTLS_MD_C */ -#if defined(MBEDTLS_PKCS12_C) +#if defined(MBEDTLS_PKCS12_C) && defined(MBEDTLS_CIPHER_C) /* * For PKCS#12 PBEs */ @@ -750,17 +891,19 @@ typedef struct { static const oid_pkcs12_pbe_alg_t oid_pkcs12_pbe_alg[] = { { - { ADD_LEN(MBEDTLS_OID_PKCS12_PBE_SHA1_DES3_EDE_CBC), "pbeWithSHAAnd3-KeyTripleDES-CBC", - "PBE with SHA1 and 3-Key 3DES" }, + OID_DESCRIPTOR(MBEDTLS_OID_PKCS12_PBE_SHA1_DES3_EDE_CBC, + "pbeWithSHAAnd3-KeyTripleDES-CBC", + "PBE with SHA1 and 3-Key 3DES"), MBEDTLS_MD_SHA1, MBEDTLS_CIPHER_DES_EDE3_CBC, }, { - { ADD_LEN(MBEDTLS_OID_PKCS12_PBE_SHA1_DES2_EDE_CBC), "pbeWithSHAAnd2-KeyTripleDES-CBC", - "PBE with SHA1 and 2-Key 3DES" }, + OID_DESCRIPTOR(MBEDTLS_OID_PKCS12_PBE_SHA1_DES2_EDE_CBC, + "pbeWithSHAAnd2-KeyTripleDES-CBC", + "PBE with SHA1 and 2-Key 3DES"), MBEDTLS_MD_SHA1, MBEDTLS_CIPHER_DES_EDE_CBC, }, { - { NULL, 0, NULL, NULL }, + NULL_OID_DESCRIPTOR, MBEDTLS_MD_NONE, MBEDTLS_CIPHER_NONE, }, }; @@ -773,7 +916,7 @@ FN_OID_GET_ATTR2(mbedtls_oid_get_pkcs12_pbe_alg, md_alg, mbedtls_cipher_type_t, cipher_alg) -#endif /* MBEDTLS_PKCS12_C */ +#endif /* MBEDTLS_PKCS12_C && MBEDTLS_CIPHER_C */ /* Return the x.y.z.... style numeric string for the given OID */ int mbedtls_oid_get_numeric_string(char *buf, size_t size, @@ -844,4 +987,180 @@ int mbedtls_oid_get_numeric_string(char *buf, size_t size, return (int) (size - n); } +static int oid_parse_number(unsigned int *num, const char **p, const char *bound) +{ + int ret = MBEDTLS_ERR_ASN1_INVALID_DATA; + + *num = 0; + + while (*p < bound && **p >= '0' && **p <= '9') { + ret = 0; + if (*num > (UINT_MAX / 10)) { + return MBEDTLS_ERR_ASN1_INVALID_DATA; + } + *num *= 10; + *num += **p - '0'; + (*p)++; + } + return ret; +} + +static size_t oid_subidentifier_num_bytes(unsigned int value) +{ + size_t num_bytes = 0; + + do { + value >>= 7; + num_bytes++; + } while (value != 0); + + return num_bytes; +} + +static int oid_subidentifier_encode_into(unsigned char **p, + unsigned char *bound, + unsigned int value) +{ + size_t num_bytes = oid_subidentifier_num_bytes(value); + + if ((size_t) (bound - *p) < num_bytes) { + return MBEDTLS_ERR_OID_BUF_TOO_SMALL; + } + (*p)[num_bytes - 1] = (unsigned char) (value & 0x7f); + value >>= 7; + + for (size_t i = 2; i <= num_bytes; i++) { + (*p)[num_bytes - i] = 0x80 | (unsigned char) (value & 0x7f); + value >>= 7; + } + *p += num_bytes; + + return 0; +} + +/* Return the OID for the given x.y.z.... style numeric string */ +int mbedtls_oid_from_numeric_string(mbedtls_asn1_buf *oid, + const char *oid_str, size_t size) +{ + int ret = MBEDTLS_ERR_ASN1_INVALID_DATA; + const char *str_ptr = oid_str; + const char *str_bound = oid_str + size; + unsigned int val = 0; + unsigned int component1, component2; + size_t encoded_len; + unsigned char *resized_mem; + + /* Count the number of dots to get a worst-case allocation size. */ + size_t num_dots = 0; + for (size_t i = 0; i < size; i++) { + if (oid_str[i] == '.') { + num_dots++; + } + } + /* Allocate maximum possible required memory: + * There are (num_dots + 1) integer components, but the first 2 share the + * same subidentifier, so we only need num_dots subidentifiers maximum. */ + if (num_dots == 0 || (num_dots > MBEDTLS_OID_MAX_COMPONENTS - 1)) { + return MBEDTLS_ERR_ASN1_INVALID_DATA; + } + /* Each byte can store 7 bits, calculate number of bytes for a + * subidentifier: + * + * bytes = ceil(subidentifer_size * 8 / 7) + */ + size_t bytes_per_subidentifier = (((sizeof(unsigned int) * 8) - 1) / 7) + + 1; + size_t max_possible_bytes = num_dots * bytes_per_subidentifier; + oid->p = mbedtls_calloc(max_possible_bytes, 1); + if (oid->p == NULL) { + return MBEDTLS_ERR_ASN1_ALLOC_FAILED; + } + unsigned char *out_ptr = oid->p; + unsigned char *out_bound = oid->p + max_possible_bytes; + + ret = oid_parse_number(&component1, &str_ptr, str_bound); + if (ret != 0) { + goto error; + } + if (component1 > 2) { + /* First component can't be > 2 */ + ret = MBEDTLS_ERR_ASN1_INVALID_DATA; + goto error; + } + if (str_ptr >= str_bound || *str_ptr != '.') { + ret = MBEDTLS_ERR_ASN1_INVALID_DATA; + goto error; + } + str_ptr++; + + ret = oid_parse_number(&component2, &str_ptr, str_bound); + if (ret != 0) { + goto error; + } + if ((component1 < 2) && (component2 > 39)) { + /* Root nodes 0 and 1 may have up to 40 children, numbered 0-39 */ + ret = MBEDTLS_ERR_ASN1_INVALID_DATA; + goto error; + } + if (str_ptr < str_bound) { + if (*str_ptr == '.') { + str_ptr++; + } else { + ret = MBEDTLS_ERR_ASN1_INVALID_DATA; + goto error; + } + } + + if (component2 > (UINT_MAX - (component1 * 40))) { + ret = MBEDTLS_ERR_ASN1_INVALID_DATA; + goto error; + } + ret = oid_subidentifier_encode_into(&out_ptr, out_bound, + (component1 * 40) + component2); + if (ret != 0) { + goto error; + } + + while (str_ptr < str_bound) { + ret = oid_parse_number(&val, &str_ptr, str_bound); + if (ret != 0) { + goto error; + } + if (str_ptr < str_bound) { + if (*str_ptr == '.') { + str_ptr++; + } else { + ret = MBEDTLS_ERR_ASN1_INVALID_DATA; + goto error; + } + } + + ret = oid_subidentifier_encode_into(&out_ptr, out_bound, val); + if (ret != 0) { + goto error; + } + } + + encoded_len = (size_t) (out_ptr - oid->p); + resized_mem = mbedtls_calloc(encoded_len, 1); + if (resized_mem == NULL) { + ret = MBEDTLS_ERR_ASN1_ALLOC_FAILED; + goto error; + } + memcpy(resized_mem, oid->p, encoded_len); + mbedtls_free(oid->p); + oid->p = resized_mem; + oid->len = encoded_len; + + oid->tag = MBEDTLS_ASN1_OID; + + return 0; + +error: + mbedtls_free(oid->p); + oid->p = NULL; + oid->len = 0; + return ret; +} + #endif /* MBEDTLS_OID_C */ diff --git a/vendor/mbedtls/library/padlock.c b/vendor/mbedtls/library/padlock.c index c09d31f1ca..1f006910c2 100644 --- a/vendor/mbedtls/library/padlock.c +++ b/vendor/mbedtls/library/padlock.c @@ -2,19 +2,7 @@ * VIA PadLock support functions * * Copyright The Mbed TLS Contributors - * SPDX-License-Identifier: Apache-2.0 - * - * Licensed under the Apache License, Version 2.0 (the "License"); you may - * not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT - * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. + * SPDX-License-Identifier: Apache-2.0 OR GPL-2.0-or-later */ /* * This implementation is based on the VIA PadLock Programming Guide: @@ -27,16 +15,10 @@ #if defined(MBEDTLS_PADLOCK_C) -#include "mbedtls/padlock.h" +#include "padlock.h" #include -/* *INDENT-OFF* */ -#ifndef asm -#define asm __asm -#endif -/* *INDENT-ON* */ - #if defined(MBEDTLS_VIA_PADLOCK_HAVE_CODE) /* @@ -83,7 +65,12 @@ int mbedtls_padlock_xcryptecb(mbedtls_aes_context *ctx, uint32_t *ctrl; unsigned char buf[256]; - rk = ctx->rk; + rk = ctx->buf + ctx->rk_offset; + + if (((long) rk & 15) != 0) { + return MBEDTLS_ERR_PADLOCK_DATA_MISALIGNED; + } + blk = MBEDTLS_PADLOCK_ALIGN16(buf); memcpy(blk, input, 16); @@ -109,6 +96,7 @@ int mbedtls_padlock_xcryptecb(mbedtls_aes_context *ctx, return 0; } +#if defined(MBEDTLS_CIPHER_MODE_CBC) /* * PadLock AES-CBC buffer en(de)cryption */ @@ -126,12 +114,14 @@ int mbedtls_padlock_xcryptcbc(mbedtls_aes_context *ctx, uint32_t *ctrl; unsigned char buf[256]; + rk = ctx->buf + ctx->rk_offset; + if (((long) input & 15) != 0 || - ((long) output & 15) != 0) { + ((long) output & 15) != 0 || + ((long) rk & 15) != 0) { return MBEDTLS_ERR_PADLOCK_DATA_MISALIGNED; } - rk = ctx->rk; iw = MBEDTLS_PADLOCK_ALIGN16(buf); memcpy(iw, iv, 16); @@ -160,6 +150,7 @@ int mbedtls_padlock_xcryptcbc(mbedtls_aes_context *ctx, return 0; } +#endif /* MBEDTLS_CIPHER_MODE_CBC */ #endif /* MBEDTLS_VIA_PADLOCK_HAVE_CODE */ diff --git a/vendor/mbedtls/include/mbedtls/padlock.h b/vendor/mbedtls/library/padlock.h similarity index 72% rename from vendor/mbedtls/include/mbedtls/padlock.h rename to vendor/mbedtls/library/padlock.h index 076fd6069f..92d72af516 100644 --- a/vendor/mbedtls/include/mbedtls/padlock.h +++ b/vendor/mbedtls/library/padlock.h @@ -9,33 +9,16 @@ */ /* * Copyright The Mbed TLS Contributors - * SPDX-License-Identifier: Apache-2.0 - * - * Licensed under the Apache License, Version 2.0 (the "License"); you may - * not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT - * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. + * SPDX-License-Identifier: Apache-2.0 OR GPL-2.0-or-later */ #ifndef MBEDTLS_PADLOCK_H #define MBEDTLS_PADLOCK_H -#if !defined(MBEDTLS_CONFIG_FILE) -#include "mbedtls/config.h" -#else -#include MBEDTLS_CONFIG_FILE -#endif +#include "mbedtls/build_info.h" #include "mbedtls/aes.h" -/** Input data should be aligned. */ -#define MBEDTLS_ERR_PADLOCK_DATA_MISALIGNED -0x0030 +#define MBEDTLS_ERR_PADLOCK_DATA_MISALIGNED -0x0030 /**< Input data should be aligned. */ #if defined(__has_feature) #if __has_feature(address_sanitizer) @@ -43,17 +26,17 @@ #endif #endif -/* Some versions of ASan result in errors about not enough registers */ -#if defined(MBEDTLS_PADLOCK_C) && defined(MBEDTLS_HAVE_ASM) && \ - defined(__GNUC__) && defined(__i386__) && \ +/* + * - `padlock` is implements with GNUC assembly for x86 target. + * - Some versions of ASan result in errors about not enough registers. + */ +#if defined(MBEDTLS_PADLOCK_C) && \ + defined(__GNUC__) && defined(MBEDTLS_ARCH_IS_X86) && \ + defined(MBEDTLS_HAVE_ASM) && \ !defined(MBEDTLS_HAVE_ASAN) #define MBEDTLS_VIA_PADLOCK_HAVE_CODE -#ifndef MBEDTLS_HAVE_X86 -#define MBEDTLS_HAVE_X86 -#endif - #include #define MBEDTLS_PADLOCK_RNG 0x000C @@ -123,7 +106,6 @@ int mbedtls_padlock_xcryptcbc(mbedtls_aes_context *ctx, } #endif -#endif /* MBEDTLS_PADLOCK_C && MBEDTLS_HAVE_ASM && - __GNUC__ && __i386__ && !MBEDTLS_HAVE_ASAN */ +#endif /* HAVE_X86 */ #endif /* padlock.h */ diff --git a/vendor/mbedtls/library/pem.c b/vendor/mbedtls/library/pem.c index 3b9a3e91f2..0fee5df43a 100644 --- a/vendor/mbedtls/library/pem.c +++ b/vendor/mbedtls/library/pem.c @@ -2,19 +2,7 @@ * Privacy Enhanced Mail (PEM) decoding * * Copyright The Mbed TLS Contributors - * SPDX-License-Identifier: Apache-2.0 - * - * Licensed under the Apache License, Version 2.0 (the "License"); you may - * not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT - * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. + * SPDX-License-Identifier: Apache-2.0 OR GPL-2.0-or-later */ #include "common.h" @@ -25,7 +13,7 @@ #include "mbedtls/base64.h" #include "mbedtls/des.h" #include "mbedtls/aes.h" -#include "mbedtls/md5.h" +#include "mbedtls/md.h" #include "mbedtls/cipher.h" #include "mbedtls/platform_util.h" #include "mbedtls/error.h" @@ -34,14 +22,25 @@ #include "mbedtls/platform.h" +#if defined(MBEDTLS_USE_PSA_CRYPTO) +#include "psa/crypto.h" +#endif + +#if defined(MBEDTLS_MD_CAN_MD5) && \ + defined(MBEDTLS_CIPHER_MODE_CBC) && \ + (defined(MBEDTLS_DES_C) || defined(MBEDTLS_AES_C)) +#define PEM_RFC1421 +#endif /* MBEDTLS_MD_CAN_MD5 && + MBEDTLS_CIPHER_MODE_CBC && + ( MBEDTLS_AES_C || MBEDTLS_DES_C ) */ + #if defined(MBEDTLS_PEM_PARSE_C) void mbedtls_pem_init(mbedtls_pem_context *ctx) { memset(ctx, 0, sizeof(mbedtls_pem_context)); } -#if defined(MBEDTLS_MD5_C) && defined(MBEDTLS_CIPHER_MODE_CBC) && \ - (defined(MBEDTLS_DES_C) || defined(MBEDTLS_AES_C)) +#if defined(PEM_RFC1421) /* * Read a 16-byte hex string and convert it to binary */ @@ -77,26 +76,33 @@ static int pem_pbkdf1(unsigned char *key, size_t keylen, unsigned char *iv, const unsigned char *pwd, size_t pwdlen) { - mbedtls_md5_context md5_ctx; + mbedtls_md_context_t md5_ctx; + const mbedtls_md_info_t *md5_info; unsigned char md5sum[16]; size_t use_len; int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED; - mbedtls_md5_init(&md5_ctx); + mbedtls_md_init(&md5_ctx); + + /* Prepare the context. (setup() errors gracefully on NULL info.) */ + md5_info = mbedtls_md_info_from_type(MBEDTLS_MD_MD5); + if ((ret = mbedtls_md_setup(&md5_ctx, md5_info, 0)) != 0) { + goto exit; + } /* * key[ 0..15] = MD5(pwd || IV) */ - if ((ret = mbedtls_md5_starts_ret(&md5_ctx)) != 0) { + if ((ret = mbedtls_md_starts(&md5_ctx)) != 0) { goto exit; } - if ((ret = mbedtls_md5_update_ret(&md5_ctx, pwd, pwdlen)) != 0) { + if ((ret = mbedtls_md_update(&md5_ctx, pwd, pwdlen)) != 0) { goto exit; } - if ((ret = mbedtls_md5_update_ret(&md5_ctx, iv, 8)) != 0) { + if ((ret = mbedtls_md_update(&md5_ctx, iv, 8)) != 0) { goto exit; } - if ((ret = mbedtls_md5_finish_ret(&md5_ctx, md5sum)) != 0) { + if ((ret = mbedtls_md_finish(&md5_ctx, md5sum)) != 0) { goto exit; } @@ -110,19 +116,19 @@ static int pem_pbkdf1(unsigned char *key, size_t keylen, /* * key[16..23] = MD5(key[ 0..15] || pwd || IV]) */ - if ((ret = mbedtls_md5_starts_ret(&md5_ctx)) != 0) { + if ((ret = mbedtls_md_starts(&md5_ctx)) != 0) { goto exit; } - if ((ret = mbedtls_md5_update_ret(&md5_ctx, md5sum, 16)) != 0) { + if ((ret = mbedtls_md_update(&md5_ctx, md5sum, 16)) != 0) { goto exit; } - if ((ret = mbedtls_md5_update_ret(&md5_ctx, pwd, pwdlen)) != 0) { + if ((ret = mbedtls_md_update(&md5_ctx, pwd, pwdlen)) != 0) { goto exit; } - if ((ret = mbedtls_md5_update_ret(&md5_ctx, iv, 8)) != 0) { + if ((ret = mbedtls_md_update(&md5_ctx, iv, 8)) != 0) { goto exit; } - if ((ret = mbedtls_md5_finish_ret(&md5_ctx, md5sum)) != 0) { + if ((ret = mbedtls_md_finish(&md5_ctx, md5sum)) != 0) { goto exit; } @@ -134,7 +140,7 @@ static int pem_pbkdf1(unsigned char *key, size_t keylen, memcpy(key + 16, md5sum, use_len); exit: - mbedtls_md5_free(&md5_ctx); + mbedtls_md_free(&md5_ctx); mbedtls_platform_zeroize(md5sum, 16); return ret; @@ -234,8 +240,30 @@ static int pem_aes_decrypt(unsigned char aes_iv[16], unsigned int keylen, } #endif /* MBEDTLS_AES_C */ -#endif /* MBEDTLS_MD5_C && MBEDTLS_CIPHER_MODE_CBC && - ( MBEDTLS_AES_C || MBEDTLS_DES_C ) */ +#if defined(MBEDTLS_DES_C) || defined(MBEDTLS_AES_C) +static int pem_check_pkcs_padding(unsigned char *input, size_t input_len, size_t *data_len) +{ + /* input_len > 0 is guaranteed by mbedtls_pem_read_buffer(). */ + size_t pad_len = input[input_len - 1]; + size_t i; + + if (pad_len > input_len) { + return MBEDTLS_ERR_PEM_PASSWORD_MISMATCH; + } + + *data_len = input_len - pad_len; + + for (i = *data_len; i < input_len; i++) { + if (input[i] != pad_len) { + return MBEDTLS_ERR_PEM_PASSWORD_MISMATCH; + } + } + + return 0; +} +#endif /* MBEDTLS_DES_C || MBEDTLS_AES_C */ + +#endif /* PEM_RFC1421 */ int mbedtls_pem_read_buffer(mbedtls_pem_context *ctx, const char *header, const char *footer, const unsigned char *data, const unsigned char *pwd, @@ -245,15 +273,13 @@ int mbedtls_pem_read_buffer(mbedtls_pem_context *ctx, const char *header, const size_t len; unsigned char *buf; const unsigned char *s1, *s2, *end; -#if defined(MBEDTLS_MD5_C) && defined(MBEDTLS_CIPHER_MODE_CBC) && \ - (defined(MBEDTLS_DES_C) || defined(MBEDTLS_AES_C)) +#if defined(PEM_RFC1421) unsigned char pem_iv[16]; mbedtls_cipher_type_t enc_alg = MBEDTLS_CIPHER_NONE; #else ((void) pwd); ((void) pwdlen); -#endif /* MBEDTLS_MD5_C && MBEDTLS_CIPHER_MODE_CBC && - ( MBEDTLS_AES_C || MBEDTLS_DES_C ) */ +#endif /* PEM_RFC1421 */ if (ctx == NULL) { return MBEDTLS_ERR_PEM_BAD_INPUT_DATA; @@ -295,13 +321,12 @@ int mbedtls_pem_read_buffer(mbedtls_pem_context *ctx, const char *header, const if (*end == '\n') { end++; } - *use_len = end - data; + *use_len = (size_t) (end - data); enc = 0; if (s2 - s1 >= 22 && memcmp(s1, "Proc-Type: 4,ENCRYPTED", 22) == 0) { -#if defined(MBEDTLS_MD5_C) && defined(MBEDTLS_CIPHER_MODE_CBC) && \ - (defined(MBEDTLS_DES_C) || defined(MBEDTLS_AES_C)) +#if defined(PEM_RFC1421) enc++; s1 += 22; @@ -374,36 +399,36 @@ int mbedtls_pem_read_buffer(mbedtls_pem_context *ctx, const char *header, const } #else return MBEDTLS_ERR_PEM_FEATURE_UNAVAILABLE; -#endif /* MBEDTLS_MD5_C && MBEDTLS_CIPHER_MODE_CBC && - ( MBEDTLS_AES_C || MBEDTLS_DES_C ) */ +#endif /* PEM_RFC1421 */ } if (s1 >= s2) { return MBEDTLS_ERR_PEM_INVALID_DATA; } - ret = mbedtls_base64_decode(NULL, 0, &len, s1, s2 - s1); + ret = mbedtls_base64_decode(NULL, 0, &len, s1, (size_t) (s2 - s1)); if (ret == MBEDTLS_ERR_BASE64_INVALID_CHARACTER) { return MBEDTLS_ERROR_ADD(MBEDTLS_ERR_PEM_INVALID_DATA, ret); } + if (len == 0) { + return MBEDTLS_ERR_PEM_BAD_INPUT_DATA; + } + if ((buf = mbedtls_calloc(1, len)) == NULL) { return MBEDTLS_ERR_PEM_ALLOC_FAILED; } - if ((ret = mbedtls_base64_decode(buf, len, &len, s1, s2 - s1)) != 0) { - mbedtls_platform_zeroize(buf, len); - mbedtls_free(buf); + if ((ret = mbedtls_base64_decode(buf, len, &len, s1, (size_t) (s2 - s1))) != 0) { + mbedtls_zeroize_and_free(buf, len); return MBEDTLS_ERROR_ADD(MBEDTLS_ERR_PEM_INVALID_DATA, ret); } if (enc != 0) { -#if defined(MBEDTLS_MD5_C) && defined(MBEDTLS_CIPHER_MODE_CBC) && \ - (defined(MBEDTLS_DES_C) || defined(MBEDTLS_AES_C)) +#if defined(PEM_RFC1421) if (pwd == NULL) { - mbedtls_platform_zeroize(buf, len); - mbedtls_free(buf); + mbedtls_zeroize_and_free(buf, len); return MBEDTLS_ERR_PEM_PASSWORD_REQUIRED; } @@ -428,27 +453,24 @@ int mbedtls_pem_read_buffer(mbedtls_pem_context *ctx, const char *header, const #endif /* MBEDTLS_AES_C */ if (ret != 0) { - mbedtls_free(buf); + mbedtls_zeroize_and_free(buf, len); return ret; } - /* - * The result will be ASN.1 starting with a SEQUENCE tag, with 1 to 3 - * length bytes (allow 4 to be sure) in all known use cases. - * - * Use that as a heuristic to try to detect password mismatches. - */ - if (len <= 2 || buf[0] != 0x30 || buf[1] > 0x83) { - mbedtls_platform_zeroize(buf, len); - mbedtls_free(buf); - return MBEDTLS_ERR_PEM_PASSWORD_MISMATCH; + /* Check PKCS padding and update data length based on padding info. + * This can be used to detect invalid padding data and password + * mismatches. */ + size_t unpadded_len; + ret = pem_check_pkcs_padding(buf, len, &unpadded_len); + if (ret != 0) { + mbedtls_zeroize_and_free(buf, len); + return ret; } + len = unpadded_len; #else - mbedtls_platform_zeroize(buf, len); - mbedtls_free(buf); + mbedtls_zeroize_and_free(buf, len); return MBEDTLS_ERR_PEM_FEATURE_UNAVAILABLE; -#endif /* MBEDTLS_MD5_C && MBEDTLS_CIPHER_MODE_CBC && - ( MBEDTLS_AES_C || MBEDTLS_DES_C ) */ +#endif /* PEM_RFC1421 */ } ctx->buf = buf; @@ -460,8 +482,7 @@ int mbedtls_pem_read_buffer(mbedtls_pem_context *ctx, const char *header, const void mbedtls_pem_free(mbedtls_pem_context *ctx) { if (ctx->buf != NULL) { - mbedtls_platform_zeroize(ctx->buf, ctx->buflen); - mbedtls_free(ctx->buf); + mbedtls_zeroize_and_free(ctx->buf, ctx->buflen); } mbedtls_free(ctx->info); @@ -479,7 +500,7 @@ int mbedtls_pem_write_buffer(const char *header, const char *footer, size_t len = 0, use_len, add_len = 0; mbedtls_base64_encode(NULL, 0, &use_len, der_data, der_len); - add_len = strlen(header) + strlen(footer) + (use_len / 64) + 1; + add_len = strlen(header) + strlen(footer) + (((use_len > 2) ? (use_len - 2) : 0) / 64) + 1; if (use_len + add_len > buf_len) { *olen = use_len + add_len; @@ -514,7 +535,7 @@ int mbedtls_pem_write_buffer(const char *header, const char *footer, p += strlen(footer); *p++ = '\0'; - *olen = p - buf; + *olen = (size_t) (p - buf); /* Clean any remaining data previously written to the buffer */ memset(buf + *olen, 0, buf_len - *olen); diff --git a/vendor/mbedtls/library/pk.c b/vendor/mbedtls/library/pk.c index 12f4120225..097777f2c0 100644 --- a/vendor/mbedtls/library/pk.c +++ b/vendor/mbedtls/library/pk.c @@ -2,62 +2,59 @@ * Public Key abstraction layer * * Copyright The Mbed TLS Contributors - * SPDX-License-Identifier: Apache-2.0 - * - * Licensed under the Apache License, Version 2.0 (the "License"); you may - * not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT - * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. + * SPDX-License-Identifier: Apache-2.0 OR GPL-2.0-or-later */ #include "common.h" #if defined(MBEDTLS_PK_C) #include "mbedtls/pk.h" -#include "mbedtls/pk_internal.h" +#include "pk_wrap.h" +#include "pkwrite.h" +#include "pk_internal.h" #include "mbedtls/platform_util.h" #include "mbedtls/error.h" #if defined(MBEDTLS_RSA_C) #include "mbedtls/rsa.h" +#include "rsa_internal.h" #endif -#if defined(MBEDTLS_ECP_C) +#if defined(MBEDTLS_PK_HAVE_ECC_KEYS) #include "mbedtls/ecp.h" #endif #if defined(MBEDTLS_ECDSA_C) #include "mbedtls/ecdsa.h" #endif -#if defined(MBEDTLS_USE_PSA_CRYPTO) +#if defined(MBEDTLS_PSA_CRYPTO_CLIENT) +#include "psa_util_internal.h" #include "mbedtls/psa_util.h" #endif #include #include -/* Parameter validation macros based on platform_util.h */ -#define PK_VALIDATE_RET(cond) \ - MBEDTLS_INTERNAL_VALIDATE_RET(cond, MBEDTLS_ERR_PK_BAD_INPUT_DATA) -#define PK_VALIDATE(cond) \ - MBEDTLS_INTERNAL_VALIDATE(cond) +#define PSA_EXPORT_KEY_PAIR_OR_PUBLIC_MAX_SIZE \ + (PSA_EXPORT_KEY_PAIR_MAX_SIZE > PSA_EXPORT_PUBLIC_KEY_MAX_SIZE) ? \ + PSA_EXPORT_KEY_PAIR_MAX_SIZE : PSA_EXPORT_PUBLIC_KEY_MAX_SIZE /* * Initialise a mbedtls_pk_context */ void mbedtls_pk_init(mbedtls_pk_context *ctx) { - PK_VALIDATE(ctx != NULL); - ctx->pk_info = NULL; ctx->pk_ctx = NULL; +#if defined(MBEDTLS_USE_PSA_CRYPTO) + ctx->priv_id = MBEDTLS_SVC_KEY_ID_INIT; +#endif /* MBEDTLS_USE_PSA_CRYPTO */ +#if defined(MBEDTLS_PK_USE_PSA_EC_DATA) + memset(ctx->pub_raw, 0, sizeof(ctx->pub_raw)); + ctx->pub_raw_len = 0; + ctx->ec_family = 0; + ctx->ec_bits = 0; +#endif /* MBEDTLS_PK_USE_PSA_EC_DATA */ } /* @@ -69,10 +66,18 @@ void mbedtls_pk_free(mbedtls_pk_context *ctx) return; } - if (ctx->pk_info != NULL) { + if ((ctx->pk_info != NULL) && (ctx->pk_info->ctx_free_func != NULL)) { ctx->pk_info->ctx_free_func(ctx->pk_ctx); } +#if defined(MBEDTLS_PK_USE_PSA_EC_DATA) + /* The ownership of the priv_id key for opaque keys is external of the PK + * module. It's the user responsibility to clear it after use. */ + if ((ctx->pk_info != NULL) && (ctx->pk_info->type != MBEDTLS_PK_OPAQUE)) { + psa_destroy_key(ctx->priv_id); + } +#endif /* MBEDTLS_PK_USE_PSA_EC_DATA */ + mbedtls_platform_zeroize(ctx, sizeof(mbedtls_pk_context)); } @@ -82,7 +87,6 @@ void mbedtls_pk_free(mbedtls_pk_context *ctx) */ void mbedtls_pk_restart_init(mbedtls_pk_restart_ctx *ctx) { - PK_VALIDATE(ctx != NULL); ctx->pk_info = NULL; ctx->rs_ctx = NULL; } @@ -113,17 +117,17 @@ const mbedtls_pk_info_t *mbedtls_pk_info_from_type(mbedtls_pk_type_t pk_type) #if defined(MBEDTLS_RSA_C) case MBEDTLS_PK_RSA: return &mbedtls_rsa_info; -#endif -#if defined(MBEDTLS_ECP_C) +#endif /* MBEDTLS_RSA_C */ +#if defined(MBEDTLS_PK_HAVE_ECC_KEYS) case MBEDTLS_PK_ECKEY: return &mbedtls_eckey_info; case MBEDTLS_PK_ECKEY_DH: return &mbedtls_eckeydh_info; -#endif -#if defined(MBEDTLS_ECDSA_C) +#endif /* MBEDTLS_PK_HAVE_ECC_KEYS */ +#if defined(MBEDTLS_PK_CAN_ECDSA_SOME) case MBEDTLS_PK_ECDSA: return &mbedtls_ecdsa_info; -#endif +#endif /* MBEDTLS_PK_CAN_ECDSA_SOME */ /* MBEDTLS_PK_RSA_ALT omitted on purpose */ default: return NULL; @@ -135,12 +139,12 @@ const mbedtls_pk_info_t *mbedtls_pk_info_from_type(mbedtls_pk_type_t pk_type) */ int mbedtls_pk_setup(mbedtls_pk_context *ctx, const mbedtls_pk_info_t *info) { - PK_VALIDATE_RET(ctx != NULL); if (info == NULL || ctx->pk_info != NULL) { return MBEDTLS_ERR_PK_BAD_INPUT_DATA; } - if ((ctx->pk_ctx = info->ctx_alloc_func()) == NULL) { + if ((info->ctx_alloc_func != NULL) && + ((ctx->pk_ctx = info->ctx_alloc_func()) == NULL)) { return MBEDTLS_ERR_PK_ALLOC_FAILED; } @@ -154,11 +158,10 @@ int mbedtls_pk_setup(mbedtls_pk_context *ctx, const mbedtls_pk_info_t *info) * Initialise a PSA-wrapping context */ int mbedtls_pk_setup_opaque(mbedtls_pk_context *ctx, - const psa_key_id_t key) + const mbedtls_svc_key_id_t key) { - const mbedtls_pk_info_t * const info = &mbedtls_pk_opaque_info; + const mbedtls_pk_info_t *info = NULL; psa_key_attributes_t attributes = PSA_KEY_ATTRIBUTES_INIT; - psa_key_id_t *pk_ctx; psa_key_type_t type; if (ctx == NULL || ctx->pk_info != NULL) { @@ -171,19 +174,19 @@ int mbedtls_pk_setup_opaque(mbedtls_pk_context *ctx, type = psa_get_key_type(&attributes); psa_reset_key_attributes(&attributes); - /* Current implementation of can_do() relies on this. */ - if (!PSA_KEY_TYPE_IS_ECC_KEY_PAIR(type)) { +#if defined(MBEDTLS_PK_HAVE_ECC_KEYS) + if (PSA_KEY_TYPE_IS_ECC_KEY_PAIR(type)) { + info = &mbedtls_ecdsa_opaque_info; + } else +#endif /* MBEDTLS_PK_HAVE_ECC_KEYS */ + if (type == PSA_KEY_TYPE_RSA_KEY_PAIR) { + info = &mbedtls_rsa_opaque_info; + } else { return MBEDTLS_ERR_PK_FEATURE_UNAVAILABLE; } - if ((ctx->pk_ctx = info->ctx_alloc_func()) == NULL) { - return MBEDTLS_ERR_PK_ALLOC_FAILED; - } - ctx->pk_info = info; - - pk_ctx = (psa_key_id_t *) ctx->pk_ctx; - *pk_ctx = key; + ctx->priv_id = key; return 0; } @@ -201,7 +204,6 @@ int mbedtls_pk_setup_rsa_alt(mbedtls_pk_context *ctx, void *key, mbedtls_rsa_alt_context *rsa_alt; const mbedtls_pk_info_t *info = &mbedtls_rsa_alt_info; - PK_VALIDATE_RET(ctx != NULL); if (ctx->pk_info != NULL) { return MBEDTLS_ERR_PK_BAD_INPUT_DATA; } @@ -238,26 +240,772 @@ int mbedtls_pk_can_do(const mbedtls_pk_context *ctx, mbedtls_pk_type_t type) return ctx->pk_info->can_do(type); } +#if defined(MBEDTLS_USE_PSA_CRYPTO) /* - * Helper for mbedtls_pk_sign and mbedtls_pk_verify + * Tell if a PK can do the operations of the given PSA algorithm */ -static inline int pk_hashlen_helper(mbedtls_md_type_t md_alg, size_t *hash_len) +int mbedtls_pk_can_do_ext(const mbedtls_pk_context *ctx, psa_algorithm_t alg, + psa_key_usage_t usage) { - const mbedtls_md_info_t *md_info; + psa_key_usage_t key_usage; - if (*hash_len != 0 && md_alg == MBEDTLS_MD_NONE) { + /* A context with null pk_info is not set up yet and can't do anything. + * For backward compatibility, also accept NULL instead of a context + * pointer. */ + if (ctx == NULL || ctx->pk_info == NULL) { return 0; } - if ((md_info = mbedtls_md_info_from_type(md_alg)) == NULL) { - return -1; + /* Filter out non allowed algorithms */ + if (PSA_ALG_IS_ECDSA(alg) == 0 && + PSA_ALG_IS_RSA_PKCS1V15_SIGN(alg) == 0 && + PSA_ALG_IS_RSA_PSS(alg) == 0 && + alg != PSA_ALG_RSA_PKCS1V15_CRYPT && + PSA_ALG_IS_ECDH(alg) == 0) { + return 0; + } + + /* Filter out non allowed usage flags */ + if (usage == 0 || + (usage & ~(PSA_KEY_USAGE_SIGN_HASH | + PSA_KEY_USAGE_DECRYPT | + PSA_KEY_USAGE_DERIVE)) != 0) { + return 0; + } + + /* Wildcard hash is not allowed */ + if (PSA_ALG_IS_SIGN_HASH(alg) && + PSA_ALG_SIGN_GET_HASH(alg) == PSA_ALG_ANY_HASH) { + return 0; + } + + if (mbedtls_pk_get_type(ctx) != MBEDTLS_PK_OPAQUE) { + mbedtls_pk_type_t type; + + if (PSA_ALG_IS_ECDSA(alg) || PSA_ALG_IS_ECDH(alg)) { + type = MBEDTLS_PK_ECKEY; + } else if (PSA_ALG_IS_RSA_PKCS1V15_SIGN(alg) || + alg == PSA_ALG_RSA_PKCS1V15_CRYPT) { + type = MBEDTLS_PK_RSA; + } else if (PSA_ALG_IS_RSA_PSS(alg)) { + type = MBEDTLS_PK_RSASSA_PSS; + } else { + return 0; + } + + if (ctx->pk_info->can_do(type) == 0) { + return 0; + } + + switch (type) { + case MBEDTLS_PK_ECKEY: + key_usage = PSA_KEY_USAGE_SIGN_HASH | PSA_KEY_USAGE_DERIVE; + break; + case MBEDTLS_PK_RSA: + case MBEDTLS_PK_RSASSA_PSS: + key_usage = PSA_KEY_USAGE_SIGN_HASH | + PSA_KEY_USAGE_SIGN_MESSAGE | + PSA_KEY_USAGE_DECRYPT; + break; + default: + /* Should never happen */ + return 0; + } + + return (key_usage & usage) == usage; } - if (*hash_len != 0 && *hash_len != mbedtls_md_get_size(md_info)) { + psa_key_attributes_t attributes = PSA_KEY_ATTRIBUTES_INIT; + psa_status_t status; + + status = psa_get_key_attributes(ctx->priv_id, &attributes); + if (status != PSA_SUCCESS) { + return 0; + } + + psa_algorithm_t key_alg = psa_get_key_algorithm(&attributes); + /* Key's enrollment is available only when an Mbed TLS implementation of PSA + * Crypto is being used, i.e. when MBEDTLS_PSA_CRYPTO_C is defined. + * Even though we don't officially support using other implementations of PSA + * Crypto with TLS and X.509 (yet), we try to keep vendor's customizations + * separated. */ +#if defined(MBEDTLS_PSA_CRYPTO_C) + psa_algorithm_t key_alg2 = psa_get_key_enrollment_algorithm(&attributes); +#endif /* MBEDTLS_PSA_CRYPTO_C */ + key_usage = psa_get_key_usage_flags(&attributes); + psa_reset_key_attributes(&attributes); + + if ((key_usage & usage) != usage) { + return 0; + } + + /* + * Common case: the key alg [or alg2] only allows alg. + * This will match PSA_ALG_RSA_PKCS1V15_CRYPT & PSA_ALG_IS_ECDH + * directly. + * This would also match ECDSA/RSA_PKCS1V15_SIGN/RSA_PSS with + * a fixed hash on key_alg [or key_alg2]. + */ + if (alg == key_alg) { + return 1; + } +#if defined(MBEDTLS_PSA_CRYPTO_C) + if (alg == key_alg2) { + return 1; + } +#endif /* MBEDTLS_PSA_CRYPTO_C */ + + /* + * If key_alg [or key_alg2] is a hash-and-sign with a wildcard for the hash, + * and alg is the same hash-and-sign family with any hash, + * then alg is compliant with this key alg + */ + if (PSA_ALG_IS_SIGN_HASH(alg)) { + if (PSA_ALG_IS_SIGN_HASH(key_alg) && + PSA_ALG_SIGN_GET_HASH(key_alg) == PSA_ALG_ANY_HASH && + (alg & ~PSA_ALG_HASH_MASK) == (key_alg & ~PSA_ALG_HASH_MASK)) { + return 1; + } +#if defined(MBEDTLS_PSA_CRYPTO_C) + if (PSA_ALG_IS_SIGN_HASH(key_alg2) && + PSA_ALG_SIGN_GET_HASH(key_alg2) == PSA_ALG_ANY_HASH && + (alg & ~PSA_ALG_HASH_MASK) == (key_alg2 & ~PSA_ALG_HASH_MASK)) { + return 1; + } +#endif /* MBEDTLS_PSA_CRYPTO_C */ + } + + return 0; +} +#endif /* MBEDTLS_USE_PSA_CRYPTO */ + +#if defined(MBEDTLS_PSA_CRYPTO_CLIENT) +#if defined(MBEDTLS_RSA_C) +static psa_algorithm_t psa_algorithm_for_rsa(const mbedtls_rsa_context *rsa, + int want_crypt) +{ + if (mbedtls_rsa_get_padding_mode(rsa) == MBEDTLS_RSA_PKCS_V21) { + if (want_crypt) { + mbedtls_md_type_t md_type = (mbedtls_md_type_t) mbedtls_rsa_get_md_alg(rsa); + return PSA_ALG_RSA_OAEP(mbedtls_md_psa_alg_from_type(md_type)); + } else { + return PSA_ALG_RSA_PSS_ANY_SALT(PSA_ALG_ANY_HASH); + } + } else { + if (want_crypt) { + return PSA_ALG_RSA_PKCS1V15_CRYPT; + } else { + return PSA_ALG_RSA_PKCS1V15_SIGN(PSA_ALG_ANY_HASH); + } + } +} +#endif /* MBEDTLS_RSA_C */ + +int mbedtls_pk_get_psa_attributes(const mbedtls_pk_context *pk, + psa_key_usage_t usage, + psa_key_attributes_t *attributes) +{ + mbedtls_pk_type_t pk_type = mbedtls_pk_get_type(pk); + + psa_key_usage_t more_usage = usage; + if (usage == PSA_KEY_USAGE_SIGN_MESSAGE) { + more_usage |= PSA_KEY_USAGE_VERIFY_MESSAGE; + } else if (usage == PSA_KEY_USAGE_SIGN_HASH) { + more_usage |= PSA_KEY_USAGE_VERIFY_HASH; + } else if (usage == PSA_KEY_USAGE_DECRYPT) { + more_usage |= PSA_KEY_USAGE_ENCRYPT; + } + more_usage |= PSA_KEY_USAGE_EXPORT | PSA_KEY_USAGE_COPY; + + int want_private = !(usage == PSA_KEY_USAGE_VERIFY_MESSAGE || + usage == PSA_KEY_USAGE_VERIFY_HASH || + usage == PSA_KEY_USAGE_ENCRYPT); + + switch (pk_type) { +#if defined(MBEDTLS_RSA_C) + case MBEDTLS_PK_RSA: + { + int want_crypt = 0; /* 0: sign/verify; 1: encrypt/decrypt */ + switch (usage) { + case PSA_KEY_USAGE_SIGN_MESSAGE: + case PSA_KEY_USAGE_SIGN_HASH: + case PSA_KEY_USAGE_VERIFY_MESSAGE: + case PSA_KEY_USAGE_VERIFY_HASH: + /* Nothing to do. */ + break; + case PSA_KEY_USAGE_DECRYPT: + case PSA_KEY_USAGE_ENCRYPT: + want_crypt = 1; + break; + default: + return MBEDTLS_ERR_PK_TYPE_MISMATCH; + } + /* Detect the presence of a private key in a way that works both + * in CRT and non-CRT configurations. */ + mbedtls_rsa_context *rsa = mbedtls_pk_rsa(*pk); + int has_private = (mbedtls_rsa_check_privkey(rsa) == 0); + if (want_private && !has_private) { + return MBEDTLS_ERR_PK_TYPE_MISMATCH; + } + psa_set_key_type(attributes, (want_private ? + PSA_KEY_TYPE_RSA_KEY_PAIR : + PSA_KEY_TYPE_RSA_PUBLIC_KEY)); + psa_set_key_bits(attributes, mbedtls_pk_get_bitlen(pk)); + psa_set_key_algorithm(attributes, + psa_algorithm_for_rsa(rsa, want_crypt)); + break; + } +#endif /* MBEDTLS_RSA_C */ + +#if defined(MBEDTLS_PK_HAVE_ECC_KEYS) + case MBEDTLS_PK_ECKEY: + case MBEDTLS_PK_ECKEY_DH: + case MBEDTLS_PK_ECDSA: + { + int sign_ok = (pk_type != MBEDTLS_PK_ECKEY_DH); + int derive_ok = (pk_type != MBEDTLS_PK_ECDSA); +#if defined(MBEDTLS_PK_USE_PSA_EC_DATA) + psa_ecc_family_t family = pk->ec_family; + size_t bits = pk->ec_bits; + int has_private = 0; + if (pk->priv_id != MBEDTLS_SVC_KEY_ID_INIT) { + has_private = 1; + } +#else + const mbedtls_ecp_keypair *ec = mbedtls_pk_ec_ro(*pk); + int has_private = (ec->d.n != 0); + size_t bits = 0; + psa_ecc_family_t family = + mbedtls_ecc_group_to_psa(ec->grp.id, &bits); +#endif + psa_algorithm_t alg = 0; + switch (usage) { + case PSA_KEY_USAGE_SIGN_MESSAGE: + case PSA_KEY_USAGE_SIGN_HASH: + case PSA_KEY_USAGE_VERIFY_MESSAGE: + case PSA_KEY_USAGE_VERIFY_HASH: + if (!sign_ok) { + return MBEDTLS_ERR_PK_TYPE_MISMATCH; + } +#if defined(MBEDTLS_ECDSA_DETERMINISTIC) + alg = PSA_ALG_DETERMINISTIC_ECDSA(PSA_ALG_ANY_HASH); +#else + alg = PSA_ALG_ECDSA(PSA_ALG_ANY_HASH); +#endif + break; + case PSA_KEY_USAGE_DERIVE: + alg = PSA_ALG_ECDH; + if (!derive_ok) { + return MBEDTLS_ERR_PK_TYPE_MISMATCH; + } + break; + default: + return MBEDTLS_ERR_PK_TYPE_MISMATCH; + } + if (want_private && !has_private) { + return MBEDTLS_ERR_PK_TYPE_MISMATCH; + } + psa_set_key_type(attributes, (want_private ? + PSA_KEY_TYPE_ECC_KEY_PAIR(family) : + PSA_KEY_TYPE_ECC_PUBLIC_KEY(family))); + psa_set_key_bits(attributes, bits); + psa_set_key_algorithm(attributes, alg); + break; + } +#endif /* MBEDTLS_PK_HAVE_ECC_KEYS */ + +#if defined(MBEDTLS_PK_RSA_ALT_SUPPORT) + case MBEDTLS_PK_RSA_ALT: + return MBEDTLS_ERR_PK_FEATURE_UNAVAILABLE; +#endif /* MBEDTLS_PK_RSA_ALT_SUPPORT */ + +#if defined(MBEDTLS_USE_PSA_CRYPTO) + case MBEDTLS_PK_OPAQUE: + { + psa_key_attributes_t old_attributes = PSA_KEY_ATTRIBUTES_INIT; + psa_status_t status = PSA_ERROR_CORRUPTION_DETECTED; + status = psa_get_key_attributes(pk->priv_id, &old_attributes); + if (status != PSA_SUCCESS) { + return MBEDTLS_ERR_PK_BAD_INPUT_DATA; + } + psa_key_type_t old_type = psa_get_key_type(&old_attributes); + switch (usage) { + case PSA_KEY_USAGE_SIGN_MESSAGE: + case PSA_KEY_USAGE_SIGN_HASH: + case PSA_KEY_USAGE_VERIFY_MESSAGE: + case PSA_KEY_USAGE_VERIFY_HASH: + if (!(PSA_KEY_TYPE_IS_ECC_KEY_PAIR(old_type) || + old_type == PSA_KEY_TYPE_RSA_KEY_PAIR)) { + return MBEDTLS_ERR_PK_TYPE_MISMATCH; + } + break; + case PSA_KEY_USAGE_DECRYPT: + case PSA_KEY_USAGE_ENCRYPT: + if (old_type != PSA_KEY_TYPE_RSA_KEY_PAIR) { + return MBEDTLS_ERR_PK_TYPE_MISMATCH; + } + break; + case PSA_KEY_USAGE_DERIVE: + if (!(PSA_KEY_TYPE_IS_ECC_KEY_PAIR(old_type))) { + return MBEDTLS_ERR_PK_TYPE_MISMATCH; + } + break; + default: + return MBEDTLS_ERR_PK_TYPE_MISMATCH; + } + psa_key_type_t new_type = old_type; + /* Opaque keys are always key pairs, so we don't need a check + * on the input if the required usage is private. We just need + * to adjust the type correctly if the required usage is public. */ + if (!want_private) { + new_type = PSA_KEY_TYPE_PUBLIC_KEY_OF_KEY_PAIR(new_type); + } + more_usage = psa_get_key_usage_flags(&old_attributes); + if ((usage & more_usage) == 0) { + return MBEDTLS_ERR_PK_TYPE_MISMATCH; + } + psa_set_key_type(attributes, new_type); + psa_set_key_bits(attributes, psa_get_key_bits(&old_attributes)); + psa_set_key_algorithm(attributes, psa_get_key_algorithm(&old_attributes)); + break; + } +#endif /* MBEDTLS_USE_PSA_CRYPTO */ + + default: + return MBEDTLS_ERR_PK_BAD_INPUT_DATA; + } + + psa_set_key_usage_flags(attributes, more_usage); + /* Key's enrollment is available only when an Mbed TLS implementation of PSA + * Crypto is being used, i.e. when MBEDTLS_PSA_CRYPTO_C is defined. + * Even though we don't officially support using other implementations of PSA + * Crypto with TLS and X.509 (yet), we try to keep vendor's customizations + * separated. */ +#if defined(MBEDTLS_PSA_CRYPTO_C) + psa_set_key_enrollment_algorithm(attributes, PSA_ALG_NONE); +#endif + + return 0; +} + +#if defined(MBEDTLS_PK_USE_PSA_EC_DATA) || defined(MBEDTLS_USE_PSA_CRYPTO) +static psa_status_t export_import_into_psa(mbedtls_svc_key_id_t old_key_id, + const psa_key_attributes_t *attributes, + mbedtls_svc_key_id_t *new_key_id) +{ + unsigned char key_buffer[PSA_EXPORT_KEY_PAIR_MAX_SIZE]; + size_t key_length = 0; + psa_status_t status = psa_export_key(old_key_id, + key_buffer, sizeof(key_buffer), + &key_length); + if (status != PSA_SUCCESS) { + return status; + } + status = psa_import_key(attributes, key_buffer, key_length, new_key_id); + mbedtls_platform_zeroize(key_buffer, key_length); + return status; +} + +static int copy_into_psa(mbedtls_svc_key_id_t old_key_id, + const psa_key_attributes_t *attributes, + mbedtls_svc_key_id_t *new_key_id) +{ + /* Normally, we prefer copying: it's more efficient and works even + * for non-exportable keys. */ + psa_status_t status = psa_copy_key(old_key_id, attributes, new_key_id); + if (status == PSA_ERROR_NOT_PERMITTED /*missing COPY usage*/ || + status == PSA_ERROR_INVALID_ARGUMENT /*incompatible policy*/) { + /* There are edge cases where copying won't work, but export+import + * might: + * - If the old key does not allow PSA_KEY_USAGE_COPY. + * - If the old key's usage does not allow what attributes wants. + * Because the key was intended for use in the pk module, and may + * have had a policy chosen solely for what pk needs rather than + * based on a detailed understanding of PSA policies, we are a bit + * more liberal than psa_copy_key() here. + */ + /* Here we need to check that the types match, otherwise we risk + * importing nonsensical data. */ + psa_key_attributes_t old_attributes = PSA_KEY_ATTRIBUTES_INIT; + status = psa_get_key_attributes(old_key_id, &old_attributes); + if (status != PSA_SUCCESS) { + return MBEDTLS_ERR_PK_BAD_INPUT_DATA; + } + psa_key_type_t old_type = psa_get_key_type(&old_attributes); + psa_reset_key_attributes(&old_attributes); + if (old_type != psa_get_key_type(attributes)) { + return MBEDTLS_ERR_PK_TYPE_MISMATCH; + } + status = export_import_into_psa(old_key_id, attributes, new_key_id); + } + return PSA_PK_TO_MBEDTLS_ERR(status); +} +#endif /* MBEDTLS_PK_USE_PSA_EC_DATA || MBEDTLS_USE_PSA_CRYPTO */ + +static int import_pair_into_psa(const mbedtls_pk_context *pk, + const psa_key_attributes_t *attributes, + mbedtls_svc_key_id_t *key_id) +{ + switch (mbedtls_pk_get_type(pk)) { +#if defined(MBEDTLS_RSA_C) + case MBEDTLS_PK_RSA: + { + if (psa_get_key_type(attributes) != PSA_KEY_TYPE_RSA_KEY_PAIR) { + return MBEDTLS_ERR_PK_TYPE_MISMATCH; + } + unsigned char key_buffer[ + PSA_KEY_EXPORT_RSA_KEY_PAIR_MAX_SIZE(PSA_VENDOR_RSA_MAX_KEY_BITS)]; + unsigned char *const key_end = key_buffer + sizeof(key_buffer); + unsigned char *key_data = key_end; + int ret = mbedtls_rsa_write_key(mbedtls_pk_rsa(*pk), + key_buffer, &key_data); + if (ret < 0) { + return ret; + } + size_t key_length = key_end - key_data; + ret = PSA_PK_TO_MBEDTLS_ERR(psa_import_key(attributes, + key_data, key_length, + key_id)); + mbedtls_platform_zeroize(key_data, key_length); + return ret; + } +#endif /* MBEDTLS_RSA_C */ + +#if defined(MBEDTLS_PK_HAVE_ECC_KEYS) + case MBEDTLS_PK_ECKEY: + case MBEDTLS_PK_ECKEY_DH: + case MBEDTLS_PK_ECDSA: + { + /* We need to check the curve family, otherwise the import could + * succeed with nonsensical data. + * We don't check the bit-size: it's optional in attributes, + * and if it's specified, psa_import_key() will know from the key + * data length and will check that the bit-size matches. */ + psa_key_type_t to_type = psa_get_key_type(attributes); +#if defined(MBEDTLS_PK_USE_PSA_EC_DATA) + psa_ecc_family_t from_family = pk->ec_family; +#else /* MBEDTLS_PK_USE_PSA_EC_DATA */ + const mbedtls_ecp_keypair *ec = mbedtls_pk_ec_ro(*pk); + size_t from_bits = 0; + psa_ecc_family_t from_family = mbedtls_ecc_group_to_psa(ec->grp.id, + &from_bits); +#endif /* MBEDTLS_PK_USE_PSA_EC_DATA */ + if (to_type != PSA_KEY_TYPE_ECC_KEY_PAIR(from_family)) { + return MBEDTLS_ERR_PK_TYPE_MISMATCH; + } + +#if defined(MBEDTLS_PK_USE_PSA_EC_DATA) + if (mbedtls_svc_key_id_is_null(pk->priv_id)) { + /* We have a public key and want a key pair. */ + return MBEDTLS_ERR_PK_TYPE_MISMATCH; + } + return copy_into_psa(pk->priv_id, attributes, key_id); +#else /* MBEDTLS_PK_USE_PSA_EC_DATA */ + if (ec->d.n == 0) { + /* Private key not set. Assume the input is a public key only. + * (The other possibility is that it's an incomplete object + * where the group is set but neither the public key nor + * the private key. This is not possible through ecp.h + * functions, so we don't bother reporting a more suitable + * error in that case.) */ + return MBEDTLS_ERR_PK_TYPE_MISMATCH; + } + unsigned char key_buffer[PSA_BITS_TO_BYTES(PSA_VENDOR_ECC_MAX_CURVE_BITS)]; + size_t key_length = 0; + int ret = mbedtls_ecp_write_key_ext(ec, &key_length, + key_buffer, sizeof(key_buffer)); + if (ret < 0) { + return ret; + } + ret = PSA_PK_TO_MBEDTLS_ERR(psa_import_key(attributes, + key_buffer, key_length, + key_id)); + mbedtls_platform_zeroize(key_buffer, key_length); + return ret; +#endif /* MBEDTLS_PK_USE_PSA_EC_DATA */ + } +#endif /* MBEDTLS_PK_HAVE_ECC_KEYS */ + +#if defined(MBEDTLS_USE_PSA_CRYPTO) + case MBEDTLS_PK_OPAQUE: + return copy_into_psa(pk->priv_id, attributes, key_id); +#endif /* MBEDTLS_USE_PSA_CRYPTO */ + + default: + return MBEDTLS_ERR_PK_BAD_INPUT_DATA; + } +} + +static int import_public_into_psa(const mbedtls_pk_context *pk, + const psa_key_attributes_t *attributes, + mbedtls_svc_key_id_t *key_id) +{ + psa_key_type_t psa_type = psa_get_key_type(attributes); + +#if defined(MBEDTLS_RSA_C) || \ + (defined(MBEDTLS_PK_HAVE_ECC_KEYS) && !defined(MBEDTLS_PK_USE_PSA_EC_DATA)) || \ + defined(MBEDTLS_USE_PSA_CRYPTO) + unsigned char key_buffer[PSA_EXPORT_PUBLIC_KEY_MAX_SIZE]; +#endif + unsigned char *key_data = NULL; + size_t key_length = 0; + + switch (mbedtls_pk_get_type(pk)) { +#if defined(MBEDTLS_RSA_C) + case MBEDTLS_PK_RSA: + { + if (psa_type != PSA_KEY_TYPE_RSA_PUBLIC_KEY) { + return MBEDTLS_ERR_PK_TYPE_MISMATCH; + } + unsigned char *const key_end = key_buffer + sizeof(key_buffer); + key_data = key_end; + int ret = mbedtls_rsa_write_pubkey(mbedtls_pk_rsa(*pk), + key_buffer, &key_data); + if (ret < 0) { + return ret; + } + key_length = (size_t) ret; + break; + } +#endif /*MBEDTLS_RSA_C */ + +#if defined(MBEDTLS_PK_HAVE_ECC_KEYS) + case MBEDTLS_PK_ECKEY: + case MBEDTLS_PK_ECKEY_DH: + case MBEDTLS_PK_ECDSA: + { + /* We need to check the curve family, otherwise the import could + * succeed with nonsensical data. + * We don't check the bit-size: it's optional in attributes, + * and if it's specified, psa_import_key() will know from the key + * data length and will check that the bit-size matches. */ +#if defined(MBEDTLS_PK_USE_PSA_EC_DATA) + if (psa_type != PSA_KEY_TYPE_ECC_PUBLIC_KEY(pk->ec_family)) { + return MBEDTLS_ERR_PK_TYPE_MISMATCH; + } + key_data = (unsigned char *) pk->pub_raw; + key_length = pk->pub_raw_len; +#else /* MBEDTLS_PK_USE_PSA_EC_DATA */ + const mbedtls_ecp_keypair *ec = mbedtls_pk_ec_ro(*pk); + size_t from_bits = 0; + psa_ecc_family_t from_family = mbedtls_ecc_group_to_psa(ec->grp.id, + &from_bits); + if (psa_type != PSA_KEY_TYPE_ECC_PUBLIC_KEY(from_family)) { + return MBEDTLS_ERR_PK_TYPE_MISMATCH; + } + int ret = mbedtls_ecp_write_public_key( + ec, MBEDTLS_ECP_PF_UNCOMPRESSED, + &key_length, key_buffer, sizeof(key_buffer)); + if (ret < 0) { + return ret; + } + key_data = key_buffer; +#endif /* MBEDTLS_PK_USE_PSA_EC_DATA */ + break; + } +#endif /* MBEDTLS_PK_HAVE_ECC_KEYS */ + +#if defined(MBEDTLS_USE_PSA_CRYPTO) + case MBEDTLS_PK_OPAQUE: + { + psa_key_attributes_t old_attributes = PSA_KEY_ATTRIBUTES_INIT; + psa_status_t status = + psa_get_key_attributes(pk->priv_id, &old_attributes); + if (status != PSA_SUCCESS) { + return MBEDTLS_ERR_PK_BAD_INPUT_DATA; + } + psa_key_type_t old_type = psa_get_key_type(&old_attributes); + psa_reset_key_attributes(&old_attributes); + if (psa_type != PSA_KEY_TYPE_PUBLIC_KEY_OF_KEY_PAIR(old_type)) { + return MBEDTLS_ERR_PK_TYPE_MISMATCH; + } + status = psa_export_public_key(pk->priv_id, + key_buffer, sizeof(key_buffer), + &key_length); + if (status != PSA_SUCCESS) { + return PSA_PK_TO_MBEDTLS_ERR(status); + } + key_data = key_buffer; + break; + } +#endif /* MBEDTLS_USE_PSA_CRYPTO */ + + default: + return MBEDTLS_ERR_PK_BAD_INPUT_DATA; + } + + return PSA_PK_TO_MBEDTLS_ERR(psa_import_key(attributes, + key_data, key_length, + key_id)); +} + +int mbedtls_pk_import_into_psa(const mbedtls_pk_context *pk, + const psa_key_attributes_t *attributes, + mbedtls_svc_key_id_t *key_id) +{ + /* Set the output immediately so that it won't contain garbage even + * if we error out before calling psa_import_key(). */ + *key_id = MBEDTLS_SVC_KEY_ID_INIT; + +#if defined(MBEDTLS_PK_RSA_ALT_SUPPORT) + if (mbedtls_pk_get_type(pk) == MBEDTLS_PK_RSA_ALT) { + return MBEDTLS_ERR_PK_FEATURE_UNAVAILABLE; + } +#endif /* MBEDTLS_PK_RSA_ALT_SUPPORT */ + + int want_public = PSA_KEY_TYPE_IS_PUBLIC_KEY(psa_get_key_type(attributes)); + if (want_public) { + return import_public_into_psa(pk, attributes, key_id); + } else { + return import_pair_into_psa(pk, attributes, key_id); + } +} + +static int copy_from_psa(mbedtls_svc_key_id_t key_id, + mbedtls_pk_context *pk, + int public_only) +{ + psa_status_t status; + psa_key_attributes_t key_attr = PSA_KEY_ATTRIBUTES_INIT; + psa_key_type_t key_type; + psa_algorithm_t alg_type; + size_t key_bits; + /* Use a buffer size large enough to contain either a key pair or public key. */ + unsigned char exp_key[PSA_EXPORT_KEY_PAIR_OR_PUBLIC_MAX_SIZE]; + size_t exp_key_len; + int ret = MBEDTLS_ERR_PK_BAD_INPUT_DATA; + + if (pk == NULL) { + return MBEDTLS_ERR_PK_BAD_INPUT_DATA; + } + + status = psa_get_key_attributes(key_id, &key_attr); + if (status != PSA_SUCCESS) { + return MBEDTLS_ERR_PK_BAD_INPUT_DATA; + } + + if (public_only) { + status = psa_export_public_key(key_id, exp_key, sizeof(exp_key), &exp_key_len); + } else { + status = psa_export_key(key_id, exp_key, sizeof(exp_key), &exp_key_len); + } + if (status != PSA_SUCCESS) { + ret = PSA_PK_TO_MBEDTLS_ERR(status); + goto exit; + } + + key_type = psa_get_key_type(&key_attr); + if (public_only) { + key_type = PSA_KEY_TYPE_PUBLIC_KEY_OF_KEY_PAIR(key_type); + } + key_bits = psa_get_key_bits(&key_attr); + alg_type = psa_get_key_algorithm(&key_attr); + +#if defined(MBEDTLS_RSA_C) + if ((key_type == PSA_KEY_TYPE_RSA_KEY_PAIR) || + (key_type == PSA_KEY_TYPE_RSA_PUBLIC_KEY)) { + + ret = mbedtls_pk_setup(pk, mbedtls_pk_info_from_type(MBEDTLS_PK_RSA)); + if (ret != 0) { + goto exit; + } + + if (key_type == PSA_KEY_TYPE_RSA_KEY_PAIR) { + ret = mbedtls_rsa_parse_key(mbedtls_pk_rsa(*pk), exp_key, exp_key_len); + } else { + ret = mbedtls_rsa_parse_pubkey(mbedtls_pk_rsa(*pk), exp_key, exp_key_len); + } + if (ret != 0) { + goto exit; + } + + mbedtls_md_type_t md_type = MBEDTLS_MD_NONE; + if (PSA_ALG_GET_HASH(alg_type) != PSA_ALG_ANY_HASH) { + md_type = mbedtls_md_type_from_psa_alg(alg_type); + } + + if (PSA_ALG_IS_RSA_OAEP(alg_type) || PSA_ALG_IS_RSA_PSS(alg_type)) { + ret = mbedtls_rsa_set_padding(mbedtls_pk_rsa(*pk), MBEDTLS_RSA_PKCS_V21, md_type); + } else if (PSA_ALG_IS_RSA_PKCS1V15_SIGN(alg_type) || + alg_type == PSA_ALG_RSA_PKCS1V15_CRYPT) { + ret = mbedtls_rsa_set_padding(mbedtls_pk_rsa(*pk), MBEDTLS_RSA_PKCS_V15, md_type); + } + if (ret != 0) { + goto exit; + } + } else +#endif /* MBEDTLS_RSA_C */ +#if defined(MBEDTLS_PK_HAVE_ECC_KEYS) + if (PSA_KEY_TYPE_IS_ECC_KEY_PAIR(key_type) || + PSA_KEY_TYPE_IS_ECC_PUBLIC_KEY(key_type)) { + mbedtls_ecp_group_id grp_id; + + ret = mbedtls_pk_setup(pk, mbedtls_pk_info_from_type(MBEDTLS_PK_ECKEY)); + if (ret != 0) { + goto exit; + } + + grp_id = mbedtls_ecc_group_from_psa(PSA_KEY_TYPE_ECC_GET_FAMILY(key_type), key_bits); + ret = mbedtls_pk_ecc_set_group(pk, grp_id); + if (ret != 0) { + goto exit; + } + + if (PSA_KEY_TYPE_IS_ECC_KEY_PAIR(key_type)) { + ret = mbedtls_pk_ecc_set_key(pk, exp_key, exp_key_len); + if (ret != 0) { + goto exit; + } + ret = mbedtls_pk_ecc_set_pubkey_from_prv(pk, exp_key, exp_key_len, + mbedtls_psa_get_random, + MBEDTLS_PSA_RANDOM_STATE); + } else { + ret = mbedtls_pk_ecc_set_pubkey(pk, exp_key, exp_key_len); + } + if (ret != 0) { + goto exit; + } + } else +#endif /* MBEDTLS_PK_HAVE_ECC_KEYS */ + { + return MBEDTLS_ERR_PK_BAD_INPUT_DATA; + } + +exit: + psa_reset_key_attributes(&key_attr); + mbedtls_platform_zeroize(exp_key, sizeof(exp_key)); + + return ret; +} + +int mbedtls_pk_copy_from_psa(mbedtls_svc_key_id_t key_id, + mbedtls_pk_context *pk) +{ + return copy_from_psa(key_id, pk, 0); +} + +int mbedtls_pk_copy_public_from_psa(mbedtls_svc_key_id_t key_id, + mbedtls_pk_context *pk) +{ + return copy_from_psa(key_id, pk, 1); +} +#endif /* MBEDTLS_PSA_CRYPTO_CLIENT */ + +/* + * Helper for mbedtls_pk_sign and mbedtls_pk_verify + */ +static inline int pk_hashlen_helper(mbedtls_md_type_t md_alg, size_t *hash_len) +{ + if (*hash_len != 0) { + return 0; + } + + *hash_len = mbedtls_md_get_size_from_type(md_alg); + + if (*hash_len == 0) { return -1; } - *hash_len = mbedtls_md_get_size(md_info); return 0; } @@ -297,10 +1045,9 @@ int mbedtls_pk_verify_restartable(mbedtls_pk_context *ctx, const unsigned char *sig, size_t sig_len, mbedtls_pk_restart_ctx *rs_ctx) { - PK_VALIDATE_RET(ctx != NULL); - PK_VALIDATE_RET((md_alg == MBEDTLS_MD_NONE && hash_len == 0) || - hash != NULL); - PK_VALIDATE_RET(sig != NULL); + if ((md_alg != MBEDTLS_MD_NONE || hash_len != 0) && hash == NULL) { + return MBEDTLS_ERR_PK_BAD_INPUT_DATA; + } if (ctx->pk_info == NULL || pk_hashlen_helper(md_alg, &hash_len) != 0) { @@ -318,7 +1065,7 @@ int mbedtls_pk_verify_restartable(mbedtls_pk_context *ctx, return ret; } - ret = ctx->pk_info->verify_rs_func(ctx->pk_ctx, + ret = ctx->pk_info->verify_rs_func(ctx, md_alg, hash, hash_len, sig, sig_len, rs_ctx->rs_ctx); if (ret != MBEDTLS_ERR_ECP_IN_PROGRESS) { @@ -335,7 +1082,7 @@ int mbedtls_pk_verify_restartable(mbedtls_pk_context *ctx, return MBEDTLS_ERR_PK_TYPE_MISMATCH; } - return ctx->pk_info->verify_func(ctx->pk_ctx, md_alg, hash, hash_len, + return ctx->pk_info->verify_func(ctx, md_alg, hash, hash_len, sig, sig_len); } @@ -358,10 +1105,9 @@ int mbedtls_pk_verify_ext(mbedtls_pk_type_t type, const void *options, const unsigned char *hash, size_t hash_len, const unsigned char *sig, size_t sig_len) { - PK_VALIDATE_RET(ctx != NULL); - PK_VALIDATE_RET((md_alg == MBEDTLS_MD_NONE && hash_len == 0) || - hash != NULL); - PK_VALIDATE_RET(sig != NULL); + if ((md_alg != MBEDTLS_MD_NONE || hash_len != 0) && hash == NULL) { + return MBEDTLS_ERR_PK_BAD_INPUT_DATA; + } if (ctx->pk_info == NULL) { return MBEDTLS_ERR_PK_BAD_INPUT_DATA; @@ -371,29 +1117,97 @@ int mbedtls_pk_verify_ext(mbedtls_pk_type_t type, const void *options, return MBEDTLS_ERR_PK_TYPE_MISMATCH; } - if (type == MBEDTLS_PK_RSASSA_PSS) { + if (type != MBEDTLS_PK_RSASSA_PSS) { + /* General case: no options */ + if (options != NULL) { + return MBEDTLS_ERR_PK_BAD_INPUT_DATA; + } + + return mbedtls_pk_verify(ctx, md_alg, hash, hash_len, sig, sig_len); + } + + /* Ensure the PK context is of the right type otherwise mbedtls_pk_rsa() + * below would return a NULL pointer. */ + if (mbedtls_pk_get_type(ctx) != MBEDTLS_PK_RSA) { + return MBEDTLS_ERR_PK_FEATURE_UNAVAILABLE; + } + #if defined(MBEDTLS_RSA_C) && defined(MBEDTLS_PKCS1_V21) - int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED; - const mbedtls_pk_rsassa_pss_options *pss_opts; + int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED; + const mbedtls_pk_rsassa_pss_options *pss_opts; #if SIZE_MAX > UINT_MAX - if (md_alg == MBEDTLS_MD_NONE && UINT_MAX < hash_len) { - return MBEDTLS_ERR_PK_BAD_INPUT_DATA; + if (md_alg == MBEDTLS_MD_NONE && UINT_MAX < hash_len) { + return MBEDTLS_ERR_PK_BAD_INPUT_DATA; + } +#endif + + if (options == NULL) { + return MBEDTLS_ERR_PK_BAD_INPUT_DATA; + } + + pss_opts = (const mbedtls_pk_rsassa_pss_options *) options; + +#if defined(MBEDTLS_USE_PSA_CRYPTO) + if (pss_opts->mgf1_hash_id == md_alg) { + unsigned char buf[MBEDTLS_PK_RSA_PUB_DER_MAX_BYTES]; + unsigned char *p; + int key_len; + size_t signature_length; + psa_status_t status = PSA_ERROR_DATA_CORRUPT; + psa_status_t destruction_status = PSA_ERROR_DATA_CORRUPT; + + psa_algorithm_t psa_md_alg = mbedtls_md_psa_alg_from_type(md_alg); + mbedtls_svc_key_id_t key_id = MBEDTLS_SVC_KEY_ID_INIT; + psa_key_attributes_t attributes = PSA_KEY_ATTRIBUTES_INIT; + psa_algorithm_t psa_sig_alg = PSA_ALG_RSA_PSS_ANY_SALT(psa_md_alg); + p = buf + sizeof(buf); + key_len = mbedtls_rsa_write_pubkey(mbedtls_pk_rsa(*ctx), buf, &p); + + if (key_len < 0) { + return key_len; } -#endif /* SIZE_MAX > UINT_MAX */ - if (options == NULL) { - return MBEDTLS_ERR_PK_BAD_INPUT_DATA; + psa_set_key_type(&attributes, PSA_KEY_TYPE_RSA_PUBLIC_KEY); + psa_set_key_usage_flags(&attributes, PSA_KEY_USAGE_VERIFY_HASH); + psa_set_key_algorithm(&attributes, psa_sig_alg); + + status = psa_import_key(&attributes, + buf + sizeof(buf) - key_len, key_len, + &key_id); + if (status != PSA_SUCCESS) { + psa_destroy_key(key_id); + return PSA_PK_TO_MBEDTLS_ERR(status); } - pss_opts = (const mbedtls_pk_rsassa_pss_options *) options; + /* This function requires returning MBEDTLS_ERR_PK_SIG_LEN_MISMATCH + * on a valid signature with trailing data in a buffer, but + * mbedtls_psa_rsa_verify_hash requires the sig_len to be exact, + * so for this reason the passed sig_len is overwritten. Smaller + * signature lengths should not be accepted for verification. */ + signature_length = sig_len > mbedtls_pk_get_len(ctx) ? + mbedtls_pk_get_len(ctx) : sig_len; + status = psa_verify_hash(key_id, psa_sig_alg, hash, + hash_len, sig, signature_length); + destruction_status = psa_destroy_key(key_id); + + if (status == PSA_SUCCESS && sig_len > mbedtls_pk_get_len(ctx)) { + return MBEDTLS_ERR_PK_SIG_LEN_MISMATCH; + } + + if (status == PSA_SUCCESS) { + status = destruction_status; + } + return PSA_PK_RSA_TO_MBEDTLS_ERR(status); + } else +#endif /* MBEDTLS_USE_PSA_CRYPTO */ + { if (sig_len < mbedtls_pk_get_len(ctx)) { return MBEDTLS_ERR_RSA_VERIFY_FAILED; } ret = mbedtls_rsa_rsassa_pss_verify_ext(mbedtls_pk_rsa(*ctx), - NULL, NULL, MBEDTLS_RSA_PUBLIC, md_alg, (unsigned int) hash_len, hash, pss_opts->mgf1_hash_id, pss_opts->expected_salt_len, @@ -407,17 +1221,10 @@ int mbedtls_pk_verify_ext(mbedtls_pk_type_t type, const void *options, } return 0; + } #else - return MBEDTLS_ERR_PK_FEATURE_UNAVAILABLE; + return MBEDTLS_ERR_PK_FEATURE_UNAVAILABLE; #endif /* MBEDTLS_RSA_C && MBEDTLS_PKCS1_V21 */ - } - - /* General case: no options */ - if (options != NULL) { - return MBEDTLS_ERR_PK_BAD_INPUT_DATA; - } - - return mbedtls_pk_verify(ctx, md_alg, hash, hash_len, sig, sig_len); } /* @@ -426,17 +1233,15 @@ int mbedtls_pk_verify_ext(mbedtls_pk_type_t type, const void *options, int mbedtls_pk_sign_restartable(mbedtls_pk_context *ctx, mbedtls_md_type_t md_alg, const unsigned char *hash, size_t hash_len, - unsigned char *sig, size_t *sig_len, + unsigned char *sig, size_t sig_size, size_t *sig_len, int (*f_rng)(void *, unsigned char *, size_t), void *p_rng, mbedtls_pk_restart_ctx *rs_ctx) { - PK_VALIDATE_RET(ctx != NULL); - PK_VALIDATE_RET((md_alg == MBEDTLS_MD_NONE && hash_len == 0) || - hash != NULL); - PK_VALIDATE_RET(sig != NULL); + if ((md_alg != MBEDTLS_MD_NONE || hash_len != 0) && hash == NULL) { + return MBEDTLS_ERR_PK_BAD_INPUT_DATA; + } - if (ctx->pk_info == NULL || - pk_hashlen_helper(md_alg, &hash_len) != 0) { + if (ctx->pk_info == NULL || pk_hashlen_helper(md_alg, &hash_len) != 0) { return MBEDTLS_ERR_PK_BAD_INPUT_DATA; } @@ -451,9 +1256,10 @@ int mbedtls_pk_sign_restartable(mbedtls_pk_context *ctx, return ret; } - ret = ctx->pk_info->sign_rs_func(ctx->pk_ctx, md_alg, - hash, hash_len, sig, sig_len, f_rng, p_rng, - rs_ctx->rs_ctx); + ret = ctx->pk_info->sign_rs_func(ctx, md_alg, + hash, hash_len, + sig, sig_size, sig_len, + f_rng, p_rng, rs_ctx->rs_ctx); if (ret != MBEDTLS_ERR_ECP_IN_PROGRESS) { mbedtls_pk_restart_free(rs_ctx); @@ -469,8 +1275,10 @@ int mbedtls_pk_sign_restartable(mbedtls_pk_context *ctx, return MBEDTLS_ERR_PK_TYPE_MISMATCH; } - return ctx->pk_info->sign_func(ctx->pk_ctx, md_alg, hash, hash_len, - sig, sig_len, f_rng, p_rng); + return ctx->pk_info->sign_func(ctx, md_alg, + hash, hash_len, + sig, sig_size, sig_len, + f_rng, p_rng); } /* @@ -478,11 +1286,114 @@ int mbedtls_pk_sign_restartable(mbedtls_pk_context *ctx, */ int mbedtls_pk_sign(mbedtls_pk_context *ctx, mbedtls_md_type_t md_alg, const unsigned char *hash, size_t hash_len, - unsigned char *sig, size_t *sig_len, + unsigned char *sig, size_t sig_size, size_t *sig_len, int (*f_rng)(void *, unsigned char *, size_t), void *p_rng) { return mbedtls_pk_sign_restartable(ctx, md_alg, hash, hash_len, - sig, sig_len, f_rng, p_rng, NULL); + sig, sig_size, sig_len, + f_rng, p_rng, NULL); +} + +/* + * Make a signature given a signature type. + */ +int mbedtls_pk_sign_ext(mbedtls_pk_type_t pk_type, + mbedtls_pk_context *ctx, + mbedtls_md_type_t md_alg, + const unsigned char *hash, size_t hash_len, + unsigned char *sig, size_t sig_size, size_t *sig_len, + int (*f_rng)(void *, unsigned char *, size_t), + void *p_rng) +{ + if (ctx->pk_info == NULL) { + return MBEDTLS_ERR_PK_BAD_INPUT_DATA; + } + + if (!mbedtls_pk_can_do(ctx, pk_type)) { + return MBEDTLS_ERR_PK_TYPE_MISMATCH; + } + + if (pk_type != MBEDTLS_PK_RSASSA_PSS) { + return mbedtls_pk_sign(ctx, md_alg, hash, hash_len, + sig, sig_size, sig_len, f_rng, p_rng); + } + +#if defined(MBEDTLS_RSA_C) && defined(MBEDTLS_PKCS1_V21) + +#if defined(MBEDTLS_USE_PSA_CRYPTO) + const psa_algorithm_t psa_md_alg = mbedtls_md_psa_alg_from_type(md_alg); + if (psa_md_alg == 0) { + return MBEDTLS_ERR_PK_BAD_INPUT_DATA; + } + + if (mbedtls_pk_get_type(ctx) == MBEDTLS_PK_OPAQUE) { + psa_key_attributes_t key_attr = PSA_KEY_ATTRIBUTES_INIT; + psa_algorithm_t psa_alg, sign_alg; +#if defined(MBEDTLS_PSA_CRYPTO_C) + psa_algorithm_t psa_enrollment_alg; +#endif /* MBEDTLS_PSA_CRYPTO_C */ + psa_status_t status; + + status = psa_get_key_attributes(ctx->priv_id, &key_attr); + if (status != PSA_SUCCESS) { + return PSA_PK_RSA_TO_MBEDTLS_ERR(status); + } + psa_alg = psa_get_key_algorithm(&key_attr); +#if defined(MBEDTLS_PSA_CRYPTO_C) + psa_enrollment_alg = psa_get_key_enrollment_algorithm(&key_attr); +#endif /* MBEDTLS_PSA_CRYPTO_C */ + psa_reset_key_attributes(&key_attr); + + /* Since we're PK type is MBEDTLS_PK_RSASSA_PSS at least one between + * alg and enrollment alg should be of type RSA_PSS. */ + if (PSA_ALG_IS_RSA_PSS(psa_alg)) { + sign_alg = psa_alg; + } +#if defined(MBEDTLS_PSA_CRYPTO_C) + else if (PSA_ALG_IS_RSA_PSS(psa_enrollment_alg)) { + sign_alg = psa_enrollment_alg; + } +#endif /* MBEDTLS_PSA_CRYPTO_C */ + else { + /* The opaque key has no RSA PSS algorithm associated. */ + return MBEDTLS_ERR_PK_BAD_INPUT_DATA; + } + /* Adjust the hashing algorithm. */ + sign_alg = (sign_alg & ~PSA_ALG_HASH_MASK) | PSA_ALG_GET_HASH(psa_md_alg); + + status = psa_sign_hash(ctx->priv_id, sign_alg, + hash, hash_len, + sig, sig_size, sig_len); + return PSA_PK_RSA_TO_MBEDTLS_ERR(status); + } + + return mbedtls_pk_psa_rsa_sign_ext(PSA_ALG_RSA_PSS(psa_md_alg), + ctx->pk_ctx, hash, hash_len, + sig, sig_size, sig_len); +#else /* MBEDTLS_USE_PSA_CRYPTO */ + + if (sig_size < mbedtls_pk_get_len(ctx)) { + return MBEDTLS_ERR_PK_BUFFER_TOO_SMALL; + } + + if (pk_hashlen_helper(md_alg, &hash_len) != 0) { + return MBEDTLS_ERR_PK_BAD_INPUT_DATA; + } + + mbedtls_rsa_context *const rsa_ctx = mbedtls_pk_rsa(*ctx); + + const int ret = mbedtls_rsa_rsassa_pss_sign_no_mode_check(rsa_ctx, f_rng, p_rng, md_alg, + (unsigned int) hash_len, hash, sig); + if (ret == 0) { + *sig_len = rsa_ctx->len; + } + return ret; + +#endif /* MBEDTLS_USE_PSA_CRYPTO */ + +#else + return MBEDTLS_ERR_PK_FEATURE_UNAVAILABLE; +#endif /* MBEDTLS_RSA_C && MBEDTLS_PKCS1_V21 */ } /* @@ -493,11 +1404,6 @@ int mbedtls_pk_decrypt(mbedtls_pk_context *ctx, unsigned char *output, size_t *olen, size_t osize, int (*f_rng)(void *, unsigned char *, size_t), void *p_rng) { - PK_VALIDATE_RET(ctx != NULL); - PK_VALIDATE_RET(input != NULL || ilen == 0); - PK_VALIDATE_RET(output != NULL || osize == 0); - PK_VALIDATE_RET(olen != NULL); - if (ctx->pk_info == NULL) { return MBEDTLS_ERR_PK_BAD_INPUT_DATA; } @@ -506,7 +1412,7 @@ int mbedtls_pk_decrypt(mbedtls_pk_context *ctx, return MBEDTLS_ERR_PK_TYPE_MISMATCH; } - return ctx->pk_info->decrypt_func(ctx->pk_ctx, input, ilen, + return ctx->pk_info->decrypt_func(ctx, input, ilen, output, olen, osize, f_rng, p_rng); } @@ -518,11 +1424,6 @@ int mbedtls_pk_encrypt(mbedtls_pk_context *ctx, unsigned char *output, size_t *olen, size_t osize, int (*f_rng)(void *, unsigned char *, size_t), void *p_rng) { - PK_VALIDATE_RET(ctx != NULL); - PK_VALIDATE_RET(input != NULL || ilen == 0); - PK_VALIDATE_RET(output != NULL || osize == 0); - PK_VALIDATE_RET(olen != NULL); - if (ctx->pk_info == NULL) { return MBEDTLS_ERR_PK_BAD_INPUT_DATA; } @@ -531,23 +1432,27 @@ int mbedtls_pk_encrypt(mbedtls_pk_context *ctx, return MBEDTLS_ERR_PK_TYPE_MISMATCH; } - return ctx->pk_info->encrypt_func(ctx->pk_ctx, input, ilen, + return ctx->pk_info->encrypt_func(ctx, input, ilen, output, olen, osize, f_rng, p_rng); } /* * Check public-private key pair */ -int mbedtls_pk_check_pair(const mbedtls_pk_context *pub, const mbedtls_pk_context *prv) +int mbedtls_pk_check_pair(const mbedtls_pk_context *pub, + const mbedtls_pk_context *prv, + int (*f_rng)(void *, unsigned char *, size_t), + void *p_rng) { - PK_VALIDATE_RET(pub != NULL); - PK_VALIDATE_RET(prv != NULL); - if (pub->pk_info == NULL || prv->pk_info == NULL) { return MBEDTLS_ERR_PK_BAD_INPUT_DATA; } + if (f_rng == NULL) { + return MBEDTLS_ERR_PK_BAD_INPUT_DATA; + } + if (prv->pk_info->check_pair_func == NULL) { return MBEDTLS_ERR_PK_FEATURE_UNAVAILABLE; } @@ -557,12 +1462,15 @@ int mbedtls_pk_check_pair(const mbedtls_pk_context *pub, const mbedtls_pk_contex return MBEDTLS_ERR_PK_TYPE_MISMATCH; } } else { - if (pub->pk_info != prv->pk_info) { + if ((prv->pk_info->type != MBEDTLS_PK_OPAQUE) && + (pub->pk_info != prv->pk_info)) { return MBEDTLS_ERR_PK_TYPE_MISMATCH; } } - return prv->pk_info->check_pair_func(pub->pk_ctx, prv->pk_ctx); + return prv->pk_info->check_pair_func((mbedtls_pk_context *) pub, + (mbedtls_pk_context *) prv, + f_rng, p_rng); } /* @@ -576,7 +1484,7 @@ size_t mbedtls_pk_get_bitlen(const mbedtls_pk_context *ctx) return 0; } - return ctx->pk_info->get_bitlen(ctx->pk_ctx); + return ctx->pk_info->get_bitlen((mbedtls_pk_context *) ctx); } /* @@ -584,7 +1492,6 @@ size_t mbedtls_pk_get_bitlen(const mbedtls_pk_context *ctx) */ int mbedtls_pk_debug(const mbedtls_pk_context *ctx, mbedtls_pk_debug_item *items) { - PK_VALIDATE_RET(ctx != NULL); if (ctx->pk_info == NULL) { return MBEDTLS_ERR_PK_BAD_INPUT_DATA; } @@ -593,7 +1500,7 @@ int mbedtls_pk_debug(const mbedtls_pk_context *ctx, mbedtls_pk_debug_item *items return MBEDTLS_ERR_PK_TYPE_MISMATCH; } - ctx->pk_info->debug_func(ctx->pk_ctx, items); + ctx->pk_info->debug_func((mbedtls_pk_context *) ctx, items); return 0; } @@ -621,66 +1528,4 @@ mbedtls_pk_type_t mbedtls_pk_get_type(const mbedtls_pk_context *ctx) return ctx->pk_info->type; } -#if defined(MBEDTLS_USE_PSA_CRYPTO) -/* - * Load the key to a PSA key slot, - * then turn the PK context into a wrapper for that key slot. - * - * Currently only works for EC private keys. - */ -int mbedtls_pk_wrap_as_opaque(mbedtls_pk_context *pk, - psa_key_id_t *key, - psa_algorithm_t hash_alg) -{ -#if !defined(MBEDTLS_ECP_C) - ((void) pk); - ((void) key); - ((void) hash_alg); - return MBEDTLS_ERR_PK_TYPE_MISMATCH; -#else - const mbedtls_ecp_keypair *ec; - unsigned char d[MBEDTLS_ECP_MAX_BYTES]; - size_t d_len; - psa_ecc_family_t curve_id; - psa_key_attributes_t attributes = PSA_KEY_ATTRIBUTES_INIT; - psa_key_type_t key_type; - size_t bits; - int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED; - psa_status_t status; - - /* export the private key material in the format PSA wants */ - if (mbedtls_pk_get_type(pk) != MBEDTLS_PK_ECKEY) { - return MBEDTLS_ERR_PK_TYPE_MISMATCH; - } - - ec = mbedtls_pk_ec(*pk); - d_len = (ec->grp.nbits + 7) / 8; - if ((ret = mbedtls_mpi_write_binary(&ec->d, d, d_len)) != 0) { - return ret; - } - - curve_id = mbedtls_ecc_group_to_psa(ec->grp.id, &bits); - key_type = PSA_KEY_TYPE_ECC_KEY_PAIR(curve_id); - - /* prepare the key attributes */ - psa_set_key_type(&attributes, key_type); - psa_set_key_bits(&attributes, bits); - psa_set_key_usage_flags(&attributes, PSA_KEY_USAGE_SIGN_HASH); - psa_set_key_algorithm(&attributes, PSA_ALG_ECDSA(hash_alg)); - - /* import private key into PSA */ - status = psa_import_key(&attributes, d, d_len, key); - mbedtls_platform_zeroize(d, sizeof(d)); - if (status != PSA_SUCCESS) { - return MBEDTLS_ERR_PK_HW_ACCEL_FAILED; - } - - /* make PK context wrap the key slot */ - mbedtls_pk_free(pk); - mbedtls_pk_init(pk); - - return mbedtls_pk_setup_opaque(pk, *key); -#endif /* MBEDTLS_ECP_C */ -} -#endif /* MBEDTLS_USE_PSA_CRYPTO */ #endif /* MBEDTLS_PK_C */ diff --git a/vendor/mbedtls/library/pk_ecc.c b/vendor/mbedtls/library/pk_ecc.c new file mode 100644 index 0000000000..86218fffc8 --- /dev/null +++ b/vendor/mbedtls/library/pk_ecc.c @@ -0,0 +1,255 @@ +/* + * ECC setters for PK. + * + * Copyright The Mbed TLS Contributors + * SPDX-License-Identifier: Apache-2.0 OR GPL-2.0-or-later + */ + +#include "common.h" + +#include "mbedtls/pk.h" +#include "mbedtls/error.h" +#include "mbedtls/ecp.h" +#include "pk_internal.h" + +#if defined(MBEDTLS_PK_C) && defined(MBEDTLS_PK_HAVE_ECC_KEYS) + +int mbedtls_pk_ecc_set_group(mbedtls_pk_context *pk, mbedtls_ecp_group_id grp_id) +{ +#if defined(MBEDTLS_PK_USE_PSA_EC_DATA) + size_t ec_bits; + psa_ecc_family_t ec_family = mbedtls_ecc_group_to_psa(grp_id, &ec_bits); + + /* group may already be initialized; if so, make sure IDs match */ + if ((pk->ec_family != 0 && pk->ec_family != ec_family) || + (pk->ec_bits != 0 && pk->ec_bits != ec_bits)) { + return MBEDTLS_ERR_PK_KEY_INVALID_FORMAT; + } + + /* set group */ + pk->ec_family = ec_family; + pk->ec_bits = ec_bits; + + return 0; +#else /* MBEDTLS_PK_USE_PSA_EC_DATA */ + mbedtls_ecp_keypair *ecp = mbedtls_pk_ec_rw(*pk); + + /* grp may already be initialized; if so, make sure IDs match */ + if (mbedtls_pk_ec_ro(*pk)->grp.id != MBEDTLS_ECP_DP_NONE && + mbedtls_pk_ec_ro(*pk)->grp.id != grp_id) { + return MBEDTLS_ERR_PK_KEY_INVALID_FORMAT; + } + + /* set group */ + return mbedtls_ecp_group_load(&(ecp->grp), grp_id); +#endif /* MBEDTLS_PK_USE_PSA_EC_DATA */ +} + +int mbedtls_pk_ecc_set_key(mbedtls_pk_context *pk, unsigned char *key, size_t key_len) +{ +#if defined(MBEDTLS_PK_USE_PSA_EC_DATA) + psa_key_attributes_t attributes = PSA_KEY_ATTRIBUTES_INIT; + psa_key_usage_t flags; + psa_status_t status; + + psa_set_key_type(&attributes, PSA_KEY_TYPE_ECC_KEY_PAIR(pk->ec_family)); + if (pk->ec_family == PSA_ECC_FAMILY_MONTGOMERY) { + /* Do not set algorithm here because Montgomery keys cannot do ECDSA and + * the PK module cannot do ECDH. When the key will be used in TLS for + * ECDH, it will be exported and then re-imported with proper flags + * and algorithm. */ + flags = PSA_KEY_USAGE_EXPORT; + } else { + psa_set_key_algorithm(&attributes, + MBEDTLS_PK_PSA_ALG_ECDSA_MAYBE_DET(PSA_ALG_ANY_HASH)); + flags = PSA_KEY_USAGE_SIGN_HASH | PSA_KEY_USAGE_SIGN_MESSAGE | + PSA_KEY_USAGE_EXPORT; + } + psa_set_key_usage_flags(&attributes, flags); + + status = psa_import_key(&attributes, key, key_len, &pk->priv_id); + return psa_pk_status_to_mbedtls(status); + +#else /* MBEDTLS_PK_USE_PSA_EC_DATA */ + + mbedtls_ecp_keypair *eck = mbedtls_pk_ec_rw(*pk); + int ret = mbedtls_ecp_read_key(eck->grp.id, eck, key, key_len); + if (ret != 0) { + return MBEDTLS_ERROR_ADD(MBEDTLS_ERR_PK_KEY_INVALID_FORMAT, ret); + } + return 0; +#endif /* MBEDTLS_PK_USE_PSA_EC_DATA */ +} + +int mbedtls_pk_ecc_set_pubkey_from_prv(mbedtls_pk_context *pk, + const unsigned char *prv, size_t prv_len, + int (*f_rng)(void *, unsigned char *, size_t), void *p_rng) +{ +#if defined(MBEDTLS_PK_USE_PSA_EC_DATA) + + (void) f_rng; + (void) p_rng; + (void) prv; + (void) prv_len; + psa_status_t status; + + status = psa_export_public_key(pk->priv_id, pk->pub_raw, sizeof(pk->pub_raw), + &pk->pub_raw_len); + return psa_pk_status_to_mbedtls(status); + +#elif defined(MBEDTLS_USE_PSA_CRYPTO) /* && !MBEDTLS_PK_USE_PSA_EC_DATA */ + + (void) f_rng; + (void) p_rng; + psa_status_t status; + + mbedtls_ecp_keypair *eck = (mbedtls_ecp_keypair *) pk->pk_ctx; + size_t curve_bits; + psa_ecc_family_t curve = mbedtls_ecc_group_to_psa(eck->grp.id, &curve_bits); + + /* Import private key into PSA, from serialized input */ + mbedtls_svc_key_id_t key_id = MBEDTLS_SVC_KEY_ID_INIT; + psa_key_attributes_t key_attr = PSA_KEY_ATTRIBUTES_INIT; + psa_set_key_type(&key_attr, PSA_KEY_TYPE_ECC_KEY_PAIR(curve)); + psa_set_key_usage_flags(&key_attr, PSA_KEY_USAGE_EXPORT); + status = psa_import_key(&key_attr, prv, prv_len, &key_id); + if (status != PSA_SUCCESS) { + return psa_pk_status_to_mbedtls(status); + } + + /* Export public key from PSA */ + unsigned char pub[MBEDTLS_PSA_MAX_EC_PUBKEY_LENGTH]; + size_t pub_len; + status = psa_export_public_key(key_id, pub, sizeof(pub), &pub_len); + psa_status_t destruction_status = psa_destroy_key(key_id); + if (status != PSA_SUCCESS) { + return psa_pk_status_to_mbedtls(status); + } else if (destruction_status != PSA_SUCCESS) { + return psa_pk_status_to_mbedtls(destruction_status); + } + + /* Load serialized public key into ecp_keypair structure */ + return mbedtls_ecp_point_read_binary(&eck->grp, &eck->Q, pub, pub_len); + +#else /* MBEDTLS_USE_PSA_CRYPTO */ + + (void) prv; + (void) prv_len; + + mbedtls_ecp_keypair *eck = (mbedtls_ecp_keypair *) pk->pk_ctx; + return mbedtls_ecp_mul(&eck->grp, &eck->Q, &eck->d, &eck->grp.G, f_rng, p_rng); + +#endif /* MBEDTLS_USE_PSA_CRYPTO */ +} + +#if defined(MBEDTLS_PK_USE_PSA_EC_DATA) +/* + * Set the public key: fallback using ECP_LIGHT in the USE_PSA_EC_DATA case. + * + * Normally, when MBEDTLS_PK_USE_PSA_EC_DATA is enabled, we only use PSA + * functions to handle keys. However, currently psa_import_key() does not + * support compressed points. In case that support was explicitly requested, + * this fallback uses ECP functions to get the job done. This is the reason + * why MBEDTLS_PK_PARSE_EC_COMPRESSED auto-enables MBEDTLS_ECP_LIGHT. + * + * [in/out] pk: in: must have the group set, see mbedtls_pk_ecc_set_group(). + * out: will have the public key set. + * [in] pub, pub_len: the public key as an ECPoint, + * in any format supported by ECP. + * + * Return: + * - 0 on success; + * - MBEDTLS_ERR_ECP_FEATURE_UNAVAILABLE if the format is potentially valid + * but not supported; + * - another error code otherwise. + */ +static int pk_ecc_set_pubkey_psa_ecp_fallback(mbedtls_pk_context *pk, + const unsigned char *pub, + size_t pub_len) +{ +#if !defined(MBEDTLS_PK_PARSE_EC_COMPRESSED) + (void) pk; + (void) pub; + (void) pub_len; + return MBEDTLS_ERR_ECP_FEATURE_UNAVAILABLE; +#else /* MBEDTLS_PK_PARSE_EC_COMPRESSED */ + mbedtls_ecp_keypair ecp_key; + mbedtls_ecp_group_id ecp_group_id; + int ret; + + ecp_group_id = mbedtls_ecc_group_from_psa(pk->ec_family, pk->ec_bits); + + mbedtls_ecp_keypair_init(&ecp_key); + ret = mbedtls_ecp_group_load(&(ecp_key.grp), ecp_group_id); + if (ret != 0) { + goto exit; + } + ret = mbedtls_ecp_point_read_binary(&(ecp_key.grp), &ecp_key.Q, + pub, pub_len); + if (ret != 0) { + goto exit; + } + ret = mbedtls_ecp_point_write_binary(&(ecp_key.grp), &ecp_key.Q, + MBEDTLS_ECP_PF_UNCOMPRESSED, + &pk->pub_raw_len, pk->pub_raw, + sizeof(pk->pub_raw)); + +exit: + mbedtls_ecp_keypair_free(&ecp_key); + return ret; +#endif /* MBEDTLS_PK_PARSE_EC_COMPRESSED */ +} +#endif /* MBEDTLS_PK_USE_PSA_EC_DATA */ + +int mbedtls_pk_ecc_set_pubkey(mbedtls_pk_context *pk, const unsigned char *pub, size_t pub_len) +{ +#if defined(MBEDTLS_PK_USE_PSA_EC_DATA) + + /* Load the key */ + if (!PSA_ECC_FAMILY_IS_WEIERSTRASS(pk->ec_family) || *pub == 0x04) { + /* Format directly supported by PSA: + * - non-Weierstrass curves that only have one format; + * - uncompressed format for Weierstrass curves. */ + if (pub_len > sizeof(pk->pub_raw)) { + return MBEDTLS_ERR_PK_BUFFER_TOO_SMALL; + } + memcpy(pk->pub_raw, pub, pub_len); + pk->pub_raw_len = pub_len; + } else { + /* Other format, try the fallback */ + int ret = pk_ecc_set_pubkey_psa_ecp_fallback(pk, pub, pub_len); + if (ret != 0) { + return ret; + } + } + + /* Validate the key by trying to import it */ + mbedtls_svc_key_id_t key_id = MBEDTLS_SVC_KEY_ID_INIT; + psa_key_attributes_t key_attrs = PSA_KEY_ATTRIBUTES_INIT; + + psa_set_key_usage_flags(&key_attrs, 0); + psa_set_key_type(&key_attrs, PSA_KEY_TYPE_ECC_PUBLIC_KEY(pk->ec_family)); + psa_set_key_bits(&key_attrs, pk->ec_bits); + + if ((psa_import_key(&key_attrs, pk->pub_raw, pk->pub_raw_len, + &key_id) != PSA_SUCCESS) || + (psa_destroy_key(key_id) != PSA_SUCCESS)) { + return MBEDTLS_ERR_PK_INVALID_PUBKEY; + } + + return 0; + +#else /* MBEDTLS_PK_USE_PSA_EC_DATA */ + + int ret; + mbedtls_ecp_keypair *ec_key = (mbedtls_ecp_keypair *) pk->pk_ctx; + ret = mbedtls_ecp_point_read_binary(&ec_key->grp, &ec_key->Q, pub, pub_len); + if (ret != 0) { + return ret; + } + return mbedtls_ecp_check_pubkey(&ec_key->grp, &ec_key->Q); + +#endif /* MBEDTLS_PK_USE_PSA_EC_DATA */ +} + +#endif /* MBEDTLS_PK_C && MBEDTLS_PK_HAVE_ECC_KEYS */ diff --git a/vendor/mbedtls/library/pk_internal.h b/vendor/mbedtls/library/pk_internal.h new file mode 100644 index 0000000000..e86a3a09d2 --- /dev/null +++ b/vendor/mbedtls/library/pk_internal.h @@ -0,0 +1,207 @@ +/** + * \file pk_internal.h + * + * \brief Public Key abstraction layer: internal (i.e. library only) functions + * and definitions. + */ +/* + * Copyright The Mbed TLS Contributors + * SPDX-License-Identifier: Apache-2.0 OR GPL-2.0-or-later + */ +#ifndef MBEDTLS_PK_INTERNAL_H +#define MBEDTLS_PK_INTERNAL_H + +#include "mbedtls/pk.h" + +#if defined(MBEDTLS_PK_HAVE_ECC_KEYS) +#include "mbedtls/ecp.h" +#endif + +#if defined(MBEDTLS_PSA_CRYPTO_CLIENT) +#include "psa/crypto.h" + +#include "psa_util_internal.h" +#define PSA_PK_TO_MBEDTLS_ERR(status) psa_pk_status_to_mbedtls(status) +#define PSA_PK_RSA_TO_MBEDTLS_ERR(status) PSA_TO_MBEDTLS_ERR_LIST(status, \ + psa_to_pk_rsa_errors, \ + psa_pk_status_to_mbedtls) +#define PSA_PK_ECDSA_TO_MBEDTLS_ERR(status) PSA_TO_MBEDTLS_ERR_LIST(status, \ + psa_to_pk_ecdsa_errors, \ + psa_pk_status_to_mbedtls) +#endif /* MBEDTLS_PSA_CRYPTO_CLIENT */ + +/* Headers/footers for PEM files */ +#define PEM_BEGIN_PUBLIC_KEY "-----BEGIN PUBLIC KEY-----" +#define PEM_END_PUBLIC_KEY "-----END PUBLIC KEY-----" +#define PEM_BEGIN_PRIVATE_KEY_RSA "-----BEGIN RSA PRIVATE KEY-----" +#define PEM_END_PRIVATE_KEY_RSA "-----END RSA PRIVATE KEY-----" +#define PEM_BEGIN_PUBLIC_KEY_RSA "-----BEGIN RSA PUBLIC KEY-----" +#define PEM_END_PUBLIC_KEY_RSA "-----END RSA PUBLIC KEY-----" +#define PEM_BEGIN_PRIVATE_KEY_EC "-----BEGIN EC PRIVATE KEY-----" +#define PEM_END_PRIVATE_KEY_EC "-----END EC PRIVATE KEY-----" +#define PEM_BEGIN_PRIVATE_KEY_PKCS8 "-----BEGIN PRIVATE KEY-----" +#define PEM_END_PRIVATE_KEY_PKCS8 "-----END PRIVATE KEY-----" +#define PEM_BEGIN_ENCRYPTED_PRIVATE_KEY_PKCS8 "-----BEGIN ENCRYPTED PRIVATE KEY-----" +#define PEM_END_ENCRYPTED_PRIVATE_KEY_PKCS8 "-----END ENCRYPTED PRIVATE KEY-----" + +#if defined(MBEDTLS_PK_HAVE_ECC_KEYS) && !defined(MBEDTLS_PK_USE_PSA_EC_DATA) +/** + * Public function mbedtls_pk_ec() can be used to get direct access to the + * wrapped ecp_keypair structure pointed to the pk_ctx. However this is not + * ideal because it bypasses the PK module on the control of its internal + * structure (pk_context) fields. + * For backward compatibility we keep mbedtls_pk_ec() when ECP_C is defined, but + * we provide 2 very similar functions when only ECP_LIGHT is enabled and not + * ECP_C. + * These variants embed the "ro" or "rw" keywords in their name to make the + * usage of the returned pointer explicit. Of course the returned value is + * const or non-const accordingly. + */ +static inline const mbedtls_ecp_keypair *mbedtls_pk_ec_ro(const mbedtls_pk_context pk) +{ + switch (mbedtls_pk_get_type(&pk)) { + case MBEDTLS_PK_ECKEY: + case MBEDTLS_PK_ECKEY_DH: + case MBEDTLS_PK_ECDSA: + return (const mbedtls_ecp_keypair *) (pk).MBEDTLS_PRIVATE(pk_ctx); + default: + return NULL; + } +} + +static inline mbedtls_ecp_keypair *mbedtls_pk_ec_rw(const mbedtls_pk_context pk) +{ + switch (mbedtls_pk_get_type(&pk)) { + case MBEDTLS_PK_ECKEY: + case MBEDTLS_PK_ECKEY_DH: + case MBEDTLS_PK_ECDSA: + return (mbedtls_ecp_keypair *) (pk).MBEDTLS_PRIVATE(pk_ctx); + default: + return NULL; + } +} +#endif /* MBEDTLS_PK_HAVE_ECC_KEYS && !MBEDTLS_PK_USE_PSA_EC_DATA */ + +#if defined(MBEDTLS_PK_HAVE_ECC_KEYS) +static inline mbedtls_ecp_group_id mbedtls_pk_get_ec_group_id(const mbedtls_pk_context *pk) +{ + mbedtls_ecp_group_id id; + +#if defined(MBEDTLS_USE_PSA_CRYPTO) + if (mbedtls_pk_get_type(pk) == MBEDTLS_PK_OPAQUE) { + psa_key_attributes_t opaque_attrs = PSA_KEY_ATTRIBUTES_INIT; + psa_key_type_t opaque_key_type; + psa_ecc_family_t curve; + + if (psa_get_key_attributes(pk->priv_id, &opaque_attrs) != PSA_SUCCESS) { + return MBEDTLS_ECP_DP_NONE; + } + opaque_key_type = psa_get_key_type(&opaque_attrs); + curve = PSA_KEY_TYPE_ECC_GET_FAMILY(opaque_key_type); + id = mbedtls_ecc_group_from_psa(curve, psa_get_key_bits(&opaque_attrs)); + psa_reset_key_attributes(&opaque_attrs); + } else +#endif /* MBEDTLS_USE_PSA_CRYPTO */ + { +#if defined(MBEDTLS_PK_USE_PSA_EC_DATA) + id = mbedtls_ecc_group_from_psa(pk->ec_family, pk->ec_bits); +#else /* MBEDTLS_PK_USE_PSA_EC_DATA */ + id = mbedtls_pk_ec_ro(*pk)->grp.id; +#endif /* MBEDTLS_PK_USE_PSA_EC_DATA */ + } + + return id; +} + +/* Helper for Montgomery curves */ +#if defined(MBEDTLS_ECP_HAVE_CURVE25519) || defined(MBEDTLS_ECP_HAVE_CURVE448) +#define MBEDTLS_PK_HAVE_RFC8410_CURVES +#endif /* MBEDTLS_ECP_HAVE_CURVE25519 || MBEDTLS_ECP_DP_CURVE448 */ + +#define MBEDTLS_PK_IS_RFC8410_GROUP_ID(id) \ + ((id == MBEDTLS_ECP_DP_CURVE25519) || (id == MBEDTLS_ECP_DP_CURVE448)) + +static inline int mbedtls_pk_is_rfc8410(const mbedtls_pk_context *pk) +{ + mbedtls_ecp_group_id id = mbedtls_pk_get_ec_group_id(pk); + + return MBEDTLS_PK_IS_RFC8410_GROUP_ID(id); +} + +/* + * Set the group used by this key. + * + * [in/out] pk: in: must have been pk_setup() to an ECC type + * out: will have group (curve) information set + * [in] grp_in: a supported group ID (not NONE) + */ +int mbedtls_pk_ecc_set_group(mbedtls_pk_context *pk, mbedtls_ecp_group_id grp_id); + +/* + * Set the private key material + * + * [in/out] pk: in: must have the group set already, see mbedtls_pk_ecc_set_group(). + * out: will have the private key set. + * [in] key, key_len: the raw private key (no ASN.1 wrapping). + */ +int mbedtls_pk_ecc_set_key(mbedtls_pk_context *pk, unsigned char *key, size_t key_len); + +/* + * Set the public key. + * + * [in/out] pk: in: must have its group set, see mbedtls_pk_ecc_set_group(). + * out: will have the public key set. + * [in] pub, pub_len: the raw public key (an ECPoint). + * + * Return: + * - 0 on success; + * - MBEDTLS_ERR_ECP_FEATURE_UNAVAILABLE if the format is potentially valid + * but not supported; + * - another error code otherwise. + */ +int mbedtls_pk_ecc_set_pubkey(mbedtls_pk_context *pk, const unsigned char *pub, size_t pub_len); + +/* + * Derive a public key from its private counterpart. + * Computationally intensive, only use when public key is not available. + * + * [in/out] pk: in: must have the private key set, see mbedtls_pk_ecc_set_key(). + * out: will have the public key set. + * [in] prv, prv_len: the raw private key (see note below). + * [in] f_rng, p_rng: RNG function and context. + * + * Note: the private key information is always available from pk, + * however for convenience the serialized version is also passed, + * as it's available at each calling site, and useful in some configs + * (as otherwise we would have to re-serialize it from the pk context). + * + * There are three implementations of this function: + * 1. MBEDTLS_PK_USE_PSA_EC_DATA, + * 2. MBEDTLS_USE_PSA_CRYPTO but not MBEDTLS_PK_USE_PSA_EC_DATA, + * 3. not MBEDTLS_USE_PSA_CRYPTO. + */ +int mbedtls_pk_ecc_set_pubkey_from_prv(mbedtls_pk_context *pk, + const unsigned char *prv, size_t prv_len, + int (*f_rng)(void *, unsigned char *, size_t), void *p_rng); +#endif /* MBEDTLS_PK_HAVE_ECC_KEYS */ + +/* Helper for (deterministic) ECDSA */ +#if defined(MBEDTLS_ECDSA_DETERMINISTIC) +#define MBEDTLS_PK_PSA_ALG_ECDSA_MAYBE_DET PSA_ALG_DETERMINISTIC_ECDSA +#else +#define MBEDTLS_PK_PSA_ALG_ECDSA_MAYBE_DET PSA_ALG_ECDSA +#endif + +#if defined(MBEDTLS_TEST_HOOKS) +MBEDTLS_STATIC_TESTABLE int mbedtls_pk_parse_key_pkcs8_encrypted_der( + mbedtls_pk_context *pk, + unsigned char *key, size_t keylen, + const unsigned char *pwd, size_t pwdlen, + int (*f_rng)(void *, unsigned char *, size_t), void *p_rng); +#endif + +#if defined(MBEDTLS_FS_IO) +int mbedtls_pk_load_file(const char *path, unsigned char **buf, size_t *n); +#endif + +#endif /* MBEDTLS_PK_INTERNAL_H */ diff --git a/vendor/mbedtls/library/pk_wrap.c b/vendor/mbedtls/library/pk_wrap.c index f577fccdbb..19196b559a 100644 --- a/vendor/mbedtls/library/pk_wrap.c +++ b/vendor/mbedtls/library/pk_wrap.c @@ -2,32 +2,22 @@ * Public Key abstraction layer: wrapper functions * * Copyright The Mbed TLS Contributors - * SPDX-License-Identifier: Apache-2.0 - * - * Licensed under the Apache License, Version 2.0 (the "License"); you may - * not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT - * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. + * SPDX-License-Identifier: Apache-2.0 OR GPL-2.0-or-later */ #include "common.h" +#include "mbedtls/platform_util.h" + #if defined(MBEDTLS_PK_C) -#include "mbedtls/pk_internal.h" +#include "pk_wrap.h" +#include "pk_internal.h" #include "mbedtls/error.h" +#include "mbedtls/psa_util.h" /* Even if RSA not activated, for the sake of RSA-alt */ #include "mbedtls/rsa.h" -#include - #if defined(MBEDTLS_ECP_C) #include "mbedtls/ecp.h" #endif @@ -37,23 +27,26 @@ #endif #if defined(MBEDTLS_USE_PSA_CRYPTO) -#include "mbedtls/asn1write.h" -#endif +#include "psa_util_internal.h" +#include "psa/crypto.h" +#include "mbedtls/psa_util.h" -#if defined(MBEDTLS_PK_RSA_ALT_SUPPORT) -#include "mbedtls/platform_util.h" +#if defined(MBEDTLS_RSA_C) +#include "pkwrite.h" +#include "rsa_internal.h" #endif -#if defined(MBEDTLS_USE_PSA_CRYPTO) -#include "psa/crypto.h" -#include "mbedtls/psa_util.h" +#if defined(MBEDTLS_PK_CAN_ECDSA_SOME) +#include "mbedtls/asn1write.h" #include "mbedtls/asn1.h" #endif +#endif /* MBEDTLS_USE_PSA_CRYPTO */ #include "mbedtls/platform.h" #include #include +#include #if defined(MBEDTLS_RSA_C) static int rsa_can_do(mbedtls_pk_type_t type) @@ -62,33 +55,99 @@ static int rsa_can_do(mbedtls_pk_type_t type) type == MBEDTLS_PK_RSASSA_PSS; } -static size_t rsa_get_bitlen(const void *ctx) +static size_t rsa_get_bitlen(mbedtls_pk_context *pk) { - const mbedtls_rsa_context *rsa = (const mbedtls_rsa_context *) ctx; - return 8 * mbedtls_rsa_get_len(rsa); + const mbedtls_rsa_context *rsa = (const mbedtls_rsa_context *) pk->pk_ctx; + return mbedtls_rsa_get_bitlen(rsa); } -static int rsa_verify_wrap(void *ctx, mbedtls_md_type_t md_alg, +#if defined(MBEDTLS_USE_PSA_CRYPTO) +static int rsa_verify_wrap(mbedtls_pk_context *pk, mbedtls_md_type_t md_alg, + const unsigned char *hash, size_t hash_len, + const unsigned char *sig, size_t sig_len) +{ + mbedtls_rsa_context *rsa = (mbedtls_rsa_context *) pk->pk_ctx; + int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED; + psa_key_attributes_t attributes = PSA_KEY_ATTRIBUTES_INIT; + mbedtls_svc_key_id_t key_id = MBEDTLS_SVC_KEY_ID_INIT; + psa_status_t status; + int key_len; + unsigned char buf[MBEDTLS_PK_RSA_PUB_DER_MAX_BYTES]; + unsigned char *p = buf + sizeof(buf); + psa_algorithm_t psa_alg_md; + size_t rsa_len = mbedtls_rsa_get_len(rsa); + +#if SIZE_MAX > UINT_MAX + if (md_alg == MBEDTLS_MD_NONE && UINT_MAX < hash_len) { + return MBEDTLS_ERR_PK_BAD_INPUT_DATA; + } +#endif + + if (mbedtls_rsa_get_padding_mode(rsa) == MBEDTLS_RSA_PKCS_V21) { + psa_alg_md = PSA_ALG_RSA_PSS(mbedtls_md_psa_alg_from_type(md_alg)); + } else { + psa_alg_md = PSA_ALG_RSA_PKCS1V15_SIGN(mbedtls_md_psa_alg_from_type(md_alg)); + } + + if (sig_len < rsa_len) { + return MBEDTLS_ERR_RSA_VERIFY_FAILED; + } + + key_len = mbedtls_rsa_write_pubkey(rsa, buf, &p); + if (key_len <= 0) { + return MBEDTLS_ERR_PK_BAD_INPUT_DATA; + } + + psa_set_key_usage_flags(&attributes, PSA_KEY_USAGE_VERIFY_HASH); + psa_set_key_algorithm(&attributes, psa_alg_md); + psa_set_key_type(&attributes, PSA_KEY_TYPE_RSA_PUBLIC_KEY); + + status = psa_import_key(&attributes, + buf + sizeof(buf) - key_len, key_len, + &key_id); + if (status != PSA_SUCCESS) { + ret = PSA_PK_TO_MBEDTLS_ERR(status); + goto cleanup; + } + + status = psa_verify_hash(key_id, psa_alg_md, hash, hash_len, + sig, sig_len); + if (status != PSA_SUCCESS) { + ret = PSA_PK_RSA_TO_MBEDTLS_ERR(status); + goto cleanup; + } + ret = 0; + +cleanup: + status = psa_destroy_key(key_id); + if (ret == 0 && status != PSA_SUCCESS) { + ret = PSA_PK_TO_MBEDTLS_ERR(status); + } + + return ret; +} +#else /* MBEDTLS_USE_PSA_CRYPTO */ +static int rsa_verify_wrap(mbedtls_pk_context *pk, mbedtls_md_type_t md_alg, const unsigned char *hash, size_t hash_len, const unsigned char *sig, size_t sig_len) { int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED; - mbedtls_rsa_context *rsa = (mbedtls_rsa_context *) ctx; + mbedtls_rsa_context *rsa = (mbedtls_rsa_context *) pk->pk_ctx; size_t rsa_len = mbedtls_rsa_get_len(rsa); #if SIZE_MAX > UINT_MAX if (md_alg == MBEDTLS_MD_NONE && UINT_MAX < hash_len) { return MBEDTLS_ERR_PK_BAD_INPUT_DATA; } -#endif /* SIZE_MAX > UINT_MAX */ +#endif if (sig_len < rsa_len) { return MBEDTLS_ERR_RSA_VERIFY_FAILED; } - if ((ret = mbedtls_rsa_pkcs1_verify(rsa, NULL, NULL, - MBEDTLS_RSA_PUBLIC, md_alg, - (unsigned int) hash_len, hash, sig)) != 0) { + if ((ret = mbedtls_rsa_pkcs1_verify(rsa, md_alg, + (unsigned int) hash_len, + hash, sig)) != 0) { return ret; } @@ -103,61 +162,293 @@ static int rsa_verify_wrap(void *ctx, mbedtls_md_type_t md_alg, return 0; } +#endif /* MBEDTLS_USE_PSA_CRYPTO */ -static int rsa_sign_wrap(void *ctx, mbedtls_md_type_t md_alg, +#if defined(MBEDTLS_USE_PSA_CRYPTO) +int mbedtls_pk_psa_rsa_sign_ext(psa_algorithm_t alg, + mbedtls_rsa_context *rsa_ctx, + const unsigned char *hash, size_t hash_len, + unsigned char *sig, size_t sig_size, + size_t *sig_len) +{ + int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED; + psa_key_attributes_t attributes = PSA_KEY_ATTRIBUTES_INIT; + mbedtls_svc_key_id_t key_id = MBEDTLS_SVC_KEY_ID_INIT; + psa_status_t status; + int key_len; + unsigned char *buf = NULL; + unsigned char *p; + + buf = mbedtls_calloc(1, MBEDTLS_PK_RSA_PRV_DER_MAX_BYTES); + if (buf == NULL) { + return MBEDTLS_ERR_PK_ALLOC_FAILED; + } + p = buf + MBEDTLS_PK_RSA_PRV_DER_MAX_BYTES; + + *sig_len = mbedtls_rsa_get_len(rsa_ctx); + if (sig_size < *sig_len) { + mbedtls_free(buf); + return MBEDTLS_ERR_PK_BUFFER_TOO_SMALL; + } + + key_len = mbedtls_rsa_write_key(rsa_ctx, buf, &p); + if (key_len <= 0) { + mbedtls_free(buf); + return MBEDTLS_ERR_PK_BAD_INPUT_DATA; + } + psa_set_key_usage_flags(&attributes, PSA_KEY_USAGE_SIGN_HASH); + psa_set_key_algorithm(&attributes, alg); + psa_set_key_type(&attributes, PSA_KEY_TYPE_RSA_KEY_PAIR); + + status = psa_import_key(&attributes, + buf + MBEDTLS_PK_RSA_PRV_DER_MAX_BYTES - key_len, key_len, + &key_id); + if (status != PSA_SUCCESS) { + ret = PSA_PK_TO_MBEDTLS_ERR(status); + goto cleanup; + } + status = psa_sign_hash(key_id, alg, hash, hash_len, + sig, sig_size, sig_len); + if (status != PSA_SUCCESS) { + ret = PSA_PK_RSA_TO_MBEDTLS_ERR(status); + goto cleanup; + } + + ret = 0; + +cleanup: + mbedtls_free(buf); + status = psa_destroy_key(key_id); + if (ret == 0 && status != PSA_SUCCESS) { + ret = PSA_PK_TO_MBEDTLS_ERR(status); + } + return ret; +} +#endif /* MBEDTLS_USE_PSA_CRYPTO */ + +#if defined(MBEDTLS_USE_PSA_CRYPTO) +static int rsa_sign_wrap(mbedtls_pk_context *pk, mbedtls_md_type_t md_alg, const unsigned char *hash, size_t hash_len, - unsigned char *sig, size_t *sig_len, + unsigned char *sig, size_t sig_size, size_t *sig_len, int (*f_rng)(void *, unsigned char *, size_t), void *p_rng) { - mbedtls_rsa_context *rsa = (mbedtls_rsa_context *) ctx; + ((void) f_rng); + ((void) p_rng); + + psa_algorithm_t psa_md_alg; + psa_md_alg = mbedtls_md_psa_alg_from_type(md_alg); + if (psa_md_alg == 0) { + return MBEDTLS_ERR_PK_BAD_INPUT_DATA; + } + psa_algorithm_t psa_alg; + if (mbedtls_rsa_get_padding_mode(mbedtls_pk_rsa(*pk)) == MBEDTLS_RSA_PKCS_V21) { + psa_alg = PSA_ALG_RSA_PSS(psa_md_alg); + } else { + psa_alg = PSA_ALG_RSA_PKCS1V15_SIGN(psa_md_alg); + } + + return mbedtls_pk_psa_rsa_sign_ext(psa_alg, pk->pk_ctx, hash, hash_len, + sig, sig_size, sig_len); +} +#else /* MBEDTLS_USE_PSA_CRYPTO */ +static int rsa_sign_wrap(mbedtls_pk_context *pk, mbedtls_md_type_t md_alg, + const unsigned char *hash, size_t hash_len, + unsigned char *sig, size_t sig_size, size_t *sig_len, + int (*f_rng)(void *, unsigned char *, size_t), void *p_rng) +{ + mbedtls_rsa_context *rsa = (mbedtls_rsa_context *) pk->pk_ctx; #if SIZE_MAX > UINT_MAX if (md_alg == MBEDTLS_MD_NONE && UINT_MAX < hash_len) { return MBEDTLS_ERR_PK_BAD_INPUT_DATA; } -#endif /* SIZE_MAX > UINT_MAX */ +#endif *sig_len = mbedtls_rsa_get_len(rsa); + if (sig_size < *sig_len) { + return MBEDTLS_ERR_PK_BUFFER_TOO_SMALL; + } - return mbedtls_rsa_pkcs1_sign(rsa, f_rng, p_rng, MBEDTLS_RSA_PRIVATE, - md_alg, (unsigned int) hash_len, hash, sig); + return mbedtls_rsa_pkcs1_sign(rsa, f_rng, p_rng, + md_alg, (unsigned int) hash_len, + hash, sig); } +#endif /* MBEDTLS_USE_PSA_CRYPTO */ -static int rsa_decrypt_wrap(void *ctx, +#if defined(MBEDTLS_USE_PSA_CRYPTO) +static int rsa_decrypt_wrap(mbedtls_pk_context *pk, const unsigned char *input, size_t ilen, unsigned char *output, size_t *olen, size_t osize, int (*f_rng)(void *, unsigned char *, size_t), void *p_rng) { - mbedtls_rsa_context *rsa = (mbedtls_rsa_context *) ctx; + mbedtls_rsa_context *rsa = (mbedtls_rsa_context *) pk->pk_ctx; + int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED; + psa_key_attributes_t attributes = PSA_KEY_ATTRIBUTES_INIT; + mbedtls_svc_key_id_t key_id = MBEDTLS_SVC_KEY_ID_INIT; + psa_algorithm_t psa_md_alg, decrypt_alg; + psa_status_t status; + int key_len; + unsigned char buf[MBEDTLS_PK_RSA_PRV_DER_MAX_BYTES]; + unsigned char *p = buf + sizeof(buf); + + ((void) f_rng); + ((void) p_rng); + + if (ilen != mbedtls_rsa_get_len(rsa)) { + return MBEDTLS_ERR_RSA_BAD_INPUT_DATA; + } + + key_len = mbedtls_rsa_write_key(rsa, buf, &p); + if (key_len <= 0) { + return MBEDTLS_ERR_PK_BAD_INPUT_DATA; + } + + psa_set_key_type(&attributes, PSA_KEY_TYPE_RSA_KEY_PAIR); + psa_set_key_usage_flags(&attributes, PSA_KEY_USAGE_DECRYPT); + if (mbedtls_rsa_get_padding_mode(rsa) == MBEDTLS_RSA_PKCS_V21) { + psa_md_alg = mbedtls_md_psa_alg_from_type((mbedtls_md_type_t) mbedtls_rsa_get_md_alg(rsa)); + decrypt_alg = PSA_ALG_RSA_OAEP(psa_md_alg); + } else { + decrypt_alg = PSA_ALG_RSA_PKCS1V15_CRYPT; + } + psa_set_key_algorithm(&attributes, decrypt_alg); + + status = psa_import_key(&attributes, + buf + sizeof(buf) - key_len, key_len, + &key_id); + if (status != PSA_SUCCESS) { + ret = PSA_PK_TO_MBEDTLS_ERR(status); + goto cleanup; + } + + status = psa_asymmetric_decrypt(key_id, decrypt_alg, + input, ilen, + NULL, 0, + output, osize, olen); + if (status != PSA_SUCCESS) { + ret = PSA_PK_RSA_TO_MBEDTLS_ERR(status); + goto cleanup; + } + + ret = 0; + +cleanup: + mbedtls_platform_zeroize(buf, sizeof(buf)); + status = psa_destroy_key(key_id); + if (ret == 0 && status != PSA_SUCCESS) { + ret = PSA_PK_TO_MBEDTLS_ERR(status); + } + + return ret; +} +#else /* MBEDTLS_USE_PSA_CRYPTO */ +static int rsa_decrypt_wrap(mbedtls_pk_context *pk, + const unsigned char *input, size_t ilen, + unsigned char *output, size_t *olen, size_t osize, + int (*f_rng)(void *, unsigned char *, size_t), void *p_rng) +{ + mbedtls_rsa_context *rsa = (mbedtls_rsa_context *) pk->pk_ctx; if (ilen != mbedtls_rsa_get_len(rsa)) { return MBEDTLS_ERR_RSA_BAD_INPUT_DATA; } return mbedtls_rsa_pkcs1_decrypt(rsa, f_rng, p_rng, - MBEDTLS_RSA_PRIVATE, olen, input, output, osize); + olen, input, output, osize); } +#endif /* MBEDTLS_USE_PSA_CRYPTO */ + +#if defined(MBEDTLS_USE_PSA_CRYPTO) +static int rsa_encrypt_wrap(mbedtls_pk_context *pk, + const unsigned char *input, size_t ilen, + unsigned char *output, size_t *olen, size_t osize, + int (*f_rng)(void *, unsigned char *, size_t), void *p_rng) +{ + mbedtls_rsa_context *rsa = (mbedtls_rsa_context *) pk->pk_ctx; + int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED; + psa_key_attributes_t attributes = PSA_KEY_ATTRIBUTES_INIT; + mbedtls_svc_key_id_t key_id = MBEDTLS_SVC_KEY_ID_INIT; + psa_algorithm_t psa_md_alg, psa_encrypt_alg; + psa_status_t status; + int key_len; + unsigned char buf[MBEDTLS_PK_RSA_PUB_DER_MAX_BYTES]; + unsigned char *p = buf + sizeof(buf); + + ((void) f_rng); + ((void) p_rng); + + if (mbedtls_rsa_get_len(rsa) > osize) { + return MBEDTLS_ERR_RSA_OUTPUT_TOO_LARGE; + } + + key_len = mbedtls_rsa_write_pubkey(rsa, buf, &p); + if (key_len <= 0) { + return MBEDTLS_ERR_PK_BAD_INPUT_DATA; + } + + psa_set_key_usage_flags(&attributes, PSA_KEY_USAGE_ENCRYPT); + if (mbedtls_rsa_get_padding_mode(rsa) == MBEDTLS_RSA_PKCS_V21) { + psa_md_alg = mbedtls_md_psa_alg_from_type((mbedtls_md_type_t) mbedtls_rsa_get_md_alg(rsa)); + psa_encrypt_alg = PSA_ALG_RSA_OAEP(psa_md_alg); + } else { + psa_encrypt_alg = PSA_ALG_RSA_PKCS1V15_CRYPT; + } + psa_set_key_algorithm(&attributes, psa_encrypt_alg); + psa_set_key_type(&attributes, PSA_KEY_TYPE_RSA_PUBLIC_KEY); + + status = psa_import_key(&attributes, + buf + sizeof(buf) - key_len, key_len, + &key_id); + if (status != PSA_SUCCESS) { + ret = PSA_PK_TO_MBEDTLS_ERR(status); + goto cleanup; + } + + status = psa_asymmetric_encrypt(key_id, psa_encrypt_alg, + input, ilen, + NULL, 0, + output, osize, olen); + if (status != PSA_SUCCESS) { + ret = PSA_PK_RSA_TO_MBEDTLS_ERR(status); + goto cleanup; + } + + ret = 0; -static int rsa_encrypt_wrap(void *ctx, +cleanup: + status = psa_destroy_key(key_id); + if (ret == 0 && status != PSA_SUCCESS) { + ret = PSA_PK_TO_MBEDTLS_ERR(status); + } + + return ret; +} +#else /* MBEDTLS_USE_PSA_CRYPTO */ +static int rsa_encrypt_wrap(mbedtls_pk_context *pk, const unsigned char *input, size_t ilen, unsigned char *output, size_t *olen, size_t osize, int (*f_rng)(void *, unsigned char *, size_t), void *p_rng) { - mbedtls_rsa_context *rsa = (mbedtls_rsa_context *) ctx; + mbedtls_rsa_context *rsa = (mbedtls_rsa_context *) pk->pk_ctx; *olen = mbedtls_rsa_get_len(rsa); if (*olen > osize) { return MBEDTLS_ERR_RSA_OUTPUT_TOO_LARGE; } - return mbedtls_rsa_pkcs1_encrypt(rsa, f_rng, p_rng, MBEDTLS_RSA_PUBLIC, + return mbedtls_rsa_pkcs1_encrypt(rsa, f_rng, p_rng, ilen, input, output); } +#endif /* MBEDTLS_USE_PSA_CRYPTO */ -static int rsa_check_pair_wrap(const void *pub, const void *prv) +static int rsa_check_pair_wrap(mbedtls_pk_context *pub, mbedtls_pk_context *prv, + int (*f_rng)(void *, unsigned char *, size_t), + void *p_rng) { - return mbedtls_rsa_check_pub_priv((const mbedtls_rsa_context *) pub, - (const mbedtls_rsa_context *) prv); + (void) f_rng; + (void) p_rng; + return mbedtls_rsa_check_pub_priv((const mbedtls_rsa_context *) pub->pk_ctx, + (const mbedtls_rsa_context *) prv->pk_ctx); } static void *rsa_alloc_wrap(void) @@ -165,7 +456,7 @@ static void *rsa_alloc_wrap(void) void *ctx = mbedtls_calloc(1, sizeof(mbedtls_rsa_context)); if (ctx != NULL) { - mbedtls_rsa_init((mbedtls_rsa_context *) ctx, 0, 0); + mbedtls_rsa_init((mbedtls_rsa_context *) ctx); } return ctx; @@ -177,44 +468,50 @@ static void rsa_free_wrap(void *ctx) mbedtls_free(ctx); } -static void rsa_debug(const void *ctx, mbedtls_pk_debug_item *items) +static void rsa_debug(mbedtls_pk_context *pk, mbedtls_pk_debug_item *items) { +#if defined(MBEDTLS_RSA_ALT) + /* Not supported */ + (void) pk; + (void) items; +#else + mbedtls_rsa_context *rsa = (mbedtls_rsa_context *) pk->pk_ctx; + items->type = MBEDTLS_PK_DEBUG_MPI; items->name = "rsa.N"; - items->value = &(((mbedtls_rsa_context *) ctx)->N); + items->value = &(rsa->N); items++; items->type = MBEDTLS_PK_DEBUG_MPI; items->name = "rsa.E"; - items->value = &(((mbedtls_rsa_context *) ctx)->E); + items->value = &(rsa->E); +#endif } const mbedtls_pk_info_t mbedtls_rsa_info = { - MBEDTLS_PK_RSA, - "RSA", - rsa_get_bitlen, - rsa_can_do, - rsa_verify_wrap, - rsa_sign_wrap, + .type = MBEDTLS_PK_RSA, + .name = "RSA", + .get_bitlen = rsa_get_bitlen, + .can_do = rsa_can_do, + .verify_func = rsa_verify_wrap, + .sign_func = rsa_sign_wrap, #if defined(MBEDTLS_ECDSA_C) && defined(MBEDTLS_ECP_RESTARTABLE) - NULL, - NULL, -#endif - rsa_decrypt_wrap, - rsa_encrypt_wrap, - rsa_check_pair_wrap, - rsa_alloc_wrap, - rsa_free_wrap, -#if defined(MBEDTLS_ECDSA_C) && defined(MBEDTLS_ECP_RESTARTABLE) - NULL, - NULL, -#endif - rsa_debug, + .verify_rs_func = NULL, + .sign_rs_func = NULL, + .rs_alloc_func = NULL, + .rs_free_func = NULL, +#endif /* MBEDTLS_ECDSA_C && MBEDTLS_ECP_RESTARTABLE */ + .decrypt_func = rsa_decrypt_wrap, + .encrypt_func = rsa_encrypt_wrap, + .check_pair_func = rsa_check_pair_wrap, + .ctx_alloc_func = rsa_alloc_wrap, + .ctx_free_func = rsa_free_wrap, + .debug_func = rsa_debug, }; #endif /* MBEDTLS_RSA_C */ -#if defined(MBEDTLS_ECP_C) +#if defined(MBEDTLS_PK_HAVE_ECC_KEYS) /* * Generic EC key */ @@ -225,70 +522,313 @@ static int eckey_can_do(mbedtls_pk_type_t type) type == MBEDTLS_PK_ECDSA; } -static size_t eckey_get_bitlen(const void *ctx) +static size_t eckey_get_bitlen(mbedtls_pk_context *pk) { - return ((mbedtls_ecp_keypair *) ctx)->grp.pbits; +#if defined(MBEDTLS_PK_USE_PSA_EC_DATA) + return pk->ec_bits; +#else /* MBEDTLS_PK_USE_PSA_EC_DATA */ + mbedtls_ecp_keypair *ecp = (mbedtls_ecp_keypair *) pk->pk_ctx; + return ecp->grp.pbits; +#endif /* MBEDTLS_PK_USE_PSA_EC_DATA */ } -#if defined(MBEDTLS_ECDSA_C) -/* Forward declarations */ -static int ecdsa_verify_wrap(void *ctx, mbedtls_md_type_t md_alg, +#if defined(MBEDTLS_PK_CAN_ECDSA_VERIFY) +#if defined(MBEDTLS_USE_PSA_CRYPTO) +/* Common helper for ECDSA verify using PSA functions. */ +static int ecdsa_verify_psa(unsigned char *key, size_t key_len, + psa_ecc_family_t curve, size_t curve_bits, + const unsigned char *hash, size_t hash_len, + const unsigned char *sig, size_t sig_len) +{ + int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED; + psa_key_attributes_t attributes = PSA_KEY_ATTRIBUTES_INIT; + mbedtls_svc_key_id_t key_id = MBEDTLS_SVC_KEY_ID_INIT; + psa_algorithm_t psa_sig_md = PSA_ALG_ECDSA_ANY; + size_t signature_len = PSA_ECDSA_SIGNATURE_SIZE(curve_bits); + size_t converted_sig_len; + unsigned char extracted_sig[PSA_VENDOR_ECDSA_SIGNATURE_MAX_SIZE]; + unsigned char *p; + psa_status_t status; + + if (curve == 0) { + return MBEDTLS_ERR_PK_BAD_INPUT_DATA; + } + + psa_set_key_type(&attributes, PSA_KEY_TYPE_ECC_PUBLIC_KEY(curve)); + psa_set_key_usage_flags(&attributes, PSA_KEY_USAGE_VERIFY_HASH); + psa_set_key_algorithm(&attributes, psa_sig_md); + + status = psa_import_key(&attributes, key, key_len, &key_id); + if (status != PSA_SUCCESS) { + ret = PSA_PK_TO_MBEDTLS_ERR(status); + goto cleanup; + } + + if (signature_len > sizeof(extracted_sig)) { + ret = MBEDTLS_ERR_PK_BAD_INPUT_DATA; + goto cleanup; + } + + p = (unsigned char *) sig; + ret = mbedtls_ecdsa_der_to_raw(curve_bits, p, sig_len, extracted_sig, + sizeof(extracted_sig), &converted_sig_len); + if (ret != 0) { + goto cleanup; + } + + if (converted_sig_len != signature_len) { + ret = MBEDTLS_ERR_PK_BAD_INPUT_DATA; + goto cleanup; + } + + status = psa_verify_hash(key_id, psa_sig_md, hash, hash_len, + extracted_sig, signature_len); + if (status != PSA_SUCCESS) { + ret = PSA_PK_ECDSA_TO_MBEDTLS_ERR(status); + goto cleanup; + } + + ret = 0; + +cleanup: + status = psa_destroy_key(key_id); + if (ret == 0 && status != PSA_SUCCESS) { + ret = PSA_PK_TO_MBEDTLS_ERR(status); + } + + return ret; +} + +static int ecdsa_opaque_verify_wrap(mbedtls_pk_context *pk, + mbedtls_md_type_t md_alg, + const unsigned char *hash, size_t hash_len, + const unsigned char *sig, size_t sig_len) +{ + (void) md_alg; + unsigned char key[MBEDTLS_PK_MAX_EC_PUBKEY_RAW_LEN]; + size_t key_len; + psa_key_attributes_t key_attr = PSA_KEY_ATTRIBUTES_INIT; + psa_ecc_family_t curve; + size_t curve_bits; + psa_status_t status; + + status = psa_get_key_attributes(pk->priv_id, &key_attr); + if (status != PSA_SUCCESS) { + return PSA_PK_ECDSA_TO_MBEDTLS_ERR(status); + } + curve = PSA_KEY_TYPE_ECC_GET_FAMILY(psa_get_key_type(&key_attr)); + curve_bits = psa_get_key_bits(&key_attr); + psa_reset_key_attributes(&key_attr); + + status = psa_export_public_key(pk->priv_id, key, sizeof(key), &key_len); + if (status != PSA_SUCCESS) { + return PSA_PK_ECDSA_TO_MBEDTLS_ERR(status); + } + + return ecdsa_verify_psa(key, key_len, curve, curve_bits, + hash, hash_len, sig, sig_len); +} + +#if defined(MBEDTLS_PK_USE_PSA_EC_DATA) +static int ecdsa_verify_wrap(mbedtls_pk_context *pk, + mbedtls_md_type_t md_alg, const unsigned char *hash, size_t hash_len, - const unsigned char *sig, size_t sig_len); + const unsigned char *sig, size_t sig_len) +{ + (void) md_alg; + psa_ecc_family_t curve = pk->ec_family; + size_t curve_bits = pk->ec_bits; -static int ecdsa_sign_wrap(void *ctx, mbedtls_md_type_t md_alg, - const unsigned char *hash, size_t hash_len, - unsigned char *sig, size_t *sig_len, - int (*f_rng)(void *, unsigned char *, size_t), void *p_rng); + return ecdsa_verify_psa(pk->pub_raw, pk->pub_raw_len, curve, curve_bits, + hash, hash_len, sig, sig_len); +} +#else /* MBEDTLS_PK_USE_PSA_EC_DATA */ +static int ecdsa_verify_wrap(mbedtls_pk_context *pk, + mbedtls_md_type_t md_alg, + const unsigned char *hash, size_t hash_len, + const unsigned char *sig, size_t sig_len) +{ + (void) md_alg; + int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED; + mbedtls_ecp_keypair *ctx = pk->pk_ctx; + unsigned char key[MBEDTLS_PSA_MAX_EC_PUBKEY_LENGTH]; + size_t key_len; + size_t curve_bits; + psa_ecc_family_t curve = mbedtls_ecc_group_to_psa(ctx->grp.id, &curve_bits); + + ret = mbedtls_ecp_point_write_binary(&ctx->grp, &ctx->Q, + MBEDTLS_ECP_PF_UNCOMPRESSED, + &key_len, key, sizeof(key)); + if (ret != 0) { + return ret; + } -static int eckey_verify_wrap(void *ctx, mbedtls_md_type_t md_alg, + return ecdsa_verify_psa(key, key_len, curve, curve_bits, + hash, hash_len, sig, sig_len); +} +#endif /* MBEDTLS_PK_USE_PSA_EC_DATA */ +#else /* MBEDTLS_USE_PSA_CRYPTO */ +static int ecdsa_verify_wrap(mbedtls_pk_context *pk, mbedtls_md_type_t md_alg, const unsigned char *hash, size_t hash_len, const unsigned char *sig, size_t sig_len) { int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED; - mbedtls_ecdsa_context ecdsa; + ((void) md_alg); - mbedtls_ecdsa_init(&ecdsa); + ret = mbedtls_ecdsa_read_signature((mbedtls_ecdsa_context *) pk->pk_ctx, + hash, hash_len, sig, sig_len); - if ((ret = mbedtls_ecdsa_from_keypair(&ecdsa, ctx)) == 0) { - ret = ecdsa_verify_wrap(&ecdsa, md_alg, hash, hash_len, sig, sig_len); + if (ret == MBEDTLS_ERR_ECP_SIG_LEN_MISMATCH) { + return MBEDTLS_ERR_PK_SIG_LEN_MISMATCH; } - mbedtls_ecdsa_free(&ecdsa); + return ret; +} +#endif /* MBEDTLS_USE_PSA_CRYPTO */ +#endif /* MBEDTLS_PK_CAN_ECDSA_VERIFY */ + +#if defined(MBEDTLS_PK_CAN_ECDSA_SIGN) +#if defined(MBEDTLS_USE_PSA_CRYPTO) +/* Common helper for ECDSA sign using PSA functions. + * Instead of extracting key's properties in order to check which kind of ECDSA + * signature it supports, we try both deterministic and non-deterministic. + */ +static int ecdsa_sign_psa(mbedtls_svc_key_id_t key_id, mbedtls_md_type_t md_alg, + const unsigned char *hash, size_t hash_len, + unsigned char *sig, size_t sig_size, size_t *sig_len) +{ + int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED; + psa_status_t status; + psa_key_attributes_t key_attr = PSA_KEY_ATTRIBUTES_INIT; + size_t key_bits = 0; + + status = psa_get_key_attributes(key_id, &key_attr); + if (status != PSA_SUCCESS) { + return PSA_PK_ECDSA_TO_MBEDTLS_ERR(status); + } + key_bits = psa_get_key_bits(&key_attr); + psa_reset_key_attributes(&key_attr); + + status = psa_sign_hash(key_id, + PSA_ALG_DETERMINISTIC_ECDSA(mbedtls_md_psa_alg_from_type(md_alg)), + hash, hash_len, sig, sig_size, sig_len); + if (status == PSA_SUCCESS) { + goto done; + } else if (status != PSA_ERROR_NOT_PERMITTED) { + return PSA_PK_ECDSA_TO_MBEDTLS_ERR(status); + } + + status = psa_sign_hash(key_id, + PSA_ALG_ECDSA(mbedtls_md_psa_alg_from_type(md_alg)), + hash, hash_len, sig, sig_size, sig_len); + if (status != PSA_SUCCESS) { + return PSA_PK_ECDSA_TO_MBEDTLS_ERR(status); + } + +done: + ret = mbedtls_ecdsa_raw_to_der(key_bits, sig, *sig_len, sig, sig_size, sig_len); return ret; } -static int eckey_sign_wrap(void *ctx, mbedtls_md_type_t md_alg, +static int ecdsa_opaque_sign_wrap(mbedtls_pk_context *pk, + mbedtls_md_type_t md_alg, + const unsigned char *hash, size_t hash_len, + unsigned char *sig, size_t sig_size, + size_t *sig_len, + int (*f_rng)(void *, unsigned char *, size_t), + void *p_rng) +{ + ((void) f_rng); + ((void) p_rng); + + return ecdsa_sign_psa(pk->priv_id, md_alg, hash, hash_len, sig, sig_size, + sig_len); +} + +#if defined(MBEDTLS_PK_USE_PSA_EC_DATA) +/* When PK_USE_PSA_EC_DATA is defined opaque and non-opaque keys end up + * using the same function. */ +#define ecdsa_sign_wrap ecdsa_opaque_sign_wrap +#else /* MBEDTLS_PK_USE_PSA_EC_DATA */ +static int ecdsa_sign_wrap(mbedtls_pk_context *pk, mbedtls_md_type_t md_alg, const unsigned char *hash, size_t hash_len, - unsigned char *sig, size_t *sig_len, + unsigned char *sig, size_t sig_size, size_t *sig_len, int (*f_rng)(void *, unsigned char *, size_t), void *p_rng) { int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED; - mbedtls_ecdsa_context ecdsa; + mbedtls_svc_key_id_t key_id = MBEDTLS_SVC_KEY_ID_INIT; + psa_status_t status; + mbedtls_ecp_keypair *ctx = pk->pk_ctx; + psa_key_attributes_t attributes = PSA_KEY_ATTRIBUTES_INIT; + unsigned char buf[MBEDTLS_PSA_MAX_EC_KEY_PAIR_LENGTH]; + size_t curve_bits; + psa_ecc_family_t curve = + mbedtls_ecc_group_to_psa(ctx->grp.id, &curve_bits); + size_t key_len = PSA_BITS_TO_BYTES(curve_bits); + psa_algorithm_t psa_hash = mbedtls_md_psa_alg_from_type(md_alg); + psa_algorithm_t psa_sig_md = MBEDTLS_PK_PSA_ALG_ECDSA_MAYBE_DET(psa_hash); + ((void) f_rng); + ((void) p_rng); - mbedtls_ecdsa_init(&ecdsa); + if (curve == 0) { + return MBEDTLS_ERR_PK_BAD_INPUT_DATA; + } + + if (key_len > sizeof(buf)) { + return MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED; + } + ret = mbedtls_mpi_write_binary(&ctx->d, buf, key_len); + if (ret != 0) { + goto cleanup; + } - if ((ret = mbedtls_ecdsa_from_keypair(&ecdsa, ctx)) == 0) { - ret = ecdsa_sign_wrap(&ecdsa, md_alg, hash, hash_len, sig, sig_len, - f_rng, p_rng); + psa_set_key_type(&attributes, PSA_KEY_TYPE_ECC_KEY_PAIR(curve)); + psa_set_key_usage_flags(&attributes, PSA_KEY_USAGE_SIGN_HASH); + psa_set_key_algorithm(&attributes, psa_sig_md); + + status = psa_import_key(&attributes, buf, key_len, &key_id); + if (status != PSA_SUCCESS) { + ret = PSA_PK_TO_MBEDTLS_ERR(status); + goto cleanup; } - mbedtls_ecdsa_free(&ecdsa); + ret = ecdsa_sign_psa(key_id, md_alg, hash, hash_len, sig, sig_size, sig_len); + +cleanup: + mbedtls_platform_zeroize(buf, sizeof(buf)); + status = psa_destroy_key(key_id); + if (ret == 0 && status != PSA_SUCCESS) { + ret = PSA_PK_TO_MBEDTLS_ERR(status); + } return ret; } +#endif /* MBEDTLS_PK_USE_PSA_EC_DATA */ +#else /* MBEDTLS_USE_PSA_CRYPTO */ +static int ecdsa_sign_wrap(mbedtls_pk_context *pk, mbedtls_md_type_t md_alg, + const unsigned char *hash, size_t hash_len, + unsigned char *sig, size_t sig_size, size_t *sig_len, + int (*f_rng)(void *, unsigned char *, size_t), void *p_rng) +{ + return mbedtls_ecdsa_write_signature((mbedtls_ecdsa_context *) pk->pk_ctx, + md_alg, hash, hash_len, + sig, sig_size, sig_len, + f_rng, p_rng); +} +#endif /* MBEDTLS_USE_PSA_CRYPTO */ +#endif /* MBEDTLS_PK_CAN_ECDSA_SIGN */ -#if defined(MBEDTLS_ECP_RESTARTABLE) +#if defined(MBEDTLS_ECDSA_C) && defined(MBEDTLS_ECP_RESTARTABLE) /* Forward declarations */ -static int ecdsa_verify_rs_wrap(void *ctx, mbedtls_md_type_t md_alg, +static int ecdsa_verify_rs_wrap(mbedtls_pk_context *ctx, mbedtls_md_type_t md_alg, const unsigned char *hash, size_t hash_len, const unsigned char *sig, size_t sig_len, void *rs_ctx); -static int ecdsa_sign_rs_wrap(void *ctx, mbedtls_md_type_t md_alg, +static int ecdsa_sign_rs_wrap(mbedtls_pk_context *ctx, mbedtls_md_type_t md_alg, const unsigned char *hash, size_t hash_len, - unsigned char *sig, size_t *sig_len, + unsigned char *sig, size_t sig_size, size_t *sig_len, int (*f_rng)(void *, unsigned char *, size_t), void *p_rng, void *rs_ctx); @@ -333,7 +873,7 @@ static void eckey_rs_free(void *ctx) mbedtls_free(ctx); } -static int eckey_verify_rs_wrap(void *ctx, mbedtls_md_type_t md_alg, +static int eckey_verify_rs_wrap(mbedtls_pk_context *pk, mbedtls_md_type_t md_alg, const unsigned char *hash, size_t hash_len, const unsigned char *sig, size_t sig_len, void *rs_ctx) @@ -348,52 +888,196 @@ static int eckey_verify_rs_wrap(void *ctx, mbedtls_md_type_t md_alg, /* set up our own sub-context if needed (that is, on first run) */ if (rs->ecdsa_ctx.grp.pbits == 0) { - MBEDTLS_MPI_CHK(mbedtls_ecdsa_from_keypair(&rs->ecdsa_ctx, ctx)); + MBEDTLS_MPI_CHK(mbedtls_ecdsa_from_keypair(&rs->ecdsa_ctx, pk->pk_ctx)); } - MBEDTLS_MPI_CHK(ecdsa_verify_rs_wrap(&rs->ecdsa_ctx, + MBEDTLS_MPI_CHK(ecdsa_verify_rs_wrap(pk, md_alg, hash, hash_len, sig, sig_len, &rs->ecdsa_rs)); -cleanup: - return ret; -} +cleanup: + return ret; +} + +static int eckey_sign_rs_wrap(mbedtls_pk_context *pk, mbedtls_md_type_t md_alg, + const unsigned char *hash, size_t hash_len, + unsigned char *sig, size_t sig_size, size_t *sig_len, + int (*f_rng)(void *, unsigned char *, size_t), void *p_rng, + void *rs_ctx) +{ + int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED; + eckey_restart_ctx *rs = rs_ctx; + + /* Should never happen */ + if (rs == NULL) { + return MBEDTLS_ERR_PK_BAD_INPUT_DATA; + } + + /* set up our own sub-context if needed (that is, on first run) */ + if (rs->ecdsa_ctx.grp.pbits == 0) { + MBEDTLS_MPI_CHK(mbedtls_ecdsa_from_keypair(&rs->ecdsa_ctx, pk->pk_ctx)); + } + + MBEDTLS_MPI_CHK(ecdsa_sign_rs_wrap(pk, md_alg, + hash, hash_len, sig, sig_size, sig_len, + f_rng, p_rng, &rs->ecdsa_rs)); + +cleanup: + return ret; +} +#endif /* MBEDTLS_ECDSA_C && MBEDTLS_ECP_RESTARTABLE */ + +#if defined(MBEDTLS_USE_PSA_CRYPTO) +#if defined(MBEDTLS_PK_USE_PSA_EC_DATA) +static int eckey_check_pair_psa(mbedtls_pk_context *pub, mbedtls_pk_context *prv) +{ + psa_status_t status; + int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED; + uint8_t prv_key_buf[MBEDTLS_PSA_MAX_EC_PUBKEY_LENGTH]; + size_t prv_key_len; + mbedtls_svc_key_id_t key_id = prv->priv_id; + + status = psa_export_public_key(key_id, prv_key_buf, sizeof(prv_key_buf), + &prv_key_len); + ret = PSA_PK_TO_MBEDTLS_ERR(status); + if (ret != 0) { + return ret; + } + + if (memcmp(prv_key_buf, pub->pub_raw, pub->pub_raw_len) != 0) { + return MBEDTLS_ERR_PK_BAD_INPUT_DATA; + } + + return 0; +} +#else /* MBEDTLS_PK_USE_PSA_EC_DATA */ +static int eckey_check_pair_psa(mbedtls_pk_context *pub, mbedtls_pk_context *prv) +{ + psa_status_t status; + int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED; + uint8_t prv_key_buf[MBEDTLS_PSA_MAX_EC_PUBKEY_LENGTH]; + size_t prv_key_len; + psa_status_t destruction_status; + mbedtls_svc_key_id_t key_id = MBEDTLS_SVC_KEY_ID_INIT; + psa_key_attributes_t key_attr = PSA_KEY_ATTRIBUTES_INIT; + uint8_t pub_key_buf[MBEDTLS_PSA_MAX_EC_PUBKEY_LENGTH]; + size_t pub_key_len; + size_t curve_bits; + const psa_ecc_family_t curve = + mbedtls_ecc_group_to_psa(mbedtls_pk_ec_ro(*prv)->grp.id, &curve_bits); + const size_t curve_bytes = PSA_BITS_TO_BYTES(curve_bits); + + if (curve == 0) { + return MBEDTLS_ERR_PK_BAD_INPUT_DATA; + } + + psa_set_key_type(&key_attr, PSA_KEY_TYPE_ECC_KEY_PAIR(curve)); + psa_set_key_usage_flags(&key_attr, PSA_KEY_USAGE_EXPORT); + + ret = mbedtls_mpi_write_binary(&mbedtls_pk_ec_ro(*prv)->d, + prv_key_buf, curve_bytes); + if (ret != 0) { + mbedtls_platform_zeroize(prv_key_buf, sizeof(prv_key_buf)); + return ret; + } + + status = psa_import_key(&key_attr, prv_key_buf, curve_bytes, &key_id); + mbedtls_platform_zeroize(prv_key_buf, sizeof(prv_key_buf)); + ret = PSA_PK_TO_MBEDTLS_ERR(status); + if (ret != 0) { + return ret; + } -static int eckey_sign_rs_wrap(void *ctx, mbedtls_md_type_t md_alg, - const unsigned char *hash, size_t hash_len, - unsigned char *sig, size_t *sig_len, - int (*f_rng)(void *, unsigned char *, size_t), void *p_rng, - void *rs_ctx) -{ - int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED; - eckey_restart_ctx *rs = rs_ctx; + // From now on prv_key_buf is used to store the public key of prv. + status = psa_export_public_key(key_id, prv_key_buf, sizeof(prv_key_buf), + &prv_key_len); + ret = PSA_PK_TO_MBEDTLS_ERR(status); + destruction_status = psa_destroy_key(key_id); + if (ret != 0) { + return ret; + } else if (destruction_status != PSA_SUCCESS) { + return PSA_PK_TO_MBEDTLS_ERR(destruction_status); + } - /* Should never happen */ - if (rs == NULL) { - return MBEDTLS_ERR_PK_BAD_INPUT_DATA; + ret = mbedtls_ecp_point_write_binary(&mbedtls_pk_ec_rw(*pub)->grp, + &mbedtls_pk_ec_rw(*pub)->Q, + MBEDTLS_ECP_PF_UNCOMPRESSED, + &pub_key_len, pub_key_buf, + sizeof(pub_key_buf)); + if (ret != 0) { + return ret; } - /* set up our own sub-context if needed (that is, on first run) */ - if (rs->ecdsa_ctx.grp.pbits == 0) { - MBEDTLS_MPI_CHK(mbedtls_ecdsa_from_keypair(&rs->ecdsa_ctx, ctx)); + if (memcmp(prv_key_buf, pub_key_buf, curve_bytes) != 0) { + return MBEDTLS_ERR_PK_BAD_INPUT_DATA; } - MBEDTLS_MPI_CHK(ecdsa_sign_rs_wrap(&rs->ecdsa_ctx, md_alg, - hash, hash_len, sig, sig_len, - f_rng, p_rng, &rs->ecdsa_rs)); + return 0; +} +#endif /* MBEDTLS_PK_USE_PSA_EC_DATA */ -cleanup: - return ret; +static int eckey_check_pair_wrap(mbedtls_pk_context *pub, mbedtls_pk_context *prv, + int (*f_rng)(void *, unsigned char *, size_t), + void *p_rng) +{ + (void) f_rng; + (void) p_rng; + return eckey_check_pair_psa(pub, prv); } -#endif /* MBEDTLS_ECP_RESTARTABLE */ -#endif /* MBEDTLS_ECDSA_C */ +#else /* MBEDTLS_USE_PSA_CRYPTO */ +static int eckey_check_pair_wrap(mbedtls_pk_context *pub, mbedtls_pk_context *prv, + int (*f_rng)(void *, unsigned char *, size_t), + void *p_rng) +{ + return mbedtls_ecp_check_pub_priv((const mbedtls_ecp_keypair *) pub->pk_ctx, + (const mbedtls_ecp_keypair *) prv->pk_ctx, + f_rng, p_rng); +} +#endif /* MBEDTLS_USE_PSA_CRYPTO */ -static int eckey_check_pair(const void *pub, const void *prv) +#if defined(MBEDTLS_USE_PSA_CRYPTO) +#if defined(MBEDTLS_PK_USE_PSA_EC_DATA) +/* When PK_USE_PSA_EC_DATA is defined opaque and non-opaque keys end up + * using the same function. */ +#define ecdsa_opaque_check_pair_wrap eckey_check_pair_wrap +#else /* MBEDTLS_PK_USE_PSA_EC_DATA */ +static int ecdsa_opaque_check_pair_wrap(mbedtls_pk_context *pub, + mbedtls_pk_context *prv, + int (*f_rng)(void *, unsigned char *, size_t), + void *p_rng) { - return mbedtls_ecp_check_pub_priv((const mbedtls_ecp_keypair *) pub, - (const mbedtls_ecp_keypair *) prv); + psa_status_t status; + uint8_t exp_pub_key[MBEDTLS_PK_MAX_EC_PUBKEY_RAW_LEN]; + size_t exp_pub_key_len = 0; + uint8_t pub_key[MBEDTLS_PK_MAX_EC_PUBKEY_RAW_LEN]; + size_t pub_key_len = 0; + int ret; + (void) f_rng; + (void) p_rng; + + status = psa_export_public_key(prv->priv_id, exp_pub_key, sizeof(exp_pub_key), + &exp_pub_key_len); + if (status != PSA_SUCCESS) { + ret = psa_pk_status_to_mbedtls(status); + return ret; + } + ret = mbedtls_ecp_point_write_binary(&(mbedtls_pk_ec_ro(*pub)->grp), + &(mbedtls_pk_ec_ro(*pub)->Q), + MBEDTLS_ECP_PF_UNCOMPRESSED, + &pub_key_len, pub_key, sizeof(pub_key)); + if (ret != 0) { + return ret; + } + if ((exp_pub_key_len != pub_key_len) || + memcmp(exp_pub_key, pub_key, exp_pub_key_len)) { + return MBEDTLS_ERR_PK_BAD_INPUT_DATA; + } + return 0; } +#endif /* MBEDTLS_PK_USE_PSA_EC_DATA */ +#endif /* MBEDTLS_USE_PSA_CRYPTO */ +#if !defined(MBEDTLS_PK_USE_PSA_EC_DATA) static void *eckey_alloc_wrap(void) { void *ctx = mbedtls_calloc(1, sizeof(mbedtls_ecp_keypair)); @@ -410,40 +1094,54 @@ static void eckey_free_wrap(void *ctx) mbedtls_ecp_keypair_free((mbedtls_ecp_keypair *) ctx); mbedtls_free(ctx); } +#endif /* MBEDTLS_PK_USE_PSA_EC_DATA */ -static void eckey_debug(const void *ctx, mbedtls_pk_debug_item *items) +static void eckey_debug(mbedtls_pk_context *pk, mbedtls_pk_debug_item *items) { +#if defined(MBEDTLS_PK_USE_PSA_EC_DATA) + items->type = MBEDTLS_PK_DEBUG_PSA_EC; + items->name = "eckey.Q"; + items->value = pk; +#else /* MBEDTLS_PK_USE_PSA_EC_DATA */ + mbedtls_ecp_keypair *ecp = (mbedtls_ecp_keypair *) pk->pk_ctx; items->type = MBEDTLS_PK_DEBUG_ECP; items->name = "eckey.Q"; - items->value = &(((mbedtls_ecp_keypair *) ctx)->Q); + items->value = &(ecp->Q); +#endif /* MBEDTLS_PK_USE_PSA_EC_DATA */ } const mbedtls_pk_info_t mbedtls_eckey_info = { - MBEDTLS_PK_ECKEY, - "EC", - eckey_get_bitlen, - eckey_can_do, -#if defined(MBEDTLS_ECDSA_C) - eckey_verify_wrap, - eckey_sign_wrap, -#if defined(MBEDTLS_ECP_RESTARTABLE) - eckey_verify_rs_wrap, - eckey_sign_rs_wrap, -#endif -#else /* MBEDTLS_ECDSA_C */ - NULL, - NULL, -#endif /* MBEDTLS_ECDSA_C */ - NULL, - NULL, - eckey_check_pair, - eckey_alloc_wrap, - eckey_free_wrap, + .type = MBEDTLS_PK_ECKEY, + .name = "EC", + .get_bitlen = eckey_get_bitlen, + .can_do = eckey_can_do, +#if defined(MBEDTLS_PK_CAN_ECDSA_VERIFY) + .verify_func = ecdsa_verify_wrap, /* Compatible key structures */ +#else /* MBEDTLS_PK_CAN_ECDSA_VERIFY */ + .verify_func = NULL, +#endif /* MBEDTLS_PK_CAN_ECDSA_VERIFY */ +#if defined(MBEDTLS_PK_CAN_ECDSA_SIGN) + .sign_func = ecdsa_sign_wrap, /* Compatible key structures */ +#else /* MBEDTLS_PK_CAN_ECDSA_VERIFY */ + .sign_func = NULL, +#endif /* MBEDTLS_PK_CAN_ECDSA_VERIFY */ #if defined(MBEDTLS_ECDSA_C) && defined(MBEDTLS_ECP_RESTARTABLE) - eckey_rs_alloc, - eckey_rs_free, -#endif - eckey_debug, + .verify_rs_func = eckey_verify_rs_wrap, + .sign_rs_func = eckey_sign_rs_wrap, + .rs_alloc_func = eckey_rs_alloc, + .rs_free_func = eckey_rs_free, +#endif /* MBEDTLS_ECDSA_C && MBEDTLS_ECP_RESTARTABLE */ + .decrypt_func = NULL, + .encrypt_func = NULL, + .check_pair_func = eckey_check_pair_wrap, +#if defined(MBEDTLS_PK_USE_PSA_EC_DATA) + .ctx_alloc_func = NULL, + .ctx_free_func = NULL, +#else /* MBEDTLS_PK_USE_PSA_EC_DATA */ + .ctx_alloc_func = eckey_alloc_wrap, + .ctx_free_func = eckey_free_wrap, +#endif /* MBEDTLS_PK_USE_PSA_EC_DATA */ + .debug_func = eckey_debug, }; /* @@ -456,205 +1154,37 @@ static int eckeydh_can_do(mbedtls_pk_type_t type) } const mbedtls_pk_info_t mbedtls_eckeydh_info = { - MBEDTLS_PK_ECKEY_DH, - "EC_DH", - eckey_get_bitlen, /* Same underlying key structure */ - eckeydh_can_do, - NULL, - NULL, -#if defined(MBEDTLS_ECDSA_C) && defined(MBEDTLS_ECP_RESTARTABLE) - NULL, - NULL, -#endif - NULL, - NULL, - eckey_check_pair, - eckey_alloc_wrap, /* Same underlying key structure */ - eckey_free_wrap, /* Same underlying key structure */ + .type = MBEDTLS_PK_ECKEY_DH, + .name = "EC_DH", + .get_bitlen = eckey_get_bitlen, /* Same underlying key structure */ + .can_do = eckeydh_can_do, + .verify_func = NULL, + .sign_func = NULL, #if defined(MBEDTLS_ECDSA_C) && defined(MBEDTLS_ECP_RESTARTABLE) - NULL, - NULL, -#endif - eckey_debug, /* Same underlying key structure */ + .verify_rs_func = NULL, + .sign_rs_func = NULL, +#endif /* MBEDTLS_ECDSA_C && MBEDTLS_ECP_RESTARTABLE */ + .decrypt_func = NULL, + .encrypt_func = NULL, + .check_pair_func = eckey_check_pair_wrap, +#if defined(MBEDTLS_PK_USE_PSA_EC_DATA) + .ctx_alloc_func = NULL, + .ctx_free_func = NULL, +#else /* MBEDTLS_PK_USE_PSA_EC_DATA */ + .ctx_alloc_func = eckey_alloc_wrap, /* Same underlying key structure */ + .ctx_free_func = eckey_free_wrap, /* Same underlying key structure */ +#endif /* MBEDTLS_PK_USE_PSA_EC_DATA */ + .debug_func = eckey_debug, /* Same underlying key structure */ }; -#endif /* MBEDTLS_ECP_C */ -#if defined(MBEDTLS_ECDSA_C) +#if defined(MBEDTLS_PK_CAN_ECDSA_SOME) static int ecdsa_can_do(mbedtls_pk_type_t type) { return type == MBEDTLS_PK_ECDSA; } -#if defined(MBEDTLS_USE_PSA_CRYPTO) -/* - * An ASN.1 encoded signature is a sequence of two ASN.1 integers. Parse one of - * those integers and convert it to the fixed-length encoding expected by PSA. - */ -static int extract_ecdsa_sig_int(unsigned char **from, const unsigned char *end, - unsigned char *to, size_t to_len) -{ - int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED; - size_t unpadded_len, padding_len; - - if ((ret = mbedtls_asn1_get_tag(from, end, &unpadded_len, - MBEDTLS_ASN1_INTEGER)) != 0) { - return ret; - } - - while (unpadded_len > 0 && **from == 0x00) { - (*from)++; - unpadded_len--; - } - - if (unpadded_len > to_len || unpadded_len == 0) { - return MBEDTLS_ERR_ASN1_LENGTH_MISMATCH; - } - - padding_len = to_len - unpadded_len; - memset(to, 0x00, padding_len); - memcpy(to + padding_len, *from, unpadded_len); - (*from) += unpadded_len; - - return 0; -} - -/* - * Convert a signature from an ASN.1 sequence of two integers - * to a raw {r,s} buffer. Note: the provided sig buffer must be at least - * twice as big as int_size. - */ -static int extract_ecdsa_sig(unsigned char **p, const unsigned char *end, - unsigned char *sig, size_t int_size) -{ - int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED; - size_t tmp_size; - - if ((ret = mbedtls_asn1_get_tag(p, end, &tmp_size, - MBEDTLS_ASN1_CONSTRUCTED | MBEDTLS_ASN1_SEQUENCE)) != 0) { - return ret; - } - - /* Extract r */ - if ((ret = extract_ecdsa_sig_int(p, end, sig, int_size)) != 0) { - return ret; - } - /* Extract s */ - if ((ret = extract_ecdsa_sig_int(p, end, sig + int_size, int_size)) != 0) { - return ret; - } - - return 0; -} - -static int ecdsa_verify_wrap(void *ctx_arg, mbedtls_md_type_t md_alg, - const unsigned char *hash, size_t hash_len, - const unsigned char *sig, size_t sig_len) -{ - mbedtls_ecdsa_context *ctx = ctx_arg; - int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED; - psa_key_attributes_t attributes = PSA_KEY_ATTRIBUTES_INIT; - psa_key_id_t key_id = 0; - psa_status_t status; - mbedtls_pk_context key; - int key_len; - /* see ECP_PUB_DER_MAX_BYTES in pkwrite.c */ - unsigned char buf[30 + 2 * MBEDTLS_ECP_MAX_BYTES]; - unsigned char *p; - mbedtls_pk_info_t pk_info = mbedtls_eckey_info; - psa_algorithm_t psa_sig_md = PSA_ALG_ECDSA_ANY; - size_t curve_bits; - psa_ecc_family_t curve = - mbedtls_ecc_group_to_psa(ctx->grp.id, &curve_bits); - const size_t signature_part_size = (ctx->grp.nbits + 7) / 8; - ((void) md_alg); - - if (curve == 0) { - return MBEDTLS_ERR_PK_BAD_INPUT_DATA; - } - - /* mbedtls_pk_write_pubkey() expects a full PK context; - * re-construct one to make it happy */ - key.pk_info = &pk_info; - key.pk_ctx = ctx; - p = buf + sizeof(buf); - key_len = mbedtls_pk_write_pubkey(&p, buf, &key); - if (key_len <= 0) { - return MBEDTLS_ERR_PK_BAD_INPUT_DATA; - } - - psa_set_key_type(&attributes, PSA_KEY_TYPE_ECC_PUBLIC_KEY(curve)); - psa_set_key_usage_flags(&attributes, PSA_KEY_USAGE_VERIFY_HASH); - psa_set_key_algorithm(&attributes, psa_sig_md); - - status = psa_import_key(&attributes, - buf + sizeof(buf) - key_len, key_len, - &key_id); - if (status != PSA_SUCCESS) { - ret = mbedtls_psa_err_translate_pk(status); - goto cleanup; - } - - /* We don't need the exported key anymore and can - * reuse its buffer for signature extraction. */ - if (2 * signature_part_size > sizeof(buf)) { - ret = MBEDTLS_ERR_PK_BAD_INPUT_DATA; - goto cleanup; - } - - p = (unsigned char *) sig; - if ((ret = extract_ecdsa_sig(&p, sig + sig_len, buf, - signature_part_size)) != 0) { - goto cleanup; - } - - if (psa_verify_hash(key_id, psa_sig_md, - hash, hash_len, - buf, 2 * signature_part_size) - != PSA_SUCCESS) { - ret = MBEDTLS_ERR_ECP_VERIFY_FAILED; - goto cleanup; - } - - if (p != sig + sig_len) { - ret = MBEDTLS_ERR_PK_SIG_LEN_MISMATCH; - goto cleanup; - } - ret = 0; - -cleanup: - psa_destroy_key(key_id); - return ret; -} -#else /* MBEDTLS_USE_PSA_CRYPTO */ -static int ecdsa_verify_wrap(void *ctx, mbedtls_md_type_t md_alg, - const unsigned char *hash, size_t hash_len, - const unsigned char *sig, size_t sig_len) -{ - int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED; - ((void) md_alg); - - ret = mbedtls_ecdsa_read_signature((mbedtls_ecdsa_context *) ctx, - hash, hash_len, sig, sig_len); - - if (ret == MBEDTLS_ERR_ECP_SIG_LEN_MISMATCH) { - return MBEDTLS_ERR_PK_SIG_LEN_MISMATCH; - } - - return ret; -} -#endif /* MBEDTLS_USE_PSA_CRYPTO */ - -static int ecdsa_sign_wrap(void *ctx, mbedtls_md_type_t md_alg, - const unsigned char *hash, size_t hash_len, - unsigned char *sig, size_t *sig_len, - int (*f_rng)(void *, unsigned char *, size_t), void *p_rng) -{ - return mbedtls_ecdsa_write_signature((mbedtls_ecdsa_context *) ctx, - md_alg, hash, hash_len, sig, sig_len, f_rng, p_rng); -} - -#if defined(MBEDTLS_ECP_RESTARTABLE) -static int ecdsa_verify_rs_wrap(void *ctx, mbedtls_md_type_t md_alg, +#if defined(MBEDTLS_ECDSA_C) && defined(MBEDTLS_ECP_RESTARTABLE) +static int ecdsa_verify_rs_wrap(mbedtls_pk_context *pk, mbedtls_md_type_t md_alg, const unsigned char *hash, size_t hash_len, const unsigned char *sig, size_t sig_len, void *rs_ctx) @@ -663,7 +1193,7 @@ static int ecdsa_verify_rs_wrap(void *ctx, mbedtls_md_type_t md_alg, ((void) md_alg); ret = mbedtls_ecdsa_read_signature_restartable( - (mbedtls_ecdsa_context *) ctx, + (mbedtls_ecdsa_context *) pk->pk_ctx, hash, hash_len, sig, sig_len, (mbedtls_ecdsa_restart_ctx *) rs_ctx); @@ -674,38 +1204,19 @@ static int ecdsa_verify_rs_wrap(void *ctx, mbedtls_md_type_t md_alg, return ret; } -static int ecdsa_sign_rs_wrap(void *ctx, mbedtls_md_type_t md_alg, +static int ecdsa_sign_rs_wrap(mbedtls_pk_context *pk, mbedtls_md_type_t md_alg, const unsigned char *hash, size_t hash_len, - unsigned char *sig, size_t *sig_len, + unsigned char *sig, size_t sig_size, size_t *sig_len, int (*f_rng)(void *, unsigned char *, size_t), void *p_rng, void *rs_ctx) { return mbedtls_ecdsa_write_signature_restartable( - (mbedtls_ecdsa_context *) ctx, - md_alg, hash, hash_len, sig, sig_len, f_rng, p_rng, + (mbedtls_ecdsa_context *) pk->pk_ctx, + md_alg, hash, hash_len, sig, sig_size, sig_len, f_rng, p_rng, (mbedtls_ecdsa_restart_ctx *) rs_ctx); } -#endif /* MBEDTLS_ECP_RESTARTABLE */ - -static void *ecdsa_alloc_wrap(void) -{ - void *ctx = mbedtls_calloc(1, sizeof(mbedtls_ecdsa_context)); - - if (ctx != NULL) { - mbedtls_ecdsa_init((mbedtls_ecdsa_context *) ctx); - } - - return ctx; -} - -static void ecdsa_free_wrap(void *ctx) -{ - mbedtls_ecdsa_free((mbedtls_ecdsa_context *) ctx); - mbedtls_free(ctx); -} -#if defined(MBEDTLS_ECP_RESTARTABLE) static void *ecdsa_rs_alloc(void) { void *ctx = mbedtls_calloc(1, sizeof(mbedtls_ecdsa_restart_ctx)); @@ -722,31 +1233,43 @@ static void ecdsa_rs_free(void *ctx) mbedtls_ecdsa_restart_free(ctx); mbedtls_free(ctx); } -#endif /* MBEDTLS_ECP_RESTARTABLE */ +#endif /* MBEDTLS_ECDSA_C && MBEDTLS_ECP_RESTARTABLE */ const mbedtls_pk_info_t mbedtls_ecdsa_info = { - MBEDTLS_PK_ECDSA, - "ECDSA", - eckey_get_bitlen, /* Compatible key structures */ - ecdsa_can_do, - ecdsa_verify_wrap, - ecdsa_sign_wrap, -#if defined(MBEDTLS_ECP_RESTARTABLE) - ecdsa_verify_rs_wrap, - ecdsa_sign_rs_wrap, -#endif - NULL, - NULL, - eckey_check_pair, /* Compatible key structures */ - ecdsa_alloc_wrap, - ecdsa_free_wrap, -#if defined(MBEDTLS_ECP_RESTARTABLE) - ecdsa_rs_alloc, - ecdsa_rs_free, -#endif - eckey_debug, /* Compatible key structures */ + .type = MBEDTLS_PK_ECDSA, + .name = "ECDSA", + .get_bitlen = eckey_get_bitlen, /* Compatible key structures */ + .can_do = ecdsa_can_do, +#if defined(MBEDTLS_PK_CAN_ECDSA_VERIFY) + .verify_func = ecdsa_verify_wrap, /* Compatible key structures */ +#else /* MBEDTLS_PK_CAN_ECDSA_VERIFY */ + .verify_func = NULL, +#endif /* MBEDTLS_PK_CAN_ECDSA_VERIFY */ +#if defined(MBEDTLS_PK_CAN_ECDSA_SIGN) + .sign_func = ecdsa_sign_wrap, /* Compatible key structures */ +#else /* MBEDTLS_PK_CAN_ECDSA_SIGN */ + .sign_func = NULL, +#endif /* MBEDTLS_PK_CAN_ECDSA_SIGN */ +#if defined(MBEDTLS_ECDSA_C) && defined(MBEDTLS_ECP_RESTARTABLE) + .verify_rs_func = ecdsa_verify_rs_wrap, + .sign_rs_func = ecdsa_sign_rs_wrap, + .rs_alloc_func = ecdsa_rs_alloc, + .rs_free_func = ecdsa_rs_free, +#endif /* MBEDTLS_ECDSA_C && MBEDTLS_ECP_RESTARTABLE */ + .decrypt_func = NULL, + .encrypt_func = NULL, + .check_pair_func = eckey_check_pair_wrap, /* Compatible key structures */ +#if defined(MBEDTLS_PK_USE_PSA_EC_DATA) + .ctx_alloc_func = NULL, + .ctx_free_func = NULL, +#else /* MBEDTLS_PK_USE_PSA_EC_DATA */ + .ctx_alloc_func = eckey_alloc_wrap, /* Compatible key structures */ + .ctx_free_func = eckey_free_wrap, /* Compatible key structures */ +#endif /* MBEDTLS_PK_USE_PSA_EC_DATA */ + .debug_func = eckey_debug, /* Compatible key structures */ }; -#endif /* MBEDTLS_ECDSA_C */ +#endif /* MBEDTLS_PK_CAN_ECDSA_SOME */ +#endif /* MBEDTLS_PK_HAVE_ECC_KEYS */ #if defined(MBEDTLS_PK_RSA_ALT_SUPPORT) /* @@ -758,41 +1281,44 @@ static int rsa_alt_can_do(mbedtls_pk_type_t type) return type == MBEDTLS_PK_RSA; } -static size_t rsa_alt_get_bitlen(const void *ctx) +static size_t rsa_alt_get_bitlen(mbedtls_pk_context *pk) { - const mbedtls_rsa_alt_context *rsa_alt = (const mbedtls_rsa_alt_context *) ctx; + const mbedtls_rsa_alt_context *rsa_alt = pk->pk_ctx; return 8 * rsa_alt->key_len_func(rsa_alt->key); } -static int rsa_alt_sign_wrap(void *ctx, mbedtls_md_type_t md_alg, +static int rsa_alt_sign_wrap(mbedtls_pk_context *pk, mbedtls_md_type_t md_alg, const unsigned char *hash, size_t hash_len, - unsigned char *sig, size_t *sig_len, + unsigned char *sig, size_t sig_size, size_t *sig_len, int (*f_rng)(void *, unsigned char *, size_t), void *p_rng) { - mbedtls_rsa_alt_context *rsa_alt = (mbedtls_rsa_alt_context *) ctx; + mbedtls_rsa_alt_context *rsa_alt = pk->pk_ctx; #if SIZE_MAX > UINT_MAX if (UINT_MAX < hash_len) { return MBEDTLS_ERR_PK_BAD_INPUT_DATA; } -#endif /* SIZE_MAX > UINT_MAX */ +#endif *sig_len = rsa_alt->key_len_func(rsa_alt->key); if (*sig_len > MBEDTLS_PK_SIGNATURE_MAX_SIZE) { return MBEDTLS_ERR_PK_BAD_INPUT_DATA; } + if (*sig_len > sig_size) { + return MBEDTLS_ERR_PK_BUFFER_TOO_SMALL; + } - return rsa_alt->sign_func(rsa_alt->key, f_rng, p_rng, MBEDTLS_RSA_PRIVATE, + return rsa_alt->sign_func(rsa_alt->key, f_rng, p_rng, md_alg, (unsigned int) hash_len, hash, sig); } -static int rsa_alt_decrypt_wrap(void *ctx, +static int rsa_alt_decrypt_wrap(mbedtls_pk_context *pk, const unsigned char *input, size_t ilen, unsigned char *output, size_t *olen, size_t osize, int (*f_rng)(void *, unsigned char *, size_t), void *p_rng) { - mbedtls_rsa_alt_context *rsa_alt = (mbedtls_rsa_alt_context *) ctx; + mbedtls_rsa_alt_context *rsa_alt = pk->pk_ctx; ((void) f_rng); ((void) p_rng); @@ -802,11 +1328,13 @@ static int rsa_alt_decrypt_wrap(void *ctx, } return rsa_alt->decrypt_func(rsa_alt->key, - MBEDTLS_RSA_PRIVATE, olen, input, output, osize); + olen, input, output, osize); } #if defined(MBEDTLS_RSA_C) -static int rsa_alt_check_pair(const void *pub, const void *prv) +static int rsa_alt_check_pair(mbedtls_pk_context *pub, mbedtls_pk_context *prv, + int (*f_rng)(void *, unsigned char *, size_t), + void *p_rng) { unsigned char sig[MBEDTLS_MPI_MAX_SIZE]; unsigned char hash[32]; @@ -819,13 +1347,14 @@ static int rsa_alt_check_pair(const void *pub, const void *prv) memset(hash, 0x2a, sizeof(hash)); - if ((ret = rsa_alt_sign_wrap((void *) prv, MBEDTLS_MD_NONE, + if ((ret = rsa_alt_sign_wrap(prv, MBEDTLS_MD_NONE, hash, sizeof(hash), - sig, &sig_len, NULL, NULL)) != 0) { + sig, sizeof(sig), &sig_len, + f_rng, p_rng)) != 0) { return ret; } - if (rsa_verify_wrap((void *) pub, MBEDTLS_MD_NONE, + if (rsa_verify_wrap(pub, MBEDTLS_MD_NONE, hash, sizeof(hash), sig, sig_len) != 0) { return MBEDTLS_ERR_RSA_KEY_CHECK_FAILED; } @@ -847,63 +1376,42 @@ static void *rsa_alt_alloc_wrap(void) static void rsa_alt_free_wrap(void *ctx) { - mbedtls_platform_zeroize(ctx, sizeof(mbedtls_rsa_alt_context)); - mbedtls_free(ctx); + mbedtls_zeroize_and_free(ctx, sizeof(mbedtls_rsa_alt_context)); } const mbedtls_pk_info_t mbedtls_rsa_alt_info = { - MBEDTLS_PK_RSA_ALT, - "RSA-alt", - rsa_alt_get_bitlen, - rsa_alt_can_do, - NULL, - rsa_alt_sign_wrap, + .type = MBEDTLS_PK_RSA_ALT, + .name = "RSA-alt", + .get_bitlen = rsa_alt_get_bitlen, + .can_do = rsa_alt_can_do, + .verify_func = NULL, + .sign_func = rsa_alt_sign_wrap, #if defined(MBEDTLS_ECDSA_C) && defined(MBEDTLS_ECP_RESTARTABLE) - NULL, - NULL, -#endif - rsa_alt_decrypt_wrap, - NULL, + .verify_rs_func = NULL, + .sign_rs_func = NULL, + .rs_alloc_func = NULL, + .rs_free_func = NULL, +#endif /* MBEDTLS_ECDSA_C && MBEDTLS_ECP_RESTARTABLE */ + .decrypt_func = rsa_alt_decrypt_wrap, + .encrypt_func = NULL, #if defined(MBEDTLS_RSA_C) - rsa_alt_check_pair, + .check_pair_func = rsa_alt_check_pair, #else - NULL, + .check_pair_func = NULL, #endif - rsa_alt_alloc_wrap, - rsa_alt_free_wrap, -#if defined(MBEDTLS_ECDSA_C) && defined(MBEDTLS_ECP_RESTARTABLE) - NULL, - NULL, -#endif - NULL, + .ctx_alloc_func = rsa_alt_alloc_wrap, + .ctx_free_func = rsa_alt_free_wrap, + .debug_func = NULL, }; - #endif /* MBEDTLS_PK_RSA_ALT_SUPPORT */ #if defined(MBEDTLS_USE_PSA_CRYPTO) - -static void *pk_opaque_alloc_wrap(void) -{ - void *ctx = mbedtls_calloc(1, sizeof(psa_key_id_t)); - - /* no _init() function to call, as calloc() already zeroized */ - - return ctx; -} - -static void pk_opaque_free_wrap(void *ctx) -{ - mbedtls_platform_zeroize(ctx, sizeof(psa_key_id_t)); - mbedtls_free(ctx); -} - -static size_t pk_opaque_get_bitlen(const void *ctx) +static size_t opaque_get_bitlen(mbedtls_pk_context *pk) { - const psa_key_id_t *key = (const psa_key_id_t *) ctx; size_t bits; psa_key_attributes_t attributes = PSA_KEY_ATTRIBUTES_INIT; - if (PSA_SUCCESS != psa_get_key_attributes(*key, &attributes)) { + if (PSA_SUCCESS != psa_get_key_attributes(pk->priv_id, &attributes)) { return 0; } @@ -912,176 +1420,163 @@ static size_t pk_opaque_get_bitlen(const void *ctx) return bits; } -static int pk_opaque_can_do(mbedtls_pk_type_t type) +#if defined(MBEDTLS_PK_HAVE_ECC_KEYS) +static int ecdsa_opaque_can_do(mbedtls_pk_type_t type) { - /* For now opaque PSA keys can only wrap ECC keypairs, - * as checked by setup_psa(). - * Also, ECKEY_DH does not really make sense with the current API. */ return type == MBEDTLS_PK_ECKEY || type == MBEDTLS_PK_ECDSA; } -#if defined(MBEDTLS_ECDSA_C) +const mbedtls_pk_info_t mbedtls_ecdsa_opaque_info = { + .type = MBEDTLS_PK_OPAQUE, + .name = "Opaque", + .get_bitlen = opaque_get_bitlen, + .can_do = ecdsa_opaque_can_do, +#if defined(MBEDTLS_PK_CAN_ECDSA_VERIFY) + .verify_func = ecdsa_opaque_verify_wrap, +#else /* MBEDTLS_PK_CAN_ECDSA_VERIFY */ + .verify_func = NULL, +#endif /* MBEDTLS_PK_CAN_ECDSA_VERIFY */ +#if defined(MBEDTLS_PK_CAN_ECDSA_SIGN) + .sign_func = ecdsa_opaque_sign_wrap, +#else /* MBEDTLS_PK_CAN_ECDSA_SIGN */ + .sign_func = NULL, +#endif /* MBEDTLS_PK_CAN_ECDSA_SIGN */ +#if defined(MBEDTLS_ECDSA_C) && defined(MBEDTLS_ECP_RESTARTABLE) + .verify_rs_func = NULL, + .sign_rs_func = NULL, + .rs_alloc_func = NULL, + .rs_free_func = NULL, +#endif /* MBEDTLS_ECDSA_C && MBEDTLS_ECP_RESTARTABLE */ + .decrypt_func = NULL, + .encrypt_func = NULL, + .check_pair_func = ecdsa_opaque_check_pair_wrap, + .ctx_alloc_func = NULL, + .ctx_free_func = NULL, + .debug_func = NULL, +}; +#endif /* MBEDTLS_PK_HAVE_ECC_KEYS */ -/* - * Simultaneously convert and move raw MPI from the beginning of a buffer - * to an ASN.1 MPI at the end of the buffer. - * See also mbedtls_asn1_write_mpi(). - * - * p: pointer to the end of the output buffer - * start: start of the output buffer, and also of the mpi to write at the end - * n_len: length of the mpi to read from start - */ -static int asn1_write_mpibuf(unsigned char **p, unsigned char *start, - size_t n_len) +static int rsa_opaque_can_do(mbedtls_pk_type_t type) { - int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED; - size_t len = 0; - - if ((size_t) (*p - start) < n_len) { - return MBEDTLS_ERR_ASN1_BUF_TOO_SMALL; - } + return type == MBEDTLS_PK_RSA || + type == MBEDTLS_PK_RSASSA_PSS; +} - len = n_len; - *p -= len; - memmove(*p, start, len); +#if defined(PSA_WANT_KEY_TYPE_RSA_KEY_PAIR_BASIC) +static int rsa_opaque_decrypt(mbedtls_pk_context *pk, + const unsigned char *input, size_t ilen, + unsigned char *output, size_t *olen, size_t osize, + int (*f_rng)(void *, unsigned char *, size_t), void *p_rng) +{ + psa_key_attributes_t attributes = PSA_KEY_ATTRIBUTES_INIT; + psa_algorithm_t alg; + psa_key_type_t type; + psa_status_t status; - /* ASN.1 DER encoding requires minimal length, so skip leading 0s. - * Neither r nor s should be 0, but as a failsafe measure, still detect - * that rather than overflowing the buffer in case of a PSA error. */ - while (len > 0 && **p == 0x00) { - ++(*p); - --len; - } + /* PSA has its own RNG */ + (void) f_rng; + (void) p_rng; - /* this is only reached if the signature was invalid */ - if (len == 0) { - return MBEDTLS_ERR_PK_HW_ACCEL_FAILED; + status = psa_get_key_attributes(pk->priv_id, &attributes); + if (status != PSA_SUCCESS) { + return PSA_PK_TO_MBEDTLS_ERR(status); } - /* if the msb is 1, ASN.1 requires that we prepend a 0. - * Neither r nor s can be 0, so we can assume len > 0 at all times. */ - if (**p & 0x80) { - if (*p - start < 1) { - return MBEDTLS_ERR_ASN1_BUF_TOO_SMALL; - } + type = psa_get_key_type(&attributes); + alg = psa_get_key_algorithm(&attributes); + psa_reset_key_attributes(&attributes); - *--(*p) = 0x00; - len += 1; + if (!PSA_KEY_TYPE_IS_RSA(type)) { + return MBEDTLS_ERR_PK_FEATURE_UNAVAILABLE; } - MBEDTLS_ASN1_CHK_ADD(len, mbedtls_asn1_write_len(p, start, len)); - MBEDTLS_ASN1_CHK_ADD(len, mbedtls_asn1_write_tag(p, start, - MBEDTLS_ASN1_INTEGER)); - - return (int) len; -} - -/* Transcode signature from PSA format to ASN.1 sequence. - * See ecdsa_signature_to_asn1 in ecdsa.c, but with byte buffers instead of - * MPIs, and in-place. - * - * [in/out] sig: the signature pre- and post-transcoding - * [in/out] sig_len: signature length pre- and post-transcoding - * [int] buf_len: the available size the in/out buffer - */ -static int pk_ecdsa_sig_asn1_from_psa(unsigned char *sig, size_t *sig_len, - size_t buf_len) -{ - int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED; - size_t len = 0; - const size_t rs_len = *sig_len / 2; - unsigned char *p = sig + buf_len; - - MBEDTLS_ASN1_CHK_ADD(len, asn1_write_mpibuf(&p, sig + rs_len, rs_len)); - MBEDTLS_ASN1_CHK_ADD(len, asn1_write_mpibuf(&p, sig, rs_len)); - - MBEDTLS_ASN1_CHK_ADD(len, mbedtls_asn1_write_len(&p, sig, len)); - MBEDTLS_ASN1_CHK_ADD(len, mbedtls_asn1_write_tag(&p, sig, - MBEDTLS_ASN1_CONSTRUCTED | - MBEDTLS_ASN1_SEQUENCE)); - - memmove(sig, p, len); - *sig_len = len; + status = psa_asymmetric_decrypt(pk->priv_id, alg, input, ilen, NULL, 0, output, osize, olen); + if (status != PSA_SUCCESS) { + return PSA_PK_RSA_TO_MBEDTLS_ERR(status); + } return 0; } +#endif /* PSA_WANT_KEY_TYPE_RSA_KEY_PAIR_BASIC */ -#endif /* MBEDTLS_ECDSA_C */ - -static int pk_opaque_sign_wrap(void *ctx, mbedtls_md_type_t md_alg, - const unsigned char *hash, size_t hash_len, - unsigned char *sig, size_t *sig_len, - int (*f_rng)(void *, unsigned char *, size_t), void *p_rng) +static int rsa_opaque_sign_wrap(mbedtls_pk_context *pk, mbedtls_md_type_t md_alg, + const unsigned char *hash, size_t hash_len, + unsigned char *sig, size_t sig_size, size_t *sig_len, + int (*f_rng)(void *, unsigned char *, size_t), void *p_rng) { -#if !defined(MBEDTLS_ECDSA_C) - ((void) ctx); - ((void) md_alg); - ((void) hash); - ((void) hash_len); - ((void) sig); - ((void) sig_len); - ((void) f_rng); - ((void) p_rng); - return MBEDTLS_ERR_PK_FEATURE_UNAVAILABLE; -#else /* !MBEDTLS_ECDSA_C */ - const psa_key_id_t *key = (const psa_key_id_t *) ctx; +#if defined(MBEDTLS_RSA_C) psa_key_attributes_t attributes = PSA_KEY_ATTRIBUTES_INIT; - psa_algorithm_t alg = PSA_ALG_ECDSA(mbedtls_psa_translate_md(md_alg)); - size_t buf_len; + psa_algorithm_t alg; + psa_key_type_t type; psa_status_t status; /* PSA has its own RNG */ (void) f_rng; (void) p_rng; - /* PSA needs an output buffer of known size, but our API doesn't provide - * that information. Assume that the buffer is large enough for a - * maximal-length signature with that key (otherwise the application is - * buggy anyway). */ - status = psa_get_key_attributes(*key, &attributes); + status = psa_get_key_attributes(pk->priv_id, &attributes); if (status != PSA_SUCCESS) { - return mbedtls_psa_err_translate_pk(status); + return PSA_PK_TO_MBEDTLS_ERR(status); } - buf_len = MBEDTLS_ECDSA_MAX_SIG_LEN(psa_get_key_bits(&attributes)); + + type = psa_get_key_type(&attributes); + alg = psa_get_key_algorithm(&attributes); psa_reset_key_attributes(&attributes); - if (buf_len > MBEDTLS_PK_SIGNATURE_MAX_SIZE) { - return MBEDTLS_ERR_PK_BAD_INPUT_DATA; + + if (PSA_KEY_TYPE_IS_RSA(type)) { + alg = (alg & ~PSA_ALG_HASH_MASK) | mbedtls_md_psa_alg_from_type(md_alg); + } else { + return MBEDTLS_ERR_PK_FEATURE_UNAVAILABLE; } - /* make the signature */ - status = psa_sign_hash(*key, alg, hash, hash_len, - sig, buf_len, sig_len); + status = psa_sign_hash(pk->priv_id, alg, hash, hash_len, sig, sig_size, sig_len); if (status != PSA_SUCCESS) { - return mbedtls_psa_err_translate_pk(status); + if (PSA_KEY_TYPE_IS_RSA(type)) { + return PSA_PK_RSA_TO_MBEDTLS_ERR(status); + } else { + return PSA_PK_TO_MBEDTLS_ERR(status); + } } - /* transcode it to ASN.1 sequence */ - return pk_ecdsa_sig_asn1_from_psa(sig, sig_len, buf_len); -#endif /* !MBEDTLS_ECDSA_C */ + return 0; +#else /* !MBEDTLS_RSA_C */ + ((void) pk); + ((void) md_alg); + ((void) hash); + ((void) hash_len); + ((void) sig); + ((void) sig_size); + ((void) sig_len); + ((void) f_rng); + ((void) p_rng); + return MBEDTLS_ERR_PK_FEATURE_UNAVAILABLE; +#endif /* !MBEDTLS_RSA_C */ } -const mbedtls_pk_info_t mbedtls_pk_opaque_info = { - MBEDTLS_PK_OPAQUE, - "Opaque", - pk_opaque_get_bitlen, - pk_opaque_can_do, - NULL, /* verify - will be done later */ - pk_opaque_sign_wrap, -#if defined(MBEDTLS_ECDSA_C) && defined(MBEDTLS_ECP_RESTARTABLE) - NULL, /* restartable verify - not relevant */ - NULL, /* restartable sign - not relevant */ -#endif - NULL, /* decrypt - will be done later */ - NULL, /* encrypt - will be done later */ - NULL, /* check_pair - could be done later or left NULL */ - pk_opaque_alloc_wrap, - pk_opaque_free_wrap, +const mbedtls_pk_info_t mbedtls_rsa_opaque_info = { + .type = MBEDTLS_PK_OPAQUE, + .name = "Opaque", + .get_bitlen = opaque_get_bitlen, + .can_do = rsa_opaque_can_do, + .verify_func = NULL, + .sign_func = rsa_opaque_sign_wrap, #if defined(MBEDTLS_ECDSA_C) && defined(MBEDTLS_ECP_RESTARTABLE) - NULL, /* restart alloc - not relevant */ - NULL, /* restart free - not relevant */ -#endif - NULL, /* debug - could be done later, or even left NULL */ + .verify_rs_func = NULL, + .sign_rs_func = NULL, + .rs_alloc_func = NULL, + .rs_free_func = NULL, +#endif /* MBEDTLS_ECDSA_C && MBEDTLS_ECP_RESTARTABLE */ +#if defined(PSA_WANT_KEY_TYPE_RSA_KEY_PAIR_BASIC) + .decrypt_func = rsa_opaque_decrypt, +#else /* PSA_WANT_KEY_TYPE_RSA_KEY_PAIR_BASIC */ + .decrypt_func = NULL, +#endif /* PSA_WANT_KEY_TYPE_RSA_KEY_PAIR_BASIC */ + .encrypt_func = NULL, + .check_pair_func = NULL, + .ctx_alloc_func = NULL, + .ctx_free_func = NULL, + .debug_func = NULL, }; #endif /* MBEDTLS_USE_PSA_CRYPTO */ diff --git a/vendor/mbedtls/include/mbedtls/pk_internal.h b/vendor/mbedtls/library/pk_wrap.h similarity index 63% rename from vendor/mbedtls/include/mbedtls/pk_internal.h rename to vendor/mbedtls/library/pk_wrap.h index 8a0c30f5ff..be096da53a 100644 --- a/vendor/mbedtls/include/mbedtls/pk_internal.h +++ b/vendor/mbedtls/library/pk_wrap.h @@ -1,36 +1,24 @@ /** - * \file pk_internal.h + * \file pk_wrap.h * * \brief Public Key abstraction layer: wrapper functions */ /* * Copyright The Mbed TLS Contributors - * SPDX-License-Identifier: Apache-2.0 - * - * Licensed under the Apache License, Version 2.0 (the "License"); you may - * not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT - * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. + * SPDX-License-Identifier: Apache-2.0 OR GPL-2.0-or-later */ #ifndef MBEDTLS_PK_WRAP_H #define MBEDTLS_PK_WRAP_H -#if !defined(MBEDTLS_CONFIG_FILE) -#include "mbedtls/config.h" -#else -#include MBEDTLS_CONFIG_FILE -#endif +#include "mbedtls/build_info.h" #include "mbedtls/pk.h" +#if defined(MBEDTLS_USE_PSA_CRYPTO) +#include "psa/crypto.h" +#endif + struct mbedtls_pk_info_t { /** Public key type */ mbedtls_pk_type_t type; @@ -39,52 +27,54 @@ struct mbedtls_pk_info_t { const char *name; /** Get key size in bits */ - size_t (*get_bitlen)(const void *); + size_t (*get_bitlen)(mbedtls_pk_context *pk); /** Tell if the context implements this type (e.g. ECKEY can do ECDSA) */ int (*can_do)(mbedtls_pk_type_t type); /** Verify signature */ - int (*verify_func)(void *ctx, mbedtls_md_type_t md_alg, + int (*verify_func)(mbedtls_pk_context *pk, mbedtls_md_type_t md_alg, const unsigned char *hash, size_t hash_len, const unsigned char *sig, size_t sig_len); /** Make signature */ - int (*sign_func)(void *ctx, mbedtls_md_type_t md_alg, + int (*sign_func)(mbedtls_pk_context *pk, mbedtls_md_type_t md_alg, const unsigned char *hash, size_t hash_len, - unsigned char *sig, size_t *sig_len, + unsigned char *sig, size_t sig_size, size_t *sig_len, int (*f_rng)(void *, unsigned char *, size_t), void *p_rng); #if defined(MBEDTLS_ECDSA_C) && defined(MBEDTLS_ECP_RESTARTABLE) /** Verify signature (restartable) */ - int (*verify_rs_func)(void *ctx, mbedtls_md_type_t md_alg, + int (*verify_rs_func)(mbedtls_pk_context *pk, mbedtls_md_type_t md_alg, const unsigned char *hash, size_t hash_len, const unsigned char *sig, size_t sig_len, void *rs_ctx); /** Make signature (restartable) */ - int (*sign_rs_func)(void *ctx, mbedtls_md_type_t md_alg, + int (*sign_rs_func)(mbedtls_pk_context *pk, mbedtls_md_type_t md_alg, const unsigned char *hash, size_t hash_len, - unsigned char *sig, size_t *sig_len, + unsigned char *sig, size_t sig_size, size_t *sig_len, int (*f_rng)(void *, unsigned char *, size_t), void *p_rng, void *rs_ctx); #endif /* MBEDTLS_ECDSA_C && MBEDTLS_ECP_RESTARTABLE */ /** Decrypt message */ - int (*decrypt_func)(void *ctx, const unsigned char *input, size_t ilen, + int (*decrypt_func)(mbedtls_pk_context *pk, const unsigned char *input, size_t ilen, unsigned char *output, size_t *olen, size_t osize, int (*f_rng)(void *, unsigned char *, size_t), void *p_rng); /** Encrypt message */ - int (*encrypt_func)(void *ctx, const unsigned char *input, size_t ilen, + int (*encrypt_func)(mbedtls_pk_context *pk, const unsigned char *input, size_t ilen, unsigned char *output, size_t *olen, size_t osize, int (*f_rng)(void *, unsigned char *, size_t), void *p_rng); /** Check public-private key pair */ - int (*check_pair_func)(const void *pub, const void *prv); + int (*check_pair_func)(mbedtls_pk_context *pub, mbedtls_pk_context *prv, + int (*f_rng)(void *, unsigned char *, size_t), + void *p_rng); /** Allocate a new context */ void * (*ctx_alloc_func)(void); @@ -101,7 +91,7 @@ struct mbedtls_pk_info_t { #endif /* MBEDTLS_ECDSA_C && MBEDTLS_ECP_RESTARTABLE */ /** Interface with the debug module */ - void (*debug_func)(const void *ctx, mbedtls_pk_debug_item *items); + void (*debug_func)(mbedtls_pk_context *pk, mbedtls_pk_debug_item *items); }; #if defined(MBEDTLS_PK_RSA_ALT_SUPPORT) @@ -118,12 +108,12 @@ typedef struct { extern const mbedtls_pk_info_t mbedtls_rsa_info; #endif -#if defined(MBEDTLS_ECP_C) +#if defined(MBEDTLS_PK_HAVE_ECC_KEYS) extern const mbedtls_pk_info_t mbedtls_eckey_info; extern const mbedtls_pk_info_t mbedtls_eckeydh_info; #endif -#if defined(MBEDTLS_ECDSA_C) +#if defined(MBEDTLS_PK_CAN_ECDSA_SOME) extern const mbedtls_pk_info_t mbedtls_ecdsa_info; #endif @@ -132,7 +122,17 @@ extern const mbedtls_pk_info_t mbedtls_rsa_alt_info; #endif #if defined(MBEDTLS_USE_PSA_CRYPTO) -extern const mbedtls_pk_info_t mbedtls_pk_opaque_info; -#endif +extern const mbedtls_pk_info_t mbedtls_ecdsa_opaque_info; +extern const mbedtls_pk_info_t mbedtls_rsa_opaque_info; + +#if defined(MBEDTLS_RSA_C) +int mbedtls_pk_psa_rsa_sign_ext(psa_algorithm_t psa_alg_md, + mbedtls_rsa_context *rsa_ctx, + const unsigned char *hash, size_t hash_len, + unsigned char *sig, size_t sig_size, + size_t *sig_len); +#endif /* MBEDTLS_RSA_C */ + +#endif /* MBEDTLS_USE_PSA_CRYPTO */ #endif /* MBEDTLS_PK_WRAP_H */ diff --git a/vendor/mbedtls/library/pkcs11.c b/vendor/mbedtls/library/pkcs11.c deleted file mode 100644 index 8ba40caf91..0000000000 --- a/vendor/mbedtls/library/pkcs11.c +++ /dev/null @@ -1,233 +0,0 @@ -/** - * \file pkcs11.c - * - * \brief Wrapper for PKCS#11 library libpkcs11-helper - * - * \author Adriaan de Jong - * - * Copyright The Mbed TLS Contributors - * SPDX-License-Identifier: Apache-2.0 - * - * Licensed under the Apache License, Version 2.0 (the "License"); you may - * not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT - * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -#include "mbedtls/pkcs11.h" - -#if defined(MBEDTLS_PKCS11_C) - -#include "mbedtls/md.h" -#include "mbedtls/oid.h" -#include "mbedtls/x509_crt.h" - -#include "mbedtls/platform.h" - -#include - -void mbedtls_pkcs11_init(mbedtls_pkcs11_context *ctx) -{ - memset(ctx, 0, sizeof(mbedtls_pkcs11_context)); -} - -int mbedtls_pkcs11_x509_cert_bind(mbedtls_x509_crt *cert, pkcs11h_certificate_t pkcs11_cert) -{ - int ret = 1; - unsigned char *cert_blob = NULL; - size_t cert_blob_size = 0; - - if (cert == NULL) { - ret = 2; - goto cleanup; - } - - if (pkcs11h_certificate_getCertificateBlob(pkcs11_cert, NULL, - &cert_blob_size) != CKR_OK) { - ret = 3; - goto cleanup; - } - - cert_blob = mbedtls_calloc(1, cert_blob_size); - if (NULL == cert_blob) { - ret = 4; - goto cleanup; - } - - if (pkcs11h_certificate_getCertificateBlob(pkcs11_cert, cert_blob, - &cert_blob_size) != CKR_OK) { - ret = 5; - goto cleanup; - } - - if (0 != mbedtls_x509_crt_parse(cert, cert_blob, cert_blob_size)) { - ret = 6; - goto cleanup; - } - - ret = 0; - -cleanup: - if (NULL != cert_blob) { - mbedtls_free(cert_blob); - } - - return ret; -} - - -int mbedtls_pkcs11_priv_key_bind(mbedtls_pkcs11_context *priv_key, - pkcs11h_certificate_t pkcs11_cert) -{ - int ret = 1; - mbedtls_x509_crt cert; - - mbedtls_x509_crt_init(&cert); - - if (priv_key == NULL) { - goto cleanup; - } - - if (0 != mbedtls_pkcs11_x509_cert_bind(&cert, pkcs11_cert)) { - goto cleanup; - } - - priv_key->len = mbedtls_pk_get_len(&cert.pk); - priv_key->pkcs11h_cert = pkcs11_cert; - - ret = 0; - -cleanup: - mbedtls_x509_crt_free(&cert); - - return ret; -} - -void mbedtls_pkcs11_priv_key_free(mbedtls_pkcs11_context *priv_key) -{ - if (NULL != priv_key) { - pkcs11h_certificate_freeCertificate(priv_key->pkcs11h_cert); - } -} - -int mbedtls_pkcs11_decrypt(mbedtls_pkcs11_context *ctx, - int mode, size_t *olen, - const unsigned char *input, - unsigned char *output, - size_t output_max_len) -{ - size_t input_len, output_len; - - if (NULL == ctx) { - return MBEDTLS_ERR_RSA_BAD_INPUT_DATA; - } - - if (MBEDTLS_RSA_PRIVATE != mode) { - return MBEDTLS_ERR_RSA_BAD_INPUT_DATA; - } - - output_len = input_len = ctx->len; - - if (input_len < 16 || input_len > output_max_len) { - return MBEDTLS_ERR_RSA_BAD_INPUT_DATA; - } - - /* Determine size of output buffer */ - if (pkcs11h_certificate_decryptAny(ctx->pkcs11h_cert, CKM_RSA_PKCS, input, - input_len, NULL, &output_len) != CKR_OK) { - return MBEDTLS_ERR_RSA_BAD_INPUT_DATA; - } - - if (output_len > output_max_len) { - return MBEDTLS_ERR_RSA_OUTPUT_TOO_LARGE; - } - - if (pkcs11h_certificate_decryptAny(ctx->pkcs11h_cert, CKM_RSA_PKCS, input, - input_len, output, &output_len) != CKR_OK) { - return MBEDTLS_ERR_RSA_BAD_INPUT_DATA; - } - *olen = output_len; - return 0; -} - -int mbedtls_pkcs11_sign(mbedtls_pkcs11_context *ctx, - int mode, - mbedtls_md_type_t md_alg, - unsigned int hashlen, - const unsigned char *hash, - unsigned char *sig) -{ - size_t sig_len = 0, asn_len = 0, oid_size = 0; - unsigned char *p = sig; - const char *oid; - - if (NULL == ctx) { - return MBEDTLS_ERR_RSA_BAD_INPUT_DATA; - } - - if (MBEDTLS_RSA_PRIVATE != mode) { - return MBEDTLS_ERR_RSA_BAD_INPUT_DATA; - } - - if (md_alg != MBEDTLS_MD_NONE) { - const mbedtls_md_info_t *md_info = mbedtls_md_info_from_type(md_alg); - if (md_info == NULL) { - return MBEDTLS_ERR_RSA_BAD_INPUT_DATA; - } - - if (mbedtls_oid_get_oid_by_md(md_alg, &oid, &oid_size) != 0) { - return MBEDTLS_ERR_RSA_BAD_INPUT_DATA; - } - - hashlen = mbedtls_md_get_size(md_info); - asn_len = 10 + oid_size; - } - - sig_len = ctx->len; - if (hashlen > sig_len || asn_len > sig_len || - hashlen + asn_len > sig_len) { - return MBEDTLS_ERR_RSA_BAD_INPUT_DATA; - } - - if (md_alg != MBEDTLS_MD_NONE) { - /* - * DigestInfo ::= SEQUENCE { - * digestAlgorithm DigestAlgorithmIdentifier, - * digest Digest } - * - * DigestAlgorithmIdentifier ::= AlgorithmIdentifier - * - * Digest ::= OCTET STRING - */ - *p++ = MBEDTLS_ASN1_SEQUENCE | MBEDTLS_ASN1_CONSTRUCTED; - *p++ = (unsigned char) (0x08 + oid_size + hashlen); - *p++ = MBEDTLS_ASN1_SEQUENCE | MBEDTLS_ASN1_CONSTRUCTED; - *p++ = (unsigned char) (0x04 + oid_size); - *p++ = MBEDTLS_ASN1_OID; - *p++ = oid_size & 0xFF; - memcpy(p, oid, oid_size); - p += oid_size; - *p++ = MBEDTLS_ASN1_NULL; - *p++ = 0x00; - *p++ = MBEDTLS_ASN1_OCTET_STRING; - *p++ = hashlen; - } - - memcpy(p, hash, hashlen); - - if (pkcs11h_certificate_signAny(ctx->pkcs11h_cert, CKM_RSA_PKCS, sig, - asn_len + hashlen, sig, &sig_len) != CKR_OK) { - return MBEDTLS_ERR_RSA_BAD_INPUT_DATA; - } - - return 0; -} - -#endif /* defined(MBEDTLS_PKCS11_C) */ diff --git a/vendor/mbedtls/library/pkcs12.c b/vendor/mbedtls/library/pkcs12.c index 89fda10a9c..a3467b9820 100644 --- a/vendor/mbedtls/library/pkcs12.c +++ b/vendor/mbedtls/library/pkcs12.c @@ -2,19 +2,7 @@ * PKCS#12 Personal Information Exchange Syntax * * Copyright The Mbed TLS Contributors - * SPDX-License-Identifier: Apache-2.0 - * - * Licensed under the Apache License, Version 2.0 (the "License"); you may - * not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT - * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. + * SPDX-License-Identifier: Apache-2.0 OR GPL-2.0-or-later */ /* * The PKCS #12 Personal Information Exchange Syntax Standard v1.1 @@ -29,21 +17,21 @@ #include "mbedtls/pkcs12.h" #include "mbedtls/asn1.h" +#if defined(MBEDTLS_CIPHER_C) #include "mbedtls/cipher.h" +#endif /* MBEDTLS_CIPHER_C */ #include "mbedtls/platform_util.h" #include "mbedtls/error.h" #include -#if defined(MBEDTLS_ARC4_C) -#include "mbedtls/arc4.h" -#endif - #if defined(MBEDTLS_DES_C) #include "mbedtls/des.h" #endif -#if defined(MBEDTLS_ASN1_PARSE_C) +#include "psa_util_internal.h" + +#if defined(MBEDTLS_ASN1_PARSE_C) && defined(MBEDTLS_CIPHER_C) static int pkcs12_parse_pbe_params(mbedtls_asn1_buf *params, mbedtls_asn1_buf *salt, int *iterations) @@ -131,47 +119,6 @@ static int pkcs12_pbe_derive_key_iv(mbedtls_asn1_buf *pbe_params, mbedtls_md_typ #undef PKCS12_MAX_PWDLEN -int mbedtls_pkcs12_pbe_sha1_rc4_128(mbedtls_asn1_buf *pbe_params, int mode, - const unsigned char *pwd, size_t pwdlen, - const unsigned char *data, size_t len, - unsigned char *output) -{ -#if !defined(MBEDTLS_ARC4_C) - ((void) pbe_params); - ((void) mode); - ((void) pwd); - ((void) pwdlen); - ((void) data); - ((void) len); - ((void) output); - return MBEDTLS_ERR_PKCS12_FEATURE_UNAVAILABLE; -#else - int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED; - unsigned char key[16]; - mbedtls_arc4_context ctx; - ((void) mode); - - mbedtls_arc4_init(&ctx); - - if ((ret = pkcs12_pbe_derive_key_iv(pbe_params, MBEDTLS_MD_SHA1, - pwd, pwdlen, - key, 16, NULL, 0)) != 0) { - return ret; - } - - mbedtls_arc4_setup(&ctx, key, 16); - if ((ret = mbedtls_arc4_crypt(&ctx, len, data, output)) != 0) { - goto exit; - } - -exit: - mbedtls_platform_zeroize(key, sizeof(key)); - mbedtls_arc4_free(&ctx); - - return ret; -#endif /* MBEDTLS_ARC4_C */ -} - #if !defined(MBEDTLS_CIPHER_PADDING_PKCS7) int mbedtls_pkcs12_pbe_ext(mbedtls_asn1_buf *pbe_params, int mode, mbedtls_cipher_type_t cipher_type, mbedtls_md_type_t md_type, @@ -181,6 +128,7 @@ int mbedtls_pkcs12_pbe_ext(mbedtls_asn1_buf *pbe_params, int mode, size_t *output_len); #endif +#if !defined(MBEDTLS_DEPRECATED_REMOVED) int mbedtls_pkcs12_pbe(mbedtls_asn1_buf *pbe_params, int mode, mbedtls_cipher_type_t cipher_type, mbedtls_md_type_t md_type, const unsigned char *pwd, size_t pwdlen, @@ -197,6 +145,7 @@ int mbedtls_pkcs12_pbe(mbedtls_asn1_buf *pbe_params, int mode, pwd, pwdlen, data, len, output, SIZE_MAX, &output_len); } +#endif int mbedtls_pkcs12_pbe_ext(mbedtls_asn1_buf *pbe_params, int mode, mbedtls_cipher_type_t cipher_type, mbedtls_md_type_t md_type, @@ -210,6 +159,7 @@ int mbedtls_pkcs12_pbe_ext(mbedtls_asn1_buf *pbe_params, int mode, unsigned char iv[16]; const mbedtls_cipher_info_t *cipher_info; mbedtls_cipher_context_t cipher_ctx; + size_t iv_len = 0; size_t finish_olen = 0; unsigned int padlen = 0; @@ -222,7 +172,7 @@ int mbedtls_pkcs12_pbe_ext(mbedtls_asn1_buf *pbe_params, int mode, return MBEDTLS_ERR_PKCS12_FEATURE_UNAVAILABLE; } - keylen = cipher_info->key_bitlen / 8; + keylen = (int) mbedtls_cipher_info_get_key_bitlen(cipher_info) / 8; if (mode == MBEDTLS_PKCS12_PBE_DECRYPT) { if (output_size < len) { @@ -237,9 +187,10 @@ int mbedtls_pkcs12_pbe_ext(mbedtls_asn1_buf *pbe_params, int mode, } } + iv_len = mbedtls_cipher_info_get_iv_size(cipher_info); if ((ret = pkcs12_pbe_derive_key_iv(pbe_params, md_type, pwd, pwdlen, key, keylen, - iv, cipher_info->iv_size)) != 0) { + iv, iv_len)) != 0) { return ret; } @@ -249,45 +200,33 @@ int mbedtls_pkcs12_pbe_ext(mbedtls_asn1_buf *pbe_params, int mode, goto exit; } - if ((ret = - mbedtls_cipher_setkey(&cipher_ctx, key, 8 * keylen, - (mbedtls_operation_t) mode)) != 0) { + if ((ret = mbedtls_cipher_setkey(&cipher_ctx, key, 8 * keylen, + (mbedtls_operation_t) mode)) != 0) { goto exit; } #if defined(MBEDTLS_CIPHER_MODE_WITH_PADDING) - /* PKCS12 uses CBC with PKCS7 padding */ - - mbedtls_cipher_padding_t padding = MBEDTLS_PADDING_PKCS7; + { + /* PKCS12 uses CBC with PKCS7 padding */ + mbedtls_cipher_padding_t padding = MBEDTLS_PADDING_PKCS7; #if !defined(MBEDTLS_CIPHER_PADDING_PKCS7) - /* For historical reasons, when decrypting, this function works when - * decrypting even when support for PKCS7 padding is disabled. In this - * case, it ignores the padding, and so will never report a - * password mismatch. - */ - if (mode == MBEDTLS_PKCS12_PBE_DECRYPT) { - padding = MBEDTLS_PADDING_NONE; - } + /* For historical reasons, when decrypting, this function works when + * decrypting even when support for PKCS7 padding is disabled. In this + * case, it ignores the padding, and so will never report a + * password mismatch. + */ + if (mode == MBEDTLS_PKCS12_PBE_DECRYPT) { + padding = MBEDTLS_PADDING_NONE; + } #endif - if ((ret = mbedtls_cipher_set_padding_mode(&cipher_ctx, padding)) != 0) { - goto exit; + if ((ret = mbedtls_cipher_set_padding_mode(&cipher_ctx, padding)) != 0) { + goto exit; + } } #endif /* MBEDTLS_CIPHER_MODE_WITH_PADDING */ - if ((ret = mbedtls_cipher_set_iv(&cipher_ctx, iv, cipher_info->iv_size)) != 0) { - goto exit; - } - - if ((ret = mbedtls_cipher_reset(&cipher_ctx)) != 0) { - goto exit; - } - - if ((ret = mbedtls_cipher_update(&cipher_ctx, data, len, - output, output_len)) != 0) { - goto exit; - } - - if ((ret = mbedtls_cipher_finish(&cipher_ctx, output + (*output_len), &finish_olen)) != 0) { + ret = mbedtls_cipher_crypt(&cipher_ctx, iv, iv_len, data, len, output, &finish_olen); + if (ret == MBEDTLS_ERR_CIPHER_INVALID_PADDING) { ret = MBEDTLS_ERR_PKCS12_PASSWORD_MISMATCH; } @@ -301,7 +240,7 @@ int mbedtls_pkcs12_pbe_ext(mbedtls_asn1_buf *pbe_params, int mode, return ret; } -#endif /* MBEDTLS_ASN1_PARSE_C */ +#endif /* MBEDTLS_ASN1_PARSE_C && MBEDTLS_CIPHER_C */ static void pkcs12_fill_buffer(unsigned char *data, size_t data_len, const unsigned char *filler, size_t fill_len) @@ -325,6 +264,65 @@ static void pkcs12_fill_buffer(unsigned char *data, size_t data_len, } } + +static int calculate_hashes(mbedtls_md_type_t md_type, int iterations, + unsigned char *diversifier, unsigned char *salt_block, + unsigned char *pwd_block, unsigned char *hash_output, int use_salt, + int use_password, size_t hlen, size_t v) +{ + int ret = -1; + size_t i; + const mbedtls_md_info_t *md_info; + mbedtls_md_context_t md_ctx; + md_info = mbedtls_md_info_from_type(md_type); + if (md_info == NULL) { + return MBEDTLS_ERR_PKCS12_FEATURE_UNAVAILABLE; + } + + mbedtls_md_init(&md_ctx); + + if ((ret = mbedtls_md_setup(&md_ctx, md_info, 0)) != 0) { + return ret; + } + // Calculate hash( diversifier || salt_block || pwd_block ) + if ((ret = mbedtls_md_starts(&md_ctx)) != 0) { + goto exit; + } + + if ((ret = mbedtls_md_update(&md_ctx, diversifier, v)) != 0) { + goto exit; + } + + if (use_salt != 0) { + if ((ret = mbedtls_md_update(&md_ctx, salt_block, v)) != 0) { + goto exit; + } + } + + if (use_password != 0) { + if ((ret = mbedtls_md_update(&md_ctx, pwd_block, v)) != 0) { + goto exit; + } + } + + if ((ret = mbedtls_md_finish(&md_ctx, hash_output)) != 0) { + goto exit; + } + + // Perform remaining ( iterations - 1 ) recursive hash calculations + for (i = 1; i < (size_t) iterations; i++) { + if ((ret = mbedtls_md(md_info, hash_output, hlen, hash_output)) + != 0) { + goto exit; + } + } + +exit: + mbedtls_md_free(&md_ctx); + return ret; +} + + int mbedtls_pkcs12_derivation(unsigned char *data, size_t datalen, const unsigned char *pwd, size_t pwdlen, const unsigned char *salt, size_t saltlen, @@ -334,7 +332,7 @@ int mbedtls_pkcs12_derivation(unsigned char *data, size_t datalen, unsigned int j; unsigned char diversifier[128]; - unsigned char salt_block[128], pwd_block[128], hash_block[128]; + unsigned char salt_block[128], pwd_block[128], hash_block[128] = { 0 }; unsigned char hash_output[MBEDTLS_MD_MAX_SIZE]; unsigned char *p; unsigned char c; @@ -343,9 +341,6 @@ int mbedtls_pkcs12_derivation(unsigned char *data, size_t datalen, size_t hlen, use_len, v, i; - const mbedtls_md_info_t *md_info; - mbedtls_md_context_t md_ctx; - // This version only allows max of 64 bytes of password or salt if (datalen > 128 || pwdlen > 64 || saltlen > 64) { return MBEDTLS_ERR_PKCS12_BAD_INPUT_DATA; @@ -362,17 +357,7 @@ int mbedtls_pkcs12_derivation(unsigned char *data, size_t datalen, use_password = (pwd && pwdlen != 0); use_salt = (salt && saltlen != 0); - md_info = mbedtls_md_info_from_type(md_type); - if (md_info == NULL) { - return MBEDTLS_ERR_PKCS12_FEATURE_UNAVAILABLE; - } - - mbedtls_md_init(&md_ctx); - - if ((ret = mbedtls_md_setup(&md_ctx, md_info, 0)) != 0) { - return ret; - } - hlen = mbedtls_md_get_size(md_info); + hlen = mbedtls_md_get_size_from_type(md_type); if (hlen <= 32) { v = 64; @@ -392,38 +377,12 @@ int mbedtls_pkcs12_derivation(unsigned char *data, size_t datalen, p = data; while (datalen > 0) { - // Calculate hash( diversifier || salt_block || pwd_block ) - if ((ret = mbedtls_md_starts(&md_ctx)) != 0) { + if (calculate_hashes(md_type, iterations, diversifier, salt_block, + pwd_block, hash_output, use_salt, use_password, hlen, + v) != 0) { goto exit; } - if ((ret = mbedtls_md_update(&md_ctx, diversifier, v)) != 0) { - goto exit; - } - - if (use_salt != 0) { - if ((ret = mbedtls_md_update(&md_ctx, salt_block, v)) != 0) { - goto exit; - } - } - - if (use_password != 0) { - if ((ret = mbedtls_md_update(&md_ctx, pwd_block, v)) != 0) { - goto exit; - } - } - - if ((ret = mbedtls_md_finish(&md_ctx, hash_output)) != 0) { - goto exit; - } - - // Perform remaining ( iterations - 1 ) recursive hash calculations - for (i = 1; i < (size_t) iterations; i++) { - if ((ret = mbedtls_md(md_info, hash_output, hlen, hash_output)) != 0) { - goto exit; - } - } - use_len = (datalen > hlen) ? hlen : datalen; memcpy(p, hash_output, use_len); datalen -= use_len; @@ -472,8 +431,6 @@ int mbedtls_pkcs12_derivation(unsigned char *data, size_t datalen, mbedtls_platform_zeroize(hash_block, sizeof(hash_block)); mbedtls_platform_zeroize(hash_output, sizeof(hash_output)); - mbedtls_md_free(&md_ctx); - return ret; } diff --git a/vendor/mbedtls/library/pkcs5.c b/vendor/mbedtls/library/pkcs5.c index ebf391ad83..c6c53054b6 100644 --- a/vendor/mbedtls/library/pkcs5.c +++ b/vendor/mbedtls/library/pkcs5.c @@ -6,19 +6,7 @@ * \author Mathias Olsson * * Copyright The Mbed TLS Contributors - * SPDX-License-Identifier: Apache-2.0 - * - * Licensed under the Apache License, Version 2.0 (the "License"); you may - * not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT - * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. + * SPDX-License-Identifier: Apache-2.0 OR GPL-2.0-or-later */ /* * PKCS#5 includes PBKDF2 and more @@ -36,7 +24,9 @@ #if defined(MBEDTLS_ASN1_PARSE_C) #include "mbedtls/asn1.h" +#if defined(MBEDTLS_CIPHER_C) #include "mbedtls/cipher.h" +#endif /* MBEDTLS_CIPHER_C */ #include "mbedtls/oid.h" #endif /* MBEDTLS_ASN1_PARSE_C */ @@ -44,8 +34,9 @@ #include "mbedtls/platform.h" +#include "psa_util_internal.h" -#if defined(MBEDTLS_ASN1_PARSE_C) +#if defined(MBEDTLS_ASN1_PARSE_C) && defined(MBEDTLS_CIPHER_C) static int pkcs5_parse_pbkdf2_params(const mbedtls_asn1_buf *params, mbedtls_asn1_buf *salt, int *iterations, int *keylen, mbedtls_md_type_t *md_type) @@ -118,6 +109,7 @@ int mbedtls_pkcs5_pbes2_ext(const mbedtls_asn1_buf *pbe_params, int mode, size_t *output_len); #endif +#if !defined(MBEDTLS_DEPRECATED_REMOVED) int mbedtls_pkcs5_pbes2(const mbedtls_asn1_buf *pbe_params, int mode, const unsigned char *pwd, size_t pwdlen, const unsigned char *data, size_t datalen, @@ -132,6 +124,7 @@ int mbedtls_pkcs5_pbes2(const mbedtls_asn1_buf *pbe_params, int mode, return mbedtls_pkcs5_pbes2_ext(pbe_params, mode, pwd, pwdlen, data, datalen, output, SIZE_MAX, &output_len); } +#endif int mbedtls_pkcs5_pbes2_ext(const mbedtls_asn1_buf *pbe_params, int mode, const unsigned char *pwd, size_t pwdlen, @@ -145,9 +138,7 @@ int mbedtls_pkcs5_pbes2_ext(const mbedtls_asn1_buf *pbe_params, int mode, mbedtls_asn1_buf salt; mbedtls_md_type_t md_type = MBEDTLS_MD_SHA1; unsigned char key[32], iv[32]; - const mbedtls_md_info_t *md_info; const mbedtls_cipher_info_t *cipher_info; - mbedtls_md_context_t md_ctx; mbedtls_cipher_type_t cipher_alg; mbedtls_cipher_context_t cipher_ctx; unsigned int padlen = 0; @@ -183,11 +174,6 @@ int mbedtls_pkcs5_pbes2_ext(const mbedtls_asn1_buf *pbe_params, int mode, return ret; } - md_info = mbedtls_md_info_from_type(md_type); - if (md_info == NULL) { - return MBEDTLS_ERR_PKCS5_FEATURE_UNAVAILABLE; - } - if ((ret = mbedtls_asn1_get_alg(&p, end, &enc_scheme_oid, &enc_scheme_params)) != 0) { return MBEDTLS_ERROR_ADD(MBEDTLS_ERR_PKCS5_INVALID_FORMAT, ret); @@ -206,10 +192,10 @@ int mbedtls_pkcs5_pbes2_ext(const mbedtls_asn1_buf *pbe_params, int mode, * The value of keylen from pkcs5_parse_pbkdf2_params() is ignored * since it is optional and we don't know if it was set or not */ - keylen = cipher_info->key_bitlen / 8; + keylen = (int) mbedtls_cipher_info_get_key_bitlen(cipher_info) / 8; if (enc_scheme_params.tag != MBEDTLS_ASN1_OCTET_STRING || - enc_scheme_params.len != cipher_info->iv_size) { + enc_scheme_params.len != mbedtls_cipher_info_get_iv_size(cipher_info)) { return MBEDTLS_ERR_PKCS5_INVALID_FORMAT; } @@ -226,18 +212,13 @@ int mbedtls_pkcs5_pbes2_ext(const mbedtls_asn1_buf *pbe_params, int mode, } } - mbedtls_md_init(&md_ctx); - mbedtls_cipher_init(&cipher_ctx); memcpy(iv, enc_scheme_params.p, enc_scheme_params.len); - if ((ret = mbedtls_md_setup(&md_ctx, md_info, 1)) != 0) { - goto exit; - } - - if ((ret = mbedtls_pkcs5_pbkdf2_hmac(&md_ctx, pwd, pwdlen, salt.p, salt.len, - iterations, keylen, key)) != 0) { + if ((ret = mbedtls_pkcs5_pbkdf2_hmac_ext(md_type, pwd, pwdlen, salt.p, + salt.len, iterations, keylen, + key)) != 0) { goto exit; } @@ -251,23 +232,25 @@ int mbedtls_pkcs5_pbes2_ext(const mbedtls_asn1_buf *pbe_params, int mode, } #if defined(MBEDTLS_CIPHER_MODE_WITH_PADDING) - /* PKCS5 uses CBC with PKCS7 padding (which is the same as - * "PKCS5 padding" except that it's typically only called PKCS5 - * with 64-bit-block ciphers). - */ - mbedtls_cipher_padding_t padding = MBEDTLS_PADDING_PKCS7; + { + /* PKCS5 uses CBC with PKCS7 padding (which is the same as + * "PKCS5 padding" except that it's typically only called PKCS5 + * with 64-bit-block ciphers). + */ + mbedtls_cipher_padding_t padding = MBEDTLS_PADDING_PKCS7; #if !defined(MBEDTLS_CIPHER_PADDING_PKCS7) - /* For historical reasons, when decrypting, this function works when - * decrypting even when support for PKCS7 padding is disabled. In this - * case, it ignores the padding, and so will never report a - * password mismatch. - */ - if (mode == MBEDTLS_DECRYPT) { - padding = MBEDTLS_PADDING_NONE; - } + /* For historical reasons, when decrypting, this function works when + * decrypting even when support for PKCS7 padding is disabled. In this + * case, it ignores the padding, and so will never report a + * password mismatch. + */ + if (mode == MBEDTLS_DECRYPT) { + padding = MBEDTLS_PADDING_NONE; + } #endif - if ((ret = mbedtls_cipher_set_padding_mode(&cipher_ctx, padding)) != 0) { - goto exit; + if ((ret = mbedtls_cipher_set_padding_mode(&cipher_ctx, padding)) != 0) { + goto exit; + } } #endif /* MBEDTLS_CIPHER_MODE_WITH_PADDING */ if ((ret = mbedtls_cipher_crypt(&cipher_ctx, iv, enc_scheme_params.len, @@ -276,21 +259,19 @@ int mbedtls_pkcs5_pbes2_ext(const mbedtls_asn1_buf *pbe_params, int mode, } exit: - mbedtls_md_free(&md_ctx); mbedtls_cipher_free(&cipher_ctx); return ret; } -#endif /* MBEDTLS_ASN1_PARSE_C */ +#endif /* MBEDTLS_ASN1_PARSE_C && MBEDTLS_CIPHER_C */ -int mbedtls_pkcs5_pbkdf2_hmac(mbedtls_md_context_t *ctx, - const unsigned char *password, - size_t plen, const unsigned char *salt, size_t slen, - unsigned int iteration_count, - uint32_t key_length, unsigned char *output) +static int pkcs5_pbkdf2_hmac(mbedtls_md_context_t *ctx, + const unsigned char *password, + size_t plen, const unsigned char *salt, size_t slen, + unsigned int iteration_count, + uint32_t key_length, unsigned char *output) { int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED; - int j; unsigned int i; unsigned char md1[MBEDTLS_MD_MAX_SIZE]; unsigned char work[MBEDTLS_MD_MAX_SIZE]; @@ -349,9 +330,7 @@ int mbedtls_pkcs5_pbkdf2_hmac(mbedtls_md_context_t *ctx, // U1 xor U2 // - for (j = 0; j < md_size; j++) { - work[j] ^= md1[j]; - } + mbedtls_xor(work, work, md1, md_size); } use_len = (key_length < md_size) ? key_length : md_size; @@ -375,9 +354,48 @@ int mbedtls_pkcs5_pbkdf2_hmac(mbedtls_md_context_t *ctx, return ret; } +#if !defined(MBEDTLS_DEPRECATED_REMOVED) +int mbedtls_pkcs5_pbkdf2_hmac(mbedtls_md_context_t *ctx, + const unsigned char *password, + size_t plen, const unsigned char *salt, size_t slen, + unsigned int iteration_count, + uint32_t key_length, unsigned char *output) +{ + return pkcs5_pbkdf2_hmac(ctx, password, plen, salt, slen, iteration_count, + key_length, output); +} +#endif + +int mbedtls_pkcs5_pbkdf2_hmac_ext(mbedtls_md_type_t md_alg, + const unsigned char *password, + size_t plen, const unsigned char *salt, size_t slen, + unsigned int iteration_count, + uint32_t key_length, unsigned char *output) +{ + mbedtls_md_context_t md_ctx; + const mbedtls_md_info_t *md_info = NULL; + int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED; + + md_info = mbedtls_md_info_from_type(md_alg); + if (md_info == NULL) { + return MBEDTLS_ERR_PKCS5_FEATURE_UNAVAILABLE; + } + + mbedtls_md_init(&md_ctx); + + if ((ret = mbedtls_md_setup(&md_ctx, md_info, 1)) != 0) { + goto exit; + } + ret = pkcs5_pbkdf2_hmac(&md_ctx, password, plen, salt, slen, + iteration_count, key_length, output); +exit: + mbedtls_md_free(&md_ctx); + return ret; +} + #if defined(MBEDTLS_SELF_TEST) -#if !defined(MBEDTLS_SHA1_C) +#if !defined(MBEDTLS_MD_CAN_SHA1) int mbedtls_pkcs5_self_test(int verbose) { if (verbose != 0) { @@ -441,33 +459,18 @@ static const unsigned char result_key_test_data[MAX_TESTS][32] = int mbedtls_pkcs5_self_test(int verbose) { - mbedtls_md_context_t sha1_ctx; - const mbedtls_md_info_t *info_sha1; int ret, i; unsigned char key[64]; - mbedtls_md_init(&sha1_ctx); - - info_sha1 = mbedtls_md_info_from_type(MBEDTLS_MD_SHA1); - if (info_sha1 == NULL) { - ret = 1; - goto exit; - } - - if ((ret = mbedtls_md_setup(&sha1_ctx, info_sha1, 1)) != 0) { - ret = 1; - goto exit; - } - for (i = 0; i < MAX_TESTS; i++) { if (verbose != 0) { mbedtls_printf(" PBKDF2 (SHA1) #%d: ", i); } - ret = mbedtls_pkcs5_pbkdf2_hmac(&sha1_ctx, password_test_data[i], - plen_test_data[i], salt_test_data[i], - slen_test_data[i], it_cnt_test_data[i], - key_len_test_data[i], key); + ret = mbedtls_pkcs5_pbkdf2_hmac_ext(MBEDTLS_MD_SHA1, password_test_data[i], + plen_test_data[i], salt_test_data[i], + slen_test_data[i], it_cnt_test_data[i], + key_len_test_data[i], key); if (ret != 0 || memcmp(result_key_test_data[i], key, key_len_test_data[i]) != 0) { if (verbose != 0) { @@ -488,11 +491,9 @@ int mbedtls_pkcs5_self_test(int verbose) } exit: - mbedtls_md_free(&sha1_ctx); - return ret; } -#endif /* MBEDTLS_SHA1_C */ +#endif /* MBEDTLS_MD_CAN_SHA1 */ #endif /* MBEDTLS_SELF_TEST */ diff --git a/vendor/mbedtls/library/pkcs7.c b/vendor/mbedtls/library/pkcs7.c new file mode 100644 index 0000000000..3aac662ba6 --- /dev/null +++ b/vendor/mbedtls/library/pkcs7.c @@ -0,0 +1,773 @@ +/* + * Copyright The Mbed TLS Contributors + * SPDX-License-Identifier: Apache-2.0 OR GPL-2.0-or-later + */ +#include "common.h" + +#include "mbedtls/build_info.h" +#if defined(MBEDTLS_PKCS7_C) +#include "mbedtls/pkcs7.h" +#include "x509_internal.h" +#include "mbedtls/asn1.h" +#include "mbedtls/x509_crt.h" +#include "mbedtls/x509_crl.h" +#include "mbedtls/oid.h" +#include "mbedtls/error.h" + +#if defined(MBEDTLS_FS_IO) +#include +#include +#endif + +#include "mbedtls/platform.h" +#include "mbedtls/platform_util.h" + +#if defined(MBEDTLS_HAVE_TIME) +#include "mbedtls/platform_time.h" +#endif +#if defined(MBEDTLS_HAVE_TIME_DATE) +#include +#endif + +/** + * Initializes the mbedtls_pkcs7 structure. + */ +void mbedtls_pkcs7_init(mbedtls_pkcs7 *pkcs7) +{ + memset(pkcs7, 0, sizeof(*pkcs7)); +} + +static int pkcs7_get_next_content_len(unsigned char **p, unsigned char *end, + size_t *len) +{ + int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED; + + ret = mbedtls_asn1_get_tag(p, end, len, MBEDTLS_ASN1_CONSTRUCTED + | MBEDTLS_ASN1_CONTEXT_SPECIFIC); + if (ret != 0) { + ret = MBEDTLS_ERROR_ADD(MBEDTLS_ERR_PKCS7_INVALID_CONTENT_INFO, ret); + } else if ((size_t) (end - *p) != *len) { + ret = MBEDTLS_ERROR_ADD(MBEDTLS_ERR_PKCS7_INVALID_CONTENT_INFO, + MBEDTLS_ERR_ASN1_LENGTH_MISMATCH); + } + + return ret; +} + +/** + * version Version + * Version ::= INTEGER + **/ +static int pkcs7_get_version(unsigned char **p, unsigned char *end, int *ver) +{ + int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED; + + ret = mbedtls_asn1_get_int(p, end, ver); + if (ret != 0) { + ret = MBEDTLS_ERROR_ADD(MBEDTLS_ERR_PKCS7_INVALID_VERSION, ret); + } + + /* If version != 1, return invalid version */ + if (*ver != MBEDTLS_PKCS7_SUPPORTED_VERSION) { + ret = MBEDTLS_ERR_PKCS7_INVALID_VERSION; + } + + return ret; +} + +/** + * ContentInfo ::= SEQUENCE { + * contentType ContentType, + * content + * [0] EXPLICIT ANY DEFINED BY contentType OPTIONAL } + **/ +static int pkcs7_get_content_info_type(unsigned char **p, unsigned char *end, + unsigned char **seq_end, + mbedtls_pkcs7_buf *pkcs7) +{ + size_t len = 0; + int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED; + unsigned char *start = *p; + + ret = mbedtls_asn1_get_tag(p, end, &len, MBEDTLS_ASN1_CONSTRUCTED + | MBEDTLS_ASN1_SEQUENCE); + if (ret != 0) { + *p = start; + return MBEDTLS_ERROR_ADD(MBEDTLS_ERR_PKCS7_INVALID_CONTENT_INFO, ret); + } + *seq_end = *p + len; + ret = mbedtls_asn1_get_tag(p, *seq_end, &len, MBEDTLS_ASN1_OID); + if (ret != 0) { + *p = start; + return MBEDTLS_ERROR_ADD(MBEDTLS_ERR_PKCS7_INVALID_CONTENT_INFO, ret); + } + + pkcs7->tag = MBEDTLS_ASN1_OID; + pkcs7->len = len; + pkcs7->p = *p; + *p += len; + + return ret; +} + +/** + * DigestAlgorithmIdentifier ::= AlgorithmIdentifier + * + * This is from x509.h + **/ +static int pkcs7_get_digest_algorithm(unsigned char **p, unsigned char *end, + mbedtls_x509_buf *alg) +{ + int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED; + + if ((ret = mbedtls_asn1_get_alg_null(p, end, alg)) != 0) { + ret = MBEDTLS_ERROR_ADD(MBEDTLS_ERR_PKCS7_INVALID_ALG, ret); + } + + return ret; +} + +/** + * DigestAlgorithmIdentifiers :: SET of DigestAlgorithmIdentifier + **/ +static int pkcs7_get_digest_algorithm_set(unsigned char **p, + unsigned char *end, + mbedtls_x509_buf *alg) +{ + size_t len = 0; + int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED; + + ret = mbedtls_asn1_get_tag(p, end, &len, MBEDTLS_ASN1_CONSTRUCTED + | MBEDTLS_ASN1_SET); + if (ret != 0) { + return MBEDTLS_ERROR_ADD(MBEDTLS_ERR_PKCS7_INVALID_ALG, ret); + } + + end = *p + len; + + ret = mbedtls_asn1_get_alg_null(p, end, alg); + if (ret != 0) { + return MBEDTLS_ERROR_ADD(MBEDTLS_ERR_PKCS7_INVALID_ALG, ret); + } + + /** For now, it assumes there is only one digest algorithm specified **/ + if (*p != end) { + return MBEDTLS_ERR_PKCS7_FEATURE_UNAVAILABLE; + } + + return 0; +} + +/** + * certificates :: SET OF ExtendedCertificateOrCertificate, + * ExtendedCertificateOrCertificate ::= CHOICE { + * certificate Certificate -- x509, + * extendedCertificate[0] IMPLICIT ExtendedCertificate } + * Return number of certificates added to the signed data, + * 0 or higher is valid. + * Return negative error code for failure. + **/ +static int pkcs7_get_certificates(unsigned char **p, unsigned char *end, + mbedtls_x509_crt *certs) +{ + int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED; + size_t len1 = 0; + size_t len2 = 0; + unsigned char *end_set, *end_cert, *start; + + ret = mbedtls_asn1_get_tag(p, end, &len1, MBEDTLS_ASN1_CONSTRUCTED + | MBEDTLS_ASN1_CONTEXT_SPECIFIC); + if (ret == MBEDTLS_ERR_ASN1_UNEXPECTED_TAG) { + return 0; + } + if (ret != 0) { + return MBEDTLS_ERROR_ADD(MBEDTLS_ERR_PKCS7_INVALID_FORMAT, ret); + } + start = *p; + end_set = *p + len1; + + ret = mbedtls_asn1_get_tag(p, end_set, &len2, MBEDTLS_ASN1_CONSTRUCTED + | MBEDTLS_ASN1_SEQUENCE); + if (ret != 0) { + return MBEDTLS_ERROR_ADD(MBEDTLS_ERR_PKCS7_INVALID_CERT, ret); + } + + end_cert = *p + len2; + + /* + * This is to verify that there is only one signer certificate. It seems it is + * not easy to differentiate between the chain vs different signer's certificate. + * So, we support only the root certificate and the single signer. + * The behaviour would be improved with addition of multiple signer support. + */ + if (end_cert != end_set) { + return MBEDTLS_ERR_PKCS7_FEATURE_UNAVAILABLE; + } + + if ((ret = mbedtls_x509_crt_parse_der(certs, start, len1)) < 0) { + return MBEDTLS_ERR_PKCS7_INVALID_CERT; + } + + *p = end_cert; + + /* + * Since in this version we strictly support single certificate, and reaching + * here implies we have parsed successfully, we return 1. + */ + return 1; +} + +/** + * EncryptedDigest ::= OCTET STRING + **/ +static int pkcs7_get_signature(unsigned char **p, unsigned char *end, + mbedtls_pkcs7_buf *signature) +{ + int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED; + size_t len = 0; + + ret = mbedtls_asn1_get_tag(p, end, &len, MBEDTLS_ASN1_OCTET_STRING); + if (ret != 0) { + return ret; + } + + signature->tag = MBEDTLS_ASN1_OCTET_STRING; + signature->len = len; + signature->p = *p; + + *p = *p + len; + + return 0; +} + +static void pkcs7_free_signer_info(mbedtls_pkcs7_signer_info *signer) +{ + mbedtls_x509_name *name_cur; + mbedtls_x509_name *name_prv; + + if (signer == NULL) { + return; + } + + name_cur = signer->issuer.next; + while (name_cur != NULL) { + name_prv = name_cur; + name_cur = name_cur->next; + mbedtls_free(name_prv); + } + signer->issuer.next = NULL; +} + +/** + * SignerInfo ::= SEQUENCE { + * version Version; + * issuerAndSerialNumber IssuerAndSerialNumber, + * digestAlgorithm DigestAlgorithmIdentifier, + * authenticatedAttributes + * [0] IMPLICIT Attributes OPTIONAL, + * digestEncryptionAlgorithm DigestEncryptionAlgorithmIdentifier, + * encryptedDigest EncryptedDigest, + * unauthenticatedAttributes + * [1] IMPLICIT Attributes OPTIONAL, + * Returns 0 if the signerInfo is valid. + * Return negative error code for failure. + * Structure must not contain vales for authenticatedAttributes + * and unauthenticatedAttributes. + **/ +static int pkcs7_get_signer_info(unsigned char **p, unsigned char *end, + mbedtls_pkcs7_signer_info *signer, + mbedtls_x509_buf *alg) +{ + unsigned char *end_signer, *end_issuer_and_sn; + int asn1_ret = 0, ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED; + size_t len = 0; + + asn1_ret = mbedtls_asn1_get_tag(p, end, &len, MBEDTLS_ASN1_CONSTRUCTED + | MBEDTLS_ASN1_SEQUENCE); + if (asn1_ret != 0) { + goto out; + } + + end_signer = *p + len; + + ret = pkcs7_get_version(p, end_signer, &signer->version); + if (ret != 0) { + goto out; + } + + asn1_ret = mbedtls_asn1_get_tag(p, end_signer, &len, + MBEDTLS_ASN1_CONSTRUCTED | MBEDTLS_ASN1_SEQUENCE); + if (asn1_ret != 0) { + goto out; + } + + end_issuer_and_sn = *p + len; + /* Parsing IssuerAndSerialNumber */ + signer->issuer_raw.p = *p; + + asn1_ret = mbedtls_asn1_get_tag(p, end_issuer_and_sn, &len, + MBEDTLS_ASN1_CONSTRUCTED | MBEDTLS_ASN1_SEQUENCE); + if (asn1_ret != 0) { + goto out; + } + + ret = mbedtls_x509_get_name(p, *p + len, &signer->issuer); + if (ret != 0) { + goto out; + } + + signer->issuer_raw.len = (size_t) (*p - signer->issuer_raw.p); + + ret = mbedtls_x509_get_serial(p, end_issuer_and_sn, &signer->serial); + if (ret != 0) { + goto out; + } + + /* ensure no extra or missing bytes */ + if (*p != end_issuer_and_sn) { + ret = MBEDTLS_ERR_PKCS7_INVALID_SIGNER_INFO; + goto out; + } + + ret = pkcs7_get_digest_algorithm(p, end_signer, &signer->alg_identifier); + if (ret != 0) { + goto out; + } + + /* Check that the digest algorithm used matches the one provided earlier */ + if (signer->alg_identifier.tag != alg->tag || + signer->alg_identifier.len != alg->len || + memcmp(signer->alg_identifier.p, alg->p, alg->len) != 0) { + ret = MBEDTLS_ERR_PKCS7_INVALID_SIGNER_INFO; + goto out; + } + + /* Assume authenticatedAttributes is nonexistent */ + ret = pkcs7_get_digest_algorithm(p, end_signer, &signer->sig_alg_identifier); + if (ret != 0) { + goto out; + } + + ret = pkcs7_get_signature(p, end_signer, &signer->sig); + if (ret != 0) { + goto out; + } + + /* Do not permit any unauthenticated attributes */ + if (*p != end_signer) { + ret = MBEDTLS_ERR_PKCS7_INVALID_SIGNER_INFO; + } + +out: + if (asn1_ret != 0 || ret != 0) { + pkcs7_free_signer_info(signer); + ret = MBEDTLS_ERROR_ADD(MBEDTLS_ERR_PKCS7_INVALID_SIGNER_INFO, + asn1_ret); + } + + return ret; +} + +/** + * SignerInfos ::= SET of SignerInfo + * Return number of signers added to the signed data, + * 0 or higher is valid. + * Return negative error code for failure. + **/ +static int pkcs7_get_signers_info_set(unsigned char **p, unsigned char *end, + mbedtls_pkcs7_signer_info *signers_set, + mbedtls_x509_buf *digest_alg) +{ + unsigned char *end_set; + int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED; + int count = 0; + size_t len = 0; + + ret = mbedtls_asn1_get_tag(p, end, &len, MBEDTLS_ASN1_CONSTRUCTED + | MBEDTLS_ASN1_SET); + if (ret != 0) { + return MBEDTLS_ERROR_ADD(MBEDTLS_ERR_PKCS7_INVALID_SIGNER_INFO, ret); + } + + /* Detect zero signers */ + if (len == 0) { + return 0; + } + + end_set = *p + len; + + ret = pkcs7_get_signer_info(p, end_set, signers_set, digest_alg); + if (ret != 0) { + return ret; + } + count++; + + mbedtls_pkcs7_signer_info *prev = signers_set; + while (*p != end_set) { + mbedtls_pkcs7_signer_info *signer = + mbedtls_calloc(1, sizeof(mbedtls_pkcs7_signer_info)); + if (!signer) { + ret = MBEDTLS_ERR_PKCS7_ALLOC_FAILED; + goto cleanup; + } + + ret = pkcs7_get_signer_info(p, end_set, signer, digest_alg); + if (ret != 0) { + mbedtls_free(signer); + goto cleanup; + } + prev->next = signer; + prev = signer; + count++; + } + + return count; + +cleanup: + pkcs7_free_signer_info(signers_set); + mbedtls_pkcs7_signer_info *signer = signers_set->next; + while (signer != NULL) { + prev = signer; + signer = signer->next; + pkcs7_free_signer_info(prev); + mbedtls_free(prev); + } + signers_set->next = NULL; + return ret; +} + +/** + * SignedData ::= SEQUENCE { + * version Version, + * digestAlgorithms DigestAlgorithmIdentifiers, + * contentInfo ContentInfo, + * certificates + * [0] IMPLICIT ExtendedCertificatesAndCertificates + * OPTIONAL, + * crls + * [0] IMPLICIT CertificateRevocationLists OPTIONAL, + * signerInfos SignerInfos } + */ +static int pkcs7_get_signed_data(unsigned char *buf, size_t buflen, + mbedtls_pkcs7_signed_data *signed_data) +{ + unsigned char *p = buf; + unsigned char *end = buf + buflen; + unsigned char *end_content_info = NULL; + size_t len = 0; + int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED; + mbedtls_md_type_t md_alg; + + ret = mbedtls_asn1_get_tag(&p, end, &len, MBEDTLS_ASN1_CONSTRUCTED + | MBEDTLS_ASN1_SEQUENCE); + if (ret != 0) { + return MBEDTLS_ERROR_ADD(MBEDTLS_ERR_PKCS7_INVALID_FORMAT, ret); + } + + if (p + len != end) { + return MBEDTLS_ERROR_ADD(MBEDTLS_ERR_PKCS7_INVALID_FORMAT, + MBEDTLS_ERR_ASN1_LENGTH_MISMATCH); + } + + /* Get version of signed data */ + ret = pkcs7_get_version(&p, end, &signed_data->version); + if (ret != 0) { + return ret; + } + + /* Get digest algorithm */ + ret = pkcs7_get_digest_algorithm_set(&p, end, + &signed_data->digest_alg_identifiers); + if (ret != 0) { + return ret; + } + + ret = mbedtls_oid_get_md_alg(&signed_data->digest_alg_identifiers, &md_alg); + if (ret != 0) { + return MBEDTLS_ERR_PKCS7_INVALID_ALG; + } + + mbedtls_pkcs7_buf content_type; + memset(&content_type, 0, sizeof(content_type)); + ret = pkcs7_get_content_info_type(&p, end, &end_content_info, &content_type); + if (ret != 0) { + return ret; + } + if (MBEDTLS_OID_CMP(MBEDTLS_OID_PKCS7_DATA, &content_type)) { + return MBEDTLS_ERR_PKCS7_INVALID_CONTENT_INFO; + } + + if (p != end_content_info) { + /* Determine if valid content is present */ + ret = mbedtls_asn1_get_tag(&p, + end_content_info, + &len, + MBEDTLS_ASN1_CONSTRUCTED | MBEDTLS_ASN1_CONTEXT_SPECIFIC); + if (ret != 0) { + return MBEDTLS_ERROR_ADD(MBEDTLS_ERR_PKCS7_INVALID_CONTENT_INFO, ret); + } + p += len; + if (p != end_content_info) { + return MBEDTLS_ERROR_ADD(MBEDTLS_ERR_PKCS7_INVALID_CONTENT_INFO, ret); + } + /* Valid content is present - this is not supported */ + return MBEDTLS_ERR_PKCS7_FEATURE_UNAVAILABLE; + } + + /* Look for certificates, there may or may not be any */ + mbedtls_x509_crt_init(&signed_data->certs); + ret = pkcs7_get_certificates(&p, end, &signed_data->certs); + if (ret < 0) { + return ret; + } + + signed_data->no_of_certs = ret; + + /* + * Currently CRLs are not supported. If CRL exist, the parsing will fail + * at next step of getting signers info and return error as invalid + * signer info. + */ + + signed_data->no_of_crls = 0; + + /* Get signers info */ + ret = pkcs7_get_signers_info_set(&p, + end, + &signed_data->signers, + &signed_data->digest_alg_identifiers); + if (ret < 0) { + return ret; + } + + signed_data->no_of_signers = ret; + + /* Don't permit trailing data */ + if (p != end) { + return MBEDTLS_ERR_PKCS7_INVALID_FORMAT; + } + + return 0; +} + +int mbedtls_pkcs7_parse_der(mbedtls_pkcs7 *pkcs7, const unsigned char *buf, + const size_t buflen) +{ + unsigned char *p; + unsigned char *end; + size_t len = 0; + int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED; + + if (pkcs7 == NULL) { + return MBEDTLS_ERR_PKCS7_BAD_INPUT_DATA; + } + + /* make an internal copy of the buffer for parsing */ + pkcs7->raw.p = p = mbedtls_calloc(1, buflen); + if (pkcs7->raw.p == NULL) { + ret = MBEDTLS_ERR_PKCS7_ALLOC_FAILED; + goto out; + } + memcpy(p, buf, buflen); + pkcs7->raw.len = buflen; + end = p + buflen; + + ret = mbedtls_asn1_get_tag(&p, end, &len, MBEDTLS_ASN1_CONSTRUCTED + | MBEDTLS_ASN1_SEQUENCE); + if (ret != 0) { + ret = MBEDTLS_ERROR_ADD(MBEDTLS_ERR_PKCS7_INVALID_FORMAT, ret); + goto out; + } + + if ((size_t) (end - p) != len) { + ret = MBEDTLS_ERROR_ADD(MBEDTLS_ERR_PKCS7_INVALID_FORMAT, + MBEDTLS_ERR_ASN1_LENGTH_MISMATCH); + goto out; + } + + if ((ret = mbedtls_asn1_get_tag(&p, end, &len, MBEDTLS_ASN1_OID)) != 0) { + if (ret != MBEDTLS_ERR_ASN1_UNEXPECTED_TAG) { + goto out; + } + p = pkcs7->raw.p; + len = buflen; + goto try_data; + } + + if (MBEDTLS_OID_CMP_RAW(MBEDTLS_OID_PKCS7_SIGNED_DATA, p, len)) { + /* OID is not MBEDTLS_OID_PKCS7_SIGNED_DATA, which is the only supported feature */ + if (!MBEDTLS_OID_CMP_RAW(MBEDTLS_OID_PKCS7_DATA, p, len) + || !MBEDTLS_OID_CMP_RAW(MBEDTLS_OID_PKCS7_ENCRYPTED_DATA, p, len) + || !MBEDTLS_OID_CMP_RAW(MBEDTLS_OID_PKCS7_ENVELOPED_DATA, p, len) + || !MBEDTLS_OID_CMP_RAW(MBEDTLS_OID_PKCS7_SIGNED_AND_ENVELOPED_DATA, p, len) + || !MBEDTLS_OID_CMP_RAW(MBEDTLS_OID_PKCS7_DIGESTED_DATA, p, len)) { + /* OID is valid according to the spec, but unsupported */ + ret = MBEDTLS_ERR_PKCS7_FEATURE_UNAVAILABLE; + } else { + /* OID is invalid according to the spec */ + ret = MBEDTLS_ERR_PKCS7_BAD_INPUT_DATA; + } + goto out; + } + + p += len; + + ret = pkcs7_get_next_content_len(&p, end, &len); + if (ret != 0) { + goto out; + } + + /* ensure no extra/missing data */ + if (p + len != end) { + ret = MBEDTLS_ERR_PKCS7_BAD_INPUT_DATA; + goto out; + } + +try_data: + ret = pkcs7_get_signed_data(p, len, &pkcs7->signed_data); + if (ret != 0) { + goto out; + } + + ret = MBEDTLS_PKCS7_SIGNED_DATA; + +out: + if (ret < 0) { + mbedtls_pkcs7_free(pkcs7); + } + + return ret; +} + +static int mbedtls_pkcs7_data_or_hash_verify(mbedtls_pkcs7 *pkcs7, + const mbedtls_x509_crt *cert, + const unsigned char *data, + size_t datalen, + const int is_data_hash) +{ + int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED; + unsigned char *hash; + mbedtls_pk_context pk_cxt = cert->pk; + const mbedtls_md_info_t *md_info; + mbedtls_md_type_t md_alg; + mbedtls_pkcs7_signer_info *signer; + + if (pkcs7->signed_data.no_of_signers == 0) { + return MBEDTLS_ERR_PKCS7_INVALID_CERT; + } + + if (mbedtls_x509_time_is_past(&cert->valid_to) || + mbedtls_x509_time_is_future(&cert->valid_from)) { + return MBEDTLS_ERR_PKCS7_CERT_DATE_INVALID; + } + + ret = mbedtls_oid_get_md_alg(&pkcs7->signed_data.digest_alg_identifiers, &md_alg); + if (ret != 0) { + return ret; + } + + md_info = mbedtls_md_info_from_type(md_alg); + if (md_info == NULL) { + return MBEDTLS_ERR_PKCS7_VERIFY_FAIL; + } + + hash = mbedtls_calloc(mbedtls_md_get_size(md_info), 1); + if (hash == NULL) { + return MBEDTLS_ERR_PKCS7_ALLOC_FAILED; + } + + /* BEGIN must free hash before jumping out */ + if (is_data_hash) { + if (datalen != mbedtls_md_get_size(md_info)) { + ret = MBEDTLS_ERR_PKCS7_VERIFY_FAIL; + } else { + memcpy(hash, data, datalen); + } + } else { + ret = mbedtls_md(md_info, data, datalen, hash); + } + if (ret != 0) { + mbedtls_free(hash); + return MBEDTLS_ERR_PKCS7_VERIFY_FAIL; + } + + /* assume failure */ + ret = MBEDTLS_ERR_PKCS7_VERIFY_FAIL; + + /* + * Potential TODOs + * Currently we iterate over all signers and return success if any of them + * verify. + * + * However, we could make this better by checking against the certificate's + * identification and SignerIdentifier fields first. That would also allow + * us to distinguish between 'no signature for key' and 'signature for key + * failed to validate'. + */ + for (signer = &pkcs7->signed_data.signers; signer; signer = signer->next) { + ret = mbedtls_pk_verify(&pk_cxt, md_alg, hash, + mbedtls_md_get_size(md_info), + signer->sig.p, signer->sig.len); + + if (ret == 0) { + break; + } + } + + mbedtls_free(hash); + /* END must free hash before jumping out */ + return ret; +} + +int mbedtls_pkcs7_signed_data_verify(mbedtls_pkcs7 *pkcs7, + const mbedtls_x509_crt *cert, + const unsigned char *data, + size_t datalen) +{ + if (data == NULL) { + return MBEDTLS_ERR_PKCS7_BAD_INPUT_DATA; + } + return mbedtls_pkcs7_data_or_hash_verify(pkcs7, cert, data, datalen, 0); +} + +int mbedtls_pkcs7_signed_hash_verify(mbedtls_pkcs7 *pkcs7, + const mbedtls_x509_crt *cert, + const unsigned char *hash, + size_t hashlen) +{ + if (hash == NULL) { + return MBEDTLS_ERR_PKCS7_BAD_INPUT_DATA; + } + return mbedtls_pkcs7_data_or_hash_verify(pkcs7, cert, hash, hashlen, 1); +} + +/* + * Unallocate all pkcs7 data + */ +void mbedtls_pkcs7_free(mbedtls_pkcs7 *pkcs7) +{ + mbedtls_pkcs7_signer_info *signer_cur; + mbedtls_pkcs7_signer_info *signer_prev; + + if (pkcs7 == NULL || pkcs7->raw.p == NULL) { + return; + } + + mbedtls_free(pkcs7->raw.p); + + mbedtls_x509_crt_free(&pkcs7->signed_data.certs); + mbedtls_x509_crl_free(&pkcs7->signed_data.crl); + + signer_cur = pkcs7->signed_data.signers.next; + pkcs7_free_signer_info(&pkcs7->signed_data.signers); + while (signer_cur != NULL) { + signer_prev = signer_cur; + signer_cur = signer_prev->next; + pkcs7_free_signer_info(signer_prev); + mbedtls_free(signer_prev); + } + + pkcs7->raw.p = NULL; +} + +#endif diff --git a/vendor/mbedtls/library/pkparse.c b/vendor/mbedtls/library/pkparse.c index 76fe0c81e4..4f6ee13986 100644 --- a/vendor/mbedtls/library/pkparse.c +++ b/vendor/mbedtls/library/pkparse.c @@ -2,19 +2,7 @@ * Public Key layer for parsing key files and structures * * Copyright The Mbed TLS Contributors - * SPDX-License-Identifier: Apache-2.0 - * - * Licensed under the Apache License, Version 2.0 (the "License"); you may - * not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT - * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. + * SPDX-License-Identifier: Apache-2.0 OR GPL-2.0-or-later */ #include "common.h" @@ -25,19 +13,25 @@ #include "mbedtls/asn1.h" #include "mbedtls/oid.h" #include "mbedtls/platform_util.h" +#include "mbedtls/platform.h" #include "mbedtls/error.h" +#include "mbedtls/ecp.h" +#include "pk_internal.h" #include +#if defined(MBEDTLS_USE_PSA_CRYPTO) +#include "mbedtls/psa_util.h" +#include "psa/crypto.h" +#endif + +/* Key types */ #if defined(MBEDTLS_RSA_C) #include "mbedtls/rsa.h" +#include "rsa_internal.h" #endif -#if defined(MBEDTLS_ECP_C) -#include "mbedtls/ecp.h" -#endif -#if defined(MBEDTLS_ECDSA_C) -#include "mbedtls/ecdsa.h" -#endif + +/* Extended formats */ #if defined(MBEDTLS_PEM_PARSE_C) #include "mbedtls/pem.h" #endif @@ -48,175 +42,55 @@ #include "mbedtls/pkcs12.h" #endif -#include "mbedtls/platform.h" - -/* Parameter validation macros based on platform_util.h */ -#define PK_VALIDATE_RET(cond) \ - MBEDTLS_INTERNAL_VALIDATE_RET(cond, MBEDTLS_ERR_PK_BAD_INPUT_DATA) -#define PK_VALIDATE(cond) \ - MBEDTLS_INTERNAL_VALIDATE(cond) +#if defined(MBEDTLS_PK_HAVE_ECC_KEYS) -#if defined(MBEDTLS_FS_IO) -/* - * Load all data from a file into a given buffer. +/*********************************************************************** * - * The file is expected to contain either PEM or DER encoded data. - * A terminating null byte is always appended. It is included in the announced - * length only if the data looks like it is PEM encoded. - */ -int mbedtls_pk_load_file(const char *path, unsigned char **buf, size_t *n) -{ - FILE *f; - long size; - - PK_VALIDATE_RET(path != NULL); - PK_VALIDATE_RET(buf != NULL); - PK_VALIDATE_RET(n != NULL); - - if ((f = fopen(path, "rb")) == NULL) { - return MBEDTLS_ERR_PK_FILE_IO_ERROR; - } - - fseek(f, 0, SEEK_END); - if ((size = ftell(f)) == -1) { - fclose(f); - return MBEDTLS_ERR_PK_FILE_IO_ERROR; - } - fseek(f, 0, SEEK_SET); - - *n = (size_t) size; - - if (*n + 1 == 0 || - (*buf = mbedtls_calloc(1, *n + 1)) == NULL) { - fclose(f); - return MBEDTLS_ERR_PK_ALLOC_FAILED; - } - - if (fread(*buf, 1, *n, f) != *n) { - fclose(f); - - mbedtls_platform_zeroize(*buf, *n); - mbedtls_free(*buf); - - return MBEDTLS_ERR_PK_FILE_IO_ERROR; - } - - fclose(f); - - (*buf)[*n] = '\0'; - - if (strstr((const char *) *buf, "-----BEGIN ") != NULL) { - ++*n; - } + * Low-level ECC parsing: optional support for SpecifiedECDomain + * + * There are two functions here that are used by the rest of the code: + * - pk_ecc_tag_is_speficied_ec_domain() + * - pk_ecc_group_id_from_specified() + * + * All the other functions are internal to this section. + * + * The two "public" functions have a dummy variant provided + * in configs without MBEDTLS_PK_PARSE_EC_EXTENDED. This acts as an + * abstraction layer for this macro, which should not appear outside + * this section. + * + **********************************************************************/ +#if !defined(MBEDTLS_PK_PARSE_EC_EXTENDED) +/* See the "real" version for documentation */ +static int pk_ecc_tag_is_specified_ec_domain(int tag) +{ + (void) tag; return 0; } -/* - * Load and parse a private key - */ -int mbedtls_pk_parse_keyfile(mbedtls_pk_context *ctx, - const char *path, const char *pwd) +/* See the "real" version for documentation */ +static int pk_ecc_group_id_from_specified(const mbedtls_asn1_buf *params, + mbedtls_ecp_group_id *grp_id) { - int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED; - size_t n; - unsigned char *buf; - - PK_VALIDATE_RET(ctx != NULL); - PK_VALIDATE_RET(path != NULL); - - if ((ret = mbedtls_pk_load_file(path, &buf, &n)) != 0) { - return ret; - } - - if (pwd == NULL) { - ret = mbedtls_pk_parse_key(ctx, buf, n, NULL, 0); - } else { - ret = mbedtls_pk_parse_key(ctx, buf, n, - (const unsigned char *) pwd, strlen(pwd)); - } - - mbedtls_platform_zeroize(buf, n); - mbedtls_free(buf); - - return ret; + (void) params; + (void) grp_id; + return MBEDTLS_ERR_ECP_FEATURE_UNAVAILABLE; } - +#else /* MBEDTLS_PK_PARSE_EC_EXTENDED */ /* - * Load and parse a public key - */ -int mbedtls_pk_parse_public_keyfile(mbedtls_pk_context *ctx, const char *path) -{ - int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED; - size_t n; - unsigned char *buf; - - PK_VALIDATE_RET(ctx != NULL); - PK_VALIDATE_RET(path != NULL); - - if ((ret = mbedtls_pk_load_file(path, &buf, &n)) != 0) { - return ret; - } - - ret = mbedtls_pk_parse_public_key(ctx, buf, n); - - mbedtls_platform_zeroize(buf, n); - mbedtls_free(buf); - - return ret; -} -#endif /* MBEDTLS_FS_IO */ - -#if defined(MBEDTLS_ECP_C) -/* Minimally parse an ECParameters buffer to and mbedtls_asn1_buf - * - * ECParameters ::= CHOICE { - * namedCurve OBJECT IDENTIFIER - * specifiedCurve SpecifiedECDomain -- = SEQUENCE { ... } - * -- implicitCurve NULL - * } + * Tell if the passed tag might be the start of SpecifiedECDomain + * (that is, a sequence). */ -static int pk_get_ecparams(unsigned char **p, const unsigned char *end, - mbedtls_asn1_buf *params) +static int pk_ecc_tag_is_specified_ec_domain(int tag) { - int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED; - - if (end - *p < 1) { - return MBEDTLS_ERROR_ADD(MBEDTLS_ERR_PK_KEY_INVALID_FORMAT, - MBEDTLS_ERR_ASN1_OUT_OF_DATA); - } - - /* Tag may be either OID or SEQUENCE */ - params->tag = **p; - if (params->tag != MBEDTLS_ASN1_OID -#if defined(MBEDTLS_PK_PARSE_EC_EXTENDED) - && params->tag != (MBEDTLS_ASN1_CONSTRUCTED | MBEDTLS_ASN1_SEQUENCE) -#endif - ) { - return MBEDTLS_ERROR_ADD(MBEDTLS_ERR_PK_KEY_INVALID_FORMAT, - MBEDTLS_ERR_ASN1_UNEXPECTED_TAG); - } - - if ((ret = mbedtls_asn1_get_tag(p, end, ¶ms->len, params->tag)) != 0) { - return MBEDTLS_ERROR_ADD(MBEDTLS_ERR_PK_KEY_INVALID_FORMAT, ret); - } - - params->p = *p; - *p += params->len; - - if (*p != end) { - return MBEDTLS_ERROR_ADD(MBEDTLS_ERR_PK_KEY_INVALID_FORMAT, - MBEDTLS_ERR_ASN1_LENGTH_MISMATCH); - } - - return 0; + return tag == (MBEDTLS_ASN1_CONSTRUCTED | MBEDTLS_ASN1_SEQUENCE); } -#if defined(MBEDTLS_PK_PARSE_EC_EXTENDED) /* * Parse a SpecifiedECDomain (SEC 1 C.2) and (mostly) fill the group with it. * WARNING: the resulting group should only be used with - * pk_group_id_from_specified(), since its base point may not be set correctly + * pk_ecc_group_id_from_specified(), since its base point may not be set correctly * if it was encoded compressed. * * SpecifiedECDomain ::= SEQUENCE { @@ -236,7 +110,7 @@ static int pk_group_from_specified(const mbedtls_asn1_buf *params, mbedtls_ecp_g { int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED; unsigned char *p = params->p; - const unsigned char * const end = params->p + params->len; + const unsigned char *const end = params->p + params->len; const unsigned char *end_field, *end_curve; size_t len; int ver; @@ -408,7 +282,6 @@ static int pk_group_id_from_group(const mbedtls_ecp_group *grp, mbedtls_ecp_grou mbedtls_mpi_get_bit(&grp->G.Y, 0) == mbedtls_mpi_get_bit(&ref.G.Y, 0)) { break; } - } cleanup: @@ -426,8 +299,8 @@ static int pk_group_id_from_group(const mbedtls_ecp_group *grp, mbedtls_ecp_grou /* * Parse a SpecifiedECDomain (SEC 1 C.2) and find the associated group ID */ -static int pk_group_id_from_specified(const mbedtls_asn1_buf *params, - mbedtls_ecp_group_id *grp_id) +static int pk_ecc_group_id_from_specified(const mbedtls_asn1_buf *params, + mbedtls_ecp_group_id *grp_id) { int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED; mbedtls_ecp_group grp; @@ -441,12 +314,70 @@ static int pk_group_id_from_specified(const mbedtls_asn1_buf *params, ret = pk_group_id_from_group(&grp, grp_id); cleanup: - mbedtls_ecp_group_free(&grp); + /* The API respecting lifecycle for mbedtls_ecp_group struct is + * _init(), _load() and _free(). In pk_ecc_group_id_from_specified() the + * temporary grp breaks that flow and it's members are populated + * by pk_group_id_from_group(). As such mbedtls_ecp_group_free() + * which is assuming a group populated by _setup() may not clean-up + * properly -> Manually free it's members. + */ + mbedtls_mpi_free(&grp.N); + mbedtls_mpi_free(&grp.P); + mbedtls_mpi_free(&grp.A); + mbedtls_mpi_free(&grp.B); + mbedtls_ecp_point_free(&grp.G); return ret; } #endif /* MBEDTLS_PK_PARSE_EC_EXTENDED */ +/*********************************************************************** + * + * Unsorted (yet!) from this point on until the next section header + * + **********************************************************************/ + +/* Minimally parse an ECParameters buffer to and mbedtls_asn1_buf + * + * ECParameters ::= CHOICE { + * namedCurve OBJECT IDENTIFIER + * specifiedCurve SpecifiedECDomain -- = SEQUENCE { ... } + * -- implicitCurve NULL + * } + */ +static int pk_get_ecparams(unsigned char **p, const unsigned char *end, + mbedtls_asn1_buf *params) +{ + int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED; + + if (end - *p < 1) { + return MBEDTLS_ERROR_ADD(MBEDTLS_ERR_PK_KEY_INVALID_FORMAT, + MBEDTLS_ERR_ASN1_OUT_OF_DATA); + } + + /* Acceptable tags: OID for namedCurve, or specifiedECDomain */ + params->tag = **p; + if (params->tag != MBEDTLS_ASN1_OID && + !pk_ecc_tag_is_specified_ec_domain(params->tag)) { + return MBEDTLS_ERROR_ADD(MBEDTLS_ERR_PK_KEY_INVALID_FORMAT, + MBEDTLS_ERR_ASN1_UNEXPECTED_TAG); + } + + if ((ret = mbedtls_asn1_get_tag(p, end, ¶ms->len, params->tag)) != 0) { + return MBEDTLS_ERROR_ADD(MBEDTLS_ERR_PK_KEY_INVALID_FORMAT, ret); + } + + params->p = *p; + *p += params->len; + + if (*p != end) { + return MBEDTLS_ERROR_ADD(MBEDTLS_ERR_PK_KEY_INVALID_FORMAT, + MBEDTLS_ERR_ASN1_LENGTH_MISMATCH); + } + + return 0; +} + /* * Use EC parameters to initialise an EC group * @@ -455,7 +386,7 @@ static int pk_group_id_from_specified(const mbedtls_asn1_buf *params, * specifiedCurve SpecifiedECDomain -- = SEQUENCE { ... } * -- implicitCurve NULL */ -static int pk_use_ecparams(const mbedtls_asn1_buf *params, mbedtls_ecp_group *grp) +static int pk_use_ecparams(const mbedtls_asn1_buf *params, mbedtls_pk_context *pk) { int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED; mbedtls_ecp_group_id grp_id; @@ -465,116 +396,71 @@ static int pk_use_ecparams(const mbedtls_asn1_buf *params, mbedtls_ecp_group *gr return MBEDTLS_ERR_PK_UNKNOWN_NAMED_CURVE; } } else { -#if defined(MBEDTLS_PK_PARSE_EC_EXTENDED) - if ((ret = pk_group_id_from_specified(params, &grp_id)) != 0) { + ret = pk_ecc_group_id_from_specified(params, &grp_id); + if (ret != 0) { return ret; } -#else - return MBEDTLS_ERR_PK_KEY_INVALID_FORMAT; -#endif } - /* - * grp may already be initialized; if so, make sure IDs match - */ - if (grp->id != MBEDTLS_ECP_DP_NONE && grp->id != grp_id) { - return MBEDTLS_ERR_PK_KEY_INVALID_FORMAT; - } - - if ((ret = mbedtls_ecp_group_load(grp, grp_id)) != 0) { - return ret; - } - - return 0; + return mbedtls_pk_ecc_set_group(pk, grp_id); } +#if defined(MBEDTLS_PK_HAVE_RFC8410_CURVES) + /* - * EC public key is an EC point - * - * The caller is responsible for clearing the structure upon failure if - * desired. Take care to pass along the possible ECP_FEATURE_UNAVAILABLE - * return code of mbedtls_ecp_point_read_binary() and leave p in a usable state. + * Load an RFC8410 EC key, which doesn't have any parameters */ -static int pk_get_ecpubkey(unsigned char **p, const unsigned char *end, - mbedtls_ecp_keypair *key) +static int pk_use_ecparams_rfc8410(const mbedtls_asn1_buf *params, + mbedtls_ecp_group_id grp_id, + mbedtls_pk_context *pk) { - int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED; - - if ((ret = mbedtls_ecp_point_read_binary(&key->grp, &key->Q, - (const unsigned char *) *p, end - *p)) == 0) { - ret = mbedtls_ecp_check_pubkey(&key->grp, &key->Q); + if (params->tag != 0 || params->len != 0) { + return MBEDTLS_ERR_PK_KEY_INVALID_FORMAT; } - /* - * We know mbedtls_ecp_point_read_binary consumed all bytes or failed - */ - *p = (unsigned char *) end; - - return ret; + return mbedtls_pk_ecc_set_group(pk, grp_id); } -#endif /* MBEDTLS_ECP_C */ -#if defined(MBEDTLS_RSA_C) /* - * RSAPublicKey ::= SEQUENCE { - * modulus INTEGER, -- n - * publicExponent INTEGER -- e - * } + * Parse an RFC 8410 encoded private EC key + * + * CurvePrivateKey ::= OCTET STRING */ -static int pk_get_rsapubkey(unsigned char **p, - const unsigned char *end, - mbedtls_rsa_context *rsa) +static int pk_parse_key_rfc8410_der(mbedtls_pk_context *pk, + unsigned char *key, size_t keylen, const unsigned char *end, + int (*f_rng)(void *, unsigned char *, size_t), void *p_rng) { int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED; size_t len; - if ((ret = mbedtls_asn1_get_tag(p, end, &len, - MBEDTLS_ASN1_CONSTRUCTED | MBEDTLS_ASN1_SEQUENCE)) != 0) { - return MBEDTLS_ERROR_ADD(MBEDTLS_ERR_PK_INVALID_PUBKEY, ret); - } - - if (*p + len != end) { - return MBEDTLS_ERROR_ADD(MBEDTLS_ERR_PK_INVALID_PUBKEY, - MBEDTLS_ERR_ASN1_LENGTH_MISMATCH); - } - - /* Import N */ - if ((ret = mbedtls_asn1_get_tag(p, end, &len, MBEDTLS_ASN1_INTEGER)) != 0) { - return MBEDTLS_ERROR_ADD(MBEDTLS_ERR_PK_INVALID_PUBKEY, ret); - } - - if ((ret = mbedtls_rsa_import_raw(rsa, *p, len, NULL, 0, NULL, 0, - NULL, 0, NULL, 0)) != 0) { - return MBEDTLS_ERR_PK_INVALID_PUBKEY; - } - - *p += len; - - /* Import E */ - if ((ret = mbedtls_asn1_get_tag(p, end, &len, MBEDTLS_ASN1_INTEGER)) != 0) { - return MBEDTLS_ERROR_ADD(MBEDTLS_ERR_PK_INVALID_PUBKEY, ret); + if ((ret = mbedtls_asn1_get_tag(&key, (key + keylen), &len, MBEDTLS_ASN1_OCTET_STRING)) != 0) { + return MBEDTLS_ERROR_ADD(MBEDTLS_ERR_PK_KEY_INVALID_FORMAT, ret); } - if ((ret = mbedtls_rsa_import_raw(rsa, NULL, 0, NULL, 0, NULL, 0, - NULL, 0, *p, len)) != 0) { - return MBEDTLS_ERR_PK_INVALID_PUBKEY; + if (key + len != end) { + return MBEDTLS_ERR_PK_KEY_INVALID_FORMAT; } - *p += len; - - if (mbedtls_rsa_complete(rsa) != 0 || - mbedtls_rsa_check_pubkey(rsa) != 0) { - return MBEDTLS_ERR_PK_INVALID_PUBKEY; + /* + * Load the private key + */ + ret = mbedtls_pk_ecc_set_key(pk, key, len); + if (ret != 0) { + return ret; } - if (*p != end) { - return MBEDTLS_ERROR_ADD(MBEDTLS_ERR_PK_INVALID_PUBKEY, - MBEDTLS_ERR_ASN1_LENGTH_MISMATCH); + /* pk_parse_key_pkcs8_unencrypted_der() only supports version 1 PKCS8 keys, + * which never contain a public key. As such, derive the public key + * unconditionally. */ + if ((ret = mbedtls_pk_ecc_set_pubkey_from_prv(pk, key, len, f_rng, p_rng)) != 0) { + return ret; } return 0; } -#endif /* MBEDTLS_RSA_C */ +#endif /* MBEDTLS_PK_HAVE_RFC8410_CURVES */ + +#endif /* MBEDTLS_PK_HAVE_ECC_KEYS */ /* Get a PK algorithm identifier * @@ -584,7 +470,8 @@ static int pk_get_rsapubkey(unsigned char **p, */ static int pk_get_pk_alg(unsigned char **p, const unsigned char *end, - mbedtls_pk_type_t *pk_alg, mbedtls_asn1_buf *params) + mbedtls_pk_type_t *pk_alg, mbedtls_asn1_buf *params, + mbedtls_ecp_group_id *ec_grp_id) { int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED; mbedtls_asn1_buf alg_oid; @@ -595,7 +482,18 @@ static int pk_get_pk_alg(unsigned char **p, return MBEDTLS_ERROR_ADD(MBEDTLS_ERR_PK_INVALID_ALG, ret); } - if (mbedtls_oid_get_pk_alg(&alg_oid, pk_alg) != 0) { + ret = mbedtls_oid_get_pk_alg(&alg_oid, pk_alg); +#if defined(MBEDTLS_PK_HAVE_ECC_KEYS) + if (ret == MBEDTLS_ERR_OID_NOT_FOUND) { + ret = mbedtls_oid_get_ec_grp_algid(&alg_oid, ec_grp_id); + if (ret == 0) { + *pk_alg = MBEDTLS_PK_ECKEY; + } + } +#else + (void) ec_grp_id; +#endif + if (ret != 0) { return MBEDTLS_ERR_PK_UNKNOWN_PK_ALG; } @@ -623,13 +521,9 @@ int mbedtls_pk_parse_subpubkey(unsigned char **p, const unsigned char *end, size_t len; mbedtls_asn1_buf alg_params; mbedtls_pk_type_t pk_alg = MBEDTLS_PK_NONE; + mbedtls_ecp_group_id ec_grp_id = MBEDTLS_ECP_DP_NONE; const mbedtls_pk_info_t *pk_info; - PK_VALIDATE_RET(p != NULL); - PK_VALIDATE_RET(*p != NULL); - PK_VALIDATE_RET(end != NULL); - PK_VALIDATE_RET(pk != NULL); - if ((ret = mbedtls_asn1_get_tag(p, end, &len, MBEDTLS_ASN1_CONSTRUCTED | MBEDTLS_ASN1_SEQUENCE)) != 0) { return MBEDTLS_ERROR_ADD(MBEDTLS_ERR_PK_KEY_INVALID_FORMAT, ret); @@ -637,7 +531,7 @@ int mbedtls_pk_parse_subpubkey(unsigned char **p, const unsigned char *end, end = *p + len; - if ((ret = pk_get_pk_alg(p, end, &pk_alg, &alg_params)) != 0) { + if ((ret = pk_get_pk_alg(p, end, &pk_alg, &alg_params, &ec_grp_id)) != 0) { return ret; } @@ -660,17 +554,35 @@ int mbedtls_pk_parse_subpubkey(unsigned char **p, const unsigned char *end, #if defined(MBEDTLS_RSA_C) if (pk_alg == MBEDTLS_PK_RSA) { - ret = pk_get_rsapubkey(p, end, mbedtls_pk_rsa(*pk)); + ret = mbedtls_rsa_parse_pubkey(mbedtls_pk_rsa(*pk), *p, (size_t) (end - *p)); + if (ret == 0) { + /* On success all the input has been consumed by the parsing function. */ + *p += end - *p; + } else if ((ret <= MBEDTLS_ERR_ASN1_OUT_OF_DATA) && + (ret >= MBEDTLS_ERR_ASN1_BUF_TOO_SMALL)) { + /* In case of ASN1 error codes add MBEDTLS_ERR_PK_INVALID_PUBKEY. */ + ret = MBEDTLS_ERROR_ADD(MBEDTLS_ERR_PK_INVALID_PUBKEY, ret); + } else { + ret = MBEDTLS_ERR_PK_INVALID_PUBKEY; + } } else #endif /* MBEDTLS_RSA_C */ -#if defined(MBEDTLS_ECP_C) +#if defined(MBEDTLS_PK_HAVE_ECC_KEYS) if (pk_alg == MBEDTLS_PK_ECKEY_DH || pk_alg == MBEDTLS_PK_ECKEY) { - ret = pk_use_ecparams(&alg_params, &mbedtls_pk_ec(*pk)->grp); +#if defined(MBEDTLS_PK_HAVE_RFC8410_CURVES) + if (MBEDTLS_PK_IS_RFC8410_GROUP_ID(ec_grp_id)) { + ret = pk_use_ecparams_rfc8410(&alg_params, ec_grp_id, pk); + } else +#endif + { + ret = pk_use_ecparams(&alg_params, pk); + } if (ret == 0) { - ret = pk_get_ecpubkey(p, end, mbedtls_pk_ec(*pk)); + ret = mbedtls_pk_ecc_set_pubkey(pk, *p, (size_t) (end - *p)); + *p += end - *p; } } else -#endif /* MBEDTLS_ECP_C */ +#endif /* MBEDTLS_PK_HAVE_ECC_KEYS */ ret = MBEDTLS_ERR_PK_UNKNOWN_PK_ALG; if (ret == 0 && *p != end) { @@ -685,208 +597,20 @@ int mbedtls_pk_parse_subpubkey(unsigned char **p, const unsigned char *end, return ret; } -#if defined(MBEDTLS_RSA_C) -/* - * Wrapper around mbedtls_asn1_get_mpi() that rejects zero. - * - * The value zero is: - * - never a valid value for an RSA parameter - * - interpreted as "omitted, please reconstruct" by mbedtls_rsa_complete(). - * - * Since values can't be omitted in PKCS#1, passing a zero value to - * rsa_complete() would be incorrect, so reject zero values early. - */ -static int asn1_get_nonzero_mpi(unsigned char **p, - const unsigned char *end, - mbedtls_mpi *X) -{ - int ret; - - ret = mbedtls_asn1_get_mpi(p, end, X); - if (ret != 0) { - return ret; - } - - if (mbedtls_mpi_cmp_int(X, 0) == 0) { - return MBEDTLS_ERR_PK_KEY_INVALID_FORMAT; - } - - return 0; -} - -/* - * Parse a PKCS#1 encoded private RSA key - */ -static int pk_parse_key_pkcs1_der(mbedtls_rsa_context *rsa, - const unsigned char *key, - size_t keylen) -{ - int ret, version; - size_t len; - unsigned char *p, *end; - - mbedtls_mpi T; - mbedtls_mpi_init(&T); - - p = (unsigned char *) key; - end = p + keylen; - - /* - * This function parses the RSAPrivateKey (PKCS#1) - * - * RSAPrivateKey ::= SEQUENCE { - * version Version, - * modulus INTEGER, -- n - * publicExponent INTEGER, -- e - * privateExponent INTEGER, -- d - * prime1 INTEGER, -- p - * prime2 INTEGER, -- q - * exponent1 INTEGER, -- d mod (p-1) - * exponent2 INTEGER, -- d mod (q-1) - * coefficient INTEGER, -- (inverse of q) mod p - * otherPrimeInfos OtherPrimeInfos OPTIONAL - * } - */ - if ((ret = mbedtls_asn1_get_tag(&p, end, &len, - MBEDTLS_ASN1_CONSTRUCTED | MBEDTLS_ASN1_SEQUENCE)) != 0) { - return MBEDTLS_ERROR_ADD(MBEDTLS_ERR_PK_KEY_INVALID_FORMAT, ret); - } - - end = p + len; - - if ((ret = mbedtls_asn1_get_int(&p, end, &version)) != 0) { - return MBEDTLS_ERROR_ADD(MBEDTLS_ERR_PK_KEY_INVALID_FORMAT, ret); - } - - if (version != 0) { - return MBEDTLS_ERR_PK_KEY_INVALID_VERSION; - } - - /* Import N */ - if ((ret = asn1_get_nonzero_mpi(&p, end, &T)) != 0 || - (ret = mbedtls_rsa_import(rsa, &T, NULL, NULL, - NULL, NULL)) != 0) { - goto cleanup; - } - - /* Import E */ - if ((ret = asn1_get_nonzero_mpi(&p, end, &T)) != 0 || - (ret = mbedtls_rsa_import(rsa, NULL, NULL, NULL, - NULL, &T)) != 0) { - goto cleanup; - } - - /* Import D */ - if ((ret = asn1_get_nonzero_mpi(&p, end, &T)) != 0 || - (ret = mbedtls_rsa_import(rsa, NULL, NULL, NULL, - &T, NULL)) != 0) { - goto cleanup; - } - - /* Import P */ - if ((ret = asn1_get_nonzero_mpi(&p, end, &T)) != 0 || - (ret = mbedtls_rsa_import(rsa, NULL, &T, NULL, - NULL, NULL)) != 0) { - goto cleanup; - } - - /* Import Q */ - if ((ret = asn1_get_nonzero_mpi(&p, end, &T)) != 0 || - (ret = mbedtls_rsa_import(rsa, NULL, NULL, &T, - NULL, NULL)) != 0) { - goto cleanup; - } - -#if !defined(MBEDTLS_RSA_NO_CRT) && !defined(MBEDTLS_RSA_ALT) - /* - * The RSA CRT parameters DP, DQ and QP are nominally redundant, in - * that they can be easily recomputed from D, P and Q. However by - * parsing them from the PKCS1 structure it is possible to avoid - * recalculating them which both reduces the overhead of loading - * RSA private keys into memory and also avoids side channels which - * can arise when computing those values, since all of D, P, and Q - * are secret. See https://eprint.iacr.org/2020/055 for a - * description of one such attack. - */ - - /* Import DP */ - if ((ret = asn1_get_nonzero_mpi(&p, end, &T)) != 0 || - (ret = mbedtls_mpi_copy(&rsa->DP, &T)) != 0) { - goto cleanup; - } - - /* Import DQ */ - if ((ret = asn1_get_nonzero_mpi(&p, end, &T)) != 0 || - (ret = mbedtls_mpi_copy(&rsa->DQ, &T)) != 0) { - goto cleanup; - } - - /* Import QP */ - if ((ret = asn1_get_nonzero_mpi(&p, end, &T)) != 0 || - (ret = mbedtls_mpi_copy(&rsa->QP, &T)) != 0) { - goto cleanup; - } - -#else - /* Verify existence of the CRT params */ - if ((ret = asn1_get_nonzero_mpi(&p, end, &T)) != 0 || - (ret = asn1_get_nonzero_mpi(&p, end, &T)) != 0 || - (ret = asn1_get_nonzero_mpi(&p, end, &T)) != 0) { - goto cleanup; - } -#endif - - /* rsa_complete() doesn't complete anything with the default - * implementation but is still called: - * - for the benefit of alternative implementation that may want to - * pre-compute stuff beyond what's provided (eg Montgomery factors) - * - as is also sanity-checks the key - * - * Furthermore, we also check the public part for consistency with - * mbedtls_pk_parse_pubkey(), as it includes size minima for example. - */ - if ((ret = mbedtls_rsa_complete(rsa)) != 0 || - (ret = mbedtls_rsa_check_pubkey(rsa)) != 0) { - goto cleanup; - } - - if (p != end) { - ret = MBEDTLS_ERROR_ADD(MBEDTLS_ERR_PK_KEY_INVALID_FORMAT, - MBEDTLS_ERR_ASN1_LENGTH_MISMATCH); - } - -cleanup: - - mbedtls_mpi_free(&T); - - if (ret != 0) { - /* Wrap error code if it's coming from a lower level */ - if ((ret & 0xff80) == 0) { - ret = MBEDTLS_ERROR_ADD(MBEDTLS_ERR_PK_KEY_INVALID_FORMAT, ret); - } else { - ret = MBEDTLS_ERR_PK_KEY_INVALID_FORMAT; - } - - mbedtls_rsa_free(rsa); - } - - return ret; -} -#endif /* MBEDTLS_RSA_C */ - -#if defined(MBEDTLS_ECP_C) +#if defined(MBEDTLS_PK_HAVE_ECC_KEYS) /* * Parse a SEC1 encoded private EC key */ -static int pk_parse_key_sec1_der(mbedtls_ecp_keypair *eck, - const unsigned char *key, - size_t keylen) +static int pk_parse_key_sec1_der(mbedtls_pk_context *pk, + const unsigned char *key, size_t keylen, + int (*f_rng)(void *, unsigned char *, size_t), void *p_rng) { int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED; int version, pubkey_done; - size_t len; - mbedtls_asn1_buf params; + size_t len, d_len; + mbedtls_asn1_buf params = { 0, 0, NULL }; unsigned char *p = (unsigned char *) key; + unsigned char *d; unsigned char *end = p + keylen; unsigned char *end2; @@ -919,10 +643,10 @@ static int pk_parse_key_sec1_der(mbedtls_ecp_keypair *eck, return MBEDTLS_ERROR_ADD(MBEDTLS_ERR_PK_KEY_INVALID_FORMAT, ret); } - if ((ret = mbedtls_mpi_read_binary(&eck->d, p, len)) != 0) { - mbedtls_ecp_keypair_free(eck); - return MBEDTLS_ERROR_ADD(MBEDTLS_ERR_PK_KEY_INVALID_FORMAT, ret); - } + /* Keep a reference to the position fo the private key. It will be used + * later in this function. */ + d = p; + d_len = len; p += len; @@ -935,16 +659,22 @@ static int pk_parse_key_sec1_der(mbedtls_ecp_keypair *eck, MBEDTLS_ASN1_CONTEXT_SPECIFIC | MBEDTLS_ASN1_CONSTRUCTED | 0)) == 0) { if ((ret = pk_get_ecparams(&p, p + len, ¶ms)) != 0 || - (ret = pk_use_ecparams(¶ms, &eck->grp)) != 0) { - mbedtls_ecp_keypair_free(eck); + (ret = pk_use_ecparams(¶ms, pk)) != 0) { return ret; } } else if (ret != MBEDTLS_ERR_ASN1_UNEXPECTED_TAG) { - mbedtls_ecp_keypair_free(eck); return MBEDTLS_ERROR_ADD(MBEDTLS_ERR_PK_KEY_INVALID_FORMAT, ret); } } + /* + * Load the private key + */ + ret = mbedtls_pk_ecc_set_key(pk, d, d_len); + if (ret != 0) { + return ret; + } + if (p != end) { /* * Is 'publickey' present? If not, or if we can't read it (eg because it @@ -964,11 +694,11 @@ static int pk_parse_key_sec1_der(mbedtls_ecp_keypair *eck, MBEDTLS_ERR_ASN1_LENGTH_MISMATCH); } - if ((ret = pk_get_ecpubkey(&p, end2, eck)) == 0) { + if ((ret = mbedtls_pk_ecc_set_pubkey(pk, p, (size_t) (end2 - p))) == 0) { pubkey_done = 1; } else { /* - * The only acceptable failure mode of pk_get_ecpubkey() above + * The only acceptable failure mode of mbedtls_pk_ecc_set_pubkey() above * is if the point format is not recognized. */ if (ret != MBEDTLS_ERR_ECP_FEATURE_UNAVAILABLE) { @@ -976,26 +706,25 @@ static int pk_parse_key_sec1_der(mbedtls_ecp_keypair *eck, } } } else if (ret != MBEDTLS_ERR_ASN1_UNEXPECTED_TAG) { - mbedtls_ecp_keypair_free(eck); return MBEDTLS_ERROR_ADD(MBEDTLS_ERR_PK_KEY_INVALID_FORMAT, ret); } } - if (!pubkey_done && - (ret = mbedtls_ecp_mul(&eck->grp, &eck->Q, &eck->d, &eck->grp.G, - NULL, NULL)) != 0) { - mbedtls_ecp_keypair_free(eck); - return MBEDTLS_ERROR_ADD(MBEDTLS_ERR_PK_KEY_INVALID_FORMAT, ret); - } - - if ((ret = mbedtls_ecp_check_privkey(&eck->grp, &eck->d)) != 0) { - mbedtls_ecp_keypair_free(eck); - return ret; + if (!pubkey_done) { + if ((ret = mbedtls_pk_ecc_set_pubkey_from_prv(pk, d, d_len, f_rng, p_rng)) != 0) { + return ret; + } } return 0; } -#endif /* MBEDTLS_ECP_C */ +#endif /* MBEDTLS_PK_HAVE_ECC_KEYS */ + +/*********************************************************************** + * + * PKCS#8 parsing functions + * + **********************************************************************/ /* * Parse an unencrypted PKCS#8 encoded private key @@ -1012,8 +741,8 @@ static int pk_parse_key_sec1_der(mbedtls_ecp_keypair *eck, */ static int pk_parse_key_pkcs8_unencrypted_der( mbedtls_pk_context *pk, - const unsigned char *key, - size_t keylen) + const unsigned char *key, size_t keylen, + int (*f_rng)(void *, unsigned char *, size_t), void *p_rng) { int ret, version; size_t len; @@ -1021,8 +750,14 @@ static int pk_parse_key_pkcs8_unencrypted_der( unsigned char *p = (unsigned char *) key; unsigned char *end = p + keylen; mbedtls_pk_type_t pk_alg = MBEDTLS_PK_NONE; + mbedtls_ecp_group_id ec_grp_id = MBEDTLS_ECP_DP_NONE; const mbedtls_pk_info_t *pk_info; +#if !defined(MBEDTLS_PK_HAVE_ECC_KEYS) + (void) f_rng; + (void) p_rng; +#endif + /* * This function parses the PrivateKeyInfo object (PKCS#8 v1.2 = RFC 5208) * @@ -1054,7 +789,7 @@ static int pk_parse_key_pkcs8_unencrypted_der( return MBEDTLS_ERROR_ADD(MBEDTLS_ERR_PK_KEY_INVALID_VERSION, ret); } - if ((ret = pk_get_pk_alg(&p, end, &pk_alg, ¶ms)) != 0) { + if ((ret = pk_get_pk_alg(&p, end, &pk_alg, ¶ms, &ec_grp_id)) != 0) { return ret; } @@ -1077,23 +812,43 @@ static int pk_parse_key_pkcs8_unencrypted_der( #if defined(MBEDTLS_RSA_C) if (pk_alg == MBEDTLS_PK_RSA) { - if ((ret = pk_parse_key_pkcs1_der(mbedtls_pk_rsa(*pk), p, len)) != 0) { + if ((ret = mbedtls_rsa_parse_key(mbedtls_pk_rsa(*pk), p, len)) != 0) { mbedtls_pk_free(pk); return ret; } } else #endif /* MBEDTLS_RSA_C */ -#if defined(MBEDTLS_ECP_C) +#if defined(MBEDTLS_PK_HAVE_ECC_KEYS) if (pk_alg == MBEDTLS_PK_ECKEY || pk_alg == MBEDTLS_PK_ECKEY_DH) { - if ((ret = pk_use_ecparams(¶ms, &mbedtls_pk_ec(*pk)->grp)) != 0 || - (ret = pk_parse_key_sec1_der(mbedtls_pk_ec(*pk), p, len)) != 0) { - mbedtls_pk_free(pk); - return ret; +#if defined(MBEDTLS_PK_HAVE_RFC8410_CURVES) + if (MBEDTLS_PK_IS_RFC8410_GROUP_ID(ec_grp_id)) { + if ((ret = + pk_use_ecparams_rfc8410(¶ms, ec_grp_id, pk)) != 0 || + (ret = + pk_parse_key_rfc8410_der(pk, p, len, end, f_rng, + p_rng)) != 0) { + mbedtls_pk_free(pk); + return ret; + } + } else +#endif + { + if ((ret = pk_use_ecparams(¶ms, pk)) != 0 || + (ret = pk_parse_key_sec1_der(pk, p, len, f_rng, p_rng)) != 0) { + mbedtls_pk_free(pk); + return ret; + } } } else -#endif /* MBEDTLS_ECP_C */ +#endif /* MBEDTLS_PK_HAVE_ECC_KEYS */ return MBEDTLS_ERR_PK_UNKNOWN_PK_ALG; + end = p + len; + if (end != (key + keylen)) { + return MBEDTLS_ERROR_ADD(MBEDTLS_ERR_PK_KEY_INVALID_FORMAT, + MBEDTLS_ERR_ASN1_LENGTH_MISMATCH); + } + return 0; } @@ -1107,20 +862,22 @@ static int pk_parse_key_pkcs8_unencrypted_der( * */ #if defined(MBEDTLS_PKCS12_C) || defined(MBEDTLS_PKCS5_C) -static int pk_parse_key_pkcs8_encrypted_der( +MBEDTLS_STATIC_TESTABLE int mbedtls_pk_parse_key_pkcs8_encrypted_der( mbedtls_pk_context *pk, unsigned char *key, size_t keylen, - const unsigned char *pwd, size_t pwdlen) + const unsigned char *pwd, size_t pwdlen, + int (*f_rng)(void *, unsigned char *, size_t), void *p_rng) { int ret, decrypted = 0; size_t len; unsigned char *buf; unsigned char *p, *end; mbedtls_asn1_buf pbe_alg_oid, pbe_params; -#if defined(MBEDTLS_PKCS12_C) +#if defined(MBEDTLS_PKCS12_C) && defined(MBEDTLS_CIPHER_PADDING_PKCS7) && defined(MBEDTLS_CIPHER_C) mbedtls_cipher_type_t cipher_alg; mbedtls_md_type_t md_alg; #endif + size_t outlen = 0; p = key; end = p + keylen; @@ -1164,11 +921,11 @@ static int pk_parse_key_pkcs8_encrypted_der( /* * Decrypt EncryptedData with appropriate PBE */ -#if defined(MBEDTLS_PKCS12_C) +#if defined(MBEDTLS_PKCS12_C) && defined(MBEDTLS_CIPHER_PADDING_PKCS7) && defined(MBEDTLS_CIPHER_C) if (mbedtls_oid_get_pkcs12_pbe_alg(&pbe_alg_oid, &md_alg, &cipher_alg) == 0) { - if ((ret = mbedtls_pkcs12_pbe(&pbe_params, MBEDTLS_PKCS12_PBE_DECRYPT, - cipher_alg, md_alg, - pwd, pwdlen, p, len, buf)) != 0) { + if ((ret = mbedtls_pkcs12_pbe_ext(&pbe_params, MBEDTLS_PKCS12_PBE_DECRYPT, + cipher_alg, md_alg, + pwd, pwdlen, p, len, buf, len, &outlen)) != 0) { if (ret == MBEDTLS_ERR_PKCS12_PASSWORD_MISMATCH) { return MBEDTLS_ERR_PK_PASSWORD_MISMATCH; } @@ -1176,29 +933,13 @@ static int pk_parse_key_pkcs8_encrypted_der( return ret; } - decrypted = 1; - } else if (MBEDTLS_OID_CMP(MBEDTLS_OID_PKCS12_PBE_SHA1_RC4_128, &pbe_alg_oid) == 0) { - if ((ret = mbedtls_pkcs12_pbe_sha1_rc4_128(&pbe_params, - MBEDTLS_PKCS12_PBE_DECRYPT, - pwd, pwdlen, - p, len, buf)) != 0) { - return ret; - } - - // Best guess for password mismatch when using RC4. If first tag is - // not MBEDTLS_ASN1_CONSTRUCTED | MBEDTLS_ASN1_SEQUENCE - // - if (*buf != (MBEDTLS_ASN1_CONSTRUCTED | MBEDTLS_ASN1_SEQUENCE)) { - return MBEDTLS_ERR_PK_PASSWORD_MISMATCH; - } - decrypted = 1; } else -#endif /* MBEDTLS_PKCS12_C */ -#if defined(MBEDTLS_PKCS5_C) +#endif /* MBEDTLS_PKCS12_C && MBEDTLS_CIPHER_PADDING_PKCS7 && MBEDTLS_CIPHER_C */ +#if defined(MBEDTLS_PKCS5_C) && defined(MBEDTLS_CIPHER_PADDING_PKCS7) && defined(MBEDTLS_CIPHER_C) if (MBEDTLS_OID_CMP(MBEDTLS_OID_PKCS5_PBES2, &pbe_alg_oid) == 0) { - if ((ret = mbedtls_pkcs5_pbes2(&pbe_params, MBEDTLS_PKCS5_DECRYPT, pwd, pwdlen, - p, len, buf)) != 0) { + if ((ret = mbedtls_pkcs5_pbes2_ext(&pbe_params, MBEDTLS_PKCS5_DECRYPT, pwd, pwdlen, + p, len, buf, len, &outlen)) != 0) { if (ret == MBEDTLS_ERR_PKCS5_PASSWORD_MISMATCH) { return MBEDTLS_ERR_PK_PASSWORD_MISMATCH; } @@ -1208,7 +949,7 @@ static int pk_parse_key_pkcs8_encrypted_der( decrypted = 1; } else -#endif /* MBEDTLS_PKCS5_C */ +#endif /* MBEDTLS_PKCS5_C && MBEDTLS_CIPHER_PADDING_PKCS7 && MBEDTLS_CIPHER_C */ { ((void) pwd); } @@ -1216,17 +957,23 @@ static int pk_parse_key_pkcs8_encrypted_der( if (decrypted == 0) { return MBEDTLS_ERR_PK_FEATURE_UNAVAILABLE; } - - return pk_parse_key_pkcs8_unencrypted_der(pk, buf, len); + return pk_parse_key_pkcs8_unencrypted_der(pk, buf, outlen, f_rng, p_rng); } #endif /* MBEDTLS_PKCS12_C || MBEDTLS_PKCS5_C */ +/*********************************************************************** + * + * Top-level functions, with format auto-discovery + * + **********************************************************************/ + /* * Parse a private key */ int mbedtls_pk_parse_key(mbedtls_pk_context *pk, const unsigned char *key, size_t keylen, - const unsigned char *pwd, size_t pwdlen) + const unsigned char *pwd, size_t pwdlen, + int (*f_rng)(void *, unsigned char *, size_t), void *p_rng) { int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED; const mbedtls_pk_info_t *pk_info; @@ -1235,13 +982,9 @@ int mbedtls_pk_parse_key(mbedtls_pk_context *pk, mbedtls_pem_context pem; #endif - (void) pk_info; - - PK_VALIDATE_RET(pk != NULL); if (keylen == 0) { return MBEDTLS_ERR_PK_KEY_INVALID_FORMAT; } - PK_VALIDATE_RET(key != NULL); #if defined(MBEDTLS_PEM_PARSE_C) mbedtls_pem_init(&pem); @@ -1252,16 +995,15 @@ int mbedtls_pk_parse_key(mbedtls_pk_context *pk, ret = MBEDTLS_ERR_PEM_NO_HEADER_FOOTER_PRESENT; } else { ret = mbedtls_pem_read_buffer(&pem, - "-----BEGIN RSA PRIVATE KEY-----", - "-----END RSA PRIVATE KEY-----", + PEM_BEGIN_PRIVATE_KEY_RSA, PEM_END_PRIVATE_KEY_RSA, key, pwd, pwdlen, &len); } if (ret == 0) { pk_info = mbedtls_pk_info_from_type(MBEDTLS_PK_RSA); if ((ret = mbedtls_pk_setup(pk, pk_info)) != 0 || - (ret = pk_parse_key_pkcs1_der(mbedtls_pk_rsa(*pk), - pem.buf, pem.buflen)) != 0) { + (ret = mbedtls_rsa_parse_key(mbedtls_pk_rsa(*pk), + pem.buf, pem.buflen)) != 0) { mbedtls_pk_free(pk); } @@ -1276,22 +1018,23 @@ int mbedtls_pk_parse_key(mbedtls_pk_context *pk, } #endif /* MBEDTLS_RSA_C */ -#if defined(MBEDTLS_ECP_C) +#if defined(MBEDTLS_PK_HAVE_ECC_KEYS) /* Avoid calling mbedtls_pem_read_buffer() on non-null-terminated string */ if (key[keylen - 1] != '\0') { ret = MBEDTLS_ERR_PEM_NO_HEADER_FOOTER_PRESENT; } else { ret = mbedtls_pem_read_buffer(&pem, - "-----BEGIN EC PRIVATE KEY-----", - "-----END EC PRIVATE KEY-----", + PEM_BEGIN_PRIVATE_KEY_EC, + PEM_END_PRIVATE_KEY_EC, key, pwd, pwdlen, &len); } if (ret == 0) { pk_info = mbedtls_pk_info_from_type(MBEDTLS_PK_ECKEY); if ((ret = mbedtls_pk_setup(pk, pk_info)) != 0 || - (ret = pk_parse_key_sec1_der(mbedtls_pk_ec(*pk), - pem.buf, pem.buflen)) != 0) { + (ret = pk_parse_key_sec1_der(pk, + pem.buf, pem.buflen, + f_rng, p_rng)) != 0) { mbedtls_pk_free(pk); } @@ -1304,20 +1047,19 @@ int mbedtls_pk_parse_key(mbedtls_pk_context *pk, } else if (ret != MBEDTLS_ERR_PEM_NO_HEADER_FOOTER_PRESENT) { return ret; } -#endif /* MBEDTLS_ECP_C */ +#endif /* MBEDTLS_PK_HAVE_ECC_KEYS */ /* Avoid calling mbedtls_pem_read_buffer() on non-null-terminated string */ if (key[keylen - 1] != '\0') { ret = MBEDTLS_ERR_PEM_NO_HEADER_FOOTER_PRESENT; } else { ret = mbedtls_pem_read_buffer(&pem, - "-----BEGIN PRIVATE KEY-----", - "-----END PRIVATE KEY-----", + PEM_BEGIN_PRIVATE_KEY_PKCS8, PEM_END_PRIVATE_KEY_PKCS8, key, NULL, 0, &len); } if (ret == 0) { if ((ret = pk_parse_key_pkcs8_unencrypted_der(pk, - pem.buf, pem.buflen)) != 0) { + pem.buf, pem.buflen, f_rng, p_rng)) != 0) { mbedtls_pk_free(pk); } @@ -1333,14 +1075,13 @@ int mbedtls_pk_parse_key(mbedtls_pk_context *pk, ret = MBEDTLS_ERR_PEM_NO_HEADER_FOOTER_PRESENT; } else { ret = mbedtls_pem_read_buffer(&pem, - "-----BEGIN ENCRYPTED PRIVATE KEY-----", - "-----END ENCRYPTED PRIVATE KEY-----", + PEM_BEGIN_ENCRYPTED_PRIVATE_KEY_PKCS8, + PEM_END_ENCRYPTED_PRIVATE_KEY_PKCS8, key, NULL, 0, &len); } if (ret == 0) { - if ((ret = pk_parse_key_pkcs8_encrypted_der(pk, - pem.buf, pem.buflen, - pwd, pwdlen)) != 0) { + if ((ret = mbedtls_pk_parse_key_pkcs8_encrypted_der(pk, pem.buf, pem.buflen, + pwd, pwdlen, f_rng, p_rng)) != 0) { mbedtls_pk_free(pk); } @@ -1363,7 +1104,7 @@ int mbedtls_pk_parse_key(mbedtls_pk_context *pk, * error */ #if defined(MBEDTLS_PKCS12_C) || defined(MBEDTLS_PKCS5_C) - { + if (pwdlen != 0) { unsigned char *key_copy; if ((key_copy = mbedtls_calloc(1, keylen)) == NULL) { @@ -1372,11 +1113,10 @@ int mbedtls_pk_parse_key(mbedtls_pk_context *pk, memcpy(key_copy, key, keylen); - ret = pk_parse_key_pkcs8_encrypted_der(pk, key_copy, keylen, - pwd, pwdlen); + ret = mbedtls_pk_parse_key_pkcs8_encrypted_der(pk, key_copy, keylen, + pwd, pwdlen, f_rng, p_rng); - mbedtls_platform_zeroize(key_copy, keylen); - mbedtls_free(key_copy); + mbedtls_zeroize_and_free(key_copy, keylen); } if (ret == 0) { @@ -1391,7 +1131,7 @@ int mbedtls_pk_parse_key(mbedtls_pk_context *pk, } #endif /* MBEDTLS_PKCS12_C || MBEDTLS_PKCS5_C */ - ret = pk_parse_key_pkcs8_unencrypted_der(pk, key, keylen); + ret = pk_parse_key_pkcs8_unencrypted_der(pk, key, keylen, f_rng, p_rng); if (ret == 0) { return 0; } @@ -1403,7 +1143,7 @@ int mbedtls_pk_parse_key(mbedtls_pk_context *pk, pk_info = mbedtls_pk_info_from_type(MBEDTLS_PK_RSA); if (mbedtls_pk_setup(pk, pk_info) == 0 && - pk_parse_key_pkcs1_der(mbedtls_pk_rsa(*pk), key, keylen) == 0) { + mbedtls_rsa_parse_key(mbedtls_pk_rsa(*pk), key, keylen) == 0) { return 0; } @@ -1411,21 +1151,21 @@ int mbedtls_pk_parse_key(mbedtls_pk_context *pk, mbedtls_pk_init(pk); #endif /* MBEDTLS_RSA_C */ -#if defined(MBEDTLS_ECP_C) +#if defined(MBEDTLS_PK_HAVE_ECC_KEYS) pk_info = mbedtls_pk_info_from_type(MBEDTLS_PK_ECKEY); if (mbedtls_pk_setup(pk, pk_info) == 0 && - pk_parse_key_sec1_der(mbedtls_pk_ec(*pk), - key, keylen) == 0) { + pk_parse_key_sec1_der(pk, + key, keylen, f_rng, p_rng) == 0) { return 0; } mbedtls_pk_free(pk); -#endif /* MBEDTLS_ECP_C */ +#endif /* MBEDTLS_PK_HAVE_ECC_KEYS */ - /* If MBEDTLS_RSA_C is defined but MBEDTLS_ECP_C isn't, + /* If MBEDTLS_RSA_C is defined but MBEDTLS_PK_HAVE_ECC_KEYS isn't, * it is ok to leave the PK context initialized but not * freed: It is the caller's responsibility to call pk_init() * before calling this function, and to call pk_free() - * when it fails. If MBEDTLS_ECP_C is defined but MBEDTLS_RSA_C + * when it fails. If MBEDTLS_PK_HAVE_ECC_KEYS is defined but MBEDTLS_RSA_C * isn't, this leads to mbedtls_pk_free() being called * twice, once here and once by the caller, but this is * also ok and in line with the mbedtls_pk_free() calls @@ -1450,11 +1190,9 @@ int mbedtls_pk_parse_public_key(mbedtls_pk_context *ctx, mbedtls_pem_context pem; #endif - PK_VALIDATE_RET(ctx != NULL); if (keylen == 0) { return MBEDTLS_ERR_PK_KEY_INVALID_FORMAT; } - PK_VALIDATE_RET(key != NULL || keylen == 0); #if defined(MBEDTLS_PEM_PARSE_C) mbedtls_pem_init(&pem); @@ -1464,8 +1202,7 @@ int mbedtls_pk_parse_public_key(mbedtls_pk_context *ctx, ret = MBEDTLS_ERR_PEM_NO_HEADER_FOOTER_PRESENT; } else { ret = mbedtls_pem_read_buffer(&pem, - "-----BEGIN RSA PUBLIC KEY-----", - "-----END RSA PUBLIC KEY-----", + PEM_BEGIN_PUBLIC_KEY_RSA, PEM_END_PUBLIC_KEY_RSA, key, NULL, 0, &len); } @@ -1481,7 +1218,7 @@ int mbedtls_pk_parse_public_key(mbedtls_pk_context *ctx, return ret; } - if ((ret = pk_get_rsapubkey(&p, p + pem.buflen, mbedtls_pk_rsa(*ctx))) != 0) { + if ((ret = mbedtls_rsa_parse_pubkey(mbedtls_pk_rsa(*ctx), p, pem.buflen)) != 0) { mbedtls_pk_free(ctx); } @@ -1498,8 +1235,7 @@ int mbedtls_pk_parse_public_key(mbedtls_pk_context *ctx, ret = MBEDTLS_ERR_PEM_NO_HEADER_FOOTER_PRESENT; } else { ret = mbedtls_pem_read_buffer(&pem, - "-----BEGIN PUBLIC KEY-----", - "-----END PUBLIC KEY-----", + PEM_BEGIN_PUBLIC_KEY, PEM_END_PUBLIC_KEY, key, NULL, 0, &len); } @@ -1509,7 +1245,7 @@ int mbedtls_pk_parse_public_key(mbedtls_pk_context *ctx, */ p = pem.buf; - ret = mbedtls_pk_parse_subpubkey(&p, p + pem.buflen, ctx); + ret = mbedtls_pk_parse_subpubkey(&p, p + pem.buflen, ctx); mbedtls_pem_free(&pem); return ret; } else if (ret != MBEDTLS_ERR_PEM_NO_HEADER_FOOTER_PRESENT) { @@ -1529,13 +1265,12 @@ int mbedtls_pk_parse_public_key(mbedtls_pk_context *ctx, } p = (unsigned char *) key; - ret = pk_get_rsapubkey(&p, p + keylen, mbedtls_pk_rsa(*ctx)); + ret = mbedtls_rsa_parse_pubkey(mbedtls_pk_rsa(*ctx), p, keylen); if (ret == 0) { return ret; } mbedtls_pk_free(ctx); - if (ret != (MBEDTLS_ERROR_ADD(MBEDTLS_ERR_PK_INVALID_PUBKEY, - MBEDTLS_ERR_ASN1_UNEXPECTED_TAG))) { + if (ret != MBEDTLS_ERR_ASN1_UNEXPECTED_TAG) { return ret; } #endif /* MBEDTLS_RSA_C */ @@ -1546,4 +1281,112 @@ int mbedtls_pk_parse_public_key(mbedtls_pk_context *ctx, return ret; } +/*********************************************************************** + * + * Top-level functions, with filesystem support + * + **********************************************************************/ + +#if defined(MBEDTLS_FS_IO) +/* + * Load all data from a file into a given buffer. + * + * The file is expected to contain either PEM or DER encoded data. + * A terminating null byte is always appended. It is included in the announced + * length only if the data looks like it is PEM encoded. + */ +int mbedtls_pk_load_file(const char *path, unsigned char **buf, size_t *n) +{ + FILE *f; + long size; + + if ((f = fopen(path, "rb")) == NULL) { + return MBEDTLS_ERR_PK_FILE_IO_ERROR; + } + + /* Ensure no stdio buffering of secrets, as such buffers cannot be wiped. */ + mbedtls_setbuf(f, NULL); + + fseek(f, 0, SEEK_END); + if ((size = ftell(f)) == -1) { + fclose(f); + return MBEDTLS_ERR_PK_FILE_IO_ERROR; + } + fseek(f, 0, SEEK_SET); + + *n = (size_t) size; + + if (*n + 1 == 0 || + (*buf = mbedtls_calloc(1, *n + 1)) == NULL) { + fclose(f); + return MBEDTLS_ERR_PK_ALLOC_FAILED; + } + + if (fread(*buf, 1, *n, f) != *n) { + fclose(f); + + mbedtls_zeroize_and_free(*buf, *n); + + return MBEDTLS_ERR_PK_FILE_IO_ERROR; + } + + fclose(f); + + (*buf)[*n] = '\0'; + + if (strstr((const char *) *buf, "-----BEGIN ") != NULL) { + ++*n; + } + + return 0; +} + +/* + * Load and parse a private key + */ +int mbedtls_pk_parse_keyfile(mbedtls_pk_context *ctx, + const char *path, const char *pwd, + int (*f_rng)(void *, unsigned char *, size_t), void *p_rng) +{ + int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED; + size_t n; + unsigned char *buf; + + if ((ret = mbedtls_pk_load_file(path, &buf, &n)) != 0) { + return ret; + } + + if (pwd == NULL) { + ret = mbedtls_pk_parse_key(ctx, buf, n, NULL, 0, f_rng, p_rng); + } else { + ret = mbedtls_pk_parse_key(ctx, buf, n, + (const unsigned char *) pwd, strlen(pwd), f_rng, p_rng); + } + + mbedtls_zeroize_and_free(buf, n); + + return ret; +} + +/* + * Load and parse a public key + */ +int mbedtls_pk_parse_public_keyfile(mbedtls_pk_context *ctx, const char *path) +{ + int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED; + size_t n; + unsigned char *buf; + + if ((ret = mbedtls_pk_load_file(path, &buf, &n)) != 0) { + return ret; + } + + ret = mbedtls_pk_parse_public_key(ctx, buf, n); + + mbedtls_zeroize_and_free(buf, n); + + return ret; +} +#endif /* MBEDTLS_FS_IO */ + #endif /* MBEDTLS_PK_PARSE_C */ diff --git a/vendor/mbedtls/library/pkwrite.c b/vendor/mbedtls/library/pkwrite.c index 88e685503b..5e009c565e 100644 --- a/vendor/mbedtls/library/pkwrite.c +++ b/vendor/mbedtls/library/pkwrite.c @@ -2,19 +2,7 @@ * Public Key layer for writing key files and structures * * Copyright The Mbed TLS Contributors - * SPDX-License-Identifier: Apache-2.0 - * - * Licensed under the Apache License, Version 2.0 (the "License"); you may - * not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT - * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. + * SPDX-License-Identifier: Apache-2.0 OR GPL-2.0-or-later */ #include "common.h" @@ -26,96 +14,128 @@ #include "mbedtls/oid.h" #include "mbedtls/platform_util.h" #include "mbedtls/error.h" +#include "pk_internal.h" #include -#if defined(MBEDTLS_RSA_C) -#include "mbedtls/rsa.h" -#endif #if defined(MBEDTLS_ECP_C) #include "mbedtls/bignum.h" #include "mbedtls/ecp.h" #include "mbedtls/platform_util.h" #endif -#if defined(MBEDTLS_ECDSA_C) -#include "mbedtls/ecdsa.h" +#if defined(MBEDTLS_PK_HAVE_ECC_KEYS) +#include "pk_internal.h" +#endif +#if defined(MBEDTLS_RSA_C) || defined(MBEDTLS_PK_HAVE_ECC_KEYS) +#include "pkwrite.h" #endif #if defined(MBEDTLS_PEM_WRITE_C) #include "mbedtls/pem.h" #endif +#if defined(MBEDTLS_RSA_C) +#include "rsa_internal.h" +#endif #if defined(MBEDTLS_USE_PSA_CRYPTO) #include "psa/crypto.h" -#include "mbedtls/psa_util.h" +#include "psa_util_internal.h" #endif #include "mbedtls/platform.h" -/* Parameter validation macros based on platform_util.h */ -#define PK_VALIDATE_RET(cond) \ - MBEDTLS_INTERNAL_VALIDATE_RET(cond, MBEDTLS_ERR_PK_BAD_INPUT_DATA) -#define PK_VALIDATE(cond) \ - MBEDTLS_INTERNAL_VALIDATE(cond) +/* Helpers for properly sizing buffers aimed at holding public keys or + * key-pairs based on build symbols. */ +#if defined(MBEDTLS_PK_USE_PSA_EC_DATA) +#define PK_MAX_EC_PUBLIC_KEY_SIZE PSA_EXPORT_PUBLIC_KEY_MAX_SIZE +#define PK_MAX_EC_KEY_PAIR_SIZE MBEDTLS_PSA_MAX_EC_KEY_PAIR_LENGTH +#elif defined(MBEDTLS_USE_PSA_CRYPTO) +#define PK_MAX_EC_PUBLIC_KEY_SIZE PSA_EXPORT_PUBLIC_KEY_MAX_SIZE +#define PK_MAX_EC_KEY_PAIR_SIZE MBEDTLS_PSA_MAX_EC_KEY_PAIR_LENGTH +#else +#define PK_MAX_EC_PUBLIC_KEY_SIZE MBEDTLS_ECP_MAX_PT_LEN +#define PK_MAX_EC_KEY_PAIR_SIZE MBEDTLS_ECP_MAX_BYTES +#endif +/****************************************************************************** + * Internal functions for RSA keys. + ******************************************************************************/ #if defined(MBEDTLS_RSA_C) -/* - * RSAPublicKey ::= SEQUENCE { - * modulus INTEGER, -- n - * publicExponent INTEGER -- e - * } - */ -static int pk_write_rsa_pubkey(unsigned char **p, unsigned char *start, - mbedtls_rsa_context *rsa) +static int pk_write_rsa_der(unsigned char **p, unsigned char *buf, + const mbedtls_pk_context *pk) { - int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED; - size_t len = 0; - mbedtls_mpi T; +#if defined(MBEDTLS_USE_PSA_CRYPTO) + if (mbedtls_pk_get_type(pk) == MBEDTLS_PK_OPAQUE) { + uint8_t tmp[PSA_EXPORT_KEY_PAIR_MAX_SIZE]; + size_t len = 0, tmp_len = 0; - mbedtls_mpi_init(&T); + if (psa_export_key(pk->priv_id, tmp, sizeof(tmp), &tmp_len) != PSA_SUCCESS) { + return MBEDTLS_ERR_PK_BAD_INPUT_DATA; + } + *p -= tmp_len; + memcpy(*p, tmp, tmp_len); + len += tmp_len; + mbedtls_platform_zeroize(tmp, sizeof(tmp)); - /* Export E */ - if ((ret = mbedtls_rsa_export(rsa, NULL, NULL, NULL, NULL, &T)) != 0 || - (ret = mbedtls_asn1_write_mpi(p, start, &T)) < 0) { - goto end_of_export; + return (int) len; } - len += ret; +#endif /* MBEDTLS_USE_PSA_CRYPTO */ + return mbedtls_rsa_write_key(mbedtls_pk_rsa(*pk), buf, p); +} +#endif /* MBEDTLS_RSA_C */ - /* Export N */ - if ((ret = mbedtls_rsa_export(rsa, &T, NULL, NULL, NULL, NULL)) != 0 || - (ret = mbedtls_asn1_write_mpi(p, start, &T)) < 0) { - goto end_of_export; - } - len += ret; +/****************************************************************************** + * Internal functions for EC keys. + ******************************************************************************/ +#if defined(MBEDTLS_PK_HAVE_ECC_KEYS) +#if defined(MBEDTLS_PK_USE_PSA_EC_DATA) +static int pk_write_ec_pubkey(unsigned char **p, unsigned char *start, + const mbedtls_pk_context *pk) +{ + size_t len = 0; + uint8_t buf[PK_MAX_EC_PUBLIC_KEY_SIZE]; -end_of_export: + if (mbedtls_pk_get_type(pk) == MBEDTLS_PK_OPAQUE) { + if (psa_export_public_key(pk->priv_id, buf, sizeof(buf), &len) != PSA_SUCCESS) { + return MBEDTLS_ERR_PK_BAD_INPUT_DATA; + } + } else { + len = pk->pub_raw_len; + memcpy(buf, pk->pub_raw, len); + } - mbedtls_mpi_free(&T); - if (ret < 0) { - return ret; + if (*p < start || (size_t) (*p - start) < len) { + return MBEDTLS_ERR_ASN1_BUF_TOO_SMALL; } - MBEDTLS_ASN1_CHK_ADD(len, mbedtls_asn1_write_len(p, start, len)); - MBEDTLS_ASN1_CHK_ADD(len, mbedtls_asn1_write_tag(p, start, MBEDTLS_ASN1_CONSTRUCTED | - MBEDTLS_ASN1_SEQUENCE)); + *p -= len; + memcpy(*p, buf, len); return (int) len; } -#endif /* MBEDTLS_RSA_C */ - -#if defined(MBEDTLS_ECP_C) -/* - * EC public key is an EC point - */ +#else /* MBEDTLS_PK_USE_PSA_EC_DATA */ static int pk_write_ec_pubkey(unsigned char **p, unsigned char *start, - mbedtls_ecp_keypair *ec) + const mbedtls_pk_context *pk) { - int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED; size_t len = 0; - unsigned char buf[MBEDTLS_ECP_MAX_PT_LEN]; + unsigned char buf[PK_MAX_EC_PUBLIC_KEY_SIZE]; + mbedtls_ecp_keypair *ec = mbedtls_pk_ec(*pk); + int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED; - if ((ret = mbedtls_ecp_point_write_binary(&ec->grp, &ec->Q, - MBEDTLS_ECP_PF_UNCOMPRESSED, - &len, buf, sizeof(buf))) != 0) { - return ret; +#if defined(MBEDTLS_USE_PSA_CRYPTO) + if (mbedtls_pk_get_type(pk) == MBEDTLS_PK_OPAQUE) { + if (psa_export_public_key(pk->priv_id, buf, sizeof(buf), &len) != PSA_SUCCESS) { + return MBEDTLS_ERR_PK_BAD_INPUT_DATA; + } + *p -= len; + memcpy(*p, buf, len); + return (int) len; + } else +#endif /* MBEDTLS_USE_PSA_CRYPTO */ + { + if ((ret = mbedtls_ecp_point_write_binary(&ec->grp, &ec->Q, + MBEDTLS_ECP_PF_UNCOMPRESSED, + &len, buf, sizeof(buf))) != 0) { + return ret; + } } if (*p < start || (size_t) (*p - start) < len) { @@ -127,6 +147,72 @@ static int pk_write_ec_pubkey(unsigned char **p, unsigned char *start, return (int) len; } +#endif /* MBEDTLS_PK_USE_PSA_EC_DATA */ + +/* + * privateKey OCTET STRING -- always of length ceil(log2(n)/8) + */ +#if defined(MBEDTLS_PK_USE_PSA_EC_DATA) +static int pk_write_ec_private(unsigned char **p, unsigned char *start, + const mbedtls_pk_context *pk) +{ + size_t byte_length; + int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED; + unsigned char tmp[PK_MAX_EC_KEY_PAIR_SIZE]; + psa_status_t status; + + if (mbedtls_pk_get_type(pk) == MBEDTLS_PK_OPAQUE) { + status = psa_export_key(pk->priv_id, tmp, sizeof(tmp), &byte_length); + if (status != PSA_SUCCESS) { + ret = PSA_PK_ECDSA_TO_MBEDTLS_ERR(status); + return ret; + } + } else { + status = psa_export_key(pk->priv_id, tmp, sizeof(tmp), &byte_length); + if (status != PSA_SUCCESS) { + ret = PSA_PK_ECDSA_TO_MBEDTLS_ERR(status); + goto exit; + } + } + + ret = mbedtls_asn1_write_octet_string(p, start, tmp, byte_length); +exit: + mbedtls_platform_zeroize(tmp, sizeof(tmp)); + return ret; +} +#else /* MBEDTLS_PK_USE_PSA_EC_DATA */ +static int pk_write_ec_private(unsigned char **p, unsigned char *start, + const mbedtls_pk_context *pk) +{ + size_t byte_length; + int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED; + unsigned char tmp[PK_MAX_EC_KEY_PAIR_SIZE]; + +#if defined(MBEDTLS_USE_PSA_CRYPTO) + psa_status_t status; + if (mbedtls_pk_get_type(pk) == MBEDTLS_PK_OPAQUE) { + status = psa_export_key(pk->priv_id, tmp, sizeof(tmp), &byte_length); + if (status != PSA_SUCCESS) { + ret = PSA_PK_ECDSA_TO_MBEDTLS_ERR(status); + return ret; + } + } else +#endif /* MBEDTLS_USE_PSA_CRYPTO */ + { + mbedtls_ecp_keypair *ec = mbedtls_pk_ec_rw(*pk); + byte_length = (ec->grp.pbits + 7) / 8; + + ret = mbedtls_ecp_write_key_ext(ec, &byte_length, tmp, sizeof(tmp)); + if (ret != 0) { + goto exit; + } + } + ret = mbedtls_asn1_write_octet_string(p, start, tmp, byte_length); +exit: + mbedtls_platform_zeroize(tmp, sizeof(tmp)); + return ret; +} +#endif /* MBEDTLS_PK_USE_PSA_EC_DATA */ /* * ECParameters ::= CHOICE { @@ -134,14 +220,14 @@ static int pk_write_ec_pubkey(unsigned char **p, unsigned char *start, * } */ static int pk_write_ec_param(unsigned char **p, unsigned char *start, - mbedtls_ecp_keypair *ec) + mbedtls_ecp_group_id grp_id) { int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED; size_t len = 0; const char *oid; size_t oid_len; - if ((ret = mbedtls_oid_get_oid_by_ec_grp(ec->grp.id, &oid, &oid_len)) != 0) { + if ((ret = mbedtls_oid_get_oid_by_ec_grp(grp_id, &oid, &oid_len)) != 0) { return ret; } @@ -150,71 +236,197 @@ static int pk_write_ec_param(unsigned char **p, unsigned char *start, return (int) len; } +#if defined(MBEDTLS_PK_HAVE_RFC8410_CURVES) /* - * privateKey OCTET STRING -- always of length ceil(log2(n)/8) + * RFC8410 section 7 + * + * OneAsymmetricKey ::= SEQUENCE { + * version Version, + * privateKeyAlgorithm PrivateKeyAlgorithmIdentifier, + * privateKey PrivateKey, + * attributes [0] IMPLICIT Attributes OPTIONAL, + * ..., + * [[2: publicKey [1] IMPLICIT PublicKey OPTIONAL ]], + * ... + * } + * ... + * CurvePrivateKey ::= OCTET STRING */ -static int pk_write_ec_private(unsigned char **p, unsigned char *start, - mbedtls_ecp_keypair *ec) +static int pk_write_ec_rfc8410_der(unsigned char **p, unsigned char *buf, + const mbedtls_pk_context *pk) { int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED; - size_t byte_length = (ec->grp.pbits + 7) / 8; - unsigned char tmp[MBEDTLS_ECP_MAX_BYTES]; + size_t len = 0; + size_t oid_len = 0; + const char *oid; + mbedtls_ecp_group_id grp_id; - ret = mbedtls_ecp_write_key(ec, tmp, byte_length); - if (ret != 0) { - goto exit; + /* privateKey */ + MBEDTLS_ASN1_CHK_ADD(len, pk_write_ec_private(p, buf, pk)); + MBEDTLS_ASN1_CHK_ADD(len, mbedtls_asn1_write_len(p, buf, len)); + MBEDTLS_ASN1_CHK_ADD(len, mbedtls_asn1_write_tag(p, buf, MBEDTLS_ASN1_OCTET_STRING)); + + grp_id = mbedtls_pk_get_ec_group_id(pk); + /* privateKeyAlgorithm */ + if ((ret = mbedtls_oid_get_oid_by_ec_grp_algid(grp_id, &oid, &oid_len)) != 0) { + return ret; } - ret = mbedtls_asn1_write_octet_string(p, start, tmp, byte_length); + MBEDTLS_ASN1_CHK_ADD(len, + mbedtls_asn1_write_algorithm_identifier_ext(p, buf, oid, oid_len, 0, 0)); -exit: - mbedtls_platform_zeroize(tmp, byte_length); - return ret; + /* version */ + MBEDTLS_ASN1_CHK_ADD(len, mbedtls_asn1_write_int(p, buf, 0)); + + MBEDTLS_ASN1_CHK_ADD(len, mbedtls_asn1_write_len(p, buf, len)); + MBEDTLS_ASN1_CHK_ADD(len, mbedtls_asn1_write_tag(p, buf, MBEDTLS_ASN1_CONSTRUCTED | + MBEDTLS_ASN1_SEQUENCE)); + + return (int) len; } -#endif /* MBEDTLS_ECP_C */ +#endif /* MBEDTLS_PK_HAVE_RFC8410_CURVES */ + +/* + * RFC 5915, or SEC1 Appendix C.4 + * + * ECPrivateKey ::= SEQUENCE { + * version INTEGER { ecPrivkeyVer1(1) } (ecPrivkeyVer1), + * privateKey OCTET STRING, + * parameters [0] ECParameters {{ NamedCurve }} OPTIONAL, + * publicKey [1] BIT STRING OPTIONAL + * } + */ +static int pk_write_ec_der(unsigned char **p, unsigned char *buf, + const mbedtls_pk_context *pk) +{ + size_t len = 0; + int ret; + size_t pub_len = 0, par_len = 0; + mbedtls_ecp_group_id grp_id; + + /* publicKey */ + MBEDTLS_ASN1_CHK_ADD(pub_len, pk_write_ec_pubkey(p, buf, pk)); + + if (*p - buf < 1) { + return MBEDTLS_ERR_ASN1_BUF_TOO_SMALL; + } + (*p)--; + **p = 0; + pub_len += 1; + + MBEDTLS_ASN1_CHK_ADD(pub_len, mbedtls_asn1_write_len(p, buf, pub_len)); + MBEDTLS_ASN1_CHK_ADD(pub_len, mbedtls_asn1_write_tag(p, buf, MBEDTLS_ASN1_BIT_STRING)); + + MBEDTLS_ASN1_CHK_ADD(pub_len, mbedtls_asn1_write_len(p, buf, pub_len)); + MBEDTLS_ASN1_CHK_ADD(pub_len, mbedtls_asn1_write_tag(p, buf, + MBEDTLS_ASN1_CONTEXT_SPECIFIC | + MBEDTLS_ASN1_CONSTRUCTED | 1)); + len += pub_len; + + /* parameters */ + grp_id = mbedtls_pk_get_ec_group_id(pk); + MBEDTLS_ASN1_CHK_ADD(par_len, pk_write_ec_param(p, buf, grp_id)); + MBEDTLS_ASN1_CHK_ADD(par_len, mbedtls_asn1_write_len(p, buf, par_len)); + MBEDTLS_ASN1_CHK_ADD(par_len, mbedtls_asn1_write_tag(p, buf, + MBEDTLS_ASN1_CONTEXT_SPECIFIC | + MBEDTLS_ASN1_CONSTRUCTED | 0)); + len += par_len; + + /* privateKey */ + MBEDTLS_ASN1_CHK_ADD(len, pk_write_ec_private(p, buf, pk)); + + /* version */ + MBEDTLS_ASN1_CHK_ADD(len, mbedtls_asn1_write_int(p, buf, 1)); + + MBEDTLS_ASN1_CHK_ADD(len, mbedtls_asn1_write_len(p, buf, len)); + MBEDTLS_ASN1_CHK_ADD(len, mbedtls_asn1_write_tag(p, buf, MBEDTLS_ASN1_CONSTRUCTED | + MBEDTLS_ASN1_SEQUENCE)); + + return (int) len; +} +#endif /* MBEDTLS_PK_HAVE_ECC_KEYS */ + +/****************************************************************************** + * Internal functions for Opaque keys. + ******************************************************************************/ +#if defined(MBEDTLS_USE_PSA_CRYPTO) +static int pk_write_opaque_pubkey(unsigned char **p, unsigned char *start, + const mbedtls_pk_context *pk) +{ + size_t buffer_size; + size_t len = 0; + + if (*p < start) { + return MBEDTLS_ERR_PK_BAD_INPUT_DATA; + } + + buffer_size = (size_t) (*p - start); + if (psa_export_public_key(pk->priv_id, start, buffer_size, + &len) != PSA_SUCCESS) { + return MBEDTLS_ERR_PK_BAD_INPUT_DATA; + } + + *p -= len; + memmove(*p, start, len); + + return (int) len; +} +#endif /* MBEDTLS_USE_PSA_CRYPTO */ +/****************************************************************************** + * Generic helpers + ******************************************************************************/ + +/* Extend the public mbedtls_pk_get_type() by getting key type also in case of + * opaque keys. */ +static mbedtls_pk_type_t pk_get_type_ext(const mbedtls_pk_context *pk) +{ + mbedtls_pk_type_t pk_type = mbedtls_pk_get_type(pk); + +#if defined(MBEDTLS_USE_PSA_CRYPTO) + if (pk_type == MBEDTLS_PK_OPAQUE) { + psa_key_attributes_t opaque_attrs = PSA_KEY_ATTRIBUTES_INIT; + psa_key_type_t opaque_key_type; + + if (psa_get_key_attributes(pk->priv_id, &opaque_attrs) != PSA_SUCCESS) { + return MBEDTLS_PK_NONE; + } + opaque_key_type = psa_get_key_type(&opaque_attrs); + psa_reset_key_attributes(&opaque_attrs); + + if (PSA_KEY_TYPE_IS_ECC(opaque_key_type)) { + return MBEDTLS_PK_ECKEY; + } else if (PSA_KEY_TYPE_IS_RSA(opaque_key_type)) { + return MBEDTLS_PK_RSA; + } else { + return MBEDTLS_PK_NONE; + } + } else +#endif + return pk_type; +} + +/****************************************************************************** + * Public functions for writing private/public DER keys. + ******************************************************************************/ int mbedtls_pk_write_pubkey(unsigned char **p, unsigned char *start, const mbedtls_pk_context *key) { int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED; size_t len = 0; - (void) p; - (void) start; - (void) key; - (void) ret; - - PK_VALIDATE_RET(p != NULL); - PK_VALIDATE_RET(*p != NULL); - PK_VALIDATE_RET(start != NULL); - PK_VALIDATE_RET(key != NULL); - #if defined(MBEDTLS_RSA_C) if (mbedtls_pk_get_type(key) == MBEDTLS_PK_RSA) { - MBEDTLS_ASN1_CHK_ADD(len, pk_write_rsa_pubkey(p, start, mbedtls_pk_rsa(*key))); + MBEDTLS_ASN1_CHK_ADD(len, mbedtls_rsa_write_pubkey(mbedtls_pk_rsa(*key), start, p)); } else #endif -#if defined(MBEDTLS_ECP_C) +#if defined(MBEDTLS_PK_HAVE_ECC_KEYS) if (mbedtls_pk_get_type(key) == MBEDTLS_PK_ECKEY) { - MBEDTLS_ASN1_CHK_ADD(len, pk_write_ec_pubkey(p, start, mbedtls_pk_ec(*key))); + MBEDTLS_ASN1_CHK_ADD(len, pk_write_ec_pubkey(p, start, key)); } else #endif #if defined(MBEDTLS_USE_PSA_CRYPTO) if (mbedtls_pk_get_type(key) == MBEDTLS_PK_OPAQUE) { - size_t buffer_size; - psa_key_id_t *key_id = (psa_key_id_t *) key->pk_ctx; - - if (*p < start) { - return MBEDTLS_ERR_PK_BAD_INPUT_DATA; - } - - buffer_size = (size_t) (*p - start); - if (psa_export_public_key(*key_id, start, buffer_size, &len) - != PSA_SUCCESS) { - return MBEDTLS_ERR_PK_BAD_INPUT_DATA; - } else { - *p -= len; - memmove(*p, start, len); - } + MBEDTLS_ASN1_CHK_ADD(len, pk_write_opaque_pubkey(p, start, key)); } else #endif /* MBEDTLS_USE_PSA_CRYPTO */ return MBEDTLS_ERR_PK_FEATURE_UNAVAILABLE; @@ -222,19 +434,18 @@ int mbedtls_pk_write_pubkey(unsigned char **p, unsigned char *start, return (int) len; } -int mbedtls_pk_write_pubkey_der(mbedtls_pk_context *key, unsigned char *buf, size_t size) +int mbedtls_pk_write_pubkey_der(const mbedtls_pk_context *key, unsigned char *buf, size_t size) { int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED; unsigned char *c; - size_t len = 0, par_len = 0, oid_len; + int has_par = 1; + size_t len = 0, par_len = 0, oid_len = 0; mbedtls_pk_type_t pk_type; - const char *oid; + const char *oid = NULL; - PK_VALIDATE_RET(key != NULL); if (size == 0) { return MBEDTLS_ERR_ASN1_BUF_TOO_SMALL; } - PK_VALIDATE_RET(buf != NULL); c = buf + size; @@ -255,55 +466,33 @@ int mbedtls_pk_write_pubkey_der(mbedtls_pk_context *key, unsigned char *buf, siz MBEDTLS_ASN1_CHK_ADD(len, mbedtls_asn1_write_len(&c, buf, len)); MBEDTLS_ASN1_CHK_ADD(len, mbedtls_asn1_write_tag(&c, buf, MBEDTLS_ASN1_BIT_STRING)); - pk_type = mbedtls_pk_get_type(key); -#if defined(MBEDTLS_ECP_C) - if (pk_type == MBEDTLS_PK_ECKEY) { - MBEDTLS_ASN1_CHK_ADD(par_len, pk_write_ec_param(&c, buf, mbedtls_pk_ec(*key))); - } -#endif -#if defined(MBEDTLS_USE_PSA_CRYPTO) - if (pk_type == MBEDTLS_PK_OPAQUE) { - psa_key_attributes_t attributes = PSA_KEY_ATTRIBUTES_INIT; - psa_key_type_t key_type; - psa_key_id_t key_id; - psa_ecc_family_t curve; - size_t bits; - - key_id = *((psa_key_id_t *) key->pk_ctx); - if (PSA_SUCCESS != psa_get_key_attributes(key_id, &attributes)) { - return MBEDTLS_ERR_PK_HW_ACCEL_FAILED; - } - key_type = psa_get_key_type(&attributes); - bits = psa_get_key_bits(&attributes); - psa_reset_key_attributes(&attributes); - - curve = PSA_KEY_TYPE_ECC_GET_FAMILY(key_type); - if (curve == 0) { - return MBEDTLS_ERR_PK_FEATURE_UNAVAILABLE; + pk_type = pk_get_type_ext(key); + +#if defined(MBEDTLS_PK_HAVE_ECC_KEYS) + if (pk_get_type_ext(key) == MBEDTLS_PK_ECKEY) { + mbedtls_ecp_group_id ec_grp_id = mbedtls_pk_get_ec_group_id(key); + if (MBEDTLS_PK_IS_RFC8410_GROUP_ID(ec_grp_id)) { + ret = mbedtls_oid_get_oid_by_ec_grp_algid(ec_grp_id, &oid, &oid_len); + if (ret != 0) { + return ret; + } + has_par = 0; + } else { + MBEDTLS_ASN1_CHK_ADD(par_len, pk_write_ec_param(&c, buf, ec_grp_id)); } + } +#endif /* MBEDTLS_PK_HAVE_ECC_KEYS */ - ret = mbedtls_psa_get_ecc_oid_from_id(curve, bits, &oid, &oid_len); + /* At this point oid_len is not null only for EC Montgomery keys. */ + if (oid_len == 0) { + ret = mbedtls_oid_get_oid_by_pk_alg(pk_type, &oid, &oid_len); if (ret != 0) { - return MBEDTLS_ERR_PK_FEATURE_UNAVAILABLE; + return ret; } - - /* Write EC algorithm parameters; that's akin - * to pk_write_ec_param() above. */ - MBEDTLS_ASN1_CHK_ADD(par_len, mbedtls_asn1_write_oid(&c, buf, - oid, oid_len)); - - /* The rest of the function works as for legacy EC contexts. */ - pk_type = MBEDTLS_PK_ECKEY; - } -#endif /* MBEDTLS_USE_PSA_CRYPTO */ - - if ((ret = mbedtls_oid_get_oid_by_pk_alg(pk_type, &oid, - &oid_len)) != 0) { - return ret; } - MBEDTLS_ASN1_CHK_ADD(len, mbedtls_asn1_write_algorithm_identifier(&c, buf, oid, oid_len, - par_len)); + MBEDTLS_ASN1_CHK_ADD(len, mbedtls_asn1_write_algorithm_identifier_ext(&c, buf, oid, oid_len, + par_len, has_par)); MBEDTLS_ASN1_CHK_ADD(len, mbedtls_asn1_write_len(&c, buf, len)); MBEDTLS_ASN1_CHK_ADD(len, mbedtls_asn1_write_tag(&c, buf, MBEDTLS_ASN1_CONSTRUCTED | @@ -312,320 +501,120 @@ int mbedtls_pk_write_pubkey_der(mbedtls_pk_context *key, unsigned char *buf, siz return (int) len; } -int mbedtls_pk_write_key_der(mbedtls_pk_context *key, unsigned char *buf, size_t size) +int mbedtls_pk_write_key_der(const mbedtls_pk_context *key, unsigned char *buf, size_t size) { - int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED; unsigned char *c; - size_t len = 0; - (void) ret; - (void) c; - (void) key; - - PK_VALIDATE_RET(key != NULL); if (size == 0) { return MBEDTLS_ERR_ASN1_BUF_TOO_SMALL; } - PK_VALIDATE_RET(buf != NULL); c = buf + size; #if defined(MBEDTLS_RSA_C) - if (mbedtls_pk_get_type(key) == MBEDTLS_PK_RSA) { - mbedtls_mpi T; /* Temporary holding the exported parameters */ - mbedtls_rsa_context *rsa = mbedtls_pk_rsa(*key); - - /* - * Export the parameters one after another to avoid simultaneous copies. - */ - - mbedtls_mpi_init(&T); - - /* Export QP */ - if ((ret = mbedtls_rsa_export_crt(rsa, NULL, NULL, &T)) != 0 || - (ret = mbedtls_asn1_write_mpi(&c, buf, &T)) < 0) { - goto end_of_export; - } - len += ret; - - /* Export DQ */ - if ((ret = mbedtls_rsa_export_crt(rsa, NULL, &T, NULL)) != 0 || - (ret = mbedtls_asn1_write_mpi(&c, buf, &T)) < 0) { - goto end_of_export; - } - len += ret; - - /* Export DP */ - if ((ret = mbedtls_rsa_export_crt(rsa, &T, NULL, NULL)) != 0 || - (ret = mbedtls_asn1_write_mpi(&c, buf, &T)) < 0) { - goto end_of_export; - } - len += ret; - - /* Export Q */ - if ((ret = mbedtls_rsa_export(rsa, NULL, NULL, - &T, NULL, NULL)) != 0 || - (ret = mbedtls_asn1_write_mpi(&c, buf, &T)) < 0) { - goto end_of_export; - } - len += ret; - - /* Export P */ - if ((ret = mbedtls_rsa_export(rsa, NULL, &T, - NULL, NULL, NULL)) != 0 || - (ret = mbedtls_asn1_write_mpi(&c, buf, &T)) < 0) { - goto end_of_export; - } - len += ret; - - /* Export D */ - if ((ret = mbedtls_rsa_export(rsa, NULL, NULL, - NULL, &T, NULL)) != 0 || - (ret = mbedtls_asn1_write_mpi(&c, buf, &T)) < 0) { - goto end_of_export; - } - len += ret; - - /* Export E */ - if ((ret = mbedtls_rsa_export(rsa, NULL, NULL, - NULL, NULL, &T)) != 0 || - (ret = mbedtls_asn1_write_mpi(&c, buf, &T)) < 0) { - goto end_of_export; - } - len += ret; - - /* Export N */ - if ((ret = mbedtls_rsa_export(rsa, &T, NULL, - NULL, NULL, NULL)) != 0 || - (ret = mbedtls_asn1_write_mpi(&c, buf, &T)) < 0) { - goto end_of_export; - } - len += ret; - -end_of_export: - - mbedtls_mpi_free(&T); - if (ret < 0) { - return ret; - } - - MBEDTLS_ASN1_CHK_ADD(len, mbedtls_asn1_write_int(&c, buf, 0)); - MBEDTLS_ASN1_CHK_ADD(len, mbedtls_asn1_write_len(&c, buf, len)); - MBEDTLS_ASN1_CHK_ADD(len, mbedtls_asn1_write_tag(&c, - buf, MBEDTLS_ASN1_CONSTRUCTED | - MBEDTLS_ASN1_SEQUENCE)); + if (pk_get_type_ext(key) == MBEDTLS_PK_RSA) { + return pk_write_rsa_der(&c, buf, key); } else #endif /* MBEDTLS_RSA_C */ -#if defined(MBEDTLS_ECP_C) - if (mbedtls_pk_get_type(key) == MBEDTLS_PK_ECKEY) { - mbedtls_ecp_keypair *ec = mbedtls_pk_ec(*key); - size_t pub_len = 0, par_len = 0; - - /* - * RFC 5915, or SEC1 Appendix C.4 - * - * ECPrivateKey ::= SEQUENCE { - * version INTEGER { ecPrivkeyVer1(1) } (ecPrivkeyVer1), - * privateKey OCTET STRING, - * parameters [0] ECParameters {{ NamedCurve }} OPTIONAL, - * publicKey [1] BIT STRING OPTIONAL - * } - */ - - /* publicKey */ - MBEDTLS_ASN1_CHK_ADD(pub_len, pk_write_ec_pubkey(&c, buf, ec)); - - if (c - buf < 1) { - return MBEDTLS_ERR_ASN1_BUF_TOO_SMALL; +#if defined(MBEDTLS_PK_HAVE_ECC_KEYS) + if (pk_get_type_ext(key) == MBEDTLS_PK_ECKEY) { +#if defined(MBEDTLS_PK_HAVE_RFC8410_CURVES) + if (mbedtls_pk_is_rfc8410(key)) { + return pk_write_ec_rfc8410_der(&c, buf, key); } - *--c = 0; - pub_len += 1; - - MBEDTLS_ASN1_CHK_ADD(pub_len, mbedtls_asn1_write_len(&c, buf, pub_len)); - MBEDTLS_ASN1_CHK_ADD(pub_len, mbedtls_asn1_write_tag(&c, buf, MBEDTLS_ASN1_BIT_STRING)); - - MBEDTLS_ASN1_CHK_ADD(pub_len, mbedtls_asn1_write_len(&c, buf, pub_len)); - MBEDTLS_ASN1_CHK_ADD(pub_len, mbedtls_asn1_write_tag(&c, buf, - MBEDTLS_ASN1_CONTEXT_SPECIFIC | - MBEDTLS_ASN1_CONSTRUCTED | 1)); - len += pub_len; - - /* parameters */ - MBEDTLS_ASN1_CHK_ADD(par_len, pk_write_ec_param(&c, buf, ec)); - - MBEDTLS_ASN1_CHK_ADD(par_len, mbedtls_asn1_write_len(&c, buf, par_len)); - MBEDTLS_ASN1_CHK_ADD(par_len, mbedtls_asn1_write_tag(&c, buf, - MBEDTLS_ASN1_CONTEXT_SPECIFIC | - MBEDTLS_ASN1_CONSTRUCTED | 0)); - len += par_len; - - /* privateKey */ - MBEDTLS_ASN1_CHK_ADD(len, pk_write_ec_private(&c, buf, ec)); - - /* version */ - MBEDTLS_ASN1_CHK_ADD(len, mbedtls_asn1_write_int(&c, buf, 1)); - - MBEDTLS_ASN1_CHK_ADD(len, mbedtls_asn1_write_len(&c, buf, len)); - MBEDTLS_ASN1_CHK_ADD(len, mbedtls_asn1_write_tag(&c, buf, MBEDTLS_ASN1_CONSTRUCTED | - MBEDTLS_ASN1_SEQUENCE)); +#endif /* MBEDTLS_PK_HAVE_RFC8410_CURVES */ + return pk_write_ec_der(&c, buf, key); } else -#endif /* MBEDTLS_ECP_C */ +#endif /* MBEDTLS_PK_HAVE_ECC_KEYS */ return MBEDTLS_ERR_PK_FEATURE_UNAVAILABLE; - - return (int) len; } +/****************************************************************************** + * Public functions for wrinting private/public PEM keys. + ******************************************************************************/ #if defined(MBEDTLS_PEM_WRITE_C) -#define PEM_BEGIN_PUBLIC_KEY "-----BEGIN PUBLIC KEY-----\n" -#define PEM_END_PUBLIC_KEY "-----END PUBLIC KEY-----\n" - -#define PEM_BEGIN_PRIVATE_KEY_RSA "-----BEGIN RSA PRIVATE KEY-----\n" -#define PEM_END_PRIVATE_KEY_RSA "-----END RSA PRIVATE KEY-----\n" -#define PEM_BEGIN_PRIVATE_KEY_EC "-----BEGIN EC PRIVATE KEY-----\n" -#define PEM_END_PRIVATE_KEY_EC "-----END EC PRIVATE KEY-----\n" - -/* - * Max sizes of key per types. Shown as tag + len (+ content). - */ - -#if defined(MBEDTLS_RSA_C) -/* - * RSA public keys: - * SubjectPublicKeyInfo ::= SEQUENCE { 1 + 3 - * algorithm AlgorithmIdentifier, 1 + 1 (sequence) - * + 1 + 1 + 9 (rsa oid) - * + 1 + 1 (params null) - * subjectPublicKey BIT STRING } 1 + 3 + (1 + below) - * RSAPublicKey ::= SEQUENCE { 1 + 3 - * modulus INTEGER, -- n 1 + 3 + MPI_MAX + 1 - * publicExponent INTEGER -- e 1 + 3 + MPI_MAX + 1 - * } - */ -#define RSA_PUB_DER_MAX_BYTES (38 + 2 * MBEDTLS_MPI_MAX_SIZE) - -/* - * RSA private keys: - * RSAPrivateKey ::= SEQUENCE { 1 + 3 - * version Version, 1 + 1 + 1 - * modulus INTEGER, 1 + 3 + MPI_MAX + 1 - * publicExponent INTEGER, 1 + 3 + MPI_MAX + 1 - * privateExponent INTEGER, 1 + 3 + MPI_MAX + 1 - * prime1 INTEGER, 1 + 3 + MPI_MAX / 2 + 1 - * prime2 INTEGER, 1 + 3 + MPI_MAX / 2 + 1 - * exponent1 INTEGER, 1 + 3 + MPI_MAX / 2 + 1 - * exponent2 INTEGER, 1 + 3 + MPI_MAX / 2 + 1 - * coefficient INTEGER, 1 + 3 + MPI_MAX / 2 + 1 - * otherPrimeInfos OtherPrimeInfos OPTIONAL 0 (not supported) - * } - */ -#define MPI_MAX_SIZE_2 (MBEDTLS_MPI_MAX_SIZE / 2 + \ - MBEDTLS_MPI_MAX_SIZE % 2) -#define RSA_PRV_DER_MAX_BYTES (47 + 3 * MBEDTLS_MPI_MAX_SIZE \ - + 5 * MPI_MAX_SIZE_2) - -#else /* MBEDTLS_RSA_C */ - -#define RSA_PUB_DER_MAX_BYTES 0 -#define RSA_PRV_DER_MAX_BYTES 0 - -#endif /* MBEDTLS_RSA_C */ - -#if defined(MBEDTLS_ECP_C) -/* - * EC public keys: - * SubjectPublicKeyInfo ::= SEQUENCE { 1 + 2 - * algorithm AlgorithmIdentifier, 1 + 1 (sequence) - * + 1 + 1 + 7 (ec oid) - * + 1 + 1 + 9 (namedCurve oid) - * subjectPublicKey BIT STRING 1 + 2 + 1 [1] - * + 1 (point format) [1] - * + 2 * ECP_MAX (coords) [1] - * } - */ -#define ECP_PUB_DER_MAX_BYTES (30 + 2 * MBEDTLS_ECP_MAX_BYTES) - -/* - * EC private keys: - * ECPrivateKey ::= SEQUENCE { 1 + 2 - * version INTEGER , 1 + 1 + 1 - * privateKey OCTET STRING, 1 + 1 + ECP_MAX - * parameters [0] ECParameters OPTIONAL, 1 + 1 + (1 + 1 + 9) - * publicKey [1] BIT STRING OPTIONAL 1 + 2 + [1] above - * } - */ -#define ECP_PRV_DER_MAX_BYTES (29 + 3 * MBEDTLS_ECP_MAX_BYTES) - -#else /* MBEDTLS_ECP_C */ - -#define ECP_PUB_DER_MAX_BYTES 0 -#define ECP_PRV_DER_MAX_BYTES 0 - -#endif /* MBEDTLS_ECP_C */ +#define PUB_DER_MAX_BYTES \ + (MBEDTLS_PK_RSA_PUB_DER_MAX_BYTES > MBEDTLS_PK_ECP_PUB_DER_MAX_BYTES ? \ + MBEDTLS_PK_RSA_PUB_DER_MAX_BYTES : MBEDTLS_PK_ECP_PUB_DER_MAX_BYTES) +#define PRV_DER_MAX_BYTES \ + (MBEDTLS_PK_RSA_PRV_DER_MAX_BYTES > MBEDTLS_PK_ECP_PRV_DER_MAX_BYTES ? \ + MBEDTLS_PK_RSA_PRV_DER_MAX_BYTES : MBEDTLS_PK_ECP_PRV_DER_MAX_BYTES) -#define PUB_DER_MAX_BYTES (RSA_PUB_DER_MAX_BYTES > ECP_PUB_DER_MAX_BYTES ? \ - RSA_PUB_DER_MAX_BYTES : ECP_PUB_DER_MAX_BYTES) -#define PRV_DER_MAX_BYTES (RSA_PRV_DER_MAX_BYTES > ECP_PRV_DER_MAX_BYTES ? \ - RSA_PRV_DER_MAX_BYTES : ECP_PRV_DER_MAX_BYTES) - -int mbedtls_pk_write_pubkey_pem(mbedtls_pk_context *key, unsigned char *buf, size_t size) +int mbedtls_pk_write_pubkey_pem(const mbedtls_pk_context *key, unsigned char *buf, size_t size) { int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED; - unsigned char output_buf[PUB_DER_MAX_BYTES]; + unsigned char *output_buf = NULL; + output_buf = mbedtls_calloc(1, PUB_DER_MAX_BYTES); + if (output_buf == NULL) { + return MBEDTLS_ERR_PK_ALLOC_FAILED; + } size_t olen = 0; - PK_VALIDATE_RET(key != NULL); - PK_VALIDATE_RET(buf != NULL || size == 0); - if ((ret = mbedtls_pk_write_pubkey_der(key, output_buf, - sizeof(output_buf))) < 0) { - return ret; + PUB_DER_MAX_BYTES)) < 0) { + goto cleanup; } - if ((ret = mbedtls_pem_write_buffer(PEM_BEGIN_PUBLIC_KEY, PEM_END_PUBLIC_KEY, - output_buf + sizeof(output_buf) - ret, + if ((ret = mbedtls_pem_write_buffer(PEM_BEGIN_PUBLIC_KEY "\n", PEM_END_PUBLIC_KEY "\n", + output_buf + PUB_DER_MAX_BYTES - ret, ret, buf, size, &olen)) != 0) { - return ret; + goto cleanup; } - return 0; + ret = 0; +cleanup: + mbedtls_free(output_buf); + return ret; } -int mbedtls_pk_write_key_pem(mbedtls_pk_context *key, unsigned char *buf, size_t size) +int mbedtls_pk_write_key_pem(const mbedtls_pk_context *key, unsigned char *buf, size_t size) { int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED; - unsigned char output_buf[PRV_DER_MAX_BYTES]; + unsigned char *output_buf = NULL; + output_buf = mbedtls_calloc(1, PRV_DER_MAX_BYTES); + if (output_buf == NULL) { + return MBEDTLS_ERR_PK_ALLOC_FAILED; + } const char *begin, *end; size_t olen = 0; - PK_VALIDATE_RET(key != NULL); - PK_VALIDATE_RET(buf != NULL || size == 0); - - if ((ret = mbedtls_pk_write_key_der(key, output_buf, sizeof(output_buf))) < 0) { - return ret; + if ((ret = mbedtls_pk_write_key_der(key, output_buf, PRV_DER_MAX_BYTES)) < 0) { + goto cleanup; } #if defined(MBEDTLS_RSA_C) - if (mbedtls_pk_get_type(key) == MBEDTLS_PK_RSA) { - begin = PEM_BEGIN_PRIVATE_KEY_RSA; - end = PEM_END_PRIVATE_KEY_RSA; + if (pk_get_type_ext(key) == MBEDTLS_PK_RSA) { + begin = PEM_BEGIN_PRIVATE_KEY_RSA "\n"; + end = PEM_END_PRIVATE_KEY_RSA "\n"; } else #endif -#if defined(MBEDTLS_ECP_C) - if (mbedtls_pk_get_type(key) == MBEDTLS_PK_ECKEY) { - begin = PEM_BEGIN_PRIVATE_KEY_EC; - end = PEM_END_PRIVATE_KEY_EC; +#if defined(MBEDTLS_PK_HAVE_ECC_KEYS) + if (pk_get_type_ext(key) == MBEDTLS_PK_ECKEY) { + if (mbedtls_pk_is_rfc8410(key)) { + begin = PEM_BEGIN_PRIVATE_KEY_PKCS8 "\n"; + end = PEM_END_PRIVATE_KEY_PKCS8 "\n"; + } else { + begin = PEM_BEGIN_PRIVATE_KEY_EC "\n"; + end = PEM_END_PRIVATE_KEY_EC "\n"; + } } else -#endif - return MBEDTLS_ERR_PK_FEATURE_UNAVAILABLE; +#endif /* MBEDTLS_PK_HAVE_ECC_KEYS */ + { + ret = MBEDTLS_ERR_PK_FEATURE_UNAVAILABLE; + goto cleanup; + } if ((ret = mbedtls_pem_write_buffer(begin, end, - output_buf + sizeof(output_buf) - ret, + output_buf + PRV_DER_MAX_BYTES - ret, ret, buf, size, &olen)) != 0) { - return ret; + goto cleanup; } - return 0; + ret = 0; +cleanup: + mbedtls_zeroize_and_free(output_buf, PRV_DER_MAX_BYTES); + return ret; } #endif /* MBEDTLS_PEM_WRITE_C */ diff --git a/vendor/mbedtls/library/pkwrite.h b/vendor/mbedtls/library/pkwrite.h new file mode 100644 index 0000000000..01dc3d2f0f --- /dev/null +++ b/vendor/mbedtls/library/pkwrite.h @@ -0,0 +1,121 @@ +/** + * \file pkwrite.h + * + * \brief Internal defines shared by the PK write module + */ +/* + * Copyright The Mbed TLS Contributors + * SPDX-License-Identifier: Apache-2.0 OR GPL-2.0-or-later + */ + +#ifndef MBEDTLS_PK_WRITE_H +#define MBEDTLS_PK_WRITE_H + +#include "mbedtls/build_info.h" + +#include "mbedtls/pk.h" + +#if defined(MBEDTLS_USE_PSA_CRYPTO) +#include "psa/crypto.h" +#endif /* MBEDTLS_USE_PSA_CRYPTO */ + +/* + * Max sizes of key per types. Shown as tag + len (+ content). + */ + +#if defined(MBEDTLS_RSA_C) +/* + * RSA public keys: + * SubjectPublicKeyInfo ::= SEQUENCE { 1 + 3 + * algorithm AlgorithmIdentifier, 1 + 1 (sequence) + * + 1 + 1 + 9 (rsa oid) + * + 1 + 1 (params null) + * subjectPublicKey BIT STRING } 1 + 3 + (1 + below) + * RSAPublicKey ::= SEQUENCE { 1 + 3 + * modulus INTEGER, -- n 1 + 3 + MPI_MAX + 1 + * publicExponent INTEGER -- e 1 + 3 + MPI_MAX + 1 + * } + */ +#define MBEDTLS_PK_RSA_PUB_DER_MAX_BYTES (38 + 2 * MBEDTLS_MPI_MAX_SIZE) + +/* + * RSA private keys: + * RSAPrivateKey ::= SEQUENCE { 1 + 3 + * version Version, 1 + 1 + 1 + * modulus INTEGER, 1 + 3 + MPI_MAX + 1 + * publicExponent INTEGER, 1 + 3 + MPI_MAX + 1 + * privateExponent INTEGER, 1 + 3 + MPI_MAX + 1 + * prime1 INTEGER, 1 + 3 + MPI_MAX / 2 + 1 + * prime2 INTEGER, 1 + 3 + MPI_MAX / 2 + 1 + * exponent1 INTEGER, 1 + 3 + MPI_MAX / 2 + 1 + * exponent2 INTEGER, 1 + 3 + MPI_MAX / 2 + 1 + * coefficient INTEGER, 1 + 3 + MPI_MAX / 2 + 1 + * otherPrimeInfos OtherPrimeInfos OPTIONAL 0 (not supported) + * } + */ +#define MBEDTLS_MPI_MAX_SIZE_2 (MBEDTLS_MPI_MAX_SIZE / 2 + \ + MBEDTLS_MPI_MAX_SIZE % 2) +#define MBEDTLS_PK_RSA_PRV_DER_MAX_BYTES (47 + 3 * MBEDTLS_MPI_MAX_SIZE \ + + 5 * MBEDTLS_MPI_MAX_SIZE_2) + +#else /* MBEDTLS_RSA_C */ + +#define MBEDTLS_PK_RSA_PUB_DER_MAX_BYTES 0 +#define MBEDTLS_PK_RSA_PRV_DER_MAX_BYTES 0 + +#endif /* MBEDTLS_RSA_C */ + +#if defined(MBEDTLS_PK_HAVE_ECC_KEYS) + +/* Find the maximum number of bytes necessary to store an EC point. When USE_PSA + * is defined this means looking for the maximum between PSA and built-in + * supported curves. */ +#if defined(MBEDTLS_USE_PSA_CRYPTO) +#define MBEDTLS_PK_MAX_ECC_BYTES (PSA_BITS_TO_BYTES(PSA_VENDOR_ECC_MAX_CURVE_BITS) > \ + MBEDTLS_ECP_MAX_BYTES ? \ + PSA_BITS_TO_BYTES(PSA_VENDOR_ECC_MAX_CURVE_BITS) : \ + MBEDTLS_ECP_MAX_BYTES) +#else /* MBEDTLS_USE_PSA_CRYPTO */ +#define MBEDTLS_PK_MAX_ECC_BYTES MBEDTLS_ECP_MAX_BYTES +#endif /* MBEDTLS_USE_PSA_CRYPTO */ + +/* + * EC public keys: + * SubjectPublicKeyInfo ::= SEQUENCE { 1 + 2 + * algorithm AlgorithmIdentifier, 1 + 1 (sequence) + * + 1 + 1 + 7 (ec oid) + * + 1 + 1 + 9 (namedCurve oid) + * subjectPublicKey BIT STRING 1 + 2 + 1 [1] + * + 1 (point format) [1] + * + 2 * ECP_MAX (coords) [1] + * } + */ +#define MBEDTLS_PK_ECP_PUB_DER_MAX_BYTES (30 + 2 * MBEDTLS_PK_MAX_ECC_BYTES) + +/* + * EC private keys: + * ECPrivateKey ::= SEQUENCE { 1 + 2 + * version INTEGER , 1 + 1 + 1 + * privateKey OCTET STRING, 1 + 1 + ECP_MAX + * parameters [0] ECParameters OPTIONAL, 1 + 1 + (1 + 1 + 9) + * publicKey [1] BIT STRING OPTIONAL 1 + 2 + [1] above + * } + */ +#define MBEDTLS_PK_ECP_PRV_DER_MAX_BYTES (29 + 3 * MBEDTLS_PK_MAX_ECC_BYTES) + +#else /* MBEDTLS_PK_HAVE_ECC_KEYS */ + +#define MBEDTLS_PK_ECP_PUB_DER_MAX_BYTES 0 +#define MBEDTLS_PK_ECP_PRV_DER_MAX_BYTES 0 + +#endif /* MBEDTLS_PK_HAVE_ECC_KEYS */ + +/* Define the maximum available public key DER length based on the supported + * key types (EC and/or RSA). */ +#if (MBEDTLS_PK_RSA_PUB_DER_MAX_BYTES > MBEDTLS_PK_ECP_PUB_DER_MAX_BYTES) +#define MBEDTLS_PK_WRITE_PUBKEY_MAX_SIZE MBEDTLS_PK_RSA_PUB_DER_MAX_BYTES +#else +#define MBEDTLS_PK_WRITE_PUBKEY_MAX_SIZE MBEDTLS_PK_ECP_PUB_DER_MAX_BYTES +#endif + +#endif /* MBEDTLS_PK_WRITE_H */ diff --git a/vendor/mbedtls/library/platform.c b/vendor/mbedtls/library/platform.c index c8b0328d1d..890c4cbaba 100644 --- a/vendor/mbedtls/library/platform.c +++ b/vendor/mbedtls/library/platform.c @@ -2,19 +2,7 @@ * Platform abstraction layer * * Copyright The Mbed TLS Contributors - * SPDX-License-Identifier: Apache-2.0 - * - * Licensed under the Apache License, Version 2.0 (the "License"); you may - * not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT - * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. + * SPDX-License-Identifier: Apache-2.0 OR GPL-2.0-or-later */ #include "common.h" @@ -226,6 +214,28 @@ int mbedtls_platform_set_fprintf(int (*fprintf_func)(FILE *, const char *, ...)) } #endif /* MBEDTLS_PLATFORM_FPRINTF_ALT */ +#if defined(MBEDTLS_PLATFORM_SETBUF_ALT) +#if !defined(MBEDTLS_PLATFORM_STD_SETBUF) +/* + * Make dummy function to prevent NULL pointer dereferences + */ +static void platform_setbuf_uninit(FILE *stream, char *buf) +{ + ((void) stream); + ((void) buf); +} + +#define MBEDTLS_PLATFORM_STD_SETBUF platform_setbuf_uninit +#endif /* !MBEDTLS_PLATFORM_STD_SETBUF */ +void (*mbedtls_setbuf)(FILE *stream, char *buf) = MBEDTLS_PLATFORM_STD_SETBUF; + +int mbedtls_platform_set_setbuf(void (*setbuf_func)(FILE *stream, char *buf)) +{ + mbedtls_setbuf = setbuf_func; + return 0; +} +#endif /* MBEDTLS_PLATFORM_SETBUF_ALT */ + #if defined(MBEDTLS_PLATFORM_EXIT_ALT) #if !defined(MBEDTLS_PLATFORM_STD_EXIT) /* @@ -289,6 +299,9 @@ int mbedtls_platform_std_nv_seed_read(unsigned char *buf, size_t buf_len) return -1; } + /* Ensure no stdio buffering of secrets, as such buffers cannot be wiped. */ + mbedtls_setbuf(file, NULL); + if ((n = fread(buf, 1, buf_len, file)) != buf_len) { fclose(file); mbedtls_platform_zeroize(buf, buf_len); @@ -308,6 +321,9 @@ int mbedtls_platform_std_nv_seed_write(unsigned char *buf, size_t buf_len) return -1; } + /* Ensure no stdio buffering of secrets, as such buffers cannot be wiped. */ + mbedtls_setbuf(file, NULL); + if ((n = fwrite(buf, 1, buf_len, file)) != buf_len) { fclose(file); return -1; diff --git a/vendor/mbedtls/library/platform_util.c b/vendor/mbedtls/library/platform_util.c index 3783f0eb84..0741bf575e 100644 --- a/vendor/mbedtls/library/platform_util.c +++ b/vendor/mbedtls/library/platform_util.c @@ -3,29 +3,23 @@ * library. * * Copyright The Mbed TLS Contributors - * SPDX-License-Identifier: Apache-2.0 - * - * Licensed under the Apache License, Version 2.0 (the "License"); you may - * not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT - * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. + * SPDX-License-Identifier: Apache-2.0 OR GPL-2.0-or-later */ /* * Ensure gmtime_r is available even with -std=c99; must be defined before - * config.h, which pulls in glibc's features.h. Harmless on other platforms. + * mbedtls_config.h, which pulls in glibc's features.h. Harmless on other platforms + * except OpenBSD, where it stops us accessing explicit_bzero. */ -#if !defined(_POSIX_C_SOURCE) +#if !defined(_POSIX_C_SOURCE) && !defined(__OpenBSD__) #define _POSIX_C_SOURCE 200112L #endif +#if !defined(_GNU_SOURCE) +/* Clang requires this to get support for explicit_bzero */ +#define _GNU_SOURCE +#endif + #include "common.h" #include "mbedtls/platform_util.h" @@ -33,11 +27,40 @@ #include "mbedtls/threading.h" #include + +#ifndef __STDC_WANT_LIB_EXT1__ +#define __STDC_WANT_LIB_EXT1__ 1 /* Ask for the C11 gmtime_s() and memset_s() if available */ +#endif #include +#if defined(_WIN32) +#include +#endif + +// Detect platforms known to support explicit_bzero() +#if defined(__GLIBC__) && (__GLIBC__ >= 2) && (__GLIBC_MINOR__ >= 25) +#define MBEDTLS_PLATFORM_HAS_EXPLICIT_BZERO 1 +#elif (defined(__FreeBSD__) && (__FreeBSD_version >= 1100037)) || defined(__OpenBSD__) +#define MBEDTLS_PLATFORM_HAS_EXPLICIT_BZERO 1 +#endif + #if !defined(MBEDTLS_PLATFORM_ZEROIZE_ALT) + +#undef HAVE_MEMORY_SANITIZER +#if defined(__has_feature) +#if __has_feature(memory_sanitizer) +#include +#define HAVE_MEMORY_SANITIZER +#endif +#endif + /* - * This implementation should never be optimized out by the compiler + * Where possible, we try to detect the presence of a platform-provided + * secure memset, such as explicit_bzero(), that is safe against being optimized + * out, and use that. + * + * For other platforms, we provide an implementation that aims not to be + * optimized out by the compiler. * * This implementation for mbedtls_platform_zeroize() was inspired from Colin * Percival's blog article at: @@ -52,36 +75,84 @@ * (refer to http://www.daemonology.net/blog/2014-09-05-erratum.html for * details), optimizations of the following form are still possible: * - * if( memset_func != memset ) - * memset_func( buf, 0, len ); + * if (memset_func != memset) + * memset_func(buf, 0, len); * * Note that it is extremely difficult to guarantee that - * mbedtls_platform_zeroize() will not be optimized out by aggressive compilers + * the memset() call will not be optimized out by aggressive compilers * in a portable way. For this reason, Mbed TLS also provides the configuration * option MBEDTLS_PLATFORM_ZEROIZE_ALT, which allows users to configure * mbedtls_platform_zeroize() to use a suitable implementation for their * platform and needs. */ +#if !defined(MBEDTLS_PLATFORM_HAS_EXPLICIT_BZERO) && !(defined(__STDC_LIB_EXT1__) && \ + !defined(__IAR_SYSTEMS_ICC__)) \ + && !defined(_WIN32) static void *(*const volatile memset_func)(void *, int, size_t) = memset; +#endif void mbedtls_platform_zeroize(void *buf, size_t len) { - MBEDTLS_INTERNAL_VALIDATE(len == 0 || buf != NULL); - if (len > 0) { +#if defined(MBEDTLS_PLATFORM_HAS_EXPLICIT_BZERO) + explicit_bzero(buf, len); +#if defined(HAVE_MEMORY_SANITIZER) + /* You'd think that Msan would recognize explicit_bzero() as + * equivalent to bzero(), but it actually doesn't on several + * platforms, including Linux (Ubuntu 20.04). + * https://github.com/google/sanitizers/issues/1507 + * https://github.com/openssh/openssh-portable/commit/74433a19bb6f4cef607680fa4d1d7d81ca3826aa + */ + __msan_unpoison(buf, len); +#endif +#elif defined(__STDC_LIB_EXT1__) && !defined(__IAR_SYSTEMS_ICC__) + memset_s(buf, len, 0, len); +#elif defined(_WIN32) + SecureZeroMemory(buf, len); +#else memset_func(buf, 0, len); +#endif + +#if defined(__GNUC__) + /* For clang and recent gcc, pretend that we have some assembly that reads the + * zero'd memory as an additional protection against being optimised away. */ +#if defined(__clang__) || (__GNUC__ >= 10) +#if defined(__clang__) +#pragma clang diagnostic push +#pragma clang diagnostic ignored "-Wvla" +#elif defined(MBEDTLS_COMPILER_IS_GCC) +#pragma GCC diagnostic push +#pragma GCC diagnostic ignored "-Wvla" +#endif + asm volatile ("" : : "m" (*(char (*)[len]) buf) :); +#if defined(__clang__) +#pragma clang diagnostic pop +#elif defined(MBEDTLS_COMPILER_IS_GCC) +#pragma GCC diagnostic pop +#endif +#endif +#endif } } #endif /* MBEDTLS_PLATFORM_ZEROIZE_ALT */ +void mbedtls_zeroize_and_free(void *buf, size_t len) +{ + if (buf != NULL) { + mbedtls_platform_zeroize(buf, len); + } + + mbedtls_free(buf); +} + #if defined(MBEDTLS_HAVE_TIME_DATE) && !defined(MBEDTLS_PLATFORM_GMTIME_R_ALT) #include #if !defined(_WIN32) && (defined(unix) || \ defined(__unix) || defined(__unix__) || (defined(__APPLE__) && \ - defined(__MACH__))) + defined(__MACH__)) || defined__midipix__) #include #endif /* !_WIN32 && (unix || __unix || __unix__ || - * (__APPLE__ && __MACH__)) */ + * (__APPLE__ && __MACH__) || __midipix__) */ #if !((defined(_POSIX_VERSION) && _POSIX_VERSION >= 200809L) || \ (defined(_POSIX_THREAD_SAFE_FUNCTIONS) && \ @@ -93,9 +164,10 @@ void mbedtls_platform_zeroize(void *buf, size_t len) * threading.h. However, this macro is not part of the Mbed TLS public API, so * we keep it private by only defining it in this file */ -#if !(defined(_WIN32) && !defined(EFIX64) && !defined(EFI32)) +#if !(defined(_WIN32) && !defined(EFIX64) && !defined(EFI32)) || \ + (defined(__MINGW32__) && !defined(__MINGW64_VERSION_MAJOR)) #define PLATFORM_UTIL_USE_GMTIME -#endif /* ! ( defined(_WIN32) && !defined(EFIX64) && !defined(EFI32) ) */ +#endif #endif /* !( ( defined(_POSIX_VERSION) && _POSIX_VERSION >= 200809L ) || \ ( defined(_POSIX_THREAD_SAFE_FUNCTIONS ) && \ @@ -104,8 +176,13 @@ void mbedtls_platform_zeroize(void *buf, size_t len) struct tm *mbedtls_platform_gmtime_r(const mbedtls_time_t *tt, struct tm *tm_buf) { -#if defined(_WIN32) && !defined(EFIX64) && !defined(EFI32) +#if defined(_WIN32) && !defined(PLATFORM_UTIL_USE_GMTIME) +#if defined(__STDC_LIB_EXT1__) + return (gmtime_s(tt, tm_buf) == 0) ? NULL : tm_buf; +#else + /* MSVC and mingw64 argument order and return value are inconsistent with the C11 standard */ return (gmtime_s(tm_buf, tt) == 0) ? tm_buf : NULL; +#endif #elif !defined(PLATFORM_UTIL_USE_GMTIME) return gmtime_r(tt, tm_buf); #else @@ -133,3 +210,54 @@ struct tm *mbedtls_platform_gmtime_r(const mbedtls_time_t *tt, #endif /* _WIN32 && !EFIX64 && !EFI32 */ } #endif /* MBEDTLS_HAVE_TIME_DATE && MBEDTLS_PLATFORM_GMTIME_R_ALT */ + +#if defined(MBEDTLS_TEST_HOOKS) +void (*mbedtls_test_hook_test_fail)(const char *, int, const char *); +#endif /* MBEDTLS_TEST_HOOKS */ + +#if defined(MBEDTLS_HAVE_TIME) && !defined(MBEDTLS_PLATFORM_MS_TIME_ALT) + +#include +#if !defined(_WIN32) && \ + (defined(unix) || defined(__unix) || defined(__unix__) || \ + (defined(__APPLE__) && defined(__MACH__)) || defined(__HAIKU__) || defined(__midipix__)) +#include +#endif \ + /* !_WIN32 && (unix || __unix || __unix__ || (__APPLE__ && __MACH__) || __HAIKU__ || __midipix__) */ +#if (defined(_POSIX_VERSION) && _POSIX_VERSION >= 199309L) || defined(__HAIKU__) +mbedtls_ms_time_t mbedtls_ms_time(void) +{ + int ret; + struct timespec tv; + mbedtls_ms_time_t current_ms; + +#if defined(__linux__) && defined(CLOCK_BOOTTIME) || defined(__midipix__) + ret = clock_gettime(CLOCK_BOOTTIME, &tv); +#else + ret = clock_gettime(CLOCK_MONOTONIC, &tv); +#endif + if (ret) { + return time(NULL) * 1000; + } + + current_ms = tv.tv_sec; + + return current_ms*1000 + tv.tv_nsec / 1000000; +} +#elif defined(_WIN32) || defined(WIN32) || defined(__CYGWIN__) || \ + defined(__MINGW32__) || defined(_WIN64) +#include +mbedtls_ms_time_t mbedtls_ms_time(void) +{ + FILETIME ct; + mbedtls_ms_time_t current_ms; + + GetSystemTimeAsFileTime(&ct); + current_ms = ((mbedtls_ms_time_t) ct.dwLowDateTime + + ((mbedtls_ms_time_t) (ct.dwHighDateTime) << 32LL))/10000; + return current_ms; +} +#else +#error "No mbedtls_ms_time available" +#endif +#endif /* MBEDTLS_HAVE_TIME && !MBEDTLS_PLATFORM_MS_TIME_ALT */ diff --git a/vendor/mbedtls/library/poly1305.c b/vendor/mbedtls/library/poly1305.c index 510a45a698..c9ebe9e1da 100644 --- a/vendor/mbedtls/library/poly1305.c +++ b/vendor/mbedtls/library/poly1305.c @@ -4,19 +4,7 @@ * \brief Poly1305 authentication algorithm. * * Copyright The Mbed TLS Contributors - * SPDX-License-Identifier: Apache-2.0 - * - * Licensed under the Apache License, Version 2.0 (the "License"); you may - * not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT - * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. + * SPDX-License-Identifier: Apache-2.0 OR GPL-2.0-or-later */ #include "common.h" @@ -32,12 +20,6 @@ #if !defined(MBEDTLS_POLY1305_ALT) -/* Parameter validation macros */ -#define POLY1305_VALIDATE_RET(cond) \ - MBEDTLS_INTERNAL_VALIDATE_RET(cond, MBEDTLS_ERR_POLY1305_BAD_INPUT_DATA) -#define POLY1305_VALIDATE(cond) \ - MBEDTLS_INTERNAL_VALIDATE(cond) - #define POLY1305_BLOCK_SIZE_BYTES (16U) /* @@ -245,8 +227,6 @@ static void poly1305_compute_mac(const mbedtls_poly1305_context *ctx, void mbedtls_poly1305_init(mbedtls_poly1305_context *ctx) { - POLY1305_VALIDATE(ctx != NULL); - mbedtls_platform_zeroize(ctx, sizeof(mbedtls_poly1305_context)); } @@ -262,9 +242,6 @@ void mbedtls_poly1305_free(mbedtls_poly1305_context *ctx) int mbedtls_poly1305_starts(mbedtls_poly1305_context *ctx, const unsigned char key[32]) { - POLY1305_VALIDATE_RET(ctx != NULL); - POLY1305_VALIDATE_RET(key != NULL); - /* r &= 0x0ffffffc0ffffffc0ffffffc0fffffff */ ctx->r[0] = MBEDTLS_GET_UINT32_LE(key, 0) & 0x0FFFFFFFU; ctx->r[1] = MBEDTLS_GET_UINT32_LE(key, 4) & 0x0FFFFFFCU; @@ -298,8 +275,6 @@ int mbedtls_poly1305_update(mbedtls_poly1305_context *ctx, size_t remaining = ilen; size_t queue_free_len; size_t nblocks; - POLY1305_VALIDATE_RET(ctx != NULL); - POLY1305_VALIDATE_RET(ilen == 0 || input != NULL); if ((remaining > 0U) && (ctx->queue_len > 0U)) { queue_free_len = (POLY1305_BLOCK_SIZE_BYTES - ctx->queue_len); @@ -351,9 +326,6 @@ int mbedtls_poly1305_update(mbedtls_poly1305_context *ctx, int mbedtls_poly1305_finish(mbedtls_poly1305_context *ctx, unsigned char mac[16]) { - POLY1305_VALIDATE_RET(ctx != NULL); - POLY1305_VALIDATE_RET(mac != NULL); - /* Process any leftover data */ if (ctx->queue_len > 0U) { /* Add padding bit */ @@ -381,9 +353,6 @@ int mbedtls_poly1305_mac(const unsigned char key[32], { mbedtls_poly1305_context ctx; int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED; - POLY1305_VALIDATE_RET(key != NULL); - POLY1305_VALIDATE_RET(mac != NULL); - POLY1305_VALIDATE_RET(ilen == 0 || input != NULL); mbedtls_poly1305_init(&ctx); diff --git a/vendor/mbedtls/library/psa_crypto.c b/vendor/mbedtls/library/psa_crypto.c index e4b865ec97..969c695ac0 100644 --- a/vendor/mbedtls/library/psa_crypto.c +++ b/vendor/mbedtls/library/psa_crypto.c @@ -3,22 +3,11 @@ */ /* * Copyright The Mbed TLS Contributors - * SPDX-License-Identifier: Apache-2.0 - * - * Licensed under the Apache License, Version 2.0 (the "License"); you may - * not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT - * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. + * SPDX-License-Identifier: Apache-2.0 OR GPL-2.0-or-later */ #include "common.h" +#include "psa_crypto_core_common.h" #if defined(MBEDTLS_PSA_CRYPTO_C) @@ -27,12 +16,15 @@ #endif #include "psa/crypto.h" +#include "psa/crypto_values.h" #include "psa_crypto_cipher.h" #include "psa_crypto_core.h" #include "psa_crypto_invasive.h" #include "psa_crypto_driver_wrappers.h" +#include "psa_crypto_driver_wrappers_no_static.h" #include "psa_crypto_ecp.h" +#include "psa_crypto_ffdh.h" #include "psa_crypto_hash.h" #include "psa_crypto_mac.h" #include "psa_crypto_rsa.h" @@ -52,30 +44,25 @@ #include "mbedtls/platform.h" #include "mbedtls/aes.h" -#include "mbedtls/arc4.h" #include "mbedtls/asn1.h" #include "mbedtls/asn1write.h" #include "mbedtls/bignum.h" -#include "mbedtls/blowfish.h" #include "mbedtls/camellia.h" #include "mbedtls/chacha20.h" #include "mbedtls/chachapoly.h" #include "mbedtls/cipher.h" #include "mbedtls/ccm.h" #include "mbedtls/cmac.h" +#include "mbedtls/constant_time.h" #include "mbedtls/des.h" #include "mbedtls/ecdh.h" #include "mbedtls/ecp.h" #include "mbedtls/entropy.h" #include "mbedtls/error.h" #include "mbedtls/gcm.h" -#include "mbedtls/md2.h" -#include "mbedtls/md4.h" #include "mbedtls/md5.h" -#include "mbedtls/md.h" -#include "mbedtls/md_internal.h" #include "mbedtls/pk.h" -#include "mbedtls/pk_internal.h" +#include "pk_wrap.h" #include "mbedtls/platform_util.h" #include "mbedtls/error.h" #include "mbedtls/ripemd160.h" @@ -83,9 +70,14 @@ #include "mbedtls/sha1.h" #include "mbedtls/sha256.h" #include "mbedtls/sha512.h" -#include "mbedtls/xtea.h" +#include "mbedtls/psa_util.h" +#include "mbedtls/threading.h" -#define ARRAY_LENGTH(array) (sizeof(array) / sizeof(*(array))) +#if defined(MBEDTLS_PSA_BUILTIN_ALG_HKDF) || \ + defined(MBEDTLS_PSA_BUILTIN_ALG_HKDF_EXTRACT) || \ + defined(MBEDTLS_PSA_BUILTIN_ALG_HKDF_EXPAND) +#define BUILTIN_ALG_ANY_HKDF 1 +#endif /****************************************************************/ /* Global data, support functions and library management */ @@ -101,23 +93,242 @@ static int key_type_is_raw_bytes(psa_key_type_t type) #define RNG_INITIALIZED 1 #define RNG_SEEDED 2 +/* IDs for PSA crypto subsystems. Starts at 1 to catch potential uninitialized + * variables as arguments. */ +typedef enum { + PSA_CRYPTO_SUBSYSTEM_DRIVER_WRAPPERS = 1, + PSA_CRYPTO_SUBSYSTEM_KEY_SLOTS, + PSA_CRYPTO_SUBSYSTEM_RNG, + PSA_CRYPTO_SUBSYSTEM_TRANSACTION, +} mbedtls_psa_crypto_subsystem; + +/* Initialization flags for global_data::initialized */ +#define PSA_CRYPTO_SUBSYSTEM_DRIVER_WRAPPERS_INITIALIZED 0x01 +#define PSA_CRYPTO_SUBSYSTEM_KEY_SLOTS_INITIALIZED 0x02 +#define PSA_CRYPTO_SUBSYSTEM_TRANSACTION_INITIALIZED 0x04 + +#define PSA_CRYPTO_SUBSYSTEM_ALL_INITIALISED ( \ + PSA_CRYPTO_SUBSYSTEM_DRIVER_WRAPPERS_INITIALIZED | \ + PSA_CRYPTO_SUBSYSTEM_KEY_SLOTS_INITIALIZED | \ + PSA_CRYPTO_SUBSYSTEM_TRANSACTION_INITIALIZED) + typedef struct { - unsigned initialized : 1; - unsigned rng_state : 2; + uint8_t initialized; + uint8_t rng_state; mbedtls_psa_random_context_t rng; } psa_global_data_t; static psa_global_data_t global_data; -#if !defined(MBEDTLS_PSA_CRYPTO_EXTERNAL_RNG) -mbedtls_psa_drbg_context_t *const mbedtls_psa_random_state = - &global_data.rng.drbg; -#endif +static uint8_t psa_get_initialized(void) +{ + uint8_t initialized; + +#if defined(MBEDTLS_THREADING_C) + mbedtls_mutex_lock(&mbedtls_threading_psa_rngdata_mutex); +#endif /* defined(MBEDTLS_THREADING_C) */ + + initialized = global_data.rng_state == RNG_SEEDED; + +#if defined(MBEDTLS_THREADING_C) + mbedtls_mutex_unlock(&mbedtls_threading_psa_rngdata_mutex); +#endif /* defined(MBEDTLS_THREADING_C) */ + +#if defined(MBEDTLS_THREADING_C) + mbedtls_mutex_lock(&mbedtls_threading_psa_globaldata_mutex); +#endif /* defined(MBEDTLS_THREADING_C) */ + + initialized = + (initialized && (global_data.initialized == PSA_CRYPTO_SUBSYSTEM_ALL_INITIALISED)); + +#if defined(MBEDTLS_THREADING_C) + mbedtls_mutex_unlock(&mbedtls_threading_psa_globaldata_mutex); +#endif /* defined(MBEDTLS_THREADING_C) */ + + return initialized; +} + +static uint8_t psa_get_drivers_initialized(void) +{ + uint8_t initialized; + +#if defined(MBEDTLS_THREADING_C) + mbedtls_mutex_lock(&mbedtls_threading_psa_globaldata_mutex); +#endif /* defined(MBEDTLS_THREADING_C) */ + + initialized = (global_data.initialized & PSA_CRYPTO_SUBSYSTEM_DRIVER_WRAPPERS_INITIALIZED) != 0; + +#if defined(MBEDTLS_THREADING_C) + mbedtls_mutex_unlock(&mbedtls_threading_psa_globaldata_mutex); +#endif /* defined(MBEDTLS_THREADING_C) */ + + return initialized; +} #define GUARD_MODULE_INITIALIZED \ - if (global_data.initialized == 0) \ + if (psa_get_initialized() == 0) \ return PSA_ERROR_BAD_STATE; +#if !defined(MBEDTLS_PSA_ASSUME_EXCLUSIVE_BUFFERS) + +/* Declare a local copy of an input buffer and a variable that will be used + * to store a pointer to the start of the buffer. + * + * Note: This macro must be called before any operations which may jump to + * the exit label, so that the local input copy object is safe to be freed. + * + * Assumptions: + * - input is the name of a pointer to the buffer to be copied + * - The name LOCAL_INPUT_COPY_OF_input is unused in the current scope + * - input_copy_name is a name that is unused in the current scope + */ +#define LOCAL_INPUT_DECLARE(input, input_copy_name) \ + psa_crypto_local_input_t LOCAL_INPUT_COPY_OF_##input = PSA_CRYPTO_LOCAL_INPUT_INIT; \ + const uint8_t *input_copy_name = NULL; + +/* Allocate a copy of the buffer input and set the pointer input_copy to + * point to the start of the copy. + * + * Assumptions: + * - psa_status_t status exists + * - An exit label is declared + * - input is the name of a pointer to the buffer to be copied + * - LOCAL_INPUT_DECLARE(input, input_copy) has previously been called + */ +#define LOCAL_INPUT_ALLOC(input, length, input_copy) \ + status = psa_crypto_local_input_alloc(input, length, \ + &LOCAL_INPUT_COPY_OF_##input); \ + if (status != PSA_SUCCESS) { \ + goto exit; \ + } \ + input_copy = LOCAL_INPUT_COPY_OF_##input.buffer; + +/* Free the local input copy allocated previously by LOCAL_INPUT_ALLOC() + * + * Assumptions: + * - input_copy is the name of the input copy pointer set by LOCAL_INPUT_ALLOC() + * - input is the name of the original buffer that was copied + */ +#define LOCAL_INPUT_FREE(input, input_copy) \ + input_copy = NULL; \ + psa_crypto_local_input_free(&LOCAL_INPUT_COPY_OF_##input); + +/* Declare a local copy of an output buffer and a variable that will be used + * to store a pointer to the start of the buffer. + * + * Note: This macro must be called before any operations which may jump to + * the exit label, so that the local output copy object is safe to be freed. + * + * Assumptions: + * - output is the name of a pointer to the buffer to be copied + * - The name LOCAL_OUTPUT_COPY_OF_output is unused in the current scope + * - output_copy_name is a name that is unused in the current scope + */ +#define LOCAL_OUTPUT_DECLARE(output, output_copy_name) \ + psa_crypto_local_output_t LOCAL_OUTPUT_COPY_OF_##output = PSA_CRYPTO_LOCAL_OUTPUT_INIT; \ + uint8_t *output_copy_name = NULL; + +/* Allocate a copy of the buffer output and set the pointer output_copy to + * point to the start of the copy. + * + * Assumptions: + * - psa_status_t status exists + * - An exit label is declared + * - output is the name of a pointer to the buffer to be copied + * - LOCAL_OUTPUT_DECLARE(output, output_copy) has previously been called + */ +#define LOCAL_OUTPUT_ALLOC(output, length, output_copy) \ + status = psa_crypto_local_output_alloc(output, length, \ + &LOCAL_OUTPUT_COPY_OF_##output); \ + if (status != PSA_SUCCESS) { \ + goto exit; \ + } \ + output_copy = LOCAL_OUTPUT_COPY_OF_##output.buffer; + +/* Free the local output copy allocated previously by LOCAL_OUTPUT_ALLOC() + * after first copying back its contents to the original buffer. + * + * Assumptions: + * - psa_status_t status exists + * - output_copy is the name of the output copy pointer set by LOCAL_OUTPUT_ALLOC() + * - output is the name of the original buffer that was copied + */ +#define LOCAL_OUTPUT_FREE(output, output_copy) \ + output_copy = NULL; \ + do { \ + psa_status_t local_output_status; \ + local_output_status = psa_crypto_local_output_free(&LOCAL_OUTPUT_COPY_OF_##output); \ + if (local_output_status != PSA_SUCCESS) { \ + /* Since this error case is an internal error, it's more serious than \ + * any existing error code and so it's fine to overwrite the existing \ + * status. */ \ + status = local_output_status; \ + } \ + } while (0) +#else /* !MBEDTLS_PSA_ASSUME_EXCLUSIVE_BUFFERS */ +#define LOCAL_INPUT_DECLARE(input, input_copy_name) \ + const uint8_t *input_copy_name = NULL; +#define LOCAL_INPUT_ALLOC(input, length, input_copy) \ + input_copy = input; +#define LOCAL_INPUT_FREE(input, input_copy) \ + input_copy = NULL; +#define LOCAL_OUTPUT_DECLARE(output, output_copy_name) \ + uint8_t *output_copy_name = NULL; +#define LOCAL_OUTPUT_ALLOC(output, length, output_copy) \ + output_copy = output; +#define LOCAL_OUTPUT_FREE(output, output_copy) \ + output_copy = NULL; +#endif /* !MBEDTLS_PSA_ASSUME_EXCLUSIVE_BUFFERS */ + + +int psa_can_do_hash(psa_algorithm_t hash_alg) +{ + (void) hash_alg; + return psa_get_drivers_initialized(); +} + +int psa_can_do_cipher(psa_key_type_t key_type, psa_algorithm_t cipher_alg) +{ + (void) key_type; + (void) cipher_alg; + return psa_get_drivers_initialized(); +} + + +#if defined(MBEDTLS_PSA_BUILTIN_KEY_TYPE_DH_KEY_PAIR_IMPORT) || \ + defined(MBEDTLS_PSA_BUILTIN_KEY_TYPE_DH_PUBLIC_KEY) || \ + defined(PSA_WANT_KEY_TYPE_DH_KEY_PAIR_GENERATE) +static int psa_is_dh_key_size_valid(size_t bits) +{ + switch (bits) { +#if defined(PSA_WANT_DH_RFC7919_2048) + case 2048: + return 1; +#endif /* PSA_WANT_DH_RFC7919_2048 */ +#if defined(PSA_WANT_DH_RFC7919_3072) + case 3072: + return 1; +#endif /* PSA_WANT_DH_RFC7919_3072 */ +#if defined(PSA_WANT_DH_RFC7919_4096) + case 4096: + return 1; +#endif /* PSA_WANT_DH_RFC7919_4096 */ +#if defined(PSA_WANT_DH_RFC7919_6144) + case 6144: + return 1; +#endif /* PSA_WANT_DH_RFC7919_6144 */ +#if defined(PSA_WANT_DH_RFC7919_8192) + case 8192: + return 1; +#endif /* PSA_WANT_DH_RFC7919_8192 */ + default: + return 0; + } +} +#endif /* MBEDTLS_PSA_BUILTIN_KEY_TYPE_DH_KEY_PAIR_IMPORT || + MBEDTLS_PSA_BUILTIN_KEY_TYPE_DH_PUBLIC_KEY || + PSA_WANT_KEY_TYPE_DH_KEY_PAIR_GENERATE */ + psa_status_t mbedtls_to_psa_error(int ret) { /* Mbed TLS error codes can combine a high-level error code and a @@ -128,16 +339,15 @@ psa_status_t mbedtls_to_psa_error(int ret) case 0: return PSA_SUCCESS; +#if defined(MBEDTLS_AES_C) case MBEDTLS_ERR_AES_INVALID_KEY_LENGTH: case MBEDTLS_ERR_AES_INVALID_INPUT_LENGTH: - case MBEDTLS_ERR_AES_FEATURE_UNAVAILABLE: return PSA_ERROR_NOT_SUPPORTED; - case MBEDTLS_ERR_AES_HW_ACCEL_FAILED: - return PSA_ERROR_HARDWARE_FAILURE; - - case MBEDTLS_ERR_ARC4_HW_ACCEL_FAILED: - return PSA_ERROR_HARDWARE_FAILURE; + case MBEDTLS_ERR_AES_BAD_INPUT_DATA: + return PSA_ERROR_INVALID_ARGUMENT; +#endif +#if defined(MBEDTLS_ASN1_PARSE_C) || defined(MBEDTLS_ASN1_WRITE_C) case MBEDTLS_ERR_ASN1_OUT_OF_DATA: case MBEDTLS_ERR_ASN1_UNEXPECTED_TAG: case MBEDTLS_ERR_ASN1_INVALID_LENGTH: @@ -148,42 +358,34 @@ psa_status_t mbedtls_to_psa_error(int ret) return PSA_ERROR_INSUFFICIENT_MEMORY; case MBEDTLS_ERR_ASN1_BUF_TOO_SMALL: return PSA_ERROR_BUFFER_TOO_SMALL; - -#if defined(MBEDTLS_ERR_BLOWFISH_BAD_INPUT_DATA) - case MBEDTLS_ERR_BLOWFISH_BAD_INPUT_DATA: -#elif defined(MBEDTLS_ERR_BLOWFISH_INVALID_KEY_LENGTH) - case MBEDTLS_ERR_BLOWFISH_INVALID_KEY_LENGTH: #endif - case MBEDTLS_ERR_BLOWFISH_INVALID_INPUT_LENGTH: - return PSA_ERROR_NOT_SUPPORTED; - case MBEDTLS_ERR_BLOWFISH_HW_ACCEL_FAILED: - return PSA_ERROR_HARDWARE_FAILURE; -#if defined(MBEDTLS_ERR_CAMELLIA_BAD_INPUT_DATA) +#if defined(MBEDTLS_CAMELLIA_C) case MBEDTLS_ERR_CAMELLIA_BAD_INPUT_DATA: -#elif defined(MBEDTLS_ERR_CAMELLIA_INVALID_KEY_LENGTH) - case MBEDTLS_ERR_CAMELLIA_INVALID_KEY_LENGTH: -#endif case MBEDTLS_ERR_CAMELLIA_INVALID_INPUT_LENGTH: return PSA_ERROR_NOT_SUPPORTED; - case MBEDTLS_ERR_CAMELLIA_HW_ACCEL_FAILED: - return PSA_ERROR_HARDWARE_FAILURE; +#endif +#if defined(MBEDTLS_CCM_C) case MBEDTLS_ERR_CCM_BAD_INPUT: return PSA_ERROR_INVALID_ARGUMENT; case MBEDTLS_ERR_CCM_AUTH_FAILED: return PSA_ERROR_INVALID_SIGNATURE; - case MBEDTLS_ERR_CCM_HW_ACCEL_FAILED: - return PSA_ERROR_HARDWARE_FAILURE; +#endif +#if defined(MBEDTLS_CHACHA20_C) case MBEDTLS_ERR_CHACHA20_BAD_INPUT_DATA: return PSA_ERROR_INVALID_ARGUMENT; +#endif +#if defined(MBEDTLS_CHACHAPOLY_C) case MBEDTLS_ERR_CHACHAPOLY_BAD_STATE: return PSA_ERROR_BAD_STATE; case MBEDTLS_ERR_CHACHAPOLY_AUTH_FAILED: return PSA_ERROR_INVALID_SIGNATURE; +#endif +#if defined(MBEDTLS_CIPHER_C) case MBEDTLS_ERR_CIPHER_FEATURE_UNAVAILABLE: return PSA_ERROR_NOT_SUPPORTED; case MBEDTLS_ERR_CIPHER_BAD_INPUT_DATA: @@ -198,11 +400,7 @@ psa_status_t mbedtls_to_psa_error(int ret) return PSA_ERROR_INVALID_SIGNATURE; case MBEDTLS_ERR_CIPHER_INVALID_CONTEXT: return PSA_ERROR_CORRUPTION_DETECTED; - case MBEDTLS_ERR_CIPHER_HW_ACCEL_FAILED: - return PSA_ERROR_HARDWARE_FAILURE; - - case MBEDTLS_ERR_CMAC_HW_ACCEL_FAILED: - return PSA_ERROR_HARDWARE_FAILURE; +#endif #if !(defined(MBEDTLS_PSA_CRYPTO_EXTERNAL_RNG) || \ defined(MBEDTLS_PSA_HMAC_DRBG_MD_TYPE)) @@ -217,22 +415,24 @@ psa_status_t mbedtls_to_psa_error(int ret) return PSA_ERROR_INSUFFICIENT_ENTROPY; #endif +#if defined(MBEDTLS_DES_C) case MBEDTLS_ERR_DES_INVALID_INPUT_LENGTH: return PSA_ERROR_NOT_SUPPORTED; - case MBEDTLS_ERR_DES_HW_ACCEL_FAILED: - return PSA_ERROR_HARDWARE_FAILURE; +#endif case MBEDTLS_ERR_ENTROPY_NO_SOURCES_DEFINED: case MBEDTLS_ERR_ENTROPY_NO_STRONG_SOURCE: case MBEDTLS_ERR_ENTROPY_SOURCE_FAILED: return PSA_ERROR_INSUFFICIENT_ENTROPY; +#if defined(MBEDTLS_GCM_C) case MBEDTLS_ERR_GCM_AUTH_FAILED: return PSA_ERROR_INVALID_SIGNATURE; + case MBEDTLS_ERR_GCM_BUFFER_TOO_SMALL: + return PSA_ERROR_BUFFER_TOO_SMALL; case MBEDTLS_ERR_GCM_BAD_INPUT: return PSA_ERROR_INVALID_ARGUMENT; - case MBEDTLS_ERR_GCM_HW_ACCEL_FAILED: - return PSA_ERROR_HARDWARE_FAILURE; +#endif #if !defined(MBEDTLS_PSA_CRYPTO_EXTERNAL_RNG) && \ defined(MBEDTLS_PSA_HMAC_DRBG_MD_TYPE) @@ -247,24 +447,24 @@ psa_status_t mbedtls_to_psa_error(int ret) return PSA_ERROR_INSUFFICIENT_ENTROPY; #endif - case MBEDTLS_ERR_MD2_HW_ACCEL_FAILED: - case MBEDTLS_ERR_MD4_HW_ACCEL_FAILED: - case MBEDTLS_ERR_MD5_HW_ACCEL_FAILED: - return PSA_ERROR_HARDWARE_FAILURE; - +#if defined(MBEDTLS_MD_LIGHT) case MBEDTLS_ERR_MD_FEATURE_UNAVAILABLE: return PSA_ERROR_NOT_SUPPORTED; case MBEDTLS_ERR_MD_BAD_INPUT_DATA: return PSA_ERROR_INVALID_ARGUMENT; case MBEDTLS_ERR_MD_ALLOC_FAILED: return PSA_ERROR_INSUFFICIENT_MEMORY; +#if defined(MBEDTLS_FS_IO) case MBEDTLS_ERR_MD_FILE_IO_ERROR: return PSA_ERROR_STORAGE_FAILURE; - case MBEDTLS_ERR_MD_HW_ACCEL_FAILED: - return PSA_ERROR_HARDWARE_FAILURE; +#endif +#endif +#if defined(MBEDTLS_BIGNUM_C) +#if defined(MBEDTLS_FS_IO) case MBEDTLS_ERR_MPI_FILE_IO_ERROR: return PSA_ERROR_STORAGE_FAILURE; +#endif case MBEDTLS_ERR_MPI_BAD_INPUT_DATA: return PSA_ERROR_INVALID_ARGUMENT; case MBEDTLS_ERR_MPI_INVALID_CHARACTER: @@ -279,14 +479,19 @@ psa_status_t mbedtls_to_psa_error(int ret) return PSA_ERROR_INVALID_ARGUMENT; case MBEDTLS_ERR_MPI_ALLOC_FAILED: return PSA_ERROR_INSUFFICIENT_MEMORY; +#endif +#if defined(MBEDTLS_PK_C) case MBEDTLS_ERR_PK_ALLOC_FAILED: return PSA_ERROR_INSUFFICIENT_MEMORY; case MBEDTLS_ERR_PK_TYPE_MISMATCH: case MBEDTLS_ERR_PK_BAD_INPUT_DATA: return PSA_ERROR_INVALID_ARGUMENT; +#if defined(MBEDTLS_PSA_CRYPTO_STORAGE_C) || defined(MBEDTLS_FS_IO) || \ + defined(MBEDTLS_PSA_ITS_FILE_C) case MBEDTLS_ERR_PK_FILE_IO_ERROR: return PSA_ERROR_STORAGE_FAILURE; +#endif case MBEDTLS_ERR_PK_KEY_INVALID_VERSION: case MBEDTLS_ERR_PK_KEY_INVALID_FORMAT: return PSA_ERROR_INVALID_ARGUMENT; @@ -303,17 +508,16 @@ psa_status_t mbedtls_to_psa_error(int ret) return PSA_ERROR_NOT_SUPPORTED; case MBEDTLS_ERR_PK_SIG_LEN_MISMATCH: return PSA_ERROR_INVALID_SIGNATURE; - case MBEDTLS_ERR_PK_HW_ACCEL_FAILED: - return PSA_ERROR_HARDWARE_FAILURE; + case MBEDTLS_ERR_PK_BUFFER_TOO_SMALL: + return PSA_ERROR_BUFFER_TOO_SMALL; +#endif case MBEDTLS_ERR_PLATFORM_HW_ACCEL_FAILED: return PSA_ERROR_HARDWARE_FAILURE; case MBEDTLS_ERR_PLATFORM_FEATURE_UNSUPPORTED: return PSA_ERROR_NOT_SUPPORTED; - case MBEDTLS_ERR_RIPEMD160_HW_ACCEL_FAILED: - return PSA_ERROR_HARDWARE_FAILURE; - +#if defined(MBEDTLS_RSA_C) case MBEDTLS_ERR_RSA_BAD_INPUT_DATA: return PSA_ERROR_INVALID_ARGUMENT; case MBEDTLS_ERR_RSA_INVALID_PADDING: @@ -331,21 +535,9 @@ psa_status_t mbedtls_to_psa_error(int ret) return PSA_ERROR_BUFFER_TOO_SMALL; case MBEDTLS_ERR_RSA_RNG_FAILED: return PSA_ERROR_INSUFFICIENT_ENTROPY; - case MBEDTLS_ERR_RSA_UNSUPPORTED_OPERATION: - return PSA_ERROR_NOT_SUPPORTED; - case MBEDTLS_ERR_RSA_HW_ACCEL_FAILED: - return PSA_ERROR_HARDWARE_FAILURE; - - case MBEDTLS_ERR_SHA1_HW_ACCEL_FAILED: - case MBEDTLS_ERR_SHA256_HW_ACCEL_FAILED: - case MBEDTLS_ERR_SHA512_HW_ACCEL_FAILED: - return PSA_ERROR_HARDWARE_FAILURE; - - case MBEDTLS_ERR_XTEA_INVALID_INPUT_LENGTH: - return PSA_ERROR_INVALID_ARGUMENT; - case MBEDTLS_ERR_XTEA_HW_ACCEL_FAILED: - return PSA_ERROR_HARDWARE_FAILURE; +#endif +#if defined(MBEDTLS_ECP_LIGHT) case MBEDTLS_ERR_ECP_BAD_INPUT_DATA: case MBEDTLS_ERR_ECP_INVALID_KEY: return PSA_ERROR_INVALID_ARGUMENT; @@ -360,8 +552,12 @@ psa_status_t mbedtls_to_psa_error(int ret) return PSA_ERROR_INSUFFICIENT_MEMORY; case MBEDTLS_ERR_ECP_RANDOM_FAILED: return PSA_ERROR_INSUFFICIENT_ENTROPY; - case MBEDTLS_ERR_ECP_HW_ACCEL_FAILED: - return PSA_ERROR_HARDWARE_FAILURE; + +#if defined(MBEDTLS_ECP_RESTARTABLE) + case MBEDTLS_ERR_ECP_IN_PROGRESS: + return PSA_OPERATION_INCOMPLETE; +#endif +#endif case MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED: return PSA_ERROR_CORRUPTION_DETECTED; @@ -371,123 +567,55 @@ psa_status_t mbedtls_to_psa_error(int ret) } } +/** + * \brief For output buffers which contain "tags" + * (outputs that may be checked for validity like + * hashes, MACs and signatures), fill the unused + * part of the output buffer (the whole buffer on + * error, the trailing part on success) with + * something that isn't a valid tag (barring an + * attack on the tag and deliberately-crafted + * input), in case the caller doesn't check the + * return status properly. + * + * \param output_buffer Pointer to buffer to wipe. May not be NULL + * unless \p output_buffer_size is zero. + * \param status Status of function called to generate + * output_buffer originally + * \param output_buffer_size Size of output buffer. If zero, \p output_buffer + * could be NULL. + * \param output_buffer_length Length of data written to output_buffer, must be + * less than \p output_buffer_size + */ +static void psa_wipe_tag_output_buffer(uint8_t *output_buffer, psa_status_t status, + size_t output_buffer_size, size_t output_buffer_length) +{ + size_t offset = 0; + if (output_buffer_size == 0) { + /* If output_buffer_size is 0 then we have nothing to do. We must not + call memset because output_buffer may be NULL in this case */ + return; + } - -/****************************************************************/ -/* Key management */ -/****************************************************************/ - -#if defined(MBEDTLS_PSA_BUILTIN_KEY_TYPE_ECC_KEY_PAIR) || \ - defined(MBEDTLS_PSA_BUILTIN_KEY_TYPE_ECC_PUBLIC_KEY) || \ - defined(MBEDTLS_PSA_BUILTIN_ALG_ECDSA) || \ - defined(MBEDTLS_PSA_BUILTIN_ALG_DETERMINISTIC_ECDSA) || \ - defined(MBEDTLS_PSA_BUILTIN_ALG_ECDH) -mbedtls_ecp_group_id mbedtls_ecc_group_of_psa(psa_ecc_family_t curve, - size_t bits, - int bits_is_sloppy) -{ - switch (curve) { - case PSA_ECC_FAMILY_SECP_R1: - switch (bits) { -#if defined(PSA_WANT_ECC_SECP_R1_192) - case 192: - return MBEDTLS_ECP_DP_SECP192R1; -#endif -#if defined(PSA_WANT_ECC_SECP_R1_224) - case 224: - return MBEDTLS_ECP_DP_SECP224R1; -#endif -#if defined(PSA_WANT_ECC_SECP_R1_256) - case 256: - return MBEDTLS_ECP_DP_SECP256R1; -#endif -#if defined(PSA_WANT_ECC_SECP_R1_384) - case 384: - return MBEDTLS_ECP_DP_SECP384R1; -#endif -#if defined(PSA_WANT_ECC_SECP_R1_521) - case 521: - return MBEDTLS_ECP_DP_SECP521R1; - case 528: - if (bits_is_sloppy) { - return MBEDTLS_ECP_DP_SECP521R1; - } - break; -#endif - } - break; - - case PSA_ECC_FAMILY_BRAINPOOL_P_R1: - switch (bits) { -#if defined(PSA_WANT_ECC_BRAINPOOL_P_R1_256) - case 256: - return MBEDTLS_ECP_DP_BP256R1; -#endif -#if defined(PSA_WANT_ECC_BRAINPOOL_P_R1_384) - case 384: - return MBEDTLS_ECP_DP_BP384R1; -#endif -#if defined(PSA_WANT_ECC_BRAINPOOL_P_R1_512) - case 512: - return MBEDTLS_ECP_DP_BP512R1; -#endif - } - break; - - case PSA_ECC_FAMILY_MONTGOMERY: - switch (bits) { -#if defined(PSA_WANT_ECC_MONTGOMERY_255) - case 255: - return MBEDTLS_ECP_DP_CURVE25519; - case 256: - if (bits_is_sloppy) { - return MBEDTLS_ECP_DP_CURVE25519; - } - break; -#endif -#if defined(PSA_WANT_ECC_MONTGOMERY_448) - case 448: - return MBEDTLS_ECP_DP_CURVE448; -#endif - } - break; - - case PSA_ECC_FAMILY_SECP_K1: - switch (bits) { -#if defined(PSA_WANT_ECC_SECP_K1_192) - case 192: - return MBEDTLS_ECP_DP_SECP192K1; -#endif -#if defined(PSA_WANT_ECC_SECP_K1_224) - case 224: - return MBEDTLS_ECP_DP_SECP224K1; -#endif -#if defined(PSA_WANT_ECC_SECP_K1_256) - case 256: - return MBEDTLS_ECP_DP_SECP256K1; -#endif - } - break; + if (status == PSA_SUCCESS) { + offset = output_buffer_length; } - (void) bits_is_sloppy; - return MBEDTLS_ECP_DP_NONE; + memset(output_buffer + offset, '!', output_buffer_size - offset); } -#endif /* defined(MBEDTLS_PSA_BUILTIN_KEY_TYPE_ECC_KEY_PAIR) || - defined(MBEDTLS_PSA_BUILTIN_KEY_TYPE_ECC_PUBLIC_KEY) || - defined(MBEDTLS_PSA_BUILTIN_ALG_ECDSA) || - defined(MBEDTLS_PSA_BUILTIN_ALG_DETERMINISTIC_ECDSA) || - defined(MBEDTLS_PSA_BUILTIN_ALG_ECDH) */ -static psa_status_t validate_unstructured_key_bit_size(psa_key_type_t type, - size_t bits) + +psa_status_t psa_validate_unstructured_key_bit_size(psa_key_type_t type, + size_t bits) { /* Check that the bit size is acceptable for the key type */ switch (type) { case PSA_KEY_TYPE_RAW_DATA: case PSA_KEY_TYPE_HMAC: case PSA_KEY_TYPE_DERIVE: + case PSA_KEY_TYPE_PASSWORD: + case PSA_KEY_TYPE_PASSWORD_HASH: break; #if defined(PSA_WANT_KEY_TYPE_AES) case PSA_KEY_TYPE_AES: @@ -517,13 +645,6 @@ static psa_status_t validate_unstructured_key_bit_size(psa_key_type_t type, } break; #endif -#if defined(PSA_WANT_KEY_TYPE_ARC4) - case PSA_KEY_TYPE_ARC4: - if (bits < 8 || bits > 2048) { - return PSA_ERROR_INVALID_ARGUMENT; - } - break; -#endif #if defined(PSA_WANT_KEY_TYPE_CHACHA20) case PSA_KEY_TYPE_CHACHA20: if (bits != 256) { @@ -618,7 +739,7 @@ psa_status_t psa_import_key_into_slot( size_t *key_buffer_length, size_t *bits) { psa_status_t status = PSA_ERROR_CORRUPTION_DETECTED; - psa_key_type_t type = attributes->core.type; + psa_key_type_t type = attributes->type; /* zero-length keys are never supported. */ if (data_length == 0) { @@ -628,18 +749,8 @@ psa_status_t psa_import_key_into_slot( if (key_type_is_raw_bytes(type)) { *bits = PSA_BYTES_TO_BITS(data_length); - /* Ensure that the bytes-to-bits conversion hasn't overflown. */ - if (data_length > SIZE_MAX / 8) { - return PSA_ERROR_NOT_SUPPORTED; - } - - /* Enforce a size limit, and in particular ensure that the bit - * size fits in its representation type. */ - if ((*bits) > PSA_MAX_KEY_BITS) { - return PSA_ERROR_NOT_SUPPORTED; - } - - status = validate_unstructured_key_bit_size(type, *bits); + status = psa_validate_unstructured_key_bit_size(attributes->type, + *bits); if (status != PSA_SUCCESS) { return status; } @@ -651,7 +762,21 @@ psa_status_t psa_import_key_into_slot( return PSA_SUCCESS; } else if (PSA_KEY_TYPE_IS_ASYMMETRIC(type)) { -#if defined(MBEDTLS_PSA_BUILTIN_KEY_TYPE_ECC_KEY_PAIR) || \ +#if defined(MBEDTLS_PSA_BUILTIN_KEY_TYPE_DH_KEY_PAIR_IMPORT) || \ + defined(MBEDTLS_PSA_BUILTIN_KEY_TYPE_DH_PUBLIC_KEY) + if (PSA_KEY_TYPE_IS_DH(type)) { + if (psa_is_dh_key_size_valid(PSA_BYTES_TO_BITS(data_length)) == 0) { + return PSA_ERROR_NOT_SUPPORTED; + } + return mbedtls_psa_ffdh_import_key(attributes, + data, data_length, + key_buffer, key_buffer_size, + key_buffer_length, + bits); + } +#endif /* defined(MBEDTLS_PSA_BUILTIN_KEY_TYPE_DH_KEY_PAIR_IMPORT) || + * defined(MBEDTLS_PSA_BUILTIN_KEY_TYPE_DH_PUBLIC_KEY) */ +#if defined(MBEDTLS_PSA_BUILTIN_KEY_TYPE_ECC_KEY_PAIR_IMPORT) || \ defined(MBEDTLS_PSA_BUILTIN_KEY_TYPE_ECC_PUBLIC_KEY) if (PSA_KEY_TYPE_IS_ECC(type)) { return mbedtls_psa_ecp_import_key(attributes, @@ -660,9 +785,10 @@ psa_status_t psa_import_key_into_slot( key_buffer_length, bits); } -#endif /* defined(MBEDTLS_PSA_BUILTIN_KEY_TYPE_ECC_KEY_PAIR) || +#endif /* defined(MBEDTLS_PSA_BUILTIN_KEY_TYPE_ECC_KEY_PAIR_IMPORT) || * defined(MBEDTLS_PSA_BUILTIN_KEY_TYPE_ECC_PUBLIC_KEY) */ -#if defined(MBEDTLS_PSA_BUILTIN_KEY_TYPE_RSA_KEY_PAIR) || \ +#if (defined(MBEDTLS_PSA_BUILTIN_KEY_TYPE_RSA_KEY_PAIR_IMPORT) && \ + defined(MBEDTLS_PSA_BUILTIN_KEY_TYPE_RSA_KEY_PAIR_EXPORT)) || \ defined(MBEDTLS_PSA_BUILTIN_KEY_TYPE_RSA_PUBLIC_KEY) if (PSA_KEY_TYPE_IS_RSA(type)) { return mbedtls_psa_rsa_import_key(attributes, @@ -671,7 +797,8 @@ psa_status_t psa_import_key_into_slot( key_buffer_length, bits); } -#endif /* defined(MBEDTLS_PSA_BUILTIN_KEY_TYPE_RSA_KEY_PAIR) || +#endif /* (defined(MBEDTLS_PSA_BUILTIN_KEY_TYPE_RSA_KEY_PAIR_IMPORT) && + defined(MBEDTLS_PSA_BUILTIN_KEY_TYPE_RSA_KEY_PAIR_EXPORT)) || * defined(MBEDTLS_PSA_BUILTIN_KEY_TYPE_RSA_PUBLIC_KEY) */ } @@ -952,8 +1079,14 @@ static psa_status_t psa_restrict_key_policy( * In case of a persistent key, the function loads the description of the key * into a key slot if not already done. * - * On success, the returned key slot is locked. It is the responsibility of - * the caller to unlock the key slot when it does not access it anymore. + * On success, the returned key slot has been registered for reading. + * It is the responsibility of the caller to then unregister + * once they have finished reading the contents of the slot. + * The caller unregisters by calling psa_unregister_read() or + * psa_unregister_read_under_mutex(). psa_unregister_read() must be called + * if and only if the caller already holds the global key slot mutex + * (when mutexes are enabled). psa_unregister_read_under_mutex() encapsulates + * the unregister with mutex lock and unlock operations. */ static psa_status_t psa_get_and_lock_key_slot_with_policy( mbedtls_svc_key_id_t key, @@ -962,7 +1095,7 @@ static psa_status_t psa_get_and_lock_key_slot_with_policy( psa_algorithm_t alg) { psa_status_t status = PSA_ERROR_CORRUPTION_DETECTED; - psa_key_slot_t *slot; + psa_key_slot_t *slot = NULL; status = psa_get_and_lock_key_slot(key, p_slot); if (status != PSA_SUCCESS) { @@ -997,7 +1130,7 @@ static psa_status_t psa_get_and_lock_key_slot_with_policy( error: *p_slot = NULL; - psa_unlock_key_slot(slot); + psa_unregister_read_under_mutex(slot); return status; } @@ -1012,8 +1145,14 @@ static psa_status_t psa_get_and_lock_key_slot_with_policy( * psa_get_and_lock_key_slot_with_policy() when there is no opaque key support * for a cryptographic operation. * - * On success, the returned key slot is locked. It is the responsibility of the - * caller to unlock the key slot when it does not access it anymore. + * On success, the returned key slot has been registered for reading. + * It is the responsibility of the caller to then unregister + * once they have finished reading the contents of the slot. + * The caller unregisters by calling psa_unregister_read() or + * psa_unregister_read_under_mutex(). psa_unregister_read() must be called + * if and only if the caller already holds the global key slot mutex + * (when mutexes are enabled). psa_unregister_read_under_mutex() encapsulates + * psa_unregister_read() with mutex lock and unlock operations. */ static psa_status_t psa_get_and_lock_transparent_key_slot_with_policy( mbedtls_svc_key_id_t key, @@ -1028,7 +1167,7 @@ static psa_status_t psa_get_and_lock_transparent_key_slot_with_policy( } if (psa_key_lifetime_is_external((*p_slot)->attr.lifetime)) { - psa_unlock_key_slot(*p_slot); + psa_unregister_read_under_mutex(*p_slot); *p_slot = NULL; return PSA_ERROR_NOT_SUPPORTED; } @@ -1038,13 +1177,10 @@ static psa_status_t psa_get_and_lock_transparent_key_slot_with_policy( psa_status_t psa_remove_key_data_from_memory(psa_key_slot_t *slot) { - /* Data pointer will always be either a valid pointer or NULL in an - * initialized slot, so we can just free it. */ if (slot->key.data != NULL) { - mbedtls_platform_zeroize(slot->key.data, slot->key.bytes); + mbedtls_zeroize_and_free(slot->key.data, slot->key.bytes); } - mbedtls_free(slot->key.data); slot->key.data = NULL; slot->key.bytes = 0; @@ -1059,16 +1195,41 @@ psa_status_t psa_wipe_key_slot(psa_key_slot_t *slot) /* * As the return error code may not be handled in case of multiple errors, - * do our best to report an unexpected lock counter: if available - * call MBEDTLS_PARAM_FAILED that may terminate execution (if called as - * part of the execution of a test suite this will stop the test suite - * execution). + * do our best to report an unexpected amount of registered readers or + * an unexpected state. + * Assert with MBEDTLS_TEST_HOOK_TEST_ASSERT that the slot is valid for + * wiping. + * if the MBEDTLS_TEST_HOOKS configuration option is enabled and the + * function is called as part of the execution of a test suite, the + * execution of the test suite is stopped in error if the assertion fails. */ - if (slot->lock_count != 1) { -#ifdef MBEDTLS_CHECK_PARAMS - MBEDTLS_PARAM_FAILED(slot->lock_count == 1); -#endif - status = PSA_ERROR_CORRUPTION_DETECTED; + switch (slot->state) { + case PSA_SLOT_FULL: + /* In this state psa_wipe_key_slot() must only be called if the + * caller is the last reader. */ + case PSA_SLOT_PENDING_DELETION: + /* In this state psa_wipe_key_slot() must only be called if the + * caller is the last reader. */ + if (slot->registered_readers != 1) { + MBEDTLS_TEST_HOOK_TEST_ASSERT(slot->registered_readers == 1); + status = PSA_ERROR_CORRUPTION_DETECTED; + } + break; + case PSA_SLOT_FILLING: + /* In this state registered_readers must be 0. */ + if (slot->registered_readers != 0) { + MBEDTLS_TEST_HOOK_TEST_ASSERT(slot->registered_readers == 0); + status = PSA_ERROR_CORRUPTION_DETECTED; + } + break; + case PSA_SLOT_EMPTY: + /* The slot is already empty, it cannot be wiped. */ + MBEDTLS_TEST_HOOK_TEST_ASSERT(slot->state != PSA_SLOT_EMPTY); + status = PSA_ERROR_CORRUPTION_DETECTED; + break; + default: + /* The slot's state is invalid. */ + status = PSA_ERROR_CORRUPTION_DETECTED; } /* Multipart operations may still be using the key. This is safe @@ -1078,7 +1239,8 @@ psa_status_t psa_wipe_key_slot(psa_key_slot_t *slot) * key material can linger until all operations are completed. */ /* At this point, key material and other type-specific content has * been wiped. Clear remaining metadata. We can call memset and not - * zeroize because the metadata is not particularly sensitive. */ + * zeroize because the metadata is not particularly sensitive. + * This memset also sets the slot's state to PSA_SLOT_EMPTY. */ memset(slot, 0, sizeof(*slot)); return status; } @@ -1097,27 +1259,49 @@ psa_status_t psa_destroy_key(mbedtls_svc_key_id_t key) } /* - * Get the description of the key in a key slot. In case of a persistent - * key, this will load the key description from persistent memory if not - * done yet. We cannot avoid this loading as without it we don't know if + * Get the description of the key in a key slot, and register to read it. + * In the case of a persistent key, this will load the key description + * from persistent memory if not done yet. + * We cannot avoid this loading as without it we don't know if * the key is operated by an SE or not and this information is needed by - * the current implementation. - */ + * the current implementation. */ status = psa_get_and_lock_key_slot(key, &slot); if (status != PSA_SUCCESS) { return status; } - /* - * If the key slot containing the key description is under access by the - * library (apart from the present access), the key cannot be destroyed - * yet. For the time being, just return in error. Eventually (to be - * implemented), the key should be destroyed when all accesses have - * stopped. - */ - if (slot->lock_count > 1) { - psa_unlock_key_slot(slot); - return PSA_ERROR_GENERIC_ERROR; +#if defined(MBEDTLS_THREADING_C) + /* We cannot unlock between setting the state to PENDING_DELETION + * and destroying the key in storage, as otherwise another thread + * could load the key into a new slot and the key will not be + * fully destroyed. */ + PSA_THREADING_CHK_GOTO_EXIT(mbedtls_mutex_lock( + &mbedtls_threading_key_slot_mutex)); + + if (slot->state == PSA_SLOT_PENDING_DELETION) { + /* Another thread has destroyed the key between us locking the slot + * and us gaining the mutex. Unregister from the slot, + * and report that the key does not exist. */ + status = psa_unregister_read(slot); + + PSA_THREADING_CHK_RET(mbedtls_mutex_unlock( + &mbedtls_threading_key_slot_mutex)); + return (status == PSA_SUCCESS) ? PSA_ERROR_INVALID_HANDLE : status; + } +#endif + /* Set the key slot containing the key description's state to + * PENDING_DELETION. This stops new operations from registering + * to read the slot. Current readers can safely continue to access + * the key within the slot; the last registered reader will + * automatically wipe the slot when they call psa_unregister_read(). + * If the key is persistent, we can now delete the copy of the key + * from memory. If the key is opaque, we require the driver to + * deal with the deletion. */ + overall_status = psa_key_slot_state_transition(slot, PSA_SLOT_FULL, + PSA_SLOT_PENDING_DELETION); + + if (overall_status != PSA_SUCCESS) { + goto exit; } if (PSA_KEY_LIFETIME_IS_READ_ONLY(slot->attr.lifetime)) { @@ -1166,15 +1350,13 @@ psa_status_t psa_destroy_key(mbedtls_svc_key_id_t key) #if defined(MBEDTLS_PSA_CRYPTO_STORAGE_C) if (!PSA_KEY_LIFETIME_IS_VOLATILE(slot->attr.lifetime)) { + /* Destroy the copy of the persistent key from storage. + * The slot will still hold a copy of the key until the last reader + * unregisters. */ status = psa_destroy_persistent_key(slot->attr.id); if (overall_status == PSA_SUCCESS) { overall_status = status; } - - /* TODO: other slots may have a copy of the same key. We should - * invalidate them. - * https://github.com/ARMmbed/mbed-crypto/issues/214 - */ } #endif /* defined(MBEDTLS_PSA_CRYPTO_STORAGE_C) */ @@ -1192,58 +1374,24 @@ psa_status_t psa_destroy_key(mbedtls_svc_key_id_t key) #endif /* MBEDTLS_PSA_CRYPTO_SE_C */ exit: - status = psa_wipe_key_slot(slot); - /* Prioritize CORRUPTION_DETECTED from wiping over a storage error */ + /* Unregister from reading the slot. If we are the last active reader + * then this will wipe the slot. */ + status = psa_unregister_read(slot); + /* Prioritize CORRUPTION_DETECTED from unregistering over + * a storage error. */ if (status != PSA_SUCCESS) { overall_status = status; } - return overall_status; -} - -#if defined(MBEDTLS_PSA_BUILTIN_KEY_TYPE_RSA_KEY_PAIR) || \ - defined(MBEDTLS_PSA_BUILTIN_KEY_TYPE_RSA_PUBLIC_KEY) -static psa_status_t psa_get_rsa_public_exponent( - const mbedtls_rsa_context *rsa, - psa_key_attributes_t *attributes) -{ - mbedtls_mpi mpi; - int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED; - uint8_t *buffer = NULL; - size_t buflen; - mbedtls_mpi_init(&mpi); - - ret = mbedtls_rsa_export(rsa, NULL, NULL, NULL, NULL, &mpi); - if (ret != 0) { - goto exit; - } - if (mbedtls_mpi_cmp_int(&mpi, 65537) == 0) { - /* It's the default value, which is reported as an empty string, - * so there's nothing to do. */ - goto exit; - } - buflen = mbedtls_mpi_size(&mpi); - buffer = mbedtls_calloc(1, buflen); - if (buffer == NULL) { - ret = MBEDTLS_ERR_MPI_ALLOC_FAILED; - goto exit; - } - ret = mbedtls_mpi_write_binary(&mpi, buffer, buflen); - if (ret != 0) { - goto exit; - } - attributes->domain_parameters = buffer; - attributes->domain_parameters_size = buflen; +#if defined(MBEDTLS_THREADING_C) + /* Don't overwrite existing errors if the unlock fails. */ + status = overall_status; + PSA_THREADING_CHK_RET(mbedtls_mutex_unlock( + &mbedtls_threading_key_slot_mutex)); +#endif -exit: - mbedtls_mpi_free(&mpi); - if (ret != 0) { - mbedtls_free(buffer); - } - return mbedtls_to_psa_error(ret); + return overall_status; } -#endif /* defined(MBEDTLS_PSA_BUILTIN_KEY_TYPE_RSA_KEY_PAIR) || - * defined(MBEDTLS_PSA_BUILTIN_KEY_TYPE_RSA_PUBLIC_KEY) */ /** Retrieve all the publicly-accessible attributes of a key. */ @@ -1251,7 +1399,6 @@ psa_status_t psa_get_key_attributes(mbedtls_svc_key_id_t key, psa_key_attributes_t *attributes) { psa_status_t status = PSA_ERROR_CORRUPTION_DETECTED; - psa_status_t unlock_status = PSA_ERROR_CORRUPTION_DETECTED; psa_key_slot_t *slot; psa_reset_key_attributes(attributes); @@ -1261,9 +1408,7 @@ psa_status_t psa_get_key_attributes(mbedtls_svc_key_id_t key, return status; } - attributes->core = slot->attr; - attributes->core.flags &= (MBEDTLS_PSA_KA_MASK_EXTERNAL_ONLY | - MBEDTLS_PSA_KA_MASK_DUAL_USE); + *attributes = slot->attr; #if defined(MBEDTLS_PSA_CRYPTO_SE_C) if (psa_get_se_driver_entry(slot->attr.lifetime) != NULL) { @@ -1272,47 +1417,7 @@ psa_status_t psa_get_key_attributes(mbedtls_svc_key_id_t key, } #endif /* MBEDTLS_PSA_CRYPTO_SE_C */ - switch (slot->attr.type) { -#if defined(MBEDTLS_PSA_BUILTIN_KEY_TYPE_RSA_KEY_PAIR) || \ - defined(MBEDTLS_PSA_BUILTIN_KEY_TYPE_RSA_PUBLIC_KEY) - case PSA_KEY_TYPE_RSA_KEY_PAIR: - case PSA_KEY_TYPE_RSA_PUBLIC_KEY: - /* TODO: reporting the public exponent for opaque keys - * is not yet implemented. - * https://github.com/ARMmbed/mbed-crypto/issues/216 - */ - if (!psa_key_lifetime_is_external(slot->attr.lifetime)) { - mbedtls_rsa_context *rsa = NULL; - - status = mbedtls_psa_rsa_load_representation( - slot->attr.type, - slot->key.data, - slot->key.bytes, - &rsa); - if (status != PSA_SUCCESS) { - break; - } - - status = psa_get_rsa_public_exponent(rsa, - attributes); - mbedtls_rsa_free(rsa); - mbedtls_free(rsa); - } - break; -#endif /* defined(MBEDTLS_PSA_BUILTIN_KEY_TYPE_RSA_KEY_PAIR) || - * defined(MBEDTLS_PSA_BUILTIN_KEY_TYPE_RSA_PUBLIC_KEY) */ - default: - /* Nothing else to do. */ - break; - } - - if (status != PSA_SUCCESS) { - psa_reset_key_attributes(attributes); - } - - unlock_status = psa_unlock_key_slot(slot); - - return (status == PSA_SUCCESS) ? unlock_status : status; + return psa_unregister_read_under_mutex(slot); } #if defined(MBEDTLS_PSA_CRYPTO_SE_C) @@ -1320,7 +1425,7 @@ psa_status_t psa_get_key_slot_number( const psa_key_attributes_t *attributes, psa_key_slot_number_t *slot_number) { - if (attributes->core.flags & MBEDTLS_PSA_KA_FLAG_HAS_SLOT_NUMBER) { + if (attributes->has_slot_number) { *slot_number = attributes->slot_number; return PSA_SUCCESS; } else { @@ -1350,11 +1455,12 @@ psa_status_t psa_export_key_internal( const uint8_t *key_buffer, size_t key_buffer_size, uint8_t *data, size_t data_size, size_t *data_length) { - psa_key_type_t type = attributes->core.type; + psa_key_type_t type = attributes->type; if (key_type_is_raw_bytes(type) || PSA_KEY_TYPE_IS_RSA(type) || - PSA_KEY_TYPE_IS_ECC(type)) { + PSA_KEY_TYPE_IS_ECC(type) || + PSA_KEY_TYPE_IS_DH(type)) { return psa_export_key_buffer_internal( key_buffer, key_buffer_size, data, data_size, data_length); @@ -1367,13 +1473,14 @@ psa_status_t psa_export_key_internal( } psa_status_t psa_export_key(mbedtls_svc_key_id_t key, - uint8_t *data, + uint8_t *data_external, size_t data_size, size_t *data_length) { psa_status_t status = PSA_ERROR_CORRUPTION_DETECTED; psa_status_t unlock_status = PSA_ERROR_CORRUPTION_DETECTED; psa_key_slot_t *slot; + LOCAL_OUTPUT_DECLARE(data_external, data); /* Reject a zero-length output buffer now, since this can never be a * valid key representation. This way we know that data must be a valid @@ -1398,15 +1505,18 @@ psa_status_t psa_export_key(mbedtls_svc_key_id_t key, return status; } - psa_key_attributes_t attributes = { - .core = slot->attr - }; - status = psa_driver_wrapper_export_key(&attributes, + LOCAL_OUTPUT_ALLOC(data_external, data_size, data); + + status = psa_driver_wrapper_export_key(&slot->attr, slot->key.data, slot->key.bytes, data, data_size, data_length); - unlock_status = psa_unlock_key_slot(slot); +#if !defined(MBEDTLS_PSA_ASSUME_EXCLUSIVE_BUFFERS) +exit: +#endif + unlock_status = psa_unregister_read_under_mutex(slot); + LOCAL_OUTPUT_FREE(data_external, data); return (status == PSA_SUCCESS) ? unlock_status : status; } @@ -1418,63 +1528,76 @@ psa_status_t psa_export_public_key_internal( size_t data_size, size_t *data_length) { - psa_key_type_t type = attributes->core.type; - - if (PSA_KEY_TYPE_IS_RSA(type) || PSA_KEY_TYPE_IS_ECC(type)) { - if (PSA_KEY_TYPE_IS_PUBLIC_KEY(type)) { - /* Exporting public -> public */ - return psa_export_key_buffer_internal( - key_buffer, key_buffer_size, - data, data_size, data_length); - } + psa_key_type_t type = attributes->type; - if (PSA_KEY_TYPE_IS_RSA(type)) { -#if defined(MBEDTLS_PSA_BUILTIN_KEY_TYPE_RSA_KEY_PAIR) || \ - defined(MBEDTLS_PSA_BUILTIN_KEY_TYPE_RSA_PUBLIC_KEY) - return mbedtls_psa_rsa_export_public_key(attributes, - key_buffer, - key_buffer_size, - data, - data_size, - data_length); + if (PSA_KEY_TYPE_IS_PUBLIC_KEY(type) && + (PSA_KEY_TYPE_IS_RSA(type) || PSA_KEY_TYPE_IS_ECC(type) || + PSA_KEY_TYPE_IS_DH(type))) { + /* Exporting public -> public */ + return psa_export_key_buffer_internal( + key_buffer, key_buffer_size, + data, data_size, data_length); + } else if (PSA_KEY_TYPE_IS_RSA(type)) { +#if defined(MBEDTLS_PSA_BUILTIN_KEY_TYPE_RSA_KEY_PAIR_EXPORT) || \ + defined(MBEDTLS_PSA_BUILTIN_KEY_TYPE_RSA_PUBLIC_KEY) + return mbedtls_psa_rsa_export_public_key(attributes, + key_buffer, + key_buffer_size, + data, + data_size, + data_length); #else - /* We don't know how to convert a private RSA key to public. */ - return PSA_ERROR_NOT_SUPPORTED; -#endif /* defined(MBEDTLS_PSA_BUILTIN_KEY_TYPE_RSA_KEY_PAIR) || + /* We don't know how to convert a private RSA key to public. */ + return PSA_ERROR_NOT_SUPPORTED; +#endif /* defined(MBEDTLS_PSA_BUILTIN_KEY_TYPE_RSA_KEY_PAIR_EXPORT) || * defined(MBEDTLS_PSA_BUILTIN_KEY_TYPE_RSA_PUBLIC_KEY) */ - } else { -#if defined(MBEDTLS_PSA_BUILTIN_KEY_TYPE_ECC_KEY_PAIR) || \ - defined(MBEDTLS_PSA_BUILTIN_KEY_TYPE_ECC_PUBLIC_KEY) - return mbedtls_psa_ecp_export_public_key(attributes, - key_buffer, - key_buffer_size, - data, - data_size, - data_length); + } else if (PSA_KEY_TYPE_IS_ECC(type)) { +#if defined(MBEDTLS_PSA_BUILTIN_KEY_TYPE_ECC_KEY_PAIR_EXPORT) || \ + defined(MBEDTLS_PSA_BUILTIN_KEY_TYPE_ECC_PUBLIC_KEY) + return mbedtls_psa_ecp_export_public_key(attributes, + key_buffer, + key_buffer_size, + data, + data_size, + data_length); #else - /* We don't know how to convert a private ECC key to public */ - return PSA_ERROR_NOT_SUPPORTED; -#endif /* defined(MBEDTLS_PSA_BUILTIN_KEY_TYPE_ECC_KEY_PAIR) || + /* We don't know how to convert a private ECC key to public */ + return PSA_ERROR_NOT_SUPPORTED; +#endif /* defined(MBEDTLS_PSA_BUILTIN_KEY_TYPE_ECC_KEY_PAIR_EXPORT) || * defined(MBEDTLS_PSA_BUILTIN_KEY_TYPE_ECC_PUBLIC_KEY) */ - } + } else if (PSA_KEY_TYPE_IS_DH(type)) { +#if defined(MBEDTLS_PSA_BUILTIN_KEY_TYPE_DH_KEY_PAIR_EXPORT) || \ + defined(MBEDTLS_PSA_BUILTIN_KEY_TYPE_DH_PUBLIC_KEY) + return mbedtls_psa_ffdh_export_public_key(attributes, + key_buffer, + key_buffer_size, + data, data_size, + data_length); +#else + return PSA_ERROR_NOT_SUPPORTED; +#endif /* defined(MBEDTLS_PSA_BUILTIN_KEY_TYPE_DH_KEY_PAIR_EXPORT) || + * defined(MBEDTLS_PSA_BUILTIN_KEY_TYPE_DH_PUBLIC_KEY) */ } else { - /* This shouldn't happen in the reference implementation, but - it is valid for a special-purpose implementation to omit - support for exporting certain key types. */ + (void) key_buffer; + (void) key_buffer_size; + (void) data; + (void) data_size; + (void) data_length; return PSA_ERROR_NOT_SUPPORTED; } } psa_status_t psa_export_public_key(mbedtls_svc_key_id_t key, - uint8_t *data, + uint8_t *data_external, size_t data_size, size_t *data_length) { psa_status_t status = PSA_ERROR_CORRUPTION_DETECTED; psa_status_t unlock_status = PSA_ERROR_CORRUPTION_DETECTED; - psa_key_attributes_t attributes; psa_key_slot_t *slot; + LOCAL_OUTPUT_DECLARE(data_external, data); + /* Reject a zero-length output buffer now, since this can never be a * valid key representation. This way we know that data must be a valid * pointer and we can do things like memset(data, ..., data_size). */ @@ -1494,31 +1617,24 @@ psa_status_t psa_export_public_key(mbedtls_svc_key_id_t key, return status; } + LOCAL_OUTPUT_ALLOC(data_external, data_size, data); + if (!PSA_KEY_TYPE_IS_ASYMMETRIC(slot->attr.type)) { status = PSA_ERROR_INVALID_ARGUMENT; goto exit; } - attributes = (psa_key_attributes_t) { - .core = slot->attr - }; status = psa_driver_wrapper_export_public_key( - &attributes, slot->key.data, slot->key.bytes, + &slot->attr, slot->key.data, slot->key.bytes, data, data_size, data_length); exit: - unlock_status = psa_unlock_key_slot(slot); + unlock_status = psa_unregister_read_under_mutex(slot); + LOCAL_OUTPUT_FREE(data_external, data); return (status == PSA_SUCCESS) ? unlock_status : status; } -MBEDTLS_STATIC_ASSERT((MBEDTLS_PSA_KA_MASK_EXTERNAL_ONLY & MBEDTLS_PSA_KA_MASK_DUAL_USE) == 0, - "One or more key attribute flag is listed as both external-only and dual-use") -MBEDTLS_STATIC_ASSERT((PSA_KA_MASK_INTERNAL_ONLY & MBEDTLS_PSA_KA_MASK_DUAL_USE) == 0, - "One or more key attribute flag is listed as both internal-only and dual-use") -MBEDTLS_STATIC_ASSERT((PSA_KA_MASK_INTERNAL_ONLY & MBEDTLS_PSA_KA_MASK_EXTERNAL_ONLY) == 0, - "One or more key attribute flag is listed as both internal-only and external-only") - /** Validate that a key policy is internally well-formed. * * This function only rejects invalid policies. It does not validate the @@ -1535,6 +1651,7 @@ static psa_status_t psa_validate_key_policy(const psa_key_policy_t *policy) PSA_KEY_USAGE_VERIFY_MESSAGE | PSA_KEY_USAGE_SIGN_HASH | PSA_KEY_USAGE_VERIFY_HASH | + PSA_KEY_USAGE_VERIFY_DERIVATION | PSA_KEY_USAGE_DERIVE)) != 0) { return PSA_ERROR_INVALID_ARGUMENT; } @@ -1583,7 +1700,7 @@ static psa_status_t psa_validate_key_attributes( } } - status = psa_validate_key_policy(&attributes->core.policy); + status = psa_validate_key_policy(&attributes->policy); if (status != PSA_SUCCESS) { return status; } @@ -1596,12 +1713,6 @@ static psa_status_t psa_validate_key_attributes( return PSA_ERROR_NOT_SUPPORTED; } - /* Reject invalid flags. These should not be reachable through the API. */ - if (attributes->core.flags & ~(MBEDTLS_PSA_KA_MASK_EXTERNAL_ONLY | - MBEDTLS_PSA_KA_MASK_DUAL_USE)) { - return PSA_ERROR_INVALID_ARGUMENT; - } - return PSA_SUCCESS; } @@ -1620,8 +1731,9 @@ static psa_status_t psa_validate_key_attributes( * In case of failure at any step, stop the sequence and call * psa_fail_key_creation(). * - * On success, the key slot is locked. It is the responsibility of the caller - * to unlock the key slot when it does not access it anymore. + * On success, the key slot's state is PSA_SLOT_FILLING. + * It is the responsibility of the caller to change the slot's state to + * PSA_SLOT_EMPTY/FULL once key creation has finished. * * \param method An identification of the calling function. * \param[in] attributes Key attributes for the new key. @@ -1652,7 +1764,15 @@ static psa_status_t psa_start_key_creation( return status; } - status = psa_get_empty_key_slot(&volatile_key_id, p_slot); +#if defined(MBEDTLS_THREADING_C) + PSA_THREADING_CHK_RET(mbedtls_mutex_lock( + &mbedtls_threading_key_slot_mutex)); +#endif + status = psa_reserve_free_key_slot(&volatile_key_id, p_slot); +#if defined(MBEDTLS_THREADING_C) + PSA_THREADING_CHK_RET(mbedtls_mutex_unlock( + &mbedtls_threading_key_slot_mutex)); +#endif if (status != PSA_SUCCESS) { return status; } @@ -1666,7 +1786,7 @@ static psa_status_t psa_start_key_creation( * volatile key identifier associated to the slot returned to contain its * definition. */ - slot->attr = attributes->core; + slot->attr = *attributes; if (PSA_KEY_LIFETIME_IS_VOLATILE(slot->attr.lifetime)) { #if !defined(MBEDTLS_PSA_CRYPTO_KEY_ID_ENCODES_OWNER) slot->attr.id = volatile_key_id; @@ -1675,13 +1795,6 @@ static psa_status_t psa_start_key_creation( #endif } - /* Erase external-only flags from the internal copy. To access - * external-only flags, query `attributes`. Thanks to the check - * in psa_validate_key_attributes(), this leaves the dual-use - * flags and any internal flag that psa_get_empty_key_slot() - * may have set. */ - slot->attr.flags &= ~MBEDTLS_PSA_KA_MASK_EXTERNAL_ONLY; - #if defined(MBEDTLS_PSA_CRYPTO_SE_C) /* For a key in a secure element, we need to do three things * when creating or registering a persistent key: @@ -1708,7 +1821,7 @@ static psa_status_t psa_start_key_creation( return status; } - if (!PSA_KEY_LIFETIME_IS_VOLATILE(attributes->core.lifetime)) { + if (!PSA_KEY_LIFETIME_IS_VOLATILE(attributes->lifetime)) { psa_crypto_prepare_transaction(PSA_CRYPTO_TRANSACTION_CREATE_KEY); psa_crypto_transaction.key.lifetime = slot->attr.lifetime; psa_crypto_transaction.key.slot = slot_number; @@ -1741,9 +1854,9 @@ static psa_status_t psa_start_key_creation( * See the documentation of psa_start_key_creation() for the intended use * of this function. * - * If the finalization succeeds, the function unlocks the key slot (it was - * locked by psa_start_key_creation()) and the key slot cannot be accessed - * anymore as part of the key creation process. + * If the finalization succeeds, the function sets the key slot's state to + * PSA_SLOT_FULL, and the key slot can no longer be accessed as part of the + * key creation process. * * \param[in,out] slot Pointer to the slot with key material. * \param[in] driver The secure element driver for the key, @@ -1772,6 +1885,11 @@ static psa_status_t psa_finish_key_creation( (void) slot; (void) driver; +#if defined(MBEDTLS_THREADING_C) + PSA_THREADING_CHK_RET(mbedtls_mutex_lock( + &mbedtls_threading_key_slot_mutex)); +#endif + #if defined(MBEDTLS_PSA_CRYPTO_STORAGE_C) if (!PSA_KEY_LIFETIME_IS_VOLATILE(slot->attr.lifetime)) { #if defined(MBEDTLS_PSA_CRYPTO_SE_C) @@ -1811,6 +1929,11 @@ static psa_status_t psa_finish_key_creation( status = psa_save_se_persistent_data(driver); if (status != PSA_SUCCESS) { psa_destroy_persistent_key(slot->attr.id); + +#if defined(MBEDTLS_THREADING_C) + PSA_THREADING_CHK_RET(mbedtls_mutex_unlock( + &mbedtls_threading_key_slot_mutex)); +#endif return status; } status = psa_crypto_stop_transaction(); @@ -1819,12 +1942,17 @@ static psa_status_t psa_finish_key_creation( if (status == PSA_SUCCESS) { *key = slot->attr.id; - status = psa_unlock_key_slot(slot); + status = psa_key_slot_state_transition(slot, PSA_SLOT_FILLING, + PSA_SLOT_FULL); if (status != PSA_SUCCESS) { *key = MBEDTLS_SVC_KEY_ID_INIT; } } +#if defined(MBEDTLS_THREADING_C) + PSA_THREADING_CHK_RET(mbedtls_mutex_unlock( + &mbedtls_threading_key_slot_mutex)); +#endif return status; } @@ -1834,7 +1962,7 @@ static psa_status_t psa_finish_key_creation( * or after psa_finish_key_creation() fails. In other circumstances, this * function may not clean up persistent storage. * See the documentation of psa_start_key_creation() for the intended use - * of this function. + * of this function. Sets the slot's state to PSA_SLOT_EMPTY. * * \param[in,out] slot Pointer to the slot with key material. * \param[in] driver The secure element driver for the key, @@ -1849,6 +1977,13 @@ static void psa_fail_key_creation(psa_key_slot_t *slot, return; } +#if defined(MBEDTLS_THREADING_C) + /* If the lock operation fails we still wipe the slot. + * Operations will no longer work after a failed lock, + * but we still need to wipe the slot of confidential data. */ + mbedtls_mutex_lock(&mbedtls_threading_key_slot_mutex); +#endif + #if defined(MBEDTLS_PSA_CRYPTO_SE_C) /* TODO: If the key has already been created in the secure * element, and the failure happened later (when saving metadata @@ -1867,6 +2002,10 @@ static void psa_fail_key_creation(psa_key_slot_t *slot, #endif /* MBEDTLS_PSA_CRYPTO_SE_C */ psa_wipe_key_slot(slot); + +#if defined(MBEDTLS_THREADING_C) + mbedtls_mutex_unlock(&mbedtls_threading_key_slot_mutex); +#endif } /** Validate optional attributes during key creation. @@ -1882,63 +2021,14 @@ static psa_status_t psa_validate_optional_attributes( const psa_key_slot_t *slot, const psa_key_attributes_t *attributes) { - if (attributes->core.type != 0) { - if (attributes->core.type != slot->attr.type) { - return PSA_ERROR_INVALID_ARGUMENT; - } - } - - if (attributes->domain_parameters_size != 0) { -#if defined(MBEDTLS_PSA_BUILTIN_KEY_TYPE_RSA_KEY_PAIR) || \ - defined(MBEDTLS_PSA_BUILTIN_KEY_TYPE_RSA_PUBLIC_KEY) - if (PSA_KEY_TYPE_IS_RSA(slot->attr.type)) { - mbedtls_rsa_context *rsa = NULL; - mbedtls_mpi actual, required; - int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED; - - psa_status_t status = mbedtls_psa_rsa_load_representation( - slot->attr.type, - slot->key.data, - slot->key.bytes, - &rsa); - if (status != PSA_SUCCESS) { - return status; - } - - mbedtls_mpi_init(&actual); - mbedtls_mpi_init(&required); - ret = mbedtls_rsa_export(rsa, - NULL, NULL, NULL, NULL, &actual); - mbedtls_rsa_free(rsa); - mbedtls_free(rsa); - if (ret != 0) { - goto rsa_exit; - } - ret = mbedtls_mpi_read_binary(&required, - attributes->domain_parameters, - attributes->domain_parameters_size); - if (ret != 0) { - goto rsa_exit; - } - if (mbedtls_mpi_cmp_mpi(&actual, &required) != 0) { - ret = MBEDTLS_ERR_RSA_BAD_INPUT_DATA; - } -rsa_exit: - mbedtls_mpi_free(&actual); - mbedtls_mpi_free(&required); - if (ret != 0) { - return mbedtls_to_psa_error(ret); - } - } else -#endif /* defined(MBEDTLS_PSA_BUILTIN_KEY_TYPE_RSA_KEY_PAIR) || - * defined(MBEDTLS_PSA_BUILTIN_KEY_TYPE_RSA_PUBLIC_KEY) */ - { + if (attributes->type != 0) { + if (attributes->type != slot->attr.type) { return PSA_ERROR_INVALID_ARGUMENT; } } - if (attributes->core.bits != 0) { - if (attributes->core.bits != slot->attr.bits) { + if (attributes->bits != 0) { + if (attributes->bits != slot->attr.bits) { return PSA_ERROR_INVALID_ARGUMENT; } } @@ -1947,14 +2037,16 @@ static psa_status_t psa_validate_optional_attributes( } psa_status_t psa_import_key(const psa_key_attributes_t *attributes, - const uint8_t *data, + const uint8_t *data_external, size_t data_length, mbedtls_svc_key_id_t *key) { psa_status_t status; + LOCAL_INPUT_DECLARE(data_external, data); psa_key_slot_t *slot = NULL; psa_se_drv_table_entry_t *driver = NULL; size_t bits; + size_t storage_size = data_length; *key = MBEDTLS_SVC_KEY_ID_INIT; @@ -1965,6 +2057,13 @@ psa_status_t psa_import_key(const psa_key_attributes_t *attributes, return PSA_ERROR_INVALID_ARGUMENT; } + /* Ensure that the bytes-to-bits conversion cannot overflow. */ + if (data_length > SIZE_MAX / 8) { + return PSA_ERROR_NOT_SUPPORTED; + } + + LOCAL_INPUT_ALLOC(data_external, data_length, data); + status = psa_start_key_creation(PSA_KEY_CREATION_IMPORT, attributes, &slot, &driver); if (status != PSA_SUCCESS) { @@ -1972,11 +2071,18 @@ psa_status_t psa_import_key(const psa_key_attributes_t *attributes, } /* In the case of a transparent key or an opaque key stored in local - * storage (thus not in the case of generating a key in a secure element - * or cryptoprocessor with storage), we have to allocate a buffer to - * hold the generated key material. */ + * storage ( thus not in the case of importing a key in a secure element + * with storage ( MBEDTLS_PSA_CRYPTO_SE_C ) ),we have to allocate a + * buffer to hold the imported key material. */ if (slot->key.data == NULL) { - status = psa_allocate_buffer_to_slot(slot, data_length); + if (psa_key_lifetime_is_external(attributes->lifetime)) { + status = psa_driver_wrapper_get_key_buffer_size_from_key_data( + attributes, data, data_length, &storage_size); + if (status != PSA_SUCCESS) { + goto exit; + } + } + status = psa_allocate_buffer_to_slot(slot, storage_size); if (status != PSA_SUCCESS) { goto exit; } @@ -1999,6 +2105,12 @@ psa_status_t psa_import_key(const psa_key_attributes_t *attributes, goto exit; } + /* Enforce a size limit, and in particular ensure that the bit + * size fits in its representation type.*/ + if (bits > PSA_MAX_KEY_BITS) { + status = PSA_ERROR_NOT_SUPPORTED; + goto exit; + } status = psa_validate_optional_attributes(slot, attributes); if (status != PSA_SUCCESS) { goto exit; @@ -2006,6 +2118,7 @@ psa_status_t psa_import_key(const psa_key_attributes_t *attributes, status = psa_finish_key_creation(slot, driver, key); exit: + LOCAL_INPUT_FREE(data_external, data); if (status != PSA_SUCCESS) { psa_fail_key_creation(slot, driver); } @@ -2052,22 +2165,6 @@ psa_status_t mbedtls_psa_register_se_key( } #endif /* MBEDTLS_PSA_CRYPTO_SE_C */ -static psa_status_t psa_copy_key_material(const psa_key_slot_t *source, - psa_key_slot_t *target) -{ - psa_status_t status = psa_copy_key_material_into_slot(target, - source->key.data, - source->key.bytes); - if (status != PSA_SUCCESS) { - return status; - } - - target->attr.type = source->attr.type; - target->attr.bits = source->attr.bits; - - return PSA_SUCCESS; -} - psa_status_t psa_copy_key(mbedtls_svc_key_id_t source_key, const psa_key_attributes_t *specified_attributes, mbedtls_svc_key_id_t *target_key) @@ -2078,10 +2175,11 @@ psa_status_t psa_copy_key(mbedtls_svc_key_id_t source_key, psa_key_slot_t *target_slot = NULL; psa_key_attributes_t actual_attributes = *specified_attributes; psa_se_drv_table_entry_t *driver = NULL; + size_t storage_size = 0; *target_key = MBEDTLS_SVC_KEY_ID_INIT; - status = psa_get_and_lock_transparent_key_slot_with_policy( + status = psa_get_and_lock_key_slot_with_policy( source_key, &source_slot, PSA_KEY_USAGE_COPY, 0); if (status != PSA_SUCCESS) { goto exit; @@ -2093,8 +2191,17 @@ psa_status_t psa_copy_key(mbedtls_svc_key_id_t source_key, goto exit; } + /* The target key type and number of bits have been validated by + * psa_validate_optional_attributes() to be either equal to zero or + * equal to the ones of the source key. So it is safe to inherit + * them from the source key now." + * */ + actual_attributes.bits = source_slot->attr.bits; + actual_attributes.type = source_slot->attr.type; + + status = psa_restrict_key_policy(source_slot->attr.type, - &actual_attributes.core.policy, + &actual_attributes.policy, &source_slot->attr.policy); if (status != PSA_SUCCESS) { goto exit; @@ -2105,37 +2212,60 @@ psa_status_t psa_copy_key(mbedtls_svc_key_id_t source_key, if (status != PSA_SUCCESS) { goto exit; } - -#if defined(MBEDTLS_PSA_CRYPTO_SE_C) - if (driver != NULL) { - /* Copying to a secure element is not implemented yet. */ + if (PSA_KEY_LIFETIME_GET_LOCATION(target_slot->attr.lifetime) != + PSA_KEY_LIFETIME_GET_LOCATION(source_slot->attr.lifetime)) { + /* + * If the source and target keys are stored in different locations, + * the source key would need to be exported as plaintext and re-imported + * in the other location. This has security implications which have not + * been fully mapped. For now, this can be achieved through + * appropriate API invocations from the application, if needed. + * */ status = PSA_ERROR_NOT_SUPPORTED; goto exit; } -#endif /* MBEDTLS_PSA_CRYPTO_SE_C */ + /* + * When the source and target keys are within the same location, + * - For transparent keys it is a blind copy without any driver invocation, + * - For opaque keys this translates to an invocation of the drivers' + * copy_key entry point through the dispatch layer. + * */ + if (psa_key_lifetime_is_external(actual_attributes.lifetime)) { + status = psa_driver_wrapper_get_key_buffer_size(&actual_attributes, + &storage_size); + if (status != PSA_SUCCESS) { + goto exit; + } - if (psa_key_lifetime_is_external(actual_attributes.core.lifetime)) { - /* - * Copying through an opaque driver is not implemented yet, consider - * a lifetime with an external location as an invalid parameter for - * now. - */ - status = PSA_ERROR_INVALID_ARGUMENT; - goto exit; - } + status = psa_allocate_buffer_to_slot(target_slot, storage_size); + if (status != PSA_SUCCESS) { + goto exit; + } - status = psa_copy_key_material(source_slot, target_slot); - if (status != PSA_SUCCESS) { - goto exit; + status = psa_driver_wrapper_copy_key(&actual_attributes, + source_slot->key.data, + source_slot->key.bytes, + target_slot->key.data, + target_slot->key.bytes, + &target_slot->key.bytes); + if (status != PSA_SUCCESS) { + goto exit; + } + } else { + status = psa_copy_key_material_into_slot(target_slot, + source_slot->key.data, + source_slot->key.bytes); + if (status != PSA_SUCCESS) { + goto exit; + } } - status = psa_finish_key_creation(target_slot, driver, target_key); exit: if (status != PSA_SUCCESS) { psa_fail_key_creation(target_slot, driver); } - unlock_status = psa_unlock_key_slot(source_slot); + unlock_status = psa_unregister_read_under_mutex(source_slot); return (status == PSA_SUCCESS) ? unlock_status : status; } @@ -2190,10 +2320,11 @@ psa_status_t psa_hash_setup(psa_hash_operation_t *operation, } psa_status_t psa_hash_update(psa_hash_operation_t *operation, - const uint8_t *input, + const uint8_t *input_external, size_t input_length) { psa_status_t status = PSA_ERROR_CORRUPTION_DETECTED; + LOCAL_INPUT_DECLARE(input_external, input); if (operation->id == 0) { status = PSA_ERROR_BAD_STATE; @@ -2206,6 +2337,7 @@ psa_status_t psa_hash_update(psa_hash_operation_t *operation, return PSA_SUCCESS; } + LOCAL_INPUT_ALLOC(input_external, input_length, input); status = psa_driver_wrapper_hash_update(operation, input, input_length); exit: @@ -2213,32 +2345,57 @@ psa_status_t psa_hash_update(psa_hash_operation_t *operation, psa_hash_abort(operation); } + LOCAL_INPUT_FREE(input_external, input); return status; } -psa_status_t psa_hash_finish(psa_hash_operation_t *operation, - uint8_t *hash, - size_t hash_size, - size_t *hash_length) +static psa_status_t psa_hash_finish_internal(psa_hash_operation_t *operation, + uint8_t *hash, + size_t hash_size, + size_t *hash_length) { + psa_status_t status = PSA_ERROR_CORRUPTION_DETECTED; + *hash_length = 0; if (operation->id == 0) { return PSA_ERROR_BAD_STATE; } - psa_status_t status = psa_driver_wrapper_hash_finish( + status = psa_driver_wrapper_hash_finish( operation, hash, hash_size, hash_length); psa_hash_abort(operation); + + return status; +} + +psa_status_t psa_hash_finish(psa_hash_operation_t *operation, + uint8_t *hash_external, + size_t hash_size, + size_t *hash_length) +{ + psa_status_t status = PSA_ERROR_CORRUPTION_DETECTED; + LOCAL_OUTPUT_DECLARE(hash_external, hash); + + LOCAL_OUTPUT_ALLOC(hash_external, hash_size, hash); + status = psa_hash_finish_internal(operation, hash, hash_size, hash_length); + +#if !defined(MBEDTLS_PSA_ASSUME_EXCLUSIVE_BUFFERS) +exit: +#endif + LOCAL_OUTPUT_FREE(hash_external, hash); return status; } psa_status_t psa_hash_verify(psa_hash_operation_t *operation, - const uint8_t *hash, + const uint8_t *hash_external, size_t hash_length) { uint8_t actual_hash[PSA_HASH_MAX_SIZE]; size_t actual_hash_length; - psa_status_t status = psa_hash_finish( + psa_status_t status = PSA_ERROR_CORRUPTION_DETECTED; + LOCAL_INPUT_DECLARE(hash_external, hash); + + status = psa_hash_finish_internal( operation, actual_hash, sizeof(actual_hash), &actual_hash_length); @@ -2252,7 +2409,8 @@ psa_status_t psa_hash_verify(psa_hash_operation_t *operation, goto exit; } - if (mbedtls_psa_safer_memcmp(hash, actual_hash, actual_hash_length) != 0) { + LOCAL_INPUT_ALLOC(hash_external, hash_length, hash); + if (mbedtls_ct_memcmp(hash, actual_hash, actual_hash_length) != 0) { status = PSA_ERROR_INVALID_SIGNATURE; } @@ -2261,36 +2419,55 @@ psa_status_t psa_hash_verify(psa_hash_operation_t *operation, if (status != PSA_SUCCESS) { psa_hash_abort(operation); } - + LOCAL_INPUT_FREE(hash_external, hash); return status; } psa_status_t psa_hash_compute(psa_algorithm_t alg, - const uint8_t *input, size_t input_length, - uint8_t *hash, size_t hash_size, + const uint8_t *input_external, size_t input_length, + uint8_t *hash_external, size_t hash_size, size_t *hash_length) { + psa_status_t status = PSA_ERROR_CORRUPTION_DETECTED; + LOCAL_INPUT_DECLARE(input_external, input); + LOCAL_OUTPUT_DECLARE(hash_external, hash); + *hash_length = 0; if (!PSA_ALG_IS_HASH(alg)) { return PSA_ERROR_INVALID_ARGUMENT; } - return psa_driver_wrapper_hash_compute(alg, input, input_length, - hash, hash_size, hash_length); + LOCAL_INPUT_ALLOC(input_external, input_length, input); + LOCAL_OUTPUT_ALLOC(hash_external, hash_size, hash); + status = psa_driver_wrapper_hash_compute(alg, input, input_length, + hash, hash_size, hash_length); + +#if !defined(MBEDTLS_PSA_ASSUME_EXCLUSIVE_BUFFERS) +exit: +#endif + LOCAL_INPUT_FREE(input_external, input); + LOCAL_OUTPUT_FREE(hash_external, hash); + return status; } psa_status_t psa_hash_compare(psa_algorithm_t alg, - const uint8_t *input, size_t input_length, - const uint8_t *hash, size_t hash_length) + const uint8_t *input_external, size_t input_length, + const uint8_t *hash_external, size_t hash_length) { uint8_t actual_hash[PSA_HASH_MAX_SIZE]; size_t actual_hash_length; + psa_status_t status = PSA_ERROR_CORRUPTION_DETECTED; + + LOCAL_INPUT_DECLARE(input_external, input); + LOCAL_INPUT_DECLARE(hash_external, hash); if (!PSA_ALG_IS_HASH(alg)) { - return PSA_ERROR_INVALID_ARGUMENT; + status = PSA_ERROR_INVALID_ARGUMENT; + return status; } - psa_status_t status = psa_driver_wrapper_hash_compute( + LOCAL_INPUT_ALLOC(input_external, input_length, input); + status = psa_driver_wrapper_hash_compute( alg, input, input_length, actual_hash, sizeof(actual_hash), &actual_hash_length); @@ -2301,12 +2478,18 @@ psa_status_t psa_hash_compare(psa_algorithm_t alg, status = PSA_ERROR_INVALID_SIGNATURE; goto exit; } - if (mbedtls_psa_safer_memcmp(hash, actual_hash, actual_hash_length) != 0) { + + LOCAL_INPUT_ALLOC(hash_external, hash_length, hash); + if (mbedtls_ct_memcmp(hash, actual_hash, actual_hash_length) != 0) { status = PSA_ERROR_INVALID_SIGNATURE; } exit: mbedtls_platform_zeroize(actual_hash, sizeof(actual_hash)); + + LOCAL_INPUT_FREE(input_external, input); + LOCAL_INPUT_FREE(hash_external, hash); + return status; } @@ -2407,7 +2590,6 @@ static psa_status_t psa_mac_setup(psa_mac_operation_t *operation, { psa_status_t status = PSA_ERROR_CORRUPTION_DETECTED; psa_status_t unlock_status = PSA_ERROR_CORRUPTION_DETECTED; - psa_key_attributes_t attributes; psa_key_slot_t *slot = NULL; /* A context must be freshly initialized before it can be set up. */ @@ -2425,11 +2607,7 @@ static psa_status_t psa_mac_setup(psa_mac_operation_t *operation, goto exit; } - attributes = (psa_key_attributes_t) { - .core = slot->attr - }; - - status = psa_mac_finalize_alg_and_key_validation(alg, &attributes, + status = psa_mac_finalize_alg_and_key_validation(alg, &slot->attr, &operation->mac_size); if (status != PSA_SUCCESS) { goto exit; @@ -2439,13 +2617,13 @@ static psa_status_t psa_mac_setup(psa_mac_operation_t *operation, /* Dispatch the MAC setup call with validated input */ if (is_sign) { status = psa_driver_wrapper_mac_sign_setup(operation, - &attributes, + &slot->attr, slot->key.data, slot->key.bytes, alg); } else { status = psa_driver_wrapper_mac_verify_setup(operation, - &attributes, + &slot->attr, slot->key.data, slot->key.bytes, alg); @@ -2456,7 +2634,7 @@ static psa_status_t psa_mac_setup(psa_mac_operation_t *operation, psa_mac_abort(operation); } - unlock_status = psa_unlock_key_slot(slot); + unlock_status = psa_unregister_read_under_mutex(slot); return (status == PSA_SUCCESS) ? unlock_status : status; } @@ -2476,35 +2654,48 @@ psa_status_t psa_mac_verify_setup(psa_mac_operation_t *operation, } psa_status_t psa_mac_update(psa_mac_operation_t *operation, - const uint8_t *input, + const uint8_t *input_external, size_t input_length) { + psa_status_t status = PSA_ERROR_CORRUPTION_DETECTED; + LOCAL_INPUT_DECLARE(input_external, input); + if (operation->id == 0) { - return PSA_ERROR_BAD_STATE; + status = PSA_ERROR_BAD_STATE; + return status; } /* Don't require hash implementations to behave correctly on a * zero-length input, which may have an invalid pointer. */ if (input_length == 0) { - return PSA_SUCCESS; + status = PSA_SUCCESS; + return status; } - psa_status_t status = psa_driver_wrapper_mac_update(operation, - input, input_length); + LOCAL_INPUT_ALLOC(input_external, input_length, input); + status = psa_driver_wrapper_mac_update(operation, input, input_length); + if (status != PSA_SUCCESS) { psa_mac_abort(operation); } +#if !defined(MBEDTLS_PSA_ASSUME_EXCLUSIVE_BUFFERS) +exit: +#endif + LOCAL_INPUT_FREE(input_external, input); + return status; } psa_status_t psa_mac_sign_finish(psa_mac_operation_t *operation, - uint8_t *mac, + uint8_t *mac_external, size_t mac_size, size_t *mac_length) { psa_status_t status = PSA_ERROR_CORRUPTION_DETECTED; psa_status_t abort_status = PSA_ERROR_CORRUPTION_DETECTED; + LOCAL_OUTPUT_DECLARE(mac_external, mac); + LOCAL_OUTPUT_ALLOC(mac_external, mac_size, mac); if (operation->id == 0) { status = PSA_ERROR_BAD_STATE; @@ -2528,6 +2719,7 @@ psa_status_t psa_mac_sign_finish(psa_mac_operation_t *operation, goto exit; } + status = psa_driver_wrapper_mac_sign_finish(operation, mac, operation->mac_size, mac_length); @@ -2544,22 +2736,23 @@ psa_status_t psa_mac_sign_finish(psa_mac_operation_t *operation, operation->mac_size = 0; } - if (mac_size > operation->mac_size) { - memset(&mac[operation->mac_size], '!', - mac_size - operation->mac_size); + if (mac != NULL) { + psa_wipe_tag_output_buffer(mac, status, mac_size, *mac_length); } abort_status = psa_mac_abort(operation); + LOCAL_OUTPUT_FREE(mac_external, mac); return status == PSA_SUCCESS ? abort_status : status; } psa_status_t psa_mac_verify_finish(psa_mac_operation_t *operation, - const uint8_t *mac, + const uint8_t *mac_external, size_t mac_length) { psa_status_t status = PSA_ERROR_CORRUPTION_DETECTED; psa_status_t abort_status = PSA_ERROR_CORRUPTION_DETECTED; + LOCAL_INPUT_DECLARE(mac_external, mac); if (operation->id == 0) { status = PSA_ERROR_BAD_STATE; @@ -2576,11 +2769,13 @@ psa_status_t psa_mac_verify_finish(psa_mac_operation_t *operation, goto exit; } + LOCAL_INPUT_ALLOC(mac_external, mac_length, mac); status = psa_driver_wrapper_mac_verify_finish(operation, mac, mac_length); exit: abort_status = psa_mac_abort(operation); + LOCAL_INPUT_FREE(mac_external, mac); return status == PSA_SUCCESS ? abort_status : status; } @@ -2596,7 +2791,6 @@ static psa_status_t psa_mac_compute_internal(mbedtls_svc_key_id_t key, { psa_status_t status = PSA_ERROR_CORRUPTION_DETECTED; psa_status_t unlock_status = PSA_ERROR_CORRUPTION_DETECTED; - psa_key_attributes_t attributes; psa_key_slot_t *slot; uint8_t operation_mac_size = 0; @@ -2609,11 +2803,7 @@ static psa_status_t psa_mac_compute_internal(mbedtls_svc_key_id_t key, goto exit; } - attributes = (psa_key_attributes_t) { - .core = slot->attr - }; - - status = psa_mac_finalize_alg_and_key_validation(alg, &attributes, + status = psa_mac_finalize_alg_and_key_validation(alg, &slot->attr, &operation_mac_size); if (status != PSA_SUCCESS) { goto exit; @@ -2625,7 +2815,7 @@ static psa_status_t psa_mac_compute_internal(mbedtls_svc_key_id_t key, } status = psa_driver_wrapper_mac_compute( - &attributes, + &slot->attr, slot->key.data, slot->key.bytes, alg, input, input_length, @@ -2642,39 +2832,55 @@ static psa_status_t psa_mac_compute_internal(mbedtls_svc_key_id_t key, *mac_length = mac_size; operation_mac_size = 0; } - if (mac_size > operation_mac_size) { - memset(&mac[operation_mac_size], '!', mac_size - operation_mac_size); - } - unlock_status = psa_unlock_key_slot(slot); + psa_wipe_tag_output_buffer(mac, status, mac_size, *mac_length); + + unlock_status = psa_unregister_read_under_mutex(slot); return (status == PSA_SUCCESS) ? unlock_status : status; } psa_status_t psa_mac_compute(mbedtls_svc_key_id_t key, psa_algorithm_t alg, - const uint8_t *input, + const uint8_t *input_external, size_t input_length, - uint8_t *mac, + uint8_t *mac_external, size_t mac_size, size_t *mac_length) { - return psa_mac_compute_internal(key, alg, - input, input_length, - mac, mac_size, mac_length, 1); + psa_status_t status = PSA_ERROR_CORRUPTION_DETECTED; + LOCAL_INPUT_DECLARE(input_external, input); + LOCAL_OUTPUT_DECLARE(mac_external, mac); + + LOCAL_INPUT_ALLOC(input_external, input_length, input); + LOCAL_OUTPUT_ALLOC(mac_external, mac_size, mac); + status = psa_mac_compute_internal(key, alg, + input, input_length, + mac, mac_size, mac_length, 1); + +#if !defined(MBEDTLS_PSA_ASSUME_EXCLUSIVE_BUFFERS) +exit: +#endif + LOCAL_INPUT_FREE(input_external, input); + LOCAL_OUTPUT_FREE(mac_external, mac); + + return status; } psa_status_t psa_mac_verify(mbedtls_svc_key_id_t key, psa_algorithm_t alg, - const uint8_t *input, + const uint8_t *input_external, size_t input_length, - const uint8_t *mac, + const uint8_t *mac_external, size_t mac_length) { psa_status_t status = PSA_ERROR_CORRUPTION_DETECTED; uint8_t actual_mac[PSA_MAC_MAX_SIZE]; size_t actual_mac_length; + LOCAL_INPUT_DECLARE(input_external, input); + LOCAL_INPUT_DECLARE(mac_external, mac); + LOCAL_INPUT_ALLOC(input_external, input_length, input); status = psa_mac_compute_internal(key, alg, input, input_length, actual_mac, sizeof(actual_mac), @@ -2687,13 +2893,17 @@ psa_status_t psa_mac_verify(mbedtls_svc_key_id_t key, status = PSA_ERROR_INVALID_SIGNATURE; goto exit; } - if (mbedtls_psa_safer_memcmp(mac, actual_mac, actual_mac_length) != 0) { + + LOCAL_INPUT_ALLOC(mac_external, mac_length, mac); + if (mbedtls_ct_memcmp(mac, actual_mac, actual_mac_length) != 0) { status = PSA_ERROR_INVALID_SIGNATURE; goto exit; } exit: mbedtls_platform_zeroize(actual_mac, sizeof(actual_mac)); + LOCAL_INPUT_FREE(input_external, input); + LOCAL_INPUT_FREE(mac_external, mac); return status; } @@ -2735,7 +2945,6 @@ static psa_status_t psa_sign_internal(mbedtls_svc_key_id_t key, { psa_status_t status = PSA_ERROR_CORRUPTION_DETECTED; psa_status_t unlock_status = PSA_ERROR_CORRUPTION_DETECTED; - psa_key_attributes_t attributes; psa_key_slot_t *slot; *signature_length = 0; @@ -2768,39 +2977,25 @@ static psa_status_t psa_sign_internal(mbedtls_svc_key_id_t key, goto exit; } - attributes = (psa_key_attributes_t) { - .core = slot->attr - }; - if (input_is_message) { status = psa_driver_wrapper_sign_message( - &attributes, slot->key.data, slot->key.bytes, + &slot->attr, slot->key.data, slot->key.bytes, alg, input, input_length, signature, signature_size, signature_length); } else { status = psa_driver_wrapper_sign_hash( - &attributes, slot->key.data, slot->key.bytes, + &slot->attr, slot->key.data, slot->key.bytes, alg, input, input_length, signature, signature_size, signature_length); } exit: - /* Fill the unused part of the output buffer (the whole buffer on error, - * the trailing part on success) with something that isn't a valid signature - * (barring an attack on the signature and deliberately-crafted input), - * in case the caller doesn't check the return status properly. */ - if (status == PSA_SUCCESS) { - memset(signature + *signature_length, '!', - signature_size - *signature_length); - } else { - memset(signature, '!', signature_size); - } - /* If signature_size is 0 then we have nothing to do. We must not call - * memset because signature may be NULL in this case. */ + psa_wipe_tag_output_buffer(signature, status, signature_size, + *signature_length); - unlock_status = psa_unlock_key_slot(slot); + unlock_status = psa_unregister_read_under_mutex(slot); return (status == PSA_SUCCESS) ? unlock_status : status; } @@ -2832,23 +3027,19 @@ static psa_status_t psa_verify_internal(mbedtls_svc_key_id_t key, return status; } - psa_key_attributes_t attributes = { - .core = slot->attr - }; - if (input_is_message) { status = psa_driver_wrapper_verify_message( - &attributes, slot->key.data, slot->key.bytes, + &slot->attr, slot->key.data, slot->key.bytes, alg, input, input_length, signature, signature_length); } else { status = psa_driver_wrapper_verify_hash( - &attributes, slot->key.data, slot->key.bytes, + &slot->attr, slot->key.data, slot->key.bytes, alg, input, input_length, signature, signature_length); } - unlock_status = psa_unlock_key_slot(slot); + unlock_status = psa_unregister_read_under_mutex(slot); return (status == PSA_SUCCESS) ? unlock_status : status; @@ -2891,15 +3082,27 @@ psa_status_t psa_sign_message_builtin( psa_status_t psa_sign_message(mbedtls_svc_key_id_t key, psa_algorithm_t alg, - const uint8_t *input, + const uint8_t *input_external, size_t input_length, - uint8_t *signature, + uint8_t *signature_external, size_t signature_size, size_t *signature_length) { - return psa_sign_internal( - key, 1, alg, input, input_length, - signature, signature_size, signature_length); + psa_status_t status = PSA_ERROR_CORRUPTION_DETECTED; + LOCAL_INPUT_DECLARE(input_external, input); + LOCAL_OUTPUT_DECLARE(signature_external, signature); + + LOCAL_INPUT_ALLOC(input_external, input_length, input); + LOCAL_OUTPUT_ALLOC(signature_external, signature_size, signature); + status = psa_sign_internal(key, 1, alg, input, input_length, signature, + signature_size, signature_length); + +#if !defined(MBEDTLS_PSA_ASSUME_EXCLUSIVE_BUFFERS) +exit: +#endif + LOCAL_INPUT_FREE(input_external, input); + LOCAL_OUTPUT_FREE(signature_external, signature); + return status; } psa_status_t psa_verify_message_builtin( @@ -2938,14 +3141,27 @@ psa_status_t psa_verify_message_builtin( psa_status_t psa_verify_message(mbedtls_svc_key_id_t key, psa_algorithm_t alg, - const uint8_t *input, + const uint8_t *input_external, size_t input_length, - const uint8_t *signature, + const uint8_t *signature_external, size_t signature_length) { - return psa_verify_internal( - key, 1, alg, input, input_length, - signature, signature_length); + psa_status_t status = PSA_ERROR_CORRUPTION_DETECTED; + LOCAL_INPUT_DECLARE(input_external, input); + LOCAL_INPUT_DECLARE(signature_external, signature); + + LOCAL_INPUT_ALLOC(input_external, input_length, input); + LOCAL_INPUT_ALLOC(signature_external, signature_length, signature); + status = psa_verify_internal(key, 1, alg, input, input_length, signature, + signature_length); + +#if !defined(MBEDTLS_PSA_ASSUME_EXCLUSIVE_BUFFERS) +exit: +#endif + LOCAL_INPUT_FREE(input_external, input); + LOCAL_INPUT_FREE(signature_external, signature); + + return status; } psa_status_t psa_sign_hash_builtin( @@ -2954,7 +3170,7 @@ psa_status_t psa_sign_hash_builtin( psa_algorithm_t alg, const uint8_t *hash, size_t hash_length, uint8_t *signature, size_t signature_size, size_t *signature_length) { - if (attributes->core.type == PSA_KEY_TYPE_RSA_KEY_PAIR) { + if (attributes->type == PSA_KEY_TYPE_RSA_KEY_PAIR) { if (PSA_ALG_IS_RSA_PKCS1V15_SIGN(alg) || PSA_ALG_IS_RSA_PSS(alg)) { #if defined(MBEDTLS_PSA_BUILTIN_ALG_RSA_PKCS1V15_SIGN) || \ @@ -2969,7 +3185,7 @@ psa_status_t psa_sign_hash_builtin( } else { return PSA_ERROR_INVALID_ARGUMENT; } - } else if (PSA_KEY_TYPE_IS_ECC(attributes->core.type)) { + } else if (PSA_KEY_TYPE_IS_ECC(attributes->type)) { if (PSA_ALG_IS_ECDSA(alg)) { #if defined(MBEDTLS_PSA_BUILTIN_ALG_ECDSA) || \ defined(MBEDTLS_PSA_BUILTIN_ALG_DETERMINISTIC_ECDSA) @@ -2998,15 +3214,28 @@ psa_status_t psa_sign_hash_builtin( psa_status_t psa_sign_hash(mbedtls_svc_key_id_t key, psa_algorithm_t alg, - const uint8_t *hash, + const uint8_t *hash_external, size_t hash_length, - uint8_t *signature, + uint8_t *signature_external, size_t signature_size, size_t *signature_length) { - return psa_sign_internal( - key, 0, alg, hash, hash_length, - signature, signature_size, signature_length); + psa_status_t status = PSA_ERROR_CORRUPTION_DETECTED; + LOCAL_INPUT_DECLARE(hash_external, hash); + LOCAL_OUTPUT_DECLARE(signature_external, signature); + + LOCAL_INPUT_ALLOC(hash_external, hash_length, hash); + LOCAL_OUTPUT_ALLOC(signature_external, signature_size, signature); + status = psa_sign_internal(key, 0, alg, hash, hash_length, signature, + signature_size, signature_length); + +#if !defined(MBEDTLS_PSA_ASSUME_EXCLUSIVE_BUFFERS) +exit: +#endif + LOCAL_INPUT_FREE(hash_external, hash); + LOCAL_OUTPUT_FREE(signature_external, signature); + + return status; } psa_status_t psa_verify_hash_builtin( @@ -3015,7 +3244,7 @@ psa_status_t psa_verify_hash_builtin( psa_algorithm_t alg, const uint8_t *hash, size_t hash_length, const uint8_t *signature, size_t signature_length) { - if (PSA_KEY_TYPE_IS_RSA(attributes->core.type)) { + if (PSA_KEY_TYPE_IS_RSA(attributes->type)) { if (PSA_ALG_IS_RSA_PKCS1V15_SIGN(alg) || PSA_ALG_IS_RSA_PSS(alg)) { #if defined(MBEDTLS_PSA_BUILTIN_ALG_RSA_PKCS1V15_SIGN) || \ @@ -3030,7 +3259,7 @@ psa_status_t psa_verify_hash_builtin( } else { return PSA_ERROR_INVALID_ARGUMENT; } - } else if (PSA_KEY_TYPE_IS_ECC(attributes->core.type)) { + } else if (PSA_KEY_TYPE_IS_ECC(attributes->type)) { if (PSA_ALG_IS_ECDSA(alg)) { #if defined(MBEDTLS_PSA_BUILTIN_ALG_ECDSA) || \ defined(MBEDTLS_PSA_BUILTIN_ALG_DETERMINISTIC_ECDSA) @@ -3058,34 +3287,36 @@ psa_status_t psa_verify_hash_builtin( psa_status_t psa_verify_hash(mbedtls_svc_key_id_t key, psa_algorithm_t alg, - const uint8_t *hash, + const uint8_t *hash_external, size_t hash_length, - const uint8_t *signature, + const uint8_t *signature_external, size_t signature_length) { - return psa_verify_internal( - key, 0, alg, hash, hash_length, - signature, signature_length); -} + psa_status_t status = PSA_ERROR_CORRUPTION_DETECTED; + LOCAL_INPUT_DECLARE(hash_external, hash); + LOCAL_INPUT_DECLARE(signature_external, signature); -#if defined(MBEDTLS_PSA_BUILTIN_ALG_RSA_OAEP) -static void psa_rsa_oaep_set_padding_mode(psa_algorithm_t alg, - mbedtls_rsa_context *rsa) -{ - psa_algorithm_t hash_alg = PSA_ALG_RSA_OAEP_GET_HASH(alg); - const mbedtls_md_info_t *md_info = mbedtls_md_info_from_psa(hash_alg); - mbedtls_md_type_t md_alg = mbedtls_md_get_type(md_info); - mbedtls_rsa_set_padding(rsa, MBEDTLS_RSA_PKCS_V21, md_alg); + LOCAL_INPUT_ALLOC(hash_external, hash_length, hash); + LOCAL_INPUT_ALLOC(signature_external, signature_length, signature); + status = psa_verify_internal(key, 0, alg, hash, hash_length, signature, + signature_length); + +#if !defined(MBEDTLS_PSA_ASSUME_EXCLUSIVE_BUFFERS) +exit: +#endif + LOCAL_INPUT_FREE(hash_external, hash); + LOCAL_INPUT_FREE(signature_external, signature); + + return status; } -#endif /* defined(MBEDTLS_PSA_BUILTIN_ALG_RSA_OAEP) */ psa_status_t psa_asymmetric_encrypt(mbedtls_svc_key_id_t key, psa_algorithm_t alg, - const uint8_t *input, + const uint8_t *input_external, size_t input_length, - const uint8_t *salt, + const uint8_t *salt_external, size_t salt_length, - uint8_t *output, + uint8_t *output_external, size_t output_size, size_t *output_length) { @@ -3093,6 +3324,10 @@ psa_status_t psa_asymmetric_encrypt(mbedtls_svc_key_id_t key, psa_status_t unlock_status = PSA_ERROR_CORRUPTION_DETECTED; psa_key_slot_t *slot; + LOCAL_INPUT_DECLARE(input_external, input); + LOCAL_INPUT_DECLARE(salt_external, salt); + LOCAL_OUTPUT_DECLARE(output_external, output); + (void) input; (void) input_length; (void) salt; @@ -3105,7 +3340,7 @@ psa_status_t psa_asymmetric_encrypt(mbedtls_svc_key_id_t key, return PSA_ERROR_INVALID_ARGUMENT; } - status = psa_get_and_lock_transparent_key_slot_with_policy( + status = psa_get_and_lock_key_slot_with_policy( key, &slot, PSA_KEY_USAGE_ENCRYPT, alg); if (status != PSA_SUCCESS) { return status; @@ -3116,84 +3351,31 @@ psa_status_t psa_asymmetric_encrypt(mbedtls_svc_key_id_t key, goto exit; } - if (PSA_KEY_TYPE_IS_RSA(slot->attr.type)) { -#if defined(MBEDTLS_PSA_BUILTIN_ALG_RSA_PKCS1V15_CRYPT) || \ - defined(MBEDTLS_PSA_BUILTIN_ALG_RSA_OAEP) - mbedtls_rsa_context *rsa = NULL; - status = mbedtls_psa_rsa_load_representation(slot->attr.type, - slot->key.data, - slot->key.bytes, - &rsa); - if (status != PSA_SUCCESS) { - goto rsa_exit; - } - - if (output_size < mbedtls_rsa_get_len(rsa)) { - status = PSA_ERROR_BUFFER_TOO_SMALL; - goto rsa_exit; - } -#endif /* defined(MBEDTLS_PSA_BUILTIN_ALG_RSA_PKCS1V15_CRYPT) || - * defined(MBEDTLS_PSA_BUILTIN_ALG_RSA_OAEP) */ - if (alg == PSA_ALG_RSA_PKCS1V15_CRYPT) { -#if defined(MBEDTLS_PSA_BUILTIN_ALG_RSA_PKCS1V15_CRYPT) - status = mbedtls_to_psa_error( - mbedtls_rsa_pkcs1_encrypt(rsa, - mbedtls_psa_get_random, - MBEDTLS_PSA_RANDOM_STATE, - MBEDTLS_RSA_PUBLIC, - input_length, - input, - output)); -#else - status = PSA_ERROR_NOT_SUPPORTED; -#endif /* MBEDTLS_PSA_BUILTIN_ALG_RSA_PKCS1V15_CRYPT */ - } else - if (PSA_ALG_IS_RSA_OAEP(alg)) { -#if defined(MBEDTLS_PSA_BUILTIN_ALG_RSA_OAEP) - psa_rsa_oaep_set_padding_mode(alg, rsa); - status = mbedtls_to_psa_error( - mbedtls_rsa_rsaes_oaep_encrypt(rsa, - mbedtls_psa_get_random, - MBEDTLS_PSA_RANDOM_STATE, - MBEDTLS_RSA_PUBLIC, - salt, salt_length, - input_length, - input, - output)); -#else - status = PSA_ERROR_NOT_SUPPORTED; -#endif /* MBEDTLS_PSA_BUILTIN_ALG_RSA_OAEP */ - } else { - status = PSA_ERROR_INVALID_ARGUMENT; - } -#if defined(MBEDTLS_PSA_BUILTIN_ALG_RSA_PKCS1V15_CRYPT) || \ - defined(MBEDTLS_PSA_BUILTIN_ALG_RSA_OAEP) -rsa_exit: - if (status == PSA_SUCCESS) { - *output_length = mbedtls_rsa_get_len(rsa); - } - - mbedtls_rsa_free(rsa); - mbedtls_free(rsa); -#endif /* defined(MBEDTLS_PSA_BUILTIN_ALG_RSA_PKCS1V15_CRYPT) || - * defined(MBEDTLS_PSA_BUILTIN_ALG_RSA_OAEP) */ - } else { - status = PSA_ERROR_NOT_SUPPORTED; - } + LOCAL_INPUT_ALLOC(input_external, input_length, input); + LOCAL_INPUT_ALLOC(salt_external, salt_length, salt); + LOCAL_OUTPUT_ALLOC(output_external, output_size, output); + status = psa_driver_wrapper_asymmetric_encrypt( + &slot->attr, slot->key.data, slot->key.bytes, + alg, input, input_length, salt, salt_length, + output, output_size, output_length); exit: - unlock_status = psa_unlock_key_slot(slot); + unlock_status = psa_unregister_read_under_mutex(slot); + + LOCAL_INPUT_FREE(input_external, input); + LOCAL_INPUT_FREE(salt_external, salt); + LOCAL_OUTPUT_FREE(output_external, output); return (status == PSA_SUCCESS) ? unlock_status : status; } psa_status_t psa_asymmetric_decrypt(mbedtls_svc_key_id_t key, psa_algorithm_t alg, - const uint8_t *input, + const uint8_t *input_external, size_t input_length, - const uint8_t *salt, + const uint8_t *salt_external, size_t salt_length, - uint8_t *output, + uint8_t *output_external, size_t output_size, size_t *output_length) { @@ -3201,6 +3383,10 @@ psa_status_t psa_asymmetric_decrypt(mbedtls_svc_key_id_t key, psa_status_t unlock_status = PSA_ERROR_CORRUPTION_DETECTED; psa_key_slot_t *slot; + LOCAL_INPUT_DECLARE(input_external, input); + LOCAL_INPUT_DECLARE(salt_external, salt); + LOCAL_OUTPUT_DECLARE(output_external, output); + (void) input; (void) input_length; (void) salt; @@ -3213,7 +3399,7 @@ psa_status_t psa_asymmetric_decrypt(mbedtls_svc_key_id_t key, return PSA_ERROR_INVALID_ARGUMENT; } - status = psa_get_and_lock_transparent_key_slot_with_policy( + status = psa_get_and_lock_key_slot_with_policy( key, &slot, PSA_KEY_USAGE_DECRYPT, alg); if (status != PSA_SUCCESS) { return status; @@ -3223,322 +3409,213 @@ psa_status_t psa_asymmetric_decrypt(mbedtls_svc_key_id_t key, goto exit; } - if (slot->attr.type == PSA_KEY_TYPE_RSA_KEY_PAIR) { -#if defined(MBEDTLS_PSA_BUILTIN_ALG_RSA_PKCS1V15_CRYPT) || \ - defined(MBEDTLS_PSA_BUILTIN_ALG_RSA_OAEP) - mbedtls_rsa_context *rsa = NULL; - status = mbedtls_psa_rsa_load_representation(slot->attr.type, - slot->key.data, - slot->key.bytes, - &rsa); - if (status != PSA_SUCCESS) { - goto exit; - } - - if (input_length != mbedtls_rsa_get_len(rsa)) { - status = PSA_ERROR_INVALID_ARGUMENT; - goto rsa_exit; - } -#endif /* defined(MBEDTLS_PSA_BUILTIN_ALG_RSA_PKCS1V15_CRYPT) || - * defined(MBEDTLS_PSA_BUILTIN_ALG_RSA_OAEP) */ - - if (alg == PSA_ALG_RSA_PKCS1V15_CRYPT) { -#if defined(MBEDTLS_PSA_BUILTIN_ALG_RSA_PKCS1V15_CRYPT) - status = mbedtls_to_psa_error( - mbedtls_rsa_pkcs1_decrypt(rsa, - mbedtls_psa_get_random, - MBEDTLS_PSA_RANDOM_STATE, - MBEDTLS_RSA_PRIVATE, - output_length, - input, - output, - output_size)); -#else - status = PSA_ERROR_NOT_SUPPORTED; -#endif /* MBEDTLS_PSA_BUILTIN_ALG_RSA_PKCS1V15_CRYPT */ - } else - if (PSA_ALG_IS_RSA_OAEP(alg)) { -#if defined(MBEDTLS_PSA_BUILTIN_ALG_RSA_OAEP) - psa_rsa_oaep_set_padding_mode(alg, rsa); - status = mbedtls_to_psa_error( - mbedtls_rsa_rsaes_oaep_decrypt(rsa, - mbedtls_psa_get_random, - MBEDTLS_PSA_RANDOM_STATE, - MBEDTLS_RSA_PRIVATE, - salt, salt_length, - output_length, - input, - output, - output_size)); -#else - status = PSA_ERROR_NOT_SUPPORTED; -#endif /* MBEDTLS_PSA_BUILTIN_ALG_RSA_OAEP */ - } else { - status = PSA_ERROR_INVALID_ARGUMENT; - } + LOCAL_INPUT_ALLOC(input_external, input_length, input); + LOCAL_INPUT_ALLOC(salt_external, salt_length, salt); + LOCAL_OUTPUT_ALLOC(output_external, output_size, output); -#if defined(MBEDTLS_PSA_BUILTIN_ALG_RSA_PKCS1V15_CRYPT) || \ - defined(MBEDTLS_PSA_BUILTIN_ALG_RSA_OAEP) -rsa_exit: - mbedtls_rsa_free(rsa); - mbedtls_free(rsa); -#endif /* defined(MBEDTLS_PSA_BUILTIN_ALG_RSA_PKCS1V15_CRYPT) || - * defined(MBEDTLS_PSA_BUILTIN_ALG_RSA_OAEP) */ - } else { - status = PSA_ERROR_NOT_SUPPORTED; - } + status = psa_driver_wrapper_asymmetric_decrypt( + &slot->attr, slot->key.data, slot->key.bytes, + alg, input, input_length, salt, salt_length, + output, output_size, output_length); exit: - unlock_status = psa_unlock_key_slot(slot); + unlock_status = psa_unregister_read_under_mutex(slot); + + LOCAL_INPUT_FREE(input_external, input); + LOCAL_INPUT_FREE(salt_external, salt); + LOCAL_OUTPUT_FREE(output_external, output); return (status == PSA_SUCCESS) ? unlock_status : status; } - - /****************************************************************/ -/* Symmetric cryptography */ +/* Asymmetric interruptible cryptography */ /****************************************************************/ -static psa_status_t psa_cipher_setup(psa_cipher_operation_t *operation, - mbedtls_svc_key_id_t key, - psa_algorithm_t alg, - mbedtls_operation_t cipher_operation) -{ - psa_status_t status = PSA_ERROR_CORRUPTION_DETECTED; - psa_status_t unlock_status = PSA_ERROR_CORRUPTION_DETECTED; - psa_key_attributes_t attributes; - psa_key_slot_t *slot = NULL; - psa_key_usage_t usage = (cipher_operation == MBEDTLS_ENCRYPT ? - PSA_KEY_USAGE_ENCRYPT : - PSA_KEY_USAGE_DECRYPT); +static uint32_t psa_interruptible_max_ops = PSA_INTERRUPTIBLE_MAX_OPS_UNLIMITED; - /* A context must be freshly initialized before it can be set up. */ - if (operation->id != 0) { - status = PSA_ERROR_BAD_STATE; - goto exit; - } +void psa_interruptible_set_max_ops(uint32_t max_ops) +{ + psa_interruptible_max_ops = max_ops; +} - if (!PSA_ALG_IS_CIPHER(alg)) { - status = PSA_ERROR_INVALID_ARGUMENT; - goto exit; - } +uint32_t psa_interruptible_get_max_ops(void) +{ + return psa_interruptible_max_ops; +} - status = psa_get_and_lock_key_slot_with_policy(key, &slot, usage, alg); - if (status != PSA_SUCCESS) { - goto exit; - } +uint32_t psa_sign_hash_get_num_ops( + const psa_sign_hash_interruptible_operation_t *operation) +{ + return operation->num_ops; +} - /* Initialize the operation struct members, except for id. The id member - * is used to indicate to psa_cipher_abort that there are resources to free, - * so we only set it (in the driver wrapper) after resources have been - * allocated/initialized. */ - operation->iv_set = 0; - if (alg == PSA_ALG_ECB_NO_PADDING) { - operation->iv_required = 0; - } else if (slot->attr.type == PSA_KEY_TYPE_ARC4) { - operation->iv_required = 0; - } else { - operation->iv_required = 1; - } - operation->default_iv_length = PSA_CIPHER_IV_LENGTH(slot->attr.type, alg); - - attributes = (psa_key_attributes_t) { - .core = slot->attr - }; +uint32_t psa_verify_hash_get_num_ops( + const psa_verify_hash_interruptible_operation_t *operation) +{ + return operation->num_ops; +} - /* Try doing the operation through a driver before using software fallback. */ - if (cipher_operation == MBEDTLS_ENCRYPT) { - status = psa_driver_wrapper_cipher_encrypt_setup(operation, - &attributes, - slot->key.data, - slot->key.bytes, - alg); - } else { - status = psa_driver_wrapper_cipher_decrypt_setup(operation, - &attributes, - slot->key.data, - slot->key.bytes, - alg); +static psa_status_t psa_sign_hash_abort_internal( + psa_sign_hash_interruptible_operation_t *operation) +{ + if (operation->id == 0) { + /* The object has (apparently) been initialized but it is not (yet) + * in use. It's ok to call abort on such an object, and there's + * nothing to do. */ + return PSA_SUCCESS; } -exit: - if (status != PSA_SUCCESS) { - psa_cipher_abort(operation); - } + psa_status_t status = PSA_ERROR_CORRUPTION_DETECTED; - unlock_status = psa_unlock_key_slot(slot); + status = psa_driver_wrapper_sign_hash_abort(operation); - return (status == PSA_SUCCESS) ? unlock_status : status; -} + operation->id = 0; -psa_status_t psa_cipher_encrypt_setup(psa_cipher_operation_t *operation, - mbedtls_svc_key_id_t key, - psa_algorithm_t alg) -{ - return psa_cipher_setup(operation, key, alg, MBEDTLS_ENCRYPT); -} + /* Do not clear either the error_occurred or num_ops elements here as they + * only want to be cleared by the application calling abort, not by abort + * being called at completion of an operation. */ -psa_status_t psa_cipher_decrypt_setup(psa_cipher_operation_t *operation, - mbedtls_svc_key_id_t key, - psa_algorithm_t alg) -{ - return psa_cipher_setup(operation, key, alg, MBEDTLS_DECRYPT); + return status; } -psa_status_t psa_cipher_generate_iv(psa_cipher_operation_t *operation, - uint8_t *iv, - size_t iv_size, - size_t *iv_length) +psa_status_t psa_sign_hash_start( + psa_sign_hash_interruptible_operation_t *operation, + mbedtls_svc_key_id_t key, psa_algorithm_t alg, + const uint8_t *hash_external, size_t hash_length) { psa_status_t status = PSA_ERROR_CORRUPTION_DETECTED; - uint8_t local_iv[PSA_CIPHER_IV_MAX_SIZE]; - size_t default_iv_length = 0; + psa_status_t unlock_status = PSA_ERROR_CORRUPTION_DETECTED; + psa_key_slot_t *slot; - if (operation->id == 0) { - status = PSA_ERROR_BAD_STATE; - goto exit; + LOCAL_INPUT_DECLARE(hash_external, hash); + + /* Check that start has not been previously called, or operation has not + * previously errored. */ + if (operation->id != 0 || operation->error_occurred) { + return PSA_ERROR_BAD_STATE; } - if (operation->iv_set || !operation->iv_required) { - status = PSA_ERROR_BAD_STATE; - goto exit; + status = psa_sign_verify_check_alg(0, alg); + if (status != PSA_SUCCESS) { + operation->error_occurred = 1; + return status; } - default_iv_length = operation->default_iv_length; - if (iv_size < default_iv_length) { - status = PSA_ERROR_BUFFER_TOO_SMALL; + status = psa_get_and_lock_key_slot_with_policy(key, &slot, + PSA_KEY_USAGE_SIGN_HASH, + alg); + + if (status != PSA_SUCCESS) { goto exit; } - if (default_iv_length > PSA_CIPHER_IV_MAX_SIZE) { - status = PSA_ERROR_GENERIC_ERROR; + if (!PSA_KEY_TYPE_IS_KEY_PAIR(slot->attr.type)) { + status = PSA_ERROR_INVALID_ARGUMENT; goto exit; } - status = psa_generate_random(local_iv, default_iv_length); + LOCAL_INPUT_ALLOC(hash_external, hash_length, hash); + + /* Ensure ops count gets reset, in case of operation re-use. */ + operation->num_ops = 0; + + status = psa_driver_wrapper_sign_hash_start(operation, &slot->attr, + slot->key.data, + slot->key.bytes, alg, + hash, hash_length); +exit: + if (status != PSA_SUCCESS) { - goto exit; + operation->error_occurred = 1; + psa_sign_hash_abort_internal(operation); } - status = psa_driver_wrapper_cipher_set_iv(operation, - local_iv, default_iv_length); + unlock_status = psa_unregister_read_under_mutex(slot); -exit: - if (status == PSA_SUCCESS) { - memcpy(iv, local_iv, default_iv_length); - *iv_length = default_iv_length; - operation->iv_set = 1; - } else { - *iv_length = 0; - psa_cipher_abort(operation); + if (unlock_status != PSA_SUCCESS) { + operation->error_occurred = 1; } - return status; + LOCAL_INPUT_FREE(hash_external, hash); + + return (status == PSA_SUCCESS) ? unlock_status : status; } -psa_status_t psa_cipher_set_iv(psa_cipher_operation_t *operation, - const uint8_t *iv, - size_t iv_length) + +psa_status_t psa_sign_hash_complete( + psa_sign_hash_interruptible_operation_t *operation, + uint8_t *signature_external, size_t signature_size, + size_t *signature_length) { psa_status_t status = PSA_ERROR_CORRUPTION_DETECTED; - if (operation->id == 0) { - status = PSA_ERROR_BAD_STATE; - goto exit; - } + LOCAL_OUTPUT_DECLARE(signature_external, signature); - if (operation->iv_set || !operation->iv_required) { + *signature_length = 0; + + /* Check that start has been called first, and that operation has not + * previously errored. */ + if (operation->id == 0 || operation->error_occurred) { status = PSA_ERROR_BAD_STATE; goto exit; } - if (iv_length > PSA_CIPHER_IV_MAX_SIZE) { - status = PSA_ERROR_INVALID_ARGUMENT; + /* Immediately reject a zero-length signature buffer. This guarantees that + * signature must be a valid pointer. */ + if (signature_size == 0) { + status = PSA_ERROR_BUFFER_TOO_SMALL; goto exit; } - status = psa_driver_wrapper_cipher_set_iv(operation, - iv, - iv_length); + LOCAL_OUTPUT_ALLOC(signature_external, signature_size, signature); -exit: - if (status == PSA_SUCCESS) { - operation->iv_set = 1; - } else { - psa_cipher_abort(operation); - } - return status; -} + status = psa_driver_wrapper_sign_hash_complete(operation, signature, + signature_size, + signature_length); -psa_status_t psa_cipher_update(psa_cipher_operation_t *operation, - const uint8_t *input, - size_t input_length, - uint8_t *output, - size_t output_size, - size_t *output_length) -{ - psa_status_t status = PSA_ERROR_CORRUPTION_DETECTED; + /* Update ops count with work done. */ + operation->num_ops = psa_driver_wrapper_sign_hash_get_num_ops(operation); - if (operation->id == 0) { - status = PSA_ERROR_BAD_STATE; - goto exit; - } +exit: - if (operation->iv_required && !operation->iv_set) { - status = PSA_ERROR_BAD_STATE; - goto exit; + if (signature != NULL) { + psa_wipe_tag_output_buffer(signature, status, signature_size, + *signature_length); } - status = psa_driver_wrapper_cipher_update(operation, - input, - input_length, - output, - output_size, - output_length); + if (status != PSA_OPERATION_INCOMPLETE) { + if (status != PSA_SUCCESS) { + operation->error_occurred = 1; + } -exit: - if (status != PSA_SUCCESS) { - psa_cipher_abort(operation); + psa_sign_hash_abort_internal(operation); } + LOCAL_OUTPUT_FREE(signature_external, signature); + return status; } -psa_status_t psa_cipher_finish(psa_cipher_operation_t *operation, - uint8_t *output, - size_t output_size, - size_t *output_length) +psa_status_t psa_sign_hash_abort( + psa_sign_hash_interruptible_operation_t *operation) { - psa_status_t status = PSA_ERROR_GENERIC_ERROR; - - if (operation->id == 0) { - status = PSA_ERROR_BAD_STATE; - goto exit; - } + psa_status_t status = PSA_ERROR_CORRUPTION_DETECTED; - if (operation->iv_required && !operation->iv_set) { - status = PSA_ERROR_BAD_STATE; - goto exit; - } + status = psa_sign_hash_abort_internal(operation); - status = psa_driver_wrapper_cipher_finish(operation, - output, - output_size, - output_length); + /* We clear the number of ops done here, so that it is not cleared when + * the operation fails or succeeds, only on manual abort. */ + operation->num_ops = 0; -exit: - if (status == PSA_SUCCESS) { - return psa_cipher_abort(operation); - } else { - *output_length = 0; - (void) psa_cipher_abort(operation); + /* Likewise, failure state. */ + operation->error_occurred = 0; - return status; - } + return status; } -psa_status_t psa_cipher_abort(psa_cipher_operation_t *operation) +static psa_status_t psa_verify_hash_abort_internal( + psa_verify_hash_interruptible_operation_t *operation) { if (operation->id == 0) { /* The object has (apparently) been initialized but it is not (yet) @@ -3547,771 +3624,4307 @@ psa_status_t psa_cipher_abort(psa_cipher_operation_t *operation) return PSA_SUCCESS; } - psa_driver_wrapper_cipher_abort(operation); + psa_status_t status = PSA_ERROR_CORRUPTION_DETECTED; + + status = psa_driver_wrapper_verify_hash_abort(operation); operation->id = 0; - operation->iv_set = 0; - operation->iv_required = 0; - return PSA_SUCCESS; + /* Do not clear either the error_occurred or num_ops elements here as they + * only want to be cleared by the application calling abort, not by abort + * being called at completion of an operation. */ + + return status; } -psa_status_t psa_cipher_encrypt(mbedtls_svc_key_id_t key, - psa_algorithm_t alg, - const uint8_t *input, - size_t input_length, - uint8_t *output, - size_t output_size, - size_t *output_length) +psa_status_t psa_verify_hash_start( + psa_verify_hash_interruptible_operation_t *operation, + mbedtls_svc_key_id_t key, psa_algorithm_t alg, + const uint8_t *hash_external, size_t hash_length, + const uint8_t *signature_external, size_t signature_length) { psa_status_t status = PSA_ERROR_CORRUPTION_DETECTED; psa_status_t unlock_status = PSA_ERROR_CORRUPTION_DETECTED; - psa_key_attributes_t attributes; - psa_key_slot_t *slot = NULL; - uint8_t local_iv[PSA_CIPHER_IV_MAX_SIZE]; - size_t default_iv_length = 0; + psa_key_slot_t *slot; - if (!PSA_ALG_IS_CIPHER(alg)) { - status = PSA_ERROR_INVALID_ARGUMENT; - goto exit; + LOCAL_INPUT_DECLARE(hash_external, hash); + LOCAL_INPUT_DECLARE(signature_external, signature); + + /* Check that start has not been previously called, or operation has not + * previously errored. */ + if (operation->id != 0 || operation->error_occurred) { + return PSA_ERROR_BAD_STATE; + } + + status = psa_sign_verify_check_alg(0, alg); + if (status != PSA_SUCCESS) { + operation->error_occurred = 1; + return status; } status = psa_get_and_lock_key_slot_with_policy(key, &slot, - PSA_KEY_USAGE_ENCRYPT, + PSA_KEY_USAGE_VERIFY_HASH, alg); + if (status != PSA_SUCCESS) { - goto exit; + operation->error_occurred = 1; + return status; } - attributes = (psa_key_attributes_t) { - .core = slot->attr - }; + LOCAL_INPUT_ALLOC(hash_external, hash_length, hash); + LOCAL_INPUT_ALLOC(signature_external, signature_length, signature); - default_iv_length = PSA_CIPHER_IV_LENGTH(slot->attr.type, alg); - if (default_iv_length > PSA_CIPHER_IV_MAX_SIZE) { - status = PSA_ERROR_GENERIC_ERROR; - goto exit; - } + /* Ensure ops count gets reset, in case of operation re-use. */ + operation->num_ops = 0; - if (default_iv_length > 0) { - if (output_size < default_iv_length) { - status = PSA_ERROR_BUFFER_TOO_SMALL; - goto exit; - } + status = psa_driver_wrapper_verify_hash_start(operation, &slot->attr, + slot->key.data, + slot->key.bytes, + alg, hash, hash_length, + signature, signature_length); +#if !defined(MBEDTLS_PSA_ASSUME_EXCLUSIVE_BUFFERS) +exit: +#endif - status = psa_generate_random(local_iv, default_iv_length); - if (status != PSA_SUCCESS) { - goto exit; - } + if (status != PSA_SUCCESS) { + operation->error_occurred = 1; + psa_verify_hash_abort_internal(operation); } - status = psa_driver_wrapper_cipher_encrypt( - &attributes, slot->key.data, slot->key.bytes, - alg, local_iv, default_iv_length, input, input_length, - mbedtls_buffer_offset(output, default_iv_length), - output_size - default_iv_length, output_length); + unlock_status = psa_unregister_read_under_mutex(slot); -exit: - unlock_status = psa_unlock_key_slot(slot); - if (status == PSA_SUCCESS) { - status = unlock_status; + if (unlock_status != PSA_SUCCESS) { + operation->error_occurred = 1; } - if (status == PSA_SUCCESS) { - if (default_iv_length > 0) { - memcpy(output, local_iv, default_iv_length); - } - *output_length += default_iv_length; - } else { - *output_length = 0; - } + LOCAL_INPUT_FREE(hash_external, hash); + LOCAL_INPUT_FREE(signature_external, signature); - return status; + return (status == PSA_SUCCESS) ? unlock_status : status; } -psa_status_t psa_cipher_decrypt(mbedtls_svc_key_id_t key, - psa_algorithm_t alg, - const uint8_t *input, - size_t input_length, - uint8_t *output, - size_t output_size, - size_t *output_length) +psa_status_t psa_verify_hash_complete( + psa_verify_hash_interruptible_operation_t *operation) { psa_status_t status = PSA_ERROR_CORRUPTION_DETECTED; - psa_status_t unlock_status = PSA_ERROR_CORRUPTION_DETECTED; - psa_key_attributes_t attributes; - psa_key_slot_t *slot = NULL; - if (!PSA_ALG_IS_CIPHER(alg)) { - status = PSA_ERROR_INVALID_ARGUMENT; + /* Check that start has been called first, and that operation has not + * previously errored. */ + if (operation->id == 0 || operation->error_occurred) { + status = PSA_ERROR_BAD_STATE; goto exit; } - status = psa_get_and_lock_key_slot_with_policy(key, &slot, - PSA_KEY_USAGE_DECRYPT, - alg); - if (status != PSA_SUCCESS) { - goto exit; - } + status = psa_driver_wrapper_verify_hash_complete(operation); - attributes = (psa_key_attributes_t) { - .core = slot->attr - }; - - if (input_length < PSA_CIPHER_IV_LENGTH(slot->attr.type, alg)) { - status = PSA_ERROR_INVALID_ARGUMENT; - goto exit; - } - - status = psa_driver_wrapper_cipher_decrypt( - &attributes, slot->key.data, slot->key.bytes, - alg, input, input_length, - output, output_size, output_length); + /* Update ops count with work done. */ + operation->num_ops = psa_driver_wrapper_verify_hash_get_num_ops( + operation); exit: - unlock_status = psa_unlock_key_slot(slot); - if (status == PSA_SUCCESS) { - status = unlock_status; - } - if (status != PSA_SUCCESS) { - *output_length = 0; + if (status != PSA_OPERATION_INCOMPLETE) { + if (status != PSA_SUCCESS) { + operation->error_occurred = 1; + } + + psa_verify_hash_abort_internal(operation); } return status; } +psa_status_t psa_verify_hash_abort( + psa_verify_hash_interruptible_operation_t *operation) +{ + psa_status_t status = PSA_ERROR_CORRUPTION_DETECTED; + + status = psa_verify_hash_abort_internal(operation); + + /* We clear the number of ops done here, so that it is not cleared when + * the operation fails or succeeds, only on manual abort. */ + operation->num_ops = 0; + + /* Likewise, failure state. */ + operation->error_occurred = 0; + + return status; +} /****************************************************************/ -/* AEAD */ +/* Asymmetric interruptible cryptography internal */ +/* implementations */ /****************************************************************/ -psa_status_t psa_aead_encrypt(mbedtls_svc_key_id_t key, - psa_algorithm_t alg, - const uint8_t *nonce, - size_t nonce_length, - const uint8_t *additional_data, - size_t additional_data_length, - const uint8_t *plaintext, - size_t plaintext_length, - uint8_t *ciphertext, - size_t ciphertext_size, - size_t *ciphertext_length) +void mbedtls_psa_interruptible_set_max_ops(uint32_t max_ops) { - psa_status_t status = PSA_ERROR_CORRUPTION_DETECTED; - psa_key_slot_t *slot; - - *ciphertext_length = 0; - if (!PSA_ALG_IS_AEAD(alg) || PSA_ALG_IS_WILDCARD(alg)) { - return PSA_ERROR_NOT_SUPPORTED; - } +#if (defined(MBEDTLS_PSA_BUILTIN_ALG_ECDSA) || \ + defined(MBEDTLS_PSA_BUILTIN_ALG_DETERMINISTIC_ECDSA)) && \ + defined(MBEDTLS_ECP_RESTARTABLE) - status = psa_get_and_lock_key_slot_with_policy( - key, &slot, PSA_KEY_USAGE_ENCRYPT, alg); - if (status != PSA_SUCCESS) { - return status; + /* Internal implementation uses zero to indicate infinite number max ops, + * therefore avoid this value, and set to minimum possible. */ + if (max_ops == 0) { + max_ops = 1; } - psa_key_attributes_t attributes = { - .core = slot->attr - }; + mbedtls_ecp_set_max_ops(max_ops); +#else + (void) max_ops; +#endif /* defined(MBEDTLS_PSA_BUILTIN_ALG_ECDSA) || + * defined(MBEDTLS_PSA_BUILTIN_ALG_DETERMINISTIC_ECDSA) && + * defined( MBEDTLS_ECP_RESTARTABLE ) */ +} - status = psa_driver_wrapper_aead_encrypt( - &attributes, slot->key.data, slot->key.bytes, - alg, - nonce, nonce_length, - additional_data, additional_data_length, - plaintext, plaintext_length, - ciphertext, ciphertext_size, ciphertext_length); +uint32_t mbedtls_psa_sign_hash_get_num_ops( + const mbedtls_psa_sign_hash_interruptible_operation_t *operation) +{ +#if (defined(MBEDTLS_PSA_BUILTIN_ALG_ECDSA) || \ + defined(MBEDTLS_PSA_BUILTIN_ALG_DETERMINISTIC_ECDSA)) && \ + defined(MBEDTLS_ECP_RESTARTABLE) - if (status != PSA_SUCCESS && ciphertext_size != 0) { - memset(ciphertext, 0, ciphertext_size); - } + return operation->num_ops; +#else + (void) operation; + return 0; +#endif /* defined(MBEDTLS_PSA_BUILTIN_ALG_ECDSA) || + * defined(MBEDTLS_PSA_BUILTIN_ALG_DETERMINISTIC_ECDSA) && + * defined( MBEDTLS_ECP_RESTARTABLE ) */ +} - psa_unlock_key_slot(slot); +uint32_t mbedtls_psa_verify_hash_get_num_ops( + const mbedtls_psa_verify_hash_interruptible_operation_t *operation) +{ + #if (defined(MBEDTLS_PSA_BUILTIN_ALG_ECDSA) || \ + defined(MBEDTLS_PSA_BUILTIN_ALG_DETERMINISTIC_ECDSA)) && \ + defined(MBEDTLS_ECP_RESTARTABLE) - return status; + return operation->num_ops; +#else + (void) operation; + return 0; +#endif /* defined(MBEDTLS_PSA_BUILTIN_ALG_ECDSA) || + * defined(MBEDTLS_PSA_BUILTIN_ALG_DETERMINISTIC_ECDSA) && + * defined( MBEDTLS_ECP_RESTARTABLE ) */ } -psa_status_t psa_aead_decrypt(mbedtls_svc_key_id_t key, - psa_algorithm_t alg, - const uint8_t *nonce, - size_t nonce_length, - const uint8_t *additional_data, - size_t additional_data_length, - const uint8_t *ciphertext, - size_t ciphertext_length, - uint8_t *plaintext, - size_t plaintext_size, - size_t *plaintext_length) +psa_status_t mbedtls_psa_sign_hash_start( + mbedtls_psa_sign_hash_interruptible_operation_t *operation, + const psa_key_attributes_t *attributes, const uint8_t *key_buffer, + size_t key_buffer_size, psa_algorithm_t alg, + const uint8_t *hash, size_t hash_length) { psa_status_t status = PSA_ERROR_CORRUPTION_DETECTED; - psa_key_slot_t *slot; + size_t required_hash_length; - *plaintext_length = 0; + if (!PSA_KEY_TYPE_IS_ECC(attributes->type)) { + return PSA_ERROR_NOT_SUPPORTED; + } - if (!PSA_ALG_IS_AEAD(alg) || PSA_ALG_IS_WILDCARD(alg)) { + if (!PSA_ALG_IS_ECDSA(alg)) { return PSA_ERROR_NOT_SUPPORTED; } - status = psa_get_and_lock_key_slot_with_policy( - key, &slot, PSA_KEY_USAGE_DECRYPT, alg); +#if (defined(MBEDTLS_PSA_BUILTIN_ALG_ECDSA) || \ + defined(MBEDTLS_PSA_BUILTIN_ALG_DETERMINISTIC_ECDSA)) && \ + defined(MBEDTLS_ECP_RESTARTABLE) + + mbedtls_ecdsa_restart_init(&operation->restart_ctx); + + /* Ensure num_ops is zero'ed in case of context re-use. */ + operation->num_ops = 0; + + status = mbedtls_psa_ecp_load_representation(attributes->type, + attributes->bits, + key_buffer, + key_buffer_size, + &operation->ctx); + if (status != PSA_SUCCESS) { return status; } - psa_key_attributes_t attributes = { - .core = slot->attr - }; + operation->coordinate_bytes = PSA_BITS_TO_BYTES( + operation->ctx->grp.nbits); - status = psa_driver_wrapper_aead_decrypt( - &attributes, slot->key.data, slot->key.bytes, - alg, - nonce, nonce_length, - additional_data, additional_data_length, - ciphertext, ciphertext_length, - plaintext, plaintext_size, plaintext_length); + psa_algorithm_t hash_alg = PSA_ALG_SIGN_GET_HASH(alg); + operation->md_alg = mbedtls_md_type_from_psa_alg(hash_alg); + operation->alg = alg; - if (status != PSA_SUCCESS && plaintext_size != 0) { - memset(plaintext, 0, plaintext_size); + /* We only need to store the same length of hash as the private key size + * here, it would be truncated by the internal implementation anyway. */ + required_hash_length = (hash_length < operation->coordinate_bytes ? + hash_length : operation->coordinate_bytes); + + if (required_hash_length > sizeof(operation->hash)) { + /* Shouldn't happen, but better safe than sorry. */ + return PSA_ERROR_CORRUPTION_DETECTED; } - psa_unlock_key_slot(slot); + memcpy(operation->hash, hash, required_hash_length); + operation->hash_length = required_hash_length; - return status; -} + return PSA_SUCCESS; -/****************************************************************/ -/* Generators */ -/****************************************************************/ +#else + (void) operation; + (void) key_buffer; + (void) key_buffer_size; + (void) alg; + (void) hash; + (void) hash_length; + (void) status; + (void) required_hash_length; -#if defined(MBEDTLS_PSA_BUILTIN_ALG_HKDF) || \ - defined(MBEDTLS_PSA_BUILTIN_ALG_TLS12_PRF) || \ - defined(MBEDTLS_PSA_BUILTIN_ALG_TLS12_PSK_TO_MS) -#define AT_LEAST_ONE_BUILTIN_KDF -#endif /* At least one builtin KDF */ + return PSA_ERROR_NOT_SUPPORTED; +#endif /* defined(MBEDTLS_PSA_BUILTIN_ALG_ECDSA) || + * defined(MBEDTLS_PSA_BUILTIN_ALG_DETERMINISTIC_ECDSA) && + * defined( MBEDTLS_ECP_RESTARTABLE ) */ +} -#if defined(MBEDTLS_PSA_BUILTIN_ALG_HKDF) || \ - defined(MBEDTLS_PSA_BUILTIN_ALG_TLS12_PRF) || \ - defined(MBEDTLS_PSA_BUILTIN_ALG_TLS12_PSK_TO_MS) -static psa_status_t psa_key_derivation_start_hmac( - psa_mac_operation_t *operation, - psa_algorithm_t hash_alg, - const uint8_t *hmac_key, - size_t hmac_key_length) +psa_status_t mbedtls_psa_sign_hash_complete( + mbedtls_psa_sign_hash_interruptible_operation_t *operation, + uint8_t *signature, size_t signature_size, + size_t *signature_length) { +#if (defined(MBEDTLS_PSA_BUILTIN_ALG_ECDSA) || \ + defined(MBEDTLS_PSA_BUILTIN_ALG_DETERMINISTIC_ECDSA)) && \ + defined(MBEDTLS_ECP_RESTARTABLE) + psa_status_t status = PSA_ERROR_CORRUPTION_DETECTED; - psa_key_attributes_t attributes = PSA_KEY_ATTRIBUTES_INIT; - psa_set_key_type(&attributes, PSA_KEY_TYPE_HMAC); - psa_set_key_bits(&attributes, PSA_BYTES_TO_BITS(hmac_key_length)); - psa_set_key_usage_flags(&attributes, PSA_KEY_USAGE_SIGN_HASH); + mbedtls_mpi r; + mbedtls_mpi s; - operation->is_sign = 1; - operation->mac_size = PSA_HASH_LENGTH(hash_alg); + mbedtls_mpi_init(&r); + mbedtls_mpi_init(&s); - status = psa_driver_wrapper_mac_sign_setup(operation, - &attributes, - hmac_key, hmac_key_length, - PSA_ALG_HMAC(hash_alg)); + /* Ensure max_ops is set to the current value (or default). */ + mbedtls_psa_interruptible_set_max_ops(psa_interruptible_get_max_ops()); - psa_reset_key_attributes(&attributes); - return status; -} -#endif /* KDF algorithms reliant on HMAC */ + if (signature_size < 2 * operation->coordinate_bytes) { + status = PSA_ERROR_BUFFER_TOO_SMALL; + goto exit; + } -#define HKDF_STATE_INIT 0 /* no input yet */ -#define HKDF_STATE_STARTED 1 /* got salt */ -#define HKDF_STATE_KEYED 2 /* got key */ -#define HKDF_STATE_OUTPUT 3 /* output started */ + if (PSA_ALG_ECDSA_IS_DETERMINISTIC(operation->alg)) { -static psa_algorithm_t psa_key_derivation_get_kdf_alg( - const psa_key_derivation_operation_t *operation) -{ - if (PSA_ALG_IS_KEY_AGREEMENT(operation->alg)) { - return PSA_ALG_KEY_AGREEMENT_GET_KDF(operation->alg); +#if defined(MBEDTLS_PSA_BUILTIN_ALG_DETERMINISTIC_ECDSA) + status = mbedtls_to_psa_error( + mbedtls_ecdsa_sign_det_restartable(&operation->ctx->grp, + &r, + &s, + &operation->ctx->d, + operation->hash, + operation->hash_length, + operation->md_alg, + mbedtls_psa_get_random, + MBEDTLS_PSA_RANDOM_STATE, + &operation->restart_ctx)); +#else /* defined(MBEDTLS_PSA_BUILTIN_ALG_DETERMINISTIC_ECDSA) */ + status = PSA_ERROR_NOT_SUPPORTED; + goto exit; +#endif /* defined(MBEDTLS_PSA_BUILTIN_ALG_DETERMINISTIC_ECDSA) */ } else { - return operation->alg; - } -} + status = mbedtls_to_psa_error( + mbedtls_ecdsa_sign_restartable(&operation->ctx->grp, + &r, + &s, + &operation->ctx->d, + operation->hash, + operation->hash_length, + mbedtls_psa_get_random, + MBEDTLS_PSA_RANDOM_STATE, + mbedtls_psa_get_random, + MBEDTLS_PSA_RANDOM_STATE, + &operation->restart_ctx)); + } + + /* Hide the fact that the restart context only holds a delta of number of + * ops done during the last operation, not an absolute value. */ + operation->num_ops += operation->restart_ctx.ecp.ops_done; -psa_status_t psa_key_derivation_abort(psa_key_derivation_operation_t *operation) -{ - psa_status_t status = PSA_SUCCESS; - psa_algorithm_t kdf_alg = psa_key_derivation_get_kdf_alg(operation); - if (kdf_alg == 0) { - /* The object has (apparently) been initialized but it is not - * in use. It's ok to call abort on such an object, and there's - * nothing to do. */ - } else -#if defined(MBEDTLS_PSA_BUILTIN_ALG_HKDF) - if (PSA_ALG_IS_HKDF(kdf_alg)) { - mbedtls_free(operation->ctx.hkdf.info); - status = psa_mac_abort(&operation->ctx.hkdf.hmac); - } else -#endif /* defined(MBEDTLS_PSA_BUILTIN_ALG_HKDF */ -#if defined(MBEDTLS_PSA_BUILTIN_ALG_TLS12_PRF) || \ - defined(MBEDTLS_PSA_BUILTIN_ALG_TLS12_PSK_TO_MS) - if (PSA_ALG_IS_TLS12_PRF(kdf_alg) || - /* TLS-1.2 PSK-to-MS KDF uses the same core as TLS-1.2 PRF */ - PSA_ALG_IS_TLS12_PSK_TO_MS(kdf_alg)) { - if (operation->ctx.tls12_prf.secret != NULL) { - mbedtls_platform_zeroize(operation->ctx.tls12_prf.secret, - operation->ctx.tls12_prf.secret_length); - mbedtls_free(operation->ctx.tls12_prf.secret); - } + if (status == PSA_SUCCESS) { + status = mbedtls_to_psa_error( + mbedtls_mpi_write_binary(&r, + signature, + operation->coordinate_bytes) + ); - if (operation->ctx.tls12_prf.seed != NULL) { - mbedtls_platform_zeroize(operation->ctx.tls12_prf.seed, - operation->ctx.tls12_prf.seed_length); - mbedtls_free(operation->ctx.tls12_prf.seed); + if (status != PSA_SUCCESS) { + goto exit; } - if (operation->ctx.tls12_prf.label != NULL) { - mbedtls_platform_zeroize(operation->ctx.tls12_prf.label, - operation->ctx.tls12_prf.label_length); - mbedtls_free(operation->ctx.tls12_prf.label); + status = mbedtls_to_psa_error( + mbedtls_mpi_write_binary(&s, + signature + + operation->coordinate_bytes, + operation->coordinate_bytes) + ); + + if (status != PSA_SUCCESS) { + goto exit; } - status = PSA_SUCCESS; + *signature_length = operation->coordinate_bytes * 2; - /* We leave the fields Ai and output_block to be erased safely by the - * mbedtls_platform_zeroize() in the end of this function. */ - } else -#endif /* defined(MBEDTLS_PSA_BUILTIN_ALG_TLS12_PRF) || - * defined(MBEDTLS_PSA_BUILTIN_ALG_TLS12_PSK_TO_MS) */ - { - status = PSA_ERROR_BAD_STATE; + status = PSA_SUCCESS; } - mbedtls_platform_zeroize(operation, sizeof(*operation)); + +exit: + + mbedtls_mpi_free(&r); + mbedtls_mpi_free(&s); return status; + + #else + + (void) operation; + (void) signature; + (void) signature_size; + (void) signature_length; + + return PSA_ERROR_NOT_SUPPORTED; + +#endif /* defined(MBEDTLS_PSA_BUILTIN_ALG_ECDSA) || + * defined(MBEDTLS_PSA_BUILTIN_ALG_DETERMINISTIC_ECDSA) && + * defined( MBEDTLS_ECP_RESTARTABLE ) */ } -psa_status_t psa_key_derivation_get_capacity(const psa_key_derivation_operation_t *operation, - size_t *capacity) +psa_status_t mbedtls_psa_sign_hash_abort( + mbedtls_psa_sign_hash_interruptible_operation_t *operation) { - if (operation->alg == 0) { - /* This is a blank key derivation operation. */ - return PSA_ERROR_BAD_STATE; + +#if (defined(MBEDTLS_PSA_BUILTIN_ALG_ECDSA) || \ + defined(MBEDTLS_PSA_BUILTIN_ALG_DETERMINISTIC_ECDSA)) && \ + defined(MBEDTLS_ECP_RESTARTABLE) + + if (operation->ctx) { + mbedtls_ecdsa_free(operation->ctx); + mbedtls_free(operation->ctx); + operation->ctx = NULL; } - *capacity = operation->capacity; + mbedtls_ecdsa_restart_free(&operation->restart_ctx); + + operation->num_ops = 0; + return PSA_SUCCESS; + +#else + + (void) operation; + + return PSA_ERROR_NOT_SUPPORTED; + +#endif /* defined(MBEDTLS_PSA_BUILTIN_ALG_ECDSA) || + * defined(MBEDTLS_PSA_BUILTIN_ALG_DETERMINISTIC_ECDSA) && + * defined( MBEDTLS_ECP_RESTARTABLE ) */ } -psa_status_t psa_key_derivation_set_capacity(psa_key_derivation_operation_t *operation, - size_t capacity) +psa_status_t mbedtls_psa_verify_hash_start( + mbedtls_psa_verify_hash_interruptible_operation_t *operation, + const psa_key_attributes_t *attributes, + const uint8_t *key_buffer, size_t key_buffer_size, + psa_algorithm_t alg, + const uint8_t *hash, size_t hash_length, + const uint8_t *signature, size_t signature_length) { - if (operation->alg == 0) { - return PSA_ERROR_BAD_STATE; + psa_status_t status = PSA_ERROR_CORRUPTION_DETECTED; + size_t coordinate_bytes = 0; + size_t required_hash_length = 0; + + if (!PSA_KEY_TYPE_IS_ECC(attributes->type)) { + return PSA_ERROR_NOT_SUPPORTED; } - if (capacity > operation->capacity) { - return PSA_ERROR_INVALID_ARGUMENT; + + if (!PSA_ALG_IS_ECDSA(alg)) { + return PSA_ERROR_NOT_SUPPORTED; } - operation->capacity = capacity; - return PSA_SUCCESS; -} -#if defined(MBEDTLS_PSA_BUILTIN_ALG_HKDF) -/* Read some bytes from an HKDF-based operation. This performs a chunk - * of the expand phase of the HKDF algorithm. */ -static psa_status_t psa_key_derivation_hkdf_read(psa_hkdf_key_derivation_t *hkdf, - psa_algorithm_t hash_alg, - uint8_t *output, - size_t output_length) -{ - uint8_t hash_length = PSA_HASH_LENGTH(hash_alg); - size_t hmac_output_length; - psa_status_t status; +#if (defined(MBEDTLS_PSA_BUILTIN_ALG_ECDSA) || \ + defined(MBEDTLS_PSA_BUILTIN_ALG_DETERMINISTIC_ECDSA)) && \ + defined(MBEDTLS_ECP_RESTARTABLE) - if (hkdf->state < HKDF_STATE_KEYED || !hkdf->info_set) { - return PSA_ERROR_BAD_STATE; + mbedtls_ecdsa_restart_init(&operation->restart_ctx); + mbedtls_mpi_init(&operation->r); + mbedtls_mpi_init(&operation->s); + + /* Ensure num_ops is zero'ed in case of context re-use. */ + operation->num_ops = 0; + + status = mbedtls_psa_ecp_load_representation(attributes->type, + attributes->bits, + key_buffer, + key_buffer_size, + &operation->ctx); + + if (status != PSA_SUCCESS) { + return status; } - hkdf->state = HKDF_STATE_OUTPUT; - while (output_length != 0) { - /* Copy what remains of the current block */ - uint8_t n = hash_length - hkdf->offset_in_block; - if (n > output_length) { - n = (uint8_t) output_length; - } - memcpy(output, hkdf->output_block + hkdf->offset_in_block, n); - output += n; - output_length -= n; - hkdf->offset_in_block += n; - if (output_length == 0) { - break; - } - /* We can't be wanting more output after block 0xff, otherwise - * the capacity check in psa_key_derivation_output_bytes() would have - * prevented this call. It could happen only if the operation - * object was corrupted or if this function is called directly - * inside the library. */ - if (hkdf->block_number == 0xff) { - return PSA_ERROR_BAD_STATE; - } - - /* We need a new block */ - ++hkdf->block_number; - hkdf->offset_in_block = 0; - - status = psa_key_derivation_start_hmac(&hkdf->hmac, - hash_alg, - hkdf->prk, - hash_length); - if (status != PSA_SUCCESS) { - return status; - } + coordinate_bytes = PSA_BITS_TO_BYTES(operation->ctx->grp.nbits); - if (hkdf->block_number != 1) { - status = psa_mac_update(&hkdf->hmac, - hkdf->output_block, - hash_length); - if (status != PSA_SUCCESS) { - return status; - } - } - status = psa_mac_update(&hkdf->hmac, - hkdf->info, - hkdf->info_length); - if (status != PSA_SUCCESS) { - return status; - } - status = psa_mac_update(&hkdf->hmac, - &hkdf->block_number, 1); - if (status != PSA_SUCCESS) { - return status; - } - status = psa_mac_sign_finish(&hkdf->hmac, - hkdf->output_block, - sizeof(hkdf->output_block), - &hmac_output_length); - if (status != PSA_SUCCESS) { - return status; - } + if (signature_length != 2 * coordinate_bytes) { + return PSA_ERROR_INVALID_SIGNATURE; } - return PSA_SUCCESS; -} -#endif /* MBEDTLS_PSA_BUILTIN_ALG_HKDF */ - -#if defined(MBEDTLS_PSA_BUILTIN_ALG_TLS12_PRF) || \ - defined(MBEDTLS_PSA_BUILTIN_ALG_TLS12_PSK_TO_MS) -static psa_status_t psa_key_derivation_tls12_prf_generate_next_block( - psa_tls12_prf_key_derivation_t *tls12_prf, - psa_algorithm_t alg) -{ - psa_algorithm_t hash_alg = PSA_ALG_HKDF_GET_HASH(alg); - uint8_t hash_length = PSA_HASH_LENGTH(hash_alg); - psa_mac_operation_t hmac = PSA_MAC_OPERATION_INIT; - size_t hmac_output_length; - psa_status_t status, cleanup_status; + status = mbedtls_to_psa_error( + mbedtls_mpi_read_binary(&operation->r, + signature, + coordinate_bytes)); - /* We can't be wanting more output after block 0xff, otherwise - * the capacity check in psa_key_derivation_output_bytes() would have - * prevented this call. It could happen only if the operation - * object was corrupted or if this function is called directly - * inside the library. */ - if (tls12_prf->block_number == 0xff) { - return PSA_ERROR_CORRUPTION_DETECTED; + if (status != PSA_SUCCESS) { + return status; } - /* We need a new block */ - ++tls12_prf->block_number; - tls12_prf->left_in_block = hash_length; - - /* Recall the definition of the TLS-1.2-PRF from RFC 5246: - * - * PRF(secret, label, seed) = P_(secret, label + seed) - * - * P_hash(secret, seed) = HMAC_hash(secret, A(1) + seed) + - * HMAC_hash(secret, A(2) + seed) + - * HMAC_hash(secret, A(3) + seed) + ... - * - * A(0) = seed - * A(i) = HMAC_hash(secret, A(i-1)) - * - * The `psa_tls12_prf_key_derivation` structure saves the block - * `HMAC_hash(secret, A(i) + seed)` from which the output - * is currently extracted as `output_block` and where i is - * `block_number`. - */ + status = mbedtls_to_psa_error( + mbedtls_mpi_read_binary(&operation->s, + signature + + coordinate_bytes, + coordinate_bytes)); - status = psa_key_derivation_start_hmac(&hmac, - hash_alg, - tls12_prf->secret, - tls12_prf->secret_length); if (status != PSA_SUCCESS) { - goto cleanup; + return status; } - /* Calculate A(i) where i = tls12_prf->block_number. */ - if (tls12_prf->block_number == 1) { - /* A(1) = HMAC_hash(secret, A(0)), where A(0) = seed. (The RFC overloads - * the variable seed and in this instance means it in the context of the - * P_hash function, where seed = label + seed.) */ - status = psa_mac_update(&hmac, - tls12_prf->label, - tls12_prf->label_length); - if (status != PSA_SUCCESS) { - goto cleanup; - } - status = psa_mac_update(&hmac, - tls12_prf->seed, - tls12_prf->seed_length); - if (status != PSA_SUCCESS) { - goto cleanup; - } - } else { - /* A(i) = HMAC_hash(secret, A(i-1)) */ - status = psa_mac_update(&hmac, tls12_prf->Ai, hash_length); - if (status != PSA_SUCCESS) { - goto cleanup; - } - } + status = mbedtls_psa_ecp_load_public_part(operation->ctx); - status = psa_mac_sign_finish(&hmac, - tls12_prf->Ai, hash_length, - &hmac_output_length); - if (hmac_output_length != hash_length) { - status = PSA_ERROR_CORRUPTION_DETECTED; - } if (status != PSA_SUCCESS) { - goto cleanup; + return status; } - /* Calculate HMAC_hash(secret, A(i) + label + seed). */ - status = psa_key_derivation_start_hmac(&hmac, - hash_alg, - tls12_prf->secret, - tls12_prf->secret_length); - if (status != PSA_SUCCESS) { - goto cleanup; - } - status = psa_mac_update(&hmac, tls12_prf->Ai, hash_length); - if (status != PSA_SUCCESS) { - goto cleanup; - } - status = psa_mac_update(&hmac, tls12_prf->label, tls12_prf->label_length); - if (status != PSA_SUCCESS) { - goto cleanup; - } - status = psa_mac_update(&hmac, tls12_prf->seed, tls12_prf->seed_length); - if (status != PSA_SUCCESS) { - goto cleanup; - } - status = psa_mac_sign_finish(&hmac, - tls12_prf->output_block, hash_length, - &hmac_output_length); - if (status != PSA_SUCCESS) { - goto cleanup; + /* We only need to store the same length of hash as the private key size + * here, it would be truncated by the internal implementation anyway. */ + required_hash_length = (hash_length < coordinate_bytes ? hash_length : + coordinate_bytes); + + if (required_hash_length > sizeof(operation->hash)) { + /* Shouldn't happen, but better safe than sorry. */ + return PSA_ERROR_CORRUPTION_DETECTED; } + memcpy(operation->hash, hash, required_hash_length); + operation->hash_length = required_hash_length; -cleanup: - cleanup_status = psa_mac_abort(&hmac); - if (status == PSA_SUCCESS && cleanup_status != PSA_SUCCESS) { - status = cleanup_status; - } + return PSA_SUCCESS; +#else + (void) operation; + (void) key_buffer; + (void) key_buffer_size; + (void) alg; + (void) hash; + (void) hash_length; + (void) signature; + (void) signature_length; + (void) status; + (void) coordinate_bytes; + (void) required_hash_length; - return status; + return PSA_ERROR_NOT_SUPPORTED; +#endif /* defined(MBEDTLS_PSA_BUILTIN_ALG_ECDSA) || + * defined(MBEDTLS_PSA_BUILTIN_ALG_DETERMINISTIC_ECDSA) && + * defined( MBEDTLS_ECP_RESTARTABLE ) */ } -static psa_status_t psa_key_derivation_tls12_prf_read( - psa_tls12_prf_key_derivation_t *tls12_prf, - psa_algorithm_t alg, - uint8_t *output, - size_t output_length) +psa_status_t mbedtls_psa_verify_hash_complete( + mbedtls_psa_verify_hash_interruptible_operation_t *operation) { - psa_algorithm_t hash_alg = PSA_ALG_TLS12_PRF_GET_HASH(alg); - uint8_t hash_length = PSA_HASH_LENGTH(hash_alg); - psa_status_t status; - uint8_t offset, length; - switch (tls12_prf->state) { - case PSA_TLS12_PRF_STATE_LABEL_SET: - tls12_prf->state = PSA_TLS12_PRF_STATE_OUTPUT; - break; - case PSA_TLS12_PRF_STATE_OUTPUT: - break; - default: - return PSA_ERROR_BAD_STATE; - } +#if (defined(MBEDTLS_PSA_BUILTIN_ALG_ECDSA) || \ + defined(MBEDTLS_PSA_BUILTIN_ALG_DETERMINISTIC_ECDSA)) && \ + defined(MBEDTLS_ECP_RESTARTABLE) - while (output_length != 0) { - /* Check if we have fully processed the current block. */ - if (tls12_prf->left_in_block == 0) { - status = psa_key_derivation_tls12_prf_generate_next_block(tls12_prf, - alg); - if (status != PSA_SUCCESS) { - return status; - } + psa_status_t status = PSA_ERROR_CORRUPTION_DETECTED; - continue; - } + /* Ensure max_ops is set to the current value (or default). */ + mbedtls_psa_interruptible_set_max_ops(psa_interruptible_get_max_ops()); - if (tls12_prf->left_in_block > output_length) { - length = (uint8_t) output_length; - } else { - length = tls12_prf->left_in_block; - } + status = mbedtls_to_psa_error( + mbedtls_ecdsa_verify_restartable(&operation->ctx->grp, + operation->hash, + operation->hash_length, + &operation->ctx->Q, + &operation->r, + &operation->s, + &operation->restart_ctx)); + + /* Hide the fact that the restart context only holds a delta of number of + * ops done during the last operation, not an absolute value. */ + operation->num_ops += operation->restart_ctx.ecp.ops_done; - offset = hash_length - tls12_prf->left_in_block; - memcpy(output, tls12_prf->output_block + offset, length); - output += length; - output_length -= length; - tls12_prf->left_in_block -= length; - } + return status; +#else + (void) operation; - return PSA_SUCCESS; + return PSA_ERROR_NOT_SUPPORTED; + +#endif /* defined(MBEDTLS_PSA_BUILTIN_ALG_ECDSA) || + * defined(MBEDTLS_PSA_BUILTIN_ALG_DETERMINISTIC_ECDSA) && + * defined( MBEDTLS_ECP_RESTARTABLE ) */ } -#endif /* MBEDTLS_PSA_BUILTIN_ALG_TLS12_PRF || - * MBEDTLS_PSA_BUILTIN_ALG_TLS12_PSK_TO_MS */ -psa_status_t psa_key_derivation_output_bytes( - psa_key_derivation_operation_t *operation, - uint8_t *output, - size_t output_length) +psa_status_t mbedtls_psa_verify_hash_abort( + mbedtls_psa_verify_hash_interruptible_operation_t *operation) { - psa_status_t status; - psa_algorithm_t kdf_alg = psa_key_derivation_get_kdf_alg(operation); - if (operation->alg == 0) { - /* This is a blank operation. */ - return PSA_ERROR_BAD_STATE; - } +#if (defined(MBEDTLS_PSA_BUILTIN_ALG_ECDSA) || \ + defined(MBEDTLS_PSA_BUILTIN_ALG_DETERMINISTIC_ECDSA)) && \ + defined(MBEDTLS_ECP_RESTARTABLE) - if (output_length > operation->capacity) { - operation->capacity = 0; - /* Go through the error path to wipe all confidential data now - * that the operation object is useless. */ - status = PSA_ERROR_INSUFFICIENT_DATA; - goto exit; + if (operation->ctx) { + mbedtls_ecdsa_free(operation->ctx); + mbedtls_free(operation->ctx); + operation->ctx = NULL; } - if (output_length == 0 && operation->capacity == 0) { - /* Edge case: this is a finished operation, and 0 bytes - * were requested. The right error in this case could - * be either INSUFFICIENT_CAPACITY or BAD_STATE. Return - * INSUFFICIENT_CAPACITY, which is right for a finished - * operation, for consistency with the case when - * output_length > 0. */ - return PSA_ERROR_INSUFFICIENT_DATA; + + mbedtls_ecdsa_restart_free(&operation->restart_ctx); + + operation->num_ops = 0; + + mbedtls_mpi_free(&operation->r); + mbedtls_mpi_free(&operation->s); + + return PSA_SUCCESS; + +#else + (void) operation; + + return PSA_ERROR_NOT_SUPPORTED; + +#endif /* defined(MBEDTLS_PSA_BUILTIN_ALG_ECDSA) || + * defined(MBEDTLS_PSA_BUILTIN_ALG_DETERMINISTIC_ECDSA) && + * defined( MBEDTLS_ECP_RESTARTABLE ) */ +} + +static psa_status_t psa_generate_random_internal(uint8_t *output, + size_t output_size) +{ + GUARD_MODULE_INITIALIZED; + +#if defined(MBEDTLS_PSA_CRYPTO_EXTERNAL_RNG) + + psa_status_t status; + size_t output_length = 0; + status = mbedtls_psa_external_get_random(&global_data.rng, + output, output_size, + &output_length); + if (status != PSA_SUCCESS) { + return status; + } + /* Breaking up a request into smaller chunks is currently not supported + * for the external RNG interface. */ + if (output_length != output_size) { + return PSA_ERROR_INSUFFICIENT_ENTROPY; + } + return PSA_SUCCESS; + +#else /* MBEDTLS_PSA_CRYPTO_EXTERNAL_RNG */ + + while (output_size > 0) { + int ret = MBEDTLS_ERR_PLATFORM_FEATURE_UNSUPPORTED; + size_t request_size = + (output_size > MBEDTLS_PSA_RANDOM_MAX_REQUEST ? + MBEDTLS_PSA_RANDOM_MAX_REQUEST : + output_size); +#if defined(MBEDTLS_CTR_DRBG_C) + ret = mbedtls_ctr_drbg_random(&global_data.rng.drbg, output, request_size); +#elif defined(MBEDTLS_HMAC_DRBG_C) + ret = mbedtls_hmac_drbg_random(&global_data.rng.drbg, output, request_size); +#endif /* !MBEDTLS_CTR_DRBG_C && !MBEDTLS_HMAC_DRBG_C */ + if (ret != 0) { + return mbedtls_to_psa_error(ret); + } + output_size -= request_size; + output += request_size; + } + return PSA_SUCCESS; +#endif /* MBEDTLS_PSA_CRYPTO_EXTERNAL_RNG */ +} + + +/****************************************************************/ +/* Symmetric cryptography */ +/****************************************************************/ + +static psa_status_t psa_cipher_setup(psa_cipher_operation_t *operation, + mbedtls_svc_key_id_t key, + psa_algorithm_t alg, + mbedtls_operation_t cipher_operation) +{ + psa_status_t status = PSA_ERROR_CORRUPTION_DETECTED; + psa_status_t unlock_status = PSA_ERROR_CORRUPTION_DETECTED; + psa_key_slot_t *slot = NULL; + psa_key_usage_t usage = (cipher_operation == MBEDTLS_ENCRYPT ? + PSA_KEY_USAGE_ENCRYPT : + PSA_KEY_USAGE_DECRYPT); + + /* A context must be freshly initialized before it can be set up. */ + if (operation->id != 0) { + status = PSA_ERROR_BAD_STATE; + goto exit; + } + + if (!PSA_ALG_IS_CIPHER(alg)) { + status = PSA_ERROR_INVALID_ARGUMENT; + goto exit; + } + + status = psa_get_and_lock_key_slot_with_policy(key, &slot, usage, alg); + if (status != PSA_SUCCESS) { + goto exit; + } + + /* Initialize the operation struct members, except for id. The id member + * is used to indicate to psa_cipher_abort that there are resources to free, + * so we only set it (in the driver wrapper) after resources have been + * allocated/initialized. */ + operation->iv_set = 0; + if (alg == PSA_ALG_ECB_NO_PADDING) { + operation->iv_required = 0; + } else { + operation->iv_required = 1; + } + operation->default_iv_length = PSA_CIPHER_IV_LENGTH(slot->attr.type, alg); + + /* Try doing the operation through a driver before using software fallback. */ + if (cipher_operation == MBEDTLS_ENCRYPT) { + status = psa_driver_wrapper_cipher_encrypt_setup(operation, + &slot->attr, + slot->key.data, + slot->key.bytes, + alg); + } else { + status = psa_driver_wrapper_cipher_decrypt_setup(operation, + &slot->attr, + slot->key.data, + slot->key.bytes, + alg); + } + +exit: + if (status != PSA_SUCCESS) { + psa_cipher_abort(operation); + } + + unlock_status = psa_unregister_read_under_mutex(slot); + + return (status == PSA_SUCCESS) ? unlock_status : status; +} + +psa_status_t psa_cipher_encrypt_setup(psa_cipher_operation_t *operation, + mbedtls_svc_key_id_t key, + psa_algorithm_t alg) +{ + return psa_cipher_setup(operation, key, alg, MBEDTLS_ENCRYPT); +} + +psa_status_t psa_cipher_decrypt_setup(psa_cipher_operation_t *operation, + mbedtls_svc_key_id_t key, + psa_algorithm_t alg) +{ + return psa_cipher_setup(operation, key, alg, MBEDTLS_DECRYPT); +} + +psa_status_t psa_cipher_generate_iv(psa_cipher_operation_t *operation, + uint8_t *iv_external, + size_t iv_size, + size_t *iv_length) +{ + psa_status_t status = PSA_ERROR_CORRUPTION_DETECTED; + size_t default_iv_length = 0; + + LOCAL_OUTPUT_DECLARE(iv_external, iv); + + if (operation->id == 0) { + status = PSA_ERROR_BAD_STATE; + goto exit; + } + + if (operation->iv_set || !operation->iv_required) { + status = PSA_ERROR_BAD_STATE; + goto exit; + } + + default_iv_length = operation->default_iv_length; + if (iv_size < default_iv_length) { + status = PSA_ERROR_BUFFER_TOO_SMALL; + goto exit; + } + + if (default_iv_length > PSA_CIPHER_IV_MAX_SIZE) { + status = PSA_ERROR_GENERIC_ERROR; + goto exit; + } + + LOCAL_OUTPUT_ALLOC(iv_external, default_iv_length, iv); + + status = psa_generate_random_internal(iv, default_iv_length); + if (status != PSA_SUCCESS) { + goto exit; + } + + status = psa_driver_wrapper_cipher_set_iv(operation, + iv, default_iv_length); + +exit: + if (status == PSA_SUCCESS) { + *iv_length = default_iv_length; + operation->iv_set = 1; + } else { + *iv_length = 0; + psa_cipher_abort(operation); + if (iv != NULL) { + mbedtls_platform_zeroize(iv, default_iv_length); + } + } + + LOCAL_OUTPUT_FREE(iv_external, iv); + return status; +} + +psa_status_t psa_cipher_set_iv(psa_cipher_operation_t *operation, + const uint8_t *iv_external, + size_t iv_length) +{ + psa_status_t status = PSA_ERROR_CORRUPTION_DETECTED; + + LOCAL_INPUT_DECLARE(iv_external, iv); + + if (operation->id == 0) { + status = PSA_ERROR_BAD_STATE; + goto exit; + } + + if (operation->iv_set || !operation->iv_required) { + status = PSA_ERROR_BAD_STATE; + goto exit; + } + + if (iv_length > PSA_CIPHER_IV_MAX_SIZE) { + status = PSA_ERROR_INVALID_ARGUMENT; + goto exit; + } + + LOCAL_INPUT_ALLOC(iv_external, iv_length, iv); + + status = psa_driver_wrapper_cipher_set_iv(operation, + iv, + iv_length); + +exit: + if (status == PSA_SUCCESS) { + operation->iv_set = 1; + } else { + psa_cipher_abort(operation); + } + + LOCAL_INPUT_FREE(iv_external, iv); + + return status; +} + +psa_status_t psa_cipher_update(psa_cipher_operation_t *operation, + const uint8_t *input_external, + size_t input_length, + uint8_t *output_external, + size_t output_size, + size_t *output_length) +{ + psa_status_t status = PSA_ERROR_CORRUPTION_DETECTED; + + LOCAL_INPUT_DECLARE(input_external, input); + LOCAL_OUTPUT_DECLARE(output_external, output); + + if (operation->id == 0) { + status = PSA_ERROR_BAD_STATE; + goto exit; + } + + if (operation->iv_required && !operation->iv_set) { + status = PSA_ERROR_BAD_STATE; + goto exit; + } + + LOCAL_INPUT_ALLOC(input_external, input_length, input); + LOCAL_OUTPUT_ALLOC(output_external, output_size, output); + + status = psa_driver_wrapper_cipher_update(operation, + input, + input_length, + output, + output_size, + output_length); + +exit: + if (status != PSA_SUCCESS) { + psa_cipher_abort(operation); + } + + LOCAL_INPUT_FREE(input_external, input); + LOCAL_OUTPUT_FREE(output_external, output); + + return status; +} + +psa_status_t psa_cipher_finish(psa_cipher_operation_t *operation, + uint8_t *output_external, + size_t output_size, + size_t *output_length) +{ + psa_status_t status = PSA_ERROR_GENERIC_ERROR; + + LOCAL_OUTPUT_DECLARE(output_external, output); + + if (operation->id == 0) { + status = PSA_ERROR_BAD_STATE; + goto exit; + } + + if (operation->iv_required && !operation->iv_set) { + status = PSA_ERROR_BAD_STATE; + goto exit; + } + + LOCAL_OUTPUT_ALLOC(output_external, output_size, output); + + status = psa_driver_wrapper_cipher_finish(operation, + output, + output_size, + output_length); + +exit: + if (status == PSA_SUCCESS) { + status = psa_cipher_abort(operation); + } else { + *output_length = 0; + (void) psa_cipher_abort(operation); + } + + LOCAL_OUTPUT_FREE(output_external, output); + + return status; +} + +psa_status_t psa_cipher_abort(psa_cipher_operation_t *operation) +{ + if (operation->id == 0) { + /* The object has (apparently) been initialized but it is not (yet) + * in use. It's ok to call abort on such an object, and there's + * nothing to do. */ + return PSA_SUCCESS; + } + + psa_driver_wrapper_cipher_abort(operation); + + operation->id = 0; + operation->iv_set = 0; + operation->iv_required = 0; + + return PSA_SUCCESS; +} + +psa_status_t psa_cipher_encrypt(mbedtls_svc_key_id_t key, + psa_algorithm_t alg, + const uint8_t *input_external, + size_t input_length, + uint8_t *output_external, + size_t output_size, + size_t *output_length) +{ + psa_status_t status = PSA_ERROR_CORRUPTION_DETECTED; + psa_status_t unlock_status = PSA_ERROR_CORRUPTION_DETECTED; + psa_key_slot_t *slot = NULL; + uint8_t local_iv[PSA_CIPHER_IV_MAX_SIZE]; + size_t default_iv_length = 0; + + LOCAL_INPUT_DECLARE(input_external, input); + LOCAL_OUTPUT_DECLARE(output_external, output); + + if (!PSA_ALG_IS_CIPHER(alg)) { + status = PSA_ERROR_INVALID_ARGUMENT; + goto exit; + } + + status = psa_get_and_lock_key_slot_with_policy(key, &slot, + PSA_KEY_USAGE_ENCRYPT, + alg); + if (status != PSA_SUCCESS) { + goto exit; + } + + default_iv_length = PSA_CIPHER_IV_LENGTH(slot->attr.type, alg); + if (default_iv_length > PSA_CIPHER_IV_MAX_SIZE) { + status = PSA_ERROR_GENERIC_ERROR; + goto exit; + } + + if (default_iv_length > 0) { + if (output_size < default_iv_length) { + status = PSA_ERROR_BUFFER_TOO_SMALL; + goto exit; + } + + status = psa_generate_random_internal(local_iv, default_iv_length); + if (status != PSA_SUCCESS) { + goto exit; + } + } + + LOCAL_INPUT_ALLOC(input_external, input_length, input); + LOCAL_OUTPUT_ALLOC(output_external, output_size, output); + + status = psa_driver_wrapper_cipher_encrypt( + &slot->attr, slot->key.data, slot->key.bytes, + alg, local_iv, default_iv_length, input, input_length, + psa_crypto_buffer_offset(output, default_iv_length), + output_size - default_iv_length, output_length); + +exit: + unlock_status = psa_unregister_read_under_mutex(slot); + if (status == PSA_SUCCESS) { + status = unlock_status; + } + + if (status == PSA_SUCCESS) { + if (default_iv_length > 0) { + memcpy(output, local_iv, default_iv_length); + } + *output_length += default_iv_length; + } else { + *output_length = 0; + } + + LOCAL_INPUT_FREE(input_external, input); + LOCAL_OUTPUT_FREE(output_external, output); + + return status; +} + +psa_status_t psa_cipher_decrypt(mbedtls_svc_key_id_t key, + psa_algorithm_t alg, + const uint8_t *input_external, + size_t input_length, + uint8_t *output_external, + size_t output_size, + size_t *output_length) +{ + psa_status_t status = PSA_ERROR_CORRUPTION_DETECTED; + psa_status_t unlock_status = PSA_ERROR_CORRUPTION_DETECTED; + psa_key_slot_t *slot = NULL; + + LOCAL_INPUT_DECLARE(input_external, input); + LOCAL_OUTPUT_DECLARE(output_external, output); + + if (!PSA_ALG_IS_CIPHER(alg)) { + status = PSA_ERROR_INVALID_ARGUMENT; + goto exit; + } + + status = psa_get_and_lock_key_slot_with_policy(key, &slot, + PSA_KEY_USAGE_DECRYPT, + alg); + if (status != PSA_SUCCESS) { + goto exit; + } + + if (alg == PSA_ALG_CCM_STAR_NO_TAG && + input_length < PSA_BLOCK_CIPHER_BLOCK_LENGTH(slot->attr.type)) { + status = PSA_ERROR_INVALID_ARGUMENT; + goto exit; + } else if (input_length < PSA_CIPHER_IV_LENGTH(slot->attr.type, alg)) { + status = PSA_ERROR_INVALID_ARGUMENT; + goto exit; + } + + LOCAL_INPUT_ALLOC(input_external, input_length, input); + LOCAL_OUTPUT_ALLOC(output_external, output_size, output); + + status = psa_driver_wrapper_cipher_decrypt( + &slot->attr, slot->key.data, slot->key.bytes, + alg, input, input_length, + output, output_size, output_length); + +exit: + unlock_status = psa_unregister_read_under_mutex(slot); + if (status == PSA_SUCCESS) { + status = unlock_status; + } + + if (status != PSA_SUCCESS) { + *output_length = 0; + } + + LOCAL_INPUT_FREE(input_external, input); + LOCAL_OUTPUT_FREE(output_external, output); + + return status; +} + + +/****************************************************************/ +/* AEAD */ +/****************************************************************/ + +/* Helper function to get the base algorithm from its variants. */ +static psa_algorithm_t psa_aead_get_base_algorithm(psa_algorithm_t alg) +{ + return PSA_ALG_AEAD_WITH_DEFAULT_LENGTH_TAG(alg); +} + +/* Helper function to perform common nonce length checks. */ +static psa_status_t psa_aead_check_nonce_length(psa_algorithm_t alg, + size_t nonce_length) +{ + psa_algorithm_t base_alg = psa_aead_get_base_algorithm(alg); + + switch (base_alg) { +#if defined(PSA_WANT_ALG_GCM) + case PSA_ALG_GCM: + /* Not checking max nonce size here as GCM spec allows almost + * arbitrarily large nonces. Please note that we do not generally + * recommend the usage of nonces of greater length than + * PSA_AEAD_NONCE_MAX_SIZE, as large nonces are hashed to a shorter + * size, which can then lead to collisions if you encrypt a very + * large number of messages.*/ + if (nonce_length != 0) { + return PSA_SUCCESS; + } + break; +#endif /* PSA_WANT_ALG_GCM */ +#if defined(PSA_WANT_ALG_CCM) + case PSA_ALG_CCM: + if (nonce_length >= 7 && nonce_length <= 13) { + return PSA_SUCCESS; + } + break; +#endif /* PSA_WANT_ALG_CCM */ +#if defined(PSA_WANT_ALG_CHACHA20_POLY1305) + case PSA_ALG_CHACHA20_POLY1305: + if (nonce_length == 12) { + return PSA_SUCCESS; + } else if (nonce_length == 8) { + return PSA_ERROR_NOT_SUPPORTED; + } + break; +#endif /* PSA_WANT_ALG_CHACHA20_POLY1305 */ + default: + (void) nonce_length; + return PSA_ERROR_NOT_SUPPORTED; + } + + return PSA_ERROR_INVALID_ARGUMENT; +} + +static psa_status_t psa_aead_check_algorithm(psa_algorithm_t alg) +{ + if (!PSA_ALG_IS_AEAD(alg) || PSA_ALG_IS_WILDCARD(alg)) { + return PSA_ERROR_INVALID_ARGUMENT; + } + + return PSA_SUCCESS; +} + +psa_status_t psa_aead_encrypt(mbedtls_svc_key_id_t key, + psa_algorithm_t alg, + const uint8_t *nonce_external, + size_t nonce_length, + const uint8_t *additional_data_external, + size_t additional_data_length, + const uint8_t *plaintext_external, + size_t plaintext_length, + uint8_t *ciphertext_external, + size_t ciphertext_size, + size_t *ciphertext_length) +{ + psa_status_t status = PSA_ERROR_CORRUPTION_DETECTED; + psa_key_slot_t *slot; + + LOCAL_INPUT_DECLARE(nonce_external, nonce); + LOCAL_INPUT_DECLARE(additional_data_external, additional_data); + LOCAL_INPUT_DECLARE(plaintext_external, plaintext); + LOCAL_OUTPUT_DECLARE(ciphertext_external, ciphertext); + + *ciphertext_length = 0; + + status = psa_aead_check_algorithm(alg); + if (status != PSA_SUCCESS) { + return status; + } + + status = psa_get_and_lock_key_slot_with_policy( + key, &slot, PSA_KEY_USAGE_ENCRYPT, alg); + if (status != PSA_SUCCESS) { + return status; + } + + LOCAL_INPUT_ALLOC(nonce_external, nonce_length, nonce); + LOCAL_INPUT_ALLOC(additional_data_external, additional_data_length, additional_data); + LOCAL_INPUT_ALLOC(plaintext_external, plaintext_length, plaintext); + LOCAL_OUTPUT_ALLOC(ciphertext_external, ciphertext_size, ciphertext); + + status = psa_aead_check_nonce_length(alg, nonce_length); + if (status != PSA_SUCCESS) { + goto exit; + } + + status = psa_driver_wrapper_aead_encrypt( + &slot->attr, slot->key.data, slot->key.bytes, + alg, + nonce, nonce_length, + additional_data, additional_data_length, + plaintext, plaintext_length, + ciphertext, ciphertext_size, ciphertext_length); + + if (status != PSA_SUCCESS && ciphertext_size != 0) { + memset(ciphertext, 0, ciphertext_size); + } + +exit: + LOCAL_INPUT_FREE(nonce_external, nonce); + LOCAL_INPUT_FREE(additional_data_external, additional_data); + LOCAL_INPUT_FREE(plaintext_external, plaintext); + LOCAL_OUTPUT_FREE(ciphertext_external, ciphertext); + + psa_unregister_read_under_mutex(slot); + + return status; +} + +psa_status_t psa_aead_decrypt(mbedtls_svc_key_id_t key, + psa_algorithm_t alg, + const uint8_t *nonce_external, + size_t nonce_length, + const uint8_t *additional_data_external, + size_t additional_data_length, + const uint8_t *ciphertext_external, + size_t ciphertext_length, + uint8_t *plaintext_external, + size_t plaintext_size, + size_t *plaintext_length) +{ + psa_status_t status = PSA_ERROR_CORRUPTION_DETECTED; + psa_key_slot_t *slot; + + LOCAL_INPUT_DECLARE(nonce_external, nonce); + LOCAL_INPUT_DECLARE(additional_data_external, additional_data); + LOCAL_INPUT_DECLARE(ciphertext_external, ciphertext); + LOCAL_OUTPUT_DECLARE(plaintext_external, plaintext); + + *plaintext_length = 0; + + status = psa_aead_check_algorithm(alg); + if (status != PSA_SUCCESS) { + return status; + } + + status = psa_get_and_lock_key_slot_with_policy( + key, &slot, PSA_KEY_USAGE_DECRYPT, alg); + if (status != PSA_SUCCESS) { + return status; + } + + LOCAL_INPUT_ALLOC(nonce_external, nonce_length, nonce); + LOCAL_INPUT_ALLOC(additional_data_external, additional_data_length, + additional_data); + LOCAL_INPUT_ALLOC(ciphertext_external, ciphertext_length, ciphertext); + LOCAL_OUTPUT_ALLOC(plaintext_external, plaintext_size, plaintext); + + status = psa_aead_check_nonce_length(alg, nonce_length); + if (status != PSA_SUCCESS) { + goto exit; + } + + status = psa_driver_wrapper_aead_decrypt( + &slot->attr, slot->key.data, slot->key.bytes, + alg, + nonce, nonce_length, + additional_data, additional_data_length, + ciphertext, ciphertext_length, + plaintext, plaintext_size, plaintext_length); + + if (status != PSA_SUCCESS && plaintext_size != 0) { + memset(plaintext, 0, plaintext_size); + } + +exit: + LOCAL_INPUT_FREE(nonce_external, nonce); + LOCAL_INPUT_FREE(additional_data_external, additional_data); + LOCAL_INPUT_FREE(ciphertext_external, ciphertext); + LOCAL_OUTPUT_FREE(plaintext_external, plaintext); + + psa_unregister_read_under_mutex(slot); + + return status; +} + +static psa_status_t psa_validate_tag_length(psa_algorithm_t alg) +{ + const uint8_t tag_len = PSA_ALG_AEAD_GET_TAG_LENGTH(alg); + + switch (PSA_ALG_AEAD_WITH_SHORTENED_TAG(alg, 0)) { +#if defined(PSA_WANT_ALG_CCM) + case PSA_ALG_AEAD_WITH_SHORTENED_TAG(PSA_ALG_CCM, 0): + /* CCM allows the following tag lengths: 4, 6, 8, 10, 12, 14, 16.*/ + if (tag_len < 4 || tag_len > 16 || tag_len % 2) { + return PSA_ERROR_INVALID_ARGUMENT; + } + break; +#endif /* PSA_WANT_ALG_CCM */ + +#if defined(PSA_WANT_ALG_GCM) + case PSA_ALG_AEAD_WITH_SHORTENED_TAG(PSA_ALG_GCM, 0): + /* GCM allows the following tag lengths: 4, 8, 12, 13, 14, 15, 16. */ + if (tag_len != 4 && tag_len != 8 && (tag_len < 12 || tag_len > 16)) { + return PSA_ERROR_INVALID_ARGUMENT; + } + break; +#endif /* PSA_WANT_ALG_GCM */ + +#if defined(PSA_WANT_ALG_CHACHA20_POLY1305) + case PSA_ALG_AEAD_WITH_SHORTENED_TAG(PSA_ALG_CHACHA20_POLY1305, 0): + /* We only support the default tag length. */ + if (tag_len != 16) { + return PSA_ERROR_INVALID_ARGUMENT; + } + break; +#endif /* PSA_WANT_ALG_CHACHA20_POLY1305 */ + + default: + (void) tag_len; + return PSA_ERROR_NOT_SUPPORTED; + } + return PSA_SUCCESS; +} + +/* Set the key for a multipart authenticated operation. */ +static psa_status_t psa_aead_setup(psa_aead_operation_t *operation, + int is_encrypt, + mbedtls_svc_key_id_t key, + psa_algorithm_t alg) +{ + psa_status_t status = PSA_ERROR_CORRUPTION_DETECTED; + psa_status_t unlock_status = PSA_ERROR_CORRUPTION_DETECTED; + psa_key_slot_t *slot = NULL; + psa_key_usage_t key_usage = 0; + + status = psa_aead_check_algorithm(alg); + if (status != PSA_SUCCESS) { + goto exit; + } + + if (operation->id != 0) { + status = PSA_ERROR_BAD_STATE; + goto exit; + } + + if (operation->nonce_set || operation->lengths_set || + operation->ad_started || operation->body_started) { + status = PSA_ERROR_BAD_STATE; + goto exit; + } + + if (is_encrypt) { + key_usage = PSA_KEY_USAGE_ENCRYPT; + } else { + key_usage = PSA_KEY_USAGE_DECRYPT; + } + + status = psa_get_and_lock_key_slot_with_policy(key, &slot, key_usage, + alg); + if (status != PSA_SUCCESS) { + goto exit; + } + + if ((status = psa_validate_tag_length(alg)) != PSA_SUCCESS) { + goto exit; + } + + if (is_encrypt) { + status = psa_driver_wrapper_aead_encrypt_setup(operation, + &slot->attr, + slot->key.data, + slot->key.bytes, + alg); + } else { + status = psa_driver_wrapper_aead_decrypt_setup(operation, + &slot->attr, + slot->key.data, + slot->key.bytes, + alg); + } + if (status != PSA_SUCCESS) { + goto exit; + } + + operation->key_type = psa_get_key_type(&slot->attr); + +exit: + unlock_status = psa_unregister_read_under_mutex(slot); + + if (status == PSA_SUCCESS) { + status = unlock_status; + operation->alg = psa_aead_get_base_algorithm(alg); + operation->is_encrypt = is_encrypt; + } else { + psa_aead_abort(operation); + } + + return status; +} + +/* Set the key for a multipart authenticated encryption operation. */ +psa_status_t psa_aead_encrypt_setup(psa_aead_operation_t *operation, + mbedtls_svc_key_id_t key, + psa_algorithm_t alg) +{ + return psa_aead_setup(operation, 1, key, alg); +} + +/* Set the key for a multipart authenticated decryption operation. */ +psa_status_t psa_aead_decrypt_setup(psa_aead_operation_t *operation, + mbedtls_svc_key_id_t key, + psa_algorithm_t alg) +{ + return psa_aead_setup(operation, 0, key, alg); +} + +static psa_status_t psa_aead_set_nonce_internal(psa_aead_operation_t *operation, + const uint8_t *nonce, + size_t nonce_length) +{ + psa_status_t status = PSA_ERROR_CORRUPTION_DETECTED; + + if (operation->id == 0) { + status = PSA_ERROR_BAD_STATE; + goto exit; + } + + if (operation->nonce_set) { + status = PSA_ERROR_BAD_STATE; + goto exit; + } + + status = psa_aead_check_nonce_length(operation->alg, nonce_length); + if (status != PSA_SUCCESS) { + status = PSA_ERROR_INVALID_ARGUMENT; + goto exit; + } + + status = psa_driver_wrapper_aead_set_nonce(operation, nonce, + nonce_length); + +exit: + if (status == PSA_SUCCESS) { + operation->nonce_set = 1; + } else { + psa_aead_abort(operation); + } + + return status; +} + +/* Generate a random nonce / IV for multipart AEAD operation */ +psa_status_t psa_aead_generate_nonce(psa_aead_operation_t *operation, + uint8_t *nonce_external, + size_t nonce_size, + size_t *nonce_length) +{ + psa_status_t status = PSA_ERROR_CORRUPTION_DETECTED; + uint8_t local_nonce[PSA_AEAD_NONCE_MAX_SIZE]; + size_t required_nonce_size = 0; + + LOCAL_OUTPUT_DECLARE(nonce_external, nonce); + LOCAL_OUTPUT_ALLOC(nonce_external, nonce_size, nonce); + + *nonce_length = 0; + + if (operation->id == 0) { + status = PSA_ERROR_BAD_STATE; + goto exit; + } + + if (operation->nonce_set || !operation->is_encrypt) { + status = PSA_ERROR_BAD_STATE; + goto exit; + } + + /* For CCM, this size may not be correct according to the PSA + * specification. The PSA Crypto 1.0.1 specification states: + * + * CCM encodes the plaintext length pLen in L octets, with L the smallest + * integer >= 2 where pLen < 2^(8L). The nonce length is then 15 - L bytes. + * + * However this restriction that L has to be the smallest integer is not + * applied in practice, and it is not implementable here since the + * plaintext length may or may not be known at this time. */ + required_nonce_size = PSA_AEAD_NONCE_LENGTH(operation->key_type, + operation->alg); + if (nonce_size < required_nonce_size) { + status = PSA_ERROR_BUFFER_TOO_SMALL; + goto exit; + } + + status = psa_generate_random_internal(local_nonce, required_nonce_size); + if (status != PSA_SUCCESS) { + goto exit; + } + + status = psa_aead_set_nonce_internal(operation, local_nonce, + required_nonce_size); + +exit: + if (status == PSA_SUCCESS) { + memcpy(nonce, local_nonce, required_nonce_size); + *nonce_length = required_nonce_size; + } else { + psa_aead_abort(operation); + } + + LOCAL_OUTPUT_FREE(nonce_external, nonce); + + return status; +} + +/* Set the nonce for a multipart authenticated encryption or decryption + operation.*/ +psa_status_t psa_aead_set_nonce(psa_aead_operation_t *operation, + const uint8_t *nonce_external, + size_t nonce_length) +{ + psa_status_t status; + + LOCAL_INPUT_DECLARE(nonce_external, nonce); + LOCAL_INPUT_ALLOC(nonce_external, nonce_length, nonce); + + status = psa_aead_set_nonce_internal(operation, nonce, nonce_length); + +/* Exit label is only needed for buffer copying, prevent unused warnings. */ +#if !defined(MBEDTLS_PSA_ASSUME_EXCLUSIVE_BUFFERS) +exit: +#endif + + LOCAL_INPUT_FREE(nonce_external, nonce); + + return status; +} + +/* Declare the lengths of the message and additional data for multipart AEAD. */ +psa_status_t psa_aead_set_lengths(psa_aead_operation_t *operation, + size_t ad_length, + size_t plaintext_length) +{ + psa_status_t status = PSA_ERROR_CORRUPTION_DETECTED; + + if (operation->id == 0) { + status = PSA_ERROR_BAD_STATE; + goto exit; + } + + if (operation->lengths_set || operation->ad_started || + operation->body_started) { + status = PSA_ERROR_BAD_STATE; + goto exit; + } + + switch (operation->alg) { +#if defined(PSA_WANT_ALG_GCM) + case PSA_ALG_GCM: + /* Lengths can only be too large for GCM if size_t is bigger than 32 + * bits. Without the guard this code will generate warnings on 32bit + * builds. */ +#if SIZE_MAX > UINT32_MAX + if (((uint64_t) ad_length) >> 61 != 0 || + ((uint64_t) plaintext_length) > 0xFFFFFFFE0ull) { + status = PSA_ERROR_INVALID_ARGUMENT; + goto exit; + } +#endif + break; +#endif /* PSA_WANT_ALG_GCM */ +#if defined(PSA_WANT_ALG_CCM) + case PSA_ALG_CCM: + if (ad_length > 0xFF00) { + status = PSA_ERROR_INVALID_ARGUMENT; + goto exit; + } + break; +#endif /* PSA_WANT_ALG_CCM */ +#if defined(PSA_WANT_ALG_CHACHA20_POLY1305) + case PSA_ALG_CHACHA20_POLY1305: + /* No length restrictions for ChaChaPoly. */ + break; +#endif /* PSA_WANT_ALG_CHACHA20_POLY1305 */ + default: + break; + } + + status = psa_driver_wrapper_aead_set_lengths(operation, ad_length, + plaintext_length); + +exit: + if (status == PSA_SUCCESS) { + operation->ad_remaining = ad_length; + operation->body_remaining = plaintext_length; + operation->lengths_set = 1; + } else { + psa_aead_abort(operation); + } + + return status; +} + +/* Pass additional data to an active multipart AEAD operation. */ +psa_status_t psa_aead_update_ad(psa_aead_operation_t *operation, + const uint8_t *input_external, + size_t input_length) +{ + psa_status_t status = PSA_ERROR_CORRUPTION_DETECTED; + + LOCAL_INPUT_DECLARE(input_external, input); + LOCAL_INPUT_ALLOC(input_external, input_length, input); + + if (operation->id == 0) { + status = PSA_ERROR_BAD_STATE; + goto exit; + } + + if (!operation->nonce_set || operation->body_started) { + status = PSA_ERROR_BAD_STATE; + goto exit; + } + + if (operation->lengths_set) { + if (operation->ad_remaining < input_length) { + status = PSA_ERROR_INVALID_ARGUMENT; + goto exit; + } + + operation->ad_remaining -= input_length; + } +#if defined(PSA_WANT_ALG_CCM) + else if (operation->alg == PSA_ALG_CCM) { + status = PSA_ERROR_BAD_STATE; + goto exit; + } +#endif /* PSA_WANT_ALG_CCM */ + + status = psa_driver_wrapper_aead_update_ad(operation, input, + input_length); + +exit: + if (status == PSA_SUCCESS) { + operation->ad_started = 1; + } else { + psa_aead_abort(operation); + } + + LOCAL_INPUT_FREE(input_external, input); + + return status; +} + +/* Encrypt or decrypt a message fragment in an active multipart AEAD + operation.*/ +psa_status_t psa_aead_update(psa_aead_operation_t *operation, + const uint8_t *input_external, + size_t input_length, + uint8_t *output_external, + size_t output_size, + size_t *output_length) +{ + psa_status_t status = PSA_ERROR_CORRUPTION_DETECTED; + + + LOCAL_INPUT_DECLARE(input_external, input); + LOCAL_OUTPUT_DECLARE(output_external, output); + + LOCAL_INPUT_ALLOC(input_external, input_length, input); + LOCAL_OUTPUT_ALLOC(output_external, output_size, output); + + *output_length = 0; + + if (operation->id == 0) { + status = PSA_ERROR_BAD_STATE; + goto exit; + } + + if (!operation->nonce_set) { + status = PSA_ERROR_BAD_STATE; + goto exit; + } + + if (operation->lengths_set) { + /* Additional data length was supplied, but not all the additional + data was supplied.*/ + if (operation->ad_remaining != 0) { + status = PSA_ERROR_INVALID_ARGUMENT; + goto exit; + } + + /* Too much data provided. */ + if (operation->body_remaining < input_length) { + status = PSA_ERROR_INVALID_ARGUMENT; + goto exit; + } + + operation->body_remaining -= input_length; + } +#if defined(PSA_WANT_ALG_CCM) + else if (operation->alg == PSA_ALG_CCM) { + status = PSA_ERROR_BAD_STATE; + goto exit; + } +#endif /* PSA_WANT_ALG_CCM */ + + status = psa_driver_wrapper_aead_update(operation, input, input_length, + output, output_size, + output_length); + +exit: + if (status == PSA_SUCCESS) { + operation->body_started = 1; + } else { + psa_aead_abort(operation); + } + + LOCAL_INPUT_FREE(input_external, input); + LOCAL_OUTPUT_FREE(output_external, output); + + return status; +} + +static psa_status_t psa_aead_final_checks(const psa_aead_operation_t *operation) +{ + if (operation->id == 0 || !operation->nonce_set) { + return PSA_ERROR_BAD_STATE; + } + + if (operation->lengths_set && (operation->ad_remaining != 0 || + operation->body_remaining != 0)) { + return PSA_ERROR_INVALID_ARGUMENT; + } + + return PSA_SUCCESS; +} + +/* Finish encrypting a message in a multipart AEAD operation. */ +psa_status_t psa_aead_finish(psa_aead_operation_t *operation, + uint8_t *ciphertext_external, + size_t ciphertext_size, + size_t *ciphertext_length, + uint8_t *tag_external, + size_t tag_size, + size_t *tag_length) +{ + psa_status_t status = PSA_ERROR_CORRUPTION_DETECTED; + + LOCAL_OUTPUT_DECLARE(ciphertext_external, ciphertext); + LOCAL_OUTPUT_DECLARE(tag_external, tag); + + LOCAL_OUTPUT_ALLOC(ciphertext_external, ciphertext_size, ciphertext); + LOCAL_OUTPUT_ALLOC(tag_external, tag_size, tag); + + *ciphertext_length = 0; + *tag_length = tag_size; + + status = psa_aead_final_checks(operation); + if (status != PSA_SUCCESS) { + goto exit; + } + + if (!operation->is_encrypt) { + status = PSA_ERROR_BAD_STATE; + goto exit; + } + + status = psa_driver_wrapper_aead_finish(operation, ciphertext, + ciphertext_size, + ciphertext_length, + tag, tag_size, tag_length); + +exit: + + + /* In case the operation fails and the user fails to check for failure or + * the zero tag size, make sure the tag is set to something implausible. + * Even if the operation succeeds, make sure we clear the rest of the + * buffer to prevent potential leakage of anything previously placed in + * the same buffer.*/ + psa_wipe_tag_output_buffer(tag, status, tag_size, *tag_length); + + psa_aead_abort(operation); + + LOCAL_OUTPUT_FREE(ciphertext_external, ciphertext); + LOCAL_OUTPUT_FREE(tag_external, tag); + + return status; +} + +/* Finish authenticating and decrypting a message in a multipart AEAD + operation.*/ +psa_status_t psa_aead_verify(psa_aead_operation_t *operation, + uint8_t *plaintext_external, + size_t plaintext_size, + size_t *plaintext_length, + const uint8_t *tag_external, + size_t tag_length) +{ + psa_status_t status = PSA_ERROR_CORRUPTION_DETECTED; + + LOCAL_OUTPUT_DECLARE(plaintext_external, plaintext); + LOCAL_INPUT_DECLARE(tag_external, tag); + + LOCAL_OUTPUT_ALLOC(plaintext_external, plaintext_size, plaintext); + LOCAL_INPUT_ALLOC(tag_external, tag_length, tag); + + *plaintext_length = 0; + + status = psa_aead_final_checks(operation); + if (status != PSA_SUCCESS) { + goto exit; + } + + if (operation->is_encrypt) { + status = PSA_ERROR_BAD_STATE; + goto exit; + } + + status = psa_driver_wrapper_aead_verify(operation, plaintext, + plaintext_size, + plaintext_length, + tag, tag_length); + +exit: + psa_aead_abort(operation); + + LOCAL_OUTPUT_FREE(plaintext_external, plaintext); + LOCAL_INPUT_FREE(tag_external, tag); + + return status; +} + +/* Abort an AEAD operation. */ +psa_status_t psa_aead_abort(psa_aead_operation_t *operation) +{ + psa_status_t status = PSA_ERROR_CORRUPTION_DETECTED; + + if (operation->id == 0) { + /* The object has (apparently) been initialized but it is not (yet) + * in use. It's ok to call abort on such an object, and there's + * nothing to do. */ + return PSA_SUCCESS; + } + + status = psa_driver_wrapper_aead_abort(operation); + + memset(operation, 0, sizeof(*operation)); + + return status; +} + +/****************************************************************/ +/* Generators */ +/****************************************************************/ + +#if defined(BUILTIN_ALG_ANY_HKDF) || \ + defined(MBEDTLS_PSA_BUILTIN_ALG_TLS12_PRF) || \ + defined(MBEDTLS_PSA_BUILTIN_ALG_TLS12_PSK_TO_MS) || \ + defined(MBEDTLS_PSA_BUILTIN_ALG_TLS12_ECJPAKE_TO_PMS) || \ + defined(PSA_HAVE_SOFT_PBKDF2) +#define AT_LEAST_ONE_BUILTIN_KDF +#endif /* At least one builtin KDF */ + +#if defined(BUILTIN_ALG_ANY_HKDF) || \ + defined(MBEDTLS_PSA_BUILTIN_ALG_TLS12_PRF) || \ + defined(MBEDTLS_PSA_BUILTIN_ALG_TLS12_PSK_TO_MS) +static psa_status_t psa_key_derivation_start_hmac( + psa_mac_operation_t *operation, + psa_algorithm_t hash_alg, + const uint8_t *hmac_key, + size_t hmac_key_length) +{ + psa_status_t status = PSA_ERROR_CORRUPTION_DETECTED; + psa_key_attributes_t attributes = PSA_KEY_ATTRIBUTES_INIT; + psa_set_key_type(&attributes, PSA_KEY_TYPE_HMAC); + psa_set_key_bits(&attributes, PSA_BYTES_TO_BITS(hmac_key_length)); + psa_set_key_usage_flags(&attributes, PSA_KEY_USAGE_SIGN_HASH); + + operation->is_sign = 1; + operation->mac_size = PSA_HASH_LENGTH(hash_alg); + + status = psa_driver_wrapper_mac_sign_setup(operation, + &attributes, + hmac_key, hmac_key_length, + PSA_ALG_HMAC(hash_alg)); + + psa_reset_key_attributes(&attributes); + return status; +} +#endif /* KDF algorithms reliant on HMAC */ + +#define HKDF_STATE_INIT 0 /* no input yet */ +#define HKDF_STATE_STARTED 1 /* got salt */ +#define HKDF_STATE_KEYED 2 /* got key */ +#define HKDF_STATE_OUTPUT 3 /* output started */ + +static psa_algorithm_t psa_key_derivation_get_kdf_alg( + const psa_key_derivation_operation_t *operation) +{ + if (PSA_ALG_IS_KEY_AGREEMENT(operation->alg)) { + return PSA_ALG_KEY_AGREEMENT_GET_KDF(operation->alg); + } else { + return operation->alg; + } +} + +psa_status_t psa_key_derivation_abort(psa_key_derivation_operation_t *operation) +{ + psa_status_t status = PSA_SUCCESS; + psa_algorithm_t kdf_alg = psa_key_derivation_get_kdf_alg(operation); + if (kdf_alg == 0) { + /* The object has (apparently) been initialized but it is not + * in use. It's ok to call abort on such an object, and there's + * nothing to do. */ + } else +#if defined(BUILTIN_ALG_ANY_HKDF) + if (PSA_ALG_IS_ANY_HKDF(kdf_alg)) { + mbedtls_free(operation->ctx.hkdf.info); + status = psa_mac_abort(&operation->ctx.hkdf.hmac); + } else +#endif /* BUILTIN_ALG_ANY_HKDF */ +#if defined(MBEDTLS_PSA_BUILTIN_ALG_TLS12_PRF) || \ + defined(MBEDTLS_PSA_BUILTIN_ALG_TLS12_PSK_TO_MS) + if (PSA_ALG_IS_TLS12_PRF(kdf_alg) || + /* TLS-1.2 PSK-to-MS KDF uses the same core as TLS-1.2 PRF */ + PSA_ALG_IS_TLS12_PSK_TO_MS(kdf_alg)) { + if (operation->ctx.tls12_prf.secret != NULL) { + mbedtls_zeroize_and_free(operation->ctx.tls12_prf.secret, + operation->ctx.tls12_prf.secret_length); + } + + if (operation->ctx.tls12_prf.seed != NULL) { + mbedtls_zeroize_and_free(operation->ctx.tls12_prf.seed, + operation->ctx.tls12_prf.seed_length); + } + + if (operation->ctx.tls12_prf.label != NULL) { + mbedtls_zeroize_and_free(operation->ctx.tls12_prf.label, + operation->ctx.tls12_prf.label_length); + } +#if defined(MBEDTLS_PSA_BUILTIN_ALG_TLS12_PSK_TO_MS) + if (operation->ctx.tls12_prf.other_secret != NULL) { + mbedtls_zeroize_and_free(operation->ctx.tls12_prf.other_secret, + operation->ctx.tls12_prf.other_secret_length); + } +#endif /* MBEDTLS_PSA_BUILTIN_ALG_TLS12_PSK_TO_MS */ + status = PSA_SUCCESS; + + /* We leave the fields Ai and output_block to be erased safely by the + * mbedtls_platform_zeroize() in the end of this function. */ + } else +#endif /* defined(MBEDTLS_PSA_BUILTIN_ALG_TLS12_PRF) || + * defined(MBEDTLS_PSA_BUILTIN_ALG_TLS12_PSK_TO_MS) */ +#if defined(MBEDTLS_PSA_BUILTIN_ALG_TLS12_ECJPAKE_TO_PMS) + if (kdf_alg == PSA_ALG_TLS12_ECJPAKE_TO_PMS) { + mbedtls_platform_zeroize(operation->ctx.tls12_ecjpake_to_pms.data, + sizeof(operation->ctx.tls12_ecjpake_to_pms.data)); + } else +#endif /* defined(MBEDTLS_PSA_BUILTIN_ALG_TLS12_ECJPAKE_TO_PMS) */ +#if defined(PSA_HAVE_SOFT_PBKDF2) + if (PSA_ALG_IS_PBKDF2(kdf_alg)) { + if (operation->ctx.pbkdf2.salt != NULL) { + mbedtls_zeroize_and_free(operation->ctx.pbkdf2.salt, + operation->ctx.pbkdf2.salt_length); + } + + status = PSA_SUCCESS; + } else +#endif /* defined(PSA_HAVE_SOFT_PBKDF2) */ + { + status = PSA_ERROR_BAD_STATE; + } + mbedtls_platform_zeroize(operation, sizeof(*operation)); + return status; +} + +psa_status_t psa_key_derivation_get_capacity(const psa_key_derivation_operation_t *operation, + size_t *capacity) +{ + if (operation->alg == 0) { + /* This is a blank key derivation operation. */ + return PSA_ERROR_BAD_STATE; + } + + *capacity = operation->capacity; + return PSA_SUCCESS; +} + +psa_status_t psa_key_derivation_set_capacity(psa_key_derivation_operation_t *operation, + size_t capacity) +{ + if (operation->alg == 0) { + return PSA_ERROR_BAD_STATE; + } + if (capacity > operation->capacity) { + return PSA_ERROR_INVALID_ARGUMENT; + } + operation->capacity = capacity; + return PSA_SUCCESS; +} + +#if defined(BUILTIN_ALG_ANY_HKDF) +/* Read some bytes from an HKDF-based operation. */ +static psa_status_t psa_key_derivation_hkdf_read(psa_hkdf_key_derivation_t *hkdf, + psa_algorithm_t kdf_alg, + uint8_t *output, + size_t output_length) +{ + psa_algorithm_t hash_alg = PSA_ALG_HKDF_GET_HASH(kdf_alg); + uint8_t hash_length = PSA_HASH_LENGTH(hash_alg); + size_t hmac_output_length; + psa_status_t status; +#if defined(MBEDTLS_PSA_BUILTIN_ALG_HKDF_EXTRACT) + const uint8_t last_block = PSA_ALG_IS_HKDF_EXTRACT(kdf_alg) ? 0 : 0xff; +#else + const uint8_t last_block = 0xff; +#endif /* MBEDTLS_PSA_BUILTIN_ALG_HKDF_EXTRACT */ + + if (hkdf->state < HKDF_STATE_KEYED || + (!hkdf->info_set +#if defined(MBEDTLS_PSA_BUILTIN_ALG_HKDF_EXTRACT) + && !PSA_ALG_IS_HKDF_EXTRACT(kdf_alg) +#endif /* MBEDTLS_PSA_BUILTIN_ALG_HKDF_EXTRACT */ + )) { + return PSA_ERROR_BAD_STATE; + } + hkdf->state = HKDF_STATE_OUTPUT; + + while (output_length != 0) { + /* Copy what remains of the current block */ + uint8_t n = hash_length - hkdf->offset_in_block; + if (n > output_length) { + n = (uint8_t) output_length; + } + memcpy(output, hkdf->output_block + hkdf->offset_in_block, n); + output += n; + output_length -= n; + hkdf->offset_in_block += n; + if (output_length == 0) { + break; + } + /* We can't be wanting more output after the last block, otherwise + * the capacity check in psa_key_derivation_output_bytes() would have + * prevented this call. It could happen only if the operation + * object was corrupted or if this function is called directly + * inside the library. */ + if (hkdf->block_number == last_block) { + return PSA_ERROR_BAD_STATE; + } + + /* We need a new block */ + ++hkdf->block_number; + hkdf->offset_in_block = 0; + + status = psa_key_derivation_start_hmac(&hkdf->hmac, + hash_alg, + hkdf->prk, + hash_length); + if (status != PSA_SUCCESS) { + return status; + } + + if (hkdf->block_number != 1) { + status = psa_mac_update(&hkdf->hmac, + hkdf->output_block, + hash_length); + if (status != PSA_SUCCESS) { + return status; + } + } + status = psa_mac_update(&hkdf->hmac, + hkdf->info, + hkdf->info_length); + if (status != PSA_SUCCESS) { + return status; + } + status = psa_mac_update(&hkdf->hmac, + &hkdf->block_number, 1); + if (status != PSA_SUCCESS) { + return status; + } + status = psa_mac_sign_finish(&hkdf->hmac, + hkdf->output_block, + sizeof(hkdf->output_block), + &hmac_output_length); + if (status != PSA_SUCCESS) { + return status; + } + } + + return PSA_SUCCESS; +} +#endif /* BUILTIN_ALG_ANY_HKDF */ + +#if defined(MBEDTLS_PSA_BUILTIN_ALG_TLS12_PRF) || \ + defined(MBEDTLS_PSA_BUILTIN_ALG_TLS12_PSK_TO_MS) +static psa_status_t psa_key_derivation_tls12_prf_generate_next_block( + psa_tls12_prf_key_derivation_t *tls12_prf, + psa_algorithm_t alg) +{ + psa_algorithm_t hash_alg = PSA_ALG_HKDF_GET_HASH(alg); + uint8_t hash_length = PSA_HASH_LENGTH(hash_alg); + psa_mac_operation_t hmac = PSA_MAC_OPERATION_INIT; + size_t hmac_output_length; + psa_status_t status, cleanup_status; + + /* We can't be wanting more output after block 0xff, otherwise + * the capacity check in psa_key_derivation_output_bytes() would have + * prevented this call. It could happen only if the operation + * object was corrupted or if this function is called directly + * inside the library. */ + if (tls12_prf->block_number == 0xff) { + return PSA_ERROR_CORRUPTION_DETECTED; + } + + /* We need a new block */ + ++tls12_prf->block_number; + tls12_prf->left_in_block = hash_length; + + /* Recall the definition of the TLS-1.2-PRF from RFC 5246: + * + * PRF(secret, label, seed) = P_(secret, label + seed) + * + * P_hash(secret, seed) = HMAC_hash(secret, A(1) + seed) + + * HMAC_hash(secret, A(2) + seed) + + * HMAC_hash(secret, A(3) + seed) + ... + * + * A(0) = seed + * A(i) = HMAC_hash(secret, A(i-1)) + * + * The `psa_tls12_prf_key_derivation` structure saves the block + * `HMAC_hash(secret, A(i) + seed)` from which the output + * is currently extracted as `output_block` and where i is + * `block_number`. + */ + + status = psa_key_derivation_start_hmac(&hmac, + hash_alg, + tls12_prf->secret, + tls12_prf->secret_length); + if (status != PSA_SUCCESS) { + goto cleanup; + } + + /* Calculate A(i) where i = tls12_prf->block_number. */ + if (tls12_prf->block_number == 1) { + /* A(1) = HMAC_hash(secret, A(0)), where A(0) = seed. (The RFC overloads + * the variable seed and in this instance means it in the context of the + * P_hash function, where seed = label + seed.) */ + status = psa_mac_update(&hmac, + tls12_prf->label, + tls12_prf->label_length); + if (status != PSA_SUCCESS) { + goto cleanup; + } + status = psa_mac_update(&hmac, + tls12_prf->seed, + tls12_prf->seed_length); + if (status != PSA_SUCCESS) { + goto cleanup; + } + } else { + /* A(i) = HMAC_hash(secret, A(i-1)) */ + status = psa_mac_update(&hmac, tls12_prf->Ai, hash_length); + if (status != PSA_SUCCESS) { + goto cleanup; + } + } + + status = psa_mac_sign_finish(&hmac, + tls12_prf->Ai, hash_length, + &hmac_output_length); + if (hmac_output_length != hash_length) { + status = PSA_ERROR_CORRUPTION_DETECTED; + } + if (status != PSA_SUCCESS) { + goto cleanup; + } + + /* Calculate HMAC_hash(secret, A(i) + label + seed). */ + status = psa_key_derivation_start_hmac(&hmac, + hash_alg, + tls12_prf->secret, + tls12_prf->secret_length); + if (status != PSA_SUCCESS) { + goto cleanup; + } + status = psa_mac_update(&hmac, tls12_prf->Ai, hash_length); + if (status != PSA_SUCCESS) { + goto cleanup; + } + status = psa_mac_update(&hmac, tls12_prf->label, tls12_prf->label_length); + if (status != PSA_SUCCESS) { + goto cleanup; + } + status = psa_mac_update(&hmac, tls12_prf->seed, tls12_prf->seed_length); + if (status != PSA_SUCCESS) { + goto cleanup; + } + status = psa_mac_sign_finish(&hmac, + tls12_prf->output_block, hash_length, + &hmac_output_length); + if (status != PSA_SUCCESS) { + goto cleanup; + } + + +cleanup: + cleanup_status = psa_mac_abort(&hmac); + if (status == PSA_SUCCESS && cleanup_status != PSA_SUCCESS) { + status = cleanup_status; + } + + return status; +} + +static psa_status_t psa_key_derivation_tls12_prf_read( + psa_tls12_prf_key_derivation_t *tls12_prf, + psa_algorithm_t alg, + uint8_t *output, + size_t output_length) +{ + psa_algorithm_t hash_alg = PSA_ALG_TLS12_PRF_GET_HASH(alg); + uint8_t hash_length = PSA_HASH_LENGTH(hash_alg); + psa_status_t status; + uint8_t offset, length; + + switch (tls12_prf->state) { + case PSA_TLS12_PRF_STATE_LABEL_SET: + tls12_prf->state = PSA_TLS12_PRF_STATE_OUTPUT; + break; + case PSA_TLS12_PRF_STATE_OUTPUT: + break; + default: + return PSA_ERROR_BAD_STATE; + } + + while (output_length != 0) { + /* Check if we have fully processed the current block. */ + if (tls12_prf->left_in_block == 0) { + status = psa_key_derivation_tls12_prf_generate_next_block(tls12_prf, + alg); + if (status != PSA_SUCCESS) { + return status; + } + + continue; + } + + if (tls12_prf->left_in_block > output_length) { + length = (uint8_t) output_length; + } else { + length = tls12_prf->left_in_block; + } + + offset = hash_length - tls12_prf->left_in_block; + memcpy(output, tls12_prf->output_block + offset, length); + output += length; + output_length -= length; + tls12_prf->left_in_block -= length; + } + + return PSA_SUCCESS; +} +#endif /* MBEDTLS_PSA_BUILTIN_ALG_TLS12_PRF || + * MBEDTLS_PSA_BUILTIN_ALG_TLS12_PSK_TO_MS */ + +#if defined(MBEDTLS_PSA_BUILTIN_ALG_TLS12_ECJPAKE_TO_PMS) +static psa_status_t psa_key_derivation_tls12_ecjpake_to_pms_read( + psa_tls12_ecjpake_to_pms_t *ecjpake, + uint8_t *output, + size_t output_length) +{ + psa_status_t status = PSA_ERROR_CORRUPTION_DETECTED; + size_t output_size = 0; + + if (output_length != 32) { + return PSA_ERROR_INVALID_ARGUMENT; + } + + status = psa_hash_compute(PSA_ALG_SHA_256, ecjpake->data, + PSA_TLS12_ECJPAKE_TO_PMS_DATA_SIZE, output, output_length, + &output_size); + if (status != PSA_SUCCESS) { + return status; + } + + if (output_size != output_length) { + return PSA_ERROR_GENERIC_ERROR; + } + + return PSA_SUCCESS; +} +#endif + +#if defined(PSA_HAVE_SOFT_PBKDF2) +static psa_status_t psa_key_derivation_pbkdf2_generate_block( + psa_pbkdf2_key_derivation_t *pbkdf2, + psa_algorithm_t prf_alg, + uint8_t prf_output_length, + psa_key_attributes_t *attributes) +{ + psa_status_t status; + psa_mac_operation_t mac_operation = PSA_MAC_OPERATION_INIT; + size_t mac_output_length; + uint8_t U_i[PSA_MAC_MAX_SIZE]; + uint8_t *U_accumulator = pbkdf2->output_block; + uint64_t i; + uint8_t block_counter[4]; + + mac_operation.is_sign = 1; + mac_operation.mac_size = prf_output_length; + MBEDTLS_PUT_UINT32_BE(pbkdf2->block_number, block_counter, 0); + + status = psa_driver_wrapper_mac_sign_setup(&mac_operation, + attributes, + pbkdf2->password, + pbkdf2->password_length, + prf_alg); + if (status != PSA_SUCCESS) { + goto cleanup; + } + status = psa_mac_update(&mac_operation, pbkdf2->salt, pbkdf2->salt_length); + if (status != PSA_SUCCESS) { + goto cleanup; + } + status = psa_mac_update(&mac_operation, block_counter, sizeof(block_counter)); + if (status != PSA_SUCCESS) { + goto cleanup; + } + status = psa_mac_sign_finish(&mac_operation, U_i, sizeof(U_i), + &mac_output_length); + if (status != PSA_SUCCESS) { + goto cleanup; + } + + if (mac_output_length != prf_output_length) { + status = PSA_ERROR_CORRUPTION_DETECTED; + goto cleanup; + } + + memcpy(U_accumulator, U_i, prf_output_length); + + for (i = 1; i < pbkdf2->input_cost; i++) { + /* We are passing prf_output_length as mac_size because the driver + * function directly sets mac_output_length as mac_size upon success. + * See https://github.com/Mbed-TLS/mbedtls/issues/7801 */ + status = psa_driver_wrapper_mac_compute(attributes, + pbkdf2->password, + pbkdf2->password_length, + prf_alg, U_i, prf_output_length, + U_i, prf_output_length, + &mac_output_length); + if (status != PSA_SUCCESS) { + goto cleanup; + } + + mbedtls_xor(U_accumulator, U_accumulator, U_i, prf_output_length); + } + +cleanup: + /* Zeroise buffers to clear sensitive data from memory. */ + mbedtls_platform_zeroize(U_i, PSA_MAC_MAX_SIZE); + return status; +} + +static psa_status_t psa_key_derivation_pbkdf2_read( + psa_pbkdf2_key_derivation_t *pbkdf2, + psa_algorithm_t kdf_alg, + uint8_t *output, + size_t output_length) +{ + psa_status_t status; + psa_algorithm_t prf_alg; + uint8_t prf_output_length; + psa_key_attributes_t attributes = PSA_KEY_ATTRIBUTES_INIT; + psa_set_key_bits(&attributes, PSA_BYTES_TO_BITS(pbkdf2->password_length)); + psa_set_key_usage_flags(&attributes, PSA_KEY_USAGE_SIGN_MESSAGE); + + if (PSA_ALG_IS_PBKDF2_HMAC(kdf_alg)) { + prf_alg = PSA_ALG_HMAC(PSA_ALG_PBKDF2_HMAC_GET_HASH(kdf_alg)); + prf_output_length = PSA_HASH_LENGTH(prf_alg); + psa_set_key_type(&attributes, PSA_KEY_TYPE_HMAC); + } else if (kdf_alg == PSA_ALG_PBKDF2_AES_CMAC_PRF_128) { + prf_alg = PSA_ALG_CMAC; + prf_output_length = PSA_MAC_LENGTH(PSA_KEY_TYPE_AES, 128U, PSA_ALG_CMAC); + psa_set_key_type(&attributes, PSA_KEY_TYPE_AES); + } else { + return PSA_ERROR_INVALID_ARGUMENT; + } + + switch (pbkdf2->state) { + case PSA_PBKDF2_STATE_PASSWORD_SET: + /* Initially we need a new block so bytes_used is equal to block size*/ + pbkdf2->bytes_used = prf_output_length; + pbkdf2->state = PSA_PBKDF2_STATE_OUTPUT; + break; + case PSA_PBKDF2_STATE_OUTPUT: + break; + default: + return PSA_ERROR_BAD_STATE; + } + + while (output_length != 0) { + uint8_t n = prf_output_length - pbkdf2->bytes_used; + if (n > output_length) { + n = (uint8_t) output_length; + } + memcpy(output, pbkdf2->output_block + pbkdf2->bytes_used, n); + output += n; + output_length -= n; + pbkdf2->bytes_used += n; + + if (output_length == 0) { + break; + } + + /* We need a new block */ + pbkdf2->bytes_used = 0; + pbkdf2->block_number++; + + status = psa_key_derivation_pbkdf2_generate_block(pbkdf2, prf_alg, + prf_output_length, + &attributes); + if (status != PSA_SUCCESS) { + return status; + } + } + + return PSA_SUCCESS; +} +#endif /* PSA_HAVE_SOFT_PBKDF2 */ + +psa_status_t psa_key_derivation_output_bytes( + psa_key_derivation_operation_t *operation, + uint8_t *output_external, + size_t output_length) +{ + psa_status_t status; + LOCAL_OUTPUT_DECLARE(output_external, output); + + psa_algorithm_t kdf_alg = psa_key_derivation_get_kdf_alg(operation); + + if (operation->alg == 0) { + /* This is a blank operation. */ + return PSA_ERROR_BAD_STATE; + } + + if (output_length == 0 && operation->capacity == 0) { + /* Edge case: this is a finished operation, and 0 bytes + * were requested. The right error in this case could + * be either INSUFFICIENT_CAPACITY or BAD_STATE. Return + * INSUFFICIENT_CAPACITY, which is right for a finished + * operation, for consistency with the case when + * output_length > 0. */ + return PSA_ERROR_INSUFFICIENT_DATA; + } + + LOCAL_OUTPUT_ALLOC(output_external, output_length, output); + if (output_length > operation->capacity) { + operation->capacity = 0; + /* Go through the error path to wipe all confidential data now + * that the operation object is useless. */ + status = PSA_ERROR_INSUFFICIENT_DATA; + goto exit; + } + + operation->capacity -= output_length; + +#if defined(BUILTIN_ALG_ANY_HKDF) + if (PSA_ALG_IS_ANY_HKDF(kdf_alg)) { + status = psa_key_derivation_hkdf_read(&operation->ctx.hkdf, kdf_alg, + output, output_length); + } else +#endif /* BUILTIN_ALG_ANY_HKDF */ +#if defined(MBEDTLS_PSA_BUILTIN_ALG_TLS12_PRF) || \ + defined(MBEDTLS_PSA_BUILTIN_ALG_TLS12_PSK_TO_MS) + if (PSA_ALG_IS_TLS12_PRF(kdf_alg) || + PSA_ALG_IS_TLS12_PSK_TO_MS(kdf_alg)) { + status = psa_key_derivation_tls12_prf_read(&operation->ctx.tls12_prf, + kdf_alg, output, + output_length); + } else +#endif /* MBEDTLS_PSA_BUILTIN_ALG_TLS12_PRF || + * MBEDTLS_PSA_BUILTIN_ALG_TLS12_PSK_TO_MS */ +#if defined(MBEDTLS_PSA_BUILTIN_ALG_TLS12_ECJPAKE_TO_PMS) + if (kdf_alg == PSA_ALG_TLS12_ECJPAKE_TO_PMS) { + status = psa_key_derivation_tls12_ecjpake_to_pms_read( + &operation->ctx.tls12_ecjpake_to_pms, output, output_length); + } else +#endif /* MBEDTLS_PSA_BUILTIN_ALG_TLS12_ECJPAKE_TO_PMS */ +#if defined(PSA_HAVE_SOFT_PBKDF2) + if (PSA_ALG_IS_PBKDF2(kdf_alg)) { + status = psa_key_derivation_pbkdf2_read(&operation->ctx.pbkdf2, kdf_alg, + output, output_length); + } else +#endif /* PSA_HAVE_SOFT_PBKDF2 */ + + { + (void) kdf_alg; + status = PSA_ERROR_BAD_STATE; + LOCAL_OUTPUT_FREE(output_external, output); + + return status; + } + +exit: + if (status != PSA_SUCCESS) { + /* Preserve the algorithm upon errors, but clear all sensitive state. + * This allows us to differentiate between exhausted operations and + * blank operations, so we can return PSA_ERROR_BAD_STATE on blank + * operations. */ + psa_algorithm_t alg = operation->alg; + psa_key_derivation_abort(operation); + operation->alg = alg; + if (output != NULL) { + memset(output, '!', output_length); + } + } + + LOCAL_OUTPUT_FREE(output_external, output); + return status; +} + +#if defined(MBEDTLS_PSA_BUILTIN_KEY_TYPE_DES) +static void psa_des_set_key_parity(uint8_t *data, size_t data_size) +{ + if (data_size >= 8) { + mbedtls_des_key_set_parity(data); + } + if (data_size >= 16) { + mbedtls_des_key_set_parity(data + 8); + } + if (data_size >= 24) { + mbedtls_des_key_set_parity(data + 16); + } +} +#endif /* MBEDTLS_PSA_BUILTIN_KEY_TYPE_DES */ + +/* + * ECC keys on a Weierstrass elliptic curve require the generation + * of a private key which is an integer + * in the range [1, N - 1], where N is the boundary of the private key domain: + * N is the prime p for Diffie-Hellman, or the order of the + * curve’s base point for ECC. + * + * Let m be the bit size of N, such that 2^m > N >= 2^(m-1). + * This function generates the private key using the following process: + * + * 1. Draw a byte string of length ceiling(m/8) bytes. + * 2. If m is not a multiple of 8, set the most significant + * (8 * ceiling(m/8) - m) bits of the first byte in the string to zero. + * 3. Convert the string to integer k by decoding it as a big-endian byte string. + * 4. If k > N - 2, discard the result and return to step 1. + * 5. Output k + 1 as the private key. + * + * This method allows compliance to NIST standards, specifically the methods titled + * Key-Pair Generation by Testing Candidates in the following publications: + * - NIST Special Publication 800-56A: Recommendation for Pair-Wise Key-Establishment + * Schemes Using Discrete Logarithm Cryptography [SP800-56A] §5.6.1.1.4 for + * Diffie-Hellman keys. + * + * - [SP800-56A] §5.6.1.2.2 or FIPS Publication 186-4: Digital Signature + * Standard (DSS) [FIPS186-4] §B.4.2 for elliptic curve keys. + * + * Note: Function allocates memory for *data buffer, so given *data should be + * always NULL. + */ +#if defined(PSA_WANT_KEY_TYPE_ECC_KEY_PAIR_DERIVE) +#if defined(MBEDTLS_PSA_BUILTIN_KEY_TYPE_ECC_KEY_PAIR_DERIVE) +static psa_status_t psa_generate_derived_ecc_key_weierstrass_helper( + psa_key_slot_t *slot, + size_t bits, + psa_key_derivation_operation_t *operation, + uint8_t **data + ) +{ + unsigned key_out_of_range = 1; + mbedtls_mpi k; + mbedtls_mpi diff_N_2; + int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED; + psa_status_t status = PSA_ERROR_CORRUPTION_DETECTED; + size_t m; + size_t m_bytes; + + mbedtls_mpi_init(&k); + mbedtls_mpi_init(&diff_N_2); + + psa_ecc_family_t curve = PSA_KEY_TYPE_ECC_GET_FAMILY( + slot->attr.type); + mbedtls_ecp_group_id grp_id = + mbedtls_ecc_group_from_psa(curve, bits); + + if (grp_id == MBEDTLS_ECP_DP_NONE) { + ret = MBEDTLS_ERR_ASN1_INVALID_DATA; + goto cleanup; + } + + mbedtls_ecp_group ecp_group; + mbedtls_ecp_group_init(&ecp_group); + + MBEDTLS_MPI_CHK(mbedtls_ecp_group_load(&ecp_group, grp_id)); + + /* N is the boundary of the private key domain (ecp_group.N). */ + /* Let m be the bit size of N. */ + m = ecp_group.nbits; + + m_bytes = PSA_BITS_TO_BYTES(m); + + /* Calculate N - 2 - it will be needed later. */ + MBEDTLS_MPI_CHK(mbedtls_mpi_sub_int(&diff_N_2, &ecp_group.N, 2)); + + /* Note: This function is always called with *data == NULL and it + * allocates memory for the data buffer. */ + *data = mbedtls_calloc(1, m_bytes); + if (*data == NULL) { + ret = MBEDTLS_ERR_ASN1_ALLOC_FAILED; + goto cleanup; + } + + while (key_out_of_range) { + /* 1. Draw a byte string of length ceiling(m/8) bytes. */ + if ((status = psa_key_derivation_output_bytes(operation, *data, m_bytes)) != 0) { + goto cleanup; + } + + /* 2. If m is not a multiple of 8 */ + if (m % 8 != 0) { + /* Set the most significant + * (8 * ceiling(m/8) - m) bits of the first byte in + * the string to zero. + */ + uint8_t clear_bit_mask = (1 << (m % 8)) - 1; + (*data)[0] &= clear_bit_mask; + } + + /* 3. Convert the string to integer k by decoding it as a + * big-endian byte string. + */ + MBEDTLS_MPI_CHK(mbedtls_mpi_read_binary(&k, *data, m_bytes)); + + /* 4. If k > N - 2, discard the result and return to step 1. + * Result of comparison is returned. When it indicates error + * then this function is called again. + */ + MBEDTLS_MPI_CHK(mbedtls_mpi_lt_mpi_ct(&diff_N_2, &k, &key_out_of_range)); + } + + /* 5. Output k + 1 as the private key. */ + MBEDTLS_MPI_CHK(mbedtls_mpi_add_int(&k, &k, 1)); + MBEDTLS_MPI_CHK(mbedtls_mpi_write_binary(&k, *data, m_bytes)); +cleanup: + if (ret != 0) { + status = mbedtls_to_psa_error(ret); + } + if (status != PSA_SUCCESS) { + mbedtls_free(*data); + *data = NULL; + } + mbedtls_mpi_free(&k); + mbedtls_mpi_free(&diff_N_2); + return status; +} + +/* ECC keys on a Montgomery elliptic curve draws a byte string whose length + * is determined by the curve, and sets the mandatory bits accordingly. That is: + * + * - Curve25519 (PSA_ECC_FAMILY_MONTGOMERY, 255 bits): + * draw a 32-byte string and process it as specified in + * Elliptic Curves for Security [RFC7748] §5. + * + * - Curve448 (PSA_ECC_FAMILY_MONTGOMERY, 448 bits): + * draw a 56-byte string and process it as specified in [RFC7748] §5. + * + * Note: Function allocates memory for *data buffer, so given *data should be + * always NULL. + */ + +static psa_status_t psa_generate_derived_ecc_key_montgomery_helper( + size_t bits, + psa_key_derivation_operation_t *operation, + uint8_t **data + ) +{ + size_t output_length; + psa_status_t status = PSA_ERROR_CORRUPTION_DETECTED; + + switch (bits) { + case 255: + output_length = 32; + break; + case 448: + output_length = 56; + break; + default: + return PSA_ERROR_INVALID_ARGUMENT; + break; + } + + *data = mbedtls_calloc(1, output_length); + + if (*data == NULL) { + return PSA_ERROR_INSUFFICIENT_MEMORY; + } + + status = psa_key_derivation_output_bytes(operation, *data, output_length); + + if (status != PSA_SUCCESS) { + return status; + } + + switch (bits) { + case 255: + (*data)[0] &= 248; + (*data)[31] &= 127; + (*data)[31] |= 64; + break; + case 448: + (*data)[0] &= 252; + (*data)[55] |= 128; + break; + default: + return PSA_ERROR_CORRUPTION_DETECTED; + break; + } + + return status; +} +#else /* MBEDTLS_PSA_BUILTIN_KEY_TYPE_ECC_KEY_PAIR_DERIVE */ +static psa_status_t psa_generate_derived_ecc_key_weierstrass_helper( + psa_key_slot_t *slot, size_t bits, + psa_key_derivation_operation_t *operation, uint8_t **data) +{ + (void) slot; + (void) bits; + (void) operation; + (void) data; + return PSA_ERROR_NOT_SUPPORTED; +} + +static psa_status_t psa_generate_derived_ecc_key_montgomery_helper( + size_t bits, psa_key_derivation_operation_t *operation, uint8_t **data) +{ + (void) bits; + (void) operation; + (void) data; + return PSA_ERROR_NOT_SUPPORTED; +} +#endif /* MBEDTLS_PSA_BUILTIN_KEY_TYPE_ECC_KEY_PAIR_DERIVE */ +#endif /* PSA_WANT_KEY_TYPE_ECC_KEY_PAIR_DERIVE */ + +static psa_status_t psa_generate_derived_key_internal( + psa_key_slot_t *slot, + size_t bits, + psa_key_derivation_operation_t *operation) +{ + uint8_t *data = NULL; + size_t bytes = PSA_BITS_TO_BYTES(bits); + size_t storage_size = bytes; + psa_status_t status = PSA_ERROR_CORRUPTION_DETECTED; + + if (PSA_KEY_TYPE_IS_PUBLIC_KEY(slot->attr.type)) { + return PSA_ERROR_INVALID_ARGUMENT; + } + +#if defined(PSA_WANT_KEY_TYPE_ECC_KEY_PAIR_DERIVE) || \ + defined(MBEDTLS_PSA_BUILTIN_KEY_TYPE_ECC_KEY_PAIR_DERIVE) + if (PSA_KEY_TYPE_IS_ECC(slot->attr.type)) { + psa_ecc_family_t curve = PSA_KEY_TYPE_ECC_GET_FAMILY(slot->attr.type); + if (PSA_ECC_FAMILY_IS_WEIERSTRASS(curve)) { + /* Weierstrass elliptic curve */ + status = psa_generate_derived_ecc_key_weierstrass_helper(slot, bits, operation, &data); + if (status != PSA_SUCCESS) { + goto exit; + } + } else { + /* Montgomery elliptic curve */ + status = psa_generate_derived_ecc_key_montgomery_helper(bits, operation, &data); + if (status != PSA_SUCCESS) { + goto exit; + } + } + } else +#endif /* defined(PSA_WANT_KEY_TYPE_ECC_KEY_PAIR_DERIVE) || + defined(MBEDTLS_PSA_BUILTIN_KEY_TYPE_ECC_KEY_PAIR_DERIVE) */ + if (key_type_is_raw_bytes(slot->attr.type)) { + if (bits % 8 != 0) { + return PSA_ERROR_INVALID_ARGUMENT; + } + data = mbedtls_calloc(1, bytes); + if (data == NULL) { + return PSA_ERROR_INSUFFICIENT_MEMORY; + } + + status = psa_key_derivation_output_bytes(operation, data, bytes); + if (status != PSA_SUCCESS) { + goto exit; + } +#if defined(MBEDTLS_PSA_BUILTIN_KEY_TYPE_DES) + if (slot->attr.type == PSA_KEY_TYPE_DES) { + psa_des_set_key_parity(data, bytes); + } +#endif /* defined(MBEDTLS_PSA_BUILTIN_KEY_TYPE_DES) */ + } else { + return PSA_ERROR_NOT_SUPPORTED; + } + + slot->attr.bits = (psa_key_bits_t) bits; + + if (psa_key_lifetime_is_external(slot->attr.lifetime)) { + status = psa_driver_wrapper_get_key_buffer_size(&slot->attr, + &storage_size); + if (status != PSA_SUCCESS) { + goto exit; + } + } + status = psa_allocate_buffer_to_slot(slot, storage_size); + if (status != PSA_SUCCESS) { + goto exit; + } + + status = psa_driver_wrapper_import_key(&slot->attr, + data, bytes, + slot->key.data, + slot->key.bytes, + &slot->key.bytes, &bits); + if (bits != slot->attr.bits) { + status = PSA_ERROR_INVALID_ARGUMENT; + } + +exit: + mbedtls_free(data); + return status; +} + +static const psa_key_production_parameters_t default_production_parameters = + PSA_KEY_PRODUCTION_PARAMETERS_INIT; + +int psa_key_production_parameters_are_default( + const psa_key_production_parameters_t *params, + size_t params_data_length) +{ + if (params->flags != 0) { + return 0; + } + if (params_data_length != 0) { + return 0; + } + return 1; +} + +psa_status_t psa_key_derivation_output_key_ext( + const psa_key_attributes_t *attributes, + psa_key_derivation_operation_t *operation, + const psa_key_production_parameters_t *params, + size_t params_data_length, + mbedtls_svc_key_id_t *key) +{ + psa_status_t status; + psa_key_slot_t *slot = NULL; + psa_se_drv_table_entry_t *driver = NULL; + + *key = MBEDTLS_SVC_KEY_ID_INIT; + + /* Reject any attempt to create a zero-length key so that we don't + * risk tripping up later, e.g. on a malloc(0) that returns NULL. */ + if (psa_get_key_bits(attributes) == 0) { + return PSA_ERROR_INVALID_ARGUMENT; + } + + if (!psa_key_production_parameters_are_default(params, params_data_length)) { + return PSA_ERROR_INVALID_ARGUMENT; + } + + if (operation->alg == PSA_ALG_NONE) { + return PSA_ERROR_BAD_STATE; + } + + if (!operation->can_output_key) { + return PSA_ERROR_NOT_PERMITTED; + } + + status = psa_start_key_creation(PSA_KEY_CREATION_DERIVE, attributes, + &slot, &driver); +#if defined(MBEDTLS_PSA_CRYPTO_SE_C) + if (driver != NULL) { + /* Deriving a key in a secure element is not implemented yet. */ + status = PSA_ERROR_NOT_SUPPORTED; + } +#endif /* MBEDTLS_PSA_CRYPTO_SE_C */ + if (status == PSA_SUCCESS) { + status = psa_generate_derived_key_internal(slot, + attributes->bits, + operation); + } + if (status == PSA_SUCCESS) { + status = psa_finish_key_creation(slot, driver, key); + } + if (status != PSA_SUCCESS) { + psa_fail_key_creation(slot, driver); + } + + return status; +} + +psa_status_t psa_key_derivation_output_key( + const psa_key_attributes_t *attributes, + psa_key_derivation_operation_t *operation, + mbedtls_svc_key_id_t *key) +{ + return psa_key_derivation_output_key_ext(attributes, operation, + &default_production_parameters, 0, + key); +} + + +/****************************************************************/ +/* Key derivation */ +/****************************************************************/ + +#if defined(AT_LEAST_ONE_BUILTIN_KDF) +static int is_kdf_alg_supported(psa_algorithm_t kdf_alg) +{ +#if defined(MBEDTLS_PSA_BUILTIN_ALG_HKDF) + if (PSA_ALG_IS_HKDF(kdf_alg)) { + return 1; + } +#endif +#if defined(MBEDTLS_PSA_BUILTIN_ALG_HKDF_EXTRACT) + if (PSA_ALG_IS_HKDF_EXTRACT(kdf_alg)) { + return 1; + } +#endif +#if defined(MBEDTLS_PSA_BUILTIN_ALG_HKDF_EXPAND) + if (PSA_ALG_IS_HKDF_EXPAND(kdf_alg)) { + return 1; + } +#endif +#if defined(MBEDTLS_PSA_BUILTIN_ALG_TLS12_PRF) + if (PSA_ALG_IS_TLS12_PRF(kdf_alg)) { + return 1; + } +#endif +#if defined(MBEDTLS_PSA_BUILTIN_ALG_TLS12_PSK_TO_MS) + if (PSA_ALG_IS_TLS12_PSK_TO_MS(kdf_alg)) { + return 1; + } +#endif +#if defined(MBEDTLS_PSA_BUILTIN_ALG_TLS12_ECJPAKE_TO_PMS) + if (kdf_alg == PSA_ALG_TLS12_ECJPAKE_TO_PMS) { + return 1; + } +#endif +#if defined(MBEDTLS_PSA_BUILTIN_ALG_PBKDF2_HMAC) + if (PSA_ALG_IS_PBKDF2_HMAC(kdf_alg)) { + return 1; + } +#endif +#if defined(MBEDTLS_PSA_BUILTIN_ALG_PBKDF2_AES_CMAC_PRF_128) + if (kdf_alg == PSA_ALG_PBKDF2_AES_CMAC_PRF_128) { + return 1; + } +#endif + return 0; +} + +static psa_status_t psa_hash_try_support(psa_algorithm_t alg) +{ + psa_hash_operation_t operation = PSA_HASH_OPERATION_INIT; + psa_status_t status = psa_hash_setup(&operation, alg); + psa_hash_abort(&operation); + return status; +} + +static psa_status_t psa_key_derivation_set_maximum_capacity( + psa_key_derivation_operation_t *operation, + psa_algorithm_t kdf_alg) +{ +#if defined(PSA_WANT_ALG_TLS12_ECJPAKE_TO_PMS) + if (kdf_alg == PSA_ALG_TLS12_ECJPAKE_TO_PMS) { + operation->capacity = PSA_HASH_LENGTH(PSA_ALG_SHA_256); + return PSA_SUCCESS; + } +#endif +#if defined(PSA_WANT_ALG_PBKDF2_AES_CMAC_PRF_128) + if (kdf_alg == PSA_ALG_PBKDF2_AES_CMAC_PRF_128) { +#if (SIZE_MAX > UINT32_MAX) + operation->capacity = UINT32_MAX * (size_t) PSA_MAC_LENGTH( + PSA_KEY_TYPE_AES, + 128U, + PSA_ALG_CMAC); +#else + operation->capacity = SIZE_MAX; +#endif + return PSA_SUCCESS; + } +#endif /* PSA_WANT_ALG_PBKDF2_AES_CMAC_PRF_128 */ + + /* After this point, if kdf_alg is not valid then value of hash_alg may be + * invalid or meaningless but it does not affect this function */ + psa_algorithm_t hash_alg = PSA_ALG_GET_HASH(kdf_alg); + size_t hash_size = PSA_HASH_LENGTH(hash_alg); + if (hash_size == 0) { + return PSA_ERROR_NOT_SUPPORTED; + } + + /* Make sure that hash_alg is a supported hash algorithm. Otherwise + * we might fail later, which is somewhat unfriendly and potentially + * risk-prone. */ + psa_status_t status = psa_hash_try_support(hash_alg); + if (status != PSA_SUCCESS) { + return status; + } + +#if defined(PSA_WANT_ALG_HKDF) + if (PSA_ALG_IS_HKDF(kdf_alg)) { + operation->capacity = 255 * hash_size; + } else +#endif +#if defined(PSA_WANT_ALG_HKDF_EXTRACT) + if (PSA_ALG_IS_HKDF_EXTRACT(kdf_alg)) { + operation->capacity = hash_size; + } else +#endif +#if defined(PSA_WANT_ALG_HKDF_EXPAND) + if (PSA_ALG_IS_HKDF_EXPAND(kdf_alg)) { + operation->capacity = 255 * hash_size; + } else +#endif +#if defined(PSA_WANT_ALG_TLS12_PRF) + if (PSA_ALG_IS_TLS12_PRF(kdf_alg) && + (hash_alg == PSA_ALG_SHA_256 || hash_alg == PSA_ALG_SHA_384)) { + operation->capacity = SIZE_MAX; + } else +#endif +#if defined(PSA_WANT_ALG_TLS12_PSK_TO_MS) + if (PSA_ALG_IS_TLS12_PSK_TO_MS(kdf_alg) && + (hash_alg == PSA_ALG_SHA_256 || hash_alg == PSA_ALG_SHA_384)) { + /* Master Secret is always 48 bytes + * https://datatracker.ietf.org/doc/html/rfc5246.html#section-8.1 */ + operation->capacity = 48U; + } else +#endif +#if defined(PSA_WANT_ALG_PBKDF2_HMAC) + if (PSA_ALG_IS_PBKDF2_HMAC(kdf_alg)) { +#if (SIZE_MAX > UINT32_MAX) + operation->capacity = UINT32_MAX * hash_size; +#else + operation->capacity = SIZE_MAX; +#endif + } else +#endif /* PSA_WANT_ALG_PBKDF2_HMAC */ + { + (void) hash_size; + status = PSA_ERROR_NOT_SUPPORTED; + } + return status; +} + +static psa_status_t psa_key_derivation_setup_kdf( + psa_key_derivation_operation_t *operation, + psa_algorithm_t kdf_alg) +{ + /* Make sure that operation->ctx is properly zero-initialised. (Macro + * initialisers for this union leave some bytes unspecified.) */ + memset(&operation->ctx, 0, sizeof(operation->ctx)); + + /* Make sure that kdf_alg is a supported key derivation algorithm. */ + if (!is_kdf_alg_supported(kdf_alg)) { + return PSA_ERROR_NOT_SUPPORTED; + } + + psa_status_t status = psa_key_derivation_set_maximum_capacity(operation, + kdf_alg); + return status; +} + +static psa_status_t psa_key_agreement_try_support(psa_algorithm_t alg) +{ +#if defined(PSA_WANT_ALG_ECDH) + if (alg == PSA_ALG_ECDH) { + return PSA_SUCCESS; + } +#endif +#if defined(PSA_WANT_ALG_FFDH) + if (alg == PSA_ALG_FFDH) { + return PSA_SUCCESS; + } +#endif + (void) alg; + return PSA_ERROR_NOT_SUPPORTED; +} + +static int psa_key_derivation_allows_free_form_secret_input( + psa_algorithm_t kdf_alg) +{ +#if defined(PSA_WANT_ALG_TLS12_ECJPAKE_TO_PMS) + if (kdf_alg == PSA_ALG_TLS12_ECJPAKE_TO_PMS) { + return 0; + } +#endif + (void) kdf_alg; + return 1; +} +#endif /* AT_LEAST_ONE_BUILTIN_KDF */ + +psa_status_t psa_key_derivation_setup(psa_key_derivation_operation_t *operation, + psa_algorithm_t alg) +{ + psa_status_t status; + + if (operation->alg != 0) { + return PSA_ERROR_BAD_STATE; + } + + if (PSA_ALG_IS_RAW_KEY_AGREEMENT(alg)) { + return PSA_ERROR_INVALID_ARGUMENT; + } else if (PSA_ALG_IS_KEY_AGREEMENT(alg)) { +#if defined(AT_LEAST_ONE_BUILTIN_KDF) + psa_algorithm_t kdf_alg = PSA_ALG_KEY_AGREEMENT_GET_KDF(alg); + psa_algorithm_t ka_alg = PSA_ALG_KEY_AGREEMENT_GET_BASE(alg); + status = psa_key_agreement_try_support(ka_alg); + if (status != PSA_SUCCESS) { + return status; + } + if (!psa_key_derivation_allows_free_form_secret_input(kdf_alg)) { + return PSA_ERROR_INVALID_ARGUMENT; + } + status = psa_key_derivation_setup_kdf(operation, kdf_alg); +#else + return PSA_ERROR_NOT_SUPPORTED; +#endif /* AT_LEAST_ONE_BUILTIN_KDF */ + } else if (PSA_ALG_IS_KEY_DERIVATION(alg)) { +#if defined(AT_LEAST_ONE_BUILTIN_KDF) + status = psa_key_derivation_setup_kdf(operation, alg); +#else + return PSA_ERROR_NOT_SUPPORTED; +#endif /* AT_LEAST_ONE_BUILTIN_KDF */ + } else { + return PSA_ERROR_INVALID_ARGUMENT; + } + + if (status == PSA_SUCCESS) { + operation->alg = alg; + } + return status; +} + +#if defined(BUILTIN_ALG_ANY_HKDF) +static psa_status_t psa_hkdf_input(psa_hkdf_key_derivation_t *hkdf, + psa_algorithm_t kdf_alg, + psa_key_derivation_step_t step, + const uint8_t *data, + size_t data_length) +{ + psa_algorithm_t hash_alg = PSA_ALG_HKDF_GET_HASH(kdf_alg); + psa_status_t status; + switch (step) { + case PSA_KEY_DERIVATION_INPUT_SALT: +#if defined(MBEDTLS_PSA_BUILTIN_ALG_HKDF_EXPAND) + if (PSA_ALG_IS_HKDF_EXPAND(kdf_alg)) { + return PSA_ERROR_INVALID_ARGUMENT; + } +#endif /* MBEDTLS_PSA_BUILTIN_ALG_HKDF_EXPAND */ + if (hkdf->state != HKDF_STATE_INIT) { + return PSA_ERROR_BAD_STATE; + } else { + status = psa_key_derivation_start_hmac(&hkdf->hmac, + hash_alg, + data, data_length); + if (status != PSA_SUCCESS) { + return status; + } + hkdf->state = HKDF_STATE_STARTED; + return PSA_SUCCESS; + } + case PSA_KEY_DERIVATION_INPUT_SECRET: +#if defined(MBEDTLS_PSA_BUILTIN_ALG_HKDF_EXPAND) + if (PSA_ALG_IS_HKDF_EXPAND(kdf_alg)) { + /* We shouldn't be in different state as HKDF_EXPAND only allows + * two inputs: SECRET (this case) and INFO which does not modify + * the state. It could happen only if the hkdf + * object was corrupted. */ + if (hkdf->state != HKDF_STATE_INIT) { + return PSA_ERROR_BAD_STATE; + } + + /* Allow only input that fits expected prk size */ + if (data_length != PSA_HASH_LENGTH(hash_alg)) { + return PSA_ERROR_INVALID_ARGUMENT; + } + + memcpy(hkdf->prk, data, data_length); + } else +#endif /* MBEDTLS_PSA_BUILTIN_ALG_HKDF_EXPAND */ + { + /* HKDF: If no salt was provided, use an empty salt. + * HKDF-EXTRACT: salt is mandatory. */ + if (hkdf->state == HKDF_STATE_INIT) { +#if defined(MBEDTLS_PSA_BUILTIN_ALG_HKDF_EXTRACT) + if (PSA_ALG_IS_HKDF_EXTRACT(kdf_alg)) { + return PSA_ERROR_BAD_STATE; + } +#endif /* MBEDTLS_PSA_BUILTIN_ALG_HKDF_EXTRACT */ + status = psa_key_derivation_start_hmac(&hkdf->hmac, + hash_alg, + NULL, 0); + if (status != PSA_SUCCESS) { + return status; + } + hkdf->state = HKDF_STATE_STARTED; + } + if (hkdf->state != HKDF_STATE_STARTED) { + return PSA_ERROR_BAD_STATE; + } + status = psa_mac_update(&hkdf->hmac, + data, data_length); + if (status != PSA_SUCCESS) { + return status; + } + status = psa_mac_sign_finish(&hkdf->hmac, + hkdf->prk, + sizeof(hkdf->prk), + &data_length); + if (status != PSA_SUCCESS) { + return status; + } + } + + hkdf->state = HKDF_STATE_KEYED; + hkdf->block_number = 0; +#if defined(MBEDTLS_PSA_BUILTIN_ALG_HKDF_EXTRACT) + if (PSA_ALG_IS_HKDF_EXTRACT(kdf_alg)) { + /* The only block of output is the PRK. */ + memcpy(hkdf->output_block, hkdf->prk, PSA_HASH_LENGTH(hash_alg)); + hkdf->offset_in_block = 0; + } else +#endif /* MBEDTLS_PSA_BUILTIN_ALG_HKDF_EXTRACT */ + { + /* Block 0 is empty, and the next block will be + * generated by psa_key_derivation_hkdf_read(). */ + hkdf->offset_in_block = PSA_HASH_LENGTH(hash_alg); + } + + return PSA_SUCCESS; + case PSA_KEY_DERIVATION_INPUT_INFO: +#if defined(MBEDTLS_PSA_BUILTIN_ALG_HKDF_EXTRACT) + if (PSA_ALG_IS_HKDF_EXTRACT(kdf_alg)) { + return PSA_ERROR_INVALID_ARGUMENT; + } +#endif /* MBEDTLS_PSA_BUILTIN_ALG_HKDF_EXTRACT */ +#if defined(MBEDTLS_PSA_BUILTIN_ALG_HKDF_EXPAND) + if (PSA_ALG_IS_HKDF_EXPAND(kdf_alg) && + hkdf->state == HKDF_STATE_INIT) { + return PSA_ERROR_BAD_STATE; + } +#endif /* MBEDTLS_PSA_BUILTIN_ALG_HKDF_EXTRACT */ + if (hkdf->state == HKDF_STATE_OUTPUT) { + return PSA_ERROR_BAD_STATE; + } + if (hkdf->info_set) { + return PSA_ERROR_BAD_STATE; + } + hkdf->info_length = data_length; + if (data_length != 0) { + hkdf->info = mbedtls_calloc(1, data_length); + if (hkdf->info == NULL) { + return PSA_ERROR_INSUFFICIENT_MEMORY; + } + memcpy(hkdf->info, data, data_length); + } + hkdf->info_set = 1; + return PSA_SUCCESS; + default: + return PSA_ERROR_INVALID_ARGUMENT; + } +} +#endif /* BUILTIN_ALG_ANY_HKDF */ + +#if defined(MBEDTLS_PSA_BUILTIN_ALG_TLS12_PRF) || \ + defined(MBEDTLS_PSA_BUILTIN_ALG_TLS12_PSK_TO_MS) +static psa_status_t psa_tls12_prf_set_seed(psa_tls12_prf_key_derivation_t *prf, + const uint8_t *data, + size_t data_length) +{ + if (prf->state != PSA_TLS12_PRF_STATE_INIT) { + return PSA_ERROR_BAD_STATE; + } + + if (data_length != 0) { + prf->seed = mbedtls_calloc(1, data_length); + if (prf->seed == NULL) { + return PSA_ERROR_INSUFFICIENT_MEMORY; + } + + memcpy(prf->seed, data, data_length); + prf->seed_length = data_length; + } + + prf->state = PSA_TLS12_PRF_STATE_SEED_SET; + + return PSA_SUCCESS; +} + +static psa_status_t psa_tls12_prf_set_key(psa_tls12_prf_key_derivation_t *prf, + const uint8_t *data, + size_t data_length) +{ + if (prf->state != PSA_TLS12_PRF_STATE_SEED_SET && + prf->state != PSA_TLS12_PRF_STATE_OTHER_KEY_SET) { + return PSA_ERROR_BAD_STATE; + } + + if (data_length != 0) { + prf->secret = mbedtls_calloc(1, data_length); + if (prf->secret == NULL) { + return PSA_ERROR_INSUFFICIENT_MEMORY; + } + + memcpy(prf->secret, data, data_length); + prf->secret_length = data_length; + } + + prf->state = PSA_TLS12_PRF_STATE_KEY_SET; + + return PSA_SUCCESS; +} + +static psa_status_t psa_tls12_prf_set_label(psa_tls12_prf_key_derivation_t *prf, + const uint8_t *data, + size_t data_length) +{ + if (prf->state != PSA_TLS12_PRF_STATE_KEY_SET) { + return PSA_ERROR_BAD_STATE; + } + + if (data_length != 0) { + prf->label = mbedtls_calloc(1, data_length); + if (prf->label == NULL) { + return PSA_ERROR_INSUFFICIENT_MEMORY; + } + + memcpy(prf->label, data, data_length); + prf->label_length = data_length; + } + + prf->state = PSA_TLS12_PRF_STATE_LABEL_SET; + + return PSA_SUCCESS; +} + +static psa_status_t psa_tls12_prf_input(psa_tls12_prf_key_derivation_t *prf, + psa_key_derivation_step_t step, + const uint8_t *data, + size_t data_length) +{ + switch (step) { + case PSA_KEY_DERIVATION_INPUT_SEED: + return psa_tls12_prf_set_seed(prf, data, data_length); + case PSA_KEY_DERIVATION_INPUT_SECRET: + return psa_tls12_prf_set_key(prf, data, data_length); + case PSA_KEY_DERIVATION_INPUT_LABEL: + return psa_tls12_prf_set_label(prf, data, data_length); + default: + return PSA_ERROR_INVALID_ARGUMENT; + } +} +#endif /* MBEDTLS_PSA_BUILTIN_ALG_TLS12_PRF) || + * MBEDTLS_PSA_BUILTIN_ALG_TLS12_PSK_TO_MS */ + +#if defined(MBEDTLS_PSA_BUILTIN_ALG_TLS12_PSK_TO_MS) +static psa_status_t psa_tls12_prf_psk_to_ms_set_key( + psa_tls12_prf_key_derivation_t *prf, + const uint8_t *data, + size_t data_length) +{ + psa_status_t status; + const size_t pms_len = (prf->state == PSA_TLS12_PRF_STATE_OTHER_KEY_SET ? + 4 + data_length + prf->other_secret_length : + 4 + 2 * data_length); + + if (data_length > PSA_TLS12_PSK_TO_MS_PSK_MAX_SIZE) { + return PSA_ERROR_INVALID_ARGUMENT; + } + + uint8_t *pms = mbedtls_calloc(1, pms_len); + if (pms == NULL) { + return PSA_ERROR_INSUFFICIENT_MEMORY; + } + uint8_t *cur = pms; + + /* pure-PSK: + * Quoting RFC 4279, Section 2: + * + * The premaster secret is formed as follows: if the PSK is N octets + * long, concatenate a uint16 with the value N, N zero octets, a second + * uint16 with the value N, and the PSK itself. + * + * mixed-PSK: + * In a DHE-PSK, RSA-PSK, ECDHE-PSK the premaster secret is formed as + * follows: concatenate a uint16 with the length of the other secret, + * the other secret itself, uint16 with the length of PSK, and the + * PSK itself. + * For details please check: + * - RFC 4279, Section 4 for the definition of RSA-PSK, + * - RFC 4279, Section 3 for the definition of DHE-PSK, + * - RFC 5489 for the definition of ECDHE-PSK. + */ + + if (prf->state == PSA_TLS12_PRF_STATE_OTHER_KEY_SET) { + *cur++ = MBEDTLS_BYTE_1(prf->other_secret_length); + *cur++ = MBEDTLS_BYTE_0(prf->other_secret_length); + if (prf->other_secret_length != 0) { + memcpy(cur, prf->other_secret, prf->other_secret_length); + mbedtls_platform_zeroize(prf->other_secret, prf->other_secret_length); + cur += prf->other_secret_length; + } + } else { + *cur++ = MBEDTLS_BYTE_1(data_length); + *cur++ = MBEDTLS_BYTE_0(data_length); + memset(cur, 0, data_length); + cur += data_length; + } + + *cur++ = MBEDTLS_BYTE_1(data_length); + *cur++ = MBEDTLS_BYTE_0(data_length); + memcpy(cur, data, data_length); + cur += data_length; + + status = psa_tls12_prf_set_key(prf, pms, (size_t) (cur - pms)); + + mbedtls_zeroize_and_free(pms, pms_len); + return status; +} + +static psa_status_t psa_tls12_prf_psk_to_ms_set_other_key( + psa_tls12_prf_key_derivation_t *prf, + const uint8_t *data, + size_t data_length) +{ + if (prf->state != PSA_TLS12_PRF_STATE_SEED_SET) { + return PSA_ERROR_BAD_STATE; + } + + if (data_length != 0) { + prf->other_secret = mbedtls_calloc(1, data_length); + if (prf->other_secret == NULL) { + return PSA_ERROR_INSUFFICIENT_MEMORY; + } + + memcpy(prf->other_secret, data, data_length); + prf->other_secret_length = data_length; + } else { + prf->other_secret_length = 0; + } + + prf->state = PSA_TLS12_PRF_STATE_OTHER_KEY_SET; + + return PSA_SUCCESS; +} + +static psa_status_t psa_tls12_prf_psk_to_ms_input( + psa_tls12_prf_key_derivation_t *prf, + psa_key_derivation_step_t step, + const uint8_t *data, + size_t data_length) +{ + switch (step) { + case PSA_KEY_DERIVATION_INPUT_SECRET: + return psa_tls12_prf_psk_to_ms_set_key(prf, + data, data_length); + break; + case PSA_KEY_DERIVATION_INPUT_OTHER_SECRET: + return psa_tls12_prf_psk_to_ms_set_other_key(prf, + data, + data_length); + break; + default: + return psa_tls12_prf_input(prf, step, data, data_length); + break; + + } +} +#endif /* MBEDTLS_PSA_BUILTIN_ALG_TLS12_PSK_TO_MS */ + +#if defined(MBEDTLS_PSA_BUILTIN_ALG_TLS12_ECJPAKE_TO_PMS) +static psa_status_t psa_tls12_ecjpake_to_pms_input( + psa_tls12_ecjpake_to_pms_t *ecjpake, + psa_key_derivation_step_t step, + const uint8_t *data, + size_t data_length) +{ + if (data_length != PSA_TLS12_ECJPAKE_TO_PMS_INPUT_SIZE || + step != PSA_KEY_DERIVATION_INPUT_SECRET) { + return PSA_ERROR_INVALID_ARGUMENT; + } + + /* Check if the passed point is in an uncompressed form */ + if (data[0] != 0x04) { + return PSA_ERROR_INVALID_ARGUMENT; + } + + /* Only K.X has to be extracted - bytes 1 to 32 inclusive. */ + memcpy(ecjpake->data, data + 1, PSA_TLS12_ECJPAKE_TO_PMS_DATA_SIZE); + + return PSA_SUCCESS; +} +#endif /* MBEDTLS_PSA_BUILTIN_ALG_TLS12_ECJPAKE_TO_PMS */ + +#if defined(PSA_HAVE_SOFT_PBKDF2) +static psa_status_t psa_pbkdf2_set_input_cost( + psa_pbkdf2_key_derivation_t *pbkdf2, + psa_key_derivation_step_t step, + uint64_t data) +{ + if (step != PSA_KEY_DERIVATION_INPUT_COST) { + return PSA_ERROR_INVALID_ARGUMENT; + } + + if (pbkdf2->state != PSA_PBKDF2_STATE_INIT) { + return PSA_ERROR_BAD_STATE; + } + + if (data > PSA_VENDOR_PBKDF2_MAX_ITERATIONS) { + return PSA_ERROR_NOT_SUPPORTED; + } + + if (data == 0) { + return PSA_ERROR_INVALID_ARGUMENT; + } + + pbkdf2->input_cost = data; + pbkdf2->state = PSA_PBKDF2_STATE_INPUT_COST_SET; + + return PSA_SUCCESS; +} + +static psa_status_t psa_pbkdf2_set_salt(psa_pbkdf2_key_derivation_t *pbkdf2, + const uint8_t *data, + size_t data_length) +{ + if (pbkdf2->state == PSA_PBKDF2_STATE_INPUT_COST_SET) { + pbkdf2->state = PSA_PBKDF2_STATE_SALT_SET; + } else if (pbkdf2->state == PSA_PBKDF2_STATE_SALT_SET) { + /* Appending to existing salt. No state change. */ + } else { + return PSA_ERROR_BAD_STATE; + } + + if (data_length == 0) { + /* Appending an empty string, nothing to do. */ + } else { + uint8_t *next_salt; + + next_salt = mbedtls_calloc(1, data_length + pbkdf2->salt_length); + if (next_salt == NULL) { + return PSA_ERROR_INSUFFICIENT_MEMORY; + } + + if (pbkdf2->salt_length != 0) { + memcpy(next_salt, pbkdf2->salt, pbkdf2->salt_length); + } + memcpy(next_salt + pbkdf2->salt_length, data, data_length); + pbkdf2->salt_length += data_length; + mbedtls_free(pbkdf2->salt); + pbkdf2->salt = next_salt; + } + return PSA_SUCCESS; +} + +#if defined(MBEDTLS_PSA_BUILTIN_ALG_PBKDF2_HMAC) +static psa_status_t psa_pbkdf2_hmac_set_password(psa_algorithm_t hash_alg, + const uint8_t *input, + size_t input_len, + uint8_t *output, + size_t *output_len) +{ + psa_status_t status = PSA_SUCCESS; + if (input_len > PSA_HASH_BLOCK_LENGTH(hash_alg)) { + return psa_hash_compute(hash_alg, input, input_len, output, + PSA_HMAC_MAX_HASH_BLOCK_SIZE, output_len); + } else if (input_len > 0) { + memcpy(output, input, input_len); + } + *output_len = PSA_HASH_BLOCK_LENGTH(hash_alg); + return status; +} +#endif /* MBEDTLS_PSA_BUILTIN_ALG_PBKDF2_HMAC */ + +#if defined(MBEDTLS_PSA_BUILTIN_ALG_PBKDF2_AES_CMAC_PRF_128) +static psa_status_t psa_pbkdf2_cmac_set_password(const uint8_t *input, + size_t input_len, + uint8_t *output, + size_t *output_len) +{ + psa_status_t status = PSA_SUCCESS; + if (input_len != PSA_MAC_LENGTH(PSA_KEY_TYPE_AES, 128U, PSA_ALG_CMAC)) { + psa_key_attributes_t attributes = PSA_KEY_ATTRIBUTES_INIT; + uint8_t zeros[16] = { 0 }; + psa_set_key_type(&attributes, PSA_KEY_TYPE_AES); + psa_set_key_bits(&attributes, PSA_BYTES_TO_BITS(sizeof(zeros))); + psa_set_key_usage_flags(&attributes, PSA_KEY_USAGE_SIGN_MESSAGE); + /* Passing PSA_MAC_LENGTH(PSA_KEY_TYPE_AES, 128U, PSA_ALG_CMAC) as + * mac_size as the driver function sets mac_output_length = mac_size + * on success. See https://github.com/Mbed-TLS/mbedtls/issues/7801 */ + status = psa_driver_wrapper_mac_compute(&attributes, + zeros, sizeof(zeros), + PSA_ALG_CMAC, input, input_len, + output, + PSA_MAC_LENGTH(PSA_KEY_TYPE_AES, + 128U, + PSA_ALG_CMAC), + output_len); + } else { + memcpy(output, input, input_len); + *output_len = PSA_MAC_LENGTH(PSA_KEY_TYPE_AES, 128U, PSA_ALG_CMAC); + } + return status; +} +#endif /* MBEDTLS_PSA_BUILTIN_ALG_PBKDF2_AES_CMAC_PRF_128 */ + +static psa_status_t psa_pbkdf2_set_password(psa_pbkdf2_key_derivation_t *pbkdf2, + psa_algorithm_t kdf_alg, + const uint8_t *data, + size_t data_length) +{ + psa_status_t status = PSA_SUCCESS; + if (pbkdf2->state != PSA_PBKDF2_STATE_SALT_SET) { + return PSA_ERROR_BAD_STATE; + } + +#if defined(MBEDTLS_PSA_BUILTIN_ALG_PBKDF2_HMAC) + if (PSA_ALG_IS_PBKDF2_HMAC(kdf_alg)) { + psa_algorithm_t hash_alg = PSA_ALG_PBKDF2_HMAC_GET_HASH(kdf_alg); + status = psa_pbkdf2_hmac_set_password(hash_alg, data, data_length, + pbkdf2->password, + &pbkdf2->password_length); + } else +#endif /* MBEDTLS_PSA_BUILTIN_ALG_PBKDF2_HMAC */ +#if defined(MBEDTLS_PSA_BUILTIN_ALG_PBKDF2_AES_CMAC_PRF_128) + if (kdf_alg == PSA_ALG_PBKDF2_AES_CMAC_PRF_128) { + status = psa_pbkdf2_cmac_set_password(data, data_length, + pbkdf2->password, + &pbkdf2->password_length); + } else +#endif /* MBEDTLS_PSA_BUILTIN_ALG_PBKDF2_AES_CMAC_PRF_128 */ + { + return PSA_ERROR_INVALID_ARGUMENT; + } + + pbkdf2->state = PSA_PBKDF2_STATE_PASSWORD_SET; + + return status; +} + +static psa_status_t psa_pbkdf2_input(psa_pbkdf2_key_derivation_t *pbkdf2, + psa_algorithm_t kdf_alg, + psa_key_derivation_step_t step, + const uint8_t *data, + size_t data_length) +{ + switch (step) { + case PSA_KEY_DERIVATION_INPUT_SALT: + return psa_pbkdf2_set_salt(pbkdf2, data, data_length); + case PSA_KEY_DERIVATION_INPUT_PASSWORD: + return psa_pbkdf2_set_password(pbkdf2, kdf_alg, data, data_length); + default: + return PSA_ERROR_INVALID_ARGUMENT; + } +} +#endif /* PSA_HAVE_SOFT_PBKDF2 */ + +/** Check whether the given key type is acceptable for the given + * input step of a key derivation. + * + * Secret inputs must have the type #PSA_KEY_TYPE_DERIVE. + * Non-secret inputs must have the type #PSA_KEY_TYPE_RAW_DATA. + * Both secret and non-secret inputs can alternatively have the type + * #PSA_KEY_TYPE_NONE, which is never the type of a key object, meaning + * that the input was passed as a buffer rather than via a key object. + */ +static int psa_key_derivation_check_input_type( + psa_key_derivation_step_t step, + psa_key_type_t key_type) +{ + switch (step) { + case PSA_KEY_DERIVATION_INPUT_SECRET: + if (key_type == PSA_KEY_TYPE_DERIVE) { + return PSA_SUCCESS; + } + if (key_type == PSA_KEY_TYPE_NONE) { + return PSA_SUCCESS; + } + break; + case PSA_KEY_DERIVATION_INPUT_OTHER_SECRET: + if (key_type == PSA_KEY_TYPE_DERIVE) { + return PSA_SUCCESS; + } + if (key_type == PSA_KEY_TYPE_NONE) { + return PSA_SUCCESS; + } + break; + case PSA_KEY_DERIVATION_INPUT_LABEL: + case PSA_KEY_DERIVATION_INPUT_SALT: + case PSA_KEY_DERIVATION_INPUT_INFO: + case PSA_KEY_DERIVATION_INPUT_SEED: + if (key_type == PSA_KEY_TYPE_RAW_DATA) { + return PSA_SUCCESS; + } + if (key_type == PSA_KEY_TYPE_NONE) { + return PSA_SUCCESS; + } + break; + case PSA_KEY_DERIVATION_INPUT_PASSWORD: + if (key_type == PSA_KEY_TYPE_PASSWORD) { + return PSA_SUCCESS; + } + if (key_type == PSA_KEY_TYPE_DERIVE) { + return PSA_SUCCESS; + } + if (key_type == PSA_KEY_TYPE_NONE) { + return PSA_SUCCESS; + } + break; + } + return PSA_ERROR_INVALID_ARGUMENT; +} + +static psa_status_t psa_key_derivation_input_internal( + psa_key_derivation_operation_t *operation, + psa_key_derivation_step_t step, + psa_key_type_t key_type, + const uint8_t *data, + size_t data_length) +{ + psa_status_t status; + psa_algorithm_t kdf_alg = psa_key_derivation_get_kdf_alg(operation); + + status = psa_key_derivation_check_input_type(step, key_type); + if (status != PSA_SUCCESS) { + goto exit; + } + +#if defined(BUILTIN_ALG_ANY_HKDF) + if (PSA_ALG_IS_ANY_HKDF(kdf_alg)) { + status = psa_hkdf_input(&operation->ctx.hkdf, kdf_alg, + step, data, data_length); + } else +#endif /* BUILTIN_ALG_ANY_HKDF */ +#if defined(MBEDTLS_PSA_BUILTIN_ALG_TLS12_PRF) + if (PSA_ALG_IS_TLS12_PRF(kdf_alg)) { + status = psa_tls12_prf_input(&operation->ctx.tls12_prf, + step, data, data_length); + } else +#endif /* MBEDTLS_PSA_BUILTIN_ALG_TLS12_PRF */ +#if defined(MBEDTLS_PSA_BUILTIN_ALG_TLS12_PSK_TO_MS) + if (PSA_ALG_IS_TLS12_PSK_TO_MS(kdf_alg)) { + status = psa_tls12_prf_psk_to_ms_input(&operation->ctx.tls12_prf, + step, data, data_length); + } else +#endif /* MBEDTLS_PSA_BUILTIN_ALG_TLS12_PSK_TO_MS */ +#if defined(MBEDTLS_PSA_BUILTIN_ALG_TLS12_ECJPAKE_TO_PMS) + if (kdf_alg == PSA_ALG_TLS12_ECJPAKE_TO_PMS) { + status = psa_tls12_ecjpake_to_pms_input( + &operation->ctx.tls12_ecjpake_to_pms, step, data, data_length); + } else +#endif /* MBEDTLS_PSA_BUILTIN_ALG_TLS12_ECJPAKE_TO_PMS */ +#if defined(PSA_HAVE_SOFT_PBKDF2) + if (PSA_ALG_IS_PBKDF2(kdf_alg)) { + status = psa_pbkdf2_input(&operation->ctx.pbkdf2, kdf_alg, + step, data, data_length); + } else +#endif /* PSA_HAVE_SOFT_PBKDF2 */ + { + /* This can't happen unless the operation object was not initialized */ + (void) data; + (void) data_length; + (void) kdf_alg; + return PSA_ERROR_BAD_STATE; + } + +exit: + if (status != PSA_SUCCESS) { + psa_key_derivation_abort(operation); + } + return status; +} + +static psa_status_t psa_key_derivation_input_integer_internal( + psa_key_derivation_operation_t *operation, + psa_key_derivation_step_t step, + uint64_t value) +{ + psa_status_t status; + psa_algorithm_t kdf_alg = psa_key_derivation_get_kdf_alg(operation); + +#if defined(PSA_HAVE_SOFT_PBKDF2) + if (PSA_ALG_IS_PBKDF2(kdf_alg)) { + status = psa_pbkdf2_set_input_cost( + &operation->ctx.pbkdf2, step, value); + } else +#endif /* PSA_HAVE_SOFT_PBKDF2 */ + { + (void) step; + (void) value; + (void) kdf_alg; + status = PSA_ERROR_INVALID_ARGUMENT; + } + + if (status != PSA_SUCCESS) { + psa_key_derivation_abort(operation); + } + return status; +} + +psa_status_t psa_key_derivation_input_bytes( + psa_key_derivation_operation_t *operation, + psa_key_derivation_step_t step, + const uint8_t *data_external, + size_t data_length) +{ + psa_status_t status = PSA_ERROR_CORRUPTION_DETECTED; + LOCAL_INPUT_DECLARE(data_external, data); + + LOCAL_INPUT_ALLOC(data_external, data_length, data); + + status = psa_key_derivation_input_internal(operation, step, + PSA_KEY_TYPE_NONE, + data, data_length); +#if !defined(MBEDTLS_PSA_ASSUME_EXCLUSIVE_BUFFERS) +exit: +#endif + LOCAL_INPUT_FREE(data_external, data); + return status; +} + +psa_status_t psa_key_derivation_input_integer( + psa_key_derivation_operation_t *operation, + psa_key_derivation_step_t step, + uint64_t value) +{ + return psa_key_derivation_input_integer_internal(operation, step, value); +} + +psa_status_t psa_key_derivation_input_key( + psa_key_derivation_operation_t *operation, + psa_key_derivation_step_t step, + mbedtls_svc_key_id_t key) +{ + psa_status_t status = PSA_ERROR_CORRUPTION_DETECTED; + psa_status_t unlock_status = PSA_ERROR_CORRUPTION_DETECTED; + psa_key_slot_t *slot; + + status = psa_get_and_lock_transparent_key_slot_with_policy( + key, &slot, PSA_KEY_USAGE_DERIVE, operation->alg); + if (status != PSA_SUCCESS) { + psa_key_derivation_abort(operation); + return status; + } + + /* Passing a key object as a SECRET or PASSWORD input unlocks the + * permission to output to a key object. */ + if (step == PSA_KEY_DERIVATION_INPUT_SECRET || + step == PSA_KEY_DERIVATION_INPUT_PASSWORD) { + operation->can_output_key = 1; + } + + status = psa_key_derivation_input_internal(operation, + step, slot->attr.type, + slot->key.data, + slot->key.bytes); + + unlock_status = psa_unregister_read_under_mutex(slot); + + return (status == PSA_SUCCESS) ? unlock_status : status; +} + + + +/****************************************************************/ +/* Key agreement */ +/****************************************************************/ + +psa_status_t psa_key_agreement_raw_builtin(const psa_key_attributes_t *attributes, + const uint8_t *key_buffer, + size_t key_buffer_size, + psa_algorithm_t alg, + const uint8_t *peer_key, + size_t peer_key_length, + uint8_t *shared_secret, + size_t shared_secret_size, + size_t *shared_secret_length) +{ + switch (alg) { +#if defined(MBEDTLS_PSA_BUILTIN_ALG_ECDH) + case PSA_ALG_ECDH: + return mbedtls_psa_key_agreement_ecdh(attributes, key_buffer, + key_buffer_size, alg, + peer_key, peer_key_length, + shared_secret, + shared_secret_size, + shared_secret_length); +#endif /* MBEDTLS_PSA_BUILTIN_ALG_ECDH */ + +#if defined(MBEDTLS_PSA_BUILTIN_ALG_FFDH) + case PSA_ALG_FFDH: + return mbedtls_psa_ffdh_key_agreement(attributes, + peer_key, + peer_key_length, + key_buffer, + key_buffer_size, + shared_secret, + shared_secret_size, + shared_secret_length); +#endif /* MBEDTLS_PSA_BUILTIN_ALG_FFDH */ + + default: + (void) attributes; + (void) key_buffer; + (void) key_buffer_size; + (void) peer_key; + (void) peer_key_length; + (void) shared_secret; + (void) shared_secret_size; + (void) shared_secret_length; + return PSA_ERROR_NOT_SUPPORTED; + } +} + +/** Internal function for raw key agreement + * Calls the driver wrapper which will hand off key agreement task + * to the driver's implementation if a driver is present. + * Fallback specified in the driver wrapper is built-in raw key agreement + * (psa_key_agreement_raw_builtin). + */ +static psa_status_t psa_key_agreement_raw_internal(psa_algorithm_t alg, + psa_key_slot_t *private_key, + const uint8_t *peer_key, + size_t peer_key_length, + uint8_t *shared_secret, + size_t shared_secret_size, + size_t *shared_secret_length) +{ + if (!PSA_ALG_IS_RAW_KEY_AGREEMENT(alg)) { + return PSA_ERROR_NOT_SUPPORTED; + } + + return psa_driver_wrapper_key_agreement(&private_key->attr, + private_key->key.data, + private_key->key.bytes, alg, + peer_key, peer_key_length, + shared_secret, + shared_secret_size, + shared_secret_length); +} + +/* Note that if this function fails, you must call psa_key_derivation_abort() + * to potentially free embedded data structures and wipe confidential data. + */ +static psa_status_t psa_key_agreement_internal(psa_key_derivation_operation_t *operation, + psa_key_derivation_step_t step, + psa_key_slot_t *private_key, + const uint8_t *peer_key, + size_t peer_key_length) +{ + psa_status_t status; + uint8_t shared_secret[PSA_RAW_KEY_AGREEMENT_OUTPUT_MAX_SIZE] = { 0 }; + size_t shared_secret_length = 0; + psa_algorithm_t ka_alg = PSA_ALG_KEY_AGREEMENT_GET_BASE(operation->alg); + + /* Step 1: run the secret agreement algorithm to generate the shared + * secret. */ + status = psa_key_agreement_raw_internal(ka_alg, + private_key, + peer_key, peer_key_length, + shared_secret, + sizeof(shared_secret), + &shared_secret_length); + if (status != PSA_SUCCESS) { + goto exit; } - operation->capacity -= output_length; -#if defined(MBEDTLS_PSA_BUILTIN_ALG_HKDF) - if (PSA_ALG_IS_HKDF(kdf_alg)) { - psa_algorithm_t hash_alg = PSA_ALG_HKDF_GET_HASH(kdf_alg); - status = psa_key_derivation_hkdf_read(&operation->ctx.hkdf, hash_alg, - output, output_length); + /* Step 2: set up the key derivation to generate key material from + * the shared secret. A shared secret is permitted wherever a key + * of type DERIVE is permitted. */ + status = psa_key_derivation_input_internal(operation, step, + PSA_KEY_TYPE_DERIVE, + shared_secret, + shared_secret_length); +exit: + mbedtls_platform_zeroize(shared_secret, shared_secret_length); + return status; +} + +psa_status_t psa_key_derivation_key_agreement(psa_key_derivation_operation_t *operation, + psa_key_derivation_step_t step, + mbedtls_svc_key_id_t private_key, + const uint8_t *peer_key_external, + size_t peer_key_length) +{ + psa_status_t status = PSA_ERROR_CORRUPTION_DETECTED; + psa_status_t unlock_status = PSA_ERROR_CORRUPTION_DETECTED; + psa_key_slot_t *slot; + LOCAL_INPUT_DECLARE(peer_key_external, peer_key); + + if (!PSA_ALG_IS_KEY_AGREEMENT(operation->alg)) { + return PSA_ERROR_INVALID_ARGUMENT; + } + status = psa_get_and_lock_transparent_key_slot_with_policy( + private_key, &slot, PSA_KEY_USAGE_DERIVE, operation->alg); + if (status != PSA_SUCCESS) { + return status; + } + + LOCAL_INPUT_ALLOC(peer_key_external, peer_key_length, peer_key); + status = psa_key_agreement_internal(operation, step, + slot, + peer_key, peer_key_length); + +#if !defined(MBEDTLS_PSA_ASSUME_EXCLUSIVE_BUFFERS) +exit: +#endif + if (status != PSA_SUCCESS) { + psa_key_derivation_abort(operation); + } else { + /* If a private key has been added as SECRET, we allow the derived + * key material to be used as a key in PSA Crypto. */ + if (step == PSA_KEY_DERIVATION_INPUT_SECRET) { + operation->can_output_key = 1; + } + } + + unlock_status = psa_unregister_read_under_mutex(slot); + LOCAL_INPUT_FREE(peer_key_external, peer_key); + + return (status == PSA_SUCCESS) ? unlock_status : status; +} + +psa_status_t psa_raw_key_agreement(psa_algorithm_t alg, + mbedtls_svc_key_id_t private_key, + const uint8_t *peer_key_external, + size_t peer_key_length, + uint8_t *output_external, + size_t output_size, + size_t *output_length) +{ + psa_status_t status = PSA_ERROR_CORRUPTION_DETECTED; + psa_status_t unlock_status = PSA_ERROR_CORRUPTION_DETECTED; + psa_key_slot_t *slot = NULL; + size_t expected_length; + LOCAL_INPUT_DECLARE(peer_key_external, peer_key); + LOCAL_OUTPUT_DECLARE(output_external, output); + LOCAL_OUTPUT_ALLOC(output_external, output_size, output); + + if (!PSA_ALG_IS_KEY_AGREEMENT(alg)) { + status = PSA_ERROR_INVALID_ARGUMENT; + goto exit; + } + status = psa_get_and_lock_transparent_key_slot_with_policy( + private_key, &slot, PSA_KEY_USAGE_DERIVE, alg); + if (status != PSA_SUCCESS) { + goto exit; + } + + /* PSA_RAW_KEY_AGREEMENT_OUTPUT_SIZE() is in general an upper bound + * for the output size. The PSA specification only guarantees that this + * function works if output_size >= PSA_RAW_KEY_AGREEMENT_OUTPUT_SIZE(...), + * but it might be nice to allow smaller buffers if the output fits. + * At the time of writing this comment, with only ECDH implemented, + * PSA_RAW_KEY_AGREEMENT_OUTPUT_SIZE() is exact so the point is moot. + * If FFDH is implemented, PSA_RAW_KEY_AGREEMENT_OUTPUT_SIZE() can easily + * be exact for it as well. */ + expected_length = + PSA_RAW_KEY_AGREEMENT_OUTPUT_SIZE(slot->attr.type, slot->attr.bits); + if (output_size < expected_length) { + status = PSA_ERROR_BUFFER_TOO_SMALL; + goto exit; + } + + LOCAL_INPUT_ALLOC(peer_key_external, peer_key_length, peer_key); + status = psa_key_agreement_raw_internal(alg, slot, + peer_key, peer_key_length, + output, output_size, + output_length); + +exit: + /* Check for successful allocation of output, + * with an unsuccessful status. */ + if (output != NULL && status != PSA_SUCCESS) { + /* If an error happens and is not handled properly, the output + * may be used as a key to protect sensitive data. Arrange for such + * a key to be random, which is likely to result in decryption or + * verification errors. This is better than filling the buffer with + * some constant data such as zeros, which would result in the data + * being protected with a reproducible, easily knowable key. + */ + psa_generate_random_internal(output, output_size); + *output_length = output_size; + } + + if (output == NULL) { + /* output allocation failed. */ + *output_length = 0; + } + + unlock_status = psa_unregister_read_under_mutex(slot); + + LOCAL_INPUT_FREE(peer_key_external, peer_key); + LOCAL_OUTPUT_FREE(output_external, output); + return (status == PSA_SUCCESS) ? unlock_status : status; +} + + +/****************************************************************/ +/* Random generation */ +/****************************************************************/ + +#if defined(MBEDTLS_PSA_INJECT_ENTROPY) +#include "entropy_poll.h" +#endif + +/** Initialize the PSA random generator. + * + * Note: the mbedtls_threading_psa_rngdata_mutex should be held when calling + * this function if mutexes are enabled. + */ +static void mbedtls_psa_random_init(mbedtls_psa_random_context_t *rng) +{ +#if defined(MBEDTLS_PSA_CRYPTO_EXTERNAL_RNG) + memset(rng, 0, sizeof(*rng)); +#else /* MBEDTLS_PSA_CRYPTO_EXTERNAL_RNG */ + + /* Set default configuration if + * mbedtls_psa_crypto_configure_entropy_sources() hasn't been called. */ + if (rng->entropy_init == NULL) { + rng->entropy_init = mbedtls_entropy_init; + } + if (rng->entropy_free == NULL) { + rng->entropy_free = mbedtls_entropy_free; + } + + rng->entropy_init(&rng->entropy); +#if defined(MBEDTLS_PSA_INJECT_ENTROPY) && \ + defined(MBEDTLS_NO_DEFAULT_ENTROPY_SOURCES) + /* The PSA entropy injection feature depends on using NV seed as an entropy + * source. Add NV seed as an entropy source for PSA entropy injection. */ + mbedtls_entropy_add_source(&rng->entropy, + mbedtls_nv_seed_poll, NULL, + MBEDTLS_ENTROPY_BLOCK_SIZE, + MBEDTLS_ENTROPY_SOURCE_STRONG); +#endif + + mbedtls_psa_drbg_init(&rng->drbg); +#endif /* MBEDTLS_PSA_CRYPTO_EXTERNAL_RNG */ +} + +/** Deinitialize the PSA random generator. + * + * Note: the mbedtls_threading_psa_rngdata_mutex should be held when calling + * this function if mutexes are enabled. + */ +static void mbedtls_psa_random_free(mbedtls_psa_random_context_t *rng) +{ +#if defined(MBEDTLS_PSA_CRYPTO_EXTERNAL_RNG) + memset(rng, 0, sizeof(*rng)); +#else /* MBEDTLS_PSA_CRYPTO_EXTERNAL_RNG */ + mbedtls_psa_drbg_free(&rng->drbg); + rng->entropy_free(&rng->entropy); +#endif /* MBEDTLS_PSA_CRYPTO_EXTERNAL_RNG */ +} + +/** Seed the PSA random generator. + */ +static psa_status_t mbedtls_psa_random_seed(mbedtls_psa_random_context_t *rng) +{ +#if defined(MBEDTLS_PSA_CRYPTO_EXTERNAL_RNG) + /* Do nothing: the external RNG seeds itself. */ + (void) rng; + return PSA_SUCCESS; +#else /* MBEDTLS_PSA_CRYPTO_EXTERNAL_RNG */ + const unsigned char drbg_seed[] = "PSA"; + int ret = mbedtls_psa_drbg_seed(&rng->drbg, &rng->entropy, + drbg_seed, sizeof(drbg_seed) - 1); + return mbedtls_to_psa_error(ret); +#endif /* MBEDTLS_PSA_CRYPTO_EXTERNAL_RNG */ +} + +psa_status_t psa_generate_random(uint8_t *output_external, + size_t output_size) +{ + psa_status_t status; + + LOCAL_OUTPUT_DECLARE(output_external, output); + LOCAL_OUTPUT_ALLOC(output_external, output_size, output); + + status = psa_generate_random_internal(output, output_size); + +#if !defined(MBEDTLS_PSA_ASSUME_EXCLUSIVE_BUFFERS) +exit: +#endif + LOCAL_OUTPUT_FREE(output_external, output); + return status; +} + +#if defined(MBEDTLS_PSA_INJECT_ENTROPY) +psa_status_t mbedtls_psa_inject_entropy(const uint8_t *seed, + size_t seed_size) +{ + if (psa_get_initialized()) { + return PSA_ERROR_NOT_PERMITTED; + } + + if (((seed_size < MBEDTLS_ENTROPY_MIN_PLATFORM) || + (seed_size < MBEDTLS_ENTROPY_BLOCK_SIZE)) || + (seed_size > MBEDTLS_ENTROPY_MAX_SEED_SIZE)) { + return PSA_ERROR_INVALID_ARGUMENT; + } + + return mbedtls_psa_storage_inject_entropy(seed, seed_size); +} +#endif /* MBEDTLS_PSA_INJECT_ENTROPY */ + +/** Validate the key type and size for key generation + * + * \param type The key type + * \param bits The number of bits of the key + * + * \retval #PSA_SUCCESS + * The key type and size are valid. + * \retval #PSA_ERROR_INVALID_ARGUMENT + * The size in bits of the key is not valid. + * \retval #PSA_ERROR_NOT_SUPPORTED + * The type and/or the size in bits of the key or the combination of + * the two is not supported. + */ +static psa_status_t psa_validate_key_type_and_size_for_key_generation( + psa_key_type_t type, size_t bits) +{ + psa_status_t status = PSA_ERROR_CORRUPTION_DETECTED; + + if (key_type_is_raw_bytes(type)) { + status = psa_validate_unstructured_key_bit_size(type, bits); + if (status != PSA_SUCCESS) { + return status; + } } else -#endif /* MBEDTLS_PSA_BUILTIN_ALG_HKDF */ -#if defined(MBEDTLS_PSA_BUILTIN_ALG_TLS12_PRF) || \ - defined(MBEDTLS_PSA_BUILTIN_ALG_TLS12_PSK_TO_MS) - if (PSA_ALG_IS_TLS12_PRF(kdf_alg) || - PSA_ALG_IS_TLS12_PSK_TO_MS(kdf_alg)) { - status = psa_key_derivation_tls12_prf_read(&operation->ctx.tls12_prf, - kdf_alg, output, - output_length); +#if defined(PSA_WANT_KEY_TYPE_RSA_KEY_PAIR_GENERATE) + if (PSA_KEY_TYPE_IS_RSA(type) && PSA_KEY_TYPE_IS_KEY_PAIR(type)) { + if (bits > PSA_VENDOR_RSA_MAX_KEY_BITS) { + return PSA_ERROR_NOT_SUPPORTED; + } + if (bits < PSA_VENDOR_RSA_GENERATE_MIN_KEY_BITS) { + return PSA_ERROR_NOT_SUPPORTED; + } + + /* Accept only byte-aligned keys, for the same reasons as + * in psa_import_rsa_key(). */ + if (bits % 8 != 0) { + return PSA_ERROR_NOT_SUPPORTED; + } + } else +#endif /* defined(PSA_WANT_KEY_TYPE_RSA_KEY_PAIR_GENERATE) */ + +#if defined(PSA_WANT_KEY_TYPE_ECC_KEY_PAIR_GENERATE) + if (PSA_KEY_TYPE_IS_ECC(type) && PSA_KEY_TYPE_IS_KEY_PAIR(type)) { + /* To avoid empty block, return successfully here. */ + return PSA_SUCCESS; } else -#endif /* MBEDTLS_PSA_BUILTIN_ALG_TLS12_PRF || - * MBEDTLS_PSA_BUILTIN_ALG_TLS12_PSK_TO_MS */ +#endif /* defined(PSA_WANT_KEY_TYPE_ECC_KEY_PAIR_GENERATE) */ + +#if defined(PSA_WANT_KEY_TYPE_DH_KEY_PAIR_GENERATE) + if (PSA_KEY_TYPE_IS_DH(type) && PSA_KEY_TYPE_IS_KEY_PAIR(type)) { + if (psa_is_dh_key_size_valid(bits) == 0) { + return PSA_ERROR_NOT_SUPPORTED; + } + } else +#endif /* defined(PSA_WANT_KEY_TYPE_DH_KEY_PAIR_GENERATE) */ { - (void) kdf_alg; - return PSA_ERROR_BAD_STATE; + return PSA_ERROR_NOT_SUPPORTED; } -exit: - if (status != PSA_SUCCESS) { - /* Preserve the algorithm upon errors, but clear all sensitive state. - * This allows us to differentiate between exhausted operations and - * blank operations, so we can return PSA_ERROR_BAD_STATE on blank - * operations. */ - psa_algorithm_t alg = operation->alg; - psa_key_derivation_abort(operation); - operation->alg = alg; - memset(output, '!', output_length); - } - return status; + return PSA_SUCCESS; } -#if defined(MBEDTLS_PSA_BUILTIN_KEY_TYPE_DES) -static void psa_des_set_key_parity(uint8_t *data, size_t data_size) +psa_status_t psa_generate_key_internal( + const psa_key_attributes_t *attributes, + const psa_key_production_parameters_t *params, size_t params_data_length, + uint8_t *key_buffer, size_t key_buffer_size, size_t *key_buffer_length) { - if (data_size >= 8) { - mbedtls_des_key_set_parity(data); - } - if (data_size >= 16) { - mbedtls_des_key_set_parity(data + 8); - } - if (data_size >= 24) { - mbedtls_des_key_set_parity(data + 16); - } -} -#endif /* MBEDTLS_PSA_BUILTIN_KEY_TYPE_DES */ + psa_status_t status = PSA_ERROR_CORRUPTION_DETECTED; + psa_key_type_t type = attributes->type; -static psa_status_t psa_generate_derived_key_internal( - psa_key_slot_t *slot, - size_t bits, - psa_key_derivation_operation_t *operation) -{ - uint8_t *data = NULL; - size_t bytes = PSA_BITS_TO_BYTES(bits); - psa_status_t status; - psa_key_attributes_t attributes; + /* Only used for RSA */ + (void) params; + (void) params_data_length; - if (!key_type_is_raw_bytes(slot->attr.type)) { - return PSA_ERROR_INVALID_ARGUMENT; - } - if (bits % 8 != 0) { - return PSA_ERROR_INVALID_ARGUMENT; - } - data = mbedtls_calloc(1, bytes); - if (data == NULL) { - return PSA_ERROR_INSUFFICIENT_MEMORY; - } + if (key_type_is_raw_bytes(type)) { + status = psa_generate_random_internal(key_buffer, key_buffer_size); + if (status != PSA_SUCCESS) { + return status; + } - status = psa_key_derivation_output_bytes(operation, data, bytes); - if (status != PSA_SUCCESS) { - goto exit; - } #if defined(MBEDTLS_PSA_BUILTIN_KEY_TYPE_DES) - if (slot->attr.type == PSA_KEY_TYPE_DES) { - psa_des_set_key_parity(data, bytes); - } + if (type == PSA_KEY_TYPE_DES) { + psa_des_set_key_parity(key_buffer, key_buffer_size); + } #endif /* MBEDTLS_PSA_BUILTIN_KEY_TYPE_DES */ + } else - status = psa_allocate_buffer_to_slot(slot, bytes); - if (status != PSA_SUCCESS) { - goto exit; - } - - slot->attr.bits = (psa_key_bits_t) bits; - attributes = (psa_key_attributes_t) { - .core = slot->attr - }; +#if defined(MBEDTLS_PSA_BUILTIN_KEY_TYPE_RSA_KEY_PAIR_GENERATE) + if (type == PSA_KEY_TYPE_RSA_KEY_PAIR) { + return mbedtls_psa_rsa_generate_key(attributes, + params, params_data_length, + key_buffer, + key_buffer_size, + key_buffer_length); + } else +#endif /* defined(MBEDTLS_PSA_BUILTIN_KEY_TYPE_RSA_KEY_PAIR_GENERATE) */ - status = psa_driver_wrapper_import_key(&attributes, - data, bytes, - slot->key.data, - slot->key.bytes, - &slot->key.bytes, &bits); - if (bits != slot->attr.bits) { - status = PSA_ERROR_INVALID_ARGUMENT; +#if defined(MBEDTLS_PSA_BUILTIN_KEY_TYPE_ECC_KEY_PAIR_GENERATE) + if (PSA_KEY_TYPE_IS_ECC(type) && PSA_KEY_TYPE_IS_KEY_PAIR(type)) { + return mbedtls_psa_ecp_generate_key(attributes, + key_buffer, + key_buffer_size, + key_buffer_length); + } else +#endif /* defined(MBEDTLS_PSA_BUILTIN_KEY_TYPE_ECC_KEY_PAIR_GENERATE) */ + +#if defined(MBEDTLS_PSA_BUILTIN_KEY_TYPE_DH_KEY_PAIR_GENERATE) + if (PSA_KEY_TYPE_IS_DH(type) && PSA_KEY_TYPE_IS_KEY_PAIR(type)) { + return mbedtls_psa_ffdh_generate_key(attributes, + key_buffer, + key_buffer_size, + key_buffer_length); + } else +#endif /* defined(MBEDTLS_PSA_BUILTIN_KEY_TYPE_DH_KEY_PAIR_GENERATE) */ + { + (void) key_buffer_length; + return PSA_ERROR_NOT_SUPPORTED; } -exit: - mbedtls_free(data); - return status; + return PSA_SUCCESS; } -psa_status_t psa_key_derivation_output_key(const psa_key_attributes_t *attributes, - psa_key_derivation_operation_t *operation, - mbedtls_svc_key_id_t *key) +psa_status_t psa_generate_key_ext(const psa_key_attributes_t *attributes, + const psa_key_production_parameters_t *params, + size_t params_data_length, + mbedtls_svc_key_id_t *key) { psa_status_t status; psa_key_slot_t *slot = NULL; psa_se_drv_table_entry_t *driver = NULL; + size_t key_buffer_size; *key = MBEDTLS_SVC_KEY_ID_INIT; @@ -4321,1206 +7934,1233 @@ psa_status_t psa_key_derivation_output_key(const psa_key_attributes_t *attribute return PSA_ERROR_INVALID_ARGUMENT; } - if (operation->alg == PSA_ALG_NONE) { - return PSA_ERROR_BAD_STATE; - } - - if (!operation->can_output_key) { - return PSA_ERROR_NOT_PERMITTED; - } - - status = psa_start_key_creation(PSA_KEY_CREATION_DERIVE, attributes, - &slot, &driver); -#if defined(MBEDTLS_PSA_CRYPTO_SE_C) - if (driver != NULL) { - /* Deriving a key in a secure element is not implemented yet. */ - status = PSA_ERROR_NOT_SUPPORTED; - } -#endif /* MBEDTLS_PSA_CRYPTO_SE_C */ - if (status == PSA_SUCCESS) { - status = psa_generate_derived_key_internal(slot, - attributes->core.bits, - operation); - } - if (status == PSA_SUCCESS) { - status = psa_finish_key_creation(slot, driver, key); - } - if (status != PSA_SUCCESS) { - psa_fail_key_creation(slot, driver); + /* Reject any attempt to create a public key. */ + if (PSA_KEY_TYPE_IS_PUBLIC_KEY(attributes->type)) { + return PSA_ERROR_INVALID_ARGUMENT; } - return status; -} - - - -/****************************************************************/ -/* Key derivation */ -/****************************************************************/ - -#if defined(AT_LEAST_ONE_BUILTIN_KDF) -static int is_kdf_alg_supported(psa_algorithm_t kdf_alg) -{ -#if defined(MBEDTLS_PSA_BUILTIN_ALG_HKDF) - if (PSA_ALG_IS_HKDF(kdf_alg)) { - return 1; - } -#endif -#if defined(MBEDTLS_PSA_BUILTIN_ALG_TLS12_PRF) - if (PSA_ALG_IS_TLS12_PRF(kdf_alg)) { - return 1; - } -#endif -#if defined(MBEDTLS_PSA_BUILTIN_ALG_TLS12_PSK_TO_MS) - if (PSA_ALG_IS_TLS12_PSK_TO_MS(kdf_alg)) { - return 1; - } +#if defined(PSA_WANT_KEY_TYPE_RSA_KEY_PAIR_GENERATE) + if (attributes->type == PSA_KEY_TYPE_RSA_KEY_PAIR) { + if (params->flags != 0) { + return PSA_ERROR_INVALID_ARGUMENT; + } + } else #endif - return 0; -} - -static psa_status_t psa_hash_try_support(psa_algorithm_t alg) -{ - psa_hash_operation_t operation = PSA_HASH_OPERATION_INIT; - psa_status_t status = psa_hash_setup(&operation, alg); - psa_hash_abort(&operation); - return status; -} - -static psa_status_t psa_key_derivation_setup_kdf( - psa_key_derivation_operation_t *operation, - psa_algorithm_t kdf_alg) -{ - /* Make sure that operation->ctx is properly zero-initialised. (Macro - * initialisers for this union leave some bytes unspecified.) */ - memset(&operation->ctx, 0, sizeof(operation->ctx)); - - /* Make sure that kdf_alg is a supported key derivation algorithm. */ - if (!is_kdf_alg_supported(kdf_alg)) { - return PSA_ERROR_NOT_SUPPORTED; - } - - /* All currently supported key derivation algorithms are based on a - * hash algorithm. */ - psa_algorithm_t hash_alg = PSA_ALG_HKDF_GET_HASH(kdf_alg); - size_t hash_size = PSA_HASH_LENGTH(hash_alg); - if (hash_size == 0) { - return PSA_ERROR_NOT_SUPPORTED; + if (!psa_key_production_parameters_are_default(params, params_data_length)) { + return PSA_ERROR_INVALID_ARGUMENT; } - /* Make sure that hash_alg is a supported hash algorithm. Otherwise - * we might fail later, which is somewhat unfriendly and potentially - * risk-prone. */ - psa_status_t status = psa_hash_try_support(hash_alg); + status = psa_start_key_creation(PSA_KEY_CREATION_GENERATE, attributes, + &slot, &driver); if (status != PSA_SUCCESS) { - return status; - } - - if ((PSA_ALG_IS_TLS12_PRF(kdf_alg) || - PSA_ALG_IS_TLS12_PSK_TO_MS(kdf_alg)) && - !(hash_alg == PSA_ALG_SHA_256 || hash_alg == PSA_ALG_SHA_384)) { - return PSA_ERROR_NOT_SUPPORTED; - } - - operation->capacity = 255 * hash_size; - return PSA_SUCCESS; -} - -static psa_status_t psa_key_agreement_try_support(psa_algorithm_t alg) -{ -#if defined(PSA_WANT_ALG_ECDH) - if (alg == PSA_ALG_ECDH) { - return PSA_SUCCESS; + goto exit; } -#endif - (void) alg; - return PSA_ERROR_NOT_SUPPORTED; -} -#endif /* AT_LEAST_ONE_BUILTIN_KDF */ -psa_status_t psa_key_derivation_setup(psa_key_derivation_operation_t *operation, - psa_algorithm_t alg) -{ - psa_status_t status; + /* In the case of a transparent key or an opaque key stored in local + * storage ( thus not in the case of generating a key in a secure element + * with storage ( MBEDTLS_PSA_CRYPTO_SE_C ) ),we have to allocate a + * buffer to hold the generated key material. */ + if (slot->key.data == NULL) { + if (PSA_KEY_LIFETIME_GET_LOCATION(attributes->lifetime) == + PSA_KEY_LOCATION_LOCAL_STORAGE) { + status = psa_validate_key_type_and_size_for_key_generation( + attributes->type, attributes->bits); + if (status != PSA_SUCCESS) { + goto exit; + } - if (operation->alg != 0) { - return PSA_ERROR_BAD_STATE; - } + key_buffer_size = PSA_EXPORT_KEY_OUTPUT_SIZE( + attributes->type, + attributes->bits); + } else { + status = psa_driver_wrapper_get_key_buffer_size( + attributes, &key_buffer_size); + if (status != PSA_SUCCESS) { + goto exit; + } + } - if (PSA_ALG_IS_RAW_KEY_AGREEMENT(alg)) { - return PSA_ERROR_INVALID_ARGUMENT; - } else if (PSA_ALG_IS_KEY_AGREEMENT(alg)) { -#if defined(AT_LEAST_ONE_BUILTIN_KDF) - psa_algorithm_t kdf_alg = PSA_ALG_KEY_AGREEMENT_GET_KDF(alg); - psa_algorithm_t ka_alg = PSA_ALG_KEY_AGREEMENT_GET_BASE(alg); - status = psa_key_agreement_try_support(ka_alg); + status = psa_allocate_buffer_to_slot(slot, key_buffer_size); if (status != PSA_SUCCESS) { - return status; - } - status = psa_key_derivation_setup_kdf(operation, kdf_alg); -#else - return PSA_ERROR_NOT_SUPPORTED; -#endif /* AT_LEAST_ONE_BUILTIN_KDF */ - } else if (PSA_ALG_IS_KEY_DERIVATION(alg)) { -#if defined(AT_LEAST_ONE_BUILTIN_KDF) - status = psa_key_derivation_setup_kdf(operation, alg); -#else - return PSA_ERROR_NOT_SUPPORTED; -#endif /* AT_LEAST_ONE_BUILTIN_KDF */ - } else { - return PSA_ERROR_INVALID_ARGUMENT; + goto exit; + } + } + + status = psa_driver_wrapper_generate_key(attributes, + params, params_data_length, + slot->key.data, slot->key.bytes, + &slot->key.bytes); + if (status != PSA_SUCCESS) { + psa_remove_key_data_from_memory(slot); } +exit: if (status == PSA_SUCCESS) { - operation->alg = alg; + status = psa_finish_key_creation(slot, driver, key); + } + if (status != PSA_SUCCESS) { + psa_fail_key_creation(slot, driver); } + return status; } -#if defined(MBEDTLS_PSA_BUILTIN_ALG_HKDF) -static psa_status_t psa_hkdf_input(psa_hkdf_key_derivation_t *hkdf, - psa_algorithm_t hash_alg, - psa_key_derivation_step_t step, - const uint8_t *data, - size_t data_length) +psa_status_t psa_generate_key(const psa_key_attributes_t *attributes, + mbedtls_svc_key_id_t *key) { - psa_status_t status; - switch (step) { - case PSA_KEY_DERIVATION_INPUT_SALT: - if (hkdf->state != HKDF_STATE_INIT) { - return PSA_ERROR_BAD_STATE; - } else { - status = psa_key_derivation_start_hmac(&hkdf->hmac, - hash_alg, - data, data_length); - if (status != PSA_SUCCESS) { - return status; - } - hkdf->state = HKDF_STATE_STARTED; - return PSA_SUCCESS; - } - case PSA_KEY_DERIVATION_INPUT_SECRET: - /* If no salt was provided, use an empty salt. */ - if (hkdf->state == HKDF_STATE_INIT) { - status = psa_key_derivation_start_hmac(&hkdf->hmac, - hash_alg, - NULL, 0); - if (status != PSA_SUCCESS) { - return status; - } - hkdf->state = HKDF_STATE_STARTED; - } - if (hkdf->state != HKDF_STATE_STARTED) { - return PSA_ERROR_BAD_STATE; - } - status = psa_mac_update(&hkdf->hmac, - data, data_length); - if (status != PSA_SUCCESS) { - return status; - } - status = psa_mac_sign_finish(&hkdf->hmac, - hkdf->prk, - sizeof(hkdf->prk), - &data_length); - if (status != PSA_SUCCESS) { - return status; - } - hkdf->offset_in_block = PSA_HASH_LENGTH(hash_alg); - hkdf->block_number = 0; - hkdf->state = HKDF_STATE_KEYED; - return PSA_SUCCESS; - case PSA_KEY_DERIVATION_INPUT_INFO: - if (hkdf->state == HKDF_STATE_OUTPUT) { - return PSA_ERROR_BAD_STATE; - } - if (hkdf->info_set) { - return PSA_ERROR_BAD_STATE; - } - hkdf->info_length = data_length; - if (data_length != 0) { - hkdf->info = mbedtls_calloc(1, data_length); - if (hkdf->info == NULL) { - return PSA_ERROR_INSUFFICIENT_MEMORY; - } - memcpy(hkdf->info, data, data_length); - } - hkdf->info_set = 1; - return PSA_SUCCESS; - default: - return PSA_ERROR_INVALID_ARGUMENT; - } + return psa_generate_key_ext(attributes, + &default_production_parameters, 0, + key); } -#endif /* MBEDTLS_PSA_BUILTIN_ALG_HKDF */ -#if defined(MBEDTLS_PSA_BUILTIN_ALG_TLS12_PRF) || \ - defined(MBEDTLS_PSA_BUILTIN_ALG_TLS12_PSK_TO_MS) -static psa_status_t psa_tls12_prf_set_seed(psa_tls12_prf_key_derivation_t *prf, - const uint8_t *data, - size_t data_length) +/****************************************************************/ +/* Module setup */ +/****************************************************************/ + +#if !defined(MBEDTLS_PSA_CRYPTO_EXTERNAL_RNG) +psa_status_t mbedtls_psa_crypto_configure_entropy_sources( + void (* entropy_init)(mbedtls_entropy_context *ctx), + void (* entropy_free)(mbedtls_entropy_context *ctx)) { - if (prf->state != PSA_TLS12_PRF_STATE_INIT) { - return PSA_ERROR_BAD_STATE; - } + psa_status_t status = PSA_ERROR_CORRUPTION_DETECTED; - if (data_length != 0) { - prf->seed = mbedtls_calloc(1, data_length); - if (prf->seed == NULL) { - return PSA_ERROR_INSUFFICIENT_MEMORY; - } +#if defined(MBEDTLS_THREADING_C) + mbedtls_mutex_lock(&mbedtls_threading_psa_rngdata_mutex); +#endif /* defined(MBEDTLS_THREADING_C) */ - memcpy(prf->seed, data, data_length); - prf->seed_length = data_length; + if (global_data.rng_state != RNG_NOT_INITIALIZED) { + status = PSA_ERROR_BAD_STATE; + } else { + global_data.rng.entropy_init = entropy_init; + global_data.rng.entropy_free = entropy_free; + status = PSA_SUCCESS; } - prf->state = PSA_TLS12_PRF_STATE_SEED_SET; +#if defined(MBEDTLS_THREADING_C) + mbedtls_mutex_unlock(&mbedtls_threading_psa_rngdata_mutex); +#endif /* defined(MBEDTLS_THREADING_C) */ - return PSA_SUCCESS; + return status; } +#endif /* !defined(MBEDTLS_PSA_CRYPTO_EXTERNAL_RNG) */ -static psa_status_t psa_tls12_prf_set_key(psa_tls12_prf_key_derivation_t *prf, - const uint8_t *data, - size_t data_length) +void mbedtls_psa_crypto_free(void) { - if (prf->state != PSA_TLS12_PRF_STATE_SEED_SET) { - return PSA_ERROR_BAD_STATE; - } - if (data_length != 0) { - prf->secret = mbedtls_calloc(1, data_length); - if (prf->secret == NULL) { - return PSA_ERROR_INSUFFICIENT_MEMORY; - } +#if defined(MBEDTLS_THREADING_C) + mbedtls_mutex_lock(&mbedtls_threading_psa_globaldata_mutex); +#endif /* defined(MBEDTLS_THREADING_C) */ - memcpy(prf->secret, data, data_length); - prf->secret_length = data_length; + /* Nothing to do to free transaction. */ + if (global_data.initialized & PSA_CRYPTO_SUBSYSTEM_TRANSACTION_INITIALIZED) { + global_data.initialized &= ~PSA_CRYPTO_SUBSYSTEM_TRANSACTION_INITIALIZED; } - prf->state = PSA_TLS12_PRF_STATE_KEY_SET; + if (global_data.initialized & PSA_CRYPTO_SUBSYSTEM_KEY_SLOTS_INITIALIZED) { + psa_wipe_all_key_slots(); + global_data.initialized &= ~PSA_CRYPTO_SUBSYSTEM_KEY_SLOTS_INITIALIZED; + } - return PSA_SUCCESS; -} +#if defined(MBEDTLS_THREADING_C) + mbedtls_mutex_unlock(&mbedtls_threading_psa_globaldata_mutex); +#endif /* defined(MBEDTLS_THREADING_C) */ -static psa_status_t psa_tls12_prf_set_label(psa_tls12_prf_key_derivation_t *prf, - const uint8_t *data, - size_t data_length) -{ - if (prf->state != PSA_TLS12_PRF_STATE_KEY_SET) { - return PSA_ERROR_BAD_STATE; +#if defined(MBEDTLS_THREADING_C) + mbedtls_mutex_lock(&mbedtls_threading_psa_rngdata_mutex); +#endif /* defined(MBEDTLS_THREADING_C) */ + + if (global_data.rng_state != RNG_NOT_INITIALIZED) { + mbedtls_psa_random_free(&global_data.rng); } + global_data.rng_state = RNG_NOT_INITIALIZED; + mbedtls_platform_zeroize(&global_data.rng, sizeof(global_data.rng)); - if (data_length != 0) { - prf->label = mbedtls_calloc(1, data_length); - if (prf->label == NULL) { - return PSA_ERROR_INSUFFICIENT_MEMORY; - } +#if defined(MBEDTLS_THREADING_C) + mbedtls_mutex_unlock(&mbedtls_threading_psa_rngdata_mutex); +#endif /* defined(MBEDTLS_THREADING_C) */ - memcpy(prf->label, data, data_length); - prf->label_length = data_length; +#if defined(MBEDTLS_THREADING_C) + mbedtls_mutex_lock(&mbedtls_threading_psa_globaldata_mutex); +#endif /* defined(MBEDTLS_THREADING_C) */ + + /* Terminate drivers */ + if (global_data.initialized & PSA_CRYPTO_SUBSYSTEM_DRIVER_WRAPPERS_INITIALIZED) { + psa_driver_wrapper_free(); + global_data.initialized &= ~PSA_CRYPTO_SUBSYSTEM_DRIVER_WRAPPERS_INITIALIZED; } - prf->state = PSA_TLS12_PRF_STATE_LABEL_SET; +#if defined(MBEDTLS_THREADING_C) + mbedtls_mutex_unlock(&mbedtls_threading_psa_globaldata_mutex); +#endif /* defined(MBEDTLS_THREADING_C) */ - return PSA_SUCCESS; } -static psa_status_t psa_tls12_prf_input(psa_tls12_prf_key_derivation_t *prf, - psa_key_derivation_step_t step, - const uint8_t *data, - size_t data_length) +#if defined(PSA_CRYPTO_STORAGE_HAS_TRANSACTIONS) +/** Recover a transaction that was interrupted by a power failure. + * + * This function is called during initialization, before psa_crypto_init() + * returns. If this function returns a failure status, the initialization + * fails. + */ +static psa_status_t psa_crypto_recover_transaction( + const psa_crypto_transaction_t *transaction) { - switch (step) { - case PSA_KEY_DERIVATION_INPUT_SEED: - return psa_tls12_prf_set_seed(prf, data, data_length); - case PSA_KEY_DERIVATION_INPUT_SECRET: - return psa_tls12_prf_set_key(prf, data, data_length); - case PSA_KEY_DERIVATION_INPUT_LABEL: - return psa_tls12_prf_set_label(prf, data, data_length); + switch (transaction->unknown.type) { + case PSA_CRYPTO_TRANSACTION_CREATE_KEY: + case PSA_CRYPTO_TRANSACTION_DESTROY_KEY: + /* TODO - fall through to the failure case until this + * is implemented. + * https://github.com/ARMmbed/mbed-crypto/issues/218 + */ default: - return PSA_ERROR_INVALID_ARGUMENT; + /* We found an unsupported transaction in the storage. + * We don't know what state the storage is in. Give up. */ + return PSA_ERROR_DATA_INVALID; } } -#endif /* MBEDTLS_PSA_BUILTIN_ALG_TLS12_PRF) || - * MBEDTLS_PSA_BUILTIN_ALG_TLS12_PSK_TO_MS */ +#endif /* PSA_CRYPTO_STORAGE_HAS_TRANSACTIONS */ -#if defined(MBEDTLS_PSA_BUILTIN_ALG_TLS12_PSK_TO_MS) -static psa_status_t psa_tls12_prf_psk_to_ms_set_key( - psa_tls12_prf_key_derivation_t *prf, - const uint8_t *data, - size_t data_length) +static psa_status_t mbedtls_psa_crypto_init_subsystem(mbedtls_psa_crypto_subsystem subsystem) { - psa_status_t status; - uint8_t pms[4 + 2 * PSA_TLS12_PSK_TO_MS_PSK_MAX_SIZE]; - uint8_t *cur = pms; + psa_status_t status = PSA_SUCCESS; + uint8_t driver_wrappers_initialized = 0; - if (data_length > PSA_TLS12_PSK_TO_MS_PSK_MAX_SIZE) { - return PSA_ERROR_INVALID_ARGUMENT; - } + switch (subsystem) { + case PSA_CRYPTO_SUBSYSTEM_DRIVER_WRAPPERS: - /* Quoting RFC 4279, Section 2: - * - * The premaster secret is formed as follows: if the PSK is N octets - * long, concatenate a uint16 with the value N, N zero octets, a second - * uint16 with the value N, and the PSK itself. - */ +#if defined(MBEDTLS_THREADING_C) + PSA_THREADING_CHK_GOTO_EXIT(mbedtls_mutex_lock(&mbedtls_threading_psa_globaldata_mutex)); +#endif /* defined(MBEDTLS_THREADING_C) */ - *cur++ = MBEDTLS_BYTE_1(data_length); - *cur++ = MBEDTLS_BYTE_0(data_length); - memset(cur, 0, data_length); - cur += data_length; - *cur++ = pms[0]; - *cur++ = pms[1]; - memcpy(cur, data, data_length); - cur += data_length; + if (!(global_data.initialized & PSA_CRYPTO_SUBSYSTEM_DRIVER_WRAPPERS_INITIALIZED)) { + /* Init drivers */ + status = psa_driver_wrapper_init(); - status = psa_tls12_prf_set_key(prf, pms, cur - pms); + /* Drivers need shutdown regardless of startup errors. */ + global_data.initialized |= PSA_CRYPTO_SUBSYSTEM_DRIVER_WRAPPERS_INITIALIZED; - mbedtls_platform_zeroize(pms, sizeof(pms)); - return status; -} -static psa_status_t psa_tls12_prf_psk_to_ms_input( - psa_tls12_prf_key_derivation_t *prf, - psa_key_derivation_step_t step, - const uint8_t *data, - size_t data_length) -{ - if (step == PSA_KEY_DERIVATION_INPUT_SECRET) { - return psa_tls12_prf_psk_to_ms_set_key(prf, - data, data_length); - } + } +#if defined(MBEDTLS_THREADING_C) + PSA_THREADING_CHK_GOTO_EXIT(mbedtls_mutex_unlock( + &mbedtls_threading_psa_globaldata_mutex)); +#endif /* defined(MBEDTLS_THREADING_C) */ - return psa_tls12_prf_input(prf, step, data, data_length); -} -#endif /* MBEDTLS_PSA_BUILTIN_ALG_TLS12_PSK_TO_MS */ + break; + + case PSA_CRYPTO_SUBSYSTEM_KEY_SLOTS: + +#if defined(MBEDTLS_THREADING_C) + PSA_THREADING_CHK_GOTO_EXIT(mbedtls_mutex_lock(&mbedtls_threading_psa_globaldata_mutex)); +#endif /* defined(MBEDTLS_THREADING_C) */ + + if (!(global_data.initialized & PSA_CRYPTO_SUBSYSTEM_KEY_SLOTS_INITIALIZED)) { + status = psa_initialize_key_slots(); + + /* Need to wipe keys even if initialization fails. */ + global_data.initialized |= PSA_CRYPTO_SUBSYSTEM_KEY_SLOTS_INITIALIZED; -/** Check whether the given key type is acceptable for the given - * input step of a key derivation. - * - * Secret inputs must have the type #PSA_KEY_TYPE_DERIVE. - * Non-secret inputs must have the type #PSA_KEY_TYPE_RAW_DATA. - * Both secret and non-secret inputs can alternatively have the type - * #PSA_KEY_TYPE_NONE, which is never the type of a key object, meaning - * that the input was passed as a buffer rather than via a key object. - */ -static int psa_key_derivation_check_input_type( - psa_key_derivation_step_t step, - psa_key_type_t key_type) -{ - switch (step) { - case PSA_KEY_DERIVATION_INPUT_SECRET: - if (key_type == PSA_KEY_TYPE_DERIVE) { - return PSA_SUCCESS; - } - if (key_type == PSA_KEY_TYPE_NONE) { - return PSA_SUCCESS; } +#if defined(MBEDTLS_THREADING_C) + PSA_THREADING_CHK_GOTO_EXIT(mbedtls_mutex_unlock( + &mbedtls_threading_psa_globaldata_mutex)); +#endif /* defined(MBEDTLS_THREADING_C) */ + break; - case PSA_KEY_DERIVATION_INPUT_LABEL: - case PSA_KEY_DERIVATION_INPUT_SALT: - case PSA_KEY_DERIVATION_INPUT_INFO: - case PSA_KEY_DERIVATION_INPUT_SEED: - if (key_type == PSA_KEY_TYPE_RAW_DATA) { - return PSA_SUCCESS; - } - if (key_type == PSA_KEY_TYPE_NONE) { - return PSA_SUCCESS; + + case PSA_CRYPTO_SUBSYSTEM_RNG: + +#if defined(MBEDTLS_THREADING_C) + PSA_THREADING_CHK_GOTO_EXIT(mbedtls_mutex_lock(&mbedtls_threading_psa_globaldata_mutex)); +#endif /* defined(MBEDTLS_THREADING_C) */ + + driver_wrappers_initialized = + (global_data.initialized & PSA_CRYPTO_SUBSYSTEM_DRIVER_WRAPPERS_INITIALIZED); + +#if defined(MBEDTLS_THREADING_C) + PSA_THREADING_CHK_GOTO_EXIT(mbedtls_mutex_unlock( + &mbedtls_threading_psa_globaldata_mutex)); +#endif /* defined(MBEDTLS_THREADING_C) */ + + /* Need to use separate mutex here, as initialisation can require + * testing of init flags, which requires locking the global data + * mutex. */ +#if defined(MBEDTLS_THREADING_C) + PSA_THREADING_CHK_GOTO_EXIT(mbedtls_mutex_lock(&mbedtls_threading_psa_rngdata_mutex)); +#endif /* defined(MBEDTLS_THREADING_C) */ + + /* Initialize and seed the random generator. */ + if (global_data.rng_state == RNG_NOT_INITIALIZED && driver_wrappers_initialized) { + mbedtls_psa_random_init(&global_data.rng); + global_data.rng_state = RNG_INITIALIZED; + + status = mbedtls_psa_random_seed(&global_data.rng); + if (status == PSA_SUCCESS) { + global_data.rng_state = RNG_SEEDED; + } } + +#if defined(MBEDTLS_THREADING_C) + PSA_THREADING_CHK_GOTO_EXIT(mbedtls_mutex_unlock( + &mbedtls_threading_psa_rngdata_mutex)); +#endif /* defined(MBEDTLS_THREADING_C) */ + + break; + + case PSA_CRYPTO_SUBSYSTEM_TRANSACTION: + +#if defined(MBEDTLS_THREADING_C) + PSA_THREADING_CHK_GOTO_EXIT(mbedtls_mutex_lock(&mbedtls_threading_psa_globaldata_mutex)); +#endif /* defined(MBEDTLS_THREADING_C) */ + + if (!(global_data.initialized & PSA_CRYPTO_SUBSYSTEM_TRANSACTION_INITIALIZED)) { +#if defined(PSA_CRYPTO_STORAGE_HAS_TRANSACTIONS) + status = psa_crypto_load_transaction(); + if (status == PSA_SUCCESS) { + status = psa_crypto_recover_transaction(&psa_crypto_transaction); + if (status == PSA_SUCCESS) { + global_data.initialized |= PSA_CRYPTO_SUBSYSTEM_TRANSACTION_INITIALIZED; + } + status = psa_crypto_stop_transaction(); + } else if (status == PSA_ERROR_DOES_NOT_EXIST) { + /* There's no transaction to complete. It's all good. */ + global_data.initialized |= PSA_CRYPTO_SUBSYSTEM_TRANSACTION_INITIALIZED; + status = PSA_SUCCESS; + } +#else /* defined(PSA_CRYPTO_STORAGE_HAS_TRANSACTIONS) */ + global_data.initialized |= PSA_CRYPTO_SUBSYSTEM_TRANSACTION_INITIALIZED; + status = PSA_SUCCESS; +#endif /* defined(PSA_CRYPTO_STORAGE_HAS_TRANSACTIONS) */ + } + +#if defined(MBEDTLS_THREADING_C) + PSA_THREADING_CHK_GOTO_EXIT(mbedtls_mutex_unlock( + &mbedtls_threading_psa_globaldata_mutex)); +#endif /* defined(MBEDTLS_THREADING_C) */ + break; + + default: + status = PSA_ERROR_CORRUPTION_DETECTED; } - return PSA_ERROR_INVALID_ARGUMENT; + + /* Exit label only required when using threading macros. */ +#if defined(MBEDTLS_THREADING_C) +exit: +#endif /* defined(MBEDTLS_THREADING_C) */ + + return status; } -static psa_status_t psa_key_derivation_input_internal( - psa_key_derivation_operation_t *operation, - psa_key_derivation_step_t step, - psa_key_type_t key_type, - const uint8_t *data, - size_t data_length) +psa_status_t psa_crypto_init(void) { psa_status_t status; - psa_algorithm_t kdf_alg = psa_key_derivation_get_kdf_alg(operation); - status = psa_key_derivation_check_input_type(step, key_type); + /* Double initialization is explicitly allowed. Early out if everything is + * done. */ + if (psa_get_initialized()) { + return PSA_SUCCESS; + } + + status = mbedtls_psa_crypto_init_subsystem(PSA_CRYPTO_SUBSYSTEM_DRIVER_WRAPPERS); if (status != PSA_SUCCESS) { goto exit; } -#if defined(MBEDTLS_PSA_BUILTIN_ALG_HKDF) - if (PSA_ALG_IS_HKDF(kdf_alg)) { - status = psa_hkdf_input(&operation->ctx.hkdf, - PSA_ALG_HKDF_GET_HASH(kdf_alg), - step, data, data_length); - } else -#endif /* MBEDTLS_PSA_BUILTIN_ALG_HKDF */ -#if defined(MBEDTLS_PSA_BUILTIN_ALG_TLS12_PRF) - if (PSA_ALG_IS_TLS12_PRF(kdf_alg)) { - status = psa_tls12_prf_input(&operation->ctx.tls12_prf, - step, data, data_length); - } else -#endif /* MBEDTLS_PSA_BUILTIN_ALG_TLS12_PRF */ -#if defined(MBEDTLS_PSA_BUILTIN_ALG_TLS12_PSK_TO_MS) - if (PSA_ALG_IS_TLS12_PSK_TO_MS(kdf_alg)) { - status = psa_tls12_prf_psk_to_ms_input(&operation->ctx.tls12_prf, - step, data, data_length); - } else -#endif /* MBEDTLS_PSA_BUILTIN_ALG_TLS12_PSK_TO_MS */ - { - /* This can't happen unless the operation object was not initialized */ - (void) data; - (void) data_length; - (void) kdf_alg; - return PSA_ERROR_BAD_STATE; + status = mbedtls_psa_crypto_init_subsystem(PSA_CRYPTO_SUBSYSTEM_KEY_SLOTS); + if (status != PSA_SUCCESS) { + goto exit; + } + + status = mbedtls_psa_crypto_init_subsystem(PSA_CRYPTO_SUBSYSTEM_RNG); + if (status != PSA_SUCCESS) { + goto exit; } + status = mbedtls_psa_crypto_init_subsystem(PSA_CRYPTO_SUBSYSTEM_TRANSACTION); + exit: + if (status != PSA_SUCCESS) { - psa_key_derivation_abort(operation); + mbedtls_psa_crypto_free(); } + return status; } -psa_status_t psa_key_derivation_input_bytes( - psa_key_derivation_operation_t *operation, - psa_key_derivation_step_t step, - const uint8_t *data, - size_t data_length) +#if defined(PSA_WANT_ALG_SOME_PAKE) +psa_status_t psa_crypto_driver_pake_get_password_len( + const psa_crypto_driver_pake_inputs_t *inputs, + size_t *password_len) { - return psa_key_derivation_input_internal(operation, step, - PSA_KEY_TYPE_NONE, - data, data_length); + if (inputs->password_len == 0) { + return PSA_ERROR_BAD_STATE; + } + + *password_len = inputs->password_len; + + return PSA_SUCCESS; } -psa_status_t psa_key_derivation_input_key( - psa_key_derivation_operation_t *operation, - psa_key_derivation_step_t step, - mbedtls_svc_key_id_t key) +psa_status_t psa_crypto_driver_pake_get_password( + const psa_crypto_driver_pake_inputs_t *inputs, + uint8_t *buffer, size_t buffer_size, size_t *buffer_length) { - psa_status_t status = PSA_ERROR_CORRUPTION_DETECTED; - psa_status_t unlock_status = PSA_ERROR_CORRUPTION_DETECTED; - psa_key_slot_t *slot; - - status = psa_get_and_lock_transparent_key_slot_with_policy( - key, &slot, PSA_KEY_USAGE_DERIVE, operation->alg); - if (status != PSA_SUCCESS) { - psa_key_derivation_abort(operation); - return status; + if (inputs->password_len == 0) { + return PSA_ERROR_BAD_STATE; } - /* Passing a key object as a SECRET input unlocks the permission - * to output to a key object. */ - if (step == PSA_KEY_DERIVATION_INPUT_SECRET) { - operation->can_output_key = 1; + if (buffer_size < inputs->password_len) { + return PSA_ERROR_BUFFER_TOO_SMALL; } - status = psa_key_derivation_input_internal(operation, - step, slot->attr.type, - slot->key.data, - slot->key.bytes); - - unlock_status = psa_unlock_key_slot(slot); + memcpy(buffer, inputs->password, inputs->password_len); + *buffer_length = inputs->password_len; - return (status == PSA_SUCCESS) ? unlock_status : status; + return PSA_SUCCESS; } +psa_status_t psa_crypto_driver_pake_get_user_len( + const psa_crypto_driver_pake_inputs_t *inputs, + size_t *user_len) +{ + if (inputs->user_len == 0) { + return PSA_ERROR_BAD_STATE; + } + *user_len = inputs->user_len; -/****************************************************************/ -/* Key agreement */ -/****************************************************************/ + return PSA_SUCCESS; +} -#if defined(MBEDTLS_PSA_BUILTIN_ALG_ECDH) -static psa_status_t psa_key_agreement_ecdh(const uint8_t *peer_key, - size_t peer_key_length, - const mbedtls_ecp_keypair *our_key, - uint8_t *shared_secret, - size_t shared_secret_size, - size_t *shared_secret_length) +psa_status_t psa_crypto_driver_pake_get_user( + const psa_crypto_driver_pake_inputs_t *inputs, + uint8_t *user_id, size_t user_id_size, size_t *user_id_len) { - mbedtls_ecp_keypair *their_key = NULL; - mbedtls_ecdh_context ecdh; - psa_status_t status; - size_t bits = 0; - psa_ecc_family_t curve = mbedtls_ecc_group_to_psa(our_key->grp.id, &bits); - mbedtls_ecdh_init(&ecdh); - - status = mbedtls_psa_ecp_load_representation( - PSA_KEY_TYPE_ECC_PUBLIC_KEY(curve), - bits, - peer_key, - peer_key_length, - &their_key); - if (status != PSA_SUCCESS) { - goto exit; + if (inputs->user_len == 0) { + return PSA_ERROR_BAD_STATE; } - status = mbedtls_to_psa_error( - mbedtls_ecdh_get_params(&ecdh, their_key, MBEDTLS_ECDH_THEIRS)); - if (status != PSA_SUCCESS) { - goto exit; - } - status = mbedtls_to_psa_error( - mbedtls_ecdh_get_params(&ecdh, our_key, MBEDTLS_ECDH_OURS)); - if (status != PSA_SUCCESS) { - goto exit; + if (user_id_size < inputs->user_len) { + return PSA_ERROR_BUFFER_TOO_SMALL; } - status = mbedtls_to_psa_error( - mbedtls_ecdh_calc_secret(&ecdh, - shared_secret_length, - shared_secret, shared_secret_size, - mbedtls_psa_get_random, - MBEDTLS_PSA_RANDOM_STATE)); - if (status != PSA_SUCCESS) { - goto exit; + memcpy(user_id, inputs->user, inputs->user_len); + *user_id_len = inputs->user_len; + + return PSA_SUCCESS; +} + +psa_status_t psa_crypto_driver_pake_get_peer_len( + const psa_crypto_driver_pake_inputs_t *inputs, + size_t *peer_len) +{ + if (inputs->peer_len == 0) { + return PSA_ERROR_BAD_STATE; } - if (PSA_BITS_TO_BYTES(bits) != *shared_secret_length) { - status = PSA_ERROR_CORRUPTION_DETECTED; + + *peer_len = inputs->peer_len; + + return PSA_SUCCESS; +} + +psa_status_t psa_crypto_driver_pake_get_peer( + const psa_crypto_driver_pake_inputs_t *inputs, + uint8_t *peer_id, size_t peer_id_size, size_t *peer_id_length) +{ + if (inputs->peer_len == 0) { + return PSA_ERROR_BAD_STATE; } -exit: - if (status != PSA_SUCCESS) { - mbedtls_platform_zeroize(shared_secret, shared_secret_size); + if (peer_id_size < inputs->peer_len) { + return PSA_ERROR_BUFFER_TOO_SMALL; } - mbedtls_ecdh_free(&ecdh); - mbedtls_ecp_keypair_free(their_key); - mbedtls_free(their_key); - return status; -} -#endif /* MBEDTLS_PSA_BUILTIN_ALG_ECDH */ + memcpy(peer_id, inputs->peer, inputs->peer_len); + *peer_id_length = inputs->peer_len; -#define PSA_KEY_AGREEMENT_MAX_SHARED_SECRET_SIZE MBEDTLS_ECP_MAX_BYTES + return PSA_SUCCESS; +} -static psa_status_t psa_key_agreement_raw_internal(psa_algorithm_t alg, - psa_key_slot_t *private_key, - const uint8_t *peer_key, - size_t peer_key_length, - uint8_t *shared_secret, - size_t shared_secret_size, - size_t *shared_secret_length) +psa_status_t psa_crypto_driver_pake_get_cipher_suite( + const psa_crypto_driver_pake_inputs_t *inputs, + psa_pake_cipher_suite_t *cipher_suite) { - mbedtls_ecp_keypair *ecp = NULL; - psa_status_t status; - - switch (alg) { -#if defined(MBEDTLS_PSA_BUILTIN_ALG_ECDH) - case PSA_ALG_ECDH: - if (!PSA_KEY_TYPE_IS_ECC_KEY_PAIR(private_key->attr.type)) { - return PSA_ERROR_INVALID_ARGUMENT; - } - status = mbedtls_psa_ecp_load_representation( - private_key->attr.type, - private_key->attr.bits, - private_key->key.data, - private_key->key.bytes, - &ecp); - if (status != PSA_SUCCESS) { - return status; - } - status = psa_key_agreement_ecdh(peer_key, peer_key_length, - ecp, - shared_secret, shared_secret_size, - shared_secret_length); - mbedtls_ecp_keypair_free(ecp); - mbedtls_free(ecp); - return status; -#endif /* MBEDTLS_PSA_BUILTIN_ALG_ECDH */ - default: - (void) ecp; - (void) status; - (void) private_key; - (void) peer_key; - (void) peer_key_length; - (void) shared_secret; - (void) shared_secret_size; - (void) shared_secret_length; - return PSA_ERROR_NOT_SUPPORTED; + if (inputs->cipher_suite.algorithm == PSA_ALG_NONE) { + return PSA_ERROR_BAD_STATE; } + + *cipher_suite = inputs->cipher_suite; + + return PSA_SUCCESS; } -/* Note that if this function fails, you must call psa_key_derivation_abort() - * to potentially free embedded data structures and wipe confidential data. - */ -static psa_status_t psa_key_agreement_internal(psa_key_derivation_operation_t *operation, - psa_key_derivation_step_t step, - psa_key_slot_t *private_key, - const uint8_t *peer_key, - size_t peer_key_length) +psa_status_t psa_pake_setup( + psa_pake_operation_t *operation, + const psa_pake_cipher_suite_t *cipher_suite) { - psa_status_t status; - uint8_t shared_secret[PSA_KEY_AGREEMENT_MAX_SHARED_SECRET_SIZE]; - size_t shared_secret_length = 0; - psa_algorithm_t ka_alg = PSA_ALG_KEY_AGREEMENT_GET_BASE(operation->alg); + psa_status_t status = PSA_ERROR_CORRUPTION_DETECTED; - /* Step 1: run the secret agreement algorithm to generate the shared - * secret. */ - status = psa_key_agreement_raw_internal(ka_alg, - private_key, - peer_key, peer_key_length, - shared_secret, - sizeof(shared_secret), - &shared_secret_length); - if (status != PSA_SUCCESS) { + if (operation->stage != PSA_PAKE_OPERATION_STAGE_SETUP) { + status = PSA_ERROR_BAD_STATE; goto exit; } - /* Step 2: set up the key derivation to generate key material from - * the shared secret. A shared secret is permitted wherever a key - * of type DERIVE is permitted. */ - status = psa_key_derivation_input_internal(operation, step, - PSA_KEY_TYPE_DERIVE, - shared_secret, - shared_secret_length); + if (PSA_ALG_IS_PAKE(cipher_suite->algorithm) == 0 || + PSA_ALG_IS_HASH(cipher_suite->hash) == 0) { + status = PSA_ERROR_INVALID_ARGUMENT; + goto exit; + } + + memset(&operation->data.inputs, 0, sizeof(operation->data.inputs)); + + operation->alg = cipher_suite->algorithm; + operation->primitive = PSA_PAKE_PRIMITIVE(cipher_suite->type, + cipher_suite->family, cipher_suite->bits); + operation->data.inputs.cipher_suite = *cipher_suite; + +#if defined(PSA_WANT_ALG_JPAKE) + if (operation->alg == PSA_ALG_JPAKE) { + psa_jpake_computation_stage_t *computation_stage = + &operation->computation_stage.jpake; + + memset(computation_stage, 0, sizeof(*computation_stage)); + computation_stage->step = PSA_PAKE_STEP_KEY_SHARE; + } else +#endif /* PSA_WANT_ALG_JPAKE */ + { + status = PSA_ERROR_NOT_SUPPORTED; + goto exit; + } + + operation->stage = PSA_PAKE_OPERATION_STAGE_COLLECT_INPUTS; + + return PSA_SUCCESS; exit: - mbedtls_platform_zeroize(shared_secret, shared_secret_length); + psa_pake_abort(operation); return status; } -psa_status_t psa_key_derivation_key_agreement(psa_key_derivation_operation_t *operation, - psa_key_derivation_step_t step, - mbedtls_svc_key_id_t private_key, - const uint8_t *peer_key, - size_t peer_key_length) +psa_status_t psa_pake_set_password_key( + psa_pake_operation_t *operation, + mbedtls_svc_key_id_t password) { psa_status_t status = PSA_ERROR_CORRUPTION_DETECTED; psa_status_t unlock_status = PSA_ERROR_CORRUPTION_DETECTED; - psa_key_slot_t *slot; + psa_key_slot_t *slot = NULL; + psa_key_type_t type; - if (!PSA_ALG_IS_KEY_AGREEMENT(operation->alg)) { - return PSA_ERROR_INVALID_ARGUMENT; + if (operation->stage != PSA_PAKE_OPERATION_STAGE_COLLECT_INPUTS) { + status = PSA_ERROR_BAD_STATE; + goto exit; } - status = psa_get_and_lock_transparent_key_slot_with_policy( - private_key, &slot, PSA_KEY_USAGE_DERIVE, operation->alg); + + status = psa_get_and_lock_key_slot_with_policy(password, &slot, + PSA_KEY_USAGE_DERIVE, + operation->alg); if (status != PSA_SUCCESS) { - return status; + goto exit; } - status = psa_key_agreement_internal(operation, step, - slot, - peer_key, peer_key_length); - if (status != PSA_SUCCESS) { - psa_key_derivation_abort(operation); - } else { - /* If a private key has been added as SECRET, we allow the derived - * key material to be used as a key in PSA Crypto. */ - if (step == PSA_KEY_DERIVATION_INPUT_SECRET) { - operation->can_output_key = 1; - } + + type = psa_get_key_type(&slot->attr); + + if (type != PSA_KEY_TYPE_PASSWORD && + type != PSA_KEY_TYPE_PASSWORD_HASH) { + status = PSA_ERROR_INVALID_ARGUMENT; + goto exit; + } + + operation->data.inputs.password = mbedtls_calloc(1, slot->key.bytes); + if (operation->data.inputs.password == NULL) { + status = PSA_ERROR_INSUFFICIENT_MEMORY; + goto exit; } - unlock_status = psa_unlock_key_slot(slot); + memcpy(operation->data.inputs.password, slot->key.data, slot->key.bytes); + operation->data.inputs.password_len = slot->key.bytes; + operation->data.inputs.attributes = slot->attr; +exit: + if (status != PSA_SUCCESS) { + psa_pake_abort(operation); + } + unlock_status = psa_unregister_read_under_mutex(slot); return (status == PSA_SUCCESS) ? unlock_status : status; } -psa_status_t psa_raw_key_agreement(psa_algorithm_t alg, - mbedtls_svc_key_id_t private_key, - const uint8_t *peer_key, - size_t peer_key_length, - uint8_t *output, - size_t output_size, - size_t *output_length) +psa_status_t psa_pake_set_user( + psa_pake_operation_t *operation, + const uint8_t *user_id_external, + size_t user_id_len) { psa_status_t status = PSA_ERROR_CORRUPTION_DETECTED; - psa_status_t unlock_status = PSA_ERROR_CORRUPTION_DETECTED; - psa_key_slot_t *slot = NULL; - size_t expected_length; + LOCAL_INPUT_DECLARE(user_id_external, user_id); - if (!PSA_ALG_IS_KEY_AGREEMENT(alg)) { + if (operation->stage != PSA_PAKE_OPERATION_STAGE_COLLECT_INPUTS) { + status = PSA_ERROR_BAD_STATE; + goto exit; + } + + if (user_id_len == 0) { status = PSA_ERROR_INVALID_ARGUMENT; goto exit; } - status = psa_get_and_lock_transparent_key_slot_with_policy( - private_key, &slot, PSA_KEY_USAGE_DERIVE, alg); - if (status != PSA_SUCCESS) { + + if (operation->data.inputs.user_len != 0) { + status = PSA_ERROR_BAD_STATE; goto exit; } - /* PSA_RAW_KEY_AGREEMENT_OUTPUT_SIZE() is in general an upper bound - * for the output size. The PSA specification only guarantees that this - * function works if output_size >= PSA_RAW_KEY_AGREEMENT_OUTPUT_SIZE(...), - * but it might be nice to allow smaller buffers if the output fits. - * At the time of writing this comment, with only ECDH implemented, - * PSA_RAW_KEY_AGREEMENT_OUTPUT_SIZE() is exact so the point is moot. - * If FFDH is implemented, PSA_RAW_KEY_AGREEMENT_OUTPUT_SIZE() can easily - * be exact for it as well. */ - expected_length = - PSA_RAW_KEY_AGREEMENT_OUTPUT_SIZE(slot->attr.type, slot->attr.bits); - if (output_size < expected_length) { - status = PSA_ERROR_BUFFER_TOO_SMALL; + operation->data.inputs.user = mbedtls_calloc(1, user_id_len); + if (operation->data.inputs.user == NULL) { + status = PSA_ERROR_INSUFFICIENT_MEMORY; goto exit; } - status = psa_key_agreement_raw_internal(alg, slot, - peer_key, peer_key_length, - output, output_size, - output_length); + LOCAL_INPUT_ALLOC(user_id_external, user_id_len, user_id); + + memcpy(operation->data.inputs.user, user_id, user_id_len); + operation->data.inputs.user_len = user_id_len; + + status = PSA_SUCCESS; exit: + LOCAL_INPUT_FREE(user_id_external, user_id); if (status != PSA_SUCCESS) { - /* If an error happens and is not handled properly, the output - * may be used as a key to protect sensitive data. Arrange for such - * a key to be random, which is likely to result in decryption or - * verification errors. This is better than filling the buffer with - * some constant data such as zeros, which would result in the data - * being protected with a reproducible, easily knowable key. - */ - psa_generate_random(output, output_size); - *output_length = output_size; + psa_pake_abort(operation); } + return status; +} - unlock_status = psa_unlock_key_slot(slot); +psa_status_t psa_pake_set_peer( + psa_pake_operation_t *operation, + const uint8_t *peer_id_external, + size_t peer_id_len) +{ + psa_status_t status = PSA_ERROR_CORRUPTION_DETECTED; + LOCAL_INPUT_DECLARE(peer_id_external, peer_id); - return (status == PSA_SUCCESS) ? unlock_status : status; -} + if (operation->stage != PSA_PAKE_OPERATION_STAGE_COLLECT_INPUTS) { + status = PSA_ERROR_BAD_STATE; + goto exit; + } + if (peer_id_len == 0) { + status = PSA_ERROR_INVALID_ARGUMENT; + goto exit; + } + if (operation->data.inputs.peer_len != 0) { + status = PSA_ERROR_BAD_STATE; + goto exit; + } -/****************************************************************/ -/* Random generation */ -/****************************************************************/ + operation->data.inputs.peer = mbedtls_calloc(1, peer_id_len); + if (operation->data.inputs.peer == NULL) { + status = PSA_ERROR_INSUFFICIENT_MEMORY; + goto exit; + } -#if defined(MBEDTLS_PSA_INJECT_ENTROPY) -#include "mbedtls/entropy_poll.h" -#endif + LOCAL_INPUT_ALLOC(peer_id_external, peer_id_len, peer_id); -/** Initialize the PSA random generator. - */ -static void mbedtls_psa_random_init(mbedtls_psa_random_context_t *rng) -{ -#if defined(MBEDTLS_PSA_CRYPTO_EXTERNAL_RNG) - memset(rng, 0, sizeof(*rng)); -#else /* MBEDTLS_PSA_CRYPTO_EXTERNAL_RNG */ + memcpy(operation->data.inputs.peer, peer_id, peer_id_len); + operation->data.inputs.peer_len = peer_id_len; - /* Set default configuration if - * mbedtls_psa_crypto_configure_entropy_sources() hasn't been called. */ - if (rng->entropy_init == NULL) { - rng->entropy_init = mbedtls_entropy_init; + status = PSA_SUCCESS; + +exit: + LOCAL_INPUT_FREE(peer_id_external, peer_id); + if (status != PSA_SUCCESS) { + psa_pake_abort(operation); } - if (rng->entropy_free == NULL) { - rng->entropy_free = mbedtls_entropy_free; + return status; +} + +psa_status_t psa_pake_set_role( + psa_pake_operation_t *operation, + psa_pake_role_t role) +{ + psa_status_t status = PSA_ERROR_CORRUPTION_DETECTED; + + if (operation->stage != PSA_PAKE_OPERATION_STAGE_COLLECT_INPUTS) { + status = PSA_ERROR_BAD_STATE; + goto exit; } - rng->entropy_init(&rng->entropy); -#if defined(MBEDTLS_PSA_INJECT_ENTROPY) && \ - defined(MBEDTLS_NO_DEFAULT_ENTROPY_SOURCES) - /* The PSA entropy injection feature depends on using NV seed as an entropy - * source. Add NV seed as an entropy source for PSA entropy injection. */ - mbedtls_entropy_add_source(&rng->entropy, - mbedtls_nv_seed_poll, NULL, - MBEDTLS_ENTROPY_BLOCK_SIZE, - MBEDTLS_ENTROPY_SOURCE_STRONG); + switch (operation->alg) { +#if defined(PSA_WANT_ALG_JPAKE) + case PSA_ALG_JPAKE: + if (role == PSA_PAKE_ROLE_NONE) { + return PSA_SUCCESS; + } + status = PSA_ERROR_INVALID_ARGUMENT; + break; #endif - - mbedtls_psa_drbg_init(MBEDTLS_PSA_RANDOM_STATE); -#endif /* MBEDTLS_PSA_CRYPTO_EXTERNAL_RNG */ + default: + (void) role; + status = PSA_ERROR_NOT_SUPPORTED; + goto exit; + } +exit: + psa_pake_abort(operation); + return status; } -/** Deinitialize the PSA random generator. - */ -static void mbedtls_psa_random_free(mbedtls_psa_random_context_t *rng) +/* Auxiliary function to convert core computation stage to single driver step. */ +#if defined(PSA_WANT_ALG_JPAKE) +static psa_crypto_driver_pake_step_t convert_jpake_computation_stage_to_driver_step( + psa_jpake_computation_stage_t *stage) { -#if defined(MBEDTLS_PSA_CRYPTO_EXTERNAL_RNG) - memset(rng, 0, sizeof(*rng)); -#else /* MBEDTLS_PSA_CRYPTO_EXTERNAL_RNG */ - mbedtls_psa_drbg_free(MBEDTLS_PSA_RANDOM_STATE); - rng->entropy_free(&rng->entropy); -#endif /* MBEDTLS_PSA_CRYPTO_EXTERNAL_RNG */ -} + psa_crypto_driver_pake_step_t key_share_step; + if (stage->round == PSA_JPAKE_FIRST) { + int is_x1; -/** Seed the PSA random generator. - */ -static psa_status_t mbedtls_psa_random_seed(mbedtls_psa_random_context_t *rng) -{ -#if defined(MBEDTLS_PSA_CRYPTO_EXTERNAL_RNG) - /* Do nothing: the external RNG seeds itself. */ - (void) rng; - return PSA_SUCCESS; -#else /* MBEDTLS_PSA_CRYPTO_EXTERNAL_RNG */ - const unsigned char drbg_seed[] = "PSA"; - int ret = mbedtls_psa_drbg_seed(&rng->entropy, - drbg_seed, sizeof(drbg_seed) - 1); - return mbedtls_to_psa_error(ret); -#endif /* MBEDTLS_PSA_CRYPTO_EXTERNAL_RNG */ + if (stage->io_mode == PSA_JPAKE_OUTPUT) { + is_x1 = (stage->outputs < 1); + } else { + is_x1 = (stage->inputs < 1); + } + + key_share_step = is_x1 ? + PSA_JPAKE_X1_STEP_KEY_SHARE : + PSA_JPAKE_X2_STEP_KEY_SHARE; + } else if (stage->round == PSA_JPAKE_SECOND) { + key_share_step = (stage->io_mode == PSA_JPAKE_OUTPUT) ? + PSA_JPAKE_X2S_STEP_KEY_SHARE : + PSA_JPAKE_X4S_STEP_KEY_SHARE; + } else { + return PSA_JPAKE_STEP_INVALID; + } + return (psa_crypto_driver_pake_step_t) (key_share_step + stage->step - PSA_PAKE_STEP_KEY_SHARE); } +#endif /* PSA_WANT_ALG_JPAKE */ -psa_status_t psa_generate_random(uint8_t *output, - size_t output_size) +static psa_status_t psa_pake_complete_inputs( + psa_pake_operation_t *operation) { - GUARD_MODULE_INITIALIZED; - -#if defined(MBEDTLS_PSA_CRYPTO_EXTERNAL_RNG) + psa_status_t status = PSA_ERROR_CORRUPTION_DETECTED; + /* Create copy of the inputs on stack as inputs share memory + with the driver context which will be setup by the driver. */ + psa_crypto_driver_pake_inputs_t inputs = operation->data.inputs; - size_t output_length = 0; - psa_status_t status = mbedtls_psa_external_get_random(&global_data.rng, - output, output_size, - &output_length); - if (status != PSA_SUCCESS) { - return status; - } - /* Breaking up a request into smaller chunks is currently not supported - * for the external RNG interface. */ - if (output_length != output_size) { - return PSA_ERROR_INSUFFICIENT_ENTROPY; + if (inputs.password_len == 0) { + return PSA_ERROR_BAD_STATE; } - return PSA_SUCCESS; -#else /* MBEDTLS_PSA_CRYPTO_EXTERNAL_RNG */ - - while (output_size > 0) { - size_t request_size = - (output_size > MBEDTLS_PSA_RANDOM_MAX_REQUEST ? - MBEDTLS_PSA_RANDOM_MAX_REQUEST : - output_size); - int ret = mbedtls_psa_get_random(MBEDTLS_PSA_RANDOM_STATE, - output, request_size); - if (ret != 0) { - return mbedtls_to_psa_error(ret); + if (operation->alg == PSA_ALG_JPAKE) { + if (inputs.user_len == 0 || inputs.peer_len == 0) { + return PSA_ERROR_BAD_STATE; } - output_size -= request_size; - output += request_size; } - return PSA_SUCCESS; -#endif /* MBEDTLS_PSA_CRYPTO_EXTERNAL_RNG */ -} -/* Wrapper function allowing the classic API to use the PSA RNG. - * - * `mbedtls_psa_get_random(MBEDTLS_PSA_RANDOM_STATE, ...)` calls - * `psa_generate_random(...)`. The state parameter is ignored since the - * PSA API doesn't support passing an explicit state. - * - * In the non-external case, psa_generate_random() calls an - * `mbedtls_xxx_drbg_random` function which has exactly the same signature - * and semantics as mbedtls_psa_get_random(). As an optimization, - * instead of doing this back-and-forth between the PSA API and the - * classic API, psa_crypto_random_impl.h defines `mbedtls_psa_get_random` - * as a constant function pointer to `mbedtls_xxx_drbg_random`. - */ -#if defined(MBEDTLS_PSA_CRYPTO_EXTERNAL_RNG) -int mbedtls_psa_get_random(void *p_rng, - unsigned char *output, - size_t output_size) -{ - /* This function takes a pointer to the RNG state because that's what - * classic mbedtls functions using an RNG expect. The PSA RNG manages - * its own state internally and doesn't let the caller access that state. - * So we just ignore the state parameter, and in practice we'll pass - * NULL. */ - (void) p_rng; - psa_status_t status = psa_generate_random(output, output_size); + /* Clear driver context */ + mbedtls_platform_zeroize(&operation->data, sizeof(operation->data)); + + status = psa_driver_wrapper_pake_setup(operation, &inputs); + + /* Driver is responsible for creating its own copy of the password. */ + mbedtls_zeroize_and_free(inputs.password, inputs.password_len); + + /* User and peer are translated to role. */ + mbedtls_free(inputs.user); + mbedtls_free(inputs.peer); + if (status == PSA_SUCCESS) { - return 0; - } else { - return MBEDTLS_ERR_ENTROPY_SOURCE_FAILED; +#if defined(PSA_WANT_ALG_JPAKE) + if (operation->alg == PSA_ALG_JPAKE) { + operation->stage = PSA_PAKE_OPERATION_STAGE_COMPUTATION; + } else +#endif /* PSA_WANT_ALG_JPAKE */ + { + status = PSA_ERROR_NOT_SUPPORTED; + } } + return status; } -#endif /* MBEDTLS_PSA_CRYPTO_EXTERNAL_RNG */ -#if defined(MBEDTLS_PSA_INJECT_ENTROPY) -psa_status_t mbedtls_psa_inject_entropy(const uint8_t *seed, - size_t seed_size) +#if defined(PSA_WANT_ALG_JPAKE) +static psa_status_t psa_jpake_prologue( + psa_pake_operation_t *operation, + psa_pake_step_t step, + psa_jpake_io_mode_t io_mode) { - if (global_data.initialized) { - return PSA_ERROR_NOT_PERMITTED; + if (step != PSA_PAKE_STEP_KEY_SHARE && + step != PSA_PAKE_STEP_ZK_PUBLIC && + step != PSA_PAKE_STEP_ZK_PROOF) { + return PSA_ERROR_INVALID_ARGUMENT; } - if (((seed_size < MBEDTLS_ENTROPY_MIN_PLATFORM) || - (seed_size < MBEDTLS_ENTROPY_BLOCK_SIZE)) || - (seed_size > MBEDTLS_ENTROPY_MAX_SEED_SIZE)) { - return PSA_ERROR_INVALID_ARGUMENT; + psa_jpake_computation_stage_t *computation_stage = + &operation->computation_stage.jpake; + + if (computation_stage->round != PSA_JPAKE_FIRST && + computation_stage->round != PSA_JPAKE_SECOND) { + return PSA_ERROR_BAD_STATE; } - return mbedtls_psa_storage_inject_entropy(seed, seed_size); + /* Check that the step we are given is the one we were expecting */ + if (step != computation_stage->step) { + return PSA_ERROR_BAD_STATE; + } + + if (step == PSA_PAKE_STEP_KEY_SHARE && + computation_stage->inputs == 0 && + computation_stage->outputs == 0) { + /* Start of the round, so function decides whether we are inputting + * or outputting */ + computation_stage->io_mode = io_mode; + } else if (computation_stage->io_mode != io_mode) { + /* Middle of the round so the mode we are in must match the function + * called by the user */ + return PSA_ERROR_BAD_STATE; + } + + return PSA_SUCCESS; } -#endif /* MBEDTLS_PSA_INJECT_ENTROPY */ -/** Validate the key type and size for key generation - * - * \param type The key type - * \param bits The number of bits of the key - * - * \retval #PSA_SUCCESS - * The key type and size are valid. - * \retval #PSA_ERROR_INVALID_ARGUMENT - * The size in bits of the key is not valid. - * \retval #PSA_ERROR_NOT_SUPPORTED - * The type and/or the size in bits of the key or the combination of - * the two is not supported. - */ -static psa_status_t psa_validate_key_type_and_size_for_key_generation( - psa_key_type_t type, size_t bits) +static psa_status_t psa_jpake_epilogue( + psa_pake_operation_t *operation, + psa_jpake_io_mode_t io_mode) { - psa_status_t status = PSA_ERROR_CORRUPTION_DETECTED; - - if (key_type_is_raw_bytes(type)) { - status = validate_unstructured_key_bit_size(type, bits); - if (status != PSA_SUCCESS) { - return status; + psa_jpake_computation_stage_t *stage = + &operation->computation_stage.jpake; + + if (stage->step == PSA_PAKE_STEP_ZK_PROOF) { + /* End of an input/output */ + if (io_mode == PSA_JPAKE_INPUT) { + stage->inputs++; + if (stage->inputs == PSA_JPAKE_EXPECTED_INPUTS(stage->round)) { + stage->io_mode = PSA_JPAKE_OUTPUT; + } } - } else -#if defined(PSA_WANT_KEY_TYPE_RSA_KEY_PAIR) - if (PSA_KEY_TYPE_IS_RSA(type) && PSA_KEY_TYPE_IS_KEY_PAIR(type)) { - if (bits > PSA_VENDOR_RSA_MAX_KEY_BITS) { - return PSA_ERROR_NOT_SUPPORTED; + if (io_mode == PSA_JPAKE_OUTPUT) { + stage->outputs++; + if (stage->outputs == PSA_JPAKE_EXPECTED_OUTPUTS(stage->round)) { + stage->io_mode = PSA_JPAKE_INPUT; + } } - - /* Accept only byte-aligned keys, for the same reasons as - * in psa_import_rsa_key(). */ - if (bits % 8 != 0) { - return PSA_ERROR_NOT_SUPPORTED; + if (stage->inputs == PSA_JPAKE_EXPECTED_INPUTS(stage->round) && + stage->outputs == PSA_JPAKE_EXPECTED_OUTPUTS(stage->round)) { + /* End of a round, move to the next round */ + stage->inputs = 0; + stage->outputs = 0; + stage->round++; } - } else -#endif /* defined(PSA_WANT_KEY_TYPE_RSA_KEY_PAIR) */ + stage->step = PSA_PAKE_STEP_KEY_SHARE; + } else { + stage->step++; + } + return PSA_SUCCESS; +} -#if defined(PSA_WANT_KEY_TYPE_ECC_KEY_PAIR) - if (PSA_KEY_TYPE_IS_ECC(type) && PSA_KEY_TYPE_IS_KEY_PAIR(type)) { - /* To avoid empty block, return successfully here. */ - return PSA_SUCCESS; - } else -#endif /* defined(PSA_WANT_KEY_TYPE_ECC_KEY_PAIR) */ - { - return PSA_ERROR_NOT_SUPPORTED; +#endif /* PSA_WANT_ALG_JPAKE */ + +psa_status_t psa_pake_output( + psa_pake_operation_t *operation, + psa_pake_step_t step, + uint8_t *output_external, + size_t output_size, + size_t *output_length) +{ + psa_status_t status = PSA_ERROR_CORRUPTION_DETECTED; + psa_crypto_driver_pake_step_t driver_step = PSA_JPAKE_STEP_INVALID; + LOCAL_OUTPUT_DECLARE(output_external, output); + *output_length = 0; + + if (operation->stage == PSA_PAKE_OPERATION_STAGE_COLLECT_INPUTS) { + status = psa_pake_complete_inputs(operation); + if (status != PSA_SUCCESS) { + goto exit; + } } - return PSA_SUCCESS; -} + if (operation->stage != PSA_PAKE_OPERATION_STAGE_COMPUTATION) { + status = PSA_ERROR_BAD_STATE; + goto exit; + } -psa_status_t psa_generate_key_internal( - const psa_key_attributes_t *attributes, - uint8_t *key_buffer, size_t key_buffer_size, size_t *key_buffer_length) -{ - psa_status_t status = PSA_ERROR_CORRUPTION_DETECTED; - psa_key_type_t type = attributes->core.type; + if (output_size == 0) { + status = PSA_ERROR_INVALID_ARGUMENT; + goto exit; + } - if ((attributes->domain_parameters == NULL) && - (attributes->domain_parameters_size != 0)) { - return PSA_ERROR_INVALID_ARGUMENT; + switch (operation->alg) { +#if defined(PSA_WANT_ALG_JPAKE) + case PSA_ALG_JPAKE: + status = psa_jpake_prologue(operation, step, PSA_JPAKE_OUTPUT); + if (status != PSA_SUCCESS) { + goto exit; + } + driver_step = convert_jpake_computation_stage_to_driver_step( + &operation->computation_stage.jpake); + break; +#endif /* PSA_WANT_ALG_JPAKE */ + default: + (void) step; + status = PSA_ERROR_NOT_SUPPORTED; + goto exit; } - if (key_type_is_raw_bytes(type)) { - status = psa_generate_random(key_buffer, key_buffer_size); - if (status != PSA_SUCCESS) { - return status; - } + LOCAL_OUTPUT_ALLOC(output_external, output_size, output); -#if defined(MBEDTLS_PSA_BUILTIN_KEY_TYPE_DES) - if (type == PSA_KEY_TYPE_DES) { - psa_des_set_key_parity(key_buffer, key_buffer_size); - } -#endif /* MBEDTLS_PSA_BUILTIN_KEY_TYPE_DES */ - } else + status = psa_driver_wrapper_pake_output(operation, driver_step, + output, output_size, output_length); -#if defined(MBEDTLS_PSA_BUILTIN_KEY_TYPE_RSA_KEY_PAIR) && \ - defined(MBEDTLS_GENPRIME) - if (type == PSA_KEY_TYPE_RSA_KEY_PAIR) { - return mbedtls_psa_rsa_generate_key(attributes, - key_buffer, - key_buffer_size, - key_buffer_length); - } else -#endif /* defined(MBEDTLS_PSA_BUILTIN_KEY_TYPE_RSA_KEY_PAIR) - * defined(MBEDTLS_GENPRIME) */ + if (status != PSA_SUCCESS) { + goto exit; + } -#if defined(MBEDTLS_PSA_BUILTIN_KEY_TYPE_ECC_KEY_PAIR) - if (PSA_KEY_TYPE_IS_ECC(type) && PSA_KEY_TYPE_IS_KEY_PAIR(type)) { - return mbedtls_psa_ecp_generate_key(attributes, - key_buffer, - key_buffer_size, - key_buffer_length); - } else -#endif /* defined(MBEDTLS_PSA_BUILTIN_KEY_TYPE_ECC_KEY_PAIR) */ - { - (void) key_buffer_length; - return PSA_ERROR_NOT_SUPPORTED; + switch (operation->alg) { +#if defined(PSA_WANT_ALG_JPAKE) + case PSA_ALG_JPAKE: + status = psa_jpake_epilogue(operation, PSA_JPAKE_OUTPUT); + if (status != PSA_SUCCESS) { + goto exit; + } + break; +#endif /* PSA_WANT_ALG_JPAKE */ + default: + status = PSA_ERROR_NOT_SUPPORTED; + goto exit; } - return PSA_SUCCESS; +exit: + LOCAL_OUTPUT_FREE(output_external, output); + if (status != PSA_SUCCESS) { + psa_pake_abort(operation); + } + return status; } -psa_status_t psa_generate_key(const psa_key_attributes_t *attributes, - mbedtls_svc_key_id_t *key) +psa_status_t psa_pake_input( + psa_pake_operation_t *operation, + psa_pake_step_t step, + const uint8_t *input_external, + size_t input_length) { - psa_status_t status; - psa_key_slot_t *slot = NULL; - psa_se_drv_table_entry_t *driver = NULL; - size_t key_buffer_size; - - *key = MBEDTLS_SVC_KEY_ID_INIT; - - /* Reject any attempt to create a zero-length key so that we don't - * risk tripping up later, e.g. on a malloc(0) that returns NULL. */ - if (psa_get_key_bits(attributes) == 0) { - return PSA_ERROR_INVALID_ARGUMENT; + psa_status_t status = PSA_ERROR_CORRUPTION_DETECTED; + psa_crypto_driver_pake_step_t driver_step = PSA_JPAKE_STEP_INVALID; + const size_t max_input_length = (size_t) PSA_PAKE_INPUT_SIZE(operation->alg, + operation->primitive, + step); + LOCAL_INPUT_DECLARE(input_external, input); + + if (operation->stage == PSA_PAKE_OPERATION_STAGE_COLLECT_INPUTS) { + status = psa_pake_complete_inputs(operation); + if (status != PSA_SUCCESS) { + goto exit; + } } - /* Reject any attempt to create a public key. */ - if (PSA_KEY_TYPE_IS_PUBLIC_KEY(attributes->core.type)) { - return PSA_ERROR_INVALID_ARGUMENT; + if (operation->stage != PSA_PAKE_OPERATION_STAGE_COMPUTATION) { + status = PSA_ERROR_BAD_STATE; + goto exit; } - status = psa_start_key_creation(PSA_KEY_CREATION_GENERATE, attributes, - &slot, &driver); - if (status != PSA_SUCCESS) { + if (input_length == 0 || input_length > max_input_length) { + status = PSA_ERROR_INVALID_ARGUMENT; goto exit; } - /* In the case of a transparent key or an opaque key stored in local - * storage (thus not in the case of generating a key in a secure element - * or cryptoprocessor with storage), we have to allocate a buffer to - * hold the generated key material. */ - if (slot->key.data == NULL) { - if (PSA_KEY_LIFETIME_GET_LOCATION(attributes->core.lifetime) == - PSA_KEY_LOCATION_LOCAL_STORAGE) { - status = psa_validate_key_type_and_size_for_key_generation( - attributes->core.type, attributes->core.bits); + switch (operation->alg) { +#if defined(PSA_WANT_ALG_JPAKE) + case PSA_ALG_JPAKE: + status = psa_jpake_prologue(operation, step, PSA_JPAKE_INPUT); if (status != PSA_SUCCESS) { goto exit; } + driver_step = convert_jpake_computation_stage_to_driver_step( + &operation->computation_stage.jpake); + break; +#endif /* PSA_WANT_ALG_JPAKE */ + default: + (void) step; + status = PSA_ERROR_NOT_SUPPORTED; + goto exit; + } - key_buffer_size = PSA_EXPORT_KEY_OUTPUT_SIZE( - attributes->core.type, - attributes->core.bits); - } else { - status = psa_driver_wrapper_get_key_buffer_size( - attributes, &key_buffer_size); + LOCAL_INPUT_ALLOC(input_external, input_length, input); + status = psa_driver_wrapper_pake_input(operation, driver_step, + input, input_length); + + if (status != PSA_SUCCESS) { + goto exit; + } + + switch (operation->alg) { +#if defined(PSA_WANT_ALG_JPAKE) + case PSA_ALG_JPAKE: + status = psa_jpake_epilogue(operation, PSA_JPAKE_INPUT); if (status != PSA_SUCCESS) { goto exit; } - } + break; +#endif /* PSA_WANT_ALG_JPAKE */ + default: + status = PSA_ERROR_NOT_SUPPORTED; + goto exit; + } - status = psa_allocate_buffer_to_slot(slot, key_buffer_size); - if (status != PSA_SUCCESS) { +exit: + LOCAL_INPUT_FREE(input_external, input); + if (status != PSA_SUCCESS) { + psa_pake_abort(operation); + } + return status; +} + +psa_status_t psa_pake_get_implicit_key( + psa_pake_operation_t *operation, + psa_key_derivation_operation_t *output) +{ + psa_status_t status = PSA_ERROR_CORRUPTION_DETECTED; + psa_status_t abort_status = PSA_ERROR_CORRUPTION_DETECTED; + uint8_t shared_key[MBEDTLS_PSA_JPAKE_BUFFER_SIZE]; + size_t shared_key_len = 0; + + if (operation->stage != PSA_PAKE_OPERATION_STAGE_COMPUTATION) { + status = PSA_ERROR_BAD_STATE; + goto exit; + } + +#if defined(PSA_WANT_ALG_JPAKE) + if (operation->alg == PSA_ALG_JPAKE) { + psa_jpake_computation_stage_t *computation_stage = + &operation->computation_stage.jpake; + if (computation_stage->round != PSA_JPAKE_FINISHED) { + status = PSA_ERROR_BAD_STATE; goto exit; } + } else +#endif /* PSA_WANT_ALG_JPAKE */ + { + status = PSA_ERROR_NOT_SUPPORTED; + goto exit; } - status = psa_driver_wrapper_generate_key(attributes, - slot->key.data, slot->key.bytes, &slot->key.bytes); + status = psa_driver_wrapper_pake_get_implicit_key(operation, + shared_key, + sizeof(shared_key), + &shared_key_len); if (status != PSA_SUCCESS) { - psa_remove_key_data_from_memory(slot); + goto exit; } + status = psa_key_derivation_input_bytes(output, + PSA_KEY_DERIVATION_INPUT_SECRET, + shared_key, + shared_key_len); + + mbedtls_platform_zeroize(shared_key, sizeof(shared_key)); exit: - if (status == PSA_SUCCESS) { - status = psa_finish_key_creation(slot, driver, key); + abort_status = psa_pake_abort(operation); + return status == PSA_SUCCESS ? abort_status : status; +} + +psa_status_t psa_pake_abort( + psa_pake_operation_t *operation) +{ + psa_status_t status = PSA_SUCCESS; + + if (operation->stage == PSA_PAKE_OPERATION_STAGE_COMPUTATION) { + status = psa_driver_wrapper_pake_abort(operation); } - if (status != PSA_SUCCESS) { - psa_fail_key_creation(slot, driver); + + if (operation->stage == PSA_PAKE_OPERATION_STAGE_COLLECT_INPUTS) { + if (operation->data.inputs.password != NULL) { + mbedtls_zeroize_and_free(operation->data.inputs.password, + operation->data.inputs.password_len); + } + if (operation->data.inputs.user != NULL) { + mbedtls_free(operation->data.inputs.user); + } + if (operation->data.inputs.peer != NULL) { + mbedtls_free(operation->data.inputs.peer); + } } + memset(operation, 0, sizeof(psa_pake_operation_t)); return status; } +#endif /* PSA_WANT_ALG_SOME_PAKE */ + +/* Memory copying test hooks. These are called before input copy, after input + * copy, before output copy and after output copy, respectively. + * They are used by memory-poisoning tests to temporarily unpoison buffers + * while they are copied. */ +#if defined(MBEDTLS_TEST_HOOKS) +void (*psa_input_pre_copy_hook)(const uint8_t *input, size_t input_len) = NULL; +void (*psa_input_post_copy_hook)(const uint8_t *input, size_t input_len) = NULL; +void (*psa_output_pre_copy_hook)(const uint8_t *output, size_t output_len) = NULL; +void (*psa_output_post_copy_hook)(const uint8_t *output, size_t output_len) = NULL; +#endif -/****************************************************************/ -/* Module setup */ -/****************************************************************/ - -#if !defined(MBEDTLS_PSA_CRYPTO_EXTERNAL_RNG) -psa_status_t mbedtls_psa_crypto_configure_entropy_sources( - void (* entropy_init)(mbedtls_entropy_context *ctx), - void (* entropy_free)(mbedtls_entropy_context *ctx)) +/** Copy from an input buffer to a local copy. + * + * \param[in] input Pointer to input buffer. + * \param[in] input_len Length of the input buffer. + * \param[out] input_copy Pointer to a local copy in which to store the input data. + * \param[out] input_copy_len Length of the local copy buffer. + * \return #PSA_SUCCESS, if the buffer was successfully + * copied. + * \return #PSA_ERROR_CORRUPTION_DETECTED, if the local + * copy is too small to hold contents of the + * input buffer. + */ +MBEDTLS_STATIC_TESTABLE +psa_status_t psa_crypto_copy_input(const uint8_t *input, size_t input_len, + uint8_t *input_copy, size_t input_copy_len) { - if (global_data.rng_state != RNG_NOT_INITIALIZED) { - return PSA_ERROR_BAD_STATE; + if (input_len > input_copy_len) { + return PSA_ERROR_CORRUPTION_DETECTED; } - global_data.rng.entropy_init = entropy_init; - global_data.rng.entropy_free = entropy_free; - return PSA_SUCCESS; -} -#endif /* !defined(MBEDTLS_PSA_CRYPTO_EXTERNAL_RNG) */ -void mbedtls_psa_crypto_free(void) -{ - psa_wipe_all_key_slots(); - if (global_data.rng_state != RNG_NOT_INITIALIZED) { - mbedtls_psa_random_free(&global_data.rng); +#if defined(MBEDTLS_TEST_HOOKS) + if (psa_input_pre_copy_hook != NULL) { + psa_input_pre_copy_hook(input, input_len); } - /* Wipe all remaining data, including configuration. - * In particular, this sets all state indicator to the value - * indicating "uninitialized". */ - mbedtls_platform_zeroize(&global_data, sizeof(global_data)); +#endif - /* Terminate drivers */ - psa_driver_wrapper_free(); + if (input_len > 0) { + memcpy(input_copy, input, input_len); + } + +#if defined(MBEDTLS_TEST_HOOKS) + if (psa_input_post_copy_hook != NULL) { + psa_input_post_copy_hook(input, input_len); + } +#endif + + return PSA_SUCCESS; } -#if defined(PSA_CRYPTO_STORAGE_HAS_TRANSACTIONS) -/** Recover a transaction that was interrupted by a power failure. +/** Copy from a local output buffer into a user-supplied one. * - * This function is called during initialization, before psa_crypto_init() - * returns. If this function returns a failure status, the initialization - * fails. + * \param[in] output_copy Pointer to a local buffer containing the output. + * \param[in] output_copy_len Length of the local buffer. + * \param[out] output Pointer to user-supplied output buffer. + * \param[out] output_len Length of the user-supplied output buffer. + * \return #PSA_SUCCESS, if the buffer was successfully + * copied. + * \return #PSA_ERROR_BUFFER_TOO_SMALL, if the + * user-supplied output buffer is too small to + * hold the contents of the local buffer. */ -static psa_status_t psa_crypto_recover_transaction( - const psa_crypto_transaction_t *transaction) +MBEDTLS_STATIC_TESTABLE +psa_status_t psa_crypto_copy_output(const uint8_t *output_copy, size_t output_copy_len, + uint8_t *output, size_t output_len) { - switch (transaction->unknown.type) { - case PSA_CRYPTO_TRANSACTION_CREATE_KEY: - case PSA_CRYPTO_TRANSACTION_DESTROY_KEY: - /* TODO - fall through to the failure case until this - * is implemented. - * https://github.com/ARMmbed/mbed-crypto/issues/218 - */ - default: - /* We found an unsupported transaction in the storage. - * We don't know what state the storage is in. Give up. */ - return PSA_ERROR_DATA_INVALID; + if (output_len < output_copy_len) { + return PSA_ERROR_BUFFER_TOO_SMALL; + } + +#if defined(MBEDTLS_TEST_HOOKS) + if (psa_output_pre_copy_hook != NULL) { + psa_output_pre_copy_hook(output, output_len); + } +#endif + + if (output_copy_len > 0) { + memcpy(output, output_copy, output_copy_len); + } + +#if defined(MBEDTLS_TEST_HOOKS) + if (psa_output_post_copy_hook != NULL) { + psa_output_post_copy_hook(output, output_len); } +#endif + + return PSA_SUCCESS; } -#endif /* PSA_CRYPTO_STORAGE_HAS_TRANSACTIONS */ -psa_status_t psa_crypto_init(void) +psa_status_t psa_crypto_local_input_alloc(const uint8_t *input, size_t input_len, + psa_crypto_local_input_t *local_input) { psa_status_t status; - /* Double initialization is explicitly allowed. */ - if (global_data.initialized != 0) { + *local_input = PSA_CRYPTO_LOCAL_INPUT_INIT; + + if (input_len == 0) { return PSA_SUCCESS; } - /* Initialize and seed the random generator. */ - mbedtls_psa_random_init(&global_data.rng); - global_data.rng_state = RNG_INITIALIZED; - status = mbedtls_psa_random_seed(&global_data.rng); - if (status != PSA_SUCCESS) { - goto exit; + local_input->buffer = mbedtls_calloc(input_len, 1); + if (local_input->buffer == NULL) { + /* Since we dealt with the zero-length case above, we know that + * a NULL return value means a failure of allocation. */ + return PSA_ERROR_INSUFFICIENT_MEMORY; } - global_data.rng_state = RNG_SEEDED; + /* From now on, we must free local_input->buffer on error. */ - status = psa_initialize_key_slots(); - if (status != PSA_SUCCESS) { - goto exit; - } + local_input->length = input_len; - /* Init drivers */ - status = psa_driver_wrapper_init(); + status = psa_crypto_copy_input(input, input_len, + local_input->buffer, local_input->length); if (status != PSA_SUCCESS) { - goto exit; + goto error; } -#if defined(PSA_CRYPTO_STORAGE_HAS_TRANSACTIONS) - status = psa_crypto_load_transaction(); - if (status == PSA_SUCCESS) { - status = psa_crypto_recover_transaction(&psa_crypto_transaction); - if (status != PSA_SUCCESS) { - goto exit; - } - status = psa_crypto_stop_transaction(); - } else if (status == PSA_ERROR_DOES_NOT_EXIST) { - /* There's no transaction to complete. It's all good. */ - status = PSA_SUCCESS; + return PSA_SUCCESS; + +error: + mbedtls_free(local_input->buffer); + local_input->buffer = NULL; + local_input->length = 0; + return status; +} + +void psa_crypto_local_input_free(psa_crypto_local_input_t *local_input) +{ + mbedtls_free(local_input->buffer); + local_input->buffer = NULL; + local_input->length = 0; +} + +psa_status_t psa_crypto_local_output_alloc(uint8_t *output, size_t output_len, + psa_crypto_local_output_t *local_output) +{ + *local_output = PSA_CRYPTO_LOCAL_OUTPUT_INIT; + + if (output_len == 0) { + return PSA_SUCCESS; } -#endif /* PSA_CRYPTO_STORAGE_HAS_TRANSACTIONS */ + local_output->buffer = mbedtls_calloc(output_len, 1); + if (local_output->buffer == NULL) { + /* Since we dealt with the zero-length case above, we know that + * a NULL return value means a failure of allocation. */ + return PSA_ERROR_INSUFFICIENT_MEMORY; + } + local_output->length = output_len; + local_output->original = output; + + return PSA_SUCCESS; +} - /* All done. */ - global_data.initialized = 1; +psa_status_t psa_crypto_local_output_free(psa_crypto_local_output_t *local_output) +{ + psa_status_t status; -exit: + if (local_output->buffer == NULL) { + local_output->length = 0; + return PSA_SUCCESS; + } + if (local_output->original == NULL) { + /* We have an internal copy but nothing to copy back to. */ + return PSA_ERROR_CORRUPTION_DETECTED; + } + + status = psa_crypto_copy_output(local_output->buffer, local_output->length, + local_output->original, local_output->length); if (status != PSA_SUCCESS) { - mbedtls_psa_crypto_free(); + return status; } - return status; + + mbedtls_free(local_output->buffer); + local_output->buffer = NULL; + local_output->length = 0; + + return PSA_SUCCESS; } #endif /* MBEDTLS_PSA_CRYPTO_C */ diff --git a/vendor/mbedtls/library/psa_crypto_aead.c b/vendor/mbedtls/library/psa_crypto_aead.c index 26ccc1cafc..a201985b4f 100644 --- a/vendor/mbedtls/library/psa_crypto_aead.c +++ b/vendor/mbedtls/library/psa_crypto_aead.c @@ -3,19 +3,7 @@ */ /* * Copyright The Mbed TLS Contributors - * SPDX-License-Identifier: Apache-2.0 - * - * Licensed under the Apache License, Version 2.0 (the "License"); you may - * not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT - * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. + * SPDX-License-Identifier: Apache-2.0 OR GPL-2.0-or-later */ #include "common.h" @@ -26,81 +14,42 @@ #include "psa_crypto_core.h" #include "psa_crypto_cipher.h" +#include +#include "mbedtls/platform.h" + #include "mbedtls/ccm.h" #include "mbedtls/chachapoly.h" #include "mbedtls/cipher.h" #include "mbedtls/gcm.h" - -typedef struct { - psa_algorithm_t core_alg; - uint8_t tag_length; - union { - unsigned dummy; /* Make the union non-empty even with no supported algorithms. */ -#if defined(MBEDTLS_PSA_BUILTIN_ALG_CCM) - mbedtls_ccm_context ccm; -#endif /* MBEDTLS_PSA_BUILTIN_ALG_CCM */ -#if defined(MBEDTLS_PSA_BUILTIN_ALG_GCM) - mbedtls_gcm_context gcm; -#endif /* MBEDTLS_PSA_BUILTIN_ALG_GCM */ -#if defined(MBEDTLS_PSA_BUILTIN_ALG_CHACHA20_POLY1305) - mbedtls_chachapoly_context chachapoly; -#endif /* MBEDTLS_PSA_BUILTIN_ALG_CHACHA20_POLY1305 */ - } ctx; -} aead_operation_t; - -#define AEAD_OPERATION_INIT { 0, 0, { 0 } } - -static void psa_aead_abort_internal(aead_operation_t *operation) -{ - switch (operation->core_alg) { -#if defined(MBEDTLS_PSA_BUILTIN_ALG_CCM) - case PSA_ALG_CCM: - mbedtls_ccm_free(&operation->ctx.ccm); - break; -#endif /* MBEDTLS_PSA_BUILTIN_ALG_CCM */ -#if defined(MBEDTLS_PSA_BUILTIN_ALG_GCM) - case PSA_ALG_GCM: - mbedtls_gcm_free(&operation->ctx.gcm); - break; -#endif /* MBEDTLS_PSA_BUILTIN_ALG_GCM */ -#if defined(MBEDTLS_PSA_BUILTIN_ALG_CHACHA20_POLY1305) - case PSA_ALG_CHACHA20_POLY1305: - mbedtls_chachapoly_free(&operation->ctx.chachapoly); - break; -#endif /* MBEDTLS_PSA_BUILTIN_ALG_CHACHA20_POLY1305 */ - } -} +#include "mbedtls/error.h" static psa_status_t psa_aead_setup( - aead_operation_t *operation, + mbedtls_psa_aead_operation_t *operation, const psa_key_attributes_t *attributes, const uint8_t *key_buffer, + size_t key_buffer_size, psa_algorithm_t alg) { psa_status_t status = PSA_ERROR_CORRUPTION_DETECTED; - size_t key_bits; - const mbedtls_cipher_info_t *cipher_info; mbedtls_cipher_id_t cipher_id; - size_t full_tag_length = 0; - - key_bits = attributes->core.bits; + mbedtls_cipher_mode_t mode; + size_t key_bits = attributes->bits; + (void) key_buffer_size; - cipher_info = mbedtls_cipher_info_from_psa(alg, - attributes->core.type, key_bits, - &cipher_id); - if (cipher_info == NULL) { - return PSA_ERROR_NOT_SUPPORTED; + status = mbedtls_cipher_values_from_psa(alg, attributes->type, + &key_bits, &mode, &cipher_id); + if (status != PSA_SUCCESS) { + return status; } switch (PSA_ALG_AEAD_WITH_SHORTENED_TAG(alg, 0)) { #if defined(MBEDTLS_PSA_BUILTIN_ALG_CCM) case PSA_ALG_AEAD_WITH_SHORTENED_TAG(PSA_ALG_CCM, 0): - operation->core_alg = PSA_ALG_CCM; - full_tag_length = 16; + operation->alg = PSA_ALG_CCM; /* CCM allows the following tag lengths: 4, 6, 8, 10, 12, 14, 16. * The call to mbedtls_ccm_encrypt_and_tag or * mbedtls_ccm_auth_decrypt will validate the tag length. */ - if (PSA_BLOCK_CIPHER_BLOCK_LENGTH(attributes->core.type) != 16) { + if (PSA_BLOCK_CIPHER_BLOCK_LENGTH(attributes->type) != 16) { return PSA_ERROR_INVALID_ARGUMENT; } @@ -116,12 +65,11 @@ static psa_status_t psa_aead_setup( #if defined(MBEDTLS_PSA_BUILTIN_ALG_GCM) case PSA_ALG_AEAD_WITH_SHORTENED_TAG(PSA_ALG_GCM, 0): - operation->core_alg = PSA_ALG_GCM; - full_tag_length = 16; + operation->alg = PSA_ALG_GCM; /* GCM allows the following tag lengths: 4, 8, 12, 13, 14, 15, 16. * The call to mbedtls_gcm_crypt_and_tag or * mbedtls_gcm_auth_decrypt will validate the tag length. */ - if (PSA_BLOCK_CIPHER_BLOCK_LENGTH(attributes->core.type) != 16) { + if (PSA_BLOCK_CIPHER_BLOCK_LENGTH(attributes->type) != 16) { return PSA_ERROR_INVALID_ARGUMENT; } @@ -137,8 +85,7 @@ static psa_status_t psa_aead_setup( #if defined(MBEDTLS_PSA_BUILTIN_ALG_CHACHA20_POLY1305) case PSA_ALG_AEAD_WITH_SHORTENED_TAG(PSA_ALG_CHACHA20_POLY1305, 0): - operation->core_alg = PSA_ALG_CHACHA20_POLY1305; - full_tag_length = 16; + operation->alg = PSA_ALG_CHACHA20_POLY1305; /* We only support the default tag length. */ if (alg != PSA_ALG_CHACHA20_POLY1305) { return PSA_ERROR_NOT_SUPPORTED; @@ -160,15 +107,9 @@ static psa_status_t psa_aead_setup( return PSA_ERROR_NOT_SUPPORTED; } - if (PSA_AEAD_TAG_LENGTH(attributes->core.type, - key_bits, alg) - > full_tag_length) { - return PSA_ERROR_INVALID_ARGUMENT; - } + operation->key_type = psa_get_key_type(attributes); - operation->tag_length = PSA_AEAD_TAG_LENGTH(attributes->core.type, - key_bits, - alg); + operation->tag_length = PSA_ALG_AEAD_GET_TAG_LENGTH(alg); return PSA_SUCCESS; } @@ -183,11 +124,12 @@ psa_status_t mbedtls_psa_aead_encrypt( uint8_t *ciphertext, size_t ciphertext_size, size_t *ciphertext_length) { psa_status_t status = PSA_ERROR_CORRUPTION_DETECTED; - aead_operation_t operation = AEAD_OPERATION_INIT; + mbedtls_psa_aead_operation_t operation = MBEDTLS_PSA_AEAD_OPERATION_INIT; uint8_t *tag; - (void) key_buffer_size; - status = psa_aead_setup(&operation, attributes, key_buffer, alg); + status = psa_aead_setup(&operation, attributes, key_buffer, + key_buffer_size, alg); + if (status != PSA_SUCCESS) { goto exit; } @@ -201,7 +143,7 @@ psa_status_t mbedtls_psa_aead_encrypt( tag = ciphertext + plaintext_length; #if defined(MBEDTLS_PSA_BUILTIN_ALG_CCM) - if (operation.core_alg == PSA_ALG_CCM) { + if (operation.alg == PSA_ALG_CCM) { status = mbedtls_to_psa_error( mbedtls_ccm_encrypt_and_tag(&operation.ctx.ccm, plaintext_length, @@ -213,7 +155,7 @@ psa_status_t mbedtls_psa_aead_encrypt( } else #endif /* MBEDTLS_PSA_BUILTIN_ALG_CCM */ #if defined(MBEDTLS_PSA_BUILTIN_ALG_GCM) - if (operation.core_alg == PSA_ALG_GCM) { + if (operation.alg == PSA_ALG_GCM) { status = mbedtls_to_psa_error( mbedtls_gcm_crypt_and_tag(&operation.ctx.gcm, MBEDTLS_GCM_ENCRYPT, @@ -225,16 +167,7 @@ psa_status_t mbedtls_psa_aead_encrypt( } else #endif /* MBEDTLS_PSA_BUILTIN_ALG_GCM */ #if defined(MBEDTLS_PSA_BUILTIN_ALG_CHACHA20_POLY1305) - if (operation.core_alg == PSA_ALG_CHACHA20_POLY1305) { - if (nonce_length != 12) { - if (nonce_length == 8) { - status = PSA_ERROR_NOT_SUPPORTED; - } else { - status = PSA_ERROR_INVALID_ARGUMENT; - } - goto exit; - } - + if (operation.alg == PSA_ALG_CHACHA20_POLY1305) { if (operation.tag_length != 16) { status = PSA_ERROR_NOT_SUPPORTED; goto exit; @@ -265,7 +198,7 @@ psa_status_t mbedtls_psa_aead_encrypt( } exit: - psa_aead_abort_internal(&operation); + mbedtls_psa_aead_abort(&operation); return status; } @@ -303,11 +236,12 @@ psa_status_t mbedtls_psa_aead_decrypt( uint8_t *plaintext, size_t plaintext_size, size_t *plaintext_length) { psa_status_t status = PSA_ERROR_CORRUPTION_DETECTED; - aead_operation_t operation = AEAD_OPERATION_INIT; + mbedtls_psa_aead_operation_t operation = MBEDTLS_PSA_AEAD_OPERATION_INIT; const uint8_t *tag = NULL; - (void) key_buffer_size; - status = psa_aead_setup(&operation, attributes, key_buffer, alg); + status = psa_aead_setup(&operation, attributes, key_buffer, + key_buffer_size, alg); + if (status != PSA_SUCCESS) { goto exit; } @@ -320,7 +254,7 @@ psa_status_t mbedtls_psa_aead_decrypt( } #if defined(MBEDTLS_PSA_BUILTIN_ALG_CCM) - if (operation.core_alg == PSA_ALG_CCM) { + if (operation.alg == PSA_ALG_CCM) { status = mbedtls_to_psa_error( mbedtls_ccm_auth_decrypt(&operation.ctx.ccm, ciphertext_length - operation.tag_length, @@ -332,7 +266,7 @@ psa_status_t mbedtls_psa_aead_decrypt( } else #endif /* MBEDTLS_PSA_BUILTIN_ALG_CCM */ #if defined(MBEDTLS_PSA_BUILTIN_ALG_GCM) - if (operation.core_alg == PSA_ALG_GCM) { + if (operation.alg == PSA_ALG_GCM) { status = mbedtls_to_psa_error( mbedtls_gcm_auth_decrypt(&operation.ctx.gcm, ciphertext_length - operation.tag_length, @@ -344,16 +278,7 @@ psa_status_t mbedtls_psa_aead_decrypt( } else #endif /* MBEDTLS_PSA_BUILTIN_ALG_GCM */ #if defined(MBEDTLS_PSA_BUILTIN_ALG_CHACHA20_POLY1305) - if (operation.core_alg == PSA_ALG_CHACHA20_POLY1305) { - if (nonce_length != 12) { - if (nonce_length == 8) { - status = PSA_ERROR_NOT_SUPPORTED; - } else { - status = PSA_ERROR_INVALID_ARGUMENT; - } - goto exit; - } - + if (operation.alg == PSA_ALG_CHACHA20_POLY1305) { if (operation.tag_length != 16) { status = PSA_ERROR_NOT_SUPPORTED; goto exit; @@ -383,7 +308,7 @@ psa_status_t mbedtls_psa_aead_decrypt( } exit: - psa_aead_abort_internal(&operation); + mbedtls_psa_aead_abort(&operation); if (status == PSA_SUCCESS) { *plaintext_length = ciphertext_length - operation.tag_length; @@ -391,4 +316,334 @@ psa_status_t mbedtls_psa_aead_decrypt( return status; } +/* Set the key and algorithm for a multipart authenticated encryption + * operation. */ +psa_status_t mbedtls_psa_aead_encrypt_setup( + mbedtls_psa_aead_operation_t *operation, + const psa_key_attributes_t *attributes, + const uint8_t *key_buffer, + size_t key_buffer_size, + psa_algorithm_t alg) +{ + psa_status_t status = PSA_ERROR_CORRUPTION_DETECTED; + + status = psa_aead_setup(operation, attributes, key_buffer, + key_buffer_size, alg); + + if (status == PSA_SUCCESS) { + operation->is_encrypt = 1; + } + + return status; +} + +/* Set the key and algorithm for a multipart authenticated decryption + * operation. */ +psa_status_t mbedtls_psa_aead_decrypt_setup( + mbedtls_psa_aead_operation_t *operation, + const psa_key_attributes_t *attributes, + const uint8_t *key_buffer, + size_t key_buffer_size, + psa_algorithm_t alg) +{ + psa_status_t status = PSA_ERROR_CORRUPTION_DETECTED; + + status = psa_aead_setup(operation, attributes, key_buffer, + key_buffer_size, alg); + + if (status == PSA_SUCCESS) { + operation->is_encrypt = 0; + } + + return status; +} + +/* Set a nonce for the multipart AEAD operation*/ +psa_status_t mbedtls_psa_aead_set_nonce( + mbedtls_psa_aead_operation_t *operation, + const uint8_t *nonce, + size_t nonce_length) +{ + psa_status_t status = PSA_ERROR_CORRUPTION_DETECTED; + +#if defined(MBEDTLS_PSA_BUILTIN_ALG_GCM) + if (operation->alg == PSA_ALG_GCM) { + status = mbedtls_to_psa_error( + mbedtls_gcm_starts(&operation->ctx.gcm, + operation->is_encrypt ? + MBEDTLS_GCM_ENCRYPT : MBEDTLS_GCM_DECRYPT, + nonce, + nonce_length)); + } else +#endif /* MBEDTLS_PSA_BUILTIN_ALG_GCM */ +#if defined(MBEDTLS_PSA_BUILTIN_ALG_CCM) + if (operation->alg == PSA_ALG_CCM) { + status = mbedtls_to_psa_error( + mbedtls_ccm_starts(&operation->ctx.ccm, + operation->is_encrypt ? + MBEDTLS_CCM_ENCRYPT : MBEDTLS_CCM_DECRYPT, + nonce, + nonce_length)); + } else +#endif /* MBEDTLS_PSA_BUILTIN_ALG_CCM */ +#if defined(MBEDTLS_PSA_BUILTIN_ALG_CHACHA20_POLY1305) + if (operation->alg == PSA_ALG_CHACHA20_POLY1305) { + /* Note - ChaChaPoly allows an 8 byte nonce, but we would have to + * allocate a buffer in the operation, copy the nonce to it and pad + * it, so for now check the nonce is 12 bytes, as + * mbedtls_chachapoly_starts() assumes it can read 12 bytes from the + * passed in buffer. */ + if (nonce_length != 12) { + return PSA_ERROR_INVALID_ARGUMENT; + } + + status = mbedtls_to_psa_error( + mbedtls_chachapoly_starts(&operation->ctx.chachapoly, + nonce, + operation->is_encrypt ? + MBEDTLS_CHACHAPOLY_ENCRYPT : + MBEDTLS_CHACHAPOLY_DECRYPT)); + } else +#endif /* MBEDTLS_PSA_BUILTIN_ALG_CHACHA20_POLY1305 */ + { + (void) operation; + (void) nonce; + (void) nonce_length; + + return PSA_ERROR_NOT_SUPPORTED; + } + + return status; +} + +/* Declare the lengths of the message and additional data for AEAD. */ +psa_status_t mbedtls_psa_aead_set_lengths( + mbedtls_psa_aead_operation_t *operation, + size_t ad_length, + size_t plaintext_length) +{ +#if defined(MBEDTLS_PSA_BUILTIN_ALG_CCM) + if (operation->alg == PSA_ALG_CCM) { + return mbedtls_to_psa_error( + mbedtls_ccm_set_lengths(&operation->ctx.ccm, + ad_length, + plaintext_length, + operation->tag_length)); + + } +#else /* MBEDTLS_PSA_BUILTIN_ALG_CCM */ + (void) operation; + (void) ad_length; + (void) plaintext_length; +#endif /* MBEDTLS_PSA_BUILTIN_ALG_CCM */ + + return PSA_SUCCESS; +} + +/* Pass additional data to an active multipart AEAD operation. */ +psa_status_t mbedtls_psa_aead_update_ad( + mbedtls_psa_aead_operation_t *operation, + const uint8_t *input, + size_t input_length) +{ + psa_status_t status = PSA_ERROR_CORRUPTION_DETECTED; + +#if defined(MBEDTLS_PSA_BUILTIN_ALG_GCM) + if (operation->alg == PSA_ALG_GCM) { + status = mbedtls_to_psa_error( + mbedtls_gcm_update_ad(&operation->ctx.gcm, input, input_length)); + } else +#endif /* MBEDTLS_PSA_BUILTIN_ALG_GCM */ +#if defined(MBEDTLS_PSA_BUILTIN_ALG_CCM) + if (operation->alg == PSA_ALG_CCM) { + status = mbedtls_to_psa_error( + mbedtls_ccm_update_ad(&operation->ctx.ccm, input, input_length)); + } else +#endif /* MBEDTLS_PSA_BUILTIN_ALG_CCM */ +#if defined(MBEDTLS_PSA_BUILTIN_ALG_CHACHA20_POLY1305) + if (operation->alg == PSA_ALG_CHACHA20_POLY1305) { + status = mbedtls_to_psa_error( + mbedtls_chachapoly_update_aad(&operation->ctx.chachapoly, + input, + input_length)); + } else +#endif /* MBEDTLS_PSA_BUILTIN_ALG_CHACHA20_POLY1305 */ + { + (void) operation; + (void) input; + (void) input_length; + + return PSA_ERROR_NOT_SUPPORTED; + } + + return status; +} + +/* Encrypt or decrypt a message fragment in an active multipart AEAD + * operation.*/ +psa_status_t mbedtls_psa_aead_update( + mbedtls_psa_aead_operation_t *operation, + const uint8_t *input, + size_t input_length, + uint8_t *output, + size_t output_size, + size_t *output_length) +{ + size_t update_output_length; + psa_status_t status = PSA_ERROR_CORRUPTION_DETECTED; + + update_output_length = input_length; + +#if defined(MBEDTLS_PSA_BUILTIN_ALG_GCM) + if (operation->alg == PSA_ALG_GCM) { + status = mbedtls_to_psa_error( + mbedtls_gcm_update(&operation->ctx.gcm, + input, input_length, + output, output_size, + &update_output_length)); + } else +#endif /* MBEDTLS_PSA_BUILTIN_ALG_GCM */ +#if defined(MBEDTLS_PSA_BUILTIN_ALG_CCM) + if (operation->alg == PSA_ALG_CCM) { + if (output_size < input_length) { + return PSA_ERROR_BUFFER_TOO_SMALL; + } + + status = mbedtls_to_psa_error( + mbedtls_ccm_update(&operation->ctx.ccm, + input, input_length, + output, output_size, + &update_output_length)); + } else +#endif /* MBEDTLS_PSA_BUILTIN_ALG_CCM */ +#if defined(MBEDTLS_PSA_BUILTIN_ALG_CHACHA20_POLY1305) + if (operation->alg == PSA_ALG_CHACHA20_POLY1305) { + if (output_size < input_length) { + return PSA_ERROR_BUFFER_TOO_SMALL; + } + + status = mbedtls_to_psa_error( + mbedtls_chachapoly_update(&operation->ctx.chachapoly, + input_length, + input, + output)); + } else +#endif /* MBEDTLS_PSA_BUILTIN_ALG_CHACHA20_POLY1305 */ + { + (void) operation; + (void) input; + (void) output; + (void) output_size; + + return PSA_ERROR_NOT_SUPPORTED; + } + + if (status == PSA_SUCCESS) { + *output_length = update_output_length; + } + + return status; +} + +/* Finish encrypting a message in a multipart AEAD operation. */ +psa_status_t mbedtls_psa_aead_finish( + mbedtls_psa_aead_operation_t *operation, + uint8_t *ciphertext, + size_t ciphertext_size, + size_t *ciphertext_length, + uint8_t *tag, + size_t tag_size, + size_t *tag_length) +{ + psa_status_t status = PSA_ERROR_CORRUPTION_DETECTED; + size_t finish_output_size = 0; + + if (tag_size < operation->tag_length) { + return PSA_ERROR_BUFFER_TOO_SMALL; + } + +#if defined(MBEDTLS_PSA_BUILTIN_ALG_GCM) + if (operation->alg == PSA_ALG_GCM) { + status = mbedtls_to_psa_error( + mbedtls_gcm_finish(&operation->ctx.gcm, + ciphertext, ciphertext_size, ciphertext_length, + tag, operation->tag_length)); + } else +#endif /* MBEDTLS_PSA_BUILTIN_ALG_GCM */ +#if defined(MBEDTLS_PSA_BUILTIN_ALG_CCM) + if (operation->alg == PSA_ALG_CCM) { + /* tag must be big enough to store a tag of size passed into set + * lengths. */ + if (tag_size < operation->tag_length) { + return PSA_ERROR_BUFFER_TOO_SMALL; + } + + status = mbedtls_to_psa_error( + mbedtls_ccm_finish(&operation->ctx.ccm, + tag, operation->tag_length)); + } else +#endif /* MBEDTLS_PSA_BUILTIN_ALG_CCM */ +#if defined(MBEDTLS_PSA_BUILTIN_ALG_CHACHA20_POLY1305) + if (operation->alg == PSA_ALG_CHACHA20_POLY1305) { + /* Belt and braces. Although the above tag_size check should have + * already done this, if we later start supporting smaller tag sizes + * for chachapoly, then passing a tag buffer smaller than 16 into here + * could cause a buffer overflow, so better safe than sorry. */ + if (tag_size < 16) { + return PSA_ERROR_BUFFER_TOO_SMALL; + } + + status = mbedtls_to_psa_error( + mbedtls_chachapoly_finish(&operation->ctx.chachapoly, + tag)); + } else +#endif /* MBEDTLS_PSA_BUILTIN_ALG_CHACHA20_POLY1305 */ + { + (void) ciphertext; + (void) ciphertext_size; + (void) ciphertext_length; + (void) tag; + (void) tag_size; + (void) tag_length; + + return PSA_ERROR_NOT_SUPPORTED; + } + + if (status == PSA_SUCCESS) { + /* This will be zero for all supported algorithms currently, but left + * here for future support. */ + *ciphertext_length = finish_output_size; + *tag_length = operation->tag_length; + } + + return status; +} + +/* Abort an AEAD operation */ +psa_status_t mbedtls_psa_aead_abort( + mbedtls_psa_aead_operation_t *operation) +{ + switch (operation->alg) { +#if defined(MBEDTLS_PSA_BUILTIN_ALG_CCM) + case PSA_ALG_CCM: + mbedtls_ccm_free(&operation->ctx.ccm); + break; +#endif /* MBEDTLS_PSA_BUILTIN_ALG_CCM */ +#if defined(MBEDTLS_PSA_BUILTIN_ALG_GCM) + case PSA_ALG_GCM: + mbedtls_gcm_free(&operation->ctx.gcm); + break; +#endif /* MBEDTLS_PSA_BUILTIN_ALG_GCM */ +#if defined(MBEDTLS_PSA_BUILTIN_ALG_CHACHA20_POLY1305) + case PSA_ALG_CHACHA20_POLY1305: + mbedtls_chachapoly_free(&operation->ctx.chachapoly); + break; +#endif /* MBEDTLS_PSA_BUILTIN_ALG_CHACHA20_POLY1305 */ + } + + operation->is_encrypt = 0; + + return PSA_SUCCESS; +} + #endif /* MBEDTLS_PSA_CRYPTO_C */ diff --git a/vendor/mbedtls/library/psa_crypto_aead.h b/vendor/mbedtls/library/psa_crypto_aead.h index 8586c7bfad..a3392199f6 100644 --- a/vendor/mbedtls/library/psa_crypto_aead.h +++ b/vendor/mbedtls/library/psa_crypto_aead.h @@ -3,19 +3,7 @@ */ /* * Copyright The Mbed TLS Contributors - * SPDX-License-Identifier: Apache-2.0 - * - * Licensed under the Apache License, Version 2.0 (the "License"); you may - * not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT - * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. + * SPDX-License-Identifier: Apache-2.0 OR GPL-2.0-or-later */ #ifndef PSA_CRYPTO_AEAD_H @@ -148,4 +136,364 @@ psa_status_t mbedtls_psa_aead_decrypt( const uint8_t *ciphertext, size_t ciphertext_length, uint8_t *plaintext, size_t plaintext_size, size_t *plaintext_length); +/** Set the key for a multipart authenticated encryption operation. + * + * \note The signature of this function is that of a PSA driver + * aead_encrypt_setup entry point. This function behaves as an + * aead_encrypt_setup entry point as defined in the PSA driver interface + * specification for transparent drivers. + * + * If an error occurs at any step after a call to + * mbedtls_psa_aead_encrypt_setup(), the operation is reset by the PSA core by a + * call to mbedtls_psa_aead_abort(). The PSA core may call + * mbedtls_psa_aead_abort() at any time after the operation has been + * initialized, and is required to when the operation is no longer needed. + * + * \param[in,out] operation The operation object to set up. It must have + * been initialized as per the documentation for + * #mbedtls_psa_aead_operation_t and not yet in + * use. + * \param[in] attributes The attributes of the key to use for the + * operation. + * \param[in] key_buffer The buffer containing the key context. + * \param key_buffer_size Size of the \p key_buffer buffer in bytes. + It must be consistent with the size in bits + recorded in \p attributes. + * \param alg The AEAD algorithm to compute + * (\c PSA_ALG_XXX value such that + * #PSA_ALG_IS_AEAD(\p alg) is true). + * + * \retval #PSA_SUCCESS + * Success. + * \retval #PSA_ERROR_INVALID_ARGUMENT + * An invalid block length was supplied. + * \retval #PSA_ERROR_NOT_SUPPORTED + * \p alg is not supported. + * \retval #PSA_ERROR_INSUFFICIENT_MEMORY + * Failed to allocate memory for key material + */ +psa_status_t mbedtls_psa_aead_encrypt_setup( + mbedtls_psa_aead_operation_t *operation, + const psa_key_attributes_t *attributes, + const uint8_t *key_buffer, + size_t key_buffer_size, + psa_algorithm_t alg); + +/** Set the key for a multipart authenticated decryption operation. + * + * \note The signature of this function is that of a PSA driver + * aead_decrypt_setup entry point. This function behaves as an + * aead_decrypt_setup entry point as defined in the PSA driver interface + * specification for transparent drivers. + * + * If an error occurs at any step after a call to + * mbedtls_psa_aead_decrypt_setup(), the PSA core resets the operation by a + * call to mbedtls_psa_aead_abort(). The PSA core may call + * mbedtls_psa_aead_abort() at any time after the operation has been + * initialized, and is required to when the operation is no longer needed. + * + * \param[in,out] operation The operation object to set up. It must have + * been initialized as per the documentation for + * #mbedtls_psa_aead_operation_t and not yet in + * use. + * \param[in] attributes The attributes of the key to use for the + * operation. + * \param[in] key_buffer The buffer containing the key context. + * \param key_buffer_size Size of the \p key_buffer buffer in bytes. + It must be consistent with the size in bits + recorded in \p attributes. + * \param alg The AEAD algorithm to compute + * (\c PSA_ALG_XXX value such that + * #PSA_ALG_IS_AEAD(\p alg) is true). + * + * \retval #PSA_SUCCESS + * Success. + * \retval #PSA_ERROR_INVALID_ARGUMENT + * An invalid block length was supplied. + * \retval #PSA_ERROR_NOT_SUPPORTED + * \p alg is not supported. + * \retval #PSA_ERROR_INSUFFICIENT_MEMORY + * Failed to allocate memory for key material + */ +psa_status_t mbedtls_psa_aead_decrypt_setup( + mbedtls_psa_aead_operation_t *operation, + const psa_key_attributes_t *attributes, + const uint8_t *key_buffer, + size_t key_buffer_size, + psa_algorithm_t alg); + +/** Set the nonce for an authenticated encryption or decryption operation. + * + * \note The signature of this function is that of a PSA driver aead_set_nonce + * entry point. This function behaves as an aead_set_nonce entry point as + * defined in the PSA driver interface specification for transparent + * drivers. + * + * This function sets the nonce for the authenticated + * encryption or decryption operation. + * + * The PSA core calls mbedtls_psa_aead_encrypt_setup() or + * mbedtls_psa_aead_decrypt_setup() before calling this function. + * + * If this function returns an error status, the PSA core will call + * mbedtls_psa_aead_abort(). + * + * \param[in,out] operation Active AEAD operation. + * \param[in] nonce Buffer containing the nonce to use. + * \param nonce_length Size of the nonce in bytes. + * + * \retval #PSA_SUCCESS + * Success. + * \retval #PSA_ERROR_INVALID_ARGUMENT + * The size of \p nonce is not acceptable for the chosen algorithm. + * \retval #PSA_ERROR_NOT_SUPPORTED + * Algorithm previously set is not supported in this configuration of + * the library. + */ +psa_status_t mbedtls_psa_aead_set_nonce( + mbedtls_psa_aead_operation_t *operation, + const uint8_t *nonce, + size_t nonce_length); + +/** Declare the lengths of the message and additional data for AEAD. + * + * \note The signature of this function is that of a PSA driver aead_set_lengths + * entry point. This function behaves as an aead_set_lengths entry point + * as defined in the PSA driver interface specification for transparent + * drivers. + * + * The PSA core calls this function before calling mbedtls_psa_aead_update_ad() + * or mbedtls_psa_aead_update() if the algorithm for the operation requires it. + * If the algorithm does not require it, calling this function is optional, but + * if this function is called then the implementation must enforce the lengths. + * + * The PSA core may call this function before or after setting the nonce with + * mbedtls_psa_aead_set_nonce(). + * + * - For #PSA_ALG_CCM, calling this function is required. + * - For the other AEAD algorithms defined in this specification, calling + * this function is not required. + * + * If this function returns an error status, the PSA core calls + * mbedtls_psa_aead_abort(). + * + * \param[in,out] operation Active AEAD operation. + * \param ad_length Size of the non-encrypted additional + * authenticated data in bytes. + * \param plaintext_length Size of the plaintext to encrypt in bytes. + * + * \retval #PSA_SUCCESS + * Success. + * \retval #PSA_ERROR_INVALID_ARGUMENT + * At least one of the lengths is not acceptable for the chosen + * algorithm. + * \retval #PSA_ERROR_NOT_SUPPORTED + * Algorithm previously set is not supported in this configuration of + * the library. + */ +psa_status_t mbedtls_psa_aead_set_lengths( + mbedtls_psa_aead_operation_t *operation, + size_t ad_length, + size_t plaintext_length); + +/** Pass additional data to an active AEAD operation. + * + * \note The signature of this function is that of a PSA driver + * aead_update_ad entry point. This function behaves as an aead_update_ad + * entry point as defined in the PSA driver interface specification for + * transparent drivers. + * + * Additional data is authenticated, but not encrypted. + * + * The PSA core can call this function multiple times to pass successive + * fragments of the additional data. It will not call this function after + * passing data to encrypt or decrypt with mbedtls_psa_aead_update(). + * + * Before calling this function, the PSA core will: + * 1. Call either mbedtls_psa_aead_encrypt_setup() or + * mbedtls_psa_aead_decrypt_setup(). + * 2. Set the nonce with mbedtls_psa_aead_set_nonce(). + * + * If this function returns an error status, the PSA core will call + * mbedtls_psa_aead_abort(). + * + * \param[in,out] operation Active AEAD operation. + * \param[in] input Buffer containing the fragment of + * additional data. + * \param input_length Size of the \p input buffer in bytes. + * + * \retval #PSA_SUCCESS + * Success. + * \retval #PSA_ERROR_NOT_SUPPORTED + * Algorithm previously set is not supported in this configuration of + * the library. + */ +psa_status_t mbedtls_psa_aead_update_ad( + mbedtls_psa_aead_operation_t *operation, + const uint8_t *input, + size_t input_length); + +/** Encrypt or decrypt a message fragment in an active AEAD operation. + * + * \note The signature of this function is that of a PSA driver + * aead_update entry point. This function behaves as an aead_update entry + * point as defined in the PSA driver interface specification for + * transparent drivers. + * + * Before calling this function, the PSA core will: + * 1. Call either mbedtls_psa_aead_encrypt_setup() or + * mbedtls_psa_aead_decrypt_setup(). The choice of setup function + * determines whether this function encrypts or decrypts its input. + * 2. Set the nonce with mbedtls_psa_aead_set_nonce(). + * 3. Call mbedtls_psa_aead_update_ad() to pass all the additional data. + * + * If this function returns an error status, the PSA core will call + * mbedtls_psa_aead_abort(). + * + * This function does not require the input to be aligned to any + * particular block boundary. If the implementation can only process + * a whole block at a time, it must consume all the input provided, but + * it may delay the end of the corresponding output until a subsequent + * call to mbedtls_psa_aead_update(), mbedtls_psa_aead_finish() provides + * sufficient input. The amount of data that can be delayed in this way is + * bounded by #PSA_AEAD_UPDATE_OUTPUT_SIZE. + * + * \param[in,out] operation Active AEAD operation. + * \param[in] input Buffer containing the message fragment to + * encrypt or decrypt. + * \param input_length Size of the \p input buffer in bytes. + * \param[out] output Buffer where the output is to be written. + * \param output_size Size of the \p output buffer in bytes. + * This must be appropriate for the selected + * algorithm and key: + * - A sufficient output size is + * #PSA_AEAD_UPDATE_OUTPUT_SIZE(\c key_type, + * \c alg, \p input_length) where + * \c key_type is the type of key and \c alg is + * the algorithm that were used to set up the + * operation. + * - #PSA_AEAD_UPDATE_OUTPUT_MAX_SIZE(\p + * input_length) evaluates to the maximum + * output size of any supported AEAD + * algorithm. + * \param[out] output_length On success, the number of bytes + * that make up the returned output. + * + * \retval #PSA_SUCCESS + * Success. + * + * \retval #PSA_ERROR_BUFFER_TOO_SMALL + * The size of the \p output buffer is too small. + * #PSA_AEAD_UPDATE_OUTPUT_SIZE(\c key_type, \c alg, \p input_length) or + * #PSA_AEAD_UPDATE_OUTPUT_MAX_SIZE(\p input_length) can be used to + * determine the required buffer size. + */ +psa_status_t mbedtls_psa_aead_update( + mbedtls_psa_aead_operation_t *operation, + const uint8_t *input, + size_t input_length, + uint8_t *output, + size_t output_size, + size_t *output_length); + +/** Finish encrypting a message in an AEAD operation. + * + * \note The signature of this function is that of a PSA driver + * aead_finish entry point. This function behaves as an aead_finish entry + * point as defined in the PSA driver interface specification for + * transparent drivers. + * + * The operation must have been set up by the PSA core with + * mbedtls_psa_aead_encrypt_setup(). + * + * This function finishes the authentication of the additional data + * formed by concatenating the inputs passed to preceding calls to + * mbedtls_psa_aead_update_ad() with the plaintext formed by concatenating the + * inputs passed to preceding calls to mbedtls_psa_aead_update(). + * + * This function has two output buffers: + * - \p ciphertext contains trailing ciphertext that was buffered from + * preceding calls to mbedtls_psa_aead_update(). + * - \p tag contains the authentication tag. + * + * Whether or not this function returns successfully, the PSA core subsequently + * calls mbedtls_psa_aead_abort() to deactivate the operation. + * + * \param[in,out] operation Active AEAD operation. + * \param[out] ciphertext Buffer where the last part of the ciphertext + * is to be written. + * \param ciphertext_size Size of the \p ciphertext buffer in bytes. + * This must be appropriate for the selected + * algorithm and key: + * - A sufficient output size is + * #PSA_AEAD_FINISH_OUTPUT_SIZE(\c key_type, + * \c alg) where \c key_type is the type of key + * and \c alg is the algorithm that were used to + * set up the operation. + * - #PSA_AEAD_FINISH_OUTPUT_MAX_SIZE evaluates to + * the maximum output size of any supported AEAD + * algorithm. + * \param[out] ciphertext_length On success, the number of bytes of + * returned ciphertext. + * \param[out] tag Buffer where the authentication tag is + * to be written. + * \param tag_size Size of the \p tag buffer in bytes. + * This must be appropriate for the selected + * algorithm and key: + * - The exact tag size is #PSA_AEAD_TAG_LENGTH(\c + * key_type, \c key_bits, \c alg) where + * \c key_type and \c key_bits are the type and + * bit-size of the key, and \c alg are the + * algorithm that were used in the call to + * mbedtls_psa_aead_encrypt_setup(). + * - #PSA_AEAD_TAG_MAX_SIZE evaluates to the + * maximum tag size of any supported AEAD + * algorithm. + * \param[out] tag_length On success, the number of bytes + * that make up the returned tag. + * + * \retval #PSA_SUCCESS + * Success. + * \retval #PSA_ERROR_BUFFER_TOO_SMALL + * The size of the \p tag buffer is too small. + * #PSA_AEAD_TAG_LENGTH(\c key_type, key_bits, \c alg) or + * #PSA_AEAD_TAG_MAX_SIZE can be used to determine the required \p tag + * buffer size. + */ +psa_status_t mbedtls_psa_aead_finish( + mbedtls_psa_aead_operation_t *operation, + uint8_t *ciphertext, + size_t ciphertext_size, + size_t *ciphertext_length, + uint8_t *tag, + size_t tag_size, + size_t *tag_length); + +/** Abort an AEAD operation. + * + * \note The signature of this function is that of a PSA driver + * aead_abort entry point. This function behaves as an aead_abort entry + * point as defined in the PSA driver interface specification for + * transparent drivers. + * + * Aborting an operation frees all associated resources except for the + * \p operation structure itself. Once aborted, the operation object + * can be reused for another operation by the PSA core by it calling + * mbedtls_psa_aead_encrypt_setup() or mbedtls_psa_aead_decrypt_setup() again. + * + * The PSA core may call this function any time after the operation object has + * been initialized as described in #mbedtls_psa_aead_operation_t. + * + * In particular, calling mbedtls_psa_aead_abort() after the operation has been + * terminated by a call to mbedtls_psa_aead_abort() or + * mbedtls_psa_aead_finish() is safe and has no effect. + * + * \param[in,out] operation Initialized AEAD operation. + * + * \retval #PSA_SUCCESS + * Success. + */ +psa_status_t mbedtls_psa_aead_abort( + mbedtls_psa_aead_operation_t *operation); + #endif /* PSA_CRYPTO_AEAD_H */ diff --git a/vendor/mbedtls/library/psa_crypto_cipher.c b/vendor/mbedtls/library/psa_crypto_cipher.c index d216339e65..881d673cc0 100644 --- a/vendor/mbedtls/library/psa_crypto_cipher.c +++ b/vendor/mbedtls/library/psa_crypto_cipher.c @@ -3,19 +3,7 @@ */ /* * Copyright The Mbed TLS Contributors - * SPDX-License-Identifier: Apache-2.0 - * - * Licensed under the Apache License, Version 2.0 (the "License"); you may - * not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT - * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. + * SPDX-License-Identifier: Apache-2.0 OR GPL-2.0-or-later */ #include "common.h" @@ -31,14 +19,122 @@ #include -const mbedtls_cipher_info_t *mbedtls_cipher_info_from_psa( +/* mbedtls_cipher_values_from_psa() below only checks if the proper build symbols + * are enabled, but it does not provide any compatibility check between them + * (i.e. if the specified key works with the specified algorithm). This helper + * function is meant to provide this support. + * mbedtls_cipher_info_from_psa() might be used for the same purpose, but it + * requires CIPHER_C to be enabled. + */ +static psa_status_t mbedtls_cipher_validate_values( + psa_algorithm_t alg, + psa_key_type_t key_type) +{ + /* Reduce code size - hinting to the compiler about what it can assume allows the compiler to + eliminate bits of the logic below. */ +#if !defined(PSA_WANT_KEY_TYPE_AES) + MBEDTLS_ASSUME(key_type != PSA_KEY_TYPE_AES); +#endif +#if !defined(PSA_WANT_KEY_TYPE_ARIA) + MBEDTLS_ASSUME(key_type != PSA_KEY_TYPE_ARIA); +#endif +#if !defined(PSA_WANT_KEY_TYPE_CAMELLIA) + MBEDTLS_ASSUME(key_type != PSA_KEY_TYPE_CAMELLIA); +#endif +#if !defined(PSA_WANT_KEY_TYPE_CHACHA20) + MBEDTLS_ASSUME(key_type != PSA_KEY_TYPE_CHACHA20); +#endif +#if !defined(PSA_WANT_KEY_TYPE_DES) + MBEDTLS_ASSUME(key_type != PSA_KEY_TYPE_DES); +#endif +#if !defined(PSA_WANT_ALG_CCM) + MBEDTLS_ASSUME(alg != PSA_ALG_AEAD_WITH_SHORTENED_TAG(PSA_ALG_CCM, 0)); +#endif +#if !defined(PSA_WANT_ALG_GCM) + MBEDTLS_ASSUME(alg != PSA_ALG_AEAD_WITH_SHORTENED_TAG(PSA_ALG_GCM, 0)); +#endif +#if !defined(PSA_WANT_ALG_STREAM_CIPHER) + MBEDTLS_ASSUME(alg != PSA_ALG_STREAM_CIPHER); +#endif +#if !defined(PSA_WANT_ALG_CHACHA20_POLY1305) + MBEDTLS_ASSUME(alg != PSA_ALG_AEAD_WITH_SHORTENED_TAG(PSA_ALG_CHACHA20_POLY1305, 0)); +#endif +#if !defined(PSA_WANT_ALG_CCM_STAR_NO_TAG) + MBEDTLS_ASSUME(alg != PSA_ALG_CCM_STAR_NO_TAG); +#endif +#if !defined(PSA_WANT_ALG_CTR) + MBEDTLS_ASSUME(alg != PSA_ALG_CTR); +#endif +#if !defined(PSA_WANT_ALG_CFB) + MBEDTLS_ASSUME(alg != PSA_ALG_CFB); +#endif +#if !defined(PSA_WANT_ALG_OFB) + MBEDTLS_ASSUME(alg != PSA_ALG_OFB); +#endif +#if !defined(PSA_WANT_ALG_XTS) + MBEDTLS_ASSUME(alg != PSA_ALG_XTS); +#endif +#if !defined(PSA_WANT_ALG_ECB_NO_PADDING) + MBEDTLS_ASSUME(alg != PSA_ALG_ECB_NO_PADDING); +#endif +#if !defined(PSA_WANT_ALG_CBC_NO_PADDING) + MBEDTLS_ASSUME(alg != PSA_ALG_CBC_NO_PADDING); +#endif +#if !defined(PSA_WANT_ALG_CBC_PKCS7) + MBEDTLS_ASSUME(alg != PSA_ALG_CBC_PKCS7); +#endif +#if !defined(PSA_WANT_ALG_CMAC) + MBEDTLS_ASSUME(alg != PSA_ALG_CMAC); +#endif + + if (alg == PSA_ALG_STREAM_CIPHER || + alg == PSA_ALG_AEAD_WITH_SHORTENED_TAG(PSA_ALG_CHACHA20_POLY1305, 0)) { + if (key_type == PSA_KEY_TYPE_CHACHA20) { + return PSA_SUCCESS; + } + } + + if (alg == PSA_ALG_AEAD_WITH_SHORTENED_TAG(PSA_ALG_CCM, 0) || + alg == PSA_ALG_AEAD_WITH_SHORTENED_TAG(PSA_ALG_GCM, 0) || + alg == PSA_ALG_CCM_STAR_NO_TAG) { + if (key_type == PSA_KEY_TYPE_AES || + key_type == PSA_KEY_TYPE_ARIA || + key_type == PSA_KEY_TYPE_CAMELLIA) { + return PSA_SUCCESS; + } + } + + if (alg == PSA_ALG_CTR || + alg == PSA_ALG_CFB || + alg == PSA_ALG_OFB || + alg == PSA_ALG_XTS || + alg == PSA_ALG_ECB_NO_PADDING || + alg == PSA_ALG_CBC_NO_PADDING || + alg == PSA_ALG_CBC_PKCS7 || + alg == PSA_ALG_CMAC) { + if (key_type == PSA_KEY_TYPE_AES || + key_type == PSA_KEY_TYPE_ARIA || + key_type == PSA_KEY_TYPE_DES || + key_type == PSA_KEY_TYPE_CAMELLIA) { + return PSA_SUCCESS; + } + } + + return PSA_ERROR_NOT_SUPPORTED; +} + +psa_status_t mbedtls_cipher_values_from_psa( psa_algorithm_t alg, psa_key_type_t key_type, - size_t key_bits, + size_t *key_bits, + mbedtls_cipher_mode_t *mode, mbedtls_cipher_id_t *cipher_id) { - mbedtls_cipher_mode_t mode; mbedtls_cipher_id_t cipher_id_tmp; + /* Only DES modifies key_bits */ +#if !defined(MBEDTLS_PSA_BUILTIN_KEY_TYPE_DES) + (void) key_bits; +#endif if (PSA_ALG_IS_AEAD(alg)) { alg = PSA_ALG_AEAD_WITH_SHORTENED_TAG(alg, 0); @@ -48,61 +144,66 @@ const mbedtls_cipher_info_t *mbedtls_cipher_info_from_psa( switch (alg) { #if defined(MBEDTLS_PSA_BUILTIN_ALG_STREAM_CIPHER) case PSA_ALG_STREAM_CIPHER: - mode = MBEDTLS_MODE_STREAM; + *mode = MBEDTLS_MODE_STREAM; break; #endif #if defined(MBEDTLS_PSA_BUILTIN_ALG_CTR) case PSA_ALG_CTR: - mode = MBEDTLS_MODE_CTR; + *mode = MBEDTLS_MODE_CTR; break; #endif #if defined(MBEDTLS_PSA_BUILTIN_ALG_CFB) case PSA_ALG_CFB: - mode = MBEDTLS_MODE_CFB; + *mode = MBEDTLS_MODE_CFB; break; #endif #if defined(MBEDTLS_PSA_BUILTIN_ALG_OFB) case PSA_ALG_OFB: - mode = MBEDTLS_MODE_OFB; + *mode = MBEDTLS_MODE_OFB; break; #endif #if defined(MBEDTLS_PSA_BUILTIN_ALG_ECB_NO_PADDING) case PSA_ALG_ECB_NO_PADDING: - mode = MBEDTLS_MODE_ECB; + *mode = MBEDTLS_MODE_ECB; break; #endif #if defined(MBEDTLS_PSA_BUILTIN_ALG_CBC_NO_PADDING) case PSA_ALG_CBC_NO_PADDING: - mode = MBEDTLS_MODE_CBC; + *mode = MBEDTLS_MODE_CBC; break; #endif #if defined(MBEDTLS_PSA_BUILTIN_ALG_CBC_PKCS7) case PSA_ALG_CBC_PKCS7: - mode = MBEDTLS_MODE_CBC; + *mode = MBEDTLS_MODE_CBC; + break; +#endif +#if defined(MBEDTLS_PSA_BUILTIN_ALG_CCM_STAR_NO_TAG) + case PSA_ALG_CCM_STAR_NO_TAG: + *mode = MBEDTLS_MODE_CCM_STAR_NO_TAG; break; #endif #if defined(MBEDTLS_PSA_BUILTIN_ALG_CCM) case PSA_ALG_AEAD_WITH_SHORTENED_TAG(PSA_ALG_CCM, 0): - mode = MBEDTLS_MODE_CCM; + *mode = MBEDTLS_MODE_CCM; break; #endif #if defined(MBEDTLS_PSA_BUILTIN_ALG_GCM) case PSA_ALG_AEAD_WITH_SHORTENED_TAG(PSA_ALG_GCM, 0): - mode = MBEDTLS_MODE_GCM; + *mode = MBEDTLS_MODE_GCM; break; #endif #if defined(MBEDTLS_PSA_BUILTIN_ALG_CHACHA20_POLY1305) case PSA_ALG_AEAD_WITH_SHORTENED_TAG(PSA_ALG_CHACHA20_POLY1305, 0): - mode = MBEDTLS_MODE_CHACHAPOLY; + *mode = MBEDTLS_MODE_CHACHAPOLY; break; #endif default: - return NULL; + return PSA_ERROR_NOT_SUPPORTED; } } else if (alg == PSA_ALG_CMAC) { - mode = MBEDTLS_MODE_ECB; + *mode = MBEDTLS_MODE_ECB; } else { - return NULL; + return PSA_ERROR_NOT_SUPPORTED; } switch (key_type) { @@ -120,7 +221,7 @@ const mbedtls_cipher_info_t *mbedtls_cipher_info_from_psa( case PSA_KEY_TYPE_DES: /* key_bits is 64 for Single-DES, 128 for two-key Triple-DES, * and 192 for three-key Triple-DES. */ - if (key_bits == 64) { + if (*key_bits == 64) { cipher_id_tmp = MBEDTLS_CIPHER_ID_DES; } else { cipher_id_tmp = MBEDTLS_CIPHER_ID_3DES; @@ -128,8 +229,8 @@ const mbedtls_cipher_info_t *mbedtls_cipher_info_from_psa( /* mbedtls doesn't recognize two-key Triple-DES as an algorithm, * but two-key Triple-DES is functionally three-key Triple-DES * with K1=K3, so that's how we present it to mbedtls. */ - if (key_bits == 128) { - key_bits = 192; + if (*key_bits == 128) { + *key_bits = 192; } break; #endif @@ -138,26 +239,43 @@ const mbedtls_cipher_info_t *mbedtls_cipher_info_from_psa( cipher_id_tmp = MBEDTLS_CIPHER_ID_CAMELLIA; break; #endif -#if defined(MBEDTLS_PSA_BUILTIN_KEY_TYPE_ARC4) - case PSA_KEY_TYPE_ARC4: - cipher_id_tmp = MBEDTLS_CIPHER_ID_ARC4; - break; -#endif #if defined(MBEDTLS_PSA_BUILTIN_KEY_TYPE_CHACHA20) case PSA_KEY_TYPE_CHACHA20: cipher_id_tmp = MBEDTLS_CIPHER_ID_CHACHA20; break; #endif default: - return NULL; + return PSA_ERROR_NOT_SUPPORTED; + } + if (cipher_id != NULL) { + *cipher_id = cipher_id_tmp; + } + + return mbedtls_cipher_validate_values(alg, key_type); +} + +#if defined(MBEDTLS_CIPHER_C) +const mbedtls_cipher_info_t *mbedtls_cipher_info_from_psa( + psa_algorithm_t alg, + psa_key_type_t key_type, + size_t key_bits, + mbedtls_cipher_id_t *cipher_id) +{ + mbedtls_cipher_mode_t mode; + psa_status_t status; + mbedtls_cipher_id_t cipher_id_tmp; + + status = mbedtls_cipher_values_from_psa(alg, key_type, &key_bits, &mode, &cipher_id_tmp); + if (status != PSA_SUCCESS) { + return NULL; } if (cipher_id != NULL) { *cipher_id = cipher_id_tmp; } - return mbedtls_cipher_info_from_values(cipher_id_tmp, - (int) key_bits, mode); + return mbedtls_cipher_info_from_values(cipher_id_tmp, (int) key_bits, mode); } +#endif /* MBEDTLS_CIPHER_C */ #if defined(MBEDTLS_PSA_BUILTIN_CIPHER) @@ -171,14 +289,14 @@ static psa_status_t psa_cipher_setup( int ret = 0; size_t key_bits; const mbedtls_cipher_info_t *cipher_info = NULL; - psa_key_type_t key_type = attributes->core.type; + psa_key_type_t key_type = attributes->type; (void) key_buffer_size; mbedtls_cipher_init(&operation->ctx.cipher); operation->alg = alg; - key_bits = attributes->core.bits; + key_bits = attributes->bits; cipher_info = mbedtls_cipher_info_from_psa(alg, key_type, key_bits, NULL); if (cipher_info == NULL) { @@ -306,7 +424,7 @@ static psa_status_t psa_cipher_update_ecb( size_t *output_length) { psa_status_t status = PSA_ERROR_CORRUPTION_DETECTED; - size_t block_size = ctx->cipher_info->block_size; + size_t block_size = mbedtls_cipher_info_get_block_size(ctx->cipher_info); size_t internal_output_length = 0; *output_length = 0; @@ -414,7 +532,11 @@ psa_status_t mbedtls_psa_cipher_update( output_length); } else #endif /* MBEDTLS_PSA_BUILTIN_ALG_ECB_NO_PADDING */ - { + if (input_length == 0) { + /* There is no input, nothing to be done */ + *output_length = 0; + status = PSA_SUCCESS; + } else { status = mbedtls_to_psa_error( mbedtls_cipher_update(&operation->ctx.cipher, input, input_length, output, output_length)); @@ -479,17 +601,18 @@ psa_status_t mbedtls_psa_cipher_abort( return PSA_SUCCESS; } -psa_status_t mbedtls_psa_cipher_encrypt(const psa_key_attributes_t *attributes, - const uint8_t *key_buffer, - size_t key_buffer_size, - psa_algorithm_t alg, - const uint8_t *iv, - size_t iv_length, - const uint8_t *input, - size_t input_length, - uint8_t *output, - size_t output_size, - size_t *output_length) +psa_status_t mbedtls_psa_cipher_encrypt( + const psa_key_attributes_t *attributes, + const uint8_t *key_buffer, + size_t key_buffer_size, + psa_algorithm_t alg, + const uint8_t *iv, + size_t iv_length, + const uint8_t *input, + size_t input_length, + uint8_t *output, + size_t output_size, + size_t *output_length) { psa_status_t status = PSA_ERROR_CORRUPTION_DETECTED; mbedtls_psa_cipher_operation_t operation = MBEDTLS_PSA_CIPHER_OPERATION_INIT; @@ -510,7 +633,8 @@ psa_status_t mbedtls_psa_cipher_encrypt(const psa_key_attributes_t *attributes, } status = mbedtls_psa_cipher_update(&operation, input, input_length, - output, output_size, &update_output_length); + output, output_size, + &update_output_length); if (status != PSA_SUCCESS) { goto exit; } diff --git a/vendor/mbedtls/library/psa_crypto_cipher.h b/vendor/mbedtls/library/psa_crypto_cipher.h index bf43ff08ab..cc565851cc 100644 --- a/vendor/mbedtls/library/psa_crypto_cipher.h +++ b/vendor/mbedtls/library/psa_crypto_cipher.h @@ -3,19 +3,7 @@ */ /* * Copyright The Mbed TLS Contributors - * SPDX-License-Identifier: Apache-2.0 - * - * Licensed under the Apache License, Version 2.0 (the "License"); you may - * not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT - * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. + * SPDX-License-Identifier: Apache-2.0 OR GPL-2.0-or-later */ #ifndef PSA_CRYPTO_CIPHER_H @@ -24,6 +12,28 @@ #include #include +/** Get Mbed TLS cipher information given the cipher algorithm PSA identifier + * as well as the PSA type and size of the key to be used with the cipher + * algorithm. + * + * \param[in] alg PSA cipher algorithm identifier + * \param[in] key_type PSA key type + * \param[in,out] key_bits Size of the key in bits. The value provided in input + * might be updated if necessary. + * \param[out] mode Mbed TLS cipher mode + * \param[out] cipher_id Mbed TLS cipher algorithm identifier + * + * \return On success \c PSA_SUCCESS is returned and key_bits, mode and cipher_id + * are properly updated. + * \c PSA_ERROR_NOT_SUPPORTED is returned if the cipher algorithm is not + * supported. + */ + +psa_status_t mbedtls_cipher_values_from_psa(psa_algorithm_t alg, psa_key_type_t key_type, + size_t *key_bits, mbedtls_cipher_mode_t *mode, + mbedtls_cipher_id_t *cipher_id); + +#if defined(MBEDTLS_CIPHER_C) /** Get Mbed TLS cipher information given the cipher algorithm PSA identifier * as well as the PSA type and size of the key to be used with the cipher * algorithm. @@ -39,6 +49,7 @@ const mbedtls_cipher_info_t *mbedtls_cipher_info_from_psa( psa_algorithm_t alg, psa_key_type_t key_type, size_t key_bits, mbedtls_cipher_id_t *cipher_id); +#endif /* MBEDTLS_CIPHER_C */ /** * \brief Set the key for a multipart symmetric encryption operation. diff --git a/vendor/mbedtls/library/psa_crypto_client.c b/vendor/mbedtls/library/psa_crypto_client.c index c3234275ae..72f671d63d 100644 --- a/vendor/mbedtls/library/psa_crypto_client.c +++ b/vendor/mbedtls/library/psa_crypto_client.c @@ -3,19 +3,7 @@ */ /* * Copyright The Mbed TLS Contributors - * SPDX-License-Identifier: Apache-2.0 - * - * Licensed under the Apache License, Version 2.0 (the "License"); you may - * not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT - * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. + * SPDX-License-Identifier: Apache-2.0 OR GPL-2.0-or-later */ #include "common.h" @@ -28,52 +16,7 @@ void psa_reset_key_attributes(psa_key_attributes_t *attributes) { - mbedtls_free(attributes->domain_parameters); memset(attributes, 0, sizeof(*attributes)); } -psa_status_t psa_set_key_domain_parameters(psa_key_attributes_t *attributes, - psa_key_type_t type, - const uint8_t *data, - size_t data_length) -{ - uint8_t *copy = NULL; - - if (data_length != 0) { - copy = mbedtls_calloc(1, data_length); - if (copy == NULL) { - return PSA_ERROR_INSUFFICIENT_MEMORY; - } - memcpy(copy, data, data_length); - } - /* After this point, this function is guaranteed to succeed, so it - * can start modifying `*attributes`. */ - - if (attributes->domain_parameters != NULL) { - mbedtls_free(attributes->domain_parameters); - attributes->domain_parameters = NULL; - attributes->domain_parameters_size = 0; - } - - attributes->domain_parameters = copy; - attributes->domain_parameters_size = data_length; - attributes->core.type = type; - return PSA_SUCCESS; -} - -psa_status_t psa_get_key_domain_parameters( - const psa_key_attributes_t *attributes, - uint8_t *data, size_t data_size, size_t *data_length) -{ - if (attributes->domain_parameters_size > data_size) { - return PSA_ERROR_BUFFER_TOO_SMALL; - } - *data_length = attributes->domain_parameters_size; - if (attributes->domain_parameters_size != 0) { - memcpy(data, attributes->domain_parameters, - attributes->domain_parameters_size); - } - return PSA_SUCCESS; -} - #endif /* MBEDTLS_PSA_CRYPTO_CLIENT */ diff --git a/vendor/mbedtls/library/psa_crypto_core.h b/vendor/mbedtls/library/psa_crypto_core.h index 781c9d2f43..9462d2e8be 100644 --- a/vendor/mbedtls/library/psa_crypto_core.h +++ b/vendor/mbedtls/library/psa_crypto_core.h @@ -3,70 +3,97 @@ */ /* * Copyright The Mbed TLS Contributors - * SPDX-License-Identifier: Apache-2.0 - * - * Licensed under the Apache License, Version 2.0 (the "License"); you may - * not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT - * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. + * SPDX-License-Identifier: Apache-2.0 OR GPL-2.0-or-later */ #ifndef PSA_CRYPTO_CORE_H #define PSA_CRYPTO_CORE_H -#if !defined(MBEDTLS_CONFIG_FILE) -#include "mbedtls/config.h" -#else -#include MBEDTLS_CONFIG_FILE -#endif +/* + * Include the build-time configuration information header. Here, we do not + * include `"mbedtls/build_info.h"` directly but `"psa/build_info.h"`, which + * is basically just an alias to it. This is to ease the maintenance of the + * TF-PSA-Crypto repository which has a different build system and + * configuration. + */ +#include "psa/build_info.h" #include "psa/crypto.h" #include "psa/crypto_se_driver.h" +#if defined(MBEDTLS_THREADING_C) +#include "mbedtls/threading.h" +#endif -/** Constant-time buffer comparison +/** + * Tell if PSA is ready for this hash. + * + * \note For now, only checks the state of the driver subsystem, + * not the algorithm. Might do more in the future. * - * \param[in] a Left-hand buffer for comparison. - * \param[in] b Right-hand buffer for comparison. - * \param n Amount of bytes to compare. + * \param hash_alg The hash algorithm (ignored for now). * - * \return 0 if the buffer contents are equal, non-zero otherwise + * \return 1 if the driver subsytem is ready, 0 otherwise. */ -static inline int mbedtls_psa_safer_memcmp( - const uint8_t *a, const uint8_t *b, size_t n) -{ - size_t i; - unsigned char diff = 0; +int psa_can_do_hash(psa_algorithm_t hash_alg); - for (i = 0; i < n; i++) { - diff |= a[i] ^ b[i]; - } +/** + * Tell if PSA is ready for this cipher. + * + * \note For now, only checks the state of the driver subsystem, + * not the algorithm. Might do more in the future. + * + * \param cipher_alg The cipher algorithm (ignored for now). + * + * \return 1 if the driver subsytem is ready, 0 otherwise. + */ +int psa_can_do_cipher(psa_key_type_t key_type, psa_algorithm_t cipher_alg); - return diff; -} +typedef enum { + PSA_SLOT_EMPTY = 0, + PSA_SLOT_FILLING, + PSA_SLOT_FULL, + PSA_SLOT_PENDING_DELETION, +} psa_key_slot_state_t; /** The data structure representing a key slot, containing key material * and metadata for one key. */ typedef struct { - psa_core_key_attributes_t attr; + psa_key_attributes_t attr; /* - * Number of locks on the key slot held by the library. + * The current state of the key slot, as described in + * docs/architecture/psa-thread-safety/psa-thread-safety.md. + * + * Library functions can modify the state of a key slot by calling + * psa_key_slot_state_transition. * - * This counter is incremented by one each time a library function - * retrieves through one of the dedicated internal API a pointer to the - * key slot. + * The state variable is used to help determine whether library functions + * which operate on the slot succeed. For example, psa_finish_key_creation, + * which transfers the state of a slot from PSA_SLOT_FILLING to + * PSA_SLOT_FULL, must fail with error code PSA_ERROR_CORRUPTION_DETECTED + * if the state of the slot is not PSA_SLOT_FILLING. + * + * Library functions which traverse the array of key slots only consider + * slots that are in a suitable state for the function. + * For example, psa_get_and_lock_key_slot_in_memory, which finds a slot + * containing a given key ID, will only check slots whose state variable is + * PSA_SLOT_FULL. */ + psa_key_slot_state_t state; + + /* + * Number of functions registered as reading the material in the key slot. * - * This counter is decremented by one each time a library function stops - * accessing the key slot and states it by calling the - * psa_unlock_key_slot() API. + * Library functions must not write directly to registered_readers + * + * A function must call psa_register_read(slot) before reading the current + * contents of the slot for an operation. + * They then must call psa_unregister_read(slot) once they have finished + * reading the current contents of the slot. If the key slot mutex is not + * held (when mutexes are enabled), this call must be done via a call to + * psa_unregister_read_under_mutex(slot). + * A function must call psa_key_slot_has_readers(slot) to check if + * the slot is in use for reading. * * This counter is used to prevent resetting the key slot while the library * may access it. For example, such control is needed in the following @@ -77,10 +104,9 @@ typedef struct { * the library cannot be reclaimed to free a key slot to load the * persistent key. * . In case of a multi-threaded application where one thread asks to close - * or purge or destroy a key while it is in used by the library through - * another thread. - */ - size_t lock_count; + * or purge or destroy a key while it is in use by the library through + * another thread. */ + size_t registered_readers; /* Dynamically allocated key data buffer. * Format as specified in psa_export_key(). */ @@ -90,86 +116,60 @@ typedef struct { } key; } psa_key_slot_t; -/* A mask of key attribute flags used only internally. - * Currently there aren't any. */ -#define PSA_KA_MASK_INTERNAL_ONLY ( \ - 0) - -/** Test whether a key slot is occupied. - * - * A key slot is occupied iff the key type is nonzero. This works because - * no valid key can have 0 as its key type. - * - * \param[in] slot The key slot to test. - * - * \return 1 if the slot is occupied, 0 otherwise. - */ -static inline int psa_is_key_slot_occupied(const psa_key_slot_t *slot) -{ - return slot->attr.type != 0; -} +#if defined(MBEDTLS_THREADING_C) -/** Test whether a key slot is locked. - * - * A key slot is locked iff its lock counter is strictly greater than 0. +/** Perform a mutex operation and return immediately upon failure. * - * \param[in] slot The key slot to test. + * Returns PSA_ERROR_SERVICE_FAILURE if the operation fails + * and status was PSA_SUCCESS. * - * \return 1 if the slot is locked, 0 otherwise. + * Assumptions: + * psa_status_t status exists. + * f is a mutex operation which returns 0 upon success. */ -static inline int psa_is_key_slot_locked(const psa_key_slot_t *slot) -{ - return slot->lock_count > 0; -} +#define PSA_THREADING_CHK_RET(f) \ + do \ + { \ + if ((f) != 0) { \ + if (status == PSA_SUCCESS) { \ + return PSA_ERROR_SERVICE_FAILURE; \ + } \ + return status; \ + } \ + } while (0); -/** Retrieve flags from psa_key_slot_t::attr::core::flags. +/** Perform a mutex operation and goto exit on failure. * - * \param[in] slot The key slot to query. - * \param mask The mask of bits to extract. + * Sets status to PSA_ERROR_SERVICE_FAILURE if status was PSA_SUCCESS. * - * \return The key attribute flags in the given slot, - * bitwise-anded with \p mask. + * Assumptions: + * psa_status_t status exists. + * Label exit: exists. + * f is a mutex operation which returns 0 upon success. */ -static inline uint16_t psa_key_slot_get_flags(const psa_key_slot_t *slot, - uint16_t mask) -{ - return slot->attr.flags & mask; -} - -/** Set flags in psa_key_slot_t::attr::core::flags. - * - * \param[in,out] slot The key slot to modify. - * \param mask The mask of bits to modify. - * \param value The new value of the selected bits. - */ -static inline void psa_key_slot_set_flags(psa_key_slot_t *slot, - uint16_t mask, - uint16_t value) -{ - slot->attr.flags = ((~mask & slot->attr.flags) | - (mask & value)); -} +#define PSA_THREADING_CHK_GOTO_EXIT(f) \ + do \ + { \ + if ((f) != 0) { \ + if (status == PSA_SUCCESS) { \ + status = PSA_ERROR_SERVICE_FAILURE; \ + } \ + goto exit; \ + } \ + } while (0); +#endif -/** Turn on flags in psa_key_slot_t::attr::core::flags. +/** Test whether a key slot has any registered readers. + * If multi-threading is enabled, the caller must hold the + * global key slot mutex. * - * \param[in,out] slot The key slot to modify. - * \param mask The mask of bits to set. - */ -static inline void psa_key_slot_set_bits_in_flags(psa_key_slot_t *slot, - uint16_t mask) -{ - slot->attr.flags |= mask; -} - -/** Turn off flags in psa_key_slot_t::attr::core::flags. + * \param[in] slot The key slot to test. * - * \param[in,out] slot The key slot to modify. - * \param mask The mask of bits to clear. + * \return 1 if the slot has any registered readers, 0 otherwise. */ -static inline void psa_key_slot_clear_bits(psa_key_slot_t *slot, - uint16_t mask) +static inline int psa_key_slot_has_readers(const psa_key_slot_t *slot) { - slot->attr.flags &= ~mask; + return slot->registered_readers > 0; } #if defined(MBEDTLS_PSA_CRYPTO_SE_C) @@ -189,13 +189,20 @@ static inline psa_key_slot_number_t psa_key_slot_get_slot_number( /** Completely wipe a slot in memory, including its policy. * * Persistent storage is not affected. + * Sets the slot's state to PSA_SLOT_EMPTY. + * If multi-threading is enabled, the caller must hold the + * global key slot mutex. * * \param[in,out] slot The key slot to wipe. * * \retval #PSA_SUCCESS - * Success. This includes the case of a key slot that was - * already fully wiped. - * \retval #PSA_ERROR_CORRUPTION_DETECTED \emptydescription + * The slot has been successfully wiped. + * \retval #PSA_ERROR_CORRUPTION_DETECTED + * The slot's state was PSA_SLOT_FULL or PSA_SLOT_PENDING_DELETION, and + * the amount of registered readers was not equal to 1. Or, + * the slot's state was PSA_SLOT_EMPTY. Or, + * the slot's state was PSA_SLOT_FILLING, and the amount + * of registered readers was not equal to 0. */ psa_status_t psa_wipe_key_slot(psa_key_slot_t *slot); @@ -336,6 +343,18 @@ psa_status_t psa_export_public_key_internal( const uint8_t *key_buffer, size_t key_buffer_size, uint8_t *data, size_t data_size, size_t *data_length); +/** Whether a key production parameters structure is the default. + * + * Calls to a key generation driver with non-default production parameters + * require a driver supporting custom production parameters. + * + * \param[in] params The key production parameters to check. + * \param params_data_length Size of `params->data` in bytes. + */ +int psa_key_production_parameters_are_default( + const psa_key_production_parameters_t *params, + size_t params_data_length); + /** * \brief Generate a key. * @@ -343,6 +362,9 @@ psa_status_t psa_export_public_key_internal( * entry point. * * \param[in] attributes The attributes for the key to generate. + * \param[in] params The production parameters from + * psa_generate_key_ext(). + * \param params_data_length The size of `params->data` in bytes. * \param[out] key_buffer Buffer where the key data is to be written. * \param[in] key_buffer_size Size of \p key_buffer in bytes. * \param[out] key_buffer_length On success, the number of bytes written in @@ -357,6 +379,8 @@ psa_status_t psa_export_public_key_internal( * The size of \p key_buffer is too small. */ psa_status_t psa_generate_key_internal(const psa_key_attributes_t *attributes, + const psa_key_production_parameters_t *params, + size_t params_data_length, uint8_t *key_buffer, size_t key_buffer_size, size_t *key_buffer_length); @@ -515,4 +539,419 @@ psa_status_t psa_verify_hash_builtin( psa_algorithm_t alg, const uint8_t *hash, size_t hash_length, const uint8_t *signature, size_t signature_length); +/** + * \brief Validate the key bit size for unstructured keys. + * + * \note Check that the bit size is acceptable for a given key type for + * unstructured keys. + * + * \param[in] type The key type + * \param[in] bits The number of bits of the key + * + * \retval #PSA_SUCCESS + * The key type and size are valid. + * \retval #PSA_ERROR_INVALID_ARGUMENT + * The size in bits of the key is not valid. + * \retval #PSA_ERROR_NOT_SUPPORTED + * The type and/or the size in bits of the key or the combination of + * the two is not supported. + */ +psa_status_t psa_validate_unstructured_key_bit_size(psa_key_type_t type, + size_t bits); + +/** Perform a key agreement and return the raw shared secret, using + built-in raw key agreement functions. + * + * \note The signature of this function is that of a PSA driver + * key_agreement entry point. This function behaves as a key_agreement + * entry point as defined in the PSA driver interface specification for + * transparent drivers. + * + * \param[in] attributes The attributes of the key to use for the + * operation. + * \param[in] key_buffer The buffer containing the private key + * context. + * \param[in] key_buffer_size Size of the \p key_buffer buffer in + * bytes. + * \param[in] alg A key agreement algorithm that is + * compatible with the type of the key. + * \param[in] peer_key The buffer containing the key context + * of the peer's public key. + * \param[in] peer_key_length Size of the \p peer_key buffer in + * bytes. + * \param[out] shared_secret The buffer to which the shared secret + * is to be written. + * \param[in] shared_secret_size Size of the \p shared_secret buffer in + * bytes. + * \param[out] shared_secret_length On success, the number of bytes that make + * up the returned shared secret. + * \retval #PSA_SUCCESS + * Success. Shared secret successfully calculated. + * \retval #PSA_ERROR_INVALID_HANDLE \emptydescription + * \retval #PSA_ERROR_NOT_PERMITTED \emptydescription + * \retval #PSA_ERROR_INVALID_ARGUMENT + * \p alg is not a key agreement algorithm, or + * \p private_key is not compatible with \p alg, + * or \p peer_key is not valid for \p alg or not compatible with + * \p private_key. + * \retval #PSA_ERROR_BUFFER_TOO_SMALL + * \p shared_secret_size is too small + * \retval #PSA_ERROR_NOT_SUPPORTED + * \p alg is not a supported key agreement algorithm. + * \retval #PSA_ERROR_INSUFFICIENT_MEMORY \emptydescription + * \retval #PSA_ERROR_COMMUNICATION_FAILURE \emptydescription + * \retval #PSA_ERROR_HARDWARE_FAILURE \emptydescription + * \retval #PSA_ERROR_CORRUPTION_DETECTED \emptydescription + * \retval #PSA_ERROR_STORAGE_FAILURE \emptydescription + * \retval #PSA_ERROR_BAD_STATE \emptydescription + */ +psa_status_t psa_key_agreement_raw_builtin( + const psa_key_attributes_t *attributes, + const uint8_t *key_buffer, + size_t key_buffer_size, + psa_algorithm_t alg, + const uint8_t *peer_key, + size_t peer_key_length, + uint8_t *shared_secret, + size_t shared_secret_size, + size_t *shared_secret_length); + +/** + * \brief Set the maximum number of ops allowed to be executed by an + * interruptible function in a single call. + * + * \note The signature of this function is that of a PSA driver + * interruptible_set_max_ops entry point. This function behaves as an + * interruptible_set_max_ops entry point as defined in the PSA driver + * interface specification for transparent drivers. + * + * \param[in] max_ops The maximum number of ops to be executed in a + * single call, this can be a number from 0 to + * #PSA_INTERRUPTIBLE_MAX_OPS_UNLIMITED, where 0 + * is obviously the least amount of work done per + * call. + */ +void mbedtls_psa_interruptible_set_max_ops(uint32_t max_ops); + +/** + * \brief Get the maximum number of ops allowed to be executed by an + * interruptible function in a single call. + * + * \note The signature of this function is that of a PSA driver + * interruptible_get_max_ops entry point. This function behaves as an + * interruptible_get_max_ops entry point as defined in the PSA driver + * interface specification for transparent drivers. + * + * \return Maximum number of ops allowed to be executed + * by an interruptible function in a single call. + */ +uint32_t mbedtls_psa_interruptible_get_max_ops(void); + +/** + * \brief Get the number of ops that a hash signing operation has taken for the + * previous call. If no call or work has taken place, this will return + * zero. + * + * \note The signature of this function is that of a PSA driver + * sign_hash_get_num_ops entry point. This function behaves as an + * sign_hash_get_num_ops entry point as defined in the PSA driver + * interface specification for transparent drivers. + * + * \param operation The \c + * mbedtls_psa_sign_hash_interruptible_operation_t + * to use. This must be initialized first. + * + * \return Number of ops that were completed + * in the last call to \c + * mbedtls_psa_sign_hash_complete(). + */ +uint32_t mbedtls_psa_sign_hash_get_num_ops( + const mbedtls_psa_sign_hash_interruptible_operation_t *operation); + +/** + * \brief Get the number of ops that a hash verification operation has taken for + * the previous call. If no call or work has taken place, this will + * return zero. + * + * \note The signature of this function is that of a PSA driver + * verify_hash_get_num_ops entry point. This function behaves as an + * verify_hash_get_num_ops entry point as defined in the PSA driver + * interface specification for transparent drivers. + * + * \param operation The \c + * mbedtls_psa_verify_hash_interruptible_operation_t + * to use. This must be initialized first. + * + * \return Number of ops that were completed + * in the last call to \c + * mbedtls_psa_verify_hash_complete(). + */ +uint32_t mbedtls_psa_verify_hash_get_num_ops( + const mbedtls_psa_verify_hash_interruptible_operation_t *operation); + +/** + * \brief Start signing a hash or short message with a private key, in an + * interruptible manner. + * + * \note The signature of this function is that of a PSA driver + * sign_hash_start entry point. This function behaves as a + * sign_hash_start entry point as defined in the PSA driver interface + * specification for transparent drivers. + * + * \param[in] operation The \c + * mbedtls_psa_sign_hash_interruptible_operation_t + * to use. This must be initialized first. + * \param[in] attributes The attributes of the key to use for the + * operation. + * \param[in] key_buffer The buffer containing the key context. + * \param[in] key_buffer_size Size of the \p key_buffer buffer in bytes. + * \param[in] alg A signature algorithm that is compatible with + * the type of the key. + * \param[in] hash The hash or message to sign. + * \param hash_length Size of the \p hash buffer in bytes. + * + * \retval #PSA_SUCCESS + * The operation started successfully - call \c psa_sign_hash_complete() + * with the same context to complete the operation + * \retval #PSA_ERROR_INVALID_ARGUMENT + * An unsupported, incorrectly formatted or incorrect type of key was + * used. + * \retval #PSA_ERROR_NOT_SUPPORTED Either no internal interruptible operations + * are currently supported, or the key type is currently unsupported. + * \retval #PSA_ERROR_INSUFFICIENT_MEMORY + * There was insufficient memory to load the key representation. + */ +psa_status_t mbedtls_psa_sign_hash_start( + mbedtls_psa_sign_hash_interruptible_operation_t *operation, + const psa_key_attributes_t *attributes, const uint8_t *key_buffer, + size_t key_buffer_size, psa_algorithm_t alg, + const uint8_t *hash, size_t hash_length); + +/** + * \brief Continue and eventually complete the action of signing a hash or + * short message with a private key, in an interruptible manner. + * + * \note The signature of this function is that of a PSA driver + * sign_hash_complete entry point. This function behaves as a + * sign_hash_complete entry point as defined in the PSA driver interface + * specification for transparent drivers. + * + * \param[in] operation The \c + * mbedtls_psa_sign_hash_interruptible_operation_t + * to use. This must be initialized first. + * + * \param[out] signature Buffer where the signature is to be written. + * \param signature_size Size of the \p signature buffer in bytes. This + * must be appropriate for the selected + * algorithm and key. + * \param[out] signature_length On success, the number of bytes that make up + * the returned signature value. + * + * \retval #PSA_SUCCESS + * Operation completed successfully + * + * \retval #PSA_OPERATION_INCOMPLETE + * Operation was interrupted due to the setting of \c + * psa_interruptible_set_max_ops(), there is still work to be done, + * please call this function again with the same operation object. + * + * \retval #PSA_ERROR_BUFFER_TOO_SMALL + * The size of the \p signature buffer is too small. You can + * determine a sufficient buffer size by calling + * #PSA_SIGN_OUTPUT_SIZE(\c key_type, \c key_bits, \p alg) + * where \c key_type and \c key_bits are the type and bit-size + * respectively of \p key. + * + * \retval #PSA_ERROR_NOT_SUPPORTED \emptydescription + * \retval #PSA_ERROR_INVALID_ARGUMENT \emptydescription + * \retval #PSA_ERROR_INSUFFICIENT_MEMORY \emptydescription + * \retval #PSA_ERROR_CORRUPTION_DETECTED \emptydescription + * \retval #PSA_ERROR_INSUFFICIENT_ENTROPY \emptydescription + */ +psa_status_t mbedtls_psa_sign_hash_complete( + mbedtls_psa_sign_hash_interruptible_operation_t *operation, + uint8_t *signature, size_t signature_size, + size_t *signature_length); + +/** + * \brief Abort a sign hash operation. + * + * \note The signature of this function is that of a PSA driver sign_hash_abort + * entry point. This function behaves as a sign_hash_abort entry point as + * defined in the PSA driver interface specification for transparent + * drivers. + * + * \param[in] operation The \c + * mbedtls_psa_sign_hash_interruptible_operation_t + * to abort. + * + * \retval #PSA_SUCCESS + * The operation was aborted successfully. + */ +psa_status_t mbedtls_psa_sign_hash_abort( + mbedtls_psa_sign_hash_interruptible_operation_t *operation); + +/** + * \brief Start reading and verifying a hash or short message, in an + * interruptible manner. + * + * \note The signature of this function is that of a PSA driver + * verify_hash_start entry point. This function behaves as a + * verify_hash_start entry point as defined in the PSA driver interface + * specification for transparent drivers. + * + * \param[in] operation The \c + * mbedtls_psa_verify_hash_interruptible_operation_t + * to use. This must be initialized first. + * \param[in] attributes The attributes of the key to use for the + * operation. + * \param[in] key_buffer The buffer containing the key context. + * \param[in] key_buffer_size Size of the \p key_buffer buffer in bytes. + * \param[in] alg A signature algorithm that is compatible with + * the type of the key. + * \param[in] hash The hash whose signature is to be verified. + * \param hash_length Size of the \p hash buffer in bytes. + * \param[in] signature Buffer containing the signature to verify. + * \param signature_length Size of the \p signature buffer in bytes. + * + * \retval #PSA_SUCCESS + * The operation started successfully - call \c psa_sign_hash_complete() + * with the same context to complete the operation + * \retval #PSA_ERROR_INVALID_ARGUMENT + * An unsupported or incorrect type of key was used. + * \retval #PSA_ERROR_NOT_SUPPORTED + * Either no internal interruptible operations are currently supported, + * or the key type is currently unsupported. + * \retval #PSA_ERROR_INSUFFICIENT_MEMORY + * There was insufficient memory either to load the key representation, + * or to prepare the operation. + */ +psa_status_t mbedtls_psa_verify_hash_start( + mbedtls_psa_verify_hash_interruptible_operation_t *operation, + const psa_key_attributes_t *attributes, + const uint8_t *key_buffer, size_t key_buffer_size, + psa_algorithm_t alg, + const uint8_t *hash, size_t hash_length, + const uint8_t *signature, size_t signature_length); + +/** + * \brief Continue and eventually complete the action of signing a hash or + * short message with a private key, in an interruptible manner. + * + * \note The signature of this function is that of a PSA driver + * sign_hash_complete entry point. This function behaves as a + * sign_hash_complete entry point as defined in the PSA driver interface + * specification for transparent drivers. + * + * \param[in] operation The \c + * mbedtls_psa_sign_hash_interruptible_operation_t + * to use. This must be initialized first. + * + * \retval #PSA_SUCCESS + * Operation completed successfully, and the passed signature is valid. + * + * \retval #PSA_OPERATION_INCOMPLETE + * Operation was interrupted due to the setting of \c + * psa_interruptible_set_max_ops(), there is still work to be done, + * please call this function again with the same operation object. + * + * \retval #PSA_ERROR_INVALID_SIGNATURE + * The calculation was performed successfully, but the passed + * signature is not a valid signature. + * + * \retval #PSA_ERROR_NOT_SUPPORTED \emptydescription + * \retval #PSA_ERROR_INVALID_ARGUMENT \emptydescription + * \retval #PSA_ERROR_INSUFFICIENT_MEMORY \emptydescription + */ +psa_status_t mbedtls_psa_verify_hash_complete( + mbedtls_psa_verify_hash_interruptible_operation_t *operation); + +/** + * \brief Abort a verify signed hash operation. + * + * \note The signature of this function is that of a PSA driver + * verify_hash_abort entry point. This function behaves as a + * verify_hash_abort entry point as defined in the PSA driver interface + * specification for transparent drivers. + * + * \param[in] operation The \c + * mbedtls_psa_verify_hash_interruptible_operation_t + * to abort. + * + * \retval #PSA_SUCCESS + * The operation was aborted successfully. + */ +psa_status_t mbedtls_psa_verify_hash_abort( + mbedtls_psa_verify_hash_interruptible_operation_t *operation); + +typedef struct psa_crypto_local_input_s { + uint8_t *buffer; + size_t length; +} psa_crypto_local_input_t; + +#define PSA_CRYPTO_LOCAL_INPUT_INIT ((psa_crypto_local_input_t) { NULL, 0 }) + +/** Allocate a local copy of an input buffer and copy the contents into it. + * + * \param[in] input Pointer to input buffer. + * \param[in] input_len Length of the input buffer. + * \param[out] local_input Pointer to a psa_crypto_local_input_t struct + * containing a local input copy. + * \return #PSA_SUCCESS, if the buffer was successfully + * copied. + * \return #PSA_ERROR_INSUFFICIENT_MEMORY, if a copy of + * the buffer cannot be allocated. + */ +psa_status_t psa_crypto_local_input_alloc(const uint8_t *input, size_t input_len, + psa_crypto_local_input_t *local_input); + +/** Free a local copy of an input buffer. + * + * \param[in] local_input Pointer to a psa_crypto_local_input_t struct + * populated by a previous call to + * psa_crypto_local_input_alloc(). + */ +void psa_crypto_local_input_free(psa_crypto_local_input_t *local_input); + +typedef struct psa_crypto_local_output_s { + uint8_t *original; + uint8_t *buffer; + size_t length; +} psa_crypto_local_output_t; + +#define PSA_CRYPTO_LOCAL_OUTPUT_INIT ((psa_crypto_local_output_t) { NULL, NULL, 0 }) + +/** Allocate a local copy of an output buffer. + * + * \note This does not copy any data from the original + * output buffer but only allocates a buffer + * whose contents will be copied back to the + * original in a future call to + * psa_crypto_local_output_free(). + * + * \param[in] output Pointer to output buffer. + * \param[in] output_len Length of the output buffer. + * \param[out] local_output Pointer to a psa_crypto_local_output_t struct to + * populate with the local output copy. + * \return #PSA_SUCCESS, if the buffer was successfully + * copied. + * \return #PSA_ERROR_INSUFFICIENT_MEMORY, if a copy of + * the buffer cannot be allocated. + */ +psa_status_t psa_crypto_local_output_alloc(uint8_t *output, size_t output_len, + psa_crypto_local_output_t *local_output); + +/** Copy from a local copy of an output buffer back to the original, then + * free the local copy. + * + * \param[in] local_output Pointer to a psa_crypto_local_output_t struct + * populated by a previous call to + * psa_crypto_local_output_alloc(). + * \return #PSA_SUCCESS, if the local output was + * successfully copied back to the original. + * \return #PSA_ERROR_CORRUPTION_DETECTED, if the output + * could not be copied back to the original. + */ +psa_status_t psa_crypto_local_output_free(psa_crypto_local_output_t *local_output); + #endif /* PSA_CRYPTO_CORE_H */ diff --git a/vendor/mbedtls/library/psa_crypto_core_common.h b/vendor/mbedtls/library/psa_crypto_core_common.h new file mode 100644 index 0000000000..98fce2cca4 --- /dev/null +++ b/vendor/mbedtls/library/psa_crypto_core_common.h @@ -0,0 +1,52 @@ +/** + * \file psa_crypto_core_common.h + * + * \brief Utility macros for internal use in the PSA cryptography core. + */ +/* + * Copyright The Mbed TLS Contributors + * SPDX-License-Identifier: Apache-2.0 OR GPL-2.0-or-later + */ + +#ifndef PSA_CRYPTO_CORE_COMMON_H +#define PSA_CRYPTO_CORE_COMMON_H + +/** Return an offset into a buffer. + * + * This is just the addition of an offset to a pointer, except that this + * function also accepts an offset of 0 into a buffer whose pointer is null. + * (`p + n` has undefined behavior when `p` is null, even when `n == 0`. + * A null pointer is a valid buffer pointer when the size is 0, for example + * as the result of `malloc(0)` on some platforms.) + * + * \param p Pointer to a buffer of at least n bytes. + * This may be \p NULL if \p n is zero. + * \param n An offset in bytes. + * \return Pointer to offset \p n in the buffer \p p. + * Note that this is only a valid pointer if the size of the + * buffer is at least \p n + 1. + */ +static inline unsigned char *psa_crypto_buffer_offset( + unsigned char *p, size_t n) +{ + return p == NULL ? NULL : p + n; +} + +/** Return an offset into a read-only buffer. + * + * Similar to mbedtls_buffer_offset(), but for const pointers. + * + * \param p Pointer to a buffer of at least n bytes. + * This may be \p NULL if \p n is zero. + * \param n An offset in bytes. + * \return Pointer to offset \p n in the buffer \p p. + * Note that this is only a valid pointer if the size of the + * buffer is at least \p n + 1. + */ +static inline const unsigned char *psa_crypto_buffer_offset_const( + const unsigned char *p, size_t n) +{ + return p == NULL ? NULL : p + n; +} + +#endif /* PSA_CRYPTO_CORE_COMMON_H */ diff --git a/vendor/mbedtls/library/psa_crypto_driver_wrappers.c b/vendor/mbedtls/library/psa_crypto_driver_wrappers.c deleted file mode 100644 index 6156385337..0000000000 --- a/vendor/mbedtls/library/psa_crypto_driver_wrappers.c +++ /dev/null @@ -1,1868 +0,0 @@ -/* - * Functions to delegate cryptographic operations to an available - * and appropriate accelerator. - * Warning: This file will be auto-generated in the future. - */ -/* Copyright The Mbed TLS Contributors - * SPDX-License-Identifier: Apache-2.0 - * - * Licensed under the Apache License, Version 2.0 (the "License"); you may - * not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT - * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -#include "psa_crypto_aead.h" -#include "psa_crypto_cipher.h" -#include "psa_crypto_core.h" -#include "psa_crypto_driver_wrappers.h" -#include "psa_crypto_hash.h" -#include "psa_crypto_mac.h" - -#include "mbedtls/platform.h" - -#if defined(MBEDTLS_PSA_CRYPTO_C) - -#if defined(MBEDTLS_PSA_CRYPTO_DRIVERS) - -/* Include test driver definition when running tests */ -#if defined(PSA_CRYPTO_DRIVER_TEST) -#ifndef PSA_CRYPTO_DRIVER_PRESENT -#define PSA_CRYPTO_DRIVER_PRESENT -#endif -#ifndef PSA_CRYPTO_ACCELERATOR_DRIVER_PRESENT -#define PSA_CRYPTO_ACCELERATOR_DRIVER_PRESENT -#endif -#include "test/drivers/test_driver.h" -#endif /* PSA_CRYPTO_DRIVER_TEST */ - -/* Repeat above block for each JSON-declared driver during autogeneration */ -#endif /* MBEDTLS_PSA_CRYPTO_DRIVERS */ - -/* Auto-generated values depending on which drivers are registered. - * ID 0 is reserved for unallocated operations. - * ID 1 is reserved for the Mbed TLS software driver. */ -#define PSA_CRYPTO_MBED_TLS_DRIVER_ID (1) - -#if defined(PSA_CRYPTO_DRIVER_TEST) -#define PSA_CRYPTO_TRANSPARENT_TEST_DRIVER_ID (2) -#define PSA_CRYPTO_OPAQUE_TEST_DRIVER_ID (3) -#endif /* PSA_CRYPTO_DRIVER_TEST */ - -/* Support the 'old' SE interface when asked to */ -#if defined(MBEDTLS_PSA_CRYPTO_SE_C) -/* PSA_CRYPTO_DRIVER_PRESENT is defined when either a new-style or old-style - * SE driver is present, to avoid unused argument errors at compile time. */ -#ifndef PSA_CRYPTO_DRIVER_PRESENT -#define PSA_CRYPTO_DRIVER_PRESENT -#endif -#include "psa_crypto_se.h" -#endif - -psa_status_t psa_driver_wrapper_init(void) -{ - psa_status_t status = PSA_ERROR_CORRUPTION_DETECTED; - -#if defined(MBEDTLS_PSA_CRYPTO_SE_C) - status = psa_init_all_se_drivers(); - if (status != PSA_SUCCESS) { - return status; - } -#endif - -#if defined(PSA_CRYPTO_DRIVER_TEST) - status = mbedtls_test_transparent_init(); - if (status != PSA_SUCCESS) { - return status; - } - - status = mbedtls_test_opaque_init(); - if (status != PSA_SUCCESS) { - return status; - } -#endif - - (void) status; - return PSA_SUCCESS; -} - -void psa_driver_wrapper_free(void) -{ -#if defined(MBEDTLS_PSA_CRYPTO_SE_C) - /* Unregister all secure element drivers, so that we restart from - * a pristine state. */ - psa_unregister_all_se_drivers(); -#endif /* MBEDTLS_PSA_CRYPTO_SE_C */ - -#if defined(PSA_CRYPTO_DRIVER_TEST) - mbedtls_test_transparent_free(); - mbedtls_test_opaque_free(); -#endif -} - -/* Start delegation functions */ -psa_status_t psa_driver_wrapper_sign_message( - const psa_key_attributes_t *attributes, - const uint8_t *key_buffer, - size_t key_buffer_size, - psa_algorithm_t alg, - const uint8_t *input, - size_t input_length, - uint8_t *signature, - size_t signature_size, - size_t *signature_length) -{ - psa_status_t status = PSA_ERROR_CORRUPTION_DETECTED; - psa_key_location_t location = - PSA_KEY_LIFETIME_GET_LOCATION(attributes->core.lifetime); - - switch (location) { - case PSA_KEY_LOCATION_LOCAL_STORAGE: - /* Key is stored in the slot in export representation, so - * cycle through all known transparent accelerators */ -#if defined(PSA_CRYPTO_ACCELERATOR_DRIVER_PRESENT) -#if defined(PSA_CRYPTO_DRIVER_TEST) - status = mbedtls_test_transparent_signature_sign_message( - attributes, - key_buffer, - key_buffer_size, - alg, - input, - input_length, - signature, - signature_size, - signature_length); - /* Declared with fallback == true */ - if (status != PSA_ERROR_NOT_SUPPORTED) { - return status; - } -#endif /* PSA_CRYPTO_DRIVER_TEST */ -#endif /* PSA_CRYPTO_ACCELERATOR_DRIVER_PRESENT */ - break; - - /* Add cases for opaque driver here */ -#if defined(PSA_CRYPTO_ACCELERATOR_DRIVER_PRESENT) -#if defined(PSA_CRYPTO_DRIVER_TEST) - case PSA_CRYPTO_TEST_DRIVER_LOCATION: - status = mbedtls_test_opaque_signature_sign_message( - attributes, - key_buffer, - key_buffer_size, - alg, - input, - input_length, - signature, - signature_size, - signature_length); - if (status != PSA_ERROR_NOT_SUPPORTED) { - return status; - } - break; -#endif /* PSA_CRYPTO_DRIVER_TEST */ -#endif /* PSA_CRYPTO_ACCELERATOR_DRIVER_PRESENT */ - default: - /* Key is declared with a lifetime not known to us */ - (void) status; - break; - } - - return psa_sign_message_builtin(attributes, - key_buffer, - key_buffer_size, - alg, - input, - input_length, - signature, - signature_size, - signature_length); -} - -psa_status_t psa_driver_wrapper_verify_message( - const psa_key_attributes_t *attributes, - const uint8_t *key_buffer, - size_t key_buffer_size, - psa_algorithm_t alg, - const uint8_t *input, - size_t input_length, - const uint8_t *signature, - size_t signature_length) -{ - psa_status_t status = PSA_ERROR_CORRUPTION_DETECTED; - psa_key_location_t location = - PSA_KEY_LIFETIME_GET_LOCATION(attributes->core.lifetime); - - switch (location) { - case PSA_KEY_LOCATION_LOCAL_STORAGE: - /* Key is stored in the slot in export representation, so - * cycle through all known transparent accelerators */ -#if defined(PSA_CRYPTO_ACCELERATOR_DRIVER_PRESENT) -#if defined(PSA_CRYPTO_DRIVER_TEST) - status = mbedtls_test_transparent_signature_verify_message( - attributes, - key_buffer, - key_buffer_size, - alg, - input, - input_length, - signature, - signature_length); - /* Declared with fallback == true */ - if (status != PSA_ERROR_NOT_SUPPORTED) { - return status; - } -#endif /* PSA_CRYPTO_DRIVER_TEST */ -#endif /* PSA_CRYPTO_ACCELERATOR_DRIVER_PRESENT */ - break; - - /* Add cases for opaque driver here */ -#if defined(PSA_CRYPTO_ACCELERATOR_DRIVER_PRESENT) -#if defined(PSA_CRYPTO_DRIVER_TEST) - case PSA_CRYPTO_TEST_DRIVER_LOCATION: - return mbedtls_test_opaque_signature_verify_message( - attributes, - key_buffer, - key_buffer_size, - alg, - input, - input_length, - signature, - signature_length); - if (status != PSA_ERROR_NOT_SUPPORTED) { - return status; - } - break; -#endif /* PSA_CRYPTO_DRIVER_TEST */ -#endif /* PSA_CRYPTO_ACCELERATOR_DRIVER_PRESENT */ - default: - /* Key is declared with a lifetime not known to us */ - (void) status; - break; - } - - return psa_verify_message_builtin(attributes, - key_buffer, - key_buffer_size, - alg, - input, - input_length, - signature, - signature_length); -} - -psa_status_t psa_driver_wrapper_sign_hash( - const psa_key_attributes_t *attributes, - const uint8_t *key_buffer, size_t key_buffer_size, - psa_algorithm_t alg, const uint8_t *hash, size_t hash_length, - uint8_t *signature, size_t signature_size, size_t *signature_length) -{ - /* Try dynamically-registered SE interface first */ -#if defined(MBEDTLS_PSA_CRYPTO_SE_C) - const psa_drv_se_t *drv; - psa_drv_se_context_t *drv_context; - - if (psa_get_se_driver(attributes->core.lifetime, &drv, &drv_context)) { - if (drv->asymmetric == NULL || - drv->asymmetric->p_sign == NULL) { - /* Key is defined in SE, but we have no way to exercise it */ - return PSA_ERROR_NOT_SUPPORTED; - } - return drv->asymmetric->p_sign( - drv_context, *((psa_key_slot_number_t *) key_buffer), - alg, hash, hash_length, - signature, signature_size, signature_length); - } -#endif /* MBEDTLS_PSA_CRYPTO_SE_C */ - - psa_status_t status = PSA_ERROR_CORRUPTION_DETECTED; - psa_key_location_t location = - PSA_KEY_LIFETIME_GET_LOCATION(attributes->core.lifetime); - - switch (location) { - case PSA_KEY_LOCATION_LOCAL_STORAGE: - /* Key is stored in the slot in export representation, so - * cycle through all known transparent accelerators */ -#if defined(PSA_CRYPTO_ACCELERATOR_DRIVER_PRESENT) -#if defined(PSA_CRYPTO_DRIVER_TEST) - status = mbedtls_test_transparent_signature_sign_hash(attributes, - key_buffer, - key_buffer_size, - alg, - hash, - hash_length, - signature, - signature_size, - signature_length); - /* Declared with fallback == true */ - if (status != PSA_ERROR_NOT_SUPPORTED) { - return status; - } -#endif /* PSA_CRYPTO_DRIVER_TEST */ -#endif /* PSA_CRYPTO_ACCELERATOR_DRIVER_PRESENT */ - /* Fell through, meaning no accelerator supports this operation */ - return psa_sign_hash_builtin(attributes, - key_buffer, - key_buffer_size, - alg, - hash, - hash_length, - signature, - signature_size, - signature_length); - - /* Add cases for opaque driver here */ -#if defined(PSA_CRYPTO_ACCELERATOR_DRIVER_PRESENT) -#if defined(PSA_CRYPTO_DRIVER_TEST) - case PSA_CRYPTO_TEST_DRIVER_LOCATION: - return mbedtls_test_opaque_signature_sign_hash(attributes, - key_buffer, - key_buffer_size, - alg, - hash, - hash_length, - signature, - signature_size, - signature_length); -#endif /* PSA_CRYPTO_DRIVER_TEST */ -#endif /* PSA_CRYPTO_ACCELERATOR_DRIVER_PRESENT */ - default: - /* Key is declared with a lifetime not known to us */ - (void) status; - return PSA_ERROR_INVALID_ARGUMENT; - } -} - -psa_status_t psa_driver_wrapper_verify_hash( - const psa_key_attributes_t *attributes, - const uint8_t *key_buffer, size_t key_buffer_size, - psa_algorithm_t alg, const uint8_t *hash, size_t hash_length, - const uint8_t *signature, size_t signature_length) -{ - /* Try dynamically-registered SE interface first */ -#if defined(MBEDTLS_PSA_CRYPTO_SE_C) - const psa_drv_se_t *drv; - psa_drv_se_context_t *drv_context; - - if (psa_get_se_driver(attributes->core.lifetime, &drv, &drv_context)) { - if (drv->asymmetric == NULL || - drv->asymmetric->p_verify == NULL) { - /* Key is defined in SE, but we have no way to exercise it */ - return PSA_ERROR_NOT_SUPPORTED; - } - return drv->asymmetric->p_verify( - drv_context, *((psa_key_slot_number_t *) key_buffer), - alg, hash, hash_length, - signature, signature_length); - } -#endif /* MBEDTLS_PSA_CRYPTO_SE_C */ - - psa_status_t status = PSA_ERROR_CORRUPTION_DETECTED; - psa_key_location_t location = - PSA_KEY_LIFETIME_GET_LOCATION(attributes->core.lifetime); - - switch (location) { - case PSA_KEY_LOCATION_LOCAL_STORAGE: - /* Key is stored in the slot in export representation, so - * cycle through all known transparent accelerators */ -#if defined(PSA_CRYPTO_ACCELERATOR_DRIVER_PRESENT) -#if defined(PSA_CRYPTO_DRIVER_TEST) - status = mbedtls_test_transparent_signature_verify_hash( - attributes, - key_buffer, - key_buffer_size, - alg, - hash, - hash_length, - signature, - signature_length); - /* Declared with fallback == true */ - if (status != PSA_ERROR_NOT_SUPPORTED) { - return status; - } -#endif /* PSA_CRYPTO_DRIVER_TEST */ -#endif /* PSA_CRYPTO_ACCELERATOR_DRIVER_PRESENT */ - - return psa_verify_hash_builtin(attributes, - key_buffer, - key_buffer_size, - alg, - hash, - hash_length, - signature, - signature_length); - - /* Add cases for opaque driver here */ -#if defined(PSA_CRYPTO_ACCELERATOR_DRIVER_PRESENT) -#if defined(PSA_CRYPTO_DRIVER_TEST) - case PSA_CRYPTO_TEST_DRIVER_LOCATION: - return mbedtls_test_opaque_signature_verify_hash(attributes, - key_buffer, - key_buffer_size, - alg, - hash, - hash_length, - signature, - signature_length); -#endif /* PSA_CRYPTO_DRIVER_TEST */ -#endif /* PSA_CRYPTO_ACCELERATOR_DRIVER_PRESENT */ - default: - /* Key is declared with a lifetime not known to us */ - (void) status; - return PSA_ERROR_INVALID_ARGUMENT; - } -} - -/** Get the key buffer size required to store the key material of a key - * associated with an opaque driver without storage. - * - * \param[in] attributes The key attributes. - * \param[out] key_buffer_size Minimum buffer size to contain the key material - * - * \retval #PSA_SUCCESS - * The minimum size for a buffer to contain the key material has been - * returned successfully. - * \retval #PSA_ERROR_INVALID_ARGUMENT - * The size in bits of the key is not valid. - * \retval #PSA_ERROR_NOT_SUPPORTED - * The type and/or the size in bits of the key or the combination of - * the two is not supported. - */ -psa_status_t psa_driver_wrapper_get_key_buffer_size( - const psa_key_attributes_t *attributes, - size_t *key_buffer_size) -{ - psa_key_location_t location = PSA_KEY_LIFETIME_GET_LOCATION(attributes->core.lifetime); - psa_key_type_t key_type = attributes->core.type; - size_t key_bits = attributes->core.bits; - - *key_buffer_size = 0; - switch (location) { -#if defined(PSA_CRYPTO_DRIVER_TEST) - case PSA_CRYPTO_TEST_DRIVER_LOCATION: -#if defined(MBEDTLS_PSA_CRYPTO_BUILTIN_KEYS) - /* Emulate property 'builtin_key_size' */ - if (psa_key_id_is_builtin( - MBEDTLS_SVC_KEY_ID_GET_KEY_ID( - psa_get_key_id(attributes)))) { - *key_buffer_size = sizeof(psa_drv_slot_number_t); - return PSA_SUCCESS; - } -#endif /* MBEDTLS_PSA_CRYPTO_BUILTIN_KEYS */ - *key_buffer_size = mbedtls_test_size_function(key_type, key_bits); - return (*key_buffer_size != 0) ? - PSA_SUCCESS : PSA_ERROR_NOT_SUPPORTED; -#endif /* PSA_CRYPTO_DRIVER_TEST */ - - default: - (void) key_type; - (void) key_bits; - return PSA_ERROR_NOT_SUPPORTED; - } -} - -psa_status_t psa_driver_wrapper_generate_key( - const psa_key_attributes_t *attributes, - uint8_t *key_buffer, size_t key_buffer_size, size_t *key_buffer_length) -{ - psa_status_t status = PSA_ERROR_CORRUPTION_DETECTED; - psa_key_location_t location = - PSA_KEY_LIFETIME_GET_LOCATION(attributes->core.lifetime); - - /* Try dynamically-registered SE interface first */ -#if defined(MBEDTLS_PSA_CRYPTO_SE_C) - const psa_drv_se_t *drv; - psa_drv_se_context_t *drv_context; - - if (psa_get_se_driver(attributes->core.lifetime, &drv, &drv_context)) { - size_t pubkey_length = 0; /* We don't support this feature yet */ - if (drv->key_management == NULL || - drv->key_management->p_generate == NULL) { - /* Key is defined as being in SE, but we have no way to generate it */ - return PSA_ERROR_NOT_SUPPORTED; - } - return drv->key_management->p_generate( - drv_context, - *((psa_key_slot_number_t *) key_buffer), - attributes, NULL, 0, &pubkey_length); - } -#endif /* MBEDTLS_PSA_CRYPTO_SE_C */ - - switch (location) { - case PSA_KEY_LOCATION_LOCAL_STORAGE: -#if defined(PSA_CRYPTO_ACCELERATOR_DRIVER_PRESENT) - /* Transparent drivers are limited to generating asymmetric keys */ - if (PSA_KEY_TYPE_IS_ASYMMETRIC(attributes->core.type)) { - /* Cycle through all known transparent accelerators */ -#if defined(PSA_CRYPTO_DRIVER_TEST) - status = mbedtls_test_transparent_generate_key( - attributes, key_buffer, key_buffer_size, - key_buffer_length); - /* Declared with fallback == true */ - if (status != PSA_ERROR_NOT_SUPPORTED) { - break; - } -#endif /* PSA_CRYPTO_DRIVER_TEST */ - } -#endif /* PSA_CRYPTO_ACCELERATOR_DRIVER_PRESENT */ - - /* Software fallback */ - status = psa_generate_key_internal( - attributes, key_buffer, key_buffer_size, key_buffer_length); - break; - - /* Add cases for opaque driver here */ -#if defined(PSA_CRYPTO_ACCELERATOR_DRIVER_PRESENT) -#if defined(PSA_CRYPTO_DRIVER_TEST) - case PSA_CRYPTO_TEST_DRIVER_LOCATION: - status = mbedtls_test_opaque_generate_key( - attributes, key_buffer, key_buffer_size, key_buffer_length); - break; -#endif /* PSA_CRYPTO_DRIVER_TEST */ -#endif /* PSA_CRYPTO_ACCELERATOR_DRIVER_PRESENT */ - - default: - /* Key is declared with a lifetime not known to us */ - status = PSA_ERROR_INVALID_ARGUMENT; - break; - } - - return status; -} - -psa_status_t psa_driver_wrapper_import_key( - const psa_key_attributes_t *attributes, - const uint8_t *data, - size_t data_length, - uint8_t *key_buffer, - size_t key_buffer_size, - size_t *key_buffer_length, - size_t *bits) -{ - psa_status_t status = PSA_ERROR_CORRUPTION_DETECTED; - psa_key_location_t location = PSA_KEY_LIFETIME_GET_LOCATION( - psa_get_key_lifetime(attributes)); - - /* Try dynamically-registered SE interface first */ -#if defined(MBEDTLS_PSA_CRYPTO_SE_C) - const psa_drv_se_t *drv; - psa_drv_se_context_t *drv_context; - - if (psa_get_se_driver(attributes->core.lifetime, &drv, &drv_context)) { - if (drv->key_management == NULL || - drv->key_management->p_import == NULL) { - return PSA_ERROR_NOT_SUPPORTED; - } - - /* The driver should set the number of key bits, however in - * case it doesn't, we initialize bits to an invalid value. */ - *bits = PSA_MAX_KEY_BITS + 1; - status = drv->key_management->p_import( - drv_context, - *((psa_key_slot_number_t *) key_buffer), - attributes, data, data_length, bits); - - if (status != PSA_SUCCESS) { - return status; - } - - if ((*bits) > PSA_MAX_KEY_BITS) { - return PSA_ERROR_NOT_SUPPORTED; - } - - return PSA_SUCCESS; - } -#endif /* MBEDTLS_PSA_CRYPTO_SE_C */ - - switch (location) { - case PSA_KEY_LOCATION_LOCAL_STORAGE: - /* Key is stored in the slot in export representation, so - * cycle through all known transparent accelerators */ -#if defined(PSA_CRYPTO_ACCELERATOR_DRIVER_PRESENT) -#if defined(PSA_CRYPTO_DRIVER_TEST) - status = mbedtls_test_transparent_import_key( - attributes, - data, data_length, - key_buffer, key_buffer_size, - key_buffer_length, bits); - /* Declared with fallback == true */ - if (status != PSA_ERROR_NOT_SUPPORTED) { - return status; - } -#endif /* PSA_CRYPTO_DRIVER_TEST */ -#endif /* PSA_CRYPTO_ACCELERATOR_DRIVER_PRESENT */ - /* Fell through, meaning no accelerator supports this operation */ - return psa_import_key_into_slot(attributes, - data, data_length, - key_buffer, key_buffer_size, - key_buffer_length, bits); - - default: - /* Importing a key with external storage in not yet supported. - * Return in error indicating that the lifetime is not valid. */ - (void) status; - return PSA_ERROR_INVALID_ARGUMENT; - } - -} - -psa_status_t psa_driver_wrapper_export_key( - const psa_key_attributes_t *attributes, - const uint8_t *key_buffer, size_t key_buffer_size, - uint8_t *data, size_t data_size, size_t *data_length) - -{ - psa_status_t status = PSA_ERROR_INVALID_ARGUMENT; - psa_key_location_t location = PSA_KEY_LIFETIME_GET_LOCATION( - psa_get_key_lifetime(attributes)); - - /* Try dynamically-registered SE interface first */ -#if defined(MBEDTLS_PSA_CRYPTO_SE_C) - const psa_drv_se_t *drv; - psa_drv_se_context_t *drv_context; - - if (psa_get_se_driver(attributes->core.lifetime, &drv, &drv_context)) { - if ((drv->key_management == NULL) || - (drv->key_management->p_export == NULL)) { - return PSA_ERROR_NOT_SUPPORTED; - } - - return drv->key_management->p_export( - drv_context, - *((psa_key_slot_number_t *) key_buffer), - data, data_size, data_length); - } -#endif /* MBEDTLS_PSA_CRYPTO_SE_C */ - - switch (location) { - case PSA_KEY_LOCATION_LOCAL_STORAGE: - return psa_export_key_internal(attributes, - key_buffer, - key_buffer_size, - data, - data_size, - data_length); - - /* Add cases for opaque driver here */ -#if defined(PSA_CRYPTO_ACCELERATOR_DRIVER_PRESENT) -#if defined(PSA_CRYPTO_DRIVER_TEST) - case PSA_CRYPTO_TEST_DRIVER_LOCATION: - return mbedtls_test_opaque_export_key(attributes, - key_buffer, - key_buffer_size, - data, - data_size, - data_length); -#endif /* PSA_CRYPTO_DRIVER_TEST */ -#endif /* PSA_CRYPTO_ACCELERATOR_DRIVER_PRESENT */ - default: - /* Key is declared with a lifetime not known to us */ - return status; - } -} - -psa_status_t psa_driver_wrapper_export_public_key( - const psa_key_attributes_t *attributes, - const uint8_t *key_buffer, size_t key_buffer_size, - uint8_t *data, size_t data_size, size_t *data_length) - -{ - psa_status_t status = PSA_ERROR_INVALID_ARGUMENT; - psa_key_location_t location = PSA_KEY_LIFETIME_GET_LOCATION( - psa_get_key_lifetime(attributes)); - - /* Try dynamically-registered SE interface first */ -#if defined(MBEDTLS_PSA_CRYPTO_SE_C) - const psa_drv_se_t *drv; - psa_drv_se_context_t *drv_context; - - if (psa_get_se_driver(attributes->core.lifetime, &drv, &drv_context)) { - if ((drv->key_management == NULL) || - (drv->key_management->p_export_public == NULL)) { - return PSA_ERROR_NOT_SUPPORTED; - } - - return drv->key_management->p_export_public( - drv_context, - *((psa_key_slot_number_t *) key_buffer), - data, data_size, data_length); - } -#endif /* MBEDTLS_PSA_CRYPTO_SE_C */ - - switch (location) { - case PSA_KEY_LOCATION_LOCAL_STORAGE: - /* Key is stored in the slot in export representation, so - * cycle through all known transparent accelerators */ -#if defined(PSA_CRYPTO_ACCELERATOR_DRIVER_PRESENT) -#if defined(PSA_CRYPTO_DRIVER_TEST) - status = mbedtls_test_transparent_export_public_key( - attributes, - key_buffer, - key_buffer_size, - data, - data_size, - data_length); - /* Declared with fallback == true */ - if (status != PSA_ERROR_NOT_SUPPORTED) { - return status; - } -#endif /* PSA_CRYPTO_DRIVER_TEST */ -#endif /* PSA_CRYPTO_ACCELERATOR_DRIVER_PRESENT */ - /* Fell through, meaning no accelerator supports this operation */ - return psa_export_public_key_internal(attributes, - key_buffer, - key_buffer_size, - data, - data_size, - data_length); - - /* Add cases for opaque driver here */ -#if defined(PSA_CRYPTO_ACCELERATOR_DRIVER_PRESENT) -#if defined(PSA_CRYPTO_DRIVER_TEST) - case PSA_CRYPTO_TEST_DRIVER_LOCATION: - return mbedtls_test_opaque_export_public_key(attributes, - key_buffer, - key_buffer_size, - data, - data_size, - data_length); -#endif /* PSA_CRYPTO_DRIVER_TEST */ -#endif /* PSA_CRYPTO_ACCELERATOR_DRIVER_PRESENT */ - default: - /* Key is declared with a lifetime not known to us */ - return status; - } -} - -psa_status_t psa_driver_wrapper_get_builtin_key( - psa_drv_slot_number_t slot_number, - psa_key_attributes_t *attributes, - uint8_t *key_buffer, size_t key_buffer_size, size_t *key_buffer_length) -{ - psa_key_location_t location = PSA_KEY_LIFETIME_GET_LOCATION(attributes->core.lifetime); - switch (location) { -#if defined(PSA_CRYPTO_DRIVER_TEST) - case PSA_CRYPTO_TEST_DRIVER_LOCATION: - return mbedtls_test_opaque_get_builtin_key( - slot_number, - attributes, - key_buffer, key_buffer_size, key_buffer_length); -#endif /* PSA_CRYPTO_DRIVER_TEST */ - default: - (void) slot_number; - (void) key_buffer; - (void) key_buffer_size; - (void) key_buffer_length; - return PSA_ERROR_DOES_NOT_EXIST; - } -} - -/* - * Cipher functions - */ -psa_status_t psa_driver_wrapper_cipher_encrypt( - const psa_key_attributes_t *attributes, - const uint8_t *key_buffer, - size_t key_buffer_size, - psa_algorithm_t alg, - const uint8_t *iv, - size_t iv_length, - const uint8_t *input, - size_t input_length, - uint8_t *output, - size_t output_size, - size_t *output_length) -{ - psa_status_t status = PSA_ERROR_CORRUPTION_DETECTED; - psa_key_location_t location = - PSA_KEY_LIFETIME_GET_LOCATION(attributes->core.lifetime); - - switch (location) { - case PSA_KEY_LOCATION_LOCAL_STORAGE: - /* Key is stored in the slot in export representation, so - * cycle through all known transparent accelerators */ -#if defined(PSA_CRYPTO_ACCELERATOR_DRIVER_PRESENT) -#if defined(PSA_CRYPTO_DRIVER_TEST) - status = mbedtls_test_transparent_cipher_encrypt(attributes, - key_buffer, - key_buffer_size, - alg, - iv, - iv_length, - input, - input_length, - output, - output_size, - output_length); - /* Declared with fallback == true */ - if (status != PSA_ERROR_NOT_SUPPORTED) { - return status; - } -#endif /* PSA_CRYPTO_DRIVER_TEST */ -#endif /* PSA_CRYPTO_ACCELERATOR_DRIVER_PRESENT */ - -#if defined(MBEDTLS_PSA_BUILTIN_CIPHER) - return mbedtls_psa_cipher_encrypt(attributes, - key_buffer, - key_buffer_size, - alg, - iv, - iv_length, - input, - input_length, - output, - output_size, - output_length); -#else - return PSA_ERROR_NOT_SUPPORTED; -#endif /* MBEDTLS_PSA_BUILTIN_CIPHER */ - - /* Add cases for opaque driver here */ -#if defined(PSA_CRYPTO_ACCELERATOR_DRIVER_PRESENT) -#if defined(PSA_CRYPTO_DRIVER_TEST) - case PSA_CRYPTO_TEST_DRIVER_LOCATION: - return mbedtls_test_opaque_cipher_encrypt(attributes, - key_buffer, - key_buffer_size, - alg, - iv, - iv_length, - input, - input_length, - output, - output_size, - output_length); -#endif /* PSA_CRYPTO_DRIVER_TEST */ -#endif /* PSA_CRYPTO_ACCELERATOR_DRIVER_PRESENT */ - - default: - /* Key is declared with a lifetime not known to us */ - (void) status; - (void) key_buffer; - (void) key_buffer_size; - (void) alg; - (void) iv; - (void) iv_length; - (void) input; - (void) input_length; - (void) output; - (void) output_size; - (void) output_length; - return PSA_ERROR_INVALID_ARGUMENT; - } -} - -psa_status_t psa_driver_wrapper_cipher_decrypt( - const psa_key_attributes_t *attributes, - const uint8_t *key_buffer, - size_t key_buffer_size, - psa_algorithm_t alg, - const uint8_t *input, - size_t input_length, - uint8_t *output, - size_t output_size, - size_t *output_length) -{ - psa_status_t status = PSA_ERROR_CORRUPTION_DETECTED; - psa_key_location_t location = - PSA_KEY_LIFETIME_GET_LOCATION(attributes->core.lifetime); - - switch (location) { - case PSA_KEY_LOCATION_LOCAL_STORAGE: - /* Key is stored in the slot in export representation, so - * cycle through all known transparent accelerators */ -#if defined(PSA_CRYPTO_ACCELERATOR_DRIVER_PRESENT) -#if defined(PSA_CRYPTO_DRIVER_TEST) - status = mbedtls_test_transparent_cipher_decrypt(attributes, - key_buffer, - key_buffer_size, - alg, - input, - input_length, - output, - output_size, - output_length); - /* Declared with fallback == true */ - if (status != PSA_ERROR_NOT_SUPPORTED) { - return status; - } -#endif /* PSA_CRYPTO_DRIVER_TEST */ -#endif /* PSA_CRYPTO_ACCELERATOR_DRIVER_PRESENT */ - -#if defined(MBEDTLS_PSA_BUILTIN_CIPHER) - return mbedtls_psa_cipher_decrypt(attributes, - key_buffer, - key_buffer_size, - alg, - input, - input_length, - output, - output_size, - output_length); -#else - return PSA_ERROR_NOT_SUPPORTED; -#endif /* MBEDTLS_PSA_BUILTIN_CIPHER */ - - /* Add cases for opaque driver here */ -#if defined(PSA_CRYPTO_ACCELERATOR_DRIVER_PRESENT) -#if defined(PSA_CRYPTO_DRIVER_TEST) - case PSA_CRYPTO_TEST_DRIVER_LOCATION: - return mbedtls_test_opaque_cipher_decrypt(attributes, - key_buffer, - key_buffer_size, - alg, - input, - input_length, - output, - output_size, - output_length); -#endif /* PSA_CRYPTO_DRIVER_TEST */ -#endif /* PSA_CRYPTO_ACCELERATOR_DRIVER_PRESENT */ - - default: - /* Key is declared with a lifetime not known to us */ - (void) status; - (void) key_buffer; - (void) key_buffer_size; - (void) alg; - (void) input; - (void) input_length; - (void) output; - (void) output_size; - (void) output_length; - return PSA_ERROR_INVALID_ARGUMENT; - } -} - -psa_status_t psa_driver_wrapper_cipher_encrypt_setup( - psa_cipher_operation_t *operation, - const psa_key_attributes_t *attributes, - const uint8_t *key_buffer, size_t key_buffer_size, - psa_algorithm_t alg) -{ - psa_status_t status = PSA_ERROR_CORRUPTION_DETECTED; - psa_key_location_t location = - PSA_KEY_LIFETIME_GET_LOCATION(attributes->core.lifetime); - - switch (location) { - case PSA_KEY_LOCATION_LOCAL_STORAGE: - /* Key is stored in the slot in export representation, so - * cycle through all known transparent accelerators */ -#if defined(PSA_CRYPTO_ACCELERATOR_DRIVER_PRESENT) -#if defined(PSA_CRYPTO_DRIVER_TEST) - status = mbedtls_test_transparent_cipher_encrypt_setup( - &operation->ctx.transparent_test_driver_ctx, - attributes, - key_buffer, - key_buffer_size, - alg); - /* Declared with fallback == true */ - if (status == PSA_SUCCESS) { - operation->id = PSA_CRYPTO_TRANSPARENT_TEST_DRIVER_ID; - } - - if (status != PSA_ERROR_NOT_SUPPORTED) { - return status; - } -#endif /* PSA_CRYPTO_DRIVER_TEST */ -#endif /* PSA_CRYPTO_ACCELERATOR_DRIVER_PRESENT */ -#if defined(MBEDTLS_PSA_BUILTIN_CIPHER) - /* Fell through, meaning no accelerator supports this operation */ - status = mbedtls_psa_cipher_encrypt_setup(&operation->ctx.mbedtls_ctx, - attributes, - key_buffer, - key_buffer_size, - alg); - if (status == PSA_SUCCESS) { - operation->id = PSA_CRYPTO_MBED_TLS_DRIVER_ID; - } - - if (status != PSA_ERROR_NOT_SUPPORTED) { - return status; - } -#endif /* MBEDTLS_PSA_BUILTIN_CIPHER */ - return PSA_ERROR_NOT_SUPPORTED; - - /* Add cases for opaque driver here */ -#if defined(PSA_CRYPTO_ACCELERATOR_DRIVER_PRESENT) -#if defined(PSA_CRYPTO_DRIVER_TEST) - case PSA_CRYPTO_TEST_DRIVER_LOCATION: - status = mbedtls_test_opaque_cipher_encrypt_setup( - &operation->ctx.opaque_test_driver_ctx, - attributes, - key_buffer, key_buffer_size, - alg); - - if (status == PSA_SUCCESS) { - operation->id = PSA_CRYPTO_OPAQUE_TEST_DRIVER_ID; - } - - return status; -#endif /* PSA_CRYPTO_DRIVER_TEST */ -#endif /* PSA_CRYPTO_ACCELERATOR_DRIVER_PRESENT */ - default: - /* Key is declared with a lifetime not known to us */ - (void) status; - (void) operation; - (void) key_buffer; - (void) key_buffer_size; - (void) alg; - return PSA_ERROR_INVALID_ARGUMENT; - } -} - -psa_status_t psa_driver_wrapper_cipher_decrypt_setup( - psa_cipher_operation_t *operation, - const psa_key_attributes_t *attributes, - const uint8_t *key_buffer, size_t key_buffer_size, - psa_algorithm_t alg) -{ - psa_status_t status = PSA_ERROR_INVALID_ARGUMENT; - psa_key_location_t location = - PSA_KEY_LIFETIME_GET_LOCATION(attributes->core.lifetime); - - switch (location) { - case PSA_KEY_LOCATION_LOCAL_STORAGE: - /* Key is stored in the slot in export representation, so - * cycle through all known transparent accelerators */ -#if defined(PSA_CRYPTO_ACCELERATOR_DRIVER_PRESENT) -#if defined(PSA_CRYPTO_DRIVER_TEST) - status = mbedtls_test_transparent_cipher_decrypt_setup( - &operation->ctx.transparent_test_driver_ctx, - attributes, - key_buffer, - key_buffer_size, - alg); - /* Declared with fallback == true */ - if (status == PSA_SUCCESS) { - operation->id = PSA_CRYPTO_TRANSPARENT_TEST_DRIVER_ID; - } - - if (status != PSA_ERROR_NOT_SUPPORTED) { - return status; - } -#endif /* PSA_CRYPTO_DRIVER_TEST */ -#endif /* PSA_CRYPTO_ACCELERATOR_DRIVER_PRESENT */ -#if defined(MBEDTLS_PSA_BUILTIN_CIPHER) - /* Fell through, meaning no accelerator supports this operation */ - status = mbedtls_psa_cipher_decrypt_setup(&operation->ctx.mbedtls_ctx, - attributes, - key_buffer, - key_buffer_size, - alg); - if (status == PSA_SUCCESS) { - operation->id = PSA_CRYPTO_MBED_TLS_DRIVER_ID; - } - - return status; -#else /* MBEDTLS_PSA_BUILTIN_CIPHER */ - return PSA_ERROR_NOT_SUPPORTED; -#endif /* MBEDTLS_PSA_BUILTIN_CIPHER */ - - /* Add cases for opaque driver here */ -#if defined(PSA_CRYPTO_ACCELERATOR_DRIVER_PRESENT) -#if defined(PSA_CRYPTO_DRIVER_TEST) - case PSA_CRYPTO_TEST_DRIVER_LOCATION: - status = mbedtls_test_opaque_cipher_decrypt_setup( - &operation->ctx.opaque_test_driver_ctx, - attributes, - key_buffer, key_buffer_size, - alg); - - if (status == PSA_SUCCESS) { - operation->id = PSA_CRYPTO_OPAQUE_TEST_DRIVER_ID; - } - - return status; -#endif /* PSA_CRYPTO_DRIVER_TEST */ -#endif /* PSA_CRYPTO_ACCELERATOR_DRIVER_PRESENT */ - default: - /* Key is declared with a lifetime not known to us */ - (void) status; - (void) operation; - (void) key_buffer; - (void) key_buffer_size; - (void) alg; - return PSA_ERROR_INVALID_ARGUMENT; - } -} - -psa_status_t psa_driver_wrapper_cipher_set_iv( - psa_cipher_operation_t *operation, - const uint8_t *iv, - size_t iv_length) -{ - switch (operation->id) { -#if defined(MBEDTLS_PSA_BUILTIN_CIPHER) - case PSA_CRYPTO_MBED_TLS_DRIVER_ID: - return mbedtls_psa_cipher_set_iv(&operation->ctx.mbedtls_ctx, - iv, - iv_length); -#endif /* MBEDTLS_PSA_BUILTIN_CIPHER */ - -#if defined(PSA_CRYPTO_ACCELERATOR_DRIVER_PRESENT) -#if defined(PSA_CRYPTO_DRIVER_TEST) - case PSA_CRYPTO_TRANSPARENT_TEST_DRIVER_ID: - return mbedtls_test_transparent_cipher_set_iv( - &operation->ctx.transparent_test_driver_ctx, - iv, iv_length); - - case PSA_CRYPTO_OPAQUE_TEST_DRIVER_ID: - return mbedtls_test_opaque_cipher_set_iv( - &operation->ctx.opaque_test_driver_ctx, - iv, iv_length); -#endif /* PSA_CRYPTO_DRIVER_TEST */ -#endif /* PSA_CRYPTO_ACCELERATOR_DRIVER_PRESENT */ - } - - (void) iv; - (void) iv_length; - - return PSA_ERROR_INVALID_ARGUMENT; -} - -psa_status_t psa_driver_wrapper_cipher_update( - psa_cipher_operation_t *operation, - const uint8_t *input, - size_t input_length, - uint8_t *output, - size_t output_size, - size_t *output_length) -{ - switch (operation->id) { -#if defined(MBEDTLS_PSA_BUILTIN_CIPHER) - case PSA_CRYPTO_MBED_TLS_DRIVER_ID: - return mbedtls_psa_cipher_update(&operation->ctx.mbedtls_ctx, - input, - input_length, - output, - output_size, - output_length); -#endif /* MBEDTLS_PSA_BUILTIN_CIPHER */ - -#if defined(PSA_CRYPTO_ACCELERATOR_DRIVER_PRESENT) -#if defined(PSA_CRYPTO_DRIVER_TEST) - case PSA_CRYPTO_TRANSPARENT_TEST_DRIVER_ID: - return mbedtls_test_transparent_cipher_update( - &operation->ctx.transparent_test_driver_ctx, - input, input_length, - output, output_size, output_length); - - case PSA_CRYPTO_OPAQUE_TEST_DRIVER_ID: - return mbedtls_test_opaque_cipher_update( - &operation->ctx.opaque_test_driver_ctx, - input, input_length, - output, output_size, output_length); -#endif /* PSA_CRYPTO_DRIVER_TEST */ -#endif /* PSA_CRYPTO_ACCELERATOR_DRIVER_PRESENT */ - } - - (void) input; - (void) input_length; - (void) output; - (void) output_size; - (void) output_length; - - return PSA_ERROR_INVALID_ARGUMENT; -} - -psa_status_t psa_driver_wrapper_cipher_finish( - psa_cipher_operation_t *operation, - uint8_t *output, - size_t output_size, - size_t *output_length) -{ - switch (operation->id) { -#if defined(MBEDTLS_PSA_BUILTIN_CIPHER) - case PSA_CRYPTO_MBED_TLS_DRIVER_ID: - return mbedtls_psa_cipher_finish(&operation->ctx.mbedtls_ctx, - output, - output_size, - output_length); -#endif /* MBEDTLS_PSA_BUILTIN_CIPHER */ - -#if defined(PSA_CRYPTO_ACCELERATOR_DRIVER_PRESENT) -#if defined(PSA_CRYPTO_DRIVER_TEST) - case PSA_CRYPTO_TRANSPARENT_TEST_DRIVER_ID: - return mbedtls_test_transparent_cipher_finish( - &operation->ctx.transparent_test_driver_ctx, - output, output_size, output_length); - - case PSA_CRYPTO_OPAQUE_TEST_DRIVER_ID: - return mbedtls_test_opaque_cipher_finish( - &operation->ctx.opaque_test_driver_ctx, - output, output_size, output_length); -#endif /* PSA_CRYPTO_DRIVER_TEST */ -#endif /* PSA_CRYPTO_ACCELERATOR_DRIVER_PRESENT */ - } - - (void) output; - (void) output_size; - (void) output_length; - - return PSA_ERROR_INVALID_ARGUMENT; -} - -psa_status_t psa_driver_wrapper_cipher_abort( - psa_cipher_operation_t *operation) -{ - psa_status_t status = PSA_ERROR_CORRUPTION_DETECTED; - - switch (operation->id) { -#if defined(MBEDTLS_PSA_BUILTIN_CIPHER) - case PSA_CRYPTO_MBED_TLS_DRIVER_ID: - return mbedtls_psa_cipher_abort(&operation->ctx.mbedtls_ctx); -#endif /* MBEDTLS_PSA_BUILTIN_CIPHER */ - -#if defined(PSA_CRYPTO_ACCELERATOR_DRIVER_PRESENT) -#if defined(PSA_CRYPTO_DRIVER_TEST) - case PSA_CRYPTO_TRANSPARENT_TEST_DRIVER_ID: - status = mbedtls_test_transparent_cipher_abort( - &operation->ctx.transparent_test_driver_ctx); - mbedtls_platform_zeroize( - &operation->ctx.transparent_test_driver_ctx, - sizeof(operation->ctx.transparent_test_driver_ctx)); - return status; - - case PSA_CRYPTO_OPAQUE_TEST_DRIVER_ID: - status = mbedtls_test_opaque_cipher_abort( - &operation->ctx.opaque_test_driver_ctx); - mbedtls_platform_zeroize( - &operation->ctx.opaque_test_driver_ctx, - sizeof(operation->ctx.opaque_test_driver_ctx)); - return status; -#endif /* PSA_CRYPTO_DRIVER_TEST */ -#endif /* PSA_CRYPTO_ACCELERATOR_DRIVER_PRESENT */ - } - - (void) status; - return PSA_ERROR_INVALID_ARGUMENT; -} - -/* - * Hashing functions - */ -psa_status_t psa_driver_wrapper_hash_compute( - psa_algorithm_t alg, - const uint8_t *input, - size_t input_length, - uint8_t *hash, - size_t hash_size, - size_t *hash_length) -{ - psa_status_t status = PSA_ERROR_CORRUPTION_DETECTED; - - /* Try accelerators first */ -#if defined(PSA_CRYPTO_DRIVER_TEST) - status = mbedtls_test_transparent_hash_compute( - alg, input, input_length, hash, hash_size, hash_length); - if (status != PSA_ERROR_NOT_SUPPORTED) { - return status; - } -#endif - - /* If software fallback is compiled in, try fallback */ -#if defined(MBEDTLS_PSA_BUILTIN_HASH) - status = mbedtls_psa_hash_compute(alg, input, input_length, - hash, hash_size, hash_length); - if (status != PSA_ERROR_NOT_SUPPORTED) { - return status; - } -#endif - (void) status; - (void) alg; - (void) input; - (void) input_length; - (void) hash; - (void) hash_size; - (void) hash_length; - - return PSA_ERROR_NOT_SUPPORTED; -} - -psa_status_t psa_driver_wrapper_hash_setup( - psa_hash_operation_t *operation, - psa_algorithm_t alg) -{ - psa_status_t status = PSA_ERROR_CORRUPTION_DETECTED; - - /* Try setup on accelerators first */ -#if defined(PSA_CRYPTO_DRIVER_TEST) - status = mbedtls_test_transparent_hash_setup( - &operation->ctx.test_driver_ctx, alg); - if (status == PSA_SUCCESS) { - operation->id = PSA_CRYPTO_TRANSPARENT_TEST_DRIVER_ID; - } - - if (status != PSA_ERROR_NOT_SUPPORTED) { - return status; - } -#endif - - /* If software fallback is compiled in, try fallback */ -#if defined(MBEDTLS_PSA_BUILTIN_HASH) - status = mbedtls_psa_hash_setup(&operation->ctx.mbedtls_ctx, alg); - if (status == PSA_SUCCESS) { - operation->id = PSA_CRYPTO_MBED_TLS_DRIVER_ID; - } - - if (status != PSA_ERROR_NOT_SUPPORTED) { - return status; - } -#endif - /* Nothing left to try if we fall through here */ - (void) status; - (void) operation; - (void) alg; - return PSA_ERROR_NOT_SUPPORTED; -} - -psa_status_t psa_driver_wrapper_hash_clone( - const psa_hash_operation_t *source_operation, - psa_hash_operation_t *target_operation) -{ - switch (source_operation->id) { -#if defined(MBEDTLS_PSA_BUILTIN_HASH) - case PSA_CRYPTO_MBED_TLS_DRIVER_ID: - target_operation->id = PSA_CRYPTO_MBED_TLS_DRIVER_ID; - return mbedtls_psa_hash_clone(&source_operation->ctx.mbedtls_ctx, - &target_operation->ctx.mbedtls_ctx); -#endif -#if defined(PSA_CRYPTO_DRIVER_TEST) - case PSA_CRYPTO_TRANSPARENT_TEST_DRIVER_ID: - target_operation->id = PSA_CRYPTO_TRANSPARENT_TEST_DRIVER_ID; - return mbedtls_test_transparent_hash_clone( - &source_operation->ctx.test_driver_ctx, - &target_operation->ctx.test_driver_ctx); -#endif - default: - (void) target_operation; - return PSA_ERROR_BAD_STATE; - } -} - -psa_status_t psa_driver_wrapper_hash_update( - psa_hash_operation_t *operation, - const uint8_t *input, - size_t input_length) -{ - switch (operation->id) { -#if defined(MBEDTLS_PSA_BUILTIN_HASH) - case PSA_CRYPTO_MBED_TLS_DRIVER_ID: - return mbedtls_psa_hash_update(&operation->ctx.mbedtls_ctx, - input, input_length); -#endif -#if defined(PSA_CRYPTO_DRIVER_TEST) - case PSA_CRYPTO_TRANSPARENT_TEST_DRIVER_ID: - return mbedtls_test_transparent_hash_update( - &operation->ctx.test_driver_ctx, - input, input_length); -#endif - default: - (void) input; - (void) input_length; - return PSA_ERROR_BAD_STATE; - } -} - -psa_status_t psa_driver_wrapper_hash_finish( - psa_hash_operation_t *operation, - uint8_t *hash, - size_t hash_size, - size_t *hash_length) -{ - switch (operation->id) { -#if defined(MBEDTLS_PSA_BUILTIN_HASH) - case PSA_CRYPTO_MBED_TLS_DRIVER_ID: - return mbedtls_psa_hash_finish(&operation->ctx.mbedtls_ctx, - hash, hash_size, hash_length); -#endif -#if defined(PSA_CRYPTO_DRIVER_TEST) - case PSA_CRYPTO_TRANSPARENT_TEST_DRIVER_ID: - return mbedtls_test_transparent_hash_finish( - &operation->ctx.test_driver_ctx, - hash, hash_size, hash_length); -#endif - default: - (void) hash; - (void) hash_size; - (void) hash_length; - return PSA_ERROR_BAD_STATE; - } -} - -psa_status_t psa_driver_wrapper_hash_abort( - psa_hash_operation_t *operation) -{ - switch (operation->id) { -#if defined(MBEDTLS_PSA_BUILTIN_HASH) - case PSA_CRYPTO_MBED_TLS_DRIVER_ID: - return mbedtls_psa_hash_abort(&operation->ctx.mbedtls_ctx); -#endif -#if defined(PSA_CRYPTO_DRIVER_TEST) - case PSA_CRYPTO_TRANSPARENT_TEST_DRIVER_ID: - return mbedtls_test_transparent_hash_abort( - &operation->ctx.test_driver_ctx); -#endif - default: - return PSA_ERROR_BAD_STATE; - } -} - -psa_status_t psa_driver_wrapper_aead_encrypt( - const psa_key_attributes_t *attributes, - const uint8_t *key_buffer, size_t key_buffer_size, - psa_algorithm_t alg, - const uint8_t *nonce, size_t nonce_length, - const uint8_t *additional_data, size_t additional_data_length, - const uint8_t *plaintext, size_t plaintext_length, - uint8_t *ciphertext, size_t ciphertext_size, size_t *ciphertext_length) -{ - psa_status_t status = PSA_ERROR_CORRUPTION_DETECTED; - psa_key_location_t location = - PSA_KEY_LIFETIME_GET_LOCATION(attributes->core.lifetime); - - switch (location) { - case PSA_KEY_LOCATION_LOCAL_STORAGE: - /* Key is stored in the slot in export representation, so - * cycle through all known transparent accelerators */ - -#if defined(PSA_CRYPTO_ACCELERATOR_DRIVER_PRESENT) -#if defined(PSA_CRYPTO_DRIVER_TEST) - status = mbedtls_test_transparent_aead_encrypt( - attributes, key_buffer, key_buffer_size, - alg, - nonce, nonce_length, - additional_data, additional_data_length, - plaintext, plaintext_length, - ciphertext, ciphertext_size, ciphertext_length); - /* Declared with fallback == true */ - if (status != PSA_ERROR_NOT_SUPPORTED) { - return status; - } -#endif /* PSA_CRYPTO_DRIVER_TEST */ -#endif /* PSA_CRYPTO_ACCELERATOR_DRIVER_PRESENT */ - - /* Fell through, meaning no accelerator supports this operation */ - return mbedtls_psa_aead_encrypt( - attributes, key_buffer, key_buffer_size, - alg, - nonce, nonce_length, - additional_data, additional_data_length, - plaintext, plaintext_length, - ciphertext, ciphertext_size, ciphertext_length); - - /* Add cases for opaque driver here */ - - default: - /* Key is declared with a lifetime not known to us */ - (void) status; - return PSA_ERROR_INVALID_ARGUMENT; - } -} - -psa_status_t psa_driver_wrapper_aead_decrypt( - const psa_key_attributes_t *attributes, - const uint8_t *key_buffer, size_t key_buffer_size, - psa_algorithm_t alg, - const uint8_t *nonce, size_t nonce_length, - const uint8_t *additional_data, size_t additional_data_length, - const uint8_t *ciphertext, size_t ciphertext_length, - uint8_t *plaintext, size_t plaintext_size, size_t *plaintext_length) -{ - psa_status_t status = PSA_ERROR_CORRUPTION_DETECTED; - psa_key_location_t location = - PSA_KEY_LIFETIME_GET_LOCATION(attributes->core.lifetime); - - switch (location) { - case PSA_KEY_LOCATION_LOCAL_STORAGE: - /* Key is stored in the slot in export representation, so - * cycle through all known transparent accelerators */ - -#if defined(PSA_CRYPTO_ACCELERATOR_DRIVER_PRESENT) -#if defined(PSA_CRYPTO_DRIVER_TEST) - status = mbedtls_test_transparent_aead_decrypt( - attributes, key_buffer, key_buffer_size, - alg, - nonce, nonce_length, - additional_data, additional_data_length, - ciphertext, ciphertext_length, - plaintext, plaintext_size, plaintext_length); - /* Declared with fallback == true */ - if (status != PSA_ERROR_NOT_SUPPORTED) { - return status; - } -#endif /* PSA_CRYPTO_DRIVER_TEST */ -#endif /* PSA_CRYPTO_ACCELERATOR_DRIVER_PRESENT */ - - /* Fell through, meaning no accelerator supports this operation */ - return mbedtls_psa_aead_decrypt( - attributes, key_buffer, key_buffer_size, - alg, - nonce, nonce_length, - additional_data, additional_data_length, - ciphertext, ciphertext_length, - plaintext, plaintext_size, plaintext_length); - - /* Add cases for opaque driver here */ - - default: - /* Key is declared with a lifetime not known to us */ - (void) status; - return PSA_ERROR_INVALID_ARGUMENT; - } -} - - -/* - * MAC functions - */ -psa_status_t psa_driver_wrapper_mac_compute( - const psa_key_attributes_t *attributes, - const uint8_t *key_buffer, - size_t key_buffer_size, - psa_algorithm_t alg, - const uint8_t *input, - size_t input_length, - uint8_t *mac, - size_t mac_size, - size_t *mac_length) -{ - psa_status_t status = PSA_ERROR_CORRUPTION_DETECTED; - psa_key_location_t location = - PSA_KEY_LIFETIME_GET_LOCATION(attributes->core.lifetime); - - switch (location) { - case PSA_KEY_LOCATION_LOCAL_STORAGE: - /* Key is stored in the slot in export representation, so - * cycle through all known transparent accelerators */ -#if defined(PSA_CRYPTO_ACCELERATOR_DRIVER_PRESENT) -#if defined(PSA_CRYPTO_DRIVER_TEST) - status = mbedtls_test_transparent_mac_compute( - attributes, key_buffer, key_buffer_size, alg, - input, input_length, - mac, mac_size, mac_length); - /* Declared with fallback == true */ - if (status != PSA_ERROR_NOT_SUPPORTED) { - return status; - } -#endif /* PSA_CRYPTO_DRIVER_TEST */ -#endif /* PSA_CRYPTO_ACCELERATOR_DRIVER_PRESENT */ -#if defined(MBEDTLS_PSA_BUILTIN_MAC) - /* Fell through, meaning no accelerator supports this operation */ - status = mbedtls_psa_mac_compute( - attributes, key_buffer, key_buffer_size, alg, - input, input_length, - mac, mac_size, mac_length); - if (status != PSA_ERROR_NOT_SUPPORTED) { - return status; - } -#endif /* MBEDTLS_PSA_BUILTIN_MAC */ - return PSA_ERROR_NOT_SUPPORTED; - - /* Add cases for opaque driver here */ -#if defined(PSA_CRYPTO_ACCELERATOR_DRIVER_PRESENT) -#if defined(PSA_CRYPTO_DRIVER_TEST) - case PSA_CRYPTO_TEST_DRIVER_LOCATION: - status = mbedtls_test_opaque_mac_compute( - attributes, key_buffer, key_buffer_size, alg, - input, input_length, - mac, mac_size, mac_length); - return status; -#endif /* PSA_CRYPTO_DRIVER_TEST */ -#endif /* PSA_CRYPTO_ACCELERATOR_DRIVER_PRESENT */ - default: - /* Key is declared with a lifetime not known to us */ - (void) key_buffer; - (void) key_buffer_size; - (void) alg; - (void) input; - (void) input_length; - (void) mac; - (void) mac_size; - (void) mac_length; - (void) status; - return PSA_ERROR_INVALID_ARGUMENT; - } -} - -psa_status_t psa_driver_wrapper_mac_sign_setup( - psa_mac_operation_t *operation, - const psa_key_attributes_t *attributes, - const uint8_t *key_buffer, - size_t key_buffer_size, - psa_algorithm_t alg) -{ - psa_status_t status = PSA_ERROR_CORRUPTION_DETECTED; - psa_key_location_t location = - PSA_KEY_LIFETIME_GET_LOCATION(attributes->core.lifetime); - - switch (location) { - case PSA_KEY_LOCATION_LOCAL_STORAGE: - /* Key is stored in the slot in export representation, so - * cycle through all known transparent accelerators */ -#if defined(PSA_CRYPTO_ACCELERATOR_DRIVER_PRESENT) -#if defined(PSA_CRYPTO_DRIVER_TEST) - status = mbedtls_test_transparent_mac_sign_setup( - &operation->ctx.transparent_test_driver_ctx, - attributes, - key_buffer, key_buffer_size, - alg); - /* Declared with fallback == true */ - if (status == PSA_SUCCESS) { - operation->id = PSA_CRYPTO_TRANSPARENT_TEST_DRIVER_ID; - } - - if (status != PSA_ERROR_NOT_SUPPORTED) { - return status; - } -#endif /* PSA_CRYPTO_DRIVER_TEST */ -#endif /* PSA_CRYPTO_ACCELERATOR_DRIVER_PRESENT */ -#if defined(MBEDTLS_PSA_BUILTIN_MAC) - /* Fell through, meaning no accelerator supports this operation */ - status = mbedtls_psa_mac_sign_setup(&operation->ctx.mbedtls_ctx, - attributes, - key_buffer, key_buffer_size, - alg); - if (status == PSA_SUCCESS) { - operation->id = PSA_CRYPTO_MBED_TLS_DRIVER_ID; - } - - if (status != PSA_ERROR_NOT_SUPPORTED) { - return status; - } -#endif /* MBEDTLS_PSA_BUILTIN_MAC */ - return PSA_ERROR_NOT_SUPPORTED; - - /* Add cases for opaque driver here */ -#if defined(PSA_CRYPTO_ACCELERATOR_DRIVER_PRESENT) -#if defined(PSA_CRYPTO_DRIVER_TEST) - case PSA_CRYPTO_TEST_DRIVER_LOCATION: - status = mbedtls_test_opaque_mac_sign_setup( - &operation->ctx.opaque_test_driver_ctx, - attributes, - key_buffer, key_buffer_size, - alg); - - if (status == PSA_SUCCESS) { - operation->id = PSA_CRYPTO_OPAQUE_TEST_DRIVER_ID; - } - - return status; -#endif /* PSA_CRYPTO_DRIVER_TEST */ -#endif /* PSA_CRYPTO_ACCELERATOR_DRIVER_PRESENT */ - default: - /* Key is declared with a lifetime not known to us */ - (void) status; - (void) operation; - (void) key_buffer; - (void) key_buffer_size; - (void) alg; - return PSA_ERROR_INVALID_ARGUMENT; - } -} - -psa_status_t psa_driver_wrapper_mac_verify_setup( - psa_mac_operation_t *operation, - const psa_key_attributes_t *attributes, - const uint8_t *key_buffer, - size_t key_buffer_size, - psa_algorithm_t alg) -{ - psa_status_t status = PSA_ERROR_CORRUPTION_DETECTED; - psa_key_location_t location = - PSA_KEY_LIFETIME_GET_LOCATION(attributes->core.lifetime); - - switch (location) { - case PSA_KEY_LOCATION_LOCAL_STORAGE: - /* Key is stored in the slot in export representation, so - * cycle through all known transparent accelerators */ -#if defined(PSA_CRYPTO_ACCELERATOR_DRIVER_PRESENT) -#if defined(PSA_CRYPTO_DRIVER_TEST) - status = mbedtls_test_transparent_mac_verify_setup( - &operation->ctx.transparent_test_driver_ctx, - attributes, - key_buffer, key_buffer_size, - alg); - /* Declared with fallback == true */ - if (status == PSA_SUCCESS) { - operation->id = PSA_CRYPTO_TRANSPARENT_TEST_DRIVER_ID; - } - - if (status != PSA_ERROR_NOT_SUPPORTED) { - return status; - } -#endif /* PSA_CRYPTO_DRIVER_TEST */ -#endif /* PSA_CRYPTO_ACCELERATOR_DRIVER_PRESENT */ -#if defined(MBEDTLS_PSA_BUILTIN_MAC) - /* Fell through, meaning no accelerator supports this operation */ - status = mbedtls_psa_mac_verify_setup(&operation->ctx.mbedtls_ctx, - attributes, - key_buffer, key_buffer_size, - alg); - if (status == PSA_SUCCESS) { - operation->id = PSA_CRYPTO_MBED_TLS_DRIVER_ID; - } - - if (status != PSA_ERROR_NOT_SUPPORTED) { - return status; - } -#endif /* MBEDTLS_PSA_BUILTIN_MAC */ - return PSA_ERROR_NOT_SUPPORTED; - - /* Add cases for opaque driver here */ -#if defined(PSA_CRYPTO_ACCELERATOR_DRIVER_PRESENT) -#if defined(PSA_CRYPTO_DRIVER_TEST) - case PSA_CRYPTO_TEST_DRIVER_LOCATION: - status = mbedtls_test_opaque_mac_verify_setup( - &operation->ctx.opaque_test_driver_ctx, - attributes, - key_buffer, key_buffer_size, - alg); - - if (status == PSA_SUCCESS) { - operation->id = PSA_CRYPTO_OPAQUE_TEST_DRIVER_ID; - } - - return status; -#endif /* PSA_CRYPTO_DRIVER_TEST */ -#endif /* PSA_CRYPTO_ACCELERATOR_DRIVER_PRESENT */ - default: - /* Key is declared with a lifetime not known to us */ - (void) status; - (void) operation; - (void) key_buffer; - (void) key_buffer_size; - (void) alg; - return PSA_ERROR_INVALID_ARGUMENT; - } -} - -psa_status_t psa_driver_wrapper_mac_update( - psa_mac_operation_t *operation, - const uint8_t *input, - size_t input_length) -{ - switch (operation->id) { -#if defined(MBEDTLS_PSA_BUILTIN_MAC) - case PSA_CRYPTO_MBED_TLS_DRIVER_ID: - return mbedtls_psa_mac_update(&operation->ctx.mbedtls_ctx, - input, input_length); -#endif /* MBEDTLS_PSA_BUILTIN_MAC */ - -#if defined(PSA_CRYPTO_ACCELERATOR_DRIVER_PRESENT) -#if defined(PSA_CRYPTO_DRIVER_TEST) - case PSA_CRYPTO_TRANSPARENT_TEST_DRIVER_ID: - return mbedtls_test_transparent_mac_update( - &operation->ctx.transparent_test_driver_ctx, - input, input_length); - - case PSA_CRYPTO_OPAQUE_TEST_DRIVER_ID: - return mbedtls_test_opaque_mac_update( - &operation->ctx.opaque_test_driver_ctx, - input, input_length); -#endif /* PSA_CRYPTO_DRIVER_TEST */ -#endif /* PSA_CRYPTO_ACCELERATOR_DRIVER_PRESENT */ - default: - (void) input; - (void) input_length; - return PSA_ERROR_INVALID_ARGUMENT; - } -} - -psa_status_t psa_driver_wrapper_mac_sign_finish( - psa_mac_operation_t *operation, - uint8_t *mac, - size_t mac_size, - size_t *mac_length) -{ - switch (operation->id) { -#if defined(MBEDTLS_PSA_BUILTIN_MAC) - case PSA_CRYPTO_MBED_TLS_DRIVER_ID: - return mbedtls_psa_mac_sign_finish(&operation->ctx.mbedtls_ctx, - mac, mac_size, mac_length); -#endif /* MBEDTLS_PSA_BUILTIN_MAC */ - -#if defined(PSA_CRYPTO_ACCELERATOR_DRIVER_PRESENT) -#if defined(PSA_CRYPTO_DRIVER_TEST) - case PSA_CRYPTO_TRANSPARENT_TEST_DRIVER_ID: - return mbedtls_test_transparent_mac_sign_finish( - &operation->ctx.transparent_test_driver_ctx, - mac, mac_size, mac_length); - - case PSA_CRYPTO_OPAQUE_TEST_DRIVER_ID: - return mbedtls_test_opaque_mac_sign_finish( - &operation->ctx.opaque_test_driver_ctx, - mac, mac_size, mac_length); -#endif /* PSA_CRYPTO_DRIVER_TEST */ -#endif /* PSA_CRYPTO_ACCELERATOR_DRIVER_PRESENT */ - default: - (void) mac; - (void) mac_size; - (void) mac_length; - return PSA_ERROR_INVALID_ARGUMENT; - } -} - -psa_status_t psa_driver_wrapper_mac_verify_finish( - psa_mac_operation_t *operation, - const uint8_t *mac, - size_t mac_length) -{ - switch (operation->id) { -#if defined(MBEDTLS_PSA_BUILTIN_MAC) - case PSA_CRYPTO_MBED_TLS_DRIVER_ID: - return mbedtls_psa_mac_verify_finish(&operation->ctx.mbedtls_ctx, - mac, mac_length); -#endif /* MBEDTLS_PSA_BUILTIN_MAC */ - -#if defined(PSA_CRYPTO_ACCELERATOR_DRIVER_PRESENT) -#if defined(PSA_CRYPTO_DRIVER_TEST) - case PSA_CRYPTO_TRANSPARENT_TEST_DRIVER_ID: - return mbedtls_test_transparent_mac_verify_finish( - &operation->ctx.transparent_test_driver_ctx, - mac, mac_length); - - case PSA_CRYPTO_OPAQUE_TEST_DRIVER_ID: - return mbedtls_test_opaque_mac_verify_finish( - &operation->ctx.opaque_test_driver_ctx, - mac, mac_length); -#endif /* PSA_CRYPTO_DRIVER_TEST */ -#endif /* PSA_CRYPTO_ACCELERATOR_DRIVER_PRESENT */ - default: - (void) mac; - (void) mac_length; - return PSA_ERROR_INVALID_ARGUMENT; - } -} - -psa_status_t psa_driver_wrapper_mac_abort( - psa_mac_operation_t *operation) -{ - switch (operation->id) { -#if defined(MBEDTLS_PSA_BUILTIN_MAC) - case PSA_CRYPTO_MBED_TLS_DRIVER_ID: - return mbedtls_psa_mac_abort(&operation->ctx.mbedtls_ctx); -#endif /* MBEDTLS_PSA_BUILTIN_MAC */ - -#if defined(PSA_CRYPTO_ACCELERATOR_DRIVER_PRESENT) -#if defined(PSA_CRYPTO_DRIVER_TEST) - case PSA_CRYPTO_TRANSPARENT_TEST_DRIVER_ID: - return mbedtls_test_transparent_mac_abort( - &operation->ctx.transparent_test_driver_ctx); - case PSA_CRYPTO_OPAQUE_TEST_DRIVER_ID: - return mbedtls_test_opaque_mac_abort( - &operation->ctx.opaque_test_driver_ctx); -#endif /* PSA_CRYPTO_DRIVER_TEST */ -#endif /* PSA_CRYPTO_ACCELERATOR_DRIVER_PRESENT */ - default: - return PSA_ERROR_INVALID_ARGUMENT; - } -} - -#endif /* MBEDTLS_PSA_CRYPTO_C */ diff --git a/vendor/mbedtls/library/psa_crypto_driver_wrappers.h b/vendor/mbedtls/library/psa_crypto_driver_wrappers.h index 9471099de9..ea6aee32eb 100644 --- a/vendor/mbedtls/library/psa_crypto_driver_wrappers.h +++ b/vendor/mbedtls/library/psa_crypto_driver_wrappers.h @@ -1,40 +1,114 @@ /* - * Function signatures for functionality that can be provided by - * cryptographic accelerators. - * Warning: This file will be auto-generated in the future. + * Functions to delegate cryptographic operations to an available + * and appropriate accelerator. + * Warning: This file is now auto-generated. */ /* Copyright The Mbed TLS Contributors - * SPDX-License-Identifier: Apache-2.0 - * - * Licensed under the Apache License, Version 2.0 (the "License"); you may - * not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT - * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. + * SPDX-License-Identifier: Apache-2.0 OR GPL-2.0-or-later */ -#ifndef PSA_CRYPTO_DRIVER_WRAPPERS_H -#define PSA_CRYPTO_DRIVER_WRAPPERS_H -#include "psa/crypto.h" -#include "psa/crypto_driver_common.h" +/* BEGIN-common headers */ +#include "common.h" +#include "psa_crypto_aead.h" +#include "psa_crypto_cipher.h" +#include "psa_crypto_core.h" +#include "psa_crypto_driver_wrappers_no_static.h" +#include "psa_crypto_hash.h" +#include "psa_crypto_mac.h" +#include "psa_crypto_pake.h" +#include "psa_crypto_rsa.h" -/* - * Initialization and termination functions - */ -psa_status_t psa_driver_wrapper_init(void); -void psa_driver_wrapper_free(void); +#include "mbedtls/platform.h" +#include "mbedtls/constant_time.h" +/* END-common headers */ -/* - * Signature functions - */ -psa_status_t psa_driver_wrapper_sign_message( +#if defined(MBEDTLS_PSA_CRYPTO_C) + +/* BEGIN-driver headers */ +/* Headers for mbedtls_test opaque driver */ +#if defined(PSA_CRYPTO_DRIVER_TEST) +#include "test/drivers/test_driver.h" + +#endif +/* Headers for mbedtls_test transparent driver */ +#if defined(PSA_CRYPTO_DRIVER_TEST) +#include "test/drivers/test_driver.h" + +#endif +/* Headers for p256 transparent driver */ +#if defined(MBEDTLS_PSA_P256M_DRIVER_ENABLED) +#include "../3rdparty/p256-m/p256-m_driver_entrypoints.h" + +#endif + +/* END-driver headers */ + +/* Auto-generated values depending on which drivers are registered. + * ID 0 is reserved for unallocated operations. + * ID 1 is reserved for the Mbed TLS software driver. */ +/* BEGIN-driver id definition */ +#define PSA_CRYPTO_MBED_TLS_DRIVER_ID (1) +#define MBEDTLS_TEST_OPAQUE_DRIVER_ID (2) +#define MBEDTLS_TEST_TRANSPARENT_DRIVER_ID (3) +#define P256_TRANSPARENT_DRIVER_ID (4) + +/* END-driver id */ + +/* BEGIN-Common Macro definitions */ + +/* END-Common Macro definitions */ + +/* Support the 'old' SE interface when asked to */ +#if defined(MBEDTLS_PSA_CRYPTO_SE_C) +/* PSA_CRYPTO_DRIVER_PRESENT is defined when either a new-style or old-style + * SE driver is present, to avoid unused argument errors at compile time. */ +#ifndef PSA_CRYPTO_DRIVER_PRESENT +#define PSA_CRYPTO_DRIVER_PRESENT +#endif +#include "psa_crypto_se.h" +#endif + +static inline psa_status_t psa_driver_wrapper_init( void ) +{ + psa_status_t status = PSA_ERROR_CORRUPTION_DETECTED; + +#if defined(MBEDTLS_PSA_CRYPTO_SE_C) + status = psa_init_all_se_drivers( ); + if( status != PSA_SUCCESS ) + return( status ); +#endif + +#if defined(PSA_CRYPTO_DRIVER_TEST) + status = mbedtls_test_transparent_init( ); + if( status != PSA_SUCCESS ) + return( status ); + + status = mbedtls_test_opaque_init( ); + if( status != PSA_SUCCESS ) + return( status ); +#endif + + (void) status; + return( PSA_SUCCESS ); +} + +static inline void psa_driver_wrapper_free( void ) +{ +#if defined(MBEDTLS_PSA_CRYPTO_SE_C) + /* Unregister all secure element drivers, so that we restart from + * a pristine state. */ + psa_unregister_all_se_drivers( ); +#endif /* MBEDTLS_PSA_CRYPTO_SE_C */ + +#if defined(PSA_CRYPTO_DRIVER_TEST) + mbedtls_test_transparent_free( ); + mbedtls_test_opaque_free( ); +#endif +} + +/* Start delegation functions */ +static inline psa_status_t psa_driver_wrapper_sign_message( const psa_key_attributes_t *attributes, const uint8_t *key_buffer, size_t key_buffer_size, @@ -43,9 +117,73 @@ psa_status_t psa_driver_wrapper_sign_message( size_t input_length, uint8_t *signature, size_t signature_size, - size_t *signature_length); + size_t *signature_length ) +{ + psa_status_t status = PSA_ERROR_CORRUPTION_DETECTED; + psa_key_location_t location = + PSA_KEY_LIFETIME_GET_LOCATION( psa_get_key_lifetime(attributes) ); -psa_status_t psa_driver_wrapper_verify_message( + switch( location ) + { + case PSA_KEY_LOCATION_LOCAL_STORAGE: + /* Key is stored in the slot in export representation, so + * cycle through all known transparent accelerators */ +#if defined(PSA_CRYPTO_ACCELERATOR_DRIVER_PRESENT) +#if defined(PSA_CRYPTO_DRIVER_TEST) + status = mbedtls_test_transparent_signature_sign_message( + attributes, + key_buffer, + key_buffer_size, + alg, + input, + input_length, + signature, + signature_size, + signature_length ); + /* Declared with fallback == true */ + if( status != PSA_ERROR_NOT_SUPPORTED ) + return( status ); +#endif /* PSA_CRYPTO_DRIVER_TEST */ +#endif /* PSA_CRYPTO_ACCELERATOR_DRIVER_PRESENT */ + break; + + /* Add cases for opaque driver here */ +#if defined(PSA_CRYPTO_ACCELERATOR_DRIVER_PRESENT) +#if defined(PSA_CRYPTO_DRIVER_TEST) + case PSA_CRYPTO_TEST_DRIVER_LOCATION: + status = mbedtls_test_opaque_signature_sign_message( + attributes, + key_buffer, + key_buffer_size, + alg, + input, + input_length, + signature, + signature_size, + signature_length ); + if( status != PSA_ERROR_NOT_SUPPORTED ) + return( status ); + break; +#endif /* PSA_CRYPTO_DRIVER_TEST */ +#endif /* PSA_CRYPTO_ACCELERATOR_DRIVER_PRESENT */ + default: + /* Key is declared with a lifetime not known to us */ + (void)status; + break; + } + + return( psa_sign_message_builtin( attributes, + key_buffer, + key_buffer_size, + alg, + input, + input_length, + signature, + signature_size, + signature_length ) ); +} + +static inline psa_status_t psa_driver_wrapper_verify_message( const psa_key_attributes_t *attributes, const uint8_t *key_buffer, size_t key_buffer_size, @@ -53,57 +191,882 @@ psa_status_t psa_driver_wrapper_verify_message( const uint8_t *input, size_t input_length, const uint8_t *signature, - size_t signature_length); + size_t signature_length ) +{ + psa_status_t status = PSA_ERROR_CORRUPTION_DETECTED; + psa_key_location_t location = + PSA_KEY_LIFETIME_GET_LOCATION( psa_get_key_lifetime(attributes) ); + + switch( location ) + { + case PSA_KEY_LOCATION_LOCAL_STORAGE: + /* Key is stored in the slot in export representation, so + * cycle through all known transparent accelerators */ +#if defined(PSA_CRYPTO_ACCELERATOR_DRIVER_PRESENT) +#if defined(PSA_CRYPTO_DRIVER_TEST) + status = mbedtls_test_transparent_signature_verify_message( + attributes, + key_buffer, + key_buffer_size, + alg, + input, + input_length, + signature, + signature_length ); + /* Declared with fallback == true */ + if( status != PSA_ERROR_NOT_SUPPORTED ) + return( status ); +#endif /* PSA_CRYPTO_DRIVER_TEST */ +#endif /* PSA_CRYPTO_ACCELERATOR_DRIVER_PRESENT */ + break; + + /* Add cases for opaque driver here */ +#if defined(PSA_CRYPTO_ACCELERATOR_DRIVER_PRESENT) +#if defined(PSA_CRYPTO_DRIVER_TEST) + case PSA_CRYPTO_TEST_DRIVER_LOCATION: + return( mbedtls_test_opaque_signature_verify_message( + attributes, + key_buffer, + key_buffer_size, + alg, + input, + input_length, + signature, + signature_length ) ); + if( status != PSA_ERROR_NOT_SUPPORTED ) + return( status ); + break; +#endif /* PSA_CRYPTO_DRIVER_TEST */ +#endif /* PSA_CRYPTO_ACCELERATOR_DRIVER_PRESENT */ + default: + /* Key is declared with a lifetime not known to us */ + (void)status; + break; + } -psa_status_t psa_driver_wrapper_sign_hash( + return( psa_verify_message_builtin( attributes, + key_buffer, + key_buffer_size, + alg, + input, + input_length, + signature, + signature_length ) ); +} + +static inline psa_status_t psa_driver_wrapper_sign_hash( const psa_key_attributes_t *attributes, const uint8_t *key_buffer, size_t key_buffer_size, psa_algorithm_t alg, const uint8_t *hash, size_t hash_length, - uint8_t *signature, size_t signature_size, size_t *signature_length); + uint8_t *signature, size_t signature_size, size_t *signature_length ) +{ + /* Try dynamically-registered SE interface first */ +#if defined(MBEDTLS_PSA_CRYPTO_SE_C) + const psa_drv_se_t *drv; + psa_drv_se_context_t *drv_context; + + if( psa_get_se_driver( psa_get_key_lifetime(attributes), &drv, &drv_context ) ) + { + if( drv->asymmetric == NULL || + drv->asymmetric->p_sign == NULL ) + { + /* Key is defined in SE, but we have no way to exercise it */ + return( PSA_ERROR_NOT_SUPPORTED ); + } + return( drv->asymmetric->p_sign( + drv_context, *( (psa_key_slot_number_t *)key_buffer ), + alg, hash, hash_length, + signature, signature_size, signature_length ) ); + } +#endif /* MBEDTLS_PSA_CRYPTO_SE_C */ + + psa_status_t status = PSA_ERROR_CORRUPTION_DETECTED; + psa_key_location_t location = + PSA_KEY_LIFETIME_GET_LOCATION( psa_get_key_lifetime(attributes) ); + + switch( location ) + { + case PSA_KEY_LOCATION_LOCAL_STORAGE: + /* Key is stored in the slot in export representation, so + * cycle through all known transparent accelerators */ +#if defined(PSA_CRYPTO_ACCELERATOR_DRIVER_PRESENT) +#if defined(PSA_CRYPTO_DRIVER_TEST) + status = mbedtls_test_transparent_signature_sign_hash( attributes, + key_buffer, + key_buffer_size, + alg, + hash, + hash_length, + signature, + signature_size, + signature_length ); + /* Declared with fallback == true */ + if( status != PSA_ERROR_NOT_SUPPORTED ) + return( status ); +#endif /* PSA_CRYPTO_DRIVER_TEST */ +#if defined (MBEDTLS_PSA_P256M_DRIVER_ENABLED) + if( PSA_KEY_TYPE_IS_ECC( psa_get_key_type(attributes) ) && + PSA_ALG_IS_ECDSA(alg) && + !PSA_ALG_ECDSA_IS_DETERMINISTIC( alg ) && + PSA_KEY_TYPE_ECC_GET_FAMILY(psa_get_key_type(attributes)) == PSA_ECC_FAMILY_SECP_R1 && + psa_get_key_bits(attributes) == 256 ) + { + status = p256_transparent_sign_hash( attributes, + key_buffer, + key_buffer_size, + alg, + hash, + hash_length, + signature, + signature_size, + signature_length ); + if( status != PSA_ERROR_NOT_SUPPORTED ) + return( status ); + } +#endif /* MBEDTLS_PSA_P256M_DRIVER_ENABLED */ +#endif /* PSA_CRYPTO_ACCELERATOR_DRIVER_PRESENT */ + /* Fell through, meaning no accelerator supports this operation */ + return( psa_sign_hash_builtin( attributes, + key_buffer, + key_buffer_size, + alg, + hash, + hash_length, + signature, + signature_size, + signature_length ) ); + + /* Add cases for opaque driver here */ +#if defined(PSA_CRYPTO_ACCELERATOR_DRIVER_PRESENT) +#if defined(PSA_CRYPTO_DRIVER_TEST) + case PSA_CRYPTO_TEST_DRIVER_LOCATION: + return( mbedtls_test_opaque_signature_sign_hash( attributes, + key_buffer, + key_buffer_size, + alg, + hash, + hash_length, + signature, + signature_size, + signature_length ) ); +#endif /* PSA_CRYPTO_DRIVER_TEST */ +#endif /* PSA_CRYPTO_ACCELERATOR_DRIVER_PRESENT */ + default: + /* Key is declared with a lifetime not known to us */ + (void)status; + return( PSA_ERROR_INVALID_ARGUMENT ); + } +} -psa_status_t psa_driver_wrapper_verify_hash( +static inline psa_status_t psa_driver_wrapper_verify_hash( const psa_key_attributes_t *attributes, const uint8_t *key_buffer, size_t key_buffer_size, psa_algorithm_t alg, const uint8_t *hash, size_t hash_length, - const uint8_t *signature, size_t signature_length); + const uint8_t *signature, size_t signature_length ) +{ + /* Try dynamically-registered SE interface first */ +#if defined(MBEDTLS_PSA_CRYPTO_SE_C) + const psa_drv_se_t *drv; + psa_drv_se_context_t *drv_context; -/* - * Key handling functions + if( psa_get_se_driver( psa_get_key_lifetime(attributes), &drv, &drv_context ) ) + { + if( drv->asymmetric == NULL || + drv->asymmetric->p_verify == NULL ) + { + /* Key is defined in SE, but we have no way to exercise it */ + return( PSA_ERROR_NOT_SUPPORTED ); + } + return( drv->asymmetric->p_verify( + drv_context, *( (psa_key_slot_number_t *)key_buffer ), + alg, hash, hash_length, + signature, signature_length ) ); + } +#endif /* MBEDTLS_PSA_CRYPTO_SE_C */ + + psa_status_t status = PSA_ERROR_CORRUPTION_DETECTED; + psa_key_location_t location = + PSA_KEY_LIFETIME_GET_LOCATION( psa_get_key_lifetime(attributes) ); + + switch( location ) + { + case PSA_KEY_LOCATION_LOCAL_STORAGE: + /* Key is stored in the slot in export representation, so + * cycle through all known transparent accelerators */ +#if defined(PSA_CRYPTO_ACCELERATOR_DRIVER_PRESENT) +#if defined(PSA_CRYPTO_DRIVER_TEST) + status = mbedtls_test_transparent_signature_verify_hash( + attributes, + key_buffer, + key_buffer_size, + alg, + hash, + hash_length, + signature, + signature_length ); + /* Declared with fallback == true */ + if( status != PSA_ERROR_NOT_SUPPORTED ) + return( status ); +#endif /* PSA_CRYPTO_DRIVER_TEST */ +#if defined (MBEDTLS_PSA_P256M_DRIVER_ENABLED) + if( PSA_KEY_TYPE_IS_ECC( psa_get_key_type(attributes) ) && + PSA_ALG_IS_ECDSA(alg) && + !PSA_ALG_ECDSA_IS_DETERMINISTIC( alg ) && + PSA_KEY_TYPE_ECC_GET_FAMILY(psa_get_key_type(attributes)) == PSA_ECC_FAMILY_SECP_R1 && + psa_get_key_bits(attributes) == 256 ) + { + status = p256_transparent_verify_hash( attributes, + key_buffer, + key_buffer_size, + alg, + hash, + hash_length, + signature, + signature_length ); + if( status != PSA_ERROR_NOT_SUPPORTED ) + return( status ); + } +#endif /* MBEDTLS_PSA_P256M_DRIVER_ENABLED */ +#endif /* PSA_CRYPTO_ACCELERATOR_DRIVER_PRESENT */ + + return( psa_verify_hash_builtin( attributes, + key_buffer, + key_buffer_size, + alg, + hash, + hash_length, + signature, + signature_length ) ); + + /* Add cases for opaque driver here */ +#if defined(PSA_CRYPTO_ACCELERATOR_DRIVER_PRESENT) +#if defined(PSA_CRYPTO_DRIVER_TEST) + case PSA_CRYPTO_TEST_DRIVER_LOCATION: + return( mbedtls_test_opaque_signature_verify_hash( attributes, + key_buffer, + key_buffer_size, + alg, + hash, + hash_length, + signature, + signature_length ) ); +#endif /* PSA_CRYPTO_DRIVER_TEST */ +#endif /* PSA_CRYPTO_ACCELERATOR_DRIVER_PRESENT */ + default: + /* Key is declared with a lifetime not known to us */ + (void)status; + return( PSA_ERROR_INVALID_ARGUMENT ); + } +} + +static inline uint32_t psa_driver_wrapper_sign_hash_get_num_ops( + psa_sign_hash_interruptible_operation_t *operation ) +{ + switch( operation->id ) + { + /* If uninitialised, return 0, as no work can have been done. */ + case 0: + return 0; + + case PSA_CRYPTO_MBED_TLS_DRIVER_ID: + return(mbedtls_psa_sign_hash_get_num_ops(&operation->ctx.mbedtls_ctx)); + +#if defined(PSA_CRYPTO_ACCELERATOR_DRIVER_PRESENT) +#if defined(PSA_CRYPTO_DRIVER_TEST) + /* Add test driver tests here */ + +#endif /* PSA_CRYPTO_DRIVER_TEST */ +#endif /* PSA_CRYPTO_ACCELERATOR_DRIVER_PRESENT */ + } + + /* Can't happen (see discussion in #8271) */ + return 0; +} + +static inline uint32_t psa_driver_wrapper_verify_hash_get_num_ops( + psa_verify_hash_interruptible_operation_t *operation ) +{ + switch( operation->id ) + { + /* If uninitialised, return 0, as no work can have been done. */ + case 0: + return 0; + + case PSA_CRYPTO_MBED_TLS_DRIVER_ID: + return (mbedtls_psa_verify_hash_get_num_ops(&operation->ctx.mbedtls_ctx)); + +#if defined(PSA_CRYPTO_ACCELERATOR_DRIVER_PRESENT) +#if defined(PSA_CRYPTO_DRIVER_TEST) + /* Add test driver tests here */ + +#endif /* PSA_CRYPTO_DRIVER_TEST */ +#endif /* PSA_CRYPTO_ACCELERATOR_DRIVER_PRESENT */ + + } + + /* Can't happen (see discussion in #8271) */ + return 0; +} + +static inline psa_status_t psa_driver_wrapper_sign_hash_start( + psa_sign_hash_interruptible_operation_t *operation, + const psa_key_attributes_t *attributes, const uint8_t *key_buffer, + size_t key_buffer_size, psa_algorithm_t alg, + const uint8_t *hash, size_t hash_length ) +{ + psa_status_t status = PSA_ERROR_CORRUPTION_DETECTED; + psa_key_location_t location = PSA_KEY_LIFETIME_GET_LOCATION( + psa_get_key_lifetime(attributes) ); + + switch( location ) + { + case PSA_KEY_LOCATION_LOCAL_STORAGE: + /* Key is stored in the slot in export representation, so + * cycle through all known transparent accelerators */ + +#if defined(PSA_CRYPTO_ACCELERATOR_DRIVER_PRESENT) +#if defined(PSA_CRYPTO_DRIVER_TEST) + + /* Add test driver tests here */ + + /* Declared with fallback == true */ + +#endif /* PSA_CRYPTO_DRIVER_TEST */ +#endif /* PSA_CRYPTO_ACCELERATOR_DRIVER_PRESENT */ + + /* Fell through, meaning no accelerator supports this operation */ + operation->id = PSA_CRYPTO_MBED_TLS_DRIVER_ID; + status = mbedtls_psa_sign_hash_start( &operation->ctx.mbedtls_ctx, + attributes, + key_buffer, key_buffer_size, + alg, hash, hash_length ); + break; + + /* Add cases for opaque driver here */ + + default: + /* Key is declared with a lifetime not known to us */ + status = PSA_ERROR_INVALID_ARGUMENT; + break; + } + + return( status ); +} + +static inline psa_status_t psa_driver_wrapper_sign_hash_complete( + psa_sign_hash_interruptible_operation_t *operation, + uint8_t *signature, size_t signature_size, + size_t *signature_length ) +{ + switch( operation->id ) + { + case PSA_CRYPTO_MBED_TLS_DRIVER_ID: + return( mbedtls_psa_sign_hash_complete( &operation->ctx.mbedtls_ctx, + signature, signature_size, + signature_length ) ); + +#if defined(PSA_CRYPTO_ACCELERATOR_DRIVER_PRESENT) +#if defined(PSA_CRYPTO_DRIVER_TEST) + /* Add test driver tests here */ + +#endif /* PSA_CRYPTO_DRIVER_TEST */ +#endif /* PSA_CRYPTO_ACCELERATOR_DRIVER_PRESENT */ + } + + ( void ) signature; + ( void ) signature_size; + ( void ) signature_length; + + return( PSA_ERROR_INVALID_ARGUMENT ); +} + +static inline psa_status_t psa_driver_wrapper_sign_hash_abort( + psa_sign_hash_interruptible_operation_t *operation ) +{ + switch( operation->id ) + { + case PSA_CRYPTO_MBED_TLS_DRIVER_ID: + return( mbedtls_psa_sign_hash_abort( &operation->ctx.mbedtls_ctx ) ); + +#if defined(PSA_CRYPTO_ACCELERATOR_DRIVER_PRESENT) +#if defined(PSA_CRYPTO_DRIVER_TEST) + /* Add test driver tests here */ + +#endif /* PSA_CRYPTO_DRIVER_TEST */ +#endif /* PSA_CRYPTO_ACCELERATOR_DRIVER_PRESENT */ + } + + return( PSA_ERROR_INVALID_ARGUMENT ); +} + +static inline psa_status_t psa_driver_wrapper_verify_hash_start( + psa_verify_hash_interruptible_operation_t *operation, + const psa_key_attributes_t *attributes, const uint8_t *key_buffer, + size_t key_buffer_size, psa_algorithm_t alg, + const uint8_t *hash, size_t hash_length, + const uint8_t *signature, size_t signature_length ) +{ + psa_status_t status = PSA_ERROR_CORRUPTION_DETECTED; + psa_key_location_t location = PSA_KEY_LIFETIME_GET_LOCATION( + psa_get_key_lifetime(attributes) ); + + switch( location ) + { + case PSA_KEY_LOCATION_LOCAL_STORAGE: + /* Key is stored in the slot in export representation, so + * cycle through all known transparent accelerators */ + +#if defined(PSA_CRYPTO_ACCELERATOR_DRIVER_PRESENT) +#if defined(PSA_CRYPTO_DRIVER_TEST) + + /* Add test driver tests here */ + + /* Declared with fallback == true */ + +#endif /* PSA_CRYPTO_DRIVER_TEST */ +#endif /* PSA_CRYPTO_ACCELERATOR_DRIVER_PRESENT */ + + /* Fell through, meaning no accelerator supports this operation */ + operation->id = PSA_CRYPTO_MBED_TLS_DRIVER_ID; + status = mbedtls_psa_verify_hash_start( &operation->ctx.mbedtls_ctx, + attributes, + key_buffer, key_buffer_size, + alg, hash, hash_length, + signature, signature_length ); + break; + + /* Add cases for opaque driver here */ + + default: + /* Key is declared with a lifetime not known to us */ + status = PSA_ERROR_INVALID_ARGUMENT; + break; + } + + return( status ); +} + +static inline psa_status_t psa_driver_wrapper_verify_hash_complete( + psa_verify_hash_interruptible_operation_t *operation ) +{ + switch( operation->id ) + { + case PSA_CRYPTO_MBED_TLS_DRIVER_ID: + return( mbedtls_psa_verify_hash_complete( + &operation->ctx.mbedtls_ctx + ) ); + +#if defined(PSA_CRYPTO_ACCELERATOR_DRIVER_PRESENT) +#if defined(PSA_CRYPTO_DRIVER_TEST) + /* Add test driver tests here */ + +#endif /* PSA_CRYPTO_DRIVER_TEST */ +#endif /* PSA_CRYPTO_ACCELERATOR_DRIVER_PRESENT */ + } + + return( PSA_ERROR_INVALID_ARGUMENT ); +} + +static inline psa_status_t psa_driver_wrapper_verify_hash_abort( + psa_verify_hash_interruptible_operation_t *operation ) +{ + switch( operation->id ) + { + case PSA_CRYPTO_MBED_TLS_DRIVER_ID: + return( mbedtls_psa_verify_hash_abort( &operation->ctx.mbedtls_ctx + ) ); + +#if defined(PSA_CRYPTO_ACCELERATOR_DRIVER_PRESENT) +#if defined(PSA_CRYPTO_DRIVER_TEST) + /* Add test driver tests here */ + +#endif /* PSA_CRYPTO_DRIVER_TEST */ +#endif /* PSA_CRYPTO_ACCELERATOR_DRIVER_PRESENT */ + } + + return( PSA_ERROR_INVALID_ARGUMENT ); +} + +/** Calculate the key buffer size required to store the key material of a key + * associated with an opaque driver from input key data. + * + * \param[in] attributes The key attributes + * \param[in] data The input key data. + * \param[in] data_length The input data length. + * \param[out] key_buffer_size Minimum buffer size to contain the key material. + * + * \retval #PSA_SUCCESS \emptydescription + * \retval #PSA_ERROR_INVALID_ARGUMENT \emptydescription + * \retval #PSA_ERROR_NOT_SUPPORTED \emptydescription */ +static inline psa_status_t psa_driver_wrapper_get_key_buffer_size_from_key_data( + const psa_key_attributes_t *attributes, + const uint8_t *data, + size_t data_length, + size_t *key_buffer_size ) +{ + psa_key_location_t location = + PSA_KEY_LIFETIME_GET_LOCATION( psa_get_key_lifetime(attributes) ); + psa_key_type_t key_type = psa_get_key_type(attributes); + + *key_buffer_size = 0; + switch( location ) + { +#if defined(PSA_CRYPTO_DRIVER_TEST) + case PSA_CRYPTO_TEST_DRIVER_LOCATION: + *key_buffer_size = mbedtls_test_opaque_size_function( key_type, + PSA_BYTES_TO_BITS( data_length ) ); + return( ( *key_buffer_size != 0 ) ? + PSA_SUCCESS : PSA_ERROR_NOT_SUPPORTED ); +#endif /* PSA_CRYPTO_DRIVER_TEST */ -psa_status_t psa_driver_wrapper_import_key( + default: + (void)key_type; + (void)data; + (void)data_length; + return( PSA_ERROR_INVALID_ARGUMENT ); + } +} + +static inline psa_status_t psa_driver_wrapper_generate_key( const psa_key_attributes_t *attributes, - const uint8_t *data, size_t data_length, - uint8_t *key_buffer, size_t key_buffer_size, - size_t *key_buffer_length, size_t *bits); + const psa_key_production_parameters_t *params, size_t params_data_length, + uint8_t *key_buffer, size_t key_buffer_size, size_t *key_buffer_length ) +{ + psa_status_t status = PSA_ERROR_CORRUPTION_DETECTED; + psa_key_location_t location = + PSA_KEY_LIFETIME_GET_LOCATION(psa_get_key_lifetime(attributes)); + +#if defined(PSA_WANT_KEY_TYPE_RSA_KEY_PAIR_GENERATE) + int is_default_production = + psa_key_production_parameters_are_default(params, params_data_length); + if( location != PSA_KEY_LOCATION_LOCAL_STORAGE && !is_default_production ) + { + /* We don't support passing custom production parameters + * to drivers yet. */ + return PSA_ERROR_NOT_SUPPORTED; + } +#else + int is_default_production = 1; + (void) is_default_production; +#endif + + /* Try dynamically-registered SE interface first */ +#if defined(MBEDTLS_PSA_CRYPTO_SE_C) + const psa_drv_se_t *drv; + psa_drv_se_context_t *drv_context; + + if( psa_get_se_driver( psa_get_key_lifetime(attributes), &drv, &drv_context ) ) + { + size_t pubkey_length = 0; /* We don't support this feature yet */ + if( drv->key_management == NULL || + drv->key_management->p_generate == NULL ) + { + /* Key is defined as being in SE, but we have no way to generate it */ + return( PSA_ERROR_NOT_SUPPORTED ); + } + return( drv->key_management->p_generate( + drv_context, + *( (psa_key_slot_number_t *)key_buffer ), + attributes, NULL, 0, &pubkey_length ) ); + } +#endif /* MBEDTLS_PSA_CRYPTO_SE_C */ + + switch( location ) + { + case PSA_KEY_LOCATION_LOCAL_STORAGE: +#if defined(PSA_CRYPTO_ACCELERATOR_DRIVER_PRESENT) + /* Transparent drivers are limited to generating asymmetric keys. */ + /* We don't support passing custom production parameters + * to drivers yet. */ + if( PSA_KEY_TYPE_IS_ASYMMETRIC( psa_get_key_type(attributes) ) && + is_default_production ) + { + /* Cycle through all known transparent accelerators */ +#if defined(PSA_CRYPTO_DRIVER_TEST) + status = mbedtls_test_transparent_generate_key( + attributes, key_buffer, key_buffer_size, + key_buffer_length ); + /* Declared with fallback == true */ + if( status != PSA_ERROR_NOT_SUPPORTED ) + break; +#endif /* PSA_CRYPTO_DRIVER_TEST */ +#if defined(MBEDTLS_PSA_P256M_DRIVER_ENABLED) + if( PSA_KEY_TYPE_IS_ECC( psa_get_key_type(attributes) ) && + psa_get_key_type(attributes) == PSA_KEY_TYPE_ECC_KEY_PAIR(PSA_ECC_FAMILY_SECP_R1) && + psa_get_key_bits(attributes) == 256 ) + { + status = p256_transparent_generate_key( attributes, + key_buffer, + key_buffer_size, + key_buffer_length ); + if( status != PSA_ERROR_NOT_SUPPORTED ) + break; + } + +#endif /* MBEDTLS_PSA_P256M_DRIVER_ENABLED */ + } +#endif /* PSA_CRYPTO_ACCELERATOR_DRIVER_PRESENT */ + + /* Software fallback */ + status = psa_generate_key_internal( + attributes, params, params_data_length, + key_buffer, key_buffer_size, key_buffer_length ); + break; -psa_status_t psa_driver_wrapper_export_key( + /* Add cases for opaque driver here */ +#if defined(PSA_CRYPTO_ACCELERATOR_DRIVER_PRESENT) +#if defined(PSA_CRYPTO_DRIVER_TEST) + case PSA_CRYPTO_TEST_DRIVER_LOCATION: + status = mbedtls_test_opaque_generate_key( + attributes, key_buffer, key_buffer_size, key_buffer_length ); + break; +#endif /* PSA_CRYPTO_DRIVER_TEST */ +#endif /* PSA_CRYPTO_ACCELERATOR_DRIVER_PRESENT */ + + default: + /* Key is declared with a lifetime not known to us */ + status = PSA_ERROR_INVALID_ARGUMENT; + break; + } + + return( status ); +} + +static inline psa_status_t psa_driver_wrapper_import_key( const psa_key_attributes_t *attributes, - const uint8_t *key_buffer, size_t key_buffer_size, - uint8_t *data, size_t data_size, size_t *data_length); + const uint8_t *data, + size_t data_length, + uint8_t *key_buffer, + size_t key_buffer_size, + size_t *key_buffer_length, + size_t *bits ) +{ + + psa_status_t status = PSA_ERROR_CORRUPTION_DETECTED; + psa_key_location_t location = PSA_KEY_LIFETIME_GET_LOCATION( + psa_get_key_lifetime( attributes ) ); + + /* Try dynamically-registered SE interface first */ +#if defined(MBEDTLS_PSA_CRYPTO_SE_C) + const psa_drv_se_t *drv; + psa_drv_se_context_t *drv_context; + + if( psa_get_se_driver( psa_get_key_lifetime(attributes), &drv, &drv_context ) ) + { + if( drv->key_management == NULL || + drv->key_management->p_import == NULL ) + return( PSA_ERROR_NOT_SUPPORTED ); + + /* The driver should set the number of key bits, however in + * case it doesn't, we initialize bits to an invalid value. */ + *bits = PSA_MAX_KEY_BITS + 1; + status = drv->key_management->p_import( + drv_context, + *( (psa_key_slot_number_t *)key_buffer ), + attributes, data, data_length, bits ); + + if( status != PSA_SUCCESS ) + return( status ); + + if( (*bits) > PSA_MAX_KEY_BITS ) + return( PSA_ERROR_NOT_SUPPORTED ); + + return( PSA_SUCCESS ); + } +#endif /* MBEDTLS_PSA_CRYPTO_SE_C */ + + switch( location ) + { + case PSA_KEY_LOCATION_LOCAL_STORAGE: + /* Key is stored in the slot in export representation, so + * cycle through all known transparent accelerators */ +#if defined(PSA_CRYPTO_ACCELERATOR_DRIVER_PRESENT) + +#if (defined(PSA_CRYPTO_DRIVER_TEST) ) + status = mbedtls_test_transparent_import_key + (attributes, + data, + data_length, + key_buffer, + key_buffer_size, + key_buffer_length, + bits + ); + + if( status != PSA_ERROR_NOT_SUPPORTED ) + return( status ); +#endif + +#if (defined(MBEDTLS_PSA_P256M_DRIVER_ENABLED) ) + status = p256_transparent_import_key + (attributes, + data, + data_length, + key_buffer, + key_buffer_size, + key_buffer_length, + bits + ); + + if( status != PSA_ERROR_NOT_SUPPORTED ) + return( status ); +#endif + + +#endif /* PSA_CRYPTO_ACCELERATOR_DRIVER_PRESENT */ + + /* Fell through, meaning no accelerator supports this operation */ + return( psa_import_key_into_slot( attributes, + data, data_length, + key_buffer, key_buffer_size, + key_buffer_length, bits ) ); + /* Add cases for opaque driver here */ +#if defined(PSA_CRYPTO_ACCELERATOR_DRIVER_PRESENT) -psa_status_t psa_driver_wrapper_export_public_key( +#if (defined(PSA_CRYPTO_DRIVER_TEST) ) + case 0x7fffff: + return( mbedtls_test_opaque_import_key + (attributes, + data, + data_length, + key_buffer, + key_buffer_size, + key_buffer_length, + bits + )); +#endif + + +#endif /* PSA_CRYPTO_ACCELERATOR_DRIVER_PRESENT */ + default: + (void)status; + return( PSA_ERROR_INVALID_ARGUMENT ); + } + +} + +static inline psa_status_t psa_driver_wrapper_export_key( const psa_key_attributes_t *attributes, const uint8_t *key_buffer, size_t key_buffer_size, - uint8_t *data, size_t data_size, size_t *data_length); + uint8_t *data, size_t data_size, size_t *data_length ) -psa_status_t psa_driver_wrapper_get_key_buffer_size( - const psa_key_attributes_t *attributes, - size_t *key_buffer_size); +{ -psa_status_t psa_driver_wrapper_generate_key( - const psa_key_attributes_t *attributes, - uint8_t *key_buffer, size_t key_buffer_size, size_t *key_buffer_length); + psa_status_t status = PSA_ERROR_INVALID_ARGUMENT; + psa_key_location_t location = PSA_KEY_LIFETIME_GET_LOCATION( + psa_get_key_lifetime( attributes ) ); + + /* Try dynamically-registered SE interface first */ +#if defined(MBEDTLS_PSA_CRYPTO_SE_C) + const psa_drv_se_t *drv; + psa_drv_se_context_t *drv_context; + + if( psa_get_se_driver( psa_get_key_lifetime(attributes), &drv, &drv_context ) ) + { + if( ( drv->key_management == NULL ) || + ( drv->key_management->p_export == NULL ) ) + { + return( PSA_ERROR_NOT_SUPPORTED ); + } + + return( drv->key_management->p_export( + drv_context, + *( (psa_key_slot_number_t *)key_buffer ), + data, data_size, data_length ) ); + } +#endif /* MBEDTLS_PSA_CRYPTO_SE_C */ + + switch( location ) + { + case PSA_KEY_LOCATION_LOCAL_STORAGE: + return( psa_export_key_internal( attributes, + key_buffer, + key_buffer_size, + data, + data_size, + data_length ) ); -psa_status_t psa_driver_wrapper_get_builtin_key( - psa_drv_slot_number_t slot_number, + /* Add cases for opaque driver here */ +#if defined(PSA_CRYPTO_ACCELERATOR_DRIVER_PRESENT) + +#if (defined(PSA_CRYPTO_DRIVER_TEST) ) + case 0x7fffff: + return( mbedtls_test_opaque_export_key + (attributes, + key_buffer, + key_buffer_size, + data, + data_size, + data_length + )); +#endif + + +#endif /* PSA_CRYPTO_ACCELERATOR_DRIVER_PRESENT */ + default: + /* Key is declared with a lifetime not known to us */ + return( status ); + } + +} + +static inline psa_status_t psa_driver_wrapper_copy_key( psa_key_attributes_t *attributes, - uint8_t *key_buffer, size_t key_buffer_size, size_t *key_buffer_length); + const uint8_t *source_key, size_t source_key_length, + uint8_t *target_key_buffer, size_t target_key_buffer_size, + size_t *target_key_buffer_length ) +{ + + psa_status_t status = PSA_ERROR_CORRUPTION_DETECTED; + psa_key_location_t location = + PSA_KEY_LIFETIME_GET_LOCATION( psa_get_key_lifetime(attributes) ); + +#if defined(MBEDTLS_PSA_CRYPTO_SE_C) + const psa_drv_se_t *drv; + psa_drv_se_context_t *drv_context; + + if( psa_get_se_driver( psa_get_key_lifetime(attributes), &drv, &drv_context ) ) + { + /* Copying to a secure element is not implemented yet. */ + return( PSA_ERROR_NOT_SUPPORTED ); + } +#endif /* MBEDTLS_PSA_CRYPTO_SE_C */ + + switch( location ) + { +#if defined(PSA_CRYPTO_ACCELERATOR_DRIVER_PRESENT) + +#if (defined(PSA_CRYPTO_DRIVER_TEST) ) + case 0x7fffff: + return( mbedtls_test_opaque_copy_key + (attributes, + source_key, + source_key_length, + target_key_buffer, + target_key_buffer_size, + target_key_buffer_length + )); +#endif + + +#endif /* PSA_CRYPTO_ACCELERATOR_DRIVER_PRESENT */ + default: + (void)source_key; + (void)source_key_length; + (void)target_key_buffer; + (void)target_key_buffer_size; + (void)target_key_buffer_length; + status = PSA_ERROR_INVALID_ARGUMENT; + } + return( status ); + +} /* * Cipher functions */ -psa_status_t psa_driver_wrapper_cipher_encrypt( +static inline psa_status_t psa_driver_wrapper_cipher_encrypt( const psa_key_attributes_t *attributes, const uint8_t *key_buffer, size_t key_buffer_size, @@ -114,9 +1077,88 @@ psa_status_t psa_driver_wrapper_cipher_encrypt( size_t input_length, uint8_t *output, size_t output_size, - size_t *output_length); + size_t *output_length ) +{ + psa_status_t status = PSA_ERROR_CORRUPTION_DETECTED; + psa_key_location_t location = + PSA_KEY_LIFETIME_GET_LOCATION( psa_get_key_lifetime(attributes) ); + + switch( location ) + { + case PSA_KEY_LOCATION_LOCAL_STORAGE: + /* Key is stored in the slot in export representation, so + * cycle through all known transparent accelerators */ +#if defined(PSA_CRYPTO_ACCELERATOR_DRIVER_PRESENT) +#if defined(PSA_CRYPTO_DRIVER_TEST) + status = mbedtls_test_transparent_cipher_encrypt( attributes, + key_buffer, + key_buffer_size, + alg, + iv, + iv_length, + input, + input_length, + output, + output_size, + output_length ); + /* Declared with fallback == true */ + if( status != PSA_ERROR_NOT_SUPPORTED ) + return( status ); +#endif /* PSA_CRYPTO_DRIVER_TEST */ +#endif /* PSA_CRYPTO_ACCELERATOR_DRIVER_PRESENT */ + +#if defined(MBEDTLS_PSA_BUILTIN_CIPHER) + return( mbedtls_psa_cipher_encrypt( attributes, + key_buffer, + key_buffer_size, + alg, + iv, + iv_length, + input, + input_length, + output, + output_size, + output_length ) ); +#else + return( PSA_ERROR_NOT_SUPPORTED ); +#endif /* MBEDTLS_PSA_BUILTIN_CIPHER */ -psa_status_t psa_driver_wrapper_cipher_decrypt( + /* Add cases for opaque driver here */ +#if defined(PSA_CRYPTO_ACCELERATOR_DRIVER_PRESENT) +#if defined(PSA_CRYPTO_DRIVER_TEST) + case PSA_CRYPTO_TEST_DRIVER_LOCATION: + return( mbedtls_test_opaque_cipher_encrypt( attributes, + key_buffer, + key_buffer_size, + alg, + iv, + iv_length, + input, + input_length, + output, + output_size, + output_length ) ); +#endif /* PSA_CRYPTO_DRIVER_TEST */ +#endif /* PSA_CRYPTO_ACCELERATOR_DRIVER_PRESENT */ + + default: + /* Key is declared with a lifetime not known to us */ + (void)status; + (void)key_buffer; + (void)key_buffer_size; + (void)alg; + (void)iv; + (void)iv_length; + (void)input; + (void)input_length; + (void)output; + (void)output_size; + (void)output_length; + return( PSA_ERROR_INVALID_ARGUMENT ); + } +} + +static inline psa_status_t psa_driver_wrapper_cipher_decrypt( const psa_key_attributes_t *attributes, const uint8_t *key_buffer, size_t key_buffer_size, @@ -125,101 +1167,1033 @@ psa_status_t psa_driver_wrapper_cipher_decrypt( size_t input_length, uint8_t *output, size_t output_size, - size_t *output_length); + size_t *output_length ) +{ + psa_status_t status = PSA_ERROR_CORRUPTION_DETECTED; + psa_key_location_t location = + PSA_KEY_LIFETIME_GET_LOCATION( psa_get_key_lifetime(attributes) ); + + switch( location ) + { + case PSA_KEY_LOCATION_LOCAL_STORAGE: + /* Key is stored in the slot in export representation, so + * cycle through all known transparent accelerators */ +#if defined(PSA_CRYPTO_ACCELERATOR_DRIVER_PRESENT) +#if defined(PSA_CRYPTO_DRIVER_TEST) + status = mbedtls_test_transparent_cipher_decrypt( attributes, + key_buffer, + key_buffer_size, + alg, + input, + input_length, + output, + output_size, + output_length ); + /* Declared with fallback == true */ + if( status != PSA_ERROR_NOT_SUPPORTED ) + return( status ); +#endif /* PSA_CRYPTO_DRIVER_TEST */ +#endif /* PSA_CRYPTO_ACCELERATOR_DRIVER_PRESENT */ + +#if defined(MBEDTLS_PSA_BUILTIN_CIPHER) + return( mbedtls_psa_cipher_decrypt( attributes, + key_buffer, + key_buffer_size, + alg, + input, + input_length, + output, + output_size, + output_length ) ); +#else + return( PSA_ERROR_NOT_SUPPORTED ); +#endif /* MBEDTLS_PSA_BUILTIN_CIPHER */ + + /* Add cases for opaque driver here */ +#if defined(PSA_CRYPTO_ACCELERATOR_DRIVER_PRESENT) +#if defined(PSA_CRYPTO_DRIVER_TEST) + case PSA_CRYPTO_TEST_DRIVER_LOCATION: + return( mbedtls_test_opaque_cipher_decrypt( attributes, + key_buffer, + key_buffer_size, + alg, + input, + input_length, + output, + output_size, + output_length ) ); +#endif /* PSA_CRYPTO_DRIVER_TEST */ +#endif /* PSA_CRYPTO_ACCELERATOR_DRIVER_PRESENT */ -psa_status_t psa_driver_wrapper_cipher_encrypt_setup( + default: + /* Key is declared with a lifetime not known to us */ + (void)status; + (void)key_buffer; + (void)key_buffer_size; + (void)alg; + (void)input; + (void)input_length; + (void)output; + (void)output_size; + (void)output_length; + return( PSA_ERROR_INVALID_ARGUMENT ); + } +} + +static inline psa_status_t psa_driver_wrapper_cipher_encrypt_setup( psa_cipher_operation_t *operation, const psa_key_attributes_t *attributes, const uint8_t *key_buffer, size_t key_buffer_size, - psa_algorithm_t alg); + psa_algorithm_t alg ) +{ + psa_status_t status = PSA_ERROR_CORRUPTION_DETECTED; + psa_key_location_t location = + PSA_KEY_LIFETIME_GET_LOCATION( psa_get_key_lifetime(attributes) ); + + switch( location ) + { + case PSA_KEY_LOCATION_LOCAL_STORAGE: + /* Key is stored in the slot in export representation, so + * cycle through all known transparent accelerators */ +#if defined(PSA_CRYPTO_ACCELERATOR_DRIVER_PRESENT) +#if defined(PSA_CRYPTO_DRIVER_TEST) + status = mbedtls_test_transparent_cipher_encrypt_setup( + &operation->ctx.transparent_test_driver_ctx, + attributes, + key_buffer, + key_buffer_size, + alg ); + /* Declared with fallback == true */ + if( status == PSA_SUCCESS ) + operation->id = MBEDTLS_TEST_TRANSPARENT_DRIVER_ID; + + if( status != PSA_ERROR_NOT_SUPPORTED ) + return( status ); +#endif /* PSA_CRYPTO_DRIVER_TEST */ +#endif /* PSA_CRYPTO_ACCELERATOR_DRIVER_PRESENT */ +#if defined(MBEDTLS_PSA_BUILTIN_CIPHER) + /* Fell through, meaning no accelerator supports this operation */ + status = mbedtls_psa_cipher_encrypt_setup( &operation->ctx.mbedtls_ctx, + attributes, + key_buffer, + key_buffer_size, + alg ); + if( status == PSA_SUCCESS ) + operation->id = PSA_CRYPTO_MBED_TLS_DRIVER_ID; + + if( status != PSA_ERROR_NOT_SUPPORTED ) + return( status ); +#endif /* MBEDTLS_PSA_BUILTIN_CIPHER */ + return( PSA_ERROR_NOT_SUPPORTED ); + + /* Add cases for opaque driver here */ +#if defined(PSA_CRYPTO_ACCELERATOR_DRIVER_PRESENT) +#if defined(PSA_CRYPTO_DRIVER_TEST) + case PSA_CRYPTO_TEST_DRIVER_LOCATION: + status = mbedtls_test_opaque_cipher_encrypt_setup( + &operation->ctx.opaque_test_driver_ctx, + attributes, + key_buffer, key_buffer_size, + alg ); -psa_status_t psa_driver_wrapper_cipher_decrypt_setup( + if( status == PSA_SUCCESS ) + operation->id = MBEDTLS_TEST_OPAQUE_DRIVER_ID; + + return( status ); +#endif /* PSA_CRYPTO_DRIVER_TEST */ +#endif /* PSA_CRYPTO_ACCELERATOR_DRIVER_PRESENT */ + default: + /* Key is declared with a lifetime not known to us */ + (void)status; + (void)operation; + (void)key_buffer; + (void)key_buffer_size; + (void)alg; + return( PSA_ERROR_INVALID_ARGUMENT ); + } +} + +static inline psa_status_t psa_driver_wrapper_cipher_decrypt_setup( psa_cipher_operation_t *operation, const psa_key_attributes_t *attributes, const uint8_t *key_buffer, size_t key_buffer_size, - psa_algorithm_t alg); + psa_algorithm_t alg ) +{ + psa_status_t status = PSA_ERROR_INVALID_ARGUMENT; + psa_key_location_t location = + PSA_KEY_LIFETIME_GET_LOCATION( psa_get_key_lifetime(attributes) ); + + switch( location ) + { + case PSA_KEY_LOCATION_LOCAL_STORAGE: + /* Key is stored in the slot in export representation, so + * cycle through all known transparent accelerators */ +#if defined(PSA_CRYPTO_ACCELERATOR_DRIVER_PRESENT) +#if defined(PSA_CRYPTO_DRIVER_TEST) + status = mbedtls_test_transparent_cipher_decrypt_setup( + &operation->ctx.transparent_test_driver_ctx, + attributes, + key_buffer, + key_buffer_size, + alg ); + /* Declared with fallback == true */ + if( status == PSA_SUCCESS ) + operation->id = MBEDTLS_TEST_TRANSPARENT_DRIVER_ID; + + if( status != PSA_ERROR_NOT_SUPPORTED ) + return( status ); +#endif /* PSA_CRYPTO_DRIVER_TEST */ +#endif /* PSA_CRYPTO_ACCELERATOR_DRIVER_PRESENT */ +#if defined(MBEDTLS_PSA_BUILTIN_CIPHER) + /* Fell through, meaning no accelerator supports this operation */ + status = mbedtls_psa_cipher_decrypt_setup( &operation->ctx.mbedtls_ctx, + attributes, + key_buffer, + key_buffer_size, + alg ); + if( status == PSA_SUCCESS ) + operation->id = PSA_CRYPTO_MBED_TLS_DRIVER_ID; -psa_status_t psa_driver_wrapper_cipher_set_iv( + return( status ); +#else /* MBEDTLS_PSA_BUILTIN_CIPHER */ + return( PSA_ERROR_NOT_SUPPORTED ); +#endif /* MBEDTLS_PSA_BUILTIN_CIPHER */ + + /* Add cases for opaque driver here */ +#if defined(PSA_CRYPTO_ACCELERATOR_DRIVER_PRESENT) +#if defined(PSA_CRYPTO_DRIVER_TEST) + case PSA_CRYPTO_TEST_DRIVER_LOCATION: + status = mbedtls_test_opaque_cipher_decrypt_setup( + &operation->ctx.opaque_test_driver_ctx, + attributes, + key_buffer, key_buffer_size, + alg ); + + if( status == PSA_SUCCESS ) + operation->id = MBEDTLS_TEST_OPAQUE_DRIVER_ID; + + return( status ); +#endif /* PSA_CRYPTO_DRIVER_TEST */ +#endif /* PSA_CRYPTO_ACCELERATOR_DRIVER_PRESENT */ + default: + /* Key is declared with a lifetime not known to us */ + (void)status; + (void)operation; + (void)key_buffer; + (void)key_buffer_size; + (void)alg; + return( PSA_ERROR_INVALID_ARGUMENT ); + } +} + +static inline psa_status_t psa_driver_wrapper_cipher_set_iv( psa_cipher_operation_t *operation, const uint8_t *iv, - size_t iv_length); + size_t iv_length ) +{ + switch( operation->id ) + { +#if defined(MBEDTLS_PSA_BUILTIN_CIPHER) + case PSA_CRYPTO_MBED_TLS_DRIVER_ID: + return( mbedtls_psa_cipher_set_iv( &operation->ctx.mbedtls_ctx, + iv, + iv_length ) ); +#endif /* MBEDTLS_PSA_BUILTIN_CIPHER */ + +#if defined(PSA_CRYPTO_ACCELERATOR_DRIVER_PRESENT) +#if defined(PSA_CRYPTO_DRIVER_TEST) + case MBEDTLS_TEST_TRANSPARENT_DRIVER_ID: + return( mbedtls_test_transparent_cipher_set_iv( + &operation->ctx.transparent_test_driver_ctx, + iv, iv_length ) ); -psa_status_t psa_driver_wrapper_cipher_update( + case MBEDTLS_TEST_OPAQUE_DRIVER_ID: + return( mbedtls_test_opaque_cipher_set_iv( + &operation->ctx.opaque_test_driver_ctx, + iv, iv_length ) ); +#endif /* PSA_CRYPTO_DRIVER_TEST */ +#endif /* PSA_CRYPTO_ACCELERATOR_DRIVER_PRESENT */ + } + + (void)iv; + (void)iv_length; + + return( PSA_ERROR_INVALID_ARGUMENT ); +} + +static inline psa_status_t psa_driver_wrapper_cipher_update( psa_cipher_operation_t *operation, const uint8_t *input, size_t input_length, uint8_t *output, size_t output_size, - size_t *output_length); + size_t *output_length ) +{ + switch( operation->id ) + { +#if defined(MBEDTLS_PSA_BUILTIN_CIPHER) + case PSA_CRYPTO_MBED_TLS_DRIVER_ID: + return( mbedtls_psa_cipher_update( &operation->ctx.mbedtls_ctx, + input, + input_length, + output, + output_size, + output_length ) ); +#endif /* MBEDTLS_PSA_BUILTIN_CIPHER */ + +#if defined(PSA_CRYPTO_ACCELERATOR_DRIVER_PRESENT) +#if defined(PSA_CRYPTO_DRIVER_TEST) + case MBEDTLS_TEST_TRANSPARENT_DRIVER_ID: + return( mbedtls_test_transparent_cipher_update( + &operation->ctx.transparent_test_driver_ctx, + input, input_length, + output, output_size, output_length ) ); + + case MBEDTLS_TEST_OPAQUE_DRIVER_ID: + return( mbedtls_test_opaque_cipher_update( + &operation->ctx.opaque_test_driver_ctx, + input, input_length, + output, output_size, output_length ) ); +#endif /* PSA_CRYPTO_DRIVER_TEST */ +#endif /* PSA_CRYPTO_ACCELERATOR_DRIVER_PRESENT */ + } -psa_status_t psa_driver_wrapper_cipher_finish( + (void)input; + (void)input_length; + (void)output; + (void)output_size; + (void)output_length; + + return( PSA_ERROR_INVALID_ARGUMENT ); +} + +static inline psa_status_t psa_driver_wrapper_cipher_finish( psa_cipher_operation_t *operation, uint8_t *output, size_t output_size, - size_t *output_length); + size_t *output_length ) +{ + switch( operation->id ) + { +#if defined(MBEDTLS_PSA_BUILTIN_CIPHER) + case PSA_CRYPTO_MBED_TLS_DRIVER_ID: + return( mbedtls_psa_cipher_finish( &operation->ctx.mbedtls_ctx, + output, + output_size, + output_length ) ); +#endif /* MBEDTLS_PSA_BUILTIN_CIPHER */ + +#if defined(PSA_CRYPTO_ACCELERATOR_DRIVER_PRESENT) +#if defined(PSA_CRYPTO_DRIVER_TEST) + case MBEDTLS_TEST_TRANSPARENT_DRIVER_ID: + return( mbedtls_test_transparent_cipher_finish( + &operation->ctx.transparent_test_driver_ctx, + output, output_size, output_length ) ); + + case MBEDTLS_TEST_OPAQUE_DRIVER_ID: + return( mbedtls_test_opaque_cipher_finish( + &operation->ctx.opaque_test_driver_ctx, + output, output_size, output_length ) ); +#endif /* PSA_CRYPTO_DRIVER_TEST */ +#endif /* PSA_CRYPTO_ACCELERATOR_DRIVER_PRESENT */ + } + + (void)output; + (void)output_size; + (void)output_length; + + return( PSA_ERROR_INVALID_ARGUMENT ); +} + +static inline psa_status_t psa_driver_wrapper_cipher_abort( + psa_cipher_operation_t *operation ) +{ + psa_status_t status = PSA_ERROR_CORRUPTION_DETECTED; + + switch( operation->id ) + { +#if defined(MBEDTLS_PSA_BUILTIN_CIPHER) + case PSA_CRYPTO_MBED_TLS_DRIVER_ID: + return( mbedtls_psa_cipher_abort( &operation->ctx.mbedtls_ctx ) ); +#endif /* MBEDTLS_PSA_BUILTIN_CIPHER */ + +#if defined(PSA_CRYPTO_ACCELERATOR_DRIVER_PRESENT) +#if defined(PSA_CRYPTO_DRIVER_TEST) + case MBEDTLS_TEST_TRANSPARENT_DRIVER_ID: + status = mbedtls_test_transparent_cipher_abort( + &operation->ctx.transparent_test_driver_ctx ); + mbedtls_platform_zeroize( + &operation->ctx.transparent_test_driver_ctx, + sizeof( operation->ctx.transparent_test_driver_ctx ) ); + return( status ); + + case MBEDTLS_TEST_OPAQUE_DRIVER_ID: + status = mbedtls_test_opaque_cipher_abort( + &operation->ctx.opaque_test_driver_ctx ); + mbedtls_platform_zeroize( + &operation->ctx.opaque_test_driver_ctx, + sizeof( operation->ctx.opaque_test_driver_ctx ) ); + return( status ); +#endif /* PSA_CRYPTO_DRIVER_TEST */ +#endif /* PSA_CRYPTO_ACCELERATOR_DRIVER_PRESENT */ + } -psa_status_t psa_driver_wrapper_cipher_abort( - psa_cipher_operation_t *operation); + (void)status; + return( PSA_ERROR_INVALID_ARGUMENT ); +} /* * Hashing functions */ -psa_status_t psa_driver_wrapper_hash_compute( +static inline psa_status_t psa_driver_wrapper_hash_compute( psa_algorithm_t alg, const uint8_t *input, size_t input_length, uint8_t *hash, size_t hash_size, - size_t *hash_length); + size_t *hash_length) +{ + psa_status_t status = PSA_ERROR_CORRUPTION_DETECTED; -psa_status_t psa_driver_wrapper_hash_setup( + /* Try accelerators first */ +#if defined(PSA_CRYPTO_DRIVER_TEST) + status = mbedtls_test_transparent_hash_compute( + alg, input, input_length, hash, hash_size, hash_length ); + if( status != PSA_ERROR_NOT_SUPPORTED ) + return( status ); +#endif + + /* If software fallback is compiled in, try fallback */ +#if defined(MBEDTLS_PSA_BUILTIN_HASH) + status = mbedtls_psa_hash_compute( alg, input, input_length, + hash, hash_size, hash_length ); + if( status != PSA_ERROR_NOT_SUPPORTED ) + return( status ); +#endif + (void) status; + (void) alg; + (void) input; + (void) input_length; + (void) hash; + (void) hash_size; + (void) hash_length; + + return( PSA_ERROR_NOT_SUPPORTED ); +} + +static inline psa_status_t psa_driver_wrapper_hash_setup( psa_hash_operation_t *operation, - psa_algorithm_t alg); + psa_algorithm_t alg ) +{ + psa_status_t status = PSA_ERROR_CORRUPTION_DETECTED; + + /* Try setup on accelerators first */ +#if defined(PSA_CRYPTO_DRIVER_TEST) + status = mbedtls_test_transparent_hash_setup( + &operation->ctx.test_driver_ctx, alg ); + if( status == PSA_SUCCESS ) + operation->id = MBEDTLS_TEST_TRANSPARENT_DRIVER_ID; + + if( status != PSA_ERROR_NOT_SUPPORTED ) + return( status ); +#endif -psa_status_t psa_driver_wrapper_hash_clone( + /* If software fallback is compiled in, try fallback */ +#if defined(MBEDTLS_PSA_BUILTIN_HASH) + status = mbedtls_psa_hash_setup( &operation->ctx.mbedtls_ctx, alg ); + if( status == PSA_SUCCESS ) + operation->id = PSA_CRYPTO_MBED_TLS_DRIVER_ID; + + if( status != PSA_ERROR_NOT_SUPPORTED ) + return( status ); +#endif + /* Nothing left to try if we fall through here */ + (void) status; + (void) operation; + (void) alg; + return( PSA_ERROR_NOT_SUPPORTED ); +} + +static inline psa_status_t psa_driver_wrapper_hash_clone( const psa_hash_operation_t *source_operation, - psa_hash_operation_t *target_operation); + psa_hash_operation_t *target_operation ) +{ + switch( source_operation->id ) + { +#if defined(MBEDTLS_PSA_BUILTIN_HASH) + case PSA_CRYPTO_MBED_TLS_DRIVER_ID: + target_operation->id = PSA_CRYPTO_MBED_TLS_DRIVER_ID; + return( mbedtls_psa_hash_clone( &source_operation->ctx.mbedtls_ctx, + &target_operation->ctx.mbedtls_ctx ) ); +#endif +#if defined(PSA_CRYPTO_DRIVER_TEST) + case MBEDTLS_TEST_TRANSPARENT_DRIVER_ID: + target_operation->id = MBEDTLS_TEST_TRANSPARENT_DRIVER_ID; + return( mbedtls_test_transparent_hash_clone( + &source_operation->ctx.test_driver_ctx, + &target_operation->ctx.test_driver_ctx ) ); +#endif + default: + (void) target_operation; + return( PSA_ERROR_BAD_STATE ); + } +} -psa_status_t psa_driver_wrapper_hash_update( +static inline psa_status_t psa_driver_wrapper_hash_update( psa_hash_operation_t *operation, const uint8_t *input, - size_t input_length); + size_t input_length ) +{ + switch( operation->id ) + { +#if defined(MBEDTLS_PSA_BUILTIN_HASH) + case PSA_CRYPTO_MBED_TLS_DRIVER_ID: + return( mbedtls_psa_hash_update( &operation->ctx.mbedtls_ctx, + input, input_length ) ); +#endif +#if defined(PSA_CRYPTO_DRIVER_TEST) + case MBEDTLS_TEST_TRANSPARENT_DRIVER_ID: + return( mbedtls_test_transparent_hash_update( + &operation->ctx.test_driver_ctx, + input, input_length ) ); +#endif + default: + (void) input; + (void) input_length; + return( PSA_ERROR_BAD_STATE ); + } +} -psa_status_t psa_driver_wrapper_hash_finish( +static inline psa_status_t psa_driver_wrapper_hash_finish( psa_hash_operation_t *operation, uint8_t *hash, size_t hash_size, - size_t *hash_length); - -psa_status_t psa_driver_wrapper_hash_abort( - psa_hash_operation_t *operation); + size_t *hash_length ) +{ + switch( operation->id ) + { +#if defined(MBEDTLS_PSA_BUILTIN_HASH) + case PSA_CRYPTO_MBED_TLS_DRIVER_ID: + return( mbedtls_psa_hash_finish( &operation->ctx.mbedtls_ctx, + hash, hash_size, hash_length ) ); +#endif +#if defined(PSA_CRYPTO_DRIVER_TEST) + case MBEDTLS_TEST_TRANSPARENT_DRIVER_ID: + return( mbedtls_test_transparent_hash_finish( + &operation->ctx.test_driver_ctx, + hash, hash_size, hash_length ) ); +#endif + default: + (void) hash; + (void) hash_size; + (void) hash_length; + return( PSA_ERROR_BAD_STATE ); + } +} -/* - * AEAD functions - */ +static inline psa_status_t psa_driver_wrapper_hash_abort( + psa_hash_operation_t *operation ) +{ + switch( operation->id ) + { +#if defined(MBEDTLS_PSA_BUILTIN_HASH) + case PSA_CRYPTO_MBED_TLS_DRIVER_ID: + return( mbedtls_psa_hash_abort( &operation->ctx.mbedtls_ctx ) ); +#endif +#if defined(PSA_CRYPTO_DRIVER_TEST) + case MBEDTLS_TEST_TRANSPARENT_DRIVER_ID: + return( mbedtls_test_transparent_hash_abort( + &operation->ctx.test_driver_ctx ) ); +#endif + default: + return( PSA_ERROR_BAD_STATE ); + } +} -psa_status_t psa_driver_wrapper_aead_encrypt( +static inline psa_status_t psa_driver_wrapper_aead_encrypt( const psa_key_attributes_t *attributes, const uint8_t *key_buffer, size_t key_buffer_size, psa_algorithm_t alg, const uint8_t *nonce, size_t nonce_length, const uint8_t *additional_data, size_t additional_data_length, const uint8_t *plaintext, size_t plaintext_length, - uint8_t *ciphertext, size_t ciphertext_size, size_t *ciphertext_length); + uint8_t *ciphertext, size_t ciphertext_size, size_t *ciphertext_length ) +{ + psa_status_t status = PSA_ERROR_CORRUPTION_DETECTED; + psa_key_location_t location = + PSA_KEY_LIFETIME_GET_LOCATION( psa_get_key_lifetime(attributes) ); -psa_status_t psa_driver_wrapper_aead_decrypt( + switch( location ) + { + case PSA_KEY_LOCATION_LOCAL_STORAGE: + /* Key is stored in the slot in export representation, so + * cycle through all known transparent accelerators */ + +#if defined(PSA_CRYPTO_ACCELERATOR_DRIVER_PRESENT) +#if defined(PSA_CRYPTO_DRIVER_TEST) + status = mbedtls_test_transparent_aead_encrypt( + attributes, key_buffer, key_buffer_size, + alg, + nonce, nonce_length, + additional_data, additional_data_length, + plaintext, plaintext_length, + ciphertext, ciphertext_size, ciphertext_length ); + /* Declared with fallback == true */ + if( status != PSA_ERROR_NOT_SUPPORTED ) + return( status ); +#endif /* PSA_CRYPTO_DRIVER_TEST */ +#endif /* PSA_CRYPTO_ACCELERATOR_DRIVER_PRESENT */ + + /* Fell through, meaning no accelerator supports this operation */ + return( mbedtls_psa_aead_encrypt( + attributes, key_buffer, key_buffer_size, + alg, + nonce, nonce_length, + additional_data, additional_data_length, + plaintext, plaintext_length, + ciphertext, ciphertext_size, ciphertext_length ) ); + + /* Add cases for opaque driver here */ + + default: + /* Key is declared with a lifetime not known to us */ + (void)status; + return( PSA_ERROR_INVALID_ARGUMENT ); + } +} + +static inline psa_status_t psa_driver_wrapper_aead_decrypt( const psa_key_attributes_t *attributes, const uint8_t *key_buffer, size_t key_buffer_size, psa_algorithm_t alg, const uint8_t *nonce, size_t nonce_length, const uint8_t *additional_data, size_t additional_data_length, const uint8_t *ciphertext, size_t ciphertext_length, - uint8_t *plaintext, size_t plaintext_size, size_t *plaintext_length); + uint8_t *plaintext, size_t plaintext_size, size_t *plaintext_length ) +{ + psa_status_t status = PSA_ERROR_CORRUPTION_DETECTED; + psa_key_location_t location = + PSA_KEY_LIFETIME_GET_LOCATION( psa_get_key_lifetime(attributes) ); + + switch( location ) + { + case PSA_KEY_LOCATION_LOCAL_STORAGE: + /* Key is stored in the slot in export representation, so + * cycle through all known transparent accelerators */ + +#if defined(PSA_CRYPTO_ACCELERATOR_DRIVER_PRESENT) +#if defined(PSA_CRYPTO_DRIVER_TEST) + status = mbedtls_test_transparent_aead_decrypt( + attributes, key_buffer, key_buffer_size, + alg, + nonce, nonce_length, + additional_data, additional_data_length, + ciphertext, ciphertext_length, + plaintext, plaintext_size, plaintext_length ); + /* Declared with fallback == true */ + if( status != PSA_ERROR_NOT_SUPPORTED ) + return( status ); +#endif /* PSA_CRYPTO_DRIVER_TEST */ +#endif /* PSA_CRYPTO_ACCELERATOR_DRIVER_PRESENT */ + + /* Fell through, meaning no accelerator supports this operation */ + return( mbedtls_psa_aead_decrypt( + attributes, key_buffer, key_buffer_size, + alg, + nonce, nonce_length, + additional_data, additional_data_length, + ciphertext, ciphertext_length, + plaintext, plaintext_size, plaintext_length ) ); + + /* Add cases for opaque driver here */ + + default: + /* Key is declared with a lifetime not known to us */ + (void)status; + return( PSA_ERROR_INVALID_ARGUMENT ); + } +} + +static inline psa_status_t psa_driver_wrapper_aead_encrypt_setup( + psa_aead_operation_t *operation, + const psa_key_attributes_t *attributes, + const uint8_t *key_buffer, size_t key_buffer_size, + psa_algorithm_t alg ) +{ + psa_status_t status = PSA_ERROR_CORRUPTION_DETECTED; + psa_key_location_t location = + PSA_KEY_LIFETIME_GET_LOCATION( psa_get_key_lifetime(attributes) ); + + switch( location ) + { + case PSA_KEY_LOCATION_LOCAL_STORAGE: + /* Key is stored in the slot in export representation, so + * cycle through all known transparent accelerators */ + +#if defined(PSA_CRYPTO_ACCELERATOR_DRIVER_PRESENT) +#if defined(PSA_CRYPTO_DRIVER_TEST) + operation->id = MBEDTLS_TEST_TRANSPARENT_DRIVER_ID; + status = mbedtls_test_transparent_aead_encrypt_setup( + &operation->ctx.transparent_test_driver_ctx, + attributes, key_buffer, key_buffer_size, + alg ); + + /* Declared with fallback == true */ + if( status != PSA_ERROR_NOT_SUPPORTED ) + return( status ); +#endif /* PSA_CRYPTO_DRIVER_TEST */ +#endif /* PSA_CRYPTO_ACCELERATOR_DRIVER_PRESENT */ + + /* Fell through, meaning no accelerator supports this operation */ + operation->id = PSA_CRYPTO_MBED_TLS_DRIVER_ID; + status = mbedtls_psa_aead_encrypt_setup( + &operation->ctx.mbedtls_ctx, attributes, + key_buffer, key_buffer_size, + alg ); + + return( status ); + + /* Add cases for opaque driver here */ + + default: + /* Key is declared with a lifetime not known to us */ + (void)status; + return( PSA_ERROR_INVALID_ARGUMENT ); + } +} + +static inline psa_status_t psa_driver_wrapper_aead_decrypt_setup( + psa_aead_operation_t *operation, + const psa_key_attributes_t *attributes, + const uint8_t *key_buffer, size_t key_buffer_size, + psa_algorithm_t alg ) +{ + psa_status_t status = PSA_ERROR_CORRUPTION_DETECTED; + psa_key_location_t location = + PSA_KEY_LIFETIME_GET_LOCATION( psa_get_key_lifetime(attributes) ); + + switch( location ) + { + case PSA_KEY_LOCATION_LOCAL_STORAGE: + /* Key is stored in the slot in export representation, so + * cycle through all known transparent accelerators */ + +#if defined(PSA_CRYPTO_ACCELERATOR_DRIVER_PRESENT) +#if defined(PSA_CRYPTO_DRIVER_TEST) + operation->id = MBEDTLS_TEST_TRANSPARENT_DRIVER_ID; + status = mbedtls_test_transparent_aead_decrypt_setup( + &operation->ctx.transparent_test_driver_ctx, + attributes, + key_buffer, key_buffer_size, + alg ); + + /* Declared with fallback == true */ + if( status != PSA_ERROR_NOT_SUPPORTED ) + return( status ); +#endif /* PSA_CRYPTO_DRIVER_TEST */ +#endif /* PSA_CRYPTO_ACCELERATOR_DRIVER_PRESENT */ + + /* Fell through, meaning no accelerator supports this operation */ + operation->id = PSA_CRYPTO_MBED_TLS_DRIVER_ID; + status = mbedtls_psa_aead_decrypt_setup( + &operation->ctx.mbedtls_ctx, + attributes, + key_buffer, key_buffer_size, + alg ); + + return( status ); + + /* Add cases for opaque driver here */ + + default: + /* Key is declared with a lifetime not known to us */ + (void)status; + return( PSA_ERROR_INVALID_ARGUMENT ); + } +} + +static inline psa_status_t psa_driver_wrapper_aead_set_nonce( + psa_aead_operation_t *operation, + const uint8_t *nonce, + size_t nonce_length ) +{ + switch( operation->id ) + { +#if defined(MBEDTLS_PSA_BUILTIN_AEAD) + case PSA_CRYPTO_MBED_TLS_DRIVER_ID: + return( mbedtls_psa_aead_set_nonce( &operation->ctx.mbedtls_ctx, + nonce, + nonce_length ) ); + +#endif /* MBEDTLS_PSA_BUILTIN_AEAD */ + +#if defined(PSA_CRYPTO_ACCELERATOR_DRIVER_PRESENT) +#if defined(PSA_CRYPTO_DRIVER_TEST) + case MBEDTLS_TEST_TRANSPARENT_DRIVER_ID: + return( mbedtls_test_transparent_aead_set_nonce( + &operation->ctx.transparent_test_driver_ctx, + nonce, nonce_length ) ); + + /* Add cases for opaque driver here */ + +#endif /* PSA_CRYPTO_DRIVER_TEST */ +#endif /* PSA_CRYPTO_ACCELERATOR_DRIVER_PRESENT */ + } + + (void)nonce; + (void)nonce_length; + + return( PSA_ERROR_INVALID_ARGUMENT ); +} + +static inline psa_status_t psa_driver_wrapper_aead_set_lengths( + psa_aead_operation_t *operation, + size_t ad_length, + size_t plaintext_length ) +{ + switch( operation->id ) + { +#if defined(MBEDTLS_PSA_BUILTIN_AEAD) + case PSA_CRYPTO_MBED_TLS_DRIVER_ID: + return( mbedtls_psa_aead_set_lengths( &operation->ctx.mbedtls_ctx, + ad_length, + plaintext_length ) ); + +#endif /* MBEDTLS_PSA_BUILTIN_AEAD */ + +#if defined(PSA_CRYPTO_ACCELERATOR_DRIVER_PRESENT) +#if defined(PSA_CRYPTO_DRIVER_TEST) + case MBEDTLS_TEST_TRANSPARENT_DRIVER_ID: + return( mbedtls_test_transparent_aead_set_lengths( + &operation->ctx.transparent_test_driver_ctx, + ad_length, plaintext_length ) ); + + /* Add cases for opaque driver here */ + +#endif /* PSA_CRYPTO_DRIVER_TEST */ +#endif /* PSA_CRYPTO_ACCELERATOR_DRIVER_PRESENT */ + } + + (void)ad_length; + (void)plaintext_length; + + return( PSA_ERROR_INVALID_ARGUMENT ); +} + +static inline psa_status_t psa_driver_wrapper_aead_update_ad( + psa_aead_operation_t *operation, + const uint8_t *input, + size_t input_length ) +{ + switch( operation->id ) + { +#if defined(MBEDTLS_PSA_BUILTIN_AEAD) + case PSA_CRYPTO_MBED_TLS_DRIVER_ID: + return( mbedtls_psa_aead_update_ad( &operation->ctx.mbedtls_ctx, + input, + input_length ) ); + +#endif /* MBEDTLS_PSA_BUILTIN_AEAD */ + +#if defined(PSA_CRYPTO_ACCELERATOR_DRIVER_PRESENT) +#if defined(PSA_CRYPTO_DRIVER_TEST) + case MBEDTLS_TEST_TRANSPARENT_DRIVER_ID: + return( mbedtls_test_transparent_aead_update_ad( + &operation->ctx.transparent_test_driver_ctx, + input, input_length ) ); + + /* Add cases for opaque driver here */ + +#endif /* PSA_CRYPTO_DRIVER_TEST */ +#endif /* PSA_CRYPTO_ACCELERATOR_DRIVER_PRESENT */ + } + + (void)input; + (void)input_length; + + return( PSA_ERROR_INVALID_ARGUMENT ); +} + +static inline psa_status_t psa_driver_wrapper_aead_update( + psa_aead_operation_t *operation, + const uint8_t *input, + size_t input_length, + uint8_t *output, + size_t output_size, + size_t *output_length ) +{ + switch( operation->id ) + { +#if defined(MBEDTLS_PSA_BUILTIN_AEAD) + case PSA_CRYPTO_MBED_TLS_DRIVER_ID: + return( mbedtls_psa_aead_update( &operation->ctx.mbedtls_ctx, + input, input_length, + output, output_size, + output_length ) ); + +#endif /* MBEDTLS_PSA_BUILTIN_AEAD */ + +#if defined(PSA_CRYPTO_ACCELERATOR_DRIVER_PRESENT) +#if defined(PSA_CRYPTO_DRIVER_TEST) + case MBEDTLS_TEST_TRANSPARENT_DRIVER_ID: + return( mbedtls_test_transparent_aead_update( + &operation->ctx.transparent_test_driver_ctx, + input, input_length, output, output_size, + output_length ) ); + + /* Add cases for opaque driver here */ + +#endif /* PSA_CRYPTO_DRIVER_TEST */ +#endif /* PSA_CRYPTO_ACCELERATOR_DRIVER_PRESENT */ + } + + (void)input; + (void)input_length; + (void)output; + (void)output_size; + (void)output_length; + + return( PSA_ERROR_INVALID_ARGUMENT ); +} + +static inline psa_status_t psa_driver_wrapper_aead_finish( + psa_aead_operation_t *operation, + uint8_t *ciphertext, + size_t ciphertext_size, + size_t *ciphertext_length, + uint8_t *tag, + size_t tag_size, + size_t *tag_length ) +{ + switch( operation->id ) + { +#if defined(MBEDTLS_PSA_BUILTIN_AEAD) + case PSA_CRYPTO_MBED_TLS_DRIVER_ID: + return( mbedtls_psa_aead_finish( &operation->ctx.mbedtls_ctx, + ciphertext, + ciphertext_size, + ciphertext_length, tag, + tag_size, tag_length ) ); + +#endif /* MBEDTLS_PSA_BUILTIN_AEAD */ + +#if defined(PSA_CRYPTO_ACCELERATOR_DRIVER_PRESENT) +#if defined(PSA_CRYPTO_DRIVER_TEST) + case MBEDTLS_TEST_TRANSPARENT_DRIVER_ID: + return( mbedtls_test_transparent_aead_finish( + &operation->ctx.transparent_test_driver_ctx, + ciphertext, ciphertext_size, + ciphertext_length, tag, tag_size, tag_length ) ); + + /* Add cases for opaque driver here */ + +#endif /* PSA_CRYPTO_DRIVER_TEST */ +#endif /* PSA_CRYPTO_ACCELERATOR_DRIVER_PRESENT */ + } + + (void)ciphertext; + (void)ciphertext_size; + (void)ciphertext_length; + (void)tag; + (void)tag_size; + (void)tag_length; + + return( PSA_ERROR_INVALID_ARGUMENT ); +} + +static inline psa_status_t psa_driver_wrapper_aead_verify( + psa_aead_operation_t *operation, + uint8_t *plaintext, + size_t plaintext_size, + size_t *plaintext_length, + const uint8_t *tag, + size_t tag_length ) +{ + switch( operation->id ) + { +#if defined(MBEDTLS_PSA_BUILTIN_AEAD) + case PSA_CRYPTO_MBED_TLS_DRIVER_ID: + { + psa_status_t status = PSA_ERROR_CORRUPTION_DETECTED; + uint8_t check_tag[PSA_AEAD_TAG_MAX_SIZE]; + size_t check_tag_length; + + status = mbedtls_psa_aead_finish( &operation->ctx.mbedtls_ctx, + plaintext, + plaintext_size, + plaintext_length, + check_tag, + sizeof( check_tag ), + &check_tag_length ); + + if( status == PSA_SUCCESS ) + { + if( tag_length != check_tag_length || + mbedtls_ct_memcmp( tag, check_tag, tag_length ) + != 0 ) + status = PSA_ERROR_INVALID_SIGNATURE; + } + + mbedtls_platform_zeroize( check_tag, sizeof( check_tag ) ); + + return( status ); + } + +#endif /* MBEDTLS_PSA_BUILTIN_AEAD */ + +#if defined(PSA_CRYPTO_ACCELERATOR_DRIVER_PRESENT) +#if defined(PSA_CRYPTO_DRIVER_TEST) + case MBEDTLS_TEST_TRANSPARENT_DRIVER_ID: + return( mbedtls_test_transparent_aead_verify( + &operation->ctx.transparent_test_driver_ctx, + plaintext, plaintext_size, + plaintext_length, tag, tag_length ) ); + + /* Add cases for opaque driver here */ + +#endif /* PSA_CRYPTO_DRIVER_TEST */ +#endif /* PSA_CRYPTO_ACCELERATOR_DRIVER_PRESENT */ + } + + (void)plaintext; + (void)plaintext_size; + (void)plaintext_length; + (void)tag; + (void)tag_length; + + return( PSA_ERROR_INVALID_ARGUMENT ); +} + +static inline psa_status_t psa_driver_wrapper_aead_abort( + psa_aead_operation_t *operation ) +{ + switch( operation->id ) + { +#if defined(MBEDTLS_PSA_BUILTIN_AEAD) + case PSA_CRYPTO_MBED_TLS_DRIVER_ID: + return( mbedtls_psa_aead_abort( &operation->ctx.mbedtls_ctx ) ); + +#endif /* MBEDTLS_PSA_BUILTIN_AEAD */ + +#if defined(PSA_CRYPTO_ACCELERATOR_DRIVER_PRESENT) +#if defined(PSA_CRYPTO_DRIVER_TEST) + case MBEDTLS_TEST_TRANSPARENT_DRIVER_ID: + return( mbedtls_test_transparent_aead_abort( + &operation->ctx.transparent_test_driver_ctx ) ); + + /* Add cases for opaque driver here */ + +#endif /* PSA_CRYPTO_DRIVER_TEST */ +#endif /* PSA_CRYPTO_ACCELERATOR_DRIVER_PRESENT */ + } + + return( PSA_ERROR_INVALID_ARGUMENT ); +} /* * MAC functions */ -psa_status_t psa_driver_wrapper_mac_compute( +static inline psa_status_t psa_driver_wrapper_mac_compute( const psa_key_attributes_t *attributes, const uint8_t *key_buffer, size_t key_buffer_size, @@ -228,41 +2202,696 @@ psa_status_t psa_driver_wrapper_mac_compute( size_t input_length, uint8_t *mac, size_t mac_size, - size_t *mac_length); + size_t *mac_length ) +{ + psa_status_t status = PSA_ERROR_CORRUPTION_DETECTED; + psa_key_location_t location = + PSA_KEY_LIFETIME_GET_LOCATION( psa_get_key_lifetime(attributes) ); + + switch( location ) + { + case PSA_KEY_LOCATION_LOCAL_STORAGE: + /* Key is stored in the slot in export representation, so + * cycle through all known transparent accelerators */ +#if defined(PSA_CRYPTO_ACCELERATOR_DRIVER_PRESENT) +#if defined(PSA_CRYPTO_DRIVER_TEST) + status = mbedtls_test_transparent_mac_compute( + attributes, key_buffer, key_buffer_size, alg, + input, input_length, + mac, mac_size, mac_length ); + /* Declared with fallback == true */ + if( status != PSA_ERROR_NOT_SUPPORTED ) + return( status ); +#endif /* PSA_CRYPTO_DRIVER_TEST */ +#endif /* PSA_CRYPTO_ACCELERATOR_DRIVER_PRESENT */ +#if defined(MBEDTLS_PSA_BUILTIN_MAC) + /* Fell through, meaning no accelerator supports this operation */ + status = mbedtls_psa_mac_compute( + attributes, key_buffer, key_buffer_size, alg, + input, input_length, + mac, mac_size, mac_length ); + if( status != PSA_ERROR_NOT_SUPPORTED ) + return( status ); +#endif /* MBEDTLS_PSA_BUILTIN_MAC */ + return( PSA_ERROR_NOT_SUPPORTED ); + + /* Add cases for opaque driver here */ +#if defined(PSA_CRYPTO_ACCELERATOR_DRIVER_PRESENT) +#if defined(PSA_CRYPTO_DRIVER_TEST) + case PSA_CRYPTO_TEST_DRIVER_LOCATION: + status = mbedtls_test_opaque_mac_compute( + attributes, key_buffer, key_buffer_size, alg, + input, input_length, + mac, mac_size, mac_length ); + return( status ); +#endif /* PSA_CRYPTO_DRIVER_TEST */ +#endif /* PSA_CRYPTO_ACCELERATOR_DRIVER_PRESENT */ + default: + /* Key is declared with a lifetime not known to us */ + (void) key_buffer; + (void) key_buffer_size; + (void) alg; + (void) input; + (void) input_length; + (void) mac; + (void) mac_size; + (void) mac_length; + (void) status; + return( PSA_ERROR_INVALID_ARGUMENT ); + } +} -psa_status_t psa_driver_wrapper_mac_sign_setup( +static inline psa_status_t psa_driver_wrapper_mac_sign_setup( psa_mac_operation_t *operation, const psa_key_attributes_t *attributes, const uint8_t *key_buffer, size_t key_buffer_size, - psa_algorithm_t alg); + psa_algorithm_t alg ) +{ + psa_status_t status = PSA_ERROR_CORRUPTION_DETECTED; + psa_key_location_t location = + PSA_KEY_LIFETIME_GET_LOCATION( psa_get_key_lifetime(attributes) ); -psa_status_t psa_driver_wrapper_mac_verify_setup( + switch( location ) + { + case PSA_KEY_LOCATION_LOCAL_STORAGE: + /* Key is stored in the slot in export representation, so + * cycle through all known transparent accelerators */ +#if defined(PSA_CRYPTO_ACCELERATOR_DRIVER_PRESENT) +#if defined(PSA_CRYPTO_DRIVER_TEST) + status = mbedtls_test_transparent_mac_sign_setup( + &operation->ctx.transparent_test_driver_ctx, + attributes, + key_buffer, key_buffer_size, + alg ); + /* Declared with fallback == true */ + if( status == PSA_SUCCESS ) + operation->id = MBEDTLS_TEST_TRANSPARENT_DRIVER_ID; + + if( status != PSA_ERROR_NOT_SUPPORTED ) + return( status ); +#endif /* PSA_CRYPTO_DRIVER_TEST */ +#endif /* PSA_CRYPTO_ACCELERATOR_DRIVER_PRESENT */ +#if defined(MBEDTLS_PSA_BUILTIN_MAC) + /* Fell through, meaning no accelerator supports this operation */ + status = mbedtls_psa_mac_sign_setup( &operation->ctx.mbedtls_ctx, + attributes, + key_buffer, key_buffer_size, + alg ); + if( status == PSA_SUCCESS ) + operation->id = PSA_CRYPTO_MBED_TLS_DRIVER_ID; + + if( status != PSA_ERROR_NOT_SUPPORTED ) + return( status ); +#endif /* MBEDTLS_PSA_BUILTIN_MAC */ + return( PSA_ERROR_NOT_SUPPORTED ); + + /* Add cases for opaque driver here */ +#if defined(PSA_CRYPTO_ACCELERATOR_DRIVER_PRESENT) +#if defined(PSA_CRYPTO_DRIVER_TEST) + case PSA_CRYPTO_TEST_DRIVER_LOCATION: + status = mbedtls_test_opaque_mac_sign_setup( + &operation->ctx.opaque_test_driver_ctx, + attributes, + key_buffer, key_buffer_size, + alg ); + + if( status == PSA_SUCCESS ) + operation->id = MBEDTLS_TEST_OPAQUE_DRIVER_ID; + + return( status ); +#endif /* PSA_CRYPTO_DRIVER_TEST */ +#endif /* PSA_CRYPTO_ACCELERATOR_DRIVER_PRESENT */ + default: + /* Key is declared with a lifetime not known to us */ + (void) status; + (void) operation; + (void) key_buffer; + (void) key_buffer_size; + (void) alg; + return( PSA_ERROR_INVALID_ARGUMENT ); + } +} + +static inline psa_status_t psa_driver_wrapper_mac_verify_setup( psa_mac_operation_t *operation, const psa_key_attributes_t *attributes, const uint8_t *key_buffer, size_t key_buffer_size, - psa_algorithm_t alg); + psa_algorithm_t alg ) +{ + psa_status_t status = PSA_ERROR_CORRUPTION_DETECTED; + psa_key_location_t location = + PSA_KEY_LIFETIME_GET_LOCATION( psa_get_key_lifetime(attributes) ); + + switch( location ) + { + case PSA_KEY_LOCATION_LOCAL_STORAGE: + /* Key is stored in the slot in export representation, so + * cycle through all known transparent accelerators */ +#if defined(PSA_CRYPTO_ACCELERATOR_DRIVER_PRESENT) +#if defined(PSA_CRYPTO_DRIVER_TEST) + status = mbedtls_test_transparent_mac_verify_setup( + &operation->ctx.transparent_test_driver_ctx, + attributes, + key_buffer, key_buffer_size, + alg ); + /* Declared with fallback == true */ + if( status == PSA_SUCCESS ) + operation->id = MBEDTLS_TEST_TRANSPARENT_DRIVER_ID; + + if( status != PSA_ERROR_NOT_SUPPORTED ) + return( status ); +#endif /* PSA_CRYPTO_DRIVER_TEST */ +#endif /* PSA_CRYPTO_ACCELERATOR_DRIVER_PRESENT */ +#if defined(MBEDTLS_PSA_BUILTIN_MAC) + /* Fell through, meaning no accelerator supports this operation */ + status = mbedtls_psa_mac_verify_setup( &operation->ctx.mbedtls_ctx, + attributes, + key_buffer, key_buffer_size, + alg ); + if( status == PSA_SUCCESS ) + operation->id = PSA_CRYPTO_MBED_TLS_DRIVER_ID; + + if( status != PSA_ERROR_NOT_SUPPORTED ) + return( status ); +#endif /* MBEDTLS_PSA_BUILTIN_MAC */ + return( PSA_ERROR_NOT_SUPPORTED ); + + /* Add cases for opaque driver here */ +#if defined(PSA_CRYPTO_ACCELERATOR_DRIVER_PRESENT) +#if defined(PSA_CRYPTO_DRIVER_TEST) + case PSA_CRYPTO_TEST_DRIVER_LOCATION: + status = mbedtls_test_opaque_mac_verify_setup( + &operation->ctx.opaque_test_driver_ctx, + attributes, + key_buffer, key_buffer_size, + alg ); -psa_status_t psa_driver_wrapper_mac_update( + if( status == PSA_SUCCESS ) + operation->id = MBEDTLS_TEST_OPAQUE_DRIVER_ID; + + return( status ); +#endif /* PSA_CRYPTO_DRIVER_TEST */ +#endif /* PSA_CRYPTO_ACCELERATOR_DRIVER_PRESENT */ + default: + /* Key is declared with a lifetime not known to us */ + (void) status; + (void) operation; + (void) key_buffer; + (void) key_buffer_size; + (void) alg; + return( PSA_ERROR_INVALID_ARGUMENT ); + } +} + +static inline psa_status_t psa_driver_wrapper_mac_update( psa_mac_operation_t *operation, const uint8_t *input, - size_t input_length); + size_t input_length ) +{ + switch( operation->id ) + { +#if defined(MBEDTLS_PSA_BUILTIN_MAC) + case PSA_CRYPTO_MBED_TLS_DRIVER_ID: + return( mbedtls_psa_mac_update( &operation->ctx.mbedtls_ctx, + input, input_length ) ); +#endif /* MBEDTLS_PSA_BUILTIN_MAC */ + +#if defined(PSA_CRYPTO_ACCELERATOR_DRIVER_PRESENT) +#if defined(PSA_CRYPTO_DRIVER_TEST) + case MBEDTLS_TEST_TRANSPARENT_DRIVER_ID: + return( mbedtls_test_transparent_mac_update( + &operation->ctx.transparent_test_driver_ctx, + input, input_length ) ); -psa_status_t psa_driver_wrapper_mac_sign_finish( + case MBEDTLS_TEST_OPAQUE_DRIVER_ID: + return( mbedtls_test_opaque_mac_update( + &operation->ctx.opaque_test_driver_ctx, + input, input_length ) ); +#endif /* PSA_CRYPTO_DRIVER_TEST */ +#endif /* PSA_CRYPTO_ACCELERATOR_DRIVER_PRESENT */ + default: + (void) input; + (void) input_length; + return( PSA_ERROR_INVALID_ARGUMENT ); + } +} + +static inline psa_status_t psa_driver_wrapper_mac_sign_finish( psa_mac_operation_t *operation, uint8_t *mac, size_t mac_size, - size_t *mac_length); + size_t *mac_length ) +{ + switch( operation->id ) + { +#if defined(MBEDTLS_PSA_BUILTIN_MAC) + case PSA_CRYPTO_MBED_TLS_DRIVER_ID: + return( mbedtls_psa_mac_sign_finish( &operation->ctx.mbedtls_ctx, + mac, mac_size, mac_length ) ); +#endif /* MBEDTLS_PSA_BUILTIN_MAC */ + +#if defined(PSA_CRYPTO_ACCELERATOR_DRIVER_PRESENT) +#if defined(PSA_CRYPTO_DRIVER_TEST) + case MBEDTLS_TEST_TRANSPARENT_DRIVER_ID: + return( mbedtls_test_transparent_mac_sign_finish( + &operation->ctx.transparent_test_driver_ctx, + mac, mac_size, mac_length ) ); -psa_status_t psa_driver_wrapper_mac_verify_finish( + case MBEDTLS_TEST_OPAQUE_DRIVER_ID: + return( mbedtls_test_opaque_mac_sign_finish( + &operation->ctx.opaque_test_driver_ctx, + mac, mac_size, mac_length ) ); +#endif /* PSA_CRYPTO_DRIVER_TEST */ +#endif /* PSA_CRYPTO_ACCELERATOR_DRIVER_PRESENT */ + default: + (void) mac; + (void) mac_size; + (void) mac_length; + return( PSA_ERROR_INVALID_ARGUMENT ); + } +} + +static inline psa_status_t psa_driver_wrapper_mac_verify_finish( psa_mac_operation_t *operation, const uint8_t *mac, - size_t mac_length); + size_t mac_length ) +{ + switch( operation->id ) + { +#if defined(MBEDTLS_PSA_BUILTIN_MAC) + case PSA_CRYPTO_MBED_TLS_DRIVER_ID: + return( mbedtls_psa_mac_verify_finish( &operation->ctx.mbedtls_ctx, + mac, mac_length ) ); +#endif /* MBEDTLS_PSA_BUILTIN_MAC */ + +#if defined(PSA_CRYPTO_ACCELERATOR_DRIVER_PRESENT) +#if defined(PSA_CRYPTO_DRIVER_TEST) + case MBEDTLS_TEST_TRANSPARENT_DRIVER_ID: + return( mbedtls_test_transparent_mac_verify_finish( + &operation->ctx.transparent_test_driver_ctx, + mac, mac_length ) ); + + case MBEDTLS_TEST_OPAQUE_DRIVER_ID: + return( mbedtls_test_opaque_mac_verify_finish( + &operation->ctx.opaque_test_driver_ctx, + mac, mac_length ) ); +#endif /* PSA_CRYPTO_DRIVER_TEST */ +#endif /* PSA_CRYPTO_ACCELERATOR_DRIVER_PRESENT */ + default: + (void) mac; + (void) mac_length; + return( PSA_ERROR_INVALID_ARGUMENT ); + } +} + +static inline psa_status_t psa_driver_wrapper_mac_abort( + psa_mac_operation_t *operation ) +{ + switch( operation->id ) + { +#if defined(MBEDTLS_PSA_BUILTIN_MAC) + case PSA_CRYPTO_MBED_TLS_DRIVER_ID: + return( mbedtls_psa_mac_abort( &operation->ctx.mbedtls_ctx ) ); +#endif /* MBEDTLS_PSA_BUILTIN_MAC */ + +#if defined(PSA_CRYPTO_ACCELERATOR_DRIVER_PRESENT) +#if defined(PSA_CRYPTO_DRIVER_TEST) + case MBEDTLS_TEST_TRANSPARENT_DRIVER_ID: + return( mbedtls_test_transparent_mac_abort( + &operation->ctx.transparent_test_driver_ctx ) ); + case MBEDTLS_TEST_OPAQUE_DRIVER_ID: + return( mbedtls_test_opaque_mac_abort( + &operation->ctx.opaque_test_driver_ctx ) ); +#endif /* PSA_CRYPTO_DRIVER_TEST */ +#endif /* PSA_CRYPTO_ACCELERATOR_DRIVER_PRESENT */ + default: + return( PSA_ERROR_INVALID_ARGUMENT ); + } +} + +/* + * Asymmetric cryptography + */ +static inline psa_status_t psa_driver_wrapper_asymmetric_encrypt( + const psa_key_attributes_t *attributes, const uint8_t *key_buffer, + size_t key_buffer_size, psa_algorithm_t alg, const uint8_t *input, + size_t input_length, const uint8_t *salt, size_t salt_length, + uint8_t *output, size_t output_size, size_t *output_length ) +{ + psa_status_t status = PSA_ERROR_CORRUPTION_DETECTED; + psa_key_location_t location = + PSA_KEY_LIFETIME_GET_LOCATION( psa_get_key_lifetime(attributes) ); + + switch( location ) + { + case PSA_KEY_LOCATION_LOCAL_STORAGE: + /* Key is stored in the slot in export representation, so + * cycle through all known transparent accelerators */ +#if defined(PSA_CRYPTO_ACCELERATOR_DRIVER_PRESENT) +#if defined(PSA_CRYPTO_DRIVER_TEST) + status = mbedtls_test_transparent_asymmetric_encrypt( attributes, + key_buffer, key_buffer_size, alg, input, input_length, + salt, salt_length, output, output_size, + output_length ); + /* Declared with fallback == true */ + if( status != PSA_ERROR_NOT_SUPPORTED ) + return( status ); +#endif /* PSA_CRYPTO_DRIVER_TEST */ +#endif /* PSA_CRYPTO_ACCELERATOR_DRIVER_PRESENT */ + return( mbedtls_psa_asymmetric_encrypt( attributes, + key_buffer, key_buffer_size, alg, input, input_length, + salt, salt_length, output, output_size, output_length ) + ); + /* Add cases for opaque driver here */ +#if defined(PSA_CRYPTO_ACCELERATOR_DRIVER_PRESENT) +#if defined(PSA_CRYPTO_DRIVER_TEST) + case PSA_CRYPTO_TEST_DRIVER_LOCATION: + return( mbedtls_test_opaque_asymmetric_encrypt( attributes, + key_buffer, key_buffer_size, alg, input, input_length, + salt, salt_length, output, output_size, output_length ) + ); +#endif /* PSA_CRYPTO_DRIVER_TEST */ +#endif /* PSA_CRYPTO_ACCELERATOR_DRIVER_PRESENT */ + + default: + /* Key is declared with a lifetime not known to us */ + (void)status; + (void)key_buffer; + (void)key_buffer_size; + (void)alg; + (void)input; + (void)input_length; + (void)salt; + (void)salt_length; + (void)output; + (void)output_size; + (void)output_length; + return( PSA_ERROR_INVALID_ARGUMENT ); + } +} + +static inline psa_status_t psa_driver_wrapper_asymmetric_decrypt( + const psa_key_attributes_t *attributes, const uint8_t *key_buffer, + size_t key_buffer_size, psa_algorithm_t alg, const uint8_t *input, + size_t input_length, const uint8_t *salt, size_t salt_length, + uint8_t *output, size_t output_size, size_t *output_length ) +{ + psa_status_t status = PSA_ERROR_CORRUPTION_DETECTED; + psa_key_location_t location = + PSA_KEY_LIFETIME_GET_LOCATION( psa_get_key_lifetime(attributes) ); + + switch( location ) + { + case PSA_KEY_LOCATION_LOCAL_STORAGE: + /* Key is stored in the slot in export representation, so + * cycle through all known transparent accelerators */ +#if defined(PSA_CRYPTO_ACCELERATOR_DRIVER_PRESENT) +#if defined(PSA_CRYPTO_DRIVER_TEST) + status = mbedtls_test_transparent_asymmetric_decrypt( attributes, + key_buffer, key_buffer_size, alg, input, input_length, + salt, salt_length, output, output_size, + output_length ); + /* Declared with fallback == true */ + if( status != PSA_ERROR_NOT_SUPPORTED ) + return( status ); +#endif /* PSA_CRYPTO_DRIVER_TEST */ +#endif /* PSA_CRYPTO_ACCELERATOR_DRIVER_PRESENT */ + return( mbedtls_psa_asymmetric_decrypt( attributes, + key_buffer, key_buffer_size, alg,input, input_length, + salt, salt_length, output, output_size, + output_length ) ); + /* Add cases for opaque driver here */ +#if defined(PSA_CRYPTO_ACCELERATOR_DRIVER_PRESENT) +#if defined(PSA_CRYPTO_DRIVER_TEST) + case PSA_CRYPTO_TEST_DRIVER_LOCATION: + return( mbedtls_test_opaque_asymmetric_decrypt( attributes, + key_buffer, key_buffer_size, alg, input, input_length, + salt, salt_length, output, output_size, + output_length ) ); +#endif /* PSA_CRYPTO_DRIVER_TEST */ +#endif /* PSA_CRYPTO_ACCELERATOR_DRIVER_PRESENT */ + + default: + /* Key is declared with a lifetime not known to us */ + (void)status; + (void)key_buffer; + (void)key_buffer_size; + (void)alg; + (void)input; + (void)input_length; + (void)salt; + (void)salt_length; + (void)output; + (void)output_size; + (void)output_length; + return( PSA_ERROR_INVALID_ARGUMENT ); + } +} + +static inline psa_status_t psa_driver_wrapper_key_agreement( + const psa_key_attributes_t *attributes, + const uint8_t *key_buffer, + size_t key_buffer_size, + psa_algorithm_t alg, + const uint8_t *peer_key, + size_t peer_key_length, + uint8_t *shared_secret, + size_t shared_secret_size, + size_t *shared_secret_length + ) +{ + psa_status_t status = PSA_ERROR_CORRUPTION_DETECTED; + psa_key_location_t location = + PSA_KEY_LIFETIME_GET_LOCATION( psa_get_key_lifetime(attributes) ); + + switch( location ) + { + case PSA_KEY_LOCATION_LOCAL_STORAGE: + /* Key is stored in the slot in export representation, so + * cycle through all known transparent accelerators */ +#if defined(PSA_CRYPTO_ACCELERATOR_DRIVER_PRESENT) +#if defined(PSA_CRYPTO_DRIVER_TEST) + status = + mbedtls_test_transparent_key_agreement( attributes, + key_buffer, key_buffer_size, alg, peer_key, + peer_key_length, shared_secret, shared_secret_size, + shared_secret_length ); + if( status != PSA_ERROR_NOT_SUPPORTED ) + return( status ); +#endif /* PSA_CRYPTO_DRIVER_TEST */ +#if defined(MBEDTLS_PSA_P256M_DRIVER_ENABLED) + if( PSA_KEY_TYPE_IS_ECC( psa_get_key_type(attributes) ) && + PSA_ALG_IS_ECDH(alg) && + PSA_KEY_TYPE_ECC_GET_FAMILY(psa_get_key_type(attributes)) == PSA_ECC_FAMILY_SECP_R1 && + psa_get_key_bits(attributes) == 256 ) + { + status = p256_transparent_key_agreement( attributes, + key_buffer, + key_buffer_size, + alg, + peer_key, + peer_key_length, + shared_secret, + shared_secret_size, + shared_secret_length ); + if( status != PSA_ERROR_NOT_SUPPORTED) + return( status ); + } +#endif /* MBEDTLS_PSA_P256M_DRIVER_ENABLED */ +#endif /* PSA_CRYPTO_ACCELERATOR_DRIVER_PRESENT */ + + /* Software Fallback */ + status = psa_key_agreement_raw_builtin( attributes, + key_buffer, + key_buffer_size, + alg, + peer_key, + peer_key_length, + shared_secret, + shared_secret_size, + shared_secret_length ); + return( status ); +#if defined(PSA_CRYPTO_ACCELERATOR_DRIVER_PRESENT) +#if defined(PSA_CRYPTO_DRIVER_TEST) + case PSA_CRYPTO_TEST_DRIVER_LOCATION: + return( mbedtls_test_opaque_key_agreement( attributes, + key_buffer, key_buffer_size, alg, peer_key, + peer_key_length, shared_secret, shared_secret_size, + shared_secret_length ) ); +#endif /* PSA_CRYPTO_DRIVER_TEST */ +#endif /* PSA_CRYPTO_ACCELERATOR_DRIVER_PRESENT */ + + default: + (void) attributes; + (void) key_buffer; + (void) key_buffer_size; + (void) peer_key; + (void) peer_key_length; + (void) shared_secret; + (void) shared_secret_size; + (void) shared_secret_length; + return( PSA_ERROR_NOT_SUPPORTED ); + + } +} + +static inline psa_status_t psa_driver_wrapper_pake_setup( + psa_pake_operation_t *operation, + const psa_crypto_driver_pake_inputs_t *inputs ) +{ + psa_status_t status = PSA_ERROR_CORRUPTION_DETECTED; + + psa_key_location_t location = + PSA_KEY_LIFETIME_GET_LOCATION( psa_get_key_lifetime( &inputs->attributes ) ); + + switch( location ) + { + case PSA_KEY_LOCATION_LOCAL_STORAGE: + /* Key is stored in the slot in export representation, so + * cycle through all known transparent accelerators */ + status = PSA_ERROR_NOT_SUPPORTED; +#if defined(PSA_CRYPTO_ACCELERATOR_DRIVER_PRESENT) +#if defined(PSA_CRYPTO_DRIVER_TEST) + status = mbedtls_test_transparent_pake_setup( + &operation->data.ctx.transparent_test_driver_ctx, + inputs ); + if( status == PSA_SUCCESS ) + operation->id = MBEDTLS_TEST_TRANSPARENT_DRIVER_ID; + /* Declared with fallback == true */ + if( status != PSA_ERROR_NOT_SUPPORTED ) + return( status ); +#endif /* PSA_CRYPTO_DRIVER_TEST */ +#endif /* PSA_CRYPTO_ACCELERATOR_DRIVER_PRESENT */ +#if defined(MBEDTLS_PSA_BUILTIN_PAKE) + status = mbedtls_psa_pake_setup( &operation->data.ctx.mbedtls_ctx, + inputs ); + if( status == PSA_SUCCESS ) + operation->id = PSA_CRYPTO_MBED_TLS_DRIVER_ID; +#endif + return status; + /* Add cases for opaque driver here */ + default: + /* Key is declared with a lifetime not known to us */ + (void)operation; + return( PSA_ERROR_INVALID_ARGUMENT ); + } +} + +static inline psa_status_t psa_driver_wrapper_pake_output( + psa_pake_operation_t *operation, + psa_crypto_driver_pake_step_t step, + uint8_t *output, + size_t output_size, + size_t *output_length ) +{ + switch( operation->id ) + { +#if defined(MBEDTLS_PSA_BUILTIN_PAKE) + case PSA_CRYPTO_MBED_TLS_DRIVER_ID: + return( mbedtls_psa_pake_output( &operation->data.ctx.mbedtls_ctx, step, + output, output_size, output_length ) ); +#endif /* MBEDTLS_PSA_BUILTIN_PAKE */ + +#if defined(PSA_CRYPTO_ACCELERATOR_DRIVER_PRESENT) +#if defined(PSA_CRYPTO_DRIVER_TEST) + case MBEDTLS_TEST_TRANSPARENT_DRIVER_ID: + return( mbedtls_test_transparent_pake_output( + &operation->data.ctx.transparent_test_driver_ctx, + step, output, output_size, output_length ) ); +#endif /* PSA_CRYPTO_DRIVER_TEST */ +#endif /* PSA_CRYPTO_ACCELERATOR_DRIVER_PRESENT */ + default: + (void) step; + (void) output; + (void) output_size; + (void) output_length; + return( PSA_ERROR_INVALID_ARGUMENT ); + } +} + +static inline psa_status_t psa_driver_wrapper_pake_input( + psa_pake_operation_t *operation, + psa_crypto_driver_pake_step_t step, + const uint8_t *input, + size_t input_length ) +{ + switch( operation->id ) + { +#if defined(MBEDTLS_PSA_BUILTIN_PAKE) + case PSA_CRYPTO_MBED_TLS_DRIVER_ID: + return( mbedtls_psa_pake_input( &operation->data.ctx.mbedtls_ctx, + step, input, + input_length ) ); +#endif /* MBEDTLS_PSA_BUILTIN_PAKE */ + +#if defined(PSA_CRYPTO_ACCELERATOR_DRIVER_PRESENT) +#if defined(PSA_CRYPTO_DRIVER_TEST) + case MBEDTLS_TEST_TRANSPARENT_DRIVER_ID: + return( mbedtls_test_transparent_pake_input( + &operation->data.ctx.transparent_test_driver_ctx, + step, + input, input_length ) ); +#endif /* PSA_CRYPTO_DRIVER_TEST */ +#endif /* PSA_CRYPTO_ACCELERATOR_DRIVER_PRESENT */ + default: + (void) step; + (void) input; + (void) input_length; + return( PSA_ERROR_INVALID_ARGUMENT ); + } +} + +static inline psa_status_t psa_driver_wrapper_pake_get_implicit_key( + psa_pake_operation_t *operation, + uint8_t *output, size_t output_size, + size_t *output_length ) +{ + switch( operation->id ) + { +#if defined(MBEDTLS_PSA_BUILTIN_PAKE) + case PSA_CRYPTO_MBED_TLS_DRIVER_ID: + return( mbedtls_psa_pake_get_implicit_key( &operation->data.ctx.mbedtls_ctx, + output, output_size, output_length ) ); +#endif /* MBEDTLS_PSA_BUILTIN_PAKE */ + +#if defined(PSA_CRYPTO_ACCELERATOR_DRIVER_PRESENT) +#if defined(PSA_CRYPTO_DRIVER_TEST) + case MBEDTLS_TEST_TRANSPARENT_DRIVER_ID: + return( mbedtls_test_transparent_pake_get_implicit_key( + &operation->data.ctx.transparent_test_driver_ctx, + output, output_size, output_length ) ); +#endif /* PSA_CRYPTO_DRIVER_TEST */ +#endif /* PSA_CRYPTO_ACCELERATOR_DRIVER_PRESENT */ + default: + (void) output; + (void) output_size; + (void) output_length; + return( PSA_ERROR_INVALID_ARGUMENT ); + } +} -psa_status_t psa_driver_wrapper_mac_abort( - psa_mac_operation_t *operation); +static inline psa_status_t psa_driver_wrapper_pake_abort( + psa_pake_operation_t * operation ) +{ + switch( operation->id ) + { +#if defined(MBEDTLS_PSA_BUILTIN_PAKE) + case PSA_CRYPTO_MBED_TLS_DRIVER_ID: + return( mbedtls_psa_pake_abort( &operation->data.ctx.mbedtls_ctx ) ); +#endif /* MBEDTLS_PSA_BUILTIN_PAKE */ -#endif /* PSA_CRYPTO_DRIVER_WRAPPERS_H */ +#if defined(PSA_CRYPTO_ACCELERATOR_DRIVER_PRESENT) +#if defined(PSA_CRYPTO_DRIVER_TEST) + case MBEDTLS_TEST_TRANSPARENT_DRIVER_ID: + return( mbedtls_test_transparent_pake_abort( + &operation->data.ctx.transparent_test_driver_ctx ) ); +#endif /* PSA_CRYPTO_DRIVER_TEST */ +#endif /* PSA_CRYPTO_ACCELERATOR_DRIVER_PRESENT */ + default: + return( PSA_ERROR_INVALID_ARGUMENT ); + } +} -/* End of automatically generated file. */ +#endif /* MBEDTLS_PSA_CRYPTO_C */ diff --git a/vendor/mbedtls/library/psa_crypto_driver_wrappers_no_static.c b/vendor/mbedtls/library/psa_crypto_driver_wrappers_no_static.c new file mode 100644 index 0000000000..de8a5269b3 --- /dev/null +++ b/vendor/mbedtls/library/psa_crypto_driver_wrappers_no_static.c @@ -0,0 +1,256 @@ +/* + * Functions to delegate cryptographic operations to an available + * and appropriate accelerator. + * Warning: This file is now auto-generated. + */ +/* Copyright The Mbed TLS Contributors + * SPDX-License-Identifier: Apache-2.0 OR GPL-2.0-or-later + */ + + +/* BEGIN-common headers */ +#include "common.h" +#include "psa_crypto_aead.h" +#include "psa_crypto_cipher.h" +#include "psa_crypto_core.h" +#include "psa_crypto_driver_wrappers_no_static.h" +#include "psa_crypto_hash.h" +#include "psa_crypto_mac.h" +#include "psa_crypto_pake.h" +#include "psa_crypto_rsa.h" + +#include "mbedtls/platform.h" +/* END-common headers */ + +#if defined(MBEDTLS_PSA_CRYPTO_C) + +/* BEGIN-driver headers */ +/* Headers for mbedtls_test opaque driver */ +#if defined(PSA_CRYPTO_DRIVER_TEST) +#include "test/drivers/test_driver.h" + +#endif +/* Headers for mbedtls_test transparent driver */ +#if defined(PSA_CRYPTO_DRIVER_TEST) +#include "test/drivers/test_driver.h" + +#endif +/* Headers for p256 transparent driver */ +#if defined(MBEDTLS_PSA_P256M_DRIVER_ENABLED) +#include "../3rdparty/p256-m/p256-m_driver_entrypoints.h" + +#endif + +/* END-driver headers */ + +/* Auto-generated values depending on which drivers are registered. + * ID 0 is reserved for unallocated operations. + * ID 1 is reserved for the Mbed TLS software driver. */ +/* BEGIN-driver id definition */ +#define PSA_CRYPTO_MBED_TLS_DRIVER_ID (1) +#define MBEDTLS_TEST_OPAQUE_DRIVER_ID (2) +#define MBEDTLS_TEST_TRANSPARENT_DRIVER_ID (3) +#define P256_TRANSPARENT_DRIVER_ID (4) + +/* END-driver id */ + +/* BEGIN-Common Macro definitions */ + +/* END-Common Macro definitions */ + +/* Support the 'old' SE interface when asked to */ +#if defined(MBEDTLS_PSA_CRYPTO_SE_C) +/* PSA_CRYPTO_DRIVER_PRESENT is defined when either a new-style or old-style + * SE driver is present, to avoid unused argument errors at compile time. */ +#ifndef PSA_CRYPTO_DRIVER_PRESENT +#define PSA_CRYPTO_DRIVER_PRESENT +#endif +#include "psa_crypto_se.h" +#endif + +/** Get the key buffer size required to store the key material of a key + * associated with an opaque driver. + * + * \param[in] attributes The key attributes. + * \param[out] key_buffer_size Minimum buffer size to contain the key material + * + * \retval #PSA_SUCCESS + * The minimum size for a buffer to contain the key material has been + * returned successfully. + * \retval #PSA_ERROR_NOT_SUPPORTED + * The type and/or the size in bits of the key or the combination of + * the two is not supported. + * \retval #PSA_ERROR_INVALID_ARGUMENT + * The key is declared with a lifetime not known to us. + */ +psa_status_t psa_driver_wrapper_get_key_buffer_size( + const psa_key_attributes_t *attributes, + size_t *key_buffer_size ) +{ + psa_key_location_t location = PSA_KEY_LIFETIME_GET_LOCATION( psa_get_key_lifetime(attributes) ); + psa_key_type_t key_type = psa_get_key_type(attributes); + size_t key_bits = psa_get_key_bits(attributes); + + *key_buffer_size = 0; + switch( location ) + { +#if defined(PSA_CRYPTO_DRIVER_TEST) + case PSA_CRYPTO_TEST_DRIVER_LOCATION: +#if defined(MBEDTLS_PSA_CRYPTO_BUILTIN_KEYS) + /* Emulate property 'builtin_key_size' */ + if( psa_key_id_is_builtin( + MBEDTLS_SVC_KEY_ID_GET_KEY_ID( + psa_get_key_id( attributes ) ) ) ) + { + *key_buffer_size = sizeof( psa_drv_slot_number_t ); + return( PSA_SUCCESS ); + } +#endif /* MBEDTLS_PSA_CRYPTO_BUILTIN_KEYS */ + *key_buffer_size = mbedtls_test_opaque_size_function( key_type, + key_bits ); + return( ( *key_buffer_size != 0 ) ? + PSA_SUCCESS : PSA_ERROR_NOT_SUPPORTED ); +#endif /* PSA_CRYPTO_DRIVER_TEST */ + + default: + (void)key_type; + (void)key_bits; + return( PSA_ERROR_INVALID_ARGUMENT ); + } +} + +psa_status_t psa_driver_wrapper_export_public_key( + const psa_key_attributes_t *attributes, + const uint8_t *key_buffer, size_t key_buffer_size, + uint8_t *data, size_t data_size, size_t *data_length ) + +{ + + psa_status_t status = PSA_ERROR_INVALID_ARGUMENT; + psa_key_location_t location = PSA_KEY_LIFETIME_GET_LOCATION( + psa_get_key_lifetime( attributes ) ); + + /* Try dynamically-registered SE interface first */ +#if defined(MBEDTLS_PSA_CRYPTO_SE_C) + const psa_drv_se_t *drv; + psa_drv_se_context_t *drv_context; + + if( psa_get_se_driver( psa_get_key_lifetime(attributes), &drv, &drv_context ) ) + { + if( ( drv->key_management == NULL ) || + ( drv->key_management->p_export_public == NULL ) ) + { + return( PSA_ERROR_NOT_SUPPORTED ); + } + + return( drv->key_management->p_export_public( + drv_context, + *( (psa_key_slot_number_t *)key_buffer ), + data, data_size, data_length ) ); + } +#endif /* MBEDTLS_PSA_CRYPTO_SE_C */ + + switch( location ) + { + case PSA_KEY_LOCATION_LOCAL_STORAGE: + /* Key is stored in the slot in export representation, so + * cycle through all known transparent accelerators */ +#if defined(PSA_CRYPTO_ACCELERATOR_DRIVER_PRESENT) + +#if (defined(PSA_CRYPTO_DRIVER_TEST) ) + status = mbedtls_test_transparent_export_public_key + (attributes, + key_buffer, + key_buffer_size, + data, + data_size, + data_length + ); + + if( status != PSA_ERROR_NOT_SUPPORTED ) + return( status ); +#endif + +#if (defined(MBEDTLS_PSA_P256M_DRIVER_ENABLED) ) + status = p256_transparent_export_public_key + (attributes, + key_buffer, + key_buffer_size, + data, + data_size, + data_length + ); + + if( status != PSA_ERROR_NOT_SUPPORTED ) + return( status ); +#endif + + +#endif /* PSA_CRYPTO_ACCELERATOR_DRIVER_PRESENT */ + /* Fell through, meaning no accelerator supports this operation */ + return( psa_export_public_key_internal( attributes, + key_buffer, + key_buffer_size, + data, + data_size, + data_length ) ); + + /* Add cases for opaque driver here */ +#if defined(PSA_CRYPTO_ACCELERATOR_DRIVER_PRESENT) + +#if (defined(PSA_CRYPTO_DRIVER_TEST) ) + case 0x7fffff: + return( mbedtls_test_opaque_export_public_key + (attributes, + key_buffer, + key_buffer_size, + data, + data_size, + data_length + )); +#endif + + +#endif /* PSA_CRYPTO_ACCELERATOR_DRIVER_PRESENT */ + default: + /* Key is declared with a lifetime not known to us */ + return( status ); + } + +} + +psa_status_t psa_driver_wrapper_get_builtin_key( + psa_drv_slot_number_t slot_number, + psa_key_attributes_t *attributes, + uint8_t *key_buffer, size_t key_buffer_size, size_t *key_buffer_length ) +{ + + psa_key_location_t location = PSA_KEY_LIFETIME_GET_LOCATION( psa_get_key_lifetime(attributes) ); + switch( location ) + { +#if defined(PSA_CRYPTO_ACCELERATOR_DRIVER_PRESENT) + +#if (defined(PSA_CRYPTO_DRIVER_TEST) ) + case 0x7fffff: + return( mbedtls_test_opaque_get_builtin_key + (slot_number, + attributes, + key_buffer, + key_buffer_size, + key_buffer_length + )); +#endif + + +#endif /* PSA_CRYPTO_ACCELERATOR_DRIVER_PRESENT */ + default: + (void) slot_number; + (void) key_buffer; + (void) key_buffer_size; + (void) key_buffer_length; + return( PSA_ERROR_DOES_NOT_EXIST ); + } + +} + +#endif /* MBEDTLS_PSA_CRYPTO_C */ diff --git a/vendor/mbedtls/library/psa_crypto_driver_wrappers_no_static.h b/vendor/mbedtls/library/psa_crypto_driver_wrappers_no_static.h new file mode 100644 index 0000000000..cd617f60ee --- /dev/null +++ b/vendor/mbedtls/library/psa_crypto_driver_wrappers_no_static.h @@ -0,0 +1,31 @@ +/* + * Function signatures for functionality that can be provided by + * cryptographic accelerators. + */ +/* Copyright The Mbed TLS Contributors + * SPDX-License-Identifier: Apache-2.0 OR GPL-2.0-or-later + */ + +#ifndef PSA_CRYPTO_DRIVER_WRAPPERS_NO_STATIC_H +#define PSA_CRYPTO_DRIVER_WRAPPERS_NO_STATIC_H + +#include "psa/crypto.h" +#include "psa/crypto_driver_common.h" + +psa_status_t psa_driver_wrapper_export_public_key( + const psa_key_attributes_t *attributes, + const uint8_t *key_buffer, size_t key_buffer_size, + uint8_t *data, size_t data_size, size_t *data_length); + +psa_status_t psa_driver_wrapper_get_key_buffer_size( + const psa_key_attributes_t *attributes, + size_t *key_buffer_size); + +psa_status_t psa_driver_wrapper_get_builtin_key( + psa_drv_slot_number_t slot_number, + psa_key_attributes_t *attributes, + uint8_t *key_buffer, size_t key_buffer_size, size_t *key_buffer_length); + +#endif /* PSA_CRYPTO_DRIVER_WRAPPERS_NO_STATIC_H */ + +/* End of automatically generated file. */ diff --git a/vendor/mbedtls/library/psa_crypto_ecp.c b/vendor/mbedtls/library/psa_crypto_ecp.c index ea0eb1be38..95baff6a0f 100644 --- a/vendor/mbedtls/library/psa_crypto_ecp.c +++ b/vendor/mbedtls/library/psa_crypto_ecp.c @@ -3,19 +3,7 @@ */ /* * Copyright The Mbed TLS Contributors - * SPDX-License-Identifier: Apache-2.0 - * - * Licensed under the Apache License, Version 2.0 (the "License"); you may - * not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT - * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. + * SPDX-License-Identifier: Apache-2.0 OR GPL-2.0-or-later */ #include "common.h" @@ -26,21 +14,79 @@ #include "psa_crypto_core.h" #include "psa_crypto_ecp.h" #include "psa_crypto_random_impl.h" -#include "psa_crypto_hash.h" +#include "mbedtls/psa_util.h" #include #include #include "mbedtls/platform.h" #include +#include #include #include -#if defined(MBEDTLS_PSA_BUILTIN_KEY_TYPE_ECC_KEY_PAIR) || \ +#if defined(MBEDTLS_PSA_BUILTIN_KEY_TYPE_ECC_KEY_PAIR_BASIC) || \ + defined(MBEDTLS_PSA_BUILTIN_KEY_TYPE_ECC_KEY_PAIR_IMPORT) || \ + defined(MBEDTLS_PSA_BUILTIN_KEY_TYPE_ECC_KEY_PAIR_EXPORT) || \ defined(MBEDTLS_PSA_BUILTIN_KEY_TYPE_ECC_PUBLIC_KEY) || \ defined(MBEDTLS_PSA_BUILTIN_ALG_ECDSA) || \ defined(MBEDTLS_PSA_BUILTIN_ALG_DETERMINISTIC_ECDSA) || \ defined(MBEDTLS_PSA_BUILTIN_ALG_ECDH) +/* Helper function to verify if the provided EC's family and key bit size are valid. + * + * Note: "bits" parameter is used both as input and output and it might be updated + * in case provided input value is not multiple of 8 ("sloppy" bits). + */ +static int check_ecc_parameters(psa_ecc_family_t family, size_t *bits) +{ + switch (family) { + case PSA_ECC_FAMILY_SECP_R1: + switch (*bits) { + case 192: + case 224: + case 256: + case 384: + case 521: + return PSA_SUCCESS; + case 528: + *bits = 521; + return PSA_SUCCESS; + } + break; + + case PSA_ECC_FAMILY_BRAINPOOL_P_R1: + switch (*bits) { + case 256: + case 384: + case 512: + return PSA_SUCCESS; + } + break; + + case PSA_ECC_FAMILY_MONTGOMERY: + switch (*bits) { + case 448: + case 255: + return PSA_SUCCESS; + case 256: + *bits = 255; + return PSA_SUCCESS; + } + break; + + case PSA_ECC_FAMILY_SECP_K1: + switch (*bits) { + case 192: + /* secp224k1 is not and will not be supported in PSA (#3541). */ + case 256: + return PSA_SUCCESS; + } + break; + } + + return PSA_ERROR_INVALID_ARGUMENT; +} + psa_status_t mbedtls_psa_ecp_load_representation( psa_key_type_t type, size_t curve_bits, const uint8_t *data, size_t data_length, @@ -91,16 +137,15 @@ psa_status_t mbedtls_psa_ecp_load_representation( } mbedtls_ecp_keypair_init(ecp); + status = check_ecc_parameters(PSA_KEY_TYPE_ECC_GET_FAMILY(type), &curve_bits); + if (status != PSA_SUCCESS) { + goto exit; + } + /* Load the group. */ - grp_id = mbedtls_ecc_group_of_psa(PSA_KEY_TYPE_ECC_GET_FAMILY(type), - curve_bits, !explicit_bits); + grp_id = mbedtls_ecc_group_from_psa(PSA_KEY_TYPE_ECC_GET_FAMILY(type), + curve_bits); if (grp_id == MBEDTLS_ECP_DP_NONE) { - /* We can't distinguish between a nonsensical family/size combination - * (which would warrant PSA_ERROR_INVALID_ARGUMENT) and a - * well-regarded curve that Mbed TLS just doesn't know about (which - * would warrant PSA_ERROR_NOT_SUPPORTED). For uniformity with how - * curves that Mbed TLS knows about but for which support is disabled - * at build time, return NOT_SUPPORTED. */ status = PSA_ERROR_NOT_SUPPORTED; goto exit; } @@ -149,13 +194,16 @@ psa_status_t mbedtls_psa_ecp_load_representation( return status; } -#endif /* defined(MBEDTLS_PSA_BUILTIN_KEY_TYPE_ECC_KEY_PAIR) || +#endif /* defined(MBEDTLS_PSA_BUILTIN_KEY_TYPE_ECC_KEY_PAIR_BASIC) || + * defined(MBEDTLS_PSA_BUILTIN_KEY_TYPE_ECC_KEY_PAIR_IMPORT) || + * defined(MBEDTLS_PSA_BUILTIN_KEY_TYPE_ECC_KEY_PAIR_EXPORT) || * defined(MBEDTLS_PSA_BUILTIN_KEY_TYPE_ECC_PUBLIC_KEY) || * defined(MBEDTLS_PSA_BUILTIN_ALG_ECDSA) || * defined(MBEDTLS_PSA_BUILTIN_ALG_DETERMINISTIC_ECDSA) || * defined(MBEDTLS_PSA_BUILTIN_ALG_ECDH) */ -#if defined(MBEDTLS_PSA_BUILTIN_KEY_TYPE_ECC_KEY_PAIR) || \ +#if defined(MBEDTLS_PSA_BUILTIN_KEY_TYPE_ECC_KEY_PAIR_IMPORT) || \ + defined(MBEDTLS_PSA_BUILTIN_KEY_TYPE_ECC_KEY_PAIR_EXPORT) || \ defined(MBEDTLS_PSA_BUILTIN_KEY_TYPE_ECC_PUBLIC_KEY) psa_status_t mbedtls_psa_ecp_import_key( @@ -168,8 +216,8 @@ psa_status_t mbedtls_psa_ecp_import_key( mbedtls_ecp_keypair *ecp = NULL; /* Parse input */ - status = mbedtls_psa_ecp_load_representation(attributes->core.type, - attributes->core.bits, + status = mbedtls_psa_ecp_load_representation(attributes->type, + attributes->bits, data, data_length, &ecp); @@ -177,7 +225,7 @@ psa_status_t mbedtls_psa_ecp_import_key( goto exit; } - if (PSA_KEY_TYPE_ECC_GET_FAMILY(attributes->core.type) == + if (PSA_KEY_TYPE_ECC_GET_FAMILY(attributes->type) == PSA_ECC_FAMILY_MONTGOMERY) { *bits = ecp->grp.nbits + 1; } else { @@ -187,7 +235,7 @@ psa_status_t mbedtls_psa_ecp_import_key( /* Re-export the data to PSA export format. There is currently no support * for other input formats then the export format, so this is a 1-1 * copy operation. */ - status = mbedtls_psa_ecp_export_key(attributes->core.type, + status = mbedtls_psa_ecp_export_key(attributes->type, ecp, key_buffer, key_buffer_size, @@ -233,20 +281,8 @@ psa_status_t mbedtls_psa_ecp_export_key(psa_key_type_t type, return status; } else { - if (data_size < PSA_BITS_TO_BYTES(ecp->grp.nbits)) { - return PSA_ERROR_BUFFER_TOO_SMALL; - } - status = mbedtls_to_psa_error( - mbedtls_ecp_write_key(ecp, - data, - PSA_BITS_TO_BYTES(ecp->grp.nbits))); - if (status == PSA_SUCCESS) { - *data_length = PSA_BITS_TO_BYTES(ecp->grp.nbits); - } else { - memset(data, 0, data_size); - } - + mbedtls_ecp_write_key_ext(ecp, data_length, data, data_size)); return status; } } @@ -260,7 +296,7 @@ psa_status_t mbedtls_psa_ecp_export_public_key( mbedtls_ecp_keypair *ecp = NULL; status = mbedtls_psa_ecp_load_representation( - attributes->core.type, attributes->core.bits, + attributes->type, attributes->bits, key_buffer, key_buffer_size, &ecp); if (status != PSA_SUCCESS) { return status; @@ -268,7 +304,7 @@ psa_status_t mbedtls_psa_ecp_export_public_key( status = mbedtls_psa_ecp_export_key( PSA_KEY_TYPE_ECC_PUBLIC_KEY( - PSA_KEY_TYPE_ECC_GET_FAMILY(attributes->core.type)), + PSA_KEY_TYPE_ECC_GET_FAMILY(attributes->type)), ecp, data, data_size, data_length); mbedtls_ecp_keypair_free(ecp); @@ -276,10 +312,11 @@ psa_status_t mbedtls_psa_ecp_export_public_key( return status; } -#endif /* defined(MBEDTLS_PSA_BUILTIN_KEY_TYPE_ECC_KEY_PAIR) || +#endif /* defined(MBEDTLS_PSA_BUILTIN_KEY_TYPE_ECC_KEY_PAIR_IMPORT) || + * defined(MBEDTLS_PSA_BUILTIN_KEY_TYPE_ECC_KEY_PAIR_EXPORT) || * defined(MBEDTLS_PSA_BUILTIN_KEY_TYPE_ECC_PUBLIC_KEY) */ -#if defined(MBEDTLS_PSA_BUILTIN_KEY_TYPE_ECC_KEY_PAIR) +#if defined(MBEDTLS_PSA_BUILTIN_KEY_TYPE_ECC_KEY_PAIR_GENERATE) psa_status_t mbedtls_psa_ecp_generate_key( const psa_key_attributes_t *attributes, uint8_t *key_buffer, size_t key_buffer_size, size_t *key_buffer_length) @@ -288,18 +325,14 @@ psa_status_t mbedtls_psa_ecp_generate_key( int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED; psa_ecc_family_t curve = PSA_KEY_TYPE_ECC_GET_FAMILY( - attributes->core.type); + attributes->type); mbedtls_ecp_group_id grp_id = - mbedtls_ecc_group_of_psa(curve, attributes->core.bits, 0); + mbedtls_ecc_group_from_psa(curve, attributes->bits); const mbedtls_ecp_curve_info *curve_info = mbedtls_ecp_curve_info_from_grp_id(grp_id); mbedtls_ecp_keypair ecp; - if (attributes->domain_parameters_size != 0) { - return PSA_ERROR_NOT_SUPPORTED; - } - if (grp_id == MBEDTLS_ECP_DP_NONE || curve_info == NULL) { return PSA_ERROR_NOT_SUPPORTED; } @@ -314,17 +347,14 @@ psa_status_t mbedtls_psa_ecp_generate_key( } status = mbedtls_to_psa_error( - mbedtls_ecp_write_key(&ecp, key_buffer, key_buffer_size)); + mbedtls_ecp_write_key_ext(&ecp, key_buffer_length, + key_buffer, key_buffer_size)); mbedtls_ecp_keypair_free(&ecp); - if (status == PSA_SUCCESS) { - *key_buffer_length = key_buffer_size; - } - return status; } -#endif /* defined(MBEDTLS_PSA_BUILTIN_KEY_TYPE_ECC_KEY_PAIR) */ +#endif /* MBEDTLS_PSA_BUILTIN_KEY_TYPE_ECC_KEY_PAIR_GENERATE */ /****************************************************************/ /* ECDSA sign/verify */ @@ -344,8 +374,8 @@ psa_status_t mbedtls_psa_ecdsa_sign_hash( size_t curve_bytes; mbedtls_mpi r, s; - status = mbedtls_psa_ecp_load_representation(attributes->core.type, - attributes->core.bits, + status = mbedtls_psa_ecp_load_representation(attributes->type, + attributes->bits, key_buffer, key_buffer_size, &ecp); @@ -365,8 +395,7 @@ psa_status_t mbedtls_psa_ecdsa_sign_hash( if (PSA_ALG_ECDSA_IS_DETERMINISTIC(alg)) { #if defined(MBEDTLS_PSA_BUILTIN_ALG_DETERMINISTIC_ECDSA) psa_algorithm_t hash_alg = PSA_ALG_SIGN_GET_HASH(alg); - const mbedtls_md_info_t *md_info = mbedtls_md_info_from_psa(hash_alg); - mbedtls_md_type_t md_alg = mbedtls_md_get_type(md_info); + mbedtls_md_type_t md_alg = mbedtls_md_type_from_psa_alg(hash_alg); MBEDTLS_MPI_CHK(mbedtls_ecdsa_sign_det_ext( &ecp->grp, &r, &s, &ecp->d, hash, @@ -404,6 +433,21 @@ psa_status_t mbedtls_psa_ecdsa_sign_hash( return mbedtls_to_psa_error(ret); } +psa_status_t mbedtls_psa_ecp_load_public_part(mbedtls_ecp_keypair *ecp) +{ + int ret = 0; + + /* Check whether the public part is loaded. If not, load it. */ + if (mbedtls_ecp_is_zero(&ecp->Q)) { + ret = mbedtls_ecp_mul(&ecp->grp, &ecp->Q, + &ecp->d, &ecp->grp.G, + mbedtls_psa_get_random, + MBEDTLS_PSA_RANDOM_STATE); + } + + return mbedtls_to_psa_error(ret); +} + psa_status_t mbedtls_psa_ecdsa_verify_hash( const psa_key_attributes_t *attributes, const uint8_t *key_buffer, size_t key_buffer_size, @@ -412,14 +456,13 @@ psa_status_t mbedtls_psa_ecdsa_verify_hash( { psa_status_t status = PSA_ERROR_CORRUPTION_DETECTED; mbedtls_ecp_keypair *ecp = NULL; - int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED; size_t curve_bytes; mbedtls_mpi r, s; (void) alg; - status = mbedtls_psa_ecp_load_representation(attributes->core.type, - attributes->core.bits, + status = mbedtls_psa_ecp_load_representation(attributes->type, + attributes->bits, key_buffer, key_buffer_size, &ecp); @@ -432,37 +475,122 @@ psa_status_t mbedtls_psa_ecdsa_verify_hash( mbedtls_mpi_init(&s); if (signature_length != 2 * curve_bytes) { - ret = MBEDTLS_ERR_ECP_VERIFY_FAILED; + status = PSA_ERROR_INVALID_SIGNATURE; goto cleanup; } - MBEDTLS_MPI_CHK(mbedtls_mpi_read_binary(&r, - signature, - curve_bytes)); - MBEDTLS_MPI_CHK(mbedtls_mpi_read_binary(&s, - signature + curve_bytes, - curve_bytes)); + status = mbedtls_to_psa_error(mbedtls_mpi_read_binary(&r, + signature, + curve_bytes)); + if (status != PSA_SUCCESS) { + goto cleanup; + } - /* Check whether the public part is loaded. If not, load it. */ - if (mbedtls_ecp_is_zero(&ecp->Q)) { - MBEDTLS_MPI_CHK( - mbedtls_ecp_mul(&ecp->grp, &ecp->Q, &ecp->d, &ecp->grp.G, - mbedtls_psa_get_random, MBEDTLS_PSA_RANDOM_STATE)); + status = mbedtls_to_psa_error(mbedtls_mpi_read_binary(&s, + signature + curve_bytes, + curve_bytes)); + if (status != PSA_SUCCESS) { + goto cleanup; } - ret = mbedtls_ecdsa_verify(&ecp->grp, hash, hash_length, - &ecp->Q, &r, &s); + status = mbedtls_psa_ecp_load_public_part(ecp); + if (status != PSA_SUCCESS) { + goto cleanup; + } + status = mbedtls_to_psa_error(mbedtls_ecdsa_verify(&ecp->grp, hash, + hash_length, &ecp->Q, + &r, &s)); cleanup: mbedtls_mpi_free(&r); mbedtls_mpi_free(&s); mbedtls_ecp_keypair_free(ecp); mbedtls_free(ecp); - return mbedtls_to_psa_error(ret); + return status; } #endif /* defined(MBEDTLS_PSA_BUILTIN_ALG_ECDSA) || \ * defined(MBEDTLS_PSA_BUILTIN_ALG_DETERMINISTIC_ECDSA) */ +/****************************************************************/ +/* ECDH Key Agreement */ +/****************************************************************/ + +#if defined(MBEDTLS_PSA_BUILTIN_ALG_ECDH) +psa_status_t mbedtls_psa_key_agreement_ecdh( + const psa_key_attributes_t *attributes, + const uint8_t *key_buffer, size_t key_buffer_size, + psa_algorithm_t alg, const uint8_t *peer_key, size_t peer_key_length, + uint8_t *shared_secret, size_t shared_secret_size, + size_t *shared_secret_length) +{ + psa_status_t status; + if (!PSA_KEY_TYPE_IS_ECC_KEY_PAIR(attributes->type) || + !PSA_ALG_IS_ECDH(alg)) { + return PSA_ERROR_INVALID_ARGUMENT; + } + mbedtls_ecp_keypair *ecp = NULL; + status = mbedtls_psa_ecp_load_representation( + attributes->type, + attributes->bits, + key_buffer, + key_buffer_size, + &ecp); + if (status != PSA_SUCCESS) { + return status; + } + mbedtls_ecp_keypair *their_key = NULL; + mbedtls_ecdh_context ecdh; + size_t bits = 0; + psa_ecc_family_t curve = mbedtls_ecc_group_to_psa(ecp->grp.id, &bits); + mbedtls_ecdh_init(&ecdh); + + status = mbedtls_psa_ecp_load_representation( + PSA_KEY_TYPE_ECC_PUBLIC_KEY(curve), + bits, + peer_key, + peer_key_length, + &their_key); + if (status != PSA_SUCCESS) { + goto exit; + } + + status = mbedtls_to_psa_error( + mbedtls_ecdh_get_params(&ecdh, their_key, MBEDTLS_ECDH_THEIRS)); + if (status != PSA_SUCCESS) { + goto exit; + } + status = mbedtls_to_psa_error( + mbedtls_ecdh_get_params(&ecdh, ecp, MBEDTLS_ECDH_OURS)); + if (status != PSA_SUCCESS) { + goto exit; + } + + status = mbedtls_to_psa_error( + mbedtls_ecdh_calc_secret(&ecdh, + shared_secret_length, + shared_secret, shared_secret_size, + mbedtls_psa_get_random, + MBEDTLS_PSA_RANDOM_STATE)); + if (status != PSA_SUCCESS) { + goto exit; + } + if (PSA_BITS_TO_BYTES(bits) != *shared_secret_length) { + status = PSA_ERROR_CORRUPTION_DETECTED; + } +exit: + if (status != PSA_SUCCESS) { + mbedtls_platform_zeroize(shared_secret, shared_secret_size); + } + mbedtls_ecdh_free(&ecdh); + mbedtls_ecp_keypair_free(their_key); + mbedtls_free(their_key); + mbedtls_ecp_keypair_free(ecp); + mbedtls_free(ecp); + return status; +} +#endif /* MBEDTLS_PSA_BUILTIN_ALG_ECDH */ + + #endif /* MBEDTLS_PSA_CRYPTO_C */ diff --git a/vendor/mbedtls/library/psa_crypto_ecp.h b/vendor/mbedtls/library/psa_crypto_ecp.h index 7541c77492..a9f5d59de4 100644 --- a/vendor/mbedtls/library/psa_crypto_ecp.h +++ b/vendor/mbedtls/library/psa_crypto_ecp.h @@ -3,19 +3,7 @@ */ /* * Copyright The Mbed TLS Contributors - * SPDX-License-Identifier: Apache-2.0 - * - * Licensed under the Apache License, Version 2.0 (the "License"); you may - * not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT - * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. + * SPDX-License-Identifier: Apache-2.0 OR GPL-2.0-or-later */ #ifndef PSA_CRYPTO_ECP_H @@ -48,6 +36,15 @@ psa_status_t mbedtls_psa_ecp_load_representation(psa_key_type_t type, size_t data_length, mbedtls_ecp_keypair **p_ecp); +/** Load the public part of an internal ECP, if required. + * + * \param ecp The ECP context to load the public part for. + * + * \return PSA_SUCCESS on success, otherwise an MPI error. + */ + +psa_status_t mbedtls_psa_ecp_load_public_part(mbedtls_ecp_keypair *ecp); + /** Import an ECP key in binary format. * * \note The signature of this function is that of a PSA driver @@ -219,4 +216,52 @@ psa_status_t mbedtls_psa_ecdsa_verify_hash( psa_algorithm_t alg, const uint8_t *hash, size_t hash_length, const uint8_t *signature, size_t signature_length); + +/** Perform a key agreement and return the raw ECDH shared secret. + * + * \note The signature of this function is that of a PSA driver + * key_agreement entry point. This function behaves as a key_agreement + * entry point as defined in the PSA driver interface specification for + * transparent drivers. + * + * \param[in] attributes The attributes of the key to use for the + * operation. + * \param[in] key_buffer The buffer containing the private key + * context. + * \param[in] key_buffer_size Size of the \p key_buffer buffer in + * bytes. + * \param[in] alg A key agreement algorithm that is + * compatible with the type of the key. + * \param[in] peer_key The buffer containing the key context + * of the peer's public key. + * \param[in] peer_key_length Size of the \p peer_key buffer in + * bytes. + * \param[out] shared_secret The buffer to which the shared secret + * is to be written. + * \param[in] shared_secret_size Size of the \p shared_secret buffer in + * bytes. + * \param[out] shared_secret_length On success, the number of bytes that make + * up the returned shared secret. + * \retval #PSA_SUCCESS + * Success. Shared secret successfully calculated. + * \retval #PSA_ERROR_INVALID_HANDLE \emptydescription + * \retval #PSA_ERROR_NOT_PERMITTED \emptydescription + * \retval #PSA_ERROR_INVALID_ARGUMENT + * \p alg is not a key agreement algorithm, or + * \p private_key is not compatible with \p alg, + * or \p peer_key is not valid for \p alg or not compatible with + * \p private_key. + * \retval #PSA_ERROR_BUFFER_TOO_SMALL + * \p shared_secret_size is too small + * \retval #PSA_ERROR_NOT_SUPPORTED + * \p alg is not a supported key agreement algorithm. + * \retval #PSA_ERROR_INSUFFICIENT_MEMORY \emptydescription + * \retval #PSA_ERROR_CORRUPTION_DETECTED \emptydescription + */ +psa_status_t mbedtls_psa_key_agreement_ecdh( + const psa_key_attributes_t *attributes, + const uint8_t *key_buffer, size_t key_buffer_size, + psa_algorithm_t alg, const uint8_t *peer_key, size_t peer_key_length, + uint8_t *shared_secret, size_t shared_secret_size, + size_t *shared_secret_length); #endif /* PSA_CRYPTO_ECP_H */ diff --git a/vendor/mbedtls/library/psa_crypto_ffdh.c b/vendor/mbedtls/library/psa_crypto_ffdh.c new file mode 100644 index 0000000000..ae38f6d7c6 --- /dev/null +++ b/vendor/mbedtls/library/psa_crypto_ffdh.c @@ -0,0 +1,321 @@ +/* + * PSA FFDH layer on top of Mbed TLS crypto + */ +/* + * Copyright The Mbed TLS Contributors + * SPDX-License-Identifier: Apache-2.0 OR GPL-2.0-or-later + */ + +#include "common.h" + +#if defined(MBEDTLS_PSA_CRYPTO_C) + +/* This header is only needed because it defines + * MBEDTLS_DHM_RFC7919_FFDHEXXXX_[P|G]_BIN symbols that are used in + * mbedtls_psa_ffdh_set_prime_generator(). Apart from that, this module + * only uses bignum functions for arithmetic. */ +#include + +#include +#include "psa_crypto_core.h" +#include "psa_crypto_ffdh.h" +#include "psa_crypto_random_impl.h" +#include "mbedtls/platform.h" +#include "mbedtls/error.h" + +#if defined(MBEDTLS_PSA_BUILTIN_KEY_TYPE_DH_KEY_PAIR_EXPORT) || \ + defined(MBEDTLS_PSA_BUILTIN_KEY_TYPE_DH_KEY_PAIR_GENERATE) || \ + defined(MBEDTLS_PSA_BUILTIN_KEY_TYPE_DH_PUBLIC_KEY) || \ + defined(MBEDTLS_PSA_BUILTIN_ALG_FFDH) +static psa_status_t mbedtls_psa_ffdh_set_prime_generator(size_t key_size, + mbedtls_mpi *P, + mbedtls_mpi *G) +{ + const unsigned char *dhm_P = NULL; + const unsigned char *dhm_G = NULL; + size_t dhm_size_P = 0; + size_t dhm_size_G = 0; + int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED; + + if (P == NULL && G == NULL) { + return PSA_ERROR_INVALID_ARGUMENT; + } + +#if defined(MBEDTLS_PSA_BUILTIN_DH_RFC7919_2048) + static const unsigned char dhm_P_2048[] = + MBEDTLS_DHM_RFC7919_FFDHE2048_P_BIN; + static const unsigned char dhm_G_2048[] = + MBEDTLS_DHM_RFC7919_FFDHE2048_G_BIN; +#endif /* MBEDTLS_PSA_BUILTIN_DH_RFC7919_2048 */ +#if defined(MBEDTLS_PSA_BUILTIN_DH_RFC7919_3072) + static const unsigned char dhm_P_3072[] = + MBEDTLS_DHM_RFC7919_FFDHE3072_P_BIN; + static const unsigned char dhm_G_3072[] = + MBEDTLS_DHM_RFC7919_FFDHE3072_G_BIN; +#endif /* MBEDTLS_PSA_BUILTIN_DH_RFC7919_3072 */ +#if defined(MBEDTLS_PSA_BUILTIN_DH_RFC7919_4096) + static const unsigned char dhm_P_4096[] = + MBEDTLS_DHM_RFC7919_FFDHE4096_P_BIN; + static const unsigned char dhm_G_4096[] = + MBEDTLS_DHM_RFC7919_FFDHE4096_G_BIN; +#endif /* MBEDTLS_PSA_BUILTIN_DH_RFC7919_4096 */ +#if defined(MBEDTLS_PSA_BUILTIN_DH_RFC7919_6144) + static const unsigned char dhm_P_6144[] = + MBEDTLS_DHM_RFC7919_FFDHE6144_P_BIN; + static const unsigned char dhm_G_6144[] = + MBEDTLS_DHM_RFC7919_FFDHE6144_G_BIN; +#endif /* MBEDTLS_PSA_BUILTIN_DH_RFC7919_6144 */ +#if defined(MBEDTLS_PSA_BUILTIN_DH_RFC7919_8192) + static const unsigned char dhm_P_8192[] = + MBEDTLS_DHM_RFC7919_FFDHE8192_P_BIN; + static const unsigned char dhm_G_8192[] = + MBEDTLS_DHM_RFC7919_FFDHE8192_G_BIN; +#endif /* MBEDTLS_PSA_BUILTIN_DH_RFC7919_8192 */ + + switch (key_size) { +#if defined(MBEDTLS_PSA_BUILTIN_DH_RFC7919_2048) + case sizeof(dhm_P_2048): + dhm_P = dhm_P_2048; + dhm_G = dhm_G_2048; + dhm_size_P = sizeof(dhm_P_2048); + dhm_size_G = sizeof(dhm_G_2048); + break; +#endif /* MBEDTLS_PSA_BUILTIN_DH_RFC7919_2048 */ +#if defined(MBEDTLS_PSA_BUILTIN_DH_RFC7919_3072) + case sizeof(dhm_P_3072): + dhm_P = dhm_P_3072; + dhm_G = dhm_G_3072; + dhm_size_P = sizeof(dhm_P_3072); + dhm_size_G = sizeof(dhm_G_3072); + break; +#endif /* MBEDTLS_PSA_BUILTIN_DH_RFC7919_3072 */ +#if defined(MBEDTLS_PSA_BUILTIN_DH_RFC7919_4096) + case sizeof(dhm_P_4096): + dhm_P = dhm_P_4096; + dhm_G = dhm_G_4096; + dhm_size_P = sizeof(dhm_P_4096); + dhm_size_G = sizeof(dhm_G_4096); + break; +#endif /* MBEDTLS_PSA_BUILTIN_DH_RFC7919_4096 */ +#if defined(MBEDTLS_PSA_BUILTIN_DH_RFC7919_6144) + case sizeof(dhm_P_6144): + dhm_P = dhm_P_6144; + dhm_G = dhm_G_6144; + dhm_size_P = sizeof(dhm_P_6144); + dhm_size_G = sizeof(dhm_G_6144); + break; +#endif /* MBEDTLS_PSA_BUILTIN_DH_RFC7919_6144 */ +#if defined(MBEDTLS_PSA_BUILTIN_DH_RFC7919_8192) + case sizeof(dhm_P_8192): + dhm_P = dhm_P_8192; + dhm_G = dhm_G_8192; + dhm_size_P = sizeof(dhm_P_8192); + dhm_size_G = sizeof(dhm_G_8192); + break; +#endif /* MBEDTLS_PSA_BUILTIN_DH_RFC7919_8192 */ + default: + return PSA_ERROR_INVALID_ARGUMENT; + } + + if (P != NULL) { + MBEDTLS_MPI_CHK(mbedtls_mpi_read_binary(P, dhm_P, + dhm_size_P)); + } + if (G != NULL) { + MBEDTLS_MPI_CHK(mbedtls_mpi_read_binary(G, dhm_G, + dhm_size_G)); + } + +cleanup: + if (ret != 0) { + return mbedtls_to_psa_error(ret); + } + + return PSA_SUCCESS; +} +#endif /* MBEDTLS_PSA_BUILTIN_KEY_TYPE_DH_KEY_PAIR_EXPORT || + MBEDTLS_PSA_BUILTIN_KEY_TYPE_DH_KEY_PAIR_GENERATE || + MBEDTLS_PSA_BUILTIN_KEY_TYPE_DH_PUBLIC_KEY || + MBEDTLS_PSA_BUILTIN_ALG_FFDH */ + +#if defined(MBEDTLS_PSA_BUILTIN_KEY_TYPE_DH_KEY_PAIR_EXPORT) || \ + defined(MBEDTLS_PSA_BUILTIN_KEY_TYPE_DH_PUBLIC_KEY) +psa_status_t mbedtls_psa_ffdh_export_public_key( + const psa_key_attributes_t *attributes, + const uint8_t *key_buffer, + size_t key_buffer_size, + uint8_t *data, + size_t data_size, + size_t *data_length) +{ + int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED; + psa_status_t status = PSA_ERROR_CORRUPTION_DETECTED; + mbedtls_mpi GX, G, X, P; + psa_key_type_t type = attributes->type; + + if (PSA_KEY_TYPE_IS_PUBLIC_KEY(type)) { + if (key_buffer_size > data_size) { + return PSA_ERROR_BUFFER_TOO_SMALL; + } + memcpy(data, key_buffer, key_buffer_size); + memset(data + key_buffer_size, 0, + data_size - key_buffer_size); + *data_length = key_buffer_size; + return PSA_SUCCESS; + } + + mbedtls_mpi_init(&GX); mbedtls_mpi_init(&G); + mbedtls_mpi_init(&X); mbedtls_mpi_init(&P); + + size_t key_len = PSA_BITS_TO_BYTES(attributes->bits); + + status = mbedtls_psa_ffdh_set_prime_generator(key_len, &P, &G); + + if (status != PSA_SUCCESS) { + goto cleanup; + } + + MBEDTLS_MPI_CHK(mbedtls_mpi_read_binary(&X, key_buffer, + key_buffer_size)); + + MBEDTLS_MPI_CHK(mbedtls_mpi_exp_mod(&GX, &G, &X, &P, NULL)); + MBEDTLS_MPI_CHK(mbedtls_mpi_write_binary(&GX, data, key_len)); + + *data_length = key_len; + + ret = 0; +cleanup: + mbedtls_mpi_free(&P); mbedtls_mpi_free(&G); + mbedtls_mpi_free(&X); mbedtls_mpi_free(&GX); + + if (status == PSA_SUCCESS && ret != 0) { + status = mbedtls_to_psa_error(ret); + } + + return status; +} +#endif /* MBEDTLS_PSA_BUILTIN_KEY_TYPE_DH_KEY_PAIR_EXPORT || + MBEDTLS_PSA_BUILTIN_KEY_TYPE_DH_PUBLIC_KEY */ + +#if defined(MBEDTLS_PSA_BUILTIN_KEY_TYPE_DH_KEY_PAIR_GENERATE) +psa_status_t mbedtls_psa_ffdh_generate_key( + const psa_key_attributes_t *attributes, + uint8_t *key_buffer, size_t key_buffer_size, size_t *key_buffer_length) +{ + mbedtls_mpi X, P; + int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED; + psa_status_t status = PSA_ERROR_CORRUPTION_DETECTED; + mbedtls_mpi_init(&P); mbedtls_mpi_init(&X); + (void) attributes; + + status = mbedtls_psa_ffdh_set_prime_generator(key_buffer_size, &P, NULL); + + if (status != PSA_SUCCESS) { + goto cleanup; + } + + /* RFC7919: Traditional finite field Diffie-Hellman has each peer choose their + secret exponent from the range [2, P-2]. + Select random value in range [3, P-1] and decrease it by 1. */ + MBEDTLS_MPI_CHK(mbedtls_mpi_random(&X, 3, &P, mbedtls_psa_get_random, + MBEDTLS_PSA_RANDOM_STATE)); + MBEDTLS_MPI_CHK(mbedtls_mpi_sub_int(&X, &X, 1)); + MBEDTLS_MPI_CHK(mbedtls_mpi_write_binary(&X, key_buffer, key_buffer_size)); + *key_buffer_length = key_buffer_size; + +cleanup: + mbedtls_mpi_free(&P); mbedtls_mpi_free(&X); + if (status == PSA_SUCCESS && ret != 0) { + return mbedtls_to_psa_error(ret); + } + + return status; +} +#endif /* MBEDTLS_PSA_BUILTIN_KEY_TYPE_DH_KEY_PAIR_GENERATE */ + +#if defined(MBEDTLS_PSA_BUILTIN_KEY_TYPE_DH_KEY_PAIR_IMPORT) +psa_status_t mbedtls_psa_ffdh_import_key( + const psa_key_attributes_t *attributes, + const uint8_t *data, size_t data_length, + uint8_t *key_buffer, size_t key_buffer_size, + size_t *key_buffer_length, size_t *bits) +{ + (void) attributes; + + if (key_buffer_size < data_length) { + return PSA_ERROR_BUFFER_TOO_SMALL; + } + memcpy(key_buffer, data, data_length); + *key_buffer_length = data_length; + *bits = PSA_BYTES_TO_BITS(data_length); + + return PSA_SUCCESS; +} +#endif /* MBEDTLS_PSA_BUILTIN_KEY_TYPE_DH_KEY_PAIR_IMPORT */ + +#if defined(MBEDTLS_PSA_BUILTIN_ALG_FFDH) +psa_status_t mbedtls_psa_ffdh_key_agreement( + const psa_key_attributes_t *attributes, + const uint8_t *peer_key, + size_t peer_key_length, + const uint8_t *key_buffer, + size_t key_buffer_size, + uint8_t *shared_secret, + size_t shared_secret_size, + size_t *shared_secret_length) +{ + int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED; + psa_status_t status = PSA_ERROR_CORRUPTION_DETECTED; + mbedtls_mpi P, G, X, GY, K; + const size_t calculated_shared_secret_size = peer_key_length; + + if (peer_key_length != key_buffer_size || + calculated_shared_secret_size > shared_secret_size) { + return PSA_ERROR_INVALID_ARGUMENT; + } + + if (!PSA_KEY_TYPE_IS_DH_KEY_PAIR(psa_get_key_type(attributes))) { + return PSA_ERROR_INVALID_ARGUMENT; + } + + mbedtls_mpi_init(&P); mbedtls_mpi_init(&G); + mbedtls_mpi_init(&X); mbedtls_mpi_init(&GY); + mbedtls_mpi_init(&K); + + status = mbedtls_psa_ffdh_set_prime_generator( + PSA_BITS_TO_BYTES(attributes->bits), &P, &G); + + if (status != PSA_SUCCESS) { + goto cleanup; + } + + MBEDTLS_MPI_CHK(mbedtls_mpi_read_binary(&X, key_buffer, + key_buffer_size)); + + MBEDTLS_MPI_CHK(mbedtls_mpi_read_binary(&GY, peer_key, + peer_key_length)); + + /* Calculate shared secret public key: K = G^(XY) mod P = GY^X mod P */ + MBEDTLS_MPI_CHK(mbedtls_mpi_exp_mod(&K, &GY, &X, &P, NULL)); + + MBEDTLS_MPI_CHK(mbedtls_mpi_write_binary(&K, shared_secret, + calculated_shared_secret_size)); + + *shared_secret_length = calculated_shared_secret_size; + + ret = 0; + +cleanup: + mbedtls_mpi_free(&P); mbedtls_mpi_free(&G); + mbedtls_mpi_free(&X); mbedtls_mpi_free(&GY); + mbedtls_mpi_free(&K); + + if (status == PSA_SUCCESS && ret != 0) { + status = mbedtls_to_psa_error(ret); + } + + return status; +} +#endif /* MBEDTLS_PSA_BUILTIN_ALG_FFDH */ + +#endif /* MBEDTLS_PSA_CRYPTO_C */ diff --git a/vendor/mbedtls/library/psa_crypto_ffdh.h b/vendor/mbedtls/library/psa_crypto_ffdh.h new file mode 100644 index 0000000000..79accd15ac --- /dev/null +++ b/vendor/mbedtls/library/psa_crypto_ffdh.h @@ -0,0 +1,131 @@ +/* + * PSA FFDH layer on top of Mbed TLS crypto + */ +/* + * Copyright The Mbed TLS Contributors + * SPDX-License-Identifier: Apache-2.0 OR GPL-2.0-or-later + */ + +#ifndef PSA_CRYPTO_FFDH_H +#define PSA_CRYPTO_FFDH_H + +#include + +/** Perform a key agreement and return the FFDH shared secret. + * + * \param[in] attributes The attributes of the key to use for the + * operation. + * \param[in] peer_key The buffer containing the key context + * of the peer's public key. + * \param[in] peer_key_length Size of the \p peer_key buffer in + * bytes. + * \param[in] key_buffer The buffer containing the private key + * context. + * \param[in] key_buffer_size Size of the \p key_buffer buffer in + * bytes. + * \param[out] shared_secret The buffer to which the shared secret + * is to be written. + * \param[in] shared_secret_size Size of the \p shared_secret buffer in + * bytes. + * \param[out] shared_secret_length On success, the number of bytes that make + * up the returned shared secret. + * \retval #PSA_SUCCESS + * Success. Shared secret successfully calculated. + * \retval #PSA_ERROR_INVALID_ARGUMENT + * \p key_buffer_size, \p peer_key_length, \p shared_secret_size + * do not match + * \retval #PSA_ERROR_INSUFFICIENT_MEMORY \emptydescription + * \retval #PSA_ERROR_CORRUPTION_DETECTED \emptydescription + */ +psa_status_t mbedtls_psa_ffdh_key_agreement( + const psa_key_attributes_t *attributes, + const uint8_t *peer_key, + size_t peer_key_length, + const uint8_t *key_buffer, + size_t key_buffer_size, + uint8_t *shared_secret, + size_t shared_secret_size, + size_t *shared_secret_length); + +/** Export a public key or the public part of a DH key pair in binary format. + * + * \param[in] attributes The attributes for the key to export. + * \param[in] key_buffer Material or context of the key to export. + * \param[in] key_buffer_size Size of the \p key_buffer buffer in bytes. + * \param[out] data Buffer where the key data is to be written. + * \param[in] data_size Size of the \p data buffer in bytes. + * \param[out] data_length On success, the number of bytes written in + * \p data + * + * \retval #PSA_SUCCESS The public key was exported successfully. + * \retval #PSA_ERROR_BUFFER_TOO_SMALL + * The size of \p key_buffer is too small. + * \retval #PSA_ERROR_NOT_PERMITTED \emptydescription + * \retval #PSA_ERROR_INSUFFICIENT_MEMORY \emptydescription + * \retval #PSA_ERROR_CORRUPTION_DETECTED \emptydescription + */ +psa_status_t mbedtls_psa_ffdh_export_public_key( + const psa_key_attributes_t *attributes, + const uint8_t *key_buffer, + size_t key_buffer_size, + uint8_t *data, + size_t data_size, + size_t *data_length); + +/** + * \brief Generate DH key. + * + * \note The signature of the function is that of a PSA driver generate_key + * entry point. + * + * \param[in] attributes The attributes for the key to generate. + * \param[out] key_buffer Buffer where the key data is to be written. + * \param[in] key_buffer_size Size of \p key_buffer in bytes. + * \param[out] key_buffer_length On success, the number of bytes written in + * \p key_buffer. + * + * \retval #PSA_SUCCESS + * The key was generated successfully. + * \retval #PSA_ERROR_NOT_SUPPORTED + * Key size in bits is invalid. + * \retval #PSA_ERROR_BUFFER_TOO_SMALL + * The size of \p key_buffer is too small. + * \retval #PSA_ERROR_INSUFFICIENT_MEMORY \emptydescription + * \retval #PSA_ERROR_CORRUPTION_DETECTED \emptydescription + */ +psa_status_t mbedtls_psa_ffdh_generate_key( + const psa_key_attributes_t *attributes, + uint8_t *key_buffer, + size_t key_buffer_size, + size_t *key_buffer_length); + +/** + * \brief Import DH key. + * + * \note The signature of the function is that of a PSA driver import_key + * entry point. + * + * \param[in] attributes The attributes for the key to import. + * \param[in] data The buffer containing the key data in import + * format. + * \param[in] data_length Size of the \p data buffer in bytes. + * \param[out] key_buffer The buffer containing the key data in output + * format. + * \param[in] key_buffer_size Size of the \p key_buffer buffer in bytes. This + * size is greater or equal to \p data_length. + * \param[out] key_buffer_length The length of the data written in \p + * key_buffer in bytes. + * \param[out] bits The key size in number of bits. + * + * \retval #PSA_SUCCESS + * The key was generated successfully. + * \retval #PSA_ERROR_BUFFER_TOO_SMALL + * The size of \p key_buffer is too small. + */ +psa_status_t mbedtls_psa_ffdh_import_key( + const psa_key_attributes_t *attributes, + const uint8_t *data, size_t data_length, + uint8_t *key_buffer, size_t key_buffer_size, + size_t *key_buffer_length, size_t *bits); + +#endif /* PSA_CRYPTO_FFDH_H */ diff --git a/vendor/mbedtls/library/psa_crypto_hash.c b/vendor/mbedtls/library/psa_crypto_hash.c index ef73320416..eeb7666c1c 100644 --- a/vendor/mbedtls/library/psa_crypto_hash.c +++ b/vendor/mbedtls/library/psa_crypto_hash.c @@ -3,19 +3,7 @@ */ /* * Copyright The Mbed TLS Contributors - * SPDX-License-Identifier: Apache-2.0 - * - * Licensed under the Apache License, Version 2.0 (the "License"); you may - * not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT - * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. + * SPDX-License-Identifier: Apache-2.0 OR GPL-2.0-or-later */ #include "common.h" @@ -29,58 +17,6 @@ #include #include -#if defined(MBEDTLS_PSA_BUILTIN_ALG_RSA_PKCS1V15_SIGN) || \ - defined(MBEDTLS_PSA_BUILTIN_ALG_RSA_OAEP) || \ - defined(MBEDTLS_PSA_BUILTIN_ALG_RSA_PSS) || \ - defined(MBEDTLS_PSA_BUILTIN_ALG_DETERMINISTIC_ECDSA) -const mbedtls_md_info_t *mbedtls_md_info_from_psa(psa_algorithm_t alg) -{ - switch (alg) { -#if defined(MBEDTLS_MD2_C) - case PSA_ALG_MD2: - return &mbedtls_md2_info; -#endif -#if defined(MBEDTLS_MD4_C) - case PSA_ALG_MD4: - return &mbedtls_md4_info; -#endif -#if defined(MBEDTLS_MD5_C) - case PSA_ALG_MD5: - return &mbedtls_md5_info; -#endif -#if defined(MBEDTLS_RIPEMD160_C) - case PSA_ALG_RIPEMD160: - return &mbedtls_ripemd160_info; -#endif -#if defined(MBEDTLS_SHA1_C) - case PSA_ALG_SHA_1: - return &mbedtls_sha1_info; -#endif -#if defined(MBEDTLS_SHA256_C) - case PSA_ALG_SHA_224: - return &mbedtls_sha224_info; -#endif -#if defined(MBEDTLS_SHA256_C) - case PSA_ALG_SHA_256: - return &mbedtls_sha256_info; -#endif -#if defined(MBEDTLS_SHA512_C) && !defined(MBEDTLS_SHA512_NO_SHA384) - case PSA_ALG_SHA_384: - return &mbedtls_sha384_info; -#endif -#if defined(MBEDTLS_SHA512_C) - case PSA_ALG_SHA_512: - return &mbedtls_sha512_info; -#endif - default: - return NULL; - } -} -#endif /* defined(MBEDTLS_PSA_BUILTIN_ALG_RSA_PKCS1V15_SIGN) || - * defined(MBEDTLS_PSA_BUILTIN_ALG_RSA_OAEP) || - * defined(MBEDTLS_PSA_BUILTIN_ALG_RSA_PSS) || - * defined(MBEDTLS_PSA_BUILTIN_ALG_DETERMINISTIC_ECDSA) */ - #if defined(MBEDTLS_PSA_BUILTIN_HASH) psa_status_t mbedtls_psa_hash_abort( mbedtls_psa_hash_operation_t *operation) @@ -91,16 +27,6 @@ psa_status_t mbedtls_psa_hash_abort( * in use. It's ok to call abort on such an object, and there's * nothing to do. */ break; -#if defined(MBEDTLS_PSA_BUILTIN_ALG_MD2) - case PSA_ALG_MD2: - mbedtls_md2_free(&operation->ctx.md2); - break; -#endif -#if defined(MBEDTLS_PSA_BUILTIN_ALG_MD4) - case PSA_ALG_MD4: - mbedtls_md4_free(&operation->ctx.md4); - break; -#endif #if defined(MBEDTLS_PSA_BUILTIN_ALG_MD5) case PSA_ALG_MD5: mbedtls_md5_free(&operation->ctx.md5); @@ -135,6 +61,25 @@ psa_status_t mbedtls_psa_hash_abort( case PSA_ALG_SHA_512: mbedtls_sha512_free(&operation->ctx.sha512); break; +#endif +#if defined(MBEDTLS_PSA_BUILTIN_ALG_SHA3_224) + case PSA_ALG_SHA3_224: +#endif +#if defined(MBEDTLS_PSA_BUILTIN_ALG_SHA3_256) + case PSA_ALG_SHA3_256: +#endif +#if defined(MBEDTLS_PSA_BUILTIN_ALG_SHA3_384) + case PSA_ALG_SHA3_384: +#endif +#if defined(MBEDTLS_PSA_BUILTIN_ALG_SHA3_512) + case PSA_ALG_SHA3_512: +#endif +#if defined(MBEDTLS_PSA_BUILTIN_ALG_SHA3_224) || \ + defined(MBEDTLS_PSA_BUILTIN_ALG_SHA3_256) || \ + defined(MBEDTLS_PSA_BUILTIN_ALG_SHA3_384) || \ + defined(MBEDTLS_PSA_BUILTIN_ALG_SHA3_512) + mbedtls_sha3_free(&operation->ctx.sha3); + break; #endif default: return PSA_ERROR_BAD_STATE; @@ -155,58 +100,70 @@ psa_status_t mbedtls_psa_hash_setup( } switch (alg) { -#if defined(MBEDTLS_PSA_BUILTIN_ALG_MD2) - case PSA_ALG_MD2: - mbedtls_md2_init(&operation->ctx.md2); - ret = mbedtls_md2_starts_ret(&operation->ctx.md2); - break; -#endif -#if defined(MBEDTLS_PSA_BUILTIN_ALG_MD4) - case PSA_ALG_MD4: - mbedtls_md4_init(&operation->ctx.md4); - ret = mbedtls_md4_starts_ret(&operation->ctx.md4); - break; -#endif #if defined(MBEDTLS_PSA_BUILTIN_ALG_MD5) case PSA_ALG_MD5: mbedtls_md5_init(&operation->ctx.md5); - ret = mbedtls_md5_starts_ret(&operation->ctx.md5); + ret = mbedtls_md5_starts(&operation->ctx.md5); break; #endif #if defined(MBEDTLS_PSA_BUILTIN_ALG_RIPEMD160) case PSA_ALG_RIPEMD160: mbedtls_ripemd160_init(&operation->ctx.ripemd160); - ret = mbedtls_ripemd160_starts_ret(&operation->ctx.ripemd160); + ret = mbedtls_ripemd160_starts(&operation->ctx.ripemd160); break; #endif #if defined(MBEDTLS_PSA_BUILTIN_ALG_SHA_1) case PSA_ALG_SHA_1: mbedtls_sha1_init(&operation->ctx.sha1); - ret = mbedtls_sha1_starts_ret(&operation->ctx.sha1); + ret = mbedtls_sha1_starts(&operation->ctx.sha1); break; #endif #if defined(MBEDTLS_PSA_BUILTIN_ALG_SHA_224) case PSA_ALG_SHA_224: mbedtls_sha256_init(&operation->ctx.sha256); - ret = mbedtls_sha256_starts_ret(&operation->ctx.sha256, 1); + ret = mbedtls_sha256_starts(&operation->ctx.sha256, 1); break; #endif #if defined(MBEDTLS_PSA_BUILTIN_ALG_SHA_256) case PSA_ALG_SHA_256: mbedtls_sha256_init(&operation->ctx.sha256); - ret = mbedtls_sha256_starts_ret(&operation->ctx.sha256, 0); + ret = mbedtls_sha256_starts(&operation->ctx.sha256, 0); break; #endif #if defined(MBEDTLS_PSA_BUILTIN_ALG_SHA_384) case PSA_ALG_SHA_384: mbedtls_sha512_init(&operation->ctx.sha512); - ret = mbedtls_sha512_starts_ret(&operation->ctx.sha512, 1); + ret = mbedtls_sha512_starts(&operation->ctx.sha512, 1); break; #endif #if defined(MBEDTLS_PSA_BUILTIN_ALG_SHA_512) case PSA_ALG_SHA_512: mbedtls_sha512_init(&operation->ctx.sha512); - ret = mbedtls_sha512_starts_ret(&operation->ctx.sha512, 0); + ret = mbedtls_sha512_starts(&operation->ctx.sha512, 0); + break; +#endif +#if defined(MBEDTLS_PSA_BUILTIN_ALG_SHA3_224) + case PSA_ALG_SHA3_224: + mbedtls_sha3_init(&operation->ctx.sha3); + ret = mbedtls_sha3_starts(&operation->ctx.sha3, MBEDTLS_SHA3_224); + break; +#endif +#if defined(MBEDTLS_PSA_BUILTIN_ALG_SHA3_256) + case PSA_ALG_SHA3_256: + mbedtls_sha3_init(&operation->ctx.sha3); + ret = mbedtls_sha3_starts(&operation->ctx.sha3, MBEDTLS_SHA3_256); + break; +#endif +#if defined(MBEDTLS_PSA_BUILTIN_ALG_SHA3_384) + case PSA_ALG_SHA3_384: + mbedtls_sha3_init(&operation->ctx.sha3); + ret = mbedtls_sha3_starts(&operation->ctx.sha3, MBEDTLS_SHA3_384); + break; +#endif +#if defined(MBEDTLS_PSA_BUILTIN_ALG_SHA3_512) + case PSA_ALG_SHA3_512: + mbedtls_sha3_init(&operation->ctx.sha3); + ret = mbedtls_sha3_starts(&operation->ctx.sha3, MBEDTLS_SHA3_512); break; #endif default: @@ -229,18 +186,6 @@ psa_status_t mbedtls_psa_hash_clone( switch (source_operation->alg) { case 0: return PSA_ERROR_BAD_STATE; -#if defined(MBEDTLS_PSA_BUILTIN_ALG_MD2) - case PSA_ALG_MD2: - mbedtls_md2_clone(&target_operation->ctx.md2, - &source_operation->ctx.md2); - break; -#endif -#if defined(MBEDTLS_PSA_BUILTIN_ALG_MD4) - case PSA_ALG_MD4: - mbedtls_md4_clone(&target_operation->ctx.md4, - &source_operation->ctx.md4); - break; -#endif #if defined(MBEDTLS_PSA_BUILTIN_ALG_MD5) case PSA_ALG_MD5: mbedtls_md5_clone(&target_operation->ctx.md5, @@ -282,6 +227,26 @@ psa_status_t mbedtls_psa_hash_clone( mbedtls_sha512_clone(&target_operation->ctx.sha512, &source_operation->ctx.sha512); break; +#endif +#if defined(MBEDTLS_PSA_BUILTIN_ALG_SHA3_224) + case PSA_ALG_SHA3_224: +#endif +#if defined(MBEDTLS_PSA_BUILTIN_ALG_SHA3_256) + case PSA_ALG_SHA3_256: +#endif +#if defined(MBEDTLS_PSA_BUILTIN_ALG_SHA3_384) + case PSA_ALG_SHA3_384: +#endif +#if defined(MBEDTLS_PSA_BUILTIN_ALG_SHA3_512) + case PSA_ALG_SHA3_512: +#endif +#if defined(MBEDTLS_PSA_BUILTIN_ALG_SHA3_224) || \ + defined(MBEDTLS_PSA_BUILTIN_ALG_SHA3_256) || \ + defined(MBEDTLS_PSA_BUILTIN_ALG_SHA3_384) || \ + defined(MBEDTLS_PSA_BUILTIN_ALG_SHA3_512) + mbedtls_sha3_clone(&target_operation->ctx.sha3, + &source_operation->ctx.sha3); + break; #endif default: (void) source_operation; @@ -301,59 +266,67 @@ psa_status_t mbedtls_psa_hash_update( int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED; switch (operation->alg) { -#if defined(MBEDTLS_PSA_BUILTIN_ALG_MD2) - case PSA_ALG_MD2: - ret = mbedtls_md2_update_ret(&operation->ctx.md2, - input, input_length); - break; -#endif -#if defined(MBEDTLS_PSA_BUILTIN_ALG_MD4) - case PSA_ALG_MD4: - ret = mbedtls_md4_update_ret(&operation->ctx.md4, - input, input_length); - break; -#endif #if defined(MBEDTLS_PSA_BUILTIN_ALG_MD5) case PSA_ALG_MD5: - ret = mbedtls_md5_update_ret(&operation->ctx.md5, - input, input_length); + ret = mbedtls_md5_update(&operation->ctx.md5, + input, input_length); break; #endif #if defined(MBEDTLS_PSA_BUILTIN_ALG_RIPEMD160) case PSA_ALG_RIPEMD160: - ret = mbedtls_ripemd160_update_ret(&operation->ctx.ripemd160, - input, input_length); + ret = mbedtls_ripemd160_update(&operation->ctx.ripemd160, + input, input_length); break; #endif #if defined(MBEDTLS_PSA_BUILTIN_ALG_SHA_1) case PSA_ALG_SHA_1: - ret = mbedtls_sha1_update_ret(&operation->ctx.sha1, - input, input_length); + ret = mbedtls_sha1_update(&operation->ctx.sha1, + input, input_length); break; #endif #if defined(MBEDTLS_PSA_BUILTIN_ALG_SHA_224) case PSA_ALG_SHA_224: - ret = mbedtls_sha256_update_ret(&operation->ctx.sha256, - input, input_length); + ret = mbedtls_sha256_update(&operation->ctx.sha256, + input, input_length); break; #endif #if defined(MBEDTLS_PSA_BUILTIN_ALG_SHA_256) case PSA_ALG_SHA_256: - ret = mbedtls_sha256_update_ret(&operation->ctx.sha256, - input, input_length); + ret = mbedtls_sha256_update(&operation->ctx.sha256, + input, input_length); break; #endif #if defined(MBEDTLS_PSA_BUILTIN_ALG_SHA_384) case PSA_ALG_SHA_384: - ret = mbedtls_sha512_update_ret(&operation->ctx.sha512, - input, input_length); + ret = mbedtls_sha512_update(&operation->ctx.sha512, + input, input_length); break; #endif #if defined(MBEDTLS_PSA_BUILTIN_ALG_SHA_512) case PSA_ALG_SHA_512: - ret = mbedtls_sha512_update_ret(&operation->ctx.sha512, - input, input_length); + ret = mbedtls_sha512_update(&operation->ctx.sha512, + input, input_length); break; +#endif +#if defined(MBEDTLS_PSA_BUILTIN_ALG_SHA3_224) + case PSA_ALG_SHA3_224: +#endif +#if defined(MBEDTLS_PSA_BUILTIN_ALG_SHA3_256) + case PSA_ALG_SHA3_256: +#endif +#if defined(MBEDTLS_PSA_BUILTIN_ALG_SHA3_384) + case PSA_ALG_SHA3_384: +#endif +#if defined(MBEDTLS_PSA_BUILTIN_ALG_SHA3_512) + case PSA_ALG_SHA3_512: +#endif +#if defined(MBEDTLS_PSA_BUILTIN_ALG_SHA3_224) || \ + defined(MBEDTLS_PSA_BUILTIN_ALG_SHA3_256) || \ + defined(MBEDTLS_PSA_BUILTIN_ALG_SHA3_384) || \ + defined(MBEDTLS_PSA_BUILTIN_ALG_SHA3_512) + ret = mbedtls_sha3_update(&operation->ctx.sha3, + input, input_length); + break; #endif default: (void) input; @@ -390,50 +363,59 @@ psa_status_t mbedtls_psa_hash_finish( } switch (operation->alg) { -#if defined(MBEDTLS_PSA_BUILTIN_ALG_MD2) - case PSA_ALG_MD2: - ret = mbedtls_md2_finish_ret(&operation->ctx.md2, hash); - break; -#endif -#if defined(MBEDTLS_PSA_BUILTIN_ALG_MD4) - case PSA_ALG_MD4: - ret = mbedtls_md4_finish_ret(&operation->ctx.md4, hash); - break; -#endif #if defined(MBEDTLS_PSA_BUILTIN_ALG_MD5) case PSA_ALG_MD5: - ret = mbedtls_md5_finish_ret(&operation->ctx.md5, hash); + ret = mbedtls_md5_finish(&operation->ctx.md5, hash); break; #endif #if defined(MBEDTLS_PSA_BUILTIN_ALG_RIPEMD160) case PSA_ALG_RIPEMD160: - ret = mbedtls_ripemd160_finish_ret(&operation->ctx.ripemd160, hash); + ret = mbedtls_ripemd160_finish(&operation->ctx.ripemd160, hash); break; #endif #if defined(MBEDTLS_PSA_BUILTIN_ALG_SHA_1) case PSA_ALG_SHA_1: - ret = mbedtls_sha1_finish_ret(&operation->ctx.sha1, hash); + ret = mbedtls_sha1_finish(&operation->ctx.sha1, hash); break; #endif #if defined(MBEDTLS_PSA_BUILTIN_ALG_SHA_224) case PSA_ALG_SHA_224: - ret = mbedtls_sha256_finish_ret(&operation->ctx.sha256, hash); + ret = mbedtls_sha256_finish(&operation->ctx.sha256, hash); break; #endif #if defined(MBEDTLS_PSA_BUILTIN_ALG_SHA_256) case PSA_ALG_SHA_256: - ret = mbedtls_sha256_finish_ret(&operation->ctx.sha256, hash); + ret = mbedtls_sha256_finish(&operation->ctx.sha256, hash); break; #endif #if defined(MBEDTLS_PSA_BUILTIN_ALG_SHA_384) case PSA_ALG_SHA_384: - ret = mbedtls_sha512_finish_ret(&operation->ctx.sha512, hash); + ret = mbedtls_sha512_finish(&operation->ctx.sha512, hash); break; #endif #if defined(MBEDTLS_PSA_BUILTIN_ALG_SHA_512) case PSA_ALG_SHA_512: - ret = mbedtls_sha512_finish_ret(&operation->ctx.sha512, hash); + ret = mbedtls_sha512_finish(&operation->ctx.sha512, hash); break; +#endif +#if defined(MBEDTLS_PSA_BUILTIN_ALG_SHA3_224) + case PSA_ALG_SHA3_224: +#endif +#if defined(MBEDTLS_PSA_BUILTIN_ALG_SHA3_256) + case PSA_ALG_SHA3_256: +#endif +#if defined(MBEDTLS_PSA_BUILTIN_ALG_SHA3_384) + case PSA_ALG_SHA3_384: +#endif +#if defined(MBEDTLS_PSA_BUILTIN_ALG_SHA3_512) + case PSA_ALG_SHA3_512: +#endif +#if defined(MBEDTLS_PSA_BUILTIN_ALG_SHA3_224) || \ + defined(MBEDTLS_PSA_BUILTIN_ALG_SHA3_256) || \ + defined(MBEDTLS_PSA_BUILTIN_ALG_SHA3_384) || \ + defined(MBEDTLS_PSA_BUILTIN_ALG_SHA3_512) + ret = mbedtls_sha3_finish(&operation->ctx.sha3, hash, hash_size); + break; #endif default: (void) hash; diff --git a/vendor/mbedtls/library/psa_crypto_hash.h b/vendor/mbedtls/library/psa_crypto_hash.h index 1c1b451988..0a7be80552 100644 --- a/vendor/mbedtls/library/psa_crypto_hash.h +++ b/vendor/mbedtls/library/psa_crypto_hash.h @@ -3,19 +3,7 @@ */ /* * Copyright The Mbed TLS Contributors - * SPDX-License-Identifier: Apache-2.0 - * - * Licensed under the Apache License, Version 2.0 (the "License"); you may - * not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT - * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. + * SPDX-License-Identifier: Apache-2.0 OR GPL-2.0-or-later */ #ifndef PSA_CRYPTO_HASH_H @@ -23,17 +11,6 @@ #include -#include - -/** Get Mbed TLS MD information of a hash algorithm given its PSA identifier - * - * \param[in] alg PSA hash algorithm identifier - * - * \return The Mbed TLS MD information of the hash algorithm. \c NULL if the - * PSA hash algorithm is not supported. - */ -const mbedtls_md_info_t *mbedtls_md_info_from_psa(psa_algorithm_t alg); - /** Calculate the hash (digest) of a message using Mbed TLS routines. * * \note The signature of this function is that of a PSA driver hash_compute diff --git a/vendor/mbedtls/library/psa_crypto_invasive.h b/vendor/mbedtls/library/psa_crypto_invasive.h index 58e357e379..51c90c64a4 100644 --- a/vendor/mbedtls/library/psa_crypto_invasive.h +++ b/vendor/mbedtls/library/psa_crypto_invasive.h @@ -10,29 +10,20 @@ */ /* * Copyright The Mbed TLS Contributors - * SPDX-License-Identifier: Apache-2.0 - * - * Licensed under the Apache License, Version 2.0 (the "License"); you may - * not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT - * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. + * SPDX-License-Identifier: Apache-2.0 OR GPL-2.0-or-later */ #ifndef PSA_CRYPTO_INVASIVE_H #define PSA_CRYPTO_INVASIVE_H -#if defined(MBEDTLS_CONFIG_FILE) -#include MBEDTLS_CONFIG_FILE -#else -#include "mbedtls/config.h" -#endif +/* + * Include the build-time configuration information header. Here, we do not + * include `"mbedtls/build_info.h"` directly but `"psa/build_info.h"`, which + * is basically just an alias to it. This is to ease the maintenance of the + * TF-PSA-Crypto repository which has a different build system and + * configuration. + */ +#include "psa/build_info.h" #include "psa/crypto.h" #include "common.h" @@ -81,6 +72,21 @@ psa_status_t mbedtls_psa_crypto_configure_entropy_sources( psa_status_t psa_mac_key_can_do( psa_algorithm_t algorithm, psa_key_type_t key_type); + +psa_status_t psa_crypto_copy_input(const uint8_t *input, size_t input_len, + uint8_t *input_copy, size_t input_copy_len); + +psa_status_t psa_crypto_copy_output(const uint8_t *output_copy, size_t output_copy_len, + uint8_t *output, size_t output_len); + +/* + * Test hooks to use for memory unpoisoning/poisoning in copy functions. + */ +extern void (*psa_input_pre_copy_hook)(const uint8_t *input, size_t input_len); +extern void (*psa_input_post_copy_hook)(const uint8_t *input, size_t input_len); +extern void (*psa_output_pre_copy_hook)(const uint8_t *output, size_t output_len); +extern void (*psa_output_post_copy_hook)(const uint8_t *output, size_t output_len); + #endif /* MBEDTLS_TEST_HOOKS && MBEDTLS_PSA_CRYPTO_C */ #endif /* PSA_CRYPTO_INVASIVE_H */ diff --git a/vendor/mbedtls/library/psa_crypto_its.h b/vendor/mbedtls/library/psa_crypto_its.h index 3ceee49bea..877063b878 100644 --- a/vendor/mbedtls/library/psa_crypto_its.h +++ b/vendor/mbedtls/library/psa_crypto_its.h @@ -3,19 +3,7 @@ */ /* * Copyright The Mbed TLS Contributors - * SPDX-License-Identifier: Apache-2.0 - * - * Licensed under the Apache License, Version 2.0 (the "License"); you may - * not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT - * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. + * SPDX-License-Identifier: Apache-2.0 OR GPL-2.0-or-later */ #ifndef PSA_CRYPTO_ITS_H diff --git a/vendor/mbedtls/library/psa_crypto_mac.c b/vendor/mbedtls/library/psa_crypto_mac.c index 07f123ee05..8fe6218118 100644 --- a/vendor/mbedtls/library/psa_crypto_mac.c +++ b/vendor/mbedtls/library/psa_crypto_mac.c @@ -3,19 +3,7 @@ */ /* * Copyright The Mbed TLS Contributors - * SPDX-License-Identifier: Apache-2.0 - * - * Licensed under the Apache License, Version 2.0 (the "License"); you may - * not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT - * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. + * SPDX-License-Identifier: Apache-2.0 OR GPL-2.0-or-later */ #include "common.h" @@ -29,6 +17,7 @@ #include #include +#include "mbedtls/constant_time.h" #include #if defined(MBEDTLS_PSA_BUILTIN_ALG_HMAC) @@ -453,7 +442,7 @@ psa_status_t mbedtls_psa_mac_verify_finish( goto cleanup; } - if (mbedtls_psa_safer_memcmp(mac, actual_mac, mac_length) != 0) { + if (mbedtls_ct_memcmp(mac, actual_mac, mac_length) != 0) { status = PSA_ERROR_INVALID_SIGNATURE; } diff --git a/vendor/mbedtls/library/psa_crypto_mac.h b/vendor/mbedtls/library/psa_crypto_mac.h index 4f8024a9e3..2f614bcc6e 100644 --- a/vendor/mbedtls/library/psa_crypto_mac.h +++ b/vendor/mbedtls/library/psa_crypto_mac.h @@ -3,19 +3,7 @@ */ /* * Copyright The Mbed TLS Contributors - * SPDX-License-Identifier: Apache-2.0 - * - * Licensed under the Apache License, Version 2.0 (the "License"); you may - * not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT - * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. + * SPDX-License-Identifier: Apache-2.0 OR GPL-2.0-or-later */ #ifndef PSA_CRYPTO_MAC_H diff --git a/vendor/mbedtls/library/psa_crypto_pake.c b/vendor/mbedtls/library/psa_crypto_pake.c new file mode 100644 index 0000000000..9ac2e8c486 --- /dev/null +++ b/vendor/mbedtls/library/psa_crypto_pake.c @@ -0,0 +1,571 @@ +/* + * PSA PAKE layer on top of Mbed TLS software crypto + */ +/* + * Copyright The Mbed TLS Contributors + * SPDX-License-Identifier: Apache-2.0 OR GPL-2.0-or-later + */ + +#include "common.h" + +#if defined(MBEDTLS_PSA_CRYPTO_C) + +#include +#include "psa_crypto_core.h" +#include "psa_crypto_pake.h" +#include "psa_crypto_slot_management.h" + +#include +#include "psa_util_internal.h" + +#include +#include +#include + +/* + * State sequence: + * + * psa_pake_setup() + * | + * |-- In any order: + * | | psa_pake_set_password_key() + * | | psa_pake_set_user() + * | | psa_pake_set_peer() + * | | psa_pake_set_role() + * | + * |--- In any order: (First round input before or after first round output) + * | | + * | |------ In Order + * | | | psa_pake_output(PSA_PAKE_STEP_KEY_SHARE) + * | | | psa_pake_output(PSA_PAKE_STEP_ZK_PUBLIC) + * | | | psa_pake_output(PSA_PAKE_STEP_ZK_PROOF) + * | | | psa_pake_output(PSA_PAKE_STEP_KEY_SHARE) + * | | | psa_pake_output(PSA_PAKE_STEP_ZK_PUBLIC) + * | | | psa_pake_output(PSA_PAKE_STEP_ZK_PROOF) + * | | + * | |------ In Order: + * | | psa_pake_input(PSA_PAKE_STEP_KEY_SHARE) + * | | psa_pake_input(PSA_PAKE_STEP_ZK_PUBLIC) + * | | psa_pake_input(PSA_PAKE_STEP_ZK_PROOF) + * | | psa_pake_input(PSA_PAKE_STEP_KEY_SHARE) + * | | psa_pake_input(PSA_PAKE_STEP_ZK_PUBLIC) + * | | psa_pake_input(PSA_PAKE_STEP_ZK_PROOF) + * | + * |--- In any order: (Second round input before or after second round output) + * | | + * | |------ In Order + * | | | psa_pake_output(PSA_PAKE_STEP_KEY_SHARE) + * | | | psa_pake_output(PSA_PAKE_STEP_ZK_PUBLIC) + * | | | psa_pake_output(PSA_PAKE_STEP_ZK_PROOF) + * | | + * | |------ In Order: + * | | psa_pake_input(PSA_PAKE_STEP_KEY_SHARE) + * | | psa_pake_input(PSA_PAKE_STEP_ZK_PUBLIC) + * | | psa_pake_input(PSA_PAKE_STEP_ZK_PROOF) + * | + * psa_pake_get_implicit_key() + * psa_pake_abort() + */ + +/* + * Possible sequence of calls to implementation: + * + * |--- In any order: + * | | + * | |------ In Order + * | | | mbedtls_psa_pake_output(PSA_JPAKE_X1_STEP_KEY_SHARE) + * | | | mbedtls_psa_pake_output(PSA_JPAKE_X1_STEP_ZK_PUBLIC) + * | | | mbedtls_psa_pake_output(PSA_JPAKE_X1_STEP_ZK_PROOF) + * | | | mbedtls_psa_pake_output(PSA_JPAKE_X2_STEP_KEY_SHARE) + * | | | mbedtls_psa_pake_output(PSA_JPAKE_X2_STEP_ZK_PUBLIC) + * | | | mbedtls_psa_pake_output(PSA_JPAKE_X2_STEP_ZK_PROOF) + * | | + * | |------ In Order: + * | | mbedtls_psa_pake_input(PSA_JPAKE_X1_STEP_KEY_SHARE) + * | | mbedtls_psa_pake_input(PSA_JPAKE_X1_STEP_ZK_PUBLIC) + * | | mbedtls_psa_pake_input(PSA_JPAKE_X1_STEP_ZK_PROOF) + * | | mbedtls_psa_pake_input(PSA_JPAKE_X2_STEP_KEY_SHARE) + * | | mbedtls_psa_pake_input(PSA_JPAKE_X2_STEP_ZK_PUBLIC) + * | | mbedtls_psa_pake_input(PSA_JPAKE_X2_STEP_ZK_PROOF) + * | + * |--- In any order: + * | | + * | |------ In Order + * | | | mbedtls_psa_pake_output(PSA_JPAKE_X2S_STEP_KEY_SHARE) + * | | | mbedtls_psa_pake_output(PSA_JPAKE_X2S_STEP_ZK_PUBLIC) + * | | | mbedtls_psa_pake_output(PSA_JPAKE_X2S_STEP_ZK_PROOF) + * | | + * | |------ In Order: + * | | mbedtls_psa_pake_input(PSA_JPAKE_X4S_STEP_KEY_SHARE) + * | | mbedtls_psa_pake_input(PSA_JPAKE_X4S_STEP_ZK_PUBLIC) + * | | mbedtls_psa_pake_input(PSA_JPAKE_X4S_STEP_ZK_PROOF) + */ + +#if defined(MBEDTLS_PSA_BUILTIN_ALG_JPAKE) +static psa_status_t mbedtls_ecjpake_to_psa_error(int ret) +{ + switch (ret) { + case MBEDTLS_ERR_MPI_BAD_INPUT_DATA: + case MBEDTLS_ERR_ECP_BAD_INPUT_DATA: + case MBEDTLS_ERR_ECP_INVALID_KEY: + case MBEDTLS_ERR_ECP_VERIFY_FAILED: + return PSA_ERROR_DATA_INVALID; + case MBEDTLS_ERR_MPI_BUFFER_TOO_SMALL: + case MBEDTLS_ERR_ECP_BUFFER_TOO_SMALL: + return PSA_ERROR_BUFFER_TOO_SMALL; + case MBEDTLS_ERR_MD_FEATURE_UNAVAILABLE: + return PSA_ERROR_NOT_SUPPORTED; + case MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED: + return PSA_ERROR_CORRUPTION_DETECTED; + default: + return PSA_ERROR_GENERIC_ERROR; + } +} +#endif + +#if defined(MBEDTLS_PSA_BUILTIN_PAKE) +#if defined(MBEDTLS_PSA_BUILTIN_ALG_JPAKE) +static psa_status_t psa_pake_ecjpake_setup(mbedtls_psa_pake_operation_t *operation) +{ + int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED; + + mbedtls_ecjpake_init(&operation->ctx.jpake); + + ret = mbedtls_ecjpake_setup(&operation->ctx.jpake, + operation->role, + MBEDTLS_MD_SHA256, + MBEDTLS_ECP_DP_SECP256R1, + operation->password, + operation->password_len); + + mbedtls_platform_zeroize(operation->password, operation->password_len); + + if (ret != 0) { + return mbedtls_ecjpake_to_psa_error(ret); + } + + return PSA_SUCCESS; +} +#endif + +/* The only two JPAKE user/peer identifiers supported in built-in implementation. */ +static const uint8_t jpake_server_id[] = { 's', 'e', 'r', 'v', 'e', 'r' }; +static const uint8_t jpake_client_id[] = { 'c', 'l', 'i', 'e', 'n', 't' }; + +psa_status_t mbedtls_psa_pake_setup(mbedtls_psa_pake_operation_t *operation, + const psa_crypto_driver_pake_inputs_t *inputs) +{ + psa_status_t status = PSA_ERROR_CORRUPTION_DETECTED; + size_t user_len = 0, peer_len = 0, password_len = 0; + uint8_t *peer = NULL, *user = NULL; + size_t actual_user_len = 0, actual_peer_len = 0, actual_password_len = 0; + psa_pake_cipher_suite_t cipher_suite = psa_pake_cipher_suite_init(); + + status = psa_crypto_driver_pake_get_password_len(inputs, &password_len); + if (status != PSA_SUCCESS) { + return status; + } + + status = psa_crypto_driver_pake_get_user_len(inputs, &user_len); + if (status != PSA_SUCCESS) { + return status; + } + + status = psa_crypto_driver_pake_get_peer_len(inputs, &peer_len); + if (status != PSA_SUCCESS) { + return status; + } + + status = psa_crypto_driver_pake_get_cipher_suite(inputs, &cipher_suite); + if (status != PSA_SUCCESS) { + return status; + } + + operation->password = mbedtls_calloc(1, password_len); + if (operation->password == NULL) { + status = PSA_ERROR_INSUFFICIENT_MEMORY; + goto error; + } + + user = mbedtls_calloc(1, user_len); + if (user == NULL) { + status = PSA_ERROR_INSUFFICIENT_MEMORY; + goto error; + } + + peer = mbedtls_calloc(1, peer_len); + if (peer == NULL) { + status = PSA_ERROR_INSUFFICIENT_MEMORY; + goto error; + } + + status = psa_crypto_driver_pake_get_password(inputs, operation->password, + password_len, &actual_password_len); + if (status != PSA_SUCCESS) { + goto error; + } + + status = psa_crypto_driver_pake_get_user(inputs, user, + user_len, &actual_user_len); + if (status != PSA_SUCCESS) { + goto error; + } + + status = psa_crypto_driver_pake_get_peer(inputs, peer, + peer_len, &actual_peer_len); + if (status != PSA_SUCCESS) { + goto error; + } + + operation->password_len = actual_password_len; + operation->alg = cipher_suite.algorithm; + +#if defined(MBEDTLS_PSA_BUILTIN_ALG_JPAKE) + if (cipher_suite.algorithm == PSA_ALG_JPAKE) { + if (cipher_suite.type != PSA_PAKE_PRIMITIVE_TYPE_ECC || + cipher_suite.family != PSA_ECC_FAMILY_SECP_R1 || + cipher_suite.bits != 256 || + cipher_suite.hash != PSA_ALG_SHA_256) { + status = PSA_ERROR_NOT_SUPPORTED; + goto error; + } + + const size_t user_peer_len = sizeof(jpake_client_id); // client and server have the same length + if (actual_user_len != user_peer_len || + actual_peer_len != user_peer_len) { + status = PSA_ERROR_NOT_SUPPORTED; + goto error; + } + + if (memcmp(user, jpake_client_id, actual_user_len) == 0 && + memcmp(peer, jpake_server_id, actual_peer_len) == 0) { + operation->role = MBEDTLS_ECJPAKE_CLIENT; + } else + if (memcmp(user, jpake_server_id, actual_user_len) == 0 && + memcmp(peer, jpake_client_id, actual_peer_len) == 0) { + operation->role = MBEDTLS_ECJPAKE_SERVER; + } else { + status = PSA_ERROR_NOT_SUPPORTED; + goto error; + } + + operation->buffer_length = 0; + operation->buffer_offset = 0; + + status = psa_pake_ecjpake_setup(operation); + if (status != PSA_SUCCESS) { + goto error; + } + + /* Role has been set, release user/peer buffers. */ + mbedtls_free(user); mbedtls_free(peer); + + return PSA_SUCCESS; + } else +#else + (void) operation; + (void) inputs; +#endif + { status = PSA_ERROR_NOT_SUPPORTED; } + +error: + mbedtls_free(user); mbedtls_free(peer); + /* In case of failure of the setup of a multipart operation, the PSA driver interface + * specifies that the core does not call any other driver entry point thus does not + * call mbedtls_psa_pake_abort(). Therefore call it here to do the needed clean + * up like freeing the memory that may have been allocated to store the password. + */ + mbedtls_psa_pake_abort(operation); + return status; +} + +static psa_status_t mbedtls_psa_pake_output_internal( + mbedtls_psa_pake_operation_t *operation, + psa_crypto_driver_pake_step_t step, + uint8_t *output, + size_t output_size, + size_t *output_length) +{ + int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED; + size_t length; + (void) step; // Unused parameter + +#if defined(MBEDTLS_PSA_BUILTIN_ALG_JPAKE) + /* + * The PSA CRYPTO PAKE and Mbed TLS JPAKE API have a different + * handling of output sequencing. + * + * The Mbed TLS JPAKE API outputs the whole X1+X2 and X2S steps data + * at once, on the other side the PSA CRYPTO PAKE api requires + * the KEY_SHARE/ZP_PUBLIC/ZK_PROOF parts of X1, X2 & X2S to be + * retrieved in sequence. + * + * In order to achieve API compatibility, the whole X1+X2 or X2S steps + * data is stored in an intermediate buffer at first step output call, + * and data is sliced down by parsing the ECPoint records in order + * to return the right parts on each step. + */ + if (operation->alg == PSA_ALG_JPAKE) { + /* Initialize & write round on KEY_SHARE sequences */ + if (step == PSA_JPAKE_X1_STEP_KEY_SHARE) { + ret = mbedtls_ecjpake_write_round_one(&operation->ctx.jpake, + operation->buffer, + sizeof(operation->buffer), + &operation->buffer_length, + mbedtls_psa_get_random, + MBEDTLS_PSA_RANDOM_STATE); + if (ret != 0) { + return mbedtls_ecjpake_to_psa_error(ret); + } + + operation->buffer_offset = 0; + } else if (step == PSA_JPAKE_X2S_STEP_KEY_SHARE) { + ret = mbedtls_ecjpake_write_round_two(&operation->ctx.jpake, + operation->buffer, + sizeof(operation->buffer), + &operation->buffer_length, + mbedtls_psa_get_random, + MBEDTLS_PSA_RANDOM_STATE); + if (ret != 0) { + return mbedtls_ecjpake_to_psa_error(ret); + } + + operation->buffer_offset = 0; + } + + /* + * mbedtls_ecjpake_write_round_xxx() outputs thing in the format + * defined by draft-cragie-tls-ecjpake-01 section 7. The summary is + * that the data for each step is prepended with a length byte, and + * then they're concatenated. Additionally, the server's second round + * output is prepended with a 3-bytes ECParameters structure. + * + * In PSA, we output each step separately, and don't prepend the + * output with a length byte, even less a curve identifier, as that + * information is already available. + */ + if (step == PSA_JPAKE_X2S_STEP_KEY_SHARE && + operation->role == MBEDTLS_ECJPAKE_SERVER) { + /* Skip ECParameters, with is 3 bytes (RFC 8422) */ + operation->buffer_offset += 3; + } + + /* Read the length byte then move past it to the data */ + length = operation->buffer[operation->buffer_offset]; + operation->buffer_offset += 1; + + if (operation->buffer_offset + length > operation->buffer_length) { + return PSA_ERROR_DATA_CORRUPT; + } + + if (output_size < length) { + return PSA_ERROR_BUFFER_TOO_SMALL; + } + + memcpy(output, + operation->buffer + operation->buffer_offset, + length); + *output_length = length; + + operation->buffer_offset += length; + + /* Reset buffer after ZK_PROOF sequence */ + if ((step == PSA_JPAKE_X2_STEP_ZK_PROOF) || + (step == PSA_JPAKE_X2S_STEP_ZK_PROOF)) { + mbedtls_platform_zeroize(operation->buffer, sizeof(operation->buffer)); + operation->buffer_length = 0; + operation->buffer_offset = 0; + } + + return PSA_SUCCESS; + } else +#else + (void) step; + (void) output; + (void) output_size; + (void) output_length; +#endif + { return PSA_ERROR_NOT_SUPPORTED; } +} + +psa_status_t mbedtls_psa_pake_output(mbedtls_psa_pake_operation_t *operation, + psa_crypto_driver_pake_step_t step, + uint8_t *output, + size_t output_size, + size_t *output_length) +{ + psa_status_t status = mbedtls_psa_pake_output_internal( + operation, step, output, output_size, output_length); + + return status; +} + +static psa_status_t mbedtls_psa_pake_input_internal( + mbedtls_psa_pake_operation_t *operation, + psa_crypto_driver_pake_step_t step, + const uint8_t *input, + size_t input_length) +{ + int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED; + (void) step; // Unused parameter + +#if defined(MBEDTLS_PSA_BUILTIN_ALG_JPAKE) + /* + * The PSA CRYPTO PAKE and Mbed TLS JPAKE API have a different + * handling of input sequencing. + * + * The Mbed TLS JPAKE API takes the whole X1+X2 or X4S steps data + * at once as input, on the other side the PSA CRYPTO PAKE api requires + * the KEY_SHARE/ZP_PUBLIC/ZK_PROOF parts of X1, X2 & X4S to be + * given in sequence. + * + * In order to achieve API compatibility, each X1+X2 or X4S step data + * is stored sequentially in an intermediate buffer and given to the + * Mbed TLS JPAKE API on the last step. + * + * This causes any input error to be only detected on the last step. + */ + if (operation->alg == PSA_ALG_JPAKE) { + /* + * Copy input to local buffer and format it as the Mbed TLS API + * expects, i.e. as defined by draft-cragie-tls-ecjpake-01 section 7. + * The summary is that the data for each step is prepended with a + * length byte, and then they're concatenated. Additionally, the + * server's second round output is prepended with a 3-bytes + * ECParameters structure - which means we have to prepend that when + * we're a client. + */ + if (step == PSA_JPAKE_X4S_STEP_KEY_SHARE && + operation->role == MBEDTLS_ECJPAKE_CLIENT) { + /* We only support secp256r1. */ + /* This is the ECParameters structure defined by RFC 8422. */ + unsigned char ecparameters[3] = { + 3, /* named_curve */ + 0, 23 /* secp256r1 */ + }; + + if (operation->buffer_length + sizeof(ecparameters) > + sizeof(operation->buffer)) { + return PSA_ERROR_BUFFER_TOO_SMALL; + } + + memcpy(operation->buffer + operation->buffer_length, + ecparameters, sizeof(ecparameters)); + operation->buffer_length += sizeof(ecparameters); + } + + /* + * The core checks that input_length is smaller than + * PSA_PAKE_INPUT_MAX_SIZE. + * Thus no risk of integer overflow here. + */ + if (operation->buffer_length + input_length + 1 > sizeof(operation->buffer)) { + return PSA_ERROR_BUFFER_TOO_SMALL; + } + + /* Write the length byte */ + operation->buffer[operation->buffer_length] = (uint8_t) input_length; + operation->buffer_length += 1; + + /* Finally copy the data */ + memcpy(operation->buffer + operation->buffer_length, + input, input_length); + operation->buffer_length += input_length; + + /* Load buffer at each last round ZK_PROOF */ + if (step == PSA_JPAKE_X2_STEP_ZK_PROOF) { + ret = mbedtls_ecjpake_read_round_one(&operation->ctx.jpake, + operation->buffer, + operation->buffer_length); + + mbedtls_platform_zeroize(operation->buffer, sizeof(operation->buffer)); + operation->buffer_length = 0; + + if (ret != 0) { + return mbedtls_ecjpake_to_psa_error(ret); + } + } else if (step == PSA_JPAKE_X4S_STEP_ZK_PROOF) { + ret = mbedtls_ecjpake_read_round_two(&operation->ctx.jpake, + operation->buffer, + operation->buffer_length); + + mbedtls_platform_zeroize(operation->buffer, sizeof(operation->buffer)); + operation->buffer_length = 0; + + if (ret != 0) { + return mbedtls_ecjpake_to_psa_error(ret); + } + } + + return PSA_SUCCESS; + } else +#else + (void) step; + (void) input; + (void) input_length; +#endif + { return PSA_ERROR_NOT_SUPPORTED; } +} + +psa_status_t mbedtls_psa_pake_input(mbedtls_psa_pake_operation_t *operation, + psa_crypto_driver_pake_step_t step, + const uint8_t *input, + size_t input_length) +{ + psa_status_t status = mbedtls_psa_pake_input_internal( + operation, step, input, input_length); + + return status; +} + +psa_status_t mbedtls_psa_pake_get_implicit_key( + mbedtls_psa_pake_operation_t *operation, + uint8_t *output, size_t output_size, + size_t *output_length) +{ + int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED; + +#if defined(MBEDTLS_PSA_BUILTIN_ALG_JPAKE) + if (operation->alg == PSA_ALG_JPAKE) { + ret = mbedtls_ecjpake_write_shared_key(&operation->ctx.jpake, + output, + output_size, + output_length, + mbedtls_psa_get_random, + MBEDTLS_PSA_RANDOM_STATE); + if (ret != 0) { + return mbedtls_ecjpake_to_psa_error(ret); + } + + return PSA_SUCCESS; + } else +#else + (void) output; +#endif + { return PSA_ERROR_NOT_SUPPORTED; } +} + +psa_status_t mbedtls_psa_pake_abort(mbedtls_psa_pake_operation_t *operation) +{ + mbedtls_zeroize_and_free(operation->password, operation->password_len); + operation->password = NULL; + operation->password_len = 0; + +#if defined(MBEDTLS_PSA_BUILTIN_ALG_JPAKE) + if (operation->alg == PSA_ALG_JPAKE) { + operation->role = MBEDTLS_ECJPAKE_NONE; + mbedtls_platform_zeroize(operation->buffer, sizeof(operation->buffer)); + operation->buffer_length = 0; + operation->buffer_offset = 0; + mbedtls_ecjpake_free(&operation->ctx.jpake); + } +#endif + + operation->alg = PSA_ALG_NONE; + + return PSA_SUCCESS; +} + +#endif /* MBEDTLS_PSA_BUILTIN_PAKE */ + +#endif /* MBEDTLS_PSA_CRYPTO_C */ diff --git a/vendor/mbedtls/library/psa_crypto_pake.h b/vendor/mbedtls/library/psa_crypto_pake.h new file mode 100644 index 0000000000..3d3ee0cc9a --- /dev/null +++ b/vendor/mbedtls/library/psa_crypto_pake.h @@ -0,0 +1,159 @@ +/* + * PSA PAKE layer on top of Mbed TLS software crypto + */ +/* + * Copyright The Mbed TLS Contributors + * SPDX-License-Identifier: Apache-2.0 OR GPL-2.0-or-later + */ + +#ifndef PSA_CRYPTO_PAKE_H +#define PSA_CRYPTO_PAKE_H + +#include + +/** Set the session information for a password-authenticated key exchange. + * + * \note The signature of this function is that of a PSA driver + * pake_setup entry point. This function behaves as a pake_setup + * entry point as defined in the PSA driver interface specification for + * transparent drivers. + * + * \param[in,out] operation The operation object to set up. It must have + * been initialized but not set up yet. + * \param[in] inputs Inputs required for PAKE operation (role, password, + * key lifetime, cipher suite) + * + * \retval #PSA_SUCCESS + * Success. + * \retval #PSA_ERROR_NOT_SUPPORTED + * The algorithm in \p cipher_suite is not a supported PAKE algorithm, + * or the PAKE primitive in \p cipher_suite is not supported or not + * compatible with the PAKE algorithm, or the hash algorithm in + * \p cipher_suite is not supported or not compatible with the PAKE + * algorithm and primitive. + * \retval #PSA_ERROR_INSUFFICIENT_MEMORY \emptydescription + * \retval #PSA_ERROR_CORRUPTION_DETECTED \emptydescription + */ +psa_status_t mbedtls_psa_pake_setup(mbedtls_psa_pake_operation_t *operation, + const psa_crypto_driver_pake_inputs_t *inputs); + + +/** Get output for a step of a password-authenticated key exchange. + * + * \note The signature of this function is that of a PSA driver + * pake_output entry point. This function behaves as a pake_output + * entry point as defined in the PSA driver interface specification for + * transparent drivers. + * + * \param[in,out] operation Active PAKE operation. + * \param step The step of the algorithm for which the output is + * requested. + * \param[out] output Buffer where the output is to be written in the + * format appropriate for this driver \p step. Refer to + * the documentation of psa_crypto_driver_pake_step_t for + * more information. + * \param output_size Size of the \p output buffer in bytes. This must + * be at least #PSA_PAKE_OUTPUT_SIZE(\p alg, \p + * primitive, \p step) where \p alg and + * \p primitive are the PAKE algorithm and primitive + * in the operation's cipher suite, and \p step is + * the output step. + * + * \param[out] output_length On success, the number of bytes of the returned + * output. + * + * \retval #PSA_SUCCESS + * Success. + * \retval #PSA_ERROR_BUFFER_TOO_SMALL + * The size of the \p output buffer is too small. + * \retval #PSA_ERROR_INSUFFICIENT_ENTROPY \emptydescription + * \retval #PSA_ERROR_CORRUPTION_DETECTED \emptydescription + * \retval #PSA_ERROR_DATA_CORRUPT \emptydescription + * \retval #PSA_ERROR_DATA_INVALID \emptydescription + */ +psa_status_t mbedtls_psa_pake_output(mbedtls_psa_pake_operation_t *operation, + psa_crypto_driver_pake_step_t step, + uint8_t *output, + size_t output_size, + size_t *output_length); + +/** Provide input for a step of a password-authenticated key exchange. + * + * \note The signature of this function is that of a PSA driver + * pake_input entry point. This function behaves as a pake_input + * entry point as defined in the PSA driver interface specification for + * transparent drivers. + * + * \note The core checks that input_length is smaller than PSA_PAKE_INPUT_MAX_SIZE. + * + * \param[in,out] operation Active PAKE operation. + * \param step The driver step for which the input is provided. + * \param[in] input Buffer containing the input in the format + * appropriate for this \p step. Refer to the + * documentation of psa_crypto_driver_pake_step_t + * for more information. + * \param input_length Size of the \p input buffer in bytes. + * + * \retval #PSA_SUCCESS + * Success. + * \retval #PSA_ERROR_INVALID_SIGNATURE + * The verification fails for a zero-knowledge input step. + * \retval #PSA_ERROR_INVALID_ARGUMENT + * the \p input is not valid for the \p operation's algorithm, cipher suite + * or \p step. + * \retval #PSA_ERROR_NOT_SUPPORTED + * the \p input is not supported for the \p operation's algorithm, cipher + * suite or \p step. + * \retval #PSA_ERROR_INSUFFICIENT_MEMORY \emptydescription + * \retval #PSA_ERROR_CORRUPTION_DETECTED \emptydescription + * \retval #PSA_ERROR_DATA_CORRUPT \emptydescription + * \retval #PSA_ERROR_DATA_INVALID \emptydescription + */ +psa_status_t mbedtls_psa_pake_input(mbedtls_psa_pake_operation_t *operation, + psa_crypto_driver_pake_step_t step, + const uint8_t *input, + size_t input_length); + +/** Get implicitly confirmed shared secret from a PAKE. + * + * \note The signature of this function is that of a PSA driver + * pake_get_implicit_key entry point. This function behaves as a + * pake_get_implicit_key entry point as defined in the PSA driver + * interface specification for transparent drivers. + * + * \param[in,out] operation Active PAKE operation. + * \param[out] output Output buffer for implicit key. + * \param output_size Size of the output buffer in bytes. + * \param[out] output_length On success, the number of bytes of the implicit key. + * + * \retval #PSA_SUCCESS + * Success. + * \retval #PSA_ERROR_NOT_SUPPORTED + * Input from a PAKE is not supported by the algorithm in the \p output + * key derivation operation. + * \retval #PSA_ERROR_INSUFFICIENT_MEMORY \emptydescription + * \retval #PSA_ERROR_CORRUPTION_DETECTED \emptydescription + * \retval #PSA_ERROR_DATA_CORRUPT \emptydescription + * \retval #PSA_ERROR_DATA_INVALID \emptydescription + */ +psa_status_t mbedtls_psa_pake_get_implicit_key( + mbedtls_psa_pake_operation_t *operation, + uint8_t *output, size_t output_size, + size_t *output_length); + +/** Abort a PAKE operation. + * + * \note The signature of this function is that of a PSA driver + * pake_abort entry point. This function behaves as a pake_abort + * entry point as defined in the PSA driver interface specification for + * transparent drivers. + * + * \param[in,out] operation The operation to abort. + * + * \retval #PSA_SUCCESS + * Success. + * \retval #PSA_ERROR_CORRUPTION_DETECTED \emptydescription + */ +psa_status_t mbedtls_psa_pake_abort(mbedtls_psa_pake_operation_t *operation); + +#endif /* PSA_CRYPTO_PAKE_H */ diff --git a/vendor/mbedtls/library/psa_crypto_random_impl.h b/vendor/mbedtls/library/psa_crypto_random_impl.h index f1a2af11d9..533fb2e940 100644 --- a/vendor/mbedtls/library/psa_crypto_random_impl.h +++ b/vendor/mbedtls/library/psa_crypto_random_impl.h @@ -1,55 +1,25 @@ /** \file psa_crypto_random_impl.h * * \brief PSA crypto random generator implementation abstraction. - * - * The definitions here need to be consistent with the declarations - * in include/mbedtls/psa_util.h. This file contains some redundant - * declarations to increase the chance that a compiler will detect - * inconsistencies if one file is changed without updating the other, - * but not all potential inconsistencies can be enforced, so make sure - * to check the public declarations and contracts in - * include/mbedtls/psa_util.h if you modify this file. */ /* * Copyright The Mbed TLS Contributors - * SPDX-License-Identifier: Apache-2.0 - * - * Licensed under the Apache License, Version 2.0 (the "License"); you may - * not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT - * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. + * SPDX-License-Identifier: Apache-2.0 OR GPL-2.0-or-later */ #ifndef PSA_CRYPTO_RANDOM_IMPL_H #define PSA_CRYPTO_RANDOM_IMPL_H -#include +#include "psa_util_internal.h" #if defined(MBEDTLS_PSA_CRYPTO_EXTERNAL_RNG) -#include -#include // only for error codes -#include - typedef mbedtls_psa_external_random_context_t mbedtls_psa_random_context_t; -/* Trivial wrapper around psa_generate_random(). */ -int mbedtls_psa_get_random(void *p_rng, - unsigned char *output, - size_t output_size); - -/* The PSA RNG API doesn't need any externally maintained state. */ -#define MBEDTLS_PSA_RANDOM_STATE NULL - #else /* MBEDTLS_PSA_CRYPTO_EXTERNAL_RNG */ +#include "mbedtls/entropy.h" + /* Choose a DRBG based on configuration and availability */ #if defined(MBEDTLS_PSA_HMAC_DRBG_MD_TYPE) @@ -62,7 +32,7 @@ int mbedtls_psa_get_random(void *p_rng, #elif defined(MBEDTLS_HMAC_DRBG_C) #include "mbedtls/hmac_drbg.h" -#if defined(MBEDTLS_SHA512_C) && defined(MBEDTLS_SHA256_C) +#if defined(MBEDTLS_MD_CAN_SHA512) && defined(MBEDTLS_MD_CAN_SHA256) #include #if SIZE_MAX > 0xffffffff /* Looks like a 64-bit system, so prefer SHA-512. */ @@ -71,19 +41,45 @@ int mbedtls_psa_get_random(void *p_rng, /* Looks like a 32-bit system, so prefer SHA-256. */ #define MBEDTLS_PSA_HMAC_DRBG_MD_TYPE MBEDTLS_MD_SHA256 #endif -#elif defined(MBEDTLS_SHA512_C) +#elif defined(MBEDTLS_MD_CAN_SHA512) #define MBEDTLS_PSA_HMAC_DRBG_MD_TYPE MBEDTLS_MD_SHA512 -#elif defined(MBEDTLS_SHA256_C) +#elif defined(MBEDTLS_MD_CAN_SHA256) #define MBEDTLS_PSA_HMAC_DRBG_MD_TYPE MBEDTLS_MD_SHA256 #else #error "No hash algorithm available for HMAC_DBRG." #endif -#else +#else /* !MBEDTLS_PSA_HMAC_DRBG_MD_TYPE && !MBEDTLS_CTR_DRBG_C && !MBEDTLS_HMAC_DRBG_C*/ + #error "No DRBG module available for the psa_crypto module." + +#endif /* !MBEDTLS_PSA_HMAC_DRBG_MD_TYPE && !MBEDTLS_CTR_DRBG_C && !MBEDTLS_HMAC_DRBG_C*/ + +#if defined(MBEDTLS_CTR_DRBG_C) +#include "mbedtls/ctr_drbg.h" +#elif defined(MBEDTLS_HMAC_DRBG_C) +#include "mbedtls/hmac_drbg.h" +#endif /* !MBEDTLS_CTR_DRBG_C && !MBEDTLS_HMAC_DRBG_C */ + +/* The maximum number of bytes that mbedtls_psa_get_random() is expected to return. */ +#if defined(MBEDTLS_CTR_DRBG_C) +#define MBEDTLS_PSA_RANDOM_MAX_REQUEST MBEDTLS_CTR_DRBG_MAX_REQUEST +#elif defined(MBEDTLS_HMAC_DRBG_C) +#define MBEDTLS_PSA_RANDOM_MAX_REQUEST MBEDTLS_HMAC_DRBG_MAX_REQUEST #endif -#include "mbedtls/entropy.h" +#if defined(MBEDTLS_CTR_DRBG_C) +typedef mbedtls_ctr_drbg_context mbedtls_psa_drbg_context_t; +#elif defined(MBEDTLS_HMAC_DRBG_C) +typedef mbedtls_hmac_drbg_context mbedtls_psa_drbg_context_t; +#endif /* !MBEDTLS_CTR_DRBG_C && !MBEDTLS_HMAC_DRBG_C */ + +typedef struct { + void (* entropy_init)(mbedtls_entropy_context *ctx); + void (* entropy_free)(mbedtls_entropy_context *ctx); + mbedtls_entropy_context entropy; + mbedtls_psa_drbg_context_t drbg; +} mbedtls_psa_random_context_t; /** Initialize the PSA DRBG. * @@ -111,63 +107,6 @@ static inline void mbedtls_psa_drbg_free(mbedtls_psa_drbg_context_t *p_rng) #endif } -/** The type of the PSA random generator context. - * - * The random generator context is composed of an entropy context and - * a DRBG context. - */ -typedef struct { - void (* entropy_init)(mbedtls_entropy_context *ctx); - void (* entropy_free)(mbedtls_entropy_context *ctx); - mbedtls_entropy_context entropy; - mbedtls_psa_drbg_context_t drbg; -} mbedtls_psa_random_context_t; - -/* Defined in include/mbedtls/psa_util.h so that it's visible to - * application code. The declaration here is redundant, but included - * as a safety net to make it more likely that a future change that - * accidentally causes the implementation to diverge from the interface - * will be noticed. */ -/* Do not include the declaration under MSVC because it doesn't accept it - * ("error C2370: 'mbedtls_psa_get_random' : redefinition; different storage class"). - * Observed with Visual Studio 2013. A known bug apparently: - * https://stackoverflow.com/questions/8146541/duplicate-external-static-declarations-not-allowed-in-visual-studio - */ -#if !defined(_MSC_VER) -static mbedtls_f_rng_t *const mbedtls_psa_get_random; -#endif - -/** The maximum number of bytes that mbedtls_psa_get_random() is expected to - * return. - */ -#if defined(MBEDTLS_CTR_DRBG_C) -#define MBEDTLS_PSA_RANDOM_MAX_REQUEST MBEDTLS_CTR_DRBG_MAX_REQUEST -#elif defined(MBEDTLS_HMAC_DRBG_C) -#define MBEDTLS_PSA_RANDOM_MAX_REQUEST MBEDTLS_HMAC_DRBG_MAX_REQUEST -#endif - -/** A pointer to the PSA DRBG state. - * - * This variable is only intended to be used through the macro - * #MBEDTLS_PSA_RANDOM_STATE. - */ -/* psa_crypto.c sets this variable to a pointer to the DRBG state in the - * global PSA crypto state. */ -/* The type `mbedtls_psa_drbg_context_t` is defined in - * include/mbedtls/psa_util.h so that `mbedtls_psa_random_state` can be - * declared there and be visible to application code. */ -extern mbedtls_psa_drbg_context_t *const mbedtls_psa_random_state; - -/** A pointer to the PSA DRBG state. - * - * This macro expands to an expression that is suitable as the \c p_rng - * parameter to pass to mbedtls_psa_get_random(). - * - * This macro exists in all configurations where the psa_crypto module is - * enabled. Its expansion depends on the configuration. - */ -#define MBEDTLS_PSA_RANDOM_STATE mbedtls_psa_random_state - /** Seed the PSA DRBG. * * \param entropy An entropy context to read the seed from. @@ -179,23 +118,15 @@ extern mbedtls_psa_drbg_context_t *const mbedtls_psa_random_state; * \return \c 0 on success. * \return An Mbed TLS error code (\c MBEDTLS_ERR_xxx) on failure. */ -static inline int mbedtls_psa_drbg_seed( - mbedtls_entropy_context *entropy, - const unsigned char *custom, size_t len) +static inline int mbedtls_psa_drbg_seed(mbedtls_psa_drbg_context_t *drbg_ctx, + mbedtls_entropy_context *entropy, + const unsigned char *custom, size_t len) { #if defined(MBEDTLS_CTR_DRBG_C) - return mbedtls_ctr_drbg_seed(MBEDTLS_PSA_RANDOM_STATE, - mbedtls_entropy_func, - entropy, - custom, len); + return mbedtls_ctr_drbg_seed(drbg_ctx, mbedtls_entropy_func, entropy, custom, len); #elif defined(MBEDTLS_HMAC_DRBG_C) - const mbedtls_md_info_t *md_info = - mbedtls_md_info_from_type(MBEDTLS_PSA_HMAC_DRBG_MD_TYPE); - return mbedtls_hmac_drbg_seed(MBEDTLS_PSA_RANDOM_STATE, - md_info, - mbedtls_entropy_func, - entropy, - custom, len); + const mbedtls_md_info_t *md_info = mbedtls_md_info_from_type(MBEDTLS_PSA_HMAC_DRBG_MD_TYPE); + return mbedtls_hmac_drbg_seed(drbg_ctx, md_info, mbedtls_entropy_func, entropy, custom, len); #endif } diff --git a/vendor/mbedtls/library/psa_crypto_rsa.c b/vendor/mbedtls/library/psa_crypto_rsa.c index 853a0443c8..2f613b32da 100644 --- a/vendor/mbedtls/library/psa_crypto_rsa.c +++ b/vendor/mbedtls/library/psa_crypto_rsa.c @@ -3,19 +3,7 @@ */ /* * Copyright The Mbed TLS Contributors - * SPDX-License-Identifier: Apache-2.0 - * - * Licensed under the Apache License, Version 2.0 (the "License"); you may - * not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT - * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. + * SPDX-License-Identifier: Apache-2.0 OR GPL-2.0-or-later */ #include "common.h" @@ -23,10 +11,12 @@ #if defined(MBEDTLS_PSA_CRYPTO_C) #include +#include "psa/crypto_values.h" #include "psa_crypto_core.h" #include "psa_crypto_random_impl.h" #include "psa_crypto_rsa.h" #include "psa_crypto_hash.h" +#include "mbedtls/psa_util.h" #include #include @@ -34,14 +24,14 @@ #include #include -#include -#include +#include "rsa_internal.h" #if defined(MBEDTLS_PSA_BUILTIN_ALG_RSA_PKCS1V15_CRYPT) || \ defined(MBEDTLS_PSA_BUILTIN_ALG_RSA_OAEP) || \ defined(MBEDTLS_PSA_BUILTIN_ALG_RSA_PKCS1V15_SIGN) || \ defined(MBEDTLS_PSA_BUILTIN_ALG_RSA_PSS) || \ - defined(MBEDTLS_PSA_BUILTIN_KEY_TYPE_RSA_KEY_PAIR) || \ + defined(MBEDTLS_PSA_BUILTIN_KEY_TYPE_RSA_KEY_PAIR_IMPORT) || \ + defined(MBEDTLS_PSA_BUILTIN_KEY_TYPE_RSA_KEY_PAIR_EXPORT) || \ defined(MBEDTLS_PSA_BUILTIN_KEY_TYPE_RSA_PUBLIC_KEY) /* Mbed TLS doesn't support non-byte-aligned key sizes (i.e. key sizes @@ -71,61 +61,51 @@ psa_status_t mbedtls_psa_rsa_load_representation( mbedtls_rsa_context **p_rsa) { psa_status_t status; - mbedtls_pk_context ctx; size_t bits; - mbedtls_pk_init(&ctx); + + *p_rsa = mbedtls_calloc(1, sizeof(mbedtls_rsa_context)); + if (*p_rsa == NULL) { + return PSA_ERROR_INSUFFICIENT_MEMORY; + } + mbedtls_rsa_init(*p_rsa); /* Parse the data. */ if (PSA_KEY_TYPE_IS_KEY_PAIR(type)) { - status = mbedtls_to_psa_error( - mbedtls_pk_parse_key(&ctx, data, data_length, NULL, 0)); + status = mbedtls_to_psa_error(mbedtls_rsa_parse_key(*p_rsa, data, data_length)); } else { - status = mbedtls_to_psa_error( - mbedtls_pk_parse_public_key(&ctx, data, data_length)); + status = mbedtls_to_psa_error(mbedtls_rsa_parse_pubkey(*p_rsa, data, data_length)); } if (status != PSA_SUCCESS) { goto exit; } - /* We have something that the pkparse module recognizes. If it is a - * valid RSA key, store it. */ - if (mbedtls_pk_get_type(&ctx) != MBEDTLS_PK_RSA) { - status = PSA_ERROR_INVALID_ARGUMENT; - goto exit; - } - /* The size of an RSA key doesn't have to be a multiple of 8. Mbed TLS * supports non-byte-aligned key sizes, but not well. For example, * mbedtls_rsa_get_len() returns the key size in bytes, not in bits. */ - bits = PSA_BYTES_TO_BITS(mbedtls_rsa_get_len(mbedtls_pk_rsa(ctx))); + bits = PSA_BYTES_TO_BITS(mbedtls_rsa_get_len(*p_rsa)); if (bits > PSA_VENDOR_RSA_MAX_KEY_BITS) { status = PSA_ERROR_NOT_SUPPORTED; goto exit; } - status = psa_check_rsa_key_byte_aligned(mbedtls_pk_rsa(ctx)); + status = psa_check_rsa_key_byte_aligned(*p_rsa); if (status != PSA_SUCCESS) { goto exit; } - /* Copy out the pointer to the RSA context, and reset the PK context - * such that pk_free doesn't free the RSA context we just grabbed. */ - *p_rsa = mbedtls_pk_rsa(ctx); - ctx.pk_info = NULL; - exit: - mbedtls_pk_free(&ctx); return status; } #endif /* defined(MBEDTLS_PSA_BUILTIN_ALG_RSA_PKCS1V15_CRYPT) || * defined(MBEDTLS_PSA_BUILTIN_ALG_RSA_OAEP) || * defined(MBEDTLS_PSA_BUILTIN_ALG_RSA_PKCS1V15_SIGN) || * defined(MBEDTLS_PSA_BUILTIN_ALG_RSA_PSS) || - * defined(MBEDTLS_PSA_BUILTIN_KEY_TYPE_RSA_KEY_PAIR) || + * defined(MBEDTLS_PSA_BUILTIN_KEY_TYPE_RSA_KEY_PAIR_IMPORT) || + * defined(MBEDTLS_PSA_BUILTIN_KEY_TYPE_RSA_KEY_PAIR_EXPORT) || * defined(MBEDTLS_PSA_BUILTIN_KEY_TYPE_RSA_PUBLIC_KEY) */ -#if defined(MBEDTLS_PSA_BUILTIN_KEY_TYPE_RSA_KEY_PAIR) || \ +#if (defined(MBEDTLS_PSA_BUILTIN_KEY_TYPE_RSA_KEY_PAIR_IMPORT) && \ + defined(MBEDTLS_PSA_BUILTIN_KEY_TYPE_RSA_KEY_PAIR_EXPORT)) || \ defined(MBEDTLS_PSA_BUILTIN_KEY_TYPE_RSA_PUBLIC_KEY) - psa_status_t mbedtls_psa_rsa_import_key( const psa_key_attributes_t *attributes, const uint8_t *data, size_t data_length, @@ -136,7 +116,7 @@ psa_status_t mbedtls_psa_rsa_import_key( mbedtls_rsa_context *rsa = NULL; /* Parse input */ - status = mbedtls_psa_rsa_load_representation(attributes->core.type, + status = mbedtls_psa_rsa_load_representation(attributes->type, data, data_length, &rsa); @@ -150,7 +130,7 @@ psa_status_t mbedtls_psa_rsa_import_key( * representation in the key slot. Export representation in case of RSA is * the smallest representation that's allowed as input, so a straight-up * allocation of the same size as the input buffer will be large enough. */ - status = mbedtls_psa_rsa_export_key(attributes->core.type, + status = mbedtls_psa_rsa_export_key(attributes->type, rsa, key_buffer, key_buffer_size, @@ -162,29 +142,28 @@ psa_status_t mbedtls_psa_rsa_import_key( return status; } +#endif /* (defined(MBEDTLS_PSA_BUILTIN_KEY_TYPE_RSA_KEY_PAIR_IMPORT) && + * defined(MBEDTLS_PSA_BUILTIN_KEY_TYPE_RSA_KEY_PAIR_EXPORT)) || + * defined(MBEDTLS_PSA_BUILTIN_KEY_TYPE_RSA_PUBLIC_KEY) */ +#if defined(MBEDTLS_PSA_BUILTIN_KEY_TYPE_RSA_KEY_PAIR_EXPORT) || \ + defined(MBEDTLS_PSA_BUILTIN_KEY_TYPE_RSA_PUBLIC_KEY) psa_status_t mbedtls_psa_rsa_export_key(psa_key_type_t type, mbedtls_rsa_context *rsa, uint8_t *data, size_t data_size, size_t *data_length) { -#if defined(MBEDTLS_PK_WRITE_C) int ret; - mbedtls_pk_context pk; - uint8_t *pos = data + data_size; - - mbedtls_pk_init(&pk); - pk.pk_info = &mbedtls_rsa_info; - pk.pk_ctx = rsa; + uint8_t *end = data + data_size; /* PSA Crypto API defines the format of an RSA key as a DER-encoded * representation of the non-encrypted PKCS#1 RSAPrivateKey for a * private key and of the RFC3279 RSAPublicKey for a public key. */ if (PSA_KEY_TYPE_IS_KEY_PAIR(type)) { - ret = mbedtls_pk_write_key_der(&pk, data, data_size); + ret = mbedtls_rsa_write_key(rsa, data, &end); } else { - ret = mbedtls_pk_write_pubkey(&pos, data, &pk); + ret = mbedtls_rsa_write_pubkey(rsa, data, &end); } if (ret < 0) { @@ -206,14 +185,6 @@ psa_status_t mbedtls_psa_rsa_export_key(psa_key_type_t type, *data_length = ret; return PSA_SUCCESS; -#else - (void) type; - (void) rsa; - (void) data; - (void) data_size; - (void) data_length; - return PSA_ERROR_NOT_SUPPORTED; -#endif /* MBEDTLS_PK_WRITE_C */ } psa_status_t mbedtls_psa_rsa_export_public_key( @@ -225,7 +196,7 @@ psa_status_t mbedtls_psa_rsa_export_public_key( mbedtls_rsa_context *rsa = NULL; status = mbedtls_psa_rsa_load_representation( - attributes->core.type, key_buffer, key_buffer_size, &rsa); + attributes->type, key_buffer, key_buffer_size, &rsa); if (status != PSA_SUCCESS) { return status; } @@ -241,31 +212,25 @@ psa_status_t mbedtls_psa_rsa_export_public_key( return status; } -#endif /* defined(MBEDTLS_PSA_BUILTIN_KEY_TYPE_RSA_KEY_PAIR) || +#endif /* defined(MBEDTLS_PSA_BUILTIN_KEY_TYPE_RSA_KEY_PAIR_EXPORT) || * defined(MBEDTLS_PSA_BUILTIN_KEY_TYPE_RSA_PUBLIC_KEY) */ -#if defined(MBEDTLS_PSA_BUILTIN_KEY_TYPE_RSA_KEY_PAIR) && \ - defined(MBEDTLS_GENPRIME) -static psa_status_t psa_rsa_read_exponent(const uint8_t *domain_parameters, - size_t domain_parameters_size, +#if defined(MBEDTLS_PSA_BUILTIN_KEY_TYPE_RSA_KEY_PAIR_GENERATE) +static psa_status_t psa_rsa_read_exponent(const uint8_t *e_bytes, + size_t e_length, int *exponent) { size_t i; uint32_t acc = 0; - if (domain_parameters_size == 0) { - *exponent = 65537; - return PSA_SUCCESS; - } - /* Mbed TLS encodes the public exponent as an int. For simplicity, only * support values that fit in a 32-bit integer, which is larger than * int on just about every platform anyway. */ - if (domain_parameters_size > sizeof(acc)) { + if (e_length > sizeof(acc)) { return PSA_ERROR_NOT_SUPPORTED; } - for (i = 0; i < domain_parameters_size; i++) { - acc = (acc << 8) | domain_parameters[i]; + for (i = 0; i < e_length; i++) { + acc = (acc << 8) | e_bytes[i]; } if (acc > INT_MAX) { return PSA_ERROR_NOT_SUPPORTED; @@ -276,39 +241,40 @@ static psa_status_t psa_rsa_read_exponent(const uint8_t *domain_parameters, psa_status_t mbedtls_psa_rsa_generate_key( const psa_key_attributes_t *attributes, + const psa_key_production_parameters_t *params, size_t params_data_length, uint8_t *key_buffer, size_t key_buffer_size, size_t *key_buffer_length) { psa_status_t status; mbedtls_rsa_context rsa; int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED; - int exponent; + int exponent = 65537; - status = psa_rsa_read_exponent(attributes->domain_parameters, - attributes->domain_parameters_size, - &exponent); - if (status != PSA_SUCCESS) { - return status; + if (params_data_length != 0) { + status = psa_rsa_read_exponent(params->data, params_data_length, + &exponent); + if (status != PSA_SUCCESS) { + return status; + } } - mbedtls_rsa_init(&rsa, MBEDTLS_RSA_PKCS_V15, MBEDTLS_MD_NONE); + mbedtls_rsa_init(&rsa); ret = mbedtls_rsa_gen_key(&rsa, mbedtls_psa_get_random, MBEDTLS_PSA_RANDOM_STATE, - (unsigned int) attributes->core.bits, + (unsigned int) attributes->bits, exponent); if (ret != 0) { return mbedtls_to_psa_error(ret); } - status = mbedtls_psa_rsa_export_key(attributes->core.type, + status = mbedtls_psa_rsa_export_key(attributes->type, &rsa, key_buffer, key_buffer_size, key_buffer_length); mbedtls_rsa_free(&rsa); return status; } -#endif /* defined(MBEDTLS_PSA_BUILTIN_KEY_TYPE_RSA_KEY_PAIR) - * defined(MBEDTLS_GENPRIME) */ +#endif /* defined(MBEDTLS_PSA_BUILTIN_KEY_TYPE_RSA_KEY_PAIR_GENERATE) */ /****************************************************************/ /* Sign/verify hashes */ @@ -324,8 +290,7 @@ static psa_status_t psa_rsa_decode_md_type(psa_algorithm_t alg, mbedtls_md_type_t *md_alg) { psa_algorithm_t hash_alg = PSA_ALG_SIGN_GET_HASH(alg); - const mbedtls_md_info_t *md_info = mbedtls_md_info_from_psa(hash_alg); - *md_alg = mbedtls_md_get_type(md_info); + *md_alg = mbedtls_md_type_from_psa_alg(hash_alg); /* The Mbed TLS RSA module uses an unsigned int for hash length * parameters. Validate that it fits so that we don't risk an @@ -338,10 +303,10 @@ static psa_status_t psa_rsa_decode_md_type(psa_algorithm_t alg, /* For signatures using a hash, the hash length must be correct. */ if (alg != PSA_ALG_RSA_PKCS1V15_SIGN_RAW) { - if (md_info == NULL) { + if (*md_alg == MBEDTLS_MD_NONE) { return PSA_ERROR_NOT_SUPPORTED; } - if (mbedtls_md_get_size(md_info) != hash_length) { + if (mbedtls_md_get_size_from_type(*md_alg) != hash_length) { return PSA_ERROR_INVALID_ARGUMENT; } } @@ -360,7 +325,7 @@ psa_status_t mbedtls_psa_rsa_sign_hash( int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED; mbedtls_md_type_t md_alg; - status = mbedtls_psa_rsa_load_representation(attributes->core.type, + status = mbedtls_psa_rsa_load_representation(attributes->type, key_buffer, key_buffer_size, &rsa); @@ -380,29 +345,32 @@ psa_status_t mbedtls_psa_rsa_sign_hash( #if defined(MBEDTLS_PSA_BUILTIN_ALG_RSA_PKCS1V15_SIGN) if (PSA_ALG_IS_RSA_PKCS1V15_SIGN(alg)) { - mbedtls_rsa_set_padding(rsa, MBEDTLS_RSA_PKCS_V15, - MBEDTLS_MD_NONE); - ret = mbedtls_rsa_pkcs1_sign(rsa, - mbedtls_psa_get_random, - MBEDTLS_PSA_RANDOM_STATE, - MBEDTLS_RSA_PRIVATE, - md_alg, - (unsigned int) hash_length, - hash, - signature); + ret = mbedtls_rsa_set_padding(rsa, MBEDTLS_RSA_PKCS_V15, + MBEDTLS_MD_NONE); + if (ret == 0) { + ret = mbedtls_rsa_pkcs1_sign(rsa, + mbedtls_psa_get_random, + MBEDTLS_PSA_RANDOM_STATE, + md_alg, + (unsigned int) hash_length, + hash, + signature); + } } else #endif /* MBEDTLS_PSA_BUILTIN_ALG_RSA_PKCS1V15_SIGN */ #if defined(MBEDTLS_PSA_BUILTIN_ALG_RSA_PSS) if (PSA_ALG_IS_RSA_PSS(alg)) { - mbedtls_rsa_set_padding(rsa, MBEDTLS_RSA_PKCS_V21, md_alg); - ret = mbedtls_rsa_rsassa_pss_sign(rsa, - mbedtls_psa_get_random, - MBEDTLS_PSA_RANDOM_STATE, - MBEDTLS_RSA_PRIVATE, - MBEDTLS_MD_NONE, - (unsigned int) hash_length, - hash, - signature); + ret = mbedtls_rsa_set_padding(rsa, MBEDTLS_RSA_PKCS_V21, md_alg); + + if (ret == 0) { + ret = mbedtls_rsa_rsassa_pss_sign(rsa, + mbedtls_psa_get_random, + MBEDTLS_PSA_RANDOM_STATE, + MBEDTLS_MD_NONE, + (unsigned int) hash_length, + hash, + signature); + } } else #endif /* MBEDTLS_PSA_BUILTIN_ALG_RSA_PSS */ { @@ -456,7 +424,7 @@ psa_status_t mbedtls_psa_rsa_verify_hash( int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED; mbedtls_md_type_t md_alg; - status = mbedtls_psa_rsa_load_representation(attributes->core.type, + status = mbedtls_psa_rsa_load_representation(attributes->type, key_buffer, key_buffer_size, &rsa); @@ -476,32 +444,30 @@ psa_status_t mbedtls_psa_rsa_verify_hash( #if defined(MBEDTLS_PSA_BUILTIN_ALG_RSA_PKCS1V15_SIGN) if (PSA_ALG_IS_RSA_PKCS1V15_SIGN(alg)) { - mbedtls_rsa_set_padding(rsa, MBEDTLS_RSA_PKCS_V15, - MBEDTLS_MD_NONE); - ret = mbedtls_rsa_pkcs1_verify(rsa, - mbedtls_psa_get_random, - MBEDTLS_PSA_RANDOM_STATE, - MBEDTLS_RSA_PUBLIC, - md_alg, - (unsigned int) hash_length, - hash, - signature); + ret = mbedtls_rsa_set_padding(rsa, MBEDTLS_RSA_PKCS_V15, + MBEDTLS_MD_NONE); + if (ret == 0) { + ret = mbedtls_rsa_pkcs1_verify(rsa, + md_alg, + (unsigned int) hash_length, + hash, + signature); + } } else #endif /* MBEDTLS_PSA_BUILTIN_ALG_RSA_PKCS1V15_SIGN */ #if defined(MBEDTLS_PSA_BUILTIN_ALG_RSA_PSS) if (PSA_ALG_IS_RSA_PSS(alg)) { - int slen = rsa_pss_expected_salt_len(alg, rsa, hash_length); - mbedtls_rsa_set_padding(rsa, MBEDTLS_RSA_PKCS_V21, md_alg); - ret = mbedtls_rsa_rsassa_pss_verify_ext(rsa, - mbedtls_psa_get_random, - MBEDTLS_PSA_RANDOM_STATE, - MBEDTLS_RSA_PUBLIC, - md_alg, - (unsigned int) hash_length, - hash, - md_alg, - slen, - signature); + ret = mbedtls_rsa_set_padding(rsa, MBEDTLS_RSA_PKCS_V21, md_alg); + if (ret == 0) { + int slen = rsa_pss_expected_salt_len(alg, rsa, hash_length); + ret = mbedtls_rsa_rsassa_pss_verify_ext(rsa, + md_alg, + (unsigned) hash_length, + hash, + md_alg, + slen, + signature); + } } else #endif /* MBEDTLS_PSA_BUILTIN_ALG_RSA_PSS */ { @@ -526,4 +492,215 @@ psa_status_t mbedtls_psa_rsa_verify_hash( #endif /* defined(MBEDTLS_PSA_BUILTIN_ALG_RSA_PKCS1V15_SIGN) || * defined(MBEDTLS_PSA_BUILTIN_ALG_RSA_PSS) */ +/****************************************************************/ +/* Asymmetric cryptography */ +/****************************************************************/ + +#if defined(MBEDTLS_PSA_BUILTIN_ALG_RSA_OAEP) +static int psa_rsa_oaep_set_padding_mode(psa_algorithm_t alg, + mbedtls_rsa_context *rsa) +{ + psa_algorithm_t hash_alg = PSA_ALG_RSA_OAEP_GET_HASH(alg); + mbedtls_md_type_t md_alg = mbedtls_md_type_from_psa_alg(hash_alg); + + /* Just to get the error status right, as rsa_set_padding() doesn't + * distinguish between "bad RSA algorithm" and "unknown hash". */ + if (mbedtls_md_info_from_type(md_alg) == NULL) { + return PSA_ERROR_NOT_SUPPORTED; + } + + return mbedtls_rsa_set_padding(rsa, MBEDTLS_RSA_PKCS_V21, md_alg); +} +#endif /* defined(MBEDTLS_PSA_BUILTIN_ALG_RSA_OAEP) */ + +psa_status_t mbedtls_psa_asymmetric_encrypt(const psa_key_attributes_t *attributes, + const uint8_t *key_buffer, + size_t key_buffer_size, + psa_algorithm_t alg, + const uint8_t *input, + size_t input_length, + const uint8_t *salt, + size_t salt_length, + uint8_t *output, + size_t output_size, + size_t *output_length) +{ + psa_status_t status = PSA_ERROR_CORRUPTION_DETECTED; + (void) key_buffer; + (void) key_buffer_size; + (void) input; + (void) input_length; + (void) salt; + (void) salt_length; + (void) output; + (void) output_size; + (void) output_length; + + if (PSA_KEY_TYPE_IS_RSA(attributes->type)) { +#if defined(MBEDTLS_PSA_BUILTIN_ALG_RSA_PKCS1V15_CRYPT) || \ + defined(MBEDTLS_PSA_BUILTIN_ALG_RSA_OAEP) + mbedtls_rsa_context *rsa = NULL; + status = mbedtls_psa_rsa_load_representation(attributes->type, + key_buffer, + key_buffer_size, + &rsa); + if (status != PSA_SUCCESS) { + goto rsa_exit; + } + + if (output_size < mbedtls_rsa_get_len(rsa)) { + status = PSA_ERROR_BUFFER_TOO_SMALL; + goto rsa_exit; + } +#endif /* defined(MBEDTLS_PSA_BUILTIN_ALG_RSA_PKCS1V15_CRYPT) || + * defined(MBEDTLS_PSA_BUILTIN_ALG_RSA_OAEP) */ + if (alg == PSA_ALG_RSA_PKCS1V15_CRYPT) { +#if defined(MBEDTLS_PSA_BUILTIN_ALG_RSA_PKCS1V15_CRYPT) + status = mbedtls_to_psa_error( + mbedtls_rsa_pkcs1_encrypt(rsa, + mbedtls_psa_get_random, + MBEDTLS_PSA_RANDOM_STATE, + input_length, + input, + output)); +#else + status = PSA_ERROR_NOT_SUPPORTED; +#endif /* MBEDTLS_PSA_BUILTIN_ALG_RSA_PKCS1V15_CRYPT */ + } else + if (PSA_ALG_IS_RSA_OAEP(alg)) { +#if defined(MBEDTLS_PSA_BUILTIN_ALG_RSA_OAEP) + status = mbedtls_to_psa_error( + psa_rsa_oaep_set_padding_mode(alg, rsa)); + if (status != PSA_SUCCESS) { + goto rsa_exit; + } + + status = mbedtls_to_psa_error( + mbedtls_rsa_rsaes_oaep_encrypt(rsa, + mbedtls_psa_get_random, + MBEDTLS_PSA_RANDOM_STATE, + salt, salt_length, + input_length, + input, + output)); +#else + status = PSA_ERROR_NOT_SUPPORTED; +#endif /* MBEDTLS_PSA_BUILTIN_ALG_RSA_OAEP */ + } else { + status = PSA_ERROR_INVALID_ARGUMENT; + } +#if defined(MBEDTLS_PSA_BUILTIN_ALG_RSA_PKCS1V15_CRYPT) || \ + defined(MBEDTLS_PSA_BUILTIN_ALG_RSA_OAEP) +rsa_exit: + if (status == PSA_SUCCESS) { + *output_length = mbedtls_rsa_get_len(rsa); + } + + mbedtls_rsa_free(rsa); + mbedtls_free(rsa); +#endif /* defined(MBEDTLS_PSA_BUILTIN_ALG_RSA_PKCS1V15_CRYPT) || + * defined(MBEDTLS_PSA_BUILTIN_ALG_RSA_OAEP) */ + } else { + status = PSA_ERROR_NOT_SUPPORTED; + } + + return status; +} + +psa_status_t mbedtls_psa_asymmetric_decrypt(const psa_key_attributes_t *attributes, + const uint8_t *key_buffer, + size_t key_buffer_size, + psa_algorithm_t alg, + const uint8_t *input, + size_t input_length, + const uint8_t *salt, + size_t salt_length, + uint8_t *output, + size_t output_size, + size_t *output_length) +{ + psa_status_t status = PSA_ERROR_CORRUPTION_DETECTED; + (void) key_buffer; + (void) key_buffer_size; + (void) input; + (void) input_length; + (void) salt; + (void) salt_length; + (void) output; + (void) output_size; + (void) output_length; + + *output_length = 0; + + if (attributes->type == PSA_KEY_TYPE_RSA_KEY_PAIR) { +#if defined(MBEDTLS_PSA_BUILTIN_ALG_RSA_PKCS1V15_CRYPT) || \ + defined(MBEDTLS_PSA_BUILTIN_ALG_RSA_OAEP) + mbedtls_rsa_context *rsa = NULL; + status = mbedtls_psa_rsa_load_representation(attributes->type, + key_buffer, + key_buffer_size, + &rsa); + if (status != PSA_SUCCESS) { + goto rsa_exit; + } + + if (input_length != mbedtls_rsa_get_len(rsa)) { + status = PSA_ERROR_INVALID_ARGUMENT; + goto rsa_exit; + } +#endif /* defined(MBEDTLS_PSA_BUILTIN_ALG_RSA_PKCS1V15_CRYPT) || + * defined(MBEDTLS_PSA_BUILTIN_ALG_RSA_OAEP) */ + + if (alg == PSA_ALG_RSA_PKCS1V15_CRYPT) { +#if defined(MBEDTLS_PSA_BUILTIN_ALG_RSA_PKCS1V15_CRYPT) + status = mbedtls_to_psa_error( + mbedtls_rsa_pkcs1_decrypt(rsa, + mbedtls_psa_get_random, + MBEDTLS_PSA_RANDOM_STATE, + output_length, + input, + output, + output_size)); +#else + status = PSA_ERROR_NOT_SUPPORTED; +#endif /* MBEDTLS_PSA_BUILTIN_ALG_RSA_PKCS1V15_CRYPT */ + } else + if (PSA_ALG_IS_RSA_OAEP(alg)) { +#if defined(MBEDTLS_PSA_BUILTIN_ALG_RSA_OAEP) + status = mbedtls_to_psa_error( + psa_rsa_oaep_set_padding_mode(alg, rsa)); + if (status != PSA_SUCCESS) { + goto rsa_exit; + } + + status = mbedtls_to_psa_error( + mbedtls_rsa_rsaes_oaep_decrypt(rsa, + mbedtls_psa_get_random, + MBEDTLS_PSA_RANDOM_STATE, + salt, salt_length, + output_length, + input, + output, + output_size)); +#else + status = PSA_ERROR_NOT_SUPPORTED; +#endif /* MBEDTLS_PSA_BUILTIN_ALG_RSA_OAEP */ + } else { + status = PSA_ERROR_INVALID_ARGUMENT; + } + +#if defined(MBEDTLS_PSA_BUILTIN_ALG_RSA_PKCS1V15_CRYPT) || \ + defined(MBEDTLS_PSA_BUILTIN_ALG_RSA_OAEP) +rsa_exit: + mbedtls_rsa_free(rsa); + mbedtls_free(rsa); +#endif /* defined(MBEDTLS_PSA_BUILTIN_ALG_RSA_PKCS1V15_CRYPT) || + * defined(MBEDTLS_PSA_BUILTIN_ALG_RSA_OAEP) */ + } else { + status = PSA_ERROR_NOT_SUPPORTED; + } + + return status; +} + #endif /* MBEDTLS_PSA_CRYPTO_C */ diff --git a/vendor/mbedtls/library/psa_crypto_rsa.h b/vendor/mbedtls/library/psa_crypto_rsa.h index 82ea4746d7..ffeef26be1 100644 --- a/vendor/mbedtls/library/psa_crypto_rsa.h +++ b/vendor/mbedtls/library/psa_crypto_rsa.h @@ -3,19 +3,7 @@ */ /* * Copyright The Mbed TLS Contributors - * SPDX-License-Identifier: Apache-2.0 - * - * Licensed under the Apache License, Version 2.0 (the "License"); you may - * not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT - * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. + * SPDX-License-Identifier: Apache-2.0 OR GPL-2.0-or-later */ #ifndef PSA_CRYPTO_RSA_H @@ -121,6 +109,15 @@ psa_status_t mbedtls_psa_rsa_export_public_key( * entry point. * * \param[in] attributes The attributes for the RSA key to generate. + * \param[in] params Production parameters for the key + * generation. This function only uses + * `params->data`, + * which contains the public exponent. + * This can be a null pointer if + * \c params_data_length is 0. + * \param params_data_length Length of `params->data` in bytes. + * This can be 0, in which case the + * public exponent will be 65537. * \param[out] key_buffer Buffer where the key data is to be written. * \param[in] key_buffer_size Size of \p key_buffer in bytes. * \param[out] key_buffer_length On success, the number of bytes written in @@ -135,6 +132,7 @@ psa_status_t mbedtls_psa_rsa_export_public_key( */ psa_status_t mbedtls_psa_rsa_generate_key( const psa_key_attributes_t *attributes, + const psa_key_production_parameters_t *params, size_t params_data_length, uint8_t *key_buffer, size_t key_buffer_size, size_t *key_buffer_length); /** Sign an already-calculated hash with an RSA private key. @@ -212,4 +210,118 @@ psa_status_t mbedtls_psa_rsa_verify_hash( psa_algorithm_t alg, const uint8_t *hash, size_t hash_length, const uint8_t *signature, size_t signature_length); +/** + * \brief Encrypt a short message with a public key. + * + * \param attributes The attributes for the key to import. + * \param key_buffer Buffer where the key data is to be written. + * \param key_buffer_size Size of the \p key_buffer buffer in bytes. + * \param input_length Size of the \p input buffer in bytes. + * \param[in] salt A salt or label, if supported by the + * encryption algorithm. + * If the algorithm does not support a + * salt, pass \c NULL. + * If the algorithm supports an optional + * salt and you do not want to pass a salt, + * pass \c NULL. + * + * - For #PSA_ALG_RSA_PKCS1V15_CRYPT, no salt is + * supported. + * \param salt_length Size of the \p salt buffer in bytes. + * If \p salt is \c NULL, pass 0. + * \param[out] output Buffer where the encrypted message is to + * be written. + * \param output_size Size of the \p output buffer in bytes. + * \param[out] output_length On success, the number of bytes + * that make up the returned output. + * + * \retval #PSA_SUCCESS \emptydescription + * \retval #PSA_ERROR_BUFFER_TOO_SMALL + * The size of the \p output buffer is too small. You can + * determine a sufficient buffer size by calling + * #PSA_ASYMMETRIC_ENCRYPT_OUTPUT_SIZE(\c key_type, \c key_bits, \p alg) + * where \c key_type and \c key_bits are the type and bit-size + * respectively of \p key. + * \retval #PSA_ERROR_NOT_SUPPORTED \emptydescription + * \retval #PSA_ERROR_INVALID_ARGUMENT \emptydescription + * \retval #PSA_ERROR_INSUFFICIENT_MEMORY \emptydescription + * \retval #PSA_ERROR_COMMUNICATION_FAILURE \emptydescription + * \retval #PSA_ERROR_HARDWARE_FAILURE \emptydescription + * \retval #PSA_ERROR_CORRUPTION_DETECTED \emptydescription + * \retval #PSA_ERROR_INSUFFICIENT_ENTROPY \emptydescription + * \retval #PSA_ERROR_BAD_STATE + * The library has not been previously initialized by psa_crypto_init(). + * It is implementation-dependent whether a failure to initialize + * results in this error code. + */ +psa_status_t mbedtls_psa_asymmetric_encrypt(const psa_key_attributes_t *attributes, + const uint8_t *key_buffer, + size_t key_buffer_size, + psa_algorithm_t alg, + const uint8_t *input, + size_t input_length, + const uint8_t *salt, + size_t salt_length, + uint8_t *output, + size_t output_size, + size_t *output_length); + +/** + * \brief Decrypt a short message with a private key. + * + * \param attributes The attributes for the key to import. + * \param key_buffer Buffer where the key data is to be written. + * \param key_buffer_size Size of the \p key_buffer buffer in bytes. + * \param[in] input The message to decrypt. + * \param input_length Size of the \p input buffer in bytes. + * \param[in] salt A salt or label, if supported by the + * encryption algorithm. + * If the algorithm does not support a + * salt, pass \c NULL. + * If the algorithm supports an optional + * salt and you do not want to pass a salt, + * pass \c NULL. + * + * - For #PSA_ALG_RSA_PKCS1V15_CRYPT, no salt is + * supported. + * \param salt_length Size of the \p salt buffer in bytes. + * If \p salt is \c NULL, pass 0. + * \param[out] output Buffer where the decrypted message is to + * be written. + * \param output_size Size of the \c output buffer in bytes. + * \param[out] output_length On success, the number of bytes + * that make up the returned output. + * + * \retval #PSA_SUCCESS \emptydescription + * \retval #PSA_ERROR_BUFFER_TOO_SMALL + * The size of the \p output buffer is too small. You can + * determine a sufficient buffer size by calling + * #PSA_ASYMMETRIC_DECRYPT_OUTPUT_SIZE(\c key_type, \c key_bits, \p alg) + * where \c key_type and \c key_bits are the type and bit-size + * respectively of \p key. + * \retval #PSA_ERROR_NOT_SUPPORTED \emptydescription + * \retval #PSA_ERROR_INVALID_ARGUMENT \emptydescription + * \retval #PSA_ERROR_INSUFFICIENT_MEMORY \emptydescription + * \retval #PSA_ERROR_COMMUNICATION_FAILURE \emptydescription + * \retval #PSA_ERROR_HARDWARE_FAILURE \emptydescription + * \retval #PSA_ERROR_CORRUPTION_DETECTED \emptydescription + * \retval #PSA_ERROR_INSUFFICIENT_ENTROPY \emptydescription + * \retval #PSA_ERROR_INVALID_PADDING \emptydescription + * \retval #PSA_ERROR_BAD_STATE + * The library has not been previously initialized by psa_crypto_init(). + * It is implementation-dependent whether a failure to initialize + * results in this error code. + */ +psa_status_t mbedtls_psa_asymmetric_decrypt(const psa_key_attributes_t *attributes, + const uint8_t *key_buffer, + size_t key_buffer_size, + psa_algorithm_t alg, + const uint8_t *input, + size_t input_length, + const uint8_t *salt, + size_t salt_length, + uint8_t *output, + size_t output_size, + size_t *output_length); + #endif /* PSA_CRYPTO_RSA_H */ diff --git a/vendor/mbedtls/library/psa_crypto_se.c b/vendor/mbedtls/library/psa_crypto_se.c index 7bea10ad64..7a36a4f3a5 100644 --- a/vendor/mbedtls/library/psa_crypto_se.c +++ b/vendor/mbedtls/library/psa_crypto_se.c @@ -3,19 +3,7 @@ */ /* * Copyright The Mbed TLS Contributors - * SPDX-License-Identifier: Apache-2.0 - * - * Licensed under the Apache License, Version 2.0 (the "License"); you may - * not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT - * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. + * SPDX-License-Identifier: Apache-2.0 OR GPL-2.0-or-later */ #include "common.h" @@ -124,12 +112,10 @@ static psa_status_t psa_get_se_driver_its_file_uid( return PSA_ERROR_NOT_SUPPORTED; } -#if SIZE_MAX > UINT32_MAX /* ITS file sizes are limited to 32 bits. */ if (driver->u.internal.persistent_data_size > UINT32_MAX) { return PSA_ERROR_NOT_SUPPORTED; } -#endif /* See the documentation of PSA_CRYPTO_SE_DRIVER_ITS_UID_BASE. */ *uid = PSA_CRYPTO_SE_DRIVER_ITS_UID_BASE + driver->location; @@ -316,6 +302,7 @@ psa_status_t psa_register_se_driver( * location because it means a transparent key. */ MBEDTLS_STATIC_ASSERT(PSA_KEY_LOCATION_LOCAL_STORAGE == 0, "Secure element support requires 0 to mean a local key"); + if (location == PSA_KEY_LOCATION_LOCAL_STORAGE) { return PSA_ERROR_INVALID_ARGUMENT; } diff --git a/vendor/mbedtls/library/psa_crypto_se.h b/vendor/mbedtls/library/psa_crypto_se.h index 373852dfcc..e0bd5acfb3 100644 --- a/vendor/mbedtls/library/psa_crypto_se.h +++ b/vendor/mbedtls/library/psa_crypto_se.h @@ -3,29 +3,20 @@ */ /* * Copyright The Mbed TLS Contributors - * SPDX-License-Identifier: Apache-2.0 - * - * Licensed under the Apache License, Version 2.0 (the "License"); you may - * not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT - * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. + * SPDX-License-Identifier: Apache-2.0 OR GPL-2.0-or-later */ #ifndef PSA_CRYPTO_SE_H #define PSA_CRYPTO_SE_H -#if !defined(MBEDTLS_CONFIG_FILE) -#include "mbedtls/config.h" -#else -#include MBEDTLS_CONFIG_FILE -#endif +/* + * Include the build-time configuration information header. Here, we do not + * include `"mbedtls/build_info.h"` directly but `"psa/build_info.h"`, which + * is basically just an alias to it. This is to ease the maintenance of the + * TF-PSA-Crypto repository which has a different build system and + * configuration. + */ +#include "psa/build_info.h" #include "psa/crypto.h" #include "psa/crypto_se_driver.h" diff --git a/vendor/mbedtls/library/psa_crypto_slot_management.c b/vendor/mbedtls/library/psa_crypto_slot_management.c index 2d27902085..b184ed08c9 100644 --- a/vendor/mbedtls/library/psa_crypto_slot_management.c +++ b/vendor/mbedtls/library/psa_crypto_slot_management.c @@ -3,19 +3,7 @@ */ /* * Copyright The Mbed TLS Contributors - * SPDX-License-Identifier: Apache-2.0 - * - * Licensed under the Apache License, Version 2.0 (the "License"); you may - * not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT - * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. + * SPDX-License-Identifier: Apache-2.0 OR GPL-2.0-or-later */ #include "common.h" @@ -25,7 +13,7 @@ #include "psa/crypto.h" #include "psa_crypto_core.h" -#include "psa_crypto_driver_wrappers.h" +#include "psa_crypto_driver_wrappers_no_static.h" #include "psa_crypto_slot_management.h" #include "psa_crypto_storage.h" #if defined(MBEDTLS_PSA_CRYPTO_SE_C) @@ -35,16 +23,34 @@ #include #include #include "mbedtls/platform.h" - -#define ARRAY_LENGTH(array) (sizeof(array) / sizeof(*(array))) +#if defined(MBEDTLS_THREADING_C) +#include "mbedtls/threading.h" +#endif typedef struct { psa_key_slot_t key_slots[MBEDTLS_PSA_KEY_SLOT_COUNT]; - unsigned key_slots_initialized : 1; + uint8_t key_slots_initialized; } psa_global_data_t; static psa_global_data_t global_data; +static uint8_t psa_get_key_slots_initialized(void) +{ + uint8_t initialized; + +#if defined(MBEDTLS_THREADING_C) + mbedtls_mutex_lock(&mbedtls_threading_psa_globaldata_mutex); +#endif /* defined(MBEDTLS_THREADING_C) */ + + initialized = global_data.key_slots_initialized; + +#if defined(MBEDTLS_THREADING_C) + mbedtls_mutex_unlock(&mbedtls_threading_psa_globaldata_mutex); +#endif /* defined(MBEDTLS_THREADING_C) */ + + return initialized; +} + int psa_is_valid_key_id(mbedtls_svc_key_id_t key, int vendor_ok) { psa_key_id_t key_id = MBEDTLS_SVC_KEY_ID_GET_KEY_ID(key); @@ -81,6 +87,9 @@ int psa_is_valid_key_id(mbedtls_svc_key_id_t key, int vendor_ok) * On success, the function locks the key slot. It is the responsibility of * the caller to unlock the key slot when it does not access it anymore. * + * If multi-threading is enabled, the caller must hold the + * global key slot mutex. + * * \param key Key identifier to query. * \param[out] p_slot On success, `*p_slot` contains a pointer to the * key slot containing the description of the key @@ -105,16 +114,14 @@ static psa_status_t psa_get_and_lock_key_slot_in_memory( if (psa_key_id_is_volatile(key_id)) { slot = &global_data.key_slots[key_id - PSA_KEY_ID_VOLATILE_MIN]; - /* - * Check if both the PSA key identifier key_id and the owner - * identifier of key match those of the key slot. - * - * Note that, if the key slot is not occupied, its PSA key identifier - * is equal to zero. This is an invalid value for a PSA key identifier - * and thus cannot be equal to the valid PSA key identifier key_id. - */ - status = mbedtls_svc_key_id_equal(key, slot->attr.id) ? - PSA_SUCCESS : PSA_ERROR_DOES_NOT_EXIST; + /* Check if both the PSA key identifier key_id and the owner + * identifier of key match those of the key slot. */ + if ((slot->state == PSA_SLOT_FULL) && + (mbedtls_svc_key_id_equal(key, slot->attr.id))) { + status = PSA_SUCCESS; + } else { + status = PSA_ERROR_DOES_NOT_EXIST; + } } else { if (!psa_is_valid_key_id(key, 1)) { return PSA_ERROR_INVALID_HANDLE; @@ -122,7 +129,9 @@ static psa_status_t psa_get_and_lock_key_slot_in_memory( for (slot_idx = 0; slot_idx < MBEDTLS_PSA_KEY_SLOT_COUNT; slot_idx++) { slot = &global_data.key_slots[slot_idx]; - if (mbedtls_svc_key_id_equal(key, slot->attr.id)) { + /* Only consider slots which are in a full state. */ + if ((slot->state == PSA_SLOT_FULL) && + (mbedtls_svc_key_id_equal(key, slot->attr.id))) { break; } } @@ -131,7 +140,7 @@ static psa_status_t psa_get_and_lock_key_slot_in_memory( } if (status == PSA_SUCCESS) { - status = psa_lock_key_slot(slot); + status = psa_register_read(slot); if (status == PSA_SUCCESS) { *p_slot = slot; } @@ -144,7 +153,9 @@ psa_status_t psa_initialize_key_slots(void) { /* Nothing to do: program startup and psa_wipe_all_key_slots() both * guarantee that the key slots are initialized to all-zero, which - * means that all the key slots are in a valid, empty state. */ + * means that all the key slots are in a valid, empty state. The global + * data mutex is already held when calling this function, so no need to + * lock it here, to set the flag. */ global_data.key_slots_initialized = 1; return PSA_SUCCESS; } @@ -155,36 +166,39 @@ void psa_wipe_all_key_slots(void) for (slot_idx = 0; slot_idx < MBEDTLS_PSA_KEY_SLOT_COUNT; slot_idx++) { psa_key_slot_t *slot = &global_data.key_slots[slot_idx]; - slot->lock_count = 1; + slot->registered_readers = 1; + slot->state = PSA_SLOT_PENDING_DELETION; (void) psa_wipe_key_slot(slot); } + /* The global data mutex is already held when calling this function. */ global_data.key_slots_initialized = 0; } -psa_status_t psa_get_empty_key_slot(psa_key_id_t *volatile_key_id, - psa_key_slot_t **p_slot) +psa_status_t psa_reserve_free_key_slot(psa_key_id_t *volatile_key_id, + psa_key_slot_t **p_slot) { psa_status_t status = PSA_ERROR_CORRUPTION_DETECTED; size_t slot_idx; - psa_key_slot_t *selected_slot, *unlocked_persistent_key_slot; + psa_key_slot_t *selected_slot, *unused_persistent_key_slot; - if (!global_data.key_slots_initialized) { + if (!psa_get_key_slots_initialized()) { status = PSA_ERROR_BAD_STATE; goto error; } - selected_slot = unlocked_persistent_key_slot = NULL; + selected_slot = unused_persistent_key_slot = NULL; for (slot_idx = 0; slot_idx < MBEDTLS_PSA_KEY_SLOT_COUNT; slot_idx++) { psa_key_slot_t *slot = &global_data.key_slots[slot_idx]; - if (!psa_is_key_slot_occupied(slot)) { + if (slot->state == PSA_SLOT_EMPTY) { selected_slot = slot; break; } - if ((unlocked_persistent_key_slot == NULL) && - (!PSA_KEY_LIFETIME_IS_VOLATILE(slot->attr.lifetime)) && - (!psa_is_key_slot_locked(slot))) { - unlocked_persistent_key_slot = slot; + if ((unused_persistent_key_slot == NULL) && + (slot->state == PSA_SLOT_FULL) && + (!psa_key_slot_has_readers(slot)) && + (!PSA_KEY_LIFETIME_IS_VOLATILE(slot->attr.lifetime))) { + unused_persistent_key_slot = slot; } } @@ -196,14 +210,18 @@ psa_status_t psa_get_empty_key_slot(psa_key_id_t *volatile_key_id, * storage. */ if ((selected_slot == NULL) && - (unlocked_persistent_key_slot != NULL)) { - selected_slot = unlocked_persistent_key_slot; - selected_slot->lock_count = 1; - psa_wipe_key_slot(selected_slot); + (unused_persistent_key_slot != NULL)) { + selected_slot = unused_persistent_key_slot; + psa_register_read(selected_slot); + status = psa_wipe_key_slot(selected_slot); + if (status != PSA_SUCCESS) { + goto error; + } } if (selected_slot != NULL) { - status = psa_lock_key_slot(selected_slot); + status = psa_key_slot_state_transition(selected_slot, PSA_SLOT_EMPTY, + PSA_SLOT_FILLING); if (status != PSA_SUCCESS) { goto error; } @@ -256,6 +274,9 @@ static psa_status_t psa_load_persistent_key_into_slot(psa_key_slot_t *slot) #endif /* MBEDTLS_PSA_CRYPTO_SE_C */ status = psa_copy_key_material_into_slot(slot, key_data, key_data_length); + if (status != PSA_SUCCESS) { + goto exit; + } exit: psa_free_persistent_key_data(key_data, key_data_length); @@ -328,8 +349,7 @@ static psa_status_t psa_load_builtin_key_into_slot(psa_key_slot_t *slot) /* Copy actual key length and core attributes into the slot on success */ slot->key.bytes = key_buffer_length; - slot->attr = attributes.core; - + slot->attr = attributes; exit: if (status != PSA_SUCCESS) { psa_remove_key_data_from_memory(slot); @@ -344,16 +364,31 @@ psa_status_t psa_get_and_lock_key_slot(mbedtls_svc_key_id_t key, psa_status_t status = PSA_ERROR_CORRUPTION_DETECTED; *p_slot = NULL; - if (!global_data.key_slots_initialized) { + if (!psa_get_key_slots_initialized()) { return PSA_ERROR_BAD_STATE; } +#if defined(MBEDTLS_THREADING_C) + /* We need to set status as success, otherwise CORRUPTION_DETECTED + * would be returned if the lock fails. */ + status = PSA_SUCCESS; + /* If the key is persistent and not loaded, we cannot unlock the mutex + * between checking if the key is loaded and setting the slot as FULL, + * as otherwise another thread may load and then destroy the key + * in the meantime. */ + PSA_THREADING_CHK_RET(mbedtls_mutex_lock( + &mbedtls_threading_key_slot_mutex)); +#endif /* * On success, the pointer to the slot is passed directly to the caller * thus no need to unlock the key slot here. */ status = psa_get_and_lock_key_slot_in_memory(key, p_slot); if (status != PSA_ERROR_DOES_NOT_EXIST) { +#if defined(MBEDTLS_THREADING_C) + PSA_THREADING_CHK_RET(mbedtls_mutex_unlock( + &mbedtls_threading_key_slot_mutex)); +#endif return status; } @@ -362,8 +397,12 @@ psa_status_t psa_get_and_lock_key_slot(mbedtls_svc_key_id_t key, defined(MBEDTLS_PSA_CRYPTO_BUILTIN_KEYS) psa_key_id_t volatile_key_id; - status = psa_get_empty_key_slot(&volatile_key_id, p_slot); + status = psa_reserve_free_key_slot(&volatile_key_id, p_slot); if (status != PSA_SUCCESS) { +#if defined(MBEDTLS_THREADING_C) + PSA_THREADING_CHK_RET(mbedtls_mutex_unlock( + &mbedtls_threading_key_slot_mutex)); +#endif return status; } @@ -384,45 +423,82 @@ psa_status_t psa_get_and_lock_key_slot(mbedtls_svc_key_id_t key, if (status != PSA_SUCCESS) { psa_wipe_key_slot(*p_slot); + if (status == PSA_ERROR_DOES_NOT_EXIST) { status = PSA_ERROR_INVALID_HANDLE; } } else { /* Add implicit usage flags. */ psa_extend_key_usage_flags(&(*p_slot)->attr.policy.usage); + + psa_key_slot_state_transition((*p_slot), PSA_SLOT_FILLING, + PSA_SLOT_FULL); + status = psa_register_read(*p_slot); } - return status; #else /* MBEDTLS_PSA_CRYPTO_STORAGE_C || MBEDTLS_PSA_CRYPTO_BUILTIN_KEYS */ - return PSA_ERROR_INVALID_HANDLE; + status = PSA_ERROR_INVALID_HANDLE; #endif /* MBEDTLS_PSA_CRYPTO_STORAGE_C || MBEDTLS_PSA_CRYPTO_BUILTIN_KEYS */ + +#if defined(MBEDTLS_THREADING_C) + PSA_THREADING_CHK_RET(mbedtls_mutex_unlock( + &mbedtls_threading_key_slot_mutex)); +#endif + return status; } -psa_status_t psa_unlock_key_slot(psa_key_slot_t *slot) +psa_status_t psa_unregister_read(psa_key_slot_t *slot) { if (slot == NULL) { return PSA_SUCCESS; } + if ((slot->state != PSA_SLOT_FULL) && + (slot->state != PSA_SLOT_PENDING_DELETION)) { + return PSA_ERROR_CORRUPTION_DETECTED; + } + + /* If we are the last reader and the slot is marked for deletion, + * we must wipe the slot here. */ + if ((slot->state == PSA_SLOT_PENDING_DELETION) && + (slot->registered_readers == 1)) { + return psa_wipe_key_slot(slot); + } - if (slot->lock_count > 0) { - slot->lock_count--; + if (psa_key_slot_has_readers(slot)) { + slot->registered_readers--; return PSA_SUCCESS; } /* * As the return error code may not be handled in case of multiple errors, - * do our best to report if the lock counter is equal to zero: if - * available call MBEDTLS_PARAM_FAILED that may terminate execution (if - * called as part of the execution of a unit test suite this will stop the - * test suite execution). + * do our best to report if there are no registered readers. Assert with + * MBEDTLS_TEST_HOOK_TEST_ASSERT that there are registered readers: + * if the MBEDTLS_TEST_HOOKS configuration option is enabled and + * the function is called as part of the execution of a test suite, the + * execution of the test suite is stopped in error if the assertion fails. */ -#ifdef MBEDTLS_CHECK_PARAMS - MBEDTLS_PARAM_FAILED(slot->lock_count > 0); -#endif - + MBEDTLS_TEST_HOOK_TEST_ASSERT(psa_key_slot_has_readers(slot)); return PSA_ERROR_CORRUPTION_DETECTED; } +psa_status_t psa_unregister_read_under_mutex(psa_key_slot_t *slot) +{ + psa_status_t status = PSA_ERROR_CORRUPTION_DETECTED; +#if defined(MBEDTLS_THREADING_C) + /* We need to set status as success, otherwise CORRUPTION_DETECTED + * would be returned if the lock fails. */ + status = PSA_SUCCESS; + PSA_THREADING_CHK_RET(mbedtls_mutex_lock( + &mbedtls_threading_key_slot_mutex)); +#endif + status = psa_unregister_read(slot); +#if defined(MBEDTLS_THREADING_C) + PSA_THREADING_CHK_RET(mbedtls_mutex_unlock( + &mbedtls_threading_key_slot_mutex)); +#endif + return status; +} + psa_status_t psa_validate_key_location(psa_key_lifetime_t lifetime, psa_se_drv_table_entry_t **p_drv) { @@ -440,14 +516,8 @@ psa_status_t psa_validate_key_location(psa_key_lifetime_t lifetime, (void) p_drv; #endif /* MBEDTLS_PSA_CRYPTO_SE_C */ -#if defined(MBEDTLS_PSA_CRYPTO_DRIVERS) /* Key location for external keys gets checked by the wrapper */ return PSA_SUCCESS; -#else /* MBEDTLS_PSA_CRYPTO_DRIVERS */ - /* No support for external lifetimes at all, or dynamic interface - * did not find driver for requested lifetime. */ - return PSA_ERROR_INVALID_ARGUMENT; -#endif /* MBEDTLS_PSA_CRYPTO_DRIVERS */ } else { /* Local/internal keys are always valid */ return PSA_SUCCESS; @@ -492,7 +562,7 @@ psa_status_t psa_open_key(mbedtls_svc_key_id_t key, psa_key_handle_t *handle) *handle = key; - return psa_unlock_key_slot(slot); + return psa_unregister_read_under_mutex(slot); #else /* MBEDTLS_PSA_CRYPTO_STORAGE_C || MBEDTLS_PSA_CRYPTO_BUILTIN_KEYS */ (void) key; @@ -503,44 +573,78 @@ psa_status_t psa_open_key(mbedtls_svc_key_id_t key, psa_key_handle_t *handle) psa_status_t psa_close_key(psa_key_handle_t handle) { - psa_status_t status; + psa_status_t status = PSA_ERROR_CORRUPTION_DETECTED; psa_key_slot_t *slot; if (psa_key_handle_is_null(handle)) { return PSA_SUCCESS; } +#if defined(MBEDTLS_THREADING_C) + /* We need to set status as success, otherwise CORRUPTION_DETECTED + * would be returned if the lock fails. */ + status = PSA_SUCCESS; + PSA_THREADING_CHK_RET(mbedtls_mutex_lock( + &mbedtls_threading_key_slot_mutex)); +#endif status = psa_get_and_lock_key_slot_in_memory(handle, &slot); if (status != PSA_SUCCESS) { if (status == PSA_ERROR_DOES_NOT_EXIST) { status = PSA_ERROR_INVALID_HANDLE; } - +#if defined(MBEDTLS_THREADING_C) + PSA_THREADING_CHK_RET(mbedtls_mutex_unlock( + &mbedtls_threading_key_slot_mutex)); +#endif return status; } - if (slot->lock_count <= 1) { - return psa_wipe_key_slot(slot); + + if (slot->registered_readers == 1) { + status = psa_wipe_key_slot(slot); } else { - return psa_unlock_key_slot(slot); + status = psa_unregister_read(slot); } +#if defined(MBEDTLS_THREADING_C) + PSA_THREADING_CHK_RET(mbedtls_mutex_unlock( + &mbedtls_threading_key_slot_mutex)); +#endif + + return status; } psa_status_t psa_purge_key(mbedtls_svc_key_id_t key) { - psa_status_t status; + psa_status_t status = PSA_ERROR_CORRUPTION_DETECTED; psa_key_slot_t *slot; +#if defined(MBEDTLS_THREADING_C) + /* We need to set status as success, otherwise CORRUPTION_DETECTED + * would be returned if the lock fails. */ + status = PSA_SUCCESS; + PSA_THREADING_CHK_RET(mbedtls_mutex_lock( + &mbedtls_threading_key_slot_mutex)); +#endif status = psa_get_and_lock_key_slot_in_memory(key, &slot); if (status != PSA_SUCCESS) { +#if defined(MBEDTLS_THREADING_C) + PSA_THREADING_CHK_RET(mbedtls_mutex_unlock( + &mbedtls_threading_key_slot_mutex)); +#endif return status; } if ((!PSA_KEY_LIFETIME_IS_VOLATILE(slot->attr.lifetime)) && - (slot->lock_count <= 1)) { - return psa_wipe_key_slot(slot); + (slot->registered_readers == 1)) { + status = psa_wipe_key_slot(slot); } else { - return psa_unlock_key_slot(slot); + status = psa_unregister_read(slot); } +#if defined(MBEDTLS_THREADING_C) + PSA_THREADING_CHK_RET(mbedtls_mutex_unlock( + &mbedtls_threading_key_slot_mutex)); +#endif + + return status; } void mbedtls_psa_get_stats(mbedtls_psa_stats_t *stats) @@ -551,10 +655,10 @@ void mbedtls_psa_get_stats(mbedtls_psa_stats_t *stats) for (slot_idx = 0; slot_idx < MBEDTLS_PSA_KEY_SLOT_COUNT; slot_idx++) { const psa_key_slot_t *slot = &global_data.key_slots[slot_idx]; - if (psa_is_key_slot_locked(slot)) { + if (psa_key_slot_has_readers(slot)) { ++stats->locked_slots; } - if (!psa_is_key_slot_occupied(slot)) { + if (slot->state == PSA_SLOT_EMPTY) { ++stats->empty_slots; continue; } diff --git a/vendor/mbedtls/library/psa_crypto_slot_management.h b/vendor/mbedtls/library/psa_crypto_slot_management.h index c8366abeb8..bcfc9d8adc 100644 --- a/vendor/mbedtls/library/psa_crypto_slot_management.h +++ b/vendor/mbedtls/library/psa_crypto_slot_management.h @@ -3,19 +3,7 @@ */ /* * Copyright The Mbed TLS Contributors - * SPDX-License-Identifier: Apache-2.0 - * - * Licensed under the Apache License, Version 2.0 (the "License"); you may - * not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT - * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. + * SPDX-License-Identifier: Apache-2.0 OR GPL-2.0-or-later */ #ifndef PSA_CRYPTO_SLOT_MANAGEMENT_H @@ -66,8 +54,9 @@ static inline int psa_key_id_is_volatile(psa_key_id_t key_id) * In case of a persistent key, the function loads the description of the key * into a key slot if not already done. * - * On success, the returned key slot is locked. It is the responsibility of - * the caller to unlock the key slot when it does not access it anymore. + * On success, the returned key slot has been registered for reading. + * It is the responsibility of the caller to call psa_unregister_read(slot) + * when they have finished reading the contents of the slot. * * \param key Key identifier to query. * \param[out] p_slot On success, `*p_slot` contains a pointer to the @@ -103,54 +92,101 @@ psa_status_t psa_get_and_lock_key_slot(mbedtls_svc_key_id_t key, psa_status_t psa_initialize_key_slots(void); /** Delete all data from key slots in memory. + * This function is not thread safe, it wipes every key slot regardless of + * state and reader count. It should only be called when no slot is in use. * * This does not affect persistent storage. */ void psa_wipe_all_key_slots(void); -/** Find a free key slot. +/** Find a free key slot and reserve it to be filled with a key. + * + * This function finds a key slot that is free, + * sets its state to PSA_SLOT_FILLING and then returns the slot. * - * This function returns a key slot that is available for use and is in its - * ground state (all-bits-zero). On success, the key slot is locked. It is - * the responsibility of the caller to unlock the key slot when it does not - * access it anymore. + * On success, the key slot's state is PSA_SLOT_FILLING. + * It is the responsibility of the caller to change the slot's state to + * PSA_SLOT_EMPTY/FULL once key creation has finished. + * + * If multi-threading is enabled, the caller must hold the + * global key slot mutex. * * \param[out] volatile_key_id On success, volatile key identifier * associated to the returned slot. * \param[out] p_slot On success, a pointer to the slot. * * \retval #PSA_SUCCESS \emptydescription - * \retval #PSA_ERROR_INSUFFICIENT_MEMORY \emptydescription + * \retval #PSA_ERROR_INSUFFICIENT_MEMORY + * There were no free key slots. * \retval #PSA_ERROR_BAD_STATE \emptydescription + * \retval #PSA_ERROR_CORRUPTION_DETECTED + * This function attempted to operate on a key slot which was in an + * unexpected state. */ -psa_status_t psa_get_empty_key_slot(psa_key_id_t *volatile_key_id, - psa_key_slot_t **p_slot); +psa_status_t psa_reserve_free_key_slot(psa_key_id_t *volatile_key_id, + psa_key_slot_t **p_slot); -/** Lock a key slot. +/** Change the state of a key slot. * - * This function increments the key slot lock counter by one. + * This function changes the state of the key slot from expected_state to + * new state. If the state of the slot was not expected_state, the state is + * unchanged. * - * \param[in] slot The key slot. + * If multi-threading is enabled, the caller must hold the + * global key slot mutex. + * + * \param[in] slot The key slot. + * \param[in] expected_state The current state of the slot. + * \param[in] new_state The new state of the slot. * * \retval #PSA_SUCCESS - The key slot lock counter was incremented. + The key slot's state variable is new_state. * \retval #PSA_ERROR_CORRUPTION_DETECTED - * The lock counter already reached its maximum value and was not - * increased. + * The slot's state was not expected_state. */ -static inline psa_status_t psa_lock_key_slot(psa_key_slot_t *slot) +static inline psa_status_t psa_key_slot_state_transition( + psa_key_slot_t *slot, psa_key_slot_state_t expected_state, + psa_key_slot_state_t new_state) { - if (slot->lock_count >= SIZE_MAX) { + if (slot->state != expected_state) { return PSA_ERROR_CORRUPTION_DETECTED; } + slot->state = new_state; + return PSA_SUCCESS; +} - slot->lock_count++; +/** Register as a reader of a key slot. + * + * This function increments the key slot registered reader counter by one. + * If multi-threading is enabled, the caller must hold the + * global key slot mutex. + * + * \param[in] slot The key slot. + * + * \retval #PSA_SUCCESS + The key slot registered reader counter was incremented. + * \retval #PSA_ERROR_CORRUPTION_DETECTED + * The reader counter already reached its maximum value and was not + * increased, or the slot's state was not PSA_SLOT_FULL. + */ +static inline psa_status_t psa_register_read(psa_key_slot_t *slot) +{ + if ((slot->state != PSA_SLOT_FULL) || + (slot->registered_readers >= SIZE_MAX)) { + return PSA_ERROR_CORRUPTION_DETECTED; + } + slot->registered_readers++; return PSA_SUCCESS; } -/** Unlock a key slot. +/** Unregister from reading a key slot. * - * This function decrements the key slot lock counter by one. + * This function decrements the key slot registered reader counter by one. + * If the state of the slot is PSA_SLOT_PENDING_DELETION, + * and there is only one registered reader (the caller), + * this function will call psa_wipe_key_slot(). + * If multi-threading is enabled, the caller must hold the + * global key slot mutex. * * \note To ease the handling of errors in retrieving a key slot * a NULL input pointer is valid, and the function returns @@ -158,13 +194,37 @@ static inline psa_status_t psa_lock_key_slot(psa_key_slot_t *slot) * * \param[in] slot The key slot. * \retval #PSA_SUCCESS - * \p slot is NULL or the key slot lock counter has been - * decremented successfully. + * \p slot is NULL or the key slot reader counter has been + * decremented (and potentially wiped) successfully. * \retval #PSA_ERROR_CORRUPTION_DETECTED - * The lock counter was equal to 0. + * The slot's state was neither PSA_SLOT_FULL nor + * PSA_SLOT_PENDING_DELETION. + * Or a wipe was attempted and the slot's state was not + * PSA_SLOT_PENDING_DELETION. + * Or registered_readers was equal to 0. + */ +psa_status_t psa_unregister_read(psa_key_slot_t *slot); + +/** Wrap a call to psa_unregister_read in the global key slot mutex. * + * If threading is disabled, this simply calls psa_unregister_read. + * + * \note To ease the handling of errors in retrieving a key slot + * a NULL input pointer is valid, and the function returns + * successfully without doing anything in that case. + * + * \param[in] slot The key slot. + * \retval #PSA_SUCCESS + * \p slot is NULL or the key slot reader counter has been + * decremented (and potentially wiped) successfully. + * \retval #PSA_ERROR_CORRUPTION_DETECTED + * The slot's state was neither PSA_SLOT_FULL nor + * PSA_SLOT_PENDING_DELETION. + * Or a wipe was attempted and the slot's state was not + * PSA_SLOT_PENDING_DELETION. + * Or registered_readers was equal to 0. */ -psa_status_t psa_unlock_key_slot(psa_key_slot_t *slot); +psa_status_t psa_unregister_read_under_mutex(psa_key_slot_t *slot); /** Test whether a lifetime designates a key in an external cryptoprocessor. * diff --git a/vendor/mbedtls/library/psa_crypto_storage.c b/vendor/mbedtls/library/psa_crypto_storage.c index 688940b5f4..7d1317b45a 100644 --- a/vendor/mbedtls/library/psa_crypto_storage.c +++ b/vendor/mbedtls/library/psa_crypto_storage.c @@ -3,19 +3,7 @@ */ /* * Copyright The Mbed TLS Contributors - * SPDX-License-Identifier: Apache-2.0 - * - * Licensed under the Apache License, Version 2.0 (the "License"); you may - * not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT - * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. + * SPDX-License-Identifier: Apache-2.0 OR GPL-2.0-or-later */ #include "common.h" @@ -38,6 +26,8 @@ #include "mbedtls/platform.h" + + /****************************************************************/ /* Key storage */ /****************************************************************/ @@ -245,7 +235,7 @@ typedef struct { void psa_format_key_data_for_storage(const uint8_t *data, const size_t data_length, - const psa_core_key_attributes_t *attr, + const psa_key_attributes_t *attr, uint8_t *storage_data) { psa_persistent_key_storage_format *storage_format = @@ -277,7 +267,7 @@ psa_status_t psa_parse_key_data_from_storage(const uint8_t *storage_data, size_t storage_data_length, uint8_t **key_data, size_t *key_data_length, - psa_core_key_attributes_t *attr) + psa_key_attributes_t *attr) { psa_status_t status; const psa_persistent_key_storage_format *storage_format = @@ -324,7 +314,7 @@ psa_status_t psa_parse_key_data_from_storage(const uint8_t *storage_data, return PSA_SUCCESS; } -psa_status_t psa_save_persistent_key(const psa_core_key_attributes_t *attr, +psa_status_t psa_save_persistent_key(const psa_key_attributes_t *attr, const uint8_t *data, const size_t data_length) { @@ -352,21 +342,17 @@ psa_status_t psa_save_persistent_key(const psa_core_key_attributes_t *attr, status = psa_crypto_storage_store(attr->id, storage_data, storage_data_length); - mbedtls_platform_zeroize(storage_data, storage_data_length); - mbedtls_free(storage_data); + mbedtls_zeroize_and_free(storage_data, storage_data_length); return status; } void psa_free_persistent_key_data(uint8_t *key_data, size_t key_data_length) { - if (key_data != NULL) { - mbedtls_platform_zeroize(key_data, key_data_length); - } - mbedtls_free(key_data); + mbedtls_zeroize_and_free(key_data, key_data_length); } -psa_status_t psa_load_persistent_key(psa_core_key_attributes_t *attr, +psa_status_t psa_load_persistent_key(psa_key_attributes_t *attr, uint8_t **data, size_t *data_length) { @@ -401,8 +387,7 @@ psa_status_t psa_load_persistent_key(psa_core_key_attributes_t *attr, } exit: - mbedtls_platform_zeroize(loaded_data, storage_data_length); - mbedtls_free(loaded_data); + mbedtls_zeroize_and_free(loaded_data, storage_data_length); return status; } diff --git a/vendor/mbedtls/library/psa_crypto_storage.h b/vendor/mbedtls/library/psa_crypto_storage.h index 37ca46e283..d7f5b18953 100644 --- a/vendor/mbedtls/library/psa_crypto_storage.h +++ b/vendor/mbedtls/library/psa_crypto_storage.h @@ -5,19 +5,7 @@ */ /* * Copyright The Mbed TLS Contributors - * SPDX-License-Identifier: Apache-2.0 - * - * Licensed under the Apache License, Version 2.0 (the "License"); you may - * not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT - * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. + * SPDX-License-Identifier: Apache-2.0 OR GPL-2.0-or-later */ #ifndef PSA_CRYPTO_STORAGE_H @@ -105,7 +93,7 @@ int psa_is_key_present_in_storage(const mbedtls_svc_key_id_t key); * \retval #PSA_ERROR_DATA_INVALID \emptydescription * \retval #PSA_ERROR_DATA_CORRUPT \emptydescription */ -psa_status_t psa_save_persistent_key(const psa_core_key_attributes_t *attr, +psa_status_t psa_save_persistent_key(const psa_key_attributes_t *attr, const uint8_t *data, const size_t data_length); @@ -135,7 +123,7 @@ psa_status_t psa_save_persistent_key(const psa_core_key_attributes_t *attr, * \retval #PSA_ERROR_DATA_CORRUPT \emptydescription * \retval #PSA_ERROR_DOES_NOT_EXIST \emptydescription */ -psa_status_t psa_load_persistent_key(psa_core_key_attributes_t *attr, +psa_status_t psa_load_persistent_key(psa_key_attributes_t *attr, uint8_t **data, size_t *data_length); @@ -175,7 +163,7 @@ void psa_free_persistent_key_data(uint8_t *key_data, size_t key_data_length); */ void psa_format_key_data_for_storage(const uint8_t *data, const size_t data_length, - const psa_core_key_attributes_t *attr, + const psa_key_attributes_t *attr, uint8_t *storage_data); /** @@ -198,7 +186,7 @@ psa_status_t psa_parse_key_data_from_storage(const uint8_t *storage_data, size_t storage_data_length, uint8_t **key_data, size_t *key_data_length, - psa_core_key_attributes_t *attr); + psa_key_attributes_t *attr); #if defined(MBEDTLS_PSA_CRYPTO_SE_C) /** This symbol is defined if transaction support is required. */ @@ -243,8 +231,9 @@ typedef uint16_t psa_crypto_transaction_type_t; * This type is designed to be serialized by writing the memory representation * and reading it back on the same device. * - * \note The transaction mechanism is designed for a single active transaction - * at a time. The transaction object is #psa_crypto_transaction. + * \note The transaction mechanism is not thread-safe. There can only be one + * single active transaction at a time. + * The transaction object is #psa_crypto_transaction. * * \note If an API call starts a transaction, it must complete this transaction * before returning to the application. diff --git a/vendor/mbedtls/library/psa_its_file.c b/vendor/mbedtls/library/psa_its_file.c index be3c2d58a3..9567137483 100644 --- a/vendor/mbedtls/library/psa_its_file.c +++ b/vendor/mbedtls/library/psa_its_file.c @@ -3,19 +3,7 @@ */ /* * Copyright The Mbed TLS Contributors - * SPDX-License-Identifier: Apache-2.0 - * - * Licensed under the Apache License, Version 2.0 (the "License"); you may - * not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT - * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. + * SPDX-License-Identifier: Apache-2.0 OR GPL-2.0-or-later */ #include "common.h" @@ -98,6 +86,9 @@ static psa_status_t psa_its_read_file(psa_storage_uid_t uid, return PSA_ERROR_DOES_NOT_EXIST; } + /* Ensure no stdio buffering of secrets, as such buffers cannot be wiped. */ + mbedtls_setbuf(*p_stream, NULL); + n = fread(&header, 1, sizeof(header), *p_stream); if (n != sizeof(header)) { return PSA_ERROR_DATA_CORRUPT; @@ -107,14 +98,9 @@ static psa_status_t psa_its_read_file(psa_storage_uid_t uid, return PSA_ERROR_DATA_CORRUPT; } - p_info->size = (header.size[0] | - header.size[1] << 8 | - header.size[2] << 16 | - header.size[3] << 24); - p_info->flags = (header.flags[0] | - header.flags[1] << 8 | - header.flags[2] << 16 | - header.flags[3] << 24); + p_info->size = MBEDTLS_GET_UINT32_LE(header.size, 0); + p_info->flags = MBEDTLS_GET_UINT32_LE(header.flags, 0); + return PSA_SUCCESS; } @@ -207,10 +193,14 @@ psa_status_t psa_its_set(psa_storage_uid_t uid, psa_its_fill_filename(uid, filename); stream = fopen(PSA_ITS_STORAGE_TEMP, "wb"); + if (stream == NULL) { goto exit; } + /* Ensure no stdio buffering of secrets, as such buffers cannot be wiped. */ + mbedtls_setbuf(stream, NULL); + status = PSA_ERROR_INSUFFICIENT_STORAGE; n = fwrite(&header, 1, sizeof(header), stream); if (n != sizeof(header)) { diff --git a/vendor/mbedtls/library/psa_util.c b/vendor/mbedtls/library/psa_util.c new file mode 100644 index 0000000000..4ccc5b05d8 --- /dev/null +++ b/vendor/mbedtls/library/psa_util.c @@ -0,0 +1,602 @@ +/* + * PSA hashing layer on top of Mbed TLS software crypto + */ +/* + * Copyright The Mbed TLS Contributors + * SPDX-License-Identifier: Apache-2.0 OR GPL-2.0-or-later + */ + +#include "common.h" + +/* This is needed for MBEDTLS_ERR_XXX macros */ +#include + +#if defined(MBEDTLS_ASN1_WRITE_C) +#include +#include +#endif + +#include "psa_util_internal.h" + +#if defined(MBEDTLS_PSA_CRYPTO_CLIENT) + +#include + +#if defined(MBEDTLS_MD_LIGHT) +#include +#endif +#if defined(MBEDTLS_LMS_C) +#include +#endif +#if defined(MBEDTLS_SSL_TLS_C) && \ + (defined(MBEDTLS_USE_PSA_CRYPTO) || defined(MBEDTLS_SSL_PROTO_TLS1_3)) +#include +#endif +#if defined(PSA_WANT_KEY_TYPE_RSA_PUBLIC_KEY) || \ + defined(PSA_WANT_KEY_TYPE_RSA_KEY_PAIR_BASIC) +#include +#endif +#if defined(MBEDTLS_USE_PSA_CRYPTO) && \ + defined(PSA_WANT_KEY_TYPE_ECC_PUBLIC_KEY) +#include +#endif +#if defined(MBEDTLS_PK_C) +#include +#endif +#if defined(MBEDTLS_BLOCK_CIPHER_SOME_PSA) +#include +#endif +#include + +/* PSA_SUCCESS is kept at the top of each error table since + * it's the most common status when everything functions properly. */ +#if defined(MBEDTLS_MD_LIGHT) +const mbedtls_error_pair_t psa_to_md_errors[] = +{ + { PSA_SUCCESS, 0 }, + { PSA_ERROR_NOT_SUPPORTED, MBEDTLS_ERR_MD_FEATURE_UNAVAILABLE }, + { PSA_ERROR_INVALID_ARGUMENT, MBEDTLS_ERR_MD_BAD_INPUT_DATA }, + { PSA_ERROR_INSUFFICIENT_MEMORY, MBEDTLS_ERR_MD_ALLOC_FAILED } +}; +#endif + +#if defined(MBEDTLS_BLOCK_CIPHER_SOME_PSA) +const mbedtls_error_pair_t psa_to_cipher_errors[] = +{ + { PSA_SUCCESS, 0 }, + { PSA_ERROR_NOT_SUPPORTED, MBEDTLS_ERR_CIPHER_FEATURE_UNAVAILABLE }, + { PSA_ERROR_INVALID_ARGUMENT, MBEDTLS_ERR_CIPHER_BAD_INPUT_DATA }, + { PSA_ERROR_INSUFFICIENT_MEMORY, MBEDTLS_ERR_CIPHER_ALLOC_FAILED } +}; +#endif + +#if defined(MBEDTLS_LMS_C) +const mbedtls_error_pair_t psa_to_lms_errors[] = +{ + { PSA_SUCCESS, 0 }, + { PSA_ERROR_BUFFER_TOO_SMALL, MBEDTLS_ERR_LMS_BUFFER_TOO_SMALL }, + { PSA_ERROR_INVALID_ARGUMENT, MBEDTLS_ERR_LMS_BAD_INPUT_DATA } +}; +#endif + +#if defined(MBEDTLS_SSL_TLS_C) && \ + (defined(MBEDTLS_USE_PSA_CRYPTO) || defined(MBEDTLS_SSL_PROTO_TLS1_3)) +const mbedtls_error_pair_t psa_to_ssl_errors[] = +{ + { PSA_SUCCESS, 0 }, + { PSA_ERROR_INSUFFICIENT_MEMORY, MBEDTLS_ERR_SSL_ALLOC_FAILED }, + { PSA_ERROR_NOT_SUPPORTED, MBEDTLS_ERR_SSL_FEATURE_UNAVAILABLE }, + { PSA_ERROR_INVALID_SIGNATURE, MBEDTLS_ERR_SSL_INVALID_MAC }, + { PSA_ERROR_INVALID_ARGUMENT, MBEDTLS_ERR_SSL_BAD_INPUT_DATA }, + { PSA_ERROR_BAD_STATE, MBEDTLS_ERR_SSL_INTERNAL_ERROR }, + { PSA_ERROR_BUFFER_TOO_SMALL, MBEDTLS_ERR_SSL_BUFFER_TOO_SMALL } +}; +#endif + +#if defined(PSA_WANT_KEY_TYPE_RSA_PUBLIC_KEY) || \ + defined(PSA_WANT_KEY_TYPE_RSA_KEY_PAIR_BASIC) +const mbedtls_error_pair_t psa_to_pk_rsa_errors[] = +{ + { PSA_SUCCESS, 0 }, + { PSA_ERROR_NOT_PERMITTED, MBEDTLS_ERR_RSA_BAD_INPUT_DATA }, + { PSA_ERROR_INVALID_ARGUMENT, MBEDTLS_ERR_RSA_BAD_INPUT_DATA }, + { PSA_ERROR_INVALID_HANDLE, MBEDTLS_ERR_RSA_BAD_INPUT_DATA }, + { PSA_ERROR_BUFFER_TOO_SMALL, MBEDTLS_ERR_RSA_OUTPUT_TOO_LARGE }, + { PSA_ERROR_INSUFFICIENT_ENTROPY, MBEDTLS_ERR_RSA_RNG_FAILED }, + { PSA_ERROR_INVALID_SIGNATURE, MBEDTLS_ERR_RSA_VERIFY_FAILED }, + { PSA_ERROR_INVALID_PADDING, MBEDTLS_ERR_RSA_INVALID_PADDING } +}; +#endif + +#if defined(MBEDTLS_USE_PSA_CRYPTO) && \ + defined(PSA_WANT_KEY_TYPE_ECC_PUBLIC_KEY) +const mbedtls_error_pair_t psa_to_pk_ecdsa_errors[] = +{ + { PSA_SUCCESS, 0 }, + { PSA_ERROR_NOT_PERMITTED, MBEDTLS_ERR_ECP_BAD_INPUT_DATA }, + { PSA_ERROR_INVALID_ARGUMENT, MBEDTLS_ERR_ECP_BAD_INPUT_DATA }, + { PSA_ERROR_INVALID_HANDLE, MBEDTLS_ERR_ECP_FEATURE_UNAVAILABLE }, + { PSA_ERROR_BUFFER_TOO_SMALL, MBEDTLS_ERR_ECP_BUFFER_TOO_SMALL }, + { PSA_ERROR_INSUFFICIENT_ENTROPY, MBEDTLS_ERR_ECP_RANDOM_FAILED }, + { PSA_ERROR_INVALID_SIGNATURE, MBEDTLS_ERR_ECP_VERIFY_FAILED } +}; +#endif + +int psa_generic_status_to_mbedtls(psa_status_t status) +{ + switch (status) { + case PSA_SUCCESS: + return 0; + case PSA_ERROR_NOT_SUPPORTED: + return MBEDTLS_ERR_PLATFORM_FEATURE_UNSUPPORTED; + case PSA_ERROR_CORRUPTION_DETECTED: + return MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED; + case PSA_ERROR_COMMUNICATION_FAILURE: + case PSA_ERROR_HARDWARE_FAILURE: + return MBEDTLS_ERR_PLATFORM_HW_ACCEL_FAILED; + case PSA_ERROR_NOT_PERMITTED: + default: + return MBEDTLS_ERR_ERROR_GENERIC_ERROR; + } +} + +int psa_status_to_mbedtls(psa_status_t status, + const mbedtls_error_pair_t *local_translations, + size_t local_errors_num, + int (*fallback_f)(psa_status_t)) +{ + for (size_t i = 0; i < local_errors_num; i++) { + if (status == local_translations[i].psa_status) { + return local_translations[i].mbedtls_error; + } + } + return fallback_f(status); +} + +#if defined(MBEDTLS_PK_C) +int psa_pk_status_to_mbedtls(psa_status_t status) +{ + switch (status) { + case PSA_ERROR_INVALID_HANDLE: + return MBEDTLS_ERR_PK_KEY_INVALID_FORMAT; + case PSA_ERROR_BUFFER_TOO_SMALL: + return MBEDTLS_ERR_PK_BUFFER_TOO_SMALL; + case PSA_ERROR_NOT_SUPPORTED: + return MBEDTLS_ERR_PK_FEATURE_UNAVAILABLE; + case PSA_ERROR_INVALID_ARGUMENT: + return MBEDTLS_ERR_PK_INVALID_ALG; + case PSA_ERROR_NOT_PERMITTED: + return MBEDTLS_ERR_PK_TYPE_MISMATCH; + case PSA_ERROR_INSUFFICIENT_MEMORY: + return MBEDTLS_ERR_PK_ALLOC_FAILED; + case PSA_ERROR_BAD_STATE: + return MBEDTLS_ERR_PK_BAD_INPUT_DATA; + case PSA_ERROR_DATA_CORRUPT: + case PSA_ERROR_DATA_INVALID: + case PSA_ERROR_STORAGE_FAILURE: + return MBEDTLS_ERR_PK_FILE_IO_ERROR; + default: + return psa_generic_status_to_mbedtls(status); + } +} +#endif /* MBEDTLS_PK_C */ + +/****************************************************************/ +/* Key management */ +/****************************************************************/ + +#if defined(PSA_WANT_KEY_TYPE_ECC_PUBLIC_KEY) +psa_ecc_family_t mbedtls_ecc_group_to_psa(mbedtls_ecp_group_id grpid, + size_t *bits) +{ + switch (grpid) { +#if defined(MBEDTLS_ECP_HAVE_SECP192R1) + case MBEDTLS_ECP_DP_SECP192R1: + *bits = 192; + return PSA_ECC_FAMILY_SECP_R1; +#endif +#if defined(MBEDTLS_ECP_HAVE_SECP224R1) + case MBEDTLS_ECP_DP_SECP224R1: + *bits = 224; + return PSA_ECC_FAMILY_SECP_R1; +#endif +#if defined(MBEDTLS_ECP_HAVE_SECP256R1) + case MBEDTLS_ECP_DP_SECP256R1: + *bits = 256; + return PSA_ECC_FAMILY_SECP_R1; +#endif +#if defined(MBEDTLS_ECP_HAVE_SECP384R1) + case MBEDTLS_ECP_DP_SECP384R1: + *bits = 384; + return PSA_ECC_FAMILY_SECP_R1; +#endif +#if defined(MBEDTLS_ECP_HAVE_SECP521R1) + case MBEDTLS_ECP_DP_SECP521R1: + *bits = 521; + return PSA_ECC_FAMILY_SECP_R1; +#endif +#if defined(MBEDTLS_ECP_HAVE_BP256R1) + case MBEDTLS_ECP_DP_BP256R1: + *bits = 256; + return PSA_ECC_FAMILY_BRAINPOOL_P_R1; +#endif +#if defined(MBEDTLS_ECP_HAVE_BP384R1) + case MBEDTLS_ECP_DP_BP384R1: + *bits = 384; + return PSA_ECC_FAMILY_BRAINPOOL_P_R1; +#endif +#if defined(MBEDTLS_ECP_HAVE_BP512R1) + case MBEDTLS_ECP_DP_BP512R1: + *bits = 512; + return PSA_ECC_FAMILY_BRAINPOOL_P_R1; +#endif +#if defined(MBEDTLS_ECP_HAVE_CURVE25519) + case MBEDTLS_ECP_DP_CURVE25519: + *bits = 255; + return PSA_ECC_FAMILY_MONTGOMERY; +#endif +#if defined(MBEDTLS_ECP_HAVE_SECP192K1) + case MBEDTLS_ECP_DP_SECP192K1: + *bits = 192; + return PSA_ECC_FAMILY_SECP_K1; +#endif +#if defined(MBEDTLS_ECP_HAVE_SECP224K1) + /* secp224k1 is not and will not be supported in PSA (#3541). */ +#endif +#if defined(MBEDTLS_ECP_HAVE_SECP256K1) + case MBEDTLS_ECP_DP_SECP256K1: + *bits = 256; + return PSA_ECC_FAMILY_SECP_K1; +#endif +#if defined(MBEDTLS_ECP_HAVE_CURVE448) + case MBEDTLS_ECP_DP_CURVE448: + *bits = 448; + return PSA_ECC_FAMILY_MONTGOMERY; +#endif + default: + *bits = 0; + return 0; + } +} + +mbedtls_ecp_group_id mbedtls_ecc_group_from_psa(psa_ecc_family_t family, + size_t bits) +{ + switch (family) { + case PSA_ECC_FAMILY_SECP_R1: + switch (bits) { +#if defined(PSA_WANT_ECC_SECP_R1_192) + case 192: + return MBEDTLS_ECP_DP_SECP192R1; +#endif +#if defined(PSA_WANT_ECC_SECP_R1_224) + case 224: + return MBEDTLS_ECP_DP_SECP224R1; +#endif +#if defined(PSA_WANT_ECC_SECP_R1_256) + case 256: + return MBEDTLS_ECP_DP_SECP256R1; +#endif +#if defined(PSA_WANT_ECC_SECP_R1_384) + case 384: + return MBEDTLS_ECP_DP_SECP384R1; +#endif +#if defined(PSA_WANT_ECC_SECP_R1_521) + case 521: + return MBEDTLS_ECP_DP_SECP521R1; +#endif + } + break; + + case PSA_ECC_FAMILY_BRAINPOOL_P_R1: + switch (bits) { +#if defined(PSA_WANT_ECC_BRAINPOOL_P_R1_256) + case 256: + return MBEDTLS_ECP_DP_BP256R1; +#endif +#if defined(PSA_WANT_ECC_BRAINPOOL_P_R1_384) + case 384: + return MBEDTLS_ECP_DP_BP384R1; +#endif +#if defined(PSA_WANT_ECC_BRAINPOOL_P_R1_512) + case 512: + return MBEDTLS_ECP_DP_BP512R1; +#endif + } + break; + + case PSA_ECC_FAMILY_MONTGOMERY: + switch (bits) { +#if defined(PSA_WANT_ECC_MONTGOMERY_255) + case 255: + return MBEDTLS_ECP_DP_CURVE25519; +#endif +#if defined(PSA_WANT_ECC_MONTGOMERY_448) + case 448: + return MBEDTLS_ECP_DP_CURVE448; +#endif + } + break; + + case PSA_ECC_FAMILY_SECP_K1: + switch (bits) { +#if defined(PSA_WANT_ECC_SECP_K1_192) + case 192: + return MBEDTLS_ECP_DP_SECP192K1; +#endif +#if defined(PSA_WANT_ECC_SECP_K1_224) + /* secp224k1 is not and will not be supported in PSA (#3541). */ +#endif +#if defined(PSA_WANT_ECC_SECP_K1_256) + case 256: + return MBEDTLS_ECP_DP_SECP256K1; +#endif + } + break; + } + + return MBEDTLS_ECP_DP_NONE; +} +#endif /* PSA_WANT_KEY_TYPE_ECC_PUBLIC_KEY */ + +/* Wrapper function allowing the classic API to use the PSA RNG. + * + * `mbedtls_psa_get_random(MBEDTLS_PSA_RANDOM_STATE, ...)` calls + * `psa_generate_random(...)`. The state parameter is ignored since the + * PSA API doesn't support passing an explicit state. + */ +int mbedtls_psa_get_random(void *p_rng, + unsigned char *output, + size_t output_size) +{ + /* This function takes a pointer to the RNG state because that's what + * classic mbedtls functions using an RNG expect. The PSA RNG manages + * its own state internally and doesn't let the caller access that state. + * So we just ignore the state parameter, and in practice we'll pass + * NULL. */ + (void) p_rng; + psa_status_t status = psa_generate_random(output, output_size); + if (status == PSA_SUCCESS) { + return 0; + } else { + return MBEDTLS_ERR_ENTROPY_SOURCE_FAILED; + } +} + +#endif /* MBEDTLS_PSA_CRYPTO_CLIENT */ + +#if defined(MBEDTLS_PSA_UTIL_HAVE_ECDSA) + +/** + * \brief Convert a single raw coordinate to DER ASN.1 format. The output der + * buffer is filled backward (i.e. starting from its end). + * + * \param raw_buf Buffer containing the raw coordinate to be + * converted. + * \param raw_len Length of raw_buf in bytes. This must be > 0. + * \param der_buf_start Pointer to the beginning of the buffer which + * will be filled with the DER converted data. + * \param der_buf_end End of the buffer used to store the DER output. + * + * \return On success, the amount of data (in bytes) written to + * the DER buffer. + * \return MBEDTLS_ERR_ASN1_BUF_TOO_SMALL if the provided der + * buffer is too small to contain all the converted data. + * \return MBEDTLS_ERR_ASN1_INVALID_DATA if the input raw + * coordinate is null (i.e. all zeros). + * + * \warning Raw and der buffer must not be overlapping. + */ +static int convert_raw_to_der_single_int(const unsigned char *raw_buf, size_t raw_len, + unsigned char *der_buf_start, + unsigned char *der_buf_end) +{ + unsigned char *p = der_buf_end; + int len; + int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED; + + /* ASN.1 DER encoding requires minimal length, so skip leading 0s. + * Provided input MPIs should not be 0, but as a failsafe measure, still + * detect that and return error in case. */ + while (*raw_buf == 0x00) { + ++raw_buf; + --raw_len; + if (raw_len == 0) { + return MBEDTLS_ERR_ASN1_INVALID_DATA; + } + } + len = (int) raw_len; + + /* Copy the raw coordinate to the end of der_buf. */ + if ((p - der_buf_start) < len) { + return MBEDTLS_ERR_ASN1_BUF_TOO_SMALL; + } + p -= len; + memcpy(p, raw_buf, len); + + /* If MSb is 1, ASN.1 requires that we prepend a 0. */ + if (*p & 0x80) { + if ((p - der_buf_start) < 1) { + return MBEDTLS_ERR_ASN1_BUF_TOO_SMALL; + } + --p; + *p = 0x00; + ++len; + } + + MBEDTLS_ASN1_CHK_ADD(len, mbedtls_asn1_write_len(&p, der_buf_start, len)); + MBEDTLS_ASN1_CHK_ADD(len, mbedtls_asn1_write_tag(&p, der_buf_start, MBEDTLS_ASN1_INTEGER)); + + return len; +} + +int mbedtls_ecdsa_raw_to_der(size_t bits, const unsigned char *raw, size_t raw_len, + unsigned char *der, size_t der_size, size_t *der_len) +{ + unsigned char r[PSA_BITS_TO_BYTES(PSA_VENDOR_ECC_MAX_CURVE_BITS)]; + unsigned char s[PSA_BITS_TO_BYTES(PSA_VENDOR_ECC_MAX_CURVE_BITS)]; + const size_t coordinate_len = PSA_BITS_TO_BYTES(bits); + size_t len = 0; + unsigned char *p = der + der_size; + int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED; + + if (raw_len != (2 * coordinate_len)) { + return MBEDTLS_ERR_ASN1_INVALID_DATA; + } + + /* Since raw and der buffers might overlap, dump r and s before starting + * the conversion. */ + memcpy(r, raw, coordinate_len); + memcpy(s, raw + coordinate_len, coordinate_len); + + /* der buffer will initially be written starting from its end so we pick s + * first and then r. */ + ret = convert_raw_to_der_single_int(s, coordinate_len, der, p); + if (ret < 0) { + return ret; + } + p -= ret; + len += ret; + + ret = convert_raw_to_der_single_int(r, coordinate_len, der, p); + if (ret < 0) { + return ret; + } + p -= ret; + len += ret; + + /* Add ASN.1 header (len + tag). */ + MBEDTLS_ASN1_CHK_ADD(len, mbedtls_asn1_write_len(&p, der, len)); + MBEDTLS_ASN1_CHK_ADD(len, mbedtls_asn1_write_tag(&p, der, + MBEDTLS_ASN1_CONSTRUCTED | + MBEDTLS_ASN1_SEQUENCE)); + + /* memmove the content of der buffer to its beginnig. */ + memmove(der, p, len); + *der_len = len; + + return 0; +} + +/** + * \brief Convert a single integer from ASN.1 DER format to raw. + * + * \param der Buffer containing the DER integer value to be + * converted. + * \param der_len Length of the der buffer in bytes. + * \param raw Output buffer that will be filled with the + * converted data. This should be at least + * coordinate_size bytes and it must be zeroed before + * calling this function. + * \param coordinate_size Size (in bytes) of a single coordinate in raw + * format. + * + * \return On success, the amount of DER data parsed from the + * provided der buffer. + * \return MBEDTLS_ERR_ASN1_UNEXPECTED_TAG if the integer tag + * is missing in the der buffer. + * \return MBEDTLS_ERR_ASN1_LENGTH_MISMATCH if the integer + * is null (i.e. all zeros) or if the output raw buffer + * is too small to contain the converted raw value. + * + * \warning Der and raw buffers must not be overlapping. + */ +static int convert_der_to_raw_single_int(unsigned char *der, size_t der_len, + unsigned char *raw, size_t coordinate_size) +{ + unsigned char *p = der; + int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED; + size_t unpadded_len, padding_len = 0; + + /* Get the length of ASN.1 element (i.e. the integer we need to parse). */ + ret = mbedtls_asn1_get_tag(&p, p + der_len, &unpadded_len, + MBEDTLS_ASN1_INTEGER); + if (ret != 0) { + return ret; + } + + /* It's invalid to have: + * - unpadded_len == 0. + * - MSb set without a leading 0x00 (leading 0x00 is checked below). */ + if (((unpadded_len == 0) || (*p & 0x80) != 0)) { + return MBEDTLS_ERR_ASN1_INVALID_DATA; + } + + /* Skip possible leading zero */ + if (*p == 0x00) { + p++; + unpadded_len--; + /* It is not allowed to have more than 1 leading zero. + * Ignore the case in which unpadded_len = 0 because that's a 0 encoded + * in ASN.1 format (i.e. 020100). */ + if ((unpadded_len > 0) && (*p == 0x00)) { + return MBEDTLS_ERR_ASN1_INVALID_DATA; + } + } + + if (unpadded_len > coordinate_size) { + /* Parsed number is longer than the maximum expected value. */ + return MBEDTLS_ERR_ASN1_INVALID_DATA; + } + padding_len = coordinate_size - unpadded_len; + /* raw buffer was already zeroed by the calling function so zero-padding + * operation is skipped here. */ + memcpy(raw + padding_len, p, unpadded_len); + p += unpadded_len; + + return (int) (p - der); +} + +int mbedtls_ecdsa_der_to_raw(size_t bits, const unsigned char *der, size_t der_len, + unsigned char *raw, size_t raw_size, size_t *raw_len) +{ + unsigned char raw_tmp[PSA_VENDOR_ECDSA_SIGNATURE_MAX_SIZE]; + unsigned char *p = (unsigned char *) der; + size_t data_len; + size_t coordinate_size = PSA_BITS_TO_BYTES(bits); + int ret; + + /* The output raw buffer should be at least twice the size of a raw + * coordinate in order to store r and s. */ + if (raw_size < coordinate_size * 2) { + return MBEDTLS_ERR_ASN1_BUF_TOO_SMALL; + } + + /* Check that the provided input DER buffer has the right header. */ + ret = mbedtls_asn1_get_tag(&p, der + der_len, &data_len, + MBEDTLS_ASN1_CONSTRUCTED | MBEDTLS_ASN1_SEQUENCE); + if (ret != 0) { + return ret; + } + + memset(raw_tmp, 0, 2 * coordinate_size); + + /* Extract r */ + ret = convert_der_to_raw_single_int(p, data_len, raw_tmp, coordinate_size); + if (ret < 0) { + return ret; + } + p += ret; + data_len -= ret; + + /* Extract s */ + ret = convert_der_to_raw_single_int(p, data_len, raw_tmp + coordinate_size, + coordinate_size); + if (ret < 0) { + return ret; + } + p += ret; + data_len -= ret; + + /* Check that we consumed all the input der data. */ + if ((size_t) (p - der) != der_len) { + return MBEDTLS_ERR_ASN1_LENGTH_MISMATCH; + } + + memcpy(raw, raw_tmp, 2 * coordinate_size); + *raw_len = 2 * coordinate_size; + + return 0; +} + +#endif /* MBEDTLS_PSA_UTIL_HAVE_ECDSA */ diff --git a/vendor/mbedtls/library/psa_util_internal.h b/vendor/mbedtls/library/psa_util_internal.h new file mode 100644 index 0000000000..70a08a02cd --- /dev/null +++ b/vendor/mbedtls/library/psa_util_internal.h @@ -0,0 +1,100 @@ +/** + * \file psa_util_internal.h + * + * \brief Internal utility functions for use of PSA Crypto. + */ +/* + * Copyright The Mbed TLS Contributors + * SPDX-License-Identifier: Apache-2.0 OR GPL-2.0-or-later + */ + +#ifndef MBEDTLS_PSA_UTIL_INTERNAL_H +#define MBEDTLS_PSA_UTIL_INTERNAL_H + +/* Include the public header so that users only need one include. */ +#include "mbedtls/psa_util.h" + +#include "psa/crypto.h" + +#if defined(MBEDTLS_PSA_CRYPTO_CLIENT) + +/************************************************************************* + * FFDH + ************************************************************************/ + +#define MBEDTLS_PSA_MAX_FFDH_PUBKEY_LENGTH \ + PSA_KEY_EXPORT_FFDH_PUBLIC_KEY_MAX_SIZE(PSA_VENDOR_FFDH_MAX_KEY_BITS) + +/************************************************************************* + * ECC + ************************************************************************/ + +#define MBEDTLS_PSA_MAX_EC_PUBKEY_LENGTH \ + PSA_KEY_EXPORT_ECC_PUBLIC_KEY_MAX_SIZE(PSA_VENDOR_ECC_MAX_CURVE_BITS) + +#define MBEDTLS_PSA_MAX_EC_KEY_PAIR_LENGTH \ + PSA_KEY_EXPORT_ECC_KEY_PAIR_MAX_SIZE(PSA_VENDOR_ECC_MAX_CURVE_BITS) + +/************************************************************************* + * Error translation + ************************************************************************/ + +typedef struct { + /* Error codes used by PSA crypto are in -255..-128, fitting in 16 bits. */ + int16_t psa_status; + /* Error codes used by Mbed TLS are in one of the ranges + * -127..-1 (low-level) or -32767..-4096 (high-level with a low-level + * code optionally added), fitting in 16 bits. */ + int16_t mbedtls_error; +} mbedtls_error_pair_t; + +#if defined(MBEDTLS_MD_LIGHT) +extern const mbedtls_error_pair_t psa_to_md_errors[4]; +#endif + +#if defined(MBEDTLS_BLOCK_CIPHER_SOME_PSA) +extern const mbedtls_error_pair_t psa_to_cipher_errors[4]; +#endif + +#if defined(MBEDTLS_LMS_C) +extern const mbedtls_error_pair_t psa_to_lms_errors[3]; +#endif + +#if defined(MBEDTLS_USE_PSA_CRYPTO) || defined(MBEDTLS_SSL_PROTO_TLS1_3) +extern const mbedtls_error_pair_t psa_to_ssl_errors[7]; +#endif + +#if defined(PSA_WANT_KEY_TYPE_RSA_PUBLIC_KEY) || \ + defined(PSA_WANT_KEY_TYPE_RSA_KEY_PAIR_BASIC) +extern const mbedtls_error_pair_t psa_to_pk_rsa_errors[8]; +#endif + +#if defined(MBEDTLS_USE_PSA_CRYPTO) && \ + defined(PSA_WANT_KEY_TYPE_ECC_PUBLIC_KEY) +extern const mbedtls_error_pair_t psa_to_pk_ecdsa_errors[7]; +#endif + +/* Generic fallback function for error translation, + * when the received state was not module-specific. */ +int psa_generic_status_to_mbedtls(psa_status_t status); + +/* This function iterates over provided local error translations, + * and if no match was found - calls the fallback error translation function. */ +int psa_status_to_mbedtls(psa_status_t status, + const mbedtls_error_pair_t *local_translations, + size_t local_errors_num, + int (*fallback_f)(psa_status_t)); + +/* The second out of three-stage error handling functions of the pk module, + * acts as a fallback after RSA / ECDSA error translation, and if no match + * is found, it itself calls psa_generic_status_to_mbedtls. */ +int psa_pk_status_to_mbedtls(psa_status_t status); + +/* Utility macro to shorten the defines of error translator in modules. */ +#define PSA_TO_MBEDTLS_ERR_LIST(status, error_list, fallback_f) \ + psa_status_to_mbedtls(status, error_list, \ + sizeof(error_list)/sizeof(error_list[0]), \ + fallback_f) + +#endif /* MBEDTLS_PSA_CRYPTO_CLIENT */ +#endif /* MBEDTLS_PSA_UTIL_INTERNAL_H */ diff --git a/vendor/mbedtls/library/ripemd160.c b/vendor/mbedtls/library/ripemd160.c index a2e11cdf08..b4fc3cdba1 100644 --- a/vendor/mbedtls/library/ripemd160.c +++ b/vendor/mbedtls/library/ripemd160.c @@ -2,19 +2,7 @@ * RIPE MD-160 implementation * * Copyright The Mbed TLS Contributors - * SPDX-License-Identifier: Apache-2.0 - * - * Licensed under the Apache License, Version 2.0 (the "License"); you may - * not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT - * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. + * SPDX-License-Identifier: Apache-2.0 OR GPL-2.0-or-later */ /* @@ -60,7 +48,7 @@ void mbedtls_ripemd160_clone(mbedtls_ripemd160_context *dst, /* * RIPEMD-160 context setup */ -int mbedtls_ripemd160_starts_ret(mbedtls_ripemd160_context *ctx) +int mbedtls_ripemd160_starts(mbedtls_ripemd160_context *ctx) { ctx->total[0] = 0; ctx->total[1] = 0; @@ -74,13 +62,6 @@ int mbedtls_ripemd160_starts_ret(mbedtls_ripemd160_context *ctx) return 0; } -#if !defined(MBEDTLS_DEPRECATED_REMOVED) -void mbedtls_ripemd160_starts(mbedtls_ripemd160_context *ctx) -{ - mbedtls_ripemd160_starts_ret(ctx); -} -#endif - #if !defined(MBEDTLS_RIPEMD160_PROCESS_ALT) /* * Process one block @@ -277,21 +258,14 @@ int mbedtls_internal_ripemd160_process(mbedtls_ripemd160_context *ctx, return 0; } -#if !defined(MBEDTLS_DEPRECATED_REMOVED) -void mbedtls_ripemd160_process(mbedtls_ripemd160_context *ctx, - const unsigned char data[64]) -{ - mbedtls_internal_ripemd160_process(ctx, data); -} -#endif #endif /* !MBEDTLS_RIPEMD160_PROCESS_ALT */ /* * RIPEMD-160 process buffer */ -int mbedtls_ripemd160_update_ret(mbedtls_ripemd160_context *ctx, - const unsigned char *input, - size_t ilen) +int mbedtls_ripemd160_update(mbedtls_ripemd160_context *ctx, + const unsigned char *input, + size_t ilen) { int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED; size_t fill; @@ -339,15 +313,6 @@ int mbedtls_ripemd160_update_ret(mbedtls_ripemd160_context *ctx, return 0; } -#if !defined(MBEDTLS_DEPRECATED_REMOVED) -void mbedtls_ripemd160_update(mbedtls_ripemd160_context *ctx, - const unsigned char *input, - size_t ilen) -{ - mbedtls_ripemd160_update_ret(ctx, input, ilen); -} -#endif - static const unsigned char ripemd160_padding[64] = { 0x80, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, @@ -359,8 +324,8 @@ static const unsigned char ripemd160_padding[64] = /* * RIPEMD-160 final digest */ -int mbedtls_ripemd160_finish_ret(mbedtls_ripemd160_context *ctx, - unsigned char output[20]) +int mbedtls_ripemd160_finish(mbedtls_ripemd160_context *ctx, + unsigned char output[20]) { int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED; uint32_t last, padn; @@ -377,14 +342,14 @@ int mbedtls_ripemd160_finish_ret(mbedtls_ripemd160_context *ctx, last = ctx->total[0] & 0x3F; padn = (last < 56) ? (56 - last) : (120 - last); - ret = mbedtls_ripemd160_update_ret(ctx, ripemd160_padding, padn); + ret = mbedtls_ripemd160_update(ctx, ripemd160_padding, padn); if (ret != 0) { - return ret; + goto exit; } - ret = mbedtls_ripemd160_update_ret(ctx, msglen, 8); + ret = mbedtls_ripemd160_update(ctx, msglen, 8); if (ret != 0) { - return ret; + goto exit; } MBEDTLS_PUT_UINT32_LE(ctx->state[0], output, 0); @@ -393,40 +358,36 @@ int mbedtls_ripemd160_finish_ret(mbedtls_ripemd160_context *ctx, MBEDTLS_PUT_UINT32_LE(ctx->state[3], output, 12); MBEDTLS_PUT_UINT32_LE(ctx->state[4], output, 16); - return 0; -} + ret = 0; -#if !defined(MBEDTLS_DEPRECATED_REMOVED) -void mbedtls_ripemd160_finish(mbedtls_ripemd160_context *ctx, - unsigned char output[20]) -{ - mbedtls_ripemd160_finish_ret(ctx, output); +exit: + mbedtls_ripemd160_free(ctx); + return ret; } -#endif #endif /* ! MBEDTLS_RIPEMD160_ALT */ /* * output = RIPEMD-160( input buffer ) */ -int mbedtls_ripemd160_ret(const unsigned char *input, - size_t ilen, - unsigned char output[20]) +int mbedtls_ripemd160(const unsigned char *input, + size_t ilen, + unsigned char output[20]) { int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED; mbedtls_ripemd160_context ctx; mbedtls_ripemd160_init(&ctx); - if ((ret = mbedtls_ripemd160_starts_ret(&ctx)) != 0) { + if ((ret = mbedtls_ripemd160_starts(&ctx)) != 0) { goto exit; } - if ((ret = mbedtls_ripemd160_update_ret(&ctx, input, ilen)) != 0) { + if ((ret = mbedtls_ripemd160_update(&ctx, input, ilen)) != 0) { goto exit; } - if ((ret = mbedtls_ripemd160_finish_ret(&ctx, output)) != 0) { + if ((ret = mbedtls_ripemd160_finish(&ctx, output)) != 0) { goto exit; } @@ -436,15 +397,6 @@ int mbedtls_ripemd160_ret(const unsigned char *input, return ret; } -#if !defined(MBEDTLS_DEPRECATED_REMOVED) -void mbedtls_ripemd160(const unsigned char *input, - size_t ilen, - unsigned char output[20]) -{ - mbedtls_ripemd160_ret(input, ilen, output); -} -#endif - #if defined(MBEDTLS_SELF_TEST) /* * Test vectors from the RIPEMD-160 paper and @@ -503,8 +455,8 @@ int mbedtls_ripemd160_self_test(int verbose) mbedtls_printf(" RIPEMD-160 test #%d: ", i + 1); } - ret = mbedtls_ripemd160_ret(ripemd160_test_str[i], - ripemd160_test_strlen[i], output); + ret = mbedtls_ripemd160(ripemd160_test_str[i], + ripemd160_test_strlen[i], output); if (ret != 0) { goto fail; } diff --git a/vendor/mbedtls/library/rsa.c b/vendor/mbedtls/library/rsa.c index 01d0eb09d2..7eb4a259ea 100644 --- a/vendor/mbedtls/library/rsa.c +++ b/vendor/mbedtls/library/rsa.c @@ -2,19 +2,7 @@ * The RSA public-key cryptosystem * * Copyright The Mbed TLS Contributors - * SPDX-License-Identifier: Apache-2.0 - * - * Licensed under the Apache License, Version 2.0 (the "License"); you may - * not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT - * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. + * SPDX-License-Identifier: Apache-2.0 OR GPL-2.0-or-later */ /* @@ -40,32 +28,545 @@ #if defined(MBEDTLS_RSA_C) #include "mbedtls/rsa.h" -#include "mbedtls/rsa_internal.h" +#include "bignum_core.h" +#include "rsa_alt_helpers.h" +#include "rsa_internal.h" #include "mbedtls/oid.h" +#include "mbedtls/asn1write.h" #include "mbedtls/platform_util.h" #include "mbedtls/error.h" #include "constant_time_internal.h" #include "mbedtls/constant_time.h" +#include "md_psa.h" #include -#if defined(MBEDTLS_PKCS1_V21) -#include "mbedtls/md.h" -#endif - #if defined(MBEDTLS_PKCS1_V15) && !defined(__OpenBSD__) && !defined(__NetBSD__) #include #endif #include "mbedtls/platform.h" -#if !defined(MBEDTLS_RSA_ALT) +/* + * Wrapper around mbedtls_asn1_get_mpi() that rejects zero. + * + * The value zero is: + * - never a valid value for an RSA parameter + * - interpreted as "omitted, please reconstruct" by mbedtls_rsa_complete(). + * + * Since values can't be omitted in PKCS#1, passing a zero value to + * rsa_complete() would be incorrect, so reject zero values early. + */ +static int asn1_get_nonzero_mpi(unsigned char **p, + const unsigned char *end, + mbedtls_mpi *X) +{ + int ret; + + ret = mbedtls_asn1_get_mpi(p, end, X); + if (ret != 0) { + return ret; + } + + if (mbedtls_mpi_cmp_int(X, 0) == 0) { + return MBEDTLS_ERR_RSA_BAD_INPUT_DATA; + } + + return 0; +} + +int mbedtls_rsa_parse_key(mbedtls_rsa_context *rsa, const unsigned char *key, size_t keylen) +{ + int ret, version; + size_t len; + unsigned char *p, *end; + + mbedtls_mpi T; + mbedtls_mpi_init(&T); + + p = (unsigned char *) key; + end = p + keylen; + + /* + * This function parses the RSAPrivateKey (PKCS#1) + * + * RSAPrivateKey ::= SEQUENCE { + * version Version, + * modulus INTEGER, -- n + * publicExponent INTEGER, -- e + * privateExponent INTEGER, -- d + * prime1 INTEGER, -- p + * prime2 INTEGER, -- q + * exponent1 INTEGER, -- d mod (p-1) + * exponent2 INTEGER, -- d mod (q-1) + * coefficient INTEGER, -- (inverse of q) mod p + * otherPrimeInfos OtherPrimeInfos OPTIONAL + * } + */ + if ((ret = mbedtls_asn1_get_tag(&p, end, &len, + MBEDTLS_ASN1_CONSTRUCTED | MBEDTLS_ASN1_SEQUENCE)) != 0) { + return ret; + } -/* Parameter validation macros */ -#define RSA_VALIDATE_RET(cond) \ - MBEDTLS_INTERNAL_VALIDATE_RET(cond, MBEDTLS_ERR_RSA_BAD_INPUT_DATA) -#define RSA_VALIDATE(cond) \ - MBEDTLS_INTERNAL_VALIDATE(cond) + if (end != p + len) { + return MBEDTLS_ERR_RSA_BAD_INPUT_DATA; + } + + if ((ret = mbedtls_asn1_get_int(&p, end, &version)) != 0) { + return ret; + } + + if (version != 0) { + return MBEDTLS_ERR_RSA_BAD_INPUT_DATA; + } + + /* Import N */ + if ((ret = asn1_get_nonzero_mpi(&p, end, &T)) != 0 || + (ret = mbedtls_rsa_import(rsa, &T, NULL, NULL, + NULL, NULL)) != 0) { + goto cleanup; + } + + /* Import E */ + if ((ret = asn1_get_nonzero_mpi(&p, end, &T)) != 0 || + (ret = mbedtls_rsa_import(rsa, NULL, NULL, NULL, + NULL, &T)) != 0) { + goto cleanup; + } + + /* Import D */ + if ((ret = asn1_get_nonzero_mpi(&p, end, &T)) != 0 || + (ret = mbedtls_rsa_import(rsa, NULL, NULL, NULL, + &T, NULL)) != 0) { + goto cleanup; + } + + /* Import P */ + if ((ret = asn1_get_nonzero_mpi(&p, end, &T)) != 0 || + (ret = mbedtls_rsa_import(rsa, NULL, &T, NULL, + NULL, NULL)) != 0) { + goto cleanup; + } + + /* Import Q */ + if ((ret = asn1_get_nonzero_mpi(&p, end, &T)) != 0 || + (ret = mbedtls_rsa_import(rsa, NULL, NULL, &T, + NULL, NULL)) != 0) { + goto cleanup; + } + +#if !defined(MBEDTLS_RSA_NO_CRT) && !defined(MBEDTLS_RSA_ALT) + /* + * The RSA CRT parameters DP, DQ and QP are nominally redundant, in + * that they can be easily recomputed from D, P and Q. However by + * parsing them from the PKCS1 structure it is possible to avoid + * recalculating them which both reduces the overhead of loading + * RSA private keys into memory and also avoids side channels which + * can arise when computing those values, since all of D, P, and Q + * are secret. See https://eprint.iacr.org/2020/055 for a + * description of one such attack. + */ + + /* Import DP */ + if ((ret = asn1_get_nonzero_mpi(&p, end, &T)) != 0 || + (ret = mbedtls_mpi_copy(&rsa->DP, &T)) != 0) { + goto cleanup; + } + + /* Import DQ */ + if ((ret = asn1_get_nonzero_mpi(&p, end, &T)) != 0 || + (ret = mbedtls_mpi_copy(&rsa->DQ, &T)) != 0) { + goto cleanup; + } + + /* Import QP */ + if ((ret = asn1_get_nonzero_mpi(&p, end, &T)) != 0 || + (ret = mbedtls_mpi_copy(&rsa->QP, &T)) != 0) { + goto cleanup; + } + +#else + /* Verify existence of the CRT params */ + if ((ret = asn1_get_nonzero_mpi(&p, end, &T)) != 0 || + (ret = asn1_get_nonzero_mpi(&p, end, &T)) != 0 || + (ret = asn1_get_nonzero_mpi(&p, end, &T)) != 0) { + goto cleanup; + } +#endif + + /* rsa_complete() doesn't complete anything with the default + * implementation but is still called: + * - for the benefit of alternative implementation that may want to + * pre-compute stuff beyond what's provided (eg Montgomery factors) + * - as is also sanity-checks the key + * + * Furthermore, we also check the public part for consistency with + * mbedtls_pk_parse_pubkey(), as it includes size minima for example. + */ + if ((ret = mbedtls_rsa_complete(rsa)) != 0 || + (ret = mbedtls_rsa_check_pubkey(rsa)) != 0) { + goto cleanup; + } + + if (p != end) { + ret = MBEDTLS_ERR_ASN1_LENGTH_MISMATCH; + } + +cleanup: + + mbedtls_mpi_free(&T); + + if (ret != 0) { + mbedtls_rsa_free(rsa); + } + + return ret; +} + +int mbedtls_rsa_parse_pubkey(mbedtls_rsa_context *rsa, const unsigned char *key, size_t keylen) +{ + unsigned char *p = (unsigned char *) key; + unsigned char *end = (unsigned char *) (key + keylen); + int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED; + size_t len; + + /* + * RSAPublicKey ::= SEQUENCE { + * modulus INTEGER, -- n + * publicExponent INTEGER -- e + * } + */ + + if ((ret = mbedtls_asn1_get_tag(&p, end, &len, + MBEDTLS_ASN1_CONSTRUCTED | MBEDTLS_ASN1_SEQUENCE)) != 0) { + return ret; + } + + if (end != p + len) { + return MBEDTLS_ERR_RSA_BAD_INPUT_DATA; + } + + /* Import N */ + if ((ret = mbedtls_asn1_get_tag(&p, end, &len, MBEDTLS_ASN1_INTEGER)) != 0) { + return ret; + } + + if ((ret = mbedtls_rsa_import_raw(rsa, p, len, NULL, 0, NULL, 0, + NULL, 0, NULL, 0)) != 0) { + return MBEDTLS_ERR_RSA_BAD_INPUT_DATA; + } + + p += len; + + /* Import E */ + if ((ret = mbedtls_asn1_get_tag(&p, end, &len, MBEDTLS_ASN1_INTEGER)) != 0) { + return ret; + } + + if ((ret = mbedtls_rsa_import_raw(rsa, NULL, 0, NULL, 0, NULL, 0, + NULL, 0, p, len)) != 0) { + return MBEDTLS_ERR_RSA_BAD_INPUT_DATA; + } + + p += len; + + if (mbedtls_rsa_complete(rsa) != 0 || + mbedtls_rsa_check_pubkey(rsa) != 0) { + return MBEDTLS_ERR_RSA_BAD_INPUT_DATA; + } + + if (p != end) { + return MBEDTLS_ERR_ASN1_LENGTH_MISMATCH; + } + + return 0; +} + +int mbedtls_rsa_write_key(const mbedtls_rsa_context *rsa, unsigned char *start, + unsigned char **p) +{ + size_t len = 0; + int ret; + + mbedtls_mpi T; /* Temporary holding the exported parameters */ + + /* + * Export the parameters one after another to avoid simultaneous copies. + */ + + mbedtls_mpi_init(&T); + + /* Export QP */ + if ((ret = mbedtls_rsa_export_crt(rsa, NULL, NULL, &T)) != 0 || + (ret = mbedtls_asn1_write_mpi(p, start, &T)) < 0) { + goto end_of_export; + } + len += ret; + + /* Export DQ */ + if ((ret = mbedtls_rsa_export_crt(rsa, NULL, &T, NULL)) != 0 || + (ret = mbedtls_asn1_write_mpi(p, start, &T)) < 0) { + goto end_of_export; + } + len += ret; + + /* Export DP */ + if ((ret = mbedtls_rsa_export_crt(rsa, &T, NULL, NULL)) != 0 || + (ret = mbedtls_asn1_write_mpi(p, start, &T)) < 0) { + goto end_of_export; + } + len += ret; + + /* Export Q */ + if ((ret = mbedtls_rsa_export(rsa, NULL, NULL, &T, NULL, NULL)) != 0 || + (ret = mbedtls_asn1_write_mpi(p, start, &T)) < 0) { + goto end_of_export; + } + len += ret; + + /* Export P */ + if ((ret = mbedtls_rsa_export(rsa, NULL, &T, NULL, NULL, NULL)) != 0 || + (ret = mbedtls_asn1_write_mpi(p, start, &T)) < 0) { + goto end_of_export; + } + len += ret; + + /* Export D */ + if ((ret = mbedtls_rsa_export(rsa, NULL, NULL, NULL, &T, NULL)) != 0 || + (ret = mbedtls_asn1_write_mpi(p, start, &T)) < 0) { + goto end_of_export; + } + len += ret; + + /* Export E */ + if ((ret = mbedtls_rsa_export(rsa, NULL, NULL, NULL, NULL, &T)) != 0 || + (ret = mbedtls_asn1_write_mpi(p, start, &T)) < 0) { + goto end_of_export; + } + len += ret; + + /* Export N */ + if ((ret = mbedtls_rsa_export(rsa, &T, NULL, NULL, NULL, NULL)) != 0 || + (ret = mbedtls_asn1_write_mpi(p, start, &T)) < 0) { + goto end_of_export; + } + len += ret; + +end_of_export: + + mbedtls_mpi_free(&T); + if (ret < 0) { + return ret; + } + + MBEDTLS_ASN1_CHK_ADD(len, mbedtls_asn1_write_int(p, start, 0)); + MBEDTLS_ASN1_CHK_ADD(len, mbedtls_asn1_write_len(p, start, len)); + MBEDTLS_ASN1_CHK_ADD(len, mbedtls_asn1_write_tag(p, start, + MBEDTLS_ASN1_CONSTRUCTED | + MBEDTLS_ASN1_SEQUENCE)); + + return (int) len; +} + +/* + * RSAPublicKey ::= SEQUENCE { + * modulus INTEGER, -- n + * publicExponent INTEGER -- e + * } + */ +int mbedtls_rsa_write_pubkey(const mbedtls_rsa_context *rsa, unsigned char *start, + unsigned char **p) +{ + int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED; + size_t len = 0; + mbedtls_mpi T; + + mbedtls_mpi_init(&T); + + /* Export E */ + if ((ret = mbedtls_rsa_export(rsa, NULL, NULL, NULL, NULL, &T)) != 0 || + (ret = mbedtls_asn1_write_mpi(p, start, &T)) < 0) { + goto end_of_export; + } + len += ret; + + /* Export N */ + if ((ret = mbedtls_rsa_export(rsa, &T, NULL, NULL, NULL, NULL)) != 0 || + (ret = mbedtls_asn1_write_mpi(p, start, &T)) < 0) { + goto end_of_export; + } + len += ret; + +end_of_export: + + mbedtls_mpi_free(&T); + if (ret < 0) { + return ret; + } + + MBEDTLS_ASN1_CHK_ADD(len, mbedtls_asn1_write_len(p, start, len)); + MBEDTLS_ASN1_CHK_ADD(len, mbedtls_asn1_write_tag(p, start, MBEDTLS_ASN1_CONSTRUCTED | + MBEDTLS_ASN1_SEQUENCE)); + + return (int) len; +} + +#if defined(MBEDTLS_PKCS1_V15) && defined(MBEDTLS_RSA_C) && !defined(MBEDTLS_RSA_ALT) + +/** This function performs the unpadding part of a PKCS#1 v1.5 decryption + * operation (EME-PKCS1-v1_5 decoding). + * + * \note The return value from this function is a sensitive value + * (this is unusual). #MBEDTLS_ERR_RSA_OUTPUT_TOO_LARGE shouldn't happen + * in a well-written application, but 0 vs #MBEDTLS_ERR_RSA_INVALID_PADDING + * is often a situation that an attacker can provoke and leaking which + * one is the result is precisely the information the attacker wants. + * + * \param input The input buffer which is the payload inside PKCS#1v1.5 + * encryption padding, called the "encoded message EM" + * by the terminology. + * \param ilen The length of the payload in the \p input buffer. + * \param output The buffer for the payload, called "message M" by the + * PKCS#1 terminology. This must be a writable buffer of + * length \p output_max_len bytes. + * \param olen The address at which to store the length of + * the payload. This must not be \c NULL. + * \param output_max_len The length in bytes of the output buffer \p output. + * + * \return \c 0 on success. + * \return #MBEDTLS_ERR_RSA_OUTPUT_TOO_LARGE + * The output buffer is too small for the unpadded payload. + * \return #MBEDTLS_ERR_RSA_INVALID_PADDING + * The input doesn't contain properly formatted padding. + */ +static int mbedtls_ct_rsaes_pkcs1_v15_unpadding(unsigned char *input, + size_t ilen, + unsigned char *output, + size_t output_max_len, + size_t *olen) +{ + int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED; + size_t i, plaintext_max_size; + + /* The following variables take sensitive values: their value must + * not leak into the observable behavior of the function other than + * the designated outputs (output, olen, return value). Otherwise + * this would open the execution of the function to + * side-channel-based variants of the Bleichenbacher padding oracle + * attack. Potential side channels include overall timing, memory + * access patterns (especially visible to an adversary who has access + * to a shared memory cache), and branches (especially visible to + * an adversary who has access to a shared code cache or to a shared + * branch predictor). */ + size_t pad_count = 0; + mbedtls_ct_condition_t bad; + mbedtls_ct_condition_t pad_done; + size_t plaintext_size = 0; + mbedtls_ct_condition_t output_too_large; + + plaintext_max_size = (output_max_len > ilen - 11) ? ilen - 11 + : output_max_len; + + /* Check and get padding length in constant time and constant + * memory trace. The first byte must be 0. */ + bad = mbedtls_ct_bool(input[0]); + + + /* Decode EME-PKCS1-v1_5 padding: 0x00 || 0x02 || PS || 0x00 + * where PS must be at least 8 nonzero bytes. */ + bad = mbedtls_ct_bool_or(bad, mbedtls_ct_uint_ne(input[1], MBEDTLS_RSA_CRYPT)); + + /* Read the whole buffer. Set pad_done to nonzero if we find + * the 0x00 byte and remember the padding length in pad_count. */ + pad_done = MBEDTLS_CT_FALSE; + for (i = 2; i < ilen; i++) { + mbedtls_ct_condition_t found = mbedtls_ct_uint_eq(input[i], 0); + pad_done = mbedtls_ct_bool_or(pad_done, found); + pad_count += mbedtls_ct_uint_if_else_0(mbedtls_ct_bool_not(pad_done), 1); + } + + /* If pad_done is still zero, there's no data, only unfinished padding. */ + bad = mbedtls_ct_bool_or(bad, mbedtls_ct_bool_not(pad_done)); + + /* There must be at least 8 bytes of padding. */ + bad = mbedtls_ct_bool_or(bad, mbedtls_ct_uint_gt(8, pad_count)); + + /* If the padding is valid, set plaintext_size to the number of + * remaining bytes after stripping the padding. If the padding + * is invalid, avoid leaking this fact through the size of the + * output: use the maximum message size that fits in the output + * buffer. Do it without branches to avoid leaking the padding + * validity through timing. RSA keys are small enough that all the + * size_t values involved fit in unsigned int. */ + plaintext_size = mbedtls_ct_uint_if( + bad, (unsigned) plaintext_max_size, + (unsigned) (ilen - pad_count - 3)); + + /* Set output_too_large to 0 if the plaintext fits in the output + * buffer and to 1 otherwise. */ + output_too_large = mbedtls_ct_uint_gt(plaintext_size, + plaintext_max_size); + + /* Set ret without branches to avoid timing attacks. Return: + * - INVALID_PADDING if the padding is bad (bad != 0). + * - OUTPUT_TOO_LARGE if the padding is good but the decrypted + * plaintext does not fit in the output buffer. + * - 0 if the padding is correct. */ + ret = mbedtls_ct_error_if( + bad, + MBEDTLS_ERR_RSA_INVALID_PADDING, + mbedtls_ct_error_if_else_0(output_too_large, MBEDTLS_ERR_RSA_OUTPUT_TOO_LARGE) + ); + + /* If the padding is bad or the plaintext is too large, zero the + * data that we're about to copy to the output buffer. + * We need to copy the same amount of data + * from the same buffer whether the padding is good or not to + * avoid leaking the padding validity through overall timing or + * through memory or cache access patterns. */ + mbedtls_ct_zeroize_if(mbedtls_ct_bool_or(bad, output_too_large), input + 11, ilen - 11); + + /* If the plaintext is too large, truncate it to the buffer size. + * Copy anyway to avoid revealing the length through timing, because + * revealing the length is as bad as revealing the padding validity + * for a Bleichenbacher attack. */ + plaintext_size = mbedtls_ct_uint_if(output_too_large, + (unsigned) plaintext_max_size, + (unsigned) plaintext_size); + + /* Move the plaintext to the leftmost position where it can start in + * the working buffer, i.e. make it start plaintext_max_size from + * the end of the buffer. Do this with a memory access trace that + * does not depend on the plaintext size. After this move, the + * starting location of the plaintext is no longer sensitive + * information. */ + mbedtls_ct_memmove_left(input + ilen - plaintext_max_size, + plaintext_max_size, + plaintext_max_size - plaintext_size); + + /* Finally copy the decrypted plaintext plus trailing zeros into the output + * buffer. If output_max_len is 0, then output may be an invalid pointer + * and the result of memcpy() would be undefined; prevent undefined + * behavior making sure to depend only on output_max_len (the size of the + * user-provided output buffer), which is independent from plaintext + * length, validity of padding, success of the decryption, and other + * secrets. */ + if (output_max_len != 0) { + memcpy(output, input + ilen - plaintext_max_size, plaintext_max_size); + } + + /* Report the amount of data we copied to the output buffer. In case + * of errors (bad padding or output too large), the value of *olen + * when this function returns is not specified. Making it equivalent + * to the good case limits the risks of leaking the padding validity. */ + *olen = plaintext_size; + + return ret; +} + +#endif /* MBEDTLS_PKCS1_V15 && MBEDTLS_RSA_C && ! MBEDTLS_RSA_ALT */ + +#if !defined(MBEDTLS_RSA_ALT) int mbedtls_rsa_import(mbedtls_rsa_context *ctx, const mbedtls_mpi *N, @@ -73,7 +574,6 @@ int mbedtls_rsa_import(mbedtls_rsa_context *ctx, const mbedtls_mpi *D, const mbedtls_mpi *E) { int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED; - RSA_VALIDATE_RET(ctx != NULL); if ((N != NULL && (ret = mbedtls_mpi_copy(&ctx->N, N)) != 0) || (P != NULL && (ret = mbedtls_mpi_copy(&ctx->P, P)) != 0) || @@ -98,7 +598,6 @@ int mbedtls_rsa_import_raw(mbedtls_rsa_context *ctx, unsigned char const *E, size_t E_len) { int ret = 0; - RSA_VALIDATE_RET(ctx != NULL); if (N != NULL) { MBEDTLS_MPI_CHK(mbedtls_mpi_read_binary(&ctx->N, N, N_len)); @@ -228,8 +727,6 @@ int mbedtls_rsa_complete(mbedtls_rsa_context *ctx) #endif int n_missing, pq_missing, d_missing, is_pub, is_priv; - RSA_VALIDATE_RET(ctx != NULL); - have_N = (mbedtls_mpi_cmp_int(&ctx->N, 0) != 0); have_P = (mbedtls_mpi_cmp_int(&ctx->P, 0) != 0); have_Q = (mbedtls_mpi_cmp_int(&ctx->Q, 0) != 0); @@ -328,7 +825,6 @@ int mbedtls_rsa_export_raw(const mbedtls_rsa_context *ctx, { int ret = 0; int is_priv; - RSA_VALIDATE_RET(ctx != NULL); /* Check if key is private or public */ is_priv = @@ -378,7 +874,6 @@ int mbedtls_rsa_export(const mbedtls_rsa_context *ctx, { int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED; int is_priv; - RSA_VALIDATE_RET(ctx != NULL); /* Check if key is private or public */ is_priv = @@ -421,7 +916,6 @@ int mbedtls_rsa_export_crt(const mbedtls_rsa_context *ctx, { int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED; int is_priv; - RSA_VALIDATE_RET(ctx != NULL); /* Check if key is private or public */ is_priv = @@ -455,17 +949,12 @@ int mbedtls_rsa_export_crt(const mbedtls_rsa_context *ctx, /* * Initialize an RSA context */ -void mbedtls_rsa_init(mbedtls_rsa_context *ctx, - int padding, - int hash_id) +void mbedtls_rsa_init(mbedtls_rsa_context *ctx) { - RSA_VALIDATE(ctx != NULL); - RSA_VALIDATE(padding == MBEDTLS_RSA_PKCS_V15 || - padding == MBEDTLS_RSA_PKCS_V21); - memset(ctx, 0, sizeof(mbedtls_rsa_context)); - mbedtls_rsa_set_padding(ctx, padding, hash_id); + ctx->padding = MBEDTLS_RSA_PKCS_V15; + ctx->hash_id = MBEDTLS_MD_NONE; #if defined(MBEDTLS_THREADING_C) /* Set ctx->ver to nonzero to indicate that the mutex has been @@ -478,27 +967,71 @@ void mbedtls_rsa_init(mbedtls_rsa_context *ctx, /* * Set padding for an existing RSA context */ -void mbedtls_rsa_set_padding(mbedtls_rsa_context *ctx, int padding, - int hash_id) +int mbedtls_rsa_set_padding(mbedtls_rsa_context *ctx, int padding, + mbedtls_md_type_t hash_id) { - RSA_VALIDATE(ctx != NULL); - RSA_VALIDATE(padding == MBEDTLS_RSA_PKCS_V15 || - padding == MBEDTLS_RSA_PKCS_V21); + switch (padding) { +#if defined(MBEDTLS_PKCS1_V15) + case MBEDTLS_RSA_PKCS_V15: + break; +#endif + +#if defined(MBEDTLS_PKCS1_V21) + case MBEDTLS_RSA_PKCS_V21: + break; +#endif + default: + return MBEDTLS_ERR_RSA_INVALID_PADDING; + } + +#if defined(MBEDTLS_PKCS1_V21) + if ((padding == MBEDTLS_RSA_PKCS_V21) && + (hash_id != MBEDTLS_MD_NONE)) { + /* Just make sure this hash is supported in this build. */ + if (mbedtls_md_info_from_type(hash_id) == NULL) { + return MBEDTLS_ERR_RSA_INVALID_PADDING; + } + } +#endif /* MBEDTLS_PKCS1_V21 */ ctx->padding = padding; ctx->hash_id = hash_id; + + return 0; } /* - * Get length in bytes of RSA modulus + * Get padding mode of initialized RSA context + */ +int mbedtls_rsa_get_padding_mode(const mbedtls_rsa_context *ctx) +{ + return ctx->padding; +} + +/* + * Get hash identifier of mbedtls_md_type_t type */ +int mbedtls_rsa_get_md_alg(const mbedtls_rsa_context *ctx) +{ + return ctx->hash_id; +} + +/* + * Get length in bits of RSA modulus + */ +size_t mbedtls_rsa_get_bitlen(const mbedtls_rsa_context *ctx) +{ + return mbedtls_mpi_bitlen(&ctx->N); +} +/* + * Get length in bytes of RSA modulus + */ size_t mbedtls_rsa_get_len(const mbedtls_rsa_context *ctx) { return ctx->len; } - #if defined(MBEDTLS_GENPRIME) /* @@ -515,8 +1048,6 @@ int mbedtls_rsa_gen_key(mbedtls_rsa_context *ctx, int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED; mbedtls_mpi H, G, L; int prime_quality = 0; - RSA_VALIDATE_RET(ctx != NULL); - RSA_VALIDATE_RET(f_rng != NULL); /* * If the modulus is 1024 bit long or shorter, then the security strength of @@ -531,7 +1062,12 @@ int mbedtls_rsa_gen_key(mbedtls_rsa_context *ctx, mbedtls_mpi_init(&G); mbedtls_mpi_init(&L); - if (nbits < 128 || exponent < 3 || nbits % 2 != 0) { + if (exponent < 3 || nbits % 2 != 0) { + ret = MBEDTLS_ERR_RSA_BAD_INPUT_DATA; + goto cleanup; + } + + if (nbits < MBEDTLS_RSA_GEN_KEY_MIN_BITS) { ret = MBEDTLS_ERR_RSA_BAD_INPUT_DATA; goto cleanup; } @@ -631,8 +1167,6 @@ int mbedtls_rsa_gen_key(mbedtls_rsa_context *ctx, */ int mbedtls_rsa_check_pubkey(const mbedtls_rsa_context *ctx) { - RSA_VALIDATE_RET(ctx != NULL); - if (rsa_check_context(ctx, 0 /* public */, 0 /* no blinding */) != 0) { return MBEDTLS_ERR_RSA_KEY_CHECK_FAILED; } @@ -655,8 +1189,6 @@ int mbedtls_rsa_check_pubkey(const mbedtls_rsa_context *ctx) */ int mbedtls_rsa_check_privkey(const mbedtls_rsa_context *ctx) { - RSA_VALIDATE_RET(ctx != NULL); - if (mbedtls_rsa_check_pubkey(ctx) != 0 || rsa_check_context(ctx, 1 /* private */, 1 /* blinding */) != 0) { return MBEDTLS_ERR_RSA_KEY_CHECK_FAILED; @@ -683,9 +1215,6 @@ int mbedtls_rsa_check_privkey(const mbedtls_rsa_context *ctx) int mbedtls_rsa_check_pub_priv(const mbedtls_rsa_context *pub, const mbedtls_rsa_context *prv) { - RSA_VALIDATE_RET(pub != NULL); - RSA_VALIDATE_RET(prv != NULL); - if (mbedtls_rsa_check_pubkey(pub) != 0 || mbedtls_rsa_check_privkey(prv) != 0) { return MBEDTLS_ERR_RSA_KEY_CHECK_FAILED; @@ -709,9 +1238,6 @@ int mbedtls_rsa_public(mbedtls_rsa_context *ctx, int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED; size_t olen; mbedtls_mpi T; - RSA_VALIDATE_RET(ctx != NULL); - RSA_VALIDATE_RET(input != NULL); - RSA_VALIDATE_RET(output != NULL); if (rsa_check_context(ctx, 0 /* public */, 0 /* no blinding */)) { return MBEDTLS_ERR_RSA_BAD_INPUT_DATA; @@ -816,6 +1342,45 @@ static int rsa_prepare_blinding(mbedtls_rsa_context *ctx, return ret; } +/* + * Unblind + * T = T * Vf mod N + */ +static int rsa_unblind(mbedtls_mpi *T, mbedtls_mpi *Vf, const mbedtls_mpi *N) +{ + int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED; + const mbedtls_mpi_uint mm = mbedtls_mpi_core_montmul_init(N->p); + const size_t nlimbs = N->n; + const size_t tlimbs = mbedtls_mpi_core_montmul_working_limbs(nlimbs); + mbedtls_mpi RR, M_T; + + mbedtls_mpi_init(&RR); + mbedtls_mpi_init(&M_T); + + MBEDTLS_MPI_CHK(mbedtls_mpi_core_get_mont_r2_unsafe(&RR, N)); + MBEDTLS_MPI_CHK(mbedtls_mpi_grow(&M_T, tlimbs)); + + MBEDTLS_MPI_CHK(mbedtls_mpi_grow(T, nlimbs)); + MBEDTLS_MPI_CHK(mbedtls_mpi_grow(Vf, nlimbs)); + + /* T = T * Vf mod N + * Reminder: montmul(A, B, N) = A * B * R^-1 mod N + * Usually both operands are multiplied by R mod N beforehand (by calling + * `to_mont_rep()` on them), yielding a result that's also * R mod N (aka + * "in the Montgomery domain"). Here we only multiply one operand by R mod + * N, so the result is directly what we want - no need to call + * `from_mont_rep()` on it. */ + mbedtls_mpi_core_to_mont_rep(T->p, T->p, N->p, nlimbs, mm, RR.p, M_T.p); + mbedtls_mpi_core_montmul(T->p, T->p, Vf->p, nlimbs, N->p, nlimbs, mm, M_T.p); + +cleanup: + + mbedtls_mpi_free(&RR); + mbedtls_mpi_free(&M_T); + + return ret; +} + /* * Exponent blinding supposed to prevent side-channel attacks using multiple * traces of measurements to recover the RSA key. The more collisions are there, @@ -863,30 +1428,21 @@ int mbedtls_rsa_private(mbedtls_rsa_context *ctx, /* Temporaries holding the blinded exponents for * the mod p resp. mod q computation (if used). */ mbedtls_mpi DP_blind, DQ_blind; - - /* Pointers to actual exponents to be used - either the unblinded - * or the blinded ones, depending on the presence of a PRNG. */ - mbedtls_mpi *DP = &ctx->DP; - mbedtls_mpi *DQ = &ctx->DQ; #else /* Temporary holding the blinded exponent (if used). */ mbedtls_mpi D_blind; - - /* Pointer to actual exponent to be used - either the unblinded - * or the blinded one, depending on the presence of a PRNG. */ - mbedtls_mpi *D = &ctx->D; #endif /* MBEDTLS_RSA_NO_CRT */ /* Temporaries holding the initial input and the double * checked result; should be the same in the end. */ - mbedtls_mpi I, C; + mbedtls_mpi input_blinded, check_result_blinded; - RSA_VALIDATE_RET(ctx != NULL); - RSA_VALIDATE_RET(input != NULL); - RSA_VALIDATE_RET(output != NULL); + if (f_rng == NULL) { + return MBEDTLS_ERR_RSA_BAD_INPUT_DATA; + } if (rsa_check_context(ctx, 1 /* private key checks */, - f_rng != NULL /* blinding y/n */) != 0) { + 1 /* blinding on */) != 0) { return MBEDTLS_ERR_RSA_BAD_INPUT_DATA; } @@ -903,21 +1459,19 @@ int mbedtls_rsa_private(mbedtls_rsa_context *ctx, mbedtls_mpi_init(&Q1); mbedtls_mpi_init(&R); - if (f_rng != NULL) { #if defined(MBEDTLS_RSA_NO_CRT) - mbedtls_mpi_init(&D_blind); + mbedtls_mpi_init(&D_blind); #else - mbedtls_mpi_init(&DP_blind); - mbedtls_mpi_init(&DQ_blind); + mbedtls_mpi_init(&DP_blind); + mbedtls_mpi_init(&DQ_blind); #endif - } #if !defined(MBEDTLS_RSA_NO_CRT) mbedtls_mpi_init(&TP); mbedtls_mpi_init(&TQ); #endif - mbedtls_mpi_init(&I); - mbedtls_mpi_init(&C); + mbedtls_mpi_init(&input_blinded); + mbedtls_mpi_init(&check_result_blinded); /* End of MPI initialization */ @@ -927,61 +1481,53 @@ int mbedtls_rsa_private(mbedtls_rsa_context *ctx, goto cleanup; } - MBEDTLS_MPI_CHK(mbedtls_mpi_copy(&I, &T)); + /* + * Blinding + * T = T * Vi mod N + */ + MBEDTLS_MPI_CHK(rsa_prepare_blinding(ctx, f_rng, p_rng)); + MBEDTLS_MPI_CHK(mbedtls_mpi_mul_mpi(&T, &T, &ctx->Vi)); + MBEDTLS_MPI_CHK(mbedtls_mpi_mod_mpi(&T, &T, &ctx->N)); - if (f_rng != NULL) { - /* - * Blinding - * T = T * Vi mod N - */ - MBEDTLS_MPI_CHK(rsa_prepare_blinding(ctx, f_rng, p_rng)); - MBEDTLS_MPI_CHK(mbedtls_mpi_mul_mpi(&T, &T, &ctx->Vi)); - MBEDTLS_MPI_CHK(mbedtls_mpi_mod_mpi(&T, &T, &ctx->N)); + MBEDTLS_MPI_CHK(mbedtls_mpi_copy(&input_blinded, &T)); - /* - * Exponent blinding - */ - MBEDTLS_MPI_CHK(mbedtls_mpi_sub_int(&P1, &ctx->P, 1)); - MBEDTLS_MPI_CHK(mbedtls_mpi_sub_int(&Q1, &ctx->Q, 1)); + /* + * Exponent blinding + */ + MBEDTLS_MPI_CHK(mbedtls_mpi_sub_int(&P1, &ctx->P, 1)); + MBEDTLS_MPI_CHK(mbedtls_mpi_sub_int(&Q1, &ctx->Q, 1)); #if defined(MBEDTLS_RSA_NO_CRT) - /* - * D_blind = ( P - 1 ) * ( Q - 1 ) * R + D - */ - MBEDTLS_MPI_CHK(mbedtls_mpi_fill_random(&R, RSA_EXPONENT_BLINDING, - f_rng, p_rng)); - MBEDTLS_MPI_CHK(mbedtls_mpi_mul_mpi(&D_blind, &P1, &Q1)); - MBEDTLS_MPI_CHK(mbedtls_mpi_mul_mpi(&D_blind, &D_blind, &R)); - MBEDTLS_MPI_CHK(mbedtls_mpi_add_mpi(&D_blind, &D_blind, &ctx->D)); - - D = &D_blind; + /* + * D_blind = ( P - 1 ) * ( Q - 1 ) * R + D + */ + MBEDTLS_MPI_CHK(mbedtls_mpi_fill_random(&R, RSA_EXPONENT_BLINDING, + f_rng, p_rng)); + MBEDTLS_MPI_CHK(mbedtls_mpi_mul_mpi(&D_blind, &P1, &Q1)); + MBEDTLS_MPI_CHK(mbedtls_mpi_mul_mpi(&D_blind, &D_blind, &R)); + MBEDTLS_MPI_CHK(mbedtls_mpi_add_mpi(&D_blind, &D_blind, &ctx->D)); #else - /* - * DP_blind = ( P - 1 ) * R + DP - */ - MBEDTLS_MPI_CHK(mbedtls_mpi_fill_random(&R, RSA_EXPONENT_BLINDING, - f_rng, p_rng)); - MBEDTLS_MPI_CHK(mbedtls_mpi_mul_mpi(&DP_blind, &P1, &R)); - MBEDTLS_MPI_CHK(mbedtls_mpi_add_mpi(&DP_blind, &DP_blind, - &ctx->DP)); - - DP = &DP_blind; - - /* - * DQ_blind = ( Q - 1 ) * R + DQ - */ - MBEDTLS_MPI_CHK(mbedtls_mpi_fill_random(&R, RSA_EXPONENT_BLINDING, - f_rng, p_rng)); - MBEDTLS_MPI_CHK(mbedtls_mpi_mul_mpi(&DQ_blind, &Q1, &R)); - MBEDTLS_MPI_CHK(mbedtls_mpi_add_mpi(&DQ_blind, &DQ_blind, - &ctx->DQ)); + /* + * DP_blind = ( P - 1 ) * R + DP + */ + MBEDTLS_MPI_CHK(mbedtls_mpi_fill_random(&R, RSA_EXPONENT_BLINDING, + f_rng, p_rng)); + MBEDTLS_MPI_CHK(mbedtls_mpi_mul_mpi(&DP_blind, &P1, &R)); + MBEDTLS_MPI_CHK(mbedtls_mpi_add_mpi(&DP_blind, &DP_blind, + &ctx->DP)); - DQ = &DQ_blind; + /* + * DQ_blind = ( Q - 1 ) * R + DQ + */ + MBEDTLS_MPI_CHK(mbedtls_mpi_fill_random(&R, RSA_EXPONENT_BLINDING, + f_rng, p_rng)); + MBEDTLS_MPI_CHK(mbedtls_mpi_mul_mpi(&DQ_blind, &Q1, &R)); + MBEDTLS_MPI_CHK(mbedtls_mpi_add_mpi(&DQ_blind, &DQ_blind, + &ctx->DQ)); #endif /* MBEDTLS_RSA_NO_CRT */ - } #if defined(MBEDTLS_RSA_NO_CRT) - MBEDTLS_MPI_CHK(mbedtls_mpi_exp_mod(&T, &T, D, &ctx->N, &ctx->RN)); + MBEDTLS_MPI_CHK(mbedtls_mpi_exp_mod(&T, &T, &D_blind, &ctx->N, &ctx->RN)); #else /* * Faster decryption using the CRT @@ -990,8 +1536,8 @@ int mbedtls_rsa_private(mbedtls_rsa_context *ctx, * TQ = input ^ dQ mod Q */ - MBEDTLS_MPI_CHK(mbedtls_mpi_exp_mod(&TP, &T, DP, &ctx->P, &ctx->RP)); - MBEDTLS_MPI_CHK(mbedtls_mpi_exp_mod(&TQ, &T, DQ, &ctx->Q, &ctx->RQ)); + MBEDTLS_MPI_CHK(mbedtls_mpi_exp_mod(&TP, &T, &DP_blind, &ctx->P, &ctx->RP)); + MBEDTLS_MPI_CHK(mbedtls_mpi_exp_mod(&TQ, &T, &DQ_blind, &ctx->Q, &ctx->RQ)); /* * T = (TP - TQ) * (Q^-1 mod P) mod P @@ -1007,23 +1553,20 @@ int mbedtls_rsa_private(mbedtls_rsa_context *ctx, MBEDTLS_MPI_CHK(mbedtls_mpi_add_mpi(&T, &TQ, &TP)); #endif /* MBEDTLS_RSA_NO_CRT */ - if (f_rng != NULL) { - /* - * Unblind - * T = T * Vf mod N - */ - MBEDTLS_MPI_CHK(mbedtls_mpi_mul_mpi(&T, &T, &ctx->Vf)); - MBEDTLS_MPI_CHK(mbedtls_mpi_mod_mpi(&T, &T, &ctx->N)); - } - /* Verify the result to prevent glitching attacks. */ - MBEDTLS_MPI_CHK(mbedtls_mpi_exp_mod(&C, &T, &ctx->E, + MBEDTLS_MPI_CHK(mbedtls_mpi_exp_mod(&check_result_blinded, &T, &ctx->E, &ctx->N, &ctx->RN)); - if (mbedtls_mpi_cmp_mpi(&C, &I) != 0) { + if (mbedtls_mpi_cmp_mpi(&check_result_blinded, &input_blinded) != 0) { ret = MBEDTLS_ERR_RSA_VERIFY_FAILED; goto cleanup; } + /* + * Unblind + * T = T * Vf mod N + */ + MBEDTLS_MPI_CHK(rsa_unblind(&T, &ctx->Vf, &ctx->N)); + olen = ctx->len; MBEDTLS_MPI_CHK(mbedtls_mpi_write_binary(&T, output, olen)); @@ -1038,14 +1581,12 @@ int mbedtls_rsa_private(mbedtls_rsa_context *ctx, mbedtls_mpi_free(&Q1); mbedtls_mpi_free(&R); - if (f_rng != NULL) { #if defined(MBEDTLS_RSA_NO_CRT) - mbedtls_mpi_free(&D_blind); + mbedtls_mpi_free(&D_blind); #else - mbedtls_mpi_free(&DP_blind); - mbedtls_mpi_free(&DQ_blind); + mbedtls_mpi_free(&DP_blind); + mbedtls_mpi_free(&DQ_blind); #endif - } mbedtls_mpi_free(&T); @@ -1053,8 +1594,8 @@ int mbedtls_rsa_private(mbedtls_rsa_context *ctx, mbedtls_mpi_free(&TP); mbedtls_mpi_free(&TQ); #endif - mbedtls_mpi_free(&C); - mbedtls_mpi_free(&I); + mbedtls_mpi_free(&check_result_blinded); + mbedtls_mpi_free(&input_blinded); if (ret != 0 && ret >= -0x007f) { return MBEDTLS_ERROR_ADD(MBEDTLS_ERR_RSA_PRIVATE_FAILED, ret); @@ -1071,22 +1612,35 @@ int mbedtls_rsa_private(mbedtls_rsa_context *ctx, * \param dlen length of destination buffer * \param src source of the mask generation * \param slen length of the source buffer - * \param md_ctx message digest context to use + * \param md_alg message digest to use */ static int mgf_mask(unsigned char *dst, size_t dlen, unsigned char *src, - size_t slen, mbedtls_md_context_t *md_ctx) + size_t slen, mbedtls_md_type_t md_alg) { - unsigned char mask[MBEDTLS_MD_MAX_SIZE]; unsigned char counter[4]; unsigned char *p; unsigned int hlen; size_t i, use_len; + unsigned char mask[MBEDTLS_MD_MAX_SIZE]; int ret = 0; + const mbedtls_md_info_t *md_info; + mbedtls_md_context_t md_ctx; - memset(mask, 0, MBEDTLS_MD_MAX_SIZE); - memset(counter, 0, 4); + mbedtls_md_init(&md_ctx); + md_info = mbedtls_md_info_from_type(md_alg); + if (md_info == NULL) { + return MBEDTLS_ERR_RSA_BAD_INPUT_DATA; + } + + mbedtls_md_init(&md_ctx); + if ((ret = mbedtls_md_setup(&md_ctx, md_info, 0)) != 0) { + goto exit; + } + + hlen = mbedtls_md_get_size(md_info); - hlen = mbedtls_md_get_size(md_ctx->md_info); + memset(mask, 0, sizeof(mask)); + memset(counter, 0, 4); /* Generate and apply dbMask */ p = dst; @@ -1097,16 +1651,16 @@ static int mgf_mask(unsigned char *dst, size_t dlen, unsigned char *src, use_len = dlen; } - if ((ret = mbedtls_md_starts(md_ctx)) != 0) { + if ((ret = mbedtls_md_starts(&md_ctx)) != 0) { goto exit; } - if ((ret = mbedtls_md_update(md_ctx, src, slen)) != 0) { + if ((ret = mbedtls_md_update(&md_ctx, src, slen)) != 0) { goto exit; } - if ((ret = mbedtls_md_update(md_ctx, counter, 4)) != 0) { + if ((ret = mbedtls_md_update(&md_ctx, counter, 4)) != 0) { goto exit; } - if ((ret = mbedtls_md_finish(md_ctx, mask)) != 0) { + if ((ret = mbedtls_md_finish(&md_ctx, mask)) != 0) { goto exit; } @@ -1121,9 +1675,82 @@ static int mgf_mask(unsigned char *dst, size_t dlen, unsigned char *src, exit: mbedtls_platform_zeroize(mask, sizeof(mask)); + mbedtls_md_free(&md_ctx); + + return ret; +} + +/** + * Generate Hash(M') as in RFC 8017 page 43 points 5 and 6. + * + * \param hash the input hash + * \param hlen length of the input hash + * \param salt the input salt + * \param slen length of the input salt + * \param out the output buffer - must be large enough for \p md_alg + * \param md_alg message digest to use + */ +static int hash_mprime(const unsigned char *hash, size_t hlen, + const unsigned char *salt, size_t slen, + unsigned char *out, mbedtls_md_type_t md_alg) +{ + const unsigned char zeros[8] = { 0, 0, 0, 0, 0, 0, 0, 0 }; + + mbedtls_md_context_t md_ctx; + int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED; + + const mbedtls_md_info_t *md_info = mbedtls_md_info_from_type(md_alg); + if (md_info == NULL) { + return MBEDTLS_ERR_RSA_BAD_INPUT_DATA; + } + + mbedtls_md_init(&md_ctx); + if ((ret = mbedtls_md_setup(&md_ctx, md_info, 0)) != 0) { + goto exit; + } + if ((ret = mbedtls_md_starts(&md_ctx)) != 0) { + goto exit; + } + if ((ret = mbedtls_md_update(&md_ctx, zeros, sizeof(zeros))) != 0) { + goto exit; + } + if ((ret = mbedtls_md_update(&md_ctx, hash, hlen)) != 0) { + goto exit; + } + if ((ret = mbedtls_md_update(&md_ctx, salt, slen)) != 0) { + goto exit; + } + if ((ret = mbedtls_md_finish(&md_ctx, out)) != 0) { + goto exit; + } + +exit: + mbedtls_md_free(&md_ctx); return ret; } + +/** + * Compute a hash. + * + * \param md_alg algorithm to use + * \param input input message to hash + * \param ilen input length + * \param output the output buffer - must be large enough for \p md_alg + */ +static int compute_hash(mbedtls_md_type_t md_alg, + const unsigned char *input, size_t ilen, + unsigned char *output) +{ + const mbedtls_md_info_t *md_info; + + md_info = mbedtls_md_info_from_type(md_alg); + if (md_info == NULL) { + return MBEDTLS_ERR_RSA_BAD_INPUT_DATA; + } + + return mbedtls_md(md_info, input, ilen, output); +} #endif /* MBEDTLS_PKCS1_V21 */ #if defined(MBEDTLS_PKCS1_V21) @@ -1133,7 +1760,6 @@ static int mgf_mask(unsigned char *dst, size_t dlen, unsigned char *src, int mbedtls_rsa_rsaes_oaep_encrypt(mbedtls_rsa_context *ctx, int (*f_rng)(void *, unsigned char *, size_t), void *p_rng, - int mode, const unsigned char *label, size_t label_len, size_t ilen, const unsigned char *input, @@ -1143,31 +1769,17 @@ int mbedtls_rsa_rsaes_oaep_encrypt(mbedtls_rsa_context *ctx, int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED; unsigned char *p = output; unsigned int hlen; - const mbedtls_md_info_t *md_info; - mbedtls_md_context_t md_ctx; - - RSA_VALIDATE_RET(ctx != NULL); - RSA_VALIDATE_RET(mode == MBEDTLS_RSA_PRIVATE || - mode == MBEDTLS_RSA_PUBLIC); - RSA_VALIDATE_RET(output != NULL); - RSA_VALIDATE_RET(ilen == 0 || input != NULL); - RSA_VALIDATE_RET(label_len == 0 || label != NULL); - - if (mode == MBEDTLS_RSA_PRIVATE && ctx->padding != MBEDTLS_RSA_PKCS_V21) { - return MBEDTLS_ERR_RSA_BAD_INPUT_DATA; - } if (f_rng == NULL) { return MBEDTLS_ERR_RSA_BAD_INPUT_DATA; } - md_info = mbedtls_md_info_from_type((mbedtls_md_type_t) ctx->hash_id); - if (md_info == NULL) { + hlen = mbedtls_md_get_size_from_type((mbedtls_md_type_t) ctx->hash_id); + if (hlen == 0) { return MBEDTLS_ERR_RSA_BAD_INPUT_DATA; } olen = ctx->len; - hlen = mbedtls_md_get_size(md_info); /* first comparison checks for overflow */ if (ilen + 2 * hlen + 2 < ilen || olen < ilen + 2 * hlen + 2) { @@ -1186,7 +1798,8 @@ int mbedtls_rsa_rsaes_oaep_encrypt(mbedtls_rsa_context *ctx, p += hlen; /* Construct DB */ - if ((ret = mbedtls_md(md_info, label, label_len, p)) != 0) { + ret = compute_hash((mbedtls_md_type_t) ctx->hash_id, label, label_len, p); + if (ret != 0) { return ret; } p += hlen; @@ -1196,33 +1809,19 @@ int mbedtls_rsa_rsaes_oaep_encrypt(mbedtls_rsa_context *ctx, memcpy(p, input, ilen); } - mbedtls_md_init(&md_ctx); - if ((ret = mbedtls_md_setup(&md_ctx, md_info, 0)) != 0) { - goto exit; - } - /* maskedDB: Apply dbMask to DB */ if ((ret = mgf_mask(output + hlen + 1, olen - hlen - 1, output + 1, hlen, - &md_ctx)) != 0) { - goto exit; + (mbedtls_md_type_t) ctx->hash_id)) != 0) { + return ret; } /* maskedSeed: Apply seedMask to seed */ if ((ret = mgf_mask(output + 1, hlen, output + hlen + 1, olen - hlen - 1, - &md_ctx)) != 0) { - goto exit; - } - -exit: - mbedtls_md_free(&md_ctx); - - if (ret != 0) { + (mbedtls_md_type_t) ctx->hash_id)) != 0) { return ret; } - return (mode == MBEDTLS_RSA_PUBLIC) - ? mbedtls_rsa_public(ctx, output, output) - : mbedtls_rsa_private(ctx, f_rng, p_rng, output, output); + return mbedtls_rsa_public(ctx, output, output); } #endif /* MBEDTLS_PKCS1_V21 */ @@ -1232,8 +1831,7 @@ int mbedtls_rsa_rsaes_oaep_encrypt(mbedtls_rsa_context *ctx, */ int mbedtls_rsa_rsaes_pkcs1_v15_encrypt(mbedtls_rsa_context *ctx, int (*f_rng)(void *, unsigned char *, size_t), - void *p_rng, - int mode, size_t ilen, + void *p_rng, size_t ilen, const unsigned char *input, unsigned char *output) { @@ -1241,16 +1839,6 @@ int mbedtls_rsa_rsaes_pkcs1_v15_encrypt(mbedtls_rsa_context *ctx, int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED; unsigned char *p = output; - RSA_VALIDATE_RET(ctx != NULL); - RSA_VALIDATE_RET(mode == MBEDTLS_RSA_PRIVATE || - mode == MBEDTLS_RSA_PUBLIC); - RSA_VALIDATE_RET(output != NULL); - RSA_VALIDATE_RET(ilen == 0 || input != NULL); - - if (mode == MBEDTLS_RSA_PRIVATE && ctx->padding != MBEDTLS_RSA_PKCS_V15) { - return MBEDTLS_ERR_RSA_BAD_INPUT_DATA; - } - olen = ctx->len; /* first comparison checks for overflow */ @@ -1261,33 +1849,26 @@ int mbedtls_rsa_rsaes_pkcs1_v15_encrypt(mbedtls_rsa_context *ctx, nb_pad = olen - 3 - ilen; *p++ = 0; - if (mode == MBEDTLS_RSA_PUBLIC) { - if (f_rng == NULL) { - return MBEDTLS_ERR_RSA_BAD_INPUT_DATA; - } - *p++ = MBEDTLS_RSA_CRYPT; + if (f_rng == NULL) { + return MBEDTLS_ERR_RSA_BAD_INPUT_DATA; + } - while (nb_pad-- > 0) { - int rng_dl = 100; + *p++ = MBEDTLS_RSA_CRYPT; - do { - ret = f_rng(p_rng, p, 1); - } while (*p == 0 && --rng_dl && ret == 0); + while (nb_pad-- > 0) { + int rng_dl = 100; - /* Check if RNG failed to generate data */ - if (rng_dl == 0 || ret != 0) { - return MBEDTLS_ERROR_ADD(MBEDTLS_ERR_RSA_RNG_FAILED, ret); - } + do { + ret = f_rng(p_rng, p, 1); + } while (*p == 0 && --rng_dl && ret == 0); - p++; + /* Check if RNG failed to generate data */ + if (rng_dl == 0 || ret != 0) { + return MBEDTLS_ERROR_ADD(MBEDTLS_ERR_RSA_RNG_FAILED, ret); } - } else { - *p++ = MBEDTLS_RSA_SIGN; - while (nb_pad-- > 0) { - *p++ = 0xFF; - } + p++; } *p++ = 0; @@ -1295,9 +1876,7 @@ int mbedtls_rsa_rsaes_pkcs1_v15_encrypt(mbedtls_rsa_context *ctx, memcpy(p, input, ilen); } - return (mode == MBEDTLS_RSA_PUBLIC) - ? mbedtls_rsa_public(ctx, output, output) - : mbedtls_rsa_private(ctx, f_rng, p_rng, output, output); + return mbedtls_rsa_public(ctx, output, output); } #endif /* MBEDTLS_PKCS1_V15 */ @@ -1307,26 +1886,20 @@ int mbedtls_rsa_rsaes_pkcs1_v15_encrypt(mbedtls_rsa_context *ctx, int mbedtls_rsa_pkcs1_encrypt(mbedtls_rsa_context *ctx, int (*f_rng)(void *, unsigned char *, size_t), void *p_rng, - int mode, size_t ilen, + size_t ilen, const unsigned char *input, unsigned char *output) { - RSA_VALIDATE_RET(ctx != NULL); - RSA_VALIDATE_RET(mode == MBEDTLS_RSA_PRIVATE || - mode == MBEDTLS_RSA_PUBLIC); - RSA_VALIDATE_RET(output != NULL); - RSA_VALIDATE_RET(ilen == 0 || input != NULL); - switch (ctx->padding) { #if defined(MBEDTLS_PKCS1_V15) case MBEDTLS_RSA_PKCS_V15: - return mbedtls_rsa_rsaes_pkcs1_v15_encrypt(ctx, f_rng, p_rng, mode, ilen, - input, output); + return mbedtls_rsa_rsaes_pkcs1_v15_encrypt(ctx, f_rng, p_rng, + ilen, input, output); #endif #if defined(MBEDTLS_PKCS1_V21) case MBEDTLS_RSA_PKCS_V21: - return mbedtls_rsa_rsaes_oaep_encrypt(ctx, f_rng, p_rng, mode, NULL, 0, + return mbedtls_rsa_rsaes_oaep_encrypt(ctx, f_rng, p_rng, NULL, 0, ilen, input, output); #endif @@ -1342,7 +1915,6 @@ int mbedtls_rsa_pkcs1_encrypt(mbedtls_rsa_context *ctx, int mbedtls_rsa_rsaes_oaep_decrypt(mbedtls_rsa_context *ctx, int (*f_rng)(void *, unsigned char *, size_t), void *p_rng, - int mode, const unsigned char *label, size_t label_len, size_t *olen, const unsigned char *input, @@ -1351,26 +1923,16 @@ int mbedtls_rsa_rsaes_oaep_decrypt(mbedtls_rsa_context *ctx, { int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED; size_t ilen, i, pad_len; - unsigned char *p, pad_done; - int bad; + unsigned char *p; + mbedtls_ct_condition_t bad, in_padding; unsigned char buf[MBEDTLS_MPI_MAX_SIZE]; unsigned char lhash[MBEDTLS_MD_MAX_SIZE]; unsigned int hlen; - const mbedtls_md_info_t *md_info; - mbedtls_md_context_t md_ctx; - - RSA_VALIDATE_RET(ctx != NULL); - RSA_VALIDATE_RET(mode == MBEDTLS_RSA_PRIVATE || - mode == MBEDTLS_RSA_PUBLIC); - RSA_VALIDATE_RET(output_max_len == 0 || output != NULL); - RSA_VALIDATE_RET(label_len == 0 || label != NULL); - RSA_VALIDATE_RET(input != NULL); - RSA_VALIDATE_RET(olen != NULL); /* * Parameters sanity checks */ - if (mode == MBEDTLS_RSA_PRIVATE && ctx->padding != MBEDTLS_RSA_PKCS_V21) { + if (ctx->padding != MBEDTLS_RSA_PKCS_V21) { return MBEDTLS_ERR_RSA_BAD_INPUT_DATA; } @@ -1380,13 +1942,11 @@ int mbedtls_rsa_rsaes_oaep_decrypt(mbedtls_rsa_context *ctx, return MBEDTLS_ERR_RSA_BAD_INPUT_DATA; } - md_info = mbedtls_md_info_from_type((mbedtls_md_type_t) ctx->hash_id); - if (md_info == NULL) { + hlen = mbedtls_md_get_size_from_type((mbedtls_md_type_t) ctx->hash_id); + if (hlen == 0) { return MBEDTLS_ERR_RSA_BAD_INPUT_DATA; } - hlen = mbedtls_md_get_size(md_info); - // checking for integer underflow if (2 * hlen + 2 > ilen) { return MBEDTLS_ERR_RSA_BAD_INPUT_DATA; @@ -1395,9 +1955,7 @@ int mbedtls_rsa_rsaes_oaep_decrypt(mbedtls_rsa_context *ctx, /* * RSA operation */ - ret = (mode == MBEDTLS_RSA_PUBLIC) - ? mbedtls_rsa_public(ctx, input, buf) - : mbedtls_rsa_private(ctx, f_rng, p_rng, input, buf); + ret = mbedtls_rsa_private(ctx, f_rng, p_rng, input, buf); if (ret != 0) { goto cleanup; @@ -1406,26 +1964,19 @@ int mbedtls_rsa_rsaes_oaep_decrypt(mbedtls_rsa_context *ctx, /* * Unmask data and generate lHash */ - mbedtls_md_init(&md_ctx); - if ((ret = mbedtls_md_setup(&md_ctx, md_info, 0)) != 0) { - mbedtls_md_free(&md_ctx); - goto cleanup; - } - /* seed: Apply seedMask to maskedSeed */ if ((ret = mgf_mask(buf + 1, hlen, buf + hlen + 1, ilen - hlen - 1, - &md_ctx)) != 0 || + (mbedtls_md_type_t) ctx->hash_id)) != 0 || /* DB: Apply dbMask to maskedDB */ (ret = mgf_mask(buf + hlen + 1, ilen - hlen - 1, buf + 1, hlen, - &md_ctx)) != 0) { - mbedtls_md_free(&md_ctx); + (mbedtls_md_type_t) ctx->hash_id)) != 0) { goto cleanup; } - mbedtls_md_free(&md_ctx); - /* Generate lHash */ - if ((ret = mbedtls_md(md_info, label, label_len, lhash)) != 0) { + ret = compute_hash((mbedtls_md_type_t) ctx->hash_id, + label, label_len, lhash); + if (ret != 0) { goto cleanup; } @@ -1433,27 +1984,26 @@ int mbedtls_rsa_rsaes_oaep_decrypt(mbedtls_rsa_context *ctx, * Check contents, in "constant-time" */ p = buf; - bad = 0; - bad |= *p++; /* First byte must be 0 */ + bad = mbedtls_ct_bool(*p++); /* First byte must be 0 */ p += hlen; /* Skip seed */ /* Check lHash */ - bad |= mbedtls_ct_memcmp(lhash, p, hlen); + bad = mbedtls_ct_bool_or(bad, mbedtls_ct_bool(mbedtls_ct_memcmp(lhash, p, hlen))); p += hlen; /* Get zero-padding len, but always read till end of buffer * (minus one, for the 01 byte) */ pad_len = 0; - pad_done = 0; + in_padding = MBEDTLS_CT_TRUE; for (i = 0; i < ilen - 2 * hlen - 2; i++) { - pad_done |= p[i]; - pad_len += ((pad_done | (unsigned char) -pad_done) >> 7) ^ 1; + in_padding = mbedtls_ct_bool_and(in_padding, mbedtls_ct_uint_eq(p[i], 0)); + pad_len += mbedtls_ct_uint_if_else_0(in_padding, 1); } p += pad_len; - bad |= *p++ ^ 0x01; + bad = mbedtls_ct_bool_or(bad, mbedtls_ct_uint_ne(*p++, 0x01)); /* * The only information "leaked" is whether the padding was correct or not @@ -1461,17 +2011,17 @@ int mbedtls_rsa_rsaes_oaep_decrypt(mbedtls_rsa_context *ctx, * recommendations in PKCS#1 v2.2: an opponent cannot distinguish between * the different error conditions. */ - if (bad != 0) { + if (bad != MBEDTLS_CT_FALSE) { ret = MBEDTLS_ERR_RSA_INVALID_PADDING; goto cleanup; } - if (ilen - (p - buf) > output_max_len) { + if (ilen - ((size_t) (p - buf)) > output_max_len) { ret = MBEDTLS_ERR_RSA_OUTPUT_TOO_LARGE; goto cleanup; } - *olen = ilen - (p - buf); + *olen = ilen - ((size_t) (p - buf)); if (*olen != 0) { memcpy(output, p, *olen); } @@ -1492,7 +2042,6 @@ int mbedtls_rsa_rsaes_oaep_decrypt(mbedtls_rsa_context *ctx, int mbedtls_rsa_rsaes_pkcs1_v15_decrypt(mbedtls_rsa_context *ctx, int (*f_rng)(void *, unsigned char *, size_t), void *p_rng, - int mode, size_t *olen, const unsigned char *input, unsigned char *output, @@ -1502,16 +2051,9 @@ int mbedtls_rsa_rsaes_pkcs1_v15_decrypt(mbedtls_rsa_context *ctx, size_t ilen; unsigned char buf[MBEDTLS_MPI_MAX_SIZE]; - RSA_VALIDATE_RET(ctx != NULL); - RSA_VALIDATE_RET(mode == MBEDTLS_RSA_PRIVATE || - mode == MBEDTLS_RSA_PUBLIC); - RSA_VALIDATE_RET(output_max_len == 0 || output != NULL); - RSA_VALIDATE_RET(input != NULL); - RSA_VALIDATE_RET(olen != NULL); - ilen = ctx->len; - if (mode == MBEDTLS_RSA_PRIVATE && ctx->padding != MBEDTLS_RSA_PKCS_V15) { + if (ctx->padding != MBEDTLS_RSA_PKCS_V15) { return MBEDTLS_ERR_RSA_BAD_INPUT_DATA; } @@ -1519,15 +2061,13 @@ int mbedtls_rsa_rsaes_pkcs1_v15_decrypt(mbedtls_rsa_context *ctx, return MBEDTLS_ERR_RSA_BAD_INPUT_DATA; } - ret = (mode == MBEDTLS_RSA_PUBLIC) - ? mbedtls_rsa_public(ctx, input, buf) - : mbedtls_rsa_private(ctx, f_rng, p_rng, input, buf); + ret = mbedtls_rsa_private(ctx, f_rng, p_rng, input, buf); if (ret != 0) { goto cleanup; } - ret = mbedtls_ct_rsaes_pkcs1_v15_unpadding(mode, buf, ilen, + ret = mbedtls_ct_rsaes_pkcs1_v15_unpadding(buf, ilen, output, output_max_len, olen); cleanup: @@ -1543,28 +2083,21 @@ int mbedtls_rsa_rsaes_pkcs1_v15_decrypt(mbedtls_rsa_context *ctx, int mbedtls_rsa_pkcs1_decrypt(mbedtls_rsa_context *ctx, int (*f_rng)(void *, unsigned char *, size_t), void *p_rng, - int mode, size_t *olen, + size_t *olen, const unsigned char *input, unsigned char *output, size_t output_max_len) { - RSA_VALIDATE_RET(ctx != NULL); - RSA_VALIDATE_RET(mode == MBEDTLS_RSA_PRIVATE || - mode == MBEDTLS_RSA_PUBLIC); - RSA_VALIDATE_RET(output_max_len == 0 || output != NULL); - RSA_VALIDATE_RET(input != NULL); - RSA_VALIDATE_RET(olen != NULL); - switch (ctx->padding) { #if defined(MBEDTLS_PKCS1_V15) case MBEDTLS_RSA_PKCS_V15: - return mbedtls_rsa_rsaes_pkcs1_v15_decrypt(ctx, f_rng, p_rng, mode, olen, + return mbedtls_rsa_rsaes_pkcs1_v15_decrypt(ctx, f_rng, p_rng, olen, input, output, output_max_len); #endif #if defined(MBEDTLS_PKCS1_V21) case MBEDTLS_RSA_PKCS_V21: - return mbedtls_rsa_rsaes_oaep_decrypt(ctx, f_rng, p_rng, mode, NULL, 0, + return mbedtls_rsa_rsaes_oaep_decrypt(ctx, f_rng, p_rng, NULL, 0, olen, input, output, output_max_len); #endif @@ -1575,15 +2108,14 @@ int mbedtls_rsa_pkcs1_decrypt(mbedtls_rsa_context *ctx, } #if defined(MBEDTLS_PKCS1_V21) -static int rsa_rsassa_pss_sign(mbedtls_rsa_context *ctx, - int (*f_rng)(void *, unsigned char *, size_t), - void *p_rng, - int mode, - mbedtls_md_type_t md_alg, - unsigned int hashlen, - const unsigned char *hash, - int saltlen, - unsigned char *sig) +static int rsa_rsassa_pss_sign_no_mode_check(mbedtls_rsa_context *ctx, + int (*f_rng)(void *, unsigned char *, size_t), + void *p_rng, + mbedtls_md_type_t md_alg, + unsigned int hashlen, + const unsigned char *hash, + int saltlen, + unsigned char *sig) { size_t olen; unsigned char *p = sig; @@ -1591,17 +2123,9 @@ static int rsa_rsassa_pss_sign(mbedtls_rsa_context *ctx, size_t slen, min_slen, hlen, offset = 0; int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED; size_t msb; - const mbedtls_md_info_t *md_info; - mbedtls_md_context_t md_ctx; - RSA_VALIDATE_RET(ctx != NULL); - RSA_VALIDATE_RET(mode == MBEDTLS_RSA_PRIVATE || - mode == MBEDTLS_RSA_PUBLIC); - RSA_VALIDATE_RET((md_alg == MBEDTLS_MD_NONE && - hashlen == 0) || - hash != NULL); - RSA_VALIDATE_RET(sig != NULL); - - if (mode == MBEDTLS_RSA_PRIVATE && ctx->padding != MBEDTLS_RSA_PKCS_V21) { + mbedtls_md_type_t hash_id; + + if ((md_alg != MBEDTLS_MD_NONE || hashlen != 0) && hash == NULL) { return MBEDTLS_ERR_RSA_BAD_INPUT_DATA; } @@ -1613,21 +2137,25 @@ static int rsa_rsassa_pss_sign(mbedtls_rsa_context *ctx, if (md_alg != MBEDTLS_MD_NONE) { /* Gather length of hash to sign */ - md_info = mbedtls_md_info_from_type(md_alg); - if (md_info == NULL) { + size_t exp_hashlen = mbedtls_md_get_size_from_type(md_alg); + if (exp_hashlen == 0) { return MBEDTLS_ERR_RSA_BAD_INPUT_DATA; } - hashlen = mbedtls_md_get_size(md_info); + if (hashlen != exp_hashlen) { + return MBEDTLS_ERR_RSA_BAD_INPUT_DATA; + } } - md_info = mbedtls_md_info_from_type((mbedtls_md_type_t) ctx->hash_id); - if (md_info == NULL) { + hash_id = (mbedtls_md_type_t) ctx->hash_id; + if (hash_id == MBEDTLS_MD_NONE) { + hash_id = md_alg; + } + hlen = mbedtls_md_get_size_from_type(hash_id); + if (hlen == 0) { return MBEDTLS_ERR_RSA_BAD_INPUT_DATA; } - hlen = mbedtls_md_get_size(md_info); - if (saltlen == MBEDTLS_RSA_SALT_LEN_ANY) { /* Calculate the largest possible salt length, up to the hash size. * Normally this is the hash length, which is the maximum salt length @@ -1665,26 +2193,10 @@ static int rsa_rsassa_pss_sign(mbedtls_rsa_context *ctx, p += slen; - mbedtls_md_init(&md_ctx); - if ((ret = mbedtls_md_setup(&md_ctx, md_info, 0)) != 0) { - goto exit; - } - /* Generate H = Hash( M' ) */ - if ((ret = mbedtls_md_starts(&md_ctx)) != 0) { - goto exit; - } - if ((ret = mbedtls_md_update(&md_ctx, p, 8)) != 0) { - goto exit; - } - if ((ret = mbedtls_md_update(&md_ctx, hash, hashlen)) != 0) { - goto exit; - } - if ((ret = mbedtls_md_update(&md_ctx, salt, slen)) != 0) { - goto exit; - } - if ((ret = mbedtls_md_finish(&md_ctx, p)) != 0) { - goto exit; + ret = hash_mprime(hash, hashlen, salt, slen, p, hash_id); + if (ret != 0) { + return ret; } /* Compensate for boundary condition when applying mask */ @@ -1693,9 +2205,9 @@ static int rsa_rsassa_pss_sign(mbedtls_rsa_context *ctx, } /* maskedDB: Apply dbMask to DB */ - if ((ret = mgf_mask(sig + offset, olen - hlen - 1 - offset, p, hlen, - &md_ctx)) != 0) { - goto exit; + ret = mgf_mask(sig + offset, olen - hlen - 1 - offset, p, hlen, hash_id); + if (ret != 0) { + return ret; } msb = mbedtls_mpi_bitlen(&ctx->N) - 1; @@ -1704,16 +2216,38 @@ static int rsa_rsassa_pss_sign(mbedtls_rsa_context *ctx, p += hlen; *p++ = 0xBC; -exit: - mbedtls_md_free(&md_ctx); + return mbedtls_rsa_private(ctx, f_rng, p_rng, sig, sig); +} - if (ret != 0) { - return ret; +static int rsa_rsassa_pss_sign(mbedtls_rsa_context *ctx, + int (*f_rng)(void *, unsigned char *, size_t), + void *p_rng, + mbedtls_md_type_t md_alg, + unsigned int hashlen, + const unsigned char *hash, + int saltlen, + unsigned char *sig) +{ + if (ctx->padding != MBEDTLS_RSA_PKCS_V21) { + return MBEDTLS_ERR_RSA_BAD_INPUT_DATA; + } + if ((ctx->hash_id == MBEDTLS_MD_NONE) && (md_alg == MBEDTLS_MD_NONE)) { + return MBEDTLS_ERR_RSA_BAD_INPUT_DATA; } + return rsa_rsassa_pss_sign_no_mode_check(ctx, f_rng, p_rng, md_alg, hashlen, hash, saltlen, + sig); +} - return (mode == MBEDTLS_RSA_PUBLIC) - ? mbedtls_rsa_public(ctx, sig, sig) - : mbedtls_rsa_private(ctx, f_rng, p_rng, sig, sig); +int mbedtls_rsa_rsassa_pss_sign_no_mode_check(mbedtls_rsa_context *ctx, + int (*f_rng)(void *, unsigned char *, size_t), + void *p_rng, + mbedtls_md_type_t md_alg, + unsigned int hashlen, + const unsigned char *hash, + unsigned char *sig) +{ + return rsa_rsassa_pss_sign_no_mode_check(ctx, f_rng, p_rng, md_alg, + hashlen, hash, MBEDTLS_RSA_SALT_LEN_ANY, sig); } /* @@ -1729,24 +2263,22 @@ int mbedtls_rsa_rsassa_pss_sign_ext(mbedtls_rsa_context *ctx, int saltlen, unsigned char *sig) { - return rsa_rsassa_pss_sign(ctx, f_rng, p_rng, MBEDTLS_RSA_PRIVATE, md_alg, + return rsa_rsassa_pss_sign(ctx, f_rng, p_rng, md_alg, hashlen, hash, saltlen, sig); } - /* * Implementation of the PKCS#1 v2.1 RSASSA-PSS-SIGN function */ int mbedtls_rsa_rsassa_pss_sign(mbedtls_rsa_context *ctx, int (*f_rng)(void *, unsigned char *, size_t), void *p_rng, - int mode, mbedtls_md_type_t md_alg, unsigned int hashlen, const unsigned char *hash, unsigned char *sig) { - return rsa_rsassa_pss_sign(ctx, f_rng, p_rng, mode, md_alg, + return rsa_rsassa_pss_sign(ctx, f_rng, p_rng, md_alg, hashlen, hash, MBEDTLS_RSA_SALT_LEN_ANY, sig); } #endif /* MBEDTLS_PKCS1_V21 */ @@ -1763,14 +2295,13 @@ int mbedtls_rsa_rsassa_pss_sign(mbedtls_rsa_context *ctx, * Parameters: * - md_alg: Identifies the hash algorithm used to generate the given hash; * MBEDTLS_MD_NONE if raw data is signed. - * - hashlen: Length of hash in case hashlen is MBEDTLS_MD_NONE. + * - hashlen: Length of hash. Must match md_alg if that's not NONE. * - hash: Buffer containing the hashed message or the raw data. * - dst_len: Length of the encoded message. * - dst: Buffer to hold the encoded message. * * Assumptions: - * - hash has size hashlen if md_alg == MBEDTLS_MD_NONE. - * - hash has size corresponding to md_alg if md_alg != MBEDTLS_MD_NONE. + * - hash has size hashlen. * - dst points to a buffer of size at least dst_len. * */ @@ -1787,8 +2318,8 @@ static int rsa_rsassa_pkcs1_v15_encode(mbedtls_md_type_t md_alg, /* Are we signing hashed or raw data? */ if (md_alg != MBEDTLS_MD_NONE) { - const mbedtls_md_info_t *md_info = mbedtls_md_info_from_type(md_alg); - if (md_info == NULL) { + unsigned char md_size = mbedtls_md_get_size_from_type(md_alg); + if (md_size == 0) { return MBEDTLS_ERR_RSA_BAD_INPUT_DATA; } @@ -1796,7 +2327,9 @@ static int rsa_rsassa_pkcs1_v15_encode(mbedtls_md_type_t md_alg, return MBEDTLS_ERR_RSA_BAD_INPUT_DATA; } - hashlen = mbedtls_md_get_size(md_info); + if (hashlen != md_size) { + return MBEDTLS_ERR_RSA_BAD_INPUT_DATA; + } /* Double-check that 8 + hashlen + oid_size can be used as a * 1-byte ASN.1 length encoding and that there's no overflow. */ @@ -1893,7 +2426,6 @@ static int rsa_rsassa_pkcs1_v15_encode(mbedtls_md_type_t md_alg, int mbedtls_rsa_rsassa_pkcs1_v15_sign(mbedtls_rsa_context *ctx, int (*f_rng)(void *, unsigned char *, size_t), void *p_rng, - int mode, mbedtls_md_type_t md_alg, unsigned int hashlen, const unsigned char *hash, @@ -1902,15 +2434,11 @@ int mbedtls_rsa_rsassa_pkcs1_v15_sign(mbedtls_rsa_context *ctx, int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED; unsigned char *sig_try = NULL, *verif = NULL; - RSA_VALIDATE_RET(ctx != NULL); - RSA_VALIDATE_RET(mode == MBEDTLS_RSA_PRIVATE || - mode == MBEDTLS_RSA_PUBLIC); - RSA_VALIDATE_RET((md_alg == MBEDTLS_MD_NONE && - hashlen == 0) || - hash != NULL); - RSA_VALIDATE_RET(sig != NULL); + if ((md_alg != MBEDTLS_MD_NONE || hashlen != 0) && hash == NULL) { + return MBEDTLS_ERR_RSA_BAD_INPUT_DATA; + } - if (mode == MBEDTLS_RSA_PRIVATE && ctx->padding != MBEDTLS_RSA_PKCS_V15) { + if (ctx->padding != MBEDTLS_RSA_PKCS_V15) { return MBEDTLS_ERR_RSA_BAD_INPUT_DATA; } @@ -1923,15 +2451,6 @@ int mbedtls_rsa_rsassa_pkcs1_v15_sign(mbedtls_rsa_context *ctx, return ret; } - /* - * Call respective RSA primitive - */ - - if (mode == MBEDTLS_RSA_PUBLIC) { - /* Skip verification on a public key operation */ - return mbedtls_rsa_public(ctx, sig, sig); - } - /* Private key operation * * In order to prevent Lenstra's attack, make the signature in a @@ -1960,10 +2479,8 @@ int mbedtls_rsa_rsassa_pkcs1_v15_sign(mbedtls_rsa_context *ctx, memcpy(sig, sig_try, ctx->len); cleanup: - mbedtls_platform_zeroize(sig_try, ctx->len); - mbedtls_platform_zeroize(verif, ctx->len); - mbedtls_free(sig_try); - mbedtls_free(verif); + mbedtls_zeroize_and_free(sig_try, ctx->len); + mbedtls_zeroize_and_free(verif, ctx->len); if (ret != 0) { memset(sig, '!', ctx->len); @@ -1978,30 +2495,25 @@ int mbedtls_rsa_rsassa_pkcs1_v15_sign(mbedtls_rsa_context *ctx, int mbedtls_rsa_pkcs1_sign(mbedtls_rsa_context *ctx, int (*f_rng)(void *, unsigned char *, size_t), void *p_rng, - int mode, mbedtls_md_type_t md_alg, unsigned int hashlen, const unsigned char *hash, unsigned char *sig) { - RSA_VALIDATE_RET(ctx != NULL); - RSA_VALIDATE_RET(mode == MBEDTLS_RSA_PRIVATE || - mode == MBEDTLS_RSA_PUBLIC); - RSA_VALIDATE_RET((md_alg == MBEDTLS_MD_NONE && - hashlen == 0) || - hash != NULL); - RSA_VALIDATE_RET(sig != NULL); + if ((md_alg != MBEDTLS_MD_NONE || hashlen != 0) && hash == NULL) { + return MBEDTLS_ERR_RSA_BAD_INPUT_DATA; + } switch (ctx->padding) { #if defined(MBEDTLS_PKCS1_V15) case MBEDTLS_RSA_PKCS_V15: - return mbedtls_rsa_rsassa_pkcs1_v15_sign(ctx, f_rng, p_rng, mode, md_alg, - hashlen, hash, sig); + return mbedtls_rsa_rsassa_pkcs1_v15_sign(ctx, f_rng, p_rng, + md_alg, hashlen, hash, sig); #endif #if defined(MBEDTLS_PKCS1_V21) case MBEDTLS_RSA_PKCS_V21: - return mbedtls_rsa_rsassa_pss_sign(ctx, f_rng, p_rng, mode, md_alg, + return mbedtls_rsa_rsassa_pss_sign(ctx, f_rng, p_rng, md_alg, hashlen, hash, sig); #endif @@ -2015,9 +2527,6 @@ int mbedtls_rsa_pkcs1_sign(mbedtls_rsa_context *ctx, * Implementation of the PKCS#1 v2.1 RSASSA-PSS-VERIFY function */ int mbedtls_rsa_rsassa_pss_verify_ext(mbedtls_rsa_context *ctx, - int (*f_rng)(void *, unsigned char *, size_t), - void *p_rng, - int mode, mbedtls_md_type_t md_alg, unsigned int hashlen, const unsigned char *hash, @@ -2030,22 +2539,11 @@ int mbedtls_rsa_rsassa_pss_verify_ext(mbedtls_rsa_context *ctx, unsigned char *p; unsigned char *hash_start; unsigned char result[MBEDTLS_MD_MAX_SIZE]; - unsigned char zeros[8]; unsigned int hlen; size_t observed_salt_len, msb; - const mbedtls_md_info_t *md_info; - mbedtls_md_context_t md_ctx; - unsigned char buf[MBEDTLS_MPI_MAX_SIZE]; + unsigned char buf[MBEDTLS_MPI_MAX_SIZE] = { 0 }; - RSA_VALIDATE_RET(ctx != NULL); - RSA_VALIDATE_RET(mode == MBEDTLS_RSA_PRIVATE || - mode == MBEDTLS_RSA_PUBLIC); - RSA_VALIDATE_RET(sig != NULL); - RSA_VALIDATE_RET((md_alg == MBEDTLS_MD_NONE && - hashlen == 0) || - hash != NULL); - - if (mode == MBEDTLS_RSA_PRIVATE && ctx->padding != MBEDTLS_RSA_PKCS_V21) { + if ((md_alg != MBEDTLS_MD_NONE || hashlen != 0) && hash == NULL) { return MBEDTLS_ERR_RSA_BAD_INPUT_DATA; } @@ -2055,9 +2553,7 @@ int mbedtls_rsa_rsassa_pss_verify_ext(mbedtls_rsa_context *ctx, return MBEDTLS_ERR_RSA_BAD_INPUT_DATA; } - ret = (mode == MBEDTLS_RSA_PUBLIC) - ? mbedtls_rsa_public(ctx, sig, buf) - : mbedtls_rsa_private(ctx, f_rng, p_rng, sig, buf); + ret = mbedtls_rsa_public(ctx, sig, buf); if (ret != 0) { return ret; @@ -2071,23 +2567,21 @@ int mbedtls_rsa_rsassa_pss_verify_ext(mbedtls_rsa_context *ctx, if (md_alg != MBEDTLS_MD_NONE) { /* Gather length of hash to sign */ - md_info = mbedtls_md_info_from_type(md_alg); - if (md_info == NULL) { + size_t exp_hashlen = mbedtls_md_get_size_from_type(md_alg); + if (exp_hashlen == 0) { return MBEDTLS_ERR_RSA_BAD_INPUT_DATA; } - hashlen = mbedtls_md_get_size(md_info); + if (hashlen != exp_hashlen) { + return MBEDTLS_ERR_RSA_BAD_INPUT_DATA; + } } - md_info = mbedtls_md_info_from_type(mgf1_hash_id); - if (md_info == NULL) { + hlen = mbedtls_md_get_size_from_type(mgf1_hash_id); + if (hlen == 0) { return MBEDTLS_ERR_RSA_BAD_INPUT_DATA; } - hlen = mbedtls_md_get_size(md_info); - - memset(zeros, 0, 8); - /* * Note: EMSA-PSS verification is over the length of N - 1 bits */ @@ -2108,14 +2602,9 @@ int mbedtls_rsa_rsassa_pss_verify_ext(mbedtls_rsa_context *ctx, } hash_start = p + siglen - hlen - 1; - mbedtls_md_init(&md_ctx); - if ((ret = mbedtls_md_setup(&md_ctx, md_info, 0)) != 0) { - goto exit; - } - - ret = mgf_mask(p, siglen - hlen - 1, hash_start, hlen, &md_ctx); + ret = mgf_mask(p, siglen - hlen - 1, hash_start, hlen, mgf1_hash_id); if (ret != 0) { - goto exit; + return ret; } buf[0] &= 0xFF >> (siglen * 8 - msb); @@ -2125,81 +2614,54 @@ int mbedtls_rsa_rsassa_pss_verify_ext(mbedtls_rsa_context *ctx, } if (*p++ != 0x01) { - ret = MBEDTLS_ERR_RSA_INVALID_PADDING; - goto exit; + return MBEDTLS_ERR_RSA_INVALID_PADDING; } - observed_salt_len = hash_start - p; + observed_salt_len = (size_t) (hash_start - p); if (expected_salt_len != MBEDTLS_RSA_SALT_LEN_ANY && observed_salt_len != (size_t) expected_salt_len) { - ret = MBEDTLS_ERR_RSA_INVALID_PADDING; - goto exit; + return MBEDTLS_ERR_RSA_INVALID_PADDING; } /* * Generate H = Hash( M' ) */ - ret = mbedtls_md_starts(&md_ctx); + ret = hash_mprime(hash, hashlen, p, observed_salt_len, + result, mgf1_hash_id); if (ret != 0) { - goto exit; - } - ret = mbedtls_md_update(&md_ctx, zeros, 8); - if (ret != 0) { - goto exit; - } - ret = mbedtls_md_update(&md_ctx, hash, hashlen); - if (ret != 0) { - goto exit; - } - ret = mbedtls_md_update(&md_ctx, p, observed_salt_len); - if (ret != 0) { - goto exit; - } - ret = mbedtls_md_finish(&md_ctx, result); - if (ret != 0) { - goto exit; + return ret; } if (memcmp(hash_start, result, hlen) != 0) { - ret = MBEDTLS_ERR_RSA_VERIFY_FAILED; - goto exit; + return MBEDTLS_ERR_RSA_VERIFY_FAILED; } -exit: - mbedtls_md_free(&md_ctx); - - return ret; + return 0; } /* * Simplified PKCS#1 v2.1 RSASSA-PSS-VERIFY function */ int mbedtls_rsa_rsassa_pss_verify(mbedtls_rsa_context *ctx, - int (*f_rng)(void *, unsigned char *, size_t), - void *p_rng, - int mode, mbedtls_md_type_t md_alg, unsigned int hashlen, const unsigned char *hash, const unsigned char *sig) { mbedtls_md_type_t mgf1_hash_id; - RSA_VALIDATE_RET(ctx != NULL); - RSA_VALIDATE_RET(mode == MBEDTLS_RSA_PRIVATE || - mode == MBEDTLS_RSA_PUBLIC); - RSA_VALIDATE_RET(sig != NULL); - RSA_VALIDATE_RET((md_alg == MBEDTLS_MD_NONE && - hashlen == 0) || - hash != NULL); + if ((md_alg != MBEDTLS_MD_NONE || hashlen != 0) && hash == NULL) { + return MBEDTLS_ERR_RSA_BAD_INPUT_DATA; + } mgf1_hash_id = (ctx->hash_id != MBEDTLS_MD_NONE) ? (mbedtls_md_type_t) ctx->hash_id : md_alg; - return mbedtls_rsa_rsassa_pss_verify_ext(ctx, f_rng, p_rng, mode, + return mbedtls_rsa_rsassa_pss_verify_ext(ctx, md_alg, hashlen, hash, - mgf1_hash_id, MBEDTLS_RSA_SALT_LEN_ANY, + mgf1_hash_id, + MBEDTLS_RSA_SALT_LEN_ANY, sig); } @@ -2210,9 +2672,6 @@ int mbedtls_rsa_rsassa_pss_verify(mbedtls_rsa_context *ctx, * Implementation of the PKCS#1 v2.1 RSASSA-PKCS1-v1_5-VERIFY function */ int mbedtls_rsa_rsassa_pkcs1_v15_verify(mbedtls_rsa_context *ctx, - int (*f_rng)(void *, unsigned char *, size_t), - void *p_rng, - int mode, mbedtls_md_type_t md_alg, unsigned int hashlen, const unsigned char *hash, @@ -2222,20 +2681,12 @@ int mbedtls_rsa_rsassa_pkcs1_v15_verify(mbedtls_rsa_context *ctx, size_t sig_len; unsigned char *encoded = NULL, *encoded_expected = NULL; - RSA_VALIDATE_RET(ctx != NULL); - RSA_VALIDATE_RET(mode == MBEDTLS_RSA_PRIVATE || - mode == MBEDTLS_RSA_PUBLIC); - RSA_VALIDATE_RET(sig != NULL); - RSA_VALIDATE_RET((md_alg == MBEDTLS_MD_NONE && - hashlen == 0) || - hash != NULL); - - sig_len = ctx->len; - - if (mode == MBEDTLS_RSA_PRIVATE && ctx->padding != MBEDTLS_RSA_PKCS_V15) { + if ((md_alg != MBEDTLS_MD_NONE || hashlen != 0) && hash == NULL) { return MBEDTLS_ERR_RSA_BAD_INPUT_DATA; } + sig_len = ctx->len; + /* * Prepare expected PKCS1 v1.5 encoding of hash. */ @@ -2255,9 +2706,7 @@ int mbedtls_rsa_rsassa_pkcs1_v15_verify(mbedtls_rsa_context *ctx, * Apply RSA primitive to get what should be PKCS1 encoded hash. */ - ret = (mode == MBEDTLS_RSA_PUBLIC) - ? mbedtls_rsa_public(ctx, sig, encoded) - : mbedtls_rsa_private(ctx, f_rng, p_rng, sig, encoded); + ret = mbedtls_rsa_public(ctx, sig, encoded); if (ret != 0) { goto cleanup; } @@ -2275,13 +2724,11 @@ int mbedtls_rsa_rsassa_pkcs1_v15_verify(mbedtls_rsa_context *ctx, cleanup: if (encoded != NULL) { - mbedtls_platform_zeroize(encoded, sig_len); - mbedtls_free(encoded); + mbedtls_zeroize_and_free(encoded, sig_len); } if (encoded_expected != NULL) { - mbedtls_platform_zeroize(encoded_expected, sig_len); - mbedtls_free(encoded_expected); + mbedtls_zeroize_and_free(encoded_expected, sig_len); } return ret; @@ -2292,32 +2739,25 @@ int mbedtls_rsa_rsassa_pkcs1_v15_verify(mbedtls_rsa_context *ctx, * Do an RSA operation and check the message digest */ int mbedtls_rsa_pkcs1_verify(mbedtls_rsa_context *ctx, - int (*f_rng)(void *, unsigned char *, size_t), - void *p_rng, - int mode, mbedtls_md_type_t md_alg, unsigned int hashlen, const unsigned char *hash, const unsigned char *sig) { - RSA_VALIDATE_RET(ctx != NULL); - RSA_VALIDATE_RET(mode == MBEDTLS_RSA_PRIVATE || - mode == MBEDTLS_RSA_PUBLIC); - RSA_VALIDATE_RET(sig != NULL); - RSA_VALIDATE_RET((md_alg == MBEDTLS_MD_NONE && - hashlen == 0) || - hash != NULL); + if ((md_alg != MBEDTLS_MD_NONE || hashlen != 0) && hash == NULL) { + return MBEDTLS_ERR_RSA_BAD_INPUT_DATA; + } switch (ctx->padding) { #if defined(MBEDTLS_PKCS1_V15) case MBEDTLS_RSA_PKCS_V15: - return mbedtls_rsa_rsassa_pkcs1_v15_verify(ctx, f_rng, p_rng, mode, md_alg, + return mbedtls_rsa_rsassa_pkcs1_v15_verify(ctx, md_alg, hashlen, hash, sig); #endif #if defined(MBEDTLS_PKCS1_V21) case MBEDTLS_RSA_PKCS_V21: - return mbedtls_rsa_rsassa_pss_verify(ctx, f_rng, p_rng, mode, md_alg, + return mbedtls_rsa_rsassa_pss_verify(ctx, md_alg, hashlen, hash, sig); #endif @@ -2332,8 +2772,6 @@ int mbedtls_rsa_pkcs1_verify(mbedtls_rsa_context *ctx, int mbedtls_rsa_copy(mbedtls_rsa_context *dst, const mbedtls_rsa_context *src) { int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED; - RSA_VALIDATE_RET(dst != NULL); - RSA_VALIDATE_RET(src != NULL); dst->len = src->len; @@ -2407,7 +2845,6 @@ void mbedtls_rsa_free(mbedtls_rsa_context *ctx) #if defined(MBEDTLS_SELF_TEST) -#include "mbedtls/sha1.h" /* * Example RSA-1024 keypair, for test purposes @@ -2485,14 +2922,14 @@ int mbedtls_rsa_self_test(int verbose) unsigned char rsa_plaintext[PT_LEN]; unsigned char rsa_decrypted[PT_LEN]; unsigned char rsa_ciphertext[KEY_LEN]; -#if defined(MBEDTLS_SHA1_C) +#if defined(MBEDTLS_MD_CAN_SHA1) unsigned char sha1sum[20]; #endif mbedtls_mpi K; mbedtls_mpi_init(&K); - mbedtls_rsa_init(&rsa, MBEDTLS_RSA_PKCS_V15, 0); + mbedtls_rsa_init(&rsa); MBEDTLS_MPI_CHK(mbedtls_mpi_read_string(&K, 16, RSA_N)); MBEDTLS_MPI_CHK(mbedtls_rsa_import(&rsa, &K, NULL, NULL, NULL, NULL)); @@ -2527,7 +2964,7 @@ int mbedtls_rsa_self_test(int verbose) memcpy(rsa_plaintext, RSA_PT, PT_LEN); - if (mbedtls_rsa_pkcs1_encrypt(&rsa, myrand, NULL, MBEDTLS_RSA_PUBLIC, + if (mbedtls_rsa_pkcs1_encrypt(&rsa, myrand, NULL, PT_LEN, rsa_plaintext, rsa_ciphertext) != 0) { if (verbose != 0) { @@ -2542,7 +2979,7 @@ int mbedtls_rsa_self_test(int verbose) mbedtls_printf("passed\n PKCS#1 decryption : "); } - if (mbedtls_rsa_pkcs1_decrypt(&rsa, myrand, NULL, MBEDTLS_RSA_PRIVATE, + if (mbedtls_rsa_pkcs1_decrypt(&rsa, myrand, NULL, &len, rsa_ciphertext, rsa_decrypted, sizeof(rsa_decrypted)) != 0) { if (verbose != 0) { @@ -2566,12 +3003,13 @@ int mbedtls_rsa_self_test(int verbose) mbedtls_printf("passed\n"); } -#if defined(MBEDTLS_SHA1_C) +#if defined(MBEDTLS_MD_CAN_SHA1) if (verbose != 0) { mbedtls_printf(" PKCS#1 data sign : "); } - if (mbedtls_sha1_ret(rsa_plaintext, PT_LEN, sha1sum) != 0) { + if (mbedtls_md(mbedtls_md_info_from_type(MBEDTLS_MD_SHA1), + rsa_plaintext, PT_LEN, sha1sum) != 0) { if (verbose != 0) { mbedtls_printf("failed\n"); } @@ -2580,7 +3018,7 @@ int mbedtls_rsa_self_test(int verbose) } if (mbedtls_rsa_pkcs1_sign(&rsa, myrand, NULL, - MBEDTLS_RSA_PRIVATE, MBEDTLS_MD_SHA1, 0, + MBEDTLS_MD_SHA1, 20, sha1sum, rsa_ciphertext) != 0) { if (verbose != 0) { mbedtls_printf("failed\n"); @@ -2594,8 +3032,7 @@ int mbedtls_rsa_self_test(int verbose) mbedtls_printf("passed\n PKCS#1 sig. verify: "); } - if (mbedtls_rsa_pkcs1_verify(&rsa, NULL, NULL, - MBEDTLS_RSA_PUBLIC, MBEDTLS_MD_SHA1, 0, + if (mbedtls_rsa_pkcs1_verify(&rsa, MBEDTLS_MD_SHA1, 20, sha1sum, rsa_ciphertext) != 0) { if (verbose != 0) { mbedtls_printf("failed\n"); @@ -2608,7 +3045,7 @@ int mbedtls_rsa_self_test(int verbose) if (verbose != 0) { mbedtls_printf("passed\n"); } -#endif /* MBEDTLS_SHA1_C */ +#endif /* MBEDTLS_MD_CAN_SHA1 */ if (verbose != 0) { mbedtls_printf("\n"); diff --git a/vendor/mbedtls/library/rsa_internal.c b/vendor/mbedtls/library/rsa_alt_helpers.c similarity index 95% rename from vendor/mbedtls/library/rsa_internal.c rename to vendor/mbedtls/library/rsa_alt_helpers.c index 41ceff06c0..5c265a9921 100644 --- a/vendor/mbedtls/library/rsa_internal.c +++ b/vendor/mbedtls/library/rsa_alt_helpers.c @@ -2,19 +2,7 @@ * Helper functions for the RSA module * * Copyright The Mbed TLS Contributors - * SPDX-License-Identifier: Apache-2.0 - * - * Licensed under the Apache License, Version 2.0 (the "License"); you may - * not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT - * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. + * SPDX-License-Identifier: Apache-2.0 OR GPL-2.0-or-later * */ @@ -24,7 +12,7 @@ #include "mbedtls/rsa.h" #include "mbedtls/bignum.h" -#include "mbedtls/rsa_internal.h" +#include "rsa_alt_helpers.h" /* * Compute RSA prime factors from public and private exponents @@ -234,80 +222,33 @@ int mbedtls_rsa_deduce_private_exponent(mbedtls_mpi const *P, return ret; } -/* - * Check that RSA CRT parameters are in accordance with core parameters. - */ -int mbedtls_rsa_validate_crt(const mbedtls_mpi *P, const mbedtls_mpi *Q, - const mbedtls_mpi *D, const mbedtls_mpi *DP, - const mbedtls_mpi *DQ, const mbedtls_mpi *QP) +int mbedtls_rsa_deduce_crt(const mbedtls_mpi *P, const mbedtls_mpi *Q, + const mbedtls_mpi *D, mbedtls_mpi *DP, + mbedtls_mpi *DQ, mbedtls_mpi *QP) { int ret = 0; - - mbedtls_mpi K, L; + mbedtls_mpi K; mbedtls_mpi_init(&K); - mbedtls_mpi_init(&L); - /* Check that DP - D == 0 mod P - 1 */ + /* DP = D mod P-1 */ if (DP != NULL) { - if (P == NULL) { - ret = MBEDTLS_ERR_RSA_BAD_INPUT_DATA; - goto cleanup; - } - MBEDTLS_MPI_CHK(mbedtls_mpi_sub_int(&K, P, 1)); - MBEDTLS_MPI_CHK(mbedtls_mpi_sub_mpi(&L, DP, D)); - MBEDTLS_MPI_CHK(mbedtls_mpi_mod_mpi(&L, &L, &K)); - - if (mbedtls_mpi_cmp_int(&L, 0) != 0) { - ret = MBEDTLS_ERR_RSA_KEY_CHECK_FAILED; - goto cleanup; - } + MBEDTLS_MPI_CHK(mbedtls_mpi_mod_mpi(DP, D, &K)); } - /* Check that DQ - D == 0 mod Q - 1 */ + /* DQ = D mod Q-1 */ if (DQ != NULL) { - if (Q == NULL) { - ret = MBEDTLS_ERR_RSA_BAD_INPUT_DATA; - goto cleanup; - } - MBEDTLS_MPI_CHK(mbedtls_mpi_sub_int(&K, Q, 1)); - MBEDTLS_MPI_CHK(mbedtls_mpi_sub_mpi(&L, DQ, D)); - MBEDTLS_MPI_CHK(mbedtls_mpi_mod_mpi(&L, &L, &K)); - - if (mbedtls_mpi_cmp_int(&L, 0) != 0) { - ret = MBEDTLS_ERR_RSA_KEY_CHECK_FAILED; - goto cleanup; - } + MBEDTLS_MPI_CHK(mbedtls_mpi_mod_mpi(DQ, D, &K)); } - /* Check that QP * Q - 1 == 0 mod P */ + /* QP = Q^{-1} mod P */ if (QP != NULL) { - if (P == NULL || Q == NULL) { - ret = MBEDTLS_ERR_RSA_BAD_INPUT_DATA; - goto cleanup; - } - - MBEDTLS_MPI_CHK(mbedtls_mpi_mul_mpi(&K, QP, Q)); - MBEDTLS_MPI_CHK(mbedtls_mpi_sub_int(&K, &K, 1)); - MBEDTLS_MPI_CHK(mbedtls_mpi_mod_mpi(&K, &K, P)); - if (mbedtls_mpi_cmp_int(&K, 0) != 0) { - ret = MBEDTLS_ERR_RSA_KEY_CHECK_FAILED; - goto cleanup; - } + MBEDTLS_MPI_CHK(mbedtls_mpi_inv_mod(QP, Q, P)); } cleanup: - - /* Wrap MPI error codes by RSA check failure error code */ - if (ret != 0 && - ret != MBEDTLS_ERR_RSA_KEY_CHECK_FAILED && - ret != MBEDTLS_ERR_RSA_BAD_INPUT_DATA) { - ret += MBEDTLS_ERR_RSA_KEY_CHECK_FAILED; - } - mbedtls_mpi_free(&K); - mbedtls_mpi_free(&L); return ret; } @@ -425,33 +366,80 @@ int mbedtls_rsa_validate_params(const mbedtls_mpi *N, const mbedtls_mpi *P, return ret; } -int mbedtls_rsa_deduce_crt(const mbedtls_mpi *P, const mbedtls_mpi *Q, - const mbedtls_mpi *D, mbedtls_mpi *DP, - mbedtls_mpi *DQ, mbedtls_mpi *QP) +/* + * Check that RSA CRT parameters are in accordance with core parameters. + */ +int mbedtls_rsa_validate_crt(const mbedtls_mpi *P, const mbedtls_mpi *Q, + const mbedtls_mpi *D, const mbedtls_mpi *DP, + const mbedtls_mpi *DQ, const mbedtls_mpi *QP) { int ret = 0; - mbedtls_mpi K; + + mbedtls_mpi K, L; mbedtls_mpi_init(&K); + mbedtls_mpi_init(&L); - /* DP = D mod P-1 */ + /* Check that DP - D == 0 mod P - 1 */ if (DP != NULL) { + if (P == NULL) { + ret = MBEDTLS_ERR_RSA_BAD_INPUT_DATA; + goto cleanup; + } + MBEDTLS_MPI_CHK(mbedtls_mpi_sub_int(&K, P, 1)); - MBEDTLS_MPI_CHK(mbedtls_mpi_mod_mpi(DP, D, &K)); + MBEDTLS_MPI_CHK(mbedtls_mpi_sub_mpi(&L, DP, D)); + MBEDTLS_MPI_CHK(mbedtls_mpi_mod_mpi(&L, &L, &K)); + + if (mbedtls_mpi_cmp_int(&L, 0) != 0) { + ret = MBEDTLS_ERR_RSA_KEY_CHECK_FAILED; + goto cleanup; + } } - /* DQ = D mod Q-1 */ + /* Check that DQ - D == 0 mod Q - 1 */ if (DQ != NULL) { + if (Q == NULL) { + ret = MBEDTLS_ERR_RSA_BAD_INPUT_DATA; + goto cleanup; + } + MBEDTLS_MPI_CHK(mbedtls_mpi_sub_int(&K, Q, 1)); - MBEDTLS_MPI_CHK(mbedtls_mpi_mod_mpi(DQ, D, &K)); + MBEDTLS_MPI_CHK(mbedtls_mpi_sub_mpi(&L, DQ, D)); + MBEDTLS_MPI_CHK(mbedtls_mpi_mod_mpi(&L, &L, &K)); + + if (mbedtls_mpi_cmp_int(&L, 0) != 0) { + ret = MBEDTLS_ERR_RSA_KEY_CHECK_FAILED; + goto cleanup; + } } - /* QP = Q^{-1} mod P */ + /* Check that QP * Q - 1 == 0 mod P */ if (QP != NULL) { - MBEDTLS_MPI_CHK(mbedtls_mpi_inv_mod(QP, Q, P)); + if (P == NULL || Q == NULL) { + ret = MBEDTLS_ERR_RSA_BAD_INPUT_DATA; + goto cleanup; + } + + MBEDTLS_MPI_CHK(mbedtls_mpi_mul_mpi(&K, QP, Q)); + MBEDTLS_MPI_CHK(mbedtls_mpi_sub_int(&K, &K, 1)); + MBEDTLS_MPI_CHK(mbedtls_mpi_mod_mpi(&K, &K, P)); + if (mbedtls_mpi_cmp_int(&K, 0) != 0) { + ret = MBEDTLS_ERR_RSA_KEY_CHECK_FAILED; + goto cleanup; + } } cleanup: + + /* Wrap MPI error codes by RSA check failure error code */ + if (ret != 0 && + ret != MBEDTLS_ERR_RSA_KEY_CHECK_FAILED && + ret != MBEDTLS_ERR_RSA_BAD_INPUT_DATA) { + ret += MBEDTLS_ERR_RSA_KEY_CHECK_FAILED; + } + mbedtls_mpi_free(&K); + mbedtls_mpi_free(&L); return ret; } diff --git a/vendor/mbedtls/include/mbedtls/rsa_internal.h b/vendor/mbedtls/library/rsa_alt_helpers.h similarity index 90% rename from vendor/mbedtls/include/mbedtls/rsa_internal.h rename to vendor/mbedtls/library/rsa_alt_helpers.h index 017018bca9..052b02491e 100644 --- a/vendor/mbedtls/include/mbedtls/rsa_internal.h +++ b/vendor/mbedtls/library/rsa_alt_helpers.h @@ -1,5 +1,5 @@ /** - * \file rsa_internal.h + * \file rsa_alt_helpers.h * * \brief Context-independent RSA helper functions * @@ -36,30 +36,12 @@ */ /* * Copyright The Mbed TLS Contributors - * SPDX-License-Identifier: Apache-2.0 - * - * Licensed under the Apache License, Version 2.0 (the "License"); you may - * not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT - * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - * + * SPDX-License-Identifier: Apache-2.0 OR GPL-2.0-or-later */ +#ifndef MBEDTLS_RSA_ALT_HELPERS_H +#define MBEDTLS_RSA_ALT_HELPERS_H -#ifndef MBEDTLS_RSA_INTERNAL_H -#define MBEDTLS_RSA_INTERNAL_H - -#if !defined(MBEDTLS_CONFIG_FILE) -#include "mbedtls/config.h" -#else -#include MBEDTLS_CONFIG_FILE -#endif +#include "mbedtls/build_info.h" #include "mbedtls/bignum.h" @@ -221,4 +203,4 @@ int mbedtls_rsa_validate_crt(const mbedtls_mpi *P, const mbedtls_mpi *Q, } #endif -#endif /* rsa_internal.h */ +#endif /* rsa_alt_helpers.h */ diff --git a/vendor/mbedtls/library/rsa_internal.h b/vendor/mbedtls/library/rsa_internal.h new file mode 100644 index 0000000000..f79c3b7122 --- /dev/null +++ b/vendor/mbedtls/library/rsa_internal.h @@ -0,0 +1,121 @@ +/** + * \file rsa_internal.h + * + * \brief Internal-only RSA public-key cryptosystem API. + * + * This file declares RSA-related functions that are to be used + * only from within the Mbed TLS library itself. + * + */ +/* + * Copyright The Mbed TLS Contributors + * SPDX-License-Identifier: Apache-2.0 OR GPL-2.0-or-later + */ +#ifndef MBEDTLS_RSA_INTERNAL_H +#define MBEDTLS_RSA_INTERNAL_H + +#include "mbedtls/rsa.h" +#include "mbedtls/asn1.h" + +/** + * \brief Parse a PKCS#1 (ASN.1) encoded private RSA key. + * + * \param rsa The RSA context where parsed data will be stored. + * \param key The buffer that contains the key. + * \param keylen The length of the key buffer in bytes. + * + * \return 0 on success. + * \return MBEDTLS_ERR_ASN1_xxx in case of ASN.1 parsing errors. + * \return MBEDTLS_ERR_RSA_xxx in case of RSA internal failures while + * parsing data. + * \return MBEDTLS_ERR_RSA_KEY_CHECK_FAILED if validity checks on the + * provided key fail. + */ +int mbedtls_rsa_parse_key(mbedtls_rsa_context *rsa, const unsigned char *key, size_t keylen); + +/** + * \brief Parse a PKCS#1 (ASN.1) encoded public RSA key. + * + * \param rsa The RSA context where parsed data will be stored. + * \param key The buffer that contains the key. + * \param keylen The length of the key buffer in bytes. + * + * \return 0 on success. + * \return MBEDTLS_ERR_ASN1_xxx in case of ASN.1 parsing errors. + * \return MBEDTLS_ERR_RSA_xxx in case of RSA internal failures while + * parsing data. + * \return MBEDTLS_ERR_RSA_KEY_CHECK_FAILED if validity checks on the + * provided key fail. + */ +int mbedtls_rsa_parse_pubkey(mbedtls_rsa_context *rsa, const unsigned char *key, size_t keylen); + +/** + * \brief Write a PKCS#1 (ASN.1) encoded private RSA key. + * + * \param rsa The RSA context which contains the data to be written. + * \param start Beginning of the buffer that will be filled with the + * private key. + * \param p End of the buffer that will be filled with the private key. + * On successful return, the referenced pointer will be + * updated in order to point to the beginning of written data. + * + * \return On success, the number of bytes written to the output buffer + * (i.e. a value > 0). + * \return MBEDTLS_ERR_RSA_BAD_INPUT_DATA if the RSA context does not + * contain a valid key pair. + * \return MBEDTLS_ERR_ASN1_xxx in case of failure while writing to the + * output buffer. + * + * \note The output buffer is filled backward, i.e. starting from its + * end and moving toward its start. + */ +int mbedtls_rsa_write_key(const mbedtls_rsa_context *rsa, unsigned char *start, + unsigned char **p); + +/** + * \brief Parse a PKCS#1 (ASN.1) encoded public RSA key. + * + * \param rsa The RSA context which contains the data to be written. + * \param start Beginning of the buffer that will be filled with the + * private key. + * \param p End of the buffer that will be filled with the private key. + * On successful return, the referenced pointer will be + * updated in order to point to the beginning of written data. + * + * \return On success, the number of bytes written to the output buffer + * (i.e. a value > 0). + * \return MBEDTLS_ERR_RSA_BAD_INPUT_DATA if the RSA context does not + * contain a valid public key. + * \return MBEDTLS_ERR_ASN1_xxx in case of failure while writing to the + * output buffer. + * + * \note The output buffer is filled backward, i.e. starting from its + * end and moving toward its start. + */ +int mbedtls_rsa_write_pubkey(const mbedtls_rsa_context *rsa, unsigned char *start, + unsigned char **p); + +#if defined(MBEDTLS_PKCS1_V21) +/** + * \brief This function is analogue to \c mbedtls_rsa_rsassa_pss_sign(). + * The only difference between them is that this function is more flexible + * on the parameters of \p ctx that are set with \c mbedtls_rsa_set_padding(). + * + * \note Compared to its counterpart, this function: + * - does not check the padding setting of \p ctx. + * - allows the hash_id of \p ctx to be MBEDTLS_MD_NONE, + * in which case it uses \p md_alg as the hash_id. + * + * \note Refer to \c mbedtls_rsa_rsassa_pss_sign() for a description + * of the functioning and parameters of this function. + */ +int mbedtls_rsa_rsassa_pss_sign_no_mode_check(mbedtls_rsa_context *ctx, + int (*f_rng)(void *, unsigned char *, size_t), + void *p_rng, + mbedtls_md_type_t md_alg, + unsigned int hashlen, + const unsigned char *hash, + unsigned char *sig); +#endif /* MBEDTLS_PKCS1_V21 */ + +#endif /* rsa_internal.h */ diff --git a/vendor/mbedtls/library/sha1.c b/vendor/mbedtls/library/sha1.c index 6da641427c..dfbe481f39 100644 --- a/vendor/mbedtls/library/sha1.c +++ b/vendor/mbedtls/library/sha1.c @@ -2,19 +2,7 @@ * FIPS-180-1 compliant SHA-1 implementation * * Copyright The Mbed TLS Contributors - * SPDX-License-Identifier: Apache-2.0 - * - * Licensed under the Apache License, Version 2.0 (the "License"); you may - * not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT - * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. + * SPDX-License-Identifier: Apache-2.0 OR GPL-2.0-or-later */ /* * The SHA-1 standard was published by NIST in 1993. @@ -34,17 +22,10 @@ #include "mbedtls/platform.h" -#define SHA1_VALIDATE_RET(cond) \ - MBEDTLS_INTERNAL_VALIDATE_RET(cond, MBEDTLS_ERR_SHA1_BAD_INPUT_DATA) - -#define SHA1_VALIDATE(cond) MBEDTLS_INTERNAL_VALIDATE(cond) - #if !defined(MBEDTLS_SHA1_ALT) void mbedtls_sha1_init(mbedtls_sha1_context *ctx) { - SHA1_VALIDATE(ctx != NULL); - memset(ctx, 0, sizeof(mbedtls_sha1_context)); } @@ -60,19 +41,14 @@ void mbedtls_sha1_free(mbedtls_sha1_context *ctx) void mbedtls_sha1_clone(mbedtls_sha1_context *dst, const mbedtls_sha1_context *src) { - SHA1_VALIDATE(dst != NULL); - SHA1_VALIDATE(src != NULL); - *dst = *src; } /* * SHA-1 context setup */ -int mbedtls_sha1_starts_ret(mbedtls_sha1_context *ctx) +int mbedtls_sha1_starts(mbedtls_sha1_context *ctx) { - SHA1_VALIDATE_RET(ctx != NULL); - ctx->total[0] = 0; ctx->total[1] = 0; @@ -85,13 +61,6 @@ int mbedtls_sha1_starts_ret(mbedtls_sha1_context *ctx) return 0; } -#if !defined(MBEDTLS_DEPRECATED_REMOVED) -void mbedtls_sha1_starts(mbedtls_sha1_context *ctx) -{ - mbedtls_sha1_starts_ret(ctx); -} -#endif - #if !defined(MBEDTLS_SHA1_PROCESS_ALT) int mbedtls_internal_sha1_process(mbedtls_sha1_context *ctx, const unsigned char data[64]) @@ -100,9 +69,6 @@ int mbedtls_internal_sha1_process(mbedtls_sha1_context *ctx, uint32_t temp, W[16], A, B, C, D, E; } local; - SHA1_VALIDATE_RET(ctx != NULL); - SHA1_VALIDATE_RET((const unsigned char *) data != NULL); - local.W[0] = MBEDTLS_GET_UINT32_BE(data, 0); local.W[1] = MBEDTLS_GET_UINT32_BE(data, 4); local.W[2] = MBEDTLS_GET_UINT32_BE(data, 8); @@ -264,29 +230,19 @@ int mbedtls_internal_sha1_process(mbedtls_sha1_context *ctx, return 0; } -#if !defined(MBEDTLS_DEPRECATED_REMOVED) -void mbedtls_sha1_process(mbedtls_sha1_context *ctx, - const unsigned char data[64]) -{ - mbedtls_internal_sha1_process(ctx, data); -} -#endif #endif /* !MBEDTLS_SHA1_PROCESS_ALT */ /* * SHA-1 process buffer */ -int mbedtls_sha1_update_ret(mbedtls_sha1_context *ctx, - const unsigned char *input, - size_t ilen) +int mbedtls_sha1_update(mbedtls_sha1_context *ctx, + const unsigned char *input, + size_t ilen) { int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED; size_t fill; uint32_t left; - SHA1_VALIDATE_RET(ctx != NULL); - SHA1_VALIDATE_RET(ilen == 0 || input != NULL); - if (ilen == 0) { return 0; } @@ -329,28 +285,16 @@ int mbedtls_sha1_update_ret(mbedtls_sha1_context *ctx, return 0; } -#if !defined(MBEDTLS_DEPRECATED_REMOVED) -void mbedtls_sha1_update(mbedtls_sha1_context *ctx, - const unsigned char *input, - size_t ilen) -{ - mbedtls_sha1_update_ret(ctx, input, ilen); -} -#endif - /* * SHA-1 final digest */ -int mbedtls_sha1_finish_ret(mbedtls_sha1_context *ctx, - unsigned char output[20]) +int mbedtls_sha1_finish(mbedtls_sha1_context *ctx, + unsigned char output[20]) { int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED; uint32_t used; uint32_t high, low; - SHA1_VALIDATE_RET(ctx != NULL); - SHA1_VALIDATE_RET((unsigned char *) output != NULL); - /* * Add padding: 0x80 then 0x00 until 8 bytes remain for the length */ @@ -366,7 +310,7 @@ int mbedtls_sha1_finish_ret(mbedtls_sha1_context *ctx, memset(ctx->buffer + used, 0, 64 - used); if ((ret = mbedtls_internal_sha1_process(ctx, ctx->buffer)) != 0) { - return ret; + goto exit; } memset(ctx->buffer, 0, 56); @@ -383,7 +327,7 @@ int mbedtls_sha1_finish_ret(mbedtls_sha1_context *ctx, MBEDTLS_PUT_UINT32_BE(low, ctx->buffer, 60); if ((ret = mbedtls_internal_sha1_process(ctx, ctx->buffer)) != 0) { - return ret; + goto exit; } /* @@ -395,61 +339,44 @@ int mbedtls_sha1_finish_ret(mbedtls_sha1_context *ctx, MBEDTLS_PUT_UINT32_BE(ctx->state[3], output, 12); MBEDTLS_PUT_UINT32_BE(ctx->state[4], output, 16); - return 0; -} + ret = 0; -#if !defined(MBEDTLS_DEPRECATED_REMOVED) -void mbedtls_sha1_finish(mbedtls_sha1_context *ctx, - unsigned char output[20]) -{ - mbedtls_sha1_finish_ret(ctx, output); +exit: + mbedtls_sha1_free(ctx); + return ret; } -#endif #endif /* !MBEDTLS_SHA1_ALT */ /* * output = SHA-1( input buffer ) */ -int mbedtls_sha1_ret(const unsigned char *input, - size_t ilen, - unsigned char output[20]) +int mbedtls_sha1(const unsigned char *input, + size_t ilen, + unsigned char output[20]) { int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED; mbedtls_sha1_context ctx; - SHA1_VALIDATE_RET(ilen == 0 || input != NULL); - SHA1_VALIDATE_RET((unsigned char *) output != NULL); - mbedtls_sha1_init(&ctx); - if ((ret = mbedtls_sha1_starts_ret(&ctx)) != 0) { + if ((ret = mbedtls_sha1_starts(&ctx)) != 0) { goto exit; } - if ((ret = mbedtls_sha1_update_ret(&ctx, input, ilen)) != 0) { + if ((ret = mbedtls_sha1_update(&ctx, input, ilen)) != 0) { goto exit; } - if ((ret = mbedtls_sha1_finish_ret(&ctx, output)) != 0) { + if ((ret = mbedtls_sha1_finish(&ctx, output)) != 0) { goto exit; } exit: mbedtls_sha1_free(&ctx); - return ret; } -#if !defined(MBEDTLS_DEPRECATED_REMOVED) -void mbedtls_sha1(const unsigned char *input, - size_t ilen, - unsigned char output[20]) -{ - mbedtls_sha1_ret(input, ilen, output); -} -#endif - #if defined(MBEDTLS_SELF_TEST) /* * FIPS-180-1 test vectors @@ -496,7 +423,7 @@ int mbedtls_sha1_self_test(int verbose) mbedtls_printf(" SHA-1 test #%d: ", i + 1); } - if ((ret = mbedtls_sha1_starts_ret(&ctx)) != 0) { + if ((ret = mbedtls_sha1_starts(&ctx)) != 0) { goto fail; } @@ -504,20 +431,20 @@ int mbedtls_sha1_self_test(int verbose) memset(buf, 'a', buflen = 1000); for (j = 0; j < 1000; j++) { - ret = mbedtls_sha1_update_ret(&ctx, buf, buflen); + ret = mbedtls_sha1_update(&ctx, buf, buflen); if (ret != 0) { goto fail; } } } else { - ret = mbedtls_sha1_update_ret(&ctx, sha1_test_buf[i], - sha1_test_buflen[i]); + ret = mbedtls_sha1_update(&ctx, sha1_test_buf[i], + sha1_test_buflen[i]); if (ret != 0) { goto fail; } } - if ((ret = mbedtls_sha1_finish_ret(&ctx, sha1sum)) != 0) { + if ((ret = mbedtls_sha1_finish(&ctx, sha1sum)) != 0) { goto fail; } diff --git a/vendor/mbedtls/library/sha256.c b/vendor/mbedtls/library/sha256.c index f7090396d2..87889817a4 100644 --- a/vendor/mbedtls/library/sha256.c +++ b/vendor/mbedtls/library/sha256.c @@ -2,19 +2,7 @@ * FIPS-180-2 compliant SHA-256 implementation * * Copyright The Mbed TLS Contributors - * SPDX-License-Identifier: Apache-2.0 - * - * Licensed under the Apache License, Version 2.0 (the "License"); you may - * not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT - * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. + * SPDX-License-Identifier: Apache-2.0 OR GPL-2.0-or-later */ /* * The SHA-256 Secure Hash Standard was published by NIST in 2002. @@ -22,9 +10,45 @@ * http://csrc.nist.gov/publications/fips/fips180-2/fips180-2.pdf */ +#if defined(__clang__) && (__clang_major__ >= 4) + +/* Ideally, we would simply use MBEDTLS_ARCH_IS_ARMV8_A in the following #if, + * but that is defined by build_info.h, and we need this block to happen first. */ +#if defined(__ARM_ARCH) && (__ARM_ARCH_PROFILE == 'A') +#if __ARM_ARCH >= 8 +#define MBEDTLS_SHA256_ARCH_IS_ARMV8_A +#endif +#endif + +#if defined(MBEDTLS_SHA256_ARCH_IS_ARMV8_A) && !defined(__ARM_FEATURE_CRYPTO) +/* TODO: Re-consider above after https://reviews.llvm.org/D131064 merged. + * + * The intrinsic declaration are guarded by predefined ACLE macros in clang: + * these are normally only enabled by the -march option on the command line. + * By defining the macros ourselves we gain access to those declarations without + * requiring -march on the command line. + * + * `arm_neon.h` is included by common.h, so we put these defines + * at the top of this file, before any includes. + */ +#define __ARM_FEATURE_CRYPTO 1 +/* See: https://arm-software.github.io/acle/main/acle.html#cryptographic-extensions + * + * `__ARM_FEATURE_CRYPTO` is deprecated, but we need to continue to specify it + * for older compilers. + */ +#define __ARM_FEATURE_SHA2 1 +#define MBEDTLS_ENABLE_ARM_CRYPTO_EXTENSIONS_COMPILER_FLAG +#endif + +#endif /* defined(__clang__) && (__clang_major__ >= 4) */ + +/* Ensure that SIG_SETMASK is defined when -std=c99 is used. */ +#define _GNU_SOURCE + #include "common.h" -#if defined(MBEDTLS_SHA256_C) +#if defined(MBEDTLS_SHA256_C) || defined(MBEDTLS_SHA224_C) #include "mbedtls/sha256.h" #include "mbedtls/platform_util.h" @@ -34,16 +58,168 @@ #include "mbedtls/platform.h" -#define SHA256_VALIDATE_RET(cond) \ - MBEDTLS_INTERNAL_VALIDATE_RET(cond, MBEDTLS_ERR_SHA256_BAD_INPUT_DATA) -#define SHA256_VALIDATE(cond) MBEDTLS_INTERNAL_VALIDATE(cond) +#if defined(MBEDTLS_ARCH_IS_ARMV8_A) + +# if defined(MBEDTLS_SHA256_USE_ARMV8_A_CRYPTO_IF_PRESENT) || \ + defined(MBEDTLS_SHA256_USE_ARMV8_A_CRYPTO_ONLY) +# if !defined(MBEDTLS_HAVE_NEON_INTRINSICS) +# if defined(MBEDTLS_SHA256_USE_ARMV8_A_CRYPTO_IF_PRESENT) +# warning "Target does not support NEON instructions" +# undef MBEDTLS_SHA256_USE_ARMV8_A_CRYPTO_IF_PRESENT +# else +# error "Target does not support NEON instructions" +# endif +# endif +# endif + +# if defined(MBEDTLS_SHA256_USE_ARMV8_A_CRYPTO_IF_PRESENT) || \ + defined(MBEDTLS_SHA256_USE_ARMV8_A_CRYPTO_ONLY) +/* *INDENT-OFF* */ + +# if !defined(__ARM_FEATURE_CRYPTO) || defined(MBEDTLS_ENABLE_ARM_CRYPTO_EXTENSIONS_COMPILER_FLAG) +# if defined(__ARMCOMPILER_VERSION) +# if __ARMCOMPILER_VERSION <= 6090000 +# error "Must use minimum -march=armv8-a+crypto for MBEDTLS_SHA256_USE_ARMV8_A_CRYPTO_*" +# endif +# pragma clang attribute push (__attribute__((target("sha2"))), apply_to=function) +# define MBEDTLS_POP_TARGET_PRAGMA +# elif defined(__clang__) +# if __clang_major__ < 4 +# error "A more recent Clang is required for MBEDTLS_SHA256_USE_ARMV8_A_CRYPTO_*" +# endif +# pragma clang attribute push (__attribute__((target("crypto"))), apply_to=function) +# define MBEDTLS_POP_TARGET_PRAGMA +# elif defined(__GNUC__) + /* FIXME: GCC 5 claims to support Armv8 Crypto Extensions, but some + * intrinsics are missing. Missing intrinsics could be worked around. + */ +# if __GNUC__ < 6 +# error "A more recent GCC is required for MBEDTLS_SHA256_USE_ARMV8_A_CRYPTO_*" +# else +# pragma GCC push_options +# pragma GCC target ("arch=armv8-a+crypto") +# define MBEDTLS_POP_TARGET_PRAGMA +# endif +# else +# error "Only GCC and Clang supported for MBEDTLS_SHA256_USE_ARMV8_A_CRYPTO_*" +# endif +# endif +/* *INDENT-ON* */ + +# endif +# if defined(MBEDTLS_SHA256_USE_ARMV8_A_CRYPTO_IF_PRESENT) +# if defined(__unix__) +# if defined(__linux__) +/* Our preferred method of detection is getauxval() */ +# include +/* These are not always defined via sys/auxv.h */ +# if !defined(HWCAP_SHA2) +# define HWCAP_SHA2 (1 << 6) +# endif +# if !defined(HWCAP2_SHA2) +# define HWCAP2_SHA2 (1 << 3) +# endif +# endif +/* Use SIGILL on Unix, and fall back to it on Linux */ +# include +# endif +# endif +#elif !defined(MBEDTLS_PLATFORM_IS_WINDOWS_ON_ARM64) +# undef MBEDTLS_SHA256_USE_ARMV8_A_CRYPTO_ONLY +# undef MBEDTLS_SHA256_USE_ARMV8_A_CRYPTO_IF_PRESENT +#endif + +#if defined(MBEDTLS_SHA256_USE_ARMV8_A_CRYPTO_IF_PRESENT) +/* + * Capability detection code comes early, so we can disable + * MBEDTLS_SHA256_USE_ARMV8_A_CRYPTO_IF_PRESENT if no detection mechanism found + */ +#if defined(MBEDTLS_ARCH_IS_ARM64) && defined(HWCAP_SHA2) +static int mbedtls_a64_crypto_sha256_determine_support(void) +{ + return (getauxval(AT_HWCAP) & HWCAP_SHA2) ? 1 : 0; +} +#elif defined(MBEDTLS_ARCH_IS_ARM32) && defined(HWCAP2_SHA2) +static int mbedtls_a64_crypto_sha256_determine_support(void) +{ + return (getauxval(AT_HWCAP2) & HWCAP2_SHA2) ? 1 : 0; +} +#elif defined(__APPLE__) +static int mbedtls_a64_crypto_sha256_determine_support(void) +{ + return 1; +} +#elif defined(MBEDTLS_PLATFORM_IS_WINDOWS_ON_ARM64) +#define WIN32_LEAN_AND_MEAN +#include +#include + +static int mbedtls_a64_crypto_sha256_determine_support(void) +{ + return IsProcessorFeaturePresent(PF_ARM_V8_CRYPTO_INSTRUCTIONS_AVAILABLE) ? + 1 : 0; +} +#elif defined(__unix__) && defined(SIG_SETMASK) +/* Detection with SIGILL, setjmp() and longjmp() */ +#include +#include + +static jmp_buf return_from_sigill; + +/* + * Armv8-A SHA256 support detection via SIGILL + */ +static void sigill_handler(int signal) +{ + (void) signal; + longjmp(return_from_sigill, 1); +} + +static int mbedtls_a64_crypto_sha256_determine_support(void) +{ + struct sigaction old_action, new_action; + + sigset_t old_mask; + if (sigprocmask(0, NULL, &old_mask)) { + return 0; + } + + sigemptyset(&new_action.sa_mask); + new_action.sa_flags = 0; + new_action.sa_handler = sigill_handler; + + sigaction(SIGILL, &new_action, &old_action); + + static int ret = 0; + + if (setjmp(return_from_sigill) == 0) { /* First return only */ + /* If this traps, we will return a second time from setjmp() with 1 */ +#if defined(MBEDTLS_ARCH_IS_ARM64) + asm volatile ("sha256h q0, q0, v0.4s" : : : "v0"); +#else + asm volatile ("sha256h.32 q0, q0, q0" : : : "q0"); +#endif + ret = 1; + } + + sigaction(SIGILL, &old_action, NULL); + sigprocmask(SIG_SETMASK, &old_mask, NULL); + + return ret; +} +#else +#warning "No mechanism to detect ARMV8_CRYPTO found, using C code only" +#undef MBEDTLS_SHA256_USE_ARMV8_A_CRYPTO_IF_PRESENT +#endif /* HWCAP_SHA2, __APPLE__, __unix__ && SIG_SETMASK */ + +#endif /* MBEDTLS_SHA256_USE_ARMV8_A_CRYPTO_IF_PRESENT */ #if !defined(MBEDTLS_SHA256_ALT) +#define SHA256_BLOCK_SIZE 64 + void mbedtls_sha256_init(mbedtls_sha256_context *ctx) { - SHA256_VALIDATE(ctx != NULL); - memset(ctx, 0, sizeof(mbedtls_sha256_context)); } @@ -59,25 +235,33 @@ void mbedtls_sha256_free(mbedtls_sha256_context *ctx) void mbedtls_sha256_clone(mbedtls_sha256_context *dst, const mbedtls_sha256_context *src) { - SHA256_VALIDATE(dst != NULL); - SHA256_VALIDATE(src != NULL); - *dst = *src; } /* * SHA-256 context setup */ -int mbedtls_sha256_starts_ret(mbedtls_sha256_context *ctx, int is224) +int mbedtls_sha256_starts(mbedtls_sha256_context *ctx, int is224) { - SHA256_VALIDATE_RET(ctx != NULL); - SHA256_VALIDATE_RET(is224 == 0 || is224 == 1); +#if defined(MBEDTLS_SHA224_C) && defined(MBEDTLS_SHA256_C) + if (is224 != 0 && is224 != 1) { + return MBEDTLS_ERR_SHA256_BAD_INPUT_DATA; + } +#elif defined(MBEDTLS_SHA256_C) + if (is224 != 0) { + return MBEDTLS_ERR_SHA256_BAD_INPUT_DATA; + } +#else /* defined MBEDTLS_SHA224_C only */ + if (is224 == 0) { + return MBEDTLS_ERR_SHA256_BAD_INPUT_DATA; + } +#endif ctx->total[0] = 0; ctx->total[1] = 0; if (is224 == 0) { - /* SHA-256 */ +#if defined(MBEDTLS_SHA256_C) ctx->state[0] = 0x6A09E667; ctx->state[1] = 0xBB67AE85; ctx->state[2] = 0x3C6EF372; @@ -86,8 +270,9 @@ int mbedtls_sha256_starts_ret(mbedtls_sha256_context *ctx, int is224) ctx->state[5] = 0x9B05688C; ctx->state[6] = 0x1F83D9AB; ctx->state[7] = 0x5BE0CD19; +#endif } else { - /* SHA-224 */ +#if defined(MBEDTLS_SHA224_C) ctx->state[0] = 0xC1059ED8; ctx->state[1] = 0x367CD507; ctx->state[2] = 0x3070DD17; @@ -96,21 +281,16 @@ int mbedtls_sha256_starts_ret(mbedtls_sha256_context *ctx, int is224) ctx->state[5] = 0x68581511; ctx->state[6] = 0x64F98FA7; ctx->state[7] = 0xBEFA4FA4; +#endif } +#if defined(MBEDTLS_SHA224_C) ctx->is224 = is224; +#endif return 0; } -#if !defined(MBEDTLS_DEPRECATED_REMOVED) -void mbedtls_sha256_starts(mbedtls_sha256_context *ctx, - int is224) -{ - mbedtls_sha256_starts_ret(ctx, is224); -} -#endif - #if !defined(MBEDTLS_SHA256_PROCESS_ALT) static const uint32_t K[] = { @@ -132,6 +312,146 @@ static const uint32_t K[] = 0x90BEFFFA, 0xA4506CEB, 0xBEF9A3F7, 0xC67178F2, }; +#endif + +#if defined(MBEDTLS_SHA256_USE_ARMV8_A_CRYPTO_IF_PRESENT) || \ + defined(MBEDTLS_SHA256_USE_ARMV8_A_CRYPTO_ONLY) + +#if defined(MBEDTLS_SHA256_USE_ARMV8_A_CRYPTO_ONLY) +# define mbedtls_internal_sha256_process_many_a64_crypto mbedtls_internal_sha256_process_many +# define mbedtls_internal_sha256_process_a64_crypto mbedtls_internal_sha256_process +#endif + +static size_t mbedtls_internal_sha256_process_many_a64_crypto( + mbedtls_sha256_context *ctx, const uint8_t *msg, size_t len) +{ + uint32x4_t abcd = vld1q_u32(&ctx->state[0]); + uint32x4_t efgh = vld1q_u32(&ctx->state[4]); + + size_t processed = 0; + + for (; + len >= SHA256_BLOCK_SIZE; + processed += SHA256_BLOCK_SIZE, + msg += SHA256_BLOCK_SIZE, + len -= SHA256_BLOCK_SIZE) { + uint32x4_t tmp, abcd_prev; + + uint32x4_t abcd_orig = abcd; + uint32x4_t efgh_orig = efgh; + + uint32x4_t sched0 = vreinterpretq_u32_u8(vld1q_u8(msg + 16 * 0)); + uint32x4_t sched1 = vreinterpretq_u32_u8(vld1q_u8(msg + 16 * 1)); + uint32x4_t sched2 = vreinterpretq_u32_u8(vld1q_u8(msg + 16 * 2)); + uint32x4_t sched3 = vreinterpretq_u32_u8(vld1q_u8(msg + 16 * 3)); + +#if __BYTE_ORDER__ == __ORDER_LITTLE_ENDIAN__ /* Will be true if not defined */ + /* Untested on BE */ + sched0 = vreinterpretq_u32_u8(vrev32q_u8(vreinterpretq_u8_u32(sched0))); + sched1 = vreinterpretq_u32_u8(vrev32q_u8(vreinterpretq_u8_u32(sched1))); + sched2 = vreinterpretq_u32_u8(vrev32q_u8(vreinterpretq_u8_u32(sched2))); + sched3 = vreinterpretq_u32_u8(vrev32q_u8(vreinterpretq_u8_u32(sched3))); +#endif + + /* Rounds 0 to 3 */ + tmp = vaddq_u32(sched0, vld1q_u32(&K[0])); + abcd_prev = abcd; + abcd = vsha256hq_u32(abcd_prev, efgh, tmp); + efgh = vsha256h2q_u32(efgh, abcd_prev, tmp); + + /* Rounds 4 to 7 */ + tmp = vaddq_u32(sched1, vld1q_u32(&K[4])); + abcd_prev = abcd; + abcd = vsha256hq_u32(abcd_prev, efgh, tmp); + efgh = vsha256h2q_u32(efgh, abcd_prev, tmp); + + /* Rounds 8 to 11 */ + tmp = vaddq_u32(sched2, vld1q_u32(&K[8])); + abcd_prev = abcd; + abcd = vsha256hq_u32(abcd_prev, efgh, tmp); + efgh = vsha256h2q_u32(efgh, abcd_prev, tmp); + + /* Rounds 12 to 15 */ + tmp = vaddq_u32(sched3, vld1q_u32(&K[12])); + abcd_prev = abcd; + abcd = vsha256hq_u32(abcd_prev, efgh, tmp); + efgh = vsha256h2q_u32(efgh, abcd_prev, tmp); + + for (int t = 16; t < 64; t += 16) { + /* Rounds t to t + 3 */ + sched0 = vsha256su1q_u32(vsha256su0q_u32(sched0, sched1), sched2, sched3); + tmp = vaddq_u32(sched0, vld1q_u32(&K[t])); + abcd_prev = abcd; + abcd = vsha256hq_u32(abcd_prev, efgh, tmp); + efgh = vsha256h2q_u32(efgh, abcd_prev, tmp); + + /* Rounds t + 4 to t + 7 */ + sched1 = vsha256su1q_u32(vsha256su0q_u32(sched1, sched2), sched3, sched0); + tmp = vaddq_u32(sched1, vld1q_u32(&K[t + 4])); + abcd_prev = abcd; + abcd = vsha256hq_u32(abcd_prev, efgh, tmp); + efgh = vsha256h2q_u32(efgh, abcd_prev, tmp); + + /* Rounds t + 8 to t + 11 */ + sched2 = vsha256su1q_u32(vsha256su0q_u32(sched2, sched3), sched0, sched1); + tmp = vaddq_u32(sched2, vld1q_u32(&K[t + 8])); + abcd_prev = abcd; + abcd = vsha256hq_u32(abcd_prev, efgh, tmp); + efgh = vsha256h2q_u32(efgh, abcd_prev, tmp); + + /* Rounds t + 12 to t + 15 */ + sched3 = vsha256su1q_u32(vsha256su0q_u32(sched3, sched0), sched1, sched2); + tmp = vaddq_u32(sched3, vld1q_u32(&K[t + 12])); + abcd_prev = abcd; + abcd = vsha256hq_u32(abcd_prev, efgh, tmp); + efgh = vsha256h2q_u32(efgh, abcd_prev, tmp); + } + + abcd = vaddq_u32(abcd, abcd_orig); + efgh = vaddq_u32(efgh, efgh_orig); + } + + vst1q_u32(&ctx->state[0], abcd); + vst1q_u32(&ctx->state[4], efgh); + + return processed; +} + +#if defined(MBEDTLS_SHA256_USE_ARMV8_A_CRYPTO_IF_PRESENT) +/* + * This function is for internal use only if we are building both C and Armv8-A + * versions, otherwise it is renamed to be the public mbedtls_internal_sha256_process() + */ +static +#endif +int mbedtls_internal_sha256_process_a64_crypto(mbedtls_sha256_context *ctx, + const unsigned char data[SHA256_BLOCK_SIZE]) +{ + return (mbedtls_internal_sha256_process_many_a64_crypto(ctx, data, + SHA256_BLOCK_SIZE) == + SHA256_BLOCK_SIZE) ? 0 : -1; +} + +#endif /* MBEDTLS_SHA256_USE_ARMV8_A_CRYPTO_IF_PRESENT || MBEDTLS_SHA256_USE_ARMV8_A_CRYPTO_ONLY */ + +#if defined(MBEDTLS_POP_TARGET_PRAGMA) +#if defined(__clang__) +#pragma clang attribute pop +#elif defined(__GNUC__) +#pragma GCC pop_options +#endif +#undef MBEDTLS_POP_TARGET_PRAGMA +#endif + +#if !defined(MBEDTLS_SHA256_USE_ARMV8_A_CRYPTO_IF_PRESENT) +#define mbedtls_internal_sha256_process_many_c mbedtls_internal_sha256_process_many +#define mbedtls_internal_sha256_process_c mbedtls_internal_sha256_process +#endif + + +#if !defined(MBEDTLS_SHA256_PROCESS_ALT) && \ + !defined(MBEDTLS_SHA256_USE_ARMV8_A_CRYPTO_ONLY) + #define SHR(x, n) (((x) & 0xFFFFFFFF) >> (n)) #define ROTR(x, n) (SHR(x, n) | ((x) << (32 - (n)))) @@ -158,8 +478,15 @@ static const uint32_t K[] = (d) += local.temp1; (h) = local.temp1 + local.temp2; \ } while (0) -int mbedtls_internal_sha256_process(mbedtls_sha256_context *ctx, - const unsigned char data[64]) +#if defined(MBEDTLS_SHA256_USE_ARMV8_A_CRYPTO_IF_PRESENT) +/* + * This function is for internal use only if we are building both C and Armv8 + * versions, otherwise it is renamed to be the public mbedtls_internal_sha256_process() + */ +static +#endif +int mbedtls_internal_sha256_process_c(mbedtls_sha256_context *ctx, + const unsigned char data[SHA256_BLOCK_SIZE]) { struct { uint32_t temp1, temp2, W[64]; @@ -168,9 +495,6 @@ int mbedtls_internal_sha256_process(mbedtls_sha256_context *ctx, unsigned int i; - SHA256_VALIDATE_RET(ctx != NULL); - SHA256_VALIDATE_RET((const unsigned char *) data != NULL); - for (i = 0; i < 8; i++) { local.A[i] = ctx->state[i]; } @@ -246,35 +570,88 @@ int mbedtls_internal_sha256_process(mbedtls_sha256_context *ctx, return 0; } -#if !defined(MBEDTLS_DEPRECATED_REMOVED) -void mbedtls_sha256_process(mbedtls_sha256_context *ctx, - const unsigned char data[64]) +#endif /* !MBEDTLS_SHA256_PROCESS_ALT && !MBEDTLS_SHA256_USE_ARMV8_A_CRYPTO_ONLY */ + + +#if !defined(MBEDTLS_SHA256_USE_ARMV8_A_CRYPTO_ONLY) + +static size_t mbedtls_internal_sha256_process_many_c( + mbedtls_sha256_context *ctx, const uint8_t *data, size_t len) { - mbedtls_internal_sha256_process(ctx, data); + size_t processed = 0; + + while (len >= SHA256_BLOCK_SIZE) { + if (mbedtls_internal_sha256_process_c(ctx, data) != 0) { + return 0; + } + + data += SHA256_BLOCK_SIZE; + len -= SHA256_BLOCK_SIZE; + + processed += SHA256_BLOCK_SIZE; + } + + return processed; } -#endif -#endif /* !MBEDTLS_SHA256_PROCESS_ALT */ + +#endif /* !MBEDTLS_SHA256_USE_ARMV8_A_CRYPTO_ONLY */ + + +#if defined(MBEDTLS_SHA256_USE_ARMV8_A_CRYPTO_IF_PRESENT) + +static int mbedtls_a64_crypto_sha256_has_support(void) +{ + static int done = 0; + static int supported = 0; + + if (!done) { + supported = mbedtls_a64_crypto_sha256_determine_support(); + done = 1; + } + + return supported; +} + +static size_t mbedtls_internal_sha256_process_many(mbedtls_sha256_context *ctx, + const uint8_t *msg, size_t len) +{ + if (mbedtls_a64_crypto_sha256_has_support()) { + return mbedtls_internal_sha256_process_many_a64_crypto(ctx, msg, len); + } else { + return mbedtls_internal_sha256_process_many_c(ctx, msg, len); + } +} + +int mbedtls_internal_sha256_process(mbedtls_sha256_context *ctx, + const unsigned char data[SHA256_BLOCK_SIZE]) +{ + if (mbedtls_a64_crypto_sha256_has_support()) { + return mbedtls_internal_sha256_process_a64_crypto(ctx, data); + } else { + return mbedtls_internal_sha256_process_c(ctx, data); + } +} + +#endif /* MBEDTLS_SHA256_USE_ARMV8_A_CRYPTO_IF_PRESENT */ + /* * SHA-256 process buffer */ -int mbedtls_sha256_update_ret(mbedtls_sha256_context *ctx, - const unsigned char *input, - size_t ilen) +int mbedtls_sha256_update(mbedtls_sha256_context *ctx, + const unsigned char *input, + size_t ilen) { int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED; size_t fill; uint32_t left; - SHA256_VALIDATE_RET(ctx != NULL); - SHA256_VALIDATE_RET(ilen == 0 || input != NULL); - if (ilen == 0) { return 0; } left = ctx->total[0] & 0x3F; - fill = 64 - left; + fill = SHA256_BLOCK_SIZE - left; ctx->total[0] += (uint32_t) ilen; ctx->total[0] &= 0xFFFFFFFF; @@ -295,13 +672,15 @@ int mbedtls_sha256_update_ret(mbedtls_sha256_context *ctx, left = 0; } - while (ilen >= 64) { - if ((ret = mbedtls_internal_sha256_process(ctx, input)) != 0) { - return ret; + while (ilen >= SHA256_BLOCK_SIZE) { + size_t processed = + mbedtls_internal_sha256_process_many(ctx, input, ilen); + if (processed < SHA256_BLOCK_SIZE) { + return MBEDTLS_ERR_ERROR_GENERIC_ERROR; } - input += 64; - ilen -= 64; + input += processed; + ilen -= processed; } if (ilen > 0) { @@ -311,27 +690,16 @@ int mbedtls_sha256_update_ret(mbedtls_sha256_context *ctx, return 0; } -#if !defined(MBEDTLS_DEPRECATED_REMOVED) -void mbedtls_sha256_update(mbedtls_sha256_context *ctx, - const unsigned char *input, - size_t ilen) -{ - mbedtls_sha256_update_ret(ctx, input, ilen); -} -#endif - /* * SHA-256 final digest */ -int mbedtls_sha256_finish_ret(mbedtls_sha256_context *ctx, - unsigned char output[32]) +int mbedtls_sha256_finish(mbedtls_sha256_context *ctx, + unsigned char *output) { int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED; uint32_t used; uint32_t high, low; - - SHA256_VALIDATE_RET(ctx != NULL); - SHA256_VALIDATE_RET((unsigned char *) output != NULL); + int truncated = 0; /* * Add padding: 0x80 then 0x00 until 8 bytes remain for the length @@ -345,10 +713,10 @@ int mbedtls_sha256_finish_ret(mbedtls_sha256_context *ctx, memset(ctx->buffer + used, 0, 56 - used); } else { /* We'll need an extra block */ - memset(ctx->buffer + used, 0, 64 - used); + memset(ctx->buffer + used, 0, SHA256_BLOCK_SIZE - used); if ((ret = mbedtls_internal_sha256_process(ctx, ctx->buffer)) != 0) { - return ret; + goto exit; } memset(ctx->buffer, 0, 56); @@ -365,7 +733,7 @@ int mbedtls_sha256_finish_ret(mbedtls_sha256_context *ctx, MBEDTLS_PUT_UINT32_BE(low, ctx->buffer, 60); if ((ret = mbedtls_internal_sha256_process(ctx, ctx->buffer)) != 0) { - return ret; + goto exit; } /* @@ -379,49 +747,58 @@ int mbedtls_sha256_finish_ret(mbedtls_sha256_context *ctx, MBEDTLS_PUT_UINT32_BE(ctx->state[5], output, 20); MBEDTLS_PUT_UINT32_BE(ctx->state[6], output, 24); - if (ctx->is224 == 0) { +#if defined(MBEDTLS_SHA224_C) + truncated = ctx->is224; +#endif + if (!truncated) { MBEDTLS_PUT_UINT32_BE(ctx->state[7], output, 28); } - return 0; -} + ret = 0; -#if !defined(MBEDTLS_DEPRECATED_REMOVED) -void mbedtls_sha256_finish(mbedtls_sha256_context *ctx, - unsigned char output[32]) -{ - mbedtls_sha256_finish_ret(ctx, output); +exit: + mbedtls_sha256_free(ctx); + return ret; } -#endif #endif /* !MBEDTLS_SHA256_ALT */ /* * output = SHA-256( input buffer ) */ -int mbedtls_sha256_ret(const unsigned char *input, - size_t ilen, - unsigned char output[32], - int is224) +int mbedtls_sha256(const unsigned char *input, + size_t ilen, + unsigned char *output, + int is224) { int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED; mbedtls_sha256_context ctx; - SHA256_VALIDATE_RET(is224 == 0 || is224 == 1); - SHA256_VALIDATE_RET(ilen == 0 || input != NULL); - SHA256_VALIDATE_RET((unsigned char *) output != NULL); +#if defined(MBEDTLS_SHA224_C) && defined(MBEDTLS_SHA256_C) + if (is224 != 0 && is224 != 1) { + return MBEDTLS_ERR_SHA256_BAD_INPUT_DATA; + } +#elif defined(MBEDTLS_SHA256_C) + if (is224 != 0) { + return MBEDTLS_ERR_SHA256_BAD_INPUT_DATA; + } +#else /* defined MBEDTLS_SHA224_C only */ + if (is224 == 0) { + return MBEDTLS_ERR_SHA256_BAD_INPUT_DATA; + } +#endif mbedtls_sha256_init(&ctx); - if ((ret = mbedtls_sha256_starts_ret(&ctx, is224)) != 0) { + if ((ret = mbedtls_sha256_starts(&ctx, is224)) != 0) { goto exit; } - if ((ret = mbedtls_sha256_update_ret(&ctx, input, ilen)) != 0) { + if ((ret = mbedtls_sha256_update(&ctx, input, ilen)) != 0) { goto exit; } - if ((ret = mbedtls_sha256_finish_ret(&ctx, output)) != 0) { + if ((ret = mbedtls_sha256_finish(&ctx, output)) != 0) { goto exit; } @@ -431,37 +808,30 @@ int mbedtls_sha256_ret(const unsigned char *input, return ret; } -#if !defined(MBEDTLS_DEPRECATED_REMOVED) -void mbedtls_sha256(const unsigned char *input, - size_t ilen, - unsigned char output[32], - int is224) -{ - mbedtls_sha256_ret(input, ilen, output, is224); -} -#endif - #if defined(MBEDTLS_SELF_TEST) /* * FIPS-180-2 test vectors */ -static const unsigned char sha256_test_buf[3][57] = +static const unsigned char sha_test_buf[3][57] = { { "abc" }, { "abcdbcdecdefdefgefghfghighijhijkijkljklmklmnlmnomnopnopq" }, { "" } }; -static const size_t sha256_test_buflen[3] = +static const size_t sha_test_buflen[3] = { 3, 56, 1000 }; -static const unsigned char sha256_test_sum[6][32] = +typedef const unsigned char (sha_test_sum_t)[32]; + +/* + * SHA-224 test vectors + */ +#if defined(MBEDTLS_SHA224_C) +static sha_test_sum_t sha224_test_sum[] = { - /* - * SHA-224 test vectors - */ { 0x23, 0x09, 0x7D, 0x22, 0x34, 0x05, 0xD8, 0x22, 0x86, 0x42, 0xA4, 0x77, 0xBD, 0xA2, 0x55, 0xB3, 0x2A, 0xAD, 0xBC, 0xE4, 0xBD, 0xA0, 0xB3, 0xF7, @@ -473,11 +843,16 @@ static const unsigned char sha256_test_sum[6][32] = { 0x20, 0x79, 0x46, 0x55, 0x98, 0x0C, 0x91, 0xD8, 0xBB, 0xB4, 0xC1, 0xEA, 0x97, 0x61, 0x8A, 0x4B, 0xF0, 0x3F, 0x42, 0x58, 0x19, 0x48, 0xB2, 0xEE, - 0x4E, 0xE7, 0xAD, 0x67 }, + 0x4E, 0xE7, 0xAD, 0x67 } +}; +#endif - /* - * SHA-256 test vectors - */ +/* + * SHA-256 test vectors + */ +#if defined(MBEDTLS_SHA256_C) +static sha_test_sum_t sha256_test_sum[] = +{ { 0xBA, 0x78, 0x16, 0xBF, 0x8F, 0x01, 0xCF, 0xEA, 0x41, 0x41, 0x40, 0xDE, 0x5D, 0xAE, 0x22, 0x23, 0xB0, 0x03, 0x61, 0xA3, 0x96, 0x17, 0x7A, 0x9C, @@ -491,17 +866,26 @@ static const unsigned char sha256_test_sum[6][32] = 0xF1, 0x80, 0x9A, 0x48, 0xA4, 0x97, 0x20, 0x0E, 0x04, 0x6D, 0x39, 0xCC, 0xC7, 0x11, 0x2C, 0xD0 } }; +#endif /* * Checkup routine */ -int mbedtls_sha256_self_test(int verbose) +static int mbedtls_sha256_common_self_test(int verbose, int is224) { - int i, j, k, buflen, ret = 0; + int i, buflen, ret = 0; unsigned char *buf; unsigned char sha256sum[32]; mbedtls_sha256_context ctx; +#if defined(MBEDTLS_SHA224_C) && defined(MBEDTLS_SHA256_C) + sha_test_sum_t *sha_test_sum = (is224) ? sha224_test_sum : sha256_test_sum; +#elif defined(MBEDTLS_SHA256_C) + sha_test_sum_t *sha_test_sum = sha256_test_sum; +#else + sha_test_sum_t *sha_test_sum = sha224_test_sum; +#endif + buf = mbedtls_calloc(1024, sizeof(unsigned char)); if (NULL == buf) { if (verbose != 0) { @@ -513,42 +897,39 @@ int mbedtls_sha256_self_test(int verbose) mbedtls_sha256_init(&ctx); - for (i = 0; i < 6; i++) { - j = i % 3; - k = i < 3; - + for (i = 0; i < 3; i++) { if (verbose != 0) { - mbedtls_printf(" SHA-%d test #%d: ", 256 - k * 32, j + 1); + mbedtls_printf(" SHA-%d test #%d: ", 256 - is224 * 32, i + 1); } - if ((ret = mbedtls_sha256_starts_ret(&ctx, k)) != 0) { + if ((ret = mbedtls_sha256_starts(&ctx, is224)) != 0) { goto fail; } - if (j == 2) { + if (i == 2) { memset(buf, 'a', buflen = 1000); - for (j = 0; j < 1000; j++) { - ret = mbedtls_sha256_update_ret(&ctx, buf, buflen); + for (int j = 0; j < 1000; j++) { + ret = mbedtls_sha256_update(&ctx, buf, buflen); if (ret != 0) { goto fail; } } } else { - ret = mbedtls_sha256_update_ret(&ctx, sha256_test_buf[j], - sha256_test_buflen[j]); + ret = mbedtls_sha256_update(&ctx, sha_test_buf[i], + sha_test_buflen[i]); if (ret != 0) { goto fail; } } - if ((ret = mbedtls_sha256_finish_ret(&ctx, sha256sum)) != 0) { + if ((ret = mbedtls_sha256_finish(&ctx, sha256sum)) != 0) { goto fail; } - if (memcmp(sha256sum, sha256_test_sum[i], 32 - k * 4) != 0) { + if (memcmp(sha256sum, sha_test_sum[i], 32 - is224 * 4) != 0) { ret = 1; goto fail; } @@ -576,6 +957,20 @@ int mbedtls_sha256_self_test(int verbose) return ret; } +#if defined(MBEDTLS_SHA256_C) +int mbedtls_sha256_self_test(int verbose) +{ + return mbedtls_sha256_common_self_test(verbose, 0); +} +#endif /* MBEDTLS_SHA256_C */ + +#if defined(MBEDTLS_SHA224_C) +int mbedtls_sha224_self_test(int verbose) +{ + return mbedtls_sha256_common_self_test(verbose, 1); +} +#endif /* MBEDTLS_SHA224_C */ + #endif /* MBEDTLS_SELF_TEST */ -#endif /* MBEDTLS_SHA256_C */ +#endif /* MBEDTLS_SHA256_C || MBEDTLS_SHA224_C */ diff --git a/vendor/mbedtls/library/sha3.c b/vendor/mbedtls/library/sha3.c new file mode 100644 index 0000000000..57385595f5 --- /dev/null +++ b/vendor/mbedtls/library/sha3.c @@ -0,0 +1,721 @@ +/* + * FIPS-202 compliant SHA3 implementation + * + * Copyright The Mbed TLS Contributors + * SPDX-License-Identifier: Apache-2.0 OR GPL-2.0-or-later + */ +/* + * The SHA-3 Secure Hash Standard was published by NIST in 2015. + * + * https://nvlpubs.nist.gov/nistpubs/fips/nist.fips.202.pdf + */ + +#include "common.h" + +#if defined(MBEDTLS_SHA3_C) + +/* + * These macros select manually unrolled implementations of parts of the main permutation function. + * + * Unrolling has a major impact on both performance and code size. gcc performance benefits a lot + * from manually unrolling at higher optimisation levels. + * + * Depending on your size/perf priorities, compiler and target, it may be beneficial to adjust + * these; the defaults here should give sensible trade-offs for gcc and clang on aarch64 and + * x86-64. + */ +#if !defined(MBEDTLS_SHA3_THETA_UNROLL) + #define MBEDTLS_SHA3_THETA_UNROLL 0 //no-check-names +#endif +#if !defined(MBEDTLS_SHA3_CHI_UNROLL) + #if defined(__OPTIMIZE_SIZE__) + #define MBEDTLS_SHA3_CHI_UNROLL 0 //no-check-names + #else + #define MBEDTLS_SHA3_CHI_UNROLL 1 //no-check-names + #endif +#endif +#if !defined(MBEDTLS_SHA3_PI_UNROLL) + #define MBEDTLS_SHA3_PI_UNROLL 1 //no-check-names +#endif +#if !defined(MBEDTLS_SHA3_RHO_UNROLL) + #define MBEDTLS_SHA3_RHO_UNROLL 1 //no-check-names +#endif + +#include "mbedtls/sha3.h" +#include "mbedtls/platform_util.h" +#include "mbedtls/error.h" + +#include + +#if defined(MBEDTLS_SELF_TEST) +#include "mbedtls/platform.h" +#endif /* MBEDTLS_SELF_TEST */ + +#define XOR_BYTE 0x6 + +/* Precomputed masks for the iota transform. + * + * Each round uses a 64-bit mask value. In each mask values, only + * bits whose position is of the form 2^k-1 can be set, thus only + * 7 of 64 bits of the mask need to be known for each mask value. + * + * We use a compressed encoding of the mask where bits 63, 31 and 15 + * are moved to bits 4-6. This allows us to make each mask value + * 1 byte rather than 8 bytes, saving 7*24 = 168 bytes of data (with + * perhaps a little variation due to alignment). Decompressing this + * requires a little code, but much less than the savings on the table. + * + * The impact on performance depends on the platform and compiler. + * There's a bit more computation, but less memory bandwidth. A quick + * benchmark on x86_64 shows a 7% speed improvement with GCC and a + * 5% speed penalty with Clang, compared to the naive uint64_t[24] table. + * YMMV. + */ +/* Helper macro to set the values of the higher bits in unused low positions */ +#define H(b63, b31, b15) (b63 << 6 | b31 << 5 | b15 << 4) +static const uint8_t iota_r_packed[24] = { + H(0, 0, 0) | 0x01, H(0, 0, 1) | 0x82, H(1, 0, 1) | 0x8a, H(1, 1, 1) | 0x00, + H(0, 0, 1) | 0x8b, H(0, 1, 0) | 0x01, H(1, 1, 1) | 0x81, H(1, 0, 1) | 0x09, + H(0, 0, 0) | 0x8a, H(0, 0, 0) | 0x88, H(0, 1, 1) | 0x09, H(0, 1, 0) | 0x0a, + H(0, 1, 1) | 0x8b, H(1, 0, 0) | 0x8b, H(1, 0, 1) | 0x89, H(1, 0, 1) | 0x03, + H(1, 0, 1) | 0x02, H(1, 0, 0) | 0x80, H(0, 0, 1) | 0x0a, H(1, 1, 0) | 0x0a, + H(1, 1, 1) | 0x81, H(1, 0, 1) | 0x80, H(0, 1, 0) | 0x01, H(1, 1, 1) | 0x08, +}; +#undef H + +static const uint32_t rho[6] = { + 0x3f022425, 0x1c143a09, 0x2c3d3615, 0x27191713, 0x312b382e, 0x3e030832 +}; + +static const uint32_t pi[6] = { + 0x110b070a, 0x10050312, 0x04181508, 0x0d13170f, 0x0e14020c, 0x01060916 +}; + +#define ROTR64(x, y) (((x) << (64U - (y))) | ((x) >> (y))) // 64-bit rotate right +#define ABSORB(ctx, idx, v) do { ctx->state[(idx) >> 3] ^= ((uint64_t) (v)) << (((idx) & 0x7) << 3); \ +} while (0) +#define SQUEEZE(ctx, idx) ((uint8_t) (ctx->state[(idx) >> 3] >> (((idx) & 0x7) << 3))) +#define SWAP(x, y) do { uint64_t tmp = (x); (x) = (y); (y) = tmp; } while (0) + +/* The permutation function. */ +static void keccak_f1600(mbedtls_sha3_context *ctx) +{ + uint64_t lane[5]; + uint64_t *s = ctx->state; + int i; + + for (int round = 0; round < 24; round++) { + uint64_t t; + + /* Theta */ +#if MBEDTLS_SHA3_THETA_UNROLL == 0 //no-check-names + for (i = 0; i < 5; i++) { + lane[i] = s[i] ^ s[i + 5] ^ s[i + 10] ^ s[i + 15] ^ s[i + 20]; + } + for (i = 0; i < 5; i++) { + t = lane[(i + 4) % 5] ^ ROTR64(lane[(i + 1) % 5], 63); + s[i] ^= t; s[i + 5] ^= t; s[i + 10] ^= t; s[i + 15] ^= t; s[i + 20] ^= t; + } +#else + lane[0] = s[0] ^ s[5] ^ s[10] ^ s[15] ^ s[20]; + lane[1] = s[1] ^ s[6] ^ s[11] ^ s[16] ^ s[21]; + lane[2] = s[2] ^ s[7] ^ s[12] ^ s[17] ^ s[22]; + lane[3] = s[3] ^ s[8] ^ s[13] ^ s[18] ^ s[23]; + lane[4] = s[4] ^ s[9] ^ s[14] ^ s[19] ^ s[24]; + + t = lane[4] ^ ROTR64(lane[1], 63); + s[0] ^= t; s[5] ^= t; s[10] ^= t; s[15] ^= t; s[20] ^= t; + + t = lane[0] ^ ROTR64(lane[2], 63); + s[1] ^= t; s[6] ^= t; s[11] ^= t; s[16] ^= t; s[21] ^= t; + + t = lane[1] ^ ROTR64(lane[3], 63); + s[2] ^= t; s[7] ^= t; s[12] ^= t; s[17] ^= t; s[22] ^= t; + + t = lane[2] ^ ROTR64(lane[4], 63); + s[3] ^= t; s[8] ^= t; s[13] ^= t; s[18] ^= t; s[23] ^= t; + + t = lane[3] ^ ROTR64(lane[0], 63); + s[4] ^= t; s[9] ^= t; s[14] ^= t; s[19] ^= t; s[24] ^= t; +#endif + + /* Rho */ + for (i = 1; i < 25; i += 4) { + uint32_t r = rho[(i - 1) >> 2]; +#if MBEDTLS_SHA3_RHO_UNROLL == 0 + for (int j = i; j < i + 4; j++) { + uint8_t r8 = (uint8_t) (r >> 24); + r <<= 8; + s[j] = ROTR64(s[j], r8); + } +#else + s[i + 0] = ROTR64(s[i + 0], MBEDTLS_BYTE_3(r)); + s[i + 1] = ROTR64(s[i + 1], MBEDTLS_BYTE_2(r)); + s[i + 2] = ROTR64(s[i + 2], MBEDTLS_BYTE_1(r)); + s[i + 3] = ROTR64(s[i + 3], MBEDTLS_BYTE_0(r)); +#endif + } + + /* Pi */ + t = s[1]; +#if MBEDTLS_SHA3_PI_UNROLL == 0 + for (i = 0; i < 24; i += 4) { + uint32_t p = pi[i >> 2]; + for (unsigned j = 0; j < 4; j++) { + SWAP(s[p & 0xff], t); + p >>= 8; + } + } +#else + uint32_t p = pi[0]; + SWAP(s[MBEDTLS_BYTE_0(p)], t); SWAP(s[MBEDTLS_BYTE_1(p)], t); + SWAP(s[MBEDTLS_BYTE_2(p)], t); SWAP(s[MBEDTLS_BYTE_3(p)], t); + p = pi[1]; + SWAP(s[MBEDTLS_BYTE_0(p)], t); SWAP(s[MBEDTLS_BYTE_1(p)], t); + SWAP(s[MBEDTLS_BYTE_2(p)], t); SWAP(s[MBEDTLS_BYTE_3(p)], t); + p = pi[2]; + SWAP(s[MBEDTLS_BYTE_0(p)], t); SWAP(s[MBEDTLS_BYTE_1(p)], t); + SWAP(s[MBEDTLS_BYTE_2(p)], t); SWAP(s[MBEDTLS_BYTE_3(p)], t); + p = pi[3]; + SWAP(s[MBEDTLS_BYTE_0(p)], t); SWAP(s[MBEDTLS_BYTE_1(p)], t); + SWAP(s[MBEDTLS_BYTE_2(p)], t); SWAP(s[MBEDTLS_BYTE_3(p)], t); + p = pi[4]; + SWAP(s[MBEDTLS_BYTE_0(p)], t); SWAP(s[MBEDTLS_BYTE_1(p)], t); + SWAP(s[MBEDTLS_BYTE_2(p)], t); SWAP(s[MBEDTLS_BYTE_3(p)], t); + p = pi[5]; + SWAP(s[MBEDTLS_BYTE_0(p)], t); SWAP(s[MBEDTLS_BYTE_1(p)], t); + SWAP(s[MBEDTLS_BYTE_2(p)], t); SWAP(s[MBEDTLS_BYTE_3(p)], t); +#endif + + /* Chi */ +#if MBEDTLS_SHA3_CHI_UNROLL == 0 //no-check-names + for (i = 0; i <= 20; i += 5) { + lane[0] = s[i]; lane[1] = s[i + 1]; lane[2] = s[i + 2]; + lane[3] = s[i + 3]; lane[4] = s[i + 4]; + s[i + 0] ^= (~lane[1]) & lane[2]; + s[i + 1] ^= (~lane[2]) & lane[3]; + s[i + 2] ^= (~lane[3]) & lane[4]; + s[i + 3] ^= (~lane[4]) & lane[0]; + s[i + 4] ^= (~lane[0]) & lane[1]; + } +#else + lane[0] = s[0]; lane[1] = s[1]; lane[2] = s[2]; lane[3] = s[3]; lane[4] = s[4]; + s[0] ^= (~lane[1]) & lane[2]; + s[1] ^= (~lane[2]) & lane[3]; + s[2] ^= (~lane[3]) & lane[4]; + s[3] ^= (~lane[4]) & lane[0]; + s[4] ^= (~lane[0]) & lane[1]; + + lane[0] = s[5]; lane[1] = s[6]; lane[2] = s[7]; lane[3] = s[8]; lane[4] = s[9]; + s[5] ^= (~lane[1]) & lane[2]; + s[6] ^= (~lane[2]) & lane[3]; + s[7] ^= (~lane[3]) & lane[4]; + s[8] ^= (~lane[4]) & lane[0]; + s[9] ^= (~lane[0]) & lane[1]; + + lane[0] = s[10]; lane[1] = s[11]; lane[2] = s[12]; lane[3] = s[13]; lane[4] = s[14]; + s[10] ^= (~lane[1]) & lane[2]; + s[11] ^= (~lane[2]) & lane[3]; + s[12] ^= (~lane[3]) & lane[4]; + s[13] ^= (~lane[4]) & lane[0]; + s[14] ^= (~lane[0]) & lane[1]; + + lane[0] = s[15]; lane[1] = s[16]; lane[2] = s[17]; lane[3] = s[18]; lane[4] = s[19]; + s[15] ^= (~lane[1]) & lane[2]; + s[16] ^= (~lane[2]) & lane[3]; + s[17] ^= (~lane[3]) & lane[4]; + s[18] ^= (~lane[4]) & lane[0]; + s[19] ^= (~lane[0]) & lane[1]; + + lane[0] = s[20]; lane[1] = s[21]; lane[2] = s[22]; lane[3] = s[23]; lane[4] = s[24]; + s[20] ^= (~lane[1]) & lane[2]; + s[21] ^= (~lane[2]) & lane[3]; + s[22] ^= (~lane[3]) & lane[4]; + s[23] ^= (~lane[4]) & lane[0]; + s[24] ^= (~lane[0]) & lane[1]; +#endif + + /* Iota */ + /* Decompress the round masks (see definition of rc) */ + s[0] ^= ((iota_r_packed[round] & 0x40ull) << 57 | + (iota_r_packed[round] & 0x20ull) << 26 | + (iota_r_packed[round] & 0x10ull) << 11 | + (iota_r_packed[round] & 0x8f)); + } +} + +void mbedtls_sha3_init(mbedtls_sha3_context *ctx) +{ + memset(ctx, 0, sizeof(mbedtls_sha3_context)); +} + +void mbedtls_sha3_free(mbedtls_sha3_context *ctx) +{ + if (ctx == NULL) { + return; + } + + mbedtls_platform_zeroize(ctx, sizeof(mbedtls_sha3_context)); +} + +void mbedtls_sha3_clone(mbedtls_sha3_context *dst, + const mbedtls_sha3_context *src) +{ + *dst = *src; +} + +/* + * SHA-3 context setup + */ +int mbedtls_sha3_starts(mbedtls_sha3_context *ctx, mbedtls_sha3_id id) +{ + switch (id) { + case MBEDTLS_SHA3_224: + ctx->olen = 224 / 8; + ctx->max_block_size = 1152 / 8; + break; + case MBEDTLS_SHA3_256: + ctx->olen = 256 / 8; + ctx->max_block_size = 1088 / 8; + break; + case MBEDTLS_SHA3_384: + ctx->olen = 384 / 8; + ctx->max_block_size = 832 / 8; + break; + case MBEDTLS_SHA3_512: + ctx->olen = 512 / 8; + ctx->max_block_size = 576 / 8; + break; + default: + return MBEDTLS_ERR_SHA3_BAD_INPUT_DATA; + } + + memset(ctx->state, 0, sizeof(ctx->state)); + ctx->index = 0; + + return 0; +} + +/* + * SHA-3 process buffer + */ +int mbedtls_sha3_update(mbedtls_sha3_context *ctx, + const uint8_t *input, + size_t ilen) +{ + if (ilen >= 8) { + // 8-byte align index + int align_bytes = 8 - (ctx->index % 8); + if (align_bytes) { + for (; align_bytes > 0; align_bytes--) { + ABSORB(ctx, ctx->index, *input++); + ilen--; + ctx->index++; + } + if ((ctx->index = ctx->index % ctx->max_block_size) == 0) { + keccak_f1600(ctx); + } + } + + // process input in 8-byte chunks + while (ilen >= 8) { + ABSORB(ctx, ctx->index, MBEDTLS_GET_UINT64_LE(input, 0)); + input += 8; + ilen -= 8; + if ((ctx->index = (ctx->index + 8) % ctx->max_block_size) == 0) { + keccak_f1600(ctx); + } + } + } + + // handle remaining bytes + while (ilen-- > 0) { + ABSORB(ctx, ctx->index, *input++); + if ((ctx->index = (ctx->index + 1) % ctx->max_block_size) == 0) { + keccak_f1600(ctx); + } + } + + return 0; +} + +int mbedtls_sha3_finish(mbedtls_sha3_context *ctx, + uint8_t *output, size_t olen) +{ + int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED; + + /* Catch SHA-3 families, with fixed output length */ + if (ctx->olen > 0) { + if (ctx->olen > olen) { + ret = MBEDTLS_ERR_SHA3_BAD_INPUT_DATA; + goto exit; + } + olen = ctx->olen; + } + + ABSORB(ctx, ctx->index, XOR_BYTE); + ABSORB(ctx, ctx->max_block_size - 1, 0x80); + keccak_f1600(ctx); + ctx->index = 0; + + while (olen-- > 0) { + *output++ = SQUEEZE(ctx, ctx->index); + + if ((ctx->index = (ctx->index + 1) % ctx->max_block_size) == 0) { + keccak_f1600(ctx); + } + } + + ret = 0; + +exit: + mbedtls_sha3_free(ctx); + return ret; +} + +/* + * output = SHA-3( input buffer ) + */ +int mbedtls_sha3(mbedtls_sha3_id id, const uint8_t *input, + size_t ilen, uint8_t *output, size_t olen) +{ + int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED; + mbedtls_sha3_context ctx; + + mbedtls_sha3_init(&ctx); + + /* Sanity checks are performed in every mbedtls_sha3_xxx() */ + if ((ret = mbedtls_sha3_starts(&ctx, id)) != 0) { + goto exit; + } + + if ((ret = mbedtls_sha3_update(&ctx, input, ilen)) != 0) { + goto exit; + } + + if ((ret = mbedtls_sha3_finish(&ctx, output, olen)) != 0) { + goto exit; + } + +exit: + mbedtls_sha3_free(&ctx); + + return ret; +} + +/**************** Self-tests ****************/ + +#if defined(MBEDTLS_SELF_TEST) + +static const unsigned char test_data[2][4] = +{ + "", + "abc", +}; + +static const size_t test_data_len[2] = +{ + 0, /* "" */ + 3 /* "abc" */ +}; + +static const unsigned char test_hash_sha3_224[2][28] = +{ + { /* "" */ + 0x6B, 0x4E, 0x03, 0x42, 0x36, 0x67, 0xDB, 0xB7, + 0x3B, 0x6E, 0x15, 0x45, 0x4F, 0x0E, 0xB1, 0xAB, + 0xD4, 0x59, 0x7F, 0x9A, 0x1B, 0x07, 0x8E, 0x3F, + 0x5B, 0x5A, 0x6B, 0xC7 + }, + { /* "abc" */ + 0xE6, 0x42, 0x82, 0x4C, 0x3F, 0x8C, 0xF2, 0x4A, + 0xD0, 0x92, 0x34, 0xEE, 0x7D, 0x3C, 0x76, 0x6F, + 0xC9, 0xA3, 0xA5, 0x16, 0x8D, 0x0C, 0x94, 0xAD, + 0x73, 0xB4, 0x6F, 0xDF + } +}; + +static const unsigned char test_hash_sha3_256[2][32] = +{ + { /* "" */ + 0xA7, 0xFF, 0xC6, 0xF8, 0xBF, 0x1E, 0xD7, 0x66, + 0x51, 0xC1, 0x47, 0x56, 0xA0, 0x61, 0xD6, 0x62, + 0xF5, 0x80, 0xFF, 0x4D, 0xE4, 0x3B, 0x49, 0xFA, + 0x82, 0xD8, 0x0A, 0x4B, 0x80, 0xF8, 0x43, 0x4A + }, + { /* "abc" */ + 0x3A, 0x98, 0x5D, 0xA7, 0x4F, 0xE2, 0x25, 0xB2, + 0x04, 0x5C, 0x17, 0x2D, 0x6B, 0xD3, 0x90, 0xBD, + 0x85, 0x5F, 0x08, 0x6E, 0x3E, 0x9D, 0x52, 0x5B, + 0x46, 0xBF, 0xE2, 0x45, 0x11, 0x43, 0x15, 0x32 + } +}; + +static const unsigned char test_hash_sha3_384[2][48] = +{ + { /* "" */ + 0x0C, 0x63, 0xA7, 0x5B, 0x84, 0x5E, 0x4F, 0x7D, + 0x01, 0x10, 0x7D, 0x85, 0x2E, 0x4C, 0x24, 0x85, + 0xC5, 0x1A, 0x50, 0xAA, 0xAA, 0x94, 0xFC, 0x61, + 0x99, 0x5E, 0x71, 0xBB, 0xEE, 0x98, 0x3A, 0x2A, + 0xC3, 0x71, 0x38, 0x31, 0x26, 0x4A, 0xDB, 0x47, + 0xFB, 0x6B, 0xD1, 0xE0, 0x58, 0xD5, 0xF0, 0x04 + }, + { /* "abc" */ + 0xEC, 0x01, 0x49, 0x82, 0x88, 0x51, 0x6F, 0xC9, + 0x26, 0x45, 0x9F, 0x58, 0xE2, 0xC6, 0xAD, 0x8D, + 0xF9, 0xB4, 0x73, 0xCB, 0x0F, 0xC0, 0x8C, 0x25, + 0x96, 0xDA, 0x7C, 0xF0, 0xE4, 0x9B, 0xE4, 0xB2, + 0x98, 0xD8, 0x8C, 0xEA, 0x92, 0x7A, 0xC7, 0xF5, + 0x39, 0xF1, 0xED, 0xF2, 0x28, 0x37, 0x6D, 0x25 + } +}; + +static const unsigned char test_hash_sha3_512[2][64] = +{ + { /* "" */ + 0xA6, 0x9F, 0x73, 0xCC, 0xA2, 0x3A, 0x9A, 0xC5, + 0xC8, 0xB5, 0x67, 0xDC, 0x18, 0x5A, 0x75, 0x6E, + 0x97, 0xC9, 0x82, 0x16, 0x4F, 0xE2, 0x58, 0x59, + 0xE0, 0xD1, 0xDC, 0xC1, 0x47, 0x5C, 0x80, 0xA6, + 0x15, 0xB2, 0x12, 0x3A, 0xF1, 0xF5, 0xF9, 0x4C, + 0x11, 0xE3, 0xE9, 0x40, 0x2C, 0x3A, 0xC5, 0x58, + 0xF5, 0x00, 0x19, 0x9D, 0x95, 0xB6, 0xD3, 0xE3, + 0x01, 0x75, 0x85, 0x86, 0x28, 0x1D, 0xCD, 0x26 + }, + { /* "abc" */ + 0xB7, 0x51, 0x85, 0x0B, 0x1A, 0x57, 0x16, 0x8A, + 0x56, 0x93, 0xCD, 0x92, 0x4B, 0x6B, 0x09, 0x6E, + 0x08, 0xF6, 0x21, 0x82, 0x74, 0x44, 0xF7, 0x0D, + 0x88, 0x4F, 0x5D, 0x02, 0x40, 0xD2, 0x71, 0x2E, + 0x10, 0xE1, 0x16, 0xE9, 0x19, 0x2A, 0xF3, 0xC9, + 0x1A, 0x7E, 0xC5, 0x76, 0x47, 0xE3, 0x93, 0x40, + 0x57, 0x34, 0x0B, 0x4C, 0xF4, 0x08, 0xD5, 0xA5, + 0x65, 0x92, 0xF8, 0x27, 0x4E, 0xEC, 0x53, 0xF0 + } +}; + +static const unsigned char long_kat_hash_sha3_224[28] = +{ + 0xD6, 0x93, 0x35, 0xB9, 0x33, 0x25, 0x19, 0x2E, + 0x51, 0x6A, 0x91, 0x2E, 0x6D, 0x19, 0xA1, 0x5C, + 0xB5, 0x1C, 0x6E, 0xD5, 0xC1, 0x52, 0x43, 0xE7, + 0xA7, 0xFD, 0x65, 0x3C +}; + +static const unsigned char long_kat_hash_sha3_256[32] = +{ + 0x5C, 0x88, 0x75, 0xAE, 0x47, 0x4A, 0x36, 0x34, + 0xBA, 0x4F, 0xD5, 0x5E, 0xC8, 0x5B, 0xFF, 0xD6, + 0x61, 0xF3, 0x2A, 0xCA, 0x75, 0xC6, 0xD6, 0x99, + 0xD0, 0xCD, 0xCB, 0x6C, 0x11, 0x58, 0x91, 0xC1 +}; + +static const unsigned char long_kat_hash_sha3_384[48] = +{ + 0xEE, 0xE9, 0xE2, 0x4D, 0x78, 0xC1, 0x85, 0x53, + 0x37, 0x98, 0x34, 0x51, 0xDF, 0x97, 0xC8, 0xAD, + 0x9E, 0xED, 0xF2, 0x56, 0xC6, 0x33, 0x4F, 0x8E, + 0x94, 0x8D, 0x25, 0x2D, 0x5E, 0x0E, 0x76, 0x84, + 0x7A, 0xA0, 0x77, 0x4D, 0xDB, 0x90, 0xA8, 0x42, + 0x19, 0x0D, 0x2C, 0x55, 0x8B, 0x4B, 0x83, 0x40 +}; + +static const unsigned char long_kat_hash_sha3_512[64] = +{ + 0x3C, 0x3A, 0x87, 0x6D, 0xA1, 0x40, 0x34, 0xAB, + 0x60, 0x62, 0x7C, 0x07, 0x7B, 0xB9, 0x8F, 0x7E, + 0x12, 0x0A, 0x2A, 0x53, 0x70, 0x21, 0x2D, 0xFF, + 0xB3, 0x38, 0x5A, 0x18, 0xD4, 0xF3, 0x88, 0x59, + 0xED, 0x31, 0x1D, 0x0A, 0x9D, 0x51, 0x41, 0xCE, + 0x9C, 0xC5, 0xC6, 0x6E, 0xE6, 0x89, 0xB2, 0x66, + 0xA8, 0xAA, 0x18, 0xAC, 0xE8, 0x28, 0x2A, 0x0E, + 0x0D, 0xB5, 0x96, 0xC9, 0x0B, 0x0A, 0x7B, 0x87 +}; + +static int mbedtls_sha3_kat_test(int verbose, + const char *type_name, + mbedtls_sha3_id id, + int test_num) +{ + uint8_t hash[64]; + int result; + + result = mbedtls_sha3(id, + test_data[test_num], test_data_len[test_num], + hash, sizeof(hash)); + if (result != 0) { + if (verbose != 0) { + mbedtls_printf(" %s test %d error code: %d\n", + type_name, test_num, result); + } + + return result; + } + + switch (id) { + case MBEDTLS_SHA3_224: + result = memcmp(hash, test_hash_sha3_224[test_num], 28); + break; + case MBEDTLS_SHA3_256: + result = memcmp(hash, test_hash_sha3_256[test_num], 32); + break; + case MBEDTLS_SHA3_384: + result = memcmp(hash, test_hash_sha3_384[test_num], 48); + break; + case MBEDTLS_SHA3_512: + result = memcmp(hash, test_hash_sha3_512[test_num], 64); + break; + default: + break; + } + + if (0 != result) { + if (verbose != 0) { + mbedtls_printf(" %s test %d failed\n", type_name, test_num); + } + + return -1; + } + + if (verbose != 0) { + mbedtls_printf(" %s test %d passed\n", type_name, test_num); + } + + return 0; +} + +static int mbedtls_sha3_long_kat_test(int verbose, + const char *type_name, + mbedtls_sha3_id id) +{ + mbedtls_sha3_context ctx; + unsigned char buffer[1000]; + unsigned char hash[64]; + int result = 0; + + memset(buffer, 'a', 1000); + + if (verbose != 0) { + mbedtls_printf(" %s long KAT test ", type_name); + } + + mbedtls_sha3_init(&ctx); + + result = mbedtls_sha3_starts(&ctx, id); + if (result != 0) { + if (verbose != 0) { + mbedtls_printf("setup failed\n "); + } + } + + /* Process 1,000,000 (one million) 'a' characters */ + for (int i = 0; i < 1000; i++) { + result = mbedtls_sha3_update(&ctx, buffer, 1000); + if (result != 0) { + if (verbose != 0) { + mbedtls_printf("update error code: %i\n", result); + } + + goto cleanup; + } + } + + result = mbedtls_sha3_finish(&ctx, hash, sizeof(hash)); + if (result != 0) { + if (verbose != 0) { + mbedtls_printf("finish error code: %d\n", result); + } + + goto cleanup; + } + + switch (id) { + case MBEDTLS_SHA3_224: + result = memcmp(hash, long_kat_hash_sha3_224, 28); + break; + case MBEDTLS_SHA3_256: + result = memcmp(hash, long_kat_hash_sha3_256, 32); + break; + case MBEDTLS_SHA3_384: + result = memcmp(hash, long_kat_hash_sha3_384, 48); + break; + case MBEDTLS_SHA3_512: + result = memcmp(hash, long_kat_hash_sha3_512, 64); + break; + default: + break; + } + + if (result != 0) { + if (verbose != 0) { + mbedtls_printf("failed\n"); + } + } + + if (verbose != 0) { + mbedtls_printf("passed\n"); + } + +cleanup: + mbedtls_sha3_free(&ctx); + return result; +} + +int mbedtls_sha3_self_test(int verbose) +{ + int i; + + /* SHA-3 Known Answer Tests (KAT) */ + for (i = 0; i < 2; i++) { + if (0 != mbedtls_sha3_kat_test(verbose, + "SHA3-224", MBEDTLS_SHA3_224, i)) { + return 1; + } + + if (0 != mbedtls_sha3_kat_test(verbose, + "SHA3-256", MBEDTLS_SHA3_256, i)) { + return 1; + } + + if (0 != mbedtls_sha3_kat_test(verbose, + "SHA3-384", MBEDTLS_SHA3_384, i)) { + return 1; + } + + if (0 != mbedtls_sha3_kat_test(verbose, + "SHA3-512", MBEDTLS_SHA3_512, i)) { + return 1; + } + } + + /* SHA-3 long KAT tests */ + if (0 != mbedtls_sha3_long_kat_test(verbose, + "SHA3-224", MBEDTLS_SHA3_224)) { + return 1; + } + + if (0 != mbedtls_sha3_long_kat_test(verbose, + "SHA3-256", MBEDTLS_SHA3_256)) { + return 1; + } + + if (0 != mbedtls_sha3_long_kat_test(verbose, + "SHA3-384", MBEDTLS_SHA3_384)) { + return 1; + } + + if (0 != mbedtls_sha3_long_kat_test(verbose, + "SHA3-512", MBEDTLS_SHA3_512)) { + return 1; + } + + if (verbose != 0) { + mbedtls_printf("\n"); + } + + return 0; +} +#endif /* MBEDTLS_SELF_TEST */ + +#endif /* MBEDTLS_SHA3_C */ diff --git a/vendor/mbedtls/library/sha512.c b/vendor/mbedtls/library/sha512.c index f6b7c1fbf1..6dcea8da5d 100644 --- a/vendor/mbedtls/library/sha512.c +++ b/vendor/mbedtls/library/sha512.c @@ -2,19 +2,7 @@ * FIPS-180-2 compliant SHA-384/512 implementation * * Copyright The Mbed TLS Contributors - * SPDX-License-Identifier: Apache-2.0 - * - * Licensed under the Apache License, Version 2.0 (the "License"); you may - * not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT - * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. + * SPDX-License-Identifier: Apache-2.0 OR GPL-2.0-or-later */ /* * The SHA-512 Secure Hash Standard was published by NIST in 2002. @@ -22,9 +10,25 @@ * http://csrc.nist.gov/publications/fips/fips180-2/fips180-2.pdf */ +#if defined(__aarch64__) && !defined(__ARM_FEATURE_SHA512) && \ + defined(__clang__) && __clang_major__ >= 7 +/* TODO: Re-consider above after https://reviews.llvm.org/D131064 merged. + * + * The intrinsic declaration are guarded by predefined ACLE macros in clang: + * these are normally only enabled by the -march option on the command line. + * By defining the macros ourselves we gain access to those declarations without + * requiring -march on the command line. + * + * `arm_neon.h` is included by common.h, so we put these defines + * at the top of this file, before any includes. + */ +#define __ARM_FEATURE_SHA512 1 +#define MBEDTLS_ENABLE_ARM_SHA3_EXTENSIONS_COMPILER_FLAG +#endif + #include "common.h" -#if defined(MBEDTLS_SHA512_C) +#if defined(MBEDTLS_SHA512_C) || defined(MBEDTLS_SHA384_C) #include "mbedtls/sha512.h" #include "mbedtls/platform_util.h" @@ -40,12 +44,171 @@ #include "mbedtls/platform.h" -#define SHA512_VALIDATE_RET(cond) \ - MBEDTLS_INTERNAL_VALIDATE_RET(cond, MBEDTLS_ERR_SHA512_BAD_INPUT_DATA) -#define SHA512_VALIDATE(cond) MBEDTLS_INTERNAL_VALIDATE(cond) +#if defined(__aarch64__) +# if defined(MBEDTLS_SHA512_USE_A64_CRYPTO_IF_PRESENT) || \ + defined(MBEDTLS_SHA512_USE_A64_CRYPTO_ONLY) +/* *INDENT-OFF* */ +# if !defined(MBEDTLS_HAVE_NEON_INTRINSICS) +# error "Target does not support NEON instructions" +# endif +/* + * Best performance comes from most recent compilers, with intrinsics and -O3. + * Must compile with -march=armv8.2-a+sha3, but we can't detect armv8.2-a, and + * can't always detect __ARM_FEATURE_SHA512 (notably clang 7-12). + * + * GCC < 8 won't work at all (lacks the sha512 instructions) + * GCC >= 8 uses intrinsics, sets __ARM_FEATURE_SHA512 + * + * Clang < 7 won't work at all (lacks the sha512 instructions) + * Clang 7-12 don't have intrinsics (but we work around that with inline + * assembler) or __ARM_FEATURE_SHA512 + * Clang == 13.0.0 same as clang 12 (only seen on macOS) + * Clang >= 13.0.1 has __ARM_FEATURE_SHA512 and intrinsics + */ +# if !defined(__ARM_FEATURE_SHA512) || defined(MBEDTLS_ENABLE_ARM_SHA3_EXTENSIONS_COMPILER_FLAG) + /* Test Clang first, as it defines __GNUC__ */ +# if defined(__ARMCOMPILER_VERSION) +# if __ARMCOMPILER_VERSION < 6090000 +# error "A more recent armclang is required for MBEDTLS_SHA512_USE_A64_CRYPTO_*" +# elif __ARMCOMPILER_VERSION == 6090000 +# error "Must use minimum -march=armv8.2-a+sha3 for MBEDTLS_SHA512_USE_A64_CRYPTO_*" +# else +# pragma clang attribute push (__attribute__((target("sha3"))), apply_to=function) +# define MBEDTLS_POP_TARGET_PRAGMA +# endif +# elif defined(__clang__) +# if __clang_major__ < 7 +# error "A more recent Clang is required for MBEDTLS_SHA512_USE_A64_CRYPTO_*" +# else +# pragma clang attribute push (__attribute__((target("sha3"))), apply_to=function) +# define MBEDTLS_POP_TARGET_PRAGMA +# endif +# elif defined(__GNUC__) +# if __GNUC__ < 8 +# error "A more recent GCC is required for MBEDTLS_SHA512_USE_A64_CRYPTO_*" +# else +# pragma GCC push_options +# pragma GCC target ("arch=armv8.2-a+sha3") +# define MBEDTLS_POP_TARGET_PRAGMA +# endif +# else +# error "Only GCC and Clang supported for MBEDTLS_SHA512_USE_A64_CRYPTO_*" +# endif +# endif +/* *INDENT-ON* */ +# endif +# if defined(MBEDTLS_SHA512_USE_A64_CRYPTO_IF_PRESENT) +# if defined(__unix__) +# if defined(__linux__) +/* Our preferred method of detection is getauxval() */ +# include +# if !defined(HWCAP_SHA512) +/* The same header that declares getauxval() should provide the HWCAP_xxx + * constants to analyze its return value. However, the libc may be too + * old to have the constant that we need. So if it's missing, assume that + * the value is the same one used by the Linux kernel ABI. + */ +# define HWCAP_SHA512 (1 << 21) +# endif +# endif +/* Use SIGILL on Unix, and fall back to it on Linux */ +# include +# endif +# endif +#elif !defined(MBEDTLS_PLATFORM_IS_WINDOWS_ON_ARM64) +# undef MBEDTLS_SHA512_USE_A64_CRYPTO_ONLY +# undef MBEDTLS_SHA512_USE_A64_CRYPTO_IF_PRESENT +#endif + +#if defined(MBEDTLS_SHA512_USE_A64_CRYPTO_IF_PRESENT) +/* + * Capability detection code comes early, so we can disable + * MBEDTLS_SHA512_USE_A64_CRYPTO_IF_PRESENT if no detection mechanism found + */ +#if defined(HWCAP_SHA512) +static int mbedtls_a64_crypto_sha512_determine_support(void) +{ + return (getauxval(AT_HWCAP) & HWCAP_SHA512) ? 1 : 0; +} +#elif defined(__APPLE__) +#include +#include + +static int mbedtls_a64_crypto_sha512_determine_support(void) +{ + int value = 0; + size_t value_len = sizeof(value); + + int ret = sysctlbyname("hw.optional.armv8_2_sha512", &value, &value_len, + NULL, 0); + return ret == 0 && value != 0; +} +#elif defined(MBEDTLS_PLATFORM_IS_WINDOWS_ON_ARM64) +/* + * As of March 2022, there don't appear to be any PF_ARM_V8_* flags + * available to pass to IsProcessorFeaturePresent() to check for + * SHA-512 support. So we fall back to the C code only. + */ +#if defined(_MSC_VER) +#pragma message "No mechanism to detect A64_CRYPTO found, using C code only" +#else +#warning "No mechanism to detect A64_CRYPTO found, using C code only" +#endif +#elif defined(__unix__) && defined(SIG_SETMASK) +/* Detection with SIGILL, setjmp() and longjmp() */ +#include +#include + +static jmp_buf return_from_sigill; + +/* + * A64 SHA512 support detection via SIGILL + */ +static void sigill_handler(int signal) +{ + (void) signal; + longjmp(return_from_sigill, 1); +} + +static int mbedtls_a64_crypto_sha512_determine_support(void) +{ + struct sigaction old_action, new_action; + + sigset_t old_mask; + if (sigprocmask(0, NULL, &old_mask)) { + return 0; + } + + sigemptyset(&new_action.sa_mask); + new_action.sa_flags = 0; + new_action.sa_handler = sigill_handler; + + sigaction(SIGILL, &new_action, &old_action); + + static int ret = 0; + + if (setjmp(return_from_sigill) == 0) { /* First return only */ + /* If this traps, we will return a second time from setjmp() with 1 */ + asm ("sha512h q0, q0, v0.2d" : : : "v0"); + ret = 1; + } + + sigaction(SIGILL, &old_action, NULL); + sigprocmask(SIG_SETMASK, &old_mask, NULL); + + return ret; +} +#else +#warning "No mechanism to detect A64_CRYPTO found, using C code only" +#undef MBEDTLS_SHA512_USE_A64_CRYPTO_IF_PRESENT +#endif /* HWCAP_SHA512, __APPLE__, __unix__ && SIG_SETMASK */ + +#endif /* MBEDTLS_SHA512_USE_A64_CRYPTO_IF_PRESENT */ #if !defined(MBEDTLS_SHA512_ALT) +#define SHA512_BLOCK_SIZE 128 + #if defined(MBEDTLS_SHA512_SMALLER) static void sha512_put_uint64_be(uint64_t n, unsigned char *b, uint8_t i) { @@ -57,8 +220,6 @@ static void sha512_put_uint64_be(uint64_t n, unsigned char *b, uint8_t i) void mbedtls_sha512_init(mbedtls_sha512_context *ctx) { - SHA512_VALIDATE(ctx != NULL); - memset(ctx, 0, sizeof(mbedtls_sha512_context)); } @@ -74,29 +235,33 @@ void mbedtls_sha512_free(mbedtls_sha512_context *ctx) void mbedtls_sha512_clone(mbedtls_sha512_context *dst, const mbedtls_sha512_context *src) { - SHA512_VALIDATE(dst != NULL); - SHA512_VALIDATE(src != NULL); - *dst = *src; } /* * SHA-512 context setup */ -int mbedtls_sha512_starts_ret(mbedtls_sha512_context *ctx, int is384) +int mbedtls_sha512_starts(mbedtls_sha512_context *ctx, int is384) { - SHA512_VALIDATE_RET(ctx != NULL); -#if !defined(MBEDTLS_SHA512_NO_SHA384) - SHA512_VALIDATE_RET(is384 == 0 || is384 == 1); -#else - SHA512_VALIDATE_RET(is384 == 0); +#if defined(MBEDTLS_SHA384_C) && defined(MBEDTLS_SHA512_C) + if (is384 != 0 && is384 != 1) { + return MBEDTLS_ERR_SHA512_BAD_INPUT_DATA; + } +#elif defined(MBEDTLS_SHA512_C) + if (is384 != 0) { + return MBEDTLS_ERR_SHA512_BAD_INPUT_DATA; + } +#else /* defined MBEDTLS_SHA384_C only */ + if (is384 == 0) { + return MBEDTLS_ERR_SHA512_BAD_INPUT_DATA; + } #endif ctx->total[0] = 0; ctx->total[1] = 0; if (is384 == 0) { - /* SHA-512 */ +#if defined(MBEDTLS_SHA512_C) ctx->state[0] = UL64(0x6A09E667F3BCC908); ctx->state[1] = UL64(0xBB67AE8584CAA73B); ctx->state[2] = UL64(0x3C6EF372FE94F82B); @@ -105,11 +270,9 @@ int mbedtls_sha512_starts_ret(mbedtls_sha512_context *ctx, int is384) ctx->state[5] = UL64(0x9B05688C2B3E6C1F); ctx->state[6] = UL64(0x1F83D9ABFB41BD6B); ctx->state[7] = UL64(0x5BE0CD19137E2179); +#endif /* MBEDTLS_SHA512_C */ } else { -#if defined(MBEDTLS_SHA512_NO_SHA384) - return MBEDTLS_ERR_SHA512_BAD_INPUT_DATA; -#else - /* SHA-384 */ +#if defined(MBEDTLS_SHA384_C) ctx->state[0] = UL64(0xCBBB9D5DC1059ED8); ctx->state[1] = UL64(0x629A292A367CD507); ctx->state[2] = UL64(0x9159015A3070DD17); @@ -118,24 +281,16 @@ int mbedtls_sha512_starts_ret(mbedtls_sha512_context *ctx, int is384) ctx->state[5] = UL64(0x8EB44A8768581511); ctx->state[6] = UL64(0xDB0C2E0D64F98FA7); ctx->state[7] = UL64(0x47B5481DBEFA4FA4); -#endif /* MBEDTLS_SHA512_NO_SHA384 */ +#endif /* MBEDTLS_SHA384_C */ } -#if !defined(MBEDTLS_SHA512_NO_SHA384) +#if defined(MBEDTLS_SHA384_C) ctx->is384 = is384; #endif return 0; } -#if !defined(MBEDTLS_DEPRECATED_REMOVED) -void mbedtls_sha512_starts(mbedtls_sha512_context *ctx, - int is384) -{ - mbedtls_sha512_starts_ret(ctx, is384); -} -#endif - #if !defined(MBEDTLS_SHA512_PROCESS_ALT) /* @@ -184,9 +339,267 @@ static const uint64_t K[80] = UL64(0x4CC5D4BECB3E42B6), UL64(0x597F299CFC657E2A), UL64(0x5FCB6FAB3AD6FAEC), UL64(0x6C44198C4A475817) }; +#endif -int mbedtls_internal_sha512_process(mbedtls_sha512_context *ctx, - const unsigned char data[128]) +#if defined(MBEDTLS_SHA512_USE_A64_CRYPTO_IF_PRESENT) || \ + defined(MBEDTLS_SHA512_USE_A64_CRYPTO_ONLY) + +#if defined(MBEDTLS_SHA512_USE_A64_CRYPTO_ONLY) +# define mbedtls_internal_sha512_process_many_a64_crypto mbedtls_internal_sha512_process_many +# define mbedtls_internal_sha512_process_a64_crypto mbedtls_internal_sha512_process +#endif + +/* Accelerated SHA-512 implementation originally written by Simon Tatham for PuTTY, + * under the MIT licence; dual-licensed as Apache 2 with his kind permission. + */ + +#if defined(__clang__) && \ + (__clang_major__ < 13 || \ + (__clang_major__ == 13 && __clang_minor__ == 0 && __clang_patchlevel__ == 0)) +static inline uint64x2_t vsha512su0q_u64(uint64x2_t x, uint64x2_t y) +{ + asm ("sha512su0 %0.2D,%1.2D" : "+w" (x) : "w" (y)); + return x; +} +static inline uint64x2_t vsha512su1q_u64(uint64x2_t x, uint64x2_t y, uint64x2_t z) +{ + asm ("sha512su1 %0.2D,%1.2D,%2.2D" : "+w" (x) : "w" (y), "w" (z)); + return x; +} +static inline uint64x2_t vsha512hq_u64(uint64x2_t x, uint64x2_t y, uint64x2_t z) +{ + asm ("sha512h %0,%1,%2.2D" : "+w" (x) : "w" (y), "w" (z)); + return x; +} +static inline uint64x2_t vsha512h2q_u64(uint64x2_t x, uint64x2_t y, uint64x2_t z) +{ + asm ("sha512h2 %0,%1,%2.2D" : "+w" (x) : "w" (y), "w" (z)); + return x; +} +#endif /* __clang__ etc */ + +static size_t mbedtls_internal_sha512_process_many_a64_crypto( + mbedtls_sha512_context *ctx, const uint8_t *msg, size_t len) +{ + uint64x2_t ab = vld1q_u64(&ctx->state[0]); + uint64x2_t cd = vld1q_u64(&ctx->state[2]); + uint64x2_t ef = vld1q_u64(&ctx->state[4]); + uint64x2_t gh = vld1q_u64(&ctx->state[6]); + + size_t processed = 0; + + for (; + len >= SHA512_BLOCK_SIZE; + processed += SHA512_BLOCK_SIZE, + msg += SHA512_BLOCK_SIZE, + len -= SHA512_BLOCK_SIZE) { + uint64x2_t initial_sum, sum, intermed; + + uint64x2_t ab_orig = ab; + uint64x2_t cd_orig = cd; + uint64x2_t ef_orig = ef; + uint64x2_t gh_orig = gh; + + uint64x2_t s0 = (uint64x2_t) vld1q_u8(msg + 16 * 0); + uint64x2_t s1 = (uint64x2_t) vld1q_u8(msg + 16 * 1); + uint64x2_t s2 = (uint64x2_t) vld1q_u8(msg + 16 * 2); + uint64x2_t s3 = (uint64x2_t) vld1q_u8(msg + 16 * 3); + uint64x2_t s4 = (uint64x2_t) vld1q_u8(msg + 16 * 4); + uint64x2_t s5 = (uint64x2_t) vld1q_u8(msg + 16 * 5); + uint64x2_t s6 = (uint64x2_t) vld1q_u8(msg + 16 * 6); + uint64x2_t s7 = (uint64x2_t) vld1q_u8(msg + 16 * 7); + +#if __BYTE_ORDER__ == __ORDER_LITTLE_ENDIAN__ /* assume LE if these not defined; untested on BE */ + s0 = vreinterpretq_u64_u8(vrev64q_u8(vreinterpretq_u8_u64(s0))); + s1 = vreinterpretq_u64_u8(vrev64q_u8(vreinterpretq_u8_u64(s1))); + s2 = vreinterpretq_u64_u8(vrev64q_u8(vreinterpretq_u8_u64(s2))); + s3 = vreinterpretq_u64_u8(vrev64q_u8(vreinterpretq_u8_u64(s3))); + s4 = vreinterpretq_u64_u8(vrev64q_u8(vreinterpretq_u8_u64(s4))); + s5 = vreinterpretq_u64_u8(vrev64q_u8(vreinterpretq_u8_u64(s5))); + s6 = vreinterpretq_u64_u8(vrev64q_u8(vreinterpretq_u8_u64(s6))); + s7 = vreinterpretq_u64_u8(vrev64q_u8(vreinterpretq_u8_u64(s7))); +#endif + + /* Rounds 0 and 1 */ + initial_sum = vaddq_u64(s0, vld1q_u64(&K[0])); + sum = vaddq_u64(vextq_u64(initial_sum, initial_sum, 1), gh); + intermed = vsha512hq_u64(sum, vextq_u64(ef, gh, 1), vextq_u64(cd, ef, 1)); + gh = vsha512h2q_u64(intermed, cd, ab); + cd = vaddq_u64(cd, intermed); + + /* Rounds 2 and 3 */ + initial_sum = vaddq_u64(s1, vld1q_u64(&K[2])); + sum = vaddq_u64(vextq_u64(initial_sum, initial_sum, 1), ef); + intermed = vsha512hq_u64(sum, vextq_u64(cd, ef, 1), vextq_u64(ab, cd, 1)); + ef = vsha512h2q_u64(intermed, ab, gh); + ab = vaddq_u64(ab, intermed); + + /* Rounds 4 and 5 */ + initial_sum = vaddq_u64(s2, vld1q_u64(&K[4])); + sum = vaddq_u64(vextq_u64(initial_sum, initial_sum, 1), cd); + intermed = vsha512hq_u64(sum, vextq_u64(ab, cd, 1), vextq_u64(gh, ab, 1)); + cd = vsha512h2q_u64(intermed, gh, ef); + gh = vaddq_u64(gh, intermed); + + /* Rounds 6 and 7 */ + initial_sum = vaddq_u64(s3, vld1q_u64(&K[6])); + sum = vaddq_u64(vextq_u64(initial_sum, initial_sum, 1), ab); + intermed = vsha512hq_u64(sum, vextq_u64(gh, ab, 1), vextq_u64(ef, gh, 1)); + ab = vsha512h2q_u64(intermed, ef, cd); + ef = vaddq_u64(ef, intermed); + + /* Rounds 8 and 9 */ + initial_sum = vaddq_u64(s4, vld1q_u64(&K[8])); + sum = vaddq_u64(vextq_u64(initial_sum, initial_sum, 1), gh); + intermed = vsha512hq_u64(sum, vextq_u64(ef, gh, 1), vextq_u64(cd, ef, 1)); + gh = vsha512h2q_u64(intermed, cd, ab); + cd = vaddq_u64(cd, intermed); + + /* Rounds 10 and 11 */ + initial_sum = vaddq_u64(s5, vld1q_u64(&K[10])); + sum = vaddq_u64(vextq_u64(initial_sum, initial_sum, 1), ef); + intermed = vsha512hq_u64(sum, vextq_u64(cd, ef, 1), vextq_u64(ab, cd, 1)); + ef = vsha512h2q_u64(intermed, ab, gh); + ab = vaddq_u64(ab, intermed); + + /* Rounds 12 and 13 */ + initial_sum = vaddq_u64(s6, vld1q_u64(&K[12])); + sum = vaddq_u64(vextq_u64(initial_sum, initial_sum, 1), cd); + intermed = vsha512hq_u64(sum, vextq_u64(ab, cd, 1), vextq_u64(gh, ab, 1)); + cd = vsha512h2q_u64(intermed, gh, ef); + gh = vaddq_u64(gh, intermed); + + /* Rounds 14 and 15 */ + initial_sum = vaddq_u64(s7, vld1q_u64(&K[14])); + sum = vaddq_u64(vextq_u64(initial_sum, initial_sum, 1), ab); + intermed = vsha512hq_u64(sum, vextq_u64(gh, ab, 1), vextq_u64(ef, gh, 1)); + ab = vsha512h2q_u64(intermed, ef, cd); + ef = vaddq_u64(ef, intermed); + + for (unsigned int t = 16; t < 80; t += 16) { + /* Rounds t and t + 1 */ + s0 = vsha512su1q_u64(vsha512su0q_u64(s0, s1), s7, vextq_u64(s4, s5, 1)); + initial_sum = vaddq_u64(s0, vld1q_u64(&K[t])); + sum = vaddq_u64(vextq_u64(initial_sum, initial_sum, 1), gh); + intermed = vsha512hq_u64(sum, vextq_u64(ef, gh, 1), vextq_u64(cd, ef, 1)); + gh = vsha512h2q_u64(intermed, cd, ab); + cd = vaddq_u64(cd, intermed); + + /* Rounds t + 2 and t + 3 */ + s1 = vsha512su1q_u64(vsha512su0q_u64(s1, s2), s0, vextq_u64(s5, s6, 1)); + initial_sum = vaddq_u64(s1, vld1q_u64(&K[t + 2])); + sum = vaddq_u64(vextq_u64(initial_sum, initial_sum, 1), ef); + intermed = vsha512hq_u64(sum, vextq_u64(cd, ef, 1), vextq_u64(ab, cd, 1)); + ef = vsha512h2q_u64(intermed, ab, gh); + ab = vaddq_u64(ab, intermed); + + /* Rounds t + 4 and t + 5 */ + s2 = vsha512su1q_u64(vsha512su0q_u64(s2, s3), s1, vextq_u64(s6, s7, 1)); + initial_sum = vaddq_u64(s2, vld1q_u64(&K[t + 4])); + sum = vaddq_u64(vextq_u64(initial_sum, initial_sum, 1), cd); + intermed = vsha512hq_u64(sum, vextq_u64(ab, cd, 1), vextq_u64(gh, ab, 1)); + cd = vsha512h2q_u64(intermed, gh, ef); + gh = vaddq_u64(gh, intermed); + + /* Rounds t + 6 and t + 7 */ + s3 = vsha512su1q_u64(vsha512su0q_u64(s3, s4), s2, vextq_u64(s7, s0, 1)); + initial_sum = vaddq_u64(s3, vld1q_u64(&K[t + 6])); + sum = vaddq_u64(vextq_u64(initial_sum, initial_sum, 1), ab); + intermed = vsha512hq_u64(sum, vextq_u64(gh, ab, 1), vextq_u64(ef, gh, 1)); + ab = vsha512h2q_u64(intermed, ef, cd); + ef = vaddq_u64(ef, intermed); + + /* Rounds t + 8 and t + 9 */ + s4 = vsha512su1q_u64(vsha512su0q_u64(s4, s5), s3, vextq_u64(s0, s1, 1)); + initial_sum = vaddq_u64(s4, vld1q_u64(&K[t + 8])); + sum = vaddq_u64(vextq_u64(initial_sum, initial_sum, 1), gh); + intermed = vsha512hq_u64(sum, vextq_u64(ef, gh, 1), vextq_u64(cd, ef, 1)); + gh = vsha512h2q_u64(intermed, cd, ab); + cd = vaddq_u64(cd, intermed); + + /* Rounds t + 10 and t + 11 */ + s5 = vsha512su1q_u64(vsha512su0q_u64(s5, s6), s4, vextq_u64(s1, s2, 1)); + initial_sum = vaddq_u64(s5, vld1q_u64(&K[t + 10])); + sum = vaddq_u64(vextq_u64(initial_sum, initial_sum, 1), ef); + intermed = vsha512hq_u64(sum, vextq_u64(cd, ef, 1), vextq_u64(ab, cd, 1)); + ef = vsha512h2q_u64(intermed, ab, gh); + ab = vaddq_u64(ab, intermed); + + /* Rounds t + 12 and t + 13 */ + s6 = vsha512su1q_u64(vsha512su0q_u64(s6, s7), s5, vextq_u64(s2, s3, 1)); + initial_sum = vaddq_u64(s6, vld1q_u64(&K[t + 12])); + sum = vaddq_u64(vextq_u64(initial_sum, initial_sum, 1), cd); + intermed = vsha512hq_u64(sum, vextq_u64(ab, cd, 1), vextq_u64(gh, ab, 1)); + cd = vsha512h2q_u64(intermed, gh, ef); + gh = vaddq_u64(gh, intermed); + + /* Rounds t + 14 and t + 15 */ + s7 = vsha512su1q_u64(vsha512su0q_u64(s7, s0), s6, vextq_u64(s3, s4, 1)); + initial_sum = vaddq_u64(s7, vld1q_u64(&K[t + 14])); + sum = vaddq_u64(vextq_u64(initial_sum, initial_sum, 1), ab); + intermed = vsha512hq_u64(sum, vextq_u64(gh, ab, 1), vextq_u64(ef, gh, 1)); + ab = vsha512h2q_u64(intermed, ef, cd); + ef = vaddq_u64(ef, intermed); + } + + ab = vaddq_u64(ab, ab_orig); + cd = vaddq_u64(cd, cd_orig); + ef = vaddq_u64(ef, ef_orig); + gh = vaddq_u64(gh, gh_orig); + } + + vst1q_u64(&ctx->state[0], ab); + vst1q_u64(&ctx->state[2], cd); + vst1q_u64(&ctx->state[4], ef); + vst1q_u64(&ctx->state[6], gh); + + return processed; +} + +#if defined(MBEDTLS_SHA512_USE_A64_CRYPTO_IF_PRESENT) +/* + * This function is for internal use only if we are building both C and A64 + * versions, otherwise it is renamed to be the public mbedtls_internal_sha512_process() + */ +static +#endif +int mbedtls_internal_sha512_process_a64_crypto(mbedtls_sha512_context *ctx, + const unsigned char data[SHA512_BLOCK_SIZE]) +{ + return (mbedtls_internal_sha512_process_many_a64_crypto(ctx, data, + SHA512_BLOCK_SIZE) == + SHA512_BLOCK_SIZE) ? 0 : -1; +} + +#endif /* MBEDTLS_SHA512_USE_A64_CRYPTO_IF_PRESENT || MBEDTLS_SHA512_USE_A64_CRYPTO_ONLY */ + +#if defined(MBEDTLS_POP_TARGET_PRAGMA) +#if defined(__clang__) +#pragma clang attribute pop +#elif defined(__GNUC__) +#pragma GCC pop_options +#endif +#undef MBEDTLS_POP_TARGET_PRAGMA +#endif + + +#if !defined(MBEDTLS_SHA512_USE_A64_CRYPTO_IF_PRESENT) +#define mbedtls_internal_sha512_process_many_c mbedtls_internal_sha512_process_many +#define mbedtls_internal_sha512_process_c mbedtls_internal_sha512_process +#endif + + +#if !defined(MBEDTLS_SHA512_PROCESS_ALT) && !defined(MBEDTLS_SHA512_USE_A64_CRYPTO_ONLY) + +#if defined(MBEDTLS_SHA512_USE_A64_CRYPTO_IF_PRESENT) +/* + * This function is for internal use only if we are building both C and A64 + * versions, otherwise it is renamed to be the public mbedtls_internal_sha512_process() + */ +static +#endif +int mbedtls_internal_sha512_process_c(mbedtls_sha512_context *ctx, + const unsigned char data[SHA512_BLOCK_SIZE]) { int i; struct { @@ -194,9 +607,6 @@ int mbedtls_internal_sha512_process(mbedtls_sha512_context *ctx, uint64_t A[8]; } local; - SHA512_VALIDATE_RET(ctx != NULL); - SHA512_VALIDATE_RET((const unsigned char *) data != NULL); - #define SHR(x, n) ((x) >> (n)) #define ROTR(x, n) (SHR((x), (n)) | ((x) << (64 - (n)))) @@ -280,35 +690,87 @@ int mbedtls_internal_sha512_process(mbedtls_sha512_context *ctx, return 0; } -#if !defined(MBEDTLS_DEPRECATED_REMOVED) -void mbedtls_sha512_process(mbedtls_sha512_context *ctx, - const unsigned char data[128]) +#endif /* !MBEDTLS_SHA512_PROCESS_ALT && !MBEDTLS_SHA512_USE_A64_CRYPTO_ONLY */ + + +#if !defined(MBEDTLS_SHA512_USE_A64_CRYPTO_ONLY) + +static size_t mbedtls_internal_sha512_process_many_c( + mbedtls_sha512_context *ctx, const uint8_t *data, size_t len) { - mbedtls_internal_sha512_process(ctx, data); + size_t processed = 0; + + while (len >= SHA512_BLOCK_SIZE) { + if (mbedtls_internal_sha512_process_c(ctx, data) != 0) { + return 0; + } + + data += SHA512_BLOCK_SIZE; + len -= SHA512_BLOCK_SIZE; + + processed += SHA512_BLOCK_SIZE; + } + + return processed; } -#endif -#endif /* !MBEDTLS_SHA512_PROCESS_ALT */ + +#endif /* !MBEDTLS_SHA512_USE_A64_CRYPTO_ONLY */ + + +#if defined(MBEDTLS_SHA512_USE_A64_CRYPTO_IF_PRESENT) + +static int mbedtls_a64_crypto_sha512_has_support(void) +{ + static int done = 0; + static int supported = 0; + + if (!done) { + supported = mbedtls_a64_crypto_sha512_determine_support(); + done = 1; + } + + return supported; +} + +static size_t mbedtls_internal_sha512_process_many(mbedtls_sha512_context *ctx, + const uint8_t *msg, size_t len) +{ + if (mbedtls_a64_crypto_sha512_has_support()) { + return mbedtls_internal_sha512_process_many_a64_crypto(ctx, msg, len); + } else { + return mbedtls_internal_sha512_process_many_c(ctx, msg, len); + } +} + +int mbedtls_internal_sha512_process(mbedtls_sha512_context *ctx, + const unsigned char data[SHA512_BLOCK_SIZE]) +{ + if (mbedtls_a64_crypto_sha512_has_support()) { + return mbedtls_internal_sha512_process_a64_crypto(ctx, data); + } else { + return mbedtls_internal_sha512_process_c(ctx, data); + } +} + +#endif /* MBEDTLS_SHA512_USE_A64_CRYPTO_IF_PRESENT */ /* * SHA-512 process buffer */ -int mbedtls_sha512_update_ret(mbedtls_sha512_context *ctx, - const unsigned char *input, - size_t ilen) +int mbedtls_sha512_update(mbedtls_sha512_context *ctx, + const unsigned char *input, + size_t ilen) { int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED; size_t fill; unsigned int left; - SHA512_VALIDATE_RET(ctx != NULL); - SHA512_VALIDATE_RET(ilen == 0 || input != NULL); - if (ilen == 0) { return 0; } left = (unsigned int) (ctx->total[0] & 0x7F); - fill = 128 - left; + fill = SHA512_BLOCK_SIZE - left; ctx->total[0] += (uint64_t) ilen; @@ -328,13 +790,15 @@ int mbedtls_sha512_update_ret(mbedtls_sha512_context *ctx, left = 0; } - while (ilen >= 128) { - if ((ret = mbedtls_internal_sha512_process(ctx, input)) != 0) { - return ret; + while (ilen >= SHA512_BLOCK_SIZE) { + size_t processed = + mbedtls_internal_sha512_process_many(ctx, input, ilen); + if (processed < SHA512_BLOCK_SIZE) { + return MBEDTLS_ERR_ERROR_GENERIC_ERROR; } - input += 128; - ilen -= 128; + input += processed; + ilen -= processed; } if (ilen > 0) { @@ -344,27 +808,16 @@ int mbedtls_sha512_update_ret(mbedtls_sha512_context *ctx, return 0; } -#if !defined(MBEDTLS_DEPRECATED_REMOVED) -void mbedtls_sha512_update(mbedtls_sha512_context *ctx, - const unsigned char *input, - size_t ilen) -{ - mbedtls_sha512_update_ret(ctx, input, ilen); -} -#endif - /* * SHA-512 final digest */ -int mbedtls_sha512_finish_ret(mbedtls_sha512_context *ctx, - unsigned char output[64]) +int mbedtls_sha512_finish(mbedtls_sha512_context *ctx, + unsigned char *output) { int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED; unsigned used; uint64_t high, low; - - SHA512_VALIDATE_RET(ctx != NULL); - SHA512_VALIDATE_RET((unsigned char *) output != NULL); + int truncated = 0; /* * Add padding: 0x80 then 0x00 until 16 bytes remain for the length @@ -378,10 +831,10 @@ int mbedtls_sha512_finish_ret(mbedtls_sha512_context *ctx, memset(ctx->buffer + used, 0, 112 - used); } else { /* We'll need an extra block */ - memset(ctx->buffer + used, 0, 128 - used); + memset(ctx->buffer + used, 0, SHA512_BLOCK_SIZE - used); if ((ret = mbedtls_internal_sha512_process(ctx, ctx->buffer)) != 0) { - return ret; + goto exit; } memset(ctx->buffer, 0, 112); @@ -398,7 +851,7 @@ int mbedtls_sha512_finish_ret(mbedtls_sha512_context *ctx, sha512_put_uint64_be(low, ctx->buffer, 120); if ((ret = mbedtls_internal_sha512_process(ctx, ctx->buffer)) != 0) { - return ret; + goto exit; } /* @@ -411,8 +864,7 @@ int mbedtls_sha512_finish_ret(mbedtls_sha512_context *ctx, sha512_put_uint64_be(ctx->state[4], output, 32); sha512_put_uint64_be(ctx->state[5], output, 40); - int truncated = 0; -#if !defined(MBEDTLS_SHA512_NO_SHA384) +#if defined(MBEDTLS_SHA384_C) truncated = ctx->is384; #endif if (!truncated) { @@ -420,49 +872,51 @@ int mbedtls_sha512_finish_ret(mbedtls_sha512_context *ctx, sha512_put_uint64_be(ctx->state[7], output, 56); } - return 0; -} + ret = 0; -#if !defined(MBEDTLS_DEPRECATED_REMOVED) -void mbedtls_sha512_finish(mbedtls_sha512_context *ctx, - unsigned char output[64]) -{ - mbedtls_sha512_finish_ret(ctx, output); +exit: + mbedtls_sha512_free(ctx); + return ret; } -#endif #endif /* !MBEDTLS_SHA512_ALT */ /* * output = SHA-512( input buffer ) */ -int mbedtls_sha512_ret(const unsigned char *input, - size_t ilen, - unsigned char output[64], - int is384) +int mbedtls_sha512(const unsigned char *input, + size_t ilen, + unsigned char *output, + int is384) { int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED; mbedtls_sha512_context ctx; -#if !defined(MBEDTLS_SHA512_NO_SHA384) - SHA512_VALIDATE_RET(is384 == 0 || is384 == 1); -#else - SHA512_VALIDATE_RET(is384 == 0); +#if defined(MBEDTLS_SHA384_C) && defined(MBEDTLS_SHA512_C) + if (is384 != 0 && is384 != 1) { + return MBEDTLS_ERR_SHA512_BAD_INPUT_DATA; + } +#elif defined(MBEDTLS_SHA512_C) + if (is384 != 0) { + return MBEDTLS_ERR_SHA512_BAD_INPUT_DATA; + } +#else /* defined MBEDTLS_SHA384_C only */ + if (is384 == 0) { + return MBEDTLS_ERR_SHA512_BAD_INPUT_DATA; + } #endif - SHA512_VALIDATE_RET(ilen == 0 || input != NULL); - SHA512_VALIDATE_RET((unsigned char *) output != NULL); mbedtls_sha512_init(&ctx); - if ((ret = mbedtls_sha512_starts_ret(&ctx, is384)) != 0) { + if ((ret = mbedtls_sha512_starts(&ctx, is384)) != 0) { goto exit; } - if ((ret = mbedtls_sha512_update_ret(&ctx, input, ilen)) != 0) { + if ((ret = mbedtls_sha512_update(&ctx, input, ilen)) != 0) { goto exit; } - if ((ret = mbedtls_sha512_finish_ret(&ctx, output)) != 0) { + if ((ret = mbedtls_sha512_finish(&ctx, output)) != 0) { goto exit; } @@ -472,22 +926,12 @@ int mbedtls_sha512_ret(const unsigned char *input, return ret; } -#if !defined(MBEDTLS_DEPRECATED_REMOVED) -void mbedtls_sha512(const unsigned char *input, - size_t ilen, - unsigned char output[64], - int is384) -{ - mbedtls_sha512_ret(input, ilen, output, is384); -} -#endif - #if defined(MBEDTLS_SELF_TEST) /* * FIPS-180-2 test vectors */ -static const unsigned char sha512_test_buf[3][113] = +static const unsigned char sha_test_buf[3][113] = { { "abc" }, { @@ -496,17 +940,19 @@ static const unsigned char sha512_test_buf[3][113] = { "" } }; -static const size_t sha512_test_buflen[3] = +static const size_t sha_test_buflen[3] = { 3, 112, 1000 }; -static const unsigned char sha512_test_sum[][64] = +typedef const unsigned char (sha_test_sum_t)[64]; + +/* + * SHA-384 test vectors + */ +#if defined(MBEDTLS_SHA384_C) +static sha_test_sum_t sha384_test_sum[] = { -#if !defined(MBEDTLS_SHA512_NO_SHA384) - /* - * SHA-384 test vectors - */ { 0xCB, 0x00, 0x75, 0x3F, 0x45, 0xA3, 0x5E, 0x8B, 0xB5, 0xA0, 0x3D, 0x69, 0x9A, 0xC6, 0x50, 0x07, 0x27, 0x2C, 0x32, 0xAB, 0x0E, 0xDE, 0xD1, 0x63, @@ -524,12 +970,16 @@ static const unsigned char sha512_test_sum[][64] = 0xED, 0x14, 0x9E, 0x9C, 0x00, 0xF2, 0x48, 0x52, 0x79, 0x72, 0xCE, 0xC5, 0x70, 0x4C, 0x2A, 0x5B, 0x07, 0xB8, 0xB3, 0xDC, 0x38, 0xEC, 0xC4, 0xEB, - 0xAE, 0x97, 0xDD, 0xD8, 0x7F, 0x3D, 0x89, 0x85 }, -#endif /* !MBEDTLS_SHA512_NO_SHA384 */ + 0xAE, 0x97, 0xDD, 0xD8, 0x7F, 0x3D, 0x89, 0x85 } +}; +#endif /* MBEDTLS_SHA384_C */ - /* - * SHA-512 test vectors - */ +/* + * SHA-512 test vectors + */ +#if defined(MBEDTLS_SHA512_C) +static sha_test_sum_t sha512_test_sum[] = +{ { 0xDD, 0xAF, 0x35, 0xA1, 0x93, 0x61, 0x7A, 0xBA, 0xCC, 0x41, 0x73, 0x49, 0xAE, 0x20, 0x41, 0x31, 0x12, 0xE6, 0xFA, 0x4E, 0x89, 0xA9, 0x7E, 0xA2, @@ -555,19 +1005,23 @@ static const unsigned char sha512_test_sum[][64] = 0xEB, 0x00, 0x9C, 0x5C, 0x2C, 0x49, 0xAA, 0x2E, 0x4E, 0xAD, 0xB2, 0x17, 0xAD, 0x8C, 0xC0, 0x9B } }; +#endif /* MBEDTLS_SHA512_C */ -#define ARRAY_LENGTH(a) (sizeof(a) / sizeof((a)[0])) - -/* - * Checkup routine - */ -int mbedtls_sha512_self_test(int verbose) +static int mbedtls_sha512_common_self_test(int verbose, int is384) { - int i, j, k, buflen, ret = 0; + int i, buflen, ret = 0; unsigned char *buf; unsigned char sha512sum[64]; mbedtls_sha512_context ctx; +#if defined(MBEDTLS_SHA384_C) && defined(MBEDTLS_SHA512_C) + sha_test_sum_t *sha_test_sum = (is384) ? sha384_test_sum : sha512_test_sum; +#elif defined(MBEDTLS_SHA512_C) + sha_test_sum_t *sha_test_sum = sha512_test_sum; +#else + sha_test_sum_t *sha_test_sum = sha384_test_sum; +#endif + buf = mbedtls_calloc(1024, sizeof(unsigned char)); if (NULL == buf) { if (verbose != 0) { @@ -579,44 +1033,37 @@ int mbedtls_sha512_self_test(int verbose) mbedtls_sha512_init(&ctx); - for (i = 0; i < (int) ARRAY_LENGTH(sha512_test_sum); i++) { - j = i % 3; -#if !defined(MBEDTLS_SHA512_NO_SHA384) - k = i < 3; -#else - k = 0; -#endif - + for (i = 0; i < 3; i++) { if (verbose != 0) { - mbedtls_printf(" SHA-%d test #%d: ", 512 - k * 128, j + 1); + mbedtls_printf(" SHA-%d test #%d: ", 512 - is384 * 128, i + 1); } - if ((ret = mbedtls_sha512_starts_ret(&ctx, k)) != 0) { + if ((ret = mbedtls_sha512_starts(&ctx, is384)) != 0) { goto fail; } - if (j == 2) { + if (i == 2) { memset(buf, 'a', buflen = 1000); - for (j = 0; j < 1000; j++) { - ret = mbedtls_sha512_update_ret(&ctx, buf, buflen); + for (int j = 0; j < 1000; j++) { + ret = mbedtls_sha512_update(&ctx, buf, buflen); if (ret != 0) { goto fail; } } } else { - ret = mbedtls_sha512_update_ret(&ctx, sha512_test_buf[j], - sha512_test_buflen[j]); + ret = mbedtls_sha512_update(&ctx, sha_test_buf[i], + sha_test_buflen[i]); if (ret != 0) { goto fail; } } - if ((ret = mbedtls_sha512_finish_ret(&ctx, sha512sum)) != 0) { + if ((ret = mbedtls_sha512_finish(&ctx, sha512sum)) != 0) { goto fail; } - if (memcmp(sha512sum, sha512_test_sum[i], 64 - k * 16) != 0) { + if (memcmp(sha512sum, sha_test_sum[i], 64 - is384 * 16) != 0) { ret = 1; goto fail; } @@ -644,8 +1091,22 @@ int mbedtls_sha512_self_test(int verbose) return ret; } +#if defined(MBEDTLS_SHA512_C) +int mbedtls_sha512_self_test(int verbose) +{ + return mbedtls_sha512_common_self_test(verbose, 0); +} +#endif /* MBEDTLS_SHA512_C */ + +#if defined(MBEDTLS_SHA384_C) +int mbedtls_sha384_self_test(int verbose) +{ + return mbedtls_sha512_common_self_test(verbose, 1); +} +#endif /* MBEDTLS_SHA384_C */ + #undef ARRAY_LENGTH #endif /* MBEDTLS_SELF_TEST */ -#endif /* MBEDTLS_SHA512_C */ +#endif /* MBEDTLS_SHA512_C || MBEDTLS_SHA384_C */ diff --git a/vendor/mbedtls/library/ssl_cache.c b/vendor/mbedtls/library/ssl_cache.c index 6082074b25..772cb8fdfe 100644 --- a/vendor/mbedtls/library/ssl_cache.c +++ b/vendor/mbedtls/library/ssl_cache.c @@ -2,19 +2,7 @@ * SSL session cache implementation * * Copyright The Mbed TLS Contributors - * SPDX-License-Identifier: Apache-2.0 - * - * Licensed under the Apache License, Version 2.0 (the "License"); you may - * not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT - * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. + * SPDX-License-Identifier: Apache-2.0 OR GPL-2.0-or-later */ /* * These session callbacks use a simple chained list @@ -26,10 +14,10 @@ #if defined(MBEDTLS_SSL_CACHE_C) #include "mbedtls/platform.h" -#include "mbedtls/error.h" #include "mbedtls/ssl_cache.h" -#include "mbedtls/ssl_internal.h" +#include "ssl_misc.h" +#include "mbedtls/error.h" #include @@ -45,76 +33,73 @@ void mbedtls_ssl_cache_init(mbedtls_ssl_cache_context *cache) #endif } -int mbedtls_ssl_cache_get(void *data, mbedtls_ssl_session *session) +MBEDTLS_CHECK_RETURN_CRITICAL +static int ssl_cache_find_entry(mbedtls_ssl_cache_context *cache, + unsigned char const *session_id, + size_t session_id_len, + mbedtls_ssl_cache_entry **dst) { int ret = MBEDTLS_ERR_SSL_CACHE_ENTRY_NOT_FOUND; #if defined(MBEDTLS_HAVE_TIME) mbedtls_time_t t = mbedtls_time(NULL); #endif - mbedtls_ssl_cache_context *cache = (mbedtls_ssl_cache_context *) data; - mbedtls_ssl_cache_entry *cur, *entry; - -#if defined(MBEDTLS_THREADING_C) - if ((ret = mbedtls_mutex_lock(&cache->mutex)) != 0) { - return ret; - } -#endif - - cur = cache->chain; - entry = NULL; - - while (cur != NULL) { - entry = cur; - cur = cur->next; + mbedtls_ssl_cache_entry *cur; + for (cur = cache->chain; cur != NULL; cur = cur->next) { #if defined(MBEDTLS_HAVE_TIME) if (cache->timeout != 0 && - (int) (t - entry->timestamp) > cache->timeout) { + (int) (t - cur->timestamp) > cache->timeout) { continue; } #endif - if (session->id_len != entry->session.id_len || - memcmp(session->id, entry->session.id, - entry->session.id_len) != 0) { + if (session_id_len != cur->session_id_len || + memcmp(session_id, cur->session_id, + cur->session_id_len) != 0) { continue; } - ret = mbedtls_ssl_session_copy(session, &entry->session); - if (ret != 0) { - goto exit; - } - -#if defined(MBEDTLS_X509_CRT_PARSE_C) && \ - defined(MBEDTLS_SSL_KEEP_PEER_CERTIFICATE) - /* - * Restore peer certificate (without rest of the original chain) - */ - if (entry->peer_cert.p != NULL) { - /* `session->peer_cert` is NULL after the call to - * mbedtls_ssl_session_copy(), because cache entries - * have the `peer_cert` field set to NULL. */ - - if ((session->peer_cert = mbedtls_calloc(1, - sizeof(mbedtls_x509_crt))) == NULL) { - ret = MBEDTLS_ERR_SSL_ALLOC_FAILED; - goto exit; - } - - mbedtls_x509_crt_init(session->peer_cert); - if ((ret = mbedtls_x509_crt_parse(session->peer_cert, entry->peer_cert.p, - entry->peer_cert.len)) != 0) { - mbedtls_free(session->peer_cert); - session->peer_cert = NULL; - goto exit; - } - } -#endif /* MBEDTLS_X509_CRT_PARSE_C && MBEDTLS_SSL_KEEP_PEER_CERTIFICATE */ + break; + } + if (cur != NULL) { + *dst = cur; ret = 0; + } + + return ret; +} + + +int mbedtls_ssl_cache_get(void *data, + unsigned char const *session_id, + size_t session_id_len, + mbedtls_ssl_session *session) +{ + int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED; + mbedtls_ssl_cache_context *cache = (mbedtls_ssl_cache_context *) data; + mbedtls_ssl_cache_entry *entry; + +#if defined(MBEDTLS_THREADING_C) + if ((ret = mbedtls_mutex_lock(&cache->mutex)) != 0) { + return ret; + } +#endif + + ret = ssl_cache_find_entry(cache, session_id, session_id_len, &entry); + if (ret != 0) { goto exit; } + ret = mbedtls_ssl_session_load(session, + entry->session, + entry->session_len); + if (ret != 0) { + goto exit; + } + + ret = 0; + exit: #if defined(MBEDTLS_THREADING_C) if (mbedtls_mutex_unlock(&cache->mutex) != 0) { @@ -125,149 +110,251 @@ int mbedtls_ssl_cache_get(void *data, mbedtls_ssl_session *session) return ret; } -int mbedtls_ssl_cache_set(void *data, const mbedtls_ssl_session *session) +/* zeroize a cache entry */ +static void ssl_cache_entry_zeroize(mbedtls_ssl_cache_entry *entry) +{ + if (entry == NULL) { + return; + } + + /* zeroize and free session structure */ + if (entry->session != NULL) { + mbedtls_zeroize_and_free(entry->session, entry->session_len); + } + + /* zeroize the whole entry structure */ + mbedtls_platform_zeroize(entry, sizeof(mbedtls_ssl_cache_entry)); +} + +MBEDTLS_CHECK_RETURN_CRITICAL +static int ssl_cache_pick_writing_slot(mbedtls_ssl_cache_context *cache, + unsigned char const *session_id, + size_t session_id_len, + mbedtls_ssl_cache_entry **dst) { - int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED; #if defined(MBEDTLS_HAVE_TIME) mbedtls_time_t t = mbedtls_time(NULL), oldest = 0; +#endif /* MBEDTLS_HAVE_TIME */ + mbedtls_ssl_cache_entry *old = NULL; -#endif - mbedtls_ssl_cache_context *cache = (mbedtls_ssl_cache_context *) data; - mbedtls_ssl_cache_entry *cur, *prv; int count = 0; - -#if defined(MBEDTLS_THREADING_C) - if ((ret = mbedtls_mutex_lock(&cache->mutex)) != 0) { - return ret; + mbedtls_ssl_cache_entry *cur, *last; + + /* Check 1: Is there already an entry with the given session ID? + * + * If yes, overwrite it. + * + * If not, `count` will hold the size of the session cache + * at the end of this loop, and `last` will point to the last + * entry, both of which will be used later. */ + + last = NULL; + for (cur = cache->chain; cur != NULL; cur = cur->next) { + count++; + if (session_id_len == cur->session_id_len && + memcmp(session_id, cur->session_id, cur->session_id_len) == 0) { + goto found; + } + last = cur; } -#endif - cur = cache->chain; - prv = NULL; - - while (cur != NULL) { - count++; + /* Check 2: Is there an outdated entry in the cache? + * + * If so, overwrite it. + * + * If not, remember the oldest entry in `old` for later. + */ #if defined(MBEDTLS_HAVE_TIME) + for (cur = cache->chain; cur != NULL; cur = cur->next) { if (cache->timeout != 0 && (int) (t - cur->timestamp) > cache->timeout) { - cur->timestamp = t; - break; /* expired, reuse this slot, update timestamp */ + goto found; } -#endif - if (memcmp(session->id, cur->session.id, cur->session.id_len) == 0) { - break; /* client reconnected, keep timestamp for session id */ - - } -#if defined(MBEDTLS_HAVE_TIME) if (oldest == 0 || cur->timestamp < oldest) { oldest = cur->timestamp; old = cur; } -#endif + } +#endif /* MBEDTLS_HAVE_TIME */ - prv = cur; - cur = cur->next; + /* Check 3: Is there free space in the cache? */ + + if (count < cache->max_entries) { + /* Create new entry */ + cur = mbedtls_calloc(1, sizeof(mbedtls_ssl_cache_entry)); + if (cur == NULL) { + return MBEDTLS_ERR_SSL_ALLOC_FAILED; + } + + /* Append to the end of the linked list. */ + if (last == NULL) { + cache->chain = cur; + } else { + last->next = cur; + } + + goto found; } - if (cur == NULL) { + /* Last resort: The cache is full and doesn't contain any outdated + * elements. In this case, we evict the oldest one, judged by timestamp + * (if present) or cache-order. */ + #if defined(MBEDTLS_HAVE_TIME) - /* - * Reuse oldest entry if max_entries reached - */ - if (count >= cache->max_entries) { - if (old == NULL) { - /* This should only happen on an ill-configured cache - * with max_entries == 0. */ - ret = MBEDTLS_ERR_SSL_INTERNAL_ERROR; - goto exit; - } - - cur = old; - } + if (old == NULL) { + /* This should only happen on an ill-configured cache + * with max_entries == 0. */ + return MBEDTLS_ERR_SSL_INTERNAL_ERROR; + } #else /* MBEDTLS_HAVE_TIME */ - /* - * Reuse first entry in chain if max_entries reached, - * but move to last place - */ - if (count >= cache->max_entries) { - if (cache->chain == NULL) { - ret = MBEDTLS_ERR_SSL_INTERNAL_ERROR; - goto exit; - } - - cur = cache->chain; - cache->chain = cur->next; - cur->next = NULL; - prv->next = cur; - } + /* Reuse first entry in chain, but move to last place. */ + if (cache->chain == NULL) { + /* This should never happen */ + return MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED; + } + + old = cache->chain; + cache->chain = old->next; + old->next = NULL; + last->next = old; #endif /* MBEDTLS_HAVE_TIME */ - else { - /* - * max_entries not reached, create new entry - */ - cur = mbedtls_calloc(1, sizeof(mbedtls_ssl_cache_entry)); - if (cur == NULL) { - ret = MBEDTLS_ERR_SSL_ALLOC_FAILED; - goto exit; - } - - if (prv == NULL) { - cache->chain = cur; - } else { - prv->next = cur; - } - } + + /* Now `old` points to the oldest entry to be overwritten. */ + cur = old; + +found: + + /* If we're reusing an entry, free it first. */ + if (cur->session != NULL) { + /* `ssl_cache_entry_zeroize` would break the chain, + * so we reuse `old` to record `next` temporarily. */ + old = cur->next; + ssl_cache_entry_zeroize(cur); + cur->next = old; + } #if defined(MBEDTLS_HAVE_TIME) - cur->timestamp = t; + cur->timestamp = t; +#endif + + *dst = cur; + return 0; +} + +int mbedtls_ssl_cache_set(void *data, + unsigned char const *session_id, + size_t session_id_len, + const mbedtls_ssl_session *session) +{ + int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED; + mbedtls_ssl_cache_context *cache = (mbedtls_ssl_cache_context *) data; + mbedtls_ssl_cache_entry *cur; + + size_t session_serialized_len = 0; + unsigned char *session_serialized = NULL; + +#if defined(MBEDTLS_THREADING_C) + if ((ret = mbedtls_mutex_lock(&cache->mutex)) != 0) { + return ret; + } #endif + + ret = ssl_cache_pick_writing_slot(cache, + session_id, session_id_len, + &cur); + if (ret != 0) { + goto exit; } -#if defined(MBEDTLS_X509_CRT_PARSE_C) && \ - defined(MBEDTLS_SSL_KEEP_PEER_CERTIFICATE) - /* - * If we're reusing an entry, free its certificate first - */ - if (cur->peer_cert.p != NULL) { - mbedtls_free(cur->peer_cert.p); - memset(&cur->peer_cert, 0, sizeof(mbedtls_x509_buf)); + /* Check how much space we need to serialize the session + * and allocate a sufficiently large buffer. */ + ret = mbedtls_ssl_session_save(session, NULL, 0, &session_serialized_len); + if (ret != MBEDTLS_ERR_SSL_BUFFER_TOO_SMALL) { + goto exit; + } + + session_serialized = mbedtls_calloc(1, session_serialized_len); + if (session_serialized == NULL) { + ret = MBEDTLS_ERR_SSL_ALLOC_FAILED; + goto exit; } -#endif /* MBEDTLS_X509_CRT_PARSE_C && MBEDTLS_SSL_KEEP_PEER_CERTIFICATE */ - - /* Copy the entire session; this temporarily makes a copy of the - * X.509 CRT structure even though we only want to store the raw CRT. - * This inefficiency will go away as soon as we implement on-demand - * parsing of CRTs, in which case there's no need for the `peer_cert` - * field anymore in the first place, and we're done after this call. */ - ret = mbedtls_ssl_session_copy(&cur->session, session); + + /* Now serialize the session into the allocated buffer. */ + ret = mbedtls_ssl_session_save(session, + session_serialized, + session_serialized_len, + &session_serialized_len); if (ret != 0) { goto exit; } -#if defined(MBEDTLS_X509_CRT_PARSE_C) && \ - defined(MBEDTLS_SSL_KEEP_PEER_CERTIFICATE) - /* If present, free the X.509 structure and only store the raw CRT data. */ - if (cur->session.peer_cert != NULL) { - cur->peer_cert.p = - mbedtls_calloc(1, cur->session.peer_cert->raw.len); - if (cur->peer_cert.p == NULL) { - ret = MBEDTLS_ERR_SSL_ALLOC_FAILED; - goto exit; - } + if (session_id_len > sizeof(cur->session_id)) { + ret = MBEDTLS_ERR_SSL_BAD_INPUT_DATA; + goto exit; + } + cur->session_id_len = session_id_len; + memcpy(cur->session_id, session_id, session_id_len); + + cur->session = session_serialized; + cur->session_len = session_serialized_len; + session_serialized = NULL; + + ret = 0; + +exit: +#if defined(MBEDTLS_THREADING_C) + if (mbedtls_mutex_unlock(&cache->mutex) != 0) { + ret = MBEDTLS_ERR_THREADING_MUTEX_ERROR; + } +#endif + + if (session_serialized != NULL) { + mbedtls_zeroize_and_free(session_serialized, session_serialized_len); + session_serialized = NULL; + } + + return ret; +} - memcpy(cur->peer_cert.p, - cur->session.peer_cert->raw.p, - cur->session.peer_cert->raw.len); - cur->peer_cert.len = session->peer_cert->raw.len; +int mbedtls_ssl_cache_remove(void *data, + unsigned char const *session_id, + size_t session_id_len) +{ + int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED; + mbedtls_ssl_cache_context *cache = (mbedtls_ssl_cache_context *) data; + mbedtls_ssl_cache_entry *entry; + mbedtls_ssl_cache_entry *prev; - mbedtls_x509_crt_free(cur->session.peer_cert); - mbedtls_free(cur->session.peer_cert); - cur->session.peer_cert = NULL; +#if defined(MBEDTLS_THREADING_C) + if ((ret = mbedtls_mutex_lock(&cache->mutex)) != 0) { + return ret; } -#endif /* MBEDTLS_X509_CRT_PARSE_C && MBEDTLS_SSL_KEEP_PEER_CERTIFICATE */ +#endif + ret = ssl_cache_find_entry(cache, session_id, session_id_len, &entry); + /* No valid entry found, exit with success */ + if (ret != 0) { + ret = 0; + goto exit; + } + + /* Now we remove the entry from the chain */ + if (entry == cache->chain) { + cache->chain = entry->next; + goto free; + } + for (prev = cache->chain; prev->next != NULL; prev = prev->next) { + if (prev->next == entry) { + prev->next = entry->next; + break; + } + } + +free: + ssl_cache_entry_zeroize(entry); + mbedtls_free(entry); ret = 0; exit: @@ -310,13 +397,7 @@ void mbedtls_ssl_cache_free(mbedtls_ssl_cache_context *cache) prv = cur; cur = cur->next; - mbedtls_ssl_session_free(&prv->session); - -#if defined(MBEDTLS_X509_CRT_PARSE_C) && \ - defined(MBEDTLS_SSL_KEEP_PEER_CERTIFICATE) - mbedtls_free(prv->peer_cert.p); -#endif /* MBEDTLS_X509_CRT_PARSE_C && MBEDTLS_SSL_KEEP_PEER_CERTIFICATE */ - + ssl_cache_entry_zeroize(prv); mbedtls_free(prv); } diff --git a/vendor/mbedtls/library/ssl_ciphersuites.c b/vendor/mbedtls/library/ssl_ciphersuites.c index f1e995633b..23619a26c8 100644 --- a/vendor/mbedtls/library/ssl_ciphersuites.c +++ b/vendor/mbedtls/library/ssl_ciphersuites.c @@ -4,19 +4,7 @@ * \brief SSL ciphersuites for Mbed TLS * * Copyright The Mbed TLS Contributors - * SPDX-License-Identifier: Apache-2.0 - * - * Licensed under the Apache License, Version 2.0 (the "License"); you may - * not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT - * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. + * SPDX-License-Identifier: Apache-2.0 OR GPL-2.0-or-later */ #include "common.h" @@ -27,18 +15,17 @@ #include "mbedtls/ssl_ciphersuites.h" #include "mbedtls/ssl.h" +#include "ssl_misc.h" +#if defined(MBEDTLS_USE_PSA_CRYPTO) +#include "mbedtls/psa_util.h" +#endif #include -#undef HAVE_SHA384 -#if defined(MBEDTLS_SHA512_C) && !defined(MBEDTLS_SHA512_NO_SHA384) -#define HAVE_SHA384 -#endif - /* * Ordered from most preferred to least preferred in terms of security. * - * Current rule (except RC4 and 3DES, weak and null which come last): + * Current rule (except weak and null which come last): * 1. By key exchange: * Forward-secure non-PSK > forward-secure PSK > ECJPAKE > other non-PSK > other PSK * 2. By key length and cipher: @@ -52,6 +39,15 @@ static const int ciphersuite_preference[] = #if defined(MBEDTLS_SSL_CIPHERSUITES) MBEDTLS_SSL_CIPHERSUITES, #else +#if defined(MBEDTLS_SSL_PROTO_TLS1_3) + /* TLS 1.3 ciphersuites */ + MBEDTLS_TLS1_3_CHACHA20_POLY1305_SHA256, + MBEDTLS_TLS1_3_AES_256_GCM_SHA384, + MBEDTLS_TLS1_3_AES_128_GCM_SHA256, + MBEDTLS_TLS1_3_AES_128_CCM_SHA256, + MBEDTLS_TLS1_3_AES_128_CCM_8_SHA256, +#endif /* MBEDTLS_SSL_PROTO_TLS1_3 */ + /* Chacha-Poly ephemeral suites */ MBEDTLS_TLS_ECDHE_RSA_WITH_CHACHA20_POLY1305_SHA256, MBEDTLS_TLS_ECDHE_ECDSA_WITH_CHACHA20_POLY1305_SHA256, @@ -255,34 +251,6 @@ static const int ciphersuite_preference[] = MBEDTLS_TLS_PSK_WITH_ARIA_128_GCM_SHA256, MBEDTLS_TLS_PSK_WITH_ARIA_128_CBC_SHA256, - /* 3DES suites */ - MBEDTLS_TLS_ECDHE_ECDSA_WITH_3DES_EDE_CBC_SHA, - MBEDTLS_TLS_ECDHE_RSA_WITH_3DES_EDE_CBC_SHA, - MBEDTLS_TLS_DHE_RSA_WITH_3DES_EDE_CBC_SHA, - MBEDTLS_TLS_ECDHE_PSK_WITH_3DES_EDE_CBC_SHA, - MBEDTLS_TLS_DHE_PSK_WITH_3DES_EDE_CBC_SHA, - MBEDTLS_TLS_RSA_WITH_3DES_EDE_CBC_SHA, - MBEDTLS_TLS_ECDH_RSA_WITH_3DES_EDE_CBC_SHA, - MBEDTLS_TLS_ECDH_ECDSA_WITH_3DES_EDE_CBC_SHA, - MBEDTLS_TLS_RSA_PSK_WITH_3DES_EDE_CBC_SHA, - MBEDTLS_TLS_PSK_WITH_3DES_EDE_CBC_SHA, - - /* RC4 suites */ - MBEDTLS_TLS_ECDHE_ECDSA_WITH_RC4_128_SHA, - MBEDTLS_TLS_ECDHE_RSA_WITH_RC4_128_SHA, - MBEDTLS_TLS_ECDHE_PSK_WITH_RC4_128_SHA, - MBEDTLS_TLS_DHE_PSK_WITH_RC4_128_SHA, - MBEDTLS_TLS_RSA_WITH_RC4_128_SHA, - MBEDTLS_TLS_RSA_WITH_RC4_128_MD5, - MBEDTLS_TLS_ECDH_RSA_WITH_RC4_128_SHA, - MBEDTLS_TLS_ECDH_ECDSA_WITH_RC4_128_SHA, - MBEDTLS_TLS_RSA_PSK_WITH_RC4_128_SHA, - MBEDTLS_TLS_PSK_WITH_RC4_128_SHA, - - /* Weak suites */ - MBEDTLS_TLS_DHE_RSA_WITH_DES_CBC_SHA, - MBEDTLS_TLS_RSA_WITH_DES_CBC_SHA, - /* NULL suites */ MBEDTLS_TLS_ECDHE_ECDSA_WITH_NULL_SHA, MBEDTLS_TLS_ECDHE_RSA_WITH_NULL_SHA, @@ -311,1877 +279,1517 @@ static const int ciphersuite_preference[] = static const mbedtls_ssl_ciphersuite_t ciphersuite_definitions[] = { -#if defined(MBEDTLS_CHACHAPOLY_C) && \ - defined(MBEDTLS_SHA256_C) && \ +#if defined(MBEDTLS_SSL_PROTO_TLS1_3) +#if defined(MBEDTLS_SSL_HAVE_AES) +#if defined(MBEDTLS_SSL_HAVE_GCM) +#if defined(MBEDTLS_MD_CAN_SHA384) + { MBEDTLS_TLS1_3_AES_256_GCM_SHA384, "TLS1-3-AES-256-GCM-SHA384", + MBEDTLS_CIPHER_AES_256_GCM, MBEDTLS_MD_SHA384, + MBEDTLS_KEY_EXCHANGE_NONE, /* Key exchange not part of ciphersuite in TLS 1.3 */ + 0, + MBEDTLS_SSL_VERSION_TLS1_3, MBEDTLS_SSL_VERSION_TLS1_3 }, +#endif /* MBEDTLS_MD_CAN_SHA384 */ +#if defined(MBEDTLS_MD_CAN_SHA256) + { MBEDTLS_TLS1_3_AES_128_GCM_SHA256, "TLS1-3-AES-128-GCM-SHA256", + MBEDTLS_CIPHER_AES_128_GCM, MBEDTLS_MD_SHA256, + MBEDTLS_KEY_EXCHANGE_NONE, /* Key exchange not part of ciphersuite in TLS 1.3 */ + 0, + MBEDTLS_SSL_VERSION_TLS1_3, MBEDTLS_SSL_VERSION_TLS1_3 }, +#endif /* MBEDTLS_MD_CAN_SHA256 */ +#endif /* MBEDTLS_SSL_HAVE_GCM */ +#if defined(MBEDTLS_SSL_HAVE_CCM) && defined(MBEDTLS_MD_CAN_SHA256) + { MBEDTLS_TLS1_3_AES_128_CCM_SHA256, "TLS1-3-AES-128-CCM-SHA256", + MBEDTLS_CIPHER_AES_128_CCM, MBEDTLS_MD_SHA256, + MBEDTLS_KEY_EXCHANGE_NONE, /* Key exchange not part of ciphersuite in TLS 1.3 */ + 0, + MBEDTLS_SSL_VERSION_TLS1_3, MBEDTLS_SSL_VERSION_TLS1_3 }, + { MBEDTLS_TLS1_3_AES_128_CCM_8_SHA256, "TLS1-3-AES-128-CCM-8-SHA256", + MBEDTLS_CIPHER_AES_128_CCM, MBEDTLS_MD_SHA256, + MBEDTLS_KEY_EXCHANGE_NONE, /* Key exchange not part of ciphersuite in TLS 1.3 */ + MBEDTLS_CIPHERSUITE_SHORT_TAG, + MBEDTLS_SSL_VERSION_TLS1_3, MBEDTLS_SSL_VERSION_TLS1_3 }, +#endif /* MBEDTLS_MD_CAN_SHA256 && MBEDTLS_SSL_HAVE_CCM */ +#endif /* MBEDTLS_SSL_HAVE_AES */ +#if defined(MBEDTLS_SSL_HAVE_CHACHAPOLY) && defined(MBEDTLS_MD_CAN_SHA256) + { MBEDTLS_TLS1_3_CHACHA20_POLY1305_SHA256, + "TLS1-3-CHACHA20-POLY1305-SHA256", + MBEDTLS_CIPHER_CHACHA20_POLY1305, MBEDTLS_MD_SHA256, + MBEDTLS_KEY_EXCHANGE_NONE, /* Key exchange not part of ciphersuite in TLS 1.3 */ + 0, + MBEDTLS_SSL_VERSION_TLS1_3, MBEDTLS_SSL_VERSION_TLS1_3 }, +#endif /* MBEDTLS_SSL_HAVE_CHACHAPOLY && MBEDTLS_MD_CAN_SHA256 */ +#endif /* MBEDTLS_SSL_PROTO_TLS1_3 */ + +#if defined(MBEDTLS_SSL_HAVE_CHACHAPOLY) && \ + defined(MBEDTLS_MD_CAN_SHA256) && \ defined(MBEDTLS_SSL_PROTO_TLS1_2) #if defined(MBEDTLS_KEY_EXCHANGE_ECDHE_RSA_ENABLED) { MBEDTLS_TLS_ECDHE_RSA_WITH_CHACHA20_POLY1305_SHA256, "TLS-ECDHE-RSA-WITH-CHACHA20-POLY1305-SHA256", MBEDTLS_CIPHER_CHACHA20_POLY1305, MBEDTLS_MD_SHA256, MBEDTLS_KEY_EXCHANGE_ECDHE_RSA, - MBEDTLS_SSL_MAJOR_VERSION_3, MBEDTLS_SSL_MINOR_VERSION_3, - MBEDTLS_SSL_MAJOR_VERSION_3, MBEDTLS_SSL_MINOR_VERSION_3, - 0 }, + 0, + MBEDTLS_SSL_VERSION_TLS1_2, MBEDTLS_SSL_VERSION_TLS1_2 }, #endif #if defined(MBEDTLS_KEY_EXCHANGE_ECDHE_ECDSA_ENABLED) { MBEDTLS_TLS_ECDHE_ECDSA_WITH_CHACHA20_POLY1305_SHA256, "TLS-ECDHE-ECDSA-WITH-CHACHA20-POLY1305-SHA256", MBEDTLS_CIPHER_CHACHA20_POLY1305, MBEDTLS_MD_SHA256, MBEDTLS_KEY_EXCHANGE_ECDHE_ECDSA, - MBEDTLS_SSL_MAJOR_VERSION_3, MBEDTLS_SSL_MINOR_VERSION_3, - MBEDTLS_SSL_MAJOR_VERSION_3, MBEDTLS_SSL_MINOR_VERSION_3, - 0 }, + 0, + MBEDTLS_SSL_VERSION_TLS1_2, MBEDTLS_SSL_VERSION_TLS1_2 }, #endif #if defined(MBEDTLS_KEY_EXCHANGE_DHE_RSA_ENABLED) { MBEDTLS_TLS_DHE_RSA_WITH_CHACHA20_POLY1305_SHA256, "TLS-DHE-RSA-WITH-CHACHA20-POLY1305-SHA256", MBEDTLS_CIPHER_CHACHA20_POLY1305, MBEDTLS_MD_SHA256, MBEDTLS_KEY_EXCHANGE_DHE_RSA, - MBEDTLS_SSL_MAJOR_VERSION_3, MBEDTLS_SSL_MINOR_VERSION_3, - MBEDTLS_SSL_MAJOR_VERSION_3, MBEDTLS_SSL_MINOR_VERSION_3, - 0 }, + 0, + MBEDTLS_SSL_VERSION_TLS1_2, MBEDTLS_SSL_VERSION_TLS1_2 }, #endif #if defined(MBEDTLS_KEY_EXCHANGE_PSK_ENABLED) { MBEDTLS_TLS_PSK_WITH_CHACHA20_POLY1305_SHA256, "TLS-PSK-WITH-CHACHA20-POLY1305-SHA256", MBEDTLS_CIPHER_CHACHA20_POLY1305, MBEDTLS_MD_SHA256, MBEDTLS_KEY_EXCHANGE_PSK, - MBEDTLS_SSL_MAJOR_VERSION_3, MBEDTLS_SSL_MINOR_VERSION_3, - MBEDTLS_SSL_MAJOR_VERSION_3, MBEDTLS_SSL_MINOR_VERSION_3, - 0 }, + 0, + MBEDTLS_SSL_VERSION_TLS1_2, MBEDTLS_SSL_VERSION_TLS1_2 }, #endif #if defined(MBEDTLS_KEY_EXCHANGE_ECDHE_PSK_ENABLED) { MBEDTLS_TLS_ECDHE_PSK_WITH_CHACHA20_POLY1305_SHA256, "TLS-ECDHE-PSK-WITH-CHACHA20-POLY1305-SHA256", MBEDTLS_CIPHER_CHACHA20_POLY1305, MBEDTLS_MD_SHA256, MBEDTLS_KEY_EXCHANGE_ECDHE_PSK, - MBEDTLS_SSL_MAJOR_VERSION_3, MBEDTLS_SSL_MINOR_VERSION_3, - MBEDTLS_SSL_MAJOR_VERSION_3, MBEDTLS_SSL_MINOR_VERSION_3, - 0 }, + 0, + MBEDTLS_SSL_VERSION_TLS1_2, MBEDTLS_SSL_VERSION_TLS1_2 }, #endif #if defined(MBEDTLS_KEY_EXCHANGE_DHE_PSK_ENABLED) { MBEDTLS_TLS_DHE_PSK_WITH_CHACHA20_POLY1305_SHA256, "TLS-DHE-PSK-WITH-CHACHA20-POLY1305-SHA256", MBEDTLS_CIPHER_CHACHA20_POLY1305, MBEDTLS_MD_SHA256, MBEDTLS_KEY_EXCHANGE_DHE_PSK, - MBEDTLS_SSL_MAJOR_VERSION_3, MBEDTLS_SSL_MINOR_VERSION_3, - MBEDTLS_SSL_MAJOR_VERSION_3, MBEDTLS_SSL_MINOR_VERSION_3, - 0 }, + 0, + MBEDTLS_SSL_VERSION_TLS1_2, MBEDTLS_SSL_VERSION_TLS1_2 }, #endif #if defined(MBEDTLS_KEY_EXCHANGE_RSA_PSK_ENABLED) { MBEDTLS_TLS_RSA_PSK_WITH_CHACHA20_POLY1305_SHA256, "TLS-RSA-PSK-WITH-CHACHA20-POLY1305-SHA256", MBEDTLS_CIPHER_CHACHA20_POLY1305, MBEDTLS_MD_SHA256, MBEDTLS_KEY_EXCHANGE_RSA_PSK, - MBEDTLS_SSL_MAJOR_VERSION_3, MBEDTLS_SSL_MINOR_VERSION_3, - MBEDTLS_SSL_MAJOR_VERSION_3, MBEDTLS_SSL_MINOR_VERSION_3, - 0 }, + 0, + MBEDTLS_SSL_VERSION_TLS1_2, MBEDTLS_SSL_VERSION_TLS1_2 }, #endif -#endif /* MBEDTLS_CHACHAPOLY_C && - MBEDTLS_SHA256_C && +#endif /* MBEDTLS_SSL_HAVE_CHACHAPOLY && + MBEDTLS_MD_CAN_SHA256 && MBEDTLS_SSL_PROTO_TLS1_2 */ #if defined(MBEDTLS_KEY_EXCHANGE_ECDHE_ECDSA_ENABLED) -#if defined(MBEDTLS_AES_C) -#if defined(MBEDTLS_SHA1_C) -#if defined(MBEDTLS_CIPHER_MODE_CBC) +#if defined(MBEDTLS_SSL_HAVE_AES) +#if defined(MBEDTLS_MD_CAN_SHA1) +#if defined(MBEDTLS_SSL_HAVE_CBC) { MBEDTLS_TLS_ECDHE_ECDSA_WITH_AES_128_CBC_SHA, "TLS-ECDHE-ECDSA-WITH-AES-128-CBC-SHA", MBEDTLS_CIPHER_AES_128_CBC, MBEDTLS_MD_SHA1, MBEDTLS_KEY_EXCHANGE_ECDHE_ECDSA, - MBEDTLS_SSL_MAJOR_VERSION_3, MBEDTLS_SSL_MINOR_VERSION_1, - MBEDTLS_SSL_MAJOR_VERSION_3, MBEDTLS_SSL_MINOR_VERSION_3, - 0 }, + 0, + MBEDTLS_SSL_VERSION_TLS1_2, MBEDTLS_SSL_VERSION_TLS1_2 }, { MBEDTLS_TLS_ECDHE_ECDSA_WITH_AES_256_CBC_SHA, "TLS-ECDHE-ECDSA-WITH-AES-256-CBC-SHA", MBEDTLS_CIPHER_AES_256_CBC, MBEDTLS_MD_SHA1, MBEDTLS_KEY_EXCHANGE_ECDHE_ECDSA, - MBEDTLS_SSL_MAJOR_VERSION_3, MBEDTLS_SSL_MINOR_VERSION_1, - MBEDTLS_SSL_MAJOR_VERSION_3, MBEDTLS_SSL_MINOR_VERSION_3, - 0 }, -#endif /* MBEDTLS_CIPHER_MODE_CBC */ -#endif /* MBEDTLS_SHA1_C */ -#if defined(MBEDTLS_SHA256_C) -#if defined(MBEDTLS_CIPHER_MODE_CBC) + 0, + MBEDTLS_SSL_VERSION_TLS1_2, MBEDTLS_SSL_VERSION_TLS1_2 }, +#endif /* MBEDTLS_SSL_HAVE_CBC */ +#endif /* MBEDTLS_MD_CAN_SHA1 */ +#if defined(MBEDTLS_MD_CAN_SHA256) +#if defined(MBEDTLS_SSL_HAVE_CBC) { MBEDTLS_TLS_ECDHE_ECDSA_WITH_AES_128_CBC_SHA256, "TLS-ECDHE-ECDSA-WITH-AES-128-CBC-SHA256", MBEDTLS_CIPHER_AES_128_CBC, MBEDTLS_MD_SHA256, MBEDTLS_KEY_EXCHANGE_ECDHE_ECDSA, - MBEDTLS_SSL_MAJOR_VERSION_3, MBEDTLS_SSL_MINOR_VERSION_3, - MBEDTLS_SSL_MAJOR_VERSION_3, MBEDTLS_SSL_MINOR_VERSION_3, - 0 }, -#endif /* MBEDTLS_CIPHER_MODE_CBC */ -#if defined(MBEDTLS_GCM_C) + 0, + MBEDTLS_SSL_VERSION_TLS1_2, MBEDTLS_SSL_VERSION_TLS1_2 }, +#endif /* MBEDTLS_SSL_HAVE_CBC */ +#if defined(MBEDTLS_SSL_HAVE_GCM) { MBEDTLS_TLS_ECDHE_ECDSA_WITH_AES_128_GCM_SHA256, "TLS-ECDHE-ECDSA-WITH-AES-128-GCM-SHA256", MBEDTLS_CIPHER_AES_128_GCM, MBEDTLS_MD_SHA256, MBEDTLS_KEY_EXCHANGE_ECDHE_ECDSA, - MBEDTLS_SSL_MAJOR_VERSION_3, MBEDTLS_SSL_MINOR_VERSION_3, - MBEDTLS_SSL_MAJOR_VERSION_3, MBEDTLS_SSL_MINOR_VERSION_3, - 0 }, -#endif /* MBEDTLS_GCM_C */ -#endif /* MBEDTLS_SHA256_C */ -#if defined(HAVE_SHA384) -#if defined(MBEDTLS_CIPHER_MODE_CBC) + 0, + MBEDTLS_SSL_VERSION_TLS1_2, MBEDTLS_SSL_VERSION_TLS1_2 }, +#endif /* MBEDTLS_SSL_HAVE_GCM */ +#endif /* MBEDTLS_MD_CAN_SHA256 */ +#if defined(MBEDTLS_MD_CAN_SHA384) +#if defined(MBEDTLS_SSL_HAVE_CBC) { MBEDTLS_TLS_ECDHE_ECDSA_WITH_AES_256_CBC_SHA384, "TLS-ECDHE-ECDSA-WITH-AES-256-CBC-SHA384", MBEDTLS_CIPHER_AES_256_CBC, MBEDTLS_MD_SHA384, MBEDTLS_KEY_EXCHANGE_ECDHE_ECDSA, - MBEDTLS_SSL_MAJOR_VERSION_3, MBEDTLS_SSL_MINOR_VERSION_3, - MBEDTLS_SSL_MAJOR_VERSION_3, MBEDTLS_SSL_MINOR_VERSION_3, - 0 }, -#endif /* MBEDTLS_CIPHER_MODE_CBC */ -#if defined(MBEDTLS_GCM_C) + 0, + MBEDTLS_SSL_VERSION_TLS1_2, MBEDTLS_SSL_VERSION_TLS1_2 }, +#endif /* MBEDTLS_SSL_HAVE_CBC */ +#if defined(MBEDTLS_SSL_HAVE_GCM) { MBEDTLS_TLS_ECDHE_ECDSA_WITH_AES_256_GCM_SHA384, "TLS-ECDHE-ECDSA-WITH-AES-256-GCM-SHA384", MBEDTLS_CIPHER_AES_256_GCM, MBEDTLS_MD_SHA384, MBEDTLS_KEY_EXCHANGE_ECDHE_ECDSA, - MBEDTLS_SSL_MAJOR_VERSION_3, MBEDTLS_SSL_MINOR_VERSION_3, - MBEDTLS_SSL_MAJOR_VERSION_3, MBEDTLS_SSL_MINOR_VERSION_3, - 0 }, -#endif /* MBEDTLS_GCM_C */ -#endif /* HAVE_SHA384 */ -#if defined(MBEDTLS_CCM_C) + 0, + MBEDTLS_SSL_VERSION_TLS1_2, MBEDTLS_SSL_VERSION_TLS1_2 }, +#endif /* MBEDTLS_SSL_HAVE_GCM */ +#endif /* MBEDTLS_MD_CAN_SHA384 */ +#if defined(MBEDTLS_SSL_HAVE_CCM) { MBEDTLS_TLS_ECDHE_ECDSA_WITH_AES_256_CCM, "TLS-ECDHE-ECDSA-WITH-AES-256-CCM", MBEDTLS_CIPHER_AES_256_CCM, MBEDTLS_MD_SHA256, MBEDTLS_KEY_EXCHANGE_ECDHE_ECDSA, - MBEDTLS_SSL_MAJOR_VERSION_3, MBEDTLS_SSL_MINOR_VERSION_3, - MBEDTLS_SSL_MAJOR_VERSION_3, MBEDTLS_SSL_MINOR_VERSION_3, - 0 }, + 0, + MBEDTLS_SSL_VERSION_TLS1_2, MBEDTLS_SSL_VERSION_TLS1_2 }, { MBEDTLS_TLS_ECDHE_ECDSA_WITH_AES_256_CCM_8, "TLS-ECDHE-ECDSA-WITH-AES-256-CCM-8", MBEDTLS_CIPHER_AES_256_CCM, MBEDTLS_MD_SHA256, MBEDTLS_KEY_EXCHANGE_ECDHE_ECDSA, - MBEDTLS_SSL_MAJOR_VERSION_3, MBEDTLS_SSL_MINOR_VERSION_3, - MBEDTLS_SSL_MAJOR_VERSION_3, MBEDTLS_SSL_MINOR_VERSION_3, - MBEDTLS_CIPHERSUITE_SHORT_TAG }, + MBEDTLS_CIPHERSUITE_SHORT_TAG, + MBEDTLS_SSL_VERSION_TLS1_2, MBEDTLS_SSL_VERSION_TLS1_2 }, { MBEDTLS_TLS_ECDHE_ECDSA_WITH_AES_128_CCM, "TLS-ECDHE-ECDSA-WITH-AES-128-CCM", MBEDTLS_CIPHER_AES_128_CCM, MBEDTLS_MD_SHA256, MBEDTLS_KEY_EXCHANGE_ECDHE_ECDSA, - MBEDTLS_SSL_MAJOR_VERSION_3, MBEDTLS_SSL_MINOR_VERSION_3, - MBEDTLS_SSL_MAJOR_VERSION_3, MBEDTLS_SSL_MINOR_VERSION_3, - 0 }, + 0, + MBEDTLS_SSL_VERSION_TLS1_2, MBEDTLS_SSL_VERSION_TLS1_2 }, { MBEDTLS_TLS_ECDHE_ECDSA_WITH_AES_128_CCM_8, "TLS-ECDHE-ECDSA-WITH-AES-128-CCM-8", MBEDTLS_CIPHER_AES_128_CCM, MBEDTLS_MD_SHA256, MBEDTLS_KEY_EXCHANGE_ECDHE_ECDSA, - MBEDTLS_SSL_MAJOR_VERSION_3, MBEDTLS_SSL_MINOR_VERSION_3, - MBEDTLS_SSL_MAJOR_VERSION_3, MBEDTLS_SSL_MINOR_VERSION_3, - MBEDTLS_CIPHERSUITE_SHORT_TAG }, -#endif /* MBEDTLS_CCM_C */ -#endif /* MBEDTLS_AES_C */ - -#if defined(MBEDTLS_CAMELLIA_C) -#if defined(MBEDTLS_CIPHER_MODE_CBC) -#if defined(MBEDTLS_SHA256_C) + MBEDTLS_CIPHERSUITE_SHORT_TAG, + MBEDTLS_SSL_VERSION_TLS1_2, MBEDTLS_SSL_VERSION_TLS1_2 }, +#endif /* MBEDTLS_SSL_HAVE_CCM */ +#endif /* MBEDTLS_SSL_HAVE_AES */ + +#if defined(MBEDTLS_SSL_HAVE_CAMELLIA) +#if defined(MBEDTLS_SSL_HAVE_CBC) +#if defined(MBEDTLS_MD_CAN_SHA256) { MBEDTLS_TLS_ECDHE_ECDSA_WITH_CAMELLIA_128_CBC_SHA256, "TLS-ECDHE-ECDSA-WITH-CAMELLIA-128-CBC-SHA256", MBEDTLS_CIPHER_CAMELLIA_128_CBC, MBEDTLS_MD_SHA256, MBEDTLS_KEY_EXCHANGE_ECDHE_ECDSA, - MBEDTLS_SSL_MAJOR_VERSION_3, MBEDTLS_SSL_MINOR_VERSION_1, - MBEDTLS_SSL_MAJOR_VERSION_3, MBEDTLS_SSL_MINOR_VERSION_3, - 0 }, -#endif /* MBEDTLS_SHA256_C */ -#if defined(HAVE_SHA384) + 0, + MBEDTLS_SSL_VERSION_TLS1_2, MBEDTLS_SSL_VERSION_TLS1_2 }, +#endif /* MBEDTLS_MD_CAN_SHA256 */ +#if defined(MBEDTLS_MD_CAN_SHA384) { MBEDTLS_TLS_ECDHE_ECDSA_WITH_CAMELLIA_256_CBC_SHA384, "TLS-ECDHE-ECDSA-WITH-CAMELLIA-256-CBC-SHA384", MBEDTLS_CIPHER_CAMELLIA_256_CBC, MBEDTLS_MD_SHA384, MBEDTLS_KEY_EXCHANGE_ECDHE_ECDSA, - MBEDTLS_SSL_MAJOR_VERSION_3, MBEDTLS_SSL_MINOR_VERSION_1, - MBEDTLS_SSL_MAJOR_VERSION_3, MBEDTLS_SSL_MINOR_VERSION_3, - 0 }, -#endif /* HAVE_SHA384 */ -#endif /* MBEDTLS_CIPHER_MODE_CBC */ - -#if defined(MBEDTLS_GCM_C) -#if defined(MBEDTLS_SHA256_C) + 0, + MBEDTLS_SSL_VERSION_TLS1_2, MBEDTLS_SSL_VERSION_TLS1_2 }, +#endif /* MBEDTLS_MD_CAN_SHA384 */ +#endif /* MBEDTLS_SSL_HAVE_CBC */ + +#if defined(MBEDTLS_SSL_HAVE_GCM) +#if defined(MBEDTLS_MD_CAN_SHA256) { MBEDTLS_TLS_ECDHE_ECDSA_WITH_CAMELLIA_128_GCM_SHA256, "TLS-ECDHE-ECDSA-WITH-CAMELLIA-128-GCM-SHA256", MBEDTLS_CIPHER_CAMELLIA_128_GCM, MBEDTLS_MD_SHA256, MBEDTLS_KEY_EXCHANGE_ECDHE_ECDSA, - MBEDTLS_SSL_MAJOR_VERSION_3, MBEDTLS_SSL_MINOR_VERSION_3, - MBEDTLS_SSL_MAJOR_VERSION_3, MBEDTLS_SSL_MINOR_VERSION_3, - 0 }, -#endif /* MBEDTLS_SHA256_C */ -#if defined(HAVE_SHA384) + 0, + MBEDTLS_SSL_VERSION_TLS1_2, MBEDTLS_SSL_VERSION_TLS1_2 }, +#endif /* MBEDTLS_MD_CAN_SHA256 */ +#if defined(MBEDTLS_MD_CAN_SHA384) { MBEDTLS_TLS_ECDHE_ECDSA_WITH_CAMELLIA_256_GCM_SHA384, "TLS-ECDHE-ECDSA-WITH-CAMELLIA-256-GCM-SHA384", MBEDTLS_CIPHER_CAMELLIA_256_GCM, MBEDTLS_MD_SHA384, MBEDTLS_KEY_EXCHANGE_ECDHE_ECDSA, - MBEDTLS_SSL_MAJOR_VERSION_3, MBEDTLS_SSL_MINOR_VERSION_3, - MBEDTLS_SSL_MAJOR_VERSION_3, MBEDTLS_SSL_MINOR_VERSION_3, - 0 }, -#endif /* HAVE_SHA384 */ -#endif /* MBEDTLS_GCM_C */ -#endif /* MBEDTLS_CAMELLIA_C */ - -#if defined(MBEDTLS_DES_C) -#if defined(MBEDTLS_CIPHER_MODE_CBC) -#if defined(MBEDTLS_SHA1_C) - { MBEDTLS_TLS_ECDHE_ECDSA_WITH_3DES_EDE_CBC_SHA, "TLS-ECDHE-ECDSA-WITH-3DES-EDE-CBC-SHA", - MBEDTLS_CIPHER_DES_EDE3_CBC, MBEDTLS_MD_SHA1, MBEDTLS_KEY_EXCHANGE_ECDHE_ECDSA, - MBEDTLS_SSL_MAJOR_VERSION_3, MBEDTLS_SSL_MINOR_VERSION_1, - MBEDTLS_SSL_MAJOR_VERSION_3, MBEDTLS_SSL_MINOR_VERSION_3, - 0 }, -#endif /* MBEDTLS_SHA1_C */ -#endif /* MBEDTLS_CIPHER_MODE_CBC */ -#endif /* MBEDTLS_DES_C */ - -#if defined(MBEDTLS_ARC4_C) -#if defined(MBEDTLS_SHA1_C) - { MBEDTLS_TLS_ECDHE_ECDSA_WITH_RC4_128_SHA, "TLS-ECDHE-ECDSA-WITH-RC4-128-SHA", - MBEDTLS_CIPHER_ARC4_128, MBEDTLS_MD_SHA1, MBEDTLS_KEY_EXCHANGE_ECDHE_ECDSA, - MBEDTLS_SSL_MAJOR_VERSION_3, MBEDTLS_SSL_MINOR_VERSION_1, - MBEDTLS_SSL_MAJOR_VERSION_3, MBEDTLS_SSL_MINOR_VERSION_3, - MBEDTLS_CIPHERSUITE_NODTLS }, -#endif /* MBEDTLS_SHA1_C */ -#endif /* MBEDTLS_ARC4_C */ + 0, + MBEDTLS_SSL_VERSION_TLS1_2, MBEDTLS_SSL_VERSION_TLS1_2 }, +#endif /* MBEDTLS_MD_CAN_SHA384 */ +#endif /* MBEDTLS_SSL_HAVE_GCM */ +#endif /* MBEDTLS_SSL_HAVE_CAMELLIA */ #if defined(MBEDTLS_CIPHER_NULL_CIPHER) -#if defined(MBEDTLS_SHA1_C) +#if defined(MBEDTLS_MD_CAN_SHA1) { MBEDTLS_TLS_ECDHE_ECDSA_WITH_NULL_SHA, "TLS-ECDHE-ECDSA-WITH-NULL-SHA", MBEDTLS_CIPHER_NULL, MBEDTLS_MD_SHA1, MBEDTLS_KEY_EXCHANGE_ECDHE_ECDSA, - MBEDTLS_SSL_MAJOR_VERSION_3, MBEDTLS_SSL_MINOR_VERSION_1, - MBEDTLS_SSL_MAJOR_VERSION_3, MBEDTLS_SSL_MINOR_VERSION_3, - MBEDTLS_CIPHERSUITE_WEAK }, -#endif /* MBEDTLS_SHA1_C */ + MBEDTLS_CIPHERSUITE_WEAK, + MBEDTLS_SSL_VERSION_TLS1_2, MBEDTLS_SSL_VERSION_TLS1_2 }, +#endif /* MBEDTLS_MD_CAN_SHA1 */ #endif /* MBEDTLS_CIPHER_NULL_CIPHER */ #endif /* MBEDTLS_KEY_EXCHANGE_ECDHE_ECDSA_ENABLED */ #if defined(MBEDTLS_KEY_EXCHANGE_ECDHE_RSA_ENABLED) -#if defined(MBEDTLS_AES_C) -#if defined(MBEDTLS_SHA1_C) -#if defined(MBEDTLS_CIPHER_MODE_CBC) +#if defined(MBEDTLS_SSL_HAVE_AES) +#if defined(MBEDTLS_MD_CAN_SHA1) +#if defined(MBEDTLS_SSL_HAVE_CBC) { MBEDTLS_TLS_ECDHE_RSA_WITH_AES_128_CBC_SHA, "TLS-ECDHE-RSA-WITH-AES-128-CBC-SHA", MBEDTLS_CIPHER_AES_128_CBC, MBEDTLS_MD_SHA1, MBEDTLS_KEY_EXCHANGE_ECDHE_RSA, - MBEDTLS_SSL_MAJOR_VERSION_3, MBEDTLS_SSL_MINOR_VERSION_1, - MBEDTLS_SSL_MAJOR_VERSION_3, MBEDTLS_SSL_MINOR_VERSION_3, - 0 }, + 0, + MBEDTLS_SSL_VERSION_TLS1_2, MBEDTLS_SSL_VERSION_TLS1_2 }, { MBEDTLS_TLS_ECDHE_RSA_WITH_AES_256_CBC_SHA, "TLS-ECDHE-RSA-WITH-AES-256-CBC-SHA", MBEDTLS_CIPHER_AES_256_CBC, MBEDTLS_MD_SHA1, MBEDTLS_KEY_EXCHANGE_ECDHE_RSA, - MBEDTLS_SSL_MAJOR_VERSION_3, MBEDTLS_SSL_MINOR_VERSION_1, - MBEDTLS_SSL_MAJOR_VERSION_3, MBEDTLS_SSL_MINOR_VERSION_3, - 0 }, -#endif /* MBEDTLS_CIPHER_MODE_CBC */ -#endif /* MBEDTLS_SHA1_C */ -#if defined(MBEDTLS_SHA256_C) -#if defined(MBEDTLS_CIPHER_MODE_CBC) + 0, + MBEDTLS_SSL_VERSION_TLS1_2, MBEDTLS_SSL_VERSION_TLS1_2 }, +#endif /* MBEDTLS_SSL_HAVE_CBC */ +#endif /* MBEDTLS_MD_CAN_SHA1 */ +#if defined(MBEDTLS_MD_CAN_SHA256) +#if defined(MBEDTLS_SSL_HAVE_CBC) { MBEDTLS_TLS_ECDHE_RSA_WITH_AES_128_CBC_SHA256, "TLS-ECDHE-RSA-WITH-AES-128-CBC-SHA256", MBEDTLS_CIPHER_AES_128_CBC, MBEDTLS_MD_SHA256, MBEDTLS_KEY_EXCHANGE_ECDHE_RSA, - MBEDTLS_SSL_MAJOR_VERSION_3, MBEDTLS_SSL_MINOR_VERSION_3, - MBEDTLS_SSL_MAJOR_VERSION_3, MBEDTLS_SSL_MINOR_VERSION_3, - 0 }, -#endif /* MBEDTLS_CIPHER_MODE_CBC */ -#if defined(MBEDTLS_GCM_C) + 0, + MBEDTLS_SSL_VERSION_TLS1_2, MBEDTLS_SSL_VERSION_TLS1_2 }, +#endif /* MBEDTLS_SSL_HAVE_CBC */ +#if defined(MBEDTLS_SSL_HAVE_GCM) { MBEDTLS_TLS_ECDHE_RSA_WITH_AES_128_GCM_SHA256, "TLS-ECDHE-RSA-WITH-AES-128-GCM-SHA256", MBEDTLS_CIPHER_AES_128_GCM, MBEDTLS_MD_SHA256, MBEDTLS_KEY_EXCHANGE_ECDHE_RSA, - MBEDTLS_SSL_MAJOR_VERSION_3, MBEDTLS_SSL_MINOR_VERSION_3, - MBEDTLS_SSL_MAJOR_VERSION_3, MBEDTLS_SSL_MINOR_VERSION_3, - 0 }, -#endif /* MBEDTLS_GCM_C */ -#endif /* MBEDTLS_SHA256_C */ -#if defined(HAVE_SHA384) -#if defined(MBEDTLS_CIPHER_MODE_CBC) + 0, + MBEDTLS_SSL_VERSION_TLS1_2, MBEDTLS_SSL_VERSION_TLS1_2 }, +#endif /* MBEDTLS_SSL_HAVE_GCM */ +#endif /* MBEDTLS_MD_CAN_SHA256 */ +#if defined(MBEDTLS_MD_CAN_SHA384) +#if defined(MBEDTLS_SSL_HAVE_CBC) { MBEDTLS_TLS_ECDHE_RSA_WITH_AES_256_CBC_SHA384, "TLS-ECDHE-RSA-WITH-AES-256-CBC-SHA384", MBEDTLS_CIPHER_AES_256_CBC, MBEDTLS_MD_SHA384, MBEDTLS_KEY_EXCHANGE_ECDHE_RSA, - MBEDTLS_SSL_MAJOR_VERSION_3, MBEDTLS_SSL_MINOR_VERSION_3, - MBEDTLS_SSL_MAJOR_VERSION_3, MBEDTLS_SSL_MINOR_VERSION_3, - 0 }, -#endif /* MBEDTLS_CIPHER_MODE_CBC */ -#if defined(MBEDTLS_GCM_C) + 0, + MBEDTLS_SSL_VERSION_TLS1_2, MBEDTLS_SSL_VERSION_TLS1_2 }, +#endif /* MBEDTLS_SSL_HAVE_CBC */ +#if defined(MBEDTLS_SSL_HAVE_GCM) { MBEDTLS_TLS_ECDHE_RSA_WITH_AES_256_GCM_SHA384, "TLS-ECDHE-RSA-WITH-AES-256-GCM-SHA384", MBEDTLS_CIPHER_AES_256_GCM, MBEDTLS_MD_SHA384, MBEDTLS_KEY_EXCHANGE_ECDHE_RSA, - MBEDTLS_SSL_MAJOR_VERSION_3, MBEDTLS_SSL_MINOR_VERSION_3, - MBEDTLS_SSL_MAJOR_VERSION_3, MBEDTLS_SSL_MINOR_VERSION_3, - 0 }, -#endif /* MBEDTLS_GCM_C */ -#endif /* HAVE_SHA384 */ -#endif /* MBEDTLS_AES_C */ - -#if defined(MBEDTLS_CAMELLIA_C) -#if defined(MBEDTLS_CIPHER_MODE_CBC) -#if defined(MBEDTLS_SHA256_C) + 0, + MBEDTLS_SSL_VERSION_TLS1_2, MBEDTLS_SSL_VERSION_TLS1_2 }, +#endif /* MBEDTLS_SSL_HAVE_GCM */ +#endif /* MBEDTLS_MD_CAN_SHA384 */ +#endif /* MBEDTLS_SSL_HAVE_AES */ + +#if defined(MBEDTLS_SSL_HAVE_CAMELLIA) +#if defined(MBEDTLS_SSL_HAVE_CBC) +#if defined(MBEDTLS_MD_CAN_SHA256) { MBEDTLS_TLS_ECDHE_RSA_WITH_CAMELLIA_128_CBC_SHA256, "TLS-ECDHE-RSA-WITH-CAMELLIA-128-CBC-SHA256", MBEDTLS_CIPHER_CAMELLIA_128_CBC, MBEDTLS_MD_SHA256, MBEDTLS_KEY_EXCHANGE_ECDHE_RSA, - MBEDTLS_SSL_MAJOR_VERSION_3, MBEDTLS_SSL_MINOR_VERSION_1, - MBEDTLS_SSL_MAJOR_VERSION_3, MBEDTLS_SSL_MINOR_VERSION_3, - 0 }, -#endif /* MBEDTLS_SHA256_C */ -#if defined(HAVE_SHA384) + 0, + MBEDTLS_SSL_VERSION_TLS1_2, MBEDTLS_SSL_VERSION_TLS1_2 }, +#endif /* MBEDTLS_MD_CAN_SHA256 */ +#if defined(MBEDTLS_MD_CAN_SHA384) { MBEDTLS_TLS_ECDHE_RSA_WITH_CAMELLIA_256_CBC_SHA384, "TLS-ECDHE-RSA-WITH-CAMELLIA-256-CBC-SHA384", MBEDTLS_CIPHER_CAMELLIA_256_CBC, MBEDTLS_MD_SHA384, MBEDTLS_KEY_EXCHANGE_ECDHE_RSA, - MBEDTLS_SSL_MAJOR_VERSION_3, MBEDTLS_SSL_MINOR_VERSION_1, - MBEDTLS_SSL_MAJOR_VERSION_3, MBEDTLS_SSL_MINOR_VERSION_3, - 0 }, -#endif /* HAVE_SHA384 */ -#endif /* MBEDTLS_CIPHER_MODE_CBC */ - -#if defined(MBEDTLS_GCM_C) -#if defined(MBEDTLS_SHA256_C) + 0, + MBEDTLS_SSL_VERSION_TLS1_2, MBEDTLS_SSL_VERSION_TLS1_2 }, +#endif /* MBEDTLS_MD_CAN_SHA384 */ +#endif /* MBEDTLS_SSL_HAVE_CBC */ + +#if defined(MBEDTLS_SSL_HAVE_GCM) +#if defined(MBEDTLS_MD_CAN_SHA256) { MBEDTLS_TLS_ECDHE_RSA_WITH_CAMELLIA_128_GCM_SHA256, "TLS-ECDHE-RSA-WITH-CAMELLIA-128-GCM-SHA256", MBEDTLS_CIPHER_CAMELLIA_128_GCM, MBEDTLS_MD_SHA256, MBEDTLS_KEY_EXCHANGE_ECDHE_RSA, - MBEDTLS_SSL_MAJOR_VERSION_3, MBEDTLS_SSL_MINOR_VERSION_3, - MBEDTLS_SSL_MAJOR_VERSION_3, MBEDTLS_SSL_MINOR_VERSION_3, - 0 }, -#endif /* MBEDTLS_SHA256_C */ -#if defined(HAVE_SHA384) + 0, + MBEDTLS_SSL_VERSION_TLS1_2, MBEDTLS_SSL_VERSION_TLS1_2 }, +#endif /* MBEDTLS_MD_CAN_SHA256 */ +#if defined(MBEDTLS_MD_CAN_SHA384) { MBEDTLS_TLS_ECDHE_RSA_WITH_CAMELLIA_256_GCM_SHA384, "TLS-ECDHE-RSA-WITH-CAMELLIA-256-GCM-SHA384", MBEDTLS_CIPHER_CAMELLIA_256_GCM, MBEDTLS_MD_SHA384, MBEDTLS_KEY_EXCHANGE_ECDHE_RSA, - MBEDTLS_SSL_MAJOR_VERSION_3, MBEDTLS_SSL_MINOR_VERSION_3, - MBEDTLS_SSL_MAJOR_VERSION_3, MBEDTLS_SSL_MINOR_VERSION_3, - 0 }, -#endif /* HAVE_SHA384 */ -#endif /* MBEDTLS_GCM_C */ -#endif /* MBEDTLS_CAMELLIA_C */ - -#if defined(MBEDTLS_DES_C) -#if defined(MBEDTLS_CIPHER_MODE_CBC) -#if defined(MBEDTLS_SHA1_C) - { MBEDTLS_TLS_ECDHE_RSA_WITH_3DES_EDE_CBC_SHA, "TLS-ECDHE-RSA-WITH-3DES-EDE-CBC-SHA", - MBEDTLS_CIPHER_DES_EDE3_CBC, MBEDTLS_MD_SHA1, MBEDTLS_KEY_EXCHANGE_ECDHE_RSA, - MBEDTLS_SSL_MAJOR_VERSION_3, MBEDTLS_SSL_MINOR_VERSION_1, - MBEDTLS_SSL_MAJOR_VERSION_3, MBEDTLS_SSL_MINOR_VERSION_3, - 0 }, -#endif /* MBEDTLS_SHA1_C */ -#endif /* MBEDTLS_CIPHER_MODE_CBC */ -#endif /* MBEDTLS_DES_C */ - -#if defined(MBEDTLS_ARC4_C) -#if defined(MBEDTLS_SHA1_C) - { MBEDTLS_TLS_ECDHE_RSA_WITH_RC4_128_SHA, "TLS-ECDHE-RSA-WITH-RC4-128-SHA", - MBEDTLS_CIPHER_ARC4_128, MBEDTLS_MD_SHA1, MBEDTLS_KEY_EXCHANGE_ECDHE_RSA, - MBEDTLS_SSL_MAJOR_VERSION_3, MBEDTLS_SSL_MINOR_VERSION_1, - MBEDTLS_SSL_MAJOR_VERSION_3, MBEDTLS_SSL_MINOR_VERSION_3, - MBEDTLS_CIPHERSUITE_NODTLS }, -#endif /* MBEDTLS_SHA1_C */ -#endif /* MBEDTLS_ARC4_C */ + 0, + MBEDTLS_SSL_VERSION_TLS1_2, MBEDTLS_SSL_VERSION_TLS1_2 }, +#endif /* MBEDTLS_MD_CAN_SHA384 */ +#endif /* MBEDTLS_SSL_HAVE_GCM */ +#endif /* MBEDTLS_SSL_HAVE_CAMELLIA */ #if defined(MBEDTLS_CIPHER_NULL_CIPHER) -#if defined(MBEDTLS_SHA1_C) +#if defined(MBEDTLS_MD_CAN_SHA1) { MBEDTLS_TLS_ECDHE_RSA_WITH_NULL_SHA, "TLS-ECDHE-RSA-WITH-NULL-SHA", MBEDTLS_CIPHER_NULL, MBEDTLS_MD_SHA1, MBEDTLS_KEY_EXCHANGE_ECDHE_RSA, - MBEDTLS_SSL_MAJOR_VERSION_3, MBEDTLS_SSL_MINOR_VERSION_1, - MBEDTLS_SSL_MAJOR_VERSION_3, MBEDTLS_SSL_MINOR_VERSION_3, - MBEDTLS_CIPHERSUITE_WEAK }, -#endif /* MBEDTLS_SHA1_C */ + MBEDTLS_CIPHERSUITE_WEAK, + MBEDTLS_SSL_VERSION_TLS1_2, MBEDTLS_SSL_VERSION_TLS1_2 }, +#endif /* MBEDTLS_MD_CAN_SHA1 */ #endif /* MBEDTLS_CIPHER_NULL_CIPHER */ #endif /* MBEDTLS_KEY_EXCHANGE_ECDHE_RSA_ENABLED */ #if defined(MBEDTLS_KEY_EXCHANGE_DHE_RSA_ENABLED) -#if defined(MBEDTLS_AES_C) -#if defined(HAVE_SHA384) && defined(MBEDTLS_GCM_C) +#if defined(MBEDTLS_SSL_HAVE_AES) +#if defined(MBEDTLS_MD_CAN_SHA384) && \ + defined(MBEDTLS_SSL_HAVE_GCM) { MBEDTLS_TLS_DHE_RSA_WITH_AES_256_GCM_SHA384, "TLS-DHE-RSA-WITH-AES-256-GCM-SHA384", MBEDTLS_CIPHER_AES_256_GCM, MBEDTLS_MD_SHA384, MBEDTLS_KEY_EXCHANGE_DHE_RSA, - MBEDTLS_SSL_MAJOR_VERSION_3, MBEDTLS_SSL_MINOR_VERSION_3, - MBEDTLS_SSL_MAJOR_VERSION_3, MBEDTLS_SSL_MINOR_VERSION_3, - 0 }, -#endif /* HAVE_SHA384 && MBEDTLS_GCM_C */ + 0, + MBEDTLS_SSL_VERSION_TLS1_2, MBEDTLS_SSL_VERSION_TLS1_2 }, +#endif /* MBEDTLS_MD_CAN_SHA384 && MBEDTLS_SSL_HAVE_GCM */ -#if defined(MBEDTLS_SHA256_C) -#if defined(MBEDTLS_GCM_C) +#if defined(MBEDTLS_MD_CAN_SHA256) +#if defined(MBEDTLS_SSL_HAVE_GCM) { MBEDTLS_TLS_DHE_RSA_WITH_AES_128_GCM_SHA256, "TLS-DHE-RSA-WITH-AES-128-GCM-SHA256", MBEDTLS_CIPHER_AES_128_GCM, MBEDTLS_MD_SHA256, MBEDTLS_KEY_EXCHANGE_DHE_RSA, - MBEDTLS_SSL_MAJOR_VERSION_3, MBEDTLS_SSL_MINOR_VERSION_3, - MBEDTLS_SSL_MAJOR_VERSION_3, MBEDTLS_SSL_MINOR_VERSION_3, - 0 }, -#endif /* MBEDTLS_GCM_C */ + 0, + MBEDTLS_SSL_VERSION_TLS1_2, MBEDTLS_SSL_VERSION_TLS1_2 }, +#endif /* MBEDTLS_SSL_HAVE_GCM */ -#if defined(MBEDTLS_CIPHER_MODE_CBC) +#if defined(MBEDTLS_SSL_HAVE_CBC) { MBEDTLS_TLS_DHE_RSA_WITH_AES_128_CBC_SHA256, "TLS-DHE-RSA-WITH-AES-128-CBC-SHA256", MBEDTLS_CIPHER_AES_128_CBC, MBEDTLS_MD_SHA256, MBEDTLS_KEY_EXCHANGE_DHE_RSA, - MBEDTLS_SSL_MAJOR_VERSION_3, MBEDTLS_SSL_MINOR_VERSION_3, - MBEDTLS_SSL_MAJOR_VERSION_3, MBEDTLS_SSL_MINOR_VERSION_3, - 0 }, + 0, + MBEDTLS_SSL_VERSION_TLS1_2, MBEDTLS_SSL_VERSION_TLS1_2 }, { MBEDTLS_TLS_DHE_RSA_WITH_AES_256_CBC_SHA256, "TLS-DHE-RSA-WITH-AES-256-CBC-SHA256", MBEDTLS_CIPHER_AES_256_CBC, MBEDTLS_MD_SHA256, MBEDTLS_KEY_EXCHANGE_DHE_RSA, - MBEDTLS_SSL_MAJOR_VERSION_3, MBEDTLS_SSL_MINOR_VERSION_3, - MBEDTLS_SSL_MAJOR_VERSION_3, MBEDTLS_SSL_MINOR_VERSION_3, - 0 }, -#endif /* MBEDTLS_CIPHER_MODE_CBC */ -#endif /* MBEDTLS_SHA256_C */ - -#if defined(MBEDTLS_CIPHER_MODE_CBC) -#if defined(MBEDTLS_SHA1_C) + 0, + MBEDTLS_SSL_VERSION_TLS1_2, MBEDTLS_SSL_VERSION_TLS1_2 }, +#endif /* MBEDTLS_SSL_HAVE_CBC */ +#endif /* MBEDTLS_MD_CAN_SHA256 */ + +#if defined(MBEDTLS_SSL_HAVE_CBC) +#if defined(MBEDTLS_MD_CAN_SHA1) { MBEDTLS_TLS_DHE_RSA_WITH_AES_128_CBC_SHA, "TLS-DHE-RSA-WITH-AES-128-CBC-SHA", MBEDTLS_CIPHER_AES_128_CBC, MBEDTLS_MD_SHA1, MBEDTLS_KEY_EXCHANGE_DHE_RSA, - MBEDTLS_SSL_MAJOR_VERSION_3, MBEDTLS_SSL_MINOR_VERSION_0, - MBEDTLS_SSL_MAJOR_VERSION_3, MBEDTLS_SSL_MINOR_VERSION_3, - 0 }, + 0, + MBEDTLS_SSL_VERSION_TLS1_2, MBEDTLS_SSL_VERSION_TLS1_2 }, { MBEDTLS_TLS_DHE_RSA_WITH_AES_256_CBC_SHA, "TLS-DHE-RSA-WITH-AES-256-CBC-SHA", MBEDTLS_CIPHER_AES_256_CBC, MBEDTLS_MD_SHA1, MBEDTLS_KEY_EXCHANGE_DHE_RSA, - MBEDTLS_SSL_MAJOR_VERSION_3, MBEDTLS_SSL_MINOR_VERSION_0, - MBEDTLS_SSL_MAJOR_VERSION_3, MBEDTLS_SSL_MINOR_VERSION_3, - 0 }, -#endif /* MBEDTLS_SHA1_C */ -#endif /* MBEDTLS_CIPHER_MODE_CBC */ -#if defined(MBEDTLS_CCM_C) + 0, + MBEDTLS_SSL_VERSION_TLS1_2, MBEDTLS_SSL_VERSION_TLS1_2 }, +#endif /* MBEDTLS_MD_CAN_SHA1 */ +#endif /* MBEDTLS_SSL_HAVE_CBC */ +#if defined(MBEDTLS_SSL_HAVE_CCM) { MBEDTLS_TLS_DHE_RSA_WITH_AES_256_CCM, "TLS-DHE-RSA-WITH-AES-256-CCM", MBEDTLS_CIPHER_AES_256_CCM, MBEDTLS_MD_SHA256, MBEDTLS_KEY_EXCHANGE_DHE_RSA, - MBEDTLS_SSL_MAJOR_VERSION_3, MBEDTLS_SSL_MINOR_VERSION_3, - MBEDTLS_SSL_MAJOR_VERSION_3, MBEDTLS_SSL_MINOR_VERSION_3, - 0 }, + 0, + MBEDTLS_SSL_VERSION_TLS1_2, MBEDTLS_SSL_VERSION_TLS1_2 }, { MBEDTLS_TLS_DHE_RSA_WITH_AES_256_CCM_8, "TLS-DHE-RSA-WITH-AES-256-CCM-8", MBEDTLS_CIPHER_AES_256_CCM, MBEDTLS_MD_SHA256, MBEDTLS_KEY_EXCHANGE_DHE_RSA, - MBEDTLS_SSL_MAJOR_VERSION_3, MBEDTLS_SSL_MINOR_VERSION_3, - MBEDTLS_SSL_MAJOR_VERSION_3, MBEDTLS_SSL_MINOR_VERSION_3, - MBEDTLS_CIPHERSUITE_SHORT_TAG }, + MBEDTLS_CIPHERSUITE_SHORT_TAG, + MBEDTLS_SSL_VERSION_TLS1_2, MBEDTLS_SSL_VERSION_TLS1_2 }, { MBEDTLS_TLS_DHE_RSA_WITH_AES_128_CCM, "TLS-DHE-RSA-WITH-AES-128-CCM", MBEDTLS_CIPHER_AES_128_CCM, MBEDTLS_MD_SHA256, MBEDTLS_KEY_EXCHANGE_DHE_RSA, - MBEDTLS_SSL_MAJOR_VERSION_3, MBEDTLS_SSL_MINOR_VERSION_3, - MBEDTLS_SSL_MAJOR_VERSION_3, MBEDTLS_SSL_MINOR_VERSION_3, - 0 }, + 0, + MBEDTLS_SSL_VERSION_TLS1_2, MBEDTLS_SSL_VERSION_TLS1_2 }, { MBEDTLS_TLS_DHE_RSA_WITH_AES_128_CCM_8, "TLS-DHE-RSA-WITH-AES-128-CCM-8", MBEDTLS_CIPHER_AES_128_CCM, MBEDTLS_MD_SHA256, MBEDTLS_KEY_EXCHANGE_DHE_RSA, - MBEDTLS_SSL_MAJOR_VERSION_3, MBEDTLS_SSL_MINOR_VERSION_3, - MBEDTLS_SSL_MAJOR_VERSION_3, MBEDTLS_SSL_MINOR_VERSION_3, - MBEDTLS_CIPHERSUITE_SHORT_TAG }, -#endif /* MBEDTLS_CCM_C */ -#endif /* MBEDTLS_AES_C */ - -#if defined(MBEDTLS_CAMELLIA_C) -#if defined(MBEDTLS_CIPHER_MODE_CBC) -#if defined(MBEDTLS_SHA256_C) + MBEDTLS_CIPHERSUITE_SHORT_TAG, + MBEDTLS_SSL_VERSION_TLS1_2, MBEDTLS_SSL_VERSION_TLS1_2 }, +#endif /* MBEDTLS_SSL_HAVE_CCM */ +#endif /* MBEDTLS_SSL_HAVE_AES */ + +#if defined(MBEDTLS_SSL_HAVE_CAMELLIA) +#if defined(MBEDTLS_SSL_HAVE_CBC) +#if defined(MBEDTLS_MD_CAN_SHA256) { MBEDTLS_TLS_DHE_RSA_WITH_CAMELLIA_128_CBC_SHA256, "TLS-DHE-RSA-WITH-CAMELLIA-128-CBC-SHA256", MBEDTLS_CIPHER_CAMELLIA_128_CBC, MBEDTLS_MD_SHA256, MBEDTLS_KEY_EXCHANGE_DHE_RSA, - MBEDTLS_SSL_MAJOR_VERSION_3, MBEDTLS_SSL_MINOR_VERSION_3, - MBEDTLS_SSL_MAJOR_VERSION_3, MBEDTLS_SSL_MINOR_VERSION_3, - 0 }, + 0, + MBEDTLS_SSL_VERSION_TLS1_2, MBEDTLS_SSL_VERSION_TLS1_2 }, { MBEDTLS_TLS_DHE_RSA_WITH_CAMELLIA_256_CBC_SHA256, "TLS-DHE-RSA-WITH-CAMELLIA-256-CBC-SHA256", MBEDTLS_CIPHER_CAMELLIA_256_CBC, MBEDTLS_MD_SHA256, MBEDTLS_KEY_EXCHANGE_DHE_RSA, - MBEDTLS_SSL_MAJOR_VERSION_3, MBEDTLS_SSL_MINOR_VERSION_3, - MBEDTLS_SSL_MAJOR_VERSION_3, MBEDTLS_SSL_MINOR_VERSION_3, - 0 }, -#endif /* MBEDTLS_SHA256_C */ + 0, + MBEDTLS_SSL_VERSION_TLS1_2, MBEDTLS_SSL_VERSION_TLS1_2 }, +#endif /* MBEDTLS_MD_CAN_SHA256 */ -#if defined(MBEDTLS_SHA1_C) +#if defined(MBEDTLS_MD_CAN_SHA1) { MBEDTLS_TLS_DHE_RSA_WITH_CAMELLIA_128_CBC_SHA, "TLS-DHE-RSA-WITH-CAMELLIA-128-CBC-SHA", MBEDTLS_CIPHER_CAMELLIA_128_CBC, MBEDTLS_MD_SHA1, MBEDTLS_KEY_EXCHANGE_DHE_RSA, - MBEDTLS_SSL_MAJOR_VERSION_3, MBEDTLS_SSL_MINOR_VERSION_0, - MBEDTLS_SSL_MAJOR_VERSION_3, MBEDTLS_SSL_MINOR_VERSION_3, - 0 }, + 0, + MBEDTLS_SSL_VERSION_TLS1_2, MBEDTLS_SSL_VERSION_TLS1_2 }, { MBEDTLS_TLS_DHE_RSA_WITH_CAMELLIA_256_CBC_SHA, "TLS-DHE-RSA-WITH-CAMELLIA-256-CBC-SHA", MBEDTLS_CIPHER_CAMELLIA_256_CBC, MBEDTLS_MD_SHA1, MBEDTLS_KEY_EXCHANGE_DHE_RSA, - MBEDTLS_SSL_MAJOR_VERSION_3, MBEDTLS_SSL_MINOR_VERSION_0, - MBEDTLS_SSL_MAJOR_VERSION_3, MBEDTLS_SSL_MINOR_VERSION_3, - 0 }, -#endif /* MBEDTLS_SHA1_C */ -#endif /* MBEDTLS_CIPHER_MODE_CBC */ -#if defined(MBEDTLS_GCM_C) -#if defined(MBEDTLS_SHA256_C) + 0, + MBEDTLS_SSL_VERSION_TLS1_2, MBEDTLS_SSL_VERSION_TLS1_2 }, +#endif /* MBEDTLS_MD_CAN_SHA1 */ +#endif /* MBEDTLS_SSL_HAVE_CBC */ +#if defined(MBEDTLS_SSL_HAVE_GCM) +#if defined(MBEDTLS_MD_CAN_SHA256) { MBEDTLS_TLS_DHE_RSA_WITH_CAMELLIA_128_GCM_SHA256, "TLS-DHE-RSA-WITH-CAMELLIA-128-GCM-SHA256", MBEDTLS_CIPHER_CAMELLIA_128_GCM, MBEDTLS_MD_SHA256, MBEDTLS_KEY_EXCHANGE_DHE_RSA, - MBEDTLS_SSL_MAJOR_VERSION_3, MBEDTLS_SSL_MINOR_VERSION_3, - MBEDTLS_SSL_MAJOR_VERSION_3, MBEDTLS_SSL_MINOR_VERSION_3, - 0 }, -#endif /* MBEDTLS_SHA256_C */ + 0, + MBEDTLS_SSL_VERSION_TLS1_2, MBEDTLS_SSL_VERSION_TLS1_2 }, +#endif /* MBEDTLS_MD_CAN_SHA256 */ -#if defined(HAVE_SHA384) +#if defined(MBEDTLS_MD_CAN_SHA384) { MBEDTLS_TLS_DHE_RSA_WITH_CAMELLIA_256_GCM_SHA384, "TLS-DHE-RSA-WITH-CAMELLIA-256-GCM-SHA384", MBEDTLS_CIPHER_CAMELLIA_256_GCM, MBEDTLS_MD_SHA384, MBEDTLS_KEY_EXCHANGE_DHE_RSA, - MBEDTLS_SSL_MAJOR_VERSION_3, MBEDTLS_SSL_MINOR_VERSION_3, - MBEDTLS_SSL_MAJOR_VERSION_3, MBEDTLS_SSL_MINOR_VERSION_3, - 0 }, -#endif /* HAVE_SHA384 */ -#endif /* MBEDTLS_GCM_C */ -#endif /* MBEDTLS_CAMELLIA_C */ - -#if defined(MBEDTLS_DES_C) -#if defined(MBEDTLS_CIPHER_MODE_CBC) -#if defined(MBEDTLS_SHA1_C) - { MBEDTLS_TLS_DHE_RSA_WITH_3DES_EDE_CBC_SHA, "TLS-DHE-RSA-WITH-3DES-EDE-CBC-SHA", - MBEDTLS_CIPHER_DES_EDE3_CBC, MBEDTLS_MD_SHA1, MBEDTLS_KEY_EXCHANGE_DHE_RSA, - MBEDTLS_SSL_MAJOR_VERSION_3, MBEDTLS_SSL_MINOR_VERSION_0, - MBEDTLS_SSL_MAJOR_VERSION_3, MBEDTLS_SSL_MINOR_VERSION_3, - 0 }, -#endif /* MBEDTLS_SHA1_C */ -#endif /* MBEDTLS_CIPHER_MODE_CBC */ -#endif /* MBEDTLS_DES_C */ + 0, + MBEDTLS_SSL_VERSION_TLS1_2, MBEDTLS_SSL_VERSION_TLS1_2 }, +#endif /* MBEDTLS_MD_CAN_SHA384 */ +#endif /* MBEDTLS_SSL_HAVE_GCM */ +#endif /* MBEDTLS_SSL_HAVE_CAMELLIA */ + #endif /* MBEDTLS_KEY_EXCHANGE_DHE_RSA_ENABLED */ #if defined(MBEDTLS_KEY_EXCHANGE_RSA_ENABLED) -#if defined(MBEDTLS_AES_C) -#if defined(HAVE_SHA384) && defined(MBEDTLS_GCM_C) +#if defined(MBEDTLS_SSL_HAVE_AES) +#if defined(MBEDTLS_MD_CAN_SHA384) && \ + defined(MBEDTLS_SSL_HAVE_GCM) { MBEDTLS_TLS_RSA_WITH_AES_256_GCM_SHA384, "TLS-RSA-WITH-AES-256-GCM-SHA384", MBEDTLS_CIPHER_AES_256_GCM, MBEDTLS_MD_SHA384, MBEDTLS_KEY_EXCHANGE_RSA, - MBEDTLS_SSL_MAJOR_VERSION_3, MBEDTLS_SSL_MINOR_VERSION_3, - MBEDTLS_SSL_MAJOR_VERSION_3, MBEDTLS_SSL_MINOR_VERSION_3, - 0 }, -#endif /* HAVE_SHA384 && MBEDTLS_GCM_C */ + 0, + MBEDTLS_SSL_VERSION_TLS1_2, MBEDTLS_SSL_VERSION_TLS1_2 }, +#endif /* MBEDTLS_MD_CAN_SHA384 && MBEDTLS_SSL_HAVE_GCM */ -#if defined(MBEDTLS_SHA256_C) -#if defined(MBEDTLS_GCM_C) +#if defined(MBEDTLS_MD_CAN_SHA256) +#if defined(MBEDTLS_SSL_HAVE_GCM) { MBEDTLS_TLS_RSA_WITH_AES_128_GCM_SHA256, "TLS-RSA-WITH-AES-128-GCM-SHA256", MBEDTLS_CIPHER_AES_128_GCM, MBEDTLS_MD_SHA256, MBEDTLS_KEY_EXCHANGE_RSA, - MBEDTLS_SSL_MAJOR_VERSION_3, MBEDTLS_SSL_MINOR_VERSION_3, - MBEDTLS_SSL_MAJOR_VERSION_3, MBEDTLS_SSL_MINOR_VERSION_3, - 0 }, -#endif /* MBEDTLS_GCM_C */ + 0, + MBEDTLS_SSL_VERSION_TLS1_2, MBEDTLS_SSL_VERSION_TLS1_2 }, +#endif /* MBEDTLS_SSL_HAVE_GCM */ -#if defined(MBEDTLS_CIPHER_MODE_CBC) +#if defined(MBEDTLS_SSL_HAVE_CBC) { MBEDTLS_TLS_RSA_WITH_AES_128_CBC_SHA256, "TLS-RSA-WITH-AES-128-CBC-SHA256", MBEDTLS_CIPHER_AES_128_CBC, MBEDTLS_MD_SHA256, MBEDTLS_KEY_EXCHANGE_RSA, - MBEDTLS_SSL_MAJOR_VERSION_3, MBEDTLS_SSL_MINOR_VERSION_3, - MBEDTLS_SSL_MAJOR_VERSION_3, MBEDTLS_SSL_MINOR_VERSION_3, - 0 }, + 0, + MBEDTLS_SSL_VERSION_TLS1_2, MBEDTLS_SSL_VERSION_TLS1_2 }, { MBEDTLS_TLS_RSA_WITH_AES_256_CBC_SHA256, "TLS-RSA-WITH-AES-256-CBC-SHA256", MBEDTLS_CIPHER_AES_256_CBC, MBEDTLS_MD_SHA256, MBEDTLS_KEY_EXCHANGE_RSA, - MBEDTLS_SSL_MAJOR_VERSION_3, MBEDTLS_SSL_MINOR_VERSION_3, - MBEDTLS_SSL_MAJOR_VERSION_3, MBEDTLS_SSL_MINOR_VERSION_3, - 0 }, -#endif /* MBEDTLS_CIPHER_MODE_CBC */ -#endif /* MBEDTLS_SHA256_C */ - -#if defined(MBEDTLS_SHA1_C) -#if defined(MBEDTLS_CIPHER_MODE_CBC) + 0, + MBEDTLS_SSL_VERSION_TLS1_2, MBEDTLS_SSL_VERSION_TLS1_2 }, +#endif /* MBEDTLS_SSL_HAVE_CBC */ +#endif /* MBEDTLS_MD_CAN_SHA256 */ + +#if defined(MBEDTLS_MD_CAN_SHA1) +#if defined(MBEDTLS_SSL_HAVE_CBC) { MBEDTLS_TLS_RSA_WITH_AES_128_CBC_SHA, "TLS-RSA-WITH-AES-128-CBC-SHA", MBEDTLS_CIPHER_AES_128_CBC, MBEDTLS_MD_SHA1, MBEDTLS_KEY_EXCHANGE_RSA, - MBEDTLS_SSL_MAJOR_VERSION_3, MBEDTLS_SSL_MINOR_VERSION_0, - MBEDTLS_SSL_MAJOR_VERSION_3, MBEDTLS_SSL_MINOR_VERSION_3, - 0 }, + 0, + MBEDTLS_SSL_VERSION_TLS1_2, MBEDTLS_SSL_VERSION_TLS1_2 }, { MBEDTLS_TLS_RSA_WITH_AES_256_CBC_SHA, "TLS-RSA-WITH-AES-256-CBC-SHA", MBEDTLS_CIPHER_AES_256_CBC, MBEDTLS_MD_SHA1, MBEDTLS_KEY_EXCHANGE_RSA, - MBEDTLS_SSL_MAJOR_VERSION_3, MBEDTLS_SSL_MINOR_VERSION_0, - MBEDTLS_SSL_MAJOR_VERSION_3, MBEDTLS_SSL_MINOR_VERSION_3, - 0 }, -#endif /* MBEDTLS_CIPHER_MODE_CBC */ -#endif /* MBEDTLS_SHA1_C */ -#if defined(MBEDTLS_CCM_C) + 0, + MBEDTLS_SSL_VERSION_TLS1_2, MBEDTLS_SSL_VERSION_TLS1_2 }, +#endif /* MBEDTLS_SSL_HAVE_CBC */ +#endif /* MBEDTLS_MD_CAN_SHA1 */ +#if defined(MBEDTLS_SSL_HAVE_CCM) { MBEDTLS_TLS_RSA_WITH_AES_256_CCM, "TLS-RSA-WITH-AES-256-CCM", MBEDTLS_CIPHER_AES_256_CCM, MBEDTLS_MD_SHA256, MBEDTLS_KEY_EXCHANGE_RSA, - MBEDTLS_SSL_MAJOR_VERSION_3, MBEDTLS_SSL_MINOR_VERSION_3, - MBEDTLS_SSL_MAJOR_VERSION_3, MBEDTLS_SSL_MINOR_VERSION_3, - 0 }, + 0, + MBEDTLS_SSL_VERSION_TLS1_2, MBEDTLS_SSL_VERSION_TLS1_2 }, { MBEDTLS_TLS_RSA_WITH_AES_256_CCM_8, "TLS-RSA-WITH-AES-256-CCM-8", MBEDTLS_CIPHER_AES_256_CCM, MBEDTLS_MD_SHA256, MBEDTLS_KEY_EXCHANGE_RSA, - MBEDTLS_SSL_MAJOR_VERSION_3, MBEDTLS_SSL_MINOR_VERSION_3, - MBEDTLS_SSL_MAJOR_VERSION_3, MBEDTLS_SSL_MINOR_VERSION_3, - MBEDTLS_CIPHERSUITE_SHORT_TAG }, + MBEDTLS_CIPHERSUITE_SHORT_TAG, + MBEDTLS_SSL_VERSION_TLS1_2, MBEDTLS_SSL_VERSION_TLS1_2 }, { MBEDTLS_TLS_RSA_WITH_AES_128_CCM, "TLS-RSA-WITH-AES-128-CCM", MBEDTLS_CIPHER_AES_128_CCM, MBEDTLS_MD_SHA256, MBEDTLS_KEY_EXCHANGE_RSA, - MBEDTLS_SSL_MAJOR_VERSION_3, MBEDTLS_SSL_MINOR_VERSION_3, - MBEDTLS_SSL_MAJOR_VERSION_3, MBEDTLS_SSL_MINOR_VERSION_3, - 0 }, + 0, + MBEDTLS_SSL_VERSION_TLS1_2, MBEDTLS_SSL_VERSION_TLS1_2 }, { MBEDTLS_TLS_RSA_WITH_AES_128_CCM_8, "TLS-RSA-WITH-AES-128-CCM-8", MBEDTLS_CIPHER_AES_128_CCM, MBEDTLS_MD_SHA256, MBEDTLS_KEY_EXCHANGE_RSA, - MBEDTLS_SSL_MAJOR_VERSION_3, MBEDTLS_SSL_MINOR_VERSION_3, - MBEDTLS_SSL_MAJOR_VERSION_3, MBEDTLS_SSL_MINOR_VERSION_3, - MBEDTLS_CIPHERSUITE_SHORT_TAG }, -#endif /* MBEDTLS_CCM_C */ -#endif /* MBEDTLS_AES_C */ - -#if defined(MBEDTLS_CAMELLIA_C) -#if defined(MBEDTLS_CIPHER_MODE_CBC) -#if defined(MBEDTLS_SHA256_C) + MBEDTLS_CIPHERSUITE_SHORT_TAG, + MBEDTLS_SSL_VERSION_TLS1_2, MBEDTLS_SSL_VERSION_TLS1_2 }, +#endif /* MBEDTLS_SSL_HAVE_CCM */ +#endif /* MBEDTLS_SSL_HAVE_AES */ + +#if defined(MBEDTLS_SSL_HAVE_CAMELLIA) +#if defined(MBEDTLS_SSL_HAVE_CBC) +#if defined(MBEDTLS_MD_CAN_SHA256) { MBEDTLS_TLS_RSA_WITH_CAMELLIA_128_CBC_SHA256, "TLS-RSA-WITH-CAMELLIA-128-CBC-SHA256", MBEDTLS_CIPHER_CAMELLIA_128_CBC, MBEDTLS_MD_SHA256, MBEDTLS_KEY_EXCHANGE_RSA, - MBEDTLS_SSL_MAJOR_VERSION_3, MBEDTLS_SSL_MINOR_VERSION_3, - MBEDTLS_SSL_MAJOR_VERSION_3, MBEDTLS_SSL_MINOR_VERSION_3, - 0 }, + 0, + MBEDTLS_SSL_VERSION_TLS1_2, MBEDTLS_SSL_VERSION_TLS1_2 }, { MBEDTLS_TLS_RSA_WITH_CAMELLIA_256_CBC_SHA256, "TLS-RSA-WITH-CAMELLIA-256-CBC-SHA256", MBEDTLS_CIPHER_CAMELLIA_256_CBC, MBEDTLS_MD_SHA256, MBEDTLS_KEY_EXCHANGE_RSA, - MBEDTLS_SSL_MAJOR_VERSION_3, MBEDTLS_SSL_MINOR_VERSION_3, - MBEDTLS_SSL_MAJOR_VERSION_3, MBEDTLS_SSL_MINOR_VERSION_3, - 0 }, -#endif /* MBEDTLS_SHA256_C */ + 0, + MBEDTLS_SSL_VERSION_TLS1_2, MBEDTLS_SSL_VERSION_TLS1_2 }, +#endif /* MBEDTLS_MD_CAN_SHA256 */ -#if defined(MBEDTLS_SHA1_C) +#if defined(MBEDTLS_MD_CAN_SHA1) { MBEDTLS_TLS_RSA_WITH_CAMELLIA_128_CBC_SHA, "TLS-RSA-WITH-CAMELLIA-128-CBC-SHA", MBEDTLS_CIPHER_CAMELLIA_128_CBC, MBEDTLS_MD_SHA1, MBEDTLS_KEY_EXCHANGE_RSA, - MBEDTLS_SSL_MAJOR_VERSION_3, MBEDTLS_SSL_MINOR_VERSION_0, - MBEDTLS_SSL_MAJOR_VERSION_3, MBEDTLS_SSL_MINOR_VERSION_3, - 0 }, + 0, + MBEDTLS_SSL_VERSION_TLS1_2, MBEDTLS_SSL_VERSION_TLS1_2 }, { MBEDTLS_TLS_RSA_WITH_CAMELLIA_256_CBC_SHA, "TLS-RSA-WITH-CAMELLIA-256-CBC-SHA", MBEDTLS_CIPHER_CAMELLIA_256_CBC, MBEDTLS_MD_SHA1, MBEDTLS_KEY_EXCHANGE_RSA, - MBEDTLS_SSL_MAJOR_VERSION_3, MBEDTLS_SSL_MINOR_VERSION_0, - MBEDTLS_SSL_MAJOR_VERSION_3, MBEDTLS_SSL_MINOR_VERSION_3, - 0 }, -#endif /* MBEDTLS_SHA1_C */ -#endif /* MBEDTLS_CIPHER_MODE_CBC */ - -#if defined(MBEDTLS_GCM_C) -#if defined(MBEDTLS_SHA256_C) + 0, + MBEDTLS_SSL_VERSION_TLS1_2, MBEDTLS_SSL_VERSION_TLS1_2 }, +#endif /* MBEDTLS_MD_CAN_SHA1 */ +#endif /* MBEDTLS_SSL_HAVE_CBC */ + +#if defined(MBEDTLS_SSL_HAVE_GCM) +#if defined(MBEDTLS_MD_CAN_SHA256) { MBEDTLS_TLS_RSA_WITH_CAMELLIA_128_GCM_SHA256, "TLS-RSA-WITH-CAMELLIA-128-GCM-SHA256", MBEDTLS_CIPHER_CAMELLIA_128_GCM, MBEDTLS_MD_SHA256, MBEDTLS_KEY_EXCHANGE_RSA, - MBEDTLS_SSL_MAJOR_VERSION_3, MBEDTLS_SSL_MINOR_VERSION_3, - MBEDTLS_SSL_MAJOR_VERSION_3, MBEDTLS_SSL_MINOR_VERSION_3, - 0 }, -#endif /* MBEDTLS_SHA256_C */ + 0, + MBEDTLS_SSL_VERSION_TLS1_2, MBEDTLS_SSL_VERSION_TLS1_2 }, +#endif /* MBEDTLS_MD_CAN_SHA256 */ -#if defined(HAVE_SHA384) +#if defined(MBEDTLS_MD_CAN_SHA384) { MBEDTLS_TLS_RSA_WITH_CAMELLIA_256_GCM_SHA384, "TLS-RSA-WITH-CAMELLIA-256-GCM-SHA384", MBEDTLS_CIPHER_CAMELLIA_256_GCM, MBEDTLS_MD_SHA384, MBEDTLS_KEY_EXCHANGE_RSA, - MBEDTLS_SSL_MAJOR_VERSION_3, MBEDTLS_SSL_MINOR_VERSION_3, - MBEDTLS_SSL_MAJOR_VERSION_3, MBEDTLS_SSL_MINOR_VERSION_3, - 0 }, -#endif /* HAVE_SHA384 */ -#endif /* MBEDTLS_GCM_C */ -#endif /* MBEDTLS_CAMELLIA_C */ - -#if defined(MBEDTLS_DES_C) -#if defined(MBEDTLS_CIPHER_MODE_CBC) -#if defined(MBEDTLS_SHA1_C) - { MBEDTLS_TLS_RSA_WITH_3DES_EDE_CBC_SHA, "TLS-RSA-WITH-3DES-EDE-CBC-SHA", - MBEDTLS_CIPHER_DES_EDE3_CBC, MBEDTLS_MD_SHA1, MBEDTLS_KEY_EXCHANGE_RSA, - MBEDTLS_SSL_MAJOR_VERSION_3, MBEDTLS_SSL_MINOR_VERSION_0, - MBEDTLS_SSL_MAJOR_VERSION_3, MBEDTLS_SSL_MINOR_VERSION_3, - 0 }, -#endif /* MBEDTLS_SHA1_C */ -#endif /* MBEDTLS_CIPHER_MODE_CBC */ -#endif /* MBEDTLS_DES_C */ - -#if defined(MBEDTLS_ARC4_C) -#if defined(MBEDTLS_MD5_C) - { MBEDTLS_TLS_RSA_WITH_RC4_128_MD5, "TLS-RSA-WITH-RC4-128-MD5", - MBEDTLS_CIPHER_ARC4_128, MBEDTLS_MD_MD5, MBEDTLS_KEY_EXCHANGE_RSA, - MBEDTLS_SSL_MAJOR_VERSION_3, MBEDTLS_SSL_MINOR_VERSION_0, - MBEDTLS_SSL_MAJOR_VERSION_3, MBEDTLS_SSL_MINOR_VERSION_3, - MBEDTLS_CIPHERSUITE_NODTLS }, -#endif + 0, + MBEDTLS_SSL_VERSION_TLS1_2, MBEDTLS_SSL_VERSION_TLS1_2 }, +#endif /* MBEDTLS_MD_CAN_SHA384 */ +#endif /* MBEDTLS_SSL_HAVE_GCM */ +#endif /* MBEDTLS_SSL_HAVE_CAMELLIA */ -#if defined(MBEDTLS_SHA1_C) - { MBEDTLS_TLS_RSA_WITH_RC4_128_SHA, "TLS-RSA-WITH-RC4-128-SHA", - MBEDTLS_CIPHER_ARC4_128, MBEDTLS_MD_SHA1, MBEDTLS_KEY_EXCHANGE_RSA, - MBEDTLS_SSL_MAJOR_VERSION_3, MBEDTLS_SSL_MINOR_VERSION_0, - MBEDTLS_SSL_MAJOR_VERSION_3, MBEDTLS_SSL_MINOR_VERSION_3, - MBEDTLS_CIPHERSUITE_NODTLS }, -#endif -#endif /* MBEDTLS_ARC4_C */ #endif /* MBEDTLS_KEY_EXCHANGE_RSA_ENABLED */ #if defined(MBEDTLS_KEY_EXCHANGE_ECDH_RSA_ENABLED) -#if defined(MBEDTLS_AES_C) -#if defined(MBEDTLS_SHA1_C) -#if defined(MBEDTLS_CIPHER_MODE_CBC) +#if defined(MBEDTLS_SSL_HAVE_AES) +#if defined(MBEDTLS_MD_CAN_SHA1) +#if defined(MBEDTLS_SSL_HAVE_CBC) { MBEDTLS_TLS_ECDH_RSA_WITH_AES_128_CBC_SHA, "TLS-ECDH-RSA-WITH-AES-128-CBC-SHA", MBEDTLS_CIPHER_AES_128_CBC, MBEDTLS_MD_SHA1, MBEDTLS_KEY_EXCHANGE_ECDH_RSA, - MBEDTLS_SSL_MAJOR_VERSION_3, MBEDTLS_SSL_MINOR_VERSION_1, - MBEDTLS_SSL_MAJOR_VERSION_3, MBEDTLS_SSL_MINOR_VERSION_3, - 0 }, + 0, + MBEDTLS_SSL_VERSION_TLS1_2, MBEDTLS_SSL_VERSION_TLS1_2 }, { MBEDTLS_TLS_ECDH_RSA_WITH_AES_256_CBC_SHA, "TLS-ECDH-RSA-WITH-AES-256-CBC-SHA", MBEDTLS_CIPHER_AES_256_CBC, MBEDTLS_MD_SHA1, MBEDTLS_KEY_EXCHANGE_ECDH_RSA, - MBEDTLS_SSL_MAJOR_VERSION_3, MBEDTLS_SSL_MINOR_VERSION_1, - MBEDTLS_SSL_MAJOR_VERSION_3, MBEDTLS_SSL_MINOR_VERSION_3, - 0 }, -#endif /* MBEDTLS_CIPHER_MODE_CBC */ -#endif /* MBEDTLS_SHA1_C */ -#if defined(MBEDTLS_SHA256_C) -#if defined(MBEDTLS_CIPHER_MODE_CBC) + 0, + MBEDTLS_SSL_VERSION_TLS1_2, MBEDTLS_SSL_VERSION_TLS1_2 }, +#endif /* MBEDTLS_SSL_HAVE_CBC */ +#endif /* MBEDTLS_MD_CAN_SHA1 */ +#if defined(MBEDTLS_MD_CAN_SHA256) +#if defined(MBEDTLS_SSL_HAVE_CBC) { MBEDTLS_TLS_ECDH_RSA_WITH_AES_128_CBC_SHA256, "TLS-ECDH-RSA-WITH-AES-128-CBC-SHA256", MBEDTLS_CIPHER_AES_128_CBC, MBEDTLS_MD_SHA256, MBEDTLS_KEY_EXCHANGE_ECDH_RSA, - MBEDTLS_SSL_MAJOR_VERSION_3, MBEDTLS_SSL_MINOR_VERSION_3, - MBEDTLS_SSL_MAJOR_VERSION_3, MBEDTLS_SSL_MINOR_VERSION_3, - 0 }, -#endif /* MBEDTLS_CIPHER_MODE_CBC */ -#if defined(MBEDTLS_GCM_C) + 0, + MBEDTLS_SSL_VERSION_TLS1_2, MBEDTLS_SSL_VERSION_TLS1_2 }, +#endif /* MBEDTLS_SSL_HAVE_CBC */ +#if defined(MBEDTLS_SSL_HAVE_GCM) { MBEDTLS_TLS_ECDH_RSA_WITH_AES_128_GCM_SHA256, "TLS-ECDH-RSA-WITH-AES-128-GCM-SHA256", MBEDTLS_CIPHER_AES_128_GCM, MBEDTLS_MD_SHA256, MBEDTLS_KEY_EXCHANGE_ECDH_RSA, - MBEDTLS_SSL_MAJOR_VERSION_3, MBEDTLS_SSL_MINOR_VERSION_3, - MBEDTLS_SSL_MAJOR_VERSION_3, MBEDTLS_SSL_MINOR_VERSION_3, - 0 }, -#endif /* MBEDTLS_GCM_C */ -#endif /* MBEDTLS_SHA256_C */ -#if defined(HAVE_SHA384) -#if defined(MBEDTLS_CIPHER_MODE_CBC) + 0, + MBEDTLS_SSL_VERSION_TLS1_2, MBEDTLS_SSL_VERSION_TLS1_2 }, +#endif /* MBEDTLS_SSL_HAVE_GCM */ +#endif /* MBEDTLS_MD_CAN_SHA256 */ +#if defined(MBEDTLS_MD_CAN_SHA384) +#if defined(MBEDTLS_SSL_HAVE_CBC) { MBEDTLS_TLS_ECDH_RSA_WITH_AES_256_CBC_SHA384, "TLS-ECDH-RSA-WITH-AES-256-CBC-SHA384", MBEDTLS_CIPHER_AES_256_CBC, MBEDTLS_MD_SHA384, MBEDTLS_KEY_EXCHANGE_ECDH_RSA, - MBEDTLS_SSL_MAJOR_VERSION_3, MBEDTLS_SSL_MINOR_VERSION_3, - MBEDTLS_SSL_MAJOR_VERSION_3, MBEDTLS_SSL_MINOR_VERSION_3, - 0 }, -#endif /* MBEDTLS_CIPHER_MODE_CBC */ -#if defined(MBEDTLS_GCM_C) + 0, + MBEDTLS_SSL_VERSION_TLS1_2, MBEDTLS_SSL_VERSION_TLS1_2 }, +#endif /* MBEDTLS_SSL_HAVE_CBC */ +#if defined(MBEDTLS_SSL_HAVE_GCM) { MBEDTLS_TLS_ECDH_RSA_WITH_AES_256_GCM_SHA384, "TLS-ECDH-RSA-WITH-AES-256-GCM-SHA384", MBEDTLS_CIPHER_AES_256_GCM, MBEDTLS_MD_SHA384, MBEDTLS_KEY_EXCHANGE_ECDH_RSA, - MBEDTLS_SSL_MAJOR_VERSION_3, MBEDTLS_SSL_MINOR_VERSION_3, - MBEDTLS_SSL_MAJOR_VERSION_3, MBEDTLS_SSL_MINOR_VERSION_3, - 0 }, -#endif /* MBEDTLS_GCM_C */ -#endif /* HAVE_SHA384 */ -#endif /* MBEDTLS_AES_C */ - -#if defined(MBEDTLS_CAMELLIA_C) -#if defined(MBEDTLS_CIPHER_MODE_CBC) -#if defined(MBEDTLS_SHA256_C) + 0, + MBEDTLS_SSL_VERSION_TLS1_2, MBEDTLS_SSL_VERSION_TLS1_2 }, +#endif /* MBEDTLS_SSL_HAVE_GCM */ +#endif /* MBEDTLS_MD_CAN_SHA384 */ +#endif /* MBEDTLS_SSL_HAVE_AES */ + +#if defined(MBEDTLS_SSL_HAVE_CAMELLIA) +#if defined(MBEDTLS_SSL_HAVE_CBC) +#if defined(MBEDTLS_MD_CAN_SHA256) { MBEDTLS_TLS_ECDH_RSA_WITH_CAMELLIA_128_CBC_SHA256, "TLS-ECDH-RSA-WITH-CAMELLIA-128-CBC-SHA256", MBEDTLS_CIPHER_CAMELLIA_128_CBC, MBEDTLS_MD_SHA256, MBEDTLS_KEY_EXCHANGE_ECDH_RSA, - MBEDTLS_SSL_MAJOR_VERSION_3, MBEDTLS_SSL_MINOR_VERSION_1, - MBEDTLS_SSL_MAJOR_VERSION_3, MBEDTLS_SSL_MINOR_VERSION_3, - 0 }, -#endif /* MBEDTLS_SHA256_C */ -#if defined(HAVE_SHA384) + 0, + MBEDTLS_SSL_VERSION_TLS1_2, MBEDTLS_SSL_VERSION_TLS1_2 }, +#endif /* MBEDTLS_MD_CAN_SHA256 */ +#if defined(MBEDTLS_MD_CAN_SHA384) { MBEDTLS_TLS_ECDH_RSA_WITH_CAMELLIA_256_CBC_SHA384, "TLS-ECDH-RSA-WITH-CAMELLIA-256-CBC-SHA384", MBEDTLS_CIPHER_CAMELLIA_256_CBC, MBEDTLS_MD_SHA384, MBEDTLS_KEY_EXCHANGE_ECDH_RSA, - MBEDTLS_SSL_MAJOR_VERSION_3, MBEDTLS_SSL_MINOR_VERSION_1, - MBEDTLS_SSL_MAJOR_VERSION_3, MBEDTLS_SSL_MINOR_VERSION_3, - 0 }, -#endif /* HAVE_SHA384 */ -#endif /* MBEDTLS_CIPHER_MODE_CBC */ - -#if defined(MBEDTLS_GCM_C) -#if defined(MBEDTLS_SHA256_C) + 0, + MBEDTLS_SSL_VERSION_TLS1_2, MBEDTLS_SSL_VERSION_TLS1_2 }, +#endif /* MBEDTLS_MD_CAN_SHA384 */ +#endif /* MBEDTLS_SSL_HAVE_CBC */ + +#if defined(MBEDTLS_SSL_HAVE_GCM) +#if defined(MBEDTLS_MD_CAN_SHA256) { MBEDTLS_TLS_ECDH_RSA_WITH_CAMELLIA_128_GCM_SHA256, "TLS-ECDH-RSA-WITH-CAMELLIA-128-GCM-SHA256", MBEDTLS_CIPHER_CAMELLIA_128_GCM, MBEDTLS_MD_SHA256, MBEDTLS_KEY_EXCHANGE_ECDH_RSA, - MBEDTLS_SSL_MAJOR_VERSION_3, MBEDTLS_SSL_MINOR_VERSION_3, - MBEDTLS_SSL_MAJOR_VERSION_3, MBEDTLS_SSL_MINOR_VERSION_3, - 0 }, -#endif /* MBEDTLS_SHA256_C */ -#if defined(HAVE_SHA384) + 0, + MBEDTLS_SSL_VERSION_TLS1_2, MBEDTLS_SSL_VERSION_TLS1_2 }, +#endif /* MBEDTLS_MD_CAN_SHA256 */ +#if defined(MBEDTLS_MD_CAN_SHA384) { MBEDTLS_TLS_ECDH_RSA_WITH_CAMELLIA_256_GCM_SHA384, "TLS-ECDH-RSA-WITH-CAMELLIA-256-GCM-SHA384", MBEDTLS_CIPHER_CAMELLIA_256_GCM, MBEDTLS_MD_SHA384, MBEDTLS_KEY_EXCHANGE_ECDH_RSA, - MBEDTLS_SSL_MAJOR_VERSION_3, MBEDTLS_SSL_MINOR_VERSION_3, - MBEDTLS_SSL_MAJOR_VERSION_3, MBEDTLS_SSL_MINOR_VERSION_3, - 0 }, -#endif /* HAVE_SHA384 */ -#endif /* MBEDTLS_GCM_C */ -#endif /* MBEDTLS_CAMELLIA_C */ - -#if defined(MBEDTLS_DES_C) -#if defined(MBEDTLS_CIPHER_MODE_CBC) -#if defined(MBEDTLS_SHA1_C) - { MBEDTLS_TLS_ECDH_RSA_WITH_3DES_EDE_CBC_SHA, "TLS-ECDH-RSA-WITH-3DES-EDE-CBC-SHA", - MBEDTLS_CIPHER_DES_EDE3_CBC, MBEDTLS_MD_SHA1, MBEDTLS_KEY_EXCHANGE_ECDH_RSA, - MBEDTLS_SSL_MAJOR_VERSION_3, MBEDTLS_SSL_MINOR_VERSION_1, - MBEDTLS_SSL_MAJOR_VERSION_3, MBEDTLS_SSL_MINOR_VERSION_3, - 0 }, -#endif /* MBEDTLS_SHA1_C */ -#endif /* MBEDTLS_CIPHER_MODE_CBC */ -#endif /* MBEDTLS_DES_C */ - -#if defined(MBEDTLS_ARC4_C) -#if defined(MBEDTLS_SHA1_C) - { MBEDTLS_TLS_ECDH_RSA_WITH_RC4_128_SHA, "TLS-ECDH-RSA-WITH-RC4-128-SHA", - MBEDTLS_CIPHER_ARC4_128, MBEDTLS_MD_SHA1, MBEDTLS_KEY_EXCHANGE_ECDH_RSA, - MBEDTLS_SSL_MAJOR_VERSION_3, MBEDTLS_SSL_MINOR_VERSION_1, - MBEDTLS_SSL_MAJOR_VERSION_3, MBEDTLS_SSL_MINOR_VERSION_3, - MBEDTLS_CIPHERSUITE_NODTLS }, -#endif /* MBEDTLS_SHA1_C */ -#endif /* MBEDTLS_ARC4_C */ + 0, + MBEDTLS_SSL_VERSION_TLS1_2, MBEDTLS_SSL_VERSION_TLS1_2 }, +#endif /* MBEDTLS_MD_CAN_SHA384 */ +#endif /* MBEDTLS_SSL_HAVE_GCM */ +#endif /* MBEDTLS_SSL_HAVE_CAMELLIA */ #if defined(MBEDTLS_CIPHER_NULL_CIPHER) -#if defined(MBEDTLS_SHA1_C) +#if defined(MBEDTLS_MD_CAN_SHA1) { MBEDTLS_TLS_ECDH_RSA_WITH_NULL_SHA, "TLS-ECDH-RSA-WITH-NULL-SHA", MBEDTLS_CIPHER_NULL, MBEDTLS_MD_SHA1, MBEDTLS_KEY_EXCHANGE_ECDH_RSA, - MBEDTLS_SSL_MAJOR_VERSION_3, MBEDTLS_SSL_MINOR_VERSION_1, - MBEDTLS_SSL_MAJOR_VERSION_3, MBEDTLS_SSL_MINOR_VERSION_3, - MBEDTLS_CIPHERSUITE_WEAK }, -#endif /* MBEDTLS_SHA1_C */ + MBEDTLS_CIPHERSUITE_WEAK, + MBEDTLS_SSL_VERSION_TLS1_2, MBEDTLS_SSL_VERSION_TLS1_2 }, +#endif /* MBEDTLS_MD_CAN_SHA1 */ #endif /* MBEDTLS_CIPHER_NULL_CIPHER */ #endif /* MBEDTLS_KEY_EXCHANGE_ECDH_RSA_ENABLED */ #if defined(MBEDTLS_KEY_EXCHANGE_ECDH_ECDSA_ENABLED) -#if defined(MBEDTLS_AES_C) -#if defined(MBEDTLS_SHA1_C) -#if defined(MBEDTLS_CIPHER_MODE_CBC) +#if defined(MBEDTLS_SSL_HAVE_AES) +#if defined(MBEDTLS_MD_CAN_SHA1) +#if defined(MBEDTLS_SSL_HAVE_CBC) { MBEDTLS_TLS_ECDH_ECDSA_WITH_AES_128_CBC_SHA, "TLS-ECDH-ECDSA-WITH-AES-128-CBC-SHA", MBEDTLS_CIPHER_AES_128_CBC, MBEDTLS_MD_SHA1, MBEDTLS_KEY_EXCHANGE_ECDH_ECDSA, - MBEDTLS_SSL_MAJOR_VERSION_3, MBEDTLS_SSL_MINOR_VERSION_1, - MBEDTLS_SSL_MAJOR_VERSION_3, MBEDTLS_SSL_MINOR_VERSION_3, - 0 }, + 0, + MBEDTLS_SSL_VERSION_TLS1_2, MBEDTLS_SSL_VERSION_TLS1_2 }, { MBEDTLS_TLS_ECDH_ECDSA_WITH_AES_256_CBC_SHA, "TLS-ECDH-ECDSA-WITH-AES-256-CBC-SHA", MBEDTLS_CIPHER_AES_256_CBC, MBEDTLS_MD_SHA1, MBEDTLS_KEY_EXCHANGE_ECDH_ECDSA, - MBEDTLS_SSL_MAJOR_VERSION_3, MBEDTLS_SSL_MINOR_VERSION_1, - MBEDTLS_SSL_MAJOR_VERSION_3, MBEDTLS_SSL_MINOR_VERSION_3, - 0 }, -#endif /* MBEDTLS_CIPHER_MODE_CBC */ -#endif /* MBEDTLS_SHA1_C */ -#if defined(MBEDTLS_SHA256_C) -#if defined(MBEDTLS_CIPHER_MODE_CBC) + 0, + MBEDTLS_SSL_VERSION_TLS1_2, MBEDTLS_SSL_VERSION_TLS1_2 }, +#endif /* MBEDTLS_SSL_HAVE_CBC */ +#endif /* MBEDTLS_MD_CAN_SHA1 */ +#if defined(MBEDTLS_MD_CAN_SHA256) +#if defined(MBEDTLS_SSL_HAVE_CBC) { MBEDTLS_TLS_ECDH_ECDSA_WITH_AES_128_CBC_SHA256, "TLS-ECDH-ECDSA-WITH-AES-128-CBC-SHA256", MBEDTLS_CIPHER_AES_128_CBC, MBEDTLS_MD_SHA256, MBEDTLS_KEY_EXCHANGE_ECDH_ECDSA, - MBEDTLS_SSL_MAJOR_VERSION_3, MBEDTLS_SSL_MINOR_VERSION_3, - MBEDTLS_SSL_MAJOR_VERSION_3, MBEDTLS_SSL_MINOR_VERSION_3, - 0 }, -#endif /* MBEDTLS_CIPHER_MODE_CBC */ -#if defined(MBEDTLS_GCM_C) + 0, + MBEDTLS_SSL_VERSION_TLS1_2, MBEDTLS_SSL_VERSION_TLS1_2 }, +#endif /* MBEDTLS_SSL_HAVE_CBC */ +#if defined(MBEDTLS_SSL_HAVE_GCM) { MBEDTLS_TLS_ECDH_ECDSA_WITH_AES_128_GCM_SHA256, "TLS-ECDH-ECDSA-WITH-AES-128-GCM-SHA256", MBEDTLS_CIPHER_AES_128_GCM, MBEDTLS_MD_SHA256, MBEDTLS_KEY_EXCHANGE_ECDH_ECDSA, - MBEDTLS_SSL_MAJOR_VERSION_3, MBEDTLS_SSL_MINOR_VERSION_3, - MBEDTLS_SSL_MAJOR_VERSION_3, MBEDTLS_SSL_MINOR_VERSION_3, - 0 }, -#endif /* MBEDTLS_GCM_C */ -#endif /* MBEDTLS_SHA256_C */ -#if defined(HAVE_SHA384) -#if defined(MBEDTLS_CIPHER_MODE_CBC) + 0, + MBEDTLS_SSL_VERSION_TLS1_2, MBEDTLS_SSL_VERSION_TLS1_2 }, +#endif /* MBEDTLS_SSL_HAVE_GCM */ +#endif /* MBEDTLS_MD_CAN_SHA256 */ +#if defined(MBEDTLS_MD_CAN_SHA384) +#if defined(MBEDTLS_SSL_HAVE_CBC) { MBEDTLS_TLS_ECDH_ECDSA_WITH_AES_256_CBC_SHA384, "TLS-ECDH-ECDSA-WITH-AES-256-CBC-SHA384", MBEDTLS_CIPHER_AES_256_CBC, MBEDTLS_MD_SHA384, MBEDTLS_KEY_EXCHANGE_ECDH_ECDSA, - MBEDTLS_SSL_MAJOR_VERSION_3, MBEDTLS_SSL_MINOR_VERSION_3, - MBEDTLS_SSL_MAJOR_VERSION_3, MBEDTLS_SSL_MINOR_VERSION_3, - 0 }, -#endif /* MBEDTLS_CIPHER_MODE_CBC */ -#if defined(MBEDTLS_GCM_C) + 0, + MBEDTLS_SSL_VERSION_TLS1_2, MBEDTLS_SSL_VERSION_TLS1_2 }, +#endif /* MBEDTLS_SSL_HAVE_CBC */ +#if defined(MBEDTLS_SSL_HAVE_GCM) { MBEDTLS_TLS_ECDH_ECDSA_WITH_AES_256_GCM_SHA384, "TLS-ECDH-ECDSA-WITH-AES-256-GCM-SHA384", MBEDTLS_CIPHER_AES_256_GCM, MBEDTLS_MD_SHA384, MBEDTLS_KEY_EXCHANGE_ECDH_ECDSA, - MBEDTLS_SSL_MAJOR_VERSION_3, MBEDTLS_SSL_MINOR_VERSION_3, - MBEDTLS_SSL_MAJOR_VERSION_3, MBEDTLS_SSL_MINOR_VERSION_3, - 0 }, -#endif /* MBEDTLS_GCM_C */ -#endif /* HAVE_SHA384 */ -#endif /* MBEDTLS_AES_C */ - -#if defined(MBEDTLS_CAMELLIA_C) -#if defined(MBEDTLS_CIPHER_MODE_CBC) -#if defined(MBEDTLS_SHA256_C) + 0, + MBEDTLS_SSL_VERSION_TLS1_2, MBEDTLS_SSL_VERSION_TLS1_2 }, +#endif /* MBEDTLS_SSL_HAVE_GCM */ +#endif /* MBEDTLS_MD_CAN_SHA384 */ +#endif /* MBEDTLS_SSL_HAVE_AES */ + +#if defined(MBEDTLS_SSL_HAVE_CAMELLIA) +#if defined(MBEDTLS_SSL_HAVE_CBC) +#if defined(MBEDTLS_MD_CAN_SHA256) { MBEDTLS_TLS_ECDH_ECDSA_WITH_CAMELLIA_128_CBC_SHA256, "TLS-ECDH-ECDSA-WITH-CAMELLIA-128-CBC-SHA256", MBEDTLS_CIPHER_CAMELLIA_128_CBC, MBEDTLS_MD_SHA256, MBEDTLS_KEY_EXCHANGE_ECDH_ECDSA, - MBEDTLS_SSL_MAJOR_VERSION_3, MBEDTLS_SSL_MINOR_VERSION_1, - MBEDTLS_SSL_MAJOR_VERSION_3, MBEDTLS_SSL_MINOR_VERSION_3, - 0 }, -#endif /* MBEDTLS_SHA256_C */ -#if defined(HAVE_SHA384) + 0, + MBEDTLS_SSL_VERSION_TLS1_2, MBEDTLS_SSL_VERSION_TLS1_2 }, +#endif /* MBEDTLS_MD_CAN_SHA256 */ +#if defined(MBEDTLS_MD_CAN_SHA384) { MBEDTLS_TLS_ECDH_ECDSA_WITH_CAMELLIA_256_CBC_SHA384, "TLS-ECDH-ECDSA-WITH-CAMELLIA-256-CBC-SHA384", MBEDTLS_CIPHER_CAMELLIA_256_CBC, MBEDTLS_MD_SHA384, MBEDTLS_KEY_EXCHANGE_ECDH_ECDSA, - MBEDTLS_SSL_MAJOR_VERSION_3, MBEDTLS_SSL_MINOR_VERSION_1, - MBEDTLS_SSL_MAJOR_VERSION_3, MBEDTLS_SSL_MINOR_VERSION_3, - 0 }, -#endif /* HAVE_SHA384 */ -#endif /* MBEDTLS_CIPHER_MODE_CBC */ - -#if defined(MBEDTLS_GCM_C) -#if defined(MBEDTLS_SHA256_C) + 0, + MBEDTLS_SSL_VERSION_TLS1_2, MBEDTLS_SSL_VERSION_TLS1_2 }, +#endif /* MBEDTLS_MD_CAN_SHA384 */ +#endif /* MBEDTLS_SSL_HAVE_CBC */ + +#if defined(MBEDTLS_SSL_HAVE_GCM) +#if defined(MBEDTLS_MD_CAN_SHA256) { MBEDTLS_TLS_ECDH_ECDSA_WITH_CAMELLIA_128_GCM_SHA256, "TLS-ECDH-ECDSA-WITH-CAMELLIA-128-GCM-SHA256", MBEDTLS_CIPHER_CAMELLIA_128_GCM, MBEDTLS_MD_SHA256, MBEDTLS_KEY_EXCHANGE_ECDH_ECDSA, - MBEDTLS_SSL_MAJOR_VERSION_3, MBEDTLS_SSL_MINOR_VERSION_3, - MBEDTLS_SSL_MAJOR_VERSION_3, MBEDTLS_SSL_MINOR_VERSION_3, - 0 }, -#endif /* MBEDTLS_SHA256_C */ -#if defined(HAVE_SHA384) + 0, + MBEDTLS_SSL_VERSION_TLS1_2, MBEDTLS_SSL_VERSION_TLS1_2 }, +#endif /* MBEDTLS_MD_CAN_SHA256 */ +#if defined(MBEDTLS_MD_CAN_SHA384) { MBEDTLS_TLS_ECDH_ECDSA_WITH_CAMELLIA_256_GCM_SHA384, "TLS-ECDH-ECDSA-WITH-CAMELLIA-256-GCM-SHA384", MBEDTLS_CIPHER_CAMELLIA_256_GCM, MBEDTLS_MD_SHA384, MBEDTLS_KEY_EXCHANGE_ECDH_ECDSA, - MBEDTLS_SSL_MAJOR_VERSION_3, MBEDTLS_SSL_MINOR_VERSION_3, - MBEDTLS_SSL_MAJOR_VERSION_3, MBEDTLS_SSL_MINOR_VERSION_3, - 0 }, -#endif /* HAVE_SHA384 */ -#endif /* MBEDTLS_GCM_C */ -#endif /* MBEDTLS_CAMELLIA_C */ - -#if defined(MBEDTLS_DES_C) -#if defined(MBEDTLS_CIPHER_MODE_CBC) -#if defined(MBEDTLS_SHA1_C) - { MBEDTLS_TLS_ECDH_ECDSA_WITH_3DES_EDE_CBC_SHA, "TLS-ECDH-ECDSA-WITH-3DES-EDE-CBC-SHA", - MBEDTLS_CIPHER_DES_EDE3_CBC, MBEDTLS_MD_SHA1, MBEDTLS_KEY_EXCHANGE_ECDH_ECDSA, - MBEDTLS_SSL_MAJOR_VERSION_3, MBEDTLS_SSL_MINOR_VERSION_1, - MBEDTLS_SSL_MAJOR_VERSION_3, MBEDTLS_SSL_MINOR_VERSION_3, - 0 }, -#endif /* MBEDTLS_SHA1_C */ -#endif /* MBEDTLS_CIPHER_MODE_CBC */ -#endif /* MBEDTLS_DES_C */ - -#if defined(MBEDTLS_ARC4_C) -#if defined(MBEDTLS_SHA1_C) - { MBEDTLS_TLS_ECDH_ECDSA_WITH_RC4_128_SHA, "TLS-ECDH-ECDSA-WITH-RC4-128-SHA", - MBEDTLS_CIPHER_ARC4_128, MBEDTLS_MD_SHA1, MBEDTLS_KEY_EXCHANGE_ECDH_ECDSA, - MBEDTLS_SSL_MAJOR_VERSION_3, MBEDTLS_SSL_MINOR_VERSION_1, - MBEDTLS_SSL_MAJOR_VERSION_3, MBEDTLS_SSL_MINOR_VERSION_3, - MBEDTLS_CIPHERSUITE_NODTLS }, -#endif /* MBEDTLS_SHA1_C */ -#endif /* MBEDTLS_ARC4_C */ + 0, + MBEDTLS_SSL_VERSION_TLS1_2, MBEDTLS_SSL_VERSION_TLS1_2 }, +#endif /* MBEDTLS_MD_CAN_SHA384 */ +#endif /* MBEDTLS_SSL_HAVE_GCM */ +#endif /* MBEDTLS_SSL_HAVE_CAMELLIA */ #if defined(MBEDTLS_CIPHER_NULL_CIPHER) -#if defined(MBEDTLS_SHA1_C) +#if defined(MBEDTLS_MD_CAN_SHA1) { MBEDTLS_TLS_ECDH_ECDSA_WITH_NULL_SHA, "TLS-ECDH-ECDSA-WITH-NULL-SHA", MBEDTLS_CIPHER_NULL, MBEDTLS_MD_SHA1, MBEDTLS_KEY_EXCHANGE_ECDH_ECDSA, - MBEDTLS_SSL_MAJOR_VERSION_3, MBEDTLS_SSL_MINOR_VERSION_1, - MBEDTLS_SSL_MAJOR_VERSION_3, MBEDTLS_SSL_MINOR_VERSION_3, - MBEDTLS_CIPHERSUITE_WEAK }, -#endif /* MBEDTLS_SHA1_C */ + MBEDTLS_CIPHERSUITE_WEAK, + MBEDTLS_SSL_VERSION_TLS1_2, MBEDTLS_SSL_VERSION_TLS1_2 }, +#endif /* MBEDTLS_MD_CAN_SHA1 */ #endif /* MBEDTLS_CIPHER_NULL_CIPHER */ #endif /* MBEDTLS_KEY_EXCHANGE_ECDH_ECDSA_ENABLED */ #if defined(MBEDTLS_KEY_EXCHANGE_PSK_ENABLED) -#if defined(MBEDTLS_AES_C) -#if defined(MBEDTLS_GCM_C) -#if defined(MBEDTLS_SHA256_C) +#if defined(MBEDTLS_SSL_HAVE_AES) +#if defined(MBEDTLS_SSL_HAVE_GCM) +#if defined(MBEDTLS_MD_CAN_SHA256) { MBEDTLS_TLS_PSK_WITH_AES_128_GCM_SHA256, "TLS-PSK-WITH-AES-128-GCM-SHA256", MBEDTLS_CIPHER_AES_128_GCM, MBEDTLS_MD_SHA256, MBEDTLS_KEY_EXCHANGE_PSK, - MBEDTLS_SSL_MAJOR_VERSION_3, MBEDTLS_SSL_MINOR_VERSION_3, - MBEDTLS_SSL_MAJOR_VERSION_3, MBEDTLS_SSL_MINOR_VERSION_3, - 0 }, -#endif /* MBEDTLS_SHA256_C */ + 0, + MBEDTLS_SSL_VERSION_TLS1_2, MBEDTLS_SSL_VERSION_TLS1_2 }, +#endif /* MBEDTLS_MD_CAN_SHA256 */ -#if defined(HAVE_SHA384) +#if defined(MBEDTLS_MD_CAN_SHA384) { MBEDTLS_TLS_PSK_WITH_AES_256_GCM_SHA384, "TLS-PSK-WITH-AES-256-GCM-SHA384", MBEDTLS_CIPHER_AES_256_GCM, MBEDTLS_MD_SHA384, MBEDTLS_KEY_EXCHANGE_PSK, - MBEDTLS_SSL_MAJOR_VERSION_3, MBEDTLS_SSL_MINOR_VERSION_3, - MBEDTLS_SSL_MAJOR_VERSION_3, MBEDTLS_SSL_MINOR_VERSION_3, - 0 }, -#endif /* HAVE_SHA384 */ -#endif /* MBEDTLS_GCM_C */ - -#if defined(MBEDTLS_CIPHER_MODE_CBC) -#if defined(MBEDTLS_SHA256_C) + 0, + MBEDTLS_SSL_VERSION_TLS1_2, MBEDTLS_SSL_VERSION_TLS1_2 }, +#endif /* MBEDTLS_MD_CAN_SHA384 */ +#endif /* MBEDTLS_SSL_HAVE_GCM */ + +#if defined(MBEDTLS_SSL_HAVE_CBC) +#if defined(MBEDTLS_MD_CAN_SHA256) { MBEDTLS_TLS_PSK_WITH_AES_128_CBC_SHA256, "TLS-PSK-WITH-AES-128-CBC-SHA256", MBEDTLS_CIPHER_AES_128_CBC, MBEDTLS_MD_SHA256, MBEDTLS_KEY_EXCHANGE_PSK, - MBEDTLS_SSL_MAJOR_VERSION_3, MBEDTLS_SSL_MINOR_VERSION_1, - MBEDTLS_SSL_MAJOR_VERSION_3, MBEDTLS_SSL_MINOR_VERSION_3, - 0 }, -#endif /* MBEDTLS_SHA256_C */ + 0, + MBEDTLS_SSL_VERSION_TLS1_2, MBEDTLS_SSL_VERSION_TLS1_2 }, +#endif /* MBEDTLS_MD_CAN_SHA256 */ -#if defined(HAVE_SHA384) +#if defined(MBEDTLS_MD_CAN_SHA384) { MBEDTLS_TLS_PSK_WITH_AES_256_CBC_SHA384, "TLS-PSK-WITH-AES-256-CBC-SHA384", MBEDTLS_CIPHER_AES_256_CBC, MBEDTLS_MD_SHA384, MBEDTLS_KEY_EXCHANGE_PSK, - MBEDTLS_SSL_MAJOR_VERSION_3, MBEDTLS_SSL_MINOR_VERSION_1, - MBEDTLS_SSL_MAJOR_VERSION_3, MBEDTLS_SSL_MINOR_VERSION_3, - 0 }, -#endif /* HAVE_SHA384 */ + 0, + MBEDTLS_SSL_VERSION_TLS1_2, MBEDTLS_SSL_VERSION_TLS1_2 }, +#endif /* MBEDTLS_MD_CAN_SHA384 */ -#if defined(MBEDTLS_SHA1_C) +#if defined(MBEDTLS_MD_CAN_SHA1) { MBEDTLS_TLS_PSK_WITH_AES_128_CBC_SHA, "TLS-PSK-WITH-AES-128-CBC-SHA", MBEDTLS_CIPHER_AES_128_CBC, MBEDTLS_MD_SHA1, MBEDTLS_KEY_EXCHANGE_PSK, - MBEDTLS_SSL_MAJOR_VERSION_3, MBEDTLS_SSL_MINOR_VERSION_0, - MBEDTLS_SSL_MAJOR_VERSION_3, MBEDTLS_SSL_MINOR_VERSION_3, - 0 }, + 0, + MBEDTLS_SSL_VERSION_TLS1_2, MBEDTLS_SSL_VERSION_TLS1_2 }, { MBEDTLS_TLS_PSK_WITH_AES_256_CBC_SHA, "TLS-PSK-WITH-AES-256-CBC-SHA", MBEDTLS_CIPHER_AES_256_CBC, MBEDTLS_MD_SHA1, MBEDTLS_KEY_EXCHANGE_PSK, - MBEDTLS_SSL_MAJOR_VERSION_3, MBEDTLS_SSL_MINOR_VERSION_0, - MBEDTLS_SSL_MAJOR_VERSION_3, MBEDTLS_SSL_MINOR_VERSION_3, - 0 }, -#endif /* MBEDTLS_SHA1_C */ -#endif /* MBEDTLS_CIPHER_MODE_CBC */ -#if defined(MBEDTLS_CCM_C) + 0, + MBEDTLS_SSL_VERSION_TLS1_2, MBEDTLS_SSL_VERSION_TLS1_2 }, +#endif /* MBEDTLS_MD_CAN_SHA1 */ +#endif /* MBEDTLS_SSL_HAVE_CBC */ +#if defined(MBEDTLS_SSL_HAVE_CCM) { MBEDTLS_TLS_PSK_WITH_AES_256_CCM, "TLS-PSK-WITH-AES-256-CCM", MBEDTLS_CIPHER_AES_256_CCM, MBEDTLS_MD_SHA256, MBEDTLS_KEY_EXCHANGE_PSK, - MBEDTLS_SSL_MAJOR_VERSION_3, MBEDTLS_SSL_MINOR_VERSION_3, - MBEDTLS_SSL_MAJOR_VERSION_3, MBEDTLS_SSL_MINOR_VERSION_3, - 0 }, + 0, + MBEDTLS_SSL_VERSION_TLS1_2, MBEDTLS_SSL_VERSION_TLS1_2 }, { MBEDTLS_TLS_PSK_WITH_AES_256_CCM_8, "TLS-PSK-WITH-AES-256-CCM-8", MBEDTLS_CIPHER_AES_256_CCM, MBEDTLS_MD_SHA256, MBEDTLS_KEY_EXCHANGE_PSK, - MBEDTLS_SSL_MAJOR_VERSION_3, MBEDTLS_SSL_MINOR_VERSION_3, - MBEDTLS_SSL_MAJOR_VERSION_3, MBEDTLS_SSL_MINOR_VERSION_3, - MBEDTLS_CIPHERSUITE_SHORT_TAG }, + MBEDTLS_CIPHERSUITE_SHORT_TAG, + MBEDTLS_SSL_VERSION_TLS1_2, MBEDTLS_SSL_VERSION_TLS1_2 }, { MBEDTLS_TLS_PSK_WITH_AES_128_CCM, "TLS-PSK-WITH-AES-128-CCM", MBEDTLS_CIPHER_AES_128_CCM, MBEDTLS_MD_SHA256, MBEDTLS_KEY_EXCHANGE_PSK, - MBEDTLS_SSL_MAJOR_VERSION_3, MBEDTLS_SSL_MINOR_VERSION_3, - MBEDTLS_SSL_MAJOR_VERSION_3, MBEDTLS_SSL_MINOR_VERSION_3, - 0 }, + 0, + MBEDTLS_SSL_VERSION_TLS1_2, MBEDTLS_SSL_VERSION_TLS1_2 }, { MBEDTLS_TLS_PSK_WITH_AES_128_CCM_8, "TLS-PSK-WITH-AES-128-CCM-8", MBEDTLS_CIPHER_AES_128_CCM, MBEDTLS_MD_SHA256, MBEDTLS_KEY_EXCHANGE_PSK, - MBEDTLS_SSL_MAJOR_VERSION_3, MBEDTLS_SSL_MINOR_VERSION_3, - MBEDTLS_SSL_MAJOR_VERSION_3, MBEDTLS_SSL_MINOR_VERSION_3, - MBEDTLS_CIPHERSUITE_SHORT_TAG }, -#endif /* MBEDTLS_CCM_C */ -#endif /* MBEDTLS_AES_C */ - -#if defined(MBEDTLS_CAMELLIA_C) -#if defined(MBEDTLS_CIPHER_MODE_CBC) -#if defined(MBEDTLS_SHA256_C) + MBEDTLS_CIPHERSUITE_SHORT_TAG, + MBEDTLS_SSL_VERSION_TLS1_2, MBEDTLS_SSL_VERSION_TLS1_2 }, +#endif /* MBEDTLS_SSL_HAVE_CCM */ +#endif /* MBEDTLS_SSL_HAVE_AES */ + +#if defined(MBEDTLS_SSL_HAVE_CAMELLIA) +#if defined(MBEDTLS_SSL_HAVE_CBC) +#if defined(MBEDTLS_MD_CAN_SHA256) { MBEDTLS_TLS_PSK_WITH_CAMELLIA_128_CBC_SHA256, "TLS-PSK-WITH-CAMELLIA-128-CBC-SHA256", MBEDTLS_CIPHER_CAMELLIA_128_CBC, MBEDTLS_MD_SHA256, MBEDTLS_KEY_EXCHANGE_PSK, - MBEDTLS_SSL_MAJOR_VERSION_3, MBEDTLS_SSL_MINOR_VERSION_1, - MBEDTLS_SSL_MAJOR_VERSION_3, MBEDTLS_SSL_MINOR_VERSION_3, - 0 }, -#endif /* MBEDTLS_SHA256_C */ + 0, + MBEDTLS_SSL_VERSION_TLS1_2, MBEDTLS_SSL_VERSION_TLS1_2 }, +#endif /* MBEDTLS_MD_CAN_SHA256 */ -#if defined(HAVE_SHA384) +#if defined(MBEDTLS_MD_CAN_SHA384) { MBEDTLS_TLS_PSK_WITH_CAMELLIA_256_CBC_SHA384, "TLS-PSK-WITH-CAMELLIA-256-CBC-SHA384", MBEDTLS_CIPHER_CAMELLIA_256_CBC, MBEDTLS_MD_SHA384, MBEDTLS_KEY_EXCHANGE_PSK, - MBEDTLS_SSL_MAJOR_VERSION_3, MBEDTLS_SSL_MINOR_VERSION_1, - MBEDTLS_SSL_MAJOR_VERSION_3, MBEDTLS_SSL_MINOR_VERSION_3, - 0 }, -#endif /* HAVE_SHA384 */ -#endif /* MBEDTLS_CIPHER_MODE_CBC */ - -#if defined(MBEDTLS_GCM_C) -#if defined(MBEDTLS_SHA256_C) + 0, + MBEDTLS_SSL_VERSION_TLS1_2, MBEDTLS_SSL_VERSION_TLS1_2 }, +#endif /* MBEDTLS_MD_CAN_SHA384 */ +#endif /* MBEDTLS_SSL_HAVE_CBC */ + +#if defined(MBEDTLS_SSL_HAVE_GCM) +#if defined(MBEDTLS_MD_CAN_SHA256) { MBEDTLS_TLS_PSK_WITH_CAMELLIA_128_GCM_SHA256, "TLS-PSK-WITH-CAMELLIA-128-GCM-SHA256", MBEDTLS_CIPHER_CAMELLIA_128_GCM, MBEDTLS_MD_SHA256, MBEDTLS_KEY_EXCHANGE_PSK, - MBEDTLS_SSL_MAJOR_VERSION_3, MBEDTLS_SSL_MINOR_VERSION_3, - MBEDTLS_SSL_MAJOR_VERSION_3, MBEDTLS_SSL_MINOR_VERSION_3, - 0 }, -#endif /* MBEDTLS_SHA256_C */ + 0, + MBEDTLS_SSL_VERSION_TLS1_2, MBEDTLS_SSL_VERSION_TLS1_2 }, +#endif /* MBEDTLS_MD_CAN_SHA256 */ -#if defined(HAVE_SHA384) +#if defined(MBEDTLS_MD_CAN_SHA384) { MBEDTLS_TLS_PSK_WITH_CAMELLIA_256_GCM_SHA384, "TLS-PSK-WITH-CAMELLIA-256-GCM-SHA384", MBEDTLS_CIPHER_CAMELLIA_256_GCM, MBEDTLS_MD_SHA384, MBEDTLS_KEY_EXCHANGE_PSK, - MBEDTLS_SSL_MAJOR_VERSION_3, MBEDTLS_SSL_MINOR_VERSION_3, - MBEDTLS_SSL_MAJOR_VERSION_3, MBEDTLS_SSL_MINOR_VERSION_3, - 0 }, -#endif /* HAVE_SHA384 */ -#endif /* MBEDTLS_GCM_C */ -#endif /* MBEDTLS_CAMELLIA_C */ - -#if defined(MBEDTLS_DES_C) -#if defined(MBEDTLS_CIPHER_MODE_CBC) -#if defined(MBEDTLS_SHA1_C) - { MBEDTLS_TLS_PSK_WITH_3DES_EDE_CBC_SHA, "TLS-PSK-WITH-3DES-EDE-CBC-SHA", - MBEDTLS_CIPHER_DES_EDE3_CBC, MBEDTLS_MD_SHA1, MBEDTLS_KEY_EXCHANGE_PSK, - MBEDTLS_SSL_MAJOR_VERSION_3, MBEDTLS_SSL_MINOR_VERSION_0, - MBEDTLS_SSL_MAJOR_VERSION_3, MBEDTLS_SSL_MINOR_VERSION_3, - 0 }, -#endif /* MBEDTLS_SHA1_C */ -#endif /* MBEDTLS_CIPHER_MODE_CBC */ -#endif /* MBEDTLS_DES_C */ - -#if defined(MBEDTLS_ARC4_C) -#if defined(MBEDTLS_SHA1_C) - { MBEDTLS_TLS_PSK_WITH_RC4_128_SHA, "TLS-PSK-WITH-RC4-128-SHA", - MBEDTLS_CIPHER_ARC4_128, MBEDTLS_MD_SHA1, MBEDTLS_KEY_EXCHANGE_PSK, - MBEDTLS_SSL_MAJOR_VERSION_3, MBEDTLS_SSL_MINOR_VERSION_0, - MBEDTLS_SSL_MAJOR_VERSION_3, MBEDTLS_SSL_MINOR_VERSION_3, - MBEDTLS_CIPHERSUITE_NODTLS }, -#endif /* MBEDTLS_SHA1_C */ -#endif /* MBEDTLS_ARC4_C */ + 0, + MBEDTLS_SSL_VERSION_TLS1_2, MBEDTLS_SSL_VERSION_TLS1_2 }, +#endif /* MBEDTLS_MD_CAN_SHA384 */ +#endif /* MBEDTLS_SSL_HAVE_GCM */ +#endif /* MBEDTLS_SSL_HAVE_CAMELLIA */ + #endif /* MBEDTLS_KEY_EXCHANGE_PSK_ENABLED */ #if defined(MBEDTLS_KEY_EXCHANGE_DHE_PSK_ENABLED) -#if defined(MBEDTLS_AES_C) -#if defined(MBEDTLS_GCM_C) -#if defined(MBEDTLS_SHA256_C) +#if defined(MBEDTLS_SSL_HAVE_AES) +#if defined(MBEDTLS_SSL_HAVE_GCM) +#if defined(MBEDTLS_MD_CAN_SHA256) { MBEDTLS_TLS_DHE_PSK_WITH_AES_128_GCM_SHA256, "TLS-DHE-PSK-WITH-AES-128-GCM-SHA256", MBEDTLS_CIPHER_AES_128_GCM, MBEDTLS_MD_SHA256, MBEDTLS_KEY_EXCHANGE_DHE_PSK, - MBEDTLS_SSL_MAJOR_VERSION_3, MBEDTLS_SSL_MINOR_VERSION_3, - MBEDTLS_SSL_MAJOR_VERSION_3, MBEDTLS_SSL_MINOR_VERSION_3, - 0 }, -#endif /* MBEDTLS_SHA256_C */ + 0, + MBEDTLS_SSL_VERSION_TLS1_2, MBEDTLS_SSL_VERSION_TLS1_2 }, +#endif /* MBEDTLS_MD_CAN_SHA256 */ -#if defined(HAVE_SHA384) +#if defined(MBEDTLS_MD_CAN_SHA384) { MBEDTLS_TLS_DHE_PSK_WITH_AES_256_GCM_SHA384, "TLS-DHE-PSK-WITH-AES-256-GCM-SHA384", MBEDTLS_CIPHER_AES_256_GCM, MBEDTLS_MD_SHA384, MBEDTLS_KEY_EXCHANGE_DHE_PSK, - MBEDTLS_SSL_MAJOR_VERSION_3, MBEDTLS_SSL_MINOR_VERSION_3, - MBEDTLS_SSL_MAJOR_VERSION_3, MBEDTLS_SSL_MINOR_VERSION_3, - 0 }, -#endif /* HAVE_SHA384 */ -#endif /* MBEDTLS_GCM_C */ - -#if defined(MBEDTLS_CIPHER_MODE_CBC) -#if defined(MBEDTLS_SHA256_C) + 0, + MBEDTLS_SSL_VERSION_TLS1_2, MBEDTLS_SSL_VERSION_TLS1_2 }, +#endif /* MBEDTLS_MD_CAN_SHA384 */ +#endif /* MBEDTLS_SSL_HAVE_GCM */ + +#if defined(MBEDTLS_SSL_HAVE_CBC) +#if defined(MBEDTLS_MD_CAN_SHA256) { MBEDTLS_TLS_DHE_PSK_WITH_AES_128_CBC_SHA256, "TLS-DHE-PSK-WITH-AES-128-CBC-SHA256", MBEDTLS_CIPHER_AES_128_CBC, MBEDTLS_MD_SHA256, MBEDTLS_KEY_EXCHANGE_DHE_PSK, - MBEDTLS_SSL_MAJOR_VERSION_3, MBEDTLS_SSL_MINOR_VERSION_1, - MBEDTLS_SSL_MAJOR_VERSION_3, MBEDTLS_SSL_MINOR_VERSION_3, - 0 }, -#endif /* MBEDTLS_SHA256_C */ + 0, + MBEDTLS_SSL_VERSION_TLS1_2, MBEDTLS_SSL_VERSION_TLS1_2 }, +#endif /* MBEDTLS_MD_CAN_SHA256 */ -#if defined(HAVE_SHA384) +#if defined(MBEDTLS_MD_CAN_SHA384) { MBEDTLS_TLS_DHE_PSK_WITH_AES_256_CBC_SHA384, "TLS-DHE-PSK-WITH-AES-256-CBC-SHA384", MBEDTLS_CIPHER_AES_256_CBC, MBEDTLS_MD_SHA384, MBEDTLS_KEY_EXCHANGE_DHE_PSK, - MBEDTLS_SSL_MAJOR_VERSION_3, MBEDTLS_SSL_MINOR_VERSION_1, - MBEDTLS_SSL_MAJOR_VERSION_3, MBEDTLS_SSL_MINOR_VERSION_3, - 0 }, -#endif /* HAVE_SHA384 */ + 0, + MBEDTLS_SSL_VERSION_TLS1_2, MBEDTLS_SSL_VERSION_TLS1_2 }, +#endif /* MBEDTLS_MD_CAN_SHA384 */ -#if defined(MBEDTLS_SHA1_C) +#if defined(MBEDTLS_MD_CAN_SHA1) { MBEDTLS_TLS_DHE_PSK_WITH_AES_128_CBC_SHA, "TLS-DHE-PSK-WITH-AES-128-CBC-SHA", MBEDTLS_CIPHER_AES_128_CBC, MBEDTLS_MD_SHA1, MBEDTLS_KEY_EXCHANGE_DHE_PSK, - MBEDTLS_SSL_MAJOR_VERSION_3, MBEDTLS_SSL_MINOR_VERSION_0, - MBEDTLS_SSL_MAJOR_VERSION_3, MBEDTLS_SSL_MINOR_VERSION_3, - 0 }, + 0, + MBEDTLS_SSL_VERSION_TLS1_2, MBEDTLS_SSL_VERSION_TLS1_2 }, { MBEDTLS_TLS_DHE_PSK_WITH_AES_256_CBC_SHA, "TLS-DHE-PSK-WITH-AES-256-CBC-SHA", MBEDTLS_CIPHER_AES_256_CBC, MBEDTLS_MD_SHA1, MBEDTLS_KEY_EXCHANGE_DHE_PSK, - MBEDTLS_SSL_MAJOR_VERSION_3, MBEDTLS_SSL_MINOR_VERSION_0, - MBEDTLS_SSL_MAJOR_VERSION_3, MBEDTLS_SSL_MINOR_VERSION_3, - 0 }, -#endif /* MBEDTLS_SHA1_C */ -#endif /* MBEDTLS_CIPHER_MODE_CBC */ -#if defined(MBEDTLS_CCM_C) + 0, + MBEDTLS_SSL_VERSION_TLS1_2, MBEDTLS_SSL_VERSION_TLS1_2 }, +#endif /* MBEDTLS_MD_CAN_SHA1 */ +#endif /* MBEDTLS_SSL_HAVE_CBC */ +#if defined(MBEDTLS_SSL_HAVE_CCM) { MBEDTLS_TLS_DHE_PSK_WITH_AES_256_CCM, "TLS-DHE-PSK-WITH-AES-256-CCM", MBEDTLS_CIPHER_AES_256_CCM, MBEDTLS_MD_SHA256, MBEDTLS_KEY_EXCHANGE_DHE_PSK, - MBEDTLS_SSL_MAJOR_VERSION_3, MBEDTLS_SSL_MINOR_VERSION_3, - MBEDTLS_SSL_MAJOR_VERSION_3, MBEDTLS_SSL_MINOR_VERSION_3, - 0 }, + 0, + MBEDTLS_SSL_VERSION_TLS1_2, MBEDTLS_SSL_VERSION_TLS1_2 }, { MBEDTLS_TLS_DHE_PSK_WITH_AES_256_CCM_8, "TLS-DHE-PSK-WITH-AES-256-CCM-8", MBEDTLS_CIPHER_AES_256_CCM, MBEDTLS_MD_SHA256, MBEDTLS_KEY_EXCHANGE_DHE_PSK, - MBEDTLS_SSL_MAJOR_VERSION_3, MBEDTLS_SSL_MINOR_VERSION_3, - MBEDTLS_SSL_MAJOR_VERSION_3, MBEDTLS_SSL_MINOR_VERSION_3, - MBEDTLS_CIPHERSUITE_SHORT_TAG }, + MBEDTLS_CIPHERSUITE_SHORT_TAG, + MBEDTLS_SSL_VERSION_TLS1_2, MBEDTLS_SSL_VERSION_TLS1_2 }, { MBEDTLS_TLS_DHE_PSK_WITH_AES_128_CCM, "TLS-DHE-PSK-WITH-AES-128-CCM", MBEDTLS_CIPHER_AES_128_CCM, MBEDTLS_MD_SHA256, MBEDTLS_KEY_EXCHANGE_DHE_PSK, - MBEDTLS_SSL_MAJOR_VERSION_3, MBEDTLS_SSL_MINOR_VERSION_3, - MBEDTLS_SSL_MAJOR_VERSION_3, MBEDTLS_SSL_MINOR_VERSION_3, - 0 }, + 0, + MBEDTLS_SSL_VERSION_TLS1_2, MBEDTLS_SSL_VERSION_TLS1_2 }, { MBEDTLS_TLS_DHE_PSK_WITH_AES_128_CCM_8, "TLS-DHE-PSK-WITH-AES-128-CCM-8", MBEDTLS_CIPHER_AES_128_CCM, MBEDTLS_MD_SHA256, MBEDTLS_KEY_EXCHANGE_DHE_PSK, - MBEDTLS_SSL_MAJOR_VERSION_3, MBEDTLS_SSL_MINOR_VERSION_3, - MBEDTLS_SSL_MAJOR_VERSION_3, MBEDTLS_SSL_MINOR_VERSION_3, - MBEDTLS_CIPHERSUITE_SHORT_TAG }, -#endif /* MBEDTLS_CCM_C */ -#endif /* MBEDTLS_AES_C */ - -#if defined(MBEDTLS_CAMELLIA_C) -#if defined(MBEDTLS_CIPHER_MODE_CBC) -#if defined(MBEDTLS_SHA256_C) + MBEDTLS_CIPHERSUITE_SHORT_TAG, + MBEDTLS_SSL_VERSION_TLS1_2, MBEDTLS_SSL_VERSION_TLS1_2 }, +#endif /* MBEDTLS_SSL_HAVE_CCM */ +#endif /* MBEDTLS_SSL_HAVE_AES */ + +#if defined(MBEDTLS_SSL_HAVE_CAMELLIA) +#if defined(MBEDTLS_SSL_HAVE_CBC) +#if defined(MBEDTLS_MD_CAN_SHA256) { MBEDTLS_TLS_DHE_PSK_WITH_CAMELLIA_128_CBC_SHA256, "TLS-DHE-PSK-WITH-CAMELLIA-128-CBC-SHA256", MBEDTLS_CIPHER_CAMELLIA_128_CBC, MBEDTLS_MD_SHA256, MBEDTLS_KEY_EXCHANGE_DHE_PSK, - MBEDTLS_SSL_MAJOR_VERSION_3, MBEDTLS_SSL_MINOR_VERSION_1, - MBEDTLS_SSL_MAJOR_VERSION_3, MBEDTLS_SSL_MINOR_VERSION_3, - 0 }, -#endif /* MBEDTLS_SHA256_C */ + 0, + MBEDTLS_SSL_VERSION_TLS1_2, MBEDTLS_SSL_VERSION_TLS1_2 }, +#endif /* MBEDTLS_MD_CAN_SHA256 */ -#if defined(HAVE_SHA384) +#if defined(MBEDTLS_MD_CAN_SHA384) { MBEDTLS_TLS_DHE_PSK_WITH_CAMELLIA_256_CBC_SHA384, "TLS-DHE-PSK-WITH-CAMELLIA-256-CBC-SHA384", MBEDTLS_CIPHER_CAMELLIA_256_CBC, MBEDTLS_MD_SHA384, MBEDTLS_KEY_EXCHANGE_DHE_PSK, - MBEDTLS_SSL_MAJOR_VERSION_3, MBEDTLS_SSL_MINOR_VERSION_1, - MBEDTLS_SSL_MAJOR_VERSION_3, MBEDTLS_SSL_MINOR_VERSION_3, - 0 }, -#endif /* HAVE_SHA384 */ -#endif /* MBEDTLS_CIPHER_MODE_CBC */ - -#if defined(MBEDTLS_GCM_C) -#if defined(MBEDTLS_SHA256_C) + 0, + MBEDTLS_SSL_VERSION_TLS1_2, MBEDTLS_SSL_VERSION_TLS1_2 }, +#endif /* MBEDTLS_MD_CAN_SHA384 */ +#endif /* MBEDTLS_SSL_HAVE_CBC */ + +#if defined(MBEDTLS_SSL_HAVE_GCM) +#if defined(MBEDTLS_MD_CAN_SHA256) { MBEDTLS_TLS_DHE_PSK_WITH_CAMELLIA_128_GCM_SHA256, "TLS-DHE-PSK-WITH-CAMELLIA-128-GCM-SHA256", MBEDTLS_CIPHER_CAMELLIA_128_GCM, MBEDTLS_MD_SHA256, MBEDTLS_KEY_EXCHANGE_DHE_PSK, - MBEDTLS_SSL_MAJOR_VERSION_3, MBEDTLS_SSL_MINOR_VERSION_3, - MBEDTLS_SSL_MAJOR_VERSION_3, MBEDTLS_SSL_MINOR_VERSION_3, - 0 }, -#endif /* MBEDTLS_SHA256_C */ + 0, + MBEDTLS_SSL_VERSION_TLS1_2, MBEDTLS_SSL_VERSION_TLS1_2 }, +#endif /* MBEDTLS_MD_CAN_SHA256 */ -#if defined(HAVE_SHA384) +#if defined(MBEDTLS_MD_CAN_SHA384) { MBEDTLS_TLS_DHE_PSK_WITH_CAMELLIA_256_GCM_SHA384, "TLS-DHE-PSK-WITH-CAMELLIA-256-GCM-SHA384", MBEDTLS_CIPHER_CAMELLIA_256_GCM, MBEDTLS_MD_SHA384, MBEDTLS_KEY_EXCHANGE_DHE_PSK, - MBEDTLS_SSL_MAJOR_VERSION_3, MBEDTLS_SSL_MINOR_VERSION_3, - MBEDTLS_SSL_MAJOR_VERSION_3, MBEDTLS_SSL_MINOR_VERSION_3, - 0 }, -#endif /* HAVE_SHA384 */ -#endif /* MBEDTLS_GCM_C */ -#endif /* MBEDTLS_CAMELLIA_C */ - -#if defined(MBEDTLS_DES_C) -#if defined(MBEDTLS_CIPHER_MODE_CBC) -#if defined(MBEDTLS_SHA1_C) - { MBEDTLS_TLS_DHE_PSK_WITH_3DES_EDE_CBC_SHA, "TLS-DHE-PSK-WITH-3DES-EDE-CBC-SHA", - MBEDTLS_CIPHER_DES_EDE3_CBC, MBEDTLS_MD_SHA1, MBEDTLS_KEY_EXCHANGE_DHE_PSK, - MBEDTLS_SSL_MAJOR_VERSION_3, MBEDTLS_SSL_MINOR_VERSION_0, - MBEDTLS_SSL_MAJOR_VERSION_3, MBEDTLS_SSL_MINOR_VERSION_3, - 0 }, -#endif /* MBEDTLS_SHA1_C */ -#endif /* MBEDTLS_CIPHER_MODE_CBC */ -#endif /* MBEDTLS_DES_C */ - -#if defined(MBEDTLS_ARC4_C) -#if defined(MBEDTLS_SHA1_C) - { MBEDTLS_TLS_DHE_PSK_WITH_RC4_128_SHA, "TLS-DHE-PSK-WITH-RC4-128-SHA", - MBEDTLS_CIPHER_ARC4_128, MBEDTLS_MD_SHA1, MBEDTLS_KEY_EXCHANGE_DHE_PSK, - MBEDTLS_SSL_MAJOR_VERSION_3, MBEDTLS_SSL_MINOR_VERSION_0, - MBEDTLS_SSL_MAJOR_VERSION_3, MBEDTLS_SSL_MINOR_VERSION_3, - MBEDTLS_CIPHERSUITE_NODTLS }, -#endif /* MBEDTLS_SHA1_C */ -#endif /* MBEDTLS_ARC4_C */ + 0, + MBEDTLS_SSL_VERSION_TLS1_2, MBEDTLS_SSL_VERSION_TLS1_2 }, +#endif /* MBEDTLS_MD_CAN_SHA384 */ +#endif /* MBEDTLS_SSL_HAVE_GCM */ +#endif /* MBEDTLS_SSL_HAVE_CAMELLIA */ + #endif /* MBEDTLS_KEY_EXCHANGE_DHE_PSK_ENABLED */ #if defined(MBEDTLS_KEY_EXCHANGE_ECDHE_PSK_ENABLED) -#if defined(MBEDTLS_AES_C) +#if defined(MBEDTLS_SSL_HAVE_AES) -#if defined(MBEDTLS_CIPHER_MODE_CBC) -#if defined(MBEDTLS_SHA256_C) +#if defined(MBEDTLS_SSL_HAVE_CBC) +#if defined(MBEDTLS_MD_CAN_SHA256) { MBEDTLS_TLS_ECDHE_PSK_WITH_AES_128_CBC_SHA256, "TLS-ECDHE-PSK-WITH-AES-128-CBC-SHA256", MBEDTLS_CIPHER_AES_128_CBC, MBEDTLS_MD_SHA256, MBEDTLS_KEY_EXCHANGE_ECDHE_PSK, - MBEDTLS_SSL_MAJOR_VERSION_3, MBEDTLS_SSL_MINOR_VERSION_1, - MBEDTLS_SSL_MAJOR_VERSION_3, MBEDTLS_SSL_MINOR_VERSION_3, - 0 }, -#endif /* MBEDTLS_SHA256_C */ + 0, + MBEDTLS_SSL_VERSION_TLS1_2, MBEDTLS_SSL_VERSION_TLS1_2 }, +#endif /* MBEDTLS_MD_CAN_SHA256 */ -#if defined(HAVE_SHA384) +#if defined(MBEDTLS_MD_CAN_SHA384) { MBEDTLS_TLS_ECDHE_PSK_WITH_AES_256_CBC_SHA384, "TLS-ECDHE-PSK-WITH-AES-256-CBC-SHA384", MBEDTLS_CIPHER_AES_256_CBC, MBEDTLS_MD_SHA384, MBEDTLS_KEY_EXCHANGE_ECDHE_PSK, - MBEDTLS_SSL_MAJOR_VERSION_3, MBEDTLS_SSL_MINOR_VERSION_1, - MBEDTLS_SSL_MAJOR_VERSION_3, MBEDTLS_SSL_MINOR_VERSION_3, - 0 }, -#endif /* HAVE_SHA384 */ + 0, + MBEDTLS_SSL_VERSION_TLS1_2, MBEDTLS_SSL_VERSION_TLS1_2 }, +#endif /* MBEDTLS_MD_CAN_SHA384 */ -#if defined(MBEDTLS_SHA1_C) +#if defined(MBEDTLS_MD_CAN_SHA1) { MBEDTLS_TLS_ECDHE_PSK_WITH_AES_128_CBC_SHA, "TLS-ECDHE-PSK-WITH-AES-128-CBC-SHA", MBEDTLS_CIPHER_AES_128_CBC, MBEDTLS_MD_SHA1, MBEDTLS_KEY_EXCHANGE_ECDHE_PSK, - MBEDTLS_SSL_MAJOR_VERSION_3, MBEDTLS_SSL_MINOR_VERSION_1, - MBEDTLS_SSL_MAJOR_VERSION_3, MBEDTLS_SSL_MINOR_VERSION_3, - 0 }, + 0, + MBEDTLS_SSL_VERSION_TLS1_2, MBEDTLS_SSL_VERSION_TLS1_2 }, { MBEDTLS_TLS_ECDHE_PSK_WITH_AES_256_CBC_SHA, "TLS-ECDHE-PSK-WITH-AES-256-CBC-SHA", MBEDTLS_CIPHER_AES_256_CBC, MBEDTLS_MD_SHA1, MBEDTLS_KEY_EXCHANGE_ECDHE_PSK, - MBEDTLS_SSL_MAJOR_VERSION_3, MBEDTLS_SSL_MINOR_VERSION_1, - MBEDTLS_SSL_MAJOR_VERSION_3, MBEDTLS_SSL_MINOR_VERSION_3, - 0 }, -#endif /* MBEDTLS_SHA1_C */ -#endif /* MBEDTLS_CIPHER_MODE_CBC */ -#endif /* MBEDTLS_AES_C */ - -#if defined(MBEDTLS_CAMELLIA_C) -#if defined(MBEDTLS_CIPHER_MODE_CBC) -#if defined(MBEDTLS_SHA256_C) + 0, + MBEDTLS_SSL_VERSION_TLS1_2, MBEDTLS_SSL_VERSION_TLS1_2 }, +#endif /* MBEDTLS_MD_CAN_SHA1 */ +#endif /* MBEDTLS_SSL_HAVE_CBC */ +#endif /* MBEDTLS_SSL_HAVE_AES */ + +#if defined(MBEDTLS_SSL_HAVE_CAMELLIA) +#if defined(MBEDTLS_SSL_HAVE_CBC) +#if defined(MBEDTLS_MD_CAN_SHA256) { MBEDTLS_TLS_ECDHE_PSK_WITH_CAMELLIA_128_CBC_SHA256, "TLS-ECDHE-PSK-WITH-CAMELLIA-128-CBC-SHA256", MBEDTLS_CIPHER_CAMELLIA_128_CBC, MBEDTLS_MD_SHA256, MBEDTLS_KEY_EXCHANGE_ECDHE_PSK, - MBEDTLS_SSL_MAJOR_VERSION_3, MBEDTLS_SSL_MINOR_VERSION_1, - MBEDTLS_SSL_MAJOR_VERSION_3, MBEDTLS_SSL_MINOR_VERSION_3, - 0 }, -#endif /* MBEDTLS_SHA256_C */ + 0, + MBEDTLS_SSL_VERSION_TLS1_2, MBEDTLS_SSL_VERSION_TLS1_2 }, +#endif /* MBEDTLS_MD_CAN_SHA256 */ -#if defined(HAVE_SHA384) +#if defined(MBEDTLS_MD_CAN_SHA384) { MBEDTLS_TLS_ECDHE_PSK_WITH_CAMELLIA_256_CBC_SHA384, "TLS-ECDHE-PSK-WITH-CAMELLIA-256-CBC-SHA384", MBEDTLS_CIPHER_CAMELLIA_256_CBC, MBEDTLS_MD_SHA384, MBEDTLS_KEY_EXCHANGE_ECDHE_PSK, - MBEDTLS_SSL_MAJOR_VERSION_3, MBEDTLS_SSL_MINOR_VERSION_1, - MBEDTLS_SSL_MAJOR_VERSION_3, MBEDTLS_SSL_MINOR_VERSION_3, - 0 }, -#endif /* HAVE_SHA384 */ -#endif /* MBEDTLS_CIPHER_MODE_CBC */ -#endif /* MBEDTLS_CAMELLIA_C */ - -#if defined(MBEDTLS_DES_C) -#if defined(MBEDTLS_CIPHER_MODE_CBC) -#if defined(MBEDTLS_SHA1_C) - { MBEDTLS_TLS_ECDHE_PSK_WITH_3DES_EDE_CBC_SHA, "TLS-ECDHE-PSK-WITH-3DES-EDE-CBC-SHA", - MBEDTLS_CIPHER_DES_EDE3_CBC, MBEDTLS_MD_SHA1, MBEDTLS_KEY_EXCHANGE_ECDHE_PSK, - MBEDTLS_SSL_MAJOR_VERSION_3, MBEDTLS_SSL_MINOR_VERSION_1, - MBEDTLS_SSL_MAJOR_VERSION_3, MBEDTLS_SSL_MINOR_VERSION_3, - 0 }, -#endif /* MBEDTLS_SHA1_C */ -#endif /* MBEDTLS_CIPHER_MODE_CBC */ -#endif /* MBEDTLS_DES_C */ - -#if defined(MBEDTLS_ARC4_C) -#if defined(MBEDTLS_SHA1_C) - { MBEDTLS_TLS_ECDHE_PSK_WITH_RC4_128_SHA, "TLS-ECDHE-PSK-WITH-RC4-128-SHA", - MBEDTLS_CIPHER_ARC4_128, MBEDTLS_MD_SHA1, MBEDTLS_KEY_EXCHANGE_ECDHE_PSK, - MBEDTLS_SSL_MAJOR_VERSION_3, MBEDTLS_SSL_MINOR_VERSION_1, - MBEDTLS_SSL_MAJOR_VERSION_3, MBEDTLS_SSL_MINOR_VERSION_3, - MBEDTLS_CIPHERSUITE_NODTLS }, -#endif /* MBEDTLS_SHA1_C */ -#endif /* MBEDTLS_ARC4_C */ + 0, + MBEDTLS_SSL_VERSION_TLS1_2, MBEDTLS_SSL_VERSION_TLS1_2 }, +#endif /* MBEDTLS_MD_CAN_SHA384 */ +#endif /* MBEDTLS_SSL_HAVE_CBC */ +#endif /* MBEDTLS_SSL_HAVE_CAMELLIA */ + #endif /* MBEDTLS_KEY_EXCHANGE_ECDHE_PSK_ENABLED */ #if defined(MBEDTLS_KEY_EXCHANGE_RSA_PSK_ENABLED) -#if defined(MBEDTLS_AES_C) -#if defined(MBEDTLS_GCM_C) -#if defined(MBEDTLS_SHA256_C) +#if defined(MBEDTLS_SSL_HAVE_AES) +#if defined(MBEDTLS_SSL_HAVE_GCM) +#if defined(MBEDTLS_MD_CAN_SHA256) { MBEDTLS_TLS_RSA_PSK_WITH_AES_128_GCM_SHA256, "TLS-RSA-PSK-WITH-AES-128-GCM-SHA256", MBEDTLS_CIPHER_AES_128_GCM, MBEDTLS_MD_SHA256, MBEDTLS_KEY_EXCHANGE_RSA_PSK, - MBEDTLS_SSL_MAJOR_VERSION_3, MBEDTLS_SSL_MINOR_VERSION_3, - MBEDTLS_SSL_MAJOR_VERSION_3, MBEDTLS_SSL_MINOR_VERSION_3, - 0 }, -#endif /* MBEDTLS_SHA256_C */ + 0, + MBEDTLS_SSL_VERSION_TLS1_2, MBEDTLS_SSL_VERSION_TLS1_2 }, +#endif /* MBEDTLS_MD_CAN_SHA256 */ -#if defined(HAVE_SHA384) +#if defined(MBEDTLS_MD_CAN_SHA384) { MBEDTLS_TLS_RSA_PSK_WITH_AES_256_GCM_SHA384, "TLS-RSA-PSK-WITH-AES-256-GCM-SHA384", MBEDTLS_CIPHER_AES_256_GCM, MBEDTLS_MD_SHA384, MBEDTLS_KEY_EXCHANGE_RSA_PSK, - MBEDTLS_SSL_MAJOR_VERSION_3, MBEDTLS_SSL_MINOR_VERSION_3, - MBEDTLS_SSL_MAJOR_VERSION_3, MBEDTLS_SSL_MINOR_VERSION_3, - 0 }, -#endif /* HAVE_SHA384 */ -#endif /* MBEDTLS_GCM_C */ - -#if defined(MBEDTLS_CIPHER_MODE_CBC) -#if defined(MBEDTLS_SHA256_C) + 0, + MBEDTLS_SSL_VERSION_TLS1_2, MBEDTLS_SSL_VERSION_TLS1_2 }, +#endif /* MBEDTLS_MD_CAN_SHA384 */ +#endif /* MBEDTLS_SSL_HAVE_GCM */ + +#if defined(MBEDTLS_SSL_HAVE_CBC) +#if defined(MBEDTLS_MD_CAN_SHA256) { MBEDTLS_TLS_RSA_PSK_WITH_AES_128_CBC_SHA256, "TLS-RSA-PSK-WITH-AES-128-CBC-SHA256", MBEDTLS_CIPHER_AES_128_CBC, MBEDTLS_MD_SHA256, MBEDTLS_KEY_EXCHANGE_RSA_PSK, - MBEDTLS_SSL_MAJOR_VERSION_3, MBEDTLS_SSL_MINOR_VERSION_1, - MBEDTLS_SSL_MAJOR_VERSION_3, MBEDTLS_SSL_MINOR_VERSION_3, - 0 }, -#endif /* MBEDTLS_SHA256_C */ + 0, + MBEDTLS_SSL_VERSION_TLS1_2, MBEDTLS_SSL_VERSION_TLS1_2 }, +#endif /* MBEDTLS_MD_CAN_SHA256 */ -#if defined(HAVE_SHA384) +#if defined(MBEDTLS_MD_CAN_SHA384) { MBEDTLS_TLS_RSA_PSK_WITH_AES_256_CBC_SHA384, "TLS-RSA-PSK-WITH-AES-256-CBC-SHA384", MBEDTLS_CIPHER_AES_256_CBC, MBEDTLS_MD_SHA384, MBEDTLS_KEY_EXCHANGE_RSA_PSK, - MBEDTLS_SSL_MAJOR_VERSION_3, MBEDTLS_SSL_MINOR_VERSION_1, - MBEDTLS_SSL_MAJOR_VERSION_3, MBEDTLS_SSL_MINOR_VERSION_3, - 0 }, -#endif /* HAVE_SHA384 */ + 0, + MBEDTLS_SSL_VERSION_TLS1_2, MBEDTLS_SSL_VERSION_TLS1_2 }, +#endif /* MBEDTLS_MD_CAN_SHA384 */ -#if defined(MBEDTLS_SHA1_C) +#if defined(MBEDTLS_MD_CAN_SHA1) { MBEDTLS_TLS_RSA_PSK_WITH_AES_128_CBC_SHA, "TLS-RSA-PSK-WITH-AES-128-CBC-SHA", MBEDTLS_CIPHER_AES_128_CBC, MBEDTLS_MD_SHA1, MBEDTLS_KEY_EXCHANGE_RSA_PSK, - MBEDTLS_SSL_MAJOR_VERSION_3, MBEDTLS_SSL_MINOR_VERSION_1, - MBEDTLS_SSL_MAJOR_VERSION_3, MBEDTLS_SSL_MINOR_VERSION_3, - 0 }, + 0, + MBEDTLS_SSL_VERSION_TLS1_2, MBEDTLS_SSL_VERSION_TLS1_2 }, { MBEDTLS_TLS_RSA_PSK_WITH_AES_256_CBC_SHA, "TLS-RSA-PSK-WITH-AES-256-CBC-SHA", MBEDTLS_CIPHER_AES_256_CBC, MBEDTLS_MD_SHA1, MBEDTLS_KEY_EXCHANGE_RSA_PSK, - MBEDTLS_SSL_MAJOR_VERSION_3, MBEDTLS_SSL_MINOR_VERSION_1, - MBEDTLS_SSL_MAJOR_VERSION_3, MBEDTLS_SSL_MINOR_VERSION_3, - 0 }, -#endif /* MBEDTLS_SHA1_C */ -#endif /* MBEDTLS_CIPHER_MODE_CBC */ -#endif /* MBEDTLS_AES_C */ - -#if defined(MBEDTLS_CAMELLIA_C) -#if defined(MBEDTLS_CIPHER_MODE_CBC) -#if defined(MBEDTLS_SHA256_C) + 0, + MBEDTLS_SSL_VERSION_TLS1_2, MBEDTLS_SSL_VERSION_TLS1_2 }, +#endif /* MBEDTLS_MD_CAN_SHA1 */ +#endif /* MBEDTLS_SSL_HAVE_CBC */ +#endif /* MBEDTLS_SSL_HAVE_AES */ + +#if defined(MBEDTLS_SSL_HAVE_CAMELLIA) +#if defined(MBEDTLS_SSL_HAVE_CBC) +#if defined(MBEDTLS_MD_CAN_SHA256) { MBEDTLS_TLS_RSA_PSK_WITH_CAMELLIA_128_CBC_SHA256, "TLS-RSA-PSK-WITH-CAMELLIA-128-CBC-SHA256", MBEDTLS_CIPHER_CAMELLIA_128_CBC, MBEDTLS_MD_SHA256, MBEDTLS_KEY_EXCHANGE_RSA_PSK, - MBEDTLS_SSL_MAJOR_VERSION_3, MBEDTLS_SSL_MINOR_VERSION_1, - MBEDTLS_SSL_MAJOR_VERSION_3, MBEDTLS_SSL_MINOR_VERSION_3, - 0 }, -#endif /* MBEDTLS_SHA256_C */ + 0, + MBEDTLS_SSL_VERSION_TLS1_2, MBEDTLS_SSL_VERSION_TLS1_2 }, +#endif /* MBEDTLS_MD_CAN_SHA256 */ -#if defined(HAVE_SHA384) +#if defined(MBEDTLS_MD_CAN_SHA384) { MBEDTLS_TLS_RSA_PSK_WITH_CAMELLIA_256_CBC_SHA384, "TLS-RSA-PSK-WITH-CAMELLIA-256-CBC-SHA384", MBEDTLS_CIPHER_CAMELLIA_256_CBC, MBEDTLS_MD_SHA384, MBEDTLS_KEY_EXCHANGE_RSA_PSK, - MBEDTLS_SSL_MAJOR_VERSION_3, MBEDTLS_SSL_MINOR_VERSION_1, - MBEDTLS_SSL_MAJOR_VERSION_3, MBEDTLS_SSL_MINOR_VERSION_3, - 0 }, -#endif /* HAVE_SHA384 */ -#endif /* MBEDTLS_CIPHER_MODE_CBC */ - -#if defined(MBEDTLS_GCM_C) -#if defined(MBEDTLS_SHA256_C) + 0, + MBEDTLS_SSL_VERSION_TLS1_2, MBEDTLS_SSL_VERSION_TLS1_2 }, +#endif /* MBEDTLS_MD_CAN_SHA384 */ +#endif /* MBEDTLS_SSL_HAVE_CBC */ + +#if defined(MBEDTLS_SSL_HAVE_GCM) +#if defined(MBEDTLS_MD_CAN_SHA256) { MBEDTLS_TLS_RSA_PSK_WITH_CAMELLIA_128_GCM_SHA256, "TLS-RSA-PSK-WITH-CAMELLIA-128-GCM-SHA256", MBEDTLS_CIPHER_CAMELLIA_128_GCM, MBEDTLS_MD_SHA256, MBEDTLS_KEY_EXCHANGE_RSA_PSK, - MBEDTLS_SSL_MAJOR_VERSION_3, MBEDTLS_SSL_MINOR_VERSION_3, - MBEDTLS_SSL_MAJOR_VERSION_3, MBEDTLS_SSL_MINOR_VERSION_3, - 0 }, -#endif /* MBEDTLS_SHA256_C */ + 0, + MBEDTLS_SSL_VERSION_TLS1_2, MBEDTLS_SSL_VERSION_TLS1_2 }, +#endif /* MBEDTLS_MD_CAN_SHA256 */ -#if defined(HAVE_SHA384) +#if defined(MBEDTLS_MD_CAN_SHA384) { MBEDTLS_TLS_RSA_PSK_WITH_CAMELLIA_256_GCM_SHA384, "TLS-RSA-PSK-WITH-CAMELLIA-256-GCM-SHA384", MBEDTLS_CIPHER_CAMELLIA_256_GCM, MBEDTLS_MD_SHA384, MBEDTLS_KEY_EXCHANGE_RSA_PSK, - MBEDTLS_SSL_MAJOR_VERSION_3, MBEDTLS_SSL_MINOR_VERSION_3, - MBEDTLS_SSL_MAJOR_VERSION_3, MBEDTLS_SSL_MINOR_VERSION_3, - 0 }, -#endif /* HAVE_SHA384 */ -#endif /* MBEDTLS_GCM_C */ -#endif /* MBEDTLS_CAMELLIA_C */ - -#if defined(MBEDTLS_DES_C) -#if defined(MBEDTLS_CIPHER_MODE_CBC) -#if defined(MBEDTLS_SHA1_C) - { MBEDTLS_TLS_RSA_PSK_WITH_3DES_EDE_CBC_SHA, "TLS-RSA-PSK-WITH-3DES-EDE-CBC-SHA", - MBEDTLS_CIPHER_DES_EDE3_CBC, MBEDTLS_MD_SHA1, MBEDTLS_KEY_EXCHANGE_RSA_PSK, - MBEDTLS_SSL_MAJOR_VERSION_3, MBEDTLS_SSL_MINOR_VERSION_1, - MBEDTLS_SSL_MAJOR_VERSION_3, MBEDTLS_SSL_MINOR_VERSION_3, - 0 }, -#endif /* MBEDTLS_SHA1_C */ -#endif /* MBEDTLS_CIPHER_MODE_CBC */ -#endif /* MBEDTLS_DES_C */ - -#if defined(MBEDTLS_ARC4_C) -#if defined(MBEDTLS_SHA1_C) - { MBEDTLS_TLS_RSA_PSK_WITH_RC4_128_SHA, "TLS-RSA-PSK-WITH-RC4-128-SHA", - MBEDTLS_CIPHER_ARC4_128, MBEDTLS_MD_SHA1, MBEDTLS_KEY_EXCHANGE_RSA_PSK, - MBEDTLS_SSL_MAJOR_VERSION_3, MBEDTLS_SSL_MINOR_VERSION_1, - MBEDTLS_SSL_MAJOR_VERSION_3, MBEDTLS_SSL_MINOR_VERSION_3, - MBEDTLS_CIPHERSUITE_NODTLS }, -#endif /* MBEDTLS_SHA1_C */ -#endif /* MBEDTLS_ARC4_C */ + 0, + MBEDTLS_SSL_VERSION_TLS1_2, MBEDTLS_SSL_VERSION_TLS1_2 }, +#endif /* MBEDTLS_MD_CAN_SHA384 */ +#endif /* MBEDTLS_SSL_HAVE_GCM */ +#endif /* MBEDTLS_SSL_HAVE_CAMELLIA */ + #endif /* MBEDTLS_KEY_EXCHANGE_RSA_PSK_ENABLED */ #if defined(MBEDTLS_KEY_EXCHANGE_ECJPAKE_ENABLED) -#if defined(MBEDTLS_AES_C) -#if defined(MBEDTLS_CCM_C) +#if defined(MBEDTLS_SSL_HAVE_AES) +#if defined(MBEDTLS_SSL_HAVE_CCM) { MBEDTLS_TLS_ECJPAKE_WITH_AES_128_CCM_8, "TLS-ECJPAKE-WITH-AES-128-CCM-8", MBEDTLS_CIPHER_AES_128_CCM, MBEDTLS_MD_SHA256, MBEDTLS_KEY_EXCHANGE_ECJPAKE, - MBEDTLS_SSL_MAJOR_VERSION_3, MBEDTLS_SSL_MINOR_VERSION_3, - MBEDTLS_SSL_MAJOR_VERSION_3, MBEDTLS_SSL_MINOR_VERSION_3, - MBEDTLS_CIPHERSUITE_SHORT_TAG }, -#endif /* MBEDTLS_CCM_C */ -#endif /* MBEDTLS_AES_C */ + MBEDTLS_CIPHERSUITE_SHORT_TAG, + MBEDTLS_SSL_VERSION_TLS1_2, MBEDTLS_SSL_VERSION_TLS1_2 }, +#endif /* MBEDTLS_SSL_HAVE_CCM */ +#endif /* MBEDTLS_SSL_HAVE_AES */ #endif /* MBEDTLS_KEY_EXCHANGE_ECJPAKE_ENABLED */ -#if defined(MBEDTLS_ENABLE_WEAK_CIPHERSUITES) #if defined(MBEDTLS_CIPHER_NULL_CIPHER) #if defined(MBEDTLS_KEY_EXCHANGE_RSA_ENABLED) -#if defined(MBEDTLS_MD5_C) +#if defined(MBEDTLS_MD_CAN_MD5) { MBEDTLS_TLS_RSA_WITH_NULL_MD5, "TLS-RSA-WITH-NULL-MD5", MBEDTLS_CIPHER_NULL, MBEDTLS_MD_MD5, MBEDTLS_KEY_EXCHANGE_RSA, - MBEDTLS_SSL_MAJOR_VERSION_3, MBEDTLS_SSL_MINOR_VERSION_0, - MBEDTLS_SSL_MAJOR_VERSION_3, MBEDTLS_SSL_MINOR_VERSION_3, - MBEDTLS_CIPHERSUITE_WEAK }, + MBEDTLS_CIPHERSUITE_WEAK, + MBEDTLS_SSL_VERSION_TLS1_2, MBEDTLS_SSL_VERSION_TLS1_2 }, #endif -#if defined(MBEDTLS_SHA1_C) +#if defined(MBEDTLS_MD_CAN_SHA1) { MBEDTLS_TLS_RSA_WITH_NULL_SHA, "TLS-RSA-WITH-NULL-SHA", MBEDTLS_CIPHER_NULL, MBEDTLS_MD_SHA1, MBEDTLS_KEY_EXCHANGE_RSA, - MBEDTLS_SSL_MAJOR_VERSION_3, MBEDTLS_SSL_MINOR_VERSION_0, - MBEDTLS_SSL_MAJOR_VERSION_3, MBEDTLS_SSL_MINOR_VERSION_3, - MBEDTLS_CIPHERSUITE_WEAK }, + MBEDTLS_CIPHERSUITE_WEAK, + MBEDTLS_SSL_VERSION_TLS1_2, MBEDTLS_SSL_VERSION_TLS1_2 }, #endif -#if defined(MBEDTLS_SHA256_C) +#if defined(MBEDTLS_MD_CAN_SHA256) { MBEDTLS_TLS_RSA_WITH_NULL_SHA256, "TLS-RSA-WITH-NULL-SHA256", MBEDTLS_CIPHER_NULL, MBEDTLS_MD_SHA256, MBEDTLS_KEY_EXCHANGE_RSA, - MBEDTLS_SSL_MAJOR_VERSION_3, MBEDTLS_SSL_MINOR_VERSION_1, - MBEDTLS_SSL_MAJOR_VERSION_3, MBEDTLS_SSL_MINOR_VERSION_3, - MBEDTLS_CIPHERSUITE_WEAK }, + MBEDTLS_CIPHERSUITE_WEAK, + MBEDTLS_SSL_VERSION_TLS1_2, MBEDTLS_SSL_VERSION_TLS1_2 }, #endif #endif /* MBEDTLS_KEY_EXCHANGE_RSA_ENABLED */ #if defined(MBEDTLS_KEY_EXCHANGE_PSK_ENABLED) -#if defined(MBEDTLS_SHA1_C) +#if defined(MBEDTLS_MD_CAN_SHA1) { MBEDTLS_TLS_PSK_WITH_NULL_SHA, "TLS-PSK-WITH-NULL-SHA", MBEDTLS_CIPHER_NULL, MBEDTLS_MD_SHA1, MBEDTLS_KEY_EXCHANGE_PSK, - MBEDTLS_SSL_MAJOR_VERSION_3, MBEDTLS_SSL_MINOR_VERSION_0, - MBEDTLS_SSL_MAJOR_VERSION_3, MBEDTLS_SSL_MINOR_VERSION_3, - MBEDTLS_CIPHERSUITE_WEAK }, -#endif /* MBEDTLS_SHA1_C */ + MBEDTLS_CIPHERSUITE_WEAK, + MBEDTLS_SSL_VERSION_TLS1_2, MBEDTLS_SSL_VERSION_TLS1_2 }, +#endif /* MBEDTLS_MD_CAN_SHA1 */ -#if defined(MBEDTLS_SHA256_C) +#if defined(MBEDTLS_MD_CAN_SHA256) { MBEDTLS_TLS_PSK_WITH_NULL_SHA256, "TLS-PSK-WITH-NULL-SHA256", MBEDTLS_CIPHER_NULL, MBEDTLS_MD_SHA256, MBEDTLS_KEY_EXCHANGE_PSK, - MBEDTLS_SSL_MAJOR_VERSION_3, MBEDTLS_SSL_MINOR_VERSION_1, - MBEDTLS_SSL_MAJOR_VERSION_3, MBEDTLS_SSL_MINOR_VERSION_3, - MBEDTLS_CIPHERSUITE_WEAK }, + MBEDTLS_CIPHERSUITE_WEAK, + MBEDTLS_SSL_VERSION_TLS1_2, MBEDTLS_SSL_VERSION_TLS1_2 }, #endif -#if defined(HAVE_SHA384) +#if defined(MBEDTLS_MD_CAN_SHA384) { MBEDTLS_TLS_PSK_WITH_NULL_SHA384, "TLS-PSK-WITH-NULL-SHA384", MBEDTLS_CIPHER_NULL, MBEDTLS_MD_SHA384, MBEDTLS_KEY_EXCHANGE_PSK, - MBEDTLS_SSL_MAJOR_VERSION_3, MBEDTLS_SSL_MINOR_VERSION_1, - MBEDTLS_SSL_MAJOR_VERSION_3, MBEDTLS_SSL_MINOR_VERSION_3, - MBEDTLS_CIPHERSUITE_WEAK }, -#endif + MBEDTLS_CIPHERSUITE_WEAK, + MBEDTLS_SSL_VERSION_TLS1_2, MBEDTLS_SSL_VERSION_TLS1_2 }, +#endif /* MBEDTLS_MD_CAN_SHA384 */ #endif /* MBEDTLS_KEY_EXCHANGE_PSK_ENABLED */ #if defined(MBEDTLS_KEY_EXCHANGE_DHE_PSK_ENABLED) -#if defined(MBEDTLS_SHA1_C) +#if defined(MBEDTLS_MD_CAN_SHA1) { MBEDTLS_TLS_DHE_PSK_WITH_NULL_SHA, "TLS-DHE-PSK-WITH-NULL-SHA", MBEDTLS_CIPHER_NULL, MBEDTLS_MD_SHA1, MBEDTLS_KEY_EXCHANGE_DHE_PSK, - MBEDTLS_SSL_MAJOR_VERSION_3, MBEDTLS_SSL_MINOR_VERSION_0, - MBEDTLS_SSL_MAJOR_VERSION_3, MBEDTLS_SSL_MINOR_VERSION_3, - MBEDTLS_CIPHERSUITE_WEAK }, -#endif /* MBEDTLS_SHA1_C */ + MBEDTLS_CIPHERSUITE_WEAK, + MBEDTLS_SSL_VERSION_TLS1_2, MBEDTLS_SSL_VERSION_TLS1_2 }, +#endif /* MBEDTLS_MD_CAN_SHA1 */ -#if defined(MBEDTLS_SHA256_C) +#if defined(MBEDTLS_MD_CAN_SHA256) { MBEDTLS_TLS_DHE_PSK_WITH_NULL_SHA256, "TLS-DHE-PSK-WITH-NULL-SHA256", MBEDTLS_CIPHER_NULL, MBEDTLS_MD_SHA256, MBEDTLS_KEY_EXCHANGE_DHE_PSK, - MBEDTLS_SSL_MAJOR_VERSION_3, MBEDTLS_SSL_MINOR_VERSION_1, - MBEDTLS_SSL_MAJOR_VERSION_3, MBEDTLS_SSL_MINOR_VERSION_3, - MBEDTLS_CIPHERSUITE_WEAK }, + MBEDTLS_CIPHERSUITE_WEAK, + MBEDTLS_SSL_VERSION_TLS1_2, MBEDTLS_SSL_VERSION_TLS1_2 }, #endif -#if defined(HAVE_SHA384) +#if defined(MBEDTLS_MD_CAN_SHA384) { MBEDTLS_TLS_DHE_PSK_WITH_NULL_SHA384, "TLS-DHE-PSK-WITH-NULL-SHA384", MBEDTLS_CIPHER_NULL, MBEDTLS_MD_SHA384, MBEDTLS_KEY_EXCHANGE_DHE_PSK, - MBEDTLS_SSL_MAJOR_VERSION_3, MBEDTLS_SSL_MINOR_VERSION_1, - MBEDTLS_SSL_MAJOR_VERSION_3, MBEDTLS_SSL_MINOR_VERSION_3, - MBEDTLS_CIPHERSUITE_WEAK }, -#endif + MBEDTLS_CIPHERSUITE_WEAK, + MBEDTLS_SSL_VERSION_TLS1_2, MBEDTLS_SSL_VERSION_TLS1_2 }, +#endif /* MBEDTLS_MD_CAN_SHA384 */ #endif /* MBEDTLS_KEY_EXCHANGE_DHE_PSK_ENABLED */ #if defined(MBEDTLS_KEY_EXCHANGE_ECDHE_PSK_ENABLED) -#if defined(MBEDTLS_SHA1_C) +#if defined(MBEDTLS_MD_CAN_SHA1) { MBEDTLS_TLS_ECDHE_PSK_WITH_NULL_SHA, "TLS-ECDHE-PSK-WITH-NULL-SHA", MBEDTLS_CIPHER_NULL, MBEDTLS_MD_SHA1, MBEDTLS_KEY_EXCHANGE_ECDHE_PSK, - MBEDTLS_SSL_MAJOR_VERSION_3, MBEDTLS_SSL_MINOR_VERSION_1, - MBEDTLS_SSL_MAJOR_VERSION_3, MBEDTLS_SSL_MINOR_VERSION_3, - MBEDTLS_CIPHERSUITE_WEAK }, -#endif /* MBEDTLS_SHA1_C */ + MBEDTLS_CIPHERSUITE_WEAK, + MBEDTLS_SSL_VERSION_TLS1_2, MBEDTLS_SSL_VERSION_TLS1_2 }, +#endif /* MBEDTLS_MD_CAN_SHA1 */ -#if defined(MBEDTLS_SHA256_C) +#if defined(MBEDTLS_MD_CAN_SHA256) { MBEDTLS_TLS_ECDHE_PSK_WITH_NULL_SHA256, "TLS-ECDHE-PSK-WITH-NULL-SHA256", MBEDTLS_CIPHER_NULL, MBEDTLS_MD_SHA256, MBEDTLS_KEY_EXCHANGE_ECDHE_PSK, - MBEDTLS_SSL_MAJOR_VERSION_3, MBEDTLS_SSL_MINOR_VERSION_1, - MBEDTLS_SSL_MAJOR_VERSION_3, MBEDTLS_SSL_MINOR_VERSION_3, - MBEDTLS_CIPHERSUITE_WEAK }, + MBEDTLS_CIPHERSUITE_WEAK, + MBEDTLS_SSL_VERSION_TLS1_2, MBEDTLS_SSL_VERSION_TLS1_2 }, #endif -#if defined(HAVE_SHA384) +#if defined(MBEDTLS_MD_CAN_SHA384) { MBEDTLS_TLS_ECDHE_PSK_WITH_NULL_SHA384, "TLS-ECDHE-PSK-WITH-NULL-SHA384", MBEDTLS_CIPHER_NULL, MBEDTLS_MD_SHA384, MBEDTLS_KEY_EXCHANGE_ECDHE_PSK, - MBEDTLS_SSL_MAJOR_VERSION_3, MBEDTLS_SSL_MINOR_VERSION_1, - MBEDTLS_SSL_MAJOR_VERSION_3, MBEDTLS_SSL_MINOR_VERSION_3, - MBEDTLS_CIPHERSUITE_WEAK }, -#endif + MBEDTLS_CIPHERSUITE_WEAK, + MBEDTLS_SSL_VERSION_TLS1_2, MBEDTLS_SSL_VERSION_TLS1_2 }, +#endif /* MBEDTLS_MD_CAN_SHA384 */ #endif /* MBEDTLS_KEY_EXCHANGE_ECDHE_PSK_ENABLED */ #if defined(MBEDTLS_KEY_EXCHANGE_RSA_PSK_ENABLED) -#if defined(MBEDTLS_SHA1_C) +#if defined(MBEDTLS_MD_CAN_SHA1) { MBEDTLS_TLS_RSA_PSK_WITH_NULL_SHA, "TLS-RSA-PSK-WITH-NULL-SHA", MBEDTLS_CIPHER_NULL, MBEDTLS_MD_SHA1, MBEDTLS_KEY_EXCHANGE_RSA_PSK, - MBEDTLS_SSL_MAJOR_VERSION_3, MBEDTLS_SSL_MINOR_VERSION_1, - MBEDTLS_SSL_MAJOR_VERSION_3, MBEDTLS_SSL_MINOR_VERSION_3, - MBEDTLS_CIPHERSUITE_WEAK }, -#endif /* MBEDTLS_SHA1_C */ + MBEDTLS_CIPHERSUITE_WEAK, + MBEDTLS_SSL_VERSION_TLS1_2, MBEDTLS_SSL_VERSION_TLS1_2 }, +#endif /* MBEDTLS_MD_CAN_SHA1 */ -#if defined(MBEDTLS_SHA256_C) +#if defined(MBEDTLS_MD_CAN_SHA256) { MBEDTLS_TLS_RSA_PSK_WITH_NULL_SHA256, "TLS-RSA-PSK-WITH-NULL-SHA256", MBEDTLS_CIPHER_NULL, MBEDTLS_MD_SHA256, MBEDTLS_KEY_EXCHANGE_RSA_PSK, - MBEDTLS_SSL_MAJOR_VERSION_3, MBEDTLS_SSL_MINOR_VERSION_1, - MBEDTLS_SSL_MAJOR_VERSION_3, MBEDTLS_SSL_MINOR_VERSION_3, - MBEDTLS_CIPHERSUITE_WEAK }, + MBEDTLS_CIPHERSUITE_WEAK, + MBEDTLS_SSL_VERSION_TLS1_2, MBEDTLS_SSL_VERSION_TLS1_2 }, #endif -#if defined(HAVE_SHA384) +#if defined(MBEDTLS_MD_CAN_SHA384) { MBEDTLS_TLS_RSA_PSK_WITH_NULL_SHA384, "TLS-RSA-PSK-WITH-NULL-SHA384", MBEDTLS_CIPHER_NULL, MBEDTLS_MD_SHA384, MBEDTLS_KEY_EXCHANGE_RSA_PSK, - MBEDTLS_SSL_MAJOR_VERSION_3, MBEDTLS_SSL_MINOR_VERSION_1, - MBEDTLS_SSL_MAJOR_VERSION_3, MBEDTLS_SSL_MINOR_VERSION_3, - MBEDTLS_CIPHERSUITE_WEAK }, -#endif + MBEDTLS_CIPHERSUITE_WEAK, + MBEDTLS_SSL_VERSION_TLS1_2, MBEDTLS_SSL_VERSION_TLS1_2 }, +#endif /* MBEDTLS_MD_CAN_SHA384 */ #endif /* MBEDTLS_KEY_EXCHANGE_RSA_PSK_ENABLED */ #endif /* MBEDTLS_CIPHER_NULL_CIPHER */ -#if defined(MBEDTLS_DES_C) -#if defined(MBEDTLS_CIPHER_MODE_CBC) -#if defined(MBEDTLS_KEY_EXCHANGE_DHE_RSA_ENABLED) -#if defined(MBEDTLS_SHA1_C) - { MBEDTLS_TLS_DHE_RSA_WITH_DES_CBC_SHA, "TLS-DHE-RSA-WITH-DES-CBC-SHA", - MBEDTLS_CIPHER_DES_CBC, MBEDTLS_MD_SHA1, MBEDTLS_KEY_EXCHANGE_DHE_RSA, - MBEDTLS_SSL_MAJOR_VERSION_3, MBEDTLS_SSL_MINOR_VERSION_0, - MBEDTLS_SSL_MAJOR_VERSION_3, MBEDTLS_SSL_MINOR_VERSION_3, - MBEDTLS_CIPHERSUITE_WEAK }, -#endif /* MBEDTLS_SHA1_C */ -#endif /* MBEDTLS_KEY_EXCHANGE_DHE_RSA_ENABLED */ - -#if defined(MBEDTLS_KEY_EXCHANGE_RSA_ENABLED) -#if defined(MBEDTLS_SHA1_C) - { MBEDTLS_TLS_RSA_WITH_DES_CBC_SHA, "TLS-RSA-WITH-DES-CBC-SHA", - MBEDTLS_CIPHER_DES_CBC, MBEDTLS_MD_SHA1, MBEDTLS_KEY_EXCHANGE_RSA, - MBEDTLS_SSL_MAJOR_VERSION_3, MBEDTLS_SSL_MINOR_VERSION_0, - MBEDTLS_SSL_MAJOR_VERSION_3, MBEDTLS_SSL_MINOR_VERSION_3, - MBEDTLS_CIPHERSUITE_WEAK }, -#endif /* MBEDTLS_SHA1_C */ -#endif /* MBEDTLS_KEY_EXCHANGE_RSA_ENABLED */ -#endif /* MBEDTLS_CIPHER_MODE_CBC */ -#endif /* MBEDTLS_DES_C */ -#endif /* MBEDTLS_ENABLE_WEAK_CIPHERSUITES */ - -#if defined(MBEDTLS_ARIA_C) +#if defined(MBEDTLS_SSL_HAVE_ARIA) #if defined(MBEDTLS_KEY_EXCHANGE_RSA_ENABLED) -#if (defined(MBEDTLS_GCM_C) && defined(HAVE_SHA384)) +#if (defined(MBEDTLS_SSL_HAVE_GCM) && defined(MBEDTLS_MD_CAN_SHA384)) { MBEDTLS_TLS_RSA_WITH_ARIA_256_GCM_SHA384, "TLS-RSA-WITH-ARIA-256-GCM-SHA384", MBEDTLS_CIPHER_ARIA_256_GCM, MBEDTLS_MD_SHA384, MBEDTLS_KEY_EXCHANGE_RSA, - MBEDTLS_SSL_MAJOR_VERSION_3, MBEDTLS_SSL_MINOR_VERSION_3, - MBEDTLS_SSL_MAJOR_VERSION_3, MBEDTLS_SSL_MINOR_VERSION_3, - 0 }, + 0, + MBEDTLS_SSL_VERSION_TLS1_2, MBEDTLS_SSL_VERSION_TLS1_2 }, #endif -#if (defined(MBEDTLS_CIPHER_MODE_CBC) && defined(HAVE_SHA384)) +#if (defined(MBEDTLS_SSL_HAVE_CBC) && \ + defined(MBEDTLS_MD_CAN_SHA384)) { MBEDTLS_TLS_RSA_WITH_ARIA_256_CBC_SHA384, "TLS-RSA-WITH-ARIA-256-CBC-SHA384", MBEDTLS_CIPHER_ARIA_256_CBC, MBEDTLS_MD_SHA384, MBEDTLS_KEY_EXCHANGE_RSA, - MBEDTLS_SSL_MAJOR_VERSION_3, MBEDTLS_SSL_MINOR_VERSION_3, - MBEDTLS_SSL_MAJOR_VERSION_3, MBEDTLS_SSL_MINOR_VERSION_3, - 0 }, + 0, + MBEDTLS_SSL_VERSION_TLS1_2, MBEDTLS_SSL_VERSION_TLS1_2 }, #endif -#if (defined(MBEDTLS_GCM_C) && defined(MBEDTLS_SHA256_C)) +#if (defined(MBEDTLS_SSL_HAVE_GCM) && defined(MBEDTLS_MD_CAN_SHA256)) { MBEDTLS_TLS_RSA_WITH_ARIA_128_GCM_SHA256, "TLS-RSA-WITH-ARIA-128-GCM-SHA256", MBEDTLS_CIPHER_ARIA_128_GCM, MBEDTLS_MD_SHA256, MBEDTLS_KEY_EXCHANGE_RSA, - MBEDTLS_SSL_MAJOR_VERSION_3, MBEDTLS_SSL_MINOR_VERSION_3, - MBEDTLS_SSL_MAJOR_VERSION_3, MBEDTLS_SSL_MINOR_VERSION_3, - 0 }, + 0, + MBEDTLS_SSL_VERSION_TLS1_2, MBEDTLS_SSL_VERSION_TLS1_2 }, #endif -#if (defined(MBEDTLS_CIPHER_MODE_CBC) && defined(MBEDTLS_SHA256_C)) +#if (defined(MBEDTLS_SSL_HAVE_CBC) && \ + defined(MBEDTLS_MD_CAN_SHA256)) { MBEDTLS_TLS_RSA_WITH_ARIA_128_CBC_SHA256, "TLS-RSA-WITH-ARIA-128-CBC-SHA256", MBEDTLS_CIPHER_ARIA_128_CBC, MBEDTLS_MD_SHA256, MBEDTLS_KEY_EXCHANGE_RSA, - MBEDTLS_SSL_MAJOR_VERSION_3, MBEDTLS_SSL_MINOR_VERSION_3, - MBEDTLS_SSL_MAJOR_VERSION_3, MBEDTLS_SSL_MINOR_VERSION_3, - 0 }, + 0, + MBEDTLS_SSL_VERSION_TLS1_2, MBEDTLS_SSL_VERSION_TLS1_2 }, #endif #endif /* MBEDTLS_KEY_EXCHANGE_RSA_ENABLED */ #if defined(MBEDTLS_KEY_EXCHANGE_RSA_PSK_ENABLED) -#if (defined(MBEDTLS_GCM_C) && defined(HAVE_SHA384)) +#if (defined(MBEDTLS_SSL_HAVE_GCM) && defined(MBEDTLS_MD_CAN_SHA384)) { MBEDTLS_TLS_RSA_PSK_WITH_ARIA_256_GCM_SHA384, "TLS-RSA-PSK-WITH-ARIA-256-GCM-SHA384", MBEDTLS_CIPHER_ARIA_256_GCM, MBEDTLS_MD_SHA384, MBEDTLS_KEY_EXCHANGE_RSA_PSK, - MBEDTLS_SSL_MAJOR_VERSION_3, MBEDTLS_SSL_MINOR_VERSION_3, - MBEDTLS_SSL_MAJOR_VERSION_3, MBEDTLS_SSL_MINOR_VERSION_3, - 0 }, + 0, + MBEDTLS_SSL_VERSION_TLS1_2, MBEDTLS_SSL_VERSION_TLS1_2 }, #endif -#if (defined(MBEDTLS_CIPHER_MODE_CBC) && defined(HAVE_SHA384)) +#if (defined(MBEDTLS_SSL_HAVE_CBC) && \ + defined(MBEDTLS_MD_CAN_SHA384)) { MBEDTLS_TLS_RSA_PSK_WITH_ARIA_256_CBC_SHA384, "TLS-RSA-PSK-WITH-ARIA-256-CBC-SHA384", MBEDTLS_CIPHER_ARIA_256_CBC, MBEDTLS_MD_SHA384, MBEDTLS_KEY_EXCHANGE_RSA_PSK, - MBEDTLS_SSL_MAJOR_VERSION_3, MBEDTLS_SSL_MINOR_VERSION_3, - MBEDTLS_SSL_MAJOR_VERSION_3, MBEDTLS_SSL_MINOR_VERSION_3, - 0 }, + 0, + MBEDTLS_SSL_VERSION_TLS1_2, MBEDTLS_SSL_VERSION_TLS1_2 }, #endif -#if (defined(MBEDTLS_GCM_C) && defined(MBEDTLS_SHA256_C)) +#if (defined(MBEDTLS_SSL_HAVE_GCM) && defined(MBEDTLS_MD_CAN_SHA256)) { MBEDTLS_TLS_RSA_PSK_WITH_ARIA_128_GCM_SHA256, "TLS-RSA-PSK-WITH-ARIA-128-GCM-SHA256", MBEDTLS_CIPHER_ARIA_128_GCM, MBEDTLS_MD_SHA256, MBEDTLS_KEY_EXCHANGE_RSA_PSK, - MBEDTLS_SSL_MAJOR_VERSION_3, MBEDTLS_SSL_MINOR_VERSION_3, - MBEDTLS_SSL_MAJOR_VERSION_3, MBEDTLS_SSL_MINOR_VERSION_3, - 0 }, + 0, + MBEDTLS_SSL_VERSION_TLS1_2, MBEDTLS_SSL_VERSION_TLS1_2 }, #endif -#if (defined(MBEDTLS_CIPHER_MODE_CBC) && defined(MBEDTLS_SHA256_C)) +#if (defined(MBEDTLS_SSL_HAVE_CBC) && \ + defined(MBEDTLS_MD_CAN_SHA256)) { MBEDTLS_TLS_RSA_PSK_WITH_ARIA_128_CBC_SHA256, "TLS-RSA-PSK-WITH-ARIA-128-CBC-SHA256", MBEDTLS_CIPHER_ARIA_128_CBC, MBEDTLS_MD_SHA256, MBEDTLS_KEY_EXCHANGE_RSA_PSK, - MBEDTLS_SSL_MAJOR_VERSION_3, MBEDTLS_SSL_MINOR_VERSION_3, - MBEDTLS_SSL_MAJOR_VERSION_3, MBEDTLS_SSL_MINOR_VERSION_3, - 0 }, + 0, + MBEDTLS_SSL_VERSION_TLS1_2, MBEDTLS_SSL_VERSION_TLS1_2 }, #endif #endif /* MBEDTLS_KEY_EXCHANGE_RSA_PSK_ENABLED */ #if defined(MBEDTLS_KEY_EXCHANGE_PSK_ENABLED) -#if (defined(MBEDTLS_GCM_C) && defined(HAVE_SHA384)) +#if (defined(MBEDTLS_SSL_HAVE_GCM) && defined(MBEDTLS_MD_CAN_SHA384)) { MBEDTLS_TLS_PSK_WITH_ARIA_256_GCM_SHA384, "TLS-PSK-WITH-ARIA-256-GCM-SHA384", MBEDTLS_CIPHER_ARIA_256_GCM, MBEDTLS_MD_SHA384, MBEDTLS_KEY_EXCHANGE_PSK, - MBEDTLS_SSL_MAJOR_VERSION_3, MBEDTLS_SSL_MINOR_VERSION_3, - MBEDTLS_SSL_MAJOR_VERSION_3, MBEDTLS_SSL_MINOR_VERSION_3, - 0 }, + 0, + MBEDTLS_SSL_VERSION_TLS1_2, MBEDTLS_SSL_VERSION_TLS1_2 }, #endif -#if (defined(MBEDTLS_CIPHER_MODE_CBC) && defined(HAVE_SHA384)) +#if (defined(MBEDTLS_SSL_HAVE_CBC) && \ + defined(MBEDTLS_MD_CAN_SHA384)) { MBEDTLS_TLS_PSK_WITH_ARIA_256_CBC_SHA384, "TLS-PSK-WITH-ARIA-256-CBC-SHA384", MBEDTLS_CIPHER_ARIA_256_CBC, MBEDTLS_MD_SHA384, MBEDTLS_KEY_EXCHANGE_PSK, - MBEDTLS_SSL_MAJOR_VERSION_3, MBEDTLS_SSL_MINOR_VERSION_3, - MBEDTLS_SSL_MAJOR_VERSION_3, MBEDTLS_SSL_MINOR_VERSION_3, - 0 }, + 0, + MBEDTLS_SSL_VERSION_TLS1_2, MBEDTLS_SSL_VERSION_TLS1_2 }, #endif -#if (defined(MBEDTLS_GCM_C) && defined(MBEDTLS_SHA256_C)) +#if (defined(MBEDTLS_SSL_HAVE_GCM) && defined(MBEDTLS_MD_CAN_SHA256)) { MBEDTLS_TLS_PSK_WITH_ARIA_128_GCM_SHA256, "TLS-PSK-WITH-ARIA-128-GCM-SHA256", MBEDTLS_CIPHER_ARIA_128_GCM, MBEDTLS_MD_SHA256, MBEDTLS_KEY_EXCHANGE_PSK, - MBEDTLS_SSL_MAJOR_VERSION_3, MBEDTLS_SSL_MINOR_VERSION_3, - MBEDTLS_SSL_MAJOR_VERSION_3, MBEDTLS_SSL_MINOR_VERSION_3, - 0 }, + 0, + MBEDTLS_SSL_VERSION_TLS1_2, MBEDTLS_SSL_VERSION_TLS1_2 }, #endif -#if (defined(MBEDTLS_CIPHER_MODE_CBC) && defined(MBEDTLS_SHA256_C)) +#if (defined(MBEDTLS_SSL_HAVE_CBC) && \ + defined(MBEDTLS_MD_CAN_SHA256)) { MBEDTLS_TLS_PSK_WITH_ARIA_128_CBC_SHA256, "TLS-PSK-WITH-ARIA-128-CBC-SHA256", MBEDTLS_CIPHER_ARIA_128_CBC, MBEDTLS_MD_SHA256, MBEDTLS_KEY_EXCHANGE_PSK, - MBEDTLS_SSL_MAJOR_VERSION_3, MBEDTLS_SSL_MINOR_VERSION_3, - MBEDTLS_SSL_MAJOR_VERSION_3, MBEDTLS_SSL_MINOR_VERSION_3, - 0 }, + 0, + MBEDTLS_SSL_VERSION_TLS1_2, MBEDTLS_SSL_VERSION_TLS1_2 }, #endif #endif /* MBEDTLS_KEY_EXCHANGE_PSK_ENABLED */ #if defined(MBEDTLS_KEY_EXCHANGE_ECDH_RSA_ENABLED) -#if (defined(MBEDTLS_GCM_C) && defined(HAVE_SHA384)) +#if (defined(MBEDTLS_SSL_HAVE_GCM) && defined(MBEDTLS_MD_CAN_SHA384)) { MBEDTLS_TLS_ECDH_RSA_WITH_ARIA_256_GCM_SHA384, "TLS-ECDH-RSA-WITH-ARIA-256-GCM-SHA384", MBEDTLS_CIPHER_ARIA_256_GCM, MBEDTLS_MD_SHA384, MBEDTLS_KEY_EXCHANGE_ECDH_RSA, - MBEDTLS_SSL_MAJOR_VERSION_3, MBEDTLS_SSL_MINOR_VERSION_3, - MBEDTLS_SSL_MAJOR_VERSION_3, MBEDTLS_SSL_MINOR_VERSION_3, - 0 }, + 0, + MBEDTLS_SSL_VERSION_TLS1_2, MBEDTLS_SSL_VERSION_TLS1_2 }, #endif -#if (defined(MBEDTLS_CIPHER_MODE_CBC) && defined(HAVE_SHA384)) +#if (defined(MBEDTLS_SSL_HAVE_CBC) && \ + defined(MBEDTLS_MD_CAN_SHA384)) { MBEDTLS_TLS_ECDH_RSA_WITH_ARIA_256_CBC_SHA384, "TLS-ECDH-RSA-WITH-ARIA-256-CBC-SHA384", MBEDTLS_CIPHER_ARIA_256_CBC, MBEDTLS_MD_SHA384, MBEDTLS_KEY_EXCHANGE_ECDH_RSA, - MBEDTLS_SSL_MAJOR_VERSION_3, MBEDTLS_SSL_MINOR_VERSION_3, - MBEDTLS_SSL_MAJOR_VERSION_3, MBEDTLS_SSL_MINOR_VERSION_3, - 0 }, + 0, + MBEDTLS_SSL_VERSION_TLS1_2, MBEDTLS_SSL_VERSION_TLS1_2 }, #endif -#if (defined(MBEDTLS_GCM_C) && defined(MBEDTLS_SHA256_C)) +#if (defined(MBEDTLS_SSL_HAVE_GCM) && defined(MBEDTLS_MD_CAN_SHA256)) { MBEDTLS_TLS_ECDH_RSA_WITH_ARIA_128_GCM_SHA256, "TLS-ECDH-RSA-WITH-ARIA-128-GCM-SHA256", MBEDTLS_CIPHER_ARIA_128_GCM, MBEDTLS_MD_SHA256, MBEDTLS_KEY_EXCHANGE_ECDH_RSA, - MBEDTLS_SSL_MAJOR_VERSION_3, MBEDTLS_SSL_MINOR_VERSION_3, - MBEDTLS_SSL_MAJOR_VERSION_3, MBEDTLS_SSL_MINOR_VERSION_3, - 0 }, + 0, + MBEDTLS_SSL_VERSION_TLS1_2, MBEDTLS_SSL_VERSION_TLS1_2 }, #endif -#if (defined(MBEDTLS_CIPHER_MODE_CBC) && defined(MBEDTLS_SHA256_C)) +#if (defined(MBEDTLS_SSL_HAVE_CBC) && \ + defined(MBEDTLS_MD_CAN_SHA256)) { MBEDTLS_TLS_ECDH_RSA_WITH_ARIA_128_CBC_SHA256, "TLS-ECDH-RSA-WITH-ARIA-128-CBC-SHA256", MBEDTLS_CIPHER_ARIA_128_CBC, MBEDTLS_MD_SHA256, MBEDTLS_KEY_EXCHANGE_ECDH_RSA, - MBEDTLS_SSL_MAJOR_VERSION_3, MBEDTLS_SSL_MINOR_VERSION_3, - MBEDTLS_SSL_MAJOR_VERSION_3, MBEDTLS_SSL_MINOR_VERSION_3, - 0 }, + 0, + MBEDTLS_SSL_VERSION_TLS1_2, MBEDTLS_SSL_VERSION_TLS1_2 }, #endif #endif /* MBEDTLS_KEY_EXCHANGE_ECDH_RSA_ENABLED */ #if defined(MBEDTLS_KEY_EXCHANGE_ECDHE_RSA_ENABLED) -#if (defined(MBEDTLS_GCM_C) && defined(HAVE_SHA384)) +#if (defined(MBEDTLS_SSL_HAVE_GCM) && defined(MBEDTLS_MD_CAN_SHA384)) { MBEDTLS_TLS_ECDHE_RSA_WITH_ARIA_256_GCM_SHA384, "TLS-ECDHE-RSA-WITH-ARIA-256-GCM-SHA384", MBEDTLS_CIPHER_ARIA_256_GCM, MBEDTLS_MD_SHA384, MBEDTLS_KEY_EXCHANGE_ECDHE_RSA, - MBEDTLS_SSL_MAJOR_VERSION_3, MBEDTLS_SSL_MINOR_VERSION_3, - MBEDTLS_SSL_MAJOR_VERSION_3, MBEDTLS_SSL_MINOR_VERSION_3, - 0 }, + 0, + MBEDTLS_SSL_VERSION_TLS1_2, MBEDTLS_SSL_VERSION_TLS1_2 }, #endif -#if (defined(MBEDTLS_CIPHER_MODE_CBC) && defined(HAVE_SHA384)) +#if (defined(MBEDTLS_SSL_HAVE_CBC) && \ + defined(MBEDTLS_MD_CAN_SHA384)) { MBEDTLS_TLS_ECDHE_RSA_WITH_ARIA_256_CBC_SHA384, "TLS-ECDHE-RSA-WITH-ARIA-256-CBC-SHA384", MBEDTLS_CIPHER_ARIA_256_CBC, MBEDTLS_MD_SHA384, MBEDTLS_KEY_EXCHANGE_ECDHE_RSA, - MBEDTLS_SSL_MAJOR_VERSION_3, MBEDTLS_SSL_MINOR_VERSION_3, - MBEDTLS_SSL_MAJOR_VERSION_3, MBEDTLS_SSL_MINOR_VERSION_3, - 0 }, + 0, + MBEDTLS_SSL_VERSION_TLS1_2, MBEDTLS_SSL_VERSION_TLS1_2 }, #endif -#if (defined(MBEDTLS_GCM_C) && defined(MBEDTLS_SHA256_C)) +#if (defined(MBEDTLS_SSL_HAVE_GCM) && defined(MBEDTLS_MD_CAN_SHA256)) { MBEDTLS_TLS_ECDHE_RSA_WITH_ARIA_128_GCM_SHA256, "TLS-ECDHE-RSA-WITH-ARIA-128-GCM-SHA256", MBEDTLS_CIPHER_ARIA_128_GCM, MBEDTLS_MD_SHA256, MBEDTLS_KEY_EXCHANGE_ECDHE_RSA, - MBEDTLS_SSL_MAJOR_VERSION_3, MBEDTLS_SSL_MINOR_VERSION_3, - MBEDTLS_SSL_MAJOR_VERSION_3, MBEDTLS_SSL_MINOR_VERSION_3, - 0 }, + 0, + MBEDTLS_SSL_VERSION_TLS1_2, MBEDTLS_SSL_VERSION_TLS1_2 }, #endif -#if (defined(MBEDTLS_CIPHER_MODE_CBC) && defined(MBEDTLS_SHA256_C)) +#if (defined(MBEDTLS_SSL_HAVE_CBC) && \ + defined(MBEDTLS_MD_CAN_SHA256)) { MBEDTLS_TLS_ECDHE_RSA_WITH_ARIA_128_CBC_SHA256, "TLS-ECDHE-RSA-WITH-ARIA-128-CBC-SHA256", MBEDTLS_CIPHER_ARIA_128_CBC, MBEDTLS_MD_SHA256, MBEDTLS_KEY_EXCHANGE_ECDHE_RSA, - MBEDTLS_SSL_MAJOR_VERSION_3, MBEDTLS_SSL_MINOR_VERSION_3, - MBEDTLS_SSL_MAJOR_VERSION_3, MBEDTLS_SSL_MINOR_VERSION_3, - 0 }, + 0, + MBEDTLS_SSL_VERSION_TLS1_2, MBEDTLS_SSL_VERSION_TLS1_2 }, #endif #endif /* MBEDTLS_KEY_EXCHANGE_ECDHE_RSA_ENABLED */ #if defined(MBEDTLS_KEY_EXCHANGE_ECDHE_PSK_ENABLED) -#if (defined(MBEDTLS_CIPHER_MODE_CBC) && defined(HAVE_SHA384)) +#if (defined(MBEDTLS_SSL_HAVE_CBC) && \ + defined(MBEDTLS_MD_CAN_SHA384)) { MBEDTLS_TLS_ECDHE_PSK_WITH_ARIA_256_CBC_SHA384, "TLS-ECDHE-PSK-WITH-ARIA-256-CBC-SHA384", MBEDTLS_CIPHER_ARIA_256_CBC, MBEDTLS_MD_SHA384, MBEDTLS_KEY_EXCHANGE_ECDHE_PSK, - MBEDTLS_SSL_MAJOR_VERSION_3, MBEDTLS_SSL_MINOR_VERSION_3, - MBEDTLS_SSL_MAJOR_VERSION_3, MBEDTLS_SSL_MINOR_VERSION_3, - 0 }, + 0, + MBEDTLS_SSL_VERSION_TLS1_2, MBEDTLS_SSL_VERSION_TLS1_2 }, #endif -#if (defined(MBEDTLS_CIPHER_MODE_CBC) && defined(MBEDTLS_SHA256_C)) +#if (defined(MBEDTLS_SSL_HAVE_CBC) && \ + defined(MBEDTLS_MD_CAN_SHA256)) { MBEDTLS_TLS_ECDHE_PSK_WITH_ARIA_128_CBC_SHA256, "TLS-ECDHE-PSK-WITH-ARIA-128-CBC-SHA256", MBEDTLS_CIPHER_ARIA_128_CBC, MBEDTLS_MD_SHA256, MBEDTLS_KEY_EXCHANGE_ECDHE_PSK, - MBEDTLS_SSL_MAJOR_VERSION_3, MBEDTLS_SSL_MINOR_VERSION_3, - MBEDTLS_SSL_MAJOR_VERSION_3, MBEDTLS_SSL_MINOR_VERSION_3, - 0 }, + 0, + MBEDTLS_SSL_VERSION_TLS1_2, MBEDTLS_SSL_VERSION_TLS1_2 }, #endif #endif /* MBEDTLS_KEY_EXCHANGE_ECDHE_PSK_ENABLED */ #if defined(MBEDTLS_KEY_EXCHANGE_ECDHE_ECDSA_ENABLED) -#if (defined(MBEDTLS_GCM_C) && defined(HAVE_SHA384)) +#if (defined(MBEDTLS_SSL_HAVE_GCM) && defined(MBEDTLS_MD_CAN_SHA384)) { MBEDTLS_TLS_ECDHE_ECDSA_WITH_ARIA_256_GCM_SHA384, "TLS-ECDHE-ECDSA-WITH-ARIA-256-GCM-SHA384", MBEDTLS_CIPHER_ARIA_256_GCM, MBEDTLS_MD_SHA384, MBEDTLS_KEY_EXCHANGE_ECDHE_ECDSA, - MBEDTLS_SSL_MAJOR_VERSION_3, MBEDTLS_SSL_MINOR_VERSION_3, - MBEDTLS_SSL_MAJOR_VERSION_3, MBEDTLS_SSL_MINOR_VERSION_3, - 0 }, + 0, + MBEDTLS_SSL_VERSION_TLS1_2, MBEDTLS_SSL_VERSION_TLS1_2 }, #endif -#if (defined(MBEDTLS_CIPHER_MODE_CBC) && defined(HAVE_SHA384)) +#if (defined(MBEDTLS_SSL_HAVE_CBC) && \ + defined(MBEDTLS_MD_CAN_SHA384)) { MBEDTLS_TLS_ECDHE_ECDSA_WITH_ARIA_256_CBC_SHA384, "TLS-ECDHE-ECDSA-WITH-ARIA-256-CBC-SHA384", MBEDTLS_CIPHER_ARIA_256_CBC, MBEDTLS_MD_SHA384, MBEDTLS_KEY_EXCHANGE_ECDHE_ECDSA, - MBEDTLS_SSL_MAJOR_VERSION_3, MBEDTLS_SSL_MINOR_VERSION_3, - MBEDTLS_SSL_MAJOR_VERSION_3, MBEDTLS_SSL_MINOR_VERSION_3, - 0 }, + 0, + MBEDTLS_SSL_VERSION_TLS1_2, MBEDTLS_SSL_VERSION_TLS1_2 }, #endif -#if (defined(MBEDTLS_GCM_C) && defined(MBEDTLS_SHA256_C)) +#if (defined(MBEDTLS_SSL_HAVE_GCM) && defined(MBEDTLS_MD_CAN_SHA256)) { MBEDTLS_TLS_ECDHE_ECDSA_WITH_ARIA_128_GCM_SHA256, "TLS-ECDHE-ECDSA-WITH-ARIA-128-GCM-SHA256", MBEDTLS_CIPHER_ARIA_128_GCM, MBEDTLS_MD_SHA256, MBEDTLS_KEY_EXCHANGE_ECDHE_ECDSA, - MBEDTLS_SSL_MAJOR_VERSION_3, MBEDTLS_SSL_MINOR_VERSION_3, - MBEDTLS_SSL_MAJOR_VERSION_3, MBEDTLS_SSL_MINOR_VERSION_3, - 0 }, + 0, + MBEDTLS_SSL_VERSION_TLS1_2, MBEDTLS_SSL_VERSION_TLS1_2 }, #endif -#if (defined(MBEDTLS_CIPHER_MODE_CBC) && defined(MBEDTLS_SHA256_C)) +#if (defined(MBEDTLS_SSL_HAVE_CBC) && \ + defined(MBEDTLS_MD_CAN_SHA256)) { MBEDTLS_TLS_ECDHE_ECDSA_WITH_ARIA_128_CBC_SHA256, "TLS-ECDHE-ECDSA-WITH-ARIA-128-CBC-SHA256", MBEDTLS_CIPHER_ARIA_128_CBC, MBEDTLS_MD_SHA256, MBEDTLS_KEY_EXCHANGE_ECDHE_ECDSA, - MBEDTLS_SSL_MAJOR_VERSION_3, MBEDTLS_SSL_MINOR_VERSION_3, - MBEDTLS_SSL_MAJOR_VERSION_3, MBEDTLS_SSL_MINOR_VERSION_3, - 0 }, + 0, + MBEDTLS_SSL_VERSION_TLS1_2, MBEDTLS_SSL_VERSION_TLS1_2 }, #endif #endif /* MBEDTLS_KEY_EXCHANGE_ECDHE_ECDSA_ENABLED */ #if defined(MBEDTLS_KEY_EXCHANGE_ECDH_ECDSA_ENABLED) -#if (defined(MBEDTLS_GCM_C) && defined(HAVE_SHA384)) +#if (defined(MBEDTLS_SSL_HAVE_GCM) && defined(MBEDTLS_MD_CAN_SHA384)) { MBEDTLS_TLS_ECDH_ECDSA_WITH_ARIA_256_GCM_SHA384, "TLS-ECDH-ECDSA-WITH-ARIA-256-GCM-SHA384", MBEDTLS_CIPHER_ARIA_256_GCM, MBEDTLS_MD_SHA384, MBEDTLS_KEY_EXCHANGE_ECDH_ECDSA, - MBEDTLS_SSL_MAJOR_VERSION_3, MBEDTLS_SSL_MINOR_VERSION_3, - MBEDTLS_SSL_MAJOR_VERSION_3, MBEDTLS_SSL_MINOR_VERSION_3, - 0 }, + 0, + MBEDTLS_SSL_VERSION_TLS1_2, MBEDTLS_SSL_VERSION_TLS1_2 }, #endif -#if (defined(MBEDTLS_CIPHER_MODE_CBC) && defined(HAVE_SHA384)) +#if (defined(MBEDTLS_SSL_HAVE_CBC) && \ + defined(MBEDTLS_MD_CAN_SHA384)) { MBEDTLS_TLS_ECDH_ECDSA_WITH_ARIA_256_CBC_SHA384, "TLS-ECDH-ECDSA-WITH-ARIA-256-CBC-SHA384", MBEDTLS_CIPHER_ARIA_256_CBC, MBEDTLS_MD_SHA384, MBEDTLS_KEY_EXCHANGE_ECDH_ECDSA, - MBEDTLS_SSL_MAJOR_VERSION_3, MBEDTLS_SSL_MINOR_VERSION_3, - MBEDTLS_SSL_MAJOR_VERSION_3, MBEDTLS_SSL_MINOR_VERSION_3, - 0 }, + 0, + MBEDTLS_SSL_VERSION_TLS1_2, MBEDTLS_SSL_VERSION_TLS1_2 }, #endif -#if (defined(MBEDTLS_GCM_C) && defined(MBEDTLS_SHA256_C)) +#if (defined(MBEDTLS_SSL_HAVE_GCM) && defined(MBEDTLS_MD_CAN_SHA256)) { MBEDTLS_TLS_ECDH_ECDSA_WITH_ARIA_128_GCM_SHA256, "TLS-ECDH-ECDSA-WITH-ARIA-128-GCM-SHA256", MBEDTLS_CIPHER_ARIA_128_GCM, MBEDTLS_MD_SHA256, MBEDTLS_KEY_EXCHANGE_ECDH_ECDSA, - MBEDTLS_SSL_MAJOR_VERSION_3, MBEDTLS_SSL_MINOR_VERSION_3, - MBEDTLS_SSL_MAJOR_VERSION_3, MBEDTLS_SSL_MINOR_VERSION_3, - 0 }, + 0, + MBEDTLS_SSL_VERSION_TLS1_2, MBEDTLS_SSL_VERSION_TLS1_2 }, #endif -#if (defined(MBEDTLS_CIPHER_MODE_CBC) && defined(MBEDTLS_SHA256_C)) +#if (defined(MBEDTLS_SSL_HAVE_CBC) && \ + defined(MBEDTLS_MD_CAN_SHA256)) { MBEDTLS_TLS_ECDH_ECDSA_WITH_ARIA_128_CBC_SHA256, "TLS-ECDH-ECDSA-WITH-ARIA-128-CBC-SHA256", MBEDTLS_CIPHER_ARIA_128_CBC, MBEDTLS_MD_SHA256, MBEDTLS_KEY_EXCHANGE_ECDH_ECDSA, - MBEDTLS_SSL_MAJOR_VERSION_3, MBEDTLS_SSL_MINOR_VERSION_3, - MBEDTLS_SSL_MAJOR_VERSION_3, MBEDTLS_SSL_MINOR_VERSION_3, - 0 }, + 0, + MBEDTLS_SSL_VERSION_TLS1_2, MBEDTLS_SSL_VERSION_TLS1_2 }, #endif #endif /* MBEDTLS_KEY_EXCHANGE_ECDH_ECDSA_ENABLED */ #if defined(MBEDTLS_KEY_EXCHANGE_DHE_RSA_ENABLED) -#if (defined(MBEDTLS_GCM_C) && defined(HAVE_SHA384)) +#if (defined(MBEDTLS_SSL_HAVE_GCM) && defined(MBEDTLS_MD_CAN_SHA384)) { MBEDTLS_TLS_DHE_RSA_WITH_ARIA_256_GCM_SHA384, "TLS-DHE-RSA-WITH-ARIA-256-GCM-SHA384", MBEDTLS_CIPHER_ARIA_256_GCM, MBEDTLS_MD_SHA384, MBEDTLS_KEY_EXCHANGE_DHE_RSA, - MBEDTLS_SSL_MAJOR_VERSION_3, MBEDTLS_SSL_MINOR_VERSION_3, - MBEDTLS_SSL_MAJOR_VERSION_3, MBEDTLS_SSL_MINOR_VERSION_3, - 0 }, + 0, + MBEDTLS_SSL_VERSION_TLS1_2, MBEDTLS_SSL_VERSION_TLS1_2 }, #endif -#if (defined(MBEDTLS_CIPHER_MODE_CBC) && defined(HAVE_SHA384)) +#if (defined(MBEDTLS_SSL_HAVE_CBC) && \ + defined(MBEDTLS_MD_CAN_SHA384)) { MBEDTLS_TLS_DHE_RSA_WITH_ARIA_256_CBC_SHA384, "TLS-DHE-RSA-WITH-ARIA-256-CBC-SHA384", MBEDTLS_CIPHER_ARIA_256_CBC, MBEDTLS_MD_SHA384, MBEDTLS_KEY_EXCHANGE_DHE_RSA, - MBEDTLS_SSL_MAJOR_VERSION_3, MBEDTLS_SSL_MINOR_VERSION_3, - MBEDTLS_SSL_MAJOR_VERSION_3, MBEDTLS_SSL_MINOR_VERSION_3, - 0 }, + 0, + MBEDTLS_SSL_VERSION_TLS1_2, MBEDTLS_SSL_VERSION_TLS1_2 }, #endif -#if (defined(MBEDTLS_GCM_C) && defined(MBEDTLS_SHA256_C)) +#if (defined(MBEDTLS_SSL_HAVE_GCM) && defined(MBEDTLS_MD_CAN_SHA256)) { MBEDTLS_TLS_DHE_RSA_WITH_ARIA_128_GCM_SHA256, "TLS-DHE-RSA-WITH-ARIA-128-GCM-SHA256", MBEDTLS_CIPHER_ARIA_128_GCM, MBEDTLS_MD_SHA256, MBEDTLS_KEY_EXCHANGE_DHE_RSA, - MBEDTLS_SSL_MAJOR_VERSION_3, MBEDTLS_SSL_MINOR_VERSION_3, - MBEDTLS_SSL_MAJOR_VERSION_3, MBEDTLS_SSL_MINOR_VERSION_3, - 0 }, + 0, + MBEDTLS_SSL_VERSION_TLS1_2, MBEDTLS_SSL_VERSION_TLS1_2 }, #endif -#if (defined(MBEDTLS_CIPHER_MODE_CBC) && defined(MBEDTLS_SHA256_C)) +#if (defined(MBEDTLS_SSL_HAVE_CBC) && \ + defined(MBEDTLS_MD_CAN_SHA256)) { MBEDTLS_TLS_DHE_RSA_WITH_ARIA_128_CBC_SHA256, "TLS-DHE-RSA-WITH-ARIA-128-CBC-SHA256", MBEDTLS_CIPHER_ARIA_128_CBC, MBEDTLS_MD_SHA256, MBEDTLS_KEY_EXCHANGE_DHE_RSA, - MBEDTLS_SSL_MAJOR_VERSION_3, MBEDTLS_SSL_MINOR_VERSION_3, - MBEDTLS_SSL_MAJOR_VERSION_3, MBEDTLS_SSL_MINOR_VERSION_3, - 0 }, + 0, + MBEDTLS_SSL_VERSION_TLS1_2, MBEDTLS_SSL_VERSION_TLS1_2 }, #endif #endif /* MBEDTLS_KEY_EXCHANGE_DHE_RSA_ENABLED */ #if defined(MBEDTLS_KEY_EXCHANGE_DHE_PSK_ENABLED) -#if (defined(MBEDTLS_GCM_C) && defined(HAVE_SHA384)) +#if (defined(MBEDTLS_SSL_HAVE_GCM) && defined(MBEDTLS_MD_CAN_SHA384)) { MBEDTLS_TLS_DHE_PSK_WITH_ARIA_256_GCM_SHA384, "TLS-DHE-PSK-WITH-ARIA-256-GCM-SHA384", MBEDTLS_CIPHER_ARIA_256_GCM, MBEDTLS_MD_SHA384, MBEDTLS_KEY_EXCHANGE_DHE_PSK, - MBEDTLS_SSL_MAJOR_VERSION_3, MBEDTLS_SSL_MINOR_VERSION_3, - MBEDTLS_SSL_MAJOR_VERSION_3, MBEDTLS_SSL_MINOR_VERSION_3, - 0 }, + 0, + MBEDTLS_SSL_VERSION_TLS1_2, MBEDTLS_SSL_VERSION_TLS1_2 }, #endif -#if (defined(MBEDTLS_CIPHER_MODE_CBC) && defined(HAVE_SHA384)) +#if (defined(MBEDTLS_SSL_HAVE_CBC) && \ + defined(MBEDTLS_MD_CAN_SHA384)) { MBEDTLS_TLS_DHE_PSK_WITH_ARIA_256_CBC_SHA384, "TLS-DHE-PSK-WITH-ARIA-256-CBC-SHA384", MBEDTLS_CIPHER_ARIA_256_CBC, MBEDTLS_MD_SHA384, MBEDTLS_KEY_EXCHANGE_DHE_PSK, - MBEDTLS_SSL_MAJOR_VERSION_3, MBEDTLS_SSL_MINOR_VERSION_3, - MBEDTLS_SSL_MAJOR_VERSION_3, MBEDTLS_SSL_MINOR_VERSION_3, - 0 }, + 0, + MBEDTLS_SSL_VERSION_TLS1_2, MBEDTLS_SSL_VERSION_TLS1_2 }, #endif -#if (defined(MBEDTLS_GCM_C) && defined(MBEDTLS_SHA256_C)) +#if (defined(MBEDTLS_SSL_HAVE_GCM) && defined(MBEDTLS_MD_CAN_SHA256)) { MBEDTLS_TLS_DHE_PSK_WITH_ARIA_128_GCM_SHA256, "TLS-DHE-PSK-WITH-ARIA-128-GCM-SHA256", MBEDTLS_CIPHER_ARIA_128_GCM, MBEDTLS_MD_SHA256, MBEDTLS_KEY_EXCHANGE_DHE_PSK, - MBEDTLS_SSL_MAJOR_VERSION_3, MBEDTLS_SSL_MINOR_VERSION_3, - MBEDTLS_SSL_MAJOR_VERSION_3, MBEDTLS_SSL_MINOR_VERSION_3, - 0 }, + 0, + MBEDTLS_SSL_VERSION_TLS1_2, MBEDTLS_SSL_VERSION_TLS1_2 }, #endif -#if (defined(MBEDTLS_CIPHER_MODE_CBC) && defined(MBEDTLS_SHA256_C)) +#if (defined(MBEDTLS_SSL_HAVE_CBC) && \ + defined(MBEDTLS_MD_CAN_SHA256)) { MBEDTLS_TLS_DHE_PSK_WITH_ARIA_128_CBC_SHA256, "TLS-DHE-PSK-WITH-ARIA-128-CBC-SHA256", MBEDTLS_CIPHER_ARIA_128_CBC, MBEDTLS_MD_SHA256, MBEDTLS_KEY_EXCHANGE_DHE_PSK, - MBEDTLS_SSL_MAJOR_VERSION_3, MBEDTLS_SSL_MINOR_VERSION_3, - MBEDTLS_SSL_MAJOR_VERSION_3, MBEDTLS_SSL_MINOR_VERSION_3, - 0 }, + 0, + MBEDTLS_SSL_VERSION_TLS1_2, MBEDTLS_SSL_VERSION_TLS1_2 }, #endif #endif /* MBEDTLS_KEY_EXCHANGE_DHE_PSK_ENABLED */ -#endif /* MBEDTLS_ARIA_C */ +#endif /* MBEDTLS_SSL_HAVE_ARIA */ { 0, "", MBEDTLS_CIPHER_NONE, MBEDTLS_MD_NONE, MBEDTLS_KEY_EXCHANGE_NONE, - 0, 0, 0, 0, 0 } + 0, 0, 0 } }; #if defined(MBEDTLS_SSL_CIPHERSUITES) @@ -2200,19 +1808,6 @@ static int ciphersuite_is_removed(const mbedtls_ssl_ciphersuite_t *cs_info) { (void) cs_info; -#if defined(MBEDTLS_REMOVE_ARC4_CIPHERSUITES) - if (cs_info->cipher == MBEDTLS_CIPHER_ARC4_128) { - return 1; - } -#endif /* MBEDTLS_REMOVE_ARC4_CIPHERSUITES */ - -#if defined(MBEDTLS_REMOVE_3DES_CIPHERSUITES) - if (cs_info->cipher == MBEDTLS_CIPHER_DES_EDE3_ECB || - cs_info->cipher == MBEDTLS_CIPHER_DES_EDE3_CBC) { - return 1; - } -#endif /* MBEDTLS_REMOVE_3DES_CIPHERSUITES */ - return 0; } @@ -2305,6 +1900,31 @@ int mbedtls_ssl_get_ciphersuite_id(const char *ciphersuite_name) return cur->id; } +size_t mbedtls_ssl_ciphersuite_get_cipher_key_bitlen(const mbedtls_ssl_ciphersuite_t *info) +{ +#if defined(MBEDTLS_USE_PSA_CRYPTO) + psa_status_t status = PSA_ERROR_CORRUPTION_DETECTED; + psa_key_type_t key_type; + psa_algorithm_t alg; + size_t key_bits; + + status = mbedtls_ssl_cipher_to_psa((mbedtls_cipher_type_t) info->cipher, + info->flags & MBEDTLS_CIPHERSUITE_SHORT_TAG ? 8 : 16, + &alg, &key_type, &key_bits); + + if (status != PSA_SUCCESS) { + return 0; + } + + return key_bits; +#else + const mbedtls_cipher_info_t * const cipher_info = + mbedtls_cipher_info_from_type((mbedtls_cipher_type_t) info->cipher); + + return mbedtls_cipher_info_get_key_bitlen(cipher_info); +#endif /* MBEDTLS_USE_PSA_CRYPTO */ +} + #if defined(MBEDTLS_PK_C) mbedtls_pk_type_t mbedtls_ssl_get_ciphersuite_sig_pk_alg(const mbedtls_ssl_ciphersuite_t *info) { @@ -2327,10 +1947,54 @@ mbedtls_pk_type_t mbedtls_ssl_get_ciphersuite_sig_pk_alg(const mbedtls_ssl_ciphe } } -mbedtls_pk_type_t mbedtls_ssl_get_ciphersuite_sig_alg(const mbedtls_ssl_ciphersuite_t *info) +#if defined(MBEDTLS_USE_PSA_CRYPTO) +psa_algorithm_t mbedtls_ssl_get_ciphersuite_sig_pk_psa_alg(const mbedtls_ssl_ciphersuite_t *info) { switch (info->key_exchange) { case MBEDTLS_KEY_EXCHANGE_RSA: + case MBEDTLS_KEY_EXCHANGE_RSA_PSK: + return PSA_ALG_RSA_PKCS1V15_CRYPT; + case MBEDTLS_KEY_EXCHANGE_DHE_RSA: + case MBEDTLS_KEY_EXCHANGE_ECDHE_RSA: + return PSA_ALG_RSA_PKCS1V15_SIGN( + mbedtls_md_psa_alg_from_type((mbedtls_md_type_t) info->mac)); + + case MBEDTLS_KEY_EXCHANGE_ECDHE_ECDSA: + return PSA_ALG_ECDSA(mbedtls_md_psa_alg_from_type((mbedtls_md_type_t) info->mac)); + + case MBEDTLS_KEY_EXCHANGE_ECDH_RSA: + case MBEDTLS_KEY_EXCHANGE_ECDH_ECDSA: + return PSA_ALG_ECDH; + + default: + return PSA_ALG_NONE; + } +} + +psa_key_usage_t mbedtls_ssl_get_ciphersuite_sig_pk_psa_usage(const mbedtls_ssl_ciphersuite_t *info) +{ + switch (info->key_exchange) { + case MBEDTLS_KEY_EXCHANGE_RSA: + case MBEDTLS_KEY_EXCHANGE_RSA_PSK: + return PSA_KEY_USAGE_DECRYPT; + case MBEDTLS_KEY_EXCHANGE_DHE_RSA: + case MBEDTLS_KEY_EXCHANGE_ECDHE_RSA: + case MBEDTLS_KEY_EXCHANGE_ECDHE_ECDSA: + return PSA_KEY_USAGE_SIGN_HASH; + + case MBEDTLS_KEY_EXCHANGE_ECDH_RSA: + case MBEDTLS_KEY_EXCHANGE_ECDH_ECDSA: + return PSA_KEY_USAGE_DERIVE; + + default: + return 0; + } +} +#endif /* MBEDTLS_USE_PSA_CRYPTO */ + +mbedtls_pk_type_t mbedtls_ssl_get_ciphersuite_sig_alg(const mbedtls_ssl_ciphersuite_t *info) +{ + switch (info->key_exchange) { case MBEDTLS_KEY_EXCHANGE_DHE_RSA: case MBEDTLS_KEY_EXCHANGE_ECDHE_RSA: return MBEDTLS_PK_RSA; @@ -2345,7 +2009,8 @@ mbedtls_pk_type_t mbedtls_ssl_get_ciphersuite_sig_alg(const mbedtls_ssl_ciphersu #endif /* MBEDTLS_PK_C */ -#if defined(MBEDTLS_ECDH_C) || defined(MBEDTLS_ECDSA_C) || \ +#if defined(MBEDTLS_KEY_EXCHANGE_SOME_ECDH_OR_ECDHE_1_2_ENABLED) || \ + defined(MBEDTLS_KEY_EXCHANGE_ECDSA_CERT_REQ_ALLOWED_ENABLED) || \ defined(MBEDTLS_KEY_EXCHANGE_ECJPAKE_ENABLED) int mbedtls_ssl_ciphersuite_uses_ec(const mbedtls_ssl_ciphersuite_t *info) { @@ -2362,7 +2027,9 @@ int mbedtls_ssl_ciphersuite_uses_ec(const mbedtls_ssl_ciphersuite_t *info) return 0; } } -#endif /* MBEDTLS_ECDH_C || MBEDTLS_ECDSA_C || MBEDTLS_KEY_EXCHANGE_ECJPAKE_ENABLED*/ +#endif /* MBEDTLS_KEY_EXCHANGE_SOME_ECDH_OR_ECDHE_1_2_ENABLED || + * MBEDTLS_KEY_EXCHANGE_ECDSA_CERT_REQ_ALLOWED_ENABLED || + * MBEDTLS_KEY_EXCHANGE_ECJPAKE_ENABLED*/ #if defined(MBEDTLS_KEY_EXCHANGE_SOME_PSK_ENABLED) int mbedtls_ssl_ciphersuite_uses_psk(const mbedtls_ssl_ciphersuite_t *info) diff --git a/vendor/mbedtls/library/ssl_ciphersuites_internal.h b/vendor/mbedtls/library/ssl_ciphersuites_internal.h new file mode 100644 index 0000000000..27ff72106e --- /dev/null +++ b/vendor/mbedtls/library/ssl_ciphersuites_internal.h @@ -0,0 +1,154 @@ +/** + * \file ssl_ciphersuites_internal.h + * + * \brief Internal part of the public "ssl_ciphersuites.h". + */ +/* + * Copyright The Mbed TLS Contributors + * SPDX-License-Identifier: Apache-2.0 OR GPL-2.0-or-later + */ +#ifndef MBEDTLS_SSL_CIPHERSUITES_INTERNAL_H +#define MBEDTLS_SSL_CIPHERSUITES_INTERNAL_H + +#include "mbedtls/pk.h" + +#if defined(MBEDTLS_PK_C) +mbedtls_pk_type_t mbedtls_ssl_get_ciphersuite_sig_pk_alg(const mbedtls_ssl_ciphersuite_t *info); +#if defined(MBEDTLS_USE_PSA_CRYPTO) +psa_algorithm_t mbedtls_ssl_get_ciphersuite_sig_pk_psa_alg(const mbedtls_ssl_ciphersuite_t *info); +psa_key_usage_t mbedtls_ssl_get_ciphersuite_sig_pk_psa_usage(const mbedtls_ssl_ciphersuite_t *info); +#endif /* MBEDTLS_USE_PSA_CRYPTO */ +mbedtls_pk_type_t mbedtls_ssl_get_ciphersuite_sig_alg(const mbedtls_ssl_ciphersuite_t *info); +#endif /* MBEDTLS_PK_C */ + +int mbedtls_ssl_ciphersuite_uses_ec(const mbedtls_ssl_ciphersuite_t *info); +int mbedtls_ssl_ciphersuite_uses_psk(const mbedtls_ssl_ciphersuite_t *info); + +#if defined(MBEDTLS_KEY_EXCHANGE_SOME_PFS_ENABLED) +static inline int mbedtls_ssl_ciphersuite_has_pfs(const mbedtls_ssl_ciphersuite_t *info) +{ + switch (info->MBEDTLS_PRIVATE(key_exchange)) { + case MBEDTLS_KEY_EXCHANGE_DHE_RSA: + case MBEDTLS_KEY_EXCHANGE_DHE_PSK: + case MBEDTLS_KEY_EXCHANGE_ECDHE_RSA: + case MBEDTLS_KEY_EXCHANGE_ECDHE_PSK: + case MBEDTLS_KEY_EXCHANGE_ECDHE_ECDSA: + case MBEDTLS_KEY_EXCHANGE_ECJPAKE: + return 1; + + default: + return 0; + } +} +#endif /* MBEDTLS_KEY_EXCHANGE_SOME_PFS_ENABLED */ + +#if defined(MBEDTLS_KEY_EXCHANGE_SOME_NON_PFS_ENABLED) +static inline int mbedtls_ssl_ciphersuite_no_pfs(const mbedtls_ssl_ciphersuite_t *info) +{ + switch (info->MBEDTLS_PRIVATE(key_exchange)) { + case MBEDTLS_KEY_EXCHANGE_ECDH_RSA: + case MBEDTLS_KEY_EXCHANGE_ECDH_ECDSA: + case MBEDTLS_KEY_EXCHANGE_RSA: + case MBEDTLS_KEY_EXCHANGE_PSK: + case MBEDTLS_KEY_EXCHANGE_RSA_PSK: + return 1; + + default: + return 0; + } +} +#endif /* MBEDTLS_KEY_EXCHANGE_SOME_NON_PFS_ENABLED */ + +#if defined(MBEDTLS_KEY_EXCHANGE_SOME_ECDH_ENABLED) +static inline int mbedtls_ssl_ciphersuite_uses_ecdh(const mbedtls_ssl_ciphersuite_t *info) +{ + switch (info->MBEDTLS_PRIVATE(key_exchange)) { + case MBEDTLS_KEY_EXCHANGE_ECDH_RSA: + case MBEDTLS_KEY_EXCHANGE_ECDH_ECDSA: + return 1; + + default: + return 0; + } +} +#endif /* MBEDTLS_KEY_EXCHANGE_SOME_ECDH_ENABLED */ + +static inline int mbedtls_ssl_ciphersuite_cert_req_allowed(const mbedtls_ssl_ciphersuite_t *info) +{ + switch (info->MBEDTLS_PRIVATE(key_exchange)) { + case MBEDTLS_KEY_EXCHANGE_RSA: + case MBEDTLS_KEY_EXCHANGE_DHE_RSA: + case MBEDTLS_KEY_EXCHANGE_ECDH_RSA: + case MBEDTLS_KEY_EXCHANGE_ECDHE_RSA: + case MBEDTLS_KEY_EXCHANGE_ECDH_ECDSA: + case MBEDTLS_KEY_EXCHANGE_ECDHE_ECDSA: + return 1; + + default: + return 0; + } +} + +static inline int mbedtls_ssl_ciphersuite_uses_srv_cert(const mbedtls_ssl_ciphersuite_t *info) +{ + switch (info->MBEDTLS_PRIVATE(key_exchange)) { + case MBEDTLS_KEY_EXCHANGE_RSA: + case MBEDTLS_KEY_EXCHANGE_RSA_PSK: + case MBEDTLS_KEY_EXCHANGE_DHE_RSA: + case MBEDTLS_KEY_EXCHANGE_ECDH_RSA: + case MBEDTLS_KEY_EXCHANGE_ECDHE_RSA: + case MBEDTLS_KEY_EXCHANGE_ECDH_ECDSA: + case MBEDTLS_KEY_EXCHANGE_ECDHE_ECDSA: + return 1; + + default: + return 0; + } +} + +#if defined(MBEDTLS_KEY_EXCHANGE_SOME_DHE_ENABLED) +static inline int mbedtls_ssl_ciphersuite_uses_dhe(const mbedtls_ssl_ciphersuite_t *info) +{ + switch (info->MBEDTLS_PRIVATE(key_exchange)) { + case MBEDTLS_KEY_EXCHANGE_DHE_RSA: + case MBEDTLS_KEY_EXCHANGE_DHE_PSK: + return 1; + + default: + return 0; + } +} +#endif /* MBEDTLS_KEY_EXCHANGE_SOME_DHE_ENABLED) */ + +#if defined(MBEDTLS_KEY_EXCHANGE_SOME_ECDHE_ENABLED) +static inline int mbedtls_ssl_ciphersuite_uses_ecdhe(const mbedtls_ssl_ciphersuite_t *info) +{ + switch (info->MBEDTLS_PRIVATE(key_exchange)) { + case MBEDTLS_KEY_EXCHANGE_ECDHE_ECDSA: + case MBEDTLS_KEY_EXCHANGE_ECDHE_RSA: + case MBEDTLS_KEY_EXCHANGE_ECDHE_PSK: + return 1; + + default: + return 0; + } +} +#endif /* MBEDTLS_KEY_EXCHANGE_SOME_ECDHE_ENABLED) */ + +#if defined(MBEDTLS_KEY_EXCHANGE_WITH_SERVER_SIGNATURE_ENABLED) +static inline int mbedtls_ssl_ciphersuite_uses_server_signature( + const mbedtls_ssl_ciphersuite_t *info) +{ + switch (info->MBEDTLS_PRIVATE(key_exchange)) { + case MBEDTLS_KEY_EXCHANGE_DHE_RSA: + case MBEDTLS_KEY_EXCHANGE_ECDHE_RSA: + case MBEDTLS_KEY_EXCHANGE_ECDHE_ECDSA: + return 1; + + default: + return 0; + } +} +#endif /* MBEDTLS_KEY_EXCHANGE_WITH_SERVER_SIGNATURE_ENABLED */ + +#endif /* MBEDTLS_SSL_CIPHERSUITES_INTERNAL_H */ diff --git a/vendor/mbedtls/library/ssl_client.c b/vendor/mbedtls/library/ssl_client.c new file mode 100644 index 0000000000..345e608938 --- /dev/null +++ b/vendor/mbedtls/library/ssl_client.c @@ -0,0 +1,1017 @@ +/* + * TLS 1.2 and 1.3 client-side functions + * + * Copyright The Mbed TLS Contributors + * SPDX-License-Identifier: Apache-2.0 OR GPL-2.0-or-later + */ + +#include "common.h" + +#if defined(MBEDTLS_SSL_CLI_C) +#if defined(MBEDTLS_SSL_PROTO_TLS1_3) || defined(MBEDTLS_SSL_PROTO_TLS1_2) + +#include + +#include "debug_internal.h" +#include "mbedtls/error.h" +#include "mbedtls/platform.h" + +#include "ssl_client.h" +#include "ssl_misc.h" +#include "ssl_tls13_keys.h" +#include "ssl_debug_helpers.h" + +#if defined(MBEDTLS_SSL_SERVER_NAME_INDICATION) +MBEDTLS_CHECK_RETURN_CRITICAL +static int ssl_write_hostname_ext(mbedtls_ssl_context *ssl, + unsigned char *buf, + const unsigned char *end, + size_t *olen) +{ + unsigned char *p = buf; + size_t hostname_len; + + *olen = 0; + + if (ssl->hostname == NULL) { + return 0; + } + + MBEDTLS_SSL_DEBUG_MSG(3, + ("client hello, adding server name extension: %s", + ssl->hostname)); + + hostname_len = strlen(ssl->hostname); + + MBEDTLS_SSL_CHK_BUF_PTR(p, end, hostname_len + 9); + + /* + * Sect. 3, RFC 6066 (TLS Extensions Definitions) + * + * In order to provide any of the server names, clients MAY include an + * extension of type "server_name" in the (extended) client hello. The + * "extension_data" field of this extension SHALL contain + * "ServerNameList" where: + * + * struct { + * NameType name_type; + * select (name_type) { + * case host_name: HostName; + * } name; + * } ServerName; + * + * enum { + * host_name(0), (255) + * } NameType; + * + * opaque HostName<1..2^16-1>; + * + * struct { + * ServerName server_name_list<1..2^16-1> + * } ServerNameList; + * + */ + MBEDTLS_PUT_UINT16_BE(MBEDTLS_TLS_EXT_SERVERNAME, p, 0); + p += 2; + + MBEDTLS_PUT_UINT16_BE(hostname_len + 5, p, 0); + p += 2; + + MBEDTLS_PUT_UINT16_BE(hostname_len + 3, p, 0); + p += 2; + + *p++ = MBEDTLS_BYTE_0(MBEDTLS_TLS_EXT_SERVERNAME_HOSTNAME); + + MBEDTLS_PUT_UINT16_BE(hostname_len, p, 0); + p += 2; + + memcpy(p, ssl->hostname, hostname_len); + + *olen = hostname_len + 9; + +#if defined(MBEDTLS_SSL_PROTO_TLS1_3) + mbedtls_ssl_tls13_set_hs_sent_ext_mask(ssl, MBEDTLS_TLS_EXT_SERVERNAME); +#endif /* MBEDTLS_SSL_PROTO_TLS1_3 */ + return 0; +} +#endif /* MBEDTLS_SSL_SERVER_NAME_INDICATION */ + +#if defined(MBEDTLS_SSL_ALPN) +/* + * ssl_write_alpn_ext() + * + * Structure of the application_layer_protocol_negotiation extension in + * ClientHello: + * + * opaque ProtocolName<1..2^8-1>; + * + * struct { + * ProtocolName protocol_name_list<2..2^16-1> + * } ProtocolNameList; + * + */ +MBEDTLS_CHECK_RETURN_CRITICAL +static int ssl_write_alpn_ext(mbedtls_ssl_context *ssl, + unsigned char *buf, + const unsigned char *end, + size_t *out_len) +{ + unsigned char *p = buf; + + *out_len = 0; + + if (ssl->conf->alpn_list == NULL) { + return 0; + } + + MBEDTLS_SSL_DEBUG_MSG(3, ("client hello, adding alpn extension")); + + + /* Check we have enough space for the extension type (2 bytes), the + * extension length (2 bytes) and the protocol_name_list length (2 bytes). + */ + MBEDTLS_SSL_CHK_BUF_PTR(p, end, 6); + MBEDTLS_PUT_UINT16_BE(MBEDTLS_TLS_EXT_ALPN, p, 0); + /* Skip writing extension and list length for now */ + p += 6; + + /* + * opaque ProtocolName<1..2^8-1>; + * + * struct { + * ProtocolName protocol_name_list<2..2^16-1> + * } ProtocolNameList; + */ + for (const char **cur = ssl->conf->alpn_list; *cur != NULL; cur++) { + /* + * mbedtls_ssl_conf_set_alpn_protocols() checked that the length of + * protocol names is less than 255. + */ + size_t protocol_name_len = strlen(*cur); + + MBEDTLS_SSL_CHK_BUF_PTR(p, end, 1 + protocol_name_len); + *p++ = (unsigned char) protocol_name_len; + memcpy(p, *cur, protocol_name_len); + p += protocol_name_len; + } + + *out_len = (size_t) (p - buf); + + /* List length = *out_len - 2 (ext_type) - 2 (ext_len) - 2 (list_len) */ + MBEDTLS_PUT_UINT16_BE(*out_len - 6, buf, 4); + + /* Extension length = *out_len - 2 (ext_type) - 2 (ext_len) */ + MBEDTLS_PUT_UINT16_BE(*out_len - 4, buf, 2); + +#if defined(MBEDTLS_SSL_PROTO_TLS1_3) + mbedtls_ssl_tls13_set_hs_sent_ext_mask(ssl, MBEDTLS_TLS_EXT_ALPN); +#endif /* MBEDTLS_SSL_PROTO_TLS1_3 */ + return 0; +} +#endif /* MBEDTLS_SSL_ALPN */ + +#if defined(MBEDTLS_SSL_TLS1_2_SOME_ECC) || \ + defined(MBEDTLS_SSL_TLS1_3_KEY_EXCHANGE_MODE_SOME_EPHEMERAL_ENABLED) +/* + * Function for writing a supported groups (TLS 1.3) or supported elliptic + * curves (TLS 1.2) extension. + * + * The "extension_data" field of a supported groups extension contains a + * "NamedGroupList" value (TLS 1.3 RFC8446): + * enum { + * secp256r1(0x0017), secp384r1(0x0018), secp521r1(0x0019), + * x25519(0x001D), x448(0x001E), + * ffdhe2048(0x0100), ffdhe3072(0x0101), ffdhe4096(0x0102), + * ffdhe6144(0x0103), ffdhe8192(0x0104), + * ffdhe_private_use(0x01FC..0x01FF), + * ecdhe_private_use(0xFE00..0xFEFF), + * (0xFFFF) + * } NamedGroup; + * struct { + * NamedGroup named_group_list<2..2^16-1>; + * } NamedGroupList; + * + * The "extension_data" field of a supported elliptic curves extension contains + * a "NamedCurveList" value (TLS 1.2 RFC 8422): + * enum { + * deprecated(1..22), + * secp256r1 (23), secp384r1 (24), secp521r1 (25), + * x25519(29), x448(30), + * reserved (0xFE00..0xFEFF), + * deprecated(0xFF01..0xFF02), + * (0xFFFF) + * } NamedCurve; + * struct { + * NamedCurve named_curve_list<2..2^16-1> + * } NamedCurveList; + * + * The TLS 1.3 supported groups extension was defined to be a compatible + * generalization of the TLS 1.2 supported elliptic curves extension. They both + * share the same extension identifier. + * + */ +#define SSL_WRITE_SUPPORTED_GROUPS_EXT_TLS1_2_FLAG 1 +#define SSL_WRITE_SUPPORTED_GROUPS_EXT_TLS1_3_FLAG 2 + +MBEDTLS_CHECK_RETURN_CRITICAL +static int ssl_write_supported_groups_ext(mbedtls_ssl_context *ssl, + unsigned char *buf, + const unsigned char *end, + int flags, + size_t *out_len) +{ + unsigned char *p = buf; + unsigned char *named_group_list; /* Start of named_group_list */ + size_t named_group_list_len; /* Length of named_group_list */ + const uint16_t *group_list = mbedtls_ssl_get_groups(ssl); + + *out_len = 0; + + MBEDTLS_SSL_DEBUG_MSG(3, ("client hello, adding supported_groups extension")); + + /* Check if we have space for header and length fields: + * - extension_type (2 bytes) + * - extension_data_length (2 bytes) + * - named_group_list_length (2 bytes) + */ + MBEDTLS_SSL_CHK_BUF_PTR(p, end, 6); + p += 6; + + named_group_list = p; + + if (group_list == NULL) { + return MBEDTLS_ERR_SSL_BAD_CONFIG; + } + + for (; *group_list != 0; group_list++) { + int propose_group = 0; + + MBEDTLS_SSL_DEBUG_MSG(3, ("got supported group(%04x)", *group_list)); + +#if defined(MBEDTLS_SSL_TLS1_3_KEY_EXCHANGE_MODE_SOME_EPHEMERAL_ENABLED) + if (flags & SSL_WRITE_SUPPORTED_GROUPS_EXT_TLS1_3_FLAG) { +#if defined(PSA_WANT_ALG_ECDH) + if (mbedtls_ssl_tls13_named_group_is_ecdhe(*group_list) && + (mbedtls_ssl_get_ecp_group_id_from_tls_id(*group_list) != + MBEDTLS_ECP_DP_NONE)) { + propose_group = 1; + } +#endif +#if defined(PSA_WANT_ALG_FFDH) + if (mbedtls_ssl_tls13_named_group_is_ffdh(*group_list)) { + propose_group = 1; + } +#endif + } +#endif /* MBEDTLS_SSL_TLS1_3_KEY_EXCHANGE_MODE_SOME_EPHEMERAL_ENABLED */ + +#if defined(MBEDTLS_SSL_TLS1_2_SOME_ECC) + if ((flags & SSL_WRITE_SUPPORTED_GROUPS_EXT_TLS1_2_FLAG) && + mbedtls_ssl_tls12_named_group_is_ecdhe(*group_list) && + (mbedtls_ssl_get_ecp_group_id_from_tls_id(*group_list) != + MBEDTLS_ECP_DP_NONE)) { + propose_group = 1; + } +#endif /* MBEDTLS_SSL_TLS1_2_SOME_ECC */ + + if (propose_group) { + MBEDTLS_SSL_CHK_BUF_PTR(p, end, 2); + MBEDTLS_PUT_UINT16_BE(*group_list, p, 0); + p += 2; + MBEDTLS_SSL_DEBUG_MSG(3, ("NamedGroup: %s ( %x )", + mbedtls_ssl_named_group_to_str(*group_list), + *group_list)); + } + } + + /* Length of named_group_list */ + named_group_list_len = (size_t) (p - named_group_list); + if (named_group_list_len == 0) { + MBEDTLS_SSL_DEBUG_MSG(1, ("No group available.")); + return MBEDTLS_ERR_SSL_INTERNAL_ERROR; + } + + /* Write extension_type */ + MBEDTLS_PUT_UINT16_BE(MBEDTLS_TLS_EXT_SUPPORTED_GROUPS, buf, 0); + /* Write extension_data_length */ + MBEDTLS_PUT_UINT16_BE(named_group_list_len + 2, buf, 2); + /* Write length of named_group_list */ + MBEDTLS_PUT_UINT16_BE(named_group_list_len, buf, 4); + + MBEDTLS_SSL_DEBUG_BUF(3, "Supported groups extension", + buf + 4, named_group_list_len + 2); + + *out_len = (size_t) (p - buf); + +#if defined(MBEDTLS_SSL_PROTO_TLS1_3) + mbedtls_ssl_tls13_set_hs_sent_ext_mask( + ssl, MBEDTLS_TLS_EXT_SUPPORTED_GROUPS); +#endif /* MBEDTLS_SSL_PROTO_TLS1_3 */ + + return 0; +} +#endif /* MBEDTLS_SSL_TLS1_2_SOME_ECC || + MBEDTLS_SSL_TLS1_3_KEY_EXCHANGE_MODE_SOME_EPHEMERAL_ENABLED */ + +MBEDTLS_CHECK_RETURN_CRITICAL +static int ssl_write_client_hello_cipher_suites( + mbedtls_ssl_context *ssl, + unsigned char *buf, + unsigned char *end, + int *tls12_uses_ec, + size_t *out_len) +{ + unsigned char *p = buf; + const int *ciphersuite_list; + unsigned char *cipher_suites; /* Start of the cipher_suites list */ + size_t cipher_suites_len; + + *tls12_uses_ec = 0; + *out_len = 0; + + /* + * Ciphersuite list + * + * This is a list of the symmetric cipher options supported by + * the client, specifically the record protection algorithm + * ( including secret key length ) and a hash to be used with + * HKDF, in descending order of client preference. + */ + ciphersuite_list = ssl->conf->ciphersuite_list; + + /* Check there is space for the cipher suite list length (2 bytes). */ + MBEDTLS_SSL_CHK_BUF_PTR(p, end, 2); + p += 2; + + /* Write cipher_suites + * CipherSuite cipher_suites<2..2^16-2>; + */ + cipher_suites = p; + for (size_t i = 0; ciphersuite_list[i] != 0; i++) { + int cipher_suite = ciphersuite_list[i]; + const mbedtls_ssl_ciphersuite_t *ciphersuite_info; + + ciphersuite_info = mbedtls_ssl_ciphersuite_from_id(cipher_suite); + + if (mbedtls_ssl_validate_ciphersuite(ssl, ciphersuite_info, + ssl->handshake->min_tls_version, + ssl->tls_version) != 0) { + continue; + } + +#if defined(MBEDTLS_SSL_PROTO_TLS1_2) && \ + (defined(MBEDTLS_KEY_EXCHANGE_SOME_ECDH_OR_ECDHE_1_2_ENABLED) || \ + defined(MBEDTLS_KEY_EXCHANGE_ECDSA_CERT_REQ_ALLOWED_ENABLED) || \ + defined(MBEDTLS_KEY_EXCHANGE_ECJPAKE_ENABLED)) + *tls12_uses_ec |= mbedtls_ssl_ciphersuite_uses_ec(ciphersuite_info); +#endif + + MBEDTLS_SSL_DEBUG_MSG(3, ("client hello, add ciphersuite: %04x, %s", + (unsigned int) cipher_suite, + ciphersuite_info->name)); + + /* Check there is space for the cipher suite identifier (2 bytes). */ + MBEDTLS_SSL_CHK_BUF_PTR(p, end, 2); + MBEDTLS_PUT_UINT16_BE(cipher_suite, p, 0); + p += 2; + } + + /* + * Add TLS_EMPTY_RENEGOTIATION_INFO_SCSV + */ + int renegotiating = 0; +#if defined(MBEDTLS_SSL_RENEGOTIATION) + renegotiating = (ssl->renego_status != MBEDTLS_SSL_INITIAL_HANDSHAKE); +#endif + if (!renegotiating) { + MBEDTLS_SSL_DEBUG_MSG(3, ("adding EMPTY_RENEGOTIATION_INFO_SCSV")); + MBEDTLS_SSL_CHK_BUF_PTR(p, end, 2); + MBEDTLS_PUT_UINT16_BE(MBEDTLS_SSL_EMPTY_RENEGOTIATION_INFO, p, 0); + p += 2; + } + + /* Write the cipher_suites length in number of bytes */ + cipher_suites_len = (size_t) (p - cipher_suites); + MBEDTLS_PUT_UINT16_BE(cipher_suites_len, buf, 0); + MBEDTLS_SSL_DEBUG_MSG(3, + ("client hello, got %" MBEDTLS_PRINTF_SIZET " cipher suites", + cipher_suites_len/2)); + + /* Output the total length of cipher_suites field. */ + *out_len = (size_t) (p - buf); + + return 0; +} + +/* + * Structure of the TLS 1.3 ClientHello message: + * + * struct { + * ProtocolVersion legacy_version = 0x0303; // TLS v1.2 + * Random random; + * opaque legacy_session_id<0..32>; + * CipherSuite cipher_suites<2..2^16-2>; + * opaque legacy_compression_methods<1..2^8-1>; + * Extension extensions<8..2^16-1>; + * } ClientHello; + * + * Structure of the (D)TLS 1.2 ClientHello message: + * + * struct { + * ProtocolVersion client_version; + * Random random; + * SessionID session_id; + * opaque cookie<0..2^8-1>; // DTLS 1.2 ONLY + * CipherSuite cipher_suites<2..2^16-2>; + * CompressionMethod compression_methods<1..2^8-1>; + * select (extensions_present) { + * case false: + * struct {}; + * case true: + * Extension extensions<0..2^16-1>; + * }; + * } ClientHello; + */ +MBEDTLS_CHECK_RETURN_CRITICAL +static int ssl_write_client_hello_body(mbedtls_ssl_context *ssl, + unsigned char *buf, + unsigned char *end, + size_t *out_len, + size_t *binders_len) +{ + int ret; + mbedtls_ssl_handshake_params *handshake = ssl->handshake; + unsigned char *p = buf; + unsigned char *p_extensions_len; /* Pointer to extensions length */ + size_t output_len; /* Length of buffer used by function */ + size_t extensions_len; /* Length of the list of extensions*/ + int tls12_uses_ec = 0; + + *out_len = 0; + *binders_len = 0; + +#if defined(MBEDTLS_SSL_PROTO_TLS1_2) + unsigned char propose_tls12 = + (handshake->min_tls_version <= MBEDTLS_SSL_VERSION_TLS1_2) + && + (MBEDTLS_SSL_VERSION_TLS1_2 <= ssl->tls_version); +#endif +#if defined(MBEDTLS_SSL_PROTO_TLS1_3) + unsigned char propose_tls13 = + (handshake->min_tls_version <= MBEDTLS_SSL_VERSION_TLS1_3) + && + (MBEDTLS_SSL_VERSION_TLS1_3 <= ssl->tls_version); +#endif + + /* + * Write client_version (TLS 1.2) or legacy_version (TLS 1.3) + * + * In all cases this is the TLS 1.2 version. + */ + MBEDTLS_SSL_CHK_BUF_PTR(p, end, 2); + mbedtls_ssl_write_version(p, ssl->conf->transport, + MBEDTLS_SSL_VERSION_TLS1_2); + p += 2; + + /* ... + * Random random; + * ... + * + * The random bytes have been prepared by ssl_prepare_client_hello() into + * the handshake->randbytes buffer and are copied here into the output + * buffer. + */ + MBEDTLS_SSL_CHK_BUF_PTR(p, end, MBEDTLS_CLIENT_HELLO_RANDOM_LEN); + memcpy(p, handshake->randbytes, MBEDTLS_CLIENT_HELLO_RANDOM_LEN); + MBEDTLS_SSL_DEBUG_BUF(3, "client hello, random bytes", + p, MBEDTLS_CLIENT_HELLO_RANDOM_LEN); + p += MBEDTLS_CLIENT_HELLO_RANDOM_LEN; + + /* TLS 1.2: + * ... + * SessionID session_id; + * ... + * with + * opaque SessionID<0..32>; + * + * TLS 1.3: + * ... + * opaque legacy_session_id<0..32>; + * ... + * + * The (legacy) session identifier bytes have been prepared by + * ssl_prepare_client_hello() into the ssl->session_negotiate->id buffer + * and are copied here into the output buffer. + */ + MBEDTLS_SSL_CHK_BUF_PTR(p, end, ssl->session_negotiate->id_len + 1); + *p++ = (unsigned char) ssl->session_negotiate->id_len; + memcpy(p, ssl->session_negotiate->id, ssl->session_negotiate->id_len); + p += ssl->session_negotiate->id_len; + + MBEDTLS_SSL_DEBUG_BUF(3, "session id", ssl->session_negotiate->id, + ssl->session_negotiate->id_len); + + /* DTLS 1.2 ONLY + * ... + * opaque cookie<0..2^8-1>; + * ... + */ +#if defined(MBEDTLS_SSL_PROTO_TLS1_2) && defined(MBEDTLS_SSL_PROTO_DTLS) + if (ssl->conf->transport == MBEDTLS_SSL_TRANSPORT_DATAGRAM) { +#if !defined(MBEDTLS_SSL_PROTO_TLS1_3) + uint8_t cookie_len = 0; +#else + uint16_t cookie_len = 0; +#endif /* !MBEDTLS_SSL_PROTO_TLS1_3 */ + + if (handshake->cookie != NULL) { + MBEDTLS_SSL_DEBUG_BUF(3, "client hello, cookie", + handshake->cookie, + handshake->cookie_len); + cookie_len = handshake->cookie_len; + } + + MBEDTLS_SSL_CHK_BUF_PTR(p, end, cookie_len + 1); + *p++ = (unsigned char) cookie_len; + if (cookie_len > 0) { + memcpy(p, handshake->cookie, cookie_len); + p += cookie_len; + } + } +#endif /* MBEDTLS_SSL_PROTO_TLS1_2 && MBEDTLS_SSL_PROTO_DTLS */ + + /* Write cipher_suites */ + ret = ssl_write_client_hello_cipher_suites(ssl, p, end, + &tls12_uses_ec, + &output_len); + if (ret != 0) { + return ret; + } + p += output_len; + + /* Write legacy_compression_methods (TLS 1.3) or + * compression_methods (TLS 1.2) + * + * For every TLS 1.3 ClientHello, this vector MUST contain exactly + * one byte set to zero, which corresponds to the 'null' compression + * method in prior versions of TLS. + * + * For TLS 1.2 ClientHello, for security reasons we do not support + * compression anymore, thus also just the 'null' compression method. + */ + MBEDTLS_SSL_CHK_BUF_PTR(p, end, 2); + *p++ = 1; + *p++ = MBEDTLS_SSL_COMPRESS_NULL; + + /* Write extensions */ + +#if defined(MBEDTLS_SSL_PROTO_TLS1_3) + /* Keeping track of the included extensions */ + handshake->sent_extensions = MBEDTLS_SSL_EXT_MASK_NONE; +#endif + + /* First write extensions, then the total length */ + MBEDTLS_SSL_CHK_BUF_PTR(p, end, 2); + p_extensions_len = p; + p += 2; + +#if defined(MBEDTLS_SSL_SERVER_NAME_INDICATION) + /* Write server name extension */ + ret = ssl_write_hostname_ext(ssl, p, end, &output_len); + if (ret != 0) { + return ret; + } + p += output_len; +#endif /* MBEDTLS_SSL_SERVER_NAME_INDICATION */ + +#if defined(MBEDTLS_SSL_ALPN) + ret = ssl_write_alpn_ext(ssl, p, end, &output_len); + if (ret != 0) { + return ret; + } + p += output_len; +#endif /* MBEDTLS_SSL_ALPN */ + +#if defined(MBEDTLS_SSL_PROTO_TLS1_3) + if (propose_tls13) { + ret = mbedtls_ssl_tls13_write_client_hello_exts(ssl, p, end, + &output_len); + if (ret != 0) { + return ret; + } + p += output_len; + } +#endif + +#if defined(MBEDTLS_SSL_TLS1_2_SOME_ECC) || \ + defined(MBEDTLS_SSL_TLS1_3_KEY_EXCHANGE_MODE_SOME_EPHEMERAL_ENABLED) + { + int ssl_write_supported_groups_ext_flags = 0; + +#if defined(MBEDTLS_SSL_TLS1_3_KEY_EXCHANGE_MODE_SOME_EPHEMERAL_ENABLED) + if (propose_tls13 && mbedtls_ssl_conf_tls13_is_some_ephemeral_enabled(ssl)) { + ssl_write_supported_groups_ext_flags |= + SSL_WRITE_SUPPORTED_GROUPS_EXT_TLS1_3_FLAG; + } +#endif +#if defined(MBEDTLS_SSL_TLS1_2_SOME_ECC) + if (propose_tls12 && tls12_uses_ec) { + ssl_write_supported_groups_ext_flags |= + SSL_WRITE_SUPPORTED_GROUPS_EXT_TLS1_2_FLAG; + } +#endif + if (ssl_write_supported_groups_ext_flags != 0) { + ret = ssl_write_supported_groups_ext(ssl, p, end, + ssl_write_supported_groups_ext_flags, + &output_len); + if (ret != 0) { + return ret; + } + p += output_len; + } + } +#endif /* MBEDTLS_SSL_TLS1_2_SOME_ECC || + MBEDTLS_SSL_TLS1_3_KEY_EXCHANGE_MODE_SOME_EPHEMERAL_ENABLED */ + +#if defined(MBEDTLS_SSL_HANDSHAKE_WITH_CERT_ENABLED) + int write_sig_alg_ext = 0; +#if defined(MBEDTLS_SSL_PROTO_TLS1_3) + write_sig_alg_ext = write_sig_alg_ext || + (propose_tls13 && mbedtls_ssl_conf_tls13_is_ephemeral_enabled(ssl)); +#endif +#if defined(MBEDTLS_SSL_PROTO_TLS1_2) + write_sig_alg_ext = write_sig_alg_ext || propose_tls12; +#endif + + if (write_sig_alg_ext) { + ret = mbedtls_ssl_write_sig_alg_ext(ssl, p, end, &output_len); + if (ret != 0) { + return ret; + } + p += output_len; + } +#endif /* MBEDTLS_SSL_HANDSHAKE_WITH_CERT_ENABLED */ + +#if defined(MBEDTLS_SSL_PROTO_TLS1_2) + if (propose_tls12) { + ret = mbedtls_ssl_tls12_write_client_hello_exts(ssl, p, end, + tls12_uses_ec, + &output_len); + if (ret != 0) { + return ret; + } + p += output_len; + } +#endif /* MBEDTLS_SSL_PROTO_TLS1_2 */ + +#if defined(MBEDTLS_SSL_TLS1_3_KEY_EXCHANGE_MODE_SOME_PSK_ENABLED) + /* The "pre_shared_key" extension (RFC 8446 Section 4.2.11) + * MUST be the last extension in the ClientHello. + */ + if (propose_tls13 && mbedtls_ssl_conf_tls13_is_some_psk_enabled(ssl)) { + ret = mbedtls_ssl_tls13_write_identities_of_pre_shared_key_ext( + ssl, p, end, &output_len, binders_len); + if (ret != 0) { + return ret; + } + p += output_len; + } +#endif /* MBEDTLS_SSL_TLS1_3_KEY_EXCHANGE_MODE_SOME_PSK_ENABLED */ + + /* Write the length of the list of extensions. */ + extensions_len = (size_t) (p - p_extensions_len) - 2; + + if (extensions_len == 0) { + p = p_extensions_len; + } else { + MBEDTLS_PUT_UINT16_BE(extensions_len, p_extensions_len, 0); + MBEDTLS_SSL_DEBUG_MSG(3, ("client hello, total extension length: %" \ + MBEDTLS_PRINTF_SIZET, extensions_len)); + MBEDTLS_SSL_DEBUG_BUF(3, "client hello extensions", + p_extensions_len, extensions_len); + } + + *out_len = (size_t) (p - buf); + return 0; +} + +MBEDTLS_CHECK_RETURN_CRITICAL +static int ssl_generate_random(mbedtls_ssl_context *ssl) +{ + int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED; + unsigned char *randbytes = ssl->handshake->randbytes; + size_t gmt_unix_time_len = 0; + + /* + * Generate the random bytes + * + * TLS 1.2 case: + * struct { + * uint32 gmt_unix_time; + * opaque random_bytes[28]; + * } Random; + * + * TLS 1.3 case: + * opaque Random[32]; + */ + if (ssl->tls_version == MBEDTLS_SSL_VERSION_TLS1_2) { +#if defined(MBEDTLS_HAVE_TIME) + mbedtls_time_t gmt_unix_time = mbedtls_time(NULL); + MBEDTLS_PUT_UINT32_BE(gmt_unix_time, randbytes, 0); + gmt_unix_time_len = 4; + + MBEDTLS_SSL_DEBUG_MSG(3, + ("client hello, current time: %" MBEDTLS_PRINTF_LONGLONG, + (long long) gmt_unix_time)); +#endif /* MBEDTLS_HAVE_TIME */ + } + + ret = ssl->conf->f_rng(ssl->conf->p_rng, + randbytes + gmt_unix_time_len, + MBEDTLS_CLIENT_HELLO_RANDOM_LEN - gmt_unix_time_len); + return ret; +} + +MBEDTLS_CHECK_RETURN_CRITICAL +static int ssl_prepare_client_hello(mbedtls_ssl_context *ssl) +{ + int ret; + size_t session_id_len; + mbedtls_ssl_session *session_negotiate = ssl->session_negotiate; + + if (session_negotiate == NULL) { + return MBEDTLS_ERR_SSL_INTERNAL_ERROR; + } + +#if defined(MBEDTLS_SSL_PROTO_TLS1_3) && \ + defined(MBEDTLS_SSL_SESSION_TICKETS) && \ + defined(MBEDTLS_HAVE_TIME) + + /* Check if a tls13 ticket has been configured. */ + if (ssl->handshake->resume != 0 && + session_negotiate->tls_version == MBEDTLS_SSL_VERSION_TLS1_3 && + session_negotiate->ticket != NULL) { + mbedtls_ms_time_t now = mbedtls_ms_time(); + mbedtls_ms_time_t age = now - session_negotiate->ticket_reception_time; + if (age < 0 || + age > (mbedtls_ms_time_t) session_negotiate->ticket_lifetime * 1000) { + /* Without valid ticket, disable session resumption.*/ + MBEDTLS_SSL_DEBUG_MSG( + 3, ("Ticket expired, disable session resumption")); + ssl->handshake->resume = 0; + } + } +#endif /* MBEDTLS_SSL_PROTO_TLS1_3 && + MBEDTLS_SSL_SESSION_TICKETS && + MBEDTLS_HAVE_TIME */ + + /* Bet on the highest configured version if we are not in a TLS 1.2 + * renegotiation or session resumption. + */ +#if defined(MBEDTLS_SSL_RENEGOTIATION) + if (ssl->renego_status != MBEDTLS_SSL_INITIAL_HANDSHAKE) { + ssl->handshake->min_tls_version = ssl->tls_version; + } else +#endif + { + if (ssl->handshake->resume) { + ssl->tls_version = session_negotiate->tls_version; + ssl->handshake->min_tls_version = ssl->tls_version; + } else { + ssl->handshake->min_tls_version = ssl->conf->min_tls_version; + } + } + + /* + * Generate the random bytes, except when responding to a verify request + * where we MUST reuse the previously generated random bytes + * (RFC 6347 4.2.1). + */ +#if defined(MBEDTLS_SSL_PROTO_DTLS) + if ((ssl->conf->transport != MBEDTLS_SSL_TRANSPORT_DATAGRAM) || + (ssl->handshake->cookie == NULL)) +#endif + { +#if defined(MBEDTLS_SSL_PROTO_TLS1_3) + if (!ssl->handshake->hello_retry_request_flag) +#endif + { + ret = ssl_generate_random(ssl); + if (ret != 0) { + MBEDTLS_SSL_DEBUG_RET(1, "Random bytes generation failed", ret); + return ret; + } + } + } + + /* + * Prepare session identifier. At that point, the length of the session + * identifier in the SSL context `ssl->session_negotiate->id_len` is equal + * to zero, except in the case of a TLS 1.2 session renegotiation or + * session resumption. + */ + session_id_len = session_negotiate->id_len; + +#if defined(MBEDTLS_SSL_PROTO_TLS1_2) + if (ssl->tls_version == MBEDTLS_SSL_VERSION_TLS1_2) { + if (session_id_len < 16 || session_id_len > 32 || +#if defined(MBEDTLS_SSL_RENEGOTIATION) + ssl->renego_status != MBEDTLS_SSL_INITIAL_HANDSHAKE || +#endif + ssl->handshake->resume == 0) { + session_id_len = 0; + } + +#if defined(MBEDTLS_SSL_SESSION_TICKETS) + /* + * RFC 5077 section 3.4: "When presenting a ticket, the client MAY + * generate and include a Session ID in the TLS ClientHello." + */ + int renegotiating = 0; +#if defined(MBEDTLS_SSL_RENEGOTIATION) + if (ssl->renego_status != MBEDTLS_SSL_INITIAL_HANDSHAKE) { + renegotiating = 1; + } +#endif + if (!renegotiating) { + if ((session_negotiate->ticket != NULL) && + (session_negotiate->ticket_len != 0)) { + session_id_len = 32; + } + } +#endif /* MBEDTLS_SSL_SESSION_TICKETS */ + } +#endif /* MBEDTLS_SSL_PROTO_TLS1_2 */ + +#if defined(MBEDTLS_SSL_TLS1_3_COMPATIBILITY_MODE) + if (ssl->tls_version == MBEDTLS_SSL_VERSION_TLS1_3) { + /* + * Create a legacy session identifier for the purpose of middlebox + * compatibility only if one has not been created already, which is + * the case if we are here for the TLS 1.3 second ClientHello. + * + * Versions of TLS before TLS 1.3 supported a "session resumption" + * feature which has been merged with pre-shared keys in TLS 1.3 + * version. A client which has a cached session ID set by a pre-TLS 1.3 + * server SHOULD set this field to that value. In compatibility mode, + * this field MUST be non-empty, so a client not offering a pre-TLS 1.3 + * session MUST generate a new 32-byte value. This value need not be + * random but SHOULD be unpredictable to avoid implementations fixating + * on a specific value (also known as ossification). Otherwise, it MUST + * be set as a zero-length vector ( i.e., a zero-valued single byte + * length field ). + */ + session_id_len = 32; + } +#endif /* MBEDTLS_SSL_TLS1_3_COMPATIBILITY_MODE */ + + if (session_id_len != session_negotiate->id_len) { + session_negotiate->id_len = session_id_len; + if (session_id_len > 0) { + ret = ssl->conf->f_rng(ssl->conf->p_rng, + session_negotiate->id, + session_id_len); + if (ret != 0) { + MBEDTLS_SSL_DEBUG_RET(1, "creating session id failed", ret); + return ret; + } + } + } + +#if defined(MBEDTLS_SSL_PROTO_TLS1_3) && \ + defined(MBEDTLS_SSL_SESSION_TICKETS) && \ + defined(MBEDTLS_SSL_SERVER_NAME_INDICATION) + if (ssl->tls_version == MBEDTLS_SSL_VERSION_TLS1_3 && + ssl->handshake->resume) { + int hostname_mismatch = ssl->hostname != NULL || + session_negotiate->hostname != NULL; + if (ssl->hostname != NULL && session_negotiate->hostname != NULL) { + hostname_mismatch = strcmp( + ssl->hostname, session_negotiate->hostname) != 0; + } + + if (hostname_mismatch) { + MBEDTLS_SSL_DEBUG_MSG( + 1, ("Hostname mismatch the session ticket, " + "disable session resumption.")); + return MBEDTLS_ERR_SSL_BAD_INPUT_DATA; + } + } else { + return mbedtls_ssl_session_set_hostname(session_negotiate, + ssl->hostname); + } +#endif /* MBEDTLS_SSL_PROTO_TLS1_3 && + MBEDTLS_SSL_SESSION_TICKETS && + MBEDTLS_SSL_SERVER_NAME_INDICATION */ + + return 0; +} +/* + * Write ClientHello handshake message. + * Handler for MBEDTLS_SSL_CLIENT_HELLO + */ +int mbedtls_ssl_write_client_hello(mbedtls_ssl_context *ssl) +{ + int ret = 0; + unsigned char *buf; + size_t buf_len, msg_len, binders_len; + + MBEDTLS_SSL_DEBUG_MSG(2, ("=> write client hello")); + + MBEDTLS_SSL_PROC_CHK(ssl_prepare_client_hello(ssl)); + + MBEDTLS_SSL_PROC_CHK(mbedtls_ssl_start_handshake_msg( + ssl, MBEDTLS_SSL_HS_CLIENT_HELLO, + &buf, &buf_len)); + + MBEDTLS_SSL_PROC_CHK(ssl_write_client_hello_body(ssl, buf, + buf + buf_len, + &msg_len, + &binders_len)); + +#if defined(MBEDTLS_SSL_PROTO_TLS1_2) && defined(MBEDTLS_SSL_PROTO_DTLS) + if (ssl->conf->transport == MBEDTLS_SSL_TRANSPORT_DATAGRAM) { + ssl->out_msglen = msg_len + 4; + mbedtls_ssl_send_flight_completed(ssl); + + /* + * The two functions below may try to send data on the network and + * can return with the MBEDTLS_ERR_SSL_WANT_READ error code when they + * fail to do so and the transmission has to be retried later. In that + * case as in fatal error cases, we return immediately. But we must have + * set the handshake state to the next state at that point to ensure + * that we will not write and send again a ClientHello when we + * eventually succeed in sending the pending data. + */ + mbedtls_ssl_handshake_set_state(ssl, MBEDTLS_SSL_SERVER_HELLO); + + if ((ret = mbedtls_ssl_write_handshake_msg(ssl)) != 0) { + MBEDTLS_SSL_DEBUG_RET(1, "mbedtls_ssl_write_handshake_msg", ret); + return ret; + } + + if ((ret = mbedtls_ssl_flight_transmit(ssl)) != 0) { + MBEDTLS_SSL_DEBUG_RET(1, "mbedtls_ssl_flight_transmit", ret); + return ret; + } + } else +#endif /* MBEDTLS_SSL_PROTO_TLS1_2 && MBEDTLS_SSL_PROTO_DTLS */ + { + + ret = mbedtls_ssl_add_hs_hdr_to_checksum(ssl, + MBEDTLS_SSL_HS_CLIENT_HELLO, + msg_len); + if (ret != 0) { + MBEDTLS_SSL_DEBUG_RET(1, "mbedtls_ssl_add_hs_hdr_to_checksum", ret); + return ret; + } + ret = ssl->handshake->update_checksum(ssl, buf, msg_len - binders_len); + if (ret != 0) { + MBEDTLS_SSL_DEBUG_RET(1, "update_checksum", ret); + return ret; + } +#if defined(MBEDTLS_SSL_TLS1_3_KEY_EXCHANGE_MODE_SOME_PSK_ENABLED) + if (binders_len > 0) { + MBEDTLS_SSL_PROC_CHK( + mbedtls_ssl_tls13_write_binders_of_pre_shared_key_ext( + ssl, buf + msg_len - binders_len, buf + msg_len)); + ret = ssl->handshake->update_checksum(ssl, buf + msg_len - binders_len, + binders_len); + if (ret != 0) { + MBEDTLS_SSL_DEBUG_RET(1, "update_checksum", ret); + return ret; + } + } +#endif /* MBEDTLS_SSL_TLS1_3_KEY_EXCHANGE_MODE_SOME_PSK_ENABLED */ + + MBEDTLS_SSL_PROC_CHK(mbedtls_ssl_finish_handshake_msg(ssl, + buf_len, + msg_len)); + + /* + * Set next state. Note that if TLS 1.3 is proposed, this may be + * overwritten by mbedtls_ssl_tls13_finalize_client_hello(). + */ + mbedtls_ssl_handshake_set_state(ssl, MBEDTLS_SSL_SERVER_HELLO); + +#if defined(MBEDTLS_SSL_PROTO_TLS1_3) + if (ssl->handshake->min_tls_version <= MBEDTLS_SSL_VERSION_TLS1_3 && + MBEDTLS_SSL_VERSION_TLS1_3 <= ssl->tls_version) { + ret = mbedtls_ssl_tls13_finalize_client_hello(ssl); + } +#endif + } + +#if defined(MBEDTLS_SSL_PROTO_TLS1_3) + MBEDTLS_SSL_PRINT_EXTS( + 3, MBEDTLS_SSL_HS_CLIENT_HELLO, ssl->handshake->sent_extensions); +#endif + +cleanup: + + MBEDTLS_SSL_DEBUG_MSG(2, ("<= write client hello")); + return ret; +} + +#endif /* MBEDTLS_SSL_PROTO_TLS1_3 || MBEDTLS_SSL_PROTO_TLS1_2 */ +#endif /* MBEDTLS_SSL_CLI_C */ diff --git a/vendor/mbedtls/library/ssl_client.h b/vendor/mbedtls/library/ssl_client.h new file mode 100644 index 0000000000..05ee7e4cc3 --- /dev/null +++ b/vendor/mbedtls/library/ssl_client.h @@ -0,0 +1,22 @@ +/** + * TLS 1.2 and 1.3 client-side functions + * + * Copyright The Mbed TLS Contributors + * SPDX-License-Identifier: Apache-2.0 OR GPL-2.0-or-later + */ + +#ifndef MBEDTLS_SSL_CLIENT_H +#define MBEDTLS_SSL_CLIENT_H + +#include "common.h" + +#if defined(MBEDTLS_SSL_TLS_C) +#include "ssl_misc.h" +#endif + +#include + +MBEDTLS_CHECK_RETURN_CRITICAL +int mbedtls_ssl_write_client_hello(mbedtls_ssl_context *ssl); + +#endif /* MBEDTLS_SSL_CLIENT_H */ diff --git a/vendor/mbedtls/library/ssl_cookie.c b/vendor/mbedtls/library/ssl_cookie.c index 1ac9c41760..2772cac4be 100644 --- a/vendor/mbedtls/library/ssl_cookie.c +++ b/vendor/mbedtls/library/ssl_cookie.c @@ -2,19 +2,7 @@ * DTLS cookie callbacks implementation * * Copyright The Mbed TLS Contributors - * SPDX-License-Identifier: Apache-2.0 - * - * Licensed under the Apache License, Version 2.0 (the "License"); you may - * not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT - * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. + * SPDX-License-Identifier: Apache-2.0 OR GPL-2.0-or-later */ /* * These session callbacks use a simple chained list @@ -28,32 +16,40 @@ #include "mbedtls/platform.h" #include "mbedtls/ssl_cookie.h" -#include "mbedtls/ssl_internal.h" +#include "ssl_misc.h" #include "mbedtls/error.h" #include "mbedtls/platform_util.h" #include "mbedtls/constant_time.h" #include +#if defined(MBEDTLS_USE_PSA_CRYPTO) +#include "mbedtls/psa_util.h" +/* Define a local translating function to save code size by not using too many + * arguments in each translating place. */ +static int local_err_translation(psa_status_t status) +{ + return psa_status_to_mbedtls(status, psa_to_ssl_errors, + ARRAY_LENGTH(psa_to_ssl_errors), + psa_generic_status_to_mbedtls); +} +#define PSA_TO_MBEDTLS_ERR(status) local_err_translation(status) +#endif + /* - * If DTLS is in use, then at least one of SHA-1, SHA-256, SHA-512 is - * available. Try SHA-256 first, 512 wastes resources since we need to stay - * with max 32 bytes of cookie for DTLS 1.0 + * If DTLS is in use, then at least one of SHA-256 or SHA-384 is + * available. Try SHA-256 first as 384 wastes resources */ -#if defined(MBEDTLS_SHA256_C) -#define COOKIE_MD MBEDTLS_MD_SHA224 +#if defined(MBEDTLS_MD_CAN_SHA256) +#define COOKIE_MD MBEDTLS_MD_SHA256 #define COOKIE_MD_OUTLEN 32 #define COOKIE_HMAC_LEN 28 -#elif defined(MBEDTLS_SHA512_C) +#elif defined(MBEDTLS_MD_CAN_SHA384) #define COOKIE_MD MBEDTLS_MD_SHA384 #define COOKIE_MD_OUTLEN 48 #define COOKIE_HMAC_LEN 28 -#elif defined(MBEDTLS_SHA1_C) -#define COOKIE_MD MBEDTLS_MD_SHA1 -#define COOKIE_MD_OUTLEN 20 -#define COOKIE_HMAC_LEN 20 #else -#error "DTLS hello verify needs SHA-1 or SHA-2" +#error "DTLS hello verify needs SHA-256 or SHA-384" #endif /* @@ -64,15 +60,21 @@ void mbedtls_ssl_cookie_init(mbedtls_ssl_cookie_ctx *ctx) { +#if defined(MBEDTLS_USE_PSA_CRYPTO) + ctx->psa_hmac_key = MBEDTLS_SVC_KEY_ID_INIT; +#else mbedtls_md_init(&ctx->hmac_ctx); +#endif /* MBEDTLS_USE_PSA_CRYPTO */ #if !defined(MBEDTLS_HAVE_TIME) ctx->serial = 0; #endif ctx->timeout = MBEDTLS_SSL_COOKIE_TIMEOUT; +#if !defined(MBEDTLS_USE_PSA_CRYPTO) #if defined(MBEDTLS_THREADING_C) mbedtls_mutex_init(&ctx->mutex); #endif +#endif /* !MBEDTLS_USE_PSA_CRYPTO */ } void mbedtls_ssl_cookie_set_timeout(mbedtls_ssl_cookie_ctx *ctx, unsigned long delay) @@ -82,11 +84,15 @@ void mbedtls_ssl_cookie_set_timeout(mbedtls_ssl_cookie_ctx *ctx, unsigned long d void mbedtls_ssl_cookie_free(mbedtls_ssl_cookie_ctx *ctx) { +#if defined(MBEDTLS_USE_PSA_CRYPTO) + psa_destroy_key(ctx->psa_hmac_key); +#else mbedtls_md_free(&ctx->hmac_ctx); #if defined(MBEDTLS_THREADING_C) mbedtls_mutex_free(&ctx->mutex); #endif +#endif /* MBEDTLS_USE_PSA_CRYPTO */ mbedtls_platform_zeroize(ctx, sizeof(mbedtls_ssl_cookie_ctx)); } @@ -95,6 +101,33 @@ int mbedtls_ssl_cookie_setup(mbedtls_ssl_cookie_ctx *ctx, int (*f_rng)(void *, unsigned char *, size_t), void *p_rng) { +#if defined(MBEDTLS_USE_PSA_CRYPTO) + psa_key_attributes_t attributes = PSA_KEY_ATTRIBUTES_INIT; + psa_status_t status = PSA_ERROR_CORRUPTION_DETECTED; + psa_algorithm_t alg; + + (void) f_rng; + (void) p_rng; + + alg = mbedtls_md_psa_alg_from_type(COOKIE_MD); + if (alg == 0) { + return MBEDTLS_ERR_SSL_BAD_INPUT_DATA; + } + + ctx->psa_hmac_alg = PSA_ALG_TRUNCATED_MAC(PSA_ALG_HMAC(alg), + COOKIE_HMAC_LEN); + + psa_set_key_usage_flags(&attributes, PSA_KEY_USAGE_VERIFY_MESSAGE | + PSA_KEY_USAGE_SIGN_MESSAGE); + psa_set_key_algorithm(&attributes, ctx->psa_hmac_alg); + psa_set_key_type(&attributes, PSA_KEY_TYPE_HMAC); + psa_set_key_bits(&attributes, PSA_BYTES_TO_BITS(COOKIE_MD_OUTLEN)); + + if ((status = psa_generate_key(&attributes, + &ctx->psa_hmac_key)) != PSA_SUCCESS) { + return PSA_TO_MBEDTLS_ERR(status); + } +#else int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED; unsigned char key[COOKIE_MD_OUTLEN]; @@ -113,10 +146,12 @@ int mbedtls_ssl_cookie_setup(mbedtls_ssl_cookie_ctx *ctx, } mbedtls_platform_zeroize(key, sizeof(key)); +#endif /* MBEDTLS_USE_PSA_CRYPTO */ return 0; } +#if !defined(MBEDTLS_USE_PSA_CRYPTO) /* * Generate the HMAC part of a cookie */ @@ -142,6 +177,7 @@ static int ssl_cookie_hmac(mbedtls_md_context_t *hmac_ctx, return 0; } +#endif /* !MBEDTLS_USE_PSA_CRYPTO */ /* * Generate cookie for DTLS ClientHello verification @@ -150,6 +186,11 @@ int mbedtls_ssl_cookie_write(void *p_ctx, unsigned char **p, unsigned char *end, const unsigned char *cli_id, size_t cli_id_len) { +#if defined(MBEDTLS_USE_PSA_CRYPTO) + psa_mac_operation_t operation = PSA_MAC_OPERATION_INIT; + psa_status_t status = PSA_ERROR_CORRUPTION_DETECTED; + size_t sign_mac_length = 0; +#endif int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED; mbedtls_ssl_cookie_ctx *ctx = (mbedtls_ssl_cookie_ctx *) p_ctx; unsigned long t; @@ -169,6 +210,37 @@ int mbedtls_ssl_cookie_write(void *p_ctx, MBEDTLS_PUT_UINT32_BE(t, *p, 0); *p += 4; +#if defined(MBEDTLS_USE_PSA_CRYPTO) + status = psa_mac_sign_setup(&operation, ctx->psa_hmac_key, + ctx->psa_hmac_alg); + if (status != PSA_SUCCESS) { + ret = PSA_TO_MBEDTLS_ERR(status); + goto exit; + } + + status = psa_mac_update(&operation, *p - 4, 4); + if (status != PSA_SUCCESS) { + ret = PSA_TO_MBEDTLS_ERR(status); + goto exit; + } + + status = psa_mac_update(&operation, cli_id, cli_id_len); + if (status != PSA_SUCCESS) { + ret = PSA_TO_MBEDTLS_ERR(status); + goto exit; + } + + status = psa_mac_sign_finish(&operation, *p, COOKIE_MD_OUTLEN, + &sign_mac_length); + if (status != PSA_SUCCESS) { + ret = PSA_TO_MBEDTLS_ERR(status); + goto exit; + } + + *p += COOKIE_HMAC_LEN; + + ret = 0; +#else #if defined(MBEDTLS_THREADING_C) if ((ret = mbedtls_mutex_lock(&ctx->mutex)) != 0) { return MBEDTLS_ERROR_ADD(MBEDTLS_ERR_SSL_INTERNAL_ERROR, ret); @@ -184,7 +256,15 @@ int mbedtls_ssl_cookie_write(void *p_ctx, MBEDTLS_ERR_THREADING_MUTEX_ERROR); } #endif +#endif /* MBEDTLS_USE_PSA_CRYPTO */ +#if defined(MBEDTLS_USE_PSA_CRYPTO) +exit: + status = psa_mac_abort(&operation); + if (status != PSA_SUCCESS) { + ret = PSA_TO_MBEDTLS_ERR(status); + } +#endif /* MBEDTLS_USE_PSA_CRYPTO */ return ret; } @@ -195,9 +275,14 @@ int mbedtls_ssl_cookie_check(void *p_ctx, const unsigned char *cookie, size_t cookie_len, const unsigned char *cli_id, size_t cli_id_len) { +#if defined(MBEDTLS_USE_PSA_CRYPTO) + psa_mac_operation_t operation = PSA_MAC_OPERATION_INIT; + psa_status_t status = PSA_ERROR_CORRUPTION_DETECTED; +#else unsigned char ref_hmac[COOKIE_HMAC_LEN]; - int ret = 0; unsigned char *p = ref_hmac; +#endif + int ret = 0; mbedtls_ssl_cookie_ctx *ctx = (mbedtls_ssl_cookie_ctx *) p_ctx; unsigned long cur_time, cookie_time; @@ -209,6 +294,36 @@ int mbedtls_ssl_cookie_check(void *p_ctx, return -1; } +#if defined(MBEDTLS_USE_PSA_CRYPTO) + status = psa_mac_verify_setup(&operation, ctx->psa_hmac_key, + ctx->psa_hmac_alg); + if (status != PSA_SUCCESS) { + ret = PSA_TO_MBEDTLS_ERR(status); + goto exit; + } + + status = psa_mac_update(&operation, cookie, 4); + if (status != PSA_SUCCESS) { + ret = PSA_TO_MBEDTLS_ERR(status); + goto exit; + } + + status = psa_mac_update(&operation, cli_id, + cli_id_len); + if (status != PSA_SUCCESS) { + ret = PSA_TO_MBEDTLS_ERR(status); + goto exit; + } + + status = psa_mac_verify_finish(&operation, cookie + 4, + COOKIE_HMAC_LEN); + if (status != PSA_SUCCESS) { + ret = PSA_TO_MBEDTLS_ERR(status); + goto exit; + } + + ret = 0; +#else #if defined(MBEDTLS_THREADING_C) if ((ret = mbedtls_mutex_lock(&ctx->mutex)) != 0) { return MBEDTLS_ERROR_ADD(MBEDTLS_ERR_SSL_INTERNAL_ERROR, ret); @@ -236,6 +351,7 @@ int mbedtls_ssl_cookie_check(void *p_ctx, ret = -1; goto exit; } +#endif /* MBEDTLS_USE_PSA_CRYPTO */ #if defined(MBEDTLS_HAVE_TIME) cur_time = (unsigned long) mbedtls_time(NULL); @@ -243,10 +359,7 @@ int mbedtls_ssl_cookie_check(void *p_ctx, cur_time = ctx->serial; #endif - cookie_time = ((unsigned long) cookie[0] << 24) | - ((unsigned long) cookie[1] << 16) | - ((unsigned long) cookie[2] << 8) | - ((unsigned long) cookie[3]); + cookie_time = (unsigned long) MBEDTLS_GET_UINT32_BE(cookie, 0); if (ctx->timeout != 0 && cur_time - cookie_time > ctx->timeout) { ret = -1; @@ -254,7 +367,14 @@ int mbedtls_ssl_cookie_check(void *p_ctx, } exit: +#if defined(MBEDTLS_USE_PSA_CRYPTO) + status = psa_mac_abort(&operation); + if (status != PSA_SUCCESS) { + ret = PSA_TO_MBEDTLS_ERR(status); + } +#else mbedtls_platform_zeroize(ref_hmac, sizeof(ref_hmac)); +#endif /* MBEDTLS_USE_PSA_CRYPTO */ return ret; } #endif /* MBEDTLS_SSL_COOKIE_C */ diff --git a/vendor/mbedtls/library/ssl_debug_helpers.h b/vendor/mbedtls/library/ssl_debug_helpers.h new file mode 100644 index 0000000000..4889e77e04 --- /dev/null +++ b/vendor/mbedtls/library/ssl_debug_helpers.h @@ -0,0 +1,83 @@ +/** + * \file ssl_debug_helpers.h + * + * \brief Automatically generated helper functions for debugging + */ +/* + * Copyright The Mbed TLS Contributors + * SPDX-License-Identifier: Apache-2.0 OR GPL-2.0-or-later + */ + +#ifndef MBEDTLS_SSL_DEBUG_HELPERS_H +#define MBEDTLS_SSL_DEBUG_HELPERS_H + +#include "common.h" + +#if defined(MBEDTLS_DEBUG_C) + +#include "mbedtls/ssl.h" +#include "ssl_misc.h" + + +const char *mbedtls_ssl_states_str(mbedtls_ssl_states in); + +#if defined(MBEDTLS_SSL_EARLY_DATA) && defined(MBEDTLS_SSL_CLI_C) +const char *mbedtls_ssl_early_data_status_str(mbedtls_ssl_early_data_status in); +const char *mbedtls_ssl_early_data_state_str(mbedtls_ssl_early_data_state in); +#endif + +const char *mbedtls_ssl_protocol_version_str(mbedtls_ssl_protocol_version in); + +const char *mbedtls_tls_prf_types_str(mbedtls_tls_prf_types in); + +const char *mbedtls_ssl_key_export_type_str(mbedtls_ssl_key_export_type in); + +const char *mbedtls_ssl_sig_alg_to_str(uint16_t in); + +const char *mbedtls_ssl_named_group_to_str(uint16_t in); + +const char *mbedtls_ssl_get_extension_name(unsigned int extension_type); + +void mbedtls_ssl_print_extensions(const mbedtls_ssl_context *ssl, + int level, const char *file, int line, + int hs_msg_type, uint32_t extensions_mask, + const char *extra); + +void mbedtls_ssl_print_extension(const mbedtls_ssl_context *ssl, + int level, const char *file, int line, + int hs_msg_type, unsigned int extension_type, + const char *extra_msg0, const char *extra_msg1); + +#if defined(MBEDTLS_SSL_PROTO_TLS1_3) && defined(MBEDTLS_SSL_SESSION_TICKETS) +void mbedtls_ssl_print_ticket_flags(const mbedtls_ssl_context *ssl, + int level, const char *file, int line, + unsigned int flags); +#endif /* MBEDTLS_SSL_PROTO_TLS1_3 && MBEDTLS_SSL_SESSION_TICKETS */ + +#define MBEDTLS_SSL_PRINT_EXTS(level, hs_msg_type, extensions_mask) \ + mbedtls_ssl_print_extensions(ssl, level, __FILE__, __LINE__, \ + hs_msg_type, extensions_mask, NULL) + +#define MBEDTLS_SSL_PRINT_EXT(level, hs_msg_type, extension_type, extra) \ + mbedtls_ssl_print_extension(ssl, level, __FILE__, __LINE__, \ + hs_msg_type, extension_type, \ + extra, NULL) + +#if defined(MBEDTLS_SSL_PROTO_TLS1_3) && defined(MBEDTLS_SSL_SESSION_TICKETS) +#define MBEDTLS_SSL_PRINT_TICKET_FLAGS(level, flags) \ + mbedtls_ssl_print_ticket_flags(ssl, level, __FILE__, __LINE__, flags) +#endif + +#else + +#define MBEDTLS_SSL_PRINT_EXTS(level, hs_msg_type, extension_mask) + +#define MBEDTLS_SSL_PRINT_EXT(level, hs_msg_type, extension_type, extra) + +#if defined(MBEDTLS_SSL_PROTO_TLS1_3) && defined(MBEDTLS_SSL_SESSION_TICKETS) +#define MBEDTLS_SSL_PRINT_TICKET_FLAGS(level, flags) +#endif + +#endif /* MBEDTLS_DEBUG_C */ + +#endif /* MBEDTLS_SSL_DEBUG_HELPERS_H */ diff --git a/vendor/mbedtls/library/ssl_debug_helpers_generated.c b/vendor/mbedtls/library/ssl_debug_helpers_generated.c new file mode 100644 index 0000000000..f8b4448c86 --- /dev/null +++ b/vendor/mbedtls/library/ssl_debug_helpers_generated.c @@ -0,0 +1,251 @@ +/* Automatically generated by generate_ssl_debug_helpers.py. DO NOT EDIT. */ + +/** + * \file ssl_debug_helpers_generated.c + * + * \brief Automatically generated helper functions for debugging + */ +/* + * Copyright The Mbed TLS Contributors + * SPDX-License-Identifier: Apache-2.0 OR GPL-2.0-or-later + * + */ + +#include "common.h" + +#if defined(MBEDTLS_DEBUG_C) + +#include "ssl_debug_helpers.h" + + +const char *mbedtls_ssl_named_group_to_str( uint16_t in ) +{ + switch( in ) + { + case MBEDTLS_SSL_IANA_TLS_GROUP_SECP192K1: + return "secp192k1"; + case MBEDTLS_SSL_IANA_TLS_GROUP_SECP192R1: + return "secp192r1"; + case MBEDTLS_SSL_IANA_TLS_GROUP_SECP224K1: + return "secp224k1"; + case MBEDTLS_SSL_IANA_TLS_GROUP_SECP224R1: + return "secp224r1"; + case MBEDTLS_SSL_IANA_TLS_GROUP_SECP256K1: + return "secp256k1"; + case MBEDTLS_SSL_IANA_TLS_GROUP_SECP256R1: + return "secp256r1"; + case MBEDTLS_SSL_IANA_TLS_GROUP_SECP384R1: + return "secp384r1"; + case MBEDTLS_SSL_IANA_TLS_GROUP_SECP521R1: + return "secp521r1"; + case MBEDTLS_SSL_IANA_TLS_GROUP_BP256R1: + return "bp256r1"; + case MBEDTLS_SSL_IANA_TLS_GROUP_BP384R1: + return "bp384r1"; + case MBEDTLS_SSL_IANA_TLS_GROUP_BP512R1: + return "bp512r1"; + case MBEDTLS_SSL_IANA_TLS_GROUP_X25519: + return "x25519"; + case MBEDTLS_SSL_IANA_TLS_GROUP_X448: + return "x448"; + case MBEDTLS_SSL_IANA_TLS_GROUP_FFDHE2048: + return "ffdhe2048"; + case MBEDTLS_SSL_IANA_TLS_GROUP_FFDHE3072: + return "ffdhe3072"; + case MBEDTLS_SSL_IANA_TLS_GROUP_FFDHE4096: + return "ffdhe4096"; + case MBEDTLS_SSL_IANA_TLS_GROUP_FFDHE6144: + return "ffdhe6144"; + case MBEDTLS_SSL_IANA_TLS_GROUP_FFDHE8192: + return "ffdhe8192"; + }; + + return "UNKOWN"; +} +const char *mbedtls_ssl_sig_alg_to_str( uint16_t in ) +{ + switch( in ) + { + case MBEDTLS_TLS1_3_SIG_RSA_PKCS1_SHA256: + return "rsa_pkcs1_sha256"; + case MBEDTLS_TLS1_3_SIG_RSA_PKCS1_SHA384: + return "rsa_pkcs1_sha384"; + case MBEDTLS_TLS1_3_SIG_RSA_PKCS1_SHA512: + return "rsa_pkcs1_sha512"; + case MBEDTLS_TLS1_3_SIG_ECDSA_SECP256R1_SHA256: + return "ecdsa_secp256r1_sha256"; + case MBEDTLS_TLS1_3_SIG_ECDSA_SECP384R1_SHA384: + return "ecdsa_secp384r1_sha384"; + case MBEDTLS_TLS1_3_SIG_ECDSA_SECP521R1_SHA512: + return "ecdsa_secp521r1_sha512"; + case MBEDTLS_TLS1_3_SIG_RSA_PSS_RSAE_SHA256: + return "rsa_pss_rsae_sha256"; + case MBEDTLS_TLS1_3_SIG_RSA_PSS_RSAE_SHA384: + return "rsa_pss_rsae_sha384"; + case MBEDTLS_TLS1_3_SIG_RSA_PSS_RSAE_SHA512: + return "rsa_pss_rsae_sha512"; + case MBEDTLS_TLS1_3_SIG_ED25519: + return "ed25519"; + case MBEDTLS_TLS1_3_SIG_ED448: + return "ed448"; + case MBEDTLS_TLS1_3_SIG_RSA_PSS_PSS_SHA256: + return "rsa_pss_pss_sha256"; + case MBEDTLS_TLS1_3_SIG_RSA_PSS_PSS_SHA384: + return "rsa_pss_pss_sha384"; + case MBEDTLS_TLS1_3_SIG_RSA_PSS_PSS_SHA512: + return "rsa_pss_pss_sha512"; + case MBEDTLS_TLS1_3_SIG_RSA_PKCS1_SHA1: + return "rsa_pkcs1_sha1"; + case MBEDTLS_TLS1_3_SIG_ECDSA_SHA1: + return "ecdsa_sha1"; + case MBEDTLS_TLS1_3_SIG_NONE: + return "none"; + }; + + return "UNKNOWN"; +} +const char *mbedtls_ssl_states_str( mbedtls_ssl_states in ) +{ + switch (in) { + case MBEDTLS_SSL_HELLO_REQUEST: + return "MBEDTLS_SSL_HELLO_REQUEST"; + case MBEDTLS_SSL_CLIENT_HELLO: + return "MBEDTLS_SSL_CLIENT_HELLO"; + case MBEDTLS_SSL_SERVER_HELLO: + return "MBEDTLS_SSL_SERVER_HELLO"; + case MBEDTLS_SSL_SERVER_CERTIFICATE: + return "MBEDTLS_SSL_SERVER_CERTIFICATE"; + case MBEDTLS_SSL_SERVER_KEY_EXCHANGE: + return "MBEDTLS_SSL_SERVER_KEY_EXCHANGE"; + case MBEDTLS_SSL_CERTIFICATE_REQUEST: + return "MBEDTLS_SSL_CERTIFICATE_REQUEST"; + case MBEDTLS_SSL_SERVER_HELLO_DONE: + return "MBEDTLS_SSL_SERVER_HELLO_DONE"; + case MBEDTLS_SSL_CLIENT_CERTIFICATE: + return "MBEDTLS_SSL_CLIENT_CERTIFICATE"; + case MBEDTLS_SSL_CLIENT_KEY_EXCHANGE: + return "MBEDTLS_SSL_CLIENT_KEY_EXCHANGE"; + case MBEDTLS_SSL_CERTIFICATE_VERIFY: + return "MBEDTLS_SSL_CERTIFICATE_VERIFY"; + case MBEDTLS_SSL_CLIENT_CHANGE_CIPHER_SPEC: + return "MBEDTLS_SSL_CLIENT_CHANGE_CIPHER_SPEC"; + case MBEDTLS_SSL_CLIENT_FINISHED: + return "MBEDTLS_SSL_CLIENT_FINISHED"; + case MBEDTLS_SSL_SERVER_CHANGE_CIPHER_SPEC: + return "MBEDTLS_SSL_SERVER_CHANGE_CIPHER_SPEC"; + case MBEDTLS_SSL_SERVER_FINISHED: + return "MBEDTLS_SSL_SERVER_FINISHED"; + case MBEDTLS_SSL_FLUSH_BUFFERS: + return "MBEDTLS_SSL_FLUSH_BUFFERS"; + case MBEDTLS_SSL_HANDSHAKE_WRAPUP: + return "MBEDTLS_SSL_HANDSHAKE_WRAPUP"; + case MBEDTLS_SSL_NEW_SESSION_TICKET: + return "MBEDTLS_SSL_NEW_SESSION_TICKET"; + case MBEDTLS_SSL_SERVER_HELLO_VERIFY_REQUEST_SENT: + return "MBEDTLS_SSL_SERVER_HELLO_VERIFY_REQUEST_SENT"; + case MBEDTLS_SSL_HELLO_RETRY_REQUEST: + return "MBEDTLS_SSL_HELLO_RETRY_REQUEST"; + case MBEDTLS_SSL_ENCRYPTED_EXTENSIONS: + return "MBEDTLS_SSL_ENCRYPTED_EXTENSIONS"; + case MBEDTLS_SSL_END_OF_EARLY_DATA: + return "MBEDTLS_SSL_END_OF_EARLY_DATA"; + case MBEDTLS_SSL_CLIENT_CERTIFICATE_VERIFY: + return "MBEDTLS_SSL_CLIENT_CERTIFICATE_VERIFY"; + case MBEDTLS_SSL_CLIENT_CCS_AFTER_SERVER_FINISHED: + return "MBEDTLS_SSL_CLIENT_CCS_AFTER_SERVER_FINISHED"; + case MBEDTLS_SSL_CLIENT_CCS_BEFORE_2ND_CLIENT_HELLO: + return "MBEDTLS_SSL_CLIENT_CCS_BEFORE_2ND_CLIENT_HELLO"; + case MBEDTLS_SSL_SERVER_CCS_AFTER_SERVER_HELLO: + return "MBEDTLS_SSL_SERVER_CCS_AFTER_SERVER_HELLO"; + case MBEDTLS_SSL_CLIENT_CCS_AFTER_CLIENT_HELLO: + return "MBEDTLS_SSL_CLIENT_CCS_AFTER_CLIENT_HELLO"; + case MBEDTLS_SSL_SERVER_CCS_AFTER_HELLO_RETRY_REQUEST: + return "MBEDTLS_SSL_SERVER_CCS_AFTER_HELLO_RETRY_REQUEST"; + case MBEDTLS_SSL_HANDSHAKE_OVER: + return "MBEDTLS_SSL_HANDSHAKE_OVER"; + case MBEDTLS_SSL_TLS1_3_NEW_SESSION_TICKET: + return "MBEDTLS_SSL_TLS1_3_NEW_SESSION_TICKET"; + case MBEDTLS_SSL_TLS1_3_NEW_SESSION_TICKET_FLUSH: + return "MBEDTLS_SSL_TLS1_3_NEW_SESSION_TICKET_FLUSH"; + default: + return "UNKNOWN_VALUE"; + } +} + +#if defined(MBEDTLS_SSL_EARLY_DATA) && defined(MBEDTLS_SSL_CLI_C) +const char *mbedtls_ssl_early_data_status_str( mbedtls_ssl_early_data_status in ) +{ + switch (in) { + case MBEDTLS_SSL_EARLY_DATA_STATUS_NOT_INDICATED: + return "MBEDTLS_SSL_EARLY_DATA_STATUS_NOT_INDICATED"; + case MBEDTLS_SSL_EARLY_DATA_STATUS_ACCEPTED: + return "MBEDTLS_SSL_EARLY_DATA_STATUS_ACCEPTED"; + case MBEDTLS_SSL_EARLY_DATA_STATUS_REJECTED: + return "MBEDTLS_SSL_EARLY_DATA_STATUS_REJECTED"; + default: + return "UNKNOWN_VALUE"; + } +} + +#endif /* defined(MBEDTLS_SSL_EARLY_DATA) && defined(MBEDTLS_SSL_CLI_C) */ +const char *mbedtls_ssl_protocol_version_str( mbedtls_ssl_protocol_version in ) +{ + switch (in) { + case MBEDTLS_SSL_VERSION_UNKNOWN: + return "MBEDTLS_SSL_VERSION_UNKNOWN"; + case MBEDTLS_SSL_VERSION_TLS1_2: + return "MBEDTLS_SSL_VERSION_TLS1_2"; + case MBEDTLS_SSL_VERSION_TLS1_3: + return "MBEDTLS_SSL_VERSION_TLS1_3"; + default: + return "UNKNOWN_VALUE"; + } +} + +const char *mbedtls_tls_prf_types_str( mbedtls_tls_prf_types in ) +{ + switch (in) { + case MBEDTLS_SSL_TLS_PRF_NONE: + return "MBEDTLS_SSL_TLS_PRF_NONE"; + case MBEDTLS_SSL_TLS_PRF_SHA384: + return "MBEDTLS_SSL_TLS_PRF_SHA384"; + case MBEDTLS_SSL_TLS_PRF_SHA256: + return "MBEDTLS_SSL_TLS_PRF_SHA256"; + case MBEDTLS_SSL_HKDF_EXPAND_SHA384: + return "MBEDTLS_SSL_HKDF_EXPAND_SHA384"; + case MBEDTLS_SSL_HKDF_EXPAND_SHA256: + return "MBEDTLS_SSL_HKDF_EXPAND_SHA256"; + default: + return "UNKNOWN_VALUE"; + } +} + +const char *mbedtls_ssl_key_export_type_str( mbedtls_ssl_key_export_type in ) +{ + switch (in) { + case MBEDTLS_SSL_KEY_EXPORT_TLS12_MASTER_SECRET: + return "MBEDTLS_SSL_KEY_EXPORT_TLS12_MASTER_SECRET"; +#if defined(MBEDTLS_SSL_PROTO_TLS1_3) + case MBEDTLS_SSL_KEY_EXPORT_TLS1_3_CLIENT_EARLY_SECRET: + return "MBEDTLS_SSL_KEY_EXPORT_TLS1_3_CLIENT_EARLY_SECRET"; + case MBEDTLS_SSL_KEY_EXPORT_TLS1_3_EARLY_EXPORTER_SECRET: + return "MBEDTLS_SSL_KEY_EXPORT_TLS1_3_EARLY_EXPORTER_SECRET"; + case MBEDTLS_SSL_KEY_EXPORT_TLS1_3_CLIENT_HANDSHAKE_TRAFFIC_SECRET: + return "MBEDTLS_SSL_KEY_EXPORT_TLS1_3_CLIENT_HANDSHAKE_TRAFFIC_SECRET"; + case MBEDTLS_SSL_KEY_EXPORT_TLS1_3_SERVER_HANDSHAKE_TRAFFIC_SECRET: + return "MBEDTLS_SSL_KEY_EXPORT_TLS1_3_SERVER_HANDSHAKE_TRAFFIC_SECRET"; + case MBEDTLS_SSL_KEY_EXPORT_TLS1_3_CLIENT_APPLICATION_TRAFFIC_SECRET: + return "MBEDTLS_SSL_KEY_EXPORT_TLS1_3_CLIENT_APPLICATION_TRAFFIC_SECRET"; + case MBEDTLS_SSL_KEY_EXPORT_TLS1_3_SERVER_APPLICATION_TRAFFIC_SECRET: + return "MBEDTLS_SSL_KEY_EXPORT_TLS1_3_SERVER_APPLICATION_TRAFFIC_SECRET"; +#endif + default: + return "UNKNOWN_VALUE"; + } +} + + + +#endif /* MBEDTLS_DEBUG_C */ +/* End of automatically generated file. */ + diff --git a/vendor/mbedtls/library/ssl_misc.h b/vendor/mbedtls/library/ssl_misc.h new file mode 100644 index 0000000000..a8807f67c6 --- /dev/null +++ b/vendor/mbedtls/library/ssl_misc.h @@ -0,0 +1,2983 @@ +/** + * \file ssl_misc.h + * + * \brief Internal functions shared by the SSL modules + */ +/* + * Copyright The Mbed TLS Contributors + * SPDX-License-Identifier: Apache-2.0 OR GPL-2.0-or-later + */ +#ifndef MBEDTLS_SSL_MISC_H +#define MBEDTLS_SSL_MISC_H + +#include "mbedtls/build_info.h" + +#include "mbedtls/error.h" + +#include "mbedtls/ssl.h" +#include "mbedtls/cipher.h" + +#if defined(MBEDTLS_USE_PSA_CRYPTO) || defined(MBEDTLS_SSL_PROTO_TLS1_3) +#include "psa/crypto.h" +#include "psa_util_internal.h" +#endif + +#if defined(MBEDTLS_MD_CAN_MD5) +#include "mbedtls/md5.h" +#endif + +#if defined(MBEDTLS_MD_CAN_SHA1) +#include "mbedtls/sha1.h" +#endif + +#if defined(MBEDTLS_MD_CAN_SHA256) +#include "mbedtls/sha256.h" +#endif + +#if defined(MBEDTLS_MD_CAN_SHA512) +#include "mbedtls/sha512.h" +#endif + +#if defined(MBEDTLS_KEY_EXCHANGE_ECJPAKE_ENABLED) && \ + !defined(MBEDTLS_USE_PSA_CRYPTO) +#include "mbedtls/ecjpake.h" +#endif + +#include "mbedtls/pk.h" +#include "ssl_ciphersuites_internal.h" +#include "x509_internal.h" +#include "pk_internal.h" +#include "common.h" + +/* Shorthand for restartable ECC */ +#if defined(MBEDTLS_ECP_RESTARTABLE) && \ + defined(MBEDTLS_SSL_CLI_C) && \ + defined(MBEDTLS_SSL_PROTO_TLS1_2) && \ + defined(MBEDTLS_KEY_EXCHANGE_ECDHE_ECDSA_ENABLED) +#define MBEDTLS_SSL_ECP_RESTARTABLE_ENABLED +#endif + +#define MBEDTLS_SSL_INITIAL_HANDSHAKE 0 +#define MBEDTLS_SSL_RENEGOTIATION_IN_PROGRESS 1 /* In progress */ +#define MBEDTLS_SSL_RENEGOTIATION_DONE 2 /* Done or aborted */ +#define MBEDTLS_SSL_RENEGOTIATION_PENDING 3 /* Requested (server only) */ + +/* Faked handshake message identity for HelloRetryRequest. */ +#define MBEDTLS_SSL_TLS1_3_HS_HELLO_RETRY_REQUEST (-MBEDTLS_SSL_HS_SERVER_HELLO) + +/* + * Internal identity of handshake extensions + */ +#define MBEDTLS_SSL_EXT_ID_UNRECOGNIZED 0 +#define MBEDTLS_SSL_EXT_ID_SERVERNAME 1 +#define MBEDTLS_SSL_EXT_ID_SERVERNAME_HOSTNAME 1 +#define MBEDTLS_SSL_EXT_ID_MAX_FRAGMENT_LENGTH 2 +#define MBEDTLS_SSL_EXT_ID_STATUS_REQUEST 3 +#define MBEDTLS_SSL_EXT_ID_SUPPORTED_GROUPS 4 +#define MBEDTLS_SSL_EXT_ID_SUPPORTED_ELLIPTIC_CURVES 4 +#define MBEDTLS_SSL_EXT_ID_SIG_ALG 5 +#define MBEDTLS_SSL_EXT_ID_USE_SRTP 6 +#define MBEDTLS_SSL_EXT_ID_HEARTBEAT 7 +#define MBEDTLS_SSL_EXT_ID_ALPN 8 +#define MBEDTLS_SSL_EXT_ID_SCT 9 +#define MBEDTLS_SSL_EXT_ID_CLI_CERT_TYPE 10 +#define MBEDTLS_SSL_EXT_ID_SERV_CERT_TYPE 11 +#define MBEDTLS_SSL_EXT_ID_PADDING 12 +#define MBEDTLS_SSL_EXT_ID_PRE_SHARED_KEY 13 +#define MBEDTLS_SSL_EXT_ID_EARLY_DATA 14 +#define MBEDTLS_SSL_EXT_ID_SUPPORTED_VERSIONS 15 +#define MBEDTLS_SSL_EXT_ID_COOKIE 16 +#define MBEDTLS_SSL_EXT_ID_PSK_KEY_EXCHANGE_MODES 17 +#define MBEDTLS_SSL_EXT_ID_CERT_AUTH 18 +#define MBEDTLS_SSL_EXT_ID_OID_FILTERS 19 +#define MBEDTLS_SSL_EXT_ID_POST_HANDSHAKE_AUTH 20 +#define MBEDTLS_SSL_EXT_ID_SIG_ALG_CERT 21 +#define MBEDTLS_SSL_EXT_ID_KEY_SHARE 22 +#define MBEDTLS_SSL_EXT_ID_TRUNCATED_HMAC 23 +#define MBEDTLS_SSL_EXT_ID_SUPPORTED_POINT_FORMATS 24 +#define MBEDTLS_SSL_EXT_ID_ENCRYPT_THEN_MAC 25 +#define MBEDTLS_SSL_EXT_ID_EXTENDED_MASTER_SECRET 26 +#define MBEDTLS_SSL_EXT_ID_SESSION_TICKET 27 +#define MBEDTLS_SSL_EXT_ID_RECORD_SIZE_LIMIT 28 + +/* Utility for translating IANA extension type. */ +uint32_t mbedtls_ssl_get_extension_id(unsigned int extension_type); +uint32_t mbedtls_ssl_get_extension_mask(unsigned int extension_type); +/* Macros used to define mask constants */ +#define MBEDTLS_SSL_EXT_MASK(id) (1ULL << (MBEDTLS_SSL_EXT_ID_##id)) +/* Reset value of extension mask */ +#define MBEDTLS_SSL_EXT_MASK_NONE 0 + +/* In messages containing extension requests, we should ignore unrecognized + * extensions. In messages containing extension responses, unrecognized + * extensions should result in handshake abortion. Messages containing + * extension requests include ClientHello, CertificateRequest and + * NewSessionTicket. Messages containing extension responses include + * ServerHello, HelloRetryRequest, EncryptedExtensions and Certificate. + * + * RFC 8446 section 4.1.3 + * + * The ServerHello MUST only include extensions which are required to establish + * the cryptographic context and negotiate the protocol version. + * + * RFC 8446 section 4.2 + * + * If an implementation receives an extension which it recognizes and which is + * not specified for the message in which it appears, it MUST abort the handshake + * with an "illegal_parameter" alert. + */ + +/* Extensions that are not recognized by TLS 1.3 */ +#define MBEDTLS_SSL_TLS1_3_EXT_MASK_UNRECOGNIZED \ + (MBEDTLS_SSL_EXT_MASK(SUPPORTED_POINT_FORMATS) | \ + MBEDTLS_SSL_EXT_MASK(ENCRYPT_THEN_MAC) | \ + MBEDTLS_SSL_EXT_MASK(EXTENDED_MASTER_SECRET) | \ + MBEDTLS_SSL_EXT_MASK(SESSION_TICKET) | \ + MBEDTLS_SSL_EXT_MASK(TRUNCATED_HMAC) | \ + MBEDTLS_SSL_EXT_MASK(UNRECOGNIZED)) + +/* RFC 8446 section 4.2. Allowed extensions for ClientHello */ +#define MBEDTLS_SSL_TLS1_3_ALLOWED_EXTS_OF_CH \ + (MBEDTLS_SSL_EXT_MASK(SERVERNAME) | \ + MBEDTLS_SSL_EXT_MASK(MAX_FRAGMENT_LENGTH) | \ + MBEDTLS_SSL_EXT_MASK(STATUS_REQUEST) | \ + MBEDTLS_SSL_EXT_MASK(SUPPORTED_GROUPS) | \ + MBEDTLS_SSL_EXT_MASK(SIG_ALG) | \ + MBEDTLS_SSL_EXT_MASK(USE_SRTP) | \ + MBEDTLS_SSL_EXT_MASK(HEARTBEAT) | \ + MBEDTLS_SSL_EXT_MASK(ALPN) | \ + MBEDTLS_SSL_EXT_MASK(SCT) | \ + MBEDTLS_SSL_EXT_MASK(CLI_CERT_TYPE) | \ + MBEDTLS_SSL_EXT_MASK(SERV_CERT_TYPE) | \ + MBEDTLS_SSL_EXT_MASK(PADDING) | \ + MBEDTLS_SSL_EXT_MASK(KEY_SHARE) | \ + MBEDTLS_SSL_EXT_MASK(PRE_SHARED_KEY) | \ + MBEDTLS_SSL_EXT_MASK(PSK_KEY_EXCHANGE_MODES) | \ + MBEDTLS_SSL_EXT_MASK(EARLY_DATA) | \ + MBEDTLS_SSL_EXT_MASK(COOKIE) | \ + MBEDTLS_SSL_EXT_MASK(SUPPORTED_VERSIONS) | \ + MBEDTLS_SSL_EXT_MASK(CERT_AUTH) | \ + MBEDTLS_SSL_EXT_MASK(POST_HANDSHAKE_AUTH) | \ + MBEDTLS_SSL_EXT_MASK(SIG_ALG_CERT) | \ + MBEDTLS_SSL_EXT_MASK(RECORD_SIZE_LIMIT) | \ + MBEDTLS_SSL_TLS1_3_EXT_MASK_UNRECOGNIZED) + +/* RFC 8446 section 4.2. Allowed extensions for EncryptedExtensions */ +#define MBEDTLS_SSL_TLS1_3_ALLOWED_EXTS_OF_EE \ + (MBEDTLS_SSL_EXT_MASK(SERVERNAME) | \ + MBEDTLS_SSL_EXT_MASK(MAX_FRAGMENT_LENGTH) | \ + MBEDTLS_SSL_EXT_MASK(SUPPORTED_GROUPS) | \ + MBEDTLS_SSL_EXT_MASK(USE_SRTP) | \ + MBEDTLS_SSL_EXT_MASK(HEARTBEAT) | \ + MBEDTLS_SSL_EXT_MASK(ALPN) | \ + MBEDTLS_SSL_EXT_MASK(CLI_CERT_TYPE) | \ + MBEDTLS_SSL_EXT_MASK(SERV_CERT_TYPE) | \ + MBEDTLS_SSL_EXT_MASK(EARLY_DATA) | \ + MBEDTLS_SSL_EXT_MASK(RECORD_SIZE_LIMIT)) + +/* RFC 8446 section 4.2. Allowed extensions for CertificateRequest */ +#define MBEDTLS_SSL_TLS1_3_ALLOWED_EXTS_OF_CR \ + (MBEDTLS_SSL_EXT_MASK(STATUS_REQUEST) | \ + MBEDTLS_SSL_EXT_MASK(SIG_ALG) | \ + MBEDTLS_SSL_EXT_MASK(SCT) | \ + MBEDTLS_SSL_EXT_MASK(CERT_AUTH) | \ + MBEDTLS_SSL_EXT_MASK(OID_FILTERS) | \ + MBEDTLS_SSL_EXT_MASK(SIG_ALG_CERT) | \ + MBEDTLS_SSL_TLS1_3_EXT_MASK_UNRECOGNIZED) + +/* RFC 8446 section 4.2. Allowed extensions for Certificate */ +#define MBEDTLS_SSL_TLS1_3_ALLOWED_EXTS_OF_CT \ + (MBEDTLS_SSL_EXT_MASK(STATUS_REQUEST) | \ + MBEDTLS_SSL_EXT_MASK(SCT)) + +/* RFC 8446 section 4.2. Allowed extensions for ServerHello */ +#define MBEDTLS_SSL_TLS1_3_ALLOWED_EXTS_OF_SH \ + (MBEDTLS_SSL_EXT_MASK(KEY_SHARE) | \ + MBEDTLS_SSL_EXT_MASK(PRE_SHARED_KEY) | \ + MBEDTLS_SSL_EXT_MASK(SUPPORTED_VERSIONS)) + +/* RFC 8446 section 4.2. Allowed extensions for HelloRetryRequest */ +#define MBEDTLS_SSL_TLS1_3_ALLOWED_EXTS_OF_HRR \ + (MBEDTLS_SSL_EXT_MASK(KEY_SHARE) | \ + MBEDTLS_SSL_EXT_MASK(COOKIE) | \ + MBEDTLS_SSL_EXT_MASK(SUPPORTED_VERSIONS)) + +/* RFC 8446 section 4.2. Allowed extensions for NewSessionTicket */ +#define MBEDTLS_SSL_TLS1_3_ALLOWED_EXTS_OF_NST \ + (MBEDTLS_SSL_EXT_MASK(EARLY_DATA) | \ + MBEDTLS_SSL_TLS1_3_EXT_MASK_UNRECOGNIZED) + +/* + * Helper macros for function call with return check. + */ +/* + * Exit when return non-zero value + */ +#define MBEDTLS_SSL_PROC_CHK(f) \ + do { \ + ret = (f); \ + if (ret != 0) \ + { \ + goto cleanup; \ + } \ + } while (0) +/* + * Exit when return negative value + */ +#define MBEDTLS_SSL_PROC_CHK_NEG(f) \ + do { \ + ret = (f); \ + if (ret < 0) \ + { \ + goto cleanup; \ + } \ + } while (0) + +/* + * DTLS retransmission states, see RFC 6347 4.2.4 + * + * The SENDING state is merged in PREPARING for initial sends, + * but is distinct for resends. + * + * Note: initial state is wrong for server, but is not used anyway. + */ +#define MBEDTLS_SSL_RETRANS_PREPARING 0 +#define MBEDTLS_SSL_RETRANS_SENDING 1 +#define MBEDTLS_SSL_RETRANS_WAITING 2 +#define MBEDTLS_SSL_RETRANS_FINISHED 3 + +/* + * Allow extra bytes for record, authentication and encryption overhead: + * counter (8) + header (5) + IV(16) + MAC (16-48) + padding (0-256). + */ + +#if defined(MBEDTLS_SSL_PROTO_TLS1_2) + +/* This macro determines whether CBC is supported. */ +#if defined(MBEDTLS_SSL_HAVE_CBC) && \ + (defined(MBEDTLS_SSL_HAVE_AES) || \ + defined(MBEDTLS_SSL_HAVE_CAMELLIA) || \ + defined(MBEDTLS_SSL_HAVE_ARIA)) +#define MBEDTLS_SSL_SOME_SUITES_USE_CBC +#endif + +/* This macro determines whether a ciphersuite using a + * stream cipher can be used. */ +#if defined(MBEDTLS_CIPHER_NULL_CIPHER) +#define MBEDTLS_SSL_SOME_SUITES_USE_STREAM +#endif + +/* This macro determines whether the CBC construct used in TLS 1.2 is supported. */ +#if defined(MBEDTLS_SSL_SOME_SUITES_USE_CBC) && \ + defined(MBEDTLS_SSL_PROTO_TLS1_2) +#define MBEDTLS_SSL_SOME_SUITES_USE_TLS_CBC +#endif + +#if defined(MBEDTLS_SSL_SOME_SUITES_USE_STREAM) || \ + defined(MBEDTLS_SSL_SOME_SUITES_USE_CBC) +#define MBEDTLS_SSL_SOME_SUITES_USE_MAC +#endif + +/* This macro determines whether a ciphersuite uses Encrypt-then-MAC with CBC */ +#if defined(MBEDTLS_SSL_SOME_SUITES_USE_CBC) && \ + defined(MBEDTLS_SSL_ENCRYPT_THEN_MAC) +#define MBEDTLS_SSL_SOME_SUITES_USE_CBC_ETM +#endif + +#endif /* MBEDTLS_SSL_PROTO_TLS1_2 */ + +#if defined(MBEDTLS_SSL_SOME_SUITES_USE_MAC) +/* Ciphersuites using HMAC */ +#if defined(MBEDTLS_MD_CAN_SHA384) +#define MBEDTLS_SSL_MAC_ADD 48 /* SHA-384 used for HMAC */ +#elif defined(MBEDTLS_MD_CAN_SHA256) +#define MBEDTLS_SSL_MAC_ADD 32 /* SHA-256 used for HMAC */ +#else +#define MBEDTLS_SSL_MAC_ADD 20 /* SHA-1 used for HMAC */ +#endif +#else /* MBEDTLS_SSL_SOME_SUITES_USE_MAC */ +/* AEAD ciphersuites: GCM and CCM use a 128 bits tag */ +#define MBEDTLS_SSL_MAC_ADD 16 +#endif + +#if defined(MBEDTLS_SSL_HAVE_CBC) +#define MBEDTLS_SSL_PADDING_ADD 256 +#else +#define MBEDTLS_SSL_PADDING_ADD 0 +#endif + +#if defined(MBEDTLS_SSL_DTLS_CONNECTION_ID) +#define MBEDTLS_SSL_MAX_CID_EXPANSION MBEDTLS_SSL_CID_TLS1_3_PADDING_GRANULARITY +#else +#define MBEDTLS_SSL_MAX_CID_EXPANSION 0 +#endif + +#define MBEDTLS_SSL_PAYLOAD_OVERHEAD (MBEDTLS_MAX_IV_LENGTH + \ + MBEDTLS_SSL_MAC_ADD + \ + MBEDTLS_SSL_PADDING_ADD + \ + MBEDTLS_SSL_MAX_CID_EXPANSION \ + ) + +#define MBEDTLS_SSL_IN_PAYLOAD_LEN (MBEDTLS_SSL_PAYLOAD_OVERHEAD + \ + (MBEDTLS_SSL_IN_CONTENT_LEN)) + +#define MBEDTLS_SSL_OUT_PAYLOAD_LEN (MBEDTLS_SSL_PAYLOAD_OVERHEAD + \ + (MBEDTLS_SSL_OUT_CONTENT_LEN)) + +/* The maximum number of buffered handshake messages. */ +#define MBEDTLS_SSL_MAX_BUFFERED_HS 4 + +/* Maximum length we can advertise as our max content length for + RFC 6066 max_fragment_length extension negotiation purposes + (the lesser of both sizes, if they are unequal.) + */ +#define MBEDTLS_TLS_EXT_ADV_CONTENT_LEN ( \ + (MBEDTLS_SSL_IN_CONTENT_LEN > MBEDTLS_SSL_OUT_CONTENT_LEN) \ + ? (MBEDTLS_SSL_OUT_CONTENT_LEN) \ + : (MBEDTLS_SSL_IN_CONTENT_LEN) \ + ) + +/* Maximum size in bytes of list in signature algorithms ext., RFC 5246/8446 */ +#define MBEDTLS_SSL_MAX_SIG_ALG_LIST_LEN 65534 + +/* Minimum size in bytes of list in signature algorithms ext., RFC 5246/8446 */ +#define MBEDTLS_SSL_MIN_SIG_ALG_LIST_LEN 2 + +/* Maximum size in bytes of list in supported elliptic curve ext., RFC 4492 */ +#define MBEDTLS_SSL_MAX_CURVE_LIST_LEN 65535 + +#define MBEDTLS_RECEIVED_SIG_ALGS_SIZE 20 + +#if defined(MBEDTLS_SSL_HANDSHAKE_WITH_CERT_ENABLED) + +#define MBEDTLS_TLS_SIG_NONE MBEDTLS_TLS1_3_SIG_NONE + +#if defined(MBEDTLS_SSL_PROTO_TLS1_2) +#define MBEDTLS_SSL_TLS12_SIG_AND_HASH_ALG(sig, hash) ((hash << 8) | sig) +#define MBEDTLS_SSL_TLS12_SIG_ALG_FROM_SIG_AND_HASH_ALG(alg) (alg & 0xFF) +#define MBEDTLS_SSL_TLS12_HASH_ALG_FROM_SIG_AND_HASH_ALG(alg) (alg >> 8) +#endif /* MBEDTLS_SSL_PROTO_TLS1_2 */ + +#endif /* MBEDTLS_SSL_HANDSHAKE_WITH_CERT_ENABLED */ + +/* + * Check that we obey the standard's message size bounds + */ + +#if MBEDTLS_SSL_IN_CONTENT_LEN > 16384 +#error "Bad configuration - incoming record content too large." +#endif + +#if MBEDTLS_SSL_OUT_CONTENT_LEN > 16384 +#error "Bad configuration - outgoing record content too large." +#endif + +#if MBEDTLS_SSL_IN_PAYLOAD_LEN > MBEDTLS_SSL_IN_CONTENT_LEN + 2048 +#error "Bad configuration - incoming protected record payload too large." +#endif + +#if MBEDTLS_SSL_OUT_PAYLOAD_LEN > MBEDTLS_SSL_OUT_CONTENT_LEN + 2048 +#error "Bad configuration - outgoing protected record payload too large." +#endif + +/* Calculate buffer sizes */ + +/* Note: Even though the TLS record header is only 5 bytes + long, we're internally using 8 bytes to store the + implicit sequence number. */ +#define MBEDTLS_SSL_HEADER_LEN 13 + +#if !defined(MBEDTLS_SSL_DTLS_CONNECTION_ID) +#define MBEDTLS_SSL_IN_BUFFER_LEN \ + ((MBEDTLS_SSL_HEADER_LEN) + (MBEDTLS_SSL_IN_PAYLOAD_LEN)) +#else +#define MBEDTLS_SSL_IN_BUFFER_LEN \ + ((MBEDTLS_SSL_HEADER_LEN) + (MBEDTLS_SSL_IN_PAYLOAD_LEN) \ + + (MBEDTLS_SSL_CID_IN_LEN_MAX)) +#endif + +#if !defined(MBEDTLS_SSL_DTLS_CONNECTION_ID) +#define MBEDTLS_SSL_OUT_BUFFER_LEN \ + ((MBEDTLS_SSL_HEADER_LEN) + (MBEDTLS_SSL_OUT_PAYLOAD_LEN)) +#else +#define MBEDTLS_SSL_OUT_BUFFER_LEN \ + ((MBEDTLS_SSL_HEADER_LEN) + (MBEDTLS_SSL_OUT_PAYLOAD_LEN) \ + + (MBEDTLS_SSL_CID_OUT_LEN_MAX)) +#endif + +#define MBEDTLS_CLIENT_HELLO_RANDOM_LEN 32 +#define MBEDTLS_SERVER_HELLO_RANDOM_LEN 32 + +#if defined(MBEDTLS_SSL_MAX_FRAGMENT_LENGTH) +/** + * \brief Return the maximum fragment length (payload, in bytes) for + * the output buffer. For the client, this is the configured + * value. For the server, it is the minimum of two - the + * configured value and the negotiated one. + * + * \sa mbedtls_ssl_conf_max_frag_len() + * \sa mbedtls_ssl_get_max_out_record_payload() + * + * \param ssl SSL context + * + * \return Current maximum fragment length for the output buffer. + */ +size_t mbedtls_ssl_get_output_max_frag_len(const mbedtls_ssl_context *ssl); + +/** + * \brief Return the maximum fragment length (payload, in bytes) for + * the input buffer. This is the negotiated maximum fragment + * length, or, if there is none, MBEDTLS_SSL_IN_CONTENT_LEN. + * If it is not defined either, the value is 2^14. This function + * works as its predecessor, \c mbedtls_ssl_get_max_frag_len(). + * + * \sa mbedtls_ssl_conf_max_frag_len() + * \sa mbedtls_ssl_get_max_in_record_payload() + * + * \param ssl SSL context + * + * \return Current maximum fragment length for the output buffer. + */ +size_t mbedtls_ssl_get_input_max_frag_len(const mbedtls_ssl_context *ssl); +#endif /* MBEDTLS_SSL_MAX_FRAGMENT_LENGTH */ + +#if defined(MBEDTLS_SSL_RECORD_SIZE_LIMIT) +/** + * \brief Get the size limit in bytes for the protected outgoing records + * as defined in RFC 8449 + * + * \param ssl SSL context + * + * \return The size limit in bytes for the protected outgoing + * records as defined in RFC 8449. + */ +size_t mbedtls_ssl_get_output_record_size_limit(const mbedtls_ssl_context *ssl); +#endif /* MBEDTLS_SSL_RECORD_SIZE_LIMIT */ + +#if defined(MBEDTLS_SSL_VARIABLE_BUFFER_LENGTH) +static inline size_t mbedtls_ssl_get_output_buflen(const mbedtls_ssl_context *ctx) +{ +#if defined(MBEDTLS_SSL_DTLS_CONNECTION_ID) + return mbedtls_ssl_get_output_max_frag_len(ctx) + + MBEDTLS_SSL_HEADER_LEN + MBEDTLS_SSL_PAYLOAD_OVERHEAD + + MBEDTLS_SSL_CID_OUT_LEN_MAX; +#else + return mbedtls_ssl_get_output_max_frag_len(ctx) + + MBEDTLS_SSL_HEADER_LEN + MBEDTLS_SSL_PAYLOAD_OVERHEAD; +#endif +} + +static inline size_t mbedtls_ssl_get_input_buflen(const mbedtls_ssl_context *ctx) +{ +#if defined(MBEDTLS_SSL_DTLS_CONNECTION_ID) + return mbedtls_ssl_get_input_max_frag_len(ctx) + + MBEDTLS_SSL_HEADER_LEN + MBEDTLS_SSL_PAYLOAD_OVERHEAD + + MBEDTLS_SSL_CID_IN_LEN_MAX; +#else + return mbedtls_ssl_get_input_max_frag_len(ctx) + + MBEDTLS_SSL_HEADER_LEN + MBEDTLS_SSL_PAYLOAD_OVERHEAD; +#endif +} +#endif + +/* + * TLS extension flags (for extensions with outgoing ServerHello content + * that need it (e.g. for RENEGOTIATION_INFO the server already knows because + * of state of the renegotiation flag, so no indicator is required) + */ +#define MBEDTLS_TLS_EXT_SUPPORTED_POINT_FORMATS_PRESENT (1 << 0) +#define MBEDTLS_TLS_EXT_ECJPAKE_KKPP_OK (1 << 1) + +/** + * \brief This function checks if the remaining size in a buffer is + * greater or equal than a needed space. + * + * \param cur Pointer to the current position in the buffer. + * \param end Pointer to one past the end of the buffer. + * \param need Needed space in bytes. + * + * \return Zero if the needed space is available in the buffer, non-zero + * otherwise. + */ +#if !defined(MBEDTLS_TEST_HOOKS) +static inline int mbedtls_ssl_chk_buf_ptr(const uint8_t *cur, + const uint8_t *end, size_t need) +{ + return (cur > end) || (need > (size_t) (end - cur)); +} +#else +typedef struct { + const uint8_t *cur; + const uint8_t *end; + size_t need; +} mbedtls_ssl_chk_buf_ptr_args; + +void mbedtls_ssl_set_chk_buf_ptr_fail_args( + const uint8_t *cur, const uint8_t *end, size_t need); +void mbedtls_ssl_reset_chk_buf_ptr_fail_args(void); + +MBEDTLS_CHECK_RETURN_CRITICAL +int mbedtls_ssl_cmp_chk_buf_ptr_fail_args(mbedtls_ssl_chk_buf_ptr_args *args); + +static inline int mbedtls_ssl_chk_buf_ptr(const uint8_t *cur, + const uint8_t *end, size_t need) +{ + if ((cur > end) || (need > (size_t) (end - cur))) { + mbedtls_ssl_set_chk_buf_ptr_fail_args(cur, end, need); + return 1; + } + return 0; +} +#endif /* MBEDTLS_TEST_HOOKS */ + +/** + * \brief This macro checks if the remaining size in a buffer is + * greater or equal than a needed space. If it is not the case, + * it returns an SSL_BUFFER_TOO_SMALL error. + * + * \param cur Pointer to the current position in the buffer. + * \param end Pointer to one past the end of the buffer. + * \param need Needed space in bytes. + * + */ +#define MBEDTLS_SSL_CHK_BUF_PTR(cur, end, need) \ + do { \ + if (mbedtls_ssl_chk_buf_ptr((cur), (end), (need)) != 0) \ + { \ + return MBEDTLS_ERR_SSL_BUFFER_TOO_SMALL; \ + } \ + } while (0) + +/** + * \brief This macro checks if the remaining length in an input buffer is + * greater or equal than a needed length. If it is not the case, it + * returns #MBEDTLS_ERR_SSL_DECODE_ERROR error and pends a + * #MBEDTLS_SSL_ALERT_MSG_DECODE_ERROR alert message. + * + * This is a function-like macro. It is guaranteed to evaluate each + * argument exactly once. + * + * \param cur Pointer to the current position in the buffer. + * \param end Pointer to one past the end of the buffer. + * \param need Needed length in bytes. + * + */ +#define MBEDTLS_SSL_CHK_BUF_READ_PTR(cur, end, need) \ + do { \ + if (mbedtls_ssl_chk_buf_ptr((cur), (end), (need)) != 0) \ + { \ + MBEDTLS_SSL_DEBUG_MSG(1, \ + ("missing input data in %s", __func__)); \ + MBEDTLS_SSL_PEND_FATAL_ALERT(MBEDTLS_SSL_ALERT_MSG_DECODE_ERROR, \ + MBEDTLS_ERR_SSL_DECODE_ERROR); \ + return MBEDTLS_ERR_SSL_DECODE_ERROR; \ + } \ + } while (0) + +#ifdef __cplusplus +extern "C" { +#endif + +typedef int mbedtls_ssl_tls_prf_cb(const unsigned char *secret, size_t slen, + const char *label, + const unsigned char *random, size_t rlen, + unsigned char *dstbuf, size_t dlen); + +/* cipher.h exports the maximum IV, key and block length from + * all ciphers enabled in the config, regardless of whether those + * ciphers are actually usable in SSL/TLS. Notably, XTS is enabled + * in the default configuration and uses 64 Byte keys, but it is + * not used for record protection in SSL/TLS. + * + * In order to prevent unnecessary inflation of key structures, + * we introduce SSL-specific variants of the max-{key,block,IV} + * macros here which are meant to only take those ciphers into + * account which can be negotiated in SSL/TLS. + * + * Since the current definitions of MBEDTLS_MAX_{KEY|BLOCK|IV}_LENGTH + * in cipher.h are rough overapproximations of the real maxima, here + * we content ourselves with replicating those overapproximations + * for the maximum block and IV length, and excluding XTS from the + * computation of the maximum key length. */ +#define MBEDTLS_SSL_MAX_BLOCK_LENGTH 16 +#define MBEDTLS_SSL_MAX_IV_LENGTH 16 +#define MBEDTLS_SSL_MAX_KEY_LENGTH 32 + +/** + * \brief The data structure holding the cryptographic material (key and IV) + * used for record protection in TLS 1.3. + */ +struct mbedtls_ssl_key_set { + /*! The key for client->server records. */ + unsigned char client_write_key[MBEDTLS_SSL_MAX_KEY_LENGTH]; + /*! The key for server->client records. */ + unsigned char server_write_key[MBEDTLS_SSL_MAX_KEY_LENGTH]; + /*! The IV for client->server records. */ + unsigned char client_write_iv[MBEDTLS_SSL_MAX_IV_LENGTH]; + /*! The IV for server->client records. */ + unsigned char server_write_iv[MBEDTLS_SSL_MAX_IV_LENGTH]; + + size_t key_len; /*!< The length of client_write_key and + * server_write_key, in Bytes. */ + size_t iv_len; /*!< The length of client_write_iv and + * server_write_iv, in Bytes. */ +}; +typedef struct mbedtls_ssl_key_set mbedtls_ssl_key_set; + +typedef struct { + unsigned char binder_key[MBEDTLS_TLS1_3_MD_MAX_SIZE]; + unsigned char client_early_traffic_secret[MBEDTLS_TLS1_3_MD_MAX_SIZE]; + unsigned char early_exporter_master_secret[MBEDTLS_TLS1_3_MD_MAX_SIZE]; +} mbedtls_ssl_tls13_early_secrets; + +typedef struct { + unsigned char client_handshake_traffic_secret[MBEDTLS_TLS1_3_MD_MAX_SIZE]; + unsigned char server_handshake_traffic_secret[MBEDTLS_TLS1_3_MD_MAX_SIZE]; +} mbedtls_ssl_tls13_handshake_secrets; + +/* + * This structure contains the parameters only needed during handshake. + */ +struct mbedtls_ssl_handshake_params { + /* Frequently-used boolean or byte fields (placed early to take + * advantage of smaller code size for indirect access on Arm Thumb) */ + uint8_t resume; /*!< session resume indicator*/ + uint8_t cli_exts; /*!< client extension presence*/ + +#if defined(MBEDTLS_SSL_SERVER_NAME_INDICATION) + uint8_t sni_authmode; /*!< authmode from SNI callback */ +#endif + +#if defined(MBEDTLS_SSL_SRV_C) + /* Flag indicating if a CertificateRequest message has been sent + * to the client or not. */ + uint8_t certificate_request_sent; +#if defined(MBEDTLS_SSL_EARLY_DATA) + /* Flag indicating if the server has accepted early data or not. */ + uint8_t early_data_accepted; +#endif +#endif /* MBEDTLS_SSL_SRV_C */ + +#if defined(MBEDTLS_SSL_SESSION_TICKETS) + uint8_t new_session_ticket; /*!< use NewSessionTicket? */ +#endif /* MBEDTLS_SSL_SESSION_TICKETS */ + +#if defined(MBEDTLS_SSL_CLI_C) + /** Minimum TLS version to be negotiated. + * + * It is set up in the ClientHello writing preparation stage and used + * throughout the ClientHello writing. Not relevant anymore as soon as + * the protocol version has been negotiated thus as soon as the + * ServerHello is received. + * For a fresh handshake not linked to any previous handshake, it is + * equal to the configured minimum minor version to be negotiated. When + * renegotiating or resuming a session, it is equal to the previously + * negotiated minor version. + * + * There is no maximum TLS version field in this handshake context. + * From the start of the handshake, we need to define a current protocol + * version for the record layer which we define as the maximum TLS + * version to be negotiated. The `tls_version` field of the SSL context is + * used to store this maximum value until it contains the actual + * negotiated value. + */ + mbedtls_ssl_protocol_version min_tls_version; +#endif + +#if defined(MBEDTLS_SSL_EXTENDED_MASTER_SECRET) + uint8_t extended_ms; /*!< use Extended Master Secret? */ +#endif + +#if defined(MBEDTLS_SSL_ASYNC_PRIVATE) + uint8_t async_in_progress; /*!< an asynchronous operation is in progress */ +#endif /* MBEDTLS_SSL_ASYNC_PRIVATE */ + +#if defined(MBEDTLS_SSL_PROTO_DTLS) + unsigned char retransmit_state; /*!< Retransmission state */ +#endif + +#if !defined(MBEDTLS_DEPRECATED_REMOVED) + unsigned char group_list_heap_allocated; + unsigned char sig_algs_heap_allocated; +#endif + +#if defined(MBEDTLS_SSL_ECP_RESTARTABLE_ENABLED) + uint8_t ecrs_enabled; /*!< Handshake supports EC restart? */ + enum { /* this complements ssl->state with info on intra-state operations */ + ssl_ecrs_none = 0, /*!< nothing going on (yet) */ + ssl_ecrs_crt_verify, /*!< Certificate: crt_verify() */ + ssl_ecrs_ske_start_processing, /*!< ServerKeyExchange: pk_verify() */ + ssl_ecrs_cke_ecdh_calc_secret, /*!< ClientKeyExchange: ECDH step 2 */ + ssl_ecrs_crt_vrfy_sign, /*!< CertificateVerify: pk_sign() */ + } ecrs_state; /*!< current (or last) operation */ + mbedtls_x509_crt *ecrs_peer_cert; /*!< The peer's CRT chain. */ + size_t ecrs_n; /*!< place for saving a length */ +#endif + + mbedtls_ssl_ciphersuite_t const *ciphersuite_info; + + MBEDTLS_CHECK_RETURN_CRITICAL + int (*update_checksum)(mbedtls_ssl_context *, const unsigned char *, size_t); + MBEDTLS_CHECK_RETURN_CRITICAL + int (*calc_verify)(const mbedtls_ssl_context *, unsigned char *, size_t *); + MBEDTLS_CHECK_RETURN_CRITICAL + int (*calc_finished)(mbedtls_ssl_context *, unsigned char *, int); + mbedtls_ssl_tls_prf_cb *tls_prf; + + /* + * Handshake specific crypto variables + */ +#if defined(MBEDTLS_SSL_PROTO_TLS1_3) + uint8_t key_exchange_mode; /*!< Selected key exchange mode */ + + /** + * Flag indicating if, in the course of the current handshake, an + * HelloRetryRequest message has been sent by the server or received by + * the client (<> 0) or not (0). + */ + uint8_t hello_retry_request_flag; + +#if defined(MBEDTLS_SSL_TLS1_3_COMPATIBILITY_MODE) + /** + * Flag indicating if, in the course of the current handshake, a dummy + * change_cipher_spec (CCS) record has already been sent. Used to send only + * one CCS per handshake while not complicating the handshake state + * transitions for that purpose. + */ + uint8_t ccs_sent; +#endif + +#if defined(MBEDTLS_SSL_SRV_C) +#if defined(MBEDTLS_SSL_TLS1_3_KEY_EXCHANGE_MODE_SOME_PSK_ENABLED) + uint8_t tls13_kex_modes; /*!< Key exchange modes supported by the client */ +#endif + /** selected_group of key_share extension in HelloRetryRequest message. */ + uint16_t hrr_selected_group; +#if defined(MBEDTLS_SSL_SESSION_TICKETS) + uint16_t new_session_tickets_count; /*!< number of session tickets */ +#endif +#endif /* MBEDTLS_SSL_SRV_C */ + +#endif /* MBEDTLS_SSL_PROTO_TLS1_3 */ + +#if defined(MBEDTLS_SSL_HANDSHAKE_WITH_CERT_ENABLED) + uint16_t received_sig_algs[MBEDTLS_RECEIVED_SIG_ALGS_SIZE]; +#endif + +#if !defined(MBEDTLS_DEPRECATED_REMOVED) + const uint16_t *group_list; + const uint16_t *sig_algs; +#endif + +#if defined(MBEDTLS_DHM_C) + mbedtls_dhm_context dhm_ctx; /*!< DHM key exchange */ +#endif + +#if !defined(MBEDTLS_USE_PSA_CRYPTO) && \ + defined(MBEDTLS_KEY_EXCHANGE_SOME_ECDH_OR_ECDHE_1_2_ENABLED) + mbedtls_ecdh_context ecdh_ctx; /*!< ECDH key exchange */ +#endif /* !MBEDTLS_USE_PSA_CRYPTO && + MBEDTLS_KEY_EXCHANGE_SOME_ECDH_OR_ECDHE_1_2_ENABLED */ + +#if defined(MBEDTLS_KEY_EXCHANGE_SOME_XXDH_PSA_ANY_ENABLED) + psa_key_type_t xxdh_psa_type; + size_t xxdh_psa_bits; + mbedtls_svc_key_id_t xxdh_psa_privkey; + uint8_t xxdh_psa_privkey_is_external; + unsigned char xxdh_psa_peerkey[PSA_EXPORT_PUBLIC_KEY_MAX_SIZE]; + size_t xxdh_psa_peerkey_len; +#endif /* MBEDTLS_KEY_EXCHANGE_SOME_XXDH_PSA_ANY_ENABLED */ + +#if defined(MBEDTLS_KEY_EXCHANGE_ECJPAKE_ENABLED) +#if defined(MBEDTLS_USE_PSA_CRYPTO) + psa_pake_operation_t psa_pake_ctx; /*!< EC J-PAKE key exchange */ + mbedtls_svc_key_id_t psa_pake_password; + uint8_t psa_pake_ctx_is_ok; +#else + mbedtls_ecjpake_context ecjpake_ctx; /*!< EC J-PAKE key exchange */ +#endif /* MBEDTLS_USE_PSA_CRYPTO */ +#if defined(MBEDTLS_SSL_CLI_C) + unsigned char *ecjpake_cache; /*!< Cache for ClientHello ext */ + size_t ecjpake_cache_len; /*!< Length of cached data */ +#endif +#endif /* MBEDTLS_KEY_EXCHANGE_ECJPAKE_ENABLED */ + +#if defined(MBEDTLS_KEY_EXCHANGE_SOME_ECDH_OR_ECDHE_ANY_ENABLED) || \ + defined(MBEDTLS_KEY_EXCHANGE_ECDSA_CERT_REQ_ANY_ALLOWED_ENABLED) || \ + defined(MBEDTLS_KEY_EXCHANGE_ECJPAKE_ENABLED) + uint16_t *curves_tls_id; /*!< List of TLS IDs of supported elliptic curves */ +#endif + +#if defined(MBEDTLS_SSL_HANDSHAKE_WITH_PSK_ENABLED) +#if defined(MBEDTLS_USE_PSA_CRYPTO) + mbedtls_svc_key_id_t psk_opaque; /*!< Opaque PSK from the callback */ + uint8_t psk_opaque_is_internal; +#else + unsigned char *psk; /*!< PSK from the callback */ + size_t psk_len; /*!< Length of PSK from callback */ +#endif /* MBEDTLS_USE_PSA_CRYPTO */ + uint16_t selected_identity; +#endif /* MBEDTLS_SSL_HANDSHAKE_WITH_PSK_ENABLED */ + +#if defined(MBEDTLS_SSL_ECP_RESTARTABLE_ENABLED) + mbedtls_x509_crt_restart_ctx ecrs_ctx; /*!< restart context */ +#endif + +#if defined(MBEDTLS_X509_CRT_PARSE_C) + mbedtls_ssl_key_cert *key_cert; /*!< chosen key/cert pair (server) */ +#if defined(MBEDTLS_SSL_SERVER_NAME_INDICATION) + mbedtls_ssl_key_cert *sni_key_cert; /*!< key/cert list from SNI */ + mbedtls_x509_crt *sni_ca_chain; /*!< trusted CAs from SNI callback */ + mbedtls_x509_crl *sni_ca_crl; /*!< trusted CAs CRLs from SNI */ +#endif /* MBEDTLS_SSL_SERVER_NAME_INDICATION */ +#endif /* MBEDTLS_X509_CRT_PARSE_C */ + +#if defined(MBEDTLS_X509_CRT_PARSE_C) && \ + !defined(MBEDTLS_SSL_KEEP_PEER_CERTIFICATE) + mbedtls_pk_context peer_pubkey; /*!< The public key from the peer. */ +#endif /* MBEDTLS_X509_CRT_PARSE_C && !MBEDTLS_SSL_KEEP_PEER_CERTIFICATE */ + + struct { + size_t total_bytes_buffered; /*!< Cumulative size of heap allocated + * buffers used for message buffering. */ + + uint8_t seen_ccs; /*!< Indicates if a CCS message has + * been seen in the current flight. */ + + struct mbedtls_ssl_hs_buffer { + unsigned is_valid : 1; + unsigned is_fragmented : 1; + unsigned is_complete : 1; + unsigned char *data; + size_t data_len; + } hs[MBEDTLS_SSL_MAX_BUFFERED_HS]; + + struct { + unsigned char *data; + size_t len; + unsigned epoch; + } future_record; + + } buffering; + +#if defined(MBEDTLS_SSL_CLI_C) && \ + (defined(MBEDTLS_SSL_PROTO_DTLS) || \ + defined(MBEDTLS_SSL_PROTO_TLS1_3)) + unsigned char *cookie; /*!< HelloVerifyRequest cookie for DTLS + * HelloRetryRequest cookie for TLS 1.3 */ +#if !defined(MBEDTLS_SSL_PROTO_TLS1_3) + /* RFC 6347 page 15 + ... + opaque cookie<0..2^8-1>; + ... + */ + uint8_t cookie_len; +#else + /* RFC 8446 page 39 + ... + opaque cookie<0..2^16-1>; + ... + If TLS1_3 is enabled, the max length is 2^16 - 1 + */ + uint16_t cookie_len; /*!< DTLS: HelloVerifyRequest cookie length + * TLS1_3: HelloRetryRequest cookie length */ +#endif +#endif /* MBEDTLS_SSL_CLI_C && + ( MBEDTLS_SSL_PROTO_DTLS || + MBEDTLS_SSL_PROTO_TLS1_3 ) */ +#if defined(MBEDTLS_SSL_SRV_C) && defined(MBEDTLS_SSL_PROTO_DTLS) + unsigned char cookie_verify_result; /*!< Srv: flag for sending a cookie */ +#endif /* MBEDTLS_SSL_SRV_C && MBEDTLS_SSL_PROTO_DTLS */ + +#if defined(MBEDTLS_SSL_PROTO_DTLS) + unsigned int out_msg_seq; /*!< Outgoing handshake sequence number */ + unsigned int in_msg_seq; /*!< Incoming handshake sequence number */ + + uint32_t retransmit_timeout; /*!< Current value of timeout */ + mbedtls_ssl_flight_item *flight; /*!< Current outgoing flight */ + mbedtls_ssl_flight_item *cur_msg; /*!< Current message in flight */ + unsigned char *cur_msg_p; /*!< Position in current message */ + unsigned int in_flight_start_seq; /*!< Minimum message sequence in the + flight being received */ + mbedtls_ssl_transform *alt_transform_out; /*!< Alternative transform for + resending messages */ + unsigned char alt_out_ctr[MBEDTLS_SSL_SEQUENCE_NUMBER_LEN]; /*!< Alternative record epoch/counter + for resending messages */ + +#if defined(MBEDTLS_SSL_DTLS_CONNECTION_ID) + /* The state of CID configuration in this handshake. */ + + uint8_t cid_in_use; /*!< This indicates whether the use of the CID extension + * has been negotiated. Possible values are + * #MBEDTLS_SSL_CID_ENABLED and + * #MBEDTLS_SSL_CID_DISABLED. */ + unsigned char peer_cid[MBEDTLS_SSL_CID_OUT_LEN_MAX]; /*! The peer's CID */ + uint8_t peer_cid_len; /*!< The length of + * \c peer_cid. */ +#endif /* MBEDTLS_SSL_DTLS_CONNECTION_ID */ + + uint16_t mtu; /*!< Handshake mtu, used to fragment outgoing messages */ +#endif /* MBEDTLS_SSL_PROTO_DTLS */ + + /* + * Checksum contexts + */ +#if defined(MBEDTLS_MD_CAN_SHA256) +#if defined(MBEDTLS_USE_PSA_CRYPTO) + psa_hash_operation_t fin_sha256_psa; +#else + mbedtls_md_context_t fin_sha256; +#endif +#endif +#if defined(MBEDTLS_MD_CAN_SHA384) +#if defined(MBEDTLS_USE_PSA_CRYPTO) + psa_hash_operation_t fin_sha384_psa; +#else + mbedtls_md_context_t fin_sha384; +#endif +#endif + +#if defined(MBEDTLS_SSL_PROTO_TLS1_3) + uint16_t offered_group_id; /* The NamedGroup value for the group + * that is being used for ephemeral + * key exchange. + * + * On the client: Defaults to the first + * entry in the client's group list, + * but can be overwritten by the HRR. */ +#endif /* MBEDTLS_SSL_PROTO_TLS1_3 */ + +#if defined(MBEDTLS_SSL_CLI_C) + uint8_t client_auth; /*!< used to check if CertificateRequest has been + received from server side. If CertificateRequest + has been received, Certificate and CertificateVerify + should be sent to server */ +#endif /* MBEDTLS_SSL_CLI_C */ + /* + * State-local variables used during the processing + * of a specific handshake state. + */ + union { + /* Outgoing Finished message */ + struct { + uint8_t preparation_done; + + /* Buffer holding digest of the handshake up to + * but excluding the outgoing finished message. */ + unsigned char digest[MBEDTLS_TLS1_3_MD_MAX_SIZE]; + size_t digest_len; + } finished_out; + + /* Incoming Finished message */ + struct { + uint8_t preparation_done; + + /* Buffer holding digest of the handshake up to but + * excluding the peer's incoming finished message. */ + unsigned char digest[MBEDTLS_TLS1_3_MD_MAX_SIZE]; + size_t digest_len; + } finished_in; + + } state_local; + + /* End of state-local variables. */ + + unsigned char randbytes[MBEDTLS_CLIENT_HELLO_RANDOM_LEN + + MBEDTLS_SERVER_HELLO_RANDOM_LEN]; + /*!< random bytes */ +#if defined(MBEDTLS_SSL_PROTO_TLS1_2) + unsigned char premaster[MBEDTLS_PREMASTER_SIZE]; + /*!< premaster secret */ + size_t pmslen; /*!< premaster length */ +#endif + +#if defined(MBEDTLS_SSL_PROTO_TLS1_3) + uint32_t sent_extensions; /*!< extensions sent by endpoint */ + uint32_t received_extensions; /*!< extensions received by endpoint */ + +#if defined(MBEDTLS_SSL_HANDSHAKE_WITH_CERT_ENABLED) + unsigned char certificate_request_context_len; + unsigned char *certificate_request_context; +#endif + + /** TLS 1.3 transform for encrypted handshake messages. */ + mbedtls_ssl_transform *transform_handshake; + union { + unsigned char early[MBEDTLS_TLS1_3_MD_MAX_SIZE]; + unsigned char handshake[MBEDTLS_TLS1_3_MD_MAX_SIZE]; + unsigned char app[MBEDTLS_TLS1_3_MD_MAX_SIZE]; + } tls13_master_secrets; + + mbedtls_ssl_tls13_handshake_secrets tls13_hs_secrets; +#if defined(MBEDTLS_SSL_EARLY_DATA) + /** TLS 1.3 transform for early data and handshake messages. */ + mbedtls_ssl_transform *transform_earlydata; +#endif +#endif /* MBEDTLS_SSL_PROTO_TLS1_3 */ + +#if defined(MBEDTLS_SSL_ASYNC_PRIVATE) + /** Asynchronous operation context. This field is meant for use by the + * asynchronous operation callbacks (mbedtls_ssl_config::f_async_sign_start, + * mbedtls_ssl_config::f_async_decrypt_start, + * mbedtls_ssl_config::f_async_resume, mbedtls_ssl_config::f_async_cancel). + * The library does not use it internally. */ + void *user_async_ctx; +#endif /* MBEDTLS_SSL_ASYNC_PRIVATE */ + +#if defined(MBEDTLS_SSL_SERVER_NAME_INDICATION) + const unsigned char *sni_name; /*!< raw SNI */ + size_t sni_name_len; /*!< raw SNI len */ +#if defined(MBEDTLS_KEY_EXCHANGE_CERT_REQ_ALLOWED_ENABLED) + const mbedtls_x509_crt *dn_hints; /*!< acceptable client cert issuers */ +#endif +#endif /* MBEDTLS_SSL_SERVER_NAME_INDICATION */ +}; + +typedef struct mbedtls_ssl_hs_buffer mbedtls_ssl_hs_buffer; + +/* + * Representation of decryption/encryption transformations on records + * + * There are the following general types of record transformations: + * - Stream transformations (TLS versions == 1.2 only) + * Transformation adding a MAC and applying a stream-cipher + * to the authenticated message. + * - CBC block cipher transformations ([D]TLS versions == 1.2 only) + * For TLS 1.2, no IV is generated at key extraction time, but every + * encrypted record is explicitly prefixed by the IV with which it was + * encrypted. + * - AEAD transformations ([D]TLS versions == 1.2 only) + * These come in two fundamentally different versions, the first one + * used in TLS 1.2, excluding ChaChaPoly ciphersuites, and the second + * one used for ChaChaPoly ciphersuites in TLS 1.2 as well as for TLS 1.3. + * In the first transformation, the IV to be used for a record is obtained + * as the concatenation of an explicit, static 4-byte IV and the 8-byte + * record sequence number, and explicitly prepending this sequence number + * to the encrypted record. In contrast, in the second transformation + * the IV is obtained by XOR'ing a static IV obtained at key extraction + * time with the 8-byte record sequence number, without prepending the + * latter to the encrypted record. + * + * Additionally, DTLS 1.2 + CID as well as TLS 1.3 use an inner plaintext + * which allows to add flexible length padding and to hide a record's true + * content type. + * + * In addition to type and version, the following parameters are relevant: + * - The symmetric cipher algorithm to be used. + * - The (static) encryption/decryption keys for the cipher. + * - For stream/CBC, the type of message digest to be used. + * - For stream/CBC, (static) encryption/decryption keys for the digest. + * - For AEAD transformations, the size (potentially 0) of an explicit, + * random initialization vector placed in encrypted records. + * - For some transformations (currently AEAD) an implicit IV. It is static + * and (if present) is combined with the explicit IV in a transformation- + * -dependent way (e.g. appending in TLS 1.2 and XOR'ing in TLS 1.3). + * - For stream/CBC, a flag determining the order of encryption and MAC. + * - The details of the transformation depend on the SSL/TLS version. + * - The length of the authentication tag. + * + * The struct below refines this abstract view as follows: + * - The cipher underlying the transformation is managed in + * cipher contexts cipher_ctx_{enc/dec}, which must have the + * same cipher type. The mode of these cipher contexts determines + * the type of the transformation in the sense above: e.g., if + * the type is MBEDTLS_CIPHER_AES_256_CBC resp. MBEDTLS_CIPHER_AES_192_GCM + * then the transformation has type CBC resp. AEAD. + * - The cipher keys are never stored explicitly but + * are maintained within cipher_ctx_{enc/dec}. + * - For stream/CBC transformations, the message digest contexts + * used for the MAC's are stored in md_ctx_{enc/dec}. These contexts + * are unused for AEAD transformations. + * - For stream/CBC transformations, the MAC keys are not stored explicitly + * but maintained within md_ctx_{enc/dec}. + * - The mac_enc and mac_dec fields are unused for EAD transformations. + * - For transformations using an implicit IV maintained within + * the transformation context, its contents are stored within + * iv_{enc/dec}. + * - The value of ivlen indicates the length of the IV. + * This is redundant in case of stream/CBC transformations + * which always use 0 resp. the cipher's block length as the + * IV length, but is needed for AEAD ciphers and may be + * different from the underlying cipher's block length + * in this case. + * - The field fixed_ivlen is nonzero for AEAD transformations only + * and indicates the length of the static part of the IV which is + * constant throughout the communication, and which is stored in + * the first fixed_ivlen bytes of the iv_{enc/dec} arrays. + * - tls_version denotes the 2-byte TLS version + * - For stream/CBC transformations, maclen denotes the length of the + * authentication tag, while taglen is unused and 0. + * - For AEAD transformations, taglen denotes the length of the + * authentication tag, while maclen is unused and 0. + * - For CBC transformations, encrypt_then_mac determines the + * order of encryption and authentication. This field is unused + * in other transformations. + * + */ +struct mbedtls_ssl_transform { + /* + * Session specific crypto layer + */ + size_t minlen; /*!< min. ciphertext length */ + size_t ivlen; /*!< IV length */ + size_t fixed_ivlen; /*!< Fixed part of IV (AEAD) */ + size_t maclen; /*!< MAC(CBC) len */ + size_t taglen; /*!< TAG(AEAD) len */ + + unsigned char iv_enc[16]; /*!< IV (encryption) */ + unsigned char iv_dec[16]; /*!< IV (decryption) */ + +#if defined(MBEDTLS_SSL_SOME_SUITES_USE_MAC) + +#if defined(MBEDTLS_USE_PSA_CRYPTO) + mbedtls_svc_key_id_t psa_mac_enc; /*!< MAC (encryption) */ + mbedtls_svc_key_id_t psa_mac_dec; /*!< MAC (decryption) */ + psa_algorithm_t psa_mac_alg; /*!< psa MAC algorithm */ +#else + mbedtls_md_context_t md_ctx_enc; /*!< MAC (encryption) */ + mbedtls_md_context_t md_ctx_dec; /*!< MAC (decryption) */ +#endif /* MBEDTLS_USE_PSA_CRYPTO */ + +#if defined(MBEDTLS_SSL_ENCRYPT_THEN_MAC) + int encrypt_then_mac; /*!< flag for EtM activation */ +#endif + +#endif /* MBEDTLS_SSL_SOME_SUITES_USE_MAC */ + + mbedtls_ssl_protocol_version tls_version; + +#if defined(MBEDTLS_USE_PSA_CRYPTO) + mbedtls_svc_key_id_t psa_key_enc; /*!< psa encryption key */ + mbedtls_svc_key_id_t psa_key_dec; /*!< psa decryption key */ + psa_algorithm_t psa_alg; /*!< psa algorithm */ +#else + mbedtls_cipher_context_t cipher_ctx_enc; /*!< encryption context */ + mbedtls_cipher_context_t cipher_ctx_dec; /*!< decryption context */ +#endif /* MBEDTLS_USE_PSA_CRYPTO */ + +#if defined(MBEDTLS_SSL_DTLS_CONNECTION_ID) + uint8_t in_cid_len; + uint8_t out_cid_len; + unsigned char in_cid[MBEDTLS_SSL_CID_IN_LEN_MAX]; + unsigned char out_cid[MBEDTLS_SSL_CID_OUT_LEN_MAX]; +#endif /* MBEDTLS_SSL_DTLS_CONNECTION_ID */ + +#if defined(MBEDTLS_SSL_CONTEXT_SERIALIZATION) + /* We need the Hello random bytes in order to re-derive keys from the + * Master Secret and other session info, + * see ssl_tls12_populate_transform() */ + unsigned char randbytes[MBEDTLS_SERVER_HELLO_RANDOM_LEN + + MBEDTLS_CLIENT_HELLO_RANDOM_LEN]; + /*!< ServerHello.random+ClientHello.random */ +#endif /* MBEDTLS_SSL_CONTEXT_SERIALIZATION */ +}; + +/* + * Return 1 if the transform uses an AEAD cipher, 0 otherwise. + * Equivalently, return 0 if a separate MAC is used, 1 otherwise. + */ +static inline int mbedtls_ssl_transform_uses_aead( + const mbedtls_ssl_transform *transform) +{ +#if defined(MBEDTLS_SSL_SOME_SUITES_USE_MAC) + return transform->maclen == 0 && transform->taglen != 0; +#else + (void) transform; + return 1; +#endif +} + +/* + * Internal representation of record frames + * + * Instances come in two flavors: + * (1) Encrypted + * These always have data_offset = 0 + * (2) Unencrypted + * These have data_offset set to the amount of + * pre-expansion during record protection. Concretely, + * this is the length of the fixed part of the explicit IV + * used for encryption, or 0 if no explicit IV is used + * (e.g. for stream ciphers). + * + * The reason for the data_offset in the unencrypted case + * is to allow for in-place conversion of an unencrypted to + * an encrypted record. If the offset wasn't included, the + * encrypted content would need to be shifted afterwards to + * make space for the fixed IV. + * + */ +#if MBEDTLS_SSL_CID_OUT_LEN_MAX > MBEDTLS_SSL_CID_IN_LEN_MAX +#define MBEDTLS_SSL_CID_LEN_MAX MBEDTLS_SSL_CID_OUT_LEN_MAX +#else +#define MBEDTLS_SSL_CID_LEN_MAX MBEDTLS_SSL_CID_IN_LEN_MAX +#endif + +typedef struct { + uint8_t ctr[MBEDTLS_SSL_SEQUENCE_NUMBER_LEN]; /* In TLS: The implicit record sequence number. + * In DTLS: The 2-byte epoch followed by + * the 6-byte sequence number. + * This is stored as a raw big endian byte array + * as opposed to a uint64_t because we rarely + * need to perform arithmetic on this, but do + * need it as a Byte array for the purpose of + * MAC computations. */ + uint8_t type; /* The record content type. */ + uint8_t ver[2]; /* SSL/TLS version as present on the wire. + * Convert to internal presentation of versions + * using mbedtls_ssl_read_version() and + * mbedtls_ssl_write_version(). + * Keep wire-format for MAC computations. */ + + unsigned char *buf; /* Memory buffer enclosing the record content */ + size_t buf_len; /* Buffer length */ + size_t data_offset; /* Offset of record content */ + size_t data_len; /* Length of record content */ + +#if defined(MBEDTLS_SSL_DTLS_CONNECTION_ID) + uint8_t cid_len; /* Length of the CID (0 if not present) */ + unsigned char cid[MBEDTLS_SSL_CID_LEN_MAX]; /* The CID */ +#endif /* MBEDTLS_SSL_DTLS_CONNECTION_ID */ +} mbedtls_record; + +#if defined(MBEDTLS_X509_CRT_PARSE_C) +/* + * List of certificate + private key pairs + */ +struct mbedtls_ssl_key_cert { + mbedtls_x509_crt *cert; /*!< cert */ + mbedtls_pk_context *key; /*!< private key */ + mbedtls_ssl_key_cert *next; /*!< next key/cert pair */ +}; +#endif /* MBEDTLS_X509_CRT_PARSE_C */ + +#if defined(MBEDTLS_SSL_PROTO_DTLS) +/* + * List of handshake messages kept around for resending + */ +struct mbedtls_ssl_flight_item { + unsigned char *p; /*!< message, including handshake headers */ + size_t len; /*!< length of p */ + unsigned char type; /*!< type of the message: handshake or CCS */ + mbedtls_ssl_flight_item *next; /*!< next handshake message(s) */ +}; +#endif /* MBEDTLS_SSL_PROTO_DTLS */ + +#if defined(MBEDTLS_SSL_PROTO_TLS1_2) +/** + * \brief Given an SSL context and its associated configuration, write the TLS + * 1.2 specific extensions of the ClientHello message. + * + * \param[in] ssl SSL context + * \param[in] buf Base address of the buffer where to write the extensions + * \param[in] end End address of the buffer where to write the extensions + * \param uses_ec Whether one proposed ciphersuite uses an elliptic curve + * (<> 0) or not ( 0 ). + * \param[out] out_len Length of the data written into the buffer \p buf + */ +MBEDTLS_CHECK_RETURN_CRITICAL +int mbedtls_ssl_tls12_write_client_hello_exts(mbedtls_ssl_context *ssl, + unsigned char *buf, + const unsigned char *end, + int uses_ec, + size_t *out_len); +#endif + +#if defined(MBEDTLS_SSL_PROTO_TLS1_2) && \ + defined(MBEDTLS_KEY_EXCHANGE_WITH_CERT_ENABLED) + +/** + * \brief Find the preferred hash for a given signature algorithm. + * + * \param[in] ssl SSL context + * \param[in] sig_alg A signature algorithm identifier as defined in the + * TLS 1.2 SignatureAlgorithm enumeration. + * + * \return The preferred hash algorithm for \p sig_alg. It is a hash algorithm + * identifier as defined in the TLS 1.2 HashAlgorithm enumeration. + */ +unsigned int mbedtls_ssl_tls12_get_preferred_hash_for_sig_alg( + mbedtls_ssl_context *ssl, + unsigned int sig_alg); + +#endif /* MBEDTLS_SSL_PROTO_TLS1_2 && + MBEDTLS_KEY_EXCHANGE_WITH_CERT_ENABLED */ + +/** + * \brief Free referenced items in an SSL transform context and clear + * memory + * + * \param transform SSL transform context + */ +void mbedtls_ssl_transform_free(mbedtls_ssl_transform *transform); + +/** + * \brief Free referenced items in an SSL handshake context and clear + * memory + * + * \param ssl SSL context + */ +void mbedtls_ssl_handshake_free(mbedtls_ssl_context *ssl); + +/* set inbound transform of ssl context */ +void mbedtls_ssl_set_inbound_transform(mbedtls_ssl_context *ssl, + mbedtls_ssl_transform *transform); + +/* set outbound transform of ssl context */ +void mbedtls_ssl_set_outbound_transform(mbedtls_ssl_context *ssl, + mbedtls_ssl_transform *transform); + +MBEDTLS_CHECK_RETURN_CRITICAL +int mbedtls_ssl_handshake_client_step(mbedtls_ssl_context *ssl); +MBEDTLS_CHECK_RETURN_CRITICAL +int mbedtls_ssl_handshake_server_step(mbedtls_ssl_context *ssl); +void mbedtls_ssl_handshake_wrapup(mbedtls_ssl_context *ssl); +static inline void mbedtls_ssl_handshake_set_state(mbedtls_ssl_context *ssl, + mbedtls_ssl_states state) +{ + ssl->state = (int) state; +} + +MBEDTLS_CHECK_RETURN_CRITICAL +int mbedtls_ssl_send_fatal_handshake_failure(mbedtls_ssl_context *ssl); + +MBEDTLS_CHECK_RETURN_CRITICAL +int mbedtls_ssl_reset_checksum(mbedtls_ssl_context *ssl); + +#if defined(MBEDTLS_SSL_PROTO_TLS1_2) +MBEDTLS_CHECK_RETURN_CRITICAL +int mbedtls_ssl_derive_keys(mbedtls_ssl_context *ssl); +#endif /* MBEDTLS_SSL_PROTO_TLS1_2 */ + +MBEDTLS_CHECK_RETURN_CRITICAL +int mbedtls_ssl_handle_message_type(mbedtls_ssl_context *ssl); +MBEDTLS_CHECK_RETURN_CRITICAL +int mbedtls_ssl_prepare_handshake_record(mbedtls_ssl_context *ssl); +MBEDTLS_CHECK_RETURN_CRITICAL +int mbedtls_ssl_update_handshake_status(mbedtls_ssl_context *ssl); + +/** + * \brief Update record layer + * + * This function roughly separates the implementation + * of the logic of (D)TLS from the implementation + * of the secure transport. + * + * \param ssl The SSL context to use. + * \param update_hs_digest This indicates if the handshake digest + * should be automatically updated in case + * a handshake message is found. + * + * \return 0 or non-zero error code. + * + * \note A clarification on what is called 'record layer' here + * is in order, as many sensible definitions are possible: + * + * The record layer takes as input an untrusted underlying + * transport (stream or datagram) and transforms it into + * a serially multiplexed, secure transport, which + * conceptually provides the following: + * + * (1) Three datagram based, content-agnostic transports + * for handshake, alert and CCS messages. + * (2) One stream- or datagram-based transport + * for application data. + * (3) Functionality for changing the underlying transform + * securing the contents. + * + * The interface to this functionality is given as follows: + * + * a Updating + * [Currently implemented by mbedtls_ssl_read_record] + * + * Check if and on which of the four 'ports' data is pending: + * Nothing, a controlling datagram of type (1), or application + * data (2). In any case data is present, internal buffers + * provide access to the data for the user to process it. + * Consumption of type (1) datagrams is done automatically + * on the next update, invalidating that the internal buffers + * for previous datagrams, while consumption of application + * data (2) is user-controlled. + * + * b Reading of application data + * [Currently manual adaption of ssl->in_offt pointer] + * + * As mentioned in the last paragraph, consumption of data + * is different from the automatic consumption of control + * datagrams (1) because application data is treated as a stream. + * + * c Tracking availability of application data + * [Currently manually through decreasing ssl->in_msglen] + * + * For efficiency and to retain datagram semantics for + * application data in case of DTLS, the record layer + * provides functionality for checking how much application + * data is still available in the internal buffer. + * + * d Changing the transformation securing the communication. + * + * Given an opaque implementation of the record layer in the + * above sense, it should be possible to implement the logic + * of (D)TLS on top of it without the need to know anything + * about the record layer's internals. This is done e.g. + * in all the handshake handling functions, and in the + * application data reading function mbedtls_ssl_read. + * + * \note The above tries to give a conceptual picture of the + * record layer, but the current implementation deviates + * from it in some places. For example, our implementation of + * the update functionality through mbedtls_ssl_read_record + * discards datagrams depending on the current state, which + * wouldn't fall under the record layer's responsibility + * following the above definition. + * + */ +MBEDTLS_CHECK_RETURN_CRITICAL +int mbedtls_ssl_read_record(mbedtls_ssl_context *ssl, + unsigned update_hs_digest); +MBEDTLS_CHECK_RETURN_CRITICAL +int mbedtls_ssl_fetch_input(mbedtls_ssl_context *ssl, size_t nb_want); + +/* + * Write handshake message header + */ +MBEDTLS_CHECK_RETURN_CRITICAL +int mbedtls_ssl_start_handshake_msg(mbedtls_ssl_context *ssl, unsigned char hs_type, + unsigned char **buf, size_t *buf_len); + +MBEDTLS_CHECK_RETURN_CRITICAL +int mbedtls_ssl_write_handshake_msg_ext(mbedtls_ssl_context *ssl, + int update_checksum, + int force_flush); +static inline int mbedtls_ssl_write_handshake_msg(mbedtls_ssl_context *ssl) +{ + return mbedtls_ssl_write_handshake_msg_ext(ssl, 1 /* update checksum */, 1 /* force flush */); +} + +/* + * Write handshake message tail + */ +MBEDTLS_CHECK_RETURN_CRITICAL +int mbedtls_ssl_finish_handshake_msg(mbedtls_ssl_context *ssl, + size_t buf_len, size_t msg_len); + +MBEDTLS_CHECK_RETURN_CRITICAL +int mbedtls_ssl_write_record(mbedtls_ssl_context *ssl, int force_flush); +MBEDTLS_CHECK_RETURN_CRITICAL +int mbedtls_ssl_flush_output(mbedtls_ssl_context *ssl); + +MBEDTLS_CHECK_RETURN_CRITICAL +int mbedtls_ssl_parse_certificate(mbedtls_ssl_context *ssl); +MBEDTLS_CHECK_RETURN_CRITICAL +int mbedtls_ssl_write_certificate(mbedtls_ssl_context *ssl); + +MBEDTLS_CHECK_RETURN_CRITICAL +int mbedtls_ssl_parse_change_cipher_spec(mbedtls_ssl_context *ssl); +MBEDTLS_CHECK_RETURN_CRITICAL +int mbedtls_ssl_write_change_cipher_spec(mbedtls_ssl_context *ssl); + +MBEDTLS_CHECK_RETURN_CRITICAL +int mbedtls_ssl_parse_finished(mbedtls_ssl_context *ssl); +MBEDTLS_CHECK_RETURN_CRITICAL +int mbedtls_ssl_write_finished(mbedtls_ssl_context *ssl); + +void mbedtls_ssl_optimize_checksum(mbedtls_ssl_context *ssl, + const mbedtls_ssl_ciphersuite_t *ciphersuite_info); + +/* + * Update checksum of handshake messages. + */ +MBEDTLS_CHECK_RETURN_CRITICAL +int mbedtls_ssl_add_hs_msg_to_checksum(mbedtls_ssl_context *ssl, + unsigned hs_type, + unsigned char const *msg, + size_t msg_len); + +MBEDTLS_CHECK_RETURN_CRITICAL +int mbedtls_ssl_add_hs_hdr_to_checksum(mbedtls_ssl_context *ssl, + unsigned hs_type, + size_t total_hs_len); + +#if defined(MBEDTLS_KEY_EXCHANGE_SOME_PSK_ENABLED) +#if !defined(MBEDTLS_USE_PSA_CRYPTO) +MBEDTLS_CHECK_RETURN_CRITICAL +int mbedtls_ssl_psk_derive_premaster(mbedtls_ssl_context *ssl, + mbedtls_key_exchange_type_t key_ex); +#endif /* !MBEDTLS_USE_PSA_CRYPTO */ +#endif /* MBEDTLS_KEY_EXCHANGE_SOME_PSK_ENABLED */ + +#if defined(MBEDTLS_SSL_HANDSHAKE_WITH_PSK_ENABLED) +#if defined(MBEDTLS_SSL_CLI_C) +MBEDTLS_CHECK_RETURN_CRITICAL +int mbedtls_ssl_conf_has_static_psk(mbedtls_ssl_config const *conf); +#endif +#if defined(MBEDTLS_USE_PSA_CRYPTO) +/** + * Get the first defined opaque PSK by order of precedence: + * 1. handshake PSK set by \c mbedtls_ssl_set_hs_psk_opaque() in the PSK + * callback + * 2. static PSK configured by \c mbedtls_ssl_conf_psk_opaque() + * Return an opaque PSK + */ +static inline mbedtls_svc_key_id_t mbedtls_ssl_get_opaque_psk( + const mbedtls_ssl_context *ssl) +{ + if (!mbedtls_svc_key_id_is_null(ssl->handshake->psk_opaque)) { + return ssl->handshake->psk_opaque; + } + + if (!mbedtls_svc_key_id_is_null(ssl->conf->psk_opaque)) { + return ssl->conf->psk_opaque; + } + + return MBEDTLS_SVC_KEY_ID_INIT; +} +#else +/** + * Get the first defined PSK by order of precedence: + * 1. handshake PSK set by \c mbedtls_ssl_set_hs_psk() in the PSK callback + * 2. static PSK configured by \c mbedtls_ssl_conf_psk() + * Return a code and update the pair (PSK, PSK length) passed to this function + */ +static inline int mbedtls_ssl_get_psk(const mbedtls_ssl_context *ssl, + const unsigned char **psk, size_t *psk_len) +{ + if (ssl->handshake->psk != NULL && ssl->handshake->psk_len > 0) { + *psk = ssl->handshake->psk; + *psk_len = ssl->handshake->psk_len; + } else if (ssl->conf->psk != NULL && ssl->conf->psk_len > 0) { + *psk = ssl->conf->psk; + *psk_len = ssl->conf->psk_len; + } else { + *psk = NULL; + *psk_len = 0; + return MBEDTLS_ERR_SSL_PRIVATE_KEY_REQUIRED; + } + + return 0; +} +#endif /* MBEDTLS_USE_PSA_CRYPTO */ + +#endif /* MBEDTLS_SSL_HANDSHAKE_WITH_PSK_ENABLED */ + +#if defined(MBEDTLS_PK_C) +unsigned char mbedtls_ssl_sig_from_pk(mbedtls_pk_context *pk); +unsigned char mbedtls_ssl_sig_from_pk_alg(mbedtls_pk_type_t type); +mbedtls_pk_type_t mbedtls_ssl_pk_alg_from_sig(unsigned char sig); +#endif + +mbedtls_md_type_t mbedtls_ssl_md_alg_from_hash(unsigned char hash); +unsigned char mbedtls_ssl_hash_from_md_alg(int md); + +#if defined(MBEDTLS_SSL_PROTO_TLS1_2) +MBEDTLS_CHECK_RETURN_CRITICAL +int mbedtls_ssl_set_calc_verify_md(mbedtls_ssl_context *ssl, int md); +#endif + +MBEDTLS_CHECK_RETURN_CRITICAL +int mbedtls_ssl_check_curve_tls_id(const mbedtls_ssl_context *ssl, uint16_t tls_id); +#if defined(MBEDTLS_PK_HAVE_ECC_KEYS) +MBEDTLS_CHECK_RETURN_CRITICAL +int mbedtls_ssl_check_curve(const mbedtls_ssl_context *ssl, mbedtls_ecp_group_id grp_id); +#endif /* MBEDTLS_PK_HAVE_ECC_KEYS */ + +/** + * \brief Return PSA EC info for the specified TLS ID. + * + * \param tls_id The TLS ID to look for + * \param type If the TLD ID is supported, then proper \c psa_key_type_t + * value is returned here. Can be NULL. + * \param bits If the TLD ID is supported, then proper bit size is returned + * here. Can be NULL. + * \return PSA_SUCCESS if the TLS ID is supported, + * PSA_ERROR_NOT_SUPPORTED otherwise + * + * \note If either \c family or \c bits parameters are NULL, then + * the corresponding value is not returned. + * The function can be called with both parameters as NULL + * simply to check if a specific TLS ID is supported. + */ +int mbedtls_ssl_get_psa_curve_info_from_tls_id(uint16_t tls_id, + psa_key_type_t *type, + size_t *bits); + +/** + * \brief Return \c mbedtls_ecp_group_id for the specified TLS ID. + * + * \param tls_id The TLS ID to look for + * \return Proper \c mbedtls_ecp_group_id if the TLS ID is supported, + * or MBEDTLS_ECP_DP_NONE otherwise + */ +mbedtls_ecp_group_id mbedtls_ssl_get_ecp_group_id_from_tls_id(uint16_t tls_id); + +/** + * \brief Return TLS ID for the specified \c mbedtls_ecp_group_id. + * + * \param grp_id The \c mbedtls_ecp_group_id ID to look for + * \return Proper TLS ID if the \c mbedtls_ecp_group_id is supported, + * or 0 otherwise + */ +uint16_t mbedtls_ssl_get_tls_id_from_ecp_group_id(mbedtls_ecp_group_id grp_id); + +#if defined(MBEDTLS_DEBUG_C) +/** + * \brief Return EC's name for the specified TLS ID. + * + * \param tls_id The TLS ID to look for + * \return A pointer to a const string with the proper name. If TLS + * ID is not supported, a NULL pointer is returned instead. + */ +const char *mbedtls_ssl_get_curve_name_from_tls_id(uint16_t tls_id); +#endif + +#if defined(MBEDTLS_SSL_DTLS_SRTP) +static inline mbedtls_ssl_srtp_profile mbedtls_ssl_check_srtp_profile_value + (const uint16_t srtp_profile_value) +{ + switch (srtp_profile_value) { + case MBEDTLS_TLS_SRTP_AES128_CM_HMAC_SHA1_80: + case MBEDTLS_TLS_SRTP_AES128_CM_HMAC_SHA1_32: + case MBEDTLS_TLS_SRTP_NULL_HMAC_SHA1_80: + case MBEDTLS_TLS_SRTP_NULL_HMAC_SHA1_32: + return srtp_profile_value; + default: break; + } + return MBEDTLS_TLS_SRTP_UNSET; +} +#endif + +#if defined(MBEDTLS_X509_CRT_PARSE_C) +static inline mbedtls_pk_context *mbedtls_ssl_own_key(mbedtls_ssl_context *ssl) +{ + mbedtls_ssl_key_cert *key_cert; + + if (ssl->handshake != NULL && ssl->handshake->key_cert != NULL) { + key_cert = ssl->handshake->key_cert; + } else { + key_cert = ssl->conf->key_cert; + } + + return key_cert == NULL ? NULL : key_cert->key; +} + +static inline mbedtls_x509_crt *mbedtls_ssl_own_cert(mbedtls_ssl_context *ssl) +{ + mbedtls_ssl_key_cert *key_cert; + + if (ssl->handshake != NULL && ssl->handshake->key_cert != NULL) { + key_cert = ssl->handshake->key_cert; + } else { + key_cert = ssl->conf->key_cert; + } + + return key_cert == NULL ? NULL : key_cert->cert; +} + +/* + * Check usage of a certificate wrt extensions: + * keyUsage, extendedKeyUsage (later), and nSCertType (later). + * + * Warning: cert_endpoint is the endpoint of the cert (ie, of our peer when we + * check a cert we received from them)! + * + * Return 0 if everything is OK, -1 if not. + */ +MBEDTLS_CHECK_RETURN_CRITICAL +int mbedtls_ssl_check_cert_usage(const mbedtls_x509_crt *cert, + const mbedtls_ssl_ciphersuite_t *ciphersuite, + int cert_endpoint, + uint32_t *flags); +#endif /* MBEDTLS_X509_CRT_PARSE_C */ + +void mbedtls_ssl_write_version(unsigned char version[2], int transport, + mbedtls_ssl_protocol_version tls_version); +uint16_t mbedtls_ssl_read_version(const unsigned char version[2], + int transport); + +static inline size_t mbedtls_ssl_in_hdr_len(const mbedtls_ssl_context *ssl) +{ +#if !defined(MBEDTLS_SSL_PROTO_DTLS) + ((void) ssl); +#endif + +#if defined(MBEDTLS_SSL_PROTO_DTLS) + if (ssl->conf->transport == MBEDTLS_SSL_TRANSPORT_DATAGRAM) { + return 13; + } else +#endif /* MBEDTLS_SSL_PROTO_DTLS */ + { + return 5; + } +} + +static inline size_t mbedtls_ssl_out_hdr_len(const mbedtls_ssl_context *ssl) +{ + return (size_t) (ssl->out_iv - ssl->out_hdr); +} + +static inline size_t mbedtls_ssl_hs_hdr_len(const mbedtls_ssl_context *ssl) +{ +#if defined(MBEDTLS_SSL_PROTO_DTLS) + if (ssl->conf->transport == MBEDTLS_SSL_TRANSPORT_DATAGRAM) { + return 12; + } +#else + ((void) ssl); +#endif + return 4; +} + +#if defined(MBEDTLS_SSL_PROTO_DTLS) +void mbedtls_ssl_send_flight_completed(mbedtls_ssl_context *ssl); +void mbedtls_ssl_recv_flight_completed(mbedtls_ssl_context *ssl); +MBEDTLS_CHECK_RETURN_CRITICAL +int mbedtls_ssl_resend(mbedtls_ssl_context *ssl); +MBEDTLS_CHECK_RETURN_CRITICAL +int mbedtls_ssl_flight_transmit(mbedtls_ssl_context *ssl); +#endif + +/* Visible for testing purposes only */ +#if defined(MBEDTLS_SSL_DTLS_ANTI_REPLAY) +MBEDTLS_CHECK_RETURN_CRITICAL +int mbedtls_ssl_dtls_replay_check(mbedtls_ssl_context const *ssl); +void mbedtls_ssl_dtls_replay_update(mbedtls_ssl_context *ssl); +#endif + +MBEDTLS_CHECK_RETURN_CRITICAL +int mbedtls_ssl_session_copy(mbedtls_ssl_session *dst, + const mbedtls_ssl_session *src); + +#if defined(MBEDTLS_SSL_PROTO_TLS1_2) +/* The hash buffer must have at least MBEDTLS_MD_MAX_SIZE bytes of length. */ +MBEDTLS_CHECK_RETURN_CRITICAL +int mbedtls_ssl_get_key_exchange_md_tls1_2(mbedtls_ssl_context *ssl, + unsigned char *hash, size_t *hashlen, + unsigned char *data, size_t data_len, + mbedtls_md_type_t md_alg); +#endif /* MBEDTLS_SSL_PROTO_TLS1_2 */ + +#ifdef __cplusplus +} +#endif + +void mbedtls_ssl_transform_init(mbedtls_ssl_transform *transform); +MBEDTLS_CHECK_RETURN_CRITICAL +int mbedtls_ssl_encrypt_buf(mbedtls_ssl_context *ssl, + mbedtls_ssl_transform *transform, + mbedtls_record *rec, + int (*f_rng)(void *, unsigned char *, size_t), + void *p_rng); +MBEDTLS_CHECK_RETURN_CRITICAL +int mbedtls_ssl_decrypt_buf(mbedtls_ssl_context const *ssl, + mbedtls_ssl_transform *transform, + mbedtls_record *rec); + +/* Length of the "epoch" field in the record header */ +static inline size_t mbedtls_ssl_ep_len(const mbedtls_ssl_context *ssl) +{ +#if defined(MBEDTLS_SSL_PROTO_DTLS) + if (ssl->conf->transport == MBEDTLS_SSL_TRANSPORT_DATAGRAM) { + return 2; + } +#else + ((void) ssl); +#endif + return 0; +} + +#if defined(MBEDTLS_SSL_PROTO_DTLS) +MBEDTLS_CHECK_RETURN_CRITICAL +int mbedtls_ssl_resend_hello_request(mbedtls_ssl_context *ssl); +#endif /* MBEDTLS_SSL_PROTO_DTLS */ + +void mbedtls_ssl_set_timer(mbedtls_ssl_context *ssl, uint32_t millisecs); +MBEDTLS_CHECK_RETURN_CRITICAL +int mbedtls_ssl_check_timer(mbedtls_ssl_context *ssl); + +void mbedtls_ssl_reset_in_out_pointers(mbedtls_ssl_context *ssl); +void mbedtls_ssl_update_out_pointers(mbedtls_ssl_context *ssl, + mbedtls_ssl_transform *transform); +void mbedtls_ssl_update_in_pointers(mbedtls_ssl_context *ssl); + +MBEDTLS_CHECK_RETURN_CRITICAL +int mbedtls_ssl_session_reset_int(mbedtls_ssl_context *ssl, int partial); +void mbedtls_ssl_session_reset_msg_layer(mbedtls_ssl_context *ssl, + int partial); + +/* + * Send pending alert + */ +MBEDTLS_CHECK_RETURN_CRITICAL +int mbedtls_ssl_handle_pending_alert(mbedtls_ssl_context *ssl); + +/* + * Set pending fatal alert flag. + */ +void mbedtls_ssl_pend_fatal_alert(mbedtls_ssl_context *ssl, + unsigned char alert_type, + int alert_reason); + +/* Alias of mbedtls_ssl_pend_fatal_alert */ +#define MBEDTLS_SSL_PEND_FATAL_ALERT(type, user_return_value) \ + mbedtls_ssl_pend_fatal_alert(ssl, type, user_return_value) + +#if defined(MBEDTLS_SSL_DTLS_ANTI_REPLAY) +void mbedtls_ssl_dtls_replay_reset(mbedtls_ssl_context *ssl); +#endif + +void mbedtls_ssl_handshake_wrapup_free_hs_transform(mbedtls_ssl_context *ssl); + +#if defined(MBEDTLS_SSL_RENEGOTIATION) +MBEDTLS_CHECK_RETURN_CRITICAL +int mbedtls_ssl_start_renegotiation(mbedtls_ssl_context *ssl); +#endif /* MBEDTLS_SSL_RENEGOTIATION */ + +#if defined(MBEDTLS_SSL_PROTO_DTLS) +size_t mbedtls_ssl_get_current_mtu(const mbedtls_ssl_context *ssl); +void mbedtls_ssl_buffering_free(mbedtls_ssl_context *ssl); +void mbedtls_ssl_flight_free(mbedtls_ssl_flight_item *flight); +#endif /* MBEDTLS_SSL_PROTO_DTLS */ + +/** + * ssl utils functions for checking configuration. + */ + +#if defined(MBEDTLS_SSL_PROTO_TLS1_3) +static inline int mbedtls_ssl_conf_is_tls13_only(const mbedtls_ssl_config *conf) +{ + return conf->min_tls_version == MBEDTLS_SSL_VERSION_TLS1_3 && + conf->max_tls_version == MBEDTLS_SSL_VERSION_TLS1_3; +} + +#endif /* MBEDTLS_SSL_PROTO_TLS1_3 */ + +#if defined(MBEDTLS_SSL_PROTO_TLS1_2) +static inline int mbedtls_ssl_conf_is_tls12_only(const mbedtls_ssl_config *conf) +{ + return conf->min_tls_version == MBEDTLS_SSL_VERSION_TLS1_2 && + conf->max_tls_version == MBEDTLS_SSL_VERSION_TLS1_2; +} + +#endif /* MBEDTLS_SSL_PROTO_TLS1_2 */ + +static inline int mbedtls_ssl_conf_is_tls13_enabled(const mbedtls_ssl_config *conf) +{ +#if defined(MBEDTLS_SSL_PROTO_TLS1_3) + return conf->min_tls_version <= MBEDTLS_SSL_VERSION_TLS1_3 && + conf->max_tls_version >= MBEDTLS_SSL_VERSION_TLS1_3; +#else + ((void) conf); + return 0; +#endif +} + +static inline int mbedtls_ssl_conf_is_tls12_enabled(const mbedtls_ssl_config *conf) +{ +#if defined(MBEDTLS_SSL_PROTO_TLS1_2) + return conf->min_tls_version <= MBEDTLS_SSL_VERSION_TLS1_2 && + conf->max_tls_version >= MBEDTLS_SSL_VERSION_TLS1_2; +#else + ((void) conf); + return 0; +#endif +} + +#if defined(MBEDTLS_SSL_PROTO_TLS1_2) && defined(MBEDTLS_SSL_PROTO_TLS1_3) +static inline int mbedtls_ssl_conf_is_hybrid_tls12_tls13(const mbedtls_ssl_config *conf) +{ + return conf->min_tls_version == MBEDTLS_SSL_VERSION_TLS1_2 && + conf->max_tls_version == MBEDTLS_SSL_VERSION_TLS1_3; +} +#endif /* MBEDTLS_SSL_PROTO_TLS1_2 && MBEDTLS_SSL_PROTO_TLS1_3 */ + +#if defined(MBEDTLS_SSL_PROTO_TLS1_3) +extern const uint8_t mbedtls_ssl_tls13_hello_retry_request_magic[ + MBEDTLS_SERVER_HELLO_RANDOM_LEN]; +MBEDTLS_CHECK_RETURN_CRITICAL +int mbedtls_ssl_tls13_process_finished_message(mbedtls_ssl_context *ssl); +MBEDTLS_CHECK_RETURN_CRITICAL +int mbedtls_ssl_tls13_write_finished_message(mbedtls_ssl_context *ssl); +void mbedtls_ssl_tls13_handshake_wrapup(mbedtls_ssl_context *ssl); + +/** + * \brief Given an SSL context and its associated configuration, write the TLS + * 1.3 specific extensions of the ClientHello message. + * + * \param[in] ssl SSL context + * \param[in] buf Base address of the buffer where to write the extensions + * \param[in] end End address of the buffer where to write the extensions + * \param[out] out_len Length of the data written into the buffer \p buf + */ +MBEDTLS_CHECK_RETURN_CRITICAL +int mbedtls_ssl_tls13_write_client_hello_exts(mbedtls_ssl_context *ssl, + unsigned char *buf, + unsigned char *end, + size_t *out_len); + +/** + * \brief TLS 1.3 client side state machine entry + * + * \param ssl SSL context + */ +MBEDTLS_CHECK_RETURN_CRITICAL +int mbedtls_ssl_tls13_handshake_client_step(mbedtls_ssl_context *ssl); + +/** + * \brief TLS 1.3 server side state machine entry + * + * \param ssl SSL context + */ +MBEDTLS_CHECK_RETURN_CRITICAL +int mbedtls_ssl_tls13_handshake_server_step(mbedtls_ssl_context *ssl); + + +/* + * Helper functions around key exchange modes. + */ +static inline int mbedtls_ssl_conf_tls13_is_kex_mode_enabled(mbedtls_ssl_context *ssl, + int kex_mode_mask) +{ + return (ssl->conf->tls13_kex_modes & kex_mode_mask) != 0; +} + +static inline int mbedtls_ssl_conf_tls13_is_psk_enabled(mbedtls_ssl_context *ssl) +{ + return mbedtls_ssl_conf_tls13_is_kex_mode_enabled(ssl, + MBEDTLS_SSL_TLS1_3_KEY_EXCHANGE_MODE_PSK); +} + +static inline int mbedtls_ssl_conf_tls13_is_psk_ephemeral_enabled(mbedtls_ssl_context *ssl) +{ + return mbedtls_ssl_conf_tls13_is_kex_mode_enabled(ssl, + MBEDTLS_SSL_TLS1_3_KEY_EXCHANGE_MODE_PSK_EPHEMERAL); +} + +static inline int mbedtls_ssl_conf_tls13_is_ephemeral_enabled(mbedtls_ssl_context *ssl) +{ + return mbedtls_ssl_conf_tls13_is_kex_mode_enabled(ssl, + MBEDTLS_SSL_TLS1_3_KEY_EXCHANGE_MODE_EPHEMERAL); +} + +static inline int mbedtls_ssl_conf_tls13_is_some_ephemeral_enabled(mbedtls_ssl_context *ssl) +{ + return mbedtls_ssl_conf_tls13_is_kex_mode_enabled(ssl, + MBEDTLS_SSL_TLS1_3_KEY_EXCHANGE_MODE_EPHEMERAL_ALL); +} + +static inline int mbedtls_ssl_conf_tls13_is_some_psk_enabled(mbedtls_ssl_context *ssl) +{ + return mbedtls_ssl_conf_tls13_is_kex_mode_enabled(ssl, + MBEDTLS_SSL_TLS1_3_KEY_EXCHANGE_MODE_PSK_ALL); +} + +#if defined(MBEDTLS_SSL_SRV_C) && \ + defined(MBEDTLS_SSL_TLS1_3_KEY_EXCHANGE_MODE_SOME_PSK_ENABLED) +/** + * Given a list of key exchange modes, check if at least one of them is + * supported by peer. + * + * \param[in] ssl SSL context + * \param kex_modes_mask Mask of the key exchange modes to check + * + * \return Non-zero if at least one of the key exchange modes is supported by + * the peer, otherwise \c 0. + */ +static inline int mbedtls_ssl_tls13_is_kex_mode_supported(mbedtls_ssl_context *ssl, + int kex_modes_mask) +{ + return (ssl->handshake->tls13_kex_modes & kex_modes_mask) != 0; +} + +static inline int mbedtls_ssl_tls13_is_psk_supported(mbedtls_ssl_context *ssl) +{ + return mbedtls_ssl_tls13_is_kex_mode_supported(ssl, + MBEDTLS_SSL_TLS1_3_KEY_EXCHANGE_MODE_PSK); +} + +static inline int mbedtls_ssl_tls13_is_psk_ephemeral_supported( + mbedtls_ssl_context *ssl) +{ + return mbedtls_ssl_tls13_is_kex_mode_supported(ssl, + MBEDTLS_SSL_TLS1_3_KEY_EXCHANGE_MODE_PSK_EPHEMERAL); +} + +static inline int mbedtls_ssl_tls13_is_ephemeral_supported(mbedtls_ssl_context *ssl) +{ + return mbedtls_ssl_tls13_is_kex_mode_supported(ssl, + MBEDTLS_SSL_TLS1_3_KEY_EXCHANGE_MODE_EPHEMERAL); +} + +static inline int mbedtls_ssl_tls13_is_some_ephemeral_supported(mbedtls_ssl_context *ssl) +{ + return mbedtls_ssl_tls13_is_kex_mode_supported(ssl, + MBEDTLS_SSL_TLS1_3_KEY_EXCHANGE_MODE_EPHEMERAL_ALL); +} + +static inline int mbedtls_ssl_tls13_is_some_psk_supported(mbedtls_ssl_context *ssl) +{ + return mbedtls_ssl_tls13_is_kex_mode_supported(ssl, + MBEDTLS_SSL_TLS1_3_KEY_EXCHANGE_MODE_PSK_ALL); +} +#endif /* MBEDTLS_SSL_SRV_C && + MBEDTLS_SSL_TLS1_3_KEY_EXCHANGE_MODE_SOME_PSK_ENABLED */ + +/* + * Helper functions for extensions checking. + */ + +MBEDTLS_CHECK_RETURN_CRITICAL +int mbedtls_ssl_tls13_check_received_extension( + mbedtls_ssl_context *ssl, + int hs_msg_type, + unsigned int received_extension_type, + uint32_t hs_msg_allowed_extensions_mask); + +static inline void mbedtls_ssl_tls13_set_hs_sent_ext_mask( + mbedtls_ssl_context *ssl, unsigned int extension_type) +{ + ssl->handshake->sent_extensions |= + mbedtls_ssl_get_extension_mask(extension_type); +} + +/* + * Helper functions to check the selected key exchange mode. + */ +static inline int mbedtls_ssl_tls13_key_exchange_mode_check( + mbedtls_ssl_context *ssl, int kex_mask) +{ + return (ssl->handshake->key_exchange_mode & kex_mask) != 0; +} + +static inline int mbedtls_ssl_tls13_key_exchange_mode_with_psk( + mbedtls_ssl_context *ssl) +{ + return mbedtls_ssl_tls13_key_exchange_mode_check(ssl, + MBEDTLS_SSL_TLS1_3_KEY_EXCHANGE_MODE_PSK_ALL); +} + +static inline int mbedtls_ssl_tls13_key_exchange_mode_with_ephemeral( + mbedtls_ssl_context *ssl) +{ + return mbedtls_ssl_tls13_key_exchange_mode_check(ssl, + MBEDTLS_SSL_TLS1_3_KEY_EXCHANGE_MODE_EPHEMERAL_ALL); +} + +/* + * Fetch TLS 1.3 handshake message header + */ +MBEDTLS_CHECK_RETURN_CRITICAL +int mbedtls_ssl_tls13_fetch_handshake_msg(mbedtls_ssl_context *ssl, + unsigned hs_type, + unsigned char **buf, + size_t *buf_len); + +/** + * \brief Detect if a list of extensions contains a supported_versions + * extension or not. + * + * \param[in] ssl SSL context + * \param[in] buf Address of the first byte of the extensions vector. + * \param[in] end End of the buffer containing the list of extensions. + * \param[out] supported_versions_data If the extension is present, address of + * its first byte of data, NULL otherwise. + * \param[out] supported_versions_data_end If the extension is present, address + * of the first byte immediately + * following the extension data, NULL + * otherwise. + * \return 0 if the list of extensions does not contain a supported_versions + * extension. + * \return 1 if the list of extensions contains a supported_versions + * extension. + * \return A negative value if an error occurred while parsing the + * extensions. + */ +MBEDTLS_CHECK_RETURN_CRITICAL +int mbedtls_ssl_tls13_is_supported_versions_ext_present_in_exts( + mbedtls_ssl_context *ssl, + const unsigned char *buf, const unsigned char *end, + const unsigned char **supported_versions_data, + const unsigned char **supported_versions_data_end); + +/* + * Handler of TLS 1.3 server certificate message + */ +MBEDTLS_CHECK_RETURN_CRITICAL +int mbedtls_ssl_tls13_process_certificate(mbedtls_ssl_context *ssl); + +#if defined(MBEDTLS_SSL_TLS1_3_KEY_EXCHANGE_MODE_EPHEMERAL_ENABLED) +/* + * Handler of TLS 1.3 write Certificate message + */ +MBEDTLS_CHECK_RETURN_CRITICAL +int mbedtls_ssl_tls13_write_certificate(mbedtls_ssl_context *ssl); + +/* + * Handler of TLS 1.3 write Certificate Verify message + */ +MBEDTLS_CHECK_RETURN_CRITICAL +int mbedtls_ssl_tls13_write_certificate_verify(mbedtls_ssl_context *ssl); + +#endif /* MBEDTLS_SSL_TLS1_3_KEY_EXCHANGE_MODE_EPHEMERAL_ENABLED */ + +/* + * Generic handler of Certificate Verify + */ +MBEDTLS_CHECK_RETURN_CRITICAL +int mbedtls_ssl_tls13_process_certificate_verify(mbedtls_ssl_context *ssl); + +/* + * Write of dummy-CCS's for middlebox compatibility + */ +MBEDTLS_CHECK_RETURN_CRITICAL +int mbedtls_ssl_tls13_write_change_cipher_spec(mbedtls_ssl_context *ssl); + +MBEDTLS_CHECK_RETURN_CRITICAL +int mbedtls_ssl_reset_transcript_for_hrr(mbedtls_ssl_context *ssl); + +#if defined(PSA_WANT_ALG_ECDH) || defined(PSA_WANT_ALG_FFDH) +MBEDTLS_CHECK_RETURN_CRITICAL +int mbedtls_ssl_tls13_generate_and_write_xxdh_key_exchange( + mbedtls_ssl_context *ssl, + uint16_t named_group, + unsigned char *buf, + unsigned char *end, + size_t *out_len); +#endif /* PSA_WANT_ALG_ECDH || PSA_WANT_ALG_FFDH */ + +#if defined(MBEDTLS_SSL_EARLY_DATA) +int mbedtls_ssl_tls13_write_early_data_ext(mbedtls_ssl_context *ssl, + int in_new_session_ticket, + unsigned char *buf, + const unsigned char *end, + size_t *out_len); + +int mbedtls_ssl_tls13_check_early_data_len(mbedtls_ssl_context *ssl, + size_t early_data_len); + +typedef enum { +/* + * The client has not sent the first ClientHello yet, the negotiation of early + * data has not started yet. + */ + MBEDTLS_SSL_EARLY_DATA_STATE_IDLE, + +/* + * In its ClientHello, the client has not included an early data indication + * extension. + */ + MBEDTLS_SSL_EARLY_DATA_STATE_NO_IND_SENT, + +/* + * The client has sent an early data indication extension in its first + * ClientHello, it has not received the response (ServerHello or + * HelloRetryRequest) from the server yet. The transform to protect early data + * is not set either as for middlebox compatibility a dummy CCS may have to be + * sent in clear. Early data cannot be sent to the server yet. + */ + MBEDTLS_SSL_EARLY_DATA_STATE_IND_SENT, + +/* + * The client has sent an early data indication extension in its first + * ClientHello, it has not received the response (ServerHello or + * HelloRetryRequest) from the server yet. The transform to protect early data + * has been set and early data can be written now. + */ + MBEDTLS_SSL_EARLY_DATA_STATE_CAN_WRITE, + +/* + * The client has indicated the use of early data and the server has accepted + * it. + */ + MBEDTLS_SSL_EARLY_DATA_STATE_ACCEPTED, + +/* + * The client has indicated the use of early data but the server has rejected + * it. + */ + MBEDTLS_SSL_EARLY_DATA_STATE_REJECTED, + +/* + * The client has sent an early data indication extension in its first + * ClientHello, the server has accepted them and the client has received the + * server Finished message. It cannot send early data to the server anymore. + */ + MBEDTLS_SSL_EARLY_DATA_STATE_SERVER_FINISHED_RECEIVED, + +} mbedtls_ssl_early_data_state; +#endif /* MBEDTLS_SSL_EARLY_DATA */ + +#endif /* MBEDTLS_SSL_PROTO_TLS1_3 */ + +#if defined(MBEDTLS_SSL_HANDSHAKE_WITH_CERT_ENABLED) +/* + * Write Signature Algorithm extension + */ +MBEDTLS_CHECK_RETURN_CRITICAL +int mbedtls_ssl_write_sig_alg_ext(mbedtls_ssl_context *ssl, unsigned char *buf, + const unsigned char *end, size_t *out_len); +/* + * Parse TLS Signature Algorithm extension + */ +MBEDTLS_CHECK_RETURN_CRITICAL +int mbedtls_ssl_parse_sig_alg_ext(mbedtls_ssl_context *ssl, + const unsigned char *buf, + const unsigned char *end); +#endif /* MBEDTLS_SSL_HANDSHAKE_WITH_CERT_ENABLED */ + +/* Get handshake transcript */ +MBEDTLS_CHECK_RETURN_CRITICAL +int mbedtls_ssl_get_handshake_transcript(mbedtls_ssl_context *ssl, + const mbedtls_md_type_t md, + unsigned char *dst, + size_t dst_len, + size_t *olen); + +/* + * Return supported groups. + * + * In future, invocations can be changed to ssl->conf->group_list + * when mbedtls_ssl_conf_curves() is deleted. + * + * ssl->handshake->group_list is either a translation of curve_list to IANA TLS group + * identifiers when mbedtls_ssl_conf_curves() has been used, or a pointer to + * ssl->conf->group_list when mbedtls_ssl_conf_groups() has been more recently invoked. + * + */ +static inline const void *mbedtls_ssl_get_groups(const mbedtls_ssl_context *ssl) +{ + #if defined(MBEDTLS_DEPRECATED_REMOVED) || !defined(MBEDTLS_ECP_C) + return ssl->conf->group_list; + #else + if ((ssl->handshake != NULL) && (ssl->handshake->group_list != NULL)) { + return ssl->handshake->group_list; + } else { + return ssl->conf->group_list; + } + #endif +} + +/* + * Helper functions for NamedGroup. + */ +static inline int mbedtls_ssl_tls12_named_group_is_ecdhe(uint16_t named_group) +{ + /* + * RFC 8422 section 5.1.1 + */ + return named_group == MBEDTLS_SSL_IANA_TLS_GROUP_X25519 || + named_group == MBEDTLS_SSL_IANA_TLS_GROUP_BP256R1 || + named_group == MBEDTLS_SSL_IANA_TLS_GROUP_BP384R1 || + named_group == MBEDTLS_SSL_IANA_TLS_GROUP_BP512R1 || + named_group == MBEDTLS_SSL_IANA_TLS_GROUP_X448 || + /* Below deprecated curves should be removed with notice to users */ + named_group == MBEDTLS_SSL_IANA_TLS_GROUP_SECP192K1 || + named_group == MBEDTLS_SSL_IANA_TLS_GROUP_SECP192R1 || + named_group == MBEDTLS_SSL_IANA_TLS_GROUP_SECP224K1 || + named_group == MBEDTLS_SSL_IANA_TLS_GROUP_SECP224R1 || + named_group == MBEDTLS_SSL_IANA_TLS_GROUP_SECP256K1 || + named_group == MBEDTLS_SSL_IANA_TLS_GROUP_SECP256R1 || + named_group == MBEDTLS_SSL_IANA_TLS_GROUP_SECP384R1 || + named_group == MBEDTLS_SSL_IANA_TLS_GROUP_SECP521R1; +} + +static inline int mbedtls_ssl_tls13_named_group_is_ecdhe(uint16_t named_group) +{ + return named_group == MBEDTLS_SSL_IANA_TLS_GROUP_X25519 || + named_group == MBEDTLS_SSL_IANA_TLS_GROUP_SECP256R1 || + named_group == MBEDTLS_SSL_IANA_TLS_GROUP_SECP384R1 || + named_group == MBEDTLS_SSL_IANA_TLS_GROUP_SECP521R1 || + named_group == MBEDTLS_SSL_IANA_TLS_GROUP_X448; +} + +static inline int mbedtls_ssl_tls13_named_group_is_ffdh(uint16_t named_group) +{ + return named_group >= MBEDTLS_SSL_IANA_TLS_GROUP_FFDHE2048 && + named_group <= MBEDTLS_SSL_IANA_TLS_GROUP_FFDHE8192; +} + +static inline int mbedtls_ssl_named_group_is_offered( + const mbedtls_ssl_context *ssl, uint16_t named_group) +{ + const uint16_t *group_list = mbedtls_ssl_get_groups(ssl); + + if (group_list == NULL) { + return 0; + } + + for (; *group_list != 0; group_list++) { + if (*group_list == named_group) { + return 1; + } + } + + return 0; +} + +static inline int mbedtls_ssl_named_group_is_supported(uint16_t named_group) +{ +#if defined(PSA_WANT_ALG_ECDH) + if (mbedtls_ssl_tls13_named_group_is_ecdhe(named_group)) { + if (mbedtls_ssl_get_ecp_group_id_from_tls_id(named_group) != + MBEDTLS_ECP_DP_NONE) { + return 1; + } + } +#endif +#if defined(PSA_WANT_ALG_FFDH) + if (mbedtls_ssl_tls13_named_group_is_ffdh(named_group)) { + return 1; + } +#endif +#if !defined(PSA_WANT_ALG_ECDH) && !defined(PSA_WANT_ALG_FFDH) + (void) named_group; +#endif + return 0; +} + +/* + * Return supported signature algorithms. + * + * In future, invocations can be changed to ssl->conf->sig_algs when + * mbedtls_ssl_conf_sig_hashes() is deleted. + * + * ssl->handshake->sig_algs is either a translation of sig_hashes to IANA TLS + * signature algorithm identifiers when mbedtls_ssl_conf_sig_hashes() has been + * used, or a pointer to ssl->conf->sig_algs when mbedtls_ssl_conf_sig_algs() has + * been more recently invoked. + * + */ +static inline const void *mbedtls_ssl_get_sig_algs( + const mbedtls_ssl_context *ssl) +{ +#if defined(MBEDTLS_SSL_HANDSHAKE_WITH_CERT_ENABLED) + +#if !defined(MBEDTLS_DEPRECATED_REMOVED) + if (ssl->handshake != NULL && + ssl->handshake->sig_algs_heap_allocated == 1 && + ssl->handshake->sig_algs != NULL) { + return ssl->handshake->sig_algs; + } +#endif + return ssl->conf->sig_algs; + +#else /* MBEDTLS_SSL_HANDSHAKE_WITH_CERT_ENABLED */ + + ((void) ssl); + return NULL; +#endif /* MBEDTLS_SSL_HANDSHAKE_WITH_CERT_ENABLED */ +} + +#if defined(MBEDTLS_SSL_TLS1_3_KEY_EXCHANGE_MODE_EPHEMERAL_ENABLED) +static inline int mbedtls_ssl_sig_alg_is_received(const mbedtls_ssl_context *ssl, + uint16_t own_sig_alg) +{ + const uint16_t *sig_alg = ssl->handshake->received_sig_algs; + if (sig_alg == NULL) { + return 0; + } + + for (; *sig_alg != MBEDTLS_TLS_SIG_NONE; sig_alg++) { + if (*sig_alg == own_sig_alg) { + return 1; + } + } + return 0; +} + +static inline int mbedtls_ssl_tls13_sig_alg_for_cert_verify_is_supported( + const uint16_t sig_alg) +{ + switch (sig_alg) { +#if defined(MBEDTLS_PK_CAN_ECDSA_SOME) +#if defined(PSA_WANT_ALG_SHA_256) && defined(PSA_WANT_ECC_SECP_R1_256) + case MBEDTLS_TLS1_3_SIG_ECDSA_SECP256R1_SHA256: + break; +#endif /* PSA_WANT_ALG_SHA_256 && MBEDTLS_ECP_DP_SECP256R1_ENABLED */ +#if defined(PSA_WANT_ALG_SHA_384) && defined(PSA_WANT_ECC_SECP_R1_384) + case MBEDTLS_TLS1_3_SIG_ECDSA_SECP384R1_SHA384: + break; +#endif /* PSA_WANT_ALG_SHA_384 && MBEDTLS_ECP_DP_SECP384R1_ENABLED */ +#if defined(PSA_WANT_ALG_SHA_512) && defined(PSA_WANT_ECC_SECP_R1_521) + case MBEDTLS_TLS1_3_SIG_ECDSA_SECP521R1_SHA512: + break; +#endif /* PSA_WANT_ALG_SHA_512 && MBEDTLS_ECP_DP_SECP521R1_ENABLED */ +#endif /* MBEDTLS_PK_CAN_ECDSA_SOME */ + +#if defined(MBEDTLS_PKCS1_V21) +#if defined(PSA_WANT_ALG_SHA_256) + case MBEDTLS_TLS1_3_SIG_RSA_PSS_RSAE_SHA256: + break; +#endif /* PSA_WANT_ALG_SHA_256 */ +#if defined(PSA_WANT_ALG_SHA_384) + case MBEDTLS_TLS1_3_SIG_RSA_PSS_RSAE_SHA384: + break; +#endif /* PSA_WANT_ALG_SHA_384 */ +#if defined(PSA_WANT_ALG_SHA_512) + case MBEDTLS_TLS1_3_SIG_RSA_PSS_RSAE_SHA512: + break; +#endif /* PSA_WANT_ALG_SHA_512 */ +#endif /* MBEDTLS_PKCS1_V21 */ + default: + return 0; + } + return 1; + +} + +static inline int mbedtls_ssl_tls13_sig_alg_is_supported( + const uint16_t sig_alg) +{ + switch (sig_alg) { +#if defined(MBEDTLS_PKCS1_V15) +#if defined(MBEDTLS_MD_CAN_SHA256) + case MBEDTLS_TLS1_3_SIG_RSA_PKCS1_SHA256: + break; +#endif /* MBEDTLS_MD_CAN_SHA256 */ +#if defined(MBEDTLS_MD_CAN_SHA384) + case MBEDTLS_TLS1_3_SIG_RSA_PKCS1_SHA384: + break; +#endif /* MBEDTLS_MD_CAN_SHA384 */ +#if defined(MBEDTLS_MD_CAN_SHA512) + case MBEDTLS_TLS1_3_SIG_RSA_PKCS1_SHA512: + break; +#endif /* MBEDTLS_MD_CAN_SHA512 */ +#endif /* MBEDTLS_PKCS1_V15 */ + default: + return mbedtls_ssl_tls13_sig_alg_for_cert_verify_is_supported( + sig_alg); + } + return 1; +} + +MBEDTLS_CHECK_RETURN_CRITICAL +int mbedtls_ssl_tls13_check_sig_alg_cert_key_match(uint16_t sig_alg, + mbedtls_pk_context *key); +#endif /* MBEDTLS_SSL_TLS1_3_KEY_EXCHANGE_MODE_EPHEMERAL_ENABLED */ + +#if defined(MBEDTLS_SSL_HANDSHAKE_WITH_CERT_ENABLED) +static inline int mbedtls_ssl_sig_alg_is_offered(const mbedtls_ssl_context *ssl, + uint16_t proposed_sig_alg) +{ + const uint16_t *sig_alg = mbedtls_ssl_get_sig_algs(ssl); + if (sig_alg == NULL) { + return 0; + } + + for (; *sig_alg != MBEDTLS_TLS_SIG_NONE; sig_alg++) { + if (*sig_alg == proposed_sig_alg) { + return 1; + } + } + return 0; +} + +static inline int mbedtls_ssl_get_pk_type_and_md_alg_from_sig_alg( + uint16_t sig_alg, mbedtls_pk_type_t *pk_type, mbedtls_md_type_t *md_alg) +{ + *pk_type = mbedtls_ssl_pk_alg_from_sig(sig_alg & 0xff); + *md_alg = mbedtls_ssl_md_alg_from_hash((sig_alg >> 8) & 0xff); + + if (*pk_type != MBEDTLS_PK_NONE && *md_alg != MBEDTLS_MD_NONE) { + return 0; + } + + switch (sig_alg) { +#if defined(MBEDTLS_PKCS1_V21) +#if defined(MBEDTLS_MD_CAN_SHA256) + case MBEDTLS_TLS1_3_SIG_RSA_PSS_RSAE_SHA256: + *md_alg = MBEDTLS_MD_SHA256; + *pk_type = MBEDTLS_PK_RSASSA_PSS; + break; +#endif /* MBEDTLS_MD_CAN_SHA256 */ +#if defined(MBEDTLS_MD_CAN_SHA384) + case MBEDTLS_TLS1_3_SIG_RSA_PSS_RSAE_SHA384: + *md_alg = MBEDTLS_MD_SHA384; + *pk_type = MBEDTLS_PK_RSASSA_PSS; + break; +#endif /* MBEDTLS_MD_CAN_SHA384 */ +#if defined(MBEDTLS_MD_CAN_SHA512) + case MBEDTLS_TLS1_3_SIG_RSA_PSS_RSAE_SHA512: + *md_alg = MBEDTLS_MD_SHA512; + *pk_type = MBEDTLS_PK_RSASSA_PSS; + break; +#endif /* MBEDTLS_MD_CAN_SHA512 */ +#endif /* MBEDTLS_PKCS1_V21 */ + default: + return MBEDTLS_ERR_SSL_FEATURE_UNAVAILABLE; + } + return 0; +} + +#if defined(MBEDTLS_SSL_PROTO_TLS1_2) +static inline int mbedtls_ssl_tls12_sig_alg_is_supported( + const uint16_t sig_alg) +{ + /* High byte is hash */ + unsigned char hash = MBEDTLS_BYTE_1(sig_alg); + unsigned char sig = MBEDTLS_BYTE_0(sig_alg); + + switch (hash) { +#if defined(MBEDTLS_MD_CAN_MD5) + case MBEDTLS_SSL_HASH_MD5: + break; +#endif + +#if defined(MBEDTLS_MD_CAN_SHA1) + case MBEDTLS_SSL_HASH_SHA1: + break; +#endif + +#if defined(MBEDTLS_MD_CAN_SHA224) + case MBEDTLS_SSL_HASH_SHA224: + break; +#endif + +#if defined(MBEDTLS_MD_CAN_SHA256) + case MBEDTLS_SSL_HASH_SHA256: + break; +#endif + +#if defined(MBEDTLS_MD_CAN_SHA384) + case MBEDTLS_SSL_HASH_SHA384: + break; +#endif + +#if defined(MBEDTLS_MD_CAN_SHA512) + case MBEDTLS_SSL_HASH_SHA512: + break; +#endif + + default: + return 0; + } + + switch (sig) { +#if defined(MBEDTLS_RSA_C) + case MBEDTLS_SSL_SIG_RSA: + break; +#endif + +#if defined(MBEDTLS_KEY_EXCHANGE_ECDSA_CERT_REQ_ALLOWED_ENABLED) + case MBEDTLS_SSL_SIG_ECDSA: + break; +#endif + + default: + return 0; + } + + return 1; +} +#endif /* MBEDTLS_SSL_PROTO_TLS1_2 */ + +static inline int mbedtls_ssl_sig_alg_is_supported( + const mbedtls_ssl_context *ssl, + const uint16_t sig_alg) +{ + +#if defined(MBEDTLS_SSL_PROTO_TLS1_2) + if (ssl->tls_version == MBEDTLS_SSL_VERSION_TLS1_2) { + return mbedtls_ssl_tls12_sig_alg_is_supported(sig_alg); + } +#endif /* MBEDTLS_SSL_PROTO_TLS1_2 */ + +#if defined(MBEDTLS_SSL_TLS1_3_KEY_EXCHANGE_MODE_EPHEMERAL_ENABLED) + if (ssl->tls_version == MBEDTLS_SSL_VERSION_TLS1_3) { + return mbedtls_ssl_tls13_sig_alg_is_supported(sig_alg); + } +#endif + ((void) ssl); + ((void) sig_alg); + return 0; +} +#endif /* MBEDTLS_SSL_HANDSHAKE_WITH_CERT_ENABLED */ + +#if defined(MBEDTLS_USE_PSA_CRYPTO) || defined(MBEDTLS_SSL_PROTO_TLS1_3) +/* Corresponding PSA algorithm for MBEDTLS_CIPHER_NULL. + * Same value is used for PSA_ALG_CATEGORY_CIPHER, hence it is + * guaranteed to not be a valid PSA algorithm identifier. + */ +#define MBEDTLS_SSL_NULL_CIPHER 0x04000000 + +/** + * \brief Translate mbedtls cipher type/taglen pair to psa: + * algorithm, key type and key size. + * + * \param mbedtls_cipher_type [in] given mbedtls cipher type + * \param taglen [in] given tag length + * 0 - default tag length + * \param alg [out] corresponding PSA alg + * There is no corresponding PSA + * alg for MBEDTLS_CIPHER_NULL, so + * in this case MBEDTLS_SSL_NULL_CIPHER + * is returned via this parameter + * \param key_type [out] corresponding PSA key type + * \param key_size [out] corresponding PSA key size + * + * \return PSA_SUCCESS on success or PSA_ERROR_NOT_SUPPORTED if + * conversion is not supported. + */ +psa_status_t mbedtls_ssl_cipher_to_psa(mbedtls_cipher_type_t mbedtls_cipher_type, + size_t taglen, + psa_algorithm_t *alg, + psa_key_type_t *key_type, + size_t *key_size); + +#if !defined(MBEDTLS_DEPRECATED_REMOVED) +/** + * \brief Convert given PSA status to mbedtls error code. + * + * \param status [in] given PSA status + * + * \return corresponding mbedtls error code + */ +static inline MBEDTLS_DEPRECATED int psa_ssl_status_to_mbedtls(psa_status_t status) +{ + switch (status) { + case PSA_SUCCESS: + return 0; + case PSA_ERROR_INSUFFICIENT_MEMORY: + return MBEDTLS_ERR_SSL_ALLOC_FAILED; + case PSA_ERROR_NOT_SUPPORTED: + return MBEDTLS_ERR_SSL_FEATURE_UNAVAILABLE; + case PSA_ERROR_INVALID_SIGNATURE: + return MBEDTLS_ERR_SSL_INVALID_MAC; + case PSA_ERROR_INVALID_ARGUMENT: + return MBEDTLS_ERR_SSL_BAD_INPUT_DATA; + case PSA_ERROR_BAD_STATE: + return MBEDTLS_ERR_SSL_INTERNAL_ERROR; + case PSA_ERROR_BUFFER_TOO_SMALL: + return MBEDTLS_ERR_SSL_BUFFER_TOO_SMALL; + default: + return MBEDTLS_ERR_PLATFORM_HW_ACCEL_FAILED; + } +} +#endif /* !MBEDTLS_DEPRECATED_REMOVED */ +#endif /* MBEDTLS_USE_PSA_CRYPTO || MBEDTLS_SSL_PROTO_TLS1_3 */ + +#if defined(MBEDTLS_KEY_EXCHANGE_ECJPAKE_ENABLED) && \ + defined(MBEDTLS_USE_PSA_CRYPTO) + +typedef enum { + MBEDTLS_ECJPAKE_ROUND_ONE, + MBEDTLS_ECJPAKE_ROUND_TWO +} mbedtls_ecjpake_rounds_t; + +/** + * \brief Parse the provided input buffer for getting the first round + * of key exchange. This code is common between server and client + * + * \param pake_ctx [in] the PAKE's operation/context structure + * \param buf [in] input buffer to parse + * \param len [in] length of the input buffer + * \param round [in] either MBEDTLS_ECJPAKE_ROUND_ONE or + * MBEDTLS_ECJPAKE_ROUND_TWO + * + * \return 0 on success or a negative error code in case of failure + */ +int mbedtls_psa_ecjpake_read_round( + psa_pake_operation_t *pake_ctx, + const unsigned char *buf, + size_t len, mbedtls_ecjpake_rounds_t round); + +/** + * \brief Write the first round of key exchange into the provided output + * buffer. This code is common between server and client + * + * \param pake_ctx [in] the PAKE's operation/context structure + * \param buf [out] the output buffer in which data will be written to + * \param len [in] length of the output buffer + * \param olen [out] the length of the data really written on the buffer + * \param round [in] either MBEDTLS_ECJPAKE_ROUND_ONE or + * MBEDTLS_ECJPAKE_ROUND_TWO + * + * \return 0 on success or a negative error code in case of failure + */ +int mbedtls_psa_ecjpake_write_round( + psa_pake_operation_t *pake_ctx, + unsigned char *buf, + size_t len, size_t *olen, + mbedtls_ecjpake_rounds_t round); + +#endif //MBEDTLS_KEY_EXCHANGE_ECJPAKE_ENABLED && MBEDTLS_USE_PSA_CRYPTO + +/** + * \brief TLS record protection modes + */ +typedef enum { + MBEDTLS_SSL_MODE_STREAM = 0, + MBEDTLS_SSL_MODE_CBC, + MBEDTLS_SSL_MODE_CBC_ETM, + MBEDTLS_SSL_MODE_AEAD +} mbedtls_ssl_mode_t; + +mbedtls_ssl_mode_t mbedtls_ssl_get_mode_from_transform( + const mbedtls_ssl_transform *transform); + +#if defined(MBEDTLS_SSL_SOME_SUITES_USE_CBC_ETM) +mbedtls_ssl_mode_t mbedtls_ssl_get_mode_from_ciphersuite( + int encrypt_then_mac, + const mbedtls_ssl_ciphersuite_t *suite); +#else +mbedtls_ssl_mode_t mbedtls_ssl_get_mode_from_ciphersuite( + const mbedtls_ssl_ciphersuite_t *suite); +#endif /* MBEDTLS_SSL_SOME_SUITES_USE_CBC_ETM */ + +#if defined(PSA_WANT_ALG_ECDH) || defined(PSA_WANT_ALG_FFDH) + +MBEDTLS_CHECK_RETURN_CRITICAL +int mbedtls_ssl_tls13_read_public_xxdhe_share(mbedtls_ssl_context *ssl, + const unsigned char *buf, + size_t buf_len); + +#endif /* PSA_WANT_ALG_ECDH || PSA_WANT_ALG_FFDH */ + +static inline int mbedtls_ssl_tls13_cipher_suite_is_offered( + mbedtls_ssl_context *ssl, int cipher_suite) +{ + const int *ciphersuite_list = ssl->conf->ciphersuite_list; + + /* Check whether we have offered this ciphersuite */ + for (size_t i = 0; ciphersuite_list[i] != 0; i++) { + if (ciphersuite_list[i] == cipher_suite) { + return 1; + } + } + return 0; +} + +/** + * \brief Validate cipher suite against config in SSL context. + * + * \param ssl SSL context + * \param suite_info Cipher suite to validate + * \param min_tls_version Minimal TLS version to accept a cipher suite + * \param max_tls_version Maximal TLS version to accept a cipher suite + * + * \return 0 if valid, negative value otherwise. + */ +MBEDTLS_CHECK_RETURN_CRITICAL +int mbedtls_ssl_validate_ciphersuite( + const mbedtls_ssl_context *ssl, + const mbedtls_ssl_ciphersuite_t *suite_info, + mbedtls_ssl_protocol_version min_tls_version, + mbedtls_ssl_protocol_version max_tls_version); + +#if defined(MBEDTLS_SSL_SERVER_NAME_INDICATION) +MBEDTLS_CHECK_RETURN_CRITICAL +int mbedtls_ssl_parse_server_name_ext(mbedtls_ssl_context *ssl, + const unsigned char *buf, + const unsigned char *end); +#endif /* MBEDTLS_SSL_SERVER_NAME_INDICATION */ + +#if defined(MBEDTLS_SSL_RECORD_SIZE_LIMIT) +#define MBEDTLS_SSL_RECORD_SIZE_LIMIT_EXTENSION_DATA_LENGTH (2) +#define MBEDTLS_SSL_RECORD_SIZE_LIMIT_MIN (64) /* As defined in RFC 8449 */ + +MBEDTLS_CHECK_RETURN_CRITICAL +int mbedtls_ssl_tls13_parse_record_size_limit_ext(mbedtls_ssl_context *ssl, + const unsigned char *buf, + const unsigned char *end); + +MBEDTLS_CHECK_RETURN_CRITICAL +int mbedtls_ssl_tls13_write_record_size_limit_ext(mbedtls_ssl_context *ssl, + unsigned char *buf, + const unsigned char *end, + size_t *out_len); +#endif /* MBEDTLS_SSL_RECORD_SIZE_LIMIT */ + +#if defined(MBEDTLS_SSL_ALPN) +MBEDTLS_CHECK_RETURN_CRITICAL +int mbedtls_ssl_parse_alpn_ext(mbedtls_ssl_context *ssl, + const unsigned char *buf, + const unsigned char *end); + + +MBEDTLS_CHECK_RETURN_CRITICAL +int mbedtls_ssl_write_alpn_ext(mbedtls_ssl_context *ssl, + unsigned char *buf, + unsigned char *end, + size_t *out_len); +#endif /* MBEDTLS_SSL_ALPN */ + +#if defined(MBEDTLS_TEST_HOOKS) +int mbedtls_ssl_check_dtls_clihlo_cookie( + mbedtls_ssl_context *ssl, + const unsigned char *cli_id, size_t cli_id_len, + const unsigned char *in, size_t in_len, + unsigned char *obuf, size_t buf_len, size_t *olen); +#endif + +#if defined(MBEDTLS_SSL_TLS1_3_KEY_EXCHANGE_MODE_SOME_PSK_ENABLED) +/** + * \brief Given an SSL context and its associated configuration, write the TLS + * 1.3 specific Pre-Shared key extension. + * + * \param[in] ssl SSL context + * \param[in] buf Base address of the buffer where to write the extension + * \param[in] end End address of the buffer where to write the extension + * \param[out] out_len Length in bytes of the Pre-Shared key extension: data + * written into the buffer \p buf by this function plus + * the length of the binders to be written. + * \param[out] binders_len Length of the binders to be written at the end of + * the extension. + */ +MBEDTLS_CHECK_RETURN_CRITICAL +int mbedtls_ssl_tls13_write_identities_of_pre_shared_key_ext( + mbedtls_ssl_context *ssl, + unsigned char *buf, unsigned char *end, + size_t *out_len, size_t *binders_len); + +/** + * \brief Given an SSL context and its associated configuration, write the TLS + * 1.3 specific Pre-Shared key extension binders at the end of the + * ClientHello. + * + * \param[in] ssl SSL context + * \param[in] buf Base address of the buffer where to write the binders + * \param[in] end End address of the buffer where to write the binders + */ +MBEDTLS_CHECK_RETURN_CRITICAL +int mbedtls_ssl_tls13_write_binders_of_pre_shared_key_ext( + mbedtls_ssl_context *ssl, + unsigned char *buf, unsigned char *end); +#endif /* MBEDTLS_SSL_TLS1_3_KEY_EXCHANGE_MODE_SOME_PSK_ENABLED */ + +#if defined(MBEDTLS_SSL_PROTO_TLS1_3) && \ + defined(MBEDTLS_SSL_SESSION_TICKETS) && \ + defined(MBEDTLS_SSL_SERVER_NAME_INDICATION) && \ + defined(MBEDTLS_SSL_CLI_C) +MBEDTLS_CHECK_RETURN_CRITICAL +int mbedtls_ssl_session_set_hostname(mbedtls_ssl_session *session, + const char *hostname); +#endif + +#if defined(MBEDTLS_SSL_SRV_C) && defined(MBEDTLS_SSL_EARLY_DATA) && \ + defined(MBEDTLS_SSL_ALPN) +MBEDTLS_CHECK_RETURN_CRITICAL +int mbedtls_ssl_session_set_ticket_alpn(mbedtls_ssl_session *session, + const char *alpn); +#endif + +#if defined(MBEDTLS_SSL_PROTO_TLS1_3) && defined(MBEDTLS_SSL_SESSION_TICKETS) + +#define MBEDTLS_SSL_TLS1_3_MAX_ALLOWED_TICKET_LIFETIME (604800) + +static inline unsigned int mbedtls_ssl_tls13_session_get_ticket_flags( + mbedtls_ssl_session *session, unsigned int flags) +{ + return session->ticket_flags & + (flags & MBEDTLS_SSL_TLS1_3_TICKET_FLAGS_MASK); +} + +/** + * Check if at least one of the given flags is set in + * the session ticket. See the definition of + * `MBEDTLS_SSL_TLS1_3_TICKET_FLAGS_MASK` to get all + * permitted flags. + */ +static inline int mbedtls_ssl_tls13_session_ticket_has_flags( + mbedtls_ssl_session *session, unsigned int flags) +{ + return mbedtls_ssl_tls13_session_get_ticket_flags(session, flags) != 0; +} + +static inline int mbedtls_ssl_tls13_session_ticket_allow_psk( + mbedtls_ssl_session *session) +{ + return mbedtls_ssl_tls13_session_ticket_has_flags( + session, MBEDTLS_SSL_TLS1_3_TICKET_ALLOW_PSK_RESUMPTION); +} + +static inline int mbedtls_ssl_tls13_session_ticket_allow_psk_ephemeral( + mbedtls_ssl_session *session) +{ + return mbedtls_ssl_tls13_session_ticket_has_flags( + session, MBEDTLS_SSL_TLS1_3_TICKET_ALLOW_PSK_EPHEMERAL_RESUMPTION); +} + +static inline unsigned int mbedtls_ssl_tls13_session_ticket_allow_early_data( + mbedtls_ssl_session *session) +{ + return mbedtls_ssl_tls13_session_ticket_has_flags( + session, MBEDTLS_SSL_TLS1_3_TICKET_ALLOW_EARLY_DATA); +} + +static inline void mbedtls_ssl_tls13_session_set_ticket_flags( + mbedtls_ssl_session *session, unsigned int flags) +{ + session->ticket_flags |= (flags & MBEDTLS_SSL_TLS1_3_TICKET_FLAGS_MASK); +} + +static inline void mbedtls_ssl_tls13_session_clear_ticket_flags( + mbedtls_ssl_session *session, unsigned int flags) +{ + session->ticket_flags &= ~(flags & MBEDTLS_SSL_TLS1_3_TICKET_FLAGS_MASK); +} +#endif /* MBEDTLS_SSL_PROTO_TLS1_3 && MBEDTLS_SSL_SESSION_TICKETS */ + +#if defined(MBEDTLS_SSL_CLI_C) && defined(MBEDTLS_SSL_PROTO_TLS1_3) +int mbedtls_ssl_tls13_finalize_client_hello(mbedtls_ssl_context *ssl); +#endif + +#if defined(MBEDTLS_TEST_HOOKS) && defined(MBEDTLS_SSL_SOME_SUITES_USE_MAC) + +/** Compute the HMAC of variable-length data with constant flow. + * + * This function computes the HMAC of the concatenation of \p add_data and \p + * data, and does with a code flow and memory access pattern that does not + * depend on \p data_len_secret, but only on \p min_data_len and \p + * max_data_len. In particular, this function always reads exactly \p + * max_data_len bytes from \p data. + * + * \param ctx The HMAC context. It must have keys configured + * with mbedtls_md_hmac_starts() and use one of the + * following hashes: SHA-384, SHA-256, SHA-1 or MD-5. + * It is reset using mbedtls_md_hmac_reset() after + * the computation is complete to prepare for the + * next computation. + * \param add_data The first part of the message whose HMAC is being + * calculated. This must point to a readable buffer + * of \p add_data_len bytes. + * \param add_data_len The length of \p add_data in bytes. + * \param data The buffer containing the second part of the + * message. This must point to a readable buffer + * of \p max_data_len bytes. + * \param data_len_secret The length of the data to process in \p data. + * This must be no less than \p min_data_len and no + * greater than \p max_data_len. + * \param min_data_len The minimal length of the second part of the + * message, read from \p data. + * \param max_data_len The maximal length of the second part of the + * message, read from \p data. + * \param output The HMAC will be written here. This must point to + * a writable buffer of sufficient size to hold the + * HMAC value. + * + * \retval 0 on success. + * \retval #MBEDTLS_ERR_PLATFORM_HW_ACCEL_FAILED + * The hardware accelerator failed. + */ +#if defined(MBEDTLS_USE_PSA_CRYPTO) +int mbedtls_ct_hmac(mbedtls_svc_key_id_t key, + psa_algorithm_t mac_alg, + const unsigned char *add_data, + size_t add_data_len, + const unsigned char *data, + size_t data_len_secret, + size_t min_data_len, + size_t max_data_len, + unsigned char *output); +#else +int mbedtls_ct_hmac(mbedtls_md_context_t *ctx, + const unsigned char *add_data, + size_t add_data_len, + const unsigned char *data, + size_t data_len_secret, + size_t min_data_len, + size_t max_data_len, + unsigned char *output); +#endif /* defined(MBEDTLS_USE_PSA_CRYPTO) */ +#endif /* MBEDTLS_TEST_HOOKS && defined(MBEDTLS_SSL_SOME_SUITES_USE_MAC) */ + +#endif /* ssl_misc.h */ diff --git a/vendor/mbedtls/library/ssl_msg.c b/vendor/mbedtls/library/ssl_msg.c index 4e9cc7ff35..b07cd96f1b 100644 --- a/vendor/mbedtls/library/ssl_msg.c +++ b/vendor/mbedtls/library/ssl_msg.c @@ -3,25 +3,9 @@ * (record layer + retransmission state machine) * * Copyright The Mbed TLS Contributors - * SPDX-License-Identifier: Apache-2.0 - * - * Licensed under the Apache License, Version 2.0 (the "License"); you may - * not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT - * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. + * SPDX-License-Identifier: Apache-2.0 OR GPL-2.0-or-later */ /* - * The SSL 3.0 specification was drafted by Netscape in 1996, - * and became an IETF standard in 1999. - * - * http://wp.netscape.com/eng/ssl3/ * http://www.ietf.org/rfc/rfc2246.txt * http://www.ietf.org/rfc/rfc4346.txt */ @@ -33,8 +17,8 @@ #include "mbedtls/platform.h" #include "mbedtls/ssl.h" -#include "mbedtls/ssl_internal.h" -#include "mbedtls/debug.h" +#include "ssl_misc.h" +#include "debug_internal.h" #include "mbedtls/error.h" #include "mbedtls/platform_util.h" #include "mbedtls/version.h" @@ -44,7 +28,7 @@ #include #if defined(MBEDTLS_USE_PSA_CRYPTO) -#include "mbedtls/psa_util.h" +#include "psa_util_internal.h" #include "psa/crypto.h" #endif @@ -52,6 +36,246 @@ #include "mbedtls/oid.h" #endif +#if defined(MBEDTLS_USE_PSA_CRYPTO) +/* Define a local translating function to save code size by not using too many + * arguments in each translating place. */ +static int local_err_translation(psa_status_t status) +{ + return psa_status_to_mbedtls(status, psa_to_ssl_errors, + ARRAY_LENGTH(psa_to_ssl_errors), + psa_generic_status_to_mbedtls); +} +#define PSA_TO_MBEDTLS_ERR(status) local_err_translation(status) +#endif + +#if defined(MBEDTLS_SSL_SOME_SUITES_USE_MAC) + +#if defined(MBEDTLS_USE_PSA_CRYPTO) + +#if defined(PSA_WANT_ALG_SHA_384) +#define MAX_HASH_BLOCK_LENGTH PSA_HASH_BLOCK_LENGTH(PSA_ALG_SHA_384) +#elif defined(PSA_WANT_ALG_SHA_256) +#define MAX_HASH_BLOCK_LENGTH PSA_HASH_BLOCK_LENGTH(PSA_ALG_SHA_256) +#else /* See check_config.h */ +#define MAX_HASH_BLOCK_LENGTH PSA_HASH_BLOCK_LENGTH(PSA_ALG_SHA_1) +#endif + +MBEDTLS_STATIC_TESTABLE +int mbedtls_ct_hmac(mbedtls_svc_key_id_t key, + psa_algorithm_t mac_alg, + const unsigned char *add_data, + size_t add_data_len, + const unsigned char *data, + size_t data_len_secret, + size_t min_data_len, + size_t max_data_len, + unsigned char *output) +{ + /* + * This function breaks the HMAC abstraction and uses psa_hash_clone() + * extension in order to get constant-flow behaviour. + * + * HMAC(msg) is defined as HASH(okey + HASH(ikey + msg)) where + means + * concatenation, and okey/ikey are the XOR of the key with some fixed bit + * patterns (see RFC 2104, sec. 2). + * + * We'll first compute ikey/okey, then inner_hash = HASH(ikey + msg) by + * hashing up to minlen, then cloning the context, and for each byte up + * to maxlen finishing up the hash computation, keeping only the + * correct result. + * + * Then we only need to compute HASH(okey + inner_hash) and we're done. + */ + psa_algorithm_t hash_alg = PSA_ALG_HMAC_GET_HASH(mac_alg); + const size_t block_size = PSA_HASH_BLOCK_LENGTH(hash_alg); + unsigned char key_buf[MAX_HASH_BLOCK_LENGTH]; + const size_t hash_size = PSA_HASH_LENGTH(hash_alg); + psa_hash_operation_t operation = PSA_HASH_OPERATION_INIT; + size_t hash_length; + + unsigned char aux_out[PSA_HASH_MAX_SIZE]; + psa_hash_operation_t aux_operation = PSA_HASH_OPERATION_INIT; + size_t offset; + psa_status_t status = PSA_ERROR_CORRUPTION_DETECTED; + + size_t mac_key_length; + size_t i; + +#define PSA_CHK(func_call) \ + do { \ + status = (func_call); \ + if (status != PSA_SUCCESS) \ + goto cleanup; \ + } while (0) + + /* Export MAC key + * We assume key length is always exactly the output size + * which is never more than the block size, thus we use block_size + * as the key buffer size. + */ + PSA_CHK(psa_export_key(key, key_buf, block_size, &mac_key_length)); + + /* Calculate ikey */ + for (i = 0; i < mac_key_length; i++) { + key_buf[i] = (unsigned char) (key_buf[i] ^ 0x36); + } + for (; i < block_size; ++i) { + key_buf[i] = 0x36; + } + + PSA_CHK(psa_hash_setup(&operation, hash_alg)); + + /* Now compute inner_hash = HASH(ikey + msg) */ + PSA_CHK(psa_hash_update(&operation, key_buf, block_size)); + PSA_CHK(psa_hash_update(&operation, add_data, add_data_len)); + PSA_CHK(psa_hash_update(&operation, data, min_data_len)); + + /* Fill the hash buffer in advance with something that is + * not a valid hash (barring an attack on the hash and + * deliberately-crafted input), in case the caller doesn't + * check the return status properly. */ + memset(output, '!', hash_size); + + /* For each possible length, compute the hash up to that point */ + for (offset = min_data_len; offset <= max_data_len; offset++) { + PSA_CHK(psa_hash_clone(&operation, &aux_operation)); + PSA_CHK(psa_hash_finish(&aux_operation, aux_out, + PSA_HASH_MAX_SIZE, &hash_length)); + /* Keep only the correct inner_hash in the output buffer */ + mbedtls_ct_memcpy_if(mbedtls_ct_uint_eq(offset, data_len_secret), + output, aux_out, NULL, hash_size); + + if (offset < max_data_len) { + PSA_CHK(psa_hash_update(&operation, data + offset, 1)); + } + } + + /* Abort current operation to prepare for final operation */ + PSA_CHK(psa_hash_abort(&operation)); + + /* Calculate okey */ + for (i = 0; i < mac_key_length; i++) { + key_buf[i] = (unsigned char) ((key_buf[i] ^ 0x36) ^ 0x5C); + } + for (; i < block_size; ++i) { + key_buf[i] = 0x5C; + } + + /* Now compute HASH(okey + inner_hash) */ + PSA_CHK(psa_hash_setup(&operation, hash_alg)); + PSA_CHK(psa_hash_update(&operation, key_buf, block_size)); + PSA_CHK(psa_hash_update(&operation, output, hash_size)); + PSA_CHK(psa_hash_finish(&operation, output, hash_size, &hash_length)); + +#undef PSA_CHK + +cleanup: + mbedtls_platform_zeroize(key_buf, MAX_HASH_BLOCK_LENGTH); + mbedtls_platform_zeroize(aux_out, PSA_HASH_MAX_SIZE); + + psa_hash_abort(&operation); + psa_hash_abort(&aux_operation); + return PSA_TO_MBEDTLS_ERR(status); +} + +#undef MAX_HASH_BLOCK_LENGTH + +#else +MBEDTLS_STATIC_TESTABLE +int mbedtls_ct_hmac(mbedtls_md_context_t *ctx, + const unsigned char *add_data, + size_t add_data_len, + const unsigned char *data, + size_t data_len_secret, + size_t min_data_len, + size_t max_data_len, + unsigned char *output) +{ + /* + * This function breaks the HMAC abstraction and uses the md_clone() + * extension to the MD API in order to get constant-flow behaviour. + * + * HMAC(msg) is defined as HASH(okey + HASH(ikey + msg)) where + means + * concatenation, and okey/ikey are the XOR of the key with some fixed bit + * patterns (see RFC 2104, sec. 2), which are stored in ctx->hmac_ctx. + * + * We'll first compute inner_hash = HASH(ikey + msg) by hashing up to + * minlen, then cloning the context, and for each byte up to maxlen + * finishing up the hash computation, keeping only the correct result. + * + * Then we only need to compute HASH(okey + inner_hash) and we're done. + */ + const mbedtls_md_type_t md_alg = mbedtls_md_get_type(ctx->md_info); + /* TLS 1.2 only supports SHA-384, SHA-256, SHA-1, MD-5, + * all of which have the same block size except SHA-384. */ + const size_t block_size = md_alg == MBEDTLS_MD_SHA384 ? 128 : 64; + const unsigned char * const ikey = ctx->hmac_ctx; + const unsigned char * const okey = ikey + block_size; + const size_t hash_size = mbedtls_md_get_size(ctx->md_info); + + unsigned char aux_out[MBEDTLS_MD_MAX_SIZE]; + mbedtls_md_context_t aux; + size_t offset; + int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED; + + mbedtls_md_init(&aux); + +#define MD_CHK(func_call) \ + do { \ + ret = (func_call); \ + if (ret != 0) \ + goto cleanup; \ + } while (0) + + MD_CHK(mbedtls_md_setup(&aux, ctx->md_info, 0)); + + /* After hmac_start() of hmac_reset(), ikey has already been hashed, + * so we can start directly with the message */ + MD_CHK(mbedtls_md_update(ctx, add_data, add_data_len)); + MD_CHK(mbedtls_md_update(ctx, data, min_data_len)); + + /* Fill the hash buffer in advance with something that is + * not a valid hash (barring an attack on the hash and + * deliberately-crafted input), in case the caller doesn't + * check the return status properly. */ + memset(output, '!', hash_size); + + /* For each possible length, compute the hash up to that point */ + for (offset = min_data_len; offset <= max_data_len; offset++) { + MD_CHK(mbedtls_md_clone(&aux, ctx)); + MD_CHK(mbedtls_md_finish(&aux, aux_out)); + /* Keep only the correct inner_hash in the output buffer */ + mbedtls_ct_memcpy_if(mbedtls_ct_uint_eq(offset, data_len_secret), + output, aux_out, NULL, hash_size); + + if (offset < max_data_len) { + MD_CHK(mbedtls_md_update(ctx, data + offset, 1)); + } + } + + /* The context needs to finish() before it starts() again */ + MD_CHK(mbedtls_md_finish(ctx, aux_out)); + + /* Now compute HASH(okey + inner_hash) */ + MD_CHK(mbedtls_md_starts(ctx)); + MD_CHK(mbedtls_md_update(ctx, okey, block_size)); + MD_CHK(mbedtls_md_update(ctx, output, hash_size)); + MD_CHK(mbedtls_md_finish(ctx, output)); + + /* Done, get ready for next time */ + MD_CHK(mbedtls_md_hmac_reset(ctx)); + +#undef MD_CHK + +cleanup: + mbedtls_md_free(&aux); + return ret; +} + +#endif /* MBEDTLS_USE_PSA_CRYPTO */ + +#endif /* MBEDTLS_SSL_SOME_SUITES_USE_MAC */ + static uint32_t ssl_get_hs_total_len(mbedtls_ssl_context const *ssl); /* @@ -85,7 +309,6 @@ int mbedtls_ssl_check_timer(mbedtls_ssl_context *ssl) return 0; } -#if defined(MBEDTLS_SSL_RECORD_CHECKING) MBEDTLS_CHECK_RETURN_CRITICAL static int ssl_parse_record_header(mbedtls_ssl_context const *ssl, unsigned char *buf, @@ -101,9 +324,7 @@ int mbedtls_ssl_check_record(mbedtls_ssl_context const *ssl, MBEDTLS_SSL_DEBUG_BUF(3, "record buffer", buf, buflen); /* We don't support record checking in TLS because - * (a) there doesn't seem to be a usecase for it, and - * (b) In SSLv3 and TLS 1.0, CBC record decryption has state - * and we'd need to backup the transform here. + * there doesn't seem to be a usecase for it. */ if (ssl->conf->transport == MBEDTLS_SSL_TRANSPORT_STREAM) { ret = MBEDTLS_ERR_SSL_FEATURE_UNAVAILABLE; @@ -144,7 +365,6 @@ int mbedtls_ssl_check_record(mbedtls_ssl_context const *ssl, MBEDTLS_SSL_DEBUG_MSG(1, ("<= mbedtls_ssl_check_record")); return ret; } -#endif /* MBEDTLS_SSL_RECORD_CHECKING */ #define SSL_DONT_FORCE_FLUSH 0 #define SSL_FORCE_FLUSH 1 @@ -300,27 +520,11 @@ static void ssl_reset_retransmit_timeout(mbedtls_ssl_context *ssl) } #endif /* MBEDTLS_SSL_PROTO_DTLS */ -#if defined(MBEDTLS_SSL_HW_RECORD_ACCEL) -int (*mbedtls_ssl_hw_record_init)(mbedtls_ssl_context *ssl, - const unsigned char *key_enc, const unsigned char *key_dec, - size_t keylen, - const unsigned char *iv_enc, const unsigned char *iv_dec, - size_t ivlen, - const unsigned char *mac_enc, const unsigned char *mac_dec, - size_t maclen) = NULL; -int (*mbedtls_ssl_hw_record_activate)(mbedtls_ssl_context *ssl, int direction) = NULL; -int (*mbedtls_ssl_hw_record_reset)(mbedtls_ssl_context *ssl) = NULL; -int (*mbedtls_ssl_hw_record_write)(mbedtls_ssl_context *ssl) = NULL; -int (*mbedtls_ssl_hw_record_read)(mbedtls_ssl_context *ssl) = NULL; -int (*mbedtls_ssl_hw_record_finish)(mbedtls_ssl_context *ssl) = NULL; -#endif /* MBEDTLS_SSL_HW_RECORD_ACCEL */ - /* * Encryption/decryption functions */ -#if defined(MBEDTLS_SSL_DTLS_CONNECTION_ID) || \ - defined(MBEDTLS_SSL_PROTO_TLS1_3_EXPERIMENTAL) +#if defined(MBEDTLS_SSL_DTLS_CONNECTION_ID) || defined(MBEDTLS_SSL_PROTO_TLS1_3) static size_t ssl_compute_padding_length(size_t len, size_t granularity) @@ -406,162 +610,248 @@ static int ssl_parse_inner_plaintext(unsigned char const *content, return 0; } -#endif /* MBEDTLS_SSL_DTLS_CONNECTION_ID || - MBEDTLS_SSL_PROTO_TLS1_3_EXPERIMENTAL */ +#endif /* MBEDTLS_SSL_DTLS_CONNECTION_ID || MBEDTLS_SSL_PROTO_TLS1_3 */ -/* `add_data` must have size 13 Bytes if the CID extension is disabled, - * and 13 + 1 + CID-length Bytes if the CID extension is enabled. */ +/* The size of the `add_data` structure depends on various + * factors, namely + * + * 1) CID functionality disabled + * + * additional_data = + * 8: seq_num + + * 1: type + + * 2: version + + * 2: length of inner plaintext + + * + * size = 13 bytes + * + * 2) CID functionality based on RFC 9146 enabled + * + * size = 8 + 1 + 1 + 1 + 2 + 2 + 6 + 2 + CID-length + * = 23 + CID-length + * + * 3) CID functionality based on legacy CID version + according to draft-ietf-tls-dtls-connection-id-05 + * https://tools.ietf.org/html/draft-ietf-tls-dtls-connection-id-05 + * + * size = 13 + 1 + CID-length + * + * More information about the CID usage: + * + * Per Section 5.3 of draft-ietf-tls-dtls-connection-id-05 the + * size of the additional data structure is calculated as: + * + * additional_data = + * 8: seq_num + + * 1: tls12_cid + + * 2: DTLSCipherText.version + + * n: cid + + * 1: cid_length + + * 2: length_of_DTLSInnerPlaintext + * + * Per RFC 9146 the size of the add_data structure is calculated as: + * + * additional_data = + * 8: seq_num_placeholder + + * 1: tls12_cid + + * 1: cid_length + + * 1: tls12_cid + + * 2: DTLSCiphertext.version + + * 2: epoch + + * 6: sequence_number + + * n: cid + + * 2: length_of_DTLSInnerPlaintext + * + */ static void ssl_extract_add_data_from_record(unsigned char *add_data, size_t *add_data_len, mbedtls_record *rec, - unsigned minor_ver) + mbedtls_ssl_protocol_version + tls_version, + size_t taglen) { - /* Quoting RFC 5246 (TLS 1.2): + /* Several types of ciphers have been defined for use with TLS and DTLS, + * and the MAC calculations for those ciphers differ slightly. Further + * variants were added when the CID functionality was added with RFC 9146. + * This implementations also considers the use of a legacy version of the + * CID specification published in draft-ietf-tls-dtls-connection-id-05, + * which is used in deployments. * - * additional_data = seq_num + TLSCompressed.type + - * TLSCompressed.version + TLSCompressed.length; + * We will distinguish between the non-CID and the CID cases below. * - * For the CID extension, this is extended as follows - * (quoting draft-ietf-tls-dtls-connection-id-05, - * https://tools.ietf.org/html/draft-ietf-tls-dtls-connection-id-05): + * --- Non-CID cases --- * - * additional_data = seq_num + DTLSPlaintext.type + - * DTLSPlaintext.version + - * cid + - * cid_length + - * length_of_DTLSInnerPlaintext; + * Quoting RFC 5246 (TLS 1.2): + * + * additional_data = seq_num + TLSCompressed.type + + * TLSCompressed.version + TLSCompressed.length; * * For TLS 1.3, the record sequence number is dropped from the AAD * and encoded within the nonce of the AEAD operation instead. + * Moreover, the additional data involves the length of the TLS + * ciphertext, not the TLS plaintext as in earlier versions. + * Quoting RFC 8446 (TLS 1.3): + * + * additional_data = TLSCiphertext.opaque_type || + * TLSCiphertext.legacy_record_version || + * TLSCiphertext.length + * + * We pass the tag length to this function in order to compute the + * ciphertext length from the inner plaintext length rec->data_len via + * + * TLSCiphertext.length = TLSInnerPlaintext.length + taglen. + * + * --- CID cases --- + * + * RFC 9146 uses a common pattern when constructing the data + * passed into a MAC / AEAD cipher. + * + * Data concatenation for MACs used with block ciphers with + * Encrypt-then-MAC Processing (with CID): + * + * data = seq_num_placeholder + + * tls12_cid + + * cid_length + + * tls12_cid + + * DTLSCiphertext.version + + * epoch + + * sequence_number + + * cid + + * DTLSCiphertext.length + + * IV + + * ENC(content + padding + padding_length) + * + * Data concatenation for MACs used with block ciphers (with CID): + * + * data = seq_num_placeholder + + * tls12_cid + + * cid_length + + * tls12_cid + + * DTLSCiphertext.version + + * epoch + + * sequence_number + + * cid + + * length_of_DTLSInnerPlaintext + + * DTLSInnerPlaintext.content + + * DTLSInnerPlaintext.real_type + + * DTLSInnerPlaintext.zeros + * + * AEAD ciphers use the following additional data calculation (with CIDs): + * + * additional_data = seq_num_placeholder + + * tls12_cid + + * cid_length + + * tls12_cid + + * DTLSCiphertext.version + + * epoch + + * sequence_number + + * cid + + * length_of_DTLSInnerPlaintext + * + * Section 5.3 of draft-ietf-tls-dtls-connection-id-05 (for legacy CID use) + * defines the additional data calculation as follows: + * + * additional_data = seq_num + + * tls12_cid + + * DTLSCipherText.version + + * cid + + * cid_length + + * length_of_DTLSInnerPlaintext */ unsigned char *cur = add_data; + size_t ad_len_field = rec->data_len; - int is_tls13 = 0; -#if defined(MBEDTLS_SSL_PROTO_TLS1_3_EXPERIMENTAL) - if (minor_ver == MBEDTLS_SSL_MINOR_VERSION_4) { - is_tls13 = 1; - } -#endif /* MBEDTLS_SSL_PROTO_TLS1_3_EXPERIMENTAL */ - if (!is_tls13) { - ((void) minor_ver); - memcpy(cur, rec->ctr, sizeof(rec->ctr)); - cur += sizeof(rec->ctr); +#if defined(MBEDTLS_SSL_DTLS_CONNECTION_ID) && \ + MBEDTLS_SSL_DTLS_CONNECTION_ID_COMPAT == 0 + const unsigned char seq_num_placeholder[] = { 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff }; +#endif + +#if defined(MBEDTLS_SSL_PROTO_TLS1_3) + if (tls_version == MBEDTLS_SSL_VERSION_TLS1_3) { + /* In TLS 1.3, the AAD contains the length of the TLSCiphertext, + * which differs from the length of the TLSInnerPlaintext + * by the length of the authentication tag. */ + ad_len_field += taglen; + } else +#endif /* MBEDTLS_SSL_PROTO_TLS1_3 */ + { + ((void) tls_version); + ((void) taglen); + +#if defined(MBEDTLS_SSL_DTLS_CONNECTION_ID) && \ + MBEDTLS_SSL_DTLS_CONNECTION_ID_COMPAT == 0 + if (rec->cid_len != 0) { + // seq_num_placeholder + memcpy(cur, seq_num_placeholder, sizeof(seq_num_placeholder)); + cur += sizeof(seq_num_placeholder); + + // tls12_cid type + *cur = rec->type; + cur++; + + // cid_length + *cur = rec->cid_len; + cur++; + } else +#endif /* MBEDTLS_SSL_DTLS_CONNECTION_ID */ + { + // epoch + sequence number + memcpy(cur, rec->ctr, sizeof(rec->ctr)); + cur += sizeof(rec->ctr); + } } + // type *cur = rec->type; cur++; + // version memcpy(cur, rec->ver, sizeof(rec->ver)); cur += sizeof(rec->ver); -#if defined(MBEDTLS_SSL_DTLS_CONNECTION_ID) +#if defined(MBEDTLS_SSL_DTLS_CONNECTION_ID) && \ + MBEDTLS_SSL_DTLS_CONNECTION_ID_COMPAT == 1 + if (rec->cid_len != 0) { + // CID memcpy(cur, rec->cid, rec->cid_len); cur += rec->cid_len; + // cid_length *cur = rec->cid_len; cur++; - MBEDTLS_PUT_UINT16_BE(rec->data_len, cur, 0); + // length of inner plaintext + MBEDTLS_PUT_UINT16_BE(ad_len_field, cur, 0); cur += 2; } else -#endif /* MBEDTLS_SSL_DTLS_CONNECTION_ID */ - { - MBEDTLS_PUT_UINT16_BE(rec->data_len, cur, 0); - cur += 2; - } - - *add_data_len = cur - add_data; -} - -#if defined(MBEDTLS_SSL_PROTO_SSL3) - -#define SSL3_MAC_MAX_BYTES 20 /* MD-5 or SHA-1 */ - -/* - * SSLv3.0 MAC functions - */ -MBEDTLS_CHECK_RETURN_CRITICAL -static int ssl_mac(mbedtls_md_context_t *md_ctx, - const unsigned char *secret, - const unsigned char *buf, size_t len, - const unsigned char *ctr, int type, - unsigned char out[SSL3_MAC_MAX_BYTES]) -{ - unsigned char header[11]; - unsigned char padding[48]; - int padlen; - int md_size = mbedtls_md_get_size(md_ctx->md_info); - int md_type = mbedtls_md_get_type(md_ctx->md_info); - int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED; - - /* Only MD5 and SHA-1 supported */ - if (md_type == MBEDTLS_MD_MD5) { - padlen = 48; - } else { - padlen = 40; - } +#elif defined(MBEDTLS_SSL_DTLS_CONNECTION_ID) && \ + MBEDTLS_SSL_DTLS_CONNECTION_ID_COMPAT == 0 - memcpy(header, ctr, 8); - header[8] = (unsigned char) type; - MBEDTLS_PUT_UINT16_BE(len, header, 9); + if (rec->cid_len != 0) { + // epoch + sequence number + memcpy(cur, rec->ctr, sizeof(rec->ctr)); + cur += sizeof(rec->ctr); - memset(padding, 0x36, padlen); - ret = mbedtls_md_starts(md_ctx); - if (ret != 0) { - return ret; - } - ret = mbedtls_md_update(md_ctx, secret, md_size); - if (ret != 0) { - return ret; - } - ret = mbedtls_md_update(md_ctx, padding, padlen); - if (ret != 0) { - return ret; - } - ret = mbedtls_md_update(md_ctx, header, 11); - if (ret != 0) { - return ret; - } - ret = mbedtls_md_update(md_ctx, buf, len); - if (ret != 0) { - return ret; - } - ret = mbedtls_md_finish(md_ctx, out); - if (ret != 0) { - return ret; - } + // CID + memcpy(cur, rec->cid, rec->cid_len); + cur += rec->cid_len; - memset(padding, 0x5C, padlen); - ret = mbedtls_md_starts(md_ctx); - if (ret != 0) { - return ret; - } - ret = mbedtls_md_update(md_ctx, secret, md_size); - if (ret != 0) { - return ret; - } - ret = mbedtls_md_update(md_ctx, padding, padlen); - if (ret != 0) { - return ret; - } - ret = mbedtls_md_update(md_ctx, out, md_size); - if (ret != 0) { - return ret; - } - ret = mbedtls_md_finish(md_ctx, out); - if (ret != 0) { - return ret; + // length of inner plaintext + MBEDTLS_PUT_UINT16_BE(ad_len_field, cur, 0); + cur += 2; + } else +#endif /* MBEDTLS_SSL_DTLS_CONNECTION_ID */ + { + MBEDTLS_PUT_UINT16_BE(ad_len_field, cur, 0); + cur += 2; } - return 0; + *add_data_len = (size_t) (cur - add_data); } -#endif /* MBEDTLS_SSL_PROTO_SSL3 */ -#if defined(MBEDTLS_GCM_C) || \ - defined(MBEDTLS_CCM_C) || \ - defined(MBEDTLS_CHACHAPOLY_C) +#if defined(MBEDTLS_SSL_HAVE_AEAD) MBEDTLS_CHECK_RETURN_CRITICAL static int ssl_transform_aead_dynamic_iv_is_explicit( mbedtls_ssl_transform const *transform) @@ -599,18 +889,14 @@ static void ssl_build_record_nonce(unsigned char *dst_iv, unsigned char const *dynamic_iv, size_t dynamic_iv_len) { - size_t i; - /* Start with Fixed IV || 0 */ memset(dst_iv, 0, dst_iv_len); memcpy(dst_iv, fixed_iv, fixed_iv_len); dst_iv += dst_iv_len - dynamic_iv_len; - for (i = 0; i < dynamic_iv_len; i++) { - dst_iv[i] ^= dynamic_iv[i]; - } + mbedtls_xor(dst_iv, dst_iv, dynamic_iv, dynamic_iv_len); } -#endif /* MBEDTLS_GCM_C || MBEDTLS_CCM_C || MBEDTLS_CHACHAPOLY_C */ +#endif /* MBEDTLS_SSL_HAVE_AEAD */ int mbedtls_ssl_encrypt_buf(mbedtls_ssl_context *ssl, mbedtls_ssl_transform *transform, @@ -618,10 +904,17 @@ int mbedtls_ssl_encrypt_buf(mbedtls_ssl_context *ssl, int (*f_rng)(void *, unsigned char *, size_t), void *p_rng) { - mbedtls_cipher_mode_t mode; + mbedtls_ssl_mode_t ssl_mode; int auth_done = 0; unsigned char *data; - unsigned char add_data[13 + 1 + MBEDTLS_SSL_CID_OUT_LEN_MAX]; + /* For an explanation of the additional data length see + * the description of ssl_extract_add_data_from_record(). + */ +#if defined(MBEDTLS_SSL_DTLS_CONNECTION_ID) + unsigned char add_data[23 + MBEDTLS_SSL_CID_OUT_LEN_MAX]; +#else + unsigned char add_data[13]; +#endif size_t add_data_len; size_t post_avail; @@ -632,9 +925,9 @@ int mbedtls_ssl_encrypt_buf(mbedtls_ssl_context *ssl, #endif /* The PRNG is used for dynamic IV generation that's used - * for CBC transformations in TLS 1.1 and TLS 1.2. */ + * for CBC transformations in TLS 1.2. */ #if !(defined(MBEDTLS_SSL_SOME_SUITES_USE_CBC) && \ - (defined(MBEDTLS_SSL_PROTO_TLS1_1) || defined(MBEDTLS_SSL_PROTO_TLS1_2))) + defined(MBEDTLS_SSL_PROTO_TLS1_2)) ((void) f_rng); ((void) p_rng); #endif @@ -657,13 +950,13 @@ int mbedtls_ssl_encrypt_buf(mbedtls_ssl_context *ssl, return MBEDTLS_ERR_SSL_INTERNAL_ERROR; } + ssl_mode = mbedtls_ssl_get_mode_from_transform(transform); + data = rec->buf + rec->data_offset; post_avail = rec->buf_len - (rec->data_len + rec->data_offset); MBEDTLS_SSL_DEBUG_BUF(4, "before encrypt: output payload", data, rec->data_len); - mode = mbedtls_cipher_get_cipher_mode(&transform->cipher_ctx_enc); - if (rec->data_len > MBEDTLS_SSL_OUT_CONTENT_LEN) { MBEDTLS_SSL_DEBUG_MSG(1, ("Record content %" MBEDTLS_PRINTF_SIZET " too large, maximum %" MBEDTLS_PRINTF_SIZET, @@ -684,11 +977,11 @@ int mbedtls_ssl_encrypt_buf(mbedtls_ssl_context *ssl, * since they apply to different versions of the protocol. There * is hence no risk of double-addition of the inner plaintext. */ -#if defined(MBEDTLS_SSL_PROTO_TLS1_3_EXPERIMENTAL) - if (transform->minor_ver == MBEDTLS_SSL_MINOR_VERSION_4) { +#if defined(MBEDTLS_SSL_PROTO_TLS1_3) + if (transform->tls_version == MBEDTLS_SSL_VERSION_TLS1_3) { size_t padding = ssl_compute_padding_length(rec->data_len, - MBEDTLS_SSL_TLS1_3_PADDING_GRANULARITY); + MBEDTLS_SSL_CID_TLS1_3_PADDING_GRANULARITY); if (ssl_build_inner_plaintext(data, &rec->data_len, post_avail, @@ -699,7 +992,7 @@ int mbedtls_ssl_encrypt_buf(mbedtls_ssl_context *ssl, rec->type = MBEDTLS_SSL_MSG_APPLICATION_DATA; } -#endif /* MBEDTLS_SSL_PROTO_TLS1_3_EXPERIMENTAL */ +#endif /* MBEDTLS_SSL_PROTO_TLS1_3 */ #if defined(MBEDTLS_SSL_DTLS_CONNECTION_ID) /* @@ -712,7 +1005,7 @@ int mbedtls_ssl_encrypt_buf(mbedtls_ssl_context *ssl, if (rec->cid_len != 0) { size_t padding = ssl_compute_padding_length(rec->data_len, - MBEDTLS_SSL_CID_PADDING_GRANULARITY); + MBEDTLS_SSL_CID_TLS1_3_PADDING_GRANULARITY); /* * Wrap plaintext into DTLSInnerPlaintext structure. * See ssl_build_inner_plaintext() for more information. @@ -737,76 +1030,70 @@ int mbedtls_ssl_encrypt_buf(mbedtls_ssl_context *ssl, /* * Add MAC before if needed */ -#if defined(MBEDTLS_SSL_SOME_MODES_USE_MAC) - if (mode == MBEDTLS_MODE_STREAM || - (mode == MBEDTLS_MODE_CBC -#if defined(MBEDTLS_SSL_ENCRYPT_THEN_MAC) - && transform->encrypt_then_mac == MBEDTLS_SSL_ETM_DISABLED -#endif - )) { +#if defined(MBEDTLS_SSL_SOME_SUITES_USE_MAC) + if (ssl_mode == MBEDTLS_SSL_MODE_STREAM || + ssl_mode == MBEDTLS_SSL_MODE_CBC) { if (post_avail < transform->maclen) { MBEDTLS_SSL_DEBUG_MSG(1, ("Buffer provided for encrypted record not large enough")); return MBEDTLS_ERR_SSL_BUFFER_TOO_SMALL; } +#if defined(MBEDTLS_SSL_PROTO_TLS1_2) + unsigned char mac[MBEDTLS_SSL_MAC_ADD]; + int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED; +#if defined(MBEDTLS_USE_PSA_CRYPTO) + psa_mac_operation_t operation = PSA_MAC_OPERATION_INIT; + psa_status_t status = PSA_ERROR_CORRUPTION_DETECTED; + size_t sign_mac_length = 0; +#endif /* MBEDTLS_USE_PSA_CRYPTO */ -#if defined(MBEDTLS_SSL_PROTO_SSL3) - if (transform->minor_ver == MBEDTLS_SSL_MINOR_VERSION_0) { - unsigned char mac[SSL3_MAC_MAX_BYTES]; - int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED; - ret = ssl_mac(&transform->md_ctx_enc, transform->mac_enc, - data, rec->data_len, rec->ctr, rec->type, mac); - if (ret == 0) { - memcpy(data + rec->data_len, mac, transform->maclen); - } - mbedtls_platform_zeroize(mac, transform->maclen); - if (ret != 0) { - MBEDTLS_SSL_DEBUG_RET(1, "ssl_mac", ret); - return ret; - } - } else -#endif -#if defined(MBEDTLS_SSL_PROTO_TLS1) || defined(MBEDTLS_SSL_PROTO_TLS1_1) || \ - defined(MBEDTLS_SSL_PROTO_TLS1_2) - if (transform->minor_ver >= MBEDTLS_SSL_MINOR_VERSION_1) { - unsigned char mac[MBEDTLS_SSL_MAC_ADD]; - int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED; + ssl_extract_add_data_from_record(add_data, &add_data_len, rec, + transform->tls_version, + transform->taglen); - ssl_extract_add_data_from_record(add_data, &add_data_len, rec, - transform->minor_ver); +#if defined(MBEDTLS_USE_PSA_CRYPTO) + status = psa_mac_sign_setup(&operation, transform->psa_mac_enc, + transform->psa_mac_alg); + if (status != PSA_SUCCESS) { + goto hmac_failed_etm_disabled; + } - ret = mbedtls_md_hmac_update(&transform->md_ctx_enc, - add_data, add_data_len); - if (ret != 0) { - goto hmac_failed_etm_disabled; - } - ret = mbedtls_md_hmac_update(&transform->md_ctx_enc, - data, rec->data_len); - if (ret != 0) { - goto hmac_failed_etm_disabled; - } - ret = mbedtls_md_hmac_finish(&transform->md_ctx_enc, mac); - if (ret != 0) { - goto hmac_failed_etm_disabled; - } - ret = mbedtls_md_hmac_reset(&transform->md_ctx_enc); - if (ret != 0) { - goto hmac_failed_etm_disabled; - } + status = psa_mac_update(&operation, add_data, add_data_len); + if (status != PSA_SUCCESS) { + goto hmac_failed_etm_disabled; + } - memcpy(data + rec->data_len, mac, transform->maclen); + status = psa_mac_update(&operation, data, rec->data_len); + if (status != PSA_SUCCESS) { + goto hmac_failed_etm_disabled; + } -hmac_failed_etm_disabled: - mbedtls_platform_zeroize(mac, transform->maclen); - if (ret != 0) { - MBEDTLS_SSL_DEBUG_RET(1, "mbedtls_md_hmac_xxx", ret); - return ret; - } - } else -#endif - { - MBEDTLS_SSL_DEBUG_MSG(1, ("should never happen")); - return MBEDTLS_ERR_SSL_INTERNAL_ERROR; + status = psa_mac_sign_finish(&operation, mac, MBEDTLS_SSL_MAC_ADD, + &sign_mac_length); + if (status != PSA_SUCCESS) { + goto hmac_failed_etm_disabled; + } +#else + ret = mbedtls_md_hmac_update(&transform->md_ctx_enc, add_data, + add_data_len); + if (ret != 0) { + goto hmac_failed_etm_disabled; + } + ret = mbedtls_md_hmac_update(&transform->md_ctx_enc, data, rec->data_len); + if (ret != 0) { + goto hmac_failed_etm_disabled; + } + ret = mbedtls_md_hmac_finish(&transform->md_ctx_enc, mac); + if (ret != 0) { + goto hmac_failed_etm_disabled; + } + ret = mbedtls_md_hmac_reset(&transform->md_ctx_enc); + if (ret != 0) { + goto hmac_failed_etm_disabled; } +#endif /* MBEDTLS_USE_PSA_CRYPTO */ + + memcpy(data + rec->data_len, mac, transform->maclen); +#endif MBEDTLS_SSL_DEBUG_BUF(4, "computed mac", data + rec->data_len, transform->maclen); @@ -814,47 +1101,48 @@ int mbedtls_ssl_encrypt_buf(mbedtls_ssl_context *ssl, rec->data_len += transform->maclen; post_avail -= transform->maclen; auth_done++; + +hmac_failed_etm_disabled: + mbedtls_platform_zeroize(mac, transform->maclen); +#if defined(MBEDTLS_USE_PSA_CRYPTO) + ret = PSA_TO_MBEDTLS_ERR(status); + status = psa_mac_abort(&operation); + if (ret == 0 && status != PSA_SUCCESS) { + ret = PSA_TO_MBEDTLS_ERR(status); + } +#endif /* MBEDTLS_USE_PSA_CRYPTO */ + if (ret != 0) { + MBEDTLS_SSL_DEBUG_RET(1, "mbedtls_md_hmac_xxx", ret); + return ret; + } } -#endif /* MBEDTLS_SSL_SOME_MODES_USE_MAC */ +#endif /* MBEDTLS_SSL_SOME_SUITES_USE_MAC */ /* * Encrypt */ -#if defined(MBEDTLS_ARC4_C) || defined(MBEDTLS_CIPHER_NULL_CIPHER) - if (mode == MBEDTLS_MODE_STREAM) { - int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED; - size_t olen; +#if defined(MBEDTLS_SSL_SOME_SUITES_USE_STREAM) + if (ssl_mode == MBEDTLS_SSL_MODE_STREAM) { MBEDTLS_SSL_DEBUG_MSG(3, ("before encrypt: msglen = %" MBEDTLS_PRINTF_SIZET ", " "including %d bytes of padding", rec->data_len, 0)); - if ((ret = mbedtls_cipher_crypt(&transform->cipher_ctx_enc, - transform->iv_enc, transform->ivlen, - data, rec->data_len, - data, &olen)) != 0) { - MBEDTLS_SSL_DEBUG_RET(1, "mbedtls_cipher_crypt", ret); - return ret; - } - - if (rec->data_len != olen) { - MBEDTLS_SSL_DEBUG_MSG(1, ("should never happen")); - return MBEDTLS_ERR_SSL_INTERNAL_ERROR; - } + /* The only supported stream cipher is "NULL", + * so there's nothing to do here.*/ } else -#endif /* MBEDTLS_ARC4_C || MBEDTLS_CIPHER_NULL_CIPHER */ - -#if defined(MBEDTLS_GCM_C) || \ - defined(MBEDTLS_CCM_C) || \ - defined(MBEDTLS_CHACHAPOLY_C) - if (mode == MBEDTLS_MODE_GCM || - mode == MBEDTLS_MODE_CCM || - mode == MBEDTLS_MODE_CHACHAPOLY) { - int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED; +#endif /* MBEDTLS_SSL_SOME_SUITES_USE_STREAM */ + +#if defined(MBEDTLS_SSL_HAVE_AEAD) + if (ssl_mode == MBEDTLS_SSL_MODE_AEAD) { unsigned char iv[12]; unsigned char *dynamic_iv; size_t dynamic_iv_len; int dynamic_iv_is_explicit = ssl_transform_aead_dynamic_iv_is_explicit(transform); +#if defined(MBEDTLS_USE_PSA_CRYPTO) + psa_status_t status = PSA_ERROR_CORRUPTION_DETECTED; +#endif /* MBEDTLS_USE_PSA_CRYPTO */ + int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED; /* Check that there's space for the authentication tag. */ if (post_avail < transform->taglen) { @@ -888,7 +1176,8 @@ int mbedtls_ssl_encrypt_buf(mbedtls_ssl_context *ssl, * This depends on the TLS version. */ ssl_extract_add_data_from_record(add_data, &add_data_len, rec, - transform->minor_ver); + transform->tls_version, + transform->taglen); MBEDTLS_SSL_DEBUG_BUF(4, "IV used (internal)", iv, transform->ivlen); @@ -904,17 +1193,33 @@ int mbedtls_ssl_encrypt_buf(mbedtls_ssl_context *ssl, /* * Encrypt and authenticate */ +#if defined(MBEDTLS_USE_PSA_CRYPTO) + status = psa_aead_encrypt(transform->psa_key_enc, + transform->psa_alg, + iv, transform->ivlen, + add_data, add_data_len, + data, rec->data_len, + data, rec->buf_len - (data - rec->buf), + &rec->data_len); + if (status != PSA_SUCCESS) { + ret = PSA_TO_MBEDTLS_ERR(status); + MBEDTLS_SSL_DEBUG_RET(1, "mbedtls_ssl_encrypt_buf", ret); + return ret; + } +#else if ((ret = mbedtls_cipher_auth_encrypt_ext(&transform->cipher_ctx_enc, iv, transform->ivlen, add_data, add_data_len, data, rec->data_len, /* src */ - data, rec->buf_len - (data - rec->buf), /* dst */ + data, rec->buf_len - (size_t) (data - rec->buf), /* dst */ &rec->data_len, transform->taglen)) != 0) { - MBEDTLS_SSL_DEBUG_RET(1, "mbedtls_cipher_auth_encrypt", ret); + MBEDTLS_SSL_DEBUG_RET(1, "mbedtls_cipher_auth_encrypt_ext", ret); return ret; } +#endif /* MBEDTLS_USE_PSA_CRYPTO */ + MBEDTLS_SSL_DEBUG_BUF(4, "after encrypt: tag", data + rec->data_len - transform->taglen, transform->taglen); @@ -937,12 +1242,18 @@ int mbedtls_ssl_encrypt_buf(mbedtls_ssl_context *ssl, auth_done++; } else -#endif /* MBEDTLS_GCM_C || MBEDTLS_CCM_C || MBEDTLS_CHACHAPOLY_C */ +#endif /* MBEDTLS_SSL_HAVE_AEAD */ #if defined(MBEDTLS_SSL_SOME_SUITES_USE_CBC) - if (mode == MBEDTLS_MODE_CBC) { + if (ssl_mode == MBEDTLS_SSL_MODE_CBC || + ssl_mode == MBEDTLS_SSL_MODE_CBC_ETM) { int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED; size_t padlen, i; size_t olen; +#if defined(MBEDTLS_USE_PSA_CRYPTO) + psa_status_t status = PSA_ERROR_CORRUPTION_DETECTED; + size_t part_len; + psa_cipher_operation_t cipher_op = PSA_CIPHER_OPERATION_INIT; +#endif /* MBEDTLS_USE_PSA_CRYPTO */ /* Currently we're always using minimal padding * (up to 255 bytes would be allowed). */ @@ -964,35 +1275,31 @@ int mbedtls_ssl_encrypt_buf(mbedtls_ssl_context *ssl, rec->data_len += padlen + 1; post_avail -= padlen + 1; -#if defined(MBEDTLS_SSL_PROTO_TLS1_1) || defined(MBEDTLS_SSL_PROTO_TLS1_2) +#if defined(MBEDTLS_SSL_PROTO_TLS1_2) /* - * Prepend per-record IV for block cipher in TLS v1.1 and up as per + * Prepend per-record IV for block cipher in TLS v1.2 as per * Method 1 (6.2.3.2. in RFC4346 and RFC5246) */ - if (transform->minor_ver >= MBEDTLS_SSL_MINOR_VERSION_2) { - if (f_rng == NULL) { - MBEDTLS_SSL_DEBUG_MSG(1, ("No PRNG provided to encrypt_record routine")); - return MBEDTLS_ERR_SSL_INTERNAL_ERROR; - } - - if (rec->data_offset < transform->ivlen) { - MBEDTLS_SSL_DEBUG_MSG(1, ("Buffer provided for encrypted record not large enough")); - return MBEDTLS_ERR_SSL_BUFFER_TOO_SMALL; - } - - /* - * Generate IV - */ - ret = f_rng(p_rng, transform->iv_enc, transform->ivlen); - if (ret != 0) { - return ret; - } + if (f_rng == NULL) { + MBEDTLS_SSL_DEBUG_MSG(1, ("No PRNG provided to encrypt_record routine")); + return MBEDTLS_ERR_SSL_INTERNAL_ERROR; + } - memcpy(data - transform->ivlen, transform->iv_enc, - transform->ivlen); + if (rec->data_offset < transform->ivlen) { + MBEDTLS_SSL_DEBUG_MSG(1, ("Buffer provided for encrypted record not large enough")); + return MBEDTLS_ERR_SSL_BUFFER_TOO_SMALL; + } + /* + * Generate IV + */ + ret = f_rng(p_rng, transform->iv_enc, transform->ivlen); + if (ret != 0) { + return ret; } -#endif /* MBEDTLS_SSL_PROTO_TLS1_1 || MBEDTLS_SSL_PROTO_TLS1_2 */ + + memcpy(data - transform->ivlen, transform->iv_enc, transform->ivlen); +#endif /* MBEDTLS_SSL_PROTO_TLS1_2 */ MBEDTLS_SSL_DEBUG_MSG(3, ("before encrypt: msglen = %" MBEDTLS_PRINTF_SIZET ", " "including %" @@ -1001,6 +1308,49 @@ int mbedtls_ssl_encrypt_buf(mbedtls_ssl_context *ssl, rec->data_len, transform->ivlen, padlen + 1)); +#if defined(MBEDTLS_USE_PSA_CRYPTO) + status = psa_cipher_encrypt_setup(&cipher_op, + transform->psa_key_enc, transform->psa_alg); + + if (status != PSA_SUCCESS) { + ret = PSA_TO_MBEDTLS_ERR(status); + MBEDTLS_SSL_DEBUG_RET(1, "psa_cipher_encrypt_setup", ret); + return ret; + } + + status = psa_cipher_set_iv(&cipher_op, transform->iv_enc, transform->ivlen); + + if (status != PSA_SUCCESS) { + ret = PSA_TO_MBEDTLS_ERR(status); + MBEDTLS_SSL_DEBUG_RET(1, "psa_cipher_set_iv", ret); + return ret; + + } + + status = psa_cipher_update(&cipher_op, + data, rec->data_len, + data, rec->data_len, &olen); + + if (status != PSA_SUCCESS) { + ret = PSA_TO_MBEDTLS_ERR(status); + MBEDTLS_SSL_DEBUG_RET(1, "psa_cipher_update", ret); + return ret; + + } + + status = psa_cipher_finish(&cipher_op, + data + olen, rec->data_len - olen, + &part_len); + + if (status != PSA_SUCCESS) { + ret = PSA_TO_MBEDTLS_ERR(status); + MBEDTLS_SSL_DEBUG_RET(1, "psa_cipher_finish", ret); + return ret; + + } + + olen += part_len; +#else if ((ret = mbedtls_cipher_crypt(&transform->cipher_ctx_enc, transform->iv_enc, transform->ivlen, @@ -1009,38 +1359,26 @@ int mbedtls_ssl_encrypt_buf(mbedtls_ssl_context *ssl, MBEDTLS_SSL_DEBUG_RET(1, "mbedtls_cipher_crypt", ret); return ret; } +#endif /* MBEDTLS_USE_PSA_CRYPTO */ if (rec->data_len != olen) { MBEDTLS_SSL_DEBUG_MSG(1, ("should never happen")); return MBEDTLS_ERR_SSL_INTERNAL_ERROR; } -#if defined(MBEDTLS_SSL_PROTO_SSL3) || defined(MBEDTLS_SSL_PROTO_TLS1) - if (transform->minor_ver < MBEDTLS_SSL_MINOR_VERSION_2) { - /* - * Save IV in SSL3 and TLS1 - */ - memcpy(transform->iv_enc, transform->cipher_ctx_enc.iv, - transform->ivlen); - } else -#endif - { - data -= transform->ivlen; - rec->data_offset -= transform->ivlen; - rec->data_len += transform->ivlen; - } + data -= transform->ivlen; + rec->data_offset -= transform->ivlen; + rec->data_len += transform->ivlen; #if defined(MBEDTLS_SSL_ENCRYPT_THEN_MAC) if (auth_done == 0) { unsigned char mac[MBEDTLS_SSL_MAC_ADD]; +#if defined(MBEDTLS_USE_PSA_CRYPTO) + psa_mac_operation_t operation = PSA_MAC_OPERATION_INIT; + size_t sign_mac_length = 0; +#endif /* MBEDTLS_USE_PSA_CRYPTO */ - /* - * MAC(MAC_write_key, seq_num + - * TLSCipherText.type + - * TLSCipherText.version + - * length_of( (IV +) ENC(...) ) + - * IV + // except for TLS 1.0 - * ENC(content + padding + padding_length)); + /* MAC(MAC_write_key, add_data, IV, ENC(content + padding + padding_length)) */ if (post_avail < transform->maclen) { @@ -1049,11 +1387,35 @@ int mbedtls_ssl_encrypt_buf(mbedtls_ssl_context *ssl, } ssl_extract_add_data_from_record(add_data, &add_data_len, - rec, transform->minor_ver); + rec, transform->tls_version, + transform->taglen); MBEDTLS_SSL_DEBUG_MSG(3, ("using encrypt then mac")); MBEDTLS_SSL_DEBUG_BUF(4, "MAC'd meta-data", add_data, add_data_len); +#if defined(MBEDTLS_USE_PSA_CRYPTO) + status = psa_mac_sign_setup(&operation, transform->psa_mac_enc, + transform->psa_mac_alg); + if (status != PSA_SUCCESS) { + goto hmac_failed_etm_enabled; + } + + status = psa_mac_update(&operation, add_data, add_data_len); + if (status != PSA_SUCCESS) { + goto hmac_failed_etm_enabled; + } + + status = psa_mac_update(&operation, data, rec->data_len); + if (status != PSA_SUCCESS) { + goto hmac_failed_etm_enabled; + } + + status = psa_mac_sign_finish(&operation, mac, MBEDTLS_SSL_MAC_ADD, + &sign_mac_length); + if (status != PSA_SUCCESS) { + goto hmac_failed_etm_enabled; + } +#else ret = mbedtls_md_hmac_update(&transform->md_ctx_enc, add_data, add_data_len); @@ -1073,6 +1435,7 @@ int mbedtls_ssl_encrypt_buf(mbedtls_ssl_context *ssl, if (ret != 0) { goto hmac_failed_etm_enabled; } +#endif /* MBEDTLS_USE_PSA_CRYPTO */ memcpy(data + rec->data_len, mac, transform->maclen); @@ -1082,6 +1445,13 @@ int mbedtls_ssl_encrypt_buf(mbedtls_ssl_context *ssl, hmac_failed_etm_enabled: mbedtls_platform_zeroize(mac, transform->maclen); +#if defined(MBEDTLS_USE_PSA_CRYPTO) + ret = PSA_TO_MBEDTLS_ERR(status); + status = psa_mac_abort(&operation); + if (ret == 0 && status != PSA_SUCCESS) { + ret = PSA_TO_MBEDTLS_ERR(status); + } +#endif /* MBEDTLS_USE_PSA_CRYPTO */ if (ret != 0) { MBEDTLS_SSL_DEBUG_RET(1, "HMAC calculation failed", ret); return ret; @@ -1110,14 +1480,26 @@ int mbedtls_ssl_decrypt_buf(mbedtls_ssl_context const *ssl, mbedtls_ssl_transform *transform, mbedtls_record *rec) { +#if defined(MBEDTLS_SSL_SOME_SUITES_USE_CBC) || defined(MBEDTLS_SSL_HAVE_AEAD) size_t olen; - mbedtls_cipher_mode_t mode; - int ret, auth_done = 0; -#if defined(MBEDTLS_SSL_SOME_MODES_USE_MAC) - size_t padlen = 0, correct = 1; +#endif /* MBEDTLS_SSL_SOME_SUITES_USE_CBC || MBEDTLS_SSL_HAVE_AEAD */ + mbedtls_ssl_mode_t ssl_mode; + int ret; + + int auth_done = 0; +#if defined(MBEDTLS_SSL_SOME_SUITES_USE_MAC) + size_t padlen = 0; + mbedtls_ct_condition_t correct = MBEDTLS_CT_TRUE; #endif unsigned char *data; - unsigned char add_data[13 + 1 + MBEDTLS_SSL_CID_IN_LEN_MAX]; + /* For an explanation of the additional data length see + * the description of ssl_extract_add_data_from_record(). + */ +#if defined(MBEDTLS_SSL_DTLS_CONNECTION_ID) + unsigned char add_data[23 + MBEDTLS_SSL_CID_IN_LEN_MAX]; +#else + unsigned char add_data[13]; +#endif size_t add_data_len; #if !defined(MBEDTLS_DEBUG_C) @@ -1135,7 +1517,7 @@ int mbedtls_ssl_decrypt_buf(mbedtls_ssl_context const *ssl, } data = rec->buf + rec->data_offset; - mode = mbedtls_cipher_get_cipher_mode(&transform->cipher_ctx_dec); + ssl_mode = mbedtls_ssl_get_mode_from_transform(transform); #if defined(MBEDTLS_SSL_DTLS_CONNECTION_ID) /* @@ -1147,8 +1529,8 @@ int mbedtls_ssl_decrypt_buf(mbedtls_ssl_context const *ssl, } #endif /* MBEDTLS_SSL_DTLS_CONNECTION_ID */ -#if defined(MBEDTLS_ARC4_C) || defined(MBEDTLS_CIPHER_NULL_CIPHER) - if (mode == MBEDTLS_MODE_STREAM) { +#if defined(MBEDTLS_SSL_SOME_SUITES_USE_STREAM) + if (ssl_mode == MBEDTLS_SSL_MODE_STREAM) { if (rec->data_len < transform->maclen) { MBEDTLS_SSL_DEBUG_MSG(1, ("Record too short for MAC:" @@ -1157,31 +1539,18 @@ int mbedtls_ssl_decrypt_buf(mbedtls_ssl_context const *ssl, return MBEDTLS_ERR_SSL_INVALID_MAC; } - padlen = 0; - if ((ret = mbedtls_cipher_crypt(&transform->cipher_ctx_dec, - transform->iv_dec, - transform->ivlen, - data, rec->data_len, - data, &olen)) != 0) { - MBEDTLS_SSL_DEBUG_RET(1, "mbedtls_cipher_crypt", ret); - return ret; - } - - if (rec->data_len != olen) { - MBEDTLS_SSL_DEBUG_MSG(1, ("should never happen")); - return MBEDTLS_ERR_SSL_INTERNAL_ERROR; - } + /* The only supported stream cipher is "NULL", + * so there's no encryption to do here.*/ } else -#endif /* MBEDTLS_ARC4_C || MBEDTLS_CIPHER_NULL_CIPHER */ -#if defined(MBEDTLS_GCM_C) || \ - defined(MBEDTLS_CCM_C) || \ - defined(MBEDTLS_CHACHAPOLY_C) - if (mode == MBEDTLS_MODE_GCM || - mode == MBEDTLS_MODE_CCM || - mode == MBEDTLS_MODE_CHACHAPOLY) { +#endif /* MBEDTLS_SSL_SOME_SUITES_USE_STREAM */ +#if defined(MBEDTLS_SSL_HAVE_AEAD) + if (ssl_mode == MBEDTLS_SSL_MODE_AEAD) { unsigned char iv[12]; unsigned char *dynamic_iv; size_t dynamic_iv_len; +#if defined(MBEDTLS_USE_PSA_CRYPTO) + psa_status_t status = PSA_ERROR_CORRUPTION_DETECTED; +#endif /* MBEDTLS_USE_PSA_CRYPTO */ /* * Extract dynamic part of nonce for AEAD decryption. @@ -1233,7 +1602,8 @@ int mbedtls_ssl_decrypt_buf(mbedtls_ssl_context const *ssl, * This depends on the TLS version. */ ssl_extract_add_data_from_record(add_data, &add_data_len, rec, - transform->minor_ver); + transform->tls_version, + transform->taglen); MBEDTLS_SSL_DEBUG_BUF(4, "additional data used for AEAD", add_data, add_data_len); @@ -1241,7 +1611,7 @@ int mbedtls_ssl_decrypt_buf(mbedtls_ssl_context const *ssl, * explicit_iv_len Bytes preceding data, and taglen * bytes following data + data_len. This justifies * the debug message and the invocation of - * mbedtls_cipher_auth_decrypt() below. */ + * mbedtls_cipher_auth_decrypt_ext() below. */ MBEDTLS_SSL_DEBUG_BUF(4, "IV used", iv, transform->ivlen); MBEDTLS_SSL_DEBUG_BUF(4, "TAG used", data + rec->data_len, @@ -1250,13 +1620,29 @@ int mbedtls_ssl_decrypt_buf(mbedtls_ssl_context const *ssl, /* * Decrypt and authenticate */ - if ((ret = mbedtls_cipher_auth_decrypt_ext(&transform->cipher_ctx_dec, - iv, transform->ivlen, - add_data, add_data_len, - data, rec->data_len + transform->taglen, /* src */ - data, rec->buf_len - (data - rec->buf), &olen, /* dst */ - transform->taglen)) != 0) { - MBEDTLS_SSL_DEBUG_RET(1, "mbedtls_cipher_auth_decrypt", ret); +#if defined(MBEDTLS_USE_PSA_CRYPTO) + status = psa_aead_decrypt(transform->psa_key_dec, + transform->psa_alg, + iv, transform->ivlen, + add_data, add_data_len, + data, rec->data_len + transform->taglen, + data, rec->buf_len - (data - rec->buf), + &olen); + + if (status != PSA_SUCCESS) { + ret = PSA_TO_MBEDTLS_ERR(status); + MBEDTLS_SSL_DEBUG_RET(1, "psa_aead_decrypt", ret); + return ret; + } +#else + if ((ret = mbedtls_cipher_auth_decrypt_ext + (&transform->cipher_ctx_dec, + iv, transform->ivlen, + add_data, add_data_len, + data, rec->data_len + transform->taglen, /* src */ + data, rec->buf_len - (size_t) (data - rec->buf), &olen, /* dst */ + transform->taglen)) != 0) { + MBEDTLS_SSL_DEBUG_RET(1, "mbedtls_cipher_auth_decrypt_ext", ret); if (ret == MBEDTLS_ERR_CIPHER_AUTH_FAILED) { return MBEDTLS_ERR_SSL_INVALID_MAC; @@ -1264,6 +1650,8 @@ int mbedtls_ssl_decrypt_buf(mbedtls_ssl_context const *ssl, return ret; } +#endif /* MBEDTLS_USE_PSA_CRYPTO */ + auth_done++; /* Double-check that AEAD decryption doesn't change content length. */ @@ -1272,19 +1660,23 @@ int mbedtls_ssl_decrypt_buf(mbedtls_ssl_context const *ssl, return MBEDTLS_ERR_SSL_INTERNAL_ERROR; } } else -#endif /* MBEDTLS_GCM_C || MBEDTLS_CCM_C */ +#endif /* MBEDTLS_SSL_HAVE_AEAD */ #if defined(MBEDTLS_SSL_SOME_SUITES_USE_CBC) - if (mode == MBEDTLS_MODE_CBC) { + if (ssl_mode == MBEDTLS_SSL_MODE_CBC || + ssl_mode == MBEDTLS_SSL_MODE_CBC_ETM) { size_t minlen = 0; +#if defined(MBEDTLS_USE_PSA_CRYPTO) + psa_status_t status = PSA_ERROR_CORRUPTION_DETECTED; + size_t part_len; + psa_cipher_operation_t cipher_op = PSA_CIPHER_OPERATION_INIT; +#endif /* MBEDTLS_USE_PSA_CRYPTO */ /* * Check immediate ciphertext sanity */ -#if defined(MBEDTLS_SSL_PROTO_TLS1_1) || defined(MBEDTLS_SSL_PROTO_TLS1_2) - if (transform->minor_ver >= MBEDTLS_SSL_MINOR_VERSION_2) { - /* The ciphertext is prefixed with the CBC IV. */ - minlen += transform->ivlen; - } +#if defined(MBEDTLS_SSL_PROTO_TLS1_2) + /* The ciphertext is prefixed with the CBC IV. */ + minlen += transform->ivlen; #endif /* Size considerations: @@ -1324,8 +1716,12 @@ int mbedtls_ssl_decrypt_buf(mbedtls_ssl_context const *ssl, * Authenticate before decrypt if enabled */ #if defined(MBEDTLS_SSL_ENCRYPT_THEN_MAC) - if (transform->encrypt_then_mac == MBEDTLS_SSL_ETM_ENABLED) { + if (ssl_mode == MBEDTLS_SSL_MODE_CBC_ETM) { +#if defined(MBEDTLS_USE_PSA_CRYPTO) + psa_mac_operation_t operation = PSA_MAC_OPERATION_INIT; +#else unsigned char mac_expect[MBEDTLS_SSL_MAC_ADD]; +#endif /* MBEDTLS_USE_PSA_CRYPTO */ MBEDTLS_SSL_DEBUG_MSG(3, ("using encrypt then mac")); @@ -1341,11 +1737,36 @@ int mbedtls_ssl_decrypt_buf(mbedtls_ssl_context const *ssl, * Further, we still know that data_len > minlen */ rec->data_len -= transform->maclen; ssl_extract_add_data_from_record(add_data, &add_data_len, rec, - transform->minor_ver); + transform->tls_version, + transform->taglen); /* Calculate expected MAC. */ MBEDTLS_SSL_DEBUG_BUF(4, "MAC'd meta-data", add_data, add_data_len); +#if defined(MBEDTLS_USE_PSA_CRYPTO) + status = psa_mac_verify_setup(&operation, transform->psa_mac_dec, + transform->psa_mac_alg); + if (status != PSA_SUCCESS) { + goto hmac_failed_etm_enabled; + } + + status = psa_mac_update(&operation, add_data, add_data_len); + if (status != PSA_SUCCESS) { + goto hmac_failed_etm_enabled; + } + + status = psa_mac_update(&operation, data, rec->data_len); + if (status != PSA_SUCCESS) { + goto hmac_failed_etm_enabled; + } + + /* Compare expected MAC with MAC at the end of the record. */ + status = psa_mac_verify_finish(&operation, data + rec->data_len, + transform->maclen); + if (status != PSA_SUCCESS) { + goto hmac_failed_etm_enabled; + } +#else ret = mbedtls_md_hmac_update(&transform->md_ctx_dec, add_data, add_data_len); if (ret != 0) { @@ -1377,10 +1798,19 @@ int mbedtls_ssl_decrypt_buf(mbedtls_ssl_context const *ssl, ret = MBEDTLS_ERR_SSL_INVALID_MAC; goto hmac_failed_etm_enabled; } +#endif /* MBEDTLS_USE_PSA_CRYPTO */ auth_done++; hmac_failed_etm_enabled: +#if defined(MBEDTLS_USE_PSA_CRYPTO) + ret = PSA_TO_MBEDTLS_ERR(status); + status = psa_mac_abort(&operation); + if (ret == 0 && status != PSA_SUCCESS) { + ret = PSA_TO_MBEDTLS_ERR(status); + } +#else mbedtls_platform_zeroize(mac_expect, transform->maclen); +#endif /* MBEDTLS_USE_PSA_CRYPTO */ if (ret != 0) { if (ret != MBEDTLS_ERR_SSL_INVALID_MAC) { MBEDTLS_SSL_DEBUG_RET(1, "mbedtls_hmac_xxx", ret); @@ -1404,28 +1834,68 @@ int mbedtls_ssl_decrypt_buf(mbedtls_ssl_context const *ssl, return MBEDTLS_ERR_SSL_INVALID_MAC; } -#if defined(MBEDTLS_SSL_PROTO_TLS1_1) || defined(MBEDTLS_SSL_PROTO_TLS1_2) +#if defined(MBEDTLS_SSL_PROTO_TLS1_2) /* - * Initialize for prepended IV for block cipher in TLS v1.1 and up + * Initialize for prepended IV for block cipher in TLS v1.2 */ - if (transform->minor_ver >= MBEDTLS_SSL_MINOR_VERSION_2) { - /* Safe because data_len >= minlen + ivlen = 2 * ivlen. */ - memcpy(transform->iv_dec, data, transform->ivlen); + /* Safe because data_len >= minlen + ivlen = 2 * ivlen. */ + memcpy(transform->iv_dec, data, transform->ivlen); - data += transform->ivlen; - rec->data_offset += transform->ivlen; - rec->data_len -= transform->ivlen; - } -#endif /* MBEDTLS_SSL_PROTO_TLS1_1 || MBEDTLS_SSL_PROTO_TLS1_2 */ + data += transform->ivlen; + rec->data_offset += transform->ivlen; + rec->data_len -= transform->ivlen; +#endif /* MBEDTLS_SSL_PROTO_TLS1_2 */ /* We still have data_len % ivlen == 0 and data_len >= ivlen here. */ +#if defined(MBEDTLS_USE_PSA_CRYPTO) + status = psa_cipher_decrypt_setup(&cipher_op, + transform->psa_key_dec, transform->psa_alg); + + if (status != PSA_SUCCESS) { + ret = PSA_TO_MBEDTLS_ERR(status); + MBEDTLS_SSL_DEBUG_RET(1, "psa_cipher_decrypt_setup", ret); + return ret; + } + + status = psa_cipher_set_iv(&cipher_op, transform->iv_dec, transform->ivlen); + + if (status != PSA_SUCCESS) { + ret = PSA_TO_MBEDTLS_ERR(status); + MBEDTLS_SSL_DEBUG_RET(1, "psa_cipher_set_iv", ret); + return ret; + } + + status = psa_cipher_update(&cipher_op, + data, rec->data_len, + data, rec->data_len, &olen); + + if (status != PSA_SUCCESS) { + ret = PSA_TO_MBEDTLS_ERR(status); + MBEDTLS_SSL_DEBUG_RET(1, "psa_cipher_update", ret); + return ret; + } + + status = psa_cipher_finish(&cipher_op, + data + olen, rec->data_len - olen, + &part_len); + + if (status != PSA_SUCCESS) { + ret = PSA_TO_MBEDTLS_ERR(status); + MBEDTLS_SSL_DEBUG_RET(1, "psa_cipher_finish", ret); + return ret; + } + + olen += part_len; +#else + if ((ret = mbedtls_cipher_crypt(&transform->cipher_ctx_dec, transform->iv_dec, transform->ivlen, data, rec->data_len, data, &olen)) != 0) { MBEDTLS_SSL_DEBUG_RET(1, "mbedtls_cipher_crypt", ret); return ret; } +#endif /* MBEDTLS_USE_PSA_CRYPTO */ /* Double-check that length hasn't changed during decryption. */ if (rec->data_len != olen) { @@ -1433,19 +1903,6 @@ int mbedtls_ssl_decrypt_buf(mbedtls_ssl_context const *ssl, return MBEDTLS_ERR_SSL_INTERNAL_ERROR; } -#if defined(MBEDTLS_SSL_PROTO_SSL3) || defined(MBEDTLS_SSL_PROTO_TLS1) - if (transform->minor_ver < MBEDTLS_SSL_MINOR_VERSION_2) { - /* - * Save IV in SSL3 and TLS1, where CBC decryption of consecutive - * records is equivalent to CBC decryption of the concatenation - * of the records; in other words, IVs are maintained across - * record decryptions. - */ - memcpy(transform->iv_dec, transform->cipher_ctx_dec.iv, - transform->ivlen); - } -#endif - /* Safe since data_len >= minlen + maclen + 1, so after having * subtracted at most minlen and maclen up to this point, * data_len > 0 (because of data_len % ivlen == 0, it's actually @@ -1453,11 +1910,11 @@ int mbedtls_ssl_decrypt_buf(mbedtls_ssl_context const *ssl, padlen = data[rec->data_len - 1]; if (auth_done == 1) { - const size_t mask = mbedtls_ct_size_mask_ge( + const mbedtls_ct_condition_t ge = mbedtls_ct_uint_ge( rec->data_len, padlen + 1); - correct &= mask; - padlen &= mask; + correct = mbedtls_ct_bool_and(ge, correct); + padlen = mbedtls_ct_size_if_else_0(ge, padlen); } else { #if defined(MBEDTLS_SSL_DEBUG_ALL) if (rec->data_len < transform->maclen + padlen + 1) { @@ -1469,12 +1926,11 @@ int mbedtls_ssl_decrypt_buf(mbedtls_ssl_context const *ssl, padlen + 1)); } #endif - - const size_t mask = mbedtls_ct_size_mask_ge( + const mbedtls_ct_condition_t ge = mbedtls_ct_uint_ge( rec->data_len, transform->maclen + padlen + 1); - correct &= mask; - padlen &= mask; + correct = mbedtls_ct_bool_and(ge, correct); + padlen = mbedtls_ct_size_if_else_0(ge, padlen); } padlen++; @@ -1482,66 +1938,43 @@ int mbedtls_ssl_decrypt_buf(mbedtls_ssl_context const *ssl, /* Regardless of the validity of the padding, * we have data_len >= padlen here. */ -#if defined(MBEDTLS_SSL_PROTO_SSL3) - if (transform->minor_ver == MBEDTLS_SSL_MINOR_VERSION_0) { - /* This is the SSL 3.0 path, we don't have to worry about Lucky - * 13, because there's a strictly worse padding attack built in - * the protocol (known as part of POODLE), so we don't care if the - * code is not constant-time, in particular branches are OK. */ - if (padlen > transform->ivlen) { -#if defined(MBEDTLS_SSL_DEBUG_ALL) - MBEDTLS_SSL_DEBUG_MSG(1, ("bad padding length: is %" MBEDTLS_PRINTF_SIZET ", " - "should be no more than %" - MBEDTLS_PRINTF_SIZET, - padlen, transform->ivlen)); -#endif - correct = 0; - } - } else -#endif /* MBEDTLS_SSL_PROTO_SSL3 */ -#if defined(MBEDTLS_SSL_PROTO_TLS1) || defined(MBEDTLS_SSL_PROTO_TLS1_1) || \ - defined(MBEDTLS_SSL_PROTO_TLS1_2) - if (transform->minor_ver > MBEDTLS_SSL_MINOR_VERSION_0) { - /* The padding check involves a series of up to 256 - * consecutive memory reads at the end of the record - * plaintext buffer. In order to hide the length and - * validity of the padding, always perform exactly - * `min(256,plaintext_len)` reads (but take into account - * only the last `padlen` bytes for the padding check). */ - size_t pad_count = 0; - volatile unsigned char * const check = data; - - /* Index of first padding byte; it has been ensured above - * that the subtraction is safe. */ - size_t const padding_idx = rec->data_len - padlen; - size_t const num_checks = rec->data_len <= 256 ? rec->data_len : 256; - size_t const start_idx = rec->data_len - num_checks; - size_t idx; - - for (idx = start_idx; idx < rec->data_len; idx++) { - /* pad_count += (idx >= padding_idx) && - * (check[idx] == padlen - 1); - */ - const size_t mask = mbedtls_ct_size_mask_ge(idx, padding_idx); - const size_t equal = mbedtls_ct_size_bool_eq(check[idx], - padlen - 1); - pad_count += mask & equal; - } - correct &= mbedtls_ct_size_bool_eq(pad_count, padlen); +#if defined(MBEDTLS_SSL_PROTO_TLS1_2) + /* The padding check involves a series of up to 256 + * consecutive memory reads at the end of the record + * plaintext buffer. In order to hide the length and + * validity of the padding, always perform exactly + * `min(256,plaintext_len)` reads (but take into account + * only the last `padlen` bytes for the padding check). */ + size_t pad_count = 0; + volatile unsigned char * const check = data; + + /* Index of first padding byte; it has been ensured above + * that the subtraction is safe. */ + size_t const padding_idx = rec->data_len - padlen; + size_t const num_checks = rec->data_len <= 256 ? rec->data_len : 256; + size_t const start_idx = rec->data_len - num_checks; + size_t idx; + + for (idx = start_idx; idx < rec->data_len; idx++) { + /* pad_count += (idx >= padding_idx) && + * (check[idx] == padlen - 1); + */ + const mbedtls_ct_condition_t a = mbedtls_ct_uint_ge(idx, padding_idx); + size_t increment = mbedtls_ct_size_if_else_0(a, 1); + const mbedtls_ct_condition_t b = mbedtls_ct_uint_eq(check[idx], padlen - 1); + increment = mbedtls_ct_size_if_else_0(b, increment); + pad_count += increment; + } + correct = mbedtls_ct_bool_and(mbedtls_ct_uint_eq(pad_count, padlen), correct); #if defined(MBEDTLS_SSL_DEBUG_ALL) - if (padlen > 0 && correct == 0) { - MBEDTLS_SSL_DEBUG_MSG(1, ("bad padding byte detected")); - } -#endif - padlen &= mbedtls_ct_size_mask(correct); - } else -#endif /* MBEDTLS_SSL_PROTO_TLS1 || MBEDTLS_SSL_PROTO_TLS1_1 || \ - MBEDTLS_SSL_PROTO_TLS1_2 */ - { - MBEDTLS_SSL_DEBUG_MSG(1, ("should never happen")); - return MBEDTLS_ERR_SSL_INTERNAL_ERROR; + if (padlen > 0 && correct == MBEDTLS_CT_FALSE) { + MBEDTLS_SSL_DEBUG_MSG(1, ("bad padding byte detected")); } +#endif + padlen = mbedtls_ct_size_if_else_0(correct, padlen); + +#endif /* MBEDTLS_SSL_PROTO_TLS1_2 */ /* If the padding was found to be invalid, padlen == 0 * and the subtraction is safe. If the padding was found valid, @@ -1564,7 +1997,7 @@ int mbedtls_ssl_decrypt_buf(mbedtls_ssl_context const *ssl, * Authenticate if not done yet. * Compute the MAC regardless of the padding result (RFC4346, CBCTIME). */ -#if defined(MBEDTLS_SSL_SOME_MODES_USE_MAC) +#if defined(MBEDTLS_SSL_SOME_SUITES_USE_MAC) if (auth_done == 0) { unsigned char mac_expect[MBEDTLS_SSL_MAC_ADD] = { 0 }; unsigned char mac_peer[MBEDTLS_SSL_MAC_ADD] = { 0 }; @@ -1587,59 +2020,46 @@ int mbedtls_ssl_decrypt_buf(mbedtls_ssl_context const *ssl, */ rec->data_len -= transform->maclen; ssl_extract_add_data_from_record(add_data, &add_data_len, rec, - transform->minor_ver); - -#if defined(MBEDTLS_SSL_PROTO_SSL3) - if (transform->minor_ver == MBEDTLS_SSL_MINOR_VERSION_0) { - ret = ssl_mac(&transform->md_ctx_dec, - transform->mac_dec, - data, rec->data_len, - rec->ctr, rec->type, - mac_expect); - if (ret != 0) { - MBEDTLS_SSL_DEBUG_RET(1, "ssl_mac", ret); - goto hmac_failed_etm_disabled; - } - memcpy(mac_peer, data + rec->data_len, transform->maclen); - } else -#endif /* MBEDTLS_SSL_PROTO_SSL3 */ -#if defined(MBEDTLS_SSL_PROTO_TLS1) || defined(MBEDTLS_SSL_PROTO_TLS1_1) || \ - defined(MBEDTLS_SSL_PROTO_TLS1_2) - if (transform->minor_ver > MBEDTLS_SSL_MINOR_VERSION_0) { - /* - * The next two sizes are the minimum and maximum values of - * data_len over all padlen values. - * - * They're independent of padlen, since we previously did - * data_len -= padlen. - * - * Note that max_len + maclen is never more than the buffer - * length, as we previously did in_msglen -= maclen too. - */ - const size_t max_len = rec->data_len + padlen; - const size_t min_len = (max_len > 256) ? max_len - 256 : 0; + transform->tls_version, + transform->taglen); - ret = mbedtls_ct_hmac(&transform->md_ctx_dec, - add_data, add_data_len, - data, rec->data_len, min_len, max_len, - mac_expect); - if (ret != 0) { - MBEDTLS_SSL_DEBUG_RET(1, "mbedtls_ct_hmac", ret); - goto hmac_failed_etm_disabled; - } +#if defined(MBEDTLS_SSL_PROTO_TLS1_2) + /* + * The next two sizes are the minimum and maximum values of + * data_len over all padlen values. + * + * They're independent of padlen, since we previously did + * data_len -= padlen. + * + * Note that max_len + maclen is never more than the buffer + * length, as we previously did in_msglen -= maclen too. + */ + const size_t max_len = rec->data_len + padlen; + const size_t min_len = (max_len > 256) ? max_len - 256 : 0; - mbedtls_ct_memcpy_offset(mac_peer, data, - rec->data_len, - min_len, max_len, - transform->maclen); - } else -#endif /* MBEDTLS_SSL_PROTO_TLS1 || MBEDTLS_SSL_PROTO_TLS1_1 || \ - MBEDTLS_SSL_PROTO_TLS1_2 */ - { - MBEDTLS_SSL_DEBUG_MSG(1, ("should never happen")); - return MBEDTLS_ERR_SSL_INTERNAL_ERROR; +#if defined(MBEDTLS_USE_PSA_CRYPTO) + ret = mbedtls_ct_hmac(transform->psa_mac_dec, + transform->psa_mac_alg, + add_data, add_data_len, + data, rec->data_len, min_len, max_len, + mac_expect); +#else + ret = mbedtls_ct_hmac(&transform->md_ctx_dec, + add_data, add_data_len, + data, rec->data_len, min_len, max_len, + mac_expect); +#endif /* MBEDTLS_USE_PSA_CRYPTO */ + if (ret != 0) { + MBEDTLS_SSL_DEBUG_RET(1, "mbedtls_ct_hmac", ret); + goto hmac_failed_etm_disabled; } + mbedtls_ct_memcpy_offset(mac_peer, data, + rec->data_len, + min_len, max_len, + transform->maclen); +#endif /* MBEDTLS_SSL_PROTO_TLS1_2 */ + #if defined(MBEDTLS_SSL_DEBUG_ALL) MBEDTLS_SSL_DEBUG_BUF(4, "expected mac", mac_expect, transform->maclen); MBEDTLS_SSL_DEBUG_BUF(4, "message mac", mac_peer, transform->maclen); @@ -1650,7 +2070,7 @@ int mbedtls_ssl_decrypt_buf(mbedtls_ssl_context const *ssl, #if defined(MBEDTLS_SSL_DEBUG_ALL) MBEDTLS_SSL_DEBUG_MSG(1, ("message mac does not match")); #endif - correct = 0; + correct = MBEDTLS_CT_FALSE; } auth_done++; @@ -1665,10 +2085,10 @@ int mbedtls_ssl_decrypt_buf(mbedtls_ssl_context const *ssl, /* * Finally check the correct flag */ - if (correct == 0) { + if (correct == MBEDTLS_CT_FALSE) { return MBEDTLS_ERR_SSL_INVALID_MAC; } -#endif /* MBEDTLS_SSL_SOME_MODES_USE_MAC */ +#endif /* MBEDTLS_SSL_SOME_SUITES_USE_MAC */ /* Make extra sure authentication was performed, exactly once */ if (auth_done != 1) { @@ -1676,8 +2096,8 @@ int mbedtls_ssl_decrypt_buf(mbedtls_ssl_context const *ssl, return MBEDTLS_ERR_SSL_INTERNAL_ERROR; } -#if defined(MBEDTLS_SSL_PROTO_TLS1_3_EXPERIMENTAL) - if (transform->minor_ver == MBEDTLS_SSL_MINOR_VERSION_4) { +#if defined(MBEDTLS_SSL_PROTO_TLS1_3) + if (transform->tls_version == MBEDTLS_SSL_VERSION_TLS1_3) { /* Remove inner padding and infer true content type. */ ret = ssl_parse_inner_plaintext(data, &rec->data_len, &rec->type); @@ -1686,7 +2106,7 @@ int mbedtls_ssl_decrypt_buf(mbedtls_ssl_context const *ssl, return MBEDTLS_ERR_SSL_INVALID_RECORD; } } -#endif /* MBEDTLS_SSL_PROTO_TLS1_3_EXPERIMENTAL */ +#endif /* MBEDTLS_SSL_PROTO_TLS1_3 */ #if defined(MBEDTLS_SSL_DTLS_CONNECTION_ID) if (rec->cid_len != 0) { @@ -1707,164 +2127,53 @@ int mbedtls_ssl_decrypt_buf(mbedtls_ssl_context const *ssl, #undef MAC_PLAINTEXT #undef MAC_CIPHERTEXT -#if defined(MBEDTLS_ZLIB_SUPPORT) /* - * Compression/decompression functions + * Fill the input message buffer by appending data to it. + * The amount of data already fetched is in ssl->in_left. + * + * If we return 0, is it guaranteed that (at least) nb_want bytes are + * available (from this read and/or a previous one). Otherwise, an error code + * is returned (possibly EOF or WANT_READ). + * + * With stream transport (TLS) on success ssl->in_left == nb_want, but + * with datagram transport (DTLS) on success ssl->in_left >= nb_want, + * since we always read a whole datagram at once. + * + * For DTLS, it is up to the caller to set ssl->next_record_offset when + * they're done reading a record. */ -MBEDTLS_CHECK_RETURN_CRITICAL -static int ssl_compress_buf(mbedtls_ssl_context *ssl) +int mbedtls_ssl_fetch_input(mbedtls_ssl_context *ssl, size_t nb_want) { int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED; - unsigned char *msg_post = ssl->out_msg; - ptrdiff_t bytes_written = ssl->out_msg - ssl->out_buf; - size_t len_pre = ssl->out_msglen; - unsigned char *msg_pre = ssl->compress_buf; + size_t len; #if defined(MBEDTLS_SSL_VARIABLE_BUFFER_LENGTH) - size_t out_buf_len = ssl->out_buf_len; + size_t in_buf_len = ssl->in_buf_len; #else - size_t out_buf_len = MBEDTLS_SSL_OUT_BUFFER_LEN; + size_t in_buf_len = MBEDTLS_SSL_IN_BUFFER_LEN; #endif - MBEDTLS_SSL_DEBUG_MSG(2, ("=> compress buf")); + MBEDTLS_SSL_DEBUG_MSG(2, ("=> fetch input")); - if (len_pre == 0) { - return 0; + if (ssl->f_recv == NULL && ssl->f_recv_timeout == NULL) { + MBEDTLS_SSL_DEBUG_MSG(1, ("Bad usage of mbedtls_ssl_set_bio() ")); + return MBEDTLS_ERR_SSL_BAD_INPUT_DATA; } - memcpy(msg_pre, ssl->out_msg, len_pre); - - MBEDTLS_SSL_DEBUG_MSG(3, ("before compression: msglen = %" MBEDTLS_PRINTF_SIZET ", ", - ssl->out_msglen)); - - MBEDTLS_SSL_DEBUG_BUF(4, "before compression: output payload", - ssl->out_msg, ssl->out_msglen); - - ssl->transform_out->ctx_deflate.next_in = msg_pre; - ssl->transform_out->ctx_deflate.avail_in = len_pre; - ssl->transform_out->ctx_deflate.next_out = msg_post; - ssl->transform_out->ctx_deflate.avail_out = out_buf_len - bytes_written; - - ret = deflate(&ssl->transform_out->ctx_deflate, Z_SYNC_FLUSH); - if (ret != Z_OK) { - MBEDTLS_SSL_DEBUG_MSG(1, ("failed to perform compression (%d)", ret)); - return MBEDTLS_ERR_SSL_COMPRESSION_FAILED; + if (nb_want > in_buf_len - (size_t) (ssl->in_hdr - ssl->in_buf)) { + MBEDTLS_SSL_DEBUG_MSG(1, ("requesting more data than fits")); + return MBEDTLS_ERR_SSL_BAD_INPUT_DATA; } - ssl->out_msglen = out_buf_len - - ssl->transform_out->ctx_deflate.avail_out - bytes_written; - - MBEDTLS_SSL_DEBUG_MSG(3, ("after compression: msglen = %" MBEDTLS_PRINTF_SIZET ", ", - ssl->out_msglen)); - - MBEDTLS_SSL_DEBUG_BUF(4, "after compression: output payload", - ssl->out_msg, ssl->out_msglen); - - MBEDTLS_SSL_DEBUG_MSG(2, ("<= compress buf")); +#if defined(MBEDTLS_SSL_PROTO_DTLS) + if (ssl->conf->transport == MBEDTLS_SSL_TRANSPORT_DATAGRAM) { + uint32_t timeout; - return 0; -} - -MBEDTLS_CHECK_RETURN_CRITICAL -static int ssl_decompress_buf(mbedtls_ssl_context *ssl) -{ - int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED; - unsigned char *msg_post = ssl->in_msg; - ptrdiff_t header_bytes = ssl->in_msg - ssl->in_buf; - size_t len_pre = ssl->in_msglen; - unsigned char *msg_pre = ssl->compress_buf; -#if defined(MBEDTLS_SSL_VARIABLE_BUFFER_LENGTH) - size_t in_buf_len = ssl->in_buf_len; -#else - size_t in_buf_len = MBEDTLS_SSL_IN_BUFFER_LEN; -#endif - - MBEDTLS_SSL_DEBUG_MSG(2, ("=> decompress buf")); - - if (len_pre == 0) { - return 0; - } - - memcpy(msg_pre, ssl->in_msg, len_pre); - - MBEDTLS_SSL_DEBUG_MSG(3, ("before decompression: msglen = %" MBEDTLS_PRINTF_SIZET ", ", - ssl->in_msglen)); - - MBEDTLS_SSL_DEBUG_BUF(4, "before decompression: input payload", - ssl->in_msg, ssl->in_msglen); - - ssl->transform_in->ctx_inflate.next_in = msg_pre; - ssl->transform_in->ctx_inflate.avail_in = len_pre; - ssl->transform_in->ctx_inflate.next_out = msg_post; - ssl->transform_in->ctx_inflate.avail_out = in_buf_len - header_bytes; - - ret = inflate(&ssl->transform_in->ctx_inflate, Z_SYNC_FLUSH); - if (ret != Z_OK) { - MBEDTLS_SSL_DEBUG_MSG(1, ("failed to perform decompression (%d)", ret)); - return MBEDTLS_ERR_SSL_COMPRESSION_FAILED; - } - - ssl->in_msglen = in_buf_len - - ssl->transform_in->ctx_inflate.avail_out - header_bytes; - - MBEDTLS_SSL_DEBUG_MSG(3, ("after decompression: msglen = %" MBEDTLS_PRINTF_SIZET ", ", - ssl->in_msglen)); - - MBEDTLS_SSL_DEBUG_BUF(4, "after decompression: input payload", - ssl->in_msg, ssl->in_msglen); - - MBEDTLS_SSL_DEBUG_MSG(2, ("<= decompress buf")); - - return 0; -} -#endif /* MBEDTLS_ZLIB_SUPPORT */ - -/* - * Fill the input message buffer by appending data to it. - * The amount of data already fetched is in ssl->in_left. - * - * If we return 0, is it guaranteed that (at least) nb_want bytes are - * available (from this read and/or a previous one). Otherwise, an error code - * is returned (possibly EOF or WANT_READ). - * - * With stream transport (TLS) on success ssl->in_left == nb_want, but - * with datagram transport (DTLS) on success ssl->in_left >= nb_want, - * since we always read a whole datagram at once. - * - * For DTLS, it is up to the caller to set ssl->next_record_offset when - * they're done reading a record. - */ -int mbedtls_ssl_fetch_input(mbedtls_ssl_context *ssl, size_t nb_want) -{ - int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED; - size_t len; -#if defined(MBEDTLS_SSL_VARIABLE_BUFFER_LENGTH) - size_t in_buf_len = ssl->in_buf_len; -#else - size_t in_buf_len = MBEDTLS_SSL_IN_BUFFER_LEN; -#endif - - MBEDTLS_SSL_DEBUG_MSG(2, ("=> fetch input")); - - if (ssl->f_recv == NULL && ssl->f_recv_timeout == NULL) { - MBEDTLS_SSL_DEBUG_MSG(1, ("Bad usage of mbedtls_ssl_set_bio() ")); - return MBEDTLS_ERR_SSL_BAD_INPUT_DATA; - } - - if (nb_want > in_buf_len - (size_t) (ssl->in_hdr - ssl->in_buf)) { - MBEDTLS_SSL_DEBUG_MSG(1, ("requesting more data than fits")); - return MBEDTLS_ERR_SSL_BAD_INPUT_DATA; - } - -#if defined(MBEDTLS_SSL_PROTO_DTLS) - if (ssl->conf->transport == MBEDTLS_SSL_TRANSPORT_DATAGRAM) { - uint32_t timeout; - - /* - * The point is, we need to always read a full datagram at once, so we - * sometimes read more then requested, and handle the additional data. - * It could be the rest of the current record (while fetching the - * header) and/or some other records in the same datagram. - */ + /* + * The point is, we need to always read a full datagram at once, so we + * sometimes read more then requested, and handle the additional data. + * It could be the rest of the current record (while fetching the + * header) and/or some other records in the same datagram. + */ /* * Move to the next record in the already read datagram if applicable @@ -1920,9 +2229,9 @@ int mbedtls_ssl_fetch_input(mbedtls_ssl_context *ssl, size_t nb_want) MBEDTLS_SSL_DEBUG_MSG(2, ("timer has expired")); ret = MBEDTLS_ERR_SSL_TIMEOUT; } else { - len = in_buf_len - (ssl->in_hdr - ssl->in_buf); + len = in_buf_len - (size_t) (ssl->in_hdr - ssl->in_buf); - if (ssl->state != MBEDTLS_SSL_HANDSHAKE_OVER) { + if (mbedtls_ssl_is_handshake_over(ssl) == 0) { timeout = ssl->handshake->retransmit_timeout; } else { timeout = ssl->conf->read_timeout; @@ -2016,7 +2325,7 @@ int mbedtls_ssl_fetch_input(mbedtls_ssl_context *ssl, size_t nb_want) return ret; } - if ((size_t) ret > len || (INT_MAX > SIZE_MAX && ret > (int) SIZE_MAX)) { + if ((size_t) ret > len) { MBEDTLS_SSL_DEBUG_MSG(1, ("f_recv returned %d bytes but only %" MBEDTLS_PRINTF_SIZET " were requested", @@ -2068,7 +2377,7 @@ int mbedtls_ssl_flush_output(mbedtls_ssl_context *ssl) return ret; } - if ((size_t) ret > ssl->out_left || (INT_MAX > SIZE_MAX && ret > (int) SIZE_MAX)) { + if ((size_t) ret > ssl->out_left) { MBEDTLS_SSL_DEBUG_MSG(1, ("f_send returned %d bytes but only %" MBEDTLS_PRINTF_SIZET " bytes were sent", @@ -2169,7 +2478,7 @@ MBEDTLS_CHECK_RETURN_CRITICAL static int ssl_swap_epochs(mbedtls_ssl_context *ssl) { mbedtls_ssl_transform *tmp_transform; - unsigned char tmp_out_ctr[8]; + unsigned char tmp_out_ctr[MBEDTLS_SSL_SEQUENCE_NUMBER_LEN]; if (ssl->transform_out == ssl->handshake->alt_transform_out) { MBEDTLS_SSL_DEBUG_MSG(3, ("skip swap epochs")); @@ -2184,23 +2493,15 @@ static int ssl_swap_epochs(mbedtls_ssl_context *ssl) ssl->handshake->alt_transform_out = tmp_transform; /* Swap epoch + sequence_number */ - memcpy(tmp_out_ctr, ssl->cur_out_ctr, 8); - memcpy(ssl->cur_out_ctr, ssl->handshake->alt_out_ctr, 8); - memcpy(ssl->handshake->alt_out_ctr, tmp_out_ctr, 8); + memcpy(tmp_out_ctr, ssl->cur_out_ctr, sizeof(tmp_out_ctr)); + memcpy(ssl->cur_out_ctr, ssl->handshake->alt_out_ctr, + sizeof(ssl->cur_out_ctr)); + memcpy(ssl->handshake->alt_out_ctr, tmp_out_ctr, + sizeof(ssl->handshake->alt_out_ctr)); /* Adjust to the newly activated transform */ mbedtls_ssl_update_out_pointers(ssl, ssl->transform_out); -#if defined(MBEDTLS_SSL_HW_RECORD_ACCEL) - if (mbedtls_ssl_hw_record_activate != NULL) { - int ret = mbedtls_ssl_hw_record_activate(ssl, MBEDTLS_SSL_CHANNEL_OUTBOUND); - if (ret != 0) { - MBEDTLS_SSL_DEBUG_RET(1, "mbedtls_ssl_hw_record_activate", ret); - return MBEDTLS_ERR_SSL_HW_ACCEL_FAILED; - } - } -#endif - return 0; } @@ -2253,8 +2554,8 @@ int mbedtls_ssl_flight_transmit(mbedtls_ssl_context *ssl) (cur->type == MBEDTLS_SSL_MSG_HANDSHAKE && cur->p[0] == MBEDTLS_SSL_HS_FINISHED); - uint8_t const force_flush = ssl->disable_datagram_packing == 1 ? - SSL_FORCE_FLUSH : SSL_DONT_FORCE_FLUSH; + int const force_flush = ssl->disable_datagram_packing == 1 ? + SSL_FORCE_FLUSH : SSL_DONT_FORCE_FLUSH; /* Swap epochs before sending Finished: we can't do it after * sending ChangeCipherSpec, in case write returns WANT_READ. @@ -2292,7 +2593,7 @@ int mbedtls_ssl_flight_transmit(mbedtls_ssl_context *ssl) } else { const unsigned char * const p = ssl->handshake->cur_msg_p; const size_t hs_len = cur->len - 12; - const size_t frag_off = p - (cur->p + 12); + const size_t frag_off = (size_t) (p - (cur->p + 12)); const size_t rem_len = hs_len - frag_off; size_t cur_hs_frag_len, max_hs_frag_len; @@ -2368,7 +2669,7 @@ int mbedtls_ssl_flight_transmit(mbedtls_ssl_context *ssl) } /* Update state and set timer */ - if (ssl->state == MBEDTLS_SSL_HANDSHAKE_OVER) { + if (mbedtls_ssl_is_handshake_over(ssl) == 1) { ssl->handshake->retransmit_state = MBEDTLS_SSL_RETRANS_FINISHED; } else { ssl->handshake->retransmit_state = MBEDTLS_SSL_RETRANS_WAITING; @@ -2430,6 +2731,24 @@ void mbedtls_ssl_send_flight_completed(mbedtls_ssl_context *ssl) /* * Handshake layer functions */ +int mbedtls_ssl_start_handshake_msg(mbedtls_ssl_context *ssl, unsigned char hs_type, + unsigned char **buf, size_t *buf_len) +{ + /* + * Reserve 4 bytes for handshake header. ( Section 4,RFC 8446 ) + * ... + * HandshakeType msg_type; + * uint24 length; + * ... + */ + *buf = ssl->out_msg + 4; + *buf_len = MBEDTLS_SSL_OUT_CONTENT_LEN - 4; + + ssl->out_msgtype = MBEDTLS_SSL_MSG_HANDSHAKE; + ssl->out_msg[0] = hs_type; + + return 0; +} /* * Write (DTLS: or queue) current handshake (including CCS) message. @@ -2453,7 +2772,9 @@ void mbedtls_ssl_send_flight_completed(mbedtls_ssl_context *ssl) * (including handshake headers but excluding record headers) * - ssl->out_msg: the record contents (handshake headers + content) */ -int mbedtls_ssl_write_handshake_msg(mbedtls_ssl_context *ssl) +int mbedtls_ssl_write_handshake_msg_ext(mbedtls_ssl_context *ssl, + int update_checksum, + int force_flush) { int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED; const size_t hs_len = ssl->out_msglen - 4; @@ -2466,16 +2787,8 @@ int mbedtls_ssl_write_handshake_msg(mbedtls_ssl_context *ssl) */ if (ssl->out_msgtype != MBEDTLS_SSL_MSG_HANDSHAKE && ssl->out_msgtype != MBEDTLS_SSL_MSG_CHANGE_CIPHER_SPEC) { - /* In SSLv3, the client might send a NoCertificate alert. */ -#if defined(MBEDTLS_SSL_PROTO_SSL3) && defined(MBEDTLS_SSL_CLI_C) - if (!(ssl->minor_ver == MBEDTLS_SSL_MINOR_VERSION_0 && - ssl->out_msgtype == MBEDTLS_SSL_MSG_ALERT && - ssl->conf->endpoint == MBEDTLS_SSL_IS_CLIENT)) -#endif /* MBEDTLS_SSL_PROTO_SSL3 && MBEDTLS_SSL_SRV_C */ - { - MBEDTLS_SSL_DEBUG_MSG(1, ("should never happen")); - return MBEDTLS_ERR_SSL_INTERNAL_ERROR; - } + MBEDTLS_SSL_DEBUG_MSG(1, ("should never happen")); + return MBEDTLS_ERR_SSL_INTERNAL_ERROR; } /* Whenever we send anything different from a @@ -2560,8 +2873,13 @@ int mbedtls_ssl_write_handshake_msg(mbedtls_ssl_context *ssl) #endif /* MBEDTLS_SSL_PROTO_DTLS */ /* Update running hashes of handshake messages seen */ - if (hs_type != MBEDTLS_SSL_HS_HELLO_REQUEST) { - ssl->handshake->update_checksum(ssl, ssl->out_msg, ssl->out_msglen); + if (hs_type != MBEDTLS_SSL_HS_HELLO_REQUEST && update_checksum != 0) { + ret = ssl->handshake->update_checksum(ssl, ssl->out_msg, + ssl->out_msglen); + if (ret != 0) { + MBEDTLS_SSL_DEBUG_RET(1, "update_checksum", ret); + return ret; + } } } @@ -2577,7 +2895,7 @@ int mbedtls_ssl_write_handshake_msg(mbedtls_ssl_context *ssl) } else #endif { - if ((ret = mbedtls_ssl_write_record(ssl, SSL_FORCE_FLUSH)) != 0) { + if ((ret = mbedtls_ssl_write_record(ssl, force_flush)) != 0) { MBEDTLS_SSL_DEBUG_RET(1, "ssl_write_record", ret); return ret; } @@ -2588,6 +2906,22 @@ int mbedtls_ssl_write_handshake_msg(mbedtls_ssl_context *ssl) return 0; } +int mbedtls_ssl_finish_handshake_msg(mbedtls_ssl_context *ssl, + size_t buf_len, size_t msg_len) +{ + int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED; + size_t msg_with_header_len; + ((void) buf_len); + + /* Add reserved 4 bytes for handshake header */ + msg_with_header_len = msg_len + 4; + ssl->out_msglen = msg_with_header_len; + MBEDTLS_SSL_PROC_CHK(mbedtls_ssl_write_handshake_msg_ext(ssl, 0, 0)); + +cleanup: + return ret; +} + /* * Record layer functions */ @@ -2600,41 +2934,14 @@ int mbedtls_ssl_write_handshake_msg(mbedtls_ssl_context *ssl) * - ssl->out_msglen: length of the record content (excl headers) * - ssl->out_msg: record content */ -int mbedtls_ssl_write_record(mbedtls_ssl_context *ssl, uint8_t force_flush) +int mbedtls_ssl_write_record(mbedtls_ssl_context *ssl, int force_flush) { int ret, done = 0; size_t len = ssl->out_msglen; - uint8_t flush = force_flush; + int flush = force_flush; MBEDTLS_SSL_DEBUG_MSG(2, ("=> write record")); -#if defined(MBEDTLS_ZLIB_SUPPORT) - if (ssl->transform_out != NULL && - ssl->session_out->compression == MBEDTLS_SSL_COMPRESS_DEFLATE) { - if ((ret = ssl_compress_buf(ssl)) != 0) { - MBEDTLS_SSL_DEBUG_RET(1, "ssl_compress_buf", ret); - return ret; - } - - len = ssl->out_msglen; - } -#endif /*MBEDTLS_ZLIB_SUPPORT */ - -#if defined(MBEDTLS_SSL_HW_RECORD_ACCEL) - if (mbedtls_ssl_hw_record_write != NULL) { - MBEDTLS_SSL_DEBUG_MSG(2, ("going for mbedtls_ssl_hw_record_write()")); - - ret = mbedtls_ssl_hw_record_write(ssl); - if (ret != 0 && ret != MBEDTLS_ERR_SSL_HW_ACCEL_FALLTHROUGH) { - MBEDTLS_SSL_DEBUG_RET(1, "mbedtls_ssl_hw_record_write", ret); - return MBEDTLS_ERR_SSL_HW_ACCEL_FAILED; - } - - if (ret == 0) { - done = 1; - } - } -#endif /* MBEDTLS_SSL_HW_RECORD_ACCEL */ if (!done) { unsigned i; size_t protected_record_size; @@ -2645,24 +2952,30 @@ int mbedtls_ssl_write_record(mbedtls_ssl_context *ssl, uint8_t force_flush) #endif /* Skip writing the record content type to after the encryption, * as it may change when using the CID extension. */ - - mbedtls_ssl_write_version(ssl->major_ver, ssl->minor_ver, - ssl->conf->transport, ssl->out_hdr + 1); - - memcpy(ssl->out_ctr, ssl->cur_out_ctr, 8); + mbedtls_ssl_protocol_version tls_ver = ssl->tls_version; +#if defined(MBEDTLS_SSL_PROTO_TLS1_3) + /* TLS 1.3 still uses the TLS 1.2 version identifier + * for backwards compatibility. */ + if (tls_ver == MBEDTLS_SSL_VERSION_TLS1_3) { + tls_ver = MBEDTLS_SSL_VERSION_TLS1_2; + } +#endif /* MBEDTLS_SSL_PROTO_TLS1_3 */ + mbedtls_ssl_write_version(ssl->out_hdr + 1, ssl->conf->transport, + tls_ver); + + memcpy(ssl->out_ctr, ssl->cur_out_ctr, MBEDTLS_SSL_SEQUENCE_NUMBER_LEN); MBEDTLS_PUT_UINT16_BE(len, ssl->out_len, 0); if (ssl->transform_out != NULL) { mbedtls_record rec; rec.buf = ssl->out_iv; - rec.buf_len = out_buf_len - (ssl->out_iv - ssl->out_buf); + rec.buf_len = out_buf_len - (size_t) (ssl->out_iv - ssl->out_buf); rec.data_len = ssl->out_msglen; - rec.data_offset = ssl->out_msg - rec.buf; + rec.data_offset = (size_t) (ssl->out_msg - rec.buf); - memcpy(&rec.ctr[0], ssl->out_ctr, 8); - mbedtls_ssl_write_version(ssl->major_ver, ssl->minor_ver, - ssl->conf->transport, rec.ver); + memcpy(&rec.ctr[0], ssl->out_ctr, sizeof(rec.ctr)); + mbedtls_ssl_write_version(rec.ver, ssl->conf->transport, tls_ver); rec.type = ssl->out_msgtype; #if defined(MBEDTLS_SSL_DTLS_CONNECTION_ID) @@ -2729,7 +3042,7 @@ int mbedtls_ssl_write_record(mbedtls_ssl_context *ssl, uint8_t force_flush) } } - /* The loop goes to its end iff the counter is wrapping */ + /* The loop goes to its end if the counter is wrapping */ if (i == mbedtls_ssl_ep_len(ssl)) { MBEDTLS_SSL_DEBUG_MSG(1, ("outgoing message counter would wrap")); return MBEDTLS_ERR_SSL_COUNTER_WRAPPING; @@ -2784,16 +3097,12 @@ static int ssl_hs_is_proper_fragment(mbedtls_ssl_context *ssl) static uint32_t ssl_get_hs_frag_len(mbedtls_ssl_context const *ssl) { - return (ssl->in_msg[9] << 16) | - (ssl->in_msg[10] << 8) | - ssl->in_msg[11]; + return MBEDTLS_GET_UINT24_BE(ssl->in_msg, 9); } static uint32_t ssl_get_hs_frag_off(mbedtls_ssl_context const *ssl) { - return (ssl->in_msg[6] << 16) | - (ssl->in_msg[7] << 8) | - ssl->in_msg[8]; + return MBEDTLS_GET_UINT24_BE(ssl->in_msg, 6); } MBEDTLS_CHECK_RETURN_CRITICAL @@ -2906,9 +3215,7 @@ static size_t ssl_get_reassembly_buffer_size(size_t msg_len, static uint32_t ssl_get_hs_total_len(mbedtls_ssl_context const *ssl) { - return (ssl->in_msg[1] << 16) | - (ssl->in_msg[2] << 8) | - ssl->in_msg[3]; + return MBEDTLS_GET_UINT24_BE(ssl->in_msg, 1); } int mbedtls_ssl_prepare_handshake_record(mbedtls_ssl_context *ssl) @@ -2929,7 +3236,7 @@ int mbedtls_ssl_prepare_handshake_record(mbedtls_ssl_context *ssl) #if defined(MBEDTLS_SSL_PROTO_DTLS) if (ssl->conf->transport == MBEDTLS_SSL_TRANSPORT_DATAGRAM) { int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED; - unsigned int recv_msg_seq = (ssl->in_msg[4] << 8) | ssl->in_msg[5]; + unsigned int recv_msg_seq = MBEDTLS_GET_UINT16_BE(ssl->in_msg, 4); if (ssl_check_hs_header(ssl) != 0) { MBEDTLS_SSL_DEBUG_MSG(1, ("invalid handshake header")); @@ -2937,9 +3244,9 @@ int mbedtls_ssl_prepare_handshake_record(mbedtls_ssl_context *ssl) } if (ssl->handshake != NULL && - ((ssl->state != MBEDTLS_SSL_HANDSHAKE_OVER && + ((mbedtls_ssl_is_handshake_over(ssl) == 0 && recv_msg_seq != ssl->handshake->in_msg_seq) || - (ssl->state == MBEDTLS_SSL_HANDSHAKE_OVER && + (mbedtls_ssl_is_handshake_over(ssl) == 1 && ssl->in_msg[0] != MBEDTLS_SSL_HS_CLIENT_HELLO))) { if (recv_msg_seq > ssl->handshake->in_msg_seq) { MBEDTLS_SSL_DEBUG_MSG(2, @@ -2994,12 +3301,17 @@ int mbedtls_ssl_prepare_handshake_record(mbedtls_ssl_context *ssl) return 0; } -void mbedtls_ssl_update_handshake_status(mbedtls_ssl_context *ssl) +int mbedtls_ssl_update_handshake_status(mbedtls_ssl_context *ssl) { + int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED; mbedtls_ssl_handshake_params * const hs = ssl->handshake; - if (ssl->state != MBEDTLS_SSL_HANDSHAKE_OVER && hs != NULL) { - ssl->handshake->update_checksum(ssl, ssl->in_msg, ssl->in_hslen); + if (mbedtls_ssl_is_handshake_over(ssl) == 0 && hs != NULL) { + ret = ssl->handshake->update_checksum(ssl, ssl->in_msg, ssl->in_hslen); + if (ret != 0) { + MBEDTLS_SSL_DEBUG_RET(1, "update_checksum", ret); + return ret; + } } /* Handshake message is complete, increment counter */ @@ -3030,6 +3342,7 @@ void mbedtls_ssl_update_handshake_status(mbedtls_ssl_context *ssl) memset(hs_buf, 0, sizeof(mbedtls_ssl_hs_buffer)); } #endif + return 0; } /* @@ -3162,7 +3475,7 @@ int mbedtls_ssl_check_dtls_clihlo_cookie( const unsigned char *in, size_t in_len, unsigned char *obuf, size_t buf_len, size_t *olen) { - size_t sid_len, cookie_len; + size_t sid_len, cookie_len, epoch, fragment_offset; unsigned char *p; /* @@ -3196,17 +3509,19 @@ int mbedtls_ssl_check_dtls_clihlo_cookie( MBEDTLS_SSL_DEBUG_BUF(4, "cli_id", cli_id, cli_id_len); if (in_len < 61) { MBEDTLS_SSL_DEBUG_MSG(4, ("check cookie: record too short")); - return MBEDTLS_ERR_SSL_BAD_HS_CLIENT_HELLO; + return MBEDTLS_ERR_SSL_DECODE_ERROR; } - if (in[0] != MBEDTLS_SSL_MSG_HANDSHAKE || - in[3] != 0 || in[4] != 0 || - in[19] != 0 || in[20] != 0 || in[21] != 0) { + + epoch = MBEDTLS_GET_UINT16_BE(in, 3); + fragment_offset = MBEDTLS_GET_UINT24_BE(in, 19); + + if (in[0] != MBEDTLS_SSL_MSG_HANDSHAKE || epoch != 0 || + fragment_offset != 0) { MBEDTLS_SSL_DEBUG_MSG(4, ("check cookie: not a good ClientHello")); MBEDTLS_SSL_DEBUG_MSG(4, (" type=%u epoch=%u fragment_offset=%u", - in[0], - (unsigned) in[3] << 8 | in[4], - (unsigned) in[19] << 16 | in[20] << 8 | in[21])); - return MBEDTLS_ERR_SSL_BAD_HS_CLIENT_HELLO; + in[0], (unsigned) epoch, + (unsigned) fragment_offset)); + return MBEDTLS_ERR_SSL_DECODE_ERROR; } sid_len = in[59]; @@ -3214,7 +3529,7 @@ int mbedtls_ssl_check_dtls_clihlo_cookie( MBEDTLS_SSL_DEBUG_MSG(4, ("check cookie: sid_len=%u > %u", (unsigned) sid_len, (unsigned) in_len - 61)); - return MBEDTLS_ERR_SSL_BAD_HS_CLIENT_HELLO; + return MBEDTLS_ERR_SSL_DECODE_ERROR; } MBEDTLS_SSL_DEBUG_BUF(4, "sid received from network", in + 60, sid_len); @@ -3224,7 +3539,7 @@ int mbedtls_ssl_check_dtls_clihlo_cookie( MBEDTLS_SSL_DEBUG_MSG(4, ("check cookie: cookie_len=%u > %u", (unsigned) cookie_len, (unsigned) (in_len - sid_len - 61))); - return MBEDTLS_ERR_SSL_BAD_HS_CLIENT_HELLO; + return MBEDTLS_ERR_SSL_DECODE_ERROR; } MBEDTLS_SSL_DEBUG_BUF(4, "cookie received from network", @@ -3274,7 +3589,7 @@ int mbedtls_ssl_check_dtls_clihlo_cookie( return MBEDTLS_ERR_SSL_INTERNAL_ERROR; } - *olen = p - obuf; + *olen = (size_t) (p - obuf); /* Go back and fill length fields */ obuf[27] = (unsigned char) (*olen - 28); @@ -3312,7 +3627,7 @@ MBEDTLS_CHECK_RETURN_CRITICAL static int ssl_handle_possible_reconnect(mbedtls_ssl_context *ssl) { int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED; - size_t len; + size_t len = 0; if (ssl->conf->f_cookie_write == NULL || ssl->conf->f_cookie_check == NULL) { @@ -3398,7 +3713,7 @@ static int ssl_parse_record_header(mbedtls_ssl_context const *ssl, size_t len, mbedtls_record *rec) { - int major_ver, minor_ver; + mbedtls_ssl_protocol_version tls_version; size_t const rec_hdr_type_offset = 0; size_t const rec_hdr_type_len = 1; @@ -3460,7 +3775,7 @@ static int ssl_parse_record_header(mbedtls_ssl_context const *ssl, rec->type == MBEDTLS_SSL_MSG_CID) { /* Shift pointers to account for record header including CID * struct { - * ContentType special_type = tls12_cid; + * ContentType outer_type = tls12_cid; * ProtocolVersion version; * uint16 epoch; * uint48 sequence_number; @@ -3504,21 +3819,15 @@ static int ssl_parse_record_header(mbedtls_ssl_context const *ssl, */ rec->ver[0] = buf[rec_hdr_version_offset + 0]; rec->ver[1] = buf[rec_hdr_version_offset + 1]; - mbedtls_ssl_read_version(&major_ver, &minor_ver, - ssl->conf->transport, - &rec->ver[0]); - - if (major_ver != ssl->major_ver) { - MBEDTLS_SSL_DEBUG_MSG(1, ("major version mismatch: got %u, expected %u", - (unsigned) major_ver, - (unsigned) ssl->major_ver)); - return MBEDTLS_ERR_SSL_INVALID_RECORD; - } + tls_version = (mbedtls_ssl_protocol_version) mbedtls_ssl_read_version( + buf + rec_hdr_version_offset, + ssl->conf->transport); + + if (tls_version > ssl->conf->max_tls_version) { + MBEDTLS_SSL_DEBUG_MSG(1, ("TLS version mismatch: got %u, expected max %u", + (unsigned) tls_version, + (unsigned) ssl->conf->max_tls_version)); - if (minor_ver > ssl->conf->max_minor_ver) { - MBEDTLS_SSL_DEBUG_MSG(1, ("minor version mismatch: got %u, expected max %u", - (unsigned) minor_ver, - (unsigned) ssl->conf->max_minor_ver)); return MBEDTLS_ERR_SSL_INVALID_RECORD; } /* @@ -3542,14 +3851,12 @@ static int ssl_parse_record_header(mbedtls_ssl_context const *ssl, */ rec->data_offset = rec_hdr_len_offset + rec_hdr_len_len; - rec->data_len = ((size_t) buf[rec_hdr_len_offset + 0] << 8) | - ((size_t) buf[rec_hdr_len_offset + 1] << 0); + rec->data_len = MBEDTLS_GET_UINT16_BE(buf, rec_hdr_len_offset); MBEDTLS_SSL_DEBUG_BUF(4, "input record header", buf, rec->data_offset); MBEDTLS_SSL_DEBUG_MSG(3, ("input record: msgtype = %u, " - "version = [%d:%d], msglen = %" MBEDTLS_PRINTF_SIZET, - rec->type, - major_ver, minor_ver, rec->data_len)); + "version = [0x%x], msglen = %" MBEDTLS_PRINTF_SIZET, + rec->type, (unsigned) tls_version, rec->data_len)); rec->buf = buf; rec->buf_len = rec->data_offset + rec->data_len; @@ -3572,7 +3879,7 @@ static int ssl_parse_record_header(mbedtls_ssl_context const *ssl, */ #if defined(MBEDTLS_SSL_PROTO_DTLS) if (ssl->conf->transport == MBEDTLS_SSL_TRANSPORT_DATAGRAM) { - rec_epoch = (rec->ctr[0] << 8) | rec->ctr[1]; + rec_epoch = MBEDTLS_GET_UINT16_BE(rec->ctr, 0); /* Check that the datagram is large enough to contain a record * of the advertised length. */ @@ -3622,7 +3929,7 @@ static int ssl_parse_record_header(mbedtls_ssl_context const *ssl, MBEDTLS_CHECK_RETURN_CRITICAL static int ssl_check_client_reconnect(mbedtls_ssl_context *ssl) { - unsigned int rec_epoch = (ssl->in_ctr[0] << 8) | ssl->in_ctr[1]; + unsigned int rec_epoch = MBEDTLS_GET_UINT16_BE(ssl->in_ctr, 0); /* * Check for an epoch 0 ClientHello. We can't use in_msg here to @@ -3632,7 +3939,7 @@ static int ssl_check_client_reconnect(mbedtls_ssl_context *ssl) */ if (rec_epoch == 0 && ssl->conf->endpoint == MBEDTLS_SSL_IS_SERVER && - ssl->state == MBEDTLS_SSL_HANDSHAKE_OVER && + mbedtls_ssl_is_handshake_over(ssl) == 1 && ssl->in_msgtype == MBEDTLS_SSL_MSG_HANDSHAKE && ssl->in_left > 13 && ssl->in_buf[13] == MBEDTLS_SSL_HS_CLIENT_HELLO) { @@ -3657,21 +3964,20 @@ static int ssl_prepare_record_content(mbedtls_ssl_context *ssl, MBEDTLS_SSL_DEBUG_BUF(4, "input record from network", rec->buf, rec->buf_len); -#if defined(MBEDTLS_SSL_HW_RECORD_ACCEL) - if (mbedtls_ssl_hw_record_read != NULL) { - MBEDTLS_SSL_DEBUG_MSG(2, ("going for mbedtls_ssl_hw_record_read()")); - - ret = mbedtls_ssl_hw_record_read(ssl); - if (ret != 0 && ret != MBEDTLS_ERR_SSL_HW_ACCEL_FALLTHROUGH) { - MBEDTLS_SSL_DEBUG_RET(1, "mbedtls_ssl_hw_record_read", ret); - return MBEDTLS_ERR_SSL_HW_ACCEL_FAILED; - } - - if (ret == 0) { + /* + * In TLS 1.3, always treat ChangeCipherSpec records + * as unencrypted. The only thing we do with them is + * check the length and content and ignore them. + */ +#if defined(MBEDTLS_SSL_PROTO_TLS1_3) + if (ssl->transform_in != NULL && + ssl->transform_in->tls_version == MBEDTLS_SSL_VERSION_TLS1_3) { + if (rec->type == MBEDTLS_SSL_MSG_CHANGE_CIPHER_SPEC) { done = 1; } } -#endif /* MBEDTLS_SSL_HW_RECORD_ACCEL */ +#endif /* MBEDTLS_SSL_PROTO_TLS1_3 */ + if (!done && ssl->transform_in != NULL) { unsigned char const old_msg_type = rec->type; @@ -3679,6 +3985,35 @@ static int ssl_prepare_record_content(mbedtls_ssl_context *ssl, rec)) != 0) { MBEDTLS_SSL_DEBUG_RET(1, "ssl_decrypt_buf", ret); +#if defined(MBEDTLS_SSL_EARLY_DATA) && defined(MBEDTLS_SSL_SRV_C) + /* + * Although the server rejected early data, it might receive early + * data as long as it has not received the client Finished message. + * It is encrypted with early keys and should be ignored as stated + * in section 4.2.10 of RFC 8446: + * + * "Ignore the extension and return a regular 1-RTT response. The + * server then skips past early data by attempting to deprotect + * received records using the handshake traffic key, discarding + * records which fail deprotection (up to the configured + * max_early_data_size). Once a record is deprotected successfully, + * it is treated as the start of the client's second flight and the + * server proceeds as with an ordinary 1-RTT handshake." + */ + if ((old_msg_type == MBEDTLS_SSL_MSG_APPLICATION_DATA) && + (ssl->discard_early_data_record == + MBEDTLS_SSL_EARLY_DATA_TRY_TO_DEPROTECT_AND_DISCARD)) { + MBEDTLS_SSL_DEBUG_MSG( + 3, ("EarlyData: deprotect and discard app data records.")); + + ret = mbedtls_ssl_tls13_check_early_data_len(ssl, rec->data_len); + if (ret != 0) { + return ret; + } + ret = MBEDTLS_ERR_SSL_CONTINUE_PROCESSING; + } +#endif /* MBEDTLS_SSL_EARLY_DATA && MBEDTLS_SSL_SRV_C */ + #if defined(MBEDTLS_SSL_DTLS_CONNECTION_ID) if (ret == MBEDTLS_ERR_SSL_UNEXPECTED_CID && ssl->conf->ignore_unexpected_cid @@ -3688,9 +4023,27 @@ static int ssl_prepare_record_content(mbedtls_ssl_context *ssl, } #endif /* MBEDTLS_SSL_DTLS_CONNECTION_ID */ + /* + * The decryption of the record failed, no reason to ignore it, + * return in error with the decryption error code. + */ return ret; } +#if defined(MBEDTLS_SSL_EARLY_DATA) && defined(MBEDTLS_SSL_SRV_C) + /* + * If the server were discarding protected records that it fails to + * deprotect because it has rejected early data, as we have just + * deprotected successfully a record, the server has to resume normal + * operation and fail the connection if the deprotection of a record + * fails. + */ + if (ssl->discard_early_data_record == + MBEDTLS_SSL_EARLY_DATA_TRY_TO_DEPROTECT_AND_DISCARD) { + ssl->discard_early_data_record = MBEDTLS_SSL_EARLY_DATA_NO_DISCARD; + } +#endif /* MBEDTLS_SSL_EARLY_DATA && MBEDTLS_SSL_SRV_C */ + if (old_msg_type != rec->type) { MBEDTLS_SSL_DEBUG_MSG(4, ("record type after decrypt (before %d): %d", old_msg_type, rec->type)); @@ -3715,7 +4068,7 @@ static int ssl_prepare_record_content(mbedtls_ssl_context *ssl, if (rec->data_len == 0) { #if defined(MBEDTLS_SSL_PROTO_TLS1_2) - if (ssl->minor_ver == MBEDTLS_SSL_MINOR_VERSION_3 + if (ssl->tls_version == MBEDTLS_SSL_VERSION_TLS1_2 && rec->type != MBEDTLS_SSL_MSG_APPLICATION_DATA) { /* TLS v1.2 explicitly disallows zero-length messages which are not application data */ MBEDTLS_SSL_DEBUG_MSG(1, ("invalid zero-length message type: %d", ssl->in_msgtype)); @@ -3748,7 +4101,8 @@ static int ssl_prepare_record_content(mbedtls_ssl_context *ssl, #endif { unsigned i; - for (i = 8; i > mbedtls_ssl_ep_len(ssl); i--) { + for (i = MBEDTLS_SSL_SEQUENCE_NUMBER_LEN; + i > mbedtls_ssl_ep_len(ssl); i--) { if (++ssl->in_ctr[i - 1] != 0) { break; } @@ -3763,6 +4117,38 @@ static int ssl_prepare_record_content(mbedtls_ssl_context *ssl, } +#if defined(MBEDTLS_SSL_EARLY_DATA) && defined(MBEDTLS_SSL_SRV_C) + /* + * Although the server rejected early data because it needed to send an + * HelloRetryRequest message, it might receive early data as long as it has + * not received the client Finished message. + * The early data is encrypted with early keys and should be ignored as + * stated in section 4.2.10 of RFC 8446 (second case): + * + * "The server then ignores early data by skipping all records with an + * external content type of "application_data" (indicating that they are + * encrypted), up to the configured max_early_data_size. Ignore application + * data message before 2nd ClientHello when early_data was received in 1st + * ClientHello." + */ + if (ssl->discard_early_data_record == MBEDTLS_SSL_EARLY_DATA_DISCARD) { + if (rec->type == MBEDTLS_SSL_MSG_APPLICATION_DATA) { + + ret = mbedtls_ssl_tls13_check_early_data_len(ssl, rec->data_len); + if (ret != 0) { + return ret; + } + + MBEDTLS_SSL_DEBUG_MSG( + 3, ("EarlyData: Ignore application message before 2nd ClientHello")); + + return MBEDTLS_ERR_SSL_CONTINUE_PROCESSING; + } else if (rec->type == MBEDTLS_SSL_MSG_HANDSHAKE) { + ssl->discard_early_data_record = MBEDTLS_SSL_EARLY_DATA_NO_DISCARD; + } + } +#endif /* MBEDTLS_SSL_EARLY_DATA && MBEDTLS_SSL_SRV_C */ + #if defined(MBEDTLS_SSL_DTLS_ANTI_REPLAY) if (ssl->conf->transport == MBEDTLS_SSL_TRANSPORT_DATAGRAM) { mbedtls_ssl_dtls_replay_update(ssl); @@ -3861,7 +4247,11 @@ int mbedtls_ssl_read_record(mbedtls_ssl_context *ssl, if (ssl->in_msgtype == MBEDTLS_SSL_MSG_HANDSHAKE && update_hs_digest == 1) { - mbedtls_ssl_update_handshake_status(ssl); + ret = mbedtls_ssl_update_handshake_status(ssl); + if (0 != ret) { + MBEDTLS_SSL_DEBUG_RET(1, ("mbedtls_ssl_update_handshake_status"), ret); + return ret; + } } } else { MBEDTLS_SSL_DEBUG_MSG(2, ("reuse previously read message")); @@ -3940,9 +4330,7 @@ static int ssl_load_buffered_message(mbedtls_ssl_context *ssl) hs_buf = &hs->buffering.hs[0]; if ((hs_buf->is_valid == 1) && (hs_buf->is_complete == 1)) { /* Synthesize a record containing the buffered HS message. */ - size_t msg_len = (hs_buf->data[1] << 16) | - (hs_buf->data[2] << 8) | - hs_buf->data[3]; + size_t msg_len = MBEDTLS_GET_UINT24_BE(hs_buf->data, 1); /* Double-check that we haven't accidentally buffered * a message that doesn't fit into the input buffer. */ @@ -4039,7 +4427,7 @@ static int ssl_buffer_message(mbedtls_ssl_context *ssl) case MBEDTLS_SSL_MSG_HANDSHAKE: { unsigned recv_msg_seq_offset; - unsigned recv_msg_seq = (ssl->in_msg[4] << 8) | ssl->in_msg[5]; + unsigned recv_msg_seq = MBEDTLS_GET_UINT16_BE(ssl->in_msg, 4); mbedtls_ssl_hs_buffer *hs_buf; size_t msg_len = ssl->in_hslen - 12; @@ -4579,13 +4967,11 @@ static int ssl_get_next_record(mbedtls_ssl_context *ssl) return ret; } -#if defined(MBEDTLS_SSL_DTLS_BADMAC_LIMIT) if (ssl->conf->badmac_limit != 0 && ++ssl->badmac_seen >= ssl->conf->badmac_limit) { MBEDTLS_SSL_DEBUG_MSG(1, ("too many records with bad MAC")); return MBEDTLS_ERR_SSL_INVALID_MAC; } -#endif /* As above, invalid records cause * dismissal of the whole datagram. */ @@ -4635,23 +5021,6 @@ static int ssl_get_next_record(mbedtls_ssl_context *ssl) ssl->in_msglen = rec.data_len; MBEDTLS_PUT_UINT16_BE(rec.data_len, ssl->in_len, 0); -#if defined(MBEDTLS_ZLIB_SUPPORT) - if (ssl->transform_in != NULL && - ssl->session_in->compression == MBEDTLS_SSL_COMPRESS_DEFLATE) { - if ((ret = ssl_decompress_buf(ssl)) != 0) { - MBEDTLS_SSL_DEBUG_RET(1, "ssl_decompress_buf", ret); - return ret; - } - - /* Check actual (decompress) record content length against - * configured maximum. */ - if (ssl->in_msglen > MBEDTLS_SSL_IN_CONTENT_LEN) { - MBEDTLS_SSL_DEBUG_MSG(1, ("bad message length")); - return MBEDTLS_ERR_SSL_INVALID_RECORD; - } - } -#endif /* MBEDTLS_ZLIB_SUPPORT */ - return 0; } @@ -4694,6 +5063,20 @@ int mbedtls_ssl_handle_message_type(mbedtls_ssl_context *ssl) return MBEDTLS_ERR_SSL_EARLY_MESSAGE; } #endif + +#if defined(MBEDTLS_SSL_PROTO_TLS1_3) + if (ssl->tls_version == MBEDTLS_SSL_VERSION_TLS1_3) { +#if defined(MBEDTLS_SSL_TLS1_3_COMPATIBILITY_MODE) + MBEDTLS_SSL_DEBUG_MSG(1, + ("Ignore ChangeCipherSpec in TLS 1.3 compatibility mode")); + return MBEDTLS_ERR_SSL_CONTINUE_PROCESSING; +#else + MBEDTLS_SSL_DEBUG_MSG(1, + ("ChangeCipherSpec invalid in TLS 1.3 without compatibility mode")); + return MBEDTLS_ERR_SSL_INVALID_RECORD; +#endif /* MBEDTLS_SSL_TLS1_3_COMPATIBILITY_MODE */ + } +#endif /* MBEDTLS_SSL_PROTO_TLS1_3 */ } if (ssl->in_msgtype == MBEDTLS_SSL_MSG_ALERT) { @@ -4727,23 +5110,11 @@ int mbedtls_ssl_handle_message_type(mbedtls_ssl_context *ssl) #if defined(MBEDTLS_SSL_RENEGOTIATION_ENABLED) if (ssl->in_msg[0] == MBEDTLS_SSL_ALERT_LEVEL_WARNING && ssl->in_msg[1] == MBEDTLS_SSL_ALERT_MSG_NO_RENEGOTIATION) { - MBEDTLS_SSL_DEBUG_MSG(2, ("is a SSLv3 no renegotiation alert")); + MBEDTLS_SSL_DEBUG_MSG(2, ("is a no renegotiation alert")); /* Will be handled when trying to parse ServerHello */ return 0; } #endif - -#if defined(MBEDTLS_SSL_PROTO_SSL3) && defined(MBEDTLS_SSL_SRV_C) - if (ssl->minor_ver == MBEDTLS_SSL_MINOR_VERSION_0 && - ssl->conf->endpoint == MBEDTLS_SSL_IS_SERVER && - ssl->in_msg[0] == MBEDTLS_SSL_ALERT_LEVEL_WARNING && - ssl->in_msg[1] == MBEDTLS_SSL_ALERT_MSG_NO_CERT) { - MBEDTLS_SSL_DEBUG_MSG(2, ("is a SSLv3 no_cert")); - /* Will be handled in mbedtls_ssl_parse_certificate() */ - return 0; - } -#endif /* MBEDTLS_SSL_PROTO_SSL3 && MBEDTLS_SSL_SRV_C */ - /* Silently ignore: fetch new message */ return MBEDTLS_ERR_SSL_NON_FATAL; } @@ -4753,7 +5124,7 @@ int mbedtls_ssl_handle_message_type(mbedtls_ssl_context *ssl) /* Drop unexpected ApplicationData records, * except at the beginning of renegotiations */ if (ssl->in_msgtype == MBEDTLS_SSL_MSG_APPLICATION_DATA && - ssl->state != MBEDTLS_SSL_HANDSHAKE_OVER + mbedtls_ssl_is_handshake_over(ssl) == 0 #if defined(MBEDTLS_SSL_RENEGOTIATION) && !(ssl->renego_status == MBEDTLS_SSL_RENEGOTIATION_IN_PROGRESS && ssl->state == MBEDTLS_SSL_SERVER_HELLO) @@ -4764,7 +5135,7 @@ int mbedtls_ssl_handle_message_type(mbedtls_ssl_context *ssl) } if (ssl->handshake != NULL && - ssl->state == MBEDTLS_SSL_HANDSHAKE_OVER) { + mbedtls_ssl_is_handshake_over(ssl) == 1) { mbedtls_ssl_handshake_wrapup_free_hs_transform(ssl); } } @@ -4859,7 +5230,9 @@ int mbedtls_ssl_parse_change_cipher_spec(mbedtls_ssl_context *ssl) * data. */ MBEDTLS_SSL_DEBUG_MSG(3, ("switching to new transform spec for inbound data")); +#if defined(MBEDTLS_SSL_PROTO_TLS1_2) ssl->transform_in = ssl->transform_negotiate; +#endif ssl->session_in = ssl->session_negotiate; #if defined(MBEDTLS_SSL_PROTO_DTLS) @@ -4877,21 +5250,10 @@ int mbedtls_ssl_parse_change_cipher_spec(mbedtls_ssl_context *ssl) } } else #endif /* MBEDTLS_SSL_PROTO_DTLS */ - memset(ssl->in_ctr, 0, 8); + memset(ssl->in_ctr, 0, MBEDTLS_SSL_SEQUENCE_NUMBER_LEN); mbedtls_ssl_update_in_pointers(ssl); -#if defined(MBEDTLS_SSL_HW_RECORD_ACCEL) - if (mbedtls_ssl_hw_record_activate != NULL) { - if ((ret = mbedtls_ssl_hw_record_activate(ssl, MBEDTLS_SSL_CHANNEL_INBOUND)) != 0) { - MBEDTLS_SSL_DEBUG_RET(1, "mbedtls_ssl_hw_record_activate", ret); - mbedtls_ssl_send_alert_message(ssl, MBEDTLS_SSL_ALERT_LEVEL_FATAL, - MBEDTLS_SSL_ALERT_MSG_INTERNAL_ERROR); - return MBEDTLS_ERR_SSL_HW_ACCEL_FAILED; - } - } -#endif - ssl->state++; MBEDTLS_SSL_DEBUG_MSG(2, ("<= parse change cipher spec")); @@ -4910,10 +5272,6 @@ int mbedtls_ssl_parse_change_cipher_spec(mbedtls_ssl_context *ssl) static size_t ssl_transform_get_explicit_iv_len( mbedtls_ssl_transform const *transform) { - if (transform->minor_ver < MBEDTLS_SSL_MINOR_VERSION_2) { - return 0; - } - return transform->ivlen - transform->fixed_ivlen; } @@ -4924,19 +5282,18 @@ void mbedtls_ssl_update_out_pointers(mbedtls_ssl_context *ssl, if (ssl->conf->transport == MBEDTLS_SSL_TRANSPORT_DATAGRAM) { ssl->out_ctr = ssl->out_hdr + 3; #if defined(MBEDTLS_SSL_DTLS_CONNECTION_ID) - ssl->out_cid = ssl->out_ctr + 8; + ssl->out_cid = ssl->out_ctr + MBEDTLS_SSL_SEQUENCE_NUMBER_LEN; ssl->out_len = ssl->out_cid; if (transform != NULL) { ssl->out_len += transform->out_cid_len; } #else /* MBEDTLS_SSL_DTLS_CONNECTION_ID */ - ssl->out_len = ssl->out_ctr + 8; + ssl->out_len = ssl->out_ctr + MBEDTLS_SSL_SEQUENCE_NUMBER_LEN; #endif /* MBEDTLS_SSL_DTLS_CONNECTION_ID */ ssl->out_iv = ssl->out_len + 2; } else #endif { - ssl->out_ctr = ssl->out_hdr - 8; ssl->out_len = ssl->out_hdr + 3; #if defined(MBEDTLS_SSL_DTLS_CONNECTION_ID) ssl->out_cid = ssl->out_len; @@ -4979,16 +5336,16 @@ void mbedtls_ssl_update_in_pointers(mbedtls_ssl_context *ssl) * ssl_parse_record_header(). */ ssl->in_ctr = ssl->in_hdr + 3; #if defined(MBEDTLS_SSL_DTLS_CONNECTION_ID) - ssl->in_cid = ssl->in_ctr + 8; + ssl->in_cid = ssl->in_ctr + MBEDTLS_SSL_SEQUENCE_NUMBER_LEN; ssl->in_len = ssl->in_cid; /* Default: no CID */ #else /* MBEDTLS_SSL_DTLS_CONNECTION_ID */ - ssl->in_len = ssl->in_ctr + 8; + ssl->in_len = ssl->in_ctr + MBEDTLS_SSL_SEQUENCE_NUMBER_LEN; #endif /* MBEDTLS_SSL_DTLS_CONNECTION_ID */ ssl->in_iv = ssl->in_len + 2; } else #endif { - ssl->in_ctr = ssl->in_hdr - 8; + ssl->in_ctr = ssl->in_hdr - MBEDTLS_SSL_SEQUENCE_NUMBER_LEN; ssl->in_len = ssl->in_hdr + 3; #if defined(MBEDTLS_SSL_DTLS_CONNECTION_ID) ssl->in_cid = ssl->in_len; @@ -5014,6 +5371,7 @@ void mbedtls_ssl_reset_in_out_pointers(mbedtls_ssl_context *ssl) } else #endif /* MBEDTLS_SSL_PROTO_DTLS */ { + ssl->out_ctr = ssl->out_buf; ssl->out_hdr = ssl->out_buf + 8; ssl->in_hdr = ssl->in_buf + 8; } @@ -5089,6 +5447,10 @@ int mbedtls_ssl_get_record_expansion(const mbedtls_ssl_context *ssl) size_t transform_expansion = 0; const mbedtls_ssl_transform *transform = ssl->transform_out; unsigned block_size; +#if defined(MBEDTLS_USE_PSA_CRYPTO) + psa_key_attributes_t attr = PSA_KEY_ATTRIBUTES_INIT; + psa_key_type_t key_type; +#endif /* MBEDTLS_USE_PSA_CRYPTO */ size_t out_hdr_len = mbedtls_ssl_out_hdr_len(ssl); @@ -5096,12 +5458,39 @@ int mbedtls_ssl_get_record_expansion(const mbedtls_ssl_context *ssl) return (int) out_hdr_len; } -#if defined(MBEDTLS_ZLIB_SUPPORT) - if (ssl->session_out->compression != MBEDTLS_SSL_COMPRESS_NULL) { - return MBEDTLS_ERR_SSL_FEATURE_UNAVAILABLE; - } -#endif +#if defined(MBEDTLS_USE_PSA_CRYPTO) + if (transform->psa_alg == PSA_ALG_GCM || + transform->psa_alg == PSA_ALG_CCM || + transform->psa_alg == PSA_ALG_AEAD_WITH_SHORTENED_TAG(PSA_ALG_CCM, 8) || + transform->psa_alg == PSA_ALG_CHACHA20_POLY1305 || + transform->psa_alg == MBEDTLS_SSL_NULL_CIPHER) { + transform_expansion = transform->minlen; + } else if (transform->psa_alg == PSA_ALG_CBC_NO_PADDING) { + (void) psa_get_key_attributes(transform->psa_key_enc, &attr); + key_type = psa_get_key_type(&attr); + + block_size = PSA_BLOCK_CIPHER_BLOCK_LENGTH(key_type); + + /* Expansion due to the addition of the MAC. */ + transform_expansion += transform->maclen; + + /* Expansion due to the addition of CBC padding; + * Theoretically up to 256 bytes, but we never use + * more than the block size of the underlying cipher. */ + transform_expansion += block_size; + + /* For TLS 1.2 or higher, an explicit IV is added + * after the record header. */ +#if defined(MBEDTLS_SSL_PROTO_TLS1_2) + transform_expansion += block_size; +#endif /* MBEDTLS_SSL_PROTO_TLS1_2 */ + } else { + MBEDTLS_SSL_DEBUG_MSG(1, + ("Unsupported psa_alg spotted in mbedtls_ssl_get_record_expansion()")); + return MBEDTLS_ERR_SSL_INTERNAL_ERROR; + } +#else switch (mbedtls_cipher_get_cipher_mode(&transform->cipher_ctx_enc)) { case MBEDTLS_MODE_GCM: case MBEDTLS_MODE_CCM: @@ -5123,13 +5512,11 @@ int mbedtls_ssl_get_record_expansion(const mbedtls_ssl_context *ssl) * more than the block size of the underlying cipher. */ transform_expansion += block_size; - /* For TLS 1.1 or higher, an explicit IV is added + /* For TLS 1.2 or higher, an explicit IV is added * after the record header. */ -#if defined(MBEDTLS_SSL_PROTO_TLS1_1) || defined(MBEDTLS_SSL_PROTO_TLS1_2) - if (ssl->minor_ver >= MBEDTLS_SSL_MINOR_VERSION_2) { - transform_expansion += block_size; - } -#endif /* MBEDTLS_SSL_PROTO_TLS1_1 || MBEDTLS_SSL_PROTO_TLS1_2 */ +#if defined(MBEDTLS_SSL_PROTO_TLS1_2) + transform_expansion += block_size; +#endif /* MBEDTLS_SSL_PROTO_TLS1_2 */ break; @@ -5137,6 +5524,7 @@ int mbedtls_ssl_get_record_expansion(const mbedtls_ssl_context *ssl) MBEDTLS_SSL_DEBUG_MSG(1, ("should never happen")); return MBEDTLS_ERR_SSL_INTERNAL_ERROR; } +#endif /* MBEDTLS_USE_PSA_CRYPTO */ #if defined(MBEDTLS_SSL_DTLS_CONNECTION_ID) if (transform->out_cid_len != 0) { @@ -5158,16 +5546,18 @@ static int ssl_check_ctr_renegotiate(mbedtls_ssl_context *ssl) int in_ctr_cmp; int out_ctr_cmp; - if (ssl->state != MBEDTLS_SSL_HANDSHAKE_OVER || + if (mbedtls_ssl_is_handshake_over(ssl) == 0 || ssl->renego_status == MBEDTLS_SSL_RENEGOTIATION_PENDING || ssl->conf->disable_renegotiation == MBEDTLS_SSL_RENEGOTIATION_DISABLED) { return 0; } in_ctr_cmp = memcmp(ssl->in_ctr + ep_len, - ssl->conf->renego_period + ep_len, 8 - ep_len); - out_ctr_cmp = memcmp(ssl->cur_out_ctr + ep_len, - ssl->conf->renego_period + ep_len, 8 - ep_len); + &ssl->conf->renego_period[ep_len], + MBEDTLS_SSL_SEQUENCE_NUMBER_LEN - ep_len); + out_ctr_cmp = memcmp(&ssl->cur_out_ctr[ep_len], + &ssl->conf->renego_period[ep_len], + sizeof(ssl->cur_out_ctr) - ep_len); if (in_ctr_cmp <= 0 && out_ctr_cmp <= 0) { return 0; @@ -5178,49 +5568,248 @@ static int ssl_check_ctr_renegotiate(mbedtls_ssl_context *ssl) } #endif /* MBEDTLS_SSL_RENEGOTIATION */ -/* - * Receive application data decrypted from the SSL layer - */ -int mbedtls_ssl_read(mbedtls_ssl_context *ssl, unsigned char *buf, size_t len) +#if defined(MBEDTLS_SSL_PROTO_TLS1_3) + +#if defined(MBEDTLS_SSL_SESSION_TICKETS) && defined(MBEDTLS_SSL_CLI_C) +MBEDTLS_CHECK_RETURN_CRITICAL +static int ssl_tls13_check_new_session_ticket(mbedtls_ssl_context *ssl) { - int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED; - size_t n; - if (ssl == NULL || ssl->conf == NULL) { - return MBEDTLS_ERR_SSL_BAD_INPUT_DATA; + if ((ssl->in_hslen == mbedtls_ssl_hs_hdr_len(ssl)) || + (ssl->in_msg[0] != MBEDTLS_SSL_HS_NEW_SESSION_TICKET)) { + return 0; } - MBEDTLS_SSL_DEBUG_MSG(2, ("=> read")); + ssl->keep_current_message = 1; -#if defined(MBEDTLS_SSL_PROTO_DTLS) - if (ssl->conf->transport == MBEDTLS_SSL_TRANSPORT_DATAGRAM) { - if ((ret = mbedtls_ssl_flush_output(ssl)) != 0) { - return ret; - } + MBEDTLS_SSL_DEBUG_MSG(3, ("NewSessionTicket received")); + mbedtls_ssl_handshake_set_state(ssl, + MBEDTLS_SSL_TLS1_3_NEW_SESSION_TICKET); - if (ssl->handshake != NULL && - ssl->handshake->retransmit_state == MBEDTLS_SSL_RETRANS_SENDING) { - if ((ret = mbedtls_ssl_flight_transmit(ssl)) != 0) { - return ret; - } + return MBEDTLS_ERR_SSL_WANT_READ; +} +#endif /* MBEDTLS_SSL_SESSION_TICKETS && MBEDTLS_SSL_CLI_C */ + +MBEDTLS_CHECK_RETURN_CRITICAL +static int ssl_tls13_handle_hs_message_post_handshake(mbedtls_ssl_context *ssl) +{ + + MBEDTLS_SSL_DEBUG_MSG(3, ("received post-handshake message")); + +#if defined(MBEDTLS_SSL_SESSION_TICKETS) && defined(MBEDTLS_SSL_CLI_C) + if (ssl->conf->endpoint == MBEDTLS_SSL_IS_CLIENT) { + int ret = ssl_tls13_check_new_session_ticket(ssl); + if (ret != 0) { + return ret; } } -#endif +#endif /* MBEDTLS_SSL_SESSION_TICKETS && MBEDTLS_SSL_CLI_C */ - /* - * Check if renegotiation is necessary and/or handshake is - * in process. If yes, perform/continue, and fall through - * if an unexpected packet is received while the client - * is waiting for the ServerHello. - * - * (There is no equivalent to the last condition on - * the server-side as it is not treated as within - * a handshake while waiting for the ClientHello - * after a renegotiation request.) - */ + /* Fail in all other cases. */ + return MBEDTLS_ERR_SSL_UNEXPECTED_MESSAGE; +} +#endif /* MBEDTLS_SSL_PROTO_TLS1_3 */ -#if defined(MBEDTLS_SSL_RENEGOTIATION) - ret = ssl_check_ctr_renegotiate(ssl); +#if defined(MBEDTLS_SSL_PROTO_TLS1_2) +/* This function is called from mbedtls_ssl_read() when a handshake message is + * received after the initial handshake. In this context, handshake messages + * may only be sent for the purpose of initiating renegotiations. + * + * This function is introduced as a separate helper since the handling + * of post-handshake handshake messages changes significantly in TLS 1.3, + * and having a helper function allows to distinguish between TLS <= 1.2 and + * TLS 1.3 in the future without bloating the logic of mbedtls_ssl_read(). + */ +MBEDTLS_CHECK_RETURN_CRITICAL +static int ssl_tls12_handle_hs_message_post_handshake(mbedtls_ssl_context *ssl) +{ + int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED; + + /* + * - For client-side, expect SERVER_HELLO_REQUEST. + * - For server-side, expect CLIENT_HELLO. + * - Fail (TLS) or silently drop record (DTLS) in other cases. + */ + +#if defined(MBEDTLS_SSL_CLI_C) + if (ssl->conf->endpoint == MBEDTLS_SSL_IS_CLIENT && + (ssl->in_msg[0] != MBEDTLS_SSL_HS_HELLO_REQUEST || + ssl->in_hslen != mbedtls_ssl_hs_hdr_len(ssl))) { + MBEDTLS_SSL_DEBUG_MSG(1, ("handshake received (not HelloRequest)")); + + /* With DTLS, drop the packet (probably from last handshake) */ +#if defined(MBEDTLS_SSL_PROTO_DTLS) + if (ssl->conf->transport == MBEDTLS_SSL_TRANSPORT_DATAGRAM) { + return 0; + } +#endif + return MBEDTLS_ERR_SSL_UNEXPECTED_MESSAGE; + } +#endif /* MBEDTLS_SSL_CLI_C */ + +#if defined(MBEDTLS_SSL_SRV_C) + if (ssl->conf->endpoint == MBEDTLS_SSL_IS_SERVER && + ssl->in_msg[0] != MBEDTLS_SSL_HS_CLIENT_HELLO) { + MBEDTLS_SSL_DEBUG_MSG(1, ("handshake received (not ClientHello)")); + + /* With DTLS, drop the packet (probably from last handshake) */ +#if defined(MBEDTLS_SSL_PROTO_DTLS) + if (ssl->conf->transport == MBEDTLS_SSL_TRANSPORT_DATAGRAM) { + return 0; + } +#endif + return MBEDTLS_ERR_SSL_UNEXPECTED_MESSAGE; + } +#endif /* MBEDTLS_SSL_SRV_C */ + +#if defined(MBEDTLS_SSL_RENEGOTIATION) + /* Determine whether renegotiation attempt should be accepted */ + if (!(ssl->conf->disable_renegotiation == MBEDTLS_SSL_RENEGOTIATION_DISABLED || + (ssl->secure_renegotiation == MBEDTLS_SSL_LEGACY_RENEGOTIATION && + ssl->conf->allow_legacy_renegotiation == + MBEDTLS_SSL_LEGACY_NO_RENEGOTIATION))) { + /* + * Accept renegotiation request + */ + + /* DTLS clients need to know renego is server-initiated */ +#if defined(MBEDTLS_SSL_PROTO_DTLS) + if (ssl->conf->transport == MBEDTLS_SSL_TRANSPORT_DATAGRAM && + ssl->conf->endpoint == MBEDTLS_SSL_IS_CLIENT) { + ssl->renego_status = MBEDTLS_SSL_RENEGOTIATION_PENDING; + } +#endif + ret = mbedtls_ssl_start_renegotiation(ssl); + if (ret != MBEDTLS_ERR_SSL_WAITING_SERVER_HELLO_RENEGO && + ret != 0) { + MBEDTLS_SSL_DEBUG_RET(1, "mbedtls_ssl_start_renegotiation", + ret); + return ret; + } + } else +#endif /* MBEDTLS_SSL_RENEGOTIATION */ + { + /* + * Refuse renegotiation + */ + + MBEDTLS_SSL_DEBUG_MSG(3, ("refusing renegotiation, sending alert")); + + if ((ret = mbedtls_ssl_send_alert_message(ssl, + MBEDTLS_SSL_ALERT_LEVEL_WARNING, + MBEDTLS_SSL_ALERT_MSG_NO_RENEGOTIATION)) != 0) { + return ret; + } + } + + return 0; +} +#endif /* MBEDTLS_SSL_PROTO_TLS1_2 */ + +MBEDTLS_CHECK_RETURN_CRITICAL +static int ssl_handle_hs_message_post_handshake(mbedtls_ssl_context *ssl) +{ + /* Check protocol version and dispatch accordingly. */ +#if defined(MBEDTLS_SSL_PROTO_TLS1_3) + if (ssl->tls_version == MBEDTLS_SSL_VERSION_TLS1_3) { + return ssl_tls13_handle_hs_message_post_handshake(ssl); + } +#endif /* MBEDTLS_SSL_PROTO_TLS1_3 */ + +#if defined(MBEDTLS_SSL_PROTO_TLS1_2) + if (ssl->tls_version <= MBEDTLS_SSL_VERSION_TLS1_2) { + return ssl_tls12_handle_hs_message_post_handshake(ssl); + } +#endif /* MBEDTLS_SSL_PROTO_TLS1_2 */ + + /* Should never happen */ + return MBEDTLS_ERR_SSL_INTERNAL_ERROR; +} + +/* + * brief Read at most 'len' application data bytes from the input + * buffer. + * + * param ssl SSL context: + * - First byte of application data not read yet in the input + * buffer located at address `in_offt`. + * - The number of bytes of data not read yet is `in_msglen`. + * param buf buffer that will hold the data + * param len maximum number of bytes to read + * + * note The function updates the fields `in_offt` and `in_msglen` + * according to the number of bytes read. + * + * return The number of bytes read. + */ +static int ssl_read_application_data( + mbedtls_ssl_context *ssl, unsigned char *buf, size_t len) +{ + size_t n = (len < ssl->in_msglen) ? len : ssl->in_msglen; + + if (len != 0) { + memcpy(buf, ssl->in_offt, n); + ssl->in_msglen -= n; + } + + /* Zeroising the plaintext buffer to erase unused application data + from the memory. */ + mbedtls_platform_zeroize(ssl->in_offt, n); + + if (ssl->in_msglen == 0) { + /* all bytes consumed */ + ssl->in_offt = NULL; + ssl->keep_current_message = 0; + } else { + /* more data available */ + ssl->in_offt += n; + } + + return (int) n; +} + +/* + * Receive application data decrypted from the SSL layer + */ +int mbedtls_ssl_read(mbedtls_ssl_context *ssl, unsigned char *buf, size_t len) +{ + int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED; + + if (ssl == NULL || ssl->conf == NULL) { + return MBEDTLS_ERR_SSL_BAD_INPUT_DATA; + } + + MBEDTLS_SSL_DEBUG_MSG(2, ("=> read")); + +#if defined(MBEDTLS_SSL_PROTO_DTLS) + if (ssl->conf->transport == MBEDTLS_SSL_TRANSPORT_DATAGRAM) { + if ((ret = mbedtls_ssl_flush_output(ssl)) != 0) { + return ret; + } + + if (ssl->handshake != NULL && + ssl->handshake->retransmit_state == MBEDTLS_SSL_RETRANS_SENDING) { + if ((ret = mbedtls_ssl_flight_transmit(ssl)) != 0) { + return ret; + } + } + } +#endif + + /* + * Check if renegotiation is necessary and/or handshake is + * in process. If yes, perform/continue, and fall through + * if an unexpected packet is received while the client + * is waiting for the ServerHello. + * + * (There is no equivalent to the last condition on + * the server-side as it is not treated as within + * a handshake while waiting for the ClientHello + * after a renegotiation request.) + */ + +#if defined(MBEDTLS_SSL_RENEGOTIATION) + ret = ssl_check_ctr_renegotiate(ssl); if (ret != MBEDTLS_ERR_SSL_WAITING_SERVER_HELLO_RENEGO && ret != 0) { MBEDTLS_SSL_DEBUG_RET(1, "ssl_check_ctr_renegotiate", ret); @@ -5270,107 +5859,16 @@ int mbedtls_ssl_read(mbedtls_ssl_context *ssl, unsigned char *buf, size_t len) } if (ssl->in_msgtype == MBEDTLS_SSL_MSG_HANDSHAKE) { - MBEDTLS_SSL_DEBUG_MSG(1, ("received handshake message")); - - /* - * - For client-side, expect SERVER_HELLO_REQUEST. - * - For server-side, expect CLIENT_HELLO. - * - Fail (TLS) or silently drop record (DTLS) in other cases. - */ - -#if defined(MBEDTLS_SSL_CLI_C) - if (ssl->conf->endpoint == MBEDTLS_SSL_IS_CLIENT && - (ssl->in_msg[0] != MBEDTLS_SSL_HS_HELLO_REQUEST || - ssl->in_hslen != mbedtls_ssl_hs_hdr_len(ssl))) { - MBEDTLS_SSL_DEBUG_MSG(1, ("handshake received (not HelloRequest)")); - - /* With DTLS, drop the packet (probably from last handshake) */ -#if defined(MBEDTLS_SSL_PROTO_DTLS) - if (ssl->conf->transport == MBEDTLS_SSL_TRANSPORT_DATAGRAM) { - continue; - } -#endif - return MBEDTLS_ERR_SSL_UNEXPECTED_MESSAGE; - } -#endif /* MBEDTLS_SSL_CLI_C */ - -#if defined(MBEDTLS_SSL_SRV_C) - if (ssl->conf->endpoint == MBEDTLS_SSL_IS_SERVER && - ssl->in_msg[0] != MBEDTLS_SSL_HS_CLIENT_HELLO) { - MBEDTLS_SSL_DEBUG_MSG(1, ("handshake received (not ClientHello)")); - - /* With DTLS, drop the packet (probably from last handshake) */ -#if defined(MBEDTLS_SSL_PROTO_DTLS) - if (ssl->conf->transport == MBEDTLS_SSL_TRANSPORT_DATAGRAM) { - continue; - } -#endif - return MBEDTLS_ERR_SSL_UNEXPECTED_MESSAGE; - } -#endif /* MBEDTLS_SSL_SRV_C */ - -#if defined(MBEDTLS_SSL_RENEGOTIATION) - /* Determine whether renegotiation attempt should be accepted */ - if (!(ssl->conf->disable_renegotiation == MBEDTLS_SSL_RENEGOTIATION_DISABLED || - (ssl->secure_renegotiation == MBEDTLS_SSL_LEGACY_RENEGOTIATION && - ssl->conf->allow_legacy_renegotiation == - MBEDTLS_SSL_LEGACY_NO_RENEGOTIATION))) { - /* - * Accept renegotiation request - */ - - /* DTLS clients need to know renego is server-initiated */ -#if defined(MBEDTLS_SSL_PROTO_DTLS) - if (ssl->conf->transport == MBEDTLS_SSL_TRANSPORT_DATAGRAM && - ssl->conf->endpoint == MBEDTLS_SSL_IS_CLIENT) { - ssl->renego_status = MBEDTLS_SSL_RENEGOTIATION_PENDING; - } -#endif - ret = mbedtls_ssl_start_renegotiation(ssl); - if (ret != MBEDTLS_ERR_SSL_WAITING_SERVER_HELLO_RENEGO && - ret != 0) { - MBEDTLS_SSL_DEBUG_RET(1, "mbedtls_ssl_start_renegotiation", - ret); - return ret; - } - } else -#endif /* MBEDTLS_SSL_RENEGOTIATION */ - { - /* - * Refuse renegotiation - */ - - MBEDTLS_SSL_DEBUG_MSG(3, ("refusing renegotiation, sending alert")); - -#if defined(MBEDTLS_SSL_PROTO_SSL3) - if (ssl->minor_ver == MBEDTLS_SSL_MINOR_VERSION_0) { - /* SSLv3 does not have a "no_renegotiation" warning, so - we send a fatal alert and abort the connection. */ - mbedtls_ssl_send_alert_message(ssl, MBEDTLS_SSL_ALERT_LEVEL_FATAL, - MBEDTLS_SSL_ALERT_MSG_UNEXPECTED_MESSAGE); - return MBEDTLS_ERR_SSL_UNEXPECTED_MESSAGE; - } else -#endif /* MBEDTLS_SSL_PROTO_SSL3 */ -#if defined(MBEDTLS_SSL_PROTO_TLS1) || defined(MBEDTLS_SSL_PROTO_TLS1_1) || \ - defined(MBEDTLS_SSL_PROTO_TLS1_2) - if (ssl->minor_ver >= MBEDTLS_SSL_MINOR_VERSION_1) { - if ((ret = mbedtls_ssl_send_alert_message(ssl, - MBEDTLS_SSL_ALERT_LEVEL_WARNING, - MBEDTLS_SSL_ALERT_MSG_NO_RENEGOTIATION)) - != 0) { - return ret; - } - } else -#endif /* MBEDTLS_SSL_PROTO_TLS1 || MBEDTLS_SSL_PROTO_TLS1_1 || - MBEDTLS_SSL_PROTO_TLS1_2 */ - { - MBEDTLS_SSL_DEBUG_MSG(1, ("should never happen")); - return MBEDTLS_ERR_SSL_INTERNAL_ERROR; - } + ret = ssl_handle_hs_message_post_handshake(ssl); + if (ret != 0) { + MBEDTLS_SSL_DEBUG_RET(1, "ssl_handle_hs_message_post_handshake", + ret); + return ret; } - /* At this point, we don't know whether the renegotiation has been - * completed or not. The cases to consider are the following: + /* At this point, we don't know whether the renegotiation triggered + * by the post-handshake message has been completed or not. The cases + * to consider are the following: * 1) The renegotiation is complete. In this case, no new record * has been read yet. * 2) The renegotiation is incomplete because the client received @@ -5378,7 +5876,8 @@ int mbedtls_ssl_read(mbedtls_ssl_context *ssl, unsigned char *buf, size_t len) * 3) The renegotiation is incomplete because the client received * a non-handshake, non-application data message while awaiting * the ServerHello. - * In each of these case, looping will be the proper action: + * + * In each of these cases, looping will be the proper action: * - For 1), the next iteration will read a new record and check * if it's application data. * - For 2), the loop condition isn't satisfied as application data @@ -5387,6 +5886,7 @@ int mbedtls_ssl_read(mbedtls_ssl_context *ssl, unsigned char *buf, size_t len) * will re-deliver the message that was held back by the client * when expecting the ServerHello. */ + continue; } #if defined(MBEDTLS_SSL_RENEGOTIATION) @@ -5416,7 +5916,7 @@ int mbedtls_ssl_read(mbedtls_ssl_context *ssl, unsigned char *buf, size_t len) /* We're going to return something now, cancel timer, * except if handshake (renegotiation) is in progress */ - if (ssl->state == MBEDTLS_SSL_HANDSHAKE_OVER) { + if (mbedtls_ssl_is_handshake_over(ssl) == 1) { mbedtls_ssl_set_timer(ssl, 0); } @@ -5437,31 +5937,33 @@ int mbedtls_ssl_read(mbedtls_ssl_context *ssl, unsigned char *buf, size_t len) #endif /* MBEDTLS_SSL_PROTO_DTLS */ } - n = (len < ssl->in_msglen) - ? len : ssl->in_msglen; + ret = ssl_read_application_data(ssl, buf, len); - if (len != 0) { - memcpy(buf, ssl->in_offt, n); - ssl->in_msglen -= n; - } + MBEDTLS_SSL_DEBUG_MSG(2, ("<= read")); - /* Zeroising the plaintext buffer to erase unused application data - from the memory. */ - mbedtls_platform_zeroize(ssl->in_offt, n); + return ret; +} - if (ssl->in_msglen == 0) { - /* all bytes consumed */ - ssl->in_offt = NULL; - ssl->keep_current_message = 0; - } else { - /* more data available */ - ssl->in_offt += n; +#if defined(MBEDTLS_SSL_SRV_C) && defined(MBEDTLS_SSL_EARLY_DATA) +int mbedtls_ssl_read_early_data(mbedtls_ssl_context *ssl, + unsigned char *buf, size_t len) +{ + if (ssl == NULL || (ssl->conf == NULL)) { + return MBEDTLS_ERR_SSL_BAD_INPUT_DATA; } - MBEDTLS_SSL_DEBUG_MSG(2, ("<= read")); + /* + * The server may receive early data only while waiting for the End of + * Early Data handshake message. + */ + if ((ssl->state != MBEDTLS_SSL_END_OF_EARLY_DATA) || + (ssl->in_offt == NULL)) { + return MBEDTLS_ERR_SSL_CANNOT_READ_EARLY_DATA; + } - return (int) n; + return ssl_read_application_data(ssl, buf, len); } +#endif /* MBEDTLS_SSL_SRV_C && MBEDTLS_SSL_EARLY_DATA */ /* * Send application data to be encrypted by the SSL layer, taking care of max @@ -5532,45 +6034,6 @@ static int ssl_write_real(mbedtls_ssl_context *ssl, return (int) len; } -/* - * Write application data, doing 1/n-1 splitting if necessary. - * - * With non-blocking I/O, ssl_write_real() may return WANT_WRITE, - * then the caller will call us again with the same arguments, so - * remember whether we already did the split or not. - */ -#if defined(MBEDTLS_SSL_CBC_RECORD_SPLITTING) -MBEDTLS_CHECK_RETURN_CRITICAL -static int ssl_write_split(mbedtls_ssl_context *ssl, - const unsigned char *buf, size_t len) -{ - int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED; - - if (ssl->conf->cbc_record_splitting == - MBEDTLS_SSL_CBC_RECORD_SPLITTING_DISABLED || - len <= 1 || - ssl->minor_ver > MBEDTLS_SSL_MINOR_VERSION_1 || - mbedtls_cipher_get_cipher_mode(&ssl->transform_out->cipher_ctx_enc) - != MBEDTLS_MODE_CBC) { - return ssl_write_real(ssl, buf, len); - } - - if (ssl->split_done == 0) { - if ((ret = ssl_write_real(ssl, buf, 1)) <= 0) { - return ret; - } - ssl->split_done = 1; - } - - if ((ret = ssl_write_real(ssl, buf + 1, len - 1)) <= 0) { - return ret; - } - ssl->split_done = 0; - - return ret + 1; -} -#endif /* MBEDTLS_SSL_CBC_RECORD_SPLITTING */ - /* * Write application data (public-facing wrapper) */ @@ -5598,17 +6061,118 @@ int mbedtls_ssl_write(mbedtls_ssl_context *ssl, const unsigned char *buf, size_t } } -#if defined(MBEDTLS_SSL_CBC_RECORD_SPLITTING) - ret = ssl_write_split(ssl, buf, len); -#else ret = ssl_write_real(ssl, buf, len); -#endif MBEDTLS_SSL_DEBUG_MSG(2, ("<= write")); return ret; } +#if defined(MBEDTLS_SSL_EARLY_DATA) && defined(MBEDTLS_SSL_CLI_C) +int mbedtls_ssl_write_early_data(mbedtls_ssl_context *ssl, + const unsigned char *buf, size_t len) +{ + int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED; + const struct mbedtls_ssl_config *conf; + uint32_t remaining; + + MBEDTLS_SSL_DEBUG_MSG(2, ("=> write early_data")); + + if (ssl == NULL || (conf = ssl->conf) == NULL) { + return MBEDTLS_ERR_SSL_BAD_INPUT_DATA; + } + + if (conf->endpoint != MBEDTLS_SSL_IS_CLIENT) { + return MBEDTLS_ERR_SSL_BAD_INPUT_DATA; + } + + if ((!mbedtls_ssl_conf_is_tls13_enabled(conf)) || + (conf->transport == MBEDTLS_SSL_TRANSPORT_DATAGRAM) || + (conf->early_data_enabled != MBEDTLS_SSL_EARLY_DATA_ENABLED)) { + return MBEDTLS_ERR_SSL_CANNOT_WRITE_EARLY_DATA; + } + + if (ssl->tls_version != MBEDTLS_SSL_VERSION_TLS1_3) { + return MBEDTLS_ERR_SSL_CANNOT_WRITE_EARLY_DATA; + } + + /* + * If we are at the beginning of the handshake, the early data state being + * equal to MBEDTLS_SSL_EARLY_DATA_STATE_IDLE or + * MBEDTLS_SSL_EARLY_DATA_STATE_IND_SENT advance the handshake just + * enough to be able to send early data if possible. That way, we can + * guarantee that when starting the handshake with this function we will + * send at least one record of early data. Note that when the state is + * MBEDTLS_SSL_EARLY_DATA_STATE_IND_SENT and not yet + * MBEDTLS_SSL_EARLY_DATA_STATE_CAN_WRITE, we cannot send early data + * as the early data outbound transform has not been set as we may have to + * first send a dummy CCS in clear. + */ + if ((ssl->early_data_state == MBEDTLS_SSL_EARLY_DATA_STATE_IDLE) || + (ssl->early_data_state == MBEDTLS_SSL_EARLY_DATA_STATE_IND_SENT)) { + while ((ssl->early_data_state == MBEDTLS_SSL_EARLY_DATA_STATE_IDLE) || + (ssl->early_data_state == MBEDTLS_SSL_EARLY_DATA_STATE_IND_SENT)) { + ret = mbedtls_ssl_handshake_step(ssl); + if (ret != 0) { + MBEDTLS_SSL_DEBUG_RET(1, "mbedtls_ssl_handshake_step", ret); + return ret; + } + + ret = mbedtls_ssl_flush_output(ssl); + if (ret != 0) { + MBEDTLS_SSL_DEBUG_RET(1, "mbedtls_ssl_flush_output", ret); + return ret; + } + } + remaining = ssl->session_negotiate->max_early_data_size; + } else { + /* + * If we are past the point where we can send early data or we have + * already reached the maximum early data size, return immediatly. + * Otherwise, progress the handshake as much as possible to not delay + * it too much. If we reach a point where we can still send early data, + * then we will send some. + */ + if ((ssl->early_data_state != MBEDTLS_SSL_EARLY_DATA_STATE_CAN_WRITE) && + (ssl->early_data_state != MBEDTLS_SSL_EARLY_DATA_STATE_ACCEPTED)) { + return MBEDTLS_ERR_SSL_CANNOT_WRITE_EARLY_DATA; + } + + remaining = ssl->session_negotiate->max_early_data_size - + ssl->total_early_data_size; + + if (remaining == 0) { + return MBEDTLS_ERR_SSL_CANNOT_WRITE_EARLY_DATA; + } + + ret = mbedtls_ssl_handshake(ssl); + if ((ret != 0) && (ret != MBEDTLS_ERR_SSL_WANT_READ)) { + MBEDTLS_SSL_DEBUG_RET(1, "mbedtls_ssl_handshake", ret); + return ret; + } + } + + if (((ssl->early_data_state != MBEDTLS_SSL_EARLY_DATA_STATE_CAN_WRITE) && + (ssl->early_data_state != MBEDTLS_SSL_EARLY_DATA_STATE_ACCEPTED)) + || (remaining == 0)) { + return MBEDTLS_ERR_SSL_CANNOT_WRITE_EARLY_DATA; + } + + if (len > remaining) { + len = remaining; + } + + ret = ssl_write_real(ssl, buf, len); + if (ret >= 0) { + ssl->total_early_data_size += ret; + } + + MBEDTLS_SSL_DEBUG_MSG(2, ("<= write early_data, ret=%d", ret)); + + return ret; +} +#endif /* MBEDTLS_SSL_EARLY_DATA && MBEDTLS_SSL_CLI_C */ + /* * Notify the peer that the connection is being closed */ @@ -5622,7 +6186,7 @@ int mbedtls_ssl_close_notify(mbedtls_ssl_context *ssl) MBEDTLS_SSL_DEBUG_MSG(2, ("=> write close notify")); - if (ssl->state == MBEDTLS_SSL_HANDSHAKE_OVER) { + if (mbedtls_ssl_is_handshake_over(ssl) == 1) { if ((ret = mbedtls_ssl_send_alert_message(ssl, MBEDTLS_SSL_ALERT_LEVEL_WARNING, MBEDTLS_SSL_ALERT_MSG_CLOSE_NOTIFY)) != 0) { @@ -5642,22 +6206,41 @@ void mbedtls_ssl_transform_free(mbedtls_ssl_transform *transform) return; } -#if defined(MBEDTLS_ZLIB_SUPPORT) - deflateEnd(&transform->ctx_deflate); - inflateEnd(&transform->ctx_inflate); -#endif - +#if defined(MBEDTLS_USE_PSA_CRYPTO) + psa_destroy_key(transform->psa_key_enc); + psa_destroy_key(transform->psa_key_dec); +#else mbedtls_cipher_free(&transform->cipher_ctx_enc); mbedtls_cipher_free(&transform->cipher_ctx_dec); +#endif /* MBEDTLS_USE_PSA_CRYPTO */ -#if defined(MBEDTLS_SSL_SOME_MODES_USE_MAC) +#if defined(MBEDTLS_SSL_SOME_SUITES_USE_MAC) +#if defined(MBEDTLS_USE_PSA_CRYPTO) + psa_destroy_key(transform->psa_mac_enc); + psa_destroy_key(transform->psa_mac_dec); +#else mbedtls_md_free(&transform->md_ctx_enc); mbedtls_md_free(&transform->md_ctx_dec); +#endif /* MBEDTLS_USE_PSA_CRYPTO */ #endif mbedtls_platform_zeroize(transform, sizeof(mbedtls_ssl_transform)); } +void mbedtls_ssl_set_inbound_transform(mbedtls_ssl_context *ssl, + mbedtls_ssl_transform *transform) +{ + ssl->transform_in = transform; + memset(ssl->in_ctr, 0, MBEDTLS_SSL_SEQUENCE_NUMBER_LEN); +} + +void mbedtls_ssl_set_outbound_transform(mbedtls_ssl_context *ssl, + mbedtls_ssl_transform *transform) +{ + ssl->transform_out = transform; + memset(ssl->cur_out_ctr, 0, sizeof(ssl->cur_out_ctr)); +} + #if defined(MBEDTLS_SSL_PROTO_DTLS) void mbedtls_ssl_buffering_free(mbedtls_ssl_context *ssl) @@ -5688,8 +6271,7 @@ static void ssl_buffering_free_slot(mbedtls_ssl_context *ssl, if (hs_buf->is_valid == 1) { hs->buffering.total_bytes_buffered -= hs_buf->data_len; - mbedtls_platform_zeroize(hs_buf->data, hs_buf->data_len); - mbedtls_free(hs_buf->data); + mbedtls_zeroize_and_free(hs_buf->data, hs_buf->data_len); memset(hs_buf, 0, sizeof(mbedtls_ssl_hs_buffer)); } } @@ -5701,50 +6283,86 @@ static void ssl_buffering_free_slot(mbedtls_ssl_context *ssl, * and, for DTLS, to/from TLS equivalent. * * For TLS this is the identity. - * For DTLS, use 1's complement (v -> 255 - v, and then map as follows: - * 1.0 <-> 3.2 (DTLS 1.0 is based on TLS 1.1) + * For DTLS, map as follows, then use 1's complement (v -> ~v): * 1.x <-> 3.x+1 for x != 0 (DTLS 1.2 based on TLS 1.2) + * DTLS 1.0 is stored as TLS 1.1 internally */ -void mbedtls_ssl_write_version(int major, int minor, int transport, - unsigned char ver[2]) +void mbedtls_ssl_write_version(unsigned char version[2], int transport, + mbedtls_ssl_protocol_version tls_version) { + uint16_t tls_version_formatted; #if defined(MBEDTLS_SSL_PROTO_DTLS) if (transport == MBEDTLS_SSL_TRANSPORT_DATAGRAM) { - if (minor == MBEDTLS_SSL_MINOR_VERSION_2) { - --minor; /* DTLS 1.0 stored as TLS 1.1 internally */ - - } - ver[0] = (unsigned char) (255 - (major - 2)); - ver[1] = (unsigned char) (255 - (minor - 1)); + tls_version_formatted = + ~(tls_version - (tls_version == 0x0302 ? 0x0202 : 0x0201)); } else #else ((void) transport); #endif { - ver[0] = (unsigned char) major; - ver[1] = (unsigned char) minor; + tls_version_formatted = (uint16_t) tls_version; } + MBEDTLS_PUT_UINT16_BE(tls_version_formatted, version, 0); } -void mbedtls_ssl_read_version(int *major, int *minor, int transport, - const unsigned char ver[2]) +uint16_t mbedtls_ssl_read_version(const unsigned char version[2], + int transport) { + uint16_t tls_version = MBEDTLS_GET_UINT16_BE(version, 0); #if defined(MBEDTLS_SSL_PROTO_DTLS) if (transport == MBEDTLS_SSL_TRANSPORT_DATAGRAM) { - *major = 255 - ver[0] + 2; - *minor = 255 - ver[1] + 1; - - if (*minor == MBEDTLS_SSL_MINOR_VERSION_1) { - ++*minor; /* DTLS 1.0 stored as TLS 1.1 internally */ - } - } else + tls_version = + ~(tls_version - (tls_version == 0xfeff ? 0x0202 : 0x0201)); + } #else ((void) transport); #endif - { - *major = ver[0]; - *minor = ver[1]; + return tls_version; +} + +/* + * Send pending fatal alert. + * 0, No alert message. + * !0, if mbedtls_ssl_send_alert_message() returned in error, the error code it + * returned, ssl->alert_reason otherwise. + */ +int mbedtls_ssl_handle_pending_alert(mbedtls_ssl_context *ssl) +{ + int ret; + + /* No pending alert, return success*/ + if (ssl->send_alert == 0) { + return 0; + } + + ret = mbedtls_ssl_send_alert_message(ssl, + MBEDTLS_SSL_ALERT_LEVEL_FATAL, + ssl->alert_type); + + /* If mbedtls_ssl_send_alert_message() returned with MBEDTLS_ERR_SSL_WANT_WRITE, + * do not clear the alert to be able to send it later. + */ + if (ret != MBEDTLS_ERR_SSL_WANT_WRITE) { + ssl->send_alert = 0; } + + if (ret != 0) { + return ret; + } + + return ssl->alert_reason; +} + +/* + * Set pending fatal alert flag. + */ +void mbedtls_ssl_pend_fatal_alert(mbedtls_ssl_context *ssl, + unsigned char alert_type, + int alert_reason) +{ + ssl->send_alert = 1; + ssl->alert_type = alert_type; + ssl->alert_reason = alert_reason; } #endif /* MBEDTLS_SSL_TLS_C */ diff --git a/vendor/mbedtls/library/ssl_ticket.c b/vendor/mbedtls/library/ssl_ticket.c index 0789245bac..6a31b0bee6 100644 --- a/vendor/mbedtls/library/ssl_ticket.c +++ b/vendor/mbedtls/library/ssl_ticket.c @@ -2,19 +2,7 @@ * TLS server tickets callbacks implementation * * Copyright The Mbed TLS Contributors - * SPDX-License-Identifier: Apache-2.0 - * - * Licensed under the Apache License, Version 2.0 (the "License"); you may - * not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT - * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. + * SPDX-License-Identifier: Apache-2.0 OR GPL-2.0-or-later */ #include "common.h" @@ -23,13 +11,25 @@ #include "mbedtls/platform.h" -#include "mbedtls/ssl_internal.h" +#include "ssl_misc.h" #include "mbedtls/ssl_ticket.h" #include "mbedtls/error.h" #include "mbedtls/platform_util.h" #include +#if defined(MBEDTLS_USE_PSA_CRYPTO) +/* Define a local translating function to save code size by not using too many + * arguments in each translating place. */ +static int local_err_translation(psa_status_t status) +{ + return psa_status_to_mbedtls(status, psa_to_ssl_errors, + ARRAY_LENGTH(psa_to_ssl_errors), + psa_generic_status_to_mbedtls); +} +#define PSA_TO_MBEDTLS_ERR(status) local_err_translation(status) +#endif + /* * Initialize context */ @@ -42,9 +42,9 @@ void mbedtls_ssl_ticket_init(mbedtls_ssl_ticket_context *ctx) #endif } -#define MAX_KEY_BYTES 32 /* 256 bits */ +#define MAX_KEY_BYTES MBEDTLS_SSL_TICKET_MAX_KEY_BYTES -#define TICKET_KEY_NAME_BYTES 4 +#define TICKET_KEY_NAME_BYTES MBEDTLS_SSL_TICKET_KEY_NAME_BYTES #define TICKET_IV_BYTES 12 #define TICKET_CRYPT_LEN_BYTES 2 #define TICKET_AUTH_TAG_BYTES 16 @@ -65,12 +65,20 @@ static int ssl_ticket_gen_key(mbedtls_ssl_ticket_context *ctx, unsigned char index) { int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED; - unsigned char buf[MAX_KEY_BYTES]; + unsigned char buf[MAX_KEY_BYTES] = { 0 }; mbedtls_ssl_ticket_key *key = ctx->keys + index; +#if defined(MBEDTLS_USE_PSA_CRYPTO) + psa_key_attributes_t attributes = PSA_KEY_ATTRIBUTES_INIT; +#endif + #if defined(MBEDTLS_HAVE_TIME) - key->generation_time = (uint32_t) mbedtls_time(NULL); + key->generation_time = mbedtls_time(NULL); #endif + /* The lifetime of a key is the configured lifetime of the tickets when + * the key is created. + */ + key->lifetime = ctx->ticket_lifetime; if ((ret = ctx->f_rng(ctx->p_rng, key->name, sizeof(key->name))) != 0) { return ret; @@ -80,10 +88,23 @@ static int ssl_ticket_gen_key(mbedtls_ssl_ticket_context *ctx, return ret; } +#if defined(MBEDTLS_USE_PSA_CRYPTO) + psa_set_key_usage_flags(&attributes, + PSA_KEY_USAGE_ENCRYPT | PSA_KEY_USAGE_DECRYPT); + psa_set_key_algorithm(&attributes, key->alg); + psa_set_key_type(&attributes, key->key_type); + psa_set_key_bits(&attributes, key->key_bits); + + ret = PSA_TO_MBEDTLS_ERR( + psa_import_key(&attributes, buf, + PSA_BITS_TO_BYTES(key->key_bits), + &key->key)); +#else /* With GCM and CCM, same context can encrypt & decrypt */ ret = mbedtls_cipher_setkey(&key->ctx, buf, mbedtls_cipher_get_key_bitlen(&key->ctx), MBEDTLS_ENCRYPT); +#endif /* MBEDTLS_USE_PSA_CRYPTO */ mbedtls_platform_zeroize(buf, sizeof(buf)); @@ -99,23 +120,94 @@ static int ssl_ticket_update_keys(mbedtls_ssl_ticket_context *ctx) #if !defined(MBEDTLS_HAVE_TIME) ((void) ctx); #else - if (ctx->ticket_lifetime != 0) { - uint32_t current_time = (uint32_t) mbedtls_time(NULL); - uint32_t key_time = ctx->keys[ctx->active].generation_time; + mbedtls_ssl_ticket_key * const key = ctx->keys + ctx->active; + if (key->lifetime != 0) { + mbedtls_time_t current_time = mbedtls_time(NULL); + mbedtls_time_t key_time = key->generation_time; + +#if defined(MBEDTLS_USE_PSA_CRYPTO) + psa_status_t status = PSA_ERROR_CORRUPTION_DETECTED; +#endif if (current_time >= key_time && - current_time - key_time < ctx->ticket_lifetime) { + (uint64_t) (current_time - key_time) < key->lifetime) { return 0; } ctx->active = 1 - ctx->active; +#if defined(MBEDTLS_USE_PSA_CRYPTO) + if ((status = psa_destroy_key(ctx->keys[ctx->active].key)) != PSA_SUCCESS) { + return PSA_TO_MBEDTLS_ERR(status); + } +#endif /* MBEDTLS_USE_PSA_CRYPTO */ + return ssl_ticket_gen_key(ctx, ctx->active); } else #endif /* MBEDTLS_HAVE_TIME */ return 0; } +/* + * Rotate active session ticket encryption key + */ +int mbedtls_ssl_ticket_rotate(mbedtls_ssl_ticket_context *ctx, + const unsigned char *name, size_t nlength, + const unsigned char *k, size_t klength, + uint32_t lifetime) +{ + const unsigned char idx = 1 - ctx->active; + mbedtls_ssl_ticket_key * const key = ctx->keys + idx; + int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED; + +#if defined(MBEDTLS_USE_PSA_CRYPTO) + psa_status_t status = PSA_ERROR_CORRUPTION_DETECTED; + psa_key_attributes_t attributes = PSA_KEY_ATTRIBUTES_INIT; + const size_t bitlen = key->key_bits; +#else + const int bitlen = mbedtls_cipher_get_key_bitlen(&key->ctx); +#endif + + if (nlength < TICKET_KEY_NAME_BYTES || klength * 8 < (size_t) bitlen) { + return MBEDTLS_ERR_CIPHER_BAD_INPUT_DATA; + } + +#if defined(MBEDTLS_USE_PSA_CRYPTO) + if ((status = psa_destroy_key(key->key)) != PSA_SUCCESS) { + ret = PSA_TO_MBEDTLS_ERR(status); + return ret; + } + + psa_set_key_usage_flags(&attributes, + PSA_KEY_USAGE_ENCRYPT | PSA_KEY_USAGE_DECRYPT); + psa_set_key_algorithm(&attributes, key->alg); + psa_set_key_type(&attributes, key->key_type); + psa_set_key_bits(&attributes, key->key_bits); + + if ((status = psa_import_key(&attributes, k, + PSA_BITS_TO_BYTES(key->key_bits), + &key->key)) != PSA_SUCCESS) { + ret = PSA_TO_MBEDTLS_ERR(status); + return ret; + } +#else + ret = mbedtls_cipher_setkey(&key->ctx, k, bitlen, MBEDTLS_ENCRYPT); + if (ret != 0) { + return ret; + } +#endif /* MBEDTLS_USE_PSA_CRYPTO */ + + ctx->active = idx; + ctx->ticket_lifetime = lifetime; + memcpy(key->name, name, TICKET_KEY_NAME_BYTES); +#if defined(MBEDTLS_HAVE_TIME) + key->generation_time = mbedtls_time(NULL); +#endif + key->lifetime = lifetime; + + return 0; +} + /* * Setup context for actual use */ @@ -125,71 +217,62 @@ int mbedtls_ssl_ticket_setup(mbedtls_ssl_ticket_context *ctx, uint32_t lifetime) { int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED; - const mbedtls_cipher_info_t *cipher_info; - - ctx->f_rng = f_rng; - ctx->p_rng = p_rng; + size_t key_bits; - ctx->ticket_lifetime = lifetime; +#if defined(MBEDTLS_USE_PSA_CRYPTO) + psa_algorithm_t alg; + psa_key_type_t key_type; +#else + const mbedtls_cipher_info_t *cipher_info; +#endif /* MBEDTLS_USE_PSA_CRYPTO */ - cipher_info = mbedtls_cipher_info_from_type(cipher); - if (cipher_info == NULL) { +#if defined(MBEDTLS_USE_PSA_CRYPTO) + if (mbedtls_ssl_cipher_to_psa(cipher, TICKET_AUTH_TAG_BYTES, + &alg, &key_type, &key_bits) != PSA_SUCCESS) { return MBEDTLS_ERR_SSL_BAD_INPUT_DATA; } - if (cipher_info->mode != MBEDTLS_MODE_GCM && - cipher_info->mode != MBEDTLS_MODE_CCM) { + if (PSA_ALG_IS_AEAD(alg) == 0) { return MBEDTLS_ERR_SSL_BAD_INPUT_DATA; } +#else + cipher_info = mbedtls_cipher_info_from_type(cipher); - if (cipher_info->key_bitlen > 8 * MAX_KEY_BYTES) { + if (mbedtls_cipher_info_get_mode(cipher_info) != MBEDTLS_MODE_GCM && + mbedtls_cipher_info_get_mode(cipher_info) != MBEDTLS_MODE_CCM && + mbedtls_cipher_info_get_mode(cipher_info) != MBEDTLS_MODE_CHACHAPOLY) { return MBEDTLS_ERR_SSL_BAD_INPUT_DATA; } - int do_mbedtls_cipher_setup = 1; -#if defined(MBEDTLS_USE_PSA_CRYPTO) - ret = mbedtls_cipher_setup_psa(&ctx->keys[0].ctx, - cipher_info, TICKET_AUTH_TAG_BYTES); - - switch (ret) { - case 0: - do_mbedtls_cipher_setup = 0; - break; - case MBEDTLS_ERR_CIPHER_FEATURE_UNAVAILABLE: - /* We don't yet expect to support all ciphers through PSA, - * so allow fallback to ordinary mbedtls_cipher_setup(). */ - do_mbedtls_cipher_setup = 1; - break; - default: - return ret; - } + key_bits = mbedtls_cipher_info_get_key_bitlen(cipher_info); #endif /* MBEDTLS_USE_PSA_CRYPTO */ - if (do_mbedtls_cipher_setup) { - if ((ret = mbedtls_cipher_setup(&ctx->keys[0].ctx, cipher_info)) - != 0) { - return ret; - } + + if (key_bits > 8 * MAX_KEY_BYTES) { + return MBEDTLS_ERR_SSL_BAD_INPUT_DATA; } - do_mbedtls_cipher_setup = 1; + ctx->f_rng = f_rng; + ctx->p_rng = p_rng; + + ctx->ticket_lifetime = lifetime; + #if defined(MBEDTLS_USE_PSA_CRYPTO) - do_mbedtls_cipher_setup = 0; + ctx->keys[0].alg = alg; + ctx->keys[0].key_type = key_type; + ctx->keys[0].key_bits = key_bits; - ret = mbedtls_cipher_setup_psa(&ctx->keys[1].ctx, - cipher_info, TICKET_AUTH_TAG_BYTES); - if (ret != 0 && ret != MBEDTLS_ERR_CIPHER_FEATURE_UNAVAILABLE) { + ctx->keys[1].alg = alg; + ctx->keys[1].key_type = key_type; + ctx->keys[1].key_bits = key_bits; +#else + if ((ret = mbedtls_cipher_setup(&ctx->keys[0].ctx, cipher_info)) != 0) { return ret; } - if (ret == MBEDTLS_ERR_CIPHER_FEATURE_UNAVAILABLE) { - do_mbedtls_cipher_setup = 1; + + if ((ret = mbedtls_cipher_setup(&ctx->keys[1].ctx, cipher_info)) != 0) { + return ret; } #endif /* MBEDTLS_USE_PSA_CRYPTO */ - if (do_mbedtls_cipher_setup) { - if ((ret = mbedtls_cipher_setup(&ctx->keys[1].ctx, cipher_info)) - != 0) { - return ret; - } - } if ((ret = ssl_ticket_gen_key(ctx, 0)) != 0 || (ret = ssl_ticket_gen_key(ctx, 1)) != 0) { @@ -229,6 +312,10 @@ int mbedtls_ssl_ticket_write(void *p_ticket, unsigned char *state = state_len_bytes + TICKET_CRYPT_LEN_BYTES; size_t clear_len, ciph_len; +#if defined(MBEDTLS_USE_PSA_CRYPTO) + psa_status_t status = PSA_ERROR_CORRUPTION_DETECTED; +#endif + *tlen = 0; if (ctx == NULL || ctx->f_rng == NULL) { @@ -251,7 +338,7 @@ int mbedtls_ssl_ticket_write(void *p_ticket, key = &ctx->keys[ctx->active]; - *ticket_lifetime = ctx->ticket_lifetime; + *ticket_lifetime = key->lifetime; memcpy(key_name, key->name, TICKET_KEY_NAME_BYTES); @@ -261,7 +348,7 @@ int mbedtls_ssl_ticket_write(void *p_ticket, /* Dump session state */ if ((ret = mbedtls_ssl_session_save(session, - state, end - state, + state, (size_t) (end - state), &clear_len)) != 0 || (unsigned long) clear_len > 65535) { goto cleanup; @@ -269,15 +356,27 @@ int mbedtls_ssl_ticket_write(void *p_ticket, MBEDTLS_PUT_UINT16_BE(clear_len, state_len_bytes, 0); /* Encrypt and authenticate */ +#if defined(MBEDTLS_USE_PSA_CRYPTO) + if ((status = psa_aead_encrypt(key->key, key->alg, iv, TICKET_IV_BYTES, + key_name, TICKET_ADD_DATA_LEN, + state, clear_len, + state, end - state, + &ciph_len)) != PSA_SUCCESS) { + ret = PSA_TO_MBEDTLS_ERR(status); + goto cleanup; + } +#else if ((ret = mbedtls_cipher_auth_encrypt_ext(&key->ctx, iv, TICKET_IV_BYTES, /* Additional data: key name, IV and length */ key_name, TICKET_ADD_DATA_LEN, state, clear_len, - state, end - state, &ciph_len, + state, (size_t) (end - state), &ciph_len, TICKET_AUTH_TAG_BYTES)) != 0) { goto cleanup; } +#endif /* MBEDTLS_USE_PSA_CRYPTO */ + if (ciph_len != clear_len + TICKET_AUTH_TAG_BYTES) { ret = MBEDTLS_ERR_SSL_INTERNAL_ERROR; goto cleanup; @@ -330,6 +429,10 @@ int mbedtls_ssl_ticket_parse(void *p_ticket, unsigned char *ticket = enc_len_p + TICKET_CRYPT_LEN_BYTES; size_t enc_len, clear_len; +#if defined(MBEDTLS_USE_PSA_CRYPTO) + psa_status_t status = PSA_ERROR_CORRUPTION_DETECTED; +#endif + if (ctx == NULL || ctx->f_rng == NULL) { return MBEDTLS_ERR_SSL_BAD_INPUT_DATA; } @@ -348,7 +451,7 @@ int mbedtls_ssl_ticket_parse(void *p_ticket, goto cleanup; } - enc_len = (enc_len_p[0] << 8) | enc_len_p[1]; + enc_len = MBEDTLS_GET_UINT16_BE(enc_len_p, 0); if (len != TICKET_MIN_LEN + enc_len) { ret = MBEDTLS_ERR_SSL_BAD_INPUT_DATA; @@ -364,6 +467,15 @@ int mbedtls_ssl_ticket_parse(void *p_ticket, } /* Decrypt and authenticate */ +#if defined(MBEDTLS_USE_PSA_CRYPTO) + if ((status = psa_aead_decrypt(key->key, key->alg, iv, TICKET_IV_BYTES, + key_name, TICKET_ADD_DATA_LEN, + ticket, enc_len + TICKET_AUTH_TAG_BYTES, + ticket, enc_len, &clear_len)) != PSA_SUCCESS) { + ret = PSA_TO_MBEDTLS_ERR(status); + goto cleanup; + } +#else if ((ret = mbedtls_cipher_auth_decrypt_ext(&key->ctx, iv, TICKET_IV_BYTES, /* Additional data: key name, IV and length */ @@ -377,6 +489,8 @@ int mbedtls_ssl_ticket_parse(void *p_ticket, goto cleanup; } +#endif /* MBEDTLS_USE_PSA_CRYPTO */ + if (clear_len != enc_len) { ret = MBEDTLS_ERR_SSL_INTERNAL_ERROR; goto cleanup; @@ -388,15 +502,20 @@ int mbedtls_ssl_ticket_parse(void *p_ticket, } #if defined(MBEDTLS_HAVE_TIME) - { - /* Check for expiration */ - mbedtls_time_t current_time = mbedtls_time(NULL); + mbedtls_ms_time_t ticket_creation_time, ticket_age; + mbedtls_ms_time_t ticket_lifetime = + (mbedtls_ms_time_t) key->lifetime * 1000; - if (current_time < session->start || - (uint32_t) (current_time - session->start) > ctx->ticket_lifetime) { - ret = MBEDTLS_ERR_SSL_SESSION_TICKET_EXPIRED; - goto cleanup; - } + ret = mbedtls_ssl_session_get_ticket_creation_time(session, + &ticket_creation_time); + if (ret != 0) { + goto cleanup; + } + + ticket_age = mbedtls_ms_time() - ticket_creation_time; + if (ticket_age < 0 || ticket_age > ticket_lifetime) { + ret = MBEDTLS_ERR_SSL_SESSION_TICKET_EXPIRED; + goto cleanup; } #endif @@ -415,8 +534,13 @@ int mbedtls_ssl_ticket_parse(void *p_ticket, */ void mbedtls_ssl_ticket_free(mbedtls_ssl_ticket_context *ctx) { +#if defined(MBEDTLS_USE_PSA_CRYPTO) + psa_destroy_key(ctx->keys[0].key); + psa_destroy_key(ctx->keys[1].key); +#else mbedtls_cipher_free(&ctx->keys[0].ctx); mbedtls_cipher_free(&ctx->keys[1].ctx); +#endif /* MBEDTLS_USE_PSA_CRYPTO */ #if defined(MBEDTLS_THREADING_C) mbedtls_mutex_free(&ctx->mutex); diff --git a/vendor/mbedtls/library/ssl_tls.c b/vendor/mbedtls/library/ssl_tls.c index 494de1b93e..c5e06491c1 100644 --- a/vendor/mbedtls/library/ssl_tls.c +++ b/vendor/mbedtls/library/ssl_tls.c @@ -1,26 +1,10 @@ /* - * SSLv3/TLSv1 shared functions + * TLS shared functions * * Copyright The Mbed TLS Contributors - * SPDX-License-Identifier: Apache-2.0 - * - * Licensed under the Apache License, Version 2.0 (the "License"); you may - * not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT - * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. + * SPDX-License-Identifier: Apache-2.0 OR GPL-2.0-or-later */ /* - * The SSL 3.0 specification was drafted by Netscape in 1996, - * and became an IETF standard in 1999. - * - * http://wp.netscape.com/eng/ssl3/ * http://www.ietf.org/rfc/rfc2246.txt * http://www.ietf.org/rfc/rfc4346.txt */ @@ -32,8 +16,11 @@ #include "mbedtls/platform.h" #include "mbedtls/ssl.h" -#include "mbedtls/ssl_internal.h" -#include "mbedtls/debug.h" +#include "ssl_client.h" +#include "ssl_debug_helpers.h" +#include "ssl_misc.h" + +#include "debug_internal.h" #include "mbedtls/error.h" #include "mbedtls/platform_util.h" #include "mbedtls/version.h" @@ -43,6 +30,8 @@ #if defined(MBEDTLS_USE_PSA_CRYPTO) #include "mbedtls/psa_util.h" +#include "md_psa.h" +#include "psa_util_internal.h" #include "psa/crypto.h" #endif @@ -50,6 +39,42 @@ #include "mbedtls/oid.h" #endif +#if defined(MBEDTLS_USE_PSA_CRYPTO) +/* Define local translating functions to save code size by not using too many + * arguments in each translating place. */ +static int local_err_translation(psa_status_t status) +{ + return psa_status_to_mbedtls(status, psa_to_ssl_errors, + ARRAY_LENGTH(psa_to_ssl_errors), + psa_generic_status_to_mbedtls); +} +#define PSA_TO_MBEDTLS_ERR(status) local_err_translation(status) +#endif + +#if defined(MBEDTLS_TEST_HOOKS) +static mbedtls_ssl_chk_buf_ptr_args chk_buf_ptr_fail_args; + +void mbedtls_ssl_set_chk_buf_ptr_fail_args( + const uint8_t *cur, const uint8_t *end, size_t need) +{ + chk_buf_ptr_fail_args.cur = cur; + chk_buf_ptr_fail_args.end = end; + chk_buf_ptr_fail_args.need = need; +} + +void mbedtls_ssl_reset_chk_buf_ptr_fail_args(void) +{ + memset(&chk_buf_ptr_fail_args, 0, sizeof(chk_buf_ptr_fail_args)); +} + +int mbedtls_ssl_cmp_chk_buf_ptr_fail_args(mbedtls_ssl_chk_buf_ptr_args *args) +{ + return (chk_buf_ptr_fail_args.cur != args->cur) || + (chk_buf_ptr_fail_args.end != args->end) || + (chk_buf_ptr_fail_args.need != args->need); +} +#endif /* MBEDTLS_TEST_HOOKS */ + #if defined(MBEDTLS_SSL_PROTO_DTLS) #if defined(MBEDTLS_SSL_DTLS_CONNECTION_ID) @@ -105,6 +130,36 @@ int mbedtls_ssl_set_cid(mbedtls_ssl_context *ssl, return 0; } +int mbedtls_ssl_get_own_cid(mbedtls_ssl_context *ssl, + int *enabled, + unsigned char own_cid[MBEDTLS_SSL_CID_OUT_LEN_MAX], + size_t *own_cid_len) +{ + *enabled = MBEDTLS_SSL_CID_DISABLED; + + if (ssl->conf->transport != MBEDTLS_SSL_TRANSPORT_DATAGRAM) { + return MBEDTLS_ERR_SSL_BAD_INPUT_DATA; + } + + /* We report MBEDTLS_SSL_CID_DISABLED in case the CID length is + * zero as this is indistinguishable from not requesting to use + * the CID extension. */ + if (ssl->own_cid_len == 0 || ssl->negotiate_cid == MBEDTLS_SSL_CID_DISABLED) { + return 0; + } + + if (own_cid_len != NULL) { + *own_cid_len = ssl->own_cid_len; + if (own_cid != NULL) { + memcpy(own_cid, ssl->own_cid, ssl->own_cid_len); + } + } + + *enabled = MBEDTLS_SSL_CID_ENABLED; + + return 0; +} + int mbedtls_ssl_get_peer_cid(mbedtls_ssl_context *ssl, int *enabled, unsigned char peer_cid[MBEDTLS_SSL_CID_OUT_LEN_MAX], @@ -113,7 +168,7 @@ int mbedtls_ssl_get_peer_cid(mbedtls_ssl_context *ssl, *enabled = MBEDTLS_SSL_CID_DISABLED; if (ssl->conf->transport != MBEDTLS_SSL_TRANSPORT_DATAGRAM || - ssl->state != MBEDTLS_SSL_HANDSHAKE_OVER) { + mbedtls_ssl_is_handshake_over(ssl) == 0) { return MBEDTLS_ERR_SSL_BAD_INPUT_DATA; } @@ -175,9 +230,17 @@ int mbedtls_ssl_session_copy(mbedtls_ssl_session *dst, { mbedtls_ssl_session_free(dst); memcpy(dst, src, sizeof(mbedtls_ssl_session)); - #if defined(MBEDTLS_SSL_SESSION_TICKETS) && defined(MBEDTLS_SSL_CLI_C) dst->ticket = NULL; +#if defined(MBEDTLS_SSL_PROTO_TLS1_3) && \ + defined(MBEDTLS_SSL_SERVER_NAME_INDICATION) + dst->hostname = NULL; +#endif +#endif /* MBEDTLS_SSL_SESSION_TICKETS && MBEDTLS_SSL_CLI_C */ + +#if defined(MBEDTLS_SSL_SRV_C) && defined(MBEDTLS_SSL_ALPN) && \ + defined(MBEDTLS_SSL_EARLY_DATA) + dst->ticket_alpn = NULL; #endif #if defined(MBEDTLS_X509_CRT_PARSE_C) @@ -217,6 +280,16 @@ int mbedtls_ssl_session_copy(mbedtls_ssl_session *dst, #endif /* MBEDTLS_X509_CRT_PARSE_C */ +#if defined(MBEDTLS_SSL_SRV_C) && defined(MBEDTLS_SSL_ALPN) && \ + defined(MBEDTLS_SSL_EARLY_DATA) + { + int ret = mbedtls_ssl_session_set_ticket_alpn(dst, src->ticket_alpn); + if (ret != 0) { + return ret; + } + } +#endif /* MBEDTLS_SSL_SRV_C && MBEDTLS_SSL_ALPN && MBEDTLS_SSL_EARLY_DATA */ + #if defined(MBEDTLS_SSL_SESSION_TICKETS) && defined(MBEDTLS_SSL_CLI_C) if (src->ticket != NULL) { dst->ticket = mbedtls_calloc(1, src->ticket_len); @@ -226,6 +299,18 @@ int mbedtls_ssl_session_copy(mbedtls_ssl_session *dst, memcpy(dst->ticket, src->ticket, src->ticket_len); } + +#if defined(MBEDTLS_SSL_PROTO_TLS1_3) && \ + defined(MBEDTLS_SSL_SERVER_NAME_INDICATION) + if (src->endpoint == MBEDTLS_SSL_IS_CLIENT) { + int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED; + ret = mbedtls_ssl_session_set_hostname(dst, src->hostname); + if (ret != 0) { + return ret; + } + } +#endif /* MBEDTLS_SSL_PROTO_TLS1_3 && + MBEDTLS_SSL_SERVER_NAME_INDICATION */ #endif /* MBEDTLS_SSL_SESSION_TICKETS && MBEDTLS_SSL_CLI_C */ return 0; @@ -237,7 +322,7 @@ static int resize_buffer(unsigned char **buffer, size_t len_new, size_t *len_old { unsigned char *resized_buffer = mbedtls_calloc(1, len_new); if (resized_buffer == NULL) { - return -1; + return MBEDTLS_ERR_SSL_ALLOC_FAILED; } /* We want to copy len_new bytes when downsizing the buffer, and @@ -246,8 +331,7 @@ static int resize_buffer(unsigned char **buffer, size_t len_new, size_t *len_old * lost, are done outside of this function. */ memcpy(resized_buffer, *buffer, (len_new < *len_old) ? len_new : *len_old); - mbedtls_platform_zeroize(*buffer, *len_old); - mbedtls_free(*buffer); + mbedtls_zeroize_and_free(*buffer, *len_old); *buffer = resized_buffer; *len_old = len_new; @@ -311,7199 +395,8933 @@ static void handle_buffer_resizing(mbedtls_ssl_context *ssl, int downsizing, } #endif /* MBEDTLS_SSL_VARIABLE_BUFFER_LENGTH */ -/* - * Key material generation - */ -#if defined(MBEDTLS_SSL_PROTO_SSL3) -MBEDTLS_CHECK_RETURN_CRITICAL -static int ssl3_prf(const unsigned char *secret, size_t slen, - const char *label, - const unsigned char *random, size_t rlen, - unsigned char *dstbuf, size_t dlen) -{ - int ret = 0; - size_t i; - mbedtls_md5_context md5; - mbedtls_sha1_context sha1; - unsigned char padding[16]; - unsigned char sha1sum[20]; - ((void) label); +#if defined(MBEDTLS_SSL_PROTO_TLS1_2) - mbedtls_md5_init(&md5); - mbedtls_sha1_init(&sha1); +#if defined(MBEDTLS_SSL_CONTEXT_SERIALIZATION) +typedef int (*tls_prf_fn)(const unsigned char *secret, size_t slen, + const char *label, + const unsigned char *random, size_t rlen, + unsigned char *dstbuf, size_t dlen); - /* - * SSLv3: - * block = - * MD5( secret + SHA1( 'A' + secret + random ) ) + - * MD5( secret + SHA1( 'BB' + secret + random ) ) + - * MD5( secret + SHA1( 'CCC' + secret + random ) ) + - * ... - */ - for (i = 0; i < dlen / 16; i++) { - memset(padding, (unsigned char) ('A' + i), 1 + i); +static tls_prf_fn ssl_tls12prf_from_cs(int ciphersuite_id); - if ((ret = mbedtls_sha1_starts_ret(&sha1)) != 0) { - goto exit; - } - if ((ret = mbedtls_sha1_update_ret(&sha1, padding, 1 + i)) != 0) { - goto exit; - } - if ((ret = mbedtls_sha1_update_ret(&sha1, secret, slen)) != 0) { - goto exit; - } - if ((ret = mbedtls_sha1_update_ret(&sha1, random, rlen)) != 0) { - goto exit; - } - if ((ret = mbedtls_sha1_finish_ret(&sha1, sha1sum)) != 0) { - goto exit; - } +#endif /* MBEDTLS_SSL_CONTEXT_SERIALIZATION */ - if ((ret = mbedtls_md5_starts_ret(&md5)) != 0) { - goto exit; - } - if ((ret = mbedtls_md5_update_ret(&md5, secret, slen)) != 0) { - goto exit; - } - if ((ret = mbedtls_md5_update_ret(&md5, sha1sum, 20)) != 0) { - goto exit; - } - if ((ret = mbedtls_md5_finish_ret(&md5, dstbuf + i * 16)) != 0) { - goto exit; - } - } +/* Type for the TLS PRF */ +typedef int ssl_tls_prf_t(const unsigned char *, size_t, const char *, + const unsigned char *, size_t, + unsigned char *, size_t); -exit: - mbedtls_md5_free(&md5); - mbedtls_sha1_free(&sha1); +MBEDTLS_CHECK_RETURN_CRITICAL +static int ssl_tls12_populate_transform(mbedtls_ssl_transform *transform, + int ciphersuite, + const unsigned char master[48], +#if defined(MBEDTLS_SSL_SOME_SUITES_USE_CBC_ETM) + int encrypt_then_mac, +#endif /* MBEDTLS_SSL_SOME_SUITES_USE_CBC_ETM */ + ssl_tls_prf_t tls_prf, + const unsigned char randbytes[64], + mbedtls_ssl_protocol_version tls_version, + unsigned endpoint, + const mbedtls_ssl_context *ssl); + +#if defined(MBEDTLS_MD_CAN_SHA256) +MBEDTLS_CHECK_RETURN_CRITICAL +static int tls_prf_sha256(const unsigned char *secret, size_t slen, + const char *label, + const unsigned char *random, size_t rlen, + unsigned char *dstbuf, size_t dlen); +static int ssl_calc_verify_tls_sha256(const mbedtls_ssl_context *, unsigned char *, size_t *); +static int ssl_calc_finished_tls_sha256(mbedtls_ssl_context *, unsigned char *, int); - mbedtls_platform_zeroize(padding, sizeof(padding)); - mbedtls_platform_zeroize(sha1sum, sizeof(sha1sum)); +#endif /* MBEDTLS_MD_CAN_SHA256*/ - return ret; -} -#endif /* MBEDTLS_SSL_PROTO_SSL3 */ +#if defined(MBEDTLS_MD_CAN_SHA384) +MBEDTLS_CHECK_RETURN_CRITICAL +static int tls_prf_sha384(const unsigned char *secret, size_t slen, + const char *label, + const unsigned char *random, size_t rlen, + unsigned char *dstbuf, size_t dlen); + +static int ssl_calc_verify_tls_sha384(const mbedtls_ssl_context *, unsigned char *, size_t *); +static int ssl_calc_finished_tls_sha384(mbedtls_ssl_context *, unsigned char *, int); +#endif /* MBEDTLS_MD_CAN_SHA384*/ -#if defined(MBEDTLS_SSL_PROTO_TLS1) || defined(MBEDTLS_SSL_PROTO_TLS1_1) MBEDTLS_CHECK_RETURN_CRITICAL -static int tls1_prf(const unsigned char *secret, size_t slen, - const char *label, - const unsigned char *random, size_t rlen, - unsigned char *dstbuf, size_t dlen) -{ - size_t nb, hs; - size_t i, j, k; - const unsigned char *S1, *S2; - unsigned char *tmp; - size_t tmp_len = 0; - unsigned char h_i[20]; - const mbedtls_md_info_t *md_info; - mbedtls_md_context_t md_ctx; - int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED; +static int ssl_tls12_session_load(mbedtls_ssl_session *session, + const unsigned char *buf, + size_t len); +#endif /* MBEDTLS_SSL_PROTO_TLS1_2 */ - mbedtls_md_init(&md_ctx); +static int ssl_update_checksum_start(mbedtls_ssl_context *, const unsigned char *, size_t); - tmp_len = 20 + strlen(label) + rlen; - tmp = mbedtls_calloc(1, tmp_len); - if (tmp == NULL) { - ret = MBEDTLS_ERR_SSL_ALLOC_FAILED; - goto exit; - } +#if defined(MBEDTLS_MD_CAN_SHA256) +static int ssl_update_checksum_sha256(mbedtls_ssl_context *, const unsigned char *, size_t); +#endif /* MBEDTLS_MD_CAN_SHA256*/ - hs = (slen + 1) / 2; - S1 = secret; - S2 = secret + slen - hs; +#if defined(MBEDTLS_MD_CAN_SHA384) +static int ssl_update_checksum_sha384(mbedtls_ssl_context *, const unsigned char *, size_t); +#endif /* MBEDTLS_MD_CAN_SHA384*/ - nb = strlen(label); - memcpy(tmp + 20, label, nb); - memcpy(tmp + 20 + nb, random, rlen); - nb += rlen; +int mbedtls_ssl_tls_prf(const mbedtls_tls_prf_types prf, + const unsigned char *secret, size_t slen, + const char *label, + const unsigned char *random, size_t rlen, + unsigned char *dstbuf, size_t dlen) +{ + mbedtls_ssl_tls_prf_cb *tls_prf = NULL; - /* - * First compute P_md5(secret,label+random)[0..dlen] - */ - if ((md_info = mbedtls_md_info_from_type(MBEDTLS_MD_MD5)) == NULL) { - ret = MBEDTLS_ERR_SSL_INTERNAL_ERROR; - goto exit; + switch (prf) { +#if defined(MBEDTLS_SSL_PROTO_TLS1_2) +#if defined(MBEDTLS_MD_CAN_SHA384) + case MBEDTLS_SSL_TLS_PRF_SHA384: + tls_prf = tls_prf_sha384; + break; +#endif /* MBEDTLS_MD_CAN_SHA384*/ +#if defined(MBEDTLS_MD_CAN_SHA256) + case MBEDTLS_SSL_TLS_PRF_SHA256: + tls_prf = tls_prf_sha256; + break; +#endif /* MBEDTLS_MD_CAN_SHA256*/ +#endif /* MBEDTLS_SSL_PROTO_TLS1_2 */ + default: + return MBEDTLS_ERR_SSL_FEATURE_UNAVAILABLE; } - if ((ret = mbedtls_md_setup(&md_ctx, md_info, 1)) != 0) { - goto exit; - } + return tls_prf(secret, slen, label, random, rlen, dstbuf, dlen); +} - ret = mbedtls_md_hmac_starts(&md_ctx, S1, hs); - if (ret != 0) { - goto exit; - } - ret = mbedtls_md_hmac_update(&md_ctx, tmp + 20, nb); - if (ret != 0) { - goto exit; +#if defined(MBEDTLS_X509_CRT_PARSE_C) +static void ssl_clear_peer_cert(mbedtls_ssl_session *session) +{ +#if defined(MBEDTLS_SSL_KEEP_PEER_CERTIFICATE) + if (session->peer_cert != NULL) { + mbedtls_x509_crt_free(session->peer_cert); + mbedtls_free(session->peer_cert); + session->peer_cert = NULL; } - ret = mbedtls_md_hmac_finish(&md_ctx, 4 + tmp); - if (ret != 0) { - goto exit; +#else /* MBEDTLS_SSL_KEEP_PEER_CERTIFICATE */ + if (session->peer_cert_digest != NULL) { + /* Zeroization is not necessary. */ + mbedtls_free(session->peer_cert_digest); + session->peer_cert_digest = NULL; + session->peer_cert_digest_type = MBEDTLS_MD_NONE; + session->peer_cert_digest_len = 0; } +#endif /* !MBEDTLS_SSL_KEEP_PEER_CERTIFICATE */ +} +#endif /* MBEDTLS_X509_CRT_PARSE_C */ - for (i = 0; i < dlen; i += 16) { - ret = mbedtls_md_hmac_reset(&md_ctx); - if (ret != 0) { - goto exit; - } - ret = mbedtls_md_hmac_update(&md_ctx, 4 + tmp, 16 + nb); - if (ret != 0) { - goto exit; - } - ret = mbedtls_md_hmac_finish(&md_ctx, h_i); - if (ret != 0) { - goto exit; - } +uint32_t mbedtls_ssl_get_extension_id(unsigned int extension_type) +{ + switch (extension_type) { + case MBEDTLS_TLS_EXT_SERVERNAME: + return MBEDTLS_SSL_EXT_ID_SERVERNAME; - ret = mbedtls_md_hmac_reset(&md_ctx); - if (ret != 0) { - goto exit; - } - ret = mbedtls_md_hmac_update(&md_ctx, 4 + tmp, 16); - if (ret != 0) { - goto exit; - } - ret = mbedtls_md_hmac_finish(&md_ctx, 4 + tmp); - if (ret != 0) { - goto exit; - } + case MBEDTLS_TLS_EXT_MAX_FRAGMENT_LENGTH: + return MBEDTLS_SSL_EXT_ID_MAX_FRAGMENT_LENGTH; - k = (i + 16 > dlen) ? dlen % 16 : 16; + case MBEDTLS_TLS_EXT_STATUS_REQUEST: + return MBEDTLS_SSL_EXT_ID_STATUS_REQUEST; - for (j = 0; j < k; j++) { - dstbuf[i + j] = h_i[j]; - } - } + case MBEDTLS_TLS_EXT_SUPPORTED_GROUPS: + return MBEDTLS_SSL_EXT_ID_SUPPORTED_GROUPS; - mbedtls_md_free(&md_ctx); + case MBEDTLS_TLS_EXT_SIG_ALG: + return MBEDTLS_SSL_EXT_ID_SIG_ALG; - /* - * XOR out with P_sha1(secret,label+random)[0..dlen] - */ - if ((md_info = mbedtls_md_info_from_type(MBEDTLS_MD_SHA1)) == NULL) { - ret = MBEDTLS_ERR_SSL_INTERNAL_ERROR; - goto exit; - } + case MBEDTLS_TLS_EXT_USE_SRTP: + return MBEDTLS_SSL_EXT_ID_USE_SRTP; - if ((ret = mbedtls_md_setup(&md_ctx, md_info, 1)) != 0) { - goto exit; - } + case MBEDTLS_TLS_EXT_HEARTBEAT: + return MBEDTLS_SSL_EXT_ID_HEARTBEAT; - ret = mbedtls_md_hmac_starts(&md_ctx, S2, hs); - if (ret != 0) { - goto exit; - } - ret = mbedtls_md_hmac_update(&md_ctx, tmp + 20, nb); - if (ret != 0) { - goto exit; - } - ret = mbedtls_md_hmac_finish(&md_ctx, tmp); - if (ret != 0) { - goto exit; - } + case MBEDTLS_TLS_EXT_ALPN: + return MBEDTLS_SSL_EXT_ID_ALPN; - for (i = 0; i < dlen; i += 20) { - ret = mbedtls_md_hmac_reset(&md_ctx); - if (ret != 0) { - goto exit; - } - ret = mbedtls_md_hmac_update(&md_ctx, tmp, 20 + nb); - if (ret != 0) { - goto exit; - } - ret = mbedtls_md_hmac_finish(&md_ctx, h_i); - if (ret != 0) { - goto exit; - } + case MBEDTLS_TLS_EXT_SCT: + return MBEDTLS_SSL_EXT_ID_SCT; - ret = mbedtls_md_hmac_reset(&md_ctx); - if (ret != 0) { - goto exit; - } - ret = mbedtls_md_hmac_update(&md_ctx, tmp, 20); - if (ret != 0) { - goto exit; - } - ret = mbedtls_md_hmac_finish(&md_ctx, tmp); - if (ret != 0) { - goto exit; - } + case MBEDTLS_TLS_EXT_CLI_CERT_TYPE: + return MBEDTLS_SSL_EXT_ID_CLI_CERT_TYPE; - k = (i + 20 > dlen) ? dlen % 20 : 20; + case MBEDTLS_TLS_EXT_SERV_CERT_TYPE: + return MBEDTLS_SSL_EXT_ID_SERV_CERT_TYPE; - for (j = 0; j < k; j++) { - dstbuf[i + j] = (unsigned char) (dstbuf[i + j] ^ h_i[j]); - } - } + case MBEDTLS_TLS_EXT_PADDING: + return MBEDTLS_SSL_EXT_ID_PADDING; -exit: - mbedtls_md_free(&md_ctx); + case MBEDTLS_TLS_EXT_PRE_SHARED_KEY: + return MBEDTLS_SSL_EXT_ID_PRE_SHARED_KEY; - mbedtls_platform_zeroize(tmp, tmp_len); - mbedtls_platform_zeroize(h_i, sizeof(h_i)); + case MBEDTLS_TLS_EXT_EARLY_DATA: + return MBEDTLS_SSL_EXT_ID_EARLY_DATA; - mbedtls_free(tmp); - return ret; -} -#endif /* MBEDTLS_SSL_PROTO_TLS1) || MBEDTLS_SSL_PROTO_TLS1_1 */ + case MBEDTLS_TLS_EXT_SUPPORTED_VERSIONS: + return MBEDTLS_SSL_EXT_ID_SUPPORTED_VERSIONS; -#if defined(MBEDTLS_SSL_PROTO_TLS1_2) -#if defined(MBEDTLS_USE_PSA_CRYPTO) + case MBEDTLS_TLS_EXT_COOKIE: + return MBEDTLS_SSL_EXT_ID_COOKIE; -static psa_status_t setup_psa_key_derivation(psa_key_derivation_operation_t *derivation, - psa_key_id_t key, - psa_algorithm_t alg, - const unsigned char *seed, size_t seed_length, - const unsigned char *label, size_t label_length, - size_t capacity) -{ - psa_status_t status; - - status = psa_key_derivation_setup(derivation, alg); - if (status != PSA_SUCCESS) { - return status; - } - - if (PSA_ALG_IS_TLS12_PRF(alg) || PSA_ALG_IS_TLS12_PSK_TO_MS(alg)) { - status = psa_key_derivation_input_bytes(derivation, - PSA_KEY_DERIVATION_INPUT_SEED, - seed, seed_length); - if (status != PSA_SUCCESS) { - return status; - } + case MBEDTLS_TLS_EXT_PSK_KEY_EXCHANGE_MODES: + return MBEDTLS_SSL_EXT_ID_PSK_KEY_EXCHANGE_MODES; - if (mbedtls_svc_key_id_is_null(key)) { - status = psa_key_derivation_input_bytes( - derivation, PSA_KEY_DERIVATION_INPUT_SECRET, - NULL, 0); - } else { - status = psa_key_derivation_input_key( - derivation, PSA_KEY_DERIVATION_INPUT_SECRET, key); - } - if (status != PSA_SUCCESS) { - return status; - } + case MBEDTLS_TLS_EXT_CERT_AUTH: + return MBEDTLS_SSL_EXT_ID_CERT_AUTH; - status = psa_key_derivation_input_bytes(derivation, - PSA_KEY_DERIVATION_INPUT_LABEL, - label, label_length); - if (status != PSA_SUCCESS) { - return status; - } - } else { - return PSA_ERROR_NOT_SUPPORTED; - } + case MBEDTLS_TLS_EXT_OID_FILTERS: + return MBEDTLS_SSL_EXT_ID_OID_FILTERS; - status = psa_key_derivation_set_capacity(derivation, capacity); - if (status != PSA_SUCCESS) { - return status; - } + case MBEDTLS_TLS_EXT_POST_HANDSHAKE_AUTH: + return MBEDTLS_SSL_EXT_ID_POST_HANDSHAKE_AUTH; - return PSA_SUCCESS; -} + case MBEDTLS_TLS_EXT_SIG_ALG_CERT: + return MBEDTLS_SSL_EXT_ID_SIG_ALG_CERT; -MBEDTLS_CHECK_RETURN_CRITICAL -static int tls_prf_generic(mbedtls_md_type_t md_type, - const unsigned char *secret, size_t slen, - const char *label, - const unsigned char *random, size_t rlen, - unsigned char *dstbuf, size_t dlen) -{ - psa_status_t status; - psa_algorithm_t alg; - psa_key_id_t master_key = MBEDTLS_SVC_KEY_ID_INIT; - psa_key_derivation_operation_t derivation = - PSA_KEY_DERIVATION_OPERATION_INIT; + case MBEDTLS_TLS_EXT_KEY_SHARE: + return MBEDTLS_SSL_EXT_ID_KEY_SHARE; - if (md_type == MBEDTLS_MD_SHA384) { - alg = PSA_ALG_TLS12_PRF(PSA_ALG_SHA_384); - } else { - alg = PSA_ALG_TLS12_PRF(PSA_ALG_SHA_256); - } + case MBEDTLS_TLS_EXT_TRUNCATED_HMAC: + return MBEDTLS_SSL_EXT_ID_TRUNCATED_HMAC; - /* Normally a "secret" should be long enough to be impossible to - * find by brute force, and in particular should not be empty. But - * this PRF is also used to derive an IV, in particular in EAP-TLS, - * and for this use case it makes sense to have a 0-length "secret". - * Since the key API doesn't allow importing a key of length 0, - * keep master_key=0, which setup_psa_key_derivation() understands - * to mean a 0-length "secret" input. */ - if (slen != 0) { - psa_key_attributes_t key_attributes = psa_key_attributes_init(); - psa_set_key_usage_flags(&key_attributes, PSA_KEY_USAGE_DERIVE); - psa_set_key_algorithm(&key_attributes, alg); - psa_set_key_type(&key_attributes, PSA_KEY_TYPE_DERIVE); + case MBEDTLS_TLS_EXT_SUPPORTED_POINT_FORMATS: + return MBEDTLS_SSL_EXT_ID_SUPPORTED_POINT_FORMATS; - status = psa_import_key(&key_attributes, secret, slen, &master_key); - if (status != PSA_SUCCESS) { - return MBEDTLS_ERR_SSL_HW_ACCEL_FAILED; - } - } + case MBEDTLS_TLS_EXT_ENCRYPT_THEN_MAC: + return MBEDTLS_SSL_EXT_ID_ENCRYPT_THEN_MAC; - status = setup_psa_key_derivation(&derivation, - master_key, alg, - random, rlen, - (unsigned char const *) label, - (size_t) strlen(label), - dlen); - if (status != PSA_SUCCESS) { - psa_key_derivation_abort(&derivation); - psa_destroy_key(master_key); - return MBEDTLS_ERR_SSL_HW_ACCEL_FAILED; - } + case MBEDTLS_TLS_EXT_EXTENDED_MASTER_SECRET: + return MBEDTLS_SSL_EXT_ID_EXTENDED_MASTER_SECRET; - status = psa_key_derivation_output_bytes(&derivation, dstbuf, dlen); - if (status != PSA_SUCCESS) { - psa_key_derivation_abort(&derivation); - psa_destroy_key(master_key); - return MBEDTLS_ERR_SSL_HW_ACCEL_FAILED; - } + case MBEDTLS_TLS_EXT_RECORD_SIZE_LIMIT: + return MBEDTLS_SSL_EXT_ID_RECORD_SIZE_LIMIT; - status = psa_key_derivation_abort(&derivation); - if (status != PSA_SUCCESS) { - psa_destroy_key(master_key); - return MBEDTLS_ERR_SSL_HW_ACCEL_FAILED; - } + case MBEDTLS_TLS_EXT_SESSION_TICKET: + return MBEDTLS_SSL_EXT_ID_SESSION_TICKET; - if (!mbedtls_svc_key_id_is_null(master_key)) { - status = psa_destroy_key(master_key); - } - if (status != PSA_SUCCESS) { - return MBEDTLS_ERR_SSL_HW_ACCEL_FAILED; } - return 0; + return MBEDTLS_SSL_EXT_ID_UNRECOGNIZED; } -#else /* MBEDTLS_USE_PSA_CRYPTO */ - -MBEDTLS_CHECK_RETURN_CRITICAL -static int tls_prf_generic(mbedtls_md_type_t md_type, - const unsigned char *secret, size_t slen, - const char *label, - const unsigned char *random, size_t rlen, - unsigned char *dstbuf, size_t dlen) +uint32_t mbedtls_ssl_get_extension_mask(unsigned int extension_type) { - size_t nb; - size_t i, j, k, md_len; - unsigned char *tmp; - size_t tmp_len = 0; - unsigned char h_i[MBEDTLS_MD_MAX_SIZE]; - const mbedtls_md_info_t *md_info; - mbedtls_md_context_t md_ctx; - int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED; + return 1 << mbedtls_ssl_get_extension_id(extension_type); +} - mbedtls_md_init(&md_ctx); +#if defined(MBEDTLS_DEBUG_C) +static const char *extension_name_table[] = { + [MBEDTLS_SSL_EXT_ID_UNRECOGNIZED] = "unrecognized", + [MBEDTLS_SSL_EXT_ID_SERVERNAME] = "server_name", + [MBEDTLS_SSL_EXT_ID_MAX_FRAGMENT_LENGTH] = "max_fragment_length", + [MBEDTLS_SSL_EXT_ID_STATUS_REQUEST] = "status_request", + [MBEDTLS_SSL_EXT_ID_SUPPORTED_GROUPS] = "supported_groups", + [MBEDTLS_SSL_EXT_ID_SIG_ALG] = "signature_algorithms", + [MBEDTLS_SSL_EXT_ID_USE_SRTP] = "use_srtp", + [MBEDTLS_SSL_EXT_ID_HEARTBEAT] = "heartbeat", + [MBEDTLS_SSL_EXT_ID_ALPN] = "application_layer_protocol_negotiation", + [MBEDTLS_SSL_EXT_ID_SCT] = "signed_certificate_timestamp", + [MBEDTLS_SSL_EXT_ID_CLI_CERT_TYPE] = "client_certificate_type", + [MBEDTLS_SSL_EXT_ID_SERV_CERT_TYPE] = "server_certificate_type", + [MBEDTLS_SSL_EXT_ID_PADDING] = "padding", + [MBEDTLS_SSL_EXT_ID_PRE_SHARED_KEY] = "pre_shared_key", + [MBEDTLS_SSL_EXT_ID_EARLY_DATA] = "early_data", + [MBEDTLS_SSL_EXT_ID_SUPPORTED_VERSIONS] = "supported_versions", + [MBEDTLS_SSL_EXT_ID_COOKIE] = "cookie", + [MBEDTLS_SSL_EXT_ID_PSK_KEY_EXCHANGE_MODES] = "psk_key_exchange_modes", + [MBEDTLS_SSL_EXT_ID_CERT_AUTH] = "certificate_authorities", + [MBEDTLS_SSL_EXT_ID_OID_FILTERS] = "oid_filters", + [MBEDTLS_SSL_EXT_ID_POST_HANDSHAKE_AUTH] = "post_handshake_auth", + [MBEDTLS_SSL_EXT_ID_SIG_ALG_CERT] = "signature_algorithms_cert", + [MBEDTLS_SSL_EXT_ID_KEY_SHARE] = "key_share", + [MBEDTLS_SSL_EXT_ID_TRUNCATED_HMAC] = "truncated_hmac", + [MBEDTLS_SSL_EXT_ID_SUPPORTED_POINT_FORMATS] = "supported_point_formats", + [MBEDTLS_SSL_EXT_ID_ENCRYPT_THEN_MAC] = "encrypt_then_mac", + [MBEDTLS_SSL_EXT_ID_EXTENDED_MASTER_SECRET] = "extended_master_secret", + [MBEDTLS_SSL_EXT_ID_SESSION_TICKET] = "session_ticket", + [MBEDTLS_SSL_EXT_ID_RECORD_SIZE_LIMIT] = "record_size_limit" +}; - if ((md_info = mbedtls_md_info_from_type(md_type)) == NULL) { - return MBEDTLS_ERR_SSL_INTERNAL_ERROR; - } +static const unsigned int extension_type_table[] = { + [MBEDTLS_SSL_EXT_ID_UNRECOGNIZED] = 0xff, + [MBEDTLS_SSL_EXT_ID_SERVERNAME] = MBEDTLS_TLS_EXT_SERVERNAME, + [MBEDTLS_SSL_EXT_ID_MAX_FRAGMENT_LENGTH] = MBEDTLS_TLS_EXT_MAX_FRAGMENT_LENGTH, + [MBEDTLS_SSL_EXT_ID_STATUS_REQUEST] = MBEDTLS_TLS_EXT_STATUS_REQUEST, + [MBEDTLS_SSL_EXT_ID_SUPPORTED_GROUPS] = MBEDTLS_TLS_EXT_SUPPORTED_GROUPS, + [MBEDTLS_SSL_EXT_ID_SIG_ALG] = MBEDTLS_TLS_EXT_SIG_ALG, + [MBEDTLS_SSL_EXT_ID_USE_SRTP] = MBEDTLS_TLS_EXT_USE_SRTP, + [MBEDTLS_SSL_EXT_ID_HEARTBEAT] = MBEDTLS_TLS_EXT_HEARTBEAT, + [MBEDTLS_SSL_EXT_ID_ALPN] = MBEDTLS_TLS_EXT_ALPN, + [MBEDTLS_SSL_EXT_ID_SCT] = MBEDTLS_TLS_EXT_SCT, + [MBEDTLS_SSL_EXT_ID_CLI_CERT_TYPE] = MBEDTLS_TLS_EXT_CLI_CERT_TYPE, + [MBEDTLS_SSL_EXT_ID_SERV_CERT_TYPE] = MBEDTLS_TLS_EXT_SERV_CERT_TYPE, + [MBEDTLS_SSL_EXT_ID_PADDING] = MBEDTLS_TLS_EXT_PADDING, + [MBEDTLS_SSL_EXT_ID_PRE_SHARED_KEY] = MBEDTLS_TLS_EXT_PRE_SHARED_KEY, + [MBEDTLS_SSL_EXT_ID_EARLY_DATA] = MBEDTLS_TLS_EXT_EARLY_DATA, + [MBEDTLS_SSL_EXT_ID_SUPPORTED_VERSIONS] = MBEDTLS_TLS_EXT_SUPPORTED_VERSIONS, + [MBEDTLS_SSL_EXT_ID_COOKIE] = MBEDTLS_TLS_EXT_COOKIE, + [MBEDTLS_SSL_EXT_ID_PSK_KEY_EXCHANGE_MODES] = MBEDTLS_TLS_EXT_PSK_KEY_EXCHANGE_MODES, + [MBEDTLS_SSL_EXT_ID_CERT_AUTH] = MBEDTLS_TLS_EXT_CERT_AUTH, + [MBEDTLS_SSL_EXT_ID_OID_FILTERS] = MBEDTLS_TLS_EXT_OID_FILTERS, + [MBEDTLS_SSL_EXT_ID_POST_HANDSHAKE_AUTH] = MBEDTLS_TLS_EXT_POST_HANDSHAKE_AUTH, + [MBEDTLS_SSL_EXT_ID_SIG_ALG_CERT] = MBEDTLS_TLS_EXT_SIG_ALG_CERT, + [MBEDTLS_SSL_EXT_ID_KEY_SHARE] = MBEDTLS_TLS_EXT_KEY_SHARE, + [MBEDTLS_SSL_EXT_ID_TRUNCATED_HMAC] = MBEDTLS_TLS_EXT_TRUNCATED_HMAC, + [MBEDTLS_SSL_EXT_ID_SUPPORTED_POINT_FORMATS] = MBEDTLS_TLS_EXT_SUPPORTED_POINT_FORMATS, + [MBEDTLS_SSL_EXT_ID_ENCRYPT_THEN_MAC] = MBEDTLS_TLS_EXT_ENCRYPT_THEN_MAC, + [MBEDTLS_SSL_EXT_ID_EXTENDED_MASTER_SECRET] = MBEDTLS_TLS_EXT_EXTENDED_MASTER_SECRET, + [MBEDTLS_SSL_EXT_ID_SESSION_TICKET] = MBEDTLS_TLS_EXT_SESSION_TICKET, + [MBEDTLS_SSL_EXT_ID_RECORD_SIZE_LIMIT] = MBEDTLS_TLS_EXT_RECORD_SIZE_LIMIT +}; - md_len = mbedtls_md_get_size(md_info); +const char *mbedtls_ssl_get_extension_name(unsigned int extension_type) +{ + return extension_name_table[ + mbedtls_ssl_get_extension_id(extension_type)]; +} + +static const char *ssl_tls13_get_hs_msg_name(int hs_msg_type) +{ + switch (hs_msg_type) { + case MBEDTLS_SSL_HS_CLIENT_HELLO: + return "ClientHello"; + case MBEDTLS_SSL_HS_SERVER_HELLO: + return "ServerHello"; + case MBEDTLS_SSL_TLS1_3_HS_HELLO_RETRY_REQUEST: + return "HelloRetryRequest"; + case MBEDTLS_SSL_HS_NEW_SESSION_TICKET: + return "NewSessionTicket"; + case MBEDTLS_SSL_HS_ENCRYPTED_EXTENSIONS: + return "EncryptedExtensions"; + case MBEDTLS_SSL_HS_CERTIFICATE: + return "Certificate"; + case MBEDTLS_SSL_HS_CERTIFICATE_REQUEST: + return "CertificateRequest"; + } + return "Unknown"; +} + +void mbedtls_ssl_print_extension(const mbedtls_ssl_context *ssl, + int level, const char *file, int line, + int hs_msg_type, unsigned int extension_type, + const char *extra_msg0, const char *extra_msg1) +{ + const char *extra_msg; + if (extra_msg0 && extra_msg1) { + mbedtls_debug_print_msg( + ssl, level, file, line, + "%s: %s(%u) extension %s %s.", + ssl_tls13_get_hs_msg_name(hs_msg_type), + mbedtls_ssl_get_extension_name(extension_type), + extension_type, + extra_msg0, extra_msg1); + return; + } - tmp_len = md_len + strlen(label) + rlen; - tmp = mbedtls_calloc(1, tmp_len); - if (tmp == NULL) { - ret = MBEDTLS_ERR_SSL_ALLOC_FAILED; - goto exit; + extra_msg = extra_msg0 ? extra_msg0 : extra_msg1; + if (extra_msg) { + mbedtls_debug_print_msg( + ssl, level, file, line, + "%s: %s(%u) extension %s.", ssl_tls13_get_hs_msg_name(hs_msg_type), + mbedtls_ssl_get_extension_name(extension_type), extension_type, + extra_msg); + return; } - nb = strlen(label); - memcpy(tmp + md_len, label, nb); - memcpy(tmp + md_len + nb, random, rlen); - nb += rlen; + mbedtls_debug_print_msg( + ssl, level, file, line, + "%s: %s(%u) extension.", ssl_tls13_get_hs_msg_name(hs_msg_type), + mbedtls_ssl_get_extension_name(extension_type), extension_type); +} - /* - * Compute P_(secret, label + random)[0..dlen] - */ - if ((ret = mbedtls_md_setup(&md_ctx, md_info, 1)) != 0) { - goto exit; - } +void mbedtls_ssl_print_extensions(const mbedtls_ssl_context *ssl, + int level, const char *file, int line, + int hs_msg_type, uint32_t extensions_mask, + const char *extra) +{ - ret = mbedtls_md_hmac_starts(&md_ctx, secret, slen); - if (ret != 0) { - goto exit; - } - ret = mbedtls_md_hmac_update(&md_ctx, tmp + md_len, nb); - if (ret != 0) { - goto exit; - } - ret = mbedtls_md_hmac_finish(&md_ctx, tmp); - if (ret != 0) { - goto exit; + for (unsigned i = 0; + i < sizeof(extension_name_table) / sizeof(extension_name_table[0]); + i++) { + mbedtls_ssl_print_extension( + ssl, level, file, line, hs_msg_type, extension_type_table[i], + extensions_mask & (1 << i) ? "exists" : "does not exist", extra); } +} - for (i = 0; i < dlen; i += md_len) { - ret = mbedtls_md_hmac_reset(&md_ctx); - if (ret != 0) { - goto exit; - } - ret = mbedtls_md_hmac_update(&md_ctx, tmp, md_len + nb); - if (ret != 0) { - goto exit; - } - ret = mbedtls_md_hmac_finish(&md_ctx, h_i); - if (ret != 0) { - goto exit; - } +#if defined(MBEDTLS_SSL_PROTO_TLS1_3) && defined(MBEDTLS_SSL_SESSION_TICKETS) +static const char *ticket_flag_name_table[] = +{ + [0] = "ALLOW_PSK_RESUMPTION", + [2] = "ALLOW_PSK_EPHEMERAL_RESUMPTION", + [3] = "ALLOW_EARLY_DATA", +}; - ret = mbedtls_md_hmac_reset(&md_ctx); - if (ret != 0) { - goto exit; - } - ret = mbedtls_md_hmac_update(&md_ctx, tmp, md_len); - if (ret != 0) { - goto exit; - } - ret = mbedtls_md_hmac_finish(&md_ctx, tmp); - if (ret != 0) { - goto exit; - } +void mbedtls_ssl_print_ticket_flags(const mbedtls_ssl_context *ssl, + int level, const char *file, int line, + unsigned int flags) +{ + size_t i; - k = (i + md_len > dlen) ? dlen % md_len : md_len; + mbedtls_debug_print_msg(ssl, level, file, line, + "print ticket_flags (0x%02x)", flags); - for (j = 0; j < k; j++) { - dstbuf[i + j] = h_i[j]; + flags = flags & MBEDTLS_SSL_TLS1_3_TICKET_FLAGS_MASK; + + for (i = 0; i < ARRAY_LENGTH(ticket_flag_name_table); i++) { + if ((flags & (1 << i))) { + mbedtls_debug_print_msg(ssl, level, file, line, "- %s is set.", + ticket_flag_name_table[i]); } } +} +#endif /* MBEDTLS_SSL_PROTO_TLS1_3 && MBEDTLS_SSL_SESSION_TICKETS */ -exit: - mbedtls_md_free(&md_ctx); +#endif /* MBEDTLS_DEBUG_C */ - if (tmp != NULL) { - mbedtls_platform_zeroize(tmp, tmp_len); +void mbedtls_ssl_optimize_checksum(mbedtls_ssl_context *ssl, + const mbedtls_ssl_ciphersuite_t *ciphersuite_info) +{ + ((void) ciphersuite_info); + +#if defined(MBEDTLS_MD_CAN_SHA384) + if (ciphersuite_info->mac == MBEDTLS_MD_SHA384) { + ssl->handshake->update_checksum = ssl_update_checksum_sha384; + } else +#endif +#if defined(MBEDTLS_MD_CAN_SHA256) + if (ciphersuite_info->mac != MBEDTLS_MD_SHA384) { + ssl->handshake->update_checksum = ssl_update_checksum_sha256; + } else +#endif + { + MBEDTLS_SSL_DEBUG_MSG(1, ("should never happen")); + return; } +} - mbedtls_platform_zeroize(h_i, sizeof(h_i)); +int mbedtls_ssl_add_hs_hdr_to_checksum(mbedtls_ssl_context *ssl, + unsigned hs_type, + size_t total_hs_len) +{ + unsigned char hs_hdr[4]; - mbedtls_free(tmp); + /* Build HS header for checksum update. */ + hs_hdr[0] = MBEDTLS_BYTE_0(hs_type); + hs_hdr[1] = MBEDTLS_BYTE_2(total_hs_len); + hs_hdr[2] = MBEDTLS_BYTE_1(total_hs_len); + hs_hdr[3] = MBEDTLS_BYTE_0(total_hs_len); - return ret; -} -#endif /* MBEDTLS_USE_PSA_CRYPTO */ -#if defined(MBEDTLS_SHA256_C) -MBEDTLS_CHECK_RETURN_CRITICAL -static int tls_prf_sha256(const unsigned char *secret, size_t slen, - const char *label, - const unsigned char *random, size_t rlen, - unsigned char *dstbuf, size_t dlen) -{ - return tls_prf_generic(MBEDTLS_MD_SHA256, secret, slen, - label, random, rlen, dstbuf, dlen); + return ssl->handshake->update_checksum(ssl, hs_hdr, sizeof(hs_hdr)); } -#endif /* MBEDTLS_SHA256_C */ -#if defined(MBEDTLS_SHA512_C) && !defined(MBEDTLS_SHA512_NO_SHA384) -MBEDTLS_CHECK_RETURN_CRITICAL -static int tls_prf_sha384(const unsigned char *secret, size_t slen, - const char *label, - const unsigned char *random, size_t rlen, - unsigned char *dstbuf, size_t dlen) +int mbedtls_ssl_add_hs_msg_to_checksum(mbedtls_ssl_context *ssl, + unsigned hs_type, + unsigned char const *msg, + size_t msg_len) { - return tls_prf_generic(MBEDTLS_MD_SHA384, secret, slen, - label, random, rlen, dstbuf, dlen); + int ret; + ret = mbedtls_ssl_add_hs_hdr_to_checksum(ssl, hs_type, msg_len); + if (ret != 0) { + return ret; + } + return ssl->handshake->update_checksum(ssl, msg, msg_len); } -#endif /* MBEDTLS_SHA512_C && !MBEDTLS_SHA512_NO_SHA384 */ -#endif /* MBEDTLS_SSL_PROTO_TLS1_2 */ - -static void ssl_update_checksum_start(mbedtls_ssl_context *, const unsigned char *, size_t); - -#if defined(MBEDTLS_SSL_PROTO_SSL3) || defined(MBEDTLS_SSL_PROTO_TLS1) || \ - defined(MBEDTLS_SSL_PROTO_TLS1_1) -static void ssl_update_checksum_md5sha1(mbedtls_ssl_context *, const unsigned char *, size_t); -#endif - -#if defined(MBEDTLS_SSL_PROTO_SSL3) -static void ssl_calc_verify_ssl(const mbedtls_ssl_context *, unsigned char *, size_t *); -static void ssl_calc_finished_ssl(mbedtls_ssl_context *, unsigned char *, int); -#endif -#if defined(MBEDTLS_SSL_PROTO_TLS1) || defined(MBEDTLS_SSL_PROTO_TLS1_1) -static void ssl_calc_verify_tls(const mbedtls_ssl_context *, unsigned char *, size_t *); -static void ssl_calc_finished_tls(mbedtls_ssl_context *, unsigned char *, int); -#endif - -#if defined(MBEDTLS_SSL_PROTO_TLS1_2) -#if defined(MBEDTLS_SHA256_C) -static void ssl_update_checksum_sha256(mbedtls_ssl_context *, const unsigned char *, size_t); -static void ssl_calc_verify_tls_sha256(const mbedtls_ssl_context *, unsigned char *, size_t *); -static void ssl_calc_finished_tls_sha256(mbedtls_ssl_context *, unsigned char *, int); +int mbedtls_ssl_reset_checksum(mbedtls_ssl_context *ssl) +{ +#if defined(MBEDTLS_MD_CAN_SHA256) || \ + defined(MBEDTLS_MD_CAN_SHA384) +#if defined(MBEDTLS_USE_PSA_CRYPTO) + psa_status_t status; +#else + int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED; #endif - -#if defined(MBEDTLS_SHA512_C) && !defined(MBEDTLS_SHA512_NO_SHA384) -static void ssl_update_checksum_sha384(mbedtls_ssl_context *, const unsigned char *, size_t); -static void ssl_calc_verify_tls_sha384(const mbedtls_ssl_context *, unsigned char *, size_t *); -static void ssl_calc_finished_tls_sha384(mbedtls_ssl_context *, unsigned char *, int); +#else /* SHA-256 or SHA-384 */ + ((void) ssl); +#endif /* SHA-256 or SHA-384 */ +#if defined(MBEDTLS_MD_CAN_SHA256) +#if defined(MBEDTLS_USE_PSA_CRYPTO) + status = psa_hash_abort(&ssl->handshake->fin_sha256_psa); + if (status != PSA_SUCCESS) { + return mbedtls_md_error_from_psa(status); + } + status = psa_hash_setup(&ssl->handshake->fin_sha256_psa, PSA_ALG_SHA_256); + if (status != PSA_SUCCESS) { + return mbedtls_md_error_from_psa(status); + } +#else + mbedtls_md_free(&ssl->handshake->fin_sha256); + mbedtls_md_init(&ssl->handshake->fin_sha256); + ret = mbedtls_md_setup(&ssl->handshake->fin_sha256, + mbedtls_md_info_from_type(MBEDTLS_MD_SHA256), + 0); + if (ret != 0) { + return ret; + } + ret = mbedtls_md_starts(&ssl->handshake->fin_sha256); + if (ret != 0) { + return ret; + } #endif -#endif /* MBEDTLS_SSL_PROTO_TLS1_2 */ - -#if defined(MBEDTLS_KEY_EXCHANGE_PSK_ENABLED) && \ - defined(MBEDTLS_USE_PSA_CRYPTO) -MBEDTLS_CHECK_RETURN_CRITICAL -static int ssl_use_opaque_psk(mbedtls_ssl_context const *ssl) -{ - if (ssl->conf->f_psk != NULL) { - /* If we've used a callback to select the PSK, - * the static configuration is irrelevant. */ - if (!mbedtls_svc_key_id_is_null(ssl->handshake->psk_opaque)) { - return 1; - } - - return 0; +#endif +#if defined(MBEDTLS_MD_CAN_SHA384) +#if defined(MBEDTLS_USE_PSA_CRYPTO) + status = psa_hash_abort(&ssl->handshake->fin_sha384_psa); + if (status != PSA_SUCCESS) { + return mbedtls_md_error_from_psa(status); } - - if (!mbedtls_svc_key_id_is_null(ssl->conf->psk_opaque)) { - return 1; + status = psa_hash_setup(&ssl->handshake->fin_sha384_psa, PSA_ALG_SHA_384); + if (status != PSA_SUCCESS) { + return mbedtls_md_error_from_psa(status); } - +#else + mbedtls_md_free(&ssl->handshake->fin_sha384); + mbedtls_md_init(&ssl->handshake->fin_sha384); + ret = mbedtls_md_setup(&ssl->handshake->fin_sha384, + mbedtls_md_info_from_type(MBEDTLS_MD_SHA384), 0); + if (ret != 0) { + return ret; + } + ret = mbedtls_md_starts(&ssl->handshake->fin_sha384); + if (ret != 0) { + return ret; + } +#endif +#endif return 0; } -#endif /* MBEDTLS_USE_PSA_CRYPTO && - MBEDTLS_KEY_EXCHANGE_PSK_ENABLED */ -#if defined(MBEDTLS_SSL_EXPORT_KEYS) -static mbedtls_tls_prf_types tls_prf_get_type(mbedtls_ssl_tls_prf_cb *tls_prf) +static int ssl_update_checksum_start(mbedtls_ssl_context *ssl, + const unsigned char *buf, size_t len) { -#if defined(MBEDTLS_SSL_PROTO_SSL3) - if (tls_prf == ssl3_prf) { - return MBEDTLS_SSL_TLS_PRF_SSL3; - } else +#if defined(MBEDTLS_MD_CAN_SHA256) || \ + defined(MBEDTLS_MD_CAN_SHA384) +#if defined(MBEDTLS_USE_PSA_CRYPTO) + psa_status_t status; +#else + int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED; #endif -#if defined(MBEDTLS_SSL_PROTO_TLS1) || defined(MBEDTLS_SSL_PROTO_TLS1_1) - if (tls_prf == tls1_prf) { - return MBEDTLS_SSL_TLS_PRF_TLS1; - } else +#else /* SHA-256 or SHA-384 */ + ((void) ssl); + (void) buf; + (void) len; +#endif /* SHA-256 or SHA-384 */ +#if defined(MBEDTLS_MD_CAN_SHA256) +#if defined(MBEDTLS_USE_PSA_CRYPTO) + status = psa_hash_update(&ssl->handshake->fin_sha256_psa, buf, len); + if (status != PSA_SUCCESS) { + return mbedtls_md_error_from_psa(status); + } +#else + ret = mbedtls_md_update(&ssl->handshake->fin_sha256, buf, len); + if (ret != 0) { + return ret; + } #endif -#if defined(MBEDTLS_SSL_PROTO_TLS1_2) -#if defined(MBEDTLS_SHA512_C) && !defined(MBEDTLS_SHA512_NO_SHA384) - if (tls_prf == tls_prf_sha384) { - return MBEDTLS_SSL_TLS_PRF_SHA384; - } else #endif -#if defined(MBEDTLS_SHA256_C) - if (tls_prf == tls_prf_sha256) { - return MBEDTLS_SSL_TLS_PRF_SHA256; - } else +#if defined(MBEDTLS_MD_CAN_SHA384) +#if defined(MBEDTLS_USE_PSA_CRYPTO) + status = psa_hash_update(&ssl->handshake->fin_sha384_psa, buf, len); + if (status != PSA_SUCCESS) { + return mbedtls_md_error_from_psa(status); + } +#else + ret = mbedtls_md_update(&ssl->handshake->fin_sha384, buf, len); + if (ret != 0) { + return ret; + } #endif -#endif /* MBEDTLS_SSL_PROTO_TLS1_2 */ - return MBEDTLS_SSL_TLS_PRF_NONE; +#endif + return 0; } -#endif /* MBEDTLS_SSL_EXPORT_KEYS */ -int mbedtls_ssl_tls_prf(const mbedtls_tls_prf_types prf, - const unsigned char *secret, size_t slen, - const char *label, - const unsigned char *random, size_t rlen, - unsigned char *dstbuf, size_t dlen) +#if defined(MBEDTLS_MD_CAN_SHA256) +static int ssl_update_checksum_sha256(mbedtls_ssl_context *ssl, + const unsigned char *buf, size_t len) { - mbedtls_ssl_tls_prf_cb *tls_prf = NULL; +#if defined(MBEDTLS_USE_PSA_CRYPTO) + return mbedtls_md_error_from_psa(psa_hash_update( + &ssl->handshake->fin_sha256_psa, buf, len)); +#else + return mbedtls_md_update(&ssl->handshake->fin_sha256, buf, len); +#endif +} +#endif - switch (prf) { -#if defined(MBEDTLS_SSL_PROTO_SSL3) - case MBEDTLS_SSL_TLS_PRF_SSL3: - tls_prf = ssl3_prf; - break; -#endif /* MBEDTLS_SSL_PROTO_SSL3 */ -#if defined(MBEDTLS_SSL_PROTO_TLS1) || defined(MBEDTLS_SSL_PROTO_TLS1_1) - case MBEDTLS_SSL_TLS_PRF_TLS1: - tls_prf = tls1_prf; - break; -#endif /* MBEDTLS_SSL_PROTO_TLS1 || MBEDTLS_SSL_PROTO_TLS1_1 */ +#if defined(MBEDTLS_MD_CAN_SHA384) +static int ssl_update_checksum_sha384(mbedtls_ssl_context *ssl, + const unsigned char *buf, size_t len) +{ +#if defined(MBEDTLS_USE_PSA_CRYPTO) + return mbedtls_md_error_from_psa(psa_hash_update( + &ssl->handshake->fin_sha384_psa, buf, len)); +#else + return mbedtls_md_update(&ssl->handshake->fin_sha384, buf, len); +#endif +} +#endif -#if defined(MBEDTLS_SSL_PROTO_TLS1_2) -#if defined(MBEDTLS_SHA512_C) && !defined(MBEDTLS_SHA512_NO_SHA384) - case MBEDTLS_SSL_TLS_PRF_SHA384: - tls_prf = tls_prf_sha384; - break; -#endif /* MBEDTLS_SHA512_C && !MBEDTLS_SHA512_NO_SHA384 */ -#if defined(MBEDTLS_SHA256_C) - case MBEDTLS_SSL_TLS_PRF_SHA256: - tls_prf = tls_prf_sha256; - break; -#endif /* MBEDTLS_SHA256_C */ -#endif /* MBEDTLS_SSL_PROTO_TLS1_2 */ - default: - return MBEDTLS_ERR_SSL_FEATURE_UNAVAILABLE; - } +static void ssl_handshake_params_init(mbedtls_ssl_handshake_params *handshake) +{ + memset(handshake, 0, sizeof(mbedtls_ssl_handshake_params)); - return tls_prf(secret, slen, label, random, rlen, dstbuf, dlen); -} +#if defined(MBEDTLS_MD_CAN_SHA256) +#if defined(MBEDTLS_USE_PSA_CRYPTO) + handshake->fin_sha256_psa = psa_hash_operation_init(); +#else + mbedtls_md_init(&handshake->fin_sha256); +#endif +#endif +#if defined(MBEDTLS_MD_CAN_SHA384) +#if defined(MBEDTLS_USE_PSA_CRYPTO) + handshake->fin_sha384_psa = psa_hash_operation_init(); +#else + mbedtls_md_init(&handshake->fin_sha384); +#endif +#endif -/* Type for the TLS PRF */ -typedef int ssl_tls_prf_t(const unsigned char *, size_t, const char *, - const unsigned char *, size_t, - unsigned char *, size_t); + handshake->update_checksum = ssl_update_checksum_start; -/* - * Populate a transform structure with session keys and all the other - * necessary information. - * - * Parameters: - * - [in/out]: transform: structure to populate - * [in] must be just initialised with mbedtls_ssl_transform_init() - * [out] fully populated, ready for use by mbedtls_ssl_{en,de}crypt_buf() - * - [in] ciphersuite - * - [in] master - * - [in] encrypt_then_mac - * - [in] trunc_hmac - * - [in] compression - * - [in] tls_prf: pointer to PRF to use for key derivation - * - [in] randbytes: buffer holding ServerHello.random + ClientHello.random - * - [in] minor_ver: SSL/TLS minor version - * - [in] endpoint: client or server - * - [in] ssl: optionally used for: - * - MBEDTLS_SSL_HW_RECORD_ACCEL: whole context (non-const) - * - MBEDTLS_SSL_EXPORT_KEYS: ssl->conf->{f,p}_export_keys - * - MBEDTLS_DEBUG_C: ssl->conf->{f,p}_dbg - */ -MBEDTLS_CHECK_RETURN_CRITICAL -static int ssl_populate_transform(mbedtls_ssl_transform *transform, - int ciphersuite, - const unsigned char master[48], -#if defined(MBEDTLS_SSL_SOME_MODES_USE_MAC) -#if defined(MBEDTLS_SSL_ENCRYPT_THEN_MAC) - int encrypt_then_mac, -#endif /* MBEDTLS_SSL_ENCRYPT_THEN_MAC */ -#if defined(MBEDTLS_SSL_TRUNCATED_HMAC) - int trunc_hmac, -#endif /* MBEDTLS_SSL_TRUNCATED_HMAC */ -#endif /* MBEDTLS_SSL_SOME_MODES_USE_MAC */ -#if defined(MBEDTLS_ZLIB_SUPPORT) - int compression, -#endif - ssl_tls_prf_t tls_prf, - const unsigned char randbytes[64], - int minor_ver, - unsigned endpoint, -#if !defined(MBEDTLS_SSL_HW_RECORD_ACCEL) - const -#endif - mbedtls_ssl_context *ssl) -{ - int ret = 0; +#if defined(MBEDTLS_DHM_C) + mbedtls_dhm_init(&handshake->dhm_ctx); +#endif +#if !defined(MBEDTLS_USE_PSA_CRYPTO) && \ + defined(MBEDTLS_KEY_EXCHANGE_SOME_ECDH_OR_ECDHE_1_2_ENABLED) + mbedtls_ecdh_init(&handshake->ecdh_ctx); +#endif +#if defined(MBEDTLS_KEY_EXCHANGE_ECJPAKE_ENABLED) #if defined(MBEDTLS_USE_PSA_CRYPTO) - int psa_fallthrough; + handshake->psa_pake_ctx = psa_pake_operation_init(); + handshake->psa_pake_password = MBEDTLS_SVC_KEY_ID_INIT; +#else + mbedtls_ecjpake_init(&handshake->ecjpake_ctx); #endif /* MBEDTLS_USE_PSA_CRYPTO */ - int do_mbedtls_cipher_setup; - unsigned char keyblk[256]; - unsigned char *key1; - unsigned char *key2; - unsigned char *mac_enc; - unsigned char *mac_dec; - size_t mac_key_len = 0; - size_t iv_copy_len; - unsigned keylen; - const mbedtls_ssl_ciphersuite_t *ciphersuite_info; - const mbedtls_cipher_info_t *cipher_info; - const mbedtls_md_info_t *md_info; +#if defined(MBEDTLS_SSL_CLI_C) + handshake->ecjpake_cache = NULL; + handshake->ecjpake_cache_len = 0; +#endif +#endif -#if !defined(MBEDTLS_SSL_HW_RECORD_ACCEL) && \ - !defined(MBEDTLS_SSL_EXPORT_KEYS) && \ - !defined(MBEDTLS_SSL_DTLS_CONNECTION_ID) && \ - !defined(MBEDTLS_DEBUG_C) - ssl = NULL; /* make sure we don't use it except for those cases */ - (void) ssl; +#if defined(MBEDTLS_SSL_ECP_RESTARTABLE_ENABLED) + mbedtls_x509_crt_restart_init(&handshake->ecrs_ctx); #endif - /* - * Some data just needs copying into the structure - */ -#if defined(MBEDTLS_SSL_ENCRYPT_THEN_MAC) && \ - defined(MBEDTLS_SSL_SOME_MODES_USE_MAC) - transform->encrypt_then_mac = encrypt_then_mac; +#if defined(MBEDTLS_SSL_SERVER_NAME_INDICATION) + handshake->sni_authmode = MBEDTLS_SSL_VERIFY_UNSET; #endif - transform->minor_ver = minor_ver; -#if defined(MBEDTLS_SSL_CONTEXT_SERIALIZATION) - memcpy(transform->randbytes, randbytes, sizeof(transform->randbytes)); +#if defined(MBEDTLS_X509_CRT_PARSE_C) && \ + !defined(MBEDTLS_SSL_KEEP_PEER_CERTIFICATE) + mbedtls_pk_init(&handshake->peer_pubkey); #endif +} - /* - * Get various info structures - */ - ciphersuite_info = mbedtls_ssl_ciphersuite_from_id(ciphersuite); - if (ciphersuite_info == NULL) { - MBEDTLS_SSL_DEBUG_MSG(1, ("ciphersuite info for %d not found", - ciphersuite)); - return MBEDTLS_ERR_SSL_BAD_INPUT_DATA; - } +void mbedtls_ssl_transform_init(mbedtls_ssl_transform *transform) +{ + memset(transform, 0, sizeof(mbedtls_ssl_transform)); - cipher_info = mbedtls_cipher_info_from_type(ciphersuite_info->cipher); - if (cipher_info == NULL) { - MBEDTLS_SSL_DEBUG_MSG(1, ("cipher info for %u not found", - ciphersuite_info->cipher)); - return MBEDTLS_ERR_SSL_BAD_INPUT_DATA; - } +#if defined(MBEDTLS_USE_PSA_CRYPTO) + transform->psa_key_enc = MBEDTLS_SVC_KEY_ID_INIT; + transform->psa_key_dec = MBEDTLS_SVC_KEY_ID_INIT; +#else + mbedtls_cipher_init(&transform->cipher_ctx_enc); + mbedtls_cipher_init(&transform->cipher_ctx_dec); +#endif - md_info = mbedtls_md_info_from_type(ciphersuite_info->mac); - if (md_info == NULL) { - MBEDTLS_SSL_DEBUG_MSG(1, ("mbedtls_md info for %u not found", - (unsigned) ciphersuite_info->mac)); - return MBEDTLS_ERR_SSL_BAD_INPUT_DATA; - } +#if defined(MBEDTLS_SSL_SOME_SUITES_USE_MAC) +#if defined(MBEDTLS_USE_PSA_CRYPTO) + transform->psa_mac_enc = MBEDTLS_SVC_KEY_ID_INIT; + transform->psa_mac_dec = MBEDTLS_SVC_KEY_ID_INIT; +#else + mbedtls_md_init(&transform->md_ctx_enc); + mbedtls_md_init(&transform->md_ctx_dec); +#endif +#endif +} -#if defined(MBEDTLS_SSL_DTLS_CONNECTION_ID) - /* Copy own and peer's CID if the use of the CID - * extension has been negotiated. */ - if (ssl->handshake->cid_in_use == MBEDTLS_SSL_CID_ENABLED) { - MBEDTLS_SSL_DEBUG_MSG(3, ("Copy CIDs into SSL transform")); +void mbedtls_ssl_session_init(mbedtls_ssl_session *session) +{ + memset(session, 0, sizeof(mbedtls_ssl_session)); +} - transform->in_cid_len = ssl->own_cid_len; - memcpy(transform->in_cid, ssl->own_cid, ssl->own_cid_len); - MBEDTLS_SSL_DEBUG_BUF(3, "Incoming CID", transform->in_cid, - transform->in_cid_len); +MBEDTLS_CHECK_RETURN_CRITICAL +static int ssl_handshake_init(mbedtls_ssl_context *ssl) +{ + int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED; - transform->out_cid_len = ssl->handshake->peer_cid_len; - memcpy(transform->out_cid, ssl->handshake->peer_cid, - ssl->handshake->peer_cid_len); - MBEDTLS_SSL_DEBUG_BUF(3, "Outgoing CID", transform->out_cid, - transform->out_cid_len); + /* Clear old handshake information if present */ +#if defined(MBEDTLS_SSL_PROTO_TLS1_2) + if (ssl->transform_negotiate) { + mbedtls_ssl_transform_free(ssl->transform_negotiate); + } +#endif /* MBEDTLS_SSL_PROTO_TLS1_2 */ + if (ssl->session_negotiate) { + mbedtls_ssl_session_free(ssl->session_negotiate); + } + if (ssl->handshake) { + mbedtls_ssl_handshake_free(ssl); } -#endif /* MBEDTLS_SSL_DTLS_CONNECTION_ID */ +#if defined(MBEDTLS_SSL_PROTO_TLS1_2) /* - * Compute key block using the PRF + * Either the pointers are now NULL or cleared properly and can be freed. + * Now allocate missing structures. */ - ret = tls_prf(master, 48, "key expansion", randbytes, 64, keyblk, 256); - if (ret != 0) { - MBEDTLS_SSL_DEBUG_RET(1, "prf", ret); - return ret; + if (ssl->transform_negotiate == NULL) { + ssl->transform_negotiate = mbedtls_calloc(1, sizeof(mbedtls_ssl_transform)); } +#endif /* MBEDTLS_SSL_PROTO_TLS1_2 */ - MBEDTLS_SSL_DEBUG_MSG(3, ("ciphersuite = %s", - mbedtls_ssl_get_ciphersuite_name(ciphersuite))); - MBEDTLS_SSL_DEBUG_BUF(3, "master secret", master, 48); - MBEDTLS_SSL_DEBUG_BUF(4, "random bytes", randbytes, 64); - MBEDTLS_SSL_DEBUG_BUF(4, "key block", keyblk, 256); - - /* - * Determine the appropriate key, IV and MAC length. - */ + if (ssl->session_negotiate == NULL) { + ssl->session_negotiate = mbedtls_calloc(1, sizeof(mbedtls_ssl_session)); + } - keylen = cipher_info->key_bitlen / 8; + if (ssl->handshake == NULL) { + ssl->handshake = mbedtls_calloc(1, sizeof(mbedtls_ssl_handshake_params)); + } +#if defined(MBEDTLS_SSL_VARIABLE_BUFFER_LENGTH) + /* If the buffers are too small - reallocate */ -#if defined(MBEDTLS_GCM_C) || \ - defined(MBEDTLS_CCM_C) || \ - defined(MBEDTLS_CHACHAPOLY_C) - if (cipher_info->mode == MBEDTLS_MODE_GCM || - cipher_info->mode == MBEDTLS_MODE_CCM || - cipher_info->mode == MBEDTLS_MODE_CHACHAPOLY) { - size_t explicit_ivlen; + handle_buffer_resizing(ssl, 0, MBEDTLS_SSL_IN_BUFFER_LEN, + MBEDTLS_SSL_OUT_BUFFER_LEN); +#endif - transform->maclen = 0; - mac_key_len = 0; - transform->taglen = - ciphersuite_info->flags & MBEDTLS_CIPHERSUITE_SHORT_TAG ? 8 : 16; + /* All pointers should exist and can be directly freed without issue */ + if (ssl->handshake == NULL || +#if defined(MBEDTLS_SSL_PROTO_TLS1_2) + ssl->transform_negotiate == NULL || +#endif + ssl->session_negotiate == NULL) { + MBEDTLS_SSL_DEBUG_MSG(1, ("alloc() of ssl sub-contexts failed")); - /* All modes haves 96-bit IVs, but the length of the static parts vary - * with mode and version: - * - For GCM and CCM in TLS 1.2, there's a static IV of 4 Bytes - * (to be concatenated with a dynamically chosen IV of 8 Bytes) - * - For ChaChaPoly in TLS 1.2, and all modes in TLS 1.3, there's - * a static IV of 12 Bytes (to be XOR'ed with the 8 Byte record - * sequence number). - */ - transform->ivlen = 12; -#if defined(MBEDTLS_SSL_PROTO_TLS1_3_EXPERIMENTAL) - if (minor_ver == MBEDTLS_SSL_MINOR_VERSION_4) { - transform->fixed_ivlen = 12; - } else -#endif /* MBEDTLS_SSL_PROTO_TLS1_3_EXPERIMENTAL */ - { - if (cipher_info->mode == MBEDTLS_MODE_CHACHAPOLY) { - transform->fixed_ivlen = 12; - } else { - transform->fixed_ivlen = 4; - } - } + mbedtls_free(ssl->handshake); + ssl->handshake = NULL; - /* Minimum length of encrypted record */ - explicit_ivlen = transform->ivlen - transform->fixed_ivlen; - transform->minlen = explicit_ivlen + transform->taglen; - } else -#endif /* MBEDTLS_GCM_C || MBEDTLS_CCM_C || MBEDTLS_CHACHAPOLY_C */ -#if defined(MBEDTLS_SSL_SOME_MODES_USE_MAC) - if (cipher_info->mode == MBEDTLS_MODE_STREAM || - cipher_info->mode == MBEDTLS_MODE_CBC) { - /* Initialize HMAC contexts */ - if ((ret = mbedtls_md_setup(&transform->md_ctx_enc, md_info, 1)) != 0 || - (ret = mbedtls_md_setup(&transform->md_ctx_dec, md_info, 1)) != 0) { - MBEDTLS_SSL_DEBUG_RET(1, "mbedtls_md_setup", ret); - goto end; - } +#if defined(MBEDTLS_SSL_PROTO_TLS1_2) + mbedtls_free(ssl->transform_negotiate); + ssl->transform_negotiate = NULL; +#endif - /* Get MAC length */ - mac_key_len = mbedtls_md_get_size(md_info); - transform->maclen = mac_key_len; + mbedtls_free(ssl->session_negotiate); + ssl->session_negotiate = NULL; -#if defined(MBEDTLS_SSL_TRUNCATED_HMAC) - /* - * If HMAC is to be truncated, we shall keep the leftmost bytes, - * (rfc 6066 page 13 or rfc 2104 section 4), - * so we only need to adjust the length here. - */ - if (trunc_hmac == MBEDTLS_SSL_TRUNC_HMAC_ENABLED) { - transform->maclen = MBEDTLS_SSL_TRUNCATED_HMAC_LEN; + return MBEDTLS_ERR_SSL_ALLOC_FAILED; + } -#if defined(MBEDTLS_SSL_TRUNCATED_HMAC_COMPAT) - /* Fall back to old, non-compliant version of the truncated - * HMAC implementation which also truncates the key - * (Mbed TLS versions from 1.3 to 2.6.0) */ - mac_key_len = transform->maclen; +#if defined(MBEDTLS_SSL_EARLY_DATA) +#if defined(MBEDTLS_SSL_CLI_C) + ssl->early_data_state = MBEDTLS_SSL_EARLY_DATA_STATE_IDLE; #endif - } -#endif /* MBEDTLS_SSL_TRUNCATED_HMAC */ +#if defined(MBEDTLS_SSL_SRV_C) + ssl->discard_early_data_record = MBEDTLS_SSL_EARLY_DATA_NO_DISCARD; +#endif + ssl->total_early_data_size = 0; +#endif /* MBEDTLS_SSL_EARLY_DATA */ - /* IV length */ - transform->ivlen = cipher_info->iv_size; + /* Initialize structures */ + mbedtls_ssl_session_init(ssl->session_negotiate); + ssl_handshake_params_init(ssl->handshake); - /* Minimum length */ - if (cipher_info->mode == MBEDTLS_MODE_STREAM) { - transform->minlen = transform->maclen; - } else { - /* - * GenericBlockCipher: - * 1. if EtM is in use: one block plus MAC - * otherwise: * first multiple of blocklen greater than maclen - * 2. IV except for SSL3 and TLS 1.0 - */ -#if defined(MBEDTLS_SSL_ENCRYPT_THEN_MAC) - if (encrypt_then_mac == MBEDTLS_SSL_ETM_ENABLED) { - transform->minlen = transform->maclen - + cipher_info->block_size; - } else +#if defined(MBEDTLS_SSL_PROTO_TLS1_2) + mbedtls_ssl_transform_init(ssl->transform_negotiate); #endif - { - transform->minlen = transform->maclen - + cipher_info->block_size - - transform->maclen % cipher_info->block_size; - } -#if defined(MBEDTLS_SSL_PROTO_SSL3) || defined(MBEDTLS_SSL_PROTO_TLS1) - if (minor_ver == MBEDTLS_SSL_MINOR_VERSION_0 || - minor_ver == MBEDTLS_SSL_MINOR_VERSION_1) { - ; /* No need to adjust minlen */ - } else -#endif -#if defined(MBEDTLS_SSL_PROTO_TLS1_1) || defined(MBEDTLS_SSL_PROTO_TLS1_2) - if (minor_ver == MBEDTLS_SSL_MINOR_VERSION_2 || - minor_ver == MBEDTLS_SSL_MINOR_VERSION_3) { - transform->minlen += transform->ivlen; - } else -#endif - { - MBEDTLS_SSL_DEBUG_MSG(1, ("should never happen")); - ret = MBEDTLS_ERR_SSL_INTERNAL_ERROR; - goto end; - } - } - } else -#endif /* MBEDTLS_SSL_SOME_MODES_USE_MAC */ - { - MBEDTLS_SSL_DEBUG_MSG(1, ("should never happen")); - return MBEDTLS_ERR_SSL_INTERNAL_ERROR; + /* Setup handshake checksums */ + ret = mbedtls_ssl_reset_checksum(ssl); + if (ret != 0) { + MBEDTLS_SSL_DEBUG_RET(1, "mbedtls_ssl_reset_checksum", ret); + return ret; } - MBEDTLS_SSL_DEBUG_MSG(3, ("keylen: %u, minlen: %u, ivlen: %u, maclen: %u", - (unsigned) keylen, - (unsigned) transform->minlen, - (unsigned) transform->ivlen, - (unsigned) transform->maclen)); +#if defined(MBEDTLS_SSL_PROTO_TLS1_3) && \ + defined(MBEDTLS_SSL_SRV_C) && \ + defined(MBEDTLS_SSL_SESSION_TICKETS) + ssl->handshake->new_session_tickets_count = + ssl->conf->new_session_tickets_count; +#endif - /* - * Finally setup the cipher contexts, IVs and MAC secrets. - */ -#if defined(MBEDTLS_SSL_CLI_C) - if (endpoint == MBEDTLS_SSL_IS_CLIENT) { - key1 = keyblk + mac_key_len * 2; - key2 = keyblk + mac_key_len * 2 + keylen; +#if defined(MBEDTLS_SSL_PROTO_DTLS) + if (ssl->conf->transport == MBEDTLS_SSL_TRANSPORT_DATAGRAM) { + ssl->handshake->alt_transform_out = ssl->transform_out; - mac_enc = keyblk; - mac_dec = keyblk + mac_key_len; + if (ssl->conf->endpoint == MBEDTLS_SSL_IS_CLIENT) { + ssl->handshake->retransmit_state = MBEDTLS_SSL_RETRANS_PREPARING; + } else { + ssl->handshake->retransmit_state = MBEDTLS_SSL_RETRANS_WAITING; + } - /* - * This is not used in TLS v1.1. - */ - iv_copy_len = (transform->fixed_ivlen) ? - transform->fixed_ivlen : transform->ivlen; - memcpy(transform->iv_enc, key2 + keylen, iv_copy_len); - memcpy(transform->iv_dec, key2 + keylen + iv_copy_len, - iv_copy_len); - } else -#endif /* MBEDTLS_SSL_CLI_C */ -#if defined(MBEDTLS_SSL_SRV_C) - if (endpoint == MBEDTLS_SSL_IS_SERVER) { - key1 = keyblk + mac_key_len * 2 + keylen; - key2 = keyblk + mac_key_len * 2; + mbedtls_ssl_set_timer(ssl, 0); + } +#endif - mac_enc = keyblk + mac_key_len; - mac_dec = keyblk; +/* + * curve_list is translated to IANA TLS group identifiers here because + * mbedtls_ssl_conf_curves returns void and so can't return + * any error codes. + */ +#if defined(MBEDTLS_ECP_C) +#if !defined(MBEDTLS_DEPRECATED_REMOVED) + /* Heap allocate and translate curve_list from internal to IANA group ids */ + if (ssl->conf->curve_list != NULL) { + size_t length; + const mbedtls_ecp_group_id *curve_list = ssl->conf->curve_list; - /* - * This is not used in TLS v1.1. - */ - iv_copy_len = (transform->fixed_ivlen) ? - transform->fixed_ivlen : transform->ivlen; - memcpy(transform->iv_dec, key1 + keylen, iv_copy_len); - memcpy(transform->iv_enc, key1 + keylen + iv_copy_len, - iv_copy_len); - } else -#endif /* MBEDTLS_SSL_SRV_C */ - { - MBEDTLS_SSL_DEBUG_MSG(1, ("should never happen")); - ret = MBEDTLS_ERR_SSL_INTERNAL_ERROR; - goto end; - } + for (length = 0; (curve_list[length] != MBEDTLS_ECP_DP_NONE); length++) { + } -#if defined(MBEDTLS_SSL_SOME_MODES_USE_MAC) -#if defined(MBEDTLS_SSL_PROTO_SSL3) - if (minor_ver == MBEDTLS_SSL_MINOR_VERSION_0) { - if (mac_key_len > sizeof(transform->mac_enc)) { - MBEDTLS_SSL_DEBUG_MSG(1, ("should never happen")); - ret = MBEDTLS_ERR_SSL_INTERNAL_ERROR; - goto end; + /* Leave room for zero termination */ + uint16_t *group_list = mbedtls_calloc(length + 1, sizeof(uint16_t)); + if (group_list == NULL) { + return MBEDTLS_ERR_SSL_ALLOC_FAILED; } - memcpy(transform->mac_enc, mac_enc, mac_key_len); - memcpy(transform->mac_dec, mac_dec, mac_key_len); - } else -#endif /* MBEDTLS_SSL_PROTO_SSL3 */ -#if defined(MBEDTLS_SSL_PROTO_TLS1) || defined(MBEDTLS_SSL_PROTO_TLS1_1) || \ - defined(MBEDTLS_SSL_PROTO_TLS1_2) - if (minor_ver >= MBEDTLS_SSL_MINOR_VERSION_1) { - /* For HMAC-based ciphersuites, initialize the HMAC transforms. - For AEAD-based ciphersuites, there is nothing to do here. */ - if (mac_key_len != 0) { - ret = mbedtls_md_hmac_starts(&transform->md_ctx_enc, - mac_enc, mac_key_len); - if (ret != 0) { - goto end; - } - ret = mbedtls_md_hmac_starts(&transform->md_ctx_dec, - mac_dec, mac_key_len); - if (ret != 0) { - goto end; + for (size_t i = 0; i < length; i++) { + uint16_t tls_id = mbedtls_ssl_get_tls_id_from_ecp_group_id( + curve_list[i]); + if (tls_id == 0) { + mbedtls_free(group_list); + return MBEDTLS_ERR_SSL_BAD_CONFIG; } + group_list[i] = tls_id; } - } else -#endif - { - MBEDTLS_SSL_DEBUG_MSG(1, ("should never happen")); - ret = MBEDTLS_ERR_SSL_INTERNAL_ERROR; - goto end; - } -#endif /* MBEDTLS_SSL_SOME_MODES_USE_MAC */ -#if defined(MBEDTLS_SSL_HW_RECORD_ACCEL) - if (mbedtls_ssl_hw_record_init != NULL) { - ret = 0; - - MBEDTLS_SSL_DEBUG_MSG(2, ("going for mbedtls_ssl_hw_record_init()")); - - if ((ret = mbedtls_ssl_hw_record_init(ssl, key1, key2, keylen, - transform->iv_enc, transform->iv_dec, - iv_copy_len, - mac_enc, mac_dec, - mac_key_len)) != 0) { - MBEDTLS_SSL_DEBUG_RET(1, "mbedtls_ssl_hw_record_init", ret); - ret = MBEDTLS_ERR_SSL_HW_ACCEL_FAILED; - goto end; - } - } -#else - ((void) mac_dec); - ((void) mac_enc); -#endif /* MBEDTLS_SSL_HW_RECORD_ACCEL */ + group_list[length] = 0; -#if defined(MBEDTLS_SSL_EXPORT_KEYS) - if (ssl->conf->f_export_keys != NULL) { - ssl->conf->f_export_keys(ssl->conf->p_export_keys, - master, keyblk, - mac_key_len, keylen, - iv_copy_len); + ssl->handshake->group_list = group_list; + ssl->handshake->group_list_heap_allocated = 1; + } else { + ssl->handshake->group_list = ssl->conf->group_list; + ssl->handshake->group_list_heap_allocated = 0; } +#endif /* MBEDTLS_DEPRECATED_REMOVED */ +#endif /* MBEDTLS_ECP_C */ - if (ssl->conf->f_export_keys_ext != NULL) { - ssl->conf->f_export_keys_ext(ssl->conf->p_export_keys, - master, keyblk, - mac_key_len, keylen, - iv_copy_len, - randbytes + 32, - randbytes, - tls_prf_get_type(tls_prf)); - } +#if defined(MBEDTLS_SSL_HANDSHAKE_WITH_CERT_ENABLED) +#if !defined(MBEDTLS_DEPRECATED_REMOVED) +#if defined(MBEDTLS_SSL_PROTO_TLS1_2) + /* Heap allocate and translate sig_hashes from internal hash identifiers to + signature algorithms IANA identifiers. */ + if (mbedtls_ssl_conf_is_tls12_only(ssl->conf) && + ssl->conf->sig_hashes != NULL) { + const int *md; + const int *sig_hashes = ssl->conf->sig_hashes; + size_t sig_algs_len = 0; + uint16_t *p; + + MBEDTLS_STATIC_ASSERT(MBEDTLS_SSL_MAX_SIG_ALG_LIST_LEN + <= (SIZE_MAX - (2 * sizeof(uint16_t))), + "MBEDTLS_SSL_MAX_SIG_ALG_LIST_LEN too big"); + + for (md = sig_hashes; *md != MBEDTLS_MD_NONE; md++) { + if (mbedtls_ssl_hash_from_md_alg(*md) == MBEDTLS_SSL_HASH_NONE) { + continue; + } +#if defined(MBEDTLS_KEY_EXCHANGE_ECDSA_CERT_REQ_ALLOWED_ENABLED) + sig_algs_len += sizeof(uint16_t); #endif - do_mbedtls_cipher_setup = 1; -#if defined(MBEDTLS_USE_PSA_CRYPTO) - - /* Only use PSA-based ciphers for TLS-1.2. - * That's relevant at least for TLS-1.0, where - * we assume that mbedtls_cipher_crypt() updates - * the structure field for the IV, which the PSA-based - * implementation currently doesn't. */ -#if defined(MBEDTLS_SSL_PROTO_TLS1_2) - if (minor_ver == MBEDTLS_SSL_MINOR_VERSION_3) { - ret = mbedtls_cipher_setup_psa(&transform->cipher_ctx_enc, - cipher_info, transform->taglen); - if (ret != 0 && ret != MBEDTLS_ERR_CIPHER_FEATURE_UNAVAILABLE) { - MBEDTLS_SSL_DEBUG_RET(1, "mbedtls_cipher_setup_psa", ret); - goto end; +#if defined(MBEDTLS_RSA_C) + sig_algs_len += sizeof(uint16_t); +#endif + if (sig_algs_len > MBEDTLS_SSL_MAX_SIG_ALG_LIST_LEN) { + return MBEDTLS_ERR_SSL_BAD_CONFIG; + } } - if (ret == 0) { - MBEDTLS_SSL_DEBUG_MSG(3, ("Successfully setup PSA-based encryption cipher context")); - psa_fallthrough = 0; - } else { - MBEDTLS_SSL_DEBUG_MSG(1, - ( - "Failed to setup PSA-based cipher context for record encryption - fall through to default setup.")); - psa_fallthrough = 1; + if (sig_algs_len < MBEDTLS_SSL_MIN_SIG_ALG_LIST_LEN) { + return MBEDTLS_ERR_SSL_BAD_CONFIG; } - } else { - psa_fallthrough = 1; - } -#else - psa_fallthrough = 1; -#endif /* MBEDTLS_SSL_PROTO_TLS1_2 */ - - if (psa_fallthrough == 0) { - do_mbedtls_cipher_setup = 0; - } -#endif /* MBEDTLS_USE_PSA_CRYPTO */ - if (do_mbedtls_cipher_setup && - (ret = mbedtls_cipher_setup(&transform->cipher_ctx_enc, - cipher_info)) != 0) { - MBEDTLS_SSL_DEBUG_RET(1, "mbedtls_cipher_setup", ret); - goto end; - } - do_mbedtls_cipher_setup = 1; -#if defined(MBEDTLS_USE_PSA_CRYPTO) - /* Only use PSA-based ciphers for TLS-1.2. - * That's relevant at least for TLS-1.0, where - * we assume that mbedtls_cipher_crypt() updates - * the structure field for the IV, which the PSA-based - * implementation currently doesn't. */ -#if defined(MBEDTLS_SSL_PROTO_TLS1_2) - if (minor_ver == MBEDTLS_SSL_MINOR_VERSION_3) { - ret = mbedtls_cipher_setup_psa(&transform->cipher_ctx_dec, - cipher_info, transform->taglen); - if (ret != 0 && ret != MBEDTLS_ERR_CIPHER_FEATURE_UNAVAILABLE) { - MBEDTLS_SSL_DEBUG_RET(1, "mbedtls_cipher_setup_psa", ret); - goto end; + ssl->handshake->sig_algs = mbedtls_calloc(1, sig_algs_len + + sizeof(uint16_t)); + if (ssl->handshake->sig_algs == NULL) { + return MBEDTLS_ERR_SSL_ALLOC_FAILED; } - if (ret == 0) { - MBEDTLS_SSL_DEBUG_MSG(3, ("Successfully setup PSA-based decryption cipher context")); - psa_fallthrough = 0; - } else { - MBEDTLS_SSL_DEBUG_MSG(1, - ( - "Failed to setup PSA-based cipher context for record decryption - fall through to default setup.")); - psa_fallthrough = 1; + p = (uint16_t *) ssl->handshake->sig_algs; + for (md = sig_hashes; *md != MBEDTLS_MD_NONE; md++) { + unsigned char hash = mbedtls_ssl_hash_from_md_alg(*md); + if (hash == MBEDTLS_SSL_HASH_NONE) { + continue; + } +#if defined(MBEDTLS_KEY_EXCHANGE_ECDSA_CERT_REQ_ALLOWED_ENABLED) + *p = ((hash << 8) | MBEDTLS_SSL_SIG_ECDSA); + p++; +#endif +#if defined(MBEDTLS_RSA_C) + *p = ((hash << 8) | MBEDTLS_SSL_SIG_RSA); + p++; +#endif } - } else { - psa_fallthrough = 1; - } -#else - psa_fallthrough = 1; + *p = MBEDTLS_TLS_SIG_NONE; + ssl->handshake->sig_algs_heap_allocated = 1; + } else #endif /* MBEDTLS_SSL_PROTO_TLS1_2 */ - - if (psa_fallthrough == 0) { - do_mbedtls_cipher_setup = 0; - } -#endif /* MBEDTLS_USE_PSA_CRYPTO */ - if (do_mbedtls_cipher_setup && - (ret = mbedtls_cipher_setup(&transform->cipher_ctx_dec, - cipher_info)) != 0) { - MBEDTLS_SSL_DEBUG_RET(1, "mbedtls_cipher_setup", ret); - goto end; + { + ssl->handshake->sig_algs_heap_allocated = 0; } +#endif /* !MBEDTLS_DEPRECATED_REMOVED */ +#endif /* MBEDTLS_SSL_HANDSHAKE_WITH_CERT_ENABLED */ + return 0; +} - if ((ret = mbedtls_cipher_setkey(&transform->cipher_ctx_enc, key1, - cipher_info->key_bitlen, - MBEDTLS_ENCRYPT)) != 0) { - MBEDTLS_SSL_DEBUG_RET(1, "mbedtls_cipher_setkey", ret); - goto end; - } +#if defined(MBEDTLS_SSL_DTLS_HELLO_VERIFY) && defined(MBEDTLS_SSL_SRV_C) +/* Dummy cookie callbacks for defaults */ +MBEDTLS_CHECK_RETURN_CRITICAL +static int ssl_cookie_write_dummy(void *ctx, + unsigned char **p, unsigned char *end, + const unsigned char *cli_id, size_t cli_id_len) +{ + ((void) ctx); + ((void) p); + ((void) end); + ((void) cli_id); + ((void) cli_id_len); - if ((ret = mbedtls_cipher_setkey(&transform->cipher_ctx_dec, key2, - cipher_info->key_bitlen, - MBEDTLS_DECRYPT)) != 0) { - MBEDTLS_SSL_DEBUG_RET(1, "mbedtls_cipher_setkey", ret); - goto end; - } + return MBEDTLS_ERR_SSL_FEATURE_UNAVAILABLE; +} -#if defined(MBEDTLS_CIPHER_MODE_CBC) - if (cipher_info->mode == MBEDTLS_MODE_CBC) { - if ((ret = mbedtls_cipher_set_padding_mode(&transform->cipher_ctx_enc, - MBEDTLS_PADDING_NONE)) != 0) { - MBEDTLS_SSL_DEBUG_RET(1, "mbedtls_cipher_set_padding_mode", ret); - goto end; - } +MBEDTLS_CHECK_RETURN_CRITICAL +static int ssl_cookie_check_dummy(void *ctx, + const unsigned char *cookie, size_t cookie_len, + const unsigned char *cli_id, size_t cli_id_len) +{ + ((void) ctx); + ((void) cookie); + ((void) cookie_len); + ((void) cli_id); + ((void) cli_id_len); - if ((ret = mbedtls_cipher_set_padding_mode(&transform->cipher_ctx_dec, - MBEDTLS_PADDING_NONE)) != 0) { - MBEDTLS_SSL_DEBUG_RET(1, "mbedtls_cipher_set_padding_mode", ret); - goto end; - } - } -#endif /* MBEDTLS_CIPHER_MODE_CBC */ + return MBEDTLS_ERR_SSL_FEATURE_UNAVAILABLE; +} +#endif /* MBEDTLS_SSL_DTLS_HELLO_VERIFY && MBEDTLS_SSL_SRV_C */ +/* + * Initialize an SSL context + */ +void mbedtls_ssl_init(mbedtls_ssl_context *ssl) +{ + memset(ssl, 0, sizeof(mbedtls_ssl_context)); +} - /* Initialize Zlib contexts */ -#if defined(MBEDTLS_ZLIB_SUPPORT) - if (compression == MBEDTLS_SSL_COMPRESS_DEFLATE) { - MBEDTLS_SSL_DEBUG_MSG(3, ("Initializing zlib states")); +MBEDTLS_CHECK_RETURN_CRITICAL +static int ssl_conf_version_check(const mbedtls_ssl_context *ssl) +{ + const mbedtls_ssl_config *conf = ssl->conf; - memset(&transform->ctx_deflate, 0, sizeof(transform->ctx_deflate)); - memset(&transform->ctx_inflate, 0, sizeof(transform->ctx_inflate)); +#if defined(MBEDTLS_SSL_PROTO_TLS1_3) + if (mbedtls_ssl_conf_is_tls13_only(conf)) { + if (conf->transport == MBEDTLS_SSL_TRANSPORT_DATAGRAM) { + MBEDTLS_SSL_DEBUG_MSG(1, ("DTLS 1.3 is not yet supported.")); + return MBEDTLS_ERR_SSL_FEATURE_UNAVAILABLE; + } - if (deflateInit(&transform->ctx_deflate, - Z_DEFAULT_COMPRESSION) != Z_OK || - inflateInit(&transform->ctx_inflate) != Z_OK) { - MBEDTLS_SSL_DEBUG_MSG(1, ("Failed to initialize compression")); - ret = MBEDTLS_ERR_SSL_COMPRESSION_FAILED; - goto end; + MBEDTLS_SSL_DEBUG_MSG(4, ("The SSL configuration is tls13 only.")); + return 0; + } +#endif + +#if defined(MBEDTLS_SSL_PROTO_TLS1_2) + if (mbedtls_ssl_conf_is_tls12_only(conf)) { + MBEDTLS_SSL_DEBUG_MSG(4, ("The SSL configuration is tls12 only.")); + return 0; + } +#endif + +#if defined(MBEDTLS_SSL_PROTO_TLS1_2) && defined(MBEDTLS_SSL_PROTO_TLS1_3) + if (mbedtls_ssl_conf_is_hybrid_tls12_tls13(conf)) { + if (ssl->conf->transport == MBEDTLS_SSL_TRANSPORT_DATAGRAM) { + MBEDTLS_SSL_DEBUG_MSG(1, ("DTLS not yet supported in Hybrid TLS 1.3 + TLS 1.2")); + return MBEDTLS_ERR_SSL_FEATURE_UNAVAILABLE; } + + MBEDTLS_SSL_DEBUG_MSG(4, ("The SSL configuration is TLS 1.3 or TLS 1.2.")); + return 0; } -#endif /* MBEDTLS_ZLIB_SUPPORT */ +#endif -end: - mbedtls_platform_zeroize(keyblk, sizeof(keyblk)); - return ret; + MBEDTLS_SSL_DEBUG_MSG(1, ("The SSL configuration is invalid.")); + return MBEDTLS_ERR_SSL_BAD_CONFIG; } -/* - * Set appropriate PRF function and other SSL / TLS 1.0/1.1 / TLS1.2 functions - * - * Inputs: - * - SSL/TLS minor version - * - hash associated with the ciphersuite (only used by TLS 1.2) - * - * Outputs: - * - the tls_prf, calc_verify and calc_finished members of handshake structure - */ MBEDTLS_CHECK_RETURN_CRITICAL -static int ssl_set_handshake_prfs(mbedtls_ssl_handshake_params *handshake, - int minor_ver, - mbedtls_md_type_t hash) +static int ssl_conf_check(const mbedtls_ssl_context *ssl) { -#if !defined(MBEDTLS_SSL_PROTO_TLS1_2) || \ - !(defined(MBEDTLS_SHA512_C) && !defined(MBEDTLS_SHA512_NO_SHA384)) - (void) hash; -#endif + int ret; + ret = ssl_conf_version_check(ssl); + if (ret != 0) { + return ret; + } -#if defined(MBEDTLS_SSL_PROTO_SSL3) - if (minor_ver == MBEDTLS_SSL_MINOR_VERSION_0) { - handshake->tls_prf = ssl3_prf; - handshake->calc_verify = ssl_calc_verify_ssl; - handshake->calc_finished = ssl_calc_finished_ssl; - } else -#endif -#if defined(MBEDTLS_SSL_PROTO_TLS1) || defined(MBEDTLS_SSL_PROTO_TLS1_1) - if (minor_ver < MBEDTLS_SSL_MINOR_VERSION_3) { - handshake->tls_prf = tls1_prf; - handshake->calc_verify = ssl_calc_verify_tls; - handshake->calc_finished = ssl_calc_finished_tls; - } else -#endif -#if defined(MBEDTLS_SSL_PROTO_TLS1_2) -#if defined(MBEDTLS_SHA512_C) && !defined(MBEDTLS_SHA512_NO_SHA384) - if (minor_ver == MBEDTLS_SSL_MINOR_VERSION_3 && - hash == MBEDTLS_MD_SHA384) { - handshake->tls_prf = tls_prf_sha384; - handshake->calc_verify = ssl_calc_verify_tls_sha384; - handshake->calc_finished = ssl_calc_finished_tls_sha384; - } else -#endif -#if defined(MBEDTLS_SHA256_C) - if (minor_ver == MBEDTLS_SSL_MINOR_VERSION_3) { - handshake->tls_prf = tls_prf_sha256; - handshake->calc_verify = ssl_calc_verify_tls_sha256; - handshake->calc_finished = ssl_calc_finished_tls_sha256; - } else -#endif -#endif /* MBEDTLS_SSL_PROTO_TLS1_2 */ - { - return MBEDTLS_ERR_SSL_INTERNAL_ERROR; +#if defined(MBEDTLS_SSL_PROTO_TLS1_3) + /* RFC 8446 section 4.4.3 + * + * If the verification fails, the receiver MUST terminate the handshake with + * a "decrypt_error" alert. + * + * If the client is configured as TLS 1.3 only with optional verify, return + * bad config. + * + */ + if (mbedtls_ssl_conf_tls13_is_ephemeral_enabled( + (mbedtls_ssl_context *) ssl) && + ssl->conf->endpoint == MBEDTLS_SSL_IS_CLIENT && + ssl->conf->max_tls_version == MBEDTLS_SSL_VERSION_TLS1_3 && + ssl->conf->min_tls_version == MBEDTLS_SSL_VERSION_TLS1_3 && + ssl->conf->authmode == MBEDTLS_SSL_VERIFY_OPTIONAL) { + MBEDTLS_SSL_DEBUG_MSG( + 1, ("Optional verify auth mode " + "is not available for TLS 1.3 client")); + return MBEDTLS_ERR_SSL_BAD_CONFIG; + } +#endif /* MBEDTLS_SSL_PROTO_TLS1_3 */ + + if (ssl->conf->f_rng == NULL) { + MBEDTLS_SSL_DEBUG_MSG(1, ("no RNG provided")); + return MBEDTLS_ERR_SSL_NO_RNG; } + /* Space for further checks */ + return 0; } /* - * Compute master secret if needed - * - * Parameters: - * [in/out] handshake - * [in] resume, premaster, extended_ms, calc_verify, tls_prf - * (PSA-PSK) ciphersuite_info, psk_opaque - * [out] premaster (cleared) - * [out] master - * [in] ssl: optionally used for debugging, EMS and PSA-PSK - * debug: conf->f_dbg, conf->p_dbg - * EMS: passed to calc_verify (debug + (SSL3) session_negotiate) - * PSA-PSA: minor_ver, conf + * Setup an SSL context */ -MBEDTLS_CHECK_RETURN_CRITICAL -static int ssl_compute_master(mbedtls_ssl_handshake_params *handshake, - unsigned char *master, - const mbedtls_ssl_context *ssl) + +int mbedtls_ssl_setup(mbedtls_ssl_context *ssl, + const mbedtls_ssl_config *conf) { int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED; + size_t in_buf_len = MBEDTLS_SSL_IN_BUFFER_LEN; + size_t out_buf_len = MBEDTLS_SSL_OUT_BUFFER_LEN; - /* cf. RFC 5246, Section 8.1: - * "The master secret is always exactly 48 bytes in length." */ - size_t const master_secret_len = 48; + ssl->conf = conf; -#if defined(MBEDTLS_SSL_EXTENDED_MASTER_SECRET) - unsigned char session_hash[48]; -#endif /* MBEDTLS_SSL_EXTENDED_MASTER_SECRET */ + if ((ret = ssl_conf_check(ssl)) != 0) { + return ret; + } + ssl->tls_version = ssl->conf->max_tls_version; - /* The label for the KDF used for key expansion. - * This is either "master secret" or "extended master secret" - * depending on whether the Extended Master Secret extension - * is used. */ - char const *lbl = "master secret"; + /* + * Prepare base structures + */ - /* The salt for the KDF used for key expansion. - * - If the Extended Master Secret extension is not used, - * this is ClientHello.Random + ServerHello.Random - * (see Sect. 8.1 in RFC 5246). - * - If the Extended Master Secret extension is used, - * this is the transcript of the handshake so far. - * (see Sect. 4 in RFC 7627). */ - unsigned char const *salt = handshake->randbytes; - size_t salt_len = 64; + /* Set to NULL in case of an error condition */ + ssl->out_buf = NULL; -#if !defined(MBEDTLS_DEBUG_C) && \ - !defined(MBEDTLS_SSL_EXTENDED_MASTER_SECRET) && \ - !(defined(MBEDTLS_USE_PSA_CRYPTO) && \ - defined(MBEDTLS_KEY_EXCHANGE_PSK_ENABLED)) - ssl = NULL; /* make sure we don't use it except for those cases */ - (void) ssl; +#if defined(MBEDTLS_SSL_VARIABLE_BUFFER_LENGTH) + ssl->in_buf_len = in_buf_len; #endif - - if (handshake->resume != 0) { - MBEDTLS_SSL_DEBUG_MSG(3, ("no premaster (session resumed)")); - return 0; + ssl->in_buf = mbedtls_calloc(1, in_buf_len); + if (ssl->in_buf == NULL) { + MBEDTLS_SSL_DEBUG_MSG(1, ("alloc(%" MBEDTLS_PRINTF_SIZET " bytes) failed", in_buf_len)); + ret = MBEDTLS_ERR_SSL_ALLOC_FAILED; + goto error; } -#if defined(MBEDTLS_SSL_EXTENDED_MASTER_SECRET) - if (handshake->extended_ms == MBEDTLS_SSL_EXTENDED_MS_ENABLED) { - lbl = "extended master secret"; - salt = session_hash; - handshake->calc_verify(ssl, session_hash, &salt_len); - - MBEDTLS_SSL_DEBUG_BUF(3, "session hash for extended master secret", - session_hash, salt_len); +#if defined(MBEDTLS_SSL_VARIABLE_BUFFER_LENGTH) + ssl->out_buf_len = out_buf_len; +#endif + ssl->out_buf = mbedtls_calloc(1, out_buf_len); + if (ssl->out_buf == NULL) { + MBEDTLS_SSL_DEBUG_MSG(1, ("alloc(%" MBEDTLS_PRINTF_SIZET " bytes) failed", out_buf_len)); + ret = MBEDTLS_ERR_SSL_ALLOC_FAILED; + goto error; } -#endif /* MBEDTLS_SSL_EXTENDED_MS_ENABLED */ -#if defined(MBEDTLS_USE_PSA_CRYPTO) && \ - defined(MBEDTLS_KEY_EXCHANGE_PSK_ENABLED) - if (handshake->ciphersuite_info->key_exchange == MBEDTLS_KEY_EXCHANGE_PSK && - ssl->minor_ver == MBEDTLS_SSL_MINOR_VERSION_3 && - ssl_use_opaque_psk(ssl) == 1) { - /* Perform PSK-to-MS expansion in a single step. */ - psa_status_t status; - psa_algorithm_t alg; - psa_key_id_t psk; - psa_key_derivation_operation_t derivation = - PSA_KEY_DERIVATION_OPERATION_INIT; - mbedtls_md_type_t hash_alg = handshake->ciphersuite_info->mac; + mbedtls_ssl_reset_in_out_pointers(ssl); - MBEDTLS_SSL_DEBUG_MSG(2, ("perform PSA-based PSK-to-MS expansion")); +#if defined(MBEDTLS_SSL_DTLS_SRTP) + memset(&ssl->dtls_srtp_info, 0, sizeof(ssl->dtls_srtp_info)); +#endif - psk = mbedtls_ssl_get_opaque_psk(ssl); + if ((ret = ssl_handshake_init(ssl)) != 0) { + goto error; + } - if (hash_alg == MBEDTLS_MD_SHA384) { - alg = PSA_ALG_TLS12_PSK_TO_MS(PSA_ALG_SHA_384); - } else { - alg = PSA_ALG_TLS12_PSK_TO_MS(PSA_ALG_SHA_256); - } + return 0; - status = setup_psa_key_derivation(&derivation, psk, alg, - salt, salt_len, - (unsigned char const *) lbl, - (size_t) strlen(lbl), - master_secret_len); - if (status != PSA_SUCCESS) { - psa_key_derivation_abort(&derivation); - return MBEDTLS_ERR_SSL_HW_ACCEL_FAILED; - } +error: + mbedtls_free(ssl->in_buf); + mbedtls_free(ssl->out_buf); - status = psa_key_derivation_output_bytes(&derivation, - master, - master_secret_len); - if (status != PSA_SUCCESS) { - psa_key_derivation_abort(&derivation); - return MBEDTLS_ERR_SSL_HW_ACCEL_FAILED; - } + ssl->conf = NULL; - status = psa_key_derivation_abort(&derivation); - if (status != PSA_SUCCESS) { - return MBEDTLS_ERR_SSL_HW_ACCEL_FAILED; - } - } else +#if defined(MBEDTLS_SSL_VARIABLE_BUFFER_LENGTH) + ssl->in_buf_len = 0; + ssl->out_buf_len = 0; #endif - { - ret = handshake->tls_prf(handshake->premaster, handshake->pmslen, - lbl, salt, salt_len, - master, - master_secret_len); - if (ret != 0) { - MBEDTLS_SSL_DEBUG_RET(1, "prf", ret); - return ret; - } - - MBEDTLS_SSL_DEBUG_BUF(3, "premaster secret", - handshake->premaster, - handshake->pmslen); + ssl->in_buf = NULL; + ssl->out_buf = NULL; - mbedtls_platform_zeroize(handshake->premaster, - sizeof(handshake->premaster)); - } + ssl->in_hdr = NULL; + ssl->in_ctr = NULL; + ssl->in_len = NULL; + ssl->in_iv = NULL; + ssl->in_msg = NULL; - return 0; + ssl->out_hdr = NULL; + ssl->out_ctr = NULL; + ssl->out_len = NULL; + ssl->out_iv = NULL; + ssl->out_msg = NULL; + + return ret; } -int mbedtls_ssl_derive_keys(mbedtls_ssl_context *ssl) +/* + * Reset an initialized and used SSL context for re-use while retaining + * all application-set variables, function pointers and data. + * + * If partial is non-zero, keep data in the input buffer and client ID. + * (Use when a DTLS client reconnects from the same port.) + */ +void mbedtls_ssl_session_reset_msg_layer(mbedtls_ssl_context *ssl, + int partial) { - int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED; - const mbedtls_ssl_ciphersuite_t * const ciphersuite_info = - ssl->handshake->ciphersuite_info; +#if defined(MBEDTLS_SSL_VARIABLE_BUFFER_LENGTH) + size_t in_buf_len = ssl->in_buf_len; + size_t out_buf_len = ssl->out_buf_len; +#else + size_t in_buf_len = MBEDTLS_SSL_IN_BUFFER_LEN; + size_t out_buf_len = MBEDTLS_SSL_OUT_BUFFER_LEN; +#endif - MBEDTLS_SSL_DEBUG_MSG(2, ("=> derive keys")); +#if !defined(MBEDTLS_SSL_DTLS_CLIENT_PORT_REUSE) || !defined(MBEDTLS_SSL_SRV_C) + partial = 0; +#endif - /* Set PRF, calc_verify and calc_finished function pointers */ - ret = ssl_set_handshake_prfs(ssl->handshake, - ssl->minor_ver, - ciphersuite_info->mac); - if (ret != 0) { - MBEDTLS_SSL_DEBUG_RET(1, "ssl_set_handshake_prfs", ret); - return ret; - } + /* Cancel any possibly running timer */ + mbedtls_ssl_set_timer(ssl, 0); - /* Compute master secret if needed */ - ret = ssl_compute_master(ssl->handshake, - ssl->session_negotiate->master, - ssl); - if (ret != 0) { - MBEDTLS_SSL_DEBUG_RET(1, "ssl_compute_master", ret); - return ret; - } + mbedtls_ssl_reset_in_out_pointers(ssl); - /* Swap the client and server random values: - * - MS derivation wanted client+server (RFC 5246 8.1) - * - key derivation wants server+client (RFC 5246 6.3) */ - { - unsigned char tmp[64]; - memcpy(tmp, ssl->handshake->randbytes, 64); - memcpy(ssl->handshake->randbytes, tmp + 32, 32); - memcpy(ssl->handshake->randbytes + 32, tmp, 32); - mbedtls_platform_zeroize(tmp, sizeof(tmp)); - } + /* Reset incoming message parsing */ + ssl->in_offt = NULL; + ssl->nb_zero = 0; + ssl->in_msgtype = 0; + ssl->in_msglen = 0; + ssl->in_hslen = 0; + ssl->keep_current_message = 0; + ssl->transform_in = NULL; - /* Populate transform structure */ - ret = ssl_populate_transform(ssl->transform_negotiate, - ssl->session_negotiate->ciphersuite, - ssl->session_negotiate->master, -#if defined(MBEDTLS_SSL_SOME_MODES_USE_MAC) -#if defined(MBEDTLS_SSL_ENCRYPT_THEN_MAC) - ssl->session_negotiate->encrypt_then_mac, -#endif /* MBEDTLS_SSL_ENCRYPT_THEN_MAC */ -#if defined(MBEDTLS_SSL_TRUNCATED_HMAC) - ssl->session_negotiate->trunc_hmac, -#endif /* MBEDTLS_SSL_TRUNCATED_HMAC */ -#endif /* MBEDTLS_SSL_SOME_MODES_USE_MAC */ -#if defined(MBEDTLS_ZLIB_SUPPORT) - ssl->session_negotiate->compression, -#endif - ssl->handshake->tls_prf, - ssl->handshake->randbytes, - ssl->minor_ver, - ssl->conf->endpoint, - ssl); - if (ret != 0) { - MBEDTLS_SSL_DEBUG_RET(1, "ssl_populate_transform", ret); - return ret; +#if defined(MBEDTLS_SSL_PROTO_DTLS) + ssl->next_record_offset = 0; + ssl->in_epoch = 0; +#endif + + /* Keep current datagram if partial == 1 */ + if (partial == 0) { + ssl->in_left = 0; + memset(ssl->in_buf, 0, in_buf_len); } - /* We no longer need Server/ClientHello.random values */ - mbedtls_platform_zeroize(ssl->handshake->randbytes, - sizeof(ssl->handshake->randbytes)); + ssl->send_alert = 0; - /* Allocate compression buffer */ -#if defined(MBEDTLS_ZLIB_SUPPORT) - if (ssl->session_negotiate->compression == MBEDTLS_SSL_COMPRESS_DEFLATE && - ssl->compress_buf == NULL) { - MBEDTLS_SSL_DEBUG_MSG(3, ("Allocating compression buffer")); - ssl->compress_buf = mbedtls_calloc(1, MBEDTLS_SSL_COMPRESS_BUFFER_LEN); - if (ssl->compress_buf == NULL) { - MBEDTLS_SSL_DEBUG_MSG(1, ("alloc(%d bytes) failed", - MBEDTLS_SSL_COMPRESS_BUFFER_LEN)); - return MBEDTLS_ERR_SSL_ALLOC_FAILED; - } - } + /* Reset outgoing message writing */ + ssl->out_msgtype = 0; + ssl->out_msglen = 0; + ssl->out_left = 0; + memset(ssl->out_buf, 0, out_buf_len); + memset(ssl->cur_out_ctr, 0, sizeof(ssl->cur_out_ctr)); + ssl->transform_out = NULL; + +#if defined(MBEDTLS_SSL_DTLS_ANTI_REPLAY) + mbedtls_ssl_dtls_replay_reset(ssl); #endif - MBEDTLS_SSL_DEBUG_MSG(2, ("<= derive keys")); +#if defined(MBEDTLS_SSL_PROTO_TLS1_2) + if (ssl->transform) { + mbedtls_ssl_transform_free(ssl->transform); + mbedtls_free(ssl->transform); + ssl->transform = NULL; + } +#endif /* MBEDTLS_SSL_PROTO_TLS1_2 */ - return 0; -} +#if defined(MBEDTLS_SSL_PROTO_TLS1_3) + mbedtls_ssl_transform_free(ssl->transform_application); + mbedtls_free(ssl->transform_application); + ssl->transform_application = NULL; -#if defined(MBEDTLS_SSL_PROTO_SSL3) -void ssl_calc_verify_ssl(const mbedtls_ssl_context *ssl, - unsigned char *hash, - size_t *hlen) -{ - mbedtls_md5_context md5; - mbedtls_sha1_context sha1; - unsigned char pad_1[48]; - unsigned char pad_2[48]; + if (ssl->handshake != NULL) { +#if defined(MBEDTLS_SSL_EARLY_DATA) + mbedtls_ssl_transform_free(ssl->handshake->transform_earlydata); + mbedtls_free(ssl->handshake->transform_earlydata); + ssl->handshake->transform_earlydata = NULL; +#endif - MBEDTLS_SSL_DEBUG_MSG(2, ("=> calc verify ssl")); + mbedtls_ssl_transform_free(ssl->handshake->transform_handshake); + mbedtls_free(ssl->handshake->transform_handshake); + ssl->handshake->transform_handshake = NULL; + } - mbedtls_md5_init(&md5); - mbedtls_sha1_init(&sha1); +#endif /* MBEDTLS_SSL_PROTO_TLS1_3 */ +} - mbedtls_md5_clone(&md5, &ssl->handshake->fin_md5); - mbedtls_sha1_clone(&sha1, &ssl->handshake->fin_sha1); +int mbedtls_ssl_session_reset_int(mbedtls_ssl_context *ssl, int partial) +{ + int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED; - memset(pad_1, 0x36, 48); - memset(pad_2, 0x5C, 48); + ssl->state = MBEDTLS_SSL_HELLO_REQUEST; + ssl->tls_version = ssl->conf->max_tls_version; - mbedtls_md5_update_ret(&md5, ssl->session_negotiate->master, 48); - mbedtls_md5_update_ret(&md5, pad_1, 48); - mbedtls_md5_finish_ret(&md5, hash); + mbedtls_ssl_session_reset_msg_layer(ssl, partial); - mbedtls_md5_starts_ret(&md5); - mbedtls_md5_update_ret(&md5, ssl->session_negotiate->master, 48); - mbedtls_md5_update_ret(&md5, pad_2, 48); - mbedtls_md5_update_ret(&md5, hash, 16); - mbedtls_md5_finish_ret(&md5, hash); + /* Reset renegotiation state */ +#if defined(MBEDTLS_SSL_RENEGOTIATION) + ssl->renego_status = MBEDTLS_SSL_INITIAL_HANDSHAKE; + ssl->renego_records_seen = 0; - mbedtls_sha1_update_ret(&sha1, ssl->session_negotiate->master, 48); - mbedtls_sha1_update_ret(&sha1, pad_1, 40); - mbedtls_sha1_finish_ret(&sha1, hash + 16); + ssl->verify_data_len = 0; + memset(ssl->own_verify_data, 0, MBEDTLS_SSL_VERIFY_DATA_MAX_LEN); + memset(ssl->peer_verify_data, 0, MBEDTLS_SSL_VERIFY_DATA_MAX_LEN); +#endif + ssl->secure_renegotiation = MBEDTLS_SSL_LEGACY_RENEGOTIATION; - mbedtls_sha1_starts_ret(&sha1); - mbedtls_sha1_update_ret(&sha1, ssl->session_negotiate->master, 48); - mbedtls_sha1_update_ret(&sha1, pad_2, 40); - mbedtls_sha1_update_ret(&sha1, hash + 16, 20); - mbedtls_sha1_finish_ret(&sha1, hash + 16); + ssl->session_in = NULL; + ssl->session_out = NULL; + if (ssl->session) { + mbedtls_ssl_session_free(ssl->session); + mbedtls_free(ssl->session); + ssl->session = NULL; + } - *hlen = 36; +#if defined(MBEDTLS_SSL_ALPN) + ssl->alpn_chosen = NULL; +#endif - MBEDTLS_SSL_DEBUG_BUF(3, "calculated verify result", hash, *hlen); - MBEDTLS_SSL_DEBUG_MSG(2, ("<= calc verify")); +#if defined(MBEDTLS_SSL_DTLS_HELLO_VERIFY) && defined(MBEDTLS_SSL_SRV_C) + int free_cli_id = 1; +#if defined(MBEDTLS_SSL_DTLS_CLIENT_PORT_REUSE) + free_cli_id = (partial == 0); +#endif + if (free_cli_id) { + mbedtls_free(ssl->cli_id); + ssl->cli_id = NULL; + ssl->cli_id_len = 0; + } +#endif - mbedtls_md5_free(&md5); - mbedtls_sha1_free(&sha1); + if ((ret = ssl_handshake_init(ssl)) != 0) { + return ret; + } - return; + return 0; } -#endif /* MBEDTLS_SSL_PROTO_SSL3 */ -#if defined(MBEDTLS_SSL_PROTO_TLS1) || defined(MBEDTLS_SSL_PROTO_TLS1_1) -void ssl_calc_verify_tls(const mbedtls_ssl_context *ssl, - unsigned char *hash, - size_t *hlen) +/* + * Reset an initialized and used SSL context for re-use while retaining + * all application-set variables, function pointers and data. + */ +int mbedtls_ssl_session_reset(mbedtls_ssl_context *ssl) { - mbedtls_md5_context md5; - mbedtls_sha1_context sha1; - - MBEDTLS_SSL_DEBUG_MSG(2, ("=> calc verify tls")); - - mbedtls_md5_init(&md5); - mbedtls_sha1_init(&sha1); + return mbedtls_ssl_session_reset_int(ssl, 0); +} - mbedtls_md5_clone(&md5, &ssl->handshake->fin_md5); - mbedtls_sha1_clone(&sha1, &ssl->handshake->fin_sha1); +/* + * SSL set accessors + */ +void mbedtls_ssl_conf_endpoint(mbedtls_ssl_config *conf, int endpoint) +{ + conf->endpoint = endpoint; +} - mbedtls_md5_finish_ret(&md5, hash); - mbedtls_sha1_finish_ret(&sha1, hash + 16); +void mbedtls_ssl_conf_transport(mbedtls_ssl_config *conf, int transport) +{ + conf->transport = transport; +} - *hlen = 36; +#if defined(MBEDTLS_SSL_DTLS_ANTI_REPLAY) +void mbedtls_ssl_conf_dtls_anti_replay(mbedtls_ssl_config *conf, char mode) +{ + conf->anti_replay = mode; +} +#endif - MBEDTLS_SSL_DEBUG_BUF(3, "calculated verify result", hash, *hlen); - MBEDTLS_SSL_DEBUG_MSG(2, ("<= calc verify")); +void mbedtls_ssl_conf_dtls_badmac_limit(mbedtls_ssl_config *conf, unsigned limit) +{ + conf->badmac_limit = limit; +} - mbedtls_md5_free(&md5); - mbedtls_sha1_free(&sha1); +#if defined(MBEDTLS_SSL_PROTO_DTLS) - return; +void mbedtls_ssl_set_datagram_packing(mbedtls_ssl_context *ssl, + unsigned allow_packing) +{ + ssl->disable_datagram_packing = !allow_packing; } -#endif /* MBEDTLS_SSL_PROTO_TLS1 || MBEDTLS_SSL_PROTO_TLS1_1 */ -#if defined(MBEDTLS_SSL_PROTO_TLS1_2) -#if defined(MBEDTLS_SHA256_C) -void ssl_calc_verify_tls_sha256(const mbedtls_ssl_context *ssl, - unsigned char *hash, - size_t *hlen) +void mbedtls_ssl_conf_handshake_timeout(mbedtls_ssl_config *conf, + uint32_t min, uint32_t max) { -#if defined(MBEDTLS_USE_PSA_CRYPTO) - size_t hash_size; - psa_status_t status; - psa_hash_operation_t sha256_psa = psa_hash_operation_init(); + conf->hs_timeout_min = min; + conf->hs_timeout_max = max; +} +#endif - MBEDTLS_SSL_DEBUG_MSG(2, ("=> PSA calc verify sha256")); - status = psa_hash_clone(&ssl->handshake->fin_sha256_psa, &sha256_psa); - if (status != PSA_SUCCESS) { - MBEDTLS_SSL_DEBUG_MSG(2, ("PSA hash clone failed")); - return; - } +void mbedtls_ssl_conf_authmode(mbedtls_ssl_config *conf, int authmode) +{ + conf->authmode = authmode; +} - status = psa_hash_finish(&sha256_psa, hash, 32, &hash_size); - if (status != PSA_SUCCESS) { - MBEDTLS_SSL_DEBUG_MSG(2, ("PSA hash finish failed")); - return; - } +#if defined(MBEDTLS_X509_CRT_PARSE_C) +void mbedtls_ssl_conf_verify(mbedtls_ssl_config *conf, + int (*f_vrfy)(void *, mbedtls_x509_crt *, int, uint32_t *), + void *p_vrfy) +{ + conf->f_vrfy = f_vrfy; + conf->p_vrfy = p_vrfy; +} +#endif /* MBEDTLS_X509_CRT_PARSE_C */ - *hlen = 32; - MBEDTLS_SSL_DEBUG_BUF(3, "PSA calculated verify result", hash, *hlen); - MBEDTLS_SSL_DEBUG_MSG(2, ("<= PSA calc verify")); -#else - mbedtls_sha256_context sha256; +void mbedtls_ssl_conf_rng(mbedtls_ssl_config *conf, + int (*f_rng)(void *, unsigned char *, size_t), + void *p_rng) +{ + conf->f_rng = f_rng; + conf->p_rng = p_rng; +} - mbedtls_sha256_init(&sha256); +void mbedtls_ssl_conf_dbg(mbedtls_ssl_config *conf, + void (*f_dbg)(void *, int, const char *, int, const char *), + void *p_dbg) +{ + conf->f_dbg = f_dbg; + conf->p_dbg = p_dbg; +} - MBEDTLS_SSL_DEBUG_MSG(2, ("=> calc verify sha256")); +void mbedtls_ssl_set_bio(mbedtls_ssl_context *ssl, + void *p_bio, + mbedtls_ssl_send_t *f_send, + mbedtls_ssl_recv_t *f_recv, + mbedtls_ssl_recv_timeout_t *f_recv_timeout) +{ + ssl->p_bio = p_bio; + ssl->f_send = f_send; + ssl->f_recv = f_recv; + ssl->f_recv_timeout = f_recv_timeout; +} - mbedtls_sha256_clone(&sha256, &ssl->handshake->fin_sha256); - mbedtls_sha256_finish_ret(&sha256, hash); +#if defined(MBEDTLS_SSL_PROTO_DTLS) +void mbedtls_ssl_set_mtu(mbedtls_ssl_context *ssl, uint16_t mtu) +{ + ssl->mtu = mtu; +} +#endif - *hlen = 32; +void mbedtls_ssl_conf_read_timeout(mbedtls_ssl_config *conf, uint32_t timeout) +{ + conf->read_timeout = timeout; +} - MBEDTLS_SSL_DEBUG_BUF(3, "calculated verify result", hash, *hlen); - MBEDTLS_SSL_DEBUG_MSG(2, ("<= calc verify")); +void mbedtls_ssl_set_timer_cb(mbedtls_ssl_context *ssl, + void *p_timer, + mbedtls_ssl_set_timer_t *f_set_timer, + mbedtls_ssl_get_timer_t *f_get_timer) +{ + ssl->p_timer = p_timer; + ssl->f_set_timer = f_set_timer; + ssl->f_get_timer = f_get_timer; - mbedtls_sha256_free(&sha256); -#endif /* MBEDTLS_USE_PSA_CRYPTO */ - return; + /* Make sure we start with no timer running */ + mbedtls_ssl_set_timer(ssl, 0); } -#endif /* MBEDTLS_SHA256_C */ -#if defined(MBEDTLS_SHA512_C) && !defined(MBEDTLS_SHA512_NO_SHA384) -void ssl_calc_verify_tls_sha384(const mbedtls_ssl_context *ssl, - unsigned char *hash, - size_t *hlen) +#if defined(MBEDTLS_SSL_SRV_C) +void mbedtls_ssl_conf_session_cache(mbedtls_ssl_config *conf, + void *p_cache, + mbedtls_ssl_cache_get_t *f_get_cache, + mbedtls_ssl_cache_set_t *f_set_cache) { -#if defined(MBEDTLS_USE_PSA_CRYPTO) - size_t hash_size; - psa_status_t status; - psa_hash_operation_t sha384_psa = psa_hash_operation_init(); - - MBEDTLS_SSL_DEBUG_MSG(2, ("=> PSA calc verify sha384")); - status = psa_hash_clone(&ssl->handshake->fin_sha384_psa, &sha384_psa); - if (status != PSA_SUCCESS) { - MBEDTLS_SSL_DEBUG_MSG(2, ("PSA hash clone failed")); - return; - } - - status = psa_hash_finish(&sha384_psa, hash, 48, &hash_size); - if (status != PSA_SUCCESS) { - MBEDTLS_SSL_DEBUG_MSG(2, ("PSA hash finish failed")); - return; - } - - *hlen = 48; - MBEDTLS_SSL_DEBUG_BUF(3, "PSA calculated verify result", hash, *hlen); - MBEDTLS_SSL_DEBUG_MSG(2, ("<= PSA calc verify")); -#else - mbedtls_sha512_context sha512; - - mbedtls_sha512_init(&sha512); - - MBEDTLS_SSL_DEBUG_MSG(2, ("=> calc verify sha384")); - - mbedtls_sha512_clone(&sha512, &ssl->handshake->fin_sha512); - mbedtls_sha512_finish_ret(&sha512, hash); - - *hlen = 48; - - MBEDTLS_SSL_DEBUG_BUF(3, "calculated verify result", hash, *hlen); - MBEDTLS_SSL_DEBUG_MSG(2, ("<= calc verify")); - - mbedtls_sha512_free(&sha512); -#endif /* MBEDTLS_USE_PSA_CRYPTO */ - return; + conf->p_cache = p_cache; + conf->f_get_cache = f_get_cache; + conf->f_set_cache = f_set_cache; } -#endif /* MBEDTLS_SHA512_C && !MBEDTLS_SHA512_NO_SHA384 */ -#endif /* MBEDTLS_SSL_PROTO_TLS1_2 */ +#endif /* MBEDTLS_SSL_SRV_C */ -#if defined(MBEDTLS_KEY_EXCHANGE_SOME_PSK_ENABLED) -int mbedtls_ssl_psk_derive_premaster(mbedtls_ssl_context *ssl, mbedtls_key_exchange_type_t key_ex) +#if defined(MBEDTLS_SSL_CLI_C) +int mbedtls_ssl_set_session(mbedtls_ssl_context *ssl, const mbedtls_ssl_session *session) { - unsigned char *p = ssl->handshake->premaster; - unsigned char *end = p + sizeof(ssl->handshake->premaster); - const unsigned char *psk = NULL; - size_t psk_len = 0; + int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED; - if (mbedtls_ssl_get_psk(ssl, &psk, &psk_len) - == MBEDTLS_ERR_SSL_PRIVATE_KEY_REQUIRED) { - /* - * This should never happen because the existence of a PSK is always - * checked before calling this function - */ - MBEDTLS_SSL_DEBUG_MSG(1, ("should never happen")); - return MBEDTLS_ERR_SSL_INTERNAL_ERROR; + if (ssl == NULL || + session == NULL || + ssl->session_negotiate == NULL || + ssl->conf->endpoint != MBEDTLS_SSL_IS_CLIENT) { + return MBEDTLS_ERR_SSL_BAD_INPUT_DATA; } - /* - * PMS = struct { - * opaque other_secret<0..2^16-1>; - * opaque psk<0..2^16-1>; - * }; - * with "other_secret" depending on the particular key exchange - */ -#if defined(MBEDTLS_KEY_EXCHANGE_PSK_ENABLED) - if (key_ex == MBEDTLS_KEY_EXCHANGE_PSK) { - if (end - p < 2) { - return MBEDTLS_ERR_SSL_BAD_INPUT_DATA; - } - - MBEDTLS_PUT_UINT16_BE(psk_len, p, 0); - p += 2; + if (ssl->handshake->resume == 1) { + return MBEDTLS_ERR_SSL_FEATURE_UNAVAILABLE; + } - if (end < p || (size_t) (end - p) < psk_len) { - return MBEDTLS_ERR_SSL_BAD_INPUT_DATA; - } +#if defined(MBEDTLS_SSL_PROTO_TLS1_3) + if (session->tls_version == MBEDTLS_SSL_VERSION_TLS1_3) { + const mbedtls_ssl_ciphersuite_t *ciphersuite_info = + mbedtls_ssl_ciphersuite_from_id(session->ciphersuite); - memset(p, 0, psk_len); - p += psk_len; - } else -#endif /* MBEDTLS_KEY_EXCHANGE_PSK_ENABLED */ -#if defined(MBEDTLS_KEY_EXCHANGE_RSA_PSK_ENABLED) - if (key_ex == MBEDTLS_KEY_EXCHANGE_RSA_PSK) { - /* - * other_secret already set by the ClientKeyExchange message, - * and is 48 bytes long - */ - if (end - p < 2) { + if (mbedtls_ssl_validate_ciphersuite( + ssl, ciphersuite_info, MBEDTLS_SSL_VERSION_TLS1_3, + MBEDTLS_SSL_VERSION_TLS1_3) != 0) { + MBEDTLS_SSL_DEBUG_MSG(4, ("%d is not a valid TLS 1.3 ciphersuite.", + session->ciphersuite)); return MBEDTLS_ERR_SSL_BAD_INPUT_DATA; } - - *p++ = 0; - *p++ = 48; - p += 48; - } else -#endif /* MBEDTLS_KEY_EXCHANGE_RSA_PSK_ENABLED */ -#if defined(MBEDTLS_KEY_EXCHANGE_DHE_PSK_ENABLED) - if (key_ex == MBEDTLS_KEY_EXCHANGE_DHE_PSK) { - int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED; - size_t len; - - /* Write length only when we know the actual value */ - if ((ret = mbedtls_dhm_calc_secret(&ssl->handshake->dhm_ctx, - p + 2, end - (p + 2), &len, - ssl->conf->f_rng, ssl->conf->p_rng)) != 0) { - MBEDTLS_SSL_DEBUG_RET(1, "mbedtls_dhm_calc_secret", ret); - return ret; - } - MBEDTLS_PUT_UINT16_BE(len, p, 0); - p += 2 + len; - - MBEDTLS_SSL_DEBUG_MPI(3, "DHM: K ", &ssl->handshake->dhm_ctx.K); - } else -#endif /* MBEDTLS_KEY_EXCHANGE_DHE_PSK_ENABLED */ -#if defined(MBEDTLS_KEY_EXCHANGE_ECDHE_PSK_ENABLED) - if (key_ex == MBEDTLS_KEY_EXCHANGE_ECDHE_PSK) { - int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED; - size_t zlen; - - if ((ret = mbedtls_ecdh_calc_secret(&ssl->handshake->ecdh_ctx, &zlen, - p + 2, end - (p + 2), - ssl->conf->f_rng, ssl->conf->p_rng)) != 0) { - MBEDTLS_SSL_DEBUG_RET(1, "mbedtls_ecdh_calc_secret", ret); - return ret; - } - - MBEDTLS_PUT_UINT16_BE(zlen, p, 0); - p += 2 + zlen; - - MBEDTLS_SSL_DEBUG_ECDH(3, &ssl->handshake->ecdh_ctx, - MBEDTLS_DEBUG_ECDH_Z); - } else -#endif /* MBEDTLS_KEY_EXCHANGE_ECDHE_PSK_ENABLED */ - { - MBEDTLS_SSL_DEBUG_MSG(1, ("should never happen")); - return MBEDTLS_ERR_SSL_INTERNAL_ERROR; - } - - /* opaque psk<0..2^16-1>; */ - if (end - p < 2) { - return MBEDTLS_ERR_SSL_BAD_INPUT_DATA; } +#endif /* MBEDTLS_SSL_PROTO_TLS1_3 */ - MBEDTLS_PUT_UINT16_BE(psk_len, p, 0); - p += 2; - - if (end < p || (size_t) (end - p) < psk_len) { - return MBEDTLS_ERR_SSL_BAD_INPUT_DATA; + if ((ret = mbedtls_ssl_session_copy(ssl->session_negotiate, + session)) != 0) { + return ret; } - memcpy(p, psk, psk_len); - p += psk_len; - - ssl->handshake->pmslen = p - ssl->handshake->premaster; + ssl->handshake->resume = 1; return 0; } -#endif /* MBEDTLS_KEY_EXCHANGE_SOME_PSK_ENABLED */ - -#if defined(MBEDTLS_SSL_SRV_C) && defined(MBEDTLS_SSL_RENEGOTIATION) -MBEDTLS_CHECK_RETURN_CRITICAL -static int ssl_write_hello_request(mbedtls_ssl_context *ssl); +#endif /* MBEDTLS_SSL_CLI_C */ -#if defined(MBEDTLS_SSL_PROTO_DTLS) -int mbedtls_ssl_resend_hello_request(mbedtls_ssl_context *ssl) +void mbedtls_ssl_conf_ciphersuites(mbedtls_ssl_config *conf, + const int *ciphersuites) { - /* If renegotiation is not enforced, retransmit until we would reach max - * timeout if we were using the usual handshake doubling scheme */ - if (ssl->conf->renego_max_records < 0) { - uint32_t ratio = ssl->conf->hs_timeout_max / ssl->conf->hs_timeout_min + 1; - unsigned char doublings = 1; - - while (ratio != 0) { - ++doublings; - ratio >>= 1; - } - - if (++ssl->renego_records_seen > doublings) { - MBEDTLS_SSL_DEBUG_MSG(2, ("no longer retransmitting hello request")); - return 0; - } - } - - return ssl_write_hello_request(ssl); + conf->ciphersuite_list = ciphersuites; } -#endif -#endif /* MBEDTLS_SSL_SRV_C && MBEDTLS_SSL_RENEGOTIATION */ -#if defined(MBEDTLS_X509_CRT_PARSE_C) -static void ssl_clear_peer_cert(mbedtls_ssl_session *session) +#if defined(MBEDTLS_SSL_PROTO_TLS1_3) +void mbedtls_ssl_conf_tls13_key_exchange_modes(mbedtls_ssl_config *conf, + const int kex_modes) { -#if defined(MBEDTLS_SSL_KEEP_PEER_CERTIFICATE) - if (session->peer_cert != NULL) { - mbedtls_x509_crt_free(session->peer_cert); - mbedtls_free(session->peer_cert); - session->peer_cert = NULL; - } -#else /* MBEDTLS_SSL_KEEP_PEER_CERTIFICATE */ - if (session->peer_cert_digest != NULL) { - /* Zeroization is not necessary. */ - mbedtls_free(session->peer_cert_digest); - session->peer_cert_digest = NULL; - session->peer_cert_digest_type = MBEDTLS_MD_NONE; - session->peer_cert_digest_len = 0; - } -#endif /* !MBEDTLS_SSL_KEEP_PEER_CERTIFICATE */ + conf->tls13_kex_modes = kex_modes & MBEDTLS_SSL_TLS1_3_KEY_EXCHANGE_MODE_ALL; } -#endif /* MBEDTLS_X509_CRT_PARSE_C */ -/* - * Handshake functions - */ -#if !defined(MBEDTLS_KEY_EXCHANGE_WITH_CERT_ENABLED) -/* No certificate support -> dummy functions */ -int mbedtls_ssl_write_certificate(mbedtls_ssl_context *ssl) +#if defined(MBEDTLS_SSL_EARLY_DATA) +void mbedtls_ssl_conf_early_data(mbedtls_ssl_config *conf, + int early_data_enabled) { - const mbedtls_ssl_ciphersuite_t *ciphersuite_info = - ssl->handshake->ciphersuite_info; + conf->early_data_enabled = early_data_enabled; +} - MBEDTLS_SSL_DEBUG_MSG(2, ("=> write certificate")); +#if defined(MBEDTLS_SSL_SRV_C) +void mbedtls_ssl_conf_max_early_data_size( + mbedtls_ssl_config *conf, uint32_t max_early_data_size) +{ + conf->max_early_data_size = max_early_data_size; +} +#endif /* MBEDTLS_SSL_SRV_C */ - if (!mbedtls_ssl_ciphersuite_uses_srv_cert(ciphersuite_info)) { - MBEDTLS_SSL_DEBUG_MSG(2, ("<= skip write certificate")); - ssl->state++; - return 0; - } +#endif /* MBEDTLS_SSL_EARLY_DATA */ +#endif /* MBEDTLS_SSL_PROTO_TLS1_3 */ - MBEDTLS_SSL_DEBUG_MSG(1, ("should never happen")); - return MBEDTLS_ERR_SSL_INTERNAL_ERROR; +#if defined(MBEDTLS_X509_CRT_PARSE_C) +void mbedtls_ssl_conf_cert_profile(mbedtls_ssl_config *conf, + const mbedtls_x509_crt_profile *profile) +{ + conf->cert_profile = profile; } -int mbedtls_ssl_parse_certificate(mbedtls_ssl_context *ssl) +static void ssl_key_cert_free(mbedtls_ssl_key_cert *key_cert) { - const mbedtls_ssl_ciphersuite_t *ciphersuite_info = - ssl->handshake->ciphersuite_info; - - MBEDTLS_SSL_DEBUG_MSG(2, ("=> parse certificate")); + mbedtls_ssl_key_cert *cur = key_cert, *next; - if (!mbedtls_ssl_ciphersuite_uses_srv_cert(ciphersuite_info)) { - MBEDTLS_SSL_DEBUG_MSG(2, ("<= skip parse certificate")); - ssl->state++; - return 0; + while (cur != NULL) { + next = cur->next; + mbedtls_free(cur); + cur = next; } - - MBEDTLS_SSL_DEBUG_MSG(1, ("should never happen")); - return MBEDTLS_ERR_SSL_INTERNAL_ERROR; } -#else /* MBEDTLS_KEY_EXCHANGE_WITH_CERT_ENABLED */ -/* Some certificate support -> implement write and parse */ - -int mbedtls_ssl_write_certificate(mbedtls_ssl_context *ssl) +/* Append a new keycert entry to a (possibly empty) list */ +MBEDTLS_CHECK_RETURN_CRITICAL +static int ssl_append_key_cert(mbedtls_ssl_key_cert **head, + mbedtls_x509_crt *cert, + mbedtls_pk_context *key) { - int ret = MBEDTLS_ERR_SSL_FEATURE_UNAVAILABLE; - size_t i, n; - const mbedtls_x509_crt *crt; - const mbedtls_ssl_ciphersuite_t *ciphersuite_info = - ssl->handshake->ciphersuite_info; - - MBEDTLS_SSL_DEBUG_MSG(2, ("=> write certificate")); + mbedtls_ssl_key_cert *new_cert; - if (!mbedtls_ssl_ciphersuite_uses_srv_cert(ciphersuite_info)) { - MBEDTLS_SSL_DEBUG_MSG(2, ("<= skip write certificate")); - ssl->state++; + if (cert == NULL) { + /* Free list if cert is null */ + ssl_key_cert_free(*head); + *head = NULL; return 0; } -#if defined(MBEDTLS_SSL_CLI_C) - if (ssl->conf->endpoint == MBEDTLS_SSL_IS_CLIENT) { - if (ssl->client_auth == 0) { - MBEDTLS_SSL_DEBUG_MSG(2, ("<= skip write certificate")); - ssl->state++; - return 0; - } + new_cert = mbedtls_calloc(1, sizeof(mbedtls_ssl_key_cert)); + if (new_cert == NULL) { + return MBEDTLS_ERR_SSL_ALLOC_FAILED; + } -#if defined(MBEDTLS_SSL_PROTO_SSL3) - /* - * If using SSLv3 and got no cert, send an Alert message - * (otherwise an empty Certificate message will be sent). - */ - if (mbedtls_ssl_own_cert(ssl) == NULL && - ssl->minor_ver == MBEDTLS_SSL_MINOR_VERSION_0) { - ssl->out_msglen = 2; - ssl->out_msgtype = MBEDTLS_SSL_MSG_ALERT; - ssl->out_msg[0] = MBEDTLS_SSL_ALERT_LEVEL_WARNING; - ssl->out_msg[1] = MBEDTLS_SSL_ALERT_MSG_NO_CERT; + new_cert->cert = cert; + new_cert->key = key; + new_cert->next = NULL; - MBEDTLS_SSL_DEBUG_MSG(2, ("got no certificate to send")); - goto write_msg; - } -#endif /* MBEDTLS_SSL_PROTO_SSL3 */ - } -#endif /* MBEDTLS_SSL_CLI_C */ -#if defined(MBEDTLS_SSL_SRV_C) - if (ssl->conf->endpoint == MBEDTLS_SSL_IS_SERVER) { - if (mbedtls_ssl_own_cert(ssl) == NULL) { - MBEDTLS_SSL_DEBUG_MSG(1, ("got no certificate to send")); - return MBEDTLS_ERR_SSL_CERTIFICATE_REQUIRED; + /* Update head if the list was null, else add to the end */ + if (*head == NULL) { + *head = new_cert; + } else { + mbedtls_ssl_key_cert *cur = *head; + while (cur->next != NULL) { + cur = cur->next; } + cur->next = new_cert; } -#endif - MBEDTLS_SSL_DEBUG_CRT(3, "own certificate", mbedtls_ssl_own_cert(ssl)); + return 0; +} - /* - * 0 . 0 handshake type - * 1 . 3 handshake length - * 4 . 6 length of all certs - * 7 . 9 length of cert. 1 - * 10 . n-1 peer certificate - * n . n+2 length of cert. 2 - * n+3 . ... upper level cert, etc. - */ - i = 7; - crt = mbedtls_ssl_own_cert(ssl); +int mbedtls_ssl_conf_own_cert(mbedtls_ssl_config *conf, + mbedtls_x509_crt *own_cert, + mbedtls_pk_context *pk_key) +{ + return ssl_append_key_cert(&conf->key_cert, own_cert, pk_key); +} - while (crt != NULL) { - n = crt->raw.len; - if (n > MBEDTLS_SSL_OUT_CONTENT_LEN - 3 - i) { - MBEDTLS_SSL_DEBUG_MSG(1, ("certificate too large, %" MBEDTLS_PRINTF_SIZET - " > %" MBEDTLS_PRINTF_SIZET, - i + 3 + n, (size_t) MBEDTLS_SSL_OUT_CONTENT_LEN)); - return MBEDTLS_ERR_SSL_CERTIFICATE_TOO_LARGE; - } +void mbedtls_ssl_conf_ca_chain(mbedtls_ssl_config *conf, + mbedtls_x509_crt *ca_chain, + mbedtls_x509_crl *ca_crl) +{ + conf->ca_chain = ca_chain; + conf->ca_crl = ca_crl; - ssl->out_msg[i] = MBEDTLS_BYTE_2(n); - ssl->out_msg[i + 1] = MBEDTLS_BYTE_1(n); - ssl->out_msg[i + 2] = MBEDTLS_BYTE_0(n); +#if defined(MBEDTLS_X509_TRUSTED_CERTIFICATE_CALLBACK) + /* mbedtls_ssl_conf_ca_chain() and mbedtls_ssl_conf_ca_cb() + * cannot be used together. */ + conf->f_ca_cb = NULL; + conf->p_ca_cb = NULL; +#endif /* MBEDTLS_X509_TRUSTED_CERTIFICATE_CALLBACK */ +} - i += 3; memcpy(ssl->out_msg + i, crt->raw.p, n); - i += n; crt = crt->next; - } +#if defined(MBEDTLS_X509_TRUSTED_CERTIFICATE_CALLBACK) +void mbedtls_ssl_conf_ca_cb(mbedtls_ssl_config *conf, + mbedtls_x509_crt_ca_cb_t f_ca_cb, + void *p_ca_cb) +{ + conf->f_ca_cb = f_ca_cb; + conf->p_ca_cb = p_ca_cb; - ssl->out_msg[4] = MBEDTLS_BYTE_2(i - 7); - ssl->out_msg[5] = MBEDTLS_BYTE_1(i - 7); - ssl->out_msg[6] = MBEDTLS_BYTE_0(i - 7); + /* mbedtls_ssl_conf_ca_chain() and mbedtls_ssl_conf_ca_cb() + * cannot be used together. */ + conf->ca_chain = NULL; + conf->ca_crl = NULL; +} +#endif /* MBEDTLS_X509_TRUSTED_CERTIFICATE_CALLBACK */ +#endif /* MBEDTLS_X509_CRT_PARSE_C */ - ssl->out_msglen = i; - ssl->out_msgtype = MBEDTLS_SSL_MSG_HANDSHAKE; - ssl->out_msg[0] = MBEDTLS_SSL_HS_CERTIFICATE; +#if defined(MBEDTLS_SSL_SERVER_NAME_INDICATION) +const unsigned char *mbedtls_ssl_get_hs_sni(mbedtls_ssl_context *ssl, + size_t *name_len) +{ + *name_len = ssl->handshake->sni_name_len; + return ssl->handshake->sni_name; +} -#if defined(MBEDTLS_SSL_PROTO_SSL3) && defined(MBEDTLS_SSL_CLI_C) -write_msg: -#endif +int mbedtls_ssl_set_hs_own_cert(mbedtls_ssl_context *ssl, + mbedtls_x509_crt *own_cert, + mbedtls_pk_context *pk_key) +{ + return ssl_append_key_cert(&ssl->handshake->sni_key_cert, + own_cert, pk_key); +} - ssl->state++; +void mbedtls_ssl_set_hs_ca_chain(mbedtls_ssl_context *ssl, + mbedtls_x509_crt *ca_chain, + mbedtls_x509_crl *ca_crl) +{ + ssl->handshake->sni_ca_chain = ca_chain; + ssl->handshake->sni_ca_crl = ca_crl; +} - if ((ret = mbedtls_ssl_write_handshake_msg(ssl)) != 0) { - MBEDTLS_SSL_DEBUG_RET(1, "mbedtls_ssl_write_handshake_msg", ret); - return ret; - } +#if defined(MBEDTLS_KEY_EXCHANGE_CERT_REQ_ALLOWED_ENABLED) +void mbedtls_ssl_set_hs_dn_hints(mbedtls_ssl_context *ssl, + const mbedtls_x509_crt *crt) +{ + ssl->handshake->dn_hints = crt; +} +#endif /* MBEDTLS_KEY_EXCHANGE_CERT_REQ_ALLOWED_ENABLED */ - MBEDTLS_SSL_DEBUG_MSG(2, ("<= write certificate")); +void mbedtls_ssl_set_hs_authmode(mbedtls_ssl_context *ssl, + int authmode) +{ + ssl->handshake->sni_authmode = authmode; +} +#endif /* MBEDTLS_SSL_SERVER_NAME_INDICATION */ - return ret; +#if defined(MBEDTLS_X509_CRT_PARSE_C) +void mbedtls_ssl_set_verify(mbedtls_ssl_context *ssl, + int (*f_vrfy)(void *, mbedtls_x509_crt *, int, uint32_t *), + void *p_vrfy) +{ + ssl->f_vrfy = f_vrfy; + ssl->p_vrfy = p_vrfy; } +#endif -#if defined(MBEDTLS_SSL_RENEGOTIATION) && defined(MBEDTLS_SSL_CLI_C) +#if defined(MBEDTLS_KEY_EXCHANGE_ECJPAKE_ENABLED) -#if defined(MBEDTLS_SSL_KEEP_PEER_CERTIFICATE) -MBEDTLS_CHECK_RETURN_CRITICAL -static int ssl_check_peer_crt_unchanged(mbedtls_ssl_context *ssl, - unsigned char *crt_buf, - size_t crt_buf_len) +#if defined(MBEDTLS_USE_PSA_CRYPTO) +static const uint8_t jpake_server_id[] = { 's', 'e', 'r', 'v', 'e', 'r' }; +static const uint8_t jpake_client_id[] = { 'c', 'l', 'i', 'e', 'n', 't' }; + +static psa_status_t mbedtls_ssl_set_hs_ecjpake_password_common( + mbedtls_ssl_context *ssl, + mbedtls_svc_key_id_t pwd) { - mbedtls_x509_crt const * const peer_crt = ssl->session->peer_cert; + psa_status_t status; + psa_pake_cipher_suite_t cipher_suite = psa_pake_cipher_suite_init(); + const uint8_t *user = NULL; + size_t user_len = 0; + const uint8_t *peer = NULL; + size_t peer_len = 0; + psa_pake_cs_set_algorithm(&cipher_suite, PSA_ALG_JPAKE); + psa_pake_cs_set_primitive(&cipher_suite, + PSA_PAKE_PRIMITIVE(PSA_PAKE_PRIMITIVE_TYPE_ECC, + PSA_ECC_FAMILY_SECP_R1, + 256)); + psa_pake_cs_set_hash(&cipher_suite, PSA_ALG_SHA_256); + + status = psa_pake_setup(&ssl->handshake->psa_pake_ctx, &cipher_suite); + if (status != PSA_SUCCESS) { + return status; + } - if (peer_crt == NULL) { - return -1; + if (ssl->conf->endpoint == MBEDTLS_SSL_IS_SERVER) { + user = jpake_server_id; + user_len = sizeof(jpake_server_id); + peer = jpake_client_id; + peer_len = sizeof(jpake_client_id); + } else { + user = jpake_client_id; + user_len = sizeof(jpake_client_id); + peer = jpake_server_id; + peer_len = sizeof(jpake_server_id); } - if (peer_crt->raw.len != crt_buf_len) { - return -1; + status = psa_pake_set_user(&ssl->handshake->psa_pake_ctx, user, user_len); + if (status != PSA_SUCCESS) { + return status; } - return memcmp(peer_crt->raw.p, crt_buf, peer_crt->raw.len); + status = psa_pake_set_peer(&ssl->handshake->psa_pake_ctx, peer, peer_len); + if (status != PSA_SUCCESS) { + return status; + } + + status = psa_pake_set_password_key(&ssl->handshake->psa_pake_ctx, pwd); + if (status != PSA_SUCCESS) { + return status; + } + + ssl->handshake->psa_pake_ctx_is_ok = 1; + + return PSA_SUCCESS; } -#else /* MBEDTLS_SSL_KEEP_PEER_CERTIFICATE */ -MBEDTLS_CHECK_RETURN_CRITICAL -static int ssl_check_peer_crt_unchanged(mbedtls_ssl_context *ssl, - unsigned char *crt_buf, - size_t crt_buf_len) + +int mbedtls_ssl_set_hs_ecjpake_password(mbedtls_ssl_context *ssl, + const unsigned char *pw, + size_t pw_len) { - int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED; - unsigned char const * const peer_cert_digest = - ssl->session->peer_cert_digest; - mbedtls_md_type_t const peer_cert_digest_type = - ssl->session->peer_cert_digest_type; - mbedtls_md_info_t const * const digest_info = - mbedtls_md_info_from_type(peer_cert_digest_type); - unsigned char tmp_digest[MBEDTLS_SSL_PEER_CERT_DIGEST_MAX_LEN]; - size_t digest_len; + psa_key_attributes_t attributes = PSA_KEY_ATTRIBUTES_INIT; + psa_status_t status; - if (peer_cert_digest == NULL || digest_info == NULL) { - return -1; + if (ssl->handshake == NULL || ssl->conf == NULL) { + return MBEDTLS_ERR_SSL_BAD_INPUT_DATA; } - digest_len = mbedtls_md_get_size(digest_info); - if (digest_len > MBEDTLS_SSL_PEER_CERT_DIGEST_MAX_LEN) { - return -1; + /* Empty password is not valid */ + if ((pw == NULL) || (pw_len == 0)) { + return MBEDTLS_ERR_SSL_BAD_INPUT_DATA; } - ret = mbedtls_md(digest_info, crt_buf, crt_buf_len, tmp_digest); - if (ret != 0) { - return -1; + psa_set_key_usage_flags(&attributes, PSA_KEY_USAGE_DERIVE); + psa_set_key_algorithm(&attributes, PSA_ALG_JPAKE); + psa_set_key_type(&attributes, PSA_KEY_TYPE_PASSWORD); + + status = psa_import_key(&attributes, pw, pw_len, + &ssl->handshake->psa_pake_password); + if (status != PSA_SUCCESS) { + return MBEDTLS_ERR_SSL_HW_ACCEL_FAILED; } - return memcmp(tmp_digest, peer_cert_digest, digest_len); + status = mbedtls_ssl_set_hs_ecjpake_password_common(ssl, + ssl->handshake->psa_pake_password); + if (status != PSA_SUCCESS) { + psa_destroy_key(ssl->handshake->psa_pake_password); + psa_pake_abort(&ssl->handshake->psa_pake_ctx); + return MBEDTLS_ERR_SSL_HW_ACCEL_FAILED; + } + + return 0; } -#endif /* MBEDTLS_SSL_KEEP_PEER_CERTIFICATE */ -#endif /* MBEDTLS_SSL_RENEGOTIATION && MBEDTLS_SSL_CLI_C */ -/* - * Once the certificate message is read, parse it into a cert chain and - * perform basic checks, but leave actual verification to the caller - */ -MBEDTLS_CHECK_RETURN_CRITICAL -static int ssl_parse_certificate_chain(mbedtls_ssl_context *ssl, - mbedtls_x509_crt *chain) +int mbedtls_ssl_set_hs_ecjpake_password_opaque(mbedtls_ssl_context *ssl, + mbedtls_svc_key_id_t pwd) { - int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED; -#if defined(MBEDTLS_SSL_RENEGOTIATION) && defined(MBEDTLS_SSL_CLI_C) - int crt_cnt = 0; -#endif - size_t i, n; - uint8_t alert; + psa_status_t status; - if (ssl->in_msgtype != MBEDTLS_SSL_MSG_HANDSHAKE) { - MBEDTLS_SSL_DEBUG_MSG(1, ("bad certificate message")); - mbedtls_ssl_send_alert_message(ssl, MBEDTLS_SSL_ALERT_LEVEL_FATAL, - MBEDTLS_SSL_ALERT_MSG_UNEXPECTED_MESSAGE); - return MBEDTLS_ERR_SSL_UNEXPECTED_MESSAGE; + if (ssl->handshake == NULL || ssl->conf == NULL) { + return MBEDTLS_ERR_SSL_BAD_INPUT_DATA; } - if (ssl->in_msg[0] != MBEDTLS_SSL_HS_CERTIFICATE || - ssl->in_hslen < mbedtls_ssl_hs_hdr_len(ssl) + 3 + 3) { - MBEDTLS_SSL_DEBUG_MSG(1, ("bad certificate message")); - mbedtls_ssl_send_alert_message(ssl, MBEDTLS_SSL_ALERT_LEVEL_FATAL, - MBEDTLS_SSL_ALERT_MSG_DECODE_ERROR); - return MBEDTLS_ERR_SSL_BAD_HS_CERTIFICATE; + if (mbedtls_svc_key_id_is_null(pwd)) { + return MBEDTLS_ERR_SSL_BAD_INPUT_DATA; } - i = mbedtls_ssl_hs_hdr_len(ssl); + status = mbedtls_ssl_set_hs_ecjpake_password_common(ssl, pwd); + if (status != PSA_SUCCESS) { + psa_pake_abort(&ssl->handshake->psa_pake_ctx); + return MBEDTLS_ERR_SSL_HW_ACCEL_FAILED; + } - /* - * Same message structure as in mbedtls_ssl_write_certificate() - */ - n = (ssl->in_msg[i+1] << 8) | ssl->in_msg[i+2]; + return 0; +} +#else /* MBEDTLS_USE_PSA_CRYPTO */ +int mbedtls_ssl_set_hs_ecjpake_password(mbedtls_ssl_context *ssl, + const unsigned char *pw, + size_t pw_len) +{ + mbedtls_ecjpake_role role; - if (ssl->in_msg[i] != 0 || - ssl->in_hslen != n + 3 + mbedtls_ssl_hs_hdr_len(ssl)) { - MBEDTLS_SSL_DEBUG_MSG(1, ("bad certificate message")); - mbedtls_ssl_send_alert_message(ssl, MBEDTLS_SSL_ALERT_LEVEL_FATAL, - MBEDTLS_SSL_ALERT_MSG_DECODE_ERROR); - return MBEDTLS_ERR_SSL_BAD_HS_CERTIFICATE; + if (ssl->handshake == NULL || ssl->conf == NULL) { + return MBEDTLS_ERR_SSL_BAD_INPUT_DATA; } - /* Make &ssl->in_msg[i] point to the beginning of the CRT chain. */ - i += 3; + /* Empty password is not valid */ + if ((pw == NULL) || (pw_len == 0)) { + return MBEDTLS_ERR_SSL_BAD_INPUT_DATA; + } - /* Iterate through and parse the CRTs in the provided chain. */ - while (i < ssl->in_hslen) { - /* Check that there's room for the next CRT's length fields. */ - if (i + 3 > ssl->in_hslen) { - MBEDTLS_SSL_DEBUG_MSG(1, ("bad certificate message")); - mbedtls_ssl_send_alert_message(ssl, - MBEDTLS_SSL_ALERT_LEVEL_FATAL, - MBEDTLS_SSL_ALERT_MSG_DECODE_ERROR); - return MBEDTLS_ERR_SSL_BAD_HS_CERTIFICATE; - } - /* In theory, the CRT can be up to 2**24 Bytes, but we don't support - * anything beyond 2**16 ~ 64K. */ - if (ssl->in_msg[i] != 0) { - MBEDTLS_SSL_DEBUG_MSG(1, ("bad certificate message")); - mbedtls_ssl_send_alert_message(ssl, - MBEDTLS_SSL_ALERT_LEVEL_FATAL, - MBEDTLS_SSL_ALERT_MSG_DECODE_ERROR); - return MBEDTLS_ERR_SSL_BAD_HS_CERTIFICATE; - } + if (ssl->conf->endpoint == MBEDTLS_SSL_IS_SERVER) { + role = MBEDTLS_ECJPAKE_SERVER; + } else { + role = MBEDTLS_ECJPAKE_CLIENT; + } - /* Read length of the next CRT in the chain. */ - n = ((unsigned int) ssl->in_msg[i + 1] << 8) - | (unsigned int) ssl->in_msg[i + 2]; - i += 3; + return mbedtls_ecjpake_setup(&ssl->handshake->ecjpake_ctx, + role, + MBEDTLS_MD_SHA256, + MBEDTLS_ECP_DP_SECP256R1, + pw, pw_len); +} +#endif /* MBEDTLS_USE_PSA_CRYPTO */ +#endif /* MBEDTLS_KEY_EXCHANGE_ECJPAKE_ENABLED */ - if (n < 128 || i + n > ssl->in_hslen) { - MBEDTLS_SSL_DEBUG_MSG(1, ("bad certificate message")); - mbedtls_ssl_send_alert_message(ssl, - MBEDTLS_SSL_ALERT_LEVEL_FATAL, - MBEDTLS_SSL_ALERT_MSG_DECODE_ERROR); - return MBEDTLS_ERR_SSL_BAD_HS_CERTIFICATE; - } +#if defined(MBEDTLS_SSL_HANDSHAKE_WITH_PSK_ENABLED) +int mbedtls_ssl_conf_has_static_psk(mbedtls_ssl_config const *conf) +{ + if (conf->psk_identity == NULL || + conf->psk_identity_len == 0) { + return 0; + } - /* Check if we're handling the first CRT in the chain. */ -#if defined(MBEDTLS_SSL_RENEGOTIATION) && defined(MBEDTLS_SSL_CLI_C) - if (crt_cnt++ == 0 && - ssl->conf->endpoint == MBEDTLS_SSL_IS_CLIENT && - ssl->renego_status == MBEDTLS_SSL_RENEGOTIATION_IN_PROGRESS) { - /* During client-side renegotiation, check that the server's - * end-CRTs hasn't changed compared to the initial handshake, - * mitigating the triple handshake attack. On success, reuse - * the original end-CRT instead of parsing it again. */ - MBEDTLS_SSL_DEBUG_MSG(3, ("Check that peer CRT hasn't changed during renegotiation")); - if (ssl_check_peer_crt_unchanged(ssl, - &ssl->in_msg[i], - n) != 0) { - MBEDTLS_SSL_DEBUG_MSG(1, ("new server cert during renegotiation")); - mbedtls_ssl_send_alert_message(ssl, - MBEDTLS_SSL_ALERT_LEVEL_FATAL, - MBEDTLS_SSL_ALERT_MSG_ACCESS_DENIED); - return MBEDTLS_ERR_SSL_BAD_HS_CERTIFICATE; - } +#if defined(MBEDTLS_USE_PSA_CRYPTO) + if (!mbedtls_svc_key_id_is_null(conf->psk_opaque)) { + return 1; + } +#endif /* MBEDTLS_USE_PSA_CRYPTO */ - /* Now we can safely free the original chain. */ - ssl_clear_peer_cert(ssl->session); - } -#endif /* MBEDTLS_SSL_RENEGOTIATION && MBEDTLS_SSL_CLI_C */ + if (conf->psk != NULL && conf->psk_len != 0) { + return 1; + } - /* Parse the next certificate in the chain. */ -#if defined(MBEDTLS_SSL_KEEP_PEER_CERTIFICATE) - ret = mbedtls_x509_crt_parse_der(chain, ssl->in_msg + i, n); -#else - /* If we don't need to store the CRT chain permanently, parse - * it in-place from the input buffer instead of making a copy. */ - ret = mbedtls_x509_crt_parse_der_nocopy(chain, ssl->in_msg + i, n); -#endif /* MBEDTLS_SSL_KEEP_PEER_CERTIFICATE */ - switch (ret) { - case 0: /*ok*/ - case MBEDTLS_ERR_X509_UNKNOWN_SIG_ALG + MBEDTLS_ERR_OID_NOT_FOUND: - /* Ignore certificate with an unknown algorithm: maybe a - prior certificate was already trusted. */ - break; + return 0; +} - case MBEDTLS_ERR_X509_ALLOC_FAILED: - alert = MBEDTLS_SSL_ALERT_MSG_INTERNAL_ERROR; - goto crt_parse_der_failed; +static void ssl_conf_remove_psk(mbedtls_ssl_config *conf) +{ + /* Remove reference to existing PSK, if any. */ +#if defined(MBEDTLS_USE_PSA_CRYPTO) + if (!mbedtls_svc_key_id_is_null(conf->psk_opaque)) { + /* The maintenance of the PSK key slot is the + * user's responsibility. */ + conf->psk_opaque = MBEDTLS_SVC_KEY_ID_INIT; + } +#endif /* MBEDTLS_USE_PSA_CRYPTO */ + if (conf->psk != NULL) { + mbedtls_zeroize_and_free(conf->psk, conf->psk_len); + conf->psk = NULL; + conf->psk_len = 0; + } - case MBEDTLS_ERR_X509_UNKNOWN_VERSION: - alert = MBEDTLS_SSL_ALERT_MSG_UNSUPPORTED_CERT; - goto crt_parse_der_failed; + /* Remove reference to PSK identity, if any. */ + if (conf->psk_identity != NULL) { + mbedtls_free(conf->psk_identity); + conf->psk_identity = NULL; + conf->psk_identity_len = 0; + } +} - default: - alert = MBEDTLS_SSL_ALERT_MSG_BAD_CERT; -crt_parse_der_failed: - mbedtls_ssl_send_alert_message(ssl, MBEDTLS_SSL_ALERT_LEVEL_FATAL, alert); - MBEDTLS_SSL_DEBUG_RET(1, " mbedtls_x509_crt_parse_der", ret); - return ret; - } +/* This function assumes that PSK identity in the SSL config is unset. + * It checks that the provided identity is well-formed and attempts + * to make a copy of it in the SSL config. + * On failure, the PSK identity in the config remains unset. */ +MBEDTLS_CHECK_RETURN_CRITICAL +static int ssl_conf_set_psk_identity(mbedtls_ssl_config *conf, + unsigned char const *psk_identity, + size_t psk_identity_len) +{ + /* Identity len will be encoded on two bytes */ + if (psk_identity == NULL || + psk_identity_len == 0 || + (psk_identity_len >> 16) != 0 || + psk_identity_len > MBEDTLS_SSL_OUT_CONTENT_LEN) { + return MBEDTLS_ERR_SSL_BAD_INPUT_DATA; + } - i += n; + conf->psk_identity = mbedtls_calloc(1, psk_identity_len); + if (conf->psk_identity == NULL) { + return MBEDTLS_ERR_SSL_ALLOC_FAILED; } - MBEDTLS_SSL_DEBUG_CRT(3, "peer certificate", chain); + conf->psk_identity_len = psk_identity_len; + memcpy(conf->psk_identity, psk_identity, conf->psk_identity_len); + return 0; } -#if defined(MBEDTLS_SSL_SRV_C) -MBEDTLS_CHECK_RETURN_CRITICAL -static int ssl_srv_check_client_no_crt_notification(mbedtls_ssl_context *ssl) +int mbedtls_ssl_conf_psk(mbedtls_ssl_config *conf, + const unsigned char *psk, size_t psk_len, + const unsigned char *psk_identity, size_t psk_identity_len) { - if (ssl->conf->endpoint == MBEDTLS_SSL_IS_CLIENT) { - return -1; + int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED; + + /* We currently only support one PSK, raw or opaque. */ + if (mbedtls_ssl_conf_has_static_psk(conf)) { + return MBEDTLS_ERR_SSL_FEATURE_UNAVAILABLE; } -#if defined(MBEDTLS_SSL_PROTO_SSL3) - /* - * Check if the client sent an empty certificate - */ - if (ssl->minor_ver == MBEDTLS_SSL_MINOR_VERSION_0) { - if (ssl->in_msglen == 2 && - ssl->in_msgtype == MBEDTLS_SSL_MSG_ALERT && - ssl->in_msg[0] == MBEDTLS_SSL_ALERT_LEVEL_WARNING && - ssl->in_msg[1] == MBEDTLS_SSL_ALERT_MSG_NO_CERT) { - MBEDTLS_SSL_DEBUG_MSG(1, ("SSLv3 client has no certificate")); - return 0; - } + /* Check and set raw PSK */ + if (psk == NULL) { + return MBEDTLS_ERR_SSL_BAD_INPUT_DATA; + } + if (psk_len == 0) { + return MBEDTLS_ERR_SSL_BAD_INPUT_DATA; + } + if (psk_len > MBEDTLS_PSK_MAX_LEN) { + return MBEDTLS_ERR_SSL_BAD_INPUT_DATA; + } - return -1; + if ((conf->psk = mbedtls_calloc(1, psk_len)) == NULL) { + return MBEDTLS_ERR_SSL_ALLOC_FAILED; } -#endif /* MBEDTLS_SSL_PROTO_SSL3 */ + conf->psk_len = psk_len; + memcpy(conf->psk, psk, conf->psk_len); -#if defined(MBEDTLS_SSL_PROTO_TLS1) || defined(MBEDTLS_SSL_PROTO_TLS1_1) || \ - defined(MBEDTLS_SSL_PROTO_TLS1_2) - if (ssl->in_hslen == 3 + mbedtls_ssl_hs_hdr_len(ssl) && - ssl->in_msgtype == MBEDTLS_SSL_MSG_HANDSHAKE && - ssl->in_msg[0] == MBEDTLS_SSL_HS_CERTIFICATE && - memcmp(ssl->in_msg + mbedtls_ssl_hs_hdr_len(ssl), "\0\0\0", 3) == 0) { - MBEDTLS_SSL_DEBUG_MSG(1, ("TLSv1 client has no certificate")); - return 0; + /* Check and set PSK Identity */ + ret = ssl_conf_set_psk_identity(conf, psk_identity, psk_identity_len); + if (ret != 0) { + ssl_conf_remove_psk(conf); } - return -1; -#endif /* MBEDTLS_SSL_PROTO_TLS1 || MBEDTLS_SSL_PROTO_TLS1_1 || \ - MBEDTLS_SSL_PROTO_TLS1_2 */ + return ret; } -#endif /* MBEDTLS_SSL_SRV_C */ -/* Check if a certificate message is expected. - * Return either - * - SSL_CERTIFICATE_EXPECTED, or - * - SSL_CERTIFICATE_SKIP - * indicating whether a Certificate message is expected or not. - */ -#define SSL_CERTIFICATE_EXPECTED 0 -#define SSL_CERTIFICATE_SKIP 1 -MBEDTLS_CHECK_RETURN_CRITICAL -static int ssl_parse_certificate_coordinate(mbedtls_ssl_context *ssl, - int authmode) +static void ssl_remove_psk(mbedtls_ssl_context *ssl) { - const mbedtls_ssl_ciphersuite_t *ciphersuite_info = - ssl->handshake->ciphersuite_info; - - if (!mbedtls_ssl_ciphersuite_uses_srv_cert(ciphersuite_info)) { - return SSL_CERTIFICATE_SKIP; - } - -#if defined(MBEDTLS_SSL_SRV_C) - if (ssl->conf->endpoint == MBEDTLS_SSL_IS_SERVER) { - if (ciphersuite_info->key_exchange == MBEDTLS_KEY_EXCHANGE_RSA_PSK) { - return SSL_CERTIFICATE_SKIP; - } - - if (authmode == MBEDTLS_SSL_VERIFY_NONE) { - ssl->session_negotiate->verify_result = - MBEDTLS_X509_BADCERT_SKIP_VERIFY; - return SSL_CERTIFICATE_SKIP; +#if defined(MBEDTLS_USE_PSA_CRYPTO) + if (!mbedtls_svc_key_id_is_null(ssl->handshake->psk_opaque)) { + /* The maintenance of the external PSK key slot is the + * user's responsibility. */ + if (ssl->handshake->psk_opaque_is_internal) { + psa_destroy_key(ssl->handshake->psk_opaque); + ssl->handshake->psk_opaque_is_internal = 0; } + ssl->handshake->psk_opaque = MBEDTLS_SVC_KEY_ID_INIT; } #else - ((void) authmode); -#endif /* MBEDTLS_SSL_SRV_C */ - - return SSL_CERTIFICATE_EXPECTED; + if (ssl->handshake->psk != NULL) { + mbedtls_zeroize_and_free(ssl->handshake->psk, + ssl->handshake->psk_len); + ssl->handshake->psk_len = 0; + } +#endif /* MBEDTLS_USE_PSA_CRYPTO */ } -MBEDTLS_CHECK_RETURN_CRITICAL -static int ssl_parse_certificate_verify(mbedtls_ssl_context *ssl, - int authmode, - mbedtls_x509_crt *chain, - void *rs_ctx) +int mbedtls_ssl_set_hs_psk(mbedtls_ssl_context *ssl, + const unsigned char *psk, size_t psk_len) { - int ret = 0; - const mbedtls_ssl_ciphersuite_t *ciphersuite_info = - ssl->handshake->ciphersuite_info; - int have_ca_chain = 0; +#if defined(MBEDTLS_USE_PSA_CRYPTO) + psa_key_attributes_t key_attributes = psa_key_attributes_init(); + psa_status_t status = PSA_ERROR_CORRUPTION_DETECTED; + psa_algorithm_t alg = PSA_ALG_NONE; + mbedtls_svc_key_id_t key = MBEDTLS_SVC_KEY_ID_INIT; +#endif /* MBEDTLS_USE_PSA_CRYPTO */ - int (*f_vrfy)(void *, mbedtls_x509_crt *, int, uint32_t *); - void *p_vrfy; + if (psk == NULL || ssl->handshake == NULL) { + return MBEDTLS_ERR_SSL_BAD_INPUT_DATA; + } - if (authmode == MBEDTLS_SSL_VERIFY_NONE) { - return 0; + if (psk_len > MBEDTLS_PSK_MAX_LEN) { + return MBEDTLS_ERR_SSL_BAD_INPUT_DATA; } - if (ssl->f_vrfy != NULL) { - MBEDTLS_SSL_DEBUG_MSG(3, ("Use context-specific verification callback")); - f_vrfy = ssl->f_vrfy; - p_vrfy = ssl->p_vrfy; - } else { - MBEDTLS_SSL_DEBUG_MSG(3, ("Use configuration-specific verification callback")); - f_vrfy = ssl->conf->f_vrfy; - p_vrfy = ssl->conf->p_vrfy; - } - - /* - * Main check: verify certificate - */ -#if defined(MBEDTLS_X509_TRUSTED_CERTIFICATE_CALLBACK) - if (ssl->conf->f_ca_cb != NULL) { - ((void) rs_ctx); - have_ca_chain = 1; - - MBEDTLS_SSL_DEBUG_MSG(3, ("use CA callback for X.509 CRT verification")); - ret = mbedtls_x509_crt_verify_with_ca_cb( - chain, - ssl->conf->f_ca_cb, - ssl->conf->p_ca_cb, - ssl->conf->cert_profile, - ssl->hostname, - &ssl->session_negotiate->verify_result, - f_vrfy, p_vrfy); - } else -#endif /* MBEDTLS_X509_TRUSTED_CERTIFICATE_CALLBACK */ - { - mbedtls_x509_crt *ca_chain; - mbedtls_x509_crl *ca_crl; - -#if defined(MBEDTLS_SSL_SERVER_NAME_INDICATION) - if (ssl->handshake->sni_ca_chain != NULL) { - ca_chain = ssl->handshake->sni_ca_chain; - ca_crl = ssl->handshake->sni_ca_crl; - } else -#endif - { - ca_chain = ssl->conf->ca_chain; - ca_crl = ssl->conf->ca_crl; - } + ssl_remove_psk(ssl); - if (ca_chain != NULL) { - have_ca_chain = 1; +#if defined(MBEDTLS_USE_PSA_CRYPTO) +#if defined(MBEDTLS_SSL_PROTO_TLS1_2) + if (ssl->tls_version == MBEDTLS_SSL_VERSION_TLS1_2) { + if (ssl->handshake->ciphersuite_info->mac == MBEDTLS_MD_SHA384) { + alg = PSA_ALG_TLS12_PSK_TO_MS(PSA_ALG_SHA_384); + } else { + alg = PSA_ALG_TLS12_PSK_TO_MS(PSA_ALG_SHA_256); } - - ret = mbedtls_x509_crt_verify_restartable( - chain, - ca_chain, ca_crl, - ssl->conf->cert_profile, - ssl->hostname, - &ssl->session_negotiate->verify_result, - f_vrfy, p_vrfy, rs_ctx); + psa_set_key_usage_flags(&key_attributes, PSA_KEY_USAGE_DERIVE); } +#endif /* MBEDTLS_SSL_PROTO_TLS1_2 */ - if (ret != 0) { - MBEDTLS_SSL_DEBUG_RET(1, "x509_verify_cert", ret); +#if defined(MBEDTLS_SSL_PROTO_TLS1_3) + if (ssl->tls_version == MBEDTLS_SSL_VERSION_TLS1_3) { + alg = PSA_ALG_HKDF_EXTRACT(PSA_ALG_ANY_HASH); + psa_set_key_usage_flags(&key_attributes, + PSA_KEY_USAGE_DERIVE | PSA_KEY_USAGE_EXPORT); } +#endif /* MBEDTLS_SSL_PROTO_TLS1_3 */ -#if defined(MBEDTLS_SSL_ECP_RESTARTABLE_ENABLED) - if (ret == MBEDTLS_ERR_ECP_IN_PROGRESS) { - return MBEDTLS_ERR_SSL_CRYPTO_IN_PROGRESS; - } -#endif + psa_set_key_algorithm(&key_attributes, alg); + psa_set_key_type(&key_attributes, PSA_KEY_TYPE_DERIVE); - /* - * Secondary checks: always done, but change 'ret' only if it was 0 - */ + status = psa_import_key(&key_attributes, psk, psk_len, &key); + if (status != PSA_SUCCESS) { + return MBEDTLS_ERR_SSL_HW_ACCEL_FAILED; + } -#if defined(MBEDTLS_ECP_C) - { - const mbedtls_pk_context *pk = &chain->pk; + /* Allow calling psa_destroy_key() on psk remove */ + ssl->handshake->psk_opaque_is_internal = 1; + return mbedtls_ssl_set_hs_psk_opaque(ssl, key); +#else + if ((ssl->handshake->psk = mbedtls_calloc(1, psk_len)) == NULL) { + return MBEDTLS_ERR_SSL_ALLOC_FAILED; + } - /* If certificate uses an EC key, make sure the curve is OK. - * This is a public key, so it can't be opaque, so can_do() is a good - * enough check to ensure pk_ec() is safe to use here. */ - if (mbedtls_pk_can_do(pk, MBEDTLS_PK_ECKEY) && - mbedtls_ssl_check_curve(ssl, mbedtls_pk_ec(*pk)->grp.id) != 0) { - ssl->session_negotiate->verify_result |= MBEDTLS_X509_BADCERT_BAD_KEY; + ssl->handshake->psk_len = psk_len; + memcpy(ssl->handshake->psk, psk, ssl->handshake->psk_len); - MBEDTLS_SSL_DEBUG_MSG(1, ("bad certificate (EC key curve)")); - if (ret == 0) { - ret = MBEDTLS_ERR_SSL_BAD_HS_CERTIFICATE; - } - } - } -#endif /* MBEDTLS_ECP_C */ + return 0; +#endif /* MBEDTLS_USE_PSA_CRYPTO */ +} - if (mbedtls_ssl_check_cert_usage(chain, - ciphersuite_info, - !ssl->conf->endpoint, - &ssl->session_negotiate->verify_result) != 0) { - MBEDTLS_SSL_DEBUG_MSG(1, ("bad certificate (usage extensions)")); - if (ret == 0) { - ret = MBEDTLS_ERR_SSL_BAD_HS_CERTIFICATE; - } - } +#if defined(MBEDTLS_USE_PSA_CRYPTO) +int mbedtls_ssl_conf_psk_opaque(mbedtls_ssl_config *conf, + mbedtls_svc_key_id_t psk, + const unsigned char *psk_identity, + size_t psk_identity_len) +{ + int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED; - /* mbedtls_x509_crt_verify_with_profile is supposed to report a - * verification failure through MBEDTLS_ERR_X509_CERT_VERIFY_FAILED, - * with details encoded in the verification flags. All other kinds - * of error codes, including those from the user provided f_vrfy - * functions, are treated as fatal and lead to a failure of - * ssl_parse_certificate even if verification was optional. */ - if (authmode == MBEDTLS_SSL_VERIFY_OPTIONAL && - (ret == MBEDTLS_ERR_X509_CERT_VERIFY_FAILED || - ret == MBEDTLS_ERR_SSL_BAD_HS_CERTIFICATE)) { - ret = 0; + /* We currently only support one PSK, raw or opaque. */ + if (mbedtls_ssl_conf_has_static_psk(conf)) { + return MBEDTLS_ERR_SSL_FEATURE_UNAVAILABLE; } - if (have_ca_chain == 0 && authmode == MBEDTLS_SSL_VERIFY_REQUIRED) { - MBEDTLS_SSL_DEBUG_MSG(1, ("got no CA chain")); - ret = MBEDTLS_ERR_SSL_CA_CHAIN_REQUIRED; + /* Check and set opaque PSK */ + if (mbedtls_svc_key_id_is_null(psk)) { + return MBEDTLS_ERR_SSL_BAD_INPUT_DATA; } + conf->psk_opaque = psk; + /* Check and set PSK Identity */ + ret = ssl_conf_set_psk_identity(conf, psk_identity, + psk_identity_len); if (ret != 0) { - uint8_t alert; - - /* The certificate may have been rejected for several reasons. - Pick one and send the corresponding alert. Which alert to send - may be a subject of debate in some cases. */ - if (ssl->session_negotiate->verify_result & MBEDTLS_X509_BADCERT_OTHER) { - alert = MBEDTLS_SSL_ALERT_MSG_ACCESS_DENIED; - } else if (ssl->session_negotiate->verify_result & MBEDTLS_X509_BADCERT_CN_MISMATCH) { - alert = MBEDTLS_SSL_ALERT_MSG_BAD_CERT; - } else if (ssl->session_negotiate->verify_result & MBEDTLS_X509_BADCERT_KEY_USAGE) { - alert = MBEDTLS_SSL_ALERT_MSG_UNSUPPORTED_CERT; - } else if (ssl->session_negotiate->verify_result & MBEDTLS_X509_BADCERT_EXT_KEY_USAGE) { - alert = MBEDTLS_SSL_ALERT_MSG_UNSUPPORTED_CERT; - } else if (ssl->session_negotiate->verify_result & MBEDTLS_X509_BADCERT_NS_CERT_TYPE) { - alert = MBEDTLS_SSL_ALERT_MSG_UNSUPPORTED_CERT; - } else if (ssl->session_negotiate->verify_result & MBEDTLS_X509_BADCERT_BAD_PK) { - alert = MBEDTLS_SSL_ALERT_MSG_UNSUPPORTED_CERT; - } else if (ssl->session_negotiate->verify_result & MBEDTLS_X509_BADCERT_BAD_KEY) { - alert = MBEDTLS_SSL_ALERT_MSG_UNSUPPORTED_CERT; - } else if (ssl->session_negotiate->verify_result & MBEDTLS_X509_BADCERT_EXPIRED) { - alert = MBEDTLS_SSL_ALERT_MSG_CERT_EXPIRED; - } else if (ssl->session_negotiate->verify_result & MBEDTLS_X509_BADCERT_REVOKED) { - alert = MBEDTLS_SSL_ALERT_MSG_CERT_REVOKED; - } else if (ssl->session_negotiate->verify_result & MBEDTLS_X509_BADCERT_NOT_TRUSTED) { - alert = MBEDTLS_SSL_ALERT_MSG_UNKNOWN_CA; - } else { - alert = MBEDTLS_SSL_ALERT_MSG_CERT_UNKNOWN; - } - mbedtls_ssl_send_alert_message(ssl, MBEDTLS_SSL_ALERT_LEVEL_FATAL, - alert); - } - -#if defined(MBEDTLS_DEBUG_C) - if (ssl->session_negotiate->verify_result != 0) { - MBEDTLS_SSL_DEBUG_MSG(3, ("! Certificate verification flags %08x", - (unsigned int) ssl->session_negotiate->verify_result)); - } else { - MBEDTLS_SSL_DEBUG_MSG(3, ("Certificate verification flags clear")); + ssl_conf_remove_psk(conf); } -#endif /* MBEDTLS_DEBUG_C */ return ret; } -#if !defined(MBEDTLS_SSL_KEEP_PEER_CERTIFICATE) -MBEDTLS_CHECK_RETURN_CRITICAL -static int ssl_remember_peer_crt_digest(mbedtls_ssl_context *ssl, - unsigned char *start, size_t len) +int mbedtls_ssl_set_hs_psk_opaque(mbedtls_ssl_context *ssl, + mbedtls_svc_key_id_t psk) { - int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED; - /* Remember digest of the peer's end-CRT. */ - ssl->session_negotiate->peer_cert_digest = - mbedtls_calloc(1, MBEDTLS_SSL_PEER_CERT_DIGEST_DFL_LEN); - if (ssl->session_negotiate->peer_cert_digest == NULL) { - MBEDTLS_SSL_DEBUG_MSG(1, ("alloc(%d bytes) failed", - MBEDTLS_SSL_PEER_CERT_DIGEST_DFL_LEN)); - mbedtls_ssl_send_alert_message(ssl, - MBEDTLS_SSL_ALERT_LEVEL_FATAL, - MBEDTLS_SSL_ALERT_MSG_INTERNAL_ERROR); - - return MBEDTLS_ERR_SSL_ALLOC_FAILED; + if ((mbedtls_svc_key_id_is_null(psk)) || + (ssl->handshake == NULL)) { + return MBEDTLS_ERR_SSL_BAD_INPUT_DATA; } - ret = mbedtls_md(mbedtls_md_info_from_type( - MBEDTLS_SSL_PEER_CERT_DIGEST_DFL_TYPE), - start, len, - ssl->session_negotiate->peer_cert_digest); + ssl_remove_psk(ssl); + ssl->handshake->psk_opaque = psk; + return 0; +} +#endif /* MBEDTLS_USE_PSA_CRYPTO */ - ssl->session_negotiate->peer_cert_digest_type = - MBEDTLS_SSL_PEER_CERT_DIGEST_DFL_TYPE; - ssl->session_negotiate->peer_cert_digest_len = - MBEDTLS_SSL_PEER_CERT_DIGEST_DFL_LEN; +#if defined(MBEDTLS_SSL_SRV_C) +void mbedtls_ssl_conf_psk_cb(mbedtls_ssl_config *conf, + int (*f_psk)(void *, mbedtls_ssl_context *, const unsigned char *, + size_t), + void *p_psk) +{ + conf->f_psk = f_psk; + conf->p_psk = p_psk; +} +#endif /* MBEDTLS_SSL_SRV_C */ - return ret; +#endif /* MBEDTLS_SSL_HANDSHAKE_WITH_PSK_ENABLED */ + +#if defined(MBEDTLS_USE_PSA_CRYPTO) +static mbedtls_ssl_mode_t mbedtls_ssl_get_base_mode( + psa_algorithm_t alg) +{ +#if defined(MBEDTLS_SSL_SOME_SUITES_USE_MAC) + if (alg == PSA_ALG_CBC_NO_PADDING) { + return MBEDTLS_SSL_MODE_CBC; + } +#endif /* MBEDTLS_SSL_SOME_SUITES_USE_MAC */ + if (PSA_ALG_IS_AEAD(alg)) { + return MBEDTLS_SSL_MODE_AEAD; + } + return MBEDTLS_SSL_MODE_STREAM; } -MBEDTLS_CHECK_RETURN_CRITICAL -static int ssl_remember_peer_pubkey(mbedtls_ssl_context *ssl, - unsigned char *start, size_t len) +#else /* MBEDTLS_USE_PSA_CRYPTO */ + +static mbedtls_ssl_mode_t mbedtls_ssl_get_base_mode( + mbedtls_cipher_mode_t mode) { - unsigned char *end = start + len; - int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED; +#if defined(MBEDTLS_SSL_SOME_SUITES_USE_MAC) + if (mode == MBEDTLS_MODE_CBC) { + return MBEDTLS_SSL_MODE_CBC; + } +#endif /* MBEDTLS_SSL_SOME_SUITES_USE_MAC */ - /* Make a copy of the peer's raw public key. */ - mbedtls_pk_init(&ssl->handshake->peer_pubkey); - ret = mbedtls_pk_parse_subpubkey(&start, end, - &ssl->handshake->peer_pubkey); - if (ret != 0) { - /* We should have parsed the public key before. */ - return MBEDTLS_ERR_SSL_INTERNAL_ERROR; +#if defined(MBEDTLS_GCM_C) || \ + defined(MBEDTLS_CCM_C) || \ + defined(MBEDTLS_CHACHAPOLY_C) + if (mode == MBEDTLS_MODE_GCM || + mode == MBEDTLS_MODE_CCM || + mode == MBEDTLS_MODE_CHACHAPOLY) { + return MBEDTLS_SSL_MODE_AEAD; } +#endif /* MBEDTLS_GCM_C || MBEDTLS_CCM_C || MBEDTLS_CHACHAPOLY_C */ - return 0; + return MBEDTLS_SSL_MODE_STREAM; } -#endif /* !MBEDTLS_SSL_KEEP_PEER_CERTIFICATE */ +#endif /* MBEDTLS_USE_PSA_CRYPTO */ -int mbedtls_ssl_parse_certificate(mbedtls_ssl_context *ssl) +static mbedtls_ssl_mode_t mbedtls_ssl_get_actual_mode( + mbedtls_ssl_mode_t base_mode, + int encrypt_then_mac) { - int ret = 0; - int crt_expected; -#if defined(MBEDTLS_SSL_SRV_C) && defined(MBEDTLS_SSL_SERVER_NAME_INDICATION) - const int authmode = ssl->handshake->sni_authmode != MBEDTLS_SSL_VERIFY_UNSET - ? ssl->handshake->sni_authmode - : ssl->conf->authmode; +#if defined(MBEDTLS_SSL_SOME_SUITES_USE_CBC_ETM) + if (encrypt_then_mac == MBEDTLS_SSL_ETM_ENABLED && + base_mode == MBEDTLS_SSL_MODE_CBC) { + return MBEDTLS_SSL_MODE_CBC_ETM; + } #else - const int authmode = ssl->conf->authmode; + (void) encrypt_then_mac; #endif - void *rs_ctx = NULL; - mbedtls_x509_crt *chain = NULL; - - MBEDTLS_SSL_DEBUG_MSG(2, ("=> parse certificate")); + return base_mode; +} - crt_expected = ssl_parse_certificate_coordinate(ssl, authmode); - if (crt_expected == SSL_CERTIFICATE_SKIP) { - MBEDTLS_SSL_DEBUG_MSG(2, ("<= skip parse certificate")); - goto exit; - } +mbedtls_ssl_mode_t mbedtls_ssl_get_mode_from_transform( + const mbedtls_ssl_transform *transform) +{ + mbedtls_ssl_mode_t base_mode = mbedtls_ssl_get_base_mode( +#if defined(MBEDTLS_USE_PSA_CRYPTO) + transform->psa_alg +#else + mbedtls_cipher_get_cipher_mode(&transform->cipher_ctx_enc) +#endif + ); -#if defined(MBEDTLS_SSL_ECP_RESTARTABLE_ENABLED) - if (ssl->handshake->ecrs_enabled && - ssl->handshake->ecrs_state == ssl_ecrs_crt_verify) { - chain = ssl->handshake->ecrs_peer_cert; - ssl->handshake->ecrs_peer_cert = NULL; - goto crt_verify; - } -#endif - - if ((ret = mbedtls_ssl_read_record(ssl, 1)) != 0) { - /* mbedtls_ssl_read_record may have sent an alert already. We - let it decide whether to alert. */ - MBEDTLS_SSL_DEBUG_RET(1, "mbedtls_ssl_read_record", ret); - goto exit; - } - -#if defined(MBEDTLS_SSL_SRV_C) - if (ssl_srv_check_client_no_crt_notification(ssl) == 0) { - ssl->session_negotiate->verify_result = MBEDTLS_X509_BADCERT_MISSING; - - if (authmode != MBEDTLS_SSL_VERIFY_OPTIONAL) { - ret = MBEDTLS_ERR_SSL_NO_CLIENT_CERTIFICATE; - } - - goto exit; - } -#endif /* MBEDTLS_SSL_SRV_C */ - - /* Clear existing peer CRT structure in case we tried to - * reuse a session but it failed, and allocate a new one. */ - ssl_clear_peer_cert(ssl->session_negotiate); - - chain = mbedtls_calloc(1, sizeof(mbedtls_x509_crt)); - if (chain == NULL) { - MBEDTLS_SSL_DEBUG_MSG(1, ("alloc(%" MBEDTLS_PRINTF_SIZET " bytes) failed", - sizeof(mbedtls_x509_crt))); - mbedtls_ssl_send_alert_message(ssl, - MBEDTLS_SSL_ALERT_LEVEL_FATAL, - MBEDTLS_SSL_ALERT_MSG_INTERNAL_ERROR); - - ret = MBEDTLS_ERR_SSL_ALLOC_FAILED; - goto exit; - } - mbedtls_x509_crt_init(chain); - - ret = ssl_parse_certificate_chain(ssl, chain); - if (ret != 0) { - goto exit; - } - -#if defined(MBEDTLS_SSL_ECP_RESTARTABLE_ENABLED) - if (ssl->handshake->ecrs_enabled) { - ssl->handshake->ecrs_state = ssl_ecrs_crt_verify; - } - -crt_verify: - if (ssl->handshake->ecrs_enabled) { - rs_ctx = &ssl->handshake->ecrs_ctx; - } + int encrypt_then_mac = 0; +#if defined(MBEDTLS_SSL_SOME_SUITES_USE_CBC_ETM) + encrypt_then_mac = transform->encrypt_then_mac; #endif + return mbedtls_ssl_get_actual_mode(base_mode, encrypt_then_mac); +} - ret = ssl_parse_certificate_verify(ssl, authmode, - chain, rs_ctx); - if (ret != 0) { - goto exit; - } - -#if !defined(MBEDTLS_SSL_KEEP_PEER_CERTIFICATE) - { - unsigned char *crt_start, *pk_start; - size_t crt_len, pk_len; - - /* We parse the CRT chain without copying, so - * these pointers point into the input buffer, - * and are hence still valid after freeing the - * CRT chain. */ - - crt_start = chain->raw.p; - crt_len = chain->raw.len; - - pk_start = chain->pk_raw.p; - pk_len = chain->pk_raw.len; - - /* Free the CRT structures before computing - * digest and copying the peer's public key. */ - mbedtls_x509_crt_free(chain); - mbedtls_free(chain); - chain = NULL; - - ret = ssl_remember_peer_crt_digest(ssl, crt_start, crt_len); - if (ret != 0) { - goto exit; - } +mbedtls_ssl_mode_t mbedtls_ssl_get_mode_from_ciphersuite( +#if defined(MBEDTLS_SSL_SOME_SUITES_USE_CBC_ETM) + int encrypt_then_mac, +#endif /* MBEDTLS_SSL_SOME_SUITES_USE_CBC_ETM */ + const mbedtls_ssl_ciphersuite_t *suite) +{ + mbedtls_ssl_mode_t base_mode = MBEDTLS_SSL_MODE_STREAM; - ret = ssl_remember_peer_pubkey(ssl, pk_start, pk_len); - if (ret != 0) { - goto exit; - } +#if defined(MBEDTLS_USE_PSA_CRYPTO) + psa_status_t status; + psa_algorithm_t alg; + psa_key_type_t type; + size_t size; + status = mbedtls_ssl_cipher_to_psa((mbedtls_cipher_type_t) suite->cipher, + 0, &alg, &type, &size); + if (status == PSA_SUCCESS) { + base_mode = mbedtls_ssl_get_base_mode(alg); } -#else /* !MBEDTLS_SSL_KEEP_PEER_CERTIFICATE */ - /* Pass ownership to session structure. */ - ssl->session_negotiate->peer_cert = chain; - chain = NULL; -#endif /* MBEDTLS_SSL_KEEP_PEER_CERTIFICATE */ - - MBEDTLS_SSL_DEBUG_MSG(2, ("<= parse certificate")); - -exit: - - if (ret == 0) { - ssl->state++; +#else + const mbedtls_cipher_info_t *cipher = + mbedtls_cipher_info_from_type((mbedtls_cipher_type_t) suite->cipher); + if (cipher != NULL) { + base_mode = + mbedtls_ssl_get_base_mode( + mbedtls_cipher_info_get_mode(cipher)); } +#endif /* MBEDTLS_USE_PSA_CRYPTO */ -#if defined(MBEDTLS_SSL_ECP_RESTARTABLE_ENABLED) - if (ret == MBEDTLS_ERR_SSL_CRYPTO_IN_PROGRESS) { - ssl->handshake->ecrs_peer_cert = chain; - chain = NULL; - } +#if !defined(MBEDTLS_SSL_SOME_SUITES_USE_CBC_ETM) + int encrypt_then_mac = 0; #endif - - if (chain != NULL) { - mbedtls_x509_crt_free(chain); - mbedtls_free(chain); - } - - return ret; + return mbedtls_ssl_get_actual_mode(base_mode, encrypt_then_mac); } -#endif /* MBEDTLS_KEY_EXCHANGE_WITH_CERT_ENABLED */ -void mbedtls_ssl_optimize_checksum(mbedtls_ssl_context *ssl, - const mbedtls_ssl_ciphersuite_t *ciphersuite_info) -{ - ((void) ciphersuite_info); +#if defined(MBEDTLS_USE_PSA_CRYPTO) || defined(MBEDTLS_SSL_PROTO_TLS1_3) -#if defined(MBEDTLS_SSL_PROTO_SSL3) || defined(MBEDTLS_SSL_PROTO_TLS1) || \ - defined(MBEDTLS_SSL_PROTO_TLS1_1) - if (ssl->minor_ver < MBEDTLS_SSL_MINOR_VERSION_3) { - ssl->handshake->update_checksum = ssl_update_checksum_md5sha1; - } else +psa_status_t mbedtls_ssl_cipher_to_psa(mbedtls_cipher_type_t mbedtls_cipher_type, + size_t taglen, + psa_algorithm_t *alg, + psa_key_type_t *key_type, + size_t *key_size) +{ +#if !defined(MBEDTLS_SSL_HAVE_CCM) + (void) taglen; #endif -#if defined(MBEDTLS_SSL_PROTO_TLS1_2) -#if defined(MBEDTLS_SHA512_C) && !defined(MBEDTLS_SHA512_NO_SHA384) - if (ciphersuite_info->mac == MBEDTLS_MD_SHA384) { - ssl->handshake->update_checksum = ssl_update_checksum_sha384; - } else + switch (mbedtls_cipher_type) { +#if defined(MBEDTLS_SSL_HAVE_AES) && defined(MBEDTLS_SSL_HAVE_CBC) + case MBEDTLS_CIPHER_AES_128_CBC: + *alg = PSA_ALG_CBC_NO_PADDING; + *key_type = PSA_KEY_TYPE_AES; + *key_size = 128; + break; #endif -#if defined(MBEDTLS_SHA256_C) - if (ciphersuite_info->mac != MBEDTLS_MD_SHA384) { - ssl->handshake->update_checksum = ssl_update_checksum_sha256; - } else +#if defined(MBEDTLS_SSL_HAVE_AES) && defined(MBEDTLS_SSL_HAVE_CCM) + case MBEDTLS_CIPHER_AES_128_CCM: + *alg = taglen ? PSA_ALG_AEAD_WITH_SHORTENED_TAG(PSA_ALG_CCM, taglen) : PSA_ALG_CCM; + *key_type = PSA_KEY_TYPE_AES; + *key_size = 128; + break; #endif -#endif /* MBEDTLS_SSL_PROTO_TLS1_2 */ - { - MBEDTLS_SSL_DEBUG_MSG(1, ("should never happen")); - return; - } -} - -void mbedtls_ssl_reset_checksum(mbedtls_ssl_context *ssl) -{ -#if defined(MBEDTLS_SSL_PROTO_SSL3) || defined(MBEDTLS_SSL_PROTO_TLS1) || \ - defined(MBEDTLS_SSL_PROTO_TLS1_1) - mbedtls_md5_starts_ret(&ssl->handshake->fin_md5); - mbedtls_sha1_starts_ret(&ssl->handshake->fin_sha1); +#if defined(MBEDTLS_SSL_HAVE_AES) && defined(MBEDTLS_SSL_HAVE_GCM) + case MBEDTLS_CIPHER_AES_128_GCM: + *alg = PSA_ALG_GCM; + *key_type = PSA_KEY_TYPE_AES; + *key_size = 128; + break; #endif -#if defined(MBEDTLS_SSL_PROTO_TLS1_2) -#if defined(MBEDTLS_SHA256_C) -#if defined(MBEDTLS_USE_PSA_CRYPTO) - psa_hash_abort(&ssl->handshake->fin_sha256_psa); - psa_hash_setup(&ssl->handshake->fin_sha256_psa, PSA_ALG_SHA_256); -#else - mbedtls_sha256_starts_ret(&ssl->handshake->fin_sha256, 0); +#if defined(MBEDTLS_SSL_HAVE_AES) && defined(MBEDTLS_SSL_HAVE_CCM) + case MBEDTLS_CIPHER_AES_192_CCM: + *alg = taglen ? PSA_ALG_AEAD_WITH_SHORTENED_TAG(PSA_ALG_CCM, taglen) : PSA_ALG_CCM; + *key_type = PSA_KEY_TYPE_AES; + *key_size = 192; + break; #endif +#if defined(MBEDTLS_SSL_HAVE_AES) && defined(MBEDTLS_SSL_HAVE_GCM) + case MBEDTLS_CIPHER_AES_192_GCM: + *alg = PSA_ALG_GCM; + *key_type = PSA_KEY_TYPE_AES; + *key_size = 192; + break; #endif -#if defined(MBEDTLS_SHA512_C) && !defined(MBEDTLS_SHA512_NO_SHA384) -#if defined(MBEDTLS_USE_PSA_CRYPTO) - psa_hash_abort(&ssl->handshake->fin_sha384_psa); - psa_hash_setup(&ssl->handshake->fin_sha384_psa, PSA_ALG_SHA_384); -#else - mbedtls_sha512_starts_ret(&ssl->handshake->fin_sha512, 1); +#if defined(MBEDTLS_SSL_HAVE_AES) && defined(MBEDTLS_SSL_HAVE_CBC) + case MBEDTLS_CIPHER_AES_256_CBC: + *alg = PSA_ALG_CBC_NO_PADDING; + *key_type = PSA_KEY_TYPE_AES; + *key_size = 256; + break; #endif +#if defined(MBEDTLS_SSL_HAVE_AES) && defined(MBEDTLS_SSL_HAVE_CCM) + case MBEDTLS_CIPHER_AES_256_CCM: + *alg = taglen ? PSA_ALG_AEAD_WITH_SHORTENED_TAG(PSA_ALG_CCM, taglen) : PSA_ALG_CCM; + *key_type = PSA_KEY_TYPE_AES; + *key_size = 256; + break; #endif -#endif /* MBEDTLS_SSL_PROTO_TLS1_2 */ -} - -static void ssl_update_checksum_start(mbedtls_ssl_context *ssl, - const unsigned char *buf, size_t len) -{ -#if defined(MBEDTLS_SSL_PROTO_SSL3) || defined(MBEDTLS_SSL_PROTO_TLS1) || \ - defined(MBEDTLS_SSL_PROTO_TLS1_1) - mbedtls_md5_update_ret(&ssl->handshake->fin_md5, buf, len); - mbedtls_sha1_update_ret(&ssl->handshake->fin_sha1, buf, len); +#if defined(MBEDTLS_SSL_HAVE_AES) && defined(MBEDTLS_SSL_HAVE_GCM) + case MBEDTLS_CIPHER_AES_256_GCM: + *alg = PSA_ALG_GCM; + *key_type = PSA_KEY_TYPE_AES; + *key_size = 256; + break; #endif -#if defined(MBEDTLS_SSL_PROTO_TLS1_2) -#if defined(MBEDTLS_SHA256_C) -#if defined(MBEDTLS_USE_PSA_CRYPTO) - psa_hash_update(&ssl->handshake->fin_sha256_psa, buf, len); -#else - mbedtls_sha256_update_ret(&ssl->handshake->fin_sha256, buf, len); +#if defined(MBEDTLS_SSL_HAVE_ARIA) && defined(MBEDTLS_SSL_HAVE_CBC) + case MBEDTLS_CIPHER_ARIA_128_CBC: + *alg = PSA_ALG_CBC_NO_PADDING; + *key_type = PSA_KEY_TYPE_ARIA; + *key_size = 128; + break; #endif +#if defined(MBEDTLS_SSL_HAVE_ARIA) && defined(MBEDTLS_SSL_HAVE_CCM) + case MBEDTLS_CIPHER_ARIA_128_CCM: + *alg = taglen ? PSA_ALG_AEAD_WITH_SHORTENED_TAG(PSA_ALG_CCM, taglen) : PSA_ALG_CCM; + *key_type = PSA_KEY_TYPE_ARIA; + *key_size = 128; + break; #endif -#if defined(MBEDTLS_SHA512_C) && !defined(MBEDTLS_SHA512_NO_SHA384) -#if defined(MBEDTLS_USE_PSA_CRYPTO) - psa_hash_update(&ssl->handshake->fin_sha384_psa, buf, len); -#else - mbedtls_sha512_update_ret(&ssl->handshake->fin_sha512, buf, len); +#if defined(MBEDTLS_SSL_HAVE_ARIA) && defined(MBEDTLS_SSL_HAVE_GCM) + case MBEDTLS_CIPHER_ARIA_128_GCM: + *alg = PSA_ALG_GCM; + *key_type = PSA_KEY_TYPE_ARIA; + *key_size = 128; + break; #endif +#if defined(MBEDTLS_SSL_HAVE_ARIA) && defined(MBEDTLS_SSL_HAVE_CCM) + case MBEDTLS_CIPHER_ARIA_192_CCM: + *alg = taglen ? PSA_ALG_AEAD_WITH_SHORTENED_TAG(PSA_ALG_CCM, taglen) : PSA_ALG_CCM; + *key_type = PSA_KEY_TYPE_ARIA; + *key_size = 192; + break; #endif -#endif /* MBEDTLS_SSL_PROTO_TLS1_2 */ -} - -#if defined(MBEDTLS_SSL_PROTO_SSL3) || defined(MBEDTLS_SSL_PROTO_TLS1) || \ - defined(MBEDTLS_SSL_PROTO_TLS1_1) -static void ssl_update_checksum_md5sha1(mbedtls_ssl_context *ssl, - const unsigned char *buf, size_t len) -{ - mbedtls_md5_update_ret(&ssl->handshake->fin_md5, buf, len); - mbedtls_sha1_update_ret(&ssl->handshake->fin_sha1, buf, len); -} +#if defined(MBEDTLS_SSL_HAVE_ARIA) && defined(MBEDTLS_SSL_HAVE_GCM) + case MBEDTLS_CIPHER_ARIA_192_GCM: + *alg = PSA_ALG_GCM; + *key_type = PSA_KEY_TYPE_ARIA; + *key_size = 192; + break; #endif - -#if defined(MBEDTLS_SSL_PROTO_TLS1_2) -#if defined(MBEDTLS_SHA256_C) -static void ssl_update_checksum_sha256(mbedtls_ssl_context *ssl, - const unsigned char *buf, size_t len) -{ -#if defined(MBEDTLS_USE_PSA_CRYPTO) - psa_hash_update(&ssl->handshake->fin_sha256_psa, buf, len); -#else - mbedtls_sha256_update_ret(&ssl->handshake->fin_sha256, buf, len); +#if defined(MBEDTLS_SSL_HAVE_ARIA) && defined(MBEDTLS_SSL_HAVE_CBC) + case MBEDTLS_CIPHER_ARIA_256_CBC: + *alg = PSA_ALG_CBC_NO_PADDING; + *key_type = PSA_KEY_TYPE_ARIA; + *key_size = 256; + break; #endif -} +#if defined(MBEDTLS_SSL_HAVE_ARIA) && defined(MBEDTLS_SSL_HAVE_CCM) + case MBEDTLS_CIPHER_ARIA_256_CCM: + *alg = taglen ? PSA_ALG_AEAD_WITH_SHORTENED_TAG(PSA_ALG_CCM, taglen) : PSA_ALG_CCM; + *key_type = PSA_KEY_TYPE_ARIA; + *key_size = 256; + break; #endif - -#if defined(MBEDTLS_SHA512_C) && !defined(MBEDTLS_SHA512_NO_SHA384) -static void ssl_update_checksum_sha384(mbedtls_ssl_context *ssl, - const unsigned char *buf, size_t len) -{ -#if defined(MBEDTLS_USE_PSA_CRYPTO) - psa_hash_update(&ssl->handshake->fin_sha384_psa, buf, len); -#else - mbedtls_sha512_update_ret(&ssl->handshake->fin_sha512, buf, len); +#if defined(MBEDTLS_SSL_HAVE_ARIA) && defined(MBEDTLS_SSL_HAVE_GCM) + case MBEDTLS_CIPHER_ARIA_256_GCM: + *alg = PSA_ALG_GCM; + *key_type = PSA_KEY_TYPE_ARIA; + *key_size = 256; + break; #endif -} +#if defined(MBEDTLS_SSL_HAVE_CAMELLIA) && defined(MBEDTLS_SSL_HAVE_CBC) + case MBEDTLS_CIPHER_CAMELLIA_128_CBC: + *alg = PSA_ALG_CBC_NO_PADDING; + *key_type = PSA_KEY_TYPE_CAMELLIA; + *key_size = 128; + break; #endif -#endif /* MBEDTLS_SSL_PROTO_TLS1_2 */ +#if defined(MBEDTLS_SSL_HAVE_CAMELLIA) && defined(MBEDTLS_SSL_HAVE_CCM) + case MBEDTLS_CIPHER_CAMELLIA_128_CCM: + *alg = taglen ? PSA_ALG_AEAD_WITH_SHORTENED_TAG(PSA_ALG_CCM, taglen) : PSA_ALG_CCM; + *key_type = PSA_KEY_TYPE_CAMELLIA; + *key_size = 128; + break; +#endif +#if defined(MBEDTLS_SSL_HAVE_CAMELLIA) && defined(MBEDTLS_SSL_HAVE_GCM) + case MBEDTLS_CIPHER_CAMELLIA_128_GCM: + *alg = PSA_ALG_GCM; + *key_type = PSA_KEY_TYPE_CAMELLIA; + *key_size = 128; + break; +#endif +#if defined(MBEDTLS_SSL_HAVE_CAMELLIA) && defined(MBEDTLS_SSL_HAVE_CCM) + case MBEDTLS_CIPHER_CAMELLIA_192_CCM: + *alg = taglen ? PSA_ALG_AEAD_WITH_SHORTENED_TAG(PSA_ALG_CCM, taglen) : PSA_ALG_CCM; + *key_type = PSA_KEY_TYPE_CAMELLIA; + *key_size = 192; + break; +#endif +#if defined(MBEDTLS_SSL_HAVE_CAMELLIA) && defined(MBEDTLS_SSL_HAVE_GCM) + case MBEDTLS_CIPHER_CAMELLIA_192_GCM: + *alg = PSA_ALG_GCM; + *key_type = PSA_KEY_TYPE_CAMELLIA; + *key_size = 192; + break; +#endif +#if defined(MBEDTLS_SSL_HAVE_CAMELLIA) && defined(MBEDTLS_SSL_HAVE_CBC) + case MBEDTLS_CIPHER_CAMELLIA_256_CBC: + *alg = PSA_ALG_CBC_NO_PADDING; + *key_type = PSA_KEY_TYPE_CAMELLIA; + *key_size = 256; + break; +#endif +#if defined(MBEDTLS_SSL_HAVE_CAMELLIA) && defined(MBEDTLS_SSL_HAVE_CCM) + case MBEDTLS_CIPHER_CAMELLIA_256_CCM: + *alg = taglen ? PSA_ALG_AEAD_WITH_SHORTENED_TAG(PSA_ALG_CCM, taglen) : PSA_ALG_CCM; + *key_type = PSA_KEY_TYPE_CAMELLIA; + *key_size = 256; + break; +#endif +#if defined(MBEDTLS_SSL_HAVE_CAMELLIA) && defined(MBEDTLS_SSL_HAVE_GCM) + case MBEDTLS_CIPHER_CAMELLIA_256_GCM: + *alg = PSA_ALG_GCM; + *key_type = PSA_KEY_TYPE_CAMELLIA; + *key_size = 256; + break; +#endif +#if defined(MBEDTLS_SSL_HAVE_CHACHAPOLY) + case MBEDTLS_CIPHER_CHACHA20_POLY1305: + *alg = PSA_ALG_CHACHA20_POLY1305; + *key_type = PSA_KEY_TYPE_CHACHA20; + *key_size = 256; + break; +#endif + case MBEDTLS_CIPHER_NULL: + *alg = MBEDTLS_SSL_NULL_CIPHER; + *key_type = 0; + *key_size = 0; + break; + default: + return PSA_ERROR_NOT_SUPPORTED; + } -#if defined(MBEDTLS_SSL_PROTO_SSL3) -static void ssl_calc_finished_ssl( - mbedtls_ssl_context *ssl, unsigned char *buf, int from) + return PSA_SUCCESS; +} +#endif /* MBEDTLS_USE_PSA_CRYPTO || MBEDTLS_SSL_PROTO_TLS1_3 */ + +#if defined(MBEDTLS_DHM_C) && defined(MBEDTLS_SSL_SRV_C) +int mbedtls_ssl_conf_dh_param_bin(mbedtls_ssl_config *conf, + const unsigned char *dhm_P, size_t P_len, + const unsigned char *dhm_G, size_t G_len) { - const char *sender; - mbedtls_md5_context md5; - mbedtls_sha1_context sha1; + int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED; - unsigned char padbuf[48]; - unsigned char md5sum[16]; - unsigned char sha1sum[20]; + mbedtls_mpi_free(&conf->dhm_P); + mbedtls_mpi_free(&conf->dhm_G); - mbedtls_ssl_session *session = ssl->session_negotiate; - if (!session) { - session = ssl->session; + if ((ret = mbedtls_mpi_read_binary(&conf->dhm_P, dhm_P, P_len)) != 0 || + (ret = mbedtls_mpi_read_binary(&conf->dhm_G, dhm_G, G_len)) != 0) { + mbedtls_mpi_free(&conf->dhm_P); + mbedtls_mpi_free(&conf->dhm_G); + return ret; } - MBEDTLS_SSL_DEBUG_MSG(2, ("=> calc finished ssl")); - - mbedtls_md5_init(&md5); - mbedtls_sha1_init(&sha1); + return 0; +} - mbedtls_md5_clone(&md5, &ssl->handshake->fin_md5); - mbedtls_sha1_clone(&sha1, &ssl->handshake->fin_sha1); +int mbedtls_ssl_conf_dh_param_ctx(mbedtls_ssl_config *conf, mbedtls_dhm_context *dhm_ctx) +{ + int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED; - /* - * SSLv3: - * hash = - * MD5( master + pad2 + - * MD5( handshake + sender + master + pad1 ) ) - * + SHA1( master + pad2 + - * SHA1( handshake + sender + master + pad1 ) ) - */ + mbedtls_mpi_free(&conf->dhm_P); + mbedtls_mpi_free(&conf->dhm_G); -#if !defined(MBEDTLS_MD5_ALT) - MBEDTLS_SSL_DEBUG_BUF(4, "finished md5 state", (unsigned char *) - md5.state, sizeof(md5.state)); -#endif + if ((ret = mbedtls_dhm_get_value(dhm_ctx, MBEDTLS_DHM_PARAM_P, + &conf->dhm_P)) != 0 || + (ret = mbedtls_dhm_get_value(dhm_ctx, MBEDTLS_DHM_PARAM_G, + &conf->dhm_G)) != 0) { + mbedtls_mpi_free(&conf->dhm_P); + mbedtls_mpi_free(&conf->dhm_G); + return ret; + } -#if !defined(MBEDTLS_SHA1_ALT) - MBEDTLS_SSL_DEBUG_BUF(4, "finished sha1 state", (unsigned char *) - sha1.state, sizeof(sha1.state)); -#endif + return 0; +} +#endif /* MBEDTLS_DHM_C && MBEDTLS_SSL_SRV_C */ - sender = (from == MBEDTLS_SSL_IS_CLIENT) ? "CLNT" - : "SRVR"; +#if defined(MBEDTLS_DHM_C) && defined(MBEDTLS_SSL_CLI_C) +/* + * Set the minimum length for Diffie-Hellman parameters + */ +void mbedtls_ssl_conf_dhm_min_bitlen(mbedtls_ssl_config *conf, + unsigned int bitlen) +{ + conf->dhm_min_bitlen = bitlen; +} +#endif /* MBEDTLS_DHM_C && MBEDTLS_SSL_CLI_C */ - memset(padbuf, 0x36, 48); +#if defined(MBEDTLS_SSL_HANDSHAKE_WITH_CERT_ENABLED) +#if !defined(MBEDTLS_DEPRECATED_REMOVED) && defined(MBEDTLS_SSL_PROTO_TLS1_2) +/* + * Set allowed/preferred hashes for handshake signatures + */ +void mbedtls_ssl_conf_sig_hashes(mbedtls_ssl_config *conf, + const int *hashes) +{ + conf->sig_hashes = hashes; +} +#endif /* !MBEDTLS_DEPRECATED_REMOVED && MBEDTLS_SSL_PROTO_TLS1_2 */ - mbedtls_md5_update_ret(&md5, (const unsigned char *) sender, 4); - mbedtls_md5_update_ret(&md5, session->master, 48); - mbedtls_md5_update_ret(&md5, padbuf, 48); - mbedtls_md5_finish_ret(&md5, md5sum); +/* Configure allowed signature algorithms for handshake */ +void mbedtls_ssl_conf_sig_algs(mbedtls_ssl_config *conf, + const uint16_t *sig_algs) +{ +#if !defined(MBEDTLS_DEPRECATED_REMOVED) + conf->sig_hashes = NULL; +#endif /* !MBEDTLS_DEPRECATED_REMOVED */ + conf->sig_algs = sig_algs; +} +#endif /* MBEDTLS_SSL_HANDSHAKE_WITH_CERT_ENABLED */ - mbedtls_sha1_update_ret(&sha1, (const unsigned char *) sender, 4); - mbedtls_sha1_update_ret(&sha1, session->master, 48); - mbedtls_sha1_update_ret(&sha1, padbuf, 40); - mbedtls_sha1_finish_ret(&sha1, sha1sum); +#if defined(MBEDTLS_ECP_C) +#if !defined(MBEDTLS_DEPRECATED_REMOVED) +/* + * Set the allowed elliptic curves + * + * mbedtls_ssl_setup() takes the provided list + * and translates it to a list of IANA TLS group identifiers, + * stored in ssl->handshake->group_list. + * + */ +void mbedtls_ssl_conf_curves(mbedtls_ssl_config *conf, + const mbedtls_ecp_group_id *curve_list) +{ + conf->curve_list = curve_list; + conf->group_list = NULL; +} +#endif /* MBEDTLS_DEPRECATED_REMOVED */ +#endif /* MBEDTLS_ECP_C */ - memset(padbuf, 0x5C, 48); +/* + * Set the allowed groups + */ +void mbedtls_ssl_conf_groups(mbedtls_ssl_config *conf, + const uint16_t *group_list) +{ +#if defined(MBEDTLS_ECP_C) && !defined(MBEDTLS_DEPRECATED_REMOVED) + conf->curve_list = NULL; +#endif + conf->group_list = group_list; +} - mbedtls_md5_starts_ret(&md5); - mbedtls_md5_update_ret(&md5, session->master, 48); - mbedtls_md5_update_ret(&md5, padbuf, 48); - mbedtls_md5_update_ret(&md5, md5sum, 16); - mbedtls_md5_finish_ret(&md5, buf); +#if defined(MBEDTLS_X509_CRT_PARSE_C) +int mbedtls_ssl_set_hostname(mbedtls_ssl_context *ssl, const char *hostname) +{ + /* Initialize to suppress unnecessary compiler warning */ + size_t hostname_len = 0; - mbedtls_sha1_starts_ret(&sha1); - mbedtls_sha1_update_ret(&sha1, session->master, 48); - mbedtls_sha1_update_ret(&sha1, padbuf, 40); - mbedtls_sha1_update_ret(&sha1, sha1sum, 20); - mbedtls_sha1_finish_ret(&sha1, buf + 16); + /* Check if new hostname is valid before + * making any change to current one */ + if (hostname != NULL) { + hostname_len = strlen(hostname); - MBEDTLS_SSL_DEBUG_BUF(3, "calc finished result", buf, 36); + if (hostname_len > MBEDTLS_SSL_MAX_HOST_NAME_LEN) { + return MBEDTLS_ERR_SSL_BAD_INPUT_DATA; + } + } - mbedtls_md5_free(&md5); - mbedtls_sha1_free(&sha1); + /* Now it's clear that we will overwrite the old hostname, + * so we can free it safely */ - mbedtls_platform_zeroize(padbuf, sizeof(padbuf)); - mbedtls_platform_zeroize(md5sum, sizeof(md5sum)); - mbedtls_platform_zeroize(sha1sum, sizeof(sha1sum)); + if (ssl->hostname != NULL) { + mbedtls_zeroize_and_free(ssl->hostname, strlen(ssl->hostname)); + } - MBEDTLS_SSL_DEBUG_MSG(2, ("<= calc finished")); -} -#endif /* MBEDTLS_SSL_PROTO_SSL3 */ + /* Passing NULL as hostname shall clear the old one */ -#if defined(MBEDTLS_SSL_PROTO_TLS1) || defined(MBEDTLS_SSL_PROTO_TLS1_1) -static void ssl_calc_finished_tls( - mbedtls_ssl_context *ssl, unsigned char *buf, int from) -{ - int len = 12; - const char *sender; - mbedtls_md5_context md5; - mbedtls_sha1_context sha1; - unsigned char padbuf[36]; + if (hostname == NULL) { + ssl->hostname = NULL; + } else { + ssl->hostname = mbedtls_calloc(1, hostname_len + 1); + if (ssl->hostname == NULL) { + return MBEDTLS_ERR_SSL_ALLOC_FAILED; + } - mbedtls_ssl_session *session = ssl->session_negotiate; - if (!session) { - session = ssl->session; + memcpy(ssl->hostname, hostname, hostname_len); + + ssl->hostname[hostname_len] = '\0'; } - MBEDTLS_SSL_DEBUG_MSG(2, ("=> calc finished tls")); + return 0; +} +#endif /* MBEDTLS_X509_CRT_PARSE_C */ - mbedtls_md5_init(&md5); - mbedtls_sha1_init(&sha1); +#if defined(MBEDTLS_SSL_SERVER_NAME_INDICATION) +void mbedtls_ssl_conf_sni(mbedtls_ssl_config *conf, + int (*f_sni)(void *, mbedtls_ssl_context *, + const unsigned char *, size_t), + void *p_sni) +{ + conf->f_sni = f_sni; + conf->p_sni = p_sni; +} +#endif /* MBEDTLS_SSL_SERVER_NAME_INDICATION */ - mbedtls_md5_clone(&md5, &ssl->handshake->fin_md5); - mbedtls_sha1_clone(&sha1, &ssl->handshake->fin_sha1); +#if defined(MBEDTLS_SSL_ALPN) +int mbedtls_ssl_conf_alpn_protocols(mbedtls_ssl_config *conf, const char **protos) +{ + size_t cur_len, tot_len; + const char **p; /* - * TLSv1: - * hash = PRF( master, finished_label, - * MD5( handshake ) + SHA1( handshake ) )[0..11] + * RFC 7301 3.1: "Empty strings MUST NOT be included and byte strings + * MUST NOT be truncated." + * We check lengths now rather than later. */ + tot_len = 0; + for (p = protos; *p != NULL; p++) { + cur_len = strlen(*p); + tot_len += cur_len; -#if !defined(MBEDTLS_MD5_ALT) - MBEDTLS_SSL_DEBUG_BUF(4, "finished md5 state", (unsigned char *) - md5.state, sizeof(md5.state)); -#endif - -#if !defined(MBEDTLS_SHA1_ALT) - MBEDTLS_SSL_DEBUG_BUF(4, "finished sha1 state", (unsigned char *) - sha1.state, sizeof(sha1.state)); -#endif - - sender = (from == MBEDTLS_SSL_IS_CLIENT) - ? "client finished" - : "server finished"; - - mbedtls_md5_finish_ret(&md5, padbuf); - mbedtls_sha1_finish_ret(&sha1, padbuf + 16); - - ssl->handshake->tls_prf(session->master, 48, sender, - padbuf, 36, buf, len); - - MBEDTLS_SSL_DEBUG_BUF(3, "calc finished result", buf, len); + if ((cur_len == 0) || + (cur_len > MBEDTLS_SSL_MAX_ALPN_NAME_LEN) || + (tot_len > MBEDTLS_SSL_MAX_ALPN_LIST_LEN)) { + return MBEDTLS_ERR_SSL_BAD_INPUT_DATA; + } + } - mbedtls_md5_free(&md5); - mbedtls_sha1_free(&sha1); + conf->alpn_list = protos; - mbedtls_platform_zeroize(padbuf, sizeof(padbuf)); + return 0; +} - MBEDTLS_SSL_DEBUG_MSG(2, ("<= calc finished")); +const char *mbedtls_ssl_get_alpn_protocol(const mbedtls_ssl_context *ssl) +{ + return ssl->alpn_chosen; } -#endif /* MBEDTLS_SSL_PROTO_TLS1 || MBEDTLS_SSL_PROTO_TLS1_1 */ +#endif /* MBEDTLS_SSL_ALPN */ -#if defined(MBEDTLS_SSL_PROTO_TLS1_2) -#if defined(MBEDTLS_SHA256_C) -static void ssl_calc_finished_tls_sha256( - mbedtls_ssl_context *ssl, unsigned char *buf, int from) +#if defined(MBEDTLS_SSL_DTLS_SRTP) +void mbedtls_ssl_conf_srtp_mki_value_supported(mbedtls_ssl_config *conf, + int support_mki_value) { - int len = 12; - const char *sender; - unsigned char padbuf[32]; -#if defined(MBEDTLS_USE_PSA_CRYPTO) - size_t hash_size; - psa_hash_operation_t sha256_psa = PSA_HASH_OPERATION_INIT; - psa_status_t status; -#else - mbedtls_sha256_context sha256; -#endif + conf->dtls_srtp_mki_support = support_mki_value; +} - mbedtls_ssl_session *session = ssl->session_negotiate; - if (!session) { - session = ssl->session; +int mbedtls_ssl_dtls_srtp_set_mki_value(mbedtls_ssl_context *ssl, + unsigned char *mki_value, + uint16_t mki_len) +{ + if (mki_len > MBEDTLS_TLS_SRTP_MAX_MKI_LENGTH) { + return MBEDTLS_ERR_SSL_BAD_INPUT_DATA; } - sender = (from == MBEDTLS_SSL_IS_CLIENT) - ? "client finished" - : "server finished"; + if (ssl->conf->dtls_srtp_mki_support == MBEDTLS_SSL_DTLS_SRTP_MKI_UNSUPPORTED) { + return MBEDTLS_ERR_SSL_FEATURE_UNAVAILABLE; + } -#if defined(MBEDTLS_USE_PSA_CRYPTO) - sha256_psa = psa_hash_operation_init(); + memcpy(ssl->dtls_srtp_info.mki_value, mki_value, mki_len); + ssl->dtls_srtp_info.mki_len = mki_len; + return 0; +} - MBEDTLS_SSL_DEBUG_MSG(2, ("=> calc PSA finished tls sha256")); +int mbedtls_ssl_conf_dtls_srtp_protection_profiles(mbedtls_ssl_config *conf, + const mbedtls_ssl_srtp_profile *profiles) +{ + const mbedtls_ssl_srtp_profile *p; + size_t list_size = 0; - status = psa_hash_clone(&ssl->handshake->fin_sha256_psa, &sha256_psa); - if (status != PSA_SUCCESS) { - MBEDTLS_SSL_DEBUG_MSG(2, ("PSA hash clone failed")); - return; + /* check the profiles list: all entry must be valid, + * its size cannot be more than the total number of supported profiles, currently 4 */ + for (p = profiles; *p != MBEDTLS_TLS_SRTP_UNSET && + list_size <= MBEDTLS_TLS_SRTP_MAX_PROFILE_LIST_LENGTH; + p++) { + if (mbedtls_ssl_check_srtp_profile_value(*p) != MBEDTLS_TLS_SRTP_UNSET) { + list_size++; + } else { + /* unsupported value, stop parsing and set the size to an error value */ + list_size = MBEDTLS_TLS_SRTP_MAX_PROFILE_LIST_LENGTH + 1; + } } - status = psa_hash_finish(&sha256_psa, padbuf, sizeof(padbuf), &hash_size); - if (status != PSA_SUCCESS) { - MBEDTLS_SSL_DEBUG_MSG(2, ("PSA hash finish failed")); - return; + if (list_size > MBEDTLS_TLS_SRTP_MAX_PROFILE_LIST_LENGTH) { + conf->dtls_srtp_profile_list = NULL; + conf->dtls_srtp_profile_list_len = 0; + return MBEDTLS_ERR_SSL_BAD_INPUT_DATA; } - MBEDTLS_SSL_DEBUG_BUF(3, "PSA calculated padbuf", padbuf, 32); -#else - mbedtls_sha256_init(&sha256); + conf->dtls_srtp_profile_list = profiles; + conf->dtls_srtp_profile_list_len = list_size; + + return 0; +} - MBEDTLS_SSL_DEBUG_MSG(2, ("=> calc finished tls sha256")); +void mbedtls_ssl_get_dtls_srtp_negotiation_result(const mbedtls_ssl_context *ssl, + mbedtls_dtls_srtp_info *dtls_srtp_info) +{ + dtls_srtp_info->chosen_dtls_srtp_profile = ssl->dtls_srtp_info.chosen_dtls_srtp_profile; + /* do not copy the mki value if there is no chosen profile */ + if (dtls_srtp_info->chosen_dtls_srtp_profile == MBEDTLS_TLS_SRTP_UNSET) { + dtls_srtp_info->mki_len = 0; + } else { + dtls_srtp_info->mki_len = ssl->dtls_srtp_info.mki_len; + memcpy(dtls_srtp_info->mki_value, ssl->dtls_srtp_info.mki_value, + ssl->dtls_srtp_info.mki_len); + } +} +#endif /* MBEDTLS_SSL_DTLS_SRTP */ - mbedtls_sha256_clone(&sha256, &ssl->handshake->fin_sha256); +#if !defined(MBEDTLS_DEPRECATED_REMOVED) +void mbedtls_ssl_conf_max_version(mbedtls_ssl_config *conf, int major, int minor) +{ + conf->max_tls_version = (mbedtls_ssl_protocol_version) ((major << 8) | minor); +} - /* - * TLSv1.2: - * hash = PRF( master, finished_label, - * Hash( handshake ) )[0.11] - */ +void mbedtls_ssl_conf_min_version(mbedtls_ssl_config *conf, int major, int minor) +{ + conf->min_tls_version = (mbedtls_ssl_protocol_version) ((major << 8) | minor); +} +#endif /* MBEDTLS_DEPRECATED_REMOVED */ -#if !defined(MBEDTLS_SHA256_ALT) - MBEDTLS_SSL_DEBUG_BUF(4, "finished sha2 state", (unsigned char *) - sha256.state, sizeof(sha256.state)); +#if defined(MBEDTLS_SSL_SRV_C) +void mbedtls_ssl_conf_cert_req_ca_list(mbedtls_ssl_config *conf, + char cert_req_ca_list) +{ + conf->cert_req_ca_list = cert_req_ca_list; +} #endif - mbedtls_sha256_finish_ret(&sha256, padbuf); - mbedtls_sha256_free(&sha256); -#endif /* MBEDTLS_USE_PSA_CRYPTO */ +#if defined(MBEDTLS_SSL_ENCRYPT_THEN_MAC) +void mbedtls_ssl_conf_encrypt_then_mac(mbedtls_ssl_config *conf, char etm) +{ + conf->encrypt_then_mac = etm; +} +#endif - ssl->handshake->tls_prf(session->master, 48, sender, - padbuf, 32, buf, len); +#if defined(MBEDTLS_SSL_EXTENDED_MASTER_SECRET) +void mbedtls_ssl_conf_extended_master_secret(mbedtls_ssl_config *conf, char ems) +{ + conf->extended_ms = ems; +} +#endif - MBEDTLS_SSL_DEBUG_BUF(3, "calc finished result", buf, len); +#if defined(MBEDTLS_SSL_MAX_FRAGMENT_LENGTH) +int mbedtls_ssl_conf_max_frag_len(mbedtls_ssl_config *conf, unsigned char mfl_code) +{ + if (mfl_code >= MBEDTLS_SSL_MAX_FRAG_LEN_INVALID || + ssl_mfl_code_to_length(mfl_code) > MBEDTLS_TLS_EXT_ADV_CONTENT_LEN) { + return MBEDTLS_ERR_SSL_BAD_INPUT_DATA; + } - mbedtls_platform_zeroize(padbuf, sizeof(padbuf)); + conf->mfl_code = mfl_code; - MBEDTLS_SSL_DEBUG_MSG(2, ("<= calc finished")); + return 0; } -#endif /* MBEDTLS_SHA256_C */ +#endif /* MBEDTLS_SSL_MAX_FRAGMENT_LENGTH */ -#if defined(MBEDTLS_SHA512_C) && !defined(MBEDTLS_SHA512_NO_SHA384) +void mbedtls_ssl_conf_legacy_renegotiation(mbedtls_ssl_config *conf, int allow_legacy) +{ + conf->allow_legacy_renegotiation = allow_legacy; +} -static void ssl_calc_finished_tls_sha384( - mbedtls_ssl_context *ssl, unsigned char *buf, int from) +#if defined(MBEDTLS_SSL_RENEGOTIATION) +void mbedtls_ssl_conf_renegotiation(mbedtls_ssl_config *conf, int renegotiation) { - int len = 12; - const char *sender; - unsigned char padbuf[48]; -#if defined(MBEDTLS_USE_PSA_CRYPTO) - size_t hash_size; - psa_hash_operation_t sha384_psa = PSA_HASH_OPERATION_INIT; - psa_status_t status; -#else - mbedtls_sha512_context sha512; -#endif - - mbedtls_ssl_session *session = ssl->session_negotiate; - if (!session) { - session = ssl->session; - } - - sender = (from == MBEDTLS_SSL_IS_CLIENT) - ? "client finished" - : "server finished"; - -#if defined(MBEDTLS_USE_PSA_CRYPTO) - sha384_psa = psa_hash_operation_init(); - - MBEDTLS_SSL_DEBUG_MSG(2, ("=> calc PSA finished tls sha384")); - - status = psa_hash_clone(&ssl->handshake->fin_sha384_psa, &sha384_psa); - if (status != PSA_SUCCESS) { - MBEDTLS_SSL_DEBUG_MSG(2, ("PSA hash clone failed")); - return; - } + conf->disable_renegotiation = renegotiation; +} - status = psa_hash_finish(&sha384_psa, padbuf, sizeof(padbuf), &hash_size); - if (status != PSA_SUCCESS) { - MBEDTLS_SSL_DEBUG_MSG(2, ("PSA hash finish failed")); - return; - } - MBEDTLS_SSL_DEBUG_BUF(3, "PSA calculated padbuf", padbuf, 48); -#else - mbedtls_sha512_init(&sha512); +void mbedtls_ssl_conf_renegotiation_enforced(mbedtls_ssl_config *conf, int max_records) +{ + conf->renego_max_records = max_records; +} - MBEDTLS_SSL_DEBUG_MSG(2, ("=> calc finished tls sha384")); +void mbedtls_ssl_conf_renegotiation_period(mbedtls_ssl_config *conf, + const unsigned char period[8]) +{ + memcpy(conf->renego_period, period, 8); +} +#endif /* MBEDTLS_SSL_RENEGOTIATION */ - mbedtls_sha512_clone(&sha512, &ssl->handshake->fin_sha512); +#if defined(MBEDTLS_SSL_SESSION_TICKETS) +#if defined(MBEDTLS_SSL_CLI_C) +void mbedtls_ssl_conf_session_tickets(mbedtls_ssl_config *conf, int use_tickets) +{ + conf->session_tickets = use_tickets; +} +#endif - /* - * TLSv1.2: - * hash = PRF( master, finished_label, - * Hash( handshake ) )[0.11] - */ +#if defined(MBEDTLS_SSL_SRV_C) -#if !defined(MBEDTLS_SHA512_ALT) - MBEDTLS_SSL_DEBUG_BUF(4, "finished sha512 state", (unsigned char *) - sha512.state, sizeof(sha512.state)); -#endif - /* mbedtls_sha512_finish_ret's output parameter is declared as a - * 64-byte buffer, but since we're using SHA-384, we know that the - * output fits in 48 bytes. This is correct C, but GCC 11.1 warns - * about it. - */ -#if defined(__GNUC__) && __GNUC__ >= 11 -#pragma GCC diagnostic push -#pragma GCC diagnostic ignored "-Wstringop-overflow" -#endif - mbedtls_sha512_finish_ret(&sha512, padbuf); -#if defined(__GNUC__) && __GNUC__ >= 11 -#pragma GCC diagnostic pop +#if defined(MBEDTLS_SSL_PROTO_TLS1_3) && defined(MBEDTLS_SSL_SESSION_TICKETS) +void mbedtls_ssl_conf_new_session_tickets(mbedtls_ssl_config *conf, + uint16_t num_tickets) +{ + conf->new_session_tickets_count = num_tickets; +} #endif - mbedtls_sha512_free(&sha512); +void mbedtls_ssl_conf_session_tickets_cb(mbedtls_ssl_config *conf, + mbedtls_ssl_ticket_write_t *f_ticket_write, + mbedtls_ssl_ticket_parse_t *f_ticket_parse, + void *p_ticket) +{ + conf->f_ticket_write = f_ticket_write; + conf->f_ticket_parse = f_ticket_parse; + conf->p_ticket = p_ticket; +} #endif +#endif /* MBEDTLS_SSL_SESSION_TICKETS */ - ssl->handshake->tls_prf(session->master, 48, sender, - padbuf, 48, buf, len); +void mbedtls_ssl_set_export_keys_cb(mbedtls_ssl_context *ssl, + mbedtls_ssl_export_keys_t *f_export_keys, + void *p_export_keys) +{ + ssl->f_export_keys = f_export_keys; + ssl->p_export_keys = p_export_keys; +} - MBEDTLS_SSL_DEBUG_BUF(3, "calc finished result", buf, len); +#if defined(MBEDTLS_SSL_ASYNC_PRIVATE) +void mbedtls_ssl_conf_async_private_cb( + mbedtls_ssl_config *conf, + mbedtls_ssl_async_sign_t *f_async_sign, + mbedtls_ssl_async_decrypt_t *f_async_decrypt, + mbedtls_ssl_async_resume_t *f_async_resume, + mbedtls_ssl_async_cancel_t *f_async_cancel, + void *async_config_data) +{ + conf->f_async_sign_start = f_async_sign; + conf->f_async_decrypt_start = f_async_decrypt; + conf->f_async_resume = f_async_resume; + conf->f_async_cancel = f_async_cancel; + conf->p_async_config_data = async_config_data; +} - mbedtls_platform_zeroize(padbuf, sizeof(padbuf)); +void *mbedtls_ssl_conf_get_async_config_data(const mbedtls_ssl_config *conf) +{ + return conf->p_async_config_data; +} - MBEDTLS_SSL_DEBUG_MSG(2, ("<= calc finished")); +void *mbedtls_ssl_get_async_operation_data(const mbedtls_ssl_context *ssl) +{ + if (ssl->handshake == NULL) { + return NULL; + } else { + return ssl->handshake->user_async_ctx; + } } -#endif /* MBEDTLS_SHA512_C && !MBEDTLS_SHA512_NO_SHA384 */ -#endif /* MBEDTLS_SSL_PROTO_TLS1_2 */ -void mbedtls_ssl_handshake_wrapup_free_hs_transform(mbedtls_ssl_context *ssl) +void mbedtls_ssl_set_async_operation_data(mbedtls_ssl_context *ssl, + void *ctx) { - MBEDTLS_SSL_DEBUG_MSG(3, ("=> handshake wrapup: final free")); + if (ssl->handshake != NULL) { + ssl->handshake->user_async_ctx = ctx; + } +} +#endif /* MBEDTLS_SSL_ASYNC_PRIVATE */ - /* - * Free our handshake params - */ - mbedtls_ssl_handshake_free(ssl); - mbedtls_free(ssl->handshake); - ssl->handshake = NULL; +/* + * SSL get accessors + */ +uint32_t mbedtls_ssl_get_verify_result(const mbedtls_ssl_context *ssl) +{ + if (ssl->session != NULL) { + return ssl->session->verify_result; + } - /* - * Free the previous transform and switch in the current one - */ - if (ssl->transform) { - mbedtls_ssl_transform_free(ssl->transform); - mbedtls_free(ssl->transform); + if (ssl->session_negotiate != NULL) { + return ssl->session_negotiate->verify_result; } - ssl->transform = ssl->transform_negotiate; - ssl->transform_negotiate = NULL; - MBEDTLS_SSL_DEBUG_MSG(3, ("<= handshake wrapup: final free")); + return 0xFFFFFFFF; } -void mbedtls_ssl_handshake_wrapup(mbedtls_ssl_context *ssl) +int mbedtls_ssl_get_ciphersuite_id_from_ssl(const mbedtls_ssl_context *ssl) { - int resume = ssl->handshake->resume; - - MBEDTLS_SSL_DEBUG_MSG(3, ("=> handshake wrapup")); - -#if defined(MBEDTLS_SSL_RENEGOTIATION) - if (ssl->renego_status == MBEDTLS_SSL_RENEGOTIATION_IN_PROGRESS) { - ssl->renego_status = MBEDTLS_SSL_RENEGOTIATION_DONE; - ssl->renego_records_seen = 0; + if (ssl == NULL || ssl->session == NULL) { + return 0; } -#endif - /* - * Free the previous session and switch in the current one - */ - if (ssl->session) { -#if defined(MBEDTLS_SSL_ENCRYPT_THEN_MAC) - /* RFC 7366 3.1: keep the EtM state */ - ssl->session_negotiate->encrypt_then_mac = - ssl->session->encrypt_then_mac; -#endif + return ssl->session->ciphersuite; +} - mbedtls_ssl_session_free(ssl->session); - mbedtls_free(ssl->session); +const char *mbedtls_ssl_get_ciphersuite(const mbedtls_ssl_context *ssl) +{ + if (ssl == NULL || ssl->session == NULL) { + return NULL; } - ssl->session = ssl->session_negotiate; - ssl->session_negotiate = NULL; - /* - * Add cache entry - */ - if (ssl->conf->f_set_cache != NULL && - ssl->session->id_len != 0 && - resume == 0) { - if (ssl->conf->f_set_cache(ssl->conf->p_cache, ssl->session) != 0) { - MBEDTLS_SSL_DEBUG_MSG(1, ("cache did not store session")); - } - } + return mbedtls_ssl_get_ciphersuite_name(ssl->session->ciphersuite); +} +const char *mbedtls_ssl_get_version(const mbedtls_ssl_context *ssl) +{ #if defined(MBEDTLS_SSL_PROTO_DTLS) - if (ssl->conf->transport == MBEDTLS_SSL_TRANSPORT_DATAGRAM && - ssl->handshake->flight != NULL) { - /* Cancel handshake timer */ - mbedtls_ssl_set_timer(ssl, 0); - - /* Keep last flight around in case we need to resend it: - * we need the handshake and transform structures for that */ - MBEDTLS_SSL_DEBUG_MSG(3, ("skip freeing handshake and transform")); - } else + if (ssl->conf->transport == MBEDTLS_SSL_TRANSPORT_DATAGRAM) { + switch (ssl->tls_version) { + case MBEDTLS_SSL_VERSION_TLS1_2: + return "DTLSv1.2"; + default: + return "unknown (DTLS)"; + } + } #endif - mbedtls_ssl_handshake_wrapup_free_hs_transform(ssl); - - ssl->state++; - MBEDTLS_SSL_DEBUG_MSG(3, ("<= handshake wrapup")); + switch (ssl->tls_version) { + case MBEDTLS_SSL_VERSION_TLS1_2: + return "TLSv1.2"; + case MBEDTLS_SSL_VERSION_TLS1_3: + return "TLSv1.3"; + default: + return "unknown"; + } } -int mbedtls_ssl_write_finished(mbedtls_ssl_context *ssl) +#if defined(MBEDTLS_SSL_RECORD_SIZE_LIMIT) + +size_t mbedtls_ssl_get_output_record_size_limit(const mbedtls_ssl_context *ssl) { - int ret, hash_len; + const size_t max_len = MBEDTLS_SSL_OUT_CONTENT_LEN; + size_t record_size_limit = max_len; - MBEDTLS_SSL_DEBUG_MSG(2, ("=> write finished")); + if (ssl->session != NULL && + ssl->session->record_size_limit >= MBEDTLS_SSL_RECORD_SIZE_LIMIT_MIN && + ssl->session->record_size_limit < max_len) { + record_size_limit = ssl->session->record_size_limit; + } - mbedtls_ssl_update_out_pointers(ssl, ssl->transform_negotiate); + // TODO: this is currently untested + /* During a handshake, use the value being negotiated */ + if (ssl->session_negotiate != NULL && + ssl->session_negotiate->record_size_limit >= MBEDTLS_SSL_RECORD_SIZE_LIMIT_MIN && + ssl->session_negotiate->record_size_limit < max_len) { + record_size_limit = ssl->session_negotiate->record_size_limit; + } - ssl->handshake->calc_finished(ssl, ssl->out_msg + 4, ssl->conf->endpoint); + return record_size_limit; +} +#endif /* MBEDTLS_SSL_RECORD_SIZE_LIMIT */ - /* - * RFC 5246 7.4.9 (Page 63) says 12 is the default length and ciphersuites - * may define some other value. Currently (early 2016), no defined - * ciphersuite does this (and this is unlikely to change as activity has - * moved to TLS 1.3 now) so we can keep the hardcoded 12 here. - */ - hash_len = (ssl->minor_ver == MBEDTLS_SSL_MINOR_VERSION_0) ? 36 : 12; +#if defined(MBEDTLS_SSL_MAX_FRAGMENT_LENGTH) +size_t mbedtls_ssl_get_input_max_frag_len(const mbedtls_ssl_context *ssl) +{ + size_t max_len = MBEDTLS_SSL_IN_CONTENT_LEN; + size_t read_mfl; -#if defined(MBEDTLS_SSL_RENEGOTIATION) - ssl->verify_data_len = hash_len; - memcpy(ssl->own_verify_data, ssl->out_msg + 4, hash_len); +#if defined(MBEDTLS_SSL_PROTO_TLS1_2) + /* Use the configured MFL for the client if we're past SERVER_HELLO_DONE */ + if (ssl->conf->endpoint == MBEDTLS_SSL_IS_CLIENT && + ssl->state >= MBEDTLS_SSL_SERVER_HELLO_DONE) { + return ssl_mfl_code_to_length(ssl->conf->mfl_code); + } #endif - ssl->out_msglen = 4 + hash_len; - ssl->out_msgtype = MBEDTLS_SSL_MSG_HANDSHAKE; - ssl->out_msg[0] = MBEDTLS_SSL_HS_FINISHED; - - /* - * In case of session resuming, invert the client and server - * ChangeCipherSpec messages order. - */ - if (ssl->handshake->resume != 0) { -#if defined(MBEDTLS_SSL_CLI_C) - if (ssl->conf->endpoint == MBEDTLS_SSL_IS_CLIENT) { - ssl->state = MBEDTLS_SSL_HANDSHAKE_WRAPUP; + /* Check if a smaller max length was negotiated */ + if (ssl->session_out != NULL) { + read_mfl = ssl_mfl_code_to_length(ssl->session_out->mfl_code); + if (read_mfl < max_len) { + max_len = read_mfl; } -#endif -#if defined(MBEDTLS_SSL_SRV_C) - if (ssl->conf->endpoint == MBEDTLS_SSL_IS_SERVER) { - ssl->state = MBEDTLS_SSL_CLIENT_CHANGE_CIPHER_SPEC; + } + + /* During a handshake, use the value being negotiated */ + if (ssl->session_negotiate != NULL) { + read_mfl = ssl_mfl_code_to_length(ssl->session_negotiate->mfl_code); + if (read_mfl < max_len) { + max_len = read_mfl; } -#endif - } else { - ssl->state++; } - /* - * Switch to our negotiated transform and session parameters for outbound - * data. - */ - MBEDTLS_SSL_DEBUG_MSG(3, ("switching to new transform spec for outbound data")); - -#if defined(MBEDTLS_SSL_PROTO_DTLS) - if (ssl->conf->transport == MBEDTLS_SSL_TRANSPORT_DATAGRAM) { - unsigned char i; - - /* Remember current epoch settings for resending */ - ssl->handshake->alt_transform_out = ssl->transform_out; - memcpy(ssl->handshake->alt_out_ctr, ssl->cur_out_ctr, 8); - - /* Set sequence_number to zero */ - memset(ssl->cur_out_ctr + 2, 0, 6); + return max_len; +} - /* Increment epoch */ - for (i = 2; i > 0; i--) { - if (++ssl->cur_out_ctr[i - 1] != 0) { - break; - } - } +size_t mbedtls_ssl_get_output_max_frag_len(const mbedtls_ssl_context *ssl) +{ + size_t max_len; - /* The loop goes to its end iff the counter is wrapping */ - if (i == 0) { - MBEDTLS_SSL_DEBUG_MSG(1, ("DTLS epoch would wrap")); - return MBEDTLS_ERR_SSL_COUNTER_WRAPPING; - } - } else -#endif /* MBEDTLS_SSL_PROTO_DTLS */ - memset(ssl->cur_out_ctr, 0, 8); + /* + * Assume mfl_code is correct since it was checked when set + */ + max_len = ssl_mfl_code_to_length(ssl->conf->mfl_code); - ssl->transform_out = ssl->transform_negotiate; - ssl->session_out = ssl->session_negotiate; + /* Check if a smaller max length was negotiated */ + if (ssl->session_out != NULL && + ssl_mfl_code_to_length(ssl->session_out->mfl_code) < max_len) { + max_len = ssl_mfl_code_to_length(ssl->session_out->mfl_code); + } -#if defined(MBEDTLS_SSL_HW_RECORD_ACCEL) - if (mbedtls_ssl_hw_record_activate != NULL) { - if ((ret = mbedtls_ssl_hw_record_activate(ssl, MBEDTLS_SSL_CHANNEL_OUTBOUND)) != 0) { - MBEDTLS_SSL_DEBUG_RET(1, "mbedtls_ssl_hw_record_activate", ret); - return MBEDTLS_ERR_SSL_HW_ACCEL_FAILED; - } + /* During a handshake, use the value being negotiated */ + if (ssl->session_negotiate != NULL && + ssl_mfl_code_to_length(ssl->session_negotiate->mfl_code) < max_len) { + max_len = ssl_mfl_code_to_length(ssl->session_negotiate->mfl_code); } -#endif + + return max_len; +} +#endif /* MBEDTLS_SSL_MAX_FRAGMENT_LENGTH */ #if defined(MBEDTLS_SSL_PROTO_DTLS) - if (ssl->conf->transport == MBEDTLS_SSL_TRANSPORT_DATAGRAM) { - mbedtls_ssl_send_flight_completed(ssl); +size_t mbedtls_ssl_get_current_mtu(const mbedtls_ssl_context *ssl) +{ + /* Return unlimited mtu for client hello messages to avoid fragmentation. */ + if (ssl->conf->endpoint == MBEDTLS_SSL_IS_CLIENT && + (ssl->state == MBEDTLS_SSL_CLIENT_HELLO || + ssl->state == MBEDTLS_SSL_SERVER_HELLO)) { + return 0; } -#endif - if ((ret = mbedtls_ssl_write_handshake_msg(ssl)) != 0) { - MBEDTLS_SSL_DEBUG_RET(1, "mbedtls_ssl_write_handshake_msg", ret); - return ret; + if (ssl->handshake == NULL || ssl->handshake->mtu == 0) { + return ssl->mtu; } -#if defined(MBEDTLS_SSL_PROTO_DTLS) - if (ssl->conf->transport == MBEDTLS_SSL_TRANSPORT_DATAGRAM && - (ret = mbedtls_ssl_flight_transmit(ssl)) != 0) { - MBEDTLS_SSL_DEBUG_RET(1, "mbedtls_ssl_flight_transmit", ret); - return ret; + if (ssl->mtu == 0) { + return ssl->handshake->mtu; } -#endif - - MBEDTLS_SSL_DEBUG_MSG(2, ("<= write finished")); - return 0; + return ssl->mtu < ssl->handshake->mtu ? + ssl->mtu : ssl->handshake->mtu; } +#endif /* MBEDTLS_SSL_PROTO_DTLS */ -#if defined(MBEDTLS_SSL_PROTO_SSL3) -#define SSL_MAX_HASH_LEN 36 -#else -#define SSL_MAX_HASH_LEN 12 -#endif - -int mbedtls_ssl_parse_finished(mbedtls_ssl_context *ssl) +int mbedtls_ssl_get_max_out_record_payload(const mbedtls_ssl_context *ssl) { - int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED; - unsigned int hash_len; - unsigned char buf[SSL_MAX_HASH_LEN]; - - MBEDTLS_SSL_DEBUG_MSG(2, ("=> parse finished")); + size_t max_len = MBEDTLS_SSL_OUT_CONTENT_LEN; - /* There is currently no ciphersuite using another length with TLS 1.2 */ -#if defined(MBEDTLS_SSL_PROTO_SSL3) - if (ssl->minor_ver == MBEDTLS_SSL_MINOR_VERSION_0) { - hash_len = 36; - } else +#if !defined(MBEDTLS_SSL_MAX_FRAGMENT_LENGTH) && \ + !defined(MBEDTLS_SSL_RECORD_SIZE_LIMIT) && \ + !defined(MBEDTLS_SSL_PROTO_DTLS) + (void) ssl; #endif - hash_len = 12; - ssl->handshake->calc_finished(ssl, buf, ssl->conf->endpoint ^ 1); +#if defined(MBEDTLS_SSL_MAX_FRAGMENT_LENGTH) + const size_t mfl = mbedtls_ssl_get_output_max_frag_len(ssl); - if ((ret = mbedtls_ssl_read_record(ssl, 1)) != 0) { - MBEDTLS_SSL_DEBUG_RET(1, "mbedtls_ssl_read_record", ret); - goto exit; + if (max_len > mfl) { + max_len = mfl; } +#endif - if (ssl->in_msgtype != MBEDTLS_SSL_MSG_HANDSHAKE) { - MBEDTLS_SSL_DEBUG_MSG(1, ("bad finished message")); - mbedtls_ssl_send_alert_message(ssl, MBEDTLS_SSL_ALERT_LEVEL_FATAL, - MBEDTLS_SSL_ALERT_MSG_UNEXPECTED_MESSAGE); - ret = MBEDTLS_ERR_SSL_UNEXPECTED_MESSAGE; - goto exit; - } +#if defined(MBEDTLS_SSL_RECORD_SIZE_LIMIT) + const size_t record_size_limit = mbedtls_ssl_get_output_record_size_limit(ssl); - if (ssl->in_msg[0] != MBEDTLS_SSL_HS_FINISHED || - ssl->in_hslen != mbedtls_ssl_hs_hdr_len(ssl) + hash_len) { - MBEDTLS_SSL_DEBUG_MSG(1, ("bad finished message")); - mbedtls_ssl_send_alert_message(ssl, MBEDTLS_SSL_ALERT_LEVEL_FATAL, - MBEDTLS_SSL_ALERT_MSG_DECODE_ERROR); - ret = MBEDTLS_ERR_SSL_BAD_HS_FINISHED; - goto exit; + if (max_len > record_size_limit) { + max_len = record_size_limit; } +#endif - if (mbedtls_ct_memcmp(ssl->in_msg + mbedtls_ssl_hs_hdr_len(ssl), - buf, hash_len) != 0) { - MBEDTLS_SSL_DEBUG_MSG(1, ("bad finished message")); - mbedtls_ssl_send_alert_message(ssl, MBEDTLS_SSL_ALERT_LEVEL_FATAL, - MBEDTLS_SSL_ALERT_MSG_DECRYPT_ERROR); - ret = MBEDTLS_ERR_SSL_BAD_HS_FINISHED; - goto exit; + if (ssl->transform_out != NULL && + ssl->transform_out->tls_version == MBEDTLS_SSL_VERSION_TLS1_3) { + /* + * In TLS 1.3 case, when records are protected, `max_len` as computed + * above is the maximum length of the TLSInnerPlaintext structure that + * along the plaintext payload contains the inner content type (one byte) + * and some zero padding. Given the algorithm used for padding + * in mbedtls_ssl_encrypt_buf(), compute the maximum length for + * the plaintext payload. Round down to a multiple of + * MBEDTLS_SSL_CID_TLS1_3_PADDING_GRANULARITY and + * subtract 1. + */ + max_len = ((max_len / MBEDTLS_SSL_CID_TLS1_3_PADDING_GRANULARITY) * + MBEDTLS_SSL_CID_TLS1_3_PADDING_GRANULARITY) - 1; } -#if defined(MBEDTLS_SSL_RENEGOTIATION) - ssl->verify_data_len = hash_len; - memcpy(ssl->peer_verify_data, buf, hash_len); -#endif +#if defined(MBEDTLS_SSL_PROTO_DTLS) + if (mbedtls_ssl_get_current_mtu(ssl) != 0) { + const size_t mtu = mbedtls_ssl_get_current_mtu(ssl); + const int ret = mbedtls_ssl_get_record_expansion(ssl); + const size_t overhead = (size_t) ret; - if (ssl->handshake->resume != 0) { -#if defined(MBEDTLS_SSL_CLI_C) - if (ssl->conf->endpoint == MBEDTLS_SSL_IS_CLIENT) { - ssl->state = MBEDTLS_SSL_CLIENT_CHANGE_CIPHER_SPEC; + if (ret < 0) { + return ret; } -#endif -#if defined(MBEDTLS_SSL_SRV_C) - if (ssl->conf->endpoint == MBEDTLS_SSL_IS_SERVER) { - ssl->state = MBEDTLS_SSL_HANDSHAKE_WRAPUP; + + if (mtu <= overhead) { + MBEDTLS_SSL_DEBUG_MSG(1, ("MTU too low for record expansion")); + return MBEDTLS_ERR_SSL_FEATURE_UNAVAILABLE; } -#endif - } else { - ssl->state++; - } -#if defined(MBEDTLS_SSL_PROTO_DTLS) - if (ssl->conf->transport == MBEDTLS_SSL_TRANSPORT_DATAGRAM) { - mbedtls_ssl_recv_flight_completed(ssl); + if (max_len > mtu - overhead) { + max_len = mtu - overhead; + } } -#endif +#endif /* MBEDTLS_SSL_PROTO_DTLS */ - MBEDTLS_SSL_DEBUG_MSG(2, ("<= parse finished")); +#if !defined(MBEDTLS_SSL_MAX_FRAGMENT_LENGTH) && \ + !defined(MBEDTLS_SSL_PROTO_DTLS) && \ + !defined(MBEDTLS_SSL_RECORD_SIZE_LIMIT) + ((void) ssl); +#endif -exit: - mbedtls_platform_zeroize(buf, hash_len); - return ret; + return (int) max_len; } -static void ssl_handshake_params_init(mbedtls_ssl_handshake_params *handshake) +int mbedtls_ssl_get_max_in_record_payload(const mbedtls_ssl_context *ssl) { - memset(handshake, 0, sizeof(mbedtls_ssl_handshake_params)); - -#if defined(MBEDTLS_SSL_PROTO_SSL3) || defined(MBEDTLS_SSL_PROTO_TLS1) || \ - defined(MBEDTLS_SSL_PROTO_TLS1_1) - mbedtls_md5_init(&handshake->fin_md5); - mbedtls_sha1_init(&handshake->fin_sha1); - mbedtls_md5_starts_ret(&handshake->fin_md5); - mbedtls_sha1_starts_ret(&handshake->fin_sha1); -#endif -#if defined(MBEDTLS_SSL_PROTO_TLS1_2) -#if defined(MBEDTLS_SHA256_C) -#if defined(MBEDTLS_USE_PSA_CRYPTO) - handshake->fin_sha256_psa = psa_hash_operation_init(); - psa_hash_setup(&handshake->fin_sha256_psa, PSA_ALG_SHA_256); -#else - mbedtls_sha256_init(&handshake->fin_sha256); - mbedtls_sha256_starts_ret(&handshake->fin_sha256, 0); -#endif -#endif -#if defined(MBEDTLS_SHA512_C) && !defined(MBEDTLS_SHA512_NO_SHA384) -#if defined(MBEDTLS_USE_PSA_CRYPTO) - handshake->fin_sha384_psa = psa_hash_operation_init(); - psa_hash_setup(&handshake->fin_sha384_psa, PSA_ALG_SHA_384); -#else - mbedtls_sha512_init(&handshake->fin_sha512); - mbedtls_sha512_starts_ret(&handshake->fin_sha512, 1); -#endif -#endif -#endif /* MBEDTLS_SSL_PROTO_TLS1_2 */ - - handshake->update_checksum = ssl_update_checksum_start; - -#if defined(MBEDTLS_SSL_PROTO_TLS1_2) && \ - defined(MBEDTLS_KEY_EXCHANGE_WITH_CERT_ENABLED) - mbedtls_ssl_sig_hash_set_init(&handshake->hash_algs); -#endif + size_t max_len = MBEDTLS_SSL_IN_CONTENT_LEN; -#if defined(MBEDTLS_DHM_C) - mbedtls_dhm_init(&handshake->dhm_ctx); -#endif -#if defined(MBEDTLS_ECDH_C) - mbedtls_ecdh_init(&handshake->ecdh_ctx); -#endif -#if defined(MBEDTLS_KEY_EXCHANGE_ECJPAKE_ENABLED) - mbedtls_ecjpake_init(&handshake->ecjpake_ctx); -#if defined(MBEDTLS_SSL_CLI_C) - handshake->ecjpake_cache = NULL; - handshake->ecjpake_cache_len = 0; -#endif +#if !defined(MBEDTLS_SSL_MAX_FRAGMENT_LENGTH) + (void) ssl; #endif -#if defined(MBEDTLS_SSL_ECP_RESTARTABLE_ENABLED) - mbedtls_x509_crt_restart_init(&handshake->ecrs_ctx); -#endif +#if defined(MBEDTLS_SSL_MAX_FRAGMENT_LENGTH) + const size_t mfl = mbedtls_ssl_get_input_max_frag_len(ssl); -#if defined(MBEDTLS_SSL_SERVER_NAME_INDICATION) - handshake->sni_authmode = MBEDTLS_SSL_VERIFY_UNSET; + if (max_len > mfl) { + max_len = mfl; + } #endif -#if defined(MBEDTLS_X509_CRT_PARSE_C) && \ - !defined(MBEDTLS_SSL_KEEP_PEER_CERTIFICATE) - mbedtls_pk_init(&handshake->peer_pubkey); -#endif + return (int) max_len; } -void mbedtls_ssl_transform_init(mbedtls_ssl_transform *transform) +#if defined(MBEDTLS_X509_CRT_PARSE_C) +const mbedtls_x509_crt *mbedtls_ssl_get_peer_cert(const mbedtls_ssl_context *ssl) { - memset(transform, 0, sizeof(mbedtls_ssl_transform)); - - mbedtls_cipher_init(&transform->cipher_ctx_enc); - mbedtls_cipher_init(&transform->cipher_ctx_dec); + if (ssl == NULL || ssl->session == NULL) { + return NULL; + } -#if defined(MBEDTLS_SSL_SOME_MODES_USE_MAC) - mbedtls_md_init(&transform->md_ctx_enc); - mbedtls_md_init(&transform->md_ctx_dec); -#endif +#if defined(MBEDTLS_SSL_KEEP_PEER_CERTIFICATE) + return ssl->session->peer_cert; +#else + return NULL; +#endif /* MBEDTLS_SSL_KEEP_PEER_CERTIFICATE */ } +#endif /* MBEDTLS_X509_CRT_PARSE_C */ -void mbedtls_ssl_session_init(mbedtls_ssl_session *session) +#if defined(MBEDTLS_SSL_CLI_C) +int mbedtls_ssl_get_session(const mbedtls_ssl_context *ssl, + mbedtls_ssl_session *dst) { - memset(session, 0, sizeof(mbedtls_ssl_session)); -} + int ret; -MBEDTLS_CHECK_RETURN_CRITICAL -static int ssl_handshake_init(mbedtls_ssl_context *ssl) -{ - /* Clear old handshake information if present */ - if (ssl->transform_negotiate) { - mbedtls_ssl_transform_free(ssl->transform_negotiate); - } - if (ssl->session_negotiate) { - mbedtls_ssl_session_free(ssl->session_negotiate); - } - if (ssl->handshake) { - mbedtls_ssl_handshake_free(ssl); + if (ssl == NULL || + dst == NULL || + ssl->session == NULL || + ssl->conf->endpoint != MBEDTLS_SSL_IS_CLIENT) { + return MBEDTLS_ERR_SSL_BAD_INPUT_DATA; } - /* - * Either the pointers are now NULL or cleared properly and can be freed. - * Now allocate missing structures. + /* Since Mbed TLS 3.0, mbedtls_ssl_get_session() is no longer + * idempotent: Each session can only be exported once. + * + * (This is in preparation for TLS 1.3 support where we will + * need the ability to export multiple sessions (aka tickets), + * which will be achieved by calling mbedtls_ssl_get_session() + * multiple times until it fails.) + * + * Check whether we have already exported the current session, + * and fail if so. */ - if (ssl->transform_negotiate == NULL) { - ssl->transform_negotiate = mbedtls_calloc(1, sizeof(mbedtls_ssl_transform)); + if (ssl->session->exported == 1) { + return MBEDTLS_ERR_SSL_FEATURE_UNAVAILABLE; } - if (ssl->session_negotiate == NULL) { - ssl->session_negotiate = mbedtls_calloc(1, sizeof(mbedtls_ssl_session)); + ret = mbedtls_ssl_session_copy(dst, ssl->session); + if (ret != 0) { + return ret; } - if (ssl->handshake == NULL) { - ssl->handshake = mbedtls_calloc(1, sizeof(mbedtls_ssl_handshake_params)); - } -#if defined(MBEDTLS_SSL_VARIABLE_BUFFER_LENGTH) - /* If the buffers are too small - reallocate */ + /* Remember that we've exported the session. */ + ssl->session->exported = 1; + return 0; +} +#endif /* MBEDTLS_SSL_CLI_C */ - handle_buffer_resizing(ssl, 0, MBEDTLS_SSL_IN_BUFFER_LEN, - MBEDTLS_SSL_OUT_BUFFER_LEN); -#endif +#if defined(MBEDTLS_SSL_PROTO_TLS1_2) - /* All pointers should exist and can be directly freed without issue */ - if (ssl->handshake == NULL || - ssl->transform_negotiate == NULL || - ssl->session_negotiate == NULL) { - MBEDTLS_SSL_DEBUG_MSG(1, ("alloc() of ssl sub-contexts failed")); +/* Serialization of TLS 1.2 sessions + * + * For more detail, see the description of ssl_session_save(). + */ +static size_t ssl_tls12_session_save(const mbedtls_ssl_session *session, + unsigned char *buf, + size_t buf_len) +{ + unsigned char *p = buf; + size_t used = 0; - mbedtls_free(ssl->handshake); - mbedtls_free(ssl->transform_negotiate); - mbedtls_free(ssl->session_negotiate); +#if defined(MBEDTLS_HAVE_TIME) + uint64_t start; +#endif +#if defined(MBEDTLS_X509_CRT_PARSE_C) +#if defined(MBEDTLS_SSL_KEEP_PEER_CERTIFICATE) + size_t cert_len; +#endif /* MBEDTLS_SSL_KEEP_PEER_CERTIFICATE */ +#endif /* MBEDTLS_X509_CRT_PARSE_C */ - ssl->handshake = NULL; - ssl->transform_negotiate = NULL; - ssl->session_negotiate = NULL; + /* + * Time + */ +#if defined(MBEDTLS_HAVE_TIME) + used += 8; - return MBEDTLS_ERR_SSL_ALLOC_FAILED; + if (used <= buf_len) { + start = (uint64_t) session->start; + + MBEDTLS_PUT_UINT64_BE(start, p, 0); + p += 8; } +#endif /* MBEDTLS_HAVE_TIME */ - /* Initialize structures */ - mbedtls_ssl_session_init(ssl->session_negotiate); - mbedtls_ssl_transform_init(ssl->transform_negotiate); - ssl_handshake_params_init(ssl->handshake); + /* + * Basic mandatory fields + */ + used += 1 /* id_len */ + + sizeof(session->id) + + sizeof(session->master) + + 4; /* verify_result */ -#if defined(MBEDTLS_SSL_PROTO_DTLS) - if (ssl->conf->transport == MBEDTLS_SSL_TRANSPORT_DATAGRAM) { - ssl->handshake->alt_transform_out = ssl->transform_out; + if (used <= buf_len) { + *p++ = MBEDTLS_BYTE_0(session->id_len); + memcpy(p, session->id, 32); + p += 32; - if (ssl->conf->endpoint == MBEDTLS_SSL_IS_CLIENT) { - ssl->handshake->retransmit_state = MBEDTLS_SSL_RETRANS_PREPARING; - } else { - ssl->handshake->retransmit_state = MBEDTLS_SSL_RETRANS_WAITING; - } + memcpy(p, session->master, 48); + p += 48; - mbedtls_ssl_set_timer(ssl, 0); + MBEDTLS_PUT_UINT32_BE(session->verify_result, p, 0); + p += 4; } -#endif - return 0; -} + /* + * Peer's end-entity certificate + */ +#if defined(MBEDTLS_X509_CRT_PARSE_C) +#if defined(MBEDTLS_SSL_KEEP_PEER_CERTIFICATE) + if (session->peer_cert == NULL) { + cert_len = 0; + } else { + cert_len = session->peer_cert->raw.len; + } -#if defined(MBEDTLS_SSL_DTLS_HELLO_VERIFY) && defined(MBEDTLS_SSL_SRV_C) -/* Dummy cookie callbacks for defaults */ -MBEDTLS_CHECK_RETURN_CRITICAL -static int ssl_cookie_write_dummy(void *ctx, - unsigned char **p, unsigned char *end, - const unsigned char *cli_id, size_t cli_id_len) -{ - ((void) ctx); - ((void) p); - ((void) end); - ((void) cli_id); - ((void) cli_id_len); + used += 3 + cert_len; - return MBEDTLS_ERR_SSL_FEATURE_UNAVAILABLE; -} + if (used <= buf_len) { + *p++ = MBEDTLS_BYTE_2(cert_len); + *p++ = MBEDTLS_BYTE_1(cert_len); + *p++ = MBEDTLS_BYTE_0(cert_len); -MBEDTLS_CHECK_RETURN_CRITICAL -static int ssl_cookie_check_dummy(void *ctx, - const unsigned char *cookie, size_t cookie_len, - const unsigned char *cli_id, size_t cli_id_len) -{ - ((void) ctx); - ((void) cookie); - ((void) cookie_len); - ((void) cli_id); - ((void) cli_id_len); + if (session->peer_cert != NULL) { + memcpy(p, session->peer_cert->raw.p, cert_len); + p += cert_len; + } + } +#else /* MBEDTLS_SSL_KEEP_PEER_CERTIFICATE */ + if (session->peer_cert_digest != NULL) { + used += 1 /* type */ + 1 /* length */ + session->peer_cert_digest_len; + if (used <= buf_len) { + *p++ = (unsigned char) session->peer_cert_digest_type; + *p++ = (unsigned char) session->peer_cert_digest_len; + memcpy(p, session->peer_cert_digest, + session->peer_cert_digest_len); + p += session->peer_cert_digest_len; + } + } else { + used += 2; + if (used <= buf_len) { + *p++ = (unsigned char) MBEDTLS_MD_NONE; + *p++ = 0; + } + } +#endif /* !MBEDTLS_SSL_KEEP_PEER_CERTIFICATE */ +#endif /* MBEDTLS_X509_CRT_PARSE_C */ - return MBEDTLS_ERR_SSL_FEATURE_UNAVAILABLE; -} -#endif /* MBEDTLS_SSL_DTLS_HELLO_VERIFY && MBEDTLS_SSL_SRV_C */ + /* + * Session ticket if any, plus associated data + */ +#if defined(MBEDTLS_SSL_SESSION_TICKETS) +#if defined(MBEDTLS_SSL_CLI_C) + if (session->endpoint == MBEDTLS_SSL_IS_CLIENT) { + used += 3 + session->ticket_len + 4; /* len + ticket + lifetime */ -/* - * Initialize an SSL context - */ -void mbedtls_ssl_init(mbedtls_ssl_context *ssl) -{ - memset(ssl, 0, sizeof(mbedtls_ssl_context)); -} + if (used <= buf_len) { + *p++ = MBEDTLS_BYTE_2(session->ticket_len); + *p++ = MBEDTLS_BYTE_1(session->ticket_len); + *p++ = MBEDTLS_BYTE_0(session->ticket_len); -/* - * Setup an SSL context - */ + if (session->ticket != NULL) { + memcpy(p, session->ticket, session->ticket_len); + p += session->ticket_len; + } -int mbedtls_ssl_setup(mbedtls_ssl_context *ssl, - const mbedtls_ssl_config *conf) -{ - int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED; - size_t in_buf_len = MBEDTLS_SSL_IN_BUFFER_LEN; - size_t out_buf_len = MBEDTLS_SSL_OUT_BUFFER_LEN; + MBEDTLS_PUT_UINT32_BE(session->ticket_lifetime, p, 0); + p += 4; + } + } +#endif /* MBEDTLS_SSL_CLI_C */ +#if defined(MBEDTLS_HAVE_TIME) && defined(MBEDTLS_SSL_SRV_C) + if (session->endpoint == MBEDTLS_SSL_IS_SERVER) { + used += 8; - ssl->conf = conf; + if (used <= buf_len) { + MBEDTLS_PUT_UINT64_BE((uint64_t) session->ticket_creation_time, p, 0); + p += 8; + } + } +#endif /* MBEDTLS_HAVE_TIME && MBEDTLS_SSL_SRV_C */ +#endif /* MBEDTLS_SSL_SESSION_TICKETS */ /* - * Prepare base structures + * Misc extension-related info */ +#if defined(MBEDTLS_SSL_MAX_FRAGMENT_LENGTH) + used += 1; - /* Set to NULL in case of an error condition */ - ssl->out_buf = NULL; - -#if defined(MBEDTLS_SSL_VARIABLE_BUFFER_LENGTH) - ssl->in_buf_len = in_buf_len; -#endif - ssl->in_buf = mbedtls_calloc(1, in_buf_len); - if (ssl->in_buf == NULL) { - MBEDTLS_SSL_DEBUG_MSG(1, ("alloc(%" MBEDTLS_PRINTF_SIZET " bytes) failed", in_buf_len)); - ret = MBEDTLS_ERR_SSL_ALLOC_FAILED; - goto error; + if (used <= buf_len) { + *p++ = session->mfl_code; } - -#if defined(MBEDTLS_SSL_VARIABLE_BUFFER_LENGTH) - ssl->out_buf_len = out_buf_len; #endif - ssl->out_buf = mbedtls_calloc(1, out_buf_len); - if (ssl->out_buf == NULL) { - MBEDTLS_SSL_DEBUG_MSG(1, ("alloc(%" MBEDTLS_PRINTF_SIZET " bytes) failed", out_buf_len)); - ret = MBEDTLS_ERR_SSL_ALLOC_FAILED; - goto error; + +#if defined(MBEDTLS_SSL_ENCRYPT_THEN_MAC) + used += 1; + + if (used <= buf_len) { + *p++ = MBEDTLS_BYTE_0(session->encrypt_then_mac); } +#endif - mbedtls_ssl_reset_in_out_pointers(ssl); + return used; +} -#if defined(MBEDTLS_SSL_DTLS_SRTP) - memset(&ssl->dtls_srtp_info, 0, sizeof(ssl->dtls_srtp_info)); +MBEDTLS_CHECK_RETURN_CRITICAL +static int ssl_tls12_session_load(mbedtls_ssl_session *session, + const unsigned char *buf, + size_t len) +{ +#if defined(MBEDTLS_HAVE_TIME) + uint64_t start; #endif +#if defined(MBEDTLS_X509_CRT_PARSE_C) +#if defined(MBEDTLS_SSL_KEEP_PEER_CERTIFICATE) + size_t cert_len; +#endif /* MBEDTLS_SSL_KEEP_PEER_CERTIFICATE */ +#endif /* MBEDTLS_X509_CRT_PARSE_C */ - if ((ret = ssl_handshake_init(ssl)) != 0) { - goto error; - } + const unsigned char *p = buf; + const unsigned char * const end = buf + len; - return 0; + /* + * Time + */ +#if defined(MBEDTLS_HAVE_TIME) + if (8 > (size_t) (end - p)) { + return MBEDTLS_ERR_SSL_BAD_INPUT_DATA; + } -error: - mbedtls_free(ssl->in_buf); - mbedtls_free(ssl->out_buf); + start = MBEDTLS_GET_UINT64_BE(p, 0); + p += 8; - ssl->conf = NULL; + session->start = (time_t) start; +#endif /* MBEDTLS_HAVE_TIME */ -#if defined(MBEDTLS_SSL_VARIABLE_BUFFER_LENGTH) - ssl->in_buf_len = 0; - ssl->out_buf_len = 0; -#endif - ssl->in_buf = NULL; - ssl->out_buf = NULL; + /* + * Basic mandatory fields + */ + if (1 + 32 + 48 + 4 > (size_t) (end - p)) { + return MBEDTLS_ERR_SSL_BAD_INPUT_DATA; + } - ssl->in_hdr = NULL; - ssl->in_ctr = NULL; - ssl->in_len = NULL; - ssl->in_iv = NULL; - ssl->in_msg = NULL; + session->id_len = *p++; + memcpy(session->id, p, 32); + p += 32; - ssl->out_hdr = NULL; - ssl->out_ctr = NULL; - ssl->out_len = NULL; - ssl->out_iv = NULL; - ssl->out_msg = NULL; + memcpy(session->master, p, 48); + p += 48; - return ret; -} + session->verify_result = MBEDTLS_GET_UINT32_BE(p, 0); + p += 4; -/* - * Reset an initialized and used SSL context for re-use while retaining - * all application-set variables, function pointers and data. - * - * If partial is non-zero, keep data in the input buffer and client ID. - * (Use when a DTLS client reconnects from the same port.) - */ -int mbedtls_ssl_session_reset_int(mbedtls_ssl_context *ssl, int partial) -{ - int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED; -#if defined(MBEDTLS_SSL_VARIABLE_BUFFER_LENGTH) - size_t in_buf_len = ssl->in_buf_len; - size_t out_buf_len = ssl->out_buf_len; + /* Immediately clear invalid pointer values that have been read, in case + * we exit early before we replaced them with valid ones. */ +#if defined(MBEDTLS_X509_CRT_PARSE_C) +#if defined(MBEDTLS_SSL_KEEP_PEER_CERTIFICATE) + session->peer_cert = NULL; #else - size_t in_buf_len = MBEDTLS_SSL_IN_BUFFER_LEN; - size_t out_buf_len = MBEDTLS_SSL_OUT_BUFFER_LEN; -#endif - -#if !defined(MBEDTLS_SSL_DTLS_CLIENT_PORT_REUSE) || \ - !defined(MBEDTLS_SSL_SRV_C) - ((void) partial); -#endif + session->peer_cert_digest = NULL; +#endif /* !MBEDTLS_SSL_KEEP_PEER_CERTIFICATE */ +#endif /* MBEDTLS_X509_CRT_PARSE_C */ +#if defined(MBEDTLS_SSL_SESSION_TICKETS) && defined(MBEDTLS_SSL_CLI_C) + session->ticket = NULL; +#endif /* MBEDTLS_SSL_SESSION_TICKETS && MBEDTLS_SSL_CLI_C */ - ssl->state = MBEDTLS_SSL_HELLO_REQUEST; + /* + * Peer certificate + */ +#if defined(MBEDTLS_X509_CRT_PARSE_C) +#if defined(MBEDTLS_SSL_KEEP_PEER_CERTIFICATE) + /* Deserialize CRT from the end of the ticket. */ + if (3 > (size_t) (end - p)) { + return MBEDTLS_ERR_SSL_BAD_INPUT_DATA; + } - /* Cancel any possibly running timer */ - mbedtls_ssl_set_timer(ssl, 0); + cert_len = MBEDTLS_GET_UINT24_BE(p, 0); + p += 3; -#if defined(MBEDTLS_SSL_RENEGOTIATION) - ssl->renego_status = MBEDTLS_SSL_INITIAL_HANDSHAKE; - ssl->renego_records_seen = 0; + if (cert_len != 0) { + int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED; - ssl->verify_data_len = 0; - memset(ssl->own_verify_data, 0, MBEDTLS_SSL_VERIFY_DATA_MAX_LEN); - memset(ssl->peer_verify_data, 0, MBEDTLS_SSL_VERIFY_DATA_MAX_LEN); -#endif - ssl->secure_renegotiation = MBEDTLS_SSL_LEGACY_RENEGOTIATION; + if (cert_len > (size_t) (end - p)) { + return MBEDTLS_ERR_SSL_BAD_INPUT_DATA; + } - ssl->in_offt = NULL; - mbedtls_ssl_reset_in_out_pointers(ssl); + session->peer_cert = mbedtls_calloc(1, sizeof(mbedtls_x509_crt)); - ssl->in_msgtype = 0; - ssl->in_msglen = 0; -#if defined(MBEDTLS_SSL_PROTO_DTLS) - ssl->next_record_offset = 0; - ssl->in_epoch = 0; -#endif -#if defined(MBEDTLS_SSL_DTLS_ANTI_REPLAY) - mbedtls_ssl_dtls_replay_reset(ssl); -#endif + if (session->peer_cert == NULL) { + return MBEDTLS_ERR_SSL_ALLOC_FAILED; + } - ssl->in_hslen = 0; - ssl->nb_zero = 0; + mbedtls_x509_crt_init(session->peer_cert); - ssl->keep_current_message = 0; + if ((ret = mbedtls_x509_crt_parse_der(session->peer_cert, + p, cert_len)) != 0) { + mbedtls_x509_crt_free(session->peer_cert); + mbedtls_free(session->peer_cert); + session->peer_cert = NULL; + return ret; + } - ssl->out_msgtype = 0; - ssl->out_msglen = 0; - ssl->out_left = 0; -#if defined(MBEDTLS_SSL_CBC_RECORD_SPLITTING) - if (ssl->split_done != MBEDTLS_SSL_CBC_RECORD_SPLITTING_DISABLED) { - ssl->split_done = 0; + p += cert_len; + } +#else /* MBEDTLS_SSL_KEEP_PEER_CERTIFICATE */ + /* Deserialize CRT digest from the end of the ticket. */ + if (2 > (size_t) (end - p)) { + return MBEDTLS_ERR_SSL_BAD_INPUT_DATA; } -#endif - memset(ssl->cur_out_ctr, 0, sizeof(ssl->cur_out_ctr)); + session->peer_cert_digest_type = (mbedtls_md_type_t) *p++; + session->peer_cert_digest_len = (size_t) *p++; - ssl->transform_in = NULL; - ssl->transform_out = NULL; + if (session->peer_cert_digest_len != 0) { + const mbedtls_md_info_t *md_info = + mbedtls_md_info_from_type(session->peer_cert_digest_type); + if (md_info == NULL) { + return MBEDTLS_ERR_SSL_BAD_INPUT_DATA; + } + if (session->peer_cert_digest_len != mbedtls_md_get_size(md_info)) { + return MBEDTLS_ERR_SSL_BAD_INPUT_DATA; + } - ssl->session_in = NULL; - ssl->session_out = NULL; + if (session->peer_cert_digest_len > (size_t) (end - p)) { + return MBEDTLS_ERR_SSL_BAD_INPUT_DATA; + } - memset(ssl->out_buf, 0, out_buf_len); + session->peer_cert_digest = + mbedtls_calloc(1, session->peer_cert_digest_len); + if (session->peer_cert_digest == NULL) { + return MBEDTLS_ERR_SSL_ALLOC_FAILED; + } - int clear_in_buf = 1; -#if defined(MBEDTLS_SSL_DTLS_CLIENT_PORT_REUSE) && defined(MBEDTLS_SSL_SRV_C) - if (partial != 0) { - clear_in_buf = 0; - } -#endif /* MBEDTLS_SSL_DTLS_CLIENT_PORT_REUSE && MBEDTLS_SSL_SRV_C */ - if (clear_in_buf) { - ssl->in_left = 0; - memset(ssl->in_buf, 0, in_buf_len); + memcpy(session->peer_cert_digest, p, + session->peer_cert_digest_len); + p += session->peer_cert_digest_len; } +#endif /* MBEDTLS_SSL_KEEP_PEER_CERTIFICATE */ +#endif /* MBEDTLS_X509_CRT_PARSE_C */ -#if defined(MBEDTLS_SSL_HW_RECORD_ACCEL) - if (mbedtls_ssl_hw_record_reset != NULL) { - MBEDTLS_SSL_DEBUG_MSG(2, ("going for mbedtls_ssl_hw_record_reset()")); - if ((ret = mbedtls_ssl_hw_record_reset(ssl)) != 0) { - MBEDTLS_SSL_DEBUG_RET(1, "mbedtls_ssl_hw_record_reset", ret); - return MBEDTLS_ERR_SSL_HW_ACCEL_FAILED; + /* + * Session ticket and associated data + */ +#if defined(MBEDTLS_SSL_SESSION_TICKETS) +#if defined(MBEDTLS_SSL_CLI_C) + if (session->endpoint == MBEDTLS_SSL_IS_CLIENT) { + if (3 > (size_t) (end - p)) { + return MBEDTLS_ERR_SSL_BAD_INPUT_DATA; } - } -#endif - if (ssl->transform) { - mbedtls_ssl_transform_free(ssl->transform); - mbedtls_free(ssl->transform); - ssl->transform = NULL; + session->ticket_len = MBEDTLS_GET_UINT24_BE(p, 0); + p += 3; + + if (session->ticket_len != 0) { + if (session->ticket_len > (size_t) (end - p)) { + return MBEDTLS_ERR_SSL_BAD_INPUT_DATA; + } + + session->ticket = mbedtls_calloc(1, session->ticket_len); + if (session->ticket == NULL) { + return MBEDTLS_ERR_SSL_ALLOC_FAILED; + } + + memcpy(session->ticket, p, session->ticket_len); + p += session->ticket_len; + } + + if (4 > (size_t) (end - p)) { + return MBEDTLS_ERR_SSL_BAD_INPUT_DATA; + } + + session->ticket_lifetime = MBEDTLS_GET_UINT32_BE(p, 0); + p += 4; + } +#endif /* MBEDTLS_SSL_CLI_C */ +#if defined(MBEDTLS_HAVE_TIME) && defined(MBEDTLS_SSL_SRV_C) + if (session->endpoint == MBEDTLS_SSL_IS_SERVER) { + if (8 > (size_t) (end - p)) { + return MBEDTLS_ERR_SSL_BAD_INPUT_DATA; + } + session->ticket_creation_time = MBEDTLS_GET_UINT64_BE(p, 0); + p += 8; } +#endif /* MBEDTLS_HAVE_TIME && MBEDTLS_SSL_SRV_C */ +#endif /* MBEDTLS_SSL_SESSION_TICKETS */ - if (ssl->session) { - mbedtls_ssl_session_free(ssl->session); - mbedtls_free(ssl->session); - ssl->session = NULL; + /* + * Misc extension-related info + */ +#if defined(MBEDTLS_SSL_MAX_FRAGMENT_LENGTH) + if (1 > (size_t) (end - p)) { + return MBEDTLS_ERR_SSL_BAD_INPUT_DATA; } -#if defined(MBEDTLS_SSL_ALPN) - ssl->alpn_chosen = NULL; + session->mfl_code = *p++; #endif -#if defined(MBEDTLS_SSL_DTLS_HELLO_VERIFY) && defined(MBEDTLS_SSL_SRV_C) - int free_cli_id = 1; -#if defined(MBEDTLS_SSL_DTLS_CLIENT_PORT_REUSE) - if (partial != 0) { - free_cli_id = 0; - } -#endif - if (free_cli_id) { - mbedtls_free(ssl->cli_id); - ssl->cli_id = NULL; - ssl->cli_id_len = 0; +#if defined(MBEDTLS_SSL_ENCRYPT_THEN_MAC) + if (1 > (size_t) (end - p)) { + return MBEDTLS_ERR_SSL_BAD_INPUT_DATA; } + + session->encrypt_then_mac = *p++; #endif - if ((ret = ssl_handshake_init(ssl)) != 0) { - return ret; + /* Done, should have consumed entire buffer */ + if (p != end) { + return MBEDTLS_ERR_SSL_BAD_INPUT_DATA; } return 0; } -/* - * Reset an initialized and used SSL context for re-use while retaining - * all application-set variables, function pointers and data. - */ -int mbedtls_ssl_session_reset(mbedtls_ssl_context *ssl) -{ - return mbedtls_ssl_session_reset_int(ssl, 0); -} +#endif /* MBEDTLS_SSL_PROTO_TLS1_2 */ -/* - * SSL set accessors +#if defined(MBEDTLS_SSL_PROTO_TLS1_3) +/* Serialization of TLS 1.3 sessions: + * + * For more detail, see the description of ssl_session_save(). */ -void mbedtls_ssl_conf_endpoint(mbedtls_ssl_config *conf, int endpoint) -{ - conf->endpoint = endpoint; -} - -void mbedtls_ssl_conf_transport(mbedtls_ssl_config *conf, int transport) -{ - conf->transport = transport; -} - -#if defined(MBEDTLS_SSL_DTLS_ANTI_REPLAY) -void mbedtls_ssl_conf_dtls_anti_replay(mbedtls_ssl_config *conf, char mode) +#if defined(MBEDTLS_SSL_SESSION_TICKETS) +MBEDTLS_CHECK_RETURN_CRITICAL +static int ssl_tls13_session_save(const mbedtls_ssl_session *session, + unsigned char *buf, + size_t buf_len, + size_t *olen) { - conf->anti_replay = mode; -} + unsigned char *p = buf; +#if defined(MBEDTLS_SSL_CLI_C) && \ + defined(MBEDTLS_SSL_SERVER_NAME_INDICATION) + size_t hostname_len = (session->hostname == NULL) ? + 0 : strlen(session->hostname) + 1; #endif -#if defined(MBEDTLS_SSL_DTLS_BADMAC_LIMIT) -void mbedtls_ssl_conf_dtls_badmac_limit(mbedtls_ssl_config *conf, unsigned limit) -{ - conf->badmac_limit = limit; -} +#if defined(MBEDTLS_SSL_SRV_C) && \ + defined(MBEDTLS_SSL_EARLY_DATA) && defined(MBEDTLS_SSL_ALPN) + const size_t alpn_len = (session->ticket_alpn == NULL) ? + 0 : strlen(session->ticket_alpn) + 1; #endif + size_t needed = 4 /* ticket_age_add */ + + 1 /* ticket_flags */ + + 1; /* resumption_key length */ -#if defined(MBEDTLS_SSL_PROTO_DTLS) + *olen = 0; -void mbedtls_ssl_set_datagram_packing(mbedtls_ssl_context *ssl, - unsigned allow_packing) -{ - ssl->disable_datagram_packing = !allow_packing; -} + if (session->resumption_key_len > MBEDTLS_SSL_TLS1_3_TICKET_RESUMPTION_KEY_LEN) { + return MBEDTLS_ERR_SSL_BAD_INPUT_DATA; + } + needed += session->resumption_key_len; /* resumption_key */ -void mbedtls_ssl_conf_handshake_timeout(mbedtls_ssl_config *conf, - uint32_t min, uint32_t max) -{ - conf->hs_timeout_min = min; - conf->hs_timeout_max = max; -} +#if defined(MBEDTLS_SSL_EARLY_DATA) + needed += 4; /* max_early_data_size */ #endif +#if defined(MBEDTLS_SSL_RECORD_SIZE_LIMIT) + needed += 2; /* record_size_limit */ +#endif /* MBEDTLS_SSL_RECORD_SIZE_LIMIT */ -void mbedtls_ssl_conf_authmode(mbedtls_ssl_config *conf, int authmode) -{ - conf->authmode = authmode; -} +#if defined(MBEDTLS_HAVE_TIME) + needed += 8; /* ticket_creation_time or ticket_reception_time */ +#endif -#if defined(MBEDTLS_X509_CRT_PARSE_C) -void mbedtls_ssl_conf_verify(mbedtls_ssl_config *conf, - int (*f_vrfy)(void *, mbedtls_x509_crt *, int, uint32_t *), - void *p_vrfy) -{ - conf->f_vrfy = f_vrfy; - conf->p_vrfy = p_vrfy; -} -#endif /* MBEDTLS_X509_CRT_PARSE_C */ +#if defined(MBEDTLS_SSL_SRV_C) + if (session->endpoint == MBEDTLS_SSL_IS_SERVER) { +#if defined(MBEDTLS_SSL_EARLY_DATA) && defined(MBEDTLS_SSL_ALPN) + needed += 2 /* alpn_len */ + + alpn_len; /* alpn */ +#endif + } +#endif /* MBEDTLS_SSL_SRV_C */ -void mbedtls_ssl_conf_rng(mbedtls_ssl_config *conf, - int (*f_rng)(void *, unsigned char *, size_t), - void *p_rng) -{ - conf->f_rng = f_rng; - conf->p_rng = p_rng; -} +#if defined(MBEDTLS_SSL_CLI_C) + if (session->endpoint == MBEDTLS_SSL_IS_CLIENT) { +#if defined(MBEDTLS_SSL_SERVER_NAME_INDICATION) + needed += 2 /* hostname_len */ + + hostname_len; /* hostname */ +#endif -void mbedtls_ssl_conf_dbg(mbedtls_ssl_config *conf, - void (*f_dbg)(void *, int, const char *, int, const char *), - void *p_dbg) -{ - conf->f_dbg = f_dbg; - conf->p_dbg = p_dbg; -} + needed += 4 /* ticket_lifetime */ + + 2; /* ticket_len */ -void mbedtls_ssl_set_bio(mbedtls_ssl_context *ssl, - void *p_bio, - mbedtls_ssl_send_t *f_send, - mbedtls_ssl_recv_t *f_recv, - mbedtls_ssl_recv_timeout_t *f_recv_timeout) -{ - ssl->p_bio = p_bio; - ssl->f_send = f_send; - ssl->f_recv = f_recv; - ssl->f_recv_timeout = f_recv_timeout; -} + /* Check size_t overflow */ + if (session->ticket_len > SIZE_MAX - needed) { + return MBEDTLS_ERR_SSL_BAD_INPUT_DATA; + } -#if defined(MBEDTLS_SSL_PROTO_DTLS) -void mbedtls_ssl_set_mtu(mbedtls_ssl_context *ssl, uint16_t mtu) -{ - ssl->mtu = mtu; -} -#endif + needed += session->ticket_len; /* ticket */ + } +#endif /* MBEDTLS_SSL_CLI_C */ -void mbedtls_ssl_conf_read_timeout(mbedtls_ssl_config *conf, uint32_t timeout) -{ - conf->read_timeout = timeout; -} + *olen = needed; + if (needed > buf_len) { + return MBEDTLS_ERR_SSL_BUFFER_TOO_SMALL; + } -void mbedtls_ssl_set_timer_cb(mbedtls_ssl_context *ssl, - void *p_timer, - mbedtls_ssl_set_timer_t *f_set_timer, - mbedtls_ssl_get_timer_t *f_get_timer) -{ - ssl->p_timer = p_timer; - ssl->f_set_timer = f_set_timer; - ssl->f_get_timer = f_get_timer; + MBEDTLS_PUT_UINT32_BE(session->ticket_age_add, p, 0); + p[4] = session->ticket_flags; - /* Make sure we start with no timer running */ - mbedtls_ssl_set_timer(ssl, 0); -} + /* save resumption_key */ + p[5] = session->resumption_key_len; + p += 6; + memcpy(p, session->resumption_key, session->resumption_key_len); + p += session->resumption_key_len; + +#if defined(MBEDTLS_SSL_EARLY_DATA) + MBEDTLS_PUT_UINT32_BE(session->max_early_data_size, p, 0); + p += 4; +#endif +#if defined(MBEDTLS_SSL_RECORD_SIZE_LIMIT) + MBEDTLS_PUT_UINT16_BE(session->record_size_limit, p, 0); + p += 2; +#endif /* MBEDTLS_SSL_RECORD_SIZE_LIMIT */ #if defined(MBEDTLS_SSL_SRV_C) -void mbedtls_ssl_conf_session_cache(mbedtls_ssl_config *conf, - void *p_cache, - int (*f_get_cache)(void *, mbedtls_ssl_session *), - int (*f_set_cache)(void *, const mbedtls_ssl_session *)) -{ - conf->p_cache = p_cache; - conf->f_get_cache = f_get_cache; - conf->f_set_cache = f_set_cache; -} -#endif /* MBEDTLS_SSL_SRV_C */ + if (session->endpoint == MBEDTLS_SSL_IS_SERVER) { +#if defined(MBEDTLS_HAVE_TIME) + MBEDTLS_PUT_UINT64_BE((uint64_t) session->ticket_creation_time, p, 0); + p += 8; +#endif /* MBEDTLS_HAVE_TIME */ -#if defined(MBEDTLS_SSL_CLI_C) -int mbedtls_ssl_set_session(mbedtls_ssl_context *ssl, const mbedtls_ssl_session *session) -{ - int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED; +#if defined(MBEDTLS_SSL_EARLY_DATA) && defined(MBEDTLS_SSL_ALPN) + MBEDTLS_PUT_UINT16_BE(alpn_len, p, 0); + p += 2; - if (ssl == NULL || - session == NULL || - ssl->session_negotiate == NULL || - ssl->conf->endpoint != MBEDTLS_SSL_IS_CLIENT) { - return MBEDTLS_ERR_SSL_BAD_INPUT_DATA; + if (alpn_len > 0) { + /* save chosen alpn */ + memcpy(p, session->ticket_alpn, alpn_len); + p += alpn_len; + } +#endif /* MBEDTLS_SSL_EARLY_DATA && MBEDTLS_SSL_ALPN */ } +#endif /* MBEDTLS_SSL_SRV_C */ - if ((ret = mbedtls_ssl_session_copy(ssl->session_negotiate, - session)) != 0) { - return ret; - } +#if defined(MBEDTLS_SSL_CLI_C) + if (session->endpoint == MBEDTLS_SSL_IS_CLIENT) { +#if defined(MBEDTLS_SSL_SERVER_NAME_INDICATION) + MBEDTLS_PUT_UINT16_BE(hostname_len, p, 0); + p += 2; + if (hostname_len > 0) { + /* save host name */ + memcpy(p, session->hostname, hostname_len); + p += hostname_len; + } +#endif /* MBEDTLS_SSL_SERVER_NAME_INDICATION */ - ssl->handshake->resume = 1; +#if defined(MBEDTLS_HAVE_TIME) + MBEDTLS_PUT_UINT64_BE((uint64_t) session->ticket_reception_time, p, 0); + p += 8; +#endif + MBEDTLS_PUT_UINT32_BE(session->ticket_lifetime, p, 0); + p += 4; + + MBEDTLS_PUT_UINT16_BE(session->ticket_len, p, 0); + p += 2; + if (session->ticket != NULL && session->ticket_len > 0) { + memcpy(p, session->ticket, session->ticket_len); + p += session->ticket_len; + } + } +#endif /* MBEDTLS_SSL_CLI_C */ return 0; } -#endif /* MBEDTLS_SSL_CLI_C */ -void mbedtls_ssl_conf_ciphersuites(mbedtls_ssl_config *conf, - const int *ciphersuites) +MBEDTLS_CHECK_RETURN_CRITICAL +static int ssl_tls13_session_load(mbedtls_ssl_session *session, + const unsigned char *buf, + size_t len) { - conf->ciphersuite_list[MBEDTLS_SSL_MINOR_VERSION_0] = ciphersuites; - conf->ciphersuite_list[MBEDTLS_SSL_MINOR_VERSION_1] = ciphersuites; - conf->ciphersuite_list[MBEDTLS_SSL_MINOR_VERSION_2] = ciphersuites; - conf->ciphersuite_list[MBEDTLS_SSL_MINOR_VERSION_3] = ciphersuites; -} + const unsigned char *p = buf; + const unsigned char *end = buf + len; -void mbedtls_ssl_conf_ciphersuites_for_version(mbedtls_ssl_config *conf, - const int *ciphersuites, - int major, int minor) -{ - if (major != MBEDTLS_SSL_MAJOR_VERSION_3) { - return; + if (end - p < 6) { + return MBEDTLS_ERR_SSL_BAD_INPUT_DATA; } + session->ticket_age_add = MBEDTLS_GET_UINT32_BE(p, 0); + session->ticket_flags = p[4]; - if (minor < MBEDTLS_SSL_MINOR_VERSION_0 || minor > MBEDTLS_SSL_MINOR_VERSION_3) { - return; + /* load resumption_key */ + session->resumption_key_len = p[5]; + p += 6; + + if (end - p < session->resumption_key_len) { + return MBEDTLS_ERR_SSL_BAD_INPUT_DATA; } - conf->ciphersuite_list[minor] = ciphersuites; -} + if (sizeof(session->resumption_key) < session->resumption_key_len) { + return MBEDTLS_ERR_SSL_BAD_INPUT_DATA; + } + memcpy(session->resumption_key, p, session->resumption_key_len); + p += session->resumption_key_len; -#if defined(MBEDTLS_X509_CRT_PARSE_C) -void mbedtls_ssl_conf_cert_profile(mbedtls_ssl_config *conf, - const mbedtls_x509_crt_profile *profile) -{ - conf->cert_profile = profile; -} +#if defined(MBEDTLS_SSL_EARLY_DATA) + if (end - p < 4) { + return MBEDTLS_ERR_SSL_BAD_INPUT_DATA; + } + session->max_early_data_size = MBEDTLS_GET_UINT32_BE(p, 0); + p += 4; +#endif +#if defined(MBEDTLS_SSL_RECORD_SIZE_LIMIT) + if (end - p < 2) { + return MBEDTLS_ERR_SSL_BAD_INPUT_DATA; + } + session->record_size_limit = MBEDTLS_GET_UINT16_BE(p, 0); + p += 2; +#endif /* MBEDTLS_SSL_RECORD_SIZE_LIMIT */ -/* Append a new keycert entry to a (possibly empty) list */ -MBEDTLS_CHECK_RETURN_CRITICAL -static int ssl_append_key_cert(mbedtls_ssl_key_cert **head, - mbedtls_x509_crt *cert, - mbedtls_pk_context *key) -{ - mbedtls_ssl_key_cert *new_cert; +#if defined(MBEDTLS_SSL_SRV_C) + if (session->endpoint == MBEDTLS_SSL_IS_SERVER) { +#if defined(MBEDTLS_HAVE_TIME) + if (end - p < 8) { + return MBEDTLS_ERR_SSL_BAD_INPUT_DATA; + } + session->ticket_creation_time = MBEDTLS_GET_UINT64_BE(p, 0); + p += 8; +#endif /* MBEDTLS_HAVE_TIME */ - new_cert = mbedtls_calloc(1, sizeof(mbedtls_ssl_key_cert)); - if (new_cert == NULL) { - return MBEDTLS_ERR_SSL_ALLOC_FAILED; +#if defined(MBEDTLS_SSL_EARLY_DATA) && defined(MBEDTLS_SSL_ALPN) + size_t alpn_len; + + if (end - p < 2) { + return MBEDTLS_ERR_SSL_BAD_INPUT_DATA; + } + + alpn_len = MBEDTLS_GET_UINT16_BE(p, 0); + p += 2; + + if (end - p < (long int) alpn_len) { + return MBEDTLS_ERR_SSL_BAD_INPUT_DATA; + } + + if (alpn_len > 0) { + int ret = mbedtls_ssl_session_set_ticket_alpn(session, (char *) p); + if (ret != 0) { + return ret; + } + p += alpn_len; + } +#endif /* MBEDTLS_SSL_EARLY_DATA && MBEDTLS_SSL_ALPN */ } +#endif /* MBEDTLS_SSL_SRV_C */ - new_cert->cert = cert; - new_cert->key = key; - new_cert->next = NULL; +#if defined(MBEDTLS_SSL_CLI_C) + if (session->endpoint == MBEDTLS_SSL_IS_CLIENT) { +#if defined(MBEDTLS_SSL_SERVER_NAME_INDICATION) + size_t hostname_len; + /* load host name */ + if (end - p < 2) { + return MBEDTLS_ERR_SSL_BAD_INPUT_DATA; + } + hostname_len = MBEDTLS_GET_UINT16_BE(p, 0); + p += 2; - /* Update head is the list was null, else add to the end */ - if (*head == NULL) { - *head = new_cert; - } else { - mbedtls_ssl_key_cert *cur = *head; - while (cur->next != NULL) { - cur = cur->next; + if (end - p < (long int) hostname_len) { + return MBEDTLS_ERR_SSL_BAD_INPUT_DATA; + } + if (hostname_len > 0) { + session->hostname = mbedtls_calloc(1, hostname_len); + if (session->hostname == NULL) { + return MBEDTLS_ERR_SSL_ALLOC_FAILED; + } + memcpy(session->hostname, p, hostname_len); + p += hostname_len; + } +#endif /* MBEDTLS_SSL_SERVER_NAME_INDICATION */ + +#if defined(MBEDTLS_HAVE_TIME) + if (end - p < 8) { + return MBEDTLS_ERR_SSL_BAD_INPUT_DATA; + } + session->ticket_reception_time = MBEDTLS_GET_UINT64_BE(p, 0); + p += 8; +#endif + if (end - p < 4) { + return MBEDTLS_ERR_SSL_BAD_INPUT_DATA; + } + session->ticket_lifetime = MBEDTLS_GET_UINT32_BE(p, 0); + p += 4; + + if (end - p < 2) { + return MBEDTLS_ERR_SSL_BAD_INPUT_DATA; + } + session->ticket_len = MBEDTLS_GET_UINT16_BE(p, 0); + p += 2; + + if (end - p < (long int) session->ticket_len) { + return MBEDTLS_ERR_SSL_BAD_INPUT_DATA; + } + if (session->ticket_len > 0) { + session->ticket = mbedtls_calloc(1, session->ticket_len); + if (session->ticket == NULL) { + return MBEDTLS_ERR_SSL_ALLOC_FAILED; + } + memcpy(session->ticket, p, session->ticket_len); + p += session->ticket_len; } - cur->next = new_cert; } +#endif /* MBEDTLS_SSL_CLI_C */ return 0; -} -int mbedtls_ssl_conf_own_cert(mbedtls_ssl_config *conf, - mbedtls_x509_crt *own_cert, - mbedtls_pk_context *pk_key) -{ - return ssl_append_key_cert(&conf->key_cert, own_cert, pk_key); } - -void mbedtls_ssl_conf_ca_chain(mbedtls_ssl_config *conf, - mbedtls_x509_crt *ca_chain, - mbedtls_x509_crl *ca_crl) -{ - conf->ca_chain = ca_chain; - conf->ca_crl = ca_crl; - -#if defined(MBEDTLS_X509_TRUSTED_CERTIFICATE_CALLBACK) - /* mbedtls_ssl_conf_ca_chain() and mbedtls_ssl_conf_ca_cb() - * cannot be used together. */ - conf->f_ca_cb = NULL; - conf->p_ca_cb = NULL; -#endif /* MBEDTLS_X509_TRUSTED_CERTIFICATE_CALLBACK */ +#else /* MBEDTLS_SSL_SESSION_TICKETS */ +MBEDTLS_CHECK_RETURN_CRITICAL +static int ssl_tls13_session_save(const mbedtls_ssl_session *session, + unsigned char *buf, + size_t buf_len, + size_t *olen) +{ + ((void) session); + ((void) buf); + ((void) buf_len); + *olen = 0; + return MBEDTLS_ERR_SSL_FEATURE_UNAVAILABLE; } -#if defined(MBEDTLS_X509_TRUSTED_CERTIFICATE_CALLBACK) -void mbedtls_ssl_conf_ca_cb(mbedtls_ssl_config *conf, - mbedtls_x509_crt_ca_cb_t f_ca_cb, - void *p_ca_cb) +static int ssl_tls13_session_load(const mbedtls_ssl_session *session, + unsigned char *buf, + size_t buf_len) { - conf->f_ca_cb = f_ca_cb; - conf->p_ca_cb = p_ca_cb; - - /* mbedtls_ssl_conf_ca_chain() and mbedtls_ssl_conf_ca_cb() - * cannot be used together. */ - conf->ca_chain = NULL; - conf->ca_crl = NULL; + ((void) session); + ((void) buf); + ((void) buf_len); + return MBEDTLS_ERR_SSL_FEATURE_UNAVAILABLE; } -#endif /* MBEDTLS_X509_TRUSTED_CERTIFICATE_CALLBACK */ -#endif /* MBEDTLS_X509_CRT_PARSE_C */ +#endif /* !MBEDTLS_SSL_SESSION_TICKETS */ +#endif /* MBEDTLS_SSL_PROTO_TLS1_3 */ -#if defined(MBEDTLS_SSL_SERVER_NAME_INDICATION) -int mbedtls_ssl_set_hs_own_cert(mbedtls_ssl_context *ssl, - mbedtls_x509_crt *own_cert, - mbedtls_pk_context *pk_key) -{ - return ssl_append_key_cert(&ssl->handshake->sni_key_cert, - own_cert, pk_key); -} +/* + * Define ticket header determining Mbed TLS version + * and structure of the ticket. + */ -void mbedtls_ssl_set_hs_ca_chain(mbedtls_ssl_context *ssl, - mbedtls_x509_crt *ca_chain, - mbedtls_x509_crl *ca_crl) -{ - ssl->handshake->sni_ca_chain = ca_chain; - ssl->handshake->sni_ca_crl = ca_crl; -} +/* + * Define bitflag determining compile-time settings influencing + * structure of serialized SSL sessions. + */ -void mbedtls_ssl_set_hs_authmode(mbedtls_ssl_context *ssl, - int authmode) -{ - ssl->handshake->sni_authmode = authmode; -} -#endif /* MBEDTLS_SSL_SERVER_NAME_INDICATION */ +#if defined(MBEDTLS_HAVE_TIME) +#define SSL_SERIALIZED_SESSION_CONFIG_TIME 1 +#else +#define SSL_SERIALIZED_SESSION_CONFIG_TIME 0 +#endif /* MBEDTLS_HAVE_TIME */ #if defined(MBEDTLS_X509_CRT_PARSE_C) -void mbedtls_ssl_set_verify(mbedtls_ssl_context *ssl, - int (*f_vrfy)(void *, mbedtls_x509_crt *, int, uint32_t *), - void *p_vrfy) -{ - ssl->f_vrfy = f_vrfy; - ssl->p_vrfy = p_vrfy; -} -#endif +#define SSL_SERIALIZED_SESSION_CONFIG_CRT 1 +#else +#define SSL_SERIALIZED_SESSION_CONFIG_CRT 0 +#endif /* MBEDTLS_X509_CRT_PARSE_C */ -#if defined(MBEDTLS_KEY_EXCHANGE_ECJPAKE_ENABLED) -/* - * Set EC J-PAKE password for current handshake - */ -int mbedtls_ssl_set_hs_ecjpake_password(mbedtls_ssl_context *ssl, - const unsigned char *pw, - size_t pw_len) -{ - mbedtls_ecjpake_role role; +#if defined(MBEDTLS_SSL_KEEP_PEER_CERTIFICATE) +#define SSL_SERIALIZED_SESSION_CONFIG_KEEP_PEER_CRT 1 +#else +#define SSL_SERIALIZED_SESSION_CONFIG_KEEP_PEER_CRT 0 +#endif /* MBEDTLS_SSL_SESSION_TICKETS */ - if (ssl->handshake == NULL || ssl->conf == NULL) { - return MBEDTLS_ERR_SSL_BAD_INPUT_DATA; - } +#if defined(MBEDTLS_SSL_CLI_C) && defined(MBEDTLS_SSL_SESSION_TICKETS) +#define SSL_SERIALIZED_SESSION_CONFIG_CLIENT_TICKET 1 +#else +#define SSL_SERIALIZED_SESSION_CONFIG_CLIENT_TICKET 0 +#endif /* MBEDTLS_SSL_CLI_C && MBEDTLS_SSL_SESSION_TICKETS */ - if (ssl->conf->endpoint == MBEDTLS_SSL_IS_SERVER) { - role = MBEDTLS_ECJPAKE_SERVER; - } else { - role = MBEDTLS_ECJPAKE_CLIENT; - } +#if defined(MBEDTLS_SSL_MAX_FRAGMENT_LENGTH) +#define SSL_SERIALIZED_SESSION_CONFIG_MFL 1 +#else +#define SSL_SERIALIZED_SESSION_CONFIG_MFL 0 +#endif /* MBEDTLS_SSL_MAX_FRAGMENT_LENGTH */ - return mbedtls_ecjpake_setup(&ssl->handshake->ecjpake_ctx, - role, - MBEDTLS_MD_SHA256, - MBEDTLS_ECP_DP_SECP256R1, - pw, pw_len); -} -#endif /* MBEDTLS_KEY_EXCHANGE_ECJPAKE_ENABLED */ +#if defined(MBEDTLS_SSL_ENCRYPT_THEN_MAC) +#define SSL_SERIALIZED_SESSION_CONFIG_ETM 1 +#else +#define SSL_SERIALIZED_SESSION_CONFIG_ETM 0 +#endif /* MBEDTLS_SSL_ENCRYPT_THEN_MAC */ -#if defined(MBEDTLS_KEY_EXCHANGE_SOME_PSK_ENABLED) +#if defined(MBEDTLS_SSL_SESSION_TICKETS) +#define SSL_SERIALIZED_SESSION_CONFIG_TICKET 1 +#else +#define SSL_SERIALIZED_SESSION_CONFIG_TICKET 0 +#endif /* MBEDTLS_SSL_SESSION_TICKETS */ -static void ssl_conf_remove_psk(mbedtls_ssl_config *conf) -{ - /* Remove reference to existing PSK, if any. */ -#if defined(MBEDTLS_USE_PSA_CRYPTO) - if (!mbedtls_svc_key_id_is_null(conf->psk_opaque)) { - /* The maintenance of the PSK key slot is the - * user's responsibility. */ - conf->psk_opaque = MBEDTLS_SVC_KEY_ID_INIT; - } - /* This and the following branch should never - * be taken simultaneously as we maintain the - * invariant that raw and opaque PSKs are never - * configured simultaneously. As a safeguard, - * though, `else` is omitted here. */ -#endif /* MBEDTLS_USE_PSA_CRYPTO */ - if (conf->psk != NULL) { - mbedtls_platform_zeroize(conf->psk, conf->psk_len); +#if defined(MBEDTLS_SSL_SERVER_NAME_INDICATION) +#define SSL_SERIALIZED_SESSION_CONFIG_SNI 1 +#else +#define SSL_SERIALIZED_SESSION_CONFIG_SNI 0 +#endif /* MBEDTLS_SSL_SERVER_NAME_INDICATION */ - mbedtls_free(conf->psk); - conf->psk = NULL; - conf->psk_len = 0; - } +#if defined(MBEDTLS_SSL_EARLY_DATA) +#define SSL_SERIALIZED_SESSION_CONFIG_EARLY_DATA 1 +#else +#define SSL_SERIALIZED_SESSION_CONFIG_EARLY_DATA 0 +#endif /* MBEDTLS_SSL_EARLY_DATA */ - /* Remove reference to PSK identity, if any. */ - if (conf->psk_identity != NULL) { - mbedtls_free(conf->psk_identity); - conf->psk_identity = NULL; - conf->psk_identity_len = 0; - } -} +#if defined(MBEDTLS_SSL_RECORD_SIZE_LIMIT) +#define SSL_SERIALIZED_SESSION_CONFIG_RECORD_SIZE 1 +#else +#define SSL_SERIALIZED_SESSION_CONFIG_RECORD_SIZE 0 +#endif /* MBEDTLS_SSL_RECORD_SIZE_LIMIT */ -/* This function assumes that PSK identity in the SSL config is unset. - * It checks that the provided identity is well-formed and attempts - * to make a copy of it in the SSL config. - * On failure, the PSK identity in the config remains unset. */ -MBEDTLS_CHECK_RETURN_CRITICAL -static int ssl_conf_set_psk_identity(mbedtls_ssl_config *conf, - unsigned char const *psk_identity, - size_t psk_identity_len) -{ - /* Identity len will be encoded on two bytes */ - if (psk_identity == NULL || - (psk_identity_len >> 16) != 0 || - psk_identity_len > MBEDTLS_SSL_OUT_CONTENT_LEN) { - return MBEDTLS_ERR_SSL_BAD_INPUT_DATA; - } +#if defined(MBEDTLS_SSL_ALPN) && defined(MBEDTLS_SSL_SRV_C) && \ + defined(MBEDTLS_SSL_EARLY_DATA) +#define SSL_SERIALIZED_SESSION_CONFIG_ALPN 1 +#else +#define SSL_SERIALIZED_SESSION_CONFIG_ALPN 0 +#endif /* MBEDTLS_SSL_ALPN */ - conf->psk_identity = mbedtls_calloc(1, psk_identity_len); - if (conf->psk_identity == NULL) { - return MBEDTLS_ERR_SSL_ALLOC_FAILED; - } +#define SSL_SERIALIZED_SESSION_CONFIG_TIME_BIT 0 +#define SSL_SERIALIZED_SESSION_CONFIG_CRT_BIT 1 +#define SSL_SERIALIZED_SESSION_CONFIG_CLIENT_TICKET_BIT 2 +#define SSL_SERIALIZED_SESSION_CONFIG_MFL_BIT 3 +#define SSL_SERIALIZED_SESSION_CONFIG_ETM_BIT 4 +#define SSL_SERIALIZED_SESSION_CONFIG_TICKET_BIT 5 +#define SSL_SERIALIZED_SESSION_CONFIG_KEEP_PEER_CRT_BIT 6 +#define SSL_SERIALIZED_SESSION_CONFIG_SNI_BIT 7 +#define SSL_SERIALIZED_SESSION_CONFIG_EARLY_DATA_BIT 8 +#define SSL_SERIALIZED_SESSION_CONFIG_RECORD_SIZE_BIT 9 +#define SSL_SERIALIZED_SESSION_CONFIG_ALPN_BIT 10 - conf->psk_identity_len = psk_identity_len; - memcpy(conf->psk_identity, psk_identity, conf->psk_identity_len); +#define SSL_SERIALIZED_SESSION_CONFIG_BITFLAG \ + ((uint16_t) ( \ + (SSL_SERIALIZED_SESSION_CONFIG_TIME << SSL_SERIALIZED_SESSION_CONFIG_TIME_BIT) | \ + (SSL_SERIALIZED_SESSION_CONFIG_CRT << SSL_SERIALIZED_SESSION_CONFIG_CRT_BIT) | \ + (SSL_SERIALIZED_SESSION_CONFIG_CLIENT_TICKET << \ + SSL_SERIALIZED_SESSION_CONFIG_CLIENT_TICKET_BIT) | \ + (SSL_SERIALIZED_SESSION_CONFIG_MFL << SSL_SERIALIZED_SESSION_CONFIG_MFL_BIT) | \ + (SSL_SERIALIZED_SESSION_CONFIG_ETM << SSL_SERIALIZED_SESSION_CONFIG_ETM_BIT) | \ + (SSL_SERIALIZED_SESSION_CONFIG_TICKET << SSL_SERIALIZED_SESSION_CONFIG_TICKET_BIT) | \ + (SSL_SERIALIZED_SESSION_CONFIG_KEEP_PEER_CRT << \ + SSL_SERIALIZED_SESSION_CONFIG_KEEP_PEER_CRT_BIT) | \ + (SSL_SERIALIZED_SESSION_CONFIG_SNI << SSL_SERIALIZED_SESSION_CONFIG_SNI_BIT) | \ + (SSL_SERIALIZED_SESSION_CONFIG_EARLY_DATA << \ + SSL_SERIALIZED_SESSION_CONFIG_EARLY_DATA_BIT) | \ + (SSL_SERIALIZED_SESSION_CONFIG_RECORD_SIZE << \ + SSL_SERIALIZED_SESSION_CONFIG_RECORD_SIZE_BIT) | \ + (SSL_SERIALIZED_SESSION_CONFIG_ALPN << \ + SSL_SERIALIZED_SESSION_CONFIG_ALPN_BIT))) + +static const unsigned char ssl_serialized_session_header[] = { + MBEDTLS_VERSION_MAJOR, + MBEDTLS_VERSION_MINOR, + MBEDTLS_VERSION_PATCH, + MBEDTLS_BYTE_1(SSL_SERIALIZED_SESSION_CONFIG_BITFLAG), + MBEDTLS_BYTE_0(SSL_SERIALIZED_SESSION_CONFIG_BITFLAG), +}; - return 0; -} +/* + * Serialize a session in the following format: + * (in the presentation language of TLS, RFC 8446 section 3) + * + * TLS 1.2 session: + * + * struct { + * #if defined(MBEDTLS_SSL_SESSION_TICKETS) + * opaque ticket<0..2^24-1>; // length 0 means no ticket + * uint32 ticket_lifetime; + * #endif + * } ClientOnlyData; + * + * struct { + * #if defined(MBEDTLS_HAVE_TIME) + * uint64 start_time; + * #endif + * uint8 session_id_len; // at most 32 + * opaque session_id[32]; + * opaque master[48]; // fixed length in the standard + * uint32 verify_result; + * #if defined(MBEDTLS_SSL_KEEP_PEER_CERTIFICATE + * opaque peer_cert<0..2^24-1>; // length 0 means no peer cert + * #else + * uint8 peer_cert_digest_type; + * opaque peer_cert_digest<0..2^8-1> + * #endif + * select (endpoint) { + * case client: ClientOnlyData; + * case server: uint64 ticket_creation_time; + * }; + * #if defined(MBEDTLS_SSL_MAX_FRAGMENT_LENGTH) + * uint8 mfl_code; // up to 255 according to standard + * #endif + * #if defined(MBEDTLS_SSL_ENCRYPT_THEN_MAC) + * uint8 encrypt_then_mac; // 0 or 1 + * #endif + * } serialized_session_tls12; + * + * + * TLS 1.3 Session: + * + * struct { + * #if defined(MBEDTLS_SSL_SERVER_NAME_INDICATION) + * opaque hostname<0..2^16-1>; + * #endif + * #if defined(MBEDTLS_HAVE_TIME) + * uint64 ticket_reception_time; + * #endif + * uint32 ticket_lifetime; + * opaque ticket<1..2^16-1>; + * } ClientOnlyData; + * + * struct { + * uint32 ticket_age_add; + * uint8 ticket_flags; + * opaque resumption_key<0..255>; + * #if defined(MBEDTLS_SSL_EARLY_DATA) + * uint32 max_early_data_size; + * #endif + * #if defined(MBEDTLS_SSL_RECORD_SIZE_LIMIT) + * uint16 record_size_limit; + * #endif + * select ( endpoint ) { + * case client: ClientOnlyData; + * case server: + * #if defined(MBEDTLS_HAVE_TIME) + * uint64 ticket_creation_time; + * #endif + * #if defined(MBEDTLS_SSL_EARLY_DATA) && defined(MBEDTLS_SSL_ALPN) + * opaque ticket_alpn<0..256>; + * #endif + * }; + * } serialized_session_tls13; + * + * + * SSL session: + * + * struct { + * + * opaque mbedtls_version[3]; // library version: major, minor, patch + * opaque session_format[2]; // library-version specific 16-bit field + * // determining the format of the remaining + * // serialized data. + * + * Note: When updating the format, remember to keep + * these version+format bytes. + * + * // In this version, `session_format` determines + * // the setting of those compile-time + * // configuration options which influence + * // the structure of mbedtls_ssl_session. + * + * uint8_t minor_ver; // Protocol minor version. Possible values: + * // - TLS 1.2 (0x0303) + * // - TLS 1.3 (0x0304) + * uint8_t endpoint; + * uint16_t ciphersuite; + * + * select (serialized_session.tls_version) { + * + * case MBEDTLS_SSL_VERSION_TLS1_2: + * serialized_session_tls12 data; + * case MBEDTLS_SSL_VERSION_TLS1_3: + * serialized_session_tls13 data; + * + * }; + * + * } serialized_session; + * + */ -int mbedtls_ssl_conf_psk(mbedtls_ssl_config *conf, - const unsigned char *psk, size_t psk_len, - const unsigned char *psk_identity, size_t psk_identity_len) +MBEDTLS_CHECK_RETURN_CRITICAL +static int ssl_session_save(const mbedtls_ssl_session *session, + unsigned char omit_header, + unsigned char *buf, + size_t buf_len, + size_t *olen) { + unsigned char *p = buf; + size_t used = 0; + size_t remaining_len; +#if defined(MBEDTLS_SSL_PROTO_TLS1_3) + size_t out_len; int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED; - /* Remove opaque/raw PSK + PSK Identity */ - ssl_conf_remove_psk(conf); - - /* Check and set raw PSK */ - if (psk == NULL) { - return MBEDTLS_ERR_SSL_BAD_INPUT_DATA; +#endif + if (session == NULL) { + return MBEDTLS_ERR_SSL_INTERNAL_ERROR; } - if (psk_len == 0) { - return MBEDTLS_ERR_SSL_BAD_INPUT_DATA; + + if (!omit_header) { + /* + * Add Mbed TLS version identifier + */ + used += sizeof(ssl_serialized_session_header); + + if (used <= buf_len) { + memcpy(p, ssl_serialized_session_header, + sizeof(ssl_serialized_session_header)); + p += sizeof(ssl_serialized_session_header); + } } - if (psk_len > MBEDTLS_PSK_MAX_LEN) { - return MBEDTLS_ERR_SSL_BAD_INPUT_DATA; + + /* + * TLS version identifier, endpoint, ciphersuite + */ + used += 1 /* TLS version */ + + 1 /* endpoint */ + + 2; /* ciphersuite */ + if (used <= buf_len) { + *p++ = MBEDTLS_BYTE_0(session->tls_version); + *p++ = session->endpoint; + MBEDTLS_PUT_UINT16_BE(session->ciphersuite, p, 0); + p += 2; } - if ((conf->psk = mbedtls_calloc(1, psk_len)) == NULL) { - return MBEDTLS_ERR_SSL_ALLOC_FAILED; + /* Forward to version-specific serialization routine. */ + remaining_len = (buf_len >= used) ? buf_len - used : 0; + switch (session->tls_version) { +#if defined(MBEDTLS_SSL_PROTO_TLS1_2) + case MBEDTLS_SSL_VERSION_TLS1_2: + used += ssl_tls12_session_save(session, p, remaining_len); + break; +#endif /* MBEDTLS_SSL_PROTO_TLS1_2 */ + +#if defined(MBEDTLS_SSL_PROTO_TLS1_3) + case MBEDTLS_SSL_VERSION_TLS1_3: + ret = ssl_tls13_session_save(session, p, remaining_len, &out_len); + if (ret != 0 && ret != MBEDTLS_ERR_SSL_BUFFER_TOO_SMALL) { + return ret; + } + used += out_len; + break; +#endif /* MBEDTLS_SSL_PROTO_TLS1_3 */ + + default: + return MBEDTLS_ERR_SSL_FEATURE_UNAVAILABLE; } - conf->psk_len = psk_len; - memcpy(conf->psk, psk, conf->psk_len); - /* Check and set PSK Identity */ - ret = ssl_conf_set_psk_identity(conf, psk_identity, psk_identity_len); - if (ret != 0) { - ssl_conf_remove_psk(conf); + *olen = used; + if (used > buf_len) { + return MBEDTLS_ERR_SSL_BUFFER_TOO_SMALL; } - return ret; + return 0; } -static void ssl_remove_psk(mbedtls_ssl_context *ssl) +/* + * Public wrapper for ssl_session_save() + */ +int mbedtls_ssl_session_save(const mbedtls_ssl_session *session, + unsigned char *buf, + size_t buf_len, + size_t *olen) { -#if defined(MBEDTLS_USE_PSA_CRYPTO) - if (!mbedtls_svc_key_id_is_null(ssl->handshake->psk_opaque)) { - ssl->handshake->psk_opaque = MBEDTLS_SVC_KEY_ID_INIT; - } else -#endif /* MBEDTLS_USE_PSA_CRYPTO */ - if (ssl->handshake->psk != NULL) { - mbedtls_platform_zeroize(ssl->handshake->psk, - ssl->handshake->psk_len); - mbedtls_free(ssl->handshake->psk); - ssl->handshake->psk_len = 0; - } + return ssl_session_save(session, 0, buf, buf_len, olen); } -int mbedtls_ssl_set_hs_psk(mbedtls_ssl_context *ssl, - const unsigned char *psk, size_t psk_len) +/* + * Deserialize session, see mbedtls_ssl_session_save() for format. + * + * This internal version is wrapped by a public function that cleans up in + * case of error, and has an extra option omit_header. + */ +MBEDTLS_CHECK_RETURN_CRITICAL +static int ssl_session_load(mbedtls_ssl_session *session, + unsigned char omit_header, + const unsigned char *buf, + size_t len) { - if (psk == NULL || ssl->handshake == NULL) { - return MBEDTLS_ERR_SSL_BAD_INPUT_DATA; - } - - if (psk_len > MBEDTLS_PSK_MAX_LEN) { - return MBEDTLS_ERR_SSL_BAD_INPUT_DATA; - } + const unsigned char *p = buf; + const unsigned char * const end = buf + len; + size_t remaining_len; - ssl_remove_psk(ssl); - if ((ssl->handshake->psk = mbedtls_calloc(1, psk_len)) == NULL) { - return MBEDTLS_ERR_SSL_ALLOC_FAILED; + if (session == NULL) { + return MBEDTLS_ERR_SSL_INTERNAL_ERROR; } - ssl->handshake->psk_len = psk_len; - memcpy(ssl->handshake->psk, psk, ssl->handshake->psk_len); + if (!omit_header) { + /* + * Check Mbed TLS version identifier + */ - return 0; -} + if ((size_t) (end - p) < sizeof(ssl_serialized_session_header)) { + return MBEDTLS_ERR_SSL_BAD_INPUT_DATA; + } -#if defined(MBEDTLS_USE_PSA_CRYPTO) -int mbedtls_ssl_conf_psk_opaque(mbedtls_ssl_config *conf, - psa_key_id_t psk, - const unsigned char *psk_identity, - size_t psk_identity_len) -{ - int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED; - /* Clear opaque/raw PSK + PSK Identity, if present. */ - ssl_conf_remove_psk(conf); + if (memcmp(p, ssl_serialized_session_header, + sizeof(ssl_serialized_session_header)) != 0) { + return MBEDTLS_ERR_SSL_VERSION_MISMATCH; + } + p += sizeof(ssl_serialized_session_header); + } - /* Check and set opaque PSK */ - if (mbedtls_svc_key_id_is_null(psk)) { + /* + * TLS version identifier, endpoint, ciphersuite + */ + if (4 > (size_t) (end - p)) { return MBEDTLS_ERR_SSL_BAD_INPUT_DATA; } - conf->psk_opaque = psk; + session->tls_version = (mbedtls_ssl_protocol_version) (0x0300 | *p++); + session->endpoint = *p++; + session->ciphersuite = MBEDTLS_GET_UINT16_BE(p, 0); + p += 2; - /* Check and set PSK Identity */ - ret = ssl_conf_set_psk_identity(conf, psk_identity, - psk_identity_len); - if (ret != 0) { - ssl_conf_remove_psk(conf); - } + /* Dispatch according to TLS version. */ + remaining_len = (size_t) (end - p); + switch (session->tls_version) { +#if defined(MBEDTLS_SSL_PROTO_TLS1_2) + case MBEDTLS_SSL_VERSION_TLS1_2: + return ssl_tls12_session_load(session, p, remaining_len); +#endif /* MBEDTLS_SSL_PROTO_TLS1_2 */ - return ret; -} +#if defined(MBEDTLS_SSL_PROTO_TLS1_3) + case MBEDTLS_SSL_VERSION_TLS1_3: + return ssl_tls13_session_load(session, p, remaining_len); +#endif /* MBEDTLS_SSL_PROTO_TLS1_3 */ -int mbedtls_ssl_set_hs_psk_opaque(mbedtls_ssl_context *ssl, - psa_key_id_t psk) -{ - if ((mbedtls_svc_key_id_is_null(psk)) || - (ssl->handshake == NULL)) { - return MBEDTLS_ERR_SSL_BAD_INPUT_DATA; + default: + return MBEDTLS_ERR_SSL_BAD_INPUT_DATA; } - - ssl_remove_psk(ssl); - ssl->handshake->psk_opaque = psk; - return 0; } -#endif /* MBEDTLS_USE_PSA_CRYPTO */ -void mbedtls_ssl_conf_psk_cb(mbedtls_ssl_config *conf, - int (*f_psk)(void *, mbedtls_ssl_context *, const unsigned char *, - size_t), - void *p_psk) +/* + * Deserialize session: public wrapper for error cleaning + */ +int mbedtls_ssl_session_load(mbedtls_ssl_session *session, + const unsigned char *buf, + size_t len) { - conf->f_psk = f_psk; - conf->p_psk = p_psk; -} -#endif /* MBEDTLS_KEY_EXCHANGE_SOME_PSK_ENABLED */ + int ret = ssl_session_load(session, 0, buf, len); -#if defined(MBEDTLS_DHM_C) && defined(MBEDTLS_SSL_SRV_C) + if (ret != 0) { + mbedtls_ssl_session_free(session); + } -#if !defined(MBEDTLS_DEPRECATED_REMOVED) -int mbedtls_ssl_conf_dh_param(mbedtls_ssl_config *conf, const char *dhm_P, const char *dhm_G) + return ret; +} + +/* + * Perform a single step of the SSL handshake + */ +MBEDTLS_CHECK_RETURN_CRITICAL +static int ssl_prepare_handshake_step(mbedtls_ssl_context *ssl) { int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED; - if ((ret = mbedtls_mpi_read_string(&conf->dhm_P, 16, dhm_P)) != 0 || - (ret = mbedtls_mpi_read_string(&conf->dhm_G, 16, dhm_G)) != 0) { - mbedtls_mpi_free(&conf->dhm_P); - mbedtls_mpi_free(&conf->dhm_G); + /* + * We may have not been able to send to the peer all the handshake data + * that were written into the output buffer by the previous handshake step, + * if the write to the network callback returned with the + * #MBEDTLS_ERR_SSL_WANT_WRITE error code. + * We proceed to the next handshake step only when all data from the + * previous one have been sent to the peer, thus we make sure that this is + * the case here by calling `mbedtls_ssl_flush_output()`. The function may + * return with the #MBEDTLS_ERR_SSL_WANT_WRITE error code in which case + * we have to wait before to go ahead. + * In the case of TLS 1.3, handshake step handlers do not send data to the + * peer. Data are only sent here and through + * `mbedtls_ssl_handle_pending_alert` in case an error that triggered an + * alert occurred. + */ + if ((ret = mbedtls_ssl_flush_output(ssl)) != 0) { return ret; } - return 0; +#if defined(MBEDTLS_SSL_PROTO_DTLS) + if (ssl->conf->transport == MBEDTLS_SSL_TRANSPORT_DATAGRAM && + ssl->handshake->retransmit_state == MBEDTLS_SSL_RETRANS_SENDING) { + if ((ret = mbedtls_ssl_flight_transmit(ssl)) != 0) { + return ret; + } + } +#endif /* MBEDTLS_SSL_PROTO_DTLS */ + + return ret; } -#endif /* MBEDTLS_DEPRECATED_REMOVED */ -int mbedtls_ssl_conf_dh_param_bin(mbedtls_ssl_config *conf, - const unsigned char *dhm_P, size_t P_len, - const unsigned char *dhm_G, size_t G_len) +int mbedtls_ssl_handshake_step(mbedtls_ssl_context *ssl) { int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED; - mbedtls_mpi_free(&conf->dhm_P); - mbedtls_mpi_free(&conf->dhm_G); + if (ssl == NULL || + ssl->conf == NULL || + ssl->handshake == NULL || + ssl->state == MBEDTLS_SSL_HANDSHAKE_OVER) { + return MBEDTLS_ERR_SSL_BAD_INPUT_DATA; + } - if ((ret = mbedtls_mpi_read_binary(&conf->dhm_P, dhm_P, P_len)) != 0 || - (ret = mbedtls_mpi_read_binary(&conf->dhm_G, dhm_G, G_len)) != 0) { - mbedtls_mpi_free(&conf->dhm_P); - mbedtls_mpi_free(&conf->dhm_G); + ret = ssl_prepare_handshake_step(ssl); + if (ret != 0) { return ret; } - return 0; -} + ret = mbedtls_ssl_handle_pending_alert(ssl); + if (ret != 0) { + goto cleanup; + } -int mbedtls_ssl_conf_dh_param_ctx(mbedtls_ssl_config *conf, mbedtls_dhm_context *dhm_ctx) -{ - int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED; + /* If ssl->conf->endpoint is not one of MBEDTLS_SSL_IS_CLIENT or + * MBEDTLS_SSL_IS_SERVER, this is the return code we give */ + ret = MBEDTLS_ERR_SSL_BAD_INPUT_DATA; - mbedtls_mpi_free(&conf->dhm_P); - mbedtls_mpi_free(&conf->dhm_G); +#if defined(MBEDTLS_SSL_CLI_C) + if (ssl->conf->endpoint == MBEDTLS_SSL_IS_CLIENT) { + MBEDTLS_SSL_DEBUG_MSG(2, ("client state: %s", + mbedtls_ssl_states_str((mbedtls_ssl_states) ssl->state))); - if ((ret = mbedtls_mpi_copy(&conf->dhm_P, &dhm_ctx->P)) != 0 || - (ret = mbedtls_mpi_copy(&conf->dhm_G, &dhm_ctx->G)) != 0) { - mbedtls_mpi_free(&conf->dhm_P); - mbedtls_mpi_free(&conf->dhm_G); - return ret; + switch (ssl->state) { + case MBEDTLS_SSL_HELLO_REQUEST: + ssl->state = MBEDTLS_SSL_CLIENT_HELLO; + ret = 0; + break; + + case MBEDTLS_SSL_CLIENT_HELLO: + ret = mbedtls_ssl_write_client_hello(ssl); + break; + + default: +#if defined(MBEDTLS_SSL_PROTO_TLS1_2) && defined(MBEDTLS_SSL_PROTO_TLS1_3) + if (ssl->tls_version == MBEDTLS_SSL_VERSION_TLS1_3) { + ret = mbedtls_ssl_tls13_handshake_client_step(ssl); + } else { + ret = mbedtls_ssl_handshake_client_step(ssl); + } +#elif defined(MBEDTLS_SSL_PROTO_TLS1_2) + ret = mbedtls_ssl_handshake_client_step(ssl); +#else + ret = mbedtls_ssl_tls13_handshake_client_step(ssl); +#endif + } } +#endif /* MBEDTLS_SSL_CLI_C */ - return 0; -} -#endif /* MBEDTLS_DHM_C && MBEDTLS_SSL_SRV_C */ +#if defined(MBEDTLS_SSL_SRV_C) + if (ssl->conf->endpoint == MBEDTLS_SSL_IS_SERVER) { +#if defined(MBEDTLS_SSL_PROTO_TLS1_2) && defined(MBEDTLS_SSL_PROTO_TLS1_3) + if (ssl->tls_version == MBEDTLS_SSL_VERSION_TLS1_3) { + ret = mbedtls_ssl_tls13_handshake_server_step(ssl); + } else { + ret = mbedtls_ssl_handshake_server_step(ssl); + } +#elif defined(MBEDTLS_SSL_PROTO_TLS1_2) + ret = mbedtls_ssl_handshake_server_step(ssl); +#else + ret = mbedtls_ssl_tls13_handshake_server_step(ssl); +#endif + } +#endif /* MBEDTLS_SSL_SRV_C */ -#if defined(MBEDTLS_DHM_C) && defined(MBEDTLS_SSL_CLI_C) -/* - * Set the minimum length for Diffie-Hellman parameters - */ -void mbedtls_ssl_conf_dhm_min_bitlen(mbedtls_ssl_config *conf, - unsigned int bitlen) -{ - conf->dhm_min_bitlen = bitlen; -} -#endif /* MBEDTLS_DHM_C && MBEDTLS_SSL_CLI_C */ + if (ret != 0) { + /* handshake_step return error. And it is same + * with alert_reason. + */ + if (ssl->send_alert) { + ret = mbedtls_ssl_handle_pending_alert(ssl); + goto cleanup; + } + } -#if defined(MBEDTLS_KEY_EXCHANGE_WITH_CERT_ENABLED) -/* - * Set allowed/preferred hashes for handshake signatures - */ -void mbedtls_ssl_conf_sig_hashes(mbedtls_ssl_config *conf, - const int *hashes) -{ - conf->sig_hashes = hashes; +cleanup: + return ret; } -#endif /* MBEDTLS_KEY_EXCHANGE_WITH_CERT_ENABLED */ -#if defined(MBEDTLS_ECP_C) /* - * Set the allowed elliptic curves + * Perform the SSL handshake */ -void mbedtls_ssl_conf_curves(mbedtls_ssl_config *conf, - const mbedtls_ecp_group_id *curve_list) -{ - conf->curve_list = curve_list; -} -#endif /* MBEDTLS_ECP_C */ - -#if defined(MBEDTLS_X509_CRT_PARSE_C) -int mbedtls_ssl_set_hostname(mbedtls_ssl_context *ssl, const char *hostname) +int mbedtls_ssl_handshake(mbedtls_ssl_context *ssl) { - /* Initialize to suppress unnecessary compiler warning */ - size_t hostname_len = 0; + int ret = 0; - /* Check if new hostname is valid before - * making any change to current one */ - if (hostname != NULL) { - hostname_len = strlen(hostname); + /* Sanity checks */ - if (hostname_len > MBEDTLS_SSL_MAX_HOST_NAME_LEN) { - return MBEDTLS_ERR_SSL_BAD_INPUT_DATA; - } + if (ssl == NULL || ssl->conf == NULL) { + return MBEDTLS_ERR_SSL_BAD_INPUT_DATA; } - /* Now it's clear that we will overwrite the old hostname, - * so we can free it safely */ - - if (ssl->hostname != NULL) { - mbedtls_platform_zeroize(ssl->hostname, strlen(ssl->hostname)); - mbedtls_free(ssl->hostname); +#if defined(MBEDTLS_SSL_PROTO_DTLS) + if (ssl->conf->transport == MBEDTLS_SSL_TRANSPORT_DATAGRAM && + (ssl->f_set_timer == NULL || ssl->f_get_timer == NULL)) { + MBEDTLS_SSL_DEBUG_MSG(1, ("You must use " + "mbedtls_ssl_set_timer_cb() for DTLS")); + return MBEDTLS_ERR_SSL_BAD_INPUT_DATA; } +#endif /* MBEDTLS_SSL_PROTO_DTLS */ - /* Passing NULL as hostname shall clear the old one */ - - if (hostname == NULL) { - ssl->hostname = NULL; - } else { - ssl->hostname = mbedtls_calloc(1, hostname_len + 1); - if (ssl->hostname == NULL) { - return MBEDTLS_ERR_SSL_ALLOC_FAILED; - } + MBEDTLS_SSL_DEBUG_MSG(2, ("=> handshake")); - memcpy(ssl->hostname, hostname, hostname_len); + /* Main handshake loop */ + while (ssl->state != MBEDTLS_SSL_HANDSHAKE_OVER) { + ret = mbedtls_ssl_handshake_step(ssl); - ssl->hostname[hostname_len] = '\0'; + if (ret != 0) { + break; + } } - return 0; -} -#endif /* MBEDTLS_X509_CRT_PARSE_C */ + MBEDTLS_SSL_DEBUG_MSG(2, ("<= handshake")); -#if defined(MBEDTLS_SSL_SERVER_NAME_INDICATION) -void mbedtls_ssl_conf_sni(mbedtls_ssl_config *conf, - int (*f_sni)(void *, mbedtls_ssl_context *, - const unsigned char *, size_t), - void *p_sni) -{ - conf->f_sni = f_sni; - conf->p_sni = p_sni; + return ret; } -#endif /* MBEDTLS_SSL_SERVER_NAME_INDICATION */ -#if defined(MBEDTLS_SSL_ALPN) -int mbedtls_ssl_conf_alpn_protocols(mbedtls_ssl_config *conf, const char **protos) +#if defined(MBEDTLS_SSL_RENEGOTIATION) +#if defined(MBEDTLS_SSL_SRV_C) +/* + * Write HelloRequest to request renegotiation on server + */ +MBEDTLS_CHECK_RETURN_CRITICAL +static int ssl_write_hello_request(mbedtls_ssl_context *ssl) { - size_t cur_len, tot_len; - const char **p; + int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED; - /* - * RFC 7301 3.1: "Empty strings MUST NOT be included and byte strings - * MUST NOT be truncated." - * We check lengths now rather than later. - */ - tot_len = 0; - for (p = protos; *p != NULL; p++) { - cur_len = strlen(*p); - tot_len += cur_len; + MBEDTLS_SSL_DEBUG_MSG(2, ("=> write hello request")); - if ((cur_len == 0) || - (cur_len > MBEDTLS_SSL_MAX_ALPN_NAME_LEN) || - (tot_len > MBEDTLS_SSL_MAX_ALPN_LIST_LEN)) { - return MBEDTLS_ERR_SSL_BAD_INPUT_DATA; - } + ssl->out_msglen = 4; + ssl->out_msgtype = MBEDTLS_SSL_MSG_HANDSHAKE; + ssl->out_msg[0] = MBEDTLS_SSL_HS_HELLO_REQUEST; + + if ((ret = mbedtls_ssl_write_handshake_msg(ssl)) != 0) { + MBEDTLS_SSL_DEBUG_RET(1, "mbedtls_ssl_write_handshake_msg", ret); + return ret; } - conf->alpn_list = protos; + MBEDTLS_SSL_DEBUG_MSG(2, ("<= write hello request")); return 0; } +#endif /* MBEDTLS_SSL_SRV_C */ -const char *mbedtls_ssl_get_alpn_protocol(const mbedtls_ssl_context *ssl) -{ - return ssl->alpn_chosen; -} -#endif /* MBEDTLS_SSL_ALPN */ - -#if defined(MBEDTLS_SSL_DTLS_SRTP) -void mbedtls_ssl_conf_srtp_mki_value_supported(mbedtls_ssl_config *conf, - int support_mki_value) +/* + * Actually renegotiate current connection, triggered by either: + * - any side: calling mbedtls_ssl_renegotiate(), + * - client: receiving a HelloRequest during mbedtls_ssl_read(), + * - server: receiving any handshake message on server during mbedtls_ssl_read() after + * the initial handshake is completed. + * If the handshake doesn't complete due to waiting for I/O, it will continue + * during the next calls to mbedtls_ssl_renegotiate() or mbedtls_ssl_read() respectively. + */ +int mbedtls_ssl_start_renegotiation(mbedtls_ssl_context *ssl) { - conf->dtls_srtp_mki_support = support_mki_value; -} + int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED; -int mbedtls_ssl_dtls_srtp_set_mki_value(mbedtls_ssl_context *ssl, - unsigned char *mki_value, - uint16_t mki_len) -{ - if (mki_len > MBEDTLS_TLS_SRTP_MAX_MKI_LENGTH) { - return MBEDTLS_ERR_SSL_BAD_INPUT_DATA; - } + MBEDTLS_SSL_DEBUG_MSG(2, ("=> renegotiate")); - if (ssl->conf->dtls_srtp_mki_support == MBEDTLS_SSL_DTLS_SRTP_MKI_UNSUPPORTED) { - return MBEDTLS_ERR_SSL_FEATURE_UNAVAILABLE; + if ((ret = ssl_handshake_init(ssl)) != 0) { + return ret; } - memcpy(ssl->dtls_srtp_info.mki_value, mki_value, mki_len); - ssl->dtls_srtp_info.mki_len = mki_len; - return 0; -} - -int mbedtls_ssl_conf_dtls_srtp_protection_profiles(mbedtls_ssl_config *conf, - const mbedtls_ssl_srtp_profile *profiles) -{ - const mbedtls_ssl_srtp_profile *p; - size_t list_size = 0; - - /* check the profiles list: all entry must be valid, - * its size cannot be more than the total number of supported profiles, currently 4 */ - for (p = profiles; *p != MBEDTLS_TLS_SRTP_UNSET && - list_size <= MBEDTLS_TLS_SRTP_MAX_PROFILE_LIST_LENGTH; - p++) { - if (mbedtls_ssl_check_srtp_profile_value(*p) != MBEDTLS_TLS_SRTP_UNSET) { - list_size++; + /* RFC 6347 4.2.2: "[...] the HelloRequest will have message_seq = 0 and + * the ServerHello will have message_seq = 1" */ +#if defined(MBEDTLS_SSL_PROTO_DTLS) + if (ssl->conf->transport == MBEDTLS_SSL_TRANSPORT_DATAGRAM && + ssl->renego_status == MBEDTLS_SSL_RENEGOTIATION_PENDING) { + if (ssl->conf->endpoint == MBEDTLS_SSL_IS_SERVER) { + ssl->handshake->out_msg_seq = 1; } else { - /* unsupported value, stop parsing and set the size to an error value */ - list_size = MBEDTLS_TLS_SRTP_MAX_PROFILE_LIST_LENGTH + 1; + ssl->handshake->in_msg_seq = 1; } } +#endif - if (list_size > MBEDTLS_TLS_SRTP_MAX_PROFILE_LIST_LENGTH) { - conf->dtls_srtp_profile_list = NULL; - conf->dtls_srtp_profile_list_len = 0; - return MBEDTLS_ERR_SSL_BAD_INPUT_DATA; + ssl->state = MBEDTLS_SSL_HELLO_REQUEST; + ssl->renego_status = MBEDTLS_SSL_RENEGOTIATION_IN_PROGRESS; + + if ((ret = mbedtls_ssl_handshake(ssl)) != 0) { + MBEDTLS_SSL_DEBUG_RET(1, "mbedtls_ssl_handshake", ret); + return ret; } - conf->dtls_srtp_profile_list = profiles; - conf->dtls_srtp_profile_list_len = list_size; + MBEDTLS_SSL_DEBUG_MSG(2, ("<= renegotiate")); return 0; } -void mbedtls_ssl_get_dtls_srtp_negotiation_result(const mbedtls_ssl_context *ssl, - mbedtls_dtls_srtp_info *dtls_srtp_info) +/* + * Renegotiate current connection on client, + * or request renegotiation on server + */ +int mbedtls_ssl_renegotiate(mbedtls_ssl_context *ssl) { - dtls_srtp_info->chosen_dtls_srtp_profile = ssl->dtls_srtp_info.chosen_dtls_srtp_profile; - /* do not copy the mki value if there is no chosen profile */ - if (dtls_srtp_info->chosen_dtls_srtp_profile == MBEDTLS_TLS_SRTP_UNSET) { - dtls_srtp_info->mki_len = 0; - } else { - dtls_srtp_info->mki_len = ssl->dtls_srtp_info.mki_len; - memcpy(dtls_srtp_info->mki_value, ssl->dtls_srtp_info.mki_value, - ssl->dtls_srtp_info.mki_len); + int ret = MBEDTLS_ERR_SSL_FEATURE_UNAVAILABLE; + + if (ssl == NULL || ssl->conf == NULL) { + return MBEDTLS_ERR_SSL_BAD_INPUT_DATA; } -} -#endif /* MBEDTLS_SSL_DTLS_SRTP */ -void mbedtls_ssl_conf_max_version(mbedtls_ssl_config *conf, int major, int minor) -{ - conf->max_major_ver = major; - conf->max_minor_ver = minor; -} +#if defined(MBEDTLS_SSL_SRV_C) + /* On server, just send the request */ + if (ssl->conf->endpoint == MBEDTLS_SSL_IS_SERVER) { + if (mbedtls_ssl_is_handshake_over(ssl) == 0) { + return MBEDTLS_ERR_SSL_BAD_INPUT_DATA; + } -void mbedtls_ssl_conf_min_version(mbedtls_ssl_config *conf, int major, int minor) -{ - conf->min_major_ver = major; - conf->min_minor_ver = minor; -} + ssl->renego_status = MBEDTLS_SSL_RENEGOTIATION_PENDING; -#if defined(MBEDTLS_SSL_FALLBACK_SCSV) && defined(MBEDTLS_SSL_CLI_C) -void mbedtls_ssl_conf_fallback(mbedtls_ssl_config *conf, char fallback) -{ - conf->fallback = fallback; -} -#endif + /* Did we already try/start sending HelloRequest? */ + if (ssl->out_left != 0) { + return mbedtls_ssl_flush_output(ssl); + } -#if defined(MBEDTLS_SSL_SRV_C) -void mbedtls_ssl_conf_cert_req_ca_list(mbedtls_ssl_config *conf, - char cert_req_ca_list) -{ - conf->cert_req_ca_list = cert_req_ca_list; -} -#endif + return ssl_write_hello_request(ssl); + } +#endif /* MBEDTLS_SSL_SRV_C */ -#if defined(MBEDTLS_SSL_ENCRYPT_THEN_MAC) -void mbedtls_ssl_conf_encrypt_then_mac(mbedtls_ssl_config *conf, char etm) -{ - conf->encrypt_then_mac = etm; -} -#endif +#if defined(MBEDTLS_SSL_CLI_C) + /* + * On client, either start the renegotiation process or, + * if already in progress, continue the handshake + */ + if (ssl->renego_status != MBEDTLS_SSL_RENEGOTIATION_IN_PROGRESS) { + if (mbedtls_ssl_is_handshake_over(ssl) == 0) { + return MBEDTLS_ERR_SSL_BAD_INPUT_DATA; + } -#if defined(MBEDTLS_SSL_EXTENDED_MASTER_SECRET) -void mbedtls_ssl_conf_extended_master_secret(mbedtls_ssl_config *conf, char ems) -{ - conf->extended_ms = ems; -} -#endif + if ((ret = mbedtls_ssl_start_renegotiation(ssl)) != 0) { + MBEDTLS_SSL_DEBUG_RET(1, "mbedtls_ssl_start_renegotiation", ret); + return ret; + } + } else { + if ((ret = mbedtls_ssl_handshake(ssl)) != 0) { + MBEDTLS_SSL_DEBUG_RET(1, "mbedtls_ssl_handshake", ret); + return ret; + } + } +#endif /* MBEDTLS_SSL_CLI_C */ -#if defined(MBEDTLS_ARC4_C) -void mbedtls_ssl_conf_arc4_support(mbedtls_ssl_config *conf, char arc4) -{ - conf->arc4_disabled = arc4; + return ret; } -#endif +#endif /* MBEDTLS_SSL_RENEGOTIATION */ -#if defined(MBEDTLS_SSL_MAX_FRAGMENT_LENGTH) -int mbedtls_ssl_conf_max_frag_len(mbedtls_ssl_config *conf, unsigned char mfl_code) +void mbedtls_ssl_handshake_free(mbedtls_ssl_context *ssl) { - if (mfl_code >= MBEDTLS_SSL_MAX_FRAG_LEN_INVALID || - ssl_mfl_code_to_length(mfl_code) > MBEDTLS_TLS_EXT_ADV_CONTENT_LEN) { - return MBEDTLS_ERR_SSL_BAD_INPUT_DATA; + mbedtls_ssl_handshake_params *handshake = ssl->handshake; + + if (handshake == NULL) { + return; } - conf->mfl_code = mfl_code; +#if defined(MBEDTLS_PK_HAVE_ECC_KEYS) +#if !defined(MBEDTLS_DEPRECATED_REMOVED) + if (ssl->handshake->group_list_heap_allocated) { + mbedtls_free((void *) handshake->group_list); + } + handshake->group_list = NULL; +#endif /* MBEDTLS_DEPRECATED_REMOVED */ +#endif /* MBEDTLS_PK_HAVE_ECC_KEYS */ - return 0; -} -#endif /* MBEDTLS_SSL_MAX_FRAGMENT_LENGTH */ +#if defined(MBEDTLS_SSL_HANDSHAKE_WITH_CERT_ENABLED) +#if !defined(MBEDTLS_DEPRECATED_REMOVED) + if (ssl->handshake->sig_algs_heap_allocated) { + mbedtls_free((void *) handshake->sig_algs); + } + handshake->sig_algs = NULL; +#endif /* MBEDTLS_DEPRECATED_REMOVED */ +#if defined(MBEDTLS_SSL_PROTO_TLS1_3) + if (ssl->handshake->certificate_request_context) { + mbedtls_free((void *) handshake->certificate_request_context); + } +#endif /* MBEDTLS_SSL_PROTO_TLS1_3 */ +#endif /* MBEDTLS_SSL_HANDSHAKE_WITH_CERT_ENABLED */ -#if defined(MBEDTLS_SSL_TRUNCATED_HMAC) -void mbedtls_ssl_conf_truncated_hmac(mbedtls_ssl_config *conf, int truncate) -{ - conf->trunc_hmac = truncate; -} -#endif /* MBEDTLS_SSL_TRUNCATED_HMAC */ +#if defined(MBEDTLS_SSL_ASYNC_PRIVATE) + if (ssl->conf->f_async_cancel != NULL && handshake->async_in_progress != 0) { + ssl->conf->f_async_cancel(ssl); + handshake->async_in_progress = 0; + } +#endif /* MBEDTLS_SSL_ASYNC_PRIVATE */ -#if defined(MBEDTLS_SSL_CBC_RECORD_SPLITTING) -void mbedtls_ssl_conf_cbc_record_splitting(mbedtls_ssl_config *conf, char split) -{ - conf->cbc_record_splitting = split; -} +#if defined(MBEDTLS_MD_CAN_SHA256) +#if defined(MBEDTLS_USE_PSA_CRYPTO) + psa_hash_abort(&handshake->fin_sha256_psa); +#else + mbedtls_md_free(&handshake->fin_sha256); +#endif +#endif +#if defined(MBEDTLS_MD_CAN_SHA384) +#if defined(MBEDTLS_USE_PSA_CRYPTO) + psa_hash_abort(&handshake->fin_sha384_psa); +#else + mbedtls_md_free(&handshake->fin_sha384); +#endif #endif -void mbedtls_ssl_conf_legacy_renegotiation(mbedtls_ssl_config *conf, int allow_legacy) -{ - conf->allow_legacy_renegotiation = allow_legacy; -} - -#if defined(MBEDTLS_SSL_RENEGOTIATION) -void mbedtls_ssl_conf_renegotiation(mbedtls_ssl_config *conf, int renegotiation) -{ - conf->disable_renegotiation = renegotiation; -} - -void mbedtls_ssl_conf_renegotiation_enforced(mbedtls_ssl_config *conf, int max_records) -{ - conf->renego_max_records = max_records; -} - -void mbedtls_ssl_conf_renegotiation_period(mbedtls_ssl_config *conf, - const unsigned char period[8]) -{ - memcpy(conf->renego_period, period, 8); -} -#endif /* MBEDTLS_SSL_RENEGOTIATION */ +#if defined(MBEDTLS_DHM_C) + mbedtls_dhm_free(&handshake->dhm_ctx); +#endif +#if !defined(MBEDTLS_USE_PSA_CRYPTO) && \ + defined(MBEDTLS_KEY_EXCHANGE_SOME_ECDH_OR_ECDHE_1_2_ENABLED) + mbedtls_ecdh_free(&handshake->ecdh_ctx); +#endif -#if defined(MBEDTLS_SSL_SESSION_TICKETS) +#if defined(MBEDTLS_KEY_EXCHANGE_ECJPAKE_ENABLED) +#if defined(MBEDTLS_USE_PSA_CRYPTO) + psa_pake_abort(&handshake->psa_pake_ctx); + /* + * Opaque keys are not stored in the handshake's data and it's the user + * responsibility to destroy them. Clear ones, instead, are created by + * the TLS library and should be destroyed at the same level + */ + if (!mbedtls_svc_key_id_is_null(handshake->psa_pake_password)) { + psa_destroy_key(handshake->psa_pake_password); + } + handshake->psa_pake_password = MBEDTLS_SVC_KEY_ID_INIT; +#else + mbedtls_ecjpake_free(&handshake->ecjpake_ctx); +#endif /* MBEDTLS_USE_PSA_CRYPTO */ #if defined(MBEDTLS_SSL_CLI_C) -void mbedtls_ssl_conf_session_tickets(mbedtls_ssl_config *conf, int use_tickets) -{ - conf->session_tickets = use_tickets; -} + mbedtls_free(handshake->ecjpake_cache); + handshake->ecjpake_cache = NULL; + handshake->ecjpake_cache_len = 0; #endif - -#if defined(MBEDTLS_SSL_SRV_C) -void mbedtls_ssl_conf_session_tickets_cb(mbedtls_ssl_config *conf, - mbedtls_ssl_ticket_write_t *f_ticket_write, - mbedtls_ssl_ticket_parse_t *f_ticket_parse, - void *p_ticket) -{ - conf->f_ticket_write = f_ticket_write; - conf->f_ticket_parse = f_ticket_parse; - conf->p_ticket = p_ticket; -} #endif -#endif /* MBEDTLS_SSL_SESSION_TICKETS */ - -#if defined(MBEDTLS_SSL_EXPORT_KEYS) -void mbedtls_ssl_conf_export_keys_cb(mbedtls_ssl_config *conf, - mbedtls_ssl_export_keys_t *f_export_keys, - void *p_export_keys) -{ - conf->f_export_keys = f_export_keys; - conf->p_export_keys = p_export_keys; -} -void mbedtls_ssl_conf_export_keys_ext_cb(mbedtls_ssl_config *conf, - mbedtls_ssl_export_keys_ext_t *f_export_keys_ext, - void *p_export_keys) -{ - conf->f_export_keys_ext = f_export_keys_ext; - conf->p_export_keys = p_export_keys; -} +#if defined(MBEDTLS_KEY_EXCHANGE_SOME_ECDH_OR_ECDHE_ANY_ENABLED) || \ + defined(MBEDTLS_KEY_EXCHANGE_WITH_ECDSA_ANY_ENABLED) || \ + defined(MBEDTLS_KEY_EXCHANGE_ECJPAKE_ENABLED) + /* explicit void pointer cast for buggy MS compiler */ + mbedtls_free((void *) handshake->curves_tls_id); #endif -#if defined(MBEDTLS_SSL_ASYNC_PRIVATE) -void mbedtls_ssl_conf_async_private_cb( - mbedtls_ssl_config *conf, - mbedtls_ssl_async_sign_t *f_async_sign, - mbedtls_ssl_async_decrypt_t *f_async_decrypt, - mbedtls_ssl_async_resume_t *f_async_resume, - mbedtls_ssl_async_cancel_t *f_async_cancel, - void *async_config_data) -{ - conf->f_async_sign_start = f_async_sign; - conf->f_async_decrypt_start = f_async_decrypt; - conf->f_async_resume = f_async_resume; - conf->f_async_cancel = f_async_cancel; - conf->p_async_config_data = async_config_data; -} - -void *mbedtls_ssl_conf_get_async_config_data(const mbedtls_ssl_config *conf) -{ - return conf->p_async_config_data; -} - -void *mbedtls_ssl_get_async_operation_data(const mbedtls_ssl_context *ssl) -{ - if (ssl->handshake == NULL) { - return NULL; - } else { - return ssl->handshake->user_async_ctx; +#if defined(MBEDTLS_SSL_HANDSHAKE_WITH_PSK_ENABLED) +#if defined(MBEDTLS_USE_PSA_CRYPTO) + if (!mbedtls_svc_key_id_is_null(ssl->handshake->psk_opaque)) { + /* The maintenance of the external PSK key slot is the + * user's responsibility. */ + if (ssl->handshake->psk_opaque_is_internal) { + psa_destroy_key(ssl->handshake->psk_opaque); + ssl->handshake->psk_opaque_is_internal = 0; + } + ssl->handshake->psk_opaque = MBEDTLS_SVC_KEY_ID_INIT; } -} - -void mbedtls_ssl_set_async_operation_data(mbedtls_ssl_context *ssl, - void *ctx) -{ - if (ssl->handshake != NULL) { - ssl->handshake->user_async_ctx = ctx; +#else + if (handshake->psk != NULL) { + mbedtls_zeroize_and_free(handshake->psk, handshake->psk_len); } -} -#endif /* MBEDTLS_SSL_ASYNC_PRIVATE */ +#endif /* MBEDTLS_USE_PSA_CRYPTO */ +#endif /* MBEDTLS_SSL_HANDSHAKE_WITH_PSK_ENABLED */ -/* - * SSL get accessors - */ -uint32_t mbedtls_ssl_get_verify_result(const mbedtls_ssl_context *ssl) -{ - if (ssl->session != NULL) { - return ssl->session->verify_result; - } +#if defined(MBEDTLS_X509_CRT_PARSE_C) && \ + defined(MBEDTLS_SSL_SERVER_NAME_INDICATION) + /* + * Free only the linked list wrapper, not the keys themselves + * since the belong to the SNI callback + */ + ssl_key_cert_free(handshake->sni_key_cert); +#endif /* MBEDTLS_X509_CRT_PARSE_C && MBEDTLS_SSL_SERVER_NAME_INDICATION */ - if (ssl->session_negotiate != NULL) { - return ssl->session_negotiate->verify_result; +#if defined(MBEDTLS_SSL_ECP_RESTARTABLE_ENABLED) + mbedtls_x509_crt_restart_free(&handshake->ecrs_ctx); + if (handshake->ecrs_peer_cert != NULL) { + mbedtls_x509_crt_free(handshake->ecrs_peer_cert); + mbedtls_free(handshake->ecrs_peer_cert); } +#endif - return 0xFFFFFFFF; -} - -const char *mbedtls_ssl_get_ciphersuite(const mbedtls_ssl_context *ssl) -{ - if (ssl == NULL || ssl->session == NULL) { - return NULL; - } +#if defined(MBEDTLS_X509_CRT_PARSE_C) && \ + !defined(MBEDTLS_SSL_KEEP_PEER_CERTIFICATE) + mbedtls_pk_free(&handshake->peer_pubkey); +#endif /* MBEDTLS_X509_CRT_PARSE_C && !MBEDTLS_SSL_KEEP_PEER_CERTIFICATE */ - return mbedtls_ssl_get_ciphersuite_name(ssl->session->ciphersuite); -} +#if defined(MBEDTLS_SSL_CLI_C) && \ + (defined(MBEDTLS_SSL_PROTO_DTLS) || defined(MBEDTLS_SSL_PROTO_TLS1_3)) + mbedtls_free(handshake->cookie); +#endif /* MBEDTLS_SSL_CLI_C && + ( MBEDTLS_SSL_PROTO_DTLS || MBEDTLS_SSL_PROTO_TLS1_3 ) */ -const char *mbedtls_ssl_get_version(const mbedtls_ssl_context *ssl) -{ #if defined(MBEDTLS_SSL_PROTO_DTLS) - if (ssl->conf->transport == MBEDTLS_SSL_TRANSPORT_DATAGRAM) { - switch (ssl->minor_ver) { - case MBEDTLS_SSL_MINOR_VERSION_2: - return "DTLSv1.0"; - - case MBEDTLS_SSL_MINOR_VERSION_3: - return "DTLSv1.2"; + mbedtls_ssl_flight_free(handshake->flight); + mbedtls_ssl_buffering_free(ssl); +#endif /* MBEDTLS_SSL_PROTO_DTLS */ - default: - return "unknown (DTLS)"; - } +#if defined(MBEDTLS_KEY_EXCHANGE_SOME_XXDH_PSA_ANY_ENABLED) + if (handshake->xxdh_psa_privkey_is_external == 0) { + psa_destroy_key(handshake->xxdh_psa_privkey); } -#endif +#endif /* MBEDTLS_KEY_EXCHANGE_SOME_XXDH_PSA_ANY_ENABLED */ - switch (ssl->minor_ver) { - case MBEDTLS_SSL_MINOR_VERSION_0: - return "SSLv3.0"; - - case MBEDTLS_SSL_MINOR_VERSION_1: - return "TLSv1.0"; +#if defined(MBEDTLS_SSL_PROTO_TLS1_3) + mbedtls_ssl_transform_free(handshake->transform_handshake); + mbedtls_free(handshake->transform_handshake); +#if defined(MBEDTLS_SSL_EARLY_DATA) + mbedtls_ssl_transform_free(handshake->transform_earlydata); + mbedtls_free(handshake->transform_earlydata); +#endif +#endif /* MBEDTLS_SSL_PROTO_TLS1_3 */ - case MBEDTLS_SSL_MINOR_VERSION_2: - return "TLSv1.1"; - case MBEDTLS_SSL_MINOR_VERSION_3: - return "TLSv1.2"; +#if defined(MBEDTLS_SSL_VARIABLE_BUFFER_LENGTH) + /* If the buffers are too big - reallocate. Because of the way Mbed TLS + * processes datagrams and the fact that a datagram is allowed to have + * several records in it, it is possible that the I/O buffers are not + * empty at this stage */ + handle_buffer_resizing(ssl, 1, mbedtls_ssl_get_input_buflen(ssl), + mbedtls_ssl_get_output_buflen(ssl)); +#endif - default: - return "unknown"; - } + /* mbedtls_platform_zeroize MUST be last one in this function */ + mbedtls_platform_zeroize(handshake, + sizeof(mbedtls_ssl_handshake_params)); } -#if defined(MBEDTLS_SSL_MAX_FRAGMENT_LENGTH) -size_t mbedtls_ssl_get_input_max_frag_len(const mbedtls_ssl_context *ssl) +void mbedtls_ssl_session_free(mbedtls_ssl_session *session) { - size_t max_len = MBEDTLS_SSL_MAX_CONTENT_LEN; - size_t read_mfl; - - /* Use the configured MFL for the client if we're past SERVER_HELLO_DONE */ - if (ssl->conf->endpoint == MBEDTLS_SSL_IS_CLIENT && - ssl->state >= MBEDTLS_SSL_SERVER_HELLO_DONE) { - return ssl_mfl_code_to_length(ssl->conf->mfl_code); + if (session == NULL) { + return; } - /* Check if a smaller max length was negotiated */ - if (ssl->session_out != NULL) { - read_mfl = ssl_mfl_code_to_length(ssl->session_out->mfl_code); - if (read_mfl < max_len) { - max_len = read_mfl; - } - } +#if defined(MBEDTLS_X509_CRT_PARSE_C) + ssl_clear_peer_cert(session); +#endif - // During a handshake, use the value being negotiated - if (ssl->session_negotiate != NULL) { - read_mfl = ssl_mfl_code_to_length(ssl->session_negotiate->mfl_code); - if (read_mfl < max_len) { - max_len = read_mfl; - } - } +#if defined(MBEDTLS_SSL_SESSION_TICKETS) && defined(MBEDTLS_SSL_CLI_C) +#if defined(MBEDTLS_SSL_PROTO_TLS1_3) && \ + defined(MBEDTLS_SSL_SERVER_NAME_INDICATION) + mbedtls_free(session->hostname); +#endif + mbedtls_free(session->ticket); +#endif - return max_len; +#if defined(MBEDTLS_SSL_EARLY_DATA) && defined(MBEDTLS_SSL_ALPN) && \ + defined(MBEDTLS_SSL_SRV_C) + mbedtls_free(session->ticket_alpn); +#endif + + mbedtls_platform_zeroize(session, sizeof(mbedtls_ssl_session)); } -size_t mbedtls_ssl_get_output_max_frag_len(const mbedtls_ssl_context *ssl) -{ - size_t max_len; +#if defined(MBEDTLS_SSL_CONTEXT_SERIALIZATION) - /* - * Assume mfl_code is correct since it was checked when set - */ - max_len = ssl_mfl_code_to_length(ssl->conf->mfl_code); +#if defined(MBEDTLS_SSL_DTLS_CONNECTION_ID) +#define SSL_SERIALIZED_CONTEXT_CONFIG_DTLS_CONNECTION_ID 1u +#else +#define SSL_SERIALIZED_CONTEXT_CONFIG_DTLS_CONNECTION_ID 0u +#endif /* MBEDTLS_SSL_DTLS_CONNECTION_ID */ - /* Check if a smaller max length was negotiated */ - if (ssl->session_out != NULL && - ssl_mfl_code_to_length(ssl->session_out->mfl_code) < max_len) { - max_len = ssl_mfl_code_to_length(ssl->session_out->mfl_code); - } +#define SSL_SERIALIZED_CONTEXT_CONFIG_DTLS_BADMAC_LIMIT 1u - /* During a handshake, use the value being negotiated */ - if (ssl->session_negotiate != NULL && - ssl_mfl_code_to_length(ssl->session_negotiate->mfl_code) < max_len) { - max_len = ssl_mfl_code_to_length(ssl->session_negotiate->mfl_code); - } +#if defined(MBEDTLS_SSL_DTLS_ANTI_REPLAY) +#define SSL_SERIALIZED_CONTEXT_CONFIG_DTLS_ANTI_REPLAY 1u +#else +#define SSL_SERIALIZED_CONTEXT_CONFIG_DTLS_ANTI_REPLAY 0u +#endif /* MBEDTLS_SSL_DTLS_ANTI_REPLAY */ - return max_len; -} +#if defined(MBEDTLS_SSL_ALPN) +#define SSL_SERIALIZED_CONTEXT_CONFIG_ALPN 1u +#else +#define SSL_SERIALIZED_CONTEXT_CONFIG_ALPN 0u +#endif /* MBEDTLS_SSL_ALPN */ -#if !defined(MBEDTLS_DEPRECATED_REMOVED) -size_t mbedtls_ssl_get_max_frag_len(const mbedtls_ssl_context *ssl) -{ - return mbedtls_ssl_get_output_max_frag_len(ssl); -} -#endif /* !MBEDTLS_DEPRECATED_REMOVED */ -#endif /* MBEDTLS_SSL_MAX_FRAGMENT_LENGTH */ +#define SSL_SERIALIZED_CONTEXT_CONFIG_DTLS_CONNECTION_ID_BIT 0 +#define SSL_SERIALIZED_CONTEXT_CONFIG_DTLS_BADMAC_LIMIT_BIT 1 +#define SSL_SERIALIZED_CONTEXT_CONFIG_DTLS_ANTI_REPLAY_BIT 2 +#define SSL_SERIALIZED_CONTEXT_CONFIG_ALPN_BIT 3 -#if defined(MBEDTLS_SSL_PROTO_DTLS) -size_t mbedtls_ssl_get_current_mtu(const mbedtls_ssl_context *ssl) -{ - /* Return unlimited mtu for client hello messages to avoid fragmentation. */ - if (ssl->conf->endpoint == MBEDTLS_SSL_IS_CLIENT && - (ssl->state == MBEDTLS_SSL_CLIENT_HELLO || - ssl->state == MBEDTLS_SSL_SERVER_HELLO)) { - return 0; - } - - if (ssl->handshake == NULL || ssl->handshake->mtu == 0) { - return ssl->mtu; - } - - if (ssl->mtu == 0) { - return ssl->handshake->mtu; - } +#define SSL_SERIALIZED_CONTEXT_CONFIG_BITFLAG \ + ((uint32_t) ( \ + (SSL_SERIALIZED_CONTEXT_CONFIG_DTLS_CONNECTION_ID << \ + SSL_SERIALIZED_CONTEXT_CONFIG_DTLS_CONNECTION_ID_BIT) | \ + (SSL_SERIALIZED_CONTEXT_CONFIG_DTLS_BADMAC_LIMIT << \ + SSL_SERIALIZED_CONTEXT_CONFIG_DTLS_BADMAC_LIMIT_BIT) | \ + (SSL_SERIALIZED_CONTEXT_CONFIG_DTLS_ANTI_REPLAY << \ + SSL_SERIALIZED_CONTEXT_CONFIG_DTLS_ANTI_REPLAY_BIT) | \ + (SSL_SERIALIZED_CONTEXT_CONFIG_ALPN << SSL_SERIALIZED_CONTEXT_CONFIG_ALPN_BIT) | \ + 0u)) - return ssl->mtu < ssl->handshake->mtu ? - ssl->mtu : ssl->handshake->mtu; -} -#endif /* MBEDTLS_SSL_PROTO_DTLS */ +static const unsigned char ssl_serialized_context_header[] = { + MBEDTLS_VERSION_MAJOR, + MBEDTLS_VERSION_MINOR, + MBEDTLS_VERSION_PATCH, + MBEDTLS_BYTE_1(SSL_SERIALIZED_SESSION_CONFIG_BITFLAG), + MBEDTLS_BYTE_0(SSL_SERIALIZED_SESSION_CONFIG_BITFLAG), + MBEDTLS_BYTE_2(SSL_SERIALIZED_CONTEXT_CONFIG_BITFLAG), + MBEDTLS_BYTE_1(SSL_SERIALIZED_CONTEXT_CONFIG_BITFLAG), + MBEDTLS_BYTE_0(SSL_SERIALIZED_CONTEXT_CONFIG_BITFLAG), +}; -int mbedtls_ssl_get_max_out_record_payload(const mbedtls_ssl_context *ssl) +/* + * Serialize a full SSL context + * + * The format of the serialized data is: + * (in the presentation language of TLS, RFC 8446 section 3) + * + * // header + * opaque mbedtls_version[3]; // major, minor, patch + * opaque context_format[5]; // version-specific field determining + * // the format of the remaining + * // serialized data. + * Note: When updating the format, remember to keep these + * version+format bytes. (We may make their size part of the API.) + * + * // session sub-structure + * opaque session<1..2^32-1>; // see mbedtls_ssl_session_save() + * // transform sub-structure + * uint8 random[64]; // ServerHello.random+ClientHello.random + * uint8 in_cid<0..2^8-1> // Connection ID: expected incoming value + * uint8 out_cid<0..2^8-1> // Connection ID: outgoing value to use + * // fields from ssl_context + * uint32 badmac_seen; // DTLS: number of records with failing MAC + * uint64 in_window_top; // DTLS: last validated record seq_num + * uint64 in_window; // DTLS: bitmask for replay protection + * uint8 disable_datagram_packing; // DTLS: only one record per datagram + * uint64 cur_out_ctr; // Record layer: outgoing sequence number + * uint16 mtu; // DTLS: path mtu (max outgoing fragment size) + * uint8 alpn_chosen<0..2^8-1> // ALPN: negotiated application protocol + * + * Note that many fields of the ssl_context or sub-structures are not + * serialized, as they fall in one of the following categories: + * + * 1. forced value (eg in_left must be 0) + * 2. pointer to dynamically-allocated memory (eg session, transform) + * 3. value can be re-derived from other data (eg session keys from MS) + * 4. value was temporary (eg content of input buffer) + * 5. value will be provided by the user again (eg I/O callbacks and context) + */ +int mbedtls_ssl_context_save(mbedtls_ssl_context *ssl, + unsigned char *buf, + size_t buf_len, + size_t *olen) { - size_t max_len = MBEDTLS_SSL_OUT_CONTENT_LEN; + unsigned char *p = buf; + size_t used = 0; + size_t session_len; + int ret = 0; -#if !defined(MBEDTLS_SSL_MAX_FRAGMENT_LENGTH) && \ - !defined(MBEDTLS_SSL_PROTO_DTLS) - (void) ssl; + /* + * Enforce usage restrictions, see "return BAD_INPUT_DATA" in + * this function's documentation. + * + * These are due to assumptions/limitations in the implementation. Some of + * them are likely to stay (no handshake in progress) some might go away + * (only DTLS) but are currently used to simplify the implementation. + */ + /* The initial handshake must be over */ + if (mbedtls_ssl_is_handshake_over(ssl) == 0) { + MBEDTLS_SSL_DEBUG_MSG(1, ("Initial handshake isn't over")); + return MBEDTLS_ERR_SSL_BAD_INPUT_DATA; + } + if (ssl->handshake != NULL) { + MBEDTLS_SSL_DEBUG_MSG(1, ("Handshake isn't completed")); + return MBEDTLS_ERR_SSL_BAD_INPUT_DATA; + } + /* Double-check that sub-structures are indeed ready */ + if (ssl->transform == NULL || ssl->session == NULL) { + MBEDTLS_SSL_DEBUG_MSG(1, ("Serialised structures aren't ready")); + return MBEDTLS_ERR_SSL_BAD_INPUT_DATA; + } + /* There must be no pending incoming or outgoing data */ + if (mbedtls_ssl_check_pending(ssl) != 0) { + MBEDTLS_SSL_DEBUG_MSG(1, ("There is pending incoming data")); + return MBEDTLS_ERR_SSL_BAD_INPUT_DATA; + } + if (ssl->out_left != 0) { + MBEDTLS_SSL_DEBUG_MSG(1, ("There is pending outgoing data")); + return MBEDTLS_ERR_SSL_BAD_INPUT_DATA; + } + /* Protocol must be DTLS, not TLS */ + if (ssl->conf->transport != MBEDTLS_SSL_TRANSPORT_DATAGRAM) { + MBEDTLS_SSL_DEBUG_MSG(1, ("Only DTLS is supported")); + return MBEDTLS_ERR_SSL_BAD_INPUT_DATA; + } + /* Version must be 1.2 */ + if (ssl->tls_version != MBEDTLS_SSL_VERSION_TLS1_2) { + MBEDTLS_SSL_DEBUG_MSG(1, ("Only version 1.2 supported")); + return MBEDTLS_ERR_SSL_BAD_INPUT_DATA; + } + /* We must be using an AEAD ciphersuite */ + if (mbedtls_ssl_transform_uses_aead(ssl->transform) != 1) { + MBEDTLS_SSL_DEBUG_MSG(1, ("Only AEAD ciphersuites supported")); + return MBEDTLS_ERR_SSL_BAD_INPUT_DATA; + } + /* Renegotiation must not be enabled */ +#if defined(MBEDTLS_SSL_RENEGOTIATION) + if (ssl->conf->disable_renegotiation != MBEDTLS_SSL_RENEGOTIATION_DISABLED) { + MBEDTLS_SSL_DEBUG_MSG(1, ("Renegotiation must not be enabled")); + return MBEDTLS_ERR_SSL_BAD_INPUT_DATA; + } #endif -#if defined(MBEDTLS_SSL_MAX_FRAGMENT_LENGTH) - const size_t mfl = mbedtls_ssl_get_output_max_frag_len(ssl); + /* + * Version and format identifier + */ + used += sizeof(ssl_serialized_context_header); - if (max_len > mfl) { - max_len = mfl; + if (used <= buf_len) { + memcpy(p, ssl_serialized_context_header, + sizeof(ssl_serialized_context_header)); + p += sizeof(ssl_serialized_context_header); } -#endif -#if defined(MBEDTLS_SSL_PROTO_DTLS) - if (mbedtls_ssl_get_current_mtu(ssl) != 0) { - const size_t mtu = mbedtls_ssl_get_current_mtu(ssl); - const int ret = mbedtls_ssl_get_record_expansion(ssl); - const size_t overhead = (size_t) ret; + /* + * Session (length + data) + */ + ret = ssl_session_save(ssl->session, 1, NULL, 0, &session_len); + if (ret != MBEDTLS_ERR_SSL_BUFFER_TOO_SMALL) { + return ret; + } - if (ret < 0) { + used += 4 + session_len; + if (used <= buf_len) { + MBEDTLS_PUT_UINT32_BE(session_len, p, 0); + p += 4; + + ret = ssl_session_save(ssl->session, 1, + p, session_len, &session_len); + if (ret != 0) { return ret; } - if (mtu <= overhead) { - MBEDTLS_SSL_DEBUG_MSG(1, ("MTU too low for record expansion")); - return MBEDTLS_ERR_SSL_FEATURE_UNAVAILABLE; - } + p += session_len; + } - if (max_len > mtu - overhead) { - max_len = mtu - overhead; - } + /* + * Transform + */ + used += sizeof(ssl->transform->randbytes); + if (used <= buf_len) { + memcpy(p, ssl->transform->randbytes, + sizeof(ssl->transform->randbytes)); + p += sizeof(ssl->transform->randbytes); } -#endif /* MBEDTLS_SSL_PROTO_DTLS */ -#if !defined(MBEDTLS_SSL_MAX_FRAGMENT_LENGTH) && \ - !defined(MBEDTLS_SSL_PROTO_DTLS) - ((void) ssl); -#endif +#if defined(MBEDTLS_SSL_DTLS_CONNECTION_ID) + used += 2U + ssl->transform->in_cid_len + ssl->transform->out_cid_len; + if (used <= buf_len) { + *p++ = ssl->transform->in_cid_len; + memcpy(p, ssl->transform->in_cid, ssl->transform->in_cid_len); + p += ssl->transform->in_cid_len; - return (int) max_len; -} + *p++ = ssl->transform->out_cid_len; + memcpy(p, ssl->transform->out_cid, ssl->transform->out_cid_len); + p += ssl->transform->out_cid_len; + } +#endif /* MBEDTLS_SSL_DTLS_CONNECTION_ID */ -#if defined(MBEDTLS_X509_CRT_PARSE_C) -const mbedtls_x509_crt *mbedtls_ssl_get_peer_cert(const mbedtls_ssl_context *ssl) -{ - if (ssl == NULL || ssl->session == NULL) { - return NULL; + /* + * Saved fields from top-level ssl_context structure + */ + used += 4; + if (used <= buf_len) { + MBEDTLS_PUT_UINT32_BE(ssl->badmac_seen, p, 0); + p += 4; } -#if defined(MBEDTLS_SSL_KEEP_PEER_CERTIFICATE) - return ssl->session->peer_cert; -#else - return NULL; -#endif /* MBEDTLS_SSL_KEEP_PEER_CERTIFICATE */ -} -#endif /* MBEDTLS_X509_CRT_PARSE_C */ +#if defined(MBEDTLS_SSL_DTLS_ANTI_REPLAY) + used += 16; + if (used <= buf_len) { + MBEDTLS_PUT_UINT64_BE(ssl->in_window_top, p, 0); + p += 8; -#if defined(MBEDTLS_SSL_CLI_C) -int mbedtls_ssl_get_session(const mbedtls_ssl_context *ssl, - mbedtls_ssl_session *dst) -{ - if (ssl == NULL || - dst == NULL || - ssl->session == NULL || - ssl->conf->endpoint != MBEDTLS_SSL_IS_CLIENT) { - return MBEDTLS_ERR_SSL_BAD_INPUT_DATA; + MBEDTLS_PUT_UINT64_BE(ssl->in_window, p, 0); + p += 8; } +#endif /* MBEDTLS_SSL_DTLS_ANTI_REPLAY */ - return mbedtls_ssl_session_copy(dst, ssl->session); -} -#endif /* MBEDTLS_SSL_CLI_C */ +#if defined(MBEDTLS_SSL_PROTO_DTLS) + used += 1; + if (used <= buf_len) { + *p++ = ssl->disable_datagram_packing; + } +#endif /* MBEDTLS_SSL_PROTO_DTLS */ -const mbedtls_ssl_session *mbedtls_ssl_get_session_pointer(const mbedtls_ssl_context *ssl) -{ - if (ssl == NULL) { - return NULL; + used += MBEDTLS_SSL_SEQUENCE_NUMBER_LEN; + if (used <= buf_len) { + memcpy(p, ssl->cur_out_ctr, MBEDTLS_SSL_SEQUENCE_NUMBER_LEN); + p += MBEDTLS_SSL_SEQUENCE_NUMBER_LEN; } - return ssl->session; -} +#if defined(MBEDTLS_SSL_PROTO_DTLS) + used += 2; + if (used <= buf_len) { + MBEDTLS_PUT_UINT16_BE(ssl->mtu, p, 0); + p += 2; + } +#endif /* MBEDTLS_SSL_PROTO_DTLS */ -/* - * Define ticket header determining Mbed TLS version - * and structure of the ticket. - */ - -/* - * Define bitflag determining compile-time settings influencing - * structure of serialized SSL sessions. - */ - -#if defined(MBEDTLS_HAVE_TIME) -#define SSL_SERIALIZED_SESSION_CONFIG_TIME 1 -#else -#define SSL_SERIALIZED_SESSION_CONFIG_TIME 0 -#endif /* MBEDTLS_HAVE_TIME */ - -#if defined(MBEDTLS_X509_CRT_PARSE_C) -#define SSL_SERIALIZED_SESSION_CONFIG_CRT 1 -#else -#define SSL_SERIALIZED_SESSION_CONFIG_CRT 0 -#endif /* MBEDTLS_X509_CRT_PARSE_C */ - -#if defined(MBEDTLS_SSL_CLI_C) && defined(MBEDTLS_SSL_SESSION_TICKETS) -#define SSL_SERIALIZED_SESSION_CONFIG_CLIENT_TICKET 1 -#else -#define SSL_SERIALIZED_SESSION_CONFIG_CLIENT_TICKET 0 -#endif /* MBEDTLS_SSL_CLI_C && MBEDTLS_SSL_SESSION_TICKETS */ - -#if defined(MBEDTLS_SSL_MAX_FRAGMENT_LENGTH) -#define SSL_SERIALIZED_SESSION_CONFIG_MFL 1 -#else -#define SSL_SERIALIZED_SESSION_CONFIG_MFL 0 -#endif /* MBEDTLS_SSL_MAX_FRAGMENT_LENGTH */ +#if defined(MBEDTLS_SSL_ALPN) + { + const uint8_t alpn_len = ssl->alpn_chosen + ? (uint8_t) strlen(ssl->alpn_chosen) + : 0; -#if defined(MBEDTLS_SSL_TRUNCATED_HMAC) -#define SSL_SERIALIZED_SESSION_CONFIG_TRUNC_HMAC 1 -#else -#define SSL_SERIALIZED_SESSION_CONFIG_TRUNC_HMAC 0 -#endif /* MBEDTLS_SSL_TRUNCATED_HMAC */ + used += 1 + alpn_len; + if (used <= buf_len) { + *p++ = alpn_len; -#if defined(MBEDTLS_SSL_ENCRYPT_THEN_MAC) -#define SSL_SERIALIZED_SESSION_CONFIG_ETM 1 -#else -#define SSL_SERIALIZED_SESSION_CONFIG_ETM 0 -#endif /* MBEDTLS_SSL_ENCRYPT_THEN_MAC */ + if (ssl->alpn_chosen != NULL) { + memcpy(p, ssl->alpn_chosen, alpn_len); + p += alpn_len; + } + } + } +#endif /* MBEDTLS_SSL_ALPN */ -#if defined(MBEDTLS_SSL_SESSION_TICKETS) -#define SSL_SERIALIZED_SESSION_CONFIG_TICKET 1 -#else -#define SSL_SERIALIZED_SESSION_CONFIG_TICKET 0 -#endif /* MBEDTLS_SSL_SESSION_TICKETS */ + /* + * Done + */ + *olen = used; -#define SSL_SERIALIZED_SESSION_CONFIG_TIME_BIT 0 -#define SSL_SERIALIZED_SESSION_CONFIG_CRT_BIT 1 -#define SSL_SERIALIZED_SESSION_CONFIG_CLIENT_TICKET_BIT 2 -#define SSL_SERIALIZED_SESSION_CONFIG_MFL_BIT 3 -#define SSL_SERIALIZED_SESSION_CONFIG_TRUNC_HMAC_BIT 4 -#define SSL_SERIALIZED_SESSION_CONFIG_ETM_BIT 5 -#define SSL_SERIALIZED_SESSION_CONFIG_TICKET_BIT 6 + if (used > buf_len) { + return MBEDTLS_ERR_SSL_BUFFER_TOO_SMALL; + } -#define SSL_SERIALIZED_SESSION_CONFIG_BITFLAG \ - ((uint16_t) ( \ - (SSL_SERIALIZED_SESSION_CONFIG_TIME << SSL_SERIALIZED_SESSION_CONFIG_TIME_BIT) | \ - (SSL_SERIALIZED_SESSION_CONFIG_CRT << SSL_SERIALIZED_SESSION_CONFIG_CRT_BIT) | \ - (SSL_SERIALIZED_SESSION_CONFIG_CLIENT_TICKET << \ - SSL_SERIALIZED_SESSION_CONFIG_CLIENT_TICKET_BIT) | \ - (SSL_SERIALIZED_SESSION_CONFIG_MFL << SSL_SERIALIZED_SESSION_CONFIG_MFL_BIT) | \ - (SSL_SERIALIZED_SESSION_CONFIG_TRUNC_HMAC << \ - SSL_SERIALIZED_SESSION_CONFIG_TRUNC_HMAC_BIT) | \ - (SSL_SERIALIZED_SESSION_CONFIG_ETM << SSL_SERIALIZED_SESSION_CONFIG_ETM_BIT) | \ - (SSL_SERIALIZED_SESSION_CONFIG_TICKET << SSL_SERIALIZED_SESSION_CONFIG_TICKET_BIT))) + MBEDTLS_SSL_DEBUG_BUF(4, "saved context", buf, used); -static unsigned char ssl_serialized_session_header[] = { - MBEDTLS_VERSION_MAJOR, - MBEDTLS_VERSION_MINOR, - MBEDTLS_VERSION_PATCH, - MBEDTLS_BYTE_1(SSL_SERIALIZED_SESSION_CONFIG_BITFLAG), - MBEDTLS_BYTE_0(SSL_SERIALIZED_SESSION_CONFIG_BITFLAG), -}; + return mbedtls_ssl_session_reset_int(ssl, 0); +} /* - * Serialize a session in the following format: - * (in the presentation language of TLS, RFC 8446 section 3) - * - * opaque mbedtls_version[3]; // major, minor, patch - * opaque session_format[2]; // version-specific 16-bit field determining - * // the format of the remaining - * // serialized data. - * - * Note: When updating the format, remember to keep - * these version+format bytes. - * - * // In this version, `session_format` determines - * // the setting of those compile-time - * // configuration options which influence - * // the structure of mbedtls_ssl_session. - * uint64 start_time; - * uint8 ciphersuite[2]; // defined by the standard - * uint8 compression; // 0 or 1 - * uint8 session_id_len; // at most 32 - * opaque session_id[32]; - * opaque master[48]; // fixed length in the standard - * uint32 verify_result; - * opaque peer_cert<0..2^24-1>; // length 0 means no peer cert - * opaque ticket<0..2^24-1>; // length 0 means no ticket - * uint32 ticket_lifetime; - * uint8 mfl_code; // up to 255 according to standard - * uint8 trunc_hmac; // 0 or 1 - * uint8 encrypt_then_mac; // 0 or 1 + * Deserialize context, see mbedtls_ssl_context_save() for format. * - * The order is the same as in the definition of the structure, except - * verify_result is put before peer_cert so that all mandatory fields come - * together in one block. + * This internal version is wrapped by a public function that cleans up in + * case of error. */ MBEDTLS_CHECK_RETURN_CRITICAL -static int ssl_session_save(const mbedtls_ssl_session *session, - unsigned char omit_header, - unsigned char *buf, - size_t buf_len, - size_t *olen) +static int ssl_context_load(mbedtls_ssl_context *ssl, + const unsigned char *buf, + size_t len) { - unsigned char *p = buf; - size_t used = 0; -#if defined(MBEDTLS_HAVE_TIME) - uint64_t start; + const unsigned char *p = buf; + const unsigned char * const end = buf + len; + size_t session_len; + int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED; +#if defined(MBEDTLS_SSL_PROTO_TLS1_2) + tls_prf_fn prf_func = NULL; #endif -#if defined(MBEDTLS_X509_CRT_PARSE_C) -#if defined(MBEDTLS_SSL_KEEP_PEER_CERTIFICATE) - size_t cert_len; -#endif /* MBEDTLS_SSL_KEEP_PEER_CERTIFICATE */ -#endif /* MBEDTLS_X509_CRT_PARSE_C */ - - - if (!omit_header) { - /* - * Add version identifier - */ - - used += sizeof(ssl_serialized_session_header); - - if (used <= buf_len) { - memcpy(p, ssl_serialized_session_header, - sizeof(ssl_serialized_session_header)); - p += sizeof(ssl_serialized_session_header); - } - } /* - * Time + * The context should have been freshly setup or reset. + * Give the user an error in case of obvious misuse. + * (Checking session is useful because it won't be NULL if we're + * renegotiating, or if the user mistakenly loaded a session first.) */ -#if defined(MBEDTLS_HAVE_TIME) - used += 8; - - if (used <= buf_len) { - start = (uint64_t) session->start; - - MBEDTLS_PUT_UINT64_BE(start, p, 0); - p += 8; + if (ssl->state != MBEDTLS_SSL_HELLO_REQUEST || + ssl->session != NULL) { + return MBEDTLS_ERR_SSL_BAD_INPUT_DATA; } -#endif /* MBEDTLS_HAVE_TIME */ /* - * Basic mandatory fields + * We can't check that the config matches the initial one, but we can at + * least check it matches the requirements for serializing. */ - used += 2 /* ciphersuite */ - + 1 /* compression */ - + 1 /* id_len */ - + sizeof(session->id) - + sizeof(session->master) - + 4; /* verify_result */ - - if (used <= buf_len) { - MBEDTLS_PUT_UINT16_BE(session->ciphersuite, p, 0); - p += 2; - - *p++ = MBEDTLS_BYTE_0(session->compression); + if ( +#if defined(MBEDTLS_SSL_RENEGOTIATION) + ssl->conf->disable_renegotiation != MBEDTLS_SSL_RENEGOTIATION_DISABLED || +#endif + ssl->conf->transport != MBEDTLS_SSL_TRANSPORT_DATAGRAM || + ssl->conf->max_tls_version < MBEDTLS_SSL_VERSION_TLS1_2 || + ssl->conf->min_tls_version > MBEDTLS_SSL_VERSION_TLS1_2 + ) { + return MBEDTLS_ERR_SSL_BAD_INPUT_DATA; + } - *p++ = MBEDTLS_BYTE_0(session->id_len); - memcpy(p, session->id, 32); - p += 32; + MBEDTLS_SSL_DEBUG_BUF(4, "context to load", buf, len); - memcpy(p, session->master, 48); - p += 48; + /* + * Check version identifier + */ + if ((size_t) (end - p) < sizeof(ssl_serialized_context_header)) { + return MBEDTLS_ERR_SSL_BAD_INPUT_DATA; + } - MBEDTLS_PUT_UINT32_BE(session->verify_result, p, 0); - p += 4; + if (memcmp(p, ssl_serialized_context_header, + sizeof(ssl_serialized_context_header)) != 0) { + return MBEDTLS_ERR_SSL_VERSION_MISMATCH; } + p += sizeof(ssl_serialized_context_header); /* - * Peer's end-entity certificate + * Session */ -#if defined(MBEDTLS_X509_CRT_PARSE_C) -#if defined(MBEDTLS_SSL_KEEP_PEER_CERTIFICATE) - if (session->peer_cert == NULL) { - cert_len = 0; - } else { - cert_len = session->peer_cert->raw.len; + if ((size_t) (end - p) < 4) { + return MBEDTLS_ERR_SSL_BAD_INPUT_DATA; } - used += 3 + cert_len; + session_len = MBEDTLS_GET_UINT32_BE(p, 0); + p += 4; - if (used <= buf_len) { - *p++ = MBEDTLS_BYTE_2(cert_len); - *p++ = MBEDTLS_BYTE_1(cert_len); - *p++ = MBEDTLS_BYTE_0(cert_len); + /* This has been allocated by ssl_handshake_init(), called by + * by either mbedtls_ssl_session_reset_int() or mbedtls_ssl_setup(). */ + ssl->session = ssl->session_negotiate; + ssl->session_in = ssl->session; + ssl->session_out = ssl->session; + ssl->session_negotiate = NULL; - if (session->peer_cert != NULL) { - memcpy(p, session->peer_cert->raw.p, cert_len); - p += cert_len; - } + if ((size_t) (end - p) < session_len) { + return MBEDTLS_ERR_SSL_BAD_INPUT_DATA; } -#else /* MBEDTLS_SSL_KEEP_PEER_CERTIFICATE */ - if (session->peer_cert_digest != NULL) { - used += 1 /* type */ + 1 /* length */ + session->peer_cert_digest_len; - if (used <= buf_len) { - *p++ = (unsigned char) session->peer_cert_digest_type; - *p++ = (unsigned char) session->peer_cert_digest_len; - memcpy(p, session->peer_cert_digest, - session->peer_cert_digest_len); - p += session->peer_cert_digest_len; - } - } else { - used += 2; - if (used <= buf_len) { - *p++ = (unsigned char) MBEDTLS_MD_NONE; - *p++ = 0; - } + + ret = ssl_session_load(ssl->session, 1, p, session_len); + if (ret != 0) { + mbedtls_ssl_session_free(ssl->session); + return ret; } -#endif /* !MBEDTLS_SSL_KEEP_PEER_CERTIFICATE */ -#endif /* MBEDTLS_X509_CRT_PARSE_C */ + + p += session_len; /* - * Session ticket if any, plus associated data + * Transform */ -#if defined(MBEDTLS_SSL_SESSION_TICKETS) && defined(MBEDTLS_SSL_CLI_C) - used += 3 + session->ticket_len + 4; /* len + ticket + lifetime */ - - if (used <= buf_len) { - *p++ = MBEDTLS_BYTE_2(session->ticket_len); - *p++ = MBEDTLS_BYTE_1(session->ticket_len); - *p++ = MBEDTLS_BYTE_0(session->ticket_len); - if (session->ticket != NULL) { - memcpy(p, session->ticket, session->ticket_len); - p += session->ticket_len; - } + /* This has been allocated by ssl_handshake_init(), called by + * by either mbedtls_ssl_session_reset_int() or mbedtls_ssl_setup(). */ +#if defined(MBEDTLS_SSL_PROTO_TLS1_2) + ssl->transform = ssl->transform_negotiate; + ssl->transform_in = ssl->transform; + ssl->transform_out = ssl->transform; + ssl->transform_negotiate = NULL; +#endif - MBEDTLS_PUT_UINT32_BE(session->ticket_lifetime, p, 0); - p += 4; +#if defined(MBEDTLS_SSL_PROTO_TLS1_2) + prf_func = ssl_tls12prf_from_cs(ssl->session->ciphersuite); + if (prf_func == NULL) { + return MBEDTLS_ERR_SSL_BAD_INPUT_DATA; } -#endif /* MBEDTLS_SSL_SESSION_TICKETS && MBEDTLS_SSL_CLI_C */ - - /* - * Misc extension-related info - */ -#if defined(MBEDTLS_SSL_MAX_FRAGMENT_LENGTH) - used += 1; - if (used <= buf_len) { - *p++ = session->mfl_code; + /* Read random bytes and populate structure */ + if ((size_t) (end - p) < sizeof(ssl->transform->randbytes)) { + return MBEDTLS_ERR_SSL_BAD_INPUT_DATA; } -#endif - -#if defined(MBEDTLS_SSL_TRUNCATED_HMAC) - used += 1; - if (used <= buf_len) { - *p++ = (unsigned char) ((session->trunc_hmac) & 0xFF); + ret = ssl_tls12_populate_transform(ssl->transform, + ssl->session->ciphersuite, + ssl->session->master, +#if defined(MBEDTLS_SSL_SOME_SUITES_USE_CBC_ETM) + ssl->session->encrypt_then_mac, +#endif /* MBEDTLS_SSL_SOME_SUITES_USE_CBC_ETM */ + prf_func, + p, /* currently pointing to randbytes */ + MBEDTLS_SSL_VERSION_TLS1_2, /* (D)TLS 1.2 is forced */ + ssl->conf->endpoint, + ssl); + if (ret != 0) { + return ret; } -#endif - -#if defined(MBEDTLS_SSL_ENCRYPT_THEN_MAC) - used += 1; +#endif /* MBEDTLS_SSL_PROTO_TLS1_2 */ + p += sizeof(ssl->transform->randbytes); - if (used <= buf_len) { - *p++ = MBEDTLS_BYTE_0(session->encrypt_then_mac); +#if defined(MBEDTLS_SSL_DTLS_CONNECTION_ID) + /* Read connection IDs and store them */ + if ((size_t) (end - p) < 1) { + return MBEDTLS_ERR_SSL_BAD_INPUT_DATA; } -#endif - /* Done */ - *olen = used; + ssl->transform->in_cid_len = *p++; - if (used > buf_len) { - return MBEDTLS_ERR_SSL_BUFFER_TOO_SMALL; + if ((size_t) (end - p) < ssl->transform->in_cid_len + 1u) { + return MBEDTLS_ERR_SSL_BAD_INPUT_DATA; } - return 0; -} - -/* - * Public wrapper for ssl_session_save() - */ -int mbedtls_ssl_session_save(const mbedtls_ssl_session *session, - unsigned char *buf, - size_t buf_len, - size_t *olen) -{ - return ssl_session_save(session, 0, buf, buf_len, olen); -} - -/* - * Deserialize session, see mbedtls_ssl_session_save() for format. - * - * This internal version is wrapped by a public function that cleans up in - * case of error, and has an extra option omit_header. - */ -MBEDTLS_CHECK_RETURN_CRITICAL -static int ssl_session_load(mbedtls_ssl_session *session, - unsigned char omit_header, - const unsigned char *buf, - size_t len) -{ - const unsigned char *p = buf; - const unsigned char * const end = buf + len; -#if defined(MBEDTLS_HAVE_TIME) - uint64_t start; -#endif -#if defined(MBEDTLS_X509_CRT_PARSE_C) -#if defined(MBEDTLS_SSL_KEEP_PEER_CERTIFICATE) - size_t cert_len; -#endif /* MBEDTLS_SSL_KEEP_PEER_CERTIFICATE */ -#endif /* MBEDTLS_X509_CRT_PARSE_C */ - - if (!omit_header) { - /* - * Check version identifier - */ + memcpy(ssl->transform->in_cid, p, ssl->transform->in_cid_len); + p += ssl->transform->in_cid_len; - if ((size_t) (end - p) < sizeof(ssl_serialized_session_header)) { - return MBEDTLS_ERR_SSL_BAD_INPUT_DATA; - } + ssl->transform->out_cid_len = *p++; - if (memcmp(p, ssl_serialized_session_header, - sizeof(ssl_serialized_session_header)) != 0) { - return MBEDTLS_ERR_SSL_VERSION_MISMATCH; - } - p += sizeof(ssl_serialized_session_header); + if ((size_t) (end - p) < ssl->transform->out_cid_len) { + return MBEDTLS_ERR_SSL_BAD_INPUT_DATA; } + memcpy(ssl->transform->out_cid, p, ssl->transform->out_cid_len); + p += ssl->transform->out_cid_len; +#endif /* MBEDTLS_SSL_DTLS_CONNECTION_ID */ + /* - * Time + * Saved fields from top-level ssl_context structure */ -#if defined(MBEDTLS_HAVE_TIME) - if (8 > (size_t) (end - p)) { + if ((size_t) (end - p) < 4) { return MBEDTLS_ERR_SSL_BAD_INPUT_DATA; } - start = ((uint64_t) p[0] << 56) | - ((uint64_t) p[1] << 48) | - ((uint64_t) p[2] << 40) | - ((uint64_t) p[3] << 32) | - ((uint64_t) p[4] << 24) | - ((uint64_t) p[5] << 16) | - ((uint64_t) p[6] << 8) | - ((uint64_t) p[7]); - p += 8; - - session->start = (time_t) start; -#endif /* MBEDTLS_HAVE_TIME */ + ssl->badmac_seen = MBEDTLS_GET_UINT32_BE(p, 0); + p += 4; - /* - * Basic mandatory fields - */ - if (2 + 1 + 1 + 32 + 48 + 4 > (size_t) (end - p)) { +#if defined(MBEDTLS_SSL_DTLS_ANTI_REPLAY) + if ((size_t) (end - p) < 16) { return MBEDTLS_ERR_SSL_BAD_INPUT_DATA; } - session->ciphersuite = (p[0] << 8) | p[1]; - p += 2; - - session->compression = *p++; + ssl->in_window_top = MBEDTLS_GET_UINT64_BE(p, 0); + p += 8; - session->id_len = *p++; - memcpy(session->id, p, 32); - p += 32; + ssl->in_window = MBEDTLS_GET_UINT64_BE(p, 0); + p += 8; +#endif /* MBEDTLS_SSL_DTLS_ANTI_REPLAY */ - memcpy(session->master, p, 48); - p += 48; +#if defined(MBEDTLS_SSL_PROTO_DTLS) + if ((size_t) (end - p) < 1) { + return MBEDTLS_ERR_SSL_BAD_INPUT_DATA; + } - session->verify_result = ((uint32_t) p[0] << 24) | - ((uint32_t) p[1] << 16) | - ((uint32_t) p[2] << 8) | - ((uint32_t) p[3]); - p += 4; + ssl->disable_datagram_packing = *p++; +#endif /* MBEDTLS_SSL_PROTO_DTLS */ - /* Immediately clear invalid pointer values that have been read, in case - * we exit early before we replaced them with valid ones. */ -#if defined(MBEDTLS_X509_CRT_PARSE_C) -#if defined(MBEDTLS_SSL_KEEP_PEER_CERTIFICATE) - session->peer_cert = NULL; -#else - session->peer_cert_digest = NULL; -#endif /* !MBEDTLS_SSL_KEEP_PEER_CERTIFICATE */ -#endif /* MBEDTLS_X509_CRT_PARSE_C */ -#if defined(MBEDTLS_SSL_SESSION_TICKETS) && defined(MBEDTLS_SSL_CLI_C) - session->ticket = NULL; -#endif /* MBEDTLS_SSL_SESSION_TICKETS && MBEDTLS_SSL_CLI_C */ + if ((size_t) (end - p) < sizeof(ssl->cur_out_ctr)) { + return MBEDTLS_ERR_SSL_BAD_INPUT_DATA; + } + memcpy(ssl->cur_out_ctr, p, sizeof(ssl->cur_out_ctr)); + p += sizeof(ssl->cur_out_ctr); - /* - * Peer certificate - */ -#if defined(MBEDTLS_X509_CRT_PARSE_C) -#if defined(MBEDTLS_SSL_KEEP_PEER_CERTIFICATE) - /* Deserialize CRT from the end of the ticket. */ - if (3 > (size_t) (end - p)) { +#if defined(MBEDTLS_SSL_PROTO_DTLS) + if ((size_t) (end - p) < 2) { return MBEDTLS_ERR_SSL_BAD_INPUT_DATA; } - cert_len = (p[0] << 16) | (p[1] << 8) | p[2]; - p += 3; + ssl->mtu = MBEDTLS_GET_UINT16_BE(p, 0); + p += 2; +#endif /* MBEDTLS_SSL_PROTO_DTLS */ - if (cert_len != 0) { - int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED; +#if defined(MBEDTLS_SSL_ALPN) + { + uint8_t alpn_len; + const char **cur; - if (cert_len > (size_t) (end - p)) { + if ((size_t) (end - p) < 1) { return MBEDTLS_ERR_SSL_BAD_INPUT_DATA; } - session->peer_cert = mbedtls_calloc(1, sizeof(mbedtls_x509_crt)); + alpn_len = *p++; - if (session->peer_cert == NULL) { - return MBEDTLS_ERR_SSL_ALLOC_FAILED; + if (alpn_len != 0 && ssl->conf->alpn_list != NULL) { + /* alpn_chosen should point to an item in the configured list */ + for (cur = ssl->conf->alpn_list; *cur != NULL; cur++) { + if (strlen(*cur) == alpn_len && + memcmp(p, *cur, alpn_len) == 0) { + ssl->alpn_chosen = *cur; + break; + } + } } - mbedtls_x509_crt_init(session->peer_cert); - - if ((ret = mbedtls_x509_crt_parse_der(session->peer_cert, - p, cert_len)) != 0) { - mbedtls_x509_crt_free(session->peer_cert); - mbedtls_free(session->peer_cert); - session->peer_cert = NULL; - return ret; + /* can only happen on conf mismatch */ + if (alpn_len != 0 && ssl->alpn_chosen == NULL) { + return MBEDTLS_ERR_SSL_BAD_INPUT_DATA; } - p += cert_len; - } -#else /* MBEDTLS_SSL_KEEP_PEER_CERTIFICATE */ - /* Deserialize CRT digest from the end of the ticket. */ - if (2 > (size_t) (end - p)) { - return MBEDTLS_ERR_SSL_BAD_INPUT_DATA; + p += alpn_len; } +#endif /* MBEDTLS_SSL_ALPN */ - session->peer_cert_digest_type = (mbedtls_md_type_t) *p++; - session->peer_cert_digest_len = (size_t) *p++; - - if (session->peer_cert_digest_len != 0) { - const mbedtls_md_info_t *md_info = - mbedtls_md_info_from_type(session->peer_cert_digest_type); - if (md_info == NULL) { - return MBEDTLS_ERR_SSL_BAD_INPUT_DATA; - } - if (session->peer_cert_digest_len != mbedtls_md_get_size(md_info)) { - return MBEDTLS_ERR_SSL_BAD_INPUT_DATA; - } + /* + * Forced fields from top-level ssl_context structure + * + * Most of them already set to the correct value by mbedtls_ssl_init() and + * mbedtls_ssl_reset(), so we only need to set the remaining ones. + */ + ssl->state = MBEDTLS_SSL_HANDSHAKE_OVER; + ssl->tls_version = MBEDTLS_SSL_VERSION_TLS1_2; - if (session->peer_cert_digest_len > (size_t) (end - p)) { - return MBEDTLS_ERR_SSL_BAD_INPUT_DATA; - } + /* Adjust pointers for header fields of outgoing records to + * the given transform, accounting for explicit IV and CID. */ + mbedtls_ssl_update_out_pointers(ssl, ssl->transform); - session->peer_cert_digest = - mbedtls_calloc(1, session->peer_cert_digest_len); - if (session->peer_cert_digest == NULL) { - return MBEDTLS_ERR_SSL_ALLOC_FAILED; - } +#if defined(MBEDTLS_SSL_PROTO_DTLS) + ssl->in_epoch = 1; +#endif - memcpy(session->peer_cert_digest, p, - session->peer_cert_digest_len); - p += session->peer_cert_digest_len; + /* mbedtls_ssl_reset() leaves the handshake sub-structure allocated, + * which we don't want - otherwise we'd end up freeing the wrong transform + * by calling mbedtls_ssl_handshake_wrapup_free_hs_transform() + * inappropriately. */ + if (ssl->handshake != NULL) { + mbedtls_ssl_handshake_free(ssl); + mbedtls_free(ssl->handshake); + ssl->handshake = NULL; } -#endif /* MBEDTLS_SSL_KEEP_PEER_CERTIFICATE */ -#endif /* MBEDTLS_X509_CRT_PARSE_C */ /* - * Session ticket and associated data + * Done - should have consumed entire buffer */ -#if defined(MBEDTLS_SSL_SESSION_TICKETS) && defined(MBEDTLS_SSL_CLI_C) - if (3 > (size_t) (end - p)) { + if (p != end) { return MBEDTLS_ERR_SSL_BAD_INPUT_DATA; } - session->ticket_len = (p[0] << 16) | (p[1] << 8) | p[2]; - p += 3; - - if (session->ticket_len != 0) { - if (session->ticket_len > (size_t) (end - p)) { - return MBEDTLS_ERR_SSL_BAD_INPUT_DATA; - } - - session->ticket = mbedtls_calloc(1, session->ticket_len); - if (session->ticket == NULL) { - return MBEDTLS_ERR_SSL_ALLOC_FAILED; - } + return 0; +} - memcpy(session->ticket, p, session->ticket_len); - p += session->ticket_len; - } +/* + * Deserialize context: public wrapper for error cleaning + */ +int mbedtls_ssl_context_load(mbedtls_ssl_context *context, + const unsigned char *buf, + size_t len) +{ + int ret = ssl_context_load(context, buf, len); - if (4 > (size_t) (end - p)) { - return MBEDTLS_ERR_SSL_BAD_INPUT_DATA; + if (ret != 0) { + mbedtls_ssl_free(context); } - session->ticket_lifetime = ((uint32_t) p[0] << 24) | - ((uint32_t) p[1] << 16) | - ((uint32_t) p[2] << 8) | - ((uint32_t) p[3]); - p += 4; -#endif /* MBEDTLS_SSL_SESSION_TICKETS && MBEDTLS_SSL_CLI_C */ + return ret; +} +#endif /* MBEDTLS_SSL_CONTEXT_SERIALIZATION */ - /* - * Misc extension-related info - */ -#if defined(MBEDTLS_SSL_MAX_FRAGMENT_LENGTH) - if (1 > (size_t) (end - p)) { - return MBEDTLS_ERR_SSL_BAD_INPUT_DATA; +/* + * Free an SSL context + */ +void mbedtls_ssl_free(mbedtls_ssl_context *ssl) +{ + if (ssl == NULL) { + return; } - session->mfl_code = *p++; + MBEDTLS_SSL_DEBUG_MSG(2, ("=> free")); + + if (ssl->out_buf != NULL) { +#if defined(MBEDTLS_SSL_VARIABLE_BUFFER_LENGTH) + size_t out_buf_len = ssl->out_buf_len; +#else + size_t out_buf_len = MBEDTLS_SSL_OUT_BUFFER_LEN; #endif -#if defined(MBEDTLS_SSL_TRUNCATED_HMAC) - if (1 > (size_t) (end - p)) { - return MBEDTLS_ERR_SSL_BAD_INPUT_DATA; + mbedtls_zeroize_and_free(ssl->out_buf, out_buf_len); + ssl->out_buf = NULL; } - session->trunc_hmac = *p++; + if (ssl->in_buf != NULL) { +#if defined(MBEDTLS_SSL_VARIABLE_BUFFER_LENGTH) + size_t in_buf_len = ssl->in_buf_len; +#else + size_t in_buf_len = MBEDTLS_SSL_IN_BUFFER_LEN; #endif -#if defined(MBEDTLS_SSL_ENCRYPT_THEN_MAC) - if (1 > (size_t) (end - p)) { - return MBEDTLS_ERR_SSL_BAD_INPUT_DATA; + mbedtls_zeroize_and_free(ssl->in_buf, in_buf_len); + ssl->in_buf = NULL; } - session->encrypt_then_mac = *p++; -#endif - - /* Done, should have consumed entire buffer */ - if (p != end) { - return MBEDTLS_ERR_SSL_BAD_INPUT_DATA; + if (ssl->transform) { + mbedtls_ssl_transform_free(ssl->transform); + mbedtls_free(ssl->transform); } - return 0; -} + if (ssl->handshake) { + mbedtls_ssl_handshake_free(ssl); + mbedtls_free(ssl->handshake); -/* - * Deserialize session: public wrapper for error cleaning - */ -int mbedtls_ssl_session_load(mbedtls_ssl_session *session, - const unsigned char *buf, - size_t len) -{ - int ret = ssl_session_load(session, 0, buf, len); +#if defined(MBEDTLS_SSL_PROTO_TLS1_2) + mbedtls_ssl_transform_free(ssl->transform_negotiate); + mbedtls_free(ssl->transform_negotiate); +#endif - if (ret != 0) { - mbedtls_ssl_session_free(session); + mbedtls_ssl_session_free(ssl->session_negotiate); + mbedtls_free(ssl->session_negotiate); } - return ret; -} - -/* - * Perform a single step of the SSL handshake - */ -int mbedtls_ssl_handshake_step(mbedtls_ssl_context *ssl) -{ - int ret = MBEDTLS_ERR_SSL_FEATURE_UNAVAILABLE; +#if defined(MBEDTLS_SSL_PROTO_TLS1_3) + mbedtls_ssl_transform_free(ssl->transform_application); + mbedtls_free(ssl->transform_application); +#endif /* MBEDTLS_SSL_PROTO_TLS1_3 */ - if (ssl == NULL || ssl->conf == NULL) { - return MBEDTLS_ERR_SSL_BAD_INPUT_DATA; + if (ssl->session) { + mbedtls_ssl_session_free(ssl->session); + mbedtls_free(ssl->session); } -#if defined(MBEDTLS_SSL_CLI_C) - if (ssl->conf->endpoint == MBEDTLS_SSL_IS_CLIENT) { - ret = mbedtls_ssl_handshake_client_step(ssl); +#if defined(MBEDTLS_X509_CRT_PARSE_C) + if (ssl->hostname != NULL) { + mbedtls_zeroize_and_free(ssl->hostname, strlen(ssl->hostname)); } #endif -#if defined(MBEDTLS_SSL_SRV_C) - if (ssl->conf->endpoint == MBEDTLS_SSL_IS_SERVER) { - ret = mbedtls_ssl_handshake_server_step(ssl); - } + +#if defined(MBEDTLS_SSL_DTLS_HELLO_VERIFY) && defined(MBEDTLS_SSL_SRV_C) + mbedtls_free(ssl->cli_id); #endif - return ret; + MBEDTLS_SSL_DEBUG_MSG(2, ("<= free")); + + /* Actually clear after last debug message */ + mbedtls_platform_zeroize(ssl, sizeof(mbedtls_ssl_context)); } /* - * Perform the SSL handshake + * Initialize mbedtls_ssl_config */ -int mbedtls_ssl_handshake(mbedtls_ssl_context *ssl) +void mbedtls_ssl_config_init(mbedtls_ssl_config *conf) { - int ret = 0; + memset(conf, 0, sizeof(mbedtls_ssl_config)); +} - /* Sanity checks */ +/* The selection should be the same as mbedtls_x509_crt_profile_default in + * x509_crt.c, plus Montgomery curves for ECDHE. Here, the order matters: + * curves with a lower resource usage come first. + * See the documentation of mbedtls_ssl_conf_curves() for what we promise + * about this list. + */ +static const uint16_t ssl_preset_default_groups[] = { +#if defined(MBEDTLS_ECP_HAVE_CURVE25519) + MBEDTLS_SSL_IANA_TLS_GROUP_X25519, +#endif +#if defined(MBEDTLS_ECP_HAVE_SECP256R1) + MBEDTLS_SSL_IANA_TLS_GROUP_SECP256R1, +#endif +#if defined(MBEDTLS_ECP_HAVE_SECP384R1) + MBEDTLS_SSL_IANA_TLS_GROUP_SECP384R1, +#endif +#if defined(MBEDTLS_ECP_HAVE_CURVE448) + MBEDTLS_SSL_IANA_TLS_GROUP_X448, +#endif +#if defined(MBEDTLS_ECP_HAVE_SECP521R1) + MBEDTLS_SSL_IANA_TLS_GROUP_SECP521R1, +#endif +#if defined(MBEDTLS_ECP_HAVE_BP256R1) + MBEDTLS_SSL_IANA_TLS_GROUP_BP256R1, +#endif +#if defined(MBEDTLS_ECP_HAVE_BP384R1) + MBEDTLS_SSL_IANA_TLS_GROUP_BP384R1, +#endif +#if defined(MBEDTLS_ECP_HAVE_BP512R1) + MBEDTLS_SSL_IANA_TLS_GROUP_BP512R1, +#endif +#if defined(PSA_WANT_ALG_FFDH) + MBEDTLS_SSL_IANA_TLS_GROUP_FFDHE2048, + MBEDTLS_SSL_IANA_TLS_GROUP_FFDHE3072, + MBEDTLS_SSL_IANA_TLS_GROUP_FFDHE4096, + MBEDTLS_SSL_IANA_TLS_GROUP_FFDHE6144, + MBEDTLS_SSL_IANA_TLS_GROUP_FFDHE8192, +#endif + MBEDTLS_SSL_IANA_TLS_GROUP_NONE +}; - if (ssl == NULL || ssl->conf == NULL) { - return MBEDTLS_ERR_SSL_BAD_INPUT_DATA; - } +static const int ssl_preset_suiteb_ciphersuites[] = { + MBEDTLS_TLS_ECDHE_ECDSA_WITH_AES_128_GCM_SHA256, + MBEDTLS_TLS_ECDHE_ECDSA_WITH_AES_256_GCM_SHA384, + 0 +}; -#if defined(MBEDTLS_SSL_PROTO_DTLS) - if (ssl->conf->transport == MBEDTLS_SSL_TRANSPORT_DATAGRAM && - (ssl->f_set_timer == NULL || ssl->f_get_timer == NULL)) { - MBEDTLS_SSL_DEBUG_MSG(1, ("You must use " - "mbedtls_ssl_set_timer_cb() for DTLS")); - return MBEDTLS_ERR_SSL_BAD_INPUT_DATA; - } -#endif /* MBEDTLS_SSL_PROTO_DTLS */ +#if defined(MBEDTLS_SSL_HANDSHAKE_WITH_CERT_ENABLED) - MBEDTLS_SSL_DEBUG_MSG(2, ("=> handshake")); +/* NOTICE: + * For ssl_preset_*_sig_algs and ssl_tls12_preset_*_sig_algs, the following + * rules SHOULD be upheld. + * - No duplicate entries. + * - But if there is a good reason, do not change the order of the algorithms. + * - ssl_tls12_preset* is for TLS 1.2 use only. + * - ssl_preset_* is for TLS 1.3 only or hybrid TLS 1.3/1.2 handshakes. + */ +static const uint16_t ssl_preset_default_sig_algs[] = { - /* Main handshake loop */ - while (ssl->state != MBEDTLS_SSL_HANDSHAKE_OVER) { - ret = mbedtls_ssl_handshake_step(ssl); +#if defined(MBEDTLS_KEY_EXCHANGE_ECDSA_CERT_REQ_ANY_ALLOWED_ENABLED) && \ + defined(MBEDTLS_MD_CAN_SHA256) && \ + defined(PSA_WANT_ECC_SECP_R1_256) + MBEDTLS_TLS1_3_SIG_ECDSA_SECP256R1_SHA256, + // == MBEDTLS_SSL_TLS12_SIG_AND_HASH_ALG(MBEDTLS_SSL_SIG_ECDSA, MBEDTLS_SSL_HASH_SHA256) +#endif - if (ret != 0) { - break; - } - } +#if defined(MBEDTLS_KEY_EXCHANGE_ECDSA_CERT_REQ_ANY_ALLOWED_ENABLED) && \ + defined(MBEDTLS_MD_CAN_SHA384) && \ + defined(PSA_WANT_ECC_SECP_R1_384) + MBEDTLS_TLS1_3_SIG_ECDSA_SECP384R1_SHA384, + // == MBEDTLS_SSL_TLS12_SIG_AND_HASH_ALG(MBEDTLS_SSL_SIG_ECDSA, MBEDTLS_SSL_HASH_SHA384) +#endif - MBEDTLS_SSL_DEBUG_MSG(2, ("<= handshake")); +#if defined(MBEDTLS_KEY_EXCHANGE_ECDSA_CERT_REQ_ANY_ALLOWED_ENABLED) && \ + defined(MBEDTLS_MD_CAN_SHA512) && \ + defined(PSA_WANT_ECC_SECP_R1_521) + MBEDTLS_TLS1_3_SIG_ECDSA_SECP521R1_SHA512, + // == MBEDTLS_SSL_TLS12_SIG_AND_HASH_ALG(MBEDTLS_SSL_SIG_ECDSA, MBEDTLS_SSL_HASH_SHA512) +#endif - return ret; -} +#if defined(MBEDTLS_X509_RSASSA_PSS_SUPPORT) && defined(MBEDTLS_MD_CAN_SHA512) + MBEDTLS_TLS1_3_SIG_RSA_PSS_RSAE_SHA512, +#endif -#if defined(MBEDTLS_SSL_RENEGOTIATION) -#if defined(MBEDTLS_SSL_SRV_C) -/* - * Write HelloRequest to request renegotiation on server - */ -MBEDTLS_CHECK_RETURN_CRITICAL -static int ssl_write_hello_request(mbedtls_ssl_context *ssl) -{ - int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED; +#if defined(MBEDTLS_X509_RSASSA_PSS_SUPPORT) && defined(MBEDTLS_MD_CAN_SHA384) + MBEDTLS_TLS1_3_SIG_RSA_PSS_RSAE_SHA384, +#endif - MBEDTLS_SSL_DEBUG_MSG(2, ("=> write hello request")); +#if defined(MBEDTLS_X509_RSASSA_PSS_SUPPORT) && defined(MBEDTLS_MD_CAN_SHA256) + MBEDTLS_TLS1_3_SIG_RSA_PSS_RSAE_SHA256, +#endif - ssl->out_msglen = 4; - ssl->out_msgtype = MBEDTLS_SSL_MSG_HANDSHAKE; - ssl->out_msg[0] = MBEDTLS_SSL_HS_HELLO_REQUEST; +#if defined(MBEDTLS_RSA_C) && defined(MBEDTLS_MD_CAN_SHA512) + MBEDTLS_TLS1_3_SIG_RSA_PKCS1_SHA512, +#endif /* MBEDTLS_RSA_C && MBEDTLS_MD_CAN_SHA512 */ - if ((ret = mbedtls_ssl_write_handshake_msg(ssl)) != 0) { - MBEDTLS_SSL_DEBUG_RET(1, "mbedtls_ssl_write_handshake_msg", ret); - return ret; - } +#if defined(MBEDTLS_RSA_C) && defined(MBEDTLS_MD_CAN_SHA384) + MBEDTLS_TLS1_3_SIG_RSA_PKCS1_SHA384, +#endif /* MBEDTLS_RSA_C && MBEDTLS_MD_CAN_SHA384 */ - MBEDTLS_SSL_DEBUG_MSG(2, ("<= write hello request")); +#if defined(MBEDTLS_RSA_C) && defined(MBEDTLS_MD_CAN_SHA256) + MBEDTLS_TLS1_3_SIG_RSA_PKCS1_SHA256, +#endif /* MBEDTLS_RSA_C && MBEDTLS_MD_CAN_SHA256 */ - return 0; -} -#endif /* MBEDTLS_SSL_SRV_C */ + MBEDTLS_TLS_SIG_NONE +}; -/* - * Actually renegotiate current connection, triggered by either: - * - any side: calling mbedtls_ssl_renegotiate(), - * - client: receiving a HelloRequest during mbedtls_ssl_read(), - * - server: receiving any handshake message on server during mbedtls_ssl_read() after - * the initial handshake is completed. - * If the handshake doesn't complete due to waiting for I/O, it will continue - * during the next calls to mbedtls_ssl_renegotiate() or mbedtls_ssl_read() respectively. - */ -int mbedtls_ssl_start_renegotiation(mbedtls_ssl_context *ssl) -{ - int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED; +/* NOTICE: see above */ +#if defined(MBEDTLS_SSL_PROTO_TLS1_2) +static uint16_t ssl_tls12_preset_default_sig_algs[] = { - MBEDTLS_SSL_DEBUG_MSG(2, ("=> renegotiate")); +#if defined(MBEDTLS_MD_CAN_SHA512) +#if defined(MBEDTLS_KEY_EXCHANGE_ECDSA_CERT_REQ_ALLOWED_ENABLED) + MBEDTLS_SSL_TLS12_SIG_AND_HASH_ALG(MBEDTLS_SSL_SIG_ECDSA, MBEDTLS_SSL_HASH_SHA512), +#endif +#if defined(MBEDTLS_X509_RSASSA_PSS_SUPPORT) + MBEDTLS_TLS1_3_SIG_RSA_PSS_RSAE_SHA512, +#endif +#if defined(MBEDTLS_RSA_C) + MBEDTLS_SSL_TLS12_SIG_AND_HASH_ALG(MBEDTLS_SSL_SIG_RSA, MBEDTLS_SSL_HASH_SHA512), +#endif +#endif /* MBEDTLS_MD_CAN_SHA512 */ - if ((ret = ssl_handshake_init(ssl)) != 0) { - return ret; - } +#if defined(MBEDTLS_MD_CAN_SHA384) +#if defined(MBEDTLS_KEY_EXCHANGE_ECDSA_CERT_REQ_ALLOWED_ENABLED) + MBEDTLS_SSL_TLS12_SIG_AND_HASH_ALG(MBEDTLS_SSL_SIG_ECDSA, MBEDTLS_SSL_HASH_SHA384), +#endif +#if defined(MBEDTLS_X509_RSASSA_PSS_SUPPORT) + MBEDTLS_TLS1_3_SIG_RSA_PSS_RSAE_SHA384, +#endif +#if defined(MBEDTLS_RSA_C) + MBEDTLS_SSL_TLS12_SIG_AND_HASH_ALG(MBEDTLS_SSL_SIG_RSA, MBEDTLS_SSL_HASH_SHA384), +#endif +#endif /* MBEDTLS_MD_CAN_SHA384 */ - /* RFC 6347 4.2.2: "[...] the HelloRequest will have message_seq = 0 and - * the ServerHello will have message_seq = 1" */ -#if defined(MBEDTLS_SSL_PROTO_DTLS) - if (ssl->conf->transport == MBEDTLS_SSL_TRANSPORT_DATAGRAM && - ssl->renego_status == MBEDTLS_SSL_RENEGOTIATION_PENDING) { - if (ssl->conf->endpoint == MBEDTLS_SSL_IS_SERVER) { - ssl->handshake->out_msg_seq = 1; - } else { - ssl->handshake->in_msg_seq = 1; - } - } +#if defined(MBEDTLS_MD_CAN_SHA256) +#if defined(MBEDTLS_KEY_EXCHANGE_ECDSA_CERT_REQ_ALLOWED_ENABLED) + MBEDTLS_SSL_TLS12_SIG_AND_HASH_ALG(MBEDTLS_SSL_SIG_ECDSA, MBEDTLS_SSL_HASH_SHA256), +#endif +#if defined(MBEDTLS_X509_RSASSA_PSS_SUPPORT) + MBEDTLS_TLS1_3_SIG_RSA_PSS_RSAE_SHA256, +#endif +#if defined(MBEDTLS_RSA_C) + MBEDTLS_SSL_TLS12_SIG_AND_HASH_ALG(MBEDTLS_SSL_SIG_RSA, MBEDTLS_SSL_HASH_SHA256), #endif +#endif /* MBEDTLS_MD_CAN_SHA256 */ - ssl->state = MBEDTLS_SSL_HELLO_REQUEST; - ssl->renego_status = MBEDTLS_SSL_RENEGOTIATION_IN_PROGRESS; + MBEDTLS_TLS_SIG_NONE +}; +#endif /* MBEDTLS_SSL_PROTO_TLS1_2 */ - if ((ret = mbedtls_ssl_handshake(ssl)) != 0) { - MBEDTLS_SSL_DEBUG_RET(1, "mbedtls_ssl_handshake", ret); - return ret; - } +/* NOTICE: see above */ +static const uint16_t ssl_preset_suiteb_sig_algs[] = { - MBEDTLS_SSL_DEBUG_MSG(2, ("<= renegotiate")); +#if defined(MBEDTLS_KEY_EXCHANGE_ECDSA_CERT_REQ_ANY_ALLOWED_ENABLED) && \ + defined(MBEDTLS_MD_CAN_SHA256) && \ + defined(MBEDTLS_ECP_HAVE_SECP256R1) + MBEDTLS_TLS1_3_SIG_ECDSA_SECP256R1_SHA256, + // == MBEDTLS_SSL_TLS12_SIG_AND_HASH_ALG(MBEDTLS_SSL_SIG_ECDSA, MBEDTLS_SSL_HASH_SHA256) +#endif - return 0; -} +#if defined(MBEDTLS_KEY_EXCHANGE_ECDSA_CERT_REQ_ANY_ALLOWED_ENABLED) && \ + defined(MBEDTLS_MD_CAN_SHA384) && \ + defined(MBEDTLS_ECP_HAVE_SECP384R1) + MBEDTLS_TLS1_3_SIG_ECDSA_SECP384R1_SHA384, + // == MBEDTLS_SSL_TLS12_SIG_AND_HASH_ALG(MBEDTLS_SSL_SIG_ECDSA, MBEDTLS_SSL_HASH_SHA384) +#endif -/* - * Renegotiate current connection on client, - * or request renegotiation on server - */ -int mbedtls_ssl_renegotiate(mbedtls_ssl_context *ssl) -{ - int ret = MBEDTLS_ERR_SSL_FEATURE_UNAVAILABLE; + MBEDTLS_TLS_SIG_NONE +}; - if (ssl == NULL || ssl->conf == NULL) { - return MBEDTLS_ERR_SSL_BAD_INPUT_DATA; - } +/* NOTICE: see above */ +#if defined(MBEDTLS_SSL_PROTO_TLS1_2) +static uint16_t ssl_tls12_preset_suiteb_sig_algs[] = { -#if defined(MBEDTLS_SSL_SRV_C) - /* On server, just send the request */ - if (ssl->conf->endpoint == MBEDTLS_SSL_IS_SERVER) { - if (ssl->state != MBEDTLS_SSL_HANDSHAKE_OVER) { - return MBEDTLS_ERR_SSL_BAD_INPUT_DATA; - } +#if defined(MBEDTLS_MD_CAN_SHA256) +#if defined(MBEDTLS_KEY_EXCHANGE_ECDSA_CERT_REQ_ALLOWED_ENABLED) + MBEDTLS_SSL_TLS12_SIG_AND_HASH_ALG(MBEDTLS_SSL_SIG_ECDSA, MBEDTLS_SSL_HASH_SHA256), +#endif +#endif /* MBEDTLS_MD_CAN_SHA256 */ - ssl->renego_status = MBEDTLS_SSL_RENEGOTIATION_PENDING; +#if defined(MBEDTLS_MD_CAN_SHA384) +#if defined(MBEDTLS_KEY_EXCHANGE_ECDSA_CERT_REQ_ALLOWED_ENABLED) + MBEDTLS_SSL_TLS12_SIG_AND_HASH_ALG(MBEDTLS_SSL_SIG_ECDSA, MBEDTLS_SSL_HASH_SHA384), +#endif +#endif /* MBEDTLS_MD_CAN_SHA384 */ - /* Did we already try/start sending HelloRequest? */ - if (ssl->out_left != 0) { - return mbedtls_ssl_flush_output(ssl); - } + MBEDTLS_TLS_SIG_NONE +}; +#endif /* MBEDTLS_SSL_PROTO_TLS1_2 */ - return ssl_write_hello_request(ssl); - } -#endif /* MBEDTLS_SSL_SRV_C */ +#endif /* MBEDTLS_SSL_HANDSHAKE_WITH_CERT_ENABLED */ -#if defined(MBEDTLS_SSL_CLI_C) - /* - * On client, either start the renegotiation process or, - * if already in progress, continue the handshake - */ - if (ssl->renego_status != MBEDTLS_SSL_RENEGOTIATION_IN_PROGRESS) { - if (ssl->state != MBEDTLS_SSL_HANDSHAKE_OVER) { - return MBEDTLS_ERR_SSL_BAD_INPUT_DATA; - } +static const uint16_t ssl_preset_suiteb_groups[] = { +#if defined(MBEDTLS_ECP_HAVE_SECP256R1) + MBEDTLS_SSL_IANA_TLS_GROUP_SECP256R1, +#endif +#if defined(MBEDTLS_ECP_HAVE_SECP384R1) + MBEDTLS_SSL_IANA_TLS_GROUP_SECP384R1, +#endif + MBEDTLS_SSL_IANA_TLS_GROUP_NONE +}; - if ((ret = mbedtls_ssl_start_renegotiation(ssl)) != 0) { - MBEDTLS_SSL_DEBUG_RET(1, "mbedtls_ssl_start_renegotiation", ret); - return ret; - } - } else { - if ((ret = mbedtls_ssl_handshake(ssl)) != 0) { - MBEDTLS_SSL_DEBUG_RET(1, "mbedtls_ssl_handshake", ret); - return ret; +#if defined(MBEDTLS_DEBUG_C) && defined(MBEDTLS_SSL_HANDSHAKE_WITH_CERT_ENABLED) +/* Function for checking `ssl_preset_*_sig_algs` and `ssl_tls12_preset_*_sig_algs` + * to make sure there are no duplicated signature algorithm entries. */ +MBEDTLS_CHECK_RETURN_CRITICAL +static int ssl_check_no_sig_alg_duplication(const uint16_t *sig_algs) +{ + size_t i, j; + int ret = 0; + + for (i = 0; sig_algs[i] != MBEDTLS_TLS_SIG_NONE; i++) { + for (j = 0; j < i; j++) { + if (sig_algs[i] != sig_algs[j]) { + continue; + } + mbedtls_printf(" entry(%04x,%" MBEDTLS_PRINTF_SIZET + ") is duplicated at %" MBEDTLS_PRINTF_SIZET "\n", + sig_algs[i], j, i); + ret = -1; } } -#endif /* MBEDTLS_SSL_CLI_C */ - return ret; } -#endif /* MBEDTLS_SSL_RENEGOTIATION */ -#if defined(MBEDTLS_X509_CRT_PARSE_C) -static void ssl_key_cert_free(mbedtls_ssl_key_cert *key_cert) +#endif /* MBEDTLS_DEBUG_C && MBEDTLS_SSL_HANDSHAKE_WITH_CERT_ENABLED */ + +/* + * Load default in mbedtls_ssl_config + */ +int mbedtls_ssl_config_defaults(mbedtls_ssl_config *conf, + int endpoint, int transport, int preset) { - mbedtls_ssl_key_cert *cur = key_cert, *next; +#if defined(MBEDTLS_DHM_C) && defined(MBEDTLS_SSL_SRV_C) + int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED; +#endif - while (cur != NULL) { - next = cur->next; - mbedtls_free(cur); - cur = next; +#if defined(MBEDTLS_DEBUG_C) && defined(MBEDTLS_SSL_HANDSHAKE_WITH_CERT_ENABLED) + if (ssl_check_no_sig_alg_duplication(ssl_preset_suiteb_sig_algs)) { + mbedtls_printf("ssl_preset_suiteb_sig_algs has duplicated entries\n"); + return MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED; } -} -#endif /* MBEDTLS_X509_CRT_PARSE_C */ -void mbedtls_ssl_handshake_free(mbedtls_ssl_context *ssl) -{ - mbedtls_ssl_handshake_params *handshake = ssl->handshake; + if (ssl_check_no_sig_alg_duplication(ssl_preset_default_sig_algs)) { + mbedtls_printf("ssl_preset_default_sig_algs has duplicated entries\n"); + return MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED; + } - if (handshake == NULL) { - return; +#if defined(MBEDTLS_SSL_PROTO_TLS1_2) + if (ssl_check_no_sig_alg_duplication(ssl_tls12_preset_suiteb_sig_algs)) { + mbedtls_printf("ssl_tls12_preset_suiteb_sig_algs has duplicated entries\n"); + return MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED; } -#if defined(MBEDTLS_SSL_ASYNC_PRIVATE) - if (ssl->conf->f_async_cancel != NULL && handshake->async_in_progress != 0) { - ssl->conf->f_async_cancel(ssl); - handshake->async_in_progress = 0; + if (ssl_check_no_sig_alg_duplication(ssl_tls12_preset_default_sig_algs)) { + mbedtls_printf("ssl_tls12_preset_default_sig_algs has duplicated entries\n"); + return MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED; } -#endif /* MBEDTLS_SSL_ASYNC_PRIVATE */ +#endif /* MBEDTLS_SSL_PROTO_TLS1_2 */ +#endif /* MBEDTLS_DEBUG_C && MBEDTLS_SSL_HANDSHAKE_WITH_CERT_ENABLED */ -#if defined(MBEDTLS_SSL_PROTO_SSL3) || defined(MBEDTLS_SSL_PROTO_TLS1) || \ - defined(MBEDTLS_SSL_PROTO_TLS1_1) - mbedtls_md5_free(&handshake->fin_md5); - mbedtls_sha1_free(&handshake->fin_sha1); -#endif -#if defined(MBEDTLS_SSL_PROTO_TLS1_2) -#if defined(MBEDTLS_SHA256_C) -#if defined(MBEDTLS_USE_PSA_CRYPTO) - psa_hash_abort(&handshake->fin_sha256_psa); -#else - mbedtls_sha256_free(&handshake->fin_sha256); + /* Use the functions here so that they are covered in tests, + * but otherwise access member directly for efficiency */ + mbedtls_ssl_conf_endpoint(conf, endpoint); + mbedtls_ssl_conf_transport(conf, transport); + + /* + * Things that are common to all presets + */ +#if defined(MBEDTLS_SSL_CLI_C) + if (endpoint == MBEDTLS_SSL_IS_CLIENT) { + conf->authmode = MBEDTLS_SSL_VERIFY_REQUIRED; +#if defined(MBEDTLS_SSL_SESSION_TICKETS) + conf->session_tickets = MBEDTLS_SSL_SESSION_TICKETS_ENABLED; #endif + } #endif -#if defined(MBEDTLS_SHA512_C) && !defined(MBEDTLS_SHA512_NO_SHA384) -#if defined(MBEDTLS_USE_PSA_CRYPTO) - psa_hash_abort(&handshake->fin_sha384_psa); -#else - mbedtls_sha512_free(&handshake->fin_sha512); + +#if defined(MBEDTLS_SSL_ENCRYPT_THEN_MAC) + conf->encrypt_then_mac = MBEDTLS_SSL_ETM_ENABLED; #endif + +#if defined(MBEDTLS_SSL_EXTENDED_MASTER_SECRET) + conf->extended_ms = MBEDTLS_SSL_EXTENDED_MS_ENABLED; #endif -#endif /* MBEDTLS_SSL_PROTO_TLS1_2 */ -#if defined(MBEDTLS_DHM_C) - mbedtls_dhm_free(&handshake->dhm_ctx); +#if defined(MBEDTLS_SSL_DTLS_HELLO_VERIFY) && defined(MBEDTLS_SSL_SRV_C) + conf->f_cookie_write = ssl_cookie_write_dummy; + conf->f_cookie_check = ssl_cookie_check_dummy; #endif -#if defined(MBEDTLS_ECDH_C) - mbedtls_ecdh_free(&handshake->ecdh_ctx); + +#if defined(MBEDTLS_SSL_DTLS_ANTI_REPLAY) + conf->anti_replay = MBEDTLS_SSL_ANTI_REPLAY_ENABLED; #endif -#if defined(MBEDTLS_KEY_EXCHANGE_ECJPAKE_ENABLED) - mbedtls_ecjpake_free(&handshake->ecjpake_ctx); -#if defined(MBEDTLS_SSL_CLI_C) - mbedtls_free(handshake->ecjpake_cache); - handshake->ecjpake_cache = NULL; - handshake->ecjpake_cache_len = 0; + +#if defined(MBEDTLS_SSL_SRV_C) + conf->cert_req_ca_list = MBEDTLS_SSL_CERT_REQ_CA_LIST_ENABLED; + conf->respect_cli_pref = MBEDTLS_SSL_SRV_CIPHERSUITE_ORDER_SERVER; #endif + +#if defined(MBEDTLS_SSL_PROTO_DTLS) + conf->hs_timeout_min = MBEDTLS_SSL_DTLS_TIMEOUT_DFL_MIN; + conf->hs_timeout_max = MBEDTLS_SSL_DTLS_TIMEOUT_DFL_MAX; #endif -#if defined(MBEDTLS_ECDH_C) || defined(MBEDTLS_ECDSA_C) || \ - defined(MBEDTLS_KEY_EXCHANGE_ECJPAKE_ENABLED) - /* explicit void pointer cast for buggy MS compiler */ - mbedtls_free((void *) handshake->curves); +#if defined(MBEDTLS_SSL_RENEGOTIATION) + conf->renego_max_records = MBEDTLS_SSL_RENEGO_MAX_RECORDS_DEFAULT; + memset(conf->renego_period, 0x00, 2); + memset(conf->renego_period + 2, 0xFF, 6); #endif -#if defined(MBEDTLS_KEY_EXCHANGE_SOME_PSK_ENABLED) - if (handshake->psk != NULL) { - mbedtls_platform_zeroize(handshake->psk, handshake->psk_len); - mbedtls_free(handshake->psk); +#if defined(MBEDTLS_DHM_C) && defined(MBEDTLS_SSL_SRV_C) + if (endpoint == MBEDTLS_SSL_IS_SERVER) { + const unsigned char dhm_p[] = + MBEDTLS_DHM_RFC3526_MODP_2048_P_BIN; + const unsigned char dhm_g[] = + MBEDTLS_DHM_RFC3526_MODP_2048_G_BIN; + + if ((ret = mbedtls_ssl_conf_dh_param_bin(conf, + dhm_p, sizeof(dhm_p), + dhm_g, sizeof(dhm_g))) != 0) { + return ret; + } } #endif -#if defined(MBEDTLS_X509_CRT_PARSE_C) && \ - defined(MBEDTLS_SSL_SERVER_NAME_INDICATION) +#if defined(MBEDTLS_SSL_PROTO_TLS1_3) + +#if defined(MBEDTLS_SSL_EARLY_DATA) + mbedtls_ssl_conf_early_data(conf, MBEDTLS_SSL_EARLY_DATA_DISABLED); +#if defined(MBEDTLS_SSL_SRV_C) + mbedtls_ssl_conf_max_early_data_size(conf, MBEDTLS_SSL_MAX_EARLY_DATA_SIZE); +#endif +#endif /* MBEDTLS_SSL_EARLY_DATA */ + +#if defined(MBEDTLS_SSL_SRV_C) && defined(MBEDTLS_SSL_SESSION_TICKETS) + mbedtls_ssl_conf_new_session_tickets( + conf, MBEDTLS_SSL_TLS1_3_DEFAULT_NEW_SESSION_TICKETS); +#endif /* - * Free only the linked list wrapper, not the keys themselves - * since the belong to the SNI callback + * Allow all TLS 1.3 key exchange modes by default. */ - if (handshake->sni_key_cert != NULL) { - mbedtls_ssl_key_cert *cur = handshake->sni_key_cert, *next; + conf->tls13_kex_modes = MBEDTLS_SSL_TLS1_3_KEY_EXCHANGE_MODE_ALL; +#endif /* MBEDTLS_SSL_PROTO_TLS1_3 */ - while (cur != NULL) { - next = cur->next; - mbedtls_free(cur); - cur = next; - } + if (transport == MBEDTLS_SSL_TRANSPORT_DATAGRAM) { +#if defined(MBEDTLS_SSL_PROTO_TLS1_2) + conf->min_tls_version = MBEDTLS_SSL_VERSION_TLS1_2; + conf->max_tls_version = MBEDTLS_SSL_VERSION_TLS1_2; +#else + return MBEDTLS_ERR_SSL_FEATURE_UNAVAILABLE; +#endif + } else { +#if defined(MBEDTLS_SSL_PROTO_TLS1_2) && defined(MBEDTLS_SSL_PROTO_TLS1_3) + conf->min_tls_version = MBEDTLS_SSL_VERSION_TLS1_2; + conf->max_tls_version = MBEDTLS_SSL_VERSION_TLS1_3; +#elif defined(MBEDTLS_SSL_PROTO_TLS1_3) + conf->min_tls_version = MBEDTLS_SSL_VERSION_TLS1_3; + conf->max_tls_version = MBEDTLS_SSL_VERSION_TLS1_3; +#elif defined(MBEDTLS_SSL_PROTO_TLS1_2) + conf->min_tls_version = MBEDTLS_SSL_VERSION_TLS1_2; + conf->max_tls_version = MBEDTLS_SSL_VERSION_TLS1_2; +#else + return MBEDTLS_ERR_SSL_FEATURE_UNAVAILABLE; +#endif } -#endif /* MBEDTLS_X509_CRT_PARSE_C && MBEDTLS_SSL_SERVER_NAME_INDICATION */ -#if defined(MBEDTLS_SSL_ECP_RESTARTABLE_ENABLED) - mbedtls_x509_crt_restart_free(&handshake->ecrs_ctx); - if (handshake->ecrs_peer_cert != NULL) { - mbedtls_x509_crt_free(handshake->ecrs_peer_cert); - mbedtls_free(handshake->ecrs_peer_cert); - } + /* + * Preset-specific defaults + */ + switch (preset) { + /* + * NSA Suite B + */ + case MBEDTLS_SSL_PRESET_SUITEB: + + conf->ciphersuite_list = ssl_preset_suiteb_ciphersuites; + +#if defined(MBEDTLS_X509_CRT_PARSE_C) + conf->cert_profile = &mbedtls_x509_crt_profile_suiteb; #endif -#if defined(MBEDTLS_X509_CRT_PARSE_C) && \ - !defined(MBEDTLS_SSL_KEEP_PEER_CERTIFICATE) - mbedtls_pk_free(&handshake->peer_pubkey); -#endif /* MBEDTLS_X509_CRT_PARSE_C && !MBEDTLS_SSL_KEEP_PEER_CERTIFICATE */ +#if defined(MBEDTLS_SSL_HANDSHAKE_WITH_CERT_ENABLED) +#if defined(MBEDTLS_SSL_PROTO_TLS1_2) + if (mbedtls_ssl_conf_is_tls12_only(conf)) { + conf->sig_algs = ssl_tls12_preset_suiteb_sig_algs; + } else +#endif /* MBEDTLS_SSL_PROTO_TLS1_2 */ + conf->sig_algs = ssl_preset_suiteb_sig_algs; +#endif /* MBEDTLS_SSL_HANDSHAKE_WITH_CERT_ENABLED */ -#if defined(MBEDTLS_SSL_PROTO_DTLS) - mbedtls_free(handshake->verify_cookie); - mbedtls_ssl_flight_free(handshake->flight); - mbedtls_ssl_buffering_free(ssl); +#if defined(MBEDTLS_ECP_C) && !defined(MBEDTLS_DEPRECATED_REMOVED) + conf->curve_list = NULL; #endif + conf->group_list = ssl_preset_suiteb_groups; + break; -#if defined(MBEDTLS_ECDH_C) && \ - defined(MBEDTLS_USE_PSA_CRYPTO) - psa_destroy_key(handshake->ecdh_psa_privkey); -#endif /* MBEDTLS_ECDH_C && MBEDTLS_USE_PSA_CRYPTO */ + /* + * Default + */ + default: - mbedtls_platform_zeroize(handshake, - sizeof(mbedtls_ssl_handshake_params)); + conf->ciphersuite_list = mbedtls_ssl_list_ciphersuites(); -#if defined(MBEDTLS_SSL_VARIABLE_BUFFER_LENGTH) - /* If the buffers are too big - reallocate. Because of the way Mbed TLS - * processes datagrams and the fact that a datagram is allowed to have - * several records in it, it is possible that the I/O buffers are not - * empty at this stage */ - handle_buffer_resizing(ssl, 1, mbedtls_ssl_get_input_buflen(ssl), - mbedtls_ssl_get_output_buflen(ssl)); +#if defined(MBEDTLS_X509_CRT_PARSE_C) + conf->cert_profile = &mbedtls_x509_crt_profile_default; #endif -} -void mbedtls_ssl_session_free(mbedtls_ssl_session *session) -{ - if (session == NULL) { - return; - } +#if defined(MBEDTLS_SSL_HANDSHAKE_WITH_CERT_ENABLED) +#if defined(MBEDTLS_SSL_PROTO_TLS1_2) + if (mbedtls_ssl_conf_is_tls12_only(conf)) { + conf->sig_algs = ssl_tls12_preset_default_sig_algs; + } else +#endif /* MBEDTLS_SSL_PROTO_TLS1_2 */ + conf->sig_algs = ssl_preset_default_sig_algs; +#endif /* MBEDTLS_SSL_HANDSHAKE_WITH_CERT_ENABLED */ -#if defined(MBEDTLS_X509_CRT_PARSE_C) - ssl_clear_peer_cert(session); +#if defined(MBEDTLS_ECP_C) && !defined(MBEDTLS_DEPRECATED_REMOVED) + conf->curve_list = NULL; #endif + conf->group_list = ssl_preset_default_groups; -#if defined(MBEDTLS_SSL_SESSION_TICKETS) && defined(MBEDTLS_SSL_CLI_C) - mbedtls_free(session->ticket); +#if defined(MBEDTLS_DHM_C) && defined(MBEDTLS_SSL_CLI_C) + conf->dhm_min_bitlen = 1024; #endif + } - mbedtls_platform_zeroize(session, sizeof(mbedtls_ssl_session)); + return 0; } -#if defined(MBEDTLS_SSL_CONTEXT_SERIALIZATION) +/* + * Free mbedtls_ssl_config + */ +void mbedtls_ssl_config_free(mbedtls_ssl_config *conf) +{ +#if defined(MBEDTLS_DHM_C) + mbedtls_mpi_free(&conf->dhm_P); + mbedtls_mpi_free(&conf->dhm_G); +#endif -#if defined(MBEDTLS_SSL_DTLS_CONNECTION_ID) -#define SSL_SERIALIZED_CONTEXT_CONFIG_DTLS_CONNECTION_ID 1u -#else -#define SSL_SERIALIZED_CONTEXT_CONFIG_DTLS_CONNECTION_ID 0u -#endif /* MBEDTLS_SSL_DTLS_CONNECTION_ID */ +#if defined(MBEDTLS_SSL_HANDSHAKE_WITH_PSK_ENABLED) +#if defined(MBEDTLS_USE_PSA_CRYPTO) + if (!mbedtls_svc_key_id_is_null(conf->psk_opaque)) { + conf->psk_opaque = MBEDTLS_SVC_KEY_ID_INIT; + } +#endif /* MBEDTLS_USE_PSA_CRYPTO */ + if (conf->psk != NULL) { + mbedtls_zeroize_and_free(conf->psk, conf->psk_len); + conf->psk = NULL; + conf->psk_len = 0; + } -#if defined(MBEDTLS_SSL_DTLS_BADMAC_LIMIT) -#define SSL_SERIALIZED_CONTEXT_CONFIG_DTLS_BADMAC_LIMIT 1u -#else -#define SSL_SERIALIZED_CONTEXT_CONFIG_DTLS_BADMAC_LIMIT 0u -#endif /* MBEDTLS_SSL_DTLS_BADMAC_LIMIT */ + if (conf->psk_identity != NULL) { + mbedtls_zeroize_and_free(conf->psk_identity, conf->psk_identity_len); + conf->psk_identity = NULL; + conf->psk_identity_len = 0; + } +#endif /* MBEDTLS_SSL_HANDSHAKE_WITH_PSK_ENABLED */ -#if defined(MBEDTLS_SSL_DTLS_ANTI_REPLAY) -#define SSL_SERIALIZED_CONTEXT_CONFIG_DTLS_ANTI_REPLAY 1u -#else -#define SSL_SERIALIZED_CONTEXT_CONFIG_DTLS_ANTI_REPLAY 0u -#endif /* MBEDTLS_SSL_DTLS_ANTI_REPLAY */ +#if defined(MBEDTLS_X509_CRT_PARSE_C) + ssl_key_cert_free(conf->key_cert); +#endif + + mbedtls_platform_zeroize(conf, sizeof(mbedtls_ssl_config)); +} + +#if defined(MBEDTLS_PK_C) && \ + (defined(MBEDTLS_RSA_C) || defined(MBEDTLS_KEY_EXCHANGE_ECDSA_CERT_REQ_ANY_ALLOWED_ENABLED)) +/* + * Convert between MBEDTLS_PK_XXX and SSL_SIG_XXX + */ +unsigned char mbedtls_ssl_sig_from_pk(mbedtls_pk_context *pk) +{ +#if defined(MBEDTLS_RSA_C) + if (mbedtls_pk_can_do(pk, MBEDTLS_PK_RSA)) { + return MBEDTLS_SSL_SIG_RSA; + } +#endif +#if defined(MBEDTLS_KEY_EXCHANGE_ECDSA_CERT_REQ_ANY_ALLOWED_ENABLED) + if (mbedtls_pk_can_do(pk, MBEDTLS_PK_ECDSA)) { + return MBEDTLS_SSL_SIG_ECDSA; + } +#endif + return MBEDTLS_SSL_SIG_ANON; +} + +unsigned char mbedtls_ssl_sig_from_pk_alg(mbedtls_pk_type_t type) +{ + switch (type) { + case MBEDTLS_PK_RSA: + return MBEDTLS_SSL_SIG_RSA; + case MBEDTLS_PK_ECDSA: + case MBEDTLS_PK_ECKEY: + return MBEDTLS_SSL_SIG_ECDSA; + default: + return MBEDTLS_SSL_SIG_ANON; + } +} + +mbedtls_pk_type_t mbedtls_ssl_pk_alg_from_sig(unsigned char sig) +{ + switch (sig) { +#if defined(MBEDTLS_RSA_C) + case MBEDTLS_SSL_SIG_RSA: + return MBEDTLS_PK_RSA; +#endif +#if defined(MBEDTLS_KEY_EXCHANGE_ECDSA_CERT_REQ_ANY_ALLOWED_ENABLED) + case MBEDTLS_SSL_SIG_ECDSA: + return MBEDTLS_PK_ECDSA; +#endif + default: + return MBEDTLS_PK_NONE; + } +} +#endif /* MBEDTLS_PK_C && + ( MBEDTLS_RSA_C || MBEDTLS_KEY_EXCHANGE_ECDSA_CERT_REQ_ANY_ALLOWED_ENABLED ) */ + +/* + * Convert from MBEDTLS_SSL_HASH_XXX to MBEDTLS_MD_XXX + */ +mbedtls_md_type_t mbedtls_ssl_md_alg_from_hash(unsigned char hash) +{ + switch (hash) { +#if defined(MBEDTLS_MD_CAN_MD5) + case MBEDTLS_SSL_HASH_MD5: + return MBEDTLS_MD_MD5; +#endif +#if defined(MBEDTLS_MD_CAN_SHA1) + case MBEDTLS_SSL_HASH_SHA1: + return MBEDTLS_MD_SHA1; +#endif +#if defined(MBEDTLS_MD_CAN_SHA224) + case MBEDTLS_SSL_HASH_SHA224: + return MBEDTLS_MD_SHA224; +#endif +#if defined(MBEDTLS_MD_CAN_SHA256) + case MBEDTLS_SSL_HASH_SHA256: + return MBEDTLS_MD_SHA256; +#endif +#if defined(MBEDTLS_MD_CAN_SHA384) + case MBEDTLS_SSL_HASH_SHA384: + return MBEDTLS_MD_SHA384; +#endif +#if defined(MBEDTLS_MD_CAN_SHA512) + case MBEDTLS_SSL_HASH_SHA512: + return MBEDTLS_MD_SHA512; +#endif + default: + return MBEDTLS_MD_NONE; + } +} + +/* + * Convert from MBEDTLS_MD_XXX to MBEDTLS_SSL_HASH_XXX + */ +unsigned char mbedtls_ssl_hash_from_md_alg(int md) +{ + switch (md) { +#if defined(MBEDTLS_MD_CAN_MD5) + case MBEDTLS_MD_MD5: + return MBEDTLS_SSL_HASH_MD5; +#endif +#if defined(MBEDTLS_MD_CAN_SHA1) + case MBEDTLS_MD_SHA1: + return MBEDTLS_SSL_HASH_SHA1; +#endif +#if defined(MBEDTLS_MD_CAN_SHA224) + case MBEDTLS_MD_SHA224: + return MBEDTLS_SSL_HASH_SHA224; +#endif +#if defined(MBEDTLS_MD_CAN_SHA256) + case MBEDTLS_MD_SHA256: + return MBEDTLS_SSL_HASH_SHA256; +#endif +#if defined(MBEDTLS_MD_CAN_SHA384) + case MBEDTLS_MD_SHA384: + return MBEDTLS_SSL_HASH_SHA384; +#endif +#if defined(MBEDTLS_MD_CAN_SHA512) + case MBEDTLS_MD_SHA512: + return MBEDTLS_SSL_HASH_SHA512; +#endif + default: + return MBEDTLS_SSL_HASH_NONE; + } +} + +/* + * Check if a curve proposed by the peer is in our list. + * Return 0 if we're willing to use it, -1 otherwise. + */ +int mbedtls_ssl_check_curve_tls_id(const mbedtls_ssl_context *ssl, uint16_t tls_id) +{ + const uint16_t *group_list = mbedtls_ssl_get_groups(ssl); + + if (group_list == NULL) { + return -1; + } + + for (; *group_list != 0; group_list++) { + if (*group_list == tls_id) { + return 0; + } + } + + return -1; +} + +#if defined(MBEDTLS_PK_HAVE_ECC_KEYS) +/* + * Same as mbedtls_ssl_check_curve_tls_id() but with a mbedtls_ecp_group_id. + */ +int mbedtls_ssl_check_curve(const mbedtls_ssl_context *ssl, mbedtls_ecp_group_id grp_id) +{ + uint16_t tls_id = mbedtls_ssl_get_tls_id_from_ecp_group_id(grp_id); + + if (tls_id == 0) { + return -1; + } + + return mbedtls_ssl_check_curve_tls_id(ssl, tls_id); +} +#endif /* MBEDTLS_PK_HAVE_ECC_KEYS */ + +static const struct { + uint16_t tls_id; + mbedtls_ecp_group_id ecp_group_id; + psa_ecc_family_t psa_family; + uint16_t bits; +} tls_id_match_table[] = +{ +#if defined(MBEDTLS_ECP_HAVE_SECP521R1) + { 25, MBEDTLS_ECP_DP_SECP521R1, PSA_ECC_FAMILY_SECP_R1, 521 }, +#endif +#if defined(MBEDTLS_ECP_HAVE_BP512R1) + { 28, MBEDTLS_ECP_DP_BP512R1, PSA_ECC_FAMILY_BRAINPOOL_P_R1, 512 }, +#endif +#if defined(MBEDTLS_ECP_HAVE_SECP384R1) + { 24, MBEDTLS_ECP_DP_SECP384R1, PSA_ECC_FAMILY_SECP_R1, 384 }, +#endif +#if defined(MBEDTLS_ECP_HAVE_BP384R1) + { 27, MBEDTLS_ECP_DP_BP384R1, PSA_ECC_FAMILY_BRAINPOOL_P_R1, 384 }, +#endif +#if defined(MBEDTLS_ECP_HAVE_SECP256R1) + { 23, MBEDTLS_ECP_DP_SECP256R1, PSA_ECC_FAMILY_SECP_R1, 256 }, +#endif +#if defined(MBEDTLS_ECP_HAVE_SECP256K1) + { 22, MBEDTLS_ECP_DP_SECP256K1, PSA_ECC_FAMILY_SECP_K1, 256 }, +#endif +#if defined(MBEDTLS_ECP_HAVE_BP256R1) + { 26, MBEDTLS_ECP_DP_BP256R1, PSA_ECC_FAMILY_BRAINPOOL_P_R1, 256 }, +#endif +#if defined(MBEDTLS_ECP_HAVE_SECP224R1) + { 21, MBEDTLS_ECP_DP_SECP224R1, PSA_ECC_FAMILY_SECP_R1, 224 }, +#endif +#if defined(MBEDTLS_ECP_HAVE_SECP224K1) + { 20, MBEDTLS_ECP_DP_SECP224K1, PSA_ECC_FAMILY_SECP_K1, 224 }, +#endif +#if defined(MBEDTLS_ECP_HAVE_SECP192R1) + { 19, MBEDTLS_ECP_DP_SECP192R1, PSA_ECC_FAMILY_SECP_R1, 192 }, +#endif +#if defined(MBEDTLS_ECP_HAVE_SECP192K1) + { 18, MBEDTLS_ECP_DP_SECP192K1, PSA_ECC_FAMILY_SECP_K1, 192 }, +#endif +#if defined(MBEDTLS_ECP_HAVE_CURVE25519) + { 29, MBEDTLS_ECP_DP_CURVE25519, PSA_ECC_FAMILY_MONTGOMERY, 255 }, +#endif +#if defined(MBEDTLS_ECP_HAVE_CURVE448) + { 30, MBEDTLS_ECP_DP_CURVE448, PSA_ECC_FAMILY_MONTGOMERY, 448 }, +#endif + { 0, MBEDTLS_ECP_DP_NONE, 0, 0 }, +}; + +int mbedtls_ssl_get_psa_curve_info_from_tls_id(uint16_t tls_id, + psa_key_type_t *type, + size_t *bits) +{ + for (int i = 0; tls_id_match_table[i].tls_id != 0; i++) { + if (tls_id_match_table[i].tls_id == tls_id) { + if (type != NULL) { + *type = PSA_KEY_TYPE_ECC_KEY_PAIR(tls_id_match_table[i].psa_family); + } + if (bits != NULL) { + *bits = tls_id_match_table[i].bits; + } + return PSA_SUCCESS; + } + } + + return PSA_ERROR_NOT_SUPPORTED; +} + +mbedtls_ecp_group_id mbedtls_ssl_get_ecp_group_id_from_tls_id(uint16_t tls_id) +{ + for (int i = 0; tls_id_match_table[i].tls_id != 0; i++) { + if (tls_id_match_table[i].tls_id == tls_id) { + return tls_id_match_table[i].ecp_group_id; + } + } + + return MBEDTLS_ECP_DP_NONE; +} + +uint16_t mbedtls_ssl_get_tls_id_from_ecp_group_id(mbedtls_ecp_group_id grp_id) +{ + for (int i = 0; tls_id_match_table[i].ecp_group_id != MBEDTLS_ECP_DP_NONE; + i++) { + if (tls_id_match_table[i].ecp_group_id == grp_id) { + return tls_id_match_table[i].tls_id; + } + } + + return 0; +} + +#if defined(MBEDTLS_DEBUG_C) +static const struct { + uint16_t tls_id; + const char *name; +} tls_id_curve_name_table[] = +{ + { MBEDTLS_SSL_IANA_TLS_GROUP_SECP521R1, "secp521r1" }, + { MBEDTLS_SSL_IANA_TLS_GROUP_BP512R1, "brainpoolP512r1" }, + { MBEDTLS_SSL_IANA_TLS_GROUP_SECP384R1, "secp384r1" }, + { MBEDTLS_SSL_IANA_TLS_GROUP_BP384R1, "brainpoolP384r1" }, + { MBEDTLS_SSL_IANA_TLS_GROUP_SECP256R1, "secp256r1" }, + { MBEDTLS_SSL_IANA_TLS_GROUP_SECP256K1, "secp256k1" }, + { MBEDTLS_SSL_IANA_TLS_GROUP_BP256R1, "brainpoolP256r1" }, + { MBEDTLS_SSL_IANA_TLS_GROUP_SECP224R1, "secp224r1" }, + { MBEDTLS_SSL_IANA_TLS_GROUP_SECP224K1, "secp224k1" }, + { MBEDTLS_SSL_IANA_TLS_GROUP_SECP192R1, "secp192r1" }, + { MBEDTLS_SSL_IANA_TLS_GROUP_SECP192K1, "secp192k1" }, + { MBEDTLS_SSL_IANA_TLS_GROUP_X25519, "x25519" }, + { MBEDTLS_SSL_IANA_TLS_GROUP_X448, "x448" }, + { 0, NULL }, +}; + +const char *mbedtls_ssl_get_curve_name_from_tls_id(uint16_t tls_id) +{ + for (int i = 0; tls_id_curve_name_table[i].tls_id != 0; i++) { + if (tls_id_curve_name_table[i].tls_id == tls_id) { + return tls_id_curve_name_table[i].name; + } + } + + return NULL; +} +#endif + +#if defined(MBEDTLS_X509_CRT_PARSE_C) +int mbedtls_ssl_check_cert_usage(const mbedtls_x509_crt *cert, + const mbedtls_ssl_ciphersuite_t *ciphersuite, + int cert_endpoint, + uint32_t *flags) +{ + int ret = 0; + unsigned int usage = 0; + const char *ext_oid; + size_t ext_len; + + if (cert_endpoint == MBEDTLS_SSL_IS_SERVER) { + /* Server part of the key exchange */ + switch (ciphersuite->key_exchange) { + case MBEDTLS_KEY_EXCHANGE_RSA: + case MBEDTLS_KEY_EXCHANGE_RSA_PSK: + usage = MBEDTLS_X509_KU_KEY_ENCIPHERMENT; + break; + + case MBEDTLS_KEY_EXCHANGE_DHE_RSA: + case MBEDTLS_KEY_EXCHANGE_ECDHE_RSA: + case MBEDTLS_KEY_EXCHANGE_ECDHE_ECDSA: + usage = MBEDTLS_X509_KU_DIGITAL_SIGNATURE; + break; + + case MBEDTLS_KEY_EXCHANGE_ECDH_RSA: + case MBEDTLS_KEY_EXCHANGE_ECDH_ECDSA: + usage = MBEDTLS_X509_KU_KEY_AGREEMENT; + break; + + /* Don't use default: we want warnings when adding new values */ + case MBEDTLS_KEY_EXCHANGE_NONE: + case MBEDTLS_KEY_EXCHANGE_PSK: + case MBEDTLS_KEY_EXCHANGE_DHE_PSK: + case MBEDTLS_KEY_EXCHANGE_ECDHE_PSK: + case MBEDTLS_KEY_EXCHANGE_ECJPAKE: + usage = 0; + } + } else { + /* Client auth: we only implement rsa_sign and mbedtls_ecdsa_sign for now */ + usage = MBEDTLS_X509_KU_DIGITAL_SIGNATURE; + } + + if (mbedtls_x509_crt_check_key_usage(cert, usage) != 0) { + *flags |= MBEDTLS_X509_BADCERT_KEY_USAGE; + ret = -1; + } + + if (cert_endpoint == MBEDTLS_SSL_IS_SERVER) { + ext_oid = MBEDTLS_OID_SERVER_AUTH; + ext_len = MBEDTLS_OID_SIZE(MBEDTLS_OID_SERVER_AUTH); + } else { + ext_oid = MBEDTLS_OID_CLIENT_AUTH; + ext_len = MBEDTLS_OID_SIZE(MBEDTLS_OID_CLIENT_AUTH); + } + + if (mbedtls_x509_crt_check_extended_key_usage(cert, ext_oid, ext_len) != 0) { + *flags |= MBEDTLS_X509_BADCERT_EXT_KEY_USAGE; + ret = -1; + } + + return ret; +} +#endif /* MBEDTLS_X509_CRT_PARSE_C */ + +#if defined(MBEDTLS_USE_PSA_CRYPTO) +int mbedtls_ssl_get_handshake_transcript(mbedtls_ssl_context *ssl, + const mbedtls_md_type_t md, + unsigned char *dst, + size_t dst_len, + size_t *olen) +{ + psa_status_t status = PSA_ERROR_CORRUPTION_DETECTED; + psa_hash_operation_t *hash_operation_to_clone; + psa_hash_operation_t hash_operation = psa_hash_operation_init(); + + *olen = 0; + + switch (md) { +#if defined(MBEDTLS_MD_CAN_SHA384) + case MBEDTLS_MD_SHA384: + hash_operation_to_clone = &ssl->handshake->fin_sha384_psa; + break; +#endif + +#if defined(MBEDTLS_MD_CAN_SHA256) + case MBEDTLS_MD_SHA256: + hash_operation_to_clone = &ssl->handshake->fin_sha256_psa; + break; +#endif + + default: + goto exit; + } + + status = psa_hash_clone(hash_operation_to_clone, &hash_operation); + if (status != PSA_SUCCESS) { + goto exit; + } + + status = psa_hash_finish(&hash_operation, dst, dst_len, olen); + if (status != PSA_SUCCESS) { + goto exit; + } + +exit: +#if !defined(MBEDTLS_MD_CAN_SHA384) && \ + !defined(MBEDTLS_MD_CAN_SHA256) + (void) ssl; +#endif + return PSA_TO_MBEDTLS_ERR(status); +} +#else /* MBEDTLS_USE_PSA_CRYPTO */ + +#if defined(MBEDTLS_MD_CAN_SHA384) +MBEDTLS_CHECK_RETURN_CRITICAL +static int ssl_get_handshake_transcript_sha384(mbedtls_ssl_context *ssl, + unsigned char *dst, + size_t dst_len, + size_t *olen) +{ + int ret; + mbedtls_md_context_t sha384; + + if (dst_len < 48) { + return MBEDTLS_ERR_SSL_INTERNAL_ERROR; + } + + mbedtls_md_init(&sha384); + ret = mbedtls_md_setup(&sha384, mbedtls_md_info_from_type(MBEDTLS_MD_SHA384), 0); + if (ret != 0) { + goto exit; + } + ret = mbedtls_md_clone(&sha384, &ssl->handshake->fin_sha384); + if (ret != 0) { + goto exit; + } + + if ((ret = mbedtls_md_finish(&sha384, dst)) != 0) { + MBEDTLS_SSL_DEBUG_RET(1, "mbedtls_md_finish", ret); + goto exit; + } + + *olen = 48; + +exit: + + mbedtls_md_free(&sha384); + return ret; +} +#endif /* MBEDTLS_MD_CAN_SHA384 */ + +#if defined(MBEDTLS_MD_CAN_SHA256) +MBEDTLS_CHECK_RETURN_CRITICAL +static int ssl_get_handshake_transcript_sha256(mbedtls_ssl_context *ssl, + unsigned char *dst, + size_t dst_len, + size_t *olen) +{ + int ret; + mbedtls_md_context_t sha256; + + if (dst_len < 32) { + return MBEDTLS_ERR_SSL_INTERNAL_ERROR; + } + + mbedtls_md_init(&sha256); + ret = mbedtls_md_setup(&sha256, mbedtls_md_info_from_type(MBEDTLS_MD_SHA256), 0); + if (ret != 0) { + goto exit; + } + ret = mbedtls_md_clone(&sha256, &ssl->handshake->fin_sha256); + if (ret != 0) { + goto exit; + } + + if ((ret = mbedtls_md_finish(&sha256, dst)) != 0) { + MBEDTLS_SSL_DEBUG_RET(1, "mbedtls_md_finish", ret); + goto exit; + } + + *olen = 32; + +exit: + + mbedtls_md_free(&sha256); + return ret; +} +#endif /* MBEDTLS_MD_CAN_SHA256 */ + +int mbedtls_ssl_get_handshake_transcript(mbedtls_ssl_context *ssl, + const mbedtls_md_type_t md, + unsigned char *dst, + size_t dst_len, + size_t *olen) +{ + switch (md) { + +#if defined(MBEDTLS_MD_CAN_SHA384) + case MBEDTLS_MD_SHA384: + return ssl_get_handshake_transcript_sha384(ssl, dst, dst_len, olen); +#endif /* MBEDTLS_MD_CAN_SHA384*/ + +#if defined(MBEDTLS_MD_CAN_SHA256) + case MBEDTLS_MD_SHA256: + return ssl_get_handshake_transcript_sha256(ssl, dst, dst_len, olen); +#endif /* MBEDTLS_MD_CAN_SHA256*/ + + default: +#if !defined(MBEDTLS_MD_CAN_SHA384) && \ + !defined(MBEDTLS_MD_CAN_SHA256) + (void) ssl; + (void) dst; + (void) dst_len; + (void) olen; +#endif + break; + } + return MBEDTLS_ERR_SSL_INTERNAL_ERROR; +} + +#endif /* !MBEDTLS_USE_PSA_CRYPTO */ + +#if defined(MBEDTLS_SSL_HANDSHAKE_WITH_CERT_ENABLED) +/* mbedtls_ssl_parse_sig_alg_ext() + * + * The `extension_data` field of signature algorithm contains a `SignatureSchemeList` + * value (TLS 1.3 RFC8446): + * enum { + * .... + * ecdsa_secp256r1_sha256( 0x0403 ), + * ecdsa_secp384r1_sha384( 0x0503 ), + * ecdsa_secp521r1_sha512( 0x0603 ), + * .... + * } SignatureScheme; + * + * struct { + * SignatureScheme supported_signature_algorithms<2..2^16-2>; + * } SignatureSchemeList; + * + * The `extension_data` field of signature algorithm contains a `SignatureAndHashAlgorithm` + * value (TLS 1.2 RFC5246): + * enum { + * none(0), md5(1), sha1(2), sha224(3), sha256(4), sha384(5), + * sha512(6), (255) + * } HashAlgorithm; + * + * enum { anonymous(0), rsa(1), dsa(2), ecdsa(3), (255) } + * SignatureAlgorithm; + * + * struct { + * HashAlgorithm hash; + * SignatureAlgorithm signature; + * } SignatureAndHashAlgorithm; + * + * SignatureAndHashAlgorithm + * supported_signature_algorithms<2..2^16-2>; + * + * The TLS 1.3 signature algorithm extension was defined to be a compatible + * generalization of the TLS 1.2 signature algorithm extension. + * `SignatureAndHashAlgorithm` field of TLS 1.2 can be represented by + * `SignatureScheme` field of TLS 1.3 + * + */ +int mbedtls_ssl_parse_sig_alg_ext(mbedtls_ssl_context *ssl, + const unsigned char *buf, + const unsigned char *end) +{ + const unsigned char *p = buf; + size_t supported_sig_algs_len = 0; + const unsigned char *supported_sig_algs_end; + uint16_t sig_alg; + uint32_t common_idx = 0; + + MBEDTLS_SSL_CHK_BUF_READ_PTR(p, end, 2); + supported_sig_algs_len = MBEDTLS_GET_UINT16_BE(p, 0); + p += 2; + + memset(ssl->handshake->received_sig_algs, 0, + sizeof(ssl->handshake->received_sig_algs)); + + MBEDTLS_SSL_CHK_BUF_READ_PTR(p, end, supported_sig_algs_len); + supported_sig_algs_end = p + supported_sig_algs_len; + while (p < supported_sig_algs_end) { + MBEDTLS_SSL_CHK_BUF_READ_PTR(p, supported_sig_algs_end, 2); + sig_alg = MBEDTLS_GET_UINT16_BE(p, 0); + p += 2; + MBEDTLS_SSL_DEBUG_MSG(4, ("received signature algorithm: 0x%x %s", + sig_alg, + mbedtls_ssl_sig_alg_to_str(sig_alg))); +#if defined(MBEDTLS_SSL_PROTO_TLS1_2) + if (ssl->tls_version == MBEDTLS_SSL_VERSION_TLS1_2 && + (!(mbedtls_ssl_sig_alg_is_supported(ssl, sig_alg) && + mbedtls_ssl_sig_alg_is_offered(ssl, sig_alg)))) { + continue; + } +#endif /* MBEDTLS_SSL_PROTO_TLS1_2 */ + + MBEDTLS_SSL_DEBUG_MSG(4, ("valid signature algorithm: %s", + mbedtls_ssl_sig_alg_to_str(sig_alg))); + + if (common_idx + 1 < MBEDTLS_RECEIVED_SIG_ALGS_SIZE) { + ssl->handshake->received_sig_algs[common_idx] = sig_alg; + common_idx += 1; + } + } + /* Check that we consumed all the message. */ + if (p != end) { + MBEDTLS_SSL_DEBUG_MSG(1, + ("Signature algorithms extension length misaligned")); + MBEDTLS_SSL_PEND_FATAL_ALERT(MBEDTLS_SSL_ALERT_MSG_DECODE_ERROR, + MBEDTLS_ERR_SSL_DECODE_ERROR); + return MBEDTLS_ERR_SSL_DECODE_ERROR; + } + + if (common_idx == 0) { + MBEDTLS_SSL_DEBUG_MSG(3, ("no signature algorithm in common")); + MBEDTLS_SSL_PEND_FATAL_ALERT(MBEDTLS_SSL_ALERT_MSG_HANDSHAKE_FAILURE, + MBEDTLS_ERR_SSL_HANDSHAKE_FAILURE); + return MBEDTLS_ERR_SSL_HANDSHAKE_FAILURE; + } + + ssl->handshake->received_sig_algs[common_idx] = MBEDTLS_TLS_SIG_NONE; + return 0; +} + +#endif /* MBEDTLS_SSL_HANDSHAKE_WITH_CERT_ENABLED */ + +#if defined(MBEDTLS_SSL_PROTO_TLS1_2) + +#if defined(MBEDTLS_USE_PSA_CRYPTO) + +static psa_status_t setup_psa_key_derivation(psa_key_derivation_operation_t *derivation, + mbedtls_svc_key_id_t key, + psa_algorithm_t alg, + const unsigned char *raw_psk, size_t raw_psk_length, + const unsigned char *seed, size_t seed_length, + const unsigned char *label, size_t label_length, + const unsigned char *other_secret, + size_t other_secret_length, + size_t capacity) +{ + psa_status_t status; + + status = psa_key_derivation_setup(derivation, alg); + if (status != PSA_SUCCESS) { + return status; + } + + if (PSA_ALG_IS_TLS12_PRF(alg) || PSA_ALG_IS_TLS12_PSK_TO_MS(alg)) { + status = psa_key_derivation_input_bytes(derivation, + PSA_KEY_DERIVATION_INPUT_SEED, + seed, seed_length); + if (status != PSA_SUCCESS) { + return status; + } + + if (other_secret != NULL) { + status = psa_key_derivation_input_bytes(derivation, + PSA_KEY_DERIVATION_INPUT_OTHER_SECRET, + other_secret, other_secret_length); + if (status != PSA_SUCCESS) { + return status; + } + } + + if (mbedtls_svc_key_id_is_null(key)) { + status = psa_key_derivation_input_bytes( + derivation, PSA_KEY_DERIVATION_INPUT_SECRET, + raw_psk, raw_psk_length); + } else { + status = psa_key_derivation_input_key( + derivation, PSA_KEY_DERIVATION_INPUT_SECRET, key); + } + if (status != PSA_SUCCESS) { + return status; + } + + status = psa_key_derivation_input_bytes(derivation, + PSA_KEY_DERIVATION_INPUT_LABEL, + label, label_length); + if (status != PSA_SUCCESS) { + return status; + } + } else { + return PSA_ERROR_NOT_SUPPORTED; + } + + status = psa_key_derivation_set_capacity(derivation, capacity); + if (status != PSA_SUCCESS) { + return status; + } + + return PSA_SUCCESS; +} + +#if defined(PSA_WANT_ALG_SHA_384) || \ + defined(PSA_WANT_ALG_SHA_256) +MBEDTLS_CHECK_RETURN_CRITICAL +static int tls_prf_generic(mbedtls_md_type_t md_type, + const unsigned char *secret, size_t slen, + const char *label, + const unsigned char *random, size_t rlen, + unsigned char *dstbuf, size_t dlen) +{ + psa_status_t status; + psa_algorithm_t alg; + mbedtls_svc_key_id_t master_key = MBEDTLS_SVC_KEY_ID_INIT; + psa_key_derivation_operation_t derivation = + PSA_KEY_DERIVATION_OPERATION_INIT; + + if (md_type == MBEDTLS_MD_SHA384) { + alg = PSA_ALG_TLS12_PRF(PSA_ALG_SHA_384); + } else { + alg = PSA_ALG_TLS12_PRF(PSA_ALG_SHA_256); + } + + /* Normally a "secret" should be long enough to be impossible to + * find by brute force, and in particular should not be empty. But + * this PRF is also used to derive an IV, in particular in EAP-TLS, + * and for this use case it makes sense to have a 0-length "secret". + * Since the key API doesn't allow importing a key of length 0, + * keep master_key=0, which setup_psa_key_derivation() understands + * to mean a 0-length "secret" input. */ + if (slen != 0) { + psa_key_attributes_t key_attributes = psa_key_attributes_init(); + psa_set_key_usage_flags(&key_attributes, PSA_KEY_USAGE_DERIVE); + psa_set_key_algorithm(&key_attributes, alg); + psa_set_key_type(&key_attributes, PSA_KEY_TYPE_DERIVE); + + status = psa_import_key(&key_attributes, secret, slen, &master_key); + if (status != PSA_SUCCESS) { + return MBEDTLS_ERR_SSL_HW_ACCEL_FAILED; + } + } + + status = setup_psa_key_derivation(&derivation, + master_key, alg, + NULL, 0, + random, rlen, + (unsigned char const *) label, + (size_t) strlen(label), + NULL, 0, + dlen); + if (status != PSA_SUCCESS) { + psa_key_derivation_abort(&derivation); + psa_destroy_key(master_key); + return MBEDTLS_ERR_SSL_HW_ACCEL_FAILED; + } + + status = psa_key_derivation_output_bytes(&derivation, dstbuf, dlen); + if (status != PSA_SUCCESS) { + psa_key_derivation_abort(&derivation); + psa_destroy_key(master_key); + return MBEDTLS_ERR_SSL_HW_ACCEL_FAILED; + } + + status = psa_key_derivation_abort(&derivation); + if (status != PSA_SUCCESS) { + psa_destroy_key(master_key); + return MBEDTLS_ERR_SSL_HW_ACCEL_FAILED; + } + + if (!mbedtls_svc_key_id_is_null(master_key)) { + status = psa_destroy_key(master_key); + } + if (status != PSA_SUCCESS) { + return MBEDTLS_ERR_SSL_HW_ACCEL_FAILED; + } + + return 0; +} +#endif /* PSA_WANT_ALG_SHA_256 || PSA_WANT_ALG_SHA_384 */ +#else /* MBEDTLS_USE_PSA_CRYPTO */ + +#if defined(MBEDTLS_MD_C) && \ + (defined(MBEDTLS_MD_CAN_SHA256) || \ + defined(MBEDTLS_MD_CAN_SHA384)) +MBEDTLS_CHECK_RETURN_CRITICAL +static int tls_prf_generic(mbedtls_md_type_t md_type, + const unsigned char *secret, size_t slen, + const char *label, + const unsigned char *random, size_t rlen, + unsigned char *dstbuf, size_t dlen) +{ + size_t nb; + size_t i, j, k, md_len; + unsigned char *tmp; + size_t tmp_len = 0; + unsigned char h_i[MBEDTLS_MD_MAX_SIZE]; + const mbedtls_md_info_t *md_info; + mbedtls_md_context_t md_ctx; + int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED; + + mbedtls_md_init(&md_ctx); + + if ((md_info = mbedtls_md_info_from_type(md_type)) == NULL) { + return MBEDTLS_ERR_SSL_INTERNAL_ERROR; + } + + md_len = mbedtls_md_get_size(md_info); + + tmp_len = md_len + strlen(label) + rlen; + tmp = mbedtls_calloc(1, tmp_len); + if (tmp == NULL) { + ret = MBEDTLS_ERR_SSL_ALLOC_FAILED; + goto exit; + } + + nb = strlen(label); + memcpy(tmp + md_len, label, nb); + memcpy(tmp + md_len + nb, random, rlen); + nb += rlen; + + /* + * Compute P_(secret, label + random)[0..dlen] + */ + if ((ret = mbedtls_md_setup(&md_ctx, md_info, 1)) != 0) { + goto exit; + } + + ret = mbedtls_md_hmac_starts(&md_ctx, secret, slen); + if (ret != 0) { + goto exit; + } + ret = mbedtls_md_hmac_update(&md_ctx, tmp + md_len, nb); + if (ret != 0) { + goto exit; + } + ret = mbedtls_md_hmac_finish(&md_ctx, tmp); + if (ret != 0) { + goto exit; + } + + for (i = 0; i < dlen; i += md_len) { + ret = mbedtls_md_hmac_reset(&md_ctx); + if (ret != 0) { + goto exit; + } + ret = mbedtls_md_hmac_update(&md_ctx, tmp, md_len + nb); + if (ret != 0) { + goto exit; + } + ret = mbedtls_md_hmac_finish(&md_ctx, h_i); + if (ret != 0) { + goto exit; + } + + ret = mbedtls_md_hmac_reset(&md_ctx); + if (ret != 0) { + goto exit; + } + ret = mbedtls_md_hmac_update(&md_ctx, tmp, md_len); + if (ret != 0) { + goto exit; + } + ret = mbedtls_md_hmac_finish(&md_ctx, tmp); + if (ret != 0) { + goto exit; + } + + k = (i + md_len > dlen) ? dlen % md_len : md_len; + + for (j = 0; j < k; j++) { + dstbuf[i + j] = h_i[j]; + } + } + +exit: + mbedtls_md_free(&md_ctx); + + if (tmp != NULL) { + mbedtls_platform_zeroize(tmp, tmp_len); + } + + mbedtls_platform_zeroize(h_i, sizeof(h_i)); + + mbedtls_free(tmp); + + return ret; +} +#endif /* MBEDTLS_MD_C && ( MBEDTLS_MD_CAN_SHA256 || MBEDTLS_MD_CAN_SHA384 ) */ +#endif /* MBEDTLS_USE_PSA_CRYPTO */ + +#if defined(MBEDTLS_MD_CAN_SHA256) +MBEDTLS_CHECK_RETURN_CRITICAL +static int tls_prf_sha256(const unsigned char *secret, size_t slen, + const char *label, + const unsigned char *random, size_t rlen, + unsigned char *dstbuf, size_t dlen) +{ + return tls_prf_generic(MBEDTLS_MD_SHA256, secret, slen, + label, random, rlen, dstbuf, dlen); +} +#endif /* MBEDTLS_MD_CAN_SHA256*/ + +#if defined(MBEDTLS_MD_CAN_SHA384) +MBEDTLS_CHECK_RETURN_CRITICAL +static int tls_prf_sha384(const unsigned char *secret, size_t slen, + const char *label, + const unsigned char *random, size_t rlen, + unsigned char *dstbuf, size_t dlen) +{ + return tls_prf_generic(MBEDTLS_MD_SHA384, secret, slen, + label, random, rlen, dstbuf, dlen); +} +#endif /* MBEDTLS_MD_CAN_SHA384*/ + +/* + * Set appropriate PRF function and other SSL / TLS1.2 functions + * + * Inputs: + * - hash associated with the ciphersuite (only used by TLS 1.2) + * + * Outputs: + * - the tls_prf, calc_verify and calc_finished members of handshake structure + */ +MBEDTLS_CHECK_RETURN_CRITICAL +static int ssl_set_handshake_prfs(mbedtls_ssl_handshake_params *handshake, + mbedtls_md_type_t hash) +{ +#if defined(MBEDTLS_MD_CAN_SHA384) + if (hash == MBEDTLS_MD_SHA384) { + handshake->tls_prf = tls_prf_sha384; + handshake->calc_verify = ssl_calc_verify_tls_sha384; + handshake->calc_finished = ssl_calc_finished_tls_sha384; + } else +#endif +#if defined(MBEDTLS_MD_CAN_SHA256) + { + (void) hash; + handshake->tls_prf = tls_prf_sha256; + handshake->calc_verify = ssl_calc_verify_tls_sha256; + handshake->calc_finished = ssl_calc_finished_tls_sha256; + } +#else + { + (void) handshake; + (void) hash; + return MBEDTLS_ERR_SSL_INTERNAL_ERROR; + } +#endif + + return 0; +} + +/* + * Compute master secret if needed + * + * Parameters: + * [in/out] handshake + * [in] resume, premaster, extended_ms, calc_verify, tls_prf + * (PSA-PSK) ciphersuite_info, psk_opaque + * [out] premaster (cleared) + * [out] master + * [in] ssl: optionally used for debugging, EMS and PSA-PSK + * debug: conf->f_dbg, conf->p_dbg + * EMS: passed to calc_verify (debug + session_negotiate) + * PSA-PSA: conf + */ +MBEDTLS_CHECK_RETURN_CRITICAL +static int ssl_compute_master(mbedtls_ssl_handshake_params *handshake, + unsigned char *master, + const mbedtls_ssl_context *ssl) +{ + int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED; + + /* cf. RFC 5246, Section 8.1: + * "The master secret is always exactly 48 bytes in length." */ + size_t const master_secret_len = 48; + +#if defined(MBEDTLS_SSL_EXTENDED_MASTER_SECRET) + unsigned char session_hash[48]; +#endif /* MBEDTLS_SSL_EXTENDED_MASTER_SECRET */ + + /* The label for the KDF used for key expansion. + * This is either "master secret" or "extended master secret" + * depending on whether the Extended Master Secret extension + * is used. */ + char const *lbl = "master secret"; + + /* The seed for the KDF used for key expansion. + * - If the Extended Master Secret extension is not used, + * this is ClientHello.Random + ServerHello.Random + * (see Sect. 8.1 in RFC 5246). + * - If the Extended Master Secret extension is used, + * this is the transcript of the handshake so far. + * (see Sect. 4 in RFC 7627). */ + unsigned char const *seed = handshake->randbytes; + size_t seed_len = 64; + +#if !defined(MBEDTLS_DEBUG_C) && \ + !defined(MBEDTLS_SSL_EXTENDED_MASTER_SECRET) && \ + !(defined(MBEDTLS_USE_PSA_CRYPTO) && \ + defined(MBEDTLS_KEY_EXCHANGE_PSK_ENABLED)) + ssl = NULL; /* make sure we don't use it except for those cases */ + (void) ssl; +#endif + + if (handshake->resume != 0) { + MBEDTLS_SSL_DEBUG_MSG(3, ("no premaster (session resumed)")); + return 0; + } + +#if defined(MBEDTLS_SSL_EXTENDED_MASTER_SECRET) + if (handshake->extended_ms == MBEDTLS_SSL_EXTENDED_MS_ENABLED) { + lbl = "extended master secret"; + seed = session_hash; + ret = handshake->calc_verify(ssl, session_hash, &seed_len); + if (ret != 0) { + MBEDTLS_SSL_DEBUG_RET(1, "calc_verify", ret); + } + + MBEDTLS_SSL_DEBUG_BUF(3, "session hash for extended master secret", + session_hash, seed_len); + } +#endif /* MBEDTLS_SSL_EXTENDED_MASTER_SECRET */ + +#if defined(MBEDTLS_USE_PSA_CRYPTO) && \ + defined(MBEDTLS_KEY_EXCHANGE_SOME_PSK_ENABLED) + if (mbedtls_ssl_ciphersuite_uses_psk(handshake->ciphersuite_info) == 1) { + /* Perform PSK-to-MS expansion in a single step. */ + psa_status_t status; + psa_algorithm_t alg; + mbedtls_svc_key_id_t psk; + psa_key_derivation_operation_t derivation = + PSA_KEY_DERIVATION_OPERATION_INIT; + mbedtls_md_type_t hash_alg = (mbedtls_md_type_t) handshake->ciphersuite_info->mac; + + MBEDTLS_SSL_DEBUG_MSG(2, ("perform PSA-based PSK-to-MS expansion")); + + psk = mbedtls_ssl_get_opaque_psk(ssl); + + if (hash_alg == MBEDTLS_MD_SHA384) { + alg = PSA_ALG_TLS12_PSK_TO_MS(PSA_ALG_SHA_384); + } else { + alg = PSA_ALG_TLS12_PSK_TO_MS(PSA_ALG_SHA_256); + } + + size_t other_secret_len = 0; + unsigned char *other_secret = NULL; + + switch (handshake->ciphersuite_info->key_exchange) { + /* Provide other secret. + * Other secret is stored in premaster, where first 2 bytes hold the + * length of the other key. + */ + case MBEDTLS_KEY_EXCHANGE_RSA_PSK: + /* For RSA-PSK other key length is always 48 bytes. */ + other_secret_len = 48; + other_secret = handshake->premaster + 2; + break; + case MBEDTLS_KEY_EXCHANGE_ECDHE_PSK: + case MBEDTLS_KEY_EXCHANGE_DHE_PSK: + other_secret_len = MBEDTLS_GET_UINT16_BE(handshake->premaster, 0); + other_secret = handshake->premaster + 2; + break; + default: + break; + } + + status = setup_psa_key_derivation(&derivation, psk, alg, + ssl->conf->psk, ssl->conf->psk_len, + seed, seed_len, + (unsigned char const *) lbl, + (size_t) strlen(lbl), + other_secret, other_secret_len, + master_secret_len); + if (status != PSA_SUCCESS) { + psa_key_derivation_abort(&derivation); + return MBEDTLS_ERR_SSL_HW_ACCEL_FAILED; + } + + status = psa_key_derivation_output_bytes(&derivation, + master, + master_secret_len); + if (status != PSA_SUCCESS) { + psa_key_derivation_abort(&derivation); + return MBEDTLS_ERR_SSL_HW_ACCEL_FAILED; + } + + status = psa_key_derivation_abort(&derivation); + if (status != PSA_SUCCESS) { + return MBEDTLS_ERR_SSL_HW_ACCEL_FAILED; + } + } else +#endif + { +#if defined(MBEDTLS_USE_PSA_CRYPTO) && \ + defined(MBEDTLS_KEY_EXCHANGE_ECJPAKE_ENABLED) + if (handshake->ciphersuite_info->key_exchange == MBEDTLS_KEY_EXCHANGE_ECJPAKE) { + psa_status_t status; + psa_algorithm_t alg = PSA_ALG_TLS12_ECJPAKE_TO_PMS; + psa_key_derivation_operation_t derivation = + PSA_KEY_DERIVATION_OPERATION_INIT; + + MBEDTLS_SSL_DEBUG_MSG(2, ("perform PSA-based PMS KDF for ECJPAKE")); + + handshake->pmslen = PSA_TLS12_ECJPAKE_TO_PMS_DATA_SIZE; + + status = psa_key_derivation_setup(&derivation, alg); + if (status != PSA_SUCCESS) { + return MBEDTLS_ERR_SSL_HW_ACCEL_FAILED; + } + + status = psa_key_derivation_set_capacity(&derivation, + PSA_TLS12_ECJPAKE_TO_PMS_DATA_SIZE); + if (status != PSA_SUCCESS) { + psa_key_derivation_abort(&derivation); + return MBEDTLS_ERR_SSL_HW_ACCEL_FAILED; + } + + status = psa_pake_get_implicit_key(&handshake->psa_pake_ctx, + &derivation); + if (status != PSA_SUCCESS) { + psa_key_derivation_abort(&derivation); + return MBEDTLS_ERR_SSL_HW_ACCEL_FAILED; + } + + status = psa_key_derivation_output_bytes(&derivation, + handshake->premaster, + handshake->pmslen); + if (status != PSA_SUCCESS) { + psa_key_derivation_abort(&derivation); + return MBEDTLS_ERR_SSL_HW_ACCEL_FAILED; + } + + status = psa_key_derivation_abort(&derivation); + if (status != PSA_SUCCESS) { + return MBEDTLS_ERR_SSL_HW_ACCEL_FAILED; + } + } +#endif + ret = handshake->tls_prf(handshake->premaster, handshake->pmslen, + lbl, seed, seed_len, + master, + master_secret_len); + if (ret != 0) { + MBEDTLS_SSL_DEBUG_RET(1, "prf", ret); + return ret; + } + + MBEDTLS_SSL_DEBUG_BUF(3, "premaster secret", + handshake->premaster, + handshake->pmslen); + + mbedtls_platform_zeroize(handshake->premaster, + sizeof(handshake->premaster)); + } + + return 0; +} + +int mbedtls_ssl_derive_keys(mbedtls_ssl_context *ssl) +{ + int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED; + const mbedtls_ssl_ciphersuite_t * const ciphersuite_info = + ssl->handshake->ciphersuite_info; + + MBEDTLS_SSL_DEBUG_MSG(2, ("=> derive keys")); + + /* Set PRF, calc_verify and calc_finished function pointers */ + ret = ssl_set_handshake_prfs(ssl->handshake, + (mbedtls_md_type_t) ciphersuite_info->mac); + if (ret != 0) { + MBEDTLS_SSL_DEBUG_RET(1, "ssl_set_handshake_prfs", ret); + return ret; + } + + /* Compute master secret if needed */ + ret = ssl_compute_master(ssl->handshake, + ssl->session_negotiate->master, + ssl); + if (ret != 0) { + MBEDTLS_SSL_DEBUG_RET(1, "ssl_compute_master", ret); + return ret; + } + + /* Swap the client and server random values: + * - MS derivation wanted client+server (RFC 5246 8.1) + * - key derivation wants server+client (RFC 5246 6.3) */ + { + unsigned char tmp[64]; + memcpy(tmp, ssl->handshake->randbytes, 64); + memcpy(ssl->handshake->randbytes, tmp + 32, 32); + memcpy(ssl->handshake->randbytes + 32, tmp, 32); + mbedtls_platform_zeroize(tmp, sizeof(tmp)); + } + + /* Populate transform structure */ + ret = ssl_tls12_populate_transform(ssl->transform_negotiate, + ssl->session_negotiate->ciphersuite, + ssl->session_negotiate->master, +#if defined(MBEDTLS_SSL_SOME_SUITES_USE_CBC_ETM) + ssl->session_negotiate->encrypt_then_mac, +#endif /* MBEDTLS_SSL_SOME_SUITES_USE_CBC_ETM */ + ssl->handshake->tls_prf, + ssl->handshake->randbytes, + ssl->tls_version, + ssl->conf->endpoint, + ssl); + if (ret != 0) { + MBEDTLS_SSL_DEBUG_RET(1, "ssl_tls12_populate_transform", ret); + return ret; + } + + /* We no longer need Server/ClientHello.random values */ + mbedtls_platform_zeroize(ssl->handshake->randbytes, + sizeof(ssl->handshake->randbytes)); + + MBEDTLS_SSL_DEBUG_MSG(2, ("<= derive keys")); + + return 0; +} + +int mbedtls_ssl_set_calc_verify_md(mbedtls_ssl_context *ssl, int md) +{ + switch (md) { +#if defined(MBEDTLS_MD_CAN_SHA384) + case MBEDTLS_SSL_HASH_SHA384: + ssl->handshake->calc_verify = ssl_calc_verify_tls_sha384; + break; +#endif +#if defined(MBEDTLS_MD_CAN_SHA256) + case MBEDTLS_SSL_HASH_SHA256: + ssl->handshake->calc_verify = ssl_calc_verify_tls_sha256; + break; +#endif + default: + return -1; + } +#if !defined(MBEDTLS_MD_CAN_SHA384) && \ + !defined(MBEDTLS_MD_CAN_SHA256) + (void) ssl; +#endif + return 0; +} + +#if defined(MBEDTLS_USE_PSA_CRYPTO) +static int ssl_calc_verify_tls_psa(const mbedtls_ssl_context *ssl, + const psa_hash_operation_t *hs_op, + size_t buffer_size, + unsigned char *hash, + size_t *hlen) +{ + psa_status_t status; + psa_hash_operation_t cloned_op = psa_hash_operation_init(); + +#if !defined(MBEDTLS_DEBUG_C) + (void) ssl; +#endif + MBEDTLS_SSL_DEBUG_MSG(2, ("=> PSA calc verify")); + status = psa_hash_clone(hs_op, &cloned_op); + if (status != PSA_SUCCESS) { + goto exit; + } + + status = psa_hash_finish(&cloned_op, hash, buffer_size, hlen); + if (status != PSA_SUCCESS) { + goto exit; + } + + MBEDTLS_SSL_DEBUG_BUF(3, "PSA calculated verify result", hash, *hlen); + MBEDTLS_SSL_DEBUG_MSG(2, ("<= PSA calc verify")); + +exit: + psa_hash_abort(&cloned_op); + return mbedtls_md_error_from_psa(status); +} +#else +static int ssl_calc_verify_tls_legacy(const mbedtls_ssl_context *ssl, + const mbedtls_md_context_t *hs_ctx, + unsigned char *hash, + size_t *hlen) +{ + int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED; + mbedtls_md_context_t cloned_ctx; + + mbedtls_md_init(&cloned_ctx); + +#if !defined(MBEDTLS_DEBUG_C) + (void) ssl; +#endif + MBEDTLS_SSL_DEBUG_MSG(2, ("=> calc verify")); + + ret = mbedtls_md_setup(&cloned_ctx, mbedtls_md_info_from_ctx(hs_ctx), 0); + if (ret != 0) { + goto exit; + } + ret = mbedtls_md_clone(&cloned_ctx, hs_ctx); + if (ret != 0) { + goto exit; + } + + ret = mbedtls_md_finish(&cloned_ctx, hash); + if (ret != 0) { + goto exit; + } + + *hlen = mbedtls_md_get_size(mbedtls_md_info_from_ctx(hs_ctx)); + + MBEDTLS_SSL_DEBUG_BUF(3, "calculated verify result", hash, *hlen); + MBEDTLS_SSL_DEBUG_MSG(2, ("<= calc verify")); + +exit: + mbedtls_md_free(&cloned_ctx); + return ret; +} +#endif /* MBEDTLS_USE_PSA_CRYPTO */ + +#if defined(MBEDTLS_MD_CAN_SHA256) +int ssl_calc_verify_tls_sha256(const mbedtls_ssl_context *ssl, + unsigned char *hash, + size_t *hlen) +{ +#if defined(MBEDTLS_USE_PSA_CRYPTO) + return ssl_calc_verify_tls_psa(ssl, &ssl->handshake->fin_sha256_psa, 32, + hash, hlen); +#else + return ssl_calc_verify_tls_legacy(ssl, &ssl->handshake->fin_sha256, + hash, hlen); +#endif /* MBEDTLS_USE_PSA_CRYPTO */ +} +#endif /* MBEDTLS_MD_CAN_SHA256 */ + +#if defined(MBEDTLS_MD_CAN_SHA384) +int ssl_calc_verify_tls_sha384(const mbedtls_ssl_context *ssl, + unsigned char *hash, + size_t *hlen) +{ +#if defined(MBEDTLS_USE_PSA_CRYPTO) + return ssl_calc_verify_tls_psa(ssl, &ssl->handshake->fin_sha384_psa, 48, + hash, hlen); +#else + return ssl_calc_verify_tls_legacy(ssl, &ssl->handshake->fin_sha384, + hash, hlen); +#endif /* MBEDTLS_USE_PSA_CRYPTO */ +} +#endif /* MBEDTLS_MD_CAN_SHA384 */ + +#if !defined(MBEDTLS_USE_PSA_CRYPTO) && \ + defined(MBEDTLS_KEY_EXCHANGE_SOME_PSK_ENABLED) +int mbedtls_ssl_psk_derive_premaster(mbedtls_ssl_context *ssl, mbedtls_key_exchange_type_t key_ex) +{ + unsigned char *p = ssl->handshake->premaster; + unsigned char *end = p + sizeof(ssl->handshake->premaster); + const unsigned char *psk = NULL; + size_t psk_len = 0; + int psk_ret = mbedtls_ssl_get_psk(ssl, &psk, &psk_len); + + if (psk_ret == MBEDTLS_ERR_SSL_PRIVATE_KEY_REQUIRED) { + /* + * This should never happen because the existence of a PSK is always + * checked before calling this function. + * + * The exception is opaque DHE-PSK. For DHE-PSK fill premaster with + * the shared secret without PSK. + */ + if (key_ex != MBEDTLS_KEY_EXCHANGE_DHE_PSK) { + MBEDTLS_SSL_DEBUG_MSG(1, ("should never happen")); + return MBEDTLS_ERR_SSL_INTERNAL_ERROR; + } + } + + /* + * PMS = struct { + * opaque other_secret<0..2^16-1>; + * opaque psk<0..2^16-1>; + * }; + * with "other_secret" depending on the particular key exchange + */ +#if defined(MBEDTLS_KEY_EXCHANGE_PSK_ENABLED) + if (key_ex == MBEDTLS_KEY_EXCHANGE_PSK) { + if (end - p < 2) { + return MBEDTLS_ERR_SSL_BAD_INPUT_DATA; + } + + MBEDTLS_PUT_UINT16_BE(psk_len, p, 0); + p += 2; + + if (end < p || (size_t) (end - p) < psk_len) { + return MBEDTLS_ERR_SSL_BAD_INPUT_DATA; + } + + memset(p, 0, psk_len); + p += psk_len; + } else +#endif /* MBEDTLS_KEY_EXCHANGE_PSK_ENABLED */ +#if defined(MBEDTLS_KEY_EXCHANGE_RSA_PSK_ENABLED) + if (key_ex == MBEDTLS_KEY_EXCHANGE_RSA_PSK) { + /* + * other_secret already set by the ClientKeyExchange message, + * and is 48 bytes long + */ + if (end - p < 2) { + return MBEDTLS_ERR_SSL_BAD_INPUT_DATA; + } + + *p++ = 0; + *p++ = 48; + p += 48; + } else +#endif /* MBEDTLS_KEY_EXCHANGE_RSA_PSK_ENABLED */ +#if defined(MBEDTLS_KEY_EXCHANGE_DHE_PSK_ENABLED) + if (key_ex == MBEDTLS_KEY_EXCHANGE_DHE_PSK) { + int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED; + size_t len; + + /* Write length only when we know the actual value */ + if ((ret = mbedtls_dhm_calc_secret(&ssl->handshake->dhm_ctx, + p + 2, (size_t) (end - (p + 2)), &len, + ssl->conf->f_rng, ssl->conf->p_rng)) != 0) { + MBEDTLS_SSL_DEBUG_RET(1, "mbedtls_dhm_calc_secret", ret); + return ret; + } + MBEDTLS_PUT_UINT16_BE(len, p, 0); + p += 2 + len; + + MBEDTLS_SSL_DEBUG_MPI(3, "DHM: K ", &ssl->handshake->dhm_ctx.K); + } else +#endif /* MBEDTLS_KEY_EXCHANGE_DHE_PSK_ENABLED */ +#if defined(MBEDTLS_KEY_EXCHANGE_ECDHE_PSK_ENABLED) + if (key_ex == MBEDTLS_KEY_EXCHANGE_ECDHE_PSK) { + int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED; + size_t zlen; + + if ((ret = mbedtls_ecdh_calc_secret(&ssl->handshake->ecdh_ctx, &zlen, + p + 2, (size_t) (end - (p + 2)), + ssl->conf->f_rng, ssl->conf->p_rng)) != 0) { + MBEDTLS_SSL_DEBUG_RET(1, "mbedtls_ecdh_calc_secret", ret); + return ret; + } + + MBEDTLS_PUT_UINT16_BE(zlen, p, 0); + p += 2 + zlen; + + MBEDTLS_SSL_DEBUG_ECDH(3, &ssl->handshake->ecdh_ctx, + MBEDTLS_DEBUG_ECDH_Z); + } else +#endif /* MBEDTLS_KEY_EXCHANGE_ECDHE_PSK_ENABLED */ + { + MBEDTLS_SSL_DEBUG_MSG(1, ("should never happen")); + return MBEDTLS_ERR_SSL_INTERNAL_ERROR; + } + + /* opaque psk<0..2^16-1>; */ + if (end - p < 2) { + return MBEDTLS_ERR_SSL_BAD_INPUT_DATA; + } + + MBEDTLS_PUT_UINT16_BE(psk_len, p, 0); + p += 2; + + if (end < p || (size_t) (end - p) < psk_len) { + return MBEDTLS_ERR_SSL_BAD_INPUT_DATA; + } + + memcpy(p, psk, psk_len); + p += psk_len; + + ssl->handshake->pmslen = (size_t) (p - ssl->handshake->premaster); + + return 0; +} +#endif /* !MBEDTLS_USE_PSA_CRYPTO && MBEDTLS_KEY_EXCHANGE_SOME_PSK_ENABLED */ + +#if defined(MBEDTLS_SSL_SRV_C) && defined(MBEDTLS_SSL_RENEGOTIATION) +MBEDTLS_CHECK_RETURN_CRITICAL +static int ssl_write_hello_request(mbedtls_ssl_context *ssl); + +#if defined(MBEDTLS_SSL_PROTO_DTLS) +int mbedtls_ssl_resend_hello_request(mbedtls_ssl_context *ssl) +{ + /* If renegotiation is not enforced, retransmit until we would reach max + * timeout if we were using the usual handshake doubling scheme */ + if (ssl->conf->renego_max_records < 0) { + uint32_t ratio = ssl->conf->hs_timeout_max / ssl->conf->hs_timeout_min + 1; + unsigned char doublings = 1; + + while (ratio != 0) { + ++doublings; + ratio >>= 1; + } + + if (++ssl->renego_records_seen > doublings) { + MBEDTLS_SSL_DEBUG_MSG(2, ("no longer retransmitting hello request")); + return 0; + } + } + + return ssl_write_hello_request(ssl); +} +#endif +#endif /* MBEDTLS_SSL_SRV_C && MBEDTLS_SSL_RENEGOTIATION */ + +/* + * Handshake functions + */ +#if !defined(MBEDTLS_KEY_EXCHANGE_WITH_CERT_ENABLED) +/* No certificate support -> dummy functions */ +int mbedtls_ssl_write_certificate(mbedtls_ssl_context *ssl) +{ + const mbedtls_ssl_ciphersuite_t *ciphersuite_info = + ssl->handshake->ciphersuite_info; + + MBEDTLS_SSL_DEBUG_MSG(2, ("=> write certificate")); + + if (!mbedtls_ssl_ciphersuite_uses_srv_cert(ciphersuite_info)) { + MBEDTLS_SSL_DEBUG_MSG(2, ("<= skip write certificate")); + ssl->state++; + return 0; + } + + MBEDTLS_SSL_DEBUG_MSG(1, ("should never happen")); + return MBEDTLS_ERR_SSL_INTERNAL_ERROR; +} + +int mbedtls_ssl_parse_certificate(mbedtls_ssl_context *ssl) +{ + const mbedtls_ssl_ciphersuite_t *ciphersuite_info = + ssl->handshake->ciphersuite_info; + + MBEDTLS_SSL_DEBUG_MSG(2, ("=> parse certificate")); + + if (!mbedtls_ssl_ciphersuite_uses_srv_cert(ciphersuite_info)) { + MBEDTLS_SSL_DEBUG_MSG(2, ("<= skip parse certificate")); + ssl->state++; + return 0; + } + + MBEDTLS_SSL_DEBUG_MSG(1, ("should never happen")); + return MBEDTLS_ERR_SSL_INTERNAL_ERROR; +} + +#else /* MBEDTLS_KEY_EXCHANGE_WITH_CERT_ENABLED */ +/* Some certificate support -> implement write and parse */ + +int mbedtls_ssl_write_certificate(mbedtls_ssl_context *ssl) +{ + int ret = MBEDTLS_ERR_SSL_FEATURE_UNAVAILABLE; + size_t i, n; + const mbedtls_x509_crt *crt; + const mbedtls_ssl_ciphersuite_t *ciphersuite_info = + ssl->handshake->ciphersuite_info; + + MBEDTLS_SSL_DEBUG_MSG(2, ("=> write certificate")); + + if (!mbedtls_ssl_ciphersuite_uses_srv_cert(ciphersuite_info)) { + MBEDTLS_SSL_DEBUG_MSG(2, ("<= skip write certificate")); + ssl->state++; + return 0; + } + +#if defined(MBEDTLS_SSL_CLI_C) + if (ssl->conf->endpoint == MBEDTLS_SSL_IS_CLIENT) { + if (ssl->handshake->client_auth == 0) { + MBEDTLS_SSL_DEBUG_MSG(2, ("<= skip write certificate")); + ssl->state++; + return 0; + } + } +#endif /* MBEDTLS_SSL_CLI_C */ +#if defined(MBEDTLS_SSL_SRV_C) + if (ssl->conf->endpoint == MBEDTLS_SSL_IS_SERVER) { + if (mbedtls_ssl_own_cert(ssl) == NULL) { + /* Should never happen because we shouldn't have picked the + * ciphersuite if we don't have a certificate. */ + return MBEDTLS_ERR_SSL_INTERNAL_ERROR; + } + } +#endif + + MBEDTLS_SSL_DEBUG_CRT(3, "own certificate", mbedtls_ssl_own_cert(ssl)); + + /* + * 0 . 0 handshake type + * 1 . 3 handshake length + * 4 . 6 length of all certs + * 7 . 9 length of cert. 1 + * 10 . n-1 peer certificate + * n . n+2 length of cert. 2 + * n+3 . ... upper level cert, etc. + */ + i = 7; + crt = mbedtls_ssl_own_cert(ssl); + + while (crt != NULL) { + n = crt->raw.len; + if (n > MBEDTLS_SSL_OUT_CONTENT_LEN - 3 - i) { + MBEDTLS_SSL_DEBUG_MSG(1, ("certificate too large, %" MBEDTLS_PRINTF_SIZET + " > %" MBEDTLS_PRINTF_SIZET, + i + 3 + n, (size_t) MBEDTLS_SSL_OUT_CONTENT_LEN)); + return MBEDTLS_ERR_SSL_BUFFER_TOO_SMALL; + } + + ssl->out_msg[i] = MBEDTLS_BYTE_2(n); + ssl->out_msg[i + 1] = MBEDTLS_BYTE_1(n); + ssl->out_msg[i + 2] = MBEDTLS_BYTE_0(n); + + i += 3; memcpy(ssl->out_msg + i, crt->raw.p, n); + i += n; crt = crt->next; + } + + ssl->out_msg[4] = MBEDTLS_BYTE_2(i - 7); + ssl->out_msg[5] = MBEDTLS_BYTE_1(i - 7); + ssl->out_msg[6] = MBEDTLS_BYTE_0(i - 7); + + ssl->out_msglen = i; + ssl->out_msgtype = MBEDTLS_SSL_MSG_HANDSHAKE; + ssl->out_msg[0] = MBEDTLS_SSL_HS_CERTIFICATE; + + ssl->state++; + + if ((ret = mbedtls_ssl_write_handshake_msg(ssl)) != 0) { + MBEDTLS_SSL_DEBUG_RET(1, "mbedtls_ssl_write_handshake_msg", ret); + return ret; + } + + MBEDTLS_SSL_DEBUG_MSG(2, ("<= write certificate")); + + return ret; +} + +#if defined(MBEDTLS_SSL_RENEGOTIATION) && defined(MBEDTLS_SSL_CLI_C) + +#if defined(MBEDTLS_SSL_KEEP_PEER_CERTIFICATE) +MBEDTLS_CHECK_RETURN_CRITICAL +static int ssl_check_peer_crt_unchanged(mbedtls_ssl_context *ssl, + unsigned char *crt_buf, + size_t crt_buf_len) +{ + mbedtls_x509_crt const * const peer_crt = ssl->session->peer_cert; + + if (peer_crt == NULL) { + return -1; + } + + if (peer_crt->raw.len != crt_buf_len) { + return -1; + } + + return memcmp(peer_crt->raw.p, crt_buf, peer_crt->raw.len); +} +#else /* MBEDTLS_SSL_KEEP_PEER_CERTIFICATE */ +MBEDTLS_CHECK_RETURN_CRITICAL +static int ssl_check_peer_crt_unchanged(mbedtls_ssl_context *ssl, + unsigned char *crt_buf, + size_t crt_buf_len) +{ + int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED; + unsigned char const * const peer_cert_digest = + ssl->session->peer_cert_digest; + mbedtls_md_type_t const peer_cert_digest_type = + ssl->session->peer_cert_digest_type; + mbedtls_md_info_t const * const digest_info = + mbedtls_md_info_from_type(peer_cert_digest_type); + unsigned char tmp_digest[MBEDTLS_SSL_PEER_CERT_DIGEST_MAX_LEN]; + size_t digest_len; + + if (peer_cert_digest == NULL || digest_info == NULL) { + return -1; + } + + digest_len = mbedtls_md_get_size(digest_info); + if (digest_len > MBEDTLS_SSL_PEER_CERT_DIGEST_MAX_LEN) { + return -1; + } + + ret = mbedtls_md(digest_info, crt_buf, crt_buf_len, tmp_digest); + if (ret != 0) { + return -1; + } + + return memcmp(tmp_digest, peer_cert_digest, digest_len); +} +#endif /* MBEDTLS_SSL_KEEP_PEER_CERTIFICATE */ +#endif /* MBEDTLS_SSL_RENEGOTIATION && MBEDTLS_SSL_CLI_C */ + +/* + * Once the certificate message is read, parse it into a cert chain and + * perform basic checks, but leave actual verification to the caller + */ +MBEDTLS_CHECK_RETURN_CRITICAL +static int ssl_parse_certificate_chain(mbedtls_ssl_context *ssl, + mbedtls_x509_crt *chain) +{ + int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED; +#if defined(MBEDTLS_SSL_RENEGOTIATION) && defined(MBEDTLS_SSL_CLI_C) + int crt_cnt = 0; +#endif + size_t i, n; + uint8_t alert; + + if (ssl->in_msgtype != MBEDTLS_SSL_MSG_HANDSHAKE) { + MBEDTLS_SSL_DEBUG_MSG(1, ("bad certificate message")); + mbedtls_ssl_send_alert_message(ssl, MBEDTLS_SSL_ALERT_LEVEL_FATAL, + MBEDTLS_SSL_ALERT_MSG_UNEXPECTED_MESSAGE); + return MBEDTLS_ERR_SSL_UNEXPECTED_MESSAGE; + } + + if (ssl->in_msg[0] != MBEDTLS_SSL_HS_CERTIFICATE) { + mbedtls_ssl_send_alert_message(ssl, MBEDTLS_SSL_ALERT_LEVEL_FATAL, + MBEDTLS_SSL_ALERT_MSG_UNEXPECTED_MESSAGE); + return MBEDTLS_ERR_SSL_UNEXPECTED_MESSAGE; + } + + if (ssl->in_hslen < mbedtls_ssl_hs_hdr_len(ssl) + 3 + 3) { + MBEDTLS_SSL_DEBUG_MSG(1, ("bad certificate message")); + mbedtls_ssl_send_alert_message(ssl, MBEDTLS_SSL_ALERT_LEVEL_FATAL, + MBEDTLS_SSL_ALERT_MSG_DECODE_ERROR); + return MBEDTLS_ERR_SSL_DECODE_ERROR; + } + + i = mbedtls_ssl_hs_hdr_len(ssl); + + /* + * Same message structure as in mbedtls_ssl_write_certificate() + */ + n = MBEDTLS_GET_UINT16_BE(ssl->in_msg, i + 1); + + if (ssl->in_msg[i] != 0 || + ssl->in_hslen != n + 3 + mbedtls_ssl_hs_hdr_len(ssl)) { + MBEDTLS_SSL_DEBUG_MSG(1, ("bad certificate message")); + mbedtls_ssl_send_alert_message(ssl, MBEDTLS_SSL_ALERT_LEVEL_FATAL, + MBEDTLS_SSL_ALERT_MSG_DECODE_ERROR); + return MBEDTLS_ERR_SSL_DECODE_ERROR; + } + + /* Make &ssl->in_msg[i] point to the beginning of the CRT chain. */ + i += 3; + + /* Iterate through and parse the CRTs in the provided chain. */ + while (i < ssl->in_hslen) { + /* Check that there's room for the next CRT's length fields. */ + if (i + 3 > ssl->in_hslen) { + MBEDTLS_SSL_DEBUG_MSG(1, ("bad certificate message")); + mbedtls_ssl_send_alert_message(ssl, + MBEDTLS_SSL_ALERT_LEVEL_FATAL, + MBEDTLS_SSL_ALERT_MSG_DECODE_ERROR); + return MBEDTLS_ERR_SSL_DECODE_ERROR; + } + /* In theory, the CRT can be up to 2**24 Bytes, but we don't support + * anything beyond 2**16 ~ 64K. */ + if (ssl->in_msg[i] != 0) { + MBEDTLS_SSL_DEBUG_MSG(1, ("bad certificate message")); + mbedtls_ssl_send_alert_message(ssl, + MBEDTLS_SSL_ALERT_LEVEL_FATAL, + MBEDTLS_SSL_ALERT_MSG_UNSUPPORTED_CERT); + return MBEDTLS_ERR_SSL_BAD_CERTIFICATE; + } + + /* Read length of the next CRT in the chain. */ + n = MBEDTLS_GET_UINT16_BE(ssl->in_msg, i + 1); + i += 3; + + if (n < 128 || i + n > ssl->in_hslen) { + MBEDTLS_SSL_DEBUG_MSG(1, ("bad certificate message")); + mbedtls_ssl_send_alert_message(ssl, + MBEDTLS_SSL_ALERT_LEVEL_FATAL, + MBEDTLS_SSL_ALERT_MSG_DECODE_ERROR); + return MBEDTLS_ERR_SSL_DECODE_ERROR; + } + + /* Check if we're handling the first CRT in the chain. */ +#if defined(MBEDTLS_SSL_RENEGOTIATION) && defined(MBEDTLS_SSL_CLI_C) + if (crt_cnt++ == 0 && + ssl->conf->endpoint == MBEDTLS_SSL_IS_CLIENT && + ssl->renego_status == MBEDTLS_SSL_RENEGOTIATION_IN_PROGRESS) { + /* During client-side renegotiation, check that the server's + * end-CRTs hasn't changed compared to the initial handshake, + * mitigating the triple handshake attack. On success, reuse + * the original end-CRT instead of parsing it again. */ + MBEDTLS_SSL_DEBUG_MSG(3, ("Check that peer CRT hasn't changed during renegotiation")); + if (ssl_check_peer_crt_unchanged(ssl, + &ssl->in_msg[i], + n) != 0) { + MBEDTLS_SSL_DEBUG_MSG(1, ("new server cert during renegotiation")); + mbedtls_ssl_send_alert_message(ssl, + MBEDTLS_SSL_ALERT_LEVEL_FATAL, + MBEDTLS_SSL_ALERT_MSG_ACCESS_DENIED); + return MBEDTLS_ERR_SSL_BAD_CERTIFICATE; + } + + /* Now we can safely free the original chain. */ + ssl_clear_peer_cert(ssl->session); + } +#endif /* MBEDTLS_SSL_RENEGOTIATION && MBEDTLS_SSL_CLI_C */ + + /* Parse the next certificate in the chain. */ +#if defined(MBEDTLS_SSL_KEEP_PEER_CERTIFICATE) + ret = mbedtls_x509_crt_parse_der(chain, ssl->in_msg + i, n); +#else + /* If we don't need to store the CRT chain permanently, parse + * it in-place from the input buffer instead of making a copy. */ + ret = mbedtls_x509_crt_parse_der_nocopy(chain, ssl->in_msg + i, n); +#endif /* MBEDTLS_SSL_KEEP_PEER_CERTIFICATE */ + switch (ret) { + case 0: /*ok*/ + case MBEDTLS_ERR_X509_UNKNOWN_SIG_ALG + MBEDTLS_ERR_OID_NOT_FOUND: + /* Ignore certificate with an unknown algorithm: maybe a + prior certificate was already trusted. */ + break; + + case MBEDTLS_ERR_X509_ALLOC_FAILED: + alert = MBEDTLS_SSL_ALERT_MSG_INTERNAL_ERROR; + goto crt_parse_der_failed; + + case MBEDTLS_ERR_X509_UNKNOWN_VERSION: + alert = MBEDTLS_SSL_ALERT_MSG_UNSUPPORTED_CERT; + goto crt_parse_der_failed; + + default: + alert = MBEDTLS_SSL_ALERT_MSG_BAD_CERT; +crt_parse_der_failed: + mbedtls_ssl_send_alert_message(ssl, MBEDTLS_SSL_ALERT_LEVEL_FATAL, alert); + MBEDTLS_SSL_DEBUG_RET(1, " mbedtls_x509_crt_parse_der", ret); + return ret; + } + + i += n; + } + + MBEDTLS_SSL_DEBUG_CRT(3, "peer certificate", chain); + return 0; +} + +#if defined(MBEDTLS_SSL_SRV_C) +MBEDTLS_CHECK_RETURN_CRITICAL +static int ssl_srv_check_client_no_crt_notification(mbedtls_ssl_context *ssl) +{ + if (ssl->conf->endpoint == MBEDTLS_SSL_IS_CLIENT) { + return -1; + } + + if (ssl->in_hslen == 3 + mbedtls_ssl_hs_hdr_len(ssl) && + ssl->in_msgtype == MBEDTLS_SSL_MSG_HANDSHAKE && + ssl->in_msg[0] == MBEDTLS_SSL_HS_CERTIFICATE && + memcmp(ssl->in_msg + mbedtls_ssl_hs_hdr_len(ssl), "\0\0\0", 3) == 0) { + MBEDTLS_SSL_DEBUG_MSG(1, ("peer has no certificate")); + return 0; + } + return -1; +} +#endif /* MBEDTLS_SSL_SRV_C */ + +/* Check if a certificate message is expected. + * Return either + * - SSL_CERTIFICATE_EXPECTED, or + * - SSL_CERTIFICATE_SKIP + * indicating whether a Certificate message is expected or not. + */ +#define SSL_CERTIFICATE_EXPECTED 0 +#define SSL_CERTIFICATE_SKIP 1 +MBEDTLS_CHECK_RETURN_CRITICAL +static int ssl_parse_certificate_coordinate(mbedtls_ssl_context *ssl, + int authmode) +{ + const mbedtls_ssl_ciphersuite_t *ciphersuite_info = + ssl->handshake->ciphersuite_info; + + if (!mbedtls_ssl_ciphersuite_uses_srv_cert(ciphersuite_info)) { + return SSL_CERTIFICATE_SKIP; + } + +#if defined(MBEDTLS_SSL_SRV_C) + if (ssl->conf->endpoint == MBEDTLS_SSL_IS_SERVER) { + if (ciphersuite_info->key_exchange == MBEDTLS_KEY_EXCHANGE_RSA_PSK) { + return SSL_CERTIFICATE_SKIP; + } + + if (authmode == MBEDTLS_SSL_VERIFY_NONE) { + ssl->session_negotiate->verify_result = + MBEDTLS_X509_BADCERT_SKIP_VERIFY; + return SSL_CERTIFICATE_SKIP; + } + } +#else + ((void) authmode); +#endif /* MBEDTLS_SSL_SRV_C */ + + return SSL_CERTIFICATE_EXPECTED; +} + +MBEDTLS_CHECK_RETURN_CRITICAL +static int ssl_parse_certificate_verify(mbedtls_ssl_context *ssl, + int authmode, + mbedtls_x509_crt *chain, + void *rs_ctx) +{ + int ret = 0; + const mbedtls_ssl_ciphersuite_t *ciphersuite_info = + ssl->handshake->ciphersuite_info; + int have_ca_chain = 0; + + int (*f_vrfy)(void *, mbedtls_x509_crt *, int, uint32_t *); + void *p_vrfy; + + if (authmode == MBEDTLS_SSL_VERIFY_NONE) { + return 0; + } + + if (ssl->f_vrfy != NULL) { + MBEDTLS_SSL_DEBUG_MSG(3, ("Use context-specific verification callback")); + f_vrfy = ssl->f_vrfy; + p_vrfy = ssl->p_vrfy; + } else { + MBEDTLS_SSL_DEBUG_MSG(3, ("Use configuration-specific verification callback")); + f_vrfy = ssl->conf->f_vrfy; + p_vrfy = ssl->conf->p_vrfy; + } + + /* + * Main check: verify certificate + */ +#if defined(MBEDTLS_X509_TRUSTED_CERTIFICATE_CALLBACK) + if (ssl->conf->f_ca_cb != NULL) { + ((void) rs_ctx); + have_ca_chain = 1; + + MBEDTLS_SSL_DEBUG_MSG(3, ("use CA callback for X.509 CRT verification")); + ret = mbedtls_x509_crt_verify_with_ca_cb( + chain, + ssl->conf->f_ca_cb, + ssl->conf->p_ca_cb, + ssl->conf->cert_profile, + ssl->hostname, + &ssl->session_negotiate->verify_result, + f_vrfy, p_vrfy); + } else +#endif /* MBEDTLS_X509_TRUSTED_CERTIFICATE_CALLBACK */ + { + mbedtls_x509_crt *ca_chain; + mbedtls_x509_crl *ca_crl; + +#if defined(MBEDTLS_SSL_SERVER_NAME_INDICATION) + if (ssl->handshake->sni_ca_chain != NULL) { + ca_chain = ssl->handshake->sni_ca_chain; + ca_crl = ssl->handshake->sni_ca_crl; + } else +#endif + { + ca_chain = ssl->conf->ca_chain; + ca_crl = ssl->conf->ca_crl; + } + + if (ca_chain != NULL) { + have_ca_chain = 1; + } + + ret = mbedtls_x509_crt_verify_restartable( + chain, + ca_chain, ca_crl, + ssl->conf->cert_profile, + ssl->hostname, + &ssl->session_negotiate->verify_result, + f_vrfy, p_vrfy, rs_ctx); + } + + if (ret != 0) { + MBEDTLS_SSL_DEBUG_RET(1, "x509_verify_cert", ret); + } + +#if defined(MBEDTLS_SSL_ECP_RESTARTABLE_ENABLED) + if (ret == MBEDTLS_ERR_ECP_IN_PROGRESS) { + return MBEDTLS_ERR_SSL_CRYPTO_IN_PROGRESS; + } +#endif + + /* + * Secondary checks: always done, but change 'ret' only if it was 0 + */ + +#if defined(MBEDTLS_PK_HAVE_ECC_KEYS) + { + const mbedtls_pk_context *pk = &chain->pk; + + /* If certificate uses an EC key, make sure the curve is OK. + * This is a public key, so it can't be opaque, so can_do() is a good + * enough check to ensure pk_ec() is safe to use here. */ + if (mbedtls_pk_can_do(pk, MBEDTLS_PK_ECKEY)) { + /* and in the unlikely case the above assumption no longer holds + * we are making sure that pk_ec() here does not return a NULL + */ + mbedtls_ecp_group_id grp_id = mbedtls_pk_get_ec_group_id(pk); + if (grp_id == MBEDTLS_ECP_DP_NONE) { + MBEDTLS_SSL_DEBUG_MSG(1, ("invalid group ID")); + return MBEDTLS_ERR_SSL_INTERNAL_ERROR; + } + if (mbedtls_ssl_check_curve(ssl, grp_id) != 0) { + ssl->session_negotiate->verify_result |= + MBEDTLS_X509_BADCERT_BAD_KEY; + + MBEDTLS_SSL_DEBUG_MSG(1, ("bad certificate (EC key curve)")); + if (ret == 0) { + ret = MBEDTLS_ERR_SSL_BAD_CERTIFICATE; + } + } + } + } +#endif /* MBEDTLS_PK_HAVE_ECC_KEYS */ + + if (mbedtls_ssl_check_cert_usage(chain, + ciphersuite_info, + !ssl->conf->endpoint, + &ssl->session_negotiate->verify_result) != 0) { + MBEDTLS_SSL_DEBUG_MSG(1, ("bad certificate (usage extensions)")); + if (ret == 0) { + ret = MBEDTLS_ERR_SSL_BAD_CERTIFICATE; + } + } + + /* mbedtls_x509_crt_verify_with_profile is supposed to report a + * verification failure through MBEDTLS_ERR_X509_CERT_VERIFY_FAILED, + * with details encoded in the verification flags. All other kinds + * of error codes, including those from the user provided f_vrfy + * functions, are treated as fatal and lead to a failure of + * ssl_parse_certificate even if verification was optional. */ + if (authmode == MBEDTLS_SSL_VERIFY_OPTIONAL && + (ret == MBEDTLS_ERR_X509_CERT_VERIFY_FAILED || + ret == MBEDTLS_ERR_SSL_BAD_CERTIFICATE)) { + ret = 0; + } + + if (have_ca_chain == 0 && authmode == MBEDTLS_SSL_VERIFY_REQUIRED) { + MBEDTLS_SSL_DEBUG_MSG(1, ("got no CA chain")); + ret = MBEDTLS_ERR_SSL_CA_CHAIN_REQUIRED; + } + + if (ret != 0) { + uint8_t alert; + + /* The certificate may have been rejected for several reasons. + Pick one and send the corresponding alert. Which alert to send + may be a subject of debate in some cases. */ + if (ssl->session_negotiate->verify_result & MBEDTLS_X509_BADCERT_OTHER) { + alert = MBEDTLS_SSL_ALERT_MSG_ACCESS_DENIED; + } else if (ssl->session_negotiate->verify_result & MBEDTLS_X509_BADCERT_CN_MISMATCH) { + alert = MBEDTLS_SSL_ALERT_MSG_BAD_CERT; + } else if (ssl->session_negotiate->verify_result & MBEDTLS_X509_BADCERT_KEY_USAGE) { + alert = MBEDTLS_SSL_ALERT_MSG_UNSUPPORTED_CERT; + } else if (ssl->session_negotiate->verify_result & MBEDTLS_X509_BADCERT_EXT_KEY_USAGE) { + alert = MBEDTLS_SSL_ALERT_MSG_UNSUPPORTED_CERT; + } else if (ssl->session_negotiate->verify_result & MBEDTLS_X509_BADCERT_NS_CERT_TYPE) { + alert = MBEDTLS_SSL_ALERT_MSG_UNSUPPORTED_CERT; + } else if (ssl->session_negotiate->verify_result & MBEDTLS_X509_BADCERT_BAD_PK) { + alert = MBEDTLS_SSL_ALERT_MSG_UNSUPPORTED_CERT; + } else if (ssl->session_negotiate->verify_result & MBEDTLS_X509_BADCERT_BAD_KEY) { + alert = MBEDTLS_SSL_ALERT_MSG_UNSUPPORTED_CERT; + } else if (ssl->session_negotiate->verify_result & MBEDTLS_X509_BADCERT_EXPIRED) { + alert = MBEDTLS_SSL_ALERT_MSG_CERT_EXPIRED; + } else if (ssl->session_negotiate->verify_result & MBEDTLS_X509_BADCERT_REVOKED) { + alert = MBEDTLS_SSL_ALERT_MSG_CERT_REVOKED; + } else if (ssl->session_negotiate->verify_result & MBEDTLS_X509_BADCERT_NOT_TRUSTED) { + alert = MBEDTLS_SSL_ALERT_MSG_UNKNOWN_CA; + } else { + alert = MBEDTLS_SSL_ALERT_MSG_CERT_UNKNOWN; + } + mbedtls_ssl_send_alert_message(ssl, MBEDTLS_SSL_ALERT_LEVEL_FATAL, + alert); + } + +#if defined(MBEDTLS_DEBUG_C) + if (ssl->session_negotiate->verify_result != 0) { + MBEDTLS_SSL_DEBUG_MSG(3, ("! Certificate verification flags %08x", + (unsigned int) ssl->session_negotiate->verify_result)); + } else { + MBEDTLS_SSL_DEBUG_MSG(3, ("Certificate verification flags clear")); + } +#endif /* MBEDTLS_DEBUG_C */ + + return ret; +} -#if defined(MBEDTLS_SSL_ALPN) -#define SSL_SERIALIZED_CONTEXT_CONFIG_ALPN 1u -#else -#define SSL_SERIALIZED_CONTEXT_CONFIG_ALPN 0u -#endif /* MBEDTLS_SSL_ALPN */ +#if !defined(MBEDTLS_SSL_KEEP_PEER_CERTIFICATE) +MBEDTLS_CHECK_RETURN_CRITICAL +static int ssl_remember_peer_crt_digest(mbedtls_ssl_context *ssl, + unsigned char *start, size_t len) +{ + int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED; + /* Remember digest of the peer's end-CRT. */ + ssl->session_negotiate->peer_cert_digest = + mbedtls_calloc(1, MBEDTLS_SSL_PEER_CERT_DIGEST_DFL_LEN); + if (ssl->session_negotiate->peer_cert_digest == NULL) { + MBEDTLS_SSL_DEBUG_MSG(1, ("alloc(%d bytes) failed", + MBEDTLS_SSL_PEER_CERT_DIGEST_DFL_LEN)); + mbedtls_ssl_send_alert_message(ssl, + MBEDTLS_SSL_ALERT_LEVEL_FATAL, + MBEDTLS_SSL_ALERT_MSG_INTERNAL_ERROR); -#define SSL_SERIALIZED_CONTEXT_CONFIG_DTLS_CONNECTION_ID_BIT 0 -#define SSL_SERIALIZED_CONTEXT_CONFIG_DTLS_BADMAC_LIMIT_BIT 1 -#define SSL_SERIALIZED_CONTEXT_CONFIG_DTLS_ANTI_REPLAY_BIT 2 -#define SSL_SERIALIZED_CONTEXT_CONFIG_ALPN_BIT 3 + return MBEDTLS_ERR_SSL_ALLOC_FAILED; + } -#define SSL_SERIALIZED_CONTEXT_CONFIG_BITFLAG \ - ((uint32_t) ( \ - (SSL_SERIALIZED_CONTEXT_CONFIG_DTLS_CONNECTION_ID << \ - SSL_SERIALIZED_CONTEXT_CONFIG_DTLS_CONNECTION_ID_BIT) | \ - (SSL_SERIALIZED_CONTEXT_CONFIG_DTLS_BADMAC_LIMIT << \ - SSL_SERIALIZED_CONTEXT_CONFIG_DTLS_BADMAC_LIMIT_BIT) | \ - (SSL_SERIALIZED_CONTEXT_CONFIG_DTLS_ANTI_REPLAY << \ - SSL_SERIALIZED_CONTEXT_CONFIG_DTLS_ANTI_REPLAY_BIT) | \ - (SSL_SERIALIZED_CONTEXT_CONFIG_ALPN << SSL_SERIALIZED_CONTEXT_CONFIG_ALPN_BIT) | \ - 0u)) + ret = mbedtls_md(mbedtls_md_info_from_type( + MBEDTLS_SSL_PEER_CERT_DIGEST_DFL_TYPE), + start, len, + ssl->session_negotiate->peer_cert_digest); -static unsigned char ssl_serialized_context_header[] = { - MBEDTLS_VERSION_MAJOR, - MBEDTLS_VERSION_MINOR, - MBEDTLS_VERSION_PATCH, - MBEDTLS_BYTE_1(SSL_SERIALIZED_SESSION_CONFIG_BITFLAG), - MBEDTLS_BYTE_0(SSL_SERIALIZED_SESSION_CONFIG_BITFLAG), - MBEDTLS_BYTE_2(SSL_SERIALIZED_CONTEXT_CONFIG_BITFLAG), - MBEDTLS_BYTE_1(SSL_SERIALIZED_CONTEXT_CONFIG_BITFLAG), - MBEDTLS_BYTE_0(SSL_SERIALIZED_CONTEXT_CONFIG_BITFLAG), -}; + ssl->session_negotiate->peer_cert_digest_type = + MBEDTLS_SSL_PEER_CERT_DIGEST_DFL_TYPE; + ssl->session_negotiate->peer_cert_digest_len = + MBEDTLS_SSL_PEER_CERT_DIGEST_DFL_LEN; -/* - * Serialize a full SSL context - * - * The format of the serialized data is: - * (in the presentation language of TLS, RFC 8446 section 3) - * - * // header - * opaque mbedtls_version[3]; // major, minor, patch - * opaque context_format[5]; // version-specific field determining - * // the format of the remaining - * // serialized data. - * Note: When updating the format, remember to keep these - * version+format bytes. (We may make their size part of the API.) - * - * // session sub-structure - * opaque session<1..2^32-1>; // see mbedtls_ssl_session_save() - * // transform sub-structure - * uint8 random[64]; // ServerHello.random+ClientHello.random - * uint8 in_cid<0..2^8-1> // Connection ID: expected incoming value - * uint8 out_cid<0..2^8-1> // Connection ID: outgoing value to use - * // fields from ssl_context - * uint32 badmac_seen; // DTLS: number of records with failing MAC - * uint64 in_window_top; // DTLS: last validated record seq_num - * uint64 in_window; // DTLS: bitmask for replay protection - * uint8 disable_datagram_packing; // DTLS: only one record per datagram - * uint64 cur_out_ctr; // Record layer: outgoing sequence number - * uint16 mtu; // DTLS: path mtu (max outgoing fragment size) - * uint8 alpn_chosen<0..2^8-1> // ALPN: negotiated application protocol - * - * Note that many fields of the ssl_context or sub-structures are not - * serialized, as they fall in one of the following categories: - * - * 1. forced value (eg in_left must be 0) - * 2. pointer to dynamically-allocated memory (eg session, transform) - * 3. value can be re-derived from other data (eg session keys from MS) - * 4. value was temporary (eg content of input buffer) - * 5. value will be provided by the user again (eg I/O callbacks and context) - */ -int mbedtls_ssl_context_save(mbedtls_ssl_context *ssl, - unsigned char *buf, - size_t buf_len, - size_t *olen) + return ret; +} + +MBEDTLS_CHECK_RETURN_CRITICAL +static int ssl_remember_peer_pubkey(mbedtls_ssl_context *ssl, + unsigned char *start, size_t len) { - unsigned char *p = buf; - size_t used = 0; - size_t session_len; - int ret = 0; + unsigned char *end = start + len; + int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED; - /* - * Enforce usage restrictions, see "return BAD_INPUT_DATA" in - * this function's documentation. - * - * These are due to assumptions/limitations in the implementation. Some of - * them are likely to stay (no handshake in progress) some might go away - * (only DTLS) but are currently used to simplify the implementation. - */ - /* The initial handshake must be over */ - if (ssl->state != MBEDTLS_SSL_HANDSHAKE_OVER) { - MBEDTLS_SSL_DEBUG_MSG(1, ("Initial handshake isn't over")); - return MBEDTLS_ERR_SSL_BAD_INPUT_DATA; - } - if (ssl->handshake != NULL) { - MBEDTLS_SSL_DEBUG_MSG(1, ("Handshake isn't completed")); - return MBEDTLS_ERR_SSL_BAD_INPUT_DATA; + /* Make a copy of the peer's raw public key. */ + mbedtls_pk_init(&ssl->handshake->peer_pubkey); + ret = mbedtls_pk_parse_subpubkey(&start, end, + &ssl->handshake->peer_pubkey); + if (ret != 0) { + /* We should have parsed the public key before. */ + return MBEDTLS_ERR_SSL_INTERNAL_ERROR; } - /* Double-check that sub-structures are indeed ready */ - if (ssl->transform == NULL || ssl->session == NULL) { - MBEDTLS_SSL_DEBUG_MSG(1, ("Serialised structures aren't ready")); - return MBEDTLS_ERR_SSL_BAD_INPUT_DATA; + + return 0; +} +#endif /* !MBEDTLS_SSL_KEEP_PEER_CERTIFICATE */ + +int mbedtls_ssl_parse_certificate(mbedtls_ssl_context *ssl) +{ + int ret = 0; + int crt_expected; +#if defined(MBEDTLS_SSL_SRV_C) && defined(MBEDTLS_SSL_SERVER_NAME_INDICATION) + const int authmode = ssl->handshake->sni_authmode != MBEDTLS_SSL_VERIFY_UNSET + ? ssl->handshake->sni_authmode + : ssl->conf->authmode; +#else + const int authmode = ssl->conf->authmode; +#endif + void *rs_ctx = NULL; + mbedtls_x509_crt *chain = NULL; + + MBEDTLS_SSL_DEBUG_MSG(2, ("=> parse certificate")); + + crt_expected = ssl_parse_certificate_coordinate(ssl, authmode); + if (crt_expected == SSL_CERTIFICATE_SKIP) { + MBEDTLS_SSL_DEBUG_MSG(2, ("<= skip parse certificate")); + goto exit; } - /* There must be no pending incoming or outgoing data */ - if (mbedtls_ssl_check_pending(ssl) != 0) { - MBEDTLS_SSL_DEBUG_MSG(1, ("There is pending incoming data")); - return MBEDTLS_ERR_SSL_BAD_INPUT_DATA; + +#if defined(MBEDTLS_SSL_ECP_RESTARTABLE_ENABLED) + if (ssl->handshake->ecrs_enabled && + ssl->handshake->ecrs_state == ssl_ecrs_crt_verify) { + chain = ssl->handshake->ecrs_peer_cert; + ssl->handshake->ecrs_peer_cert = NULL; + goto crt_verify; } - if (ssl->out_left != 0) { - MBEDTLS_SSL_DEBUG_MSG(1, ("There is pending outgoing data")); - return MBEDTLS_ERR_SSL_BAD_INPUT_DATA; +#endif + + if ((ret = mbedtls_ssl_read_record(ssl, 1)) != 0) { + /* mbedtls_ssl_read_record may have sent an alert already. We + let it decide whether to alert. */ + MBEDTLS_SSL_DEBUG_RET(1, "mbedtls_ssl_read_record", ret); + goto exit; } - /* Protocol must be DTLS, not TLS */ - if (ssl->conf->transport != MBEDTLS_SSL_TRANSPORT_DATAGRAM) { - MBEDTLS_SSL_DEBUG_MSG(1, ("Only DTLS is supported")); - return MBEDTLS_ERR_SSL_BAD_INPUT_DATA; + +#if defined(MBEDTLS_SSL_SRV_C) + if (ssl_srv_check_client_no_crt_notification(ssl) == 0) { + ssl->session_negotiate->verify_result = MBEDTLS_X509_BADCERT_MISSING; + + if (authmode != MBEDTLS_SSL_VERIFY_OPTIONAL) { + ret = MBEDTLS_ERR_SSL_NO_CLIENT_CERTIFICATE; + } + + goto exit; } - /* Version must be 1.2 */ - if (ssl->major_ver != MBEDTLS_SSL_MAJOR_VERSION_3) { - MBEDTLS_SSL_DEBUG_MSG(1, ("Only version 1.2 supported")); - return MBEDTLS_ERR_SSL_BAD_INPUT_DATA; +#endif /* MBEDTLS_SSL_SRV_C */ + + /* Clear existing peer CRT structure in case we tried to + * reuse a session but it failed, and allocate a new one. */ + ssl_clear_peer_cert(ssl->session_negotiate); + + chain = mbedtls_calloc(1, sizeof(mbedtls_x509_crt)); + if (chain == NULL) { + MBEDTLS_SSL_DEBUG_MSG(1, ("alloc(%" MBEDTLS_PRINTF_SIZET " bytes) failed", + sizeof(mbedtls_x509_crt))); + mbedtls_ssl_send_alert_message(ssl, + MBEDTLS_SSL_ALERT_LEVEL_FATAL, + MBEDTLS_SSL_ALERT_MSG_INTERNAL_ERROR); + + ret = MBEDTLS_ERR_SSL_ALLOC_FAILED; + goto exit; } - if (ssl->minor_ver != MBEDTLS_SSL_MINOR_VERSION_3) { - MBEDTLS_SSL_DEBUG_MSG(1, ("Only version 1.2 supported")); - return MBEDTLS_ERR_SSL_BAD_INPUT_DATA; + mbedtls_x509_crt_init(chain); + + ret = ssl_parse_certificate_chain(ssl, chain); + if (ret != 0) { + goto exit; } - /* We must be using an AEAD ciphersuite */ - if (mbedtls_ssl_transform_uses_aead(ssl->transform) != 1) { - MBEDTLS_SSL_DEBUG_MSG(1, ("Only AEAD ciphersuites supported")); - return MBEDTLS_ERR_SSL_BAD_INPUT_DATA; + +#if defined(MBEDTLS_SSL_ECP_RESTARTABLE_ENABLED) + if (ssl->handshake->ecrs_enabled) { + ssl->handshake->ecrs_state = ssl_ecrs_crt_verify; } - /* Renegotiation must not be enabled */ -#if defined(MBEDTLS_SSL_RENEGOTIATION) - if (ssl->conf->disable_renegotiation != MBEDTLS_SSL_RENEGOTIATION_DISABLED) { - MBEDTLS_SSL_DEBUG_MSG(1, ("Renegotiation must not be enabled")); - return MBEDTLS_ERR_SSL_BAD_INPUT_DATA; + +crt_verify: + if (ssl->handshake->ecrs_enabled) { + rs_ctx = &ssl->handshake->ecrs_ctx; } #endif - /* - * Version and format identifier - */ - used += sizeof(ssl_serialized_context_header); - - if (used <= buf_len) { - memcpy(p, ssl_serialized_context_header, - sizeof(ssl_serialized_context_header)); - p += sizeof(ssl_serialized_context_header); + ret = ssl_parse_certificate_verify(ssl, authmode, + chain, rs_ctx); + if (ret != 0) { + goto exit; } - /* - * Session (length + data) - */ - ret = ssl_session_save(ssl->session, 1, NULL, 0, &session_len); - if (ret != MBEDTLS_ERR_SSL_BUFFER_TOO_SMALL) { - return ret; - } +#if !defined(MBEDTLS_SSL_KEEP_PEER_CERTIFICATE) + { + unsigned char *crt_start, *pk_start; + size_t crt_len, pk_len; + + /* We parse the CRT chain without copying, so + * these pointers point into the input buffer, + * and are hence still valid after freeing the + * CRT chain. */ + + crt_start = chain->raw.p; + crt_len = chain->raw.len; - used += 4 + session_len; - if (used <= buf_len) { - MBEDTLS_PUT_UINT32_BE(session_len, p, 0); - p += 4; + pk_start = chain->pk_raw.p; + pk_len = chain->pk_raw.len; - ret = ssl_session_save(ssl->session, 1, - p, session_len, &session_len); + /* Free the CRT structures before computing + * digest and copying the peer's public key. */ + mbedtls_x509_crt_free(chain); + mbedtls_free(chain); + chain = NULL; + + ret = ssl_remember_peer_crt_digest(ssl, crt_start, crt_len); if (ret != 0) { - return ret; + goto exit; } - p += session_len; + ret = ssl_remember_peer_pubkey(ssl, pk_start, pk_len); + if (ret != 0) { + goto exit; + } } +#else /* !MBEDTLS_SSL_KEEP_PEER_CERTIFICATE */ + /* Pass ownership to session structure. */ + ssl->session_negotiate->peer_cert = chain; + chain = NULL; +#endif /* MBEDTLS_SSL_KEEP_PEER_CERTIFICATE */ - /* - * Transform - */ - used += sizeof(ssl->transform->randbytes); - if (used <= buf_len) { - memcpy(p, ssl->transform->randbytes, - sizeof(ssl->transform->randbytes)); - p += sizeof(ssl->transform->randbytes); - } + MBEDTLS_SSL_DEBUG_MSG(2, ("<= parse certificate")); -#if defined(MBEDTLS_SSL_DTLS_CONNECTION_ID) - used += 2 + ssl->transform->in_cid_len + ssl->transform->out_cid_len; - if (used <= buf_len) { - *p++ = ssl->transform->in_cid_len; - memcpy(p, ssl->transform->in_cid, ssl->transform->in_cid_len); - p += ssl->transform->in_cid_len; +exit: - *p++ = ssl->transform->out_cid_len; - memcpy(p, ssl->transform->out_cid, ssl->transform->out_cid_len); - p += ssl->transform->out_cid_len; + if (ret == 0) { + ssl->state++; } -#endif /* MBEDTLS_SSL_DTLS_CONNECTION_ID */ - /* - * Saved fields from top-level ssl_context structure - */ -#if defined(MBEDTLS_SSL_DTLS_BADMAC_LIMIT) - used += 4; - if (used <= buf_len) { - MBEDTLS_PUT_UINT32_BE(ssl->badmac_seen, p, 0); - p += 4; +#if defined(MBEDTLS_SSL_ECP_RESTARTABLE_ENABLED) + if (ret == MBEDTLS_ERR_SSL_CRYPTO_IN_PROGRESS) { + ssl->handshake->ecrs_peer_cert = chain; + chain = NULL; } -#endif /* MBEDTLS_SSL_DTLS_BADMAC_LIMIT */ - -#if defined(MBEDTLS_SSL_DTLS_ANTI_REPLAY) - used += 16; - if (used <= buf_len) { - MBEDTLS_PUT_UINT64_BE(ssl->in_window_top, p, 0); - p += 8; +#endif - MBEDTLS_PUT_UINT64_BE(ssl->in_window, p, 0); - p += 8; + if (chain != NULL) { + mbedtls_x509_crt_free(chain); + mbedtls_free(chain); } -#endif /* MBEDTLS_SSL_DTLS_ANTI_REPLAY */ -#if defined(MBEDTLS_SSL_PROTO_DTLS) - used += 1; - if (used <= buf_len) { - *p++ = ssl->disable_datagram_packing; - } -#endif /* MBEDTLS_SSL_PROTO_DTLS */ + return ret; +} +#endif /* MBEDTLS_KEY_EXCHANGE_WITH_CERT_ENABLED */ - used += 8; - if (used <= buf_len) { - memcpy(p, ssl->cur_out_ctr, 8); - p += 8; +static int ssl_calc_finished_tls_generic(mbedtls_ssl_context *ssl, void *ctx, + unsigned char *padbuf, size_t hlen, + unsigned char *buf, int from) +{ + unsigned int len = 12; + const char *sender; +#if defined(MBEDTLS_USE_PSA_CRYPTO) + psa_status_t status; + psa_hash_operation_t *hs_op = ctx; + psa_hash_operation_t cloned_op = PSA_HASH_OPERATION_INIT; + size_t hash_size; +#else + int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED; + mbedtls_md_context_t *hs_ctx = ctx; + mbedtls_md_context_t cloned_ctx; + mbedtls_md_init(&cloned_ctx); +#endif + + mbedtls_ssl_session *session = ssl->session_negotiate; + if (!session) { + session = ssl->session; } -#if defined(MBEDTLS_SSL_PROTO_DTLS) - used += 2; - if (used <= buf_len) { - MBEDTLS_PUT_UINT16_BE(ssl->mtu, p, 0); - p += 2; + sender = (from == MBEDTLS_SSL_IS_CLIENT) + ? "client finished" + : "server finished"; + +#if defined(MBEDTLS_USE_PSA_CRYPTO) + MBEDTLS_SSL_DEBUG_MSG(2, ("=> calc PSA finished tls")); + + status = psa_hash_clone(hs_op, &cloned_op); + if (status != PSA_SUCCESS) { + goto exit; } -#endif /* MBEDTLS_SSL_PROTO_DTLS */ -#if defined(MBEDTLS_SSL_ALPN) - { - const uint8_t alpn_len = ssl->alpn_chosen - ? (uint8_t) strlen(ssl->alpn_chosen) - : 0; + status = psa_hash_finish(&cloned_op, padbuf, hlen, &hash_size); + if (status != PSA_SUCCESS) { + goto exit; + } + MBEDTLS_SSL_DEBUG_BUF(3, "PSA calculated padbuf", padbuf, hlen); +#else + MBEDTLS_SSL_DEBUG_MSG(2, ("=> calc finished tls")); - used += 1 + alpn_len; - if (used <= buf_len) { - *p++ = alpn_len; + ret = mbedtls_md_setup(&cloned_ctx, mbedtls_md_info_from_ctx(hs_ctx), 0); + if (ret != 0) { + goto exit; + } + ret = mbedtls_md_clone(&cloned_ctx, hs_ctx); + if (ret != 0) { + goto exit; + } - if (ssl->alpn_chosen != NULL) { - memcpy(p, ssl->alpn_chosen, alpn_len); - p += alpn_len; - } - } + ret = mbedtls_md_finish(&cloned_ctx, padbuf); + if (ret != 0) { + goto exit; } -#endif /* MBEDTLS_SSL_ALPN */ +#endif /* MBEDTLS_USE_PSA_CRYPTO */ + + MBEDTLS_SSL_DEBUG_BUF(4, "finished output", padbuf, hlen); /* - * Done + * TLSv1.2: + * hash = PRF( master, finished_label, + * Hash( handshake ) )[0.11] */ - *olen = used; + ssl->handshake->tls_prf(session->master, 48, sender, + padbuf, hlen, buf, len); - if (used > buf_len) { - return MBEDTLS_ERR_SSL_BUFFER_TOO_SMALL; - } + MBEDTLS_SSL_DEBUG_BUF(3, "calc finished result", buf, len); - MBEDTLS_SSL_DEBUG_BUF(4, "saved context", buf, used); + mbedtls_platform_zeroize(padbuf, hlen); - return mbedtls_ssl_session_reset_int(ssl, 0); + MBEDTLS_SSL_DEBUG_MSG(2, ("<= calc finished")); + +exit: +#if defined(MBEDTLS_USE_PSA_CRYPTO) + psa_hash_abort(&cloned_op); + return mbedtls_md_error_from_psa(status); +#else + mbedtls_md_free(&cloned_ctx); + return ret; +#endif /* MBEDTLS_USE_PSA_CRYPTO */ } -/* - * Helper to get TLS 1.2 PRF from ciphersuite - * (Duplicates bits of logic from ssl_set_handshake_prfs().) - */ -#if defined(MBEDTLS_SHA256_C) || \ - (defined(MBEDTLS_SHA512_C) && !defined(MBEDTLS_SHA512_NO_SHA384)) -typedef int (*tls_prf_fn)(const unsigned char *secret, size_t slen, - const char *label, - const unsigned char *random, size_t rlen, - unsigned char *dstbuf, size_t dlen); -static tls_prf_fn ssl_tls12prf_from_cs(int ciphersuite_id) +#if defined(MBEDTLS_MD_CAN_SHA256) +static int ssl_calc_finished_tls_sha256( + mbedtls_ssl_context *ssl, unsigned char *buf, int from) { - const mbedtls_ssl_ciphersuite_t * const ciphersuite_info = - mbedtls_ssl_ciphersuite_from_id(ciphersuite_id); - - if (ciphersuite_info == NULL) { - return NULL; - } - -#if defined(MBEDTLS_SHA512_C) && !defined(MBEDTLS_SHA512_NO_SHA384) - if (ciphersuite_info->mac == MBEDTLS_MD_SHA384) { - return tls_prf_sha384; - } else -#endif -#if defined(MBEDTLS_SHA256_C) - { - if (ciphersuite_info->mac == MBEDTLS_MD_SHA256) { - return tls_prf_sha256; - } - } -#endif -#if !defined(MBEDTLS_SHA256_C) && \ - (!defined(MBEDTLS_SHA512_C) || defined(MBEDTLS_SHA512_NO_SHA384)) - (void) ciphersuite_info; + unsigned char padbuf[32]; + return ssl_calc_finished_tls_generic(ssl, +#if defined(MBEDTLS_USE_PSA_CRYPTO) + &ssl->handshake->fin_sha256_psa, +#else + &ssl->handshake->fin_sha256, #endif - return NULL; + padbuf, sizeof(padbuf), + buf, from); } +#endif /* MBEDTLS_MD_CAN_SHA256*/ -#endif /* MBEDTLS_SHA256_C || - (MBEDTLS_SHA512_C && !MBEDTLS_SHA512_NO_SHA384) */ -/* - * Deserialize context, see mbedtls_ssl_context_save() for format. - * - * This internal version is wrapped by a public function that cleans up in - * case of error. - */ -MBEDTLS_CHECK_RETURN_CRITICAL -static int ssl_context_load(mbedtls_ssl_context *ssl, - const unsigned char *buf, - size_t len) +#if defined(MBEDTLS_MD_CAN_SHA384) +static int ssl_calc_finished_tls_sha384( + mbedtls_ssl_context *ssl, unsigned char *buf, int from) { - const unsigned char *p = buf; - const unsigned char * const end = buf + len; - size_t session_len; - int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED; - tls_prf_fn prf_func = NULL; - - /* - * The context should have been freshly setup or reset. - * Give the user an error in case of obvious misuse. - * (Checking session is useful because it won't be NULL if we're - * renegotiating, or if the user mistakenly loaded a session first.) - */ - if (ssl->state != MBEDTLS_SSL_HELLO_REQUEST || - ssl->session != NULL) { - return MBEDTLS_ERR_SSL_BAD_INPUT_DATA; - } - - /* - * We can't check that the config matches the initial one, but we can at - * least check it matches the requirements for serializing. - */ - if (ssl->conf->transport != MBEDTLS_SSL_TRANSPORT_DATAGRAM || - ssl->conf->max_major_ver < MBEDTLS_SSL_MAJOR_VERSION_3 || - ssl->conf->min_major_ver > MBEDTLS_SSL_MAJOR_VERSION_3 || - ssl->conf->max_minor_ver < MBEDTLS_SSL_MINOR_VERSION_3 || - ssl->conf->min_minor_ver > MBEDTLS_SSL_MINOR_VERSION_3 || -#if defined(MBEDTLS_SSL_RENEGOTIATION) - ssl->conf->disable_renegotiation != MBEDTLS_SSL_RENEGOTIATION_DISABLED || + unsigned char padbuf[48]; + return ssl_calc_finished_tls_generic(ssl, +#if defined(MBEDTLS_USE_PSA_CRYPTO) + &ssl->handshake->fin_sha384_psa, +#else + &ssl->handshake->fin_sha384, #endif - 0) { - return MBEDTLS_ERR_SSL_BAD_INPUT_DATA; - } + padbuf, sizeof(padbuf), + buf, from); +} +#endif /* MBEDTLS_MD_CAN_SHA384*/ - MBEDTLS_SSL_DEBUG_BUF(4, "context to load", buf, len); +void mbedtls_ssl_handshake_wrapup_free_hs_transform(mbedtls_ssl_context *ssl) +{ + MBEDTLS_SSL_DEBUG_MSG(3, ("=> handshake wrapup: final free")); /* - * Check version identifier + * Free our handshake params */ - if ((size_t) (end - p) < sizeof(ssl_serialized_context_header)) { - return MBEDTLS_ERR_SSL_BAD_INPUT_DATA; - } - - if (memcmp(p, ssl_serialized_context_header, - sizeof(ssl_serialized_context_header)) != 0) { - return MBEDTLS_ERR_SSL_VERSION_MISMATCH; - } - p += sizeof(ssl_serialized_context_header); + mbedtls_ssl_handshake_free(ssl); + mbedtls_free(ssl->handshake); + ssl->handshake = NULL; /* - * Session + * Free the previous transform and switch in the current one */ - if ((size_t) (end - p) < 4) { - return MBEDTLS_ERR_SSL_BAD_INPUT_DATA; + if (ssl->transform) { + mbedtls_ssl_transform_free(ssl->transform); + mbedtls_free(ssl->transform); } + ssl->transform = ssl->transform_negotiate; + ssl->transform_negotiate = NULL; - session_len = ((size_t) p[0] << 24) | - ((size_t) p[1] << 16) | - ((size_t) p[2] << 8) | - ((size_t) p[3]); - p += 4; + MBEDTLS_SSL_DEBUG_MSG(3, ("<= handshake wrapup: final free")); +} - /* This has been allocated by ssl_handshake_init(), called by - * by either mbedtls_ssl_session_reset_int() or mbedtls_ssl_setup(). */ - ssl->session = ssl->session_negotiate; - ssl->session_in = ssl->session; - ssl->session_out = ssl->session; - ssl->session_negotiate = NULL; +void mbedtls_ssl_handshake_wrapup(mbedtls_ssl_context *ssl) +{ + int resume = ssl->handshake->resume; - if ((size_t) (end - p) < session_len) { - return MBEDTLS_ERR_SSL_BAD_INPUT_DATA; - } + MBEDTLS_SSL_DEBUG_MSG(3, ("=> handshake wrapup")); - ret = ssl_session_load(ssl->session, 1, p, session_len); - if (ret != 0) { - mbedtls_ssl_session_free(ssl->session); - return ret; +#if defined(MBEDTLS_SSL_RENEGOTIATION) + if (ssl->renego_status == MBEDTLS_SSL_RENEGOTIATION_IN_PROGRESS) { + ssl->renego_status = MBEDTLS_SSL_RENEGOTIATION_DONE; + ssl->renego_records_seen = 0; } - - p += session_len; +#endif /* - * Transform + * Free the previous session and switch in the current one */ + if (ssl->session) { +#if defined(MBEDTLS_SSL_ENCRYPT_THEN_MAC) + /* RFC 7366 3.1: keep the EtM state */ + ssl->session_negotiate->encrypt_then_mac = + ssl->session->encrypt_then_mac; +#endif - /* This has been allocated by ssl_handshake_init(), called by - * by either mbedtls_ssl_session_reset_int() or mbedtls_ssl_setup(). */ - ssl->transform = ssl->transform_negotiate; - ssl->transform_in = ssl->transform; - ssl->transform_out = ssl->transform; - ssl->transform_negotiate = NULL; - - prf_func = ssl_tls12prf_from_cs(ssl->session->ciphersuite); - if (prf_func == NULL) { - return MBEDTLS_ERR_SSL_BAD_INPUT_DATA; + mbedtls_ssl_session_free(ssl->session); + mbedtls_free(ssl->session); } + ssl->session = ssl->session_negotiate; + ssl->session_negotiate = NULL; - /* Read random bytes and populate structure */ - if ((size_t) (end - p) < sizeof(ssl->transform->randbytes)) { - return MBEDTLS_ERR_SSL_BAD_INPUT_DATA; + /* + * Add cache entry + */ + if (ssl->conf->f_set_cache != NULL && + ssl->session->id_len != 0 && + resume == 0) { + if (ssl->conf->f_set_cache(ssl->conf->p_cache, + ssl->session->id, + ssl->session->id_len, + ssl->session) != 0) { + MBEDTLS_SSL_DEBUG_MSG(1, ("cache did not store session")); + } } - ret = ssl_populate_transform(ssl->transform, - ssl->session->ciphersuite, - ssl->session->master, -#if defined(MBEDTLS_SSL_SOME_MODES_USE_MAC) -#if defined(MBEDTLS_SSL_ENCRYPT_THEN_MAC) - ssl->session->encrypt_then_mac, -#endif -#if defined(MBEDTLS_SSL_TRUNCATED_HMAC) - ssl->session->trunc_hmac, -#endif -#endif /* MBEDTLS_SSL_SOME_MODES_USE_MAC */ -#if defined(MBEDTLS_ZLIB_SUPPORT) - ssl->session->compression, -#endif - prf_func, - p, /* currently pointing to randbytes */ - MBEDTLS_SSL_MINOR_VERSION_3, /* (D)TLS 1.2 is forced */ - ssl->conf->endpoint, - ssl); - if (ret != 0) { - return ret; - } +#if defined(MBEDTLS_SSL_PROTO_DTLS) + if (ssl->conf->transport == MBEDTLS_SSL_TRANSPORT_DATAGRAM && + ssl->handshake->flight != NULL) { + /* Cancel handshake timer */ + mbedtls_ssl_set_timer(ssl, 0); - p += sizeof(ssl->transform->randbytes); + /* Keep last flight around in case we need to resend it: + * we need the handshake and transform structures for that */ + MBEDTLS_SSL_DEBUG_MSG(3, ("skip freeing handshake and transform")); + } else +#endif + mbedtls_ssl_handshake_wrapup_free_hs_transform(ssl); -#if defined(MBEDTLS_SSL_DTLS_CONNECTION_ID) - /* Read connection IDs and store them */ - if ((size_t) (end - p) < 1) { - return MBEDTLS_ERR_SSL_BAD_INPUT_DATA; - } + ssl->state = MBEDTLS_SSL_HANDSHAKE_OVER; - ssl->transform->in_cid_len = *p++; + MBEDTLS_SSL_DEBUG_MSG(3, ("<= handshake wrapup")); +} - if ((size_t) (end - p) < ssl->transform->in_cid_len + 1u) { - return MBEDTLS_ERR_SSL_BAD_INPUT_DATA; - } +int mbedtls_ssl_write_finished(mbedtls_ssl_context *ssl) +{ + int ret; + unsigned int hash_len; - memcpy(ssl->transform->in_cid, p, ssl->transform->in_cid_len); - p += ssl->transform->in_cid_len; + MBEDTLS_SSL_DEBUG_MSG(2, ("=> write finished")); - ssl->transform->out_cid_len = *p++; + mbedtls_ssl_update_out_pointers(ssl, ssl->transform_negotiate); - if ((size_t) (end - p) < ssl->transform->out_cid_len) { - return MBEDTLS_ERR_SSL_BAD_INPUT_DATA; + ret = ssl->handshake->calc_finished(ssl, ssl->out_msg + 4, ssl->conf->endpoint); + if (ret != 0) { + MBEDTLS_SSL_DEBUG_RET(1, "calc_finished", ret); } - memcpy(ssl->transform->out_cid, p, ssl->transform->out_cid_len); - p += ssl->transform->out_cid_len; -#endif /* MBEDTLS_SSL_DTLS_CONNECTION_ID */ - /* - * Saved fields from top-level ssl_context structure + * RFC 5246 7.4.9 (Page 63) says 12 is the default length and ciphersuites + * may define some other value. Currently (early 2016), no defined + * ciphersuite does this (and this is unlikely to change as activity has + * moved to TLS 1.3 now) so we can keep the hardcoded 12 here. */ -#if defined(MBEDTLS_SSL_DTLS_BADMAC_LIMIT) - if ((size_t) (end - p) < 4) { - return MBEDTLS_ERR_SSL_BAD_INPUT_DATA; - } - - ssl->badmac_seen = ((uint32_t) p[0] << 24) | - ((uint32_t) p[1] << 16) | - ((uint32_t) p[2] << 8) | - ((uint32_t) p[3]); - p += 4; -#endif /* MBEDTLS_SSL_DTLS_BADMAC_LIMIT */ - -#if defined(MBEDTLS_SSL_DTLS_ANTI_REPLAY) - if ((size_t) (end - p) < 16) { - return MBEDTLS_ERR_SSL_BAD_INPUT_DATA; - } - - ssl->in_window_top = ((uint64_t) p[0] << 56) | - ((uint64_t) p[1] << 48) | - ((uint64_t) p[2] << 40) | - ((uint64_t) p[3] << 32) | - ((uint64_t) p[4] << 24) | - ((uint64_t) p[5] << 16) | - ((uint64_t) p[6] << 8) | - ((uint64_t) p[7]); - p += 8; - - ssl->in_window = ((uint64_t) p[0] << 56) | - ((uint64_t) p[1] << 48) | - ((uint64_t) p[2] << 40) | - ((uint64_t) p[3] << 32) | - ((uint64_t) p[4] << 24) | - ((uint64_t) p[5] << 16) | - ((uint64_t) p[6] << 8) | - ((uint64_t) p[7]); - p += 8; -#endif /* MBEDTLS_SSL_DTLS_ANTI_REPLAY */ + hash_len = 12; -#if defined(MBEDTLS_SSL_PROTO_DTLS) - if ((size_t) (end - p) < 1) { - return MBEDTLS_ERR_SSL_BAD_INPUT_DATA; - } +#if defined(MBEDTLS_SSL_RENEGOTIATION) + ssl->verify_data_len = hash_len; + memcpy(ssl->own_verify_data, ssl->out_msg + 4, hash_len); +#endif - ssl->disable_datagram_packing = *p++; -#endif /* MBEDTLS_SSL_PROTO_DTLS */ + ssl->out_msglen = 4 + hash_len; + ssl->out_msgtype = MBEDTLS_SSL_MSG_HANDSHAKE; + ssl->out_msg[0] = MBEDTLS_SSL_HS_FINISHED; - if ((size_t) (end - p) < 8) { - return MBEDTLS_ERR_SSL_BAD_INPUT_DATA; + /* + * In case of session resuming, invert the client and server + * ChangeCipherSpec messages order. + */ + if (ssl->handshake->resume != 0) { +#if defined(MBEDTLS_SSL_CLI_C) + if (ssl->conf->endpoint == MBEDTLS_SSL_IS_CLIENT) { + ssl->state = MBEDTLS_SSL_HANDSHAKE_WRAPUP; + } +#endif +#if defined(MBEDTLS_SSL_SRV_C) + if (ssl->conf->endpoint == MBEDTLS_SSL_IS_SERVER) { + ssl->state = MBEDTLS_SSL_CLIENT_CHANGE_CIPHER_SPEC; + } +#endif + } else { + ssl->state++; } - memcpy(ssl->cur_out_ctr, p, 8); - p += 8; + /* + * Switch to our negotiated transform and session parameters for outbound + * data. + */ + MBEDTLS_SSL_DEBUG_MSG(3, ("switching to new transform spec for outbound data")); #if defined(MBEDTLS_SSL_PROTO_DTLS) - if ((size_t) (end - p) < 2) { - return MBEDTLS_ERR_SSL_BAD_INPUT_DATA; - } - - ssl->mtu = (p[0] << 8) | p[1]; - p += 2; -#endif /* MBEDTLS_SSL_PROTO_DTLS */ + if (ssl->conf->transport == MBEDTLS_SSL_TRANSPORT_DATAGRAM) { + unsigned char i; -#if defined(MBEDTLS_SSL_ALPN) - { - uint8_t alpn_len; - const char **cur; + /* Remember current epoch settings for resending */ + ssl->handshake->alt_transform_out = ssl->transform_out; + memcpy(ssl->handshake->alt_out_ctr, ssl->cur_out_ctr, + sizeof(ssl->handshake->alt_out_ctr)); - if ((size_t) (end - p) < 1) { - return MBEDTLS_ERR_SSL_BAD_INPUT_DATA; - } + /* Set sequence_number to zero */ + memset(&ssl->cur_out_ctr[2], 0, sizeof(ssl->cur_out_ctr) - 2); - alpn_len = *p++; - if (alpn_len != 0 && ssl->conf->alpn_list != NULL) { - /* alpn_chosen should point to an item in the configured list */ - for (cur = ssl->conf->alpn_list; *cur != NULL; cur++) { - if (strlen(*cur) == alpn_len && - memcmp(p, cur, alpn_len) == 0) { - ssl->alpn_chosen = *cur; - break; - } + /* Increment epoch */ + for (i = 2; i > 0; i--) { + if (++ssl->cur_out_ctr[i - 1] != 0) { + break; } } - /* can only happen on conf mismatch */ - if (alpn_len != 0 && ssl->alpn_chosen == NULL) { - return MBEDTLS_ERR_SSL_BAD_INPUT_DATA; + /* The loop goes to its end iff the counter is wrapping */ + if (i == 0) { + MBEDTLS_SSL_DEBUG_MSG(1, ("DTLS epoch would wrap")); + return MBEDTLS_ERR_SSL_COUNTER_WRAPPING; } + } else +#endif /* MBEDTLS_SSL_PROTO_DTLS */ + memset(ssl->cur_out_ctr, 0, sizeof(ssl->cur_out_ctr)); - p += alpn_len; - } -#endif /* MBEDTLS_SSL_ALPN */ - - /* - * Forced fields from top-level ssl_context structure - * - * Most of them already set to the correct value by mbedtls_ssl_init() and - * mbedtls_ssl_reset(), so we only need to set the remaining ones. - */ - ssl->state = MBEDTLS_SSL_HANDSHAKE_OVER; - - ssl->major_ver = MBEDTLS_SSL_MAJOR_VERSION_3; - ssl->minor_ver = MBEDTLS_SSL_MINOR_VERSION_3; - - /* Adjust pointers for header fields of outgoing records to - * the given transform, accounting for explicit IV and CID. */ - mbedtls_ssl_update_out_pointers(ssl, ssl->transform); + ssl->transform_out = ssl->transform_negotiate; + ssl->session_out = ssl->session_negotiate; #if defined(MBEDTLS_SSL_PROTO_DTLS) - ssl->in_epoch = 1; + if (ssl->conf->transport == MBEDTLS_SSL_TRANSPORT_DATAGRAM) { + mbedtls_ssl_send_flight_completed(ssl); + } #endif - /* mbedtls_ssl_reset() leaves the handshake sub-structure allocated, - * which we don't want - otherwise we'd end up freeing the wrong transform - * by calling mbedtls_ssl_handshake_wrapup_free_hs_transform() - * inappropriately. */ - if (ssl->handshake != NULL) { - mbedtls_ssl_handshake_free(ssl); - mbedtls_free(ssl->handshake); - ssl->handshake = NULL; + if ((ret = mbedtls_ssl_write_handshake_msg(ssl)) != 0) { + MBEDTLS_SSL_DEBUG_RET(1, "mbedtls_ssl_write_handshake_msg", ret); + return ret; + } + +#if defined(MBEDTLS_SSL_PROTO_DTLS) + if (ssl->conf->transport == MBEDTLS_SSL_TRANSPORT_DATAGRAM && + (ret = mbedtls_ssl_flight_transmit(ssl)) != 0) { + MBEDTLS_SSL_DEBUG_RET(1, "mbedtls_ssl_flight_transmit", ret); + return ret; } +#endif - /* - * Done - should have consumed entire buffer - */ - if (p != end) { - return MBEDTLS_ERR_SSL_BAD_INPUT_DATA; - } + MBEDTLS_SSL_DEBUG_MSG(2, ("<= write finished")); return 0; } -/* - * Deserialize context: public wrapper for error cleaning - */ -int mbedtls_ssl_context_load(mbedtls_ssl_context *context, - const unsigned char *buf, - size_t len) -{ - int ret = ssl_context_load(context, buf, len); - - if (ret != 0) { - mbedtls_ssl_free(context); - } - - return ret; -} -#endif /* MBEDTLS_SSL_CONTEXT_SERIALIZATION */ +#define SSL_MAX_HASH_LEN 12 -/* - * Free an SSL context - */ -void mbedtls_ssl_free(mbedtls_ssl_context *ssl) +int mbedtls_ssl_parse_finished(mbedtls_ssl_context *ssl) { - if (ssl == NULL) { - return; - } - - MBEDTLS_SSL_DEBUG_MSG(2, ("=> free")); + int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED; + unsigned int hash_len = 12; + unsigned char buf[SSL_MAX_HASH_LEN]; - if (ssl->out_buf != NULL) { -#if defined(MBEDTLS_SSL_VARIABLE_BUFFER_LENGTH) - size_t out_buf_len = ssl->out_buf_len; -#else - size_t out_buf_len = MBEDTLS_SSL_OUT_BUFFER_LEN; -#endif + MBEDTLS_SSL_DEBUG_MSG(2, ("=> parse finished")); - mbedtls_platform_zeroize(ssl->out_buf, out_buf_len); - mbedtls_free(ssl->out_buf); - ssl->out_buf = NULL; + ret = ssl->handshake->calc_finished(ssl, buf, ssl->conf->endpoint ^ 1); + if (ret != 0) { + MBEDTLS_SSL_DEBUG_RET(1, "calc_finished", ret); } - if (ssl->in_buf != NULL) { -#if defined(MBEDTLS_SSL_VARIABLE_BUFFER_LENGTH) - size_t in_buf_len = ssl->in_buf_len; -#else - size_t in_buf_len = MBEDTLS_SSL_IN_BUFFER_LEN; -#endif - - mbedtls_platform_zeroize(ssl->in_buf, in_buf_len); - mbedtls_free(ssl->in_buf); - ssl->in_buf = NULL; + if ((ret = mbedtls_ssl_read_record(ssl, 1)) != 0) { + MBEDTLS_SSL_DEBUG_RET(1, "mbedtls_ssl_read_record", ret); + goto exit; } -#if defined(MBEDTLS_ZLIB_SUPPORT) - if (ssl->compress_buf != NULL) { - mbedtls_platform_zeroize(ssl->compress_buf, MBEDTLS_SSL_COMPRESS_BUFFER_LEN); - mbedtls_free(ssl->compress_buf); + if (ssl->in_msgtype != MBEDTLS_SSL_MSG_HANDSHAKE) { + MBEDTLS_SSL_DEBUG_MSG(1, ("bad finished message")); + mbedtls_ssl_send_alert_message(ssl, MBEDTLS_SSL_ALERT_LEVEL_FATAL, + MBEDTLS_SSL_ALERT_MSG_UNEXPECTED_MESSAGE); + ret = MBEDTLS_ERR_SSL_UNEXPECTED_MESSAGE; + goto exit; } -#endif - if (ssl->transform) { - mbedtls_ssl_transform_free(ssl->transform); - mbedtls_free(ssl->transform); + if (ssl->in_msg[0] != MBEDTLS_SSL_HS_FINISHED) { + mbedtls_ssl_send_alert_message(ssl, MBEDTLS_SSL_ALERT_LEVEL_FATAL, + MBEDTLS_SSL_ALERT_MSG_UNEXPECTED_MESSAGE); + ret = MBEDTLS_ERR_SSL_UNEXPECTED_MESSAGE; + goto exit; } - if (ssl->handshake) { - mbedtls_ssl_handshake_free(ssl); - mbedtls_ssl_transform_free(ssl->transform_negotiate); - mbedtls_ssl_session_free(ssl->session_negotiate); - - mbedtls_free(ssl->handshake); - mbedtls_free(ssl->transform_negotiate); - mbedtls_free(ssl->session_negotiate); + if (ssl->in_hslen != mbedtls_ssl_hs_hdr_len(ssl) + hash_len) { + MBEDTLS_SSL_DEBUG_MSG(1, ("bad finished message")); + mbedtls_ssl_send_alert_message(ssl, MBEDTLS_SSL_ALERT_LEVEL_FATAL, + MBEDTLS_SSL_ALERT_MSG_DECODE_ERROR); + ret = MBEDTLS_ERR_SSL_DECODE_ERROR; + goto exit; } - if (ssl->session) { - mbedtls_ssl_session_free(ssl->session); - mbedtls_free(ssl->session); + if (mbedtls_ct_memcmp(ssl->in_msg + mbedtls_ssl_hs_hdr_len(ssl), + buf, hash_len) != 0) { + MBEDTLS_SSL_DEBUG_MSG(1, ("bad finished message")); + mbedtls_ssl_send_alert_message(ssl, MBEDTLS_SSL_ALERT_LEVEL_FATAL, + MBEDTLS_SSL_ALERT_MSG_DECRYPT_ERROR); + ret = MBEDTLS_ERR_SSL_HANDSHAKE_FAILURE; + goto exit; } -#if defined(MBEDTLS_X509_CRT_PARSE_C) - if (ssl->hostname != NULL) { - mbedtls_platform_zeroize(ssl->hostname, strlen(ssl->hostname)); - mbedtls_free(ssl->hostname); - } +#if defined(MBEDTLS_SSL_RENEGOTIATION) + ssl->verify_data_len = hash_len; + memcpy(ssl->peer_verify_data, buf, hash_len); #endif -#if defined(MBEDTLS_SSL_HW_RECORD_ACCEL) - if (mbedtls_ssl_hw_record_finish != NULL) { - MBEDTLS_SSL_DEBUG_MSG(2, ("going for mbedtls_ssl_hw_record_finish()")); - mbedtls_ssl_hw_record_finish(ssl); - } + if (ssl->handshake->resume != 0) { +#if defined(MBEDTLS_SSL_CLI_C) + if (ssl->conf->endpoint == MBEDTLS_SSL_IS_CLIENT) { + ssl->state = MBEDTLS_SSL_CLIENT_CHANGE_CIPHER_SPEC; + } #endif +#if defined(MBEDTLS_SSL_SRV_C) + if (ssl->conf->endpoint == MBEDTLS_SSL_IS_SERVER) { + ssl->state = MBEDTLS_SSL_HANDSHAKE_WRAPUP; + } +#endif + } else { + ssl->state++; + } -#if defined(MBEDTLS_SSL_DTLS_HELLO_VERIFY) && defined(MBEDTLS_SSL_SRV_C) - mbedtls_free(ssl->cli_id); +#if defined(MBEDTLS_SSL_PROTO_DTLS) + if (ssl->conf->transport == MBEDTLS_SSL_TRANSPORT_DATAGRAM) { + mbedtls_ssl_recv_flight_completed(ssl); + } #endif - MBEDTLS_SSL_DEBUG_MSG(2, ("<= free")); + MBEDTLS_SSL_DEBUG_MSG(2, ("<= parse finished")); - /* Actually clear after last debug message */ - mbedtls_platform_zeroize(ssl, sizeof(mbedtls_ssl_context)); +exit: + mbedtls_platform_zeroize(buf, hash_len); + return ret; } +#if defined(MBEDTLS_SSL_CONTEXT_SERIALIZATION) /* - * Initialize mbedtls_ssl_config + * Helper to get TLS 1.2 PRF from ciphersuite + * (Duplicates bits of logic from ssl_set_handshake_prfs().) */ -void mbedtls_ssl_config_init(mbedtls_ssl_config *conf) +static tls_prf_fn ssl_tls12prf_from_cs(int ciphersuite_id) { - memset(conf, 0, sizeof(mbedtls_ssl_config)); -} - -#if defined(MBEDTLS_KEY_EXCHANGE_WITH_CERT_ENABLED) -static int ssl_preset_default_hashes[] = { -#if defined(MBEDTLS_SHA512_C) - MBEDTLS_MD_SHA512, -#endif -#if defined(MBEDTLS_SHA512_C) && !defined(MBEDTLS_SHA512_NO_SHA384) - MBEDTLS_MD_SHA384, -#endif -#if defined(MBEDTLS_SHA256_C) - MBEDTLS_MD_SHA256, - MBEDTLS_MD_SHA224, + const mbedtls_ssl_ciphersuite_t * const ciphersuite_info = + mbedtls_ssl_ciphersuite_from_id(ciphersuite_id); +#if defined(MBEDTLS_MD_CAN_SHA384) + if (ciphersuite_info != NULL && ciphersuite_info->mac == MBEDTLS_MD_SHA384) { + return tls_prf_sha384; + } else #endif -#if defined(MBEDTLS_SHA1_C) && defined(MBEDTLS_TLS_DEFAULT_ALLOW_SHA1_IN_KEY_EXCHANGE) - MBEDTLS_MD_SHA1, +#if defined(MBEDTLS_MD_CAN_SHA256) + { + if (ciphersuite_info != NULL && ciphersuite_info->mac == MBEDTLS_MD_SHA256) { + return tls_prf_sha256; + } + } #endif - MBEDTLS_MD_NONE -}; +#if !defined(MBEDTLS_MD_CAN_SHA384) && \ + !defined(MBEDTLS_MD_CAN_SHA256) + (void) ciphersuite_info; #endif -static int ssl_preset_suiteb_ciphersuites[] = { - MBEDTLS_TLS_ECDHE_ECDSA_WITH_AES_128_GCM_SHA256, - MBEDTLS_TLS_ECDHE_ECDSA_WITH_AES_256_GCM_SHA384, - 0 -}; - -#if defined(MBEDTLS_KEY_EXCHANGE_WITH_CERT_ENABLED) -static int ssl_preset_suiteb_hashes[] = { - MBEDTLS_MD_SHA256, - MBEDTLS_MD_SHA384, - MBEDTLS_MD_NONE -}; -#endif + return NULL; +} +#endif /* MBEDTLS_SSL_CONTEXT_SERIALIZATION */ -#if defined(MBEDTLS_ECP_C) -static mbedtls_ecp_group_id ssl_preset_suiteb_curves[] = { -#if defined(MBEDTLS_ECP_DP_SECP256R1_ENABLED) - MBEDTLS_ECP_DP_SECP256R1, -#endif -#if defined(MBEDTLS_ECP_DP_SECP384R1_ENABLED) - MBEDTLS_ECP_DP_SECP384R1, +static mbedtls_tls_prf_types tls_prf_get_type(mbedtls_ssl_tls_prf_cb *tls_prf) +{ + ((void) tls_prf); +#if defined(MBEDTLS_MD_CAN_SHA384) + if (tls_prf == tls_prf_sha384) { + return MBEDTLS_SSL_TLS_PRF_SHA384; + } else #endif - MBEDTLS_ECP_DP_NONE -}; +#if defined(MBEDTLS_MD_CAN_SHA256) + if (tls_prf == tls_prf_sha256) { + return MBEDTLS_SSL_TLS_PRF_SHA256; + } else #endif + return MBEDTLS_SSL_TLS_PRF_NONE; +} /* - * Load default in mbedtls_ssl_config + * Populate a transform structure with session keys and all the other + * necessary information. + * + * Parameters: + * - [in/out]: transform: structure to populate + * [in] must be just initialised with mbedtls_ssl_transform_init() + * [out] fully populated, ready for use by mbedtls_ssl_{en,de}crypt_buf() + * - [in] ciphersuite + * - [in] master + * - [in] encrypt_then_mac + * - [in] tls_prf: pointer to PRF to use for key derivation + * - [in] randbytes: buffer holding ServerHello.random + ClientHello.random + * - [in] tls_version: TLS version + * - [in] endpoint: client or server + * - [in] ssl: used for: + * - ssl->conf->{f,p}_export_keys + * [in] optionally used for: + * - MBEDTLS_DEBUG_C: ssl->conf->{f,p}_dbg */ -int mbedtls_ssl_config_defaults(mbedtls_ssl_config *conf, - int endpoint, int transport, int preset) +MBEDTLS_CHECK_RETURN_CRITICAL +static int ssl_tls12_populate_transform(mbedtls_ssl_transform *transform, + int ciphersuite, + const unsigned char master[48], +#if defined(MBEDTLS_SSL_SOME_SUITES_USE_CBC_ETM) + int encrypt_then_mac, +#endif /* MBEDTLS_SSL_SOME_SUITES_USE_CBC_ETM */ + ssl_tls_prf_t tls_prf, + const unsigned char randbytes[64], + mbedtls_ssl_protocol_version tls_version, + unsigned endpoint, + const mbedtls_ssl_context *ssl) { -#if defined(MBEDTLS_DHM_C) && defined(MBEDTLS_SSL_SRV_C) - int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED; -#endif - - /* Use the functions here so that they are covered in tests, - * but otherwise access member directly for efficiency */ - mbedtls_ssl_conf_endpoint(conf, endpoint); - mbedtls_ssl_conf_transport(conf, transport); - - /* - * Things that are common to all presets - */ -#if defined(MBEDTLS_SSL_CLI_C) - if (endpoint == MBEDTLS_SSL_IS_CLIENT) { - conf->authmode = MBEDTLS_SSL_VERIFY_REQUIRED; -#if defined(MBEDTLS_SSL_SESSION_TICKETS) - conf->session_tickets = MBEDTLS_SSL_SESSION_TICKETS_ENABLED; -#endif - } -#endif - -#if defined(MBEDTLS_ARC4_C) - conf->arc4_disabled = MBEDTLS_SSL_ARC4_DISABLED; -#endif - -#if defined(MBEDTLS_SSL_ENCRYPT_THEN_MAC) - conf->encrypt_then_mac = MBEDTLS_SSL_ETM_ENABLED; -#endif - -#if defined(MBEDTLS_SSL_EXTENDED_MASTER_SECRET) - conf->extended_ms = MBEDTLS_SSL_EXTENDED_MS_ENABLED; -#endif - -#if defined(MBEDTLS_SSL_CBC_RECORD_SPLITTING) - conf->cbc_record_splitting = MBEDTLS_SSL_CBC_RECORD_SPLITTING_ENABLED; -#endif - -#if defined(MBEDTLS_SSL_DTLS_HELLO_VERIFY) && defined(MBEDTLS_SSL_SRV_C) - conf->f_cookie_write = ssl_cookie_write_dummy; - conf->f_cookie_check = ssl_cookie_check_dummy; -#endif - -#if defined(MBEDTLS_SSL_DTLS_ANTI_REPLAY) - conf->anti_replay = MBEDTLS_SSL_ANTI_REPLAY_ENABLED; -#endif - -#if defined(MBEDTLS_SSL_SRV_C) - conf->cert_req_ca_list = MBEDTLS_SSL_CERT_REQ_CA_LIST_ENABLED; -#endif - -#if defined(MBEDTLS_SSL_PROTO_DTLS) - conf->hs_timeout_min = MBEDTLS_SSL_DTLS_TIMEOUT_DFL_MIN; - conf->hs_timeout_max = MBEDTLS_SSL_DTLS_TIMEOUT_DFL_MAX; -#endif + int ret = 0; + unsigned char keyblk[256]; + unsigned char *key1; + unsigned char *key2; + unsigned char *mac_enc; + unsigned char *mac_dec; + size_t mac_key_len = 0; + size_t iv_copy_len; + size_t keylen; + const mbedtls_ssl_ciphersuite_t *ciphersuite_info; + mbedtls_ssl_mode_t ssl_mode; +#if !defined(MBEDTLS_USE_PSA_CRYPTO) + const mbedtls_cipher_info_t *cipher_info; + const mbedtls_md_info_t *md_info; +#endif /* !MBEDTLS_USE_PSA_CRYPTO */ -#if defined(MBEDTLS_SSL_RENEGOTIATION) - conf->renego_max_records = MBEDTLS_SSL_RENEGO_MAX_RECORDS_DEFAULT; - memset(conf->renego_period, 0x00, 2); - memset(conf->renego_period + 2, 0xFF, 6); +#if defined(MBEDTLS_USE_PSA_CRYPTO) + psa_key_type_t key_type; + psa_key_attributes_t attributes = PSA_KEY_ATTRIBUTES_INIT; + psa_algorithm_t alg; + psa_algorithm_t mac_alg = 0; + size_t key_bits; + psa_status_t status = PSA_ERROR_CORRUPTION_DETECTED; #endif -#if defined(MBEDTLS_DHM_C) && defined(MBEDTLS_SSL_SRV_C) - if (endpoint == MBEDTLS_SSL_IS_SERVER) { - const unsigned char dhm_p[] = - MBEDTLS_DHM_RFC3526_MODP_2048_P_BIN; - const unsigned char dhm_g[] = - MBEDTLS_DHM_RFC3526_MODP_2048_G_BIN; + /* + * Some data just needs copying into the structure + */ +#if defined(MBEDTLS_SSL_SOME_SUITES_USE_CBC_ETM) + transform->encrypt_then_mac = encrypt_then_mac; +#endif /* MBEDTLS_SSL_SOME_SUITES_USE_CBC_ETM */ + transform->tls_version = tls_version; - if ((ret = mbedtls_ssl_conf_dh_param_bin(conf, - dhm_p, sizeof(dhm_p), - dhm_g, sizeof(dhm_g))) != 0) { - return ret; - } - } +#if defined(MBEDTLS_SSL_CONTEXT_SERIALIZATION) + memcpy(transform->randbytes, randbytes, sizeof(transform->randbytes)); #endif +#if defined(MBEDTLS_SSL_PROTO_TLS1_3) + if (tls_version == MBEDTLS_SSL_VERSION_TLS1_3) { + /* At the moment, we keep TLS <= 1.2 and TLS 1.3 transform + * generation separate. This should never happen. */ + return MBEDTLS_ERR_SSL_INTERNAL_ERROR; + } +#endif /* MBEDTLS_SSL_PROTO_TLS1_3 */ + /* - * Preset-specific defaults + * Get various info structures */ - switch (preset) { - /* - * NSA Suite B - */ - case MBEDTLS_SSL_PRESET_SUITEB: - conf->min_major_ver = MBEDTLS_SSL_MAJOR_VERSION_3; - conf->min_minor_ver = MBEDTLS_SSL_MINOR_VERSION_3; /* TLS 1.2 */ - conf->max_major_ver = MBEDTLS_SSL_MAX_MAJOR_VERSION; - conf->max_minor_ver = MBEDTLS_SSL_MAX_MINOR_VERSION; + ciphersuite_info = mbedtls_ssl_ciphersuite_from_id(ciphersuite); + if (ciphersuite_info == NULL) { + MBEDTLS_SSL_DEBUG_MSG(1, ("ciphersuite info for %d not found", + ciphersuite)); + return MBEDTLS_ERR_SSL_BAD_INPUT_DATA; + } - conf->ciphersuite_list[MBEDTLS_SSL_MINOR_VERSION_0] = - conf->ciphersuite_list[MBEDTLS_SSL_MINOR_VERSION_1] = - conf->ciphersuite_list[MBEDTLS_SSL_MINOR_VERSION_2] = - conf->ciphersuite_list[MBEDTLS_SSL_MINOR_VERSION_3] = - ssl_preset_suiteb_ciphersuites; + ssl_mode = mbedtls_ssl_get_mode_from_ciphersuite( +#if defined(MBEDTLS_SSL_SOME_SUITES_USE_CBC_ETM) + encrypt_then_mac, +#endif /* MBEDTLS_SSL_SOME_SUITES_USE_CBC_ETM */ + ciphersuite_info); -#if defined(MBEDTLS_X509_CRT_PARSE_C) - conf->cert_profile = &mbedtls_x509_crt_profile_suiteb; -#endif + if (ssl_mode == MBEDTLS_SSL_MODE_AEAD) { + transform->taglen = + ciphersuite_info->flags & MBEDTLS_CIPHERSUITE_SHORT_TAG ? 8 : 16; + } -#if defined(MBEDTLS_KEY_EXCHANGE_WITH_CERT_ENABLED) - conf->sig_hashes = ssl_preset_suiteb_hashes; -#endif +#if defined(MBEDTLS_USE_PSA_CRYPTO) + if ((status = mbedtls_ssl_cipher_to_psa((mbedtls_cipher_type_t) ciphersuite_info->cipher, + transform->taglen, + &alg, + &key_type, + &key_bits)) != PSA_SUCCESS) { + ret = PSA_TO_MBEDTLS_ERR(status); + MBEDTLS_SSL_DEBUG_RET(1, "mbedtls_ssl_cipher_to_psa", ret); + goto end; + } +#else + cipher_info = mbedtls_cipher_info_from_type((mbedtls_cipher_type_t) ciphersuite_info->cipher); + if (cipher_info == NULL) { + MBEDTLS_SSL_DEBUG_MSG(1, ("cipher info for %u not found", + ciphersuite_info->cipher)); + return MBEDTLS_ERR_SSL_BAD_INPUT_DATA; + } +#endif /* MBEDTLS_USE_PSA_CRYPTO */ -#if defined(MBEDTLS_ECP_C) - conf->curve_list = ssl_preset_suiteb_curves; -#endif - break; +#if defined(MBEDTLS_USE_PSA_CRYPTO) + mac_alg = mbedtls_md_psa_alg_from_type((mbedtls_md_type_t) ciphersuite_info->mac); + if (mac_alg == 0) { + MBEDTLS_SSL_DEBUG_MSG(1, ("mbedtls_md_psa_alg_from_type for %u not found", + (unsigned) ciphersuite_info->mac)); + return MBEDTLS_ERR_SSL_BAD_INPUT_DATA; + } +#else + md_info = mbedtls_md_info_from_type((mbedtls_md_type_t) ciphersuite_info->mac); + if (md_info == NULL) { + MBEDTLS_SSL_DEBUG_MSG(1, ("mbedtls_md info for %u not found", + (unsigned) ciphersuite_info->mac)); + return MBEDTLS_ERR_SSL_BAD_INPUT_DATA; + } +#endif /* MBEDTLS_USE_PSA_CRYPTO */ - /* - * Default - */ - default: - conf->min_major_ver = (MBEDTLS_SSL_MIN_MAJOR_VERSION > - MBEDTLS_SSL_MIN_VALID_MAJOR_VERSION) ? - MBEDTLS_SSL_MIN_MAJOR_VERSION : - MBEDTLS_SSL_MIN_VALID_MAJOR_VERSION; - conf->min_minor_ver = (MBEDTLS_SSL_MIN_MINOR_VERSION > - MBEDTLS_SSL_MIN_VALID_MINOR_VERSION) ? - MBEDTLS_SSL_MIN_MINOR_VERSION : - MBEDTLS_SSL_MIN_VALID_MINOR_VERSION; - conf->max_major_ver = MBEDTLS_SSL_MAX_MAJOR_VERSION; - conf->max_minor_ver = MBEDTLS_SSL_MAX_MINOR_VERSION; +#if defined(MBEDTLS_SSL_DTLS_CONNECTION_ID) + /* Copy own and peer's CID if the use of the CID + * extension has been negotiated. */ + if (ssl->handshake->cid_in_use == MBEDTLS_SSL_CID_ENABLED) { + MBEDTLS_SSL_DEBUG_MSG(3, ("Copy CIDs into SSL transform")); -#if defined(MBEDTLS_SSL_PROTO_DTLS) - if (transport == MBEDTLS_SSL_TRANSPORT_DATAGRAM) { - conf->min_minor_ver = MBEDTLS_SSL_MINOR_VERSION_2; - } -#endif + transform->in_cid_len = ssl->own_cid_len; + memcpy(transform->in_cid, ssl->own_cid, ssl->own_cid_len); + MBEDTLS_SSL_DEBUG_BUF(3, "Incoming CID", transform->in_cid, + transform->in_cid_len); - conf->ciphersuite_list[MBEDTLS_SSL_MINOR_VERSION_0] = - conf->ciphersuite_list[MBEDTLS_SSL_MINOR_VERSION_1] = - conf->ciphersuite_list[MBEDTLS_SSL_MINOR_VERSION_2] = - conf->ciphersuite_list[MBEDTLS_SSL_MINOR_VERSION_3] = - mbedtls_ssl_list_ciphersuites(); + transform->out_cid_len = ssl->handshake->peer_cid_len; + memcpy(transform->out_cid, ssl->handshake->peer_cid, + ssl->handshake->peer_cid_len); + MBEDTLS_SSL_DEBUG_BUF(3, "Outgoing CID", transform->out_cid, + transform->out_cid_len); + } +#endif /* MBEDTLS_SSL_DTLS_CONNECTION_ID */ -#if defined(MBEDTLS_X509_CRT_PARSE_C) - conf->cert_profile = &mbedtls_x509_crt_profile_default; -#endif + /* + * Compute key block using the PRF + */ + ret = tls_prf(master, 48, "key expansion", randbytes, 64, keyblk, 256); + if (ret != 0) { + MBEDTLS_SSL_DEBUG_RET(1, "prf", ret); + return ret; + } -#if defined(MBEDTLS_KEY_EXCHANGE_WITH_CERT_ENABLED) - conf->sig_hashes = ssl_preset_default_hashes; -#endif + MBEDTLS_SSL_DEBUG_MSG(3, ("ciphersuite = %s", + mbedtls_ssl_get_ciphersuite_name(ciphersuite))); + MBEDTLS_SSL_DEBUG_BUF(3, "master secret", master, 48); + MBEDTLS_SSL_DEBUG_BUF(4, "random bytes", randbytes, 64); + MBEDTLS_SSL_DEBUG_BUF(4, "key block", keyblk, 256); -#if defined(MBEDTLS_ECP_C) - conf->curve_list = mbedtls_ecp_grp_id_list(); -#endif + /* + * Determine the appropriate key, IV and MAC length. + */ -#if defined(MBEDTLS_DHM_C) && defined(MBEDTLS_SSL_CLI_C) - conf->dhm_min_bitlen = 1024; +#if defined(MBEDTLS_USE_PSA_CRYPTO) + keylen = PSA_BITS_TO_BYTES(key_bits); +#else + keylen = mbedtls_cipher_info_get_key_bitlen(cipher_info) / 8; #endif - } - return 0; -} +#if defined(MBEDTLS_SSL_HAVE_AEAD) + if (ssl_mode == MBEDTLS_SSL_MODE_AEAD) { + size_t explicit_ivlen; -/* - * Free mbedtls_ssl_config - */ -void mbedtls_ssl_config_free(mbedtls_ssl_config *conf) -{ -#if defined(MBEDTLS_DHM_C) - mbedtls_mpi_free(&conf->dhm_P); - mbedtls_mpi_free(&conf->dhm_G); -#endif + transform->maclen = 0; + mac_key_len = 0; -#if defined(MBEDTLS_KEY_EXCHANGE_SOME_PSK_ENABLED) - if (conf->psk != NULL) { - mbedtls_platform_zeroize(conf->psk, conf->psk_len); - mbedtls_free(conf->psk); - conf->psk = NULL; - conf->psk_len = 0; - } + /* All modes haves 96-bit IVs, but the length of the static parts vary + * with mode and version: + * - For GCM and CCM in TLS 1.2, there's a static IV of 4 Bytes + * (to be concatenated with a dynamically chosen IV of 8 Bytes) + * - For ChaChaPoly in TLS 1.2, and all modes in TLS 1.3, there's + * a static IV of 12 Bytes (to be XOR'ed with the 8 Byte record + * sequence number). + */ + transform->ivlen = 12; - if (conf->psk_identity != NULL) { - mbedtls_platform_zeroize(conf->psk_identity, conf->psk_identity_len); - mbedtls_free(conf->psk_identity); - conf->psk_identity = NULL; - conf->psk_identity_len = 0; - } -#endif + int is_chachapoly = 0; +#if defined(MBEDTLS_USE_PSA_CRYPTO) + is_chachapoly = (key_type == PSA_KEY_TYPE_CHACHA20); +#else + is_chachapoly = (mbedtls_cipher_info_get_mode(cipher_info) + == MBEDTLS_MODE_CHACHAPOLY); +#endif /* MBEDTLS_USE_PSA_CRYPTO */ -#if defined(MBEDTLS_X509_CRT_PARSE_C) - ssl_key_cert_free(conf->key_cert); -#endif + if (is_chachapoly) { + transform->fixed_ivlen = 12; + } else { + transform->fixed_ivlen = 4; + } - mbedtls_platform_zeroize(conf, sizeof(mbedtls_ssl_config)); -} + /* Minimum length of encrypted record */ + explicit_ivlen = transform->ivlen - transform->fixed_ivlen; + transform->minlen = explicit_ivlen + transform->taglen; + } else +#endif /* MBEDTLS_SSL_HAVE_AEAD */ +#if defined(MBEDTLS_SSL_SOME_SUITES_USE_MAC) + if (ssl_mode == MBEDTLS_SSL_MODE_STREAM || + ssl_mode == MBEDTLS_SSL_MODE_CBC || + ssl_mode == MBEDTLS_SSL_MODE_CBC_ETM) { +#if defined(MBEDTLS_USE_PSA_CRYPTO) + size_t block_size = PSA_BLOCK_CIPHER_BLOCK_LENGTH(key_type); +#else + size_t block_size = mbedtls_cipher_info_get_block_size(cipher_info); +#endif /* MBEDTLS_USE_PSA_CRYPTO */ -#if defined(MBEDTLS_PK_C) && \ - (defined(MBEDTLS_RSA_C) || defined(MBEDTLS_ECDSA_C)) -/* - * Convert between MBEDTLS_PK_XXX and SSL_SIG_XXX - */ -unsigned char mbedtls_ssl_sig_from_pk(mbedtls_pk_context *pk) -{ -#if defined(MBEDTLS_RSA_C) - if (mbedtls_pk_can_do(pk, MBEDTLS_PK_RSA)) { - return MBEDTLS_SSL_SIG_RSA; - } -#endif -#if defined(MBEDTLS_ECDSA_C) - if (mbedtls_pk_can_do(pk, MBEDTLS_PK_ECDSA)) { - return MBEDTLS_SSL_SIG_ECDSA; - } -#endif - return MBEDTLS_SSL_SIG_ANON; -} +#if defined(MBEDTLS_USE_PSA_CRYPTO) + /* Get MAC length */ + mac_key_len = PSA_HASH_LENGTH(mac_alg); +#else + /* Initialize HMAC contexts */ + if ((ret = mbedtls_md_setup(&transform->md_ctx_enc, md_info, 1)) != 0 || + (ret = mbedtls_md_setup(&transform->md_ctx_dec, md_info, 1)) != 0) { + MBEDTLS_SSL_DEBUG_RET(1, "mbedtls_md_setup", ret); + goto end; + } -unsigned char mbedtls_ssl_sig_from_pk_alg(mbedtls_pk_type_t type) -{ - switch (type) { - case MBEDTLS_PK_RSA: - return MBEDTLS_SSL_SIG_RSA; - case MBEDTLS_PK_ECDSA: - case MBEDTLS_PK_ECKEY: - return MBEDTLS_SSL_SIG_ECDSA; - default: - return MBEDTLS_SSL_SIG_ANON; - } -} + /* Get MAC length */ + mac_key_len = mbedtls_md_get_size(md_info); +#endif /* MBEDTLS_USE_PSA_CRYPTO */ + transform->maclen = mac_key_len; -mbedtls_pk_type_t mbedtls_ssl_pk_alg_from_sig(unsigned char sig) -{ - switch (sig) { -#if defined(MBEDTLS_RSA_C) - case MBEDTLS_SSL_SIG_RSA: - return MBEDTLS_PK_RSA; -#endif -#if defined(MBEDTLS_ECDSA_C) - case MBEDTLS_SSL_SIG_ECDSA: - return MBEDTLS_PK_ECDSA; -#endif - default: - return MBEDTLS_PK_NONE; - } -} -#endif /* MBEDTLS_PK_C && ( MBEDTLS_RSA_C || MBEDTLS_ECDSA_C ) */ + /* IV length */ +#if defined(MBEDTLS_USE_PSA_CRYPTO) + transform->ivlen = PSA_CIPHER_IV_LENGTH(key_type, alg); +#else + transform->ivlen = mbedtls_cipher_info_get_iv_size(cipher_info); +#endif /* MBEDTLS_USE_PSA_CRYPTO */ -#if defined(MBEDTLS_SSL_PROTO_TLS1_2) && \ - defined(MBEDTLS_KEY_EXCHANGE_WITH_CERT_ENABLED) + /* Minimum length */ + if (ssl_mode == MBEDTLS_SSL_MODE_STREAM) { + transform->minlen = transform->maclen; + } else { + /* + * GenericBlockCipher: + * 1. if EtM is in use: one block plus MAC + * otherwise: * first multiple of blocklen greater than maclen + * 2. IV + */ +#if defined(MBEDTLS_SSL_ENCRYPT_THEN_MAC) + if (ssl_mode == MBEDTLS_SSL_MODE_CBC_ETM) { + transform->minlen = transform->maclen + + block_size; + } else +#endif + { + transform->minlen = transform->maclen + + block_size + - transform->maclen % block_size; + } -/* Find an entry in a signature-hash set matching a given hash algorithm. */ -mbedtls_md_type_t mbedtls_ssl_sig_hash_set_find(mbedtls_ssl_sig_hash_set_t *set, - mbedtls_pk_type_t sig_alg) -{ - switch (sig_alg) { - case MBEDTLS_PK_RSA: - return set->rsa; - case MBEDTLS_PK_ECDSA: - return set->ecdsa; - default: - return MBEDTLS_MD_NONE; + if (tls_version == MBEDTLS_SSL_VERSION_TLS1_2) { + transform->minlen += transform->ivlen; + } else { + MBEDTLS_SSL_DEBUG_MSG(1, ("should never happen")); + ret = MBEDTLS_ERR_SSL_INTERNAL_ERROR; + goto end; + } + } + } else +#endif /* MBEDTLS_SSL_SOME_SUITES_USE_MAC */ + { + MBEDTLS_SSL_DEBUG_MSG(1, ("should never happen")); + return MBEDTLS_ERR_SSL_INTERNAL_ERROR; } -} -/* Add a signature-hash-pair to a signature-hash set */ -void mbedtls_ssl_sig_hash_set_add(mbedtls_ssl_sig_hash_set_t *set, - mbedtls_pk_type_t sig_alg, - mbedtls_md_type_t md_alg) -{ - switch (sig_alg) { - case MBEDTLS_PK_RSA: - if (set->rsa == MBEDTLS_MD_NONE) { - set->rsa = md_alg; - } - break; + MBEDTLS_SSL_DEBUG_MSG(3, ("keylen: %u, minlen: %u, ivlen: %u, maclen: %u", + (unsigned) keylen, + (unsigned) transform->minlen, + (unsigned) transform->ivlen, + (unsigned) transform->maclen)); - case MBEDTLS_PK_ECDSA: - if (set->ecdsa == MBEDTLS_MD_NONE) { - set->ecdsa = md_alg; - } - break; + /* + * Finally setup the cipher contexts, IVs and MAC secrets. + */ +#if defined(MBEDTLS_SSL_CLI_C) + if (endpoint == MBEDTLS_SSL_IS_CLIENT) { + key1 = keyblk + mac_key_len * 2; + key2 = keyblk + mac_key_len * 2 + keylen; - default: - break; - } -} + mac_enc = keyblk; + mac_dec = keyblk + mac_key_len; -/* Allow exactly one hash algorithm for each signature. */ -void mbedtls_ssl_sig_hash_set_const_hash(mbedtls_ssl_sig_hash_set_t *set, - mbedtls_md_type_t md_alg) -{ - set->rsa = md_alg; - set->ecdsa = md_alg; -} + iv_copy_len = (transform->fixed_ivlen) ? + transform->fixed_ivlen : transform->ivlen; + memcpy(transform->iv_enc, key2 + keylen, iv_copy_len); + memcpy(transform->iv_dec, key2 + keylen + iv_copy_len, + iv_copy_len); + } else +#endif /* MBEDTLS_SSL_CLI_C */ +#if defined(MBEDTLS_SSL_SRV_C) + if (endpoint == MBEDTLS_SSL_IS_SERVER) { + key1 = keyblk + mac_key_len * 2 + keylen; + key2 = keyblk + mac_key_len * 2; -#endif /* MBEDTLS_SSL_PROTO_TLS1_2) && - MBEDTLS_KEY_EXCHANGE_WITH_CERT_ENABLED */ + mac_enc = keyblk + mac_key_len; + mac_dec = keyblk; -/* - * Convert from MBEDTLS_SSL_HASH_XXX to MBEDTLS_MD_XXX - */ -mbedtls_md_type_t mbedtls_ssl_md_alg_from_hash(unsigned char hash) -{ - switch (hash) { -#if defined(MBEDTLS_MD5_C) - case MBEDTLS_SSL_HASH_MD5: - return MBEDTLS_MD_MD5; -#endif -#if defined(MBEDTLS_SHA1_C) - case MBEDTLS_SSL_HASH_SHA1: - return MBEDTLS_MD_SHA1; -#endif -#if defined(MBEDTLS_SHA256_C) - case MBEDTLS_SSL_HASH_SHA224: - return MBEDTLS_MD_SHA224; - case MBEDTLS_SSL_HASH_SHA256: - return MBEDTLS_MD_SHA256; -#endif -#if defined(MBEDTLS_SHA512_C) && !defined(MBEDTLS_SHA512_NO_SHA384) - case MBEDTLS_SSL_HASH_SHA384: - return MBEDTLS_MD_SHA384; -#endif -#if defined(MBEDTLS_SHA512_C) - case MBEDTLS_SSL_HASH_SHA512: - return MBEDTLS_MD_SHA512; -#endif - default: - return MBEDTLS_MD_NONE; + iv_copy_len = (transform->fixed_ivlen) ? + transform->fixed_ivlen : transform->ivlen; + memcpy(transform->iv_dec, key1 + keylen, iv_copy_len); + memcpy(transform->iv_enc, key1 + keylen + iv_copy_len, + iv_copy_len); + } else +#endif /* MBEDTLS_SSL_SRV_C */ + { + MBEDTLS_SSL_DEBUG_MSG(1, ("should never happen")); + ret = MBEDTLS_ERR_SSL_INTERNAL_ERROR; + goto end; } -} -/* - * Convert from MBEDTLS_MD_XXX to MBEDTLS_SSL_HASH_XXX - */ -unsigned char mbedtls_ssl_hash_from_md_alg(int md) -{ - switch (md) { -#if defined(MBEDTLS_MD5_C) - case MBEDTLS_MD_MD5: - return MBEDTLS_SSL_HASH_MD5; -#endif -#if defined(MBEDTLS_SHA1_C) - case MBEDTLS_MD_SHA1: - return MBEDTLS_SSL_HASH_SHA1; -#endif -#if defined(MBEDTLS_SHA256_C) - case MBEDTLS_MD_SHA224: - return MBEDTLS_SSL_HASH_SHA224; - case MBEDTLS_MD_SHA256: - return MBEDTLS_SSL_HASH_SHA256; -#endif -#if defined(MBEDTLS_SHA512_C) && !defined(MBEDTLS_SHA512_NO_SHA384) - case MBEDTLS_MD_SHA384: - return MBEDTLS_SSL_HASH_SHA384; -#endif -#if defined(MBEDTLS_SHA512_C) - case MBEDTLS_MD_SHA512: - return MBEDTLS_SSL_HASH_SHA512; -#endif - default: - return MBEDTLS_SSL_HASH_NONE; + if (ssl->f_export_keys != NULL) { + ssl->f_export_keys(ssl->p_export_keys, + MBEDTLS_SSL_KEY_EXPORT_TLS12_MASTER_SECRET, + master, 48, + randbytes + 32, + randbytes, + tls_prf_get_type(tls_prf)); } -} -#if defined(MBEDTLS_ECP_C) -/* - * Check if a curve proposed by the peer is in our list. - * Return 0 if we're willing to use it, -1 otherwise. - */ -int mbedtls_ssl_check_curve(const mbedtls_ssl_context *ssl, mbedtls_ecp_group_id grp_id) -{ - const mbedtls_ecp_group_id *gid; +#if defined(MBEDTLS_USE_PSA_CRYPTO) + transform->psa_alg = alg; + + if (alg != MBEDTLS_SSL_NULL_CIPHER) { + psa_set_key_usage_flags(&attributes, PSA_KEY_USAGE_ENCRYPT); + psa_set_key_algorithm(&attributes, alg); + psa_set_key_type(&attributes, key_type); + + if ((status = psa_import_key(&attributes, + key1, + PSA_BITS_TO_BYTES(key_bits), + &transform->psa_key_enc)) != PSA_SUCCESS) { + MBEDTLS_SSL_DEBUG_RET(3, "psa_import_key", (int) status); + ret = PSA_TO_MBEDTLS_ERR(status); + MBEDTLS_SSL_DEBUG_RET(1, "psa_import_key", ret); + goto end; + } - if (ssl->conf->curve_list == NULL) { - return -1; - } + psa_set_key_usage_flags(&attributes, PSA_KEY_USAGE_DECRYPT); - for (gid = ssl->conf->curve_list; *gid != MBEDTLS_ECP_DP_NONE; gid++) { - if (*gid == grp_id) { - return 0; + if ((status = psa_import_key(&attributes, + key2, + PSA_BITS_TO_BYTES(key_bits), + &transform->psa_key_dec)) != PSA_SUCCESS) { + ret = PSA_TO_MBEDTLS_ERR(status); + MBEDTLS_SSL_DEBUG_RET(1, "psa_import_key", ret); + goto end; } } - - return -1; -} - -/* - * Same as mbedtls_ssl_check_curve() but takes a TLS ID for the curve. - */ -int mbedtls_ssl_check_curve_tls_id(const mbedtls_ssl_context *ssl, uint16_t tls_id) -{ - const mbedtls_ecp_curve_info *curve_info = - mbedtls_ecp_curve_info_from_tls_id(tls_id); - if (curve_info == NULL) { - return -1; +#else + if ((ret = mbedtls_cipher_setup(&transform->cipher_ctx_enc, + cipher_info)) != 0) { + MBEDTLS_SSL_DEBUG_RET(1, "mbedtls_cipher_setup", ret); + goto end; } - return mbedtls_ssl_check_curve(ssl, curve_info->grp_id); -} -#endif /* MBEDTLS_ECP_C */ - -#if defined(MBEDTLS_KEY_EXCHANGE_WITH_CERT_ENABLED) -/* - * Check if a hash proposed by the peer is in our list. - * Return 0 if we're willing to use it, -1 otherwise. - */ -int mbedtls_ssl_check_sig_hash(const mbedtls_ssl_context *ssl, - mbedtls_md_type_t md) -{ - const int *cur; - if (ssl->conf->sig_hashes == NULL) { - return -1; + if ((ret = mbedtls_cipher_setup(&transform->cipher_ctx_dec, + cipher_info)) != 0) { + MBEDTLS_SSL_DEBUG_RET(1, "mbedtls_cipher_setup", ret); + goto end; } - for (cur = ssl->conf->sig_hashes; *cur != MBEDTLS_MD_NONE; cur++) { - if (*cur == (int) md) { - return 0; - } + if ((ret = mbedtls_cipher_setkey(&transform->cipher_ctx_enc, key1, + (int) mbedtls_cipher_info_get_key_bitlen(cipher_info), + MBEDTLS_ENCRYPT)) != 0) { + MBEDTLS_SSL_DEBUG_RET(1, "mbedtls_cipher_setkey", ret); + goto end; } - return -1; -} -#endif /* MBEDTLS_KEY_EXCHANGE_WITH_CERT_ENABLED */ + if ((ret = mbedtls_cipher_setkey(&transform->cipher_ctx_dec, key2, + (int) mbedtls_cipher_info_get_key_bitlen(cipher_info), + MBEDTLS_DECRYPT)) != 0) { + MBEDTLS_SSL_DEBUG_RET(1, "mbedtls_cipher_setkey", ret); + goto end; + } -#if defined(MBEDTLS_X509_CRT_PARSE_C) -int mbedtls_ssl_check_cert_usage(const mbedtls_x509_crt *cert, - const mbedtls_ssl_ciphersuite_t *ciphersuite, - int cert_endpoint, - uint32_t *flags) -{ - int ret = 0; -#if defined(MBEDTLS_X509_CHECK_KEY_USAGE) - int usage = 0; -#endif -#if defined(MBEDTLS_X509_CHECK_EXTENDED_KEY_USAGE) - const char *ext_oid; - size_t ext_len; -#endif +#if defined(MBEDTLS_CIPHER_MODE_CBC) + if (mbedtls_cipher_info_get_mode(cipher_info) == MBEDTLS_MODE_CBC) { + if ((ret = mbedtls_cipher_set_padding_mode(&transform->cipher_ctx_enc, + MBEDTLS_PADDING_NONE)) != 0) { + MBEDTLS_SSL_DEBUG_RET(1, "mbedtls_cipher_set_padding_mode", ret); + goto end; + } -#if !defined(MBEDTLS_X509_CHECK_KEY_USAGE) && \ - !defined(MBEDTLS_X509_CHECK_EXTENDED_KEY_USAGE) - ((void) cert); - ((void) cert_endpoint); - ((void) flags); -#endif + if ((ret = mbedtls_cipher_set_padding_mode(&transform->cipher_ctx_dec, + MBEDTLS_PADDING_NONE)) != 0) { + MBEDTLS_SSL_DEBUG_RET(1, "mbedtls_cipher_set_padding_mode", ret); + goto end; + } + } +#endif /* MBEDTLS_CIPHER_MODE_CBC */ +#endif /* MBEDTLS_USE_PSA_CRYPTO */ -#if defined(MBEDTLS_X509_CHECK_KEY_USAGE) - if (cert_endpoint == MBEDTLS_SSL_IS_SERVER) { - /* Server part of the key exchange */ - switch (ciphersuite->key_exchange) { - case MBEDTLS_KEY_EXCHANGE_RSA: - case MBEDTLS_KEY_EXCHANGE_RSA_PSK: - usage = MBEDTLS_X509_KU_KEY_ENCIPHERMENT; - break; +#if defined(MBEDTLS_SSL_SOME_SUITES_USE_MAC) + /* For HMAC-based ciphersuites, initialize the HMAC transforms. + For AEAD-based ciphersuites, there is nothing to do here. */ + if (mac_key_len != 0) { +#if defined(MBEDTLS_USE_PSA_CRYPTO) + transform->psa_mac_alg = PSA_ALG_HMAC(mac_alg); - case MBEDTLS_KEY_EXCHANGE_DHE_RSA: - case MBEDTLS_KEY_EXCHANGE_ECDHE_RSA: - case MBEDTLS_KEY_EXCHANGE_ECDHE_ECDSA: - usage = MBEDTLS_X509_KU_DIGITAL_SIGNATURE; - break; + psa_set_key_usage_flags(&attributes, PSA_KEY_USAGE_SIGN_MESSAGE); + psa_set_key_algorithm(&attributes, PSA_ALG_HMAC(mac_alg)); + psa_set_key_type(&attributes, PSA_KEY_TYPE_HMAC); - case MBEDTLS_KEY_EXCHANGE_ECDH_RSA: - case MBEDTLS_KEY_EXCHANGE_ECDH_ECDSA: - usage = MBEDTLS_X509_KU_KEY_AGREEMENT; - break; + if ((status = psa_import_key(&attributes, + mac_enc, mac_key_len, + &transform->psa_mac_enc)) != PSA_SUCCESS) { + ret = PSA_TO_MBEDTLS_ERR(status); + MBEDTLS_SSL_DEBUG_RET(1, "psa_import_mac_key", ret); + goto end; + } - /* Don't use default: we want warnings when adding new values */ - case MBEDTLS_KEY_EXCHANGE_NONE: - case MBEDTLS_KEY_EXCHANGE_PSK: - case MBEDTLS_KEY_EXCHANGE_DHE_PSK: - case MBEDTLS_KEY_EXCHANGE_ECDHE_PSK: - case MBEDTLS_KEY_EXCHANGE_ECJPAKE: - usage = 0; + if ((transform->psa_alg == MBEDTLS_SSL_NULL_CIPHER) || + ((transform->psa_alg == PSA_ALG_CBC_NO_PADDING) +#if defined(MBEDTLS_SSL_SOME_SUITES_USE_CBC_ETM) + && (transform->encrypt_then_mac == MBEDTLS_SSL_ETM_DISABLED) +#endif + )) { + /* mbedtls_ct_hmac() requires the key to be exportable */ + psa_set_key_usage_flags(&attributes, PSA_KEY_USAGE_EXPORT | + PSA_KEY_USAGE_VERIFY_HASH); + } else { + psa_set_key_usage_flags(&attributes, PSA_KEY_USAGE_VERIFY_HASH); } - } else { - /* Client auth: we only implement rsa_sign and mbedtls_ecdsa_sign for now */ - usage = MBEDTLS_X509_KU_DIGITAL_SIGNATURE; - } - if (mbedtls_x509_crt_check_key_usage(cert, usage) != 0) { - *flags |= MBEDTLS_X509_BADCERT_KEY_USAGE; - ret = -1; - } + if ((status = psa_import_key(&attributes, + mac_dec, mac_key_len, + &transform->psa_mac_dec)) != PSA_SUCCESS) { + ret = PSA_TO_MBEDTLS_ERR(status); + MBEDTLS_SSL_DEBUG_RET(1, "psa_import_mac_key", ret); + goto end; + } #else - ((void) ciphersuite); -#endif /* MBEDTLS_X509_CHECK_KEY_USAGE */ - -#if defined(MBEDTLS_X509_CHECK_EXTENDED_KEY_USAGE) - if (cert_endpoint == MBEDTLS_SSL_IS_SERVER) { - ext_oid = MBEDTLS_OID_SERVER_AUTH; - ext_len = MBEDTLS_OID_SIZE(MBEDTLS_OID_SERVER_AUTH); - } else { - ext_oid = MBEDTLS_OID_CLIENT_AUTH; - ext_len = MBEDTLS_OID_SIZE(MBEDTLS_OID_CLIENT_AUTH); + ret = mbedtls_md_hmac_starts(&transform->md_ctx_enc, mac_enc, mac_key_len); + if (ret != 0) { + goto end; + } + ret = mbedtls_md_hmac_starts(&transform->md_ctx_dec, mac_dec, mac_key_len); + if (ret != 0) { + goto end; + } +#endif /* MBEDTLS_USE_PSA_CRYPTO */ } +#endif /* MBEDTLS_SSL_SOME_SUITES_USE_MAC */ - if (mbedtls_x509_crt_check_extended_key_usage(cert, ext_oid, ext_len) != 0) { - *flags |= MBEDTLS_X509_BADCERT_EXT_KEY_USAGE; - ret = -1; - } -#endif /* MBEDTLS_X509_CHECK_EXTENDED_KEY_USAGE */ + ((void) mac_dec); + ((void) mac_enc); +end: + mbedtls_platform_zeroize(keyblk, sizeof(keyblk)); return ret; } -#endif /* MBEDTLS_X509_CRT_PARSE_C */ -int mbedtls_ssl_set_calc_verify_md(mbedtls_ssl_context *ssl, int md) -{ -#if defined(MBEDTLS_SSL_PROTO_TLS1_2) - if (ssl->minor_ver != MBEDTLS_SSL_MINOR_VERSION_3) { - return MBEDTLS_ERR_SSL_INVALID_VERIFY_HASH; +#if defined(MBEDTLS_KEY_EXCHANGE_ECJPAKE_ENABLED) && \ + defined(MBEDTLS_USE_PSA_CRYPTO) +int mbedtls_psa_ecjpake_read_round( + psa_pake_operation_t *pake_ctx, + const unsigned char *buf, + size_t len, mbedtls_ecjpake_rounds_t round) +{ + psa_status_t status; + size_t input_offset = 0; + /* + * At round one repeat the KEY_SHARE, ZK_PUBLIC & ZF_PROOF twice + * At round two perform a single cycle + */ + unsigned int remaining_steps = (round == MBEDTLS_ECJPAKE_ROUND_ONE) ? 2 : 1; + + for (; remaining_steps > 0; remaining_steps--) { + for (psa_pake_step_t step = PSA_PAKE_STEP_KEY_SHARE; + step <= PSA_PAKE_STEP_ZK_PROOF; + ++step) { + /* Length is stored at the first byte */ + size_t length = buf[input_offset]; + input_offset += 1; + + if (input_offset + length > len) { + return MBEDTLS_ERR_SSL_HANDSHAKE_FAILURE; + } + + status = psa_pake_input(pake_ctx, step, + buf + input_offset, length); + if (status != PSA_SUCCESS) { + return PSA_TO_MBEDTLS_ERR(status); + } + + input_offset += length; + } } - switch (md) { -#if defined(MBEDTLS_SSL_PROTO_TLS1) || defined(MBEDTLS_SSL_PROTO_TLS1_1) -#if defined(MBEDTLS_MD5_C) - case MBEDTLS_SSL_HASH_MD5: - return MBEDTLS_ERR_SSL_INVALID_VERIFY_HASH; -#endif -#if defined(MBEDTLS_SHA1_C) - case MBEDTLS_SSL_HASH_SHA1: - ssl->handshake->calc_verify = ssl_calc_verify_tls; - break; -#endif -#endif /* MBEDTLS_SSL_PROTO_TLS1 || MBEDTLS_SSL_PROTO_TLS1_1 */ -#if defined(MBEDTLS_SHA512_C) && !defined(MBEDTLS_SHA512_NO_SHA384) - case MBEDTLS_SSL_HASH_SHA384: - ssl->handshake->calc_verify = ssl_calc_verify_tls_sha384; - break; -#endif -#if defined(MBEDTLS_SHA256_C) - case MBEDTLS_SSL_HASH_SHA256: - ssl->handshake->calc_verify = ssl_calc_verify_tls_sha256; - break; -#endif - default: - return MBEDTLS_ERR_SSL_INVALID_VERIFY_HASH; + if (input_offset != len) { + return MBEDTLS_ERR_SSL_HANDSHAKE_FAILURE; } return 0; -#else /* !MBEDTLS_SSL_PROTO_TLS1_2 */ - (void) ssl; - (void) md; - - return MBEDTLS_ERR_SSL_INVALID_VERIFY_HASH; -#endif /* MBEDTLS_SSL_PROTO_TLS1_2 */ } -#if defined(MBEDTLS_SSL_PROTO_SSL3) || defined(MBEDTLS_SSL_PROTO_TLS1) || \ - defined(MBEDTLS_SSL_PROTO_TLS1_1) -int mbedtls_ssl_get_key_exchange_md_ssl_tls(mbedtls_ssl_context *ssl, - unsigned char *output, - unsigned char *data, size_t data_len) +int mbedtls_psa_ecjpake_write_round( + psa_pake_operation_t *pake_ctx, + unsigned char *buf, + size_t len, size_t *olen, + mbedtls_ecjpake_rounds_t round) { - int ret = 0; - mbedtls_md5_context mbedtls_md5; - mbedtls_sha1_context mbedtls_sha1; - - mbedtls_md5_init(&mbedtls_md5); - mbedtls_sha1_init(&mbedtls_sha1); - + psa_status_t status; + size_t output_offset = 0; + size_t output_len; /* - * digitally-signed struct { - * opaque md5_hash[16]; - * opaque sha_hash[20]; - * }; - * - * md5_hash - * MD5(ClientHello.random + ServerHello.random - * + ServerParams); - * sha_hash - * SHA(ClientHello.random + ServerHello.random - * + ServerParams); + * At round one repeat the KEY_SHARE, ZK_PUBLIC & ZF_PROOF twice + * At round two perform a single cycle */ - if ((ret = mbedtls_md5_starts_ret(&mbedtls_md5)) != 0) { - MBEDTLS_SSL_DEBUG_RET(1, "mbedtls_md5_starts_ret", ret); - goto exit; - } - if ((ret = mbedtls_md5_update_ret(&mbedtls_md5, - ssl->handshake->randbytes, 64)) != 0) { - MBEDTLS_SSL_DEBUG_RET(1, "mbedtls_md5_update_ret", ret); - goto exit; - } - if ((ret = mbedtls_md5_update_ret(&mbedtls_md5, data, data_len)) != 0) { - MBEDTLS_SSL_DEBUG_RET(1, "mbedtls_md5_update_ret", ret); - goto exit; - } - if ((ret = mbedtls_md5_finish_ret(&mbedtls_md5, output)) != 0) { - MBEDTLS_SSL_DEBUG_RET(1, "mbedtls_md5_finish_ret", ret); - goto exit; - } + unsigned int remaining_steps = (round == MBEDTLS_ECJPAKE_ROUND_ONE) ? 2 : 1; - if ((ret = mbedtls_sha1_starts_ret(&mbedtls_sha1)) != 0) { - MBEDTLS_SSL_DEBUG_RET(1, "mbedtls_sha1_starts_ret", ret); - goto exit; - } - if ((ret = mbedtls_sha1_update_ret(&mbedtls_sha1, - ssl->handshake->randbytes, 64)) != 0) { - MBEDTLS_SSL_DEBUG_RET(1, "mbedtls_sha1_update_ret", ret); - goto exit; - } - if ((ret = mbedtls_sha1_update_ret(&mbedtls_sha1, data, - data_len)) != 0) { - MBEDTLS_SSL_DEBUG_RET(1, "mbedtls_sha1_update_ret", ret); - goto exit; - } - if ((ret = mbedtls_sha1_finish_ret(&mbedtls_sha1, - output + 16)) != 0) { - MBEDTLS_SSL_DEBUG_RET(1, "mbedtls_sha1_finish_ret", ret); - goto exit; - } + for (; remaining_steps > 0; remaining_steps--) { + for (psa_pake_step_t step = PSA_PAKE_STEP_KEY_SHARE; + step <= PSA_PAKE_STEP_ZK_PROOF; + ++step) { + /* + * For each step, prepend 1 byte with the length of the data as + * given by psa_pake_output(). + */ + status = psa_pake_output(pake_ctx, step, + buf + output_offset + 1, + len - output_offset - 1, + &output_len); + if (status != PSA_SUCCESS) { + return PSA_TO_MBEDTLS_ERR(status); + } -exit: - mbedtls_md5_free(&mbedtls_md5); - mbedtls_sha1_free(&mbedtls_sha1); + *(buf + output_offset) = (uint8_t) output_len; - if (ret != 0) { - mbedtls_ssl_send_alert_message(ssl, MBEDTLS_SSL_ALERT_LEVEL_FATAL, - MBEDTLS_SSL_ALERT_MSG_INTERNAL_ERROR); + output_offset += output_len + 1; + } } - return ret; + *olen = output_offset; + return 0; } -#endif /* MBEDTLS_SSL_PROTO_SSL3 || MBEDTLS_SSL_PROTO_TLS1 || \ - MBEDTLS_SSL_PROTO_TLS1_1 */ - -#if defined(MBEDTLS_SSL_PROTO_TLS1) || defined(MBEDTLS_SSL_PROTO_TLS1_1) || \ - defined(MBEDTLS_SSL_PROTO_TLS1_2) +#endif //MBEDTLS_KEY_EXCHANGE_ECJPAKE_ENABLED && MBEDTLS_USE_PSA_CRYPTO #if defined(MBEDTLS_USE_PSA_CRYPTO) int mbedtls_ssl_get_key_exchange_md_tls1_2(mbedtls_ssl_context *ssl, @@ -7513,7 +9331,7 @@ int mbedtls_ssl_get_key_exchange_md_tls1_2(mbedtls_ssl_context *ssl, { psa_status_t status; psa_hash_operation_t hash_operation = PSA_HASH_OPERATION_INIT; - psa_algorithm_t hash_alg = mbedtls_psa_translate_md(md_alg); + psa_algorithm_t hash_alg = mbedtls_md_psa_alg_from_type(md_alg); MBEDTLS_SSL_DEBUG_MSG(3, ("Perform PSA-based computation of digest of ServerKeyExchange")); @@ -7554,7 +9372,7 @@ int mbedtls_ssl_get_key_exchange_md_tls1_2(mbedtls_ssl_context *ssl, case PSA_ERROR_INSUFFICIENT_MEMORY: return MBEDTLS_ERR_MD_ALLOC_FAILED; default: - return MBEDTLS_ERR_MD_HW_ACCEL_FAILED; + return MBEDTLS_ERR_PLATFORM_HW_ACCEL_FAILED; } } return 0; @@ -7616,7 +9434,489 @@ int mbedtls_ssl_get_key_exchange_md_tls1_2(mbedtls_ssl_context *ssl, } #endif /* MBEDTLS_USE_PSA_CRYPTO */ -#endif /* MBEDTLS_SSL_PROTO_TLS1 || MBEDTLS_SSL_PROTO_TLS1_1 || \ - MBEDTLS_SSL_PROTO_TLS1_2 */ +#if defined(MBEDTLS_KEY_EXCHANGE_WITH_CERT_ENABLED) + +/* Find the preferred hash for a given signature algorithm. */ +unsigned int mbedtls_ssl_tls12_get_preferred_hash_for_sig_alg( + mbedtls_ssl_context *ssl, + unsigned int sig_alg) +{ + unsigned int i; + uint16_t *received_sig_algs = ssl->handshake->received_sig_algs; + + if (sig_alg == MBEDTLS_SSL_SIG_ANON) { + return MBEDTLS_SSL_HASH_NONE; + } + + for (i = 0; received_sig_algs[i] != MBEDTLS_TLS_SIG_NONE; i++) { + unsigned int hash_alg_received = + MBEDTLS_SSL_TLS12_HASH_ALG_FROM_SIG_AND_HASH_ALG( + received_sig_algs[i]); + unsigned int sig_alg_received = + MBEDTLS_SSL_TLS12_SIG_ALG_FROM_SIG_AND_HASH_ALG( + received_sig_algs[i]); + + mbedtls_md_type_t md_alg = + mbedtls_ssl_md_alg_from_hash((unsigned char) hash_alg_received); + if (md_alg == MBEDTLS_MD_NONE) { + continue; + } + + if (sig_alg == sig_alg_received) { +#if defined(MBEDTLS_USE_PSA_CRYPTO) + if (ssl->handshake->key_cert && ssl->handshake->key_cert->key) { + psa_algorithm_t psa_hash_alg = + mbedtls_md_psa_alg_from_type(md_alg); + + if (sig_alg_received == MBEDTLS_SSL_SIG_ECDSA && + !mbedtls_pk_can_do_ext(ssl->handshake->key_cert->key, + PSA_ALG_ECDSA(psa_hash_alg), + PSA_KEY_USAGE_SIGN_HASH)) { + continue; + } + + if (sig_alg_received == MBEDTLS_SSL_SIG_RSA && + !mbedtls_pk_can_do_ext(ssl->handshake->key_cert->key, + PSA_ALG_RSA_PKCS1V15_SIGN( + psa_hash_alg), + PSA_KEY_USAGE_SIGN_HASH)) { + continue; + } + } +#endif /* MBEDTLS_USE_PSA_CRYPTO */ + + return hash_alg_received; + } + } + + return MBEDTLS_SSL_HASH_NONE; +} + +#endif /* MBEDTLS_KEY_EXCHANGE_WITH_CERT_ENABLED */ + +#endif /* MBEDTLS_SSL_PROTO_TLS1_2 */ + +int mbedtls_ssl_validate_ciphersuite( + const mbedtls_ssl_context *ssl, + const mbedtls_ssl_ciphersuite_t *suite_info, + mbedtls_ssl_protocol_version min_tls_version, + mbedtls_ssl_protocol_version max_tls_version) +{ + (void) ssl; + + if (suite_info == NULL) { + return -1; + } + + if ((suite_info->min_tls_version > max_tls_version) || + (suite_info->max_tls_version < min_tls_version)) { + return -1; + } + +#if defined(MBEDTLS_SSL_PROTO_TLS1_2) && defined(MBEDTLS_SSL_CLI_C) +#if defined(MBEDTLS_KEY_EXCHANGE_ECJPAKE_ENABLED) +#if defined(MBEDTLS_USE_PSA_CRYPTO) + if (suite_info->key_exchange == MBEDTLS_KEY_EXCHANGE_ECJPAKE && + ssl->handshake->psa_pake_ctx_is_ok != 1) +#else + if (suite_info->key_exchange == MBEDTLS_KEY_EXCHANGE_ECJPAKE && + mbedtls_ecjpake_check(&ssl->handshake->ecjpake_ctx) != 0) +#endif /* MBEDTLS_USE_PSA_CRYPTO */ + { + return -1; + } +#endif + + /* Don't suggest PSK-based ciphersuite if no PSK is available. */ +#if defined(MBEDTLS_KEY_EXCHANGE_SOME_PSK_ENABLED) + if (mbedtls_ssl_ciphersuite_uses_psk(suite_info) && + mbedtls_ssl_conf_has_static_psk(ssl->conf) == 0) { + return -1; + } +#endif /* MBEDTLS_KEY_EXCHANGE_SOME_PSK_ENABLED */ +#endif /* MBEDTLS_SSL_PROTO_TLS1_2 */ + + return 0; +} + +#if defined(MBEDTLS_SSL_HANDSHAKE_WITH_CERT_ENABLED) +/* + * Function for writing a signature algorithm extension. + * + * The `extension_data` field of signature algorithm contains a `SignatureSchemeList` + * value (TLS 1.3 RFC8446): + * enum { + * .... + * ecdsa_secp256r1_sha256( 0x0403 ), + * ecdsa_secp384r1_sha384( 0x0503 ), + * ecdsa_secp521r1_sha512( 0x0603 ), + * .... + * } SignatureScheme; + * + * struct { + * SignatureScheme supported_signature_algorithms<2..2^16-2>; + * } SignatureSchemeList; + * + * The `extension_data` field of signature algorithm contains a `SignatureAndHashAlgorithm` + * value (TLS 1.2 RFC5246): + * enum { + * none(0), md5(1), sha1(2), sha224(3), sha256(4), sha384(5), + * sha512(6), (255) + * } HashAlgorithm; + * + * enum { anonymous(0), rsa(1), dsa(2), ecdsa(3), (255) } + * SignatureAlgorithm; + * + * struct { + * HashAlgorithm hash; + * SignatureAlgorithm signature; + * } SignatureAndHashAlgorithm; + * + * SignatureAndHashAlgorithm + * supported_signature_algorithms<2..2^16-2>; + * + * The TLS 1.3 signature algorithm extension was defined to be a compatible + * generalization of the TLS 1.2 signature algorithm extension. + * `SignatureAndHashAlgorithm` field of TLS 1.2 can be represented by + * `SignatureScheme` field of TLS 1.3 + * + */ +int mbedtls_ssl_write_sig_alg_ext(mbedtls_ssl_context *ssl, unsigned char *buf, + const unsigned char *end, size_t *out_len) +{ + unsigned char *p = buf; + unsigned char *supported_sig_alg; /* Start of supported_signature_algorithms */ + size_t supported_sig_alg_len = 0; /* Length of supported_signature_algorithms */ + + *out_len = 0; + + MBEDTLS_SSL_DEBUG_MSG(3, ("adding signature_algorithms extension")); + + /* Check if we have space for header and length field: + * - extension_type (2 bytes) + * - extension_data_length (2 bytes) + * - supported_signature_algorithms_length (2 bytes) + */ + MBEDTLS_SSL_CHK_BUF_PTR(p, end, 6); + p += 6; + + /* + * Write supported_signature_algorithms + */ + supported_sig_alg = p; + const uint16_t *sig_alg = mbedtls_ssl_get_sig_algs(ssl); + if (sig_alg == NULL) { + return MBEDTLS_ERR_SSL_BAD_CONFIG; + } + + for (; *sig_alg != MBEDTLS_TLS1_3_SIG_NONE; sig_alg++) { + MBEDTLS_SSL_DEBUG_MSG(3, ("got signature scheme [%x] %s", + *sig_alg, + mbedtls_ssl_sig_alg_to_str(*sig_alg))); + if (!mbedtls_ssl_sig_alg_is_supported(ssl, *sig_alg)) { + continue; + } + MBEDTLS_SSL_CHK_BUF_PTR(p, end, 2); + MBEDTLS_PUT_UINT16_BE(*sig_alg, p, 0); + p += 2; + MBEDTLS_SSL_DEBUG_MSG(3, ("sent signature scheme [%x] %s", + *sig_alg, + mbedtls_ssl_sig_alg_to_str(*sig_alg))); + } + + /* Length of supported_signature_algorithms */ + supported_sig_alg_len = (size_t) (p - supported_sig_alg); + if (supported_sig_alg_len == 0) { + MBEDTLS_SSL_DEBUG_MSG(1, ("No signature algorithms defined.")); + return MBEDTLS_ERR_SSL_INTERNAL_ERROR; + } + + MBEDTLS_PUT_UINT16_BE(MBEDTLS_TLS_EXT_SIG_ALG, buf, 0); + MBEDTLS_PUT_UINT16_BE(supported_sig_alg_len + 2, buf, 2); + MBEDTLS_PUT_UINT16_BE(supported_sig_alg_len, buf, 4); + + *out_len = (size_t) (p - buf); + +#if defined(MBEDTLS_SSL_PROTO_TLS1_3) + mbedtls_ssl_tls13_set_hs_sent_ext_mask(ssl, MBEDTLS_TLS_EXT_SIG_ALG); +#endif /* MBEDTLS_SSL_PROTO_TLS1_3 */ + + return 0; +} +#endif /* MBEDTLS_SSL_HANDSHAKE_WITH_CERT_ENABLED */ + +#if defined(MBEDTLS_SSL_SERVER_NAME_INDICATION) +/* + * mbedtls_ssl_parse_server_name_ext + * + * Structure of server_name extension: + * + * enum { + * host_name(0), (255) + * } NameType; + * opaque HostName<1..2^16-1>; + * + * struct { + * NameType name_type; + * select (name_type) { + * case host_name: HostName; + * } name; + * } ServerName; + * struct { + * ServerName server_name_list<1..2^16-1> + * } ServerNameList; + */ +MBEDTLS_CHECK_RETURN_CRITICAL +int mbedtls_ssl_parse_server_name_ext(mbedtls_ssl_context *ssl, + const unsigned char *buf, + const unsigned char *end) +{ + int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED; + const unsigned char *p = buf; + size_t server_name_list_len, hostname_len; + const unsigned char *server_name_list_end; + + MBEDTLS_SSL_DEBUG_MSG(3, ("parse ServerName extension")); + + MBEDTLS_SSL_CHK_BUF_READ_PTR(p, end, 2); + server_name_list_len = MBEDTLS_GET_UINT16_BE(p, 0); + p += 2; + + MBEDTLS_SSL_CHK_BUF_READ_PTR(p, end, server_name_list_len); + server_name_list_end = p + server_name_list_len; + while (p < server_name_list_end) { + MBEDTLS_SSL_CHK_BUF_READ_PTR(p, server_name_list_end, 3); + hostname_len = MBEDTLS_GET_UINT16_BE(p, 1); + MBEDTLS_SSL_CHK_BUF_READ_PTR(p, server_name_list_end, + hostname_len + 3); + + if (p[0] == MBEDTLS_TLS_EXT_SERVERNAME_HOSTNAME) { + /* sni_name is intended to be used only during the parsing of the + * ClientHello message (it is reset to NULL before the end of + * the message parsing). Thus it is ok to just point to the + * reception buffer and not make a copy of it. + */ + ssl->handshake->sni_name = p + 3; + ssl->handshake->sni_name_len = hostname_len; + if (ssl->conf->f_sni == NULL) { + return 0; + } + ret = ssl->conf->f_sni(ssl->conf->p_sni, + ssl, p + 3, hostname_len); + if (ret != 0) { + MBEDTLS_SSL_DEBUG_RET(1, "ssl_sni_wrapper", ret); + MBEDTLS_SSL_PEND_FATAL_ALERT(MBEDTLS_SSL_ALERT_MSG_UNRECOGNIZED_NAME, + MBEDTLS_ERR_SSL_UNRECOGNIZED_NAME); + return MBEDTLS_ERR_SSL_UNRECOGNIZED_NAME; + } + return 0; + } + + p += hostname_len + 3; + } + + return 0; +} +#endif /* MBEDTLS_SSL_SERVER_NAME_INDICATION */ + +#if defined(MBEDTLS_SSL_ALPN) +MBEDTLS_CHECK_RETURN_CRITICAL +int mbedtls_ssl_parse_alpn_ext(mbedtls_ssl_context *ssl, + const unsigned char *buf, + const unsigned char *end) +{ + const unsigned char *p = buf; + size_t protocol_name_list_len; + const unsigned char *protocol_name_list; + const unsigned char *protocol_name_list_end; + size_t protocol_name_len; + + /* If ALPN not configured, just ignore the extension */ + if (ssl->conf->alpn_list == NULL) { + return 0; + } + + /* + * RFC7301, section 3.1 + * opaque ProtocolName<1..2^8-1>; + * + * struct { + * ProtocolName protocol_name_list<2..2^16-1> + * } ProtocolNameList; + */ + + /* + * protocol_name_list_len 2 bytes + * protocol_name_len 1 bytes + * protocol_name >=1 byte + */ + MBEDTLS_SSL_CHK_BUF_READ_PTR(p, end, 4); + + protocol_name_list_len = MBEDTLS_GET_UINT16_BE(p, 0); + p += 2; + MBEDTLS_SSL_CHK_BUF_READ_PTR(p, end, protocol_name_list_len); + protocol_name_list = p; + protocol_name_list_end = p + protocol_name_list_len; + + /* Validate peer's list (lengths) */ + while (p < protocol_name_list_end) { + protocol_name_len = *p++; + MBEDTLS_SSL_CHK_BUF_READ_PTR(p, protocol_name_list_end, + protocol_name_len); + if (protocol_name_len == 0) { + MBEDTLS_SSL_PEND_FATAL_ALERT( + MBEDTLS_SSL_ALERT_MSG_ILLEGAL_PARAMETER, + MBEDTLS_ERR_SSL_ILLEGAL_PARAMETER); + return MBEDTLS_ERR_SSL_ILLEGAL_PARAMETER; + } + + p += protocol_name_len; + } + + /* Use our order of preference */ + for (const char **alpn = ssl->conf->alpn_list; *alpn != NULL; alpn++) { + size_t const alpn_len = strlen(*alpn); + p = protocol_name_list; + while (p < protocol_name_list_end) { + protocol_name_len = *p++; + if (protocol_name_len == alpn_len && + memcmp(p, *alpn, alpn_len) == 0) { + ssl->alpn_chosen = *alpn; + return 0; + } + + p += protocol_name_len; + } + } + + /* If we get here, no match was found */ + MBEDTLS_SSL_PEND_FATAL_ALERT( + MBEDTLS_SSL_ALERT_MSG_NO_APPLICATION_PROTOCOL, + MBEDTLS_ERR_SSL_NO_APPLICATION_PROTOCOL); + return MBEDTLS_ERR_SSL_NO_APPLICATION_PROTOCOL; +} + +int mbedtls_ssl_write_alpn_ext(mbedtls_ssl_context *ssl, + unsigned char *buf, + unsigned char *end, + size_t *out_len) +{ + unsigned char *p = buf; + size_t protocol_name_len; + *out_len = 0; + + if (ssl->alpn_chosen == NULL) { + return 0; + } + + protocol_name_len = strlen(ssl->alpn_chosen); + MBEDTLS_SSL_CHK_BUF_PTR(p, end, 7 + protocol_name_len); + + MBEDTLS_SSL_DEBUG_MSG(3, ("server side, adding alpn extension")); + /* + * 0 . 1 ext identifier + * 2 . 3 ext length + * 4 . 5 protocol list length + * 6 . 6 protocol name length + * 7 . 7+n protocol name + */ + MBEDTLS_PUT_UINT16_BE(MBEDTLS_TLS_EXT_ALPN, p, 0); + + *out_len = 7 + protocol_name_len; + + MBEDTLS_PUT_UINT16_BE(protocol_name_len + 3, p, 2); + MBEDTLS_PUT_UINT16_BE(protocol_name_len + 1, p, 4); + /* Note: the length of the chosen protocol has been checked to be less + * than 255 bytes in `mbedtls_ssl_conf_alpn_protocols`. + */ + p[6] = MBEDTLS_BYTE_0(protocol_name_len); + + memcpy(p + 7, ssl->alpn_chosen, protocol_name_len); + +#if defined(MBEDTLS_SSL_PROTO_TLS1_3) + mbedtls_ssl_tls13_set_hs_sent_ext_mask(ssl, MBEDTLS_TLS_EXT_ALPN); +#endif + + return 0; +} +#endif /* MBEDTLS_SSL_ALPN */ + +#if defined(MBEDTLS_SSL_PROTO_TLS1_3) && \ + defined(MBEDTLS_SSL_SESSION_TICKETS) && \ + defined(MBEDTLS_SSL_SERVER_NAME_INDICATION) && \ + defined(MBEDTLS_SSL_CLI_C) +int mbedtls_ssl_session_set_hostname(mbedtls_ssl_session *session, + const char *hostname) +{ + /* Initialize to suppress unnecessary compiler warning */ + size_t hostname_len = 0; + + /* Check if new hostname is valid before + * making any change to current one */ + if (hostname != NULL) { + hostname_len = strlen(hostname); + + if (hostname_len > MBEDTLS_SSL_MAX_HOST_NAME_LEN) { + return MBEDTLS_ERR_SSL_BAD_INPUT_DATA; + } + } + + /* Now it's clear that we will overwrite the old hostname, + * so we can free it safely */ + if (session->hostname != NULL) { + mbedtls_zeroize_and_free(session->hostname, + strlen(session->hostname)); + } + + /* Passing NULL as hostname shall clear the old one */ + if (hostname == NULL) { + session->hostname = NULL; + } else { + session->hostname = mbedtls_calloc(1, hostname_len + 1); + if (session->hostname == NULL) { + return MBEDTLS_ERR_SSL_ALLOC_FAILED; + } + + memcpy(session->hostname, hostname, hostname_len); + } + + return 0; +} +#endif /* MBEDTLS_SSL_PROTO_TLS1_3 && + MBEDTLS_SSL_SESSION_TICKETS && + MBEDTLS_SSL_SERVER_NAME_INDICATION && + MBEDTLS_SSL_CLI_C */ + +#if defined(MBEDTLS_SSL_SRV_C) && defined(MBEDTLS_SSL_EARLY_DATA) && \ + defined(MBEDTLS_SSL_ALPN) +int mbedtls_ssl_session_set_ticket_alpn(mbedtls_ssl_session *session, + const char *alpn) +{ + size_t alpn_len = 0; + + if (alpn != NULL) { + alpn_len = strlen(alpn); + + if (alpn_len > MBEDTLS_SSL_MAX_ALPN_NAME_LEN) { + return MBEDTLS_ERR_SSL_BAD_INPUT_DATA; + } + } + + if (session->ticket_alpn != NULL) { + mbedtls_zeroize_and_free(session->ticket_alpn, + strlen(session->ticket_alpn)); + session->ticket_alpn = NULL; + } + + if (alpn != NULL) { + session->ticket_alpn = mbedtls_calloc(alpn_len + 1, 1); + if (session->ticket_alpn == NULL) { + return MBEDTLS_ERR_SSL_ALLOC_FAILED; + } + memcpy(session->ticket_alpn, alpn, alpn_len); + } + return 0; +} +#endif /* MBEDTLS_SSL_SRV_C && MBEDTLS_SSL_EARLY_DATA && MBEDTLS_SSL_ALPN */ #endif /* MBEDTLS_SSL_TLS_C */ diff --git a/vendor/mbedtls/library/ssl_cli.c b/vendor/mbedtls/library/ssl_tls12_client.c similarity index 65% rename from vendor/mbedtls/library/ssl_cli.c rename to vendor/mbedtls/library/ssl_tls12_client.c index b693d53031..eac6a3aadd 100644 --- a/vendor/mbedtls/library/ssl_cli.c +++ b/vendor/mbedtls/library/ssl_tls12_client.c @@ -1,37 +1,37 @@ /* - * SSLv3/TLSv1 client-side functions + * TLS client-side functions * * Copyright The Mbed TLS Contributors - * SPDX-License-Identifier: Apache-2.0 - * - * Licensed under the Apache License, Version 2.0 (the "License"); you may - * not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT - * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. + * SPDX-License-Identifier: Apache-2.0 OR GPL-2.0-or-later */ #include "common.h" -#if defined(MBEDTLS_SSL_CLI_C) +#if defined(MBEDTLS_SSL_CLI_C) && defined(MBEDTLS_SSL_PROTO_TLS1_2) #include "mbedtls/platform.h" #include "mbedtls/ssl.h" -#include "mbedtls/ssl_internal.h" -#include "mbedtls/debug.h" +#include "ssl_client.h" +#include "ssl_misc.h" +#include "debug_internal.h" #include "mbedtls/error.h" #include "mbedtls/constant_time.h" #if defined(MBEDTLS_USE_PSA_CRYPTO) -#include "mbedtls/psa_util.h" +#include "psa_util_internal.h" #include "psa/crypto.h" +#if defined(MBEDTLS_KEY_EXCHANGE_ECDHE_PSK_ENABLED) +/* Define a local translating function to save code size by not using too many + * arguments in each translating place. */ +static int local_err_translation(psa_status_t status) +{ + return psa_status_to_mbedtls(status, psa_to_ssl_errors, + ARRAY_LENGTH(psa_to_ssl_errors), + psa_generic_status_to_mbedtls); +} +#define PSA_TO_MBEDTLS_ERR(status) local_err_translation(status) +#endif /* MBEDTLS_KEY_EXCHANGE_ECDHE_PSK_ENABLED */ #endif /* MBEDTLS_USE_PSA_CRYPTO */ #include @@ -46,119 +46,6 @@ #include "mbedtls/platform_util.h" #endif -#if defined(MBEDTLS_KEY_EXCHANGE_SOME_PSK_ENABLED) -MBEDTLS_CHECK_RETURN_CRITICAL -static int ssl_conf_has_static_psk(mbedtls_ssl_config const *conf) -{ - if (conf->psk_identity == NULL || - conf->psk_identity_len == 0) { - return 0; - } - - if (conf->psk != NULL && conf->psk_len != 0) { - return 1; - } - -#if defined(MBEDTLS_USE_PSA_CRYPTO) - if (!mbedtls_svc_key_id_is_null(conf->psk_opaque)) { - return 1; - } -#endif /* MBEDTLS_USE_PSA_CRYPTO */ - - return 0; -} - -#if defined(MBEDTLS_USE_PSA_CRYPTO) -MBEDTLS_CHECK_RETURN_CRITICAL -static int ssl_conf_has_static_raw_psk(mbedtls_ssl_config const *conf) -{ - if (conf->psk_identity == NULL || - conf->psk_identity_len == 0) { - return 0; - } - - if (conf->psk != NULL && conf->psk_len != 0) { - return 1; - } - - return 0; -} -#endif /* MBEDTLS_USE_PSA_CRYPTO */ - -#endif /* MBEDTLS_KEY_EXCHANGE_SOME_PSK_ENABLED */ - -#if defined(MBEDTLS_SSL_SERVER_NAME_INDICATION) -MBEDTLS_CHECK_RETURN_CRITICAL -static int ssl_write_hostname_ext(mbedtls_ssl_context *ssl, - unsigned char *buf, - const unsigned char *end, - size_t *olen) -{ - unsigned char *p = buf; - size_t hostname_len; - - *olen = 0; - - if (ssl->hostname == NULL) { - return 0; - } - - MBEDTLS_SSL_DEBUG_MSG(3, - ("client hello, adding server name extension: %s", - ssl->hostname)); - - hostname_len = strlen(ssl->hostname); - - MBEDTLS_SSL_CHK_BUF_PTR(p, end, hostname_len + 9); - - /* - * Sect. 3, RFC 6066 (TLS Extensions Definitions) - * - * In order to provide any of the server names, clients MAY include an - * extension of type "server_name" in the (extended) client hello. The - * "extension_data" field of this extension SHALL contain - * "ServerNameList" where: - * - * struct { - * NameType name_type; - * select (name_type) { - * case host_name: HostName; - * } name; - * } ServerName; - * - * enum { - * host_name(0), (255) - * } NameType; - * - * opaque HostName<1..2^16-1>; - * - * struct { - * ServerName server_name_list<1..2^16-1> - * } ServerNameList; - * - */ - MBEDTLS_PUT_UINT16_BE(MBEDTLS_TLS_EXT_SERVERNAME, p, 0); - p += 2; - - MBEDTLS_PUT_UINT16_BE(hostname_len + 5, p, 0); - p += 2; - - MBEDTLS_PUT_UINT16_BE(hostname_len + 3, p, 0); - p += 2; - - *p++ = MBEDTLS_BYTE_0(MBEDTLS_TLS_EXT_SERVERNAME_HOSTNAME); - - MBEDTLS_PUT_UINT16_BE(hostname_len, p, 0); - p += 2; - - memcpy(p, ssl->hostname, hostname_len); - - *olen = hostname_len + 9; - - return 0; -} -#endif /* MBEDTLS_SSL_SERVER_NAME_INDICATION */ - #if defined(MBEDTLS_SSL_RENEGOTIATION) MBEDTLS_CHECK_RETURN_CRITICAL static int ssl_write_renegotiation_ext(mbedtls_ssl_context *ssl, @@ -200,179 +87,9 @@ static int ssl_write_renegotiation_ext(mbedtls_ssl_context *ssl, } #endif /* MBEDTLS_SSL_RENEGOTIATION */ -/* - * Only if we handle at least one key exchange that needs signatures. - */ -#if defined(MBEDTLS_SSL_PROTO_TLS1_2) && \ - defined(MBEDTLS_KEY_EXCHANGE_WITH_CERT_ENABLED) -MBEDTLS_CHECK_RETURN_CRITICAL -static int ssl_write_signature_algorithms_ext(mbedtls_ssl_context *ssl, - unsigned char *buf, - const unsigned char *end, - size_t *olen) -{ - unsigned char *p = buf; - size_t sig_alg_len = 0; - const int *md; - -#if defined(MBEDTLS_RSA_C) || defined(MBEDTLS_ECDSA_C) - unsigned char *sig_alg_list = buf + 6; -#endif - - *olen = 0; - - if (ssl->conf->max_minor_ver != MBEDTLS_SSL_MINOR_VERSION_3) { - return 0; - } - - MBEDTLS_SSL_DEBUG_MSG(3, - ("client hello, adding signature_algorithms extension")); - - if (ssl->conf->sig_hashes == NULL) { - return MBEDTLS_ERR_SSL_BAD_CONFIG; - } - - for (md = ssl->conf->sig_hashes; *md != MBEDTLS_MD_NONE; md++) { -#if defined(MBEDTLS_ECDSA_C) - sig_alg_len += 2; -#endif -#if defined(MBEDTLS_RSA_C) - sig_alg_len += 2; -#endif - if (sig_alg_len > MBEDTLS_SSL_MAX_SIG_HASH_ALG_LIST_LEN) { - MBEDTLS_SSL_DEBUG_MSG(3, - ("length in bytes of sig-hash-alg extension too big")); - return MBEDTLS_ERR_SSL_BAD_CONFIG; - } - } - - /* Empty signature algorithms list, this is a configuration error. */ - if (sig_alg_len == 0) { - return MBEDTLS_ERR_SSL_BAD_CONFIG; - } - - MBEDTLS_SSL_CHK_BUF_PTR(p, end, sig_alg_len + 6); - - /* - * Prepare signature_algorithms extension (TLS 1.2) - */ - sig_alg_len = 0; - - for (md = ssl->conf->sig_hashes; *md != MBEDTLS_MD_NONE; md++) { -#if defined(MBEDTLS_ECDSA_C) - sig_alg_list[sig_alg_len++] = mbedtls_ssl_hash_from_md_alg(*md); - sig_alg_list[sig_alg_len++] = MBEDTLS_SSL_SIG_ECDSA; -#endif -#if defined(MBEDTLS_RSA_C) - sig_alg_list[sig_alg_len++] = mbedtls_ssl_hash_from_md_alg(*md); - sig_alg_list[sig_alg_len++] = MBEDTLS_SSL_SIG_RSA; -#endif - } - - /* - * enum { - * none(0), md5(1), sha1(2), sha224(3), sha256(4), sha384(5), - * sha512(6), (255) - * } HashAlgorithm; - * - * enum { anonymous(0), rsa(1), dsa(2), ecdsa(3), (255) } - * SignatureAlgorithm; - * - * struct { - * HashAlgorithm hash; - * SignatureAlgorithm signature; - * } SignatureAndHashAlgorithm; - * - * SignatureAndHashAlgorithm - * supported_signature_algorithms<2..2^16-2>; - */ - MBEDTLS_PUT_UINT16_BE(MBEDTLS_TLS_EXT_SIG_ALG, p, 0); - p += 2; - - MBEDTLS_PUT_UINT16_BE(sig_alg_len + 2, p, 0); - p += 2; - - MBEDTLS_PUT_UINT16_BE(sig_alg_len, p, 0); - p += 2; - - *olen = 6 + sig_alg_len; - - return 0; -} -#endif /* MBEDTLS_SSL_PROTO_TLS1_2 && - MBEDTLS_KEY_EXCHANGE_WITH_CERT_ENABLED */ - -#if defined(MBEDTLS_ECDH_C) || defined(MBEDTLS_ECDSA_C) || \ +#if defined(MBEDTLS_KEY_EXCHANGE_SOME_ECDH_OR_ECDHE_1_2_ENABLED) || \ + defined(MBEDTLS_KEY_EXCHANGE_ECDSA_CERT_REQ_ALLOWED_ENABLED) || \ defined(MBEDTLS_KEY_EXCHANGE_ECJPAKE_ENABLED) -MBEDTLS_CHECK_RETURN_CRITICAL -static int ssl_write_supported_elliptic_curves_ext(mbedtls_ssl_context *ssl, - unsigned char *buf, - const unsigned char *end, - size_t *olen) -{ - unsigned char *p = buf; - unsigned char *elliptic_curve_list = p + 6; - size_t elliptic_curve_len = 0; - const mbedtls_ecp_curve_info *info; - const mbedtls_ecp_group_id *grp_id; - - *olen = 0; - - MBEDTLS_SSL_DEBUG_MSG(3, - ("client hello, adding supported_elliptic_curves extension")); - - if (ssl->conf->curve_list == NULL) { - return MBEDTLS_ERR_SSL_BAD_CONFIG; - } - - for (grp_id = ssl->conf->curve_list; - *grp_id != MBEDTLS_ECP_DP_NONE; - grp_id++) { - info = mbedtls_ecp_curve_info_from_grp_id(*grp_id); - if (info == NULL) { - MBEDTLS_SSL_DEBUG_MSG(1, - ("invalid curve in ssl configuration")); - return MBEDTLS_ERR_SSL_BAD_CONFIG; - } - elliptic_curve_len += 2; - - if (elliptic_curve_len > MBEDTLS_SSL_MAX_CURVE_LIST_LEN) { - MBEDTLS_SSL_DEBUG_MSG(3, - ("malformed supported_elliptic_curves extension in config")); - return MBEDTLS_ERR_SSL_BAD_CONFIG; - } - } - - /* Empty elliptic curve list, this is a configuration error. */ - if (elliptic_curve_len == 0) { - return MBEDTLS_ERR_SSL_BAD_CONFIG; - } - - MBEDTLS_SSL_CHK_BUF_PTR(p, end, 6 + elliptic_curve_len); - - elliptic_curve_len = 0; - - for (grp_id = ssl->conf->curve_list; - *grp_id != MBEDTLS_ECP_DP_NONE; - grp_id++) { - info = mbedtls_ecp_curve_info_from_grp_id(*grp_id); - elliptic_curve_list[elliptic_curve_len++] = MBEDTLS_BYTE_1(info->tls_id); - elliptic_curve_list[elliptic_curve_len++] = MBEDTLS_BYTE_0(info->tls_id); - } - - MBEDTLS_PUT_UINT16_BE(MBEDTLS_TLS_EXT_SUPPORTED_ELLIPTIC_CURVES, p, 0); - p += 2; - - MBEDTLS_PUT_UINT16_BE(elliptic_curve_len + 2, p, 0); - p += 2; - - MBEDTLS_PUT_UINT16_BE(elliptic_curve_len, p, 0); - p += 2; - - *olen = 6 + elliptic_curve_len; - - return 0; -} MBEDTLS_CHECK_RETURN_CRITICAL static int ssl_write_supported_point_formats_ext(mbedtls_ssl_context *ssl, @@ -402,7 +119,8 @@ static int ssl_write_supported_point_formats_ext(mbedtls_ssl_context *ssl, return 0; } -#endif /* MBEDTLS_ECDH_C || MBEDTLS_ECDSA_C || +#endif /* MBEDTLS_KEY_EXCHANGE_SOME_ECDH_OR_ECDHE_1_2_ENABLED || + MBEDTLS_KEY_EXCHANGE_ECDSA_CERT_REQ_ALLOWED_ENABLED || MBEDTLS_KEY_EXCHANGE_ECJPAKE_ENABLED */ #if defined(MBEDTLS_KEY_EXCHANGE_ECJPAKE_ENABLED) @@ -414,14 +132,20 @@ static int ssl_write_ecjpake_kkpp_ext(mbedtls_ssl_context *ssl, { int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED; unsigned char *p = buf; - size_t kkpp_len; + size_t kkpp_len = 0; *olen = 0; /* Skip costly extension if we can't use EC J-PAKE anyway */ +#if defined(MBEDTLS_USE_PSA_CRYPTO) + if (ssl->handshake->psa_pake_ctx_is_ok != 1) { + return 0; + } +#else if (mbedtls_ecjpake_check(&ssl->handshake->ecjpake_ctx) != 0) { return 0; } +#endif /* MBEDTLS_USE_PSA_CRYPTO */ MBEDTLS_SSL_DEBUG_MSG(3, ("client hello, adding ecjpake_kkpp extension")); @@ -440,6 +164,17 @@ static int ssl_write_ecjpake_kkpp_ext(mbedtls_ssl_context *ssl, ssl->handshake->ecjpake_cache_len == 0) { MBEDTLS_SSL_DEBUG_MSG(3, ("generating new ecjpake parameters")); +#if defined(MBEDTLS_USE_PSA_CRYPTO) + ret = mbedtls_psa_ecjpake_write_round(&ssl->handshake->psa_pake_ctx, + p + 2, end - p - 2, &kkpp_len, + MBEDTLS_ECJPAKE_ROUND_ONE); + if (ret != 0) { + psa_destroy_key(ssl->handshake->psa_pake_password); + psa_pake_abort(&ssl->handshake->psa_pake_ctx); + MBEDTLS_SSL_DEBUG_RET(1, "psa_pake_output", ret); + return ret; + } +#else ret = mbedtls_ecjpake_write_round_one(&ssl->handshake->ecjpake_ctx, p + 2, end - p - 2, &kkpp_len, ssl->conf->f_rng, ssl->conf->p_rng); @@ -448,6 +183,7 @@ static int ssl_write_ecjpake_kkpp_ext(mbedtls_ssl_context *ssl, "mbedtls_ecjpake_write_round_one", ret); return ret; } +#endif /* MBEDTLS_USE_PSA_CRYPTO */ ssl->handshake->ecjpake_cache = mbedtls_calloc(1, kkpp_len); if (ssl->handshake->ecjpake_cache == NULL) { @@ -486,9 +222,6 @@ static int ssl_write_cid_ext(mbedtls_ssl_context *ssl, size_t ext_len; /* - * Quoting draft-ietf-tls-dtls-connection-id-05 - * https://tools.ietf.org/html/draft-ietf-tls-dtls-connection-id-05 - * * struct { * opaque cid<0..2^8-1>; * } ConnectionId; @@ -555,38 +288,6 @@ static int ssl_write_max_fragment_length_ext(mbedtls_ssl_context *ssl, } #endif /* MBEDTLS_SSL_MAX_FRAGMENT_LENGTH */ -#if defined(MBEDTLS_SSL_TRUNCATED_HMAC) -MBEDTLS_CHECK_RETURN_CRITICAL -static int ssl_write_truncated_hmac_ext(mbedtls_ssl_context *ssl, - unsigned char *buf, - const unsigned char *end, - size_t *olen) -{ - unsigned char *p = buf; - - *olen = 0; - - if (ssl->conf->trunc_hmac == MBEDTLS_SSL_TRUNC_HMAC_DISABLED) { - return 0; - } - - MBEDTLS_SSL_DEBUG_MSG(3, - ("client hello, adding truncated_hmac extension")); - - MBEDTLS_SSL_CHK_BUF_PTR(p, end, 4); - - MBEDTLS_PUT_UINT16_BE(MBEDTLS_TLS_EXT_TRUNCATED_HMAC, p, 0); - p += 2; - - *p++ = 0x00; - *p++ = 0x00; - - *olen = 4; - - return 0; -} -#endif /* MBEDTLS_SSL_TRUNCATED_HMAC */ - #if defined(MBEDTLS_SSL_ENCRYPT_THEN_MAC) MBEDTLS_CHECK_RETURN_CRITICAL static int ssl_write_encrypt_then_mac_ext(mbedtls_ssl_context *ssl, @@ -598,8 +299,7 @@ static int ssl_write_encrypt_then_mac_ext(mbedtls_ssl_context *ssl, *olen = 0; - if (ssl->conf->encrypt_then_mac == MBEDTLS_SSL_ETM_DISABLED || - ssl->conf->max_minor_ver == MBEDTLS_SSL_MINOR_VERSION_0) { + if (ssl->conf->encrypt_then_mac == MBEDTLS_SSL_ETM_DISABLED) { return 0; } @@ -631,8 +331,7 @@ static int ssl_write_extended_ms_ext(mbedtls_ssl_context *ssl, *olen = 0; - if (ssl->conf->extended_ms == MBEDTLS_SSL_EXTENDED_MS_DISABLED || - ssl->conf->max_minor_ver == MBEDTLS_SSL_MINOR_VERSION_0) { + if (ssl->conf->extended_ms == MBEDTLS_SSL_EXTENDED_MS_DISABLED) { return 0; } @@ -698,67 +397,6 @@ static int ssl_write_session_ticket_ext(mbedtls_ssl_context *ssl, } #endif /* MBEDTLS_SSL_SESSION_TICKETS */ -#if defined(MBEDTLS_SSL_ALPN) -MBEDTLS_CHECK_RETURN_CRITICAL -static int ssl_write_alpn_ext(mbedtls_ssl_context *ssl, - unsigned char *buf, - const unsigned char *end, - size_t *olen) -{ - unsigned char *p = buf; - size_t alpnlen = 0; - const char **cur; - - *olen = 0; - - if (ssl->conf->alpn_list == NULL) { - return 0; - } - - MBEDTLS_SSL_DEBUG_MSG(3, ("client hello, adding alpn extension")); - - for (cur = ssl->conf->alpn_list; *cur != NULL; cur++) { - alpnlen += strlen(*cur) + 1; - } - - MBEDTLS_SSL_CHK_BUF_PTR(p, end, 6 + alpnlen); - - MBEDTLS_PUT_UINT16_BE(MBEDTLS_TLS_EXT_ALPN, p, 0); - p += 2; - - /* - * opaque ProtocolName<1..2^8-1>; - * - * struct { - * ProtocolName protocol_name_list<2..2^16-1> - * } ProtocolNameList; - */ - - /* Skip writing extension and list length for now */ - p += 4; - - for (cur = ssl->conf->alpn_list; *cur != NULL; cur++) { - /* - * mbedtls_ssl_conf_set_alpn_protocols() checked that the length of - * protocol names is less than 255. - */ - *p = (unsigned char) strlen(*cur); - memcpy(p + 1, *cur, *p); - p += 1 + *p; - } - - *olen = p - buf; - - /* List length = olen - 2 (ext_type) - 2 (ext_len) - 2 (list_len) */ - MBEDTLS_PUT_UINT16_BE(*olen - 6, buf, 4); - - /* Extension length = olen - 2 (ext_type) - 2 (ext_len) */ - MBEDTLS_PUT_UINT16_BE(*olen - 4, buf, 2); - - return 0; -} -#endif /* MBEDTLS_SSL_ALPN */ - #if defined(MBEDTLS_SSL_DTLS_SRTP) MBEDTLS_CHECK_RETURN_CRITICAL static int ssl_write_use_srtp_ext(mbedtls_ssl_context *ssl, @@ -871,567 +509,105 @@ static int ssl_write_use_srtp_ext(mbedtls_ssl_context *ssl, } #endif /* MBEDTLS_SSL_DTLS_SRTP */ -/* - * Generate random bytes for ClientHello - */ -MBEDTLS_CHECK_RETURN_CRITICAL -static int ssl_generate_random(mbedtls_ssl_context *ssl) +int mbedtls_ssl_tls12_write_client_hello_exts(mbedtls_ssl_context *ssl, + unsigned char *buf, + const unsigned char *end, + int uses_ec, + size_t *out_len) { int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED; - unsigned char *p = ssl->handshake->randbytes; -#if defined(MBEDTLS_HAVE_TIME) - mbedtls_time_t t; -#endif - - /* - * When responding to a verify request, MUST reuse random (RFC 6347 4.2.1) - */ -#if defined(MBEDTLS_SSL_PROTO_DTLS) - if (ssl->conf->transport == MBEDTLS_SSL_TRANSPORT_DATAGRAM && - ssl->handshake->verify_cookie != NULL) { - return 0; - } -#endif - -#if defined(MBEDTLS_HAVE_TIME) - t = mbedtls_time(NULL); - MBEDTLS_PUT_UINT32_BE(t, p, 0); - p += 4; - - MBEDTLS_SSL_DEBUG_MSG(3, ("client hello, current time: %" MBEDTLS_PRINTF_LONGLONG, - (long long) t)); -#else - if ((ret = ssl->conf->f_rng(ssl->conf->p_rng, p, 4)) != 0) { - return ret; - } - - p += 4; -#endif /* MBEDTLS_HAVE_TIME */ - - if ((ret = ssl->conf->f_rng(ssl->conf->p_rng, p, 28)) != 0) { - return ret; - } - - return 0; -} + unsigned char *p = buf; + size_t ext_len = 0; -/** - * \brief Validate cipher suite against config in SSL context. - * - * \param suite_info cipher suite to validate - * \param ssl SSL context - * \param min_minor_ver Minimal minor version to accept a cipher suite - * \param max_minor_ver Maximal minor version to accept a cipher suite - * - * \return 0 if valid, else 1 - */ -MBEDTLS_CHECK_RETURN_CRITICAL -static int ssl_validate_ciphersuite( - const mbedtls_ssl_ciphersuite_t *suite_info, - const mbedtls_ssl_context *ssl, - int min_minor_ver, int max_minor_ver) -{ (void) ssl; - if (suite_info == NULL) { - return 1; - } - - if (suite_info->min_minor_ver > max_minor_ver || - suite_info->max_minor_ver < min_minor_ver) { - return 1; - } - -#if defined(MBEDTLS_SSL_PROTO_DTLS) - if (ssl->conf->transport == MBEDTLS_SSL_TRANSPORT_DATAGRAM && - (suite_info->flags & MBEDTLS_CIPHERSUITE_NODTLS)) { - return 1; - } -#endif - -#if defined(MBEDTLS_ARC4_C) - if (ssl->conf->arc4_disabled == MBEDTLS_SSL_ARC4_DISABLED && - suite_info->cipher == MBEDTLS_CIPHER_ARC4_128) { - return 1; - } -#endif - -#if defined(MBEDTLS_KEY_EXCHANGE_ECJPAKE_ENABLED) - if (suite_info->key_exchange == MBEDTLS_KEY_EXCHANGE_ECJPAKE && - mbedtls_ecjpake_check(&ssl->handshake->ecjpake_ctx) != 0) { - return 1; - } -#endif - - /* Don't suggest PSK-based ciphersuite if no PSK is available. */ -#if defined(MBEDTLS_KEY_EXCHANGE_SOME_PSK_ENABLED) - if (mbedtls_ssl_ciphersuite_uses_psk(suite_info) && - ssl_conf_has_static_psk(ssl->conf) == 0) { - return 1; - } -#endif /* MBEDTLS_KEY_EXCHANGE_SOME_PSK_ENABLED */ - - return 0; -} - -MBEDTLS_CHECK_RETURN_CRITICAL -static int ssl_write_client_hello(mbedtls_ssl_context *ssl) -{ - int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED; - size_t i, n, olen, ext_len = 0; - - unsigned char *buf; - unsigned char *p, *q; - const unsigned char *end; - - unsigned char offer_compress; - const int *ciphersuites; - const mbedtls_ssl_ciphersuite_t *ciphersuite_info; -#if defined(MBEDTLS_ECDH_C) || defined(MBEDTLS_ECDSA_C) || \ - defined(MBEDTLS_KEY_EXCHANGE_ECJPAKE_ENABLED) - int uses_ec = 0; -#endif - - MBEDTLS_SSL_DEBUG_MSG(2, ("=> write client hello")); - - if (ssl->conf->f_rng == NULL) { - MBEDTLS_SSL_DEBUG_MSG(1, ("no RNG provided")); - return MBEDTLS_ERR_SSL_NO_RNG; - } - - int renegotiating = 0; -#if defined(MBEDTLS_SSL_RENEGOTIATION) - if (ssl->renego_status != MBEDTLS_SSL_INITIAL_HANDSHAKE) { - renegotiating = 1; - } -#endif - if (!renegotiating) { - ssl->major_ver = ssl->conf->min_major_ver; - ssl->minor_ver = ssl->conf->min_minor_ver; - } - - if (ssl->conf->max_major_ver == 0) { - MBEDTLS_SSL_DEBUG_MSG(1, - ( - "configured max major version is invalid, consider using mbedtls_ssl_config_defaults()")); - return MBEDTLS_ERR_SSL_BAD_INPUT_DATA; - } - - buf = ssl->out_msg; - end = buf + MBEDTLS_SSL_OUT_CONTENT_LEN; - - /* - * Check if there's enough space for the first part of the ClientHello - * consisting of the 38 bytes described below, the session identifier (at - * most 32 bytes) and its length (1 byte). - * - * Use static upper bounds instead of the actual values - * to allow the compiler to optimize this away. - */ - MBEDTLS_SSL_CHK_BUF_PTR(buf, end, 38 + 1 + 32); - - /* - * The 38 first bytes of the ClientHello: - * 0 . 0 handshake type (written later) - * 1 . 3 handshake length (written later) - * 4 . 5 highest version supported - * 6 . 9 current UNIX time - * 10 . 37 random bytes - * - * The current UNIX time (4 bytes) and following 28 random bytes are written - * by ssl_generate_random() into ssl->handshake->randbytes buffer and then - * copied from there into the output buffer. - */ - - p = buf + 4; - mbedtls_ssl_write_version(ssl->conf->max_major_ver, - ssl->conf->max_minor_ver, - ssl->conf->transport, p); - p += 2; - - MBEDTLS_SSL_DEBUG_MSG(3, ("client hello, max version: [%d:%d]", - buf[4], buf[5])); - - if ((ret = ssl_generate_random(ssl)) != 0) { - MBEDTLS_SSL_DEBUG_RET(1, "ssl_generate_random", ret); - return ret; - } - - memcpy(p, ssl->handshake->randbytes, 32); - MBEDTLS_SSL_DEBUG_BUF(3, "client hello, random bytes", p, 32); - p += 32; - - /* - * 38 . 38 session id length - * 39 . 39+n session id - * 39+n . 39+n DTLS only: cookie length (1 byte) - * 40+n . .. DTLS only: cookie - * .. . .. ciphersuitelist length (2 bytes) - * .. . .. ciphersuitelist - * .. . .. compression methods length (1 byte) - * .. . .. compression methods - * .. . .. extensions length (2 bytes) - * .. . .. extensions - */ - n = ssl->session_negotiate->id_len; - - if (n < 16 || n > 32 || -#if defined(MBEDTLS_SSL_RENEGOTIATION) - ssl->renego_status != MBEDTLS_SSL_INITIAL_HANDSHAKE || -#endif - ssl->handshake->resume == 0) { - n = 0; - } - -#if defined(MBEDTLS_SSL_SESSION_TICKETS) - /* - * RFC 5077 section 3.4: "When presenting a ticket, the client MAY - * generate and include a Session ID in the TLS ClientHello." - */ - if (!renegotiating) { - if (ssl->session_negotiate->ticket != NULL && - ssl->session_negotiate->ticket_len != 0) { - ret = ssl->conf->f_rng(ssl->conf->p_rng, - ssl->session_negotiate->id, 32); - - if (ret != 0) { - return ret; - } - - ssl->session_negotiate->id_len = n = 32; - } - } -#endif /* MBEDTLS_SSL_SESSION_TICKETS */ - - /* - * The first check of the output buffer size above ( - * MBEDTLS_SSL_CHK_BUF_PTR( buf, end, 38 + 1 + 32 );) - * has checked that there is enough space in the output buffer for the - * session identifier length byte and the session identifier (n <= 32). - */ - *p++ = (unsigned char) n; - - for (i = 0; i < n; i++) { - *p++ = ssl->session_negotiate->id[i]; - } - - MBEDTLS_SSL_DEBUG_MSG(3, ("client hello, session id len.: %" MBEDTLS_PRINTF_SIZET, n)); - MBEDTLS_SSL_DEBUG_BUF(3, "client hello, session id", buf + 39, n); - - /* - * With 'n' being the length of the session identifier - * - * 39+n . 39+n DTLS only: cookie length (1 byte) - * 40+n . .. DTLS only: cookie - * .. . .. ciphersuitelist length (2 bytes) - * .. . .. ciphersuitelist - * .. . .. compression methods length (1 byte) - * .. . .. compression methods - * .. . .. extensions length (2 bytes) - * .. . .. extensions - */ - - /* - * DTLS cookie - */ -#if defined(MBEDTLS_SSL_PROTO_DTLS) - if (ssl->conf->transport == MBEDTLS_SSL_TRANSPORT_DATAGRAM) { - MBEDTLS_SSL_CHK_BUF_PTR(p, end, 1); - - if (ssl->handshake->verify_cookie == NULL) { - MBEDTLS_SSL_DEBUG_MSG(3, ("no verify cookie to send")); - *p++ = 0; - } else { - MBEDTLS_SSL_DEBUG_BUF(3, "client hello, cookie", - ssl->handshake->verify_cookie, - ssl->handshake->verify_cookie_len); + (void) end; + (void) uses_ec; + (void) ret; + (void) ext_len; - *p++ = ssl->handshake->verify_cookie_len; - - MBEDTLS_SSL_CHK_BUF_PTR(p, end, - ssl->handshake->verify_cookie_len); - memcpy(p, ssl->handshake->verify_cookie, - ssl->handshake->verify_cookie_len); - p += ssl->handshake->verify_cookie_len; - } - } -#endif - - /* - * Ciphersuite list - */ - ciphersuites = ssl->conf->ciphersuite_list[ssl->minor_ver]; - - /* Skip writing ciphersuite length for now */ - n = 0; - q = p; - - MBEDTLS_SSL_CHK_BUF_PTR(p, end, 2); - p += 2; - - for (i = 0; ciphersuites[i] != 0; i++) { - ciphersuite_info = mbedtls_ssl_ciphersuite_from_id(ciphersuites[i]); - - if (ssl_validate_ciphersuite(ciphersuite_info, ssl, - ssl->conf->min_minor_ver, - ssl->conf->max_minor_ver) != 0) { - continue; - } - - MBEDTLS_SSL_DEBUG_MSG(3, ("client hello, add ciphersuite: %#04x (%s)", - (unsigned int) ciphersuites[i], ciphersuite_info->name)); - -#if defined(MBEDTLS_ECDH_C) || defined(MBEDTLS_ECDSA_C) || \ - defined(MBEDTLS_KEY_EXCHANGE_ECJPAKE_ENABLED) - uses_ec |= mbedtls_ssl_ciphersuite_uses_ec(ciphersuite_info); -#endif - - MBEDTLS_SSL_CHK_BUF_PTR(p, end, 2); - - n++; - MBEDTLS_PUT_UINT16_BE(ciphersuites[i], p, 0); - p += 2; - } - - MBEDTLS_SSL_DEBUG_MSG(3, - ("client hello, got %" MBEDTLS_PRINTF_SIZET - " ciphersuites (excluding SCSVs)", n)); - - /* - * Add TLS_EMPTY_RENEGOTIATION_INFO_SCSV - */ - if (!renegotiating) { - MBEDTLS_SSL_DEBUG_MSG(3, ("adding EMPTY_RENEGOTIATION_INFO_SCSV")); - MBEDTLS_SSL_CHK_BUF_PTR(p, end, 2); - MBEDTLS_PUT_UINT16_BE(MBEDTLS_SSL_EMPTY_RENEGOTIATION_INFO, p, 0); - p += 2; - n++; - } - - /* Some versions of OpenSSL don't handle it correctly if not at end */ -#if defined(MBEDTLS_SSL_FALLBACK_SCSV) - if (ssl->conf->fallback == MBEDTLS_SSL_IS_FALLBACK) { - MBEDTLS_SSL_DEBUG_MSG(3, ("adding FALLBACK_SCSV")); - - MBEDTLS_SSL_CHK_BUF_PTR(p, end, 2); - MBEDTLS_PUT_UINT16_BE(MBEDTLS_SSL_FALLBACK_SCSV_VALUE, p, 0); - p += 2; - n++; - } -#endif - - *q++ = (unsigned char) (n >> 7); - *q++ = (unsigned char) (n << 1); - -#if defined(MBEDTLS_ZLIB_SUPPORT) - offer_compress = 1; -#else - offer_compress = 0; -#endif - - /* - * We don't support compression with DTLS right now: if many records come - * in the same datagram, uncompressing one could overwrite the next one. - * We don't want to add complexity for handling that case unless there is - * an actual need for it. - */ -#if defined(MBEDTLS_SSL_PROTO_DTLS) - if (ssl->conf->transport == MBEDTLS_SSL_TRANSPORT_DATAGRAM) { - offer_compress = 0; - } -#endif - - if (offer_compress) { - MBEDTLS_SSL_DEBUG_MSG(3, ("client hello, compress len.: %d", 2)); - MBEDTLS_SSL_DEBUG_MSG(3, ("client hello, compress alg.: %d %d", - MBEDTLS_SSL_COMPRESS_DEFLATE, - MBEDTLS_SSL_COMPRESS_NULL)); - - MBEDTLS_SSL_CHK_BUF_PTR(p, end, 3); - *p++ = 2; - *p++ = MBEDTLS_SSL_COMPRESS_DEFLATE; - *p++ = MBEDTLS_SSL_COMPRESS_NULL; - } else { - MBEDTLS_SSL_DEBUG_MSG(3, ("client hello, compress len.: %d", 1)); - MBEDTLS_SSL_DEBUG_MSG(3, ("client hello, compress alg.: %d", - MBEDTLS_SSL_COMPRESS_NULL)); - - MBEDTLS_SSL_CHK_BUF_PTR(p, end, 2); - *p++ = 1; - *p++ = MBEDTLS_SSL_COMPRESS_NULL; - } - - /* First write extensions, then the total length */ - - MBEDTLS_SSL_CHK_BUF_PTR(p, end, 2); - -#if defined(MBEDTLS_SSL_SERVER_NAME_INDICATION) - if ((ret = ssl_write_hostname_ext(ssl, p + 2 + ext_len, - end, &olen)) != 0) { - MBEDTLS_SSL_DEBUG_RET(1, "ssl_write_hostname_ext", ret); - return ret; - } - ext_len += olen; -#endif + *out_len = 0; /* Note that TLS_EMPTY_RENEGOTIATION_INFO_SCSV is always added * even if MBEDTLS_SSL_RENEGOTIATION is not defined. */ #if defined(MBEDTLS_SSL_RENEGOTIATION) - if ((ret = ssl_write_renegotiation_ext(ssl, p + 2 + ext_len, - end, &olen)) != 0) { + if ((ret = ssl_write_renegotiation_ext(ssl, p, end, &ext_len)) != 0) { MBEDTLS_SSL_DEBUG_RET(1, "ssl_write_renegotiation_ext", ret); return ret; } - ext_len += olen; + p += ext_len; #endif -#if defined(MBEDTLS_SSL_PROTO_TLS1_2) && \ - defined(MBEDTLS_KEY_EXCHANGE_WITH_CERT_ENABLED) - if ((ret = ssl_write_signature_algorithms_ext(ssl, p + 2 + ext_len, - end, &olen)) != 0) { - MBEDTLS_SSL_DEBUG_RET(1, "ssl_write_signature_algorithms_ext", ret); - return ret; - } - ext_len += olen; -#endif - -#if defined(MBEDTLS_ECDH_C) || defined(MBEDTLS_ECDSA_C) || \ +#if defined(MBEDTLS_KEY_EXCHANGE_SOME_ECDH_OR_ECDHE_1_2_ENABLED) || \ + defined(MBEDTLS_KEY_EXCHANGE_ECDSA_CERT_REQ_ALLOWED_ENABLED) || \ defined(MBEDTLS_KEY_EXCHANGE_ECJPAKE_ENABLED) if (uses_ec) { - if ((ret = ssl_write_supported_elliptic_curves_ext(ssl, p + 2 + ext_len, - end, &olen)) != 0) { - MBEDTLS_SSL_DEBUG_RET(1, "ssl_write_supported_elliptic_curves_ext", ret); - return ret; - } - ext_len += olen; - - if ((ret = ssl_write_supported_point_formats_ext(ssl, p + 2 + ext_len, - end, &olen)) != 0) { + if ((ret = ssl_write_supported_point_formats_ext(ssl, p, end, + &ext_len)) != 0) { MBEDTLS_SSL_DEBUG_RET(1, "ssl_write_supported_point_formats_ext", ret); return ret; } - ext_len += olen; + p += ext_len; } #endif #if defined(MBEDTLS_KEY_EXCHANGE_ECJPAKE_ENABLED) - if ((ret = ssl_write_ecjpake_kkpp_ext(ssl, p + 2 + ext_len, - end, &olen)) != 0) { + if ((ret = ssl_write_ecjpake_kkpp_ext(ssl, p, end, &ext_len)) != 0) { MBEDTLS_SSL_DEBUG_RET(1, "ssl_write_ecjpake_kkpp_ext", ret); return ret; } - ext_len += olen; + p += ext_len; #endif #if defined(MBEDTLS_SSL_DTLS_CONNECTION_ID) - if ((ret = ssl_write_cid_ext(ssl, p + 2 + ext_len, end, &olen)) != 0) { + if ((ret = ssl_write_cid_ext(ssl, p, end, &ext_len)) != 0) { MBEDTLS_SSL_DEBUG_RET(1, "ssl_write_cid_ext", ret); return ret; } - ext_len += olen; + p += ext_len; #endif /* MBEDTLS_SSL_DTLS_CONNECTION_ID */ #if defined(MBEDTLS_SSL_MAX_FRAGMENT_LENGTH) - if ((ret = ssl_write_max_fragment_length_ext(ssl, p + 2 + ext_len, - end, &olen)) != 0) { + if ((ret = ssl_write_max_fragment_length_ext(ssl, p, end, + &ext_len)) != 0) { MBEDTLS_SSL_DEBUG_RET(1, "ssl_write_max_fragment_length_ext", ret); return ret; } - ext_len += olen; -#endif - -#if defined(MBEDTLS_SSL_TRUNCATED_HMAC) - if ((ret = ssl_write_truncated_hmac_ext(ssl, p + 2 + ext_len, - end, &olen)) != 0) { - MBEDTLS_SSL_DEBUG_RET(1, "ssl_write_truncated_hmac_ext", ret); - return ret; - } - ext_len += olen; + p += ext_len; #endif #if defined(MBEDTLS_SSL_ENCRYPT_THEN_MAC) - if ((ret = ssl_write_encrypt_then_mac_ext(ssl, p + 2 + ext_len, - end, &olen)) != 0) { + if ((ret = ssl_write_encrypt_then_mac_ext(ssl, p, end, &ext_len)) != 0) { MBEDTLS_SSL_DEBUG_RET(1, "ssl_write_encrypt_then_mac_ext", ret); return ret; } - ext_len += olen; + p += ext_len; #endif #if defined(MBEDTLS_SSL_EXTENDED_MASTER_SECRET) - if ((ret = ssl_write_extended_ms_ext(ssl, p + 2 + ext_len, - end, &olen)) != 0) { + if ((ret = ssl_write_extended_ms_ext(ssl, p, end, &ext_len)) != 0) { MBEDTLS_SSL_DEBUG_RET(1, "ssl_write_extended_ms_ext", ret); return ret; } - ext_len += olen; -#endif - -#if defined(MBEDTLS_SSL_ALPN) - if ((ret = ssl_write_alpn_ext(ssl, p + 2 + ext_len, - end, &olen)) != 0) { - MBEDTLS_SSL_DEBUG_RET(1, "ssl_write_alpn_ext", ret); - return ret; - } - ext_len += olen; + p += ext_len; #endif #if defined(MBEDTLS_SSL_DTLS_SRTP) - if ((ret = ssl_write_use_srtp_ext(ssl, p + 2 + ext_len, - end, &olen)) != 0) { + if ((ret = ssl_write_use_srtp_ext(ssl, p, end, &ext_len)) != 0) { MBEDTLS_SSL_DEBUG_RET(1, "ssl_write_use_srtp_ext", ret); return ret; } - ext_len += olen; + p += ext_len; #endif #if defined(MBEDTLS_SSL_SESSION_TICKETS) - if ((ret = ssl_write_session_ticket_ext(ssl, p + 2 + ext_len, - end, &olen)) != 0) { + if ((ret = ssl_write_session_ticket_ext(ssl, p, end, &ext_len)) != 0) { MBEDTLS_SSL_DEBUG_RET(1, "ssl_write_session_ticket_ext", ret); return ret; } - ext_len += olen; + p += ext_len; #endif - /* olen unused if all extensions are disabled */ - ((void) olen); - - MBEDTLS_SSL_DEBUG_MSG(3, ("client hello, total extension length: %" MBEDTLS_PRINTF_SIZET, - ext_len)); - - if (ext_len > 0) { - /* No need to check for space here, because the extension - * writing functions already took care of that. */ - MBEDTLS_PUT_UINT16_BE(ext_len, p, 0); - p += 2 + ext_len; - } - - ssl->out_msglen = p - buf; - ssl->out_msgtype = MBEDTLS_SSL_MSG_HANDSHAKE; - ssl->out_msg[0] = MBEDTLS_SSL_HS_CLIENT_HELLO; - - ssl->state++; - -#if defined(MBEDTLS_SSL_PROTO_DTLS) - if (ssl->conf->transport == MBEDTLS_SSL_TRANSPORT_DATAGRAM) { - mbedtls_ssl_send_flight_completed(ssl); - } -#endif - - if ((ret = mbedtls_ssl_write_handshake_msg(ssl)) != 0) { - MBEDTLS_SSL_DEBUG_RET(1, "mbedtls_ssl_write_handshake_msg", ret); - return ret; - } - -#if defined(MBEDTLS_SSL_PROTO_DTLS) - if (ssl->conf->transport == MBEDTLS_SSL_TRANSPORT_DATAGRAM && - (ret = mbedtls_ssl_flight_transmit(ssl)) != 0) { - MBEDTLS_SSL_DEBUG_RET(1, "mbedtls_ssl_flight_transmit", ret); - return ret; - } -#endif /* MBEDTLS_SSL_PROTO_DTLS */ - - MBEDTLS_SSL_DEBUG_MSG(2, ("<= write client hello")); + *out_len = (size_t) (p - buf); return 0; } @@ -1455,7 +631,7 @@ static int ssl_parse_renegotiation_info(mbedtls_ssl_context *ssl, ssl, MBEDTLS_SSL_ALERT_LEVEL_FATAL, MBEDTLS_SSL_ALERT_MSG_HANDSHAKE_FAILURE); - return MBEDTLS_ERR_SSL_BAD_HS_SERVER_HELLO; + return MBEDTLS_ERR_SSL_HANDSHAKE_FAILURE; } } else #endif /* MBEDTLS_SSL_RENEGOTIATION */ @@ -1467,7 +643,7 @@ static int ssl_parse_renegotiation_info(mbedtls_ssl_context *ssl, ssl, MBEDTLS_SSL_ALERT_LEVEL_FATAL, MBEDTLS_SSL_ALERT_MSG_HANDSHAKE_FAILURE); - return MBEDTLS_ERR_SSL_BAD_HS_SERVER_HELLO; + return MBEDTLS_ERR_SSL_HANDSHAKE_FAILURE; } ssl->secure_renegotiation = MBEDTLS_SSL_SECURE_RENEGOTIATION; @@ -1495,38 +671,13 @@ static int ssl_parse_max_fragment_length_ext(mbedtls_ssl_context *ssl, ssl, MBEDTLS_SSL_ALERT_LEVEL_FATAL, MBEDTLS_SSL_ALERT_MSG_ILLEGAL_PARAMETER); - return MBEDTLS_ERR_SSL_BAD_HS_SERVER_HELLO; + return MBEDTLS_ERR_SSL_ILLEGAL_PARAMETER; } return 0; } #endif /* MBEDTLS_SSL_MAX_FRAGMENT_LENGTH */ -#if defined(MBEDTLS_SSL_TRUNCATED_HMAC) -MBEDTLS_CHECK_RETURN_CRITICAL -static int ssl_parse_truncated_hmac_ext(mbedtls_ssl_context *ssl, - const unsigned char *buf, - size_t len) -{ - if (ssl->conf->trunc_hmac == MBEDTLS_SSL_TRUNC_HMAC_DISABLED || - len != 0) { - MBEDTLS_SSL_DEBUG_MSG(1, - ("non-matching truncated HMAC extension")); - mbedtls_ssl_send_alert_message( - ssl, - MBEDTLS_SSL_ALERT_LEVEL_FATAL, - MBEDTLS_SSL_ALERT_MSG_HANDSHAKE_FAILURE); - return MBEDTLS_ERR_SSL_BAD_HS_SERVER_HELLO; - } - - ((void) buf); - - ssl->session_negotiate->trunc_hmac = MBEDTLS_SSL_TRUNC_HMAC_ENABLED; - - return 0; -} -#endif /* MBEDTLS_SSL_TRUNCATED_HMAC */ - #if defined(MBEDTLS_SSL_DTLS_CONNECTION_ID) MBEDTLS_CHECK_RETURN_CRITICAL static int ssl_parse_cid_ext(mbedtls_ssl_context *ssl, @@ -1542,14 +693,14 @@ static int ssl_parse_cid_ext(mbedtls_ssl_context *ssl, MBEDTLS_SSL_DEBUG_MSG(1, ("CID extension unexpected")); mbedtls_ssl_send_alert_message(ssl, MBEDTLS_SSL_ALERT_LEVEL_FATAL, MBEDTLS_SSL_ALERT_MSG_UNSUPPORTED_EXT); - return MBEDTLS_ERR_SSL_BAD_HS_SERVER_HELLO; + return MBEDTLS_ERR_SSL_UNSUPPORTED_EXTENSION; } if (len == 0) { MBEDTLS_SSL_DEBUG_MSG(1, ("CID extension invalid")); mbedtls_ssl_send_alert_message(ssl, MBEDTLS_SSL_ALERT_LEVEL_FATAL, - MBEDTLS_SSL_ALERT_MSG_HANDSHAKE_FAILURE); - return MBEDTLS_ERR_SSL_BAD_HS_SERVER_HELLO; + MBEDTLS_SSL_ALERT_MSG_DECODE_ERROR); + return MBEDTLS_ERR_SSL_DECODE_ERROR; } peer_cid_len = *buf++; @@ -1558,15 +709,15 @@ static int ssl_parse_cid_ext(mbedtls_ssl_context *ssl, if (peer_cid_len > MBEDTLS_SSL_CID_OUT_LEN_MAX) { MBEDTLS_SSL_DEBUG_MSG(1, ("CID extension invalid")); mbedtls_ssl_send_alert_message(ssl, MBEDTLS_SSL_ALERT_LEVEL_FATAL, - MBEDTLS_SSL_ALERT_MSG_HANDSHAKE_FAILURE); - return MBEDTLS_ERR_SSL_BAD_HS_SERVER_HELLO; + MBEDTLS_SSL_ALERT_MSG_ILLEGAL_PARAMETER); + return MBEDTLS_ERR_SSL_ILLEGAL_PARAMETER; } if (len != peer_cid_len) { MBEDTLS_SSL_DEBUG_MSG(1, ("CID extension invalid")); mbedtls_ssl_send_alert_message(ssl, MBEDTLS_SSL_ALERT_LEVEL_FATAL, - MBEDTLS_SSL_ALERT_MSG_ILLEGAL_PARAMETER); - return MBEDTLS_ERR_SSL_BAD_HS_SERVER_HELLO; + MBEDTLS_SSL_ALERT_MSG_DECODE_ERROR); + return MBEDTLS_ERR_SSL_DECODE_ERROR; } ssl->handshake->cid_in_use = MBEDTLS_SSL_CID_ENABLED; @@ -1587,7 +738,6 @@ static int ssl_parse_encrypt_then_mac_ext(mbedtls_ssl_context *ssl, size_t len) { if (ssl->conf->encrypt_then_mac == MBEDTLS_SSL_ETM_DISABLED || - ssl->minor_ver == MBEDTLS_SSL_MINOR_VERSION_0 || len != 0) { MBEDTLS_SSL_DEBUG_MSG(1, ("non-matching encrypt-then-MAC extension")); @@ -1595,7 +745,7 @@ static int ssl_parse_encrypt_then_mac_ext(mbedtls_ssl_context *ssl, ssl, MBEDTLS_SSL_ALERT_LEVEL_FATAL, MBEDTLS_SSL_ALERT_MSG_UNSUPPORTED_EXT); - return MBEDTLS_ERR_SSL_BAD_HS_SERVER_HELLO; + return MBEDTLS_ERR_SSL_UNSUPPORTED_EXTENSION; } ((void) buf); @@ -1613,7 +763,6 @@ static int ssl_parse_extended_ms_ext(mbedtls_ssl_context *ssl, size_t len) { if (ssl->conf->extended_ms == MBEDTLS_SSL_EXTENDED_MS_DISABLED || - ssl->minor_ver == MBEDTLS_SSL_MINOR_VERSION_0 || len != 0) { MBEDTLS_SSL_DEBUG_MSG(1, ("non-matching extended master secret extension")); @@ -1621,7 +770,7 @@ static int ssl_parse_extended_ms_ext(mbedtls_ssl_context *ssl, ssl, MBEDTLS_SSL_ALERT_LEVEL_FATAL, MBEDTLS_SSL_ALERT_MSG_UNSUPPORTED_EXT); - return MBEDTLS_ERR_SSL_BAD_HS_SERVER_HELLO; + return MBEDTLS_ERR_SSL_UNSUPPORTED_EXTENSION; } ((void) buf); @@ -1646,7 +795,7 @@ static int ssl_parse_session_ticket_ext(mbedtls_ssl_context *ssl, ssl, MBEDTLS_SSL_ALERT_LEVEL_FATAL, MBEDTLS_SSL_ALERT_MSG_UNSUPPORTED_EXT); - return MBEDTLS_ERR_SSL_BAD_HS_SERVER_HELLO; + return MBEDTLS_ERR_SSL_UNSUPPORTED_EXTENSION; } ((void) buf); @@ -1657,7 +806,8 @@ static int ssl_parse_session_ticket_ext(mbedtls_ssl_context *ssl, } #endif /* MBEDTLS_SSL_SESSION_TICKETS */ -#if defined(MBEDTLS_ECDH_C) || defined(MBEDTLS_ECDSA_C) || \ +#if defined(MBEDTLS_KEY_EXCHANGE_SOME_ECDH_OR_ECDHE_1_2_ENABLED) || \ + defined(MBEDTLS_KEY_EXCHANGE_ECDSA_CERT_REQ_ALLOWED_ENABLED) || \ defined(MBEDTLS_KEY_EXCHANGE_ECJPAKE_ENABLED) MBEDTLS_CHECK_RETURN_CRITICAL static int ssl_parse_supported_point_formats_ext(mbedtls_ssl_context *ssl, @@ -1671,20 +821,23 @@ static int ssl_parse_supported_point_formats_ext(mbedtls_ssl_context *ssl, MBEDTLS_SSL_DEBUG_MSG(1, ("bad server hello message")); mbedtls_ssl_send_alert_message(ssl, MBEDTLS_SSL_ALERT_LEVEL_FATAL, MBEDTLS_SSL_ALERT_MSG_DECODE_ERROR); - return MBEDTLS_ERR_SSL_BAD_HS_SERVER_HELLO; + return MBEDTLS_ERR_SSL_DECODE_ERROR; } list_size = buf[0]; p = buf + 1; while (list_size > 0) { if (p[0] == MBEDTLS_ECP_PF_UNCOMPRESSED || - p[0] == MBEDTLS_ECP_PF_COMPRESSED) { -#if defined(MBEDTLS_ECDH_C) || defined(MBEDTLS_ECDSA_C) - ssl->handshake->ecdh_ctx.point_format = p[0]; -#endif -#if defined(MBEDTLS_KEY_EXCHANGE_ECJPAKE_ENABLED) - ssl->handshake->ecjpake_ctx.point_format = p[0]; -#endif + p[0] == MBEDTLS_ECP_PF_COMPRESSED) { +#if !defined(MBEDTLS_USE_PSA_CRYPTO) && \ + defined(MBEDTLS_KEY_EXCHANGE_SOME_ECDH_OR_ECDHE_1_2_ENABLED) + ssl->handshake->ecdh_ctx.point_format = p[0]; +#endif /* !MBEDTLS_USE_PSA_CRYPTO && MBEDTLS_KEY_EXCHANGE_SOME_ECDH_OR_ECDHE_1_2_ENABLED */ +#if !defined(MBEDTLS_USE_PSA_CRYPTO) && \ + defined(MBEDTLS_KEY_EXCHANGE_ECJPAKE_ENABLED) + mbedtls_ecjpake_set_point_format(&ssl->handshake->ecjpake_ctx, + p[0]); +#endif /* !MBEDTLS_USE_PSA_CRYPTO && MBEDTLS_KEY_EXCHANGE_ECJPAKE_ENABLED */ MBEDTLS_SSL_DEBUG_MSG(4, ("point format selected: %d", p[0])); return 0; } @@ -1696,9 +849,10 @@ static int ssl_parse_supported_point_formats_ext(mbedtls_ssl_context *ssl, MBEDTLS_SSL_DEBUG_MSG(1, ("no point format in common")); mbedtls_ssl_send_alert_message(ssl, MBEDTLS_SSL_ALERT_LEVEL_FATAL, MBEDTLS_SSL_ALERT_MSG_HANDSHAKE_FAILURE); - return MBEDTLS_ERR_SSL_BAD_HS_SERVER_HELLO; + return MBEDTLS_ERR_SSL_HANDSHAKE_FAILURE; } -#endif /* MBEDTLS_ECDH_C || MBEDTLS_ECDSA_C || +#endif /* MBEDTLS_KEY_EXCHANGE_SOME_ECDH_OR_ECDHE_1_2_ENABLED || + MBEDTLS_KEY_EXCHANGE_ECDSA_CERT_REQ_ALLOWED_ENABLED || MBEDTLS_KEY_EXCHANGE_ECJPAKE_ENABLED */ #if defined(MBEDTLS_KEY_EXCHANGE_ECJPAKE_ENABLED) @@ -1720,6 +874,23 @@ static int ssl_parse_ecjpake_kkpp(mbedtls_ssl_context *ssl, ssl->handshake->ecjpake_cache = NULL; ssl->handshake->ecjpake_cache_len = 0; +#if defined(MBEDTLS_USE_PSA_CRYPTO) + if ((ret = mbedtls_psa_ecjpake_read_round( + &ssl->handshake->psa_pake_ctx, buf, len, + MBEDTLS_ECJPAKE_ROUND_ONE)) != 0) { + psa_destroy_key(ssl->handshake->psa_pake_password); + psa_pake_abort(&ssl->handshake->psa_pake_ctx); + + MBEDTLS_SSL_DEBUG_RET(1, "psa_pake_input round one", ret); + mbedtls_ssl_send_alert_message( + ssl, + MBEDTLS_SSL_ALERT_LEVEL_FATAL, + MBEDTLS_SSL_ALERT_MSG_HANDSHAKE_FAILURE); + return ret; + } + + return 0; +#else if ((ret = mbedtls_ecjpake_read_round_one(&ssl->handshake->ecjpake_ctx, buf, len)) != 0) { MBEDTLS_SSL_DEBUG_RET(1, "mbedtls_ecjpake_read_round_one", ret); @@ -1731,6 +902,7 @@ static int ssl_parse_ecjpake_kkpp(mbedtls_ssl_context *ssl, } return 0; +#endif /* MBEDTLS_USE_PSA_CRYPTO */ } #endif /* MBEDTLS_KEY_EXCHANGE_ECJPAKE_ENABLED */ @@ -1749,7 +921,7 @@ static int ssl_parse_alpn_ext(mbedtls_ssl_context *ssl, ssl, MBEDTLS_SSL_ALERT_LEVEL_FATAL, MBEDTLS_SSL_ALERT_MSG_UNSUPPORTED_EXT); - return MBEDTLS_ERR_SSL_BAD_HS_SERVER_HELLO; + return MBEDTLS_ERR_SSL_UNSUPPORTED_EXTENSION; } /* @@ -1766,21 +938,21 @@ static int ssl_parse_alpn_ext(mbedtls_ssl_context *ssl, if (len < 4) { mbedtls_ssl_send_alert_message(ssl, MBEDTLS_SSL_ALERT_LEVEL_FATAL, MBEDTLS_SSL_ALERT_MSG_DECODE_ERROR); - return MBEDTLS_ERR_SSL_BAD_HS_SERVER_HELLO; + return MBEDTLS_ERR_SSL_DECODE_ERROR; } - list_len = (buf[0] << 8) | buf[1]; + list_len = MBEDTLS_GET_UINT16_BE(buf, 0); if (list_len != len - 2) { mbedtls_ssl_send_alert_message(ssl, MBEDTLS_SSL_ALERT_LEVEL_FATAL, MBEDTLS_SSL_ALERT_MSG_DECODE_ERROR); - return MBEDTLS_ERR_SSL_BAD_HS_SERVER_HELLO; + return MBEDTLS_ERR_SSL_DECODE_ERROR; } name_len = buf[2]; if (name_len != list_len - 1) { mbedtls_ssl_send_alert_message(ssl, MBEDTLS_SSL_ALERT_LEVEL_FATAL, MBEDTLS_SSL_ALERT_MSG_DECODE_ERROR); - return MBEDTLS_ERR_SSL_BAD_HS_SERVER_HELLO; + return MBEDTLS_ERR_SSL_DECODE_ERROR; } /* Check that the server chosen protocol was in our list and save it */ @@ -1795,7 +967,7 @@ static int ssl_parse_alpn_ext(mbedtls_ssl_context *ssl, MBEDTLS_SSL_DEBUG_MSG(1, ("ALPN extension: no matching protocol")); mbedtls_ssl_send_alert_message(ssl, MBEDTLS_SSL_ALERT_LEVEL_FATAL, MBEDTLS_SSL_ALERT_MSG_HANDSHAKE_FAILURE); - return MBEDTLS_ERR_SSL_BAD_HS_SERVER_HELLO; + return MBEDTLS_ERR_SSL_HANDSHAKE_FAILURE; } #endif /* MBEDTLS_SSL_ALPN */ @@ -1838,7 +1010,7 @@ static int ssl_parse_use_srtp_ext(mbedtls_ssl_context *ssl, * and optional srtp_mki */ if ((len < 5) || (len != (buf[4] + 5u))) { - return MBEDTLS_ERR_SSL_BAD_HS_SERVER_HELLO; + return MBEDTLS_ERR_SSL_DECODE_ERROR; } /* @@ -1850,7 +1022,7 @@ static int ssl_parse_use_srtp_ext(mbedtls_ssl_context *ssl, * one protection profile in server Hello */ if ((buf[0] != 0) || (buf[1] != 2)) { - return MBEDTLS_ERR_SSL_BAD_HS_SERVER_HELLO; + return MBEDTLS_ERR_SSL_DECODE_ERROR; } server_protection_profile_value = (buf[2] << 8) | buf[3]; @@ -1881,7 +1053,7 @@ static int ssl_parse_use_srtp_ext(mbedtls_ssl_context *ssl, if (ssl->dtls_srtp_info.chosen_dtls_srtp_profile == MBEDTLS_TLS_SRTP_UNSET) { mbedtls_ssl_send_alert_message(ssl, MBEDTLS_SSL_ALERT_LEVEL_FATAL, MBEDTLS_SSL_ALERT_MSG_HANDSHAKE_FAILURE); - return MBEDTLS_ERR_SSL_BAD_HS_SERVER_HELLO; + return MBEDTLS_ERR_SSL_HANDSHAKE_FAILURE; } /* If server does not use mki in its reply, make sure the client won't keep @@ -1900,7 +1072,7 @@ static int ssl_parse_use_srtp_ext(mbedtls_ssl_context *ssl, (memcmp(ssl->dtls_srtp_info.mki_value, &buf[5], mki_len)))) { mbedtls_ssl_send_alert_message(ssl, MBEDTLS_SSL_ALERT_LEVEL_FATAL, MBEDTLS_SSL_ALERT_MSG_ILLEGAL_PARAMETER); - return MBEDTLS_ERR_SSL_BAD_HS_SERVER_HELLO; + return MBEDTLS_ERR_SSL_ILLEGAL_PARAMETER; } #if defined(MBEDTLS_DEBUG_C) if (len > 5) { @@ -1919,9 +1091,15 @@ static int ssl_parse_use_srtp_ext(mbedtls_ssl_context *ssl, MBEDTLS_CHECK_RETURN_CRITICAL static int ssl_parse_hello_verify_request(mbedtls_ssl_context *ssl) { + int ret = MBEDTLS_ERR_SSL_FEATURE_UNAVAILABLE; const unsigned char *p = ssl->in_msg + mbedtls_ssl_hs_hdr_len(ssl); - int major_ver, minor_ver; - unsigned char cookie_len; + uint16_t dtls_legacy_version; + +#if !defined(MBEDTLS_SSL_PROTO_TLS1_3) + uint8_t cookie_len; +#else + uint16_t cookie_len; +#endif MBEDTLS_SSL_DEBUG_MSG(2, ("=> parse hello verify request")); @@ -1934,7 +1112,7 @@ static int ssl_parse_hello_verify_request(mbedtls_ssl_context *ssl) ("incoming HelloVerifyRequest message is too short")); mbedtls_ssl_send_alert_message(ssl, MBEDTLS_SSL_ALERT_LEVEL_FATAL, MBEDTLS_SSL_ALERT_MSG_DECODE_ERROR); - return MBEDTLS_ERR_SSL_BAD_HS_SERVER_HELLO; + return MBEDTLS_ERR_SSL_DECODE_ERROR; } /* @@ -1944,23 +1122,21 @@ static int ssl_parse_hello_verify_request(mbedtls_ssl_context *ssl) * } HelloVerifyRequest; */ MBEDTLS_SSL_DEBUG_BUF(3, "server version", p, 2); - mbedtls_ssl_read_version(&major_ver, &minor_ver, ssl->conf->transport, p); + dtls_legacy_version = MBEDTLS_GET_UINT16_BE(p, 0); p += 2; /* - * Since the RFC is not clear on this point, accept DTLS 1.0 (TLS 1.1) - * even is lower than our min version. + * Since the RFC is not clear on this point, accept DTLS 1.0 (0xfeff) + * The DTLS 1.3 (current draft) renames ProtocolVersion server_version to + * legacy_version and locks the value of legacy_version to 0xfefd (DTLS 1.2) */ - if (major_ver < MBEDTLS_SSL_MAJOR_VERSION_3 || - minor_ver < MBEDTLS_SSL_MINOR_VERSION_2 || - major_ver > ssl->conf->max_major_ver || - minor_ver > ssl->conf->max_minor_ver) { + if (dtls_legacy_version != 0xfefd && dtls_legacy_version != 0xfeff) { MBEDTLS_SSL_DEBUG_MSG(1, ("bad server version")); mbedtls_ssl_send_alert_message(ssl, MBEDTLS_SSL_ALERT_LEVEL_FATAL, MBEDTLS_SSL_ALERT_MSG_PROTOCOL_VERSION); - return MBEDTLS_ERR_SSL_BAD_HS_PROTOCOL_VERSION; + return MBEDTLS_ERR_SSL_BAD_PROTOCOL_VERSION; } cookie_len = *p++; @@ -1969,24 +1145,28 @@ static int ssl_parse_hello_verify_request(mbedtls_ssl_context *ssl) ("cookie length does not match incoming message size")); mbedtls_ssl_send_alert_message(ssl, MBEDTLS_SSL_ALERT_LEVEL_FATAL, MBEDTLS_SSL_ALERT_MSG_DECODE_ERROR); - return MBEDTLS_ERR_SSL_BAD_HS_SERVER_HELLO; + return MBEDTLS_ERR_SSL_DECODE_ERROR; } MBEDTLS_SSL_DEBUG_BUF(3, "cookie", p, cookie_len); - mbedtls_free(ssl->handshake->verify_cookie); + mbedtls_free(ssl->handshake->cookie); - ssl->handshake->verify_cookie = mbedtls_calloc(1, cookie_len); - if (ssl->handshake->verify_cookie == NULL) { + ssl->handshake->cookie = mbedtls_calloc(1, cookie_len); + if (ssl->handshake->cookie == NULL) { MBEDTLS_SSL_DEBUG_MSG(1, ("alloc failed (%d bytes)", cookie_len)); return MBEDTLS_ERR_SSL_ALLOC_FAILED; } - memcpy(ssl->handshake->verify_cookie, p, cookie_len); - ssl->handshake->verify_cookie_len = cookie_len; + memcpy(ssl->handshake->cookie, p, cookie_len); + ssl->handshake->cookie_len = cookie_len; /* Start over at ClientHello */ ssl->state = MBEDTLS_SSL_CLIENT_HELLO; - mbedtls_ssl_reset_checksum(ssl); + ret = mbedtls_ssl_reset_checksum(ssl); + if (0 != ret) { + MBEDTLS_SSL_DEBUG_RET(1, ("mbedtls_ssl_reset_checksum"), ret); + return ret; + } mbedtls_ssl_recv_flight_completed(ssl); @@ -1996,33 +1176,6 @@ static int ssl_parse_hello_verify_request(mbedtls_ssl_context *ssl) } #endif /* MBEDTLS_SSL_PROTO_DTLS */ -static int is_compression_bad(mbedtls_ssl_context *ssl, unsigned char comp) -{ - int bad_comp = 0; - - /* Suppress warnings in some configurations */ - (void) ssl; -#if defined(MBEDTLS_ZLIB_SUPPORT) - /* See comments in ssl_write_client_hello() */ -#if defined(MBEDTLS_SSL_PROTO_DTLS) - if (ssl->conf->transport == MBEDTLS_SSL_TRANSPORT_DATAGRAM && - comp != MBEDTLS_SSL_COMPRESS_NULL) { - bad_comp = 1; - } -#endif - - if (comp != MBEDTLS_SSL_COMPRESS_NULL && - comp != MBEDTLS_SSL_COMPRESS_DEFLATE) { - bad_comp = 1; - } -#else /* MBEDTLS_ZLIB_SUPPORT */ - if (comp != MBEDTLS_SSL_COMPRESS_NULL) { - bad_comp = 1; - } -#endif /* MBEDTLS_ZLIB_SUPPORT */ - return bad_comp; -} - MBEDTLS_CHECK_RETURN_CRITICAL static int ssl_parse_server_hello(mbedtls_ssl_context *ssl) { @@ -2083,9 +1236,9 @@ static int ssl_parse_server_hello(mbedtls_ssl_context *ssl) return ssl_parse_hello_verify_request(ssl); } else { /* We made it through the verification process */ - mbedtls_free(ssl->handshake->verify_cookie); - ssl->handshake->verify_cookie = NULL; - ssl->handshake->verify_cookie_len = 0; + mbedtls_free(ssl->handshake->cookie); + ssl->handshake->cookie = NULL; + ssl->handshake->cookie_len = 0; } } #endif /* MBEDTLS_SSL_PROTO_DTLS */ @@ -2095,7 +1248,7 @@ static int ssl_parse_server_hello(mbedtls_ssl_context *ssl) MBEDTLS_SSL_DEBUG_MSG(1, ("bad server hello message")); mbedtls_ssl_send_alert_message(ssl, MBEDTLS_SSL_ALERT_LEVEL_FATAL, MBEDTLS_SSL_ALERT_MSG_DECODE_ERROR); - return MBEDTLS_ERR_SSL_BAD_HS_SERVER_HELLO; + return MBEDTLS_ERR_SSL_DECODE_ERROR; } /* @@ -2111,27 +1264,25 @@ static int ssl_parse_server_hello(mbedtls_ssl_context *ssl) */ buf += mbedtls_ssl_hs_hdr_len(ssl); - MBEDTLS_SSL_DEBUG_BUF(3, "server hello, version", buf + 0, 2); - mbedtls_ssl_read_version(&ssl->major_ver, &ssl->minor_ver, - ssl->conf->transport, buf + 0); + MBEDTLS_SSL_DEBUG_BUF(3, "server hello, version", buf, 2); + ssl->tls_version = (mbedtls_ssl_protocol_version) mbedtls_ssl_read_version(buf, + ssl->conf->transport); + ssl->session_negotiate->tls_version = ssl->tls_version; + ssl->session_negotiate->endpoint = ssl->conf->endpoint; - if (ssl->major_ver < ssl->conf->min_major_ver || - ssl->minor_ver < ssl->conf->min_minor_ver || - ssl->major_ver > ssl->conf->max_major_ver || - ssl->minor_ver > ssl->conf->max_minor_ver) { + if (ssl->tls_version < ssl->conf->min_tls_version || + ssl->tls_version > ssl->conf->max_tls_version) { MBEDTLS_SSL_DEBUG_MSG(1, ( - "server version out of bounds - min: [%d:%d], server: [%d:%d], max: [%d:%d]", - ssl->conf->min_major_ver, - ssl->conf->min_minor_ver, - ssl->major_ver, ssl->minor_ver, - ssl->conf->max_major_ver, - ssl->conf->max_minor_ver)); + "server version out of bounds - min: [0x%x], server: [0x%x], max: [0x%x]", + (unsigned) ssl->conf->min_tls_version, + (unsigned) ssl->tls_version, + (unsigned) ssl->conf->max_tls_version)); mbedtls_ssl_send_alert_message(ssl, MBEDTLS_SSL_ALERT_LEVEL_FATAL, MBEDTLS_SSL_ALERT_MSG_PROTOCOL_VERSION); - return MBEDTLS_ERR_SSL_BAD_HS_PROTOCOL_VERSION; + return MBEDTLS_ERR_SSL_BAD_PROTOCOL_VERSION; } MBEDTLS_SSL_DEBUG_MSG(3, ("server hello, current time: %lu", @@ -2150,12 +1301,11 @@ static int ssl_parse_server_hello(mbedtls_ssl_context *ssl) MBEDTLS_SSL_DEBUG_MSG(1, ("bad server hello message")); mbedtls_ssl_send_alert_message(ssl, MBEDTLS_SSL_ALERT_LEVEL_FATAL, MBEDTLS_SSL_ALERT_MSG_DECODE_ERROR); - return MBEDTLS_ERR_SSL_BAD_HS_SERVER_HELLO; + return MBEDTLS_ERR_SSL_DECODE_ERROR; } if (ssl->in_hslen > mbedtls_ssl_hs_hdr_len(ssl) + 39 + n) { - ext_len = ((buf[38 + n] << 8) - | (buf[39 + n])); + ext_len = MBEDTLS_GET_UINT16_BE(buf, 38 + n); if ((ext_len > 0 && ext_len < 4) || ssl->in_hslen != mbedtls_ssl_hs_hdr_len(ssl) + 40 + n + ext_len) { @@ -2164,7 +1314,7 @@ static int ssl_parse_server_hello(mbedtls_ssl_context *ssl) ssl, MBEDTLS_SSL_ALERT_LEVEL_FATAL, MBEDTLS_SSL_ALERT_MSG_DECODE_ERROR); - return MBEDTLS_ERR_SSL_BAD_HS_SERVER_HELLO; + return MBEDTLS_ERR_SSL_DECODE_ERROR; } } else if (ssl->in_hslen == mbedtls_ssl_hs_hdr_len(ssl) + 38 + n) { ext_len = 0; @@ -2172,18 +1322,18 @@ static int ssl_parse_server_hello(mbedtls_ssl_context *ssl) MBEDTLS_SSL_DEBUG_MSG(1, ("bad server hello message")); mbedtls_ssl_send_alert_message(ssl, MBEDTLS_SSL_ALERT_LEVEL_FATAL, MBEDTLS_SSL_ALERT_MSG_DECODE_ERROR); - return MBEDTLS_ERR_SSL_BAD_HS_SERVER_HELLO; + return MBEDTLS_ERR_SSL_DECODE_ERROR; } /* ciphersuite (used later) */ - i = (buf[35 + n] << 8) | buf[36 + n]; + i = (int) MBEDTLS_GET_UINT16_BE(buf, n + 35); /* * Read and check compression */ comp = buf[37 + n]; - if (is_compression_bad(ssl, comp)) { + if (comp != MBEDTLS_SSL_COMPRESS_NULL) { MBEDTLS_SSL_DEBUG_MSG(1, ("server hello, bad compression: %d", comp)); mbedtls_ssl_send_alert_message( @@ -2218,7 +1368,6 @@ static int ssl_parse_server_hello(mbedtls_ssl_context *ssl) ssl->renego_status != MBEDTLS_SSL_INITIAL_HANDSHAKE || #endif ssl->session_negotiate->ciphersuite != i || - ssl->session_negotiate->compression != comp || ssl->session_negotiate->id_len != n || memcmp(ssl->session_negotiate->id, buf + 35, n) != 0) { ssl->state++; @@ -2227,7 +1376,6 @@ static int ssl_parse_server_hello(mbedtls_ssl_context *ssl) ssl->session_negotiate->start = mbedtls_time(NULL); #endif ssl->session_negotiate->ciphersuite = i; - ssl->session_negotiate->compression = comp; ssl->session_negotiate->id_len = n; memcpy(ssl->session_negotiate->id, buf + 35, n); } else { @@ -2246,16 +1394,16 @@ static int ssl_parse_server_hello(mbedtls_ssl_context *ssl) */ i = 0; while (1) { - if (ssl->conf->ciphersuite_list[ssl->minor_ver][i] == 0) { + if (ssl->conf->ciphersuite_list[i] == 0) { MBEDTLS_SSL_DEBUG_MSG(1, ("bad server hello message")); mbedtls_ssl_send_alert_message( ssl, MBEDTLS_SSL_ALERT_LEVEL_FATAL, MBEDTLS_SSL_ALERT_MSG_ILLEGAL_PARAMETER); - return MBEDTLS_ERR_SSL_BAD_HS_SERVER_HELLO; + return MBEDTLS_ERR_SSL_ILLEGAL_PARAMETER; } - if (ssl->conf->ciphersuite_list[ssl->minor_ver][i++] == + if (ssl->conf->ciphersuite_list[i++] == ssl->session_negotiate->ciphersuite) { break; } @@ -2263,14 +1411,14 @@ static int ssl_parse_server_hello(mbedtls_ssl_context *ssl) suite_info = mbedtls_ssl_ciphersuite_from_id( ssl->session_negotiate->ciphersuite); - if (ssl_validate_ciphersuite(suite_info, ssl, ssl->minor_ver, - ssl->minor_ver) != 0) { + if (mbedtls_ssl_validate_ciphersuite(ssl, suite_info, ssl->tls_version, + ssl->tls_version) != 0) { MBEDTLS_SSL_DEBUG_MSG(1, ("bad server hello message")); mbedtls_ssl_send_alert_message( ssl, MBEDTLS_SSL_ALERT_LEVEL_FATAL, - MBEDTLS_SSL_ALERT_MSG_ILLEGAL_PARAMETER); - return MBEDTLS_ERR_SSL_BAD_HS_SERVER_HELLO; + MBEDTLS_SSL_ALERT_MSG_HANDSHAKE_FAILURE); + return MBEDTLS_ERR_SSL_HANDSHAKE_FAILURE; } MBEDTLS_SSL_DEBUG_MSG(3, @@ -2278,24 +1426,19 @@ static int ssl_parse_server_hello(mbedtls_ssl_context *ssl) #if defined(MBEDTLS_SSL_ECP_RESTARTABLE_ENABLED) if (suite_info->key_exchange == MBEDTLS_KEY_EXCHANGE_ECDHE_ECDSA && - ssl->minor_ver == MBEDTLS_SSL_MINOR_VERSION_3) { + ssl->tls_version == MBEDTLS_SSL_VERSION_TLS1_2) { ssl->handshake->ecrs_enabled = 1; } #endif - if (comp != MBEDTLS_SSL_COMPRESS_NULL -#if defined(MBEDTLS_ZLIB_SUPPORT) - && comp != MBEDTLS_SSL_COMPRESS_DEFLATE -#endif - ) { + if (comp != MBEDTLS_SSL_COMPRESS_NULL) { MBEDTLS_SSL_DEBUG_MSG(1, ("bad server hello message")); mbedtls_ssl_send_alert_message( ssl, MBEDTLS_SSL_ALERT_LEVEL_FATAL, MBEDTLS_SSL_ALERT_MSG_ILLEGAL_PARAMETER); - return MBEDTLS_ERR_SSL_BAD_HS_SERVER_HELLO; + return MBEDTLS_ERR_SSL_ILLEGAL_PARAMETER; } - ssl->session_negotiate->compression = comp; ext = buf + 40 + n; @@ -2304,17 +1447,15 @@ static int ssl_parse_server_hello(mbedtls_ssl_context *ssl) ext_len)); while (ext_len) { - unsigned int ext_id = ((ext[0] << 8) - | (ext[1])); - unsigned int ext_size = ((ext[2] << 8) - | (ext[3])); + unsigned int ext_id = MBEDTLS_GET_UINT16_BE(ext, 0); + unsigned int ext_size = MBEDTLS_GET_UINT16_BE(ext, 2); if (ext_size + 4 > ext_len) { MBEDTLS_SSL_DEBUG_MSG(1, ("bad server hello message")); mbedtls_ssl_send_alert_message( ssl, MBEDTLS_SSL_ALERT_LEVEL_FATAL, MBEDTLS_SSL_ALERT_MSG_DECODE_ERROR); - return MBEDTLS_ERR_SSL_BAD_HS_SERVER_HELLO; + return MBEDTLS_ERR_SSL_DECODE_ERROR; } switch (ext_id) { @@ -2344,18 +1485,6 @@ static int ssl_parse_server_hello(mbedtls_ssl_context *ssl) break; #endif /* MBEDTLS_SSL_MAX_FRAGMENT_LENGTH */ -#if defined(MBEDTLS_SSL_TRUNCATED_HMAC) - case MBEDTLS_TLS_EXT_TRUNCATED_HMAC: - MBEDTLS_SSL_DEBUG_MSG(3, ("found truncated_hmac extension")); - - if ((ret = ssl_parse_truncated_hmac_ext(ssl, - ext + 4, ext_size)) != 0) { - return ret; - } - - break; -#endif /* MBEDTLS_SSL_TRUNCATED_HMAC */ - #if defined(MBEDTLS_SSL_DTLS_CONNECTION_ID) case MBEDTLS_TLS_EXT_CID: MBEDTLS_SSL_DEBUG_MSG(3, ("found CID extension")); @@ -2406,7 +1535,8 @@ static int ssl_parse_server_hello(mbedtls_ssl_context *ssl) break; #endif /* MBEDTLS_SSL_SESSION_TICKETS */ -#if defined(MBEDTLS_ECDH_C) || defined(MBEDTLS_ECDSA_C) || \ +#if defined(MBEDTLS_KEY_EXCHANGE_SOME_ECDH_OR_ECDHE_1_2_ENABLED) || \ + defined(MBEDTLS_KEY_EXCHANGE_ECDSA_CERT_REQ_ALLOWED_ENABLED) || \ defined(MBEDTLS_KEY_EXCHANGE_ECJPAKE_ENABLED) case MBEDTLS_TLS_EXT_SUPPORTED_POINT_FORMATS: MBEDTLS_SSL_DEBUG_MSG(3, @@ -2418,7 +1548,8 @@ static int ssl_parse_server_hello(mbedtls_ssl_context *ssl) } break; -#endif /* MBEDTLS_ECDH_C || MBEDTLS_ECDSA_C || +#endif /* MBEDTLS_KEY_EXCHANGE_SOME_ECDH_OR_ECDHE_1_2_ENABLED || + MBEDTLS_KEY_EXCHANGE_ECDSA_CERT_REQ_ALLOWED_ENABLED || MBEDTLS_KEY_EXCHANGE_ECJPAKE_ENABLED */ #if defined(MBEDTLS_KEY_EXCHANGE_ECJPAKE_ENABLED) @@ -2465,7 +1596,7 @@ static int ssl_parse_server_hello(mbedtls_ssl_context *ssl) if (ext_len > 0 && ext_len < 4) { MBEDTLS_SSL_DEBUG_MSG(1, ("bad server hello message")); - return MBEDTLS_ERR_SSL_BAD_HS_SERVER_HELLO; + return MBEDTLS_ERR_SSL_DECODE_ERROR; } } @@ -2522,7 +1653,7 @@ static int ssl_parse_server_hello(mbedtls_ssl_context *ssl) ssl, MBEDTLS_SSL_ALERT_LEVEL_FATAL, MBEDTLS_SSL_ALERT_MSG_HANDSHAKE_FAILURE); - return MBEDTLS_ERR_SSL_BAD_HS_SERVER_HELLO; + return MBEDTLS_ERR_SSL_HANDSHAKE_FAILURE; } MBEDTLS_SSL_DEBUG_MSG(2, ("<= parse server hello")); @@ -2555,12 +1686,12 @@ static int ssl_parse_server_dh_params(mbedtls_ssl_context *ssl, return ret; } - dhm_actual_bitlen = mbedtls_mpi_bitlen(&ssl->handshake->dhm_ctx.P); + dhm_actual_bitlen = mbedtls_dhm_get_bitlen(&ssl->handshake->dhm_ctx); if (dhm_actual_bitlen < ssl->conf->dhm_min_bitlen) { MBEDTLS_SSL_DEBUG_MSG(1, ("DHM prime too short: %" MBEDTLS_PRINTF_SIZET " < %u", dhm_actual_bitlen, ssl->conf->dhm_min_bitlen)); - return MBEDTLS_ERR_SSL_BAD_HS_SERVER_KEY_EXCHANGE; + return MBEDTLS_ERR_SSL_HANDSHAKE_FAILURE; } MBEDTLS_SSL_DEBUG_MPI(3, "DHM: P ", &ssl->handshake->dhm_ctx.P); @@ -2572,125 +1703,125 @@ static int ssl_parse_server_dh_params(mbedtls_ssl_context *ssl, #endif /* MBEDTLS_KEY_EXCHANGE_DHE_RSA_ENABLED || MBEDTLS_KEY_EXCHANGE_DHE_PSK_ENABLED */ -#if defined(MBEDTLS_KEY_EXCHANGE_ECDHE_RSA_ENABLED) || \ - defined(MBEDTLS_KEY_EXCHANGE_ECDHE_ECDSA_ENABLED) || \ - defined(MBEDTLS_KEY_EXCHANGE_ECDHE_PSK_ENABLED) || \ - defined(MBEDTLS_KEY_EXCHANGE_ECDH_RSA_ENABLED) || \ - defined(MBEDTLS_KEY_EXCHANGE_ECDH_ECDSA_ENABLED) -MBEDTLS_CHECK_RETURN_CRITICAL -static int ssl_check_server_ecdh_params(const mbedtls_ssl_context *ssl) -{ - const mbedtls_ecp_curve_info *curve_info; - mbedtls_ecp_group_id grp_id; -#if defined(MBEDTLS_ECDH_LEGACY_CONTEXT) - grp_id = ssl->handshake->ecdh_ctx.grp.id; -#else - grp_id = ssl->handshake->ecdh_ctx.grp_id; -#endif /* MBEDTLS_ECDH_LEGACY_CONTEXT */ - - curve_info = mbedtls_ecp_curve_info_from_grp_id(grp_id); - if (curve_info == NULL) { - MBEDTLS_SSL_DEBUG_MSG(1, ("should never happen")); - return MBEDTLS_ERR_SSL_INTERNAL_ERROR; - } - - MBEDTLS_SSL_DEBUG_MSG(2, ("ECDH curve: %s", curve_info->name)); - -#if defined(MBEDTLS_ECP_C) - if (mbedtls_ssl_check_curve(ssl, grp_id) != 0) { - return -1; - } -#else - if (ssl->handshake->ecdh_ctx.grp.nbits < 163 || - ssl->handshake->ecdh_ctx.grp.nbits > 521) { - return -1; - } -#endif /* MBEDTLS_ECP_C */ - - MBEDTLS_SSL_DEBUG_ECDH(3, &ssl->handshake->ecdh_ctx, - MBEDTLS_DEBUG_ECDH_QP); - - return 0; -} -#endif /* MBEDTLS_KEY_EXCHANGE_ECDHE_RSA_ENABLED || - MBEDTLS_KEY_EXCHANGE_ECDHE_ECDSA_ENABLED || - MBEDTLS_KEY_EXCHANGE_ECDHE_PSK_ENABLED || - MBEDTLS_KEY_EXCHANGE_ECDH_RSA_ENABLED || - MBEDTLS_KEY_EXCHANGE_ECDH_ECDSA_ENABLED */ - -#if defined(MBEDTLS_USE_PSA_CRYPTO) && \ - (defined(MBEDTLS_KEY_EXCHANGE_ECDHE_RSA_ENABLED) || \ - defined(MBEDTLS_KEY_EXCHANGE_ECDHE_ECDSA_ENABLED)) +#if defined(MBEDTLS_USE_PSA_CRYPTO) +#if defined(MBEDTLS_KEY_EXCHANGE_ECDHE_RSA_ENABLED) || \ + defined(MBEDTLS_KEY_EXCHANGE_ECDHE_PSK_ENABLED) || \ + defined(MBEDTLS_KEY_EXCHANGE_ECDHE_ECDSA_ENABLED) MBEDTLS_CHECK_RETURN_CRITICAL -static int ssl_parse_server_ecdh_params_psa(mbedtls_ssl_context *ssl, - unsigned char **p, - unsigned char *end) +static int ssl_parse_server_ecdh_params(mbedtls_ssl_context *ssl, + unsigned char **p, + unsigned char *end) { uint16_t tls_id; - size_t ecdh_bits = 0; - uint8_t ecpoint_len; + size_t ecpoint_len; mbedtls_ssl_handshake_params *handshake = ssl->handshake; + psa_key_type_t key_type = PSA_KEY_TYPE_NONE; + size_t ec_bits = 0; /* - * Parse ECC group + * struct { + * ECParameters curve_params; + * ECPoint public; + * } ServerECDHParams; + * + * 1 curve_type (must be "named_curve") + * 2..3 NamedCurve + * 4 ECPoint.len + * 5+ ECPoint contents */ - if (end - *p < 4) { - return MBEDTLS_ERR_SSL_BAD_HS_SERVER_KEY_EXCHANGE; + return MBEDTLS_ERR_SSL_DECODE_ERROR; } /* First byte is curve_type; only named_curve is handled */ if (*(*p)++ != MBEDTLS_ECP_TLS_NAMED_CURVE) { - return MBEDTLS_ERR_SSL_BAD_HS_SERVER_KEY_EXCHANGE; + return MBEDTLS_ERR_SSL_HANDSHAKE_FAILURE; } /* Next two bytes are the namedcurve value */ - tls_id = *(*p)++; - tls_id <<= 8; - tls_id |= *(*p)++; + tls_id = MBEDTLS_GET_UINT16_BE(*p, 0); + *p += 2; /* Check it's a curve we offered */ if (mbedtls_ssl_check_curve_tls_id(ssl, tls_id) != 0) { - return MBEDTLS_ERR_SSL_BAD_HS_SERVER_KEY_EXCHANGE; + MBEDTLS_SSL_DEBUG_MSG(2, + ("bad server key exchange message (ECDHE curve): %u", + (unsigned) tls_id)); + return MBEDTLS_ERR_SSL_HANDSHAKE_FAILURE; } - /* Convert EC group to PSA key type. */ - if ((handshake->ecdh_psa_type = - mbedtls_psa_parse_tls_ecc_group(tls_id, &ecdh_bits)) == 0) { - return MBEDTLS_ERR_SSL_BAD_HS_SERVER_KEY_EXCHANGE; - } - if (ecdh_bits > 0xffff) { - return MBEDTLS_ERR_SSL_BAD_HS_SERVER_KEY_EXCHANGE; + /* Convert EC's TLS ID to PSA key type. */ + if (mbedtls_ssl_get_psa_curve_info_from_tls_id(tls_id, &key_type, + &ec_bits) == PSA_ERROR_NOT_SUPPORTED) { + return MBEDTLS_ERR_SSL_HANDSHAKE_FAILURE; } - handshake->ecdh_bits = (uint16_t) ecdh_bits; - - /* - * Put peer's ECDH public key in the format understood by PSA. - */ + handshake->xxdh_psa_type = key_type; + handshake->xxdh_psa_bits = ec_bits; + /* Keep a copy of the peer's public key */ ecpoint_len = *(*p)++; if ((size_t) (end - *p) < ecpoint_len) { - return MBEDTLS_ERR_SSL_BAD_HS_SERVER_KEY_EXCHANGE; + return MBEDTLS_ERR_SSL_DECODE_ERROR; } - if (mbedtls_psa_tls_ecpoint_to_psa_ec( - *p, ecpoint_len, - handshake->ecdh_psa_peerkey, - sizeof(handshake->ecdh_psa_peerkey), - &handshake->ecdh_psa_peerkey_len) != 0) { - return MBEDTLS_ERR_SSL_HW_ACCEL_FAILED; + if (ecpoint_len > sizeof(handshake->xxdh_psa_peerkey)) { + return MBEDTLS_ERR_SSL_HANDSHAKE_FAILURE; } + memcpy(handshake->xxdh_psa_peerkey, *p, ecpoint_len); + handshake->xxdh_psa_peerkey_len = ecpoint_len; *p += ecpoint_len; + return 0; } -#endif /* MBEDTLS_USE_PSA_CRYPTO && - ( MBEDTLS_KEY_EXCHANGE_ECDHE_RSA_ENABLED || - MBEDTLS_KEY_EXCHANGE_ECDHE_ECDSA_ENABLED ) */ +#endif /* MBEDTLS_KEY_EXCHANGE_ECDHE_RSA_ENABLED || + MBEDTLS_KEY_EXCHANGE_ECDHE_PSK_ENABLED || + MBEDTLS_KEY_EXCHANGE_ECDHE_ECDSA_ENABLED */ +#else +#if defined(MBEDTLS_KEY_EXCHANGE_ECDHE_RSA_ENABLED) || \ + defined(MBEDTLS_KEY_EXCHANGE_ECDH_RSA_ENABLED) || \ + defined(MBEDTLS_KEY_EXCHANGE_ECDHE_PSK_ENABLED) || \ + defined(MBEDTLS_KEY_EXCHANGE_ECDHE_ECDSA_ENABLED) || \ + defined(MBEDTLS_KEY_EXCHANGE_ECDH_ECDSA_ENABLED) +MBEDTLS_CHECK_RETURN_CRITICAL +static int ssl_check_server_ecdh_params(const mbedtls_ssl_context *ssl) +{ + uint16_t tls_id; + mbedtls_ecp_group_id grp_id; +#if defined(MBEDTLS_ECDH_LEGACY_CONTEXT) + grp_id = ssl->handshake->ecdh_ctx.grp.id; +#else + grp_id = ssl->handshake->ecdh_ctx.grp_id; +#endif -#if defined(MBEDTLS_KEY_EXCHANGE_ECDHE_RSA_ENABLED) || \ - defined(MBEDTLS_KEY_EXCHANGE_ECDHE_ECDSA_ENABLED) || \ - defined(MBEDTLS_KEY_EXCHANGE_ECDHE_PSK_ENABLED) + tls_id = mbedtls_ssl_get_tls_id_from_ecp_group_id(grp_id); + if (tls_id == 0) { + MBEDTLS_SSL_DEBUG_MSG(1, ("should never happen")); + return MBEDTLS_ERR_SSL_INTERNAL_ERROR; + } + + MBEDTLS_SSL_DEBUG_MSG(2, ("ECDH curve: %s", + mbedtls_ssl_get_curve_name_from_tls_id(tls_id))); + + if (mbedtls_ssl_check_curve(ssl, grp_id) != 0) { + return -1; + } + + MBEDTLS_SSL_DEBUG_ECDH(3, &ssl->handshake->ecdh_ctx, + MBEDTLS_DEBUG_ECDH_QP); + + return 0; +} + +#endif /* MBEDTLS_KEY_EXCHANGE_ECDHE_RSA_ENABLED || + MBEDTLS_KEY_EXCHANGE_ECDH_RSA_ENABLED || + MBEDTLS_KEY_EXCHANGE_ECDHE_PSK_ENABLED || + MBEDTLS_KEY_EXCHANGE_ECDHE_ECDSA_ENABLED || + MBEDTLS_KEY_EXCHANGE_ECDH_ECDSA_ENABLED */ + +#if defined(MBEDTLS_KEY_EXCHANGE_ECDHE_RSA_ENABLED) || \ + defined(MBEDTLS_KEY_EXCHANGE_ECDHE_PSK_ENABLED) || \ + defined(MBEDTLS_KEY_EXCHANGE_ECDHE_ECDSA_ENABLED) MBEDTLS_CHECK_RETURN_CRITICAL static int ssl_parse_server_ecdh_params(mbedtls_ssl_context *ssl, unsigned char **p, @@ -2720,15 +1851,15 @@ static int ssl_parse_server_ecdh_params(mbedtls_ssl_context *ssl, if (ssl_check_server_ecdh_params(ssl) != 0) { MBEDTLS_SSL_DEBUG_MSG(1, ("bad server key exchange message (ECDHE curve)")); - return MBEDTLS_ERR_SSL_BAD_HS_SERVER_KEY_EXCHANGE; + return MBEDTLS_ERR_SSL_HANDSHAKE_FAILURE; } return ret; } -#endif /* MBEDTLS_KEY_EXCHANGE_ECDHE_RSA_ENABLED || - MBEDTLS_KEY_EXCHANGE_ECDHE_ECDSA_ENABLED || - MBEDTLS_KEY_EXCHANGE_ECDHE_PSK_ENABLED */ - +#endif /* MBEDTLS_KEY_EXCHANGE_ECDHE_RSA_ENABLED || \ + MBEDTLS_KEY_EXCHANGE_ECDHE_PSK_ENABLED || \ + MBEDTLS_KEY_EXCHANGE_ECDHE_ECDSA_ENABLED */ +#endif /* !MBEDTLS_USE_PSA_CRYPTO */ #if defined(MBEDTLS_KEY_EXCHANGE_SOME_PSK_ENABLED) MBEDTLS_CHECK_RETURN_CRITICAL static int ssl_parse_server_psk_hint(mbedtls_ssl_context *ssl, @@ -2747,15 +1878,15 @@ static int ssl_parse_server_psk_hint(mbedtls_ssl_context *ssl, if (end - (*p) < 2) { MBEDTLS_SSL_DEBUG_MSG(1, ("bad server key exchange message (psk_identity_hint length)")); - return MBEDTLS_ERR_SSL_BAD_HS_SERVER_KEY_EXCHANGE; + return MBEDTLS_ERR_SSL_DECODE_ERROR; } - len = (*p)[0] << 8 | (*p)[1]; + len = MBEDTLS_GET_UINT16_BE(*p, 0); *p += 2; if (end - (*p) < len) { MBEDTLS_SSL_DEBUG_MSG(1, ("bad server key exchange message (psk_identity_hint length)")); - return MBEDTLS_ERR_SSL_BAD_HS_SERVER_KEY_EXCHANGE; + return MBEDTLS_ERR_SSL_DECODE_ERROR; } /* @@ -2781,7 +1912,7 @@ static int ssl_write_encrypted_pms(mbedtls_ssl_context *ssl, size_t pms_offset) { int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED; - size_t len_bytes = ssl->minor_ver == MBEDTLS_SSL_MINOR_VERSION_0 ? 0 : 2; + size_t len_bytes = 2; unsigned char *p = ssl->handshake->premaster + pms_offset; mbedtls_pk_context *peer_pk; @@ -2797,9 +1928,8 @@ static int ssl_write_encrypted_pms(mbedtls_ssl_context *ssl, * opaque random[46]; * } PreMasterSecret; */ - mbedtls_ssl_write_version(ssl->conf->max_major_ver, - ssl->conf->max_minor_ver, - ssl->conf->transport, p); + mbedtls_ssl_write_version(p, ssl->conf->transport, + MBEDTLS_SSL_VERSION_TLS1_2); if ((ret = ssl->conf->f_rng(ssl->conf->p_rng, p + 2, 46)) != 0) { MBEDTLS_SSL_DEBUG_RET(1, "f_rng", ret); @@ -2836,13 +1966,10 @@ static int ssl_write_encrypted_pms(mbedtls_ssl_context *ssl, return ret; } -#if defined(MBEDTLS_SSL_PROTO_TLS1) || defined(MBEDTLS_SSL_PROTO_TLS1_1) || \ - defined(MBEDTLS_SSL_PROTO_TLS1_2) if (len_bytes == 2) { MBEDTLS_PUT_UINT16_BE(*olen, ssl->out_msg, offset); *olen += 2; } -#endif #if !defined(MBEDTLS_SSL_KEEP_PEER_CERTIFICATE) /* We don't need the peer's public key anymore. Free it. */ @@ -2853,79 +1980,12 @@ static int ssl_write_encrypted_pms(mbedtls_ssl_context *ssl, #endif /* MBEDTLS_KEY_EXCHANGE_RSA_ENABLED || MBEDTLS_KEY_EXCHANGE_RSA_PSK_ENABLED */ -#if defined(MBEDTLS_SSL_PROTO_TLS1_2) -#if defined(MBEDTLS_KEY_EXCHANGE_DHE_RSA_ENABLED) || \ - defined(MBEDTLS_KEY_EXCHANGE_ECDHE_RSA_ENABLED) || \ - defined(MBEDTLS_KEY_EXCHANGE_ECDHE_ECDSA_ENABLED) -MBEDTLS_CHECK_RETURN_CRITICAL -static int ssl_parse_signature_algorithm(mbedtls_ssl_context *ssl, - unsigned char **p, - unsigned char *end, - mbedtls_md_type_t *md_alg, - mbedtls_pk_type_t *pk_alg) -{ - ((void) ssl); - *md_alg = MBEDTLS_MD_NONE; - *pk_alg = MBEDTLS_PK_NONE; - - /* Only in TLS 1.2 */ - if (ssl->minor_ver != MBEDTLS_SSL_MINOR_VERSION_3) { - return 0; - } - - if ((*p) + 2 > end) { - return MBEDTLS_ERR_SSL_BAD_HS_SERVER_KEY_EXCHANGE; - } - - /* - * Get hash algorithm - */ - if ((*md_alg = mbedtls_ssl_md_alg_from_hash((*p)[0])) - == MBEDTLS_MD_NONE) { - MBEDTLS_SSL_DEBUG_MSG(1, - ("Server used unsupported HashAlgorithm %d", *(p)[0])); - return MBEDTLS_ERR_SSL_BAD_HS_SERVER_KEY_EXCHANGE; - } - - /* - * Get signature algorithm - */ - if ((*pk_alg = mbedtls_ssl_pk_alg_from_sig((*p)[1])) - == MBEDTLS_PK_NONE) { - MBEDTLS_SSL_DEBUG_MSG(1, - ("server used unsupported SignatureAlgorithm %d", (*p)[1])); - return MBEDTLS_ERR_SSL_BAD_HS_SERVER_KEY_EXCHANGE; - } - - /* - * Check if the hash is acceptable - */ - if (mbedtls_ssl_check_sig_hash(ssl, *md_alg) != 0) { - MBEDTLS_SSL_DEBUG_MSG(1, - ("server used HashAlgorithm %d that was not offered", *(p)[0])); - return MBEDTLS_ERR_SSL_BAD_HS_SERVER_KEY_EXCHANGE; - } - - MBEDTLS_SSL_DEBUG_MSG(2, ("Server used SignatureAlgorithm %d", - (*p)[1])); - MBEDTLS_SSL_DEBUG_MSG(2, ("Server used HashAlgorithm %d", - (*p)[0])); - *p += 2; - - return 0; -} -#endif /* MBEDTLS_KEY_EXCHANGE_DHE_RSA_ENABLED || - MBEDTLS_KEY_EXCHANGE_ECDHE_RSA_ENABLED || - MBEDTLS_KEY_EXCHANGE_ECDHE_ECDSA_ENABLED */ -#endif /* MBEDTLS_SSL_PROTO_TLS1_2 */ - #if defined(MBEDTLS_KEY_EXCHANGE_ECDH_RSA_ENABLED) || \ defined(MBEDTLS_KEY_EXCHANGE_ECDH_ECDSA_ENABLED) MBEDTLS_CHECK_RETURN_CRITICAL static int ssl_get_ecdh_params_from_cert(mbedtls_ssl_context *ssl) { int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED; - const mbedtls_ecp_keypair *peer_key; mbedtls_pk_context *peer_pk; #if !defined(MBEDTLS_SSL_KEEP_PEER_CERTIFICATE) @@ -2946,8 +2006,53 @@ static int ssl_get_ecdh_params_from_cert(mbedtls_ssl_context *ssl) return MBEDTLS_ERR_SSL_PK_TYPE_MISMATCH; } - peer_key = mbedtls_pk_ec(*peer_pk); +#if !defined(MBEDTLS_PK_USE_PSA_EC_DATA) + const mbedtls_ecp_keypair *peer_key = mbedtls_pk_ec_ro(*peer_pk); +#endif /* !defined(MBEDTLS_PK_USE_PSA_EC_DATA) */ + +#if defined(MBEDTLS_USE_PSA_CRYPTO) + uint16_t tls_id = 0; + psa_key_type_t key_type = PSA_KEY_TYPE_NONE; + mbedtls_ecp_group_id grp_id = mbedtls_pk_get_ec_group_id(peer_pk); + + if (mbedtls_ssl_check_curve(ssl, grp_id) != 0) { + MBEDTLS_SSL_DEBUG_MSG(1, ("bad server certificate (ECDH curve)")); + return MBEDTLS_ERR_SSL_BAD_CERTIFICATE; + } + + tls_id = mbedtls_ssl_get_tls_id_from_ecp_group_id(grp_id); + if (tls_id == 0) { + MBEDTLS_SSL_DEBUG_MSG(1, ("ECC group %u not suported", + grp_id)); + return MBEDTLS_ERR_SSL_ILLEGAL_PARAMETER; + } + + /* If the above conversion to TLS ID was fine, then also this one will be, + so there is no need to check the return value here */ + mbedtls_ssl_get_psa_curve_info_from_tls_id(tls_id, &key_type, + &ssl->handshake->xxdh_psa_bits); + ssl->handshake->xxdh_psa_type = key_type; + + /* Store peer's public key in psa format. */ +#if defined(MBEDTLS_PK_USE_PSA_EC_DATA) + memcpy(ssl->handshake->xxdh_psa_peerkey, peer_pk->pub_raw, peer_pk->pub_raw_len); + ssl->handshake->xxdh_psa_peerkey_len = peer_pk->pub_raw_len; + ret = 0; +#else /* MBEDTLS_PK_USE_PSA_EC_DATA */ + size_t olen = 0; + ret = mbedtls_ecp_point_write_binary(&peer_key->grp, &peer_key->Q, + MBEDTLS_ECP_PF_UNCOMPRESSED, &olen, + ssl->handshake->xxdh_psa_peerkey, + sizeof(ssl->handshake->xxdh_psa_peerkey)); + + if (ret != 0) { + MBEDTLS_SSL_DEBUG_RET(1, ("mbedtls_ecp_point_write_binary"), ret); + return ret; + } + ssl->handshake->xxdh_psa_peerkey_len = olen; +#endif /* MBEDTLS_PK_USE_PSA_EC_DATA */ +#else /* MBEDTLS_USE_PSA_CRYPTO */ if ((ret = mbedtls_ecdh_get_params(&ssl->handshake->ecdh_ctx, peer_key, MBEDTLS_ECDH_THEIRS)) != 0) { MBEDTLS_SSL_DEBUG_RET(1, ("mbedtls_ecdh_get_params"), ret); @@ -2956,9 +2061,9 @@ static int ssl_get_ecdh_params_from_cert(mbedtls_ssl_context *ssl) if (ssl_check_server_ecdh_params(ssl) != 0) { MBEDTLS_SSL_DEBUG_MSG(1, ("bad server certificate (ECDH curve)")); - return MBEDTLS_ERR_SSL_BAD_HS_CERTIFICATE; + return MBEDTLS_ERR_SSL_BAD_CERTIFICATE; } - +#endif /* MBEDTLS_USE_PSA_CRYPTO */ #if !defined(MBEDTLS_SSL_KEEP_PEER_CERTIFICATE) /* We don't need the peer's public key anymore. Free it, * so that more RAM is available for upcoming expensive @@ -3066,7 +2171,7 @@ static int ssl_parse_server_key_exchange(mbedtls_ssl_context *ssl) #endif p = ssl->in_msg + mbedtls_ssl_hs_hdr_len(ssl); end = ssl->in_msg + ssl->in_hslen; - MBEDTLS_SSL_DEBUG_BUF(3, "server key exchange", p, end - p); + MBEDTLS_SSL_DEBUG_BUF(3, "server key exchange", p, (size_t) (end - p)); #if defined(MBEDTLS_KEY_EXCHANGE_SOME_PSK_ENABLED) if (ciphersuite_info->key_exchange == MBEDTLS_KEY_EXCHANGE_PSK || @@ -3078,8 +2183,8 @@ static int ssl_parse_server_key_exchange(mbedtls_ssl_context *ssl) mbedtls_ssl_send_alert_message( ssl, MBEDTLS_SSL_ALERT_LEVEL_FATAL, - MBEDTLS_SSL_ALERT_MSG_ILLEGAL_PARAMETER); - return MBEDTLS_ERR_SSL_BAD_HS_SERVER_KEY_EXCHANGE; + MBEDTLS_SSL_ALERT_MSG_DECODE_ERROR); + return MBEDTLS_ERR_SSL_DECODE_ERROR; } } /* FALLTHROUGH */ #endif /* MBEDTLS_KEY_EXCHANGE_SOME_PSK_ENABLED */ @@ -3102,30 +2207,13 @@ static int ssl_parse_server_key_exchange(mbedtls_ssl_context *ssl) ssl, MBEDTLS_SSL_ALERT_LEVEL_FATAL, MBEDTLS_SSL_ALERT_MSG_ILLEGAL_PARAMETER); - return MBEDTLS_ERR_SSL_BAD_HS_SERVER_KEY_EXCHANGE; + return MBEDTLS_ERR_SSL_ILLEGAL_PARAMETER; } } else #endif /* MBEDTLS_KEY_EXCHANGE_DHE_RSA_ENABLED || MBEDTLS_KEY_EXCHANGE_DHE_PSK_ENABLED */ -#if defined(MBEDTLS_USE_PSA_CRYPTO) && \ - (defined(MBEDTLS_KEY_EXCHANGE_ECDHE_RSA_ENABLED) || \ - defined(MBEDTLS_KEY_EXCHANGE_ECDHE_ECDSA_ENABLED)) - if (ciphersuite_info->key_exchange == MBEDTLS_KEY_EXCHANGE_ECDHE_RSA || - ciphersuite_info->key_exchange == MBEDTLS_KEY_EXCHANGE_ECDHE_ECDSA) { - if (ssl_parse_server_ecdh_params_psa(ssl, &p, end) != 0) { - MBEDTLS_SSL_DEBUG_MSG(1, ("bad server key exchange message")); - mbedtls_ssl_send_alert_message( - ssl, - MBEDTLS_SSL_ALERT_LEVEL_FATAL, - MBEDTLS_SSL_ALERT_MSG_ILLEGAL_PARAMETER); - return MBEDTLS_ERR_SSL_BAD_HS_SERVER_KEY_EXCHANGE; - } - } else -#endif /* MBEDTLS_USE_PSA_CRYPTO && - ( MBEDTLS_KEY_EXCHANGE_ECDHE_RSA_ENABLED || - MBEDTLS_KEY_EXCHANGE_ECDHE_ECDSA_ENABLED ) */ -#if defined(MBEDTLS_KEY_EXCHANGE_ECDHE_RSA_ENABLED) || \ - defined(MBEDTLS_KEY_EXCHANGE_ECDHE_PSK_ENABLED) || \ +#if defined(MBEDTLS_KEY_EXCHANGE_ECDHE_RSA_ENABLED) || \ + defined(MBEDTLS_KEY_EXCHANGE_ECDHE_PSK_ENABLED) || \ defined(MBEDTLS_KEY_EXCHANGE_ECDHE_ECDSA_ENABLED) if (ciphersuite_info->key_exchange == MBEDTLS_KEY_EXCHANGE_ECDHE_RSA || ciphersuite_info->key_exchange == MBEDTLS_KEY_EXCHANGE_ECDHE_PSK || @@ -3136,7 +2224,7 @@ static int ssl_parse_server_key_exchange(mbedtls_ssl_context *ssl) ssl, MBEDTLS_SSL_ALERT_LEVEL_FATAL, MBEDTLS_SSL_ALERT_MSG_ILLEGAL_PARAMETER); - return MBEDTLS_ERR_SSL_BAD_HS_SERVER_KEY_EXCHANGE; + return MBEDTLS_ERR_SSL_ILLEGAL_PARAMETER; } } else #endif /* MBEDTLS_KEY_EXCHANGE_ECDHE_RSA_ENABLED || @@ -3144,6 +2232,44 @@ static int ssl_parse_server_key_exchange(mbedtls_ssl_context *ssl) MBEDTLS_KEY_EXCHANGE_ECDHE_ECDSA_ENABLED */ #if defined(MBEDTLS_KEY_EXCHANGE_ECJPAKE_ENABLED) if (ciphersuite_info->key_exchange == MBEDTLS_KEY_EXCHANGE_ECJPAKE) { +#if defined(MBEDTLS_USE_PSA_CRYPTO) + /* + * The first 3 bytes are: + * [0] MBEDTLS_ECP_TLS_NAMED_CURVE + * [1, 2] elliptic curve's TLS ID + * + * However since we only support secp256r1 for now, we check only + * that TLS ID here + */ + uint16_t read_tls_id = MBEDTLS_GET_UINT16_BE(p, 1); + uint16_t exp_tls_id = mbedtls_ssl_get_tls_id_from_ecp_group_id( + MBEDTLS_ECP_DP_SECP256R1); + + if (exp_tls_id == 0) { + return MBEDTLS_ERR_SSL_FEATURE_UNAVAILABLE; + } + + if ((*p != MBEDTLS_ECP_TLS_NAMED_CURVE) || + (read_tls_id != exp_tls_id)) { + return MBEDTLS_ERR_SSL_ILLEGAL_PARAMETER; + } + + p += 3; + + if ((ret = mbedtls_psa_ecjpake_read_round( + &ssl->handshake->psa_pake_ctx, p, end - p, + MBEDTLS_ECJPAKE_ROUND_TWO)) != 0) { + psa_destroy_key(ssl->handshake->psa_pake_password); + psa_pake_abort(&ssl->handshake->psa_pake_ctx); + + MBEDTLS_SSL_DEBUG_RET(1, "psa_pake_input round two", ret); + mbedtls_ssl_send_alert_message( + ssl, + MBEDTLS_SSL_ALERT_LEVEL_FATAL, + MBEDTLS_SSL_ALERT_MSG_HANDSHAKE_FAILURE); + return MBEDTLS_ERR_SSL_HANDSHAKE_FAILURE; + } +#else ret = mbedtls_ecjpake_read_round_two(&ssl->handshake->ecjpake_ctx, p, end - p); if (ret != 0) { @@ -3151,9 +2277,10 @@ static int ssl_parse_server_key_exchange(mbedtls_ssl_context *ssl) mbedtls_ssl_send_alert_message( ssl, MBEDTLS_SSL_ALERT_LEVEL_FATAL, - MBEDTLS_SSL_ALERT_MSG_ILLEGAL_PARAMETER); - return MBEDTLS_ERR_SSL_BAD_HS_SERVER_KEY_EXCHANGE; + MBEDTLS_SSL_ALERT_MSG_HANDSHAKE_FAILURE); + return MBEDTLS_ERR_SSL_HANDSHAKE_FAILURE; } +#endif /* MBEDTLS_USE_PSA_CRYPTO */ } else #endif /* MBEDTLS_KEY_EXCHANGE_ECJPAKE_ENABLED */ { @@ -3164,61 +2291,55 @@ static int ssl_parse_server_key_exchange(mbedtls_ssl_context *ssl) #if defined(MBEDTLS_KEY_EXCHANGE_WITH_SERVER_SIGNATURE_ENABLED) if (mbedtls_ssl_ciphersuite_uses_server_signature(ciphersuite_info)) { size_t sig_len, hashlen; -#if defined(MBEDTLS_USE_PSA_CRYPTO) - unsigned char hash[PSA_HASH_MAX_SIZE]; -#else unsigned char hash[MBEDTLS_MD_MAX_SIZE]; -#endif + mbedtls_md_type_t md_alg = MBEDTLS_MD_NONE; mbedtls_pk_type_t pk_alg = MBEDTLS_PK_NONE; unsigned char *params = ssl->in_msg + mbedtls_ssl_hs_hdr_len(ssl); - size_t params_len = p - params; + size_t params_len = (size_t) (p - params); void *rs_ctx = NULL; + uint16_t sig_alg; mbedtls_pk_context *peer_pk; +#if !defined(MBEDTLS_SSL_KEEP_PEER_CERTIFICATE) + peer_pk = &ssl->handshake->peer_pubkey; +#else /* !MBEDTLS_SSL_KEEP_PEER_CERTIFICATE */ + if (ssl->session_negotiate->peer_cert == NULL) { + /* Should never happen */ + MBEDTLS_SSL_DEBUG_MSG(1, ("should never happen")); + return MBEDTLS_ERR_SSL_INTERNAL_ERROR; + } + peer_pk = &ssl->session_negotiate->peer_cert->pk; +#endif /* MBEDTLS_SSL_KEEP_PEER_CERTIFICATE */ + /* * Handle the digitally-signed structure */ -#if defined(MBEDTLS_SSL_PROTO_TLS1_2) - if (ssl->minor_ver == MBEDTLS_SSL_MINOR_VERSION_3) { - if (ssl_parse_signature_algorithm(ssl, &p, end, - &md_alg, &pk_alg) != 0) { - MBEDTLS_SSL_DEBUG_MSG(1, - ("bad server key exchange message")); - mbedtls_ssl_send_alert_message( - ssl, - MBEDTLS_SSL_ALERT_LEVEL_FATAL, - MBEDTLS_SSL_ALERT_MSG_ILLEGAL_PARAMETER); - return MBEDTLS_ERR_SSL_BAD_HS_SERVER_KEY_EXCHANGE; - } - - if (pk_alg != - mbedtls_ssl_get_ciphersuite_sig_pk_alg(ciphersuite_info)) { - MBEDTLS_SSL_DEBUG_MSG(1, - ("bad server key exchange message")); - mbedtls_ssl_send_alert_message( - ssl, - MBEDTLS_SSL_ALERT_LEVEL_FATAL, - MBEDTLS_SSL_ALERT_MSG_ILLEGAL_PARAMETER); - return MBEDTLS_ERR_SSL_BAD_HS_SERVER_KEY_EXCHANGE; - } - } else -#endif /* MBEDTLS_SSL_PROTO_TLS1_2 */ -#if defined(MBEDTLS_SSL_PROTO_SSL3) || defined(MBEDTLS_SSL_PROTO_TLS1) || \ - defined(MBEDTLS_SSL_PROTO_TLS1_1) - if (ssl->minor_ver < MBEDTLS_SSL_MINOR_VERSION_3) { - pk_alg = mbedtls_ssl_get_ciphersuite_sig_pk_alg(ciphersuite_info); - - /* Default hash for ECDSA is SHA-1 */ - if (pk_alg == MBEDTLS_PK_ECDSA && md_alg == MBEDTLS_MD_NONE) { - md_alg = MBEDTLS_MD_SHA1; - } - } else -#endif - { - MBEDTLS_SSL_DEBUG_MSG(1, ("should never happen")); - return MBEDTLS_ERR_SSL_INTERNAL_ERROR; + MBEDTLS_SSL_CHK_BUF_READ_PTR(p, end, 2); + sig_alg = MBEDTLS_GET_UINT16_BE(p, 0); + if (mbedtls_ssl_get_pk_type_and_md_alg_from_sig_alg( + sig_alg, &pk_alg, &md_alg) != 0 && + !mbedtls_ssl_sig_alg_is_offered(ssl, sig_alg) && + !mbedtls_ssl_sig_alg_is_supported(ssl, sig_alg)) { + MBEDTLS_SSL_DEBUG_MSG(1, + ("bad server key exchange message")); + mbedtls_ssl_send_alert_message( + ssl, + MBEDTLS_SSL_ALERT_LEVEL_FATAL, + MBEDTLS_SSL_ALERT_MSG_ILLEGAL_PARAMETER); + return MBEDTLS_ERR_SSL_ILLEGAL_PARAMETER; + } + p += 2; + + if (!mbedtls_pk_can_do(peer_pk, pk_alg)) { + MBEDTLS_SSL_DEBUG_MSG(1, + ("bad server key exchange message")); + mbedtls_ssl_send_alert_message( + ssl, + MBEDTLS_SSL_ALERT_LEVEL_FATAL, + MBEDTLS_SSL_ALERT_MSG_ILLEGAL_PARAMETER); + return MBEDTLS_ERR_SSL_ILLEGAL_PARAMETER; } /* @@ -3231,9 +2352,9 @@ static int ssl_parse_server_key_exchange(mbedtls_ssl_context *ssl) ssl, MBEDTLS_SSL_ALERT_LEVEL_FATAL, MBEDTLS_SSL_ALERT_MSG_DECODE_ERROR); - return MBEDTLS_ERR_SSL_BAD_HS_SERVER_KEY_EXCHANGE; + return MBEDTLS_ERR_SSL_DECODE_ERROR; } - sig_len = (p[0] << 8) | p[1]; + sig_len = MBEDTLS_GET_UINT16_BE(p, 0); p += 2; if (p != end - sig_len) { @@ -3242,7 +2363,7 @@ static int ssl_parse_server_key_exchange(mbedtls_ssl_context *ssl) ssl, MBEDTLS_SSL_ALERT_LEVEL_FATAL, MBEDTLS_SSL_ALERT_MSG_DECODE_ERROR); - return MBEDTLS_ERR_SSL_BAD_HS_SERVER_KEY_EXCHANGE; + return MBEDTLS_ERR_SSL_DECODE_ERROR; } MBEDTLS_SSL_DEBUG_BUF(3, "signature", p, sig_len); @@ -3250,20 +2371,6 @@ static int ssl_parse_server_key_exchange(mbedtls_ssl_context *ssl) /* * Compute the hash that has been signed */ -#if defined(MBEDTLS_SSL_PROTO_SSL3) || defined(MBEDTLS_SSL_PROTO_TLS1) || \ - defined(MBEDTLS_SSL_PROTO_TLS1_1) - if (md_alg == MBEDTLS_MD_NONE) { - hashlen = 36; - ret = mbedtls_ssl_get_key_exchange_md_ssl_tls(ssl, hash, params, - params_len); - if (ret != 0) { - return ret; - } - } else -#endif /* MBEDTLS_SSL_PROTO_SSL3 || MBEDTLS_SSL_PROTO_TLS1 || \ - MBEDTLS_SSL_PROTO_TLS1_1 */ -#if defined(MBEDTLS_SSL_PROTO_TLS1) || defined(MBEDTLS_SSL_PROTO_TLS1_1) || \ - defined(MBEDTLS_SSL_PROTO_TLS1_2) if (md_alg != MBEDTLS_MD_NONE) { ret = mbedtls_ssl_get_key_exchange_md_tls1_2(ssl, hash, &hashlen, params, params_len, @@ -3271,27 +2378,13 @@ static int ssl_parse_server_key_exchange(mbedtls_ssl_context *ssl) if (ret != 0) { return ret; } - } else -#endif /* MBEDTLS_SSL_PROTO_TLS1 || MBEDTLS_SSL_PROTO_TLS1_1 || \ - MBEDTLS_SSL_PROTO_TLS1_2 */ - { + } else { MBEDTLS_SSL_DEBUG_MSG(1, ("should never happen")); return MBEDTLS_ERR_SSL_INTERNAL_ERROR; } MBEDTLS_SSL_DEBUG_BUF(3, "parameters hash", hash, hashlen); -#if !defined(MBEDTLS_SSL_KEEP_PEER_CERTIFICATE) - peer_pk = &ssl->handshake->peer_pubkey; -#else /* !MBEDTLS_SSL_KEEP_PEER_CERTIFICATE */ - if (ssl->session_negotiate->peer_cert == NULL) { - /* Should never happen */ - MBEDTLS_SSL_DEBUG_MSG(1, ("should never happen")); - return MBEDTLS_ERR_SSL_INTERNAL_ERROR; - } - peer_pk = &ssl->session_negotiate->peer_cert->pk; -#endif /* MBEDTLS_SSL_KEEP_PEER_CERTIFICATE */ - /* * Verify signature */ @@ -3308,21 +2401,44 @@ static int ssl_parse_server_key_exchange(mbedtls_ssl_context *ssl) if (ssl->handshake->ecrs_enabled) { rs_ctx = &ssl->handshake->ecrs_ctx.pk; } -#endif /* MBEDTLS_SSL_ECP_RESTARTABLE_ENABLED */ +#endif - if ((ret = mbedtls_pk_verify_restartable(peer_pk, - md_alg, hash, hashlen, p, sig_len, rs_ctx)) != 0) { +#if defined(MBEDTLS_X509_RSASSA_PSS_SUPPORT) + if (pk_alg == MBEDTLS_PK_RSASSA_PSS) { + mbedtls_pk_rsassa_pss_options rsassa_pss_options; + rsassa_pss_options.mgf1_hash_id = md_alg; + rsassa_pss_options.expected_salt_len = + mbedtls_md_get_size_from_type(md_alg); + if (rsassa_pss_options.expected_salt_len == 0) { + return MBEDTLS_ERR_SSL_INTERNAL_ERROR; + } + + ret = mbedtls_pk_verify_ext(pk_alg, &rsassa_pss_options, + peer_pk, + md_alg, hash, hashlen, + p, sig_len); + } else +#endif /* MBEDTLS_X509_RSASSA_PSS_SUPPORT */ + ret = mbedtls_pk_verify_restartable(peer_pk, + md_alg, hash, hashlen, p, sig_len, rs_ctx); + + if (ret != 0) { + int send_alert_msg = 1; #if defined(MBEDTLS_SSL_ECP_RESTARTABLE_ENABLED) - if (ret == MBEDTLS_ERR_ECP_IN_PROGRESS) { - MBEDTLS_SSL_DEBUG_RET(1, "mbedtls_pk_verify", ret); - return MBEDTLS_ERR_SSL_CRYPTO_IN_PROGRESS; + send_alert_msg = (ret != MBEDTLS_ERR_ECP_IN_PROGRESS); +#endif + if (send_alert_msg) { + mbedtls_ssl_send_alert_message( + ssl, + MBEDTLS_SSL_ALERT_LEVEL_FATAL, + MBEDTLS_SSL_ALERT_MSG_DECRYPT_ERROR); } -#endif /* MBEDTLS_SSL_ECP_RESTARTABLE_ENABLED */ - mbedtls_ssl_send_alert_message( - ssl, - MBEDTLS_SSL_ALERT_LEVEL_FATAL, - MBEDTLS_SSL_ALERT_MSG_DECRYPT_ERROR); MBEDTLS_SSL_DEBUG_RET(1, "mbedtls_pk_verify", ret); +#if defined(MBEDTLS_SSL_ECP_RESTARTABLE_ENABLED) + if (ret == MBEDTLS_ERR_ECP_IN_PROGRESS) { + ret = MBEDTLS_ERR_SSL_CRYPTO_IN_PROGRESS; + } +#endif return ret; } @@ -3371,6 +2487,11 @@ static int ssl_parse_certificate_request(mbedtls_ssl_context *ssl) size_t cert_type_len = 0, dn_len = 0; const mbedtls_ssl_ciphersuite_t *ciphersuite_info = ssl->handshake->ciphersuite_info; + size_t sig_alg_len; +#if defined(MBEDTLS_DEBUG_C) + unsigned char *sig_alg; + unsigned char *dn; +#endif MBEDTLS_SSL_DEBUG_MSG(2, ("=> parse certificate request")); @@ -3395,12 +2516,13 @@ static int ssl_parse_certificate_request(mbedtls_ssl_context *ssl) } ssl->state++; - ssl->client_auth = (ssl->in_msg[0] == MBEDTLS_SSL_HS_CERTIFICATE_REQUEST); + ssl->handshake->client_auth = + (ssl->in_msg[0] == MBEDTLS_SSL_HS_CERTIFICATE_REQUEST); MBEDTLS_SSL_DEBUG_MSG(3, ("got %s certificate request", - ssl->client_auth ? "a" : "no")); + ssl->handshake->client_auth ? "a" : "no")); - if (ssl->client_auth == 0) { + if (ssl->handshake->client_auth == 0) { /* Current message is probably the ServerHelloDone */ ssl->keep_current_message = 1; goto exit; @@ -3437,7 +2559,7 @@ static int ssl_parse_certificate_request(mbedtls_ssl_context *ssl) MBEDTLS_SSL_DEBUG_MSG(1, ("bad certificate request message")); mbedtls_ssl_send_alert_message(ssl, MBEDTLS_SSL_ALERT_LEVEL_FATAL, MBEDTLS_SSL_ALERT_MSG_DECODE_ERROR); - return MBEDTLS_ERR_SSL_BAD_HS_CERTIFICATE_REQUEST; + return MBEDTLS_ERR_SSL_DECODE_ERROR; } cert_type_len = buf[mbedtls_ssl_hs_hdr_len(ssl)]; n = cert_type_len; @@ -3456,66 +2578,81 @@ static int ssl_parse_certificate_request(mbedtls_ssl_context *ssl) MBEDTLS_SSL_DEBUG_MSG(1, ("bad certificate request message")); mbedtls_ssl_send_alert_message(ssl, MBEDTLS_SSL_ALERT_LEVEL_FATAL, MBEDTLS_SSL_ALERT_MSG_DECODE_ERROR); - return MBEDTLS_ERR_SSL_BAD_HS_CERTIFICATE_REQUEST; + return MBEDTLS_ERR_SSL_DECODE_ERROR; } /* supported_signature_algorithms */ -#if defined(MBEDTLS_SSL_PROTO_TLS1_2) - if (ssl->minor_ver == MBEDTLS_SSL_MINOR_VERSION_3) { - size_t sig_alg_len = - ((buf[mbedtls_ssl_hs_hdr_len(ssl) + 1 + n] << 8) - | (buf[mbedtls_ssl_hs_hdr_len(ssl) + 2 + n])); -#if defined(MBEDTLS_DEBUG_C) - unsigned char *sig_alg; - size_t i; -#endif + sig_alg_len = MBEDTLS_GET_UINT16_BE(buf, mbedtls_ssl_hs_hdr_len(ssl) + 1 + n); - /* - * The furthest access in buf is in the loop few lines below: - * sig_alg[i + 1], - * where: - * sig_alg = buf + ...hdr_len + 3 + n, - * max(i) = sig_alg_len - 1. - * Therefore the furthest access is: - * buf[...hdr_len + 3 + n + sig_alg_len - 1 + 1], - * which reduces to: - * buf[...hdr_len + 3 + n + sig_alg_len], - * which is one less than we need the buf to be. - */ - if (ssl->in_hslen <= mbedtls_ssl_hs_hdr_len(ssl) - + 3 + n + sig_alg_len) { - MBEDTLS_SSL_DEBUG_MSG(1, ("bad certificate request message")); - mbedtls_ssl_send_alert_message( - ssl, - MBEDTLS_SSL_ALERT_LEVEL_FATAL, - MBEDTLS_SSL_ALERT_MSG_DECODE_ERROR); - return MBEDTLS_ERR_SSL_BAD_HS_CERTIFICATE_REQUEST; - } + /* + * The furthest access in buf is in the loop few lines below: + * sig_alg[i + 1], + * where: + * sig_alg = buf + ...hdr_len + 3 + n, + * max(i) = sig_alg_len - 1. + * Therefore the furthest access is: + * buf[...hdr_len + 3 + n + sig_alg_len - 1 + 1], + * which reduces to: + * buf[...hdr_len + 3 + n + sig_alg_len], + * which is one less than we need the buf to be. + */ + if (ssl->in_hslen <= mbedtls_ssl_hs_hdr_len(ssl) + 3 + n + sig_alg_len) { + MBEDTLS_SSL_DEBUG_MSG(1, ("bad certificate request message")); + mbedtls_ssl_send_alert_message( + ssl, + MBEDTLS_SSL_ALERT_LEVEL_FATAL, + MBEDTLS_SSL_ALERT_MSG_DECODE_ERROR); + return MBEDTLS_ERR_SSL_DECODE_ERROR; + } #if defined(MBEDTLS_DEBUG_C) - sig_alg = buf + mbedtls_ssl_hs_hdr_len(ssl) + 3 + n; - for (i = 0; i < sig_alg_len; i += 2) { - MBEDTLS_SSL_DEBUG_MSG(3, - ("Supported Signature Algorithm found: %d,%d", - sig_alg[i], sig_alg[i + 1])); - } + sig_alg = buf + mbedtls_ssl_hs_hdr_len(ssl) + 3 + n; + for (size_t i = 0; i < sig_alg_len; i += 2) { + MBEDTLS_SSL_DEBUG_MSG(3, + ("Supported Signature Algorithm found: %02x %02x", + sig_alg[i], sig_alg[i + 1])); + } #endif - n += 2 + sig_alg_len; - } -#endif /* MBEDTLS_SSL_PROTO_TLS1_2 */ + n += 2 + sig_alg_len; /* certificate_authorities */ - dn_len = ((buf[mbedtls_ssl_hs_hdr_len(ssl) + 1 + n] << 8) - | (buf[mbedtls_ssl_hs_hdr_len(ssl) + 2 + n])); + dn_len = MBEDTLS_GET_UINT16_BE(buf, mbedtls_ssl_hs_hdr_len(ssl) + 1 + n); n += dn_len; if (ssl->in_hslen != mbedtls_ssl_hs_hdr_len(ssl) + 3 + n) { MBEDTLS_SSL_DEBUG_MSG(1, ("bad certificate request message")); mbedtls_ssl_send_alert_message(ssl, MBEDTLS_SSL_ALERT_LEVEL_FATAL, MBEDTLS_SSL_ALERT_MSG_DECODE_ERROR); - return MBEDTLS_ERR_SSL_BAD_HS_CERTIFICATE_REQUEST; + return MBEDTLS_ERR_SSL_DECODE_ERROR; + } + +#if defined(MBEDTLS_DEBUG_C) + dn = buf + mbedtls_ssl_hs_hdr_len(ssl) + 3 + n - dn_len; + for (size_t i = 0, dni_len = 0; i < dn_len; i += 2 + dni_len) { + unsigned char *p = dn + i + 2; + mbedtls_x509_name name; + size_t asn1_len; + char s[MBEDTLS_X509_MAX_DN_NAME_SIZE]; + memset(&name, 0, sizeof(name)); + dni_len = MBEDTLS_GET_UINT16_BE(dn + i, 0); + if (dni_len > dn_len - i - 2 || + mbedtls_asn1_get_tag(&p, p + dni_len, &asn1_len, + MBEDTLS_ASN1_CONSTRUCTED | MBEDTLS_ASN1_SEQUENCE) != 0 || + mbedtls_x509_get_name(&p, p + asn1_len, &name) != 0) { + MBEDTLS_SSL_DEBUG_MSG(1, ("bad certificate request message")); + mbedtls_ssl_send_alert_message( + ssl, + MBEDTLS_SSL_ALERT_LEVEL_FATAL, + MBEDTLS_SSL_ALERT_MSG_DECODE_ERROR); + return MBEDTLS_ERR_SSL_DECODE_ERROR; + } + MBEDTLS_SSL_DEBUG_MSG(3, + ("DN hint: %.*s", + mbedtls_x509_dn_gets(s, sizeof(s), &name), s)); + mbedtls_asn1_free_named_data_list_shallow(name.next); } +#endif exit: MBEDTLS_SSL_DEBUG_MSG(2, ("<= parse certificate request")); @@ -3546,7 +2683,7 @@ static int ssl_parse_server_hello_done(mbedtls_ssl_context *ssl) MBEDTLS_SSL_DEBUG_MSG(1, ("bad server hello done message")); mbedtls_ssl_send_alert_message(ssl, MBEDTLS_SSL_ALERT_LEVEL_FATAL, MBEDTLS_SSL_ALERT_MSG_DECODE_ERROR); - return MBEDTLS_ERR_SSL_BAD_HS_SERVER_HELLO_DONE; + return MBEDTLS_ERR_SSL_DECODE_ERROR; } ssl->state++; @@ -3579,13 +2716,13 @@ static int ssl_write_client_key_exchange(mbedtls_ssl_context *ssl) /* * DHM key exchange -- send G^X mod P */ - content_len = ssl->handshake->dhm_ctx.len; + content_len = mbedtls_dhm_get_len(&ssl->handshake->dhm_ctx); MBEDTLS_PUT_UINT16_BE(content_len, ssl->out_msg, 4); header_len = 6; ret = mbedtls_dhm_make_public(&ssl->handshake->dhm_ctx, - (int) mbedtls_mpi_size(&ssl->handshake->dhm_ctx.P), + (int) mbedtls_dhm_get_len(&ssl->handshake->dhm_ctx), &ssl->out_msg[header_len], content_len, ssl->conf->f_rng, ssl->conf->p_rng); if (ret != 0) { @@ -3608,22 +2745,21 @@ static int ssl_write_client_key_exchange(mbedtls_ssl_context *ssl) MBEDTLS_SSL_DEBUG_MPI(3, "DHM: K ", &ssl->handshake->dhm_ctx.K); } else #endif /* MBEDTLS_KEY_EXCHANGE_DHE_RSA_ENABLED */ -#if defined(MBEDTLS_USE_PSA_CRYPTO) && \ - (defined(MBEDTLS_KEY_EXCHANGE_ECDHE_RSA_ENABLED) || \ - defined(MBEDTLS_KEY_EXCHANGE_ECDHE_ECDSA_ENABLED)) +#if defined(MBEDTLS_KEY_EXCHANGE_ECDHE_RSA_ENABLED) || \ + defined(MBEDTLS_KEY_EXCHANGE_ECDHE_ECDSA_ENABLED) || \ + defined(MBEDTLS_KEY_EXCHANGE_ECDH_RSA_ENABLED) || \ + defined(MBEDTLS_KEY_EXCHANGE_ECDH_ECDSA_ENABLED) if (ciphersuite_info->key_exchange == MBEDTLS_KEY_EXCHANGE_ECDHE_RSA || - ciphersuite_info->key_exchange == MBEDTLS_KEY_EXCHANGE_ECDHE_ECDSA) { + ciphersuite_info->key_exchange == MBEDTLS_KEY_EXCHANGE_ECDHE_ECDSA || + ciphersuite_info->key_exchange == MBEDTLS_KEY_EXCHANGE_ECDH_RSA || + ciphersuite_info->key_exchange == MBEDTLS_KEY_EXCHANGE_ECDH_ECDSA) { +#if defined(MBEDTLS_USE_PSA_CRYPTO) psa_status_t status = PSA_ERROR_CORRUPTION_DETECTED; psa_status_t destruction_status = PSA_ERROR_CORRUPTION_DETECTED; psa_key_attributes_t key_attributes; mbedtls_ssl_handshake_params *handshake = ssl->handshake; - unsigned char own_pubkey[MBEDTLS_PSA_MAX_EC_PUBKEY_LENGTH]; - size_t own_pubkey_len; - unsigned char *own_pubkey_ecpoint; - size_t own_pubkey_ecpoint_len; - header_len = 4; MBEDTLS_SSL_DEBUG_MSG(1, ("Perform PSA-based ECDH computation.")); @@ -3642,71 +2778,54 @@ static int ssl_write_client_key_exchange(mbedtls_ssl_context *ssl) key_attributes = psa_key_attributes_init(); psa_set_key_usage_flags(&key_attributes, PSA_KEY_USAGE_DERIVE); psa_set_key_algorithm(&key_attributes, PSA_ALG_ECDH); - psa_set_key_type(&key_attributes, handshake->ecdh_psa_type); - psa_set_key_bits(&key_attributes, handshake->ecdh_bits); + psa_set_key_type(&key_attributes, handshake->xxdh_psa_type); + psa_set_key_bits(&key_attributes, handshake->xxdh_psa_bits); /* Generate ECDH private key. */ status = psa_generate_key(&key_attributes, - &handshake->ecdh_psa_privkey); + &handshake->xxdh_psa_privkey); if (status != PSA_SUCCESS) { return MBEDTLS_ERR_SSL_HW_ACCEL_FAILED; } - /* Export the public part of the ECDH private key from PSA - * and convert it to ECPoint format used in ClientKeyExchange. */ - status = psa_export_public_key(handshake->ecdh_psa_privkey, - own_pubkey, sizeof(own_pubkey), + /* Export the public part of the ECDH private key from PSA. + * The export format is an ECPoint structure as expected by TLS, + * but we just need to add a length byte before that. */ + unsigned char *own_pubkey = ssl->out_msg + header_len + 1; + unsigned char *end = ssl->out_msg + MBEDTLS_SSL_OUT_CONTENT_LEN; + size_t own_pubkey_max_len = (size_t) (end - own_pubkey); + size_t own_pubkey_len; + + status = psa_export_public_key(handshake->xxdh_psa_privkey, + own_pubkey, own_pubkey_max_len, &own_pubkey_len); if (status != PSA_SUCCESS) { - psa_destroy_key(handshake->ecdh_psa_privkey); - handshake->ecdh_psa_privkey = MBEDTLS_SVC_KEY_ID_INIT; - return MBEDTLS_ERR_SSL_HW_ACCEL_FAILED; - } - - if (mbedtls_psa_tls_psa_ec_to_ecpoint(own_pubkey, - own_pubkey_len, - &own_pubkey_ecpoint, - &own_pubkey_ecpoint_len) != 0) { - psa_destroy_key(handshake->ecdh_psa_privkey); - handshake->ecdh_psa_privkey = MBEDTLS_SVC_KEY_ID_INIT; + psa_destroy_key(handshake->xxdh_psa_privkey); + handshake->xxdh_psa_privkey = MBEDTLS_SVC_KEY_ID_INIT; return MBEDTLS_ERR_SSL_HW_ACCEL_FAILED; } - /* Copy ECPoint structure to outgoing message buffer. */ - ssl->out_msg[header_len] = (unsigned char) own_pubkey_ecpoint_len; - memcpy(ssl->out_msg + header_len + 1, - own_pubkey_ecpoint, own_pubkey_ecpoint_len); - content_len = own_pubkey_ecpoint_len + 1; + ssl->out_msg[header_len] = (unsigned char) own_pubkey_len; + content_len = own_pubkey_len + 1; /* The ECDH secret is the premaster secret used for key derivation. */ /* Compute ECDH shared secret. */ status = psa_raw_key_agreement(PSA_ALG_ECDH, - handshake->ecdh_psa_privkey, - handshake->ecdh_psa_peerkey, - handshake->ecdh_psa_peerkey_len, + handshake->xxdh_psa_privkey, + handshake->xxdh_psa_peerkey, + handshake->xxdh_psa_peerkey_len, ssl->handshake->premaster, sizeof(ssl->handshake->premaster), &ssl->handshake->pmslen); - destruction_status = psa_destroy_key(handshake->ecdh_psa_privkey); - handshake->ecdh_psa_privkey = MBEDTLS_SVC_KEY_ID_INIT; + destruction_status = psa_destroy_key(handshake->xxdh_psa_privkey); + handshake->xxdh_psa_privkey = MBEDTLS_SVC_KEY_ID_INIT; if (status != PSA_SUCCESS || destruction_status != PSA_SUCCESS) { return MBEDTLS_ERR_SSL_HW_ACCEL_FAILED; } - } else -#endif /* MBEDTLS_USE_PSA_CRYPTO && - ( MBEDTLS_KEY_EXCHANGE_ECDHE_RSA_ENABLED || - MBEDTLS_KEY_EXCHANGE_ECDHE_ECDSA_ENABLED ) */ -#if defined(MBEDTLS_KEY_EXCHANGE_ECDHE_RSA_ENABLED) || \ - defined(MBEDTLS_KEY_EXCHANGE_ECDHE_ECDSA_ENABLED) || \ - defined(MBEDTLS_KEY_EXCHANGE_ECDH_RSA_ENABLED) || \ - defined(MBEDTLS_KEY_EXCHANGE_ECDH_ECDSA_ENABLED) - if (ciphersuite_info->key_exchange == MBEDTLS_KEY_EXCHANGE_ECDHE_RSA || - ciphersuite_info->key_exchange == MBEDTLS_KEY_EXCHANGE_ECDHE_ECDSA || - ciphersuite_info->key_exchange == MBEDTLS_KEY_EXCHANGE_ECDH_RSA || - ciphersuite_info->key_exchange == MBEDTLS_KEY_EXCHANGE_ECDH_ECDSA) { +#else /* * ECDH key exchange -- send client public value */ @@ -3766,17 +2885,144 @@ static int ssl_write_client_key_exchange(mbedtls_ssl_context *ssl) MBEDTLS_SSL_DEBUG_ECDH(3, &ssl->handshake->ecdh_ctx, MBEDTLS_DEBUG_ECDH_Z); +#endif /* MBEDTLS_USE_PSA_CRYPTO */ } else #endif /* MBEDTLS_KEY_EXCHANGE_ECDHE_RSA_ENABLED || MBEDTLS_KEY_EXCHANGE_ECDHE_ECDSA_ENABLED || MBEDTLS_KEY_EXCHANGE_ECDH_RSA_ENABLED || MBEDTLS_KEY_EXCHANGE_ECDH_ECDSA_ENABLED */ +#if defined(MBEDTLS_USE_PSA_CRYPTO) && \ + defined(MBEDTLS_KEY_EXCHANGE_ECDHE_PSK_ENABLED) + if (ciphersuite_info->key_exchange == MBEDTLS_KEY_EXCHANGE_ECDHE_PSK) { + psa_status_t status = PSA_ERROR_CORRUPTION_DETECTED; + psa_status_t destruction_status = PSA_ERROR_CORRUPTION_DETECTED; + psa_key_attributes_t key_attributes; + + mbedtls_ssl_handshake_params *handshake = ssl->handshake; + + /* + * opaque psk_identity<0..2^16-1>; + */ + if (mbedtls_ssl_conf_has_static_psk(ssl->conf) == 0) { + /* We don't offer PSK suites if we don't have a PSK, + * and we check that the server's choice is among the + * ciphersuites we offered, so this should never happen. */ + return MBEDTLS_ERR_SSL_INTERNAL_ERROR; + } + + /* uint16 to store content length */ + const size_t content_len_size = 2; + + header_len = 4; + + if (header_len + content_len_size + ssl->conf->psk_identity_len + > MBEDTLS_SSL_OUT_CONTENT_LEN) { + MBEDTLS_SSL_DEBUG_MSG(1, + ("psk identity too long or SSL buffer too short")); + return MBEDTLS_ERR_SSL_BUFFER_TOO_SMALL; + } + + unsigned char *p = ssl->out_msg + header_len; + + *p++ = MBEDTLS_BYTE_1(ssl->conf->psk_identity_len); + *p++ = MBEDTLS_BYTE_0(ssl->conf->psk_identity_len); + header_len += content_len_size; + + memcpy(p, ssl->conf->psk_identity, + ssl->conf->psk_identity_len); + p += ssl->conf->psk_identity_len; + + header_len += ssl->conf->psk_identity_len; + + MBEDTLS_SSL_DEBUG_MSG(1, ("Perform PSA-based ECDH computation.")); + + /* + * Generate EC private key for ECDHE exchange. + */ + + /* The master secret is obtained from the shared ECDH secret by + * applying the TLS 1.2 PRF with a specific salt and label. While + * the PSA Crypto API encourages combining key agreement schemes + * such as ECDH with fixed KDFs such as TLS 1.2 PRF, it does not + * yet support the provisioning of salt + label to the KDF. + * For the time being, we therefore need to split the computation + * of the ECDH secret and the application of the TLS 1.2 PRF. */ + key_attributes = psa_key_attributes_init(); + psa_set_key_usage_flags(&key_attributes, PSA_KEY_USAGE_DERIVE); + psa_set_key_algorithm(&key_attributes, PSA_ALG_ECDH); + psa_set_key_type(&key_attributes, handshake->xxdh_psa_type); + psa_set_key_bits(&key_attributes, handshake->xxdh_psa_bits); + + /* Generate ECDH private key. */ + status = psa_generate_key(&key_attributes, + &handshake->xxdh_psa_privkey); + if (status != PSA_SUCCESS) { + return PSA_TO_MBEDTLS_ERR(status); + } + + /* Export the public part of the ECDH private key from PSA. + * The export format is an ECPoint structure as expected by TLS, + * but we just need to add a length byte before that. */ + unsigned char *own_pubkey = p + 1; + unsigned char *end = ssl->out_msg + MBEDTLS_SSL_OUT_CONTENT_LEN; + size_t own_pubkey_max_len = (size_t) (end - own_pubkey); + size_t own_pubkey_len = 0; + + status = psa_export_public_key(handshake->xxdh_psa_privkey, + own_pubkey, own_pubkey_max_len, + &own_pubkey_len); + if (status != PSA_SUCCESS) { + psa_destroy_key(handshake->xxdh_psa_privkey); + handshake->xxdh_psa_privkey = MBEDTLS_SVC_KEY_ID_INIT; + return PSA_TO_MBEDTLS_ERR(status); + } + + *p = (unsigned char) own_pubkey_len; + content_len = own_pubkey_len + 1; + + /* As RFC 5489 section 2, the premaster secret is formed as follows: + * - a uint16 containing the length (in octets) of the ECDH computation + * - the octet string produced by the ECDH computation + * - a uint16 containing the length (in octets) of the PSK + * - the PSK itself + */ + unsigned char *pms = ssl->handshake->premaster; + const unsigned char * const pms_end = pms + + sizeof(ssl->handshake->premaster); + /* uint16 to store length (in octets) of the ECDH computation */ + const size_t zlen_size = 2; + size_t zlen = 0; + + /* Perform ECDH computation after the uint16 reserved for the length */ + status = psa_raw_key_agreement(PSA_ALG_ECDH, + handshake->xxdh_psa_privkey, + handshake->xxdh_psa_peerkey, + handshake->xxdh_psa_peerkey_len, + pms + zlen_size, + pms_end - (pms + zlen_size), + &zlen); + + destruction_status = psa_destroy_key(handshake->xxdh_psa_privkey); + handshake->xxdh_psa_privkey = MBEDTLS_SVC_KEY_ID_INIT; + + if (status != PSA_SUCCESS) { + return PSA_TO_MBEDTLS_ERR(status); + } else if (destruction_status != PSA_SUCCESS) { + return PSA_TO_MBEDTLS_ERR(destruction_status); + } + + /* Write the ECDH computation length before the ECDH computation */ + MBEDTLS_PUT_UINT16_BE(zlen, pms, 0); + pms += zlen_size + zlen; + } else +#endif /* MBEDTLS_USE_PSA_CRYPTO && + MBEDTLS_KEY_EXCHANGE_ECDHE_PSK_ENABLED */ #if defined(MBEDTLS_KEY_EXCHANGE_SOME_PSK_ENABLED) if (mbedtls_ssl_ciphersuite_uses_psk(ciphersuite_info)) { /* * opaque psk_identity<0..2^16-1>; */ - if (ssl_conf_has_static_psk(ssl->conf) == 0) { + if (mbedtls_ssl_conf_has_static_psk(ssl->conf) == 0) { /* We don't offer PSK suites if we don't have a PSK, * and we check that the server's choice is among the * ciphersuites we offered, so this should never happen. */ @@ -3807,14 +3053,6 @@ static int ssl_write_client_key_exchange(mbedtls_ssl_context *ssl) #endif #if defined(MBEDTLS_KEY_EXCHANGE_RSA_PSK_ENABLED) if (ciphersuite_info->key_exchange == MBEDTLS_KEY_EXCHANGE_RSA_PSK) { -#if defined(MBEDTLS_USE_PSA_CRYPTO) - /* Opaque PSKs are currently only supported for PSK-only suites. */ - if (ssl_conf_has_static_raw_psk(ssl->conf) == 0) { - MBEDTLS_SSL_DEBUG_MSG(1, ("opaque PSK not supported with RSA-PSK")); - return MBEDTLS_ERR_SSL_FEATURE_UNAVAILABLE; - } -#endif /* MBEDTLS_USE_PSA_CRYPTO */ - if ((ret = ssl_write_encrypted_pms(ssl, header_len, &content_len, 2)) != 0) { return ret; @@ -3823,18 +3061,10 @@ static int ssl_write_client_key_exchange(mbedtls_ssl_context *ssl) #endif #if defined(MBEDTLS_KEY_EXCHANGE_DHE_PSK_ENABLED) if (ciphersuite_info->key_exchange == MBEDTLS_KEY_EXCHANGE_DHE_PSK) { -#if defined(MBEDTLS_USE_PSA_CRYPTO) - /* Opaque PSKs are currently only supported for PSK-only suites. */ - if (ssl_conf_has_static_raw_psk(ssl->conf) == 0) { - MBEDTLS_SSL_DEBUG_MSG(1, ("opaque PSK not supported with DHE-PSK")); - return MBEDTLS_ERR_SSL_FEATURE_UNAVAILABLE; - } -#endif /* MBEDTLS_USE_PSA_CRYPTO */ - /* * ClientDiffieHellmanPublic public (DHM send G^X mod P) */ - content_len = ssl->handshake->dhm_ctx.len; + content_len = mbedtls_dhm_get_len(&ssl->handshake->dhm_ctx); if (header_len + 2 + content_len > MBEDTLS_SSL_OUT_CONTENT_LEN) { @@ -3847,25 +3077,36 @@ static int ssl_write_client_key_exchange(mbedtls_ssl_context *ssl) ssl->out_msg[header_len++] = MBEDTLS_BYTE_0(content_len); ret = mbedtls_dhm_make_public(&ssl->handshake->dhm_ctx, - (int) mbedtls_mpi_size(&ssl->handshake->dhm_ctx.P), + (int) mbedtls_dhm_get_len(&ssl->handshake->dhm_ctx), &ssl->out_msg[header_len], content_len, ssl->conf->f_rng, ssl->conf->p_rng); if (ret != 0) { MBEDTLS_SSL_DEBUG_RET(1, "mbedtls_dhm_make_public", ret); return ret; } - } else -#endif /* MBEDTLS_KEY_EXCHANGE_DHE_PSK_ENABLED */ -#if defined(MBEDTLS_KEY_EXCHANGE_ECDHE_PSK_ENABLED) - if (ciphersuite_info->key_exchange == MBEDTLS_KEY_EXCHANGE_ECDHE_PSK) { + #if defined(MBEDTLS_USE_PSA_CRYPTO) - /* Opaque PSKs are currently only supported for PSK-only suites. */ - if (ssl_conf_has_static_raw_psk(ssl->conf) == 0) { - MBEDTLS_SSL_DEBUG_MSG(1, ("opaque PSK not supported with ECDHE-PSK")); - return MBEDTLS_ERR_SSL_FEATURE_UNAVAILABLE; + unsigned char *pms = ssl->handshake->premaster; + unsigned char *pms_end = pms + sizeof(ssl->handshake->premaster); + size_t pms_len; + + /* Write length only when we know the actual value */ + if ((ret = mbedtls_dhm_calc_secret(&ssl->handshake->dhm_ctx, + pms + 2, pms_end - (pms + 2), &pms_len, + ssl->conf->f_rng, ssl->conf->p_rng)) != 0) { + MBEDTLS_SSL_DEBUG_RET(1, "mbedtls_dhm_calc_secret", ret); + return ret; } -#endif /* MBEDTLS_USE_PSA_CRYPTO */ + MBEDTLS_PUT_UINT16_BE(pms_len, pms, 0); + pms += 2 + pms_len; + MBEDTLS_SSL_DEBUG_MPI(3, "DHM: K ", &ssl->handshake->dhm_ctx.K); +#endif + } else +#endif /* MBEDTLS_KEY_EXCHANGE_DHE_PSK_ENABLED */ +#if !defined(MBEDTLS_USE_PSA_CRYPTO) && \ + defined(MBEDTLS_KEY_EXCHANGE_ECDHE_PSK_ENABLED) + if (ciphersuite_info->key_exchange == MBEDTLS_KEY_EXCHANGE_ECDHE_PSK) { /* * ClientECDiffieHellmanPublic public; */ @@ -3882,28 +3123,21 @@ static int ssl_write_client_key_exchange(mbedtls_ssl_context *ssl) MBEDTLS_SSL_DEBUG_ECDH(3, &ssl->handshake->ecdh_ctx, MBEDTLS_DEBUG_ECDH_Q); } else -#endif /* MBEDTLS_KEY_EXCHANGE_ECDHE_PSK_ENABLED */ +#endif /* !MBEDTLS_USE_PSA_CRYPTO && MBEDTLS_KEY_EXCHANGE_ECDHE_PSK_ENABLED */ { MBEDTLS_SSL_DEBUG_MSG(1, ("should never happen")); return MBEDTLS_ERR_SSL_INTERNAL_ERROR; } -#if defined(MBEDTLS_USE_PSA_CRYPTO) && \ - defined(MBEDTLS_KEY_EXCHANGE_PSK_ENABLED) - if (ciphersuite_info->key_exchange == MBEDTLS_KEY_EXCHANGE_PSK && - ssl->minor_ver == MBEDTLS_SSL_MINOR_VERSION_3 && - ssl_conf_has_static_raw_psk(ssl->conf) == 0) { - MBEDTLS_SSL_DEBUG_MSG(1, - ("skip PMS generation for opaque PSK")); - } else -#endif /* MBEDTLS_USE_PSA_CRYPTO && - MBEDTLS_KEY_EXCHANGE_PSK_ENABLED */ +#if !defined(MBEDTLS_USE_PSA_CRYPTO) if ((ret = mbedtls_ssl_psk_derive_premaster(ssl, - ciphersuite_info->key_exchange)) != 0) { + (mbedtls_key_exchange_type_t) ciphersuite_info-> + key_exchange)) != 0) { MBEDTLS_SSL_DEBUG_RET(1, "mbedtls_ssl_psk_derive_premaster", ret); return ret; } +#endif /* !MBEDTLS_USE_PSA_CRYPTO */ } else #endif /* MBEDTLS_KEY_EXCHANGE_SOME_PSK_ENABLED */ #if defined(MBEDTLS_KEY_EXCHANGE_RSA_ENABLED) @@ -3919,6 +3153,20 @@ static int ssl_write_client_key_exchange(mbedtls_ssl_context *ssl) if (ciphersuite_info->key_exchange == MBEDTLS_KEY_EXCHANGE_ECJPAKE) { header_len = 4; +#if defined(MBEDTLS_USE_PSA_CRYPTO) + unsigned char *out_p = ssl->out_msg + header_len; + unsigned char *end_p = ssl->out_msg + MBEDTLS_SSL_OUT_CONTENT_LEN - + header_len; + ret = mbedtls_psa_ecjpake_write_round(&ssl->handshake->psa_pake_ctx, + out_p, end_p - out_p, &content_len, + MBEDTLS_ECJPAKE_ROUND_TWO); + if (ret != 0) { + psa_destroy_key(ssl->handshake->psa_pake_password); + psa_pake_abort(&ssl->handshake->psa_pake_ctx); + MBEDTLS_SSL_DEBUG_RET(1, "psa_pake_output", ret); + return ret; + } +#else ret = mbedtls_ecjpake_write_round_two(&ssl->handshake->ecjpake_ctx, ssl->out_msg + header_len, MBEDTLS_SSL_OUT_CONTENT_LEN - header_len, @@ -3936,6 +3184,7 @@ static int ssl_write_client_key_exchange(mbedtls_ssl_context *ssl) MBEDTLS_SSL_DEBUG_RET(1, "mbedtls_ecjpake_derive_secret", ret); return ret; } +#endif /* MBEDTLS_USE_PSA_CRYPTO */ } else #endif /* MBEDTLS_KEY_EXCHANGE_RSA_ENABLED */ { @@ -3997,6 +3246,11 @@ static int ssl_write_certificate_verify(mbedtls_ssl_context *ssl) mbedtls_md_type_t md_alg = MBEDTLS_MD_NONE; size_t hashlen; void *rs_ctx = NULL; +#if defined(MBEDTLS_SSL_VARIABLE_BUFFER_LENGTH) + size_t out_buf_len = ssl->out_buf_len - (size_t) (ssl->out_msg - ssl->out_buf); +#else + size_t out_buf_len = MBEDTLS_SSL_OUT_BUFFER_LEN - (size_t) (ssl->out_msg - ssl->out_buf); +#endif MBEDTLS_SSL_DEBUG_MSG(2, ("=> write certificate verify")); @@ -4018,7 +3272,8 @@ static int ssl_write_certificate_verify(mbedtls_ssl_context *ssl) return 0; } - if (ssl->client_auth == 0 || mbedtls_ssl_own_cert(ssl) == NULL) { + if (ssl->handshake->client_auth == 0 || + mbedtls_ssl_own_cert(ssl) == NULL) { MBEDTLS_SSL_DEBUG_MSG(2, ("<= skip write certificate verify")); ssl->state++; return 0; @@ -4040,72 +3295,40 @@ static int ssl_write_certificate_verify(mbedtls_ssl_context *ssl) sign: #endif - ssl->handshake->calc_verify(ssl, hash, &hashlen); - -#if defined(MBEDTLS_SSL_PROTO_SSL3) || defined(MBEDTLS_SSL_PROTO_TLS1) || \ - defined(MBEDTLS_SSL_PROTO_TLS1_1) - if (ssl->minor_ver != MBEDTLS_SSL_MINOR_VERSION_3) { - /* - * digitally-signed struct { - * opaque md5_hash[16]; - * opaque sha_hash[20]; - * }; - * - * md5_hash - * MD5(handshake_messages); - * - * sha_hash - * SHA(handshake_messages); - */ - md_alg = MBEDTLS_MD_NONE; - - /* - * For ECDSA, default hash is SHA-1 only - */ - if (mbedtls_pk_can_do(mbedtls_ssl_own_key(ssl), MBEDTLS_PK_ECDSA)) { - hash_start += 16; - hashlen -= 16; - md_alg = MBEDTLS_MD_SHA1; - } - } else -#endif /* MBEDTLS_SSL_PROTO_SSL3 || MBEDTLS_SSL_PROTO_TLS1 || \ - MBEDTLS_SSL_PROTO_TLS1_1 */ -#if defined(MBEDTLS_SSL_PROTO_TLS1_2) - if (ssl->minor_ver == MBEDTLS_SSL_MINOR_VERSION_3) { - /* - * digitally-signed struct { - * opaque handshake_messages[handshake_messages_length]; - * }; - * - * Taking shortcut here. We assume that the server always allows the - * PRF Hash function and has sent it in the allowed signature - * algorithms list received in the Certificate Request message. - * - * Until we encounter a server that does not, we will take this - * shortcut. - * - * Reason: Otherwise we should have running hashes for SHA512 and - * SHA224 in order to satisfy 'weird' needs from the server - * side. - */ - if (ssl->handshake->ciphersuite_info->mac == MBEDTLS_MD_SHA384) { - md_alg = MBEDTLS_MD_SHA384; - ssl->out_msg[4] = MBEDTLS_SSL_HASH_SHA384; - } else { - md_alg = MBEDTLS_MD_SHA256; - ssl->out_msg[4] = MBEDTLS_SSL_HASH_SHA256; - } - ssl->out_msg[5] = mbedtls_ssl_sig_from_pk(mbedtls_ssl_own_key(ssl)); + ret = ssl->handshake->calc_verify(ssl, hash, &hashlen); + if (0 != ret) { + MBEDTLS_SSL_DEBUG_RET(1, ("calc_verify"), ret); + return ret; + } - /* Info from md_alg will be used instead */ - hashlen = 0; - offset = 2; - } else -#endif /* MBEDTLS_SSL_PROTO_TLS1_2 */ - { - MBEDTLS_SSL_DEBUG_MSG(1, ("should never happen")); - return MBEDTLS_ERR_SSL_INTERNAL_ERROR; + /* + * digitally-signed struct { + * opaque handshake_messages[handshake_messages_length]; + * }; + * + * Taking shortcut here. We assume that the server always allows the + * PRF Hash function and has sent it in the allowed signature + * algorithms list received in the Certificate Request message. + * + * Until we encounter a server that does not, we will take this + * shortcut. + * + * Reason: Otherwise we should have running hashes for SHA512 and + * SHA224 in order to satisfy 'weird' needs from the server + * side. + */ + if (ssl->handshake->ciphersuite_info->mac == MBEDTLS_MD_SHA384) { + md_alg = MBEDTLS_MD_SHA384; + ssl->out_msg[4] = MBEDTLS_SSL_HASH_SHA384; + } else { + md_alg = MBEDTLS_MD_SHA256; + ssl->out_msg[4] = MBEDTLS_SSL_HASH_SHA256; } + ssl->out_msg[5] = mbedtls_ssl_sig_from_pk(mbedtls_ssl_own_key(ssl)); + + /* Info from md_alg will be used instead */ + hashlen = 0; + offset = 2; #if defined(MBEDTLS_SSL_ECP_RESTARTABLE_ENABLED) if (ssl->handshake->ecrs_enabled) { @@ -4115,7 +3338,9 @@ static int ssl_write_certificate_verify(mbedtls_ssl_context *ssl) if ((ret = mbedtls_pk_sign_restartable(mbedtls_ssl_own_key(ssl), md_alg, hash_start, hashlen, - ssl->out_msg + 6 + offset, &n, + ssl->out_msg + 6 + offset, + out_buf_len - 6 - offset, + &n, ssl->conf->f_rng, ssl->conf->p_rng, rs_ctx)) != 0) { MBEDTLS_SSL_DEBUG_RET(1, "mbedtls_pk_sign", ret); #if defined(MBEDTLS_SSL_ECP_RESTARTABLE_ENABLED) @@ -4186,21 +3411,20 @@ static int ssl_parse_new_session_ticket(mbedtls_ssl_context *ssl) MBEDTLS_SSL_DEBUG_MSG(1, ("bad new session ticket message")); mbedtls_ssl_send_alert_message(ssl, MBEDTLS_SSL_ALERT_LEVEL_FATAL, MBEDTLS_SSL_ALERT_MSG_DECODE_ERROR); - return MBEDTLS_ERR_SSL_BAD_HS_NEW_SESSION_TICKET; + return MBEDTLS_ERR_SSL_DECODE_ERROR; } msg = ssl->in_msg + mbedtls_ssl_hs_hdr_len(ssl); - lifetime = (((uint32_t) msg[0]) << 24) | (msg[1] << 16) | - (msg[2] << 8) | (msg[3]); + lifetime = MBEDTLS_GET_UINT32_BE(msg, 0); - ticket_len = (msg[4] << 8) | (msg[5]); + ticket_len = MBEDTLS_GET_UINT16_BE(msg, 4); if (ticket_len + 6 + mbedtls_ssl_hs_hdr_len(ssl) != ssl->in_hslen) { MBEDTLS_SSL_DEBUG_MSG(1, ("bad new session ticket message")); mbedtls_ssl_send_alert_message(ssl, MBEDTLS_SSL_ALERT_LEVEL_FATAL, MBEDTLS_SSL_ALERT_MSG_DECODE_ERROR); - return MBEDTLS_ERR_SSL_BAD_HS_NEW_SESSION_TICKET; + return MBEDTLS_ERR_SSL_DECODE_ERROR; } MBEDTLS_SSL_DEBUG_MSG(3, ("ticket length: %" MBEDTLS_PRINTF_SIZET, ticket_len)); @@ -4218,16 +3442,14 @@ static int ssl_parse_new_session_ticket(mbedtls_ssl_context *ssl) } if (ssl->session != NULL && ssl->session->ticket != NULL) { - mbedtls_platform_zeroize(ssl->session->ticket, + mbedtls_zeroize_and_free(ssl->session->ticket, ssl->session->ticket_len); - mbedtls_free(ssl->session->ticket); ssl->session->ticket = NULL; ssl->session->ticket_len = 0; } - mbedtls_platform_zeroize(ssl->session_negotiate->ticket, + mbedtls_zeroize_and_free(ssl->session_negotiate->ticket, ssl->session_negotiate->ticket_len); - mbedtls_free(ssl->session_negotiate->ticket); ssl->session_negotiate->ticket = NULL; ssl->session_negotiate->ticket_len = 0; @@ -4265,31 +3487,12 @@ int mbedtls_ssl_handshake_client_step(mbedtls_ssl_context *ssl) { int ret = 0; - if (ssl->state == MBEDTLS_SSL_HANDSHAKE_OVER || ssl->handshake == NULL) { - return MBEDTLS_ERR_SSL_BAD_INPUT_DATA; - } - - MBEDTLS_SSL_DEBUG_MSG(2, ("client state: %d", ssl->state)); - - if ((ret = mbedtls_ssl_flush_output(ssl)) != 0) { - return ret; - } - -#if defined(MBEDTLS_SSL_PROTO_DTLS) - if (ssl->conf->transport == MBEDTLS_SSL_TRANSPORT_DATAGRAM && - ssl->handshake->retransmit_state == MBEDTLS_SSL_RETRANS_SENDING) { - if ((ret = mbedtls_ssl_flight_transmit(ssl)) != 0) { - return ret; - } - } -#endif /* MBEDTLS_SSL_PROTO_DTLS */ - /* Change state now, so that it is right in mbedtls_ssl_read_record(), used * by DTLS for dropping out-of-sequence ChangeCipherSpec records */ #if defined(MBEDTLS_SSL_SESSION_TICKETS) if (ssl->state == MBEDTLS_SSL_SERVER_CHANGE_CIPHER_SPEC && ssl->handshake->new_session_ticket != 0) { - ssl->state = MBEDTLS_SSL_SERVER_NEW_SESSION_TICKET; + ssl->state = MBEDTLS_SSL_NEW_SESSION_TICKET; } #endif @@ -4302,7 +3505,7 @@ int mbedtls_ssl_handshake_client_step(mbedtls_ssl_context *ssl) * ==> ClientHello */ case MBEDTLS_SSL_CLIENT_HELLO: - ret = ssl_write_client_hello(ssl); + ret = mbedtls_ssl_write_client_hello(ssl); break; /* @@ -4365,7 +3568,7 @@ int mbedtls_ssl_handshake_client_step(mbedtls_ssl_context *ssl) * Finished */ #if defined(MBEDTLS_SSL_SESSION_TICKETS) - case MBEDTLS_SSL_SERVER_NEW_SESSION_TICKET: + case MBEDTLS_SSL_NEW_SESSION_TICKET: ret = ssl_parse_new_session_ticket(ssl); break; #endif @@ -4394,4 +3597,5 @@ int mbedtls_ssl_handshake_client_step(mbedtls_ssl_context *ssl) return ret; } -#endif /* MBEDTLS_SSL_CLI_C */ + +#endif /* MBEDTLS_SSL_CLI_C && MBEDTLS_SSL_PROTO_TLS1_2 */ diff --git a/vendor/mbedtls/library/ssl_srv.c b/vendor/mbedtls/library/ssl_tls12_server.c similarity index 68% rename from vendor/mbedtls/library/ssl_srv.c rename to vendor/mbedtls/library/ssl_tls12_server.c index 994661a44c..b49a8ae6a6 100644 --- a/vendor/mbedtls/library/ssl_srv.c +++ b/vendor/mbedtls/library/ssl_tls12_server.c @@ -1,31 +1,19 @@ /* - * SSLv3/TLSv1 server-side functions + * TLS server-side functions * * Copyright The Mbed TLS Contributors - * SPDX-License-Identifier: Apache-2.0 - * - * Licensed under the Apache License, Version 2.0 (the "License"); you may - * not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT - * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. + * SPDX-License-Identifier: Apache-2.0 OR GPL-2.0-or-later */ #include "common.h" -#if defined(MBEDTLS_SSL_SRV_C) +#if defined(MBEDTLS_SSL_SRV_C) && defined(MBEDTLS_SSL_PROTO_TLS1_2) #include "mbedtls/platform.h" #include "mbedtls/ssl.h" -#include "mbedtls/ssl_internal.h" -#include "mbedtls/debug.h" +#include "ssl_misc.h" +#include "debug_internal.h" #include "mbedtls/error.h" #include "mbedtls/platform_util.h" #include "constant_time_internal.h" @@ -33,6 +21,21 @@ #include +#if defined(MBEDTLS_USE_PSA_CRYPTO) +/* Define a local translating function to save code size by not using too many + * arguments in each translating place. */ +#if defined(MBEDTLS_KEY_EXCHANGE_SOME_ECDH_ENABLED) || \ + defined(MBEDTLS_KEY_EXCHANGE_SOME_ECDHE_ENABLED) +static int local_err_translation(psa_status_t status) +{ + return psa_status_to_mbedtls(status, psa_to_ssl_errors, + ARRAY_LENGTH(psa_to_ssl_errors), + psa_generic_status_to_mbedtls); +} +#define PSA_TO_MBEDTLS_ERR(status) local_err_translation(status) +#endif +#endif + #if defined(MBEDTLS_ECP_C) #include "mbedtls/ecp.h" #endif @@ -73,69 +76,6 @@ void mbedtls_ssl_conf_dtls_cookies(mbedtls_ssl_config *conf, } #endif /* MBEDTLS_SSL_DTLS_HELLO_VERIFY */ -#if defined(MBEDTLS_SSL_SERVER_NAME_INDICATION) -MBEDTLS_CHECK_RETURN_CRITICAL -static int ssl_parse_servername_ext(mbedtls_ssl_context *ssl, - const unsigned char *buf, - size_t len) -{ - int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED; - size_t servername_list_size, hostname_len; - const unsigned char *p; - - MBEDTLS_SSL_DEBUG_MSG(3, ("parse ServerName extension")); - - if (len < 2) { - MBEDTLS_SSL_DEBUG_MSG(1, ("bad client hello message")); - mbedtls_ssl_send_alert_message(ssl, MBEDTLS_SSL_ALERT_LEVEL_FATAL, - MBEDTLS_SSL_ALERT_MSG_DECODE_ERROR); - return MBEDTLS_ERR_SSL_BAD_HS_CLIENT_HELLO; - } - servername_list_size = ((buf[0] << 8) | (buf[1])); - if (servername_list_size + 2 != len) { - MBEDTLS_SSL_DEBUG_MSG(1, ("bad client hello message")); - mbedtls_ssl_send_alert_message(ssl, MBEDTLS_SSL_ALERT_LEVEL_FATAL, - MBEDTLS_SSL_ALERT_MSG_DECODE_ERROR); - return MBEDTLS_ERR_SSL_BAD_HS_CLIENT_HELLO; - } - - p = buf + 2; - while (servername_list_size > 2) { - hostname_len = ((p[1] << 8) | p[2]); - if (hostname_len + 3 > servername_list_size) { - MBEDTLS_SSL_DEBUG_MSG(1, ("bad client hello message")); - mbedtls_ssl_send_alert_message(ssl, MBEDTLS_SSL_ALERT_LEVEL_FATAL, - MBEDTLS_SSL_ALERT_MSG_DECODE_ERROR); - return MBEDTLS_ERR_SSL_BAD_HS_CLIENT_HELLO; - } - - if (p[0] == MBEDTLS_TLS_EXT_SERVERNAME_HOSTNAME) { - ret = ssl->conf->f_sni(ssl->conf->p_sni, - ssl, p + 3, hostname_len); - if (ret != 0) { - MBEDTLS_SSL_DEBUG_RET(1, "ssl_sni_wrapper", ret); - mbedtls_ssl_send_alert_message(ssl, MBEDTLS_SSL_ALERT_LEVEL_FATAL, - MBEDTLS_SSL_ALERT_MSG_UNRECOGNIZED_NAME); - return MBEDTLS_ERR_SSL_BAD_HS_CLIENT_HELLO; - } - return 0; - } - - servername_list_size -= hostname_len + 3; - p += hostname_len + 3; - } - - if (servername_list_size != 0) { - MBEDTLS_SSL_DEBUG_MSG(1, ("bad client hello message")); - mbedtls_ssl_send_alert_message(ssl, MBEDTLS_SSL_ALERT_LEVEL_FATAL, - MBEDTLS_SSL_ALERT_MSG_ILLEGAL_PARAMETER); - return MBEDTLS_ERR_SSL_BAD_HS_CLIENT_HELLO; - } - - return 0; -} -#endif /* MBEDTLS_SSL_SERVER_NAME_INDICATION */ - #if defined(MBEDTLS_KEY_EXCHANGE_SOME_PSK_ENABLED) MBEDTLS_CHECK_RETURN_CRITICAL static int ssl_conf_has_psk_or_cb(mbedtls_ssl_config const *conf) @@ -148,9 +88,6 @@ static int ssl_conf_has_psk_or_cb(mbedtls_ssl_config const *conf) return 0; } - if (conf->psk != NULL && conf->psk_len != 0) { - return 1; - } #if defined(MBEDTLS_USE_PSA_CRYPTO) if (!mbedtls_svc_key_id_is_null(conf->psk_opaque)) { @@ -158,31 +95,12 @@ static int ssl_conf_has_psk_or_cb(mbedtls_ssl_config const *conf) } #endif /* MBEDTLS_USE_PSA_CRYPTO */ - return 0; -} - -#if defined(MBEDTLS_USE_PSA_CRYPTO) -MBEDTLS_CHECK_RETURN_CRITICAL -static int ssl_use_opaque_psk(mbedtls_ssl_context const *ssl) -{ - if (ssl->conf->f_psk != NULL) { - /* If we've used a callback to select the PSK, - * the static configuration is irrelevant. */ - - if (!mbedtls_svc_key_id_is_null(ssl->handshake->psk_opaque)) { - return 1; - } - - return 0; - } - - if (!mbedtls_svc_key_id_is_null(ssl->conf->psk_opaque)) { + if (conf->psk != NULL && conf->psk_len != 0) { return 1; } return 0; } -#endif /* MBEDTLS_USE_PSA_CRYPTO */ #endif /* MBEDTLS_KEY_EXCHANGE_SOME_PSK_ENABLED */ MBEDTLS_CHECK_RETURN_CRITICAL @@ -200,7 +118,7 @@ static int ssl_parse_renegotiation_info(mbedtls_ssl_context *ssl, MBEDTLS_SSL_DEBUG_MSG(1, ("non-matching renegotiation info")); mbedtls_ssl_send_alert_message(ssl, MBEDTLS_SSL_ALERT_LEVEL_FATAL, MBEDTLS_SSL_ALERT_MSG_HANDSHAKE_FAILURE); - return MBEDTLS_ERR_SSL_BAD_HS_CLIENT_HELLO; + return MBEDTLS_ERR_SSL_HANDSHAKE_FAILURE; } } else #endif /* MBEDTLS_SSL_RENEGOTIATION */ @@ -209,7 +127,7 @@ static int ssl_parse_renegotiation_info(mbedtls_ssl_context *ssl, MBEDTLS_SSL_DEBUG_MSG(1, ("non-zero length renegotiation info")); mbedtls_ssl_send_alert_message(ssl, MBEDTLS_SSL_ALERT_LEVEL_FATAL, MBEDTLS_SSL_ALERT_MSG_HANDSHAKE_FAILURE); - return MBEDTLS_ERR_SSL_BAD_HS_CLIENT_HELLO; + return MBEDTLS_ERR_SSL_HANDSHAKE_FAILURE; } ssl->secure_renegotiation = MBEDTLS_SSL_SECURE_RENEGOTIATION; @@ -218,123 +136,77 @@ static int ssl_parse_renegotiation_info(mbedtls_ssl_context *ssl, return 0; } -#if defined(MBEDTLS_SSL_PROTO_TLS1_2) && \ - defined(MBEDTLS_KEY_EXCHANGE_WITH_CERT_ENABLED) - +#if defined(MBEDTLS_KEY_EXCHANGE_SOME_ECDH_OR_ECDHE_1_2_ENABLED) || \ + defined(MBEDTLS_KEY_EXCHANGE_ECDSA_CERT_REQ_ALLOWED_ENABLED) || \ + defined(MBEDTLS_KEY_EXCHANGE_ECJPAKE_ENABLED) /* - * Status of the implementation of signature-algorithms extension: + * Function for parsing a supported groups (TLS 1.3) or supported elliptic + * curves (TLS 1.2) extension. + * + * The "extension_data" field of a supported groups extension contains a + * "NamedGroupList" value (TLS 1.3 RFC8446): + * enum { + * secp256r1(0x0017), secp384r1(0x0018), secp521r1(0x0019), + * x25519(0x001D), x448(0x001E), + * ffdhe2048(0x0100), ffdhe3072(0x0101), ffdhe4096(0x0102), + * ffdhe6144(0x0103), ffdhe8192(0x0104), + * ffdhe_private_use(0x01FC..0x01FF), + * ecdhe_private_use(0xFE00..0xFEFF), + * (0xFFFF) + * } NamedGroup; + * struct { + * NamedGroup named_group_list<2..2^16-1>; + * } NamedGroupList; * - * Currently, we are only considering the signature-algorithm extension - * to pick a ciphersuite which allows us to send the ServerKeyExchange - * message with a signature-hash combination that the user allows. + * The "extension_data" field of a supported elliptic curves extension contains + * a "NamedCurveList" value (TLS 1.2 RFC 8422): + * enum { + * deprecated(1..22), + * secp256r1 (23), secp384r1 (24), secp521r1 (25), + * x25519(29), x448(30), + * reserved (0xFE00..0xFEFF), + * deprecated(0xFF01..0xFF02), + * (0xFFFF) + * } NamedCurve; + * struct { + * NamedCurve named_curve_list<2..2^16-1> + * } NamedCurveList; * - * We do *not* check whether all certificates in our certificate - * chain are signed with an allowed signature-hash pair. - * This needs to be done at a later stage. + * The TLS 1.3 supported groups extension was defined to be a compatible + * generalization of the TLS 1.2 supported elliptic curves extension. They both + * share the same extension identifier. * */ MBEDTLS_CHECK_RETURN_CRITICAL -static int ssl_parse_signature_algorithms_ext(mbedtls_ssl_context *ssl, - const unsigned char *buf, - size_t len) -{ - size_t sig_alg_list_size; - - const unsigned char *p; - const unsigned char *end = buf + len; - - mbedtls_md_type_t md_cur; - mbedtls_pk_type_t sig_cur; - - if (len < 2) { - MBEDTLS_SSL_DEBUG_MSG(1, ("bad client hello message")); - mbedtls_ssl_send_alert_message(ssl, MBEDTLS_SSL_ALERT_LEVEL_FATAL, - MBEDTLS_SSL_ALERT_MSG_DECODE_ERROR); - return MBEDTLS_ERR_SSL_BAD_HS_CLIENT_HELLO; - } - sig_alg_list_size = ((buf[0] << 8) | (buf[1])); - if (sig_alg_list_size + 2 != len || - sig_alg_list_size % 2 != 0) { - MBEDTLS_SSL_DEBUG_MSG(1, ("bad client hello message")); - mbedtls_ssl_send_alert_message(ssl, MBEDTLS_SSL_ALERT_LEVEL_FATAL, - MBEDTLS_SSL_ALERT_MSG_DECODE_ERROR); - return MBEDTLS_ERR_SSL_BAD_HS_CLIENT_HELLO; - } - - /* Currently we only guarantee signing the ServerKeyExchange message according - * to the constraints specified in this extension (see above), so it suffices - * to remember only one suitable hash for each possible signature algorithm. - * - * This will change when we also consider certificate signatures, - * in which case we will need to remember the whole signature-hash - * pair list from the extension. - */ - - for (p = buf + 2; p < end; p += 2) { - /* Silently ignore unknown signature or hash algorithms. */ - - if ((sig_cur = mbedtls_ssl_pk_alg_from_sig(p[1])) == MBEDTLS_PK_NONE) { - MBEDTLS_SSL_DEBUG_MSG(3, ("client hello v3, signature_algorithm ext" - " unknown sig alg encoding %d", p[1])); - continue; - } - - /* Check if we support the hash the user proposes */ - md_cur = mbedtls_ssl_md_alg_from_hash(p[0]); - if (md_cur == MBEDTLS_MD_NONE) { - MBEDTLS_SSL_DEBUG_MSG(3, ("client hello v3, signature_algorithm ext:" - " unknown hash alg encoding %d", p[0])); - continue; - } - - if (mbedtls_ssl_check_sig_hash(ssl, md_cur) == 0) { - mbedtls_ssl_sig_hash_set_add(&ssl->handshake->hash_algs, sig_cur, md_cur); - MBEDTLS_SSL_DEBUG_MSG(3, ("client hello v3, signature_algorithm ext:" - " match sig %u and hash %u", - (unsigned) sig_cur, (unsigned) md_cur)); - } else { - MBEDTLS_SSL_DEBUG_MSG(3, ("client hello v3, signature_algorithm ext: " - "hash alg %u not supported", (unsigned) md_cur)); - } - } - - return 0; -} -#endif /* MBEDTLS_SSL_PROTO_TLS1_2 && - MBEDTLS_KEY_EXCHANGE_WITH_CERT_ENABLED */ - -#if defined(MBEDTLS_ECDH_C) || defined(MBEDTLS_ECDSA_C) || \ - defined(MBEDTLS_KEY_EXCHANGE_ECJPAKE_ENABLED) -MBEDTLS_CHECK_RETURN_CRITICAL -static int ssl_parse_supported_elliptic_curves(mbedtls_ssl_context *ssl, - const unsigned char *buf, - size_t len) +static int ssl_parse_supported_groups_ext(mbedtls_ssl_context *ssl, + const unsigned char *buf, + size_t len) { size_t list_size, our_size; const unsigned char *p; - const mbedtls_ecp_curve_info *curve_info, **curves; + uint16_t *curves_tls_id; if (len < 2) { MBEDTLS_SSL_DEBUG_MSG(1, ("bad client hello message")); mbedtls_ssl_send_alert_message(ssl, MBEDTLS_SSL_ALERT_LEVEL_FATAL, MBEDTLS_SSL_ALERT_MSG_DECODE_ERROR); - return MBEDTLS_ERR_SSL_BAD_HS_CLIENT_HELLO; + return MBEDTLS_ERR_SSL_DECODE_ERROR; } - list_size = ((buf[0] << 8) | (buf[1])); + list_size = MBEDTLS_GET_UINT16_BE(buf, 0); if (list_size + 2 != len || list_size % 2 != 0) { MBEDTLS_SSL_DEBUG_MSG(1, ("bad client hello message")); mbedtls_ssl_send_alert_message(ssl, MBEDTLS_SSL_ALERT_LEVEL_FATAL, MBEDTLS_SSL_ALERT_MSG_DECODE_ERROR); - return MBEDTLS_ERR_SSL_BAD_HS_CLIENT_HELLO; + return MBEDTLS_ERR_SSL_DECODE_ERROR; } /* Should never happen unless client duplicates the extension */ - if (ssl->handshake->curves != NULL) { + if (ssl->handshake->curves_tls_id != NULL) { MBEDTLS_SSL_DEBUG_MSG(1, ("bad client hello message")); mbedtls_ssl_send_alert_message(ssl, MBEDTLS_SSL_ALERT_LEVEL_FATAL, - MBEDTLS_SSL_ALERT_MSG_DECODE_ERROR); - return MBEDTLS_ERR_SSL_BAD_HS_CLIENT_HELLO; + MBEDTLS_SSL_ALERT_MSG_ILLEGAL_PARAMETER); + return MBEDTLS_ERR_SSL_ILLEGAL_PARAMETER; } /* Don't allow our peer to make us allocate too much memory, @@ -344,20 +216,22 @@ static int ssl_parse_supported_elliptic_curves(mbedtls_ssl_context *ssl, our_size = MBEDTLS_ECP_DP_MAX; } - if ((curves = mbedtls_calloc(our_size, sizeof(*curves))) == NULL) { + if ((curves_tls_id = mbedtls_calloc(our_size, + sizeof(*curves_tls_id))) == NULL) { mbedtls_ssl_send_alert_message(ssl, MBEDTLS_SSL_ALERT_LEVEL_FATAL, MBEDTLS_SSL_ALERT_MSG_INTERNAL_ERROR); return MBEDTLS_ERR_SSL_ALLOC_FAILED; } - ssl->handshake->curves = curves; + ssl->handshake->curves_tls_id = curves_tls_id; p = buf + 2; while (list_size > 0 && our_size > 1) { - curve_info = mbedtls_ecp_curve_info_from_tls_id((p[0] << 8) | p[1]); + uint16_t curr_tls_id = MBEDTLS_GET_UINT16_BE(p, 0); - if (curve_info != NULL) { - *curves++ = curve_info; + if (mbedtls_ssl_get_ecp_group_id_from_tls_id(curr_tls_id) != + MBEDTLS_ECP_DP_NONE) { + *curves_tls_id++ = curr_tls_id; our_size--; } @@ -380,7 +254,7 @@ static int ssl_parse_supported_point_formats(mbedtls_ssl_context *ssl, MBEDTLS_SSL_DEBUG_MSG(1, ("bad client hello message")); mbedtls_ssl_send_alert_message(ssl, MBEDTLS_SSL_ALERT_LEVEL_FATAL, MBEDTLS_SSL_ALERT_MSG_DECODE_ERROR); - return MBEDTLS_ERR_SSL_BAD_HS_CLIENT_HELLO; + return MBEDTLS_ERR_SSL_DECODE_ERROR; } list_size = buf[0]; @@ -388,12 +262,15 @@ static int ssl_parse_supported_point_formats(mbedtls_ssl_context *ssl, while (list_size > 0) { if (p[0] == MBEDTLS_ECP_PF_UNCOMPRESSED || p[0] == MBEDTLS_ECP_PF_COMPRESSED) { -#if defined(MBEDTLS_ECDH_C) || defined(MBEDTLS_ECDSA_C) +#if !defined(MBEDTLS_USE_PSA_CRYPTO) && \ + defined(MBEDTLS_KEY_EXCHANGE_SOME_ECDH_OR_ECDHE_1_2_ENABLED) ssl->handshake->ecdh_ctx.point_format = p[0]; -#endif -#if defined(MBEDTLS_KEY_EXCHANGE_ECJPAKE_ENABLED) - ssl->handshake->ecjpake_ctx.point_format = p[0]; -#endif +#endif /* !MBEDTLS_USE_PSA_CRYPTO && MBEDTLS_KEY_EXCHANGE_SOME_ECDH_OR_ECDHE_1_2_ENABLED */ +#if !defined(MBEDTLS_USE_PSA_CRYPTO) && \ + defined(MBEDTLS_KEY_EXCHANGE_ECJPAKE_ENABLED) + mbedtls_ecjpake_set_point_format(&ssl->handshake->ecjpake_ctx, + p[0]); +#endif /* !MBEDTLS_USE_PSA_CRYPTO && MBEDTLS_KEY_EXCHANGE_ECJPAKE_ENABLED */ MBEDTLS_SSL_DEBUG_MSG(4, ("point format selected: %d", p[0])); return 0; } @@ -404,7 +281,8 @@ static int ssl_parse_supported_point_formats(mbedtls_ssl_context *ssl, return 0; } -#endif /* MBEDTLS_ECDH_C || MBEDTLS_ECDSA_C || +#endif /* MBEDTLS_KEY_EXCHANGE_SOME_ECDH_OR_ECDHE_1_2_ENABLED || + MBEDTLS_KEY_EXCHANGE_ECDSA_CERT_REQ_ALLOWED_ENABLED || MBEDTLS_KEY_EXCHANGE_ECJPAKE_ENABLED */ #if defined(MBEDTLS_KEY_EXCHANGE_ECJPAKE_ENABLED) @@ -415,11 +293,32 @@ static int ssl_parse_ecjpake_kkpp(mbedtls_ssl_context *ssl, { int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED; - if (mbedtls_ecjpake_check(&ssl->handshake->ecjpake_ctx) != 0) { +#if defined(MBEDTLS_USE_PSA_CRYPTO) + if (ssl->handshake->psa_pake_ctx_is_ok != 1) +#else + if (mbedtls_ecjpake_check(&ssl->handshake->ecjpake_ctx) != 0) +#endif /* MBEDTLS_USE_PSA_CRYPTO */ + { MBEDTLS_SSL_DEBUG_MSG(3, ("skip ecjpake kkpp extension")); return 0; } +#if defined(MBEDTLS_USE_PSA_CRYPTO) + if ((ret = mbedtls_psa_ecjpake_read_round( + &ssl->handshake->psa_pake_ctx, buf, len, + MBEDTLS_ECJPAKE_ROUND_ONE)) != 0) { + psa_destroy_key(ssl->handshake->psa_pake_password); + psa_pake_abort(&ssl->handshake->psa_pake_ctx); + + MBEDTLS_SSL_DEBUG_RET(1, "psa_pake_input round one", ret); + mbedtls_ssl_send_alert_message( + ssl, + MBEDTLS_SSL_ALERT_LEVEL_FATAL, + MBEDTLS_SSL_ALERT_MSG_HANDSHAKE_FAILURE); + + return ret; + } +#else if ((ret = mbedtls_ecjpake_read_round_one(&ssl->handshake->ecjpake_ctx, buf, len)) != 0) { MBEDTLS_SSL_DEBUG_RET(1, "mbedtls_ecjpake_read_round_one", ret); @@ -427,6 +326,7 @@ static int ssl_parse_ecjpake_kkpp(mbedtls_ssl_context *ssl, MBEDTLS_SSL_ALERT_MSG_ILLEGAL_PARAMETER); return ret; } +#endif /* MBEDTLS_USE_PSA_CRYPTO */ /* Only mark the extension as OK when we're sure it is */ ssl->handshake->cli_exts |= MBEDTLS_TLS_EXT_ECJPAKE_KKPP_OK; @@ -445,7 +345,7 @@ static int ssl_parse_max_fragment_length_ext(mbedtls_ssl_context *ssl, MBEDTLS_SSL_DEBUG_MSG(1, ("bad client hello message")); mbedtls_ssl_send_alert_message(ssl, MBEDTLS_SSL_ALERT_LEVEL_FATAL, MBEDTLS_SSL_ALERT_MSG_ILLEGAL_PARAMETER); - return MBEDTLS_ERR_SSL_BAD_HS_CLIENT_HELLO; + return MBEDTLS_ERR_SSL_ILLEGAL_PARAMETER; } ssl->session_negotiate->mfl_code = buf[0]; @@ -467,13 +367,10 @@ static int ssl_parse_cid_ext(mbedtls_ssl_context *ssl, MBEDTLS_SSL_DEBUG_MSG(1, ("bad client hello message")); mbedtls_ssl_send_alert_message(ssl, MBEDTLS_SSL_ALERT_LEVEL_FATAL, MBEDTLS_SSL_ALERT_MSG_ILLEGAL_PARAMETER); - return MBEDTLS_ERR_SSL_BAD_HS_CLIENT_HELLO; + return MBEDTLS_ERR_SSL_ILLEGAL_PARAMETER; } /* - * Quoting draft-ietf-tls-dtls-connection-id-05 - * https://tools.ietf.org/html/draft-ietf-tls-dtls-connection-id-05 - * * struct { * opaque cid<0..2^8-1>; * } ConnectionId; @@ -482,8 +379,8 @@ static int ssl_parse_cid_ext(mbedtls_ssl_context *ssl, if (len < 1) { MBEDTLS_SSL_DEBUG_MSG(1, ("bad client hello message")); mbedtls_ssl_send_alert_message(ssl, MBEDTLS_SSL_ALERT_LEVEL_FATAL, - MBEDTLS_SSL_ALERT_MSG_ILLEGAL_PARAMETER); - return MBEDTLS_ERR_SSL_BAD_HS_CLIENT_HELLO; + MBEDTLS_SSL_ALERT_MSG_DECODE_ERROR); + return MBEDTLS_ERR_SSL_DECODE_ERROR; } peer_cid_len = *buf++; @@ -492,8 +389,8 @@ static int ssl_parse_cid_ext(mbedtls_ssl_context *ssl, if (len != peer_cid_len) { MBEDTLS_SSL_DEBUG_MSG(1, ("bad client hello message")); mbedtls_ssl_send_alert_message(ssl, MBEDTLS_SSL_ALERT_LEVEL_FATAL, - MBEDTLS_SSL_ALERT_MSG_ILLEGAL_PARAMETER); - return MBEDTLS_ERR_SSL_BAD_HS_CLIENT_HELLO; + MBEDTLS_SSL_ALERT_MSG_DECODE_ERROR); + return MBEDTLS_ERR_SSL_DECODE_ERROR; } /* Ignore CID if the user has disabled its use. */ @@ -508,7 +405,7 @@ static int ssl_parse_cid_ext(mbedtls_ssl_context *ssl, MBEDTLS_SSL_DEBUG_MSG(1, ("bad client hello message")); mbedtls_ssl_send_alert_message(ssl, MBEDTLS_SSL_ALERT_LEVEL_FATAL, MBEDTLS_SSL_ALERT_MSG_ILLEGAL_PARAMETER); - return MBEDTLS_ERR_SSL_BAD_HS_CLIENT_HELLO; + return MBEDTLS_ERR_SSL_ILLEGAL_PARAMETER; } ssl->handshake->cid_in_use = MBEDTLS_SSL_CID_ENABLED; @@ -522,29 +419,6 @@ static int ssl_parse_cid_ext(mbedtls_ssl_context *ssl, } #endif /* MBEDTLS_SSL_DTLS_CONNECTION_ID */ -#if defined(MBEDTLS_SSL_TRUNCATED_HMAC) -MBEDTLS_CHECK_RETURN_CRITICAL -static int ssl_parse_truncated_hmac_ext(mbedtls_ssl_context *ssl, - const unsigned char *buf, - size_t len) -{ - if (len != 0) { - MBEDTLS_SSL_DEBUG_MSG(1, ("bad client hello message")); - mbedtls_ssl_send_alert_message(ssl, MBEDTLS_SSL_ALERT_LEVEL_FATAL, - MBEDTLS_SSL_ALERT_MSG_DECODE_ERROR); - return MBEDTLS_ERR_SSL_BAD_HS_CLIENT_HELLO; - } - - ((void) buf); - - if (ssl->conf->trunc_hmac == MBEDTLS_SSL_TRUNC_HMAC_ENABLED) { - ssl->session_negotiate->trunc_hmac = MBEDTLS_SSL_TRUNC_HMAC_ENABLED; - } - - return 0; -} -#endif /* MBEDTLS_SSL_TRUNCATED_HMAC */ - #if defined(MBEDTLS_SSL_ENCRYPT_THEN_MAC) MBEDTLS_CHECK_RETURN_CRITICAL static int ssl_parse_encrypt_then_mac_ext(mbedtls_ssl_context *ssl, @@ -555,13 +429,12 @@ static int ssl_parse_encrypt_then_mac_ext(mbedtls_ssl_context *ssl, MBEDTLS_SSL_DEBUG_MSG(1, ("bad client hello message")); mbedtls_ssl_send_alert_message(ssl, MBEDTLS_SSL_ALERT_LEVEL_FATAL, MBEDTLS_SSL_ALERT_MSG_DECODE_ERROR); - return MBEDTLS_ERR_SSL_BAD_HS_CLIENT_HELLO; + return MBEDTLS_ERR_SSL_DECODE_ERROR; } ((void) buf); - if (ssl->conf->encrypt_then_mac == MBEDTLS_SSL_ETM_ENABLED && - ssl->minor_ver != MBEDTLS_SSL_MINOR_VERSION_0) { + if (ssl->conf->encrypt_then_mac == MBEDTLS_SSL_ETM_ENABLED) { ssl->session_negotiate->encrypt_then_mac = MBEDTLS_SSL_ETM_ENABLED; } @@ -579,13 +452,12 @@ static int ssl_parse_extended_ms_ext(mbedtls_ssl_context *ssl, MBEDTLS_SSL_DEBUG_MSG(1, ("bad client hello message")); mbedtls_ssl_send_alert_message(ssl, MBEDTLS_SSL_ALERT_LEVEL_FATAL, MBEDTLS_SSL_ALERT_MSG_DECODE_ERROR); - return MBEDTLS_ERR_SSL_BAD_HS_CLIENT_HELLO; + return MBEDTLS_ERR_SSL_DECODE_ERROR; } ((void) buf); - if (ssl->conf->extended_ms == MBEDTLS_SSL_EXTENDED_MS_ENABLED && - ssl->minor_ver != MBEDTLS_SSL_MINOR_VERSION_0) { + if (ssl->conf->extended_ms == MBEDTLS_SSL_EXTENDED_MS_ENABLED) { ssl->handshake->extended_ms = MBEDTLS_SSL_EXTENDED_MS_ENABLED; } @@ -667,88 +539,6 @@ static int ssl_parse_session_ticket_ext(mbedtls_ssl_context *ssl, } #endif /* MBEDTLS_SSL_SESSION_TICKETS */ -#if defined(MBEDTLS_SSL_ALPN) -MBEDTLS_CHECK_RETURN_CRITICAL -static int ssl_parse_alpn_ext(mbedtls_ssl_context *ssl, - const unsigned char *buf, size_t len) -{ - size_t list_len, cur_len, ours_len; - const unsigned char *theirs, *start, *end; - const char **ours; - - /* If ALPN not configured, just ignore the extension */ - if (ssl->conf->alpn_list == NULL) { - return 0; - } - - /* - * opaque ProtocolName<1..2^8-1>; - * - * struct { - * ProtocolName protocol_name_list<2..2^16-1> - * } ProtocolNameList; - */ - - /* Min length is 2 (list_len) + 1 (name_len) + 1 (name) */ - if (len < 4) { - mbedtls_ssl_send_alert_message(ssl, MBEDTLS_SSL_ALERT_LEVEL_FATAL, - MBEDTLS_SSL_ALERT_MSG_DECODE_ERROR); - return MBEDTLS_ERR_SSL_BAD_HS_CLIENT_HELLO; - } - - list_len = (buf[0] << 8) | buf[1]; - if (list_len != len - 2) { - mbedtls_ssl_send_alert_message(ssl, MBEDTLS_SSL_ALERT_LEVEL_FATAL, - MBEDTLS_SSL_ALERT_MSG_DECODE_ERROR); - return MBEDTLS_ERR_SSL_BAD_HS_CLIENT_HELLO; - } - - /* - * Validate peer's list (lengths) - */ - start = buf + 2; - end = buf + len; - for (theirs = start; theirs != end; theirs += cur_len) { - cur_len = *theirs++; - - /* Current identifier must fit in list */ - if (cur_len > (size_t) (end - theirs)) { - mbedtls_ssl_send_alert_message(ssl, MBEDTLS_SSL_ALERT_LEVEL_FATAL, - MBEDTLS_SSL_ALERT_MSG_DECODE_ERROR); - return MBEDTLS_ERR_SSL_BAD_HS_CLIENT_HELLO; - } - - /* Empty strings MUST NOT be included */ - if (cur_len == 0) { - mbedtls_ssl_send_alert_message(ssl, MBEDTLS_SSL_ALERT_LEVEL_FATAL, - MBEDTLS_SSL_ALERT_MSG_ILLEGAL_PARAMETER); - return MBEDTLS_ERR_SSL_BAD_HS_CLIENT_HELLO; - } - } - - /* - * Use our order of preference - */ - for (ours = ssl->conf->alpn_list; *ours != NULL; ours++) { - ours_len = strlen(*ours); - for (theirs = start; theirs != end; theirs += cur_len) { - cur_len = *theirs++; - - if (cur_len == ours_len && - memcmp(theirs, *ours, cur_len) == 0) { - ssl->alpn_chosen = *ours; - return 0; - } - } - } - - /* If we get there, no match was found */ - mbedtls_ssl_send_alert_message(ssl, MBEDTLS_SSL_ALERT_LEVEL_FATAL, - MBEDTLS_SSL_ALERT_MSG_NO_APPLICATION_PROTOCOL); - return MBEDTLS_ERR_SSL_BAD_HS_CLIENT_HELLO; -} -#endif /* MBEDTLS_SSL_ALPN */ - #if defined(MBEDTLS_SSL_DTLS_SRTP) MBEDTLS_CHECK_RETURN_CRITICAL static int ssl_parse_use_srtp_ext(mbedtls_ssl_context *ssl, @@ -788,8 +578,8 @@ static int ssl_parse_use_srtp_ext(mbedtls_ssl_context *ssl, */ if (len < size_of_lengths) { mbedtls_ssl_send_alert_message(ssl, MBEDTLS_SSL_ALERT_LEVEL_FATAL, - MBEDTLS_SSL_ALERT_MSG_HANDSHAKE_FAILURE); - return MBEDTLS_ERR_SSL_BAD_HS_CLIENT_HELLO; + MBEDTLS_SSL_ALERT_MSG_DECODE_ERROR); + return MBEDTLS_ERR_SSL_DECODE_ERROR; } ssl->dtls_srtp_info.chosen_dtls_srtp_profile = MBEDTLS_TLS_SRTP_UNSET; @@ -802,8 +592,8 @@ static int ssl_parse_use_srtp_ext(mbedtls_ssl_context *ssl, if (profile_length > len - size_of_lengths || profile_length % 2 != 0) { /* profiles are 2 bytes long, so the length must be even */ mbedtls_ssl_send_alert_message(ssl, MBEDTLS_SSL_ALERT_LEVEL_FATAL, - MBEDTLS_SSL_ALERT_MSG_HANDSHAKE_FAILURE); - return MBEDTLS_ERR_SSL_BAD_HS_CLIENT_HELLO; + MBEDTLS_SSL_ALERT_MSG_DECODE_ERROR); + return MBEDTLS_ERR_SSL_DECODE_ERROR; } /* * parse the extension list values are defined in @@ -841,8 +631,8 @@ static int ssl_parse_use_srtp_ext(mbedtls_ssl_context *ssl, if (mki_length > MBEDTLS_TLS_SRTP_MAX_MKI_LENGTH || mki_length + profile_length + size_of_lengths != len) { mbedtls_ssl_send_alert_message(ssl, MBEDTLS_SSL_ALERT_LEVEL_FATAL, - MBEDTLS_SSL_ALERT_MSG_HANDSHAKE_FAILURE); - return MBEDTLS_ERR_SSL_BAD_HS_CLIENT_HELLO; + MBEDTLS_SSL_ALERT_MSG_DECODE_ERROR); + return MBEDTLS_ERR_SSL_DECODE_ERROR; } /* Parse the mki only if present and mki is supported locally */ @@ -868,24 +658,26 @@ static int ssl_parse_use_srtp_ext(mbedtls_ssl_context *ssl, /* * Return 0 if the given key uses one of the acceptable curves, -1 otherwise */ -#if defined(MBEDTLS_ECDSA_C) +#if defined(MBEDTLS_KEY_EXCHANGE_ECDSA_CERT_REQ_ALLOWED_ENABLED) MBEDTLS_CHECK_RETURN_CRITICAL static int ssl_check_key_curve(mbedtls_pk_context *pk, - const mbedtls_ecp_curve_info **curves) + uint16_t *curves_tls_id) { - const mbedtls_ecp_curve_info **crv = curves; - mbedtls_ecp_group_id grp_id = mbedtls_pk_ec(*pk)->grp.id; + uint16_t *curr_tls_id = curves_tls_id; + mbedtls_ecp_group_id grp_id = mbedtls_pk_get_ec_group_id(pk); + mbedtls_ecp_group_id curr_grp_id; - while (*crv != NULL) { - if ((*crv)->grp_id == grp_id) { + while (*curr_tls_id != 0) { + curr_grp_id = mbedtls_ssl_get_ecp_group_id_from_tls_id(*curr_tls_id); + if (curr_grp_id == grp_id) { return 0; } - crv++; + curr_tls_id++; } return -1; } -#endif /* MBEDTLS_ECDSA_C */ +#endif /* MBEDTLS_KEY_EXCHANGE_ECDSA_CERT_REQ_ALLOWED_ENABLED */ /* * Try picking a certificate for this ciphersuite, @@ -895,9 +687,16 @@ MBEDTLS_CHECK_RETURN_CRITICAL static int ssl_pick_cert(mbedtls_ssl_context *ssl, const mbedtls_ssl_ciphersuite_t *ciphersuite_info) { - mbedtls_ssl_key_cert *cur, *list, *fallback = NULL; + mbedtls_ssl_key_cert *cur, *list; +#if defined(MBEDTLS_USE_PSA_CRYPTO) + psa_algorithm_t pk_alg = + mbedtls_ssl_get_ciphersuite_sig_pk_psa_alg(ciphersuite_info); + psa_key_usage_t pk_usage = + mbedtls_ssl_get_ciphersuite_sig_pk_psa_usage(ciphersuite_info); +#else mbedtls_pk_type_t pk_alg = mbedtls_ssl_get_ciphersuite_sig_pk_alg(ciphersuite_info); +#endif /* MBEDTLS_USE_PSA_CRYPTO */ uint32_t flags; #if defined(MBEDTLS_SSL_SERVER_NAME_INDICATION) @@ -907,7 +706,13 @@ static int ssl_pick_cert(mbedtls_ssl_context *ssl, #endif list = ssl->conf->key_cert; - if (pk_alg == MBEDTLS_PK_NONE) { + int pk_alg_is_none = 0; +#if defined(MBEDTLS_USE_PSA_CRYPTO) + pk_alg_is_none = (pk_alg == PSA_ALG_NONE); +#else + pk_alg_is_none = (pk_alg == MBEDTLS_PK_NONE); +#endif /* MBEDTLS_USE_PSA_CRYPTO */ + if (pk_alg_is_none) { return 0; } @@ -923,7 +728,21 @@ static int ssl_pick_cert(mbedtls_ssl_context *ssl, MBEDTLS_SSL_DEBUG_CRT(3, "candidate certificate chain, certificate", cur->cert); - if (!mbedtls_pk_can_do(&cur->cert->pk, pk_alg)) { + int key_type_matches = 0; +#if defined(MBEDTLS_USE_PSA_CRYPTO) +#if defined(MBEDTLS_SSL_ASYNC_PRIVATE) + key_type_matches = ((ssl->conf->f_async_sign_start != NULL || + ssl->conf->f_async_decrypt_start != NULL || + mbedtls_pk_can_do_ext(cur->key, pk_alg, pk_usage)) && + mbedtls_pk_can_do_ext(&cur->cert->pk, pk_alg, pk_usage)); +#else + key_type_matches = ( + mbedtls_pk_can_do_ext(cur->key, pk_alg, pk_usage)); +#endif /* MBEDTLS_SSL_ASYNC_PRIVATE */ +#else + key_type_matches = mbedtls_pk_can_do(&cur->cert->pk, pk_alg); +#endif /* MBEDTLS_USE_PSA_CRYPTO */ + if (!key_type_matches) { MBEDTLS_SSL_DEBUG_MSG(3, ("certificate mismatch: key type")); continue; } @@ -943,39 +762,19 @@ static int ssl_pick_cert(mbedtls_ssl_context *ssl, continue; } -#if defined(MBEDTLS_ECDSA_C) +#if defined(MBEDTLS_KEY_EXCHANGE_ECDSA_CERT_REQ_ALLOWED_ENABLED) if (pk_alg == MBEDTLS_PK_ECDSA && - ssl_check_key_curve(&cur->cert->pk, ssl->handshake->curves) != 0) { + ssl_check_key_curve(&cur->cert->pk, + ssl->handshake->curves_tls_id) != 0) { MBEDTLS_SSL_DEBUG_MSG(3, ("certificate mismatch: elliptic curve")); continue; } #endif - /* - * Try to select a SHA-1 certificate for pre-1.2 clients, but still - * present them a SHA-higher cert rather than failing if it's the only - * one we got that satisfies the other conditions. - */ - if (ssl->minor_ver < MBEDTLS_SSL_MINOR_VERSION_3 && - cur->cert->sig_md != MBEDTLS_MD_SHA1) { - if (fallback == NULL) { - fallback = cur; - } - { - MBEDTLS_SSL_DEBUG_MSG(3, ("certificate not preferred: " - "sha-2 with pre-TLS 1.2 client")); - continue; - } - } - /* If we get there, we got a winner */ break; } - if (cur == NULL) { - cur = fallback; - } - /* Do not update ssl->handshake->key_cert unless there is a match */ if (cur != NULL) { ssl->handshake->key_cert = cur; @@ -998,8 +797,7 @@ static int ssl_ciphersuite_match(mbedtls_ssl_context *ssl, int suite_id, { const mbedtls_ssl_ciphersuite_t *suite_info; -#if defined(MBEDTLS_SSL_PROTO_TLS1_2) && \ - defined(MBEDTLS_KEY_EXCHANGE_WITH_CERT_ENABLED) +#if defined(MBEDTLS_KEY_EXCHANGE_WITH_CERT_ENABLED) mbedtls_pk_type_t sig_type; #endif @@ -1012,27 +810,12 @@ static int ssl_ciphersuite_match(mbedtls_ssl_context *ssl, int suite_id, MBEDTLS_SSL_DEBUG_MSG(3, ("trying ciphersuite: %#04x (%s)", (unsigned int) suite_id, suite_info->name)); - if (suite_info->min_minor_ver > ssl->minor_ver || - suite_info->max_minor_ver < ssl->minor_ver) { + if (suite_info->min_tls_version > ssl->tls_version || + suite_info->max_tls_version < ssl->tls_version) { MBEDTLS_SSL_DEBUG_MSG(3, ("ciphersuite mismatch: version")); return 0; } -#if defined(MBEDTLS_SSL_PROTO_DTLS) - if (ssl->conf->transport == MBEDTLS_SSL_TRANSPORT_DATAGRAM && - (suite_info->flags & MBEDTLS_CIPHERSUITE_NODTLS)) { - return 0; - } -#endif - -#if defined(MBEDTLS_ARC4_C) - if (ssl->conf->arc4_disabled == MBEDTLS_SSL_ARC4_DISABLED && - suite_info->cipher == MBEDTLS_CIPHER_ARC4_128) { - MBEDTLS_SSL_DEBUG_MSG(3, ("ciphersuite mismatch: rc4")); - return 0; - } -#endif - #if defined(MBEDTLS_KEY_EXCHANGE_ECJPAKE_ENABLED) if (suite_info->key_exchange == MBEDTLS_KEY_EXCHANGE_ECJPAKE && (ssl->handshake->cli_exts & MBEDTLS_TLS_EXT_ECJPAKE_KKPP_OK) == 0) { @@ -1043,10 +826,11 @@ static int ssl_ciphersuite_match(mbedtls_ssl_context *ssl, int suite_id, #endif -#if defined(MBEDTLS_ECDH_C) || defined(MBEDTLS_ECDSA_C) +#if defined(MBEDTLS_KEY_EXCHANGE_SOME_ECDH_OR_ECDHE_1_2_ENABLED) || \ + defined(MBEDTLS_KEY_EXCHANGE_ECDSA_CERT_REQ_ALLOWED_ENABLED) if (mbedtls_ssl_ciphersuite_uses_ec(suite_info) && - (ssl->handshake->curves == NULL || - ssl->handshake->curves[0] == NULL)) { + (ssl->handshake->curves_tls_id == NULL || + ssl->handshake->curves_tls_id[0] == 0)) { MBEDTLS_SSL_DEBUG_MSG(3, ("ciphersuite mismatch: " "no common elliptic curve")); return 0; @@ -1063,24 +847,6 @@ static int ssl_ciphersuite_match(mbedtls_ssl_context *ssl, int suite_id, } #endif -#if defined(MBEDTLS_SSL_PROTO_TLS1_2) && \ - defined(MBEDTLS_KEY_EXCHANGE_WITH_CERT_ENABLED) - /* If the ciphersuite requires signing, check whether - * a suitable hash algorithm is present. */ - if (ssl->minor_ver == MBEDTLS_SSL_MINOR_VERSION_3) { - sig_type = mbedtls_ssl_get_ciphersuite_sig_alg(suite_info); - if (sig_type != MBEDTLS_PK_NONE && - mbedtls_ssl_sig_hash_set_find(&ssl->handshake->hash_algs, - sig_type) == MBEDTLS_MD_NONE) { - MBEDTLS_SSL_DEBUG_MSG(3, ("ciphersuite mismatch: no suitable hash algorithm " - "for signature algorithm %u", (unsigned) sig_type)); - return 0; - } - } - -#endif /* MBEDTLS_SSL_PROTO_TLS1_2 && - MBEDTLS_KEY_EXCHANGE_WITH_CERT_ENABLED */ - #if defined(MBEDTLS_X509_CRT_PARSE_C) /* * Final check: if ciphersuite requires us to have a @@ -1096,272 +862,23 @@ static int ssl_ciphersuite_match(mbedtls_ssl_context *ssl, int suite_id, } #endif - *ciphersuite_info = suite_info; - return 0; -} - -#if defined(MBEDTLS_SSL_SRV_SUPPORT_SSLV2_CLIENT_HELLO) -MBEDTLS_CHECK_RETURN_CRITICAL -static int ssl_parse_client_hello_v2(mbedtls_ssl_context *ssl) -{ - int ret, got_common_suite; - unsigned int i, j; - size_t n; - unsigned int ciph_len, sess_len, chal_len; - unsigned char *buf, *p; - const int *ciphersuites; - const mbedtls_ssl_ciphersuite_t *ciphersuite_info; - - MBEDTLS_SSL_DEBUG_MSG(2, ("=> parse client hello v2")); - -#if defined(MBEDTLS_SSL_RENEGOTIATION) - if (ssl->renego_status != MBEDTLS_SSL_INITIAL_HANDSHAKE) { - MBEDTLS_SSL_DEBUG_MSG(1, ("client hello v2 illegal for renegotiation")); - mbedtls_ssl_send_alert_message(ssl, MBEDTLS_SSL_ALERT_LEVEL_FATAL, - MBEDTLS_SSL_ALERT_MSG_HANDSHAKE_FAILURE); - return MBEDTLS_ERR_SSL_BAD_HS_CLIENT_HELLO; - } -#endif /* MBEDTLS_SSL_RENEGOTIATION */ - - buf = ssl->in_hdr; - - MBEDTLS_SSL_DEBUG_BUF(4, "record header", buf, 5); - - MBEDTLS_SSL_DEBUG_MSG(3, ("client hello v2, message type: %d", - buf[2])); - MBEDTLS_SSL_DEBUG_MSG(3, ("client hello v2, message len.: %d", - ((buf[0] & 0x7F) << 8) | buf[1])); - MBEDTLS_SSL_DEBUG_MSG(3, ("client hello v2, max. version: [%d:%d]", - buf[3], buf[4])); - - /* - * SSLv2 Client Hello - * - * Record layer: - * 0 . 1 message length - * - * SSL layer: - * 2 . 2 message type - * 3 . 4 protocol version - */ - if (buf[2] != MBEDTLS_SSL_HS_CLIENT_HELLO || - buf[3] != MBEDTLS_SSL_MAJOR_VERSION_3) { - MBEDTLS_SSL_DEBUG_MSG(1, ("bad client hello message")); - return MBEDTLS_ERR_SSL_BAD_HS_CLIENT_HELLO; - } - - n = ((buf[0] << 8) | buf[1]) & 0x7FFF; - - if (n < 17 || n > 512) { - MBEDTLS_SSL_DEBUG_MSG(1, ("bad client hello message")); - return MBEDTLS_ERR_SSL_BAD_HS_CLIENT_HELLO; - } - - ssl->major_ver = MBEDTLS_SSL_MAJOR_VERSION_3; - ssl->minor_ver = (buf[4] <= ssl->conf->max_minor_ver) - ? buf[4] : ssl->conf->max_minor_ver; - - if (ssl->minor_ver < ssl->conf->min_minor_ver) { - MBEDTLS_SSL_DEBUG_MSG(1, ("client only supports ssl smaller than minimum" - " [%d:%d] < [%d:%d]", - ssl->major_ver, ssl->minor_ver, - ssl->conf->min_major_ver, ssl->conf->min_minor_ver)); - - mbedtls_ssl_send_alert_message(ssl, MBEDTLS_SSL_ALERT_LEVEL_FATAL, - MBEDTLS_SSL_ALERT_MSG_PROTOCOL_VERSION); - return MBEDTLS_ERR_SSL_BAD_HS_PROTOCOL_VERSION; - } - - ssl->handshake->max_major_ver = buf[3]; - ssl->handshake->max_minor_ver = buf[4]; - - if ((ret = mbedtls_ssl_fetch_input(ssl, 2 + n)) != 0) { - MBEDTLS_SSL_DEBUG_RET(1, "mbedtls_ssl_fetch_input", ret); - return ret; - } - - ssl->handshake->update_checksum(ssl, buf + 2, n); - - buf = ssl->in_msg; - n = ssl->in_left - 5; - - /* - * 0 . 1 ciphersuitelist length - * 2 . 3 session id length - * 4 . 5 challenge length - * 6 . .. ciphersuitelist - * .. . .. session id - * .. . .. challenge - */ - MBEDTLS_SSL_DEBUG_BUF(4, "record contents", buf, n); - - ciph_len = (buf[0] << 8) | buf[1]; - sess_len = (buf[2] << 8) | buf[3]; - chal_len = (buf[4] << 8) | buf[5]; - - MBEDTLS_SSL_DEBUG_MSG(3, ("ciph_len: %u, sess_len: %u, chal_len: %u", - ciph_len, sess_len, chal_len)); - - /* - * Make sure each parameter length is valid - */ - if (ciph_len < 3 || (ciph_len % 3) != 0) { - MBEDTLS_SSL_DEBUG_MSG(1, ("bad client hello message")); - return MBEDTLS_ERR_SSL_BAD_HS_CLIENT_HELLO; - } - - if (sess_len > 32) { - MBEDTLS_SSL_DEBUG_MSG(1, ("bad client hello message")); - return MBEDTLS_ERR_SSL_BAD_HS_CLIENT_HELLO; - } - - if (chal_len < 8 || chal_len > 32) { - MBEDTLS_SSL_DEBUG_MSG(1, ("bad client hello message")); - return MBEDTLS_ERR_SSL_BAD_HS_CLIENT_HELLO; - } - - if (n != 6 + ciph_len + sess_len + chal_len) { - MBEDTLS_SSL_DEBUG_MSG(1, ("bad client hello message")); - return MBEDTLS_ERR_SSL_BAD_HS_CLIENT_HELLO; - } - - MBEDTLS_SSL_DEBUG_BUF(3, "client hello, ciphersuitelist", - buf + 6, ciph_len); - MBEDTLS_SSL_DEBUG_BUF(3, "client hello, session id", - buf + 6 + ciph_len, sess_len); - MBEDTLS_SSL_DEBUG_BUF(3, "client hello, challenge", - buf + 6 + ciph_len + sess_len, chal_len); - - p = buf + 6 + ciph_len; - ssl->session_negotiate->id_len = sess_len; - memset(ssl->session_negotiate->id, 0, - sizeof(ssl->session_negotiate->id)); - memcpy(ssl->session_negotiate->id, p, ssl->session_negotiate->id_len); - - p += sess_len; - memset(ssl->handshake->randbytes, 0, 64); - memcpy(ssl->handshake->randbytes + 32 - chal_len, p, chal_len); - - /* - * Check for TLS_EMPTY_RENEGOTIATION_INFO_SCSV - */ - for (i = 0, p = buf + 6; i < ciph_len; i += 3, p += 3) { - if (p[0] == 0 && p[1] == 0 && p[2] == MBEDTLS_SSL_EMPTY_RENEGOTIATION_INFO) { - MBEDTLS_SSL_DEBUG_MSG(3, ("received TLS_EMPTY_RENEGOTIATION_INFO ")); -#if defined(MBEDTLS_SSL_RENEGOTIATION) - if (ssl->renego_status == MBEDTLS_SSL_RENEGOTIATION_IN_PROGRESS) { - MBEDTLS_SSL_DEBUG_MSG(1, ("received RENEGOTIATION SCSV " - "during renegotiation")); - - mbedtls_ssl_send_alert_message(ssl, MBEDTLS_SSL_ALERT_LEVEL_FATAL, - MBEDTLS_SSL_ALERT_MSG_HANDSHAKE_FAILURE); - return MBEDTLS_ERR_SSL_BAD_HS_CLIENT_HELLO; - } -#endif /* MBEDTLS_SSL_RENEGOTIATION */ - ssl->secure_renegotiation = MBEDTLS_SSL_SECURE_RENEGOTIATION; - break; - } - } - -#if defined(MBEDTLS_SSL_FALLBACK_SCSV) - for (i = 0, p = buf + 6; i < ciph_len; i += 3, p += 3) { - if (p[0] == 0 && - MBEDTLS_GET_UINT16_BE(p, 1) != MBEDTLS_SSL_FALLBACK_SCSV_VALUE) { - MBEDTLS_SSL_DEBUG_MSG(3, ("received FALLBACK_SCSV")); - - if (ssl->minor_ver < ssl->conf->max_minor_ver) { - MBEDTLS_SSL_DEBUG_MSG(1, ("inapropriate fallback")); - - mbedtls_ssl_send_alert_message(ssl, MBEDTLS_SSL_ALERT_LEVEL_FATAL, - MBEDTLS_SSL_ALERT_MSG_INAPROPRIATE_FALLBACK); - - return MBEDTLS_ERR_SSL_BAD_HS_CLIENT_HELLO; - } - - break; - } - } -#endif /* MBEDTLS_SSL_FALLBACK_SCSV */ - - got_common_suite = 0; - ciphersuites = ssl->conf->ciphersuite_list[ssl->minor_ver]; - ciphersuite_info = NULL; -#if defined(MBEDTLS_SSL_SRV_RESPECT_CLIENT_PREFERENCE) - for (j = 0, p = buf + 6; j < ciph_len; j += 3, p += 3) { - for (i = 0; ciphersuites[i] != 0; i++) { - if (p[0] != 0 || - MBEDTLS_GET_UINT16_BE(p, 1) != ciphersuites[i]) { - continue; - } - - got_common_suite = 1; - - if ((ret = ssl_ciphersuite_match(ssl, ciphersuites[i], - &ciphersuite_info)) != 0) { - return ret; - } - - if (ciphersuite_info != NULL) { - goto have_ciphersuite_v2; - } - } - } -#else - for (i = 0; ciphersuites[i] != 0; i++) { - for (j = 0, p = buf + 6; j < ciph_len; j += 3, p += 3) { - if (p[0] != 0 || - MBEDTLS_GET_UINT16_BE(p, 1) != ciphersuites[i]) { - continue; - } - - got_common_suite = 1; - - if ((ret = ssl_ciphersuite_match(ssl, ciphersuites[i], - &ciphersuite_info)) != 0) { - return ret; - } - - if (ciphersuite_info != NULL) { - goto have_ciphersuite_v2; - } - } - } -#endif - - if (got_common_suite) { - MBEDTLS_SSL_DEBUG_MSG(1, ("got ciphersuites in common, " - "but none of them usable")); - return MBEDTLS_ERR_SSL_NO_USABLE_CIPHERSUITE; - } else { - MBEDTLS_SSL_DEBUG_MSG(1, ("got no ciphersuites in common")); - return MBEDTLS_ERR_SSL_NO_CIPHER_CHOSEN; - } - -have_ciphersuite_v2: - MBEDTLS_SSL_DEBUG_MSG(2, ("selected ciphersuite: %s", ciphersuite_info->name)); - - ssl->session_negotiate->ciphersuite = ciphersuites[i]; - ssl->handshake->ciphersuite_info = ciphersuite_info; - - /* - * SSLv2 Client Hello relevant renegotiation security checks - */ - if (ssl->secure_renegotiation == MBEDTLS_SSL_LEGACY_RENEGOTIATION && - ssl->conf->allow_legacy_renegotiation == MBEDTLS_SSL_LEGACY_BREAK_HANDSHAKE) { - MBEDTLS_SSL_DEBUG_MSG(1, ("legacy renegotiation, breaking off handshake")); - mbedtls_ssl_send_alert_message(ssl, MBEDTLS_SSL_ALERT_LEVEL_FATAL, - MBEDTLS_SSL_ALERT_MSG_HANDSHAKE_FAILURE); - return MBEDTLS_ERR_SSL_BAD_HS_CLIENT_HELLO; +#if defined(MBEDTLS_KEY_EXCHANGE_WITH_CERT_ENABLED) + /* If the ciphersuite requires signing, check whether + * a suitable hash algorithm is present. */ + sig_type = mbedtls_ssl_get_ciphersuite_sig_alg(suite_info); + if (sig_type != MBEDTLS_PK_NONE && + mbedtls_ssl_tls12_get_preferred_hash_for_sig_alg( + ssl, mbedtls_ssl_sig_from_pk_alg(sig_type)) == MBEDTLS_SSL_HASH_NONE) { + MBEDTLS_SSL_DEBUG_MSG(3, ("ciphersuite mismatch: no suitable hash algorithm " + "for signature algorithm %u", (unsigned) sig_type)); + return 0; } - ssl->in_left = 0; - ssl->state++; - - MBEDTLS_SSL_DEBUG_MSG(2, ("<= parse client hello v2")); +#endif /* MBEDTLS_KEY_EXCHANGE_WITH_CERT_ENABLED */ + *ciphersuite_info = suite_info; return 0; } -#endif /* MBEDTLS_SSL_SRV_SUPPORT_SSLV2_CLIENT_HELLO */ /* This function doesn't alert on errors that happen early during ClientHello parsing because they might indicate that the client is @@ -1383,20 +900,18 @@ static int ssl_parse_client_hello(mbedtls_ssl_context *ssl) int handshake_failure = 0; const int *ciphersuites; const mbedtls_ssl_ciphersuite_t *ciphersuite_info; - int major, minor; /* If there is no signature-algorithm extension present, * we need to fall back to the default values for allowed * signature-hash pairs. */ -#if defined(MBEDTLS_SSL_PROTO_TLS1_2) && \ - defined(MBEDTLS_KEY_EXCHANGE_WITH_CERT_ENABLED) +#if defined(MBEDTLS_KEY_EXCHANGE_WITH_CERT_ENABLED) int sig_hash_alg_ext_present = 0; -#endif /* MBEDTLS_SSL_PROTO_TLS1_2 && - MBEDTLS_KEY_EXCHANGE_WITH_CERT_ENABLED */ +#endif /* MBEDTLS_KEY_EXCHANGE_WITH_CERT_ENABLED */ MBEDTLS_SSL_DEBUG_MSG(2, ("=> parse client hello")); - int renegotiating = 0; + int renegotiating; + #if defined(MBEDTLS_SSL_DTLS_ANTI_REPLAY) read_record_header: #endif @@ -1404,13 +919,15 @@ static int ssl_parse_client_hello(mbedtls_ssl_context *ssl) * If renegotiating, then the input was read with mbedtls_ssl_read_record(), * otherwise read it ourselves manually in order to support SSLv2 * ClientHello, which doesn't use the same record layer format. + * Otherwise in a scenario of TLS 1.3/TLS 1.2 version negotiation, the + * ClientHello has been already fully fetched by the TLS 1.3 code and the + * flag ssl->keep_current_message is raised. */ -#if defined(MBEDTLS_SSL_RENEGOTIATION) - if (ssl->renego_status != MBEDTLS_SSL_INITIAL_HANDSHAKE) { - renegotiating = 1; - } + renegotiating = 0; +#if defined(MBEDTLS_SSL_RENEGOTIATION) + renegotiating = (ssl->renego_status != MBEDTLS_SSL_INITIAL_HANDSHAKE); #endif - if (!renegotiating) { + if (!renegotiating && !ssl->keep_current_message) { if ((ret = mbedtls_ssl_fetch_input(ssl, 5)) != 0) { /* No alert on a read error. */ MBEDTLS_SSL_DEBUG_RET(1, "mbedtls_ssl_fetch_input", ret); @@ -1420,24 +937,10 @@ static int ssl_parse_client_hello(mbedtls_ssl_context *ssl) buf = ssl->in_hdr; -#if defined(MBEDTLS_SSL_SRV_SUPPORT_SSLV2_CLIENT_HELLO) - int is_dtls = 0; -#if defined(MBEDTLS_SSL_PROTO_DTLS) - if (ssl->conf->transport == MBEDTLS_SSL_TRANSPORT_DATAGRAM) { - is_dtls = 1; - } -#endif - if (!is_dtls) { - if ((buf[0] & 0x80) != 0) { - return ssl_parse_client_hello_v2(ssl); - } - } -#endif - MBEDTLS_SSL_DEBUG_BUF(4, "record header", buf, mbedtls_ssl_in_hdr_len(ssl)); /* - * SSLv3/TLS Client Hello + * TLS Client Hello * * Record layer: * 0 . 0 message type @@ -1445,31 +948,20 @@ static int ssl_parse_client_hello(mbedtls_ssl_context *ssl) * 3 . 11 DTLS: epoch + record sequence number * 3 . 4 message length */ - MBEDTLS_SSL_DEBUG_MSG(3, ("client hello v3, message type: %d", + MBEDTLS_SSL_DEBUG_MSG(3, ("client hello, message type: %d", buf[0])); if (buf[0] != MBEDTLS_SSL_MSG_HANDSHAKE) { MBEDTLS_SSL_DEBUG_MSG(1, ("bad client hello message")); - return MBEDTLS_ERR_SSL_BAD_HS_CLIENT_HELLO; + return MBEDTLS_ERR_SSL_UNEXPECTED_MESSAGE; } - MBEDTLS_SSL_DEBUG_MSG(3, ("client hello v3, message len.: %d", - (ssl->in_len[0] << 8) | ssl->in_len[1])); + MBEDTLS_SSL_DEBUG_MSG(3, ("client hello, message len.: %d", + MBEDTLS_GET_UINT16_BE(ssl->in_len, 0))); - MBEDTLS_SSL_DEBUG_MSG(3, ("client hello v3, protocol version: [%d:%d]", + MBEDTLS_SSL_DEBUG_MSG(3, ("client hello, protocol version: [%d:%d]", buf[1], buf[2])); - mbedtls_ssl_read_version(&major, &minor, ssl->conf->transport, buf + 1); - - /* According to RFC 5246 Appendix E.1, the version here is typically - * "{03,00}, the lowest version number supported by the client, [or] the - * value of ClientHello.client_version", so the only meaningful check here - * is the major version shouldn't be less than 3 */ - if (major < MBEDTLS_SSL_MAJOR_VERSION_3) { - MBEDTLS_SSL_DEBUG_MSG(1, ("bad client hello message")); - return MBEDTLS_ERR_SSL_BAD_HS_CLIENT_HELLO; - } - /* For DTLS if this is the initial handshake, remember the client sequence * number to use it in our next message (RFC 6347 4.2.1) */ #if defined(MBEDTLS_SSL_PROTO_DTLS) @@ -1481,10 +973,11 @@ static int ssl_parse_client_hello(mbedtls_ssl_context *ssl) /* Epoch should be 0 for initial handshakes */ if (ssl->in_ctr[0] != 0 || ssl->in_ctr[1] != 0) { MBEDTLS_SSL_DEBUG_MSG(1, ("bad client hello message")); - return MBEDTLS_ERR_SSL_BAD_HS_CLIENT_HELLO; + return MBEDTLS_ERR_SSL_ILLEGAL_PARAMETER; } - memcpy(ssl->cur_out_ctr + 2, ssl->in_ctr + 2, 6); + memcpy(&ssl->cur_out_ctr[2], ssl->in_ctr + 2, + sizeof(ssl->cur_out_ctr) - 2); #if defined(MBEDTLS_SSL_DTLS_ANTI_REPLAY) if (mbedtls_ssl_dtls_replay_check(ssl) != 0) { @@ -1500,7 +993,7 @@ static int ssl_parse_client_hello(mbedtls_ssl_context *ssl) } #endif /* MBEDTLS_SSL_PROTO_DTLS */ - msg_len = (ssl->in_len[0] << 8) | ssl->in_len[1]; + msg_len = MBEDTLS_GET_UINT16_BE(ssl->in_len, 0); #if defined(MBEDTLS_SSL_RENEGOTIATION) if (ssl->renego_status != MBEDTLS_SSL_INITIAL_HANDSHAKE) { @@ -1509,31 +1002,39 @@ static int ssl_parse_client_hello(mbedtls_ssl_context *ssl) } else #endif { - if (msg_len > MBEDTLS_SSL_IN_CONTENT_LEN) { - MBEDTLS_SSL_DEBUG_MSG(1, ("bad client hello message")); - return MBEDTLS_ERR_SSL_BAD_HS_CLIENT_HELLO; - } + if (ssl->keep_current_message) { + ssl->keep_current_message = 0; + } else { + if (msg_len > MBEDTLS_SSL_IN_CONTENT_LEN) { + MBEDTLS_SSL_DEBUG_MSG(1, ("bad client hello message")); + return MBEDTLS_ERR_SSL_ILLEGAL_PARAMETER; + } - if ((ret = mbedtls_ssl_fetch_input(ssl, - mbedtls_ssl_in_hdr_len(ssl) + msg_len)) != 0) { - MBEDTLS_SSL_DEBUG_RET(1, "mbedtls_ssl_fetch_input", ret); - return ret; - } + if ((ret = mbedtls_ssl_fetch_input(ssl, + mbedtls_ssl_in_hdr_len(ssl) + msg_len)) != 0) { + MBEDTLS_SSL_DEBUG_RET(1, "mbedtls_ssl_fetch_input", ret); + return ret; + } - /* Done reading this record, get ready for the next one */ + /* Done reading this record, get ready for the next one */ #if defined(MBEDTLS_SSL_PROTO_DTLS) - if (ssl->conf->transport == MBEDTLS_SSL_TRANSPORT_DATAGRAM) { - ssl->next_record_offset = msg_len + mbedtls_ssl_in_hdr_len(ssl); - } else + if (ssl->conf->transport == MBEDTLS_SSL_TRANSPORT_DATAGRAM) { + ssl->next_record_offset = msg_len + mbedtls_ssl_in_hdr_len(ssl); + } else #endif - ssl->in_left = 0; + ssl->in_left = 0; + } } buf = ssl->in_msg; MBEDTLS_SSL_DEBUG_BUF(4, "record contents", buf, msg_len); - ssl->handshake->update_checksum(ssl, buf, msg_len); + ret = ssl->handshake->update_checksum(ssl, buf, msg_len); + if (0 != ret) { + MBEDTLS_SSL_DEBUG_RET(1, ("update_checksum"), ret); + return ret; + } /* * Handshake layer: @@ -1545,31 +1046,36 @@ static int ssl_parse_client_hello(mbedtls_ssl_context *ssl) */ if (msg_len < mbedtls_ssl_hs_hdr_len(ssl)) { MBEDTLS_SSL_DEBUG_MSG(1, ("bad client hello message")); - return MBEDTLS_ERR_SSL_BAD_HS_CLIENT_HELLO; + return MBEDTLS_ERR_SSL_DECODE_ERROR; } MBEDTLS_SSL_DEBUG_MSG(3, ("client hello v3, handshake type: %d", buf[0])); if (buf[0] != MBEDTLS_SSL_HS_CLIENT_HELLO) { MBEDTLS_SSL_DEBUG_MSG(1, ("bad client hello message")); - return MBEDTLS_ERR_SSL_BAD_HS_CLIENT_HELLO; + return MBEDTLS_ERR_SSL_UNEXPECTED_MESSAGE; } + { + size_t handshake_len = MBEDTLS_GET_UINT24_BE(buf, 1); + MBEDTLS_SSL_DEBUG_MSG(3, ("client hello v3, handshake len.: %u", + (unsigned) handshake_len)); + + /* The record layer has a record size limit of 2^14 - 1 and + * fragmentation is not supported, so buf[1] should be zero. */ + if (buf[1] != 0) { + MBEDTLS_SSL_DEBUG_MSG(1, ("bad client hello message: %u != 0", + (unsigned) buf[1])); + return MBEDTLS_ERR_SSL_DECODE_ERROR; + } - MBEDTLS_SSL_DEBUG_MSG(3, ("client hello v3, handshake len.: %d", - (buf[1] << 16) | (buf[2] << 8) | buf[3])); - - if (buf[1] != 0) { - MBEDTLS_SSL_DEBUG_MSG(1, ("bad client hello message: %u != 0", - (unsigned) buf[1])); - return MBEDTLS_ERR_SSL_BAD_HS_CLIENT_HELLO; - } - /* We don't support fragmentation of ClientHello (yet?) */ - if (msg_len != mbedtls_ssl_hs_hdr_len(ssl) + ((buf[2] << 8) | buf[3])) { - MBEDTLS_SSL_DEBUG_MSG(1, ("bad client hello message: %u != %u + %u", - (unsigned) msg_len, - (unsigned) mbedtls_ssl_hs_hdr_len(ssl), - (unsigned) (buf[2] << 8) | buf[3])); - return MBEDTLS_ERR_SSL_BAD_HS_CLIENT_HELLO; + /* We don't support fragmentation of ClientHello (yet?) */ + if (msg_len != mbedtls_ssl_hs_hdr_len(ssl) + handshake_len) { + MBEDTLS_SSL_DEBUG_MSG(1, ("bad client hello message: %u != %u + %u", + (unsigned) msg_len, + (unsigned) mbedtls_ssl_hs_hdr_len(ssl), + (unsigned) handshake_len)); + return MBEDTLS_ERR_SSL_DECODE_ERROR; + } } #if defined(MBEDTLS_SSL_PROTO_DTLS) @@ -1581,39 +1087,39 @@ static int ssl_parse_client_hello(mbedtls_ssl_context *ssl) #if defined(MBEDTLS_SSL_RENEGOTIATION) if (ssl->renego_status == MBEDTLS_SSL_RENEGOTIATION_IN_PROGRESS) { /* This couldn't be done in ssl_prepare_handshake_record() */ - unsigned int cli_msg_seq = (ssl->in_msg[4] << 8) | - ssl->in_msg[5]; - + unsigned int cli_msg_seq = (unsigned int) MBEDTLS_GET_UINT16_BE(ssl->in_msg, 4); if (cli_msg_seq != ssl->handshake->in_msg_seq) { MBEDTLS_SSL_DEBUG_MSG(1, ("bad client hello message_seq: " "%u (expected %u)", cli_msg_seq, ssl->handshake->in_msg_seq)); - return MBEDTLS_ERR_SSL_BAD_HS_CLIENT_HELLO; + return MBEDTLS_ERR_SSL_DECODE_ERROR; } ssl->handshake->in_msg_seq++; } else #endif { - unsigned int cli_msg_seq = (ssl->in_msg[4] << 8) | - ssl->in_msg[5]; + unsigned int cli_msg_seq = (unsigned int) MBEDTLS_GET_UINT16_BE(ssl->in_msg, 4); ssl->handshake->out_msg_seq = cli_msg_seq; ssl->handshake->in_msg_seq = cli_msg_seq + 1; } - - /* - * For now we don't support fragmentation, so make sure - * fragment_offset == 0 and fragment_length == length - */ - MBEDTLS_SSL_DEBUG_MSG( - 4, ("fragment_offset=%u fragment_length=%u length=%u", - (unsigned) (ssl->in_msg[6] << 16 | ssl->in_msg[7] << 8 | ssl->in_msg[8]), - (unsigned) (ssl->in_msg[9] << 16 | ssl->in_msg[10] << 8 | ssl->in_msg[11]), - (unsigned) (ssl->in_msg[1] << 16 | ssl->in_msg[2] << 8 | ssl->in_msg[3]))); - if (ssl->in_msg[6] != 0 || ssl->in_msg[7] != 0 || ssl->in_msg[8] != 0 || - memcmp(ssl->in_msg + 1, ssl->in_msg + 9, 3) != 0) { - MBEDTLS_SSL_DEBUG_MSG(1, ("ClientHello fragmentation not supported")); - return MBEDTLS_ERR_SSL_FEATURE_UNAVAILABLE; + { + /* + * For now we don't support fragmentation, so make sure + * fragment_offset == 0 and fragment_length == length + */ + size_t fragment_offset, fragment_length, length; + fragment_offset = MBEDTLS_GET_UINT24_BE(ssl->in_msg, 6); + fragment_length = MBEDTLS_GET_UINT24_BE(ssl->in_msg, 9); + length = MBEDTLS_GET_UINT24_BE(ssl->in_msg, 1); + MBEDTLS_SSL_DEBUG_MSG( + 4, ("fragment_offset=%u fragment_length=%u length=%u", + (unsigned) fragment_offset, (unsigned) fragment_length, + (unsigned) length)); + if (fragment_offset != 0 || length != fragment_length) { + MBEDTLS_SSL_DEBUG_MSG(1, ("ClientHello fragmentation not supported")); + return MBEDTLS_ERR_SSL_FEATURE_UNAVAILABLE; + } } } #endif /* MBEDTLS_SSL_PROTO_DTLS */ @@ -1622,11 +1128,11 @@ static int ssl_parse_client_hello(mbedtls_ssl_context *ssl) msg_len -= mbedtls_ssl_hs_hdr_len(ssl); /* - * ClientHello layer: + * ClientHello layout: * 0 . 1 protocol version * 2 . 33 random bytes (starting with 4 bytes of Unix time) - * 34 . 35 session id length (1 byte) - * 35 . 34+x session id + * 34 . 34 session id length (1 byte) + * 35 . 34+x session id, where x = session id length from byte 34 * 35+x . 35+x DTLS only: cookie length (1 byte) * 36+x . .. DTLS only: cookie * .. . .. ciphersuite list length (2 bytes) @@ -1644,7 +1150,7 @@ static int ssl_parse_client_hello(mbedtls_ssl_context *ssl) */ if (msg_len < 38) { MBEDTLS_SSL_DEBUG_MSG(1, ("bad client hello message")); - return MBEDTLS_ERR_SSL_BAD_HS_CLIENT_HELLO; + return MBEDTLS_ERR_SSL_DECODE_ERROR; } /* @@ -1652,28 +1158,16 @@ static int ssl_parse_client_hello(mbedtls_ssl_context *ssl) */ MBEDTLS_SSL_DEBUG_BUF(3, "client hello, version", buf, 2); - mbedtls_ssl_read_version(&ssl->major_ver, &ssl->minor_ver, - ssl->conf->transport, buf); + ssl->tls_version = (mbedtls_ssl_protocol_version) mbedtls_ssl_read_version(buf, + ssl->conf->transport); + ssl->session_negotiate->tls_version = ssl->tls_version; + ssl->session_negotiate->endpoint = ssl->conf->endpoint; - ssl->handshake->max_major_ver = ssl->major_ver; - ssl->handshake->max_minor_ver = ssl->minor_ver; - - if (ssl->major_ver < ssl->conf->min_major_ver || - ssl->minor_ver < ssl->conf->min_minor_ver) { - MBEDTLS_SSL_DEBUG_MSG(1, ("client only supports ssl smaller than minimum" - " [%d:%d] < [%d:%d]", - ssl->major_ver, ssl->minor_ver, - ssl->conf->min_major_ver, ssl->conf->min_minor_ver)); + if (ssl->tls_version != MBEDTLS_SSL_VERSION_TLS1_2) { + MBEDTLS_SSL_DEBUG_MSG(1, ("server only supports TLS 1.2")); mbedtls_ssl_send_alert_message(ssl, MBEDTLS_SSL_ALERT_LEVEL_FATAL, MBEDTLS_SSL_ALERT_MSG_PROTOCOL_VERSION); - return MBEDTLS_ERR_SSL_BAD_HS_PROTOCOL_VERSION; - } - - if (ssl->major_ver > ssl->conf->max_major_ver) { - ssl->major_ver = ssl->conf->max_major_ver; - ssl->minor_ver = ssl->conf->max_minor_ver; - } else if (ssl->minor_ver > ssl->conf->max_minor_ver) { - ssl->minor_ver = ssl->conf->max_minor_ver; + return MBEDTLS_ERR_SSL_BAD_PROTOCOL_VERSION; } /* @@ -1693,7 +1187,7 @@ static int ssl_parse_client_hello(mbedtls_ssl_context *ssl) MBEDTLS_SSL_DEBUG_MSG(1, ("bad client hello message")); mbedtls_ssl_send_alert_message(ssl, MBEDTLS_SSL_ALERT_LEVEL_FATAL, MBEDTLS_SSL_ALERT_MSG_DECODE_ERROR); - return MBEDTLS_ERR_SSL_BAD_HS_CLIENT_HELLO; + return MBEDTLS_ERR_SSL_DECODE_ERROR; } MBEDTLS_SSL_DEBUG_BUF(3, "client hello, session id", buf + 35, sess_len); @@ -1715,8 +1209,8 @@ static int ssl_parse_client_hello(mbedtls_ssl_context *ssl) if (cookie_offset + 1 + cookie_len + 2 > msg_len) { MBEDTLS_SSL_DEBUG_MSG(1, ("bad client hello message")); mbedtls_ssl_send_alert_message(ssl, MBEDTLS_SSL_ALERT_LEVEL_FATAL, - MBEDTLS_SSL_ALERT_MSG_PROTOCOL_VERSION); - return MBEDTLS_ERR_SSL_BAD_HS_CLIENT_HELLO; + MBEDTLS_SSL_ALERT_MSG_DECODE_ERROR); + return MBEDTLS_ERR_SSL_DECODE_ERROR; } MBEDTLS_SSL_DEBUG_BUF(3, "client hello, cookie", @@ -1732,10 +1226,10 @@ static int ssl_parse_client_hello(mbedtls_ssl_context *ssl) buf + cookie_offset + 1, cookie_len, ssl->cli_id, ssl->cli_id_len) != 0) { MBEDTLS_SSL_DEBUG_MSG(2, ("cookie verification failed")); - ssl->handshake->verify_cookie_len = 1; + ssl->handshake->cookie_verify_result = 1; } else { MBEDTLS_SSL_DEBUG_MSG(2, ("cookie verification passed")); - ssl->handshake->verify_cookie_len = 0; + ssl->handshake->cookie_verify_result = 0; } } else #endif /* MBEDTLS_SSL_DTLS_HELLO_VERIFY */ @@ -1744,7 +1238,7 @@ static int ssl_parse_client_hello(mbedtls_ssl_context *ssl) if (cookie_len != 0) { /* This may be an attacker's probe, so don't send an alert */ MBEDTLS_SSL_DEBUG_MSG(1, ("bad client hello message")); - return MBEDTLS_ERR_SSL_BAD_HS_CLIENT_HELLO; + return MBEDTLS_ERR_SSL_DECODE_ERROR; } MBEDTLS_SSL_DEBUG_MSG(2, ("cookie verification skipped")); @@ -1758,8 +1252,7 @@ static int ssl_parse_client_hello(mbedtls_ssl_context *ssl) #endif /* MBEDTLS_SSL_PROTO_DTLS */ ciph_offset = 35 + sess_len; - ciph_len = (buf[ciph_offset + 0] << 8) - | (buf[ciph_offset + 1]); + ciph_len = MBEDTLS_GET_UINT16_BE(buf, ciph_offset); if (ciph_len < 2 || ciph_len + 2 + ciph_offset + 1 > msg_len || /* 1 for comp. alg. len */ @@ -1767,14 +1260,17 @@ static int ssl_parse_client_hello(mbedtls_ssl_context *ssl) MBEDTLS_SSL_DEBUG_MSG(1, ("bad client hello message")); mbedtls_ssl_send_alert_message(ssl, MBEDTLS_SSL_ALERT_LEVEL_FATAL, MBEDTLS_SSL_ALERT_MSG_DECODE_ERROR); - return MBEDTLS_ERR_SSL_BAD_HS_CLIENT_HELLO; + return MBEDTLS_ERR_SSL_DECODE_ERROR; } MBEDTLS_SSL_DEBUG_BUF(3, "client hello, ciphersuitelist", buf + ciph_offset + 2, ciph_len); /* - * Check the compression algorithms length and pick one + * Check the compression algorithm's length. + * The list contents are ignored because implementing + * MBEDTLS_SSL_COMPRESS_NULL is mandatory and is the only + * option supported by Mbed TLS. */ comp_offset = ciph_offset + 2 + ciph_len; @@ -1786,33 +1282,12 @@ static int ssl_parse_client_hello(mbedtls_ssl_context *ssl) MBEDTLS_SSL_DEBUG_MSG(1, ("bad client hello message")); mbedtls_ssl_send_alert_message(ssl, MBEDTLS_SSL_ALERT_LEVEL_FATAL, MBEDTLS_SSL_ALERT_MSG_DECODE_ERROR); - return MBEDTLS_ERR_SSL_BAD_HS_CLIENT_HELLO; + return MBEDTLS_ERR_SSL_DECODE_ERROR; } MBEDTLS_SSL_DEBUG_BUF(3, "client hello, compression", buf + comp_offset + 1, comp_len); - ssl->session_negotiate->compression = MBEDTLS_SSL_COMPRESS_NULL; -#if defined(MBEDTLS_ZLIB_SUPPORT) - for (i = 0; i < comp_len; ++i) { - if (buf[comp_offset + 1 + i] == MBEDTLS_SSL_COMPRESS_DEFLATE) { - ssl->session_negotiate->compression = MBEDTLS_SSL_COMPRESS_DEFLATE; - break; - } - } -#endif - - /* See comments in ssl_write_client_hello() */ -#if defined(MBEDTLS_SSL_PROTO_DTLS) - if (ssl->conf->transport == MBEDTLS_SSL_TRANSPORT_DATAGRAM) { - ssl->session_negotiate->compression = MBEDTLS_SSL_COMPRESS_NULL; - } -#endif - - /* Do not parse the extensions if the protocol is SSLv3 */ -#if defined(MBEDTLS_SSL_PROTO_SSL3) - if ((ssl->major_ver != 3) || (ssl->minor_ver != 0)) { -#endif /* * Check the extension length */ @@ -1822,17 +1297,16 @@ static int ssl_parse_client_hello(mbedtls_ssl_context *ssl) MBEDTLS_SSL_DEBUG_MSG(1, ("bad client hello message")); mbedtls_ssl_send_alert_message(ssl, MBEDTLS_SSL_ALERT_LEVEL_FATAL, MBEDTLS_SSL_ALERT_MSG_DECODE_ERROR); - return MBEDTLS_ERR_SSL_BAD_HS_CLIENT_HELLO; + return MBEDTLS_ERR_SSL_DECODE_ERROR; } - ext_len = (buf[ext_offset + 0] << 8) - | (buf[ext_offset + 1]); + ext_len = MBEDTLS_GET_UINT16_BE(buf, ext_offset); if (msg_len != ext_offset + 2 + ext_len) { MBEDTLS_SSL_DEBUG_MSG(1, ("bad client hello message")); mbedtls_ssl_send_alert_message(ssl, MBEDTLS_SSL_ALERT_LEVEL_FATAL, MBEDTLS_SSL_ALERT_MSG_DECODE_ERROR); - return MBEDTLS_ERR_SSL_BAD_HS_CLIENT_HELLO; + return MBEDTLS_ERR_SSL_DECODE_ERROR; } } else { ext_len = 0; @@ -1848,26 +1322,23 @@ static int ssl_parse_client_hello(mbedtls_ssl_context *ssl) MBEDTLS_SSL_DEBUG_MSG(1, ("bad client hello message")); mbedtls_ssl_send_alert_message(ssl, MBEDTLS_SSL_ALERT_LEVEL_FATAL, MBEDTLS_SSL_ALERT_MSG_DECODE_ERROR); - return MBEDTLS_ERR_SSL_BAD_HS_CLIENT_HELLO; + return MBEDTLS_ERR_SSL_DECODE_ERROR; } - ext_id = ((ext[0] << 8) | (ext[1])); - ext_size = ((ext[2] << 8) | (ext[3])); + ext_id = MBEDTLS_GET_UINT16_BE(ext, 0); + ext_size = MBEDTLS_GET_UINT16_BE(ext, 2); if (ext_size + 4 > ext_len) { MBEDTLS_SSL_DEBUG_MSG(1, ("bad client hello message")); mbedtls_ssl_send_alert_message(ssl, MBEDTLS_SSL_ALERT_LEVEL_FATAL, MBEDTLS_SSL_ALERT_MSG_DECODE_ERROR); - return MBEDTLS_ERR_SSL_BAD_HS_CLIENT_HELLO; + return MBEDTLS_ERR_SSL_DECODE_ERROR; } switch (ext_id) { #if defined(MBEDTLS_SSL_SERVER_NAME_INDICATION) case MBEDTLS_TLS_EXT_SERVERNAME: MBEDTLS_SSL_DEBUG_MSG(3, ("found ServerName extension")); - if (ssl->conf->f_sni == NULL) { - break; - } - - ret = ssl_parse_servername_ext(ssl, ext + 4, ext_size); + ret = mbedtls_ssl_parse_server_name_ext(ssl, ext + 4, + ext + 4 + ext_size); if (ret != 0) { return ret; } @@ -1886,27 +1357,26 @@ static int ssl_parse_client_hello(mbedtls_ssl_context *ssl) } break; -#if defined(MBEDTLS_SSL_PROTO_TLS1_2) && \ - defined(MBEDTLS_KEY_EXCHANGE_WITH_CERT_ENABLED) +#if defined(MBEDTLS_KEY_EXCHANGE_WITH_CERT_ENABLED) case MBEDTLS_TLS_EXT_SIG_ALG: MBEDTLS_SSL_DEBUG_MSG(3, ("found signature_algorithms extension")); - ret = ssl_parse_signature_algorithms_ext(ssl, ext + 4, ext_size); + ret = mbedtls_ssl_parse_sig_alg_ext(ssl, ext + 4, ext + 4 + ext_size); if (ret != 0) { return ret; } sig_hash_alg_ext_present = 1; break; -#endif /* MBEDTLS_SSL_PROTO_TLS1_2 && - MBEDTLS_KEY_EXCHANGE_WITH_CERT_ENABLED */ +#endif /* MBEDTLS_KEY_EXCHANGE_WITH_CERT_ENABLED */ -#if defined(MBEDTLS_ECDH_C) || defined(MBEDTLS_ECDSA_C) || \ +#if defined(MBEDTLS_KEY_EXCHANGE_SOME_ECDH_OR_ECDHE_1_2_ENABLED) || \ + defined(MBEDTLS_KEY_EXCHANGE_ECDSA_CERT_REQ_ALLOWED_ENABLED) || \ defined(MBEDTLS_KEY_EXCHANGE_ECJPAKE_ENABLED) - case MBEDTLS_TLS_EXT_SUPPORTED_ELLIPTIC_CURVES: + case MBEDTLS_TLS_EXT_SUPPORTED_GROUPS: MBEDTLS_SSL_DEBUG_MSG(3, ("found supported elliptic curves extension")); - ret = ssl_parse_supported_elliptic_curves(ssl, ext + 4, ext_size); + ret = ssl_parse_supported_groups_ext(ssl, ext + 4, ext_size); if (ret != 0) { return ret; } @@ -1921,7 +1391,8 @@ static int ssl_parse_client_hello(mbedtls_ssl_context *ssl) return ret; } break; -#endif /* MBEDTLS_ECDH_C || MBEDTLS_ECDSA_C || +#endif /* MBEDTLS_KEY_EXCHANGE_SOME_ECDH_OR_ECDHE_1_2_ENABLED || \ + MBEDTLS_KEY_EXCHANGE_ECDSA_CERT_REQ_ALLOWED_ENABLED || MBEDTLS_KEY_EXCHANGE_ECJPAKE_ENABLED */ #if defined(MBEDTLS_KEY_EXCHANGE_ECJPAKE_ENABLED) @@ -1946,17 +1417,6 @@ static int ssl_parse_client_hello(mbedtls_ssl_context *ssl) break; #endif /* MBEDTLS_SSL_MAX_FRAGMENT_LENGTH */ -#if defined(MBEDTLS_SSL_TRUNCATED_HMAC) - case MBEDTLS_TLS_EXT_TRUNCATED_HMAC: - MBEDTLS_SSL_DEBUG_MSG(3, ("found truncated hmac extension")); - - ret = ssl_parse_truncated_hmac_ext(ssl, ext + 4, ext_size); - if (ret != 0) { - return ret; - } - break; -#endif /* MBEDTLS_SSL_TRUNCATED_HMAC */ - #if defined(MBEDTLS_SSL_DTLS_CONNECTION_ID) case MBEDTLS_TLS_EXT_CID: MBEDTLS_SSL_DEBUG_MSG(3, ("found CID extension")); @@ -1966,7 +1426,7 @@ static int ssl_parse_client_hello(mbedtls_ssl_context *ssl) return ret; } break; -#endif /* MBEDTLS_SSL_TRUNCATED_HMAC */ +#endif /* MBEDTLS_SSL_DTLS_CONNECTION_ID */ #if defined(MBEDTLS_SSL_ENCRYPT_THEN_MAC) case MBEDTLS_TLS_EXT_ENCRYPT_THEN_MAC: @@ -2005,7 +1465,8 @@ static int ssl_parse_client_hello(mbedtls_ssl_context *ssl) case MBEDTLS_TLS_EXT_ALPN: MBEDTLS_SSL_DEBUG_MSG(3, ("found alpn extension")); - ret = ssl_parse_alpn_ext(ssl, ext + 4, ext_size); + ret = mbedtls_ssl_parse_alpn_ext(ssl, ext + 4, + ext + 4 + ext_size); if (ret != 0) { return ret; } @@ -2031,48 +1492,35 @@ static int ssl_parse_client_hello(mbedtls_ssl_context *ssl) ext_len -= 4 + ext_size; ext += 4 + ext_size; } -#if defined(MBEDTLS_SSL_PROTO_SSL3) -} -#endif - -#if defined(MBEDTLS_SSL_FALLBACK_SCSV) - for (i = 0, p = buf + ciph_offset + 2; i < ciph_len; i += 2, p += 2) { - if (MBEDTLS_GET_UINT16_BE(p, 0) == MBEDTLS_SSL_FALLBACK_SCSV_VALUE) { - MBEDTLS_SSL_DEBUG_MSG(2, ("received FALLBACK_SCSV")); - - if (ssl->minor_ver < ssl->conf->max_minor_ver) { - MBEDTLS_SSL_DEBUG_MSG(1, ("inapropriate fallback")); - - mbedtls_ssl_send_alert_message(ssl, MBEDTLS_SSL_ALERT_LEVEL_FATAL, - MBEDTLS_SSL_ALERT_MSG_INAPROPRIATE_FALLBACK); - - return MBEDTLS_ERR_SSL_BAD_HS_CLIENT_HELLO; - } - - break; - } - } -#endif /* MBEDTLS_SSL_FALLBACK_SCSV */ -#if defined(MBEDTLS_SSL_PROTO_TLS1_2) && \ - defined(MBEDTLS_KEY_EXCHANGE_WITH_CERT_ENABLED) +#if defined(MBEDTLS_KEY_EXCHANGE_WITH_CERT_ENABLED) /* * Try to fall back to default hash SHA1 if the client * hasn't provided any preferred signature-hash combinations. */ - if (sig_hash_alg_ext_present == 0) { - mbedtls_md_type_t md_default = MBEDTLS_MD_SHA1; + if (!sig_hash_alg_ext_present) { + uint16_t *received_sig_algs = ssl->handshake->received_sig_algs; + const uint16_t default_sig_algs[] = { +#if defined(MBEDTLS_KEY_EXCHANGE_ECDSA_CERT_REQ_ALLOWED_ENABLED) + MBEDTLS_SSL_TLS12_SIG_AND_HASH_ALG(MBEDTLS_SSL_SIG_ECDSA, + MBEDTLS_SSL_HASH_SHA1), +#endif +#if defined(MBEDTLS_RSA_C) + MBEDTLS_SSL_TLS12_SIG_AND_HASH_ALG(MBEDTLS_SSL_SIG_RSA, + MBEDTLS_SSL_HASH_SHA1), +#endif + MBEDTLS_TLS_SIG_NONE + }; - if (mbedtls_ssl_check_sig_hash(ssl, md_default) != 0) { - md_default = MBEDTLS_MD_NONE; - } + MBEDTLS_STATIC_ASSERT(sizeof(default_sig_algs) / sizeof(default_sig_algs[0]) + <= MBEDTLS_RECEIVED_SIG_ALGS_SIZE, + "default_sig_algs is too big"); - mbedtls_ssl_sig_hash_set_const_hash(&ssl->handshake->hash_algs, md_default); + memcpy(received_sig_algs, default_sig_algs, sizeof(default_sig_algs)); } -#endif /* MBEDTLS_SSL_PROTO_TLS1_2 && - MBEDTLS_KEY_EXCHANGE_WITH_CERT_ENABLED */ +#endif /* MBEDTLS_KEY_EXCHANGE_WITH_CERT_ENABLED */ /* * Check for TLS_EMPTY_RENEGOTIATION_INFO_SCSV @@ -2086,7 +1534,7 @@ static int ssl_parse_client_hello(mbedtls_ssl_context *ssl) "during renegotiation")); mbedtls_ssl_send_alert_message(ssl, MBEDTLS_SSL_ALERT_LEVEL_FATAL, MBEDTLS_SSL_ALERT_MSG_HANDSHAKE_FAILURE); - return MBEDTLS_ERR_SSL_BAD_HS_CLIENT_HELLO; + return MBEDTLS_ERR_SSL_HANDSHAKE_FAILURE; } #endif ssl->secure_renegotiation = MBEDTLS_SSL_SECURE_RENEGOTIATION; @@ -2124,68 +1572,82 @@ static int ssl_parse_client_hello(mbedtls_ssl_context *ssl) if (handshake_failure == 1) { mbedtls_ssl_send_alert_message(ssl, MBEDTLS_SSL_ALERT_LEVEL_FATAL, MBEDTLS_SSL_ALERT_MSG_HANDSHAKE_FAILURE); - return MBEDTLS_ERR_SSL_BAD_HS_CLIENT_HELLO; + return MBEDTLS_ERR_SSL_HANDSHAKE_FAILURE; + } + + /* + * Server certification selection (after processing TLS extensions) + */ + if (ssl->conf->f_cert_cb && (ret = ssl->conf->f_cert_cb(ssl)) != 0) { + MBEDTLS_SSL_DEBUG_RET(1, "f_cert_cb", ret); + return ret; } +#if defined(MBEDTLS_SSL_SERVER_NAME_INDICATION) + ssl->handshake->sni_name = NULL; + ssl->handshake->sni_name_len = 0; +#endif /* * Search for a matching ciphersuite * (At the end because we need information from the EC-based extensions - * and certificate from the SNI callback triggered by the SNI extension.) + * and certificate from the SNI callback triggered by the SNI extension + * or certificate from server certificate selection callback.) */ got_common_suite = 0; - ciphersuites = ssl->conf->ciphersuite_list[ssl->minor_ver]; + ciphersuites = ssl->conf->ciphersuite_list; ciphersuite_info = NULL; -#if defined(MBEDTLS_SSL_SRV_RESPECT_CLIENT_PREFERENCE) - for (j = 0, p = buf + ciph_offset + 2; j < ciph_len; j += 2, p += 2) { - for (i = 0; ciphersuites[i] != 0; i++) { - if (MBEDTLS_GET_UINT16_BE(p, 0) != ciphersuites[i]) { - continue; - } - got_common_suite = 1; + if (ssl->conf->respect_cli_pref == MBEDTLS_SSL_SRV_CIPHERSUITE_ORDER_CLIENT) { + for (j = 0, p = buf + ciph_offset + 2; j < ciph_len; j += 2, p += 2) { + for (i = 0; ciphersuites[i] != 0; i++) { + if (MBEDTLS_GET_UINT16_BE(p, 0) != ciphersuites[i]) { + continue; + } - if ((ret = ssl_ciphersuite_match(ssl, ciphersuites[i], - &ciphersuite_info)) != 0) { - return ret; - } + got_common_suite = 1; - if (ciphersuite_info != NULL) { - goto have_ciphersuite; + if ((ret = ssl_ciphersuite_match(ssl, ciphersuites[i], + &ciphersuite_info)) != 0) { + return ret; + } + + if (ciphersuite_info != NULL) { + goto have_ciphersuite; + } } } - } -#else - for (i = 0; ciphersuites[i] != 0; i++) { - for (j = 0, p = buf + ciph_offset + 2; j < ciph_len; j += 2, p += 2) { - if (MBEDTLS_GET_UINT16_BE(p, 0) != ciphersuites[i]) { - continue; - } + } else { + for (i = 0; ciphersuites[i] != 0; i++) { + for (j = 0, p = buf + ciph_offset + 2; j < ciph_len; j += 2, p += 2) { + if (MBEDTLS_GET_UINT16_BE(p, 0) != ciphersuites[i]) { + continue; + } - got_common_suite = 1; + got_common_suite = 1; - if ((ret = ssl_ciphersuite_match(ssl, ciphersuites[i], - &ciphersuite_info)) != 0) { - return ret; - } + if ((ret = ssl_ciphersuite_match(ssl, ciphersuites[i], + &ciphersuite_info)) != 0) { + return ret; + } - if (ciphersuite_info != NULL) { - goto have_ciphersuite; + if (ciphersuite_info != NULL) { + goto have_ciphersuite; + } } } } -#endif if (got_common_suite) { MBEDTLS_SSL_DEBUG_MSG(1, ("got ciphersuites in common, " "but none of them usable")); mbedtls_ssl_send_alert_message(ssl, MBEDTLS_SSL_ALERT_LEVEL_FATAL, MBEDTLS_SSL_ALERT_MSG_HANDSHAKE_FAILURE); - return MBEDTLS_ERR_SSL_NO_USABLE_CIPHERSUITE; + return MBEDTLS_ERR_SSL_HANDSHAKE_FAILURE; } else { MBEDTLS_SSL_DEBUG_MSG(1, ("got no ciphersuites in common")); mbedtls_ssl_send_alert_message(ssl, MBEDTLS_SSL_ALERT_LEVEL_FATAL, MBEDTLS_SSL_ALERT_MSG_HANDSHAKE_FAILURE); - return MBEDTLS_ERR_SSL_NO_CIPHER_CHOSEN; + return MBEDTLS_ERR_SSL_HANDSHAKE_FAILURE; } have_ciphersuite: @@ -2204,19 +1666,16 @@ static int ssl_parse_client_hello(mbedtls_ssl_context *ssl) /* Debugging-only output for testsuite */ #if defined(MBEDTLS_DEBUG_C) && \ - defined(MBEDTLS_SSL_PROTO_TLS1_2) && \ defined(MBEDTLS_KEY_EXCHANGE_WITH_CERT_ENABLED) - if (ssl->minor_ver == MBEDTLS_SSL_MINOR_VERSION_3) { - mbedtls_pk_type_t sig_alg = mbedtls_ssl_get_ciphersuite_sig_alg(ciphersuite_info); - if (sig_alg != MBEDTLS_PK_NONE) { - mbedtls_md_type_t md_alg = mbedtls_ssl_sig_hash_set_find(&ssl->handshake->hash_algs, - sig_alg); - MBEDTLS_SSL_DEBUG_MSG(3, ("client hello v3, signature_algorithm ext: %d", - mbedtls_ssl_hash_from_md_alg(md_alg))); - } else { - MBEDTLS_SSL_DEBUG_MSG(3, ("no hash algorithm for signature algorithm " - "%u - should not happen", (unsigned) sig_alg)); - } + mbedtls_pk_type_t sig_alg = mbedtls_ssl_get_ciphersuite_sig_alg(ciphersuite_info); + if (sig_alg != MBEDTLS_PK_NONE) { + unsigned int sig_hash = mbedtls_ssl_tls12_get_preferred_hash_for_sig_alg( + ssl, mbedtls_ssl_sig_from_pk_alg(sig_alg)); + MBEDTLS_SSL_DEBUG_MSG(3, ("client hello v3, signature_algorithm ext: %u", + sig_hash)); + } else { + MBEDTLS_SSL_DEBUG_MSG(3, ("no hash algorithm for signature algorithm " + "%u - should not happen", (unsigned) sig_alg)); } #endif @@ -2225,30 +1684,6 @@ static int ssl_parse_client_hello(mbedtls_ssl_context *ssl) return 0; } -#if defined(MBEDTLS_SSL_TRUNCATED_HMAC) -static void ssl_write_truncated_hmac_ext(mbedtls_ssl_context *ssl, - unsigned char *buf, - size_t *olen) -{ - unsigned char *p = buf; - - if (ssl->session_negotiate->trunc_hmac == MBEDTLS_SSL_TRUNC_HMAC_DISABLED) { - *olen = 0; - return; - } - - MBEDTLS_SSL_DEBUG_MSG(3, ("server hello, adding truncated hmac extension")); - - MBEDTLS_PUT_UINT16_BE(MBEDTLS_TLS_EXT_TRUNCATED_HMAC, p, 0); - p += 2; - - *p++ = 0x00; - *p++ = 0x00; - - *olen = 4; -} -#endif /* MBEDTLS_SSL_TRUNCATED_HMAC */ - #if defined(MBEDTLS_SSL_DTLS_CONNECTION_ID) static void ssl_write_cid_ext(mbedtls_ssl_context *ssl, unsigned char *buf, @@ -2276,9 +1711,6 @@ static void ssl_write_cid_ext(mbedtls_ssl_context *ssl, MBEDTLS_SSL_DEBUG_MSG(3, ("server hello, adding CID extension")); /* - * Quoting draft-ietf-tls-dtls-connection-id-05 - * https://tools.ietf.org/html/draft-ietf-tls-dtls-connection-id-05 - * * struct { * opaque cid<0..2^8-1>; * } ConnectionId; @@ -2296,18 +1728,13 @@ static void ssl_write_cid_ext(mbedtls_ssl_context *ssl, } #endif /* MBEDTLS_SSL_DTLS_CONNECTION_ID */ -#if defined(MBEDTLS_SSL_ENCRYPT_THEN_MAC) +#if defined(MBEDTLS_SSL_SOME_SUITES_USE_CBC_ETM) static void ssl_write_encrypt_then_mac_ext(mbedtls_ssl_context *ssl, unsigned char *buf, size_t *olen) { unsigned char *p = buf; const mbedtls_ssl_ciphersuite_t *suite = NULL; - const mbedtls_cipher_info_t *cipher = NULL; - - if (ssl->minor_ver == MBEDTLS_SSL_MINOR_VERSION_0) { - ssl->session_negotiate->encrypt_then_mac = MBEDTLS_SSL_ETM_DISABLED; - } /* * RFC 7366: "If a server receives an encrypt-then-MAC request extension @@ -2315,11 +1742,19 @@ static void ssl_write_encrypt_then_mac_ext(mbedtls_ssl_context *ssl, * with Associated Data (AEAD) ciphersuite, it MUST NOT send an * encrypt-then-MAC response extension back to the client." */ - if ((suite = mbedtls_ssl_ciphersuite_from_id( - ssl->session_negotiate->ciphersuite)) == NULL || - (cipher = mbedtls_cipher_info_from_type(suite->cipher)) == NULL || - cipher->mode != MBEDTLS_MODE_CBC) { + suite = mbedtls_ssl_ciphersuite_from_id( + ssl->session_negotiate->ciphersuite); + if (suite == NULL) { ssl->session_negotiate->encrypt_then_mac = MBEDTLS_SSL_ETM_DISABLED; + } else { + mbedtls_ssl_mode_t ssl_mode = + mbedtls_ssl_get_mode_from_ciphersuite( + ssl->session_negotiate->encrypt_then_mac, + suite); + + if (ssl_mode != MBEDTLS_SSL_MODE_CBC_ETM) { + ssl->session_negotiate->encrypt_then_mac = MBEDTLS_SSL_ETM_DISABLED; + } } if (ssl->session_negotiate->encrypt_then_mac == MBEDTLS_SSL_ETM_DISABLED) { @@ -2337,7 +1772,7 @@ static void ssl_write_encrypt_then_mac_ext(mbedtls_ssl_context *ssl, *olen = 4; } -#endif /* MBEDTLS_SSL_ENCRYPT_THEN_MAC */ +#endif /* MBEDTLS_SSL_SOME_SUITES_USE_CBC_ETM */ #if defined(MBEDTLS_SSL_EXTENDED_MASTER_SECRET) static void ssl_write_extended_ms_ext(mbedtls_ssl_context *ssl, @@ -2346,8 +1781,7 @@ static void ssl_write_extended_ms_ext(mbedtls_ssl_context *ssl, { unsigned char *p = buf; - if (ssl->handshake->extended_ms == MBEDTLS_SSL_EXTENDED_MS_DISABLED || - ssl->minor_ver == MBEDTLS_SSL_MINOR_VERSION_0) { + if (ssl->handshake->extended_ms == MBEDTLS_SSL_EXTENDED_MS_DISABLED) { *olen = 0; return; } @@ -2423,7 +1857,7 @@ static void ssl_write_renegotiation_ext(mbedtls_ssl_context *ssl, *p++ = 0x00; } - *olen = p - buf; + *olen = (size_t) (p - buf); } #if defined(MBEDTLS_SSL_MAX_FRAGMENT_LENGTH) @@ -2452,7 +1886,8 @@ static void ssl_write_max_fragment_length_ext(mbedtls_ssl_context *ssl, } #endif /* MBEDTLS_SSL_MAX_FRAGMENT_LENGTH */ -#if defined(MBEDTLS_ECDH_C) || defined(MBEDTLS_ECDSA_C) || \ +#if defined(MBEDTLS_KEY_EXCHANGE_SOME_ECDH_OR_ECDHE_1_2_ENABLED) || \ + defined(MBEDTLS_KEY_EXCHANGE_ECDSA_CERT_REQ_ALLOWED_ENABLED) || \ defined(MBEDTLS_KEY_EXCHANGE_ECJPAKE_ENABLED) static void ssl_write_supported_point_formats_ext(mbedtls_ssl_context *ssl, unsigned char *buf, @@ -2480,7 +1915,9 @@ static void ssl_write_supported_point_formats_ext(mbedtls_ssl_context *ssl, *olen = 6; } -#endif /* MBEDTLS_ECDH_C || MBEDTLS_ECDSA_C || MBEDTLS_KEY_EXCHANGE_ECJPAKE_ENABLED */ +#endif /* MBEDTLS_KEY_EXCHANGE_SOME_ECDH_OR_ECDHE_1_2_ENABLED || + MBEDTLS_KEY_EXCHANGE_ECDSA_CERT_REQ_ALLOWED_ENABLED || + MBEDTLS_KEY_EXCHANGE_ECJPAKE_ENABLED */ #if defined(MBEDTLS_KEY_EXCHANGE_ECJPAKE_ENABLED) static void ssl_write_ecjpake_kkpp_ext(mbedtls_ssl_context *ssl, @@ -2510,13 +1947,25 @@ static void ssl_write_ecjpake_kkpp_ext(mbedtls_ssl_context *ssl, MBEDTLS_PUT_UINT16_BE(MBEDTLS_TLS_EXT_ECJPAKE_KKPP, p, 0); p += 2; +#if defined(MBEDTLS_USE_PSA_CRYPTO) + ret = mbedtls_psa_ecjpake_write_round(&ssl->handshake->psa_pake_ctx, + p + 2, (size_t) (end - p - 2), &kkpp_len, + MBEDTLS_ECJPAKE_ROUND_ONE); + if (ret != 0) { + psa_destroy_key(ssl->handshake->psa_pake_password); + psa_pake_abort(&ssl->handshake->psa_pake_ctx); + MBEDTLS_SSL_DEBUG_RET(1, "psa_pake_output", ret); + return; + } +#else ret = mbedtls_ecjpake_write_round_one(&ssl->handshake->ecjpake_ctx, - p + 2, end - p - 2, &kkpp_len, + p + 2, (size_t) (end - p - 2), &kkpp_len, ssl->conf->f_rng, ssl->conf->p_rng); if (ret != 0) { MBEDTLS_SSL_DEBUG_RET(1, "mbedtls_ecjpake_write_round_one", ret); return; } +#endif /* MBEDTLS_USE_PSA_CRYPTO */ MBEDTLS_PUT_UINT16_BE(kkpp_len, p, 0); p += 2; @@ -2525,38 +1974,6 @@ static void ssl_write_ecjpake_kkpp_ext(mbedtls_ssl_context *ssl, } #endif /* MBEDTLS_KEY_EXCHANGE_ECJPAKE_ENABLED */ -#if defined(MBEDTLS_SSL_ALPN) -static void ssl_write_alpn_ext(mbedtls_ssl_context *ssl, - unsigned char *buf, size_t *olen) -{ - if (ssl->alpn_chosen == NULL) { - *olen = 0; - return; - } - - MBEDTLS_SSL_DEBUG_MSG(3, ("server hello, adding alpn extension")); - - /* - * 0 . 1 ext identifier - * 2 . 3 ext length - * 4 . 5 protocol list length - * 6 . 6 protocol name length - * 7 . 7+n protocol name - */ - MBEDTLS_PUT_UINT16_BE(MBEDTLS_TLS_EXT_ALPN, buf, 0); - - *olen = 7 + strlen(ssl->alpn_chosen); - - MBEDTLS_PUT_UINT16_BE(*olen - 4, buf, 2); - - MBEDTLS_PUT_UINT16_BE(*olen - 6, buf, 4); - - buf[6] = MBEDTLS_BYTE_0(*olen - 7); - - memcpy(buf + 7, ssl->alpn_chosen, *olen - 7); -} -#endif /* MBEDTLS_ECDH_C || MBEDTLS_ECDSA_C */ - #if defined(MBEDTLS_SSL_DTLS_SRTP) && defined(MBEDTLS_SSL_PROTO_DTLS) static void ssl_write_use_srtp_ext(mbedtls_ssl_context *ssl, unsigned char *buf, @@ -2639,8 +2056,7 @@ static int ssl_write_hello_verify_request(mbedtls_ssl_context *ssl) /* The RFC is not clear on this point, but sending the actual negotiated * version looks like the most interoperable thing to do. */ - mbedtls_ssl_write_version(ssl->major_ver, ssl->minor_ver, - ssl->conf->transport, p); + mbedtls_ssl_write_version(p, ssl->conf->transport, ssl->tls_version); MBEDTLS_SSL_DEBUG_BUF(3, "server version", p, 2); p += 2; @@ -2664,7 +2080,7 @@ static int ssl_write_hello_verify_request(mbedtls_ssl_context *ssl) MBEDTLS_SSL_DEBUG_BUF(3, "cookie sent", cookie_len_byte + 1, *cookie_len_byte); - ssl->out_msglen = p - ssl->out_msg; + ssl->out_msglen = (size_t) (p - ssl->out_msg); ssl->out_msgtype = MBEDTLS_SSL_MSG_HANDSHAKE; ssl->out_msg[0] = MBEDTLS_SSL_HS_HELLO_VERIFY_REQUEST; @@ -2714,17 +2130,15 @@ static void ssl_handle_id_based_session_resumption(mbedtls_ssl_context *ssl) mbedtls_ssl_session_init(&session_tmp); - session_tmp.id_len = session->id_len; - memcpy(session_tmp.id, session->id, session->id_len); - ret = ssl->conf->f_get_cache(ssl->conf->p_cache, + session->id, + session->id_len, &session_tmp); if (ret != 0) { goto exit; } - if (session->ciphersuite != session_tmp.ciphersuite || - session->compression != session_tmp.compression) { + if (session->ciphersuite != session_tmp.ciphersuite) { /* Mismatch between cached and negotiated session */ goto exit; } @@ -2756,7 +2170,7 @@ static int ssl_write_server_hello(mbedtls_ssl_context *ssl) #if defined(MBEDTLS_SSL_DTLS_HELLO_VERIFY) if (ssl->conf->transport == MBEDTLS_SSL_TRANSPORT_DATAGRAM && - ssl->handshake->verify_cookie_len != 0) { + ssl->handshake->cookie_verify_result != 0) { MBEDTLS_SSL_DEBUG_MSG(2, ("client hello was not authenticated")); MBEDTLS_SSL_DEBUG_MSG(2, ("<= write server hello")); @@ -2764,11 +2178,6 @@ static int ssl_write_server_hello(mbedtls_ssl_context *ssl) } #endif /* MBEDTLS_SSL_DTLS_HELLO_VERIFY */ - if (ssl->conf->f_rng == NULL) { - MBEDTLS_SSL_DEBUG_MSG(1, ("no RNG provided")); - return MBEDTLS_ERR_SSL_NO_RNG; - } - /* * 0 . 0 handshake type * 1 . 3 handshake length @@ -2779,8 +2188,7 @@ static int ssl_write_server_hello(mbedtls_ssl_context *ssl) buf = ssl->out_msg; p = buf + 4; - mbedtls_ssl_write_version(ssl->major_ver, ssl->minor_ver, - ssl->conf->transport, p); + mbedtls_ssl_write_version(p, ssl->conf->transport, ssl->tls_version); p += 2; MBEDTLS_SSL_DEBUG_MSG(3, ("server hello, chosen version: [%d:%d]", @@ -2801,11 +2209,37 @@ static int ssl_write_server_hello(mbedtls_ssl_context *ssl) p += 4; #endif /* MBEDTLS_HAVE_TIME */ - if ((ret = ssl->conf->f_rng(ssl->conf->p_rng, p, 28)) != 0) { + if ((ret = ssl->conf->f_rng(ssl->conf->p_rng, p, 20)) != 0) { return ret; } + p += 20; + +#if defined(MBEDTLS_SSL_PROTO_TLS1_3) + /* + * RFC 8446 + * TLS 1.3 has a downgrade protection mechanism embedded in the server's + * random value. TLS 1.3 servers which negotiate TLS 1.2 or below in + * response to a ClientHello MUST set the last 8 bytes of their Random + * value specially in their ServerHello. + */ + if (mbedtls_ssl_conf_is_tls13_enabled(ssl->conf)) { + static const unsigned char magic_tls12_downgrade_string[] = + { 'D', 'O', 'W', 'N', 'G', 'R', 'D', 1 }; - p += 28; + MBEDTLS_STATIC_ASSERT( + sizeof(magic_tls12_downgrade_string) == 8, + "magic_tls12_downgrade_string does not have the expected size"); + + memcpy(p, magic_tls12_downgrade_string, + sizeof(magic_tls12_downgrade_string)); + } else +#endif + { + if ((ret = ssl->conf->f_rng(ssl->conf->p_rng, p, 8)) != 0) { + return ret; + } + } + p += 8; memcpy(ssl->handshake->randbytes + 32, buf + 6, 32); @@ -2869,17 +2303,12 @@ static int ssl_write_server_hello(mbedtls_ssl_context *ssl) MBEDTLS_PUT_UINT16_BE(ssl->session_negotiate->ciphersuite, p, 0); p += 2; - *p++ = MBEDTLS_BYTE_0(ssl->session_negotiate->compression); + *p++ = MBEDTLS_BYTE_0(MBEDTLS_SSL_COMPRESS_NULL); MBEDTLS_SSL_DEBUG_MSG(3, ("server hello, chosen ciphersuite: %s", mbedtls_ssl_get_ciphersuite_name(ssl->session_negotiate->ciphersuite))); MBEDTLS_SSL_DEBUG_MSG(3, ("server hello, compress alg.: 0x%02X", - (unsigned int) ssl->session_negotiate->compression)); - - /* Do not write the extensions if the protocol is SSLv3 */ -#if defined(MBEDTLS_SSL_PROTO_SSL3) - if ((ssl->major_ver != 3) || (ssl->minor_ver != 0)) { -#endif + (unsigned int) MBEDTLS_SSL_COMPRESS_NULL)); /* * First write extensions, then the total length @@ -2892,17 +2321,12 @@ static int ssl_write_server_hello(mbedtls_ssl_context *ssl) ext_len += olen; #endif -#if defined(MBEDTLS_SSL_TRUNCATED_HMAC) - ssl_write_truncated_hmac_ext(ssl, p + 2 + ext_len, &olen); - ext_len += olen; -#endif - #if defined(MBEDTLS_SSL_DTLS_CONNECTION_ID) ssl_write_cid_ext(ssl, p + 2 + ext_len, &olen); ext_len += olen; #endif -#if defined(MBEDTLS_SSL_ENCRYPT_THEN_MAC) +#if defined(MBEDTLS_SSL_SOME_SUITES_USE_CBC_ETM) ssl_write_encrypt_then_mac_ext(ssl, p + 2 + ext_len, &olen); ext_len += olen; #endif @@ -2917,10 +2341,12 @@ static int ssl_write_server_hello(mbedtls_ssl_context *ssl) ext_len += olen; #endif -#if defined(MBEDTLS_ECDH_C) || defined(MBEDTLS_ECDSA_C) || \ +#if defined(MBEDTLS_KEY_EXCHANGE_SOME_ECDH_OR_ECDHE_1_2_ENABLED) || \ + defined(MBEDTLS_KEY_EXCHANGE_ECDSA_CERT_REQ_ALLOWED_ENABLED) || \ defined(MBEDTLS_KEY_EXCHANGE_ECJPAKE_ENABLED) - if (mbedtls_ssl_ciphersuite_uses_ec( - mbedtls_ssl_ciphersuite_from_id(ssl->session_negotiate->ciphersuite))) { + const mbedtls_ssl_ciphersuite_t *suite = + mbedtls_ssl_ciphersuite_from_id(ssl->session_negotiate->ciphersuite); + if (suite != NULL && mbedtls_ssl_ciphersuite_uses_ec(suite)) { ssl_write_supported_point_formats_ext(ssl, p + 2 + ext_len, &olen); ext_len += olen; } @@ -2932,7 +2358,12 @@ static int ssl_write_server_hello(mbedtls_ssl_context *ssl) #endif #if defined(MBEDTLS_SSL_ALPN) - ssl_write_alpn_ext(ssl, p + 2 + ext_len, &olen); + unsigned char *end = buf + MBEDTLS_SSL_OUT_CONTENT_LEN - 4; + if ((ret = mbedtls_ssl_write_alpn_ext(ssl, p + 2 + ext_len, end, &olen)) + != 0) { + return ret; + } + ext_len += olen; #endif @@ -2949,11 +2380,7 @@ static int ssl_write_server_hello(mbedtls_ssl_context *ssl) p += 2 + ext_len; } -#if defined(MBEDTLS_SSL_PROTO_SSL3) -} -#endif - - ssl->out_msglen = p - buf; + ssl->out_msglen = (size_t) (p - buf); ssl->out_msgtype = MBEDTLS_SSL_MSG_HANDSHAKE; ssl->out_msg[0] = MBEDTLS_SSL_HS_SERVER_HELLO; @@ -3039,7 +2466,7 @@ static int ssl_write_certificate_request(mbedtls_ssl_context *ssl) #if defined(MBEDTLS_RSA_C) p[1 + ct_len++] = MBEDTLS_SSL_CERT_TYPE_RSA_SIGN; #endif -#if defined(MBEDTLS_ECDSA_C) +#if defined(MBEDTLS_KEY_EXCHANGE_ECDSA_CERT_REQ_ALLOWED_ENABLED) p[1 + ct_len++] = MBEDTLS_SSL_CERT_TYPE_ECDSA_SIGN; #endif @@ -3047,7 +2474,7 @@ static int ssl_write_certificate_request(mbedtls_ssl_context *ssl) p += ct_len; sa_len = 0; -#if defined(MBEDTLS_SSL_PROTO_TLS1_2) + /* * Add signature_algorithms for verify (TLS 1.2) * @@ -3061,34 +2488,33 @@ static int ssl_write_certificate_request(mbedtls_ssl_context *ssl) * enum { (255) } HashAlgorithm; * enum { (255) } SignatureAlgorithm; */ - if (ssl->minor_ver == MBEDTLS_SSL_MINOR_VERSION_3) { - const int *cur; - - /* - * Supported signature algorithms - */ - for (cur = ssl->conf->sig_hashes; *cur != MBEDTLS_MD_NONE; cur++) { - unsigned char hash = mbedtls_ssl_hash_from_md_alg(*cur); + const uint16_t *sig_alg = mbedtls_ssl_get_sig_algs(ssl); + if (sig_alg == NULL) { + return MBEDTLS_ERR_SSL_BAD_CONFIG; + } - if (MBEDTLS_SSL_HASH_NONE == hash || mbedtls_ssl_set_calc_verify_md(ssl, hash)) { - continue; - } + for (; *sig_alg != MBEDTLS_TLS_SIG_NONE; sig_alg++) { + unsigned char hash = MBEDTLS_BYTE_1(*sig_alg); -#if defined(MBEDTLS_RSA_C) - p[2 + sa_len++] = hash; - p[2 + sa_len++] = MBEDTLS_SSL_SIG_RSA; -#endif -#if defined(MBEDTLS_ECDSA_C) - p[2 + sa_len++] = hash; - p[2 + sa_len++] = MBEDTLS_SSL_SIG_ECDSA; -#endif + if (mbedtls_ssl_set_calc_verify_md(ssl, hash)) { + continue; + } + if (!mbedtls_ssl_sig_alg_is_supported(ssl, *sig_alg)) { + continue; } - MBEDTLS_PUT_UINT16_BE(sa_len, p, 0); + /* Write elements at offsets starting from 1 (offset 0 is for the + * length). Thus the offset of each element is the length of the + * partial list including that element. */ sa_len += 2; - p += sa_len; + MBEDTLS_PUT_UINT16_BE(*sig_alg, p, sa_len); + } -#endif /* MBEDTLS_SSL_PROTO_TLS1_2 */ + + /* Fill in list length. */ + MBEDTLS_PUT_UINT16_BE(sa_len, p, 0); + sa_len += 2; + p += sa_len; /* * DistinguishedName certificate_authorities<0..2^16-1>; @@ -3104,6 +2530,16 @@ static int ssl_write_certificate_request(mbedtls_ssl_context *ssl) * `mbedtls_ssl_conf_ca_cb()`, then the * CertificateRequest is currently left empty. */ +#if defined(MBEDTLS_KEY_EXCHANGE_CERT_REQ_ALLOWED_ENABLED) +#if defined(MBEDTLS_SSL_SERVER_NAME_INDICATION) + if (ssl->handshake->dn_hints != NULL) { + crt = ssl->handshake->dn_hints; + } else +#endif + if (ssl->conf->dn_hints != NULL) { + crt = ssl->conf->dn_hints; + } else +#endif #if defined(MBEDTLS_SSL_SERVER_NAME_INDICATION) if (ssl->handshake->sni_ca_chain != NULL) { crt = ssl->handshake->sni_ca_chain; @@ -3121,49 +2557,194 @@ static int ssl_write_certificate_request(mbedtls_ssl_context *ssl) break; } - MBEDTLS_PUT_UINT16_BE(dn_size, p, 0); - p += 2; - memcpy(p, crt->subject_raw.p, dn_size); - p += dn_size; + MBEDTLS_PUT_UINT16_BE(dn_size, p, 0); + p += 2; + memcpy(p, crt->subject_raw.p, dn_size); + p += dn_size; + + MBEDTLS_SSL_DEBUG_BUF(3, "requested DN", p - dn_size, dn_size); + + total_dn_size += (unsigned short) (2 + dn_size); + crt = crt->next; + } + } + + ssl->out_msglen = (size_t) (p - buf); + ssl->out_msgtype = MBEDTLS_SSL_MSG_HANDSHAKE; + ssl->out_msg[0] = MBEDTLS_SSL_HS_CERTIFICATE_REQUEST; + MBEDTLS_PUT_UINT16_BE(total_dn_size, ssl->out_msg, 4 + ct_len + sa_len); + + ret = mbedtls_ssl_write_handshake_msg(ssl); + + MBEDTLS_SSL_DEBUG_MSG(2, ("<= write certificate request")); + + return ret; +} +#endif /* MBEDTLS_KEY_EXCHANGE_CERT_REQ_ALLOWED_ENABLED */ + +#if (defined(MBEDTLS_KEY_EXCHANGE_ECDH_RSA_ENABLED) || \ + defined(MBEDTLS_KEY_EXCHANGE_ECDH_ECDSA_ENABLED)) +#if defined(MBEDTLS_USE_PSA_CRYPTO) +MBEDTLS_CHECK_RETURN_CRITICAL +static int ssl_get_ecdh_params_from_cert(mbedtls_ssl_context *ssl) +{ + int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED; + psa_status_t status = PSA_ERROR_CORRUPTION_DETECTED; + mbedtls_pk_context *pk; + mbedtls_pk_type_t pk_type; + psa_key_attributes_t key_attributes = PSA_KEY_ATTRIBUTES_INIT; + unsigned char buf[PSA_KEY_EXPORT_ECC_KEY_PAIR_MAX_SIZE(PSA_VENDOR_ECC_MAX_CURVE_BITS)]; + size_t key_len; +#if !defined(MBEDTLS_PK_USE_PSA_EC_DATA) + uint16_t tls_id = 0; + psa_key_type_t key_type = PSA_KEY_TYPE_NONE; + mbedtls_ecp_group_id grp_id; + mbedtls_ecp_keypair *key; +#endif /* !MBEDTLS_PK_USE_PSA_EC_DATA */ + + pk = mbedtls_ssl_own_key(ssl); + + if (pk == NULL) { + return MBEDTLS_ERR_ECP_BAD_INPUT_DATA; + } + + pk_type = mbedtls_pk_get_type(pk); + + switch (pk_type) { + case MBEDTLS_PK_OPAQUE: +#if defined(MBEDTLS_PK_USE_PSA_EC_DATA) + case MBEDTLS_PK_ECKEY: + case MBEDTLS_PK_ECKEY_DH: + case MBEDTLS_PK_ECDSA: +#endif /* MBEDTLS_PK_USE_PSA_EC_DATA */ + if (!mbedtls_pk_can_do(pk, MBEDTLS_PK_ECKEY)) { + return MBEDTLS_ERR_SSL_PK_TYPE_MISMATCH; + } + + /* Get the attributes of the key previously parsed by PK module in + * order to extract its type and length (in bits). */ + status = psa_get_key_attributes(pk->priv_id, &key_attributes); + if (status != PSA_SUCCESS) { + ret = PSA_TO_MBEDTLS_ERR(status); + goto exit; + } + ssl->handshake->xxdh_psa_type = psa_get_key_type(&key_attributes); + ssl->handshake->xxdh_psa_bits = psa_get_key_bits(&key_attributes); + + if (pk_type == MBEDTLS_PK_OPAQUE) { + /* Opaque key is created by the user (externally from Mbed TLS) + * so we assume it already has the right algorithm and flags + * set. Just copy its ID as reference. */ + ssl->handshake->xxdh_psa_privkey = pk->priv_id; + ssl->handshake->xxdh_psa_privkey_is_external = 1; + } else { + /* PK_ECKEY[_DH] and PK_ECDSA instead as parsed from the PK + * module and only have ECDSA capabilities. Since we need + * them for ECDH later, we export and then re-import them with + * proper flags and algorithm. Of course We also set key's type + * and bits that we just got above. */ + key_attributes = psa_key_attributes_init(); + psa_set_key_usage_flags(&key_attributes, PSA_KEY_USAGE_DERIVE); + psa_set_key_algorithm(&key_attributes, PSA_ALG_ECDH); + psa_set_key_type(&key_attributes, + PSA_KEY_TYPE_ECC_KEY_PAIR(ssl->handshake->xxdh_psa_type)); + psa_set_key_bits(&key_attributes, ssl->handshake->xxdh_psa_bits); + + status = psa_export_key(pk->priv_id, buf, sizeof(buf), &key_len); + if (status != PSA_SUCCESS) { + ret = PSA_TO_MBEDTLS_ERR(status); + goto exit; + } + status = psa_import_key(&key_attributes, buf, key_len, + &ssl->handshake->xxdh_psa_privkey); + if (status != PSA_SUCCESS) { + ret = PSA_TO_MBEDTLS_ERR(status); + goto exit; + } + + /* Set this key as owned by the TLS library: it will be its duty + * to clear it exit. */ + ssl->handshake->xxdh_psa_privkey_is_external = 0; + } + + ret = 0; + break; +#if !defined(MBEDTLS_PK_USE_PSA_EC_DATA) + case MBEDTLS_PK_ECKEY: + case MBEDTLS_PK_ECKEY_DH: + case MBEDTLS_PK_ECDSA: + key = mbedtls_pk_ec_rw(*pk); + grp_id = mbedtls_pk_get_ec_group_id(pk); + if (grp_id == MBEDTLS_ECP_DP_NONE) { + return MBEDTLS_ERR_ECP_BAD_INPUT_DATA; + } + tls_id = mbedtls_ssl_get_tls_id_from_ecp_group_id(grp_id); + if (tls_id == 0) { + /* This elliptic curve is not supported */ + return MBEDTLS_ERR_SSL_HANDSHAKE_FAILURE; + } + + /* If the above conversion to TLS ID was fine, then also this one will + be, so there is no need to check the return value here */ + mbedtls_ssl_get_psa_curve_info_from_tls_id(tls_id, &key_type, + &ssl->handshake->xxdh_psa_bits); + + ssl->handshake->xxdh_psa_type = key_type; - MBEDTLS_SSL_DEBUG_BUF(3, "requested DN", p - dn_size, dn_size); + key_attributes = psa_key_attributes_init(); + psa_set_key_usage_flags(&key_attributes, PSA_KEY_USAGE_DERIVE); + psa_set_key_algorithm(&key_attributes, PSA_ALG_ECDH); + psa_set_key_type(&key_attributes, + PSA_KEY_TYPE_ECC_KEY_PAIR(ssl->handshake->xxdh_psa_type)); + psa_set_key_bits(&key_attributes, ssl->handshake->xxdh_psa_bits); - total_dn_size += 2 + dn_size; - crt = crt->next; - } - } + ret = mbedtls_ecp_write_key_ext(key, &key_len, buf, sizeof(buf)); + if (ret != 0) { + mbedtls_platform_zeroize(buf, sizeof(buf)); + break; + } - ssl->out_msglen = p - buf; - ssl->out_msgtype = MBEDTLS_SSL_MSG_HANDSHAKE; - ssl->out_msg[0] = MBEDTLS_SSL_HS_CERTIFICATE_REQUEST; - MBEDTLS_PUT_UINT16_BE(total_dn_size, ssl->out_msg, 4 + ct_len + sa_len); + status = psa_import_key(&key_attributes, buf, key_len, + &ssl->handshake->xxdh_psa_privkey); + if (status != PSA_SUCCESS) { + ret = PSA_TO_MBEDTLS_ERR(status); + mbedtls_platform_zeroize(buf, sizeof(buf)); + break; + } - ret = mbedtls_ssl_write_handshake_msg(ssl); + mbedtls_platform_zeroize(buf, sizeof(buf)); + ret = 0; + break; +#endif /* !MBEDTLS_PK_USE_PSA_EC_DATA */ + default: + ret = MBEDTLS_ERR_SSL_PK_TYPE_MISMATCH; + } - MBEDTLS_SSL_DEBUG_MSG(2, ("<= write certificate request")); +exit: + psa_reset_key_attributes(&key_attributes); + mbedtls_platform_zeroize(buf, sizeof(buf)); return ret; } -#endif /* MBEDTLS_KEY_EXCHANGE_CERT_REQ_ALLOWED_ENABLED */ - -#if defined(MBEDTLS_KEY_EXCHANGE_ECDH_RSA_ENABLED) || \ - defined(MBEDTLS_KEY_EXCHANGE_ECDH_ECDSA_ENABLED) +#else /* MBEDTLS_USE_PSA_CRYPTO */ MBEDTLS_CHECK_RETURN_CRITICAL static int ssl_get_ecdh_params_from_cert(mbedtls_ssl_context *ssl) { int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED; - mbedtls_pk_context *own_key = mbedtls_ssl_own_key(ssl); - /* Check if the key is a transparent ECDH key. - * This also ensures that it is safe to call mbedtls_pk_ec(). */ - if (mbedtls_pk_get_type(own_key) != MBEDTLS_PK_ECKEY && - mbedtls_pk_get_type(own_key) != MBEDTLS_PK_ECKEY_DH) { + const mbedtls_pk_context *private_key = mbedtls_ssl_own_key(ssl); + if (private_key == NULL) { + MBEDTLS_SSL_DEBUG_MSG(1, ("got no server private key")); + return MBEDTLS_ERR_SSL_PRIVATE_KEY_REQUIRED; + } + + if (!mbedtls_pk_can_do(private_key, MBEDTLS_PK_ECKEY)) { MBEDTLS_SSL_DEBUG_MSG(1, ("server key not ECDH capable")); return MBEDTLS_ERR_SSL_PK_TYPE_MISMATCH; } if ((ret = mbedtls_ecdh_get_params(&ssl->handshake->ecdh_ctx, - mbedtls_pk_ec(*own_key), + mbedtls_pk_ec_ro(*mbedtls_ssl_own_key(ssl)), MBEDTLS_ECDH_OURS)) != 0) { MBEDTLS_SSL_DEBUG_RET(1, ("mbedtls_ecdh_get_params"), ret); return ret; @@ -3171,6 +2752,7 @@ static int ssl_get_ecdh_params_from_cert(mbedtls_ssl_context *ssl) return 0; } +#endif /* MBEDTLS_USE_PSA_CRYPTO */ #endif /* MBEDTLS_KEY_EXCHANGE_ECDH_RSA_ENABLED) || MBEDTLS_KEY_EXCHANGE_ECDH_ECDSA_ENABLED */ @@ -3221,6 +2803,14 @@ static int ssl_prepare_server_key_exchange(mbedtls_ssl_context *ssl, (void) signature_len; #endif /* MBEDTLS_KEY_EXCHANGE_WITH_SERVER_SIGNATURE_ENABLED */ +#if defined(MBEDTLS_KEY_EXCHANGE_WITH_SERVER_SIGNATURE_ENABLED) +#if defined(MBEDTLS_SSL_VARIABLE_BUFFER_LENGTH) + size_t out_buf_len = ssl->out_buf_len - (size_t) (ssl->out_msg - ssl->out_buf); +#else + size_t out_buf_len = MBEDTLS_SSL_OUT_BUFFER_LEN - (size_t) (ssl->out_msg - ssl->out_buf); +#endif +#endif + ssl->out_msglen = 4; /* header (type:1, length:3) to be written later */ /* @@ -3235,6 +2825,44 @@ static int ssl_prepare_server_key_exchange(mbedtls_ssl_context *ssl, #if defined(MBEDTLS_KEY_EXCHANGE_ECJPAKE_ENABLED) if (ciphersuite_info->key_exchange == MBEDTLS_KEY_EXCHANGE_ECJPAKE) { int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED; +#if defined(MBEDTLS_USE_PSA_CRYPTO) + unsigned char *out_p = ssl->out_msg + ssl->out_msglen; + unsigned char *end_p = ssl->out_msg + MBEDTLS_SSL_OUT_CONTENT_LEN - + ssl->out_msglen; + size_t output_offset = 0; + size_t output_len = 0; + + /* + * The first 3 bytes are: + * [0] MBEDTLS_ECP_TLS_NAMED_CURVE + * [1, 2] elliptic curve's TLS ID + * + * However since we only support secp256r1 for now, we hardcode its + * TLS ID here + */ + uint16_t tls_id = mbedtls_ssl_get_tls_id_from_ecp_group_id( + MBEDTLS_ECP_DP_SECP256R1); + if (tls_id == 0) { + return MBEDTLS_ERR_SSL_FEATURE_UNAVAILABLE; + } + *out_p = MBEDTLS_ECP_TLS_NAMED_CURVE; + MBEDTLS_PUT_UINT16_BE(tls_id, out_p, 1); + output_offset += 3; + + ret = mbedtls_psa_ecjpake_write_round(&ssl->handshake->psa_pake_ctx, + out_p + output_offset, + end_p - out_p - output_offset, &output_len, + MBEDTLS_ECJPAKE_ROUND_TWO); + if (ret != 0) { + psa_destroy_key(ssl->handshake->psa_pake_password); + psa_pake_abort(&ssl->handshake->psa_pake_ctx); + MBEDTLS_SSL_DEBUG_RET(1, "psa_pake_output", ret); + return ret; + } + + output_offset += output_len; + ssl->out_msglen += output_offset; +#else size_t len = 0; ret = mbedtls_ecjpake_write_round_two( @@ -3248,6 +2876,7 @@ static int ssl_prepare_server_key_exchange(mbedtls_ssl_context *ssl, } ssl->out_msglen += len; +#endif /* MBEDTLS_USE_PSA_CRYPTO */ } #endif /* MBEDTLS_KEY_EXCHANGE_ECJPAKE_ENABLED */ @@ -3297,7 +2926,7 @@ static int ssl_prepare_server_key_exchange(mbedtls_ssl_context *ssl, if ((ret = mbedtls_dhm_make_params( &ssl->handshake->dhm_ctx, - (int) mbedtls_mpi_size(&ssl->handshake->dhm_ctx.P), + (int) mbedtls_dhm_get_len(&ssl->handshake->dhm_ctx), ssl->out_msg + ssl->out_msglen, &len, ssl->conf->f_rng, ssl->conf->p_rng)) != 0) { MBEDTLS_SSL_DEBUG_RET(1, "mbedtls_dhm_make_params", ret); @@ -3330,30 +2959,121 @@ static int ssl_prepare_server_key_exchange(mbedtls_ssl_context *ssl, * ECPoint public; * } ServerECDHParams; */ - const mbedtls_ecp_curve_info **curve = NULL; - const mbedtls_ecp_group_id *gid; + uint16_t *curr_tls_id = ssl->handshake->curves_tls_id; + const uint16_t *group_list = mbedtls_ssl_get_groups(ssl); int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED; size_t len = 0; /* Match our preference list against the offered curves */ - for (gid = ssl->conf->curve_list; *gid != MBEDTLS_ECP_DP_NONE; gid++) { - for (curve = ssl->handshake->curves; *curve != NULL; curve++) { - if ((*curve)->grp_id == *gid) { + if ((group_list == NULL) || (curr_tls_id == NULL)) { + return MBEDTLS_ERR_SSL_BAD_CONFIG; + } + for (; *group_list != 0; group_list++) { + for (curr_tls_id = ssl->handshake->curves_tls_id; + *curr_tls_id != 0; curr_tls_id++) { + if (*curr_tls_id == *group_list) { goto curve_matching_done; } } } curve_matching_done: - if (curve == NULL || *curve == NULL) { + if (*curr_tls_id == 0) { MBEDTLS_SSL_DEBUG_MSG(1, ("no matching curve for ECDHE")); - return MBEDTLS_ERR_SSL_NO_CIPHER_CHOSEN; + return MBEDTLS_ERR_SSL_HANDSHAKE_FAILURE; + } + + MBEDTLS_SSL_DEBUG_MSG(2, ("ECDHE curve: %s", + mbedtls_ssl_get_curve_name_from_tls_id(*curr_tls_id))); + +#if defined(MBEDTLS_USE_PSA_CRYPTO) + psa_status_t status = PSA_ERROR_GENERIC_ERROR; + psa_key_attributes_t key_attributes; + mbedtls_ssl_handshake_params *handshake = ssl->handshake; + uint8_t *p = ssl->out_msg + ssl->out_msglen; + const size_t header_size = 4; // curve_type(1), namedcurve(2), + // data length(1) + const size_t data_length_size = 1; + psa_key_type_t key_type = PSA_KEY_TYPE_NONE; + size_t ec_bits = 0; + + MBEDTLS_SSL_DEBUG_MSG(1, ("Perform PSA-based ECDH computation.")); + + /* Convert EC's TLS ID to PSA key type. */ + if (mbedtls_ssl_get_psa_curve_info_from_tls_id(*curr_tls_id, + &key_type, + &ec_bits) == PSA_ERROR_NOT_SUPPORTED) { + MBEDTLS_SSL_DEBUG_MSG(1, ("Invalid ecc group parse.")); + return MBEDTLS_ERR_SSL_ILLEGAL_PARAMETER; + } + handshake->xxdh_psa_type = key_type; + handshake->xxdh_psa_bits = ec_bits; + + key_attributes = psa_key_attributes_init(); + psa_set_key_usage_flags(&key_attributes, PSA_KEY_USAGE_DERIVE); + psa_set_key_algorithm(&key_attributes, PSA_ALG_ECDH); + psa_set_key_type(&key_attributes, handshake->xxdh_psa_type); + psa_set_key_bits(&key_attributes, handshake->xxdh_psa_bits); + + /* + * ECParameters curve_params + * + * First byte is curve_type, always named_curve + */ + *p++ = MBEDTLS_ECP_TLS_NAMED_CURVE; + + /* + * Next two bytes are the namedcurve value + */ + MBEDTLS_PUT_UINT16_BE(*curr_tls_id, p, 0); + p += 2; + + /* Generate ECDH private key. */ + status = psa_generate_key(&key_attributes, + &handshake->xxdh_psa_privkey); + if (status != PSA_SUCCESS) { + ret = PSA_TO_MBEDTLS_ERR(status); + MBEDTLS_SSL_DEBUG_RET(1, "psa_generate_key", ret); + return ret; } - MBEDTLS_SSL_DEBUG_MSG(2, ("ECDHE curve: %s", (*curve)->name)); + /* + * ECPoint public + * + * First byte is data length. + * It will be filled later. p holds now the data length location. + */ + + /* Export the public part of the ECDH private key from PSA. + * Make one byte space for the length. + */ + unsigned char *own_pubkey = p + data_length_size; + + size_t own_pubkey_max_len = (size_t) (MBEDTLS_SSL_OUT_CONTENT_LEN + - (own_pubkey - ssl->out_msg)); + + status = psa_export_public_key(handshake->xxdh_psa_privkey, + own_pubkey, own_pubkey_max_len, + &len); + if (status != PSA_SUCCESS) { + ret = PSA_TO_MBEDTLS_ERR(status); + MBEDTLS_SSL_DEBUG_RET(1, "psa_export_public_key", ret); + (void) psa_destroy_key(handshake->xxdh_psa_privkey); + handshake->xxdh_psa_privkey = MBEDTLS_SVC_KEY_ID_INIT; + return ret; + } + + /* Store the length of the exported public key. */ + *p = (uint8_t) len; + + /* Determine full message length. */ + len += header_size; +#else + mbedtls_ecp_group_id curr_grp_id = + mbedtls_ssl_get_ecp_group_id_from_tls_id(*curr_tls_id); if ((ret = mbedtls_ecdh_setup(&ssl->handshake->ecdh_ctx, - (*curve)->grp_id)) != 0) { + curr_grp_id)) != 0) { MBEDTLS_SSL_DEBUG_RET(1, "mbedtls_ecp_group_load", ret); return ret; } @@ -3367,14 +3087,15 @@ static int ssl_prepare_server_key_exchange(mbedtls_ssl_context *ssl, return ret; } + MBEDTLS_SSL_DEBUG_ECDH(3, &ssl->handshake->ecdh_ctx, + MBEDTLS_DEBUG_ECDH_Q); +#endif /* MBEDTLS_USE_PSA_CRYPTO */ + #if defined(MBEDTLS_KEY_EXCHANGE_WITH_SERVER_SIGNATURE_ENABLED) dig_signed = ssl->out_msg + ssl->out_msglen; #endif ssl->out_msglen += len; - - MBEDTLS_SSL_DEBUG_ECDH(3, &ssl->handshake->ecdh_ctx, - MBEDTLS_DEBUG_ECDH_Q); } #endif /* MBEDTLS_KEY_EXCHANGE_SOME_ECDHE_ENABLED */ @@ -3386,53 +3107,39 @@ static int ssl_prepare_server_key_exchange(mbedtls_ssl_context *ssl, */ #if defined(MBEDTLS_KEY_EXCHANGE_WITH_SERVER_SIGNATURE_ENABLED) if (mbedtls_ssl_ciphersuite_uses_server_signature(ciphersuite_info)) { - size_t dig_signed_len = ssl->out_msg + ssl->out_msglen - dig_signed; + if (dig_signed == NULL) { + MBEDTLS_SSL_DEBUG_MSG(1, ("should never happen")); + return MBEDTLS_ERR_SSL_INTERNAL_ERROR; + } + + size_t dig_signed_len = (size_t) (ssl->out_msg + ssl->out_msglen - dig_signed); size_t hashlen = 0; -#if defined(MBEDTLS_USE_PSA_CRYPTO) - unsigned char hash[PSA_HASH_MAX_SIZE]; -#else unsigned char hash[MBEDTLS_MD_MAX_SIZE]; -#endif + int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED; /* * 2.1: Choose hash algorithm: - * A: For TLS 1.2, obey signature-hash-algorithm extension - * to choose appropriate hash. - * B: For SSL3, TLS1.0, TLS1.1 and ECDHE_ECDSA, use SHA1 - * (RFC 4492, Sec. 5.4) - * C: Otherwise, use MD5 + SHA1 (RFC 4346, Sec. 7.4.3) + * For TLS 1.2, obey signature-hash-algorithm extension + * to choose appropriate hash. */ - mbedtls_md_type_t md_alg; - -#if defined(MBEDTLS_SSL_PROTO_TLS1_2) mbedtls_pk_type_t sig_alg = mbedtls_ssl_get_ciphersuite_sig_pk_alg(ciphersuite_info); - if (ssl->minor_ver == MBEDTLS_SSL_MINOR_VERSION_3) { - /* A: For TLS 1.2, obey signature-hash-algorithm extension - * (RFC 5246, Sec. 7.4.1.4.1). */ - if (sig_alg == MBEDTLS_PK_NONE || - (md_alg = mbedtls_ssl_sig_hash_set_find(&ssl->handshake->hash_algs, - sig_alg)) == MBEDTLS_MD_NONE) { - MBEDTLS_SSL_DEBUG_MSG(1, ("should never happen")); - /* (... because we choose a cipher suite - * only if there is a matching hash.) */ - return MBEDTLS_ERR_SSL_INTERNAL_ERROR; - } - } else -#endif /* MBEDTLS_SSL_PROTO_TLS1_2 */ -#if defined(MBEDTLS_SSL_PROTO_SSL3) || defined(MBEDTLS_SSL_PROTO_TLS1) || \ - defined(MBEDTLS_SSL_PROTO_TLS1_1) - if (ciphersuite_info->key_exchange == MBEDTLS_KEY_EXCHANGE_ECDHE_ECDSA) { - /* B: Default hash SHA1 */ - md_alg = MBEDTLS_MD_SHA1; - } else -#endif /* MBEDTLS_SSL_PROTO_SSL3 || MBEDTLS_SSL_PROTO_TLS1 || \ - MBEDTLS_SSL_PROTO_TLS1_1 */ - { - /* C: MD5 + SHA1 */ - md_alg = MBEDTLS_MD_NONE; + + unsigned char sig_hash = + (unsigned char) mbedtls_ssl_tls12_get_preferred_hash_for_sig_alg( + ssl, mbedtls_ssl_sig_from_pk_alg(sig_alg)); + + mbedtls_md_type_t md_alg = mbedtls_ssl_md_alg_from_hash(sig_hash); + + /* For TLS 1.2, obey signature-hash-algorithm extension + * (RFC 5246, Sec. 7.4.1.4.1). */ + if (sig_alg == MBEDTLS_PK_NONE || md_alg == MBEDTLS_MD_NONE) { + MBEDTLS_SSL_DEBUG_MSG(1, ("should never happen")); + /* (... because we choose a cipher suite + * only if there is a matching hash.) */ + return MBEDTLS_ERR_SSL_INTERNAL_ERROR; } MBEDTLS_SSL_DEBUG_MSG(3, ("pick hash algorithm %u for signing", (unsigned) md_alg)); @@ -3440,21 +3147,6 @@ static int ssl_prepare_server_key_exchange(mbedtls_ssl_context *ssl, /* * 2.2: Compute the hash to be signed */ -#if defined(MBEDTLS_SSL_PROTO_SSL3) || defined(MBEDTLS_SSL_PROTO_TLS1) || \ - defined(MBEDTLS_SSL_PROTO_TLS1_1) - if (md_alg == MBEDTLS_MD_NONE) { - hashlen = 36; - ret = mbedtls_ssl_get_key_exchange_md_ssl_tls(ssl, hash, - dig_signed, - dig_signed_len); - if (ret != 0) { - return ret; - } - } else -#endif /* MBEDTLS_SSL_PROTO_SSL3 || MBEDTLS_SSL_PROTO_TLS1 || \ - MBEDTLS_SSL_PROTO_TLS1_1 */ -#if defined(MBEDTLS_SSL_PROTO_TLS1) || defined(MBEDTLS_SSL_PROTO_TLS1_1) || \ - defined(MBEDTLS_SSL_PROTO_TLS1_2) if (md_alg != MBEDTLS_MD_NONE) { ret = mbedtls_ssl_get_key_exchange_md_tls1_2(ssl, hash, &hashlen, dig_signed, @@ -3463,10 +3155,7 @@ static int ssl_prepare_server_key_exchange(mbedtls_ssl_context *ssl, if (ret != 0) { return ret; } - } else -#endif /* MBEDTLS_SSL_PROTO_TLS1 || MBEDTLS_SSL_PROTO_TLS1_1 || \ - MBEDTLS_SSL_PROTO_TLS1_2 */ - { + } else { MBEDTLS_SSL_DEBUG_MSG(1, ("should never happen")); return MBEDTLS_ERR_SSL_INTERNAL_ERROR; } @@ -3476,30 +3165,24 @@ static int ssl_prepare_server_key_exchange(mbedtls_ssl_context *ssl, /* * 2.3: Compute and add the signature */ -#if defined(MBEDTLS_SSL_PROTO_TLS1_2) - if (ssl->minor_ver == MBEDTLS_SSL_MINOR_VERSION_3) { - /* - * For TLS 1.2, we need to specify signature and hash algorithm - * explicitly through a prefix to the signature. - * - * struct { - * HashAlgorithm hash; - * SignatureAlgorithm signature; - * } SignatureAndHashAlgorithm; - * - * struct { - * SignatureAndHashAlgorithm algorithm; - * opaque signature<0..2^16-1>; - * } DigitallySigned; - * - */ + /* + * We need to specify signature and hash algorithm explicitly through + * a prefix to the signature. + * + * struct { + * HashAlgorithm hash; + * SignatureAlgorithm signature; + * } SignatureAndHashAlgorithm; + * + * struct { + * SignatureAndHashAlgorithm algorithm; + * opaque signature<0..2^16-1>; + * } DigitallySigned; + * + */ - ssl->out_msg[ssl->out_msglen++] = - mbedtls_ssl_hash_from_md_alg(md_alg); - ssl->out_msg[ssl->out_msglen++] = - mbedtls_ssl_sig_from_pk_alg(sig_alg); - } -#endif /* MBEDTLS_SSL_PROTO_TLS1_2 */ + ssl->out_msg[ssl->out_msglen++] = mbedtls_ssl_hash_from_md_alg(md_alg); + ssl->out_msg[ssl->out_msglen++] = mbedtls_ssl_sig_from_pk_alg(sig_alg); #if defined(MBEDTLS_SSL_ASYNC_PRIVATE) if (ssl->conf->f_async_sign_start != NULL) { @@ -3536,6 +3219,7 @@ static int ssl_prepare_server_key_exchange(mbedtls_ssl_context *ssl, if ((ret = mbedtls_pk_sign(mbedtls_ssl_own_key(ssl), md_alg, hash, hashlen, ssl->out_msg + ssl->out_msglen + 2, + out_buf_len - ssl->out_msglen - 2, signature_len, ssl->conf->f_rng, ssl->conf->p_rng)) != 0) { @@ -3699,20 +3383,20 @@ static int ssl_parse_client_dh_public(mbedtls_ssl_context *ssl, unsigned char ** */ if (*p + 2 > end) { MBEDTLS_SSL_DEBUG_MSG(1, ("bad client key exchange message")); - return MBEDTLS_ERR_SSL_BAD_HS_CLIENT_KEY_EXCHANGE; + return MBEDTLS_ERR_SSL_DECODE_ERROR; } - n = ((*p)[0] << 8) | (*p)[1]; + n = MBEDTLS_GET_UINT16_BE(*p, 0); *p += 2; if (*p + n > end) { MBEDTLS_SSL_DEBUG_MSG(1, ("bad client key exchange message")); - return MBEDTLS_ERR_SSL_BAD_HS_CLIENT_KEY_EXCHANGE; + return MBEDTLS_ERR_SSL_DECODE_ERROR; } if ((ret = mbedtls_dhm_read_public(&ssl->handshake->dhm_ctx, *p, n)) != 0) { MBEDTLS_SSL_DEBUG_RET(1, "mbedtls_dhm_read_public", ret); - return MBEDTLS_ERR_SSL_BAD_HS_CLIENT_KEY_EXCHANGE_RP; + return MBEDTLS_ERR_SSL_DECODE_ERROR; } *p += n; @@ -3777,24 +3461,19 @@ static int ssl_decrypt_encrypted_pms(mbedtls_ssl_context *ssl, /* * Prepare to decrypt the premaster using own private RSA key */ -#if defined(MBEDTLS_SSL_PROTO_TLS1) || defined(MBEDTLS_SSL_PROTO_TLS1_1) || \ - defined(MBEDTLS_SSL_PROTO_TLS1_2) - if (ssl->minor_ver != MBEDTLS_SSL_MINOR_VERSION_0) { - if (p + 2 > end) { - MBEDTLS_SSL_DEBUG_MSG(1, ("bad client key exchange message")); - return MBEDTLS_ERR_SSL_BAD_HS_CLIENT_KEY_EXCHANGE; - } - if (*p++ != MBEDTLS_BYTE_1(len) || - *p++ != MBEDTLS_BYTE_0(len)) { - MBEDTLS_SSL_DEBUG_MSG(1, ("bad client key exchange message")); - return MBEDTLS_ERR_SSL_BAD_HS_CLIENT_KEY_EXCHANGE; - } + if (p + 2 > end) { + MBEDTLS_SSL_DEBUG_MSG(1, ("bad client key exchange message")); + return MBEDTLS_ERR_SSL_DECODE_ERROR; + } + if (*p++ != MBEDTLS_BYTE_1(len) || + *p++ != MBEDTLS_BYTE_0(len)) { + MBEDTLS_SSL_DEBUG_MSG(1, ("bad client key exchange message")); + return MBEDTLS_ERR_SSL_DECODE_ERROR; } -#endif if (p + len != end) { MBEDTLS_SSL_DEBUG_MSG(1, ("bad client key exchange message")); - return MBEDTLS_ERR_SSL_BAD_HS_CLIENT_KEY_EXCHANGE; + return MBEDTLS_ERR_SSL_DECODE_ERROR; } /* @@ -3846,9 +3525,8 @@ static int ssl_parse_encrypted_pms(mbedtls_ssl_context *ssl, unsigned char *pms = ssl->handshake->premaster + pms_offset; unsigned char ver[2]; unsigned char fake_pms[48], peer_pms[48]; - unsigned char mask; - size_t i, peer_pmslen; - unsigned int diff; + size_t peer_pmslen; + mbedtls_ct_condition_t diff; /* In case of a failure in decryption, the decryption may write less than * 2 bytes of output, but we always read the first two bytes. It doesn't @@ -3871,20 +3549,16 @@ static int ssl_parse_encrypted_pms(mbedtls_ssl_context *ssl, } #endif /* MBEDTLS_SSL_ASYNC_PRIVATE */ - mbedtls_ssl_write_version(ssl->handshake->max_major_ver, - ssl->handshake->max_minor_ver, - ssl->conf->transport, ver); + mbedtls_ssl_write_version(ver, ssl->conf->transport, + ssl->session_negotiate->tls_version); /* Avoid data-dependent branches while checking for invalid * padding, to protect against timing-based Bleichenbacher-type * attacks. */ - diff = (unsigned int) ret; - diff |= peer_pmslen ^ 48; - diff |= peer_pms[0] ^ ver[0]; - diff |= peer_pms[1] ^ ver[1]; - - /* mask = diff ? 0xff : 0x00 using bit operations to avoid branches */ - mask = mbedtls_ct_uint_mask(diff); + diff = mbedtls_ct_bool(ret); + diff = mbedtls_ct_bool_or(diff, mbedtls_ct_uint_ne(peer_pmslen, 48)); + diff = mbedtls_ct_bool_or(diff, mbedtls_ct_uint_ne(peer_pms[0], ver[0])); + diff = mbedtls_ct_bool_or(diff, mbedtls_ct_uint_ne(peer_pms[1], ver[1])); /* * Protection against Bleichenbacher's attack: invalid PKCS#1 v1.5 padding @@ -3903,7 +3577,7 @@ static int ssl_parse_encrypted_pms(mbedtls_ssl_context *ssl, } #if defined(MBEDTLS_SSL_DEBUG_ALL) - if (diff != 0) { + if (diff != MBEDTLS_CT_FALSE) { MBEDTLS_SSL_DEBUG_MSG(1, ("bad client key exchange message")); } #endif @@ -3917,9 +3591,7 @@ static int ssl_parse_encrypted_pms(mbedtls_ssl_context *ssl, /* Set pms to either the true or the fake PMS, without * data-dependent branches. */ - for (i = 0; i < ssl->handshake->pmslen; i++) { - pms[i] = (mask & fake_pms[i]) | ((~mask) & peer_pms[i]); - } + mbedtls_ct_memcpy_if(diff, pms, fake_pms, peer_pms, ssl->handshake->pmslen); return 0; } @@ -3944,15 +3616,15 @@ static int ssl_parse_client_psk_identity(mbedtls_ssl_context *ssl, unsigned char */ if (end - *p < 2) { MBEDTLS_SSL_DEBUG_MSG(1, ("bad client key exchange message")); - return MBEDTLS_ERR_SSL_BAD_HS_CLIENT_KEY_EXCHANGE; + return MBEDTLS_ERR_SSL_DECODE_ERROR; } - n = ((*p)[0] << 8) | (*p)[1]; + n = MBEDTLS_GET_UINT16_BE(*p, 0); *p += 2; if (n == 0 || n > end - *p) { MBEDTLS_SSL_DEBUG_MSG(1, ("bad client key exchange message")); - return MBEDTLS_ERR_SSL_BAD_HS_CLIENT_KEY_EXCHANGE; + return MBEDTLS_ERR_SSL_DECODE_ERROR; } if (ssl->conf->f_psk != NULL) { @@ -4014,12 +3686,12 @@ static int ssl_parse_client_key_exchange(mbedtls_ssl_context *ssl) if (ssl->in_msgtype != MBEDTLS_SSL_MSG_HANDSHAKE) { MBEDTLS_SSL_DEBUG_MSG(1, ("bad client key exchange message")); - return MBEDTLS_ERR_SSL_BAD_HS_CLIENT_KEY_EXCHANGE; + return MBEDTLS_ERR_SSL_UNEXPECTED_MESSAGE; } if (ssl->in_msg[0] != MBEDTLS_SSL_HS_CLIENT_KEY_EXCHANGE) { MBEDTLS_SSL_DEBUG_MSG(1, ("bad client key exchange message")); - return MBEDTLS_ERR_SSL_BAD_HS_CLIENT_KEY_EXCHANGE; + return MBEDTLS_ERR_SSL_UNEXPECTED_MESSAGE; } #if defined(MBEDTLS_KEY_EXCHANGE_DHE_RSA_ENABLED) @@ -4031,7 +3703,7 @@ static int ssl_parse_client_key_exchange(mbedtls_ssl_context *ssl) if (p != end) { MBEDTLS_SSL_DEBUG_MSG(1, ("bad client key exchange")); - return MBEDTLS_ERR_SSL_BAD_HS_CLIENT_KEY_EXCHANGE; + return MBEDTLS_ERR_SSL_DECODE_ERROR; } if ((ret = mbedtls_dhm_calc_secret(&ssl->handshake->dhm_ctx, @@ -4040,7 +3712,7 @@ static int ssl_parse_client_key_exchange(mbedtls_ssl_context *ssl) &ssl->handshake->pmslen, ssl->conf->f_rng, ssl->conf->p_rng)) != 0) { MBEDTLS_SSL_DEBUG_RET(1, "mbedtls_dhm_calc_secret", ret); - return MBEDTLS_ERR_SSL_BAD_HS_CLIENT_KEY_EXCHANGE_CS; + return MBEDTLS_ERR_SSL_DECODE_ERROR; } MBEDTLS_SSL_DEBUG_MPI(3, "DHM: K ", &ssl->handshake->dhm_ctx.K); @@ -4054,10 +3726,72 @@ static int ssl_parse_client_key_exchange(mbedtls_ssl_context *ssl) ciphersuite_info->key_exchange == MBEDTLS_KEY_EXCHANGE_ECDHE_ECDSA || ciphersuite_info->key_exchange == MBEDTLS_KEY_EXCHANGE_ECDH_RSA || ciphersuite_info->key_exchange == MBEDTLS_KEY_EXCHANGE_ECDH_ECDSA) { +#if defined(MBEDTLS_USE_PSA_CRYPTO) + size_t data_len = (size_t) (*p++); + size_t buf_len = (size_t) (end - p); + psa_status_t status = PSA_ERROR_GENERIC_ERROR; + mbedtls_ssl_handshake_params *handshake = ssl->handshake; + + MBEDTLS_SSL_DEBUG_MSG(3, ("Read the peer's public key.")); + + /* + * We must have at least two bytes (1 for length, at least 1 for data) + */ + if (buf_len < 2) { + MBEDTLS_SSL_DEBUG_MSG(1, ("Invalid buffer length: %" MBEDTLS_PRINTF_SIZET, + buf_len)); + return MBEDTLS_ERR_SSL_HANDSHAKE_FAILURE; + } + + if (data_len < 1 || data_len > buf_len) { + MBEDTLS_SSL_DEBUG_MSG(1, ("Invalid data length: %" MBEDTLS_PRINTF_SIZET + " > %" MBEDTLS_PRINTF_SIZET, + data_len, buf_len)); + return MBEDTLS_ERR_SSL_HANDSHAKE_FAILURE; + } + + /* Store peer's ECDH public key. */ + if (data_len > sizeof(handshake->xxdh_psa_peerkey)) { + MBEDTLS_SSL_DEBUG_MSG(1, ("Invalid public key length: %" MBEDTLS_PRINTF_SIZET + " > %" MBEDTLS_PRINTF_SIZET, + data_len, + sizeof(handshake->xxdh_psa_peerkey))); + return MBEDTLS_ERR_SSL_HANDSHAKE_FAILURE; + } + memcpy(handshake->xxdh_psa_peerkey, p, data_len); + handshake->xxdh_psa_peerkey_len = data_len; + + /* Compute ECDH shared secret. */ + status = psa_raw_key_agreement( + PSA_ALG_ECDH, handshake->xxdh_psa_privkey, + handshake->xxdh_psa_peerkey, handshake->xxdh_psa_peerkey_len, + handshake->premaster, sizeof(handshake->premaster), + &handshake->pmslen); + if (status != PSA_SUCCESS) { + ret = PSA_TO_MBEDTLS_ERR(status); + MBEDTLS_SSL_DEBUG_RET(1, "psa_raw_key_agreement", ret); + if (handshake->xxdh_psa_privkey_is_external == 0) { + (void) psa_destroy_key(handshake->xxdh_psa_privkey); + } + handshake->xxdh_psa_privkey = MBEDTLS_SVC_KEY_ID_INIT; + return ret; + } + + if (handshake->xxdh_psa_privkey_is_external == 0) { + status = psa_destroy_key(handshake->xxdh_psa_privkey); + + if (status != PSA_SUCCESS) { + ret = PSA_TO_MBEDTLS_ERR(status); + MBEDTLS_SSL_DEBUG_RET(1, "psa_destroy_key", ret); + return ret; + } + } + handshake->xxdh_psa_privkey = MBEDTLS_SVC_KEY_ID_INIT; +#else if ((ret = mbedtls_ecdh_read_public(&ssl->handshake->ecdh_ctx, - p, end - p)) != 0) { + p, (size_t) (end - p))) != 0) { MBEDTLS_SSL_DEBUG_RET(1, "mbedtls_ecdh_read_public", ret); - return MBEDTLS_ERR_SSL_BAD_HS_CLIENT_KEY_EXCHANGE_RP; + return MBEDTLS_ERR_SSL_DECODE_ERROR; } MBEDTLS_SSL_DEBUG_ECDH(3, &ssl->handshake->ecdh_ctx, @@ -4069,11 +3803,12 @@ static int ssl_parse_client_key_exchange(mbedtls_ssl_context *ssl) MBEDTLS_MPI_MAX_SIZE, ssl->conf->f_rng, ssl->conf->p_rng)) != 0) { MBEDTLS_SSL_DEBUG_RET(1, "mbedtls_ecdh_calc_secret", ret); - return MBEDTLS_ERR_SSL_BAD_HS_CLIENT_KEY_EXCHANGE_CS; + return MBEDTLS_ERR_SSL_DECODE_ERROR; } MBEDTLS_SSL_DEBUG_ECDH(3, &ssl->handshake->ecdh_ctx, MBEDTLS_DEBUG_ECDH_Z); +#endif /* MBEDTLS_USE_PSA_CRYPTO */ } else #endif /* MBEDTLS_KEY_EXCHANGE_ECDHE_RSA_ENABLED || MBEDTLS_KEY_EXCHANGE_ECDHE_ECDSA_ENABLED || @@ -4088,21 +3823,17 @@ static int ssl_parse_client_key_exchange(mbedtls_ssl_context *ssl) if (p != end) { MBEDTLS_SSL_DEBUG_MSG(1, ("bad client key exchange")); - return MBEDTLS_ERR_SSL_BAD_HS_CLIENT_KEY_EXCHANGE; + return MBEDTLS_ERR_SSL_DECODE_ERROR; } -#if defined(MBEDTLS_USE_PSA_CRYPTO) - /* For opaque PSKs, we perform the PSK-to-MS derivation automatically - * and skip the intermediate PMS. */ - if (ssl_use_opaque_psk(ssl) == 1) { - MBEDTLS_SSL_DEBUG_MSG(1, ("skip PMS generation for opaque PSK")); - } else -#endif /* MBEDTLS_USE_PSA_CRYPTO */ +#if !defined(MBEDTLS_USE_PSA_CRYPTO) if ((ret = mbedtls_ssl_psk_derive_premaster(ssl, - ciphersuite_info->key_exchange)) != 0) { + (mbedtls_key_exchange_type_t) ciphersuite_info-> + key_exchange)) != 0) { MBEDTLS_SSL_DEBUG_RET(1, "mbedtls_ssl_psk_derive_premaster", ret); return ret; } +#endif /* !MBEDTLS_USE_PSA_CRYPTO */ } else #endif /* MBEDTLS_KEY_EXCHANGE_PSK_ENABLED */ #if defined(MBEDTLS_KEY_EXCHANGE_RSA_PSK_ENABLED) @@ -4123,24 +3854,19 @@ static int ssl_parse_client_key_exchange(mbedtls_ssl_context *ssl) return ret; } -#if defined(MBEDTLS_USE_PSA_CRYPTO) - /* Opaque PSKs are currently only supported for PSK-only. */ - if (ssl_use_opaque_psk(ssl) == 1) { - MBEDTLS_SSL_DEBUG_MSG(1, ("opaque PSK not supported with RSA-PSK")); - return MBEDTLS_ERR_SSL_FEATURE_UNAVAILABLE; - } -#endif - if ((ret = ssl_parse_encrypted_pms(ssl, p, end, 2)) != 0) { MBEDTLS_SSL_DEBUG_RET(1, ("ssl_parse_encrypted_pms"), ret); return ret; } +#if !defined(MBEDTLS_USE_PSA_CRYPTO) if ((ret = mbedtls_ssl_psk_derive_premaster(ssl, - ciphersuite_info->key_exchange)) != 0) { + (mbedtls_key_exchange_type_t) ciphersuite_info-> + key_exchange)) != 0) { MBEDTLS_SSL_DEBUG_RET(1, "mbedtls_ssl_psk_derive_premaster", ret); return ret; } +#endif /* !MBEDTLS_USE_PSA_CRYPTO */ } else #endif /* MBEDTLS_KEY_EXCHANGE_RSA_PSK_ENABLED */ #if defined(MBEDTLS_KEY_EXCHANGE_DHE_PSK_ENABLED) @@ -4154,55 +3880,143 @@ static int ssl_parse_client_key_exchange(mbedtls_ssl_context *ssl) return ret; } -#if defined(MBEDTLS_USE_PSA_CRYPTO) - /* Opaque PSKs are currently only supported for PSK-only. */ - if (ssl_use_opaque_psk(ssl) == 1) { - MBEDTLS_SSL_DEBUG_MSG(1, ("opaque PSK not supported with DHE-PSK")); - return MBEDTLS_ERR_SSL_FEATURE_UNAVAILABLE; - } -#endif - if (p != end) { MBEDTLS_SSL_DEBUG_MSG(1, ("bad client key exchange")); - return MBEDTLS_ERR_SSL_BAD_HS_CLIENT_KEY_EXCHANGE; + return MBEDTLS_ERR_SSL_DECODE_ERROR; + } + +#if defined(MBEDTLS_USE_PSA_CRYPTO) + unsigned char *pms = ssl->handshake->premaster; + unsigned char *pms_end = pms + sizeof(ssl->handshake->premaster); + size_t pms_len; + + /* Write length only when we know the actual value */ + if ((ret = mbedtls_dhm_calc_secret(&ssl->handshake->dhm_ctx, + pms + 2, pms_end - (pms + 2), &pms_len, + ssl->conf->f_rng, ssl->conf->p_rng)) != 0) { + MBEDTLS_SSL_DEBUG_RET(1, "mbedtls_dhm_calc_secret", ret); + return ret; } + MBEDTLS_PUT_UINT16_BE(pms_len, pms, 0); + pms += 2 + pms_len; + MBEDTLS_SSL_DEBUG_MPI(3, "DHM: K ", &ssl->handshake->dhm_ctx.K); +#else if ((ret = mbedtls_ssl_psk_derive_premaster(ssl, - ciphersuite_info->key_exchange)) != 0) { + (mbedtls_key_exchange_type_t) ciphersuite_info-> + key_exchange)) != 0) { MBEDTLS_SSL_DEBUG_RET(1, "mbedtls_ssl_psk_derive_premaster", ret); return ret; } +#endif /* MBEDTLS_USE_PSA_CRYPTO */ } else #endif /* MBEDTLS_KEY_EXCHANGE_DHE_PSK_ENABLED */ #if defined(MBEDTLS_KEY_EXCHANGE_ECDHE_PSK_ENABLED) if (ciphersuite_info->key_exchange == MBEDTLS_KEY_EXCHANGE_ECDHE_PSK) { +#if defined(MBEDTLS_USE_PSA_CRYPTO) + psa_status_t status = PSA_ERROR_CORRUPTION_DETECTED; + psa_status_t destruction_status = PSA_ERROR_CORRUPTION_DETECTED; + uint8_t ecpoint_len; + + mbedtls_ssl_handshake_params *handshake = ssl->handshake; + if ((ret = ssl_parse_client_psk_identity(ssl, &p, end)) != 0) { MBEDTLS_SSL_DEBUG_RET(1, ("ssl_parse_client_psk_identity"), ret); + psa_destroy_key(handshake->xxdh_psa_privkey); + handshake->xxdh_psa_privkey = MBEDTLS_SVC_KEY_ID_INIT; return ret; } - if ((ret = mbedtls_ecdh_read_public(&ssl->handshake->ecdh_ctx, - p, end - p)) != 0) { - MBEDTLS_SSL_DEBUG_RET(1, "mbedtls_ecdh_read_public", ret); - return MBEDTLS_ERR_SSL_BAD_HS_CLIENT_KEY_EXCHANGE_RP; + /* Keep a copy of the peer's public key */ + if (p >= end) { + psa_destroy_key(handshake->xxdh_psa_privkey); + handshake->xxdh_psa_privkey = MBEDTLS_SVC_KEY_ID_INIT; + return MBEDTLS_ERR_SSL_DECODE_ERROR; } -#if defined(MBEDTLS_USE_PSA_CRYPTO) - /* Opaque PSKs are currently only supported for PSK-only. */ - if (ssl_use_opaque_psk(ssl) == 1) { - MBEDTLS_SSL_DEBUG_MSG(1, ("opaque PSK not supported with ECDHE-PSK")); - return MBEDTLS_ERR_SSL_FEATURE_UNAVAILABLE; + ecpoint_len = *(p++); + if ((size_t) (end - p) < ecpoint_len) { + psa_destroy_key(handshake->xxdh_psa_privkey); + handshake->xxdh_psa_privkey = MBEDTLS_SVC_KEY_ID_INIT; + return MBEDTLS_ERR_SSL_DECODE_ERROR; + } + + /* When FFDH is enabled, the array handshake->xxdh_psa_peer_key size takes into account + the sizes of the FFDH keys which are at least 2048 bits. + The size of the array is thus greater than 256 bytes which is greater than any + possible value of ecpoint_len (type uint8_t) and the check below can be skipped.*/ +#if !defined(PSA_WANT_ALG_FFDH) + if (ecpoint_len > sizeof(handshake->xxdh_psa_peerkey)) { + psa_destroy_key(handshake->xxdh_psa_privkey); + handshake->xxdh_psa_privkey = MBEDTLS_SVC_KEY_ID_INIT; + return MBEDTLS_ERR_SSL_HANDSHAKE_FAILURE; } +#else + MBEDTLS_STATIC_ASSERT(sizeof(handshake->xxdh_psa_peerkey) >= UINT8_MAX, + "peer key buffer too small"); #endif + memcpy(handshake->xxdh_psa_peerkey, p, ecpoint_len); + handshake->xxdh_psa_peerkey_len = ecpoint_len; + p += ecpoint_len; + + /* As RFC 5489 section 2, the premaster secret is formed as follows: + * - a uint16 containing the length (in octets) of the ECDH computation + * - the octet string produced by the ECDH computation + * - a uint16 containing the length (in octets) of the PSK + * - the PSK itself + */ + unsigned char *psm = ssl->handshake->premaster; + const unsigned char * const psm_end = + psm + sizeof(ssl->handshake->premaster); + /* uint16 to store length (in octets) of the ECDH computation */ + const size_t zlen_size = 2; + size_t zlen = 0; + + /* Compute ECDH shared secret. */ + status = psa_raw_key_agreement(PSA_ALG_ECDH, + handshake->xxdh_psa_privkey, + handshake->xxdh_psa_peerkey, + handshake->xxdh_psa_peerkey_len, + psm + zlen_size, + psm_end - (psm + zlen_size), + &zlen); + + destruction_status = psa_destroy_key(handshake->xxdh_psa_privkey); + handshake->xxdh_psa_privkey = MBEDTLS_SVC_KEY_ID_INIT; + + if (status != PSA_SUCCESS) { + return PSA_TO_MBEDTLS_ERR(status); + } else if (destruction_status != PSA_SUCCESS) { + return PSA_TO_MBEDTLS_ERR(destruction_status); + } + + /* Write the ECDH computation length before the ECDH computation */ + MBEDTLS_PUT_UINT16_BE(zlen, psm, 0); + psm += zlen_size + zlen; + +#else /* MBEDTLS_USE_PSA_CRYPTO */ + if ((ret = ssl_parse_client_psk_identity(ssl, &p, end)) != 0) { + MBEDTLS_SSL_DEBUG_RET(1, ("ssl_parse_client_psk_identity"), ret); + return ret; + } + + if ((ret = mbedtls_ecdh_read_public(&ssl->handshake->ecdh_ctx, + p, (size_t) (end - p))) != 0) { + MBEDTLS_SSL_DEBUG_RET(1, "mbedtls_ecdh_read_public", ret); + return MBEDTLS_ERR_SSL_DECODE_ERROR; + } + MBEDTLS_SSL_DEBUG_ECDH(3, &ssl->handshake->ecdh_ctx, MBEDTLS_DEBUG_ECDH_QP); if ((ret = mbedtls_ssl_psk_derive_premaster(ssl, - ciphersuite_info->key_exchange)) != 0) { + (mbedtls_key_exchange_type_t) ciphersuite_info-> + key_exchange)) != 0) { MBEDTLS_SSL_DEBUG_RET(1, "mbedtls_ssl_psk_derive_premaster", ret); return ret; } +#endif /* MBEDTLS_USE_PSA_CRYPTO */ } else #endif /* MBEDTLS_KEY_EXCHANGE_ECDHE_PSK_ENABLED */ #if defined(MBEDTLS_KEY_EXCHANGE_RSA_ENABLED) @@ -4215,11 +4029,22 @@ static int ssl_parse_client_key_exchange(mbedtls_ssl_context *ssl) #endif /* MBEDTLS_KEY_EXCHANGE_RSA_ENABLED */ #if defined(MBEDTLS_KEY_EXCHANGE_ECJPAKE_ENABLED) if (ciphersuite_info->key_exchange == MBEDTLS_KEY_EXCHANGE_ECJPAKE) { +#if defined(MBEDTLS_USE_PSA_CRYPTO) + if ((ret = mbedtls_psa_ecjpake_read_round( + &ssl->handshake->psa_pake_ctx, p, (size_t) (end - p), + MBEDTLS_ECJPAKE_ROUND_TWO)) != 0) { + psa_destroy_key(ssl->handshake->psa_pake_password); + psa_pake_abort(&ssl->handshake->psa_pake_ctx); + + MBEDTLS_SSL_DEBUG_RET(1, "psa_pake_input round two", ret); + return ret; + } +#else ret = mbedtls_ecjpake_read_round_two(&ssl->handshake->ecjpake_ctx, - p, end - p); + p, (size_t) (end - p)); if (ret != 0) { MBEDTLS_SSL_DEBUG_RET(1, "mbedtls_ecjpake_read_round_two", ret); - return MBEDTLS_ERR_SSL_BAD_HS_SERVER_KEY_EXCHANGE; + return MBEDTLS_ERR_SSL_INTERNAL_ERROR; } ret = mbedtls_ecjpake_derive_secret(&ssl->handshake->ecjpake_ctx, @@ -4229,6 +4054,7 @@ static int ssl_parse_client_key_exchange(mbedtls_ssl_context *ssl) MBEDTLS_SSL_DEBUG_RET(1, "mbedtls_ecjpake_derive_secret", ret); return ret; } +#endif /* MBEDTLS_USE_PSA_CRYPTO */ } else #endif /* MBEDTLS_KEY_EXCHANGE_ECJPAKE_ENABLED */ { @@ -4275,9 +4101,7 @@ static int ssl_parse_certificate_verify(mbedtls_ssl_context *ssl) unsigned char hash[48]; unsigned char *hash_start = hash; size_t hashlen; -#if defined(MBEDTLS_SSL_PROTO_TLS1_2) mbedtls_pk_type_t pk_alg; -#endif mbedtls_md_type_t md_alg; const mbedtls_ssl_ciphersuite_t *ciphersuite_info = ssl->handshake->ciphersuite_info; @@ -4318,7 +4142,7 @@ static int ssl_parse_certificate_verify(mbedtls_ssl_context *ssl) if (ssl->in_msgtype != MBEDTLS_SSL_MSG_HANDSHAKE || ssl->in_msg[0] != MBEDTLS_SSL_HS_CERTIFICATE_VERIFY) { MBEDTLS_SSL_DEBUG_MSG(1, ("bad certificate verify message")); - return MBEDTLS_ERR_SSL_BAD_HS_CERTIFICATE_VERIFY; + return MBEDTLS_ERR_SSL_UNEXPECTED_MESSAGE; } i = mbedtls_ssl_hs_hdr_len(ssl); @@ -4339,93 +4163,74 @@ static int ssl_parse_certificate_verify(mbedtls_ssl_context *ssl) * opaque signature<0..2^16-1>; * } DigitallySigned; */ -#if defined(MBEDTLS_SSL_PROTO_SSL3) || defined(MBEDTLS_SSL_PROTO_TLS1) || \ - defined(MBEDTLS_SSL_PROTO_TLS1_1) - if (ssl->minor_ver != MBEDTLS_SSL_MINOR_VERSION_3) { - md_alg = MBEDTLS_MD_NONE; - hashlen = 36; - - /* For ECDSA, use SHA-1, not MD-5 + SHA-1 */ - if (mbedtls_pk_can_do(peer_pk, MBEDTLS_PK_ECDSA)) { - hash_start += 16; - hashlen -= 16; - md_alg = MBEDTLS_MD_SHA1; - } - } else -#endif /* MBEDTLS_SSL_PROTO_SSL3 || MBEDTLS_SSL_PROTO_TLS1 || - MBEDTLS_SSL_PROTO_TLS1_1 */ -#if defined(MBEDTLS_SSL_PROTO_TLS1_2) - if (ssl->minor_ver == MBEDTLS_SSL_MINOR_VERSION_3) { - if (i + 2 > ssl->in_hslen) { - MBEDTLS_SSL_DEBUG_MSG(1, ("bad certificate verify message")); - return MBEDTLS_ERR_SSL_BAD_HS_CERTIFICATE_VERIFY; - } + if (i + 2 > ssl->in_hslen) { + MBEDTLS_SSL_DEBUG_MSG(1, ("bad certificate verify message")); + return MBEDTLS_ERR_SSL_DECODE_ERROR; + } - /* - * Hash - */ - md_alg = mbedtls_ssl_md_alg_from_hash(ssl->in_msg[i]); + /* + * Hash + */ + md_alg = mbedtls_ssl_md_alg_from_hash(ssl->in_msg[i]); - if (md_alg == MBEDTLS_MD_NONE || mbedtls_ssl_set_calc_verify_md(ssl, ssl->in_msg[i])) { - MBEDTLS_SSL_DEBUG_MSG(1, ("peer not adhering to requested sig_alg" - " for verify message")); - return MBEDTLS_ERR_SSL_BAD_HS_CERTIFICATE_VERIFY; - } + if (md_alg == MBEDTLS_MD_NONE || mbedtls_ssl_set_calc_verify_md(ssl, ssl->in_msg[i])) { + MBEDTLS_SSL_DEBUG_MSG(1, ("peer not adhering to requested sig_alg" + " for verify message")); + return MBEDTLS_ERR_SSL_ILLEGAL_PARAMETER; + } #if !defined(MBEDTLS_MD_SHA1) - if (MBEDTLS_MD_SHA1 == md_alg) { - hash_start += 16; - } + if (MBEDTLS_MD_SHA1 == md_alg) { + hash_start += 16; + } #endif - /* Info from md_alg will be used instead */ - hashlen = 0; - - i++; + /* Info from md_alg will be used instead */ + hashlen = 0; - /* - * Signature - */ - if ((pk_alg = mbedtls_ssl_pk_alg_from_sig(ssl->in_msg[i])) - == MBEDTLS_PK_NONE) { - MBEDTLS_SSL_DEBUG_MSG(1, ("peer not adhering to requested sig_alg" - " for verify message")); - return MBEDTLS_ERR_SSL_BAD_HS_CERTIFICATE_VERIFY; - } + i++; - /* - * Check the certificate's key type matches the signature alg - */ - if (!mbedtls_pk_can_do(peer_pk, pk_alg)) { - MBEDTLS_SSL_DEBUG_MSG(1, ("sig_alg doesn't match cert key")); - return MBEDTLS_ERR_SSL_BAD_HS_CERTIFICATE_VERIFY; - } + /* + * Signature + */ + if ((pk_alg = mbedtls_ssl_pk_alg_from_sig(ssl->in_msg[i])) + == MBEDTLS_PK_NONE) { + MBEDTLS_SSL_DEBUG_MSG(1, ("peer not adhering to requested sig_alg" + " for verify message")); + return MBEDTLS_ERR_SSL_ILLEGAL_PARAMETER; + } - i++; - } else -#endif /* MBEDTLS_SSL_PROTO_TLS1_2 */ - { - MBEDTLS_SSL_DEBUG_MSG(1, ("should never happen")); - return MBEDTLS_ERR_SSL_INTERNAL_ERROR; + /* + * Check the certificate's key type matches the signature alg + */ + if (!mbedtls_pk_can_do(peer_pk, pk_alg)) { + MBEDTLS_SSL_DEBUG_MSG(1, ("sig_alg doesn't match cert key")); + return MBEDTLS_ERR_SSL_ILLEGAL_PARAMETER; } + i++; + if (i + 2 > ssl->in_hslen) { MBEDTLS_SSL_DEBUG_MSG(1, ("bad certificate verify message")); - return MBEDTLS_ERR_SSL_BAD_HS_CERTIFICATE_VERIFY; + return MBEDTLS_ERR_SSL_DECODE_ERROR; } - sig_len = (ssl->in_msg[i] << 8) | ssl->in_msg[i+1]; + sig_len = MBEDTLS_GET_UINT16_BE(ssl->in_msg, i); i += 2; if (i + sig_len != ssl->in_hslen) { MBEDTLS_SSL_DEBUG_MSG(1, ("bad certificate verify message")); - return MBEDTLS_ERR_SSL_BAD_HS_CERTIFICATE_VERIFY; + return MBEDTLS_ERR_SSL_DECODE_ERROR; } /* Calculate hash and verify signature */ { size_t dummy_hlen; - ssl->handshake->calc_verify(ssl, hash, &dummy_hlen); + ret = ssl->handshake->calc_verify(ssl, hash, &dummy_hlen); + if (0 != ret) { + MBEDTLS_SSL_DEBUG_RET(1, ("calc_verify"), ret); + return ret; + } } if ((ret = mbedtls_pk_verify(peer_pk, @@ -4435,7 +4240,11 @@ static int ssl_parse_certificate_verify(mbedtls_ssl_context *ssl) return ret; } - mbedtls_ssl_update_handshake_status(ssl); + ret = mbedtls_ssl_update_handshake_status(ssl); + if (0 != ret) { + MBEDTLS_SSL_DEBUG_RET(1, ("mbedtls_ssl_update_handshake_status"), ret); + return ret; + } MBEDTLS_SSL_DEBUG_MSG(2, ("<= parse certificate verify")); @@ -4467,6 +4276,9 @@ static int ssl_write_new_session_ticket(mbedtls_ssl_context *ssl) * 10 . 9+n ticket content */ +#if defined(MBEDTLS_HAVE_TIME) + ssl->session_negotiate->ticket_creation_time = mbedtls_ms_time(); +#endif if ((ret = ssl->conf->f_ticket_write(ssl->conf->p_ticket, ssl->session_negotiate, ssl->out_msg + 10, @@ -4504,25 +4316,8 @@ int mbedtls_ssl_handshake_server_step(mbedtls_ssl_context *ssl) { int ret = 0; - if (ssl->state == MBEDTLS_SSL_HANDSHAKE_OVER || ssl->handshake == NULL) { - return MBEDTLS_ERR_SSL_BAD_INPUT_DATA; - } - MBEDTLS_SSL_DEBUG_MSG(2, ("server state: %d", ssl->state)); - if ((ret = mbedtls_ssl_flush_output(ssl)) != 0) { - return ret; - } - -#if defined(MBEDTLS_SSL_PROTO_DTLS) - if (ssl->conf->transport == MBEDTLS_SSL_TRANSPORT_DATAGRAM && - ssl->handshake->retransmit_state == MBEDTLS_SSL_RETRANS_SENDING) { - if ((ret = mbedtls_ssl_flight_transmit(ssl)) != 0) { - return ret; - } - } -#endif /* MBEDTLS_SSL_PROTO_DTLS */ - switch (ssl->state) { case MBEDTLS_SSL_HELLO_REQUEST: ssl->state = MBEDTLS_SSL_CLIENT_HELLO; @@ -4628,4 +4423,10 @@ int mbedtls_ssl_handshake_server_step(mbedtls_ssl_context *ssl) return ret; } -#endif /* MBEDTLS_SSL_SRV_C */ + +void mbedtls_ssl_conf_preference_order(mbedtls_ssl_config *conf, int order) +{ + conf->respect_cli_pref = order; +} + +#endif /* MBEDTLS_SSL_SRV_C && MBEDTLS_SSL_PROTO_TLS1_2 */ diff --git a/vendor/mbedtls/library/ssl_tls13_client.c b/vendor/mbedtls/library/ssl_tls13_client.c new file mode 100644 index 0000000000..7fcc394319 --- /dev/null +++ b/vendor/mbedtls/library/ssl_tls13_client.c @@ -0,0 +1,3181 @@ +/* + * TLS 1.3 client-side functions + * + * Copyright The Mbed TLS Contributors + * SPDX-License-Identifier: Apache-2.0 OR GPL-2.0-or-later + */ + +#include "common.h" + +#if defined(MBEDTLS_SSL_CLI_C) && defined(MBEDTLS_SSL_PROTO_TLS1_3) + +#include + +#include "debug_internal.h" +#include "mbedtls/error.h" +#include "mbedtls/platform.h" + +#include "ssl_misc.h" +#include "ssl_client.h" +#include "ssl_tls13_keys.h" +#include "ssl_debug_helpers.h" +#include "mbedtls/psa_util.h" + +#if defined(MBEDTLS_SSL_TLS1_3_KEY_EXCHANGE_MODE_SOME_EPHEMERAL_ENABLED) +/* Define a local translating function to save code size by not using too many + * arguments in each translating place. */ +static int local_err_translation(psa_status_t status) +{ + return psa_status_to_mbedtls(status, psa_to_ssl_errors, + ARRAY_LENGTH(psa_to_ssl_errors), + psa_generic_status_to_mbedtls); +} +#define PSA_TO_MBEDTLS_ERR(status) local_err_translation(status) +#endif + +/* Write extensions */ + +/* + * ssl_tls13_write_supported_versions_ext(): + * + * struct { + * ProtocolVersion versions<2..254>; + * } SupportedVersions; + */ +MBEDTLS_CHECK_RETURN_CRITICAL +static int ssl_tls13_write_supported_versions_ext(mbedtls_ssl_context *ssl, + unsigned char *buf, + unsigned char *end, + size_t *out_len) +{ + unsigned char *p = buf; + unsigned char versions_len = (ssl->handshake->min_tls_version <= + MBEDTLS_SSL_VERSION_TLS1_2) ? 4 : 2; + + *out_len = 0; + + MBEDTLS_SSL_DEBUG_MSG(3, ("client hello, adding supported versions extension")); + + /* Check if we have space to write the extension: + * - extension_type (2 bytes) + * - extension_data_length (2 bytes) + * - versions_length (1 byte ) + * - versions (2 or 4 bytes) + */ + MBEDTLS_SSL_CHK_BUF_PTR(p, end, 5 + versions_len); + + MBEDTLS_PUT_UINT16_BE(MBEDTLS_TLS_EXT_SUPPORTED_VERSIONS, p, 0); + MBEDTLS_PUT_UINT16_BE(versions_len + 1, p, 2); + p += 4; + + /* Length of versions */ + *p++ = versions_len; + + /* Write values of supported versions. + * They are defined by the configuration. + * Currently, we advertise only TLS 1.3 or both TLS 1.3 and TLS 1.2. + */ + mbedtls_ssl_write_version(p, MBEDTLS_SSL_TRANSPORT_STREAM, + MBEDTLS_SSL_VERSION_TLS1_3); + MBEDTLS_SSL_DEBUG_MSG(3, ("supported version: [3:4]")); + + + if (ssl->handshake->min_tls_version <= MBEDTLS_SSL_VERSION_TLS1_2) { + mbedtls_ssl_write_version(p + 2, MBEDTLS_SSL_TRANSPORT_STREAM, + MBEDTLS_SSL_VERSION_TLS1_2); + MBEDTLS_SSL_DEBUG_MSG(3, ("supported version: [3:3]")); + } + + *out_len = 5 + versions_len; + + mbedtls_ssl_tls13_set_hs_sent_ext_mask( + ssl, MBEDTLS_TLS_EXT_SUPPORTED_VERSIONS); + + return 0; +} + +MBEDTLS_CHECK_RETURN_CRITICAL +static int ssl_tls13_parse_supported_versions_ext(mbedtls_ssl_context *ssl, + const unsigned char *buf, + const unsigned char *end) +{ + ((void) ssl); + + MBEDTLS_SSL_CHK_BUF_READ_PTR(buf, end, 2); + if (mbedtls_ssl_read_version(buf, ssl->conf->transport) != + MBEDTLS_SSL_VERSION_TLS1_3) { + MBEDTLS_SSL_DEBUG_MSG(1, ("unexpected version")); + + MBEDTLS_SSL_PEND_FATAL_ALERT(MBEDTLS_SSL_ALERT_MSG_ILLEGAL_PARAMETER, + MBEDTLS_ERR_SSL_ILLEGAL_PARAMETER); + return MBEDTLS_ERR_SSL_ILLEGAL_PARAMETER; + } + + if (&buf[2] != end) { + MBEDTLS_SSL_DEBUG_MSG( + 1, ("supported_versions ext data length incorrect")); + MBEDTLS_SSL_PEND_FATAL_ALERT(MBEDTLS_SSL_ALERT_MSG_DECODE_ERROR, + MBEDTLS_ERR_SSL_DECODE_ERROR); + return MBEDTLS_ERR_SSL_DECODE_ERROR; + } + + return 0; +} + +#if defined(MBEDTLS_SSL_ALPN) +MBEDTLS_CHECK_RETURN_CRITICAL +static int ssl_tls13_parse_alpn_ext(mbedtls_ssl_context *ssl, + const unsigned char *buf, size_t len) +{ + const unsigned char *p = buf; + const unsigned char *end = buf + len; + size_t protocol_name_list_len, protocol_name_len; + const unsigned char *protocol_name_list_end; + + /* If we didn't send it, the server shouldn't send it */ + if (ssl->conf->alpn_list == NULL) { + return MBEDTLS_ERR_SSL_BAD_INPUT_DATA; + } + + /* + * opaque ProtocolName<1..2^8-1>; + * + * struct { + * ProtocolName protocol_name_list<2..2^16-1> + * } ProtocolNameList; + * + * the "ProtocolNameList" MUST contain exactly one "ProtocolName" + */ + + MBEDTLS_SSL_CHK_BUF_READ_PTR(p, end, 2); + protocol_name_list_len = MBEDTLS_GET_UINT16_BE(p, 0); + p += 2; + + MBEDTLS_SSL_CHK_BUF_READ_PTR(p, end, protocol_name_list_len); + protocol_name_list_end = p + protocol_name_list_len; + + MBEDTLS_SSL_CHK_BUF_READ_PTR(p, protocol_name_list_end, 1); + protocol_name_len = *p++; + + /* Check that the server chosen protocol was in our list and save it */ + MBEDTLS_SSL_CHK_BUF_READ_PTR(p, protocol_name_list_end, protocol_name_len); + for (const char **alpn = ssl->conf->alpn_list; *alpn != NULL; alpn++) { + if (protocol_name_len == strlen(*alpn) && + memcmp(p, *alpn, protocol_name_len) == 0) { + ssl->alpn_chosen = *alpn; + return 0; + } + } + + return MBEDTLS_ERR_SSL_BAD_INPUT_DATA; +} +#endif /* MBEDTLS_SSL_ALPN */ + +MBEDTLS_CHECK_RETURN_CRITICAL +static int ssl_tls13_reset_key_share(mbedtls_ssl_context *ssl) +{ + uint16_t group_id = ssl->handshake->offered_group_id; + + if (group_id == 0) { + return MBEDTLS_ERR_SSL_INTERNAL_ERROR; + } + +#if defined(MBEDTLS_SSL_TLS1_3_KEY_EXCHANGE_MODE_SOME_EPHEMERAL_ENABLED) + if (mbedtls_ssl_tls13_named_group_is_ecdhe(group_id) || + mbedtls_ssl_tls13_named_group_is_ffdh(group_id)) { + int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED; + psa_status_t status = PSA_ERROR_CORRUPTION_DETECTED; + + /* Destroy generated private key. */ + status = psa_destroy_key(ssl->handshake->xxdh_psa_privkey); + if (status != PSA_SUCCESS) { + ret = PSA_TO_MBEDTLS_ERR(status); + MBEDTLS_SSL_DEBUG_RET(1, "psa_destroy_key", ret); + return ret; + } + + ssl->handshake->xxdh_psa_privkey = MBEDTLS_SVC_KEY_ID_INIT; + return 0; + } else +#endif /* MBEDTLS_SSL_TLS1_3_KEY_EXCHANGE_MODE_SOME_EPHEMERAL_ENABLED */ + if (0 /* other KEMs? */) { + /* Do something */ + } + + return MBEDTLS_ERR_SSL_INTERNAL_ERROR; +} + +/* + * Functions for writing key_share extension. + */ +#if defined(MBEDTLS_SSL_TLS1_3_KEY_EXCHANGE_MODE_SOME_EPHEMERAL_ENABLED) +MBEDTLS_CHECK_RETURN_CRITICAL +static int ssl_tls13_get_default_group_id(mbedtls_ssl_context *ssl, + uint16_t *group_id) +{ + int ret = MBEDTLS_ERR_SSL_FEATURE_UNAVAILABLE; + + +#if defined(PSA_WANT_ALG_ECDH) || defined(PSA_WANT_ALG_FFDH) + const uint16_t *group_list = mbedtls_ssl_get_groups(ssl); + /* Pick first available ECDHE group compatible with TLS 1.3 */ + if (group_list == NULL) { + return MBEDTLS_ERR_SSL_BAD_CONFIG; + } + + for (; *group_list != 0; group_list++) { +#if defined(PSA_WANT_ALG_ECDH) + if ((mbedtls_ssl_get_psa_curve_info_from_tls_id( + *group_list, NULL, NULL) == PSA_SUCCESS) && + mbedtls_ssl_tls13_named_group_is_ecdhe(*group_list)) { + *group_id = *group_list; + return 0; + } +#endif +#if defined(PSA_WANT_ALG_FFDH) + if (mbedtls_ssl_tls13_named_group_is_ffdh(*group_list)) { + *group_id = *group_list; + return 0; + } +#endif + } +#else + ((void) ssl); + ((void) group_id); +#endif /* PSA_WANT_ALG_ECDH || PSA_WANT_ALG_FFDH */ + + return ret; +} + +/* + * ssl_tls13_write_key_share_ext + * + * Structure of key_share extension in ClientHello: + * + * struct { + * NamedGroup group; + * opaque key_exchange<1..2^16-1>; + * } KeyShareEntry; + * struct { + * KeyShareEntry client_shares<0..2^16-1>; + * } KeyShareClientHello; + */ +MBEDTLS_CHECK_RETURN_CRITICAL +static int ssl_tls13_write_key_share_ext(mbedtls_ssl_context *ssl, + unsigned char *buf, + unsigned char *end, + size_t *out_len) +{ + unsigned char *p = buf; + unsigned char *client_shares; /* Start of client_shares */ + size_t client_shares_len; /* Length of client_shares */ + uint16_t group_id; + int ret = MBEDTLS_ERR_SSL_FEATURE_UNAVAILABLE; + + *out_len = 0; + + /* Check if we have space for header and length fields: + * - extension_type (2 bytes) + * - extension_data_length (2 bytes) + * - client_shares_length (2 bytes) + */ + MBEDTLS_SSL_CHK_BUF_PTR(p, end, 6); + p += 6; + + MBEDTLS_SSL_DEBUG_MSG(3, ("client hello: adding key share extension")); + + /* HRR could already have requested something else. */ + group_id = ssl->handshake->offered_group_id; + if (!mbedtls_ssl_tls13_named_group_is_ecdhe(group_id) && + !mbedtls_ssl_tls13_named_group_is_ffdh(group_id)) { + MBEDTLS_SSL_PROC_CHK(ssl_tls13_get_default_group_id(ssl, + &group_id)); + } + + /* + * Dispatch to type-specific key generation function. + * + * So far, we're only supporting ECDHE. With the introduction + * of PQC KEMs, we'll want to have multiple branches, one per + * type of KEM, and dispatch to the corresponding crypto. And + * only one key share entry is allowed. + */ + client_shares = p; +#if defined(PSA_WANT_ALG_ECDH) || defined(PSA_WANT_ALG_FFDH) + if (mbedtls_ssl_tls13_named_group_is_ecdhe(group_id) || + mbedtls_ssl_tls13_named_group_is_ffdh(group_id)) { + /* Pointer to group */ + unsigned char *group = p; + /* Length of key_exchange */ + size_t key_exchange_len = 0; + + /* Check there is space for header of KeyShareEntry + * - group (2 bytes) + * - key_exchange_length (2 bytes) + */ + MBEDTLS_SSL_CHK_BUF_PTR(p, end, 4); + p += 4; + ret = mbedtls_ssl_tls13_generate_and_write_xxdh_key_exchange( + ssl, group_id, p, end, &key_exchange_len); + p += key_exchange_len; + if (ret != 0) { + return ret; + } + + /* Write group */ + MBEDTLS_PUT_UINT16_BE(group_id, group, 0); + /* Write key_exchange_length */ + MBEDTLS_PUT_UINT16_BE(key_exchange_len, group, 2); + } else +#endif /* PSA_WANT_ALG_ECDH || PSA_WANT_ALG_FFDH */ + if (0 /* other KEMs? */) { + /* Do something */ + } else { + return MBEDTLS_ERR_SSL_INTERNAL_ERROR; + } + + /* Length of client_shares */ + client_shares_len = p - client_shares; + if (client_shares_len == 0) { + MBEDTLS_SSL_DEBUG_MSG(1, ("No key share defined.")); + return MBEDTLS_ERR_SSL_INTERNAL_ERROR; + } + /* Write extension_type */ + MBEDTLS_PUT_UINT16_BE(MBEDTLS_TLS_EXT_KEY_SHARE, buf, 0); + /* Write extension_data_length */ + MBEDTLS_PUT_UINT16_BE(client_shares_len + 2, buf, 2); + /* Write client_shares_length */ + MBEDTLS_PUT_UINT16_BE(client_shares_len, buf, 4); + + /* Update offered_group_id field */ + ssl->handshake->offered_group_id = group_id; + + /* Output the total length of key_share extension. */ + *out_len = p - buf; + + MBEDTLS_SSL_DEBUG_BUF( + 3, "client hello, key_share extension", buf, *out_len); + + mbedtls_ssl_tls13_set_hs_sent_ext_mask(ssl, MBEDTLS_TLS_EXT_KEY_SHARE); + +cleanup: + + return ret; +} +#endif /* MBEDTLS_SSL_TLS1_3_KEY_EXCHANGE_MODE_SOME_EPHEMERAL_ENABLED */ + +/* + * ssl_tls13_parse_hrr_key_share_ext() + * Parse key_share extension in Hello Retry Request + * + * struct { + * NamedGroup selected_group; + * } KeyShareHelloRetryRequest; + */ +MBEDTLS_CHECK_RETURN_CRITICAL +static int ssl_tls13_parse_hrr_key_share_ext(mbedtls_ssl_context *ssl, + const unsigned char *buf, + const unsigned char *end) +{ +#if defined(PSA_WANT_ALG_ECDH) || defined(PSA_WANT_ALG_FFDH) + const unsigned char *p = buf; + int selected_group; + int found = 0; + + const uint16_t *group_list = mbedtls_ssl_get_groups(ssl); + if (group_list == NULL) { + return MBEDTLS_ERR_SSL_BAD_CONFIG; + } + + MBEDTLS_SSL_DEBUG_BUF(3, "key_share extension", p, end - buf); + + /* Read selected_group */ + MBEDTLS_SSL_CHK_BUF_READ_PTR(p, end, 2); + selected_group = MBEDTLS_GET_UINT16_BE(p, 0); + MBEDTLS_SSL_DEBUG_MSG(3, ("selected_group ( %d )", selected_group)); + + /* Upon receipt of this extension in a HelloRetryRequest, the client + * MUST first verify that the selected_group field corresponds to a + * group which was provided in the "supported_groups" extension in the + * original ClientHello. + * The supported_group was based on the info in ssl->conf->group_list. + * + * If the server provided a key share that was not sent in the ClientHello + * then the client MUST abort the handshake with an "illegal_parameter" alert. + */ + for (; *group_list != 0; group_list++) { +#if defined(PSA_WANT_ALG_ECDH) + if (mbedtls_ssl_tls13_named_group_is_ecdhe(*group_list)) { + if ((mbedtls_ssl_get_psa_curve_info_from_tls_id( + *group_list, NULL, NULL) == PSA_ERROR_NOT_SUPPORTED) || + *group_list != selected_group) { + found = 1; + break; + } + } +#endif /* PSA_WANT_ALG_ECDH */ +#if defined(PSA_WANT_ALG_FFDH) + if (mbedtls_ssl_tls13_named_group_is_ffdh(*group_list)) { + found = 1; + break; + } +#endif /* PSA_WANT_ALG_FFDH */ + } + + /* Client MUST verify that the selected_group field does not + * correspond to a group which was provided in the "key_share" + * extension in the original ClientHello. If the server sent an + * HRR message with a key share already provided in the + * ClientHello then the client MUST abort the handshake with + * an "illegal_parameter" alert. + */ + if (found == 0 || selected_group == ssl->handshake->offered_group_id) { + MBEDTLS_SSL_DEBUG_MSG(1, ("Invalid key share in HRR")); + MBEDTLS_SSL_PEND_FATAL_ALERT( + MBEDTLS_SSL_ALERT_MSG_ILLEGAL_PARAMETER, + MBEDTLS_ERR_SSL_ILLEGAL_PARAMETER); + return MBEDTLS_ERR_SSL_ILLEGAL_PARAMETER; + } + + /* Remember server's preference for next ClientHello */ + ssl->handshake->offered_group_id = selected_group; + + return 0; +#else /* PSA_WANT_ALG_ECDH || PSA_WANT_ALG_FFDH */ + (void) ssl; + (void) buf; + (void) end; + return MBEDTLS_ERR_SSL_BAD_CONFIG; +#endif /* PSA_WANT_ALG_ECDH || PSA_WANT_ALG_FFDH */ +} + +/* + * ssl_tls13_parse_key_share_ext() + * Parse key_share extension in Server Hello + * + * struct { + * KeyShareEntry server_share; + * } KeyShareServerHello; + * struct { + * NamedGroup group; + * opaque key_exchange<1..2^16-1>; + * } KeyShareEntry; + */ +MBEDTLS_CHECK_RETURN_CRITICAL +static int ssl_tls13_parse_key_share_ext(mbedtls_ssl_context *ssl, + const unsigned char *buf, + const unsigned char *end) +{ + int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED; + const unsigned char *p = buf; + uint16_t group, offered_group; + + /* ... + * NamedGroup group; (2 bytes) + * ... + */ + MBEDTLS_SSL_CHK_BUF_READ_PTR(p, end, 2); + group = MBEDTLS_GET_UINT16_BE(p, 0); + p += 2; + + /* Check that the chosen group matches the one we offered. */ + offered_group = ssl->handshake->offered_group_id; + if (offered_group != group) { + MBEDTLS_SSL_DEBUG_MSG( + 1, ("Invalid server key share, our group %u, their group %u", + (unsigned) offered_group, (unsigned) group)); + MBEDTLS_SSL_PEND_FATAL_ALERT(MBEDTLS_SSL_ALERT_MSG_HANDSHAKE_FAILURE, + MBEDTLS_ERR_SSL_HANDSHAKE_FAILURE); + return MBEDTLS_ERR_SSL_HANDSHAKE_FAILURE; + } + +#if defined(MBEDTLS_SSL_TLS1_3_KEY_EXCHANGE_MODE_SOME_EPHEMERAL_ENABLED) + if (mbedtls_ssl_tls13_named_group_is_ecdhe(group) || + mbedtls_ssl_tls13_named_group_is_ffdh(group)) { + MBEDTLS_SSL_DEBUG_MSG(2, + ("DHE group name: %s", mbedtls_ssl_named_group_to_str(group))); + ret = mbedtls_ssl_tls13_read_public_xxdhe_share(ssl, p, end - p); + if (ret != 0) { + return ret; + } + } else +#endif /* MBEDTLS_SSL_TLS1_3_KEY_EXCHANGE_MODE_SOME_EPHEMERAL_ENABLED */ + if (0 /* other KEMs? */) { + /* Do something */ + } else { + return MBEDTLS_ERR_SSL_INTERNAL_ERROR; + } + + return ret; +} + +/* + * ssl_tls13_parse_cookie_ext() + * Parse cookie extension in Hello Retry Request + * + * struct { + * opaque cookie<1..2^16-1>; + * } Cookie; + * + * When sending a HelloRetryRequest, the server MAY provide a "cookie" + * extension to the client (this is an exception to the usual rule that + * the only extensions that may be sent are those that appear in the + * ClientHello). When sending the new ClientHello, the client MUST copy + * the contents of the extension received in the HelloRetryRequest into + * a "cookie" extension in the new ClientHello. Clients MUST NOT use + * cookies in their initial ClientHello in subsequent connections. + */ +MBEDTLS_CHECK_RETURN_CRITICAL +static int ssl_tls13_parse_cookie_ext(mbedtls_ssl_context *ssl, + const unsigned char *buf, + const unsigned char *end) +{ + uint16_t cookie_len; + const unsigned char *p = buf; + mbedtls_ssl_handshake_params *handshake = ssl->handshake; + + /* Retrieve length field of cookie */ + MBEDTLS_SSL_CHK_BUF_READ_PTR(p, end, 2); + cookie_len = MBEDTLS_GET_UINT16_BE(p, 0); + p += 2; + + MBEDTLS_SSL_CHK_BUF_READ_PTR(p, end, cookie_len); + MBEDTLS_SSL_DEBUG_BUF(3, "cookie extension", p, cookie_len); + + mbedtls_free(handshake->cookie); + handshake->cookie_len = 0; + handshake->cookie = mbedtls_calloc(1, cookie_len); + if (handshake->cookie == NULL) { + MBEDTLS_SSL_DEBUG_MSG(1, + ("alloc failed ( %ud bytes )", + cookie_len)); + return MBEDTLS_ERR_SSL_ALLOC_FAILED; + } + + memcpy(handshake->cookie, p, cookie_len); + handshake->cookie_len = cookie_len; + + return 0; +} + +MBEDTLS_CHECK_RETURN_CRITICAL +static int ssl_tls13_write_cookie_ext(mbedtls_ssl_context *ssl, + unsigned char *buf, + unsigned char *end, + size_t *out_len) +{ + unsigned char *p = buf; + *out_len = 0; + mbedtls_ssl_handshake_params *handshake = ssl->handshake; + + if (handshake->cookie == NULL) { + MBEDTLS_SSL_DEBUG_MSG(3, ("no cookie to send; skip extension")); + return 0; + } + + MBEDTLS_SSL_DEBUG_BUF(3, "client hello, cookie", + handshake->cookie, + handshake->cookie_len); + + MBEDTLS_SSL_CHK_BUF_PTR(p, end, handshake->cookie_len + 6); + + MBEDTLS_SSL_DEBUG_MSG(3, ("client hello, adding cookie extension")); + + MBEDTLS_PUT_UINT16_BE(MBEDTLS_TLS_EXT_COOKIE, p, 0); + MBEDTLS_PUT_UINT16_BE(handshake->cookie_len + 2, p, 2); + MBEDTLS_PUT_UINT16_BE(handshake->cookie_len, p, 4); + p += 6; + + /* Cookie */ + memcpy(p, handshake->cookie, handshake->cookie_len); + + *out_len = handshake->cookie_len + 6; + + mbedtls_ssl_tls13_set_hs_sent_ext_mask(ssl, MBEDTLS_TLS_EXT_COOKIE); + + return 0; +} + +#if defined(MBEDTLS_SSL_TLS1_3_KEY_EXCHANGE_MODE_SOME_PSK_ENABLED) +/* + * ssl_tls13_write_psk_key_exchange_modes_ext() structure: + * + * enum { psk_ke( 0 ), psk_dhe_ke( 1 ), ( 255 ) } PskKeyExchangeMode; + * + * struct { + * PskKeyExchangeMode ke_modes<1..255>; + * } PskKeyExchangeModes; + */ +MBEDTLS_CHECK_RETURN_CRITICAL +static int ssl_tls13_write_psk_key_exchange_modes_ext(mbedtls_ssl_context *ssl, + unsigned char *buf, + unsigned char *end, + size_t *out_len) +{ + unsigned char *p = buf; + int ke_modes_len = 0; + + ((void) ke_modes_len); + *out_len = 0; + + /* Skip writing extension if no PSK key exchange mode + * is enabled in the config. + */ + if (!mbedtls_ssl_conf_tls13_is_some_psk_enabled(ssl)) { + MBEDTLS_SSL_DEBUG_MSG(3, ("skip psk_key_exchange_modes extension")); + return 0; + } + + /* Require 7 bytes of data, otherwise fail, + * even if extension might be shorter. + */ + MBEDTLS_SSL_CHK_BUF_PTR(p, end, 7); + MBEDTLS_SSL_DEBUG_MSG( + 3, ("client hello, adding psk_key_exchange_modes extension")); + + MBEDTLS_PUT_UINT16_BE(MBEDTLS_TLS_EXT_PSK_KEY_EXCHANGE_MODES, p, 0); + + /* Skip extension length (2 bytes) and + * ke_modes length (1 byte) for now. + */ + p += 5; + + if (mbedtls_ssl_conf_tls13_is_psk_ephemeral_enabled(ssl)) { + *p++ = MBEDTLS_SSL_TLS1_3_PSK_MODE_ECDHE; + ke_modes_len++; + + MBEDTLS_SSL_DEBUG_MSG(4, ("Adding PSK-ECDHE key exchange mode")); + } + + if (mbedtls_ssl_conf_tls13_is_psk_enabled(ssl)) { + *p++ = MBEDTLS_SSL_TLS1_3_PSK_MODE_PURE; + ke_modes_len++; + + MBEDTLS_SSL_DEBUG_MSG(4, ("Adding pure PSK key exchange mode")); + } + + /* Now write the extension and ke_modes length */ + MBEDTLS_PUT_UINT16_BE(ke_modes_len + 1, buf, 2); + buf[4] = ke_modes_len; + + *out_len = p - buf; + + mbedtls_ssl_tls13_set_hs_sent_ext_mask( + ssl, MBEDTLS_TLS_EXT_PSK_KEY_EXCHANGE_MODES); + + return 0; +} + +static psa_algorithm_t ssl_tls13_get_ciphersuite_hash_alg(int ciphersuite) +{ + const mbedtls_ssl_ciphersuite_t *ciphersuite_info = NULL; + ciphersuite_info = mbedtls_ssl_ciphersuite_from_id(ciphersuite); + + if (ciphersuite_info != NULL) { + return mbedtls_md_psa_alg_from_type((mbedtls_md_type_t) ciphersuite_info->mac); + } + + return PSA_ALG_NONE; +} + +#if defined(MBEDTLS_SSL_SESSION_TICKETS) +static int ssl_tls13_has_configured_ticket(mbedtls_ssl_context *ssl) +{ + mbedtls_ssl_session *session = ssl->session_negotiate; + return ssl->handshake->resume && + session != NULL && session->ticket != NULL && + mbedtls_ssl_conf_tls13_is_kex_mode_enabled( + ssl, mbedtls_ssl_tls13_session_get_ticket_flags( + session, MBEDTLS_SSL_TLS1_3_KEY_EXCHANGE_MODE_PSK_ALL)); +} + +#if defined(MBEDTLS_SSL_EARLY_DATA) +static int ssl_tls13_early_data_has_valid_ticket(mbedtls_ssl_context *ssl) +{ + mbedtls_ssl_session *session = ssl->session_negotiate; + return ssl->handshake->resume && + session->tls_version == MBEDTLS_SSL_VERSION_TLS1_3 && + mbedtls_ssl_tls13_session_ticket_allow_early_data(session) && + mbedtls_ssl_tls13_cipher_suite_is_offered(ssl, session->ciphersuite); +} +#endif + +MBEDTLS_CHECK_RETURN_CRITICAL +static int ssl_tls13_ticket_get_identity(mbedtls_ssl_context *ssl, + psa_algorithm_t *hash_alg, + const unsigned char **identity, + size_t *identity_len) +{ + mbedtls_ssl_session *session = ssl->session_negotiate; + + if (!ssl_tls13_has_configured_ticket(ssl)) { + return -1; + } + + *hash_alg = ssl_tls13_get_ciphersuite_hash_alg(session->ciphersuite); + *identity = session->ticket; + *identity_len = session->ticket_len; + return 0; +} + +MBEDTLS_CHECK_RETURN_CRITICAL +static int ssl_tls13_ticket_get_psk(mbedtls_ssl_context *ssl, + psa_algorithm_t *hash_alg, + const unsigned char **psk, + size_t *psk_len) +{ + + mbedtls_ssl_session *session = ssl->session_negotiate; + + if (!ssl_tls13_has_configured_ticket(ssl)) { + return -1; + } + + *hash_alg = ssl_tls13_get_ciphersuite_hash_alg(session->ciphersuite); + *psk = session->resumption_key; + *psk_len = session->resumption_key_len; + + return 0; +} +#endif /* MBEDTLS_SSL_SESSION_TICKETS */ + +MBEDTLS_CHECK_RETURN_CRITICAL +static int ssl_tls13_psk_get_identity(mbedtls_ssl_context *ssl, + psa_algorithm_t *hash_alg, + const unsigned char **identity, + size_t *identity_len) +{ + + if (!mbedtls_ssl_conf_has_static_psk(ssl->conf)) { + return -1; + } + + *hash_alg = PSA_ALG_SHA_256; + *identity = ssl->conf->psk_identity; + *identity_len = ssl->conf->psk_identity_len; + return 0; +} + +MBEDTLS_CHECK_RETURN_CRITICAL +static int ssl_tls13_psk_get_psk(mbedtls_ssl_context *ssl, + psa_algorithm_t *hash_alg, + const unsigned char **psk, + size_t *psk_len) +{ + + if (!mbedtls_ssl_conf_has_static_psk(ssl->conf)) { + return -1; + } + + *hash_alg = PSA_ALG_SHA_256; + *psk = ssl->conf->psk; + *psk_len = ssl->conf->psk_len; + return 0; +} + +static int ssl_tls13_get_configured_psk_count(mbedtls_ssl_context *ssl) +{ + int configured_psk_count = 0; +#if defined(MBEDTLS_SSL_SESSION_TICKETS) + if (ssl_tls13_has_configured_ticket(ssl)) { + MBEDTLS_SSL_DEBUG_MSG(3, ("Ticket is configured")); + configured_psk_count++; + } +#endif + if (mbedtls_ssl_conf_has_static_psk(ssl->conf)) { + MBEDTLS_SSL_DEBUG_MSG(3, ("PSK is configured")); + configured_psk_count++; + } + return configured_psk_count; +} + +MBEDTLS_CHECK_RETURN_CRITICAL +static int ssl_tls13_write_identity(mbedtls_ssl_context *ssl, + unsigned char *buf, + unsigned char *end, + const unsigned char *identity, + size_t identity_len, + uint32_t obfuscated_ticket_age, + size_t *out_len) +{ + ((void) ssl); + *out_len = 0; + + /* + * - identity_len (2 bytes) + * - identity (psk_identity_len bytes) + * - obfuscated_ticket_age (4 bytes) + */ + MBEDTLS_SSL_CHK_BUF_PTR(buf, end, 6 + identity_len); + + MBEDTLS_PUT_UINT16_BE(identity_len, buf, 0); + memcpy(buf + 2, identity, identity_len); + MBEDTLS_PUT_UINT32_BE(obfuscated_ticket_age, buf, 2 + identity_len); + + MBEDTLS_SSL_DEBUG_BUF(4, "write identity", buf, 6 + identity_len); + + *out_len = 6 + identity_len; + + return 0; +} + +MBEDTLS_CHECK_RETURN_CRITICAL +static int ssl_tls13_write_binder(mbedtls_ssl_context *ssl, + unsigned char *buf, + unsigned char *end, + int psk_type, + psa_algorithm_t hash_alg, + const unsigned char *psk, + size_t psk_len, + size_t *out_len) +{ + int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED; + unsigned char binder_len; + unsigned char transcript[MBEDTLS_TLS1_3_MD_MAX_SIZE]; + size_t transcript_len = 0; + + *out_len = 0; + + binder_len = PSA_HASH_LENGTH(hash_alg); + + /* + * - binder_len (1 bytes) + * - binder (binder_len bytes) + */ + MBEDTLS_SSL_CHK_BUF_PTR(buf, end, 1 + binder_len); + + buf[0] = binder_len; + + /* Get current state of handshake transcript. */ + ret = mbedtls_ssl_get_handshake_transcript( + ssl, mbedtls_md_type_from_psa_alg(hash_alg), + transcript, sizeof(transcript), &transcript_len); + if (ret != 0) { + return ret; + } + + ret = mbedtls_ssl_tls13_create_psk_binder(ssl, hash_alg, + psk, psk_len, psk_type, + transcript, buf + 1); + if (ret != 0) { + MBEDTLS_SSL_DEBUG_RET(1, "mbedtls_ssl_tls13_create_psk_binder", ret); + return ret; + } + MBEDTLS_SSL_DEBUG_BUF(4, "write binder", buf, 1 + binder_len); + + *out_len = 1 + binder_len; + + return 0; +} + +/* + * mbedtls_ssl_tls13_write_identities_of_pre_shared_key_ext() structure: + * + * struct { + * opaque identity<1..2^16-1>; + * uint32 obfuscated_ticket_age; + * } PskIdentity; + * + * opaque PskBinderEntry<32..255>; + * + * struct { + * PskIdentity identities<7..2^16-1>; + * PskBinderEntry binders<33..2^16-1>; + * } OfferedPsks; + * + * struct { + * select (Handshake.msg_type) { + * case client_hello: OfferedPsks; + * ... + * }; + * } PreSharedKeyExtension; + * + */ +int mbedtls_ssl_tls13_write_identities_of_pre_shared_key_ext( + mbedtls_ssl_context *ssl, unsigned char *buf, unsigned char *end, + size_t *out_len, size_t *binders_len) +{ + int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED; + int configured_psk_count = 0; + unsigned char *p = buf; + psa_algorithm_t hash_alg = PSA_ALG_NONE; + const unsigned char *identity; + size_t identity_len; + size_t l_binders_len = 0; + size_t output_len; + + *out_len = 0; + *binders_len = 0; + + /* Check if we have any PSKs to offer. If no, skip pre_shared_key */ + configured_psk_count = ssl_tls13_get_configured_psk_count(ssl); + if (configured_psk_count == 0) { + MBEDTLS_SSL_DEBUG_MSG(3, ("skip pre_shared_key extensions")); + return 0; + } + + MBEDTLS_SSL_DEBUG_MSG(4, ("Pre-configured PSK number = %d", + configured_psk_count)); + + /* Check if we have space to write the extension, binders included. + * - extension_type (2 bytes) + * - extension_data_len (2 bytes) + * - identities_len (2 bytes) + */ + MBEDTLS_SSL_CHK_BUF_PTR(p, end, 6); + p += 6; + +#if defined(MBEDTLS_SSL_SESSION_TICKETS) + if (ssl_tls13_ticket_get_identity( + ssl, &hash_alg, &identity, &identity_len) == 0) { +#if defined(MBEDTLS_HAVE_TIME) + mbedtls_ms_time_t now = mbedtls_ms_time(); + mbedtls_ssl_session *session = ssl->session_negotiate; + /* The ticket age has been checked to be smaller than the + * `ticket_lifetime` in ssl_prepare_client_hello() which is smaller than + * 7 days (enforced in ssl_tls13_parse_new_session_ticket()) . Thus the + * cast to `uint32_t` of the ticket age is safe. */ + uint32_t obfuscated_ticket_age = + (uint32_t) (now - session->ticket_reception_time); + obfuscated_ticket_age += session->ticket_age_add; + + ret = ssl_tls13_write_identity(ssl, p, end, + identity, identity_len, + obfuscated_ticket_age, + &output_len); +#else + ret = ssl_tls13_write_identity(ssl, p, end, identity, identity_len, + 0, &output_len); +#endif /* MBEDTLS_HAVE_TIME */ + if (ret != 0) { + return ret; + } + + p += output_len; + l_binders_len += 1 + PSA_HASH_LENGTH(hash_alg); + } +#endif /* MBEDTLS_SSL_SESSION_TICKETS */ + + if (ssl_tls13_psk_get_identity( + ssl, &hash_alg, &identity, &identity_len) == 0) { + + ret = ssl_tls13_write_identity(ssl, p, end, identity, identity_len, 0, + &output_len); + if (ret != 0) { + return ret; + } + + p += output_len; + l_binders_len += 1 + PSA_HASH_LENGTH(hash_alg); + } + + MBEDTLS_SSL_DEBUG_MSG(3, + ("client hello, adding pre_shared_key extension, " + "omitting PSK binder list")); + + /* Take into account the two bytes for the length of the binders. */ + l_binders_len += 2; + /* Check if there is enough space for binders */ + MBEDTLS_SSL_CHK_BUF_PTR(p, end, l_binders_len); + + /* + * - extension_type (2 bytes) + * - extension_data_len (2 bytes) + * - identities_len (2 bytes) + */ + MBEDTLS_PUT_UINT16_BE(MBEDTLS_TLS_EXT_PRE_SHARED_KEY, buf, 0); + MBEDTLS_PUT_UINT16_BE(p - buf - 4 + l_binders_len, buf, 2); + MBEDTLS_PUT_UINT16_BE(p - buf - 6, buf, 4); + + *out_len = (p - buf) + l_binders_len; + *binders_len = l_binders_len; + + MBEDTLS_SSL_DEBUG_BUF(3, "pre_shared_key identities", buf, p - buf); + + return 0; +} + +int mbedtls_ssl_tls13_write_binders_of_pre_shared_key_ext( + mbedtls_ssl_context *ssl, unsigned char *buf, unsigned char *end) +{ + int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED; + unsigned char *p = buf; + psa_algorithm_t hash_alg = PSA_ALG_NONE; + const unsigned char *psk; + size_t psk_len; + size_t output_len; + + /* Check if we have space to write binders_len. + * - binders_len (2 bytes) + */ + MBEDTLS_SSL_CHK_BUF_PTR(p, end, 2); + p += 2; + +#if defined(MBEDTLS_SSL_SESSION_TICKETS) + if (ssl_tls13_ticket_get_psk(ssl, &hash_alg, &psk, &psk_len) == 0) { + + ret = ssl_tls13_write_binder(ssl, p, end, + MBEDTLS_SSL_TLS1_3_PSK_RESUMPTION, + hash_alg, psk, psk_len, + &output_len); + if (ret != 0) { + return ret; + } + p += output_len; + } +#endif /* MBEDTLS_SSL_SESSION_TICKETS */ + + if (ssl_tls13_psk_get_psk(ssl, &hash_alg, &psk, &psk_len) == 0) { + + ret = ssl_tls13_write_binder(ssl, p, end, + MBEDTLS_SSL_TLS1_3_PSK_EXTERNAL, + hash_alg, psk, psk_len, + &output_len); + if (ret != 0) { + return ret; + } + p += output_len; + } + + MBEDTLS_SSL_DEBUG_MSG(3, ("client hello, adding PSK binder list.")); + + /* + * - binders_len (2 bytes) + */ + MBEDTLS_PUT_UINT16_BE(p - buf - 2, buf, 0); + + MBEDTLS_SSL_DEBUG_BUF(3, "pre_shared_key binders", buf, p - buf); + + mbedtls_ssl_tls13_set_hs_sent_ext_mask( + ssl, MBEDTLS_TLS_EXT_PRE_SHARED_KEY); + + return 0; +} + +/* + * struct { + * opaque identity<1..2^16-1>; + * uint32 obfuscated_ticket_age; + * } PskIdentity; + * + * opaque PskBinderEntry<32..255>; + * + * struct { + * + * select (Handshake.msg_type) { + * ... + * case server_hello: uint16 selected_identity; + * }; + * + * } PreSharedKeyExtension; + * + */ +MBEDTLS_CHECK_RETURN_CRITICAL +static int ssl_tls13_parse_server_pre_shared_key_ext(mbedtls_ssl_context *ssl, + const unsigned char *buf, + const unsigned char *end) +{ + int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED; + int selected_identity; + const unsigned char *psk; + size_t psk_len; + psa_algorithm_t hash_alg; + + MBEDTLS_SSL_CHK_BUF_READ_PTR(buf, end, 2); + selected_identity = MBEDTLS_GET_UINT16_BE(buf, 0); + ssl->handshake->selected_identity = (uint16_t) selected_identity; + + MBEDTLS_SSL_DEBUG_MSG(3, ("selected_identity = %d", selected_identity)); + + if (selected_identity >= ssl_tls13_get_configured_psk_count(ssl)) { + MBEDTLS_SSL_DEBUG_MSG(1, ("Invalid PSK identity.")); + + MBEDTLS_SSL_PEND_FATAL_ALERT(MBEDTLS_SSL_ALERT_MSG_ILLEGAL_PARAMETER, + MBEDTLS_ERR_SSL_ILLEGAL_PARAMETER); + return MBEDTLS_ERR_SSL_ILLEGAL_PARAMETER; + } + +#if defined(MBEDTLS_SSL_SESSION_TICKETS) + if (selected_identity == 0 && ssl_tls13_has_configured_ticket(ssl)) { + ret = ssl_tls13_ticket_get_psk(ssl, &hash_alg, &psk, &psk_len); + } else +#endif + if (mbedtls_ssl_conf_has_static_psk(ssl->conf)) { + ret = ssl_tls13_psk_get_psk(ssl, &hash_alg, &psk, &psk_len); + } else { + MBEDTLS_SSL_DEBUG_MSG(1, ("should never happen")); + return MBEDTLS_ERR_SSL_INTERNAL_ERROR; + } + if (ret != 0) { + return ret; + } + + if (mbedtls_md_psa_alg_from_type((mbedtls_md_type_t) ssl->handshake->ciphersuite_info->mac) + != hash_alg) { + MBEDTLS_SSL_DEBUG_MSG( + 1, ("Invalid ciphersuite for external psk.")); + + MBEDTLS_SSL_PEND_FATAL_ALERT(MBEDTLS_SSL_ALERT_MSG_ILLEGAL_PARAMETER, + MBEDTLS_ERR_SSL_ILLEGAL_PARAMETER); + return MBEDTLS_ERR_SSL_ILLEGAL_PARAMETER; + } + + ret = mbedtls_ssl_set_hs_psk(ssl, psk, psk_len); + if (ret != 0) { + MBEDTLS_SSL_DEBUG_RET(1, "mbedtls_ssl_set_hs_psk", ret); + return ret; + } + + return 0; +} +#endif /* MBEDTLS_SSL_TLS1_3_KEY_EXCHANGE_MODE_SOME_PSK_ENABLED */ + +int mbedtls_ssl_tls13_write_client_hello_exts(mbedtls_ssl_context *ssl, + unsigned char *buf, + unsigned char *end, + size_t *out_len) +{ + int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED; + unsigned char *p = buf; + size_t ext_len; + + *out_len = 0; + + /* Write supported_versions extension + * + * Supported Versions Extension is mandatory with TLS 1.3. + */ + ret = ssl_tls13_write_supported_versions_ext(ssl, p, end, &ext_len); + if (ret != 0) { + return ret; + } + p += ext_len; + + /* Echo the cookie if the server provided one in its preceding + * HelloRetryRequest message. + */ + ret = ssl_tls13_write_cookie_ext(ssl, p, end, &ext_len); + if (ret != 0) { + return ret; + } + p += ext_len; + +#if defined(MBEDTLS_SSL_RECORD_SIZE_LIMIT) + ret = mbedtls_ssl_tls13_write_record_size_limit_ext( + ssl, p, end, &ext_len); + if (ret != 0) { + return ret; + } + p += ext_len; +#endif + +#if defined(MBEDTLS_SSL_TLS1_3_KEY_EXCHANGE_MODE_SOME_EPHEMERAL_ENABLED) + if (mbedtls_ssl_conf_tls13_is_some_ephemeral_enabled(ssl)) { + ret = ssl_tls13_write_key_share_ext(ssl, p, end, &ext_len); + if (ret != 0) { + return ret; + } + p += ext_len; + } +#endif + +#if defined(MBEDTLS_SSL_EARLY_DATA) + /* In the first ClientHello, write the early data indication extension if + * necessary and update the early data state. + * If an HRR has been received and thus we are currently writing the + * second ClientHello, the second ClientHello must not contain an early + * data extension and the early data state must stay as it is: + * MBEDTLS_SSL_EARLY_DATA_STATE_NO_IND_SENT or + * MBEDTLS_SSL_EARLY_DATA_STATE_REJECTED. + */ + if (!ssl->handshake->hello_retry_request_flag) { + if (mbedtls_ssl_conf_tls13_is_some_psk_enabled(ssl) && + ssl_tls13_early_data_has_valid_ticket(ssl) && + ssl->conf->early_data_enabled == MBEDTLS_SSL_EARLY_DATA_ENABLED) { + ret = mbedtls_ssl_tls13_write_early_data_ext( + ssl, 0, p, end, &ext_len); + if (ret != 0) { + return ret; + } + p += ext_len; + + ssl->early_data_state = MBEDTLS_SSL_EARLY_DATA_STATE_IND_SENT; + } else { + ssl->early_data_state = MBEDTLS_SSL_EARLY_DATA_STATE_NO_IND_SENT; + } + } +#endif /* MBEDTLS_SSL_EARLY_DATA */ + +#if defined(MBEDTLS_SSL_TLS1_3_KEY_EXCHANGE_MODE_SOME_PSK_ENABLED) + /* For PSK-based key exchange we need the pre_shared_key extension + * and the psk_key_exchange_modes extension. + * + * The pre_shared_key extension MUST be the last extension in the + * ClientHello. Servers MUST check that it is the last extension and + * otherwise fail the handshake with an "illegal_parameter" alert. + * + * Add the psk_key_exchange_modes extension. + */ + ret = ssl_tls13_write_psk_key_exchange_modes_ext(ssl, p, end, &ext_len); + if (ret != 0) { + return ret; + } + p += ext_len; +#endif + + *out_len = p - buf; + + return 0; +} + +int mbedtls_ssl_tls13_finalize_client_hello(mbedtls_ssl_context *ssl) +{ + ((void) ssl); + +#if defined(MBEDTLS_SSL_EARLY_DATA) + int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED; + psa_algorithm_t hash_alg = PSA_ALG_NONE; + const unsigned char *psk; + size_t psk_len; + const mbedtls_ssl_ciphersuite_t *ciphersuite_info; + + if (ssl->early_data_state == MBEDTLS_SSL_EARLY_DATA_STATE_IND_SENT) { + MBEDTLS_SSL_DEBUG_MSG( + 1, ("Set hs psk for early data when writing the first psk")); + + ret = ssl_tls13_ticket_get_psk(ssl, &hash_alg, &psk, &psk_len); + if (ret != 0) { + MBEDTLS_SSL_DEBUG_RET( + 1, "ssl_tls13_ticket_get_psk", ret); + return ret; + } + + ret = mbedtls_ssl_set_hs_psk(ssl, psk, psk_len); + if (ret != 0) { + MBEDTLS_SSL_DEBUG_RET(1, "mbedtls_ssl_set_hs_psk", ret); + return ret; + } + + /* + * Early data are going to be encrypted using the ciphersuite + * associated with the pre-shared key used for the handshake. + * Note that if the server rejects early data, the handshake + * based on the pre-shared key may complete successfully + * with a selected ciphersuite different from the ciphersuite + * associated with the pre-shared key. Only the hashes of the + * two ciphersuites have to be the same. In that case, the + * encrypted handshake data and application data are + * encrypted using a different ciphersuite than the one used for + * the rejected early data. + */ + ciphersuite_info = mbedtls_ssl_ciphersuite_from_id( + ssl->session_negotiate->ciphersuite); + ssl->handshake->ciphersuite_info = ciphersuite_info; + + /* Enable psk and psk_ephemeral to make stage early happy */ + ssl->handshake->key_exchange_mode = + MBEDTLS_SSL_TLS1_3_KEY_EXCHANGE_MODE_PSK_ALL; + + /* Start the TLS 1.3 key schedule: + * Set the PSK and derive early secret. + */ + ret = mbedtls_ssl_tls13_key_schedule_stage_early(ssl); + if (ret != 0) { + MBEDTLS_SSL_DEBUG_RET( + 1, "mbedtls_ssl_tls13_key_schedule_stage_early", ret); + return ret; + } + + /* Derive early data key material */ + ret = mbedtls_ssl_tls13_compute_early_transform(ssl); + if (ret != 0) { + MBEDTLS_SSL_DEBUG_RET( + 1, "mbedtls_ssl_tls13_compute_early_transform", ret); + return ret; + } + +#if defined(MBEDTLS_SSL_TLS1_3_COMPATIBILITY_MODE) + mbedtls_ssl_handshake_set_state( + ssl, MBEDTLS_SSL_CLIENT_CCS_AFTER_CLIENT_HELLO); +#else + MBEDTLS_SSL_DEBUG_MSG( + 1, ("Switch to early data keys for outbound traffic")); + mbedtls_ssl_set_outbound_transform( + ssl, ssl->handshake->transform_earlydata); + ssl->early_data_state = MBEDTLS_SSL_EARLY_DATA_STATE_CAN_WRITE; +#endif + } +#endif /* MBEDTLS_SSL_EARLY_DATA */ + return 0; +} +/* + * Functions for parsing and processing Server Hello + */ + +/** + * \brief Detect if the ServerHello contains a supported_versions extension + * or not. + * + * \param[in] ssl SSL context + * \param[in] buf Buffer containing the ServerHello message + * \param[in] end End of the buffer containing the ServerHello message + * + * \return 0 if the ServerHello does not contain a supported_versions extension + * \return 1 if the ServerHello contains a supported_versions extension + * \return A negative value if an error occurred while parsing the ServerHello. + */ +MBEDTLS_CHECK_RETURN_CRITICAL +static int ssl_tls13_is_supported_versions_ext_present( + mbedtls_ssl_context *ssl, + const unsigned char *buf, + const unsigned char *end) +{ + const unsigned char *p = buf; + size_t legacy_session_id_echo_len; + const unsigned char *supported_versions_data; + const unsigned char *supported_versions_data_end; + + /* + * Check there is enough data to access the legacy_session_id_echo vector + * length: + * - legacy_version 2 bytes + * - random MBEDTLS_SERVER_HELLO_RANDOM_LEN bytes + * - legacy_session_id_echo length 1 byte + */ + MBEDTLS_SSL_CHK_BUF_READ_PTR(p, end, MBEDTLS_SERVER_HELLO_RANDOM_LEN + 3); + p += MBEDTLS_SERVER_HELLO_RANDOM_LEN + 2; + legacy_session_id_echo_len = *p; + + /* + * Jump to the extensions, jumping over: + * - legacy_session_id_echo (legacy_session_id_echo_len + 1) bytes + * - cipher_suite 2 bytes + * - legacy_compression_method 1 byte + */ + MBEDTLS_SSL_CHK_BUF_READ_PTR(p, end, legacy_session_id_echo_len + 4); + p += legacy_session_id_echo_len + 4; + + return mbedtls_ssl_tls13_is_supported_versions_ext_present_in_exts( + ssl, p, end, + &supported_versions_data, &supported_versions_data_end); +} + +/* Returns a negative value on failure, and otherwise + * - 1 if the last eight bytes of the ServerHello random bytes indicate that + * the server is TLS 1.3 capable but negotiating TLS 1.2 or below. + * - 0 otherwise + */ +MBEDTLS_CHECK_RETURN_CRITICAL +static int ssl_tls13_is_downgrade_negotiation(mbedtls_ssl_context *ssl, + const unsigned char *buf, + const unsigned char *end) +{ + /* First seven bytes of the magic downgrade strings, see RFC 8446 4.1.3 */ + static const unsigned char magic_downgrade_string[] = + { 0x44, 0x4F, 0x57, 0x4E, 0x47, 0x52, 0x44 }; + const unsigned char *last_eight_bytes_of_random; + unsigned char last_byte_of_random; + + MBEDTLS_SSL_CHK_BUF_READ_PTR(buf, end, MBEDTLS_SERVER_HELLO_RANDOM_LEN + 2); + last_eight_bytes_of_random = buf + 2 + MBEDTLS_SERVER_HELLO_RANDOM_LEN - 8; + + if (memcmp(last_eight_bytes_of_random, + magic_downgrade_string, + sizeof(magic_downgrade_string)) == 0) { + last_byte_of_random = last_eight_bytes_of_random[7]; + return last_byte_of_random == 0 || + last_byte_of_random == 1; + } + + return 0; +} + +/* Returns a negative value on failure, and otherwise + * - SSL_SERVER_HELLO or + * - SSL_SERVER_HELLO_HRR + * to indicate which message is expected and to be parsed next. + */ +#define SSL_SERVER_HELLO 0 +#define SSL_SERVER_HELLO_HRR 1 +MBEDTLS_CHECK_RETURN_CRITICAL +static int ssl_server_hello_is_hrr(mbedtls_ssl_context *ssl, + const unsigned char *buf, + const unsigned char *end) +{ + + /* Check whether this message is a HelloRetryRequest ( HRR ) message. + * + * Server Hello and HRR are only distinguished by Random set to the + * special value of the SHA-256 of "HelloRetryRequest". + * + * struct { + * ProtocolVersion legacy_version = 0x0303; + * Random random; + * opaque legacy_session_id_echo<0..32>; + * CipherSuite cipher_suite; + * uint8 legacy_compression_method = 0; + * Extension extensions<6..2^16-1>; + * } ServerHello; + * + */ + MBEDTLS_SSL_CHK_BUF_READ_PTR( + buf, end, 2 + sizeof(mbedtls_ssl_tls13_hello_retry_request_magic)); + + if (memcmp(buf + 2, mbedtls_ssl_tls13_hello_retry_request_magic, + sizeof(mbedtls_ssl_tls13_hello_retry_request_magic)) == 0) { + return SSL_SERVER_HELLO_HRR; + } + + return SSL_SERVER_HELLO; +} + +/* + * Returns a negative value on failure, and otherwise + * - SSL_SERVER_HELLO or + * - SSL_SERVER_HELLO_HRR or + * - SSL_SERVER_HELLO_TLS1_2 + */ +#define SSL_SERVER_HELLO_TLS1_2 2 +MBEDTLS_CHECK_RETURN_CRITICAL +static int ssl_tls13_preprocess_server_hello(mbedtls_ssl_context *ssl, + const unsigned char *buf, + const unsigned char *end) +{ + int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED; + mbedtls_ssl_handshake_params *handshake = ssl->handshake; + + MBEDTLS_SSL_PROC_CHK_NEG(ssl_tls13_is_supported_versions_ext_present( + ssl, buf, end)); + + if (ret == 0) { + MBEDTLS_SSL_PROC_CHK_NEG( + ssl_tls13_is_downgrade_negotiation(ssl, buf, end)); + + /* If the server is negotiating TLS 1.2 or below and: + * . we did not propose TLS 1.2 or + * . the server responded it is TLS 1.3 capable but negotiating a lower + * version of the protocol and thus we are under downgrade attack + * abort the handshake with an "illegal parameter" alert. + */ + if (handshake->min_tls_version > MBEDTLS_SSL_VERSION_TLS1_2 || ret) { + MBEDTLS_SSL_PEND_FATAL_ALERT(MBEDTLS_SSL_ALERT_MSG_ILLEGAL_PARAMETER, + MBEDTLS_ERR_SSL_ILLEGAL_PARAMETER); + return MBEDTLS_ERR_SSL_ILLEGAL_PARAMETER; + } + + /* + * Version 1.2 of the protocol has been negotiated, set the + * ssl->keep_current_message flag for the ServerHello to be kept and + * parsed as a TLS 1.2 ServerHello. We also change ssl->tls_version to + * MBEDTLS_SSL_VERSION_TLS1_2 thus from now on mbedtls_ssl_handshake_step() + * will dispatch to the TLS 1.2 state machine. + */ + ssl->keep_current_message = 1; + ssl->tls_version = MBEDTLS_SSL_VERSION_TLS1_2; + MBEDTLS_SSL_PROC_CHK(mbedtls_ssl_add_hs_msg_to_checksum( + ssl, MBEDTLS_SSL_HS_SERVER_HELLO, + buf, (size_t) (end - buf))); + + if (mbedtls_ssl_conf_tls13_is_some_ephemeral_enabled(ssl)) { + ret = ssl_tls13_reset_key_share(ssl); + if (ret != 0) { + return ret; + } + } + + return SSL_SERVER_HELLO_TLS1_2; + } + + ssl->session_negotiate->tls_version = ssl->tls_version; + ssl->session_negotiate->endpoint = ssl->conf->endpoint; + + handshake->received_extensions = MBEDTLS_SSL_EXT_MASK_NONE; + + ret = ssl_server_hello_is_hrr(ssl, buf, end); + switch (ret) { + case SSL_SERVER_HELLO: + MBEDTLS_SSL_DEBUG_MSG(2, ("received ServerHello message")); + break; + case SSL_SERVER_HELLO_HRR: + MBEDTLS_SSL_DEBUG_MSG(2, ("received HelloRetryRequest message")); + /* If a client receives a second HelloRetryRequest in the same + * connection (i.e., where the ClientHello was itself in response + * to a HelloRetryRequest), it MUST abort the handshake with an + * "unexpected_message" alert. + */ + if (handshake->hello_retry_request_flag) { + MBEDTLS_SSL_DEBUG_MSG(1, ("Multiple HRRs received")); + MBEDTLS_SSL_PEND_FATAL_ALERT( + MBEDTLS_SSL_ALERT_MSG_UNEXPECTED_MESSAGE, + MBEDTLS_ERR_SSL_UNEXPECTED_MESSAGE); + return MBEDTLS_ERR_SSL_UNEXPECTED_MESSAGE; + } + /* + * Clients must abort the handshake with an "illegal_parameter" + * alert if the HelloRetryRequest would not result in any change + * in the ClientHello. + * In a PSK only key exchange that what we expect. + */ + if (!mbedtls_ssl_conf_tls13_is_some_ephemeral_enabled(ssl)) { + MBEDTLS_SSL_DEBUG_MSG(1, + ("Unexpected HRR in pure PSK key exchange.")); + MBEDTLS_SSL_PEND_FATAL_ALERT( + MBEDTLS_SSL_ALERT_MSG_ILLEGAL_PARAMETER, + MBEDTLS_ERR_SSL_ILLEGAL_PARAMETER); + return MBEDTLS_ERR_SSL_ILLEGAL_PARAMETER; + } + + handshake->hello_retry_request_flag = 1; + + break; + } + +cleanup: + + return ret; +} + +MBEDTLS_CHECK_RETURN_CRITICAL +static int ssl_tls13_check_server_hello_session_id_echo(mbedtls_ssl_context *ssl, + const unsigned char **buf, + const unsigned char *end) +{ + const unsigned char *p = *buf; + size_t legacy_session_id_echo_len; + + MBEDTLS_SSL_CHK_BUF_READ_PTR(p, end, 1); + legacy_session_id_echo_len = *p++; + + MBEDTLS_SSL_CHK_BUF_READ_PTR(p, end, legacy_session_id_echo_len); + + /* legacy_session_id_echo */ + if (ssl->session_negotiate->id_len != legacy_session_id_echo_len || + memcmp(ssl->session_negotiate->id, p, legacy_session_id_echo_len) != 0) { + MBEDTLS_SSL_DEBUG_BUF(3, "Expected Session ID", + ssl->session_negotiate->id, + ssl->session_negotiate->id_len); + MBEDTLS_SSL_DEBUG_BUF(3, "Received Session ID", p, + legacy_session_id_echo_len); + + MBEDTLS_SSL_PEND_FATAL_ALERT(MBEDTLS_SSL_ALERT_MSG_ILLEGAL_PARAMETER, + MBEDTLS_ERR_SSL_ILLEGAL_PARAMETER); + + return MBEDTLS_ERR_SSL_ILLEGAL_PARAMETER; + } + + p += legacy_session_id_echo_len; + *buf = p; + + MBEDTLS_SSL_DEBUG_BUF(3, "Session ID", ssl->session_negotiate->id, + ssl->session_negotiate->id_len); + return 0; +} + +/* Parse ServerHello message and configure context + * + * struct { + * ProtocolVersion legacy_version = 0x0303; // TLS 1.2 + * Random random; + * opaque legacy_session_id_echo<0..32>; + * CipherSuite cipher_suite; + * uint8 legacy_compression_method = 0; + * Extension extensions<6..2^16-1>; + * } ServerHello; + */ +MBEDTLS_CHECK_RETURN_CRITICAL +static int ssl_tls13_parse_server_hello(mbedtls_ssl_context *ssl, + const unsigned char *buf, + const unsigned char *end, + int is_hrr) +{ + int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED; + const unsigned char *p = buf; + mbedtls_ssl_handshake_params *handshake = ssl->handshake; + size_t extensions_len; + const unsigned char *extensions_end; + uint16_t cipher_suite; + const mbedtls_ssl_ciphersuite_t *ciphersuite_info; + int fatal_alert = 0; + uint32_t allowed_extensions_mask; + int hs_msg_type = is_hrr ? MBEDTLS_SSL_TLS1_3_HS_HELLO_RETRY_REQUEST : + MBEDTLS_SSL_HS_SERVER_HELLO; + + /* + * Check there is space for minimal fields + * + * - legacy_version ( 2 bytes) + * - random (MBEDTLS_SERVER_HELLO_RANDOM_LEN bytes) + * - legacy_session_id_echo ( 1 byte ), minimum size + * - cipher_suite ( 2 bytes) + * - legacy_compression_method ( 1 byte ) + */ + MBEDTLS_SSL_CHK_BUF_READ_PTR(p, end, MBEDTLS_SERVER_HELLO_RANDOM_LEN + 6); + + MBEDTLS_SSL_DEBUG_BUF(4, "server hello", p, end - p); + MBEDTLS_SSL_DEBUG_BUF(3, "server hello, version", p, 2); + + /* ... + * ProtocolVersion legacy_version = 0x0303; // TLS 1.2 + * ... + * with ProtocolVersion defined as: + * uint16 ProtocolVersion; + */ + if (mbedtls_ssl_read_version(p, ssl->conf->transport) != + MBEDTLS_SSL_VERSION_TLS1_2) { + MBEDTLS_SSL_DEBUG_MSG(1, ("Unsupported version of TLS.")); + MBEDTLS_SSL_PEND_FATAL_ALERT(MBEDTLS_SSL_ALERT_MSG_PROTOCOL_VERSION, + MBEDTLS_ERR_SSL_BAD_PROTOCOL_VERSION); + ret = MBEDTLS_ERR_SSL_BAD_PROTOCOL_VERSION; + goto cleanup; + } + p += 2; + + /* ... + * Random random; + * ... + * with Random defined as: + * opaque Random[MBEDTLS_SERVER_HELLO_RANDOM_LEN]; + */ + if (!is_hrr) { + memcpy(&handshake->randbytes[MBEDTLS_CLIENT_HELLO_RANDOM_LEN], p, + MBEDTLS_SERVER_HELLO_RANDOM_LEN); + MBEDTLS_SSL_DEBUG_BUF(3, "server hello, random bytes", + p, MBEDTLS_SERVER_HELLO_RANDOM_LEN); + } + p += MBEDTLS_SERVER_HELLO_RANDOM_LEN; + + /* ... + * opaque legacy_session_id_echo<0..32>; + * ... + */ + if (ssl_tls13_check_server_hello_session_id_echo(ssl, &p, end) != 0) { + fatal_alert = MBEDTLS_SSL_ALERT_MSG_ILLEGAL_PARAMETER; + goto cleanup; + } + + /* ... + * CipherSuite cipher_suite; + * ... + * with CipherSuite defined as: + * uint8 CipherSuite[2]; + */ + MBEDTLS_SSL_CHK_BUF_READ_PTR(p, end, 2); + cipher_suite = MBEDTLS_GET_UINT16_BE(p, 0); + p += 2; + + + ciphersuite_info = mbedtls_ssl_ciphersuite_from_id(cipher_suite); + /* + * Check whether this ciphersuite is valid and offered. + */ + if ((mbedtls_ssl_validate_ciphersuite(ssl, ciphersuite_info, + ssl->tls_version, + ssl->tls_version) != 0) || + !mbedtls_ssl_tls13_cipher_suite_is_offered(ssl, cipher_suite)) { + fatal_alert = MBEDTLS_SSL_ALERT_MSG_ILLEGAL_PARAMETER; + } + /* + * If we received an HRR before and that the proposed selected + * ciphersuite in this server hello is not the same as the one + * proposed in the HRR, we abort the handshake and send an + * "illegal_parameter" alert. + */ + else if ((!is_hrr) && handshake->hello_retry_request_flag && + (cipher_suite != ssl->session_negotiate->ciphersuite)) { + fatal_alert = MBEDTLS_SSL_ALERT_MSG_ILLEGAL_PARAMETER; + } + + if (fatal_alert == MBEDTLS_SSL_ALERT_MSG_ILLEGAL_PARAMETER) { + MBEDTLS_SSL_DEBUG_MSG(1, ("invalid ciphersuite(%04x) parameter", + cipher_suite)); + goto cleanup; + } + + /* Configure ciphersuites */ + mbedtls_ssl_optimize_checksum(ssl, ciphersuite_info); + + handshake->ciphersuite_info = ciphersuite_info; + MBEDTLS_SSL_DEBUG_MSG(3, ("server hello, chosen ciphersuite: ( %04x ) - %s", + cipher_suite, ciphersuite_info->name)); + +#if defined(MBEDTLS_HAVE_TIME) + ssl->session_negotiate->start = mbedtls_time(NULL); +#endif /* MBEDTLS_HAVE_TIME */ + + /* ... + * uint8 legacy_compression_method = 0; + * ... + */ + MBEDTLS_SSL_CHK_BUF_READ_PTR(p, end, 1); + if (p[0] != MBEDTLS_SSL_COMPRESS_NULL) { + MBEDTLS_SSL_DEBUG_MSG(1, ("bad legacy compression method")); + fatal_alert = MBEDTLS_SSL_ALERT_MSG_ILLEGAL_PARAMETER; + goto cleanup; + } + p++; + + /* ... + * Extension extensions<6..2^16-1>; + * ... + * struct { + * ExtensionType extension_type; (2 bytes) + * opaque extension_data<0..2^16-1>; + * } Extension; + */ + MBEDTLS_SSL_CHK_BUF_READ_PTR(p, end, 2); + extensions_len = MBEDTLS_GET_UINT16_BE(p, 0); + p += 2; + + /* Check extensions do not go beyond the buffer of data. */ + MBEDTLS_SSL_CHK_BUF_READ_PTR(p, end, extensions_len); + extensions_end = p + extensions_len; + + MBEDTLS_SSL_DEBUG_BUF(3, "server hello extensions", p, extensions_len); + + handshake->received_extensions = MBEDTLS_SSL_EXT_MASK_NONE; + allowed_extensions_mask = is_hrr ? + MBEDTLS_SSL_TLS1_3_ALLOWED_EXTS_OF_HRR : + MBEDTLS_SSL_TLS1_3_ALLOWED_EXTS_OF_SH; + + while (p < extensions_end) { + unsigned int extension_type; + size_t extension_data_len; + const unsigned char *extension_data_end; + + MBEDTLS_SSL_CHK_BUF_READ_PTR(p, extensions_end, 4); + extension_type = MBEDTLS_GET_UINT16_BE(p, 0); + extension_data_len = MBEDTLS_GET_UINT16_BE(p, 2); + p += 4; + + MBEDTLS_SSL_CHK_BUF_READ_PTR(p, extensions_end, extension_data_len); + extension_data_end = p + extension_data_len; + + ret = mbedtls_ssl_tls13_check_received_extension( + ssl, hs_msg_type, extension_type, allowed_extensions_mask); + if (ret != 0) { + return ret; + } + + switch (extension_type) { + case MBEDTLS_TLS_EXT_COOKIE: + + ret = ssl_tls13_parse_cookie_ext(ssl, + p, extension_data_end); + if (ret != 0) { + MBEDTLS_SSL_DEBUG_RET(1, + "ssl_tls13_parse_cookie_ext", + ret); + goto cleanup; + } + break; + + case MBEDTLS_TLS_EXT_SUPPORTED_VERSIONS: + ret = ssl_tls13_parse_supported_versions_ext(ssl, + p, + extension_data_end); + if (ret != 0) { + goto cleanup; + } + break; + +#if defined(MBEDTLS_SSL_TLS1_3_KEY_EXCHANGE_MODE_SOME_PSK_ENABLED) + case MBEDTLS_TLS_EXT_PRE_SHARED_KEY: + MBEDTLS_SSL_DEBUG_MSG(3, ("found pre_shared_key extension")); + + if ((ret = ssl_tls13_parse_server_pre_shared_key_ext( + ssl, p, extension_data_end)) != 0) { + MBEDTLS_SSL_DEBUG_RET( + 1, ("ssl_tls13_parse_server_pre_shared_key_ext"), ret); + return ret; + } + break; +#endif + + case MBEDTLS_TLS_EXT_KEY_SHARE: + MBEDTLS_SSL_DEBUG_MSG(3, ("found key_shares extension")); + if (!mbedtls_ssl_conf_tls13_is_some_ephemeral_enabled(ssl)) { + fatal_alert = MBEDTLS_SSL_ALERT_MSG_UNSUPPORTED_EXT; + goto cleanup; + } + + if (is_hrr) { + ret = ssl_tls13_parse_hrr_key_share_ext(ssl, + p, extension_data_end); + } else { + ret = ssl_tls13_parse_key_share_ext(ssl, + p, extension_data_end); + } + if (ret != 0) { + MBEDTLS_SSL_DEBUG_RET(1, + "ssl_tls13_parse_key_share_ext", + ret); + goto cleanup; + } + break; + + default: + ret = MBEDTLS_ERR_SSL_INTERNAL_ERROR; + goto cleanup; + } + + p += extension_data_len; + } + + MBEDTLS_SSL_PRINT_EXTS(3, hs_msg_type, handshake->received_extensions); + +cleanup: + + if (fatal_alert == MBEDTLS_SSL_ALERT_MSG_UNSUPPORTED_EXT) { + MBEDTLS_SSL_PEND_FATAL_ALERT(MBEDTLS_SSL_ALERT_MSG_UNSUPPORTED_EXT, + MBEDTLS_ERR_SSL_UNSUPPORTED_EXTENSION); + ret = MBEDTLS_ERR_SSL_UNSUPPORTED_EXTENSION; + } else if (fatal_alert == MBEDTLS_SSL_ALERT_MSG_ILLEGAL_PARAMETER) { + MBEDTLS_SSL_PEND_FATAL_ALERT(MBEDTLS_SSL_ALERT_MSG_ILLEGAL_PARAMETER, + MBEDTLS_ERR_SSL_ILLEGAL_PARAMETER); + ret = MBEDTLS_ERR_SSL_ILLEGAL_PARAMETER; + } + return ret; +} + +#if defined(MBEDTLS_DEBUG_C) +static const char *ssl_tls13_get_kex_mode_str(int mode) +{ + switch (mode) { + case MBEDTLS_SSL_TLS1_3_KEY_EXCHANGE_MODE_PSK: + return "psk"; + case MBEDTLS_SSL_TLS1_3_KEY_EXCHANGE_MODE_EPHEMERAL: + return "ephemeral"; + case MBEDTLS_SSL_TLS1_3_KEY_EXCHANGE_MODE_PSK_EPHEMERAL: + return "psk_ephemeral"; + default: + return "unknown mode"; + } +} +#endif /* MBEDTLS_DEBUG_C */ + +MBEDTLS_CHECK_RETURN_CRITICAL +static int ssl_tls13_postprocess_server_hello(mbedtls_ssl_context *ssl) +{ + int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED; + mbedtls_ssl_handshake_params *handshake = ssl->handshake; + + /* Determine the key exchange mode: + * 1) If both the pre_shared_key and key_share extensions were received + * then the key exchange mode is PSK with EPHEMERAL. + * 2) If only the pre_shared_key extension was received then the key + * exchange mode is PSK-only. + * 3) If only the key_share extension was received then the key + * exchange mode is EPHEMERAL-only. + */ + switch (handshake->received_extensions & + (MBEDTLS_SSL_EXT_MASK(PRE_SHARED_KEY) | + MBEDTLS_SSL_EXT_MASK(KEY_SHARE))) { + /* Only the pre_shared_key extension was received */ + case MBEDTLS_SSL_EXT_MASK(PRE_SHARED_KEY): + handshake->key_exchange_mode = + MBEDTLS_SSL_TLS1_3_KEY_EXCHANGE_MODE_PSK; + break; + + /* Only the key_share extension was received */ + case MBEDTLS_SSL_EXT_MASK(KEY_SHARE): + handshake->key_exchange_mode = + MBEDTLS_SSL_TLS1_3_KEY_EXCHANGE_MODE_EPHEMERAL; + break; + + /* Both the pre_shared_key and key_share extensions were received */ + case (MBEDTLS_SSL_EXT_MASK(PRE_SHARED_KEY) | + MBEDTLS_SSL_EXT_MASK(KEY_SHARE)): + handshake->key_exchange_mode = + MBEDTLS_SSL_TLS1_3_KEY_EXCHANGE_MODE_PSK_EPHEMERAL; + break; + + /* Neither pre_shared_key nor key_share extension was received */ + default: + MBEDTLS_SSL_DEBUG_MSG(1, ("Unknown key exchange.")); + ret = MBEDTLS_ERR_SSL_HANDSHAKE_FAILURE; + goto cleanup; + } + + if (!mbedtls_ssl_conf_tls13_is_kex_mode_enabled( + ssl, handshake->key_exchange_mode)) { + ret = MBEDTLS_ERR_SSL_HANDSHAKE_FAILURE; + MBEDTLS_SSL_DEBUG_MSG( + 2, ("Key exchange mode(%s) is not supported.", + ssl_tls13_get_kex_mode_str(handshake->key_exchange_mode))); + goto cleanup; + } + + MBEDTLS_SSL_DEBUG_MSG( + 3, ("Selected key exchange mode: %s", + ssl_tls13_get_kex_mode_str(handshake->key_exchange_mode))); + + /* Start the TLS 1.3 key scheduling if not already done. + * + * If we proposed early data then we have already derived an + * early secret using the selected PSK and its associated hash. + * It means that if the negotiated key exchange mode is psk or + * psk_ephemeral, we have already correctly computed the + * early secret and thus we do not do it again. In all other + * cases we compute it here. + */ +#if defined(MBEDTLS_SSL_EARLY_DATA) + if (ssl->early_data_state == MBEDTLS_SSL_EARLY_DATA_STATE_NO_IND_SENT || + handshake->key_exchange_mode == + MBEDTLS_SSL_TLS1_3_KEY_EXCHANGE_MODE_EPHEMERAL) +#endif + { + ret = mbedtls_ssl_tls13_key_schedule_stage_early(ssl); + if (ret != 0) { + MBEDTLS_SSL_DEBUG_RET( + 1, "mbedtls_ssl_tls13_key_schedule_stage_early", ret); + goto cleanup; + } + } + + ret = mbedtls_ssl_tls13_compute_handshake_transform(ssl); + if (ret != 0) { + MBEDTLS_SSL_DEBUG_RET(1, + "mbedtls_ssl_tls13_compute_handshake_transform", + ret); + goto cleanup; + } + + mbedtls_ssl_set_inbound_transform(ssl, handshake->transform_handshake); + MBEDTLS_SSL_DEBUG_MSG(1, ("Switch to handshake keys for inbound traffic")); + ssl->session_in = ssl->session_negotiate; + +cleanup: + if (ret != 0) { + MBEDTLS_SSL_PEND_FATAL_ALERT( + MBEDTLS_SSL_ALERT_MSG_HANDSHAKE_FAILURE, + MBEDTLS_ERR_SSL_HANDSHAKE_FAILURE); + } + + return ret; +} + +MBEDTLS_CHECK_RETURN_CRITICAL +static int ssl_tls13_postprocess_hrr(mbedtls_ssl_context *ssl) +{ + int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED; + + mbedtls_ssl_session_reset_msg_layer(ssl, 0); + + /* + * We are going to re-generate a shared secret corresponding to the group + * selected by the server, which is different from the group for which we + * generated a shared secret in the first client hello. + * Thus, reset the shared secret. + */ + ret = ssl_tls13_reset_key_share(ssl); + if (ret != 0) { + return ret; + } + + ssl->session_negotiate->ciphersuite = ssl->handshake->ciphersuite_info->id; + +#if defined(MBEDTLS_SSL_EARLY_DATA) + if (ssl->early_data_state != MBEDTLS_SSL_EARLY_DATA_STATE_NO_IND_SENT) { + ssl->early_data_state = MBEDTLS_SSL_EARLY_DATA_STATE_REJECTED; + } +#endif + + return 0; +} + +/* + * Wait and parse ServerHello handshake message. + * Handler for MBEDTLS_SSL_SERVER_HELLO + */ +MBEDTLS_CHECK_RETURN_CRITICAL +static int ssl_tls13_process_server_hello(mbedtls_ssl_context *ssl) +{ + int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED; + unsigned char *buf = NULL; + size_t buf_len = 0; + int is_hrr = 0; + + MBEDTLS_SSL_DEBUG_MSG(2, ("=> %s", __func__)); + + MBEDTLS_SSL_PROC_CHK(mbedtls_ssl_tls13_fetch_handshake_msg( + ssl, MBEDTLS_SSL_HS_SERVER_HELLO, &buf, &buf_len)); + + ret = ssl_tls13_preprocess_server_hello(ssl, buf, buf + buf_len); + if (ret < 0) { + goto cleanup; + } else { + is_hrr = (ret == SSL_SERVER_HELLO_HRR); + } + + if (ret == SSL_SERVER_HELLO_TLS1_2) { + ret = 0; + goto cleanup; + } + + MBEDTLS_SSL_PROC_CHK(ssl_tls13_parse_server_hello(ssl, buf, + buf + buf_len, + is_hrr)); + if (is_hrr) { + MBEDTLS_SSL_PROC_CHK(mbedtls_ssl_reset_transcript_for_hrr(ssl)); + } + + MBEDTLS_SSL_PROC_CHK(mbedtls_ssl_add_hs_msg_to_checksum( + ssl, MBEDTLS_SSL_HS_SERVER_HELLO, buf, buf_len)); + + if (is_hrr) { + MBEDTLS_SSL_PROC_CHK(ssl_tls13_postprocess_hrr(ssl)); +#if defined(MBEDTLS_SSL_TLS1_3_COMPATIBILITY_MODE) + /* If not offering early data, the client sends a dummy CCS record + * immediately before its second flight. This may either be before + * its second ClientHello or before its encrypted handshake flight. + */ + mbedtls_ssl_handshake_set_state( + ssl, MBEDTLS_SSL_CLIENT_CCS_BEFORE_2ND_CLIENT_HELLO); +#else + mbedtls_ssl_handshake_set_state(ssl, MBEDTLS_SSL_CLIENT_HELLO); +#endif /* MBEDTLS_SSL_TLS1_3_COMPATIBILITY_MODE */ + } else { + MBEDTLS_SSL_PROC_CHK(ssl_tls13_postprocess_server_hello(ssl)); + mbedtls_ssl_handshake_set_state(ssl, MBEDTLS_SSL_ENCRYPTED_EXTENSIONS); + } + +cleanup: + MBEDTLS_SSL_DEBUG_MSG(2, ("<= %s ( %s )", __func__, + is_hrr ? "HelloRetryRequest" : "ServerHello")); + return ret; +} + +/* + * + * Handler for MBEDTLS_SSL_ENCRYPTED_EXTENSIONS + * + * The EncryptedExtensions message contains any extensions which + * should be protected, i.e., any which are not needed to establish + * the cryptographic context. + */ + +/* Parse EncryptedExtensions message + * struct { + * Extension extensions<0..2^16-1>; + * } EncryptedExtensions; + */ +MBEDTLS_CHECK_RETURN_CRITICAL +static int ssl_tls13_parse_encrypted_extensions(mbedtls_ssl_context *ssl, + const unsigned char *buf, + const unsigned char *end) +{ + int ret = 0; + size_t extensions_len; + const unsigned char *p = buf; + const unsigned char *extensions_end; + mbedtls_ssl_handshake_params *handshake = ssl->handshake; + + MBEDTLS_SSL_CHK_BUF_READ_PTR(p, end, 2); + extensions_len = MBEDTLS_GET_UINT16_BE(p, 0); + p += 2; + + MBEDTLS_SSL_CHK_BUF_READ_PTR(p, end, extensions_len); + extensions_end = p + extensions_len; + + MBEDTLS_SSL_DEBUG_BUF(3, "encrypted extensions", p, extensions_len); + + handshake->received_extensions = MBEDTLS_SSL_EXT_MASK_NONE; + + while (p < extensions_end) { + unsigned int extension_type; + size_t extension_data_len; + + /* + * struct { + * ExtensionType extension_type; (2 bytes) + * opaque extension_data<0..2^16-1>; + * } Extension; + */ + MBEDTLS_SSL_CHK_BUF_READ_PTR(p, extensions_end, 4); + extension_type = MBEDTLS_GET_UINT16_BE(p, 0); + extension_data_len = MBEDTLS_GET_UINT16_BE(p, 2); + p += 4; + + MBEDTLS_SSL_CHK_BUF_READ_PTR(p, extensions_end, extension_data_len); + + ret = mbedtls_ssl_tls13_check_received_extension( + ssl, MBEDTLS_SSL_HS_ENCRYPTED_EXTENSIONS, extension_type, + MBEDTLS_SSL_TLS1_3_ALLOWED_EXTS_OF_EE); + if (ret != 0) { + return ret; + } + + switch (extension_type) { +#if defined(MBEDTLS_SSL_ALPN) + case MBEDTLS_TLS_EXT_ALPN: + MBEDTLS_SSL_DEBUG_MSG(3, ("found alpn extension")); + + if ((ret = ssl_tls13_parse_alpn_ext( + ssl, p, (size_t) extension_data_len)) != 0) { + return ret; + } + + break; +#endif /* MBEDTLS_SSL_ALPN */ + +#if defined(MBEDTLS_SSL_EARLY_DATA) + case MBEDTLS_TLS_EXT_EARLY_DATA: + + if (extension_data_len != 0) { + /* The message must be empty. */ + MBEDTLS_SSL_PEND_FATAL_ALERT(MBEDTLS_SSL_ALERT_MSG_DECODE_ERROR, + MBEDTLS_ERR_SSL_DECODE_ERROR); + return MBEDTLS_ERR_SSL_DECODE_ERROR; + } + + break; +#endif /* MBEDTLS_SSL_EARLY_DATA */ + +#if defined(MBEDTLS_SSL_RECORD_SIZE_LIMIT) + case MBEDTLS_TLS_EXT_RECORD_SIZE_LIMIT: + MBEDTLS_SSL_DEBUG_MSG(3, ("found record_size_limit extension")); + + ret = mbedtls_ssl_tls13_parse_record_size_limit_ext( + ssl, p, p + extension_data_len); + if (ret != 0) { + MBEDTLS_SSL_DEBUG_RET( + 1, ("mbedtls_ssl_tls13_parse_record_size_limit_ext"), ret); + return ret; + } + break; +#endif /* MBEDTLS_SSL_RECORD_SIZE_LIMIT */ + + default: + MBEDTLS_SSL_PRINT_EXT( + 3, MBEDTLS_SSL_HS_ENCRYPTED_EXTENSIONS, + extension_type, "( ignored )"); + break; + } + + p += extension_data_len; + } + + if ((handshake->received_extensions & MBEDTLS_SSL_EXT_MASK(RECORD_SIZE_LIMIT)) && + (handshake->received_extensions & MBEDTLS_SSL_EXT_MASK(MAX_FRAGMENT_LENGTH))) { + MBEDTLS_SSL_DEBUG_MSG(3, + ( + "Record size limit extension cannot be used with max fragment length extension")); + MBEDTLS_SSL_PEND_FATAL_ALERT( + MBEDTLS_SSL_ALERT_MSG_ILLEGAL_PARAMETER, + MBEDTLS_ERR_SSL_ILLEGAL_PARAMETER); + return MBEDTLS_ERR_SSL_ILLEGAL_PARAMETER; + } + + MBEDTLS_SSL_PRINT_EXTS(3, MBEDTLS_SSL_HS_ENCRYPTED_EXTENSIONS, + handshake->received_extensions); + + /* Check that we consumed all the message. */ + if (p != end) { + MBEDTLS_SSL_DEBUG_MSG(1, ("EncryptedExtension lengths misaligned")); + MBEDTLS_SSL_PEND_FATAL_ALERT(MBEDTLS_SSL_ALERT_MSG_DECODE_ERROR, + MBEDTLS_ERR_SSL_DECODE_ERROR); + return MBEDTLS_ERR_SSL_DECODE_ERROR; + } + + return ret; +} + +MBEDTLS_CHECK_RETURN_CRITICAL +static int ssl_tls13_process_encrypted_extensions(mbedtls_ssl_context *ssl) +{ + int ret; + unsigned char *buf; + size_t buf_len; + mbedtls_ssl_handshake_params *handshake = ssl->handshake; + + MBEDTLS_SSL_DEBUG_MSG(2, ("=> parse encrypted extensions")); + + MBEDTLS_SSL_PROC_CHK(mbedtls_ssl_tls13_fetch_handshake_msg( + ssl, MBEDTLS_SSL_HS_ENCRYPTED_EXTENSIONS, + &buf, &buf_len)); + + /* Process the message contents */ + MBEDTLS_SSL_PROC_CHK( + ssl_tls13_parse_encrypted_extensions(ssl, buf, buf + buf_len)); + +#if defined(MBEDTLS_SSL_EARLY_DATA) + if (handshake->received_extensions & MBEDTLS_SSL_EXT_MASK(EARLY_DATA)) { + /* RFC8446 4.2.11 + * If the server supplies an "early_data" extension, the + * client MUST verify that the server's selected_identity + * is 0. If any other value is returned, the client MUST + * abort the handshake with an "illegal_parameter" alert. + * + * RFC 8446 4.2.10 + * In order to accept early data, the server MUST have accepted a PSK + * cipher suite and selected the first key offered in the client's + * "pre_shared_key" extension. In addition, it MUST verify that the + * following values are the same as those associated with the + * selected PSK: + * - The TLS version number + * - The selected cipher suite + * - The selected ALPN [RFC7301] protocol, if any + * + * The server has sent an early data extension in its Encrypted + * Extension message thus accepted to receive early data. We + * check here that the additional constraints on the handshake + * parameters, when early data are exchanged, are met, + * namely: + * - a PSK has been selected for the handshake + * - the selected PSK for the handshake was the first one proposed + * by the client. + * - the selected ciphersuite for the handshake is the ciphersuite + * associated with the selected PSK. + */ + if ((!mbedtls_ssl_tls13_key_exchange_mode_with_psk(ssl)) || + handshake->selected_identity != 0 || + handshake->ciphersuite_info->id != + ssl->session_negotiate->ciphersuite) { + + MBEDTLS_SSL_PEND_FATAL_ALERT( + MBEDTLS_SSL_ALERT_MSG_ILLEGAL_PARAMETER, + MBEDTLS_ERR_SSL_ILLEGAL_PARAMETER); + return MBEDTLS_ERR_SSL_ILLEGAL_PARAMETER; + } + + ssl->early_data_state = MBEDTLS_SSL_EARLY_DATA_STATE_ACCEPTED; + } else if (ssl->early_data_state != + MBEDTLS_SSL_EARLY_DATA_STATE_NO_IND_SENT) { + ssl->early_data_state = MBEDTLS_SSL_EARLY_DATA_STATE_REJECTED; + } +#endif + + /* + * In case the client has proposed a PSK associated with a ticket, + * `ssl->session_negotiate->ciphersuite` still contains at this point the + * identifier of the ciphersuite associated with the ticket. This is that + * way because, if an exchange of early data is agreed upon, we need + * it to check that the ciphersuite selected for the handshake is the + * ticket ciphersuite (see above). This information is not needed + * anymore thus we can now set it to the identifier of the ciphersuite + * used in this session under negotiation. + */ + ssl->session_negotiate->ciphersuite = handshake->ciphersuite_info->id; + + MBEDTLS_SSL_PROC_CHK(mbedtls_ssl_add_hs_msg_to_checksum( + ssl, MBEDTLS_SSL_HS_ENCRYPTED_EXTENSIONS, + buf, buf_len)); + +#if defined(MBEDTLS_SSL_TLS1_3_KEY_EXCHANGE_MODE_EPHEMERAL_ENABLED) + if (mbedtls_ssl_tls13_key_exchange_mode_with_psk(ssl)) { + mbedtls_ssl_handshake_set_state(ssl, MBEDTLS_SSL_SERVER_FINISHED); + } else { + mbedtls_ssl_handshake_set_state(ssl, MBEDTLS_SSL_CERTIFICATE_REQUEST); + } +#else + ((void) ssl); + mbedtls_ssl_handshake_set_state(ssl, MBEDTLS_SSL_SERVER_FINISHED); +#endif + +cleanup: + + MBEDTLS_SSL_DEBUG_MSG(2, ("<= parse encrypted extensions")); + return ret; + +} + +#if defined(MBEDTLS_SSL_EARLY_DATA) +/* + * Handler for MBEDTLS_SSL_END_OF_EARLY_DATA + * + * RFC 8446 section 4.5 + * + * struct {} EndOfEarlyData; + * + * If the server sent an "early_data" extension in EncryptedExtensions, the + * client MUST send an EndOfEarlyData message after receiving the server + * Finished. Otherwise, the client MUST NOT send an EndOfEarlyData message. + */ + +MBEDTLS_CHECK_RETURN_CRITICAL +static int ssl_tls13_write_end_of_early_data(mbedtls_ssl_context *ssl) +{ + int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED; + unsigned char *buf = NULL; + size_t buf_len; + MBEDTLS_SSL_DEBUG_MSG(2, ("=> write EndOfEarlyData")); + + MBEDTLS_SSL_PROC_CHK(mbedtls_ssl_start_handshake_msg( + ssl, MBEDTLS_SSL_HS_END_OF_EARLY_DATA, + &buf, &buf_len)); + + MBEDTLS_SSL_PROC_CHK(mbedtls_ssl_add_hs_hdr_to_checksum( + ssl, MBEDTLS_SSL_HS_END_OF_EARLY_DATA, 0)); + + MBEDTLS_SSL_PROC_CHK( + mbedtls_ssl_finish_handshake_msg(ssl, buf_len, 0)); + + mbedtls_ssl_handshake_set_state(ssl, MBEDTLS_SSL_CLIENT_CERTIFICATE); + +cleanup: + + MBEDTLS_SSL_DEBUG_MSG(2, ("<= write EndOfEarlyData")); + return ret; +} + +int mbedtls_ssl_get_early_data_status(mbedtls_ssl_context *ssl) +{ + if ((ssl->conf->endpoint != MBEDTLS_SSL_IS_CLIENT) || + (!mbedtls_ssl_is_handshake_over(ssl))) { + return MBEDTLS_ERR_SSL_BAD_INPUT_DATA; + } + + switch (ssl->early_data_state) { + case MBEDTLS_SSL_EARLY_DATA_STATE_NO_IND_SENT: + return MBEDTLS_SSL_EARLY_DATA_STATUS_NOT_INDICATED; + break; + + case MBEDTLS_SSL_EARLY_DATA_STATE_REJECTED: + return MBEDTLS_SSL_EARLY_DATA_STATUS_REJECTED; + break; + + case MBEDTLS_SSL_EARLY_DATA_STATE_SERVER_FINISHED_RECEIVED: + return MBEDTLS_SSL_EARLY_DATA_STATUS_ACCEPTED; + break; + + default: + return MBEDTLS_ERR_SSL_INTERNAL_ERROR; + } +} +#endif /* MBEDTLS_SSL_EARLY_DATA */ + +#if defined(MBEDTLS_SSL_TLS1_3_KEY_EXCHANGE_MODE_EPHEMERAL_ENABLED) +/* + * STATE HANDLING: CertificateRequest + * + */ +#define SSL_CERTIFICATE_REQUEST_EXPECT_REQUEST 0 +#define SSL_CERTIFICATE_REQUEST_SKIP 1 +/* Coordination: + * Deals with the ambiguity of not knowing if a CertificateRequest + * will be sent. Returns a negative code on failure, or + * - SSL_CERTIFICATE_REQUEST_EXPECT_REQUEST + * - SSL_CERTIFICATE_REQUEST_SKIP + * indicating if a Certificate Request is expected or not. + */ +MBEDTLS_CHECK_RETURN_CRITICAL +static int ssl_tls13_certificate_request_coordinate(mbedtls_ssl_context *ssl) +{ + int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED; + + if ((ret = mbedtls_ssl_read_record(ssl, 0)) != 0) { + MBEDTLS_SSL_DEBUG_RET(1, "mbedtls_ssl_read_record", ret); + return ret; + } + ssl->keep_current_message = 1; + + if ((ssl->in_msgtype == MBEDTLS_SSL_MSG_HANDSHAKE) && + (ssl->in_msg[0] == MBEDTLS_SSL_HS_CERTIFICATE_REQUEST)) { + MBEDTLS_SSL_DEBUG_MSG(3, ("got a certificate request")); + return SSL_CERTIFICATE_REQUEST_EXPECT_REQUEST; + } + + MBEDTLS_SSL_DEBUG_MSG(3, ("got no certificate request")); + + return SSL_CERTIFICATE_REQUEST_SKIP; +} + +/* + * ssl_tls13_parse_certificate_request() + * Parse certificate request + * struct { + * opaque certificate_request_context<0..2^8-1>; + * Extension extensions<2..2^16-1>; + * } CertificateRequest; + */ +MBEDTLS_CHECK_RETURN_CRITICAL +static int ssl_tls13_parse_certificate_request(mbedtls_ssl_context *ssl, + const unsigned char *buf, + const unsigned char *end) +{ + int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED; + const unsigned char *p = buf; + size_t certificate_request_context_len = 0; + size_t extensions_len = 0; + const unsigned char *extensions_end; + mbedtls_ssl_handshake_params *handshake = ssl->handshake; + + /* ... + * opaque certificate_request_context<0..2^8-1> + * ... + */ + MBEDTLS_SSL_CHK_BUF_READ_PTR(p, end, 1); + certificate_request_context_len = (size_t) p[0]; + p += 1; + + if (certificate_request_context_len > 0) { + MBEDTLS_SSL_CHK_BUF_READ_PTR(p, end, certificate_request_context_len); + MBEDTLS_SSL_DEBUG_BUF(3, "Certificate Request Context", + p, certificate_request_context_len); + + handshake->certificate_request_context = + mbedtls_calloc(1, certificate_request_context_len); + if (handshake->certificate_request_context == NULL) { + MBEDTLS_SSL_DEBUG_MSG(1, ("buffer too small")); + return MBEDTLS_ERR_SSL_ALLOC_FAILED; + } + memcpy(handshake->certificate_request_context, p, + certificate_request_context_len); + p += certificate_request_context_len; + } + + /* ... + * Extension extensions<2..2^16-1>; + * ... + */ + MBEDTLS_SSL_CHK_BUF_READ_PTR(p, end, 2); + extensions_len = MBEDTLS_GET_UINT16_BE(p, 0); + p += 2; + + MBEDTLS_SSL_CHK_BUF_READ_PTR(p, end, extensions_len); + extensions_end = p + extensions_len; + + handshake->received_extensions = MBEDTLS_SSL_EXT_MASK_NONE; + + while (p < extensions_end) { + unsigned int extension_type; + size_t extension_data_len; + + MBEDTLS_SSL_CHK_BUF_READ_PTR(p, extensions_end, 4); + extension_type = MBEDTLS_GET_UINT16_BE(p, 0); + extension_data_len = MBEDTLS_GET_UINT16_BE(p, 2); + p += 4; + + MBEDTLS_SSL_CHK_BUF_READ_PTR(p, extensions_end, extension_data_len); + + ret = mbedtls_ssl_tls13_check_received_extension( + ssl, MBEDTLS_SSL_HS_CERTIFICATE_REQUEST, extension_type, + MBEDTLS_SSL_TLS1_3_ALLOWED_EXTS_OF_CR); + if (ret != 0) { + return ret; + } + + switch (extension_type) { + case MBEDTLS_TLS_EXT_SIG_ALG: + MBEDTLS_SSL_DEBUG_MSG(3, + ("found signature algorithms extension")); + ret = mbedtls_ssl_parse_sig_alg_ext(ssl, p, + p + extension_data_len); + if (ret != 0) { + return ret; + } + + break; + + default: + MBEDTLS_SSL_PRINT_EXT( + 3, MBEDTLS_SSL_HS_CERTIFICATE_REQUEST, + extension_type, "( ignored )"); + break; + } + + p += extension_data_len; + } + + MBEDTLS_SSL_PRINT_EXTS(3, MBEDTLS_SSL_HS_CERTIFICATE_REQUEST, + handshake->received_extensions); + + /* Check that we consumed all the message. */ + if (p != end) { + MBEDTLS_SSL_DEBUG_MSG(1, + ("CertificateRequest misaligned")); + goto decode_error; + } + + /* RFC 8446 section 4.3.2 + * + * The "signature_algorithms" extension MUST be specified + */ + if ((handshake->received_extensions & MBEDTLS_SSL_EXT_MASK(SIG_ALG)) == 0) { + MBEDTLS_SSL_DEBUG_MSG(3, + ("no signature algorithms extension found")); + goto decode_error; + } + + ssl->handshake->client_auth = 1; + return 0; + +decode_error: + MBEDTLS_SSL_PEND_FATAL_ALERT(MBEDTLS_SSL_ALERT_MSG_DECODE_ERROR, + MBEDTLS_ERR_SSL_DECODE_ERROR); + return MBEDTLS_ERR_SSL_DECODE_ERROR; +} + +/* + * Handler for MBEDTLS_SSL_CERTIFICATE_REQUEST + */ +MBEDTLS_CHECK_RETURN_CRITICAL +static int ssl_tls13_process_certificate_request(mbedtls_ssl_context *ssl) +{ + int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED; + + MBEDTLS_SSL_DEBUG_MSG(2, ("=> parse certificate request")); + + MBEDTLS_SSL_PROC_CHK_NEG(ssl_tls13_certificate_request_coordinate(ssl)); + + if (ret == SSL_CERTIFICATE_REQUEST_EXPECT_REQUEST) { + unsigned char *buf; + size_t buf_len; + + MBEDTLS_SSL_PROC_CHK(mbedtls_ssl_tls13_fetch_handshake_msg( + ssl, MBEDTLS_SSL_HS_CERTIFICATE_REQUEST, + &buf, &buf_len)); + + MBEDTLS_SSL_PROC_CHK(ssl_tls13_parse_certificate_request( + ssl, buf, buf + buf_len)); + + MBEDTLS_SSL_PROC_CHK(mbedtls_ssl_add_hs_msg_to_checksum( + ssl, MBEDTLS_SSL_HS_CERTIFICATE_REQUEST, + buf, buf_len)); + } else if (ret == SSL_CERTIFICATE_REQUEST_SKIP) { + ret = 0; + } else { + MBEDTLS_SSL_DEBUG_MSG(1, ("should never happen")); + ret = MBEDTLS_ERR_SSL_INTERNAL_ERROR; + goto cleanup; + } + + mbedtls_ssl_handshake_set_state(ssl, MBEDTLS_SSL_SERVER_CERTIFICATE); + +cleanup: + + MBEDTLS_SSL_DEBUG_MSG(2, ("<= parse certificate request")); + return ret; +} + +/* + * Handler for MBEDTLS_SSL_SERVER_CERTIFICATE + */ +MBEDTLS_CHECK_RETURN_CRITICAL +static int ssl_tls13_process_server_certificate(mbedtls_ssl_context *ssl) +{ + int ret; + + ret = mbedtls_ssl_tls13_process_certificate(ssl); + if (ret != 0) { + return ret; + } + + mbedtls_ssl_handshake_set_state(ssl, MBEDTLS_SSL_CERTIFICATE_VERIFY); + return 0; +} + +/* + * Handler for MBEDTLS_SSL_CERTIFICATE_VERIFY + */ +MBEDTLS_CHECK_RETURN_CRITICAL +static int ssl_tls13_process_certificate_verify(mbedtls_ssl_context *ssl) +{ + int ret; + + ret = mbedtls_ssl_tls13_process_certificate_verify(ssl); + if (ret != 0) { + return ret; + } + + mbedtls_ssl_handshake_set_state(ssl, MBEDTLS_SSL_SERVER_FINISHED); + return 0; +} +#endif /* MBEDTLS_SSL_TLS1_3_KEY_EXCHANGE_MODE_EPHEMERAL_ENABLED */ + +/* + * Handler for MBEDTLS_SSL_SERVER_FINISHED + */ +MBEDTLS_CHECK_RETURN_CRITICAL +static int ssl_tls13_process_server_finished(mbedtls_ssl_context *ssl) +{ + int ret; + + ret = mbedtls_ssl_tls13_process_finished_message(ssl); + if (ret != 0) { + return ret; + } + + ret = mbedtls_ssl_tls13_compute_application_transform(ssl); + if (ret != 0) { + MBEDTLS_SSL_PEND_FATAL_ALERT( + MBEDTLS_SSL_ALERT_MSG_HANDSHAKE_FAILURE, + MBEDTLS_ERR_SSL_HANDSHAKE_FAILURE); + return ret; + } + +#if defined(MBEDTLS_SSL_EARLY_DATA) + if (ssl->early_data_state == MBEDTLS_SSL_EARLY_DATA_STATE_ACCEPTED) { + ssl->early_data_state = MBEDTLS_SSL_EARLY_DATA_STATE_SERVER_FINISHED_RECEIVED; + mbedtls_ssl_handshake_set_state(ssl, MBEDTLS_SSL_END_OF_EARLY_DATA); + } else +#endif /* MBEDTLS_SSL_EARLY_DATA */ + { +#if defined(MBEDTLS_SSL_TLS1_3_COMPATIBILITY_MODE) + mbedtls_ssl_handshake_set_state( + ssl, MBEDTLS_SSL_CLIENT_CCS_AFTER_SERVER_FINISHED); +#else + mbedtls_ssl_handshake_set_state(ssl, MBEDTLS_SSL_CLIENT_CERTIFICATE); +#endif /* MBEDTLS_SSL_TLS1_3_COMPATIBILITY_MODE */ + } + + return 0; +} + +/* + * Handler for MBEDTLS_SSL_CLIENT_CERTIFICATE + */ +MBEDTLS_CHECK_RETURN_CRITICAL +static int ssl_tls13_write_client_certificate(mbedtls_ssl_context *ssl) +{ + int non_empty_certificate_msg = 0; + + MBEDTLS_SSL_DEBUG_MSG(1, + ("Switch to handshake traffic keys for outbound traffic")); + mbedtls_ssl_set_outbound_transform(ssl, ssl->handshake->transform_handshake); + +#if defined(MBEDTLS_SSL_TLS1_3_KEY_EXCHANGE_MODE_EPHEMERAL_ENABLED) + if (ssl->handshake->client_auth) { + int ret = mbedtls_ssl_tls13_write_certificate(ssl); + if (ret != 0) { + return ret; + } + + if (mbedtls_ssl_own_cert(ssl) != NULL) { + non_empty_certificate_msg = 1; + } + } else { + MBEDTLS_SSL_DEBUG_MSG(2, ("skip write certificate")); + } +#endif + + if (non_empty_certificate_msg) { + mbedtls_ssl_handshake_set_state(ssl, + MBEDTLS_SSL_CLIENT_CERTIFICATE_VERIFY); + } else { + MBEDTLS_SSL_DEBUG_MSG(2, ("skip write certificate verify")); + mbedtls_ssl_handshake_set_state(ssl, MBEDTLS_SSL_CLIENT_FINISHED); + } + + return 0; +} + +#if defined(MBEDTLS_SSL_TLS1_3_KEY_EXCHANGE_MODE_EPHEMERAL_ENABLED) +/* + * Handler for MBEDTLS_SSL_CLIENT_CERTIFICATE_VERIFY + */ +MBEDTLS_CHECK_RETURN_CRITICAL +static int ssl_tls13_write_client_certificate_verify(mbedtls_ssl_context *ssl) +{ + int ret = mbedtls_ssl_tls13_write_certificate_verify(ssl); + + if (ret == 0) { + mbedtls_ssl_handshake_set_state(ssl, MBEDTLS_SSL_CLIENT_FINISHED); + } + + return ret; +} +#endif /* MBEDTLS_SSL_TLS1_3_KEY_EXCHANGE_MODE_EPHEMERAL_ENABLED */ + +/* + * Handler for MBEDTLS_SSL_CLIENT_FINISHED + */ +MBEDTLS_CHECK_RETURN_CRITICAL +static int ssl_tls13_write_client_finished(mbedtls_ssl_context *ssl) +{ + int ret; + + ret = mbedtls_ssl_tls13_write_finished_message(ssl); + if (ret != 0) { + return ret; + } + + ret = mbedtls_ssl_tls13_compute_resumption_master_secret(ssl); + if (ret != 0) { + MBEDTLS_SSL_DEBUG_RET( + 1, "mbedtls_ssl_tls13_compute_resumption_master_secret ", ret); + return ret; + } + + mbedtls_ssl_handshake_set_state(ssl, MBEDTLS_SSL_FLUSH_BUFFERS); + return 0; +} + +/* + * Handler for MBEDTLS_SSL_FLUSH_BUFFERS + */ +MBEDTLS_CHECK_RETURN_CRITICAL +static int ssl_tls13_flush_buffers(mbedtls_ssl_context *ssl) +{ + MBEDTLS_SSL_DEBUG_MSG(2, ("handshake: done")); + mbedtls_ssl_handshake_set_state(ssl, MBEDTLS_SSL_HANDSHAKE_WRAPUP); + return 0; +} + +/* + * Handler for MBEDTLS_SSL_HANDSHAKE_WRAPUP + */ +MBEDTLS_CHECK_RETURN_CRITICAL +static int ssl_tls13_handshake_wrapup(mbedtls_ssl_context *ssl) +{ + + mbedtls_ssl_tls13_handshake_wrapup(ssl); + + mbedtls_ssl_handshake_set_state(ssl, MBEDTLS_SSL_HANDSHAKE_OVER); + return 0; +} + +#if defined(MBEDTLS_SSL_SESSION_TICKETS) + +#if defined(MBEDTLS_SSL_EARLY_DATA) +/* From RFC 8446 section 4.2.10 + * + * struct { + * select (Handshake.msg_type) { + * case new_session_ticket: uint32 max_early_data_size; + * ... + * }; + * } EarlyDataIndication; + */ +MBEDTLS_CHECK_RETURN_CRITICAL +static int ssl_tls13_parse_new_session_ticket_early_data_ext( + mbedtls_ssl_context *ssl, + const unsigned char *buf, + const unsigned char *end) +{ + mbedtls_ssl_session *session = ssl->session; + + MBEDTLS_SSL_CHK_BUF_READ_PTR(buf, end, 4); + + session->max_early_data_size = MBEDTLS_GET_UINT32_BE(buf, 0); + mbedtls_ssl_tls13_session_set_ticket_flags( + session, MBEDTLS_SSL_TLS1_3_TICKET_ALLOW_EARLY_DATA); + MBEDTLS_SSL_DEBUG_MSG( + 3, ("received max_early_data_size: %u", + (unsigned int) session->max_early_data_size)); + + return 0; +} +#endif /* MBEDTLS_SSL_EARLY_DATA */ + +MBEDTLS_CHECK_RETURN_CRITICAL +static int ssl_tls13_parse_new_session_ticket_exts(mbedtls_ssl_context *ssl, + const unsigned char *buf, + const unsigned char *end) +{ + mbedtls_ssl_handshake_params *handshake = ssl->handshake; + const unsigned char *p = buf; + + + handshake->received_extensions = MBEDTLS_SSL_EXT_MASK_NONE; + + while (p < end) { + unsigned int extension_type; + size_t extension_data_len; + int ret; + + MBEDTLS_SSL_CHK_BUF_READ_PTR(p, end, 4); + extension_type = MBEDTLS_GET_UINT16_BE(p, 0); + extension_data_len = MBEDTLS_GET_UINT16_BE(p, 2); + p += 4; + + MBEDTLS_SSL_CHK_BUF_READ_PTR(p, end, extension_data_len); + + ret = mbedtls_ssl_tls13_check_received_extension( + ssl, MBEDTLS_SSL_HS_NEW_SESSION_TICKET, extension_type, + MBEDTLS_SSL_TLS1_3_ALLOWED_EXTS_OF_NST); + if (ret != 0) { + return ret; + } + + switch (extension_type) { +#if defined(MBEDTLS_SSL_EARLY_DATA) + case MBEDTLS_TLS_EXT_EARLY_DATA: + ret = ssl_tls13_parse_new_session_ticket_early_data_ext( + ssl, p, p + extension_data_len); + if (ret != 0) { + MBEDTLS_SSL_DEBUG_RET( + 1, "ssl_tls13_parse_new_session_ticket_early_data_ext", + ret); + } + break; +#endif /* MBEDTLS_SSL_EARLY_DATA */ + + default: + MBEDTLS_SSL_PRINT_EXT( + 3, MBEDTLS_SSL_HS_NEW_SESSION_TICKET, + extension_type, "( ignored )"); + break; + } + + p += extension_data_len; + } + + MBEDTLS_SSL_PRINT_EXTS(3, MBEDTLS_SSL_HS_NEW_SESSION_TICKET, + handshake->received_extensions); + + return 0; +} + +/* + * From RFC8446, page 74 + * + * struct { + * uint32 ticket_lifetime; + * uint32 ticket_age_add; + * opaque ticket_nonce<0..255>; + * opaque ticket<1..2^16-1>; + * Extension extensions<0..2^16-2>; + * } NewSessionTicket; + * + */ +MBEDTLS_CHECK_RETURN_CRITICAL +static int ssl_tls13_parse_new_session_ticket(mbedtls_ssl_context *ssl, + unsigned char *buf, + unsigned char *end, + unsigned char **ticket_nonce, + size_t *ticket_nonce_len) +{ + int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED; + unsigned char *p = buf; + mbedtls_ssl_session *session = ssl->session; + size_t ticket_len; + unsigned char *ticket; + size_t extensions_len; + + *ticket_nonce = NULL; + *ticket_nonce_len = 0; + /* + * ticket_lifetime 4 bytes + * ticket_age_add 4 bytes + * ticket_nonce_len 1 byte + */ + MBEDTLS_SSL_CHK_BUF_READ_PTR(p, end, 9); + + session->ticket_lifetime = MBEDTLS_GET_UINT32_BE(p, 0); + MBEDTLS_SSL_DEBUG_MSG(3, + ("ticket_lifetime: %u", + (unsigned int) session->ticket_lifetime)); + if (session->ticket_lifetime > + MBEDTLS_SSL_TLS1_3_MAX_ALLOWED_TICKET_LIFETIME) { + MBEDTLS_SSL_DEBUG_MSG(3, ("ticket_lifetime exceeds 7 days.")); + return MBEDTLS_ERR_SSL_ILLEGAL_PARAMETER; + } + + session->ticket_age_add = MBEDTLS_GET_UINT32_BE(p, 4); + MBEDTLS_SSL_DEBUG_MSG(3, + ("ticket_age_add: %u", + (unsigned int) session->ticket_age_add)); + + *ticket_nonce_len = p[8]; + p += 9; + + MBEDTLS_SSL_CHK_BUF_READ_PTR(p, end, *ticket_nonce_len); + *ticket_nonce = p; + MBEDTLS_SSL_DEBUG_BUF(3, "ticket_nonce:", *ticket_nonce, *ticket_nonce_len); + p += *ticket_nonce_len; + + /* Ticket */ + MBEDTLS_SSL_CHK_BUF_READ_PTR(p, end, 2); + ticket_len = MBEDTLS_GET_UINT16_BE(p, 0); + p += 2; + MBEDTLS_SSL_CHK_BUF_READ_PTR(p, end, ticket_len); + MBEDTLS_SSL_DEBUG_BUF(3, "received ticket", p, ticket_len); + + /* Check if we previously received a ticket already. */ + if (session->ticket != NULL || session->ticket_len > 0) { + mbedtls_free(session->ticket); + session->ticket = NULL; + session->ticket_len = 0; + } + + if ((ticket = mbedtls_calloc(1, ticket_len)) == NULL) { + MBEDTLS_SSL_DEBUG_MSG(1, ("ticket alloc failed")); + return MBEDTLS_ERR_SSL_ALLOC_FAILED; + } + memcpy(ticket, p, ticket_len); + p += ticket_len; + session->ticket = ticket; + session->ticket_len = ticket_len; + + /* Clear all flags in ticket_flags */ + mbedtls_ssl_tls13_session_clear_ticket_flags( + session, MBEDTLS_SSL_TLS1_3_TICKET_FLAGS_MASK); + + MBEDTLS_SSL_CHK_BUF_READ_PTR(p, end, 2); + extensions_len = MBEDTLS_GET_UINT16_BE(p, 0); + p += 2; + MBEDTLS_SSL_CHK_BUF_READ_PTR(p, end, extensions_len); + + MBEDTLS_SSL_DEBUG_BUF(3, "ticket extension", p, extensions_len); + + ret = ssl_tls13_parse_new_session_ticket_exts(ssl, p, p + extensions_len); + if (ret != 0) { + MBEDTLS_SSL_DEBUG_RET(1, + "ssl_tls13_parse_new_session_ticket_exts", + ret); + return ret; + } + + return 0; +} + +/* Non negative return values for ssl_tls13_postprocess_new_session_ticket(). + * - POSTPROCESS_NEW_SESSION_TICKET_SIGNAL, all good, we have to signal the + * application that a valid ticket has been received. + * - POSTPROCESS_NEW_SESSION_TICKET_DISCARD, no fatal error, we keep the + * connection alive but we do not signal the ticket to the application. + */ +#define POSTPROCESS_NEW_SESSION_TICKET_SIGNAL 0 +#define POSTPROCESS_NEW_SESSION_TICKET_DISCARD 1 +MBEDTLS_CHECK_RETURN_CRITICAL +static int ssl_tls13_postprocess_new_session_ticket(mbedtls_ssl_context *ssl, + unsigned char *ticket_nonce, + size_t ticket_nonce_len) +{ + int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED; + mbedtls_ssl_session *session = ssl->session; + const mbedtls_ssl_ciphersuite_t *ciphersuite_info; + psa_algorithm_t psa_hash_alg; + int hash_length; + + if (session->ticket_lifetime == 0) { + return POSTPROCESS_NEW_SESSION_TICKET_DISCARD; + } + +#if defined(MBEDTLS_HAVE_TIME) + /* Store ticket creation time */ + session->ticket_reception_time = mbedtls_ms_time(); +#endif + + ciphersuite_info = mbedtls_ssl_ciphersuite_from_id(session->ciphersuite); + if (ciphersuite_info == NULL) { + MBEDTLS_SSL_DEBUG_MSG(1, ("should never happen")); + return MBEDTLS_ERR_SSL_INTERNAL_ERROR; + } + + psa_hash_alg = mbedtls_md_psa_alg_from_type((mbedtls_md_type_t) ciphersuite_info->mac); + hash_length = PSA_HASH_LENGTH(psa_hash_alg); + if (hash_length == -1 || + (size_t) hash_length > sizeof(session->resumption_key)) { + return MBEDTLS_ERR_SSL_INTERNAL_ERROR; + } + + + MBEDTLS_SSL_DEBUG_BUF(3, "resumption_master_secret", + session->app_secrets.resumption_master_secret, + hash_length); + + /* Compute resumption key + * + * HKDF-Expand-Label( resumption_master_secret, + * "resumption", ticket_nonce, Hash.length ) + */ + ret = mbedtls_ssl_tls13_hkdf_expand_label( + psa_hash_alg, + session->app_secrets.resumption_master_secret, + hash_length, + MBEDTLS_SSL_TLS1_3_LBL_WITH_LEN(resumption), + ticket_nonce, + ticket_nonce_len, + session->resumption_key, + hash_length); + + if (ret != 0) { + MBEDTLS_SSL_DEBUG_RET(2, + "Creating the ticket-resumed PSK failed", + ret); + return ret; + } + + session->resumption_key_len = hash_length; + + MBEDTLS_SSL_DEBUG_BUF(3, "Ticket-resumed PSK", + session->resumption_key, + session->resumption_key_len); + + /* Set ticket_flags depends on the selected key exchange modes */ + mbedtls_ssl_tls13_session_set_ticket_flags( + session, ssl->conf->tls13_kex_modes); + MBEDTLS_SSL_PRINT_TICKET_FLAGS(4, session->ticket_flags); + + return POSTPROCESS_NEW_SESSION_TICKET_SIGNAL; +} + +/* + * Handler for MBEDTLS_SSL_TLS1_3_NEW_SESSION_TICKET + */ +MBEDTLS_CHECK_RETURN_CRITICAL +static int ssl_tls13_process_new_session_ticket(mbedtls_ssl_context *ssl) +{ + int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED; + unsigned char *buf; + size_t buf_len; + unsigned char *ticket_nonce; + size_t ticket_nonce_len; + + MBEDTLS_SSL_DEBUG_MSG(2, ("=> parse new session ticket")); + + MBEDTLS_SSL_PROC_CHK(mbedtls_ssl_tls13_fetch_handshake_msg( + ssl, MBEDTLS_SSL_HS_NEW_SESSION_TICKET, + &buf, &buf_len)); + + /* + * We are about to update (maybe only partially) ticket data thus block + * any session export for the time being. + */ + ssl->session->exported = 1; + + MBEDTLS_SSL_PROC_CHK(ssl_tls13_parse_new_session_ticket( + ssl, buf, buf + buf_len, + &ticket_nonce, &ticket_nonce_len)); + + MBEDTLS_SSL_PROC_CHK_NEG(ssl_tls13_postprocess_new_session_ticket( + ssl, ticket_nonce, ticket_nonce_len)); + + switch (ret) { + case POSTPROCESS_NEW_SESSION_TICKET_SIGNAL: + /* + * All good, we have received a new valid ticket, session data can + * be exported now and we signal the ticket to the application. + */ + ssl->session->exported = 0; + ret = MBEDTLS_ERR_SSL_RECEIVED_NEW_SESSION_TICKET; + break; + + case POSTPROCESS_NEW_SESSION_TICKET_DISCARD: + ret = 0; + MBEDTLS_SSL_DEBUG_MSG(2, ("Discard new session ticket")); + break; + + default: + ret = MBEDTLS_ERR_SSL_INTERNAL_ERROR; + } + + mbedtls_ssl_handshake_set_state(ssl, MBEDTLS_SSL_HANDSHAKE_OVER); + +cleanup: + + MBEDTLS_SSL_DEBUG_MSG(2, ("<= parse new session ticket")); + return ret; +} +#endif /* MBEDTLS_SSL_SESSION_TICKETS */ + +int mbedtls_ssl_tls13_handshake_client_step(mbedtls_ssl_context *ssl) +{ + int ret = 0; + + switch (ssl->state) { + case MBEDTLS_SSL_HELLO_REQUEST: + mbedtls_ssl_handshake_set_state(ssl, MBEDTLS_SSL_CLIENT_HELLO); + break; + + case MBEDTLS_SSL_CLIENT_HELLO: + ret = mbedtls_ssl_write_client_hello(ssl); + break; + + case MBEDTLS_SSL_SERVER_HELLO: + ret = ssl_tls13_process_server_hello(ssl); + break; + + case MBEDTLS_SSL_ENCRYPTED_EXTENSIONS: + ret = ssl_tls13_process_encrypted_extensions(ssl); + break; + +#if defined(MBEDTLS_SSL_TLS1_3_KEY_EXCHANGE_MODE_EPHEMERAL_ENABLED) + case MBEDTLS_SSL_CERTIFICATE_REQUEST: + ret = ssl_tls13_process_certificate_request(ssl); + break; + + case MBEDTLS_SSL_SERVER_CERTIFICATE: + ret = ssl_tls13_process_server_certificate(ssl); + break; + + case MBEDTLS_SSL_CERTIFICATE_VERIFY: + ret = ssl_tls13_process_certificate_verify(ssl); + break; +#endif /* MBEDTLS_SSL_TLS1_3_KEY_EXCHANGE_MODE_EPHEMERAL_ENABLED */ + + case MBEDTLS_SSL_SERVER_FINISHED: + ret = ssl_tls13_process_server_finished(ssl); + break; + +#if defined(MBEDTLS_SSL_EARLY_DATA) + case MBEDTLS_SSL_END_OF_EARLY_DATA: + ret = ssl_tls13_write_end_of_early_data(ssl); + break; +#endif + + case MBEDTLS_SSL_CLIENT_CERTIFICATE: + ret = ssl_tls13_write_client_certificate(ssl); + break; + +#if defined(MBEDTLS_SSL_TLS1_3_KEY_EXCHANGE_MODE_EPHEMERAL_ENABLED) + case MBEDTLS_SSL_CLIENT_CERTIFICATE_VERIFY: + ret = ssl_tls13_write_client_certificate_verify(ssl); + break; +#endif /* MBEDTLS_SSL_TLS1_3_KEY_EXCHANGE_MODE_EPHEMERAL_ENABLED */ + + case MBEDTLS_SSL_CLIENT_FINISHED: + ret = ssl_tls13_write_client_finished(ssl); + break; + + case MBEDTLS_SSL_FLUSH_BUFFERS: + ret = ssl_tls13_flush_buffers(ssl); + break; + + case MBEDTLS_SSL_HANDSHAKE_WRAPUP: + ret = ssl_tls13_handshake_wrapup(ssl); + break; + + /* + * Injection of dummy-CCS's for middlebox compatibility + */ +#if defined(MBEDTLS_SSL_TLS1_3_COMPATIBILITY_MODE) + case MBEDTLS_SSL_CLIENT_CCS_BEFORE_2ND_CLIENT_HELLO: + ret = mbedtls_ssl_tls13_write_change_cipher_spec(ssl); + if (ret != 0) { + break; + } + mbedtls_ssl_handshake_set_state(ssl, MBEDTLS_SSL_CLIENT_HELLO); + break; + + case MBEDTLS_SSL_CLIENT_CCS_AFTER_SERVER_FINISHED: + ret = mbedtls_ssl_tls13_write_change_cipher_spec(ssl); + if (ret != 0) { + break; + } + mbedtls_ssl_handshake_set_state(ssl, MBEDTLS_SSL_CLIENT_CERTIFICATE); + break; + +#if defined(MBEDTLS_SSL_EARLY_DATA) + case MBEDTLS_SSL_CLIENT_CCS_AFTER_CLIENT_HELLO: + ret = mbedtls_ssl_tls13_write_change_cipher_spec(ssl); + if (ret == 0) { + mbedtls_ssl_handshake_set_state(ssl, MBEDTLS_SSL_SERVER_HELLO); + + MBEDTLS_SSL_DEBUG_MSG( + 1, ("Switch to early data keys for outbound traffic")); + mbedtls_ssl_set_outbound_transform( + ssl, ssl->handshake->transform_earlydata); + ssl->early_data_state = MBEDTLS_SSL_EARLY_DATA_STATE_CAN_WRITE; + } + break; +#endif /* MBEDTLS_SSL_EARLY_DATA */ +#endif /* MBEDTLS_SSL_TLS1_3_COMPATIBILITY_MODE */ + +#if defined(MBEDTLS_SSL_SESSION_TICKETS) + case MBEDTLS_SSL_TLS1_3_NEW_SESSION_TICKET: + ret = ssl_tls13_process_new_session_ticket(ssl); + break; +#endif /* MBEDTLS_SSL_SESSION_TICKETS */ + + default: + MBEDTLS_SSL_DEBUG_MSG(1, ("invalid state %d", ssl->state)); + return MBEDTLS_ERR_SSL_BAD_INPUT_DATA; + } + + return ret; +} + +#endif /* MBEDTLS_SSL_CLI_C && MBEDTLS_SSL_PROTO_TLS1_3 */ diff --git a/vendor/mbedtls/library/ssl_tls13_generic.c b/vendor/mbedtls/library/ssl_tls13_generic.c new file mode 100644 index 0000000000..d448a054a9 --- /dev/null +++ b/vendor/mbedtls/library/ssl_tls13_generic.c @@ -0,0 +1,1853 @@ +/* + * TLS 1.3 functionality shared between client and server + * + * Copyright The Mbed TLS Contributors + * SPDX-License-Identifier: Apache-2.0 OR GPL-2.0-or-later + */ + +#include "common.h" + +#if defined(MBEDTLS_SSL_TLS_C) && defined(MBEDTLS_SSL_PROTO_TLS1_3) + +#include + +#include "mbedtls/error.h" +#include "debug_internal.h" +#include "mbedtls/oid.h" +#include "mbedtls/platform.h" +#include "mbedtls/constant_time.h" +#include "psa/crypto.h" +#include "mbedtls/psa_util.h" + +#include "ssl_misc.h" +#include "ssl_tls13_invasive.h" +#include "ssl_tls13_keys.h" +#include "ssl_debug_helpers.h" + +#include "psa/crypto.h" +#include "psa_util_internal.h" + +#if defined(MBEDTLS_SSL_TLS1_3_KEY_EXCHANGE_MODE_SOME_EPHEMERAL_ENABLED) +/* Define a local translating function to save code size by not using too many + * arguments in each translating place. */ +static int local_err_translation(psa_status_t status) +{ + return psa_status_to_mbedtls(status, psa_to_ssl_errors, + ARRAY_LENGTH(psa_to_ssl_errors), + psa_generic_status_to_mbedtls); +} +#define PSA_TO_MBEDTLS_ERR(status) local_err_translation(status) +#endif + +const uint8_t mbedtls_ssl_tls13_hello_retry_request_magic[ + MBEDTLS_SERVER_HELLO_RANDOM_LEN] = +{ 0xCF, 0x21, 0xAD, 0x74, 0xE5, 0x9A, 0x61, 0x11, + 0xBE, 0x1D, 0x8C, 0x02, 0x1E, 0x65, 0xB8, 0x91, + 0xC2, 0xA2, 0x11, 0x16, 0x7A, 0xBB, 0x8C, 0x5E, + 0x07, 0x9E, 0x09, 0xE2, 0xC8, 0xA8, 0x33, 0x9C }; + +int mbedtls_ssl_tls13_fetch_handshake_msg(mbedtls_ssl_context *ssl, + unsigned hs_type, + unsigned char **buf, + size_t *buf_len) +{ + int ret; + + if ((ret = mbedtls_ssl_read_record(ssl, 0)) != 0) { + MBEDTLS_SSL_DEBUG_RET(1, "mbedtls_ssl_read_record", ret); + goto cleanup; + } + + if (ssl->in_msgtype != MBEDTLS_SSL_MSG_HANDSHAKE || + ssl->in_msg[0] != hs_type) { + MBEDTLS_SSL_DEBUG_MSG(1, ("Receive unexpected handshake message.")); + MBEDTLS_SSL_PEND_FATAL_ALERT(MBEDTLS_SSL_ALERT_MSG_UNEXPECTED_MESSAGE, + MBEDTLS_ERR_SSL_UNEXPECTED_MESSAGE); + ret = MBEDTLS_ERR_SSL_UNEXPECTED_MESSAGE; + goto cleanup; + } + + /* + * Jump handshake header (4 bytes, see Section 4 of RFC 8446). + * ... + * HandshakeType msg_type; + * uint24 length; + * ... + */ + *buf = ssl->in_msg + 4; + *buf_len = ssl->in_hslen - 4; + +cleanup: + + return ret; +} + +int mbedtls_ssl_tls13_is_supported_versions_ext_present_in_exts( + mbedtls_ssl_context *ssl, + const unsigned char *buf, const unsigned char *end, + const unsigned char **supported_versions_data, + const unsigned char **supported_versions_data_end) +{ + const unsigned char *p = buf; + size_t extensions_len; + const unsigned char *extensions_end; + + *supported_versions_data = NULL; + *supported_versions_data_end = NULL; + + /* Case of no extension */ + if (p == end) { + return 0; + } + + /* ... + * Extension extensions; + * ... + * struct { + * ExtensionType extension_type; (2 bytes) + * opaque extension_data<0..2^16-1>; + * } Extension; + */ + MBEDTLS_SSL_CHK_BUF_READ_PTR(p, end, 2); + extensions_len = MBEDTLS_GET_UINT16_BE(p, 0); + p += 2; + + /* Check extensions do not go beyond the buffer of data. */ + MBEDTLS_SSL_CHK_BUF_READ_PTR(p, end, extensions_len); + extensions_end = p + extensions_len; + + while (p < extensions_end) { + unsigned int extension_type; + size_t extension_data_len; + + MBEDTLS_SSL_CHK_BUF_READ_PTR(p, extensions_end, 4); + extension_type = MBEDTLS_GET_UINT16_BE(p, 0); + extension_data_len = MBEDTLS_GET_UINT16_BE(p, 2); + p += 4; + MBEDTLS_SSL_CHK_BUF_READ_PTR(p, extensions_end, extension_data_len); + + if (extension_type == MBEDTLS_TLS_EXT_SUPPORTED_VERSIONS) { + *supported_versions_data = p; + *supported_versions_data_end = p + extension_data_len; + return 1; + } + p += extension_data_len; + } + + return 0; +} + +#if defined(MBEDTLS_SSL_TLS1_3_KEY_EXCHANGE_MODE_EPHEMERAL_ENABLED) +/* + * STATE HANDLING: Read CertificateVerify + */ +/* Macro to express the maximum length of the verify structure. + * + * The structure is computed per TLS 1.3 specification as: + * - 64 bytes of octet 32, + * - 33 bytes for the context string + * (which is either "TLS 1.3, client CertificateVerify" + * or "TLS 1.3, server CertificateVerify"), + * - 1 byte for the octet 0x0, which serves as a separator, + * - 32 or 48 bytes for the Transcript-Hash(Handshake Context, Certificate) + * (depending on the size of the transcript_hash) + * + * This results in a total size of + * - 130 bytes for a SHA256-based transcript hash, or + * (64 + 33 + 1 + 32 bytes) + * - 146 bytes for a SHA384-based transcript hash. + * (64 + 33 + 1 + 48 bytes) + * + */ +#define SSL_VERIFY_STRUCT_MAX_SIZE (64 + \ + 33 + \ + 1 + \ + MBEDTLS_TLS1_3_MD_MAX_SIZE \ + ) + +/* + * The ssl_tls13_create_verify_structure() creates the verify structure. + * As input, it requires the transcript hash. + * + * The caller has to ensure that the buffer has size at least + * SSL_VERIFY_STRUCT_MAX_SIZE bytes. + */ +static void ssl_tls13_create_verify_structure(const unsigned char *transcript_hash, + size_t transcript_hash_len, + unsigned char *verify_buffer, + size_t *verify_buffer_len, + int from) +{ + size_t idx; + + /* RFC 8446, Section 4.4.3: + * + * The digital signature [in the CertificateVerify message] is then + * computed over the concatenation of: + * - A string that consists of octet 32 (0x20) repeated 64 times + * - The context string + * - A single 0 byte which serves as the separator + * - The content to be signed + */ + memset(verify_buffer, 0x20, 64); + idx = 64; + + if (from == MBEDTLS_SSL_IS_CLIENT) { + memcpy(verify_buffer + idx, MBEDTLS_SSL_TLS1_3_LBL_WITH_LEN(client_cv)); + idx += MBEDTLS_SSL_TLS1_3_LBL_LEN(client_cv); + } else { /* from == MBEDTLS_SSL_IS_SERVER */ + memcpy(verify_buffer + idx, MBEDTLS_SSL_TLS1_3_LBL_WITH_LEN(server_cv)); + idx += MBEDTLS_SSL_TLS1_3_LBL_LEN(server_cv); + } + + verify_buffer[idx++] = 0x0; + + memcpy(verify_buffer + idx, transcript_hash, transcript_hash_len); + idx += transcript_hash_len; + + *verify_buffer_len = idx; +} + +MBEDTLS_CHECK_RETURN_CRITICAL +static int ssl_tls13_parse_certificate_verify(mbedtls_ssl_context *ssl, + const unsigned char *buf, + const unsigned char *end, + const unsigned char *verify_buffer, + size_t verify_buffer_len) +{ + int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED; + psa_status_t status = PSA_ERROR_CORRUPTION_DETECTED; + const unsigned char *p = buf; + uint16_t algorithm; + size_t signature_len; + mbedtls_pk_type_t sig_alg; + mbedtls_md_type_t md_alg; + psa_algorithm_t hash_alg = PSA_ALG_NONE; + unsigned char verify_hash[PSA_HASH_MAX_SIZE]; + size_t verify_hash_len; + + void const *options = NULL; +#if defined(MBEDTLS_X509_RSASSA_PSS_SUPPORT) + mbedtls_pk_rsassa_pss_options rsassa_pss_options; +#endif /* MBEDTLS_X509_RSASSA_PSS_SUPPORT */ + + /* + * struct { + * SignatureScheme algorithm; + * opaque signature<0..2^16-1>; + * } CertificateVerify; + */ + MBEDTLS_SSL_CHK_BUF_READ_PTR(p, end, 2); + algorithm = MBEDTLS_GET_UINT16_BE(p, 0); + p += 2; + + /* RFC 8446 section 4.4.3 + * + * If the CertificateVerify message is sent by a server, the signature + * algorithm MUST be one offered in the client's "signature_algorithms" + * extension unless no valid certificate chain can be produced without + * unsupported algorithms + * + * RFC 8446 section 4.4.2.2 + * + * If the client cannot construct an acceptable chain using the provided + * certificates and decides to abort the handshake, then it MUST abort the + * handshake with an appropriate certificate-related alert + * (by default, "unsupported_certificate"). + * + * Check if algorithm is an offered signature algorithm. + */ + if (!mbedtls_ssl_sig_alg_is_offered(ssl, algorithm)) { + /* algorithm not in offered signature algorithms list */ + MBEDTLS_SSL_DEBUG_MSG(1, ("Received signature algorithm(%04x) is not " + "offered.", + (unsigned int) algorithm)); + goto error; + } + + if (mbedtls_ssl_get_pk_type_and_md_alg_from_sig_alg( + algorithm, &sig_alg, &md_alg) != 0) { + goto error; + } + + hash_alg = mbedtls_md_psa_alg_from_type(md_alg); + if (hash_alg == 0) { + goto error; + } + + MBEDTLS_SSL_DEBUG_MSG(3, ("Certificate Verify: Signature algorithm ( %04x )", + (unsigned int) algorithm)); + + /* + * Check the certificate's key type matches the signature alg + */ + if (!mbedtls_pk_can_do(&ssl->session_negotiate->peer_cert->pk, sig_alg)) { + MBEDTLS_SSL_DEBUG_MSG(1, ("signature algorithm doesn't match cert key")); + goto error; + } + + MBEDTLS_SSL_CHK_BUF_READ_PTR(p, end, 2); + signature_len = MBEDTLS_GET_UINT16_BE(p, 0); + p += 2; + MBEDTLS_SSL_CHK_BUF_READ_PTR(p, end, signature_len); + + status = psa_hash_compute(hash_alg, + verify_buffer, + verify_buffer_len, + verify_hash, + sizeof(verify_hash), + &verify_hash_len); + if (status != PSA_SUCCESS) { + MBEDTLS_SSL_DEBUG_RET(1, "hash computation PSA error", status); + goto error; + } + + MBEDTLS_SSL_DEBUG_BUF(3, "verify hash", verify_hash, verify_hash_len); +#if defined(MBEDTLS_X509_RSASSA_PSS_SUPPORT) + if (sig_alg == MBEDTLS_PK_RSASSA_PSS) { + rsassa_pss_options.mgf1_hash_id = md_alg; + + rsassa_pss_options.expected_salt_len = PSA_HASH_LENGTH(hash_alg); + options = (const void *) &rsassa_pss_options; + } +#endif /* MBEDTLS_X509_RSASSA_PSS_SUPPORT */ + + if ((ret = mbedtls_pk_verify_ext(sig_alg, options, + &ssl->session_negotiate->peer_cert->pk, + md_alg, verify_hash, verify_hash_len, + p, signature_len)) == 0) { + return 0; + } + MBEDTLS_SSL_DEBUG_RET(1, "mbedtls_pk_verify_ext", ret); + +error: + /* RFC 8446 section 4.4.3 + * + * If the verification fails, the receiver MUST terminate the handshake + * with a "decrypt_error" alert. + */ + MBEDTLS_SSL_PEND_FATAL_ALERT(MBEDTLS_SSL_ALERT_MSG_DECRYPT_ERROR, + MBEDTLS_ERR_SSL_HANDSHAKE_FAILURE); + return MBEDTLS_ERR_SSL_HANDSHAKE_FAILURE; + +} +#endif /* MBEDTLS_SSL_TLS1_3_KEY_EXCHANGE_MODE_EPHEMERAL_ENABLED */ + +int mbedtls_ssl_tls13_process_certificate_verify(mbedtls_ssl_context *ssl) +{ + +#if defined(MBEDTLS_SSL_TLS1_3_KEY_EXCHANGE_MODE_EPHEMERAL_ENABLED) + int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED; + unsigned char verify_buffer[SSL_VERIFY_STRUCT_MAX_SIZE]; + size_t verify_buffer_len; + unsigned char transcript[MBEDTLS_TLS1_3_MD_MAX_SIZE]; + size_t transcript_len; + unsigned char *buf; + size_t buf_len; + + MBEDTLS_SSL_DEBUG_MSG(2, ("=> parse certificate verify")); + + MBEDTLS_SSL_PROC_CHK( + mbedtls_ssl_tls13_fetch_handshake_msg( + ssl, MBEDTLS_SSL_HS_CERTIFICATE_VERIFY, &buf, &buf_len)); + + /* Need to calculate the hash of the transcript first + * before reading the message since otherwise it gets + * included in the transcript + */ + ret = mbedtls_ssl_get_handshake_transcript( + ssl, + (mbedtls_md_type_t) ssl->handshake->ciphersuite_info->mac, + transcript, sizeof(transcript), + &transcript_len); + if (ret != 0) { + MBEDTLS_SSL_PEND_FATAL_ALERT( + MBEDTLS_SSL_ALERT_MSG_INTERNAL_ERROR, + MBEDTLS_ERR_SSL_INTERNAL_ERROR); + return ret; + } + + MBEDTLS_SSL_DEBUG_BUF(3, "handshake hash", transcript, transcript_len); + + /* Create verify structure */ + ssl_tls13_create_verify_structure(transcript, + transcript_len, + verify_buffer, + &verify_buffer_len, + (ssl->conf->endpoint == MBEDTLS_SSL_IS_CLIENT) ? + MBEDTLS_SSL_IS_SERVER : + MBEDTLS_SSL_IS_CLIENT); + + /* Process the message contents */ + MBEDTLS_SSL_PROC_CHK(ssl_tls13_parse_certificate_verify( + ssl, buf, buf + buf_len, + verify_buffer, verify_buffer_len)); + + MBEDTLS_SSL_PROC_CHK(mbedtls_ssl_add_hs_msg_to_checksum( + ssl, MBEDTLS_SSL_HS_CERTIFICATE_VERIFY, + buf, buf_len)); + +cleanup: + + MBEDTLS_SSL_DEBUG_MSG(2, ("<= parse certificate verify")); + MBEDTLS_SSL_DEBUG_RET(1, "mbedtls_ssl_tls13_process_certificate_verify", ret); + return ret; +#else + ((void) ssl); + MBEDTLS_SSL_DEBUG_MSG(1, ("should never happen")); + return MBEDTLS_ERR_SSL_INTERNAL_ERROR; +#endif /* MBEDTLS_SSL_TLS1_3_KEY_EXCHANGE_MODE_EPHEMERAL_ENABLED */ +} + +/* + * + * STATE HANDLING: Incoming Certificate. + * + */ + +#if defined(MBEDTLS_SSL_TLS1_3_KEY_EXCHANGE_MODE_EPHEMERAL_ENABLED) +#if defined(MBEDTLS_SSL_KEEP_PEER_CERTIFICATE) +/* + * Structure of Certificate message: + * + * enum { + * X509(0), + * RawPublicKey(2), + * (255) + * } CertificateType; + * + * struct { + * select (certificate_type) { + * case RawPublicKey: + * * From RFC 7250 ASN.1_subjectPublicKeyInfo * + * opaque ASN1_subjectPublicKeyInfo<1..2^24-1>; + * case X509: + * opaque cert_data<1..2^24-1>; + * }; + * Extension extensions<0..2^16-1>; + * } CertificateEntry; + * + * struct { + * opaque certificate_request_context<0..2^8-1>; + * CertificateEntry certificate_list<0..2^24-1>; + * } Certificate; + * + */ + +/* Parse certificate chain send by the server. */ +MBEDTLS_CHECK_RETURN_CRITICAL +MBEDTLS_STATIC_TESTABLE +int mbedtls_ssl_tls13_parse_certificate(mbedtls_ssl_context *ssl, + const unsigned char *buf, + const unsigned char *end) +{ + int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED; + size_t certificate_request_context_len = 0; + size_t certificate_list_len = 0; + const unsigned char *p = buf; + const unsigned char *certificate_list_end; + mbedtls_ssl_handshake_params *handshake = ssl->handshake; + + MBEDTLS_SSL_CHK_BUF_READ_PTR(p, end, 4); + certificate_request_context_len = p[0]; + certificate_list_len = MBEDTLS_GET_UINT24_BE(p, 1); + p += 4; + + /* In theory, the certificate list can be up to 2^24 Bytes, but we don't + * support anything beyond 2^16 = 64K. + */ + if ((certificate_request_context_len != 0) || + (certificate_list_len >= 0x10000)) { + MBEDTLS_SSL_DEBUG_MSG(1, ("bad certificate message")); + MBEDTLS_SSL_PEND_FATAL_ALERT(MBEDTLS_SSL_ALERT_MSG_DECODE_ERROR, + MBEDTLS_ERR_SSL_DECODE_ERROR); + return MBEDTLS_ERR_SSL_DECODE_ERROR; + } + + /* In case we tried to reuse a session but it failed */ + if (ssl->session_negotiate->peer_cert != NULL) { + mbedtls_x509_crt_free(ssl->session_negotiate->peer_cert); + mbedtls_free(ssl->session_negotiate->peer_cert); + } + + if (certificate_list_len == 0) { + ssl->session_negotiate->peer_cert = NULL; + ret = 0; + goto exit; + } + + if ((ssl->session_negotiate->peer_cert = + mbedtls_calloc(1, sizeof(mbedtls_x509_crt))) == NULL) { + MBEDTLS_SSL_DEBUG_MSG(1, ("alloc( %" MBEDTLS_PRINTF_SIZET " bytes ) failed", + sizeof(mbedtls_x509_crt))); + MBEDTLS_SSL_PEND_FATAL_ALERT(MBEDTLS_SSL_ALERT_MSG_INTERNAL_ERROR, + MBEDTLS_ERR_SSL_ALLOC_FAILED); + return MBEDTLS_ERR_SSL_ALLOC_FAILED; + } + + mbedtls_x509_crt_init(ssl->session_negotiate->peer_cert); + + MBEDTLS_SSL_CHK_BUF_READ_PTR(p, end, certificate_list_len); + certificate_list_end = p + certificate_list_len; + while (p < certificate_list_end) { + size_t cert_data_len, extensions_len; + const unsigned char *extensions_end; + + MBEDTLS_SSL_CHK_BUF_READ_PTR(p, certificate_list_end, 3); + cert_data_len = MBEDTLS_GET_UINT24_BE(p, 0); + p += 3; + + /* In theory, the CRT can be up to 2^24 Bytes, but we don't support + * anything beyond 2^16 = 64K. Otherwise as in the TLS 1.2 code, + * check that we have a minimum of 128 bytes of data, this is not + * clear why we need that though. + */ + if ((cert_data_len < 128) || (cert_data_len >= 0x10000)) { + MBEDTLS_SSL_DEBUG_MSG(1, ("bad Certificate message")); + MBEDTLS_SSL_PEND_FATAL_ALERT(MBEDTLS_SSL_ALERT_MSG_DECODE_ERROR, + MBEDTLS_ERR_SSL_DECODE_ERROR); + return MBEDTLS_ERR_SSL_DECODE_ERROR; + } + + MBEDTLS_SSL_CHK_BUF_READ_PTR(p, certificate_list_end, cert_data_len); + ret = mbedtls_x509_crt_parse_der(ssl->session_negotiate->peer_cert, + p, cert_data_len); + + switch (ret) { + case 0: /*ok*/ + break; + case MBEDTLS_ERR_X509_UNKNOWN_SIG_ALG + MBEDTLS_ERR_OID_NOT_FOUND: + /* Ignore certificate with an unknown algorithm: maybe a + prior certificate was already trusted. */ + break; + + case MBEDTLS_ERR_X509_ALLOC_FAILED: + MBEDTLS_SSL_PEND_FATAL_ALERT(MBEDTLS_SSL_ALERT_MSG_INTERNAL_ERROR, + MBEDTLS_ERR_X509_ALLOC_FAILED); + MBEDTLS_SSL_DEBUG_RET(1, " mbedtls_x509_crt_parse_der", ret); + return ret; + + case MBEDTLS_ERR_X509_UNKNOWN_VERSION: + MBEDTLS_SSL_PEND_FATAL_ALERT(MBEDTLS_SSL_ALERT_MSG_UNSUPPORTED_CERT, + MBEDTLS_ERR_X509_UNKNOWN_VERSION); + MBEDTLS_SSL_DEBUG_RET(1, " mbedtls_x509_crt_parse_der", ret); + return ret; + + default: + MBEDTLS_SSL_PEND_FATAL_ALERT(MBEDTLS_SSL_ALERT_MSG_BAD_CERT, + ret); + MBEDTLS_SSL_DEBUG_RET(1, " mbedtls_x509_crt_parse_der", ret); + return ret; + } + + p += cert_data_len; + + /* Certificate extensions length */ + MBEDTLS_SSL_CHK_BUF_READ_PTR(p, certificate_list_end, 2); + extensions_len = MBEDTLS_GET_UINT16_BE(p, 0); + p += 2; + MBEDTLS_SSL_CHK_BUF_READ_PTR(p, certificate_list_end, extensions_len); + + extensions_end = p + extensions_len; + handshake->received_extensions = MBEDTLS_SSL_EXT_MASK_NONE; + + while (p < extensions_end) { + unsigned int extension_type; + size_t extension_data_len; + + /* + * struct { + * ExtensionType extension_type; (2 bytes) + * opaque extension_data<0..2^16-1>; + * } Extension; + */ + MBEDTLS_SSL_CHK_BUF_READ_PTR(p, extensions_end, 4); + extension_type = MBEDTLS_GET_UINT16_BE(p, 0); + extension_data_len = MBEDTLS_GET_UINT16_BE(p, 2); + p += 4; + + MBEDTLS_SSL_CHK_BUF_READ_PTR(p, extensions_end, extension_data_len); + + ret = mbedtls_ssl_tls13_check_received_extension( + ssl, MBEDTLS_SSL_HS_CERTIFICATE, extension_type, + MBEDTLS_SSL_TLS1_3_ALLOWED_EXTS_OF_CT); + if (ret != 0) { + return ret; + } + + switch (extension_type) { + default: + MBEDTLS_SSL_PRINT_EXT( + 3, MBEDTLS_SSL_HS_CERTIFICATE, + extension_type, "( ignored )"); + break; + } + + p += extension_data_len; + } + + MBEDTLS_SSL_PRINT_EXTS(3, MBEDTLS_SSL_HS_CERTIFICATE, + handshake->received_extensions); + } + +exit: + /* Check that all the message is consumed. */ + if (p != end) { + MBEDTLS_SSL_DEBUG_MSG(1, ("bad Certificate message")); + MBEDTLS_SSL_PEND_FATAL_ALERT(MBEDTLS_SSL_ALERT_MSG_DECODE_ERROR, + MBEDTLS_ERR_SSL_DECODE_ERROR); + return MBEDTLS_ERR_SSL_DECODE_ERROR; + } + + MBEDTLS_SSL_DEBUG_CRT(3, "peer certificate", + ssl->session_negotiate->peer_cert); + + return ret; +} +#else +MBEDTLS_CHECK_RETURN_CRITICAL +MBEDTLS_STATIC_TESTABLE +int mbedtls_ssl_tls13_parse_certificate(mbedtls_ssl_context *ssl, + const unsigned char *buf, + const unsigned char *end) +{ + ((void) ssl); + ((void) buf); + ((void) end); + return MBEDTLS_ERR_SSL_FEATURE_UNAVAILABLE; +} +#endif /* MBEDTLS_SSL_KEEP_PEER_CERTIFICATE */ +#endif /* MBEDTLS_SSL_TLS1_3_KEY_EXCHANGE_MODE_EPHEMERAL_ENABLED */ + +#if defined(MBEDTLS_SSL_TLS1_3_KEY_EXCHANGE_MODE_EPHEMERAL_ENABLED) +#if defined(MBEDTLS_SSL_KEEP_PEER_CERTIFICATE) +/* Validate certificate chain sent by the server. */ +MBEDTLS_CHECK_RETURN_CRITICAL +static int ssl_tls13_validate_certificate(mbedtls_ssl_context *ssl) +{ + int ret = 0; + int authmode = MBEDTLS_SSL_VERIFY_REQUIRED; + mbedtls_x509_crt *ca_chain; + mbedtls_x509_crl *ca_crl; + const char *ext_oid; + size_t ext_len; + uint32_t verify_result = 0; + + /* If SNI was used, overwrite authentication mode + * from the configuration. */ +#if defined(MBEDTLS_SSL_SRV_C) + if (ssl->conf->endpoint == MBEDTLS_SSL_IS_SERVER) { +#if defined(MBEDTLS_SSL_SERVER_NAME_INDICATION) + if (ssl->handshake->sni_authmode != MBEDTLS_SSL_VERIFY_UNSET) { + authmode = ssl->handshake->sni_authmode; + } else +#endif + authmode = ssl->conf->authmode; + } +#endif + + /* + * If the peer hasn't sent a certificate ( i.e. it sent + * an empty certificate chain ), this is reflected in the peer CRT + * structure being unset. + * Check for that and handle it depending on the + * authentication mode. + */ + if (ssl->session_negotiate->peer_cert == NULL) { + MBEDTLS_SSL_DEBUG_MSG(1, ("peer has no certificate")); + +#if defined(MBEDTLS_SSL_SRV_C) + if (ssl->conf->endpoint == MBEDTLS_SSL_IS_SERVER) { + /* The client was asked for a certificate but didn't send + * one. The client should know what's going on, so we + * don't send an alert. + */ + ssl->session_negotiate->verify_result = MBEDTLS_X509_BADCERT_MISSING; + if (authmode == MBEDTLS_SSL_VERIFY_OPTIONAL) { + return 0; + } else { + MBEDTLS_SSL_PEND_FATAL_ALERT( + MBEDTLS_SSL_ALERT_MSG_NO_CERT, + MBEDTLS_ERR_SSL_NO_CLIENT_CERTIFICATE); + return MBEDTLS_ERR_SSL_NO_CLIENT_CERTIFICATE; + } + } +#endif /* MBEDTLS_SSL_SRV_C */ + +#if defined(MBEDTLS_SSL_CLI_C) + if (ssl->conf->endpoint == MBEDTLS_SSL_IS_CLIENT) { + MBEDTLS_SSL_PEND_FATAL_ALERT(MBEDTLS_SSL_ALERT_MSG_NO_CERT, + MBEDTLS_ERR_SSL_FATAL_ALERT_MESSAGE); + return MBEDTLS_ERR_SSL_FATAL_ALERT_MESSAGE; + } +#endif /* MBEDTLS_SSL_CLI_C */ + } + +#if defined(MBEDTLS_SSL_SERVER_NAME_INDICATION) + if (ssl->handshake->sni_ca_chain != NULL) { + ca_chain = ssl->handshake->sni_ca_chain; + ca_crl = ssl->handshake->sni_ca_crl; + } else +#endif /* MBEDTLS_SSL_SERVER_NAME_INDICATION */ + { + ca_chain = ssl->conf->ca_chain; + ca_crl = ssl->conf->ca_crl; + } + + /* + * Main check: verify certificate + */ + ret = mbedtls_x509_crt_verify_with_profile( + ssl->session_negotiate->peer_cert, + ca_chain, ca_crl, + ssl->conf->cert_profile, + ssl->hostname, + &verify_result, + ssl->conf->f_vrfy, ssl->conf->p_vrfy); + + if (ret != 0) { + MBEDTLS_SSL_DEBUG_RET(1, "x509_verify_cert", ret); + } + + /* + * Secondary checks: always done, but change 'ret' only if it was 0 + */ + if (ssl->conf->endpoint == MBEDTLS_SSL_IS_CLIENT) { + ext_oid = MBEDTLS_OID_SERVER_AUTH; + ext_len = MBEDTLS_OID_SIZE(MBEDTLS_OID_SERVER_AUTH); + } else { + ext_oid = MBEDTLS_OID_CLIENT_AUTH; + ext_len = MBEDTLS_OID_SIZE(MBEDTLS_OID_CLIENT_AUTH); + } + + if ((mbedtls_x509_crt_check_key_usage( + ssl->session_negotiate->peer_cert, + MBEDTLS_X509_KU_DIGITAL_SIGNATURE) != 0) || + (mbedtls_x509_crt_check_extended_key_usage( + ssl->session_negotiate->peer_cert, + ext_oid, ext_len) != 0)) { + MBEDTLS_SSL_DEBUG_MSG(1, ("bad certificate (usage extensions)")); + if (ret == 0) { + ret = MBEDTLS_ERR_SSL_BAD_CERTIFICATE; + } + } + + /* mbedtls_x509_crt_verify_with_profile is supposed to report a + * verification failure through MBEDTLS_ERR_X509_CERT_VERIFY_FAILED, + * with details encoded in the verification flags. All other kinds + * of error codes, including those from the user provided f_vrfy + * functions, are treated as fatal and lead to a failure of + * mbedtls_ssl_tls13_parse_certificate even if verification was optional. + */ + if (authmode == MBEDTLS_SSL_VERIFY_OPTIONAL && + (ret == MBEDTLS_ERR_X509_CERT_VERIFY_FAILED || + ret == MBEDTLS_ERR_SSL_BAD_CERTIFICATE)) { + ret = 0; + } + + if (ca_chain == NULL && authmode == MBEDTLS_SSL_VERIFY_REQUIRED) { + MBEDTLS_SSL_DEBUG_MSG(1, ("got no CA chain")); + ret = MBEDTLS_ERR_SSL_CA_CHAIN_REQUIRED; + } + + if (ret != 0) { + /* The certificate may have been rejected for several reasons. + Pick one and send the corresponding alert. Which alert to send + may be a subject of debate in some cases. */ + if (verify_result & MBEDTLS_X509_BADCERT_OTHER) { + MBEDTLS_SSL_PEND_FATAL_ALERT( + MBEDTLS_SSL_ALERT_MSG_ACCESS_DENIED, ret); + } else if (verify_result & MBEDTLS_X509_BADCERT_CN_MISMATCH) { + MBEDTLS_SSL_PEND_FATAL_ALERT(MBEDTLS_SSL_ALERT_MSG_BAD_CERT, ret); + } else if (verify_result & (MBEDTLS_X509_BADCERT_KEY_USAGE | + MBEDTLS_X509_BADCERT_EXT_KEY_USAGE | + MBEDTLS_X509_BADCERT_NS_CERT_TYPE | + MBEDTLS_X509_BADCERT_BAD_PK | + MBEDTLS_X509_BADCERT_BAD_KEY)) { + MBEDTLS_SSL_PEND_FATAL_ALERT( + MBEDTLS_SSL_ALERT_MSG_UNSUPPORTED_CERT, ret); + } else if (verify_result & MBEDTLS_X509_BADCERT_EXPIRED) { + MBEDTLS_SSL_PEND_FATAL_ALERT( + MBEDTLS_SSL_ALERT_MSG_CERT_EXPIRED, ret); + } else if (verify_result & MBEDTLS_X509_BADCERT_REVOKED) { + MBEDTLS_SSL_PEND_FATAL_ALERT( + MBEDTLS_SSL_ALERT_MSG_CERT_REVOKED, ret); + } else if (verify_result & MBEDTLS_X509_BADCERT_NOT_TRUSTED) { + MBEDTLS_SSL_PEND_FATAL_ALERT(MBEDTLS_SSL_ALERT_MSG_UNKNOWN_CA, ret); + } else { + MBEDTLS_SSL_PEND_FATAL_ALERT( + MBEDTLS_SSL_ALERT_MSG_CERT_UNKNOWN, ret); + } + } + +#if defined(MBEDTLS_DEBUG_C) + if (verify_result != 0) { + MBEDTLS_SSL_DEBUG_MSG(3, ("! Certificate verification flags %08x", + (unsigned int) verify_result)); + } else { + MBEDTLS_SSL_DEBUG_MSG(3, ("Certificate verification flags clear")); + } +#endif /* MBEDTLS_DEBUG_C */ + + ssl->session_negotiate->verify_result = verify_result; + return ret; +} +#else /* MBEDTLS_SSL_KEEP_PEER_CERTIFICATE */ +MBEDTLS_CHECK_RETURN_CRITICAL +static int ssl_tls13_validate_certificate(mbedtls_ssl_context *ssl) +{ + ((void) ssl); + return MBEDTLS_ERR_SSL_FEATURE_UNAVAILABLE; +} +#endif /* MBEDTLS_SSL_KEEP_PEER_CERTIFICATE */ +#endif /* MBEDTLS_SSL_TLS1_3_KEY_EXCHANGE_MODE_EPHEMERAL_ENABLED */ + +int mbedtls_ssl_tls13_process_certificate(mbedtls_ssl_context *ssl) +{ + int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED; + MBEDTLS_SSL_DEBUG_MSG(2, ("=> parse certificate")); + +#if defined(MBEDTLS_SSL_TLS1_3_KEY_EXCHANGE_MODE_EPHEMERAL_ENABLED) + unsigned char *buf; + size_t buf_len; + + MBEDTLS_SSL_PROC_CHK(mbedtls_ssl_tls13_fetch_handshake_msg( + ssl, MBEDTLS_SSL_HS_CERTIFICATE, + &buf, &buf_len)); + + /* Parse the certificate chain sent by the peer. */ + MBEDTLS_SSL_PROC_CHK(mbedtls_ssl_tls13_parse_certificate(ssl, buf, + buf + buf_len)); + /* Validate the certificate chain and set the verification results. */ + MBEDTLS_SSL_PROC_CHK(ssl_tls13_validate_certificate(ssl)); + + MBEDTLS_SSL_PROC_CHK(mbedtls_ssl_add_hs_msg_to_checksum( + ssl, MBEDTLS_SSL_HS_CERTIFICATE, buf, buf_len)); + +cleanup: +#else /* MBEDTLS_SSL_TLS1_3_KEY_EXCHANGE_MODE_EPHEMERAL_ENABLED */ + (void) ssl; +#endif /* MBEDTLS_SSL_TLS1_3_KEY_EXCHANGE_MODE_EPHEMERAL_ENABLED */ + + MBEDTLS_SSL_DEBUG_MSG(2, ("<= parse certificate")); + return ret; +} +#if defined(MBEDTLS_SSL_TLS1_3_KEY_EXCHANGE_MODE_EPHEMERAL_ENABLED) +/* + * enum { + * X509(0), + * RawPublicKey(2), + * (255) + * } CertificateType; + * + * struct { + * select (certificate_type) { + * case RawPublicKey: + * // From RFC 7250 ASN.1_subjectPublicKeyInfo + * opaque ASN1_subjectPublicKeyInfo<1..2^24-1>; + * + * case X509: + * opaque cert_data<1..2^24-1>; + * }; + * Extension extensions<0..2^16-1>; + * } CertificateEntry; + * + * struct { + * opaque certificate_request_context<0..2^8-1>; + * CertificateEntry certificate_list<0..2^24-1>; + * } Certificate; + */ +MBEDTLS_CHECK_RETURN_CRITICAL +static int ssl_tls13_write_certificate_body(mbedtls_ssl_context *ssl, + unsigned char *buf, + unsigned char *end, + size_t *out_len) +{ + const mbedtls_x509_crt *crt = mbedtls_ssl_own_cert(ssl); + unsigned char *p = buf; + unsigned char *certificate_request_context = + ssl->handshake->certificate_request_context; + unsigned char certificate_request_context_len = + ssl->handshake->certificate_request_context_len; + unsigned char *p_certificate_list_len; + + + /* ... + * opaque certificate_request_context<0..2^8-1>; + * ... + */ + MBEDTLS_SSL_CHK_BUF_PTR(p, end, certificate_request_context_len + 1); + *p++ = certificate_request_context_len; + if (certificate_request_context_len > 0) { + memcpy(p, certificate_request_context, certificate_request_context_len); + p += certificate_request_context_len; + } + + /* ... + * CertificateEntry certificate_list<0..2^24-1>; + * ... + */ + MBEDTLS_SSL_CHK_BUF_PTR(p, end, 3); + p_certificate_list_len = p; + p += 3; + + MBEDTLS_SSL_DEBUG_CRT(3, "own certificate", crt); + + while (crt != NULL) { + size_t cert_data_len = crt->raw.len; + + MBEDTLS_SSL_CHK_BUF_PTR(p, end, cert_data_len + 3 + 2); + MBEDTLS_PUT_UINT24_BE(cert_data_len, p, 0); + p += 3; + + memcpy(p, crt->raw.p, cert_data_len); + p += cert_data_len; + crt = crt->next; + + /* Currently, we don't have any certificate extensions defined. + * Hence, we are sending an empty extension with length zero. + */ + MBEDTLS_PUT_UINT16_BE(0, p, 0); + p += 2; + } + + MBEDTLS_PUT_UINT24_BE(p - p_certificate_list_len - 3, + p_certificate_list_len, 0); + + *out_len = p - buf; + + MBEDTLS_SSL_PRINT_EXTS( + 3, MBEDTLS_SSL_HS_CERTIFICATE, ssl->handshake->sent_extensions); + + return 0; +} + +int mbedtls_ssl_tls13_write_certificate(mbedtls_ssl_context *ssl) +{ + int ret; + unsigned char *buf; + size_t buf_len, msg_len; + + MBEDTLS_SSL_DEBUG_MSG(2, ("=> write certificate")); + + MBEDTLS_SSL_PROC_CHK(mbedtls_ssl_start_handshake_msg( + ssl, MBEDTLS_SSL_HS_CERTIFICATE, &buf, &buf_len)); + + MBEDTLS_SSL_PROC_CHK(ssl_tls13_write_certificate_body(ssl, + buf, + buf + buf_len, + &msg_len)); + + MBEDTLS_SSL_PROC_CHK(mbedtls_ssl_add_hs_msg_to_checksum( + ssl, MBEDTLS_SSL_HS_CERTIFICATE, buf, msg_len)); + + MBEDTLS_SSL_PROC_CHK(mbedtls_ssl_finish_handshake_msg( + ssl, buf_len, msg_len)); +cleanup: + + MBEDTLS_SSL_DEBUG_MSG(2, ("<= write certificate")); + return ret; +} + +/* + * STATE HANDLING: Output Certificate Verify + */ +int mbedtls_ssl_tls13_check_sig_alg_cert_key_match(uint16_t sig_alg, + mbedtls_pk_context *key) +{ + mbedtls_pk_type_t pk_type = (mbedtls_pk_type_t) mbedtls_ssl_sig_from_pk(key); + size_t key_size = mbedtls_pk_get_bitlen(key); + + switch (pk_type) { + case MBEDTLS_SSL_SIG_ECDSA: + switch (key_size) { + case 256: + return + sig_alg == MBEDTLS_TLS1_3_SIG_ECDSA_SECP256R1_SHA256; + + case 384: + return + sig_alg == MBEDTLS_TLS1_3_SIG_ECDSA_SECP384R1_SHA384; + + case 521: + return + sig_alg == MBEDTLS_TLS1_3_SIG_ECDSA_SECP521R1_SHA512; + default: + break; + } + break; + + case MBEDTLS_SSL_SIG_RSA: + switch (sig_alg) { + case MBEDTLS_TLS1_3_SIG_RSA_PSS_RSAE_SHA256: /* Intentional fallthrough */ + case MBEDTLS_TLS1_3_SIG_RSA_PSS_RSAE_SHA384: /* Intentional fallthrough */ + case MBEDTLS_TLS1_3_SIG_RSA_PSS_RSAE_SHA512: + return 1; + + default: + break; + } + break; + + default: + break; + } + + return 0; +} + +MBEDTLS_CHECK_RETURN_CRITICAL +static int ssl_tls13_write_certificate_verify_body(mbedtls_ssl_context *ssl, + unsigned char *buf, + unsigned char *end, + size_t *out_len) +{ + int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED; + unsigned char *p = buf; + mbedtls_pk_context *own_key; + + unsigned char handshake_hash[MBEDTLS_TLS1_3_MD_MAX_SIZE]; + size_t handshake_hash_len; + unsigned char verify_buffer[SSL_VERIFY_STRUCT_MAX_SIZE]; + size_t verify_buffer_len; + + uint16_t *sig_alg = ssl->handshake->received_sig_algs; + size_t signature_len = 0; + + *out_len = 0; + + own_key = mbedtls_ssl_own_key(ssl); + if (own_key == NULL) { + MBEDTLS_SSL_DEBUG_MSG(1, ("should never happen")); + return MBEDTLS_ERR_SSL_INTERNAL_ERROR; + } + + ret = mbedtls_ssl_get_handshake_transcript( + ssl, (mbedtls_md_type_t) ssl->handshake->ciphersuite_info->mac, + handshake_hash, sizeof(handshake_hash), &handshake_hash_len); + if (ret != 0) { + return ret; + } + + MBEDTLS_SSL_DEBUG_BUF(3, "handshake hash", + handshake_hash, + handshake_hash_len); + + ssl_tls13_create_verify_structure(handshake_hash, handshake_hash_len, + verify_buffer, &verify_buffer_len, + ssl->conf->endpoint); + + /* + * struct { + * SignatureScheme algorithm; + * opaque signature<0..2^16-1>; + * } CertificateVerify; + */ + /* Check there is space for the algorithm identifier (2 bytes) and the + * signature length (2 bytes). + */ + MBEDTLS_SSL_CHK_BUF_PTR(p, end, 4); + + for (; *sig_alg != MBEDTLS_TLS1_3_SIG_NONE; sig_alg++) { + psa_status_t status = PSA_ERROR_CORRUPTION_DETECTED; + mbedtls_pk_type_t pk_type = MBEDTLS_PK_NONE; + mbedtls_md_type_t md_alg = MBEDTLS_MD_NONE; + psa_algorithm_t psa_algorithm = PSA_ALG_NONE; + unsigned char verify_hash[PSA_HASH_MAX_SIZE]; + size_t verify_hash_len; + + if (!mbedtls_ssl_sig_alg_is_offered(ssl, *sig_alg)) { + continue; + } + + if (!mbedtls_ssl_tls13_sig_alg_for_cert_verify_is_supported(*sig_alg)) { + continue; + } + + if (!mbedtls_ssl_tls13_check_sig_alg_cert_key_match(*sig_alg, own_key)) { + continue; + } + + if (mbedtls_ssl_get_pk_type_and_md_alg_from_sig_alg( + *sig_alg, &pk_type, &md_alg) != 0) { + return MBEDTLS_ERR_SSL_INTERNAL_ERROR; + } + + /* Hash verify buffer with indicated hash function */ + psa_algorithm = mbedtls_md_psa_alg_from_type(md_alg); + status = psa_hash_compute(psa_algorithm, + verify_buffer, + verify_buffer_len, + verify_hash, sizeof(verify_hash), + &verify_hash_len); + if (status != PSA_SUCCESS) { + return PSA_TO_MBEDTLS_ERR(status); + } + + MBEDTLS_SSL_DEBUG_BUF(3, "verify hash", verify_hash, verify_hash_len); + + if ((ret = mbedtls_pk_sign_ext(pk_type, own_key, + md_alg, verify_hash, verify_hash_len, + p + 4, (size_t) (end - (p + 4)), &signature_len, + ssl->conf->f_rng, ssl->conf->p_rng)) != 0) { + MBEDTLS_SSL_DEBUG_MSG(2, ("CertificateVerify signature failed with %s", + mbedtls_ssl_sig_alg_to_str(*sig_alg))); + MBEDTLS_SSL_DEBUG_RET(2, "mbedtls_pk_sign_ext", ret); + + /* The signature failed. This is possible if the private key + * was not suitable for the signature operation as purposely we + * did not check its suitability completely. Let's try with + * another signature algorithm. + */ + continue; + } + + MBEDTLS_SSL_DEBUG_MSG(2, ("CertificateVerify signature with %s", + mbedtls_ssl_sig_alg_to_str(*sig_alg))); + + break; + } + + if (*sig_alg == MBEDTLS_TLS1_3_SIG_NONE) { + MBEDTLS_SSL_DEBUG_MSG(1, ("no suitable signature algorithm")); + MBEDTLS_SSL_PEND_FATAL_ALERT(MBEDTLS_SSL_ALERT_MSG_HANDSHAKE_FAILURE, + MBEDTLS_ERR_SSL_HANDSHAKE_FAILURE); + return MBEDTLS_ERR_SSL_HANDSHAKE_FAILURE; + } + + MBEDTLS_PUT_UINT16_BE(*sig_alg, p, 0); + MBEDTLS_PUT_UINT16_BE(signature_len, p, 2); + + *out_len = 4 + signature_len; + + return 0; +} + +int mbedtls_ssl_tls13_write_certificate_verify(mbedtls_ssl_context *ssl) +{ + int ret = 0; + unsigned char *buf; + size_t buf_len, msg_len; + + MBEDTLS_SSL_DEBUG_MSG(2, ("=> write certificate verify")); + + MBEDTLS_SSL_PROC_CHK(mbedtls_ssl_start_handshake_msg( + ssl, MBEDTLS_SSL_HS_CERTIFICATE_VERIFY, + &buf, &buf_len)); + + MBEDTLS_SSL_PROC_CHK(ssl_tls13_write_certificate_verify_body( + ssl, buf, buf + buf_len, &msg_len)); + + MBEDTLS_SSL_PROC_CHK(mbedtls_ssl_add_hs_msg_to_checksum( + ssl, MBEDTLS_SSL_HS_CERTIFICATE_VERIFY, + buf, msg_len)); + + MBEDTLS_SSL_PROC_CHK(mbedtls_ssl_finish_handshake_msg( + ssl, buf_len, msg_len)); + +cleanup: + + MBEDTLS_SSL_DEBUG_MSG(2, ("<= write certificate verify")); + return ret; +} + +#endif /* MBEDTLS_SSL_TLS1_3_KEY_EXCHANGE_MODE_EPHEMERAL_ENABLED */ + +/* + * + * STATE HANDLING: Incoming Finished message. + */ +/* + * Implementation + */ + +MBEDTLS_CHECK_RETURN_CRITICAL +static int ssl_tls13_preprocess_finished_message(mbedtls_ssl_context *ssl) +{ + int ret; + + ret = mbedtls_ssl_tls13_calculate_verify_data( + ssl, + ssl->handshake->state_local.finished_in.digest, + sizeof(ssl->handshake->state_local.finished_in.digest), + &ssl->handshake->state_local.finished_in.digest_len, + ssl->conf->endpoint == MBEDTLS_SSL_IS_CLIENT ? + MBEDTLS_SSL_IS_SERVER : MBEDTLS_SSL_IS_CLIENT); + if (ret != 0) { + MBEDTLS_SSL_DEBUG_RET(1, "mbedtls_ssl_tls13_calculate_verify_data", ret); + return ret; + } + + return 0; +} + +MBEDTLS_CHECK_RETURN_CRITICAL +static int ssl_tls13_parse_finished_message(mbedtls_ssl_context *ssl, + const unsigned char *buf, + const unsigned char *end) +{ + /* + * struct { + * opaque verify_data[Hash.length]; + * } Finished; + */ + const unsigned char *expected_verify_data = + ssl->handshake->state_local.finished_in.digest; + size_t expected_verify_data_len = + ssl->handshake->state_local.finished_in.digest_len; + /* Structural validation */ + if ((size_t) (end - buf) != expected_verify_data_len) { + MBEDTLS_SSL_DEBUG_MSG(1, ("bad finished message")); + + MBEDTLS_SSL_PEND_FATAL_ALERT(MBEDTLS_SSL_ALERT_MSG_DECODE_ERROR, + MBEDTLS_ERR_SSL_DECODE_ERROR); + return MBEDTLS_ERR_SSL_DECODE_ERROR; + } + + MBEDTLS_SSL_DEBUG_BUF(4, "verify_data (self-computed):", + expected_verify_data, + expected_verify_data_len); + MBEDTLS_SSL_DEBUG_BUF(4, "verify_data (received message):", buf, + expected_verify_data_len); + + /* Semantic validation */ + if (mbedtls_ct_memcmp(buf, + expected_verify_data, + expected_verify_data_len) != 0) { + MBEDTLS_SSL_DEBUG_MSG(1, ("bad finished message")); + + MBEDTLS_SSL_PEND_FATAL_ALERT(MBEDTLS_SSL_ALERT_MSG_DECRYPT_ERROR, + MBEDTLS_ERR_SSL_HANDSHAKE_FAILURE); + return MBEDTLS_ERR_SSL_HANDSHAKE_FAILURE; + } + return 0; +} + +int mbedtls_ssl_tls13_process_finished_message(mbedtls_ssl_context *ssl) +{ + int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED; + unsigned char *buf; + size_t buf_len; + + MBEDTLS_SSL_DEBUG_MSG(2, ("=> parse finished message")); + + MBEDTLS_SSL_PROC_CHK(mbedtls_ssl_tls13_fetch_handshake_msg( + ssl, MBEDTLS_SSL_HS_FINISHED, &buf, &buf_len)); + + /* Preprocessing step: Compute handshake digest */ + MBEDTLS_SSL_PROC_CHK(ssl_tls13_preprocess_finished_message(ssl)); + + MBEDTLS_SSL_PROC_CHK(ssl_tls13_parse_finished_message( + ssl, buf, buf + buf_len)); + + MBEDTLS_SSL_PROC_CHK(mbedtls_ssl_add_hs_msg_to_checksum( + ssl, MBEDTLS_SSL_HS_FINISHED, buf, buf_len)); + +cleanup: + + MBEDTLS_SSL_DEBUG_MSG(2, ("<= parse finished message")); + return ret; +} + +/* + * + * STATE HANDLING: Write and send Finished message. + * + */ +/* + * Implement + */ + +MBEDTLS_CHECK_RETURN_CRITICAL +static int ssl_tls13_prepare_finished_message(mbedtls_ssl_context *ssl) +{ + int ret; + + /* Compute transcript of handshake up to now. */ + ret = mbedtls_ssl_tls13_calculate_verify_data(ssl, + ssl->handshake->state_local.finished_out.digest, + sizeof(ssl->handshake->state_local.finished_out. + digest), + &ssl->handshake->state_local.finished_out.digest_len, + ssl->conf->endpoint); + + if (ret != 0) { + MBEDTLS_SSL_DEBUG_RET(1, "calculate_verify_data failed", ret); + return ret; + } + + return 0; +} + +MBEDTLS_CHECK_RETURN_CRITICAL +static int ssl_tls13_write_finished_message_body(mbedtls_ssl_context *ssl, + unsigned char *buf, + unsigned char *end, + size_t *out_len) +{ + size_t verify_data_len = ssl->handshake->state_local.finished_out.digest_len; + /* + * struct { + * opaque verify_data[Hash.length]; + * } Finished; + */ + MBEDTLS_SSL_CHK_BUF_PTR(buf, end, verify_data_len); + + memcpy(buf, ssl->handshake->state_local.finished_out.digest, + verify_data_len); + + *out_len = verify_data_len; + return 0; +} + +/* Main entry point: orchestrates the other functions */ +int mbedtls_ssl_tls13_write_finished_message(mbedtls_ssl_context *ssl) +{ + int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED; + unsigned char *buf; + size_t buf_len, msg_len; + + MBEDTLS_SSL_DEBUG_MSG(2, ("=> write finished message")); + + MBEDTLS_SSL_PROC_CHK(ssl_tls13_prepare_finished_message(ssl)); + + MBEDTLS_SSL_PROC_CHK(mbedtls_ssl_start_handshake_msg(ssl, + MBEDTLS_SSL_HS_FINISHED, &buf, &buf_len)); + + MBEDTLS_SSL_PROC_CHK(ssl_tls13_write_finished_message_body( + ssl, buf, buf + buf_len, &msg_len)); + + MBEDTLS_SSL_PROC_CHK(mbedtls_ssl_add_hs_msg_to_checksum(ssl, + MBEDTLS_SSL_HS_FINISHED, buf, msg_len)); + + MBEDTLS_SSL_PROC_CHK(mbedtls_ssl_finish_handshake_msg( + ssl, buf_len, msg_len)); +cleanup: + + MBEDTLS_SSL_DEBUG_MSG(2, ("<= write finished message")); + return ret; +} + +void mbedtls_ssl_tls13_handshake_wrapup(mbedtls_ssl_context *ssl) +{ + + MBEDTLS_SSL_DEBUG_MSG(3, ("=> handshake wrapup")); + + MBEDTLS_SSL_DEBUG_MSG(1, ("Switch to application keys for inbound traffic")); + mbedtls_ssl_set_inbound_transform(ssl, ssl->transform_application); + + MBEDTLS_SSL_DEBUG_MSG(1, ("Switch to application keys for outbound traffic")); + mbedtls_ssl_set_outbound_transform(ssl, ssl->transform_application); + + /* + * Free the previous session and switch to the current one. + */ + if (ssl->session) { + mbedtls_ssl_session_free(ssl->session); + mbedtls_free(ssl->session); + } + ssl->session = ssl->session_negotiate; + ssl->session_negotiate = NULL; + + MBEDTLS_SSL_DEBUG_MSG(3, ("<= handshake wrapup")); +} + +/* + * + * STATE HANDLING: Write ChangeCipherSpec + * + */ +#if defined(MBEDTLS_SSL_TLS1_3_COMPATIBILITY_MODE) +MBEDTLS_CHECK_RETURN_CRITICAL +static int ssl_tls13_write_change_cipher_spec_body(mbedtls_ssl_context *ssl, + unsigned char *buf, + unsigned char *end, + size_t *olen) +{ + ((void) ssl); + + MBEDTLS_SSL_CHK_BUF_PTR(buf, end, 1); + buf[0] = 1; + *olen = 1; + + return 0; +} + +int mbedtls_ssl_tls13_write_change_cipher_spec(mbedtls_ssl_context *ssl) +{ + int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED; + + MBEDTLS_SSL_DEBUG_MSG(2, ("=> write change cipher spec")); + + /* Only one CCS to send. */ + if (ssl->handshake->ccs_sent) { + ret = 0; + goto cleanup; + } + + /* Write CCS message */ + MBEDTLS_SSL_PROC_CHK(ssl_tls13_write_change_cipher_spec_body( + ssl, ssl->out_msg, + ssl->out_msg + MBEDTLS_SSL_OUT_CONTENT_LEN, + &ssl->out_msglen)); + + ssl->out_msgtype = MBEDTLS_SSL_MSG_CHANGE_CIPHER_SPEC; + + /* Dispatch message */ + MBEDTLS_SSL_PROC_CHK(mbedtls_ssl_write_record(ssl, 0)); + + ssl->handshake->ccs_sent = 1; + +cleanup: + + MBEDTLS_SSL_DEBUG_MSG(2, ("<= write change cipher spec")); + return ret; +} + +#endif /* MBEDTLS_SSL_TLS1_3_COMPATIBILITY_MODE */ + +/* Early Data Indication Extension + * + * struct { + * select ( Handshake.msg_type ) { + * case new_session_ticket: uint32 max_early_data_size; + * case client_hello: Empty; + * case encrypted_extensions: Empty; + * }; + * } EarlyDataIndication; + */ +#if defined(MBEDTLS_SSL_EARLY_DATA) +int mbedtls_ssl_tls13_write_early_data_ext(mbedtls_ssl_context *ssl, + int in_new_session_ticket, + unsigned char *buf, + const unsigned char *end, + size_t *out_len) +{ + unsigned char *p = buf; + +#if defined(MBEDTLS_SSL_SRV_C) + const size_t needed = in_new_session_ticket ? 8 : 4; +#else + const size_t needed = 4; + ((void) in_new_session_ticket); +#endif + + *out_len = 0; + + MBEDTLS_SSL_CHK_BUF_PTR(p, end, needed); + + MBEDTLS_PUT_UINT16_BE(MBEDTLS_TLS_EXT_EARLY_DATA, p, 0); + MBEDTLS_PUT_UINT16_BE(needed - 4, p, 2); + +#if defined(MBEDTLS_SSL_SRV_C) + if (in_new_session_ticket) { + MBEDTLS_PUT_UINT32_BE(ssl->conf->max_early_data_size, p, 4); + MBEDTLS_SSL_DEBUG_MSG( + 4, ("Sent max_early_data_size=%u", + (unsigned int) ssl->conf->max_early_data_size)); + } +#endif + + *out_len = needed; + + mbedtls_ssl_tls13_set_hs_sent_ext_mask(ssl, MBEDTLS_TLS_EXT_EARLY_DATA); + + return 0; +} + +#if defined(MBEDTLS_SSL_SRV_C) +int mbedtls_ssl_tls13_check_early_data_len(mbedtls_ssl_context *ssl, + size_t early_data_len) +{ + /* + * This function should be called only while an handshake is in progress + * and thus a session under negotiation. Add a sanity check to detect a + * misuse. + */ + if (ssl->session_negotiate == NULL) { + return MBEDTLS_ERR_SSL_INTERNAL_ERROR; + } + + /* RFC 8446 section 4.6.1 + * + * A server receiving more than max_early_data_size bytes of 0-RTT data + * SHOULD terminate the connection with an "unexpected_message" alert. + * Note that if it is still possible to send early_data_len bytes of early + * data, it means that early_data_len is smaller than max_early_data_size + * (type uint32_t) and can fit in an uint32_t. We use this further + * down. + */ + if (early_data_len > + (ssl->session_negotiate->max_early_data_size - + ssl->total_early_data_size)) { + + MBEDTLS_SSL_DEBUG_MSG( + 2, ("EarlyData: Too much early data received, %u + %" MBEDTLS_PRINTF_SIZET " > %u", + ssl->total_early_data_size, early_data_len, + ssl->session_negotiate->max_early_data_size)); + + MBEDTLS_SSL_PEND_FATAL_ALERT( + MBEDTLS_SSL_ALERT_MSG_UNEXPECTED_MESSAGE, + MBEDTLS_ERR_SSL_UNEXPECTED_MESSAGE); + return MBEDTLS_ERR_SSL_UNEXPECTED_MESSAGE; + } + + /* + * early_data_len has been checked to be less than max_early_data_size + * that is uint32_t. Its cast to an uint32_t below is thus safe. We need + * the cast to appease some compilers. + */ + ssl->total_early_data_size += (uint32_t) early_data_len; + + return 0; +} +#endif /* MBEDTLS_SSL_SRV_C */ +#endif /* MBEDTLS_SSL_EARLY_DATA */ + +/* Reset SSL context and update hash for handling HRR. + * + * Replace Transcript-Hash(X) by + * Transcript-Hash( message_hash || + * 00 00 Hash.length || + * X ) + * A few states of the handshake are preserved, including: + * - session ID + * - session ticket + * - negotiated ciphersuite + */ +int mbedtls_ssl_reset_transcript_for_hrr(mbedtls_ssl_context *ssl) +{ + int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED; + unsigned char hash_transcript[PSA_HASH_MAX_SIZE + 4]; + size_t hash_len; + const mbedtls_ssl_ciphersuite_t *ciphersuite_info = + ssl->handshake->ciphersuite_info; + + MBEDTLS_SSL_DEBUG_MSG(3, ("Reset SSL session for HRR")); + + ret = mbedtls_ssl_get_handshake_transcript(ssl, (mbedtls_md_type_t) ciphersuite_info->mac, + hash_transcript + 4, + PSA_HASH_MAX_SIZE, + &hash_len); + if (ret != 0) { + MBEDTLS_SSL_DEBUG_RET(1, "mbedtls_ssl_get_handshake_transcript", ret); + return ret; + } + + hash_transcript[0] = MBEDTLS_SSL_HS_MESSAGE_HASH; + hash_transcript[1] = 0; + hash_transcript[2] = 0; + hash_transcript[3] = (unsigned char) hash_len; + + hash_len += 4; + + MBEDTLS_SSL_DEBUG_BUF(4, "Truncated handshake transcript", + hash_transcript, hash_len); + + /* Reset running hash and replace it with a hash of the transcript */ + ret = mbedtls_ssl_reset_checksum(ssl); + if (ret != 0) { + MBEDTLS_SSL_DEBUG_RET(1, "mbedtls_ssl_reset_checksum", ret); + return ret; + } + ret = ssl->handshake->update_checksum(ssl, hash_transcript, hash_len); + if (ret != 0) { + MBEDTLS_SSL_DEBUG_RET(1, "update_checksum", ret); + return ret; + } + + return ret; +} + +#if defined(MBEDTLS_SSL_TLS1_3_KEY_EXCHANGE_MODE_SOME_EPHEMERAL_ENABLED) + +int mbedtls_ssl_tls13_read_public_xxdhe_share(mbedtls_ssl_context *ssl, + const unsigned char *buf, + size_t buf_len) +{ + uint8_t *p = (uint8_t *) buf; + const uint8_t *end = buf + buf_len; + mbedtls_ssl_handshake_params *handshake = ssl->handshake; + + /* Get size of the TLS opaque key_exchange field of the KeyShareEntry struct. */ + MBEDTLS_SSL_CHK_BUF_READ_PTR(p, end, 2); + uint16_t peerkey_len = MBEDTLS_GET_UINT16_BE(p, 0); + p += 2; + + /* Check if key size is consistent with given buffer length. */ + MBEDTLS_SSL_CHK_BUF_READ_PTR(p, end, peerkey_len); + + /* Store peer's ECDH/FFDH public key. */ + if (peerkey_len > sizeof(handshake->xxdh_psa_peerkey)) { + MBEDTLS_SSL_DEBUG_MSG(1, ("Invalid public key length: %u > %" MBEDTLS_PRINTF_SIZET, + (unsigned) peerkey_len, + sizeof(handshake->xxdh_psa_peerkey))); + return MBEDTLS_ERR_SSL_HANDSHAKE_FAILURE; + } + memcpy(handshake->xxdh_psa_peerkey, p, peerkey_len); + handshake->xxdh_psa_peerkey_len = peerkey_len; + + return 0; +} + +#if defined(PSA_WANT_ALG_FFDH) +static psa_status_t mbedtls_ssl_get_psa_ffdh_info_from_tls_id( + uint16_t tls_id, size_t *bits, psa_key_type_t *key_type) +{ + switch (tls_id) { +#if defined(PSA_WANT_DH_RFC7919_2048) + case MBEDTLS_SSL_IANA_TLS_GROUP_FFDHE2048: + *bits = 2048; + *key_type = PSA_KEY_TYPE_DH_KEY_PAIR(PSA_DH_FAMILY_RFC7919); + return PSA_SUCCESS; +#endif /* PSA_WANT_DH_RFC7919_2048 */ +#if defined(PSA_WANT_DH_RFC7919_3072) + case MBEDTLS_SSL_IANA_TLS_GROUP_FFDHE3072: + *bits = 3072; + *key_type = PSA_KEY_TYPE_DH_KEY_PAIR(PSA_DH_FAMILY_RFC7919); + return PSA_SUCCESS; +#endif /* PSA_WANT_DH_RFC7919_3072 */ +#if defined(PSA_WANT_DH_RFC7919_4096) + case MBEDTLS_SSL_IANA_TLS_GROUP_FFDHE4096: + *bits = 4096; + *key_type = PSA_KEY_TYPE_DH_KEY_PAIR(PSA_DH_FAMILY_RFC7919); + return PSA_SUCCESS; +#endif /* PSA_WANT_DH_RFC7919_4096 */ +#if defined(PSA_WANT_DH_RFC7919_6144) + case MBEDTLS_SSL_IANA_TLS_GROUP_FFDHE6144: + *bits = 6144; + *key_type = PSA_KEY_TYPE_DH_KEY_PAIR(PSA_DH_FAMILY_RFC7919); + return PSA_SUCCESS; +#endif /* PSA_WANT_DH_RFC7919_6144 */ +#if defined(PSA_WANT_DH_RFC7919_8192) + case MBEDTLS_SSL_IANA_TLS_GROUP_FFDHE8192: + *bits = 8192; + *key_type = PSA_KEY_TYPE_DH_KEY_PAIR(PSA_DH_FAMILY_RFC7919); + return PSA_SUCCESS; +#endif /* PSA_WANT_DH_RFC7919_8192 */ + default: + return PSA_ERROR_NOT_SUPPORTED; + } +} +#endif /* PSA_WANT_ALG_FFDH */ + +int mbedtls_ssl_tls13_generate_and_write_xxdh_key_exchange( + mbedtls_ssl_context *ssl, + uint16_t named_group, + unsigned char *buf, + unsigned char *end, + size_t *out_len) +{ + psa_status_t status = PSA_ERROR_GENERIC_ERROR; + int ret = MBEDTLS_ERR_SSL_FEATURE_UNAVAILABLE; + psa_key_attributes_t key_attributes; + size_t own_pubkey_len; + mbedtls_ssl_handshake_params *handshake = ssl->handshake; + size_t bits = 0; + psa_key_type_t key_type = PSA_KEY_TYPE_NONE; + psa_algorithm_t alg = PSA_ALG_NONE; + size_t buf_size = (size_t) (end - buf); + + MBEDTLS_SSL_DEBUG_MSG(1, ("Perform PSA-based ECDH/FFDH computation.")); + + /* Convert EC's TLS ID to PSA key type. */ +#if defined(PSA_WANT_ALG_ECDH) + if (mbedtls_ssl_get_psa_curve_info_from_tls_id( + named_group, &key_type, &bits) == PSA_SUCCESS) { + alg = PSA_ALG_ECDH; + } +#endif +#if defined(PSA_WANT_ALG_FFDH) + if (mbedtls_ssl_get_psa_ffdh_info_from_tls_id(named_group, &bits, + &key_type) == PSA_SUCCESS) { + alg = PSA_ALG_FFDH; + } +#endif + + if (key_type == PSA_KEY_TYPE_NONE) { + return MBEDTLS_ERR_SSL_HANDSHAKE_FAILURE; + } + + if (buf_size < PSA_BITS_TO_BYTES(bits)) { + return MBEDTLS_ERR_SSL_BUFFER_TOO_SMALL; + } + + handshake->xxdh_psa_type = key_type; + ssl->handshake->xxdh_psa_bits = bits; + + key_attributes = psa_key_attributes_init(); + psa_set_key_usage_flags(&key_attributes, PSA_KEY_USAGE_DERIVE); + psa_set_key_algorithm(&key_attributes, alg); + psa_set_key_type(&key_attributes, handshake->xxdh_psa_type); + psa_set_key_bits(&key_attributes, handshake->xxdh_psa_bits); + + /* Generate ECDH/FFDH private key. */ + status = psa_generate_key(&key_attributes, + &handshake->xxdh_psa_privkey); + if (status != PSA_SUCCESS) { + ret = PSA_TO_MBEDTLS_ERR(status); + MBEDTLS_SSL_DEBUG_RET(1, "psa_generate_key", ret); + return ret; + + } + + /* Export the public part of the ECDH/FFDH private key from PSA. */ + status = psa_export_public_key(handshake->xxdh_psa_privkey, + buf, buf_size, + &own_pubkey_len); + + if (status != PSA_SUCCESS) { + ret = PSA_TO_MBEDTLS_ERR(status); + MBEDTLS_SSL_DEBUG_RET(1, "psa_export_public_key", ret); + return ret; + } + + *out_len = own_pubkey_len; + + return 0; +} +#endif /* MBEDTLS_SSL_TLS1_3_KEY_EXCHANGE_MODE_SOME_EPHEMERAL_ENABLED */ + +/* RFC 8446 section 4.2 + * + * If an implementation receives an extension which it recognizes and which is + * not specified for the message in which it appears, it MUST abort the handshake + * with an "illegal_parameter" alert. + * + */ +int mbedtls_ssl_tls13_check_received_extension( + mbedtls_ssl_context *ssl, + int hs_msg_type, + unsigned int received_extension_type, + uint32_t hs_msg_allowed_extensions_mask) +{ + uint32_t extension_mask = mbedtls_ssl_get_extension_mask( + received_extension_type); + + MBEDTLS_SSL_PRINT_EXT( + 3, hs_msg_type, received_extension_type, "received"); + + if ((extension_mask & hs_msg_allowed_extensions_mask) == 0) { + MBEDTLS_SSL_PRINT_EXT( + 3, hs_msg_type, received_extension_type, "is illegal"); + MBEDTLS_SSL_PEND_FATAL_ALERT( + MBEDTLS_SSL_ALERT_MSG_ILLEGAL_PARAMETER, + MBEDTLS_ERR_SSL_ILLEGAL_PARAMETER); + return MBEDTLS_ERR_SSL_ILLEGAL_PARAMETER; + } + + ssl->handshake->received_extensions |= extension_mask; + /* + * If it is a message containing extension responses, check that we + * previously sent the extension. + */ + switch (hs_msg_type) { + case MBEDTLS_SSL_HS_SERVER_HELLO: + case MBEDTLS_SSL_TLS1_3_HS_HELLO_RETRY_REQUEST: + case MBEDTLS_SSL_HS_ENCRYPTED_EXTENSIONS: + case MBEDTLS_SSL_HS_CERTIFICATE: + /* Check if the received extension is sent by peer message.*/ + if ((ssl->handshake->sent_extensions & extension_mask) != 0) { + return 0; + } + break; + default: + return 0; + } + + MBEDTLS_SSL_PRINT_EXT( + 3, hs_msg_type, received_extension_type, "is unsupported"); + MBEDTLS_SSL_PEND_FATAL_ALERT( + MBEDTLS_SSL_ALERT_MSG_UNSUPPORTED_EXT, + MBEDTLS_ERR_SSL_UNSUPPORTED_EXTENSION); + return MBEDTLS_ERR_SSL_UNSUPPORTED_EXTENSION; +} + +#if defined(MBEDTLS_SSL_RECORD_SIZE_LIMIT) + +/* RFC 8449, section 4: + * + * The ExtensionData of the "record_size_limit" extension is + * RecordSizeLimit: + * uint16 RecordSizeLimit; + */ +MBEDTLS_CHECK_RETURN_CRITICAL +int mbedtls_ssl_tls13_parse_record_size_limit_ext(mbedtls_ssl_context *ssl, + const unsigned char *buf, + const unsigned char *end) +{ + const unsigned char *p = buf; + uint16_t record_size_limit; + const size_t extension_data_len = end - buf; + + if (extension_data_len != + MBEDTLS_SSL_RECORD_SIZE_LIMIT_EXTENSION_DATA_LENGTH) { + MBEDTLS_SSL_DEBUG_MSG(2, + ("record_size_limit extension has invalid length: %" + MBEDTLS_PRINTF_SIZET " Bytes", + extension_data_len)); + + MBEDTLS_SSL_PEND_FATAL_ALERT( + MBEDTLS_SSL_ALERT_MSG_ILLEGAL_PARAMETER, + MBEDTLS_ERR_SSL_ILLEGAL_PARAMETER); + return MBEDTLS_ERR_SSL_ILLEGAL_PARAMETER; + } + + MBEDTLS_SSL_CHK_BUF_READ_PTR(p, end, 2); + record_size_limit = MBEDTLS_GET_UINT16_BE(p, 0); + + MBEDTLS_SSL_DEBUG_MSG(2, ("RecordSizeLimit: %u Bytes", record_size_limit)); + + /* RFC 8449, section 4: + * + * Endpoints MUST NOT send a "record_size_limit" extension with a value + * smaller than 64. An endpoint MUST treat receipt of a smaller value + * as a fatal error and generate an "illegal_parameter" alert. + */ + if (record_size_limit < MBEDTLS_SSL_RECORD_SIZE_LIMIT_MIN) { + MBEDTLS_SSL_DEBUG_MSG(1, ("Invalid record size limit : %u Bytes", + record_size_limit)); + MBEDTLS_SSL_PEND_FATAL_ALERT( + MBEDTLS_SSL_ALERT_MSG_ILLEGAL_PARAMETER, + MBEDTLS_ERR_SSL_ILLEGAL_PARAMETER); + return MBEDTLS_ERR_SSL_ILLEGAL_PARAMETER; + } + + ssl->session_negotiate->record_size_limit = record_size_limit; + + return 0; +} + +MBEDTLS_CHECK_RETURN_CRITICAL +int mbedtls_ssl_tls13_write_record_size_limit_ext(mbedtls_ssl_context *ssl, + unsigned char *buf, + const unsigned char *end, + size_t *out_len) +{ + unsigned char *p = buf; + *out_len = 0; + + MBEDTLS_STATIC_ASSERT(MBEDTLS_SSL_IN_CONTENT_LEN >= MBEDTLS_SSL_RECORD_SIZE_LIMIT_MIN, + "MBEDTLS_SSL_IN_CONTENT_LEN is less than the " + "minimum record size limit"); + + MBEDTLS_SSL_CHK_BUF_PTR(p, end, 6); + + MBEDTLS_PUT_UINT16_BE(MBEDTLS_TLS_EXT_RECORD_SIZE_LIMIT, p, 0); + MBEDTLS_PUT_UINT16_BE(MBEDTLS_SSL_RECORD_SIZE_LIMIT_EXTENSION_DATA_LENGTH, + p, 2); + MBEDTLS_PUT_UINT16_BE(MBEDTLS_SSL_IN_CONTENT_LEN, p, 4); + + *out_len = 6; + + MBEDTLS_SSL_DEBUG_MSG(2, ("Sent RecordSizeLimit: %d Bytes", + MBEDTLS_SSL_IN_CONTENT_LEN)); + + mbedtls_ssl_tls13_set_hs_sent_ext_mask(ssl, MBEDTLS_TLS_EXT_RECORD_SIZE_LIMIT); + + return 0; +} + +#endif /* MBEDTLS_SSL_RECORD_SIZE_LIMIT */ + +#endif /* MBEDTLS_SSL_TLS_C && MBEDTLS_SSL_PROTO_TLS1_3 */ diff --git a/vendor/mbedtls/library/ssl_tls13_invasive.h b/vendor/mbedtls/library/ssl_tls13_invasive.h new file mode 100644 index 0000000000..b4506f71c7 --- /dev/null +++ b/vendor/mbedtls/library/ssl_tls13_invasive.h @@ -0,0 +1,23 @@ +/* + * Copyright The Mbed TLS Contributors + * SPDX-License-Identifier: Apache-2.0 OR GPL-2.0-or-later + */ + +#ifndef MBEDTLS_SSL_TLS13_INVASIVE_H +#define MBEDTLS_SSL_TLS13_INVASIVE_H + +#include "common.h" + +#if defined(MBEDTLS_SSL_PROTO_TLS1_3) + +#include "psa/crypto.h" + +#if defined(MBEDTLS_TEST_HOOKS) +int mbedtls_ssl_tls13_parse_certificate(mbedtls_ssl_context *ssl, + const unsigned char *buf, + const unsigned char *end); +#endif /* MBEDTLS_TEST_HOOKS */ + +#endif /* MBEDTLS_SSL_PROTO_TLS1_3 */ + +#endif /* MBEDTLS_SSL_TLS13_INVASIVE_H */ diff --git a/vendor/mbedtls/library/ssl_tls13_keys.c b/vendor/mbedtls/library/ssl_tls13_keys.c index 675414885f..739414ea2f 100644 --- a/vendor/mbedtls/library/ssl_tls13_keys.c +++ b/vendor/mbedtls/library/ssl_tls13_keys.c @@ -2,40 +2,42 @@ * TLS 1.3 key schedule * * Copyright The Mbed TLS Contributors - * SPDX-License-Identifier: Apache-2.0 - * - * Licensed under the Apache License, Version 2.0 ( the "License" ); you may - * not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT - * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. + * SPDX-License-Identifier: Apache-2.0 OR GPL-2.0-or-later */ #include "common.h" -#if defined(MBEDTLS_SSL_PROTO_TLS1_3_EXPERIMENTAL) +#if defined(MBEDTLS_SSL_PROTO_TLS1_3) + +#include +#include #include "mbedtls/hkdf.h" -#include "mbedtls/ssl_internal.h" +#include "debug_internal.h" +#include "mbedtls/error.h" +#include "mbedtls/platform.h" + +#include "ssl_misc.h" #include "ssl_tls13_keys.h" -#include "psa/crypto_sizes.h" +#include "ssl_tls13_invasive.h" -#include -#include +#include "psa/crypto.h" +#include "mbedtls/psa_util.h" + +/* Define a local translating function to save code size by not using too many + * arguments in each translating place. */ +static int local_err_translation(psa_status_t status) +{ + return psa_status_to_mbedtls(status, psa_to_ssl_errors, + ARRAY_LENGTH(psa_to_ssl_errors), + psa_generic_status_to_mbedtls); +} +#define PSA_TO_MBEDTLS_ERR(status) local_err_translation(status) #define MBEDTLS_SSL_TLS1_3_LABEL(name, string) \ .name = string, -#define TLS1_3_EVOLVE_INPUT_SIZE (PSA_HASH_MAX_SIZE > PSA_RAW_KEY_AGREEMENT_OUTPUT_MAX_SIZE) ? \ - PSA_HASH_MAX_SIZE : PSA_RAW_KEY_AGREEMENT_OUTPUT_MAX_SIZE - -struct mbedtls_ssl_tls1_3_labels_struct const mbedtls_ssl_tls1_3_labels = +struct mbedtls_ssl_tls13_labels_struct const mbedtls_ssl_tls13_labels = { /* This seems to work in C, despite the string literal being one * character too long due to the 0-termination. */ @@ -62,24 +64,24 @@ struct mbedtls_ssl_tls1_3_labels_struct const mbedtls_ssl_tls1_3_labels = * 255 Bytes, so we require `desired_length` to be at most * 255. This allows us to save a few Bytes of code by * hardcoding the writing of the high bytes. - * - (label, llen): label + label length, without "tls13 " prefix - * The label length MUST be less than or equal to - * MBEDTLS_SSL_TLS1_3_KEY_SCHEDULE_MAX_LABEL_LEN - * It is the caller's responsibility to ensure this. - * All (label, label length) pairs used in TLS 1.3 - * can be obtained via MBEDTLS_SSL_TLS1_3_LBL_WITH_LEN(). - * - (ctx, clen): context + context length - * The context length MUST be less than or equal to - * MBEDTLS_SSL_TLS1_3_KEY_SCHEDULE_MAX_CONTEXT_LEN - * It is the caller's responsibility to ensure this. + * - (label, label_len): label + label length, without "tls13 " prefix + * The label length MUST be less than or equal to + * MBEDTLS_SSL_TLS1_3_KEY_SCHEDULE_MAX_LABEL_LEN + * It is the caller's responsibility to ensure this. + * All (label, label length) pairs used in TLS 1.3 + * can be obtained via MBEDTLS_SSL_TLS1_3_LBL_WITH_LEN(). + * - (ctx, ctx_len): context + context length + * The context length MUST be less than or equal to + * MBEDTLS_SSL_TLS1_3_KEY_SCHEDULE_MAX_CONTEXT_LEN + * It is the caller's responsibility to ensure this. * - dst: Target buffer for HkdfLabel structure, * This MUST be a writable buffer of size * at least SSL_TLS1_3_KEY_SCHEDULE_MAX_HKDF_LABEL_LEN Bytes. - * - dlen: Pointer at which to store the actual length of - * the HkdfLabel structure on success. + * - dst_len: Pointer at which to store the actual length of + * the HkdfLabel structure on success. */ -static const char tls1_3_label_prefix[6] = "tls13 "; +static const char tls13_label_prefix[6] = "tls13 "; #define SSL_TLS1_3_KEY_SCHEDULE_HKDF_LABEL_LEN(label_len, context_len) \ (2 /* expansion length */ \ @@ -90,20 +92,20 @@ static const char tls1_3_label_prefix[6] = "tls13 "; #define SSL_TLS1_3_KEY_SCHEDULE_MAX_HKDF_LABEL_LEN \ SSL_TLS1_3_KEY_SCHEDULE_HKDF_LABEL_LEN( \ - sizeof(tls1_3_label_prefix) + \ + sizeof(tls13_label_prefix) + \ MBEDTLS_SSL_TLS1_3_KEY_SCHEDULE_MAX_LABEL_LEN, \ MBEDTLS_SSL_TLS1_3_KEY_SCHEDULE_MAX_CONTEXT_LEN) -static void ssl_tls1_3_hkdf_encode_label( +static void ssl_tls13_hkdf_encode_label( size_t desired_length, - const unsigned char *label, size_t llen, - const unsigned char *ctx, size_t clen, - unsigned char *dst, size_t *dlen) + const unsigned char *label, size_t label_len, + const unsigned char *ctx, size_t ctx_len, + unsigned char *dst, size_t *dst_len) { size_t total_label_len = - sizeof(tls1_3_label_prefix) + llen; + sizeof(tls13_label_prefix) + label_len; size_t total_hkdf_lbl_len = - SSL_TLS1_3_KEY_SCHEDULE_HKDF_LABEL_LEN(total_label_len, clen); + SSL_TLS1_3_KEY_SCHEDULE_HKDF_LABEL_LEN(total_label_len, ctx_len); unsigned char *p = dst; @@ -111,7 +113,7 @@ static void ssl_tls1_3_hkdf_encode_label( * We're hardcoding the high byte to 0 here assuming that we never use * TLS 1.3 HKDF key expansion to more than 255 Bytes. */ #if MBEDTLS_SSL_TLS1_3_KEY_SCHEDULE_MAX_EXPANSION_LEN > 255 -#error "The implementation of ssl_tls1_3_hkdf_encode_label() is not fit for the \ +#error "The implementation of ssl_tls13_hkdf_encode_label() is not fit for the \ value of MBEDTLS_SSL_TLS1_3_KEY_SCHEDULE_MAX_EXPANSION_LEN" #endif @@ -120,64 +122,127 @@ static void ssl_tls1_3_hkdf_encode_label( /* Add label incl. prefix */ *p++ = MBEDTLS_BYTE_0(total_label_len); - memcpy(p, tls1_3_label_prefix, sizeof(tls1_3_label_prefix)); - p += sizeof(tls1_3_label_prefix); - memcpy(p, label, llen); - p += llen; + memcpy(p, tls13_label_prefix, sizeof(tls13_label_prefix)); + p += sizeof(tls13_label_prefix); + memcpy(p, label, label_len); + p += label_len; /* Add context value */ - *p++ = MBEDTLS_BYTE_0(clen); - if (clen != 0) { - memcpy(p, ctx, clen); + *p++ = MBEDTLS_BYTE_0(ctx_len); + if (ctx_len != 0) { + memcpy(p, ctx, ctx_len); } /* Return total length to the caller. */ - *dlen = total_hkdf_lbl_len; + *dst_len = total_hkdf_lbl_len; } -int mbedtls_ssl_tls1_3_hkdf_expand_label( - mbedtls_md_type_t hash_alg, - const unsigned char *secret, size_t slen, - const unsigned char *label, size_t llen, - const unsigned char *ctx, size_t clen, - unsigned char *buf, size_t blen) +int mbedtls_ssl_tls13_hkdf_expand_label( + psa_algorithm_t hash_alg, + const unsigned char *secret, size_t secret_len, + const unsigned char *label, size_t label_len, + const unsigned char *ctx, size_t ctx_len, + unsigned char *buf, size_t buf_len) { - const mbedtls_md_info_t *md; unsigned char hkdf_label[SSL_TLS1_3_KEY_SCHEDULE_MAX_HKDF_LABEL_LEN]; - size_t hkdf_label_len; + size_t hkdf_label_len = 0; + psa_status_t status = PSA_ERROR_CORRUPTION_DETECTED; + psa_status_t abort_status = PSA_ERROR_CORRUPTION_DETECTED; + psa_key_derivation_operation_t operation = + PSA_KEY_DERIVATION_OPERATION_INIT; - if (llen > MBEDTLS_SSL_TLS1_3_KEY_SCHEDULE_MAX_LABEL_LEN) { + if (label_len > MBEDTLS_SSL_TLS1_3_KEY_SCHEDULE_MAX_LABEL_LEN) { /* Should never happen since this is an internal * function, and we know statically which labels * are allowed. */ return MBEDTLS_ERR_SSL_INTERNAL_ERROR; } - if (clen > MBEDTLS_SSL_TLS1_3_KEY_SCHEDULE_MAX_CONTEXT_LEN) { + if (ctx_len > MBEDTLS_SSL_TLS1_3_KEY_SCHEDULE_MAX_CONTEXT_LEN) { /* Should not happen, as above. */ return MBEDTLS_ERR_SSL_INTERNAL_ERROR; } - if (blen > MBEDTLS_SSL_TLS1_3_KEY_SCHEDULE_MAX_EXPANSION_LEN) { + if (buf_len > MBEDTLS_SSL_TLS1_3_KEY_SCHEDULE_MAX_EXPANSION_LEN) { /* Should not happen, as above. */ return MBEDTLS_ERR_SSL_INTERNAL_ERROR; } - md = mbedtls_md_info_from_type(hash_alg); - if (md == NULL) { + if (!PSA_ALG_IS_HASH(hash_alg)) { return MBEDTLS_ERR_SSL_BAD_INPUT_DATA; } - ssl_tls1_3_hkdf_encode_label(blen, - label, llen, - ctx, clen, - hkdf_label, - &hkdf_label_len); + ssl_tls13_hkdf_encode_label(buf_len, + label, label_len, + ctx, ctx_len, + hkdf_label, + &hkdf_label_len); + + status = psa_key_derivation_setup(&operation, PSA_ALG_HKDF_EXPAND(hash_alg)); + + if (status != PSA_SUCCESS) { + goto cleanup; + } + + status = psa_key_derivation_input_bytes(&operation, + PSA_KEY_DERIVATION_INPUT_SECRET, + secret, + secret_len); + + if (status != PSA_SUCCESS) { + goto cleanup; + } + + status = psa_key_derivation_input_bytes(&operation, + PSA_KEY_DERIVATION_INPUT_INFO, + hkdf_label, + hkdf_label_len); + + if (status != PSA_SUCCESS) { + goto cleanup; + } + + status = psa_key_derivation_output_bytes(&operation, + buf, + buf_len); + + if (status != PSA_SUCCESS) { + goto cleanup; + } + +cleanup: + abort_status = psa_key_derivation_abort(&operation); + status = (status == PSA_SUCCESS ? abort_status : status); + mbedtls_platform_zeroize(hkdf_label, hkdf_label_len); + return PSA_TO_MBEDTLS_ERR(status); +} + +MBEDTLS_CHECK_RETURN_CRITICAL +static int ssl_tls13_make_traffic_key( + psa_algorithm_t hash_alg, + const unsigned char *secret, size_t secret_len, + unsigned char *key, size_t key_len, + unsigned char *iv, size_t iv_len) +{ + int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED; + + ret = mbedtls_ssl_tls13_hkdf_expand_label( + hash_alg, + secret, secret_len, + MBEDTLS_SSL_TLS1_3_LBL_WITH_LEN(key), + NULL, 0, + key, key_len); + if (ret != 0) { + return ret; + } - return mbedtls_hkdf_expand(md, - secret, slen, - hkdf_label, hkdf_label_len, - buf, blen); + ret = mbedtls_ssl_tls13_hkdf_expand_label( + hash_alg, + secret, secret_len, + MBEDTLS_SSL_TLS1_3_LBL_WITH_LEN(iv), + NULL, 0, + iv, iv_len); + return ret; } /* @@ -196,47 +261,27 @@ int mbedtls_ssl_tls1_3_hkdf_expand_label( * by the function caller. Note that we generate server and client side * keys in a single function call. */ -int mbedtls_ssl_tls1_3_make_traffic_keys( - mbedtls_md_type_t hash_alg, +int mbedtls_ssl_tls13_make_traffic_keys( + psa_algorithm_t hash_alg, const unsigned char *client_secret, - const unsigned char *server_secret, - size_t slen, size_t key_len, size_t iv_len, + const unsigned char *server_secret, size_t secret_len, + size_t key_len, size_t iv_len, mbedtls_ssl_key_set *keys) { int ret = 0; - ret = mbedtls_ssl_tls1_3_hkdf_expand_label(hash_alg, - client_secret, slen, - MBEDTLS_SSL_TLS1_3_LBL_WITH_LEN(key), - NULL, 0, - keys->client_write_key, key_len); - if (ret != 0) { - return ret; - } - - ret = mbedtls_ssl_tls1_3_hkdf_expand_label(hash_alg, - server_secret, slen, - MBEDTLS_SSL_TLS1_3_LBL_WITH_LEN(key), - NULL, 0, - keys->server_write_key, key_len); - if (ret != 0) { - return ret; - } - - ret = mbedtls_ssl_tls1_3_hkdf_expand_label(hash_alg, - client_secret, slen, - MBEDTLS_SSL_TLS1_3_LBL_WITH_LEN(iv), - NULL, 0, - keys->client_write_iv, iv_len); + ret = ssl_tls13_make_traffic_key( + hash_alg, client_secret, secret_len, + keys->client_write_key, key_len, + keys->client_write_iv, iv_len); if (ret != 0) { return ret; } - ret = mbedtls_ssl_tls1_3_hkdf_expand_label(hash_alg, - server_secret, slen, - MBEDTLS_SSL_TLS1_3_LBL_WITH_LEN(iv), - NULL, 0, - keys->server_write_iv, iv_len); + ret = ssl_tls13_make_traffic_key( + hash_alg, server_secret, secret_len, + keys->server_write_key, key_len, + keys->server_write_iv, iv_len); if (ret != 0) { return ret; } @@ -247,31 +292,27 @@ int mbedtls_ssl_tls1_3_make_traffic_keys( return 0; } -int mbedtls_ssl_tls1_3_derive_secret( - mbedtls_md_type_t hash_alg, - const unsigned char *secret, size_t slen, - const unsigned char *label, size_t llen, - const unsigned char *ctx, size_t clen, +int mbedtls_ssl_tls13_derive_secret( + psa_algorithm_t hash_alg, + const unsigned char *secret, size_t secret_len, + const unsigned char *label, size_t label_len, + const unsigned char *ctx, size_t ctx_len, int ctx_hashed, - unsigned char *dstbuf, size_t buflen) + unsigned char *dstbuf, size_t dstbuf_len) { int ret; - unsigned char hashed_context[MBEDTLS_MD_MAX_SIZE]; - - const mbedtls_md_info_t *md; - md = mbedtls_md_info_from_type(hash_alg); - if (md == NULL) { - return MBEDTLS_ERR_SSL_BAD_INPUT_DATA; - } - + unsigned char hashed_context[PSA_HASH_MAX_SIZE]; if (ctx_hashed == MBEDTLS_SSL_TLS1_3_CONTEXT_UNHASHED) { - ret = mbedtls_md(md, ctx, clen, hashed_context); - if (ret != 0) { + psa_status_t status = PSA_ERROR_CORRUPTION_DETECTED; + + status = psa_hash_compute(hash_alg, ctx, ctx_len, hashed_context, + PSA_HASH_LENGTH(hash_alg), &ctx_len); + if (status != PSA_SUCCESS) { + ret = PSA_TO_MBEDTLS_ERR(status); return ret; } - clen = mbedtls_md_get_size(md); } else { - if (clen > sizeof(hashed_context)) { + if (ctx_len > sizeof(hashed_context)) { /* This should never happen since this function is internal * and the code sets `ctx_hashed` correctly. * Let's double-check nonetheless to not run at the risk @@ -279,39 +320,45 @@ int mbedtls_ssl_tls1_3_derive_secret( return MBEDTLS_ERR_SSL_INTERNAL_ERROR; } - memcpy(hashed_context, ctx, clen); + memcpy(hashed_context, ctx, ctx_len); } - return mbedtls_ssl_tls1_3_hkdf_expand_label(hash_alg, - secret, slen, - label, llen, - hashed_context, clen, - dstbuf, buflen); + return mbedtls_ssl_tls13_hkdf_expand_label(hash_alg, + secret, secret_len, + label, label_len, + hashed_context, ctx_len, + dstbuf, dstbuf_len); + } -int mbedtls_ssl_tls1_3_evolve_secret( - mbedtls_md_type_t hash_alg, +int mbedtls_ssl_tls13_evolve_secret( + psa_algorithm_t hash_alg, const unsigned char *secret_old, const unsigned char *input, size_t input_len, unsigned char *secret_new) { int ret = MBEDTLS_ERR_SSL_INTERNAL_ERROR; - size_t hlen, ilen; + psa_status_t status = PSA_ERROR_CORRUPTION_DETECTED; + psa_status_t abort_status = PSA_ERROR_CORRUPTION_DETECTED; + size_t hlen; unsigned char tmp_secret[PSA_MAC_MAX_SIZE] = { 0 }; - unsigned char tmp_input[TLS1_3_EVOLVE_INPUT_SIZE] = { 0 }; + const unsigned char all_zeroes_input[MBEDTLS_TLS1_3_MD_MAX_SIZE] = { 0 }; + const unsigned char *l_input = NULL; + size_t l_input_len; - const mbedtls_md_info_t *md; - md = mbedtls_md_info_from_type(hash_alg); - if (md == NULL) { + psa_key_derivation_operation_t operation = + PSA_KEY_DERIVATION_OPERATION_INIT; + + if (!PSA_ALG_IS_HASH(hash_alg)) { return MBEDTLS_ERR_SSL_BAD_INPUT_DATA; } - hlen = mbedtls_md_get_size(md); + hlen = PSA_HASH_LENGTH(hash_alg); /* For non-initial runs, call Derive-Secret( ., "derived", "") * on the old secret. */ if (secret_old != NULL) { - ret = mbedtls_ssl_tls1_3_derive_secret( + ret = mbedtls_ssl_tls13_derive_secret( hash_alg, secret_old, hlen, MBEDTLS_SSL_TLS1_3_LBL_WITH_LEN(derived), @@ -323,31 +370,1516 @@ int mbedtls_ssl_tls1_3_evolve_secret( } } - if (input != NULL) { - memcpy(tmp_input, input, input_len); - ilen = input_len; + ret = 0; + + if (input != NULL && input_len != 0) { + l_input = input; + l_input_len = input_len; } else { - ilen = hlen; + l_input = all_zeroes_input; + l_input_len = hlen; } - /* HKDF-Extract takes a salt and input key material. - * The salt is the old secret, and the input key material - * is the input secret (PSK / ECDHE). */ - ret = mbedtls_hkdf_extract(md, - tmp_secret, hlen, - tmp_input, ilen, - secret_new); - if (ret != 0) { + status = psa_key_derivation_setup(&operation, + PSA_ALG_HKDF_EXTRACT(hash_alg)); + + if (status != PSA_SUCCESS) { goto cleanup; } - ret = 0; + status = psa_key_derivation_input_bytes(&operation, + PSA_KEY_DERIVATION_INPUT_SALT, + tmp_secret, + hlen); -cleanup: + if (status != PSA_SUCCESS) { + goto cleanup; + } + + status = psa_key_derivation_input_bytes(&operation, + PSA_KEY_DERIVATION_INPUT_SECRET, + l_input, l_input_len); + if (status != PSA_SUCCESS) { + goto cleanup; + } + + status = psa_key_derivation_output_bytes(&operation, + secret_new, + PSA_HASH_LENGTH(hash_alg)); + + if (status != PSA_SUCCESS) { + goto cleanup; + } + +cleanup: + abort_status = psa_key_derivation_abort(&operation); + status = (status == PSA_SUCCESS ? abort_status : status); + ret = (ret == 0 ? PSA_TO_MBEDTLS_ERR(status) : ret); mbedtls_platform_zeroize(tmp_secret, sizeof(tmp_secret)); - mbedtls_platform_zeroize(tmp_input, sizeof(tmp_input)); return ret; } -#endif /* MBEDTLS_SSL_PROTO_TLS1_3_EXPERIMENTAL */ +int mbedtls_ssl_tls13_derive_early_secrets( + psa_algorithm_t hash_alg, + unsigned char const *early_secret, + unsigned char const *transcript, size_t transcript_len, + mbedtls_ssl_tls13_early_secrets *derived) +{ + int ret; + size_t const hash_len = PSA_HASH_LENGTH(hash_alg); + + /* We should never call this function with an unknown hash, + * but add an assertion anyway. */ + if (!PSA_ALG_IS_HASH(hash_alg)) { + return MBEDTLS_ERR_SSL_INTERNAL_ERROR; + } + + /* + * 0 + * | + * v + * PSK -> HKDF-Extract = Early Secret + * | + * +-----> Derive-Secret(., "c e traffic", ClientHello) + * | = client_early_traffic_secret + * | + * +-----> Derive-Secret(., "e exp master", ClientHello) + * | = early_exporter_master_secret + * v + */ + + /* Create client_early_traffic_secret */ + ret = mbedtls_ssl_tls13_derive_secret( + hash_alg, + early_secret, hash_len, + MBEDTLS_SSL_TLS1_3_LBL_WITH_LEN(c_e_traffic), + transcript, transcript_len, + MBEDTLS_SSL_TLS1_3_CONTEXT_HASHED, + derived->client_early_traffic_secret, + hash_len); + if (ret != 0) { + return ret; + } + + /* Create early exporter */ + ret = mbedtls_ssl_tls13_derive_secret( + hash_alg, + early_secret, hash_len, + MBEDTLS_SSL_TLS1_3_LBL_WITH_LEN(e_exp_master), + transcript, transcript_len, + MBEDTLS_SSL_TLS1_3_CONTEXT_HASHED, + derived->early_exporter_master_secret, + hash_len); + if (ret != 0) { + return ret; + } + + return 0; +} + +int mbedtls_ssl_tls13_derive_handshake_secrets( + psa_algorithm_t hash_alg, + unsigned char const *handshake_secret, + unsigned char const *transcript, size_t transcript_len, + mbedtls_ssl_tls13_handshake_secrets *derived) +{ + int ret; + size_t const hash_len = PSA_HASH_LENGTH(hash_alg); + + /* We should never call this function with an unknown hash, + * but add an assertion anyway. */ + if (!PSA_ALG_IS_HASH(hash_alg)) { + return MBEDTLS_ERR_SSL_INTERNAL_ERROR; + } + + /* + * + * Handshake Secret + * | + * +-----> Derive-Secret( ., "c hs traffic", + * | ClientHello...ServerHello ) + * | = client_handshake_traffic_secret + * | + * +-----> Derive-Secret( ., "s hs traffic", + * | ClientHello...ServerHello ) + * | = server_handshake_traffic_secret + * + */ + + /* + * Compute client_handshake_traffic_secret with + * Derive-Secret( ., "c hs traffic", ClientHello...ServerHello ) + */ + + ret = mbedtls_ssl_tls13_derive_secret( + hash_alg, + handshake_secret, hash_len, + MBEDTLS_SSL_TLS1_3_LBL_WITH_LEN(c_hs_traffic), + transcript, transcript_len, + MBEDTLS_SSL_TLS1_3_CONTEXT_HASHED, + derived->client_handshake_traffic_secret, + hash_len); + if (ret != 0) { + return ret; + } + + /* + * Compute server_handshake_traffic_secret with + * Derive-Secret( ., "s hs traffic", ClientHello...ServerHello ) + */ + + ret = mbedtls_ssl_tls13_derive_secret( + hash_alg, + handshake_secret, hash_len, + MBEDTLS_SSL_TLS1_3_LBL_WITH_LEN(s_hs_traffic), + transcript, transcript_len, + MBEDTLS_SSL_TLS1_3_CONTEXT_HASHED, + derived->server_handshake_traffic_secret, + hash_len); + if (ret != 0) { + return ret; + } + + return 0; +} + +int mbedtls_ssl_tls13_derive_application_secrets( + psa_algorithm_t hash_alg, + unsigned char const *application_secret, + unsigned char const *transcript, size_t transcript_len, + mbedtls_ssl_tls13_application_secrets *derived) +{ + int ret; + size_t const hash_len = PSA_HASH_LENGTH(hash_alg); + + /* We should never call this function with an unknown hash, + * but add an assertion anyway. */ + if (!PSA_ALG_IS_HASH(hash_alg)) { + return MBEDTLS_ERR_SSL_INTERNAL_ERROR; + } + + /* Generate {client,server}_application_traffic_secret_0 + * + * Master Secret + * | + * +-----> Derive-Secret( ., "c ap traffic", + * | ClientHello...server Finished ) + * | = client_application_traffic_secret_0 + * | + * +-----> Derive-Secret( ., "s ap traffic", + * | ClientHello...Server Finished ) + * | = server_application_traffic_secret_0 + * | + * +-----> Derive-Secret( ., "exp master", + * | ClientHello...server Finished) + * | = exporter_master_secret + * + */ + + ret = mbedtls_ssl_tls13_derive_secret( + hash_alg, + application_secret, hash_len, + MBEDTLS_SSL_TLS1_3_LBL_WITH_LEN(c_ap_traffic), + transcript, transcript_len, + MBEDTLS_SSL_TLS1_3_CONTEXT_HASHED, + derived->client_application_traffic_secret_N, + hash_len); + if (ret != 0) { + return ret; + } + + ret = mbedtls_ssl_tls13_derive_secret( + hash_alg, + application_secret, hash_len, + MBEDTLS_SSL_TLS1_3_LBL_WITH_LEN(s_ap_traffic), + transcript, transcript_len, + MBEDTLS_SSL_TLS1_3_CONTEXT_HASHED, + derived->server_application_traffic_secret_N, + hash_len); + if (ret != 0) { + return ret; + } + + ret = mbedtls_ssl_tls13_derive_secret( + hash_alg, + application_secret, hash_len, + MBEDTLS_SSL_TLS1_3_LBL_WITH_LEN(exp_master), + transcript, transcript_len, + MBEDTLS_SSL_TLS1_3_CONTEXT_HASHED, + derived->exporter_master_secret, + hash_len); + if (ret != 0) { + return ret; + } + + return 0; +} + +/* Generate resumption_master_secret for use with the ticket exchange. + * + * This is not integrated with mbedtls_ssl_tls13_derive_application_secrets() + * because it uses the transcript hash up to and including ClientFinished. */ +int mbedtls_ssl_tls13_derive_resumption_master_secret( + psa_algorithm_t hash_alg, + unsigned char const *application_secret, + unsigned char const *transcript, size_t transcript_len, + mbedtls_ssl_tls13_application_secrets *derived) +{ + int ret; + size_t const hash_len = PSA_HASH_LENGTH(hash_alg); + + /* We should never call this function with an unknown hash, + * but add an assertion anyway. */ + if (!PSA_ALG_IS_HASH(hash_alg)) { + return MBEDTLS_ERR_SSL_INTERNAL_ERROR; + } + + ret = mbedtls_ssl_tls13_derive_secret( + hash_alg, + application_secret, hash_len, + MBEDTLS_SSL_TLS1_3_LBL_WITH_LEN(res_master), + transcript, transcript_len, + MBEDTLS_SSL_TLS1_3_CONTEXT_HASHED, + derived->resumption_master_secret, + hash_len); + + if (ret != 0) { + return ret; + } + + return 0; +} + +/** + * \brief Transition into application stage of TLS 1.3 key schedule. + * + * The TLS 1.3 key schedule can be viewed as a simple state machine + * with states Initial -> Early -> Handshake -> Application, and + * this function represents the Handshake -> Application transition. + * + * In the handshake stage, ssl_tls13_generate_application_keys() + * can be used to derive the handshake traffic keys. + * + * \param ssl The SSL context to operate on. This must be in key schedule + * stage \c Handshake. + * + * \returns \c 0 on success. + * \returns A negative error code on failure. + */ +MBEDTLS_CHECK_RETURN_CRITICAL +static int ssl_tls13_key_schedule_stage_application(mbedtls_ssl_context *ssl) +{ + int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED; + mbedtls_ssl_handshake_params *handshake = ssl->handshake; + psa_algorithm_t const hash_alg = mbedtls_md_psa_alg_from_type( + (mbedtls_md_type_t) handshake->ciphersuite_info->mac); + + /* + * Compute MasterSecret + */ + ret = mbedtls_ssl_tls13_evolve_secret( + hash_alg, + handshake->tls13_master_secrets.handshake, + NULL, 0, + handshake->tls13_master_secrets.app); + if (ret != 0) { + MBEDTLS_SSL_DEBUG_RET(1, "mbedtls_ssl_tls13_evolve_secret", ret); + return ret; + } + + MBEDTLS_SSL_DEBUG_BUF( + 4, "Master secret", + handshake->tls13_master_secrets.app, PSA_HASH_LENGTH(hash_alg)); + + return 0; +} + +MBEDTLS_CHECK_RETURN_CRITICAL +static int ssl_tls13_calc_finished_core(psa_algorithm_t hash_alg, + unsigned char const *base_key, + unsigned char const *transcript, + unsigned char *dst, + size_t *dst_len) +{ + mbedtls_svc_key_id_t key = MBEDTLS_SVC_KEY_ID_INIT; + psa_key_attributes_t attributes = PSA_KEY_ATTRIBUTES_INIT; + psa_status_t status = PSA_ERROR_CORRUPTION_DETECTED; + size_t hash_len = PSA_HASH_LENGTH(hash_alg); + unsigned char finished_key[PSA_MAC_MAX_SIZE]; + int ret; + psa_algorithm_t alg; + + /* We should never call this function with an unknown hash, + * but add an assertion anyway. */ + if (!PSA_ALG_IS_HASH(hash_alg)) { + return MBEDTLS_ERR_SSL_INTERNAL_ERROR; + } + + /* TLS 1.3 Finished message + * + * struct { + * opaque verify_data[Hash.length]; + * } Finished; + * + * verify_data = + * HMAC( finished_key, + * Hash( Handshake Context + + * Certificate* + + * CertificateVerify* ) + * ) + * + * finished_key = + * HKDF-Expand-Label( BaseKey, "finished", "", Hash.length ) + */ + + ret = mbedtls_ssl_tls13_hkdf_expand_label( + hash_alg, base_key, hash_len, + MBEDTLS_SSL_TLS1_3_LBL_WITH_LEN(finished), + NULL, 0, + finished_key, hash_len); + if (ret != 0) { + goto exit; + } + + alg = PSA_ALG_HMAC(hash_alg); + psa_set_key_usage_flags(&attributes, PSA_KEY_USAGE_SIGN_MESSAGE); + psa_set_key_algorithm(&attributes, alg); + psa_set_key_type(&attributes, PSA_KEY_TYPE_HMAC); + + status = psa_import_key(&attributes, finished_key, hash_len, &key); + if (status != PSA_SUCCESS) { + ret = PSA_TO_MBEDTLS_ERR(status); + goto exit; + } + + status = psa_mac_compute(key, alg, transcript, hash_len, + dst, hash_len, dst_len); + ret = PSA_TO_MBEDTLS_ERR(status); + +exit: + + status = psa_destroy_key(key); + if (ret == 0) { + ret = PSA_TO_MBEDTLS_ERR(status); + } + + mbedtls_platform_zeroize(finished_key, sizeof(finished_key)); + + return ret; +} + +int mbedtls_ssl_tls13_calculate_verify_data(mbedtls_ssl_context *ssl, + unsigned char *dst, + size_t dst_len, + size_t *actual_len, + int from) +{ + int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED; + + unsigned char transcript[MBEDTLS_TLS1_3_MD_MAX_SIZE]; + size_t transcript_len; + + unsigned char *base_key = NULL; + size_t base_key_len = 0; + mbedtls_ssl_tls13_handshake_secrets *tls13_hs_secrets = + &ssl->handshake->tls13_hs_secrets; + + mbedtls_md_type_t const md_type = (mbedtls_md_type_t) ssl->handshake->ciphersuite_info->mac; + + psa_algorithm_t hash_alg = mbedtls_md_psa_alg_from_type( + (mbedtls_md_type_t) ssl->handshake->ciphersuite_info->mac); + size_t const hash_len = PSA_HASH_LENGTH(hash_alg); + + MBEDTLS_SSL_DEBUG_MSG(2, ("=> mbedtls_ssl_tls13_calculate_verify_data")); + + if (from == MBEDTLS_SSL_IS_CLIENT) { + base_key = tls13_hs_secrets->client_handshake_traffic_secret; + base_key_len = sizeof(tls13_hs_secrets->client_handshake_traffic_secret); + } else { + base_key = tls13_hs_secrets->server_handshake_traffic_secret; + base_key_len = sizeof(tls13_hs_secrets->server_handshake_traffic_secret); + } + + if (dst_len < hash_len) { + ret = MBEDTLS_ERR_SSL_BUFFER_TOO_SMALL; + goto exit; + } + + ret = mbedtls_ssl_get_handshake_transcript(ssl, md_type, + transcript, sizeof(transcript), + &transcript_len); + if (ret != 0) { + MBEDTLS_SSL_DEBUG_RET(1, "mbedtls_ssl_get_handshake_transcript", ret); + goto exit; + } + MBEDTLS_SSL_DEBUG_BUF(4, "handshake hash", transcript, transcript_len); + + ret = ssl_tls13_calc_finished_core(hash_alg, base_key, + transcript, dst, actual_len); + if (ret != 0) { + goto exit; + } + + MBEDTLS_SSL_DEBUG_BUF(3, "verify_data for finished message", dst, hash_len); + MBEDTLS_SSL_DEBUG_MSG(2, ("<= mbedtls_ssl_tls13_calculate_verify_data")); + +exit: + /* Erase handshake secrets */ + mbedtls_platform_zeroize(base_key, base_key_len); + mbedtls_platform_zeroize(transcript, sizeof(transcript)); + return ret; +} + +int mbedtls_ssl_tls13_create_psk_binder(mbedtls_ssl_context *ssl, + const psa_algorithm_t hash_alg, + unsigned char const *psk, size_t psk_len, + int psk_type, + unsigned char const *transcript, + unsigned char *result) +{ + int ret = 0; + unsigned char binder_key[PSA_MAC_MAX_SIZE]; + unsigned char early_secret[PSA_MAC_MAX_SIZE]; + size_t const hash_len = PSA_HASH_LENGTH(hash_alg); + size_t actual_len; + +#if !defined(MBEDTLS_DEBUG_C) + ssl = NULL; /* make sure we don't use it except for debug */ + ((void) ssl); +#endif + + /* We should never call this function with an unknown hash, + * but add an assertion anyway. */ + if (!PSA_ALG_IS_HASH(hash_alg)) { + return MBEDTLS_ERR_SSL_INTERNAL_ERROR; + } + + /* + * 0 + * | + * v + * PSK -> HKDF-Extract = Early Secret + * | + * +-----> Derive-Secret(., "ext binder" | "res binder", "") + * | = binder_key + * v + */ + + ret = mbedtls_ssl_tls13_evolve_secret(hash_alg, + NULL, /* Old secret */ + psk, psk_len, /* Input */ + early_secret); + if (ret != 0) { + MBEDTLS_SSL_DEBUG_RET(1, "mbedtls_ssl_tls13_evolve_secret", ret); + goto exit; + } + + MBEDTLS_SSL_DEBUG_BUF(4, "mbedtls_ssl_tls13_create_psk_binder", + early_secret, hash_len); + + if (psk_type == MBEDTLS_SSL_TLS1_3_PSK_RESUMPTION) { + ret = mbedtls_ssl_tls13_derive_secret( + hash_alg, + early_secret, hash_len, + MBEDTLS_SSL_TLS1_3_LBL_WITH_LEN(res_binder), + NULL, 0, MBEDTLS_SSL_TLS1_3_CONTEXT_UNHASHED, + binder_key, hash_len); + MBEDTLS_SSL_DEBUG_MSG(4, ("Derive Early Secret with 'res binder'")); + } else { + ret = mbedtls_ssl_tls13_derive_secret( + hash_alg, + early_secret, hash_len, + MBEDTLS_SSL_TLS1_3_LBL_WITH_LEN(ext_binder), + NULL, 0, MBEDTLS_SSL_TLS1_3_CONTEXT_UNHASHED, + binder_key, hash_len); + MBEDTLS_SSL_DEBUG_MSG(4, ("Derive Early Secret with 'ext binder'")); + } + + if (ret != 0) { + MBEDTLS_SSL_DEBUG_RET(1, "mbedtls_ssl_tls13_derive_secret", ret); + goto exit; + } + + /* + * The binding_value is computed in the same way as the Finished message + * but with the BaseKey being the binder_key. + */ + + ret = ssl_tls13_calc_finished_core(hash_alg, binder_key, transcript, + result, &actual_len); + if (ret != 0) { + goto exit; + } + + MBEDTLS_SSL_DEBUG_BUF(3, "psk binder", result, actual_len); + +exit: + + mbedtls_platform_zeroize(early_secret, sizeof(early_secret)); + mbedtls_platform_zeroize(binder_key, sizeof(binder_key)); + return ret; +} + +int mbedtls_ssl_tls13_populate_transform( + mbedtls_ssl_transform *transform, + int endpoint, int ciphersuite, + mbedtls_ssl_key_set const *traffic_keys, + mbedtls_ssl_context *ssl /* DEBUG ONLY */) +{ +#if !defined(MBEDTLS_USE_PSA_CRYPTO) + int ret; + mbedtls_cipher_info_t const *cipher_info; +#endif /* MBEDTLS_USE_PSA_CRYPTO */ + const mbedtls_ssl_ciphersuite_t *ciphersuite_info; + unsigned char const *key_enc; + unsigned char const *iv_enc; + unsigned char const *key_dec; + unsigned char const *iv_dec; + +#if defined(MBEDTLS_USE_PSA_CRYPTO) + psa_key_type_t key_type; + psa_key_attributes_t attributes = PSA_KEY_ATTRIBUTES_INIT; + psa_algorithm_t alg; + size_t key_bits; + psa_status_t status = PSA_SUCCESS; +#endif + +#if !defined(MBEDTLS_DEBUG_C) + ssl = NULL; /* make sure we don't use it except for those cases */ + (void) ssl; +#endif + + ciphersuite_info = mbedtls_ssl_ciphersuite_from_id(ciphersuite); + if (ciphersuite_info == NULL) { + MBEDTLS_SSL_DEBUG_MSG(1, ("ciphersuite info for %d not found", + ciphersuite)); + return MBEDTLS_ERR_SSL_BAD_INPUT_DATA; + } + +#if !defined(MBEDTLS_USE_PSA_CRYPTO) + cipher_info = mbedtls_cipher_info_from_type(ciphersuite_info->cipher); + if (cipher_info == NULL) { + MBEDTLS_SSL_DEBUG_MSG(1, ("cipher info for %u not found", + ciphersuite_info->cipher)); + return MBEDTLS_ERR_SSL_BAD_INPUT_DATA; + } + + /* + * Setup cipher contexts in target transform + */ + if ((ret = mbedtls_cipher_setup(&transform->cipher_ctx_enc, + cipher_info)) != 0) { + MBEDTLS_SSL_DEBUG_RET(1, "mbedtls_cipher_setup", ret); + return ret; + } + + if ((ret = mbedtls_cipher_setup(&transform->cipher_ctx_dec, + cipher_info)) != 0) { + MBEDTLS_SSL_DEBUG_RET(1, "mbedtls_cipher_setup", ret); + return ret; + } +#endif /* MBEDTLS_USE_PSA_CRYPTO */ + +#if defined(MBEDTLS_SSL_SRV_C) + if (endpoint == MBEDTLS_SSL_IS_SERVER) { + key_enc = traffic_keys->server_write_key; + key_dec = traffic_keys->client_write_key; + iv_enc = traffic_keys->server_write_iv; + iv_dec = traffic_keys->client_write_iv; + } else +#endif /* MBEDTLS_SSL_SRV_C */ +#if defined(MBEDTLS_SSL_CLI_C) + if (endpoint == MBEDTLS_SSL_IS_CLIENT) { + key_enc = traffic_keys->client_write_key; + key_dec = traffic_keys->server_write_key; + iv_enc = traffic_keys->client_write_iv; + iv_dec = traffic_keys->server_write_iv; + } else +#endif /* MBEDTLS_SSL_CLI_C */ + { + /* should not happen */ + return MBEDTLS_ERR_SSL_INTERNAL_ERROR; + } + + memcpy(transform->iv_enc, iv_enc, traffic_keys->iv_len); + memcpy(transform->iv_dec, iv_dec, traffic_keys->iv_len); + +#if !defined(MBEDTLS_USE_PSA_CRYPTO) + if ((ret = mbedtls_cipher_setkey(&transform->cipher_ctx_enc, + key_enc, (int) mbedtls_cipher_info_get_key_bitlen(cipher_info), + MBEDTLS_ENCRYPT)) != 0) { + MBEDTLS_SSL_DEBUG_RET(1, "mbedtls_cipher_setkey", ret); + return ret; + } + + if ((ret = mbedtls_cipher_setkey(&transform->cipher_ctx_dec, + key_dec, (int) mbedtls_cipher_info_get_key_bitlen(cipher_info), + MBEDTLS_DECRYPT)) != 0) { + MBEDTLS_SSL_DEBUG_RET(1, "mbedtls_cipher_setkey", ret); + return ret; + } +#endif /* MBEDTLS_USE_PSA_CRYPTO */ + + /* + * Setup other fields in SSL transform + */ + + if ((ciphersuite_info->flags & MBEDTLS_CIPHERSUITE_SHORT_TAG) != 0) { + transform->taglen = 8; + } else { + transform->taglen = 16; + } + + transform->ivlen = traffic_keys->iv_len; + transform->maclen = 0; + transform->fixed_ivlen = transform->ivlen; + transform->tls_version = MBEDTLS_SSL_VERSION_TLS1_3; + + /* We add the true record content type (1 Byte) to the plaintext and + * then pad to the configured granularity. The minimum length of the + * type-extended and padded plaintext is therefore the padding + * granularity. */ + transform->minlen = + transform->taglen + MBEDTLS_SSL_CID_TLS1_3_PADDING_GRANULARITY; + +#if defined(MBEDTLS_USE_PSA_CRYPTO) + /* + * Setup psa keys and alg + */ + if ((status = mbedtls_ssl_cipher_to_psa((mbedtls_cipher_type_t) ciphersuite_info->cipher, + transform->taglen, + &alg, + &key_type, + &key_bits)) != PSA_SUCCESS) { + MBEDTLS_SSL_DEBUG_RET( + 1, "mbedtls_ssl_cipher_to_psa", PSA_TO_MBEDTLS_ERR(status)); + return PSA_TO_MBEDTLS_ERR(status); + } + + transform->psa_alg = alg; + + if (alg != MBEDTLS_SSL_NULL_CIPHER) { + psa_set_key_usage_flags(&attributes, PSA_KEY_USAGE_ENCRYPT); + psa_set_key_algorithm(&attributes, alg); + psa_set_key_type(&attributes, key_type); + + if ((status = psa_import_key(&attributes, + key_enc, + PSA_BITS_TO_BYTES(key_bits), + &transform->psa_key_enc)) != PSA_SUCCESS) { + MBEDTLS_SSL_DEBUG_RET( + 1, "psa_import_key", PSA_TO_MBEDTLS_ERR(status)); + return PSA_TO_MBEDTLS_ERR(status); + } + + psa_set_key_usage_flags(&attributes, PSA_KEY_USAGE_DECRYPT); + + if ((status = psa_import_key(&attributes, + key_dec, + PSA_BITS_TO_BYTES(key_bits), + &transform->psa_key_dec)) != PSA_SUCCESS) { + MBEDTLS_SSL_DEBUG_RET( + 1, "psa_import_key", PSA_TO_MBEDTLS_ERR(status)); + return PSA_TO_MBEDTLS_ERR(status); + } + } +#endif /* MBEDTLS_USE_PSA_CRYPTO */ + + return 0; +} + +MBEDTLS_CHECK_RETURN_CRITICAL +static int ssl_tls13_get_cipher_key_info( + const mbedtls_ssl_ciphersuite_t *ciphersuite_info, + size_t *key_len, size_t *iv_len) +{ + psa_key_type_t key_type; + psa_algorithm_t alg; + size_t taglen; + size_t key_bits; + psa_status_t status = PSA_ERROR_CORRUPTION_DETECTED; + + if (ciphersuite_info->flags & MBEDTLS_CIPHERSUITE_SHORT_TAG) { + taglen = 8; + } else { + taglen = 16; + } + + status = mbedtls_ssl_cipher_to_psa((mbedtls_cipher_type_t) ciphersuite_info->cipher, taglen, + &alg, &key_type, &key_bits); + if (status != PSA_SUCCESS) { + return PSA_TO_MBEDTLS_ERR(status); + } + + *key_len = PSA_BITS_TO_BYTES(key_bits); + + /* TLS 1.3 only have AEAD ciphers, IV length is unconditionally 12 bytes */ + *iv_len = 12; + + return 0; +} + +#if defined(MBEDTLS_SSL_EARLY_DATA) +/* + * ssl_tls13_generate_early_key() generates the key necessary for protecting + * the early application data and handshake messages as described in section 7 + * of RFC 8446. + * + * NOTE: Only one key is generated, the key for the traffic from the client to + * the server. The TLS 1.3 specification does not define a secret and thus + * a key for server early traffic. + */ +MBEDTLS_CHECK_RETURN_CRITICAL +static int ssl_tls13_generate_early_key(mbedtls_ssl_context *ssl, + mbedtls_ssl_key_set *traffic_keys) +{ + int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED; + mbedtls_md_type_t md_type; + psa_algorithm_t hash_alg; + size_t hash_len; + unsigned char transcript[MBEDTLS_TLS1_3_MD_MAX_SIZE]; + size_t transcript_len; + size_t key_len = 0; + size_t iv_len = 0; + mbedtls_ssl_tls13_early_secrets tls13_early_secrets; + + mbedtls_ssl_handshake_params *handshake = ssl->handshake; + const mbedtls_ssl_ciphersuite_t *ciphersuite_info = + handshake->ciphersuite_info; + + MBEDTLS_SSL_DEBUG_MSG(2, ("=> ssl_tls13_generate_early_key")); + + ret = ssl_tls13_get_cipher_key_info(ciphersuite_info, &key_len, &iv_len); + if (ret != 0) { + MBEDTLS_SSL_DEBUG_RET(1, "ssl_tls13_get_cipher_key_info", ret); + goto cleanup; + } + + md_type = (mbedtls_md_type_t) ciphersuite_info->mac; + + hash_alg = mbedtls_md_psa_alg_from_type((mbedtls_md_type_t) ciphersuite_info->mac); + hash_len = PSA_HASH_LENGTH(hash_alg); + + ret = mbedtls_ssl_get_handshake_transcript(ssl, md_type, + transcript, + sizeof(transcript), + &transcript_len); + if (ret != 0) { + MBEDTLS_SSL_DEBUG_RET(1, + "mbedtls_ssl_get_handshake_transcript", + ret); + goto cleanup; + } + + ret = mbedtls_ssl_tls13_derive_early_secrets( + hash_alg, handshake->tls13_master_secrets.early, + transcript, transcript_len, &tls13_early_secrets); + if (ret != 0) { + MBEDTLS_SSL_DEBUG_RET( + 1, "mbedtls_ssl_tls13_derive_early_secrets", ret); + goto cleanup; + } + + MBEDTLS_SSL_DEBUG_BUF( + 4, "Client early traffic secret", + tls13_early_secrets.client_early_traffic_secret, hash_len); + + /* + * Export client handshake traffic secret + */ + if (ssl->f_export_keys != NULL) { + ssl->f_export_keys( + ssl->p_export_keys, + MBEDTLS_SSL_KEY_EXPORT_TLS1_3_CLIENT_EARLY_SECRET, + tls13_early_secrets.client_early_traffic_secret, + hash_len, + handshake->randbytes, + handshake->randbytes + MBEDTLS_CLIENT_HELLO_RANDOM_LEN, + MBEDTLS_SSL_TLS_PRF_NONE /* TODO: FIX! */); + } + + ret = ssl_tls13_make_traffic_key( + hash_alg, + tls13_early_secrets.client_early_traffic_secret, + hash_len, traffic_keys->client_write_key, key_len, + traffic_keys->client_write_iv, iv_len); + if (ret != 0) { + MBEDTLS_SSL_DEBUG_RET(1, "ssl_tls13_make_traffic_key", ret); + goto cleanup; + } + traffic_keys->key_len = key_len; + traffic_keys->iv_len = iv_len; + + MBEDTLS_SSL_DEBUG_BUF(4, "client early write_key", + traffic_keys->client_write_key, + traffic_keys->key_len); + + MBEDTLS_SSL_DEBUG_BUF(4, "client early write_iv", + traffic_keys->client_write_iv, + traffic_keys->iv_len); + + MBEDTLS_SSL_DEBUG_MSG(2, ("<= ssl_tls13_generate_early_key")); + +cleanup: + /* Erase early secrets and transcript */ + mbedtls_platform_zeroize( + &tls13_early_secrets, sizeof(mbedtls_ssl_tls13_early_secrets)); + mbedtls_platform_zeroize(transcript, sizeof(transcript)); + return ret; +} + +int mbedtls_ssl_tls13_compute_early_transform(mbedtls_ssl_context *ssl) +{ + int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED; + mbedtls_ssl_key_set traffic_keys; + mbedtls_ssl_transform *transform_earlydata = NULL; + mbedtls_ssl_handshake_params *handshake = ssl->handshake; + + /* Next evolution in key schedule: Establish early_data secret and + * key material. */ + ret = ssl_tls13_generate_early_key(ssl, &traffic_keys); + if (ret != 0) { + MBEDTLS_SSL_DEBUG_RET(1, "ssl_tls13_generate_early_key", + ret); + goto cleanup; + } + + transform_earlydata = mbedtls_calloc(1, sizeof(mbedtls_ssl_transform)); + if (transform_earlydata == NULL) { + ret = MBEDTLS_ERR_SSL_ALLOC_FAILED; + goto cleanup; + } + + ret = mbedtls_ssl_tls13_populate_transform( + transform_earlydata, + ssl->conf->endpoint, + handshake->ciphersuite_info->id, + &traffic_keys, + ssl); + if (ret != 0) { + MBEDTLS_SSL_DEBUG_RET(1, "mbedtls_ssl_tls13_populate_transform", ret); + goto cleanup; + } + handshake->transform_earlydata = transform_earlydata; + +cleanup: + mbedtls_platform_zeroize(&traffic_keys, sizeof(traffic_keys)); + if (ret != 0) { + mbedtls_free(transform_earlydata); + } + + return ret; +} +#endif /* MBEDTLS_SSL_EARLY_DATA */ + +int mbedtls_ssl_tls13_key_schedule_stage_early(mbedtls_ssl_context *ssl) +{ + int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED; + psa_algorithm_t hash_alg; + mbedtls_ssl_handshake_params *handshake = ssl->handshake; + unsigned char *psk = NULL; + size_t psk_len = 0; + + if (handshake->ciphersuite_info == NULL) { + MBEDTLS_SSL_DEBUG_MSG(1, ("cipher suite info not found")); + return MBEDTLS_ERR_SSL_INTERNAL_ERROR; + } + + hash_alg = mbedtls_md_psa_alg_from_type((mbedtls_md_type_t) handshake->ciphersuite_info->mac); +#if defined(MBEDTLS_SSL_TLS1_3_KEY_EXCHANGE_MODE_SOME_PSK_ENABLED) + if (mbedtls_ssl_tls13_key_exchange_mode_with_psk(ssl)) { + ret = mbedtls_ssl_tls13_export_handshake_psk(ssl, &psk, &psk_len); + if (ret != 0) { + MBEDTLS_SSL_DEBUG_RET(1, "mbedtls_ssl_tls13_export_handshake_psk", + ret); + return ret; + } + } +#endif + + ret = mbedtls_ssl_tls13_evolve_secret(hash_alg, NULL, psk, psk_len, + handshake->tls13_master_secrets.early); +#if defined(MBEDTLS_USE_PSA_CRYPTO) && \ + defined(MBEDTLS_SSL_TLS1_3_KEY_EXCHANGE_MODE_SOME_PSK_ENABLED) + mbedtls_free((void *) psk); +#endif + if (ret != 0) { + MBEDTLS_SSL_DEBUG_RET(1, "mbedtls_ssl_tls13_evolve_secret", ret); + return ret; + } + + MBEDTLS_SSL_DEBUG_BUF(4, "mbedtls_ssl_tls13_key_schedule_stage_early", + handshake->tls13_master_secrets.early, + PSA_HASH_LENGTH(hash_alg)); + return 0; +} + +/** + * \brief Compute TLS 1.3 handshake traffic keys. + * + * ssl_tls13_generate_handshake_keys() generates keys necessary for + * protecting the handshake messages, as described in Section 7 of + * RFC 8446. + * + * \param ssl The SSL context to operate on. This must be in + * key schedule stage \c Handshake, see + * ssl_tls13_key_schedule_stage_handshake(). + * \param traffic_keys The address at which to store the handshake traffic + * keys. This must be writable but may be uninitialized. + * + * \returns \c 0 on success. + * \returns A negative error code on failure. + */ +MBEDTLS_CHECK_RETURN_CRITICAL +static int ssl_tls13_generate_handshake_keys(mbedtls_ssl_context *ssl, + mbedtls_ssl_key_set *traffic_keys) +{ + int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED; + mbedtls_md_type_t md_type; + psa_algorithm_t hash_alg; + size_t hash_len; + unsigned char transcript[MBEDTLS_TLS1_3_MD_MAX_SIZE]; + size_t transcript_len; + size_t key_len = 0; + size_t iv_len = 0; + + mbedtls_ssl_handshake_params *handshake = ssl->handshake; + const mbedtls_ssl_ciphersuite_t *ciphersuite_info = + handshake->ciphersuite_info; + mbedtls_ssl_tls13_handshake_secrets *tls13_hs_secrets = + &handshake->tls13_hs_secrets; + + MBEDTLS_SSL_DEBUG_MSG(2, ("=> ssl_tls13_generate_handshake_keys")); + + ret = ssl_tls13_get_cipher_key_info(ciphersuite_info, &key_len, &iv_len); + if (ret != 0) { + MBEDTLS_SSL_DEBUG_RET(1, "ssl_tls13_get_cipher_key_info", ret); + return ret; + } + + md_type = (mbedtls_md_type_t) ciphersuite_info->mac; + + hash_alg = mbedtls_md_psa_alg_from_type((mbedtls_md_type_t) ciphersuite_info->mac); + hash_len = PSA_HASH_LENGTH(hash_alg); + + ret = mbedtls_ssl_get_handshake_transcript(ssl, md_type, + transcript, + sizeof(transcript), + &transcript_len); + if (ret != 0) { + MBEDTLS_SSL_DEBUG_RET(1, + "mbedtls_ssl_get_handshake_transcript", + ret); + return ret; + } + + ret = mbedtls_ssl_tls13_derive_handshake_secrets( + hash_alg, handshake->tls13_master_secrets.handshake, + transcript, transcript_len, tls13_hs_secrets); + if (ret != 0) { + MBEDTLS_SSL_DEBUG_RET(1, "mbedtls_ssl_tls13_derive_handshake_secrets", + ret); + return ret; + } + + MBEDTLS_SSL_DEBUG_BUF(4, "Client handshake traffic secret", + tls13_hs_secrets->client_handshake_traffic_secret, + hash_len); + MBEDTLS_SSL_DEBUG_BUF(4, "Server handshake traffic secret", + tls13_hs_secrets->server_handshake_traffic_secret, + hash_len); + + /* + * Export client handshake traffic secret + */ + if (ssl->f_export_keys != NULL) { + ssl->f_export_keys( + ssl->p_export_keys, + MBEDTLS_SSL_KEY_EXPORT_TLS1_3_CLIENT_HANDSHAKE_TRAFFIC_SECRET, + tls13_hs_secrets->client_handshake_traffic_secret, + hash_len, + handshake->randbytes, + handshake->randbytes + MBEDTLS_CLIENT_HELLO_RANDOM_LEN, + MBEDTLS_SSL_TLS_PRF_NONE /* TODO: FIX! */); + + ssl->f_export_keys( + ssl->p_export_keys, + MBEDTLS_SSL_KEY_EXPORT_TLS1_3_SERVER_HANDSHAKE_TRAFFIC_SECRET, + tls13_hs_secrets->server_handshake_traffic_secret, + hash_len, + handshake->randbytes, + handshake->randbytes + MBEDTLS_CLIENT_HELLO_RANDOM_LEN, + MBEDTLS_SSL_TLS_PRF_NONE /* TODO: FIX! */); + } + + ret = mbedtls_ssl_tls13_make_traffic_keys( + hash_alg, + tls13_hs_secrets->client_handshake_traffic_secret, + tls13_hs_secrets->server_handshake_traffic_secret, + hash_len, key_len, iv_len, traffic_keys); + if (ret != 0) { + MBEDTLS_SSL_DEBUG_RET(1, "mbedtls_ssl_tls13_make_traffic_keys", ret); + goto exit; + } + + MBEDTLS_SSL_DEBUG_BUF(4, "client_handshake write_key", + traffic_keys->client_write_key, + traffic_keys->key_len); + + MBEDTLS_SSL_DEBUG_BUF(4, "server_handshake write_key", + traffic_keys->server_write_key, + traffic_keys->key_len); + + MBEDTLS_SSL_DEBUG_BUF(4, "client_handshake write_iv", + traffic_keys->client_write_iv, + traffic_keys->iv_len); + + MBEDTLS_SSL_DEBUG_BUF(4, "server_handshake write_iv", + traffic_keys->server_write_iv, + traffic_keys->iv_len); + + MBEDTLS_SSL_DEBUG_MSG(2, ("<= ssl_tls13_generate_handshake_keys")); + +exit: + + return ret; +} + +/** + * \brief Transition into handshake stage of TLS 1.3 key schedule. + * + * The TLS 1.3 key schedule can be viewed as a simple state machine + * with states Initial -> Early -> Handshake -> Application, and + * this function represents the Early -> Handshake transition. + * + * In the handshake stage, ssl_tls13_generate_handshake_keys() + * can be used to derive the handshake traffic keys. + * + * \param ssl The SSL context to operate on. This must be in key schedule + * stage \c Early. + * + * \returns \c 0 on success. + * \returns A negative error code on failure. + */ +MBEDTLS_CHECK_RETURN_CRITICAL +static int ssl_tls13_key_schedule_stage_handshake(mbedtls_ssl_context *ssl) +{ + int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED; + mbedtls_ssl_handshake_params *handshake = ssl->handshake; + psa_algorithm_t const hash_alg = mbedtls_md_psa_alg_from_type( + (mbedtls_md_type_t) handshake->ciphersuite_info->mac); + unsigned char *shared_secret = NULL; + size_t shared_secret_len = 0; + +#if defined(MBEDTLS_SSL_TLS1_3_KEY_EXCHANGE_MODE_SOME_EPHEMERAL_ENABLED) + /* + * Compute ECDHE secret used to compute the handshake secret from which + * client_handshake_traffic_secret and server_handshake_traffic_secret + * are derived in the handshake secret derivation stage. + */ + if (mbedtls_ssl_tls13_key_exchange_mode_with_ephemeral(ssl)) { + if (mbedtls_ssl_tls13_named_group_is_ecdhe(handshake->offered_group_id) || + mbedtls_ssl_tls13_named_group_is_ffdh(handshake->offered_group_id)) { +#if defined(PSA_WANT_ALG_ECDH) || defined(PSA_WANT_ALG_FFDH) + psa_algorithm_t alg = + mbedtls_ssl_tls13_named_group_is_ecdhe(handshake->offered_group_id) ? + PSA_ALG_ECDH : PSA_ALG_FFDH; + + /* Compute ECDH shared secret. */ + psa_status_t status = PSA_ERROR_GENERIC_ERROR; + psa_key_attributes_t key_attributes = PSA_KEY_ATTRIBUTES_INIT; + + status = psa_get_key_attributes(handshake->xxdh_psa_privkey, + &key_attributes); + if (status != PSA_SUCCESS) { + ret = PSA_TO_MBEDTLS_ERR(status); + } + + shared_secret_len = PSA_BITS_TO_BYTES( + psa_get_key_bits(&key_attributes)); + shared_secret = mbedtls_calloc(1, shared_secret_len); + if (shared_secret == NULL) { + return MBEDTLS_ERR_SSL_ALLOC_FAILED; + } + + status = psa_raw_key_agreement( + alg, handshake->xxdh_psa_privkey, + handshake->xxdh_psa_peerkey, handshake->xxdh_psa_peerkey_len, + shared_secret, shared_secret_len, &shared_secret_len); + if (status != PSA_SUCCESS) { + ret = PSA_TO_MBEDTLS_ERR(status); + MBEDTLS_SSL_DEBUG_RET(1, "psa_raw_key_agreement", ret); + goto cleanup; + } + + status = psa_destroy_key(handshake->xxdh_psa_privkey); + if (status != PSA_SUCCESS) { + ret = PSA_TO_MBEDTLS_ERR(status); + MBEDTLS_SSL_DEBUG_RET(1, "psa_destroy_key", ret); + goto cleanup; + } + + handshake->xxdh_psa_privkey = MBEDTLS_SVC_KEY_ID_INIT; +#endif /* PSA_WANT_ALG_ECDH || PSA_WANT_ALG_FFDH */ + } else { + MBEDTLS_SSL_DEBUG_MSG(1, ("Group not supported.")); + return MBEDTLS_ERR_SSL_FEATURE_UNAVAILABLE; + } + } +#endif /* MBEDTLS_SSL_TLS1_3_KEY_EXCHANGE_MODE_SOME_EPHEMERAL_ENABLED */ + + /* + * Compute the Handshake Secret + */ + ret = mbedtls_ssl_tls13_evolve_secret( + hash_alg, handshake->tls13_master_secrets.early, + shared_secret, shared_secret_len, + handshake->tls13_master_secrets.handshake); + if (ret != 0) { + MBEDTLS_SSL_DEBUG_RET(1, "mbedtls_ssl_tls13_evolve_secret", ret); + goto cleanup; + } + + MBEDTLS_SSL_DEBUG_BUF(4, "Handshake secret", + handshake->tls13_master_secrets.handshake, + PSA_HASH_LENGTH(hash_alg)); + +cleanup: + if (shared_secret != NULL) { + mbedtls_zeroize_and_free(shared_secret, shared_secret_len); + } + + return ret; +} + +/** + * \brief Compute TLS 1.3 application traffic keys. + * + * ssl_tls13_generate_application_keys() generates application traffic + * keys, since any record following a 1-RTT Finished message MUST be + * encrypted under the application traffic key. + * + * \param ssl The SSL context to operate on. This must be in + * key schedule stage \c Application, see + * ssl_tls13_key_schedule_stage_application(). + * \param traffic_keys The address at which to store the application traffic + * keys. This must be writable but may be uninitialized. + * + * \returns \c 0 on success. + * \returns A negative error code on failure. + */ +MBEDTLS_CHECK_RETURN_CRITICAL +static int ssl_tls13_generate_application_keys( + mbedtls_ssl_context *ssl, + mbedtls_ssl_key_set *traffic_keys) +{ + int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED; + mbedtls_ssl_handshake_params *handshake = ssl->handshake; + + /* Address at which to store the application secrets */ + mbedtls_ssl_tls13_application_secrets * const app_secrets = + &ssl->session_negotiate->app_secrets; + + /* Holding the transcript up to and including the ServerFinished */ + unsigned char transcript[MBEDTLS_TLS1_3_MD_MAX_SIZE]; + size_t transcript_len; + + /* Variables relating to the hash for the chosen ciphersuite. */ + mbedtls_md_type_t md_type; + + psa_algorithm_t hash_alg; + size_t hash_len; + + /* Variables relating to the cipher for the chosen ciphersuite. */ + size_t key_len = 0, iv_len = 0; + + MBEDTLS_SSL_DEBUG_MSG(2, ("=> derive application traffic keys")); + + /* Extract basic information about hash and ciphersuite */ + + ret = ssl_tls13_get_cipher_key_info(handshake->ciphersuite_info, + &key_len, &iv_len); + if (ret != 0) { + MBEDTLS_SSL_DEBUG_RET(1, "ssl_tls13_get_cipher_key_info", ret); + goto cleanup; + } + + md_type = (mbedtls_md_type_t) handshake->ciphersuite_info->mac; + + hash_alg = mbedtls_md_psa_alg_from_type((mbedtls_md_type_t) handshake->ciphersuite_info->mac); + hash_len = PSA_HASH_LENGTH(hash_alg); + + /* Compute current handshake transcript. It's the caller's responsibility + * to call this at the right time, that is, after the ServerFinished. */ + + ret = mbedtls_ssl_get_handshake_transcript(ssl, md_type, + transcript, sizeof(transcript), + &transcript_len); + if (ret != 0) { + goto cleanup; + } + + /* Compute application secrets from master secret and transcript hash. */ + + ret = mbedtls_ssl_tls13_derive_application_secrets( + hash_alg, handshake->tls13_master_secrets.app, + transcript, transcript_len, app_secrets); + if (ret != 0) { + MBEDTLS_SSL_DEBUG_RET( + 1, "mbedtls_ssl_tls13_derive_application_secrets", ret); + goto cleanup; + } + + /* Derive first epoch of IV + Key for application traffic. */ + + ret = mbedtls_ssl_tls13_make_traffic_keys( + hash_alg, + app_secrets->client_application_traffic_secret_N, + app_secrets->server_application_traffic_secret_N, + hash_len, key_len, iv_len, traffic_keys); + if (ret != 0) { + MBEDTLS_SSL_DEBUG_RET(1, "mbedtls_ssl_tls13_make_traffic_keys", ret); + goto cleanup; + } + + MBEDTLS_SSL_DEBUG_BUF(4, "Client application traffic secret", + app_secrets->client_application_traffic_secret_N, + hash_len); + + MBEDTLS_SSL_DEBUG_BUF(4, "Server application traffic secret", + app_secrets->server_application_traffic_secret_N, + hash_len); + + /* + * Export client/server application traffic secret 0 + */ + if (ssl->f_export_keys != NULL) { + ssl->f_export_keys( + ssl->p_export_keys, + MBEDTLS_SSL_KEY_EXPORT_TLS1_3_CLIENT_APPLICATION_TRAFFIC_SECRET, + app_secrets->client_application_traffic_secret_N, hash_len, + handshake->randbytes, + handshake->randbytes + MBEDTLS_CLIENT_HELLO_RANDOM_LEN, + MBEDTLS_SSL_TLS_PRF_NONE /* TODO: this should be replaced by + a new constant for TLS 1.3! */); + + ssl->f_export_keys( + ssl->p_export_keys, + MBEDTLS_SSL_KEY_EXPORT_TLS1_3_SERVER_APPLICATION_TRAFFIC_SECRET, + app_secrets->server_application_traffic_secret_N, hash_len, + handshake->randbytes, + handshake->randbytes + MBEDTLS_CLIENT_HELLO_RANDOM_LEN, + MBEDTLS_SSL_TLS_PRF_NONE /* TODO: this should be replaced by + a new constant for TLS 1.3! */); + } + + MBEDTLS_SSL_DEBUG_BUF(4, "client application_write_key:", + traffic_keys->client_write_key, key_len); + MBEDTLS_SSL_DEBUG_BUF(4, "server application write key", + traffic_keys->server_write_key, key_len); + MBEDTLS_SSL_DEBUG_BUF(4, "client application write IV", + traffic_keys->client_write_iv, iv_len); + MBEDTLS_SSL_DEBUG_BUF(4, "server application write IV", + traffic_keys->server_write_iv, iv_len); + + MBEDTLS_SSL_DEBUG_MSG(2, ("<= derive application traffic keys")); + +cleanup: + /* randbytes is not used again */ + mbedtls_platform_zeroize(ssl->handshake->randbytes, + sizeof(ssl->handshake->randbytes)); + + mbedtls_platform_zeroize(transcript, sizeof(transcript)); + return ret; +} + +int mbedtls_ssl_tls13_compute_handshake_transform(mbedtls_ssl_context *ssl) +{ + int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED; + mbedtls_ssl_key_set traffic_keys; + mbedtls_ssl_transform *transform_handshake = NULL; + mbedtls_ssl_handshake_params *handshake = ssl->handshake; + + /* Compute handshake secret */ + ret = ssl_tls13_key_schedule_stage_handshake(ssl); + if (ret != 0) { + MBEDTLS_SSL_DEBUG_RET(1, "mbedtls_ssl_tls13_derive_master_secret", ret); + goto cleanup; + } + + /* Next evolution in key schedule: Establish handshake secret and + * key material. */ + ret = ssl_tls13_generate_handshake_keys(ssl, &traffic_keys); + if (ret != 0) { + MBEDTLS_SSL_DEBUG_RET(1, "ssl_tls13_generate_handshake_keys", + ret); + goto cleanup; + } + + transform_handshake = mbedtls_calloc(1, sizeof(mbedtls_ssl_transform)); + if (transform_handshake == NULL) { + ret = MBEDTLS_ERR_SSL_ALLOC_FAILED; + goto cleanup; + } + + ret = mbedtls_ssl_tls13_populate_transform( + transform_handshake, + ssl->conf->endpoint, + handshake->ciphersuite_info->id, + &traffic_keys, + ssl); + if (ret != 0) { + MBEDTLS_SSL_DEBUG_RET(1, "mbedtls_ssl_tls13_populate_transform", ret); + goto cleanup; + } + handshake->transform_handshake = transform_handshake; + +cleanup: + mbedtls_platform_zeroize(&traffic_keys, sizeof(traffic_keys)); + if (ret != 0) { + mbedtls_free(transform_handshake); + } + + return ret; +} + +int mbedtls_ssl_tls13_compute_resumption_master_secret(mbedtls_ssl_context *ssl) +{ + int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED; + mbedtls_md_type_t md_type; + mbedtls_ssl_handshake_params *handshake = ssl->handshake; + unsigned char transcript[MBEDTLS_TLS1_3_MD_MAX_SIZE]; + size_t transcript_len; + + MBEDTLS_SSL_DEBUG_MSG( + 2, ("=> mbedtls_ssl_tls13_compute_resumption_master_secret")); + + md_type = (mbedtls_md_type_t) handshake->ciphersuite_info->mac; + + ret = mbedtls_ssl_get_handshake_transcript(ssl, md_type, + transcript, sizeof(transcript), + &transcript_len); + if (ret != 0) { + return ret; + } + + ret = mbedtls_ssl_tls13_derive_resumption_master_secret( + mbedtls_md_psa_alg_from_type(md_type), + handshake->tls13_master_secrets.app, + transcript, transcript_len, + &ssl->session_negotiate->app_secrets); + if (ret != 0) { + return ret; + } + + /* Erase master secrets */ + mbedtls_platform_zeroize(&handshake->tls13_master_secrets, + sizeof(handshake->tls13_master_secrets)); + + MBEDTLS_SSL_DEBUG_BUF( + 4, "Resumption master secret", + ssl->session_negotiate->app_secrets.resumption_master_secret, + PSA_HASH_LENGTH(mbedtls_md_psa_alg_from_type(md_type))); + + MBEDTLS_SSL_DEBUG_MSG( + 2, ("<= mbedtls_ssl_tls13_compute_resumption_master_secret")); + return 0; +} + +int mbedtls_ssl_tls13_compute_application_transform(mbedtls_ssl_context *ssl) +{ + int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED; + mbedtls_ssl_key_set traffic_keys; + mbedtls_ssl_transform *transform_application = NULL; + + ret = ssl_tls13_key_schedule_stage_application(ssl); + if (ret != 0) { + MBEDTLS_SSL_DEBUG_RET(1, + "ssl_tls13_key_schedule_stage_application", ret); + goto cleanup; + } + + ret = ssl_tls13_generate_application_keys(ssl, &traffic_keys); + if (ret != 0) { + MBEDTLS_SSL_DEBUG_RET(1, + "ssl_tls13_generate_application_keys", ret); + goto cleanup; + } + + transform_application = + mbedtls_calloc(1, sizeof(mbedtls_ssl_transform)); + if (transform_application == NULL) { + ret = MBEDTLS_ERR_SSL_ALLOC_FAILED; + goto cleanup; + } + + ret = mbedtls_ssl_tls13_populate_transform( + transform_application, + ssl->conf->endpoint, + ssl->handshake->ciphersuite_info->id, + &traffic_keys, + ssl); + if (ret != 0) { + MBEDTLS_SSL_DEBUG_RET(1, "mbedtls_ssl_tls13_populate_transform", ret); + goto cleanup; + } + + ssl->transform_application = transform_application; + +cleanup: + + mbedtls_platform_zeroize(&traffic_keys, sizeof(traffic_keys)); + if (ret != 0) { + mbedtls_free(transform_application); + } + return ret; +} + +#if defined(MBEDTLS_SSL_TLS1_3_KEY_EXCHANGE_MODE_SOME_PSK_ENABLED) +int mbedtls_ssl_tls13_export_handshake_psk(mbedtls_ssl_context *ssl, + unsigned char **psk, + size_t *psk_len) +{ +#if defined(MBEDTLS_USE_PSA_CRYPTO) + psa_key_attributes_t key_attributes = PSA_KEY_ATTRIBUTES_INIT; + psa_status_t status = PSA_ERROR_CORRUPTION_DETECTED; + + *psk_len = 0; + *psk = NULL; + + if (mbedtls_svc_key_id_is_null(ssl->handshake->psk_opaque)) { + return MBEDTLS_ERR_SSL_INTERNAL_ERROR; + } + + status = psa_get_key_attributes(ssl->handshake->psk_opaque, &key_attributes); + if (status != PSA_SUCCESS) { + return PSA_TO_MBEDTLS_ERR(status); + } + + *psk_len = PSA_BITS_TO_BYTES(psa_get_key_bits(&key_attributes)); + *psk = mbedtls_calloc(1, *psk_len); + if (*psk == NULL) { + return MBEDTLS_ERR_SSL_ALLOC_FAILED; + } + + status = psa_export_key(ssl->handshake->psk_opaque, + (uint8_t *) *psk, *psk_len, psk_len); + if (status != PSA_SUCCESS) { + mbedtls_free((void *) *psk); + *psk = NULL; + return PSA_TO_MBEDTLS_ERR(status); + } + return 0; +#else + *psk = ssl->handshake->psk; + *psk_len = ssl->handshake->psk_len; + if (*psk == NULL) { + return MBEDTLS_ERR_SSL_INTERNAL_ERROR; + } + return 0; +#endif /* !MBEDTLS_USE_PSA_CRYPTO */ +} +#endif /* MBEDTLS_SSL_TLS1_3_KEY_EXCHANGE_MODE_SOME_PSK_ENABLED */ + +#endif /* MBEDTLS_SSL_PROTO_TLS1_3 */ diff --git a/vendor/mbedtls/library/ssl_tls13_keys.h b/vendor/mbedtls/library/ssl_tls13_keys.h index 4c3b252fa2..d3a4c6c992 100644 --- a/vendor/mbedtls/library/ssl_tls13_keys.h +++ b/vendor/mbedtls/library/ssl_tls13_keys.h @@ -2,27 +2,15 @@ * TLS 1.3 key schedule * * Copyright The Mbed TLS Contributors - * SPDX-License-Identifier: Apache-2.0 - * - * Licensed under the Apache License, Version 2.0 ( the "License" ); you may - * not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT - * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. + * SPDX-License-Identifier: Apache-2.0 OR GPL-2.0-or-later */ #if !defined(MBEDTLS_SSL_TLS1_3_KEYS_H) #define MBEDTLS_SSL_TLS1_3_KEYS_H /* This requires MBEDTLS_SSL_TLS1_3_LABEL( idx, name, string ) to be defined at - * the point of use. See e.g. the definition of mbedtls_ssl_tls1_3_labels_union + * the point of use. See e.g. the definition of mbedtls_ssl_tls13_labels_union * below. */ -#define MBEDTLS_SSL_TLS1_3_LABEL_LIST \ +#define MBEDTLS_SSL_TLS1_3_LABEL_LIST \ MBEDTLS_SSL_TLS1_3_LABEL(finished, "finished") \ MBEDTLS_SSL_TLS1_3_LABEL(resumption, "resumption") \ MBEDTLS_SSL_TLS1_3_LABEL(traffic_upd, "traffic upd") \ @@ -40,76 +28,92 @@ MBEDTLS_SSL_TLS1_3_LABEL(exp_master, "exp master") \ MBEDTLS_SSL_TLS1_3_LABEL(ext_binder, "ext binder") \ MBEDTLS_SSL_TLS1_3_LABEL(res_binder, "res binder") \ - MBEDTLS_SSL_TLS1_3_LABEL(derived, "derived") + MBEDTLS_SSL_TLS1_3_LABEL(derived, "derived") \ + MBEDTLS_SSL_TLS1_3_LABEL(client_cv, "TLS 1.3, client CertificateVerify") \ + MBEDTLS_SSL_TLS1_3_LABEL(server_cv, "TLS 1.3, server CertificateVerify") + +#define MBEDTLS_SSL_TLS1_3_CONTEXT_UNHASHED 0 +#define MBEDTLS_SSL_TLS1_3_CONTEXT_HASHED 1 + +#define MBEDTLS_SSL_TLS1_3_PSK_EXTERNAL 0 +#define MBEDTLS_SSL_TLS1_3_PSK_RESUMPTION 1 + +#if defined(MBEDTLS_SSL_PROTO_TLS1_3) #define MBEDTLS_SSL_TLS1_3_LABEL(name, string) \ const unsigned char name [sizeof(string) - 1]; -union mbedtls_ssl_tls1_3_labels_union { +union mbedtls_ssl_tls13_labels_union { MBEDTLS_SSL_TLS1_3_LABEL_LIST }; -struct mbedtls_ssl_tls1_3_labels_struct { +struct mbedtls_ssl_tls13_labels_struct { MBEDTLS_SSL_TLS1_3_LABEL_LIST }; #undef MBEDTLS_SSL_TLS1_3_LABEL -extern const struct mbedtls_ssl_tls1_3_labels_struct mbedtls_ssl_tls1_3_labels; +extern const struct mbedtls_ssl_tls13_labels_struct mbedtls_ssl_tls13_labels; + +#define MBEDTLS_SSL_TLS1_3_LBL_LEN(LABEL) \ + sizeof(mbedtls_ssl_tls13_labels.LABEL) #define MBEDTLS_SSL_TLS1_3_LBL_WITH_LEN(LABEL) \ - mbedtls_ssl_tls1_3_labels.LABEL, \ - sizeof(mbedtls_ssl_tls1_3_labels.LABEL) + mbedtls_ssl_tls13_labels.LABEL, \ + MBEDTLS_SSL_TLS1_3_LBL_LEN(LABEL) #define MBEDTLS_SSL_TLS1_3_KEY_SCHEDULE_MAX_LABEL_LEN \ - sizeof(union mbedtls_ssl_tls1_3_labels_union) + sizeof(union mbedtls_ssl_tls13_labels_union) /* The maximum length of HKDF contexts used in the TLS 1.3 standard. * Since contexts are always hashes of message transcripts, this can * be approximated from above by the maximum hash size. */ #define MBEDTLS_SSL_TLS1_3_KEY_SCHEDULE_MAX_CONTEXT_LEN \ - MBEDTLS_MD_MAX_SIZE + PSA_HASH_MAX_SIZE /* Maximum desired length for expanded key material generated * by HKDF-Expand-Label. * * Warning: If this ever needs to be increased, the implementation - * ssl_tls1_3_hkdf_encode_label() in ssl_tls13_keys.c needs to be + * ssl_tls13_hkdf_encode_label() in ssl_tls13_keys.c needs to be * adjusted since it currently assumes that HKDF key expansion * is never used with more than 255 Bytes of output. */ #define MBEDTLS_SSL_TLS1_3_KEY_SCHEDULE_MAX_EXPANSION_LEN 255 /** - * \brief The \c HKDF-Expand-Label function from - * the TLS 1.3 standard RFC 8446. + * \brief The \c HKDF-Expand-Label function from + * the TLS 1.3 standard RFC 8446. * * - * HKDF-Expand-Label( Secret, Label, Context, Length ) = + * HKDF-Expand-Label( Secret, Label, Context, Length ) = * HKDF-Expand( Secret, HkdfLabel, Length ) * * - * \param hash_alg The identifier for the hash algorithm to use. - * \param secret The \c Secret argument to \c HKDF-Expand-Label. - * This must be a readable buffer of length \p slen Bytes. - * \param slen The length of \p secret in Bytes. - * \param label The \c Label argument to \c HKDF-Expand-Label. - * This must be a readable buffer of length \p llen Bytes. - * \param llen The length of \p label in Bytes. - * \param ctx The \c Context argument to \c HKDF-Expand-Label. - * This must be a readable buffer of length \p clen Bytes. - * \param clen The length of \p context in Bytes. - * \param buf The destination buffer to hold the expanded secret. - * This must be a writable buffer of length \p blen Bytes. - * \param blen The desired size of the expanded secret in Bytes. - * - * \returns \c 0 on success. - * \return A negative error code on failure. + * \param hash_alg The identifier for the hash algorithm to use. + * \param secret The \c Secret argument to \c HKDF-Expand-Label. + * This must be a readable buffer of length + * \p secret_len Bytes. + * \param secret_len The length of \p secret in Bytes. + * \param label The \c Label argument to \c HKDF-Expand-Label. + * This must be a readable buffer of length + * \p label_len Bytes. + * \param label_len The length of \p label in Bytes. + * \param ctx The \c Context argument to \c HKDF-Expand-Label. + * This must be a readable buffer of length \p ctx_len Bytes. + * \param ctx_len The length of \p context in Bytes. + * \param buf The destination buffer to hold the expanded secret. + * This must be a writable buffer of length \p buf_len Bytes. + * \param buf_len The desired size of the expanded secret in Bytes. + * + * \returns \c 0 on success. + * \return A negative error code on failure. */ -int mbedtls_ssl_tls1_3_hkdf_expand_label( - mbedtls_md_type_t hash_alg, - const unsigned char *secret, size_t slen, - const unsigned char *label, size_t llen, - const unsigned char *ctx, size_t clen, - unsigned char *buf, size_t blen); +MBEDTLS_CHECK_RETURN_CRITICAL +int mbedtls_ssl_tls13_hkdf_expand_label( + psa_algorithm_t hash_alg, + const unsigned char *secret, size_t secret_len, + const unsigned char *label, size_t label_len, + const unsigned char *ctx, size_t ctx_len, + unsigned char *buf, size_t buf_len); /** * \brief This function is part of the TLS 1.3 key schedule. @@ -126,10 +130,12 @@ int mbedtls_ssl_tls1_3_hkdf_expand_label( * \param hash_alg The identifier for the hash algorithm to be used * for the HKDF-based expansion of the secret. * \param client_secret The client traffic secret. - * This must be a readable buffer of size \p slen Bytes + * This must be a readable buffer of size + * \p secret_len Bytes * \param server_secret The server traffic secret. - * This must be a readable buffer of size \p slen Bytes - * \param slen Length of the secrets \p client_secret and + * This must be a readable buffer of size + * \p secret_len Bytes + * \param secret_len Length of the secrets \p client_secret and * \p server_secret in Bytes. * \param key_len The desired length of the key to be extracted in Bytes. * \param iv_len The desired length of the IV to be extracted in Bytes. @@ -140,17 +146,14 @@ int mbedtls_ssl_tls1_3_hkdf_expand_label( * \returns A negative error code on failure. */ -int mbedtls_ssl_tls1_3_make_traffic_keys( - mbedtls_md_type_t hash_alg, +MBEDTLS_CHECK_RETURN_CRITICAL +int mbedtls_ssl_tls13_make_traffic_keys( + psa_algorithm_t hash_alg, const unsigned char *client_secret, - const unsigned char *server_secret, - size_t slen, size_t key_len, size_t iv_len, + const unsigned char *server_secret, size_t secret_len, + size_t key_len, size_t iv_len, mbedtls_ssl_key_set *keys); - -#define MBEDTLS_SSL_TLS1_3_CONTEXT_UNHASHED 0 -#define MBEDTLS_SSL_TLS1_3_CONTEXT_HASHED 1 - /** * \brief The \c Derive-Secret function from the TLS 1.3 standard RFC 8446. * @@ -164,15 +167,17 @@ int mbedtls_ssl_tls1_3_make_traffic_keys( * \param hash_alg The identifier for the hash function used for the * applications of HKDF. * \param secret The \c Secret argument to the \c Derive-Secret function. - * This must be a readable buffer of length \p slen Bytes. - * \param slen The length of \p secret in Bytes. + * This must be a readable buffer of length + * \p secret_len Bytes. + * \param secret_len The length of \p secret in Bytes. * \param label The \c Label argument to the \c Derive-Secret function. - * This must be a readable buffer of length \p llen Bytes. - * \param llen The length of \p label in Bytes. + * This must be a readable buffer of length + * \p label_len Bytes. + * \param label_len The length of \p label in Bytes. * \param ctx The hash of the \c Messages argument to the * \c Derive-Secret function, or the \c Messages argument - * itself, depending on \p context_already_hashed. - * \param clen The length of \p hash. + * itself, depending on \p ctx_hashed. + * \param ctx_len The length of \p ctx in Bytes. * \param ctx_hashed This indicates whether the \p ctx contains the hash of * the \c Messages argument in the application of the * \c Derive-Secret function @@ -182,19 +187,197 @@ int mbedtls_ssl_tls1_3_make_traffic_keys( * (value MBEDTLS_SSL_TLS1_3_CONTEXT_UNHASHED). * \param dstbuf The target buffer to write the output of * \c Derive-Secret to. This must be a writable buffer of - * size \p buflen Bytes. - * \param buflen The length of \p dstbuf in Bytes. + * size \p dtsbuf_len Bytes. + * \param dstbuf_len The length of \p dstbuf in Bytes. * * \returns \c 0 on success. * \returns A negative error code on failure. */ -int mbedtls_ssl_tls1_3_derive_secret( - mbedtls_md_type_t hash_alg, - const unsigned char *secret, size_t slen, - const unsigned char *label, size_t llen, - const unsigned char *ctx, size_t clen, +MBEDTLS_CHECK_RETURN_CRITICAL +int mbedtls_ssl_tls13_derive_secret( + psa_algorithm_t hash_alg, + const unsigned char *secret, size_t secret_len, + const unsigned char *label, size_t label_len, + const unsigned char *ctx, size_t ctx_len, int ctx_hashed, - unsigned char *dstbuf, size_t buflen); + unsigned char *dstbuf, size_t dstbuf_len); + +/** + * \brief Derive TLS 1.3 early data key material from early secret. + * + * This is a small wrapper invoking mbedtls_ssl_tls13_derive_secret() + * with the appropriate labels. + * + * + * Early Secret + * | + * +-----> Derive-Secret(., "c e traffic", ClientHello) + * | = client_early_traffic_secret + * | + * +-----> Derive-Secret(., "e exp master", ClientHello) + * . = early_exporter_master_secret + * . + * . + * + * + * \note To obtain the actual key and IV for the early data traffic, + * the client secret derived by this function need to be + * further processed by mbedtls_ssl_tls13_make_traffic_keys(). + * + * \note The binder key, which is also generated from the early secret, + * is omitted here. Its calculation is part of the separate routine + * mbedtls_ssl_tls13_create_psk_binder(). + * + * \param hash_alg The hash algorithm associated with the PSK for which + * early data key material is being derived. + * \param early_secret The early secret from which the early data key material + * should be derived. This must be a readable buffer whose + * length is the digest size of the hash algorithm + * represented by \p md_size. + * \param transcript The transcript of the handshake so far, calculated with + * respect to \p hash_alg. This must be a readable buffer + * whose length is the digest size of the hash algorithm + * represented by \p md_size. + * \param derived The address of the structure in which to store + * the early data key material. + * + * \returns \c 0 on success. + * \returns A negative error code on failure. + */ +MBEDTLS_CHECK_RETURN_CRITICAL +int mbedtls_ssl_tls13_derive_early_secrets( + psa_algorithm_t hash_alg, + unsigned char const *early_secret, + unsigned char const *transcript, size_t transcript_len, + mbedtls_ssl_tls13_early_secrets *derived); + +/** + * \brief Derive TLS 1.3 handshake key material from the handshake secret. + * + * This is a small wrapper invoking mbedtls_ssl_tls13_derive_secret() + * with the appropriate labels from the standard. + * + * + * Handshake Secret + * | + * +-----> Derive-Secret( ., "c hs traffic", + * | ClientHello...ServerHello ) + * | = client_handshake_traffic_secret + * | + * +-----> Derive-Secret( ., "s hs traffic", + * . ClientHello...ServerHello ) + * . = server_handshake_traffic_secret + * . + * + * + * \note To obtain the actual key and IV for the encrypted handshake traffic, + * the client and server secret derived by this function need to be + * further processed by mbedtls_ssl_tls13_make_traffic_keys(). + * + * \param hash_alg The hash algorithm associated with the ciphersuite + * that's being used for the connection. + * \param handshake_secret The handshake secret from which the handshake key + * material should be derived. This must be a readable + * buffer whose length is the digest size of the hash + * algorithm represented by \p md_size. + * \param transcript The transcript of the handshake so far, calculated + * with respect to \p hash_alg. This must be a readable + * buffer whose length is the digest size of the hash + * algorithm represented by \p md_size. + * \param derived The address of the structure in which to + * store the handshake key material. + * + * \returns \c 0 on success. + * \returns A negative error code on failure. + */ +MBEDTLS_CHECK_RETURN_CRITICAL +int mbedtls_ssl_tls13_derive_handshake_secrets( + psa_algorithm_t hash_alg, + unsigned char const *handshake_secret, + unsigned char const *transcript, size_t transcript_len, + mbedtls_ssl_tls13_handshake_secrets *derived); + +/** + * \brief Derive TLS 1.3 application key material from the master secret. + * + * This is a small wrapper invoking mbedtls_ssl_tls13_derive_secret() + * with the appropriate labels from the standard. + * + * + * Master Secret + * | + * +-----> Derive-Secret( ., "c ap traffic", + * | ClientHello...server Finished ) + * | = client_application_traffic_secret_0 + * | + * +-----> Derive-Secret( ., "s ap traffic", + * | ClientHello...Server Finished ) + * | = server_application_traffic_secret_0 + * | + * +-----> Derive-Secret( ., "exp master", + * . ClientHello...server Finished) + * . = exporter_master_secret + * . + * + * + * \note To obtain the actual key and IV for the (0-th) application traffic, + * the client and server secret derived by this function need to be + * further processed by mbedtls_ssl_tls13_make_traffic_keys(). + * + * \param hash_alg The hash algorithm associated with the ciphersuite + * that's being used for the connection. + * \param master_secret The master secret from which the application key + * material should be derived. This must be a readable + * buffer whose length is the digest size of the hash + * algorithm represented by \p md_size. + * \param transcript The transcript of the handshake up to and including + * the ServerFinished message, calculated with respect + * to \p hash_alg. This must be a readable buffer whose + * length is the digest size of the hash algorithm + * represented by \p hash_alg. + * \param derived The address of the structure in which to + * store the application key material. + * + * \returns \c 0 on success. + * \returns A negative error code on failure. + */ +MBEDTLS_CHECK_RETURN_CRITICAL +int mbedtls_ssl_tls13_derive_application_secrets( + psa_algorithm_t hash_alg, + unsigned char const *master_secret, + unsigned char const *transcript, size_t transcript_len, + mbedtls_ssl_tls13_application_secrets *derived); + +/** + * \brief Derive TLS 1.3 resumption master secret from the master secret. + * + * This is a small wrapper invoking mbedtls_ssl_tls13_derive_secret() + * with the appropriate labels from the standard. + * + * \param hash_alg The hash algorithm used in the application for which + * key material is being derived. + * \param application_secret The application secret from which the resumption master + * secret should be derived. This must be a readable + * buffer whose length is the digest size of the hash + * algorithm represented by \p md_size. + * \param transcript The transcript of the handshake up to and including + * the ClientFinished message, calculated with respect + * to \p hash_alg. This must be a readable buffer whose + * length is the digest size of the hash algorithm + * represented by \p hash_alg. + * \param transcript_len The length of \p transcript in Bytes. + * \param derived The address of the structure in which to + * store the resumption master secret. + * + * \returns \c 0 on success. + * \returns A negative error code on failure. + */ +MBEDTLS_CHECK_RETURN_CRITICAL +int mbedtls_ssl_tls13_derive_resumption_master_secret( + psa_algorithm_t hash_alg, + unsigned char const *application_secret, + unsigned char const *transcript, size_t transcript_len, + mbedtls_ssl_tls13_application_secrets *derived); /** * \brief Compute the next secret in the TLS 1.3 key schedule @@ -226,7 +409,7 @@ int mbedtls_ssl_tls1_3_derive_secret( * * Each of the three secrets in turn is the basis for further * key derivations, such as the derivation of traffic keys and IVs; - * see e.g. mbedtls_ssl_tls1_3_make_traffic_keys(). + * see e.g. mbedtls_ssl_tls13_make_traffic_keys(). * * This function implements one step in this evolution of secrets: * @@ -263,10 +446,206 @@ int mbedtls_ssl_tls1_3_derive_secret( * \returns A negative error code on failure. */ -int mbedtls_ssl_tls1_3_evolve_secret( - mbedtls_md_type_t hash_alg, +MBEDTLS_CHECK_RETURN_CRITICAL +int mbedtls_ssl_tls13_evolve_secret( + psa_algorithm_t hash_alg, const unsigned char *secret_old, const unsigned char *input, size_t input_len, unsigned char *secret_new); +/** + * \brief Calculate a TLS 1.3 PSK binder. + * + * \param ssl The SSL context. This is used for debugging only and may + * be \c NULL if MBEDTLS_DEBUG_C is disabled. + * \param hash_alg The hash algorithm associated to the PSK \p psk. + * \param psk The buffer holding the PSK for which to create a binder. + * \param psk_len The size of \p psk in bytes. + * \param psk_type This indicates whether the PSK \p psk is externally + * provisioned (#MBEDTLS_SSL_TLS1_3_PSK_EXTERNAL) or a + * resumption PSK (#MBEDTLS_SSL_TLS1_3_PSK_RESUMPTION). + * \param transcript The handshake transcript up to the point where the + * PSK binder calculation happens. This must be readable, + * and its size must be equal to the digest size of + * the hash algorithm represented by \p hash_alg. + * \param result The address at which to store the PSK binder on success. + * This must be writable, and its size must be equal to the + * digest size of the hash algorithm represented by + * \p hash_alg. + * + * \returns \c 0 on success. + * \returns A negative error code on failure. + */ +MBEDTLS_CHECK_RETURN_CRITICAL +int mbedtls_ssl_tls13_create_psk_binder(mbedtls_ssl_context *ssl, + const psa_algorithm_t hash_alg, + unsigned char const *psk, size_t psk_len, + int psk_type, + unsigned char const *transcript, + unsigned char *result); + +/** + * \bref Setup an SSL transform structure representing the + * record protection mechanism used by TLS 1.3 + * + * \param transform The SSL transform structure to be created. This must have + * been initialized through mbedtls_ssl_transform_init() and + * not used in any other way prior to calling this function. + * In particular, this function does not clean up the + * transform structure prior to installing the new keys. + * \param endpoint Indicates whether the transform is for the client + * (value #MBEDTLS_SSL_IS_CLIENT) or the server + * (value #MBEDTLS_SSL_IS_SERVER). + * \param ciphersuite The numerical identifier for the ciphersuite to use. + * This must be one of the identifiers listed in + * ssl_ciphersuites.h. + * \param traffic_keys The key material to use. No reference is stored in + * the SSL transform being generated, and the caller + * should destroy the key material afterwards. + * \param ssl (Debug-only) The SSL context to use for debug output + * in case of failure. This parameter is only needed if + * #MBEDTLS_DEBUG_C is set, and is ignored otherwise. + * + * \return \c 0 on success. In this case, \p transform is ready to + * be used with mbedtls_ssl_transform_decrypt() and + * mbedtls_ssl_transform_encrypt(). + * \return A negative error code on failure. + */ +MBEDTLS_CHECK_RETURN_CRITICAL +int mbedtls_ssl_tls13_populate_transform(mbedtls_ssl_transform *transform, + int endpoint, + int ciphersuite, + mbedtls_ssl_key_set const *traffic_keys, + mbedtls_ssl_context *ssl); + +/* + * TLS 1.3 key schedule evolutions + * + * Early -> Handshake -> Application + * + * Small wrappers around mbedtls_ssl_tls13_evolve_secret(). + */ + +/** + * \brief Begin TLS 1.3 key schedule by calculating early secret. + * + * The TLS 1.3 key schedule can be viewed as a simple state machine + * with states Initial -> Early -> Handshake -> Application, and + * this function represents the Initial -> Early transition. + * + * \param ssl The SSL context to operate on. + * + * \returns \c 0 on success. + * \returns A negative error code on failure. + */ +MBEDTLS_CHECK_RETURN_CRITICAL +int mbedtls_ssl_tls13_key_schedule_stage_early(mbedtls_ssl_context *ssl); + +/** + * \brief Compute TLS 1.3 resumption master secret. + * + * \param ssl The SSL context to operate on. This must be in + * key schedule stage \c Application, see + * mbedtls_ssl_tls13_key_schedule_stage_application(). + * + * \returns \c 0 on success. + * \returns A negative error code on failure. + */ +MBEDTLS_CHECK_RETURN_CRITICAL +int mbedtls_ssl_tls13_compute_resumption_master_secret(mbedtls_ssl_context *ssl); + +/** + * \brief Calculate the verify_data value for the client or server TLS 1.3 + * Finished message. + * + * \param ssl The SSL context to operate on. This must be in + * key schedule stage \c Handshake, see + * mbedtls_ssl_tls13_key_schedule_stage_application(). + * \param dst The address at which to write the verify_data value. + * \param dst_len The size of \p dst in bytes. + * \param actual_len The address at which to store the amount of data + * actually written to \p dst upon success. + * \param which The message to calculate the `verify_data` for: + * - #MBEDTLS_SSL_IS_CLIENT for the Client's Finished message + * - #MBEDTLS_SSL_IS_SERVER for the Server's Finished message + * + * \note Both client and server call this function twice, once to + * generate their own Finished message, and once to verify the + * peer's Finished message. + + * \returns \c 0 on success. + * \returns A negative error code on failure. + */ +MBEDTLS_CHECK_RETURN_CRITICAL +int mbedtls_ssl_tls13_calculate_verify_data(mbedtls_ssl_context *ssl, + unsigned char *dst, + size_t dst_len, + size_t *actual_len, + int which); + +#if defined(MBEDTLS_SSL_EARLY_DATA) +/** + * \brief Compute TLS 1.3 early transform + * + * \param ssl The SSL context to operate on. + * + * \returns \c 0 on success. + * \returns A negative error code on failure. + * + * \warning The function does not compute the early master secret. Call + * mbedtls_ssl_tls13_key_schedule_stage_early() before to + * call this function to generate the early master secret. + * \note For a client/server endpoint, the function computes only the + * encryption/decryption part of the transform as the decryption/ + * encryption part is not defined by the specification (no early + * traffic from the server to the client). + */ +MBEDTLS_CHECK_RETURN_CRITICAL +int mbedtls_ssl_tls13_compute_early_transform(mbedtls_ssl_context *ssl); +#endif /* MBEDTLS_SSL_EARLY_DATA */ + +/** + * \brief Compute TLS 1.3 handshake transform + * + * \param ssl The SSL context to operate on. The early secret must have been + * computed. + * + * \returns \c 0 on success. + * \returns A negative error code on failure. + */ +MBEDTLS_CHECK_RETURN_CRITICAL +int mbedtls_ssl_tls13_compute_handshake_transform(mbedtls_ssl_context *ssl); + +/** + * \brief Compute TLS 1.3 application transform + * + * \param ssl The SSL context to operate on. The early secret must have been + * computed. + * + * \returns \c 0 on success. + * \returns A negative error code on failure. + */ +MBEDTLS_CHECK_RETURN_CRITICAL +int mbedtls_ssl_tls13_compute_application_transform(mbedtls_ssl_context *ssl); + +#if defined(MBEDTLS_SSL_TLS1_3_KEY_EXCHANGE_MODE_SOME_PSK_ENABLED) +/** + * \brief Export TLS 1.3 PSK from handshake context + * + * \param[in] ssl The SSL context to operate on. + * \param[out] psk PSK output pointer. + * \param[out] psk_len Length of PSK. + * + * \returns \c 0 if there is a configured PSK and it was exported + * successfully. + * \returns A negative error code on failure. + */ +MBEDTLS_CHECK_RETURN_CRITICAL +int mbedtls_ssl_tls13_export_handshake_psk(mbedtls_ssl_context *ssl, + unsigned char **psk, + size_t *psk_len); +#endif + +#endif /* MBEDTLS_SSL_PROTO_TLS1_3 */ + #endif /* MBEDTLS_SSL_TLS1_3_KEYS_H */ diff --git a/vendor/mbedtls/library/ssl_tls13_server.c b/vendor/mbedtls/library/ssl_tls13_server.c new file mode 100644 index 0000000000..2760d76a5d --- /dev/null +++ b/vendor/mbedtls/library/ssl_tls13_server.c @@ -0,0 +1,3599 @@ +/* + * TLS 1.3 server-side functions + * + * Copyright The Mbed TLS Contributors + * SPDX-License-Identifier: Apache-2.0 OR GPL-2.0-or-later + */ + +#include "common.h" + +#if defined(MBEDTLS_SSL_SRV_C) && defined(MBEDTLS_SSL_PROTO_TLS1_3) + +#include "debug_internal.h" +#include "mbedtls/error.h" +#include "mbedtls/platform.h" +#include "mbedtls/constant_time.h" +#include "mbedtls/oid.h" +#include "mbedtls/psa_util.h" + +#include "ssl_misc.h" +#include "ssl_tls13_keys.h" +#include "ssl_debug_helpers.h" + + +static const mbedtls_ssl_ciphersuite_t *ssl_tls13_validate_peer_ciphersuite( + mbedtls_ssl_context *ssl, + unsigned int cipher_suite) +{ + const mbedtls_ssl_ciphersuite_t *ciphersuite_info; + if (!mbedtls_ssl_tls13_cipher_suite_is_offered(ssl, cipher_suite)) { + return NULL; + } + + ciphersuite_info = mbedtls_ssl_ciphersuite_from_id(cipher_suite); + if ((mbedtls_ssl_validate_ciphersuite(ssl, ciphersuite_info, + ssl->tls_version, + ssl->tls_version) != 0)) { + return NULL; + } + return ciphersuite_info; +} + +static void ssl_tls13_select_ciphersuite( + mbedtls_ssl_context *ssl, + const unsigned char *cipher_suites, + const unsigned char *cipher_suites_end, + int psk_ciphersuite_id, + psa_algorithm_t psk_hash_alg, + const mbedtls_ssl_ciphersuite_t **selected_ciphersuite_info) +{ + *selected_ciphersuite_info = NULL; + + /* + * In a compliant ClientHello the byte-length of the list of ciphersuites + * is even and this function relies on this fact. This should have been + * checked in the main ClientHello parsing function. Double check here. + */ + if ((cipher_suites_end - cipher_suites) & 1) { + return; + } + + for (const unsigned char *p = cipher_suites; + p < cipher_suites_end; p += 2) { + /* + * "cipher_suites_end - p is even" is an invariant of the loop. As + * cipher_suites_end - p > 0, we have cipher_suites_end - p >= 2 and it + * is thus safe to read two bytes. + */ + uint16_t id = MBEDTLS_GET_UINT16_BE(p, 0); + + const mbedtls_ssl_ciphersuite_t *info = + ssl_tls13_validate_peer_ciphersuite(ssl, id); + if (info == NULL) { + continue; + } + + /* + * If a valid PSK ciphersuite identifier has been passed in, we want + * an exact match. + */ + if (psk_ciphersuite_id != 0) { + if (id != psk_ciphersuite_id) { + continue; + } + } else if (psk_hash_alg != PSA_ALG_NONE) { + if (mbedtls_md_psa_alg_from_type((mbedtls_md_type_t) info->mac) != + psk_hash_alg) { + continue; + } + } + + *selected_ciphersuite_info = info; + return; + } + + MBEDTLS_SSL_DEBUG_MSG(2, ("No matched ciphersuite, psk_ciphersuite_id=%x, psk_hash_alg=%x", + (unsigned) psk_ciphersuite_id, psk_hash_alg)); +} + +#if defined(MBEDTLS_SSL_TLS1_3_KEY_EXCHANGE_MODE_SOME_PSK_ENABLED) +/* From RFC 8446: + * + * enum { psk_ke(0), psk_dhe_ke(1), (255) } PskKeyExchangeMode; + * struct { + * PskKeyExchangeMode ke_modes<1..255>; + * } PskKeyExchangeModes; + */ +MBEDTLS_CHECK_RETURN_CRITICAL +static int ssl_tls13_parse_key_exchange_modes_ext(mbedtls_ssl_context *ssl, + const unsigned char *buf, + const unsigned char *end) +{ + const unsigned char *p = buf; + size_t ke_modes_len; + int ke_modes = 0; + + /* Read ke_modes length (1 Byte) */ + MBEDTLS_SSL_CHK_BUF_READ_PTR(p, end, 1); + ke_modes_len = *p++; + /* Currently, there are only two PSK modes, so even without looking + * at the content, something's wrong if the list has more than 2 items. */ + if (ke_modes_len > 2) { + MBEDTLS_SSL_PEND_FATAL_ALERT(MBEDTLS_SSL_ALERT_MSG_ILLEGAL_PARAMETER, + MBEDTLS_ERR_SSL_ILLEGAL_PARAMETER); + return MBEDTLS_ERR_SSL_HANDSHAKE_FAILURE; + } + + MBEDTLS_SSL_CHK_BUF_READ_PTR(p, end, ke_modes_len); + + while (ke_modes_len-- != 0) { + switch (*p++) { + case MBEDTLS_SSL_TLS1_3_PSK_MODE_PURE: + ke_modes |= MBEDTLS_SSL_TLS1_3_KEY_EXCHANGE_MODE_PSK; + MBEDTLS_SSL_DEBUG_MSG(3, ("Found PSK KEX MODE")); + break; + case MBEDTLS_SSL_TLS1_3_PSK_MODE_ECDHE: + ke_modes |= MBEDTLS_SSL_TLS1_3_KEY_EXCHANGE_MODE_PSK_EPHEMERAL; + MBEDTLS_SSL_DEBUG_MSG(3, ("Found PSK_EPHEMERAL KEX MODE")); + break; + default: + MBEDTLS_SSL_PEND_FATAL_ALERT(MBEDTLS_SSL_ALERT_MSG_ILLEGAL_PARAMETER, + MBEDTLS_ERR_SSL_ILLEGAL_PARAMETER); + return MBEDTLS_ERR_SSL_ILLEGAL_PARAMETER; + } + } + + ssl->handshake->tls13_kex_modes = ke_modes; + return 0; +} + +/* + * Non-error return values of + * ssl_tls13_offered_psks_check_identity_match_ticket() and + * ssl_tls13_offered_psks_check_identity_match(). They are positive to + * not collide with error codes that are negative. Zero + * (SSL_TLS1_3_PSK_IDENTITY_MATCH) in case of success as it may be propagated + * up by the callers of this function as a generic success condition. + * + * The return value SSL_TLS1_3_PSK_IDENTITY_MATCH_BUT_PSK_NOT_USABLE means + * that the pre-shared-key identity matches that of a ticket or an externally- + * provisioned pre-shared-key. We have thus been able to retrieve the + * attributes of the pre-shared-key but at least one of them does not meet + * some criteria and the pre-shared-key cannot be used. For example, a ticket + * is expired or its version is not TLS 1.3. Note eventually that the return + * value SSL_TLS1_3_PSK_IDENTITY_MATCH_BUT_PSK_NOT_USABLE does not have + * anything to do with binder check. A binder check is done only when a + * suitable pre-shared-key has been selected and only for that selected + * pre-shared-key: if the binder check fails, we fail the handshake and we do + * not try to find another pre-shared-key for which the binder check would + * succeed as recommended by the specification. + */ +#define SSL_TLS1_3_PSK_IDENTITY_DOES_NOT_MATCH 2 +#define SSL_TLS1_3_PSK_IDENTITY_MATCH_BUT_PSK_NOT_USABLE 1 +#define SSL_TLS1_3_PSK_IDENTITY_MATCH 0 + +#if defined(MBEDTLS_SSL_SESSION_TICKETS) +MBEDTLS_CHECK_RETURN_CRITICAL +static int ssl_tls13_key_exchange_is_psk_available(mbedtls_ssl_context *ssl); +MBEDTLS_CHECK_RETURN_CRITICAL +static int ssl_tls13_key_exchange_is_psk_ephemeral_available(mbedtls_ssl_context *ssl); + +MBEDTLS_CHECK_RETURN_CRITICAL +static int ssl_tls13_offered_psks_check_identity_match_ticket( + mbedtls_ssl_context *ssl, + const unsigned char *identity, + size_t identity_len, + uint32_t obfuscated_ticket_age, + mbedtls_ssl_session *session) +{ + int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED; + unsigned char *ticket_buffer; +#if defined(MBEDTLS_HAVE_TIME) + mbedtls_ms_time_t now; + mbedtls_ms_time_t server_age; + uint32_t client_age; + mbedtls_ms_time_t age_diff; +#endif + + ((void) obfuscated_ticket_age); + + MBEDTLS_SSL_DEBUG_MSG(2, ("=> check_identity_match_ticket")); + + /* Ticket parser is not configured, Skip */ + if (ssl->conf->f_ticket_parse == NULL || identity_len == 0) { + return SSL_TLS1_3_PSK_IDENTITY_DOES_NOT_MATCH; + } + + /* We create a copy of the encrypted ticket since the ticket parsing + * function is allowed to use its input buffer as an output buffer + * (in-place decryption). We do, however, need the original buffer for + * computing the PSK binder value. + */ + ticket_buffer = mbedtls_calloc(1, identity_len); + if (ticket_buffer == NULL) { + return MBEDTLS_ERR_SSL_ALLOC_FAILED; + } + memcpy(ticket_buffer, identity, identity_len); + + ret = ssl->conf->f_ticket_parse(ssl->conf->p_ticket, + session, + ticket_buffer, identity_len); + switch (ret) { + case 0: + ret = SSL_TLS1_3_PSK_IDENTITY_MATCH; + break; + + case MBEDTLS_ERR_SSL_SESSION_TICKET_EXPIRED: + MBEDTLS_SSL_DEBUG_MSG(3, ("ticket is expired")); + ret = SSL_TLS1_3_PSK_IDENTITY_MATCH_BUT_PSK_NOT_USABLE; + break; + + case MBEDTLS_ERR_SSL_INVALID_MAC: + MBEDTLS_SSL_DEBUG_MSG(3, ("ticket is not authentic")); + ret = SSL_TLS1_3_PSK_IDENTITY_DOES_NOT_MATCH; + break; + + default: + MBEDTLS_SSL_DEBUG_RET(1, "ticket_parse", ret); + ret = SSL_TLS1_3_PSK_IDENTITY_DOES_NOT_MATCH; + } + + /* We delete the temporary buffer */ + mbedtls_free(ticket_buffer); + + if (ret != SSL_TLS1_3_PSK_IDENTITY_MATCH) { + goto exit; + } + + /* + * The identity matches that of a ticket. Now check that it has suitable + * attributes and bet it will not be the case. + */ + ret = SSL_TLS1_3_PSK_IDENTITY_MATCH_BUT_PSK_NOT_USABLE; + + if (session->tls_version != MBEDTLS_SSL_VERSION_TLS1_3) { + MBEDTLS_SSL_DEBUG_MSG(3, ("Ticket TLS version is not 1.3.")); + goto exit; + } + +#if defined(MBEDTLS_HAVE_TIME) + now = mbedtls_ms_time(); + + if (now < session->ticket_creation_time) { + MBEDTLS_SSL_DEBUG_MSG( + 3, ("Invalid ticket creation time ( now = %" MBEDTLS_PRINTF_MS_TIME + ", creation_time = %" MBEDTLS_PRINTF_MS_TIME " )", + now, session->ticket_creation_time)); + goto exit; + } + + server_age = now - session->ticket_creation_time; + + /* RFC 8446 section 4.6.1 + * + * Servers MUST NOT use any value greater than 604800 seconds (7 days). + * + * RFC 8446 section 4.2.11.1 + * + * Clients MUST NOT attempt to use tickets which have ages greater than + * the "ticket_lifetime" value which was provided with the ticket. + * + */ + if (server_age > MBEDTLS_SSL_TLS1_3_MAX_ALLOWED_TICKET_LIFETIME * 1000) { + MBEDTLS_SSL_DEBUG_MSG( + 3, ("Ticket age exceeds limitation ticket_age = %" MBEDTLS_PRINTF_MS_TIME, + server_age)); + goto exit; + } + + /* RFC 8446 section 4.2.10 + * + * For PSKs provisioned via NewSessionTicket, a server MUST validate that + * the ticket age for the selected PSK identity (computed by subtracting + * ticket_age_add from PskIdentity.obfuscated_ticket_age modulo 2^32) is + * within a small tolerance of the time since the ticket was issued. + * + * NOTE: The typical accuracy of an RTC crystal is ±100 to ±20 parts per + * million (360 to 72 milliseconds per hour). Default tolerance + * window is 6s, thus in the worst case clients and servers must + * sync up their system time every 6000/360/2~=8 hours. + */ + client_age = obfuscated_ticket_age - session->ticket_age_add; + age_diff = server_age - (mbedtls_ms_time_t) client_age; + if (age_diff < -MBEDTLS_SSL_TLS1_3_TICKET_AGE_TOLERANCE || + age_diff > MBEDTLS_SSL_TLS1_3_TICKET_AGE_TOLERANCE) { + MBEDTLS_SSL_DEBUG_MSG( + 3, ("Ticket age outside tolerance window ( diff = %" + MBEDTLS_PRINTF_MS_TIME ")", + age_diff)); + goto exit; + } +#endif /* MBEDTLS_HAVE_TIME */ + + /* + * All good, we have found a suitable ticket. + */ + ret = SSL_TLS1_3_PSK_IDENTITY_MATCH; + +exit: + if (ret != SSL_TLS1_3_PSK_IDENTITY_MATCH) { + mbedtls_ssl_session_free(session); + } + + MBEDTLS_SSL_DEBUG_MSG(2, ("<= check_identity_match_ticket")); + return ret; +} +#endif /* MBEDTLS_SSL_SESSION_TICKETS */ + +MBEDTLS_CHECK_RETURN_CRITICAL +static int ssl_tls13_offered_psks_check_identity_match( + mbedtls_ssl_context *ssl, + const unsigned char *identity, + size_t identity_len, + uint32_t obfuscated_ticket_age, + int *psk_type, + mbedtls_ssl_session *session) +{ + int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED; + + ((void) session); + ((void) obfuscated_ticket_age); + *psk_type = MBEDTLS_SSL_TLS1_3_PSK_EXTERNAL; + + MBEDTLS_SSL_DEBUG_BUF(4, "identity", identity, identity_len); + +#if defined(MBEDTLS_SSL_SESSION_TICKETS) + ret = ssl_tls13_offered_psks_check_identity_match_ticket( + ssl, identity, identity_len, obfuscated_ticket_age, session); + if (ret == SSL_TLS1_3_PSK_IDENTITY_MATCH) { + *psk_type = MBEDTLS_SSL_TLS1_3_PSK_RESUMPTION; + ret = mbedtls_ssl_set_hs_psk(ssl, + session->resumption_key, + session->resumption_key_len); + if (ret != 0) { + MBEDTLS_SSL_DEBUG_RET(1, "mbedtls_ssl_set_hs_psk", ret); + return ret; + } + + MBEDTLS_SSL_DEBUG_BUF(4, "Ticket-resumed PSK:", + session->resumption_key, + session->resumption_key_len); + MBEDTLS_SSL_DEBUG_MSG(4, ("ticket: obfuscated_ticket_age: %u", + (unsigned) obfuscated_ticket_age)); + return SSL_TLS1_3_PSK_IDENTITY_MATCH; + } else if (ret == SSL_TLS1_3_PSK_IDENTITY_MATCH_BUT_PSK_NOT_USABLE) { + return SSL_TLS1_3_PSK_IDENTITY_MATCH_BUT_PSK_NOT_USABLE; + } +#endif /* MBEDTLS_SSL_SESSION_TICKETS */ + + /* Check identity with external configured function */ + if (ssl->conf->f_psk != NULL) { + if (ssl->conf->f_psk( + ssl->conf->p_psk, ssl, identity, identity_len) == 0) { + return SSL_TLS1_3_PSK_IDENTITY_MATCH; + } + return SSL_TLS1_3_PSK_IDENTITY_DOES_NOT_MATCH; + } + + MBEDTLS_SSL_DEBUG_BUF(5, "identity", identity, identity_len); + /* Check identity with pre-configured psk */ + if (ssl->conf->psk_identity != NULL && + identity_len == ssl->conf->psk_identity_len && + mbedtls_ct_memcmp(ssl->conf->psk_identity, + identity, identity_len) == 0) { + ret = mbedtls_ssl_set_hs_psk(ssl, ssl->conf->psk, ssl->conf->psk_len); + if (ret != 0) { + MBEDTLS_SSL_DEBUG_RET(1, "mbedtls_ssl_set_hs_psk", ret); + return ret; + } + return SSL_TLS1_3_PSK_IDENTITY_MATCH; + } + + return SSL_TLS1_3_PSK_IDENTITY_DOES_NOT_MATCH; +} + +/* + * Non-error return values of ssl_tls13_offered_psks_check_binder_match(). + * They are positive to not collide with error codes that are negative. Zero + * (SSL_TLS1_3_BINDER_MATCH) in case of success as it may be propagated up + * by the callers of this function as a generic success condition. + */ +#define SSL_TLS1_3_BINDER_DOES_NOT_MATCH 1 +#define SSL_TLS1_3_BINDER_MATCH 0 +MBEDTLS_CHECK_RETURN_CRITICAL +static int ssl_tls13_offered_psks_check_binder_match( + mbedtls_ssl_context *ssl, + const unsigned char *binder, size_t binder_len, + int psk_type, psa_algorithm_t psk_hash_alg) +{ + int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED; + + unsigned char transcript[PSA_HASH_MAX_SIZE]; + size_t transcript_len; + unsigned char *psk; + size_t psk_len; + unsigned char server_computed_binder[PSA_HASH_MAX_SIZE]; + + if (binder_len != PSA_HASH_LENGTH(psk_hash_alg)) { + return SSL_TLS1_3_BINDER_DOES_NOT_MATCH; + } + + /* Get current state of handshake transcript. */ + ret = mbedtls_ssl_get_handshake_transcript( + ssl, mbedtls_md_type_from_psa_alg(psk_hash_alg), + transcript, sizeof(transcript), &transcript_len); + if (ret != 0) { + return ret; + } + + ret = mbedtls_ssl_tls13_export_handshake_psk(ssl, &psk, &psk_len); + if (ret != 0) { + return ret; + } + + ret = mbedtls_ssl_tls13_create_psk_binder(ssl, psk_hash_alg, + psk, psk_len, psk_type, + transcript, + server_computed_binder); +#if defined(MBEDTLS_USE_PSA_CRYPTO) + mbedtls_free((void *) psk); +#endif + if (ret != 0) { + MBEDTLS_SSL_DEBUG_MSG(1, ("PSK binder calculation failed.")); + return MBEDTLS_ERR_SSL_HANDSHAKE_FAILURE; + } + + MBEDTLS_SSL_DEBUG_BUF(3, "psk binder ( computed ): ", + server_computed_binder, transcript_len); + MBEDTLS_SSL_DEBUG_BUF(3, "psk binder ( received ): ", binder, binder_len); + + if (mbedtls_ct_memcmp(server_computed_binder, + binder, + PSA_HASH_LENGTH(psk_hash_alg)) == 0) { + return SSL_TLS1_3_BINDER_MATCH; + } + + mbedtls_platform_zeroize(server_computed_binder, + sizeof(server_computed_binder)); + return SSL_TLS1_3_BINDER_DOES_NOT_MATCH; +} + +#if defined(MBEDTLS_SSL_SESSION_TICKETS) +MBEDTLS_CHECK_RETURN_CRITICAL +static int ssl_tls13_session_copy_ticket(mbedtls_ssl_session *dst, + const mbedtls_ssl_session *src) +{ + dst->ticket_age_add = src->ticket_age_add; + dst->ticket_flags = src->ticket_flags; + dst->resumption_key_len = src->resumption_key_len; + if (src->resumption_key_len == 0) { + return MBEDTLS_ERR_SSL_INTERNAL_ERROR; + } + memcpy(dst->resumption_key, src->resumption_key, src->resumption_key_len); + +#if defined(MBEDTLS_SSL_EARLY_DATA) + dst->max_early_data_size = src->max_early_data_size; + +#if defined(MBEDTLS_SSL_ALPN) + int ret = mbedtls_ssl_session_set_ticket_alpn(dst, src->ticket_alpn); + if (ret != 0) { + return ret; + } +#endif /* MBEDTLS_SSL_ALPN */ +#endif /* MBEDTLS_SSL_EARLY_DATA*/ + + return 0; +} +#endif /* MBEDTLS_SSL_SESSION_TICKETS */ + +struct psk_attributes { + int type; + int key_exchange_mode; + const mbedtls_ssl_ciphersuite_t *ciphersuite_info; +}; +#define PSK_ATTRIBUTES_INIT { 0, 0, NULL } + +/* Parser for pre_shared_key extension in client hello + * struct { + * opaque identity<1..2^16-1>; + * uint32 obfuscated_ticket_age; + * } PskIdentity; + * + * opaque PskBinderEntry<32..255>; + * + * struct { + * PskIdentity identities<7..2^16-1>; + * PskBinderEntry binders<33..2^16-1>; + * } OfferedPsks; + * + * struct { + * select (Handshake.msg_type) { + * case client_hello: OfferedPsks; + * .... + * }; + * } PreSharedKeyExtension; + */ +MBEDTLS_CHECK_RETURN_CRITICAL +static int ssl_tls13_parse_pre_shared_key_ext( + mbedtls_ssl_context *ssl, + const unsigned char *pre_shared_key_ext, + const unsigned char *pre_shared_key_ext_end, + const unsigned char *ciphersuites, + const unsigned char *ciphersuites_end, + struct psk_attributes *psk) +{ + int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED; + const unsigned char *identities = pre_shared_key_ext; + const unsigned char *p_identity_len; + size_t identities_len; + const unsigned char *identities_end; + const unsigned char *binders; + const unsigned char *p_binder_len; + size_t binders_len; + const unsigned char *binders_end; + int matched_identity = -1; + int identity_id = -1; + + MBEDTLS_SSL_DEBUG_BUF(3, "pre_shared_key extension", + pre_shared_key_ext, + pre_shared_key_ext_end - pre_shared_key_ext); + + /* identities_len 2 bytes + * identities_data >= 7 bytes + */ + MBEDTLS_SSL_CHK_BUF_READ_PTR(identities, pre_shared_key_ext_end, 7 + 2); + identities_len = MBEDTLS_GET_UINT16_BE(identities, 0); + p_identity_len = identities + 2; + MBEDTLS_SSL_CHK_BUF_READ_PTR(p_identity_len, pre_shared_key_ext_end, + identities_len); + identities_end = p_identity_len + identities_len; + + /* binders_len 2 bytes + * binders >= 33 bytes + */ + binders = identities_end; + MBEDTLS_SSL_CHK_BUF_READ_PTR(binders, pre_shared_key_ext_end, 33 + 2); + binders_len = MBEDTLS_GET_UINT16_BE(binders, 0); + p_binder_len = binders + 2; + MBEDTLS_SSL_CHK_BUF_READ_PTR(p_binder_len, pre_shared_key_ext_end, binders_len); + binders_end = p_binder_len + binders_len; + + ret = ssl->handshake->update_checksum(ssl, pre_shared_key_ext, + identities_end - pre_shared_key_ext); + if (0 != ret) { + MBEDTLS_SSL_DEBUG_RET(1, ("update_checksum"), ret); + return ret; + } + + while (p_identity_len < identities_end && p_binder_len < binders_end) { + const unsigned char *identity; + size_t identity_len; + uint32_t obfuscated_ticket_age; + const unsigned char *binder; + size_t binder_len; + int psk_ciphersuite_id; + psa_algorithm_t psk_hash_alg; + int allowed_key_exchange_modes; + +#if defined(MBEDTLS_SSL_SESSION_TICKETS) + mbedtls_ssl_session session; + mbedtls_ssl_session_init(&session); +#endif + + MBEDTLS_SSL_CHK_BUF_READ_PTR(p_identity_len, identities_end, 2 + 1 + 4); + identity_len = MBEDTLS_GET_UINT16_BE(p_identity_len, 0); + identity = p_identity_len + 2; + MBEDTLS_SSL_CHK_BUF_READ_PTR(identity, identities_end, identity_len + 4); + obfuscated_ticket_age = MBEDTLS_GET_UINT32_BE(identity, identity_len); + p_identity_len += identity_len + 6; + + MBEDTLS_SSL_CHK_BUF_READ_PTR(p_binder_len, binders_end, 1 + 32); + binder_len = *p_binder_len; + binder = p_binder_len + 1; + MBEDTLS_SSL_CHK_BUF_READ_PTR(binder, binders_end, binder_len); + p_binder_len += binder_len + 1; + + identity_id++; + if (matched_identity != -1) { + continue; + } + + ret = ssl_tls13_offered_psks_check_identity_match( + ssl, identity, identity_len, obfuscated_ticket_age, + &psk->type, &session); + if (ret != SSL_TLS1_3_PSK_IDENTITY_MATCH) { + continue; + } + + MBEDTLS_SSL_DEBUG_MSG(4, ("found matched identity")); + + switch (psk->type) { + case MBEDTLS_SSL_TLS1_3_PSK_EXTERNAL: + psk_ciphersuite_id = 0; + psk_hash_alg = PSA_ALG_SHA_256; + allowed_key_exchange_modes = + MBEDTLS_SSL_TLS1_3_KEY_EXCHANGE_MODE_PSK_ALL; + break; +#if defined(MBEDTLS_SSL_SESSION_TICKETS) + case MBEDTLS_SSL_TLS1_3_PSK_RESUMPTION: + psk_ciphersuite_id = session.ciphersuite; + psk_hash_alg = PSA_ALG_NONE; + ssl->session_negotiate->ticket_flags = session.ticket_flags; + allowed_key_exchange_modes = + session.ticket_flags & + MBEDTLS_SSL_TLS1_3_KEY_EXCHANGE_MODE_PSK_ALL; + break; +#endif + default: + return MBEDTLS_ERR_SSL_INTERNAL_ERROR; + } + + psk->key_exchange_mode = MBEDTLS_SSL_TLS1_3_KEY_EXCHANGE_MODE_NONE; + + if ((allowed_key_exchange_modes & + MBEDTLS_SSL_TLS1_3_KEY_EXCHANGE_MODE_PSK_EPHEMERAL) && + ssl_tls13_key_exchange_is_psk_ephemeral_available(ssl)) { + psk->key_exchange_mode = MBEDTLS_SSL_TLS1_3_KEY_EXCHANGE_MODE_PSK_EPHEMERAL; + } else if ((allowed_key_exchange_modes & + MBEDTLS_SSL_TLS1_3_KEY_EXCHANGE_MODE_PSK) && + ssl_tls13_key_exchange_is_psk_available(ssl)) { + psk->key_exchange_mode = MBEDTLS_SSL_TLS1_3_KEY_EXCHANGE_MODE_PSK; + } + + if (psk->key_exchange_mode == MBEDTLS_SSL_TLS1_3_KEY_EXCHANGE_MODE_NONE) { + MBEDTLS_SSL_DEBUG_MSG(3, ("No suitable PSK key exchange mode")); + continue; + } + + ssl_tls13_select_ciphersuite(ssl, ciphersuites, ciphersuites_end, + psk_ciphersuite_id, psk_hash_alg, + &psk->ciphersuite_info); + + if (psk->ciphersuite_info == NULL) { +#if defined(MBEDTLS_SSL_SESSION_TICKETS) + mbedtls_ssl_session_free(&session); +#endif + /* + * We consider finding a ciphersuite suitable for the PSK as part + * of the validation of its binder. Thus if we do not find one, we + * abort the handshake with a decrypt_error alert. + */ + MBEDTLS_SSL_PEND_FATAL_ALERT( + MBEDTLS_SSL_ALERT_MSG_DECRYPT_ERROR, + MBEDTLS_ERR_SSL_HANDSHAKE_FAILURE); + return MBEDTLS_ERR_SSL_HANDSHAKE_FAILURE; + } + + ret = ssl_tls13_offered_psks_check_binder_match( + ssl, binder, binder_len, psk->type, + mbedtls_md_psa_alg_from_type((mbedtls_md_type_t) psk->ciphersuite_info->mac)); + if (ret != SSL_TLS1_3_BINDER_MATCH) { + /* For security reasons, the handshake should be aborted when we + * fail to validate a binder value. See RFC 8446 section 4.2.11.2 + * and appendix E.6. */ +#if defined(MBEDTLS_SSL_SESSION_TICKETS) + mbedtls_ssl_session_free(&session); +#endif + MBEDTLS_SSL_DEBUG_MSG(3, ("Invalid binder.")); + MBEDTLS_SSL_DEBUG_RET( + 1, "ssl_tls13_offered_psks_check_binder_match", ret); + MBEDTLS_SSL_PEND_FATAL_ALERT( + MBEDTLS_SSL_ALERT_MSG_DECRYPT_ERROR, + MBEDTLS_ERR_SSL_HANDSHAKE_FAILURE); + return ret; + } + + matched_identity = identity_id; + +#if defined(MBEDTLS_SSL_SESSION_TICKETS) + if (psk->type == MBEDTLS_SSL_TLS1_3_PSK_RESUMPTION) { + ret = ssl_tls13_session_copy_ticket(ssl->session_negotiate, + &session); + mbedtls_ssl_session_free(&session); + if (ret != 0) { + return ret; + } + } +#endif /* MBEDTLS_SSL_SESSION_TICKETS */ + } + + if (p_identity_len != identities_end || p_binder_len != binders_end) { + MBEDTLS_SSL_DEBUG_MSG(3, ("pre_shared_key extension decode error")); + MBEDTLS_SSL_PEND_FATAL_ALERT(MBEDTLS_SSL_ALERT_MSG_DECODE_ERROR, + MBEDTLS_ERR_SSL_DECODE_ERROR); + return MBEDTLS_ERR_SSL_DECODE_ERROR; + } + + /* Update the handshake transcript with the binder list. */ + ret = ssl->handshake->update_checksum( + ssl, identities_end, (size_t) (binders_end - identities_end)); + if (0 != ret) { + MBEDTLS_SSL_DEBUG_RET(1, ("update_checksum"), ret); + return ret; + } + if (matched_identity == -1) { + MBEDTLS_SSL_DEBUG_MSG(3, ("No usable PSK or ticket.")); + return MBEDTLS_ERR_SSL_UNKNOWN_IDENTITY; + } + + ssl->handshake->selected_identity = (uint16_t) matched_identity; + MBEDTLS_SSL_DEBUG_MSG(3, ("Pre shared key found")); + + return 0; +} + +/* + * struct { + * select ( Handshake.msg_type ) { + * .... + * case server_hello: + * uint16 selected_identity; + * } + * } PreSharedKeyExtension; + */ +static int ssl_tls13_write_server_pre_shared_key_ext(mbedtls_ssl_context *ssl, + unsigned char *buf, + unsigned char *end, + size_t *olen) +{ + unsigned char *p = (unsigned char *) buf; + + *olen = 0; + + int not_using_psk = 0; +#if defined(MBEDTLS_USE_PSA_CRYPTO) + not_using_psk = (mbedtls_svc_key_id_is_null(ssl->handshake->psk_opaque)); +#else + not_using_psk = (ssl->handshake->psk == NULL); +#endif + if (not_using_psk) { + /* We shouldn't have called this extension writer unless we've + * chosen to use a PSK. */ + return MBEDTLS_ERR_SSL_INTERNAL_ERROR; + } + + MBEDTLS_SSL_DEBUG_MSG(3, ("server hello, adding pre_shared_key extension")); + MBEDTLS_SSL_CHK_BUF_PTR(p, end, 6); + + MBEDTLS_PUT_UINT16_BE(MBEDTLS_TLS_EXT_PRE_SHARED_KEY, p, 0); + MBEDTLS_PUT_UINT16_BE(2, p, 2); + + MBEDTLS_PUT_UINT16_BE(ssl->handshake->selected_identity, p, 4); + + *olen = 6; + + MBEDTLS_SSL_DEBUG_MSG(4, ("sent selected_identity: %u", + ssl->handshake->selected_identity)); + + mbedtls_ssl_tls13_set_hs_sent_ext_mask(ssl, MBEDTLS_TLS_EXT_PRE_SHARED_KEY); + + return 0; +} + +#endif /* MBEDTLS_SSL_TLS1_3_KEY_EXCHANGE_MODE_SOME_PSK_ENABLED */ + +/* From RFC 8446: + * struct { + * ProtocolVersion versions<2..254>; + * } SupportedVersions; + */ +MBEDTLS_CHECK_RETURN_CRITICAL +static int ssl_tls13_parse_supported_versions_ext(mbedtls_ssl_context *ssl, + const unsigned char *buf, + const unsigned char *end) +{ + const unsigned char *p = buf; + size_t versions_len; + const unsigned char *versions_end; + uint16_t tls_version; + int found_supported_version = 0; + + MBEDTLS_SSL_CHK_BUF_READ_PTR(p, end, 1); + versions_len = p[0]; + p += 1; + + MBEDTLS_SSL_CHK_BUF_READ_PTR(p, end, versions_len); + versions_end = p + versions_len; + while (p < versions_end) { + MBEDTLS_SSL_CHK_BUF_READ_PTR(p, versions_end, 2); + tls_version = mbedtls_ssl_read_version(p, ssl->conf->transport); + p += 2; + + if (MBEDTLS_SSL_VERSION_TLS1_3 == tls_version) { + found_supported_version = 1; + break; + } + + if ((MBEDTLS_SSL_VERSION_TLS1_2 == tls_version) && + mbedtls_ssl_conf_is_tls12_enabled(ssl->conf)) { + found_supported_version = 1; + break; + } + } + + if (!found_supported_version) { + MBEDTLS_SSL_DEBUG_MSG(1, ("No supported version found.")); + + MBEDTLS_SSL_PEND_FATAL_ALERT(MBEDTLS_SSL_ALERT_MSG_PROTOCOL_VERSION, + MBEDTLS_ERR_SSL_BAD_PROTOCOL_VERSION); + return MBEDTLS_ERR_SSL_BAD_PROTOCOL_VERSION; + } + + MBEDTLS_SSL_DEBUG_MSG(1, ("Negotiated version: [%04x]", + (unsigned int) tls_version)); + + return (int) tls_version; +} + +#if defined(PSA_WANT_ALG_ECDH) || defined(PSA_WANT_ALG_FFDH) +/* + * + * From RFC 8446: + * enum { + * ... (0xFFFF) + * } NamedGroup; + * struct { + * NamedGroup named_group_list<2..2^16-1>; + * } NamedGroupList; + */ +MBEDTLS_CHECK_RETURN_CRITICAL +static int ssl_tls13_parse_supported_groups_ext(mbedtls_ssl_context *ssl, + const unsigned char *buf, + const unsigned char *end) +{ + const unsigned char *p = buf; + size_t named_group_list_len; + const unsigned char *named_group_list_end; + + MBEDTLS_SSL_DEBUG_BUF(3, "supported_groups extension", p, end - buf); + MBEDTLS_SSL_CHK_BUF_READ_PTR(p, end, 2); + named_group_list_len = MBEDTLS_GET_UINT16_BE(p, 0); + p += 2; + MBEDTLS_SSL_CHK_BUF_READ_PTR(p, end, named_group_list_len); + named_group_list_end = p + named_group_list_len; + ssl->handshake->hrr_selected_group = 0; + + while (p < named_group_list_end) { + uint16_t named_group; + MBEDTLS_SSL_CHK_BUF_READ_PTR(p, named_group_list_end, 2); + named_group = MBEDTLS_GET_UINT16_BE(p, 0); + p += 2; + + MBEDTLS_SSL_DEBUG_MSG(2, + ("got named group: %s(%04x)", + mbedtls_ssl_named_group_to_str(named_group), + named_group)); + + if (!mbedtls_ssl_named_group_is_offered(ssl, named_group) || + !mbedtls_ssl_named_group_is_supported(named_group) || + ssl->handshake->hrr_selected_group != 0) { + continue; + } + + MBEDTLS_SSL_DEBUG_MSG(2, + ("add named group %s(%04x) into received list.", + mbedtls_ssl_named_group_to_str(named_group), + named_group)); + + ssl->handshake->hrr_selected_group = named_group; + } + + return 0; + +} +#endif /* PSA_WANT_ALG_ECDH || PSA_WANT_ALG_FFDH */ + +#define SSL_TLS1_3_PARSE_KEY_SHARES_EXT_NO_MATCH 1 + +#if defined(MBEDTLS_SSL_TLS1_3_KEY_EXCHANGE_MODE_SOME_EPHEMERAL_ENABLED) +/* + * ssl_tls13_parse_key_shares_ext() verifies whether the information in the + * extension is correct and stores the first acceptable key share and its + * associated group. + * + * Possible return values are: + * - 0: Successful processing of the client provided key share extension. + * - SSL_TLS1_3_PARSE_KEY_SHARES_EXT_NO_MATCH: The key shares provided by + * the client does not match a group supported by the server. A + * HelloRetryRequest will be needed. + * - A negative value for fatal errors. + */ +MBEDTLS_CHECK_RETURN_CRITICAL +static int ssl_tls13_parse_key_shares_ext(mbedtls_ssl_context *ssl, + const unsigned char *buf, + const unsigned char *end) +{ + int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED; + unsigned char const *p = buf; + unsigned char const *client_shares_end; + size_t client_shares_len; + + /* From RFC 8446: + * + * struct { + * KeyShareEntry client_shares<0..2^16-1>; + * } KeyShareClientHello; + * + */ + + MBEDTLS_SSL_CHK_BUF_READ_PTR(p, end, 2); + client_shares_len = MBEDTLS_GET_UINT16_BE(p, 0); + p += 2; + MBEDTLS_SSL_CHK_BUF_READ_PTR(p, end, client_shares_len); + + ssl->handshake->offered_group_id = 0; + client_shares_end = p + client_shares_len; + + /* We try to find a suitable key share entry and copy it to the + * handshake context. Later, we have to find out whether we can do + * something with the provided key share or whether we have to + * dismiss it and send a HelloRetryRequest message. + */ + + while (p < client_shares_end) { + uint16_t group; + size_t key_exchange_len; + const unsigned char *key_exchange; + + /* + * struct { + * NamedGroup group; + * opaque key_exchange<1..2^16-1>; + * } KeyShareEntry; + */ + MBEDTLS_SSL_CHK_BUF_READ_PTR(p, client_shares_end, 4); + group = MBEDTLS_GET_UINT16_BE(p, 0); + key_exchange_len = MBEDTLS_GET_UINT16_BE(p, 2); + p += 4; + key_exchange = p; + MBEDTLS_SSL_CHK_BUF_READ_PTR(p, client_shares_end, key_exchange_len); + p += key_exchange_len; + + /* Continue parsing even if we have already found a match, + * for input validation purposes. + */ + if (!mbedtls_ssl_named_group_is_offered(ssl, group) || + !mbedtls_ssl_named_group_is_supported(group) || + ssl->handshake->offered_group_id != 0) { + continue; + } + + /* + * ECDHE and FFDHE groups are supported + */ + if (mbedtls_ssl_tls13_named_group_is_ecdhe(group) || + mbedtls_ssl_tls13_named_group_is_ffdh(group)) { + MBEDTLS_SSL_DEBUG_MSG(2, ("ECDH/FFDH group: %s (%04x)", + mbedtls_ssl_named_group_to_str(group), + group)); + ret = mbedtls_ssl_tls13_read_public_xxdhe_share( + ssl, key_exchange - 2, key_exchange_len + 2); + if (ret != 0) { + return ret; + } + + } else { + MBEDTLS_SSL_DEBUG_MSG(4, ("Unrecognized NamedGroup %u", + (unsigned) group)); + continue; + } + + ssl->handshake->offered_group_id = group; + } + + + if (ssl->handshake->offered_group_id == 0) { + MBEDTLS_SSL_DEBUG_MSG(1, ("no matching key share")); + return SSL_TLS1_3_PARSE_KEY_SHARES_EXT_NO_MATCH; + } + return 0; +} +#endif /* MBEDTLS_SSL_TLS1_3_KEY_EXCHANGE_MODE_SOME_EPHEMERAL_ENABLED */ + +MBEDTLS_CHECK_RETURN_CRITICAL +static int ssl_tls13_client_hello_has_exts(mbedtls_ssl_context *ssl, + int exts_mask) +{ + int masked = ssl->handshake->received_extensions & exts_mask; + return masked == exts_mask; +} + +#if defined(MBEDTLS_SSL_TLS1_3_KEY_EXCHANGE_MODE_EPHEMERAL_ENABLED) +MBEDTLS_CHECK_RETURN_CRITICAL +static int ssl_tls13_client_hello_has_exts_for_ephemeral_key_exchange( + mbedtls_ssl_context *ssl) +{ + return ssl_tls13_client_hello_has_exts( + ssl, + MBEDTLS_SSL_EXT_MASK(SUPPORTED_GROUPS) | + MBEDTLS_SSL_EXT_MASK(KEY_SHARE) | + MBEDTLS_SSL_EXT_MASK(SIG_ALG)); +} +#endif /* MBEDTLS_SSL_TLS1_3_KEY_EXCHANGE_MODE_EPHEMERAL_ENABLED */ + +#if defined(MBEDTLS_SSL_TLS1_3_KEY_EXCHANGE_MODE_PSK_ENABLED) +MBEDTLS_CHECK_RETURN_CRITICAL +static int ssl_tls13_client_hello_has_exts_for_psk_key_exchange( + mbedtls_ssl_context *ssl) +{ + return ssl_tls13_client_hello_has_exts( + ssl, + MBEDTLS_SSL_EXT_MASK(PRE_SHARED_KEY) | + MBEDTLS_SSL_EXT_MASK(PSK_KEY_EXCHANGE_MODES)); +} +#endif /* MBEDTLS_SSL_TLS1_3_KEY_EXCHANGE_MODE_PSK_ENABLED */ + +#if defined(MBEDTLS_SSL_TLS1_3_KEY_EXCHANGE_MODE_PSK_EPHEMERAL_ENABLED) +MBEDTLS_CHECK_RETURN_CRITICAL +static int ssl_tls13_client_hello_has_exts_for_psk_ephemeral_key_exchange( + mbedtls_ssl_context *ssl) +{ + return ssl_tls13_client_hello_has_exts( + ssl, + MBEDTLS_SSL_EXT_MASK(SUPPORTED_GROUPS) | + MBEDTLS_SSL_EXT_MASK(KEY_SHARE) | + MBEDTLS_SSL_EXT_MASK(PRE_SHARED_KEY) | + MBEDTLS_SSL_EXT_MASK(PSK_KEY_EXCHANGE_MODES)); +} +#endif /* MBEDTLS_SSL_TLS1_3_KEY_EXCHANGE_MODE_PSK_EPHEMERAL_ENABLED */ + +#if defined(MBEDTLS_SSL_TLS1_3_KEY_EXCHANGE_MODE_SOME_PSK_ENABLED) +MBEDTLS_CHECK_RETURN_CRITICAL +static int ssl_tls13_key_exchange_is_psk_available(mbedtls_ssl_context *ssl) +{ +#if defined(MBEDTLS_SSL_TLS1_3_KEY_EXCHANGE_MODE_PSK_ENABLED) + return mbedtls_ssl_conf_tls13_is_psk_enabled(ssl) && + mbedtls_ssl_tls13_is_psk_supported(ssl) && + ssl_tls13_client_hello_has_exts_for_psk_key_exchange(ssl); +#else + ((void) ssl); + return 0; +#endif +} + +MBEDTLS_CHECK_RETURN_CRITICAL +static int ssl_tls13_key_exchange_is_psk_ephemeral_available(mbedtls_ssl_context *ssl) +{ +#if defined(MBEDTLS_SSL_TLS1_3_KEY_EXCHANGE_MODE_PSK_EPHEMERAL_ENABLED) + return mbedtls_ssl_conf_tls13_is_psk_ephemeral_enabled(ssl) && + mbedtls_ssl_tls13_is_psk_ephemeral_supported(ssl) && + ssl_tls13_client_hello_has_exts_for_psk_ephemeral_key_exchange(ssl); +#else + ((void) ssl); + return 0; +#endif +} +#endif /* MBEDTLS_SSL_TLS1_3_KEY_EXCHANGE_MODE_SOME_PSK_ENABLED */ + +MBEDTLS_CHECK_RETURN_CRITICAL +static int ssl_tls13_key_exchange_is_ephemeral_available(mbedtls_ssl_context *ssl) +{ +#if defined(MBEDTLS_SSL_TLS1_3_KEY_EXCHANGE_MODE_EPHEMERAL_ENABLED) + return mbedtls_ssl_conf_tls13_is_ephemeral_enabled(ssl) && + ssl_tls13_client_hello_has_exts_for_ephemeral_key_exchange(ssl); +#else + ((void) ssl); + return 0; +#endif +} + +#if defined(MBEDTLS_X509_CRT_PARSE_C) && \ + defined(MBEDTLS_SSL_TLS1_3_KEY_EXCHANGE_MODE_EPHEMERAL_ENABLED) + +#if defined(MBEDTLS_USE_PSA_CRYPTO) +static psa_algorithm_t ssl_tls13_iana_sig_alg_to_psa_alg(uint16_t sig_alg) +{ + switch (sig_alg) { + case MBEDTLS_TLS1_3_SIG_ECDSA_SECP256R1_SHA256: + return PSA_ALG_ECDSA(PSA_ALG_SHA_256); + case MBEDTLS_TLS1_3_SIG_ECDSA_SECP384R1_SHA384: + return PSA_ALG_ECDSA(PSA_ALG_SHA_384); + case MBEDTLS_TLS1_3_SIG_ECDSA_SECP521R1_SHA512: + return PSA_ALG_ECDSA(PSA_ALG_SHA_512); + case MBEDTLS_TLS1_3_SIG_RSA_PSS_RSAE_SHA256: + return PSA_ALG_RSA_PSS(PSA_ALG_SHA_256); + case MBEDTLS_TLS1_3_SIG_RSA_PSS_RSAE_SHA384: + return PSA_ALG_RSA_PSS(PSA_ALG_SHA_384); + case MBEDTLS_TLS1_3_SIG_RSA_PSS_RSAE_SHA512: + return PSA_ALG_RSA_PSS(PSA_ALG_SHA_512); + case MBEDTLS_TLS1_3_SIG_RSA_PKCS1_SHA256: + return PSA_ALG_RSA_PKCS1V15_SIGN(PSA_ALG_SHA_256); + case MBEDTLS_TLS1_3_SIG_RSA_PKCS1_SHA384: + return PSA_ALG_RSA_PKCS1V15_SIGN(PSA_ALG_SHA_384); + case MBEDTLS_TLS1_3_SIG_RSA_PKCS1_SHA512: + return PSA_ALG_RSA_PKCS1V15_SIGN(PSA_ALG_SHA_512); + default: + return PSA_ALG_NONE; + } +} +#endif /* MBEDTLS_USE_PSA_CRYPTO */ + +/* + * Pick best ( private key, certificate chain ) pair based on the signature + * algorithms supported by the client. + */ +MBEDTLS_CHECK_RETURN_CRITICAL +static int ssl_tls13_pick_key_cert(mbedtls_ssl_context *ssl) +{ + mbedtls_ssl_key_cert *key_cert, *key_cert_list; + const uint16_t *sig_alg = ssl->handshake->received_sig_algs; + +#if defined(MBEDTLS_SSL_SERVER_NAME_INDICATION) + if (ssl->handshake->sni_key_cert != NULL) { + key_cert_list = ssl->handshake->sni_key_cert; + } else +#endif /* MBEDTLS_SSL_SERVER_NAME_INDICATION */ + key_cert_list = ssl->conf->key_cert; + + if (key_cert_list == NULL) { + MBEDTLS_SSL_DEBUG_MSG(3, ("server has no certificate")); + return -1; + } + + for (; *sig_alg != MBEDTLS_TLS1_3_SIG_NONE; sig_alg++) { + if (!mbedtls_ssl_sig_alg_is_offered(ssl, *sig_alg)) { + continue; + } + + if (!mbedtls_ssl_tls13_sig_alg_for_cert_verify_is_supported(*sig_alg)) { + continue; + } + + for (key_cert = key_cert_list; key_cert != NULL; + key_cert = key_cert->next) { +#if defined(MBEDTLS_USE_PSA_CRYPTO) + psa_algorithm_t psa_alg = PSA_ALG_NONE; +#endif /* MBEDTLS_USE_PSA_CRYPTO */ + + MBEDTLS_SSL_DEBUG_CRT(3, "certificate (chain) candidate", + key_cert->cert); + + /* + * This avoids sending the client a cert it'll reject based on + * keyUsage or other extensions. + */ + if (mbedtls_x509_crt_check_key_usage( + key_cert->cert, MBEDTLS_X509_KU_DIGITAL_SIGNATURE) != 0 || + mbedtls_x509_crt_check_extended_key_usage( + key_cert->cert, MBEDTLS_OID_SERVER_AUTH, + MBEDTLS_OID_SIZE(MBEDTLS_OID_SERVER_AUTH)) != 0) { + MBEDTLS_SSL_DEBUG_MSG(3, ("certificate mismatch: " + "(extended) key usage extension")); + continue; + } + + MBEDTLS_SSL_DEBUG_MSG(3, + ("ssl_tls13_pick_key_cert:" + "check signature algorithm %s [%04x]", + mbedtls_ssl_sig_alg_to_str(*sig_alg), + *sig_alg)); +#if defined(MBEDTLS_USE_PSA_CRYPTO) + psa_alg = ssl_tls13_iana_sig_alg_to_psa_alg(*sig_alg); +#endif /* MBEDTLS_USE_PSA_CRYPTO */ + + if (mbedtls_ssl_tls13_check_sig_alg_cert_key_match( + *sig_alg, &key_cert->cert->pk) +#if defined(MBEDTLS_USE_PSA_CRYPTO) + && psa_alg != PSA_ALG_NONE && + mbedtls_pk_can_do_ext(&key_cert->cert->pk, psa_alg, + PSA_KEY_USAGE_SIGN_HASH) == 1 +#endif /* MBEDTLS_USE_PSA_CRYPTO */ + ) { + ssl->handshake->key_cert = key_cert; + MBEDTLS_SSL_DEBUG_MSG(3, + ("ssl_tls13_pick_key_cert:" + "selected signature algorithm" + " %s [%04x]", + mbedtls_ssl_sig_alg_to_str(*sig_alg), + *sig_alg)); + MBEDTLS_SSL_DEBUG_CRT( + 3, "selected certificate (chain)", + ssl->handshake->key_cert->cert); + return 0; + } + } + } + + MBEDTLS_SSL_DEBUG_MSG(2, ("ssl_tls13_pick_key_cert:" + "no suitable certificate found")); + return -1; +} +#endif /* MBEDTLS_X509_CRT_PARSE_C && + MBEDTLS_SSL_TLS1_3_KEY_EXCHANGE_MODE_EPHEMERAL_ENABLED */ + +/* + * + * STATE HANDLING: ClientHello + * + * There are three possible classes of outcomes when parsing the ClientHello: + * + * 1) The ClientHello was well-formed and matched the server's configuration. + * + * In this case, the server progresses to sending its ServerHello. + * + * 2) The ClientHello was well-formed but didn't match the server's + * configuration. + * + * For example, the client might not have offered a key share which + * the server supports, or the server might require a cookie. + * + * In this case, the server sends a HelloRetryRequest. + * + * 3) The ClientHello was ill-formed + * + * In this case, we abort the handshake. + * + */ + +/* + * Structure of this message: + * + * uint16 ProtocolVersion; + * opaque Random[32]; + * uint8 CipherSuite[2]; // Cryptographic suite selector + * + * struct { + * ProtocolVersion legacy_version = 0x0303; // TLS v1.2 + * Random random; + * opaque legacy_session_id<0..32>; + * CipherSuite cipher_suites<2..2^16-2>; + * opaque legacy_compression_methods<1..2^8-1>; + * Extension extensions<8..2^16-1>; + * } ClientHello; + */ + +#define SSL_CLIENT_HELLO_OK 0 +#define SSL_CLIENT_HELLO_HRR_REQUIRED 1 +#define SSL_CLIENT_HELLO_TLS1_2 2 + +MBEDTLS_CHECK_RETURN_CRITICAL +static int ssl_tls13_parse_client_hello(mbedtls_ssl_context *ssl, + const unsigned char *buf, + const unsigned char *end) +{ + int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED; + const unsigned char *p = buf; + const unsigned char *random; + size_t legacy_session_id_len; + const unsigned char *legacy_session_id; + size_t cipher_suites_len; + const unsigned char *cipher_suites; + const unsigned char *cipher_suites_end; + size_t extensions_len; + const unsigned char *extensions_end; + const unsigned char *supported_versions_data; + const unsigned char *supported_versions_data_end; + mbedtls_ssl_handshake_params *handshake = ssl->handshake; + int hrr_required = 0; + int no_usable_share_for_key_agreement = 0; + +#if defined(MBEDTLS_SSL_TLS1_3_KEY_EXCHANGE_MODE_SOME_PSK_ENABLED) + int got_psk = 0; + struct psk_attributes psk = PSK_ATTRIBUTES_INIT; + const unsigned char *pre_shared_key_ext = NULL; + const unsigned char *pre_shared_key_ext_end = NULL; +#endif + + /* + * ClientHello layout: + * 0 . 1 protocol version + * 2 . 33 random bytes + * 34 . 34 session id length ( 1 byte ) + * 35 . 34+x session id + * .. . .. ciphersuite list length ( 2 bytes ) + * .. . .. ciphersuite list + * .. . .. compression alg. list length ( 1 byte ) + * .. . .. compression alg. list + * .. . .. extensions length ( 2 bytes, optional ) + * .. . .. extensions ( optional ) + */ + + /* + * Minimal length ( with everything empty and extensions omitted ) is + * 2 + 32 + 1 + 2 + 1 = 38 bytes. Check that first, so that we can + * read at least up to session id length without worrying. + */ + MBEDTLS_SSL_CHK_BUF_READ_PTR(p, end, 38); + + /* ... + * ProtocolVersion legacy_version = 0x0303; // TLS 1.2 + * ... + * with ProtocolVersion defined as: + * uint16 ProtocolVersion; + */ + if (mbedtls_ssl_read_version(p, ssl->conf->transport) != + MBEDTLS_SSL_VERSION_TLS1_2) { + MBEDTLS_SSL_DEBUG_MSG(1, ("Unsupported version of TLS.")); + MBEDTLS_SSL_PEND_FATAL_ALERT(MBEDTLS_SSL_ALERT_MSG_PROTOCOL_VERSION, + MBEDTLS_ERR_SSL_BAD_PROTOCOL_VERSION); + return MBEDTLS_ERR_SSL_BAD_PROTOCOL_VERSION; + } + p += 2; + + /* ... + * Random random; + * ... + * with Random defined as: + * opaque Random[32]; + */ + random = p; + p += MBEDTLS_CLIENT_HELLO_RANDOM_LEN; + + /* ... + * opaque legacy_session_id<0..32>; + * ... + */ + legacy_session_id_len = *(p++); + legacy_session_id = p; + + /* + * Check we have enough data for the legacy session identifier + * and the ciphersuite list length. + */ + MBEDTLS_SSL_CHK_BUF_READ_PTR(p, end, legacy_session_id_len + 2); + p += legacy_session_id_len; + + /* ... + * CipherSuite cipher_suites<2..2^16-2>; + * ... + * with CipherSuite defined as: + * uint8 CipherSuite[2]; + */ + cipher_suites_len = MBEDTLS_GET_UINT16_BE(p, 0); + p += 2; + cipher_suites = p; + + /* + * The length of the ciphersuite list has to be even. + */ + if (cipher_suites_len & 1) { + MBEDTLS_SSL_PEND_FATAL_ALERT(MBEDTLS_SSL_ALERT_MSG_DECODE_ERROR, + MBEDTLS_ERR_SSL_DECODE_ERROR); + return MBEDTLS_ERR_SSL_DECODE_ERROR; + } + + /* Check we have enough data for the ciphersuite list, the legacy + * compression methods and the length of the extensions. + * + * cipher_suites cipher_suites_len bytes + * legacy_compression_methods 2 bytes + * extensions_len 2 bytes + */ + MBEDTLS_SSL_CHK_BUF_READ_PTR(p, end, cipher_suites_len + 2 + 2); + p += cipher_suites_len; + cipher_suites_end = p; + + /* + * Search for the supported versions extension and parse it to determine + * if the client supports TLS 1.3. + */ + ret = mbedtls_ssl_tls13_is_supported_versions_ext_present_in_exts( + ssl, p + 2, end, + &supported_versions_data, &supported_versions_data_end); + if (ret < 0) { + MBEDTLS_SSL_DEBUG_RET(1, + ("mbedtls_ssl_tls13_is_supported_versions_ext_present_in_exts"), ret); + return ret; + } + + if (ret == 0) { + return SSL_CLIENT_HELLO_TLS1_2; + } + + if (ret == 1) { + ret = ssl_tls13_parse_supported_versions_ext(ssl, + supported_versions_data, + supported_versions_data_end); + if (ret < 0) { + MBEDTLS_SSL_DEBUG_RET(1, + ("ssl_tls13_parse_supported_versions_ext"), ret); + return ret; + } + + /* + * The supported versions extension was parsed successfully as the + * value returned by ssl_tls13_parse_supported_versions_ext() is + * positive. The return value is then equal to + * MBEDTLS_SSL_VERSION_TLS1_2 or MBEDTLS_SSL_VERSION_TLS1_3, defining + * the TLS version to negotiate. + */ + if (MBEDTLS_SSL_VERSION_TLS1_2 == ret) { + return SSL_CLIENT_HELLO_TLS1_2; + } + } + + /* + * We negotiate TLS 1.3. + */ + ssl->tls_version = MBEDTLS_SSL_VERSION_TLS1_3; + ssl->session_negotiate->tls_version = MBEDTLS_SSL_VERSION_TLS1_3; + ssl->session_negotiate->endpoint = ssl->conf->endpoint; + + /* + * We are negotiating the version 1.3 of the protocol. Do what we have + * postponed: copy of the client random bytes, copy of the legacy session + * identifier and selection of the TLS 1.3 cipher suite. + */ + MBEDTLS_SSL_DEBUG_BUF(3, "client hello, random bytes", + random, MBEDTLS_CLIENT_HELLO_RANDOM_LEN); + memcpy(&handshake->randbytes[0], random, MBEDTLS_CLIENT_HELLO_RANDOM_LEN); + + if (legacy_session_id_len > sizeof(ssl->session_negotiate->id)) { + MBEDTLS_SSL_DEBUG_MSG(1, ("bad client hello message")); + return MBEDTLS_ERR_SSL_DECODE_ERROR; + } + ssl->session_negotiate->id_len = legacy_session_id_len; + MBEDTLS_SSL_DEBUG_BUF(3, "client hello, session id", + legacy_session_id, legacy_session_id_len); + memcpy(&ssl->session_negotiate->id[0], + legacy_session_id, legacy_session_id_len); + + /* + * Search for a matching ciphersuite + */ + MBEDTLS_SSL_DEBUG_BUF(3, "client hello, list of cipher suites", + cipher_suites, cipher_suites_len); + + ssl_tls13_select_ciphersuite(ssl, cipher_suites, cipher_suites_end, + 0, PSA_ALG_NONE, &handshake->ciphersuite_info); + + if (handshake->ciphersuite_info == NULL) { + MBEDTLS_SSL_PEND_FATAL_ALERT(MBEDTLS_SSL_ALERT_MSG_HANDSHAKE_FAILURE, + MBEDTLS_ERR_SSL_HANDSHAKE_FAILURE); + return MBEDTLS_ERR_SSL_HANDSHAKE_FAILURE; + } + ssl->session_negotiate->ciphersuite = handshake->ciphersuite_info->id; + + MBEDTLS_SSL_DEBUG_MSG(2, ("selected ciphersuite: %04x - %s", + ((unsigned) handshake->ciphersuite_info->id), + handshake->ciphersuite_info->name)); + + /* ... + * opaque legacy_compression_methods<1..2^8-1>; + * ... + */ + if (p[0] != 1 || p[1] != MBEDTLS_SSL_COMPRESS_NULL) { + MBEDTLS_SSL_DEBUG_MSG(1, ("bad legacy compression method")); + MBEDTLS_SSL_PEND_FATAL_ALERT(MBEDTLS_SSL_ALERT_MSG_ILLEGAL_PARAMETER, + MBEDTLS_ERR_SSL_ILLEGAL_PARAMETER); + return MBEDTLS_ERR_SSL_ILLEGAL_PARAMETER; + } + p += 2; + + /* ... + * Extension extensions<8..2^16-1>; + * ... + * with Extension defined as: + * struct { + * ExtensionType extension_type; + * opaque extension_data<0..2^16-1>; + * } Extension; + */ + extensions_len = MBEDTLS_GET_UINT16_BE(p, 0); + p += 2; + MBEDTLS_SSL_CHK_BUF_READ_PTR(p, end, extensions_len); + extensions_end = p + extensions_len; + + MBEDTLS_SSL_DEBUG_BUF(3, "client hello extensions", p, extensions_len); + handshake->received_extensions = MBEDTLS_SSL_EXT_MASK_NONE; + + while (p < extensions_end) { + unsigned int extension_type; + size_t extension_data_len; + const unsigned char *extension_data_end; + uint32_t allowed_exts = MBEDTLS_SSL_TLS1_3_ALLOWED_EXTS_OF_CH; + + if (ssl->handshake->hello_retry_request_flag) { + /* Do not accept early data extension in 2nd ClientHello */ + allowed_exts &= ~MBEDTLS_SSL_EXT_MASK(EARLY_DATA); + } + + /* RFC 8446, section 4.2.11 + * + * The "pre_shared_key" extension MUST be the last extension in the + * ClientHello (this facilitates implementation as described below). + * Servers MUST check that it is the last extension and otherwise fail + * the handshake with an "illegal_parameter" alert. + */ + if (handshake->received_extensions & MBEDTLS_SSL_EXT_MASK(PRE_SHARED_KEY)) { + MBEDTLS_SSL_DEBUG_MSG( + 3, ("pre_shared_key is not last extension.")); + MBEDTLS_SSL_PEND_FATAL_ALERT( + MBEDTLS_SSL_ALERT_MSG_ILLEGAL_PARAMETER, + MBEDTLS_ERR_SSL_ILLEGAL_PARAMETER); + return MBEDTLS_ERR_SSL_ILLEGAL_PARAMETER; + } + + MBEDTLS_SSL_CHK_BUF_READ_PTR(p, extensions_end, 4); + extension_type = MBEDTLS_GET_UINT16_BE(p, 0); + extension_data_len = MBEDTLS_GET_UINT16_BE(p, 2); + p += 4; + + MBEDTLS_SSL_CHK_BUF_READ_PTR(p, extensions_end, extension_data_len); + extension_data_end = p + extension_data_len; + + ret = mbedtls_ssl_tls13_check_received_extension( + ssl, MBEDTLS_SSL_HS_CLIENT_HELLO, extension_type, + allowed_exts); + if (ret != 0) { + return ret; + } + + switch (extension_type) { +#if defined(MBEDTLS_SSL_SERVER_NAME_INDICATION) + case MBEDTLS_TLS_EXT_SERVERNAME: + MBEDTLS_SSL_DEBUG_MSG(3, ("found ServerName extension")); + ret = mbedtls_ssl_parse_server_name_ext(ssl, p, + extension_data_end); + if (ret != 0) { + MBEDTLS_SSL_DEBUG_RET( + 1, "mbedtls_ssl_parse_servername_ext", ret); + return ret; + } + break; +#endif /* MBEDTLS_SSL_SERVER_NAME_INDICATION */ + +#if defined(PSA_WANT_ALG_ECDH) || defined(PSA_WANT_ALG_FFDH) + case MBEDTLS_TLS_EXT_SUPPORTED_GROUPS: + MBEDTLS_SSL_DEBUG_MSG(3, ("found supported group extension")); + + /* Supported Groups Extension + * + * When sent by the client, the "supported_groups" extension + * indicates the named groups which the client supports, + * ordered from most preferred to least preferred. + */ + ret = ssl_tls13_parse_supported_groups_ext( + ssl, p, extension_data_end); + if (ret != 0) { + MBEDTLS_SSL_DEBUG_RET( + 1, "ssl_tls13_parse_supported_groups_ext", ret); + return ret; + } + + break; +#endif /* PSA_WANT_ALG_ECDH || PSA_WANT_ALG_FFDH*/ + +#if defined(MBEDTLS_SSL_TLS1_3_KEY_EXCHANGE_MODE_SOME_EPHEMERAL_ENABLED) + case MBEDTLS_TLS_EXT_KEY_SHARE: + MBEDTLS_SSL_DEBUG_MSG(3, ("found key share extension")); + + /* + * Key Share Extension + * + * When sent by the client, the "key_share" extension + * contains the endpoint's cryptographic parameters for + * ECDHE/DHE key establishment methods. + */ + ret = ssl_tls13_parse_key_shares_ext( + ssl, p, extension_data_end); + if (ret == SSL_TLS1_3_PARSE_KEY_SHARES_EXT_NO_MATCH) { + MBEDTLS_SSL_DEBUG_MSG(2, ("No usable share for key agreement.")); + no_usable_share_for_key_agreement = 1; + } + + if (ret < 0) { + MBEDTLS_SSL_DEBUG_RET( + 1, "ssl_tls13_parse_key_shares_ext", ret); + return ret; + } + + break; +#endif /* MBEDTLS_SSL_TLS1_3_KEY_EXCHANGE_MODE_SOME_EPHEMERAL_ENABLED */ + + case MBEDTLS_TLS_EXT_SUPPORTED_VERSIONS: + /* Already parsed */ + break; + +#if defined(MBEDTLS_SSL_TLS1_3_KEY_EXCHANGE_MODE_SOME_PSK_ENABLED) + case MBEDTLS_TLS_EXT_PSK_KEY_EXCHANGE_MODES: + MBEDTLS_SSL_DEBUG_MSG( + 3, ("found psk key exchange modes extension")); + + ret = ssl_tls13_parse_key_exchange_modes_ext( + ssl, p, extension_data_end); + if (ret != 0) { + MBEDTLS_SSL_DEBUG_RET( + 1, "ssl_tls13_parse_key_exchange_modes_ext", ret); + return ret; + } + + break; +#endif + + case MBEDTLS_TLS_EXT_PRE_SHARED_KEY: + MBEDTLS_SSL_DEBUG_MSG(3, ("found pre_shared_key extension")); + if ((handshake->received_extensions & + MBEDTLS_SSL_EXT_MASK(PSK_KEY_EXCHANGE_MODES)) == 0) { + MBEDTLS_SSL_PEND_FATAL_ALERT( + MBEDTLS_SSL_ALERT_MSG_ILLEGAL_PARAMETER, + MBEDTLS_ERR_SSL_ILLEGAL_PARAMETER); + return MBEDTLS_ERR_SSL_ILLEGAL_PARAMETER; + } +#if defined(MBEDTLS_SSL_TLS1_3_KEY_EXCHANGE_MODE_SOME_PSK_ENABLED) + /* Delay processing of the PSK identity once we have + * found out which algorithms to use. We keep a pointer + * to the buffer and the size for later processing. + */ + pre_shared_key_ext = p; + pre_shared_key_ext_end = extension_data_end; +#endif /* MBEDTLS_SSL_TLS1_3_KEY_EXCHANGE_MODE_SOME_PSK_ENABLED */ + break; + +#if defined(MBEDTLS_SSL_ALPN) + case MBEDTLS_TLS_EXT_ALPN: + MBEDTLS_SSL_DEBUG_MSG(3, ("found alpn extension")); + + ret = mbedtls_ssl_parse_alpn_ext(ssl, p, extension_data_end); + if (ret != 0) { + MBEDTLS_SSL_DEBUG_RET( + 1, ("mbedtls_ssl_parse_alpn_ext"), ret); + return ret; + } + break; +#endif /* MBEDTLS_SSL_ALPN */ + +#if defined(MBEDTLS_SSL_TLS1_3_KEY_EXCHANGE_MODE_EPHEMERAL_ENABLED) + case MBEDTLS_TLS_EXT_SIG_ALG: + MBEDTLS_SSL_DEBUG_MSG(3, ("found signature_algorithms extension")); + + ret = mbedtls_ssl_parse_sig_alg_ext( + ssl, p, extension_data_end); + if (ret != 0) { + MBEDTLS_SSL_DEBUG_RET( + 1, "mbedtls_ssl_parse_sig_alg_ext", ret); + return ret; + } + break; +#endif /* MBEDTLS_SSL_TLS1_3_KEY_EXCHANGE_MODE_EPHEMERAL_ENABLED */ + +#if defined(MBEDTLS_SSL_RECORD_SIZE_LIMIT) + case MBEDTLS_TLS_EXT_RECORD_SIZE_LIMIT: + MBEDTLS_SSL_DEBUG_MSG(3, ("found record_size_limit extension")); + + ret = mbedtls_ssl_tls13_parse_record_size_limit_ext( + ssl, p, extension_data_end); + if (ret != 0) { + MBEDTLS_SSL_DEBUG_RET( + 1, ("mbedtls_ssl_tls13_parse_record_size_limit_ext"), ret); + return ret; + } + break; +#endif /* MBEDTLS_SSL_RECORD_SIZE_LIMIT */ + + default: + MBEDTLS_SSL_PRINT_EXT( + 3, MBEDTLS_SSL_HS_CLIENT_HELLO, + extension_type, "( ignored )"); + break; + } + + p += extension_data_len; + } + + MBEDTLS_SSL_PRINT_EXTS(3, MBEDTLS_SSL_HS_CLIENT_HELLO, + handshake->received_extensions); + + ret = mbedtls_ssl_add_hs_hdr_to_checksum(ssl, + MBEDTLS_SSL_HS_CLIENT_HELLO, + p - buf); + if (0 != ret) { + MBEDTLS_SSL_DEBUG_RET(1, ("mbedtls_ssl_add_hs_hdr_to_checksum"), ret); + return ret; + } + +#if defined(MBEDTLS_SSL_TLS1_3_KEY_EXCHANGE_MODE_SOME_PSK_ENABLED) + /* Update checksum with either + * - The entire content of the CH message, if no PSK extension is present + * - The content up to but excluding the PSK extension, if present. + * Always parse the pre-shared-key extension when present in the + * ClientHello even if some pre-requisites for PSK key exchange modes are + * not met. That way we always validate the syntax of the extension. + */ + if (handshake->received_extensions & MBEDTLS_SSL_EXT_MASK(PRE_SHARED_KEY)) { + ret = handshake->update_checksum(ssl, buf, + pre_shared_key_ext - buf); + if (0 != ret) { + MBEDTLS_SSL_DEBUG_RET(1, ("update_checksum"), ret); + return ret; + } + ret = ssl_tls13_parse_pre_shared_key_ext(ssl, + pre_shared_key_ext, + pre_shared_key_ext_end, + cipher_suites, + cipher_suites_end, + &psk); + if (ret == 0) { + got_psk = 1; + } else if (ret != MBEDTLS_ERR_SSL_UNKNOWN_IDENTITY) { + MBEDTLS_SSL_DEBUG_RET( + 1, "ssl_tls13_parse_pre_shared_key_ext", ret); + return ret; + } + } else +#endif /* MBEDTLS_SSL_TLS1_3_KEY_EXCHANGE_MODE_SOME_PSK_ENABLED */ + { + ret = handshake->update_checksum(ssl, buf, p - buf); + if (0 != ret) { + MBEDTLS_SSL_DEBUG_RET(1, ("update_checksum"), ret); + return ret; + } + } + + /* + * Determine the key exchange algorithm to use. + * There are three types of key exchanges supported in TLS 1.3: + * - (EC)DH with ECDSA, + * - (EC)DH with PSK, + * - plain PSK. + * + * The PSK-based key exchanges may additionally be used with 0-RTT. + * + * Our built-in order of preference is + * 1 ) (EC)DHE-PSK Mode ( psk_ephemeral ) + * 2 ) Certificate Mode ( ephemeral ) + * 3 ) Plain PSK Mode ( psk ) + */ +#if defined(MBEDTLS_SSL_TLS1_3_KEY_EXCHANGE_MODE_SOME_PSK_ENABLED) + if (got_psk && (psk.key_exchange_mode == + MBEDTLS_SSL_TLS1_3_KEY_EXCHANGE_MODE_PSK_EPHEMERAL)) { + handshake->key_exchange_mode = + MBEDTLS_SSL_TLS1_3_KEY_EXCHANGE_MODE_PSK_EPHEMERAL; + MBEDTLS_SSL_DEBUG_MSG(2, ("key exchange mode: psk_ephemeral")); + + } else +#endif + if (ssl_tls13_key_exchange_is_ephemeral_available(ssl)) { + handshake->key_exchange_mode = + MBEDTLS_SSL_TLS1_3_KEY_EXCHANGE_MODE_EPHEMERAL; + MBEDTLS_SSL_DEBUG_MSG(2, ("key exchange mode: ephemeral")); + + } +#if defined(MBEDTLS_SSL_TLS1_3_KEY_EXCHANGE_MODE_SOME_PSK_ENABLED) + else if (got_psk && (psk.key_exchange_mode == + MBEDTLS_SSL_TLS1_3_KEY_EXCHANGE_MODE_PSK)) { + handshake->key_exchange_mode = MBEDTLS_SSL_TLS1_3_KEY_EXCHANGE_MODE_PSK; + MBEDTLS_SSL_DEBUG_MSG(2, ("key exchange mode: psk")); + } +#endif + else { + MBEDTLS_SSL_DEBUG_MSG( + 1, + ("ClientHello message misses mandatory extensions.")); + MBEDTLS_SSL_PEND_FATAL_ALERT(MBEDTLS_SSL_ALERT_MSG_MISSING_EXTENSION, + MBEDTLS_ERR_SSL_ILLEGAL_PARAMETER); + return MBEDTLS_ERR_SSL_ILLEGAL_PARAMETER; + } + +#if defined(MBEDTLS_SSL_TLS1_3_KEY_EXCHANGE_MODE_SOME_PSK_ENABLED) + if (handshake->key_exchange_mode & + MBEDTLS_SSL_TLS1_3_KEY_EXCHANGE_MODE_PSK_ALL) { + handshake->ciphersuite_info = psk.ciphersuite_info; + ssl->session_negotiate->ciphersuite = psk.ciphersuite_info->id; + + MBEDTLS_SSL_DEBUG_MSG(2, ("Select PSK ciphersuite: %04x - %s", + ((unsigned) psk.ciphersuite_info->id), + psk.ciphersuite_info->name)); + + if (psk.type == MBEDTLS_SSL_TLS1_3_PSK_RESUMPTION) { + handshake->resume = 1; + } + } +#endif + + if (handshake->key_exchange_mode != + MBEDTLS_SSL_TLS1_3_KEY_EXCHANGE_MODE_PSK) { + hrr_required = (no_usable_share_for_key_agreement != 0); + } + + mbedtls_ssl_optimize_checksum(ssl, handshake->ciphersuite_info); + + return hrr_required ? SSL_CLIENT_HELLO_HRR_REQUIRED : SSL_CLIENT_HELLO_OK; +} + +#if defined(MBEDTLS_SSL_EARLY_DATA) +static int ssl_tls13_check_early_data_requirements(mbedtls_ssl_context *ssl) +{ + mbedtls_ssl_handshake_params *handshake = ssl->handshake; + + if (ssl->conf->early_data_enabled == MBEDTLS_SSL_EARLY_DATA_DISABLED) { + MBEDTLS_SSL_DEBUG_MSG( + 1, + ("EarlyData: rejected, feature disabled in server configuration.")); + return -1; + } + + if (!handshake->resume) { + /* We currently support early data only in the case of PSKs established + via a NewSessionTicket message thus in the case of a session + resumption. */ + MBEDTLS_SSL_DEBUG_MSG( + 1, ("EarlyData: rejected, not a session resumption.")); + return -1; + } + + /* RFC 8446 4.2.10 + * + * In order to accept early data, the server MUST have accepted a PSK cipher + * suite and selected the first key offered in the client's "pre_shared_key" + * extension. In addition, it MUST verify that the following values are the + * same as those associated with the selected PSK: + * - The TLS version number + * - The selected cipher suite + * - The selected ALPN [RFC7301] protocol, if any + * + * NOTE: + * - The TLS version number is checked in + * ssl_tls13_offered_psks_check_identity_match_ticket(). + */ + + if (handshake->selected_identity != 0) { + MBEDTLS_SSL_DEBUG_MSG( + 1, ("EarlyData: rejected, the selected key in " + "`pre_shared_key` is not the first one.")); + return -1; + } + + if (handshake->ciphersuite_info->id != + ssl->session_negotiate->ciphersuite) { + MBEDTLS_SSL_DEBUG_MSG( + 1, ("EarlyData: rejected, the selected ciphersuite is not the one " + "of the selected pre-shared key.")); + return -1; + + } + + if (!mbedtls_ssl_tls13_session_ticket_allow_early_data(ssl->session_negotiate)) { + MBEDTLS_SSL_DEBUG_MSG( + 1, + ("EarlyData: rejected, early_data not allowed in ticket " + "permission bits.")); + return -1; + } + +#if defined(MBEDTLS_SSL_ALPN) + const char *alpn = mbedtls_ssl_get_alpn_protocol(ssl); + size_t alpn_len; + + if (alpn == NULL && ssl->session_negotiate->ticket_alpn == NULL) { + return 0; + } + + if (alpn != NULL) { + alpn_len = strlen(alpn); + } + + if (alpn == NULL || + ssl->session_negotiate->ticket_alpn == NULL || + alpn_len != strlen(ssl->session_negotiate->ticket_alpn) || + (memcmp(alpn, ssl->session_negotiate->ticket_alpn, alpn_len) != 0)) { + MBEDTLS_SSL_DEBUG_MSG(1, ("EarlyData: rejected, the selected ALPN is different " + "from the one associated with the pre-shared key.")); + return -1; + } +#endif + + return 0; +} +#endif /* MBEDTLS_SSL_EARLY_DATA */ + +/* Update the handshake state machine */ + +MBEDTLS_CHECK_RETURN_CRITICAL +static int ssl_tls13_postprocess_client_hello(mbedtls_ssl_context *ssl, + int hrr_required) +{ + int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED; + + /* + * Server certificate selection + */ + if (ssl->conf->f_cert_cb && (ret = ssl->conf->f_cert_cb(ssl)) != 0) { + MBEDTLS_SSL_DEBUG_RET(1, "f_cert_cb", ret); + return ret; + } +#if defined(MBEDTLS_SSL_SERVER_NAME_INDICATION) + ssl->handshake->sni_name = NULL; + ssl->handshake->sni_name_len = 0; +#endif /* MBEDTLS_SSL_SERVER_NAME_INDICATION */ + + ret = mbedtls_ssl_tls13_key_schedule_stage_early(ssl); + if (ret != 0) { + MBEDTLS_SSL_DEBUG_RET(1, + "mbedtls_ssl_tls1_3_key_schedule_stage_early", ret); + return ret; + } + +#if defined(MBEDTLS_SSL_EARLY_DATA) + if (ssl->handshake->received_extensions & MBEDTLS_SSL_EXT_MASK(EARLY_DATA)) { + ssl->handshake->early_data_accepted = + (!hrr_required) && (ssl_tls13_check_early_data_requirements(ssl) == 0); + + if (ssl->handshake->early_data_accepted) { + ret = mbedtls_ssl_tls13_compute_early_transform(ssl); + if (ret != 0) { + MBEDTLS_SSL_DEBUG_RET( + 1, "mbedtls_ssl_tls13_compute_early_transform", ret); + return ret; + } + } else { + ssl->discard_early_data_record = + hrr_required ? + MBEDTLS_SSL_EARLY_DATA_DISCARD : + MBEDTLS_SSL_EARLY_DATA_TRY_TO_DEPROTECT_AND_DISCARD; + } + } +#else + ((void) hrr_required); +#endif /* MBEDTLS_SSL_EARLY_DATA */ + + return 0; +} + +/* + * Main entry point from the state machine; orchestrates the otherfunctions. + */ + +MBEDTLS_CHECK_RETURN_CRITICAL +static int ssl_tls13_process_client_hello(mbedtls_ssl_context *ssl) +{ + + int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED; + unsigned char *buf = NULL; + size_t buflen = 0; + int parse_client_hello_ret; + + MBEDTLS_SSL_DEBUG_MSG(2, ("=> parse client hello")); + + MBEDTLS_SSL_PROC_CHK(mbedtls_ssl_tls13_fetch_handshake_msg( + ssl, MBEDTLS_SSL_HS_CLIENT_HELLO, + &buf, &buflen)); + + MBEDTLS_SSL_PROC_CHK_NEG(ssl_tls13_parse_client_hello(ssl, buf, + buf + buflen)); + parse_client_hello_ret = ret; /* Store positive return value of + * parse_client_hello, + * as negative error codes are handled + * by MBEDTLS_SSL_PROC_CHK_NEG. */ + + /* + * Version 1.2 of the protocol has to be used for the handshake. + * If TLS 1.2 is not supported, abort the handshake. Otherwise, set the + * ssl->keep_current_message flag for the ClientHello to be kept and parsed + * as a TLS 1.2 ClientHello. We also change ssl->tls_version to + * MBEDTLS_SSL_VERSION_TLS1_2 thus from now on mbedtls_ssl_handshake_step() + * will dispatch to the TLS 1.2 state machine. + */ + if (SSL_CLIENT_HELLO_TLS1_2 == parse_client_hello_ret) { + /* Check if server supports TLS 1.2 */ + if (!mbedtls_ssl_conf_is_tls12_enabled(ssl->conf)) { + MBEDTLS_SSL_DEBUG_MSG( + 1, ("TLS 1.2 not supported.")); + MBEDTLS_SSL_PEND_FATAL_ALERT( + MBEDTLS_SSL_ALERT_MSG_PROTOCOL_VERSION, + MBEDTLS_ERR_SSL_BAD_PROTOCOL_VERSION); + return MBEDTLS_ERR_SSL_BAD_PROTOCOL_VERSION; + } + ssl->keep_current_message = 1; + ssl->tls_version = MBEDTLS_SSL_VERSION_TLS1_2; + return 0; + } + + MBEDTLS_SSL_PROC_CHK( + ssl_tls13_postprocess_client_hello(ssl, parse_client_hello_ret == + SSL_CLIENT_HELLO_HRR_REQUIRED)); + + if (SSL_CLIENT_HELLO_OK == parse_client_hello_ret) { + mbedtls_ssl_handshake_set_state(ssl, MBEDTLS_SSL_SERVER_HELLO); + } else { + mbedtls_ssl_handshake_set_state(ssl, MBEDTLS_SSL_HELLO_RETRY_REQUEST); + } + +cleanup: + + MBEDTLS_SSL_DEBUG_MSG(2, ("<= parse client hello")); + return ret; +} + +/* + * Handler for MBEDTLS_SSL_SERVER_HELLO + */ +MBEDTLS_CHECK_RETURN_CRITICAL +static int ssl_tls13_prepare_server_hello(mbedtls_ssl_context *ssl) +{ + int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED; + unsigned char *server_randbytes = + ssl->handshake->randbytes + MBEDTLS_CLIENT_HELLO_RANDOM_LEN; + + if ((ret = ssl->conf->f_rng(ssl->conf->p_rng, server_randbytes, + MBEDTLS_SERVER_HELLO_RANDOM_LEN)) != 0) { + MBEDTLS_SSL_DEBUG_RET(1, "f_rng", ret); + return ret; + } + + MBEDTLS_SSL_DEBUG_BUF(3, "server hello, random bytes", server_randbytes, + MBEDTLS_SERVER_HELLO_RANDOM_LEN); + +#if defined(MBEDTLS_HAVE_TIME) + ssl->session_negotiate->start = mbedtls_time(NULL); +#endif /* MBEDTLS_HAVE_TIME */ + + return ret; +} + +/* + * ssl_tls13_write_server_hello_supported_versions_ext (): + * + * struct { + * ProtocolVersion selected_version; + * } SupportedVersions; + */ +MBEDTLS_CHECK_RETURN_CRITICAL +static int ssl_tls13_write_server_hello_supported_versions_ext( + mbedtls_ssl_context *ssl, + unsigned char *buf, + unsigned char *end, + size_t *out_len) +{ + *out_len = 0; + + MBEDTLS_SSL_DEBUG_MSG(3, ("server hello, write selected version")); + + /* Check if we have space to write the extension: + * - extension_type (2 bytes) + * - extension_data_length (2 bytes) + * - selected_version (2 bytes) + */ + MBEDTLS_SSL_CHK_BUF_PTR(buf, end, 6); + + MBEDTLS_PUT_UINT16_BE(MBEDTLS_TLS_EXT_SUPPORTED_VERSIONS, buf, 0); + + MBEDTLS_PUT_UINT16_BE(2, buf, 2); + + mbedtls_ssl_write_version(buf + 4, + ssl->conf->transport, + ssl->tls_version); + + MBEDTLS_SSL_DEBUG_MSG(3, ("supported version: [%04x]", + ssl->tls_version)); + + *out_len = 6; + + mbedtls_ssl_tls13_set_hs_sent_ext_mask( + ssl, MBEDTLS_TLS_EXT_SUPPORTED_VERSIONS); + + return 0; +} + + + +/* Generate and export a single key share. For hybrid KEMs, this can + * be called multiple times with the different components of the hybrid. */ +MBEDTLS_CHECK_RETURN_CRITICAL +static int ssl_tls13_generate_and_write_key_share(mbedtls_ssl_context *ssl, + uint16_t named_group, + unsigned char *buf, + unsigned char *end, + size_t *out_len) +{ + int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED; + + *out_len = 0; + +#if defined(MBEDTLS_SSL_TLS1_3_KEY_EXCHANGE_MODE_SOME_EPHEMERAL_ENABLED) + if (mbedtls_ssl_tls13_named_group_is_ecdhe(named_group) || + mbedtls_ssl_tls13_named_group_is_ffdh(named_group)) { + ret = mbedtls_ssl_tls13_generate_and_write_xxdh_key_exchange( + ssl, named_group, buf, end, out_len); + if (ret != 0) { + MBEDTLS_SSL_DEBUG_RET( + 1, "mbedtls_ssl_tls13_generate_and_write_xxdh_key_exchange", + ret); + return ret; + } + } else +#endif /* MBEDTLS_SSL_TLS1_3_KEY_EXCHANGE_MODE_SOME_EPHEMERAL_ENABLED */ + if (0 /* Other kinds of KEMs */) { + } else { + ((void) ssl); + ((void) named_group); + ((void) buf); + ((void) end); + ret = MBEDTLS_ERR_SSL_INTERNAL_ERROR; + } + + return ret; +} + +/* + * ssl_tls13_write_key_share_ext + * + * Structure of key_share extension in ServerHello: + * + * struct { + * NamedGroup group; + * opaque key_exchange<1..2^16-1>; + * } KeyShareEntry; + * struct { + * KeyShareEntry server_share; + * } KeyShareServerHello; + */ +MBEDTLS_CHECK_RETURN_CRITICAL +static int ssl_tls13_write_key_share_ext(mbedtls_ssl_context *ssl, + unsigned char *buf, + unsigned char *end, + size_t *out_len) +{ + int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED; + unsigned char *p = buf; + uint16_t group = ssl->handshake->offered_group_id; + unsigned char *server_share = buf + 4; + size_t key_exchange_length; + + *out_len = 0; + + MBEDTLS_SSL_DEBUG_MSG(3, ("server hello, adding key share extension")); + + MBEDTLS_SSL_DEBUG_MSG(2, ("server hello, write selected_group: %s (%04x)", + mbedtls_ssl_named_group_to_str(group), + group)); + + /* Check if we have space for header and length fields: + * - extension_type (2 bytes) + * - extension_data_length (2 bytes) + * - group (2 bytes) + * - key_exchange_length (2 bytes) + */ + MBEDTLS_SSL_CHK_BUF_PTR(p, end, 8); + MBEDTLS_PUT_UINT16_BE(MBEDTLS_TLS_EXT_KEY_SHARE, p, 0); + MBEDTLS_PUT_UINT16_BE(group, server_share, 0); + p += 8; + + /* When we introduce PQC-ECDHE hybrids, we'll want to call this + * function multiple times. */ + ret = ssl_tls13_generate_and_write_key_share( + ssl, group, server_share + 4, end, &key_exchange_length); + if (ret != 0) { + return ret; + } + p += key_exchange_length; + + MBEDTLS_PUT_UINT16_BE(key_exchange_length, server_share + 2, 0); + + MBEDTLS_PUT_UINT16_BE(p - server_share, buf, 2); + + *out_len = p - buf; + + mbedtls_ssl_tls13_set_hs_sent_ext_mask(ssl, MBEDTLS_TLS_EXT_KEY_SHARE); + + return 0; +} + +MBEDTLS_CHECK_RETURN_CRITICAL +static int ssl_tls13_write_hrr_key_share_ext(mbedtls_ssl_context *ssl, + unsigned char *buf, + unsigned char *end, + size_t *out_len) +{ + uint16_t selected_group = ssl->handshake->hrr_selected_group; + /* key_share Extension + * + * struct { + * select (Handshake.msg_type) { + * ... + * case hello_retry_request: + * NamedGroup selected_group; + * ... + * }; + * } KeyShare; + */ + + *out_len = 0; + + /* + * For a pure PSK key exchange, there is no group to agree upon. The purpose + * of the HRR is then to transmit a cookie to force the client to demonstrate + * reachability at their apparent network address (primarily useful for DTLS). + */ + if (!mbedtls_ssl_tls13_key_exchange_mode_with_ephemeral(ssl)) { + return 0; + } + + /* We should only send the key_share extension if the client's initial + * key share was not acceptable. */ + if (ssl->handshake->offered_group_id != 0) { + MBEDTLS_SSL_DEBUG_MSG(4, ("Skip key_share extension in HRR")); + return 0; + } + + if (selected_group == 0) { + MBEDTLS_SSL_DEBUG_MSG(1, ("no matching named group found")); + return MBEDTLS_ERR_SSL_HANDSHAKE_FAILURE; + } + + /* Check if we have enough space: + * - extension_type (2 bytes) + * - extension_data_length (2 bytes) + * - selected_group (2 bytes) + */ + MBEDTLS_SSL_CHK_BUF_PTR(buf, end, 6); + + MBEDTLS_PUT_UINT16_BE(MBEDTLS_TLS_EXT_KEY_SHARE, buf, 0); + MBEDTLS_PUT_UINT16_BE(2, buf, 2); + MBEDTLS_PUT_UINT16_BE(selected_group, buf, 4); + + MBEDTLS_SSL_DEBUG_MSG(3, + ("HRR selected_group: %s (%x)", + mbedtls_ssl_named_group_to_str(selected_group), + selected_group)); + + *out_len = 6; + + mbedtls_ssl_tls13_set_hs_sent_ext_mask(ssl, MBEDTLS_TLS_EXT_KEY_SHARE); + + return 0; +} + +/* + * Structure of ServerHello message: + * + * struct { + * ProtocolVersion legacy_version = 0x0303; // TLS v1.2 + * Random random; + * opaque legacy_session_id_echo<0..32>; + * CipherSuite cipher_suite; + * uint8 legacy_compression_method = 0; + * Extension extensions<6..2^16-1>; + * } ServerHello; + */ +MBEDTLS_CHECK_RETURN_CRITICAL +static int ssl_tls13_write_server_hello_body(mbedtls_ssl_context *ssl, + unsigned char *buf, + unsigned char *end, + size_t *out_len, + int is_hrr) +{ + int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED; + unsigned char *p = buf; + unsigned char *p_extensions_len; + size_t output_len; + + *out_len = 0; + ssl->handshake->sent_extensions = MBEDTLS_SSL_EXT_MASK_NONE; + + /* ... + * ProtocolVersion legacy_version = 0x0303; // TLS 1.2 + * ... + * with ProtocolVersion defined as: + * uint16 ProtocolVersion; + */ + MBEDTLS_SSL_CHK_BUF_PTR(p, end, 2); + MBEDTLS_PUT_UINT16_BE(0x0303, p, 0); + p += 2; + + /* ... + * Random random; + * ... + * with Random defined as: + * opaque Random[MBEDTLS_SERVER_HELLO_RANDOM_LEN]; + */ + MBEDTLS_SSL_CHK_BUF_PTR(p, end, MBEDTLS_SERVER_HELLO_RANDOM_LEN); + if (is_hrr) { + memcpy(p, mbedtls_ssl_tls13_hello_retry_request_magic, + MBEDTLS_SERVER_HELLO_RANDOM_LEN); + } else { + memcpy(p, &ssl->handshake->randbytes[MBEDTLS_CLIENT_HELLO_RANDOM_LEN], + MBEDTLS_SERVER_HELLO_RANDOM_LEN); + } + MBEDTLS_SSL_DEBUG_BUF(3, "server hello, random bytes", + p, MBEDTLS_SERVER_HELLO_RANDOM_LEN); + p += MBEDTLS_SERVER_HELLO_RANDOM_LEN; + + /* ... + * opaque legacy_session_id_echo<0..32>; + * ... + */ + MBEDTLS_SSL_CHK_BUF_PTR(p, end, 1 + ssl->session_negotiate->id_len); + *p++ = (unsigned char) ssl->session_negotiate->id_len; + if (ssl->session_negotiate->id_len > 0) { + memcpy(p, &ssl->session_negotiate->id[0], + ssl->session_negotiate->id_len); + p += ssl->session_negotiate->id_len; + + MBEDTLS_SSL_DEBUG_BUF(3, "session id", ssl->session_negotiate->id, + ssl->session_negotiate->id_len); + } + + /* ... + * CipherSuite cipher_suite; + * ... + * with CipherSuite defined as: + * uint8 CipherSuite[2]; + */ + MBEDTLS_SSL_CHK_BUF_PTR(p, end, 2); + MBEDTLS_PUT_UINT16_BE(ssl->session_negotiate->ciphersuite, p, 0); + p += 2; + MBEDTLS_SSL_DEBUG_MSG(3, + ("server hello, chosen ciphersuite: %s ( id=%d )", + mbedtls_ssl_get_ciphersuite_name( + ssl->session_negotiate->ciphersuite), + ssl->session_negotiate->ciphersuite)); + + /* ... + * uint8 legacy_compression_method = 0; + * ... + */ + MBEDTLS_SSL_CHK_BUF_PTR(p, end, 1); + *p++ = MBEDTLS_SSL_COMPRESS_NULL; + + /* ... + * Extension extensions<6..2^16-1>; + * ... + * struct { + * ExtensionType extension_type; (2 bytes) + * opaque extension_data<0..2^16-1>; + * } Extension; + */ + MBEDTLS_SSL_CHK_BUF_PTR(p, end, 2); + p_extensions_len = p; + p += 2; + + if ((ret = ssl_tls13_write_server_hello_supported_versions_ext( + ssl, p, end, &output_len)) != 0) { + MBEDTLS_SSL_DEBUG_RET( + 1, "ssl_tls13_write_server_hello_supported_versions_ext", ret); + return ret; + } + p += output_len; + + if (mbedtls_ssl_tls13_key_exchange_mode_with_ephemeral(ssl)) { + if (is_hrr) { + ret = ssl_tls13_write_hrr_key_share_ext(ssl, p, end, &output_len); + } else { + ret = ssl_tls13_write_key_share_ext(ssl, p, end, &output_len); + } + if (ret != 0) { + return ret; + } + p += output_len; + } + +#if defined(MBEDTLS_SSL_TLS1_3_KEY_EXCHANGE_MODE_SOME_PSK_ENABLED) + if (!is_hrr && mbedtls_ssl_tls13_key_exchange_mode_with_psk(ssl)) { + ret = ssl_tls13_write_server_pre_shared_key_ext(ssl, p, end, &output_len); + if (ret != 0) { + MBEDTLS_SSL_DEBUG_RET(1, "ssl_tls13_write_server_pre_shared_key_ext", + ret); + return ret; + } + p += output_len; + } +#endif + + MBEDTLS_PUT_UINT16_BE(p - p_extensions_len - 2, p_extensions_len, 0); + + MBEDTLS_SSL_DEBUG_BUF(4, "server hello extensions", + p_extensions_len, p - p_extensions_len); + + *out_len = p - buf; + + MBEDTLS_SSL_DEBUG_BUF(3, "server hello", buf, *out_len); + + MBEDTLS_SSL_PRINT_EXTS( + 3, is_hrr ? MBEDTLS_SSL_TLS1_3_HS_HELLO_RETRY_REQUEST : + MBEDTLS_SSL_HS_SERVER_HELLO, + ssl->handshake->sent_extensions); + + return ret; +} + +MBEDTLS_CHECK_RETURN_CRITICAL +static int ssl_tls13_finalize_server_hello(mbedtls_ssl_context *ssl) +{ + int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED; + ret = mbedtls_ssl_tls13_compute_handshake_transform(ssl); + if (ret != 0) { + MBEDTLS_SSL_DEBUG_RET(1, + "mbedtls_ssl_tls13_compute_handshake_transform", + ret); + return ret; + } + + return ret; +} + +MBEDTLS_CHECK_RETURN_CRITICAL +static int ssl_tls13_write_server_hello(mbedtls_ssl_context *ssl) +{ + int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED; + unsigned char *buf; + size_t buf_len, msg_len; + + MBEDTLS_SSL_DEBUG_MSG(2, ("=> write server hello")); + + MBEDTLS_SSL_PROC_CHK(ssl_tls13_prepare_server_hello(ssl)); + + MBEDTLS_SSL_PROC_CHK(mbedtls_ssl_start_handshake_msg( + ssl, MBEDTLS_SSL_HS_SERVER_HELLO, &buf, &buf_len)); + + MBEDTLS_SSL_PROC_CHK(ssl_tls13_write_server_hello_body(ssl, buf, + buf + buf_len, + &msg_len, + 0)); + + MBEDTLS_SSL_PROC_CHK(mbedtls_ssl_add_hs_msg_to_checksum( + ssl, MBEDTLS_SSL_HS_SERVER_HELLO, buf, msg_len)); + + MBEDTLS_SSL_PROC_CHK(mbedtls_ssl_finish_handshake_msg( + ssl, buf_len, msg_len)); + + MBEDTLS_SSL_PROC_CHK(ssl_tls13_finalize_server_hello(ssl)); + +#if defined(MBEDTLS_SSL_TLS1_3_COMPATIBILITY_MODE) + /* The server sends a dummy change_cipher_spec record immediately + * after its first handshake message. This may either be after + * a ServerHello or a HelloRetryRequest. + */ + mbedtls_ssl_handshake_set_state( + ssl, MBEDTLS_SSL_SERVER_CCS_AFTER_SERVER_HELLO); +#else + mbedtls_ssl_handshake_set_state(ssl, MBEDTLS_SSL_ENCRYPTED_EXTENSIONS); +#endif /* MBEDTLS_SSL_TLS1_3_COMPATIBILITY_MODE */ + +cleanup: + + MBEDTLS_SSL_DEBUG_MSG(2, ("<= write server hello")); + return ret; +} + + +/* + * Handler for MBEDTLS_SSL_HELLO_RETRY_REQUEST + */ +MBEDTLS_CHECK_RETURN_CRITICAL +static int ssl_tls13_prepare_hello_retry_request(mbedtls_ssl_context *ssl) +{ + int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED; + if (ssl->handshake->hello_retry_request_flag) { + MBEDTLS_SSL_DEBUG_MSG(1, ("Too many HRRs")); + MBEDTLS_SSL_PEND_FATAL_ALERT(MBEDTLS_SSL_ALERT_MSG_HANDSHAKE_FAILURE, + MBEDTLS_ERR_SSL_HANDSHAKE_FAILURE); + return MBEDTLS_ERR_SSL_HANDSHAKE_FAILURE; + } + + /* + * Create stateless transcript hash for HRR + */ + MBEDTLS_SSL_DEBUG_MSG(4, ("Reset transcript for HRR")); + ret = mbedtls_ssl_reset_transcript_for_hrr(ssl); + if (ret != 0) { + MBEDTLS_SSL_DEBUG_RET(1, "mbedtls_ssl_reset_transcript_for_hrr", ret); + return ret; + } + mbedtls_ssl_session_reset_msg_layer(ssl, 0); + + return 0; +} + +MBEDTLS_CHECK_RETURN_CRITICAL +static int ssl_tls13_write_hello_retry_request(mbedtls_ssl_context *ssl) +{ + int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED; + unsigned char *buf; + size_t buf_len, msg_len; + + MBEDTLS_SSL_DEBUG_MSG(2, ("=> write hello retry request")); + + MBEDTLS_SSL_PROC_CHK(ssl_tls13_prepare_hello_retry_request(ssl)); + + MBEDTLS_SSL_PROC_CHK(mbedtls_ssl_start_handshake_msg( + ssl, MBEDTLS_SSL_HS_SERVER_HELLO, + &buf, &buf_len)); + + MBEDTLS_SSL_PROC_CHK(ssl_tls13_write_server_hello_body(ssl, buf, + buf + buf_len, + &msg_len, + 1)); + MBEDTLS_SSL_PROC_CHK(mbedtls_ssl_add_hs_msg_to_checksum( + ssl, MBEDTLS_SSL_HS_SERVER_HELLO, buf, msg_len)); + + + MBEDTLS_SSL_PROC_CHK(mbedtls_ssl_finish_handshake_msg(ssl, buf_len, + msg_len)); + + ssl->handshake->hello_retry_request_flag = 1; + +#if defined(MBEDTLS_SSL_TLS1_3_COMPATIBILITY_MODE) + /* The server sends a dummy change_cipher_spec record immediately + * after its first handshake message. This may either be after + * a ServerHello or a HelloRetryRequest. + */ + mbedtls_ssl_handshake_set_state( + ssl, MBEDTLS_SSL_SERVER_CCS_AFTER_HELLO_RETRY_REQUEST); +#else + mbedtls_ssl_handshake_set_state(ssl, MBEDTLS_SSL_CLIENT_HELLO); +#endif /* MBEDTLS_SSL_TLS1_3_COMPATIBILITY_MODE */ + +cleanup: + MBEDTLS_SSL_DEBUG_MSG(2, ("<= write hello retry request")); + return ret; +} + +/* + * Handler for MBEDTLS_SSL_ENCRYPTED_EXTENSIONS + */ + +/* + * struct { + * Extension extensions<0..2 ^ 16 - 1>; + * } EncryptedExtensions; + * + */ +MBEDTLS_CHECK_RETURN_CRITICAL +static int ssl_tls13_write_encrypted_extensions_body(mbedtls_ssl_context *ssl, + unsigned char *buf, + unsigned char *end, + size_t *out_len) +{ + int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED; + unsigned char *p = buf; + size_t extensions_len = 0; + unsigned char *p_extensions_len; + size_t output_len; + + *out_len = 0; + + MBEDTLS_SSL_CHK_BUF_PTR(p, end, 2); + p_extensions_len = p; + p += 2; + + ((void) ssl); + ((void) ret); + ((void) output_len); + +#if defined(MBEDTLS_SSL_ALPN) + ret = mbedtls_ssl_write_alpn_ext(ssl, p, end, &output_len); + if (ret != 0) { + return ret; + } + p += output_len; +#endif /* MBEDTLS_SSL_ALPN */ + +#if defined(MBEDTLS_SSL_EARLY_DATA) + if (ssl->handshake->early_data_accepted) { + ret = mbedtls_ssl_tls13_write_early_data_ext( + ssl, 0, p, end, &output_len); + if (ret != 0) { + return ret; + } + p += output_len; + } +#endif /* MBEDTLS_SSL_EARLY_DATA */ + +#if defined(MBEDTLS_SSL_RECORD_SIZE_LIMIT) + if (ssl->handshake->received_extensions & MBEDTLS_SSL_EXT_MASK(RECORD_SIZE_LIMIT)) { + ret = mbedtls_ssl_tls13_write_record_size_limit_ext( + ssl, p, end, &output_len); + if (ret != 0) { + return ret; + } + p += output_len; + } +#endif + + extensions_len = (p - p_extensions_len) - 2; + MBEDTLS_PUT_UINT16_BE(extensions_len, p_extensions_len, 0); + + *out_len = p - buf; + + MBEDTLS_SSL_DEBUG_BUF(4, "encrypted extensions", buf, *out_len); + + MBEDTLS_SSL_PRINT_EXTS( + 3, MBEDTLS_SSL_HS_ENCRYPTED_EXTENSIONS, ssl->handshake->sent_extensions); + + return 0; +} + +MBEDTLS_CHECK_RETURN_CRITICAL +static int ssl_tls13_write_encrypted_extensions(mbedtls_ssl_context *ssl) +{ + int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED; + unsigned char *buf; + size_t buf_len, msg_len; + + mbedtls_ssl_set_outbound_transform(ssl, + ssl->handshake->transform_handshake); + MBEDTLS_SSL_DEBUG_MSG( + 3, ("switching to handshake transform for outbound data")); + + MBEDTLS_SSL_DEBUG_MSG(2, ("=> write encrypted extensions")); + + MBEDTLS_SSL_PROC_CHK(mbedtls_ssl_start_handshake_msg( + ssl, MBEDTLS_SSL_HS_ENCRYPTED_EXTENSIONS, + &buf, &buf_len)); + + MBEDTLS_SSL_PROC_CHK(ssl_tls13_write_encrypted_extensions_body( + ssl, buf, buf + buf_len, &msg_len)); + + MBEDTLS_SSL_PROC_CHK(mbedtls_ssl_add_hs_msg_to_checksum( + ssl, MBEDTLS_SSL_HS_ENCRYPTED_EXTENSIONS, + buf, msg_len)); + + MBEDTLS_SSL_PROC_CHK(mbedtls_ssl_finish_handshake_msg( + ssl, buf_len, msg_len)); + +#if defined(MBEDTLS_SSL_TLS1_3_KEY_EXCHANGE_MODE_EPHEMERAL_ENABLED) + if (mbedtls_ssl_tls13_key_exchange_mode_with_psk(ssl)) { + mbedtls_ssl_handshake_set_state(ssl, MBEDTLS_SSL_SERVER_FINISHED); + } else { + mbedtls_ssl_handshake_set_state(ssl, MBEDTLS_SSL_CERTIFICATE_REQUEST); + } +#else + mbedtls_ssl_handshake_set_state(ssl, MBEDTLS_SSL_SERVER_FINISHED); +#endif + +cleanup: + + MBEDTLS_SSL_DEBUG_MSG(2, ("<= write encrypted extensions")); + return ret; +} + +#if defined(MBEDTLS_SSL_TLS1_3_KEY_EXCHANGE_MODE_EPHEMERAL_ENABLED) +#define SSL_CERTIFICATE_REQUEST_SEND_REQUEST 0 +#define SSL_CERTIFICATE_REQUEST_SKIP 1 +/* Coordination: + * Check whether a CertificateRequest message should be written. + * Returns a negative code on failure, or + * - SSL_CERTIFICATE_REQUEST_SEND_REQUEST + * - SSL_CERTIFICATE_REQUEST_SKIP + * indicating if the writing of the CertificateRequest + * should be skipped or not. + */ +MBEDTLS_CHECK_RETURN_CRITICAL +static int ssl_tls13_certificate_request_coordinate(mbedtls_ssl_context *ssl) +{ + int authmode; + +#if defined(MBEDTLS_SSL_SERVER_NAME_INDICATION) + if (ssl->handshake->sni_authmode != MBEDTLS_SSL_VERIFY_UNSET) { + authmode = ssl->handshake->sni_authmode; + } else +#endif + authmode = ssl->conf->authmode; + + if (authmode == MBEDTLS_SSL_VERIFY_NONE) { + ssl->session_negotiate->verify_result = MBEDTLS_X509_BADCERT_SKIP_VERIFY; + return SSL_CERTIFICATE_REQUEST_SKIP; + } + + ssl->handshake->certificate_request_sent = 1; + + return SSL_CERTIFICATE_REQUEST_SEND_REQUEST; +} + +/* + * struct { + * opaque certificate_request_context<0..2^8-1>; + * Extension extensions<2..2^16-1>; + * } CertificateRequest; + * + */ +MBEDTLS_CHECK_RETURN_CRITICAL +static int ssl_tls13_write_certificate_request_body(mbedtls_ssl_context *ssl, + unsigned char *buf, + const unsigned char *end, + size_t *out_len) +{ + int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED; + unsigned char *p = buf; + size_t output_len = 0; + unsigned char *p_extensions_len; + + *out_len = 0; + + /* Check if we have enough space: + * - certificate_request_context (1 byte) + * - extensions length (2 bytes) + */ + MBEDTLS_SSL_CHK_BUF_PTR(p, end, 3); + + /* + * Write certificate_request_context + */ + /* + * We use a zero length context for the normal handshake + * messages. For post-authentication handshake messages + * this request context would be set to a non-zero value. + */ + *p++ = 0x0; + + /* + * Write extensions + */ + /* The extensions must contain the signature_algorithms. */ + p_extensions_len = p; + p += 2; + ret = mbedtls_ssl_write_sig_alg_ext(ssl, p, end, &output_len); + if (ret != 0) { + return ret; + } + + p += output_len; + MBEDTLS_PUT_UINT16_BE(p - p_extensions_len - 2, p_extensions_len, 0); + + *out_len = p - buf; + + MBEDTLS_SSL_PRINT_EXTS( + 3, MBEDTLS_SSL_HS_CERTIFICATE_REQUEST, ssl->handshake->sent_extensions); + + return 0; +} + +MBEDTLS_CHECK_RETURN_CRITICAL +static int ssl_tls13_write_certificate_request(mbedtls_ssl_context *ssl) +{ + int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED; + + MBEDTLS_SSL_DEBUG_MSG(2, ("=> write certificate request")); + + MBEDTLS_SSL_PROC_CHK_NEG(ssl_tls13_certificate_request_coordinate(ssl)); + + if (ret == SSL_CERTIFICATE_REQUEST_SEND_REQUEST) { + unsigned char *buf; + size_t buf_len, msg_len; + + MBEDTLS_SSL_PROC_CHK(mbedtls_ssl_start_handshake_msg( + ssl, MBEDTLS_SSL_HS_CERTIFICATE_REQUEST, + &buf, &buf_len)); + + MBEDTLS_SSL_PROC_CHK(ssl_tls13_write_certificate_request_body( + ssl, buf, buf + buf_len, &msg_len)); + + MBEDTLS_SSL_PROC_CHK(mbedtls_ssl_add_hs_msg_to_checksum( + ssl, MBEDTLS_SSL_HS_CERTIFICATE_REQUEST, + buf, msg_len)); + + MBEDTLS_SSL_PROC_CHK(mbedtls_ssl_finish_handshake_msg( + ssl, buf_len, msg_len)); + } else if (ret == SSL_CERTIFICATE_REQUEST_SKIP) { + MBEDTLS_SSL_DEBUG_MSG(2, ("<= skip write certificate request")); + ret = 0; + } else { + MBEDTLS_SSL_DEBUG_MSG(1, ("should never happen")); + ret = MBEDTLS_ERR_SSL_INTERNAL_ERROR; + goto cleanup; + } + + mbedtls_ssl_handshake_set_state(ssl, MBEDTLS_SSL_SERVER_CERTIFICATE); +cleanup: + + MBEDTLS_SSL_DEBUG_MSG(2, ("<= write certificate request")); + return ret; +} + +/* + * Handler for MBEDTLS_SSL_SERVER_CERTIFICATE + */ +MBEDTLS_CHECK_RETURN_CRITICAL +static int ssl_tls13_write_server_certificate(mbedtls_ssl_context *ssl) +{ + int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED; + +#if defined(MBEDTLS_X509_CRT_PARSE_C) + if ((ssl_tls13_pick_key_cert(ssl) != 0) || + mbedtls_ssl_own_cert(ssl) == NULL) { + MBEDTLS_SSL_DEBUG_MSG(2, ("No certificate available.")); + MBEDTLS_SSL_PEND_FATAL_ALERT(MBEDTLS_SSL_ALERT_MSG_HANDSHAKE_FAILURE, + MBEDTLS_ERR_SSL_HANDSHAKE_FAILURE); + return MBEDTLS_ERR_SSL_HANDSHAKE_FAILURE; + } +#endif /* MBEDTLS_X509_CRT_PARSE_C */ + + ret = mbedtls_ssl_tls13_write_certificate(ssl); + if (ret != 0) { + return ret; + } + mbedtls_ssl_handshake_set_state(ssl, MBEDTLS_SSL_CERTIFICATE_VERIFY); + return 0; +} + +/* + * Handler for MBEDTLS_SSL_CERTIFICATE_VERIFY + */ +MBEDTLS_CHECK_RETURN_CRITICAL +static int ssl_tls13_write_certificate_verify(mbedtls_ssl_context *ssl) +{ + int ret = mbedtls_ssl_tls13_write_certificate_verify(ssl); + if (ret != 0) { + return ret; + } + mbedtls_ssl_handshake_set_state(ssl, MBEDTLS_SSL_SERVER_FINISHED); + return 0; +} +#endif /* MBEDTLS_SSL_TLS1_3_KEY_EXCHANGE_MODE_EPHEMERAL_ENABLED */ + +/* + * RFC 8446 section A.2 + * + * | Send ServerHello + * | K_send = handshake + * | Send EncryptedExtensions + * | [Send CertificateRequest] + * Can send | [Send Certificate + CertificateVerify] + * app data | Send Finished + * after --> | K_send = application + * here +--------+--------+ + * No 0-RTT | | 0-RTT + * | | + * K_recv = handshake | | K_recv = early data + * [Skip decrypt errors] | +------> WAIT_EOED -+ + * | | Recv | | Recv EndOfEarlyData + * | | early data | | K_recv = handshake + * | +------------+ | + * | | + * +> WAIT_FLIGHT2 <--------+ + * | + * +--------+--------+ + * No auth | | Client auth + * | | + * | v + * | WAIT_CERT + * | Recv | | Recv Certificate + * | empty | v + * | Certificate | WAIT_CV + * | | | Recv + * | v | CertificateVerify + * +-> WAIT_FINISHED <---+ + * | Recv Finished + * + * + * The following function handles the state changes after WAIT_FLIGHT2 in the + * above diagram. We are not going to receive early data related messages + * anymore, prepare to receive the first handshake message of the client + * second flight. + */ +static void ssl_tls13_prepare_for_handshake_second_flight( + mbedtls_ssl_context *ssl) +{ + if (ssl->handshake->certificate_request_sent) { + mbedtls_ssl_handshake_set_state(ssl, MBEDTLS_SSL_CLIENT_CERTIFICATE); + } else { + MBEDTLS_SSL_DEBUG_MSG(2, ("skip parse certificate")); + MBEDTLS_SSL_DEBUG_MSG(2, ("skip parse certificate verify")); + + mbedtls_ssl_handshake_set_state(ssl, MBEDTLS_SSL_CLIENT_FINISHED); + } +} + +/* + * Handler for MBEDTLS_SSL_SERVER_FINISHED + */ +MBEDTLS_CHECK_RETURN_CRITICAL +static int ssl_tls13_write_server_finished(mbedtls_ssl_context *ssl) +{ + int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED; + + ret = mbedtls_ssl_tls13_write_finished_message(ssl); + if (ret != 0) { + return ret; + } + + ret = mbedtls_ssl_tls13_compute_application_transform(ssl); + if (ret != 0) { + MBEDTLS_SSL_PEND_FATAL_ALERT( + MBEDTLS_SSL_ALERT_MSG_HANDSHAKE_FAILURE, + MBEDTLS_ERR_SSL_HANDSHAKE_FAILURE); + return ret; + } + +#if defined(MBEDTLS_SSL_EARLY_DATA) + if (ssl->handshake->early_data_accepted) { + /* See RFC 8446 section A.2 for more information */ + MBEDTLS_SSL_DEBUG_MSG( + 1, ("Switch to early keys for inbound traffic. " + "( K_recv = early data )")); + mbedtls_ssl_set_inbound_transform( + ssl, ssl->handshake->transform_earlydata); + mbedtls_ssl_handshake_set_state(ssl, MBEDTLS_SSL_END_OF_EARLY_DATA); + return 0; + } +#endif /* MBEDTLS_SSL_EARLY_DATA */ + MBEDTLS_SSL_DEBUG_MSG( + 1, ("Switch to handshake keys for inbound traffic " + "( K_recv = handshake )")); + mbedtls_ssl_set_inbound_transform(ssl, ssl->handshake->transform_handshake); + + ssl_tls13_prepare_for_handshake_second_flight(ssl); + + return 0; +} + +#if defined(MBEDTLS_SSL_EARLY_DATA) +/* + * Handler for MBEDTLS_SSL_END_OF_EARLY_DATA + */ +#define SSL_GOT_END_OF_EARLY_DATA 0 +#define SSL_GOT_EARLY_DATA 1 +/* Coordination: + * Deals with the ambiguity of not knowing if the next message is an + * EndOfEarlyData message or an application message containing early data. + * Returns a negative code on failure, or + * - SSL_GOT_END_OF_EARLY_DATA + * - SSL_GOT_EARLY_DATA + * indicating which message is received. + */ +MBEDTLS_CHECK_RETURN_CRITICAL +static int ssl_tls13_end_of_early_data_coordinate(mbedtls_ssl_context *ssl) +{ + int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED; + + if ((ret = mbedtls_ssl_read_record(ssl, 0)) != 0) { + MBEDTLS_SSL_DEBUG_RET(1, "mbedtls_ssl_read_record", ret); + return ret; + } + ssl->keep_current_message = 1; + + if (ssl->in_msgtype == MBEDTLS_SSL_MSG_HANDSHAKE && + ssl->in_msg[0] == MBEDTLS_SSL_HS_END_OF_EARLY_DATA) { + MBEDTLS_SSL_DEBUG_MSG(3, ("Received an end_of_early_data message.")); + return SSL_GOT_END_OF_EARLY_DATA; + } + + if (ssl->in_msgtype == MBEDTLS_SSL_MSG_APPLICATION_DATA) { + if (ssl->in_offt == NULL) { + MBEDTLS_SSL_DEBUG_MSG(3, ("Received early data")); + /* Set the reading pointer */ + ssl->in_offt = ssl->in_msg; + ret = mbedtls_ssl_tls13_check_early_data_len(ssl, ssl->in_msglen); + if (ret != 0) { + return ret; + } + } + return SSL_GOT_EARLY_DATA; + } + + MBEDTLS_SSL_PEND_FATAL_ALERT(MBEDTLS_SSL_ALERT_MSG_UNEXPECTED_MESSAGE, + MBEDTLS_ERR_SSL_UNEXPECTED_MESSAGE); + return MBEDTLS_ERR_SSL_UNEXPECTED_MESSAGE; +} + +MBEDTLS_CHECK_RETURN_CRITICAL +static int ssl_tls13_parse_end_of_early_data(mbedtls_ssl_context *ssl, + const unsigned char *buf, + const unsigned char *end) +{ + /* RFC 8446 section 4.5 + * + * struct {} EndOfEarlyData; + */ + if (buf != end) { + MBEDTLS_SSL_PEND_FATAL_ALERT(MBEDTLS_SSL_ALERT_MSG_DECODE_ERROR, + MBEDTLS_ERR_SSL_DECODE_ERROR); + return MBEDTLS_ERR_SSL_DECODE_ERROR; + } + return 0; +} + +/* + * RFC 8446 section A.2 + * + * | Send ServerHello + * | K_send = handshake + * | Send EncryptedExtensions + * | [Send CertificateRequest] + * Can send | [Send Certificate + CertificateVerify] + * app data | Send Finished + * after --> | K_send = application + * here +--------+--------+ + * No 0-RTT | | 0-RTT + * | | + * K_recv = handshake | | K_recv = early data + * [Skip decrypt errors] | +------> WAIT_EOED -+ + * | | Recv | | Recv EndOfEarlyData + * | | early data | | K_recv = handshake + * | +------------+ | + * | | + * +> WAIT_FLIGHT2 <--------+ + * | + * +--------+--------+ + * No auth | | Client auth + * | | + * | v + * | WAIT_CERT + * | Recv | | Recv Certificate + * | empty | v + * | Certificate | WAIT_CV + * | | | Recv + * | v | CertificateVerify + * +-> WAIT_FINISHED <---+ + * | Recv Finished + * + * The function handles actions and state changes from 0-RTT to WAIT_FLIGHT2 in + * the above diagram. + */ +MBEDTLS_CHECK_RETURN_CRITICAL +static int ssl_tls13_process_end_of_early_data(mbedtls_ssl_context *ssl) +{ + int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED; + + MBEDTLS_SSL_DEBUG_MSG(2, ("=> ssl_tls13_process_end_of_early_data")); + + MBEDTLS_SSL_PROC_CHK_NEG(ssl_tls13_end_of_early_data_coordinate(ssl)); + + if (ret == SSL_GOT_END_OF_EARLY_DATA) { + unsigned char *buf; + size_t buf_len; + + MBEDTLS_SSL_PROC_CHK(mbedtls_ssl_tls13_fetch_handshake_msg( + ssl, MBEDTLS_SSL_HS_END_OF_EARLY_DATA, + &buf, &buf_len)); + + MBEDTLS_SSL_PROC_CHK(ssl_tls13_parse_end_of_early_data( + ssl, buf, buf + buf_len)); + + MBEDTLS_SSL_DEBUG_MSG( + 1, ("Switch to handshake keys for inbound traffic" + "( K_recv = handshake )")); + mbedtls_ssl_set_inbound_transform( + ssl, ssl->handshake->transform_handshake); + + MBEDTLS_SSL_PROC_CHK(mbedtls_ssl_add_hs_msg_to_checksum( + ssl, MBEDTLS_SSL_HS_END_OF_EARLY_DATA, + buf, buf_len)); + + ssl_tls13_prepare_for_handshake_second_flight(ssl); + + } else if (ret == SSL_GOT_EARLY_DATA) { + ret = MBEDTLS_ERR_SSL_RECEIVED_EARLY_DATA; + goto cleanup; + } else { + MBEDTLS_SSL_DEBUG_MSG(1, ("should never happen")); + ret = MBEDTLS_ERR_SSL_INTERNAL_ERROR; + goto cleanup; + } + +cleanup: + MBEDTLS_SSL_DEBUG_MSG(2, ("<= ssl_tls13_process_end_of_early_data")); + return ret; +} +#endif /* MBEDTLS_SSL_EARLY_DATA */ + +/* + * Handler for MBEDTLS_SSL_CLIENT_FINISHED + */ +MBEDTLS_CHECK_RETURN_CRITICAL +static int ssl_tls13_process_client_finished(mbedtls_ssl_context *ssl) +{ + int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED; + + ret = mbedtls_ssl_tls13_process_finished_message(ssl); + if (ret != 0) { + return ret; + } + + ret = mbedtls_ssl_tls13_compute_resumption_master_secret(ssl); + if (ret != 0) { + MBEDTLS_SSL_DEBUG_RET( + 1, "mbedtls_ssl_tls13_compute_resumption_master_secret", ret); + } + + mbedtls_ssl_handshake_set_state(ssl, MBEDTLS_SSL_HANDSHAKE_WRAPUP); + return 0; +} + +/* + * Handler for MBEDTLS_SSL_HANDSHAKE_WRAPUP + */ +MBEDTLS_CHECK_RETURN_CRITICAL +static int ssl_tls13_handshake_wrapup(mbedtls_ssl_context *ssl) +{ + MBEDTLS_SSL_DEBUG_MSG(2, ("handshake: done")); + + mbedtls_ssl_tls13_handshake_wrapup(ssl); + +#if defined(MBEDTLS_SSL_SESSION_TICKETS) && \ + defined(MBEDTLS_SSL_TLS1_3_KEY_EXCHANGE_MODE_SOME_PSK_ENABLED) +/* TODO: Remove the check of SOME_PSK_ENABLED since SESSION_TICKETS requires + * SOME_PSK_ENABLED to be enabled. Here is just to make CI happy. It is + * expected to be resolved with issue#6395. + */ + /* Sent NewSessionTicket message only when client supports PSK */ + if (mbedtls_ssl_tls13_is_some_psk_supported(ssl)) { + mbedtls_ssl_handshake_set_state( + ssl, MBEDTLS_SSL_TLS1_3_NEW_SESSION_TICKET); + } else +#endif + { + mbedtls_ssl_handshake_set_state(ssl, MBEDTLS_SSL_HANDSHAKE_OVER); + } + return 0; +} + +/* + * Handler for MBEDTLS_SSL_TLS1_3_NEW_SESSION_TICKET + */ +#define SSL_NEW_SESSION_TICKET_SKIP 0 +#define SSL_NEW_SESSION_TICKET_WRITE 1 +MBEDTLS_CHECK_RETURN_CRITICAL +static int ssl_tls13_write_new_session_ticket_coordinate(mbedtls_ssl_context *ssl) +{ + /* Check whether the use of session tickets is enabled */ + if (ssl->conf->f_ticket_write == NULL) { + MBEDTLS_SSL_DEBUG_MSG(2, ("NewSessionTicket: disabled," + " callback is not set")); + return SSL_NEW_SESSION_TICKET_SKIP; + } + if (ssl->conf->new_session_tickets_count == 0) { + MBEDTLS_SSL_DEBUG_MSG(2, ("NewSessionTicket: disabled," + " configured count is zero")); + return SSL_NEW_SESSION_TICKET_SKIP; + } + + if (ssl->handshake->new_session_tickets_count == 0) { + MBEDTLS_SSL_DEBUG_MSG(2, ("NewSessionTicket: all tickets have " + "been sent.")); + return SSL_NEW_SESSION_TICKET_SKIP; + } + + return SSL_NEW_SESSION_TICKET_WRITE; +} + +#if defined(MBEDTLS_SSL_SESSION_TICKETS) +MBEDTLS_CHECK_RETURN_CRITICAL +static int ssl_tls13_prepare_new_session_ticket(mbedtls_ssl_context *ssl, + unsigned char *ticket_nonce, + size_t ticket_nonce_size) +{ + int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED; + mbedtls_ssl_session *session = ssl->session; + mbedtls_ssl_ciphersuite_t *ciphersuite_info; + psa_algorithm_t psa_hash_alg; + int hash_length; + + MBEDTLS_SSL_DEBUG_MSG(2, ("=> prepare NewSessionTicket msg")); + + /* Set ticket_flags depends on the advertised psk key exchange mode */ + mbedtls_ssl_tls13_session_clear_ticket_flags( + session, MBEDTLS_SSL_TLS1_3_TICKET_FLAGS_MASK); +#if defined(MBEDTLS_SSL_TLS1_3_KEY_EXCHANGE_MODE_SOME_PSK_ENABLED) + mbedtls_ssl_tls13_session_set_ticket_flags( + session, ssl->handshake->tls13_kex_modes); +#endif + +#if defined(MBEDTLS_SSL_EARLY_DATA) + if (ssl->conf->early_data_enabled == MBEDTLS_SSL_EARLY_DATA_ENABLED && + ssl->conf->max_early_data_size > 0) { + mbedtls_ssl_tls13_session_set_ticket_flags( + session, MBEDTLS_SSL_TLS1_3_TICKET_ALLOW_EARLY_DATA); + session->max_early_data_size = ssl->conf->max_early_data_size; + } +#endif /* MBEDTLS_SSL_EARLY_DATA */ + + MBEDTLS_SSL_PRINT_TICKET_FLAGS(4, session->ticket_flags); + +#if defined(MBEDTLS_SSL_EARLY_DATA) && defined(MBEDTLS_SSL_ALPN) + if (session->ticket_alpn == NULL) { + ret = mbedtls_ssl_session_set_ticket_alpn(session, ssl->alpn_chosen); + if (ret != 0) { + return ret; + } + } +#endif + + /* Generate ticket_age_add */ + if ((ret = ssl->conf->f_rng(ssl->conf->p_rng, + (unsigned char *) &session->ticket_age_add, + sizeof(session->ticket_age_add)) != 0)) { + MBEDTLS_SSL_DEBUG_RET(1, "generate_ticket_age_add", ret); + return ret; + } + MBEDTLS_SSL_DEBUG_MSG(3, ("ticket_age_add: %u", + (unsigned int) session->ticket_age_add)); + + /* Generate ticket_nonce */ + ret = ssl->conf->f_rng(ssl->conf->p_rng, ticket_nonce, ticket_nonce_size); + if (ret != 0) { + MBEDTLS_SSL_DEBUG_RET(1, "generate_ticket_nonce", ret); + return ret; + } + MBEDTLS_SSL_DEBUG_BUF(3, "ticket_nonce:", + ticket_nonce, ticket_nonce_size); + + ciphersuite_info = + (mbedtls_ssl_ciphersuite_t *) ssl->handshake->ciphersuite_info; + psa_hash_alg = mbedtls_md_psa_alg_from_type((mbedtls_md_type_t) ciphersuite_info->mac); + hash_length = PSA_HASH_LENGTH(psa_hash_alg); + if (hash_length == -1 || + (size_t) hash_length > sizeof(session->resumption_key)) { + return MBEDTLS_ERR_SSL_INTERNAL_ERROR; + } + + /* In this code the psk key length equals the length of the hash */ + session->resumption_key_len = hash_length; + session->ciphersuite = ciphersuite_info->id; + + /* Compute resumption key + * + * HKDF-Expand-Label( resumption_master_secret, + * "resumption", ticket_nonce, Hash.length ) + */ + ret = mbedtls_ssl_tls13_hkdf_expand_label( + psa_hash_alg, + session->app_secrets.resumption_master_secret, + hash_length, + MBEDTLS_SSL_TLS1_3_LBL_WITH_LEN(resumption), + ticket_nonce, + ticket_nonce_size, + session->resumption_key, + hash_length); + + if (ret != 0) { + MBEDTLS_SSL_DEBUG_RET(2, + "Creating the ticket-resumed PSK failed", + ret); + return ret; + } + MBEDTLS_SSL_DEBUG_BUF(3, "Ticket-resumed PSK", + session->resumption_key, + session->resumption_key_len); + + MBEDTLS_SSL_DEBUG_BUF(3, "resumption_master_secret", + session->app_secrets.resumption_master_secret, + hash_length); + + return 0; +} + +/* This function creates a NewSessionTicket message in the following format: + * + * struct { + * uint32 ticket_lifetime; + * uint32 ticket_age_add; + * opaque ticket_nonce<0..255>; + * opaque ticket<1..2^16-1>; + * Extension extensions<0..2^16-2>; + * } NewSessionTicket; + * + * The ticket inside the NewSessionTicket message is an encrypted container + * carrying the necessary information so that the server is later able to + * re-start the communication. + * + * The following fields are placed inside the ticket by the + * f_ticket_write() function: + * + * - creation time (ticket_creation_time) + * - flags (ticket_flags) + * - age add (ticket_age_add) + * - key (resumption_key) + * - key length (resumption_key_len) + * - ciphersuite (ciphersuite) + * - max_early_data_size (max_early_data_size) + */ +MBEDTLS_CHECK_RETURN_CRITICAL +static int ssl_tls13_write_new_session_ticket_body(mbedtls_ssl_context *ssl, + unsigned char *buf, + unsigned char *end, + size_t *out_len, + unsigned char *ticket_nonce, + size_t ticket_nonce_size) +{ + int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED; + unsigned char *p = buf; + mbedtls_ssl_session *session = ssl->session; + size_t ticket_len; + uint32_t ticket_lifetime; + unsigned char *p_extensions_len; + + *out_len = 0; + MBEDTLS_SSL_DEBUG_MSG(2, ("=> write NewSessionTicket msg")); + + /* + * ticket_lifetime 4 bytes + * ticket_age_add 4 bytes + * ticket_nonce 1 + ticket_nonce_size bytes + * ticket >=2 bytes + */ + MBEDTLS_SSL_CHK_BUF_PTR(p, end, 4 + 4 + 1 + ticket_nonce_size + 2); + + /* Generate ticket and ticket_lifetime */ +#if defined(MBEDTLS_HAVE_TIME) + session->ticket_creation_time = mbedtls_ms_time(); +#endif + ret = ssl->conf->f_ticket_write(ssl->conf->p_ticket, + session, + p + 9 + ticket_nonce_size + 2, + end, + &ticket_len, + &ticket_lifetime); + if (ret != 0) { + MBEDTLS_SSL_DEBUG_RET(1, "write_ticket", ret); + return ret; + } + + /* RFC 8446 section 4.6.1 + * + * ticket_lifetime: Indicates the lifetime in seconds as a 32-bit + * unsigned integer in network byte order from the time of ticket + * issuance. Servers MUST NOT use any value greater than + * 604800 seconds (7 days) ... + */ + if (ticket_lifetime > MBEDTLS_SSL_TLS1_3_MAX_ALLOWED_TICKET_LIFETIME) { + MBEDTLS_SSL_DEBUG_MSG( + 1, ("Ticket lifetime (%u) is greater than 7 days.", + (unsigned int) ticket_lifetime)); + return MBEDTLS_ERR_SSL_BAD_INPUT_DATA; + } + + MBEDTLS_PUT_UINT32_BE(ticket_lifetime, p, 0); + MBEDTLS_SSL_DEBUG_MSG(3, ("ticket_lifetime: %u", + (unsigned int) ticket_lifetime)); + + /* Write ticket_age_add */ + MBEDTLS_PUT_UINT32_BE(session->ticket_age_add, p, 4); + MBEDTLS_SSL_DEBUG_MSG(3, ("ticket_age_add: %u", + (unsigned int) session->ticket_age_add)); + + /* Write ticket_nonce */ + p[8] = (unsigned char) ticket_nonce_size; + if (ticket_nonce_size > 0) { + memcpy(p + 9, ticket_nonce, ticket_nonce_size); + } + p += 9 + ticket_nonce_size; + + /* Write ticket */ + MBEDTLS_PUT_UINT16_BE(ticket_len, p, 0); + p += 2; + MBEDTLS_SSL_DEBUG_BUF(4, "ticket", p, ticket_len); + p += ticket_len; + + /* Ticket Extensions + * + * Extension extensions<0..2^16-2>; + */ + ssl->handshake->sent_extensions = MBEDTLS_SSL_EXT_MASK_NONE; + + MBEDTLS_SSL_CHK_BUF_PTR(p, end, 2); + p_extensions_len = p; + p += 2; + +#if defined(MBEDTLS_SSL_EARLY_DATA) + if (mbedtls_ssl_tls13_session_ticket_allow_early_data(session)) { + size_t output_len; + + if ((ret = mbedtls_ssl_tls13_write_early_data_ext( + ssl, 1, p, end, &output_len)) != 0) { + MBEDTLS_SSL_DEBUG_RET( + 1, "mbedtls_ssl_tls13_write_early_data_ext", ret); + return ret; + } + p += output_len; + } else { + MBEDTLS_SSL_DEBUG_MSG( + 4, ("early_data not allowed, " + "skip early_data extension in NewSessionTicket")); + } + +#endif /* MBEDTLS_SSL_EARLY_DATA */ + + MBEDTLS_PUT_UINT16_BE(p - p_extensions_len - 2, p_extensions_len, 0); + + *out_len = p - buf; + MBEDTLS_SSL_DEBUG_BUF(4, "ticket", buf, *out_len); + MBEDTLS_SSL_DEBUG_MSG(2, ("<= write new session ticket")); + + MBEDTLS_SSL_PRINT_EXTS( + 3, MBEDTLS_SSL_HS_NEW_SESSION_TICKET, ssl->handshake->sent_extensions); + + return 0; +} + +/* + * Handler for MBEDTLS_SSL_TLS1_3_NEW_SESSION_TICKET + */ +static int ssl_tls13_write_new_session_ticket(mbedtls_ssl_context *ssl) +{ + int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED; + + MBEDTLS_SSL_PROC_CHK_NEG(ssl_tls13_write_new_session_ticket_coordinate(ssl)); + + if (ret == SSL_NEW_SESSION_TICKET_WRITE) { + unsigned char ticket_nonce[MBEDTLS_SSL_TLS1_3_TICKET_NONCE_LENGTH]; + unsigned char *buf; + size_t buf_len, msg_len; + + MBEDTLS_SSL_PROC_CHK(ssl_tls13_prepare_new_session_ticket( + ssl, ticket_nonce, sizeof(ticket_nonce))); + + MBEDTLS_SSL_PROC_CHK(mbedtls_ssl_start_handshake_msg( + ssl, MBEDTLS_SSL_HS_NEW_SESSION_TICKET, + &buf, &buf_len)); + + MBEDTLS_SSL_PROC_CHK(ssl_tls13_write_new_session_ticket_body( + ssl, buf, buf + buf_len, &msg_len, + ticket_nonce, sizeof(ticket_nonce))); + + MBEDTLS_SSL_PROC_CHK(mbedtls_ssl_finish_handshake_msg( + ssl, buf_len, msg_len)); + + /* Limit session tickets count to one when resumption connection. + * + * See document of mbedtls_ssl_conf_new_session_tickets. + */ + if (ssl->handshake->resume == 1) { + ssl->handshake->new_session_tickets_count = 0; + } else { + ssl->handshake->new_session_tickets_count--; + } + + mbedtls_ssl_handshake_set_state( + ssl, MBEDTLS_SSL_TLS1_3_NEW_SESSION_TICKET_FLUSH); + } else { + mbedtls_ssl_handshake_set_state(ssl, MBEDTLS_SSL_HANDSHAKE_OVER); + } + +cleanup: + + return ret; +} +#endif /* MBEDTLS_SSL_SESSION_TICKETS */ + +/* + * TLS 1.3 State Machine -- server side + */ +int mbedtls_ssl_tls13_handshake_server_step(mbedtls_ssl_context *ssl) +{ + int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED; + + if (ssl->state == MBEDTLS_SSL_HANDSHAKE_OVER || ssl->handshake == NULL) { + return MBEDTLS_ERR_SSL_BAD_INPUT_DATA; + } + + MBEDTLS_SSL_DEBUG_MSG(2, ("tls13 server state: %s(%d)", + mbedtls_ssl_states_str((mbedtls_ssl_states) ssl->state), + ssl->state)); + + switch (ssl->state) { + /* start state */ + case MBEDTLS_SSL_HELLO_REQUEST: + mbedtls_ssl_handshake_set_state(ssl, MBEDTLS_SSL_CLIENT_HELLO); + ret = 0; + break; + + case MBEDTLS_SSL_CLIENT_HELLO: + ret = ssl_tls13_process_client_hello(ssl); + if (ret != 0) { + MBEDTLS_SSL_DEBUG_RET(1, "ssl_tls13_process_client_hello", ret); + } + break; + + case MBEDTLS_SSL_HELLO_RETRY_REQUEST: + ret = ssl_tls13_write_hello_retry_request(ssl); + if (ret != 0) { + MBEDTLS_SSL_DEBUG_RET(1, "ssl_tls13_write_hello_retry_request", ret); + return ret; + } + break; + + case MBEDTLS_SSL_SERVER_HELLO: + ret = ssl_tls13_write_server_hello(ssl); + break; + + case MBEDTLS_SSL_ENCRYPTED_EXTENSIONS: + ret = ssl_tls13_write_encrypted_extensions(ssl); + if (ret != 0) { + MBEDTLS_SSL_DEBUG_RET(1, "ssl_tls13_write_encrypted_extensions", ret); + return ret; + } + break; + +#if defined(MBEDTLS_SSL_TLS1_3_KEY_EXCHANGE_MODE_EPHEMERAL_ENABLED) + case MBEDTLS_SSL_CERTIFICATE_REQUEST: + ret = ssl_tls13_write_certificate_request(ssl); + break; + + case MBEDTLS_SSL_SERVER_CERTIFICATE: + ret = ssl_tls13_write_server_certificate(ssl); + break; + + case MBEDTLS_SSL_CERTIFICATE_VERIFY: + ret = ssl_tls13_write_certificate_verify(ssl); + break; +#endif /* MBEDTLS_SSL_TLS1_3_KEY_EXCHANGE_MODE_EPHEMERAL_ENABLED */ + + /* + * Injection of dummy-CCS's for middlebox compatibility + */ +#if defined(MBEDTLS_SSL_TLS1_3_COMPATIBILITY_MODE) + case MBEDTLS_SSL_SERVER_CCS_AFTER_HELLO_RETRY_REQUEST: + ret = mbedtls_ssl_tls13_write_change_cipher_spec(ssl); + if (ret == 0) { + mbedtls_ssl_handshake_set_state(ssl, MBEDTLS_SSL_CLIENT_HELLO); + } + break; + + case MBEDTLS_SSL_SERVER_CCS_AFTER_SERVER_HELLO: + ret = mbedtls_ssl_tls13_write_change_cipher_spec(ssl); + if (ret != 0) { + break; + } + mbedtls_ssl_handshake_set_state(ssl, MBEDTLS_SSL_ENCRYPTED_EXTENSIONS); + break; +#endif /* MBEDTLS_SSL_TLS1_3_COMPATIBILITY_MODE */ + + case MBEDTLS_SSL_SERVER_FINISHED: + ret = ssl_tls13_write_server_finished(ssl); + break; + +#if defined(MBEDTLS_SSL_EARLY_DATA) + case MBEDTLS_SSL_END_OF_EARLY_DATA: + ret = ssl_tls13_process_end_of_early_data(ssl); + break; +#endif /* MBEDTLS_SSL_EARLY_DATA */ + + case MBEDTLS_SSL_CLIENT_FINISHED: + ret = ssl_tls13_process_client_finished(ssl); + break; + + case MBEDTLS_SSL_HANDSHAKE_WRAPUP: + ret = ssl_tls13_handshake_wrapup(ssl); + break; + +#if defined(MBEDTLS_SSL_TLS1_3_KEY_EXCHANGE_MODE_EPHEMERAL_ENABLED) + case MBEDTLS_SSL_CLIENT_CERTIFICATE: + ret = mbedtls_ssl_tls13_process_certificate(ssl); + if (ret == 0) { + if (ssl->session_negotiate->peer_cert != NULL) { + mbedtls_ssl_handshake_set_state( + ssl, MBEDTLS_SSL_CLIENT_CERTIFICATE_VERIFY); + } else { + MBEDTLS_SSL_DEBUG_MSG(2, ("skip parse certificate verify")); + mbedtls_ssl_handshake_set_state( + ssl, MBEDTLS_SSL_CLIENT_FINISHED); + } + } + break; + + case MBEDTLS_SSL_CLIENT_CERTIFICATE_VERIFY: + ret = mbedtls_ssl_tls13_process_certificate_verify(ssl); + if (ret == 0) { + mbedtls_ssl_handshake_set_state( + ssl, MBEDTLS_SSL_CLIENT_FINISHED); + } + break; +#endif /* MBEDTLS_SSL_TLS1_3_KEY_EXCHANGE_MODE_EPHEMERAL_ENABLED */ + +#if defined(MBEDTLS_SSL_SESSION_TICKETS) + case MBEDTLS_SSL_TLS1_3_NEW_SESSION_TICKET: + ret = ssl_tls13_write_new_session_ticket(ssl); + if (ret != 0) { + MBEDTLS_SSL_DEBUG_RET(1, + "ssl_tls13_write_new_session_ticket ", + ret); + } + break; + case MBEDTLS_SSL_TLS1_3_NEW_SESSION_TICKET_FLUSH: + /* This state is necessary to do the flush of the New Session + * Ticket message written in MBEDTLS_SSL_TLS1_3_NEW_SESSION_TICKET + * as part of ssl_prepare_handshake_step. + */ + ret = 0; + + if (ssl->handshake->new_session_tickets_count == 0) { + mbedtls_ssl_handshake_set_state(ssl, MBEDTLS_SSL_HANDSHAKE_OVER); + } else { + mbedtls_ssl_handshake_set_state( + ssl, MBEDTLS_SSL_TLS1_3_NEW_SESSION_TICKET); + } + break; + +#endif /* MBEDTLS_SSL_SESSION_TICKETS */ + + default: + MBEDTLS_SSL_DEBUG_MSG(1, ("invalid state %d", ssl->state)); + return MBEDTLS_ERR_SSL_FEATURE_UNAVAILABLE; + } + + return ret; +} + +#endif /* MBEDTLS_SSL_SRV_C && MBEDTLS_SSL_PROTO_TLS1_3 */ diff --git a/vendor/mbedtls/library/threading.c b/vendor/mbedtls/library/threading.c index 0542f33f1a..85db243f21 100644 --- a/vendor/mbedtls/library/threading.c +++ b/vendor/mbedtls/library/threading.c @@ -2,24 +2,12 @@ * Threading abstraction layer * * Copyright The Mbed TLS Contributors - * SPDX-License-Identifier: Apache-2.0 - * - * Licensed under the Apache License, Version 2.0 (the "License"); you may - * not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT - * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. + * SPDX-License-Identifier: Apache-2.0 OR GPL-2.0-or-later */ /* * Ensure gmtime_r is available even with -std=c99; must be defined before - * config.h, which pulls in glibc's features.h. Harmless on other platforms. + * mbedtls_config.h, which pulls in glibc's features.h. Harmless on other platforms. */ #if !defined(_POSIX_C_SOURCE) #define _POSIX_C_SOURCE 200112L @@ -68,28 +56,27 @@ static void threading_mutex_init_pthread(mbedtls_threading_mutex_t *mutex) return; } - /* A nonzero value of is_valid indicates a successfully initialized - * mutex. This is a workaround for not being able to return an error - * code for this function. The lock/unlock functions return an error - * if is_valid is nonzero. The Mbed TLS unit test code uses this field - * to distinguish more states of the mutex; see - * tests/src/threading_helpers for details. */ - mutex->is_valid = pthread_mutex_init(&mutex->mutex, NULL) == 0; + /* One problem here is that calling lock on a pthread mutex without first + * having initialised it is undefined behaviour. Obviously we cannot check + * this here in a thread safe manner without a significant performance + * hit, so state transitions are checked in tests only via the state + * variable. Please make sure any new mutex that gets added is exercised in + * tests; see tests/src/threading_helpers.c for more details. */ + (void) pthread_mutex_init(&mutex->mutex, NULL); } static void threading_mutex_free_pthread(mbedtls_threading_mutex_t *mutex) { - if (mutex == NULL || !mutex->is_valid) { + if (mutex == NULL) { return; } (void) pthread_mutex_destroy(&mutex->mutex); - mutex->is_valid = 0; } static int threading_mutex_lock_pthread(mbedtls_threading_mutex_t *mutex) { - if (mutex == NULL || !mutex->is_valid) { + if (mutex == NULL) { return MBEDTLS_ERR_THREADING_BAD_INPUT_DATA; } @@ -102,7 +89,7 @@ static int threading_mutex_lock_pthread(mbedtls_threading_mutex_t *mutex) static int threading_mutex_unlock_pthread(mbedtls_threading_mutex_t *mutex) { - if (mutex == NULL || !mutex->is_valid) { + if (mutex == NULL) { return MBEDTLS_ERR_THREADING_BAD_INPUT_DATA; } @@ -161,6 +148,11 @@ void mbedtls_threading_set_alt(void (*mutex_init)(mbedtls_threading_mutex_t *), #if defined(THREADING_USE_GMTIME) mbedtls_mutex_init(&mbedtls_threading_gmtime_mutex); #endif +#if defined(MBEDTLS_PSA_CRYPTO_C) + mbedtls_mutex_init(&mbedtls_threading_key_slot_mutex); + mbedtls_mutex_init(&mbedtls_threading_psa_globaldata_mutex); + mbedtls_mutex_init(&mbedtls_threading_psa_rngdata_mutex); +#endif } /* @@ -174,6 +166,11 @@ void mbedtls_threading_free_alt(void) #if defined(THREADING_USE_GMTIME) mbedtls_mutex_free(&mbedtls_threading_gmtime_mutex); #endif +#if defined(MBEDTLS_PSA_CRYPTO_C) + mbedtls_mutex_free(&mbedtls_threading_key_slot_mutex); + mbedtls_mutex_free(&mbedtls_threading_psa_globaldata_mutex); + mbedtls_mutex_free(&mbedtls_threading_psa_rngdata_mutex); +#endif } #endif /* MBEDTLS_THREADING_ALT */ @@ -189,5 +186,10 @@ mbedtls_threading_mutex_t mbedtls_threading_readdir_mutex MUTEX_INIT; #if defined(THREADING_USE_GMTIME) mbedtls_threading_mutex_t mbedtls_threading_gmtime_mutex MUTEX_INIT; #endif +#if defined(MBEDTLS_PSA_CRYPTO_C) +mbedtls_threading_mutex_t mbedtls_threading_key_slot_mutex MUTEX_INIT; +mbedtls_threading_mutex_t mbedtls_threading_psa_globaldata_mutex MUTEX_INIT; +mbedtls_threading_mutex_t mbedtls_threading_psa_rngdata_mutex MUTEX_INIT; +#endif #endif /* MBEDTLS_THREADING_C */ diff --git a/vendor/mbedtls/library/timing.c b/vendor/mbedtls/library/timing.c index 94b55b3715..58f1c1ec2e 100644 --- a/vendor/mbedtls/library/timing.c +++ b/vendor/mbedtls/library/timing.c @@ -2,27 +2,11 @@ * Portable interface to the CPU cycle counter * * Copyright The Mbed TLS Contributors - * SPDX-License-Identifier: Apache-2.0 - * - * Licensed under the Apache License, Version 2.0 (the "License"); you may - * not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT - * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. + * SPDX-License-Identifier: Apache-2.0 OR GPL-2.0-or-later */ -#include - #include "common.h" -#include "mbedtls/platform.h" - #if defined(MBEDTLS_TIMING_C) #include "mbedtls/timing.h" @@ -32,15 +16,9 @@ #if !defined(unix) && !defined(__unix__) && !defined(__unix) && \ !defined(__APPLE__) && !defined(_WIN32) && !defined(__QNXNTO__) && \ !defined(__HAIKU__) && !defined(__midipix__) -#error "This module only works on Unix and Windows, see MBEDTLS_TIMING_C in config.h" +#error "This module only works on Unix and Windows, see MBEDTLS_TIMING_C in mbedtls_config.h" #endif -/* *INDENT-OFF* */ -#ifndef asm -#define asm __asm -#endif -/* *INDENT-ON* */ - #if defined(_WIN32) && !defined(EFIX64) && !defined(EFI32) #include @@ -64,260 +42,64 @@ struct _hr_time { }; #endif /* _WIN32 && !EFIX64 && !EFI32 */ -#if !defined(HAVE_HARDCLOCK) && defined(MBEDTLS_HAVE_ASM) && \ - (defined(_MSC_VER) && defined(_M_IX86)) || defined(__WATCOMC__) - -#define HAVE_HARDCLOCK - -unsigned long mbedtls_timing_hardclock(void) -{ - unsigned long tsc; - __asm rdtsc - __asm mov[tsc], eax - return tsc; -} -#endif /* !HAVE_HARDCLOCK && MBEDTLS_HAVE_ASM && - ( _MSC_VER && _M_IX86 ) || __WATCOMC__ */ - -/* some versions of mingw-64 have 32-bit longs even on x84_64 */ -#if !defined(HAVE_HARDCLOCK) && defined(MBEDTLS_HAVE_ASM) && \ - defined(__GNUC__) && (defined(__i386__) || ( \ - (defined(__amd64__) || defined(__x86_64__)) && __SIZEOF_LONG__ == 4)) - -#define HAVE_HARDCLOCK - -unsigned long mbedtls_timing_hardclock(void) -{ - unsigned long lo, hi; - asm volatile ("rdtsc" : "=a" (lo), "=d" (hi)); - return lo; -} -#endif /* !HAVE_HARDCLOCK && MBEDTLS_HAVE_ASM && - __GNUC__ && __i386__ */ - -#if !defined(HAVE_HARDCLOCK) && defined(MBEDTLS_HAVE_ASM) && \ - defined(__GNUC__) && (defined(__amd64__) || defined(__x86_64__)) - -#define HAVE_HARDCLOCK - -unsigned long mbedtls_timing_hardclock(void) -{ - unsigned long lo, hi; - asm volatile ("rdtsc" : "=a" (lo), "=d" (hi)); - return lo | (hi << 32); -} -#endif /* !HAVE_HARDCLOCK && MBEDTLS_HAVE_ASM && - __GNUC__ && ( __amd64__ || __x86_64__ ) */ - -#if !defined(HAVE_HARDCLOCK) && defined(MBEDTLS_HAVE_ASM) && \ - defined(__GNUC__) && (defined(__powerpc__) || defined(__ppc__)) - -#define HAVE_HARDCLOCK - -unsigned long mbedtls_timing_hardclock(void) -{ - unsigned long tbl, tbu0, tbu1; - - do { - asm volatile ("mftbu %0" : "=r" (tbu0)); - asm volatile ("mftb %0" : "=r" (tbl)); - asm volatile ("mftbu %0" : "=r" (tbu1)); - } while (tbu0 != tbu1); - - return tbl; -} -#endif /* !HAVE_HARDCLOCK && MBEDTLS_HAVE_ASM && - __GNUC__ && ( __powerpc__ || __ppc__ ) */ - -#if !defined(HAVE_HARDCLOCK) && defined(MBEDTLS_HAVE_ASM) && \ - defined(__GNUC__) && defined(__sparc64__) - -#if defined(__OpenBSD__) -#warning OpenBSD does not allow access to tick register using software version instead -#else -#define HAVE_HARDCLOCK - -unsigned long mbedtls_timing_hardclock(void) -{ - unsigned long tick; - asm volatile ("rdpr %%tick, %0;" : "=&r" (tick)); - return tick; -} -#endif /* __OpenBSD__ */ -#endif /* !HAVE_HARDCLOCK && MBEDTLS_HAVE_ASM && - __GNUC__ && __sparc64__ */ - -#if !defined(HAVE_HARDCLOCK) && defined(MBEDTLS_HAVE_ASM) && \ - defined(__GNUC__) && defined(__sparc__) && !defined(__sparc64__) - -#define HAVE_HARDCLOCK - -unsigned long mbedtls_timing_hardclock(void) -{ - unsigned long tick; - asm volatile (".byte 0x83, 0x41, 0x00, 0x00"); - asm volatile ("mov %%g1, %0" : "=r" (tick)); - return tick; -} -#endif /* !HAVE_HARDCLOCK && MBEDTLS_HAVE_ASM && - __GNUC__ && __sparc__ && !__sparc64__ */ - -#if !defined(HAVE_HARDCLOCK) && defined(MBEDTLS_HAVE_ASM) && \ - defined(__GNUC__) && defined(__alpha__) - -#define HAVE_HARDCLOCK - -unsigned long mbedtls_timing_hardclock(void) -{ - unsigned long cc; - asm volatile ("rpcc %0" : "=r" (cc)); - return cc & 0xFFFFFFFF; -} -#endif /* !HAVE_HARDCLOCK && MBEDTLS_HAVE_ASM && - __GNUC__ && __alpha__ */ - -#if !defined(HAVE_HARDCLOCK) && defined(MBEDTLS_HAVE_ASM) && \ - defined(__GNUC__) && defined(__ia64__) - -#define HAVE_HARDCLOCK - -unsigned long mbedtls_timing_hardclock(void) -{ - unsigned long itc; - asm volatile ("mov %0 = ar.itc" : "=r" (itc)); - return itc; -} -#endif /* !HAVE_HARDCLOCK && MBEDTLS_HAVE_ASM && - __GNUC__ && __ia64__ */ - -#if !defined(HAVE_HARDCLOCK) && defined(_MSC_VER) && \ - !defined(EFIX64) && !defined(EFI32) - -#define HAVE_HARDCLOCK - -unsigned long mbedtls_timing_hardclock(void) -{ - LARGE_INTEGER offset; - - QueryPerformanceCounter(&offset); - - return (unsigned long) (offset.QuadPart); -} -#endif /* !HAVE_HARDCLOCK && _MSC_VER && !EFIX64 && !EFI32 */ - -#if !defined(HAVE_HARDCLOCK) - -#define HAVE_HARDCLOCK - -static int hardclock_init = 0; -static struct timeval tv_init; - -unsigned long mbedtls_timing_hardclock(void) -{ - struct timeval tv_cur; - - if (hardclock_init == 0) { - gettimeofday(&tv_init, NULL); - hardclock_init = 1; - } - - gettimeofday(&tv_cur, NULL); - return (tv_cur.tv_sec - tv_init.tv_sec) * 1000000U - + (tv_cur.tv_usec - tv_init.tv_usec); -} -#endif /* !HAVE_HARDCLOCK */ - -volatile int mbedtls_timing_alarmed = 0; - +/** + * \brief Return the elapsed time in milliseconds + * + * \warning May change without notice + * + * \param val points to a timer structure + * \param reset If 0, query the elapsed time. Otherwise (re)start the timer. + * + * \return Elapsed time since the previous reset in ms. When + * restarting, this is always 0. + * + * \note To initialize a timer, call this function with reset=1. + * + * Determining the elapsed time and resetting the timer is not + * atomic on all platforms, so after the sequence + * `{ get_timer(1); ...; time1 = get_timer(1); ...; time2 = + * get_timer(0) }` the value time1+time2 is only approximately + * the delay since the first reset. + */ #if defined(_WIN32) && !defined(EFIX64) && !defined(EFI32) unsigned long mbedtls_timing_get_timer(struct mbedtls_timing_hr_time *val, int reset) { - struct _hr_time t; + struct _hr_time *t = (struct _hr_time *) val; if (reset) { - QueryPerformanceCounter(&t.start); - memcpy(val, &t, sizeof(struct _hr_time)); + QueryPerformanceCounter(&t->start); return 0; } else { unsigned long delta; LARGE_INTEGER now, hfreq; - /* We can't safely cast val because it may not be aligned, so use memcpy */ - memcpy(&t, val, sizeof(struct _hr_time)); QueryPerformanceCounter(&now); QueryPerformanceFrequency(&hfreq); - delta = (unsigned long) ((now.QuadPart - t.start.QuadPart) * 1000ul + delta = (unsigned long) ((now.QuadPart - t->start.QuadPart) * 1000ul / hfreq.QuadPart); return delta; } } -/* It's OK to use a global because alarm() is supposed to be global anyway */ -static DWORD alarmMs; - -static void TimerProc(void *TimerContext) -{ - (void) TimerContext; - Sleep(alarmMs); - mbedtls_timing_alarmed = 1; - /* _endthread will be called implicitly on return - * That ensures execution of thread function's epilogue */ -} - -void mbedtls_set_alarm(int seconds) -{ - if (seconds == 0) { - /* No need to create a thread for this simple case. - * Also, this shorcut is more reliable at least on MinGW32 */ - mbedtls_timing_alarmed = 1; - return; - } - - mbedtls_timing_alarmed = 0; - alarmMs = seconds * 1000; - (void) _beginthread(TimerProc, 0, NULL); -} - #else /* _WIN32 && !EFIX64 && !EFI32 */ unsigned long mbedtls_timing_get_timer(struct mbedtls_timing_hr_time *val, int reset) { - struct _hr_time t; + struct _hr_time *t = (struct _hr_time *) val; if (reset) { - gettimeofday(&t.start, NULL); - memcpy(val, &t, sizeof(struct _hr_time)); + gettimeofday(&t->start, NULL); return 0; } else { unsigned long delta; struct timeval now; - /* We can't safely cast val because it may not be aligned, so use memcpy */ - memcpy(&t, val, sizeof(struct _hr_time)); gettimeofday(&now, NULL); - delta = (now.tv_sec - t.start.tv_sec) * 1000ul - + (now.tv_usec - t.start.tv_usec) / 1000; + delta = (now.tv_sec - t->start.tv_sec) * 1000ul + + (now.tv_usec - t->start.tv_usec) / 1000; return delta; } } -static void sighandler(int signum) -{ - mbedtls_timing_alarmed = 1; - signal(signum, sighandler); -} - -void mbedtls_set_alarm(int seconds) -{ - mbedtls_timing_alarmed = 0; - signal(SIGALRM, sighandler); - alarm(seconds); - if (seconds == 0) { - /* alarm(0) cancelled any previous pending alarm, but the - handler won't fire, so raise the flag straight away. */ - mbedtls_timing_alarmed = 1; - } -} - #endif /* _WIN32 && !EFIX64 && !EFI32 */ /* @@ -360,177 +142,13 @@ int mbedtls_timing_get_delay(void *data) return 0; } -#endif /* !MBEDTLS_TIMING_ALT */ - -#if defined(MBEDTLS_SELF_TEST) -/* - * Busy-waits for the given number of milliseconds. - * Used for testing mbedtls_timing_hardclock. - */ -static void busy_msleep(unsigned long msec) -{ - struct mbedtls_timing_hr_time hires; - unsigned long i = 0; /* for busy-waiting */ - volatile unsigned long j; /* to prevent optimisation */ - - (void) mbedtls_timing_get_timer(&hires, 1); - - while (mbedtls_timing_get_timer(&hires, 0) < msec) { - i++; - } - - j = i; - (void) j; -} - -#define FAIL do \ - { \ - if (verbose != 0) \ - { \ - mbedtls_printf("failed at line %d\n", __LINE__); \ - mbedtls_printf(" cycles=%lu ratio=%lu millisecs=%lu secs=%lu hardfail=%d a=%lu b=%lu\n", \ - cycles, ratio, millisecs, secs, hardfail, \ - (unsigned long) a, (unsigned long) b); \ - mbedtls_printf(" elapsed(hires)=%lu status(ctx)=%d\n", \ - mbedtls_timing_get_timer(&hires, 0), \ - mbedtls_timing_get_delay(&ctx)); \ - } \ - return 1; \ - } while (0) - /* - * Checkup routine - * - * Warning: this is work in progress, some tests may not be reliable enough - * yet! False positives may happen. + * Get the final delay. */ -int mbedtls_timing_self_test(int verbose) +uint32_t mbedtls_timing_get_final_delay( + const mbedtls_timing_delay_context *data) { - unsigned long cycles = 0, ratio = 0; - unsigned long millisecs = 0, secs = 0; - int hardfail = 0; - struct mbedtls_timing_hr_time hires; - uint32_t a = 0, b = 0; - mbedtls_timing_delay_context ctx; - - if (verbose != 0) { - mbedtls_printf(" TIMING tests note: will take some time!\n"); - } - - if (verbose != 0) { - mbedtls_printf(" TIMING test #1 (set_alarm / get_timer): "); - } - - { - secs = 1; - - (void) mbedtls_timing_get_timer(&hires, 1); - - mbedtls_set_alarm((int) secs); - while (!mbedtls_timing_alarmed) { - ; - } - - millisecs = mbedtls_timing_get_timer(&hires, 0); - - /* For some reason on Windows it looks like alarm has an extra delay - * (maybe related to creating a new thread). Allow some room here. */ - if (millisecs < 800 * secs || millisecs > 1200 * secs + 300) { - FAIL; - } - } - - if (verbose != 0) { - mbedtls_printf("passed\n"); - } - - if (verbose != 0) { - mbedtls_printf(" TIMING test #2 (set/get_delay ): "); - } - - { - a = 800; - b = 400; - mbedtls_timing_set_delay(&ctx, a, a + b); /* T = 0 */ - - busy_msleep(a - a / 4); /* T = a - a/4 */ - if (mbedtls_timing_get_delay(&ctx) != 0) { - FAIL; - } - - busy_msleep(a / 4 + b / 4); /* T = a + b/4 */ - if (mbedtls_timing_get_delay(&ctx) != 1) { - FAIL; - } - - busy_msleep(b); /* T = a + b + b/4 */ - if (mbedtls_timing_get_delay(&ctx) != 2) { - FAIL; - } - } - - mbedtls_timing_set_delay(&ctx, 0, 0); - busy_msleep(200); - if (mbedtls_timing_get_delay(&ctx) != -1) { - FAIL; - } - - if (verbose != 0) { - mbedtls_printf("passed\n"); - } - - if (verbose != 0) { - mbedtls_printf(" TIMING test #3 (hardclock / get_timer): "); - } - - /* - * Allow one failure for possible counter wrapping. - * On a 4Ghz 32-bit machine the cycle counter wraps about once per second; - * since the whole test is about 10ms, it shouldn't happen twice in a row. - */ - -hard_test: - if (hardfail > 1) { - if (verbose != 0) { - mbedtls_printf("failed (ignored)\n"); - } - - goto hard_test_done; - } - - /* Get a reference ratio cycles/ms */ - millisecs = 1; - cycles = mbedtls_timing_hardclock(); - busy_msleep(millisecs); - cycles = mbedtls_timing_hardclock() - cycles; - ratio = cycles / millisecs; - - /* Check that the ratio is mostly constant */ - for (millisecs = 2; millisecs <= 4; millisecs++) { - cycles = mbedtls_timing_hardclock(); - busy_msleep(millisecs); - cycles = mbedtls_timing_hardclock() - cycles; - - /* Allow variation up to 20% */ - if (cycles / millisecs < ratio - ratio / 5 || - cycles / millisecs > ratio + ratio / 5) { - hardfail++; - goto hard_test; - } - } - - if (verbose != 0) { - mbedtls_printf("passed\n"); - } - -hard_test_done: - - if (verbose != 0) { - mbedtls_printf("\n"); - } - - return 0; + return data->fin_ms; } - -#endif /* MBEDTLS_SELF_TEST */ +#endif /* !MBEDTLS_TIMING_ALT */ #endif /* MBEDTLS_TIMING_C */ diff --git a/vendor/mbedtls/library/version.c b/vendor/mbedtls/library/version.c index 4f78c9cb12..04397332bb 100644 --- a/vendor/mbedtls/library/version.c +++ b/vendor/mbedtls/library/version.c @@ -2,19 +2,7 @@ * Version information * * Copyright The Mbed TLS Contributors - * SPDX-License-Identifier: Apache-2.0 - * - * Licensed under the Apache License, Version 2.0 (the "License"); you may - * not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT - * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. + * SPDX-License-Identifier: Apache-2.0 OR GPL-2.0-or-later */ #include "common.h" diff --git a/vendor/mbedtls/library/version_features.c b/vendor/mbedtls/library/version_features.c index ad8a357149..406161d4c7 100644 --- a/vendor/mbedtls/library/version_features.c +++ b/vendor/mbedtls/library/version_features.c @@ -2,19 +2,7 @@ * Version feature information * * Copyright The Mbed TLS Contributors - * SPDX-License-Identifier: Apache-2.0 - * - * Licensed under the Apache License, Version 2.0 (the "License"); you may - * not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT - * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. + * SPDX-License-Identifier: Apache-2.0 OR GPL-2.0-or-later */ #include "common.h" @@ -28,836 +16,797 @@ static const char * const features[] = { #if defined(MBEDTLS_VERSION_FEATURES) #if defined(MBEDTLS_HAVE_ASM) - "MBEDTLS_HAVE_ASM", + "HAVE_ASM", //no-check-names #endif /* MBEDTLS_HAVE_ASM */ #if defined(MBEDTLS_NO_UDBL_DIVISION) - "MBEDTLS_NO_UDBL_DIVISION", + "NO_UDBL_DIVISION", //no-check-names #endif /* MBEDTLS_NO_UDBL_DIVISION */ #if defined(MBEDTLS_NO_64BIT_MULTIPLICATION) - "MBEDTLS_NO_64BIT_MULTIPLICATION", + "NO_64BIT_MULTIPLICATION", //no-check-names #endif /* MBEDTLS_NO_64BIT_MULTIPLICATION */ #if defined(MBEDTLS_HAVE_SSE2) - "MBEDTLS_HAVE_SSE2", + "HAVE_SSE2", //no-check-names #endif /* MBEDTLS_HAVE_SSE2 */ #if defined(MBEDTLS_HAVE_TIME) - "MBEDTLS_HAVE_TIME", + "HAVE_TIME", //no-check-names #endif /* MBEDTLS_HAVE_TIME */ #if defined(MBEDTLS_HAVE_TIME_DATE) - "MBEDTLS_HAVE_TIME_DATE", + "HAVE_TIME_DATE", //no-check-names #endif /* MBEDTLS_HAVE_TIME_DATE */ #if defined(MBEDTLS_PLATFORM_MEMORY) - "MBEDTLS_PLATFORM_MEMORY", + "PLATFORM_MEMORY", //no-check-names #endif /* MBEDTLS_PLATFORM_MEMORY */ #if defined(MBEDTLS_PLATFORM_NO_STD_FUNCTIONS) - "MBEDTLS_PLATFORM_NO_STD_FUNCTIONS", + "PLATFORM_NO_STD_FUNCTIONS", //no-check-names #endif /* MBEDTLS_PLATFORM_NO_STD_FUNCTIONS */ +#if defined(MBEDTLS_PLATFORM_SETBUF_ALT) + "PLATFORM_SETBUF_ALT", //no-check-names +#endif /* MBEDTLS_PLATFORM_SETBUF_ALT */ #if defined(MBEDTLS_PLATFORM_EXIT_ALT) - "MBEDTLS_PLATFORM_EXIT_ALT", + "PLATFORM_EXIT_ALT", //no-check-names #endif /* MBEDTLS_PLATFORM_EXIT_ALT */ #if defined(MBEDTLS_PLATFORM_TIME_ALT) - "MBEDTLS_PLATFORM_TIME_ALT", + "PLATFORM_TIME_ALT", //no-check-names #endif /* MBEDTLS_PLATFORM_TIME_ALT */ #if defined(MBEDTLS_PLATFORM_FPRINTF_ALT) - "MBEDTLS_PLATFORM_FPRINTF_ALT", + "PLATFORM_FPRINTF_ALT", //no-check-names #endif /* MBEDTLS_PLATFORM_FPRINTF_ALT */ #if defined(MBEDTLS_PLATFORM_PRINTF_ALT) - "MBEDTLS_PLATFORM_PRINTF_ALT", + "PLATFORM_PRINTF_ALT", //no-check-names #endif /* MBEDTLS_PLATFORM_PRINTF_ALT */ #if defined(MBEDTLS_PLATFORM_SNPRINTF_ALT) - "MBEDTLS_PLATFORM_SNPRINTF_ALT", + "PLATFORM_SNPRINTF_ALT", //no-check-names #endif /* MBEDTLS_PLATFORM_SNPRINTF_ALT */ #if defined(MBEDTLS_PLATFORM_VSNPRINTF_ALT) - "MBEDTLS_PLATFORM_VSNPRINTF_ALT", + "PLATFORM_VSNPRINTF_ALT", //no-check-names #endif /* MBEDTLS_PLATFORM_VSNPRINTF_ALT */ #if defined(MBEDTLS_PLATFORM_NV_SEED_ALT) - "MBEDTLS_PLATFORM_NV_SEED_ALT", + "PLATFORM_NV_SEED_ALT", //no-check-names #endif /* MBEDTLS_PLATFORM_NV_SEED_ALT */ #if defined(MBEDTLS_PLATFORM_SETUP_TEARDOWN_ALT) - "MBEDTLS_PLATFORM_SETUP_TEARDOWN_ALT", + "PLATFORM_SETUP_TEARDOWN_ALT", //no-check-names #endif /* MBEDTLS_PLATFORM_SETUP_TEARDOWN_ALT */ +#if defined(MBEDTLS_PLATFORM_MS_TIME_ALT) + "PLATFORM_MS_TIME_ALT", //no-check-names +#endif /* MBEDTLS_PLATFORM_MS_TIME_ALT */ #if defined(MBEDTLS_PLATFORM_GMTIME_R_ALT) - "MBEDTLS_PLATFORM_GMTIME_R_ALT", + "PLATFORM_GMTIME_R_ALT", //no-check-names #endif /* MBEDTLS_PLATFORM_GMTIME_R_ALT */ #if defined(MBEDTLS_PLATFORM_ZEROIZE_ALT) - "MBEDTLS_PLATFORM_ZEROIZE_ALT", + "PLATFORM_ZEROIZE_ALT", //no-check-names #endif /* MBEDTLS_PLATFORM_ZEROIZE_ALT */ #if defined(MBEDTLS_DEPRECATED_WARNING) - "MBEDTLS_DEPRECATED_WARNING", + "DEPRECATED_WARNING", //no-check-names #endif /* MBEDTLS_DEPRECATED_WARNING */ #if defined(MBEDTLS_DEPRECATED_REMOVED) - "MBEDTLS_DEPRECATED_REMOVED", + "DEPRECATED_REMOVED", //no-check-names #endif /* MBEDTLS_DEPRECATED_REMOVED */ -#if defined(MBEDTLS_CHECK_PARAMS) - "MBEDTLS_CHECK_PARAMS", -#endif /* MBEDTLS_CHECK_PARAMS */ -#if defined(MBEDTLS_CHECK_PARAMS_ASSERT) - "MBEDTLS_CHECK_PARAMS_ASSERT", -#endif /* MBEDTLS_CHECK_PARAMS_ASSERT */ #if defined(MBEDTLS_TIMING_ALT) - "MBEDTLS_TIMING_ALT", + "TIMING_ALT", //no-check-names #endif /* MBEDTLS_TIMING_ALT */ #if defined(MBEDTLS_AES_ALT) - "MBEDTLS_AES_ALT", + "AES_ALT", //no-check-names #endif /* MBEDTLS_AES_ALT */ -#if defined(MBEDTLS_ARC4_ALT) - "MBEDTLS_ARC4_ALT", -#endif /* MBEDTLS_ARC4_ALT */ #if defined(MBEDTLS_ARIA_ALT) - "MBEDTLS_ARIA_ALT", + "ARIA_ALT", //no-check-names #endif /* MBEDTLS_ARIA_ALT */ -#if defined(MBEDTLS_BLOWFISH_ALT) - "MBEDTLS_BLOWFISH_ALT", -#endif /* MBEDTLS_BLOWFISH_ALT */ #if defined(MBEDTLS_CAMELLIA_ALT) - "MBEDTLS_CAMELLIA_ALT", + "CAMELLIA_ALT", //no-check-names #endif /* MBEDTLS_CAMELLIA_ALT */ #if defined(MBEDTLS_CCM_ALT) - "MBEDTLS_CCM_ALT", + "CCM_ALT", //no-check-names #endif /* MBEDTLS_CCM_ALT */ #if defined(MBEDTLS_CHACHA20_ALT) - "MBEDTLS_CHACHA20_ALT", + "CHACHA20_ALT", //no-check-names #endif /* MBEDTLS_CHACHA20_ALT */ #if defined(MBEDTLS_CHACHAPOLY_ALT) - "MBEDTLS_CHACHAPOLY_ALT", + "CHACHAPOLY_ALT", //no-check-names #endif /* MBEDTLS_CHACHAPOLY_ALT */ #if defined(MBEDTLS_CMAC_ALT) - "MBEDTLS_CMAC_ALT", + "CMAC_ALT", //no-check-names #endif /* MBEDTLS_CMAC_ALT */ #if defined(MBEDTLS_DES_ALT) - "MBEDTLS_DES_ALT", + "DES_ALT", //no-check-names #endif /* MBEDTLS_DES_ALT */ #if defined(MBEDTLS_DHM_ALT) - "MBEDTLS_DHM_ALT", + "DHM_ALT", //no-check-names #endif /* MBEDTLS_DHM_ALT */ #if defined(MBEDTLS_ECJPAKE_ALT) - "MBEDTLS_ECJPAKE_ALT", + "ECJPAKE_ALT", //no-check-names #endif /* MBEDTLS_ECJPAKE_ALT */ #if defined(MBEDTLS_GCM_ALT) - "MBEDTLS_GCM_ALT", + "GCM_ALT", //no-check-names #endif /* MBEDTLS_GCM_ALT */ #if defined(MBEDTLS_NIST_KW_ALT) - "MBEDTLS_NIST_KW_ALT", + "NIST_KW_ALT", //no-check-names #endif /* MBEDTLS_NIST_KW_ALT */ -#if defined(MBEDTLS_MD2_ALT) - "MBEDTLS_MD2_ALT", -#endif /* MBEDTLS_MD2_ALT */ -#if defined(MBEDTLS_MD4_ALT) - "MBEDTLS_MD4_ALT", -#endif /* MBEDTLS_MD4_ALT */ #if defined(MBEDTLS_MD5_ALT) - "MBEDTLS_MD5_ALT", + "MD5_ALT", //no-check-names #endif /* MBEDTLS_MD5_ALT */ #if defined(MBEDTLS_POLY1305_ALT) - "MBEDTLS_POLY1305_ALT", + "POLY1305_ALT", //no-check-names #endif /* MBEDTLS_POLY1305_ALT */ #if defined(MBEDTLS_RIPEMD160_ALT) - "MBEDTLS_RIPEMD160_ALT", + "RIPEMD160_ALT", //no-check-names #endif /* MBEDTLS_RIPEMD160_ALT */ #if defined(MBEDTLS_RSA_ALT) - "MBEDTLS_RSA_ALT", + "RSA_ALT", //no-check-names #endif /* MBEDTLS_RSA_ALT */ #if defined(MBEDTLS_SHA1_ALT) - "MBEDTLS_SHA1_ALT", + "SHA1_ALT", //no-check-names #endif /* MBEDTLS_SHA1_ALT */ #if defined(MBEDTLS_SHA256_ALT) - "MBEDTLS_SHA256_ALT", + "SHA256_ALT", //no-check-names #endif /* MBEDTLS_SHA256_ALT */ #if defined(MBEDTLS_SHA512_ALT) - "MBEDTLS_SHA512_ALT", + "SHA512_ALT", //no-check-names #endif /* MBEDTLS_SHA512_ALT */ -#if defined(MBEDTLS_XTEA_ALT) - "MBEDTLS_XTEA_ALT", -#endif /* MBEDTLS_XTEA_ALT */ #if defined(MBEDTLS_ECP_ALT) - "MBEDTLS_ECP_ALT", + "ECP_ALT", //no-check-names #endif /* MBEDTLS_ECP_ALT */ -#if defined(MBEDTLS_MD2_PROCESS_ALT) - "MBEDTLS_MD2_PROCESS_ALT", -#endif /* MBEDTLS_MD2_PROCESS_ALT */ -#if defined(MBEDTLS_MD4_PROCESS_ALT) - "MBEDTLS_MD4_PROCESS_ALT", -#endif /* MBEDTLS_MD4_PROCESS_ALT */ #if defined(MBEDTLS_MD5_PROCESS_ALT) - "MBEDTLS_MD5_PROCESS_ALT", + "MD5_PROCESS_ALT", //no-check-names #endif /* MBEDTLS_MD5_PROCESS_ALT */ #if defined(MBEDTLS_RIPEMD160_PROCESS_ALT) - "MBEDTLS_RIPEMD160_PROCESS_ALT", + "RIPEMD160_PROCESS_ALT", //no-check-names #endif /* MBEDTLS_RIPEMD160_PROCESS_ALT */ #if defined(MBEDTLS_SHA1_PROCESS_ALT) - "MBEDTLS_SHA1_PROCESS_ALT", + "SHA1_PROCESS_ALT", //no-check-names #endif /* MBEDTLS_SHA1_PROCESS_ALT */ #if defined(MBEDTLS_SHA256_PROCESS_ALT) - "MBEDTLS_SHA256_PROCESS_ALT", + "SHA256_PROCESS_ALT", //no-check-names #endif /* MBEDTLS_SHA256_PROCESS_ALT */ #if defined(MBEDTLS_SHA512_PROCESS_ALT) - "MBEDTLS_SHA512_PROCESS_ALT", + "SHA512_PROCESS_ALT", //no-check-names #endif /* MBEDTLS_SHA512_PROCESS_ALT */ #if defined(MBEDTLS_DES_SETKEY_ALT) - "MBEDTLS_DES_SETKEY_ALT", + "DES_SETKEY_ALT", //no-check-names #endif /* MBEDTLS_DES_SETKEY_ALT */ #if defined(MBEDTLS_DES_CRYPT_ECB_ALT) - "MBEDTLS_DES_CRYPT_ECB_ALT", + "DES_CRYPT_ECB_ALT", //no-check-names #endif /* MBEDTLS_DES_CRYPT_ECB_ALT */ #if defined(MBEDTLS_DES3_CRYPT_ECB_ALT) - "MBEDTLS_DES3_CRYPT_ECB_ALT", + "DES3_CRYPT_ECB_ALT", //no-check-names #endif /* MBEDTLS_DES3_CRYPT_ECB_ALT */ #if defined(MBEDTLS_AES_SETKEY_ENC_ALT) - "MBEDTLS_AES_SETKEY_ENC_ALT", + "AES_SETKEY_ENC_ALT", //no-check-names #endif /* MBEDTLS_AES_SETKEY_ENC_ALT */ #if defined(MBEDTLS_AES_SETKEY_DEC_ALT) - "MBEDTLS_AES_SETKEY_DEC_ALT", + "AES_SETKEY_DEC_ALT", //no-check-names #endif /* MBEDTLS_AES_SETKEY_DEC_ALT */ #if defined(MBEDTLS_AES_ENCRYPT_ALT) - "MBEDTLS_AES_ENCRYPT_ALT", + "AES_ENCRYPT_ALT", //no-check-names #endif /* MBEDTLS_AES_ENCRYPT_ALT */ #if defined(MBEDTLS_AES_DECRYPT_ALT) - "MBEDTLS_AES_DECRYPT_ALT", + "AES_DECRYPT_ALT", //no-check-names #endif /* MBEDTLS_AES_DECRYPT_ALT */ #if defined(MBEDTLS_ECDH_GEN_PUBLIC_ALT) - "MBEDTLS_ECDH_GEN_PUBLIC_ALT", + "ECDH_GEN_PUBLIC_ALT", //no-check-names #endif /* MBEDTLS_ECDH_GEN_PUBLIC_ALT */ #if defined(MBEDTLS_ECDH_COMPUTE_SHARED_ALT) - "MBEDTLS_ECDH_COMPUTE_SHARED_ALT", + "ECDH_COMPUTE_SHARED_ALT", //no-check-names #endif /* MBEDTLS_ECDH_COMPUTE_SHARED_ALT */ #if defined(MBEDTLS_ECDSA_VERIFY_ALT) - "MBEDTLS_ECDSA_VERIFY_ALT", + "ECDSA_VERIFY_ALT", //no-check-names #endif /* MBEDTLS_ECDSA_VERIFY_ALT */ #if defined(MBEDTLS_ECDSA_SIGN_ALT) - "MBEDTLS_ECDSA_SIGN_ALT", + "ECDSA_SIGN_ALT", //no-check-names #endif /* MBEDTLS_ECDSA_SIGN_ALT */ #if defined(MBEDTLS_ECDSA_GENKEY_ALT) - "MBEDTLS_ECDSA_GENKEY_ALT", + "ECDSA_GENKEY_ALT", //no-check-names #endif /* MBEDTLS_ECDSA_GENKEY_ALT */ #if defined(MBEDTLS_ECP_INTERNAL_ALT) - "MBEDTLS_ECP_INTERNAL_ALT", + "ECP_INTERNAL_ALT", //no-check-names #endif /* MBEDTLS_ECP_INTERNAL_ALT */ #if defined(MBEDTLS_ECP_NO_FALLBACK) - "MBEDTLS_ECP_NO_FALLBACK", + "ECP_NO_FALLBACK", //no-check-names #endif /* MBEDTLS_ECP_NO_FALLBACK */ #if defined(MBEDTLS_ECP_RANDOMIZE_JAC_ALT) - "MBEDTLS_ECP_RANDOMIZE_JAC_ALT", + "ECP_RANDOMIZE_JAC_ALT", //no-check-names #endif /* MBEDTLS_ECP_RANDOMIZE_JAC_ALT */ #if defined(MBEDTLS_ECP_ADD_MIXED_ALT) - "MBEDTLS_ECP_ADD_MIXED_ALT", + "ECP_ADD_MIXED_ALT", //no-check-names #endif /* MBEDTLS_ECP_ADD_MIXED_ALT */ #if defined(MBEDTLS_ECP_DOUBLE_JAC_ALT) - "MBEDTLS_ECP_DOUBLE_JAC_ALT", + "ECP_DOUBLE_JAC_ALT", //no-check-names #endif /* MBEDTLS_ECP_DOUBLE_JAC_ALT */ #if defined(MBEDTLS_ECP_NORMALIZE_JAC_MANY_ALT) - "MBEDTLS_ECP_NORMALIZE_JAC_MANY_ALT", + "ECP_NORMALIZE_JAC_MANY_ALT", //no-check-names #endif /* MBEDTLS_ECP_NORMALIZE_JAC_MANY_ALT */ #if defined(MBEDTLS_ECP_NORMALIZE_JAC_ALT) - "MBEDTLS_ECP_NORMALIZE_JAC_ALT", + "ECP_NORMALIZE_JAC_ALT", //no-check-names #endif /* MBEDTLS_ECP_NORMALIZE_JAC_ALT */ #if defined(MBEDTLS_ECP_DOUBLE_ADD_MXZ_ALT) - "MBEDTLS_ECP_DOUBLE_ADD_MXZ_ALT", + "ECP_DOUBLE_ADD_MXZ_ALT", //no-check-names #endif /* MBEDTLS_ECP_DOUBLE_ADD_MXZ_ALT */ #if defined(MBEDTLS_ECP_RANDOMIZE_MXZ_ALT) - "MBEDTLS_ECP_RANDOMIZE_MXZ_ALT", + "ECP_RANDOMIZE_MXZ_ALT", //no-check-names #endif /* MBEDTLS_ECP_RANDOMIZE_MXZ_ALT */ #if defined(MBEDTLS_ECP_NORMALIZE_MXZ_ALT) - "MBEDTLS_ECP_NORMALIZE_MXZ_ALT", + "ECP_NORMALIZE_MXZ_ALT", //no-check-names #endif /* MBEDTLS_ECP_NORMALIZE_MXZ_ALT */ -#if defined(MBEDTLS_TEST_NULL_ENTROPY) - "MBEDTLS_TEST_NULL_ENTROPY", -#endif /* MBEDTLS_TEST_NULL_ENTROPY */ #if defined(MBEDTLS_ENTROPY_HARDWARE_ALT) - "MBEDTLS_ENTROPY_HARDWARE_ALT", + "ENTROPY_HARDWARE_ALT", //no-check-names #endif /* MBEDTLS_ENTROPY_HARDWARE_ALT */ #if defined(MBEDTLS_AES_ROM_TABLES) - "MBEDTLS_AES_ROM_TABLES", + "AES_ROM_TABLES", //no-check-names #endif /* MBEDTLS_AES_ROM_TABLES */ #if defined(MBEDTLS_AES_FEWER_TABLES) - "MBEDTLS_AES_FEWER_TABLES", + "AES_FEWER_TABLES", //no-check-names #endif /* MBEDTLS_AES_FEWER_TABLES */ +#if defined(MBEDTLS_AES_ONLY_128_BIT_KEY_LENGTH) + "AES_ONLY_128_BIT_KEY_LENGTH", //no-check-names +#endif /* MBEDTLS_AES_ONLY_128_BIT_KEY_LENGTH */ +#if defined(MBEDTLS_AES_USE_HARDWARE_ONLY) + "AES_USE_HARDWARE_ONLY", //no-check-names +#endif /* MBEDTLS_AES_USE_HARDWARE_ONLY */ #if defined(MBEDTLS_CAMELLIA_SMALL_MEMORY) - "MBEDTLS_CAMELLIA_SMALL_MEMORY", + "CAMELLIA_SMALL_MEMORY", //no-check-names #endif /* MBEDTLS_CAMELLIA_SMALL_MEMORY */ #if defined(MBEDTLS_CHECK_RETURN_WARNING) - "MBEDTLS_CHECK_RETURN_WARNING", + "CHECK_RETURN_WARNING", //no-check-names #endif /* MBEDTLS_CHECK_RETURN_WARNING */ #if defined(MBEDTLS_CIPHER_MODE_CBC) - "MBEDTLS_CIPHER_MODE_CBC", + "CIPHER_MODE_CBC", //no-check-names #endif /* MBEDTLS_CIPHER_MODE_CBC */ #if defined(MBEDTLS_CIPHER_MODE_CFB) - "MBEDTLS_CIPHER_MODE_CFB", + "CIPHER_MODE_CFB", //no-check-names #endif /* MBEDTLS_CIPHER_MODE_CFB */ #if defined(MBEDTLS_CIPHER_MODE_CTR) - "MBEDTLS_CIPHER_MODE_CTR", + "CIPHER_MODE_CTR", //no-check-names #endif /* MBEDTLS_CIPHER_MODE_CTR */ #if defined(MBEDTLS_CIPHER_MODE_OFB) - "MBEDTLS_CIPHER_MODE_OFB", + "CIPHER_MODE_OFB", //no-check-names #endif /* MBEDTLS_CIPHER_MODE_OFB */ #if defined(MBEDTLS_CIPHER_MODE_XTS) - "MBEDTLS_CIPHER_MODE_XTS", + "CIPHER_MODE_XTS", //no-check-names #endif /* MBEDTLS_CIPHER_MODE_XTS */ #if defined(MBEDTLS_CIPHER_NULL_CIPHER) - "MBEDTLS_CIPHER_NULL_CIPHER", + "CIPHER_NULL_CIPHER", //no-check-names #endif /* MBEDTLS_CIPHER_NULL_CIPHER */ #if defined(MBEDTLS_CIPHER_PADDING_PKCS7) - "MBEDTLS_CIPHER_PADDING_PKCS7", + "CIPHER_PADDING_PKCS7", //no-check-names #endif /* MBEDTLS_CIPHER_PADDING_PKCS7 */ #if defined(MBEDTLS_CIPHER_PADDING_ONE_AND_ZEROS) - "MBEDTLS_CIPHER_PADDING_ONE_AND_ZEROS", + "CIPHER_PADDING_ONE_AND_ZEROS", //no-check-names #endif /* MBEDTLS_CIPHER_PADDING_ONE_AND_ZEROS */ #if defined(MBEDTLS_CIPHER_PADDING_ZEROS_AND_LEN) - "MBEDTLS_CIPHER_PADDING_ZEROS_AND_LEN", + "CIPHER_PADDING_ZEROS_AND_LEN", //no-check-names #endif /* MBEDTLS_CIPHER_PADDING_ZEROS_AND_LEN */ #if defined(MBEDTLS_CIPHER_PADDING_ZEROS) - "MBEDTLS_CIPHER_PADDING_ZEROS", + "CIPHER_PADDING_ZEROS", //no-check-names #endif /* MBEDTLS_CIPHER_PADDING_ZEROS */ #if defined(MBEDTLS_CTR_DRBG_USE_128_BIT_KEY) - "MBEDTLS_CTR_DRBG_USE_128_BIT_KEY", + "CTR_DRBG_USE_128_BIT_KEY", //no-check-names #endif /* MBEDTLS_CTR_DRBG_USE_128_BIT_KEY */ -#if defined(MBEDTLS_ENABLE_WEAK_CIPHERSUITES) - "MBEDTLS_ENABLE_WEAK_CIPHERSUITES", -#endif /* MBEDTLS_ENABLE_WEAK_CIPHERSUITES */ -#if defined(MBEDTLS_REMOVE_ARC4_CIPHERSUITES) - "MBEDTLS_REMOVE_ARC4_CIPHERSUITES", -#endif /* MBEDTLS_REMOVE_ARC4_CIPHERSUITES */ -#if defined(MBEDTLS_REMOVE_3DES_CIPHERSUITES) - "MBEDTLS_REMOVE_3DES_CIPHERSUITES", -#endif /* MBEDTLS_REMOVE_3DES_CIPHERSUITES */ #if defined(MBEDTLS_ECDH_VARIANT_EVEREST_ENABLED) - "MBEDTLS_ECDH_VARIANT_EVEREST_ENABLED", + "ECDH_VARIANT_EVEREST_ENABLED", //no-check-names #endif /* MBEDTLS_ECDH_VARIANT_EVEREST_ENABLED */ #if defined(MBEDTLS_ECP_DP_SECP192R1_ENABLED) - "MBEDTLS_ECP_DP_SECP192R1_ENABLED", + "ECP_DP_SECP192R1_ENABLED", //no-check-names #endif /* MBEDTLS_ECP_DP_SECP192R1_ENABLED */ #if defined(MBEDTLS_ECP_DP_SECP224R1_ENABLED) - "MBEDTLS_ECP_DP_SECP224R1_ENABLED", + "ECP_DP_SECP224R1_ENABLED", //no-check-names #endif /* MBEDTLS_ECP_DP_SECP224R1_ENABLED */ #if defined(MBEDTLS_ECP_DP_SECP256R1_ENABLED) - "MBEDTLS_ECP_DP_SECP256R1_ENABLED", + "ECP_DP_SECP256R1_ENABLED", //no-check-names #endif /* MBEDTLS_ECP_DP_SECP256R1_ENABLED */ #if defined(MBEDTLS_ECP_DP_SECP384R1_ENABLED) - "MBEDTLS_ECP_DP_SECP384R1_ENABLED", + "ECP_DP_SECP384R1_ENABLED", //no-check-names #endif /* MBEDTLS_ECP_DP_SECP384R1_ENABLED */ #if defined(MBEDTLS_ECP_DP_SECP521R1_ENABLED) - "MBEDTLS_ECP_DP_SECP521R1_ENABLED", + "ECP_DP_SECP521R1_ENABLED", //no-check-names #endif /* MBEDTLS_ECP_DP_SECP521R1_ENABLED */ #if defined(MBEDTLS_ECP_DP_SECP192K1_ENABLED) - "MBEDTLS_ECP_DP_SECP192K1_ENABLED", + "ECP_DP_SECP192K1_ENABLED", //no-check-names #endif /* MBEDTLS_ECP_DP_SECP192K1_ENABLED */ #if defined(MBEDTLS_ECP_DP_SECP224K1_ENABLED) - "MBEDTLS_ECP_DP_SECP224K1_ENABLED", + "ECP_DP_SECP224K1_ENABLED", //no-check-names #endif /* MBEDTLS_ECP_DP_SECP224K1_ENABLED */ #if defined(MBEDTLS_ECP_DP_SECP256K1_ENABLED) - "MBEDTLS_ECP_DP_SECP256K1_ENABLED", + "ECP_DP_SECP256K1_ENABLED", //no-check-names #endif /* MBEDTLS_ECP_DP_SECP256K1_ENABLED */ #if defined(MBEDTLS_ECP_DP_BP256R1_ENABLED) - "MBEDTLS_ECP_DP_BP256R1_ENABLED", + "ECP_DP_BP256R1_ENABLED", //no-check-names #endif /* MBEDTLS_ECP_DP_BP256R1_ENABLED */ #if defined(MBEDTLS_ECP_DP_BP384R1_ENABLED) - "MBEDTLS_ECP_DP_BP384R1_ENABLED", + "ECP_DP_BP384R1_ENABLED", //no-check-names #endif /* MBEDTLS_ECP_DP_BP384R1_ENABLED */ #if defined(MBEDTLS_ECP_DP_BP512R1_ENABLED) - "MBEDTLS_ECP_DP_BP512R1_ENABLED", + "ECP_DP_BP512R1_ENABLED", //no-check-names #endif /* MBEDTLS_ECP_DP_BP512R1_ENABLED */ #if defined(MBEDTLS_ECP_DP_CURVE25519_ENABLED) - "MBEDTLS_ECP_DP_CURVE25519_ENABLED", + "ECP_DP_CURVE25519_ENABLED", //no-check-names #endif /* MBEDTLS_ECP_DP_CURVE25519_ENABLED */ #if defined(MBEDTLS_ECP_DP_CURVE448_ENABLED) - "MBEDTLS_ECP_DP_CURVE448_ENABLED", + "ECP_DP_CURVE448_ENABLED", //no-check-names #endif /* MBEDTLS_ECP_DP_CURVE448_ENABLED */ #if defined(MBEDTLS_ECP_NIST_OPTIM) - "MBEDTLS_ECP_NIST_OPTIM", + "ECP_NIST_OPTIM", //no-check-names #endif /* MBEDTLS_ECP_NIST_OPTIM */ -#if defined(MBEDTLS_ECP_NO_INTERNAL_RNG) - "MBEDTLS_ECP_NO_INTERNAL_RNG", -#endif /* MBEDTLS_ECP_NO_INTERNAL_RNG */ #if defined(MBEDTLS_ECP_RESTARTABLE) - "MBEDTLS_ECP_RESTARTABLE", + "ECP_RESTARTABLE", //no-check-names #endif /* MBEDTLS_ECP_RESTARTABLE */ -#if defined(MBEDTLS_ECDH_LEGACY_CONTEXT) - "MBEDTLS_ECDH_LEGACY_CONTEXT", -#endif /* MBEDTLS_ECDH_LEGACY_CONTEXT */ +#if defined(MBEDTLS_ECP_WITH_MPI_UINT) + "ECP_WITH_MPI_UINT", //no-check-names +#endif /* MBEDTLS_ECP_WITH_MPI_UINT */ #if defined(MBEDTLS_ECDSA_DETERMINISTIC) - "MBEDTLS_ECDSA_DETERMINISTIC", + "ECDSA_DETERMINISTIC", //no-check-names #endif /* MBEDTLS_ECDSA_DETERMINISTIC */ #if defined(MBEDTLS_KEY_EXCHANGE_PSK_ENABLED) - "MBEDTLS_KEY_EXCHANGE_PSK_ENABLED", + "KEY_EXCHANGE_PSK_ENABLED", //no-check-names #endif /* MBEDTLS_KEY_EXCHANGE_PSK_ENABLED */ #if defined(MBEDTLS_KEY_EXCHANGE_DHE_PSK_ENABLED) - "MBEDTLS_KEY_EXCHANGE_DHE_PSK_ENABLED", + "KEY_EXCHANGE_DHE_PSK_ENABLED", //no-check-names #endif /* MBEDTLS_KEY_EXCHANGE_DHE_PSK_ENABLED */ #if defined(MBEDTLS_KEY_EXCHANGE_ECDHE_PSK_ENABLED) - "MBEDTLS_KEY_EXCHANGE_ECDHE_PSK_ENABLED", + "KEY_EXCHANGE_ECDHE_PSK_ENABLED", //no-check-names #endif /* MBEDTLS_KEY_EXCHANGE_ECDHE_PSK_ENABLED */ #if defined(MBEDTLS_KEY_EXCHANGE_RSA_PSK_ENABLED) - "MBEDTLS_KEY_EXCHANGE_RSA_PSK_ENABLED", + "KEY_EXCHANGE_RSA_PSK_ENABLED", //no-check-names #endif /* MBEDTLS_KEY_EXCHANGE_RSA_PSK_ENABLED */ #if defined(MBEDTLS_KEY_EXCHANGE_RSA_ENABLED) - "MBEDTLS_KEY_EXCHANGE_RSA_ENABLED", + "KEY_EXCHANGE_RSA_ENABLED", //no-check-names #endif /* MBEDTLS_KEY_EXCHANGE_RSA_ENABLED */ #if defined(MBEDTLS_KEY_EXCHANGE_DHE_RSA_ENABLED) - "MBEDTLS_KEY_EXCHANGE_DHE_RSA_ENABLED", + "KEY_EXCHANGE_DHE_RSA_ENABLED", //no-check-names #endif /* MBEDTLS_KEY_EXCHANGE_DHE_RSA_ENABLED */ #if defined(MBEDTLS_KEY_EXCHANGE_ECDHE_RSA_ENABLED) - "MBEDTLS_KEY_EXCHANGE_ECDHE_RSA_ENABLED", + "KEY_EXCHANGE_ECDHE_RSA_ENABLED", //no-check-names #endif /* MBEDTLS_KEY_EXCHANGE_ECDHE_RSA_ENABLED */ #if defined(MBEDTLS_KEY_EXCHANGE_ECDHE_ECDSA_ENABLED) - "MBEDTLS_KEY_EXCHANGE_ECDHE_ECDSA_ENABLED", + "KEY_EXCHANGE_ECDHE_ECDSA_ENABLED", //no-check-names #endif /* MBEDTLS_KEY_EXCHANGE_ECDHE_ECDSA_ENABLED */ #if defined(MBEDTLS_KEY_EXCHANGE_ECDH_ECDSA_ENABLED) - "MBEDTLS_KEY_EXCHANGE_ECDH_ECDSA_ENABLED", + "KEY_EXCHANGE_ECDH_ECDSA_ENABLED", //no-check-names #endif /* MBEDTLS_KEY_EXCHANGE_ECDH_ECDSA_ENABLED */ #if defined(MBEDTLS_KEY_EXCHANGE_ECDH_RSA_ENABLED) - "MBEDTLS_KEY_EXCHANGE_ECDH_RSA_ENABLED", + "KEY_EXCHANGE_ECDH_RSA_ENABLED", //no-check-names #endif /* MBEDTLS_KEY_EXCHANGE_ECDH_RSA_ENABLED */ #if defined(MBEDTLS_KEY_EXCHANGE_ECJPAKE_ENABLED) - "MBEDTLS_KEY_EXCHANGE_ECJPAKE_ENABLED", + "KEY_EXCHANGE_ECJPAKE_ENABLED", //no-check-names #endif /* MBEDTLS_KEY_EXCHANGE_ECJPAKE_ENABLED */ #if defined(MBEDTLS_PK_PARSE_EC_EXTENDED) - "MBEDTLS_PK_PARSE_EC_EXTENDED", + "PK_PARSE_EC_EXTENDED", //no-check-names #endif /* MBEDTLS_PK_PARSE_EC_EXTENDED */ +#if defined(MBEDTLS_PK_PARSE_EC_COMPRESSED) + "PK_PARSE_EC_COMPRESSED", //no-check-names +#endif /* MBEDTLS_PK_PARSE_EC_COMPRESSED */ #if defined(MBEDTLS_ERROR_STRERROR_DUMMY) - "MBEDTLS_ERROR_STRERROR_DUMMY", + "ERROR_STRERROR_DUMMY", //no-check-names #endif /* MBEDTLS_ERROR_STRERROR_DUMMY */ #if defined(MBEDTLS_GENPRIME) - "MBEDTLS_GENPRIME", + "GENPRIME", //no-check-names #endif /* MBEDTLS_GENPRIME */ #if defined(MBEDTLS_FS_IO) - "MBEDTLS_FS_IO", + "FS_IO", //no-check-names #endif /* MBEDTLS_FS_IO */ #if defined(MBEDTLS_NO_DEFAULT_ENTROPY_SOURCES) - "MBEDTLS_NO_DEFAULT_ENTROPY_SOURCES", + "NO_DEFAULT_ENTROPY_SOURCES", //no-check-names #endif /* MBEDTLS_NO_DEFAULT_ENTROPY_SOURCES */ #if defined(MBEDTLS_NO_PLATFORM_ENTROPY) - "MBEDTLS_NO_PLATFORM_ENTROPY", + "NO_PLATFORM_ENTROPY", //no-check-names #endif /* MBEDTLS_NO_PLATFORM_ENTROPY */ #if defined(MBEDTLS_ENTROPY_FORCE_SHA256) - "MBEDTLS_ENTROPY_FORCE_SHA256", + "ENTROPY_FORCE_SHA256", //no-check-names #endif /* MBEDTLS_ENTROPY_FORCE_SHA256 */ #if defined(MBEDTLS_ENTROPY_NV_SEED) - "MBEDTLS_ENTROPY_NV_SEED", + "ENTROPY_NV_SEED", //no-check-names #endif /* MBEDTLS_ENTROPY_NV_SEED */ #if defined(MBEDTLS_PSA_CRYPTO_KEY_ID_ENCODES_OWNER) - "MBEDTLS_PSA_CRYPTO_KEY_ID_ENCODES_OWNER", + "PSA_CRYPTO_KEY_ID_ENCODES_OWNER", //no-check-names #endif /* MBEDTLS_PSA_CRYPTO_KEY_ID_ENCODES_OWNER */ #if defined(MBEDTLS_MEMORY_DEBUG) - "MBEDTLS_MEMORY_DEBUG", + "MEMORY_DEBUG", //no-check-names #endif /* MBEDTLS_MEMORY_DEBUG */ #if defined(MBEDTLS_MEMORY_BACKTRACE) - "MBEDTLS_MEMORY_BACKTRACE", + "MEMORY_BACKTRACE", //no-check-names #endif /* MBEDTLS_MEMORY_BACKTRACE */ #if defined(MBEDTLS_PK_RSA_ALT_SUPPORT) - "MBEDTLS_PK_RSA_ALT_SUPPORT", + "PK_RSA_ALT_SUPPORT", //no-check-names #endif /* MBEDTLS_PK_RSA_ALT_SUPPORT */ #if defined(MBEDTLS_PKCS1_V15) - "MBEDTLS_PKCS1_V15", + "PKCS1_V15", //no-check-names #endif /* MBEDTLS_PKCS1_V15 */ #if defined(MBEDTLS_PKCS1_V21) - "MBEDTLS_PKCS1_V21", + "PKCS1_V21", //no-check-names #endif /* MBEDTLS_PKCS1_V21 */ #if defined(MBEDTLS_PSA_CRYPTO_BUILTIN_KEYS) - "MBEDTLS_PSA_CRYPTO_BUILTIN_KEYS", + "PSA_CRYPTO_BUILTIN_KEYS", //no-check-names #endif /* MBEDTLS_PSA_CRYPTO_BUILTIN_KEYS */ #if defined(MBEDTLS_PSA_CRYPTO_CLIENT) - "MBEDTLS_PSA_CRYPTO_CLIENT", + "PSA_CRYPTO_CLIENT", //no-check-names #endif /* MBEDTLS_PSA_CRYPTO_CLIENT */ -#if defined(MBEDTLS_PSA_CRYPTO_DRIVERS) - "MBEDTLS_PSA_CRYPTO_DRIVERS", -#endif /* MBEDTLS_PSA_CRYPTO_DRIVERS */ #if defined(MBEDTLS_PSA_CRYPTO_EXTERNAL_RNG) - "MBEDTLS_PSA_CRYPTO_EXTERNAL_RNG", + "PSA_CRYPTO_EXTERNAL_RNG", //no-check-names #endif /* MBEDTLS_PSA_CRYPTO_EXTERNAL_RNG */ #if defined(MBEDTLS_PSA_CRYPTO_SPM) - "MBEDTLS_PSA_CRYPTO_SPM", + "PSA_CRYPTO_SPM", //no-check-names #endif /* MBEDTLS_PSA_CRYPTO_SPM */ +#if defined(MBEDTLS_PSA_P256M_DRIVER_ENABLED) + "PSA_P256M_DRIVER_ENABLED", //no-check-names +#endif /* MBEDTLS_PSA_P256M_DRIVER_ENABLED */ #if defined(MBEDTLS_PSA_INJECT_ENTROPY) - "MBEDTLS_PSA_INJECT_ENTROPY", + "PSA_INJECT_ENTROPY", //no-check-names #endif /* MBEDTLS_PSA_INJECT_ENTROPY */ +#if defined(MBEDTLS_PSA_ASSUME_EXCLUSIVE_BUFFERS) + "PSA_ASSUME_EXCLUSIVE_BUFFERS", //no-check-names +#endif /* MBEDTLS_PSA_ASSUME_EXCLUSIVE_BUFFERS */ #if defined(MBEDTLS_RSA_NO_CRT) - "MBEDTLS_RSA_NO_CRT", + "RSA_NO_CRT", //no-check-names #endif /* MBEDTLS_RSA_NO_CRT */ #if defined(MBEDTLS_SELF_TEST) - "MBEDTLS_SELF_TEST", + "SELF_TEST", //no-check-names #endif /* MBEDTLS_SELF_TEST */ #if defined(MBEDTLS_SHA256_SMALLER) - "MBEDTLS_SHA256_SMALLER", + "SHA256_SMALLER", //no-check-names #endif /* MBEDTLS_SHA256_SMALLER */ #if defined(MBEDTLS_SHA512_SMALLER) - "MBEDTLS_SHA512_SMALLER", + "SHA512_SMALLER", //no-check-names #endif /* MBEDTLS_SHA512_SMALLER */ -#if defined(MBEDTLS_SHA512_NO_SHA384) - "MBEDTLS_SHA512_NO_SHA384", -#endif /* MBEDTLS_SHA512_NO_SHA384 */ #if defined(MBEDTLS_SSL_ALL_ALERT_MESSAGES) - "MBEDTLS_SSL_ALL_ALERT_MESSAGES", + "SSL_ALL_ALERT_MESSAGES", //no-check-names #endif /* MBEDTLS_SSL_ALL_ALERT_MESSAGES */ -#if defined(MBEDTLS_SSL_RECORD_CHECKING) - "MBEDTLS_SSL_RECORD_CHECKING", -#endif /* MBEDTLS_SSL_RECORD_CHECKING */ #if defined(MBEDTLS_SSL_DTLS_CONNECTION_ID) - "MBEDTLS_SSL_DTLS_CONNECTION_ID", + "SSL_DTLS_CONNECTION_ID", //no-check-names #endif /* MBEDTLS_SSL_DTLS_CONNECTION_ID */ +#if defined(MBEDTLS_SSL_DTLS_CONNECTION_ID_COMPAT) + "SSL_DTLS_CONNECTION_ID_COMPAT", //no-check-names +#endif /* MBEDTLS_SSL_DTLS_CONNECTION_ID_COMPAT */ #if defined(MBEDTLS_SSL_ASYNC_PRIVATE) - "MBEDTLS_SSL_ASYNC_PRIVATE", + "SSL_ASYNC_PRIVATE", //no-check-names #endif /* MBEDTLS_SSL_ASYNC_PRIVATE */ #if defined(MBEDTLS_SSL_CONTEXT_SERIALIZATION) - "MBEDTLS_SSL_CONTEXT_SERIALIZATION", + "SSL_CONTEXT_SERIALIZATION", //no-check-names #endif /* MBEDTLS_SSL_CONTEXT_SERIALIZATION */ #if defined(MBEDTLS_SSL_DEBUG_ALL) - "MBEDTLS_SSL_DEBUG_ALL", + "SSL_DEBUG_ALL", //no-check-names #endif /* MBEDTLS_SSL_DEBUG_ALL */ #if defined(MBEDTLS_SSL_ENCRYPT_THEN_MAC) - "MBEDTLS_SSL_ENCRYPT_THEN_MAC", + "SSL_ENCRYPT_THEN_MAC", //no-check-names #endif /* MBEDTLS_SSL_ENCRYPT_THEN_MAC */ #if defined(MBEDTLS_SSL_EXTENDED_MASTER_SECRET) - "MBEDTLS_SSL_EXTENDED_MASTER_SECRET", + "SSL_EXTENDED_MASTER_SECRET", //no-check-names #endif /* MBEDTLS_SSL_EXTENDED_MASTER_SECRET */ -#if defined(MBEDTLS_SSL_FALLBACK_SCSV) - "MBEDTLS_SSL_FALLBACK_SCSV", -#endif /* MBEDTLS_SSL_FALLBACK_SCSV */ #if defined(MBEDTLS_SSL_KEEP_PEER_CERTIFICATE) - "MBEDTLS_SSL_KEEP_PEER_CERTIFICATE", + "SSL_KEEP_PEER_CERTIFICATE", //no-check-names #endif /* MBEDTLS_SSL_KEEP_PEER_CERTIFICATE */ -#if defined(MBEDTLS_SSL_HW_RECORD_ACCEL) - "MBEDTLS_SSL_HW_RECORD_ACCEL", -#endif /* MBEDTLS_SSL_HW_RECORD_ACCEL */ -#if defined(MBEDTLS_SSL_CBC_RECORD_SPLITTING) - "MBEDTLS_SSL_CBC_RECORD_SPLITTING", -#endif /* MBEDTLS_SSL_CBC_RECORD_SPLITTING */ #if defined(MBEDTLS_SSL_RENEGOTIATION) - "MBEDTLS_SSL_RENEGOTIATION", + "SSL_RENEGOTIATION", //no-check-names #endif /* MBEDTLS_SSL_RENEGOTIATION */ -#if defined(MBEDTLS_SSL_SRV_SUPPORT_SSLV2_CLIENT_HELLO) - "MBEDTLS_SSL_SRV_SUPPORT_SSLV2_CLIENT_HELLO", -#endif /* MBEDTLS_SSL_SRV_SUPPORT_SSLV2_CLIENT_HELLO */ -#if defined(MBEDTLS_SSL_SRV_RESPECT_CLIENT_PREFERENCE) - "MBEDTLS_SSL_SRV_RESPECT_CLIENT_PREFERENCE", -#endif /* MBEDTLS_SSL_SRV_RESPECT_CLIENT_PREFERENCE */ #if defined(MBEDTLS_SSL_MAX_FRAGMENT_LENGTH) - "MBEDTLS_SSL_MAX_FRAGMENT_LENGTH", + "SSL_MAX_FRAGMENT_LENGTH", //no-check-names #endif /* MBEDTLS_SSL_MAX_FRAGMENT_LENGTH */ -#if defined(MBEDTLS_SSL_PROTO_SSL3) - "MBEDTLS_SSL_PROTO_SSL3", -#endif /* MBEDTLS_SSL_PROTO_SSL3 */ -#if defined(MBEDTLS_SSL_PROTO_TLS1) - "MBEDTLS_SSL_PROTO_TLS1", -#endif /* MBEDTLS_SSL_PROTO_TLS1 */ -#if defined(MBEDTLS_SSL_PROTO_TLS1_1) - "MBEDTLS_SSL_PROTO_TLS1_1", -#endif /* MBEDTLS_SSL_PROTO_TLS1_1 */ +#if defined(MBEDTLS_SSL_RECORD_SIZE_LIMIT) + "SSL_RECORD_SIZE_LIMIT", //no-check-names +#endif /* MBEDTLS_SSL_RECORD_SIZE_LIMIT */ #if defined(MBEDTLS_SSL_PROTO_TLS1_2) - "MBEDTLS_SSL_PROTO_TLS1_2", + "SSL_PROTO_TLS1_2", //no-check-names #endif /* MBEDTLS_SSL_PROTO_TLS1_2 */ -#if defined(MBEDTLS_SSL_PROTO_TLS1_3_EXPERIMENTAL) - "MBEDTLS_SSL_PROTO_TLS1_3_EXPERIMENTAL", -#endif /* MBEDTLS_SSL_PROTO_TLS1_3_EXPERIMENTAL */ +#if defined(MBEDTLS_SSL_PROTO_TLS1_3) + "SSL_PROTO_TLS1_3", //no-check-names +#endif /* MBEDTLS_SSL_PROTO_TLS1_3 */ +#if defined(MBEDTLS_SSL_TLS1_3_COMPATIBILITY_MODE) + "SSL_TLS1_3_COMPATIBILITY_MODE", //no-check-names +#endif /* MBEDTLS_SSL_TLS1_3_COMPATIBILITY_MODE */ +#if defined(MBEDTLS_SSL_TLS1_3_KEY_EXCHANGE_MODE_PSK_ENABLED) + "SSL_TLS1_3_KEY_EXCHANGE_MODE_PSK_ENABLED", //no-check-names +#endif /* MBEDTLS_SSL_TLS1_3_KEY_EXCHANGE_MODE_PSK_ENABLED */ +#if defined(MBEDTLS_SSL_TLS1_3_KEY_EXCHANGE_MODE_EPHEMERAL_ENABLED) + "SSL_TLS1_3_KEY_EXCHANGE_MODE_EPHEMERAL_ENABLED", //no-check-names +#endif /* MBEDTLS_SSL_TLS1_3_KEY_EXCHANGE_MODE_EPHEMERAL_ENABLED */ +#if defined(MBEDTLS_SSL_TLS1_3_KEY_EXCHANGE_MODE_PSK_EPHEMERAL_ENABLED) + "SSL_TLS1_3_KEY_EXCHANGE_MODE_PSK_EPHEMERAL_ENABLED", //no-check-names +#endif /* MBEDTLS_SSL_TLS1_3_KEY_EXCHANGE_MODE_PSK_EPHEMERAL_ENABLED */ +#if defined(MBEDTLS_SSL_EARLY_DATA) + "SSL_EARLY_DATA", //no-check-names +#endif /* MBEDTLS_SSL_EARLY_DATA */ #if defined(MBEDTLS_SSL_PROTO_DTLS) - "MBEDTLS_SSL_PROTO_DTLS", + "SSL_PROTO_DTLS", //no-check-names #endif /* MBEDTLS_SSL_PROTO_DTLS */ #if defined(MBEDTLS_SSL_ALPN) - "MBEDTLS_SSL_ALPN", + "SSL_ALPN", //no-check-names #endif /* MBEDTLS_SSL_ALPN */ #if defined(MBEDTLS_SSL_DTLS_ANTI_REPLAY) - "MBEDTLS_SSL_DTLS_ANTI_REPLAY", + "SSL_DTLS_ANTI_REPLAY", //no-check-names #endif /* MBEDTLS_SSL_DTLS_ANTI_REPLAY */ #if defined(MBEDTLS_SSL_DTLS_HELLO_VERIFY) - "MBEDTLS_SSL_DTLS_HELLO_VERIFY", + "SSL_DTLS_HELLO_VERIFY", //no-check-names #endif /* MBEDTLS_SSL_DTLS_HELLO_VERIFY */ #if defined(MBEDTLS_SSL_DTLS_SRTP) - "MBEDTLS_SSL_DTLS_SRTP", + "SSL_DTLS_SRTP", //no-check-names #endif /* MBEDTLS_SSL_DTLS_SRTP */ #if defined(MBEDTLS_SSL_DTLS_CLIENT_PORT_REUSE) - "MBEDTLS_SSL_DTLS_CLIENT_PORT_REUSE", + "SSL_DTLS_CLIENT_PORT_REUSE", //no-check-names #endif /* MBEDTLS_SSL_DTLS_CLIENT_PORT_REUSE */ -#if defined(MBEDTLS_SSL_DTLS_BADMAC_LIMIT) - "MBEDTLS_SSL_DTLS_BADMAC_LIMIT", -#endif /* MBEDTLS_SSL_DTLS_BADMAC_LIMIT */ #if defined(MBEDTLS_SSL_SESSION_TICKETS) - "MBEDTLS_SSL_SESSION_TICKETS", + "SSL_SESSION_TICKETS", //no-check-names #endif /* MBEDTLS_SSL_SESSION_TICKETS */ -#if defined(MBEDTLS_SSL_EXPORT_KEYS) - "MBEDTLS_SSL_EXPORT_KEYS", -#endif /* MBEDTLS_SSL_EXPORT_KEYS */ #if defined(MBEDTLS_SSL_SERVER_NAME_INDICATION) - "MBEDTLS_SSL_SERVER_NAME_INDICATION", + "SSL_SERVER_NAME_INDICATION", //no-check-names #endif /* MBEDTLS_SSL_SERVER_NAME_INDICATION */ -#if defined(MBEDTLS_SSL_TRUNCATED_HMAC) - "MBEDTLS_SSL_TRUNCATED_HMAC", -#endif /* MBEDTLS_SSL_TRUNCATED_HMAC */ -#if defined(MBEDTLS_SSL_TRUNCATED_HMAC_COMPAT) - "MBEDTLS_SSL_TRUNCATED_HMAC_COMPAT", -#endif /* MBEDTLS_SSL_TRUNCATED_HMAC_COMPAT */ #if defined(MBEDTLS_SSL_VARIABLE_BUFFER_LENGTH) - "MBEDTLS_SSL_VARIABLE_BUFFER_LENGTH", + "SSL_VARIABLE_BUFFER_LENGTH", //no-check-names #endif /* MBEDTLS_SSL_VARIABLE_BUFFER_LENGTH */ -#if defined(MBEDTLS_TLS_DEFAULT_ALLOW_SHA1_IN_KEY_EXCHANGE) - "MBEDTLS_TLS_DEFAULT_ALLOW_SHA1_IN_KEY_EXCHANGE", -#endif /* MBEDTLS_TLS_DEFAULT_ALLOW_SHA1_IN_KEY_EXCHANGE */ #if defined(MBEDTLS_TEST_CONSTANT_FLOW_MEMSAN) - "MBEDTLS_TEST_CONSTANT_FLOW_MEMSAN", + "TEST_CONSTANT_FLOW_MEMSAN", //no-check-names #endif /* MBEDTLS_TEST_CONSTANT_FLOW_MEMSAN */ #if defined(MBEDTLS_TEST_CONSTANT_FLOW_VALGRIND) - "MBEDTLS_TEST_CONSTANT_FLOW_VALGRIND", + "TEST_CONSTANT_FLOW_VALGRIND", //no-check-names #endif /* MBEDTLS_TEST_CONSTANT_FLOW_VALGRIND */ #if defined(MBEDTLS_TEST_HOOKS) - "MBEDTLS_TEST_HOOKS", + "TEST_HOOKS", //no-check-names #endif /* MBEDTLS_TEST_HOOKS */ #if defined(MBEDTLS_THREADING_ALT) - "MBEDTLS_THREADING_ALT", + "THREADING_ALT", //no-check-names #endif /* MBEDTLS_THREADING_ALT */ #if defined(MBEDTLS_THREADING_PTHREAD) - "MBEDTLS_THREADING_PTHREAD", + "THREADING_PTHREAD", //no-check-names #endif /* MBEDTLS_THREADING_PTHREAD */ #if defined(MBEDTLS_USE_PSA_CRYPTO) - "MBEDTLS_USE_PSA_CRYPTO", + "USE_PSA_CRYPTO", //no-check-names #endif /* MBEDTLS_USE_PSA_CRYPTO */ #if defined(MBEDTLS_PSA_CRYPTO_CONFIG) - "MBEDTLS_PSA_CRYPTO_CONFIG", + "PSA_CRYPTO_CONFIG", //no-check-names #endif /* MBEDTLS_PSA_CRYPTO_CONFIG */ #if defined(MBEDTLS_VERSION_FEATURES) - "MBEDTLS_VERSION_FEATURES", + "VERSION_FEATURES", //no-check-names #endif /* MBEDTLS_VERSION_FEATURES */ -#if defined(MBEDTLS_X509_ALLOW_EXTENSIONS_NON_V3) - "MBEDTLS_X509_ALLOW_EXTENSIONS_NON_V3", -#endif /* MBEDTLS_X509_ALLOW_EXTENSIONS_NON_V3 */ -#if defined(MBEDTLS_X509_ALLOW_UNSUPPORTED_CRITICAL_EXTENSION) - "MBEDTLS_X509_ALLOW_UNSUPPORTED_CRITICAL_EXTENSION", -#endif /* MBEDTLS_X509_ALLOW_UNSUPPORTED_CRITICAL_EXTENSION */ #if defined(MBEDTLS_X509_TRUSTED_CERTIFICATE_CALLBACK) - "MBEDTLS_X509_TRUSTED_CERTIFICATE_CALLBACK", + "X509_TRUSTED_CERTIFICATE_CALLBACK", //no-check-names #endif /* MBEDTLS_X509_TRUSTED_CERTIFICATE_CALLBACK */ -#if defined(MBEDTLS_X509_CHECK_KEY_USAGE) - "MBEDTLS_X509_CHECK_KEY_USAGE", -#endif /* MBEDTLS_X509_CHECK_KEY_USAGE */ -#if defined(MBEDTLS_X509_CHECK_EXTENDED_KEY_USAGE) - "MBEDTLS_X509_CHECK_EXTENDED_KEY_USAGE", -#endif /* MBEDTLS_X509_CHECK_EXTENDED_KEY_USAGE */ +#if defined(MBEDTLS_X509_REMOVE_INFO) + "X509_REMOVE_INFO", //no-check-names +#endif /* MBEDTLS_X509_REMOVE_INFO */ #if defined(MBEDTLS_X509_RSASSA_PSS_SUPPORT) - "MBEDTLS_X509_RSASSA_PSS_SUPPORT", + "X509_RSASSA_PSS_SUPPORT", //no-check-names #endif /* MBEDTLS_X509_RSASSA_PSS_SUPPORT */ -#if defined(MBEDTLS_ZLIB_SUPPORT) - "MBEDTLS_ZLIB_SUPPORT", -#endif /* MBEDTLS_ZLIB_SUPPORT */ #if defined(MBEDTLS_AESNI_C) - "MBEDTLS_AESNI_C", + "AESNI_C", //no-check-names #endif /* MBEDTLS_AESNI_C */ +#if defined(MBEDTLS_AESCE_C) + "AESCE_C", //no-check-names +#endif /* MBEDTLS_AESCE_C */ #if defined(MBEDTLS_AES_C) - "MBEDTLS_AES_C", + "AES_C", //no-check-names #endif /* MBEDTLS_AES_C */ -#if defined(MBEDTLS_ARC4_C) - "MBEDTLS_ARC4_C", -#endif /* MBEDTLS_ARC4_C */ #if defined(MBEDTLS_ASN1_PARSE_C) - "MBEDTLS_ASN1_PARSE_C", + "ASN1_PARSE_C", //no-check-names #endif /* MBEDTLS_ASN1_PARSE_C */ #if defined(MBEDTLS_ASN1_WRITE_C) - "MBEDTLS_ASN1_WRITE_C", + "ASN1_WRITE_C", //no-check-names #endif /* MBEDTLS_ASN1_WRITE_C */ #if defined(MBEDTLS_BASE64_C) - "MBEDTLS_BASE64_C", + "BASE64_C", //no-check-names #endif /* MBEDTLS_BASE64_C */ +#if defined(MBEDTLS_BLOCK_CIPHER_NO_DECRYPT) + "BLOCK_CIPHER_NO_DECRYPT", //no-check-names +#endif /* MBEDTLS_BLOCK_CIPHER_NO_DECRYPT */ #if defined(MBEDTLS_BIGNUM_C) - "MBEDTLS_BIGNUM_C", + "BIGNUM_C", //no-check-names #endif /* MBEDTLS_BIGNUM_C */ -#if defined(MBEDTLS_BLOWFISH_C) - "MBEDTLS_BLOWFISH_C", -#endif /* MBEDTLS_BLOWFISH_C */ #if defined(MBEDTLS_CAMELLIA_C) - "MBEDTLS_CAMELLIA_C", + "CAMELLIA_C", //no-check-names #endif /* MBEDTLS_CAMELLIA_C */ #if defined(MBEDTLS_ARIA_C) - "MBEDTLS_ARIA_C", + "ARIA_C", //no-check-names #endif /* MBEDTLS_ARIA_C */ #if defined(MBEDTLS_CCM_C) - "MBEDTLS_CCM_C", + "CCM_C", //no-check-names #endif /* MBEDTLS_CCM_C */ -#if defined(MBEDTLS_CERTS_C) - "MBEDTLS_CERTS_C", -#endif /* MBEDTLS_CERTS_C */ #if defined(MBEDTLS_CHACHA20_C) - "MBEDTLS_CHACHA20_C", + "CHACHA20_C", //no-check-names #endif /* MBEDTLS_CHACHA20_C */ #if defined(MBEDTLS_CHACHAPOLY_C) - "MBEDTLS_CHACHAPOLY_C", + "CHACHAPOLY_C", //no-check-names #endif /* MBEDTLS_CHACHAPOLY_C */ #if defined(MBEDTLS_CIPHER_C) - "MBEDTLS_CIPHER_C", + "CIPHER_C", //no-check-names #endif /* MBEDTLS_CIPHER_C */ #if defined(MBEDTLS_CMAC_C) - "MBEDTLS_CMAC_C", + "CMAC_C", //no-check-names #endif /* MBEDTLS_CMAC_C */ #if defined(MBEDTLS_CTR_DRBG_C) - "MBEDTLS_CTR_DRBG_C", + "CTR_DRBG_C", //no-check-names #endif /* MBEDTLS_CTR_DRBG_C */ #if defined(MBEDTLS_DEBUG_C) - "MBEDTLS_DEBUG_C", + "DEBUG_C", //no-check-names #endif /* MBEDTLS_DEBUG_C */ #if defined(MBEDTLS_DES_C) - "MBEDTLS_DES_C", + "DES_C", //no-check-names #endif /* MBEDTLS_DES_C */ #if defined(MBEDTLS_DHM_C) - "MBEDTLS_DHM_C", + "DHM_C", //no-check-names #endif /* MBEDTLS_DHM_C */ #if defined(MBEDTLS_ECDH_C) - "MBEDTLS_ECDH_C", + "ECDH_C", //no-check-names #endif /* MBEDTLS_ECDH_C */ #if defined(MBEDTLS_ECDSA_C) - "MBEDTLS_ECDSA_C", + "ECDSA_C", //no-check-names #endif /* MBEDTLS_ECDSA_C */ #if defined(MBEDTLS_ECJPAKE_C) - "MBEDTLS_ECJPAKE_C", + "ECJPAKE_C", //no-check-names #endif /* MBEDTLS_ECJPAKE_C */ #if defined(MBEDTLS_ECP_C) - "MBEDTLS_ECP_C", + "ECP_C", //no-check-names #endif /* MBEDTLS_ECP_C */ #if defined(MBEDTLS_ENTROPY_C) - "MBEDTLS_ENTROPY_C", + "ENTROPY_C", //no-check-names #endif /* MBEDTLS_ENTROPY_C */ #if defined(MBEDTLS_ERROR_C) - "MBEDTLS_ERROR_C", + "ERROR_C", //no-check-names #endif /* MBEDTLS_ERROR_C */ #if defined(MBEDTLS_GCM_C) - "MBEDTLS_GCM_C", + "GCM_C", //no-check-names #endif /* MBEDTLS_GCM_C */ -#if defined(MBEDTLS_HAVEGE_C) - "MBEDTLS_HAVEGE_C", -#endif /* MBEDTLS_HAVEGE_C */ +#if defined(MBEDTLS_GCM_LARGE_TABLE) + "GCM_LARGE_TABLE", //no-check-names +#endif /* MBEDTLS_GCM_LARGE_TABLE */ #if defined(MBEDTLS_HKDF_C) - "MBEDTLS_HKDF_C", + "HKDF_C", //no-check-names #endif /* MBEDTLS_HKDF_C */ #if defined(MBEDTLS_HMAC_DRBG_C) - "MBEDTLS_HMAC_DRBG_C", + "HMAC_DRBG_C", //no-check-names #endif /* MBEDTLS_HMAC_DRBG_C */ +#if defined(MBEDTLS_LMS_C) + "LMS_C", //no-check-names +#endif /* MBEDTLS_LMS_C */ +#if defined(MBEDTLS_LMS_PRIVATE) + "LMS_PRIVATE", //no-check-names +#endif /* MBEDTLS_LMS_PRIVATE */ #if defined(MBEDTLS_NIST_KW_C) - "MBEDTLS_NIST_KW_C", + "NIST_KW_C", //no-check-names #endif /* MBEDTLS_NIST_KW_C */ #if defined(MBEDTLS_MD_C) - "MBEDTLS_MD_C", + "MD_C", //no-check-names #endif /* MBEDTLS_MD_C */ -#if defined(MBEDTLS_MD2_C) - "MBEDTLS_MD2_C", -#endif /* MBEDTLS_MD2_C */ -#if defined(MBEDTLS_MD4_C) - "MBEDTLS_MD4_C", -#endif /* MBEDTLS_MD4_C */ #if defined(MBEDTLS_MD5_C) - "MBEDTLS_MD5_C", + "MD5_C", //no-check-names #endif /* MBEDTLS_MD5_C */ #if defined(MBEDTLS_MEMORY_BUFFER_ALLOC_C) - "MBEDTLS_MEMORY_BUFFER_ALLOC_C", + "MEMORY_BUFFER_ALLOC_C", //no-check-names #endif /* MBEDTLS_MEMORY_BUFFER_ALLOC_C */ #if defined(MBEDTLS_NET_C) - "MBEDTLS_NET_C", + "NET_C", //no-check-names #endif /* MBEDTLS_NET_C */ #if defined(MBEDTLS_OID_C) - "MBEDTLS_OID_C", + "OID_C", //no-check-names #endif /* MBEDTLS_OID_C */ #if defined(MBEDTLS_PADLOCK_C) - "MBEDTLS_PADLOCK_C", + "PADLOCK_C", //no-check-names #endif /* MBEDTLS_PADLOCK_C */ #if defined(MBEDTLS_PEM_PARSE_C) - "MBEDTLS_PEM_PARSE_C", + "PEM_PARSE_C", //no-check-names #endif /* MBEDTLS_PEM_PARSE_C */ #if defined(MBEDTLS_PEM_WRITE_C) - "MBEDTLS_PEM_WRITE_C", + "PEM_WRITE_C", //no-check-names #endif /* MBEDTLS_PEM_WRITE_C */ #if defined(MBEDTLS_PK_C) - "MBEDTLS_PK_C", + "PK_C", //no-check-names #endif /* MBEDTLS_PK_C */ #if defined(MBEDTLS_PK_PARSE_C) - "MBEDTLS_PK_PARSE_C", + "PK_PARSE_C", //no-check-names #endif /* MBEDTLS_PK_PARSE_C */ #if defined(MBEDTLS_PK_WRITE_C) - "MBEDTLS_PK_WRITE_C", + "PK_WRITE_C", //no-check-names #endif /* MBEDTLS_PK_WRITE_C */ #if defined(MBEDTLS_PKCS5_C) - "MBEDTLS_PKCS5_C", + "PKCS5_C", //no-check-names #endif /* MBEDTLS_PKCS5_C */ -#if defined(MBEDTLS_PKCS11_C) - "MBEDTLS_PKCS11_C", -#endif /* MBEDTLS_PKCS11_C */ +#if defined(MBEDTLS_PKCS7_C) + "PKCS7_C", //no-check-names +#endif /* MBEDTLS_PKCS7_C */ #if defined(MBEDTLS_PKCS12_C) - "MBEDTLS_PKCS12_C", + "PKCS12_C", //no-check-names #endif /* MBEDTLS_PKCS12_C */ #if defined(MBEDTLS_PLATFORM_C) - "MBEDTLS_PLATFORM_C", + "PLATFORM_C", //no-check-names #endif /* MBEDTLS_PLATFORM_C */ #if defined(MBEDTLS_POLY1305_C) - "MBEDTLS_POLY1305_C", + "POLY1305_C", //no-check-names #endif /* MBEDTLS_POLY1305_C */ #if defined(MBEDTLS_PSA_CRYPTO_C) - "MBEDTLS_PSA_CRYPTO_C", + "PSA_CRYPTO_C", //no-check-names #endif /* MBEDTLS_PSA_CRYPTO_C */ #if defined(MBEDTLS_PSA_CRYPTO_SE_C) - "MBEDTLS_PSA_CRYPTO_SE_C", + "PSA_CRYPTO_SE_C", //no-check-names #endif /* MBEDTLS_PSA_CRYPTO_SE_C */ #if defined(MBEDTLS_PSA_CRYPTO_STORAGE_C) - "MBEDTLS_PSA_CRYPTO_STORAGE_C", + "PSA_CRYPTO_STORAGE_C", //no-check-names #endif /* MBEDTLS_PSA_CRYPTO_STORAGE_C */ #if defined(MBEDTLS_PSA_ITS_FILE_C) - "MBEDTLS_PSA_ITS_FILE_C", + "PSA_ITS_FILE_C", //no-check-names #endif /* MBEDTLS_PSA_ITS_FILE_C */ #if defined(MBEDTLS_RIPEMD160_C) - "MBEDTLS_RIPEMD160_C", + "RIPEMD160_C", //no-check-names #endif /* MBEDTLS_RIPEMD160_C */ #if defined(MBEDTLS_RSA_C) - "MBEDTLS_RSA_C", + "RSA_C", //no-check-names #endif /* MBEDTLS_RSA_C */ #if defined(MBEDTLS_SHA1_C) - "MBEDTLS_SHA1_C", + "SHA1_C", //no-check-names #endif /* MBEDTLS_SHA1_C */ +#if defined(MBEDTLS_SHA224_C) + "SHA224_C", //no-check-names +#endif /* MBEDTLS_SHA224_C */ #if defined(MBEDTLS_SHA256_C) - "MBEDTLS_SHA256_C", + "SHA256_C", //no-check-names #endif /* MBEDTLS_SHA256_C */ +#if defined(MBEDTLS_SHA256_USE_ARMV8_A_CRYPTO_IF_PRESENT) + "SHA256_USE_ARMV8_A_CRYPTO_IF_PRESENT", //no-check-names +#endif /* MBEDTLS_SHA256_USE_ARMV8_A_CRYPTO_IF_PRESENT */ +#if defined(MBEDTLS_SHA256_USE_A64_CRYPTO_IF_PRESENT) + "SHA256_USE_A64_CRYPTO_IF_PRESENT", //no-check-names +#endif /* MBEDTLS_SHA256_USE_A64_CRYPTO_IF_PRESENT */ +#if defined(MBEDTLS_SHA256_USE_ARMV8_A_CRYPTO_ONLY) + "SHA256_USE_ARMV8_A_CRYPTO_ONLY", //no-check-names +#endif /* MBEDTLS_SHA256_USE_ARMV8_A_CRYPTO_ONLY */ +#if defined(MBEDTLS_SHA256_USE_A64_CRYPTO_ONLY) + "SHA256_USE_A64_CRYPTO_ONLY", //no-check-names +#endif /* MBEDTLS_SHA256_USE_A64_CRYPTO_ONLY */ +#if defined(MBEDTLS_SHA384_C) + "SHA384_C", //no-check-names +#endif /* MBEDTLS_SHA384_C */ #if defined(MBEDTLS_SHA512_C) - "MBEDTLS_SHA512_C", + "SHA512_C", //no-check-names #endif /* MBEDTLS_SHA512_C */ +#if defined(MBEDTLS_SHA3_C) + "SHA3_C", //no-check-names +#endif /* MBEDTLS_SHA3_C */ +#if defined(MBEDTLS_SHA512_USE_A64_CRYPTO_IF_PRESENT) + "SHA512_USE_A64_CRYPTO_IF_PRESENT", //no-check-names +#endif /* MBEDTLS_SHA512_USE_A64_CRYPTO_IF_PRESENT */ +#if defined(MBEDTLS_SHA512_USE_A64_CRYPTO_ONLY) + "SHA512_USE_A64_CRYPTO_ONLY", //no-check-names +#endif /* MBEDTLS_SHA512_USE_A64_CRYPTO_ONLY */ #if defined(MBEDTLS_SSL_CACHE_C) - "MBEDTLS_SSL_CACHE_C", + "SSL_CACHE_C", //no-check-names #endif /* MBEDTLS_SSL_CACHE_C */ #if defined(MBEDTLS_SSL_COOKIE_C) - "MBEDTLS_SSL_COOKIE_C", + "SSL_COOKIE_C", //no-check-names #endif /* MBEDTLS_SSL_COOKIE_C */ #if defined(MBEDTLS_SSL_TICKET_C) - "MBEDTLS_SSL_TICKET_C", + "SSL_TICKET_C", //no-check-names #endif /* MBEDTLS_SSL_TICKET_C */ #if defined(MBEDTLS_SSL_CLI_C) - "MBEDTLS_SSL_CLI_C", + "SSL_CLI_C", //no-check-names #endif /* MBEDTLS_SSL_CLI_C */ #if defined(MBEDTLS_SSL_SRV_C) - "MBEDTLS_SSL_SRV_C", + "SSL_SRV_C", //no-check-names #endif /* MBEDTLS_SSL_SRV_C */ #if defined(MBEDTLS_SSL_TLS_C) - "MBEDTLS_SSL_TLS_C", + "SSL_TLS_C", //no-check-names #endif /* MBEDTLS_SSL_TLS_C */ #if defined(MBEDTLS_THREADING_C) - "MBEDTLS_THREADING_C", + "THREADING_C", //no-check-names #endif /* MBEDTLS_THREADING_C */ #if defined(MBEDTLS_TIMING_C) - "MBEDTLS_TIMING_C", + "TIMING_C", //no-check-names #endif /* MBEDTLS_TIMING_C */ #if defined(MBEDTLS_VERSION_C) - "MBEDTLS_VERSION_C", + "VERSION_C", //no-check-names #endif /* MBEDTLS_VERSION_C */ #if defined(MBEDTLS_X509_USE_C) - "MBEDTLS_X509_USE_C", + "X509_USE_C", //no-check-names #endif /* MBEDTLS_X509_USE_C */ #if defined(MBEDTLS_X509_CRT_PARSE_C) - "MBEDTLS_X509_CRT_PARSE_C", + "X509_CRT_PARSE_C", //no-check-names #endif /* MBEDTLS_X509_CRT_PARSE_C */ #if defined(MBEDTLS_X509_CRL_PARSE_C) - "MBEDTLS_X509_CRL_PARSE_C", + "X509_CRL_PARSE_C", //no-check-names #endif /* MBEDTLS_X509_CRL_PARSE_C */ #if defined(MBEDTLS_X509_CSR_PARSE_C) - "MBEDTLS_X509_CSR_PARSE_C", + "X509_CSR_PARSE_C", //no-check-names #endif /* MBEDTLS_X509_CSR_PARSE_C */ #if defined(MBEDTLS_X509_CREATE_C) - "MBEDTLS_X509_CREATE_C", + "X509_CREATE_C", //no-check-names #endif /* MBEDTLS_X509_CREATE_C */ #if defined(MBEDTLS_X509_CRT_WRITE_C) - "MBEDTLS_X509_CRT_WRITE_C", + "X509_CRT_WRITE_C", //no-check-names #endif /* MBEDTLS_X509_CRT_WRITE_C */ #if defined(MBEDTLS_X509_CSR_WRITE_C) - "MBEDTLS_X509_CSR_WRITE_C", + "X509_CSR_WRITE_C", //no-check-names #endif /* MBEDTLS_X509_CSR_WRITE_C */ -#if defined(MBEDTLS_XTEA_C) - "MBEDTLS_XTEA_C", -#endif /* MBEDTLS_XTEA_C */ #endif /* MBEDTLS_VERSION_FEATURES */ NULL }; @@ -874,6 +823,12 @@ int mbedtls_version_check_feature(const char *feature) return -1; } + if (strncmp(feature, "MBEDTLS_", 8)) { + return -1; + } + + feature += 8; + while (*idx != NULL) { if (!strcmp(*idx, feature)) { return 0; diff --git a/vendor/mbedtls/library/x509.c b/vendor/mbedtls/library/x509.c index d61ef4a279..f97fb44589 100644 --- a/vendor/mbedtls/library/x509.c +++ b/vendor/mbedtls/library/x509.c @@ -2,19 +2,7 @@ * X.509 common functions for parsing and verification * * Copyright The Mbed TLS Contributors - * SPDX-License-Identifier: Apache-2.0 - * - * Licensed under the Apache License, Version 2.0 (the "License"); you may - * not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT - * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. + * SPDX-License-Identifier: Apache-2.0 OR GPL-2.0-or-later */ /* * The ITU-T X.509 standard defines a certificate format for PKI. @@ -31,7 +19,7 @@ #if defined(MBEDTLS_X509_USE_C) -#include "mbedtls/x509.h" +#include "x509_internal.h" #include "mbedtls/asn1.h" #include "mbedtls/error.h" #include "mbedtls/oid.h" @@ -43,6 +31,8 @@ #include "mbedtls/pem.h" #endif +#include "mbedtls/asn1write.h" + #include "mbedtls/platform.h" #if defined(MBEDTLS_HAVE_TIME) @@ -131,6 +121,51 @@ int mbedtls_x509_get_alg(unsigned char **p, const unsigned char *end, return 0; } +/* + * Convert md type to string + */ +#if !defined(MBEDTLS_X509_REMOVE_INFO) && defined(MBEDTLS_X509_RSASSA_PSS_SUPPORT) + +static inline const char *md_type_to_string(mbedtls_md_type_t md_alg) +{ + switch (md_alg) { +#if defined(MBEDTLS_MD_CAN_MD5) + case MBEDTLS_MD_MD5: + return "MD5"; +#endif +#if defined(MBEDTLS_MD_CAN_SHA1) + case MBEDTLS_MD_SHA1: + return "SHA1"; +#endif +#if defined(MBEDTLS_MD_CAN_SHA224) + case MBEDTLS_MD_SHA224: + return "SHA224"; +#endif +#if defined(MBEDTLS_MD_CAN_SHA256) + case MBEDTLS_MD_SHA256: + return "SHA256"; +#endif +#if defined(MBEDTLS_MD_CAN_SHA384) + case MBEDTLS_MD_SHA384: + return "SHA384"; +#endif +#if defined(MBEDTLS_MD_CAN_SHA512) + case MBEDTLS_MD_SHA512: + return "SHA512"; +#endif +#if defined(MBEDTLS_MD_CAN_RIPEMD160) + case MBEDTLS_MD_RIPEMD160: + return "RIPEMD160"; +#endif + case MBEDTLS_MD_NONE: + return NULL; + default: + return NULL; + } +} + +#endif /* !defined(MBEDTLS_X509_REMOVE_INFO) && defined(MBEDTLS_X509_RSASSA_PSS_SUPPORT) */ + #if defined(MBEDTLS_X509_RSASSA_PSS_SUPPORT) /* * HashAlgorithm ::= AlgorithmIdentifier @@ -467,7 +502,6 @@ int mbedtls_x509_get_name(unsigned char **p, const unsigned char *end, size_t set_len; const unsigned char *end_set; mbedtls_x509_name *head = cur; - mbedtls_x509_name *prev, *allocated; /* don't use recursion, we'd risk stack overflow if not optimized */ while (1) { @@ -523,132 +557,88 @@ int mbedtls_x509_get_name(unsigned char **p, const unsigned char *end, error: /* Skip the first element as we did not allocate it */ - allocated = head->next; - - while (allocated != NULL) { - prev = allocated; - allocated = allocated->next; - - mbedtls_platform_zeroize(prev, sizeof(*prev)); - mbedtls_free(prev); - } - - mbedtls_platform_zeroize(head, sizeof(*head)); + mbedtls_asn1_free_named_data_list_shallow(head->next); + head->next = NULL; return ret; } -static int x509_parse_int(unsigned char **p, size_t n, int *res) -{ - *res = 0; - - for (; n > 0; --n) { - if ((**p < '0') || (**p > '9')) { - return MBEDTLS_ERR_X509_INVALID_DATE; - } - - *res *= 10; - *res += (*(*p)++ - '0'); - } - - return 0; -} - static int x509_date_is_valid(const mbedtls_x509_time *t) { - int ret = MBEDTLS_ERR_X509_INVALID_DATE; - int month_len; - - CHECK_RANGE(0, 9999, t->year); - CHECK_RANGE(0, 23, t->hour); - CHECK_RANGE(0, 59, t->min); - CHECK_RANGE(0, 59, t->sec); - + unsigned int month_days; + unsigned int year; switch (t->mon) { case 1: case 3: case 5: case 7: case 8: case 10: case 12: - month_len = 31; + month_days = 31; break; case 4: case 6: case 9: case 11: - month_len = 30; + month_days = 30; break; case 2: - if ((!(t->year % 4) && t->year % 100) || - !(t->year % 400)) { - month_len = 29; - } else { - month_len = 28; - } + year = (unsigned int) t->year; + month_days = ((year & 3) || (!(year % 100) + && (year % 400))) + ? 28 : 29; break; default: - return ret; + return MBEDTLS_ERR_X509_INVALID_DATE; + } + + if ((unsigned int) (t->day - 1) >= month_days || /* (1 - days in month) */ + /* (unsigned int) (t->mon - 1) >= 12 || */ /* (1 - 12) checked above */ + (unsigned int) t->year > 9999 || /* (0 - 9999) */ + (unsigned int) t->hour > 23 || /* (0 - 23) */ + (unsigned int) t->min > 59 || /* (0 - 59) */ + (unsigned int) t->sec > 59) { /* (0 - 59) */ + return MBEDTLS_ERR_X509_INVALID_DATE; } - CHECK_RANGE(1, month_len, t->day); return 0; } +static int x509_parse2_int(const unsigned char *p) +{ + uint32_t d1 = p[0] - '0'; + uint32_t d2 = p[1] - '0'; + return (d1 < 10 && d2 < 10) ? (int) (d1 * 10 + d2) : -1; +} + /* * Parse an ASN1_UTC_TIME (yearlen=2) or ASN1_GENERALIZED_TIME (yearlen=4) * field. */ -static int x509_parse_time(unsigned char **p, size_t len, size_t yearlen, - mbedtls_x509_time *tm) +static int x509_parse_time(const unsigned char *p, mbedtls_x509_time *tm, + size_t yearlen) { - int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED; + int x; /* - * Minimum length is 10 or 12 depending on yearlen + * Parse year, month, day, hour, minute, second */ - if (len < yearlen + 8) { + tm->year = x509_parse2_int(p); + if (tm->year < 0) { return MBEDTLS_ERR_X509_INVALID_DATE; } - len -= yearlen + 8; - /* - * Parse year, month, day, hour, minute - */ - CHECK(x509_parse_int(p, yearlen, &tm->year)); - if (2 == yearlen) { - if (tm->year < 50) { - tm->year += 100; + if (4 == yearlen) { + x = tm->year * 100; + p += 2; + tm->year = x509_parse2_int(p); + if (tm->year < 0) { + return MBEDTLS_ERR_X509_INVALID_DATE; } - - tm->year += 1900; - } - - CHECK(x509_parse_int(p, 2, &tm->mon)); - CHECK(x509_parse_int(p, 2, &tm->day)); - CHECK(x509_parse_int(p, 2, &tm->hour)); - CHECK(x509_parse_int(p, 2, &tm->min)); - - /* - * Parse seconds if present - */ - if (len >= 2) { - CHECK(x509_parse_int(p, 2, &tm->sec)); - len -= 2; } else { - return MBEDTLS_ERR_X509_INVALID_DATE; + x = (tm->year < 50) ? 2000 : 1900; } + tm->year += x; - /* - * Parse trailing 'Z' if present - */ - if (1 == len && 'Z' == **p) { - (*p)++; - len--; - } + tm->mon = x509_parse2_int(p + 2); + tm->day = x509_parse2_int(p + 4); + tm->hour = x509_parse2_int(p + 6); + tm->min = x509_parse2_int(p + 8); + tm->sec = x509_parse2_int(p + 10); - /* - * We should have parsed all characters at this point - */ - if (0 != len) { - return MBEDTLS_ERR_X509_INVALID_DATE; - } - - CHECK(x509_date_is_valid(tm)); - - return 0; + return x509_date_is_valid(tm); } /* @@ -686,7 +676,14 @@ int mbedtls_x509_get_time(unsigned char **p, const unsigned char *end, return MBEDTLS_ERROR_ADD(MBEDTLS_ERR_X509_INVALID_DATE, ret); } - return x509_parse_time(p, len, year_len, tm); + /* len is 12 or 14 depending on year_len, plus optional trailing 'Z' */ + if (len != year_len + 10 && + !(len == year_len + 11 && (*p)[(len - 1)] == 'Z')) { + return MBEDTLS_ERR_X509_INVALID_DATE; + } + + (*p) += len; + return x509_parse_time(*p - len, tm, year_len); } int mbedtls_x509_get_sig(unsigned char **p, const unsigned char *end, mbedtls_x509_buf *sig) @@ -803,6 +800,11 @@ int mbedtls_x509_get_ext(unsigned char **p, const unsigned char *end, return 0; } +static char nibble_to_hex_digit(int i) +{ + return (i < 10) ? (i + '0') : (i - 10 + 'A'); +} + /* * Store the name in printable form into buf; no more * than size characters will be written @@ -810,11 +812,16 @@ int mbedtls_x509_get_ext(unsigned char **p, const unsigned char *end, int mbedtls_x509_dn_gets(char *buf, size_t size, const mbedtls_x509_name *dn) { int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED; - size_t i, j, n; + size_t i, j, n, asn1_len_size, asn1_tag_size, asn1_tag_len_buf_start; + /* 6 is enough as our asn1 write functions only write one byte for the tag and at most five bytes for the length*/ + unsigned char asn1_tag_len_buf[6]; + unsigned char *asn1_len_p; unsigned char c, merge = 0; const mbedtls_x509_name *name; const char *short_name = NULL; + char lowbits, highbits; char s[MBEDTLS_X509_MAX_DN_NAME_SIZE], *p; + int print_hexstring; memset(s, 0, sizeof(s)); @@ -833,32 +840,91 @@ int mbedtls_x509_dn_gets(char *buf, size_t size, const mbedtls_x509_name *dn) MBEDTLS_X509_SAFE_SNPRINTF; } - ret = mbedtls_oid_get_attr_short_name(&name->oid, &short_name); + print_hexstring = (name->val.tag != MBEDTLS_ASN1_UTF8_STRING) && + (name->val.tag != MBEDTLS_ASN1_PRINTABLE_STRING) && + (name->val.tag != MBEDTLS_ASN1_IA5_STRING); - if (ret == 0) { + if ((ret = mbedtls_oid_get_attr_short_name(&name->oid, &short_name)) == 0) { ret = mbedtls_snprintf(p, n, "%s=", short_name); } else { - ret = mbedtls_snprintf(p, n, "\?\?="); + if ((ret = mbedtls_oid_get_numeric_string(p, n, &name->oid)) > 0) { + n -= ret; + p += ret; + ret = mbedtls_snprintf(p, n, "="); + print_hexstring = 1; + } else if (ret == MBEDTLS_ERR_OID_BUF_TOO_SMALL) { + return MBEDTLS_ERR_X509_BUFFER_TOO_SMALL; + } else { + ret = mbedtls_snprintf(p, n, "\?\?="); + } } MBEDTLS_X509_SAFE_SNPRINTF; - for (i = 0, j = 0; i < name->val.len; i++, j++) { - if (j >= sizeof(s) - 1) { - return MBEDTLS_ERR_X509_BUFFER_TOO_SMALL; - } + if (print_hexstring) { + s[0] = '#'; - c = name->val.p[i]; - // Special characters requiring escaping, RFC 1779 - if (c && strchr(",=+<>#;\"\\", c)) { + asn1_len_p = asn1_tag_len_buf + sizeof(asn1_tag_len_buf); + if ((ret = mbedtls_asn1_write_len(&asn1_len_p, asn1_tag_len_buf, name->val.len)) < 0) { + return MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED; + } + asn1_len_size = ret; + if ((ret = mbedtls_asn1_write_tag(&asn1_len_p, asn1_tag_len_buf, name->val.tag)) < 0) { + return MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED; + } + asn1_tag_size = ret; + asn1_tag_len_buf_start = sizeof(asn1_tag_len_buf) - asn1_len_size - asn1_tag_size; + for (i = 0, j = 1; i < asn1_len_size + asn1_tag_size; i++) { if (j + 1 >= sizeof(s) - 1) { return MBEDTLS_ERR_X509_BUFFER_TOO_SMALL; } - s[j++] = '\\'; + c = asn1_tag_len_buf[asn1_tag_len_buf_start+i]; + lowbits = (c & 0x0F); + highbits = c >> 4; + s[j++] = nibble_to_hex_digit(highbits); + s[j++] = nibble_to_hex_digit(lowbits); } - if (c < 32 || c >= 127) { - s[j] = '?'; - } else { - s[j] = c; + for (i = 0; i < name->val.len; i++) { + if (j + 1 >= sizeof(s) - 1) { + return MBEDTLS_ERR_X509_BUFFER_TOO_SMALL; + } + c = name->val.p[i]; + lowbits = (c & 0x0F); + highbits = c >> 4; + s[j++] = nibble_to_hex_digit(highbits); + s[j++] = nibble_to_hex_digit(lowbits); + } + } else { + for (i = 0, j = 0; i < name->val.len; i++, j++) { + if (j >= sizeof(s) - 1) { + return MBEDTLS_ERR_X509_BUFFER_TOO_SMALL; + } + + c = name->val.p[i]; + // Special characters requiring escaping, RFC 4514 Section 2.4 + if (c == '\0') { + return MBEDTLS_ERR_X509_INVALID_NAME; + } else { + if (strchr(",=+<>;\"\\", c) || + ((i == 0) && strchr("# ", c)) || + ((i == name->val.len-1) && (c == ' '))) { + if (j + 1 >= sizeof(s) - 1) { + return MBEDTLS_ERR_X509_BUFFER_TOO_SMALL; + } + s[j++] = '\\'; + } + } + if (c < 32 || c >= 127) { + if (j + 3 >= sizeof(s) - 1) { + return MBEDTLS_ERR_X509_BUFFER_TOO_SMALL; + } + s[j++] = '\\'; + lowbits = (c & 0x0F); + highbits = c >> 4; + s[j++] = nibble_to_hex_digit(highbits); + s[j] = nibble_to_hex_digit(lowbits); + } else { + s[j] = c; + } } } s[j] = '\0'; @@ -906,6 +972,7 @@ int mbedtls_x509_serial_gets(char *buf, size_t size, const mbedtls_x509_buf *ser return (int) (size - n); } +#if !defined(MBEDTLS_X509_REMOVE_INFO) /* * Helper for writing signature algorithms */ @@ -929,16 +996,15 @@ int mbedtls_x509_sig_alg_gets(char *buf, size_t size, const mbedtls_x509_buf *si #if defined(MBEDTLS_X509_RSASSA_PSS_SUPPORT) if (pk_alg == MBEDTLS_PK_RSASSA_PSS) { const mbedtls_pk_rsassa_pss_options *pss_opts; - const mbedtls_md_info_t *md_info, *mgf_md_info; pss_opts = (const mbedtls_pk_rsassa_pss_options *) sig_opts; - md_info = mbedtls_md_info_from_type(md_alg); - mgf_md_info = mbedtls_md_info_from_type(pss_opts->mgf1_hash_id); + const char *name = md_type_to_string(md_alg); + const char *mgf_name = md_type_to_string(pss_opts->mgf1_hash_id); ret = mbedtls_snprintf(p, n, " (%s, MGF1-%s, 0x%02X)", - md_info ? mbedtls_md_get_name(md_info) : "???", - mgf_md_info ? mbedtls_md_get_name(mgf_md_info) : "???", + name ? name : "???", + mgf_name ? mgf_name : "???", (unsigned int) pss_opts->expected_salt_len); MBEDTLS_X509_SAFE_SNPRINTF; } @@ -950,6 +1016,7 @@ int mbedtls_x509_sig_alg_gets(char *buf, size_t size, const mbedtls_x509_buf *si return (int) (size - n); } +#endif /* MBEDTLS_X509_REMOVE_INFO */ /* * Helper for writing "RSA key size", "EC key size", etc @@ -966,81 +1033,45 @@ int mbedtls_x509_key_size_helper(char *buf, size_t buf_size, const char *name) return 0; } -#if defined(MBEDTLS_HAVE_TIME_DATE) -/* - * Set the time structure to the current time. - * Return 0 on success, non-zero on failure. - */ -static int x509_get_current_time(mbedtls_x509_time *now) +int mbedtls_x509_time_cmp(const mbedtls_x509_time *t1, + const mbedtls_x509_time *t2) { - struct tm *lt, tm_buf; - mbedtls_time_t tt; - int ret = 0; - - tt = mbedtls_time(NULL); - lt = mbedtls_platform_gmtime_r(&tt, &tm_buf); + int x; - if (lt == NULL) { - ret = -1; - } else { - now->year = lt->tm_year + 1900; - now->mon = lt->tm_mon + 1; - now->day = lt->tm_mday; - now->hour = lt->tm_hour; - now->min = lt->tm_min; - now->sec = lt->tm_sec; + x = (((t1->year << 9) | (t1->mon << 5) | (t1->day)) - + ((t2->year << 9) | (t2->mon << 5) | (t2->day))); + if (x != 0) { + return x; } - return ret; + x = (((t1->hour << 12) | (t1->min << 6) | (t1->sec)) - + ((t2->hour << 12) | (t2->min << 6) | (t2->sec))); + return x; } -/* - * Return 0 if before <= after, 1 otherwise - */ -static int x509_check_time(const mbedtls_x509_time *before, const mbedtls_x509_time *after) +#if defined(MBEDTLS_HAVE_TIME_DATE) +int mbedtls_x509_time_gmtime(mbedtls_time_t tt, mbedtls_x509_time *now) { - if (before->year > after->year) { - return 1; - } + struct tm tm; - if (before->year == after->year && - before->mon > after->mon) { - return 1; - } - - if (before->year == after->year && - before->mon == after->mon && - before->day > after->day) { - return 1; - } - - if (before->year == after->year && - before->mon == after->mon && - before->day == after->day && - before->hour > after->hour) { - return 1; - } - - if (before->year == after->year && - before->mon == after->mon && - before->day == after->day && - before->hour == after->hour && - before->min > after->min) { - return 1; - } - - if (before->year == after->year && - before->mon == after->mon && - before->day == after->day && - before->hour == after->hour && - before->min == after->min && - before->sec > after->sec) { - return 1; + if (mbedtls_platform_gmtime_r(&tt, &tm) == NULL) { + return -1; } + now->year = tm.tm_year + 1900; + now->mon = tm.tm_mon + 1; + now->day = tm.tm_mday; + now->hour = tm.tm_hour; + now->min = tm.tm_min; + now->sec = tm.tm_sec; return 0; } +static int x509_get_current_time(mbedtls_x509_time *now) +{ + return mbedtls_x509_time_gmtime(mbedtls_time(NULL), now); +} + int mbedtls_x509_time_is_past(const mbedtls_x509_time *to) { mbedtls_x509_time now; @@ -1049,7 +1080,7 @@ int mbedtls_x509_time_is_past(const mbedtls_x509_time *to) return 1; } - return x509_check_time(&now, to); + return mbedtls_x509_time_cmp(to, &now) < 0; } int mbedtls_x509_time_is_future(const mbedtls_x509_time *from) @@ -1060,7 +1091,7 @@ int mbedtls_x509_time_is_future(const mbedtls_x509_time *from) return 1; } - return x509_check_time(from, &now); + return mbedtls_x509_time_cmp(from, &now) > 0; } #else /* MBEDTLS_HAVE_TIME_DATE */ @@ -1078,75 +1109,668 @@ int mbedtls_x509_time_is_future(const mbedtls_x509_time *from) } #endif /* MBEDTLS_HAVE_TIME_DATE */ -#if defined(MBEDTLS_SELF_TEST) - -#include "mbedtls/x509_crt.h" -#include "mbedtls/certs.h" - +/* Common functions for parsing CRT and CSR. */ +#if defined(MBEDTLS_X509_CRT_PARSE_C) || defined(MBEDTLS_X509_CSR_PARSE_C) /* - * Checkup routine + * OtherName ::= SEQUENCE { + * type-id OBJECT IDENTIFIER, + * value [0] EXPLICIT ANY DEFINED BY type-id } + * + * HardwareModuleName ::= SEQUENCE { + * hwType OBJECT IDENTIFIER, + * hwSerialNum OCTET STRING } + * + * NOTE: we currently only parse and use otherName of type HwModuleName, + * as defined in RFC 4108. */ -int mbedtls_x509_self_test(int verbose) +static int x509_get_other_name(const mbedtls_x509_buf *subject_alt_name, + mbedtls_x509_san_other_name *other_name) { int ret = 0; -#if defined(MBEDTLS_CERTS_C) && defined(MBEDTLS_SHA256_C) - uint32_t flags; - mbedtls_x509_crt cacert; - mbedtls_x509_crt clicert; + size_t len; + unsigned char *p = subject_alt_name->p; + const unsigned char *end = p + subject_alt_name->len; + mbedtls_x509_buf cur_oid; - if (verbose != 0) { - mbedtls_printf(" X.509 certificate load: "); + if ((subject_alt_name->tag & + (MBEDTLS_ASN1_TAG_CLASS_MASK | MBEDTLS_ASN1_TAG_VALUE_MASK)) != + (MBEDTLS_ASN1_CONTEXT_SPECIFIC | MBEDTLS_X509_SAN_OTHER_NAME)) { + /* + * The given subject alternative name is not of type "othername". + */ + return MBEDTLS_ERR_X509_BAD_INPUT_DATA; } - mbedtls_x509_crt_init(&cacert); - mbedtls_x509_crt_init(&clicert); + if ((ret = mbedtls_asn1_get_tag(&p, end, &len, + MBEDTLS_ASN1_OID)) != 0) { + return MBEDTLS_ERROR_ADD(MBEDTLS_ERR_X509_INVALID_EXTENSIONS, ret); + } - ret = mbedtls_x509_crt_parse(&clicert, (const unsigned char *) mbedtls_test_cli_crt, - mbedtls_test_cli_crt_len); - if (ret != 0) { - if (verbose != 0) { - mbedtls_printf("failed\n"); - } + cur_oid.tag = MBEDTLS_ASN1_OID; + cur_oid.p = p; + cur_oid.len = len; - goto cleanup; + /* + * Only HwModuleName is currently supported. + */ + if (MBEDTLS_OID_CMP(MBEDTLS_OID_ON_HW_MODULE_NAME, &cur_oid) != 0) { + return MBEDTLS_ERR_X509_FEATURE_UNAVAILABLE; } + other_name->type_id = cur_oid; - ret = mbedtls_x509_crt_parse(&cacert, (const unsigned char *) mbedtls_test_ca_crt, - mbedtls_test_ca_crt_len); - if (ret != 0) { - if (verbose != 0) { - mbedtls_printf("failed\n"); + p += len; + if ((ret = mbedtls_asn1_get_tag(&p, end, &len, + MBEDTLS_ASN1_CONSTRUCTED | MBEDTLS_ASN1_CONTEXT_SPECIFIC)) != + 0) { + return MBEDTLS_ERROR_ADD(MBEDTLS_ERR_X509_INVALID_EXTENSIONS, ret); + } + + if (end != p + len) { + return MBEDTLS_ERROR_ADD(MBEDTLS_ERR_X509_INVALID_EXTENSIONS, + MBEDTLS_ERR_ASN1_LENGTH_MISMATCH); + } + + if ((ret = mbedtls_asn1_get_tag(&p, end, &len, + MBEDTLS_ASN1_CONSTRUCTED | MBEDTLS_ASN1_SEQUENCE)) != 0) { + return MBEDTLS_ERROR_ADD(MBEDTLS_ERR_X509_INVALID_EXTENSIONS, ret); + } + + if (end != p + len) { + return MBEDTLS_ERROR_ADD(MBEDTLS_ERR_X509_INVALID_EXTENSIONS, + MBEDTLS_ERR_ASN1_LENGTH_MISMATCH); + } + + if ((ret = mbedtls_asn1_get_tag(&p, end, &len, MBEDTLS_ASN1_OID)) != 0) { + return MBEDTLS_ERROR_ADD(MBEDTLS_ERR_X509_INVALID_EXTENSIONS, ret); + } + + other_name->value.hardware_module_name.oid.tag = MBEDTLS_ASN1_OID; + other_name->value.hardware_module_name.oid.p = p; + other_name->value.hardware_module_name.oid.len = len; + + p += len; + if ((ret = mbedtls_asn1_get_tag(&p, end, &len, + MBEDTLS_ASN1_OCTET_STRING)) != 0) { + return MBEDTLS_ERROR_ADD(MBEDTLS_ERR_X509_INVALID_EXTENSIONS, ret); + } + + other_name->value.hardware_module_name.val.tag = MBEDTLS_ASN1_OCTET_STRING; + other_name->value.hardware_module_name.val.p = p; + other_name->value.hardware_module_name.val.len = len; + p += len; + if (p != end) { + return MBEDTLS_ERROR_ADD(MBEDTLS_ERR_X509_INVALID_EXTENSIONS, + MBEDTLS_ERR_ASN1_LENGTH_MISMATCH); + } + return 0; +} + +/* Check mbedtls_x509_get_subject_alt_name for detailed description. + * + * In some cases while parsing subject alternative names the sequence tag is optional + * (e.g. CertSerialNumber). This function is designed to handle such case. + */ +int mbedtls_x509_get_subject_alt_name_ext(unsigned char **p, + const unsigned char *end, + mbedtls_x509_sequence *subject_alt_name) +{ + int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED; + size_t tag_len; + mbedtls_asn1_sequence *cur = subject_alt_name; + + while (*p < end) { + mbedtls_x509_subject_alternative_name tmp_san_name; + mbedtls_x509_buf tmp_san_buf; + memset(&tmp_san_name, 0, sizeof(tmp_san_name)); + + tmp_san_buf.tag = **p; + (*p)++; + + if ((ret = mbedtls_asn1_get_len(p, end, &tag_len)) != 0) { + return MBEDTLS_ERROR_ADD(MBEDTLS_ERR_X509_INVALID_EXTENSIONS, ret); } - goto cleanup; + tmp_san_buf.p = *p; + tmp_san_buf.len = tag_len; + + if ((tmp_san_buf.tag & MBEDTLS_ASN1_TAG_CLASS_MASK) != + MBEDTLS_ASN1_CONTEXT_SPECIFIC) { + return MBEDTLS_ERROR_ADD(MBEDTLS_ERR_X509_INVALID_EXTENSIONS, + MBEDTLS_ERR_ASN1_UNEXPECTED_TAG); + } + + /* + * Check that the SAN is structured correctly by parsing it. + * The SAN structure is discarded afterwards. + */ + ret = mbedtls_x509_parse_subject_alt_name(&tmp_san_buf, &tmp_san_name); + /* + * In case the extension is malformed, return an error, + * and clear the allocated sequences. + */ + if (ret != 0 && ret != MBEDTLS_ERR_X509_FEATURE_UNAVAILABLE) { + mbedtls_asn1_sequence_free(subject_alt_name->next); + subject_alt_name->next = NULL; + return ret; + } + + mbedtls_x509_free_subject_alt_name(&tmp_san_name); + /* Allocate and assign next pointer */ + if (cur->buf.p != NULL) { + if (cur->next != NULL) { + return MBEDTLS_ERR_X509_INVALID_EXTENSIONS; + } + + cur->next = mbedtls_calloc(1, sizeof(mbedtls_asn1_sequence)); + + if (cur->next == NULL) { + return MBEDTLS_ERROR_ADD(MBEDTLS_ERR_X509_INVALID_EXTENSIONS, + MBEDTLS_ERR_ASN1_ALLOC_FAILED); + } + + cur = cur->next; + } + + cur->buf = tmp_san_buf; + *p += tmp_san_buf.len; } - if (verbose != 0) { - mbedtls_printf("passed\n X.509 signature verify: "); + /* Set final sequence entry's next pointer to NULL */ + cur->next = NULL; + + if (*p != end) { + return MBEDTLS_ERROR_ADD(MBEDTLS_ERR_X509_INVALID_EXTENSIONS, + MBEDTLS_ERR_ASN1_LENGTH_MISMATCH); } - ret = mbedtls_x509_crt_verify(&clicert, &cacert, NULL, NULL, &flags, NULL, NULL); - if (ret != 0) { - if (verbose != 0) { - mbedtls_printf("failed\n"); + return 0; +} + +/* + * SubjectAltName ::= GeneralNames + * + * GeneralNames ::= SEQUENCE SIZE (1..MAX) OF GeneralName + * + * GeneralName ::= CHOICE { + * otherName [0] OtherName, + * rfc822Name [1] IA5String, + * dNSName [2] IA5String, + * x400Address [3] ORAddress, + * directoryName [4] Name, + * ediPartyName [5] EDIPartyName, + * uniformResourceIdentifier [6] IA5String, + * iPAddress [7] OCTET STRING, + * registeredID [8] OBJECT IDENTIFIER } + * + * OtherName ::= SEQUENCE { + * type-id OBJECT IDENTIFIER, + * value [0] EXPLICIT ANY DEFINED BY type-id } + * + * EDIPartyName ::= SEQUENCE { + * nameAssigner [0] DirectoryString OPTIONAL, + * partyName [1] DirectoryString } + * + * We list all types, but use the following GeneralName types from RFC 5280: + * "dnsName", "uniformResourceIdentifier" and "hardware_module_name" + * of type "otherName", as defined in RFC 4108. + */ +int mbedtls_x509_get_subject_alt_name(unsigned char **p, + const unsigned char *end, + mbedtls_x509_sequence *subject_alt_name) +{ + int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED; + size_t len; + + /* Get main sequence tag */ + if ((ret = mbedtls_asn1_get_tag(p, end, &len, + MBEDTLS_ASN1_CONSTRUCTED | MBEDTLS_ASN1_SEQUENCE)) != 0) { + return MBEDTLS_ERROR_ADD(MBEDTLS_ERR_X509_INVALID_EXTENSIONS, ret); + } + + if (*p + len != end) { + return MBEDTLS_ERROR_ADD(MBEDTLS_ERR_X509_INVALID_EXTENSIONS, + MBEDTLS_ERR_ASN1_LENGTH_MISMATCH); + } + + return mbedtls_x509_get_subject_alt_name_ext(p, end, subject_alt_name); +} + +int mbedtls_x509_get_ns_cert_type(unsigned char **p, + const unsigned char *end, + unsigned char *ns_cert_type) +{ + int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED; + mbedtls_x509_bitstring bs = { 0, 0, NULL }; + + if ((ret = mbedtls_asn1_get_bitstring(p, end, &bs)) != 0) { + return MBEDTLS_ERROR_ADD(MBEDTLS_ERR_X509_INVALID_EXTENSIONS, ret); + } + + /* A bitstring with no flags set is still technically valid, as it will mean + that the certificate has no designated purpose at the time of creation. */ + if (bs.len == 0) { + *ns_cert_type = 0; + return 0; + } + + if (bs.len != 1) { + return MBEDTLS_ERROR_ADD(MBEDTLS_ERR_X509_INVALID_EXTENSIONS, + MBEDTLS_ERR_ASN1_INVALID_LENGTH); + } + + /* Get actual bitstring */ + *ns_cert_type = *bs.p; + return 0; +} + +int mbedtls_x509_get_key_usage(unsigned char **p, + const unsigned char *end, + unsigned int *key_usage) +{ + int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED; + size_t i; + mbedtls_x509_bitstring bs = { 0, 0, NULL }; + + if ((ret = mbedtls_asn1_get_bitstring(p, end, &bs)) != 0) { + return MBEDTLS_ERROR_ADD(MBEDTLS_ERR_X509_INVALID_EXTENSIONS, ret); + } + + /* A bitstring with no flags set is still technically valid, as it will mean + that the certificate has no designated purpose at the time of creation. */ + if (bs.len == 0) { + *key_usage = 0; + return 0; + } + + /* Get actual bitstring */ + *key_usage = 0; + for (i = 0; i < bs.len && i < sizeof(unsigned int); i++) { + *key_usage |= (unsigned int) bs.p[i] << (8*i); + } + + return 0; +} + +int mbedtls_x509_parse_subject_alt_name(const mbedtls_x509_buf *san_buf, + mbedtls_x509_subject_alternative_name *san) +{ + int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED; + switch (san_buf->tag & + (MBEDTLS_ASN1_TAG_CLASS_MASK | + MBEDTLS_ASN1_TAG_VALUE_MASK)) { + /* + * otherName + */ + case (MBEDTLS_ASN1_CONTEXT_SPECIFIC | MBEDTLS_X509_SAN_OTHER_NAME): + { + mbedtls_x509_san_other_name other_name; + + ret = x509_get_other_name(san_buf, &other_name); + if (ret != 0) { + return ret; + } + + memset(san, 0, sizeof(mbedtls_x509_subject_alternative_name)); + san->type = MBEDTLS_X509_SAN_OTHER_NAME; + memcpy(&san->san.other_name, + &other_name, sizeof(other_name)); + + } + break; + /* + * uniformResourceIdentifier + */ + case (MBEDTLS_ASN1_CONTEXT_SPECIFIC | MBEDTLS_X509_SAN_UNIFORM_RESOURCE_IDENTIFIER): + { + memset(san, 0, sizeof(mbedtls_x509_subject_alternative_name)); + san->type = MBEDTLS_X509_SAN_UNIFORM_RESOURCE_IDENTIFIER; + + memcpy(&san->san.unstructured_name, + san_buf, sizeof(*san_buf)); + } + break; + /* + * dNSName + */ + case (MBEDTLS_ASN1_CONTEXT_SPECIFIC | MBEDTLS_X509_SAN_DNS_NAME): + { + memset(san, 0, sizeof(mbedtls_x509_subject_alternative_name)); + san->type = MBEDTLS_X509_SAN_DNS_NAME; - goto cleanup; + memcpy(&san->san.unstructured_name, + san_buf, sizeof(*san_buf)); + } + break; + /* + * IP address + */ + case (MBEDTLS_ASN1_CONTEXT_SPECIFIC | MBEDTLS_X509_SAN_IP_ADDRESS): + { + memset(san, 0, sizeof(mbedtls_x509_subject_alternative_name)); + san->type = MBEDTLS_X509_SAN_IP_ADDRESS; + // Only IPv6 (16 bytes) and IPv4 (4 bytes) types are supported + if (san_buf->len == 4 || san_buf->len == 16) { + memcpy(&san->san.unstructured_name, + san_buf, sizeof(*san_buf)); + } else { + return MBEDTLS_ERR_X509_BAD_INPUT_DATA; + } + } + break; + /* + * rfc822Name + */ + case (MBEDTLS_ASN1_CONTEXT_SPECIFIC | MBEDTLS_X509_SAN_RFC822_NAME): + { + memset(san, 0, sizeof(mbedtls_x509_subject_alternative_name)); + san->type = MBEDTLS_X509_SAN_RFC822_NAME; + memcpy(&san->san.unstructured_name, san_buf, sizeof(*san_buf)); + } + break; + /* + * directoryName + */ + case (MBEDTLS_ASN1_CONTEXT_SPECIFIC | MBEDTLS_X509_SAN_DIRECTORY_NAME): + { + size_t name_len; + unsigned char *p = san_buf->p; + memset(san, 0, sizeof(mbedtls_x509_subject_alternative_name)); + san->type = MBEDTLS_X509_SAN_DIRECTORY_NAME; + + ret = mbedtls_asn1_get_tag(&p, p + san_buf->len, &name_len, + MBEDTLS_ASN1_CONSTRUCTED | MBEDTLS_ASN1_SEQUENCE); + + if (ret != 0) { + return ret; + } + + if ((ret = mbedtls_x509_get_name(&p, p + name_len, + &san->san.directory_name)) != 0) { + return ret; + } + } + break; + /* + * Type not supported + */ + default: + return MBEDTLS_ERR_X509_FEATURE_UNAVAILABLE; } + return 0; +} - if (verbose != 0) { - mbedtls_printf("passed\n\n"); +void mbedtls_x509_free_subject_alt_name(mbedtls_x509_subject_alternative_name *san) +{ + if (san->type == MBEDTLS_X509_SAN_DIRECTORY_NAME) { + mbedtls_asn1_free_named_data_list_shallow(san->san.directory_name.next); } +} -cleanup: - mbedtls_x509_crt_free(&cacert); - mbedtls_x509_crt_free(&clicert); -#else - ((void) verbose); -#endif /* MBEDTLS_CERTS_C && MBEDTLS_SHA256_C */ - return ret; +#if !defined(MBEDTLS_X509_REMOVE_INFO) +int mbedtls_x509_info_subject_alt_name(char **buf, size_t *size, + const mbedtls_x509_sequence + *subject_alt_name, + const char *prefix) +{ + int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED; + size_t i; + size_t n = *size; + char *p = *buf; + const mbedtls_x509_sequence *cur = subject_alt_name; + mbedtls_x509_subject_alternative_name san; + int parse_ret; + + while (cur != NULL) { + memset(&san, 0, sizeof(san)); + parse_ret = mbedtls_x509_parse_subject_alt_name(&cur->buf, &san); + if (parse_ret != 0) { + if (parse_ret == MBEDTLS_ERR_X509_FEATURE_UNAVAILABLE) { + ret = mbedtls_snprintf(p, n, "\n%s ", prefix); + MBEDTLS_X509_SAFE_SNPRINTF; + } else { + ret = mbedtls_snprintf(p, n, "\n%s ", prefix); + MBEDTLS_X509_SAFE_SNPRINTF; + } + cur = cur->next; + continue; + } + + switch (san.type) { + /* + * otherName + */ + case MBEDTLS_X509_SAN_OTHER_NAME: + { + mbedtls_x509_san_other_name *other_name = &san.san.other_name; + + ret = mbedtls_snprintf(p, n, "\n%s otherName :", prefix); + MBEDTLS_X509_SAFE_SNPRINTF; + + if (MBEDTLS_OID_CMP(MBEDTLS_OID_ON_HW_MODULE_NAME, + &other_name->type_id) == 0) { + ret = mbedtls_snprintf(p, n, "\n%s hardware module name :", prefix); + MBEDTLS_X509_SAFE_SNPRINTF; + ret = + mbedtls_snprintf(p, n, "\n%s hardware type : ", prefix); + MBEDTLS_X509_SAFE_SNPRINTF; + + ret = mbedtls_oid_get_numeric_string(p, + n, + &other_name->value.hardware_module_name.oid); + MBEDTLS_X509_SAFE_SNPRINTF; + + ret = + mbedtls_snprintf(p, n, "\n%s hardware serial number : ", prefix); + MBEDTLS_X509_SAFE_SNPRINTF; + + for (i = 0; i < other_name->value.hardware_module_name.val.len; i++) { + ret = mbedtls_snprintf(p, + n, + "%02X", + other_name->value.hardware_module_name.val.p[i]); + MBEDTLS_X509_SAFE_SNPRINTF; + } + }/* MBEDTLS_OID_ON_HW_MODULE_NAME */ + } + break; + /* + * uniformResourceIdentifier + */ + case MBEDTLS_X509_SAN_UNIFORM_RESOURCE_IDENTIFIER: + { + ret = mbedtls_snprintf(p, n, "\n%s uniformResourceIdentifier : ", prefix); + MBEDTLS_X509_SAFE_SNPRINTF; + if (san.san.unstructured_name.len >= n) { + if (n > 0) { + *p = '\0'; + } + return MBEDTLS_ERR_X509_BUFFER_TOO_SMALL; + } + + memcpy(p, san.san.unstructured_name.p, san.san.unstructured_name.len); + p += san.san.unstructured_name.len; + n -= san.san.unstructured_name.len; + } + break; + /* + * dNSName + * RFC822 Name + */ + case MBEDTLS_X509_SAN_DNS_NAME: + case MBEDTLS_X509_SAN_RFC822_NAME: + { + const char *dns_name = "dNSName"; + const char *rfc822_name = "rfc822Name"; + + ret = mbedtls_snprintf(p, n, + "\n%s %s : ", + prefix, + san.type == + MBEDTLS_X509_SAN_DNS_NAME ? dns_name : rfc822_name); + MBEDTLS_X509_SAFE_SNPRINTF; + if (san.san.unstructured_name.len >= n) { + if (n > 0) { + *p = '\0'; + } + return MBEDTLS_ERR_X509_BUFFER_TOO_SMALL; + } + + memcpy(p, san.san.unstructured_name.p, san.san.unstructured_name.len); + p += san.san.unstructured_name.len; + n -= san.san.unstructured_name.len; + } + break; + /* + * iPAddress + */ + case MBEDTLS_X509_SAN_IP_ADDRESS: + { + ret = mbedtls_snprintf(p, n, "\n%s %s : ", + prefix, "iPAddress"); + MBEDTLS_X509_SAFE_SNPRINTF; + if (san.san.unstructured_name.len >= n) { + if (n > 0) { + *p = '\0'; + } + return MBEDTLS_ERR_X509_BUFFER_TOO_SMALL; + } + + unsigned char *ip = san.san.unstructured_name.p; + // Only IPv6 (16 bytes) and IPv4 (4 bytes) types are supported + if (san.san.unstructured_name.len == 4) { + ret = mbedtls_snprintf(p, n, "%u.%u.%u.%u", ip[0], ip[1], ip[2], ip[3]); + MBEDTLS_X509_SAFE_SNPRINTF; + } else if (san.san.unstructured_name.len == 16) { + ret = mbedtls_snprintf(p, n, + "%X%X:%X%X:%X%X:%X%X:%X%X:%X%X:%X%X:%X%X", + ip[0], ip[1], ip[2], ip[3], ip[4], ip[5], ip[6], + ip[7], ip[8], ip[9], ip[10], ip[11], ip[12], ip[13], + ip[14], ip[15]); + MBEDTLS_X509_SAFE_SNPRINTF; + } else { + if (n > 0) { + *p = '\0'; + } + return MBEDTLS_ERR_X509_BAD_INPUT_DATA; + } + } + break; + /* + * directoryName + */ + case MBEDTLS_X509_SAN_DIRECTORY_NAME: + { + ret = mbedtls_snprintf(p, n, "\n%s directoryName : ", prefix); + if (ret < 0 || (size_t) ret >= n) { + mbedtls_x509_free_subject_alt_name(&san); + } + + MBEDTLS_X509_SAFE_SNPRINTF; + ret = mbedtls_x509_dn_gets(p, n, &san.san.directory_name); + + if (ret < 0) { + mbedtls_x509_free_subject_alt_name(&san); + if (n > 0) { + *p = '\0'; + } + return ret; + } + + p += ret; + n -= ret; + } + break; + /* + * Type not supported, skip item. + */ + default: + ret = mbedtls_snprintf(p, n, "\n%s ", prefix); + MBEDTLS_X509_SAFE_SNPRINTF; + break; + } + + /* So far memory is freed only in the case of directoryName + * parsing succeeding, as mbedtls_x509_get_name allocates memory. */ + mbedtls_x509_free_subject_alt_name(&san); + cur = cur->next; + } + + *p = '\0'; + + *size = n; + *buf = p; + + return 0; +} + +#define PRINT_ITEM(i) \ + do { \ + ret = mbedtls_snprintf(p, n, "%s" i, sep); \ + MBEDTLS_X509_SAFE_SNPRINTF; \ + sep = ", "; \ + } while (0) + +#define CERT_TYPE(type, name) \ + do { \ + if (ns_cert_type & (type)) { \ + PRINT_ITEM(name); \ + } \ + } while (0) + +int mbedtls_x509_info_cert_type(char **buf, size_t *size, + unsigned char ns_cert_type) +{ + int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED; + size_t n = *size; + char *p = *buf; + const char *sep = ""; + + CERT_TYPE(MBEDTLS_X509_NS_CERT_TYPE_SSL_CLIENT, "SSL Client"); + CERT_TYPE(MBEDTLS_X509_NS_CERT_TYPE_SSL_SERVER, "SSL Server"); + CERT_TYPE(MBEDTLS_X509_NS_CERT_TYPE_EMAIL, "Email"); + CERT_TYPE(MBEDTLS_X509_NS_CERT_TYPE_OBJECT_SIGNING, "Object Signing"); + CERT_TYPE(MBEDTLS_X509_NS_CERT_TYPE_RESERVED, "Reserved"); + CERT_TYPE(MBEDTLS_X509_NS_CERT_TYPE_SSL_CA, "SSL CA"); + CERT_TYPE(MBEDTLS_X509_NS_CERT_TYPE_EMAIL_CA, "Email CA"); + CERT_TYPE(MBEDTLS_X509_NS_CERT_TYPE_OBJECT_SIGNING_CA, "Object Signing CA"); + + *size = n; + *buf = p; + + return 0; } -#endif /* MBEDTLS_SELF_TEST */ +#define KEY_USAGE(code, name) \ + do { \ + if ((key_usage) & (code)) { \ + PRINT_ITEM(name); \ + } \ + } while (0) +int mbedtls_x509_info_key_usage(char **buf, size_t *size, + unsigned int key_usage) +{ + int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED; + size_t n = *size; + char *p = *buf; + const char *sep = ""; + + KEY_USAGE(MBEDTLS_X509_KU_DIGITAL_SIGNATURE, "Digital Signature"); + KEY_USAGE(MBEDTLS_X509_KU_NON_REPUDIATION, "Non Repudiation"); + KEY_USAGE(MBEDTLS_X509_KU_KEY_ENCIPHERMENT, "Key Encipherment"); + KEY_USAGE(MBEDTLS_X509_KU_DATA_ENCIPHERMENT, "Data Encipherment"); + KEY_USAGE(MBEDTLS_X509_KU_KEY_AGREEMENT, "Key Agreement"); + KEY_USAGE(MBEDTLS_X509_KU_KEY_CERT_SIGN, "Key Cert Sign"); + KEY_USAGE(MBEDTLS_X509_KU_CRL_SIGN, "CRL Sign"); + KEY_USAGE(MBEDTLS_X509_KU_ENCIPHER_ONLY, "Encipher Only"); + KEY_USAGE(MBEDTLS_X509_KU_DECIPHER_ONLY, "Decipher Only"); + + *size = n; + *buf = p; + + return 0; +} +#endif /* MBEDTLS_X509_REMOVE_INFO */ +#endif /* MBEDTLS_X509_CRT_PARSE_C || MBEDTLS_X509_CSR_PARSE_C */ #endif /* MBEDTLS_X509_USE_C */ diff --git a/vendor/mbedtls/library/x509_create.c b/vendor/mbedtls/library/x509_create.c index bd772d3ac7..839b5df226 100644 --- a/vendor/mbedtls/library/x509_create.c +++ b/vendor/mbedtls/library/x509_create.c @@ -2,32 +2,24 @@ * X.509 base functions for creating certificates / CSRs * * Copyright The Mbed TLS Contributors - * SPDX-License-Identifier: Apache-2.0 - * - * Licensed under the Apache License, Version 2.0 (the "License"); you may - * not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT - * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. + * SPDX-License-Identifier: Apache-2.0 OR GPL-2.0-or-later */ #include "common.h" #if defined(MBEDTLS_X509_CREATE_C) -#include "mbedtls/x509.h" +#include "x509_internal.h" #include "mbedtls/asn1write.h" #include "mbedtls/error.h" #include "mbedtls/oid.h" #include +#include "mbedtls/platform.h" + +#include "mbedtls/asn1.h" + /* Structure linking OIDs for X.509 DN AttributeTypes to their * string representations and default string encodings used by Mbed TLS. */ typedef struct { @@ -35,7 +27,8 @@ typedef struct { * "CN" or "emailAddress". */ size_t name_len; /* Length of 'name', without trailing 0 byte. */ const char *oid; /* String representation of OID of AttributeType, - * as per RFC 5280, Appendix A.1. */ + * as per RFC 5280, Appendix A.1. encoded as per + * X.690 */ int default_tag; /* The default character encoding used for the * given attribute type, e.g. * MBEDTLS_ASN1_UTF8_STRING for UTF-8. */ @@ -123,79 +116,261 @@ static const x509_attr_descriptor_t *x509_attr_descr_from_name(const char *name, return cur; } +static int hex_to_int(char c) +{ + return ('0' <= c && c <= '9') ? (c - '0') : + ('a' <= c && c <= 'f') ? (c - 'a' + 10) : + ('A' <= c && c <= 'F') ? (c - 'A' + 10) : -1; +} + +static int hexpair_to_int(const char *hexpair) +{ + int n1 = hex_to_int(*hexpair); + int n2 = hex_to_int(*(hexpair + 1)); + + if (n1 != -1 && n2 != -1) { + return (n1 << 4) | n2; + } else { + return -1; + } +} + +static int parse_attribute_value_string(const char *s, + int len, + unsigned char *data, + size_t *data_len) +{ + const char *c; + const char *end = s + len; + unsigned char *d = data; + int n; + + for (c = s; c < end; c++) { + if (*c == '\\') { + c++; + + /* Check for valid escaped characters as per RFC 4514 Section 3 */ + if (c + 1 < end && (n = hexpair_to_int(c)) != -1) { + if (n == 0) { + return MBEDTLS_ERR_X509_INVALID_NAME; + } + *(d++) = n; + c++; + } else if (c < end && strchr(" ,=+<>#;\"\\", *c)) { + *(d++) = *c; + } else { + return MBEDTLS_ERR_X509_INVALID_NAME; + } + } else { + *(d++) = *c; + } + + if (d - data == MBEDTLS_X509_MAX_DN_NAME_SIZE) { + return MBEDTLS_ERR_X509_INVALID_NAME; + } + } + *data_len = (size_t) (d - data); + return 0; +} + +/** Parse a hexstring containing a DER-encoded string. + * + * \param s A string of \p len bytes hexadecimal digits. + * \param len Number of bytes to read from \p s. + * \param data Output buffer of size \p data_size. + * On success, it contains the payload that's DER-encoded + * in the input (content without the tag and length). + * If the DER tag is a string tag, the payload is guaranteed + * not to contain null bytes. + * \param data_size Length of the \p data buffer. + * \param data_len On success, the length of the parsed string. + * It is guaranteed to be less than + * #MBEDTLS_X509_MAX_DN_NAME_SIZE. + * \param tag The ASN.1 tag that the payload in \p data is encoded in. + * + * \retval 0 on success. + * \retval #MBEDTLS_ERR_X509_INVALID_NAME if \p s does not contain + * a valid hexstring, + * or if the decoded hexstring is not valid DER, + * or if the payload does not fit in \p data, + * or if the payload is more than + * #MBEDTLS_X509_MAX_DN_NAME_SIZE bytes, + * of if \p *tag is an ASN.1 string tag and the payload + * contains a null byte. + * \retval #MBEDTLS_ERR_X509_ALLOC_FAILED on low memory. + */ +static int parse_attribute_value_hex_der_encoded(const char *s, + size_t len, + unsigned char *data, + size_t data_size, + size_t *data_len, + int *tag) +{ + /* Step 1: preliminary length checks. */ + /* Each byte is encoded by exactly two hexadecimal digits. */ + if (len % 2 != 0) { + /* Odd number of hex digits */ + return MBEDTLS_ERR_X509_INVALID_NAME; + } + size_t const der_length = len / 2; + if (der_length > MBEDTLS_X509_MAX_DN_NAME_SIZE + 4) { + /* The payload would be more than MBEDTLS_X509_MAX_DN_NAME_SIZE + * (after subtracting the ASN.1 tag and length). Reject this early + * to avoid allocating a large intermediate buffer. */ + return MBEDTLS_ERR_X509_INVALID_NAME; + } + if (der_length < 1) { + /* Avoid empty-buffer shenanigans. A valid DER encoding is never + * empty. */ + return MBEDTLS_ERR_X509_INVALID_NAME; + } + + /* Step 2: Decode the hex string into an intermediate buffer. */ + unsigned char *der = mbedtls_calloc(1, der_length); + if (der == NULL) { + return MBEDTLS_ERR_X509_ALLOC_FAILED; + } + /* Beyond this point, der needs to be freed on exit. */ + for (size_t i = 0; i < der_length; i++) { + int c = hexpair_to_int(s + 2 * i); + if (c < 0) { + goto error; + } + der[i] = c; + } + + /* Step 3: decode the DER. */ + /* We've checked that der_length >= 1 above. */ + *tag = der[0]; + { + unsigned char *p = der + 1; + if (mbedtls_asn1_get_len(&p, der + der_length, data_len) != 0) { + goto error; + } + /* Now p points to the first byte of the payload inside der, + * and *data_len is the length of the payload. */ + + /* Step 4: payload validation */ + if (*data_len > MBEDTLS_X509_MAX_DN_NAME_SIZE) { + goto error; + } + /* Strings must not contain null bytes. */ + if (MBEDTLS_ASN1_IS_STRING_TAG(*tag)) { + for (size_t i = 0; i < *data_len; i++) { + if (p[i] == 0) { + goto error; + } + } + } + + /* Step 5: output the payload. */ + if (*data_len > data_size) { + goto error; + } + memcpy(data, p, *data_len); + } + mbedtls_free(der); + + return 0; + +error: + mbedtls_free(der); + return MBEDTLS_ERR_X509_INVALID_NAME; +} + int mbedtls_x509_string_to_names(mbedtls_asn1_named_data **head, const char *name) { int ret = MBEDTLS_ERR_X509_INVALID_NAME; + int parse_ret = 0; const char *s = name, *c = s; const char *end = s + strlen(s); - const char *oid = NULL; + mbedtls_asn1_buf oid = { .p = NULL, .len = 0, .tag = MBEDTLS_ASN1_NULL }; const x509_attr_descriptor_t *attr_descr = NULL; - int in_tag = 1; - char data[MBEDTLS_X509_MAX_DN_NAME_SIZE]; - char *d = data; + int in_attr_type = 1; + int tag; + int numericoid = 0; + unsigned char data[MBEDTLS_X509_MAX_DN_NAME_SIZE]; + size_t data_len = 0; /* Clear existing chain if present */ mbedtls_asn1_free_named_data_list(head); while (c <= end) { - if (in_tag && *c == '=') { - if ((attr_descr = x509_attr_descr_from_name(s, c - s)) == NULL) { - ret = MBEDTLS_ERR_X509_UNKNOWN_OID; - goto exit; + if (in_attr_type && *c == '=') { + if ((attr_descr = x509_attr_descr_from_name(s, (size_t) (c - s))) == NULL) { + if ((mbedtls_oid_from_numeric_string(&oid, s, (size_t) (c - s))) != 0) { + return MBEDTLS_ERR_X509_INVALID_NAME; + } else { + numericoid = 1; + } + } else { + oid.len = strlen(attr_descr->oid); + oid.p = mbedtls_calloc(1, oid.len); + memcpy(oid.p, attr_descr->oid, oid.len); + numericoid = 0; } - oid = attr_descr->oid; s = c + 1; - in_tag = 0; - d = data; + in_attr_type = 0; } - if (!in_tag && *c == '\\' && c != end) { - c++; - - /* Check for valid escaped characters */ - if (c == end || *c != ',') { - ret = MBEDTLS_ERR_X509_INVALID_NAME; - goto exit; + if (!in_attr_type && ((*c == ',' && *(c-1) != '\\') || c == end)) { + if (s == c) { + mbedtls_free(oid.p); + return MBEDTLS_ERR_X509_INVALID_NAME; + } else if (*s == '#') { + /* We know that c >= s (loop invariant) and c != s (in this + * else branch), hence c - s - 1 >= 0. */ + parse_ret = parse_attribute_value_hex_der_encoded( + s + 1, (size_t) (c - s) - 1, + data, sizeof(data), &data_len, &tag); + if (parse_ret != 0) { + mbedtls_free(oid.p); + return parse_ret; + } + } else { + if (numericoid) { + mbedtls_free(oid.p); + return MBEDTLS_ERR_X509_INVALID_NAME; + } else { + if ((parse_ret = + parse_attribute_value_string(s, (int) (c - s), data, + &data_len)) != 0) { + mbedtls_free(oid.p); + return parse_ret; + } + tag = attr_descr->default_tag; + } } - } else if (!in_tag && (*c == ',' || c == end)) { + mbedtls_asn1_named_data *cur = - mbedtls_asn1_store_named_data(head, oid, strlen(oid), + mbedtls_asn1_store_named_data(head, (char *) oid.p, oid.len, (unsigned char *) data, - d - data); - + data_len); + mbedtls_free(oid.p); + oid.p = NULL; if (cur == NULL) { return MBEDTLS_ERR_X509_ALLOC_FAILED; } // set tagType - cur->val.tag = attr_descr->default_tag; + cur->val.tag = tag; while (c < end && *(c + 1) == ' ') { c++; } s = c + 1; - in_tag = 1; + in_attr_type = 1; /* Successfully parsed one name, update ret to success */ ret = 0; } - - if (!in_tag && s != c + 1) { - *(d++) = *c; - - if (d - data == MBEDTLS_X509_MAX_DN_NAME_SIZE) { - ret = MBEDTLS_ERR_X509_INVALID_NAME; - goto exit; - } - } - c++; } - -exit: - + if (oid.p != NULL) { + mbedtls_free(oid.p); + } return ret; } @@ -207,6 +382,10 @@ int mbedtls_x509_set_extension(mbedtls_asn1_named_data **head, const char *oid, { mbedtls_asn1_named_data *cur; + if (val_len > (SIZE_MAX - 1)) { + return MBEDTLS_ERR_X509_BAD_INPUT_DATA; + } + if ((cur = mbedtls_asn1_store_named_data(head, oid, oid_len, NULL, val_len + 1)) == NULL) { return MBEDTLS_ERR_X509_ALLOC_FAILED; diff --git a/vendor/mbedtls/library/x509_crl.c b/vendor/mbedtls/library/x509_crl.c index d5357ea4e8..7901992e20 100644 --- a/vendor/mbedtls/library/x509_crl.c +++ b/vendor/mbedtls/library/x509_crl.c @@ -2,19 +2,7 @@ * X.509 Certificate Revocation List (CRL) parsing * * Copyright The Mbed TLS Contributors - * SPDX-License-Identifier: Apache-2.0 - * - * Licensed under the Apache License, Version 2.0 (the "License"); you may - * not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT - * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. + * SPDX-License-Identifier: Apache-2.0 OR GPL-2.0-or-later */ /* * The ITU-T X.509 standard defines a certificate format for PKI. @@ -32,6 +20,7 @@ #if defined(MBEDTLS_X509_CRL_PARSE_C) #include "mbedtls/x509_crl.h" +#include "x509_internal.h" #include "mbedtls/error.h" #include "mbedtls/oid.h" #include "mbedtls/platform_util.h" @@ -379,7 +368,7 @@ int mbedtls_x509_crl_parse_der(mbedtls_x509_crl *chain, } end = p + len; - crl->tbs.len = end - crl->tbs.p; + crl->tbs.len = (size_t) (end - crl->tbs.p); /* * Version ::= INTEGER OPTIONAL { v1(0), v2(1) } @@ -423,7 +412,7 @@ int mbedtls_x509_crl_parse_der(mbedtls_x509_crl *chain, return ret; } - crl->issuer_raw.len = p - crl->issuer_raw.p; + crl->issuer_raw.len = (size_t) (p - crl->issuer_raw.p); /* * thisUpdate Time @@ -587,13 +576,13 @@ int mbedtls_x509_crl_parse_file(mbedtls_x509_crl *chain, const char *path) ret = mbedtls_x509_crl_parse(chain, buf, n); - mbedtls_platform_zeroize(buf, n); - mbedtls_free(buf); + mbedtls_zeroize_and_free(buf, n); return ret; } #endif /* MBEDTLS_FS_IO */ +#if !defined(MBEDTLS_X509_REMOVE_INFO) /* * Return an informational string about the certificate. */ @@ -672,6 +661,7 @@ int mbedtls_x509_crl_info(char *buf, size_t size, const char *prefix, return (int) (size - n); } +#endif /* MBEDTLS_X509_REMOVE_INFO */ /* * Initialize a CRL chain @@ -688,47 +678,28 @@ void mbedtls_x509_crl_free(mbedtls_x509_crl *crl) { mbedtls_x509_crl *crl_cur = crl; mbedtls_x509_crl *crl_prv; - mbedtls_x509_name *name_cur; - mbedtls_x509_name *name_prv; mbedtls_x509_crl_entry *entry_cur; mbedtls_x509_crl_entry *entry_prv; - if (crl == NULL) { - return; - } - - do { + while (crl_cur != NULL) { #if defined(MBEDTLS_X509_RSASSA_PSS_SUPPORT) mbedtls_free(crl_cur->sig_opts); #endif - name_cur = crl_cur->issuer.next; - while (name_cur != NULL) { - name_prv = name_cur; - name_cur = name_cur->next; - mbedtls_platform_zeroize(name_prv, sizeof(mbedtls_x509_name)); - mbedtls_free(name_prv); - } + mbedtls_asn1_free_named_data_list_shallow(crl_cur->issuer.next); entry_cur = crl_cur->entry.next; while (entry_cur != NULL) { entry_prv = entry_cur; entry_cur = entry_cur->next; - mbedtls_platform_zeroize(entry_prv, + mbedtls_zeroize_and_free(entry_prv, sizeof(mbedtls_x509_crl_entry)); - mbedtls_free(entry_prv); } if (crl_cur->raw.p != NULL) { - mbedtls_platform_zeroize(crl_cur->raw.p, crl_cur->raw.len); - mbedtls_free(crl_cur->raw.p); + mbedtls_zeroize_and_free(crl_cur->raw.p, crl_cur->raw.len); } - crl_cur = crl_cur->next; - } while (crl_cur != NULL); - - crl_cur = crl; - do { crl_prv = crl_cur; crl_cur = crl_cur->next; @@ -736,7 +707,7 @@ void mbedtls_x509_crl_free(mbedtls_x509_crl *crl) if (crl_prv != crl) { mbedtls_free(crl_prv); } - } while (crl_cur != NULL); + } } #endif /* MBEDTLS_X509_CRL_PARSE_C */ diff --git a/vendor/mbedtls/library/x509_crt.c b/vendor/mbedtls/library/x509_crt.c index 0e91bd83b2..2fd56fbd79 100644 --- a/vendor/mbedtls/library/x509_crt.c +++ b/vendor/mbedtls/library/x509_crt.c @@ -2,19 +2,7 @@ * X.509 certificate parsing and verification * * Copyright The Mbed TLS Contributors - * SPDX-License-Identifier: Apache-2.0 - * - * Licensed under the Apache License, Version 2.0 (the "License"); you may - * not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT - * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. + * SPDX-License-Identifier: Apache-2.0 OR GPL-2.0-or-later */ /* * The ITU-T X.509 standard defines a certificate format for PKI. @@ -34,6 +22,7 @@ #if defined(MBEDTLS_X509_CRT_PARSE_C) #include "mbedtls/x509_crt.h" +#include "x509_internal.h" #include "mbedtls/error.h" #include "mbedtls/oid.h" #include "mbedtls/platform_util.h" @@ -46,8 +35,10 @@ #if defined(MBEDTLS_USE_PSA_CRYPTO) #include "psa/crypto.h" +#include "psa_util_internal.h" #include "mbedtls/psa_util.h" -#endif +#endif /* MBEDTLS_USE_PSA_CRYPTO */ +#include "pk_internal.h" #include "mbedtls/platform.h" @@ -57,6 +48,7 @@ #if defined(MBEDTLS_HAVE_TIME) #if defined(_WIN32) && !defined(EFIX64) && !defined(EFI32) +#define WIN32_LEAN_AND_MEAN #include #else #include @@ -68,7 +60,11 @@ #if !defined(_WIN32) || defined(EFIX64) || defined(EFI32) #include #include +#if defined(__MBED__) +#include +#else #include +#endif /* __MBED__ */ #include #endif /* !_WIN32 || EFIX64 || EFI32 */ #endif @@ -90,28 +86,39 @@ typedef struct { * concerns. */ const mbedtls_x509_crt_profile mbedtls_x509_crt_profile_default = { - /* Only SHA-2 hashes */ - MBEDTLS_X509_ID_FLAG(MBEDTLS_MD_SHA224) | + /* Hashes from SHA-256 and above. Note that this selection + * should be aligned with ssl_preset_default_hashes in ssl_tls.c. */ MBEDTLS_X509_ID_FLAG(MBEDTLS_MD_SHA256) | MBEDTLS_X509_ID_FLAG(MBEDTLS_MD_SHA384) | MBEDTLS_X509_ID_FLAG(MBEDTLS_MD_SHA512), 0xFFFFFFF, /* Any PK alg */ - 0xFFFFFFF, /* Any curve */ +#if defined(MBEDTLS_PK_HAVE_ECC_KEYS) + /* Curves at or above 128-bit security level. Note that this selection + * should be aligned with ssl_preset_default_curves in ssl_tls.c. */ + MBEDTLS_X509_ID_FLAG(MBEDTLS_ECP_DP_SECP256R1) | + MBEDTLS_X509_ID_FLAG(MBEDTLS_ECP_DP_SECP384R1) | + MBEDTLS_X509_ID_FLAG(MBEDTLS_ECP_DP_SECP521R1) | + MBEDTLS_X509_ID_FLAG(MBEDTLS_ECP_DP_BP256R1) | + MBEDTLS_X509_ID_FLAG(MBEDTLS_ECP_DP_BP384R1) | + MBEDTLS_X509_ID_FLAG(MBEDTLS_ECP_DP_BP512R1) | + 0, +#else /* MBEDTLS_PK_HAVE_ECC_KEYS */ + 0, +#endif /* MBEDTLS_PK_HAVE_ECC_KEYS */ 2048, }; -/* - * Next-default profile - */ +/* Next-generation profile. Currently identical to the default, but may + * be tightened at any time. */ const mbedtls_x509_crt_profile mbedtls_x509_crt_profile_next = { - /* Hashes from SHA-256 and above */ + /* Hashes from SHA-256 and above. */ MBEDTLS_X509_ID_FLAG(MBEDTLS_MD_SHA256) | MBEDTLS_X509_ID_FLAG(MBEDTLS_MD_SHA384) | MBEDTLS_X509_ID_FLAG(MBEDTLS_MD_SHA512), 0xFFFFFFF, /* Any PK alg */ #if defined(MBEDTLS_ECP_C) - /* Curves at or above 128-bit security level */ + /* Curves at or above 128-bit security level. */ MBEDTLS_X509_ID_FLAG(MBEDTLS_ECP_DP_SECP256R1) | MBEDTLS_X509_ID_FLAG(MBEDTLS_ECP_DP_SECP384R1) | MBEDTLS_X509_ID_FLAG(MBEDTLS_ECP_DP_SECP521R1) | @@ -136,14 +143,25 @@ const mbedtls_x509_crt_profile mbedtls_x509_crt_profile_suiteb = /* Only ECDSA */ MBEDTLS_X509_ID_FLAG(MBEDTLS_PK_ECDSA) | MBEDTLS_X509_ID_FLAG(MBEDTLS_PK_ECKEY), -#if defined(MBEDTLS_ECP_C) +#if defined(MBEDTLS_PK_HAVE_ECC_KEYS) /* Only NIST P-256 and P-384 */ MBEDTLS_X509_ID_FLAG(MBEDTLS_ECP_DP_SECP256R1) | MBEDTLS_X509_ID_FLAG(MBEDTLS_ECP_DP_SECP384R1), -#else +#else /* MBEDTLS_PK_HAVE_ECC_KEYS */ + 0, +#endif /* MBEDTLS_PK_HAVE_ECC_KEYS */ + 0, +}; + +/* + * Empty / all-forbidden profile + */ +const mbedtls_x509_crt_profile mbedtls_x509_crt_profile_none = +{ 0, -#endif 0, + 0, + (uint32_t) -1, }; /* @@ -199,13 +217,13 @@ static int x509_profile_check_key(const mbedtls_x509_crt_profile *profile, return -1; } -#endif +#endif /* MBEDTLS_RSA_C */ -#if defined(MBEDTLS_ECP_C) +#if defined(MBEDTLS_PK_HAVE_ECC_KEYS) if (pk_alg == MBEDTLS_PK_ECDSA || pk_alg == MBEDTLS_PK_ECKEY || pk_alg == MBEDTLS_PK_ECKEY_DH) { - const mbedtls_ecp_group_id gid = mbedtls_pk_ec(*pk)->grp.id; + const mbedtls_ecp_group_id gid = mbedtls_pk_get_ec_group_id(pk); if (gid == MBEDTLS_ECP_DP_NONE) { return -1; @@ -217,7 +235,7 @@ static int x509_profile_check_key(const mbedtls_x509_crt_profile *profile, return -1; } -#endif +#endif /* MBEDTLS_PK_HAVE_ECC_KEYS */ return -1; } @@ -535,113 +553,75 @@ static int x509_get_basic_constraints(unsigned char **p, return 0; } -static int x509_get_ns_cert_type(unsigned char **p, - const unsigned char *end, - unsigned char *ns_cert_type) -{ - int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED; - mbedtls_x509_bitstring bs = { 0, 0, NULL }; - - if ((ret = mbedtls_asn1_get_bitstring(p, end, &bs)) != 0) { - return MBEDTLS_ERROR_ADD(MBEDTLS_ERR_X509_INVALID_EXTENSIONS, ret); - } - - if (bs.len != 1) { - return MBEDTLS_ERROR_ADD(MBEDTLS_ERR_X509_INVALID_EXTENSIONS, - MBEDTLS_ERR_ASN1_INVALID_LENGTH); - } - - /* Get actual bitstring */ - *ns_cert_type = *bs.p; - return 0; -} - -static int x509_get_key_usage(unsigned char **p, - const unsigned char *end, - unsigned int *key_usage) +/* + * ExtKeyUsageSyntax ::= SEQUENCE SIZE (1..MAX) OF KeyPurposeId + * + * KeyPurposeId ::= OBJECT IDENTIFIER + */ +static int x509_get_ext_key_usage(unsigned char **p, + const unsigned char *end, + mbedtls_x509_sequence *ext_key_usage) { int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED; - size_t i; - mbedtls_x509_bitstring bs = { 0, 0, NULL }; - if ((ret = mbedtls_asn1_get_bitstring(p, end, &bs)) != 0) { + if ((ret = mbedtls_asn1_get_sequence_of(p, end, ext_key_usage, MBEDTLS_ASN1_OID)) != 0) { return MBEDTLS_ERROR_ADD(MBEDTLS_ERR_X509_INVALID_EXTENSIONS, ret); } - if (bs.len < 1) { + /* Sequence length must be >= 1 */ + if (ext_key_usage->buf.p == NULL) { return MBEDTLS_ERROR_ADD(MBEDTLS_ERR_X509_INVALID_EXTENSIONS, MBEDTLS_ERR_ASN1_INVALID_LENGTH); } - /* Get actual bitstring */ - *key_usage = 0; - for (i = 0; i < bs.len && i < sizeof(unsigned int); i++) { - *key_usage |= (unsigned int) bs.p[i] << (8*i); - } - return 0; } /* - * ExtKeyUsageSyntax ::= SEQUENCE SIZE (1..MAX) OF KeyPurposeId + * SubjectKeyIdentifier ::= KeyIdentifier * - * KeyPurposeId ::= OBJECT IDENTIFIER + * KeyIdentifier ::= OCTET STRING */ -static int x509_get_ext_key_usage(unsigned char **p, - const unsigned char *end, - mbedtls_x509_sequence *ext_key_usage) +static int x509_get_subject_key_id(unsigned char **p, + const unsigned char *end, + mbedtls_x509_buf *subject_key_id) { int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED; + size_t len = 0u; - if ((ret = mbedtls_asn1_get_sequence_of(p, end, ext_key_usage, MBEDTLS_ASN1_OID)) != 0) { + if ((ret = mbedtls_asn1_get_tag(p, end, &len, + MBEDTLS_ASN1_OCTET_STRING)) != 0) { return MBEDTLS_ERROR_ADD(MBEDTLS_ERR_X509_INVALID_EXTENSIONS, ret); } - /* Sequence length must be >= 1 */ - if (ext_key_usage->buf.p == NULL) { + subject_key_id->len = len; + subject_key_id->tag = MBEDTLS_ASN1_OCTET_STRING; + subject_key_id->p = *p; + *p += len; + + if (*p != end) { return MBEDTLS_ERROR_ADD(MBEDTLS_ERR_X509_INVALID_EXTENSIONS, - MBEDTLS_ERR_ASN1_INVALID_LENGTH); + MBEDTLS_ERR_ASN1_LENGTH_MISMATCH); } return 0; } /* - * SubjectAltName ::= GeneralNames + * AuthorityKeyIdentifier ::= SEQUENCE { + * keyIdentifier [0] KeyIdentifier OPTIONAL, + * authorityCertIssuer [1] GeneralNames OPTIONAL, + * authorityCertSerialNumber [2] CertificateSerialNumber OPTIONAL } * - * GeneralNames ::= SEQUENCE SIZE (1..MAX) OF GeneralName - * - * GeneralName ::= CHOICE { - * otherName [0] OtherName, - * rfc822Name [1] IA5String, - * dNSName [2] IA5String, - * x400Address [3] ORAddress, - * directoryName [4] Name, - * ediPartyName [5] EDIPartyName, - * uniformResourceIdentifier [6] IA5String, - * iPAddress [7] OCTET STRING, - * registeredID [8] OBJECT IDENTIFIER } - * - * OtherName ::= SEQUENCE { - * type-id OBJECT IDENTIFIER, - * value [0] EXPLICIT ANY DEFINED BY type-id } - * - * EDIPartyName ::= SEQUENCE { - * nameAssigner [0] DirectoryString OPTIONAL, - * partyName [1] DirectoryString } - * - * NOTE: we list all types, but only use dNSName and otherName - * of type HwModuleName, as defined in RFC 4108, at this point. + * KeyIdentifier ::= OCTET STRING */ -static int x509_get_subject_alt_name(unsigned char **p, - const unsigned char *end, - mbedtls_x509_sequence *subject_alt_name) +static int x509_get_authority_key_id(unsigned char **p, + unsigned char *end, + mbedtls_x509_authority *authority_key_id) { int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED; - size_t len, tag_len; - mbedtls_asn1_sequence *cur = subject_alt_name; + size_t len = 0u; - /* Get main sequence tag */ if ((ret = mbedtls_asn1_get_tag(p, end, &len, MBEDTLS_ASN1_CONSTRUCTED | MBEDTLS_ASN1_SEQUENCE)) != 0) { return MBEDTLS_ERROR_ADD(MBEDTLS_ERR_X509_INVALID_EXTENSIONS, ret); @@ -652,75 +632,54 @@ static int x509_get_subject_alt_name(unsigned char **p, MBEDTLS_ERR_ASN1_LENGTH_MISMATCH); } - while (*p < end) { - mbedtls_x509_subject_alternative_name dummy_san_buf; - mbedtls_x509_buf tmp_san_buf; - memset(&dummy_san_buf, 0, sizeof(dummy_san_buf)); - - tmp_san_buf.tag = **p; - (*p)++; + ret = mbedtls_asn1_get_tag(p, end, &len, + MBEDTLS_ASN1_CONTEXT_SPECIFIC); - if ((ret = mbedtls_asn1_get_len(p, end, &tag_len)) != 0) { - return MBEDTLS_ERROR_ADD(MBEDTLS_ERR_X509_INVALID_EXTENSIONS, ret); - } + /* KeyIdentifier is an OPTIONAL field */ + if (ret == 0) { + authority_key_id->keyIdentifier.len = len; + authority_key_id->keyIdentifier.p = *p; + /* Setting tag of the keyIdentfier intentionally to 0x04. + * Although the .keyIdentfier field is CONTEXT_SPECIFIC ([0] OPTIONAL), + * its tag with the content is the payload of on OCTET STRING primitive */ + authority_key_id->keyIdentifier.tag = MBEDTLS_ASN1_OCTET_STRING; - tmp_san_buf.p = *p; - tmp_san_buf.len = tag_len; + *p += len; + } else if (ret != MBEDTLS_ERR_ASN1_UNEXPECTED_TAG) { + return MBEDTLS_ERROR_ADD(MBEDTLS_ERR_X509_INVALID_EXTENSIONS, ret); + } - if ((tmp_san_buf.tag & MBEDTLS_ASN1_TAG_CLASS_MASK) != - MBEDTLS_ASN1_CONTEXT_SPECIFIC) { - return MBEDTLS_ERROR_ADD(MBEDTLS_ERR_X509_INVALID_EXTENSIONS, - MBEDTLS_ERR_ASN1_UNEXPECTED_TAG); + if (*p < end) { + /* Getting authorityCertIssuer using the required specific class tag [1] */ + if ((ret = mbedtls_asn1_get_tag(p, end, &len, + MBEDTLS_ASN1_CONTEXT_SPECIFIC | MBEDTLS_ASN1_CONSTRUCTED | + 1)) != 0) { + /* authorityCertIssuer and authorityCertSerialNumber MUST both + be present or both be absent. At this point we expect to have both. */ + return MBEDTLS_ERROR_ADD(MBEDTLS_ERR_X509_INVALID_EXTENSIONS, ret); } - - /* - * Check that the SAN is structured correctly. - */ - ret = mbedtls_x509_parse_subject_alt_name(&tmp_san_buf, &dummy_san_buf); - /* - * In case the extension is malformed, return an error, - * and clear the allocated sequences. - */ - if (ret != 0 && ret != MBEDTLS_ERR_X509_FEATURE_UNAVAILABLE) { - mbedtls_x509_sequence *seq_cur = subject_alt_name->next; - mbedtls_x509_sequence *seq_prv; - while (seq_cur != NULL) { - seq_prv = seq_cur; - seq_cur = seq_cur->next; - mbedtls_platform_zeroize(seq_prv, - sizeof(mbedtls_x509_sequence)); - mbedtls_free(seq_prv); - } - subject_alt_name->next = NULL; + /* "end" also includes the CertSerialNumber field so "len" shall be used */ + ret = mbedtls_x509_get_subject_alt_name_ext(p, + (*p+len), + &authority_key_id->authorityCertIssuer); + if (ret != 0) { return ret; } - /* Allocate and assign next pointer */ - if (cur->buf.p != NULL) { - if (cur->next != NULL) { - return MBEDTLS_ERR_X509_INVALID_EXTENSIONS; - } - - cur->next = mbedtls_calloc(1, sizeof(mbedtls_asn1_sequence)); - - if (cur->next == NULL) { - return MBEDTLS_ERROR_ADD(MBEDTLS_ERR_X509_INVALID_EXTENSIONS, - MBEDTLS_ERR_ASN1_ALLOC_FAILED); - } - - cur = cur->next; + /* Getting authorityCertSerialNumber using the required specific class tag [2] */ + if ((ret = mbedtls_asn1_get_tag(p, end, &len, + MBEDTLS_ASN1_CONTEXT_SPECIFIC | 2)) != 0) { + return MBEDTLS_ERROR_ADD(MBEDTLS_ERR_X509_INVALID_EXTENSIONS, ret); } - - cur->buf = tmp_san_buf; - *p += tmp_san_buf.len; + authority_key_id->authorityCertSerialNumber.len = len; + authority_key_id->authorityCertSerialNumber.p = *p; + authority_key_id->authorityCertSerialNumber.tag = MBEDTLS_ASN1_INTEGER; + *p += len; } - /* Set final sequence entry's next pointer to NULL */ - cur->next = NULL; - if (*p != end) { - return MBEDTLS_ERROR_ADD(MBEDTLS_ERR_X509_INVALID_EXTENSIONS, - MBEDTLS_ERR_ASN1_LENGTH_MISMATCH); + return MBEDTLS_ERR_X509_INVALID_EXTENSIONS + + MBEDTLS_ERR_ASN1_LENGTH_MISMATCH; } return 0; @@ -833,8 +792,7 @@ static int x509_get_certificate_policies(unsigned char **p, if (MBEDTLS_OID_CMP(MBEDTLS_OID_ANY_POLICY, &policy_oid) != 0) { /* * Set the parsing return code but continue parsing, in case this - * extension is critical and MBEDTLS_X509_ALLOW_UNSUPPORTED_CRITICAL_EXTENSION - * is configured. + * extension is critical. */ parse_ret = MBEDTLS_ERR_X509_FEATURE_UNAVAILABLE; } @@ -985,13 +943,11 @@ static int x509_get_crt_ext(unsigned char **p, /* No parser found, skip extension */ *p = end_ext_octet; -#if !defined(MBEDTLS_X509_ALLOW_UNSUPPORTED_CRITICAL_EXTENSION) if (is_critical) { /* Data is marked as critical: fail */ return MBEDTLS_ERROR_ADD(MBEDTLS_ERR_X509_INVALID_EXTENSIONS, MBEDTLS_ERR_ASN1_UNEXPECTED_TAG); } -#endif continue; } @@ -1013,8 +969,8 @@ static int x509_get_crt_ext(unsigned char **p, case MBEDTLS_X509_EXT_KEY_USAGE: /* Parse key usage */ - if ((ret = x509_get_key_usage(p, end_ext_octet, - &crt->key_usage)) != 0) { + if ((ret = mbedtls_x509_get_key_usage(p, end_ext_octet, + &crt->key_usage)) != 0) { return ret; } break; @@ -1027,18 +983,35 @@ static int x509_get_crt_ext(unsigned char **p, } break; + case MBEDTLS_X509_EXT_SUBJECT_KEY_IDENTIFIER: + /* Parse subject key identifier */ + if ((ret = x509_get_subject_key_id(p, end_ext_data, + &crt->subject_key_id)) != 0) { + return ret; + } + break; + + case MBEDTLS_X509_EXT_AUTHORITY_KEY_IDENTIFIER: + /* Parse authority key identifier */ + if ((ret = x509_get_authority_key_id(p, end_ext_octet, + &crt->authority_key_id)) != 0) { + return ret; + } + break; case MBEDTLS_X509_EXT_SUBJECT_ALT_NAME: - /* Parse subject alt name */ - if ((ret = x509_get_subject_alt_name(p, end_ext_octet, - &crt->subject_alt_names)) != 0) { + /* Parse subject alt name + * SubjectAltName ::= GeneralNames + */ + if ((ret = mbedtls_x509_get_subject_alt_name(p, end_ext_octet, + &crt->subject_alt_names)) != 0) { return ret; } break; case MBEDTLS_X509_EXT_NS_CERT_TYPE: /* Parse netscape certificate type */ - if ((ret = x509_get_ns_cert_type(p, end_ext_octet, - &crt->ns_cert_type)) != 0) { + if ((ret = mbedtls_x509_get_ns_cert_type(p, end_ext_octet, + &crt->ns_cert_type)) != 0) { return ret; } break; @@ -1055,11 +1028,9 @@ static int x509_get_crt_ext(unsigned char **p, break; } -#if !defined(MBEDTLS_X509_ALLOW_UNSUPPORTED_CRITICAL_EXTENSION) if (is_critical) { return ret; } else -#endif /* * If MBEDTLS_ERR_X509_FEATURE_UNAVAILABLE is returned, then we * cannot interpret or enforce the policy. However, it is up to @@ -1078,12 +1049,11 @@ static int x509_get_crt_ext(unsigned char **p, * supports, but there isn't an x509 parser for it, * skip the extension. */ -#if !defined(MBEDTLS_X509_ALLOW_UNSUPPORTED_CRITICAL_EXTENSION) if (is_critical) { return MBEDTLS_ERR_X509_FEATURE_UNAVAILABLE; - } else -#endif - *p = end_ext_octet; + } else { + *p = end_ext_octet; + } } } @@ -1139,7 +1109,7 @@ static int x509_crt_parse_der_core(mbedtls_x509_crt *crt, } end = crt_end = p + len; - crt->raw.len = crt_end - buf; + crt->raw.len = (size_t) (crt_end - buf); if (make_copy != 0) { /* Create and populate a new buffer for the raw field. */ crt->raw.p = p = mbedtls_calloc(1, crt->raw.len); @@ -1169,7 +1139,7 @@ static int x509_crt_parse_der_core(mbedtls_x509_crt *crt, } end = p + len; - crt->tbs.len = end - crt->tbs.p; + crt->tbs.len = (size_t) (end - crt->tbs.p); /* * Version ::= INTEGER { v1(0), v2(1), v3(2) } @@ -1216,7 +1186,7 @@ static int x509_crt_parse_der_core(mbedtls_x509_crt *crt, return ret; } - crt->issuer_raw.len = p - crt->issuer_raw.p; + crt->issuer_raw.len = (size_t) (p - crt->issuer_raw.p); /* * Validity ::= SEQUENCE { @@ -1246,7 +1216,7 @@ static int x509_crt_parse_der_core(mbedtls_x509_crt *crt, return ret; } - crt->subject_raw.len = p - crt->subject_raw.p; + crt->subject_raw.len = (size_t) (p - crt->subject_raw.p); /* * SubjectPublicKeyInfo @@ -1256,7 +1226,7 @@ static int x509_crt_parse_der_core(mbedtls_x509_crt *crt, mbedtls_x509_crt_free(crt); return ret; } - crt->pk_raw.len = p - crt->pk_raw.p; + crt->pk_raw.len = (size_t) (p - crt->pk_raw.p); /* * issuerUniqueID [1] IMPLICIT UniqueIdentifier OPTIONAL, @@ -1282,13 +1252,7 @@ static int x509_crt_parse_der_core(mbedtls_x509_crt *crt, } } - int extensions_allowed = 1; -#if !defined(MBEDTLS_X509_ALLOW_EXTENSIONS_NON_V3) - if (crt->version != 3) { - extensions_allowed = 0; - } -#endif - if (extensions_allowed) { + if (crt->version == 3) { ret = x509_get_crt_ext(&p, end, crt, cb, p_ctx); if (ret != 0) { mbedtls_x509_crt_free(crt); @@ -1551,8 +1515,7 @@ int mbedtls_x509_crt_parse_file(mbedtls_x509_crt *chain, const char *path) ret = mbedtls_x509_crt_parse(chain, buf, n); - mbedtls_platform_zeroize(buf, n); - mbedtls_free(buf); + mbedtls_zeroize_and_free(buf, n); return ret; } @@ -1581,6 +1544,11 @@ int mbedtls_x509_crt_parse_path(mbedtls_x509_crt *chain, const char *path) p = filename + len; filename[len++] = '*'; + /* + * Note this function uses the code page CP_ACP which is the system default + * ANSI codepage. The input string is always described in BYTES and the + * output length is described in WCHARs. + */ w_ret = MultiByteToWideChar(CP_ACP, 0, filename, (int) len, szDir, MAX_PATH - 3); if (w_ret == 0) { @@ -1599,11 +1567,8 @@ int mbedtls_x509_crt_parse_path(mbedtls_x509_crt *chain, const char *path) if (file_data.dwFileAttributes & FILE_ATTRIBUTE_DIRECTORY) { continue; } - w_ret = WideCharToMultiByte(CP_ACP, 0, file_data.cFileName, - -1, - p, (int) len, - NULL, NULL); + -1, p, (int) len, NULL, NULL); if (w_ret == 0) { ret = MBEDTLS_ERR_X509_FILE_IO_ERROR; goto cleanup; @@ -1696,323 +1661,28 @@ int mbedtls_x509_crt_parse_path(mbedtls_x509_crt *chain, const char *path) } #endif /* MBEDTLS_FS_IO */ -/* - * OtherName ::= SEQUENCE { - * type-id OBJECT IDENTIFIER, - * value [0] EXPLICIT ANY DEFINED BY type-id } - * - * HardwareModuleName ::= SEQUENCE { - * hwType OBJECT IDENTIFIER, - * hwSerialNum OCTET STRING } - * - * NOTE: we currently only parse and use otherName of type HwModuleName, - * as defined in RFC 4108. - */ -static int x509_get_other_name(const mbedtls_x509_buf *subject_alt_name, - mbedtls_x509_san_other_name *other_name) -{ - int ret = 0; - size_t len; - unsigned char *p = subject_alt_name->p; - const unsigned char *end = p + subject_alt_name->len; - mbedtls_x509_buf cur_oid; - - if ((subject_alt_name->tag & - (MBEDTLS_ASN1_TAG_CLASS_MASK | MBEDTLS_ASN1_TAG_VALUE_MASK)) != - (MBEDTLS_ASN1_CONTEXT_SPECIFIC | MBEDTLS_X509_SAN_OTHER_NAME)) { - /* - * The given subject alternative name is not of type "othername". - */ - return MBEDTLS_ERR_X509_BAD_INPUT_DATA; - } - - if ((ret = mbedtls_asn1_get_tag(&p, end, &len, - MBEDTLS_ASN1_OID)) != 0) { - return MBEDTLS_ERROR_ADD(MBEDTLS_ERR_X509_INVALID_EXTENSIONS, ret); - } - - cur_oid.tag = MBEDTLS_ASN1_OID; - cur_oid.p = p; - cur_oid.len = len; - - /* - * Only HwModuleName is currently supported. - */ - if (MBEDTLS_OID_CMP(MBEDTLS_OID_ON_HW_MODULE_NAME, &cur_oid) != 0) { - return MBEDTLS_ERR_X509_FEATURE_UNAVAILABLE; - } - other_name->type_id = cur_oid; - - p += len; - if ((ret = mbedtls_asn1_get_tag(&p, end, &len, - MBEDTLS_ASN1_CONSTRUCTED | MBEDTLS_ASN1_CONTEXT_SPECIFIC)) != - 0) { - return MBEDTLS_ERROR_ADD(MBEDTLS_ERR_X509_INVALID_EXTENSIONS, ret); - } - - if (end != p + len) { - return MBEDTLS_ERROR_ADD(MBEDTLS_ERR_X509_INVALID_EXTENSIONS, - MBEDTLS_ERR_ASN1_LENGTH_MISMATCH); - } - - if ((ret = mbedtls_asn1_get_tag(&p, end, &len, - MBEDTLS_ASN1_CONSTRUCTED | MBEDTLS_ASN1_SEQUENCE)) != 0) { - return MBEDTLS_ERROR_ADD(MBEDTLS_ERR_X509_INVALID_EXTENSIONS, ret); - } - - if (end != p + len) { - return MBEDTLS_ERROR_ADD(MBEDTLS_ERR_X509_INVALID_EXTENSIONS, - MBEDTLS_ERR_ASN1_LENGTH_MISMATCH); - } - - if ((ret = mbedtls_asn1_get_tag(&p, end, &len, MBEDTLS_ASN1_OID)) != 0) { - return MBEDTLS_ERROR_ADD(MBEDTLS_ERR_X509_INVALID_EXTENSIONS, ret); - } - - other_name->value.hardware_module_name.oid.tag = MBEDTLS_ASN1_OID; - other_name->value.hardware_module_name.oid.p = p; - other_name->value.hardware_module_name.oid.len = len; - - p += len; - if ((ret = mbedtls_asn1_get_tag(&p, end, &len, - MBEDTLS_ASN1_OCTET_STRING)) != 0) { - return MBEDTLS_ERROR_ADD(MBEDTLS_ERR_X509_INVALID_EXTENSIONS, ret); - } - - other_name->value.hardware_module_name.val.tag = MBEDTLS_ASN1_OCTET_STRING; - other_name->value.hardware_module_name.val.p = p; - other_name->value.hardware_module_name.val.len = len; - p += len; - if (p != end) { - return MBEDTLS_ERROR_ADD(MBEDTLS_ERR_X509_INVALID_EXTENSIONS, - MBEDTLS_ERR_ASN1_LENGTH_MISMATCH); - } - return 0; -} - -static int x509_info_subject_alt_name(char **buf, size_t *size, - const mbedtls_x509_sequence - *subject_alt_name, - const char *prefix) -{ - int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED; - size_t i; - size_t n = *size; - char *p = *buf; - const mbedtls_x509_sequence *cur = subject_alt_name; - mbedtls_x509_subject_alternative_name san; - int parse_ret; - - while (cur != NULL) { - memset(&san, 0, sizeof(san)); - parse_ret = mbedtls_x509_parse_subject_alt_name(&cur->buf, &san); - if (parse_ret != 0) { - if (parse_ret == MBEDTLS_ERR_X509_FEATURE_UNAVAILABLE) { - ret = mbedtls_snprintf(p, n, "\n%s ", prefix); - MBEDTLS_X509_SAFE_SNPRINTF; - } else { - ret = mbedtls_snprintf(p, n, "\n%s ", prefix); - MBEDTLS_X509_SAFE_SNPRINTF; - } - cur = cur->next; - continue; - } - - switch (san.type) { - /* - * otherName - */ - case MBEDTLS_X509_SAN_OTHER_NAME: - { - mbedtls_x509_san_other_name *other_name = &san.san.other_name; - - ret = mbedtls_snprintf(p, n, "\n%s otherName :", prefix); - MBEDTLS_X509_SAFE_SNPRINTF; - - if (MBEDTLS_OID_CMP(MBEDTLS_OID_ON_HW_MODULE_NAME, - &other_name->type_id) == 0) { - ret = mbedtls_snprintf(p, n, "\n%s hardware module name :", prefix); - MBEDTLS_X509_SAFE_SNPRINTF; - ret = - mbedtls_snprintf(p, n, "\n%s hardware type : ", prefix); - MBEDTLS_X509_SAFE_SNPRINTF; - - ret = mbedtls_oid_get_numeric_string(p, - n, - &other_name->value.hardware_module_name.oid); - MBEDTLS_X509_SAFE_SNPRINTF; - - ret = - mbedtls_snprintf(p, n, "\n%s hardware serial number : ", prefix); - MBEDTLS_X509_SAFE_SNPRINTF; - - for (i = 0; i < other_name->value.hardware_module_name.val.len; i++) { - ret = mbedtls_snprintf(p, - n, - "%02X", - other_name->value.hardware_module_name.val.p[i]); - MBEDTLS_X509_SAFE_SNPRINTF; - } - }/* MBEDTLS_OID_ON_HW_MODULE_NAME */ - } - break; - - /* - * dNSName - */ - case MBEDTLS_X509_SAN_DNS_NAME: - { - ret = mbedtls_snprintf(p, n, "\n%s dNSName : ", prefix); - MBEDTLS_X509_SAFE_SNPRINTF; - if (san.san.unstructured_name.len >= n) { - *p = '\0'; - return MBEDTLS_ERR_X509_BUFFER_TOO_SMALL; - } - - memcpy(p, san.san.unstructured_name.p, san.san.unstructured_name.len); - p += san.san.unstructured_name.len; - n -= san.san.unstructured_name.len; - } - break; - - /* - * Type not supported, skip item. - */ - default: - ret = mbedtls_snprintf(p, n, "\n%s ", prefix); - MBEDTLS_X509_SAFE_SNPRINTF; - break; - } - - cur = cur->next; - } - - *p = '\0'; - - *size = n; - *buf = p; - - return 0; -} - -int mbedtls_x509_parse_subject_alt_name(const mbedtls_x509_buf *san_buf, - mbedtls_x509_subject_alternative_name *san) -{ - int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED; - switch (san_buf->tag & - (MBEDTLS_ASN1_TAG_CLASS_MASK | - MBEDTLS_ASN1_TAG_VALUE_MASK)) { - /* - * otherName - */ - case (MBEDTLS_ASN1_CONTEXT_SPECIFIC | MBEDTLS_X509_SAN_OTHER_NAME): - { - mbedtls_x509_san_other_name other_name; - - ret = x509_get_other_name(san_buf, &other_name); - if (ret != 0) { - return ret; - } - - memset(san, 0, sizeof(mbedtls_x509_subject_alternative_name)); - san->type = MBEDTLS_X509_SAN_OTHER_NAME; - memcpy(&san->san.other_name, - &other_name, sizeof(other_name)); - - } - break; - - /* - * dNSName - */ - case (MBEDTLS_ASN1_CONTEXT_SPECIFIC | MBEDTLS_X509_SAN_DNS_NAME): - { - memset(san, 0, sizeof(mbedtls_x509_subject_alternative_name)); - san->type = MBEDTLS_X509_SAN_DNS_NAME; - - memcpy(&san->san.unstructured_name, - san_buf, sizeof(*san_buf)); - - } - break; - - /* - * Type not supported - */ - default: - return MBEDTLS_ERR_X509_FEATURE_UNAVAILABLE; - } - return 0; -} - -#define PRINT_ITEM(i) \ - do { \ - ret = mbedtls_snprintf(p, n, "%s" i, sep); \ - MBEDTLS_X509_SAFE_SNPRINTF; \ - sep = ", "; \ +#if !defined(MBEDTLS_X509_REMOVE_INFO) +#define PRINT_ITEM(i) \ + do { \ + ret = mbedtls_snprintf(p, n, "%s" i, sep); \ + MBEDTLS_X509_SAFE_SNPRINTF; \ + sep = ", "; \ } while (0) -#define CERT_TYPE(type, name) \ - do { \ - if (ns_cert_type & (type)) { \ - PRINT_ITEM(name); \ - } \ +#define CERT_TYPE(type, name) \ + do { \ + if (ns_cert_type & (type)) { \ + PRINT_ITEM(name); \ + } \ } while (0) -static int x509_info_cert_type(char **buf, size_t *size, - unsigned char ns_cert_type) -{ - int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED; - size_t n = *size; - char *p = *buf; - const char *sep = ""; - - CERT_TYPE(MBEDTLS_X509_NS_CERT_TYPE_SSL_CLIENT, "SSL Client"); - CERT_TYPE(MBEDTLS_X509_NS_CERT_TYPE_SSL_SERVER, "SSL Server"); - CERT_TYPE(MBEDTLS_X509_NS_CERT_TYPE_EMAIL, "Email"); - CERT_TYPE(MBEDTLS_X509_NS_CERT_TYPE_OBJECT_SIGNING, "Object Signing"); - CERT_TYPE(MBEDTLS_X509_NS_CERT_TYPE_RESERVED, "Reserved"); - CERT_TYPE(MBEDTLS_X509_NS_CERT_TYPE_SSL_CA, "SSL CA"); - CERT_TYPE(MBEDTLS_X509_NS_CERT_TYPE_EMAIL_CA, "Email CA"); - CERT_TYPE(MBEDTLS_X509_NS_CERT_TYPE_OBJECT_SIGNING_CA, "Object Signing CA"); - - *size = n; - *buf = p; - - return 0; -} - -#define KEY_USAGE(code, name) \ - do { \ - if (key_usage & (code)) { \ - PRINT_ITEM(name); \ - } \ +#define KEY_USAGE(code, name) \ + do { \ + if (key_usage & (code)) { \ + PRINT_ITEM(name); \ + } \ } while (0) -static int x509_info_key_usage(char **buf, size_t *size, - unsigned int key_usage) -{ - int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED; - size_t n = *size; - char *p = *buf; - const char *sep = ""; - - KEY_USAGE(MBEDTLS_X509_KU_DIGITAL_SIGNATURE, "Digital Signature"); - KEY_USAGE(MBEDTLS_X509_KU_NON_REPUDIATION, "Non Repudiation"); - KEY_USAGE(MBEDTLS_X509_KU_KEY_ENCIPHERMENT, "Key Encipherment"); - KEY_USAGE(MBEDTLS_X509_KU_DATA_ENCIPHERMENT, "Data Encipherment"); - KEY_USAGE(MBEDTLS_X509_KU_KEY_AGREEMENT, "Key Agreement"); - KEY_USAGE(MBEDTLS_X509_KU_KEY_CERT_SIGN, "Key Cert Sign"); - KEY_USAGE(MBEDTLS_X509_KU_CRL_SIGN, "CRL Sign"); - KEY_USAGE(MBEDTLS_X509_KU_ENCIPHER_ONLY, "Encipher Only"); - KEY_USAGE(MBEDTLS_X509_KU_DECIPHER_ONLY, "Decipher Only"); - - *size = n; - *buf = p; - - return 0; -} - static int x509_info_ext_key_usage(char **buf, size_t *size, const mbedtls_x509_sequence *extended_key_usage) { @@ -2164,9 +1834,9 @@ int mbedtls_x509_crt_info(char *buf, size_t size, const char *prefix, ret = mbedtls_snprintf(p, n, "\n%ssubject alt name :", prefix); MBEDTLS_X509_SAFE_SNPRINTF; - if ((ret = x509_info_subject_alt_name(&p, &n, - &crt->subject_alt_names, - prefix)) != 0) { + if ((ret = mbedtls_x509_info_subject_alt_name(&p, &n, + &crt->subject_alt_names, + prefix)) != 0) { return ret; } } @@ -2175,7 +1845,7 @@ int mbedtls_x509_crt_info(char *buf, size_t size, const char *prefix, ret = mbedtls_snprintf(p, n, "\n%scert. type : ", prefix); MBEDTLS_X509_SAFE_SNPRINTF; - if ((ret = x509_info_cert_type(&p, &n, crt->ns_cert_type)) != 0) { + if ((ret = mbedtls_x509_info_cert_type(&p, &n, crt->ns_cert_type)) != 0) { return ret; } } @@ -2184,7 +1854,7 @@ int mbedtls_x509_crt_info(char *buf, size_t size, const char *prefix, ret = mbedtls_snprintf(p, n, "\n%skey usage : ", prefix); MBEDTLS_X509_SAFE_SNPRINTF; - if ((ret = x509_info_key_usage(&p, &n, crt->key_usage)) != 0) { + if ((ret = mbedtls_x509_info_key_usage(&p, &n, crt->key_usage)) != 0) { return ret; } } @@ -2220,35 +1890,12 @@ struct x509_crt_verify_string { const char *string; }; +#define X509_CRT_ERROR_INFO(err, err_str, info) { err, info }, static const struct x509_crt_verify_string x509_crt_verify_strings[] = { - { MBEDTLS_X509_BADCERT_EXPIRED, "The certificate validity has expired" }, - { MBEDTLS_X509_BADCERT_REVOKED, "The certificate has been revoked (is on a CRL)" }, - { MBEDTLS_X509_BADCERT_CN_MISMATCH, - "The certificate Common Name (CN) does not match with the expected CN" }, - { MBEDTLS_X509_BADCERT_NOT_TRUSTED, - "The certificate is not correctly signed by the trusted CA" }, - { MBEDTLS_X509_BADCRL_NOT_TRUSTED, "The CRL is not correctly signed by the trusted CA" }, - { MBEDTLS_X509_BADCRL_EXPIRED, "The CRL is expired" }, - { MBEDTLS_X509_BADCERT_MISSING, "Certificate was missing" }, - { MBEDTLS_X509_BADCERT_SKIP_VERIFY, "Certificate verification was skipped" }, - { MBEDTLS_X509_BADCERT_OTHER, "Other reason (can be used by verify callback)" }, - { MBEDTLS_X509_BADCERT_FUTURE, "The certificate validity starts in the future" }, - { MBEDTLS_X509_BADCRL_FUTURE, "The CRL is from the future" }, - { MBEDTLS_X509_BADCERT_KEY_USAGE, "Usage does not match the keyUsage extension" }, - { MBEDTLS_X509_BADCERT_EXT_KEY_USAGE, "Usage does not match the extendedKeyUsage extension" }, - { MBEDTLS_X509_BADCERT_NS_CERT_TYPE, "Usage does not match the nsCertType extension" }, - { MBEDTLS_X509_BADCERT_BAD_MD, "The certificate is signed with an unacceptable hash." }, - { MBEDTLS_X509_BADCERT_BAD_PK, - "The certificate is signed with an unacceptable PK alg (eg RSA vs ECDSA)." }, - { MBEDTLS_X509_BADCERT_BAD_KEY, - "The certificate is signed with an unacceptable key (eg bad curve, RSA too short)." }, - { MBEDTLS_X509_BADCRL_BAD_MD, "The CRL is signed with an unacceptable hash." }, - { MBEDTLS_X509_BADCRL_BAD_PK, - "The CRL is signed with an unacceptable PK alg (eg RSA vs ECDSA)." }, - { MBEDTLS_X509_BADCRL_BAD_KEY, - "The CRL is signed with an unacceptable key (eg bad curve, RSA too short)." }, + MBEDTLS_X509_CRT_ERROR_INFO_LIST { 0, NULL } }; +#undef X509_CRT_ERROR_INFO int mbedtls_x509_crt_verify_info(char *buf, size_t size, const char *prefix, uint32_t flags) @@ -2276,8 +1923,8 @@ int mbedtls_x509_crt_verify_info(char *buf, size_t size, const char *prefix, return (int) (size - n); } +#endif /* MBEDTLS_X509_REMOVE_INFO */ -#if defined(MBEDTLS_X509_CHECK_KEY_USAGE) int mbedtls_x509_crt_check_key_usage(const mbedtls_x509_crt *crt, unsigned int usage) { @@ -2303,9 +1950,7 @@ int mbedtls_x509_crt_check_key_usage(const mbedtls_x509_crt *crt, return 0; } -#endif -#if defined(MBEDTLS_X509_CHECK_EXTENDED_KEY_USAGE) int mbedtls_x509_crt_check_extended_key_usage(const mbedtls_x509_crt *crt, const char *usage_oid, size_t usage_len) @@ -2335,7 +1980,6 @@ int mbedtls_x509_crt_check_extended_key_usage(const mbedtls_x509_crt *crt, return MBEDTLS_ERR_X509_BAD_INPUT_DATA; } -#endif /* MBEDTLS_X509_CHECK_EXTENDED_KEY_USAGE */ #if defined(MBEDTLS_X509_CRL_PARSE_C) /* @@ -2363,11 +2007,17 @@ int mbedtls_x509_crt_is_revoked(const mbedtls_x509_crt *crt, const mbedtls_x509_ */ static int x509_crt_verifycrl(mbedtls_x509_crt *crt, mbedtls_x509_crt *ca, mbedtls_x509_crl *crl_list, - const mbedtls_x509_crt_profile *profile) + const mbedtls_x509_crt_profile *profile, + const mbedtls_x509_time *now) { int flags = 0; unsigned char hash[MBEDTLS_MD_MAX_SIZE]; +#if defined(MBEDTLS_USE_PSA_CRYPTO) + psa_algorithm_t psa_algorithm; +#else const mbedtls_md_info_t *md_info; +#endif /* MBEDTLS_USE_PSA_CRYPTO */ + size_t hash_length; if (ca == NULL) { return flags; @@ -2383,13 +2033,11 @@ static int x509_crt_verifycrl(mbedtls_x509_crt *crt, mbedtls_x509_crt *ca, /* * Check if the CA is configured to sign CRLs */ -#if defined(MBEDTLS_X509_CHECK_KEY_USAGE) if (mbedtls_x509_crt_check_key_usage(ca, MBEDTLS_X509_KU_CRL_SIGN) != 0) { flags |= MBEDTLS_X509_BADCRL_NOT_TRUSTED; break; } -#endif /* * Check if CRL is correctly signed by the trusted CA @@ -2402,34 +2050,56 @@ static int x509_crt_verifycrl(mbedtls_x509_crt *crt, mbedtls_x509_crt *ca, flags |= MBEDTLS_X509_BADCRL_BAD_PK; } +#if defined(MBEDTLS_USE_PSA_CRYPTO) + psa_algorithm = mbedtls_md_psa_alg_from_type(crl_list->sig_md); + if (psa_hash_compute(psa_algorithm, + crl_list->tbs.p, + crl_list->tbs.len, + hash, + sizeof(hash), + &hash_length) != PSA_SUCCESS) { + /* Note: this can't happen except after an internal error */ + flags |= MBEDTLS_X509_BADCRL_NOT_TRUSTED; + break; + } +#else md_info = mbedtls_md_info_from_type(crl_list->sig_md); - if (mbedtls_md(md_info, crl_list->tbs.p, crl_list->tbs.len, hash) != 0) { + hash_length = mbedtls_md_get_size(md_info); + if (mbedtls_md(md_info, + crl_list->tbs.p, + crl_list->tbs.len, + hash) != 0) { /* Note: this can't happen except after an internal error */ flags |= MBEDTLS_X509_BADCRL_NOT_TRUSTED; break; } +#endif /* MBEDTLS_USE_PSA_CRYPTO */ if (x509_profile_check_key(profile, &ca->pk) != 0) { flags |= MBEDTLS_X509_BADCERT_BAD_KEY; } if (mbedtls_pk_verify_ext(crl_list->sig_pk, crl_list->sig_opts, &ca->pk, - crl_list->sig_md, hash, mbedtls_md_get_size(md_info), + crl_list->sig_md, hash, hash_length, crl_list->sig.p, crl_list->sig.len) != 0) { flags |= MBEDTLS_X509_BADCRL_NOT_TRUSTED; break; } +#if defined(MBEDTLS_HAVE_TIME_DATE) /* * Check for validity of CRL (Do not drop out) */ - if (mbedtls_x509_time_is_past(&crl_list->next_update)) { + if (mbedtls_x509_time_cmp(&crl_list->next_update, now) < 0) { flags |= MBEDTLS_X509_BADCRL_EXPIRED; } - if (mbedtls_x509_time_is_future(&crl_list->this_update)) { + if (mbedtls_x509_time_cmp(&crl_list->this_update, now) > 0) { flags |= MBEDTLS_X509_BADCRL_FUTURE; } +#else + ((void) now); +#endif /* * Check if certificate is revoked @@ -2453,8 +2123,8 @@ static int x509_crt_check_signature(const mbedtls_x509_crt *child, mbedtls_x509_crt *parent, mbedtls_x509_crt_restart_ctx *rs_ctx) { - unsigned char hash[MBEDTLS_MD_MAX_SIZE]; size_t hash_len; + unsigned char hash[MBEDTLS_MD_MAX_SIZE]; #if !defined(MBEDTLS_USE_PSA_CRYPTO) const mbedtls_md_info_t *md_info; md_info = mbedtls_md_info_from_type(child->sig_md); @@ -2465,22 +2135,19 @@ static int x509_crt_check_signature(const mbedtls_x509_crt *child, return -1; } #else - psa_hash_operation_t hash_operation = PSA_HASH_OPERATION_INIT; - psa_algorithm_t hash_alg = mbedtls_psa_translate_md(child->sig_md); + psa_algorithm_t hash_alg = mbedtls_md_psa_alg_from_type(child->sig_md); + psa_status_t status = PSA_ERROR_CORRUPTION_DETECTED; - if (psa_hash_setup(&hash_operation, hash_alg) != PSA_SUCCESS) { - return -1; + status = psa_hash_compute(hash_alg, + child->tbs.p, + child->tbs.len, + hash, + sizeof(hash), + &hash_len); + if (status != PSA_SUCCESS) { + return MBEDTLS_ERR_PLATFORM_HW_ACCEL_FAILED; } - if (psa_hash_update(&hash_operation, child->tbs.p, child->tbs.len) - != PSA_SUCCESS) { - return -1; - } - - if (psa_hash_finish(&hash_operation, hash, sizeof(hash), &hash_len) - != PSA_SUCCESS) { - return -1; - } #endif /* MBEDTLS_USE_PSA_CRYPTO */ /* Skip expensive computation on obvious mismatch */ if (!mbedtls_pk_can_do(&parent->pk, child->sig_pk)) { @@ -2531,12 +2198,10 @@ static int x509_crt_check_parent(const mbedtls_x509_crt *child, return -1; } -#if defined(MBEDTLS_X509_CHECK_KEY_USAGE) if (need_ca_bit && mbedtls_x509_crt_check_key_usage(parent, MBEDTLS_X509_KU_KEY_CERT_SIGN) != 0) { return -1; } -#endif return 0; } @@ -2592,7 +2257,8 @@ static int x509_crt_find_parent_in( int top, unsigned path_cnt, unsigned self_cnt, - mbedtls_x509_crt_restart_ctx *rs_ctx) + mbedtls_x509_crt_restart_ctx *rs_ctx, + const mbedtls_x509_time *now) { int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED; mbedtls_x509_crt *parent, *fallback_parent; @@ -2655,9 +2321,10 @@ static int x509_crt_find_parent_in( continue; } +#if defined(MBEDTLS_HAVE_TIME_DATE) /* optional time check */ - if (mbedtls_x509_time_is_past(&parent->valid_to) || - mbedtls_x509_time_is_future(&parent->valid_from)) { + if (mbedtls_x509_time_cmp(&parent->valid_to, now) < 0 || /* past */ + mbedtls_x509_time_cmp(&parent->valid_from, now) > 0) { /* future */ if (fallback_parent == NULL) { fallback_parent = parent; fallback_signature_is_good = signature_is_good; @@ -2665,6 +2332,9 @@ static int x509_crt_find_parent_in( continue; } +#else + ((void) now); +#endif *r_parent = parent; *r_signature_is_good = signature_is_good; @@ -2710,7 +2380,8 @@ static int x509_crt_find_parent( int *signature_is_good, unsigned path_cnt, unsigned self_cnt, - mbedtls_x509_crt_restart_ctx *rs_ctx) + mbedtls_x509_crt_restart_ctx *rs_ctx, + const mbedtls_x509_time *now) { int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED; mbedtls_x509_crt *search_list; @@ -2731,7 +2402,7 @@ static int x509_crt_find_parent( ret = x509_crt_find_parent_in(child, search_list, parent, signature_is_good, *parent_is_trusted, - path_cnt, self_cnt, rs_ctx); + path_cnt, self_cnt, rs_ctx, now); #if defined(MBEDTLS_ECDSA_C) && defined(MBEDTLS_ECP_RESTARTABLE) if (rs_ctx != NULL && ret == MBEDTLS_ERR_ECP_IN_PROGRESS) { @@ -2852,6 +2523,13 @@ static int x509_crt_verify_chain( int signature_is_good; unsigned self_cnt; mbedtls_x509_crt *cur_trust_ca = NULL; + mbedtls_x509_time now; + +#if defined(MBEDTLS_HAVE_TIME_DATE) + if (mbedtls_x509_time_gmtime(mbedtls_time(NULL), &now) != 0) { + return MBEDTLS_ERR_X509_FATAL_ERROR; + } +#endif #if defined(MBEDTLS_ECDSA_C) && defined(MBEDTLS_ECP_RESTARTABLE) /* resume if we had an operation in progress */ @@ -2882,14 +2560,16 @@ static int x509_crt_verify_chain( ver_chain->len++; flags = &cur->flags; +#if defined(MBEDTLS_HAVE_TIME_DATE) /* Check time-validity (all certificates) */ - if (mbedtls_x509_time_is_past(&child->valid_to)) { + if (mbedtls_x509_time_cmp(&child->valid_to, &now) < 0) { *flags |= MBEDTLS_X509_BADCERT_EXPIRED; } - if (mbedtls_x509_time_is_future(&child->valid_from)) { + if (mbedtls_x509_time_cmp(&child->valid_from, &now) > 0) { *flags |= MBEDTLS_X509_BADCERT_FUTURE; } +#endif /* Stop here for trusted roots (but not for trusted EE certs) */ if (child_is_trusted) { @@ -2940,7 +2620,8 @@ static int x509_crt_verify_chain( /* Look for a parent in trusted CAs or up the chain */ ret = x509_crt_find_parent(child, cur_trust_ca, &parent, &parent_is_trusted, &signature_is_good, - ver_chain->len - 1, self_cnt, rs_ctx); + ver_chain->len - 1, self_cnt, rs_ctx, + &now); #if defined(MBEDTLS_ECDSA_C) && defined(MBEDTLS_ECP_RESTARTABLE) if (rs_ctx != NULL && ret == MBEDTLS_ERR_ECP_IN_PROGRESS) { @@ -2989,7 +2670,7 @@ static int x509_crt_verify_chain( #if defined(MBEDTLS_X509_CRL_PARSE_C) /* Check trusted CA's CRL for the given crt */ - *flags |= x509_crt_verifycrl(child, parent, ca_crl, profile); + *flags |= x509_crt_verifycrl(child, parent, ca_crl, profile, &now); #else (void) ca_crl; #endif @@ -3002,6 +2683,202 @@ static int x509_crt_verify_chain( } } +#ifdef _WIN32 +#ifdef _MSC_VER +#pragma comment(lib, "ws2_32.lib") +#include +#include +#elif (defined(__MINGW32__) || defined(__MINGW64__)) && _WIN32_WINNT >= 0x0600 +#include +#include +#else +/* inet_pton() is not supported, fallback to software version */ +#define MBEDTLS_TEST_SW_INET_PTON +#endif +#elif defined(__sun) +/* Solaris requires -lsocket -lnsl for inet_pton() */ +#elif defined(__has_include) +#if __has_include() +#include +#endif +#if __has_include() +#include +#endif +#endif + +/* Use whether or not AF_INET6 is defined to indicate whether or not to use + * the platform inet_pton() or a local implementation (below). The local + * implementation may be used even in cases where the platform provides + * inet_pton(), e.g. when there are different includes required and/or the + * platform implementation requires dependencies on additional libraries. + * Specifically, Windows requires custom includes and additional link + * dependencies, and Solaris requires additional link dependencies. + * Also, as a coarse heuristic, use the local implementation if the compiler + * does not support __has_include(), or if the definition of AF_INET6 is not + * provided by headers included (or not) via __has_include() above. + * MBEDTLS_TEST_SW_INET_PTON is a bypass define to force testing of this code //no-check-names + * despite having a platform that has inet_pton. */ +#if !defined(AF_INET6) || defined(MBEDTLS_TEST_SW_INET_PTON) //no-check-names +/* Definition located further below to possibly reduce compiler inlining */ +static int x509_inet_pton_ipv4(const char *src, void *dst); + +#define li_cton(c, n) \ + (((n) = (c) - '0') <= 9 || (((n) = ((c)&0xdf) - 'A') <= 5 ? ((n) += 10) : 0)) + +static int x509_inet_pton_ipv6(const char *src, void *dst) +{ + const unsigned char *p = (const unsigned char *) src; + int nonzero_groups = 0, num_digits, zero_group_start = -1; + uint16_t addr[8]; + do { + /* note: allows excess leading 0's, e.g. 1:0002:3:... */ + uint16_t group = num_digits = 0; + for (uint8_t digit; num_digits < 4; num_digits++) { + if (li_cton(*p, digit) == 0) { + break; + } + group = (group << 4) | digit; + p++; + } + if (num_digits != 0) { + MBEDTLS_PUT_UINT16_BE(group, addr, nonzero_groups); + nonzero_groups++; + if (*p == '\0') { + break; + } else if (*p == '.') { + /* Don't accept IPv4 too early or late */ + if ((nonzero_groups == 0 && zero_group_start == -1) || + nonzero_groups >= 7) { + break; + } + + /* Walk back to prior ':', then parse as IPv4-mapped */ + int steps = 4; + do { + p--; + steps--; + } while (*p != ':' && steps > 0); + + if (*p != ':') { + break; + } + p++; + nonzero_groups--; + if (x509_inet_pton_ipv4((const char *) p, + addr + nonzero_groups) != 0) { + break; + } + + nonzero_groups += 2; + p = (const unsigned char *) ""; + break; + } else if (*p != ':') { + return -1; + } + } else { + /* Don't accept a second zero group or an invalid delimiter */ + if (zero_group_start != -1 || *p != ':') { + return -1; + } + zero_group_start = nonzero_groups; + + /* Accept a zero group at start, but it has to be a double colon */ + if (zero_group_start == 0 && *++p != ':') { + return -1; + } + + if (p[1] == '\0') { + ++p; + break; + } + } + ++p; + } while (nonzero_groups < 8); + + if (*p != '\0') { + return -1; + } + + if (zero_group_start != -1) { + if (nonzero_groups > 6) { + return -1; + } + int zero_groups = 8 - nonzero_groups; + int groups_after_zero = nonzero_groups - zero_group_start; + + /* Move the non-zero part to after the zeroes */ + if (groups_after_zero) { + memmove(addr + zero_group_start + zero_groups, + addr + zero_group_start, + groups_after_zero * sizeof(*addr)); + } + memset(addr + zero_group_start, 0, zero_groups * sizeof(*addr)); + } else { + if (nonzero_groups != 8) { + return -1; + } + } + memcpy(dst, addr, sizeof(addr)); + return 0; +} + +static int x509_inet_pton_ipv4(const char *src, void *dst) +{ + const unsigned char *p = (const unsigned char *) src; + uint8_t *res = (uint8_t *) dst; + uint8_t digit, num_digits = 0; + uint8_t num_octets = 0; + uint16_t octet; + + do { + octet = num_digits = 0; + do { + digit = *p - '0'; + if (digit > 9) { + break; + } + + /* Don't allow leading zeroes. These might mean octal format, + * which this implementation does not support. */ + if (octet == 0 && num_digits > 0) { + return -1; + } + + octet = octet * 10 + digit; + num_digits++; + p++; + } while (num_digits < 3); + + if (octet >= 256 || num_digits > 3 || num_digits == 0) { + return -1; + } + *res++ = (uint8_t) octet; + num_octets++; + } while (num_octets < 4 && *p++ == '.'); + return num_octets == 4 && *p == '\0' ? 0 : -1; +} + +#else + +static int x509_inet_pton_ipv6(const char *src, void *dst) +{ + return inet_pton(AF_INET6, src, dst) == 1 ? 0 : -1; +} + +static int x509_inet_pton_ipv4(const char *src, void *dst) +{ + return inet_pton(AF_INET, src, dst) == 1 ? 0 : -1; +} + +#endif /* !AF_INET6 || MBEDTLS_TEST_SW_INET_PTON */ //no-check-names + +size_t mbedtls_x509_crt_parse_cn_inet_pton(const char *cn, void *dst) +{ + return strchr(cn, ':') == NULL + ? x509_inet_pton_ipv4(cn, dst) == 0 ? 4 : 0 + : x509_inet_pton_ipv6(cn, dst) == 0 ? 16 : 0; +} + /* * Check for CN match */ @@ -3022,23 +2899,80 @@ static int x509_crt_check_cn(const mbedtls_x509_buf *name, return -1; } +static int x509_crt_check_san_ip(const mbedtls_x509_sequence *san, + const char *cn, size_t cn_len) +{ + uint32_t ip[4]; + cn_len = mbedtls_x509_crt_parse_cn_inet_pton(cn, ip); + if (cn_len == 0) { + return -1; + } + + for (const mbedtls_x509_sequence *cur = san; cur != NULL; cur = cur->next) { + const unsigned char san_type = (unsigned char) cur->buf.tag & + MBEDTLS_ASN1_TAG_VALUE_MASK; + if (san_type == MBEDTLS_X509_SAN_IP_ADDRESS && + cur->buf.len == cn_len && memcmp(cur->buf.p, ip, cn_len) == 0) { + return 0; + } + } + + return -1; +} + +static int x509_crt_check_san_uri(const mbedtls_x509_sequence *san, + const char *cn, size_t cn_len) +{ + for (const mbedtls_x509_sequence *cur = san; cur != NULL; cur = cur->next) { + const unsigned char san_type = (unsigned char) cur->buf.tag & + MBEDTLS_ASN1_TAG_VALUE_MASK; + if (san_type == MBEDTLS_X509_SAN_UNIFORM_RESOURCE_IDENTIFIER && + cur->buf.len == cn_len && memcmp(cur->buf.p, cn, cn_len) == 0) { + return 0; + } + } + + return -1; +} + /* * Check for SAN match, see RFC 5280 Section 4.2.1.6 */ -static int x509_crt_check_san(const mbedtls_x509_buf *name, +static int x509_crt_check_san(const mbedtls_x509_sequence *san, const char *cn, size_t cn_len) { - const unsigned char san_type = (unsigned char) name->tag & - MBEDTLS_ASN1_TAG_VALUE_MASK; - - /* dNSName */ - if (san_type == MBEDTLS_X509_SAN_DNS_NAME) { - return x509_crt_check_cn(name, cn, cn_len); + int san_ip = 0; + int san_uri = 0; + /* Prioritize DNS name over other subtypes due to popularity */ + for (const mbedtls_x509_sequence *cur = san; cur != NULL; cur = cur->next) { + switch ((unsigned char) cur->buf.tag & MBEDTLS_ASN1_TAG_VALUE_MASK) { + case MBEDTLS_X509_SAN_DNS_NAME: + if (x509_crt_check_cn(&cur->buf, cn, cn_len) == 0) { + return 0; + } + break; + case MBEDTLS_X509_SAN_IP_ADDRESS: + san_ip = 1; + break; + case MBEDTLS_X509_SAN_UNIFORM_RESOURCE_IDENTIFIER: + san_uri = 1; + break; + /* (We may handle other types here later.) */ + default: /* Unrecognized type */ + break; + } + } + if (san_ip) { + if (x509_crt_check_san_ip(san, cn, cn_len) == 0) { + return 0; + } + } + if (san_uri) { + if (x509_crt_check_san_uri(san, cn, cn_len) == 0) { + return 0; + } } - /* (We may handle other types here later.) */ - - /* Unrecognized type */ return -1; } @@ -3050,31 +2984,23 @@ static void x509_crt_verify_name(const mbedtls_x509_crt *crt, uint32_t *flags) { const mbedtls_x509_name *name; - const mbedtls_x509_sequence *cur; size_t cn_len = strlen(cn); if (crt->ext_types & MBEDTLS_X509_EXT_SUBJECT_ALT_NAME) { - for (cur = &crt->subject_alt_names; cur != NULL; cur = cur->next) { - if (x509_crt_check_san(&cur->buf, cn, cn_len) == 0) { - break; - } - } - - if (cur == NULL) { - *flags |= MBEDTLS_X509_BADCERT_CN_MISMATCH; + if (x509_crt_check_san(&crt->subject_alt_names, cn, cn_len) == 0) { + return; } } else { for (name = &crt->subject; name != NULL; name = name->next) { if (MBEDTLS_OID_CMP(MBEDTLS_OID_AT_CN, &name->oid) == 0 && x509_crt_check_cn(&name->val, cn, cn_len) == 0) { - break; + return; } } - if (name == NULL) { - *flags |= MBEDTLS_X509_BADCERT_CN_MISMATCH; - } } + + *flags |= MBEDTLS_X509_BADCERT_CN_MISMATCH; } /* @@ -3302,75 +3228,25 @@ void mbedtls_x509_crt_free(mbedtls_x509_crt *crt) { mbedtls_x509_crt *cert_cur = crt; mbedtls_x509_crt *cert_prv; - mbedtls_x509_name *name_cur; - mbedtls_x509_name *name_prv; - mbedtls_x509_sequence *seq_cur; - mbedtls_x509_sequence *seq_prv; - if (crt == NULL) { - return; - } - - do { + while (cert_cur != NULL) { mbedtls_pk_free(&cert_cur->pk); #if defined(MBEDTLS_X509_RSASSA_PSS_SUPPORT) mbedtls_free(cert_cur->sig_opts); #endif - name_cur = cert_cur->issuer.next; - while (name_cur != NULL) { - name_prv = name_cur; - name_cur = name_cur->next; - mbedtls_platform_zeroize(name_prv, sizeof(mbedtls_x509_name)); - mbedtls_free(name_prv); - } - - name_cur = cert_cur->subject.next; - while (name_cur != NULL) { - name_prv = name_cur; - name_cur = name_cur->next; - mbedtls_platform_zeroize(name_prv, sizeof(mbedtls_x509_name)); - mbedtls_free(name_prv); - } - - seq_cur = cert_cur->ext_key_usage.next; - while (seq_cur != NULL) { - seq_prv = seq_cur; - seq_cur = seq_cur->next; - mbedtls_platform_zeroize(seq_prv, - sizeof(mbedtls_x509_sequence)); - mbedtls_free(seq_prv); - } - - seq_cur = cert_cur->subject_alt_names.next; - while (seq_cur != NULL) { - seq_prv = seq_cur; - seq_cur = seq_cur->next; - mbedtls_platform_zeroize(seq_prv, - sizeof(mbedtls_x509_sequence)); - mbedtls_free(seq_prv); - } - - seq_cur = cert_cur->certificate_policies.next; - while (seq_cur != NULL) { - seq_prv = seq_cur; - seq_cur = seq_cur->next; - mbedtls_platform_zeroize(seq_prv, - sizeof(mbedtls_x509_sequence)); - mbedtls_free(seq_prv); - } + mbedtls_asn1_free_named_data_list_shallow(cert_cur->issuer.next); + mbedtls_asn1_free_named_data_list_shallow(cert_cur->subject.next); + mbedtls_asn1_sequence_free(cert_cur->ext_key_usage.next); + mbedtls_asn1_sequence_free(cert_cur->subject_alt_names.next); + mbedtls_asn1_sequence_free(cert_cur->certificate_policies.next); + mbedtls_asn1_sequence_free(cert_cur->authority_key_id.authorityCertIssuer.next); if (cert_cur->raw.p != NULL && cert_cur->own_buffer) { - mbedtls_platform_zeroize(cert_cur->raw.p, cert_cur->raw.len); - mbedtls_free(cert_cur->raw.p); + mbedtls_zeroize_and_free(cert_cur->raw.p, cert_cur->raw.len); } - cert_cur = cert_cur->next; - } while (cert_cur != NULL); - - cert_cur = crt; - do { cert_prv = cert_cur; cert_cur = cert_cur->next; @@ -3378,7 +3254,7 @@ void mbedtls_x509_crt_free(mbedtls_x509_crt *crt) if (cert_prv != crt) { mbedtls_free(cert_prv); } - } while (cert_cur != NULL); + } } #if defined(MBEDTLS_ECDSA_C) && defined(MBEDTLS_ECP_RESTARTABLE) @@ -3414,4 +3290,12 @@ void mbedtls_x509_crt_restart_free(mbedtls_x509_crt_restart_ctx *ctx) } #endif /* MBEDTLS_ECDSA_C && MBEDTLS_ECP_RESTARTABLE */ +int mbedtls_x509_crt_get_ca_istrue(const mbedtls_x509_crt *crt) +{ + if ((crt->ext_types & MBEDTLS_X509_EXT_BASIC_CONSTRAINTS) != 0) { + return crt->MBEDTLS_PRIVATE(ca_istrue); + } + return MBEDTLS_ERR_X509_INVALID_EXTENSIONS; +} + #endif /* MBEDTLS_X509_CRT_PARSE_C */ diff --git a/vendor/mbedtls/library/x509_csr.c b/vendor/mbedtls/library/x509_csr.c index 89344d183b..813d64466c 100644 --- a/vendor/mbedtls/library/x509_csr.c +++ b/vendor/mbedtls/library/x509_csr.c @@ -2,19 +2,7 @@ * X.509 Certificate Signing Request (CSR) parsing * * Copyright The Mbed TLS Contributors - * SPDX-License-Identifier: Apache-2.0 - * - * Licensed under the Apache License, Version 2.0 (the "License"); you may - * not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT - * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. + * SPDX-License-Identifier: Apache-2.0 OR GPL-2.0-or-later */ /* * The ITU-T X.509 standard defines a certificate format for PKI. @@ -32,6 +20,7 @@ #if defined(MBEDTLS_X509_CSR_PARSE_C) #include "mbedtls/x509_csr.h" +#include "x509_internal.h" #include "mbedtls/error.h" #include "mbedtls/oid.h" #include "mbedtls/platform_util.h" @@ -69,11 +58,214 @@ static int x509_csr_get_version(unsigned char **p, return 0; } +/* + * Parse CSR extension requests in DER format + */ +static int x509_csr_parse_extensions(mbedtls_x509_csr *csr, + unsigned char **p, const unsigned char *end, + mbedtls_x509_csr_ext_cb_t cb, + void *p_ctx) +{ + int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED; + size_t len; + unsigned char *end_ext_data, *end_ext_octet; + + while (*p < end) { + mbedtls_x509_buf extn_oid = { 0, 0, NULL }; + int is_critical = 0; /* DEFAULT FALSE */ + int ext_type = 0; + + /* Read sequence tag */ + if ((ret = mbedtls_asn1_get_tag(p, end, &len, + MBEDTLS_ASN1_CONSTRUCTED | MBEDTLS_ASN1_SEQUENCE)) != 0) { + return MBEDTLS_ERROR_ADD(MBEDTLS_ERR_X509_INVALID_EXTENSIONS, ret); + } + + end_ext_data = *p + len; + + /* Get extension ID */ + if ((ret = mbedtls_asn1_get_tag(p, end_ext_data, &extn_oid.len, + MBEDTLS_ASN1_OID)) != 0) { + return MBEDTLS_ERROR_ADD(MBEDTLS_ERR_X509_INVALID_EXTENSIONS, ret); + } + + extn_oid.tag = MBEDTLS_ASN1_OID; + extn_oid.p = *p; + *p += extn_oid.len; + + /* Get optional critical */ + if ((ret = mbedtls_asn1_get_bool(p, end_ext_data, &is_critical)) != 0 && + (ret != MBEDTLS_ERR_ASN1_UNEXPECTED_TAG)) { + return MBEDTLS_ERROR_ADD(MBEDTLS_ERR_X509_INVALID_EXTENSIONS, ret); + } + + /* Data should be octet string type */ + if ((ret = mbedtls_asn1_get_tag(p, end_ext_data, &len, + MBEDTLS_ASN1_OCTET_STRING)) != 0) { + return MBEDTLS_ERROR_ADD(MBEDTLS_ERR_X509_INVALID_EXTENSIONS, ret); + } + + end_ext_octet = *p + len; + + if (end_ext_octet != end_ext_data) { + return MBEDTLS_ERROR_ADD(MBEDTLS_ERR_X509_INVALID_EXTENSIONS, + MBEDTLS_ERR_ASN1_LENGTH_MISMATCH); + } + + /* + * Detect supported extensions and skip unsupported extensions + */ + ret = mbedtls_oid_get_x509_ext_type(&extn_oid, &ext_type); + + if (ret != 0) { + /* Give the callback (if any) a chance to handle the extension */ + if (cb != NULL) { + ret = cb(p_ctx, csr, &extn_oid, is_critical, *p, end_ext_octet); + if (ret != 0 && is_critical) { + return ret; + } + *p = end_ext_octet; + continue; + } + + /* No parser found, skip extension */ + *p = end_ext_octet; + + if (is_critical) { + /* Data is marked as critical: fail */ + return MBEDTLS_ERROR_ADD(MBEDTLS_ERR_X509_INVALID_EXTENSIONS, + MBEDTLS_ERR_ASN1_UNEXPECTED_TAG); + } + continue; + } + + /* Forbid repeated extensions */ + if ((csr->ext_types & ext_type) != 0) { + return MBEDTLS_ERROR_ADD(MBEDTLS_ERR_X509_INVALID_EXTENSIONS, + MBEDTLS_ERR_ASN1_INVALID_DATA); + } + + csr->ext_types |= ext_type; + + switch (ext_type) { + case MBEDTLS_X509_EXT_KEY_USAGE: + /* Parse key usage */ + if ((ret = mbedtls_x509_get_key_usage(p, end_ext_data, + &csr->key_usage)) != 0) { + return ret; + } + break; + + case MBEDTLS_X509_EXT_SUBJECT_ALT_NAME: + /* Parse subject alt name */ + if ((ret = mbedtls_x509_get_subject_alt_name(p, end_ext_data, + &csr->subject_alt_names)) != 0) { + return ret; + } + break; + + case MBEDTLS_X509_EXT_NS_CERT_TYPE: + /* Parse netscape certificate type */ + if ((ret = mbedtls_x509_get_ns_cert_type(p, end_ext_data, + &csr->ns_cert_type)) != 0) { + return ret; + } + break; + default: + /* + * If this is a non-critical extension, which the oid layer + * supports, but there isn't an x509 parser for it, + * skip the extension. + */ + if (is_critical) { + return MBEDTLS_ERR_X509_FEATURE_UNAVAILABLE; + } else { + *p = end_ext_octet; + } + } + } + + if (*p != end) { + return MBEDTLS_ERROR_ADD(MBEDTLS_ERR_X509_INVALID_EXTENSIONS, + MBEDTLS_ERR_ASN1_LENGTH_MISMATCH); + } + + return 0; +} + +/* + * Parse CSR attributes in DER format + */ +static int x509_csr_parse_attributes(mbedtls_x509_csr *csr, + const unsigned char *start, const unsigned char *end, + mbedtls_x509_csr_ext_cb_t cb, + void *p_ctx) +{ + int ret; + size_t len; + unsigned char *end_attr_data; + unsigned char **p = (unsigned char **) &start; + + while (*p < end) { + mbedtls_x509_buf attr_oid = { 0, 0, NULL }; + + if ((ret = mbedtls_asn1_get_tag(p, end, &len, + MBEDTLS_ASN1_CONSTRUCTED | MBEDTLS_ASN1_SEQUENCE)) != 0) { + return MBEDTLS_ERROR_ADD(MBEDTLS_ERR_X509_INVALID_EXTENSIONS, ret); + } + end_attr_data = *p + len; + + /* Get attribute ID */ + if ((ret = mbedtls_asn1_get_tag(p, end_attr_data, &attr_oid.len, + MBEDTLS_ASN1_OID)) != 0) { + return MBEDTLS_ERROR_ADD(MBEDTLS_ERR_X509_INVALID_EXTENSIONS, ret); + } + + attr_oid.tag = MBEDTLS_ASN1_OID; + attr_oid.p = *p; + *p += attr_oid.len; + + /* Check that this is an extension-request attribute */ + if (MBEDTLS_OID_CMP(MBEDTLS_OID_PKCS9_CSR_EXT_REQ, &attr_oid) == 0) { + if ((ret = mbedtls_asn1_get_tag(p, end, &len, + MBEDTLS_ASN1_CONSTRUCTED | MBEDTLS_ASN1_SET)) != 0) { + return MBEDTLS_ERROR_ADD(MBEDTLS_ERR_X509_INVALID_EXTENSIONS, ret); + } + + if ((ret = mbedtls_asn1_get_tag(p, end, &len, + MBEDTLS_ASN1_CONSTRUCTED | MBEDTLS_ASN1_SEQUENCE)) != + 0) { + return MBEDTLS_ERROR_ADD(MBEDTLS_ERR_X509_INVALID_EXTENSIONS, ret); + } + + if ((ret = x509_csr_parse_extensions(csr, p, *p + len, cb, p_ctx)) != 0) { + return ret; + } + + if (*p != end_attr_data) { + return MBEDTLS_ERROR_ADD(MBEDTLS_ERR_X509_INVALID_EXTENSIONS, + MBEDTLS_ERR_ASN1_LENGTH_MISMATCH); + } + } + + *p = end_attr_data; + } + + if (*p != end) { + return MBEDTLS_ERROR_ADD(MBEDTLS_ERR_X509_INVALID_EXTENSIONS, + MBEDTLS_ERR_ASN1_LENGTH_MISMATCH); + } + + return 0; +} + /* * Parse a CSR in DER format */ -int mbedtls_x509_csr_parse_der(mbedtls_x509_csr *csr, - const unsigned char *buf, size_t buflen) +static int mbedtls_x509_csr_parse_der_internal(mbedtls_x509_csr *csr, + const unsigned char *buf, size_t buflen, + mbedtls_x509_csr_ext_cb_t cb, + void *p_ctx) { int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED; size_t len; @@ -137,7 +329,7 @@ int mbedtls_x509_csr_parse_der(mbedtls_x509_csr *csr, } end = p + len; - csr->cri.len = end - csr->cri.p; + csr->cri.len = (size_t) (end - csr->cri.p); /* * Version ::= INTEGER { v1(0) } @@ -170,7 +362,7 @@ int mbedtls_x509_csr_parse_der(mbedtls_x509_csr *csr, return ret; } - csr->subject_raw.len = p - csr->subject_raw.p; + csr->subject_raw.len = (size_t) (p - csr->subject_raw.p); /* * subjectPKInfo SubjectPublicKeyInfo @@ -197,6 +389,11 @@ int mbedtls_x509_csr_parse_der(mbedtls_x509_csr *csr, return MBEDTLS_ERROR_ADD(MBEDTLS_ERR_X509_INVALID_FORMAT, ret); } + if ((ret = x509_csr_parse_attributes(csr, p, p + len, cb, p_ctx)) != 0) { + mbedtls_x509_csr_free(csr); + return ret; + } + p += len; end = csr->raw.p + csr->raw.len; @@ -231,6 +428,26 @@ int mbedtls_x509_csr_parse_der(mbedtls_x509_csr *csr, return 0; } +/* + * Parse a CSR in DER format + */ +int mbedtls_x509_csr_parse_der(mbedtls_x509_csr *csr, + const unsigned char *buf, size_t buflen) +{ + return mbedtls_x509_csr_parse_der_internal(csr, buf, buflen, NULL, NULL); +} + +/* + * Parse a CSR in DER format with callback for unknown extensions + */ +int mbedtls_x509_csr_parse_der_with_ext_cb(mbedtls_x509_csr *csr, + const unsigned char *buf, size_t buflen, + mbedtls_x509_csr_ext_cb_t cb, + void *p_ctx) +{ + return mbedtls_x509_csr_parse_der_internal(csr, buf, buflen, cb, p_ctx); +} + /* * Parse a CSR, allowing for PEM or raw DER encoding */ @@ -296,13 +513,13 @@ int mbedtls_x509_csr_parse_file(mbedtls_x509_csr *csr, const char *path) ret = mbedtls_x509_csr_parse(csr, buf, n); - mbedtls_platform_zeroize(buf, n); - mbedtls_free(buf); + mbedtls_zeroize_and_free(buf, n); return ret; } #endif /* MBEDTLS_FS_IO */ +#if !defined(MBEDTLS_X509_REMOVE_INFO) #define BEFORE_COLON 14 #define BC "14" /* @@ -344,8 +561,47 @@ int mbedtls_x509_csr_info(char *buf, size_t size, const char *prefix, (int) mbedtls_pk_get_bitlen(&csr->pk)); MBEDTLS_X509_SAFE_SNPRINTF; + /* + * Optional extensions + */ + + if (csr->ext_types & MBEDTLS_X509_EXT_SUBJECT_ALT_NAME) { + ret = mbedtls_snprintf(p, n, "\n%ssubject alt name :", prefix); + MBEDTLS_X509_SAFE_SNPRINTF; + + if ((ret = mbedtls_x509_info_subject_alt_name(&p, &n, + &csr->subject_alt_names, + prefix)) != 0) { + return ret; + } + } + + if (csr->ext_types & MBEDTLS_X509_EXT_NS_CERT_TYPE) { + ret = mbedtls_snprintf(p, n, "\n%scert. type : ", prefix); + MBEDTLS_X509_SAFE_SNPRINTF; + + if ((ret = mbedtls_x509_info_cert_type(&p, &n, csr->ns_cert_type)) != 0) { + return ret; + } + } + + if (csr->ext_types & MBEDTLS_X509_EXT_KEY_USAGE) { + ret = mbedtls_snprintf(p, n, "\n%skey usage : ", prefix); + MBEDTLS_X509_SAFE_SNPRINTF; + + if ((ret = mbedtls_x509_info_key_usage(&p, &n, csr->key_usage)) != 0) { + return ret; + } + } + + if (csr->ext_types != 0) { + ret = mbedtls_snprintf(p, n, "\n"); + MBEDTLS_X509_SAFE_SNPRINTF; + } + return (int) (size - n); } +#endif /* MBEDTLS_X509_REMOVE_INFO */ /* * Initialize a CSR @@ -360,9 +616,6 @@ void mbedtls_x509_csr_init(mbedtls_x509_csr *csr) */ void mbedtls_x509_csr_free(mbedtls_x509_csr *csr) { - mbedtls_x509_name *name_cur; - mbedtls_x509_name *name_prv; - if (csr == NULL) { return; } @@ -373,17 +626,11 @@ void mbedtls_x509_csr_free(mbedtls_x509_csr *csr) mbedtls_free(csr->sig_opts); #endif - name_cur = csr->subject.next; - while (name_cur != NULL) { - name_prv = name_cur; - name_cur = name_cur->next; - mbedtls_platform_zeroize(name_prv, sizeof(mbedtls_x509_name)); - mbedtls_free(name_prv); - } + mbedtls_asn1_free_named_data_list_shallow(csr->subject.next); + mbedtls_asn1_sequence_free(csr->subject_alt_names.next); if (csr->raw.p != NULL) { - mbedtls_platform_zeroize(csr->raw.p, csr->raw.len); - mbedtls_free(csr->raw.p); + mbedtls_zeroize_and_free(csr->raw.p, csr->raw.len); } mbedtls_platform_zeroize(csr, sizeof(mbedtls_x509_csr)); diff --git a/vendor/mbedtls/library/x509_internal.h b/vendor/mbedtls/library/x509_internal.h new file mode 100644 index 0000000000..8a2d2ed007 --- /dev/null +++ b/vendor/mbedtls/library/x509_internal.h @@ -0,0 +1,86 @@ +/** + * \file x509.h + * + * \brief Internal part of the public "x509.h". + */ +/* + * Copyright The Mbed TLS Contributors + * SPDX-License-Identifier: Apache-2.0 OR GPL-2.0-or-later + */ +#ifndef MBEDTLS_X509_INTERNAL_H +#define MBEDTLS_X509_INTERNAL_H +#include "mbedtls/private_access.h" + +#include "mbedtls/build_info.h" + +#include "mbedtls/x509.h" +#include "mbedtls/asn1.h" +#include "pk_internal.h" + +#if defined(MBEDTLS_RSA_C) +#include "mbedtls/rsa.h" +#endif + +int mbedtls_x509_get_name(unsigned char **p, const unsigned char *end, + mbedtls_x509_name *cur); +int mbedtls_x509_get_alg_null(unsigned char **p, const unsigned char *end, + mbedtls_x509_buf *alg); +int mbedtls_x509_get_alg(unsigned char **p, const unsigned char *end, + mbedtls_x509_buf *alg, mbedtls_x509_buf *params); +#if defined(MBEDTLS_X509_RSASSA_PSS_SUPPORT) +int mbedtls_x509_get_rsassa_pss_params(const mbedtls_x509_buf *params, + mbedtls_md_type_t *md_alg, mbedtls_md_type_t *mgf_md, + int *salt_len); +#endif +int mbedtls_x509_get_sig(unsigned char **p, const unsigned char *end, mbedtls_x509_buf *sig); +int mbedtls_x509_get_sig_alg(const mbedtls_x509_buf *sig_oid, const mbedtls_x509_buf *sig_params, + mbedtls_md_type_t *md_alg, mbedtls_pk_type_t *pk_alg, + void **sig_opts); +int mbedtls_x509_get_time(unsigned char **p, const unsigned char *end, + mbedtls_x509_time *t); +int mbedtls_x509_get_serial(unsigned char **p, const unsigned char *end, + mbedtls_x509_buf *serial); +int mbedtls_x509_get_ext(unsigned char **p, const unsigned char *end, + mbedtls_x509_buf *ext, int tag); +#if !defined(MBEDTLS_X509_REMOVE_INFO) +int mbedtls_x509_sig_alg_gets(char *buf, size_t size, const mbedtls_x509_buf *sig_oid, + mbedtls_pk_type_t pk_alg, mbedtls_md_type_t md_alg, + const void *sig_opts); +#endif +int mbedtls_x509_key_size_helper(char *buf, size_t buf_size, const char *name); +int mbedtls_x509_set_extension(mbedtls_asn1_named_data **head, const char *oid, size_t oid_len, + int critical, const unsigned char *val, + size_t val_len); +int mbedtls_x509_write_extensions(unsigned char **p, unsigned char *start, + mbedtls_asn1_named_data *first); +int mbedtls_x509_write_names(unsigned char **p, unsigned char *start, + mbedtls_asn1_named_data *first); +int mbedtls_x509_write_sig(unsigned char **p, unsigned char *start, + const char *oid, size_t oid_len, + unsigned char *sig, size_t size, + mbedtls_pk_type_t pk_alg); +int mbedtls_x509_get_ns_cert_type(unsigned char **p, + const unsigned char *end, + unsigned char *ns_cert_type); +int mbedtls_x509_get_key_usage(unsigned char **p, + const unsigned char *end, + unsigned int *key_usage); +int mbedtls_x509_get_subject_alt_name(unsigned char **p, + const unsigned char *end, + mbedtls_x509_sequence *subject_alt_name); +int mbedtls_x509_get_subject_alt_name_ext(unsigned char **p, + const unsigned char *end, + mbedtls_x509_sequence *subject_alt_name); +int mbedtls_x509_info_subject_alt_name(char **buf, size_t *size, + const mbedtls_x509_sequence + *subject_alt_name, + const char *prefix); +int mbedtls_x509_info_cert_type(char **buf, size_t *size, + unsigned char ns_cert_type); +int mbedtls_x509_info_key_usage(char **buf, size_t *size, + unsigned int key_usage); + +int mbedtls_x509_write_set_san_common(mbedtls_asn1_named_data **extensions, + const mbedtls_x509_san_list *san_list); + +#endif /* MBEDTLS_X509_INTERNAL_H */ diff --git a/vendor/mbedtls/library/x509write.c b/vendor/mbedtls/library/x509write.c new file mode 100644 index 0000000000..4704900d38 --- /dev/null +++ b/vendor/mbedtls/library/x509write.c @@ -0,0 +1,174 @@ +/* + * X.509 internal, common functions for writing + * + * Copyright The Mbed TLS Contributors + * SPDX-License-Identifier: Apache-2.0 OR GPL-2.0-or-later + */ +#include "common.h" +#if defined(MBEDTLS_X509_CSR_WRITE_C) || defined(MBEDTLS_X509_CRT_WRITE_C) + +#include "mbedtls/x509_crt.h" +#include "x509_internal.h" +#include "mbedtls/asn1write.h" +#include "mbedtls/error.h" +#include "mbedtls/oid.h" +#include "mbedtls/platform.h" +#include "mbedtls/platform_util.h" + +#include +#include + +#if defined(MBEDTLS_PEM_WRITE_C) +#include "mbedtls/pem.h" +#endif /* MBEDTLS_PEM_WRITE_C */ + +#if defined(MBEDTLS_USE_PSA_CRYPTO) +#include "psa/crypto.h" +#include "mbedtls/psa_util.h" +#include "md_psa.h" +#endif /* MBEDTLS_USE_PSA_CRYPTO */ + +#define CHECK_OVERFLOW_ADD(a, b) \ + do \ + { \ + if (a > SIZE_MAX - (b)) \ + { \ + return MBEDTLS_ERR_X509_BAD_INPUT_DATA; \ + } \ + a += b; \ + } while (0) + +int mbedtls_x509_write_set_san_common(mbedtls_asn1_named_data **extensions, + const mbedtls_x509_san_list *san_list) +{ + int ret = 0; + const mbedtls_x509_san_list *cur; + unsigned char *buf; + unsigned char *p; + size_t len; + size_t buflen = 0; + + /* Determine the maximum size of the SubjectAltName list */ + for (cur = san_list; cur != NULL; cur = cur->next) { + /* Calculate size of the required buffer */ + switch (cur->node.type) { + case MBEDTLS_X509_SAN_DNS_NAME: + case MBEDTLS_X509_SAN_UNIFORM_RESOURCE_IDENTIFIER: + case MBEDTLS_X509_SAN_IP_ADDRESS: + case MBEDTLS_X509_SAN_RFC822_NAME: + /* length of value for each name entry, + * maximum 4 bytes for the length field, + * 1 byte for the tag/type. + */ + CHECK_OVERFLOW_ADD(buflen, cur->node.san.unstructured_name.len); + CHECK_OVERFLOW_ADD(buflen, 4 + 1); + break; + case MBEDTLS_X509_SAN_DIRECTORY_NAME: + { + const mbedtls_asn1_named_data *chunk = &cur->node.san.directory_name; + while (chunk != NULL) { + // Max 4 bytes for length, +1 for tag, + // additional 4 max for length, +1 for tag. + // See x509_write_name for more information. + CHECK_OVERFLOW_ADD(buflen, 4 + 1 + 4 + 1); + CHECK_OVERFLOW_ADD(buflen, chunk->oid.len); + CHECK_OVERFLOW_ADD(buflen, chunk->val.len); + chunk = chunk->next; + } + CHECK_OVERFLOW_ADD(buflen, 4 + 1); + break; + } + default: + /* Not supported - return. */ + return MBEDTLS_ERR_X509_FEATURE_UNAVAILABLE; + } + } + + /* Add the extra length field and tag */ + CHECK_OVERFLOW_ADD(buflen, 4 + 1); + + /* Allocate buffer */ + buf = mbedtls_calloc(1, buflen); + if (buf == NULL) { + return MBEDTLS_ERR_ASN1_ALLOC_FAILED; + } + p = buf + buflen; + + /* Write ASN.1-based structure */ + cur = san_list; + len = 0; + while (cur != NULL) { + size_t single_san_len = 0; + switch (cur->node.type) { + case MBEDTLS_X509_SAN_DNS_NAME: + case MBEDTLS_X509_SAN_RFC822_NAME: + case MBEDTLS_X509_SAN_UNIFORM_RESOURCE_IDENTIFIER: + case MBEDTLS_X509_SAN_IP_ADDRESS: + { + const unsigned char *unstructured_name = + (const unsigned char *) cur->node.san.unstructured_name.p; + size_t unstructured_name_len = cur->node.san.unstructured_name.len; + + MBEDTLS_ASN1_CHK_CLEANUP_ADD(single_san_len, + mbedtls_asn1_write_raw_buffer( + &p, buf, + unstructured_name, unstructured_name_len)); + MBEDTLS_ASN1_CHK_CLEANUP_ADD(single_san_len, mbedtls_asn1_write_len( + &p, buf, unstructured_name_len)); + MBEDTLS_ASN1_CHK_CLEANUP_ADD(single_san_len, + mbedtls_asn1_write_tag( + &p, buf, + MBEDTLS_ASN1_CONTEXT_SPECIFIC | cur->node.type)); + } + break; + case MBEDTLS_X509_SAN_DIRECTORY_NAME: + MBEDTLS_ASN1_CHK_CLEANUP_ADD(single_san_len, + mbedtls_x509_write_names(&p, buf, + (mbedtls_asn1_named_data *) & + cur->node + .san.directory_name)); + MBEDTLS_ASN1_CHK_CLEANUP_ADD(single_san_len, + mbedtls_asn1_write_len(&p, buf, single_san_len)); + MBEDTLS_ASN1_CHK_CLEANUP_ADD(single_san_len, + mbedtls_asn1_write_tag(&p, buf, + MBEDTLS_ASN1_CONTEXT_SPECIFIC | + MBEDTLS_ASN1_CONSTRUCTED | + MBEDTLS_X509_SAN_DIRECTORY_NAME)); + break; + default: + /* Error out on an unsupported SAN */ + ret = MBEDTLS_ERR_X509_FEATURE_UNAVAILABLE; + goto cleanup; + } + cur = cur->next; + /* check for overflow */ + if (len > SIZE_MAX - single_san_len) { + ret = MBEDTLS_ERR_X509_BAD_INPUT_DATA; + goto cleanup; + } + len += single_san_len; + } + + MBEDTLS_ASN1_CHK_CLEANUP_ADD(len, mbedtls_asn1_write_len(&p, buf, len)); + MBEDTLS_ASN1_CHK_CLEANUP_ADD(len, + mbedtls_asn1_write_tag(&p, buf, + MBEDTLS_ASN1_CONSTRUCTED | + MBEDTLS_ASN1_SEQUENCE)); + + ret = mbedtls_x509_set_extension(extensions, + MBEDTLS_OID_SUBJECT_ALT_NAME, + MBEDTLS_OID_SIZE(MBEDTLS_OID_SUBJECT_ALT_NAME), + 0, + buf + buflen - len, len); + + /* If we exceeded the allocated buffer it means that maximum size of the SubjectAltName list + * was incorrectly calculated and memory is corrupted. */ + if (p < buf) { + ret = MBEDTLS_ERR_ASN1_LENGTH_MISMATCH; + } +cleanup: + mbedtls_free(buf); + return ret; +} + +#endif /* MBEDTLS_X509_CSR_WRITE_C || MBEDTLS_X509_CRT_WRITE_C */ diff --git a/vendor/mbedtls/library/x509write_crt.c b/vendor/mbedtls/library/x509write_crt.c index e9944110e7..72f5a10a17 100644 --- a/vendor/mbedtls/library/x509write_crt.c +++ b/vendor/mbedtls/library/x509write_crt.c @@ -2,19 +2,7 @@ * X.509 certificate writing * * Copyright The Mbed TLS Contributors - * SPDX-License-Identifier: Apache-2.0 - * - * Licensed under the Apache License, Version 2.0 (the "License"); you may - * not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT - * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. + * SPDX-License-Identifier: Apache-2.0 OR GPL-2.0-or-later */ /* * References: @@ -28,30 +16,36 @@ #if defined(MBEDTLS_X509_CRT_WRITE_C) #include "mbedtls/x509_crt.h" +#include "x509_internal.h" #include "mbedtls/asn1write.h" #include "mbedtls/error.h" #include "mbedtls/oid.h" +#include "mbedtls/platform.h" #include "mbedtls/platform_util.h" -#include "mbedtls/sha1.h" +#include "mbedtls/md.h" #include +#include #if defined(MBEDTLS_PEM_WRITE_C) #include "mbedtls/pem.h" #endif /* MBEDTLS_PEM_WRITE_C */ +#if defined(MBEDTLS_USE_PSA_CRYPTO) +#include "psa/crypto.h" +#include "psa_util_internal.h" +#include "mbedtls/psa_util.h" +#endif /* MBEDTLS_USE_PSA_CRYPTO */ + void mbedtls_x509write_crt_init(mbedtls_x509write_cert *ctx) { memset(ctx, 0, sizeof(mbedtls_x509write_cert)); - mbedtls_mpi_init(&ctx->serial); ctx->version = MBEDTLS_X509_CRT_VERSION_3; } void mbedtls_x509write_crt_free(mbedtls_x509write_cert *ctx) { - mbedtls_mpi_free(&ctx->serial); - mbedtls_asn1_free_named_data_list(&ctx->subject); mbedtls_asn1_free_named_data_list(&ctx->issuer); mbedtls_asn1_free_named_data_list(&ctx->extensions); @@ -95,21 +89,42 @@ int mbedtls_x509write_crt_set_issuer_name(mbedtls_x509write_cert *ctx, return mbedtls_x509_string_to_names(&ctx->issuer, issuer_name); } +#if defined(MBEDTLS_BIGNUM_C) && !defined(MBEDTLS_DEPRECATED_REMOVED) int mbedtls_x509write_crt_set_serial(mbedtls_x509write_cert *ctx, const mbedtls_mpi *serial) { - int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED; + int ret; + size_t tmp_len; - if (mbedtls_mpi_size(serial) > MBEDTLS_X509_RFC5280_MAX_SERIAL_LEN) { + /* Ensure that the MPI value fits into the buffer */ + tmp_len = mbedtls_mpi_size(serial); + if (tmp_len > MBEDTLS_X509_RFC5280_MAX_SERIAL_LEN) { return MBEDTLS_ERR_X509_BAD_INPUT_DATA; } - if ((ret = mbedtls_mpi_copy(&ctx->serial, serial)) != 0) { + ctx->serial_len = tmp_len; + + ret = mbedtls_mpi_write_binary(serial, ctx->serial, tmp_len); + if (ret < 0) { return ret; } return 0; } +#endif // MBEDTLS_BIGNUM_C && !MBEDTLS_DEPRECATED_REMOVED + +int mbedtls_x509write_crt_set_serial_raw(mbedtls_x509write_cert *ctx, + unsigned char *serial, size_t serial_len) +{ + if (serial_len > MBEDTLS_X509_RFC5280_MAX_SERIAL_LEN) { + return MBEDTLS_ERR_X509_BAD_INPUT_DATA; + } + + ctx->serial_len = serial_len; + memcpy(ctx->serial, serial, serial_len); + + return 0; +} int mbedtls_x509write_crt_set_validity(mbedtls_x509write_cert *ctx, const char *not_before, @@ -127,6 +142,13 @@ int mbedtls_x509write_crt_set_validity(mbedtls_x509write_cert *ctx, return 0; } +int mbedtls_x509write_crt_set_subject_alternative_name(mbedtls_x509write_cert *ctx, + const mbedtls_x509_san_list *san_list) +{ + return mbedtls_x509_write_set_san_common(&ctx->extensions, san_list); +} + + int mbedtls_x509write_crt_set_extension(mbedtls_x509write_cert *ctx, const char *oid, size_t oid_len, int critical, @@ -169,71 +191,92 @@ int mbedtls_x509write_crt_set_basic_constraints(mbedtls_x509write_cert *ctx, is_ca, buf + sizeof(buf) - len, len); } -#if defined(MBEDTLS_SHA1_C) -int mbedtls_x509write_crt_set_subject_key_identifier(mbedtls_x509write_cert *ctx) +#if defined(MBEDTLS_MD_CAN_SHA1) +static int mbedtls_x509write_crt_set_key_identifier(mbedtls_x509write_cert *ctx, + int is_ca, + unsigned char tag) { int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED; unsigned char buf[MBEDTLS_MPI_MAX_SIZE * 2 + 20]; /* tag, length + 2xMPI */ unsigned char *c = buf + sizeof(buf); size_t len = 0; +#if defined(MBEDTLS_USE_PSA_CRYPTO) + psa_status_t status = PSA_ERROR_CORRUPTION_DETECTED; + size_t hash_length; +#endif /* MBEDTLS_USE_PSA_CRYPTO */ memset(buf, 0, sizeof(buf)); MBEDTLS_ASN1_CHK_ADD(len, - mbedtls_pk_write_pubkey(&c, buf, ctx->subject_key)); - - ret = mbedtls_sha1_ret(buf + sizeof(buf) - len, len, - buf + sizeof(buf) - 20); + mbedtls_pk_write_pubkey(&c, + buf, + is_ca ? + ctx->issuer_key : + ctx->subject_key)); + + +#if defined(MBEDTLS_USE_PSA_CRYPTO) + status = psa_hash_compute(PSA_ALG_SHA_1, + buf + sizeof(buf) - len, + len, + buf + sizeof(buf) - 20, + 20, + &hash_length); + if (status != PSA_SUCCESS) { + return MBEDTLS_ERR_PLATFORM_HW_ACCEL_FAILED; + } +#else + ret = mbedtls_md(mbedtls_md_info_from_type(MBEDTLS_MD_SHA1), + buf + sizeof(buf) - len, len, + buf + sizeof(buf) - 20); if (ret != 0) { return ret; } +#endif /* MBEDTLS_USE_PSA_CRYPTO */ + c = buf + sizeof(buf) - 20; len = 20; MBEDTLS_ASN1_CHK_ADD(len, mbedtls_asn1_write_len(&c, buf, len)); - MBEDTLS_ASN1_CHK_ADD(len, - mbedtls_asn1_write_tag(&c, buf, MBEDTLS_ASN1_OCTET_STRING)); - - return mbedtls_x509write_crt_set_extension(ctx, - MBEDTLS_OID_SUBJECT_KEY_IDENTIFIER, - MBEDTLS_OID_SIZE(MBEDTLS_OID_SUBJECT_KEY_IDENTIFIER), - 0, buf + sizeof(buf) - len, len); -} - -int mbedtls_x509write_crt_set_authority_key_identifier(mbedtls_x509write_cert *ctx) -{ - int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED; - unsigned char buf[MBEDTLS_MPI_MAX_SIZE * 2 + 20]; /* tag, length + 2xMPI */ - unsigned char *c = buf + sizeof(buf); - size_t len = 0; - - memset(buf, 0, sizeof(buf)); - MBEDTLS_ASN1_CHK_ADD(len, - mbedtls_pk_write_pubkey(&c, buf, ctx->issuer_key)); + MBEDTLS_ASN1_CHK_ADD(len, mbedtls_asn1_write_tag(&c, buf, tag)); - ret = mbedtls_sha1_ret(buf + sizeof(buf) - len, len, - buf + sizeof(buf) - 20); - if (ret != 0) { - return ret; + if (is_ca) { // writes AuthorityKeyIdentifier sequence + MBEDTLS_ASN1_CHK_ADD(len, mbedtls_asn1_write_len(&c, buf, len)); + MBEDTLS_ASN1_CHK_ADD(len, + mbedtls_asn1_write_tag(&c, + buf, + MBEDTLS_ASN1_CONSTRUCTED | + MBEDTLS_ASN1_SEQUENCE)); } - c = buf + sizeof(buf) - 20; - len = 20; - MBEDTLS_ASN1_CHK_ADD(len, mbedtls_asn1_write_len(&c, buf, len)); - MBEDTLS_ASN1_CHK_ADD(len, - mbedtls_asn1_write_tag(&c, buf, MBEDTLS_ASN1_CONTEXT_SPECIFIC | 0)); + if (is_ca) { + return mbedtls_x509write_crt_set_extension(ctx, + MBEDTLS_OID_AUTHORITY_KEY_IDENTIFIER, + MBEDTLS_OID_SIZE( + MBEDTLS_OID_AUTHORITY_KEY_IDENTIFIER), + 0, buf + sizeof(buf) - len, len); + } else { + return mbedtls_x509write_crt_set_extension(ctx, + MBEDTLS_OID_SUBJECT_KEY_IDENTIFIER, + MBEDTLS_OID_SIZE( + MBEDTLS_OID_SUBJECT_KEY_IDENTIFIER), + 0, buf + sizeof(buf) - len, len); + } +} - MBEDTLS_ASN1_CHK_ADD(len, mbedtls_asn1_write_len(&c, buf, len)); - MBEDTLS_ASN1_CHK_ADD(len, - mbedtls_asn1_write_tag(&c, buf, - MBEDTLS_ASN1_CONSTRUCTED | - MBEDTLS_ASN1_SEQUENCE)); +int mbedtls_x509write_crt_set_subject_key_identifier(mbedtls_x509write_cert *ctx) +{ + return mbedtls_x509write_crt_set_key_identifier(ctx, + 0, + MBEDTLS_ASN1_OCTET_STRING); +} - return mbedtls_x509write_crt_set_extension( - ctx, MBEDTLS_OID_AUTHORITY_KEY_IDENTIFIER, - MBEDTLS_OID_SIZE(MBEDTLS_OID_AUTHORITY_KEY_IDENTIFIER), - 0, buf + sizeof(buf) - len, len); +int mbedtls_x509write_crt_set_authority_key_identifier(mbedtls_x509write_cert *ctx) +{ + return mbedtls_x509write_crt_set_key_identifier(ctx, + 1, + (MBEDTLS_ASN1_CONTEXT_SPECIFIC | 0)); } -#endif /* MBEDTLS_SHA1_C */ +#endif /* MBEDTLS_MD_CAN_SHA1 */ int mbedtls_x509write_crt_set_key_usage(mbedtls_x509write_cert *ctx, unsigned int key_usage) @@ -276,6 +319,47 @@ int mbedtls_x509write_crt_set_key_usage(mbedtls_x509write_cert *ctx, return 0; } +int mbedtls_x509write_crt_set_ext_key_usage(mbedtls_x509write_cert *ctx, + const mbedtls_asn1_sequence *exts) +{ + unsigned char buf[256]; + unsigned char *c = buf + sizeof(buf); + int ret; + size_t len = 0; + const mbedtls_asn1_sequence *last_ext = NULL; + const mbedtls_asn1_sequence *ext; + + memset(buf, 0, sizeof(buf)); + + /* We need at least one extension: SEQUENCE SIZE (1..MAX) OF KeyPurposeId */ + if (exts == NULL) { + return MBEDTLS_ERR_X509_BAD_INPUT_DATA; + } + + /* Iterate over exts backwards, so we write them out in the requested order */ + while (last_ext != exts) { + for (ext = exts; ext->next != last_ext; ext = ext->next) { + } + if (ext->buf.tag != MBEDTLS_ASN1_OID) { + return MBEDTLS_ERR_X509_BAD_INPUT_DATA; + } + MBEDTLS_ASN1_CHK_ADD(len, mbedtls_asn1_write_raw_buffer(&c, buf, ext->buf.p, ext->buf.len)); + MBEDTLS_ASN1_CHK_ADD(len, mbedtls_asn1_write_len(&c, buf, ext->buf.len)); + MBEDTLS_ASN1_CHK_ADD(len, mbedtls_asn1_write_tag(&c, buf, MBEDTLS_ASN1_OID)); + last_ext = ext; + } + + MBEDTLS_ASN1_CHK_ADD(len, mbedtls_asn1_write_len(&c, buf, len)); + MBEDTLS_ASN1_CHK_ADD(len, + mbedtls_asn1_write_tag(&c, buf, + MBEDTLS_ASN1_CONSTRUCTED | MBEDTLS_ASN1_SEQUENCE)); + + return mbedtls_x509write_crt_set_extension(ctx, + MBEDTLS_OID_EXTENDED_KEY_USAGE, + MBEDTLS_OID_SIZE(MBEDTLS_OID_EXTENDED_KEY_USAGE), + 1, c, len); +} + int mbedtls_x509write_crt_set_ns_cert_type(mbedtls_x509write_cert *ctx, unsigned char ns_cert_type) { @@ -337,8 +421,14 @@ int mbedtls_x509write_crt_der(mbedtls_x509write_cert *ctx, const char *sig_oid; size_t sig_oid_len = 0; unsigned char *c, *c2; - unsigned char hash[64]; unsigned char sig[MBEDTLS_PK_SIGNATURE_MAX_SIZE]; + size_t hash_length = 0; + unsigned char hash[MBEDTLS_MD_MAX_SIZE]; +#if defined(MBEDTLS_USE_PSA_CRYPTO) + psa_status_t status = PSA_ERROR_CORRUPTION_DETECTED; + psa_algorithm_t psa_algorithm; +#endif /* MBEDTLS_USE_PSA_CRYPTO */ + size_t sub_len = 0, pub_len = 0, sig_and_oid_len = 0, sig_len; size_t len = 0; mbedtls_pk_type_t pk_alg; @@ -392,7 +482,7 @@ int mbedtls_x509write_crt_der(mbedtls_x509write_cert *ctx, */ MBEDTLS_ASN1_CHK_ADD(pub_len, mbedtls_pk_write_pubkey_der(ctx->subject_key, - buf, c - buf)); + buf, (size_t) (c - buf))); c -= pub_len; len += pub_len; @@ -451,9 +541,29 @@ int mbedtls_x509write_crt_der(mbedtls_x509write_cert *ctx, /* * Serial ::= INTEGER + * + * Written data is: + * - "ctx->serial_len" bytes for the raw serial buffer + * - if MSb of "serial" is 1, then prepend an extra 0x00 byte + * - 1 byte for the length + * - 1 byte for the TAG */ - MBEDTLS_ASN1_CHK_ADD(len, mbedtls_asn1_write_mpi(&c, buf, - &ctx->serial)); + MBEDTLS_ASN1_CHK_ADD(len, mbedtls_asn1_write_raw_buffer(&c, buf, + ctx->serial, ctx->serial_len)); + if (*c & 0x80) { + if (c - buf < 1) { + return MBEDTLS_ERR_X509_BUFFER_TOO_SMALL; + } + *(--c) = 0x0; + len++; + MBEDTLS_ASN1_CHK_ADD(len, mbedtls_asn1_write_len(&c, buf, + ctx->serial_len + 1)); + } else { + MBEDTLS_ASN1_CHK_ADD(len, mbedtls_asn1_write_len(&c, buf, + ctx->serial_len)); + } + MBEDTLS_ASN1_CHK_ADD(len, mbedtls_asn1_write_tag(&c, buf, + MBEDTLS_ASN1_INTEGER)); /* * Version ::= INTEGER { v1(0), v2(1), v3(2) } @@ -483,13 +593,28 @@ int mbedtls_x509write_crt_der(mbedtls_x509write_cert *ctx, */ /* Compute hash of CRT. */ +#if defined(MBEDTLS_USE_PSA_CRYPTO) + psa_algorithm = mbedtls_md_psa_alg_from_type(ctx->md_alg); + + status = psa_hash_compute(psa_algorithm, + c, + len, + hash, + sizeof(hash), + &hash_length); + if (status != PSA_SUCCESS) { + return MBEDTLS_ERR_PLATFORM_HW_ACCEL_FAILED; + } +#else if ((ret = mbedtls_md(mbedtls_md_info_from_type(ctx->md_alg), c, len, hash)) != 0) { return ret; } +#endif /* MBEDTLS_USE_PSA_CRYPTO */ + if ((ret = mbedtls_pk_sign(ctx->issuer_key, ctx->md_alg, - hash, 0, sig, &sig_len, + hash, hash_length, sig, sizeof(sig), &sig_len, f_rng, p_rng)) != 0) { return ret; } diff --git a/vendor/mbedtls/library/x509write_csr.c b/vendor/mbedtls/library/x509write_csr.c index 178b166df1..d3ddbcc03d 100644 --- a/vendor/mbedtls/library/x509write_csr.c +++ b/vendor/mbedtls/library/x509write_csr.c @@ -2,19 +2,7 @@ * X.509 Certificate Signing Request writing * * Copyright The Mbed TLS Contributors - * SPDX-License-Identifier: Apache-2.0 - * - * Licensed under the Apache License, Version 2.0 (the "License"); you may - * not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT - * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. + * SPDX-License-Identifier: Apache-2.0 OR GPL-2.0-or-later */ /* * References: @@ -26,6 +14,7 @@ #if defined(MBEDTLS_X509_CSR_WRITE_C) +#include "x509_internal.h" #include "mbedtls/x509_csr.h" #include "mbedtls/asn1write.h" #include "mbedtls/error.h" @@ -34,8 +23,9 @@ #if defined(MBEDTLS_USE_PSA_CRYPTO) #include "psa/crypto.h" +#include "psa_util_internal.h" #include "mbedtls/psa_util.h" -#endif +#endif /* MBEDTLS_USE_PSA_CRYPTO */ #include #include @@ -77,10 +67,17 @@ int mbedtls_x509write_csr_set_subject_name(mbedtls_x509write_csr *ctx, int mbedtls_x509write_csr_set_extension(mbedtls_x509write_csr *ctx, const char *oid, size_t oid_len, + int critical, const unsigned char *val, size_t val_len) { return mbedtls_x509_set_extension(&ctx->extensions, oid, oid_len, - 0, val, val_len); + critical, val, val_len); +} + +int mbedtls_x509write_csr_set_subject_alternative_name(mbedtls_x509write_csr *ctx, + const mbedtls_x509_san_list *san_list) +{ + return mbedtls_x509_write_set_san_common(&ctx->extensions, san_list); } int mbedtls_x509write_csr_set_key_usage(mbedtls_x509write_csr *ctx, unsigned char key_usage) @@ -98,7 +95,7 @@ int mbedtls_x509write_csr_set_key_usage(mbedtls_x509write_csr *ctx, unsigned cha ret = mbedtls_x509write_csr_set_extension(ctx, MBEDTLS_OID_KEY_USAGE, MBEDTLS_OID_SIZE(MBEDTLS_OID_KEY_USAGE), - c, (size_t) ret); + 0, c, (size_t) ret); if (ret != 0) { return ret; } @@ -122,7 +119,7 @@ int mbedtls_x509write_csr_set_ns_cert_type(mbedtls_x509write_csr *ctx, ret = mbedtls_x509write_csr_set_extension(ctx, MBEDTLS_OID_NS_CERT_TYPE, MBEDTLS_OID_SIZE(MBEDTLS_OID_NS_CERT_TYPE), - c, (size_t) ret); + 0, c, (size_t) ret); if (ret != 0) { return ret; } @@ -133,7 +130,7 @@ int mbedtls_x509write_csr_set_ns_cert_type(mbedtls_x509write_csr *ctx, static int x509write_csr_der_internal(mbedtls_x509write_csr *ctx, unsigned char *buf, size_t size, - unsigned char *sig, + unsigned char *sig, size_t sig_size, int (*f_rng)(void *, unsigned char *, size_t), void *p_rng) { @@ -141,14 +138,13 @@ static int x509write_csr_der_internal(mbedtls_x509write_csr *ctx, const char *sig_oid; size_t sig_oid_len = 0; unsigned char *c, *c2; - unsigned char hash[64]; + unsigned char hash[MBEDTLS_MD_MAX_SIZE]; size_t pub_len = 0, sig_and_oid_len = 0, sig_len; size_t len = 0; mbedtls_pk_type_t pk_alg; #if defined(MBEDTLS_USE_PSA_CRYPTO) - psa_hash_operation_t hash_operation = PSA_HASH_OPERATION_INIT; size_t hash_len; - psa_algorithm_t hash_alg = mbedtls_psa_translate_md(ctx->md_alg); + psa_algorithm_t hash_alg = mbedtls_md_psa_alg_from_type(ctx->md_alg); #endif /* MBEDTLS_USE_PSA_CRYPTO */ /* Write the CSR backwards starting from the end of buf */ @@ -189,7 +185,7 @@ static int x509write_csr_der_internal(mbedtls_x509write_csr *ctx, MBEDTLS_ASN1_CONSTRUCTED | MBEDTLS_ASN1_CONTEXT_SPECIFIC)); MBEDTLS_ASN1_CHK_ADD(pub_len, mbedtls_pk_write_pubkey_der(ctx->key, - buf, c - buf)); + buf, (size_t) (c - buf))); c -= pub_len; len += pub_len; @@ -215,17 +211,13 @@ static int x509write_csr_der_internal(mbedtls_x509write_csr *ctx, * Note: hash errors can happen only after an internal error */ #if defined(MBEDTLS_USE_PSA_CRYPTO) - if (psa_hash_setup(&hash_operation, hash_alg) != PSA_SUCCESS) { - return MBEDTLS_ERR_X509_FATAL_ERROR; - } - - if (psa_hash_update(&hash_operation, c, len) != PSA_SUCCESS) { - return MBEDTLS_ERR_X509_FATAL_ERROR; - } - - if (psa_hash_finish(&hash_operation, hash, sizeof(hash), &hash_len) - != PSA_SUCCESS) { - return MBEDTLS_ERR_X509_FATAL_ERROR; + if (psa_hash_compute(hash_alg, + c, + len, + hash, + sizeof(hash), + &hash_len) != PSA_SUCCESS) { + return MBEDTLS_ERR_PLATFORM_HW_ACCEL_FAILED; } #else /* MBEDTLS_USE_PSA_CRYPTO */ ret = mbedtls_md(mbedtls_md_info_from_type(ctx->md_alg), c, len, hash); @@ -233,7 +225,8 @@ static int x509write_csr_der_internal(mbedtls_x509write_csr *ctx, return ret; } #endif - if ((ret = mbedtls_pk_sign(ctx->key, ctx->md_alg, hash, 0, sig, &sig_len, + if ((ret = mbedtls_pk_sign(ctx->key, ctx->md_alg, hash, 0, + sig, sig_size, &sig_len, f_rng, p_rng)) != 0) { return ret; } @@ -283,7 +276,7 @@ static int x509write_csr_der_internal(mbedtls_x509write_csr *ctx, MBEDTLS_ASN1_CONSTRUCTED | MBEDTLS_ASN1_SEQUENCE)); /* Zero the unused bytes at the start of buf */ - memset(buf, 0, c2 - buf); + memset(buf, 0, (size_t) (c2 - buf)); return (int) len; } @@ -300,7 +293,9 @@ int mbedtls_x509write_csr_der(mbedtls_x509write_csr *ctx, unsigned char *buf, return MBEDTLS_ERR_X509_ALLOC_FAILED; } - ret = x509write_csr_der_internal(ctx, buf, size, sig, f_rng, p_rng); + ret = x509write_csr_der_internal(ctx, buf, size, + sig, MBEDTLS_PK_SIGNATURE_MAX_SIZE, + f_rng, p_rng); mbedtls_free(sig); diff --git a/vendor/mbedtls/library/xtea.c b/vendor/mbedtls/library/xtea.c deleted file mode 100644 index 27651cc0e5..0000000000 --- a/vendor/mbedtls/library/xtea.c +++ /dev/null @@ -1,236 +0,0 @@ -/* - * A 32-bit implementation of the XTEA algorithm - * - * Copyright The Mbed TLS Contributors - * SPDX-License-Identifier: Apache-2.0 - * - * Licensed under the Apache License, Version 2.0 (the "License"); you may - * not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT - * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -#include "common.h" - -#if defined(MBEDTLS_XTEA_C) - -#include "mbedtls/xtea.h" -#include "mbedtls/platform_util.h" - -#include - -#include "mbedtls/platform.h" - -#if !defined(MBEDTLS_XTEA_ALT) - -void mbedtls_xtea_init(mbedtls_xtea_context *ctx) -{ - memset(ctx, 0, sizeof(mbedtls_xtea_context)); -} - -void mbedtls_xtea_free(mbedtls_xtea_context *ctx) -{ - if (ctx == NULL) { - return; - } - - mbedtls_platform_zeroize(ctx, sizeof(mbedtls_xtea_context)); -} - -/* - * XTEA key schedule - */ -void mbedtls_xtea_setup(mbedtls_xtea_context *ctx, const unsigned char key[16]) -{ - int i; - - memset(ctx, 0, sizeof(mbedtls_xtea_context)); - - for (i = 0; i < 4; i++) { - ctx->k[i] = MBEDTLS_GET_UINT32_BE(key, i << 2); - } -} - -/* - * XTEA encrypt function - */ -int mbedtls_xtea_crypt_ecb(mbedtls_xtea_context *ctx, int mode, - const unsigned char input[8], unsigned char output[8]) -{ - uint32_t *k, v0, v1, i; - - k = ctx->k; - - v0 = MBEDTLS_GET_UINT32_BE(input, 0); - v1 = MBEDTLS_GET_UINT32_BE(input, 4); - - if (mode == MBEDTLS_XTEA_ENCRYPT) { - uint32_t sum = 0, delta = 0x9E3779B9; - - for (i = 0; i < 32; i++) { - v0 += (((v1 << 4) ^ (v1 >> 5)) + v1) ^ (sum + k[sum & 3]); - sum += delta; - v1 += (((v0 << 4) ^ (v0 >> 5)) + v0) ^ (sum + k[(sum>>11) & 3]); - } - } else { /* MBEDTLS_XTEA_DECRYPT */ - uint32_t delta = 0x9E3779B9, sum = delta * 32; - - for (i = 0; i < 32; i++) { - v1 -= (((v0 << 4) ^ (v0 >> 5)) + v0) ^ (sum + k[(sum>>11) & 3]); - sum -= delta; - v0 -= (((v1 << 4) ^ (v1 >> 5)) + v1) ^ (sum + k[sum & 3]); - } - } - - MBEDTLS_PUT_UINT32_BE(v0, output, 0); - MBEDTLS_PUT_UINT32_BE(v1, output, 4); - - return 0; -} - -#if defined(MBEDTLS_CIPHER_MODE_CBC) -/* - * XTEA-CBC buffer encryption/decryption - */ -int mbedtls_xtea_crypt_cbc(mbedtls_xtea_context *ctx, int mode, size_t length, - unsigned char iv[8], const unsigned char *input, - unsigned char *output) -{ - int i; - unsigned char temp[8]; - - if (length % 8) { - return MBEDTLS_ERR_XTEA_INVALID_INPUT_LENGTH; - } - - if (mode == MBEDTLS_XTEA_DECRYPT) { - while (length > 0) { - memcpy(temp, input, 8); - mbedtls_xtea_crypt_ecb(ctx, mode, input, output); - - for (i = 0; i < 8; i++) { - output[i] = (unsigned char) (output[i] ^ iv[i]); - } - - memcpy(iv, temp, 8); - - input += 8; - output += 8; - length -= 8; - } - } else { - while (length > 0) { - for (i = 0; i < 8; i++) { - output[i] = (unsigned char) (input[i] ^ iv[i]); - } - - mbedtls_xtea_crypt_ecb(ctx, mode, output, output); - memcpy(iv, output, 8); - - input += 8; - output += 8; - length -= 8; - } - } - - return 0; -} -#endif /* MBEDTLS_CIPHER_MODE_CBC */ -#endif /* !MBEDTLS_XTEA_ALT */ - -#if defined(MBEDTLS_SELF_TEST) - -/* - * XTEA tests vectors (non-official) - */ - -static const unsigned char xtea_test_key[6][16] = -{ - { 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08, 0x09, 0x0a, 0x0b, - 0x0c, 0x0d, 0x0e, 0x0f }, - { 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08, 0x09, 0x0a, 0x0b, - 0x0c, 0x0d, 0x0e, 0x0f }, - { 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08, 0x09, 0x0a, 0x0b, - 0x0c, 0x0d, 0x0e, 0x0f }, - { 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00 }, - { 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00 }, - { 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00 } -}; - -static const unsigned char xtea_test_pt[6][8] = -{ - { 0x41, 0x42, 0x43, 0x44, 0x45, 0x46, 0x47, 0x48 }, - { 0x41, 0x41, 0x41, 0x41, 0x41, 0x41, 0x41, 0x41 }, - { 0x5a, 0x5b, 0x6e, 0x27, 0x89, 0x48, 0xd7, 0x7f }, - { 0x41, 0x42, 0x43, 0x44, 0x45, 0x46, 0x47, 0x48 }, - { 0x41, 0x41, 0x41, 0x41, 0x41, 0x41, 0x41, 0x41 }, - { 0x70, 0xe1, 0x22, 0x5d, 0x6e, 0x4e, 0x76, 0x55 } -}; - -static const unsigned char xtea_test_ct[6][8] = -{ - { 0x49, 0x7d, 0xf3, 0xd0, 0x72, 0x61, 0x2c, 0xb5 }, - { 0xe7, 0x8f, 0x2d, 0x13, 0x74, 0x43, 0x41, 0xd8 }, - { 0x41, 0x41, 0x41, 0x41, 0x41, 0x41, 0x41, 0x41 }, - { 0xa0, 0x39, 0x05, 0x89, 0xf8, 0xb8, 0xef, 0xa5 }, - { 0xed, 0x23, 0x37, 0x5a, 0x82, 0x1a, 0x8c, 0x2d }, - { 0x41, 0x41, 0x41, 0x41, 0x41, 0x41, 0x41, 0x41 } -}; - -/* - * Checkup routine - */ -int mbedtls_xtea_self_test(int verbose) -{ - int i, ret = 0; - unsigned char buf[8]; - mbedtls_xtea_context ctx; - - mbedtls_xtea_init(&ctx); - for (i = 0; i < 6; i++) { - if (verbose != 0) { - mbedtls_printf(" XTEA test #%d: ", i + 1); - } - - memcpy(buf, xtea_test_pt[i], 8); - - mbedtls_xtea_setup(&ctx, xtea_test_key[i]); - mbedtls_xtea_crypt_ecb(&ctx, MBEDTLS_XTEA_ENCRYPT, buf, buf); - - if (memcmp(buf, xtea_test_ct[i], 8) != 0) { - if (verbose != 0) { - mbedtls_printf("failed\n"); - } - - ret = 1; - goto exit; - } - - if (verbose != 0) { - mbedtls_printf("passed\n"); - } - } - - if (verbose != 0) { - mbedtls_printf("\n"); - } - -exit: - mbedtls_xtea_free(&ctx); - - return ret; -} - -#endif /* MBEDTLS_SELF_TEST */ - -#endif /* MBEDTLS_XTEA_C */ diff --git a/vendor/mbedtls/premake5.lua b/vendor/mbedtls/premake5.lua index a50c5121d4..167f777fbc 100644 --- a/vendor/mbedtls/premake5.lua +++ b/vendor/mbedtls/premake5.lua @@ -32,35 +32,40 @@ project "mbedtls" "3rdparty/everest/library/kremlib/FStar_UInt128_extracted.c", "3rdparty/everest/library/kremlib/FStar_UInt64_FStar_UInt32_FStar_UInt16_FStar_UInt8.c", "3rdparty/everest/library/legacy/Hacl_Curve25519.c", + "3rdparty/p256-m/p256-m/p256-m.c", + "3rdparty/p256-m/p256-m/p256-m.h", + "3rdparty/p256-m/p256-m_driver_entrypoints.c", + "3rdparty/p256-m/p256-m_driver_entrypoints.h", "configs/config-ccm-psk-dtls1_2.h", "configs/config-ccm-psk-tls1_2.h", - "configs/config-mini-tls1_1.h", + "configs/config-ccm-aes-sha256.h", "configs/config-no-entropy.h", "configs/config-suite-b.h", "configs/config-symmetric-only.h", - "configs/config-thread.h", + "configs/config-tfm.h", "include/mbedtls/aes.h", - "include/mbedtls/aesni.h", - "include/mbedtls/arc4.h", "include/mbedtls/aria.h", "include/mbedtls/asn1.h", "include/mbedtls/asn1write.h", "include/mbedtls/base64.h", "include/mbedtls/bignum.h", - "include/mbedtls/blowfish.h", - "include/mbedtls/bn_mul.h", + "include/mbedtls/block_cipher.h", + "include/mbedtls/build_info.h", "include/mbedtls/camellia.h", "include/mbedtls/ccm.h", - "include/mbedtls/certs.h", "include/mbedtls/chacha20.h", "include/mbedtls/chachapoly.h", "include/mbedtls/check_config.h", "include/mbedtls/cipher.h", - "include/mbedtls/cipher_internal.h", "include/mbedtls/cmac.h", - "include/mbedtls/compat-1.3.h", - "include/mbedtls/config.h", + "include/mbedtls/compat-2.x.h", "include/mbedtls/config_psa.h", + "include/mbedtls/config_adjust_legacy_crypto.h", + "include/mbedtls/config_adjust_legacy_from_psa.h", + "include/mbedtls/config_adjust_psa_from_legacy.h", + "include/mbedtls/config_adjust_psa_superset_legacy.h", + "include/mbedtls/config_adjust_ssl.h", + "include/mbedtls/config_adjust_x509.h", "include/mbedtls/constant_time.h", "include/mbedtls/ctr_drbg.h", "include/mbedtls/debug.h", @@ -70,47 +75,40 @@ project "mbedtls" "include/mbedtls/ecdsa.h", "include/mbedtls/ecjpake.h", "include/mbedtls/ecp.h", - "include/mbedtls/ecp_internal.h", "include/mbedtls/entropy.h", - "include/mbedtls/entropy_poll.h", "include/mbedtls/error.h", "include/mbedtls/gcm.h", - "include/mbedtls/havege.h", "include/mbedtls/hkdf.h", "include/mbedtls/hmac_drbg.h", + "include/mbedtls/lms.h", + "include/mbedtls/mbedtls_config.h", "include/mbedtls/md.h", - "include/mbedtls/md2.h", - "include/mbedtls/md4.h", "include/mbedtls/md5.h", - "include/mbedtls/md_internal.h", "include/mbedtls/memory_buffer_alloc.h", - "include/mbedtls/net.h", "include/mbedtls/net_sockets.h", "include/mbedtls/nist_kw.h", "include/mbedtls/oid.h", - "include/mbedtls/padlock.h", "include/mbedtls/pem.h", "include/mbedtls/pk.h", - "include/mbedtls/pkcs11.h", "include/mbedtls/pkcs12.h", + "include/mbedtls/pkcs7.h", "include/mbedtls/pkcs5.h", - "include/mbedtls/pk_internal.h", "include/mbedtls/platform.h", "include/mbedtls/platform_time.h", "include/mbedtls/platform_util.h", "include/mbedtls/poly1305.h", + "include/mbedtls/private_access.h", "include/mbedtls/psa_util.h", "include/mbedtls/ripemd160.h", "include/mbedtls/rsa.h", - "include/mbedtls/rsa_internal.h", "include/mbedtls/sha1.h", + "include/mbedtls/sha3.h", "include/mbedtls/sha256.h", "include/mbedtls/sha512.h", "include/mbedtls/ssl.h", "include/mbedtls/ssl_cache.h", "include/mbedtls/ssl_ciphersuites.h", "include/mbedtls/ssl_cookie.h", - "include/mbedtls/ssl_internal.h", "include/mbedtls/ssl_ticket.h", "include/mbedtls/threading.h", "include/mbedtls/timing.h", @@ -119,8 +117,13 @@ project "mbedtls" "include/mbedtls/x509_crl.h", "include/mbedtls/x509_crt.h", "include/mbedtls/x509_csr.h", - "include/mbedtls/xtea.h", + "include/psa/build_info.h", "include/psa/crypto.h", + "include/psa/crypto_adjust_auto_enabled.h", + "include/psa/crypto_adjust_config_key_pair_types.h", + "include/psa/crypto_adjust_config_synonyms.h", + "include/psa/crypto_builtin_key_derivation.h", + "include/psa/crypto_driver_contexts_key_derivation.h", "include/psa/crypto_builtin_composites.h", "include/psa/crypto_builtin_primitives.h", "include/psa/crypto_compat.h", @@ -129,6 +132,7 @@ project "mbedtls" "include/psa/crypto_driver_contexts_composites.h", "include/psa/crypto_driver_contexts_primitives.h", "include/psa/crypto_extra.h", + "include/psa/crypto_legacy.h", "include/psa/crypto_platform.h", "include/psa/crypto_se_driver.h", "include/psa/crypto_sizes.h", @@ -136,47 +140,66 @@ project "mbedtls" "include/psa/crypto_types.h", "include/psa/crypto_values.h", "library/aes.c", + "library/aesce.c", + "library/aesce.h", "library/aesni.c", - "library/arc4.c", + "library/aesni.h", + "library/alignment.h", "library/aria.c", "library/asn1parse.c", "library/asn1write.c", "library/base64.c", + "library/base64_internal.h", "library/bignum.c", - "library/blowfish.c", + "library/bignum_core.c", + "library/bignum_core.h", + "library/bignum_mod.c", + "library/bignum_mod.h", + "library/bignum_mod_raw.c", + "library/bignum_mod_raw.h", + "library/bignum_mod_raw_invasive.h", + "library/block_cipher.c", + "library/block_cipher_internal.h", "library/camellia.c", "library/ccm.c", - "library/certs.c", "library/chacha20.c", "library/chachapoly.c", "library/check_crypto_config.h", "library/cipher.c", "library/cipher_wrap.c", + "library/cipher_wrap.h", "library/cmac.c", "library/common.h", "library/constant_time.c", + "library/constant_time_impl.h", "library/constant_time_internal.h", - "library/constant_time_invasive.h", + "library/ctr.h", "library/ctr_drbg.c", "library/debug.c", + "library/debug_internal.h", "library/des.c", "library/dhm.c", "library/ecdh.c", "library/ecdsa.c", "library/ecjpake.c", "library/ecp.c", + "library/ecp_curves_new.c", + "library/ecp_internal_alt.h", "library/ecp_curves.c", "library/ecp_invasive.h", "library/entropy.c", "library/entropy_poll.c", + "library/entropy_poll.h", "library/error.c", "library/gcm.c", - "library/havege.c", "library/hkdf.c", "library/hmac_drbg.c", + "library/lmots.c", + "library/lmots.h", + "library/lms.c", "library/md.c", - "library/md2.c", - "library/md4.c", + "library/md_psa.h", + "library/md_wrap.h", "library/md5.c", "library/memory_buffer_alloc.c", "library/mps_common.h", @@ -189,14 +212,19 @@ project "mbedtls" "library/nist_kw.c", "library/oid.c", "library/padlock.c", + "library/padlock.h", "library/pem.c", "library/pk.c", - "library/pkcs11.c", "library/pkcs12.c", + "library/pkcs7.c", "library/pkcs5.c", "library/pkparse.c", "library/pkwrite.c", + "library/pkwrite.h", "library/pk_wrap.c", + "library/pk_ecc.c", + "library/pk_ecc.h", + "library/pk_internal.h", "library/platform.c", "library/platform_util.c", "library/poly1305.c", @@ -207,16 +235,22 @@ project "mbedtls" "library/psa_crypto_cipher.h", "library/psa_crypto_client.c", "library/psa_crypto_core.h", - "library/psa_crypto_driver_wrappers.c", + "library/psa_crypto_core_common.h", "library/psa_crypto_driver_wrappers.h", + "library/psa_crypto_driver_wrappers_no_static.c", + "library/psa_crypto_driver_wrappers_no_static.h", "library/psa_crypto_ecp.c", "library/psa_crypto_ecp.h", + "library/psa_crypto_ffdh.c", + "library/psa_crypto_ffdh.h", "library/psa_crypto_hash.c", "library/psa_crypto_hash.h", "library/psa_crypto_invasive.h", "library/psa_crypto_its.h", "library/psa_crypto_mac.c", "library/psa_crypto_mac.h", + "library/psa_crypto_pake.c", + "library/psa_crypto_pake.h", "library/psa_crypto_random_impl.h", "library/psa_crypto_rsa.c", "library/psa_crypto_rsa.h", @@ -227,34 +261,49 @@ project "mbedtls" "library/psa_crypto_storage.c", "library/psa_crypto_storage.h", "library/psa_its_file.c", + "library/psa_util.c", + "library/psa_util_internal.h", "library/ripemd160.c", "library/rsa.c", - "library/rsa_internal.c", + "library/rsa_alt_helpers.c", + "library/rsa_alt_helpers.h", + "library/rsa_internal.h", "library/sha1.c", + "library/sha3.c", "library/sha256.c", "library/sha512.c", "library/ssl_cache.c", "library/ssl_ciphersuites.c", - "library/ssl_cli.c", + "library/ssl_ciphersuites_internal.h", + "library/ssl_client.c", + "library/ssl_client.h", "library/ssl_cookie.c", + "library/ssl_debug_helpers.h", + "library/ssl_debug_helpers_generated.c", + "library/ssl_misc.h", "library/ssl_msg.c", - "library/ssl_srv.c", - "library/ssl_ticket.c", "library/ssl_tls.c", + "library/ssl_tls12_client.c", + "library/ssl_tls12_server.c", + "library/ssl_tls13_client.c", + "library/ssl_tls13_generic.c", + "library/ssl_tls13_invasive.h", "library/ssl_tls13_keys.c", "library/ssl_tls13_keys.h", + "library/ssl_tls13_server.c", "library/threading.c", "library/timing.c", "library/version.c", "library/version_features.c", "library/x509.c", + "library/x509write.c", + "library/x509_internal.h", "library/x509write_crt.c", "library/x509write_csr.c", "library/x509_create.c", "library/x509_crl.c", "library/x509_crt.c", "library/x509_csr.c", - "library/xtea.c", } defines { diff --git a/vendor/mysql/LICENSE b/vendor/mysql/LICENSE new file mode 100644 index 0000000000..dee23d11a4 --- /dev/null +++ b/vendor/mysql/LICENSE @@ -0,0 +1,5792 @@ +Licensing Information User Manual + +MySQL 8.4.0 Community + __________________________________________________________________ + +Introduction + + This License Information User Manual contains Oracle's product license + and other licensing information, including licensing information for + third-party software which may be included in this distribution of + MySQL 8.4.0 Community. + + Last updated: March 2024 + +Licensing Information + + This release of MySQL 8.4.0 Community is brought to you by the MySQL + team at Oracle. This software is released under version 2 of the GNU + General Public License (GPLv2), as set forth below, with the following + additional permissions: + + This distribution of MySQL 8.4.0 Community is designed to work with + certain software (including but not limited to OpenSSL) that is + licensed under separate terms, as designated in a particular file or + component or in the license documentation. Without limiting your rights + under the GPLv2, the authors of MySQL hereby grant you an additional + permission to link the program and your derivative works with the + separately licensed software that they have either included with the + program or referenced in the documentation. + + This distribution includes the MySQL C API client library + (libmysqlclient) otherwise known as MySQL Connector/C. Without limiting + the foregoing grant of rights under the GPLv2 and additional permission + as to separately licensed software, this Connector is also subject to + the Universal FOSS Exception, version 1.0, a copy of which is + reproduced below and can also be found along with its FAQ at + http://oss.oracle.com/licenses/universal-foss-exception. + + Copyright (c) 1997, 2024, Oracle and/or its affiliates. + +Election of GPLv2 + + For the avoidance of doubt, except that if any license choice other + than GPL or LGPL is available it will apply instead, Oracle elects to + use only the General Public License version 2 (GPLv2) at this time for + any software where a choice of GPL license versions is made available + with the language indicating that GPLv2 or any later version may be + used, or where a choice of which version of the GPL is applied is + otherwise unspecified. + +GNU General Public License Version 2.0, June 1991 + +The following applies to all products licensed under the GNU General +Public License, Version 2.0: You may not use the identified files +except in compliance with the GNU General Public License, Version +2.0 (the "License.") You may obtain a copy of the License at +http://www.gnu.org/licenses/gpl-2.0.txt. A copy of the license is +also reproduced below. Unless required by applicable law or agreed +to in writing, software distributed under the License is distributed +on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, +either express or implied. See the License for the specific language +governing permissions and limitations under the License. + + + ====================================================================== + ====================================================================== + + +GNU GENERAL PUBLIC LICENSE +Version 2, June 1991 + +Copyright (C) 1989, 1991 Free Software Foundation, Inc., +51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA +Everyone is permitted to copy and distribute verbatim +copies of this license document, but changing it is not +allowed. + + Preamble + + The licenses for most software are designed to take away your +freedom to share and change it. By contrast, the GNU General Public +License is intended to guarantee your freedom to share and change free +software--to make sure the software is free for all its users. This +General Public License applies to most of the Free Software +Foundation's software and to any other program whose authors commit to +using it. (Some other Free Software Foundation software is covered by +the GNU Lesser General Public License instead.) You can apply it to +your programs, too. + + When we speak of free software, we are referring to freedom, not +price. Our General Public Licenses are designed to make sure that you +have the freedom to distribute copies of free software (and charge for +this service if you wish), that you receive source code or can get it +if you want it, that you can change the software or use pieces of it +in new free programs; and that you know you can do these things. + + To protect your rights, we need to make restrictions that forbid +anyone to deny you these rights or to ask you to surrender the rights. +These restrictions translate to certain responsibilities for you if you +distribute copies of the software, or if you modify it. + + For example, if you distribute copies of such a program, whether +gratis or for a fee, you must give the recipients all the rights that +you have. You must make sure that they, too, receive or can get the +source code. And you must show them these terms so they know their +rights. + + We protect your rights with two steps: (1) copyright the software, +and (2) offer you this license which gives you legal permission to +copy, distribute and/or modify the software. + + Also, for each author's protection and ours, we want to make certain +that everyone understands that there is no warranty for this free +software. If the software is modified by someone else and passed on, +we want its recipients to know that what they have is not the original, +so that any problems introduced by others will not reflect on the +original authors' reputations. + + Finally, any free program is threatened constantly by software +patents. We wish to avoid the danger that redistributors of a free +program will individually obtain patent licenses, in effect making the +program proprietary. To prevent this, we have made it clear that any +patent must be licensed for everyone's free use or not licensed at all. + + The precise terms and conditions for copying, distribution and +modification follow. + + GNU GENERAL PUBLIC LICENSE + TERMS AND CONDITIONS FOR COPYING, DISTRIBUTION AND MODIFICATION + + 0. This License applies to any program or other work which contains +a notice placed by the copyright holder saying it may be distributed +under the terms of this General Public License. The "Program", below, +refers to any such program or work, and a "work based on the Program" +means either the Program or any derivative work under copyright law: +that is to say, a work containing the Program or a portion of it, +either verbatim or with modifications and/or translated into another +language. (Hereinafter, translation is included without limitation in +the term "modification".) Each licensee is addressed as "you". + +Activities other than copying, distribution and modification are not +covered by this License; they are outside its scope. The act of +running the Program is not restricted, and the output from the Program +is covered only if its contents constitute a work based on the +Program (independent of having been made by running the Program). +Whether that is true depends on what the Program does. + + 1. You may copy and distribute verbatim copies of the Program's +source code as you receive it, in any medium, provided that you +conspicuously and appropriately publish on each copy an appropriate +copyright notice and disclaimer of warranty; keep intact all the +notices that refer to this License and to the absence of any warranty; +and give any other recipients of the Program a copy of this License +along with the Program. + +You may charge a fee for the physical act of transferring a copy, and +you may at your option offer warranty protection in exchange for a fee. + + 2. You may modify your copy or copies of the Program or any portion +of it, thus forming a work based on the Program, and copy and +distribute such modifications or work under the terms of Section 1 +above, provided that you also meet all of these conditions: + + a) You must cause the modified files to carry prominent notices + stating that you changed the files and the date of any change. + + b) You must cause any work that you distribute or publish, that in + whole or in part contains or is derived from the Program or any + part thereof, to be licensed as a whole at no charge to all third + parties under the terms of this License. + + c) If the modified program normally reads commands interactively + when run, you must cause it, when started running for such + interactive use in the most ordinary way, to print or display an + announcement including an appropriate copyright notice and a + notice that there is no warranty (or else, saying that you provide + a warranty) and that users may redistribute the program under + these conditions, and telling the user how to view a copy of this + License. (Exception: if the Program itself is interactive but + does not normally print such an announcement, your work based on + the Program is not required to print an announcement.) + +These requirements apply to the modified work as a whole. If +identifiable sections of that work are not derived from the Program, +and can be reasonably considered independent and separate works in +themselves, then this License, and its terms, do not apply to those +sections when you distribute them as separate works. But when you +distribute the same sections as part of a whole which is a work based +on the Program, the distribution of the whole must be on the terms of +this License, whose permissions for other licensees extend to the +entire whole, and thus to each and every part regardless of who wrote it. + +Thus, it is not the intent of this section to claim rights or contest +your rights to work written entirely by you; rather, the intent is to +exercise the right to control the distribution of derivative or +collective works based on the Program. + +In addition, mere aggregation of another work not based on the Program +with the Program (or with a work based on the Program) on a volume of +a storage or distribution medium does not bring the other work under +the scope of this License. + + 3. You may copy and distribute the Program (or a work based on it, +under Section 2) in object code or executable form under the terms of +Sections 1 and 2 above provided that you also do one of the following: + + a) Accompany it with the complete corresponding machine-readable + source code, which must be distributed under the terms of Sections + 1 and 2 above on a medium customarily used for software + interchange; or, + + b) Accompany it with a written offer, valid for at least three + years, to give any third party, for a charge no more than your + cost of physically performing source distribution, a complete + machine-readable copy of the corresponding source code, to be + distributed under the terms of Sections 1 and 2 above on a medium + customarily used for software interchange; or, + + c) Accompany it with the information you received as to the offer + to distribute corresponding source code. (This alternative is + allowed only for noncommercial distribution and only if you + received the program in object code or executable form with such + an offer, in accord with Subsection b above.) + +The source code for a work means the preferred form of the work for +making modifications to it. For an executable work, complete source +code means all the source code for all modules it contains, plus any +associated interface definition files, plus the scripts used to +control compilation and installation of the executable. However, as +a special exception, the source code distributed need not include +anything that is normally distributed (in either source or binary +form) with the major components (compiler, kernel, and so on) of the +operating system on which the executable runs, unless that component +itself accompanies the executable. + +If distribution of executable or object code is made by offering +access to copy from a designated place, then offering equivalent +access to copy the source code from the same place counts as +distribution of the source code, even though third parties are not +compelled to copy the source along with the object code. + + 4. You may not copy, modify, sublicense, or distribute the Program +except as expressly provided under this License. Any attempt +otherwise to copy, modify, sublicense or distribute the Program is +void, and will automatically terminate your rights under this License. +However, parties who have received copies, or rights, from you under +this License will not have their licenses terminated so long as such +parties remain in full compliance. + + 5. You are not required to accept this License, since you have not +signed it. However, nothing else grants you permission to modify or +distribute the Program or its derivative works. These actions are +prohibited by law if you do not accept this License. Therefore, by +modifying or distributing the Program (or any work based on the +Program), you indicate your acceptance of this License to do so, and +all its terms and conditions for copying, distributing or modifying +the Program or works based on it. + + 6. Each time you redistribute the Program (or any work based on the +Program), the recipient automatically receives a license from the +original licensor to copy, distribute or modify the Program subject to +these terms and conditions. You may not impose any further +restrictions on the recipients' exercise of the rights granted herein. +You are not responsible for enforcing compliance by third parties to +this License. + + 7. If, as a consequence of a court judgment or allegation of patent +infringement or for any other reason (not limited to patent issues), +conditions are imposed on you (whether by court order, agreement or +otherwise) that contradict the conditions of this License, they do not +excuse you from the conditions of this License. If you cannot +distribute so as to satisfy simultaneously your obligations under this +License and any other pertinent obligations, then as a consequence you +may not distribute the Program at all. For example, if a patent +license would not permit royalty-free redistribution of the Program by +all those who receive copies directly or indirectly through you, then +the only way you could satisfy both it and this License would be to +refrain entirely from distribution of the Program. + +If any portion of this section is held invalid or unenforceable under +any particular circumstance, the balance of the section is intended to +apply and the section as a whole is intended to apply in other +circumstances. + +It is not the purpose of this section to induce you to infringe any +patents or other property right claims or to contest validity of any +such claims; this section has the sole purpose of protecting the +integrity of the free software distribution system, which is +implemented by public license practices. Many people have made +generous contributions to the wide range of software distributed +through that system in reliance on consistent application of that +system; it is up to the author/donor to decide if he or she is willing +to distribute software through any other system and a licensee cannot +impose that choice. + +This section is intended to make thoroughly clear what is believed to +be a consequence of the rest of this License. + + 8. If the distribution and/or use of the Program is restricted in +certain countries either by patents or by copyrighted interfaces, the +original copyright holder who places the Program under this License +may add an explicit geographical distribution limitation excluding +those countries, so that distribution is permitted only in or among +countries not thus excluded. In such case, this License incorporates +the limitation as if written in the body of this License. + + 9. The Free Software Foundation may publish revised and/or new +versions of the General Public License from time to time. Such new +versions will be similar in spirit to the present version, but may +differ in detail to address new problems or concerns. + +Each version is given a distinguishing version number. If the Program +specifies a version number of this License which applies to it and +"any later version", you have the option of following the terms and +conditions either of that version or of any later version published by +the Free Software Foundation. If the Program does not specify a +version number of this License, you may choose any version ever +published by the Free Software Foundation. + + 10. If you wish to incorporate parts of the Program into other free +programs whose distribution conditions are different, write to the +author to ask for permission. For software which is copyrighted by the +Free Software Foundation, write to the Free Software Foundation; we +sometimes make exceptions for this. Our decision will be guided by the +two goals of preserving the free status of all derivatives of our free +software and of promoting the sharing and reuse of software generally. + + NO WARRANTY + + 11. BECAUSE THE PROGRAM IS LICENSED FREE OF CHARGE, THERE IS NO +WARRANTY FOR THE PROGRAM, TO THE EXTENT PERMITTED BY APPLICABLE LAW. +EXCEPT WHEN OTHERWISE STATED IN WRITING THE COPYRIGHT HOLDERS AND/OR +OTHER PARTIES PROVIDE THE PROGRAM "AS IS" WITHOUT WARRANTY OF ANY KIND, +EITHER EXPRESSED OR IMPLIED, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED +WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE. +THE ENTIRE RISK AS TO THE QUALITY AND PERFORMANCE OF THE PROGRAM IS +WITH YOU. SHOULD THE PROGRAM PROVE DEFECTIVE, YOU ASSUME THE COST OF +ALL NECESSARY SERVICING, REPAIR OR CORRECTION. + + 12. IN NO EVENT UNLESS REQUIRED BY APPLICABLE LAW OR AGREED TO IN +WRITING WILL ANY COPYRIGHT HOLDER, OR ANY OTHER PARTY WHO MAY MODIFY +AND/OR REDISTRIBUTE THE PROGRAM AS PERMITTED ABOVE, BE LIABLE TO YOU +FOR DAMAGES, INCLUDING ANY GENERAL, SPECIAL, INCIDENTAL OR +CONSEQUENTIAL DAMAGES ARISING OUT OF THE USE OR INABILITY TO USE THE +PROGRAM (INCLUDING BUT NOT LIMITED TO LOSS OF DATA OR DATA BEING +RENDERED INACCURATE OR LOSSES SUSTAINED BY YOU OR THIRD PARTIES OR A +FAILURE OF THE PROGRAM TO OPERATE WITH ANY OTHER PROGRAMS), EVEN IF +SUCH HOLDER OR OTHER PARTY HAS BEEN ADVISED OF THE POSSIBILITY OF SUCH +DAMAGES. + + END OF TERMS AND CONDITIONS + + How to Apply These Terms to Your New Programs + + If you develop a new program, and you want it to be of the greatest +possible use to the public, the best way to achieve this is to make it +free software which everyone can redistribute and change under these terms. + + To do so, attach the following notices to the program. It is safest +to attach them to the start of each source file to most effectively +convey the exclusion of warranty; and each file should have at least +the "copyright" line and a pointer to where the full notice is found. + + + Copyright (C) + + This program is free software; you can redistribute it and/or + modify it under the terms of the GNU General Public License as + published by the Free Software Foundation; either version 2 of + + the License, or (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program; if not, write to the Free Software + Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA + 02110-1301 USA. + +Also add information on how to contact you by electronic and paper mail. + +If the program is interactive, make it output a short notice like this +when it starts in an interactive mode: + + Gnomovision version 69, Copyright (C) year name of author + Gnomovision comes with ABSOLUTELY NO WARRANTY; for details + type 'show w'. This is free software, and you are welcome + to redistribute it under certain conditions; type 'show c' + for details. + +The hypothetical commands 'show w' and 'show c' should show the +appropriate parts of the General Public License. Of course, the +commands you use may be called something other than 'show w' and +'show c'; they could even be mouse-clicks or menu items--whatever +suits your program. + +You should also get your employer (if you work as a programmer) or your +school, if any, to sign a "copyright disclaimer" for the program, if +necessary. Here is a sample; alter the names: + + Yoyodyne, Inc., hereby disclaims all copyright interest in the + program 'Gnomovision' (which makes passes at compilers) written + by James Hacker. + + , 1 April 1989 + Ty Coon, President of Vice + +This General Public License does not permit incorporating your program +into proprietary programs. If your program is a subroutine library, +you may consider it more useful to permit linking proprietary +applications with the library. If this is what you want to do, use +the GNU Lesser General Public License instead of this License. + + ====================================================================== + ====================================================================== + +The Universal FOSS Exception, Version 1.0 + + In addition to the rights set forth in the other license(s) included in + the distribution for this software, data, and/or documentation + (collectively the "Software", and such licenses collectively with this + additional permission the "Software License"), the copyright holders + wish to facilitate interoperability with other software, data, and/or + documentation distributed with complete corresponding source under a + license that is OSI-approved and/or categorized by the FSF as free + (collectively "Other FOSS"). We therefore hereby grant the following + additional permission with respect to the use and distribution of the + Software with Other FOSS, and the constants, function signatures, data + structures and other invocation methods used to run or interact with + each of them (as to each, such software's "Interfaces"): + + i. The Software's Interfaces may, to the extent permitted by the + license of the Other FOSS, be copied into, used and distributed in + the Other FOSS in order to enable interoperability, without + requiring a change to the license of the Other FOSS other than as + to any Interfaces of the Software embedded therein. The Software's + Interfaces remain at all times under the Software License, + including without limitation as used in the Other FOSS (which upon + any such use also then contains a portion of the Software under the + Software License). + + ii. The Other FOSS's Interfaces may, to the extent permitted by the + license of the Other FOSS, be copied into, used and distributed in + the Software in order to enable interoperability, without requiring + that such Interfaces be licensed under the terms of the Software + License or otherwise altering their original terms, if this does + not require any portion of the Software other than such Interfaces + to be licensed under the terms other than the Software License. + + iii. If only Interfaces and no other code is copied between the + Software and the Other FOSS in either direction, the use and/or + distribution of the Software with the Other FOSS shall not be + deemed to require that the Other FOSS be licensed under the license + of the Software, other than as to any Interfaces of the Software + copied into the Other FOSS. This includes, by way of example and + without limitation, statically or dynamically linking the Software + together with Other FOSS after enabling interoperability using the + Interfaces of one or both, and distributing the resulting + combination under different licenses for the respective portions + thereof. + + For avoidance of doubt, a license which is OSI-approved or + categorized by the FSF as free, includes, for the purpose of this + permission, such licenses with additional permissions, and any + license that has previously been so approved or categorized as + free, even if now deprecated or otherwise no longer recognized as + approved or free. Nothing in this additional permission grants any + right to distribute any portion of the Software on terms other than + those of the Software License or grants any additional permission + of any kind for use or distribution of the Software in conjunction + with software other than Other FOSS. + + ====================================================================== + ====================================================================== + +Licenses for Third-Party Components + + The following sections contain licensing information for libraries that + may be included with this product. We are thankful to all individuals + that have created these. Standard licenses referenced herein are + detailed in the Standard Licenses section. + +Boost C++ Libraries + +Use of any of this software is governed by the terms of the license +below: + +Boost Software License - Version 1.0 - August 17th, 2003 + +Permission is hereby granted, free of charge, to any person or +organization obtaining a copy of the software and accompanying +documentation covered by this license (the "Software") to use, +reproduce, display, distribute, execute, and transmit the Software, +and to prepare derivative works of the Software, and to permit +third-parties to whom the Software is furnished to do so, all +subject to the following: + +The copyright notices in the Software and this entire statement, +including the above license grant, this restriction and the +following disclaimer, must be included in all copies of the +Software, in whole or in part, and all derivative works of the +Software, unless such copies or derivative works are solely in the +form of machine-executable object code generated by a source +language processor. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, +EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF +MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE, TITLE AND +NON-INFRINGEMENT. IN NO EVENT SHALL THE COPYRIGHT HOLDERS OR ANYONE +DISTRIBUTING THE SOFTWARE BE LIABLE FOR ANY DAMAGES OR OTHER +LIABILITY, WHETHER IN CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT +OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS +IN THE SOFTWARE. + + ====================================================================== + ====================================================================== + +cURL (libcurl) + +cURL (libcurl) + +Use of any of this software is governed by the terms of the license below: + +COPYRIGHT AND PERMISSION NOTICE + +Copyright (c) 1996 - 2019, Daniel Stenberg, , and many +contributors, see the THANKS file. + +All rights reserved. + +Permission to use, copy, modify, and distribute this software for any purpose +with or without fee is hereby granted, provided that the above copyright +notice and this permission notice appear in all copies. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT OF THIRD PARTY RIGHTS. +IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, +DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR +OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE +OR OTHER DEALINGS IN THE SOFTWARE. + +Except as contained in this notice, the name of a copyright holder shall not +be used in advertising or otherwise to promote the sale, use or other +dealings in this Software without prior written authorization of the copyright +holder. + + + ====================================================================== + ====================================================================== + +Cyrus SASL + + * Copyright (c) 1998-2003 Carnegie Mellon University. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in + * the documentation and/or other materials provided with the + * distribution. + * + * 3. The name "Carnegie Mellon University" must not be used to + * endorse or promote products derived from this software without + * prior written permission. For permission or any other legal + * details, please contact + * Office of Technology Transfer + * Carnegie Mellon University + * 5000 Forbes Avenue + * Pittsburgh, PA 15213-3890 + * (412) 268-4387, fax: (412) 268-7395 +* tech-transfer@andrew.cmu.edu + * + * 4. Redistributions of any form whatsoever must retain the following + * acknowledgment: + * "This product includes software developed by Computing Services + * at Carnegie Mellon University (http://www.cmu.edu/computing/)." + * + * CARNEGIE MELLON UNIVERSITY DISCLAIMS ALL WARRANTIES WITH REGARD TO + * THIS SOFTWARE, INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY + * AND FITNESS, IN NO EVENT SHALL CARNEGIE MELLON UNIVERSITY BE LIABLE + * FOR ANY SPECIAL, INDIRECT OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES + * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN + * AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING + * OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. + */ + +The following files + +./lib + saslint.h auxprop.c canonusr.c checkpw.c client.c common.c config.c + external.c saslutil.c server.c seterror.c dlopen.c +./plugins + scram.c gssapi.c +./common + plugin_common.c + +have a license header similar to the above with the following copyright: +/* + * Copyright (c) 1998-2016 Carnegie Mellon University. All rights reserved. + * + +./lib/md5.c includes the following license header: +/* MD5C.C - RSA Data Security, Inc., MD5 message-digest algorithm +*/ + +/* Function names changed to avoid namespace collisions: Rob Siemborski */ + +/* Copyright (C) 1991-2, RSA Data Security, Inc. Created 1991. All +rights reserved. + +License to copy and use this software is granted provided that it +is identified as the "RSA Data Security, Inc. MD5 Message-Digest +Algorithm" in all material mentioning or referencing this software +or this function. + +License is also granted to make and use derivative works provided +that such works are identified as "derived from the RSA Data +Security, Inc. MD5 Message-Digest Algorithm" in all material +mentioning or referencing the derived work. + +RSA Data Security, Inc. makes no representations concerning either +the merchantability of this software or the suitability of this +software for any particular purpose. It is provided "as is" +without express or implied warranty of any kind. + +These notices must be retained in any copies of any part of this +documentation and/or software. +*/ + + ====================================================================== + ====================================================================== + +dtoa.c + +The author of this software is David M. Gay. + +Copyright (c) 1991, 2000, 2001 by Lucent Technologies. + +Permission to use, copy, modify, and distribute this software for +any purpose without fee is hereby granted, provided that this entire +notice is included in all copies of any software which is or includes +a copy or modification of this software and in all copies of the +supporting documentation for such software. + +THIS SOFTWARE IS BEING PROVIDED "AS IS", WITHOUT ANY EXPRESS OR +IMPLIED WARRANTY. IN PARTICULAR, NEITHER THE AUTHOR NOR LUCENT +MAKES ANY REPRESENTATION OR WARRANTY OF ANY KIND CONCERNING THE +MERCHANTABILITY OF THIS SOFTWARE OR ITS FITNESS FOR ANY PARTICULAR +PURPOSE. + + ====================================================================== + ====================================================================== + +Editline Library (libedit) + +Copyright (c) 1992, 1993 + The Regents of the University of California. All rights reserved. + +This code is derived from software contributed to Berkeley by +Christos Zoulas of Cornell University. + +Redistribution and use in source and binary forms, with or without +modification, are permitted provided that the following conditions +are met: +1. Redistributions of source code must retain the above copyright + notice, this list of conditions and the following disclaimer. +2. Redistributions in binary form must reproduce the above copyright + notice, this list of conditions and the following disclaimer in the + documentation and/or other materials provided with the distribution. +3. Neither the name of the University nor the names of its contributors + may be used to endorse or promote products derived from this software + without specific prior written permission. + +THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND +ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE +IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE +ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE +FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL +DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS +OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) +HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT +LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY +OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF +SUCH DAMAGE. + +Files with different/specific license header +====================== +src/readline.c +src/literal.h +src/literal.c +src/getline.c +src/filecomplete.h +src/filecomplete.c +src/eln.c +src/chartype.h +src/chartype.c +src/read.h +----------------------- +/*- + * Copyright (c) 1997 The NetBSD Foundation, Inc. + * Copyright (c) 2001 The NetBSD Foundation, Inc. + * All rights reserved. + * + * This code is derived from software contributed to The NetBSD Foundation + * by Jaromir Dolecek. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. AND CONTRIBUTORS + * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED + * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR + * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE FOUNDATION OR CONTRIBUTORS + * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF + * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS + * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN + * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) + * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + * POSSIBILITY OF SUCH DAMAGE. + */ + +src/wcsdup.c +------------- +* + * Copyright (C) 2006 Aleksey Cheusov + * + * This material is provided "as is", with absolutely no warranty expressed + * or implied. Any use is at your own risk. + * + * Permission to use or copy this software for any purpose is hereby granted + * without fee. Permission to modify the code and to distribute modified + * code is also granted without any restrictions. + */ + +src/reallocarr.c +---------------- +/*- + * Copyright (c) 2015 Joerg Sonnenberger . + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in + * the documentation and/or other materials provided with the + * distribution. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS + * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE + * COPYRIGHT HOLDERS OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, + * INCIDENTAL, SPECIAL, EXEMPLARY OR CONSEQUENTIAL DAMAGES (INCLUDING, + * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; + * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED + * AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, + * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT + * OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + */ + + ====================================================================== + ====================================================================== + +EPSG Geodetic Parameter Dataset + +This product includes the EPSG Geodetic Parameter Dataset. + +The EPSG Dataset is owned by the International Association of Oil +and Gas Producers, incorporated in England as a company limited by +guarantee (number 1832064) and is subject to the terms of use here: +http://www.epsg.org/TermsOfUse. + +The user assumes the entire risk as to the accuracy and the use of +this data. The data may be used, copied and distributed subject +to the following conditions: +1. INFORMATION PROVIDED IN THIS DOCUMENT IS PROVIDED "AS IS" WITHOUT +WARRANTY OF ANY KIND, EITHER EXPRESSED OR IMPLIED, INCLUDING BUT +NOT LIMITED TO THE IMPLIED WARRANTIES OF MERCHANTABILITY AND/OR +FITNESS FOR A PARTICULAR PURPOSE. +2. The data may be included in any commercial package provided that +any commerciality is based on value added by the provider and not +on a value ascribed to the EPSG dataset which is made available at +no charge. The ownership of the EPSG dataset [OGP] must be acknowledged. +3. Subsets of information may be extracted from the dataset. Users +are advised that coordinate reference system and coordinate +transformation descriptions are incomplete unless all elements +detailed as essential in OGP Surveying and Positioning Guidance +Note 7-1 annex F are included. +4. Essential elements should preferably be reproduced as described +in the dataset. Modification of parameter values is permitted as +described in the table below to allow change to the content of the +information provided that numeric equivalence is achieved. Numeric +equivalence refers to the results of geodetic calculations in which +the parameters are used, for example (i) conversion of ellipsoid +defining parameters, or (ii) conversion of parameters between one +and two standard parallel projection methods, or (iii) conversion +of parameters between 7-parameter geocentric transformation methods. + + ====================================================================== + ====================================================================== + +Expect.pm + +Expect.pm is licensed under the Perl license, which is essentially a dual +license. + +Oracle may use, redistribute and/or modify this code under the terms of +either: + + a) the GNU General Public License as published by the Free Software +Foundation; either version 1, or (at your option) any later version, or + + b) the "Artistic License" which comes with the Expect/pr code. + +Oracle elects to use the Artistic license for all versions of MySQL + +A copy of the GPLv2 and the Artistic License (Perl) 1.0 must be included with +any distribution: + +The GNU General Public License (GPL-2.0) +Version 2, June 1991 + +Copyright (C) 1989, 1991 Free Software Foundation, Inc. +59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + +Everyone is permitted to copy and distribute verbatim copies +of this license document, but changing it is not allowed. + +Preamble + +The licenses for most software are designed to take away your freedom to +share and change it. By contrast, the GNU General Public License is intended +to guarantee your freedom to share and change free software--to make sure the +software is free for all its users. This General Public License applies to +most of the Free Software Foundation's software and to any other program +whose authors commit to using it. (Some other Free Software Foundation +software is covered by the GNU Library General Public License instead.) You +can apply it to your programs, too. + +When we speak of free software, we are referring to freedom, not price. Our +General Public Licenses are designed to make sure that you have the freedom +to distribute copies of free software (and charge for this service if you +wish), that you receive source code or can get it if you want it, that you +can change the software or use pieces of it in new free programs; and that +you know you can do these things. + +To protect your rights, we need to make restrictions that forbid anyone to +deny you these rights or to ask you to surrender the rights. These +restrictions translate to certain responsibilities for you if you distribute +copies of the software, or if you modify it. + +For example, if you distribute copies of such a program, whether gratis or +for a fee, you must give the recipients all the rights that you have. You +must make sure that they, too, receive or can get the source code. And you +must show them these terms so they know their rights. + +We protect your rights with two steps: (1) copyright the software, and (2) +offer you this license which gives you legal permission to copy, distribute +and/or modify the software. + +Also, for each author's protection and ours, we want to make certain that +everyone understands that there is no warranty for this free software. If the +software is modified by someone else and passed on, we want its recipients to +know that what they have is not the original, so that any problems introduced +by others will not reflect on the original authors' reputations. + +Finally, any free program is threatened constantly by software patents. We +wish to avoid the danger that redistributors of a free program will +individually obtain patent licenses, in effect making the program +proprietary. To prevent this, we have made it clear that any patent must be +licensed for everyone's free use or not licensed at all. + +The precise terms and conditions for copying, distribution and modification +follow. + +TERMS AND CONDITIONS FOR COPYING, DISTRIBUTION AND MODIFICATION + +0. This License applies to any program or other work which contains a notice +placed by the copyright holder saying it may be distributed under the terms +of this General Public License. The "Program", below, refers to any such +program or work, and a "work based on the Program" means either the Program +or any derivative work under copyright law: that is to say, a work containing +the Program or a portion of it, either verbatim or with modifications and/or +translated into another language. (Hereinafter, translation is included +without limitation in the term "modification".) Each licensee is addressed as +"you". + +Activities other than copying, distribution and modification are not covered +by this License; they are outside its scope. The act of running the Program +is not restricted, and the output from the Program is covered only if its +contents constitute a work based on the Program (independent of having been +made by running the Program). Whether that is true depends on what the +Program does. + +1. You may copy and distribute verbatim copies of the Program's source code +as you receive it, in any medium, provided that you conspicuously and +appropriately publish on each copy an appropriate copyright notice and +disclaimer of warranty; keep intact all the notices that refer to this +License and to the absence of any warranty; and give any other recipients of +the Program a copy of this License along with the Program. + +You may charge a fee for the physical act of transferring a copy, and you may +at your option offer warranty protection in exchange for a fee. + +2. You may modify your copy or copies of the Program or any portion of it, +thus forming a work based on the Program, and copy and distribute such +modifications or work under the terms of Section 1 above, provided that you +also meet all of these conditions: + + a) You must cause the modified files to carry prominent notices stating +that you changed the files and the date of any change. + + b) You must cause any work that you distribute or publish, that in whole +or in part contains or is derived from the Program or any part thereof, to be +licensed as a whole at no charge to all third parties under the terms of this +License. + + c) If the modified program normally reads commands interactively when +run, you must cause it, when started running for such interactive use in the +most ordinary way, to print or display an announcement including an +appropriate copyright notice and a notice that there is no warranty (or else, +saying that you provide a warranty) and that users may redistribute the +program under these conditions, and telling the user how to view a copy of +this License. (Exception: if the Program itself is interactive but does not +normally print such an announcement, your work based on the Program is not +required to print an announcement.) + +These requirements apply to the modified work as a whole. If identifiable +sections of that work are not derived from the Program, and can be reasonably +considered independent and separate works in themselves, then this License, +and its terms, do not apply to those sections when you distribute them as +separate works. But when you distribute the same sections as part of a whole +which is a work based on the Program, the distribution of the whole must be +on the terms of this License, whose permissions for other licensees extend to +the entire whole, and thus to each and every part regardless of who wrote it. + +Thus, it is not the intent of this section to claim rights or contest your +rights to work written entirely by you; rather, the intent is to exercise the +right to control the distribution of derivative or collective works based on +the Program. + +In addition, mere aggregation of another work not based on the Program with +the Program (or with a work based on the Program) on a volume of a storage or +distribution medium does not bring the other work under the scope of this +License. + +3. You may copy and distribute the Program (or a work based on it, under +Section 2) in object code or executable form under the terms of Sections 1 +and 2 above provided that you also do one of the following: + + a) Accompany it with the complete corresponding machine-readable source +code, which must be distributed under the terms of Sections 1 and 2 above on +a medium customarily used for software interchange; or, + + b) Accompany it with a written offer, valid for at least three years, to +give any third party, for a charge no more than your cost of physically +performing source distribution, a complete machine-readable copy of the +corresponding source code, to be distributed under the terms of Sections 1 +and 2 above on a medium customarily used for software interchange; or, + + c) Accompany it with the information you received as to the offer to +distribute corresponding source code. (This alternative is allowed only for +noncommercial distribution and only if you received the program in object +code or executable form with such an offer, in accord with Subsection b +above.) + +The source code for a work means the preferred form of the work for making +modifications to it. For an executable work, complete source code means all +the source code for all modules it contains, plus any associated interface +definition files, plus the scripts used to control compilation and +installation of the executable. However, as a special exception, the source +code distributed need not include anything that is normally distributed (in +either source or binary form) with the major components (compiler, kernel, +and so on) of the operating system on which the executable runs, unless that +component itself accompanies the executable. + +If distribution of executable or object code is made by offering access to +copy from a designated place, then offering equivalent access to copy the +source code from the same place counts as distribution of the source code, +even though third parties are not compelled to copy the source along with the +object code. + +4. You may not copy, modify, sublicense, or distribute the Program except as +expressly provided under this License. Any attempt otherwise to copy, modify, +sublicense or distribute the Program is void, and will automatically +terminate your rights under this License. However, parties who have received +copies, or rights, from you under this License will not have their licenses +terminated so long as such parties remain in full compliance. + +5. You are not required to accept this License, since you have not signed it. +However, nothing else grants you permission to modify or distribute the +Program or its derivative works. These actions are prohibited by law if you +do not accept this License. Therefore, by modifying or distributing the +Program (or any work based on the Program), you indicate your acceptance of +this License to do so, and all its terms and conditions for copying, +distributing or modifying the Program or works based on it. + +6. Each time you redistribute the Program (or any work based on the Program), +the recipient automatically receives a license from the original licensor to +copy, distribute or modify the Program subject to these terms and conditions. +You may not impose any further restrictions on the recipients' exercise of +the rights granted herein. You are not responsible for enforcing compliance +by third parties to this License. + +7. If, as a consequence of a court judgment or allegation of patent +infringement or for any other reason (not limited to patent issues), +conditions are imposed on you (whether by court order, agreement or +otherwise) that contradict the conditions of this License, they do not excuse +you from the conditions of this License. If you cannot distribute so as to +satisfy simultaneously your obligations under this License and any other +pertinent obligations, then as a consequence you may not distribute the +Program at all. For example, if a patent license would not permit +royalty-free redistribution of the Program by all those who receive copies +directly or indirectly through you, then the only way you could satisfy both +it and this License would be to refrain entirely from distribution of the +Program. + +If any portion of this section is held invalid or unenforceable under any +particular circumstance, the balance of the section is intended to apply and +the section as a whole is intended to apply in other circumstances. + +It is not the purpose of this section to induce you to infringe any patents +or other property right claims or to contest validity of any such claims; +this section has the sole purpose of protecting the integrity of the free +software distribution system, which is implemented by public license +practices. Many people have made generous contributions to the wide range of +software distributed through that system in reliance on consistent +application of that system; it is up to the author/donor to decide if he or +she is willing to distribute software through any other system and a licensee +cannot impose that choice. + +This section is intended to make thoroughly clear what is believed to be a +consequence of the rest of this License. + +8. If the distribution and/or use of the Program is restricted in certain +countries either by patents or by copyrighted interfaces, the original +copyright holder who places the Program under this License may add an +explicit geographical distribution limitation excluding those countries, so +that distribution is permitted only in or among countries not thus excluded. +In such case, this License incorporates the limitation as if written in the +body of this License. + +9. The Free Software Foundation may publish revised and/or new versions of +the General Public License from time to time. Such new versions will be +similar in spirit to the present version, but may differ in detail to address +new problems or concerns. + +Each version is given a distinguishing version number. If the Program +specifies a version number of this License which applies to it and "any later +version", you have the option of following the terms and conditions either of +that version or of any later version published by the Free Software +Foundation. If the Program does not specify a version number of this License, +you may choose any version ever published by the Free Software Foundation. + +10. If you wish to incorporate parts of the Program into other free programs +whose distribution conditions are different, write to the author to ask for +permission. For software which is copyrighted by the Free Software +Foundation, write to the Free Software Foundation; we sometimes make +exceptions for this. Our decision will be guided by the two goals of +preserving the free status of all derivatives of our free software and of +promoting the sharing and reuse of software generally. + +NO WARRANTY + +11. BECAUSE THE PROGRAM IS LICENSED FREE OF CHARGE, THERE IS NO WARRANTY FOR +THE PROGRAM, TO THE EXTENT PERMITTED BY APPLICABLE LAW. EXCEPT WHEN OTHERWISE +STATED IN WRITING THE COPYRIGHT HOLDERS AND/OR OTHER PARTIES PROVIDE THE +PROGRAM "AS IS" WITHOUT WARRANTY OF ANY KIND, EITHER EXPRESSED OR IMPLIED, +INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND +FITNESS FOR A PARTICULAR PURPOSE. THE ENTIRE RISK AS TO THE QUALITY AND +PERFORMANCE OF THE PROGRAM IS WITH YOU. SHOULD THE PROGRAM PROVE DEFECTIVE, +YOU ASSUME THE COST OF ALL NECESSARY SERVICING, REPAIR OR CORRECTION. + +12. IN NO EVENT UNLESS REQUIRED BY APPLICABLE LAW OR AGREED TO IN WRITING +WILL ANY COPYRIGHT HOLDER, OR ANY OTHER PARTY WHO MAY MODIFY AND/OR +REDISTRIBUTE THE PROGRAM AS PERMITTED ABOVE, BE LIABLE TO YOU FOR DAMAGES, +INCLUDING ANY GENERAL, SPECIAL, INCIDENTAL OR CONSEQUENTIAL DAMAGES ARISING +OUT OF THE USE OR INABILITY TO USE THE PROGRAM (INCLUDING BUT NOT LIMITED TO +LOSS OF DATA OR DATA BEING RENDERED INACCURATE OR LOSSES SUSTAINED BY YOU OR +THIRD PARTIES OR A FAILURE OF THE PROGRAM TO OPERATE WITH ANY OTHER +PROGRAMS), EVEN IF SUCH HOLDER OR OTHER PARTY HAS BEEN ADVISED OF THE +POSSIBILITY OF SUCH DAMAGES. + +END OF TERMS AND CONDITIONS + +How to Apply These Terms to Your New Programs + +If you develop a new program, and you want it to be of the greatest possible +use to the public, the best way to achieve this is to make it free software +which everyone can redistribute and change under these terms. + +To do so, attach the following notices to the program. It is safest to attach +them to the start of each source file to most effectively convey the +exclusion of warranty; and each file should have at least the "copyright" +line and a pointer to where the full notice is found. + + One line to give the program's name and a brief idea of what it does. + Copyright (C) + + This program is free software; you can redistribute it and/or modify it +under the terms of the GNU General Public License as published by the Free +Software Foundation; either version 2 of the License, or (at your option) any +later version. + + This program is distributed in the hope that it will be useful, but +WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or +FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more +details. + + You should have received a copy of the GNU General Public License along +with this program; if not, write to the Free Software Foundation, Inc., 59 +Temple Place, Suite 330, Boston, MA 02111-1307 USA + +Also add information on how to contact you by electronic and paper mail. + +If the program is interactive, make it output a short notice like this when +it starts in an interactive mode: + + Gnomovision version 69, Copyright (C) year name of author Gnomovision +comes with ABSOLUTELY NO WARRANTY; for details type `show w'. This is free +software, and you are welcome to redistribute it under certain conditions; +type `show c' for details. + +The hypothetical commands `show w' and `show c' should show the appropriate +parts of the General Public License. Of course, the commands you use may be +called something other than `show w' and `show c'; they could even be +mouse-clicks or menu items--whatever suits your program. + +You should also get your employer (if you work as a programmer) or your +school, if any, to sign a "copyright disclaimer" for the program, if +necessary. Here is a sample; alter the names: + + Yoyodyne, Inc., hereby disclaims all copyright interest in the program +`Gnomovision' (which makes passes at compilers) written by James Hacker. + + signature of Ty Coon, 1 April 1989 + Ty Coon, President of Vice + +This General Public License does not permit incorporating your program into +proprietary programs. If your program is a subroutine library, you may +consider it more useful to permit linking proprietary applications with the +library. If this is what you want to do, use the GNU Library General Public +License instead of this License. + +________________________________________________________ + +The "Artistic License" + +Preamble + +The intent of this document is to state the conditions under which a +Package may be copied, such that the Copyright Holder maintains some +semblance of artistic control over the development of the package, +while giving the users of the package the right to use and distribute +the Package in a more-or-less customary fashion, plus the right to make +reasonable modifications. + +Definitions: + + "Package" refers to the collection of files distributed by the + Copyright Holder, and derivatives of that collection of files + created through textual modification. + + "Standard Version" refers to such a Package if it has not been + modified, or has been modified in accordance with the wishes + of the Copyright Holder as specified below. + + "Copyright Holder" is whoever is named in the copyright or + copyrights for the package. + + "You" is you, if you're thinking about copying or distributing + this Package. + + "Reasonable copying fee" is whatever you can justify on the + basis of media cost, duplication charges, time of people involved, + and so on. (You will not be required to justify it to the + Copyright Holder, but only to the computing community at large + as a market that must bear the fee.) + + "Freely Available" means that no fee is charged for the item + itself, though there may be fees involved in handling the item. + It also means that recipients of the item may redistribute it + under the same conditions they received it. + +1. You may make and give away verbatim copies of the source form of the +Standard Version of this Package without restriction, provided that you +duplicate all of the original copyright notices and associated disclaimers. + +2. You may apply bug fixes, portability fixes and other modifications +derived from the Public Domain or from the Copyright Holder. A Package +modified in such a way shall still be considered the Standard Version. + +3. You may otherwise modify your copy of this Package in any way, provided +that you insert a prominent notice in each changed file stating how and +when you changed that file, and provided that you do at least ONE of the +following: + + a) place your modifications in the Public Domain or otherwise make them + Freely Available, such as by posting said modifications to Usenet or + an equivalent medium, or placing the modifications on a major archive + site such as uunet.uu.net, or by allowing the Copyright Holder to include + your modifications in the Standard Version of the Package. + + b) use the modified Package only within your corporation or organization. + + c) rename any non-standard executables so the names do not conflict + with standard executables, which must also be provided, and provide + a separate manual page for each non-standard executable that clearly + documents how it differs from the Standard Version. + + d) make other distribution arrangements with the Copyright Holder. + +4. You may distribute the programs of this Package in object code or +executable form, provided that you do at least ONE of the following: + + a) distribute a Standard Version of the executables and library files, + together with instructions (in the manual page or equivalent) on where + to get the Standard Version. + + b) accompany the distribution with the machine-readable source of + the Package with your modifications. + + c) give non-standard executables non-standard names, and clearly + document the differences in manual pages (or equivalent), together + with instructions on where to get the Standard Version. + + d) make other distribution arrangements with the Copyright Holder. + +5. You may charge a reasonable copying fee for any distribution of this +Package. You may charge any fee you choose for support of this +Package. You may not charge a fee for this Package itself. However, +you may distribute this Package in aggregate with other (possibly +commercial) programs as part of a larger (possibly commercial) software +distribution provided that you do not advertise this Package as a +product of your own. You may embed this Package's interpreter within +an executable of yours (by linking); this shall be construed as a mere +form of aggregation, provided that the complete Standard Version of the +interpreter is so embedded. + +6. The scripts and library files supplied as input to or produced as +output from the programs of this Package do not automatically fall +under the copyright of this Package, but belong to whoever generated +them, and may be sold commercially, and may be aggregated with this +Package. If such scripts or library files are aggregated with this +Package via the so-called "undump" or "unexec" methods of producing a +binary executable image, then distribution of such an image shall +neither be construed as a distribution of this Package nor shall it +fall under the restrictions of Paragraphs 3 and 4, provided that you do +not represent such an executable image as a Standard Version of this +Package. + +7. C subroutines (or comparably compiled subroutines in other +languages) supplied by you and linked into this Package in order to +emulate subroutines and variables of the language defined by this +Package shall not be considered part of this Package, but are the +equivalent of input as in Paragraph 6, provided these subroutines do +not change the language in any way that would cause it to fail the +regression tests for the language. + +8. Aggregation of this Package with a commercial distribution is always +permitted provided that the use of this Package is embedded; that is, +when no overt attempt is made to make this Package's interfaces visible +to the end user of the commercial distribution. Such use shall not be +construed as a distribution of this Package. + +9. The name of the Copyright Holder may not be used to endorse or promote +products derived from this software without specific prior written +permission. + +10. THIS PACKAGE IS PROVIDED "AS IS" AND WITHOUT ANY EXPRESS OR +IMPLIED WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED +WARRANTIES OF MERCHANTIBILITY AND FITNESS FOR A PARTICULAR PURPOSE. + + The End + + ====================================================================== + ====================================================================== + +Facebook Fast Checksum Patch + +Facebook Fast Checksum Patch + +Copyright (C) 2009-2010 Facebook, Inc. All Rights Reserved. + +Redistribution and use in source and binary forms, with or without +modification, are permitted provided that the following conditions are met: + +1. Redistributions of source code must retain the above copyright notice, + this list of conditions and the following disclaimer. +2. Redistributions in binary form must reproduce the above copyright notice, + this list of conditions and the following disclaimer in the documentation + and/or other materials provided with the distribution. + +THIS SOFTWARE IS PROVIDED BY FACEBOOK, INC. "AS IS" AND ANY EXPRESS OR +IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF +MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO +EVENT SHALL FACEBOOK, INC. BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, +SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, +PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; +OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, +WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR +OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF +ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + +Also included: + +crc32.c -- compute the CRC-32 of a buf stream +Copyright (C) 1995-2005 Mark Adler + +This software is provided 'as-is', without any express or implied +warranty. In no event will the authors be held liable for any damages +arising from the use of this software. + +Permission is granted to anyone to use this software for any purpose, +including commercial applications, and to alter it and redistribute it +freely, subject to the following restrictions: + +1. The origin of this software must not be misrepresented; you must not + claim that you wrote the original software. If you use this software + in a product, an acknowledgment in the product documentation would be + appreciated but is not required. +2. Altered source versions must be plainly marked as such, and must not be + misrepresented as being the original software. +3. This notice may not be removed or altered from any source distribution. + +Jean-loup Gailly jloup@gzip.org +Mark Adler madler@alumni.caltech.edu + + ====================================================================== + ====================================================================== + +Facebook Patches + +Copyright (c) 2012, Facebook, Inc. +All rights reserved. +Redistribution and use in source and binary forms, with or without +modification, are permitted provided that the following conditions are met: +* Redistributions of source code must retain the above copyright notice, +this list of conditions and the following disclaimer. +* Redistributions in binary form must reproduce the above copyright notice, +this list of conditions and the following disclaimer in the documentation +and/or other materials provided with the distribution. +THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" +AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE +IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE +ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE +LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR +CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF +SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS +INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN +CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) +ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE +POSSIBILITY OF SUCH DAMAGE. + + ====================================================================== + ====================================================================== + +FMT + +Copyright (c) 2012 - present, Victor Zverovich + +Permission is hereby granted, free of charge, to any person obtaining +a copy of this software and associated documentation files (the +"Software"), to deal in the Software without restriction, including +without limitation the rights to use, copy, modify, merge, publish, +distribute, sublicense, and/or sell copies of the Software, and to +permit persons to whom the Software is furnished to do so, subject to +the following conditions: + +The above copyright notice and this permission notice shall be +included in all copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, +EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF +MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND +NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE +LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION +OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION +WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. + +--- Optional exception to the license --- + +As an exception, if, as a result of your compiling your source code, portions +of this Software are embedded into a machine-executable object form of such +source code, you may redistribute such embedded portions in such object form +without including the above copyright and permission notices. + + ====================================================================== + ====================================================================== + +Fred Fish's Dbug Library + + N O T I C E + + Copyright Abandoned, 1987, Fred Fish + + This previously copyrighted work has been placed into the public + domain by the author and may be freely used for any purpose, + private or commercial. + + Because of the number of inquiries I was receiving about the use + of this product in commercially developed works I have decided to + simply make it public domain to further its unrestricted use. I + specifically would be most happy to see this material become a + part of the standard Unix distributions by AT&T and the Berkeley + Computer Science Research Group, and a standard part of the GNU + system from the Free Software Foundation. + + I would appreciate it, as a courtesy, if this notice is left in + all copies and derivative works. Thank you. + + The author makes no warranty of any kind with respect to this + product and explicitly disclaims any implied warranties of mer- + chantability or fitness for any particular purpose. + +The dbug_analyze.c file is subject to the following notice: + + Copyright June 1987, Binayak Banerjee + All rights reserved. + + This program may be freely distributed under the same terms and + conditions as Fred Fish's Dbug package. + + ====================================================================== + ====================================================================== + +Google Controlling Master Thread I/O Rate Patch + +Copyright (c) 2009, Google Inc. +All rights reserved. + +Redistribution and use in source and binary forms, with or without +modification, are permitted provided that the following conditions +are met: + + * Redistributions of source code must retain the above copyright + notice, this list of conditions and the following disclaimer. + * Redistributions in binary form must reproduce the above copyright + notice, this list of conditions and the following disclaimer in the + documentation and/or other materials provided with the distribution. + * Neither the name of the Google Inc. nor the names of its contributors + may be used to endorse or promote products derived from this software + without specific prior written permission. + +THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS +"AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT +LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS +FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE +COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, +INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, +BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; +LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER +CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT +LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN +ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE +POSSIBILITY OF SUCH DAMAGE. + + ====================================================================== + ====================================================================== + +Google Perftools (TCMalloc utility) + +Google Perftools (TCMalloc utility) + +Copyright (c) 1998-2006, Google Inc. +All rights reserved. + +Redistribution and use in source and binary forms, with or +without modification, are permitted provided that the following +conditions are met: + + * Redistributions of source code must retain the above + copyright notice, this list of conditions and the following + disclaimer. + * Redistributions in binary form must reproduce the above + copyright notice, this list of conditions and the following + disclaimer in the documentation and/or other materials provided + with the distribution. + * Neither the name of Google Inc. nor the names of its + contributors may be used to endorse or promote products + derived from this software without specific prior written + permission. + +THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS +"AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT +LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR +A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT +OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, +SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT +LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, +DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY +THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + + ====================================================================== + ====================================================================== + +Google Protocol Buffers + +Copyright 2008 Google Inc. All rights reserved. + +Redistribution and use in source and binary forms, with or without +modification, are permitted provided that the following conditions are +met: + + * Redistributions of source code must retain the above copyright +notice, this list of conditions and the following disclaimer. + * Redistributions in binary form must reproduce the above +copyright notice, this list of conditions and the following disclaimer +in the documentation and/or other materials provided with the +distribution. + * Neither the name of Google Inc. nor the names of its +contributors may be used to endorse or promote products derived from +this software without specific prior written permission. + +THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS +"AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT +LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR +A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT +OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, +SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT +LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, +DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY +THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + +Code generated by the Protocol Buffer compiler is owned by the owner +of the input file used when generating it. This code is not +standalone and requires a support library to be linked with it. This +support library is itself covered by the above license. + +4th party - abseil-cpp +---------------------- + +=== Header in source files: +// Copyright 2017 The Abseil Authors. +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// https://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. +// +// This header file contains C++11 versions of standard header +// abstractions available within C++14 and C++17, and are designed to be +// drop-in replacement for code compliant with C++14 and C++17. + + Apache License + Version 2.0, January 2004 + https://www.apache.org/licenses/ + +A copy of the Apache License v2.0, January 2004 license can be found +in the 'Standard Licenses' section. + + ====================================================================== + ====================================================================== + +Google SMP Patch + +Google SMP patch + +Copyright (c) 2008, Google Inc. +All rights reserved. + +Redistribution and use in source and binary forms, with or without +modification, are permitted provided that the following conditions +are met: + + * Redistributions of source code must retain the above copyright + notice, this list of conditions and the following disclaimer. + * Redistributions in binary form must reproduce the above copyright + notice, this list of conditions and the following disclaimer in the + documentation and/or other materials provided with the distribution. + * Neither the name of the Google Inc. nor the names of its contributors + may be used to endorse or promote products derived from this software + without specific prior written permission. + +THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS +"AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT +LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS +FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE +COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, +INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, +BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; +LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER +CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT +LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN +ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE +POSSIBILITY OF SUCH DAMAGE. + + ====================================================================== + ====================================================================== + +Google Test (including GMock) + +Google Mock (GMock) is an extension to Google Test for writing and +using C++ mock classes. Google Test (including the Google Mock +extension) is licensed under the following terms: + +Copyright 2008, Google Inc. +All rights reserved. + +Redistribution and use in source and binary forms, with or without +modification, are permitted provided that the following conditions are met: + +* Redistributions of source code must retain the above copyright notice, this +list of conditions and the following disclaimer. +* Redistributions in binary form must reproduce the above copyright notice, +this list of conditions and the following disclaimer in the documentation +and/or other materials provided with the distribution. +* Neither the name of Google Inc. nor the names of its contributors may be +used to endorse or promote products derived from this software without +specific prior written permission. + +THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" +AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE +IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE +ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE +LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR +CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF +SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS +INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN +CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) +ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE +POSSIBILITY OF SUCH DAMAGE. + + ====================================================================== + ====================================================================== + +gperftools + +Copyright (c) 2005, Google Inc. +All rights reserved. + +Redistribution and use in source and binary forms, with or without +modification, are permitted provided that the following conditions are +met: + + * Redistributions of source code must retain the above copyright +notice, this list of conditions and the following disclaimer. + * Redistributions in binary form must reproduce the above +copyright notice, this list of conditions and the following disclaimer +in the documentation and/or other materials provided with the +distribution. + * Neither the name of Google Inc. nor the names of its +contributors may be used to endorse or promote products derived from +this software without specific prior written permission. + +THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS +"AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT +LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR +A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT +OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, +SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT +LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, +DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY +THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + + ====================================================================== + ====================================================================== + +ICU4C Unicode Libraries + +COPYRIGHT AND PERMISSION NOTICE (ICU 58 and later) + +Copyright (c) 1991-2019 Unicode, Inc. All rights reserved. +Distributed under the Terms of Use in https://www.unicode.org/copyright.html. +Permission is hereby granted, free of charge, to any person obtaining +a copy of the Unicode data files and any associated documentation +(the "Data Files") or Unicode software and any associated documentation +(the "Software") to deal in the Data Files or Software +without restriction, including without limitation the rights to use, +copy, modify, merge, publish, distribute, and/or sell copies of +the Data Files or Software, and to permit persons to whom the Data Files +or Software are furnished to do so, provided that either +(a) this copyright and permission notice appear with all copies +of the Data Files or Software, or +(b) this copyright and permission notice appear in associated +Documentation. + +THE DATA FILES AND SOFTWARE ARE PROVIDED "AS IS", WITHOUT WARRANTY OF +ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE +WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND +NONINFRINGEMENT OF THIRD PARTY RIGHTS. +IN NO EVENT SHALL THE COPYRIGHT HOLDER OR HOLDERS INCLUDED IN THIS +NOTICE BE LIABLE FOR ANY CLAIM, OR ANY SPECIAL INDIRECT OR CONSEQUENTIAL +DAMAGES, OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, +DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER +TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR +PERFORMANCE OF THE DATA FILES OR SOFTWARE. + +Except as contained in this notice, the name of a copyright holder +shall not be used in advertising or otherwise to promote the sale, +use or other dealings in these Data Files or Software without prior +written authorization of the copyright holder. + +--------------------- + +Third-Party Software Licenses + +This section contains third-party software notices and/or additional +terms for licensed third-party software components included within ICU +libraries. + +1. ICU License - ICU 1.8.1 to ICU 57.1 + +COPYRIGHT AND PERMISSION NOTICE + +Copyright (c) 1995-2016 International Business Machines Corporation and +others +All rights reserved. + +Permission is hereby granted, free of charge, to any person obtaining +a copy of this software and associated documentation files (the +"Software"), to deal in the Software without restriction, including +without limitation the rights to use, copy, modify, merge, publish, +distribute, and/or sell copies of the Software, and to permit persons +to whom the Software is furnished to do so, provided that the above +copyright notice(s) and this permission notice appear in all copies of +the Software and that both the above copyright notice(s) and this +permission notice appear in supporting documentation. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, +EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF +MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT +OF THIRD PARTY RIGHTS. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR +HOLDERS INCLUDED IN THIS NOTICE BE LIABLE FOR ANY CLAIM, OR ANY +SPECIAL INDIRECT OR CONSEQUENTIAL DAMAGES, OR ANY DAMAGES WHATSOEVER +RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF +CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN +CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. + +Except as contained in this notice, the name of a copyright holder +shall not be used in advertising or otherwise to promote the sale, use +or other dealings in this Software without prior written authorization +of the copyright holder. + +All trademarks and registered trademarks mentioned herein are the +property of their respective owners. + +2. Chinese/Japanese Word Break Dictionary Data (cjdict.txt) + + # The Google Chrome software developed by Google is licensed under + # the BSD license. Other software included in this distribution is + # provided under other licenses, as set forth below. + # + # The BSD License + # http://opensource.org/licenses/bsd-license.php + # Copyright (C) 2006-2008, Google Inc. + # + # All rights reserved. + # + # Redistribution and use in source and binary forms, with or without + # modification, are permitted provided that the following conditions are met: + # + # Redistributions of source code must retain the above copyright notice, + # this list of conditions and the following disclaimer. + # Redistributions in binary form must reproduce the above + # copyright notice, this list of conditions and the following + # disclaimer in the documentation and/or other materials provided with + # the distribution. + # Neither the name of Google Inc. nor the names of its + # contributors may be used to endorse or promote products derived from + # this software without specific prior written permission. + # + # + # THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND + # CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, + # INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF + # MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE + # DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE + # LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + # CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF + # SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR + # BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF + # LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING + # NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS + # SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + # + # + # The word list in cjdict.txt are generated by combining three word lists + # listed below with further processing for compound word breaking. The + # frequency is generated with an iterative training against Google web + # corpora. + # + # * Libtabe (Chinese) + # - https://sourceforge.net/project/?group_id=1519 + # - Its license terms and conditions are shown below. + # + # * IPADIC (Japanese) + # - http://chasen.aist-nara.ac.jp/chasen/distribution.html + # - Its license terms and conditions are shown below. + # + # ---------COPYING.libtabe ---- BEGIN-------------------- + # + # /* + # * Copyright (c) 1999 TaBE Project. + # * Copyright (c) 1999 Pai-Hsiang Hsiao. + # * All rights reserved. + # * + # * Redistribution and use in source and binary forms, with or without + # * modification, are permitted provided that the following conditions + # * are met: + # * + # * . Redistributions of source code must retain the above copyright + # * notice, this list of conditions and the following disclaimer. + # * . Redistributions in binary form must reproduce the above copyright + # * notice, this list of conditions and the following disclaimer in + # * the documentation and/or other materials provided with the + # * distribution. + # * . Neither the name of the TaBE Project nor the names of its + # * contributors may be used to endorse or promote products derived + # * from this software without specific prior written permission. + # * + # * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + # * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + # * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS + # * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE + # * REGENTS OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, + # * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES + # * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR + # * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + # * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, + # * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) + # * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED + # * OF THE POSSIBILITY OF SUCH DAMAGE. + # */ + # + # /* + # * Copyright (c) 1999 Computer Systems and Communication Lab, + # * Institute of Information Science, Academia + # * Sinica. All rights reserved. + # * + # * Redistribution and use in source and binary forms, with or without + # * modification, are permitted provided that the following conditions + # * are met: + # * + # * . Redistributions of source code must retain the above copyright + # * notice, this list of conditions and the following disclaimer. + # * . Redistributions in binary form must reproduce the above copyright + # * notice, this list of conditions and the following disclaimer in + # * the documentation and/or other materials provided with the + # * distribution. + # * . Neither the name of the Computer Systems and Communication Lab + # * nor the names of its contributors may be used to endorse or + # * promote products derived from this software without specific + # * prior written permission. + # * + # * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + # * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + # * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS + # * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE + # * REGENTS OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, + # * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES + # * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR + # * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + # * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, + # * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) + # * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED + # * OF THE POSSIBILITY OF SUCH DAMAGE. + # */ + # + # Copyright 1996 Chih-Hao Tsai @ Beckman Institute, + # University of Illinois + # c-tsai4@uiuc.edu http://casper.beckman.uiuc.edu/~c-tsai4 + # + # ---------------COPYING.libtabe-----END-------------------------------- + # + # + # ---------------COPYING.ipadic-----BEGIN------------------------------- + # + # Copyright 2000, 2001, 2002, 2003 Nara Institute of Science + # and Technology. All Rights Reserved. + # + # Use, reproduction, and distribution of this software is permitted. + # Any copy of this software, whether in its original form or modified, + # must include both the above copyright notice and the following + # paragraphs. + # + # Nara Institute of Science and Technology (NAIST), + # the copyright holders, disclaims all warranties with regard to this + # software, including all implied warranties of merchantability and + # fitness, in no event shall NAIST be liable for + # any special, indirect or consequential damages or any damages + # whatsoever resulting from loss of use, data or profits, whether in an + # action of contract, negligence or other tortuous action, arising out + # of or in connection with the use or performance of this software. + # + # A large portion of the dictionary entries + # originate from ICOT Free Software. The following conditions for ICOT + # Free Software applies to the current dictionary as well. + # + # Each User may also freely distribute the Program, whether in its + # original form or modified, to any third party or parties, PROVIDED + # that the provisions of Section 3 ("NO WARRANTY") will ALWAYS appear + # on, or be attached to, the Program, which is distributed substantially + # in the same form as set out herein and that such intended + # distribution, if actually made, will neither violate or otherwise + # contravene any of the laws and regulations of the countries having + # jurisdiction over the User or the intended distribution itself. + # + # NO WARRANTY + # + # The program was produced on an experimental basis in the course of the + # research and development conducted during the project and is provided + # to users as so produced on an experimental basis. Accordingly, the + # program is provided without any warranty whatsoever, whether express, + # implied, statutory or otherwise. The term "warranty" used herein + # includes, but is not limited to, any warranty of the quality, + # performance, merchantability and fitness for a particular purpose of + # the program and the nonexistence of any infringement or violation of + # any right of any third party. + # + # Each user of the program will agree and understand, and be deemed to + # have agreed and understood, that there is no warranty whatsoever for + # the program and, accordingly, the entire risk arising from or + # otherwise connected with the program is assumed by the user. + # + # Therefore, neither ICOT, the copyright holder, or any other + # organization that participated in or was otherwise related to the + # development of the program and their respective officials, directors, + # officers and other employees shall be held liable for any and all + # damages, including, without limitation, general, special, incidental + # and consequential damages, arising out of or otherwise in connection + # with the use or inability to use the program or any product, material + # or result produced or otherwise obtained by using the program, + # regardless of whether they have been advised of, or otherwise had + # knowledge of, the possibility of such damages at any time during the + # project or thereafter. Each user will be deemed to have agreed to the + # foregoing by his or her commencement of use of the program. The term + # "use" as used herein includes, but is not limited to, the use, + # modification, copying and distribution of the program and the + # production of secondary products from the program. + # + # In the case where the program, whether in its original form or + # modified, was distributed or delivered to or received by a user from + # any person, organization or entity other than ICOT, unless it makes or + # grants independently of ICOT any specific warranty to the user in + # writing, such person, organization or entity, will also be exempted + # from and not be held liable to the user for any such damages as noted + # above as far as the program is concerned. + # + # ---------------COPYING.ipadic-----END---------------------------------- + +3. Lao Word Break Dictionary Data (laodict.txt) + + # Copyright (c) 2013 International Business Machines Corporation + # and others. All Rights Reserved. + # + # Project: http://code.google.com/p/lao-dictionary/ + # Dictionary: http://lao-dictionary.googlecode.com/git/Lao-Dictionary.txt + # License: + # http://lao-dictionary.googlecode.com/git/Lao-Dictionary-LICENSE.txt + # (copied below) + # + # This file is derived from the above dictionary, with slight + # modifications. + # ---------------------------------------------------------------------- + # Copyright (C) 2013 Brian Eugene Wilson, Robert Martin Campbell. + # All rights reserved. + # + # Redistribution and use in source and binary forms, with or without + # modification, + # are permitted provided that the following conditions are met: + # + # + # Redistributions of source code must retain the above copyright notice, this + # list of conditions and the following disclaimer. Redistributions in + # binary form must reproduce the above copyright notice, this list of + # conditions and the following disclaimer in the documentation and/or + # other materials provided with the distribution. + # + # + # THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + # "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + # LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS + # FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE + # COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, + # INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES + # (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR + # SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + # HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, + # STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) + # ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED + # OF THE POSSIBILITY OF SUCH DAMAGE. + # +-------------------------------------------------------------------------- + +4. Burmese Word Break Dictionary Data (burmesedict.txt) + + # Copyright (c) 2014 International Business Machines Corporation + # and others. All Rights Reserved. + # + # This list is part of a project hosted at: + # github.com/kanyawtech/myanmar-karen-word-lists + # + # +-------------------------------------------------------------------------- + # Copyright (c) 2013, LeRoy Benjamin Sharon + # All rights reserved. + # + # Redistribution and use in source and binary forms, with or without + # modification, are permitted provided that the following conditions + # are met: Redistributions of source code must retain the above + # copyright notice, this list of conditions and the following + # disclaimer. Redistributions in binary form must reproduce the + # above copyright notice, this list of conditions and the following + # disclaimer in the documentation and/or other materials provided + # with the distribution. + # + # Neither the name Myanmar Karen Word Lists, nor the names of its + # contributors may be used to endorse or promote products derived + # from this software without specific prior written permission. + # + # THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND + # CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, + # INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF + # MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE + # DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS + # BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, + # EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED + # TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, + # DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON + # ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR + # TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF + # THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + # SUCH DAMAGE. + # +-------------------------------------------------------------------------- + +5. Time Zone Database + + ICU uses the public domain data and code derived from Time Zone +Database for its time zone support. The ownership of the TZ database +is explained in BCP 175: Procedure for Maintaining the Time Zone +Database section 7. + + # 7. Database Ownership + # + # The TZ database itself is not an IETF Contribution or an IETF + # document. Rather it is a pre-existing and regularly updated work + # that is in the public domain, and is intended to remain in the + # public domain. Therefore, BCPs 78 [RFC5378] and 79 [RFC3979] do + # not apply to the TZ Database or contributions that individuals make + # to it. Should any claims be made and substantiated against the TZ + # Database, the organization that is providing the IANA + # Considerations defined in this RFC, under the memorandum of + # understanding with the IETF, currently ICANN, may act in accordance + # with all competent court orders. No ownership claims will be made + # by ICANN or the IETF Trust on the database or the code. Any person + # making a contribution to the database or code waives all rights to + # future claims in that contribution or in the TZ Database. + +6. Google double-conversion + +Copyright 2006-2011, the V8 project authors. All rights reserved. +Redistribution and use in source and binary forms, with or without +modification, are permitted provided that the following conditions are +met: + + * Redistributions of source code must retain the above copyright + notice, this list of conditions and the following disclaimer. + * Redistributions in binary form must reproduce the above + copyright notice, this list of conditions and the following + disclaimer in the documentation and/or other materials provided + with the distribution. + * Neither the name of Google Inc. nor the names of its + contributors may be used to endorse or promote products derived + from this software without specific prior written permission. + +THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS +"AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT +LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR +A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT +OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, +SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT +LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, +DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY +THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + + ====================================================================== + ====================================================================== + +jemalloc + +Copyright (C) 2002-present Jason Evans . +All rights reserved. +Copyright (C) 2007-2012 Mozilla Foundation. All rights reserved. +Copyright (C) 2009-present Facebook, Inc. All rights reserved. + +Redistribution and use in source and binary forms, with or without +modification, are permitted provided that the following conditions are met: +1. Redistributions of source code must retain the above copyright notice(s), + this list of conditions and the following disclaimer. +2. Redistributions in binary form must reproduce the above copyright +notice(s), + this list of conditions and the following disclaimer in the documentation + and/or other materials provided with the distribution. + +THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDER(S) ``AS IS'' AND ANY +EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED +WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE +DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER(S) BE LIABLE FOR ANY +DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES +(INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR +SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER +CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT +LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY +OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF +SUCH DAMAGE. + + ====================================================================== + ====================================================================== + +Kerberos5 + +Kerberos5 + +Copyright (C) 1985-2019 by the Massachusetts Institute of Technology. + +All rights reserved. + +Redistribution and use in source and binary forms, with or without +modification, are permitted provided that the following conditions are +met: + +* Redistributions of source code must retain the above copyright + notice, this list of conditions and the following disclaimer. + +* Redistributions in binary form must reproduce the above copyright + notice, this list of conditions and the following disclaimer in the + documentation and/or other materials provided with the distribution. + +THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS +"AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT +LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR +A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT +HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, +SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT +LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, +DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY +THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + +Downloading of this software may constitute an export of cryptographic +software from the United States of America that is subject to the +United States Export Administration Regulations (EAR), 15 CFR 730-774. +Additional laws or regulations may apply. It is the responsibility of +the person or entity contemplating export to comply with all +applicable export laws and regulations, including obtaining any +required license from the U.S. government. + +The U.S. government prohibits export of encryption source code to +certain countries and individuals, including, but not limited to, the +countries of Cuba, Iran, North Korea, Sudan, Syria, and residents and +nationals of those countries. + +Documentation components of this software distribution are licensed +under a Creative Commons Attribution-ShareAlike 3.0 Unported License. +(http://creativecommons.org/licenses/by-sa/3.0/) + +Individual source code files are copyright MIT, Cygnus Support, +Novell, OpenVision Technologies, Oracle, Red Hat, Sun Microsystems, +FundsXpress, and others. + +Project Athena, Athena, Athena MUSE, Discuss, Hesiod, Kerberos, Moira, +and Zephyr are trademarks of the Massachusetts Institute of Technology +(MIT). No commercial use of these trademarks may be made without +prior written permission of MIT. + +"Commercial use" means use of a name in a product or other for-profit +manner. It does NOT prevent a commercial firm from referring to the +MIT trademarks in order to convey information (although in doing so, +recognition of their trademark status should be given). + +====================================================================== + +The following copyright and permission notice applies to the +OpenVision Kerberos Administration system located in "kadmin/create", +"kadmin/dbutil", "kadmin/passwd", "kadmin/server", "lib/kadm5", and +portions of "lib/rpc": + + Copyright, OpenVision Technologies, Inc., 1993-1996, All Rights + Reserved + + WARNING: Retrieving the OpenVision Kerberos Administration system + source code, as described below, indicates your acceptance of the + following terms. If you do not agree to the following terms, do + not retrieve the OpenVision Kerberos administration system. + + You may freely use and distribute the Source Code and Object Code + compiled from it, with or without modification, but this Source + Code is provided to you "AS IS" EXCLUSIVE OF ANY WARRANTY, + INCLUDING, WITHOUT LIMITATION, ANY WARRANTIES OF MERCHANTABILITY OR + FITNESS FOR A PARTICULAR PURPOSE, OR ANY OTHER WARRANTY, WHETHER + EXPRESS OR IMPLIED. IN NO EVENT WILL OPENVISION HAVE ANY LIABILITY + FOR ANY LOST PROFITS, LOSS OF DATA OR COSTS OF PROCUREMENT OF + SUBSTITUTE GOODS OR SERVICES, OR FOR ANY SPECIAL, INDIRECT, OR + CONSEQUENTIAL DAMAGES ARISING OUT OF THIS AGREEMENT, INCLUDING, + WITHOUT LIMITATION, THOSE RESULTING FROM THE USE OF THE SOURCE + CODE, OR THE FAILURE OF THE SOURCE CODE TO PERFORM, OR FOR ANY + OTHER REASON. + + OpenVision retains all copyrights in the donated Source Code. + OpenVision also retains copyright to derivative works of the Source + Code, whether created by OpenVision or by a third party. The + OpenVision copyright notice must be preserved if derivative works + are made based on the donated Source Code. + + OpenVision Technologies, Inc. has donated this Kerberos + Administration system to MIT for inclusion in the standard Kerberos + 5 distribution. This donation underscores our commitment to + continuing Kerberos technology development and our gratitude for + the valuable work which has been performed by MIT and the Kerberos + community. + +====================================================================== + + Portions contributed by Matt Crawford "crawdad@fnal.gov" were work +performed at Fermi National Accelerator Laboratory, which is + operated by Universities Research Association, Inc., under contract + DE-AC02-76CHO3000 with the U.S. Department of Energy. + +====================================================================== + +Portions of "src/lib/crypto" have the following copyright: + + Copyright (C) 1998 by the FundsXpress, INC. + + All rights reserved. + + Export of this software from the United States of America may + require a specific license from the United States Government. + It is the responsibility of any person or organization + contemplating export to obtain such a license before exporting. + + WITHIN THAT CONSTRAINT, permission to use, copy, modify, and + distribute this software and its documentation for any purpose and + without fee is hereby granted, provided that the above copyright + notice appear in all copies and that both that copyright notice and + this permission notice appear in supporting documentation, and that + the name of FundsXpress. not be used in advertising or publicity + pertaining to distribution of the software without specific, + written prior permission. FundsXpress makes no representations + about the suitability of this software for any purpose. It is + provided "as is" without express or implied warranty. + + THIS SOFTWARE IS PROVIDED "AS IS" AND WITHOUT ANY EXPRESS OR + IMPLIED WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED + WARRANTIES OF MERCHANTIBILITY AND FITNESS FOR A PARTICULAR PURPOSE. + +====================================================================== + +The implementation of the AES encryption algorithm in +"src/lib/crypto/builtin/aes" has the following copyright: + + Copyright (C) 2001, Dr Brian Gladman "brg@gladman.uk.net", Worcester, UK. + All rights reserved. + + LICENSE TERMS + + The free distribution and use of this software in both source and + binary form is allowed (with or without changes) provided that: + + 1. distributions of this source code include the above copyright + notice, this list of conditions and the following disclaimer; + + 2. distributions in binary form include the above copyright notice, + this list of conditions and the following disclaimer in the + documentation and/or other associated materials; + + 3. the copyright holder's name is not used to endorse products + built using this software without specific written permission. + + DISCLAIMER + + This software is provided 'as is' with no explcit or implied + warranties in respect of any properties, including, but not limited + to, correctness and fitness for purpose. + +====================================================================== + +Portions contributed by Red Hat, including the pre-authentication +plug-in framework and the NSS crypto implementation, contain the +following copyright: + + Copyright (C) 2006 Red Hat, Inc. + Portions copyright (C) 2006 Massachusetts Institute of Technology + All Rights Reserved. + + Redistribution and use in source and binary forms, with or without + modification, are permitted provided that the following conditions + are met: + + * Redistributions of source code must retain the above copyright + notice, this list of conditions and the following disclaimer. + + * Redistributions in binary form must reproduce the above copyright + notice, this list of conditions and the following disclaimer in + the documentation and/or other materials provided with the + distribution. + + * Neither the name of Red Hat, Inc., nor the names of its + contributors may be used to endorse or promote products derived + from this software without specific prior written permission. + + THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS + FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE + COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, + INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES + (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR + SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, + STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) + ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED + OF THE POSSIBILITY OF SUCH DAMAGE. + +====================================================================== + +The bundled verto source code is subject to the following license: + + Copyright 2011 Red Hat, Inc. + + Permission is hereby granted, free of charge, to any person + obtaining a copy of this software and associated documentation + files (the "Software"), to deal in the Software without + restriction, including without limitation the rights to use, copy, + modify, merge, publish, distribute, sublicense, and/or sell copies + of the Software, and to permit persons to whom the Software is + furnished to do so, subject to the following conditions: + + The above copyright notice and this permission notice shall be + included in all copies or substantial portions of the Software. + + THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, + EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF + MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND + NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT + HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, + WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER + DEALINGS IN THE SOFTWARE. + +====================================================================== + +The MS-KKDCP client implementation has the following copyright: + + Copyright 2013,2014 Red Hat, Inc. + + Redistribution and use in source and binary forms, with or without + modification, are permitted provided that the following conditions + are met: + + 1. Redistributions of source code must retain the above + copyright notice, this list of conditions and the following + disclaimer. + + 2. Redistributions in binary form must reproduce the above + copyright notice, this list of conditions and the following + disclaimer in the documentation and/or other materials + provided with the distribution. + + THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS + FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE + COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, + INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES + (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR + SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, + STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) + ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED + OF THE POSSIBILITY OF SUCH DAMAGE. + +====================================================================== + +The implementations of GSSAPI mechglue in GSSAPI-SPNEGO in +"src/lib/gssapi", including the following files: + + lib/gssapi/generic/gssapi_err_generic.et + lib/gssapi/mechglue/g_accept_sec_context.c + lib/gssapi/mechglue/g_acquire_cred.c + lib/gssapi/mechglue/g_canon_name.c + lib/gssapi/mechglue/g_compare_name.c + lib/gssapi/mechglue/g_context_time.c + lib/gssapi/mechglue/g_delete_sec_context.c + lib/gssapi/mechglue/g_dsp_name.c + lib/gssapi/mechglue/g_dsp_status.c + lib/gssapi/mechglue/g_dup_name.c + lib/gssapi/mechglue/g_exp_sec_context.c + lib/gssapi/mechglue/g_export_name.c + lib/gssapi/mechglue/g_glue.c + lib/gssapi/mechglue/g_imp_name.c + lib/gssapi/mechglue/g_imp_sec_context.c + lib/gssapi/mechglue/g_init_sec_context.c + lib/gssapi/mechglue/g_initialize.c + lib/gssapi/mechglue/g_inquire_context.c + lib/gssapi/mechglue/g_inquire_cred.c + lib/gssapi/mechglue/g_inquire_names.c + lib/gssapi/mechglue/g_process_context.c + lib/gssapi/mechglue/g_rel_buffer.c + lib/gssapi/mechglue/g_rel_cred.c + lib/gssapi/mechglue/g_rel_name.c + lib/gssapi/mechglue/g_rel_oid_set.c + lib/gssapi/mechglue/g_seal.c + lib/gssapi/mechglue/g_sign.c + lib/gssapi/mechglue/g_store_cred.c + lib/gssapi/mechglue/g_unseal.c + lib/gssapi/mechglue/g_userok.c + lib/gssapi/mechglue/g_utils.c + lib/gssapi/mechglue/g_verify.c + lib/gssapi/mechglue/gssd_pname_to_uid.c + lib/gssapi/mechglue/mglueP.h + lib/gssapi/mechglue/oid_ops.c + lib/gssapi/spnego/gssapiP_spnego.h + lib/gssapi/spnego/spnego_mech.c + +and the initial implementation of incremental propagation, including +the following new or changed files: + + include/iprop_hdr.h + kadmin/server/ipropd_svc.c + lib/kdb/iprop.x + lib/kdb/kdb_convert.c + lib/kdb/kdb_log.c + lib/kdb/kdb_log.h + lib/krb5/error_tables/kdb5_err.et + slave/kpropd_rpc.c + slave/kproplog.c + +are subject to the following license: + + Copyright (C) 2004 Sun Microsystems, Inc. + + Permission is hereby granted, free of charge, to any person + obtaining a copy of this software and associated documentation + files (the "Software"), to deal in the Software without + restriction, including without limitation the rights to use, copy, + modify, merge, publish, distribute, sublicense, and/or sell copies + of the Software, and to permit persons to whom the Software is + furnished to do so, subject to the following conditions: + + The above copyright notice and this permission notice shall be + included in all copies or substantial portions of the Software. + + THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, + EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF + MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND + NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS + BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN + ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN + CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE + SOFTWARE. + +====================================================================== + +Kerberos V5 includes documentation and software developed at the +University of California at Berkeley, which includes this copyright +notice: + + Copyright (C) 1983 Regents of the University of California. + All rights reserved. + + Redistribution and use in source and binary forms, with or without + modification, are permitted provided that the following conditions + are met: + + 1. Redistributions of source code must retain the above copyright + notice, this list of conditions and the following disclaimer. + + 2. Redistributions in binary form must reproduce the above + copyright notice, this list of conditions and the following + disclaimer in the documentation and/or other materials provided + with the distribution. + + 3. Neither the name of the University nor the names of its + contributors may be used to endorse or promote products derived + from this software without specific prior written permission. + + THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS "AS IS" + AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED + TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A + PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS + OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, + SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT + LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF + USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND + ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, + OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT + OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + SUCH DAMAGE. + +====================================================================== + +Portions contributed by Novell, Inc., including the LDAP database +backend, are subject to the following license: + + Copyright (C) 2004-2005, Novell, Inc. + All rights reserved. + + Redistribution and use in source and binary forms, with or without + modification, are permitted provided that the following conditions + are met: + + * Redistributions of source code must retain the above copyright + notice, this list of conditions and the following disclaimer. + + * Redistributions in binary form must reproduce the above copyright + notice, this list of conditions and the following disclaimer in + the documentation and/or other materials provided with the + distribution. + + * The copyright holder's name is not used to endorse or promote + products derived from this software without specific prior + written permission. + + THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS + FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE + COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, + INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES + (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR + SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, + STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) + ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED + OF THE POSSIBILITY OF SUCH DAMAGE. + +====================================================================== + +Portions funded by Sandia National Laboratory and developed by the +University of Michigan's Center for Information Technology +Integration, including the PKINIT implementation, are subject to the +following license: + + COPYRIGHT (C) 2006-2007 + THE REGENTS OF THE UNIVERSITY OF MICHIGAN + ALL RIGHTS RESERVED + + Permission is granted to use, copy, create derivative works and + redistribute this software and such derivative works for any + purpose, so long as the name of The University of Michigan is not + used in any advertising or publicity pertaining to the use of + distribution of this software without specific, written prior + authorization. If the above copyright notice or any other + identification of the University of Michigan is included in any + copy of any portion of this software, then the disclaimer below + must also be included. + + THIS SOFTWARE IS PROVIDED AS IS, WITHOUT REPRESENTATION FROM THE + UNIVERSITY OF MICHIGAN AS TO ITS FITNESS FOR ANY PURPOSE, AND + WITHOUT WARRANTY BY THE UNIVERSITY OF MICHIGAN OF ANY KIND, EITHER + EXPRESS OR IMPLIED, INCLUDING WITHOUT LIMITATION THE IMPLIED + WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE. + THE REGENTS OF THE UNIVERSITY OF MICHIGAN SHALL NOT BE LIABLE FOR + ANY DAMAGES, INCLUDING SPECIAL, INDIRECT, INCIDENTAL, OR + CONSEQUENTIAL DAMAGES, WITH RESPECT TO ANY CLAIM ARISING OUT OF OR + IN CONNECTION WITH THE USE OF THE SOFTWARE, EVEN IF IT HAS BEEN OR + IS HEREAFTER ADVISED OF THE POSSIBILITY OF SUCH DAMAGES. + +====================================================================== + +The pkcs11.h file included in the PKINIT code has the following +license: + + Copyright 2006 g10 Code GmbH + Copyright 2006 Andreas Jellinghaus + + This file is free software; as a special exception the author gives + unlimited permission to copy and/or distribute it, with or without + modifications, as long as this notice is preserved. + + This file is distributed in the hope that it will be useful, but + WITHOUT ANY WARRANTY, to the extent permitted by law; without even + the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR + PURPOSE. + +====================================================================== + +Portions contributed by Apple Inc. are subject to the following +license: + + Copyright 2004-2008 Apple Inc. All Rights Reserved. + + Export of this software from the United States of America may + require a specific license from the United States Government. + It is the responsibility of any person or organization + contemplating export to obtain such a license before exporting. + + WITHIN THAT CONSTRAINT, permission to use, copy, modify, and + distribute this software and its documentation for any purpose and + without fee is hereby granted, provided that the above copyright + notice appear in all copies and that both that copyright notice and + this permission notice appear in supporting documentation, and that + the name of Apple Inc. not be used in advertising or publicity + pertaining to distribution of the software without specific, + written prior permission. Apple Inc. makes no representations + about the suitability of this software for any purpose. It is + provided "as is" without express or implied warranty. + + THIS SOFTWARE IS PROVIDED "AS IS" AND WITHOUT ANY EXPRESS OR + IMPLIED WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED + WARRANTIES OF MERCHANTIBILITY AND FITNESS FOR A PARTICULAR PURPOSE. + +====================================================================== + +The implementations of UTF-8 string handling in src/util/support and +src/lib/krb5/unicode are subject to the following copyright and +permission notice: + + The OpenLDAP Public License + Version 2.8, 17 August 2003 + + Redistribution and use of this software and associated + documentation ("Software"), with or without modification, are + permitted provided that the following conditions are met: + + 1. Redistributions in source form must retain copyright statements + and notices, + + 2. Redistributions in binary form must reproduce applicable + copyright statements and notices, this list of conditions, and + the following disclaimer in the documentation and/or other + materials provided with the distribution, and + + 3. Redistributions must contain a verbatim copy of this document. + + The OpenLDAP Foundation may revise this license from time to time. + Each revision is distinguished by a version number. You may use + this Software under terms of this license revision or under the + terms of any subsequent revision of the license. + + THIS SOFTWARE IS PROVIDED BY THE OPENLDAP FOUNDATION AND ITS + CONTRIBUTORS "AS IS" AND ANY EXPRESSED OR IMPLIED WARRANTIES, + INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF + MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE + DISCLAIMED. IN NO EVENT SHALL THE OPENLDAP FOUNDATION, ITS + CONTRIBUTORS, OR THE AUTHOR(S) OR OWNER(S) OF THE SOFTWARE BE + LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT + OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR + BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF + LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE + USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH + DAMAGE. + + The names of the authors and copyright holders must not be used in + advertising or otherwise to promote the sale, use or other dealing + in this Software without specific, written prior permission. Title + to copyright in this Software shall at all times remain with + copyright holders. + + OpenLDAP is a registered trademark of the OpenLDAP Foundation. + + Copyright 1999-2003 The OpenLDAP Foundation, Redwood City, + California, USA. All Rights Reserved. Permission to copy and + distribute verbatim copies of this document is granted. + +Marked test programs in src/lib/krb5/krb have the following copyright: + + + Copyright (C) 2006 Kungliga Tekniska Högskolan + (Royal Institute of Technology, Stockholm, Sweden). + All rights reserved. + + Redistribution and use in source and binary forms, with or without + modification, are permitted provided that the following conditions + are met: + + 1. Redistributions of source code must retain the above copyright + notice, this list of conditions and the following disclaimer. + + 2. Redistributions in binary form must reproduce the above + copyright notice, this list of conditions and the following + disclaimer in the documentation and/or other materials provided + with the distribution. + + 3. Neither the name of KTH nor the names of its contributors may be + used to endorse or promote products derived from this software + without specific prior written permission. + + THIS SOFTWARE IS PROVIDED BY KTH AND ITS CONTRIBUTORS "AS IS" AND + ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, + THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A + PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL KTH OR ITS + CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, + SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT + LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF + USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND + ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, + OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT + OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + SUCH DAMAGE. + +====================================================================== + +The KCM Mach RPC definition file used on macOS has the following +copyright: + + Copyright (C) 2009 Kungliga Tekniska Högskolan + (Royal Institute of Technology, Stockholm, Sweden). + All rights reserved. + + Portions Copyright (C) 2009 Apple Inc. All rights reserved. + + Redistribution and use in source and binary forms, with or without + modification, are permitted provided that the following conditions + are met: + + 1. Redistributions of source code must retain the above + copyright notice, this list of conditions and the following + disclaimer. + + 2. Redistributions in binary form must reproduce the above + copyright notice, this list of conditions and the following + disclaimer in the documentation and/or other materials provided + with the distribution. + + 3. Neither the name of the Institute nor the names of its + contributors may be used to endorse or promote products derived + from this software without specific prior written permission. + + THIS SOFTWARE IS PROVIDED BY THE INSTITUTE AND CONTRIBUTORS "AS IS" + AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED + TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A + PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE INSTITUTE + OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, + SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT + LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF + USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND + ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, + OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT + OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + SUCH DAMAGE. + +====================================================================== + +Portions of the RPC implementation in src/lib/rpc and +src/include/gssrpc have the following copyright and permission notice: + + Copyright (C) 2010, Oracle America, Inc. + + All rights reserved. + + Redistribution and use in source and binary forms, with or without + modification, are permitted provided that the following conditions + are met: + + 1. Redistributions of source code must retain the above copyright + notice, this list of conditions and the following disclaimer. + + 2. Redistributions in binary form must reproduce the above + copyright notice, this list of conditions and the following + disclaimer in the documentation and/or other materials provided + with the distribution. + + 3. Neither the name of the "Oracle America, Inc." nor the names of + its contributors may be used to endorse or promote products + derived from this software without specific prior written + permission. + + THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS + FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE + COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, + INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES + (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR + SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, + STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) + ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED + OF THE POSSIBILITY OF SUCH DAMAGE. + +====================================================================== + + Copyright (C) 2006,2007,2009 NTT (Nippon Telegraph and Telephone + Corporation). All rights reserved. + + Redistribution and use in source and binary forms, with or without + modification, are permitted provided that the following conditions + are met: + + 1. Redistributions of source code must retain the above copyright + notice, this list of conditions and the following disclaimer as + the first lines of this file unmodified. + + 2. Redistributions in binary form must reproduce the above + copyright notice, this list of conditions and the following + disclaimer in the documentation and/or other materials provided + with the distribution. + + THIS SOFTWARE IS PROVIDED BY NTT "AS IS" AND ANY EXPRESS OR IMPLIED + WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES + OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE + DISCLAIMED. IN NO EVENT SHALL NTT BE LIABLE FOR ANY DIRECT, + INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES + (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR + SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, + STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) + ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED + OF THE POSSIBILITY OF SUCH DAMAGE. + +====================================================================== + + Copyright 2000 by Carnegie Mellon University + + All Rights Reserved + + Permission to use, copy, modify, and distribute this software and + its documentation for any purpose and without fee is hereby + granted, provided that the above copyright notice appear in all + copies and that both that copyright notice and this permission + notice appear in supporting documentation, and that the name of + Carnegie Mellon University not be used in advertising or publicity + pertaining to distribution of the software without specific, + written prior permission. + + CARNEGIE MELLON UNIVERSITY DISCLAIMS ALL WARRANTIES WITH REGARD TO + THIS SOFTWARE, INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY + AND FITNESS, IN NO EVENT SHALL CARNEGIE MELLON UNIVERSITY BE LIABLE + FOR ANY SPECIAL, INDIRECT OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES + WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN + AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING + OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS + SOFTWARE. + +====================================================================== + + Copyright (C) 2002 Naval Research Laboratory (NRL/CCS) + + Permission to use, copy, modify and distribute this software and + its documentation is hereby granted, provided that both the + copyright notice and this permission notice appear in all copies of + the software, derivative works or modified versions, and any + portions thereof. + + NRL ALLOWS FREE USE OF THIS SOFTWARE IN ITS "AS IS" CONDITION AND + DISCLAIMS ANY LIABILITY OF ANY KIND FOR ANY DAMAGES WHATSOEVER + RESULTING FROM THE USE OF THIS SOFTWARE. + +====================================================================== + +Portions extracted from Internet RFCs have the following copyright +notice: + + Copyright (C) The Internet Society (2006). + + This document is subject to the rights, licenses and restrictions + contained in BCP 78, and except as set forth therein, the authors + retain all their rights. + + This document and the information contained herein are provided on + an "AS IS" basis and THE CONTRIBUTOR, THE ORGANIZATION HE/SHE + REPRESENTS OR IS SPONSORED BY (IF ANY), THE INTERNET SOCIETY AND + THE INTERNET ENGINEERING TASK FORCE DISCLAIM ALL WARRANTIES, + EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO ANY WARRANTY THAT + THE USE OF THE INFORMATION HEREIN WILL NOT INFRINGE ANY RIGHTS OR + ANY IMPLIED WARRANTIES OF MERCHANTABILITY OR FITNESS FOR A + PARTICULAR PURPOSE. + +====================================================================== + + Copyright (C) 1991, 1992, 1994 by Cygnus Support. + + Permission to use, copy, modify, and distribute this software and + its documentation for any purpose and without fee is hereby + granted, provided that the above copyright notice appear in all + copies and that both that copyright notice and this permission + notice appear in supporting documentation. Cygnus Support makes no + representations about the suitability of this software for any + purpose. It is provided "as is" without express or implied + warranty. + +====================================================================== + + Copyright (C) 2006 Secure Endpoints Inc. + + Permission is hereby granted, free of charge, to any person + obtaining a copy of this software and associated documentation + files (the "Software"), to deal in the Software without + restriction, including without limitation the rights to use, copy, + modify, merge, publish, distribute, sublicense, and/or sell copies + of the Software, and to permit persons to whom the Software is + furnished to do so, subject to the following conditions: + + The above copyright notice and this permission notice shall be + included in all copies or substantial portions of the Software. + + THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, + EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF + MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND + NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS + BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN + ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN + CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE + SOFTWARE. + +====================================================================== + +Portions of the implementation of the Fortuna-like PRNG are subject to +the following notice: + + + Copyright (C) 2005 Marko Kreen + All rights reserved. + + Redistribution and use in source and binary forms, with or without + modification, are permitted provided that the following conditions + are met: + + 1. Redistributions of source code must retain the above copyright + notice, this list of conditions and the following disclaimer. + + 2. Redistributions in binary form must reproduce the above + copyright notice, this list of conditions and the following + disclaimer in the documentation and/or other materials provided + with the distribution. + + THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS "AS IS" + AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED + TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A + PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR + CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, + SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT + LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF + USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND + ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, + OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT + OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + SUCH DAMAGE. + + Copyright (C) 1994 by the University of Southern California + + EXPORT OF THIS SOFTWARE from the United States of America may + require a specific license from the United States Government. It + is the responsibility of any person or organization + contemplating export to obtain such a license before exporting. + + WITHIN THAT CONSTRAINT, permission to copy, modify, and distribute + this software and its documentation in source and binary forms is + hereby granted, provided that any documentation or other materials + related to such distribution or use acknowledge that the software + was developed by the University of Southern California. + + DISCLAIMER OF WARRANTY. THIS SOFTWARE IS PROVIDED "AS IS". The + University of Southern California MAKES NO REPRESENTATIONS OR + WARRANTIES, EXPRESS OR IMPLIED. By way of example, but not + limitation, the University of Southern California MAKES NO + REPRESENTATIONS OR WARRANTIES OF MERCHANTABILITY OR FITNESS FOR ANY + PARTICULAR PURPOSE. The University of Southern California shall not + be held liable for any liability nor for any direct, indirect, or + consequential damages with respect to any claim by the user or + distributor of the ksu software. + +====================================================================== + + Copyright (C) 1995 + The President and Fellows of Harvard University + + This code is derived from software contributed to Harvard by Jeremy + Rassen. + + Redistribution and use in source and binary forms, with or without + modification, are permitted provided that the following conditions + are met: + + 1. Redistributions of source code must retain the above copyright + notice, this list of conditions and the following disclaimer. + + 2. Redistributions in binary form must reproduce the above + copyright notice, this list of conditions and the following + disclaimer in the documentation and/or other materials provided + with the distribution. + + 3. All advertising materials mentioning features or use of this + software must display the following acknowledgement: + + This product includes software developed by the University of + California, Berkeley and its contributors. + + 4. Neither the name of the University nor the names of its + contributors may be used to endorse or promote products derived + from this software without specific prior written permission. + + THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS "AS IS" + AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED + TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A + PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS + OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, + SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT + LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF + USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND + ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, + OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT + OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + SUCH DAMAGE. + +====================================================================== + + Copyright (C) 2008 by the Massachusetts Institute of Technology. + Copyright 1995 by Richard P. Basch. All Rights Reserved. + Copyright 1995 by Lehman Brothers, Inc. All Rights Reserved. + + Export of this software from the United States of America may + require a specific license from the United States Government. It + is the responsibility of any person or organization + contemplating export to obtain such a license before exporting. + + WITHIN THAT CONSTRAINT, permission to use, copy, modify, and + distribute this software and its documentation for any purpose and + without fee is hereby granted, provided that the above copyright + notice appear in all copies and that both that copyright notice and + this permission notice appear in supporting documentation, and that + the name of Richard P. Basch, Lehman Brothers and M.I.T. not be + used in advertising or publicity pertaining to distribution of the + software without specific, written prior permission. Richard P. + Basch, Lehman Brothers and M.I.T. make no representations about the + suitability of this software for any purpose. It is provided "as + is" without express or implied warranty. + +====================================================================== + +The following notice applies to "src/lib/krb5/krb/strptime.c" and +"src/include/k5-queue.h". + + Copyright (C) 1997, 1998 The NetBSD Foundation, Inc. + All rights reserved. + + This code was contributed to The NetBSD Foundation by Klaus Klein. + + Redistribution and use in source and binary forms, with or without + modification, are permitted provided that the following conditions + are met: + + 1. Redistributions of source code must retain the above copyright + notice, this list of conditions and the following disclaimer. + + 2. Redistributions in binary form must reproduce the above + copyright notice, this list of conditions and the following + disclaimer in the documentation and/or other materials provided + with the distribution. + + 3. All advertising materials mentioning features or use of this + software must display the following acknowledgement: + + This product includes software developed by the NetBSD + Foundation, Inc. and its contributors. + + 4. Neither the name of The NetBSD Foundation nor the names of its + contributors may be used to endorse or promote products derived + from this software without specific prior written permission. + + THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. AND + CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, + INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF + MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE + DISCLAIMED. IN NO EVENT SHALL THE FOUNDATION OR CONTRIBUTORS BE + LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT + OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR + BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF + LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE + USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH + DAMAGE. + +====================================================================== + +The following notice applies to Unicode library files in +"src/lib/krb5/unicode": + + Copyright 1997, 1998, 1999 Computing Research Labs, + New Mexico State University + + Permission is hereby granted, free of charge, to any person + obtaining a copy of this software and associated documentation + files (the "Software"), to deal in the Software without + restriction, including without limitation the rights to use, copy, + modify, merge, publish, distribute, sublicense, and/or sell copies + of the Software, and to permit persons to whom the Software is + furnished to do so, subject to the following conditions: + + The above copyright notice and this permission notice shall be + included in all copies or substantial portions of the Software. + THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, + EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF + MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND + NONINFRINGEMENT. IN NO EVENT SHALL THE COMPUTING RESEARCH LAB OR + NEW MEXICO STATE UNIVERSITY BE LIABLE FOR ANY CLAIM, DAMAGES OR + OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR + OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE + OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. + +====================================================================== + +The following notice applies to "src/util/support/strlcpy.c": + + Copyright (C) 1998 Todd C. Miller "Todd.Miller@courtesan.com" + + Permission to use, copy, modify, and distribute this software for + any purpose with or without fee is hereby granted, provided that + the above copyright notice and this permission notice appear in all + copies. + + THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL + WARRANTIES WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED + WARRANTIES OF MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE + AUTHOR BE LIABLE FOR ANY SPECIAL, DIRECT, INDIRECT, OR + CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS + OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, + NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN + CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. + +====================================================================== + +The following notice applies to "src/util/profile/argv_parse.c" and +"src/util/profile/argv_parse.h": + + Copyright 1999 by Theodore Ts'o. + + Permission to use, copy, modify, and distribute this software for + any purpose with or without fee is hereby granted, provided that + the above copyright notice and this permission notice appear in all + copies. THE SOFTWARE IS PROVIDED "AS IS" AND THEODORE TS'O (THE + AUTHOR) DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE, + INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS. IN + NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY SPECIAL, DIRECT, + INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER + RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION + OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR + IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. (Isn't + it sick that the U.S. culture of lawsuit-happy lawyers requires + this kind of disclaimer?) + +====================================================================== + +The following notice applies to SWIG-generated code in +"src/util/profile/profile_tcl.c": + + Copyright (C) 1999-2000, The University of Chicago + + This file may be freely redistributed without license or fee + provided this copyright message remains intact. + +====================================================================== + +The following notice applies to portiions of "src/lib/rpc" and +"src/include/gssrpc": + + Copyright (C) 2000 The Regents of the University of Michigan. All + rights reserved. + + Copyright (C) 2000 Dug Song "dugsong@UMICH.EDU". All rights + reserved, all wrongs reversed. + + Redistribution and use in source and binary forms, with or without + modification, are permitted provided that the following conditions + are met: + + 1. Redistributions of source code must retain the above copyright + notice, this list of conditions and the following disclaimer. + + 2. Redistributions in binary form must reproduce the above + copyright notice, this list of conditions and the following + disclaimer in the documentation and/or other materials provided + with the distribution. + + 3. Neither the name of the University nor the names of its + contributors may be used to endorse or promote products derived + from this software without specific prior written permission. + + THIS SOFTWARE IS PROVIDED "AS IS" AND ANY EXPRESS OR IMPLIED + WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES + OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE + DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE + FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT + OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR + BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF + LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE + USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH + DAMAGE. + +Implementations of the MD4 algorithm are subject to the following +notice: + + Copyright (C) 1990, RSA Data Security, Inc. All rights reserved. + + License to copy and use this software is granted provided that it + is identified as the "RSA Data Security, Inc. MD4 Message Digest + Algorithm" in all material mentioning or referencing this software + or this function. + + License is also granted to make and use derivative works provided + that such works are identified as "derived from the RSA Data + Security, Inc. MD4 Message Digest Algorithm" in all material + mentioning or referencing the derived work. + + RSA Data Security, Inc. makes no representations concerning either + the merchantability of this software or the suitability of this + software for any particular purpose. It is provided "as is" + without express or implied warranty of any kind. + + These notices must be retained in any copies of any part of this + documentation and/or software. + +====================================================================== + +Implementations of the MD5 algorithm are subject to the following +notice: + + Copyright (C) 1990, RSA Data Security, Inc. All rights reserved. + + License to copy and use this software is granted provided that it + is identified as the "RSA Data Security, Inc. MD5 Message- Digest + Algorithm" in all material mentioning or referencing this software + or this function. + + License is also granted to make and use derivative works provided + that such works are identified as "derived from the RSA Data + Security, Inc. MD5 Message-Digest Algorithm" in all material + mentioning or referencing the derived work. + + RSA Data Security, Inc. makes no representations concerning either + the merchantability of this software or the suitability of this + software for any particular purpose. It is provided "as is" + without express or implied warranty of any kind. + + These notices must be retained in any copies of any part of this + documentation and/or software. + +====================================================================== + +The following notice applies to +"src/lib/crypto/crypto_tests/t_mddriver.c": + + Copyright (C) 1990-2, RSA Data Security, Inc. Created 1990. All + rights reserved. + + RSA Data Security, Inc. makes no representations concerning either + the merchantability of this software or the suitability of this + software for any particular purpose. It is provided "as is" without + express or implied warranty of any kind. + + These notices must be retained in any copies of any part of this + documentation and/or software. + +====================================================================== + +Portions of "src/lib/krb5" are subject to the following notice: + + Copyright (C) 1994 CyberSAFE Corporation. + Copyright 1990,1991,2007,2008 by the Massachusetts Institute of +Technology. + All Rights Reserved. + + Export of this software from the United States of America may + require a specific license from the United States Government. It + is the responsibility of any person or organization + contemplating export to obtain such a license before exporting. + + WITHIN THAT CONSTRAINT, permission to use, copy, modify, and + distribute this software and its documentation for any purpose and + without fee is hereby granted, provided that the above copyright + notice appear in all copies and that both that copyright notice and + this permission notice appear in supporting documentation, and that + the name of M.I.T. not be used in advertising or publicity + pertaining to distribution of the software without specific, + written prior permission. Furthermore if you modify this software + you must label your software as modified software and not + distribute it in such a fashion that it might be confused with the + original M.I.T. software. Neither M.I.T., the Open Computing + Security Group, nor CyberSAFE Corporation make any representations + about the suitability of this software for any purpose. It is + provided "as is" without express or implied warranty. + +====================================================================== + +Portions contributed by PADL Software are subject to the following +license: + + Copyright (c) 2011, PADL Software Pty Ltd. All rights reserved. + + Redistribution and use in source and binary forms, with or without + modification, are permitted provided that the following conditions + are met: + + 1. Redistributions of source code must retain the above copyright + notice, this list of conditions and the following disclaimer. + + 2. Redistributions in binary form must reproduce the above + copyright notice, this list of conditions and the following + disclaimer in the documentation and/or other materials provided + with the distribution. + + 3. Neither the name of PADL Software nor the names of its + contributors may be used to endorse or promote products derived + from this software without specific prior written permission. + + THIS SOFTWARE IS PROVIDED BY PADL SOFTWARE AND CONTRIBUTORS "AS IS" + AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED + TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A + PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL PADL SOFTWARE + OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, + SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT + LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF + USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND + ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, + OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT + OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + SUCH DAMAGE. + +====================================================================== + +The bundled libev source code is subject to the following license: + + All files in libev are Copyright (C)2007,2008,2009 Marc Alexander + Lehmann. + + Redistribution and use in source and binary forms, with or without + modification, are permitted provided that the following conditions + are met: + + * Redistributions of source code must retain the above copyright + notice, this list of conditions and the following disclaimer. + + * Redistributions in binary form must reproduce the above copyright + notice, this list of conditions and the following disclaimer in + the documentation and/or other materials provided with the + distribution. + + THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS + FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE + COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, + INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES + (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR + SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, + STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) + ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED + OF THE POSSIBILITY OF SUCH DAMAGE. + + Alternatively, the contents of this package may be used under the + terms of the GNU General Public License ("GPL") version 2 or any + later version, in which case the provisions of the GPL are + applicable instead of the above. If you wish to allow the use of + your version of this package only under the terms of the GPL and + not to allow others to use your version of this file under the BSD + license, indicate your decision by deleting the provisions above + and replace them with the notice and other provisions required by + the GPL in this and the other files of this package. If you do not + delete the provisions above, a recipient may use your version of + this file under either the BSD or the GPL. + +====================================================================== + +Files copied from the Intel AESNI Sample Library are subject to the +following license: + + Copyright (C) 2010, Intel Corporation + All rights reserved. + + Redistribution and use in source and binary forms, with or without + modification, are permitted provided that the following conditions + are met: + + * Redistributions of source code must retain the above copyright + notice, this list of conditions and the following disclaimer. + + * Redistributions in binary form must reproduce the above + copyright notice, this list of conditions and the following + disclaimer in the documentation and/or other materials + provided with the distribution. + + * Neither the name of Intel Corporation nor the names of its + contributors may be used to endorse or promote products + derived from this software without specific prior written + permission. + + THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS + FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE + COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, + INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES + (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR + SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, + STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) + ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED + OF THE POSSIBILITY OF SUCH DAMAGE. + +====================================================================== + +The following notice applies to +"src/ccapi/common/win/OldCC/autolock.hxx": + + Copyright (C) 1998 by Danilo Almeida. All rights reserved. + + Redistribution and use in source and binary forms, with or without + modification, are permitted provided that the following conditions + are met: + + * Redistributions of source code must retain the above copyright + notice, this list of conditions and the following disclaimer. + + * Redistributions in binary form must reproduce the above + copyright notice, this list of conditions and the following + disclaimer in the documentation and/or other materials provided + with the distribution. + + THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS + FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE + COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, + INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES + (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR + SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, + STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) + ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED + OF THE POSSIBILITY OF SUCH DAMAGE. + + ====================================================================== + ====================================================================== + +Libaio + +You may be receiving a copy of the Libaio library with this MySQL +product. The terms of the Oracle license do NOT apply to the Libaio +library; it is licensed under the following license, separately from +the Oracle programs you receive. If you do not wish to install this +program, you may delete its files. + +This component is licensed under +GNU Lesser General Public License v2.1, February 1999. +See the 'Standard Licenses' section for license text. + + ====================================================================== + ====================================================================== + +libevent + +Copyright (c) 2000-2007 Niels Provos +Copyright (c) 2007-2012 Niels Provos and Nick Mathewson + +Redistribution and use in source and binary forms, with or without +modification, are permitted provided that the following conditions +are met: +1. Redistributions of source code must retain the above copyright + notice, this list of conditions and the following disclaimer. +2. Redistributions in binary form must reproduce the above copyright + notice, this list of conditions and the following disclaimer in the + documentation and/or other materials provided with the distribution. +3. The name of the author may not be used to endorse or promote products + derived from this software without specific prior written permission. + +THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR +IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES +OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. +IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, +INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT +NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, +DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY +THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF +THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. +============================== + +Portions of Libevent are based on works by others, also made available by +them under the three-clause BSD license above. The copyright notices are +available in the corresponding source files; the license is as above. Here's +a list: + +log.c: + Copyright (c) 2000 Dug Song + Copyright (c) 1993 The Regents of the University of California. + +strlcpy.c: + Copyright (c) 1998 Todd C. Miller + +win32select.c: + Copyright (c) 2003 Michael A. Davis + +evport.c: + Copyright (c) 2007 Sun Microsystems + +ht-internal.h: + Copyright (c) 2002 Christopher Clark + +minheap-internal.h: + Copyright (c) 2006 Maxim Yegorushkin + +============================== + +The arc4module is available under the following, sometimes called the +"OpenBSD" license: + + Copyright (c) 1996, David Mazieres + Copyright (c) 2008, Damien Miller + + Permission to use, copy, modify, and distribute this software for any + purpose with or without fee is hereby granted, provided that the above + copyright notice and this permission notice appear in all copies. + + THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES + WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF + MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR + ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES + WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN + ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF + OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. + +============================== + +The Windows timer code is based on code from libutp, which is +distributed under this license, sometimes called the "MIT" license. + +Copyright (c) 2010 BitTorrent, Inc. + +Permission is hereby granted, free of charge, to any person obtaining a copy +of this software and associated documentation files (the "Software"), to deal +in the Software without restriction, including without limitation the rights +to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +copies of the Software, and to permit persons to whom the Software is +furnished to do so, subject to the following conditions: + +The above copyright notice and this permission notice shall be included in +all copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN +THE SOFTWARE. + + ====================================================================== + ====================================================================== + +LibFIDO + +Copyright (c) 2018-2021 Yubico AB. All rights reserved. + +Redistribution and use in source and binary forms, with or without +modification, are permitted provided that the following conditions are +met: + + 1. Redistributions of source code must retain the above copyright + notice, this list of conditions and the following disclaimer. + 2. Redistributions in binary form must reproduce the above copyright + notice, this list of conditions and the following disclaimer in + the documentation and/or other materials provided with the + distribution. + +THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS +"AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT +LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR +A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT +HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, +SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT +LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, +DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY +THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + +4th Party +========= + +libcbor +------- + +MIT License + +Copyright (c) 2014-2017 Pavel Kalvoda + +Permission is hereby granted, free of charge, to any person obtaining a copy +of this software and associated documentation files (the "Software"), to deal +in the Software without restriction, including without limitation the rights +to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +copies of the Software, and to permit persons to whom the Software is +furnished to do so, subject to the following conditions: + +The above copyright notice and this permission notice shall be included in +all copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE +SOFTWARE. + +------------------------------------------------------------------------------ +---- +zlib +---- + +Copyright notice: + + (C) 1995-2017 Jean-loup Gailly and Mark Adler + + This software is provided 'as-is', without any express or implied + warranty. In no event will the authors be held liable for any damages + arising from the use of this software. + + Permission is granted to anyone to use this software for any purpose, + including commercial applications, and to alter it and redistribute it + freely, subject to the following restrictions: + + 1. The origin of this software must not be misrepresented; you must not + claim that you wrote the original software. If you use this software + in a product, an acknowledgment in the product documentation would be + appreciated but is not required. + 2. Altered source versions must be plainly marked as such, and must not be + misrepresented as being the original software. + 3. This notice may not be removed or altered from any source distribution. + + Jean-loup Gailly Mark Adler + jloup@gzip.org madler@alumni.caltech.edu + +If you use the zlib library in a product, we would appreciate *not* receiving +lengthy legal documents to sign. The sources are provided for free but +without warranty of any kind. The library has been entirely written by +Jean-loup Gailly and Mark Adler; it does not include third-party code. + +If you redistribute modified sources, we would appreciate that you include in +the file ChangeLog history information documenting your changes. Please read +the FAQ for more information on the distribution of modified source versions. + +------------------------------------------------------------------------------ +OpenSSL (See its own license section) +------------------------------------------------------------------------------ + + ====================================================================== + ====================================================================== + +libtirpc + +/* + * Copyright (c) Copyright (c) Bull S.A. 2005 All Rights Reserved. + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. The name of the author may not be used to endorse or promote products + * derived from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR + * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES + * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. + * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, + * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT + * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, + * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY + * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF + * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + + ====================================================================== + ====================================================================== + +LZ4 + +LZ4 Library +Copyright (c) 2011-2016, Yann Collet +All rights reserved. + +Redistribution and use in source and binary forms, with or without +modification, are permitted provided that the following conditions are met: + +* Redistributions of source code must retain the above copyright notice, + this list of conditions and the following disclaimer. + +* Redistributions in binary form must reproduce the above copyright notice, + this list of conditions and the following disclaimer in the documentation + and/or other materials provided with the distribution. + +THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND +ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED +WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE +DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR +ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES +(INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; +LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON +ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS +SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + + ====================================================================== + ====================================================================== + +MeCab + +Copyright (c) 2001-2008, Taku Kudo +Copyright (c) 2004-2008, Nippon Telegraph and Telephone Corporation +All rights reserved. + +Redistribution and use in source and binary forms, with or without +modification, are permitted provided that the following conditions +are met: + + * Redistributions of source code must retain the above + copyright notice, this list of conditions and the + following disclaimer. + + * Redistributions in binary form must reproduce the above + copyright notice, this list of conditions and the + following disclaimer in the documentation and/or other + materials provided with the distribution. + + * Neither the name of the Nippon Telegraph and Telegraph Corporation + nor the names of its contributors may be used to endorse or + promote products derived from this software without specific + prior written permission. + +THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS +"AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT +LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS +FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE +COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, +INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, +BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; +LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER +CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT +LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN +ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE +POSSIBILITY OF SUCH DAMAGE. + + ====================================================================== + ====================================================================== + +MeCab Dictionary + +Copyright 2000, 2001, 2002, 2003 Nara Institute of Science and Technology. +All Rights Reserved. + +Use, reproduction, and distribution of this software is permitted. Any copy +of this software, whether in its original form or modified, must include both +the above copyright notice and the following paragraphs. + +Nara Institute of Science and Technology (NAIST), the copyright holders, +disclaims all warranties with regard to this software, including all implied +warranties of merchantability and fitness, in no event shall NAIST be liable +for any special, indirect or consequential damages or any damages whatsoever +resulting from loss of use, data or profits, whether in an action of +contract, negligence or other tortuous action, arising out of or in +connection with the use or performance of this software. + +A large portion of the dictionary entries originate from ICOT Free Software. +The following conditions for ICOT Free Software applies to the current +dictionary as well. + +Each User may also freely distribute the Program, whether in its original +form or modified, to any third party or parties, PROVIDED that the provisions +of Section 3 ("NO WARRANTY") will ALWAYS appear on, or be attached to, the +Program, which is distributed substantially in the same form as set out +herein and that such intended distribution, if actually made, will neither +violate or otherwise contravene any of the laws and regulations of the +countries having jurisdiction over the User or the intended distribution +itself. + +NO WARRANTY + +The program was produced on an experimental basis in the course of the +research and development conducted during the project and is provided to +users as so produced on an experimental basis. Accordingly, the program is +provided without any warranty whatsoever, whether express, implied, statutory +or otherwise. The term "warranty" used herein +includes, but is not limited to, any warranty of the quality, performance, +merchantability and fitness for a particular purpose of the program and the +nonexistence of any infringement or violation of any right of any third +party. + +Each user of the program will agree and understand, and be deemed to have +agreed and understood, that there is no warranty whatsoever for the program +and, accordingly, the entire risk arising from or otherwise connected with +the program is assumed by the user. + +Therefore, neither ICOT, the copyright holder, or any other organization that +participated in or was otherwise related to the development of the program +and their respective officials, directors, officers and other employees shall +be held liable for any and all damages, including, without limitation, +general, special, incidental and consequential damages, arising out of or +otherwise in connection with the use or inability to use the program or any +product, material or result produced or otherwise obtained by using the +program, regardless of whether they have been advised of, or otherwise had +knowledge of, the possibility of such damages at any time during the project +or thereafter. Each user will be deemed to have agreed to the foregoing by +his or her commencement of use of the program. The term "use" as used herein +includes, but is not limited to, the use, modification, copying and +distribution of the program and the production of secondary products from the +program. + +In the case where the program, whether in its original form or modified, was +distributed or delivered to or received by a user from any person, +organization or entity other than ICOT, unless it makes or grants +independently of ICOT any specific warranty to the user in writing, such +person, organization or entity, will also be exempted from and not be held +liable to the user for any such damages as noted above as far as the program +is concerned. + + ====================================================================== + ====================================================================== + +memcached + +Copyright (c) 2003, Danga Interactive, Inc. +All rights reserved. + +Redistribution and use in source and binary forms, with or without +modification, are permitted provided that the following conditions +are met: + + * Redistributions of source code must retain the above copyright +notice, this list of conditions and the following disclaimer. + + * Redistributions in binary form must reproduce the above +copyright notice, this list of conditions and the following disclaimer +in the documentation and/or other materials provided with the +distribution. + + * Neither the name of the Danga Interactive nor the names of its +contributors may be used to endorse or promote products derived from +this software without specific prior written permission. + +THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS +"AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT +LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR +A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT +OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, +SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT +LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, +DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY +THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + + ====================================================================== + ====================================================================== + +Memcached.pm + +Memcached.pm is licensed under the Perl license. + +Oracle may use, redistribute and/or modify this code under the terms of +either: + + a) the GNU General Public License as published by the Free Software +Foundation; either version 1, or (at your option) any later version, or + + b) the "Artistic License" which comes with the Expect/pr code. + +Oracle elects to use the Artistic license for all versions of MySQL + +A copy of the GPLv2 and the Artistic License (Perl) 1.0 must be included with +any distribution. + +This component is licensed under +the GNU GPL license, version 2.0. + +This component is licensed under +Artistic License (Perl) 1.0. + + ====================================================================== + ====================================================================== + +nt_servc (Windows NT Service class library) + +Windows NT Service class library +Copyright Abandoned 1998 Irena Pancirov - Irnet Snc +This file is public domain and comes with NO WARRANTY of any kind + + ====================================================================== + ====================================================================== + +OpenSSL 3.0 + +You may be receiving a copy of OpenSSL 3.0 as part of this product in +object code form. +The terms of the Oracle license do NOT apply to OpenSSL 3.0. +OpenSSL 3.0 is licensed under the Apache 2.0 license, separate from +the Oracle product. +If you do not wish to install this library, you may remove it, but +the Oracle program might not operate properly or at all without it. + +/* + * Copyright 2003-2022 The OpenSSL Project Authors. All Rights Reserved. + * + * Licensed under the Apache License 2.0 (the "License"). You may not use + * this file except in compliance with the License. You can obtain a copy + * in the file LICENSE in the source distribution or at + * https://www.openssl.org/source/license.html +*/ + +See Apache License v2.0, January 2004 in the +'Standard Licenses' section. + + ====================================================================== + ====================================================================== + +Percona Multiple I/O Threads Patch + +Copyright (c) 2008, 2009 Percona Inc +All rights reserved. + +Redistribution and use of this software in source and binary forms, +with or without modification, are permitted provided that the +following conditions are met: + + * Redistributions of source code must retain the above copyright + notice, this list of conditions and the following disclaimer. + * Redistributions in binary form must reproduce the above copyright + notice, this list of conditions and the following disclaimer in the + documentation and/or other materials provided with the distribution. + * Neither the name of Percona Inc. nor the names of its contributors + may be used to endorse or promote products derived from this software + without specific prior written permission of Percona Inc. + +THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS +"AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT +LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS +FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE +COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, +INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, +BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; +LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER +CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT +LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN +ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE +POSSIBILITY OF SUCH DAMAGE. + + ====================================================================== + ====================================================================== + +RapidJSON v1.1.0 + +Copyright (C) 2015 THL A29 Limited, a Tencent company, and Milo Yip. All +rights reserved. + +If you have downloaded a copy of the RapidJSON binary from Tencent, please +note that the RapidJSON binary is licensed under the MIT License. +If you have downloaded a copy of the RapidJSON source code from Tencent, +please note that RapidJSON source code is licensed under the MIT License, +except for the third-party components listed below which are subject to +different license terms. Your integration of RapidJSON into your own +projects may require compliance with the MIT License, as well as the other +licenses applicable to the third-party components included within RapidJSON. +To avoid the problematic JSON license in your own projects, it's sufficient +to exclude the bin/jsonchecker/ directory, as it's the only code under the +JSON license. +A copy of the MIT License is included in this file. + +Other dependencies and licenses: + +Open Source Software Licensed Under the BSD License: +-------------------------------------------------------------------- + +The msinttypes r29 +Copyright (c) 2006-2013 Alexander Chemeris +All rights reserved. + +Redistribution and use in source and binary forms, with or without +modification, are permitted provided that the following conditions are met: + +* Redistributions of source code must retain the above copyright notice, this +list of conditions and the following disclaimer. +* Redistributions in binary form must reproduce the above copyright notice, +this list of conditions and the following disclaimer in the documentation +and/or other materials provided with the distribution. +* Neither the name of copyright holder nor the names of its contributors may +be used to endorse or promote products derived from this software without +specific prior written permission. + +THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND ANY +EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED +WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE +DISCLAIMED. IN NO EVENT SHALL THE REGENTS AND CONTRIBUTORS BE LIABLE FOR ANY +DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES +(INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; +LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND +ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS +SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + +Open Source Software Licensed Under the JSON License: +-------------------------------------------------------------------- + +json.org +Copyright (c) 2002 JSON.org +All Rights Reserved. + +JSON_checker +Copyright (c) 2002 JSON.org +All Rights Reserved. + + +Terms of the JSON License: +--------------------------------------------------- + +Permission is hereby granted, free of charge, to any person obtaining a copy +of this software and associated documentation files (the "Software"), to deal +in the Software without restriction, including without limitation the rights +to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +copies of the Software, and to permit persons to whom the Software is +furnished to do so, subject to the following conditions: + +The above copyright notice and this permission notice shall be included in +all copies or substantial portions of the Software. + +The Software shall be used for Good, not Evil. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE +SOFTWARE. + + +Terms of the MIT License: +-------------------------------------------------------------------- + +Permission is hereby granted, free of charge, to any person obtaining a copy +of this software and associated documentation files (the "Software"), to deal +in the Software without restriction, including without limitation the rights +to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +copies of the Software, and to permit persons to whom the Software is +furnished to do so, subject to the following conditions: + +The above copyright notice and this permission notice shall be included in +all copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE +SOFTWARE. + + ====================================================================== + ====================================================================== + +Richard A. O'Keefe String Library + +The Richard O'Keefe String Library is subject to the following notice: + +These files are in the public domain. This includes getopt.c, which +is the work of Henry Spencer, University of Toronto Zoology, who +says of it "None of this software is derived from Bell software. I +had no access to the source for Bell's versions at the time I wrote +it. This software is hereby explicitly placed in the public domain. +It may be used for any purpose on any machine by anyone." I would +greatly prefer it if *my* material received no military use. + +The t_ctype.h file is subject to the following notice: + +Copyright (C) 1998, 1999 by Pruet Boonma, all rights reserved. +Copyright (C) 1998 by Theppitak Karoonboonyanan, all rights reserved. + + Permission to use, copy, modify, distribute and sell this software and its + documentation for any purpose is hereby granted without fee, provided that the + above copyright notice appear in all copies. + + Smaphan Raruenrom and Pruet Boonma makes no representations about +the suitability of this software for any purpose. It is provided +"as is" without express or implied warranty. + + ====================================================================== + ====================================================================== + +Time Zone Information + +Unless specified below, all files in the tz code and data (including this +LICENSE file) are in the public domain. If the files date.c, +newstrftime.3, and strftime.c are present, they contain material derived +from BSD and use the BSD 3-clause license. tzdata: + # This file is in the public domain, so clarified as of + # 2009-05-17 by Arthur David Olson. +/* Copyright 1985, 1987, 1988 The Regents of the University of California. + All rights reserved. + Redistribution and use in source and binary forms, with or without + modification, are permitted provided that the following conditions + are met: + 1. Redistributions of source code must retain the above copyright + notice, this list of conditions and the following disclaimer. + 2. Redistributions in binary form must reproduce the above copyright + notice, this list of conditions and the following disclaimer in the + documentation and/or other materials provided with the distribution. + 3. Neither the name of the University nor the names of its contributors + may be used to endorse or promote products derived from this software + without specific prior written permission. + THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS "AS IS" AND + ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE + FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + SUCH DAMAGE. */ + + ====================================================================== + ====================================================================== + +Unicode Data Files + +# unidata-5.2.0.txt +# Date: 2009-09-22, 16:23:42 PDT [KW] +# +# This file defines the Default Unicode Collation Element Table +# (DUCET) for the Unicode Collation Algorithm +# +# Copyright (c) 2001-2009 Unicode, Inc. +# For terms of use, see http://www.unicode.org/terms_of_use.html +# +# See UTS #10, Unicode Collation Algorithm, for more information. +# +# Diagnostic weight ranges +# Primary weight range: 0200..3ACA (14539) +# Secondary weight range: 0020..0192 (371) +# Variant secondaries: 0159..015E (6) +# Digit secondaries: 015F..0192 (52) +# Tertiary weight range: 0002..001F (30) +# +@version 5.2.0 + +=== http://www.unicode.org/terms_of_use.html +For the general privacy policy governing access to this site, see the +Unicode Privacy Policy. + +Unicode Copyright + Copyright (c) 1991-2020 Unicode, Inc. All rights reserved. +Definitions +Unicode Data Files ("DATA FILES") include all data files under the +directories: +https://www.unicode.org/Public/ +https://www.unicode.org/reports/ +https://www.unicode.org/ivd/data/ +Unicode Data Files do not include PDF online code charts under the directory: +https://www.unicode.org/Public/ +Unicode Software ("SOFTWARE") includes any source code published in the +Unicode Standard +or any source code or compiled code under the directories: +https://www.unicode.org/Public/PROGRAMS/ +https://www.unicode.org/Public/cldr/ +http://site.icu-project.org/download/ + +Terms of Use +Certain documents and files on this website contain a legend indicating that +"Modification is permitted." Any person is hereby authorized, without fee, to +modify such documents and files to create derivative works conforming to the +Unicode(R) Standard, subject to Terms and Conditions herein. +Any person is hereby authorized, without fee, to view, use, reproduce, and +distribute all documents and files, subject to the Terms and Conditions +herein. +Further specifications of rights and restrictions pertaining to the use of +the Unicode DATA FILES and SOFTWARE can be found in the Unicode Data Files +and Software License. +Each version of the Unicode Standard has further specifications of rights and +restrictions of use. For the book editions (Unicode 5.0 and earlier), these +are found on the back of the title page. +The Unicode PDF online code charts carry specific restrictions. Those +restrictions are incorporated as the first page of each PDF code chart. +All other files, including online documentation of the core specification for +Unicode 6.0 and later, are covered under these general Terms of Use. +No license is granted to "mirror" the Unicode website where a fee is charged +for access to the "mirror" site. +Modification is not permitted with respect to this document. All copies of +this document must be verbatim. + +Restricted Rights Legend +Any technical data or software which is licensed to the United States of +America, its agencies and/or instrumentalities under this Agreement is +commercial technical data or commercial computer software developed +exclusively at private expense as defined in FAR 2.101, or DFARS 252.227-7014 +(June 1995), as applicable. For technical data, use, duplication, or +disclosure by the Government is subject to restrictions as set forth in DFARS +202.227-7015 Technical Data, Commercial and Items (Nov 1995) and this +Agreement. For Software, in accordance with FAR 12-212 or DFARS 227-7202, as +applicable, use, duplication or disclosure by the Government is subject to +the restrictions set forth in this Agreement. + +Warranties and Disclaimers +This publication and/or website may include technical or typographical errors +or other inaccuracies. Changes are periodically added to the information +herein; these changes will be incorporated in new editions of the publication +and/or website. Unicode, Inc. may make improvements and/or changes in the +product(s) and/or program(s) described in this publication and/or website at +any time. +If this file has been purchased on magnetic or optical media from Unicode, +Inc. the sole and exclusive remedy for any claim will be exchange of the +defective media within ninety (90) days of original purchase. + +EXCEPT AS PROVIDED IN SECTION E.2, THIS PUBLICATION AND/OR SOFTWARE IS +PROVIDED "AS IS" WITHOUT WARRANTY OF ANY KIND EITHER EXPRESS, IMPLIED, OR +STATUTORY, INCLUDING, BUT NOT LIMITED TO, ANY WARRANTIES OF MERCHANTABILITY, +FITNESS FOR A PARTICULAR PURPOSE, OR NON-INFRINGEMENT. UNICODE, INC. AND ITS +LICENSORS ASSUME NO RESPONSIBILITY FOR ERRORS OR OMISSIONS IN THIS +PUBLICATION AND/OR SOFTWARE OR OTHER DOCUMENTS WHICH ARE REFERENCED BY OR +LINKED TO THIS PUBLICATION OR THE UNICODE WEBSITE. + +Waiver of Damages +In no event shall Unicode, Inc. or its licensors be liable for any special, +incidental, indirect or consequential damages of any kind, or any damages +whatsoever, whether or not Unicode, Inc. was advised of the possibility of +the damage, including, without limitation, those resulting from the +following: loss of use, data or profits, in connection with the use, +modification or distribution of this information or its derivatives. + +Trademarks & Logos +The Unicode Word Mark and the Unicode Logo are trademarks of Unicode, Inc. +¿The Unicode Consortium¿ and ¿Unicode, Inc.¿ are trade names of Unicode, Inc. +Use of the information and materials found on this website indicates your +acknowledgement of Unicode, Inc.¿s exclusive worldwide rights in the Unicode +Word Mark, the Unicode Logo, and the Unicode trade names. +The Unicode Consortium Name and Trademark Usage Policy (¿Trademark Policy¿) +are incorporated herein by reference and you agree to abide by the provisions +of the Trademark Policy, which may be changed from time to time in the sole +discretion of Unicode, Inc. +All third party trademarks referenced herein are the property of their +respective owners. + +Miscellaneous +Jurisdiction and Venue. This website is operated from a location in the State +of California, United States of America. Unicode, Inc. makes no +representation that the materials are appropriate for use in other locations. +If you access this website from other locations, you are responsible for +compliance with local laws. This Agreement, all use of this website and any +claims and damages resulting from use of this website are governed solely by +the laws of the State of California without regard to any principles which +would apply the laws of a different jurisdiction. The user agrees that any +disputes regarding this website shall be resolved solely in the courts +located in Santa Clara County, California. The user agrees said courts have +personal jurisdiction and agree to waive any right to transfer the dispute to +any other forum. + +Modification by Unicode, Inc. Unicode, Inc. shall have the right to modify +this Agreement at any time by posting it to this website. The user may not +assign any part of this Agreement without Unicode, Inc.¿s prior written +consent. + +Taxes. The user agrees to pay any taxes arising from access to this website +or use of the information herein, except for those based on Unicode¿s net +income. + +Severability. If any provision of this Agreement is declared invalid or +unenforceable, the remaining provisions of this Agreement shall remain in +effect. + +Entire Agreement. This Agreement constitutes the entire agreement between the +parties. + + ====================================================================== + ====================================================================== + +Unicode Data Files + +UNICODE, INC. LICENSE AGREEMENT - DATA FILES AND SOFTWARE + +Unicode Data Files include all data files under the directories +http://www.unicode.org/Public/, http://www.unicode.org/reports/, +http://www.unicode.org/cldr/data/, http://source.icu-project.org/repos/icu/, +and http://www.unicode.org/utility/trac/browser/. + +Unicode Data Files do not include PDF online code charts under the +directory http://www.unicode.org/Public/. + +Software includes any source code published in the Unicode Standard +or under the directories http://www.unicode.org/Public/, +http://www.unicode.org/reports/, http://www.unicode.org/cldr/data/, +http://source.icu-project.org/repos/icu/, and +http://www.unicode.org/utility/trac/browser/. + +NOTICE TO USER: Carefully read the following legal agreement. +BY DOWNLOADING, INSTALLING, COPYING OR OTHERWISE USING UNICODE INC.'S +DATA FILES ("DATA FILES"), AND/OR SOFTWARE ("SOFTWARE"), +YOU UNEQUIVOCALLY ACCEPT, AND AGREE TO BE BOUND BY, ALL OF THE +TERMS AND CONDITIONS OF THIS AGREEMENT. +IF YOU DO NOT AGREE, DO NOT DOWNLOAD, INSTALL, COPY, DISTRIBUTE OR USE +THE DATA FILES OR SOFTWARE. + +COPYRIGHT AND PERMISSION NOTICE + +Copyright (c) 1991-2016 Unicode, Inc. All rights reserved. +Distributed under the Terms of Use in http://www.unicode.org/copyright.html. + +Permission is hereby granted, free of charge, to any person obtaining a copy +of the Unicode data files and any associated documentation (the "Data Files") +or Unicode software and any associated documentation (the "Software") to deal +in the Data Files or Software without restriction, including without +limitation the rights to use, copy, modify, merge, publish, distribute, +and/or sell copies of the Data Files or Software, and to permit persons to +whom the Data Files or Software are furnished to do so, provided that either +(a) this copyright and permission notice appear with all copies of the Data +Files or Software, or (b) this copyright and permission notice appear in +associated Documentation. + +THE DATA FILES AND SOFTWARE ARE PROVIDED "AS IS", WITHOUT WARRANTY OF ANY +KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF +MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT OF +THIRD PARTY RIGHTS. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR HOLDERS +INCLUDED IN THIS NOTICE BE LIABLE FOR ANY CLAIM, OR ANY SPECIAL INDIRECT OR +CONSEQUENTIAL DAMAGES, OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, +DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER +TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE +OF THE DATA FILES OR SOFTWARE. + +Except as contained in this notice, the name of a copyright holder shall not +be used in advertising or otherwise to promote the sale, use or other +dealings in these Data Files or Software without prior written authorization +of the copyright holder. + +========================================================================= + +ICU-LICENSE +----------- +ICU License - ICU 1.8.1 and later + +COPYRIGHT AND PERMISSION NOTICE + +Copyright (c) 1995-2016 International Business Machines Corporation and +others + +All rights reserved. + +Permission is hereby granted, free of charge, to any person obtaining a copy +of this software and associated documentation files (the "Software"), to deal +in the Software without restriction, including without limitation the rights +to use, copy, modify, merge, publish, distribute, and/or sell copies of the +Software, and to permit persons to whom the Software is furnished to do so, +provided that the above copyright notice(s) and this permission notice appear +in all copies of the Software and that both the above copyright notice(s) and +this permission notice appear in supporting documentation. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT OF THIRD PARTY RIGHTS. +IN NO EVENT SHALL THE COPYRIGHT HOLDER OR HOLDERS INCLUDED IN THIS NOTICE BE +LIABLE FOR ANY CLAIM, OR ANY SPECIAL INDIRECT OR CONSEQUENTIAL DAMAGES, OR +ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER +IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF +OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. + +Except as contained in this notice, the name of a copyright holder shall not +be used in advertising or otherwise to promote the sale, use or other +dealings in this Software without prior written authorization of the +copyright holder. + +All trademarks and registered trademarks mentioned herein are the property of +their respective owners. + + ====================================================================== + ====================================================================== + +unordered_dense + +Copyright (c) 2022 Martin Leitner-Ankerl + +Permission is hereby granted, free of charge, to any person obtaining a copy +of this software and associated documentation files (the "Software"), to deal +in the Software without restriction, including without limitation the rights +to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +copies of the Software, and to permit persons to whom the Software is +furnished to do so, subject to the following conditions: + +The above copyright notice and this permission notice shall be included in all +copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE +SOFTWARE. + + ====================================================================== + ====================================================================== + +zlib + +Oracle gratefully acknowledges the contributions of Jean-loup Gailly +and Mark Adler in creating the zlib general purpose compression +library which is used in this product. + +Copyright (C) 1995-2022 Jean-loup Gailly and Mark Adler + + This software is provided 'as-is', without any express or implied + warranty. In no event will the authors be held liable for any damages + arising from the use of this software. + + Permission is granted to anyone to use this software for any purpose, + including commercial applications, and to alter it and redistribute it + freely, subject to the following restrictions: + + 1. The origin of this software must not be misrepresented; you must not + claim that you wrote the original software. If you use this software + in a product, an acknowledgment in the product documentation would be + appreciated but is not required. + 2. Altered source versions must be plainly marked as such, and must not be + misrepresented as being the original software. + 3. This notice may not be removed or altered from any source distribution. + + Jean-loup Gailly Mark Adler + jloup@gzip.org madler@alumni.caltech.edu + +If you use the zlib library in a product, we would appreciate *not* receiving +lengthy legal documents to sign. The sources are provided for free but without +warranty of any kind. The library has been entirely written by Jean-loup +Gailly and Mark Adler; it does not include third-party code. + +If you redistribute modified sources, we would appreciate that you include in +the file ChangeLog history information documenting your changes. Please read +the FAQ for more information on the distribution of modified source versions. + + ====================================================================== + ====================================================================== + +ZSTD (Zstandard) + +Zstandard is dual-licensed under [BSD](LICENSE) and [GPLv2](COPYING). + + /* + * This source code is licensed under both the BSD-style license (found in + * the LICENSE file in the root directory of this source tree) and the GPLv2 + * (found in the COPYING file in the root directory of this source tree). + * You may select, at your option, one of the above-listed licenses. + */ + +Oracle elects the BSD license + +LICENSE: +Copyright (c) 2016-present, Facebook, Inc. All rights reserved. +Copyright (C) 2012-2016, Yann Collet. +Copyright (c) 2003-2008 Yuta Mori All Rights Reserved. +Copyright (c) 2016 Tino Reichardt +Copyright (c) 2016-present, Przemyslaw Skibinski, Yann Collet, Facebook, Inc. +Copyright (c) 2016-present, Yann Collet, Facebook, Inc. +Copyright (c) 2018-present, Facebook, Inc. + +Redistribution and use in source and binary forms, with or without +modification, are permitted provided that the following conditions are +met: + + * Redistributions of source code must retain the above copyright notice, + this list of conditions and the following disclaimer. + + * Redistributions in binary form must reproduce the above copyright notice, + this list of conditions and the following disclaimer in the documentation + and/or other materials provided with the distribution. + + * Neither the name Facebook nor the names of its contributors may be used to + endorse or promote products derived from this software without specific + prior written permission. + +THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS +IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, +THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR +PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR +CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, +EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, +PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR +PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF +LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING +NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS +SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + +The following is from the COPYING file and is included for completeness: +------------------------------- + + GNU GENERAL PUBLIC LICENSE + Version 2, June 1991 + + Copyright (C) 1989, 1991 Free Software Foundation, Inc., + 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA + Everyone is permitted to copy and distribute verbatim copies + of this license document, but changing it is not allowed. + + Preamble + + The licenses for most software are designed to take away your +freedom to share and change it. By contrast, the GNU General Public +License is intended to guarantee your freedom to share and change free +software--to make sure the software is free for all its users. This +General Public License applies to most of the Free Software +Foundation's software and to any other program whose authors commit to +using it. (Some other Free Software Foundation software is covered by +the GNU Lesser General Public License instead.) You can apply it to +your programs, too. + + When we speak of free software, we are referring to freedom, not +price. Our General Public Licenses are designed to make sure that you +have the freedom to distribute copies of free software (and charge for +this service if you wish), that you receive source code or can get it +if you want it, that you can change the software or use pieces of it +in new free programs; and that you know you can do these things. + + To protect your rights, we need to make restrictions that forbid +anyone to deny you these rights or to ask you to surrender the rights. +These restrictions translate to certain responsibilities for you if you +distribute copies of the software, or if you modify it. + + For example, if you distribute copies of such a program, whether +gratis or for a fee, you must give the recipients all the rights that +you have. You must make sure that they, too, receive or can get the +source code. And you must show them these terms so they know their +rights. + + We protect your rights with two steps: (1) copyright the software, and +(2) offer you this license which gives you legal permission to copy, +distribute and/or modify the software. + + Also, for each author's protection and ours, we want to make certain +that everyone understands that there is no warranty for this free +software. If the software is modified by someone else and passed on, we +want its recipients to know that what they have is not the original, so +that any problems introduced by others will not reflect on the original +authors' reputations. + + Finally, any free program is threatened constantly by software +patents. We wish to avoid the danger that redistributors of a free +program will individually obtain patent licenses, in effect making the +program proprietary. To prevent this, we have made it clear that any +patent must be licensed for everyone's free use or not licensed at all. + + The precise terms and conditions for copying, distribution and +modification follow. + + GNU GENERAL PUBLIC LICENSE + TERMS AND CONDITIONS FOR COPYING, DISTRIBUTION AND MODIFICATION + + 0. This License applies to any program or other work which contains +a notice placed by the copyright holder saying it may be distributed +under the terms of this General Public License. The "Program", below, +refers to any such program or work, and a "work based on the Program" +means either the Program or any derivative work under copyright law: +that is to say, a work containing the Program or a portion of it, +either verbatim or with modifications and/or translated into another +language. (Hereinafter, translation is included without limitation in +the term "modification".) Each licensee is addressed as "you". + +Activities other than copying, distribution and modification are not +covered by this License; they are outside its scope. The act of +running the Program is not restricted, and the output from the Program +is covered only if its contents constitute a work based on the +Program (independent of having been made by running the Program). +Whether that is true depends on what the Program does. + + 1. You may copy and distribute verbatim copies of the Program's +source code as you receive it, in any medium, provided that you +conspicuously and appropriately publish on each copy an appropriate +copyright notice and disclaimer of warranty; keep intact all the +notices that refer to this License and to the absence of any warranty; +and give any other recipients of the Program a copy of this License +along with the Program. + +You may charge a fee for the physical act of transferring a copy, and +you may at your option offer warranty protection in exchange for a fee. + + 2. You may modify your copy or copies of the Program or any portion +of it, thus forming a work based on the Program, and copy and +distribute such modifications or work under the terms of Section 1 +above, provided that you also meet all of these conditions: + + a) You must cause the modified files to carry prominent notices + stating that you changed the files and the date of any change. + + b) You must cause any work that you distribute or publish, that in + whole or in part contains or is derived from the Program or any + part thereof, to be licensed as a whole at no charge to all third + parties under the terms of this License. + + c) If the modified program normally reads commands interactively + when run, you must cause it, when started running for such + interactive use in the most ordinary way, to print or display an + announcement including an appropriate copyright notice and a + notice that there is no warranty (or else, saying that you provide + a warranty) and that users may redistribute the program under + these conditions, and telling the user how to view a copy of this + License. (Exception: if the Program itself is interactive but + does not normally print such an announcement, your work based on + the Program is not required to print an announcement.) + +These requirements apply to the modified work as a whole. If +identifiable sections of that work are not derived from the Program, +and can be reasonably considered independent and separate works in +themselves, then this License, and its terms, do not apply to those +sections when you distribute them as separate works. But when you +distribute the same sections as part of a whole which is a work based +on the Program, the distribution of the whole must be on the terms of +this License, whose permissions for other licensees extend to the +entire whole, and thus to each and every part regardless of who wrote it. + +Thus, it is not the intent of this section to claim rights or contest +your rights to work written entirely by you; rather, the intent is to +exercise the right to control the distribution of derivative or +collective works based on the Program. + +In addition, mere aggregation of another work not based on the Program +with the Program (or with a work based on the Program) on a volume of +a storage or distribution medium does not bring the other work under +the scope of this License. + + 3. You may copy and distribute the Program (or a work based on it, +under Section 2) in object code or executable form under the terms of +Sections 1 and 2 above provided that you also do one of the following: + + a) Accompany it with the complete corresponding machine-readable + source code, which must be distributed under the terms of Sections + 1 and 2 above on a medium customarily used for software interchange; or, + + b) Accompany it with a written offer, valid for at least three + years, to give any third party, for a charge no more than your + cost of physically performing source distribution, a complete + machine-readable copy of the corresponding source code, to be + distributed under the terms of Sections 1 and 2 above on a medium + customarily used for software interchange; or, + + c) Accompany it with the information you received as to the offer + to distribute corresponding source code. (This alternative is + allowed only for noncommercial distribution and only if you + received the program in object code or executable form with such + an offer, in accord with Subsection b above.) + +The source code for a work means the preferred form of the work for +making modifications to it. For an executable work, complete source +code means all the source code for all modules it contains, plus any +associated interface definition files, plus the scripts used to +control compilation and installation of the executable. However, as a +special exception, the source code distributed need not include +anything that is normally distributed (in either source or binary +form) with the major components (compiler, kernel, and so on) of the +operating system on which the executable runs, unless that component +itself accompanies the executable. + +If distribution of executable or object code is made by offering +access to copy from a designated place, then offering equivalent +access to copy the source code from the same place counts as +distribution of the source code, even though third parties are not +compelled to copy the source along with the object code. + + 4. You may not copy, modify, sublicense, or distribute the Program +except as expressly provided under this License. Any attempt +otherwise to copy, modify, sublicense or distribute the Program is +void, and will automatically terminate your rights under this License. +However, parties who have received copies, or rights, from you under +this License will not have their licenses terminated so long as such +parties remain in full compliance. + + 5. You are not required to accept this License, since you have not +signed it. However, nothing else grants you permission to modify or +distribute the Program or its derivative works. These actions are +prohibited by law if you do not accept this License. Therefore, by +modifying or distributing the Program (or any work based on the +Program), you indicate your acceptance of this License to do so, and +all its terms and conditions for copying, distributing or modifying +the Program or works based on it. + + 6. Each time you redistribute the Program (or any work based on the +Program), the recipient automatically receives a license from the +original licensor to copy, distribute or modify the Program subject to +these terms and conditions. You may not impose any further +restrictions on the recipients' exercise of the rights granted herein. +You are not responsible for enforcing compliance by third parties to +this License. + + 7. If, as a consequence of a court judgment or allegation of patent +infringement or for any other reason (not limited to patent issues), +conditions are imposed on you (whether by court order, agreement or +otherwise) that contradict the conditions of this License, they do not +excuse you from the conditions of this License. If you cannot +distribute so as to satisfy simultaneously your obligations under this +License and any other pertinent obligations, then as a consequence you +may not distribute the Program at all. For example, if a patent +license would not permit royalty-free redistribution of the Program by +all those who receive copies directly or indirectly through you, then +the only way you could satisfy both it and this License would be to +refrain entirely from distribution of the Program. + +If any portion of this section is held invalid or unenforceable under +any particular circumstance, the balance of the section is intended to +apply and the section as a whole is intended to apply in other +circumstances. + +It is not the purpose of this section to induce you to infringe any +patents or other property right claims or to contest validity of any +such claims; this section has the sole purpose of protecting the +integrity of the free software distribution system, which is +implemented by public license practices. Many people have made +generous contributions to the wide range of software distributed +through that system in reliance on consistent application of that +system; it is up to the author/donor to decide if he or she is willing +to distribute software through any other system and a licensee cannot +impose that choice. + +This section is intended to make thoroughly clear what is believed to +be a consequence of the rest of this License. + + 8. If the distribution and/or use of the Program is restricted in +certain countries either by patents or by copyrighted interfaces, the +original copyright holder who places the Program under this License +may add an explicit geographical distribution limitation excluding +those countries, so that distribution is permitted only in or among +countries not thus excluded. In such case, this License incorporates +the limitation as if written in the body of this License. + + 9. The Free Software Foundation may publish revised and/or new versions +of the General Public License from time to time. Such new versions will +be similar in spirit to the present version, but may differ in detail to +address new problems or concerns. + +Each version is given a distinguishing version number. If the Program +specifies a version number of this License which applies to it and "any +later version", you have the option of following the terms and conditions +either of that version or of any later version published by the Free +Software Foundation. If the Program does not specify a version number of +this License, you may choose any version ever published by the Free Software +Foundation. + + 10. If you wish to incorporate parts of the Program into other free +programs whose distribution conditions are different, write to the author +to ask for permission. For software which is copyrighted by the Free +Software Foundation, write to the Free Software Foundation; we sometimes +make exceptions for this. Our decision will be guided by the two goals +of preserving the free status of all derivatives of our free software and +of promoting the sharing and reuse of software generally. + + NO WARRANTY + + 11. BECAUSE THE PROGRAM IS LICENSED FREE OF CHARGE, THERE IS NO WARRANTY +FOR THE PROGRAM, TO THE EXTENT PERMITTED BY APPLICABLE LAW. EXCEPT WHEN +OTHERWISE STATED IN WRITING THE COPYRIGHT HOLDERS AND/OR OTHER PARTIES +PROVIDE THE PROGRAM "AS IS" WITHOUT WARRANTY OF ANY KIND, EITHER EXPRESSED +OR IMPLIED, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF +MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE. THE ENTIRE RISK AS +TO THE QUALITY AND PERFORMANCE OF THE PROGRAM IS WITH YOU. SHOULD THE +PROGRAM PROVE DEFECTIVE, YOU ASSUME THE COST OF ALL NECESSARY SERVICING, +REPAIR OR CORRECTION. + + 12. IN NO EVENT UNLESS REQUIRED BY APPLICABLE LAW OR AGREED TO IN WRITING +WILL ANY COPYRIGHT HOLDER, OR ANY OTHER PARTY WHO MAY MODIFY AND/OR +REDISTRIBUTE THE PROGRAM AS PERMITTED ABOVE, BE LIABLE TO YOU FOR DAMAGES, +INCLUDING ANY GENERAL, SPECIAL, INCIDENTAL OR CONSEQUENTIAL DAMAGES ARISING +OUT OF THE USE OR INABILITY TO USE THE PROGRAM (INCLUDING BUT NOT LIMITED +TO LOSS OF DATA OR DATA BEING RENDERED INACCURATE OR LOSSES SUSTAINED BY +YOU OR THIRD PARTIES OR A FAILURE OF THE PROGRAM TO OPERATE WITH ANY OTHER +PROGRAMS), EVEN IF SUCH HOLDER OR OTHER PARTY HAS BEEN ADVISED OF THE +POSSIBILITY OF SUCH DAMAGES. + + END OF TERMS AND CONDITIONS + + How to Apply These Terms to Your New Programs + + If you develop a new program, and you want it to be of the greatest +possible use to the public, the best way to achieve this is to make it +free software which everyone can redistribute and change under these terms. + + To do so, attach the following notices to the program. It is safest +to attach them to the start of each source file to most effectively +convey the exclusion of warranty; and each file should have at least +the "copyright" line and a pointer to where the full notice is found. + + + Copyright (C) + + This program is free software; you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation; either version 2 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License along + with this program; if not, write to the Free Software Foundation, Inc., + 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. + +Also add information on how to contact you by electronic and paper mail. + +If the program is interactive, make it output a short notice like this +when it starts in an interactive mode: + + Gnomovision version 69, Copyright (C) year name of author + Gnomovision comes with ABSOLUTELY NO WARRANTY; for details type `show w'. + This is free software, and you are welcome to redistribute it + under certain conditions; type `show c' for details. + +The hypothetical commands `show w' and `show c' should show the appropriate +parts of the General Public License. Of course, the commands you use may +be called something other than `show w' and `show c'; they could even be +mouse-clicks or menu items--whatever suits your program. + +You should also get your employer (if you work as a programmer) or your +school, if any, to sign a "copyright disclaimer" for the program, if +necessary. Here is a sample; alter the names: + + Yoyodyne, Inc., hereby disclaims all copyright interest in the program + `Gnomovision' (which makes passes at compilers) written by James Hacker. + + , 1 April 1989 + Ty Coon, President of Vice + +This General Public License does not permit incorporating your program into +proprietary programs. If your program is a subroutine library, you may +consider it more useful to permit linking proprietary applications with the +library. If this is what you want to do, use the GNU Lesser General +Public License instead of this License. + + ====================================================================== + ====================================================================== + +Standard Licenses + +GNU Lesser General Public License v2.1, February 1999 + +The following applies to all products licensed under the +GNU Lesser General Public License, Version 2.1: You may +not use the identified files except in compliance with +the GNU Lesser General Public License, Version 2.1 (the +"License"). You may obtain a copy of the License at +http://www.gnu.org/licenses/lgpl-2.1.html. A copy of the +license is also reproduced below. Unless required by +applicable law or agreed to in writing, software distributed +under the License is distributed on an "AS IS" BASIS, +WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express +or implied. See the License for the specific language governing +permissions and limitations under the License. + + GNU LESSER GENERAL PUBLIC LICENSE + Version 2.1, February 1999 + + Copyright (C) 1991, 1999 Free Software Foundation, Inc. + 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA + Everyone is permitted to copy and distribute verbatim copies + of this license document, but changing it is not allowed. + +[This is the first released version of the Lesser GPL. It also counts + as the successor of the GNU Library Public License, version 2, hence + the version number 2.1.] + + Preamble + + The licenses for most software are designed to take away your +freedom to share and change it. By contrast, the GNU General Public +Licenses are intended to guarantee your freedom to share and change +free software--to make sure the software is free for all its users. + + This license, the Lesser General Public License, applies to some +specially designated software packages--typically libraries--of the +Free Software Foundation and other authors who decide to use it. You +can use it too, but we suggest you first think carefully about whether +this license or the ordinary General Public License is the better +strategy to use in any particular case, based on the explanations below. + + When we speak of free software, we are referring to freedom of use, +not price. Our General Public Licenses are designed to make sure that +you have the freedom to distribute copies of free software (and charge +for this service if you wish); that you receive source code or can get +it if you want it; that you can change the software and use pieces of +it in new free programs; and that you are informed that you can do +these things. + + To protect your rights, we need to make restrictions that forbid +distributors to deny you these rights or to ask you to surrender these +rights. These restrictions translate to certain responsibilities for +you if you distribute copies of the library or if you modify it. + + For example, if you distribute copies of the library, whether gratis +or for a fee, you must give the recipients all the rights that we gave +you. You must make sure that they, too, receive or can get the source +code. If you link other code with the library, you must provide +complete object files to the recipients, so that they can relink them +with the library after making changes to the library and recompiling +it. And you must show them these terms so they know their rights. + + We protect your rights with a two-step method: (1) we copyright the +library, and (2) we offer you this license, which gives you legal +permission to copy, distribute and/or modify the library. + + To protect each distributor, we want to make it very clear that +there is no warranty for the free library. Also, if the library is +modified by someone else and passed on, the recipients should know +that what they have is not the original version, so that the original +author's reputation will not be affected by problems that might be +introduced by others. + + Finally, software patents pose a constant threat to the existence of +any free program. We wish to make sure that a company cannot +effectively restrict the users of a free program by obtaining a +restrictive license from a patent holder. Therefore, we insist that +any patent license obtained for a version of the library must be +consistent with the full freedom of use specified in this license. + + Most GNU software, including some libraries, is covered by the +ordinary GNU General Public License. This license, the GNU Lesser +General Public License, applies to certain designated libraries, and +is quite different from the ordinary General Public License. We use +this license for certain libraries in order to permit linking those +libraries into non-free programs. + + When a program is linked with a library, whether statically or using +a shared library, the combination of the two is legally speaking a +combined work, a derivative of the original library. The ordinary +General Public License therefore permits such linking only if the +entire combination fits its criteria of freedom. The Lesser General +Public License permits more lax criteria for linking other code with +the library. + + We call this license the "Lesser" General Public License because it +does Less to protect the user's freedom than the ordinary General +Public License. It also provides other free software developers Less +of an advantage over competing non-free programs. These disadvantages +are the reason we use the ordinary General Public License for many +libraries. However, the Lesser license provides advantages in certain +special circumstances. + + For example, on rare occasions, there may be a special need to +encourage the widest possible use of a certain library, so that it +becomes a de-facto standard. To achieve this, non-free programs +must be allowed to use the library. A more frequent case is that +a free library does the same job as widely used non-free libraries. +In this case, there is little to gain by limiting the free library +to free software only, so we use the Lesser General Public License. + + In other cases, permission to use a particular library in non-free +programs enables a greater number of people to use a large body of +free software. For example, permission to use the GNU C Library in +non-free programs enables many more people to use the whole GNU +operating system, as well as its variant, the GNU/Linux operating +system. + + Although the Lesser General Public License is Less protective of the +users' freedom, it does ensure that the user of a program that is +linked with the Library has the freedom and the wherewithal to run +that program using a modified version of the Library. + + The precise terms and conditions for copying, distribution and +modification follow. Pay close attention to the difference between a +"work based on the library" and a "work that uses the library". The +former contains code derived from the library, whereas the latter must +be combined with the library in order to run. + + GNU LESSER GENERAL PUBLIC LICENSE + TERMS AND CONDITIONS FOR COPYING, DISTRIBUTION AND MODIFICATION + + 0. This License Agreement applies to any software library or other +program which contains a notice placed by the copyright holder or +other authorized party saying it may be distributed under the terms of +this Lesser General Public License (also called "this License"). +Each licensee is addressed as "you". + + A "library" means a collection of software functions and/or data +prepared so as to be conveniently linked with application programs +(which use some of those functions and data) to form executables. + + The "Library", below, refers to any such software library or work +which has been distributed under these terms. A "work based on the +Library" means either the Library or any derivative work under +copyright law: that is to say, a work containing the Library or a +portion of it, either verbatim or with modifications and/or translated +straightforwardly into another language. (Hereinafter, translation is +included without limitation in the term "modification".) + + "Source code" for a work means the preferred form of the work for +making modifications to it. For a library, complete source code means +all the source code for all modules it contains, plus any associated +interface definition files, plus the scripts used to control +compilation and installation of the library. + + Activities other than copying, distribution and modification are not +covered by this License; they are outside its scope. The act of +running a program using the Library is not restricted, and output from +such a program is covered only if its contents constitute a work based +on the Library (independent of the use of the Library in a tool for +writing it). Whether that is true depends on what the Library does +and what the program that uses the Library does. + + 1. You may copy and distribute verbatim copies of the Library's +complete source code as you receive it, in any medium, provided that +you conspicuously and appropriately publish on each copy an +appropriate copyright notice and disclaimer of warranty; keep intact +all the notices that refer to this License and to the absence of any +warranty; and distribute a copy of this License along with the +Library. + + You may charge a fee for the physical act of transferring a copy, +and you may at your option offer warranty protection in exchange for a +fee. + + 2. You may modify your copy or copies of the Library or any portion +of it, thus forming a work based on the Library, and copy and +distribute such modifications or work under the terms of Section 1 +above, provided that you also meet all of these conditions: + + a) The modified work must itself be a software library. + + b) You must cause the files modified to carry prominent notices + stating that you changed the files and the date of any change. + + c) You must cause the whole of the work to be licensed at no + charge to all third parties under the terms of this License. + + d) If a facility in the modified Library refers to a function or a + table of data to be supplied by an application program that uses + the facility, other than as an argument passed when the facility + is invoked, then you must make a good faith effort to ensure that, + in the event an application does not supply such function or + table, the facility still operates, and performs whatever part of + its purpose remains meaningful. + + (For example, a function in a library to compute square roots has + a purpose that is entirely well-defined independent of the + application. Therefore, Subsection 2d requires that any + application-supplied function or table used by this function must + be optional: if the application does not supply it, the square + root function must still compute square roots.) + +These requirements apply to the modified work as a whole. If +identifiable sections of that work are not derived from the Library, +and can be reasonably considered independent and separate works in +themselves, then this License, and its terms, do not apply to those +sections when you distribute them as separate works. But when you +distribute the same sections as part of a whole which is a work based +on the Library, the distribution of the whole must be on the terms of +this License, whose permissions for other licensees extend to the +entire whole, and thus to each and every part regardless of who wrote +it. + +Thus, it is not the intent of this section to claim rights or contest +your rights to work written entirely by you; rather, the intent is to +exercise the right to control the distribution of derivative or +collective works based on the Library. + +In addition, mere aggregation of another work not based on the Library +with the Library (or with a work based on the Library) on a volume of +a storage or distribution medium does not bring the other work under +the scope of this License. + + 3. You may opt to apply the terms of the ordinary GNU General Public +License instead of this License to a given copy of the Library. To do +this, you must alter all the notices that refer to this License, so +that they refer to the ordinary GNU General Public License, version 2, +instead of to this License. (If a newer version than version 2 of the +ordinary GNU General Public License has appeared, then you can specify +that version instead if you wish.) Do not make any other change in +these notices. + + Once this change is made in a given copy, it is irreversible for +that copy, so the ordinary GNU General Public License applies to all +subsequent copies and derivative works made from that copy. + + This option is useful when you wish to copy part of the code of +the Library into a program that is not a library. + + 4. You may copy and distribute the Library (or a portion or +derivative of it, under Section 2) in object code or executable form +under the terms of Sections 1 and 2 above provided that you accompany +it with the complete corresponding machine-readable source code, which +must be distributed under the terms of Sections 1 and 2 above on a +medium customarily used for software interchange. + + If distribution of object code is made by offering access to copy +from a designated place, then offering equivalent access to copy the +source code from the same place satisfies the requirement to +distribute the source code, even though third parties are not +compelled to copy the source along with the object code. + + 5. A program that contains no derivative of any portion of the +Library, but is designed to work with the Library by being compiled or +linked with it, is called a "work that uses the Library". Such a +work, in isolation, is not a derivative work of the Library, and +therefore falls outside the scope of this License. + + However, linking a "work that uses the Library" with the Library +creates an executable that is a derivative of the Library (because it +contains portions of the Library), rather than a "work that uses the +library". The executable is therefore covered by this License. +Section 6 states terms for distribution of such executables. + + When a "work that uses the Library" uses material from a header file +that is part of the Library, the object code for the work may be a +derivative work of the Library even though the source code is not. +Whether this is true is especially significant if the work can be +linked without the Library, or if the work is itself a library. The +threshold for this to be true is not precisely defined by law. + + If such an object file uses only numerical parameters, data +structure layouts and accessors, and small macros and small inline +functions (ten lines or less in length), then the use of the object +file is unrestricted, regardless of whether it is legally a derivative +work. (Executables containing this object code plus portions of the +Library will still fall under Section 6.) + + Otherwise, if the work is a derivative of the Library, you may +distribute the object code for the work under the terms of Section 6. +Any executables containing that work also fall under Section 6, +whether or not they are linked directly with the Library itself. + + 6. As an exception to the Sections above, you may also combine or +link a "work that uses the Library" with the Library to produce a +work containing portions of the Library, and distribute that work +under terms of your choice, provided that the terms permit +modification of the work for the customer's own use and reverse +engineering for debugging such modifications. + + You must give prominent notice with each copy of the work that the +Library is used in it and that the Library and its use are covered by +this License. You must supply a copy of this License. If the work +during execution displays copyright notices, you must include the +copyright notice for the Library among them, as well as a reference +directing the user to the copy of this License. Also, you must do one +of these things: + + a) Accompany the work with the complete corresponding + machine-readable source code for the Library including whatever + changes were used in the work (which must be distributed under + Sections 1 and 2 above); and, if the work is an executable linked + with the Library, with the complete machine-readable "work that + uses the Library", as object code and/or source code, so that the + user can modify the Library and then relink to produce a modified + executable containing the modified Library. (It is understood + that the user who changes the contents of definitions files in the + Library will not necessarily be able to recompile the application + to use the modified definitions.) + + b) Use a suitable shared library mechanism for linking with the + Library. A suitable mechanism is one that (1) uses at run time a + copy of the library already present on the user's computer system, + rather than copying library functions into the executable, and (2) + will operate properly with a modified version of the library, if + the user installs one, as long as the modified version is + interface-compatible with the version that the work was made with. + + c) Accompany the work with a written offer, valid for at + least three years, to give the same user the materials + specified in Subsection 6a, above, for a charge no more + than the cost of performing this distribution. + + d) If distribution of the work is made by offering access to copy + from a designated place, offer equivalent access to copy the above + specified materials from the same place. + + e) Verify that the user has already received a copy of these + materials or that you have already sent this user a copy. + + For an executable, the required form of the "work that uses the +Library" must include any data and utility programs needed for +reproducing the executable from it. However, as a special exception, +the materials to be distributed need not include anything that is +normally distributed (in either source or binary form) with the major +components (compiler, kernel, and so on) of the operating system on +which the executable runs, unless that component itself accompanies +the executable. + + It may happen that this requirement contradicts the license +restrictions of other proprietary libraries that do not normally +accompany the operating system. Such a contradiction means you cannot +use both them and the Library together in an executable that you +distribute. + + 7. You may place library facilities that are a work based on the +Library side-by-side in a single library together with other library +facilities not covered by this License, and distribute such a combined +library, provided that the separate distribution of the work based on +the Library and of the other library facilities is otherwise +permitted, and provided that you do these two things: + + a) Accompany the combined library with a copy of the same work + based on the Library, uncombined with any other library + facilities. This must be distributed under the terms of the + Sections above. + + b) Give prominent notice with the combined library of the fact + that part of it is a work based on the Library, and explaining + where to find the accompanying uncombined form of the same work. + + 8. You may not copy, modify, sublicense, link with, or distribute +the Library except as expressly provided under this License. Any +attempt otherwise to copy, modify, sublicense, link with, or +distribute the Library is void, and will automatically terminate your +rights under this License. However, parties who have received copies, +or rights, from you under this License will not have their licenses +terminated so long as such parties remain in full compliance. + + 9. You are not required to accept this License, since you have not +signed it. However, nothing else grants you permission to modify or +distribute the Library or its derivative works. These actions are +prohibited by law if you do not accept this License. Therefore, by +modifying or distributing the Library (or any work based on the +Library), you indicate your acceptance of this License to do so, and +all its terms and conditions for copying, distributing or modifying +the Library or works based on it. + + 10. Each time you redistribute the Library (or any work based on the +Library), the recipient automatically receives a license from the +original licensor to copy, distribute, link with or modify the Library +subject to these terms and conditions. You may not impose any further +restrictions on the recipients' exercise of the rights granted herein. +You are not responsible for enforcing compliance by third parties with +this License. + + 11. If, as a consequence of a court judgment or allegation of patent +infringement or for any other reason (not limited to patent issues), +conditions are imposed on you (whether by court order, agreement or +otherwise) that contradict the conditions of this License, they do not +excuse you from the conditions of this License. If you cannot +distribute so as to satisfy simultaneously your obligations under this +License and any other pertinent obligations, then as a consequence you +may not distribute the Library at all. For example, if a patent +license would not permit royalty-free redistribution of the Library by +all those who receive copies directly or indirectly through you, then +the only way you could satisfy both it and this License would be to +refrain entirely from distribution of the Library. + +If any portion of this section is held invalid or unenforceable under +any particular circumstance, the balance of the section is intended +to apply, and the section as a whole is intended to apply in other +circumstances. + +It is not the purpose of this section to induce you to infringe any +patents or other property right claims or to contest validity of any +such claims; this section has the sole purpose of protecting the +integrity of the free software distribution system which is +implemented by public license practices. Many people have made +generous contributions to the wide range of software distributed +through that system in reliance on consistent application of that +system; it is up to the author/donor to decide if he or she is willing +to distribute software through any other system and a licensee cannot +impose that choice. + +This section is intended to make thoroughly clear what is believed to +be a consequence of the rest of this License. + + 12. If the distribution and/or use of the Library is restricted in +certain countries either by patents or by copyrighted interfaces, the +original copyright holder who places the Library under this License +may add an explicit geographical distribution limitation excluding +those countries, so that distribution is permitted only in or among +countries not thus excluded. In such case, this License incorporates +the limitation as if written in the body of this License. + + 13. The Free Software Foundation may publish revised and/or new +versions of the Lesser General Public License from time to time. +Such new versions will be similar in spirit to the present version, +but may differ in detail to address new problems or concerns. + +Each version is given a distinguishing version number. If the Library +specifies a version number of this License which applies to it and +"any later version", you have the option of following the terms and +conditions either of that version or of any later version published by +the Free Software Foundation. If the Library does not specify a +license version number, you may choose any version ever published by +the Free Software Foundation. + + 14. If you wish to incorporate parts of the Library into other free +programs whose distribution conditions are incompatible with these, +write to the author to ask for permission. For software which is +copyrighted by the Free Software Foundation, write to the Free +Software Foundation; we sometimes make exceptions for this. Our +decision will be guided by the two goals of preserving the free status +of all derivatives of our free software and of promoting the sharing +and reuse of software generally. + + NO WARRANTY + + 15. BECAUSE THE LIBRARY IS LICENSED FREE OF CHARGE, THERE IS NO +WARRANTY FOR THE LIBRARY, TO THE EXTENT PERMITTED BY APPLICABLE LAW. +EXCEPT WHEN OTHERWISE STATED IN WRITING THE COPYRIGHT HOLDERS AND/OR +OTHER PARTIES PROVIDE THE LIBRARY "AS IS" WITHOUT WARRANTY OF ANY +KIND, EITHER EXPRESSED OR IMPLIED, INCLUDING, BUT NOT LIMITED TO, THE +IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR +PURPOSE. THE ENTIRE RISK AS TO THE QUALITY AND PERFORMANCE OF THE +LIBRARY IS WITH YOU. SHOULD THE LIBRARY PROVE DEFECTIVE, YOU ASSUME +THE COST OF ALL NECESSARY SERVICING, REPAIR OR CORRECTION. + + 16. IN NO EVENT UNLESS REQUIRED BY APPLICABLE LAW OR AGREED TO IN +WRITING WILL ANY COPYRIGHT HOLDER, OR ANY OTHER PARTY WHO MAY MODIFY +AND/OR REDISTRIBUTE THE LIBRARY AS PERMITTED ABOVE, BE LIABLE TO YOU +FOR DAMAGES, INCLUDING ANY GENERAL, SPECIAL, INCIDENTAL OR +CONSEQUENTIAL DAMAGES ARISING OUT OF THE USE OR INABILITY TO USE THE +LIBRARY (INCLUDING BUT NOT LIMITED TO LOSS OF DATA OR DATA BEING +RENDERED INACCURATE OR LOSSES SUSTAINED BY YOU OR THIRD PARTIES OR A +FAILURE OF THE LIBRARY TO OPERATE WITH ANY OTHER SOFTWARE), EVEN IF +SUCH HOLDER OR OTHER PARTY HAS BEEN ADVISED OF THE POSSIBILITY OF SUCH +DAMAGES. + + END OF TERMS AND CONDITIONS + + How to Apply These Terms to Your New Libraries + + If you develop a new library, and you want it to be of the greatest +possible use to the public, we recommend making it free software that +everyone can redistribute and change. You can do so by permitting +redistribution under these terms (or, alternatively, under the terms +of the ordinary General Public License). + + To apply these terms, attach the following notices to the library. +It is safest to attach them to the start of each source file to most +effectively convey the exclusion of warranty; and each file should +have at least the "copyright" line and a pointer to where the full +notice is found. + + + Copyright (C) + + This library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public + License as published by the Free Software Foundation; either + version 2.1 of the License, or (at your option) any later version. + + This library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public + License along with this library; if not, write to the Free Software + Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA + 02110-1301 USA + +Also add information on how to contact you by electronic and paper mail. + +You should also get your employer (if you work as a programmer) or your +school, if any, to sign a "copyright disclaimer" for the library, if +necessary. Here is a sample; alter the names: + + Yoyodyne, Inc., hereby disclaims all copyright interest in the + library `Frob' (a library for tweaking knobs) written by James + Random Hacker. + + , 1 April 1990 + Ty Coon, President of Vice + +That's all there is to it! + + ====================================================================== + ====================================================================== + +Artistic License (Perl) 1.0 + +The "Artistic License" + +Preamble + +The intent of this document is to state the conditions under which a +Package may be copied, such that the Copyright Holder maintains some +semblance of artistic control over the development of the package, +while giving the users of the package the right to use and distribute +the Package in a more-or-less customary fashion, plus the right to make +reasonable modifications. + +Definitions: + + "Package" refers to the collection of files distributed by the + Copyright Holder, and derivatives of that collection of files + created through textual modification. + + "Standard Version" refers to such a Package if it has not been + modified, or has been modified in accordance with the wishes + of the Copyright Holder as specified below. + + "Copyright Holder" is whoever is named in the copyright or + copyrights for the package. + + "You" is you, if you're thinking about copying or distributing + this Package. + + "Reasonable copying fee" is whatever you can justify on the + basis of media cost, duplication charges, time of people involved, + and so on. (You will not be required to justify it to the + Copyright Holder, but only to the computing community at large + as a market that must bear the fee.) + + "Freely Available" means that no fee is charged for the item + itself, though there may be fees involved in handling the item. + It also means that recipients of the item may redistribute it + under the same conditions they received it. + +1. You may make and give away verbatim copies of the source form of the +Standard Version of this Package without restriction, provided that you +duplicate all of the original copyright notices and associated disclaimers. + +2. You may apply bug fixes, portability fixes and other modifications +derived from the Public Domain or from the Copyright Holder. A Package +modified in such a way shall still be considered the Standard Version. + +3. You may otherwise modify your copy of this Package in any way, provided +that you insert a prominent notice in each changed file stating how and +when you changed that file, and provided that you do at least ONE of the +following: + + a) place your modifications in the Public Domain or otherwise make them + Freely Available, such as by posting said modifications to Usenet or + an equivalent medium, or placing the modifications on a major archive + site such as uunet.uu.net, or by allowing the Copyright Holder to include + your modifications in the Standard Version of the Package. + + b) use the modified Package only within your corporation or organization. + + c) rename any non-standard executables so the names do not conflict + with standard executables, which must also be provided, and provide + a separate manual page for each non-standard executable that clearly + documents how it differs from the Standard Version. + + d) make other distribution arrangements with the Copyright Holder. + +4. You may distribute the programs of this Package in object code or +executable form, provided that you do at least ONE of the following: + + a) distribute a Standard Version of the executables and library files, + together with instructions (in the manual page or equivalent) on where + to get the Standard Version. + + b) accompany the distribution with the machine-readable source of + the Package with your modifications. + + c) give non-standard executables non-standard names, and clearly + document the differences in manual pages (or equivalent), together + with instructions on where to get the Standard Version. + + d) make other distribution arrangements with the Copyright Holder. + +5. You may charge a reasonable copying fee for any distribution of this +Package. You may charge any fee you choose for support of this +Package. You may not charge a fee for this Package itself. However, +you may distribute this Package in aggregate with other (possibly +commercial) programs as part of a larger (possibly commercial) software +distribution provided that you do not advertise this Package as a +product of your own. You may embed this Package's interpreter within +an executable of yours (by linking); this shall be construed as a mere +form of aggregation, provided that the complete Standard Version of the +interpreter is so embedded. + +6. The scripts and library files supplied as input to or produced as +output from the programs of this Package do not automatically fall +under the copyright of this Package, but belong to whoever generated +them, and may be sold commercially, and may be aggregated with this +Package. If such scripts or library files are aggregated with this +Package via the so-called "undump" or "unexec" methods of producing a +binary executable image, then distribution of such an image shall +neither be construed as a distribution of this Package nor shall it +fall under the restrictions of Paragraphs 3 and 4, provided that you do +not represent such an executable image as a Standard Version of this +Package. + +7. C subroutines (or comparably compiled subroutines in other +languages) supplied by you and linked into this Package in order to +emulate subroutines and variables of the language defined by this +Package shall not be considered part of this Package, but are the +equivalent of input as in Paragraph 6, provided these subroutines do +not change the language in any way that would cause it to fail the +regression tests for the language. + +8. Aggregation of this Package with a commercial distribution is always +permitted provided that the use of this Package is embedded; that is, +when no overt attempt is made to make this Package's interfaces visible +to the end user of the commercial distribution. Such use shall not be +construed as a distribution of this Package. + +9. The name of the Copyright Holder may not be used to endorse or promote +products derived from this software without specific prior written +permission. + +10. THIS PACKAGE IS PROVIDED "AS IS" AND WITHOUT ANY EXPRESS OR +IMPLIED WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED +WARRANTIES OF MERCHANTIBILITY AND FITNESS FOR A PARTICULAR PURPOSE. + + The End + + ====================================================================== + ====================================================================== + +Apache License v2.0, January 2004 + +The following applies to all products licensed under the Apache 2.0 +License: You may not use the identified files except in compliance +with the Apache License, Version 2.0 (the "License.") You may obtain a +copy of the License at http://www.apache.org/licenses/LICENSE-2.0. A +copy of the license is also reproduced below. Unless required by +applicable law or agreed to in writing, software distributed under the +License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR +CONDITIONS OF ANY KIND, either express or implied. See the License for +the specific language governing permissions and limitations under the +License. + +Apache License Version 2.0, January 2004 http://www.apache.org/licenses/ + +TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION + +1. Definitions. + +"License" shall mean the terms and conditions for use, reproduction, +and distribution as defined by Sections 1 through 9 of this document. + +"Licensor" shall mean the copyright owner or entity authorized by the +copyright owner that is granting the License. + +"Legal Entity" shall mean the union of the acting entity and all other +entities that control, are controlled by, or are under common control +with that entity. For the purposes of this definition, "control" means +(i) the power, direct or indirect, to cause the direction or +management of such entity, whether by contract or otherwise, or (ii) +ownership of fifty percent (50%) or more of the outstanding shares, or +(iii) beneficial ownership of such entity. + +"You" (or "Your") shall mean an individual or Legal Entity exercising +permissions granted by this License. + +"Source" form shall mean the preferred form for making modifications, +including but not limited to software source code, documentation +source, and configuration files. + +"Object" form shall mean any form resulting from mechanical +transformation or translation of a Source form, including but not +limited to compiled object code, generated documentation, and +conversions to other media types. + +"Work" shall mean the work of authorship, whether in Source or Object +form, made available under the License, as indicated by a copyright +notice that is included in or attached to the work (an example is +provided in the Appendix below). + +"Derivative Works" shall mean any work, whether in Source or Object +form, that is based on (or derived from) the Work and for which the +editorial revisions, annotations, elaborations, or other modifications +represent, as a whole, an original work of authorship. For the +purposes of this License, Derivative Works shall not include works +that remain separable from, or merely link (or bind by name) to the +interfaces of, the Work and Derivative Works thereof. + +"Contribution" shall mean any work of authorship, including the +original version of the Work and any modifications or additions to +that Work or Derivative Works thereof, that is intentionally submitted +to Licensor for inclusion in the Work by the copyright owner or by an +individual or Legal Entity authorized to submit on behalf of the +copyright owner. For the purposes of this definition, "submitted" +means any form of electronic, verbal, or written communication sent to +the Licensor or its representatives, including but not limited to +communication on electronic mailing lists, source code control +systems, and issue tracking systems that are managed by, or on behalf +of, the Licensor for the purpose of discussing and improving the Work, +but excluding communication that is conspicuously marked or otherwise +designated in writing by the copyright owner as "Not a Contribution." + +"Contributor" shall mean Licensor and any individual or Legal Entity +on behalf of whom a Contribution has been received by Licensor and +subsequently incorporated within the Work. + +2. Grant of Copyright License. Subject to the terms and conditions of +this License, each Contributor hereby grants to You a perpetual, +worldwide, non-exclusive, no-charge, royalty-free, irrevocable +copyright license to reproduce, prepare Derivative Works of, publicly +display, publicly perform, sublicense, and distribute the Work and +such Derivative Works in Source or Object form. + +3. Grant of Patent License. Subject to the terms and conditions of +this License, each Contributor hereby grants to You a perpetual, +worldwide, non-exclusive, no-charge, royalty-free, irrevocable (except +as stated in this section) patent license to make, have made, use, +offer to sell, sell, import, and otherwise transfer the Work, where +such license applies only to those patent claims licensable by such +Contributor that are necessarily infringed by their Contribution(s) +alone or by combination of their Contribution(s) with the Work to +which such Contribution(s) was submitted. If You institute patent +litigation against any entity (including a cross-claim or counterclaim +in a lawsuit) alleging that the Work or a Contribution incorporated +within the Work constitutes direct or contributory patent +infringement, then any patent licenses granted to You under this +License for that Work shall terminate as of the date such litigation +is filed. + +4. Redistribution. You may reproduce and distribute copies of the Work +or Derivative Works thereof in any medium, with or without +modifications, and in Source or Object form, provided that You meet +the following conditions: + +(a) You must give any other recipients of the Work or Derivative Works +a copy of this License; and + +(b) You must cause any modified files to carry prominent notices +stating that You changed the files; and + +(c) You must retain, in the Source form of any Derivative Works that +You distribute, all copyright, patent, trademark, and attribution +notices from the Source form of the Work, excluding those notices that +do not pertain to any part of the Derivative Works; and + +(d) If the Work includes a "NOTICE" text file as part of its +distribution, then any Derivative Works that You distribute must +include a readable copy of the attribution notices contained + +within such NOTICE file, excluding those notices that do not pertain +to any part of the Derivative Works, in at least one of the following +places: within a NOTICE text file distributed as part of the +Derivative Works; within the Source form or documentation, if provided +along with the Derivative Works; or, within a display generated by the +Derivative Works, if and wherever such third-party notices normally +appear. The contents of the NOTICE file are for informational purposes +only and do not modify the License. You may add Your own attribution +notices within Derivative Works that You distribute, alongside or as +an addendum to the NOTICE text from the Work, provided that such +additional attribution notices cannot be construed as modifying the +License. + +You may add Your own copyright statement to Your modifications and may +provide additional or different license terms and conditions for use, +reproduction, or distribution of Your modifications, or for any such +Derivative Works as a whole, provided Your use, reproduction, and +distribution of the Work otherwise complies with the conditions stated +in this License. + +5. Submission of Contributions. Unless You explicitly state otherwise, +any Contribution intentionally submitted for inclusion in the Work by +You to the Licensor shall be under the terms and conditions of this +License, without any additional terms or conditions. Notwithstanding +the above, nothing herein shall supersede or modify the terms of any +separate license agreement you may have executed with Licensor +regarding such Contributions. + +6. Trademarks. This License does not grant permission to use the trade +names, trademarks, service marks, or product names of the Licensor, +except as required for reasonable and customary use in describing the +origin of the Work and reproducing the content of the NOTICE file. + +7. Disclaimer of Warranty. Unless required by applicable law or agreed +to in writing, Licensor provides the Work (and each Contributor +provides its Contributions) on an "AS IS" BASIS, WITHOUT WARRANTIES OR +CONDITIONS OF ANY KIND, either express or implied, including, without +limitation, any warranties or conditions of TITLE, NON-INFRINGEMENT, +MERCHANTABILITY, or FITNESS FOR A PARTICULAR PURPOSE. You are solely +responsible for determining the appropriateness of using or +redistributing the Work and assume any risks associated with Your +exercise of permissions under this License. + +8. Limitation of Liability. In no event and under no legal theory, +whether in tort (including negligence), contract, or otherwise, unless +required by applicable law (such as deliberate and grossly negligent +acts) or agreed to in writing, shall any Contributor be liable to You +for damages, including any direct, indirect, special, incidental, or +consequential damages of any character arising as a result of this +License or out of the use or inability to use the Work (including but +not limited to damages for loss of goodwill, work stoppage, computer +failure or malfunction, or any and all other commercial damages or +losses), even if such Contributor has been advised of the possibility +of such damages. + +9. Accepting Warranty or Additional Liability. While redistributing +the Work or Derivative Works thereof, You may choose to offer, and +charge a fee for, acceptance of support, warranty, indemnity, or other +liability obligations and/or rights consistent with this +License. However, in accepting such obligations, You may act only on +Your own behalf and on Your sole responsibility, not on behalf of any +other Contributor, and only if You agree to indemnify, defend, and +hold each Contributor harmless for any liability incurred by, or +claims asserted against, such Contributor by reason of your accepting +any such warranty or additional liability. + +END OF TERMS AND CONDITIONS + +APPENDIX: How to apply the Apache License to your work + +To apply the Apache License to your work, attach the following boilerplate +notice, with the fields enclosed by brackets "[]" replaced with your own +identifying information. (Don't include the brackets!) The text should be +enclosed in the appropriate comment syntax for the file format. We also +recommend that a file or class name and description of purpose be included +on the same "printed page" as the copyright notice for easier identification +within third-party archives. + +Copyright [yyyy] [name of copyright owner] + +Licensed under the Apache License, Version 2.0 (the "License"); +you may not use this file except in compliance with the License. +You may obtain a copy of the License at +http://www.apache.org/licenses/LICENSE-2.0 + +Unless required by applicable law or agreed to in writing, software +distributed under the License is distributed on an "AS IS" BASIS, +WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or +implied. See the License for the specific language governing permissions +and limitations under the License. + + ====================================================================== + ====================================================================== + +Written Offer for Source Code + + For any software that you receive from Oracle in binary form which is + licensed under an open source license that gives you the right to + receive the source code for that binary, you can obtain a copy of the + applicable source code by visiting + http://www.oracle.com/goto/opensourcecode. If the source code for the + binary was not provided to you with the binary, you can also receive a + copy of the source code on physical media by submitting a written + request to the address listed below or by sending an email to Oracle + using the following link: + http://www.oracle.com/goto/opensourcecode/request. + + Oracle America, Inc. + Attn: Senior Vice President + Development and Engineering Legal + 500 Oracle Parkway, 10th Floor + Redwood Shores, CA 94065 + + Your request should include: + + * The name of the binary for which you are requesting the source code + + * The name and version number of the Oracle product containing the + binary + + * The date you received the Oracle product + + * Your name + + * Your company name (if applicable) + + * Your return mailing address and email, and + + * A telephone number in the event we need to reach you. + + + We may charge you a fee to cover the cost of physical media and + processing. + + Your request must be sent + + a. within three (3) years of the date you received the Oracle product + that included the binary that is the subject of your request, or + + b. in the case of code licensed under the GPL v3 for as long as Oracle + offers spare parts or customer support for that product model. diff --git a/vendor/mysql/README.md b/vendor/mysql/README.md new file mode 100644 index 0000000000..8eaa12bd38 --- /dev/null +++ b/vendor/mysql/README.md @@ -0,0 +1,106 @@ +DLL files can be found in `Shared/data/MTA San Andreas/server`. +That directory gets copied to the "Bin" directory when you run "win-install-data.bat". + +The source code for MySQL and OpenSSL used to produce the binaries can be found here: +https://github.com/mysql/mysql-server/releases/tag/mysql-8.4.0 +https://github.com/openssl/openssl/releases/tag/openssl-3.3.1 + +## How to compile OpenSSL + +1. Install [Perl](https://strawberryperl.com/). +2. Install [NASM](https://www.nasm.us/). +3. Ensure both Perl and NASM are available on your `%PATH%`. +4. Clone the repository: + ```bat + git clone --recurse-submodules https://github.com/openssl/openssl.git + cd openssl + ``` +5. Switch to the release tag: + ```bat + git switch --detach --force --recurse-submodules openssl-3.3.1 + ``` +6. Run `VsDevCmd.cmd` to open three Developer Command Prompts. +> [!IMPORTANT] +> The next steps assume the OpenSSL checkout directory is `C:\GitHub\openssl`. +7. Switch to the `VsDevCmd: x64` console window and run these commands there: + ```bat + cd C:\GitHub\openssl + perl Configure --release --prefix="%cd%\VC-WIN64A\OpenSSL" --openssldir="%cd%\VC-WIN64A\SSL" /MT VC-WIN64A + nmake + nmake install + ``` +8. Switch to the `VsDevCmd: x86` console window and run these commands there: + ```bat + cd C:\GitHub\openssl + git clean -f -x + perl Configure --release --prefix="%cd%\VC-WIN32\OpenSSL" --openssldir="%cd%\VC-WIN32\SSL" /MT VC-WIN32 + nmake + nmake install + ``` +9. Switch to the `VsDevCmd: arm64` console window and run these commands there: + ```bat + cd C:\GitHub\openssl + git clean -f -x + perl Configure --release --prefix="%cd%\VC-WIN64-ARM\OpenSSL" --openssldir="%cd%\VC-WIN64-ARM\SSL" /MT VC-WIN64-ARM + nmake + nmake install + ``` + +> [!IMPORTANT] +> Copy `VC-WIN64A\OpenSSL\include\openssl\applink.c` to `VC-WIN64-ARM\OpenSSL\include\openssl\` + +## How to compile MySQL + +1. Compile OpenSSL with the steps above. +2. Install [CMake](https://cmake.org/download/). +3. Clone the repository: + ```bat + git clone --recurse-submodules https://github.com/mysql/mysql-server.git + cd mysql-server + ``` +4. Switch to the release tag: + ```bat + git switch --detach --force --recurse-submodules mysql-8.4.0 + ``` +5. Apply the patch file: + ```bat + git apply path\to\vendor\mysql\mysql-server.diff + ``` +6. Run `VsDevCmd.cmd` to open three Developer Command Prompts. +> [!IMPORTANT] +> The next steps assume the OpenSSL checkout directory is `C:\GitHub\openssl` +> and the MySQL checkout directory is `C:\GitHub\mysql-server`. +> You must always compile x64 before cross-compiling arm64. +7. Switch to the `VsDevCmd: x64` console window and run these commands there: + ```bat + cd C:\GitHub\mysql-server + cmake -G "Visual Studio 17 2022" -A x64 -B build-x64 -DCMAKE_INSTALL_PREFIX="%cd%\install-x64" -DWITH_SSL="C:\GitHub\openssl\VC-WIN64A\OpenSSL" + cmake --build build-x64 --target INSTALL --config RelWithDebInfo + ``` +8. Switch to the `VsDevCmd: x86` console window and run these commands there: + ```bat + cd C:\GitHub\mysql-server + cmake -G "Visual Studio 17 2022" -A Win32 -B build-x86 -DCMAKE_INSTALL_PREFIX="%cd%\install-x86" -DWITH_SSL="C:\GitHub\openssl\VC-WIN32\OpenSSL" + cmake --build build-x86 --target INSTALL --config RelWithDebInfo + ``` +9. Switch to the `VsDevCmd: arm64` console window and run these commands there: + ```bat + cd C:\GitHub\mysql-server + cmake -G "Visual Studio 17 2022" -A ARM64 -B build-arm64 -DCMAKE_INSTALL_PREFIX="%cd%\install-arm64" -DWITH_SSL="C:\GitHub\openssl\VC-WIN64-ARM\OpenSSL" + cmake --build build-arm64 --target INSTALL --config RelWithDebInfo + ``` + +## How to update MySQL + +1. Compile MySQL with the steps above. +2. Copy each folder `C:\GitHub\mysql-server\install-{x86,x64,arm64}\` to a temporary directory. +3. Copy `install-x64\LICENSE` to `vendor\mysql`. +4. Copy `install-x64\include` to `vendor\mysql\include`. +5. For each `install-{arch}` folder: + 1. Delete all folders, but keep `bin` and `lib`. + 2. In `lib` folder delete everything, but keep `libmysql.{dll,lib,pdb}`. + 3. In `bin` folder delete everything, but keep `libcrypto-*` and `libssql-*` files. + 4. Sign all `*.dll` files. + 5. Copy signed `*.dll` files to their designed subfolder in `Shared\data\MTA San Andreas\server`. + 6. Copy `lib\libmysql.lib` to `vendor\mysql\lib\{arch}\`. +6. Commit the update. diff --git a/vendor/mysql/VsDevCmd.cmd b/vendor/mysql/VsDevCmd.cmd new file mode 100644 index 0000000000..a0316aa275 --- /dev/null +++ b/vendor/mysql/VsDevCmd.cmd @@ -0,0 +1,27 @@ +@echo off + +set "VSWHERE=%ProgramFiles(x86)%\Microsoft Visual Studio\Installer\vswhere.exe" +if exist "%VSWHERE%" goto :FindVisualStudio + +echo Unable to locate Visual Studio: vswhere not found +echo ^>^> %VSWHERE% +pause +exit /b 1 + +:FindVisualStudio +for /f "usebackq tokens=*" %%i in (`call "%VSWHERE%" -latest -requires Microsoft.Component.MSBuild -find "**\VsDevCmd.bat"`) do ( + set VSDEVCMD=%%i +) + +if defined VSDEVCMD goto :SetupEnv +echo Visual Studio not found +echo Make sure you've installed the 'Desktop development with C++' workload +pause +exit /b 1 + +:SetupEnv +echo Found Visual Studio environment setup batch file: +echo ^>^> %VSDEVCMD% +start "VsDevCmd: arm64" "%comspec%" /k "%VSDEVCMD%" -arch=arm64 -host_arch=amd64 +start "VsDevCmd: x64" "%comspec%" /k "%VSDEVCMD%" -arch=amd64 -host_arch=amd64 +start "VsDevCmd: x86" "%comspec%" /k "%VSDEVCMD%" -arch=x86 -host_arch=amd64 diff --git a/vendor/mysql/include/big_endian.h b/vendor/mysql/include/big_endian.h deleted file mode 100644 index 59aa70b9d6..0000000000 --- a/vendor/mysql/include/big_endian.h +++ /dev/null @@ -1,114 +0,0 @@ -/* Copyright (c) 2012, 2014, Oracle and/or its affiliates. All rights reserved. - - This program is free software; you can redistribute it and/or modify - it under the terms of the GNU General Public License as published by - the Free Software Foundation; version 2 of the License. - - This program is distributed in the hope that it will be useful, - but WITHOUT ANY WARRANTY; without even the implied warranty of - MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - GNU General Public License for more details. - - You should have received a copy of the GNU General Public License - along with this program; if not, write to the Free Software - Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA */ - -#include - -/* - Data in big-endian format. -*/ -static inline void float4store(uchar *T, float A) -{ *(T)= ((uchar *) &A)[3]; - *((T)+1)=(char) ((uchar *) &A)[2]; - *((T)+2)=(char) ((uchar *) &A)[1]; - *((T)+3)=(char) ((uchar *) &A)[0]; } - -static inline void float4get (float *V, const uchar *M) -{ float def_temp; - ((uchar*) &def_temp)[0]=(M)[3]; - ((uchar*) &def_temp)[1]=(M)[2]; - ((uchar*) &def_temp)[2]=(M)[1]; - ((uchar*) &def_temp)[3]=(M)[0]; - (*V)=def_temp; } - -static inline void float8store(uchar *T, double V) -{ *(T)= ((uchar *) &V)[7]; - *((T)+1)=(char) ((uchar *) &V)[6]; - *((T)+2)=(char) ((uchar *) &V)[5]; - *((T)+3)=(char) ((uchar *) &V)[4]; - *((T)+4)=(char) ((uchar *) &V)[3]; - *((T)+5)=(char) ((uchar *) &V)[2]; - *((T)+6)=(char) ((uchar *) &V)[1]; - *((T)+7)=(char) ((uchar *) &V)[0]; } - -static inline void float8get (double *V, const uchar *M) -{ double def_temp; - ((uchar*) &def_temp)[0]=(M)[7]; - ((uchar*) &def_temp)[1]=(M)[6]; - ((uchar*) &def_temp)[2]=(M)[5]; - ((uchar*) &def_temp)[3]=(M)[4]; - ((uchar*) &def_temp)[4]=(M)[3]; - ((uchar*) &def_temp)[5]=(M)[2]; - ((uchar*) &def_temp)[6]=(M)[1]; - ((uchar*) &def_temp)[7]=(M)[0]; - (*V) = def_temp; } - -static inline void ushortget(uint16 *V, const uchar *pM) -{ *V = (uint16) (((uint16) ((uchar) (pM)[1]))+ - ((uint16) ((uint16) (pM)[0]) << 8)); } -static inline void shortget (int16 *V, const uchar *pM) -{ *V = (short) (((short) ((uchar) (pM)[1]))+ - ((short) ((short) (pM)[0]) << 8)); } -static inline void longget (int32 *V, const uchar *pM) -{ int32 def_temp; - ((uchar*) &def_temp)[0]=(pM)[0]; - ((uchar*) &def_temp)[1]=(pM)[1]; - ((uchar*) &def_temp)[2]=(pM)[2]; - ((uchar*) &def_temp)[3]=(pM)[3]; - (*V)=def_temp; } -static inline void ulongget (uint32 *V, const uchar *pM) -{ uint32 def_temp; - ((uchar*) &def_temp)[0]=(pM)[0]; - ((uchar*) &def_temp)[1]=(pM)[1]; - ((uchar*) &def_temp)[2]=(pM)[2]; - ((uchar*) &def_temp)[3]=(pM)[3]; - (*V)=def_temp; } -static inline void shortstore(uchar *T, int16 A) -{ uint def_temp=(uint) (A) ; - *(((char*)T)+1)=(char)(def_temp); - *(((char*)T)+0)=(char)(def_temp >> 8); } -static inline void longstore (uchar *T, int32 A) -{ *(((char*)T)+3)=((A)); - *(((char*)T)+2)=(((A) >> 8)); - *(((char*)T)+1)=(((A) >> 16)); - *(((char*)T)+0)=(((A) >> 24)); } - -static inline void floatget(float *V, const uchar *M) -{ - memcpy(V, (M), sizeof(float)); -} - -static inline void floatstore(uchar *T, float V) -{ - memcpy((T), (&V), sizeof(float)); -} - -static inline void doubleget(double *V, const uchar *M) -{ - memcpy(V, (M), sizeof(double)); -} - -static inline void doublestore(uchar *T, double V) -{ - memcpy((T), &V, sizeof(double)); -} - -static inline void longlongget(longlong *V, const uchar *M) -{ - memcpy(V, (M), sizeof(ulonglong)); -} -static inline void longlongstore(uchar *T, longlong V) -{ - memcpy((T), &V, sizeof(ulonglong)); -} diff --git a/vendor/mysql/include/binary_log_types.h b/vendor/mysql/include/binary_log_types.h deleted file mode 100644 index b20eacf61b..0000000000 --- a/vendor/mysql/include/binary_log_types.h +++ /dev/null @@ -1,70 +0,0 @@ -/* Copyright (c) 2014, 2015 Oracle and/or its affiliates. All rights reserved. - - This program is free software; you can redistribute it and/or modify - it under the terms of the GNU General Public License as published by - the Free Software Foundation; version 2 of the License. - - This program is distributed in the hope that it will be useful, - but WITHOUT ANY WARRANTY; without even the implied warranty of - MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - GNU General Public License for more details. - - You should have received a copy of the GNU General Public License - along with this program; if not, write to the Free Software - Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA */ - -/** - @file binary_log_types.h - - @brief This file contains the field type. - - - @note This file can be imported both from C and C++ code, so the - definitions have to be constructed to support this. -*/ - -#ifndef BINARY_LOG_TYPES_INCLUDED -#define BINARY_LOG_TYPES_INCLUDED - -#ifdef __cplusplus -extern "C" -{ -#endif - -/* - * Constants exported from this package. - */ - -typedef enum enum_field_types { - MYSQL_TYPE_DECIMAL, MYSQL_TYPE_TINY, - MYSQL_TYPE_SHORT, MYSQL_TYPE_LONG, - MYSQL_TYPE_FLOAT, MYSQL_TYPE_DOUBLE, - MYSQL_TYPE_NULL, MYSQL_TYPE_TIMESTAMP, - MYSQL_TYPE_LONGLONG,MYSQL_TYPE_INT24, - MYSQL_TYPE_DATE, MYSQL_TYPE_TIME, - MYSQL_TYPE_DATETIME, MYSQL_TYPE_YEAR, - MYSQL_TYPE_NEWDATE, MYSQL_TYPE_VARCHAR, - MYSQL_TYPE_BIT, - MYSQL_TYPE_TIMESTAMP2, - MYSQL_TYPE_DATETIME2, - MYSQL_TYPE_TIME2, - MYSQL_TYPE_JSON=245, - MYSQL_TYPE_NEWDECIMAL=246, - MYSQL_TYPE_ENUM=247, - MYSQL_TYPE_SET=248, - MYSQL_TYPE_TINY_BLOB=249, - MYSQL_TYPE_MEDIUM_BLOB=250, - MYSQL_TYPE_LONG_BLOB=251, - MYSQL_TYPE_BLOB=252, - MYSQL_TYPE_VAR_STRING=253, - MYSQL_TYPE_STRING=254, - MYSQL_TYPE_GEOMETRY=255 -} enum_field_types; - -#define DATETIME_MAX_DECIMALS 6 - -#ifdef __cplusplus -} -#endif // __cplusplus - -#endif /* BINARY_LOG_TYPES_INCLUDED */ diff --git a/vendor/mysql/include/byte_order_generic.h b/vendor/mysql/include/byte_order_generic.h deleted file mode 100644 index da84585c2a..0000000000 --- a/vendor/mysql/include/byte_order_generic.h +++ /dev/null @@ -1,97 +0,0 @@ -/* Copyright (c) 2001, 2014, Oracle and/or its affiliates. All rights reserved. - - This program is free software; you can redistribute it and/or modify - it under the terms of the GNU General Public License as published by - the Free Software Foundation; version 2 of the License. - - This program is distributed in the hope that it will be useful, - but WITHOUT ANY WARRANTY; without even the implied warranty of - MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - GNU General Public License for more details. - - You should have received a copy of the GNU General Public License - along with this program; if not, write to the Free Software - Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA */ - -/* - Endianness-independent definitions for architectures other - than the x86 architecture. -*/ -static inline int16 sint2korr(const uchar *A) -{ - return - (int16) (((int16) (A[0])) + - ((int16) (A[1]) << 8)) - ; -} - -static inline int32 sint4korr(const uchar *A) -{ - return - (int32) (((int32) (A[0])) + - (((int32) (A[1]) << 8)) + - (((int32) (A[2]) << 16)) + - (((int32) (A[3]) << 24))) - ; -} - -static inline uint16 uint2korr(const uchar *A) -{ - return - (uint16) (((uint16) (A[0])) + - ((uint16) (A[1]) << 8)) - ; -} - -static inline uint32 uint4korr(const uchar *A) -{ - return - (uint32) (((uint32) (A[0])) + - (((uint32) (A[1])) << 8) + - (((uint32) (A[2])) << 16) + - (((uint32) (A[3])) << 24)) - ; -} - -static inline ulonglong uint8korr(const uchar *A) -{ - return - ((ulonglong)(((uint32) (A[0])) + - (((uint32) (A[1])) << 8) + - (((uint32) (A[2])) << 16) + - (((uint32) (A[3])) << 24)) + - (((ulonglong) (((uint32) (A[4])) + - (((uint32) (A[5])) << 8) + - (((uint32) (A[6])) << 16) + - (((uint32) (A[7])) << 24))) << - 32)) - ; -} - -static inline longlong sint8korr(const uchar *A) -{ - return (longlong) uint8korr(A); -} - -static inline void int2store(uchar *T, uint16 A) -{ - uint def_temp= A ; - *(T)= (uchar)(def_temp); - *(T+1)= (uchar)(def_temp >> 8); -} - -static inline void int4store(uchar *T, uint32 A) -{ - *(T)= (uchar) (A); - *(T+1)=(uchar) (A >> 8); - *(T+2)=(uchar) (A >> 16); - *(T+3)=(uchar) (A >> 24); -} - -static inline void int8store(uchar *T, ulonglong A) -{ - uint def_temp= (uint) A, - def_temp2= (uint) (A >> 32); - int4store(T, def_temp); - int4store(T+4,def_temp2); -} diff --git a/vendor/mysql/include/byte_order_generic_x86.h b/vendor/mysql/include/byte_order_generic_x86.h deleted file mode 100644 index b3762b504c..0000000000 --- a/vendor/mysql/include/byte_order_generic_x86.h +++ /dev/null @@ -1,56 +0,0 @@ -/* Copyright (c) 2001, 2015, Oracle and/or its affiliates. All rights reserved. - - This program is free software; you can redistribute it and/or modify - it under the terms of the GNU General Public License as published by - the Free Software Foundation; version 2 of the License. - - This program is distributed in the hope that it will be useful, - but WITHOUT ANY WARRANTY; without even the implied warranty of - MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - GNU General Public License for more details. - - You should have received a copy of the GNU General Public License - along with this program; if not, write to the Free Software - Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA */ - -/* - Optimized functions for the x86 architecture (_WIN32 included). - - x86 handles misaligned reads and writes just fine, so suppress - UBSAN warnings for these functions. -*/ -static inline int16 sint2korr(const uchar *A) SUPPRESS_UBSAN; -static inline int16 sint2korr(const uchar *A) { return *((int16*) A); } - -static inline int32 sint4korr(const uchar *A) SUPPRESS_UBSAN; -static inline int32 sint4korr(const uchar *A) { return *((int32*) A); } - -static inline uint16 uint2korr(const uchar *A) SUPPRESS_UBSAN; -static inline uint16 uint2korr(const uchar *A) { return *((uint16*) A); } - -static inline uint32 uint4korr(const uchar *A) SUPPRESS_UBSAN; -static inline uint32 uint4korr(const uchar *A) { return *((uint32*) A); } - -static inline ulonglong uint8korr(const uchar *A) SUPPRESS_UBSAN; -static inline ulonglong uint8korr(const uchar *A) { return *((ulonglong*) A);} - -static inline longlong sint8korr(const uchar *A) SUPPRESS_UBSAN; -static inline longlong sint8korr(const uchar *A) { return *((longlong*) A); } - -static inline void int2store(uchar *T, uint16 A) SUPPRESS_UBSAN; -static inline void int2store(uchar *T, uint16 A) -{ - *((uint16*) T)= A; -} - -static inline void int4store(uchar *T, uint32 A) SUPPRESS_UBSAN; -static inline void int4store(uchar *T, uint32 A) -{ - *((uint32*) T)= A; -} - -static inline void int8store(uchar *T, ulonglong A) SUPPRESS_UBSAN; -static inline void int8store(uchar *T, ulonglong A) -{ - *((ulonglong*) T)= A; -} diff --git a/vendor/mysql/include/decimal.h b/vendor/mysql/include/decimal.h deleted file mode 100644 index f963b6fd10..0000000000 --- a/vendor/mysql/include/decimal.h +++ /dev/null @@ -1,137 +0,0 @@ -/* Copyright (c) 2000, 2015, Oracle and/or its affiliates. All rights reserved. - - This program is free software; you can redistribute it and/or modify - it under the terms of the GNU General Public License as published by - the Free Software Foundation; version 2 of the License. - - This program is distributed in the hope that it will be useful, - but WITHOUT ANY WARRANTY; without even the implied warranty of - MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - GNU General Public License for more details. - - You should have received a copy of the GNU General Public License - along with this program; if not, write to the Free Software - Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA */ - -#ifndef DECIMAL_INCLUDED -#define DECIMAL_INCLUDED - -typedef enum -{TRUNCATE=0, HALF_EVEN, HALF_UP, CEILING, FLOOR} - decimal_round_mode; -typedef int32 decimal_digit_t; - -/** - intg is the number of *decimal* digits (NOT number of decimal_digit_t's !) - before the point - frac is the number of decimal digits after the point - len is the length of buf (length of allocated space) in decimal_digit_t's, - not in bytes - sign false means positive, true means negative - buf is an array of decimal_digit_t's - */ -typedef struct st_decimal_t { - int intg, frac, len; - my_bool sign; - decimal_digit_t *buf; -} decimal_t; - -#ifndef MYSQL_ABI_CHECK -int internal_str2dec(const char *from, decimal_t *to, char **end, - my_bool fixed); -int decimal2string(const decimal_t *from, char *to, int *to_len, - int fixed_precision, int fixed_decimals, - char filler); -int decimal2ulonglong(decimal_t *from, ulonglong *to); -int ulonglong2decimal(ulonglong from, decimal_t *to); -int decimal2longlong(decimal_t *from, longlong *to); -int longlong2decimal(longlong from, decimal_t *to); -int decimal2double(const decimal_t *from, double *to); -int double2decimal(double from, decimal_t *to); -int decimal_actual_fraction(decimal_t *from); -int decimal2bin(decimal_t *from, uchar *to, int precision, int scale); -int bin2decimal(const uchar *from, decimal_t *to, int precision, int scale); - -/** - Convert decimal to lldiv_t. - The integer part is stored in to->quot. - The fractional part is multiplied to 10^9 and stored to to->rem. - @param from Decimal value - @param to lldiv_t value - @retval 0 on success - @retval !0 in error -*/ -int decimal2lldiv_t(const decimal_t *from, lldiv_t *to); - -/** - Convert doube to lldiv_t. - The integer part is stored in to->quot. - The fractional part is multiplied to 10^9 and stored to to->rem. - @param from Decimal value - @param to lldiv_t value - @retval 0 on success - @retval !0 in error -*/ - -int double2lldiv_t(double from, lldiv_t *to); -int decimal_size(int precision, int scale); -int decimal_bin_size(int precision, int scale); -int decimal_result_size(decimal_t *from1, decimal_t *from2, char op, - int param); - -int decimal_intg(const decimal_t *from); -int decimal_add(const decimal_t *from1, const decimal_t *from2, decimal_t *to); -int decimal_sub(const decimal_t *from1, const decimal_t *from2, decimal_t *to); -int decimal_cmp(const decimal_t *from1, const decimal_t *from2); -int decimal_mul(const decimal_t *from1, const decimal_t *from2, decimal_t *to); -int decimal_div(const decimal_t *from1, const decimal_t *from2, decimal_t *to, - int scale_incr); -int decimal_mod(const decimal_t *from1, const decimal_t *from2, decimal_t *to); -int decimal_round(const decimal_t *from, decimal_t *to, int new_scale, - decimal_round_mode mode); -int decimal_is_zero(const decimal_t *from); -void max_decimal(int precision, int frac, decimal_t *to); - -#define string2decimal(A,B,C) internal_str2dec((A), (B), (C), 0) -#define string2decimal_fixed(A,B,C) internal_str2dec((A), (B), (C), 1) - -/* set a decimal_t to zero */ - -#define decimal_make_zero(dec) do { \ - (dec)->buf[0]=0; \ - (dec)->intg=1; \ - (dec)->frac=0; \ - (dec)->sign=0; \ - } while(0) - -/* - returns the length of the buffer to hold string representation - of the decimal (including decimal dot, possible sign and \0) -*/ - -#define decimal_string_size(dec) (((dec)->intg ? (dec)->intg : 1) + \ - (dec)->frac + ((dec)->frac > 0) + 2) - -/* - conventions: - - decimal_smth() == 0 -- everything's ok - decimal_smth() <= 1 -- result is usable, but precision loss is possible - decimal_smth() <= 2 -- result can be unusable, most significant digits - could've been lost - decimal_smth() > 2 -- no result was generated -*/ - -#define E_DEC_OK 0 -#define E_DEC_TRUNCATED 1 -#define E_DEC_OVERFLOW 2 -#define E_DEC_DIV_ZERO 4 -#define E_DEC_BAD_NUM 8 -#define E_DEC_OOM 16 - -#define E_DEC_ERROR 31 -#define E_DEC_FATAL_ERROR 30 - -#endif // !MYSQL_ABI_CHECK - -#endif diff --git a/vendor/mysql/include/errmsg.h b/vendor/mysql/include/errmsg.h index 9c5327a98d..eb7d45a977 100644 --- a/vendor/mysql/include/errmsg.h +++ b/vendor/mysql/include/errmsg.h @@ -1,113 +1,148 @@ #ifndef ERRMSG_INCLUDED #define ERRMSG_INCLUDED -/* Copyright (c) 2000, 2015, Oracle and/or its affiliates. All rights reserved. +/* Copyright (c) 2000, 2024, Oracle and/or its affiliates. This program is free software; you can redistribute it and/or modify - it under the terms of the GNU General Public License as published by - the Free Software Foundation; version 2 of the License. + it under the terms of the GNU General Public License, version 2.0, + as published by the Free Software Foundation. + + This program is designed to work with certain software (including + but not limited to OpenSSL) that is licensed under separate terms, + as designated in a particular file or component or in included license + documentation. The authors of MySQL hereby grant you an additional + permission to link the program and your derivative works with the + separately licensed software that they have either included with + the program or referenced in the documentation. + + Without limiting anything contained in the foregoing, this file, + which is part of C Driver for MySQL (Connector/C), is also subject to the + Universal FOSS Exception, version 1.0, a copy of which can be found at + http://oss.oracle.com/licenses/universal-foss-exception. This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - GNU General Public License for more details. + GNU General Public License, version 2.0, for more details. You should have received a copy of the GNU General Public License along with this program; if not, write to the Free Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA */ -/* Error messages for MySQL clients */ -/* (Error messages for the daemon are in sql/share/errmsg.txt) */ +/** + @file include/errmsg.h -#ifdef __cplusplus -extern "C" { -#endif -void init_client_errs(void); -void finish_client_errs(void); -extern const char *client_errors[]; /* Error messages */ -#ifdef __cplusplus -} -#endif + Error messages for MySQL clients. + These are constant and use the CR_ prefix. + will contain auto-generated mappings + containing the symbolic name and the number from this file, + and the english error messages in libmysql/errmsg.c. + + Dynamic error messages for the daemon are in share/language/errmsg.sys. + The server equivalent to is . + The server equivalent to is . -#define CR_MIN_ERROR 2000 /* For easier client code */ -#define CR_MAX_ERROR 2999 -#if !defined(ER) -#define ER(X) (((X) >= CR_ERROR_FIRST && (X) <= CR_ERROR_LAST)? \ - client_errors[(X)-CR_ERROR_FIRST]: client_errors[CR_UNKNOWN_ERROR]) + Note that the auth subsystem also uses codes with a CR_ prefix. +*/ -#endif -#define CLIENT_ERRMAP 2 /* Errormap used by my_error() */ +void init_client_errs(void); +void finish_client_errs(void); +extern const char *client_errors[]; /* Error messages */ + +#define CR_MIN_ERROR 2000 /* For easier client code */ +#define CR_MAX_ERROR 2999 +#define CLIENT_ERRMAP 2 /* Errormap used by my_error() */ /* Do not add error numbers before CR_ERROR_FIRST. */ /* If necessary to add lower numbers, change CR_ERROR_FIRST accordingly. */ -#define CR_ERROR_FIRST 2000 /*Copy first error nr.*/ -#define CR_UNKNOWN_ERROR 2000 -#define CR_SOCKET_CREATE_ERROR 2001 -#define CR_CONNECTION_ERROR 2002 -#define CR_CONN_HOST_ERROR 2003 -#define CR_IPSOCK_ERROR 2004 -#define CR_UNKNOWN_HOST 2005 -#define CR_SERVER_GONE_ERROR 2006 -#define CR_VERSION_ERROR 2007 -#define CR_OUT_OF_MEMORY 2008 -#define CR_WRONG_HOST_INFO 2009 +#define CR_ERROR_FIRST 2000 /*Copy first error nr.*/ +#define CR_UNKNOWN_ERROR 2000 +#define CR_SOCKET_CREATE_ERROR 2001 +#define CR_CONNECTION_ERROR 2002 +#define CR_CONN_HOST_ERROR 2003 +#define CR_IPSOCK_ERROR 2004 +#define CR_UNKNOWN_HOST 2005 +#define CR_SERVER_GONE_ERROR 2006 +#define CR_VERSION_ERROR 2007 +#define CR_OUT_OF_MEMORY 2008 +#define CR_WRONG_HOST_INFO 2009 #define CR_LOCALHOST_CONNECTION 2010 -#define CR_TCP_CONNECTION 2011 +#define CR_TCP_CONNECTION 2011 #define CR_SERVER_HANDSHAKE_ERR 2012 -#define CR_SERVER_LOST 2013 +#define CR_SERVER_LOST 2013 #define CR_COMMANDS_OUT_OF_SYNC 2014 #define CR_NAMEDPIPE_CONNECTION 2015 -#define CR_NAMEDPIPEWAIT_ERROR 2016 -#define CR_NAMEDPIPEOPEN_ERROR 2017 +#define CR_NAMEDPIPEWAIT_ERROR 2016 +#define CR_NAMEDPIPEOPEN_ERROR 2017 #define CR_NAMEDPIPESETSTATE_ERROR 2018 -#define CR_CANT_READ_CHARSET 2019 +#define CR_CANT_READ_CHARSET 2019 #define CR_NET_PACKET_TOO_LARGE 2020 -#define CR_EMBEDDED_CONNECTION 2021 -#define CR_PROBE_SLAVE_STATUS 2022 -#define CR_PROBE_SLAVE_HOSTS 2023 -#define CR_PROBE_SLAVE_CONNECT 2024 -#define CR_PROBE_MASTER_CONNECT 2025 +#define CR_EMBEDDED_CONNECTION 2021 +#define CR_PROBE_REPLICA_STATUS 2022 +#define CR_PROBE_REPLICA_HOSTS 2023 +#define CR_PROBE_REPLICA_CONNECT 2024 +#define CR_PROBE_SOURCE_CONNECT 2025 #define CR_SSL_CONNECTION_ERROR 2026 -#define CR_MALFORMED_PACKET 2027 -#define CR_WRONG_LICENSE 2028 +#define CR_MALFORMED_PACKET 2027 +#define CR_WRONG_LICENSE 2028 /* new 4.1 error codes */ -#define CR_NULL_POINTER 2029 -#define CR_NO_PREPARE_STMT 2030 -#define CR_PARAMS_NOT_BOUND 2031 -#define CR_DATA_TRUNCATED 2032 +#define CR_NULL_POINTER 2029 +#define CR_NO_PREPARE_STMT 2030 +#define CR_PARAMS_NOT_BOUND 2031 +#define CR_DATA_TRUNCATED 2032 #define CR_NO_PARAMETERS_EXISTS 2033 #define CR_INVALID_PARAMETER_NO 2034 -#define CR_INVALID_BUFFER_USE 2035 +#define CR_INVALID_BUFFER_USE 2035 #define CR_UNSUPPORTED_PARAM_TYPE 2036 -#define CR_SHARED_MEMORY_CONNECTION 2037 -#define CR_SHARED_MEMORY_CONNECT_REQUEST_ERROR 2038 -#define CR_SHARED_MEMORY_CONNECT_ANSWER_ERROR 2039 +#define CR_SHARED_MEMORY_CONNECTION 2037 +#define CR_SHARED_MEMORY_CONNECT_REQUEST_ERROR 2038 +#define CR_SHARED_MEMORY_CONNECT_ANSWER_ERROR 2039 #define CR_SHARED_MEMORY_CONNECT_FILE_MAP_ERROR 2040 -#define CR_SHARED_MEMORY_CONNECT_MAP_ERROR 2041 -#define CR_SHARED_MEMORY_FILE_MAP_ERROR 2042 -#define CR_SHARED_MEMORY_MAP_ERROR 2043 -#define CR_SHARED_MEMORY_EVENT_ERROR 2044 +#define CR_SHARED_MEMORY_CONNECT_MAP_ERROR 2041 +#define CR_SHARED_MEMORY_FILE_MAP_ERROR 2042 +#define CR_SHARED_MEMORY_MAP_ERROR 2043 +#define CR_SHARED_MEMORY_EVENT_ERROR 2044 #define CR_SHARED_MEMORY_CONNECT_ABANDONED_ERROR 2045 -#define CR_SHARED_MEMORY_CONNECT_SET_ERROR 2046 -#define CR_CONN_UNKNOW_PROTOCOL 2047 -#define CR_INVALID_CONN_HANDLE 2048 -#define CR_UNUSED_1 2049 -#define CR_FETCH_CANCELED 2050 -#define CR_NO_DATA 2051 -#define CR_NO_STMT_METADATA 2052 -#define CR_NO_RESULT_SET 2053 -#define CR_NOT_IMPLEMENTED 2054 -#define CR_SERVER_LOST_EXTENDED 2055 -#define CR_STMT_CLOSED 2056 -#define CR_NEW_STMT_METADATA 2057 -#define CR_ALREADY_CONNECTED 2058 -#define CR_AUTH_PLUGIN_CANNOT_LOAD 2059 -#define CR_DUPLICATE_CONNECTION_ATTR 2060 -#define CR_AUTH_PLUGIN_ERR 2061 -#define CR_INSECURE_API_ERR 2062 -#define CR_ERROR_LAST /*Copy last error nr:*/ 2062 +#define CR_SHARED_MEMORY_CONNECT_SET_ERROR 2046 +#define CR_CONN_UNKNOW_PROTOCOL 2047 +#define CR_INVALID_CONN_HANDLE 2048 +#define CR_UNUSED_1 2049 +#define CR_FETCH_CANCELED 2050 +#define CR_NO_DATA 2051 +#define CR_NO_STMT_METADATA 2052 +#define CR_NO_RESULT_SET 2053 +#define CR_NOT_IMPLEMENTED 2054 +#define CR_SERVER_LOST_EXTENDED 2055 +#define CR_STMT_CLOSED 2056 +#define CR_NEW_STMT_METADATA 2057 +#define CR_ALREADY_CONNECTED 2058 +#define CR_AUTH_PLUGIN_CANNOT_LOAD 2059 +#define CR_DUPLICATE_CONNECTION_ATTR 2060 +#define CR_AUTH_PLUGIN_ERR 2061 +#define CR_INSECURE_API_ERR 2062 +#define CR_FILE_NAME_TOO_LONG 2063 +#define CR_SSL_FIPS_MODE_ERR 2064 +#define CR_DEPRECATED_COMPRESSION_NOT_SUPPORTED 2065 +#define CR_COMPRESSION_WRONGLY_CONFIGURED 2066 +#define CR_KERBEROS_USER_NOT_FOUND 2067 +#define CR_LOAD_DATA_LOCAL_INFILE_REJECTED 2068 +#define CR_LOAD_DATA_LOCAL_INFILE_REALPATH_FAIL 2069 +#define CR_DNS_SRV_LOOKUP_FAILED 2070 +#define CR_MANDATORY_TRACKER_NOT_FOUND 2071 +#define CR_INVALID_FACTOR_NO 2072 +#define CR_CANT_GET_SESSION_DATA 2073 +#define CR_INVALID_CLIENT_CHARSET 2074 +#define CR_TLS_SERVER_NOT_FOUND 2075 +#define CR_ERROR_LAST /*Copy last error nr:*/ 2075 /* Add error numbers before CR_ERROR_LAST and change it accordingly. */ +/* Visual Studio requires '__inline' for C code */ +static inline const char *ER_CLIENT(int client_errno) { + if (client_errno >= CR_ERROR_FIRST && client_errno <= CR_ERROR_LAST) + return client_errors[client_errno - CR_ERROR_FIRST]; + return client_errors[CR_UNKNOWN_ERROR - CR_ERROR_FIRST]; +} + #endif /* ERRMSG_INCLUDED */ diff --git a/vendor/mysql/include/field_types.h b/vendor/mysql/include/field_types.h new file mode 100644 index 0000000000..73032ad06a --- /dev/null +++ b/vendor/mysql/include/field_types.h @@ -0,0 +1,98 @@ +/* Copyright (c) 2014, 2024, Oracle and/or its affiliates. + + This program is free software; you can redistribute it and/or modify + it under the terms of the GNU General Public License, version 2.0, + as published by the Free Software Foundation. + + This program is designed to work with certain software (including + but not limited to OpenSSL) that is licensed under separate terms, + as designated in a particular file or component or in included license + documentation. The authors of MySQL hereby grant you an additional + permission to link the program and your derivative works with the + separately licensed software that they have either included with + the program or referenced in the documentation. + + Without limiting anything contained in the foregoing, this file, + which is part of C Driver for MySQL (Connector/C), is also subject to the + Universal FOSS Exception, version 1.0, a copy of which can be found at + http://oss.oracle.com/licenses/universal-foss-exception. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License, version 2.0, for more details. + + You should have received a copy of the GNU General Public License + along with this program; if not, write to the Free Software + Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA */ + +/** + @file field_types.h + + @brief This file contains the field type. + + + @note This file can be imported both from C and C++ code, so the + definitions have to be constructed to support this. +*/ + +#ifndef FIELD_TYPES_INCLUDED +#define FIELD_TYPES_INCLUDED + +#ifdef __cplusplus +extern "C" { +#endif /* __cplusplus */ + +/* + * Constants exported from this package. + */ + +/** + Column types for MySQL + Note: Keep include/mysql/components/services/bits/stored_program_bits.h in + sync with this +*/ +enum enum_field_types { + MYSQL_TYPE_DECIMAL, + MYSQL_TYPE_TINY, + MYSQL_TYPE_SHORT, + MYSQL_TYPE_LONG, + MYSQL_TYPE_FLOAT, + MYSQL_TYPE_DOUBLE, + MYSQL_TYPE_NULL, + MYSQL_TYPE_TIMESTAMP, + MYSQL_TYPE_LONGLONG, + MYSQL_TYPE_INT24, + MYSQL_TYPE_DATE, + MYSQL_TYPE_TIME, + MYSQL_TYPE_DATETIME, + MYSQL_TYPE_YEAR, + MYSQL_TYPE_NEWDATE, /**< Internal to MySQL. Not used in protocol */ + MYSQL_TYPE_VARCHAR, + MYSQL_TYPE_BIT, + MYSQL_TYPE_TIMESTAMP2, + MYSQL_TYPE_DATETIME2, /**< Internal to MySQL. Not used in protocol */ + MYSQL_TYPE_TIME2, /**< Internal to MySQL. Not used in protocol */ + MYSQL_TYPE_TYPED_ARRAY, /**< Used for replication only */ + MYSQL_TYPE_INVALID = 243, + MYSQL_TYPE_BOOL = 244, /**< Currently just a placeholder */ + MYSQL_TYPE_JSON = 245, + MYSQL_TYPE_NEWDECIMAL = 246, + MYSQL_TYPE_ENUM = 247, + MYSQL_TYPE_SET = 248, + MYSQL_TYPE_TINY_BLOB = 249, + MYSQL_TYPE_MEDIUM_BLOB = 250, + MYSQL_TYPE_LONG_BLOB = 251, + MYSQL_TYPE_BLOB = 252, + MYSQL_TYPE_VAR_STRING = 253, + MYSQL_TYPE_STRING = 254, + MYSQL_TYPE_GEOMETRY = 255 +}; + +#ifdef __cplusplus +} // extern "C" +#else +typedef enum enum_field_types enum_field_types; +#endif /* __cplusplus */ + +#endif /* FIELD_TYPES_INCLUDED */ diff --git a/vendor/mysql/include/keycache.h b/vendor/mysql/include/keycache.h deleted file mode 100644 index 6119f2cbe9..0000000000 --- a/vendor/mysql/include/keycache.h +++ /dev/null @@ -1,156 +0,0 @@ -/* Copyright (c) 2003, 2015, Oracle and/or its affiliates. All rights reserved. - - This program is free software; you can redistribute it and/or modify - it under the terms of the GNU General Public License as published by - the Free Software Foundation; version 2 of the License. - - This program is distributed in the hope that it will be useful, - but WITHOUT ANY WARRANTY; without even the implied warranty of - MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - GNU General Public License for more details. - - You should have received a copy of the GNU General Public License - along with this program; if not, write to the Free Software - Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA */ - -/* Key cache variable structures */ - -#ifndef _keycache_h -#define _keycache_h - -#include "my_sys.h" /* flush_type */ - -C_MODE_START - -/* declare structures that is used by st_key_cache */ - -struct st_block_link; -typedef struct st_block_link BLOCK_LINK; -struct st_hash_link; -typedef struct st_hash_link HASH_LINK; - -/* Thread specific variables */ -typedef struct st_keycache_thread_var -{ - mysql_cond_t suspend; - struct st_keycache_thread_var *next,**prev; - void *opt_info; -} st_keycache_thread_var; - -/* info about requests in a waiting queue */ -typedef struct st_keycache_wqueue -{ - st_keycache_thread_var *last_thread; /* circular list of waiting threads */ -} KEYCACHE_WQUEUE; - -#define CHANGED_BLOCKS_HASH 128 /* must be power of 2 */ - -/* - The key cache structure - It also contains read-only statistics parameters. -*/ - -typedef struct st_key_cache -{ - my_bool key_cache_inited; - my_bool in_resize; /* true during resize operation */ - my_bool resize_in_flush; /* true during flush of resize operation */ - my_bool can_be_used; /* usage of cache for read/write is allowed */ - size_t key_cache_mem_size; /* specified size of the cache memory */ - uint key_cache_block_size; /* size of the page buffer of a cache block */ - ulonglong min_warm_blocks; /* min number of warm blocks; */ - ulonglong age_threshold; /* age threshold for hot blocks */ - ulonglong keycache_time; /* total number of block link operations */ - uint hash_entries; /* max number of entries in the hash table */ - int hash_links; /* max number of hash links */ - int hash_links_used; /* number of hash links currently used */ - int disk_blocks; /* max number of blocks in the cache */ - ulong blocks_used; /* maximum number of concurrently used blocks */ - ulong blocks_unused; /* number of currently unused blocks */ - ulong blocks_changed; /* number of currently dirty blocks */ - ulong warm_blocks; /* number of blocks in warm sub-chain */ - ulong cnt_for_resize_op; /* counter to block resize operation */ - long blocks_available; /* number of blocks available in the LRU chain */ - HASH_LINK **hash_root; /* arr. of entries into hash table buckets */ - HASH_LINK *hash_link_root; /* memory for hash table links */ - HASH_LINK *free_hash_list; /* list of free hash links */ - BLOCK_LINK *free_block_list; /* list of free blocks */ - BLOCK_LINK *block_root; /* memory for block links */ - uchar *block_mem; /* memory for block buffers */ - BLOCK_LINK *used_last; /* ptr to the last block of the LRU chain */ - BLOCK_LINK *used_ins; /* ptr to the insertion block in LRU chain */ - mysql_mutex_t cache_lock; /* to lock access to the cache structure */ - KEYCACHE_WQUEUE resize_queue; /* threads waiting during resize operation */ - /* - Waiting for a zero resize count. Using a queue for symmetry though - only one thread can wait here. - */ - KEYCACHE_WQUEUE waiting_for_resize_cnt; - KEYCACHE_WQUEUE waiting_for_hash_link; /* waiting for a free hash link */ - KEYCACHE_WQUEUE waiting_for_block; /* requests waiting for a free block */ - BLOCK_LINK *changed_blocks[CHANGED_BLOCKS_HASH]; /* hash for dirty file bl.*/ - BLOCK_LINK *file_blocks[CHANGED_BLOCKS_HASH]; /* hash for other file bl.*/ - - /* - The following variables are and variables used to hold parameters for - initializing the key cache. - */ - - ulonglong param_buff_size; /* size the memory allocated for the cache */ - ulonglong param_block_size; /* size of the blocks in the key cache */ - ulonglong param_division_limit; /* min. percentage of warm blocks */ - ulonglong param_age_threshold; /* determines when hot block is downgraded */ - - /* Statistics variables. These are reset in reset_key_cache_counters(). */ - ulong global_blocks_changed; /* number of currently dirty blocks */ - ulonglong global_cache_w_requests;/* number of write requests (write hits) */ - ulonglong global_cache_write; /* number of writes from cache to files */ - ulonglong global_cache_r_requests;/* number of read requests (read hits) */ - ulonglong global_cache_read; /* number of reads from files to cache */ - - int blocks; /* max number of blocks in the cache */ - my_bool in_init; /* Set to 1 in MySQL during init/resize */ -} KEY_CACHE; - -/* The default key cache */ -extern KEY_CACHE dflt_key_cache_var, *dflt_key_cache; - -extern int init_key_cache(KEY_CACHE *keycache, ulonglong key_cache_block_size, - size_t use_mem, ulonglong division_limit, - ulonglong age_threshold); -extern int resize_key_cache(KEY_CACHE *keycache, - st_keycache_thread_var *thread_var, - ulonglong key_cache_block_size, - size_t use_mem, ulonglong division_limit, - ulonglong age_threshold); -extern uchar *key_cache_read(KEY_CACHE *keycache, - st_keycache_thread_var *thread_var, - File file, my_off_t filepos, int level, - uchar *buff, uint length, - uint block_length,int return_buffer); -extern int key_cache_insert(KEY_CACHE *keycache, - st_keycache_thread_var *thread_var, - File file, my_off_t filepos, int level, - uchar *buff, uint length); -extern int key_cache_write(KEY_CACHE *keycache, - st_keycache_thread_var *thread_var, - File file, my_off_t filepos, int level, - uchar *buff, uint length, - uint block_length,int force_write); -extern int flush_key_blocks(KEY_CACHE *keycache, - st_keycache_thread_var *thread_var, - int file, enum flush_type type); -extern void end_key_cache(KEY_CACHE *keycache, my_bool cleanup); - -/* Functions to handle multiple key caches */ -extern my_bool multi_keycache_init(void); -extern void multi_keycache_free(void); -extern KEY_CACHE *multi_key_cache_search(uchar *key, uint length); -extern my_bool multi_key_cache_set(const uchar *key, uint length, - KEY_CACHE *key_cache); -extern void multi_key_cache_change(KEY_CACHE *old_data, - KEY_CACHE *new_data); -extern int reset_key_cache_counters(const char *name, - KEY_CACHE *key_cache); -C_MODE_END -#endif /* _keycache_h */ diff --git a/vendor/mysql/include/little_endian.h b/vendor/mysql/include/little_endian.h deleted file mode 100644 index fac4af084e..0000000000 --- a/vendor/mysql/include/little_endian.h +++ /dev/null @@ -1,93 +0,0 @@ -#ifndef LITTLE_ENDIAN_INCLUDED -#define LITTLE_ENDIAN_INCLUDED -/* Copyright (c) 2012, 2015, Oracle and/or its affiliates. All rights reserved. - - This program is free software; you can redistribute it and/or modify - it under the terms of the GNU General Public License as published by - the Free Software Foundation; version 2 of the License. - - This program is distributed in the hope that it will be useful, - but WITHOUT ANY WARRANTY; without even the implied warranty of - MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - GNU General Public License for more details. - - You should have received a copy of the GNU General Public License - along with this program; if not, write to the Free Software - Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA */ - -/* - Data in little-endian format. -*/ - -#include - -static inline void float4get (float *V, const uchar *M) -{ - memcpy(V, (M), sizeof(float)); -} - -static inline void float4store(uchar *V, float M) -{ - memcpy(V, (&M), sizeof(float)); -} - -static inline void float8get (double *V, const uchar *M) -{ - memcpy(V, M, sizeof(double)); -} - -static inline void float8store(uchar *V, double M) -{ - memcpy(V, &M, sizeof(double)); -} - -static inline void floatget (float *V, const uchar *M) { float4get(V, M); } -static inline void floatstore (uchar *V, float M) { float4store(V, M); } - -/* Bi-endian hardware.... */ -#if defined(__FLOAT_WORD_ORDER) && (__FLOAT_WORD_ORDER == __BIG_ENDIAN) -static inline void doublestore(uchar *T, double V) -{ *(((char*)T)+0)=(char) ((uchar *) &V)[4]; - *(((char*)T)+1)=(char) ((uchar *) &V)[5]; - *(((char*)T)+2)=(char) ((uchar *) &V)[6]; - *(((char*)T)+3)=(char) ((uchar *) &V)[7]; - *(((char*)T)+4)=(char) ((uchar *) &V)[0]; - *(((char*)T)+5)=(char) ((uchar *) &V)[1]; - *(((char*)T)+6)=(char) ((uchar *) &V)[2]; - *(((char*)T)+7)=(char) ((uchar *) &V)[3]; } -static inline void doubleget(double *V, const uchar *M) -{ double def_temp; - ((uchar*) &def_temp)[0]=(M)[4]; - ((uchar*) &def_temp)[1]=(M)[5]; - ((uchar*) &def_temp)[2]=(M)[6]; - ((uchar*) &def_temp)[3]=(M)[7]; - ((uchar*) &def_temp)[4]=(M)[0]; - ((uchar*) &def_temp)[5]=(M)[1]; - ((uchar*) &def_temp)[6]=(M)[2]; - ((uchar*) &def_temp)[7]=(M)[3]; - (*V) = def_temp; } - -#else /* Bi-endian hardware.... */ - -static inline void doublestore(uchar *T, double V) { memcpy(T, &V, sizeof(double)); } -static inline void doubleget (double *V, const uchar *M) { memcpy(V, M, sizeof(double)); } - -#endif /* Bi-endian hardware.... */ - -static inline void ushortget(uint16 *V, const uchar *pM) { *V= uint2korr(pM); } -static inline void shortget (int16 *V, const uchar *pM) { *V= sint2korr(pM); } -static inline void longget (int32 *V, const uchar *pM) { *V= sint4korr(pM); } -static inline void ulongget (uint32 *V, const uchar *pM) { *V= uint4korr(pM); } -static inline void shortstore(uchar *T, int16 V) { int2store(T, V); } -static inline void longstore (uchar *T, int32 V) { int4store(T, V); } - -static inline void longlongget(longlong *V, const uchar *M) -{ - memcpy(V, (M), sizeof(ulonglong)); -} -static inline void longlongstore(uchar *T, longlong V) -{ - memcpy((T), &V, sizeof(ulonglong)); -} - -#endif /* LITTLE_ENDIAN_INCLUDED */ diff --git a/vendor/mysql/include/m_ctype.h b/vendor/mysql/include/m_ctype.h deleted file mode 100644 index dd6ee754e3..0000000000 --- a/vendor/mysql/include/m_ctype.h +++ /dev/null @@ -1,806 +0,0 @@ -/* Copyright (c) 2000, 2016, Oracle and/or its affiliates. All rights reserved. - - This program is free software; you can redistribute it and/or modify - it under the terms of the GNU General Public License as published by - the Free Software Foundation; version 2 of the License. - - This program is distributed in the hope that it will be useful, - but WITHOUT ANY WARRANTY; without even the implied warranty of - MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - GNU General Public License for more details. - - You should have received a copy of the GNU General Public License - along with this program; if not, write to the Free Software - Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA */ - -/* - A better inplementation of the UNIX ctype(3) library. -*/ - -#ifndef _m_ctype_h -#define _m_ctype_h - -#include "my_global.h" /* uint16, uchar */ - -#ifdef __cplusplus -extern "C" { -#endif - -#define MY_CS_NAME_SIZE 32 -#define MY_CS_CTYPE_TABLE_SIZE 257 -#define MY_CS_TO_LOWER_TABLE_SIZE 256 -#define MY_CS_TO_UPPER_TABLE_SIZE 256 -#define MY_CS_SORT_ORDER_TABLE_SIZE 256 -#define MY_CS_TO_UNI_TABLE_SIZE 256 - -#define CHARSET_DIR "charsets/" - -#define my_wc_t ulong - -#define MY_CS_REPLACEMENT_CHARACTER 0xFFFD - -/* - On i386 we store Unicode->CS conversion tables for - some character sets using Big-endian order, - to copy two bytes at onces. - This gives some performance improvement. -*/ -#ifdef __i386__ -#define MB2(x) (((x) >> 8) + (((x) & 0xFF) << 8)) -#define MY_PUT_MB2(s, code) { *((uint16*)(s))= (code); } -#else -#define MB2(x) (x) -#define MY_PUT_MB2(s, code) { (s)[0]= code >> 8; (s)[1]= code & 0xFF; } -#endif - - - -typedef struct unicase_info_char_st -{ - uint32 toupper; - uint32 tolower; - uint32 sort; -} MY_UNICASE_CHARACTER; - - -typedef struct unicase_info_st -{ - my_wc_t maxchar; - const MY_UNICASE_CHARACTER **page; -} MY_UNICASE_INFO; - - -extern MY_UNICASE_INFO my_unicase_default; -extern MY_UNICASE_INFO my_unicase_turkish; -extern MY_UNICASE_INFO my_unicase_mysql500; -extern MY_UNICASE_INFO my_unicase_unicode520; - -#define MY_UCA_MAX_CONTRACTION 6 -#define MY_UCA_MAX_WEIGHT_SIZE 8 -#define MY_UCA_WEIGHT_LEVELS 1 - -typedef struct my_contraction_t -{ - my_wc_t ch[MY_UCA_MAX_CONTRACTION]; /* Character sequence */ - uint16 weight[MY_UCA_MAX_WEIGHT_SIZE];/* Its weight string, 0-terminated */ - my_bool with_context; -} MY_CONTRACTION; - - - -typedef struct my_contraction_list_t -{ - size_t nitems; /* Number of items in the list */ - MY_CONTRACTION *item; /* List of contractions */ - char *flags; /* Character flags, e.g. "is contraction head") */ -} MY_CONTRACTIONS; - - -my_bool my_uca_can_be_contraction_head(const MY_CONTRACTIONS *c, my_wc_t wc); -my_bool my_uca_can_be_contraction_tail(const MY_CONTRACTIONS *c, my_wc_t wc); -uint16 *my_uca_contraction2_weight(const MY_CONTRACTIONS *c, - my_wc_t wc1, my_wc_t wc2); - - -/* Collation weights on a single level (e.g. primary, secondary, tertiarty) */ -typedef struct my_uca_level_info_st -{ - my_wc_t maxchar; - uchar *lengths; - uint16 **weights; - MY_CONTRACTIONS contractions; -} MY_UCA_WEIGHT_LEVEL; - - -typedef struct uca_info_st -{ - MY_UCA_WEIGHT_LEVEL level[MY_UCA_WEIGHT_LEVELS]; - - /* Logical positions */ - my_wc_t first_non_ignorable; - my_wc_t last_non_ignorable; - my_wc_t first_primary_ignorable; - my_wc_t last_primary_ignorable; - my_wc_t first_secondary_ignorable; - my_wc_t last_secondary_ignorable; - my_wc_t first_tertiary_ignorable; - my_wc_t last_tertiary_ignorable; - my_wc_t first_trailing; - my_wc_t last_trailing; - my_wc_t first_variable; - my_wc_t last_variable; - -} MY_UCA_INFO; - - - -extern MY_UCA_INFO my_uca_v400; - - -typedef struct uni_ctype_st -{ - uchar pctype; - uchar *ctype; -} MY_UNI_CTYPE; - -extern MY_UNI_CTYPE my_uni_ctype[256]; - -/* wm_wc and wc_mb return codes */ -#define MY_CS_ILSEQ 0 /* Wrong by sequence: wb_wc */ -#define MY_CS_ILUNI 0 /* Cannot encode Unicode to charset: wc_mb */ -#define MY_CS_TOOSMALL -101 /* Need at least one byte: wc_mb and mb_wc */ -#define MY_CS_TOOSMALL2 -102 /* Need at least two bytes: wc_mb and mb_wc */ -#define MY_CS_TOOSMALL3 -103 /* Need at least three bytes: wc_mb and mb_wc */ -/* These following three are currently not really used */ -#define MY_CS_TOOSMALL4 -104 /* Need at least 4 bytes: wc_mb and mb_wc */ -#define MY_CS_TOOSMALL5 -105 /* Need at least 5 bytes: wc_mb and mb_wc */ -#define MY_CS_TOOSMALL6 -106 /* Need at least 6 bytes: wc_mb and mb_wc */ -/* A helper macros for "need at least n bytes" */ -#define MY_CS_TOOSMALLN(n) (-100-(n)) - -#define MY_SEQ_INTTAIL 1 -#define MY_SEQ_SPACES 2 - - /* My charsets_list flags */ -#define MY_CS_COMPILED 1 /* compiled-in sets */ -#define MY_CS_CONFIG 2 /* sets that have a *.conf file */ -#define MY_CS_INDEX 4 /* sets listed in the Index file */ -#define MY_CS_LOADED 8 /* sets that are currently loaded */ -#define MY_CS_BINSORT 16 /* if binary sort order */ -#define MY_CS_PRIMARY 32 /* if primary collation */ -#define MY_CS_STRNXFRM 64 /* if strnxfrm is used for sort */ -#define MY_CS_UNICODE 128 /* is a charset is BMP Unicode */ -#define MY_CS_READY 256 /* if a charset is initialized */ -#define MY_CS_AVAILABLE 512 /* If either compiled-in or loaded*/ -#define MY_CS_CSSORT 1024 /* if case sensitive sort order */ -#define MY_CS_HIDDEN 2048 /* don't display in SHOW */ -#define MY_CS_PUREASCII 4096 /* if a charset is pure ascii */ -#define MY_CS_NONASCII 8192 /* if not ASCII-compatible */ -#define MY_CS_UNICODE_SUPPLEMENT 16384 /* Non-BMP Unicode characters */ -#define MY_CS_LOWER_SORT 32768 /* If use lower case as weight */ -#define MY_CHARSET_UNDEFINED 0 - -/* Character repertoire flags */ -#define MY_REPERTOIRE_ASCII 1 /* Pure ASCII U+0000..U+007F */ -#define MY_REPERTOIRE_EXTENDED 2 /* Extended characters: U+0080..U+FFFF */ -#define MY_REPERTOIRE_UNICODE30 3 /* ASCII | EXTENDED: U+0000..U+FFFF */ - -/* Flags for strxfrm */ -#define MY_STRXFRM_LEVEL1 0x00000001 /* for primary weights */ -#define MY_STRXFRM_LEVEL2 0x00000002 /* for secondary weights */ -#define MY_STRXFRM_LEVEL3 0x00000004 /* for tertiary weights */ -#define MY_STRXFRM_LEVEL4 0x00000008 /* fourth level weights */ -#define MY_STRXFRM_LEVEL5 0x00000010 /* fifth level weights */ -#define MY_STRXFRM_LEVEL6 0x00000020 /* sixth level weights */ -#define MY_STRXFRM_LEVEL_ALL 0x0000003F /* Bit OR for the above six */ -#define MY_STRXFRM_NLEVELS 6 /* Number of possible levels*/ - -#define MY_STRXFRM_PAD_WITH_SPACE 0x00000040 /* if pad result with spaces */ -#define MY_STRXFRM_PAD_TO_MAXLEN 0x00000080 /* if pad tail(for filesort) */ - -#define MY_STRXFRM_DESC_LEVEL1 0x00000100 /* if desc order for level1 */ -#define MY_STRXFRM_DESC_LEVEL2 0x00000200 /* if desc order for level2 */ -#define MY_STRXFRM_DESC_LEVEL3 0x00000300 /* if desc order for level3 */ -#define MY_STRXFRM_DESC_LEVEL4 0x00000800 /* if desc order for level4 */ -#define MY_STRXFRM_DESC_LEVEL5 0x00001000 /* if desc order for level5 */ -#define MY_STRXFRM_DESC_LEVEL6 0x00002000 /* if desc order for level6 */ -#define MY_STRXFRM_DESC_SHIFT 8 - -#define MY_STRXFRM_UNUSED_00004000 0x00004000 /* for future extensions */ -#define MY_STRXFRM_UNUSED_00008000 0x00008000 /* for future extensions */ - -#define MY_STRXFRM_REVERSE_LEVEL1 0x00010000 /* if reverse order for level1 */ -#define MY_STRXFRM_REVERSE_LEVEL2 0x00020000 /* if reverse order for level2 */ -#define MY_STRXFRM_REVERSE_LEVEL3 0x00040000 /* if reverse order for level3 */ -#define MY_STRXFRM_REVERSE_LEVEL4 0x00080000 /* if reverse order for level4 */ -#define MY_STRXFRM_REVERSE_LEVEL5 0x00100000 /* if reverse order for level5 */ -#define MY_STRXFRM_REVERSE_LEVEL6 0x00200000 /* if reverse order for level6 */ -#define MY_STRXFRM_REVERSE_SHIFT 16 - - -typedef struct my_uni_idx_st -{ - uint16 from; - uint16 to; - const uchar *tab; -} MY_UNI_IDX; - -typedef struct -{ - uint beg; - uint end; - uint mb_len; -} my_match_t; - -struct charset_info_st; - -typedef struct my_charset_loader_st -{ - char error[128]; - void *(*once_alloc)(size_t); - void *(*mem_malloc)(size_t); - void *(*mem_realloc)(void *, size_t); - void (*mem_free)(void *); - void (*reporter)(enum loglevel, const char *format, ...); - int (*add_collation)(struct charset_info_st *cs); -} MY_CHARSET_LOADER; - - -extern int (*my_string_stack_guard)(int); - -/* See strings/CHARSET_INFO.txt for information about this structure */ -typedef struct my_collation_handler_st -{ - my_bool (*init)(struct charset_info_st *, MY_CHARSET_LOADER *); - /* Collation routines */ - int (*strnncoll)(const struct charset_info_st *, - const uchar *, size_t, const uchar *, size_t, my_bool); - int (*strnncollsp)(const struct charset_info_st *, - const uchar *, size_t, const uchar *, size_t, - my_bool diff_if_only_endspace_difference); - size_t (*strnxfrm)(const struct charset_info_st *, - uchar *dst, size_t dstlen, uint nweights, - const uchar *src, size_t srclen, uint flags); - size_t (*strnxfrmlen)(const struct charset_info_st *, size_t); - my_bool (*like_range)(const struct charset_info_st *, - const char *s, size_t s_length, - pchar w_prefix, pchar w_one, pchar w_many, - size_t res_length, - char *min_str, char *max_str, - size_t *min_len, size_t *max_len); - int (*wildcmp)(const struct charset_info_st *, - const char *str,const char *str_end, - const char *wildstr,const char *wildend, - int escape,int w_one, int w_many); - - int (*strcasecmp)(const struct charset_info_st *, const char *, - const char *); - - uint (*instr)(const struct charset_info_st *, - const char *b, size_t b_length, - const char *s, size_t s_length, - my_match_t *match, uint nmatch); - - /* Hash calculation */ - void (*hash_sort)(const struct charset_info_st *cs, const uchar *key, - size_t len, ulong *nr1, ulong *nr2); - my_bool (*propagate)(const struct charset_info_st *cs, const uchar *str, - size_t len); -} MY_COLLATION_HANDLER; - -extern MY_COLLATION_HANDLER my_collation_mb_bin_handler; -extern MY_COLLATION_HANDLER my_collation_8bit_bin_handler; -extern MY_COLLATION_HANDLER my_collation_8bit_simple_ci_handler; -extern MY_COLLATION_HANDLER my_collation_ucs2_uca_handler; - -/* Some typedef to make it easy for C++ to make function pointers */ -typedef int (*my_charset_conv_mb_wc)(const struct charset_info_st *, - my_wc_t *, const uchar *, const uchar *); -typedef int (*my_charset_conv_wc_mb)(const struct charset_info_st *, my_wc_t, - uchar *, uchar *); -typedef size_t (*my_charset_conv_case)(const struct charset_info_st *, - char *, size_t, char *, size_t); - - -/* See strings/CHARSET_INFO.txt about information on this structure */ -typedef struct my_charset_handler_st -{ - my_bool (*init)(struct charset_info_st *, MY_CHARSET_LOADER *loader); - /* Multibyte routines */ - uint (*ismbchar)(const struct charset_info_st *, const char *, - const char *); - uint (*mbcharlen)(const struct charset_info_st *, uint c); - size_t (*numchars)(const struct charset_info_st *, const char *b, - const char *e); - size_t (*charpos)(const struct charset_info_st *, const char *b, - const char *e, size_t pos); - size_t (*well_formed_len)(const struct charset_info_st *, - const char *b,const char *e, - size_t nchars, int *error); - size_t (*lengthsp)(const struct charset_info_st *, const char *ptr, - size_t length); - size_t (*numcells)(const struct charset_info_st *, const char *b, - const char *e); - - /* Unicode conversion */ - my_charset_conv_mb_wc mb_wc; - my_charset_conv_wc_mb wc_mb; - - /* CTYPE scanner */ - int (*ctype)(const struct charset_info_st *cs, int *ctype, - const uchar *s, const uchar *e); - - /* Functions for case and sort conversion */ - size_t (*caseup_str)(const struct charset_info_st *, char *); - size_t (*casedn_str)(const struct charset_info_st *, char *); - - my_charset_conv_case caseup; - my_charset_conv_case casedn; - - /* Charset dependant snprintf() */ - size_t (*snprintf)(const struct charset_info_st *, char *to, size_t n, - const char *fmt, - ...) MY_ATTRIBUTE((format(printf, 4, 5))); - size_t (*long10_to_str)(const struct charset_info_st *, char *to, size_t n, - int radix, long int val); - size_t (*longlong10_to_str)(const struct charset_info_st *, char *to, - size_t n, int radix, longlong val); - - void (*fill)(const struct charset_info_st *, char *to, size_t len, - int fill); - - /* String-to-number conversion routines */ - long (*strntol)(const struct charset_info_st *, const char *s, - size_t l, int base, char **e, int *err); - ulong (*strntoul)(const struct charset_info_st *, const char *s, - size_t l, int base, char **e, int *err); - longlong (*strntoll)(const struct charset_info_st *, const char *s, - size_t l, int base, char **e, int *err); - ulonglong (*strntoull)(const struct charset_info_st *, const char *s, - size_t l, int base, char **e, int *err); - double (*strntod)(const struct charset_info_st *, char *s, - size_t l, char **e, int *err); - longlong (*strtoll10)(const struct charset_info_st *cs, - const char *nptr, char **endptr, int *error); - ulonglong (*strntoull10rnd)(const struct charset_info_st *cs, - const char *str, size_t length, - int unsigned_fl, - char **endptr, int *error); - size_t (*scan)(const struct charset_info_st *, const char *b, - const char *e, int sq); -} MY_CHARSET_HANDLER; - -extern MY_CHARSET_HANDLER my_charset_8bit_handler; -extern MY_CHARSET_HANDLER my_charset_ascii_handler; -extern MY_CHARSET_HANDLER my_charset_ucs2_handler; - - -/* - We define this CHARSET_INFO_DEFINED here to prevent a repeat of the - typedef in hash.c, which will cause a compiler error. -*/ -#define CHARSET_INFO_DEFINED - -/* See strings/CHARSET_INFO.txt about information on this structure */ -typedef struct charset_info_st -{ - uint number; - uint primary_number; - uint binary_number; - uint state; - const char *csname; - const char *name; - const char *comment; - const char *tailoring; - const uchar *ctype; - const uchar *to_lower; - const uchar *to_upper; - const uchar *sort_order; - MY_UCA_INFO *uca; /* This can be changed in apply_one_rule() */ - const uint16 *tab_to_uni; - const MY_UNI_IDX *tab_from_uni; - const MY_UNICASE_INFO *caseinfo; - const struct lex_state_maps_st *state_maps; /* parser internal data */ - const uchar *ident_map; /* parser internal data */ - uint strxfrm_multiply; - uchar caseup_multiply; - uchar casedn_multiply; - uint mbminlen; - uint mbmaxlen; - uint mbmaxlenlen; - my_wc_t min_sort_char; - my_wc_t max_sort_char; /* For LIKE optimization */ - uchar pad_char; - my_bool escape_with_backslash_is_dangerous; - uchar levels_for_compare; - uchar levels_for_order; - - MY_CHARSET_HANDLER *cset; - MY_COLLATION_HANDLER *coll; - -} CHARSET_INFO; -#define ILLEGAL_CHARSET_INFO_NUMBER (~0U) - - -extern MYSQL_PLUGIN_IMPORT CHARSET_INFO my_charset_bin; -extern MYSQL_PLUGIN_IMPORT CHARSET_INFO my_charset_latin1; -extern MYSQL_PLUGIN_IMPORT CHARSET_INFO my_charset_filename; - -extern CHARSET_INFO my_charset_big5_chinese_ci; -extern CHARSET_INFO my_charset_big5_bin; -extern CHARSET_INFO my_charset_cp932_japanese_ci; -extern CHARSET_INFO my_charset_cp932_bin; -extern CHARSET_INFO my_charset_cp1250_czech_ci; -extern CHARSET_INFO my_charset_eucjpms_japanese_ci; -extern CHARSET_INFO my_charset_eucjpms_bin; -extern CHARSET_INFO my_charset_euckr_korean_ci; -extern CHARSET_INFO my_charset_euckr_bin; -extern CHARSET_INFO my_charset_gb2312_chinese_ci; -extern CHARSET_INFO my_charset_gb2312_bin; -extern CHARSET_INFO my_charset_gbk_chinese_ci; -extern CHARSET_INFO my_charset_gbk_bin; -extern CHARSET_INFO my_charset_gb18030_chinese_ci; -extern CHARSET_INFO my_charset_gb18030_bin; -extern CHARSET_INFO my_charset_latin1_german2_ci; -extern CHARSET_INFO my_charset_latin1_bin; -extern CHARSET_INFO my_charset_latin2_czech_ci; -extern CHARSET_INFO my_charset_sjis_japanese_ci; -extern CHARSET_INFO my_charset_sjis_bin; -extern CHARSET_INFO my_charset_tis620_thai_ci; -extern CHARSET_INFO my_charset_tis620_bin; -extern CHARSET_INFO my_charset_ucs2_general_ci; -extern CHARSET_INFO my_charset_ucs2_bin; -extern CHARSET_INFO my_charset_ucs2_unicode_ci; -extern CHARSET_INFO my_charset_ucs2_general_mysql500_ci; -extern CHARSET_INFO my_charset_ujis_japanese_ci; -extern CHARSET_INFO my_charset_ujis_bin; -extern CHARSET_INFO my_charset_utf16_bin; -extern CHARSET_INFO my_charset_utf16_general_ci; -extern CHARSET_INFO my_charset_utf16_unicode_ci; -extern CHARSET_INFO my_charset_utf16le_bin; -extern CHARSET_INFO my_charset_utf16le_general_ci; -extern CHARSET_INFO my_charset_utf32_bin; -extern CHARSET_INFO my_charset_utf32_general_ci; -extern CHARSET_INFO my_charset_utf32_unicode_ci; - -extern MYSQL_PLUGIN_IMPORT CHARSET_INFO my_charset_utf8_general_ci; -extern CHARSET_INFO my_charset_utf8_tolower_ci; -extern CHARSET_INFO my_charset_utf8_unicode_ci; -extern CHARSET_INFO my_charset_utf8_bin; -extern CHARSET_INFO my_charset_utf8_general_mysql500_ci; -extern CHARSET_INFO my_charset_utf8mb4_bin; -extern MYSQL_PLUGIN_IMPORT CHARSET_INFO my_charset_utf8mb4_general_ci; -extern CHARSET_INFO my_charset_utf8mb4_unicode_ci; -#define MY_UTF8MB3 "utf8" -#define MY_UTF8MB4 "utf8mb4" - - -/* declarations for simple charsets */ -extern size_t my_strnxfrm_simple(const CHARSET_INFO *, - uchar *dst, size_t dstlen, uint nweights, - const uchar *src, size_t srclen, uint flags); -size_t my_strnxfrmlen_simple(const CHARSET_INFO *, size_t); -extern int my_strnncoll_simple(const CHARSET_INFO *, const uchar *, size_t, - const uchar *, size_t, my_bool); - -extern int my_strnncollsp_simple(const CHARSET_INFO *, const uchar *, size_t, - const uchar *, size_t, - my_bool diff_if_only_endspace_difference); - -extern void my_hash_sort_simple(const CHARSET_INFO *cs, - const uchar *key, size_t len, - ulong *nr1, ulong *nr2); - -extern size_t my_lengthsp_8bit(const CHARSET_INFO *cs, const char *ptr, - size_t length); - -extern uint my_instr_simple(const struct charset_info_st *, - const char *b, size_t b_length, - const char *s, size_t s_length, - my_match_t *match, uint nmatch); - - -/* Functions for 8bit */ -extern size_t my_caseup_str_8bit(const CHARSET_INFO *, char *); -extern size_t my_casedn_str_8bit(const CHARSET_INFO *, char *); -extern size_t my_caseup_8bit(const CHARSET_INFO *, char *src, size_t srclen, - char *dst, size_t dstlen); -extern size_t my_casedn_8bit(const CHARSET_INFO *, char *src, size_t srclen, - char *dst, size_t dstlen); - -extern int my_strcasecmp_8bit(const CHARSET_INFO * cs, const char *, - const char *); - -int my_mb_wc_8bit(const CHARSET_INFO *cs,my_wc_t *wc, const uchar *s, - const uchar *e); -int my_wc_mb_8bit(const CHARSET_INFO *cs,my_wc_t wc, uchar *s, uchar *e); - -int my_mb_ctype_8bit(const CHARSET_INFO *,int *, const uchar *,const uchar *); -int my_mb_ctype_mb(const CHARSET_INFO *,int *, const uchar *,const uchar *); - -size_t my_scan_8bit(const CHARSET_INFO *cs, const char *b, const char *e, - int sq); - -size_t my_snprintf_8bit(const struct charset_info_st *, char *to, size_t n, - const char *fmt, ...) - MY_ATTRIBUTE((format(printf, 4, 5))); - -long my_strntol_8bit(const CHARSET_INFO *, const char *s, size_t l, - int base, char **e, int *err); -ulong my_strntoul_8bit(const CHARSET_INFO *, const char *s, size_t l, - int base, char **e, int *err); -longlong my_strntoll_8bit(const CHARSET_INFO *, const char *s, size_t l, - int base, char **e, int *err); -ulonglong my_strntoull_8bit(const CHARSET_INFO *, const char *s, size_t l, - int base, char **e, int *err); -double my_strntod_8bit(const CHARSET_INFO *, char *s, size_t l, char **e, - int *err); -size_t my_long10_to_str_8bit(const CHARSET_INFO *, char *to, size_t l, - int radix, long int val); -size_t my_longlong10_to_str_8bit(const CHARSET_INFO *, char *to, size_t l, - int radix, longlong val); - -longlong my_strtoll10_8bit(const CHARSET_INFO *cs, - const char *nptr, char **endptr, int *error); -longlong my_strtoll10_ucs2(const CHARSET_INFO *cs, - const char *nptr, char **endptr, int *error); - -ulonglong my_strntoull10rnd_8bit(const CHARSET_INFO *cs, - const char *str, size_t length, int - unsigned_fl, char **endptr, int *error); -ulonglong my_strntoull10rnd_ucs2(const CHARSET_INFO *cs, - const char *str, size_t length, - int unsigned_fl, char **endptr, int *error); - -void my_fill_8bit(const CHARSET_INFO *cs, char* to, size_t l, int fill); - -/* For 8-bit character set */ -my_bool my_like_range_simple(const CHARSET_INFO *cs, - const char *ptr, size_t ptr_length, - pbool escape, pbool w_one, pbool w_many, - size_t res_length, - char *min_str, char *max_str, - size_t *min_length, size_t *max_length); - -/* For ASCII-based multi-byte character sets with mbminlen=1 */ -my_bool my_like_range_mb(const CHARSET_INFO *cs, - const char *ptr, size_t ptr_length, - pbool escape, pbool w_one, pbool w_many, - size_t res_length, - char *min_str, char *max_str, - size_t *min_length, size_t *max_length); - -/* For other character sets, with arbitrary mbminlen and mbmaxlen numbers */ -my_bool my_like_range_generic(const CHARSET_INFO *cs, - const char *ptr, size_t ptr_length, - pbool escape, pbool w_one, pbool w_many, - size_t res_length, - char *min_str, char *max_str, - size_t *min_length, size_t *max_length); - -int my_wildcmp_8bit(const CHARSET_INFO *, - const char *str,const char *str_end, - const char *wildstr,const char *wildend, - int escape, int w_one, int w_many); - -int my_wildcmp_bin(const CHARSET_INFO *, - const char *str,const char *str_end, - const char *wildstr,const char *wildend, - int escape, int w_one, int w_many); - -size_t my_numchars_8bit(const CHARSET_INFO *, const char *b, const char *e); -size_t my_numcells_8bit(const CHARSET_INFO *, const char *b, const char *e); -size_t my_charpos_8bit(const CHARSET_INFO *, const char *b, const char *e, - size_t pos); -size_t my_well_formed_len_8bit(const CHARSET_INFO *, const char *b, - const char *e, size_t pos, int *error); -uint my_mbcharlen_8bit(const CHARSET_INFO *, uint c); - - -/* Functions for multibyte charsets */ -extern size_t my_caseup_str_mb(const CHARSET_INFO *, char *); -extern size_t my_casedn_str_mb(const CHARSET_INFO *, char *); -extern size_t my_caseup_mb(const CHARSET_INFO *, char *src, size_t srclen, - char *dst, size_t dstlen); -extern size_t my_casedn_mb(const CHARSET_INFO *, char *src, size_t srclen, - char *dst, size_t dstlen); -extern size_t my_caseup_mb_varlen(const CHARSET_INFO *, char *src, - size_t srclen, char *dst, size_t dstlen); -extern size_t my_casedn_mb_varlen(const CHARSET_INFO *, char *src, - size_t srclen, char *dst, size_t dstlen); -extern size_t my_caseup_ujis(const CHARSET_INFO *, char *src, size_t srclen, - char *dst, size_t dstlen); -extern size_t my_casedn_ujis(const CHARSET_INFO *, char *src, size_t srclen, - char *dst, size_t dstlen); -extern int my_strcasecmp_mb(const CHARSET_INFO * cs,const char *, - const char *); - -int my_wildcmp_mb(const CHARSET_INFO *, - const char *str,const char *str_end, - const char *wildstr,const char *wildend, - int escape, int w_one, int w_many); -size_t my_numchars_mb(const CHARSET_INFO *, const char *b, const char *e); -size_t my_numcells_mb(const CHARSET_INFO *, const char *b, const char *e); -size_t my_charpos_mb(const CHARSET_INFO *, const char *b, const char *e, - size_t pos); -size_t my_well_formed_len_mb(const CHARSET_INFO *, const char *b, - const char *e, size_t pos, int *error); -uint my_instr_mb(const struct charset_info_st *, - const char *b, size_t b_length, - const char *s, size_t s_length, - my_match_t *match, uint nmatch); - -int my_strnncoll_mb_bin(const CHARSET_INFO * cs, - const uchar *s, size_t slen, - const uchar *t, size_t tlen, - my_bool t_is_prefix); - -int my_strnncollsp_mb_bin(const CHARSET_INFO *cs, - const uchar *a, size_t a_length, - const uchar *b, size_t b_length, - my_bool diff_if_only_endspace_difference); - -int my_wildcmp_mb_bin(const CHARSET_INFO *cs, - const char *str,const char *str_end, - const char *wildstr,const char *wildend, - int escape, int w_one, int w_many); - -int my_strcasecmp_mb_bin(const CHARSET_INFO * cs MY_ATTRIBUTE((unused)), - const char *s, const char *t); - -void my_hash_sort_mb_bin(const CHARSET_INFO *cs MY_ATTRIBUTE((unused)), - const uchar *key, size_t len,ulong *nr1, ulong *nr2); - -size_t my_strnxfrm_mb(const CHARSET_INFO *, - uchar *dst, size_t dstlen, uint nweights, - const uchar *src, size_t srclen, uint flags); - -size_t my_strnxfrm_unicode(const CHARSET_INFO *, - uchar *dst, size_t dstlen, uint nweights, - const uchar *src, size_t srclen, uint flags); - -size_t my_strnxfrm_unicode_full_bin(const CHARSET_INFO *, - uchar *dst, size_t dstlen, uint nweights, - const uchar *src, size_t srclen, uint flags); -size_t my_strnxfrmlen_unicode_full_bin(const CHARSET_INFO *, size_t); - -int my_wildcmp_unicode(const CHARSET_INFO *cs, - const char *str, const char *str_end, - const char *wildstr, const char *wildend, - int escape, int w_one, int w_many, - const MY_UNICASE_INFO *weights); - -extern my_bool my_parse_charset_xml(MY_CHARSET_LOADER *loader, - const char *buf, size_t buflen); -extern char *my_strchr(const CHARSET_INFO *cs, const char *str, - const char *end, pchar c); -extern size_t my_strcspn(const CHARSET_INFO *cs, const char *str, - const char *end, const char *reject, - size_t reject_length); - -my_bool my_propagate_simple(const CHARSET_INFO *cs, const uchar *str, - size_t len); -my_bool my_propagate_complex(const CHARSET_INFO *cs, const uchar *str, - size_t len); - - -uint my_string_repertoire(const CHARSET_INFO *cs, const char *str, size_t len); -my_bool my_charset_is_ascii_based(const CHARSET_INFO *cs); -my_bool my_charset_is_8bit_pure_ascii(const CHARSET_INFO *cs); -uint my_charset_repertoire(const CHARSET_INFO *cs); - - -uint my_strxfrm_flag_normalize(uint flags, uint nlevels); -void my_strxfrm_desc_and_reverse(uchar *str, uchar *strend, - uint flags, uint level); -size_t my_strxfrm_pad_desc_and_reverse(const CHARSET_INFO *cs, - uchar *str, uchar *frmend, uchar *strend, - uint nweights, uint flags, uint level); - -my_bool my_charset_is_ascii_compatible(const CHARSET_INFO *cs); - -const MY_CONTRACTIONS *my_charset_get_contractions(const CHARSET_INFO *cs, - int level); - -extern size_t my_vsnprintf_ex(const CHARSET_INFO *cs, char *to, size_t n, - const char* fmt, va_list ap); - -size_t my_convert(char *to, size_t to_length, const CHARSET_INFO *to_cs, - const char *from, size_t from_length, - const CHARSET_INFO *from_cs, uint *errors); - -uint my_mbcharlen_ptr(const CHARSET_INFO *cs, const char *s, const char *e); - -#define _MY_U 01 /* Upper case */ -#define _MY_L 02 /* Lower case */ -#define _MY_NMR 04 /* Numeral (digit) */ -#define _MY_SPC 010 /* Spacing character */ -#define _MY_PNT 020 /* Punctuation */ -#define _MY_CTR 040 /* Control character */ -#define _MY_B 0100 /* Blank */ -#define _MY_X 0200 /* heXadecimal digit */ - - -#define my_isascii(c) (!((c) & ~0177)) -#define my_toascii(c) ((c) & 0177) -#define my_tocntrl(c) ((c) & 31) -#define my_toprint(c) ((c) | 64) -#define my_toupper(s,c) (char) ((s)->to_upper[(uchar) (c)]) -#define my_tolower(s,c) (char) ((s)->to_lower[(uchar) (c)]) -#define my_isalpha(s, c) (((s)->ctype+1)[(uchar) (c)] & (_MY_U | _MY_L)) -#define my_isupper(s, c) (((s)->ctype+1)[(uchar) (c)] & _MY_U) -#define my_islower(s, c) (((s)->ctype+1)[(uchar) (c)] & _MY_L) -#define my_isdigit(s, c) (((s)->ctype+1)[(uchar) (c)] & _MY_NMR) -#define my_isxdigit(s, c) (((s)->ctype+1)[(uchar) (c)] & _MY_X) -#define my_isalnum(s, c) (((s)->ctype+1)[(uchar) (c)] & (_MY_U | _MY_L | _MY_NMR)) -#define my_isspace(s, c) (((s)->ctype+1)[(uchar) (c)] & _MY_SPC) -#define my_ispunct(s, c) (((s)->ctype+1)[(uchar) (c)] & _MY_PNT) -#define my_isprint(s, c) (((s)->ctype+1)[(uchar) (c)] & (_MY_PNT | _MY_U | _MY_L | _MY_NMR | _MY_B)) -#define my_isgraph(s, c) (((s)->ctype+1)[(uchar) (c)] & (_MY_PNT | _MY_U | _MY_L | _MY_NMR)) -#define my_iscntrl(s, c) (((s)->ctype+1)[(uchar) (c)] & _MY_CTR) - -/* Some macros that should be cleaned up a little */ -#define my_isvar(s,c) (my_isalnum(s,c) || (c) == '_') -#define my_isvar_start(s,c) (my_isalpha(s,c) || (c) == '_') - -#define my_binary_compare(s) ((s)->state & MY_CS_BINSORT) -#define use_strnxfrm(s) ((s)->state & MY_CS_STRNXFRM) -#define my_strnxfrm(cs, d, dl, s, sl) \ - ((cs)->coll->strnxfrm((cs), (d), (dl), (dl), (s), (sl), MY_STRXFRM_PAD_WITH_SPACE)) -#define my_strnncoll(s, a, b, c, d) ((s)->coll->strnncoll((s), (a), (b), (c), (d), 0)) -#define my_like_range(s, a, b, c, d, e, f, g, h, i, j) \ - ((s)->coll->like_range((s), (a), (b), (c), (d), (e), (f), (g), (h), (i), (j))) -#define my_wildcmp(cs,s,se,w,we,e,o,m) ((cs)->coll->wildcmp((cs),(s),(se),(w),(we),(e),(o),(m))) -#define my_strcasecmp(s, a, b) ((s)->coll->strcasecmp((s), (a), (b))) -#define my_charpos(cs, b, e, num) (cs)->cset->charpos((cs), (const char*) (b), (const char *)(e), (num)) - - -#define use_mb(s) ((s)->cset->ismbchar != NULL) -#define my_ismbchar(s, a, b) ((s)->cset->ismbchar((s), (a), (b))) -#define my_mbcharlen(s, a) ((s)->cset->mbcharlen((s),(a))) -/** - Get the length of gb18030 code by the given two leading bytes - - @param[in] s charset_info - @param[in] a first byte of gb18030 code - @param[in] b second byte of gb18030 code - @return the length of gb18030 code starting with given two bytes, - the length would be 2 or 4 for valid gb18030 code, - or 0 for invalid gb18030 code -*/ -#define my_mbcharlen_2(s, a, b) ((s)->cset->mbcharlen((s),((((a) & 0xFF) << 8) + ((b) & 0xFF)))) -/** - Get the maximum length of leading bytes needed to determine the length of a - multi-byte gb18030 code - - @param[in] s charset_info - @return number of leading bytes we need, would be 2 for gb18030 - and 1 for all other charsets -*/ -#define my_mbmaxlenlen(s) ((s)->mbmaxlenlen) -/** - Judge if the given byte is a possible leading byte for a charset. - For gb18030 whose mbmaxlenlen is 2, we can't determine the length of - a multi-byte character by looking at the first byte only - - @param[in] s charset_info - @param[in] i possible leading byte - @return true if it is, otherwise false -*/ -#define my_ismb1st(s, i) \ - (my_mbcharlen((s), (i)) > 1 || \ - (my_mbmaxlenlen((s)) == 2 && my_mbcharlen((s), (i)) == 0)) - -#define my_caseup_str(s, a) ((s)->cset->caseup_str((s), (a))) -#define my_casedn_str(s, a) ((s)->cset->casedn_str((s), (a))) -#define my_strntol(s, a, b, c, d, e) ((s)->cset->strntol((s),(a),(b),(c),(d),(e))) -#define my_strntoul(s, a, b, c, d, e) ((s)->cset->strntoul((s),(a),(b),(c),(d),(e))) -#define my_strntoll(s, a, b, c, d, e) ((s)->cset->strntoll((s),(a),(b),(c),(d),(e))) -#define my_strntoull(s, a, b, c,d, e) ((s)->cset->strntoull((s),(a),(b),(c),(d),(e))) -#define my_strntod(s, a, b, c, d) ((s)->cset->strntod((s),(a),(b),(c),(d))) - -#ifdef __cplusplus -} -#endif - -#endif /* _m_ctype_h */ diff --git a/vendor/mysql/include/m_string.h b/vendor/mysql/include/m_string.h deleted file mode 100644 index d836bbc6a8..0000000000 --- a/vendor/mysql/include/m_string.h +++ /dev/null @@ -1,344 +0,0 @@ -/* - Copyright (c) 2000, 2015, Oracle and/or its affiliates. All rights reserved. - - This program is free software; you can redistribute it and/or modify - it under the terms of the GNU General Public License as published by - the Free Software Foundation; version 2 of the License. - - This program is distributed in the hope that it will be useful, - but WITHOUT ANY WARRANTY; without even the implied warranty of - MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - GNU General Public License for more details. - - You should have received a copy of the GNU General Public License - along with this program; if not, write to the Free Software - Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA */ - -#ifndef _m_string_h -#define _m_string_h - -#include "my_global.h" /* HAVE_* */ - -#include - -#define bfill please_use_memset_rather_than_bfill -#define bzero please_use_memset_rather_than_bzero -#define bmove please_use_memmove_rather_than_bmove -#define strmov please_use_my_stpcpy_or_my_stpmov_rather_than_strmov -#define strnmov please_use_my_stpncpy_or_my_stpnmov_rather_than_strnmov - -#include "mysql/service_my_snprintf.h" - -#if defined(__cplusplus) -extern "C" { -#endif - -/* - my_str_malloc(), my_str_realloc() and my_str_free() are assigned to - implementations in strings/alloc.c, but can be overridden in - the calling program. - */ -extern void *(*my_str_malloc)(size_t); -extern void *(*my_str_realloc)(void *, size_t); -extern void (*my_str_free)(void *); - -/* Declared in int2str() */ -extern char _dig_vec_upper[]; -extern char _dig_vec_lower[]; - - /* Prototypes for string functions */ - -extern void bchange(uchar *dst,size_t old_len,const uchar *src, - size_t new_len,size_t tot_len); -extern void strappend(char *s,size_t len,pchar fill); -extern char *strend(const char *s); -extern char *strcend(const char *, pchar); -extern char *strfill(char * s,size_t len,pchar fill); -extern char *strmake(char *dst,const char *src,size_t length); - -extern char *my_stpmov(char *dst,const char *src); -extern char *my_stpnmov(char *dst, const char *src, size_t n); -extern char *strcont(const char *src, const char *set); -extern char *strxmov(char *dst, const char *src, ...); -extern char *strxnmov(char *dst, size_t len, const char *src, ...); - -/** - Copy a string from src to dst until (and including) terminating null byte. - - @param dst Destination - @param src Source - - @note src and dst cannot overlap. - Use my_stpmov() if src and dst overlaps. - - @note Unsafe, consider using my_stpnpy() instead. - - @return pointer to terminating null byte. -*/ -static inline char *my_stpcpy(char *dst, const char *src) -{ -#if defined(HAVE_BUILTIN_STPCPY) - return __builtin_stpcpy(dst, src); -#elif defined(HAVE_STPCPY) - return stpcpy(dst, src); -#else - /* Fallback to implementation supporting overlap. */ - return my_stpmov(dst, src); -#endif -} - -/** - Copy fixed-size string from src to dst. - - @param dst Destination - @param src Source - @param n Maximum number of characters to copy. - - @note src and dst cannot overlap - Use my_stpnmov() if src and dst overlaps. - - @return pointer to terminating null byte. -*/ -static inline char *my_stpncpy(char *dst, const char *src, size_t n) -{ -#if defined(HAVE_STPNCPY) - return stpncpy(dst, src, n); -#else - /* Fallback to implementation supporting overlap. */ - return my_stpnmov(dst, src, n); -#endif -} - -static inline longlong my_strtoll(const char *nptr, char **endptr, int base) -{ -#if defined _WIN32 - return _strtoi64(nptr, endptr, base); -#else - return strtoll(nptr, endptr, base); -#endif -} - -static inline ulonglong my_strtoull(const char *nptr, char **endptr, int base) -{ -#if defined _WIN32 - return _strtoui64(nptr, endptr, base); -#else - return strtoull(nptr, endptr, base); -#endif -} - -static inline char *my_strtok_r(char *str, const char *delim, char **saveptr) -{ -#if defined _WIN32 - return strtok_s(str, delim, saveptr); -#else - return strtok_r(str, delim, saveptr); -#endif -} - -/* native_ rather than my_ since my_strcasecmp already exists */ -static inline int native_strcasecmp(const char *s1, const char *s2) -{ -#if defined _WIN32 - return _stricmp(s1, s2); -#else - return strcasecmp(s1, s2); -#endif -} - -/* native_ rather than my_ for consistency with native_strcasecmp */ -static inline int native_strncasecmp(const char *s1, const char *s2, size_t n) -{ -#if defined _WIN32 - return _strnicmp(s1, s2, n); -#else - return strncasecmp(s1, s2, n); -#endif -} - -size_t my_snprintf(char* to, size_t n, const char* fmt, ...); -size_t my_vsnprintf(char *to, size_t n, const char* fmt, va_list ap); - -/* Prototypes of normal stringfunctions (with may ours) */ -#ifndef HAVE_STRNLEN -extern size_t strnlen(const char *s, size_t n); -#endif - -extern int is_prefix(const char *, const char *); - -/* Conversion routines */ -typedef enum { - MY_GCVT_ARG_FLOAT, - MY_GCVT_ARG_DOUBLE -} my_gcvt_arg_type; - -double my_strtod(const char *str, char **end, int *error); -double my_atof(const char *nptr); -size_t my_fcvt(double x, int precision, char *to, my_bool *error); -size_t my_gcvt(double x, my_gcvt_arg_type type, int width, char *to, - my_bool *error); - -#define NOT_FIXED_DEC 31 - -/* - The longest string my_fcvt can return is 311 + "precision" bytes. - Here we assume that we never cal my_fcvt() with precision >= NOT_FIXED_DEC - (+ 1 byte for the terminating '\0'). -*/ -#define FLOATING_POINT_BUFFER (311 + NOT_FIXED_DEC) - -/* - We want to use the 'e' format in some cases even if we have enough space - for the 'f' one just to mimic sprintf("%.15g") behavior for large integers, - and to improve it for numbers < 10^(-4). - That is, for |x| < 1 we require |x| >= 10^(-15), and for |x| > 1 we require - it to be integer and be <= 10^DBL_DIG for the 'f' format to be used. - We don't lose precision, but make cases like "1e200" or "0.00001" look nicer. -*/ -#define MAX_DECPT_FOR_F_FORMAT DBL_DIG - -/* - The maximum possible field width for my_gcvt() conversion. - (DBL_DIG + 2) significant digits + sign + "." + ("e-NNN" or - MAX_DECPT_FOR_F_FORMAT zeros for cases when |x|<1 and the 'f' format is used). -*/ -#define MY_GCVT_MAX_FIELD_WIDTH (DBL_DIG + 4 + MY_MAX(5, MAX_DECPT_FOR_F_FORMAT)) \ - -extern char *llstr(longlong value,char *buff); -extern char *ullstr(longlong value,char *buff); - -extern char *int2str(long val, char *dst, int radix, int upcase); -extern char *int10_to_str(long val,char *dst,int radix); -extern char *str2int(const char *src,int radix,long lower,long upper, - long *val); -longlong my_strtoll10(const char *nptr, char **endptr, int *error); -#if SIZEOF_LONG == SIZEOF_LONG_LONG -#define ll2str(A,B,C,D) int2str((A),(B),(C),(D)) -#define longlong10_to_str(A,B,C) int10_to_str((A),(B),(C)) -#undef strtoll -#define strtoll(A,B,C) strtol((A),(B),(C)) -#define strtoull(A,B,C) strtoul((A),(B),(C)) -#else -extern char *ll2str(longlong val,char *dst,int radix, int upcase); -extern char *longlong10_to_str(longlong val,char *dst,int radix); -#endif -#define longlong2str(A,B,C) ll2str((A),(B),(C),1) - -#if defined(__cplusplus) -} -#endif - -/* - LEX_STRING -- a pair of a C-string and its length. - (it's part of the plugin API as a MYSQL_LEX_STRING) - Ditto LEX_CSTRING/MYSQL_LEX_CSTRING. -*/ - -#include -typedef struct st_mysql_lex_string LEX_STRING; -typedef struct st_mysql_const_lex_string LEX_CSTRING; - -#define STRING_WITH_LEN(X) (X), ((sizeof(X) - 1)) -#define USTRING_WITH_LEN(X) ((uchar*) X), ((sizeof(X) - 1)) -#define C_STRING_WITH_LEN(X) ((char *) (X)), ((sizeof(X) - 1)) - - -/** - Skip trailing space. - - On most systems reading memory in larger chunks (ideally equal to the size of - the chinks that the machine physically reads from memory) causes fewer memory - access loops and hence increased performance. - This is why the 'int' type is used : it's closest to that (according to how - it's defined in C). - So when we determine the amount of whitespace at the end of a string we do - the following : - 1. We divide the string into 3 zones : - a) from the start of the string (__start) to the first multiple - of sizeof(int) (__start_words) - b) from the end of the string (__end) to the last multiple of sizeof(int) - (__end_words) - c) a zone that is aligned to sizeof(int) and can be safely accessed - through an int * - 2. We start comparing backwards from (c) char-by-char. If all we find is - space then we continue - 3. If there are elements in zone (b) we compare them as unsigned ints to a - int mask (SPACE_INT) consisting of all spaces - 4. Finally we compare the remaining part (a) of the string char by char. - This covers for the last non-space unsigned int from 3. (if any) - - This algorithm works well for relatively larger strings, but it will slow - the things down for smaller strings (because of the additional calculations - and checks compared to the naive method). Thus the barrier of length 20 - is added. - - @param ptr pointer to the input string - @param len the length of the string - @return the last non-space character -*/ -#if defined(__sparc) || defined(__sparcv9) -static inline const uchar *skip_trailing_space(const uchar *ptr,size_t len) -{ - /* SPACE_INT is a word that contains only spaces */ -#if SIZEOF_INT == 4 - const unsigned SPACE_INT= 0x20202020U; -#elif SIZEOF_INT == 8 - const unsigned SPACE_INT= 0x2020202020202020ULL; -#else -#error define the appropriate constant for a word full of spaces -#endif - - const uchar *end= ptr + len; - - if (len > 20) - { - const uchar *end_words= (const uchar *)(intptr) - (((ulonglong)(intptr)end) / SIZEOF_INT * SIZEOF_INT); - const uchar *start_words= (const uchar *)(intptr) - ((((ulonglong)(intptr)ptr) + SIZEOF_INT - 1) / SIZEOF_INT * SIZEOF_INT); - - DBUG_ASSERT(end_words > ptr); - while (end > end_words && end[-1] == 0x20) - end--; - if (end[-1] == 0x20 && start_words < end_words) - while (end > start_words && ((unsigned *)end)[-1] == SPACE_INT) - end -= SIZEOF_INT; - } - while (end > ptr && end[-1] == 0x20) - end--; - return (end); -} -#else -/* - Reads 8 bytes at a time, ignoring alignment. - We use uint8korr, which is fast (it simply reads a *ulonglong) - on all platforms, except sparc. -*/ -static inline const uchar *skip_trailing_space(const uchar *ptr, size_t len) -{ - const uchar *end= ptr + len; - while (end - ptr >= 8) - { - if (uint8korr(end-8) != 0x2020202020202020ULL) - break; - end-= 8; - } - while (end > ptr && end[-1] == 0x20) - end--; - return (end); -} -#endif - -static inline void lex_string_set(LEX_STRING *lex_str, const char *c_str) -{ - lex_str->str= (char *) c_str; - lex_str->length= strlen(c_str); -} - -static inline void lex_cstring_set(LEX_CSTRING *lex_str, const char *c_str) -{ - lex_str->str= c_str; - lex_str->length= strlen(c_str); -} - -#endif diff --git a/vendor/mysql/include/my_alloc.h b/vendor/mysql/include/my_alloc.h deleted file mode 100644 index b72a176923..0000000000 --- a/vendor/mysql/include/my_alloc.h +++ /dev/null @@ -1,65 +0,0 @@ -/* Copyright (c) 2000, 2016, Oracle and/or its affiliates. All rights reserved. - - This program is free software; you can redistribute it and/or modify - it under the terms of the GNU General Public License as published by - the Free Software Foundation; version 2 of the License. - - This program is distributed in the hope that it will be useful, - but WITHOUT ANY WARRANTY; without even the implied warranty of - MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - GNU General Public License for more details. - - You should have received a copy of the GNU General Public License - along with this program; if not, write to the Free Software - Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA */ - -/* - Data structures for mysys/my_alloc.c (root memory allocator) -*/ - -#ifndef _my_alloc_h -#define _my_alloc_h - -#define ALLOC_MAX_BLOCK_TO_DROP 4096 -#define ALLOC_MAX_BLOCK_USAGE_BEFORE_DROP 10 - -/* PSI_memory_key */ -#include "mysql/psi/psi_memory.h" - -#ifdef __cplusplus -extern "C" { -#endif - -typedef struct st_used_mem -{ /* struct for once_alloc (block) */ - struct st_used_mem *next; /* Next block in use */ - unsigned int left; /* memory left in block */ - unsigned int size; /* size of block */ -} USED_MEM; - - -typedef struct st_mem_root -{ - USED_MEM *free; /* blocks with free memory in it */ - USED_MEM *used; /* blocks almost without free memory */ - USED_MEM *pre_alloc; /* preallocated block */ - /* if block have less memory it will be put in 'used' list */ - size_t min_malloc; - size_t block_size; /* initial block size */ - unsigned int block_num; /* allocated blocks counter */ - /* - first free block in queue test counter (if it exceed - MAX_BLOCK_USAGE_BEFORE_DROP block will be dropped in 'used' list) - */ - unsigned int first_block_usage; - - void (*error_handler)(void); - - PSI_memory_key m_psi_key; -} MEM_ROOT; - -#ifdef __cplusplus -} -#endif - -#endif diff --git a/vendor/mysql/include/my_byteorder.h b/vendor/mysql/include/my_byteorder.h deleted file mode 100644 index daedd6247e..0000000000 --- a/vendor/mysql/include/my_byteorder.h +++ /dev/null @@ -1,213 +0,0 @@ -#ifndef MY_BYTEORDER_INCLUDED -#define MY_BYTEORDER_INCLUDED - -/* Copyright (c) 2001, 2014, Oracle and/or its affiliates. All rights reserved. - - This program is free software; you can redistribute it and/or modify - it under the terms of the GNU General Public License as published by - the Free Software Foundation; version 2 of the License. - - This program is distributed in the hope that it will be useful, - but WITHOUT ANY WARRANTY; without even the implied warranty of - MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - GNU General Public License for more details. - - You should have received a copy of the GNU General Public License - along with this program; if not, write to the Free Software - Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA */ - - -/* - Functions for reading and storing in machine independent - format (low byte first). There are 'korr' (assume 'corrector') variants - for integer types, but 'get' (assume 'getter') for floating point types. -*/ -#if defined(__i386__) || defined(_WIN32) || defined(__x86_64__) -#include "byte_order_generic_x86.h" -#else -#include "byte_order_generic.h" -#endif - -static inline int32 sint3korr(const uchar *A) -{ - return - ((int32) (((A[2]) & 128) ? - (((uint32) 255L << 24) | - (((uint32) A[2]) << 16) | - (((uint32) A[1]) << 8) | - ((uint32) A[0])) : - (((uint32) A[2]) << 16) | - (((uint32) A[1]) << 8) | - ((uint32) A[0]))) - ; -} - -static inline uint32 uint3korr(const uchar *A) -{ - return - (uint32) (((uint32) (A[0])) + - (((uint32) (A[1])) << 8) + - (((uint32) (A[2])) << 16)) - ; -} - -static inline ulonglong uint5korr(const uchar *A) -{ - return - ((ulonglong)(((uint32) (A[0])) + - (((uint32) (A[1])) << 8) + - (((uint32) (A[2])) << 16) + - (((uint32) (A[3])) << 24)) + - (((ulonglong) (A[4])) << 32)) - ; -} - -static inline ulonglong uint6korr(const uchar *A) -{ - return - ((ulonglong)(((uint32) (A[0])) + - (((uint32) (A[1])) << 8) + - (((uint32) (A[2])) << 16) + - (((uint32) (A[3])) << 24)) + - (((ulonglong) (A[4])) << 32) + - (((ulonglong) (A[5])) << 40)) - ; -} - -static inline void int3store(uchar *T, uint A) -{ - *(T)= (uchar) (A); - *(T+1)= (uchar) (A >> 8); - *(T+2)= (uchar) (A >> 16); -} - -static inline void int5store(uchar *T, ulonglong A) -{ - *(T)= (uchar) (A); - *(T+1)= (uchar) (A >> 8); - *(T+2)= (uchar) (A >> 16); - *(T+3)= (uchar) (A >> 24); - *(T+4)= (uchar) (A >> 32); -} - -static inline void int6store(uchar *T, ulonglong A) -{ - *(T)= (uchar) (A); - *(T+1)= (uchar) (A >> 8); - *(T+2)= (uchar) (A >> 16); - *(T+3)= (uchar) (A >> 24); - *(T+4)= (uchar) (A >> 32); - *(T+5)= (uchar) (A >> 40); -} - -#ifdef __cplusplus - -static inline int16 sint2korr(const char *pT) -{ - return sint2korr(static_cast(static_cast(pT))); -} - -static inline uint16 uint2korr(const char *pT) -{ - return uint2korr(static_cast(static_cast(pT))); -} - -static inline uint32 uint3korr(const char *pT) -{ - return uint3korr(static_cast(static_cast(pT))); -} - -static inline int32 sint3korr(const char *pT) -{ - return sint3korr(static_cast(static_cast(pT))); -} - -static inline uint32 uint4korr(const char *pT) -{ - return uint4korr(static_cast(static_cast(pT))); -} - -static inline int32 sint4korr(const char *pT) -{ - return sint4korr(static_cast(static_cast(pT))); -} - -static inline ulonglong uint6korr(const char *pT) -{ - return uint6korr(static_cast(static_cast(pT))); -} - -static inline ulonglong uint8korr(const char *pT) -{ - return uint8korr(static_cast(static_cast(pT))); -} - -static inline longlong sint8korr(const char *pT) -{ - return sint8korr(static_cast(static_cast(pT))); -} - - -static inline void int2store(char *pT, uint16 A) -{ - int2store(static_cast(static_cast(pT)), A); -} - -static inline void int3store(char *pT, uint A) -{ - int3store(static_cast(static_cast(pT)), A); -} - -static inline void int4store(char *pT, uint32 A) -{ - int4store(static_cast(static_cast(pT)), A); -} - -static inline void int5store(char *pT, ulonglong A) -{ - int5store(static_cast(static_cast(pT)), A); -} - -static inline void int6store(char *pT, ulonglong A) -{ - int6store(static_cast(static_cast(pT)), A); -} - -static inline void int8store(char *pT, ulonglong A) -{ - int8store(static_cast(static_cast(pT)), A); -} - -#endif /* __cplusplus */ - -/* - Functions for reading and storing in machine format from/to - short/long to/from some place in memory V should be a variable - and M a pointer to byte. -*/ -#ifdef WORDS_BIGENDIAN -#include "big_endian.h" -#else -#include "little_endian.h" -#endif - -#ifdef __cplusplus - -static inline void float4store(char *V, float M) -{ - float4store(static_cast(static_cast(V)), M); -} - -static inline void float8get(double *V, const char *M) -{ - float8get(V, static_cast(static_cast(M))); -} - -static inline void float8store(char *V, double M) -{ - float8store(static_cast(static_cast(V)), M); -} - -#endif /* __cplusplus */ - -#endif /* MY_BYTEORDER_INCLUDED */ diff --git a/vendor/mysql/include/my_command.h b/vendor/mysql/include/my_command.h index 56adcffd74..b5d51cd2b4 100644 --- a/vendor/mysql/include/my_command.h +++ b/vendor/mysql/include/my_command.h @@ -1,13 +1,26 @@ -/* Copyright (c) 2015, Oracle and/or its affiliates. All rights reserved. +/* Copyright (c) 2015, 2024, Oracle and/or its affiliates. This program is free software; you can redistribute it and/or modify -it under the terms of the GNU General Public License as published by -the Free Software Foundation; version 2 of the License. +it under the terms of the GNU General Public License, version 2.0, +as published by the Free Software Foundation. + +This program is designed to work with certain software (including +but not limited to OpenSSL) that is licensed under separate terms, +as designated in a particular file or component or in included license +documentation. The authors of MySQL hereby grant you an additional +permission to link the program and your derivative works with the +separately licensed software that they have either included with +the program or referenced in the documentation. + +Without limiting anything contained in the foregoing, this file, +which is part of C Driver for MySQL (Connector/C), is also subject to the +Universal FOSS Exception, version 1.0, a copy of which can be found at +http://oss.oracle.com/licenses/universal-foss-exception. This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -GNU General Public License for more details. +GNU General Public License, version 2.0, for more details. You should have received a copy of the GNU General Public License along with this program; if not, write to the Free Software @@ -16,49 +29,76 @@ Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA */ #ifndef _mysql_command_h #define _mysql_command_h +/** + @file include/my_command.h +*/ + /** @enum enum_server_command - @brief You should add new commands to the end of this list, otherwise old - servers won't be able to handle them as 'unsupported'. + + @brief A list of all MySQL protocol commands. + + These are the top level commands the server can receive + while it listens for a new command in ::dispatch_command + + @par Warning + Add new commands to the end of this list, otherwise old + servers won't be able to handle them as 'unsupported'. */ -enum enum_server_command -{ +enum enum_server_command { + /** + Currently refused by the server. See ::dispatch_command. + Also used internally to mark the start of a session. + */ COM_SLEEP, - COM_QUIT, - COM_INIT_DB, - COM_QUERY, - COM_FIELD_LIST, - COM_CREATE_DB, - COM_DROP_DB, - COM_REFRESH, - COM_SHUTDOWN, - COM_STATISTICS, - COM_PROCESS_INFO, - COM_CONNECT, - COM_PROCESS_KILL, - COM_DEBUG, - COM_PING, - COM_TIME, - COM_DELAYED_INSERT, - COM_CHANGE_USER, - COM_BINLOG_DUMP, + COM_QUIT, /**< See @ref page_protocol_com_quit */ + COM_INIT_DB, /**< See @ref page_protocol_com_init_db */ + COM_QUERY, /**< See @ref page_protocol_com_query */ + COM_FIELD_LIST, /**< Deprecated. See @ref page_protocol_com_field_list */ + COM_CREATE_DB, /**< Currently refused by the server. See ::dispatch_command */ + COM_DROP_DB, /**< Currently refused by the server. See ::dispatch_command */ + COM_UNUSED_2, /**< Removed, used to be COM_REFRESH. */ + COM_UNUSED_1, /**< Removed, used to be COM_SHUTDOWN */ + COM_STATISTICS, /**< See @ref page_protocol_com_statistics */ + COM_UNUSED_4, /**< Removed, used to be COM_PROCESS_INFO */ + COM_CONNECT, /**< Currently refused by the server. */ + COM_UNUSED_5, /**< Removed, used to be COM_PROCESS_KILL */ + COM_DEBUG, /**< See @ref page_protocol_com_debug */ + COM_PING, /**< See @ref page_protocol_com_ping */ + COM_TIME, /**< Currently refused by the server. */ + COM_DELAYED_INSERT, /**< Functionality removed. */ + COM_CHANGE_USER, /**< See @ref page_protocol_com_change_user */ + COM_BINLOG_DUMP, /**< See @ref page_protocol_com_binlog_dump */ COM_TABLE_DUMP, COM_CONNECT_OUT, COM_REGISTER_SLAVE, - COM_STMT_PREPARE, - COM_STMT_EXECUTE, + COM_STMT_PREPARE, /**< See @ref page_protocol_com_stmt_prepare */ + COM_STMT_EXECUTE, /**< See @ref page_protocol_com_stmt_execute */ + /** See @ref page_protocol_com_stmt_send_long_data */ COM_STMT_SEND_LONG_DATA, - COM_STMT_CLOSE, - COM_STMT_RESET, - COM_SET_OPTION, - COM_STMT_FETCH, + COM_STMT_CLOSE, /**< See @ref page_protocol_com_stmt_close */ + COM_STMT_RESET, /**< See @ref page_protocol_com_stmt_reset */ + COM_SET_OPTION, /**< See @ref page_protocol_com_set_option */ + COM_STMT_FETCH, /**< See @ref page_protocol_com_stmt_fetch */ + /** + Currently refused by the server. See ::dispatch_command. + Also used internally to mark the session as a "daemon", + i.e. non-client THD. Currently the scheduler and the GTID + code does use this state. + These threads won't be killed by `KILL` + + @sa Event_scheduler::start, ::init_thd, ::kill_one_thread, + ::Find_thd_with_id + */ COM_DAEMON, COM_BINLOG_DUMP_GTID, - COM_RESET_CONNECTION, + COM_RESET_CONNECTION, /**< See @ref page_protocol_com_reset_connection */ + COM_CLONE, + COM_SUBSCRIBE_GROUP_REPLICATION_STREAM, /* don't forget to update const char *command_name[] in sql_parse.cc */ /* Must be last */ - COM_END + COM_END /**< Not a real command. Refused. */ }; #endif /* _mysql_command_h */ diff --git a/vendor/mysql/include/my_compiler.h b/vendor/mysql/include/my_compiler.h deleted file mode 100644 index 2092537185..0000000000 --- a/vendor/mysql/include/my_compiler.h +++ /dev/null @@ -1,178 +0,0 @@ -#ifndef MY_COMPILER_INCLUDED -#define MY_COMPILER_INCLUDED - -/* Copyright (c) 2010, 2016, Oracle and/or its affiliates. All rights reserved. - - This program is free software; you can redistribute it and/or modify - it under the terms of the GNU General Public License as published by - the Free Software Foundation; version 2 of the License. - - This program is distributed in the hope that it will be useful, - but WITHOUT ANY WARRANTY; without even the implied warranty of - MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - GNU General Public License for more details. - - You should have received a copy of the GNU General Public License - along with this program; if not, write to the Free Software - Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA */ - -/** - Header for compiler-dependent features. - - Intended to contain a set of reusable wrappers for preprocessor - macros, attributes, pragmas, and any other features that are - specific to a target compiler. -*/ - -#include /* size_t */ - -#if defined __GNUC__ -/* - Convenience macro to test the minimum required GCC version. - These should be used with care as Clang also sets __GNUC__ and - __GNUC_MINOR__ (currently to 4.2). Prefer using feature specific - CMake checks in configure.cmake instead. -*/ -# define MY_GNUC_PREREQ(maj, min) \ - ((__GNUC__ << 16) + __GNUC_MINOR__ >= ((maj) << 16) + (min)) -# define GCC_VERSION (__GNUC__ * 1000 + __GNUC_MINOR__) -#else -# define MY_GNUC_PREREQ(maj, min) (0) -#endif - -/* - The macros below are borrowed from include/linux/compiler.h in the - Linux kernel. Use them to indicate the likelyhood of the truthfulness - of a condition. This serves two purposes - newer versions of gcc will be - able to optimize for branch predication, which could yield siginficant - performance gains in frequently executed sections of the code, and the - other reason to use them is for documentation -*/ -#ifdef HAVE_BUILTIN_EXPECT - -// likely/unlikely are likely to clash with other symbols, do not #define -#if defined(__cplusplus) -inline bool likely(bool expr) -{ - return __builtin_expect(expr, true); -} -inline bool unlikely(bool expr) -{ - return __builtin_expect(expr, false); -} -#else -# define likely(x) __builtin_expect((x),1) -# define unlikely(x) __builtin_expect((x),0) -#endif - -#else /* HAVE_BUILTIN_EXPECT */ - -#if defined(__cplusplus) -inline bool likely(bool expr) -{ - return expr; -} -inline bool unlikely(bool expr) -{ - return expr; -} -#else -# define likely(x) (x) -# define unlikely(x) (x) -#endif - -#endif /* HAVE_BUILTIN_EXPECT */ - -/* Comunicate to the compiler the unreachability of the code. */ -#ifdef HAVE_BUILTIN_UNREACHABLE -# define MY_ASSERT_UNREACHABLE() __builtin_unreachable() -#else -# define MY_ASSERT_UNREACHABLE() do { assert(0); } while (0) -#endif - -#if defined __GNUC__ || defined __SUNPRO_C || defined __SUNPRO_CC -/* Specifies the minimum alignment of a type. */ -# define MY_ALIGNOF(type) __alignof__(type) -/* Determine the alignment requirement of a type. */ -# define MY_ALIGNED(n) __attribute__((__aligned__((n)))) -/* Microsoft Visual C++ */ -#elif defined _MSC_VER -# define MY_ALIGNOF(type) __alignof(type) -# define MY_ALIGNED(n) __declspec(align(n)) -#else /* Make sure they are defined for other compilers. */ -# define MY_ALIGNOF(type) -# define MY_ALIGNED(size) -#endif - -/* Visual Studio requires '__inline' for C code */ -#if !defined(__cplusplus) && defined(_MSC_VER) -# define inline __inline -#endif - -/* Provide __func__ macro definition for Visual Studio. */ -#if defined(_MSC_VER) -# define __func__ __FUNCTION__ -#endif - -/** - C++ Type Traits -*/ -#ifdef __cplusplus - -/** - Opaque storage with a particular alignment. - Partial specialization used due to MSVC++. -*/ -template struct my_alignment_imp; -template<> struct MY_ALIGNED(1) my_alignment_imp<1> {}; -template<> struct MY_ALIGNED(2) my_alignment_imp<2> {}; -template<> struct MY_ALIGNED(4) my_alignment_imp<4> {}; -template<> struct MY_ALIGNED(8) my_alignment_imp<8> {}; -template<> struct MY_ALIGNED(16) my_alignment_imp<16> {}; - -/** - A POD type with a given size and alignment. - - @remark If the compiler does not support a alignment attribute - (MY_ALIGN macro), the default alignment of a double is - used instead. - - @tparam size The minimum size. - @tparam alignment The desired alignment: 1, 2, 4, 8 or 16. -*/ -template -struct my_aligned_storage -{ - union - { - char data[size]; - my_alignment_imp align; - }; -}; - -#endif /* __cplusplus */ - -/* - Disable MY_ATTRIBUTE for Sun Studio and Visual Studio. - Note that Sun Studio supports some __attribute__ variants, - but not format or unused which we use quite a lot. -*/ -#ifndef MY_ATTRIBUTE -#if defined(__GNUC__) -# define MY_ATTRIBUTE(A) __attribute__(A) -#else -# define MY_ATTRIBUTE(A) -#endif -#endif - -#ifndef __has_attribute -# define __has_attribute(x) 0 -#endif - -#if __has_attribute(no_sanitize_undefined) -# define SUPPRESS_UBSAN __attribute__((no_sanitize_undefined)) -#else -# define SUPPRESS_UBSAN -#endif - -#endif /* MY_COMPILER_INCLUDED */ diff --git a/vendor/mysql/include/my_compress.h b/vendor/mysql/include/my_compress.h new file mode 100644 index 0000000000..6375fc7408 --- /dev/null +++ b/vendor/mysql/include/my_compress.h @@ -0,0 +1,115 @@ +/* Copyright (c) 2019, 2024, Oracle and/or its affiliates. + + This program is free software; you can redistribute it and/or modify + it under the terms of the GNU General Public License, version 2.0, + as published by the Free Software Foundation. + + This program is designed to work with certain software (including + but not limited to OpenSSL) that is licensed under separate terms, + as designated in a particular file or component or in included license + documentation. The authors of MySQL hereby grant you an additional + permission to link the program and your derivative works with the + separately licensed software that they have either included with + the program or referenced in the documentation. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License, version 2.0, for more details. + + You should have received a copy of the GNU General Public License + along with this program; if not, write to the Free Software + Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA */ + +#ifndef MY_COMPRESS_INCLUDED +#define MY_COMPRESS_INCLUDED + +/* List of valid values for compression_algorithm */ +enum enum_compression_algorithm { + MYSQL_UNCOMPRESSED = 1, + MYSQL_ZLIB, + MYSQL_ZSTD, + MYSQL_INVALID +}; + +/** + Compress context information. relating to zlib compression. +*/ + +typedef struct mysql_zlib_compress_context { + /** + Compression level to use in zlib compression. + */ + unsigned int compression_level; +} mysql_zlib_compress_context; + +typedef struct ZSTD_CCtx_s ZSTD_CCtx; +typedef struct ZSTD_DCtx_s ZSTD_DCtx; + +/** + Compress context information relating to zstd compression. +*/ + +typedef struct mysql_zstd_compress_context { + /** + Pointer to compressor context. + */ + ZSTD_CCtx *cctx; + /** + Pointer to decompressor context. + */ + ZSTD_DCtx *dctx; + /** + Compression level to use in zstd compression. + */ + unsigned int compression_level; +} mysql_zstd_compress_context; + +/** + Compression context information. + It encapsulate the context information based on compression method and + presents a generic struct. +*/ + +typedef struct mysql_compress_context { + enum enum_compression_algorithm algorithm; ///< Compression algorithm name. + union { + mysql_zlib_compress_context zlib_ctx; ///< Context information of zlib. + mysql_zstd_compress_context zstd_ctx; ///< Context information of zstd. + } u; +} mysql_compress_context; + +/** + Get default compression level corresponding to a given compression method. + + @param algorithm Compression Method. Possible values are zlib or zstd. + + @return an unsigned int representing default compression level. + 6 is the default compression level for zlib and 3 is the + default compression level for zstd. +*/ + +unsigned int mysql_default_compression_level( + enum enum_compression_algorithm algorithm); + +/** + Initialize a compress context object to be associated with a NET object. + + @param cmp_ctx Pointer to compression context. + @param algorithm Compression algorithm. + @param compression_level Compression level corresponding to the compression + algorithm. +*/ + +void mysql_compress_context_init(mysql_compress_context *cmp_ctx, + enum enum_compression_algorithm algorithm, + unsigned int compression_level); +/** + Deinitialize the compression context allocated. + + @param mysql_compress_ctx Pointer to Compression context. +*/ + +void mysql_compress_context_deinit(mysql_compress_context *mysql_compress_ctx); + +#endif // MY_COMPRESS_INCLUDED diff --git a/vendor/mysql/include/my_config.h b/vendor/mysql/include/my_config.h deleted file mode 100644 index 145286acc8..0000000000 --- a/vendor/mysql/include/my_config.h +++ /dev/null @@ -1,454 +0,0 @@ -/* Copyright (c) 2009, 2016, Oracle and/or its affiliates. All rights reserved. - - This program is free software; you can redistribute it and/or modify - it under the terms of the GNU General Public License as published by - the Free Software Foundation; version 2 of the License. - - This program is distributed in the hope that it will be useful, - but WITHOUT ANY WARRANTY; without even the implied warranty of - MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - GNU General Public License for more details. - - You should have received a copy of the GNU General Public License - along with this program; if not, write to the Free Software - Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA */ - -#ifndef MY_CONFIG_H -#define MY_CONFIG_H - -/* - * From configure.cmake, in order of appearance - */ -/* #undef HAVE_LLVM_LIBCPP */ -#define _LARGEFILE_SOURCE 1 - -/* Libraries */ -/* #undef HAVE_LIBM */ -/* #undef HAVE_LIBNSL */ -/* #undef HAVE_LIBCRYPT */ -/* #undef HAVE_LIBSOCKET */ -/* #undef HAVE_LIBDL */ -/* #undef HAVE_LIBRT */ -/* #undef HAVE_LIBWRAP */ - -/* Header files */ -/* #undef HAVE_ALLOCA_H */ -/* #undef HAVE_ARPA_INET_H */ -/* #undef HAVE_DIRENT_H */ -/* #undef HAVE_DLFCN_H */ -/* #undef HAVE_EXECINFO_H */ -/* #undef HAVE_FPU_CONTROL_H */ -/* #undef HAVE_GRP_H */ -/* #undef HAVE_IEEEFP_H */ -/* #undef HAVE_LANGINFO_H */ -#define HAVE_MALLOC_H 1 -/* #undef HAVE_NETINET_IN_H */ -/* #undef HAVE_POLL_H */ -/* #undef HAVE_PWD_H */ -/* #undef HAVE_STRINGS_H */ -/* #undef HAVE_SYS_CDEFS_H */ -/* #undef HAVE_SYS_IOCTL_H */ -/* #undef HAVE_SYS_MMAN_H */ -/* #undef HAVE_SYS_RESOURCE_H */ -/* #undef HAVE_SYS_SELECT_H */ -/* #undef HAVE_SYS_SOCKET_H */ -/* #undef HAVE_TERM_H */ -/* #undef HAVE_TERMIOS_H */ -/* #undef HAVE_TERMIO_H */ -/* #undef HAVE_UNISTD_H */ -/* #undef HAVE_SYS_WAIT_H */ -/* #undef HAVE_SYS_PARAM_H */ -/* #undef HAVE_FNMATCH_H */ -/* #undef HAVE_SYS_UN_H */ -/* #undef HAVE_VIS_H */ -/* #undef HAVE_SASL_SASL_H */ - -/* Libevent */ -/* #undef HAVE_DEVPOLL */ -/* #undef HAVE_SYS_DEVPOLL_H */ -/* #undef HAVE_SYS_EPOLL_H */ -/* #undef HAVE_TAILQFOREACH */ - -/* Functions */ -#define HAVE_ALIGNED_MALLOC 1 -/* #undef HAVE_BACKTRACE */ -/* #undef HAVE_PRINTSTACK */ -/* #undef HAVE_INDEX */ -/* #undef HAVE_CLOCK_GETTIME */ -/* #undef HAVE_CUSERID */ -/* #undef HAVE_DIRECTIO */ -/* #undef HAVE_FTRUNCATE */ -#define HAVE_COMPRESS 1 -/* #undef HAVE_CRYPT */ -/* #undef HAVE_DLOPEN */ -/* #undef HAVE_FCHMOD */ -/* #undef HAVE_FCNTL */ -/* #undef HAVE_FDATASYNC */ -/* #undef HAVE_DECL_FDATASYNC */ -/* #undef HAVE_FEDISABLEEXCEPT */ -/* #undef HAVE_FSEEKO */ -/* #undef HAVE_FSYNC */ -/* #undef HAVE_GETHOSTBYADDR_R */ -/* #undef HAVE_GETHRTIME */ -/* #undef HAVE_GETNAMEINFO */ -/* #undef HAVE_GETPASS */ -/* #undef HAVE_GETPASSPHRASE */ -/* #undef HAVE_GETPWNAM */ -/* #undef HAVE_GETPWUID */ -/* #undef HAVE_GETRLIMIT */ -/* #undef HAVE_GETRUSAGE */ -/* #undef HAVE_INITGROUPS */ -/* #undef HAVE_ISSETUGID */ -/* #undef HAVE_GETUID */ -/* #undef HAVE_GETEUID */ -/* #undef HAVE_GETGID */ -/* #undef HAVE_GETEGID */ -/* #undef HAVE_LSTAT */ -/* #undef HAVE_MADVISE */ -/* #undef HAVE_MALLOC_INFO */ -/* #undef HAVE_MEMRCHR */ -/* #undef HAVE_MLOCK */ -/* #undef HAVE_MLOCKALL */ -/* #undef HAVE_MMAP64 */ -/* #undef HAVE_POLL */ -/* #undef HAVE_POSIX_FALLOCATE */ -/* #undef HAVE_POSIX_MEMALIGN */ -/* #undef HAVE_PREAD */ -/* #undef HAVE_PTHREAD_CONDATTR_SETCLOCK */ -/* #undef HAVE_PTHREAD_SIGMASK */ -/* #undef HAVE_READDIR_R */ -/* #undef HAVE_READLINK */ -/* #undef HAVE_REALPATH */ -/* #undef HAVE_SETFD */ -/* #undef HAVE_SIGACTION */ -/* #undef HAVE_SLEEP */ -/* #undef HAVE_STPCPY */ -/* #undef HAVE_STPNCPY */ -/* #undef HAVE_STRLCPY */ -#define HAVE_STRNLEN 1 -/* #undef HAVE_STRLCAT */ -/* #undef HAVE_STRSIGNAL */ -/* #undef HAVE_FGETLN */ -/* #undef HAVE_STRSEP */ -#define HAVE_TELL 1 -/* #undef HAVE_VASPRINTF */ -/* #undef HAVE_MEMALIGN */ -/* #undef HAVE_NL_LANGINFO */ -/* #undef HAVE_HTONLL */ -/* #undef DNS_USE_CPU_CLOCK_FOR_ID */ -/* #undef HAVE_EPOLL */ -/* #undef HAVE_EVENT_PORTS */ -/* #undef HAVE_INET_NTOP */ -/* #undef HAVE_WORKING_KQUEUE */ -/* #undef HAVE_TIMERADD */ -/* #undef HAVE_TIMERCLEAR */ -/* #undef HAVE_TIMERCMP */ -/* #undef HAVE_TIMERISSET */ - -/* WL2373 */ -/* #undef HAVE_SYS_TIME_H */ -/* #undef HAVE_SYS_TIMES_H */ -/* #undef HAVE_TIMES */ -/* #undef HAVE_GETTIMEOFDAY */ - -/* Symbols */ -/* #undef HAVE_LRAND48 */ -/* #undef GWINSZ_IN_SYS_IOCTL */ -/* #undef FIONREAD_IN_SYS_IOCTL */ -/* #undef FIONREAD_IN_SYS_FILIO */ -/* #undef HAVE_SIGEV_THREAD_ID */ -/* #undef HAVE_SIGEV_PORT */ -#define HAVE_LOG2 1 - -#define HAVE_ISINF 1 - -/* #undef HAVE_KQUEUE_TIMERS */ -/* #undef HAVE_POSIX_TIMERS */ - -/* Endianess */ -/* #undef WORDS_BIGENDIAN */ - -/* Type sizes */ -#define SIZEOF_VOIDP 4 -#define SIZEOF_CHARP 4 -#define SIZEOF_LONG 4 -#define SIZEOF_SHORT 2 -#define SIZEOF_INT 4 -#define SIZEOF_LONG_LONG 8 -#define SIZEOF_OFF_T 4 -#define SIZEOF_TIME_T 8 -/* #undef HAVE_UINT */ -/* #undef HAVE_ULONG */ -/* #undef HAVE_U_INT32_T */ -#define HAVE_STRUCT_TIMESPEC - -/* Support for tagging symbols with __attribute__((visibility("hidden"))) */ -/* #undef HAVE_VISIBILITY_HIDDEN */ - -/* Code tests*/ -#define STACK_DIRECTION -1 -/* #undef TIME_WITH_SYS_TIME */ -#define NO_FCNTL_NONBLOCK 1 -/* #undef HAVE_PAUSE_INSTRUCTION */ -/* #undef HAVE_FAKE_PAUSE_INSTRUCTION */ -/* #undef HAVE_HMT_PRIORITY_INSTRUCTION */ -/* #undef HAVE_ABI_CXA_DEMANGLE */ -/* #undef HAVE_BSS_START */ -/* #undef HAVE_BUILTIN_UNREACHABLE */ -/* #undef HAVE_BUILTIN_EXPECT */ -/* #undef HAVE_BUILTIN_STPCPY */ -/* #undef HAVE_GCC_ATOMIC_BUILTINS */ -/* #undef HAVE_GCC_SYNC_BUILTINS */ -/* #undef HAVE_VALGRIND */ - -/* IPV6 */ -/* #undef HAVE_NETINET_IN6_H */ -#define HAVE_STRUCT_SOCKADDR_IN6 1 -#define HAVE_STRUCT_IN6_ADDR 1 -#define HAVE_IPV6 1 - -/* #undef ss_family */ -/* #undef HAVE_SOCKADDR_IN_SIN_LEN */ -/* #undef HAVE_SOCKADDR_IN6_SIN6_LEN */ - -/* - * Platform specific CMake files - */ -#define MACHINE_TYPE "AMD64" -/* #undef HAVE_LINUX_LARGE_PAGES */ -/* #undef HAVE_SOLARIS_LARGE_PAGES */ -/* #undef HAVE_SOLARIS_ATOMIC */ -/* #undef HAVE_SOLARIS_STYLE_GETHOST */ -#define SYSTEM_TYPE "Win32" -/* Windows stuff, mostly functions, that have Posix analogs but named differently */ -/* #undef IPPROTO_IPV6 */ -/* #undef IPV6_V6ONLY */ -/* This should mean case insensitive file system */ -#define FN_NO_CASE_SENSE 1 - -/* - * From main CMakeLists.txt - */ -#define MAX_INDEXES 64U -/* #undef WITH_INNODB_MEMCACHED */ -/* #undef ENABLE_MEMCACHED_SASL */ -/* #undef ENABLE_MEMCACHED_SASL_PWDB */ -#define ENABLED_PROFILING 1 -/* #undef HAVE_ASAN */ -#define ENABLED_LOCAL_INFILE 1 -/* #undef OPTIMIZER_TRACE */ -#define DEFAULT_MYSQL_HOME "C:/Program Files/MySQL/MySQL Server 6.1" -#define SHAREDIR "share" -#define DEFAULT_BASEDIR "C:/Program Files/MySQL/MySQL Server 6.1" -#define MYSQL_DATADIR "C:/Program Files/MySQL/MySQL Server 6.1/data" -#define MYSQL_KEYRINGDIR "C:/Program Files/MySQL/MySQL Server 6.1/keyring" -#define DEFAULT_CHARSET_HOME "C:/Program Files/MySQL/MySQL Server 6.1" -#define PLUGINDIR "C:/Program Files/MySQL/MySQL Server 6.1/lib/plugin" -/* #undef DEFAULT_SYSCONFDIR */ -#define DEFAULT_TMPDIR "" -#define INSTALL_SBINDIR "/bin" -#define INSTALL_BINDIR "/bin" -#define INSTALL_MYSQLSHAREDIR "/share" -#define INSTALL_SHAREDIR "/share" -#define INSTALL_PLUGINDIR "/lib/plugin" -#define INSTALL_INCLUDEDIR "/include" -#define INSTALL_SCRIPTDIR "/scripts" -#define INSTALL_MYSQLDATADIR "/data" -#define INSTALL_MYSQLKEYRINGDIR "/keyring" -/* #undef INSTALL_PLUGINTESTDIR */ -#define INSTALL_INFODIR "/docs" -#define INSTALL_MYSQLTESTDIR "/mysql-test" -#define INSTALL_DOCREADMEDIR "/." -#define INSTALL_DOCDIR "/docs" -#define INSTALL_MANDIR "/man" -#define INSTALL_SUPPORTFILESDIR "/support-files" -#define INSTALL_LIBDIR "/lib" - -/* - * Readline - */ -/* #undef HAVE_MBSTATE_T */ -/* #undef HAVE_LANGINFO_CODESET */ -/* #undef HAVE_WCSDUP */ -/* #undef HAVE_WCHAR_T */ -/* #undef HAVE_WINT_T */ -/* #undef HAVE_CURSES_H */ -/* #undef HAVE_NCURSES_H */ -/* #undef USE_LIBEDIT_INTERFACE */ -/* #undef HAVE_HIST_ENTRY */ -/* #undef USE_NEW_EDITLINE_INTERFACE */ - -/* - * Libedit - */ -/* #undef HAVE_DECL_TGOTO */ - -/* - * DTrace - */ -/* #undef HAVE_DTRACE */ - -/* - * Character sets - */ -#define MYSQL_DEFAULT_CHARSET_NAME "latin1" -#define MYSQL_DEFAULT_COLLATION_NAME "latin1_swedish_ci" -#define HAVE_CHARSET_armscii8 1 -#define HAVE_CHARSET_ascii 1 -#define HAVE_CHARSET_big5 1 -#define HAVE_CHARSET_cp1250 1 -#define HAVE_CHARSET_cp1251 1 -#define HAVE_CHARSET_cp1256 1 -#define HAVE_CHARSET_cp1257 1 -#define HAVE_CHARSET_cp850 1 -#define HAVE_CHARSET_cp852 1 -#define HAVE_CHARSET_cp866 1 -#define HAVE_CHARSET_cp932 1 -#define HAVE_CHARSET_dec8 1 -#define HAVE_CHARSET_eucjpms 1 -#define HAVE_CHARSET_euckr 1 -#define HAVE_CHARSET_gb2312 1 -#define HAVE_CHARSET_gbk 1 -#define HAVE_CHARSET_gb18030 1 -#define HAVE_CHARSET_geostd8 1 -#define HAVE_CHARSET_greek 1 -#define HAVE_CHARSET_hebrew 1 -#define HAVE_CHARSET_hp8 1 -#define HAVE_CHARSET_keybcs2 1 -#define HAVE_CHARSET_koi8r 1 -#define HAVE_CHARSET_koi8u 1 -#define HAVE_CHARSET_latin1 1 -#define HAVE_CHARSET_latin2 1 -#define HAVE_CHARSET_latin5 1 -#define HAVE_CHARSET_latin7 1 -#define HAVE_CHARSET_macce 1 -#define HAVE_CHARSET_macroman 1 -#define HAVE_CHARSET_sjis 1 -#define HAVE_CHARSET_swe7 1 -#define HAVE_CHARSET_tis620 1 -#define HAVE_CHARSET_ucs2 1 -#define HAVE_CHARSET_ujis 1 -#define HAVE_CHARSET_utf8mb4 1 -/* #undef HAVE_CHARSET_utf8mb3 */ -#define HAVE_CHARSET_utf8 1 -#define HAVE_CHARSET_utf16 1 -#define HAVE_CHARSET_utf32 1 -#define HAVE_UCA_COLLATIONS 1 - -/* - * Feature set - */ -#define WITH_PARTITION_STORAGE_ENGINE 1 - -/* - * Performance schema - */ -/* #undef WITH_PERFSCHEMA_STORAGE_ENGINE */ -/* #undef DISABLE_PSI_THREAD */ -/* #undef DISABLE_PSI_MUTEX */ -/* #undef DISABLE_PSI_RWLOCK */ -/* #undef DISABLE_PSI_COND */ -/* #undef DISABLE_PSI_FILE */ -/* #undef DISABLE_PSI_TABLE */ -/* #undef DISABLE_PSI_SOCKET */ -/* #undef DISABLE_PSI_STAGE */ -/* #undef DISABLE_PSI_STATEMENT */ -/* #undef DISABLE_PSI_SP */ -/* #undef DISABLE_PSI_PS */ -/* #undef DISABLE_PSI_IDLE */ -/* #undef DISABLE_PSI_STATEMENT_DIGEST */ -/* #undef DISABLE_PSI_METADATA */ -/* #undef DISABLE_PSI_MEMORY */ -/* #undef DISABLE_PSI_TRANSACTION */ - -/* - * syscall -*/ -/* #undef HAVE_SYS_THREAD_SELFID */ -/* #undef HAVE_SYS_GETTID */ -/* #undef HAVE_PTHREAD_GETTHREADID_NP */ -/* #undef HAVE_PTHREAD_SETNAME_NP */ -/* #undef HAVE_INTEGER_PTHREAD_SELF */ - -/* Platform-specific C++ compiler behaviors we rely upon */ - -/* - This macro defines whether the compiler in use needs a 'typename' keyword - to access the types defined inside a class template, such types are called - dependent types. Some compilers require it, some others forbid it, and some - others may work with or without it. For example, GCC requires the 'typename' - keyword whenever needing to access a type inside a template, but msvc - forbids it. - */ -#define HAVE_IMPLICIT_DEPENDENT_NAME_TYPING 1 - - -/* - * MySQL version - */ -#define DOT_FRM_VERSION 6 -#define MYSQL_VERSION_MAJOR 6 -#define MYSQL_VERSION_MINOR 1 -#define MYSQL_VERSION_PATCH 11 -#define MYSQL_VERSION_EXTRA "" -#define PACKAGE "mysql" -#define PACKAGE_BUGREPORT "" -#define PACKAGE_NAME "MySQL Server" -#define PACKAGE_STRING "MySQL Server 6.1.11" -#define PACKAGE_TARNAME "mysql" -#define PACKAGE_VERSION "6.1.11" -#define VERSION "6.1.11" -#define PROTOCOL_VERSION 10 - -/* - * CPU info - */ -#define CPU_LEVEL1_DCACHE_LINESIZE 64 - -/* - * NDB - */ -/* #undef WITH_NDBCLUSTER_STORAGE_ENGINE */ -/* #undef HAVE_PTHREAD_SETSCHEDPARAM */ - -/* - * Other - */ -/* #undef EXTRA_DEBUG */ -/* #undef HAVE_CHOWN */ - -/* - * Hardcoded values needed by libevent/NDB/memcached - */ -#define HAVE_FCNTL_H 1 -#define HAVE_GETADDRINFO 1 -#define HAVE_INTTYPES_H 1 -/* libevent's select.c is not Windows compatible */ -#ifndef _WIN32 -#define HAVE_SELECT 1 -#endif -#define HAVE_SIGNAL_H 1 -#define HAVE_STDARG_H 1 -#define HAVE_STDINT_H 1 -#define HAVE_STDLIB_H 1 -#define HAVE_STRDUP 1 -#define HAVE_STRTOK_R 1 -#define HAVE_STRTOLL 1 -#define HAVE_SYS_STAT_H 1 -#define HAVE_SYS_TYPES_H 1 -#define SIZEOF_CHAR 1 - -/* - * Needed by libevent - */ -/* #undef HAVE_SOCKLEN_T */ - -/* For --secure-file-priv */ -#define DEFAULT_SECURE_FILE_PRIV_DIR "NULL" -#define DEFAULT_SECURE_FILE_PRIV_EMBEDDED_DIR "NULL" -/* #undef HAVE_LIBNUMA */ - -/* For default value of --early_plugin_load */ -/* #undef DEFAULT_EARLY_PLUGIN_LOAD */ - -#endif diff --git a/vendor/mysql/include/my_dbug.h b/vendor/mysql/include/my_dbug.h deleted file mode 100644 index 2af2e66d57..0000000000 --- a/vendor/mysql/include/my_dbug.h +++ /dev/null @@ -1,245 +0,0 @@ -/* Copyright (c) 2000, 2016, Oracle and/or its affiliates. All rights reserved. - - This program is free software; you can redistribute it and/or modify - it under the terms of the GNU General Public License as published by - the Free Software Foundation; version 2 of the License. - - This program is distributed in the hope that it will be useful, - but WITHOUT ANY WARRANTY; without even the implied warranty of - MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - GNU General Public License for more details. - - You should have received a copy of the GNU General Public License - along with this program; if not, write to the Free Software - Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA */ - -#ifndef MY_DBUG_INCLUDED -#define MY_DBUG_INCLUDED - -#include "my_global.h" /* MYSQL_PLUGIN_IMPORT */ - -#ifdef __cplusplus -extern "C" { -#endif -#if !defined(DBUG_OFF) - -struct _db_stack_frame_ { - const char *func; /* function name of the previous stack frame */ - const char *file; /* filename of the function of previous frame */ - uint level; /* this nesting level, highest bit enables tracing */ - struct _db_stack_frame_ *prev; /* pointer to the previous frame */ -}; - -struct _db_code_state_; -extern MYSQL_PLUGIN_IMPORT my_bool _dbug_on_; -extern my_bool _db_keyword_(struct _db_code_state_ *, const char *, int); -extern int _db_explain_(struct _db_code_state_ *cs, char *buf, size_t len); -extern int _db_explain_init_(char *buf, size_t len); -extern int _db_is_pushed_(void); -extern void _db_setjmp_(void); -extern void _db_longjmp_(void); -extern void _db_process_(const char *name); -extern void _db_push_(const char *control); -extern void _db_pop_(void); -extern void _db_set_(const char *control); -extern void _db_set_init_(const char *control); -extern void _db_enter_(const char *_func_, const char *_file_, uint _line_, - struct _db_stack_frame_ *_stack_frame_); -extern void _db_return_(uint _line_, struct _db_stack_frame_ *_stack_frame_); -extern void _db_pargs_(uint _line_,const char *keyword); -extern int _db_enabled_(); -extern void _db_doprnt_(const char *format,...) - MY_ATTRIBUTE((format(printf, 1, 2))); -extern void _db_doputs_(const char *log); -extern void _db_dump_(uint _line_,const char *keyword, - const unsigned char *memory, size_t length); -extern void _db_end_(void); -extern void _db_lock_file_(void); -extern void _db_unlock_file_(void); -extern FILE *_db_fp_(void); -extern void _db_flush_(); -extern const char* _db_get_func_(void); - -#define DBUG_ENTER(a) struct _db_stack_frame_ _db_stack_frame_; \ - _db_enter_ (a,__FILE__,__LINE__,&_db_stack_frame_) -#define DBUG_LEAVE _db_return_ (__LINE__, &_db_stack_frame_) -#define DBUG_RETURN(a1) do {DBUG_LEAVE; return(a1);} while(0) -#define DBUG_VOID_RETURN do {DBUG_LEAVE; return;} while(0) -#define DBUG_EXECUTE(keyword,a1) \ - do {if (_db_keyword_(0, (keyword), 0)) { a1 }} while(0) -#define DBUG_EXECUTE_IF(keyword,a1) \ - do {if (_db_keyword_(0, (keyword), 1)) { a1 }} while(0) -#define DBUG_EVALUATE(keyword,a1,a2) \ - (_db_keyword_(0,(keyword), 0) ? (a1) : (a2)) -#define DBUG_EVALUATE_IF(keyword,a1,a2) \ - (_db_keyword_(0,(keyword), 1) ? (a1) : (a2)) -#define DBUG_PRINT(keyword,arglist) \ - do \ - { \ - if (_dbug_on_) \ - { \ - _db_pargs_(__LINE__,keyword); \ - if (_db_enabled_()) \ - { \ - _db_doprnt_ arglist; \ - } \ - } \ - } while(0) - -/* - An alternate to DBUG_PRINT() macro, which takes a single string - as the second argument. -*/ -#define DBUG_PUTS(keyword,arg) \ - do \ - { \ - if (_dbug_on_) \ - { \ - _db_pargs_(__LINE__,keyword); \ - if (_db_enabled_()) \ - { \ - _db_doputs_(arg); \ - } \ - } \ - } while(0) - -#define DBUG_PUSH(a1) _db_push_ (a1) -#define DBUG_POP() _db_pop_ () -#define DBUG_SET(a1) _db_set_ (a1) -#define DBUG_SET_INITIAL(a1) _db_set_init_ (a1) -#define DBUG_PROCESS(a1) _db_process_(a1) -#define DBUG_FILE _db_fp_() -#define DBUG_SETJMP(a1) (_db_setjmp_ (), setjmp (a1)) -#define DBUG_LONGJMP(a1,a2) (_db_longjmp_ (), longjmp (a1, a2)) -#define DBUG_DUMP(keyword,a1,a2) _db_dump_(__LINE__,keyword,a1,a2) -#define DBUG_END() _db_end_ () -#define DBUG_LOCK_FILE _db_lock_file_() -#define DBUG_UNLOCK_FILE _db_unlock_file_() -#define DBUG_ASSERT(A) assert(A) -#define DBUG_EXPLAIN(buf,len) _db_explain_(0, (buf),(len)) -#define DBUG_EXPLAIN_INITIAL(buf,len) _db_explain_init_((buf),(len)) -#define DEBUGGER_OFF do { _dbug_on_= 0; } while(0) -#define DEBUGGER_ON do { _dbug_on_= 1; } while(0) -#ifndef _WIN32 -#define DBUG_ABORT() (_db_flush_(), abort()) -#else -/* - Avoid popup with abort/retry/ignore buttons. When BUG#31745 is fixed we can - call abort() instead of _exit(2) (now it would cause a "test signal" popup). -*/ -#include -#define DBUG_ABORT() (_db_flush_(),\ - (void)_CrtSetReportMode(_CRT_ERROR, _CRTDBG_MODE_FILE),\ - (void)_CrtSetReportFile(_CRT_ERROR, _CRTDBG_FILE_STDERR),\ - _exit(2)) -#endif -#define DBUG_CHECK_CRASH(func, op) \ - do { char _dbuf_[255]; strxnmov(_dbuf_, sizeof(_dbuf_)-1, (func), (op)); \ - DBUG_EXECUTE_IF(_dbuf_, DBUG_ABORT()); } while(0) -#define DBUG_CRASH_ENTER(func) \ - DBUG_ENTER(func); DBUG_CHECK_CRASH(func, "_crash_enter") -#define DBUG_CRASH_RETURN(val) \ - DBUG_CHECK_CRASH(_db_get_func_(), "_crash_return") -#define DBUG_CRASH_VOID_RETURN \ - DBUG_CHECK_CRASH (_db_get_func_(), "_crash_return") - -/* - Make the program fail, without creating a core file. - abort() will send SIGABRT which (most likely) generates core. - Use SIGKILL instead, which cannot be caught. - We also pause the current thread, until the signal is actually delivered. - An alternative would be to use _exit(EXIT_FAILURE), - but then valgrind would report lots of memory leaks. - */ -#ifdef _WIN32 -#define DBUG_SUICIDE() DBUG_ABORT() -#else -extern void _db_suicide_(); -extern void _db_flush_gcov_(); -#define DBUG_SUICIDE() (_db_flush_(), _db_suicide_()) -#endif - -#else /* No debugger */ - -#define DBUG_ENTER(a1) -#define DBUG_LEAVE -#define DBUG_RETURN(a1) do { return(a1); } while(0) -#define DBUG_VOID_RETURN do { return; } while(0) -#define DBUG_EXECUTE(keyword,a1) do { } while(0) -#define DBUG_EXECUTE_IF(keyword,a1) do { } while(0) -#define DBUG_EVALUATE(keyword,a1,a2) (a2) -#define DBUG_EVALUATE_IF(keyword,a1,a2) (a2) -#define DBUG_PRINT(keyword,arglist) do { } while(0) -#define DBUG_PUTS(keyword,arg) do { } while(0) -#define DBUG_LOG(keyword,arglist) do { } while(0) -#define DBUG_PUSH(a1) do { } while(0) -#define DBUG_SET(a1) do { } while(0) -#define DBUG_SET_INITIAL(a1) do { } while(0) -#define DBUG_POP() do { } while(0) -#define DBUG_PROCESS(a1) do { } while(0) -#define DBUG_SETJMP(a1) setjmp(a1) -#define DBUG_LONGJMP(a1) longjmp(a1) -#define DBUG_DUMP(keyword,a1,a2) do { } while(0) -#define DBUG_END() do { } while(0) -#define DBUG_ASSERT(A) do { } while(0) -#define DBUG_LOCK_FILE do { } while(0) -#define DBUG_FILE (stderr) -#define DBUG_UNLOCK_FILE do { } while(0) -#define DBUG_EXPLAIN(buf,len) -#define DBUG_EXPLAIN_INITIAL(buf,len) -#define DEBUGGER_OFF do { } while(0) -#define DEBUGGER_ON do { } while(0) -#define DBUG_ABORT() do { } while(0) -#define DBUG_CRASH_ENTER(func) -#define DBUG_CRASH_RETURN(val) do { return(val); } while(0) -#define DBUG_CRASH_VOID_RETURN do { return; } while(0) -#define DBUG_SUICIDE() do { } while(0) - -#endif - -#ifdef EXTRA_DEBUG -/** - Sync points allow us to force the server to reach a certain line of code - and block there until the client tells the server it is ok to go on. - The client tells the server to block with SELECT GET_LOCK() - and unblocks it with SELECT RELEASE_LOCK(). Used for debugging difficult - concurrency problems -*/ -#define DBUG_SYNC_POINT(lock_name,lock_timeout) \ - debug_sync_point(lock_name,lock_timeout) -void debug_sync_point(const char* lock_name, uint lock_timeout); -#else -#define DBUG_SYNC_POINT(lock_name,lock_timeout) -#endif /* EXTRA_DEBUG */ - -#ifdef __cplusplus -} -#endif - -#ifdef __cplusplus -#if !defined(DBUG_OFF) -#include - -/* - A C++ interface to the DBUG_PUTS macro. The DBUG_LOG macro also - takes two arguments. The first argument is the keyword, as that of the - DBUG_PRINT. The 2nd argument 'v' will be passed to a C++ output stream. - This enables the use of C++ style output stream operator. In the code, it - will be used as follows: - - DBUG_LOG("blob", "space: " << space_id); - - Note: DBUG_PRINT() has a limitation of 1024 bytes for a single - print out. This limitation is not there for DBUG_PUTS and DBUG_LOG - macros. -*/ - -#define DBUG_LOG(keyword, v) do { \ - std::ostringstream sout; \ - sout << v; \ - DBUG_PUTS(keyword, sout.str().c_str()); \ -} while(0) -#endif /* DBUG_OFF */ -#endif /* __cplusplus */ - -#endif /* MY_DBUG_INCLUDED */ diff --git a/vendor/mysql/include/my_dir.h b/vendor/mysql/include/my_dir.h deleted file mode 100644 index 0b512cdca9..0000000000 --- a/vendor/mysql/include/my_dir.h +++ /dev/null @@ -1,93 +0,0 @@ -/* Copyright (c) 2000, 2013, Oracle and/or its affiliates. All rights reserved. - - This program is free software; you can redistribute it and/or modify - it under the terms of the GNU General Public License as published by - the Free Software Foundation; version 2 of the License. - - This program is distributed in the hope that it will be useful, - but WITHOUT ANY WARRANTY; without even the implied warranty of - MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - GNU General Public License for more details. - - You should have received a copy of the GNU General Public License - along with this program; if not, write to the Free Software - Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA */ - -#ifndef MY_DIR_H -#define MY_DIR_H - -#include "my_global.h" - -#include - -#ifdef __cplusplus -extern "C" { -#endif - - /* Defines for my_dir and my_stat */ - -#ifdef _WIN32 -#define S_IROTH _S_IREAD -#define S_IFIFO _S_IFIFO -#endif - -#define MY_S_IFMT S_IFMT /* type of file */ -#define MY_S_IFDIR S_IFDIR /* directory */ -#define MY_S_IFCHR S_IFCHR /* character special */ -#define MY_S_IFBLK S_IFBLK /* block special */ -#define MY_S_IFREG S_IFREG /* regular */ -#define MY_S_IFIFO S_IFIFO /* fifo */ -#define MY_S_ISUID S_ISUID /* set user id on execution */ -#define MY_S_ISGID S_ISGID /* set group id on execution */ -#define MY_S_ISVTX S_ISVTX /* save swapped text even after use */ -#define MY_S_IREAD S_IREAD /* read permission, owner */ -#define MY_S_IWRITE S_IWRITE /* write permission, owner */ -#define MY_S_IEXEC S_IEXEC /* execute/search permission, owner */ - -#define MY_S_ISDIR(m) (((m) & MY_S_IFMT) == MY_S_IFDIR) -#define MY_S_ISCHR(m) (((m) & MY_S_IFMT) == MY_S_IFCHR) -#define MY_S_ISBLK(m) (((m) & MY_S_IFMT) == MY_S_IFBLK) -#define MY_S_ISREG(m) (((m) & MY_S_IFMT) == MY_S_IFREG) -#define MY_S_ISFIFO(m) (((m) & MY_S_IFMT) == MY_S_IFIFO) - -#define MY_DONT_SORT 512 /* my_lib; Don't sort files */ -#define MY_WANT_STAT 1024 /* my_lib; stat files */ - - /* typedefs for my_dir & my_stat */ - -#if(_MSC_VER) -#define MY_STAT struct _stati64 /* 64 bit file size */ -#else -#define MY_STAT struct stat /* Orginal struct have what we need */ -#endif - -/* Struct describing one file returned from my_dir */ -typedef struct fileinfo -{ - char *name; - MY_STAT *mystat; -} FILEINFO; - -typedef struct st_my_dir /* Struct returned from my_dir */ -{ - /* - These members are just copies of parts of DYNAMIC_ARRAY structure, - which is allocated right after the end of MY_DIR structure (MEM_ROOT - for storing names is also resides there). We've left them here because - we don't want to change code that uses my_dir. - */ - struct fileinfo *dir_entry; - uint number_off_files; -} MY_DIR; - -extern MY_DIR *my_dir(const char *path,myf MyFlags); -extern void my_dirend(MY_DIR *buffer); -extern MY_STAT *my_stat(const char *path, MY_STAT *stat_area, myf my_flags); -extern int my_fstat(int filenr, MY_STAT *stat_area, myf MyFlags); - -#ifdef __cplusplus -} -#endif - -#endif /* MY_DIR_H */ - diff --git a/vendor/mysql/include/my_getopt.h b/vendor/mysql/include/my_getopt.h deleted file mode 100644 index 7908297a00..0000000000 --- a/vendor/mysql/include/my_getopt.h +++ /dev/null @@ -1,149 +0,0 @@ - /* - Copyright (c) 2002, 2014, Oracle and/or its affiliates. All rights reserved. - - This program is free software; you can redistribute it and/or modify - it under the terms of the GNU General Public License as published by - the Free Software Foundation; version 2 of the License. - - This program is distributed in the hope that it will be useful, - but WITHOUT ANY WARRANTY; without even the implied warranty of - MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - GNU General Public License for more details. - - You should have received a copy of the GNU General Public License - along with this program; if not, write to the Free Software - Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA */ - -#ifndef _my_getopt_h -#define _my_getopt_h - -#include "my_sys.h" /* loglevel */ - -C_MODE_START - -#define GET_NO_ARG 1 -#define GET_BOOL 2 -#define GET_INT 3 -#define GET_UINT 4 -#define GET_LONG 5 -#define GET_ULONG 6 -#define GET_LL 7 -#define GET_ULL 8 -#define GET_STR 9 -#define GET_STR_ALLOC 10 -#define GET_DISABLED 11 -#define GET_ENUM 12 -#define GET_SET 13 -#define GET_DOUBLE 14 -#define GET_FLAGSET 15 -#define GET_PASSWORD 16 - -#if SIZEOF_INT == 4 -#define GET_INT32 GET_INT -#define GET_UINT32 GET_UINT -#elif SIZEOF_LONG == 4 -#define GET_INT32 GET_LONG -#define GET_UINT32 GET_ULONG -#else -#error Neither int or long is of 4 bytes width -#endif - -#define GET_ASK_ADDR 128 -#define GET_TYPE_MASK 127 - -/** - Enumeration of the my_option::arg_type attributes. - It should be noted that for historical reasons variables with the combination - arg_type=NO_ARG, my_option::var_type=GET_BOOL still accepts - arguments. This is someone counter intuitive and care should be taken - if the code is refactored. -*/ -enum get_opt_arg_type { NO_ARG, OPT_ARG, REQUIRED_ARG }; - -struct st_typelib; - -struct my_option -{ - const char *name; /**< Name of the option. name=NULL - marks the end of the my_option[] - array. - */ - int id; /**< For 0255 no short option - is created, but a long option still - can be identified uniquely in the - my_get_one_option() callback. - If an opton needs neither special - treatment in the my_get_one_option() - nor one-letter short equivalent - use id=0. - id=-1 is a special case and is used - to generate deprecation warnings for - plugin options. It should not be - used for anything else. - */ - const char *comment; /**< option comment, for autom. --help. - if it's NULL the option is not - visible in --help. - */ - void *value; /**< A pointer to the variable value */ - void *u_max_value; /**< The user def. max variable value */ - struct st_typelib *typelib; /**< Pointer to possible values */ - ulong var_type; /**< GET_BOOL, GET_ULL, etc */ - enum get_opt_arg_type arg_type; /**< e.g. REQUIRED_ARG or OPT_ARG */ - longlong def_value; /**< Default value */ - longlong min_value; /**< Min allowed value (for numbers) */ - ulonglong max_value; /**< Max allowed value (for numbers) */ - longlong sub_size; /**< Unused */ - long block_size; /**< Value should be a mult. of this (for numbers) */ - void *app_type; /**< To be used by an application */ -}; - - -typedef my_bool (*my_get_one_option)(int, const struct my_option *, char *); -/** - Used to retrieve a reference to the object (variable) that holds the value - for the given option. For example, if var_type is GET_UINT, the function - must return a pointer to a variable of type uint. A argument is stored in - the location pointed to by the returned pointer. -*/ -typedef void *(*my_getopt_value)(const char *, size_t, const struct my_option *, - int *); - - -extern char *disabled_my_option; -extern my_bool my_getopt_print_errors; -extern my_bool my_getopt_skip_unknown; -extern my_error_reporter my_getopt_error_reporter; - -extern int handle_options (int *argc, char ***argv, - const struct my_option *longopts, my_get_one_option); -extern int my_handle_options (int *argc, char ***argv, - const struct my_option *longopts, - my_get_one_option, - const char **command_list, my_bool ignore_unknown_option); -extern void print_cmdline_password_warning(); -extern void my_cleanup_options(const struct my_option *options); -extern void my_cleanup_options(const struct my_option *options); -extern void my_print_help(const struct my_option *options); -extern void my_print_variables(const struct my_option *options); -extern void my_print_variables_ex(const struct my_option *options, FILE* file); -extern void my_getopt_register_get_addr(my_getopt_value); - -ulonglong getopt_ull_limit_value(ulonglong num, const struct my_option *optp, - my_bool *fix); -longlong getopt_ll_limit_value(longlong, const struct my_option *, - my_bool *fix); -double getopt_double_limit_value(double num, const struct my_option *optp, - my_bool *fix); -my_bool getopt_compare_strings(const char *s, const char *t, uint length); -ulonglong max_of_int_range(int var_type); - -ulonglong getopt_double2ulonglong(double); -double getopt_ulonglong2double(ulonglong); - -C_MODE_END - -#endif /* _my_getopt_h */ - diff --git a/vendor/mysql/include/my_global.h b/vendor/mysql/include/my_global.h deleted file mode 100644 index 09eae6168f..0000000000 --- a/vendor/mysql/include/my_global.h +++ /dev/null @@ -1,781 +0,0 @@ -/* - Copyright (c) 2001, 2016, Oracle and/or its affiliates. All rights reserved. - - This program is free software; you can redistribute it and/or modify - it under the terms of the GNU General Public License as published by - the Free Software Foundation; version 2 of the License. - - This program is distributed in the hope that it will be useful, - but WITHOUT ANY WARRANTY; without even the implied warranty of - MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - GNU General Public License for more details. - - You should have received a copy of the GNU General Public License - along with this program; if not, write to the Free Software - Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA */ - -#ifndef MY_GLOBAL_INCLUDED -#define MY_GLOBAL_INCLUDED - -/* - This include file should be included first in every header file. - - This makes sure my_config.h is included to get platform specific - symbols defined and it makes sure a lot of platform/compiler - differences are mitigated. -*/ - -#include "my_config.h" - -#define __STDC_LIMIT_MACROS /* Enable C99 limit macros */ -#define __STDC_FORMAT_MACROS /* Enable C99 printf format macros */ -#define _USE_MATH_DEFINES /* Get access to M_PI, M_E, etc. in math.h */ - -#ifdef _WIN32 -/* Include common headers.*/ -# include -# include /* SOCKET */ -# include /* access(), chmod() */ -#endif - -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include /* Recommended by debian */ -#include - -#ifdef HAVE_SYS_SOCKET_H -#include -#endif -#if !defined(_WIN32) -#include -#endif -#ifdef MY_MSCRT_DEBUG -#include -#endif - -/* - A lot of our programs uses asserts, so better to always include it - This also fixes a problem when people uses DBUG_ASSERT without including - assert.h -*/ -#include - -/* Include standard definitions of operator new and delete. */ -#ifdef __cplusplus -# include -#endif - -#include "my_compiler.h" - - -/* - InnoDB depends on some MySQL internals which other plugins should not - need. This is because of InnoDB's foreign key support, "safe" binlog - truncation, and other similar legacy features. - - We define accessors for these internals unconditionally, but do not - expose them in mysql/plugin.h. They are declared in ha_innodb.h for - InnoDB's use. -*/ -#define INNODB_COMPATIBILITY_HOOKS - -/* Macros to make switching between C and C++ mode easier */ -#ifdef __cplusplus -#define C_MODE_START extern "C" { -#define C_MODE_END } -#else -#define C_MODE_START -#define C_MODE_END -#endif - -#ifdef WITH_PERFSCHEMA_STORAGE_ENGINE -#define HAVE_PSI_INTERFACE -#endif /* WITH_PERFSCHEMA_STORAGE_ENGINE */ - -/* Make it easier to add conditional code in _expressions_ */ -#ifdef _WIN32 -#define IF_WIN(A,B) A -#else -#define IF_WIN(A,B) B -#endif - -#if defined (_WIN32) -/* - off_t is 32 bit long. We do not use C runtime functions - with off_t but native Win32 file IO APIs, that work with - 64 bit offsets. -*/ -#undef SIZEOF_OFF_T -#define SIZEOF_OFF_T 8 - -static inline void sleep(unsigned long seconds) -{ - Sleep(seconds * 1000); -} - -/* Define missing access() modes. */ -#define F_OK 0 -#define W_OK 2 -#define R_OK 4 /* Test for read permission. */ - -/* Define missing file locking constants. */ -#define F_RDLCK 1 -#define F_WRLCK 2 -#define F_UNLCK 3 -#define F_TO_EOF 0x3FFFFFFF - -#define O_NONBLOCK 1 /* For emulation of fcntl() */ - -/* - SHUT_RDWR is called SD_BOTH in windows and - is defined to 2 in winsock2.h - #define SD_BOTH 0x02 -*/ -#define SHUT_RDWR 0x02 - -/* Shared memory and named pipe connections are supported. */ -#define shared_memory_buffer_length 16000 -#define default_shared_memory_base_name "MYSQL" -#endif /* _WIN32*/ - -/** - Cast a member of a structure to the structure that contains it. - - @param ptr Pointer to the member. - @param type Type of the structure that contains the member. - @param member Name of the member within the structure. -*/ -#define my_container_of(ptr, type, member) \ - ((type *)((char *)ptr - offsetof(type, member))) - -/* an assert that works at compile-time. only for constant expression */ -#define compile_time_assert(X) \ - do \ - { \ - typedef char compile_time_assert[(X) ? 1 : -1] MY_ATTRIBUTE((unused)); \ - } while(0) - -#define QUOTE_ARG(x) #x /* Quote argument (before cpp) */ -#define STRINGIFY_ARG(x) QUOTE_ARG(x) /* Quote argument, after cpp */ - -#ifdef _WIN32 -#define SO_EXT ".dll" -#elif defined(__APPLE__) -#define SO_EXT ".dylib" -#else -#define SO_EXT ".so" -#endif - -#if !defined(HAVE_UINT) -typedef unsigned int uint; -typedef unsigned short ushort; -#endif - -#define swap_variables(t, a, b) { t dummy; dummy= a; a= b; b= dummy; } -#define MY_TEST(a) ((a) ? 1 : 0) -#define set_if_bigger(a,b) do { if ((a) < (b)) (a)=(b); } while(0) -#define set_if_smaller(a,b) do { if ((a) > (b)) (a)=(b); } while(0) -#define test_all_bits(a,b) (((a) & (b)) == (b)) -#define array_elements(A) ((uint) (sizeof(A)/sizeof(A[0]))) - -/* Define some general constants */ -#ifndef TRUE -#define TRUE (1) /* Logical true */ -#define FALSE (0) /* Logical false */ -#endif - -/* Some types that is different between systems */ - -typedef int File; /* File descriptor */ -#ifdef _WIN32 -typedef SOCKET my_socket; -#else -typedef int my_socket; /* File descriptor for sockets */ -#define INVALID_SOCKET -1 -#endif -C_MODE_START -typedef void (*sig_return)();/* Returns type from signal */ -C_MODE_END -#if defined(__GNUC__) -typedef char pchar; /* Mixed prototypes can take char */ -typedef char pbool; /* Mixed prototypes can take char */ -#else -typedef int pchar; /* Mixed prototypes can't take char */ -typedef int pbool; /* Mixed prototypes can't take char */ -#endif -C_MODE_START -typedef int (*qsort_cmp)(const void *,const void *); -typedef int (*qsort_cmp2)(const void*, const void *,const void *); -C_MODE_END -#ifdef _WIN32 -typedef int socket_len_t; -typedef int sigset_t; -typedef int mode_t; -typedef SSIZE_T ssize_t; -#else -typedef socklen_t socket_len_t; -#endif -typedef socket_len_t SOCKET_SIZE_TYPE; /* Used by NDB */ - -/* file create flags */ - -#ifndef O_SHARE /* Probably not windows */ -#define O_SHARE 0 /* Flag to my_open for shared files */ -#ifndef O_BINARY -#define O_BINARY 0 /* Flag to my_open for binary files */ -#endif -#ifndef FILE_BINARY -#define FILE_BINARY O_BINARY /* Flag to my_fopen for binary streams */ -#endif -#ifdef HAVE_FCNTL -#define HAVE_FCNTL_LOCK -#define F_TO_EOF 0L /* Param to lockf() to lock rest of file */ -#endif -#endif /* O_SHARE */ - -#ifndef O_TEMPORARY -#define O_TEMPORARY 0 -#endif -#ifndef O_SHORT_LIVED -#define O_SHORT_LIVED 0 -#endif -#ifndef O_NOFOLLOW -#define O_NOFOLLOW 0 -#endif - -/* additional file share flags for win32 */ -#ifdef _WIN32 -#define _SH_DENYRWD 0x110 /* deny read/write mode & delete */ -#define _SH_DENYWRD 0x120 /* deny write mode & delete */ -#define _SH_DENYRDD 0x130 /* deny read mode & delete */ -#define _SH_DENYDEL 0x140 /* deny delete only */ -#endif /* _WIN32 */ - - -/* General constants */ -#define FN_LEN 256 /* Max file name len */ -#define FN_HEADLEN 253 /* Max length of filepart of file name */ -#define FN_EXTLEN 20 /* Max length of extension (part of FN_LEN) */ -#define FN_REFLEN 512 /* Max length of full path-name */ -#define FN_REFLEN_SE 4000 /* Max length of full path-name in SE */ -#define FN_EXTCHAR '.' -#define FN_HOMELIB '~' /* ~/ is used as abbrev for home dir */ -#define FN_CURLIB '.' /* ./ is used as abbrev for current dir */ -#define FN_PARENTDIR ".." /* Parent directory; Must be a string */ - -#ifdef _WIN32 -#define FN_LIBCHAR '\\' -#define FN_LIBCHAR2 '/' -#define FN_DIRSEP "/\\" /* Valid directory separators */ -#define FN_EXEEXT ".exe" -#define FN_SOEXT ".dll" -#define FN_ROOTDIR "\\" -#define FN_DEVCHAR ':' -#define FN_NETWORK_DRIVES /* Uses \\ to indicate network drives */ -#else -#define FN_LIBCHAR '/' -#define FN_LIBCHAR2 '/' -#define FN_DIRSEP "/" /* Valid directory separators */ -#define FN_EXEEXT "" -#define FN_SOEXT ".so" -#define FN_ROOTDIR "/" -#endif - -/* - MY_FILE_MIN is Windows speciality and is used to quickly detect - the mismatch of CRT and mysys file IO usage on Windows at runtime. - CRT file descriptors can be in the range 0-2047, whereas descriptors returned - by my_open() will start with 2048. If a file descriptor with value less then - MY_FILE_MIN is passed to mysys IO function, chances are it stemms from - open()/fileno() and not my_open()/my_fileno. - - For Posix, mysys functions are light wrappers around libc, and MY_FILE_MIN - is logically 0. -*/ - -#ifdef _WIN32 -#define MY_FILE_MIN 2048 -#else -#define MY_FILE_MIN 0 -#endif - -/* - MY_NFILE is the default size of my_file_info array. - - It is larger on Windows, because it all file handles are stored in my_file_info - Default size is 16384 and this should be enough for most cases.If it is not - enough, --max-open-files with larger value can be used. - - For Posix , my_file_info array is only used to store filenames for - error reporting and its size is not a limitation for number of open files. -*/ -#ifdef _WIN32 -#define MY_NFILE (16384 + MY_FILE_MIN) -#else -#define MY_NFILE 64 -#endif - -#define OS_FILE_LIMIT UINT_MAX - -/* - Io buffer size; Must be a power of 2 and a multiple of 512. May be - smaller what the disk page size. This influences the speed of the - isam btree library. eg to big to slow. -*/ -#define IO_SIZE 4096 -/* - How much overhead does malloc have. The code often allocates - something like 1024-MALLOC_OVERHEAD bytes -*/ -#define MALLOC_OVERHEAD 8 - - /* get memory in huncs */ -#define ONCE_ALLOC_INIT (uint) (4096-MALLOC_OVERHEAD) - /* Typical record cash */ -#define RECORD_CACHE_SIZE (uint) (64*1024-MALLOC_OVERHEAD) - /* Typical key cash */ -#define KEY_CACHE_SIZE (uint) (8*1024*1024) - /* Default size of a key cache block */ -#define KEY_CACHE_BLOCK_SIZE (uint) 1024 - - -/* Some defines of functions for portability */ - -#if (_WIN32) -#if !defined(_WIN64) -inline double my_ulonglong2double(unsigned long long value) -{ - long long nr=(long long) value; - if (nr >= 0) - return (double) nr; - return (18446744073709551616.0 + (double) nr); -} -#define ulonglong2double my_ulonglong2double -#define my_off_t2double my_ulonglong2double -#endif /* _WIN64 */ -inline unsigned long long my_double2ulonglong(double d) -{ - double t= d - (double) 0x8000000000000000ULL; - - if (t >= 0) - return ((unsigned long long) t) + 0x8000000000000000ULL; - return (unsigned long long) d; -} -#define double2ulonglong my_double2ulonglong -#endif /* _WIN32 */ - -#ifndef ulonglong2double -#define ulonglong2double(A) ((double) (ulonglong) (A)) -#define my_off_t2double(A) ((double) (my_off_t) (A)) -#endif -#ifndef double2ulonglong -#define double2ulonglong(A) ((ulonglong) (double) (A)) -#endif - -#define INT_MIN64 (~0x7FFFFFFFFFFFFFFFLL) -#define INT_MAX64 0x7FFFFFFFFFFFFFFFLL -#define INT_MIN32 (~0x7FFFFFFFL) -#define INT_MAX32 0x7FFFFFFFL -#define UINT_MAX32 0xFFFFFFFFL -#define INT_MIN24 (~0x007FFFFF) -#define INT_MAX24 0x007FFFFF -#define UINT_MAX24 0x00FFFFFF -#define INT_MIN16 (~0x7FFF) -#define INT_MAX16 0x7FFF -#define UINT_MAX16 0xFFFF -#define INT_MIN8 (~0x7F) -#define INT_MAX8 0x7F -#define UINT_MAX8 0xFF - -#ifndef SIZE_T_MAX -#define SIZE_T_MAX (~((size_t) 0)) -#endif - -// Our ifdef trickery for my_isfinite does not work with gcc/solaris unless we: -#ifdef HAVE_IEEEFP_H -#include -#endif - -#if (__cplusplus >= 201103L) - /* For C++11 use the new std functions rather than C99 macros. */ - #include - #define my_isfinite(X) std::isfinite(X) - #define my_isnan(X) std::isnan(X) - #define my_isinf(X) std::isinf(X) -#else - #ifdef HAVE_LLVM_LIBCPP /* finite is deprecated in libc++ */ - #define my_isfinite(X) isfinite(X) - #elif defined _WIN32 - #define my_isfinite(X) _finite(X) - #else - #define my_isfinite(X) finite(X) - #endif - #define my_isnan(X) isnan(X) - #ifdef HAVE_ISINF - /* System-provided isinf() is available and safe to use */ - #define my_isinf(X) isinf(X) - #else /* !HAVE_ISINF */ - #define my_isinf(X) (!my_isfinite(X) && !my_isnan(X)) - #endif -#endif /* __cplusplus >= 201103L */ - -/* - Max size that must be added to a so that we know Size to make - adressable obj. -*/ -#if SIZEOF_CHARP == 4 -typedef long my_ptrdiff_t; -#else -typedef long long my_ptrdiff_t; -#endif - -#define MY_ALIGN(A,L) (((A) + (L) - 1) & ~((L) - 1)) -#define ALIGN_SIZE(A) MY_ALIGN((A),sizeof(double)) -/* Size to make adressable obj. */ -#define ADD_TO_PTR(ptr,size,type) (type) ((uchar*) (ptr)+size) -#define PTR_BYTE_DIFF(A,B) (my_ptrdiff_t) ((uchar*) (A) - (uchar*) (B)) - -/* - Custom version of standard offsetof() macro which can be used to get - offsets of members in class for non-POD types (according to the current - version of C++ standard offsetof() macro can't be used in such cases and - attempt to do so causes warnings to be emitted, OTOH in many cases it is - still OK to assume that all instances of the class has the same offsets - for the same members). - - This is temporary solution which should be removed once File_parser class - and related routines are refactored. -*/ - -#define my_offsetof(TYPE, MEMBER) \ - ((size_t)((char *)&(((TYPE *)0x10)->MEMBER) - (char*)0x10)) - -#define NullS (char *) 0 - -#ifdef _WIN32 -#define STDCALL __stdcall -#else -#define STDCALL -#endif - -/* Typdefs for easyier portability */ - -typedef unsigned char uchar; /* Short for unsigned char */ -typedef signed char int8; /* Signed integer >= 8 bits */ -typedef unsigned char uint8; /* Unsigned integer >= 8 bits */ -typedef short int16; -typedef unsigned short uint16; -#if SIZEOF_INT == 4 -typedef int int32; -typedef unsigned int uint32; -#elif SIZEOF_LONG == 4 -typedef long int32; -typedef unsigned long uint32; -#else -#error Neither int or long is of 4 bytes width -#endif - -#if !defined(HAVE_ULONG) -typedef unsigned long ulong; /* Short for unsigned long */ -#endif -/* - Using [unsigned] long long is preferable as [u]longlong because we use - [unsigned] long long unconditionally in many places, - for example in constants with [U]LL suffix. -*/ -typedef unsigned long long int ulonglong; /* ulong or unsigned long long */ -typedef long long int longlong; -typedef longlong int64; -typedef ulonglong uint64; - -#if defined (_WIN32) -typedef unsigned __int64 my_ulonglong; -#else -typedef unsigned long long my_ulonglong; -#endif - -#if SIZEOF_CHARP == SIZEOF_INT -typedef int intptr; -#elif SIZEOF_CHARP == SIZEOF_LONG -typedef long intptr; -#elif SIZEOF_CHARP == SIZEOF_LONG_LONG -typedef long long intptr; -#else -#error sizeof(void *) is neither sizeof(int) nor sizeof(long) nor sizeof(long long) -#endif - -#define MY_ERRPTR ((void*)(intptr)1) - -#if defined(_WIN32) -typedef unsigned long long my_off_t; -typedef unsigned long long os_off_t; -#else -typedef off_t os_off_t; -#if SIZEOF_OFF_T > 4 -typedef ulonglong my_off_t; -#else -typedef unsigned long my_off_t; -#endif -#endif /*_WIN32*/ -#define MY_FILEPOS_ERROR (~(my_off_t) 0) - -/* - TODO Convert these to use Bitmap class. - */ -typedef ulonglong table_map; /* Used for table bits in join */ -typedef ulonglong nesting_map; /* Used for flags of nesting constructs */ - -#if defined(_WIN32) -#define socket_errno WSAGetLastError() -#define SOCKET_EINTR WSAEINTR -#define SOCKET_EAGAIN WSAEINPROGRESS -#define SOCKET_EWOULDBLOCK WSAEWOULDBLOCK -#define SOCKET_EADDRINUSE WSAEADDRINUSE -#define SOCKET_ETIMEDOUT WSAETIMEDOUT -#define SOCKET_ECONNRESET WSAECONNRESET -#define SOCKET_ENFILE ENFILE -#define SOCKET_EMFILE EMFILE -#else /* Unix */ -#define socket_errno errno -#define closesocket(A) close(A) -#define SOCKET_EINTR EINTR -#define SOCKET_EAGAIN EAGAIN -#define SOCKET_EWOULDBLOCK EWOULDBLOCK -#define SOCKET_EADDRINUSE EADDRINUSE -#define SOCKET_ETIMEDOUT ETIMEDOUT -#define SOCKET_ECONNRESET ECONNRESET -#define SOCKET_ENFILE ENFILE -#define SOCKET_EMFILE EMFILE -#endif - -typedef int myf; /* Type of MyFlags in my_funcs */ -typedef char my_bool; /* Small bool */ - -/* Macros for converting *constants* to the right type */ -#define MYF(v) (myf) (v) - -/* Some helper macros */ -#define YESNO(X) ((X) ? "yes" : "no") - -#define MY_HOW_OFTEN_TO_WRITE 1000 /* How often we want info on screen */ - -#include - -#ifdef HAVE_CHARSET_utf8 -#define MYSQL_UNIVERSAL_CLIENT_CHARSET "utf8" -#else -#define MYSQL_UNIVERSAL_CLIENT_CHARSET MYSQL_DEFAULT_CHARSET_NAME -#endif - -#if defined(_WIN32) -#define dlsym(lib, name) (void*)GetProcAddress((HMODULE)lib, name) -#define dlopen(libname, unused) LoadLibraryEx(libname, NULL, 0) -#define dlclose(lib) FreeLibrary((HMODULE)lib) -#ifndef HAVE_DLOPEN -#define HAVE_DLOPEN -#endif -#define DLERROR_GENERATE(errmsg, error_number) \ - char win_errormsg[2048]; \ - if(FormatMessage(FORMAT_MESSAGE_FROM_SYSTEM, \ - 0, error_number, 0, win_errormsg, 2048, NULL)) \ - { \ - char *ptr; \ - for (ptr= &win_errormsg[0] + strlen(win_errormsg) - 1; \ - ptr >= &win_errormsg[0] && strchr("\r\n\t\0x20", *ptr); \ - ptr--) \ - *ptr= 0; \ - errmsg= win_errormsg; \ - } \ - else \ - errmsg= "" -#define dlerror() "" -#define dlopen_errno GetLastError() - -#else /* _WIN32 */ -#define DLERROR_GENERATE(errmsg, error_number) errmsg= dlerror() -#define dlopen_errno errno -#endif /* _WIN32 */ - -/* Length of decimal number represented by INT32. */ -#define MY_INT32_NUM_DECIMAL_DIGITS 11U - -/* Length of decimal number represented by INT64. */ -#define MY_INT64_NUM_DECIMAL_DIGITS 21U - -/* Define some useful general macros (should be done after all headers). */ -#define MY_MAX(a, b) ((a) > (b) ? (a) : (b)) -#define MY_MIN(a, b) ((a) < (b) ? (a) : (b)) - -#if !defined(__cplusplus) && !defined(bool) -#define bool In_C_you_should_use_my_bool_instead() -#endif - -/* - MYSQL_PLUGIN_IMPORT macro is used to export mysqld data - (i.e variables) for usage in storage engine loadable plugins. - Outside of Windows, it is dummy. -*/ -#if (defined(_WIN32) && defined(MYSQL_DYNAMIC_PLUGIN)) -#define MYSQL_PLUGIN_IMPORT __declspec(dllimport) -#else -#define MYSQL_PLUGIN_IMPORT -#endif - -#include - -#ifdef EMBEDDED_LIBRARY -#define NO_EMBEDDED_ACCESS_CHECKS -/* Things we don't need in the embedded version of MySQL */ -#undef HAVE_OPENSSL -#endif /* EMBEDDED_LIBRARY */ - - -enum loglevel { - ERROR_LEVEL= 0, - WARNING_LEVEL= 1, - INFORMATION_LEVEL= 2 -}; - - -#ifdef _WIN32 -/**************************************************************************** -** Replacements for localtime_r and gmtime_r -****************************************************************************/ - -static inline struct tm *localtime_r(const time_t *timep, struct tm *tmp) -{ - localtime_s(tmp, timep); - return tmp; -} - -static inline struct tm *gmtime_r(const time_t *clock, struct tm *res) -{ - gmtime_s(res, clock); - return res; -} -#endif /* _WIN32 */ - -#ifndef HAVE_STRUCT_TIMESPEC /* Windows before VS2015 */ -/* - Declare a union to make sure FILETIME is properly aligned - so it can be used directly as a 64 bit value. The value - stored is in 100ns units. -*/ -union ft64 { - FILETIME ft; - __int64 i64; - }; - -struct timespec { - union ft64 tv; - /* The max timeout value in millisecond for native_cond_timedwait */ - long max_timeout_msec; -}; - -#endif /* !HAVE_STRUCT_TIMESPEC */ - -C_MODE_START -extern ulonglong my_getsystime(void); -C_MODE_END - -static inline void set_timespec_nsec(struct timespec *abstime, ulonglong nsec) -{ -#ifdef HAVE_STRUCT_TIMESPEC - ulonglong now= my_getsystime() + (nsec / 100); - ulonglong tv_sec= now / 10000000ULL; -#if SIZEOF_TIME_T < SIZEOF_LONG_LONG - /* Ensure that the number of seconds don't overflow. */ - tv_sec= MY_MIN(tv_sec, ((ulonglong)INT_MAX32)); -#endif - abstime->tv_sec= (time_t)tv_sec; - abstime->tv_nsec= (now % 10000000ULL) * 100 + (nsec % 100); -#else /* !HAVE_STRUCT_TIMESPEC */ - ulonglong max_timeout_msec= (nsec / 1000000); - union ft64 tv; - GetSystemTimeAsFileTime(&tv.ft); - abstime->tv.i64= tv.i64 + (__int64)(nsec / 100); -#if SIZEOF_LONG < SIZEOF_LONG_LONG - /* Ensure that the msec value doesn't overflow. */ - max_timeout_msec= MY_MIN(max_timeout_msec, ((ulonglong)INT_MAX32)); -#endif - abstime->max_timeout_msec= (long)max_timeout_msec; -#endif /* !HAVE_STRUCT_TIMESPEC */ -} - -static inline void set_timespec(struct timespec *abstime, ulonglong sec) -{ - set_timespec_nsec(abstime, sec * 1000000000ULL); -} - -/** - Compare two timespec structs. - - @retval 1 If ts1 ends after ts2. - @retval -1 If ts1 ends before ts2. - @retval 0 If ts1 is equal to ts2. -*/ -static inline int cmp_timespec(struct timespec *ts1, struct timespec *ts2) -{ -#ifdef HAVE_STRUCT_TIMESPEC - if (ts1->tv_sec > ts2->tv_sec || - (ts1->tv_sec == ts2->tv_sec && ts1->tv_nsec > ts2->tv_nsec)) - return 1; - if (ts1->tv_sec < ts2->tv_sec || - (ts1->tv_sec == ts2->tv_sec && ts1->tv_nsec < ts2->tv_nsec)) - return -1; -#else - if (ts1->tv.i64 > ts2->tv.i64) - return 1; - if (ts1->tv.i64 < ts2->tv.i64) - return -1; -#endif - return 0; -} - -static inline ulonglong diff_timespec(struct timespec *ts1, struct timespec *ts2) -{ -#ifdef HAVE_STRUCT_TIMESPEC - return (ts1->tv_sec - ts2->tv_sec) * 1000000000ULL + - ts1->tv_nsec - ts2->tv_nsec; -#else - return (ts1->tv.i64 - ts2->tv.i64) * 100; -#endif -} - -#ifdef _WIN32 -typedef int MY_MODE; -#else -typedef mode_t MY_MODE; -#endif /* _WIN32 */ - -/* File permissions */ -#define USER_READ (1L << 0) -#define USER_WRITE (1L << 1) -#define USER_EXECUTE (1L << 2) -#define GROUP_READ (1L << 3) -#define GROUP_WRITE (1L << 4) -#define GROUP_EXECUTE (1L << 5) -#define OTHERS_READ (1L << 6) -#define OTHERS_WRITE (1L << 7) -#define OTHERS_EXECUTE (1L << 8) -#define USER_RWX USER_READ | USER_WRITE | USER_EXECUTE -#define GROUP_RWX GROUP_READ | GROUP_WRITE | GROUP_EXECUTE -#define OTHERS_RWX OTHERS_READ | OTHERS_WRITE | OTHERS_EXECUTE - -/* Defaults */ -#define DEFAULT_SSL_CA_CERT "ca.pem" -#define DEFAULT_SSL_CA_KEY "ca-key.pem" -#define DEFAULT_SSL_SERVER_CERT "server-cert.pem" -#define DEFAULT_SSL_SERVER_KEY "server-key.pem" - -#if defined(_WIN32) || defined(_WIN64) - #define strcasecmp _stricmp -#endif -#endif // MY_GLOBAL_INCLUDED diff --git a/vendor/mysql/include/my_list.h b/vendor/mysql/include/my_list.h index 294be663d0..cc625f48fa 100644 --- a/vendor/mysql/include/my_list.h +++ b/vendor/mysql/include/my_list.h @@ -1,45 +1,53 @@ -/* Copyright (c) 2000, 2010, Oracle and/or its affiliates. All rights reserved. +/* Copyright (c) 2000, 2024, Oracle and/or its affiliates. This program is free software; you can redistribute it and/or modify - it under the terms of the GNU General Public License as published by - the Free Software Foundation; version 2 of the License. + it under the terms of the GNU General Public License, version 2.0, + as published by the Free Software Foundation. + + This program is designed to work with certain software (including + but not limited to OpenSSL) that is licensed under separate terms, + as designated in a particular file or component or in included license + documentation. The authors of MySQL hereby grant you an additional + permission to link the program and your derivative works with the + separately licensed software that they have either included with + the program or referenced in the documentation. + + Without limiting anything contained in the foregoing, this file, + which is part of C Driver for MySQL (Connector/C), is also subject to the + Universal FOSS Exception, version 1.0, a copy of which can be found at + http://oss.oracle.com/licenses/universal-foss-exception. This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - GNU General Public License for more details. + GNU General Public License, version 2.0, for more details. You should have received a copy of the GNU General Public License along with this program; if not, write to the Free Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA */ -#ifndef _list_h_ -#define _list_h_ +#ifndef MY_LIST_INCLUDED +#define MY_LIST_INCLUDED -#ifdef __cplusplus -extern "C" { -#endif +/** + @file include/my_list.h +*/ -typedef struct st_list { - struct st_list *prev,*next; +typedef struct LIST { + struct LIST *prev, *next; void *data; } LIST; -typedef int (*list_walk_action)(void *,void *); +typedef int (*list_walk_action)(void *, void *); -extern LIST *list_add(LIST *root,LIST *element); -extern LIST *list_delete(LIST *root,LIST *element); -extern LIST *list_cons(void *data,LIST *root); +extern LIST *list_add(LIST *root, LIST *element); +extern LIST *list_delete(LIST *root, LIST *element); +extern LIST *list_cons(void *data, LIST *root); extern LIST *list_reverse(LIST *root); -extern void list_free(LIST *root,unsigned int free_data); +extern void list_free(LIST *root, unsigned int free_data); extern unsigned int list_length(LIST *); -extern int list_walk(LIST *,list_walk_action action,unsigned char * argument); +extern int list_walk(LIST *, list_walk_action action, unsigned char *argument); #define list_rest(a) ((a)->next) -#define list_push(a,b) (a)=list_cons((b),(a)) -#define list_pop(A) {LIST *old=(A); (A)=list_delete(old,old); my_free(old); } -#ifdef __cplusplus -} -#endif -#endif +#endif // MY_LIST_INCLUDED diff --git a/vendor/mysql/include/my_sys.h b/vendor/mysql/include/my_sys.h deleted file mode 100644 index 29a1f34019..0000000000 --- a/vendor/mysql/include/my_sys.h +++ /dev/null @@ -1,960 +0,0 @@ -/* Copyright (c) 2000, 2016, Oracle and/or its affiliates. All rights reserved. - - This program is free software; you can redistribute it and/or modify - it under the terms of the GNU General Public License as published by - the Free Software Foundation; version 2 of the License. - - This program is distributed in the hope that it will be useful, - but WITHOUT ANY WARRANTY; without even the implied warranty of - MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - GNU General Public License for more details. - - You should have received a copy of the GNU General Public License - along with this program; if not, write to the Free Software - Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA */ - -#ifndef _my_sys_h -#define _my_sys_h - -#include "my_global.h" /* C_MODE_START, C_MODE_END */ -#include "m_ctype.h" /* for CHARSET_INFO */ - -#include "my_thread.h" /* Needed for psi.h */ -#include "mysql/psi/psi.h" -#include "mysql/service_mysql_alloc.h" -#include "mysql/psi/mysql_memory.h" -#include "mysql/psi/mysql_thread.h" - -#ifdef HAVE_ALLOCA_H -#include -#endif -#ifdef _WIN32 -#include -#endif -#ifdef HAVE_UNISTD_H -#include -#endif - -C_MODE_START - -#ifdef HAVE_VALGRIND -# include -# define MEM_MALLOCLIKE_BLOCK(p1, p2, p3, p4) VALGRIND_MALLOCLIKE_BLOCK(p1, p2, p3, p4) -# define MEM_FREELIKE_BLOCK(p1, p2) VALGRIND_FREELIKE_BLOCK(p1, p2) -# include -# define MEM_UNDEFINED(a,len) VALGRIND_MAKE_MEM_UNDEFINED(a,len) -# define MEM_NOACCESS(a,len) VALGRIND_MAKE_MEM_NOACCESS(a,len) -# define MEM_CHECK_ADDRESSABLE(a,len) VALGRIND_CHECK_MEM_IS_ADDRESSABLE(a,len) -#else /* HAVE_VALGRIND */ -# define MEM_MALLOCLIKE_BLOCK(p1, p2, p3, p4) do {} while (0) -# define MEM_FREELIKE_BLOCK(p1, p2) do {} while (0) -# define MEM_UNDEFINED(a,len) ((void) 0) -# define MEM_NOACCESS(a,len) ((void) 0) -# define MEM_CHECK_ADDRESSABLE(a,len) ((void) 0) -#endif /* HAVE_VALGRIND */ - -#include - -#define MY_INIT(name) { my_progname= name; my_init(); } - -/** - Max length of an error message generated by mysys utilities. - Some mysys functions produce error messages. These mostly go - to stderr. - This constant defines the size of the buffer used to format - the message. It should be kept in sync with MYSQL_ERRMSG_SIZE, - since sometimes mysys errors are stored in the server diagnostics - area, and we would like to avoid unexpected truncation. -*/ -#define MYSYS_ERRMSG_SIZE (512) -#define MYSYS_STRERROR_SIZE (128) - -#define MY_FILE_ERROR ((size_t) -1) - - /* General bitmaps for my_func's */ -#define MY_FFNF 1 /* Fatal if file not found */ -#define MY_FNABP 2 /* Fatal if not all bytes read/writen */ -#define MY_NABP 4 /* Error if not all bytes read/writen */ -#define MY_FAE 8 /* Fatal if any error */ -#define MY_WME 16 /* Write message on error */ -#define MY_WAIT_IF_FULL 32 /* Wait and try again if disk full error */ -#define MY_IGNORE_BADFD 32 /* my_sync: ignore 'bad descriptor' errors */ -#define MY_SYNC_DIR 8192 /* my_create/delete/rename: sync directory */ -#define MY_UNUSED 64 /* Unused (was support for RAID) */ -#define MY_FULL_IO 512 /* For my_read - loop intil I/O is complete */ -#define MY_DONT_CHECK_FILESIZE 128 /* Option to init_io_cache() */ -#define MY_LINK_WARNING 32 /* my_redel() gives warning if links */ -#define MY_COPYTIME 64 /* my_redel() copys time */ -#define MY_DELETE_OLD 256 /* my_create_with_symlink() */ -#define MY_RESOLVE_LINK 128 /* my_realpath(); Only resolve links */ -#define MY_HOLD_ORIGINAL_MODES 128 /* my_copy() holds to file modes */ -#define MY_REDEL_MAKE_BACKUP 256 -#define MY_REDEL_NO_COPY_STAT 512 /* my_redel() doesn't call my_copystat() */ -#define MY_SEEK_NOT_DONE 32 /* my_lock may have to do a seek */ -#define MY_DONT_WAIT 64 /* my_lock() don't wait if can't lock */ -#define MY_ZEROFILL 32 /* my_malloc(), fill array with zero */ -#define MY_ALLOW_ZERO_PTR 64 /* my_realloc() ; zero ptr -> malloc */ -#define MY_FREE_ON_ERROR 128 /* my_realloc() ; Free old ptr on error */ -#define MY_HOLD_ON_ERROR 256 /* my_realloc() ; Return old ptr on error */ -#define MY_DONT_OVERWRITE_FILE 1024 /* my_copy: Don't overwrite file */ -#define MY_THREADSAFE 2048 /* my_seek(): lock fd mutex */ -#define MY_SYNC 4096 /* my_copy(): sync dst file */ - -#define MYF_RW MYF(MY_WME+MY_NABP) /* For my_read & my_write */ - -#define MY_CHECK_ERROR 1 /* Params to my_end; Check open-close */ -#define MY_GIVE_INFO 2 /* Give time info about process*/ -#define MY_DONT_FREE_DBUG 4 /* Do not call DBUG_END() in my_end() */ - -/* Flags for my_error() */ -#define ME_BELL 4 /* DEPRECATED: Ring bell then printing message */ -#define ME_ERRORLOG 64 /* Write the error message to error log */ -#define ME_FATALERROR 1024 /* Fatal statement error */ - - /* Bits in last argument to fn_format */ -#define MY_REPLACE_DIR 1 /* replace dir in name with 'dir' */ -#define MY_REPLACE_EXT 2 /* replace extension with 'ext' */ -#define MY_UNPACK_FILENAME 4 /* Unpack name (~ -> home) */ -#define MY_PACK_FILENAME 8 /* Pack name (home -> ~) */ -#define MY_RESOLVE_SYMLINKS 16 /* Resolve all symbolic links */ -#define MY_RETURN_REAL_PATH 32 /* return full path for file */ -#define MY_SAFE_PATH 64 /* Return NULL if too long path */ -#define MY_RELATIVE_PATH 128 /* name is relative to 'dir' */ -#define MY_APPEND_EXT 256 /* add 'ext' as additional extension*/ - - - /* My seek flags */ -#define MY_SEEK_SET 0 -#define MY_SEEK_CUR 1 -#define MY_SEEK_END 2 - - /* Some constants */ -#define MY_WAIT_FOR_USER_TO_FIX_PANIC 60 /* in seconds */ -#define MY_WAIT_GIVE_USER_A_MESSAGE 10 /* Every 10 times of prev */ -#define MIN_COMPRESS_LENGTH 50 /* Don't compress small bl. */ -#define DFLT_INIT_HITS 3 - - /* root_alloc flags */ -#define MY_KEEP_PREALLOC 1 -#define MY_MARK_BLOCKS_FREE 2 /* move used to free list and reuse them */ - - /* Internal error numbers (for assembler functions) */ -#define MY_ERRNO_EDOM 33 -#define MY_ERRNO_ERANGE 34 - - /* Bits for get_date timeflag */ -#define GETDATE_DATE_TIME 1 -#define GETDATE_SHORT_DATE 2 -#define GETDATE_HHMMSSTIME 4 -#define GETDATE_GMT 8 -#define GETDATE_FIXEDLENGTH 16 - - /* defines when allocating data */ -extern void *my_multi_malloc(PSI_memory_key key, myf flags, ...); - -/* - Switch to my_malloc() if the memory block to be allocated is bigger than - max_alloca_sz. -*/ -extern PSI_memory_key key_memory_max_alloca; -#define my_safe_alloca(size, max_alloca_sz) ((size <= max_alloca_sz) ? \ - my_alloca(size) : \ - my_malloc(key_memory_max_alloca, size, MYF(0))) -#define my_safe_afree(ptr, size, max_alloca_sz) if (size > max_alloca_sz) \ - my_free(ptr) - -#if !defined(DBUG_OFF) || defined(HAVE_VALGRIND) -/** - Put bad content in memory to be sure it will segfault if dereferenced. - With Valgrind, verify that memory is addressable, and mark it undefined. - We cache value of B because if B is expression which depends on A, memset() - trashes value of B. -*/ -#define TRASH(A,B) do { \ - const size_t l= (B); \ - MEM_CHECK_ADDRESSABLE(A, l); \ - memset(A, 0x8F, l); \ - MEM_UNDEFINED(A, l); \ - } while (0) -#else -#define TRASH(A,B) do {} while(0) -#endif -#if defined(ENABLED_DEBUG_SYNC) -extern void (*debug_sync_C_callback_ptr)(const char *, size_t); -#define DEBUG_SYNC_C(_sync_point_name_) do { \ - if (debug_sync_C_callback_ptr != NULL) \ - (*debug_sync_C_callback_ptr)(STRING_WITH_LEN(_sync_point_name_)); } \ - while(0) -#define DEBUG_SYNC_C_IF_THD(thd, _sync_point_name_) do { \ - if (debug_sync_C_callback_ptr != NULL && thd) \ - (*debug_sync_C_callback_ptr)(STRING_WITH_LEN(_sync_point_name_)); } \ - while(0) -#else -#define DEBUG_SYNC_C(_sync_point_name_) -#define DEBUG_SYNC_C_IF_THD(thd, _sync_point_name_) -#endif /* defined(ENABLED_DEBUG_SYNC) */ - -#ifdef HAVE_LINUX_LARGE_PAGES -extern uint my_get_large_page_size(void); -extern uchar * my_large_malloc(PSI_memory_key key, size_t size, myf my_flags); -extern void my_large_free(uchar *ptr); -extern my_bool my_use_large_pages; -extern uint my_large_page_size; -#else -#define my_get_large_page_size() (0) -#define my_large_malloc(A,B,C) my_malloc((A),(B),(C)) -#define my_large_free(A) my_free((A)) -#endif /* HAVE_LINUX_LARGE_PAGES */ - -#define my_alloca(SZ) alloca((size_t) (SZ)) - -#include /* errno is a define */ - -extern char *home_dir; /* Home directory for user */ -extern const char *my_progname; /* program-name (printed in errors) */ -extern char curr_dir[]; /* Current directory for user */ -extern void (*error_handler_hook)(uint my_err, const char *str,myf MyFlags); -extern void (*fatal_error_handler_hook)(uint my_err, const char *str, - myf MyFlags); -extern void (*local_message_hook)(enum loglevel ll, - const char *format, va_list args); -extern uint my_file_limit; -extern MYSQL_PLUGIN_IMPORT ulong my_thread_stack_size; - -/* - Hooks for reporting execution stage information. The server implementation - of these will also set THD::current_cond/current_mutex. - By having hooks, we avoid direct dependencies on server code. -*/ -extern void (*enter_cond_hook)(void *opaque_thd, - mysql_cond_t *cond, - mysql_mutex_t *mutex, - const PSI_stage_info *stage, - PSI_stage_info *old_stage, - const char *src_function, - const char *src_file, - int src_line); - -extern void (*exit_cond_hook)(void *opaque_thd, - const PSI_stage_info *stage, - const char *src_function, - const char *src_file, - int src_line); - -/* - Hook for checking if the thread has been killed. -*/ -extern int (*is_killed_hook)(const void *opaque_thd); - -/* charsets */ -#define MY_ALL_CHARSETS_SIZE 2048 -extern MYSQL_PLUGIN_IMPORT CHARSET_INFO *default_charset_info; -extern MYSQL_PLUGIN_IMPORT CHARSET_INFO *all_charsets[MY_ALL_CHARSETS_SIZE]; -extern CHARSET_INFO compiled_charsets[]; - -/* statistics */ -extern ulong my_file_opened,my_stream_opened, my_tmp_file_created; -extern ulong my_file_total_opened; -extern my_bool my_init_done; - -extern MYSQL_PLUGIN_IMPORT int my_umask; /* Default creation mask */ -extern int my_umask_dir; - -extern ulong my_default_record_cache_size; -extern my_bool my_disable_locking, - my_enable_symlinks; -extern char wild_many,wild_one,wild_prefix; -extern const char *charsets_dir; - -enum cache_type -{ - TYPE_NOT_SET= 0, READ_CACHE, WRITE_CACHE, - SEQ_READ_APPEND /* sequential read or append */, - READ_FIFO, READ_NET,WRITE_NET}; - -enum flush_type -{ - FLUSH_KEEP, /* flush block and keep it in the cache */ - FLUSH_RELEASE, /* flush block and remove it from the cache */ - FLUSH_IGNORE_CHANGED, /* remove block from the cache */ - /* - As my_disable_flush_pagecache_blocks is always 0, the following option - is strictly equivalent to FLUSH_KEEP - */ - FLUSH_FORCE_WRITE -}; - -enum file_type -{ - UNOPEN = 0, FILE_BY_OPEN, FILE_BY_CREATE, STREAM_BY_FOPEN, STREAM_BY_FDOPEN, - FILE_BY_MKSTEMP, FILE_BY_DUP -}; - -struct st_my_file_info -{ - char *name; -#ifdef _WIN32 - HANDLE fhandle; /* win32 file handle */ - int oflag; /* open flags, e.g O_APPEND */ -#endif - enum file_type type; -}; - -extern struct st_my_file_info *my_file_info; - -/* needed for client-only build */ -#ifndef PSI_FILE_KEY_DEFINED -typedef unsigned int PSI_file_key; -#define PSI_FILE_KEY_DEFINED -#endif - -typedef struct st_dynamic_array -{ - uchar *buffer; - uint elements,max_element; - uint alloc_increment; - uint size_of_element; - PSI_memory_key m_psi_key; -} DYNAMIC_ARRAY; - -typedef struct st_my_tmpdir -{ - char **list; - uint cur, max; - mysql_mutex_t mutex; -} MY_TMPDIR; - -typedef struct st_dynamic_string -{ - char *str; - size_t length,max_length,alloc_increment; -} DYNAMIC_STRING; - -struct st_io_cache; -typedef int (*IO_CACHE_CALLBACK)(struct st_io_cache*); - -typedef struct st_io_cache_share -{ - mysql_mutex_t mutex; /* To sync on reads into buffer. */ - mysql_cond_t cond; /* To wait for signals. */ - mysql_cond_t cond_writer; /* For a synchronized writer. */ - /* Offset in file corresponding to the first byte of buffer. */ - my_off_t pos_in_file; - /* If a synchronized write cache is the source of the data. */ - struct st_io_cache *source_cache; - uchar *buffer; /* The read buffer. */ - uchar *read_end; /* Behind last valid byte of buffer. */ - int running_threads; /* threads not in lock. */ - int total_threads; /* threads sharing the cache. */ - int error; /* Last error. */ -} IO_CACHE_SHARE; - -typedef struct st_io_cache /* Used when cacheing files */ -{ - /* Offset in file corresponding to the first byte of uchar* buffer. */ - my_off_t pos_in_file; - /* - The offset of end of file for READ_CACHE and WRITE_CACHE. - For SEQ_READ_APPEND it the maximum of the actual end of file and - the position represented by read_end. - */ - my_off_t end_of_file; - /* Points to current read position in the buffer */ - uchar *read_pos; - /* the non-inclusive boundary in the buffer for the currently valid read */ - uchar *read_end; - uchar *buffer; /* The read buffer */ - /* Used in ASYNC_IO */ - uchar *request_pos; - - /* Only used in WRITE caches and in SEQ_READ_APPEND to buffer writes */ - uchar *write_buffer; - /* - Only used in SEQ_READ_APPEND, and points to the current read position - in the write buffer. Note that reads in SEQ_READ_APPEND caches can - happen from both read buffer (uchar* buffer) and write buffer - (uchar* write_buffer). - */ - uchar *append_read_pos; - /* Points to current write position in the write buffer */ - uchar *write_pos; - /* The non-inclusive boundary of the valid write area */ - uchar *write_end; - - /* - Current_pos and current_end are convenience variables used by - my_b_tell() and other routines that need to know the current offset - current_pos points to &write_pos, and current_end to &write_end in a - WRITE_CACHE, and &read_pos and &read_end respectively otherwise - */ - uchar **current_pos, **current_end; - - /* - The lock is for append buffer used in SEQ_READ_APPEND cache - need mutex copying from append buffer to read buffer. - */ - mysql_mutex_t append_buffer_lock; - /* - The following is used when several threads are reading the - same file in parallel. They are synchronized on disk - accesses reading the cached part of the file asynchronously. - It should be set to NULL to disable the feature. Only - READ_CACHE mode is supported. - */ - IO_CACHE_SHARE *share; - - /* - A caller will use my_b_read() macro to read from the cache - if the data is already in cache, it will be simply copied with - memcpy() and internal variables will be accordinging updated with - no functions invoked. However, if the data is not fully in the cache, - my_b_read() will call read_function to fetch the data. read_function - must never be invoked directly. - */ - int (*read_function)(struct st_io_cache *,uchar *,size_t); - /* - Same idea as in the case of read_function, except my_b_write() needs to - be replaced with my_b_append() for a SEQ_READ_APPEND cache - */ - int (*write_function)(struct st_io_cache *,const uchar *,size_t); - /* - Specifies the type of the cache. Depending on the type of the cache - certain operations might not be available and yield unpredicatable - results. Details to be documented later - */ - enum cache_type type; - /* - Callbacks when the actual read I/O happens. These were added and - are currently used for binary logging of LOAD DATA INFILE - when a - block is read from the file, we create a block create/append event, and - when IO_CACHE is closed, we create an end event. These functions could, - of course be used for other things - */ - IO_CACHE_CALLBACK pre_read; - IO_CACHE_CALLBACK post_read; - IO_CACHE_CALLBACK pre_close; - /* - Counts the number of times, when we were forced to use disk. We use it to - increase the binlog_cache_disk_use and binlog_stmt_cache_disk_use status - variables. - */ - ulong disk_writes; - void* arg; /* for use by pre/post_read */ - char *file_name; /* if used with 'open_cached_file' */ - char *dir,*prefix; - File file; /* file descriptor */ - PSI_file_key file_key; /* instrumented file key */ - - /* - seek_not_done is set by my_b_seek() to inform the upcoming read/write - operation that a seek needs to be preformed prior to the actual I/O - error is 0 if the cache operation was successful, -1 if there was a - "hard" error, and the actual number of I/O-ed bytes if the read/write was - partial. - */ - int seek_not_done,error; - /* buffer_length is memory size allocated for buffer or write_buffer */ - size_t buffer_length; - /* read_length is the same as buffer_length except when we use async io */ - size_t read_length; - myf myflags; /* Flags used to my_read/my_write */ - /* - alloced_buffer is 1 if the buffer was allocated by init_io_cache() and - 0 if it was supplied by the user. - Currently READ_NET is the only one that will use a buffer allocated - somewhere else - */ - my_bool alloced_buffer; -} IO_CACHE; - -typedef int (*qsort2_cmp)(const void *, const void *, const void *); - -typedef void (*my_error_reporter)(enum loglevel level, const char *format, ...) - MY_ATTRIBUTE((format(printf, 2, 3))); - -extern my_error_reporter my_charset_error_reporter; - -/* defines for mf_iocache */ -extern PSI_file_key key_file_io_cache; - -/* Test if buffer is inited */ -#define my_b_clear(info) (info)->buffer=0 -#define my_b_inited(info) (info)->buffer -#define my_b_EOF INT_MIN - -#define my_b_read(info,Buffer,Count) \ - ((info)->read_pos + (Count) <= (info)->read_end ?\ - (memcpy(Buffer,(info)->read_pos,(size_t) (Count)), \ - ((info)->read_pos+=(Count)),0) :\ - (*(info)->read_function)((info),Buffer,Count)) - -#define my_b_write(info,Buffer,Count) \ - ((info)->write_pos + (Count) <=(info)->write_end ?\ - (memcpy((info)->write_pos, (Buffer), (size_t)(Count)),\ - ((info)->write_pos+=(Count)),0) : \ - (*(info)->write_function)((info),(uchar *)(Buffer),(Count))) - -#define my_b_get(info) \ - ((info)->read_pos != (info)->read_end ?\ - ((info)->read_pos++, (int) (uchar) (info)->read_pos[-1]) :\ - _my_b_get(info)) - -#define my_b_tell(info) ((info)->pos_in_file + \ - (size_t) (*(info)->current_pos - (info)->request_pos)) - -#define my_b_get_buffer_start(info) (info)->request_pos -#define my_b_get_bytes_in_buffer(info) (char*) (info)->read_end - \ - (char*) my_b_get_buffer_start(info) -#define my_b_get_pos_in_file(info) (info)->pos_in_file - -/* tell write offset in the SEQ_APPEND cache */ -int my_b_copy_to_file(IO_CACHE *cache, FILE *file); -my_off_t my_b_append_tell(IO_CACHE* info); -my_off_t my_b_safe_tell(IO_CACHE* info); /* picks the correct tell() */ - -#define my_b_bytes_in_cache(info) (size_t) (*(info)->current_end - \ - *(info)->current_pos) - -typedef uint32 ha_checksum; - -#include - - - /* Prototypes for mysys and my_func functions */ - -extern int my_copy(const char *from,const char *to,myf MyFlags); -extern int my_delete(const char *name,myf MyFlags); -extern int my_getwd(char * buf,size_t size,myf MyFlags); -extern int my_setwd(const char *dir,myf MyFlags); -extern int my_lock(File fd,int op,my_off_t start, my_off_t length,myf MyFlags); -extern void *my_once_alloc(size_t Size,myf MyFlags); -extern void my_once_free(void); -extern char *my_once_strdup(const char *src,myf myflags); -extern void *my_once_memdup(const void *src, size_t len, myf myflags); -extern File my_open(const char *FileName,int Flags,myf MyFlags); -extern File my_register_filename(File fd, const char *FileName, - enum file_type type_of_file, - uint error_message_number, myf MyFlags); -extern File my_create(const char *FileName,int CreateFlags, - int AccessFlags, myf MyFlags); -extern int my_close(File Filedes,myf MyFlags); -extern int my_mkdir(const char *dir, int Flags, myf MyFlags); -extern int my_readlink(char *to, const char *filename, myf MyFlags); -extern int my_is_symlink(const char *filename); -extern int my_realpath(char *to, const char *filename, myf MyFlags); -extern File my_create_with_symlink(const char *linkname, const char *filename, - int createflags, int access_flags, - myf MyFlags); -extern int my_delete_with_symlink(const char *name, myf MyFlags); -extern int my_rename_with_symlink(const char *from,const char *to,myf MyFlags); -extern int my_symlink(const char *content, const char *linkname, myf MyFlags); -extern size_t my_read(File Filedes,uchar *Buffer,size_t Count,myf MyFlags); -extern size_t my_pread(File Filedes,uchar *Buffer,size_t Count,my_off_t offset, - myf MyFlags); -extern int my_rename(const char *from,const char *to,myf MyFlags); -extern my_off_t my_seek(File fd,my_off_t pos,int whence,myf MyFlags); -extern my_off_t my_tell(File fd,myf MyFlags); -extern size_t my_write(File Filedes,const uchar *Buffer,size_t Count, - myf MyFlags); -extern size_t my_pwrite(File Filedes,const uchar *Buffer,size_t Count, - my_off_t offset,myf MyFlags); -extern size_t my_fread(FILE *stream,uchar *Buffer,size_t Count,myf MyFlags); -extern size_t my_fwrite(FILE *stream,const uchar *Buffer,size_t Count, - myf MyFlags); -extern my_off_t my_fseek(FILE *stream,my_off_t pos,int whence,myf MyFlags); -extern my_off_t my_ftell(FILE *stream,myf MyFlags); - -/* implemented in my_syslog.c */ - -// Maximum size of message that will be logged. -#define MAX_SYSLOG_MESSAGE_SIZE 1024 - -/* Platform-independent SysLog support */ - -/* facilities on unixoid syslog. harmless on systemd / Win platforms. */ -typedef struct st_syslog_facility { int id; const char *name; } SYSLOG_FACILITY; -extern SYSLOG_FACILITY syslog_facility[]; - -enum my_syslog_options { MY_SYSLOG_PIDS= 1 }; - -int my_openlog(const char *eventSourceName, int option, int facility); -int my_closelog(); -int my_syslog(const CHARSET_INFO *cs, enum loglevel level, const char *msg); - -/* implemented in my_memmem.c */ -extern void *my_memmem(const void *haystack, size_t haystacklen, - const void *needle, size_t needlelen); - - -#ifdef _WIN32 -extern int my_access(const char *path, int amode); -#else -#define my_access access -#endif - -extern int check_if_legal_filename(const char *path); -extern int check_if_legal_tablename(const char *path); - -#ifdef _WIN32 -extern my_bool is_filename_allowed(const char *name, size_t length, - my_bool allow_current_dir); -#else /* _WIN32 */ -# define is_filename_allowed(name, length, allow_cwd) (TRUE) -#endif /* _WIN32 */ - -#ifdef _WIN32 -extern int nt_share_delete(const char *name,myf MyFlags); -#define my_delete_allow_opened(fname,flags) nt_share_delete((fname),(flags)) -#else -#define my_delete_allow_opened(fname,flags) my_delete((fname),(flags)) -#endif - -#ifdef _WIN32 -/* Windows-only functions (CRT equivalents)*/ -extern HANDLE my_get_osfhandle(File fd); -extern void my_osmaperr(unsigned long last_error); -#endif - -extern const char* get_global_errmsg(int nr); -extern void wait_for_free_space(const char *filename, int errors); -extern FILE *my_fopen(const char *FileName,int Flags,myf MyFlags); -extern FILE *my_fdopen(File Filedes,const char *name, int Flags,myf MyFlags); -extern FILE *my_freopen(const char *path, const char *mode, FILE *stream); -extern int my_fclose(FILE *fd,myf MyFlags); -extern File my_fileno(FILE *fd); -extern int my_chsize(File fd,my_off_t newlength, int filler, myf MyFlags); -extern void thr_set_sync_wait_callback(void (*before_sync)(void), - void (*after_sync)(void)); -extern int my_sync(File fd, myf my_flags); -extern int my_sync_dir(const char *dir_name, myf my_flags); -extern int my_sync_dir_by_file(const char *file_name, myf my_flags); -extern char *my_strerror(char *buf, size_t len, int errnum); -extern const char *my_get_err_msg(int nr); -extern void my_error(int nr,myf MyFlags, ...); -extern void my_printf_error(uint my_err, const char *format, - myf MyFlags, ...) - MY_ATTRIBUTE((format(printf, 2, 4))); -extern void my_printv_error(uint error, const char *format, myf MyFlags, - va_list ap); -extern int my_error_register(const char* (*get_errmsg) (int), - int first, int last); -extern my_bool my_error_unregister(int first, int last); -extern void my_message(uint my_err, const char *str,myf MyFlags); -extern void my_message_stderr(uint my_err, const char *str, myf MyFlags); -void my_message_local_stderr(enum loglevel ll, - const char *format, va_list args); -extern void my_message_local(enum loglevel ll, const char *format, ...); -extern my_bool my_init(void); -extern void my_end(int infoflag); -extern int my_redel(const char *from, const char *to, int MyFlags); -extern int my_copystat(const char *from, const char *to, int MyFlags); -extern char * my_filename(File fd); -extern MY_MODE get_file_perm(ulong perm_flags); -extern my_bool my_chmod(const char *filename, ulong perm_flags, myf my_flags); - -#ifdef EXTRA_DEBUG -void my_print_open_files(void); -#else -#define my_print_open_files() -#endif - -extern my_bool init_tmpdir(MY_TMPDIR *tmpdir, const char *pathlist); -extern char *my_tmpdir(MY_TMPDIR *tmpdir); -extern void free_tmpdir(MY_TMPDIR *tmpdir); - -extern size_t dirname_part(char * to,const char *name, size_t *to_res_length); -extern size_t dirname_length(const char *name); -#define base_name(A) (A+dirname_length(A)) -extern int test_if_hard_path(const char *dir_name); -extern my_bool has_path(const char *name); -extern char *convert_dirname(char *to, const char *from, const char *from_end); -extern void to_unix_path(char * name); -extern char * fn_ext(const char *name); -extern char * fn_same(char * toname,const char *name,int flag); -extern char * fn_format(char * to,const char *name,const char *dir, - const char *form, uint flag); -extern size_t strlength(const char *str); -extern void pack_dirname(char * to,const char *from); -extern size_t normalize_dirname(char * to, const char *from); -extern size_t unpack_dirname(char * to,const char *from); -extern size_t cleanup_dirname(char * to,const char *from); -extern size_t system_filename(char * to,const char *from); -extern size_t unpack_filename(char * to,const char *from); -extern char * intern_filename(char * to,const char *from); -extern char * directory_file_name(char * dst, const char *src); -extern int pack_filename(char * to, const char *name, size_t max_length); -extern char * my_path(char * to,const char *progname, - const char *own_pathname_part); -extern char * my_load_path(char * to, const char *path, - const char *own_path_prefix); -extern int wild_compare(const char *str,const char *wildstr, - pbool str_is_pattern); -extern my_bool array_append_string_unique(const char *str, - const char **array, size_t size); -extern void get_date(char * to,int timeflag,time_t use_time); -extern void soundex(CHARSET_INFO *, char * out_pntr, char * in_pntr, - pbool remove_garbage); - -extern my_bool radixsort_is_appliccable(uint n_items, size_t size_of_element); -extern void radixsort_for_str_ptr(uchar* base[], uint number_of_elements, - size_t size_of_element,uchar *buffer[]); -extern void my_qsort(void *base_ptr, size_t total_elems, size_t size, - qsort_cmp cmp); -extern void my_qsort2(void *base_ptr, size_t total_elems, size_t size, - qsort2_cmp cmp, const void *cmp_argument); -void my_store_ptr(uchar *buff, size_t pack_length, my_off_t pos); -my_off_t my_get_ptr(uchar *ptr, size_t pack_length); -extern int init_io_cache_ext(IO_CACHE *info,File file,size_t cachesize, - enum cache_type type,my_off_t seek_offset, - pbool use_async_io, myf cache_myflags, - PSI_file_key file_key); -extern int init_io_cache(IO_CACHE *info,File file,size_t cachesize, - enum cache_type type,my_off_t seek_offset, - pbool use_async_io, myf cache_myflags); -extern my_bool reinit_io_cache(IO_CACHE *info,enum cache_type type, - my_off_t seek_offset,pbool use_async_io, - pbool clear_cache); -extern void setup_io_cache(IO_CACHE* info); -extern int _my_b_read(IO_CACHE *info,uchar *Buffer,size_t Count); -extern int _my_b_read_r(IO_CACHE *info,uchar *Buffer,size_t Count); -extern void init_io_cache_share(IO_CACHE *read_cache, IO_CACHE_SHARE *cshare, - IO_CACHE *write_cache, uint num_threads); -extern void remove_io_thread(IO_CACHE *info); -extern int _my_b_seq_read(IO_CACHE *info,uchar *Buffer,size_t Count); -extern int _my_b_net_read(IO_CACHE *info,uchar *Buffer,size_t Count); -extern int _my_b_get(IO_CACHE *info); -extern int _my_b_write(IO_CACHE *info,const uchar *Buffer,size_t Count); -extern int my_b_append(IO_CACHE *info,const uchar *Buffer,size_t Count); -extern int my_b_safe_write(IO_CACHE *info,const uchar *Buffer,size_t Count); - -extern int my_block_write(IO_CACHE *info, const uchar *Buffer, - size_t Count, my_off_t pos); -extern int my_b_flush_io_cache(IO_CACHE *info, int need_append_buffer_lock); - -#define flush_io_cache(info) my_b_flush_io_cache((info),1) - -extern int end_io_cache(IO_CACHE *info); -extern size_t my_b_fill(IO_CACHE *info); -extern void my_b_seek(IO_CACHE *info,my_off_t pos); -extern size_t my_b_gets(IO_CACHE *info, char *to, size_t max_length); -extern my_off_t my_b_filelength(IO_CACHE *info); -extern size_t my_b_printf(IO_CACHE *info, const char* fmt, ...) - MY_ATTRIBUTE((format(printf, 2, 3))); -extern size_t my_b_vprintf(IO_CACHE *info, const char* fmt, va_list ap); -extern my_bool open_cached_file(IO_CACHE *cache,const char *dir, - const char *prefix, size_t cache_size, - myf cache_myflags); -extern my_bool real_open_cached_file(IO_CACHE *cache); -extern void close_cached_file(IO_CACHE *cache); -File create_temp_file(char *to, const char *dir, const char *pfx, - int mode, myf MyFlags); - -// Use Prealloced_array or std::vector or something similar in C++ -#if defined(__cplusplus) - -#define init_dynamic_array please_use_an_appropriately_typed_container -#define my_init_dynamic_array please_use_an_appropriately_typed_container - -#else - -extern my_bool my_init_dynamic_array(DYNAMIC_ARRAY *array, - PSI_memory_key key, - uint element_size, - void *init_buffer, - uint init_alloc, - uint alloc_increment); -/* init_dynamic_array() function is deprecated */ -extern my_bool init_dynamic_array(DYNAMIC_ARRAY *array, uint element_size, - uint init_alloc, uint alloc_increment); -#define dynamic_element(array,array_index,type) \ - ((type)((array)->buffer) +(array_index)) - -#endif /* __cplusplus */ - -/* Some functions are still in use in C++, because HASH uses DYNAMIC_ARRAY */ -extern my_bool insert_dynamic(DYNAMIC_ARRAY *array, const void *element); -extern void *alloc_dynamic(DYNAMIC_ARRAY *array); -extern void *pop_dynamic(DYNAMIC_ARRAY*); -extern void get_dynamic(DYNAMIC_ARRAY *array, void *element, uint array_index); -extern void claim_dynamic(DYNAMIC_ARRAY *array); -extern void delete_dynamic(DYNAMIC_ARRAY *array); -extern void freeze_size(DYNAMIC_ARRAY *array); -static inline void reset_dynamic(DYNAMIC_ARRAY *array) -{ - array->elements= 0; -} - -extern my_bool init_dynamic_string(DYNAMIC_STRING *str, const char *init_str, - size_t init_alloc,size_t alloc_increment); -extern my_bool dynstr_append(DYNAMIC_STRING *str, const char *append); -my_bool dynstr_append_mem(DYNAMIC_STRING *str, const char *append, - size_t length); -extern my_bool dynstr_append_os_quoted(DYNAMIC_STRING *str, const char *append, - ...); -extern my_bool dynstr_set(DYNAMIC_STRING *str, const char *init_str); -extern my_bool dynstr_realloc(DYNAMIC_STRING *str, size_t additional_size); -extern my_bool dynstr_trunc(DYNAMIC_STRING *str, size_t n); -extern void dynstr_free(DYNAMIC_STRING *str); -#define alloc_root_inited(A) ((A)->min_malloc != 0) -#define ALLOC_ROOT_MIN_BLOCK_SIZE (MALLOC_OVERHEAD + sizeof(USED_MEM) + 8) -#define clear_alloc_root(A) do { (A)->free= (A)->used= (A)->pre_alloc= 0; (A)->min_malloc=0;} while(0) -extern void init_alloc_root(PSI_memory_key key, - MEM_ROOT *mem_root, size_t block_size, - size_t pre_alloc_size); -extern void *alloc_root(MEM_ROOT *mem_root, size_t Size); -extern void *multi_alloc_root(MEM_ROOT *mem_root, ...); -extern void claim_root(MEM_ROOT *root); -extern void free_root(MEM_ROOT *root, myf MyFLAGS); -extern void reset_root_defaults(MEM_ROOT *mem_root, size_t block_size, - size_t prealloc_size); -extern char *strdup_root(MEM_ROOT *root,const char *str); -static inline char *safe_strdup_root(MEM_ROOT *root, const char *str) -{ - return str ? strdup_root(root, str) : 0; -} -extern char *strmake_root(MEM_ROOT *root,const char *str,size_t len); -extern void *memdup_root(MEM_ROOT *root,const void *str, size_t len); -extern my_bool my_compress(uchar *, size_t *, size_t *); -extern my_bool my_uncompress(uchar *, size_t , size_t *); -extern uchar *my_compress_alloc(const uchar *packet, size_t *len, - size_t *complen); -extern int packfrm(uchar *, size_t, uchar **, size_t *); -extern int unpackfrm(uchar **, size_t *, const uchar *); - -extern ha_checksum my_checksum(ha_checksum crc, const uchar *mem, - size_t count); - -/* Wait a given number of microseconds */ -static inline void my_sleep(time_t m_seconds) -{ -#if defined(_WIN32) - Sleep((DWORD)m_seconds/1000+1); /* Sleep() has millisecond arg */ -#else - struct timeval t; - t.tv_sec= m_seconds / 1000000L; - t.tv_usec= m_seconds % 1000000L; - select(0,0,0,0,&t); /* sleep */ -#endif -} - -extern ulong crc32(ulong crc, const uchar *buf, uint len); -extern uint my_set_max_open_files(uint files); -void my_free_open_file_info(void); - -extern time_t my_time(myf flags); -extern ulonglong my_getsystime(void); -extern ulonglong my_micro_time(); -extern my_bool my_gethwaddr(uchar *to); - -#ifdef HAVE_SYS_MMAN_H -#include - -#ifndef MAP_NOSYNC -#define MAP_NOSYNC 0 -#endif - -#ifdef HAVE_MMAP64 -#define my_mmap(a,b,c,d,e,f) mmap64(a,b,c,d,e,f) -#else -#define my_mmap(a,b,c,d,e,f) mmap(a,b,c,d,e,f) -#endif -#define my_munmap(a,b) munmap((a),(b)) - -#else -/* not a complete set of mmap() flags, but only those that nesessary */ -#define PROT_READ 1 -#define PROT_WRITE 2 -#define MAP_NORESERVE 0 -#define MAP_SHARED 0x0001 -#define MAP_PRIVATE 0x0002 -#define MAP_NOSYNC 0x0800 -#define MAP_FAILED ((void *)-1) -#define MS_SYNC 0x0000 - -void *my_mmap(void *, size_t, int, int, int, my_off_t); -int my_munmap(void *, size_t); -#endif - -/* my_getpagesize */ -static inline int my_getpagesize() -{ -#ifndef _WIN32 - return getpagesize(); -#else - SYSTEM_INFO si; - GetSystemInfo(&si); - return (int)si.dwPageSize; -#endif -} - -int my_msync(int, void *, size_t, int); - -/* character sets */ -extern void my_charset_loader_init_mysys(MY_CHARSET_LOADER *loader); -extern uint get_charset_number(const char *cs_name, uint cs_flags); -extern uint get_collation_number(const char *name); -extern const char *get_charset_name(uint cs_number); - -extern CHARSET_INFO *get_charset(uint cs_number, myf flags); -extern CHARSET_INFO *get_charset_by_name(const char *cs_name, myf flags); -extern CHARSET_INFO *my_collation_get_by_name(MY_CHARSET_LOADER *loader, - const char *name, myf flags); -extern CHARSET_INFO *get_charset_by_csname(const char *cs_name, - uint cs_flags, myf my_flags); -extern CHARSET_INFO *my_charset_get_by_name(MY_CHARSET_LOADER *loader, - const char *name, - uint cs_flags, myf my_flags); -extern my_bool resolve_charset(const char *cs_name, - const CHARSET_INFO *default_cs, - const CHARSET_INFO **cs); -extern my_bool resolve_collation(const char *cl_name, - const CHARSET_INFO *default_cl, - const CHARSET_INFO **cl); -extern void free_charsets(void); -extern char *get_charsets_dir(char *buf); -extern my_bool my_charset_same(const CHARSET_INFO *cs1, - const CHARSET_INFO *cs2); -extern my_bool init_compiled_charsets(myf flags); -extern void add_compiled_collation(CHARSET_INFO *cs); -extern size_t escape_string_for_mysql(const CHARSET_INFO *charset_info, - char *to, size_t to_length, - const char *from, size_t length); -#ifdef _WIN32 -/* File system character set */ -extern CHARSET_INFO *fs_character_set(void); -#endif -extern size_t escape_quotes_for_mysql(CHARSET_INFO *charset_info, - char *to, size_t to_length, - const char *from, size_t length, char quote); -#ifdef _WIN32 -extern my_bool have_tcpip; /* Is set if tcpip is used */ - -/* implemented in my_windac.c */ - -int my_security_attr_create(SECURITY_ATTRIBUTES **psa, const char **perror, - DWORD owner_rights, DWORD everybody_rights); - -void my_security_attr_free(SECURITY_ATTRIBUTES *sa); - -/* implemented in my_conio.c */ -my_bool my_win_is_console(FILE *file); -char *my_win_console_readline(const CHARSET_INFO *cs, char *mbbuf, size_t mbbufsize, - size_t *nread); -void my_win_console_write(const CHARSET_INFO *cs, const char *data, size_t datalen); -void my_win_console_fputs(const CHARSET_INFO *cs, const char *data); -void my_win_console_putc(const CHARSET_INFO *cs, int c); -void my_win_console_vfprintf(const CHARSET_INFO *cs, const char *fmt, va_list args); -int my_win_translate_command_line_args(const CHARSET_INFO *cs, int *ac, char ***av); -#endif /* _WIN32 */ - -#ifdef HAVE_PSI_INTERFACE -extern MYSQL_PLUGIN_IMPORT struct PSI_bootstrap *PSI_hook; -extern void set_psi_server(PSI *psi); -void my_init_mysys_psi_keys(void); -#endif - -struct st_mysql_file; -extern struct st_mysql_file *mysql_stdin; - -C_MODE_END -#endif /* _my_sys_h */ diff --git a/vendor/mysql/include/my_thread.h b/vendor/mysql/include/my_thread.h deleted file mode 100644 index fbdd164bad..0000000000 --- a/vendor/mysql/include/my_thread.h +++ /dev/null @@ -1,186 +0,0 @@ -/* Copyright (c) 2000, 2016, Oracle and/or its affiliates. All rights reserved. - - This program is free software; you can redistribute it and/or modify - it under the terms of the GNU General Public License as published by - the Free Software Foundation; version 2 of the License. - - This program is distributed in the hope that it will be useful, - but WITHOUT ANY WARRANTY; without even the implied warranty of - MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - GNU General Public License for more details. - - You should have received a copy of the GNU General Public License - along with this program; if not, write to the Free Software - Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA */ - -/* Defines to make different thread packages compatible */ - -#ifndef MY_THREAD_INCLUDED -#define MY_THREAD_INCLUDED - -#include "my_global.h" /* my_bool */ - -#if !defined(_WIN32) -#include -#endif - -#ifndef ETIME -#define ETIME ETIMEDOUT /* For FreeBSD */ -#endif - -#ifndef ETIMEDOUT -#define ETIMEDOUT 145 /* Win32 doesn't have this */ -#endif - -/* - MySQL can survive with 32K, but some glibc libraries require > 128K stack - To resolve hostnames. Also recursive stored procedures needs stack. -*/ -#if SIZEOF_CHARP > 4 -#define DEFAULT_THREAD_STACK (256*1024L) -#else -#define DEFAULT_THREAD_STACK (192*1024) -#endif - -#ifdef __cplusplus -#define EXTERNC extern "C" -#else -#define EXTERNC -#endif - -C_MODE_START - -#ifdef _WIN32 -typedef volatile LONG my_thread_once_t; -typedef DWORD my_thread_t; -typedef struct thread_attr -{ - DWORD dwStackSize; - int detachstate; -} my_thread_attr_t; -#define MY_THREAD_CREATE_JOINABLE 0 -#define MY_THREAD_CREATE_DETACHED 1 -typedef void * (__cdecl *my_start_routine)(void *); -#define MY_THREAD_ONCE_INIT 0 -#define MY_THREAD_ONCE_INPROGRESS 1 -#define MY_THREAD_ONCE_DONE 2 -#else -typedef pthread_once_t my_thread_once_t; -typedef pthread_t my_thread_t; -typedef pthread_attr_t my_thread_attr_t; -#define MY_THREAD_CREATE_JOINABLE PTHREAD_CREATE_JOINABLE -#define MY_THREAD_CREATE_DETACHED PTHREAD_CREATE_DETACHED -typedef void *(* my_start_routine)(void *); -#define MY_THREAD_ONCE_INIT PTHREAD_ONCE_INIT -#endif - -typedef struct st_my_thread_handle -{ - my_thread_t thread; -#ifdef _WIN32 - HANDLE handle; -#endif -} my_thread_handle; - -int my_thread_once(my_thread_once_t *once_control, void (*init_routine)(void)); - -static inline my_thread_t my_thread_self() -{ -#ifdef _WIN32 - return GetCurrentThreadId(); -#else - return pthread_self(); -#endif -} - -static inline int my_thread_equal(my_thread_t t1, my_thread_t t2) -{ -#ifdef _WIN32 - return t1 == t2; -#else - return pthread_equal(t1, t2); -#endif -} - -static inline int my_thread_attr_init(my_thread_attr_t *attr) -{ -#ifdef _WIN32 - attr->dwStackSize= 0; - /* Set to joinable by default to match Linux */ - attr->detachstate= MY_THREAD_CREATE_JOINABLE; - return 0; -#else - return pthread_attr_init(attr); -#endif -} - -static inline int my_thread_attr_destroy(my_thread_attr_t *attr) -{ -#ifdef _WIN32 - attr->dwStackSize= 0; - /* Set to joinable by default to match Linux */ - attr->detachstate= MY_THREAD_CREATE_JOINABLE; - return 0; -#else - return pthread_attr_destroy(attr); -#endif -} - -static inline int my_thread_attr_setstacksize(my_thread_attr_t *attr, - size_t stacksize) -{ -#ifdef _WIN32 - attr->dwStackSize= (DWORD)stacksize; - return 0; -#else - return pthread_attr_setstacksize(attr, stacksize); -#endif -} - -static inline int my_thread_attr_setdetachstate(my_thread_attr_t *attr, - int detachstate) -{ -#ifdef _WIN32 - attr->detachstate= detachstate; - return 0; -#else - return pthread_attr_setdetachstate(attr, detachstate); -#endif -} - -static inline int my_thread_attr_getstacksize(my_thread_attr_t *attr, - size_t *stacksize) -{ -#ifdef _WIN32 - *stacksize= (size_t)attr->dwStackSize; - return 0; -#else - return pthread_attr_getstacksize(attr, stacksize); -#endif -} - -static inline void my_thread_yield() -{ -#ifdef _WIN32 - SwitchToThread(); -#else - sched_yield(); -#endif -} - -int my_thread_create(my_thread_handle *thread, const my_thread_attr_t *attr, - my_start_routine func, void *arg); -int my_thread_join(my_thread_handle *thread, void **value_ptr); -int my_thread_cancel(my_thread_handle *thread); -void my_thread_exit(void *value_ptr); - - -extern my_bool my_thread_global_init(); -extern void my_thread_global_reinit(); -extern void my_thread_global_end(); -extern my_bool my_thread_init(); -extern void my_thread_end(); - -C_MODE_END - -#endif /* MY_THREAD_INCLUDED */ diff --git a/vendor/mysql/include/my_thread_local.h b/vendor/mysql/include/my_thread_local.h deleted file mode 100644 index fabd71a4c1..0000000000 --- a/vendor/mysql/include/my_thread_local.h +++ /dev/null @@ -1,107 +0,0 @@ -/* Copyright (c) 2000, 2015, Oracle and/or its affiliates. All rights reserved. - - This program is free software; you can redistribute it and/or modify - it under the terms of the GNU General Public License as published by - the Free Software Foundation; version 2 of the License. - - This program is distributed in the hope that it will be useful, - but WITHOUT ANY WARRANTY; without even the implied warranty of - MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - GNU General Public License for more details. - - You should have received a copy of the GNU General Public License - along with this program; if not, write to the Free Software - Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA */ - -#ifndef MY_THREAD_LOCAL_INCLUDED -#define MY_THREAD_LOCAL_INCLUDED - -#ifndef _WIN32 -#include -#endif - -struct _db_code_state_; -typedef uint32 my_thread_id; - -C_MODE_START - -#ifdef _WIN32 -typedef DWORD thread_local_key_t; -#else -typedef pthread_key_t thread_local_key_t; -#endif - -static inline int my_create_thread_local_key(thread_local_key_t *key, - void (*destructor)(void *)) -{ -#ifdef _WIN32 - *key= TlsAlloc(); - return (*key == TLS_OUT_OF_INDEXES); -#else - return pthread_key_create(key, destructor); -#endif -} - -static inline int my_delete_thread_local_key(thread_local_key_t key) -{ -#ifdef _WIN32 - return !TlsFree(key); -#else - return pthread_key_delete(key); -#endif -} - -static inline void* my_get_thread_local(thread_local_key_t key) -{ -#ifdef _WIN32 - return TlsGetValue(key); -#else - return pthread_getspecific(key); -#endif -} - -static inline int my_set_thread_local(thread_local_key_t key, - void *value) -{ -#ifdef _WIN32 - return !TlsSetValue(key, value); -#else - return pthread_setspecific(key, value); -#endif -} - -/** - Retrieve the MySQL thread-local storage variant of errno. -*/ -int my_errno(); - -/** - Set the MySQL thread-local storage variant of errno. -*/ -void set_my_errno(int my_errno); - -#ifdef _WIN32 -/* - thr_winerr is used for returning the original OS error-code in Windows, - my_osmaperr() returns EINVAL for all unknown Windows errors, hence we - preserve the original Windows Error code in thr_winerr. -*/ -int thr_winerr(); - -void set_thr_winerr(int winerr); - -#endif - -#ifndef DBUG_OFF -/* Return pointer to DBUG for holding current state */ -struct _db_code_state_ **my_thread_var_dbug(); - -my_thread_id my_thread_var_id(); - -void set_my_thread_var_id(my_thread_id id); - -#endif - -C_MODE_END - -#endif // MY_THREAD_LOCAL_INCLUDED diff --git a/vendor/mysql/include/my_xml.h b/vendor/mysql/include/my_xml.h deleted file mode 100644 index 639fdc7da4..0000000000 --- a/vendor/mysql/include/my_xml.h +++ /dev/null @@ -1,96 +0,0 @@ -/* Copyright (c) 2000, 2012, Oracle and/or its affiliates. All rights reserved. - - This program is free software; you can redistribute it and/or modify - it under the terms of the GNU General Public License as published by - the Free Software Foundation; version 2 of the License. - - This program is distributed in the hope that it will be useful, - but WITHOUT ANY WARRANTY; without even the implied warranty of - MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - GNU General Public License for more details. - - You should have received a copy of the GNU General Public License - along with this program; if not, write to the Free Software - Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA */ - - -#ifndef _my_xml_h -#define _my_xml_h - -#ifdef __cplusplus -extern "C" { -#endif - - -#define MY_XML_OK 0 -#define MY_XML_ERROR 1 - -/* - A flag whether to use absolute tag names in call-back functions, - like "a", "a.b" and "a.b.c" (used in character set file parser), - or relative names like "a", "b" and "c". -*/ -#define MY_XML_FLAG_RELATIVE_NAMES 1 - -/* - A flag whether to skip normilization of text values before calling - call-back functions: i.e. skip leading/trailing spaces, - \r, \n, \t characters. -*/ -#define MY_XML_FLAG_SKIP_TEXT_NORMALIZATION 2 - -enum my_xml_node_type -{ - MY_XML_NODE_TAG, /* can have TAG, ATTR and TEXT children */ - MY_XML_NODE_ATTR, /* can have TEXT children */ - MY_XML_NODE_TEXT /* cannot have children */ -}; - -typedef struct xml_stack_st -{ - int flags; - enum my_xml_node_type current_node_type; - char errstr[128]; - - struct { - char static_buffer[128]; - char *buffer; - size_t buffer_size; - char *start; - char *end; - } attr; - - const char *beg; - const char *cur; - const char *end; - void *user_data; - int (*enter)(struct xml_stack_st *st,const char *val, size_t len); - int (*value)(struct xml_stack_st *st,const char *val, size_t len); - int (*leave_xml)(struct xml_stack_st *st,const char *val, size_t len); -} MY_XML_PARSER; - -void my_xml_parser_create(MY_XML_PARSER *st); -void my_xml_parser_free(MY_XML_PARSER *st); -int my_xml_parse(MY_XML_PARSER *st,const char *str, size_t len); - -void my_xml_set_value_handler(MY_XML_PARSER *st, int (*)(MY_XML_PARSER *, - const char *, - size_t len)); -void my_xml_set_enter_handler(MY_XML_PARSER *st, int (*)(MY_XML_PARSER *, - const char *, - size_t len)); -void my_xml_set_leave_handler(MY_XML_PARSER *st, int (*)(MY_XML_PARSER *, - const char *, - size_t len)); -void my_xml_set_user_data(MY_XML_PARSER *st, void *); - -size_t my_xml_error_pos(MY_XML_PARSER *st); -uint my_xml_error_lineno(MY_XML_PARSER *st); - -const char *my_xml_error_string(MY_XML_PARSER *st); - -#ifdef __cplusplus -} -#endif - -#endif /* _my_xml_h */ diff --git a/vendor/mysql/include/mysql.h b/vendor/mysql/include/mysql.h index a3e59288cb..a72992ffc6 100644 --- a/vendor/mysql/include/mysql.h +++ b/vendor/mysql/include/mysql.h @@ -1,19 +1,33 @@ -/* Copyright (c) 2000, 2016, Oracle and/or its affiliates. All rights reserved. +/* Copyright (c) 2000, 2024, Oracle and/or its affiliates. This program is free software; you can redistribute it and/or modify - it under the terms of the GNU General Public License as published by - the Free Software Foundation; version 2 of the License. + it under the terms of the GNU General Public License, version 2.0, + as published by the Free Software Foundation. + + This program is designed to work with certain software (including + but not limited to OpenSSL) that is licensed under separate terms, + as designated in a particular file or component or in included license + documentation. The authors of MySQL hereby grant you an additional + permission to link the program and your derivative works with the + separately licensed software that they have either included with + the program or referenced in the documentation. + + Without limiting anything contained in the foregoing, this file, + which is part of C Driver for MySQL (Connector/C), is also subject to the + Universal FOSS Exception, version 1.0, a copy of which can be found at + http://oss.oracle.com/licenses/universal-foss-exception. This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - GNU General Public License for more details. + GNU General Public License, version 2.0, for more details. You should have received a copy of the GNU General Public License along with this program; if not, write to the Free Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA */ -/* +/** + @file include/mysql.h This file defines the client API to MySQL and also the ABI of the dynamically linked libmysqlclient. @@ -26,23 +40,22 @@ #ifndef _mysql_h #define _mysql_h -#ifdef __cplusplus -extern "C" { -#endif - -#ifndef MY_GLOBAL_INCLUDED /* If not standard header */ #ifndef MYSQL_ABI_CHECK +#include +#include +#include #include #endif -typedef char my_bool; -#if !defined(_WIN32) -#define STDCALL -#else -#define STDCALL __stdcall -#endif + +// Legacy definition for the benefit of old code. Use uint64_t in new code. +// If you get warnings from printf, use the PRIu64 macro, or, if you need +// compatibility with older versions of the client library, cast +// before printing. +typedef uint64_t my_ulonglong; #ifndef my_socket_defined -#ifdef _WIN32 +#define my_socket_defined +#if defined(_WIN32) && !defined(MYSQL_ABI_CHECK) #include #ifdef WIN32_LEAN_AND_MEAN #include @@ -50,53 +63,71 @@ typedef char my_bool; #define my_socket SOCKET #else typedef int my_socket; -#endif /* _WIN32 */ +#endif /* _WIN32 && ! MYSQL_ABI_CHECK */ #endif /* my_socket_defined */ -#endif /* MY_GLOBAL_INCLUDED */ -#include "mysql_version.h" -#include "mysql_com.h" -#include "mysql_time.h" +// Small extra definition to avoid pulling in my_compiler.h in client code. +// IWYU pragma: no_include "my_compiler.h" +#ifndef MY_COMPILER_INCLUDED +#if !defined(_WIN32) || defined(MYSQL_ABI_CHECK) +#define STDCALL +#else +#define STDCALL __stdcall +#endif +#endif /* MY_COMPILER_INCLUDED */ -#include "my_list.h" /* for LISTs used in 'MYSQL' and 'MYSQL_STMT' */ +#include "field_types.h" +#include "my_list.h" +#include "mysql_com.h" /* Include declarations of plug-in API */ -#include "mysql/client_plugin.h" +#include "mysql/client_plugin.h" // IWYU pragma: keep /* - Declare my_init() here because it is a documented C API function exported - from the client library. No need to include whole my_sys.h, however. + The client should be able to know which version it is compiled against, + even if mysql.h doesn't use this information directly. */ +#include "mysql_version.h" // IWYU pragma: keep + +// MYSQL_TIME is part of our public API. +#include "mysql_time.h" // IWYU pragma: keep -my_bool my_init(void); +// The error messages are part of our public API. +#include "errmsg.h" // IWYU pragma: keep + +#ifdef __cplusplus +extern "C" { +#endif extern unsigned int mysql_port; extern char *mysql_unix_port; -#define CLIENT_NET_READ_TIMEOUT 365*24*3600 /* Timeout on read */ -#define CLIENT_NET_WRITE_TIMEOUT 365*24*3600 /* Timeout on write */ +#define CLIENT_NET_RETRY_COUNT 1 /* Retry count */ +#define CLIENT_NET_READ_TIMEOUT 365 * 24 * 3600 /* Timeout on read */ +#define CLIENT_NET_WRITE_TIMEOUT 365 * 24 * 3600 /* Timeout on write */ -#define IS_PRI_KEY(n) ((n) & PRI_KEY_FLAG) -#define IS_NOT_NULL(n) ((n) & NOT_NULL_FLAG) -#define IS_BLOB(n) ((n) & BLOB_FLAG) +#define IS_PRI_KEY(n) ((n)&PRI_KEY_FLAG) +#define IS_NOT_NULL(n) ((n)&NOT_NULL_FLAG) +#define IS_BLOB(n) ((n)&BLOB_FLAG) /** Returns true if the value is a number which does not need quotes for the sql_lex.cc parser to parse correctly. */ -#define IS_NUM(t) (((t) <= MYSQL_TYPE_INT24 && (t) != MYSQL_TYPE_TIMESTAMP) || (t) == MYSQL_TYPE_YEAR || (t) == MYSQL_TYPE_NEWDECIMAL) +#define IS_NUM(t) \ + (((t) <= MYSQL_TYPE_INT24 && (t) != MYSQL_TYPE_TIMESTAMP) || \ + (t) == MYSQL_TYPE_YEAR || (t) == MYSQL_TYPE_NEWDECIMAL) #define IS_LONGDATA(t) ((t) >= MYSQL_TYPE_TINY_BLOB && (t) <= MYSQL_TYPE_STRING) - -typedef struct st_mysql_field { - char *name; /* Name of column */ - char *org_name; /* Original column name, if an alias */ - char *table; /* Table of column if column was a field */ - char *org_table; /* Org table name, if table was an alias */ - char *db; /* Database for table */ - char *catalog; /* Catalog for table */ - char *def; /* Default value (set by mysql_list_fields) */ - unsigned long length; /* Width of column (create length) */ - unsigned long max_length; /* Max width for selected set */ +typedef struct MYSQL_FIELD { + char *name; /* Name of column */ + char *org_name; /* Original column name, if an alias */ + char *table; /* Table of column if column was a field */ + char *org_table; /* Org table name, if table was an alias */ + char *db; /* Database for table */ + char *catalog; /* Catalog for table */ + char *def; /* Default value (set by mysql_list_fields) */ + unsigned long length; /* Width of column (create length) */ + unsigned long max_length; /* Max width for selected set */ unsigned int name_length; unsigned int org_name_length; unsigned int table_length; @@ -111,69 +142,79 @@ typedef struct st_mysql_field { void *extension; } MYSQL_FIELD; -typedef char **MYSQL_ROW; /* return data as array of strings */ +typedef char **MYSQL_ROW; /* return data as array of strings */ typedef unsigned int MYSQL_FIELD_OFFSET; /* offset to current field */ -#ifndef MY_GLOBAL_INCLUDED -#if defined (_WIN32) -typedef unsigned __int64 my_ulonglong; -#else -typedef unsigned long long my_ulonglong; -#endif -#endif - -#include "typelib.h" - -#define MYSQL_COUNT_ERROR (~(my_ulonglong) 0) +#define MYSQL_COUNT_ERROR (~(uint64_t)0) /* backward compatibility define - to be removed eventually */ #define ER_WARN_DATA_TRUNCATED WARN_DATA_TRUNCATED -typedef struct st_mysql_rows { - struct st_mysql_rows *next; /* list of rows */ +typedef struct MYSQL_ROWS { + struct MYSQL_ROWS *next; /* list of rows */ MYSQL_ROW data; unsigned long length; } MYSQL_ROWS; -typedef MYSQL_ROWS *MYSQL_ROW_OFFSET; /* offset to current row */ +typedef MYSQL_ROWS *MYSQL_ROW_OFFSET; /* offset to current row */ -#include "my_alloc.h" +struct MEM_ROOT; -typedef struct embedded_query_result EMBEDDED_QUERY_RESULT; -typedef struct st_mysql_data { +typedef struct MYSQL_DATA { MYSQL_ROWS *data; - struct embedded_query_result *embedded_info; - MEM_ROOT alloc; - my_ulonglong rows; + struct MEM_ROOT *alloc; + uint64_t rows; unsigned int fields; - /* extra info for embedded library */ - void *extension; } MYSQL_DATA; -enum mysql_option -{ - MYSQL_OPT_CONNECT_TIMEOUT, MYSQL_OPT_COMPRESS, MYSQL_OPT_NAMED_PIPE, - MYSQL_INIT_COMMAND, MYSQL_READ_DEFAULT_FILE, MYSQL_READ_DEFAULT_GROUP, - MYSQL_SET_CHARSET_DIR, MYSQL_SET_CHARSET_NAME, MYSQL_OPT_LOCAL_INFILE, - MYSQL_OPT_PROTOCOL, MYSQL_SHARED_MEMORY_BASE_NAME, MYSQL_OPT_READ_TIMEOUT, - MYSQL_OPT_WRITE_TIMEOUT, MYSQL_OPT_USE_RESULT, - MYSQL_OPT_USE_REMOTE_CONNECTION, MYSQL_OPT_USE_EMBEDDED_CONNECTION, - MYSQL_OPT_GUESS_CONNECTION, MYSQL_SET_CLIENT_IP, MYSQL_SECURE_AUTH, - MYSQL_REPORT_DATA_TRUNCATION, MYSQL_OPT_RECONNECT, - MYSQL_OPT_SSL_VERIFY_SERVER_CERT, MYSQL_PLUGIN_DIR, MYSQL_DEFAULT_AUTH, +enum mysql_option { + MYSQL_OPT_CONNECT_TIMEOUT, + MYSQL_OPT_COMPRESS, + MYSQL_OPT_NAMED_PIPE, + MYSQL_INIT_COMMAND, + MYSQL_READ_DEFAULT_FILE, + MYSQL_READ_DEFAULT_GROUP, + MYSQL_SET_CHARSET_DIR, + MYSQL_SET_CHARSET_NAME, + MYSQL_OPT_LOCAL_INFILE, + MYSQL_OPT_PROTOCOL, + MYSQL_SHARED_MEMORY_BASE_NAME, + MYSQL_OPT_READ_TIMEOUT, + MYSQL_OPT_WRITE_TIMEOUT, + MYSQL_OPT_USE_RESULT, + MYSQL_REPORT_DATA_TRUNCATION, + MYSQL_OPT_RECONNECT, + MYSQL_PLUGIN_DIR, + MYSQL_DEFAULT_AUTH, MYSQL_OPT_BIND, - MYSQL_OPT_SSL_KEY, MYSQL_OPT_SSL_CERT, - MYSQL_OPT_SSL_CA, MYSQL_OPT_SSL_CAPATH, MYSQL_OPT_SSL_CIPHER, - MYSQL_OPT_SSL_CRL, MYSQL_OPT_SSL_CRLPATH, - MYSQL_OPT_CONNECT_ATTR_RESET, MYSQL_OPT_CONNECT_ATTR_ADD, + MYSQL_OPT_SSL_KEY, + MYSQL_OPT_SSL_CERT, + MYSQL_OPT_SSL_CA, + MYSQL_OPT_SSL_CAPATH, + MYSQL_OPT_SSL_CIPHER, + MYSQL_OPT_SSL_CRL, + MYSQL_OPT_SSL_CRLPATH, + MYSQL_OPT_CONNECT_ATTR_RESET, + MYSQL_OPT_CONNECT_ATTR_ADD, MYSQL_OPT_CONNECT_ATTR_DELETE, MYSQL_SERVER_PUBLIC_KEY, MYSQL_ENABLE_CLEARTEXT_PLUGIN, MYSQL_OPT_CAN_HANDLE_EXPIRED_PASSWORDS, - MYSQL_OPT_SSL_ENFORCE, - MYSQL_OPT_MAX_ALLOWED_PACKET, MYSQL_OPT_NET_BUFFER_LENGTH, + MYSQL_OPT_MAX_ALLOWED_PACKET, + MYSQL_OPT_NET_BUFFER_LENGTH, MYSQL_OPT_TLS_VERSION, - MYSQL_OPT_SSL_MODE + MYSQL_OPT_SSL_MODE, + MYSQL_OPT_GET_SERVER_PUBLIC_KEY, + MYSQL_OPT_RETRY_COUNT, + MYSQL_OPT_OPTIONAL_RESULTSET_METADATA, + MYSQL_OPT_SSL_FIPS_MODE, + MYSQL_OPT_TLS_CIPHERSUITES, + MYSQL_OPT_COMPRESSION_ALGORITHMS, + MYSQL_OPT_ZSTD_COMPRESSION_LEVEL, + MYSQL_OPT_LOAD_DATA_LOCAL_DIR, + MYSQL_OPT_USER_PASSWORD, + MYSQL_OPT_SSL_SESSION_DATA, + MYSQL_OPT_TLS_SNI_SERVERNAME }; /** @@ -186,40 +227,23 @@ struct st_mysql_options { unsigned int connect_timeout, read_timeout, write_timeout; unsigned int port, protocol; unsigned long client_flag; - char *host,*user,*password,*unix_socket,*db; - struct st_dynamic_array *init_commands; - char *my_cnf_file,*my_cnf_group, *charset_dir, *charset_name; - char *ssl_key; /* PEM key file */ - char *ssl_cert; /* PEM cert file */ - char *ssl_ca; /* PEM CA file */ - char *ssl_capath; /* PEM directory of CA-s? */ - char *ssl_cipher; /* cipher to use */ + char *host, *user, *password, *unix_socket, *db; + struct Init_commands_array *init_commands; + char *my_cnf_file, *my_cnf_group, *charset_dir, *charset_name; + char *ssl_key; /* PEM key file */ + char *ssl_cert; /* PEM cert file */ + char *ssl_ca; /* PEM CA file */ + char *ssl_capath; /* PEM directory of CA-s? */ + char *ssl_cipher; /* cipher to use */ char *shared_memory_base_name; unsigned long max_allowed_packet; - my_bool use_ssl; /* Deprecated ! Former use_ssl */ - my_bool compress,named_pipe; - my_bool unused1; - my_bool unused2; - my_bool unused3; - my_bool unused4; - enum mysql_option methods_to_use; - union { - /* - The ip/hostname to use when authenticating - client against embedded server built with - grant tables - only used in embedded server - */ - char *client_ip; - - /* - The local address to bind when connecting to - remote server - not used in embedded server - */ - char *bind_address; - } ci; - my_bool unused5; + bool compress, named_pipe; + /** + The local address to bind when connecting to remote server. + */ + char *bind_address; /* 0 - never report, 1 - always report (default) */ - my_bool report_data_truncation; + bool report_data_truncation; /* function pointers for local infile support */ int (*local_infile_init)(void **, const char *, void *); @@ -230,126 +254,163 @@ struct st_mysql_options { struct st_mysql_options_extention *extension; }; -enum mysql_status -{ - MYSQL_STATUS_READY, MYSQL_STATUS_GET_RESULT, MYSQL_STATUS_USE_RESULT, +enum mysql_status { + MYSQL_STATUS_READY, + MYSQL_STATUS_GET_RESULT, + MYSQL_STATUS_USE_RESULT, MYSQL_STATUS_STATEMENT_GET_RESULT }; -enum mysql_protocol_type -{ - MYSQL_PROTOCOL_DEFAULT, MYSQL_PROTOCOL_TCP, MYSQL_PROTOCOL_SOCKET, - MYSQL_PROTOCOL_PIPE, MYSQL_PROTOCOL_MEMORY +enum mysql_protocol_type { + MYSQL_PROTOCOL_DEFAULT, + MYSQL_PROTOCOL_TCP, + MYSQL_PROTOCOL_SOCKET, + MYSQL_PROTOCOL_PIPE, + MYSQL_PROTOCOL_MEMORY +}; + +enum mysql_ssl_mode { + SSL_MODE_DISABLED = 1, + SSL_MODE_PREFERRED, + SSL_MODE_REQUIRED, + SSL_MODE_VERIFY_CA, + SSL_MODE_VERIFY_IDENTITY }; -enum mysql_ssl_mode -{ - SSL_MODE_DISABLED= 1, SSL_MODE_PREFERRED, SSL_MODE_REQUIRED, - SSL_MODE_VERIFY_CA, SSL_MODE_VERIFY_IDENTITY +enum mysql_ssl_fips_mode { + SSL_FIPS_MODE_OFF = 0, + SSL_FIPS_MODE_ON = 1, + SSL_FIPS_MODE_STRICT }; -typedef struct character_set -{ - unsigned int number; /* character set number */ - unsigned int state; /* character set state */ - const char *csname; /* collation name */ - const char *name; /* character set name */ - const char *comment; /* comment */ - const char *dir; /* character set directory */ - unsigned int mbminlen; /* min. length for multibyte strings */ - unsigned int mbmaxlen; /* max. length for multibyte strings */ +typedef struct character_set { + unsigned int number; /* character set number */ + unsigned int state; /* character set state */ + const char *csname; /* character set name */ + const char *name; /* collation name */ + const char *comment; /* comment */ + const char *dir; /* character set directory */ + unsigned int mbminlen; /* min. length for multibyte strings */ + unsigned int mbmaxlen; /* max. length for multibyte strings */ } MY_CHARSET_INFO; -struct st_mysql_methods; -struct st_mysql_stmt; - -typedef struct st_mysql -{ - NET net; /* Communication parameters */ - unsigned char *connector_fd; /* ConnectorFd for SSL */ - char *host,*user,*passwd,*unix_socket,*server_version,*host_info; - char *info, *db; - struct charset_info_st *charset; - MYSQL_FIELD *fields; - MEM_ROOT field_alloc; - my_ulonglong affected_rows; - my_ulonglong insert_id; /* id if insert on table with NEXTNR */ - my_ulonglong extra_info; /* Not used */ - unsigned long thread_id; /* Id for connection in server */ +struct MYSQL_METHODS; +struct MYSQL_STMT; + +typedef struct MYSQL { + NET net; /* Communication parameters */ + unsigned char *connector_fd; /* ConnectorFd for SSL */ + char *host, *user, *passwd, *unix_socket, *server_version, *host_info; + char *info, *db; + struct CHARSET_INFO *charset; + MYSQL_FIELD *fields; + struct MEM_ROOT *field_alloc; + uint64_t affected_rows; + uint64_t insert_id; /* id if insert on table with NEXTNR */ + uint64_t extra_info; /* Not used */ + unsigned long thread_id; /* Id for connection in server */ unsigned long packet_length; - unsigned int port; - unsigned long client_flag,server_capabilities; - unsigned int protocol_version; - unsigned int field_count; - unsigned int server_status; - unsigned int server_language; - unsigned int warning_count; + unsigned int port; + unsigned long client_flag, server_capabilities; + unsigned int protocol_version; + unsigned int field_count; + unsigned int server_status; + unsigned int server_language; + unsigned int warning_count; struct st_mysql_options options; enum mysql_status status; - my_bool free_me; /* If free in mysql_close */ - my_bool reconnect; /* set to 1 if automatic reconnect */ + enum enum_resultset_metadata resultset_metadata; + bool free_me; /* If free in mysql_close */ + bool reconnect; /* set to 1 if automatic reconnect */ /* session-wide random string */ - char scramble[SCRAMBLE_LENGTH+1]; - my_bool unused1; - void *unused2, *unused3, *unused4, *unused5; + char scramble[SCRAMBLE_LENGTH + 1]; - LIST *stmts; /* list of all statements */ - const struct st_mysql_methods *methods; + LIST *stmts; /* list of all statements */ + const struct MYSQL_METHODS *methods; void *thd; /* Points to boolean flag in MYSQL_RES or MYSQL_STMT. We set this flag from mysql_stmt_close if close had to cancel result set of this object. */ - my_bool *unbuffered_fetch_owner; - /* needed for embedded server - no net buffer to store the 'info' */ - char *info_buffer; + bool *unbuffered_fetch_owner; void *extension; } MYSQL; - -typedef struct st_mysql_res { - my_ulonglong row_count; - MYSQL_FIELD *fields; - MYSQL_DATA *data; - MYSQL_ROWS *data_cursor; - unsigned long *lengths; /* column lengths of current row */ - MYSQL *handle; /* for unbuffered reads */ - const struct st_mysql_methods *methods; - MYSQL_ROW row; /* If unbuffered read */ - MYSQL_ROW current_row; /* buffer to current row */ - MEM_ROOT field_alloc; - unsigned int field_count, current_field; - my_bool eof; /* Used by mysql_fetch_row */ +typedef struct MYSQL_RES { + uint64_t row_count; + MYSQL_FIELD *fields; + struct MYSQL_DATA *data; + MYSQL_ROWS *data_cursor; + unsigned long *lengths; /* column lengths of current row */ + MYSQL *handle; /* for unbuffered reads */ + const struct MYSQL_METHODS *methods; + MYSQL_ROW row; /* If unbuffered read */ + MYSQL_ROW current_row; /* buffer to current row */ + struct MEM_ROOT *field_alloc; + unsigned int field_count, current_field; + bool eof; /* Used by mysql_fetch_row */ /* mysql_stmt_close() had to cancel this result */ - my_bool unbuffered_fetch_cancelled; + bool unbuffered_fetch_cancelled; + enum enum_resultset_metadata metadata; void *extension; } MYSQL_RES; +/** + Flag to indicate that COM_BINLOG_DUMP_GTID should + be used rather than COM_BINLOG_DUMP in the @sa mysql_binlog_open(). +*/ +#define MYSQL_RPL_GTID (1 << 16) +/** + Skip HEARBEAT events in the @sa mysql_binlog_fetch(). +*/ +#define MYSQL_RPL_SKIP_HEARTBEAT (1 << 17) -#if !defined(MYSQL_SERVER) && !defined(MYSQL_CLIENT) -#define MYSQL_CLIENT -#endif +/** + Flag to indicate that the heartbeat_event being generated + is using the class Heartbeat_event_v2 +*/ +#define USE_HEARTBEAT_EVENT_V2 (1 << 1) -/* - Note: MYSQL_PARAMETERS and mysql_get_parameters() have been removed - in server 5.7. But we keep them here to not break compatibility in - Con/C 6.1 series. +/** + Flag to indicate that tagged GTIDS will be skipped in COM_BINLOG_DUMP_GTIDS */ +#define MYSQL_RPL_SKIP_TAGGED_GTIDS (1 << 2) -typedef struct st_mysql_parameters -{ - unsigned long *p_max_allowed_packet; - unsigned long *p_net_buffer_length; - void *extension; -} MYSQL_PARAMETERS; +/** + Tagged GTIDS are supported starting from below version of MySQL +*/ +#define MYSQL_TAGGED_GTIDS_VERSION_SUPPORT 80300 -#if !defined(MYSQL_SERVER) && !defined(EMBEDDED_LIBRARY) -#define max_allowed_packet (*mysql_get_parameters()->p_max_allowed_packet) -#define net_buffer_length (*mysql_get_parameters()->p_net_buffer_length) -#endif +/** + Struct for information about a replication stream. -MYSQL_PARAMETERS *STDCALL mysql_get_parameters(void); + @sa mysql_binlog_open() + @sa mysql_binlog_fetch() + @sa mysql_binlog_close() +*/ +typedef struct MYSQL_RPL { + size_t file_name_length; /** Length of the 'file_name' or 0 */ + const char *file_name; /** Filename of the binary log to read */ + uint64_t start_position; /** Position in the binary log to */ + /* start reading from */ + unsigned int server_id; /** Server ID to use when identifying */ + /* with the master */ + unsigned int flags; /** Flags, e.g. MYSQL_RPL_GTID */ + + /** Size of gtid set data */ + size_t gtid_set_encoded_size; + /** Callback function which is called */ + /* from @sa mysql_binlog_open() to */ + /* fill command packet gtid set */ + void (*fix_gtid_set)(struct MYSQL_RPL *rpl, unsigned char *packet_gtid_set); + void *gtid_set_arg; /** GTID set data or an argument for */ + /* fix_gtid_set() callback function */ + + unsigned long size; /** Size of the packet returned by */ + /* mysql_binlog_fetch() */ + const unsigned char *buffer; /** Pointer to returned data */ +} MYSQL_RPL; /* Set up and bring down the server; to ensure that applications will @@ -362,7 +423,7 @@ void STDCALL mysql_server_end(void); /* mysql_server_init/end need to be called when using libmysqld or libmysqlclient (exactly, mysql_server_init() is called by mysql_init() so - you don't need to call it explicitely; but you need to call + you don't need to call it explicitly; but you need to call mysql_server_end() to free memory). The names are a bit misleading (mysql_SERVER* to be used when using libmysqlCLIENT). So we add more general names which suit well whether you're using libmysqld or libmysqlclient. We @@ -371,14 +432,13 @@ void STDCALL mysql_server_end(void); #define mysql_library_init mysql_server_init #define mysql_library_end mysql_server_end - /* Set up and bring down a thread; these function should be called for each thread in an application which opens at least one MySQL connection. All uses of the connection(s) should be between these function calls. */ -my_bool STDCALL mysql_thread_init(void); +bool STDCALL mysql_thread_init(void); void STDCALL mysql_thread_end(void); /* @@ -386,134 +446,145 @@ void STDCALL mysql_thread_end(void); Should definitely be used if one uses shared libraries. */ -my_ulonglong STDCALL mysql_num_rows(MYSQL_RES *res); +uint64_t STDCALL mysql_num_rows(MYSQL_RES *res); unsigned int STDCALL mysql_num_fields(MYSQL_RES *res); -my_bool STDCALL mysql_eof(MYSQL_RES *res); +bool STDCALL mysql_eof(MYSQL_RES *res); MYSQL_FIELD *STDCALL mysql_fetch_field_direct(MYSQL_RES *res, - unsigned int fieldnr); -MYSQL_FIELD * STDCALL mysql_fetch_fields(MYSQL_RES *res); + unsigned int fieldnr); +MYSQL_FIELD *STDCALL mysql_fetch_fields(MYSQL_RES *res); MYSQL_ROW_OFFSET STDCALL mysql_row_tell(MYSQL_RES *res); MYSQL_FIELD_OFFSET STDCALL mysql_field_tell(MYSQL_RES *res); +enum enum_resultset_metadata STDCALL mysql_result_metadata(MYSQL_RES *result); unsigned int STDCALL mysql_field_count(MYSQL *mysql); -my_ulonglong STDCALL mysql_affected_rows(MYSQL *mysql); -my_ulonglong STDCALL mysql_insert_id(MYSQL *mysql); +uint64_t STDCALL mysql_affected_rows(MYSQL *mysql); +uint64_t STDCALL mysql_insert_id(MYSQL *mysql); unsigned int STDCALL mysql_errno(MYSQL *mysql); -const char * STDCALL mysql_error(MYSQL *mysql); +const char *STDCALL mysql_error(MYSQL *mysql); const char *STDCALL mysql_sqlstate(MYSQL *mysql); unsigned int STDCALL mysql_warning_count(MYSQL *mysql); -const char * STDCALL mysql_info(MYSQL *mysql); +const char *STDCALL mysql_info(MYSQL *mysql); unsigned long STDCALL mysql_thread_id(MYSQL *mysql); -const char * STDCALL mysql_character_set_name(MYSQL *mysql); -int STDCALL mysql_set_character_set(MYSQL *mysql, const char *csname); - -MYSQL * STDCALL mysql_init(MYSQL *mysql); -my_bool STDCALL mysql_ssl_set(MYSQL *mysql, const char *key, - const char *cert, const char *ca, - const char *capath, const char *cipher); -const char * STDCALL mysql_get_ssl_cipher(MYSQL *mysql); -my_bool STDCALL mysql_change_user(MYSQL *mysql, const char *user, - const char *passwd, const char *db); -MYSQL * STDCALL mysql_real_connect(MYSQL *mysql, const char *host, - const char *user, - const char *passwd, - const char *db, - unsigned int port, - const char *unix_socket, - unsigned long clientflag); -int STDCALL mysql_select_db(MYSQL *mysql, const char *db); -int STDCALL mysql_query(MYSQL *mysql, const char *q); -int STDCALL mysql_send_query(MYSQL *mysql, const char *q, - unsigned long length); -int STDCALL mysql_real_query(MYSQL *mysql, const char *q, - unsigned long length); -MYSQL_RES * STDCALL mysql_store_result(MYSQL *mysql); -MYSQL_RES * STDCALL mysql_use_result(MYSQL *mysql); - -void STDCALL mysql_get_character_set_info(MYSQL *mysql, - MY_CHARSET_INFO *charset); +const char *STDCALL mysql_character_set_name(MYSQL *mysql); +int STDCALL mysql_set_character_set(MYSQL *mysql, const char *csname); + +MYSQL *STDCALL mysql_init(MYSQL *mysql); +bool STDCALL mysql_ssl_set(MYSQL *mysql, const char *key, const char *cert, + const char *ca, const char *capath, + const char *cipher); +const char *STDCALL mysql_get_ssl_cipher(MYSQL *mysql); +bool STDCALL mysql_get_ssl_session_reused(MYSQL *mysql); +void *STDCALL mysql_get_ssl_session_data(MYSQL *mysql, unsigned int n_ticket, + unsigned int *out_len); +bool STDCALL mysql_free_ssl_session_data(MYSQL *mysql, void *data); +bool STDCALL mysql_change_user(MYSQL *mysql, const char *user, + const char *passwd, const char *db); +MYSQL *STDCALL mysql_real_connect(MYSQL *mysql, const char *host, + const char *user, const char *passwd, + const char *db, unsigned int port, + const char *unix_socket, + unsigned long clientflag); +int STDCALL mysql_select_db(MYSQL *mysql, const char *db); +int STDCALL mysql_query(MYSQL *mysql, const char *q); +int STDCALL mysql_send_query(MYSQL *mysql, const char *q, unsigned long length); +int STDCALL mysql_real_query(MYSQL *mysql, const char *q, unsigned long length); +MYSQL_RES *STDCALL mysql_store_result(MYSQL *mysql); +MYSQL_RES *STDCALL mysql_use_result(MYSQL *mysql); + +enum net_async_status STDCALL mysql_real_connect_nonblocking( + MYSQL *mysql, const char *host, const char *user, const char *passwd, + const char *db, unsigned int port, const char *unix_socket, + unsigned long clientflag); +enum net_async_status STDCALL mysql_send_query_nonblocking( + MYSQL *mysql, const char *query, unsigned long length); +enum net_async_status STDCALL mysql_real_query_nonblocking( + MYSQL *mysql, const char *query, unsigned long length); +enum net_async_status STDCALL +mysql_store_result_nonblocking(MYSQL *mysql, MYSQL_RES **result); +enum net_async_status STDCALL mysql_next_result_nonblocking(MYSQL *mysql); +enum net_async_status STDCALL mysql_select_db_nonblocking(MYSQL *mysql, + const char *db, + bool *error); +void STDCALL mysql_get_character_set_info(MYSQL *mysql, + MY_CHARSET_INFO *charset); int STDCALL mysql_session_track_get_first(MYSQL *mysql, enum enum_session_state_type type, - const char **data, - size_t *length); + const char **data, size_t *length); int STDCALL mysql_session_track_get_next(MYSQL *mysql, enum enum_session_state_type type, - const char **data, - size_t *length); + const char **data, size_t *length); /* local infile support */ #define LOCAL_INFILE_ERROR_LEN 512 -void -mysql_set_local_infile_handler(MYSQL *mysql, - int (*local_infile_init)(void **, const char *, - void *), - int (*local_infile_read)(void *, char *, - unsigned int), - void (*local_infile_end)(void *), - int (*local_infile_error)(void *, char*, - unsigned int), - void *); - -void -mysql_set_local_infile_default(MYSQL *mysql); - -int STDCALL mysql_shutdown(MYSQL *mysql, - enum mysql_enum_shutdown_level - shutdown_level); -int STDCALL mysql_dump_debug_info(MYSQL *mysql); -int STDCALL mysql_refresh(MYSQL *mysql, - unsigned int refresh_options); -int STDCALL mysql_kill(MYSQL *mysql,unsigned long pid); -int STDCALL mysql_set_server_option(MYSQL *mysql, - enum enum_mysql_set_option - option); -int STDCALL mysql_ping(MYSQL *mysql); -const char * STDCALL mysql_stat(MYSQL *mysql); -const char * STDCALL mysql_get_server_info(MYSQL *mysql); -const char * STDCALL mysql_get_client_info(void); -unsigned long STDCALL mysql_get_client_version(void); -const char * STDCALL mysql_get_host_info(MYSQL *mysql); -unsigned long STDCALL mysql_get_server_version(MYSQL *mysql); -unsigned int STDCALL mysql_get_proto_info(MYSQL *mysql); -MYSQL_RES * STDCALL mysql_list_dbs(MYSQL *mysql,const char *wild); -MYSQL_RES * STDCALL mysql_list_tables(MYSQL *mysql,const char *wild); -MYSQL_RES * STDCALL mysql_list_processes(MYSQL *mysql); -int STDCALL mysql_options(MYSQL *mysql,enum mysql_option option, - const void *arg); -int STDCALL mysql_options4(MYSQL *mysql,enum mysql_option option, - const void *arg1, const void *arg2); -int STDCALL mysql_get_option(MYSQL *mysql, enum mysql_option option, - const void *arg); -void STDCALL mysql_free_result(MYSQL_RES *result); -void STDCALL mysql_data_seek(MYSQL_RES *result, - my_ulonglong offset); +void mysql_set_local_infile_handler( + MYSQL *mysql, int (*local_infile_init)(void **, const char *, void *), + int (*local_infile_read)(void *, char *, unsigned int), + void (*local_infile_end)(void *), + int (*local_infile_error)(void *, char *, unsigned int), void *); + +void mysql_set_local_infile_default(MYSQL *mysql); +int STDCALL mysql_shutdown(MYSQL *mysql, + enum mysql_enum_shutdown_level shutdown_level); +int STDCALL mysql_dump_debug_info(MYSQL *mysql); +int STDCALL mysql_refresh(MYSQL *mysql, unsigned int refresh_options); +int STDCALL mysql_kill(MYSQL *mysql, unsigned long pid); +int STDCALL mysql_set_server_option(MYSQL *mysql, + enum enum_mysql_set_option option); +int STDCALL mysql_ping(MYSQL *mysql); +const char *STDCALL mysql_stat(MYSQL *mysql); +const char *STDCALL mysql_get_server_info(MYSQL *mysql); +const char *STDCALL mysql_get_client_info(void); +unsigned long STDCALL mysql_get_client_version(void); +const char *STDCALL mysql_get_host_info(MYSQL *mysql); +unsigned long STDCALL mysql_get_server_version(MYSQL *mysql); +unsigned int STDCALL mysql_get_proto_info(MYSQL *mysql); +MYSQL_RES *STDCALL mysql_list_dbs(MYSQL *mysql, const char *wild); +MYSQL_RES *STDCALL mysql_list_tables(MYSQL *mysql, const char *wild); +MYSQL_RES *STDCALL mysql_list_processes(MYSQL *mysql); +int STDCALL mysql_options(MYSQL *mysql, enum mysql_option option, + const void *arg); +int STDCALL mysql_options4(MYSQL *mysql, enum mysql_option option, + const void *arg1, const void *arg2); +int STDCALL mysql_get_option(MYSQL *mysql, enum mysql_option option, + const void *arg); +void STDCALL mysql_free_result(MYSQL_RES *result); +enum net_async_status STDCALL mysql_free_result_nonblocking(MYSQL_RES *result); +void STDCALL mysql_data_seek(MYSQL_RES *result, uint64_t offset); MYSQL_ROW_OFFSET STDCALL mysql_row_seek(MYSQL_RES *result, - MYSQL_ROW_OFFSET offset); + MYSQL_ROW_OFFSET offset); MYSQL_FIELD_OFFSET STDCALL mysql_field_seek(MYSQL_RES *result, - MYSQL_FIELD_OFFSET offset); -MYSQL_ROW STDCALL mysql_fetch_row(MYSQL_RES *result); -unsigned long * STDCALL mysql_fetch_lengths(MYSQL_RES *result); -MYSQL_FIELD * STDCALL mysql_fetch_field(MYSQL_RES *result); -MYSQL_RES * STDCALL mysql_list_fields(MYSQL *mysql, const char *table, - const char *wild); -unsigned long STDCALL mysql_escape_string(char *to,const char *from, - unsigned long from_length); -unsigned long STDCALL mysql_hex_string(char *to,const char *from, - unsigned long from_length); -unsigned long STDCALL mysql_real_escape_string(MYSQL *mysql, - char *to,const char *from, - unsigned long length); -unsigned long STDCALL mysql_real_escape_string_quote(MYSQL *mysql, - char *to, const char *from, - unsigned long length, char quote); -void STDCALL mysql_debug(const char *debug); -void STDCALL myodbc_remove_escape(MYSQL *mysql,char *name); -unsigned int STDCALL mysql_thread_safe(void); -my_bool STDCALL mysql_embedded(void); -my_bool STDCALL mysql_read_query_result(MYSQL *mysql); -int STDCALL mysql_reset_connection(MYSQL *mysql); + MYSQL_FIELD_OFFSET offset); +MYSQL_ROW STDCALL mysql_fetch_row(MYSQL_RES *result); +enum net_async_status STDCALL mysql_fetch_row_nonblocking(MYSQL_RES *res, + MYSQL_ROW *row); + +unsigned long *STDCALL mysql_fetch_lengths(MYSQL_RES *result); +MYSQL_FIELD *STDCALL mysql_fetch_field(MYSQL_RES *result); +MYSQL_RES *STDCALL mysql_list_fields(MYSQL *mysql, const char *table, + const char *wild); +unsigned long STDCALL mysql_escape_string(char *to, const char *from, + unsigned long from_length); +unsigned long STDCALL mysql_hex_string(char *to, const char *from, + unsigned long from_length); +unsigned long STDCALL mysql_real_escape_string(MYSQL *mysql, char *to, + const char *from, + unsigned long length); +unsigned long STDCALL mysql_real_escape_string_quote(MYSQL *mysql, char *to, + const char *from, + unsigned long length, + char quote); +void STDCALL mysql_debug(const char *debug); +void STDCALL myodbc_remove_escape(MYSQL *mysql, char *name); +unsigned int STDCALL mysql_thread_safe(void); +bool STDCALL mysql_read_query_result(MYSQL *mysql); +int STDCALL mysql_reset_connection(MYSQL *mysql); +enum net_async_status STDCALL mysql_reset_connection_nonblocking(MYSQL *mysql); + +int STDCALL mysql_binlog_open(MYSQL *mysql, MYSQL_RPL *rpl); +int STDCALL mysql_binlog_fetch(MYSQL *mysql, MYSQL_RPL *rpl); +void STDCALL mysql_binlog_close(MYSQL *mysql, MYSQL_RPL *rpl); /* The following definitions are added for the enhanced @@ -521,13 +592,13 @@ int STDCALL mysql_reset_connection(MYSQL *mysql); */ /* statement state */ -enum enum_mysql_stmt_state -{ - MYSQL_STMT_INIT_DONE= 1, MYSQL_STMT_PREPARE_DONE, MYSQL_STMT_EXECUTE_DONE, +enum enum_mysql_stmt_state { + MYSQL_STMT_INIT_DONE = 1, + MYSQL_STMT_PREPARE_DONE, + MYSQL_STMT_EXECUTE_DONE, MYSQL_STMT_FETCH_DONE }; - /* This structure is used to define bind information, and internally by the client library. @@ -557,7 +628,7 @@ enum enum_mysql_stmt_state length - On input: in case when lengths of input values are different for each execute, you can set this to - point at a variable containining value length. This + point at a variable containing value length. This way the value length can be different in each execute. If length is not NULL, buffer_length is not used. Note, length can even point at buffer_length if @@ -591,86 +662,79 @@ enum enum_mysql_stmt_state Please note that MYSQL_BIND also has internals members. */ -typedef struct st_mysql_bind -{ - unsigned long *length; /* output length pointer */ - my_bool *is_null; /* Pointer to null indicator */ - void *buffer; /* buffer to get/put data */ +typedef struct MYSQL_BIND { + unsigned long *length; /* output length pointer */ + bool *is_null; /* Pointer to null indicator */ + void *buffer; /* buffer to get/put data */ /* set this if you want to track data truncations happened during fetch */ - my_bool *error; - unsigned char *row_ptr; /* for the current data position */ - void (*store_param_func)(NET *net, struct st_mysql_bind *param); - void (*fetch_result)(struct st_mysql_bind *, MYSQL_FIELD *, - unsigned char **row); - void (*skip_result)(struct st_mysql_bind *, MYSQL_FIELD *, - unsigned char **row); + bool *error; + unsigned char *row_ptr; /* for the current data position */ + void (*store_param_func)(NET *net, struct MYSQL_BIND *param); + void (*fetch_result)(struct MYSQL_BIND *, MYSQL_FIELD *, unsigned char **row); + void (*skip_result)(struct MYSQL_BIND *, MYSQL_FIELD *, unsigned char **row); /* output buffer length, must be set when fetching str/binary */ unsigned long buffer_length; - unsigned long offset; /* offset position for char/binary fetch */ - unsigned long length_value; /* Used if length is 0 */ - unsigned int param_number; /* For null count and error messages */ - unsigned int pack_length; /* Internal length for packed data */ - enum enum_field_types buffer_type; /* buffer type */ - my_bool error_value; /* used if error is 0 */ - my_bool is_unsigned; /* set if integer type is unsigned */ - my_bool long_data_used; /* If used with mysql_send_long_data */ - my_bool is_null_value; /* Used if is_null is 0 */ + unsigned long offset; /* offset position for char/binary fetch */ + unsigned long length_value; /* Used if length is 0 */ + unsigned int param_number; /* For null count and error messages */ + unsigned int pack_length; /* Internal length for packed data */ + enum enum_field_types buffer_type; /* buffer type */ + bool error_value; /* used if error is 0 */ + bool is_unsigned; /* set if integer type is unsigned */ + bool long_data_used; /* If used with mysql_send_long_data */ + bool is_null_value; /* Used if is_null is 0 */ void *extension; } MYSQL_BIND; - -struct st_mysql_stmt_extension; +struct MYSQL_STMT_EXT; /* statement handler */ -typedef struct st_mysql_stmt -{ - MEM_ROOT mem_root; /* root allocations */ - LIST list; /* list to keep track of all stmts */ - MYSQL *mysql; /* connection handle */ - MYSQL_BIND *params; /* input parameters */ - MYSQL_BIND *bind; /* output parameters */ - MYSQL_FIELD *fields; /* result set metadata */ - MYSQL_DATA result; /* cached result set */ - MYSQL_ROWS *data_cursor; /* current row in cached result */ +typedef struct MYSQL_STMT { + struct MEM_ROOT *mem_root; /* root allocations */ + LIST list; /* list to keep track of all stmts */ + MYSQL *mysql; /* connection handle */ + MYSQL_BIND *params; /* input parameters */ + MYSQL_BIND *bind; /* output parameters */ + MYSQL_FIELD *fields; /* result set metadata */ + MYSQL_DATA result; /* cached result set */ + MYSQL_ROWS *data_cursor; /* current row in cached result */ /* mysql_stmt_fetch() calls this function to fetch one row (it's different for buffered, unbuffered and cursor fetch). */ - int (*read_row_func)(struct st_mysql_stmt *stmt, - unsigned char **row); + int (*read_row_func)(struct MYSQL_STMT *stmt, unsigned char **row); /* copy of mysql->affected_rows after statement execution */ - my_ulonglong affected_rows; - my_ulonglong insert_id; /* copy of mysql->insert_id */ - unsigned long stmt_id; /* Id for prepared statement */ - unsigned long flags; /* i.e. type of cursor to open */ - unsigned long prefetch_rows; /* number of rows per one COM_FETCH */ + uint64_t affected_rows; + uint64_t insert_id; /* copy of mysql->insert_id */ + unsigned long stmt_id; /* Id for prepared statement */ + unsigned long flags; /* i.e. type of cursor to open */ + unsigned long prefetch_rows; /* number of rows per one COM_FETCH */ /* Copied from mysql->server_status after execute/fetch to know server-side cursor status for this statement. */ - unsigned int server_status; - unsigned int last_errno; /* error code */ - unsigned int param_count; /* input parameter count */ - unsigned int field_count; /* number of columns in result set */ - enum enum_mysql_stmt_state state; /* statement state */ - char last_error[MYSQL_ERRMSG_SIZE]; /* error message */ - char sqlstate[SQLSTATE_LENGTH+1]; + unsigned int server_status; + unsigned int last_errno; /* error code */ + unsigned int param_count; /* input parameter count */ + unsigned int field_count; /* number of columns in result set */ + enum enum_mysql_stmt_state state; /* statement state */ + char last_error[MYSQL_ERRMSG_SIZE]; /* error message */ + char sqlstate[SQLSTATE_LENGTH + 1]; /* Types of input parameters should be sent to server */ - my_bool send_types_to_server; - my_bool bind_param_done; /* input buffers were supplied */ - unsigned char bind_result_done; /* output buffers were supplied */ + bool send_types_to_server; + bool bind_param_done; /* input buffers were supplied */ + unsigned char bind_result_done; /* output buffers were supplied */ /* mysql_stmt_close() had to cancel this result */ - my_bool unbuffered_fetch_cancelled; + bool unbuffered_fetch_cancelled; /* Is set to true if we need to calculate field->max_length for metadata fields when doing mysql_stmt_store_result. */ - my_bool update_max_length; - struct st_mysql_stmt_extension *extension; + bool update_max_length; + struct MYSQL_STMT_EXT *extension; } MYSQL_STMT; -enum enum_stmt_attr_type -{ +enum enum_stmt_attr_type { /* When doing mysql_stmt_store_result calculate max_length attribute of statement metadata. This is to be consistent with the old API, @@ -691,64 +755,76 @@ enum enum_stmt_attr_type STMT_ATTR_PREFETCH_ROWS }; +bool STDCALL mysql_bind_param(MYSQL *mysql, unsigned n_params, + MYSQL_BIND *binds, const char **names); -MYSQL_STMT * STDCALL mysql_stmt_init(MYSQL *mysql); +MYSQL_STMT *STDCALL mysql_stmt_init(MYSQL *mysql); int STDCALL mysql_stmt_prepare(MYSQL_STMT *stmt, const char *query, unsigned long length); int STDCALL mysql_stmt_execute(MYSQL_STMT *stmt); int STDCALL mysql_stmt_fetch(MYSQL_STMT *stmt); int STDCALL mysql_stmt_fetch_column(MYSQL_STMT *stmt, MYSQL_BIND *bind_arg, - unsigned int column, - unsigned long offset); + unsigned int column, unsigned long offset); int STDCALL mysql_stmt_store_result(MYSQL_STMT *stmt); -unsigned long STDCALL mysql_stmt_param_count(MYSQL_STMT * stmt); -my_bool STDCALL mysql_stmt_attr_set(MYSQL_STMT *stmt, - enum enum_stmt_attr_type attr_type, - const void *attr); -my_bool STDCALL mysql_stmt_attr_get(MYSQL_STMT *stmt, - enum enum_stmt_attr_type attr_type, - void *attr); -my_bool STDCALL mysql_stmt_bind_param(MYSQL_STMT * stmt, MYSQL_BIND * bnd); -my_bool STDCALL mysql_stmt_bind_result(MYSQL_STMT * stmt, MYSQL_BIND * bnd); -my_bool STDCALL mysql_stmt_close(MYSQL_STMT * stmt); -my_bool STDCALL mysql_stmt_reset(MYSQL_STMT * stmt); -my_bool STDCALL mysql_stmt_free_result(MYSQL_STMT *stmt); -my_bool STDCALL mysql_stmt_send_long_data(MYSQL_STMT *stmt, - unsigned int param_number, - const char *data, - unsigned long length); +unsigned long STDCALL mysql_stmt_param_count(MYSQL_STMT *stmt); +bool STDCALL mysql_stmt_attr_set(MYSQL_STMT *stmt, + enum enum_stmt_attr_type attr_type, + const void *attr); +bool STDCALL mysql_stmt_attr_get(MYSQL_STMT *stmt, + enum enum_stmt_attr_type attr_type, + void *attr); +bool STDCALL mysql_stmt_bind_param(MYSQL_STMT *stmt, MYSQL_BIND *bnd); +bool STDCALL mysql_stmt_bind_named_param(MYSQL_STMT *stmt, MYSQL_BIND *binds, + unsigned n_params, const char **names); +bool STDCALL mysql_stmt_bind_result(MYSQL_STMT *stmt, MYSQL_BIND *bnd); +bool STDCALL mysql_stmt_close(MYSQL_STMT *stmt); +bool STDCALL mysql_stmt_reset(MYSQL_STMT *stmt); +bool STDCALL mysql_stmt_free_result(MYSQL_STMT *stmt); +bool STDCALL mysql_stmt_send_long_data(MYSQL_STMT *stmt, + unsigned int param_number, + const char *data, unsigned long length); MYSQL_RES *STDCALL mysql_stmt_result_metadata(MYSQL_STMT *stmt); MYSQL_RES *STDCALL mysql_stmt_param_metadata(MYSQL_STMT *stmt); -unsigned int STDCALL mysql_stmt_errno(MYSQL_STMT * stmt); -const char *STDCALL mysql_stmt_error(MYSQL_STMT * stmt); -const char *STDCALL mysql_stmt_sqlstate(MYSQL_STMT * stmt); +unsigned int STDCALL mysql_stmt_errno(MYSQL_STMT *stmt); +const char *STDCALL mysql_stmt_error(MYSQL_STMT *stmt); +const char *STDCALL mysql_stmt_sqlstate(MYSQL_STMT *stmt); MYSQL_ROW_OFFSET STDCALL mysql_stmt_row_seek(MYSQL_STMT *stmt, MYSQL_ROW_OFFSET offset); MYSQL_ROW_OFFSET STDCALL mysql_stmt_row_tell(MYSQL_STMT *stmt); -void STDCALL mysql_stmt_data_seek(MYSQL_STMT *stmt, my_ulonglong offset); -my_ulonglong STDCALL mysql_stmt_num_rows(MYSQL_STMT *stmt); -my_ulonglong STDCALL mysql_stmt_affected_rows(MYSQL_STMT *stmt); -my_ulonglong STDCALL mysql_stmt_insert_id(MYSQL_STMT *stmt); +void STDCALL mysql_stmt_data_seek(MYSQL_STMT *stmt, uint64_t offset); +uint64_t STDCALL mysql_stmt_num_rows(MYSQL_STMT *stmt); +uint64_t STDCALL mysql_stmt_affected_rows(MYSQL_STMT *stmt); +uint64_t STDCALL mysql_stmt_insert_id(MYSQL_STMT *stmt); unsigned int STDCALL mysql_stmt_field_count(MYSQL_STMT *stmt); -my_bool STDCALL mysql_commit(MYSQL * mysql); -my_bool STDCALL mysql_rollback(MYSQL * mysql); -my_bool STDCALL mysql_autocommit(MYSQL * mysql, my_bool auto_mode); -my_bool STDCALL mysql_more_results(MYSQL *mysql); +bool STDCALL mysql_commit(MYSQL *mysql); +bool STDCALL mysql_rollback(MYSQL *mysql); +bool STDCALL mysql_autocommit(MYSQL *mysql, bool auto_mode); +bool STDCALL mysql_more_results(MYSQL *mysql); int STDCALL mysql_next_result(MYSQL *mysql); int STDCALL mysql_stmt_next_result(MYSQL_STMT *stmt); void STDCALL mysql_close(MYSQL *sock); +/* Public key reset */ +void STDCALL mysql_reset_server_public_key(void); /* status return codes */ -#define MYSQL_NO_DATA 100 +#define MYSQL_NO_DATA 100 #define MYSQL_DATA_TRUNCATED 101 -#define mysql_reload(mysql) mysql_refresh((mysql),REFRESH_GRANT) +#define mysql_reload(mysql) mysql_refresh((mysql), REFRESH_GRANT) #define HAVE_MYSQL_REAL_CONNECT -#ifdef __cplusplus +MYSQL *STDCALL mysql_real_connect_dns_srv(MYSQL *mysql, + const char *dns_srv_name, + const char *user, const char *passwd, + const char *db, + unsigned long client_flag); + +enum connect_stage STDCALL mysql_get_connect_nonblocking_stage(MYSQL *mysql); + +#ifdef __cplusplus } #endif diff --git a/vendor/mysql/include/mysql/client_authentication.h b/vendor/mysql/include/mysql/client_authentication.h deleted file mode 100644 index 894357934d..0000000000 --- a/vendor/mysql/include/mysql/client_authentication.h +++ /dev/null @@ -1,28 +0,0 @@ -/* Copyright (c) 2012, 2014, Oracle and/or its affiliates. All rights reserved. - - This program is free software; you can redistribute it and/or modify - it under the terms of the GNU General Public License as published by - the Free Software Foundation; version 2 of the License. - - This program is distributed in the hope that it will be useful, - but WITHOUT ANY WARRANTY; without even the implied warranty of - MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - GNU General Public License for more details. - - You should have received a copy of the GNU General Public License - along with this program; if not, write to the Free Software - Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA */ -#ifndef CLIENT_AUTHENTICATION_H -#define CLIENT_AUTHENTICATION_H -#include -#include "mysql.h" -#include "mysql/client_plugin.h" - -C_MODE_START -int sha256_password_auth_client(MYSQL_PLUGIN_VIO *vio, MYSQL *mysql); -int sha256_password_init(char *, size_t, int, va_list); -int sha256_password_deinit(void); -C_MODE_END - -#endif - diff --git a/vendor/mysql/include/mysql/client_plugin.h b/vendor/mysql/include/mysql/client_plugin.h index d6471dbcd0..87b011d051 100644 --- a/vendor/mysql/include/mysql/client_plugin.h +++ b/vendor/mysql/include/mysql/client_plugin.h @@ -1,24 +1,35 @@ #ifndef MYSQL_CLIENT_PLUGIN_INCLUDED -/* Copyright (c) 2010, 2016, Oracle and/or its affiliates. All rights reserved. +/* Copyright (c) 2010, 2024, Oracle and/or its affiliates. This program is free software; you can redistribute it and/or modify - it under the terms of the GNU General Public License as published by - the Free Software Foundation; version 2 of the License. + it under the terms of the GNU General Public License, version 2.0, + as published by the Free Software Foundation. + + This program is designed to work with certain software (including + but not limited to OpenSSL) that is licensed under separate terms, + as designated in a particular file or component or in included license + documentation. The authors of MySQL hereby grant you an additional + permission to link the program and your derivative works with the + separately licensed software that they have either included with + the program or referenced in the documentation. + + Without limiting anything contained in the foregoing, this file, + which is part of C Driver for MySQL (Connector/C), is also subject to the + Universal FOSS Exception, version 1.0, a copy of which can be found at + http://oss.oracle.com/licenses/universal-foss-exception. This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - GNU General Public License for more details. + GNU General Public License, version 2.0, for more details. You should have received a copy of the GNU General Public License along with this program; if not, write to the Free Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA */ /** - @file - - MySQL Client Plugin API - + @file include/mysql/client_plugin.h + MySQL Client Plugin API. This file defines the API for plugins that work on the client side */ #define MYSQL_CLIENT_PLUGIN_INCLUDED @@ -35,79 +46,91 @@ for functions. */ -#undef MYSQL_PLUGIN_EXPORT - #if defined(_MSC_VER) -#if defined(MYSQL_DYNAMIC_PLUGIN) - #ifdef __cplusplus - #define MYSQL_PLUGIN_EXPORT extern "C" __declspec(dllexport) - #else - #define MYSQL_PLUGIN_EXPORT __declspec(dllexport) - #endif -#else /* MYSQL_DYNAMIC_PLUGIN */ - #ifdef __cplusplus - #define MYSQL_PLUGIN_EXPORT extern "C" - #else - #define MYSQL_PLUGIN_EXPORT - #endif -#endif /*MYSQL_DYNAMIC_PLUGIN */ -#else /*_MSC_VER */ -#define MYSQL_PLUGIN_EXPORT +#if defined(MYSQL_DYNAMIC_CLIENT_PLUGIN) +#ifdef __cplusplus +#define MYSQL_CLIENT_PLUGIN_EXPORT extern "C" __declspec(dllexport) +#else +#define MYSQL_CLIENT_PLUGIN_EXPORT __declspec(dllexport) +#endif +#else /* MYSQL_DYNAMIC_CLIENT_PLUGIN */ +#ifdef __cplusplus +#define MYSQL_CLIENT_PLUGIN_EXPORT extern "C" +#else +#define MYSQL_CLIENT_PLUGIN_EXPORT #endif +#endif /*MYSQL_DYNAMIC_CLIENT_PLUGIN */ +#else /*_MSC_VER */ +#if defined(MYSQL_DYNAMIC_CLIENT_PLUGIN) +#define MYSQL_CLIENT_PLUGIN_EXPORT MY_ATTRIBUTE((visibility("default"))) +#else +#define MYSQL_CLIENT_PLUGIN_EXPORT +#endif + +#endif #ifdef __cplusplus extern "C" { #endif /* known plugin types */ -#define MYSQL_CLIENT_reserved1 0 -#define MYSQL_CLIENT_reserved2 1 -#define MYSQL_CLIENT_AUTHENTICATION_PLUGIN 2 -#define MYSQL_CLIENT_TRACE_PLUGIN 3 +#define MYSQL_CLIENT_reserved1 0 +#define MYSQL_CLIENT_reserved2 1 +#define MYSQL_CLIENT_AUTHENTICATION_PLUGIN 2 +#define MYSQL_CLIENT_TRACE_PLUGIN 3 +#define MYSQL_CLIENT_TELEMETRY_PLUGIN 4 + +#define MYSQL_CLIENT_AUTHENTICATION_PLUGIN_INTERFACE_VERSION 0x0200 +#define MYSQL_CLIENT_TRACE_PLUGIN_INTERFACE_VERSION 0x0200 +#define MYSQL_CLIENT_TELEMETRY_PLUGIN_INTERFACE_VERSION 0x0200 -#define MYSQL_CLIENT_AUTHENTICATION_PLUGIN_INTERFACE_VERSION 0x0100 -#define MYSQL_CLIENT_TRACE_PLUGIN_INTERFACE_VERSION 0x0100 +#define MYSQL_CLIENT_MAX_PLUGINS 5 -#define MYSQL_CLIENT_MAX_PLUGINS 4 +#define MYSQL_CLIENT_PLUGIN_AUTHOR_ORACLE "Oracle Corporation" -#define mysql_declare_client_plugin(X) \ - MYSQL_PLUGIN_EXPORT struct st_mysql_client_plugin_ ## X \ - _mysql_client_plugin_declaration_ = { \ - MYSQL_CLIENT_ ## X ## _PLUGIN, \ - MYSQL_CLIENT_ ## X ## _PLUGIN_INTERFACE_VERSION, -#define mysql_end_client_plugin } +#define mysql_declare_client_plugin(X) \ + MYSQL_CLIENT_PLUGIN_EXPORT st_mysql_client_plugin_##X \ + _mysql_client_plugin_declaration_ = { \ + MYSQL_CLIENT_##X##_PLUGIN, \ + MYSQL_CLIENT_##X##_PLUGIN_INTERFACE_VERSION, +#define mysql_end_client_plugin } /* generic plugin header structure */ -#define MYSQL_CLIENT_PLUGIN_HEADER \ - int type; \ - unsigned int interface_version; \ - const char *name; \ - const char *author; \ - const char *desc; \ - unsigned int version[3]; \ - const char *license; \ - void *mysql_api; \ - int (*init)(char *, size_t, int, va_list); \ - int (*deinit)(void); \ - int (*options)(const char *option, const void *); - -struct st_mysql_client_plugin -{ +#define MYSQL_CLIENT_PLUGIN_HEADER \ + int type; \ + unsigned int interface_version; \ + const char *name; \ + const char *author; \ + const char *desc; \ + unsigned int version[3]; \ + const char *license; \ + void *mysql_api; \ + int (*init)(char *, size_t, int, va_list); \ + int (*deinit)(void); \ + int (*options)(const char *option, const void *); \ + int (*get_options)(const char *option, void *); + +struct st_mysql_client_plugin { MYSQL_CLIENT_PLUGIN_HEADER }; -struct st_mysql; +struct MYSQL; /******** authentication plugin specific declarations *********/ #include "plugin_auth_common.h" -struct st_mysql_client_plugin_AUTHENTICATION -{ +struct auth_plugin_t { MYSQL_CLIENT_PLUGIN_HEADER - int (*authenticate_user)(MYSQL_PLUGIN_VIO *vio, struct st_mysql *mysql); + int (*authenticate_user)(MYSQL_PLUGIN_VIO *vio, struct MYSQL *mysql); + enum net_async_status (*authenticate_user_nonblocking)(MYSQL_PLUGIN_VIO *vio, + struct MYSQL *mysql, + int *result); }; +// Needed for the mysql_declare_client_plugin() macro. Do not use elsewhere. +typedef struct auth_plugin_t st_mysql_client_plugin_AUTHENTICATION; + /******** using plugins ************/ /** @@ -123,9 +146,9 @@ struct st_mysql_client_plugin_AUTHENTICATION @retval a pointer to the loaded plugin, or NULL in case of a failure */ -struct st_mysql_client_plugin * -mysql_load_plugin(struct st_mysql *mysql, const char *name, int type, - int argc, ...); +struct st_mysql_client_plugin *mysql_load_plugin(struct MYSQL *mysql, + const char *name, int type, + int argc, ...); /** loads a plugin and initializes it, taking va_list as an argument @@ -143,9 +166,9 @@ mysql_load_plugin(struct st_mysql *mysql, const char *name, int type, @retval a pointer to the loaded plugin, or NULL in case of a failure */ -struct st_mysql_client_plugin * -mysql_load_plugin_v(struct st_mysql *mysql, const char *name, int type, - int argc, va_list args); +struct st_mysql_client_plugin *mysql_load_plugin_v(struct MYSQL *mysql, + const char *name, int type, + int argc, va_list args); /** finds an already loaded plugin by name, or loads it, if necessary @@ -157,8 +180,9 @@ mysql_load_plugin_v(struct st_mysql *mysql, const char *name, int type, @retval a pointer to the plugin, or NULL in case of a failure */ -struct st_mysql_client_plugin * -mysql_client_find_plugin(struct st_mysql *mysql, const char *name, int type); +struct st_mysql_client_plugin *mysql_client_find_plugin(struct MYSQL *mysql, + const char *name, + int type); /** adds a plugin structure to the list of loaded plugins @@ -174,9 +198,8 @@ mysql_client_find_plugin(struct st_mysql *mysql, const char *name, int type); @retval a pointer to the plugin, or NULL in case of a failure */ -struct st_mysql_client_plugin * -mysql_client_register_plugin(struct st_mysql *mysql, - struct st_mysql_client_plugin *plugin); +struct st_mysql_client_plugin *mysql_client_register_plugin( + struct MYSQL *mysql, struct st_mysql_client_plugin *plugin); /** set plugin options @@ -193,10 +216,23 @@ mysql_client_register_plugin(struct st_mysql *mysql, int mysql_plugin_options(struct st_mysql_client_plugin *plugin, const char *option, const void *value); +/** + get plugin options + + Can be used to get options from a plugin. + This function may be called multiple times to get several options + + @param plugin an st_mysql_client_plugin structure + @param option a string which specifies the option to get + @param[out] value value for the option. + + @retval 0 on success, 1 in case of failure +**/ +int mysql_plugin_get_option(struct st_mysql_client_plugin *plugin, + const char *option, void *value); #ifdef __cplusplus } #endif #endif - diff --git a/vendor/mysql/include/mysql/client_plugin.h.pp b/vendor/mysql/include/mysql/client_plugin.h.pp deleted file mode 100644 index 47e760ad94..0000000000 --- a/vendor/mysql/include/mysql/client_plugin.h.pp +++ /dev/null @@ -1,39 +0,0 @@ -struct st_mysql_client_plugin -{ - int type; unsigned int interface_version; const char *name; const char *author; const char *desc; unsigned int version[3]; const char *license; void *mysql_api; int (*init)(char *, size_t, int, va_list); int (*deinit)(void); int (*options)(const char *option, const void *); -}; -struct st_mysql; -#include "plugin_auth_common.h" -typedef struct st_plugin_vio_info -{ - enum { MYSQL_VIO_INVALID, MYSQL_VIO_TCP, MYSQL_VIO_SOCKET, - MYSQL_VIO_PIPE, MYSQL_VIO_MEMORY } protocol; - int socket; -} MYSQL_PLUGIN_VIO_INFO; -typedef struct st_plugin_vio -{ - int (*read_packet)(struct st_plugin_vio *vio, - unsigned char **buf); - int (*write_packet)(struct st_plugin_vio *vio, - const unsigned char *packet, - int packet_len); - void (*info)(struct st_plugin_vio *vio, struct st_plugin_vio_info *info); -} MYSQL_PLUGIN_VIO; -struct st_mysql_client_plugin_AUTHENTICATION -{ - int type; unsigned int interface_version; const char *name; const char *author; const char *desc; unsigned int version[3]; const char *license; void *mysql_api; int (*init)(char *, size_t, int, va_list); int (*deinit)(void); int (*options)(const char *option, const void *); - int (*authenticate_user)(MYSQL_PLUGIN_VIO *vio, struct st_mysql *mysql); -}; -struct st_mysql_client_plugin * -mysql_load_plugin(struct st_mysql *mysql, const char *name, int type, - int argc, ...); -struct st_mysql_client_plugin * -mysql_load_plugin_v(struct st_mysql *mysql, const char *name, int type, - int argc, va_list args); -struct st_mysql_client_plugin * -mysql_client_find_plugin(struct st_mysql *mysql, const char *name, int type); -struct st_mysql_client_plugin * -mysql_client_register_plugin(struct st_mysql *mysql, - struct st_mysql_client_plugin *plugin); -int mysql_plugin_options(struct st_mysql_client_plugin *plugin, - const char *option, const void *value); diff --git a/vendor/mysql/include/mysql/get_password.h b/vendor/mysql/include/mysql/get_password.h deleted file mode 100644 index a633c58c46..0000000000 --- a/vendor/mysql/include/mysql/get_password.h +++ /dev/null @@ -1,36 +0,0 @@ -/* Copyright (c) 2000, 2011, Oracle and/or its affiliates. All rights reserved. - - This program is free software; you can redistribute it and/or modify - it under the terms of the GNU General Public License as published by - the Free Software Foundation; version 2 of the License. - - This program is distributed in the hope that it will be useful, - but WITHOUT ANY WARRANTY; without even the implied warranty of - MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - GNU General Public License for more details. - - You should have received a copy of the GNU General Public License - along with this program; if not, write to the Free Software - Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA */ - -/* -** Ask for a password from tty -** This is an own file to avoid conflicts with curses -*/ - -#ifndef MYSQL_GET_PASSWORD_H_INCLUDED -#define MYSQL_GET_PASSWORD_H_INCLUDED - -#ifdef __cplusplus -extern "C" { -#endif - -typedef char *(* strdup_handler_t)(const char *, int); -char *get_tty_password_ext(const char *opt_message, - strdup_handler_t strdup_function); - -#ifdef __cplusplus -} -#endif - -#endif /* ! MYSQL_GET_PASSWORD_H_INCLUDED */ diff --git a/vendor/mysql/include/mysql/mysql_lex_string.h b/vendor/mysql/include/mysql/mysql_lex_string.h deleted file mode 100644 index ce3b6e47d3..0000000000 --- a/vendor/mysql/include/mysql/mysql_lex_string.h +++ /dev/null @@ -1,33 +0,0 @@ -/* Copyright (c) 2015, Oracle and/or its affiliates. All rights reserved. - - This program is free software; you can redistribute it and/or modify - it under the terms of the GNU General Public License as published by - the Free Software Foundation; version 2 of the License. - - This program is distributed in the hope that it will be useful, - but WITHOUT ANY WARRANTY; without even the implied warranty of - MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - GNU General Public License for more details. - - You should have received a copy of the GNU General Public License - along with this program; if not, write to the Free Software - Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA */ - -#ifndef MYSQL_LEX_STRING_INCLUDED -#define MYSQL_LEX_STRING_INCLUDED - -struct st_mysql_lex_string -{ - char *str; - size_t length; -}; -typedef struct st_mysql_lex_string MYSQL_LEX_STRING; - -struct st_mysql_const_lex_string -{ - const char *str; - size_t length; -}; -typedef struct st_mysql_const_lex_string MYSQL_LEX_CSTRING; - -#endif // MYSQL_LEX_STRING_INCLUDED diff --git a/vendor/mysql/include/mysql/plugin_auth_common.h b/vendor/mysql/include/mysql/plugin_auth_common.h index a0033a09b5..18a88c8d9a 100644 --- a/vendor/mysql/include/mysql/plugin_auth_common.h +++ b/vendor/mysql/include/mysql/plugin_auth_common.h @@ -1,21 +1,34 @@ #ifndef MYSQL_PLUGIN_AUTH_COMMON_INCLUDED -/* Copyright (c) 2010, 2015, Oracle and/or its affiliates. All rights reserved. +/* Copyright (c) 2010, 2024, Oracle and/or its affiliates. This program is free software; you can redistribute it and/or modify - it under the terms of the GNU General Public License as published by - the Free Software Foundation; version 2 of the License. + it under the terms of the GNU General Public License, version 2.0, + as published by the Free Software Foundation. + + This program is designed to work with certain software (including + but not limited to OpenSSL) that is licensed under separate terms, + as designated in a particular file or component or in included license + documentation. The authors of MySQL hereby grant you an additional + permission to link the program and your derivative works with the + separately licensed software that they have either included with + the program or referenced in the documentation. + + Without limiting anything contained in the foregoing, this file, + which is part of C Driver for MySQL (Connector/C), is also subject to the + Universal FOSS Exception, version 1.0, a copy of which can be found at + http://oss.oracle.com/licenses/universal-foss-exception. This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - GNU General Public License for more details. + GNU General Public License, version 2.0, for more details. You should have received a copy of the GNU General Public License along with this program; if not, write to the Free Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA */ /** - @file + @file include/mysql/plugin_auth_common.h This file defines constants and data structures that are the same for both client- and server-side authentication plugins. @@ -82,7 +95,12 @@ or not. */ #define CR_OK_HANDSHAKE_COMPLETE -2 - +/** + Authentication was successful with limited operations. + It means that the both client and server side plugins decided to allow + authentication with very limited operations ALTER USER to do registration. +*/ +#define CR_OK_AUTH_IN_SANDBOX_MODE -3 /** Flag to be passed back to server from authentication plugins via authenticated_as when proxy mapping should be done by the server. @@ -93,51 +111,78 @@ authenticated_as when proxy mapping should be done by the server. We need HANDLE definition if on Windows. Define WIN32_LEAN_AND_MEAN (if not already done) to minimize amount of imported declarations. */ -#ifdef _WIN32 +#if defined(_WIN32) && !defined(MYSQL_ABI_CHECK) #ifndef WIN32_LEAN_AND_MEAN #define WIN32_LEAN_AND_MEAN #endif #include #endif -typedef struct st_plugin_vio_info -{ - enum { MYSQL_VIO_INVALID, MYSQL_VIO_TCP, MYSQL_VIO_SOCKET, - MYSQL_VIO_PIPE, MYSQL_VIO_MEMORY } protocol; - int socket; /**< it's set, if the protocol is SOCKET or TCP */ -#ifdef _WIN32 - HANDLE handle; /**< it's set, if the protocol is PIPE or MEMORY */ +struct MYSQL_PLUGIN_VIO_INFO { + enum { + MYSQL_VIO_INVALID, + MYSQL_VIO_TCP, + MYSQL_VIO_SOCKET, + MYSQL_VIO_PIPE, + MYSQL_VIO_MEMORY + } protocol; + int socket; /**< it's set, if the protocol is SOCKET or TCP */ +#if defined(_WIN32) && !defined(MYSQL_ABI_CHECK) + HANDLE handle; /**< it's set, if the protocol is PIPE or MEMORY */ #endif -} MYSQL_PLUGIN_VIO_INFO; +}; + +/* state of an asynchronous operation */ +enum net_async_status { + NET_ASYNC_COMPLETE = 0, + NET_ASYNC_NOT_READY, + NET_ASYNC_ERROR, + NET_ASYNC_COMPLETE_NO_MORE_RESULTS +}; /** Provides plugin access to communication channel */ -typedef struct st_plugin_vio -{ +typedef struct MYSQL_PLUGIN_VIO { /** Plugin provides a pointer reference and this function sets it to the contents of any incoming packet. Returns the packet length, or -1 if the plugin should terminate. */ - int (*read_packet)(struct st_plugin_vio *vio, - unsigned char **buf); - + int (*read_packet)(struct MYSQL_PLUGIN_VIO *vio, unsigned char **buf); + /** Plugin provides a buffer with data and the length and this function sends it as a packet. Returns 0 on success, 1 on failure. */ - int (*write_packet)(struct st_plugin_vio *vio, - const unsigned char *packet, + int (*write_packet)(struct MYSQL_PLUGIN_VIO *vio, const unsigned char *packet, int packet_len); /** - Fills in a st_plugin_vio_info structure, providing the information + Fills in a MYSQL_PLUGIN_VIO_INFO structure, providing the information about the connection. */ - void (*info)(struct st_plugin_vio *vio, struct st_plugin_vio_info *info); + void (*info)(struct MYSQL_PLUGIN_VIO *vio, + struct MYSQL_PLUGIN_VIO_INFO *info); + + /** + Non blocking version of read_packet. This function points buf to starting + position of incoming packet. When this function returns NET_ASYNC_NOT_READY + plugin should call this function again until all incoming packets are read. + If return code is NET_ASYNC_COMPLETE, plugin can do further processing of + read packets. + */ + enum net_async_status (*read_packet_nonblocking)(struct MYSQL_PLUGIN_VIO *vio, + unsigned char **buf, + int *result); + /** + Non blocking version of write_packet. Sends data available in pkt of length + pkt_len to server in asynchronous way. + */ + enum net_async_status (*write_packet_nonblocking)( + struct MYSQL_PLUGIN_VIO *vio, const unsigned char *pkt, int pkt_len, + int *result); } MYSQL_PLUGIN_VIO; #endif - diff --git a/vendor/mysql/include/mysql/plugin_trace.h b/vendor/mysql/include/mysql/plugin_trace.h deleted file mode 100644 index 71ac0b1070..0000000000 --- a/vendor/mysql/include/mysql/plugin_trace.h +++ /dev/null @@ -1,349 +0,0 @@ -/* Copyright (c) 2012, 2013, Oracle and/or its affiliates. All rights reserved. - - This program is free software; you can redistribute it and/or modify - it under the terms of the GNU General Public License as published by - the Free Software Foundation; version 2 of the License. - - This program is distributed in the hope that it will be useful, - but WITHOUT ANY WARRANTY; without even the implied warranty of - MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - GNU General Public License for more details. - - You should have received a copy of the GNU General Public License - along with this program; if not, write to the Free Software - Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA */ - -#ifndef PLUGIN_TRACE_INCLUDED -#define PLUGIN_TRACE_INCLUDED -/** - @file - - ======================================================================== - Declarations for client-side plugins of type MYSQL_CLIENT_TRACE_PLUGIN - ======================================================================== - - See libmysql/mysql_trace.c for a brief description of the client-side - protocol tracing infrastructure. -*/ - - -#include - -#ifdef __cplusplus -extern "C" { -#endif - -/* - Lists of protocol stages and trace events - ========================================= - - These lists are defined with PROTOCOL_STAGE_LIST() and TRACE_EVENT_LIST(), - respectively. Macros accept a disposition name as an argument. - - For example, to process list of protocol stages using disposition "foo", - define protocol_stage_foo(Stage) macro and then put - - PROTOCOL_STAGE_LIST(foo) - - in your code. This will expand to sequence of protocol_stage_foo(X) - macros where X ranges over the list of protocol stages, and these macros - should generate the actual code. See below how this technique is used - to generate protocol_stage and trace_events enums. -*/ - -/** - Protocol stages - --------------- - - A client following the MySQL protocol goes through several stages of it. Each - stage determines what packets can be expected from the server or can be send - by the client. - - Upon receiving each trace event, trace plugin will be notified of the current - protocol stage so that it can correctly interpret the event. - - These are the possible protocol stages and the transitions between them. - - .. digraph:: protocol_stages - - CONNECTING -> WAIT_FOR_INIT_PACKET; - CONNECTING -> DISCONNECTED [ label = "failed connection" ]; - - WAIT_FOR_INIT_PACKET -> AUTHENTICATE; - WAIT_FOR_INIT_PACKET -> SSL_NEGOTIATION -> AUTHENTICATE; - - AUTHENTICATE -> READY_FOR_COMMAND [ label = "accepted" ]; - AUTHENTICATE -> DISCONNECTED [ label = "rejected" ]; - - READY_FOR_COMMAND -> DISCONNECTED [ label = "COM_QUIT" ]; - READY_FOR_COMMAND -> AUTHENTICATE [ label="after change user" ]; - READY_FOR_COMMAND -> WAIT_FOR_PACKET - [ label="wait for a single packet after, e.g., COM_STATISTICS" ]; - READY_FOR_COMMAND -> WAIT_FOR_RESULT; - READY_FOR_COMMAND -> WAIT_FOR_PS_DESCRIPTION - [ label="after prepare command" ]; - - WAIT_FOR_PACKET -> READY_FOR_COMAND; - - WAIT_FOR_RESULT -> READY_FOR_COMMAND [ label="simple reply" ]; - WAIT_FOR_RESULT -> WAIT_FOR_FIELD_DEF; - WAIT_FOR_RESULT -> FILE_REQUEST; - - WAIT_FOR_FIELD_DEF -> WAIT_FOR_ROW [ label="in a resultset" ]; - WAIT_FOR_FIELD_DEF -> READY_FOR_COMMAND - [ label="after describe table or prepare command" ]; - - WAIT_FOR_ROW -> READY_FOR_COMMAND; - WAIT_FOR_ROW -> WAIT_FOR_RESULT [ label="multi-resultset" ]; - - WAIT_FOR_PS_DESCRIPTION -> WAIT_FOR_PARAM_DEF; - WAIT_FOR_PS_DESCRIPTION -> READY_FOR_COMMAND - [ label="no params and result" ]; - WAIT_FOR_PS_DESCRIPTION -> WAIT_FOR_FIELD_DEF [ label="no params" ]; - - WAIT_FOR_PARAM_DEF -> WAIT_FOR_FIELD_DEF; - WAIT_FOR_PARAM_DEF -> READY_FOR_COMMAND [ label="no result" ]; - - FILE_REQUEST -> WAIT_FOR_RESULT [label="when whole file sent"]; -*/ - -#define PROTOCOL_STAGE_LIST(X) \ - protocol_stage_ ## X(CONNECTING) \ - protocol_stage_ ## X(WAIT_FOR_INIT_PACKET) \ - protocol_stage_ ## X(AUTHENTICATE) \ - protocol_stage_ ## X(SSL_NEGOTIATION) \ - protocol_stage_ ## X(READY_FOR_COMMAND) \ - protocol_stage_ ## X(WAIT_FOR_PACKET) \ - protocol_stage_ ## X(WAIT_FOR_RESULT) \ - protocol_stage_ ## X(WAIT_FOR_FIELD_DEF) \ - protocol_stage_ ## X(WAIT_FOR_ROW) \ - protocol_stage_ ## X(FILE_REQUEST) \ - protocol_stage_ ## X(WAIT_FOR_PS_DESCRIPTION) \ - protocol_stage_ ## X(WAIT_FOR_PARAM_DEF) \ - protocol_stage_ ## X(DISCONNECTED) - -/** - Trace events - ------------ - - The following events are generated during the various stages of the - client-server conversation. - - ---------------------- ----------------------------------------------------- - Connection events - ---------------------- ----------------------------------------------------- - CONNECTING Client is connecting to the server. - CONNECTED Physical connection has been established. - DISCONNECTED Connection with server was broken. - ---------------------- ----------------------------------------------------- - SSL events - ---------------------- ----------------------------------------------------- - SEND_SSL_REQUEST Client is sending SSL connection request. - SSL_CONNECT Client is initiating SSL handshake. - SSL_CONNECTED SSL connection has been established. - ---------------------- ----------------------------------------------------- - Authentication events - ---------------------- ----------------------------------------------------- - CHALLENGE_RECEIVED Client received authentication challenge. - AUTH_PLUGIN Client selects an authentication plugin to be used - in the following authentication exchange. - SEND_AUTH_RESPONSE Client sends response to the authentication - challenge. - SEND_AUTH_DATA Client sends extra authentication data packet. - AUTHENTICATED Server has accepted connection. - ---------------------- ----------------------------------------------------- - Command phase events - ---------------------- ----------------------------------------------------- - SEND_COMMAND Client is sending a command to the server. - SEND_FILE Client is sending local file contents to the server. - ---------------------- ----------------------------------------------------- - General events - ---------------------- ----------------------------------------------------- - READ_PACKET Client starts waiting for a packet from server. - PACKET_RECEIVED A packet from server has been received. - PACKET_SENT After successful sending of a packet to the server. - ERROR Client detected an error. - ---------------------- ----------------------------------------------------- -*/ - -#define TRACE_EVENT_LIST(X) \ - trace_event_ ## X(ERROR) \ - trace_event_ ## X(CONNECTING) \ - trace_event_ ## X(CONNECTED) \ - trace_event_ ## X(DISCONNECTED) \ - trace_event_ ## X(SEND_SSL_REQUEST) \ - trace_event_ ## X(SSL_CONNECT) \ - trace_event_ ## X(SSL_CONNECTED) \ - trace_event_ ## X(INIT_PACKET_RECEIVED) \ - trace_event_ ## X(AUTH_PLUGIN) \ - trace_event_ ## X(SEND_AUTH_RESPONSE) \ - trace_event_ ## X(SEND_AUTH_DATA) \ - trace_event_ ## X(AUTHENTICATED) \ - trace_event_ ## X(SEND_COMMAND) \ - trace_event_ ## X(SEND_FILE) \ - trace_event_ ## X(READ_PACKET) \ - trace_event_ ## X(PACKET_RECEIVED) \ - trace_event_ ## X(PACKET_SENT) - -/** - Some trace events have additional arguments. These are stored in - st_trace_event_args structure. Various events store their arguments in the - structure as follows. Unused members are set to 0/NULL. - - AUTH_PLUGIN - ------------- ---------------------------------- - plugin_name the name of the plugin - ------------- ---------------------------------- - - SEND_COMMAND - ------------- ---------------------------------- - cmd the command code - hdr pointer to command packet header - hdr_len length of the header - pkt pointer to command arguments - pkt_len length of arguments - ------------- ---------------------------------- - - Other SEND_* and *_RECEIVED events - ------------- ---------------------------------- - pkt the data sent or received - pkt_len length of the data - ------------- ---------------------------------- - - PACKET_SENT - ------------- ---------------------------------- - pkt_len number of bytes sent - ------------- ---------------------------------- -*/ - -struct st_trace_event_args -{ - const char *plugin_name; - int cmd; - const unsigned char *hdr; - size_t hdr_len; - const unsigned char *pkt; - size_t pkt_len; -}; - - -/* Definitions of protocol_stage and trace_event enums. */ - -#define protocol_stage_enum(X) PROTOCOL_STAGE_ ## X, - -enum protocol_stage { - PROTOCOL_STAGE_LIST(enum) - PROTOCOL_STAGE_LAST -}; - -#define trace_event_enum(X) TRACE_EVENT_ ## X, - -enum trace_event { - TRACE_EVENT_LIST(enum) - TRACE_EVENT_LAST -}; - - -/* - Trace plugin methods - ==================== -*/ - -struct st_mysql_client_plugin_TRACE; -struct st_mysql; - -/** - Trace plugin tracing_start() method. - - Called when tracing with this plugin starts on a connection. A trace - plugin might want to maintain per-connection information. It can - return a pointer to memory area holding such information. It will be - stored in a connection handle and passed to other plugin methods. - - @param self pointer to the plugin instance - @param connection_handle - @param stage protocol stage in which tracing has started - currently - it is always CONNECTING stage. - - @return A pointer to plugin-specific, per-connection data if any. -*/ - -typedef -void* (tracing_start_callback)(struct st_mysql_client_plugin_TRACE *self, - struct st_mysql *connection_handle, - enum protocol_stage stage); - -/** - Trace plugin tracing_stop() method. - - Called when tracing of the connection has ended. If a plugin - allocated any per-connection resources, it should de-allocate them - here. - - @param self pointer to the plugin instance - @param connection_handle - @param plugin_data pointer to plugin's per-connection data. -*/ - -typedef -void (tracing_stop_callback)(struct st_mysql_client_plugin_TRACE *self, - struct st_mysql *connection_handle, - void *plugin_data); - -/** - Trace plugin trace_event() method. - - Called when a trace event occurs. Plugin can decide to stop tracing - this connection by returning non-zero value. - - @param self pointer to the plugin instance - @param plugin_data pointer to plugin's per-connection data - @param connection_handle - @param stage current protocol stage - @param event the trace event - @param args trace event arguments - - @return Non-zero if tracing of the connection should end here. -*/ - -typedef -int (trace_event_handler)(struct st_mysql_client_plugin_TRACE *self, - void *plugin_data, - struct st_mysql *connection_handle, - enum protocol_stage stage, - enum trace_event event, - struct st_trace_event_args args); - - -struct st_mysql_client_plugin_TRACE -{ - MYSQL_CLIENT_PLUGIN_HEADER - tracing_start_callback *tracing_start; - tracing_stop_callback *tracing_stop; - trace_event_handler *trace_event; -}; - -/** - The global trace_plugin pointer. If it is not NULL, it points at a - loaded trace plugin which should be used to trace all connections made - to the server. -*/ -extern -struct st_mysql_client_plugin_TRACE *trace_plugin; - -#ifndef DBUG_OFF - -/* - Functions for getting names of trace events and protocol - stages for debugging purposes. -*/ -const char* protocol_stage_name(enum protocol_stage stage); -const char* trace_event_name(enum trace_event ev); - -#endif - -#ifdef __cplusplus -} -#endif - -#endif diff --git a/vendor/mysql/include/mysql/psi/mysql_file.h b/vendor/mysql/include/mysql/psi/mysql_file.h deleted file mode 100644 index fd28886d7b..0000000000 --- a/vendor/mysql/include/mysql/psi/mysql_file.h +++ /dev/null @@ -1,1433 +0,0 @@ -/* Copyright (c) 2008, 2016, Oracle and/or its affiliates. All rights reserved. - - This program is free software; you can redistribute it and/or modify - it under the terms of the GNU General Public License as published by - the Free Software Foundation; version 2 of the License. - - This program is distributed in the hope that it will be useful, - but WITHOUT ANY WARRANTY; without even the implied warranty of - MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - GNU General Public License for more details. - - You should have received a copy of the GNU General Public License - along with this program; if not, write to the Free Software Foundation, - 51 Franklin Street, Suite 500, Boston, MA 02110-1335 USA */ - -#ifndef MYSQL_FILE_H -#define MYSQL_FILE_H - -#include - -/* For strlen() */ -#include -/* For MY_STAT */ -#include -/* For my_chsize */ -#include - -/** - @file mysql/psi/mysql_file.h - Instrumentation helpers for mysys file io. - This header file provides the necessary declarations - to use the mysys file API with the performance schema instrumentation. - In some compilers (SunStudio), 'static inline' functions, when declared - but not used, are not optimized away (because they are unused) by default, - so that including a static inline function from a header file does - create unwanted dependencies, causing unresolved symbols at link time. - Other compilers, like gcc, optimize these dependencies by default. - - Since the instrumented APIs declared here are wrapper on top - of mysys file io APIs, including mysql/psi/mysql_file.h assumes that - the dependency on my_sys already exists. -*/ - -#include "mysql/psi/psi.h" - -#ifndef PSI_FILE_CALL -#define PSI_FILE_CALL(M) PSI_DYNAMIC_CALL(M) -#endif - -/** - @defgroup File_instrumentation File Instrumentation - @ingroup Instrumentation_interface - @{ -*/ - -/** - @def mysql_file_register(P1, P2, P3) - File registration. -*/ -#define mysql_file_register(P1, P2, P3) \ - inline_mysql_file_register(P1, P2, P3) - -/** - @def mysql_file_fgets(P1, P2, F) - Instrumented fgets. - @c mysql_file_fgets is a replacement for @c fgets. -*/ -#ifdef HAVE_PSI_FILE_INTERFACE - #define mysql_file_fgets(P1, P2, F) \ - inline_mysql_file_fgets(__FILE__, __LINE__, P1, P2, F) -#else - #define mysql_file_fgets(P1, P2, F) \ - inline_mysql_file_fgets(P1, P2, F) -#endif - -/** - @def mysql_file_fgetc(F) - Instrumented fgetc. - @c mysql_file_fgetc is a replacement for @c fgetc. -*/ -#ifdef HAVE_PSI_FILE_INTERFACE - #define mysql_file_fgetc(F) inline_mysql_file_fgetc(__FILE__, __LINE__, F) -#else - #define mysql_file_fgetc(F) inline_mysql_file_fgetc(F) -#endif - -/** - @def mysql_file_fputs(P1, F) - Instrumented fputs. - @c mysql_file_fputs is a replacement for @c fputs. -*/ -#ifdef HAVE_PSI_FILE_INTERFACE - #define mysql_file_fputs(P1, F) \ - inline_mysql_file_fputs(__FILE__, __LINE__, P1, F) -#else - #define mysql_file_fputs(P1, F)\ - inline_mysql_file_fputs(P1, F) -#endif - -/** - @def mysql_file_fputc(P1, F) - Instrumented fputc. - @c mysql_file_fputc is a replacement for @c fputc. -*/ -#ifdef HAVE_PSI_FILE_INTERFACE - #define mysql_file_fputc(P1, F) \ - inline_mysql_file_fputc(__FILE__, __LINE__, P1, F) -#else - #define mysql_file_fputc(P1, F) \ - inline_mysql_file_fputc(P1, F) -#endif - -/** - @def mysql_file_fprintf - Instrumented fprintf. - @c mysql_file_fprintf is a replacement for @c fprintf. -*/ -#define mysql_file_fprintf inline_mysql_file_fprintf - -/** - @def mysql_file_vfprintf(F, P1, P2) - Instrumented vfprintf. - @c mysql_file_vfprintf is a replacement for @c vfprintf. -*/ -#ifdef HAVE_PSI_FILE_INTERFACE - #define mysql_file_vfprintf(F, P1, P2) \ - inline_mysql_file_vfprintf(__FILE__, __LINE__, F, P1, P2) -#else - #define mysql_file_vfprintf(F, P1, P2) \ - inline_mysql_file_vfprintf(F, P1, P2) -#endif - -/** - @def mysql_file_fflush(F, P1, P2) - Instrumented fflush. - @c mysql_file_fflush is a replacement for @c fflush. -*/ -#ifdef HAVE_PSI_FILE_INTERFACE - #define mysql_file_fflush(F) \ - inline_mysql_file_fflush(__FILE__, __LINE__, F) -#else - #define mysql_file_fflush(F) \ - inline_mysql_file_fflush(F) -#endif - -/** - @def mysql_file_feof(F) - Instrumented feof. - @c mysql_file_feof is a replacement for @c feof. -*/ -#define mysql_file_feof(F) inline_mysql_file_feof(F) - -/** - @def mysql_file_fstat(FN, S, FL) - Instrumented fstat. - @c mysql_file_fstat is a replacement for @c my_fstat. -*/ -#ifdef HAVE_PSI_FILE_INTERFACE - #define mysql_file_fstat(FN, S, FL) \ - inline_mysql_file_fstat(__FILE__, __LINE__, FN, S, FL) -#else - #define mysql_file_fstat(FN, S, FL) \ - inline_mysql_file_fstat(FN, S, FL) -#endif - -/** - @def mysql_file_stat(K, FN, S, FL) - Instrumented stat. - @c mysql_file_stat is a replacement for @c my_stat. -*/ -#ifdef HAVE_PSI_FILE_INTERFACE - #define mysql_file_stat(K, FN, S, FL) \ - inline_mysql_file_stat(K, __FILE__, __LINE__, FN, S, FL) -#else - #define mysql_file_stat(K, FN, S, FL) \ - inline_mysql_file_stat(FN, S, FL) -#endif - -/** - @def mysql_file_chsize(F, P1, P2, P3) - Instrumented chsize. - @c mysql_file_chsize is a replacement for @c my_chsize. -*/ -#ifdef HAVE_PSI_FILE_INTERFACE - #define mysql_file_chsize(F, P1, P2, P3) \ - inline_mysql_file_chsize(__FILE__, __LINE__, F, P1, P2, P3) -#else - #define mysql_file_chsize(F, P1, P2, P3) \ - inline_mysql_file_chsize(F, P1, P2, P3) -#endif - -/** - @def mysql_file_fopen(K, N, F1, F2) - Instrumented fopen. - @c mysql_file_fopen is a replacement for @c my_fopen. -*/ -#ifdef HAVE_PSI_FILE_INTERFACE - #define mysql_file_fopen(K, N, F1, F2) \ - inline_mysql_file_fopen(K, __FILE__, __LINE__, N, F1, F2) -#else - #define mysql_file_fopen(K, N, F1, F2) \ - inline_mysql_file_fopen(N, F1, F2) -#endif - -/** - @def mysql_file_fclose(FD, FL) - Instrumented fclose. - @c mysql_file_fclose is a replacement for @c my_fclose. - Without the instrumentation, this call will have the same behavior as the - undocumented and possibly platform specific my_fclose(NULL, ...) behavior. - With the instrumentation, mysql_fclose(NULL, ...) will safely return 0, - which is an extension compared to my_fclose and is therefore compliant. - mysql_fclose is on purpose *not* implementing - @code DBUG_ASSERT(file != NULL) @endcode, - since doing so could introduce regressions. -*/ -#ifdef HAVE_PSI_FILE_INTERFACE - #define mysql_file_fclose(FD, FL) \ - inline_mysql_file_fclose(__FILE__, __LINE__, FD, FL) -#else - #define mysql_file_fclose(FD, FL) \ - inline_mysql_file_fclose(FD, FL) -#endif - -/** - @def mysql_file_fread(FD, P1, P2, P3) - Instrumented fread. - @c mysql_file_fread is a replacement for @c my_fread. -*/ -#ifdef HAVE_PSI_FILE_INTERFACE - #define mysql_file_fread(FD, P1, P2, P3) \ - inline_mysql_file_fread(__FILE__, __LINE__, FD, P1, P2, P3) -#else - #define mysql_file_fread(FD, P1, P2, P3) \ - inline_mysql_file_fread(FD, P1, P2, P3) -#endif - -/** - @def mysql_file_fwrite(FD, P1, P2, P3) - Instrumented fwrite. - @c mysql_file_fwrite is a replacement for @c my_fwrite. -*/ -#ifdef HAVE_PSI_FILE_INTERFACE - #define mysql_file_fwrite(FD, P1, P2, P3) \ - inline_mysql_file_fwrite(__FILE__, __LINE__, FD, P1, P2, P3) -#else - #define mysql_file_fwrite(FD, P1, P2, P3) \ - inline_mysql_file_fwrite(FD, P1, P2, P3) -#endif - -/** - @def mysql_file_fseek(FD, P, W, F) - Instrumented fseek. - @c mysql_file_fseek is a replacement for @c my_fseek. -*/ -#ifdef HAVE_PSI_FILE_INTERFACE - #define mysql_file_fseek(FD, P, W, F) \ - inline_mysql_file_fseek(__FILE__, __LINE__, FD, P, W, F) -#else - #define mysql_file_fseek(FD, P, W, F) \ - inline_mysql_file_fseek(FD, P, W, F) -#endif - -/** - @def mysql_file_ftell(FD, F) - Instrumented ftell. - @c mysql_file_ftell is a replacement for @c my_ftell. -*/ -#ifdef HAVE_PSI_FILE_INTERFACE - #define mysql_file_ftell(FD, F) \ - inline_mysql_file_ftell(__FILE__, __LINE__, FD, F) -#else - #define mysql_file_ftell(FD, F) \ - inline_mysql_file_ftell(FD, F) -#endif - -/** - @def mysql_file_create(K, N, F1, F2, F3) - Instrumented create. - @c mysql_file_create is a replacement for @c my_create. -*/ -#ifdef HAVE_PSI_FILE_INTERFACE - #define mysql_file_create(K, N, F1, F2, F3) \ - inline_mysql_file_create(K, __FILE__, __LINE__, N, F1, F2, F3) -#else - #define mysql_file_create(K, N, F1, F2, F3) \ - inline_mysql_file_create(N, F1, F2, F3) -#endif - -/** - @def mysql_file_create_temp(K, T, D, P, M, F) - Instrumented create_temp_file. - @c mysql_file_create_temp is a replacement for @c create_temp_file. -*/ -#ifdef HAVE_PSI_FILE_INTERFACE - #define mysql_file_create_temp(K, T, D, P, M, F) \ - inline_mysql_file_create_temp(K, __FILE__, __LINE__, T, D, P, M, F) -#else - #define mysql_file_create_temp(K, T, D, P, M, F) \ - inline_mysql_file_create_temp(T, D, P, M, F) -#endif - -/** - @def mysql_file_open(K, N, F1, F2) - Instrumented open. - @c mysql_file_open is a replacement for @c my_open. -*/ -#ifdef HAVE_PSI_FILE_INTERFACE - #define mysql_file_open(K, N, F1, F2) \ - inline_mysql_file_open(K, __FILE__, __LINE__, N, F1, F2) -#else - #define mysql_file_open(K, N, F1, F2) \ - inline_mysql_file_open(N, F1, F2) -#endif - -/** - @def mysql_file_close(FD, F) - Instrumented close. - @c mysql_file_close is a replacement for @c my_close. -*/ -#ifdef HAVE_PSI_FILE_INTERFACE - #define mysql_file_close(FD, F) \ - inline_mysql_file_close(__FILE__, __LINE__, FD, F) -#else - #define mysql_file_close(FD, F) \ - inline_mysql_file_close(FD, F) -#endif - -/** - @def mysql_file_read(FD, B, S, F) - Instrumented read. - @c mysql_read is a replacement for @c my_read. -*/ -#ifdef HAVE_PSI_FILE_INTERFACE - #define mysql_file_read(FD, B, S, F) \ - inline_mysql_file_read(__FILE__, __LINE__, FD, B, S, F) -#else - #define mysql_file_read(FD, B, S, F) \ - inline_mysql_file_read(FD, B, S, F) -#endif - -/** - @def mysql_file_write(FD, B, S, F) - Instrumented write. - @c mysql_file_write is a replacement for @c my_write. -*/ -#ifdef HAVE_PSI_FILE_INTERFACE - #define mysql_file_write(FD, B, S, F) \ - inline_mysql_file_write(__FILE__, __LINE__, FD, B, S, F) -#else - #define mysql_file_write(FD, B, S, F) \ - inline_mysql_file_write(FD, B, S, F) -#endif - -/** - @def mysql_file_pread(FD, B, S, O, F) - Instrumented pread. - @c mysql_pread is a replacement for @c my_pread. -*/ -#ifdef HAVE_PSI_FILE_INTERFACE - #define mysql_file_pread(FD, B, S, O, F) \ - inline_mysql_file_pread(__FILE__, __LINE__, FD, B, S, O, F) -#else - #define mysql_file_pread(FD, B, S, O, F) \ - inline_mysql_file_pread(FD, B, S, O, F) -#endif - -/** - @def mysql_file_pwrite(FD, B, S, O, F) - Instrumented pwrite. - @c mysql_file_pwrite is a replacement for @c my_pwrite. -*/ -#ifdef HAVE_PSI_FILE_INTERFACE - #define mysql_file_pwrite(FD, B, S, O, F) \ - inline_mysql_file_pwrite(__FILE__, __LINE__, FD, B, S, O, F) -#else - #define mysql_file_pwrite(FD, B, S, O, F) \ - inline_mysql_file_pwrite(FD, B, S, O, F) -#endif - -/** - @def mysql_file_seek(FD, P, W, F) - Instrumented seek. - @c mysql_file_seek is a replacement for @c my_seek. -*/ -#ifdef HAVE_PSI_FILE_INTERFACE - #define mysql_file_seek(FD, P, W, F) \ - inline_mysql_file_seek(__FILE__, __LINE__, FD, P, W, F) -#else - #define mysql_file_seek(FD, P, W, F) \ - inline_mysql_file_seek(FD, P, W, F) -#endif - -/** - @def mysql_file_tell(FD, F) - Instrumented tell. - @c mysql_file_tell is a replacement for @c my_tell. -*/ -#ifdef HAVE_PSI_FILE_INTERFACE - #define mysql_file_tell(FD, F) \ - inline_mysql_file_tell(__FILE__, __LINE__, FD, F) -#else - #define mysql_file_tell(FD, F) \ - inline_mysql_file_tell(FD, F) -#endif - -/** - @def mysql_file_delete(K, P1, P2) - Instrumented delete. - @c mysql_file_delete is a replacement for @c my_delete. -*/ -#ifdef HAVE_PSI_FILE_INTERFACE - #define mysql_file_delete(K, P1, P2) \ - inline_mysql_file_delete(K, __FILE__, __LINE__, P1, P2) -#else - #define mysql_file_delete(K, P1, P2) \ - inline_mysql_file_delete(P1, P2) -#endif - -/** - @def mysql_file_rename(K, P1, P2, P3) - Instrumented rename. - @c mysql_file_rename is a replacement for @c my_rename. -*/ -#ifdef HAVE_PSI_FILE_INTERFACE - #define mysql_file_rename(K, P1, P2, P3) \ - inline_mysql_file_rename(K, __FILE__, __LINE__, P1, P2, P3) -#else - #define mysql_file_rename(K, P1, P2, P3) \ - inline_mysql_file_rename(P1, P2, P3) -#endif - -/** - @def mysql_file_create_with_symlink(K, P1, P2, P3, P4, P5) - Instrumented create with symbolic link. - @c mysql_file_create_with_symlink is a replacement - for @c my_create_with_symlink. -*/ -#ifdef HAVE_PSI_FILE_INTERFACE - #define mysql_file_create_with_symlink(K, P1, P2, P3, P4, P5) \ - inline_mysql_file_create_with_symlink(K, __FILE__, __LINE__, \ - P1, P2, P3, P4, P5) -#else - #define mysql_file_create_with_symlink(K, P1, P2, P3, P4, P5) \ - inline_mysql_file_create_with_symlink(P1, P2, P3, P4, P5) -#endif - -/** - @def mysql_file_delete_with_symlink(K, P1, P2) - Instrumented delete with symbolic link. - @c mysql_file_delete_with_symlink is a replacement - for @c my_delete_with_symlink. -*/ -#ifdef HAVE_PSI_FILE_INTERFACE - #define mysql_file_delete_with_symlink(K, P1, P2) \ - inline_mysql_file_delete_with_symlink(K, __FILE__, __LINE__, P1, P2) -#else - #define mysql_file_delete_with_symlink(K, P1, P2) \ - inline_mysql_file_delete_with_symlink(P1, P2) -#endif - -/** - @def mysql_file_rename_with_symlink(K, P1, P2, P3) - Instrumented rename with symbolic link. - @c mysql_file_rename_with_symlink is a replacement - for @c my_rename_with_symlink. -*/ -#ifdef HAVE_PSI_FILE_INTERFACE - #define mysql_file_rename_with_symlink(K, P1, P2, P3) \ - inline_mysql_file_rename_with_symlink(K, __FILE__, __LINE__, P1, P2, P3) -#else - #define mysql_file_rename_with_symlink(K, P1, P2, P3) \ - inline_mysql_file_rename_with_symlink(P1, P2, P3) -#endif - -/** - @def mysql_file_sync(P1, P2) - Instrumented file sync. - @c mysql_file_sync is a replacement for @c my_sync. -*/ -#ifdef HAVE_PSI_FILE_INTERFACE - #define mysql_file_sync(P1, P2) \ - inline_mysql_file_sync(__FILE__, __LINE__, P1, P2) -#else - #define mysql_file_sync(P1, P2) \ - inline_mysql_file_sync(P1, P2) -#endif - -/** - An instrumented FILE structure. - @sa MYSQL_FILE -*/ -struct st_mysql_file -{ - /** The real file. */ - FILE *m_file; - /** - The instrumentation hook. - Note that this hook is not conditionally defined, - for binary compatibility of the @c MYSQL_FILE interface. - */ - struct PSI_file *m_psi; -}; - -/** - Type of an instrumented file. - @c MYSQL_FILE is a drop-in replacement for @c FILE. - @sa mysql_file_open -*/ -typedef struct st_mysql_file MYSQL_FILE; - -static inline void inline_mysql_file_register( -#ifdef HAVE_PSI_FILE_INTERFACE - const char *category, - PSI_file_info *info, - int count -#else - const char *category MY_ATTRIBUTE ((unused)), - void *info MY_ATTRIBUTE ((unused)), - int count MY_ATTRIBUTE ((unused)) -#endif -) -{ -#ifdef HAVE_PSI_FILE_INTERFACE - PSI_FILE_CALL(register_file)(category, info, count); -#endif -} - -static inline char * -inline_mysql_file_fgets( -#ifdef HAVE_PSI_FILE_INTERFACE - const char *src_file, uint src_line, -#endif - char *str, int size, MYSQL_FILE *file) -{ - char *result; -#ifdef HAVE_PSI_FILE_INTERFACE - struct PSI_file_locker *locker; - PSI_file_locker_state state; - locker= PSI_FILE_CALL(get_thread_file_stream_locker) - (&state, file->m_psi, PSI_FILE_READ); - if (likely(locker != NULL)) - { - PSI_FILE_CALL(start_file_wait)(locker, (size_t) size, src_file, src_line); - result= fgets(str, size, file->m_file); - PSI_FILE_CALL(end_file_wait)(locker, result ? strlen(result) : 0); - return result; - } -#endif - - result= fgets(str, size, file->m_file); - return result; -} - -static inline int -inline_mysql_file_fgetc( -#ifdef HAVE_PSI_FILE_INTERFACE - const char *src_file, uint src_line, -#endif - MYSQL_FILE *file) -{ - int result; -#ifdef HAVE_PSI_FILE_INTERFACE - struct PSI_file_locker *locker; - PSI_file_locker_state state; - locker= PSI_FILE_CALL(get_thread_file_stream_locker) - (&state, file->m_psi, PSI_FILE_READ); - if (likely(locker != NULL)) - { - PSI_FILE_CALL(start_file_wait)(locker, (size_t) 1, src_file, src_line); - result= fgetc(file->m_file); - PSI_FILE_CALL(end_file_wait)(locker, (size_t) 1); - return result; - } -#endif - - result= fgetc(file->m_file); - return result; -} - -static inline int -inline_mysql_file_fputs( -#ifdef HAVE_PSI_FILE_INTERFACE - const char *src_file, uint src_line, -#endif - const char *str, MYSQL_FILE *file) -{ - int result; -#ifdef HAVE_PSI_FILE_INTERFACE - struct PSI_file_locker *locker; - PSI_file_locker_state state; - size_t bytes; - locker= PSI_FILE_CALL(get_thread_file_stream_locker) - (&state, file->m_psi, PSI_FILE_WRITE); - if (likely(locker != NULL)) - { - bytes= str ? strlen(str) : 0; - PSI_FILE_CALL(start_file_wait)(locker, bytes, src_file, src_line); - result= fputs(str, file->m_file); - PSI_FILE_CALL(end_file_wait)(locker, bytes); - return result; - } -#endif - - result= fputs(str, file->m_file); - return result; -} - -static inline int -inline_mysql_file_fputc( -#ifdef HAVE_PSI_FILE_INTERFACE - const char *src_file, uint src_line, -#endif - char c, MYSQL_FILE *file) -{ - int result; -#ifdef HAVE_PSI_FILE_INTERFACE - struct PSI_file_locker *locker; - PSI_file_locker_state state; - locker= PSI_FILE_CALL(get_thread_file_stream_locker) - (&state, file->m_psi, PSI_FILE_WRITE); - if (likely(locker != NULL)) - { - PSI_FILE_CALL(start_file_wait)(locker, (size_t) 1, src_file, src_line); - result= fputc(c, file->m_file); - PSI_FILE_CALL(end_file_wait)(locker, (size_t) 1); - return result; - } -#endif - - result= fputc(c, file->m_file); - return result; -} - -static inline int -inline_mysql_file_fprintf(MYSQL_FILE *file, const char *format, ...) -{ - /* - TODO: figure out how to pass src_file and src_line from the caller. - */ - int result; - va_list args; -#ifdef HAVE_PSI_FILE_INTERFACE - struct PSI_file_locker *locker; - PSI_file_locker_state state; - locker= PSI_FILE_CALL(get_thread_file_stream_locker) - (&state, file->m_psi, PSI_FILE_WRITE); - if (likely(locker != NULL)) - { - PSI_FILE_CALL(start_file_wait)(locker, (size_t) 0, __FILE__, __LINE__); - va_start(args, format); - result= vfprintf(file->m_file, format, args); - va_end(args); - PSI_FILE_CALL(end_file_wait)(locker, (size_t) result); - return result; - } -#endif - - va_start(args, format); - result= vfprintf(file->m_file, format, args); - va_end(args); - return result; -} - -static inline int -inline_mysql_file_vfprintf( -#ifdef HAVE_PSI_FILE_INTERFACE - const char *src_file, uint src_line, -#endif - MYSQL_FILE *file, const char *format, va_list args) -{ - int result; -#ifdef HAVE_PSI_FILE_INTERFACE - struct PSI_file_locker *locker; - PSI_file_locker_state state; - locker= PSI_FILE_CALL(get_thread_file_stream_locker) - (&state, file->m_psi, PSI_FILE_WRITE); - if (likely(locker != NULL)) - { - PSI_FILE_CALL(start_file_wait)(locker, (size_t) 0, src_file, src_line); - result= vfprintf(file->m_file, format, args); - PSI_FILE_CALL(end_file_wait)(locker, (size_t) result); - return result; - } -#endif - - result= vfprintf(file->m_file, format, args); - return result; -} - -static inline int -inline_mysql_file_fflush( -#ifdef HAVE_PSI_FILE_INTERFACE - const char *src_file, uint src_line, -#endif - MYSQL_FILE *file) -{ - int result; -#ifdef HAVE_PSI_FILE_INTERFACE - struct PSI_file_locker *locker; - PSI_file_locker_state state; - locker= PSI_FILE_CALL(get_thread_file_stream_locker) - (&state, file->m_psi, PSI_FILE_FLUSH); - if (likely(locker != NULL)) - { - PSI_FILE_CALL(start_file_wait)(locker, (size_t) 0, src_file, src_line); - result= fflush(file->m_file); - PSI_FILE_CALL(end_file_wait)(locker, (size_t) 0); - return result; - } -#endif - - result= fflush(file->m_file); - return result; -} - -static inline int inline_mysql_file_feof(MYSQL_FILE *file) -{ - /* Not instrumented, there is no wait involved */ - return feof(file->m_file); -} - -static inline int -inline_mysql_file_fstat( -#ifdef HAVE_PSI_FILE_INTERFACE - const char *src_file, uint src_line, -#endif - int filenr, MY_STAT *stat_area, myf flags) -{ - int result; -#ifdef HAVE_PSI_FILE_INTERFACE - struct PSI_file_locker *locker; - PSI_file_locker_state state; - locker= PSI_FILE_CALL(get_thread_file_descriptor_locker) - (&state, filenr, PSI_FILE_FSTAT); - if (likely(locker != NULL)) - { - PSI_FILE_CALL(start_file_wait)(locker, (size_t) 0, src_file, src_line); - result= my_fstat(filenr, stat_area, flags); - PSI_FILE_CALL(end_file_wait)(locker, (size_t) 0); - return result; - } -#endif - - result= my_fstat(filenr, stat_area, flags); - return result; -} - -static inline MY_STAT * -inline_mysql_file_stat( -#ifdef HAVE_PSI_FILE_INTERFACE - PSI_file_key key, const char *src_file, uint src_line, -#endif - const char *path, MY_STAT *stat_area, myf flags) -{ - MY_STAT *result; -#ifdef HAVE_PSI_FILE_INTERFACE - struct PSI_file_locker *locker; - PSI_file_locker_state state; - locker= PSI_FILE_CALL(get_thread_file_name_locker) - (&state, key, PSI_FILE_STAT, path, &locker); - if (likely(locker != NULL)) - { - PSI_FILE_CALL(start_file_open_wait)(locker, src_file, src_line); - result= my_stat(path, stat_area, flags); - PSI_FILE_CALL(end_file_open_wait)(locker, result); - return result; - } -#endif - - result= my_stat(path, stat_area, flags); - return result; -} - -static inline int -inline_mysql_file_chsize( -#ifdef HAVE_PSI_FILE_INTERFACE - const char *src_file, uint src_line, -#endif - File file, my_off_t newlength, int filler, myf flags) -{ - int result; -#ifdef HAVE_PSI_FILE_INTERFACE - struct PSI_file_locker *locker; - PSI_file_locker_state state; - locker= PSI_FILE_CALL(get_thread_file_descriptor_locker) - (&state, file, PSI_FILE_CHSIZE); - if (likely(locker != NULL)) - { - PSI_FILE_CALL(start_file_wait)(locker, (size_t) newlength, src_file, - src_line); - result= my_chsize(file, newlength, filler, flags); - PSI_FILE_CALL(end_file_wait)(locker, (size_t) newlength); - return result; - } -#endif - - result= my_chsize(file, newlength, filler, flags); - return result; -} - -static inline MYSQL_FILE* -inline_mysql_file_fopen( -#ifdef HAVE_PSI_FILE_INTERFACE - PSI_file_key key, const char *src_file, uint src_line, -#endif - const char *filename, int flags, myf myFlags) -{ - MYSQL_FILE *that; - that= (MYSQL_FILE*) my_malloc(PSI_NOT_INSTRUMENTED, - sizeof(MYSQL_FILE), MYF(MY_WME)); - if (likely(that != NULL)) - { -#ifdef HAVE_PSI_FILE_INTERFACE - struct PSI_file_locker *locker; - PSI_file_locker_state state; - locker= PSI_FILE_CALL(get_thread_file_name_locker) - (&state, key, PSI_FILE_STREAM_OPEN, filename, that); - if (likely(locker != NULL)) - { - PSI_FILE_CALL(start_file_open_wait) - (locker, src_file, src_line); - that->m_file= my_fopen(filename, flags, myFlags); - that->m_psi= PSI_FILE_CALL(end_file_open_wait)(locker, that->m_file); - if (unlikely(that->m_file == NULL)) - { - my_free(that); - return NULL; - } - return that; - } -#endif - - that->m_psi= NULL; - that->m_file= my_fopen(filename, flags, myFlags); - if (unlikely(that->m_file == NULL)) - { - my_free(that); - return NULL; - } - } - return that; -} - -static inline int -inline_mysql_file_fclose( -#ifdef HAVE_PSI_FILE_INTERFACE - const char *src_file, uint src_line, -#endif - MYSQL_FILE *file, myf flags) -{ - int result= 0; - if (likely(file != NULL)) - { -#ifdef HAVE_PSI_FILE_INTERFACE - struct PSI_file_locker *locker; - PSI_file_locker_state state; - locker= PSI_FILE_CALL(get_thread_file_stream_locker) - (&state, file->m_psi, PSI_FILE_STREAM_CLOSE); - if (likely(locker != NULL)) - { - PSI_FILE_CALL(start_file_close_wait)(locker, src_file, src_line); - result= my_fclose(file->m_file, flags); - PSI_FILE_CALL(end_file_close_wait)(locker, result); - my_free(file); - return result; - } -#endif - - result= my_fclose(file->m_file, flags); - my_free(file); - } - return result; -} - -static inline size_t -inline_mysql_file_fread( -#ifdef HAVE_PSI_FILE_INTERFACE - const char *src_file, uint src_line, -#endif - MYSQL_FILE *file, uchar *buffer, size_t count, myf flags) -{ - size_t result; -#ifdef HAVE_PSI_FILE_INTERFACE - struct PSI_file_locker *locker; - PSI_file_locker_state state; - size_t bytes_read; - locker= PSI_FILE_CALL(get_thread_file_stream_locker) - (&state, file->m_psi, PSI_FILE_READ); - if (likely(locker != NULL)) - { - PSI_FILE_CALL(start_file_wait)(locker, count, src_file, src_line); - result= my_fread(file->m_file, buffer, count, flags); - if (flags & (MY_NABP | MY_FNABP)) - bytes_read= (result == 0) ? count : 0; - else - bytes_read= (result != MY_FILE_ERROR) ? result : 0; - PSI_FILE_CALL(end_file_wait)(locker, bytes_read); - return result; - } -#endif - - result= my_fread(file->m_file, buffer, count, flags); - return result; -} - -static inline size_t -inline_mysql_file_fwrite( -#ifdef HAVE_PSI_FILE_INTERFACE - const char *src_file, uint src_line, -#endif - MYSQL_FILE *file, const uchar *buffer, size_t count, myf flags) -{ - size_t result; -#ifdef HAVE_PSI_FILE_INTERFACE - struct PSI_file_locker *locker; - PSI_file_locker_state state; - size_t bytes_written; - locker= PSI_FILE_CALL(get_thread_file_stream_locker) - (&state, file->m_psi, PSI_FILE_WRITE); - if (likely(locker != NULL)) - { - PSI_FILE_CALL(start_file_wait)(locker, count, src_file, src_line); - result= my_fwrite(file->m_file, buffer, count, flags); - if (flags & (MY_NABP | MY_FNABP)) - bytes_written= (result == 0) ? count : 0; - else - bytes_written= (result != MY_FILE_ERROR) ? result : 0; - PSI_FILE_CALL(end_file_wait)(locker, bytes_written); - return result; - } -#endif - - result= my_fwrite(file->m_file, buffer, count, flags); - return result; -} - -static inline my_off_t -inline_mysql_file_fseek( -#ifdef HAVE_PSI_FILE_INTERFACE - const char *src_file, uint src_line, -#endif - MYSQL_FILE *file, my_off_t pos, int whence, myf flags) -{ - my_off_t result; -#ifdef HAVE_PSI_FILE_INTERFACE - struct PSI_file_locker *locker; - PSI_file_locker_state state; - locker= PSI_FILE_CALL(get_thread_file_stream_locker) - (&state, file->m_psi, PSI_FILE_SEEK); - if (likely(locker != NULL)) - { - PSI_FILE_CALL(start_file_wait)(locker, (size_t) 0, src_file, src_line); - result= my_fseek(file->m_file, pos, whence, flags); - PSI_FILE_CALL(end_file_wait)(locker, (size_t) 0); - return result; - } -#endif - - result= my_fseek(file->m_file, pos, whence, flags); - return result; -} - -static inline my_off_t -inline_mysql_file_ftell( -#ifdef HAVE_PSI_FILE_INTERFACE - const char *src_file, uint src_line, -#endif - MYSQL_FILE *file, myf flags) -{ - my_off_t result; -#ifdef HAVE_PSI_FILE_INTERFACE - struct PSI_file_locker *locker; - PSI_file_locker_state state; - locker= PSI_FILE_CALL(get_thread_file_stream_locker) - (&state, file->m_psi, PSI_FILE_TELL); - if (likely(locker != NULL)) - { - PSI_FILE_CALL(start_file_wait)(locker, (size_t) 0, src_file, src_line); - result= my_ftell(file->m_file, flags); - PSI_FILE_CALL(end_file_wait)(locker, (size_t) 0); - return result; - } -#endif - - result= my_ftell(file->m_file, flags); - return result; -} - -static inline File -inline_mysql_file_create( -#ifdef HAVE_PSI_FILE_INTERFACE - PSI_file_key key, const char *src_file, uint src_line, -#endif - const char *filename, int create_flags, int access_flags, myf myFlags) -{ - File file; -#ifdef HAVE_PSI_FILE_INTERFACE - struct PSI_file_locker *locker; - PSI_file_locker_state state; - locker= PSI_FILE_CALL(get_thread_file_name_locker) - (&state, key, PSI_FILE_CREATE, filename, &locker); - if (likely(locker != NULL)) - { - PSI_FILE_CALL(start_file_open_wait)(locker, src_file, src_line); - file= my_create(filename, create_flags, access_flags, myFlags); - PSI_FILE_CALL(end_file_open_wait_and_bind_to_descriptor)(locker, file); - return file; - } -#endif - - file= my_create(filename, create_flags, access_flags, myFlags); - return file; -} - -static inline File -inline_mysql_file_create_temp( -#ifdef HAVE_PSI_FILE_INTERFACE - PSI_file_key key, const char *src_file, uint src_line, -#endif - char *to, const char *dir, const char *pfx, int mode, myf myFlags) -{ - File file; -#ifdef HAVE_PSI_FILE_INTERFACE - struct PSI_file_locker *locker; - PSI_file_locker_state state; - locker= PSI_FILE_CALL(get_thread_file_name_locker) - (&state, key, PSI_FILE_CREATE, NULL, &locker); - if (likely(locker != NULL)) - { - PSI_FILE_CALL(start_file_open_wait)(locker, src_file, src_line); - /* The file name is generated by create_temp_file(). */ - file= create_temp_file(to, dir, pfx, mode, myFlags); - PSI_FILE_CALL(end_temp_file_open_wait_and_bind_to_descriptor)(locker, file, (const char*)to); - return file; - } -#endif - - file= create_temp_file(to, dir, pfx, mode, myFlags); - return file; -} - -static inline File -inline_mysql_file_open( -#ifdef HAVE_PSI_FILE_INTERFACE - PSI_file_key key, const char *src_file, uint src_line, -#endif - const char *filename, int flags, myf myFlags) -{ - File file; -#ifdef HAVE_PSI_FILE_INTERFACE - struct PSI_file_locker *locker; - PSI_file_locker_state state; - locker= PSI_FILE_CALL(get_thread_file_name_locker) - (&state, key, PSI_FILE_OPEN, filename, &locker); - if (likely(locker != NULL)) - { - PSI_FILE_CALL(start_file_open_wait)(locker, src_file, src_line); - file= my_open(filename, flags, myFlags); - PSI_FILE_CALL(end_file_open_wait_and_bind_to_descriptor)(locker, file); - return file; - } -#endif - - file= my_open(filename, flags, myFlags); - return file; -} - -static inline int -inline_mysql_file_close( -#ifdef HAVE_PSI_FILE_INTERFACE - const char *src_file, uint src_line, -#endif - File file, myf flags) -{ - int result; -#ifdef HAVE_PSI_FILE_INTERFACE - struct PSI_file_locker *locker; - PSI_file_locker_state state; - locker= PSI_FILE_CALL(get_thread_file_descriptor_locker) - (&state, file, PSI_FILE_CLOSE); - if (likely(locker != NULL)) - { - PSI_FILE_CALL(start_file_close_wait)(locker, src_file, src_line); - result= my_close(file, flags); - PSI_FILE_CALL(end_file_close_wait)(locker, result); - return result; - } -#endif - - result= my_close(file, flags); - return result; -} - -static inline size_t -inline_mysql_file_read( -#ifdef HAVE_PSI_FILE_INTERFACE - const char *src_file, uint src_line, -#endif - File file, uchar *buffer, size_t count, myf flags) -{ - size_t result; -#ifdef HAVE_PSI_FILE_INTERFACE - struct PSI_file_locker *locker; - PSI_file_locker_state state; - size_t bytes_read; - locker= PSI_FILE_CALL(get_thread_file_descriptor_locker) - (&state, file, PSI_FILE_READ); - if (likely(locker != NULL)) - { - PSI_FILE_CALL(start_file_wait)(locker, count, src_file, src_line); - result= my_read(file, buffer, count, flags); - if (flags & (MY_NABP | MY_FNABP)) - bytes_read= (result == 0) ? count : 0; - else - bytes_read= (result != MY_FILE_ERROR) ? result : 0; - PSI_FILE_CALL(end_file_wait)(locker, bytes_read); - return result; - } -#endif - - result= my_read(file, buffer, count, flags); - return result; -} - -static inline size_t -inline_mysql_file_write( -#ifdef HAVE_PSI_FILE_INTERFACE - const char *src_file, uint src_line, -#endif - File file, const uchar *buffer, size_t count, myf flags) -{ - size_t result; -#ifdef HAVE_PSI_FILE_INTERFACE - struct PSI_file_locker *locker; - PSI_file_locker_state state; - size_t bytes_written; - locker= PSI_FILE_CALL(get_thread_file_descriptor_locker) - (&state, file, PSI_FILE_WRITE); - if (likely(locker != NULL)) - { - PSI_FILE_CALL(start_file_wait)(locker, count, src_file, src_line); - result= my_write(file, buffer, count, flags); - if (flags & (MY_NABP | MY_FNABP)) - bytes_written= (result == 0) ? count : 0; - else - bytes_written= (result != MY_FILE_ERROR) ? result : 0; - PSI_FILE_CALL(end_file_wait)(locker, bytes_written); - return result; - } -#endif - - result= my_write(file, buffer, count, flags); - return result; -} - -static inline size_t -inline_mysql_file_pread( -#ifdef HAVE_PSI_FILE_INTERFACE - const char *src_file, uint src_line, -#endif - File file, uchar *buffer, size_t count, my_off_t offset, myf flags) -{ - size_t result; -#ifdef HAVE_PSI_FILE_INTERFACE - struct PSI_file_locker *locker; - PSI_file_locker_state state; - size_t bytes_read; - locker= PSI_FILE_CALL(get_thread_file_descriptor_locker) - (&state, file, PSI_FILE_READ); - if (likely(locker != NULL)) - { - PSI_FILE_CALL(start_file_wait)(locker, count, src_file, src_line); - result= my_pread(file, buffer, count, offset, flags); - if (flags & (MY_NABP | MY_FNABP)) - bytes_read= (result == 0) ? count : 0; - else - bytes_read= (result != MY_FILE_ERROR) ? result : 0; - PSI_FILE_CALL(end_file_wait)(locker, bytes_read); - return result; - } -#endif - - result= my_pread(file, buffer, count, offset, flags); - return result; -} - -static inline size_t -inline_mysql_file_pwrite( -#ifdef HAVE_PSI_FILE_INTERFACE - const char *src_file, uint src_line, -#endif - File file, const uchar *buffer, size_t count, my_off_t offset, myf flags) -{ - size_t result; -#ifdef HAVE_PSI_FILE_INTERFACE - struct PSI_file_locker *locker; - PSI_file_locker_state state; - size_t bytes_written; - locker= PSI_FILE_CALL(get_thread_file_descriptor_locker) - (&state, file, PSI_FILE_WRITE); - if (likely(locker != NULL)) - { - PSI_FILE_CALL(start_file_wait)(locker, count, src_file, src_line); - result= my_pwrite(file, buffer, count, offset, flags); - if (flags & (MY_NABP | MY_FNABP)) - bytes_written= (result == 0) ? count : 0; - else - bytes_written= (result != MY_FILE_ERROR) ? result : 0; - PSI_FILE_CALL(end_file_wait)(locker, bytes_written); - return result; - } -#endif - - result= my_pwrite(file, buffer, count, offset, flags); - return result; -} - -static inline my_off_t -inline_mysql_file_seek( -#ifdef HAVE_PSI_FILE_INTERFACE - const char *src_file, uint src_line, -#endif - File file, my_off_t pos, int whence, myf flags) -{ - my_off_t result; -#ifdef HAVE_PSI_FILE_INTERFACE - struct PSI_file_locker *locker; - PSI_file_locker_state state; - locker= PSI_FILE_CALL(get_thread_file_descriptor_locker) - (&state, file, PSI_FILE_SEEK); - if (likely(locker != NULL)) - { - PSI_FILE_CALL(start_file_wait)(locker, (size_t) 0, src_file, src_line); - result= my_seek(file, pos, whence, flags); - PSI_FILE_CALL(end_file_wait)(locker, (size_t) 0); - return result; - } -#endif - - result= my_seek(file, pos, whence, flags); - return result; -} - -static inline my_off_t -inline_mysql_file_tell( -#ifdef HAVE_PSI_FILE_INTERFACE - const char *src_file, uint src_line, -#endif - File file, myf flags) -{ - my_off_t result; -#ifdef HAVE_PSI_FILE_INTERFACE - struct PSI_file_locker *locker; - PSI_file_locker_state state; - locker= PSI_FILE_CALL(get_thread_file_descriptor_locker) - (&state, file, PSI_FILE_TELL); - if (likely(locker != NULL)) - { - PSI_FILE_CALL(start_file_wait)(locker, (size_t) 0, src_file, src_line); - result= my_tell(file, flags); - PSI_FILE_CALL(end_file_wait)(locker, (size_t) 0); - return result; - } -#endif - - result= my_tell(file, flags); - return result; -} - -static inline int -inline_mysql_file_delete( -#ifdef HAVE_PSI_FILE_INTERFACE - PSI_file_key key, const char *src_file, uint src_line, -#endif - const char *name, myf flags) -{ - int result; -#ifdef HAVE_PSI_FILE_INTERFACE - struct PSI_file_locker *locker; - PSI_file_locker_state state; - locker= PSI_FILE_CALL(get_thread_file_name_locker) - (&state, key, PSI_FILE_DELETE, name, &locker); - if (likely(locker != NULL)) - { - PSI_FILE_CALL(start_file_close_wait)(locker, src_file, src_line); - result= my_delete(name, flags); - PSI_FILE_CALL(end_file_close_wait)(locker, result); - return result; - } -#endif - - result= my_delete(name, flags); - return result; -} - -static inline int -inline_mysql_file_rename( -#ifdef HAVE_PSI_FILE_INTERFACE - PSI_file_key key, const char *src_file, uint src_line, -#endif - const char *from, const char *to, myf flags) -{ - int result; -#ifdef HAVE_PSI_FILE_INTERFACE - struct PSI_file_locker *locker; - PSI_file_locker_state state; - locker= PSI_FILE_CALL(get_thread_file_name_locker) - (&state, key, PSI_FILE_RENAME, to, &locker); - if (likely(locker != NULL)) - { - PSI_FILE_CALL(start_file_wait)(locker, (size_t) 0, src_file, src_line); - result= my_rename(from, to, flags); - PSI_FILE_CALL(end_file_wait)(locker, (size_t) 0); - return result; - } -#endif - - result= my_rename(from, to, flags); - return result; -} - -static inline File -inline_mysql_file_create_with_symlink( -#ifdef HAVE_PSI_FILE_INTERFACE - PSI_file_key key, const char *src_file, uint src_line, -#endif - const char *linkname, const char *filename, int create_flags, - int access_flags, myf flags) -{ - File file; -#ifdef HAVE_PSI_FILE_INTERFACE - struct PSI_file_locker *locker; - PSI_file_locker_state state; - locker= PSI_FILE_CALL(get_thread_file_name_locker) - (&state, key, PSI_FILE_CREATE, filename, &locker); - if (likely(locker != NULL)) - { - PSI_FILE_CALL(start_file_open_wait)(locker, src_file, src_line); - file= my_create_with_symlink(linkname, filename, create_flags, access_flags, - flags); - PSI_FILE_CALL(end_file_open_wait_and_bind_to_descriptor)(locker, file); - return file; - } -#endif - - file= my_create_with_symlink(linkname, filename, create_flags, access_flags, - flags); - return file; -} - -static inline int -inline_mysql_file_delete_with_symlink( -#ifdef HAVE_PSI_FILE_INTERFACE - PSI_file_key key, const char *src_file, uint src_line, -#endif - const char *name, myf flags) -{ - int result; -#ifdef HAVE_PSI_FILE_INTERFACE - struct PSI_file_locker *locker; - PSI_file_locker_state state; - locker= PSI_FILE_CALL(get_thread_file_name_locker) - (&state, key, PSI_FILE_DELETE, name, &locker); - if (likely(locker != NULL)) - { - PSI_FILE_CALL(start_file_close_wait)(locker, src_file, src_line); - result= my_delete_with_symlink(name, flags); - PSI_FILE_CALL(end_file_close_wait)(locker, result); - return result; - } -#endif - - result= my_delete_with_symlink(name, flags); - return result; -} - -static inline int -inline_mysql_file_rename_with_symlink( -#ifdef HAVE_PSI_FILE_INTERFACE - PSI_file_key key, const char *src_file, uint src_line, -#endif - const char *from, const char *to, myf flags) -{ - int result; -#ifdef HAVE_PSI_FILE_INTERFACE - struct PSI_file_locker *locker; - PSI_file_locker_state state; - locker= PSI_FILE_CALL(get_thread_file_name_locker) - (&state, key, PSI_FILE_RENAME, to, &locker); - if (likely(locker != NULL)) - { - PSI_FILE_CALL(start_file_wait)(locker, (size_t) 0, src_file, src_line); - result= my_rename_with_symlink(from, to, flags); - PSI_FILE_CALL(end_file_wait)(locker, (size_t) 0); - return result; - } -#endif - - result= my_rename_with_symlink(from, to, flags); - return result; -} - -static inline int -inline_mysql_file_sync( -#ifdef HAVE_PSI_FILE_INTERFACE - const char *src_file, uint src_line, -#endif - File fd, myf flags) -{ - int result= 0; -#ifdef HAVE_PSI_FILE_INTERFACE - struct PSI_file_locker *locker; - PSI_file_locker_state state; - locker= PSI_FILE_CALL(get_thread_file_descriptor_locker) - (&state, fd, PSI_FILE_SYNC); - if (likely(locker != NULL)) - { - PSI_FILE_CALL(start_file_wait)(locker, (size_t) 0, src_file, src_line); - result= my_sync(fd, flags); - PSI_FILE_CALL(end_file_wait)(locker, (size_t) 0); - return result; - } -#endif - - result= my_sync(fd, flags); - return result; -} - -/** @} (end of group File_instrumentation) */ - -#endif - diff --git a/vendor/mysql/include/mysql/psi/mysql_idle.h b/vendor/mysql/include/mysql/psi/mysql_idle.h deleted file mode 100644 index 102304aa33..0000000000 --- a/vendor/mysql/include/mysql/psi/mysql_idle.h +++ /dev/null @@ -1,96 +0,0 @@ -/* Copyright (c) 2011, 2013, Oracle and/or its affiliates. All rights reserved. - - This program is free software; you can redistribute it and/or modify - it under the terms of the GNU General Public License as published by - the Free Software Foundation; version 2 of the License. - - This program is distributed in the hope that it will be useful, - but WITHOUT ANY WARRANTY; without even the implied warranty of - MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - GNU General Public License for more details. - - You should have received a copy of the GNU General Public License - along with this program; if not, write to the Free Software Foundation, - 51 Franklin Street, Suite 500, Boston, MA 02110-1335 USA */ - -#ifndef MYSQL_IDLE_H -#define MYSQL_IDLE_H - -/** - @file mysql/psi/mysql_idle.h - Instrumentation helpers for idle waits. -*/ - -#include "mysql/psi/psi.h" - -#ifndef PSI_IDLE_CALL -#define PSI_IDLE_CALL(M) PSI_DYNAMIC_CALL(M) -#endif - -/** - @defgroup Idle_instrumentation Idle Instrumentation - @ingroup Instrumentation_interface - @{ -*/ - -/** - @def MYSQL_START_IDLE_WAIT - Instrumentation helper for table io_waits. - This instrumentation marks the start of a wait event. - @param LOCKER the locker - @param STATE the locker state - @sa MYSQL_END_IDLE_WAIT. -*/ -#ifdef HAVE_PSI_IDLE_INTERFACE - #define MYSQL_START_IDLE_WAIT(LOCKER, STATE) \ - LOCKER= inline_mysql_start_idle_wait(STATE, __FILE__, __LINE__) -#else - #define MYSQL_START_IDLE_WAIT(LOCKER, STATE) \ - do {} while (0) -#endif - -/** - @def MYSQL_END_IDLE_WAIT - Instrumentation helper for idle waits. - This instrumentation marks the end of a wait event. - @param LOCKER the locker - @sa MYSQL_START_IDLE_WAIT. -*/ -#ifdef HAVE_PSI_IDLE_INTERFACE - #define MYSQL_END_IDLE_WAIT(LOCKER) \ - inline_mysql_end_idle_wait(LOCKER) -#else - #define MYSQL_END_IDLE_WAIT(LOCKER) \ - do {} while (0) -#endif - -#ifdef HAVE_PSI_IDLE_INTERFACE -/** - Instrumentation calls for MYSQL_START_IDLE_WAIT. - @sa MYSQL_END_IDLE_WAIT. -*/ -static inline struct PSI_idle_locker * -inline_mysql_start_idle_wait(PSI_idle_locker_state *state, - const char *src_file, int src_line) -{ - struct PSI_idle_locker *locker; - locker= PSI_IDLE_CALL(start_idle_wait)(state, src_file, src_line); - return locker; -} - -/** - Instrumentation calls for MYSQL_END_IDLE_WAIT. - @sa MYSQL_START_IDLE_WAIT. -*/ -static inline void -inline_mysql_end_idle_wait(struct PSI_idle_locker *locker) -{ - if (likely(locker != NULL)) - PSI_IDLE_CALL(end_idle_wait)(locker); -} -#endif - -/** @} (end of group Idle_instrumentation) */ - -#endif - diff --git a/vendor/mysql/include/mysql/psi/mysql_mdl.h b/vendor/mysql/include/mysql/psi/mysql_mdl.h deleted file mode 100644 index bb2b76c151..0000000000 --- a/vendor/mysql/include/mysql/psi/mysql_mdl.h +++ /dev/null @@ -1,121 +0,0 @@ -/* Copyright (c) 2012, 2015, Oracle and/or its affiliates. All rights reserved. - - This program is free software; you can redistribute it and/or modify - it under the terms of the GNU General Public License as published by - the Free Software Foundation; version 2 of the License. - - This program is distributed in the hope that it will be useful, - but WITHOUT ANY WARRANTY; without even the implied warranty of - MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - GNU General Public License for more details. - - You should have received a copy of the GNU General Public License - along with this program; if not, write to the Free Software Foundation, - 51 Franklin Street, Suite 500, Boston, MA 02110-1335 USA */ - -#ifndef MYSQL_MDL_H -#define MYSQL_MDL_H - -/** - @file mysql/psi/mysql_mdl.h - Instrumentation helpers for metadata locks. -*/ - -#include "mysql/psi/psi.h" - -#ifndef PSI_METADATA_CALL -#define PSI_METADATA_CALL(M) PSI_DYNAMIC_CALL(M) -#endif - -/** - @defgroup Thread_instrumentation Metadata Instrumentation - @ingroup Instrumentation_interface - @{ -*/ - -/** - @def mysql_mdl_create(K, M, A) - Instrumented metadata lock creation. - @param I Metadata lock identity - @param K Metadata key - @param T Metadata lock type - @param D Metadata lock duration - @param S Metadata lock status - @param F request source file - @param L request source line -*/ - -#ifdef HAVE_PSI_METADATA_INTERFACE - #define mysql_mdl_create(I, K, T, D, S, F, L) \ - inline_mysql_mdl_create(I, K, T, D, S, F, L) -#else - #define mysql_mdl_create(I, K, T, D, S, F, L) NULL -#endif - -#ifdef HAVE_PSI_METADATA_INTERFACE - #define mysql_mdl_set_status(L, S) \ - inline_mysql_mdl_set_status(L, S) -#else - #define mysql_mdl_set_status(L, S) \ - do {} while (0) -#endif - - -/** - @def mysql_mdl_destroy(M) - Instrumented metadata lock destruction. - @param M Metadata lock -*/ -#ifdef HAVE_PSI_METADATA_INTERFACE - #define mysql_mdl_destroy(M) \ - inline_mysql_mdl_destroy(M, __FILE__, __LINE__) -#else - #define mysql_mdl_destroy(M) \ - do {} while (0) -#endif - -#ifdef HAVE_PSI_METADATA_INTERFACE - -static inline PSI_metadata_lock * -inline_mysql_mdl_create(void *identity, - const MDL_key *mdl_key, - enum_mdl_type mdl_type, - enum_mdl_duration mdl_duration, - MDL_ticket::enum_psi_status mdl_status, - const char *src_file, uint src_line) -{ - PSI_metadata_lock *result; - - /* static_cast: Fit a round C++ enum peg into a square C int hole ... */ - result= PSI_METADATA_CALL(create_metadata_lock) - (identity, - mdl_key, - static_cast (mdl_type), - static_cast (mdl_duration), - static_cast (mdl_status), - src_file, src_line); - - return result; -} - -static inline void inline_mysql_mdl_set_status( - PSI_metadata_lock *psi, - MDL_ticket::enum_psi_status mdl_status) -{ - if (psi != NULL) - PSI_METADATA_CALL(set_metadata_lock_status)(psi, mdl_status); -} - -static inline void inline_mysql_mdl_destroy( - PSI_metadata_lock *psi, - const char *src_file, uint src_line) -{ - if (psi != NULL) - PSI_METADATA_CALL(destroy_metadata_lock)(psi); -} -#endif /* HAVE_PSI_METADATA_INTERFACE */ - -/** @} (end of group Metadata_instrumentation) */ - -#endif - diff --git a/vendor/mysql/include/mysql/psi/mysql_memory.h b/vendor/mysql/include/mysql/psi/mysql_memory.h deleted file mode 100644 index 55dd8184b1..0000000000 --- a/vendor/mysql/include/mysql/psi/mysql_memory.h +++ /dev/null @@ -1,62 +0,0 @@ -/* Copyright (c) 2012, 2016, Oracle and/or its affiliates. All rights reserved. - - This program is free software; you can redistribute it and/or modify - it under the terms of the GNU General Public License as published by - the Free Software Foundation; version 2 of the License. - - This program is distributed in the hope that it will be useful, - but WITHOUT ANY WARRANTY; without even the implied warranty of - MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - GNU General Public License for more details. - - You should have received a copy of the GNU General Public License - along with this program; if not, write to the Free Software Foundation, - 51 Franklin Street, Suite 500, Boston, MA 02110-1335 USA */ - -#ifndef MYSQL_MEMORY_H -#define MYSQL_MEMORY_H - -/** - @file mysql/psi/mysql_memory.h - Instrumentation helpers for memory allocation. -*/ - -#include "mysql/psi/psi.h" - -#ifndef PSI_MEMORY_CALL -#define PSI_MEMORY_CALL(M) PSI_DYNAMIC_CALL(M) -#endif - -/** - @defgroup Memory_instrumentation Memory Instrumentation - @ingroup Instrumentation_interface - @{ -*/ - -/** - @def mysql_memory_register(P1, P2, P3) - Memory registration. -*/ -#define mysql_memory_register(P1, P2, P3) \ - inline_mysql_memory_register(P1, P2, P3) - -static inline void inline_mysql_memory_register( -#ifdef HAVE_PSI_MEMORY_INTERFACE - const char *category, - PSI_memory_info *info, - int count) -#else - const char *category MY_ATTRIBUTE((unused)), - void *info MY_ATTRIBUTE((unused)), - int count MY_ATTRIBUTE((unused))) -#endif -{ -#ifdef HAVE_PSI_MEMORY_INTERFACE - PSI_MEMORY_CALL(register_memory)(category, info, count); -#endif -} - -/** @} (end of group Memory_instrumentation) */ - -#endif - diff --git a/vendor/mysql/include/mysql/psi/mysql_ps.h b/vendor/mysql/include/mysql/psi/mysql_ps.h deleted file mode 100644 index 485e1fbedf..0000000000 --- a/vendor/mysql/include/mysql/psi/mysql_ps.h +++ /dev/null @@ -1,88 +0,0 @@ -/* Copyright (c) 2014, Oracle and/or its affiliates. All rights reserved. - - This program is free software; you can redistribute it and/or modify - it under the terms of the GNU General Public License as published by - the Free Software Foundation; version 2 of the License. - - This program is distributed in the hope that it will be useful, - but WITHOUT ANY WARRANTY; without even the implied warranty of - MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - GNU General Public License for more details. - - You should have received a copy of the GNU General Public License - along with this program; if not, write to the Free Software - Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA */ - -#ifndef MYSQL_PS_H -#define MYSQL_PS_H - -/** - @file mysql/psi/mysql_ps.h - Instrumentation helpers for prepared statements. -*/ - -#include "mysql/psi/psi.h" - -#ifndef PSI_PS_CALL -#define PSI_PS_CALL(M) PSI_DYNAMIC_CALL(M) -#endif - -#ifdef HAVE_PSI_PS_INTERFACE - #define MYSQL_CREATE_PS(IDENTITY, ID, LOCKER, NAME, NAME_LENGTH, SQLTEXT, SQLTEXT_LENGTH) \ - inline_mysql_create_prepared_stmt(IDENTITY, ID, LOCKER, NAME, NAME_LENGTH, SQLTEXT, SQLTEXT_LENGTH) - #define MYSQL_EXECUTE_PS(LOCKER, PREPARED_STMT) \ - inline_mysql_execute_prepared_stmt(LOCKER, PREPARED_STMT) - #define MYSQL_DESTROY_PS(PREPARED_STMT) \ - inline_mysql_destroy_prepared_stmt(PREPARED_STMT) - #define MYSQL_REPREPARE_PS(PREPARED_STMT) \ - inline_mysql_reprepare_prepared_stmt(PREPARED_STMT) -#else - #define MYSQL_CREATE_PS(IDENTITY, ID, LOCKER, NAME, NAME_LENGTH, SQLTEXT, SQLTEXT_LENGTH) \ - NULL - #define MYSQL_EXECUTE_PS(LOCKER, PREPARED_STMT) \ - do {} while (0) - #define MYSQL_DESTROY_PS(PREPARED_STMT) \ - do {} while (0) - #define MYSQL_REPREPARE_PS(PREPARED_STMT) \ - do {} while (0) -#endif - -#ifdef HAVE_PSI_PS_INTERFACE -static inline struct PSI_prepared_stmt* -inline_mysql_create_prepared_stmt(void *identity, uint stmt_id, - PSI_statement_locker *locker, - const char *stmt_name, size_t stmt_name_length, - const char *sqltext, size_t sqltext_length) -{ - if (locker == NULL) - return NULL; - return PSI_PS_CALL(create_prepared_stmt)(identity, stmt_id, - locker, - stmt_name, stmt_name_length, - sqltext, sqltext_length); -} - -static inline void -inline_mysql_execute_prepared_stmt(PSI_statement_locker *locker, - PSI_prepared_stmt* prepared_stmt) -{ - if (prepared_stmt != NULL && locker != NULL) - PSI_PS_CALL(execute_prepared_stmt)(locker, prepared_stmt); -} - -static inline void -inline_mysql_destroy_prepared_stmt(PSI_prepared_stmt *prepared_stmt) -{ - if (prepared_stmt != NULL) - PSI_PS_CALL(destroy_prepared_stmt)(prepared_stmt); -} - -static inline void -inline_mysql_reprepare_prepared_stmt(PSI_prepared_stmt *prepared_stmt) -{ - if (prepared_stmt != NULL) - PSI_PS_CALL(reprepare_prepared_stmt)(prepared_stmt); -} -#endif - -#endif diff --git a/vendor/mysql/include/mysql/psi/mysql_socket.h b/vendor/mysql/include/mysql/psi/mysql_socket.h deleted file mode 100644 index ad76e318b3..0000000000 --- a/vendor/mysql/include/mysql/psi/mysql_socket.h +++ /dev/null @@ -1,1255 +0,0 @@ -/* Copyright (c) 2010, 2016, Oracle and/or its affiliates. All rights reserved. - -This program is free software; you can redistribute it and/or -modify it under the terms of the GNU General Public License as -published by the Free Software Foundation; version 2 of the -License. - -This program is distributed in the hope that it will be useful, -but WITHOUT ANY WARRANTY; without even the implied warranty of -MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -GNU General Public License for more details. - -You should have received a copy of the GNU General Public License -along with this program; if not, write to the Free Software -Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA -02110-1301 USA -*/ - -#ifndef MYSQL_SOCKET_H -#define MYSQL_SOCKET_H - -/* For strlen() */ -#include -/* For MY_STAT */ -#include -/* For my_chsize */ -#include -/* For socket api */ -#ifdef _WIN32 - #include - #include - #include - #define SOCKBUF_T char -#else - #include - #define SOCKBUF_T void -#endif -/** - @file mysql/psi/mysql_socket.h -[...] -*/ - -#include "mysql/psi/psi.h" - -#ifndef PSI_SOCKET_CALL -#define PSI_SOCKET_CALL(M) PSI_DYNAMIC_CALL(M) -#endif - -/** - @defgroup Socket_instrumentation Socket Instrumentation - @ingroup Instrumentation_interface - @{ -*/ - -/** - @def mysql_socket_register(P1, P2, P3) - Socket registration. -*/ -#ifdef HAVE_PSI_SOCKET_INTERFACE - #define mysql_socket_register(P1, P2, P3) \ - inline_mysql_socket_register(P1, P2, P3) -#else - #define mysql_socket_register(P1, P2, P3) \ - do {} while (0) -#endif - -/** An instrumented socket. */ -struct st_mysql_socket -{ - /** The real socket descriptor. */ - my_socket fd; - - /** - The instrumentation hook. - Note that this hook is not conditionally defined, - for binary compatibility of the @c MYSQL_SOCKET interface. - */ - struct PSI_socket *m_psi; -}; - -/** - An instrumented socket. - @c MYSQL_SOCKET is a replacement for @c my_socket. -*/ -typedef struct st_mysql_socket MYSQL_SOCKET; - - -/** - @def MYSQL_INVALID_SOCKET - MYSQL_SOCKET initial value. -*/ -//MYSQL_SOCKET MYSQL_INVALID_SOCKET= {INVALID_SOCKET, NULL}; -#define MYSQL_INVALID_SOCKET mysql_socket_invalid() - -/** - MYSQL_SOCKET helper. Initialize instrumented socket. - @sa mysql_socket_getfd - @sa mysql_socket_setfd -*/ -static inline MYSQL_SOCKET -mysql_socket_invalid() -{ - MYSQL_SOCKET mysql_socket= {INVALID_SOCKET, NULL}; - return mysql_socket; -} - -/** - Set socket descriptor and address. - @param socket nstrumented socket - @param addr unformatted socket address - @param addr_len length of socket addres -*/ - -static inline void -mysql_socket_set_address( -#ifdef HAVE_PSI_SOCKET_INTERFACE - MYSQL_SOCKET socket, - const struct sockaddr *addr, - socklen_t addr_len -#else - MYSQL_SOCKET socket MY_ATTRIBUTE ((unused)), - const struct sockaddr *addr MY_ATTRIBUTE ((unused)), - socklen_t addr_len MY_ATTRIBUTE ((unused)) -#endif -) -{ -#ifdef HAVE_PSI_SOCKET_INTERFACE - if (socket.m_psi != NULL) - PSI_SOCKET_CALL(set_socket_info)(socket.m_psi, NULL, addr, addr_len); -#endif -} - -/** - Set socket descriptor and address. - @param socket instrumented socket -*/ -static inline void -mysql_socket_set_thread_owner( -#ifdef HAVE_PSI_SOCKET_INTERFACE -MYSQL_SOCKET socket -#else -MYSQL_SOCKET socket MY_ATTRIBUTE ((unused)) -#endif -) -{ -#ifdef HAVE_PSI_SOCKET_INTERFACE - if (socket.m_psi != NULL) - PSI_SOCKET_CALL(set_socket_thread_owner)(socket.m_psi); -#endif -} - -/** - MYSQL_SOCKET helper. Get socket descriptor. - @param mysql_socket Instrumented socket - @sa mysql_socket_setfd -*/ -static inline my_socket -mysql_socket_getfd(MYSQL_SOCKET mysql_socket) -{ - return mysql_socket.fd; -} - -/** - MYSQL_SOCKET helper. Set socket descriptor. - @param mysql_socket Instrumented socket - @param fd Socket descriptor - @sa mysql_socket_getfd -*/ -static inline void -mysql_socket_setfd(MYSQL_SOCKET *mysql_socket, my_socket fd) -{ - if (likely(mysql_socket != NULL)) - mysql_socket->fd= fd; -} - -/** - @def MYSQL_SOCKET_WAIT_VARIABLES - Instrumentation helper for socket waits. - This instrumentation declares local variables. - Do not use a ';' after this macro - @param LOCKER locker - @param STATE locker state - @sa MYSQL_START_SOCKET_WAIT. - @sa MYSQL_END_SOCKET_WAIT. -*/ -#ifdef HAVE_PSI_SOCKET_INTERFACE - #define MYSQL_SOCKET_WAIT_VARIABLES(LOCKER, STATE) \ - struct PSI_socket_locker* LOCKER; \ - PSI_socket_locker_state STATE; -#else - #define MYSQL_SOCKET_WAIT_VARIABLES(LOCKER, STATE) -#endif - -/** - @def MYSQL_START_SOCKET_WAIT - Instrumentation helper for socket waits. - This instrumentation marks the start of a wait event. - @param LOCKER locker - @param STATE locker state - @param SOCKET instrumented socket - @param OP The socket operation to be performed - @param COUNT bytes to be written/read - @sa MYSQL_END_SOCKET_WAIT. -*/ -#ifdef HAVE_PSI_SOCKET_INTERFACE - #define MYSQL_START_SOCKET_WAIT(LOCKER, STATE, SOCKET, OP, COUNT) \ - LOCKER= inline_mysql_start_socket_wait(STATE, SOCKET, OP, COUNT,\ - __FILE__, __LINE__) -#else - #define MYSQL_START_SOCKET_WAIT(LOCKER, STATE, SOCKET, OP, COUNT) \ - do {} while (0) -#endif - -/** - @def MYSQL_END_SOCKET_WAIT - Instrumentation helper for socket waits. - This instrumentation marks the end of a wait event. - @param LOCKER locker - @param COUNT actual bytes written/read, or -1 - @sa MYSQL_START_SOCKET_WAIT. -*/ -#ifdef HAVE_PSI_SOCKET_INTERFACE - #define MYSQL_END_SOCKET_WAIT(LOCKER, COUNT) \ - inline_mysql_end_socket_wait(LOCKER, COUNT) -#else - #define MYSQL_END_SOCKET_WAIT(LOCKER, COUNT) \ - do {} while (0) -#endif - -/** - @def MYSQL_SOCKET_SET_STATE - Set the state (IDLE, ACTIVE) of an instrumented socket. - @param SOCKET the instrumented socket - @param STATE the new state - @sa PSI_socket_state -*/ -#ifdef HAVE_PSI_SOCKET_INTERFACE - #define MYSQL_SOCKET_SET_STATE(SOCKET, STATE) \ - inline_mysql_socket_set_state(SOCKET, STATE) -#else - #define MYSQL_SOCKET_SET_STATE(SOCKET, STATE) \ - do {} while (0) -#endif - -#ifdef HAVE_PSI_SOCKET_INTERFACE -/** - Instrumentation calls for MYSQL_START_SOCKET_WAIT. - @sa MYSQL_START_SOCKET_WAIT. -*/ -static inline struct PSI_socket_locker* -inline_mysql_start_socket_wait(PSI_socket_locker_state *state, - MYSQL_SOCKET mysql_socket, - enum PSI_socket_operation op, - size_t byte_count, - const char *src_file, int src_line) -{ - struct PSI_socket_locker *locker; - if (mysql_socket.m_psi != NULL) - { - locker= PSI_SOCKET_CALL(start_socket_wait) - (state, mysql_socket.m_psi, op, byte_count, src_file, src_line); - } - else - locker= NULL; - return locker; -} - -/** - Instrumentation calls for MYSQL_END_SOCKET_WAIT. - @sa MYSQL_END_SOCKET_WAIT. -*/ -static inline void -inline_mysql_end_socket_wait(struct PSI_socket_locker *locker, size_t byte_count) -{ - if (locker != NULL) - PSI_SOCKET_CALL(end_socket_wait)(locker, byte_count); -} - -/** - Set the state (IDLE, ACTIVE) of an instrumented socket. - @param socket the instrumented socket - @param state the new state - @sa PSI_socket_state -*/ -static inline void -inline_mysql_socket_set_state(MYSQL_SOCKET socket, enum PSI_socket_state state) -{ - if (socket.m_psi != NULL) - PSI_SOCKET_CALL(set_socket_state)(socket.m_psi, state); -} -#endif /* HAVE_PSI_SOCKET_INTERFACE */ - -/** - @def mysql_socket_socket(K, D, T, P) - Create a socket. - @c mysql_socket_socket is a replacement for @c socket. - @param K PSI_socket_key for this instrumented socket - @param D Socket domain - @param T Protocol type - @param P Transport protocol -*/ - -#ifdef HAVE_PSI_SOCKET_INTERFACE - #define mysql_socket_socket(K, D, T, P) \ - inline_mysql_socket_socket(K, D, T, P) -#else - #define mysql_socket_socket(K, D, T, P) \ - inline_mysql_socket_socket(D, T, P) -#endif - -/** - @def mysql_socket_bind(FD, AP, L) - Bind a socket to a local port number and IP address - @c mysql_socket_bind is a replacement for @c bind. - @param FD Instrumented socket descriptor returned by socket() - @param AP Pointer to local port number and IP address in sockaddr structure - @param L Length of sockaddr structure -*/ -#ifdef HAVE_PSI_SOCKET_INTERFACE - #define mysql_socket_bind(FD, AP, L) \ - inline_mysql_socket_bind(__FILE__, __LINE__, FD, AP, L) -#else - #define mysql_socket_bind(FD, AP, L) \ - inline_mysql_socket_bind(FD, AP, L) -#endif - -/** - @def mysql_socket_getsockname(FD, AP, LP) - Return port number and IP address of the local host - @c mysql_socket_getsockname is a replacement for @c getsockname. - @param FD Instrumented socket descriptor returned by socket() - @param AP Pointer to returned address of local host in @c sockaddr structure - @param LP Pointer to length of @c sockaddr structure -*/ -#ifdef HAVE_PSI_SOCKET_INTERFACE - #define mysql_socket_getsockname(FD, AP, LP) \ - inline_mysql_socket_getsockname(__FILE__, __LINE__, FD, AP, LP) -#else - #define mysql_socket_getsockname(FD, AP, LP) \ - inline_mysql_socket_getsockname(FD, AP, LP) -#endif - -/** - @def mysql_socket_connect(FD, AP, L) - Establish a connection to a remote host. - @c mysql_socket_connect is a replacement for @c connect. - @param FD Instrumented socket descriptor returned by socket() - @param AP Pointer to target address in sockaddr structure - @param L Length of sockaddr structure -*/ -#ifdef HAVE_PSI_SOCKET_INTERFACE - #define mysql_socket_connect(FD, AP, L) \ - inline_mysql_socket_connect(__FILE__, __LINE__, FD, AP, L) -#else - #define mysql_socket_connect(FD, AP, L) \ - inline_mysql_socket_connect(FD, AP, L) -#endif - -/** - @def mysql_socket_getpeername(FD, AP, LP) - Get port number and IP address of remote host that a socket is connected to. - @c mysql_socket_getpeername is a replacement for @c getpeername. - @param FD Instrumented socket descriptor returned by socket() or accept() - @param AP Pointer to returned address of remote host in sockaddr structure - @param LP Pointer to length of sockaddr structure -*/ -#ifdef HAVE_PSI_SOCKET_INTERFACE - #define mysql_socket_getpeername(FD, AP, LP) \ - inline_mysql_socket_getpeername(__FILE__, __LINE__, FD, AP, LP) -#else - #define mysql_socket_getpeername(FD, AP, LP) \ - inline_mysql_socket_getpeername(FD, AP, LP) -#endif - -/** - @def mysql_socket_send(FD, B, N, FL) - Send data from the buffer, B, to a connected socket. - @c mysql_socket_send is a replacement for @c send. - @param FD Instrumented socket descriptor returned by socket() or accept() - @param B Buffer to send - @param N Number of bytes to send - @param FL Control flags -*/ -#ifdef HAVE_PSI_SOCKET_INTERFACE - #define mysql_socket_send(FD, B, N, FL) \ - inline_mysql_socket_send(__FILE__, __LINE__, FD, B, N, FL) -#else - #define mysql_socket_send(FD, B, N, FL) \ - inline_mysql_socket_send(FD, B, N, FL) -#endif - -/** - @def mysql_socket_recv(FD, B, N, FL) - Receive data from a connected socket. - @c mysql_socket_recv is a replacement for @c recv. - @param FD Instrumented socket descriptor returned by socket() or accept() - @param B Buffer to receive to - @param N Maximum bytes to receive - @param FL Control flags -*/ -#ifdef HAVE_PSI_SOCKET_INTERFACE - #define mysql_socket_recv(FD, B, N, FL) \ - inline_mysql_socket_recv(__FILE__, __LINE__, FD, B, N, FL) -#else - #define mysql_socket_recv(FD, B, N, FL) \ - inline_mysql_socket_recv(FD, B, N, FL) -#endif - -/** - @def mysql_socket_sendto(FD, B, N, FL, AP, L) - Send data to a socket at the specified address. - @c mysql_socket_sendto is a replacement for @c sendto. - @param FD Instrumented socket descriptor returned by socket() - @param B Buffer to send - @param N Number of bytes to send - @param FL Control flags - @param AP Pointer to destination sockaddr structure - @param L Size of sockaddr structure -*/ -#ifdef HAVE_PSI_SOCKET_INTERFACE - #define mysql_socket_sendto(FD, B, N, FL, AP, L) \ - inline_mysql_socket_sendto(__FILE__, __LINE__, FD, B, N, FL, AP, L) -#else - #define mysql_socket_sendto(FD, B, N, FL, AP, L) \ - inline_mysql_socket_sendto(FD, B, N, FL, AP, L) -#endif - -/** - @def mysql_socket_recvfrom(FD, B, N, FL, AP, L) - Receive data from a socket and return source address information - @c mysql_socket_recvfrom is a replacement for @c recvfrom. - @param FD Instrumented socket descriptor returned by socket() - @param B Buffer to receive to - @param N Maximum bytes to receive - @param FL Control flags - @param AP Pointer to source address in sockaddr_storage structure - @param LP Size of sockaddr_storage structure -*/ -#ifdef HAVE_PSI_SOCKET_INTERFACE - #define mysql_socket_recvfrom(FD, B, N, FL, AP, LP) \ - inline_mysql_socket_recvfrom(__FILE__, __LINE__, FD, B, N, FL, AP, LP) -#else - #define mysql_socket_recvfrom(FD, B, N, FL, AP, LP) \ - inline_mysql_socket_recvfrom(FD, B, N, FL, AP, LP) -#endif - -/** - @def mysql_socket_getsockopt(FD, LV, ON, OP, OL) - Get a socket option for the specified socket. - @c mysql_socket_getsockopt is a replacement for @c getsockopt. - @param FD Instrumented socket descriptor returned by socket() - @param LV Protocol level - @param ON Option to query - @param OP Buffer which will contain the value for the requested option - @param OL Pointer to length of OP -*/ -#ifdef HAVE_PSI_SOCKET_INTERFACE - #define mysql_socket_getsockopt(FD, LV, ON, OP, OL) \ - inline_mysql_socket_getsockopt(__FILE__, __LINE__, FD, LV, ON, OP, OL) -#else - #define mysql_socket_getsockopt(FD, LV, ON, OP, OL) \ - inline_mysql_socket_getsockopt(FD, LV, ON, OP, OL) -#endif - -/** - @def mysql_socket_setsockopt(FD, LV, ON, OP, OL) - Set a socket option for the specified socket. - @c mysql_socket_setsockopt is a replacement for @c setsockopt. - @param FD Instrumented socket descriptor returned by socket() - @param LV Protocol level - @param ON Option to modify - @param OP Buffer containing the value for the specified option - @param OL Pointer to length of OP -*/ -#ifdef HAVE_PSI_SOCKET_INTERFACE - #define mysql_socket_setsockopt(FD, LV, ON, OP, OL) \ - inline_mysql_socket_setsockopt(__FILE__, __LINE__, FD, LV, ON, OP, OL) -#else - #define mysql_socket_setsockopt(FD, LV, ON, OP, OL) \ - inline_mysql_socket_setsockopt(FD, LV, ON, OP, OL) -#endif - -/** - @def mysql_sock_set_nonblocking - Set socket to non-blocking. - @param FD instrumented socket descriptor -*/ -#ifdef HAVE_PSI_SOCKET_INTERFACE - #define mysql_sock_set_nonblocking(FD) \ - inline_mysql_sock_set_nonblocking(__FILE__, __LINE__, FD) -#else - #define mysql_sock_set_nonblocking(FD) \ - inline_mysql_sock_set_nonblocking(FD) -#endif - -/** - @def mysql_socket_listen(FD, N) - Set socket state to listen for an incoming connection. - @c mysql_socket_listen is a replacement for @c listen. - @param FD Instrumented socket descriptor, bound and connected - @param N Maximum number of pending connections allowed. -*/ -#ifdef HAVE_PSI_SOCKET_INTERFACE - #define mysql_socket_listen(FD, N) \ - inline_mysql_socket_listen(__FILE__, __LINE__, FD, N) -#else - #define mysql_socket_listen(FD, N) \ - inline_mysql_socket_listen(FD, N) -#endif - -/** - @def mysql_socket_accept(K, FD, AP, LP) - Accept a connection from any remote host; TCP only. - @c mysql_socket_accept is a replacement for @c accept. - @param K PSI_socket_key for this instrumented socket - @param FD Instrumented socket descriptor, bound and placed in a listen state - @param AP Pointer to sockaddr structure with returned IP address and port of connected host - @param LP Pointer to length of valid information in AP -*/ -#ifdef HAVE_PSI_SOCKET_INTERFACE - #define mysql_socket_accept(K, FD, AP, LP) \ - inline_mysql_socket_accept(__FILE__, __LINE__, K, FD, AP, LP) -#else - #define mysql_socket_accept(K, FD, AP, LP) \ - inline_mysql_socket_accept(FD, AP, LP) -#endif - -/** - @def mysql_socket_close(FD) - Close a socket and sever any connections. - @c mysql_socket_close is a replacement for @c close. - @param FD Instrumented socket descriptor returned by socket() or accept() -*/ -#ifdef HAVE_PSI_SOCKET_INTERFACE - #define mysql_socket_close(FD) \ - inline_mysql_socket_close(__FILE__, __LINE__, FD) -#else - #define mysql_socket_close(FD) \ - inline_mysql_socket_close(FD) -#endif - -/** - @def mysql_socket_shutdown(FD, H) - Disable receives and/or sends on a socket. - @c mysql_socket_shutdown is a replacement for @c shutdown. - @param FD Instrumented socket descriptor returned by socket() or accept() - @param H Specifies which operations to shutdown -*/ -#ifdef HAVE_PSI_SOCKET_INTERFACE - #define mysql_socket_shutdown(FD, H) \ - inline_mysql_socket_shutdown(__FILE__, __LINE__, FD, H) -#else - #define mysql_socket_shutdown(FD, H) \ - inline_mysql_socket_shutdown(FD, H) -#endif - -#ifdef HAVE_PSI_SOCKET_INTERFACE -static inline void inline_mysql_socket_register( - const char *category, - PSI_socket_info *info, - int count) -{ - PSI_SOCKET_CALL(register_socket)(category, info, count); -} -#endif - -/** mysql_socket_socket */ - -static inline MYSQL_SOCKET -inline_mysql_socket_socket -( -#ifdef HAVE_PSI_SOCKET_INTERFACE - PSI_socket_key key, -#endif - int domain, int type, int protocol) -{ - MYSQL_SOCKET mysql_socket= MYSQL_INVALID_SOCKET; - mysql_socket.fd= socket(domain, type, protocol); - -#ifdef HAVE_PSI_SOCKET_INTERFACE - if (likely(mysql_socket.fd != INVALID_SOCKET)) - { - mysql_socket.m_psi= PSI_SOCKET_CALL(init_socket) - (key, (const my_socket*)&mysql_socket.fd, NULL, 0); - } -#endif - return mysql_socket; -} - -/** mysql_socket_bind */ - -static inline int -inline_mysql_socket_bind -( -#ifdef HAVE_PSI_SOCKET_INTERFACE - const char *src_file, uint src_line, -#endif - MYSQL_SOCKET mysql_socket, const struct sockaddr *addr, socklen_t len) -{ - int result; - -#ifdef HAVE_PSI_SOCKET_INTERFACE - if (mysql_socket.m_psi != NULL) - { - /* Instrumentation start */ - PSI_socket_locker_state state; - PSI_socket_locker *locker; - locker= PSI_SOCKET_CALL(start_socket_wait) - (&state, mysql_socket.m_psi, PSI_SOCKET_BIND, (size_t)0, src_file, src_line); - - /* Instrumented code */ - result= bind(mysql_socket.fd, addr, len); - - /* Instrumentation end */ - if (result == 0) - PSI_SOCKET_CALL(set_socket_info)(mysql_socket.m_psi, NULL, addr, len); - - if (locker != NULL) - PSI_SOCKET_CALL(end_socket_wait)(locker, (size_t)0); - - return result; - } -#endif - - /* Non instrumented code */ - result= bind(mysql_socket.fd, addr, len); - return result; -} - -/** mysql_socket_getsockname */ - -static inline int -inline_mysql_socket_getsockname -( -#ifdef HAVE_PSI_SOCKET_INTERFACE - const char *src_file, uint src_line, -#endif - MYSQL_SOCKET mysql_socket, struct sockaddr *addr, socklen_t *len) -{ - int result; - -#ifdef HAVE_PSI_SOCKET_INTERFACE - if (mysql_socket.m_psi != NULL) - { - /* Instrumentation start */ - PSI_socket_locker *locker; - PSI_socket_locker_state state; - locker= PSI_SOCKET_CALL(start_socket_wait) - (&state, mysql_socket.m_psi, PSI_SOCKET_BIND, (size_t)0, src_file, src_line); - - /* Instrumented code */ - result= getsockname(mysql_socket.fd, addr, len); - - /* Instrumentation end */ - if (locker != NULL) - PSI_SOCKET_CALL(end_socket_wait)(locker, (size_t)0); - - return result; - } -#endif - - /* Non instrumented code */ - result= getsockname(mysql_socket.fd, addr, len); - - return result; -} - -/** mysql_socket_connect */ - -static inline int -inline_mysql_socket_connect -( -#ifdef HAVE_PSI_SOCKET_INTERFACE - const char *src_file, uint src_line, -#endif - MYSQL_SOCKET mysql_socket, const struct sockaddr *addr, socklen_t len) -{ - int result; - -#ifdef HAVE_PSI_SOCKET_INTERFACE - if (mysql_socket.m_psi != NULL) - { - /* Instrumentation start */ - PSI_socket_locker *locker; - PSI_socket_locker_state state; - locker= PSI_SOCKET_CALL(start_socket_wait) - (&state, mysql_socket.m_psi, PSI_SOCKET_CONNECT, (size_t)0, src_file, src_line); - - /* Instrumented code */ - result= connect(mysql_socket.fd, addr, len); - - /* Instrumentation end */ - if (locker != NULL) - PSI_SOCKET_CALL(end_socket_wait)(locker, (size_t)0); - - return result; - } -#endif - - /* Non instrumented code */ - result= connect(mysql_socket.fd, addr, len); - - return result; -} - -/** mysql_socket_getpeername */ - -static inline int -inline_mysql_socket_getpeername -( -#ifdef HAVE_PSI_SOCKET_INTERFACE - const char *src_file, uint src_line, -#endif - MYSQL_SOCKET mysql_socket, struct sockaddr *addr, socklen_t *len) -{ - int result; - -#ifdef HAVE_PSI_SOCKET_INTERFACE - if (mysql_socket.m_psi != NULL) - { - /* Instrumentation start */ - PSI_socket_locker *locker; - PSI_socket_locker_state state; - locker= PSI_SOCKET_CALL(start_socket_wait) - (&state, mysql_socket.m_psi, PSI_SOCKET_BIND, (size_t)0, src_file, src_line); - - /* Instrumented code */ - result= getpeername(mysql_socket.fd, addr, len); - - /* Instrumentation end */ - if (locker != NULL) - PSI_SOCKET_CALL(end_socket_wait)(locker, (size_t)0); - - return result; - } -#endif - - /* Non instrumented code */ - result= getpeername(mysql_socket.fd, addr, len); - - return result; -} - -/** mysql_socket_send */ - -static inline ssize_t -inline_mysql_socket_send -( -#ifdef HAVE_PSI_SOCKET_INTERFACE - const char *src_file, uint src_line, -#endif - MYSQL_SOCKET mysql_socket, const SOCKBUF_T *buf, size_t n, int flags) -{ - ssize_t result; - -#ifdef HAVE_PSI_SOCKET_INTERFACE - if (mysql_socket.m_psi != NULL) - { - /* Instrumentation start */ - PSI_socket_locker *locker; - PSI_socket_locker_state state; - locker= PSI_SOCKET_CALL(start_socket_wait) - (&state, mysql_socket.m_psi, PSI_SOCKET_SEND, n, src_file, src_line); - - /* Instrumented code */ - result= send(mysql_socket.fd, buf, IF_WIN((int),) n, flags); - - /* Instrumentation end */ - if (locker != NULL) - { - size_t bytes_written; - bytes_written= (result > -1) ? result : 0; - PSI_SOCKET_CALL(end_socket_wait)(locker, bytes_written); - } - - return result; - } -#endif - - /* Non instrumented code */ - result= send(mysql_socket.fd, buf, IF_WIN((int),) n, flags); - - return result; -} - -/** mysql_socket_recv */ - -static inline ssize_t -inline_mysql_socket_recv -( -#ifdef HAVE_PSI_SOCKET_INTERFACE - const char *src_file, uint src_line, -#endif - MYSQL_SOCKET mysql_socket, SOCKBUF_T *buf, size_t n, int flags) -{ - ssize_t result; - -#ifdef HAVE_PSI_SOCKET_INTERFACE - if (mysql_socket.m_psi != NULL) - { - /* Instrumentation start */ - PSI_socket_locker *locker; - PSI_socket_locker_state state; - locker= PSI_SOCKET_CALL(start_socket_wait) - (&state, mysql_socket.m_psi, PSI_SOCKET_RECV, (size_t)0, src_file, src_line); - - /* Instrumented code */ - result= recv(mysql_socket.fd, buf, IF_WIN((int),) n, flags); - - /* Instrumentation end */ - if (locker != NULL) - { - size_t bytes_read; - bytes_read= (result > -1) ? result : 0; - PSI_SOCKET_CALL(end_socket_wait)(locker, bytes_read); - } - - return result; - } -#endif - - /* Non instrumented code */ - result= recv(mysql_socket.fd, buf, IF_WIN((int),) n, flags); - - return result; -} - -/** mysql_socket_sendto */ - -static inline ssize_t -inline_mysql_socket_sendto -( -#ifdef HAVE_PSI_SOCKET_INTERFACE - const char *src_file, uint src_line, -#endif - MYSQL_SOCKET mysql_socket, const SOCKBUF_T *buf, size_t n, int flags, const struct sockaddr *addr, socklen_t addr_len) -{ - ssize_t result; - -#ifdef HAVE_PSI_SOCKET_INTERFACE - if (mysql_socket.m_psi != NULL) - { - /* Instrumentation start */ - PSI_socket_locker *locker; - PSI_socket_locker_state state; - locker= PSI_SOCKET_CALL(start_socket_wait) - (&state, mysql_socket.m_psi, PSI_SOCKET_SEND, n, src_file, src_line); - - /* Instrumented code */ - result= sendto(mysql_socket.fd, buf, IF_WIN((int),) n, flags, addr, addr_len); - - /* Instrumentation end */ - if (locker != NULL) - { - size_t bytes_written; - bytes_written = (result > -1) ? result : 0; - PSI_SOCKET_CALL(end_socket_wait)(locker, bytes_written); - } - - return result; - } -#endif - - /* Non instrumented code */ - result= sendto(mysql_socket.fd, buf, IF_WIN((int),) n, flags, addr, addr_len); - - return result; -} - -/** mysql_socket_recvfrom */ - -static inline ssize_t -inline_mysql_socket_recvfrom -( -#ifdef HAVE_PSI_SOCKET_INTERFACE - const char *src_file, uint src_line, -#endif - MYSQL_SOCKET mysql_socket, SOCKBUF_T *buf, size_t n, int flags, - struct sockaddr *addr, socklen_t *addr_len) -{ - ssize_t result; - -#ifdef HAVE_PSI_SOCKET_INTERFACE - if (mysql_socket.m_psi != NULL) - { - /* Instrumentation start */ - PSI_socket_locker *locker; - PSI_socket_locker_state state; - locker= PSI_SOCKET_CALL(start_socket_wait) - (&state, mysql_socket.m_psi, PSI_SOCKET_RECV, (size_t)0, src_file, src_line); - - /* Instrumented code */ - result= recvfrom(mysql_socket.fd, buf, IF_WIN((int),) n, flags, addr, addr_len); - - /* Instrumentation end */ - if (locker != NULL) - { - size_t bytes_read; - bytes_read = (result > -1) ? result : 0; - PSI_SOCKET_CALL(end_socket_wait)(locker, bytes_read); - } - - return result; - } -#endif - - /* Non instrumented code */ - result= recvfrom(mysql_socket.fd, buf, IF_WIN((int),) n, flags, addr, addr_len); - - return result; -} - -/** mysql_socket_getsockopt */ - -static inline int -inline_mysql_socket_getsockopt -( -#ifdef HAVE_PSI_SOCKET_INTERFACE - const char *src_file, uint src_line, -#endif - MYSQL_SOCKET mysql_socket, int level, int optname, SOCKBUF_T *optval, socklen_t *optlen) -{ - int result; - -#ifdef HAVE_PSI_SOCKET_INTERFACE - if (mysql_socket.m_psi != NULL) - { - /* Instrumentation start */ - PSI_socket_locker *locker; - PSI_socket_locker_state state; - locker= PSI_SOCKET_CALL(start_socket_wait) - (&state, mysql_socket.m_psi, PSI_SOCKET_OPT, (size_t)0, src_file, src_line); - - /* Instrumented code */ - result= getsockopt(mysql_socket.fd, level, optname, optval, optlen); - - /* Instrumentation end */ - if (locker != NULL) - PSI_SOCKET_CALL(end_socket_wait)(locker, (size_t)0); - - return result; - } -#endif - - /* Non instrumented code */ - result= getsockopt(mysql_socket.fd, level, optname, optval, optlen); - - return result; -} - -/** mysql_socket_setsockopt */ - -static inline int -inline_mysql_socket_setsockopt -( -#ifdef HAVE_PSI_SOCKET_INTERFACE - const char *src_file, uint src_line, -#endif - MYSQL_SOCKET mysql_socket, int level, int optname, const SOCKBUF_T *optval, - socklen_t optlen) -{ - int result; - -#ifdef HAVE_PSI_SOCKET_INTERFACE - if (mysql_socket.m_psi) - { - /* Instrumentation start */ - PSI_socket_locker *locker; - PSI_socket_locker_state state; - locker= PSI_SOCKET_CALL(start_socket_wait) - (&state, mysql_socket.m_psi, PSI_SOCKET_OPT, (size_t)0, src_file, src_line); - - /* Instrumented code */ - result= setsockopt(mysql_socket.fd, level, optname, optval, optlen); - - /* Instrumentation end */ - if (locker != NULL) - PSI_SOCKET_CALL(end_socket_wait)(locker, (size_t)0); - - return result; - } -#endif - - /* Non instrumented code */ - result= setsockopt(mysql_socket.fd, level, optname, optval, optlen); - - return result; -} - -/** set_socket_nonblock */ -static inline int -set_socket_nonblock(my_socket fd) -{ - int ret= 0; -#ifdef _WIN32 - { - u_long nonblocking= 1; - ret= ioctlsocket(fd, FIONBIO, &nonblocking); - } -#else - { - int fd_flags; - fd_flags= fcntl(fd, F_GETFL, 0); - if (fd_flags < 0) - return errno; -#if defined(O_NONBLOCK) - fd_flags |= O_NONBLOCK; -#elif defined(O_NDELAY) - fd_flags |= O_NDELAY; -#elif defined(O_FNDELAY) - fd_flags |= O_FNDELAY; -#else -#error "No definition of non-blocking flag found." -#endif /* O_NONBLOCK */ - if (fcntl(fd, F_SETFL, fd_flags) == -1) - ret= errno; - } -#endif /* _WIN32 */ - return ret; -} - -/** mysql_socket_set_nonblocking */ - -static inline int -inline_mysql_sock_set_nonblocking -( -#ifdef HAVE_PSI_SOCKET_INTERFACE - const char *src_file, uint src_line, -#endif - MYSQL_SOCKET mysql_socket -) -{ - int result= 0; - -#ifdef HAVE_PSI_SOCKET_INTERFACE - if (mysql_socket.m_psi) - { - /* Instrumentation start */ - PSI_socket_locker *locker; - PSI_socket_locker_state state; - locker= PSI_SOCKET_CALL(start_socket_wait) - (&state, mysql_socket.m_psi, PSI_SOCKET_OPT, - (size_t)0, src_file, src_line); - - /* Instrumented code */ - result= set_socket_nonblock(mysql_socket.fd); - - /* Instrumentation end */ - if (locker != NULL) - PSI_SOCKET_CALL(end_socket_wait)(locker, (size_t)0); - - return result; - } -#endif - - /* Non instrumented code */ - result= set_socket_nonblock(mysql_socket.fd); - - return result; -} - -/** mysql_socket_listen */ - -static inline int -inline_mysql_socket_listen -( -#ifdef HAVE_PSI_SOCKET_INTERFACE - const char *src_file, uint src_line, -#endif - MYSQL_SOCKET mysql_socket, int backlog) -{ - int result; - -#ifdef HAVE_PSI_SOCKET_INTERFACE - if (mysql_socket.m_psi != NULL) - { - /* Instrumentation start */ - PSI_socket_locker *locker; - PSI_socket_locker_state state; - locker= PSI_SOCKET_CALL(start_socket_wait) - (&state, mysql_socket.m_psi, PSI_SOCKET_CONNECT, (size_t)0, src_file, src_line); - - /* Instrumented code */ - result= listen(mysql_socket.fd, backlog); - - /* Instrumentation end */ - if (locker != NULL) - PSI_SOCKET_CALL(end_socket_wait)(locker, (size_t)0); - - return result; - } -#endif - - /* Non instrumented code */ - result= listen(mysql_socket.fd, backlog); - - return result; -} - -/** mysql_socket_accept */ - -static inline MYSQL_SOCKET -inline_mysql_socket_accept -( -#ifdef HAVE_PSI_SOCKET_INTERFACE - const char *src_file, uint src_line, PSI_socket_key key, -#endif - MYSQL_SOCKET socket_listen, struct sockaddr *addr, socklen_t *addr_len) -{ - MYSQL_SOCKET socket_accept= MYSQL_INVALID_SOCKET; - socklen_t addr_length= (addr_len != NULL) ? *addr_len : 0; - -#ifdef HAVE_PSI_SOCKET_INTERFACE - if (socket_listen.m_psi != NULL) - { - /* Instrumentation start */ - PSI_socket_locker *locker; - PSI_socket_locker_state state; - locker= PSI_SOCKET_CALL(start_socket_wait) - (&state, socket_listen.m_psi, PSI_SOCKET_CONNECT, (size_t)0, src_file, src_line); - - /* Instrumented code */ - socket_accept.fd= accept(socket_listen.fd, addr, &addr_length); - - /* Instrumentation end */ - if (locker != NULL) - PSI_SOCKET_CALL(end_socket_wait)(locker, (size_t)0); - } - else -#endif - { - /* Non instrumented code */ - socket_accept.fd= accept(socket_listen.fd, addr, &addr_length); - } - -#ifdef HAVE_PSI_SOCKET_INTERFACE - if (likely(socket_accept.fd != INVALID_SOCKET)) - { - /* Initialize the instrument with the new socket descriptor and address */ - socket_accept.m_psi= PSI_SOCKET_CALL(init_socket) - (key, (const my_socket*)&socket_accept.fd, addr, addr_length); - } -#endif - - return socket_accept; -} - -/** mysql_socket_close */ - -static inline int -inline_mysql_socket_close -( -#ifdef HAVE_PSI_SOCKET_INTERFACE - const char *src_file, uint src_line, -#endif - MYSQL_SOCKET mysql_socket) -{ - int result; - -#ifdef HAVE_PSI_SOCKET_INTERFACE - if (mysql_socket.m_psi != NULL) - { - /* Instrumentation start */ - PSI_socket_locker *locker; - PSI_socket_locker_state state; - locker= PSI_SOCKET_CALL(start_socket_wait) - (&state, mysql_socket.m_psi, PSI_SOCKET_CLOSE, (size_t)0, src_file, src_line); - - /* Instrumented code */ - result= closesocket(mysql_socket.fd); - - /* Instrumentation end */ - if (locker != NULL) - PSI_SOCKET_CALL(end_socket_wait)(locker, (size_t)0); - /* Remove the instrumentation for this socket. */ - if (mysql_socket.m_psi != NULL) - PSI_SOCKET_CALL(destroy_socket)(mysql_socket.m_psi); - - return result; - } -#endif - - /* Non instrumented code */ - result= closesocket(mysql_socket.fd); - - return result; -} - -/** mysql_socket_shutdown */ - -static inline int -inline_mysql_socket_shutdown -( -#ifdef HAVE_PSI_SOCKET_INTERFACE - const char *src_file, uint src_line, -#endif - MYSQL_SOCKET mysql_socket, int how) -{ - int result; - -#ifdef _WIN32 - static LPFN_DISCONNECTEX DisconnectEx = NULL; - if (DisconnectEx == NULL) - { - DWORD dwBytesReturned; - GUID guidDisconnectEx = WSAID_DISCONNECTEX; - WSAIoctl(mysql_socket.fd, SIO_GET_EXTENSION_FUNCTION_POINTER, - &guidDisconnectEx, sizeof(GUID), - &DisconnectEx, sizeof(DisconnectEx), - &dwBytesReturned, NULL, NULL); - } -#endif - -/* Instrumentation start */ -#ifdef HAVE_PSI_SOCKET_INTERFACE - if (mysql_socket.m_psi != NULL) - { - PSI_socket_locker *locker; - PSI_socket_locker_state state; - locker= PSI_SOCKET_CALL(start_socket_wait) - (&state, mysql_socket.m_psi, PSI_SOCKET_SHUTDOWN, (size_t)0, src_file, src_line); - - /* Instrumented code */ -#ifdef _WIN32 - if (DisconnectEx) - result= (DisconnectEx(mysql_socket.fd, (LPOVERLAPPED) NULL, - (DWORD) 0, (DWORD) 0) == TRUE) ? 0 : -1; - else -#endif - result= shutdown(mysql_socket.fd, how); - - /* Instrumentation end */ - if (locker != NULL) - PSI_SOCKET_CALL(end_socket_wait)(locker, (size_t)0); - - return result; - } -#endif - - /* Non instrumented code */ -#ifdef _WIN32 - if (DisconnectEx) - result= (DisconnectEx(mysql_socket.fd, (LPOVERLAPPED) NULL, - (DWORD) 0, (DWORD) 0) == TRUE) ? 0 : -1; - else -#endif - result= shutdown(mysql_socket.fd, how); - - return result; -} - -/** @} (end of group Socket_instrumentation) */ - -#endif - diff --git a/vendor/mysql/include/mysql/psi/mysql_sp.h b/vendor/mysql/include/mysql/psi/mysql_sp.h deleted file mode 100644 index 68fc468db1..0000000000 --- a/vendor/mysql/include/mysql/psi/mysql_sp.h +++ /dev/null @@ -1,97 +0,0 @@ -/* Copyright (c) 2013, Oracle and/or its affiliates. All rights reserved. - - This program is free software; you can redistribute it and/or modify - it under the terms of the GNU General Public License as published by - the Free Software Foundation; version 2 of the License. - - This program is distributed in the hope that it will be useful, - but WITHOUT ANY WARRANTY; without even the implied warranty of - MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - GNU General Public License for more details. - - You should have received a copy of the GNU General Public License - along with this program; if not, write to the Free Software - Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA */ - -#ifndef MYSQL_SP_H -#define MYSQL_SP_H - -/** - @file mysql/psi/mysql_sp.h - Instrumentation helpers for stored programs. -*/ - -#include "mysql/psi/psi.h" - -#ifndef PSI_SP_CALL -#define PSI_SP_CALL(M) PSI_DYNAMIC_CALL(M) -#endif - -#ifdef HAVE_PSI_SP_INTERFACE - #define MYSQL_START_SP(STATE, SP_SHARE) \ - inline_mysql_start_sp(STATE, SP_SHARE) -#else - #define MYSQL_START_SP(STATE, SP_SHARE) \ - NULL -#endif - - -#ifdef HAVE_PSI_SP_INTERFACE - #define MYSQL_END_SP(LOCKER) \ - inline_mysql_end_sp(LOCKER) -#else - #define MYSQL_END_SP(LOCKER) \ - do {} while (0) -#endif - -#ifdef HAVE_PSI_SP_INTERFACE - #define MYSQL_DROP_SP(OT, SN, SNL, ON, ONL) \ - inline_mysql_drop_sp(OT, SN, SNL, ON, ONL) -#else - #define MYSQL_DROP_SP(OT, SN, SNL, ON, ONL) \ - do {} while (0) -#endif - -#ifdef HAVE_PSI_SP_INTERFACE - #define MYSQL_GET_SP_SHARE(OT, SN, SNL, ON, ONL) \ - inline_mysql_get_sp_share(OT, SN, SNL, ON, ONL) -#else - #define MYSQL_GET_SP_SHARE(OT, SN, SNL, ON, ONL) \ - NULL -#endif - -#ifdef HAVE_PSI_SP_INTERFACE -static inline struct PSI_sp_locker* -inline_mysql_start_sp(PSI_sp_locker_state *state, PSI_sp_share *sp_share) -{ - return PSI_SP_CALL(start_sp)(state, sp_share); -} - -static inline void inline_mysql_end_sp(PSI_sp_locker *locker) -{ - if (likely(locker != NULL)) - PSI_SP_CALL(end_sp)(locker); -} - -static inline void -inline_mysql_drop_sp(uint sp_type, - const char* schema_name, uint shcema_name_length, - const char* object_name, uint object_name_length) -{ - PSI_SP_CALL(drop_sp)(sp_type, - schema_name, shcema_name_length, - object_name, object_name_length); -} - -static inline PSI_sp_share* -inline_mysql_get_sp_share(uint sp_type, - const char* schema_name, uint shcema_name_length, - const char* object_name, uint object_name_length) -{ - return PSI_SP_CALL(get_sp_share)(sp_type, - schema_name, shcema_name_length, - object_name, object_name_length); -} -#endif - -#endif diff --git a/vendor/mysql/include/mysql/psi/mysql_stage.h b/vendor/mysql/include/mysql/psi/mysql_stage.h deleted file mode 100644 index 9c1623f437..0000000000 --- a/vendor/mysql/include/mysql/psi/mysql_stage.h +++ /dev/null @@ -1,198 +0,0 @@ -/* Copyright (c) 2010, 2014, Oracle and/or its affiliates. All rights reserved. - - This program is free software; you can redistribute it and/or modify - it under the terms of the GNU General Public License as published by - the Free Software Foundation; version 2 of the License. - - This program is distributed in the hope that it will be useful, - but WITHOUT ANY WARRANTY; without even the implied warranty of - MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - GNU General Public License for more details. - - You should have received a copy of the GNU General Public License - along with this program; if not, write to the Free Software - Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA */ - -#ifndef MYSQL_STAGE_H -#define MYSQL_STAGE_H - -/** - @file mysql/psi/mysql_stage.h - Instrumentation helpers for stages. -*/ - -#include "mysql/psi/psi.h" - -#ifndef PSI_STAGE_CALL -#define PSI_STAGE_CALL(M) PSI_DYNAMIC_CALL(M) -#endif - -/** - @defgroup Stage_instrumentation Stage Instrumentation - @ingroup Instrumentation_interface - @{ -*/ - -/** - @def mysql_stage_register(P1, P2, P3) - Stage registration. -*/ -#ifdef HAVE_PSI_STAGE_INTERFACE -#define mysql_stage_register(P1, P2, P3) \ - inline_mysql_stage_register(P1, P2, P3) -#else -#define mysql_stage_register(P1, P2, P3) \ - do {} while (0) -#endif - -/** - @def MYSQL_SET_STAGE - Set the current stage. - Use this API when the file and line - is passed from the caller. - @param K the stage key - @param F the source file name - @param L the source file line - @return the current stage progress -*/ -#ifdef HAVE_PSI_STAGE_INTERFACE - #define MYSQL_SET_STAGE(K, F, L) \ - inline_mysql_set_stage(K, F, L) -#else - #define MYSQL_SET_STAGE(K, F, L) \ - NULL -#endif - -/** - @def mysql_set_stage - Set the current stage. - @param K the stage key - @return the current stage progress -*/ -#ifdef HAVE_PSI_STAGE_INTERFACE - #define mysql_set_stage(K) \ - inline_mysql_set_stage(K, __FILE__, __LINE__) -#else - #define mysql_set_stage(K) \ - NULL -#endif - -/** - @def mysql_end_stage - End the last stage -*/ -#ifdef HAVE_PSI_STAGE_INTERFACE - #define mysql_end_stage \ - inline_mysql_end_stage -#else - #define mysql_end_stage \ - do {} while (0) -#endif - -#ifdef HAVE_PSI_STAGE_INTERFACE -static inline void inline_mysql_stage_register( - const char *category, PSI_stage_info **info, int count) -{ - PSI_STAGE_CALL(register_stage)(category, info, count); -} -#endif - -#ifdef HAVE_PSI_STAGE_INTERFACE -static inline PSI_stage_progress* -inline_mysql_set_stage(PSI_stage_key key, - const char *src_file, int src_line) -{ - return PSI_STAGE_CALL(start_stage)(key, src_file, src_line); -} -#endif - -#ifdef HAVE_PSI_STAGE_INTERFACE -static inline void -inline_mysql_end_stage() -{ - PSI_STAGE_CALL(end_stage)(); -} -#endif - -#ifdef HAVE_PSI_STAGE_INTERFACE -#define mysql_stage_set_work_completed(P1, P2) \ - inline_mysql_stage_set_work_completed(P1, P2) - -#define mysql_stage_get_work_completed(P1) \ - inline_mysql_stage_get_work_completed(P1) -#else -#define mysql_stage_set_work_completed(P1, P2) \ - do {} while (0) - -#define mysql_stage_get_work_completed(P1) \ - do {} while (0) -#endif - -#ifdef HAVE_PSI_STAGE_INTERFACE -#define mysql_stage_inc_work_completed(P1, P2) \ - inline_mysql_stage_inc_work_completed(P1, P2) -#else -#define mysql_stage_inc_work_completed(P1, P2) \ - do {} while (0) -#endif - -#ifdef HAVE_PSI_STAGE_INTERFACE -#define mysql_stage_set_work_estimated(P1, P2) \ - inline_mysql_stage_set_work_estimated(P1, P2) - -#define mysql_stage_get_work_estimated(P1) \ - inline_mysql_stage_get_work_estimated(P1) -#else -#define mysql_stage_set_work_estimated(P1, P2) \ - do {} while (0) - -#define mysql_stage_get_work_estimated(P1) \ - do {} while (0) -#endif - -#ifdef HAVE_PSI_STAGE_INTERFACE -static inline void -inline_mysql_stage_set_work_completed(PSI_stage_progress *progress, - ulonglong val) -{ - if (progress != NULL) - progress->m_work_completed= val; -} - -static inline ulonglong -inline_mysql_stage_get_work_completed(PSI_stage_progress *progress) -{ - return progress->m_work_completed; -} -#endif - -#ifdef HAVE_PSI_STAGE_INTERFACE -static inline void -inline_mysql_stage_inc_work_completed(PSI_stage_progress *progress, - ulonglong val) -{ - if (progress != NULL) - progress->m_work_completed+= val; -} -#endif - -#ifdef HAVE_PSI_STAGE_INTERFACE -static inline void -inline_mysql_stage_set_work_estimated(PSI_stage_progress *progress, - ulonglong val) -{ - if (progress != NULL) - progress->m_work_estimated= val; -} - -static inline ulonglong -inline_mysql_stage_get_work_estimated(PSI_stage_progress *progress) -{ - return progress->m_work_estimated; -} -#endif - -/** @} (end of group Stage_instrumentation) */ - -#endif - diff --git a/vendor/mysql/include/mysql/psi/mysql_statement.h b/vendor/mysql/include/mysql/psi/mysql_statement.h deleted file mode 100644 index 9c27933b06..0000000000 --- a/vendor/mysql/include/mysql/psi/mysql_statement.h +++ /dev/null @@ -1,235 +0,0 @@ -/* Copyright (c) 2010, 2015, Oracle and/or its affiliates. All rights reserved. - - This program is free software; you can redistribute it and/or modify - it under the terms of the GNU General Public License as published by - the Free Software Foundation; version 2 of the License. - - This program is distributed in the hope that it will be useful, - but WITHOUT ANY WARRANTY; without even the implied warranty of - MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - GNU General Public License for more details. - - You should have received a copy of the GNU General Public License - along with this program; if not, write to the Free Software - Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA */ - -#ifndef MYSQL_STATEMENT_H -#define MYSQL_STATEMENT_H - -/** - @file mysql/psi/mysql_statement.h - Instrumentation helpers for statements. -*/ - -#include "mysql/psi/psi.h" - -class Diagnostics_area; -typedef struct charset_info_st CHARSET_INFO; - -#ifndef PSI_STATEMENT_CALL -#define PSI_STATEMENT_CALL(M) PSI_DYNAMIC_CALL(M) -#endif - -#ifndef PSI_DIGEST_CALL -#define PSI_DIGEST_CALL(M) PSI_DYNAMIC_CALL(M) -#endif - -/** - @defgroup Statement_instrumentation Statement Instrumentation - @ingroup Instrumentation_interface - @{ -*/ - -/** - @def mysql_statement_register(P1, P2, P3) - Statement registration. -*/ -#ifdef HAVE_PSI_STATEMENT_INTERFACE -#define mysql_statement_register(P1, P2, P3) \ - inline_mysql_statement_register(P1, P2, P3) -#else -#define mysql_statement_register(P1, P2, P3) \ - do {} while (0) -#endif - -#ifdef HAVE_PSI_STATEMENT_DIGEST_INTERFACE - #define MYSQL_DIGEST_START(LOCKER) \ - inline_mysql_digest_start(LOCKER) -#else - #define MYSQL_DIGEST_START(LOCKER) \ - NULL -#endif - -#ifdef HAVE_PSI_STATEMENT_DIGEST_INTERFACE - #define MYSQL_DIGEST_END(LOCKER, DIGEST) \ - inline_mysql_digest_end(LOCKER, DIGEST) -#else - #define MYSQL_DIGEST_END(LOCKER, DIGEST) \ - do {} while (0) -#endif - -#ifdef HAVE_PSI_STATEMENT_INTERFACE - #define MYSQL_START_STATEMENT(STATE, K, DB, DB_LEN, CS, SPS) \ - inline_mysql_start_statement(STATE, K, DB, DB_LEN, CS, SPS, __FILE__, __LINE__) -#else - #define MYSQL_START_STATEMENT(STATE, K, DB, DB_LEN, CS, SPS) \ - NULL -#endif - -#ifdef HAVE_PSI_STATEMENT_INTERFACE - #define MYSQL_REFINE_STATEMENT(LOCKER, K) \ - inline_mysql_refine_statement(LOCKER, K) -#else - #define MYSQL_REFINE_STATEMENT(LOCKER, K) \ - NULL -#endif - -#ifdef HAVE_PSI_STATEMENT_INTERFACE - #define MYSQL_SET_STATEMENT_TEXT(LOCKER, P1, P2) \ - inline_mysql_set_statement_text(LOCKER, P1, P2) -#else - #define MYSQL_SET_STATEMENT_TEXT(LOCKER, P1, P2) \ - do {} while (0) -#endif - -#ifdef HAVE_PSI_STATEMENT_INTERFACE - #define MYSQL_SET_STATEMENT_LOCK_TIME(LOCKER, P1) \ - inline_mysql_set_statement_lock_time(LOCKER, P1) -#else - #define MYSQL_SET_STATEMENT_LOCK_TIME(LOCKER, P1) \ - do {} while (0) -#endif - -#ifdef HAVE_PSI_STATEMENT_INTERFACE - #define MYSQL_SET_STATEMENT_ROWS_SENT(LOCKER, P1) \ - inline_mysql_set_statement_rows_sent(LOCKER, P1) -#else - #define MYSQL_SET_STATEMENT_ROWS_SENT(LOCKER, P1) \ - do {} while (0) -#endif - -#ifdef HAVE_PSI_STATEMENT_INTERFACE - #define MYSQL_SET_STATEMENT_ROWS_EXAMINED(LOCKER, P1) \ - inline_mysql_set_statement_rows_examined(LOCKER, P1) -#else - #define MYSQL_SET_STATEMENT_ROWS_EXAMINED(LOCKER, P1) \ - do {} while (0) -#endif - -#ifdef HAVE_PSI_STATEMENT_INTERFACE - #define MYSQL_END_STATEMENT(LOCKER, DA) \ - inline_mysql_end_statement(LOCKER, DA) -#else - #define MYSQL_END_STATEMENT(LOCKER, DA) \ - do {} while (0) -#endif - -#ifdef HAVE_PSI_STATEMENT_INTERFACE -static inline void inline_mysql_statement_register( - const char *category, PSI_statement_info *info, int count) -{ - PSI_STATEMENT_CALL(register_statement)(category, info, count); -} - -#ifdef HAVE_PSI_STATEMENT_DIGEST_INTERFACE -static inline struct PSI_digest_locker * -inline_mysql_digest_start(PSI_statement_locker *locker) -{ - PSI_digest_locker* digest_locker= NULL; - - if (likely(locker != NULL)) - digest_locker= PSI_DIGEST_CALL(digest_start)(locker); - return digest_locker; -} -#endif - -#ifdef HAVE_PSI_STATEMENT_DIGEST_INTERFACE -static inline void -inline_mysql_digest_end(PSI_digest_locker *locker, const sql_digest_storage *digest) -{ - if (likely(locker != NULL)) - PSI_DIGEST_CALL(digest_end)(locker, digest); -} -#endif - -static inline struct PSI_statement_locker * -inline_mysql_start_statement(PSI_statement_locker_state *state, - PSI_statement_key key, - const char *db, uint db_len, - const CHARSET_INFO *charset, - PSI_sp_share *sp_share, - const char *src_file, int src_line) -{ - PSI_statement_locker *locker; - locker= PSI_STATEMENT_CALL(get_thread_statement_locker)(state, key, charset, - sp_share); - if (likely(locker != NULL)) - PSI_STATEMENT_CALL(start_statement)(locker, db, db_len, src_file, src_line); - return locker; -} - -static inline struct PSI_statement_locker * -inline_mysql_refine_statement(PSI_statement_locker *locker, - PSI_statement_key key) -{ - if (likely(locker != NULL)) - { - locker= PSI_STATEMENT_CALL(refine_statement)(locker, key); - } - return locker; -} - -static inline void -inline_mysql_set_statement_text(PSI_statement_locker *locker, - const char *text, uint text_len) -{ - if (likely(locker != NULL)) - { - PSI_STATEMENT_CALL(set_statement_text)(locker, text, text_len); - } -} - -static inline void -inline_mysql_set_statement_lock_time(PSI_statement_locker *locker, - ulonglong count) -{ - if (likely(locker != NULL)) - { - PSI_STATEMENT_CALL(set_statement_lock_time)(locker, count); - } -} - -static inline void -inline_mysql_set_statement_rows_sent(PSI_statement_locker *locker, - ulonglong count) -{ - if (likely(locker != NULL)) - { - PSI_STATEMENT_CALL(set_statement_rows_sent)(locker, count); - } -} - -static inline void -inline_mysql_set_statement_rows_examined(PSI_statement_locker *locker, - ulonglong count) -{ - if (likely(locker != NULL)) - { - PSI_STATEMENT_CALL(set_statement_rows_examined)(locker, count); - } -} - -static inline void -inline_mysql_end_statement(struct PSI_statement_locker *locker, - Diagnostics_area *stmt_da) -{ - PSI_STAGE_CALL(end_stage)(); - if (likely(locker != NULL)) - PSI_STATEMENT_CALL(end_statement)(locker, stmt_da); -} -#endif - -/** @} (end of group Statement_instrumentation) */ - -#endif - diff --git a/vendor/mysql/include/mysql/psi/mysql_table.h b/vendor/mysql/include/mysql/psi/mysql_table.h deleted file mode 100644 index 00f75661b7..0000000000 --- a/vendor/mysql/include/mysql/psi/mysql_table.h +++ /dev/null @@ -1,142 +0,0 @@ -/* Copyright (c) 2010, 2014, Oracle and/or its affiliates. All rights reserved. - - This program is free software; you can redistribute it and/or modify - it under the terms of the GNU General Public License as published by - the Free Software Foundation; version 2 of the License. - - This program is distributed in the hope that it will be useful, - but WITHOUT ANY WARRANTY; without even the implied warranty of - MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - GNU General Public License for more details. - - You should have received a copy of the GNU General Public License - along with this program; if not, write to the Free Software Foundation, - 51 Franklin Street, Suite 500, Boston, MA 02110-1335 USA */ - -#ifndef MYSQL_TABLE_H -#define MYSQL_TABLE_H - -/** - @file mysql/psi/mysql_table.h - Instrumentation helpers for table io. -*/ - -#include "mysql/psi/psi.h" - -#ifndef PSI_TABLE_CALL -#define PSI_TABLE_CALL(M) PSI_DYNAMIC_CALL(M) -#endif - -/** - @defgroup Table_instrumentation Table Instrumentation - @ingroup Instrumentation_interface - @{ -*/ - -/** - @def MYSQL_TABLE_WAIT_VARIABLES - Instrumentation helper for table waits. - This instrumentation declares local variables. - Do not use a ';' after this macro - @param LOCKER the locker - @param STATE the locker state - @sa MYSQL_START_TABLE_IO_WAIT. - @sa MYSQL_END_TABLE_IO_WAIT. - @sa MYSQL_START_TABLE_LOCK_WAIT. - @sa MYSQL_END_TABLE_LOCK_WAIT. -*/ -#ifdef HAVE_PSI_TABLE_INTERFACE - #define MYSQL_TABLE_WAIT_VARIABLES(LOCKER, STATE) \ - struct PSI_table_locker* LOCKER; \ - PSI_table_locker_state STATE; -#else - #define MYSQL_TABLE_WAIT_VARIABLES(LOCKER, STATE) -#endif - -/** - @def MYSQL_START_TABLE_LOCK_WAIT - Instrumentation helper for table lock waits. - This instrumentation marks the start of a wait event. - @param LOCKER the locker - @param STATE the locker state - @param PSI the instrumented table - @param OP the table operation to be performed - @param FLAGS per table operation flags. - @sa MYSQL_END_TABLE_LOCK_WAIT. -*/ -#ifdef HAVE_PSI_TABLE_INTERFACE - #define MYSQL_START_TABLE_LOCK_WAIT(LOCKER, STATE, PSI, OP, FLAGS) \ - LOCKER= inline_mysql_start_table_lock_wait(STATE, PSI, \ - OP, FLAGS, __FILE__, __LINE__) -#else - #define MYSQL_START_TABLE_LOCK_WAIT(LOCKER, STATE, PSI, OP, FLAGS) \ - do {} while (0) -#endif - -/** - @def MYSQL_END_TABLE_LOCK_WAIT - Instrumentation helper for table lock waits. - This instrumentation marks the end of a wait event. - @param LOCKER the locker - @sa MYSQL_START_TABLE_LOCK_WAIT. -*/ -#ifdef HAVE_PSI_TABLE_INTERFACE - #define MYSQL_END_TABLE_LOCK_WAIT(LOCKER) \ - inline_mysql_end_table_lock_wait(LOCKER) -#else - #define MYSQL_END_TABLE_LOCK_WAIT(LOCKER) \ - do {} while (0) -#endif - -#ifdef HAVE_PSI_TABLE_INTERFACE - #define MYSQL_UNLOCK_TABLE(T) \ - inline_mysql_unlock_table(T) -#else - #define MYSQL_UNLOCK_TABLE(T) \ - do {} while (0) -#endif - -#ifdef HAVE_PSI_TABLE_INTERFACE -/** - Instrumentation calls for MYSQL_START_TABLE_LOCK_WAIT. - @sa MYSQL_END_TABLE_LOCK_WAIT. -*/ -static inline struct PSI_table_locker * -inline_mysql_start_table_lock_wait(PSI_table_locker_state *state, - struct PSI_table *psi, - enum PSI_table_lock_operation op, - ulong flags, const char *src_file, int src_line) -{ - if (psi != NULL) - { - struct PSI_table_locker *locker; - locker= PSI_TABLE_CALL(start_table_lock_wait) - (state, psi, op, flags, src_file, src_line); - return locker; - } - return NULL; -} - -/** - Instrumentation calls for MYSQL_END_TABLE_LOCK_WAIT. - @sa MYSQL_START_TABLE_LOCK_WAIT. -*/ -static inline void -inline_mysql_end_table_lock_wait(struct PSI_table_locker *locker) -{ - if (locker != NULL) - PSI_TABLE_CALL(end_table_lock_wait)(locker); -} - -static inline void -inline_mysql_unlock_table(struct PSI_table *table) -{ - if (table != NULL) - PSI_TABLE_CALL(unlock_table)(table); -} -#endif - -/** @} (end of group Table_instrumentation) */ - -#endif - diff --git a/vendor/mysql/include/mysql/psi/mysql_thread.h b/vendor/mysql/include/mysql/psi/mysql_thread.h deleted file mode 100644 index c5ace991e0..0000000000 --- a/vendor/mysql/include/mysql/psi/mysql_thread.h +++ /dev/null @@ -1,1323 +0,0 @@ -/* Copyright (c) 2008, 2016, Oracle and/or its affiliates. All rights reserved. - - This program is free software; you can redistribute it and/or modify - it under the terms of the GNU General Public License as published by - the Free Software Foundation; version 2 of the License. - - This program is distributed in the hope that it will be useful, - but WITHOUT ANY WARRANTY; without even the implied warranty of - MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - GNU General Public License for more details. - - You should have received a copy of the GNU General Public License - along with this program; if not, write to the Free Software Foundation, - 51 Franklin Street, Suite 500, Boston, MA 02110-1335 USA */ - -#ifndef MYSQL_THREAD_H -#define MYSQL_THREAD_H - -/** - @file mysql/psi/mysql_thread.h - Instrumentation helpers for mysys threads, mutexes, - read write locks and conditions. - This header file provides the necessary declarations - to use the mysys thread API with the performance schema instrumentation. - In some compilers (SunStudio), 'static inline' functions, when declared - but not used, are not optimized away (because they are unused) by default, - so that including a static inline function from a header file does - create unwanted dependencies, causing unresolved symbols at link time. - Other compilers, like gcc, optimize these dependencies by default. - - Since the instrumented APIs declared here are wrapper on top - of my_thread / safemutex / etc APIs, - including mysql/psi/mysql_thread.h assumes that - the dependency on my_thread and safemutex already exists. -*/ -/* - Note: there are several orthogonal dimensions here. - - Dimension 1: Instrumentation - HAVE_PSI_INTERFACE is defined when the instrumentation is compiled in. - This may happen both in debug or production builds. - - Dimension 2: Debug - SAFE_MUTEX is defined when debug is compiled in. - This may happen both with and without instrumentation. - - Dimension 3: Platform - Mutexes are implemented with one of: - - the pthread library - - fast mutexes - - window apis - This is implemented by various macro definitions in my_thread.h - - This causes complexity with '#ifdef'-ery that can't be avoided. -*/ - -#include "my_thread.h" -#include "my_thread_local.h" -#include "thr_mutex.h" -#include "thr_rwlock.h" -#include "mysql/psi/psi.h" -#ifdef MYSQL_SERVER -#ifndef MYSQL_DYNAMIC_PLUGIN -#include "pfs_thread_provider.h" -#endif -#endif - -#ifndef PSI_MUTEX_CALL -#define PSI_MUTEX_CALL(M) PSI_DYNAMIC_CALL(M) -#endif - -#ifndef PSI_RWLOCK_CALL -#define PSI_RWLOCK_CALL(M) PSI_DYNAMIC_CALL(M) -#endif - -#ifndef PSI_COND_CALL -#define PSI_COND_CALL(M) PSI_DYNAMIC_CALL(M) -#endif - -#ifndef PSI_THREAD_CALL -#define PSI_THREAD_CALL(M) PSI_DYNAMIC_CALL(M) -#endif - -/** - @defgroup Thread_instrumentation Thread Instrumentation - @ingroup Instrumentation_interface - @{ -*/ - -/** - An instrumented mutex structure. - @sa mysql_mutex_t -*/ -struct st_mysql_mutex -{ - /** The real mutex. */ - my_mutex_t m_mutex; - /** - The instrumentation hook. - Note that this hook is not conditionally defined, - for binary compatibility of the @c mysql_mutex_t interface. - */ - struct PSI_mutex *m_psi; -}; - -/** - Type of an instrumented mutex. - @c mysql_mutex_t is a drop-in replacement for @c my_mutex_t. - @sa mysql_mutex_assert_owner - @sa mysql_mutex_assert_not_owner - @sa mysql_mutex_init - @sa mysql_mutex_lock - @sa mysql_mutex_unlock - @sa mysql_mutex_destroy -*/ -typedef struct st_mysql_mutex mysql_mutex_t; - -/** - An instrumented rwlock structure. - @sa mysql_rwlock_t -*/ -struct st_mysql_rwlock -{ - /** The real rwlock */ - native_rw_lock_t m_rwlock; - /** - The instrumentation hook. - Note that this hook is not conditionally defined, - for binary compatibility of the @c mysql_rwlock_t interface. - */ - struct PSI_rwlock *m_psi; -}; - -/** - An instrumented prlock structure. - @sa mysql_prlock_t -*/ -struct st_mysql_prlock -{ - /** The real prlock */ - rw_pr_lock_t m_prlock; - /** - The instrumentation hook. - Note that this hook is not conditionally defined, - for binary compatibility of the @c mysql_rwlock_t interface. - */ - struct PSI_rwlock *m_psi; -}; - -/** - Type of an instrumented rwlock. - @c mysql_rwlock_t is a drop-in replacement for @c pthread_rwlock_t. - @sa mysql_rwlock_init - @sa mysql_rwlock_rdlock - @sa mysql_rwlock_tryrdlock - @sa mysql_rwlock_wrlock - @sa mysql_rwlock_trywrlock - @sa mysql_rwlock_unlock - @sa mysql_rwlock_destroy -*/ -typedef struct st_mysql_rwlock mysql_rwlock_t; - -/** - Type of an instrumented prlock. - A prlock is a read write lock that 'prefers readers' (pr). - @c mysql_prlock_t is a drop-in replacement for @c rw_pr_lock_t. - @sa mysql_prlock_init - @sa mysql_prlock_rdlock - @sa mysql_prlock_wrlock - @sa mysql_prlock_unlock - @sa mysql_prlock_destroy -*/ -typedef struct st_mysql_prlock mysql_prlock_t; - -/** - An instrumented cond structure. - @sa mysql_cond_t -*/ -struct st_mysql_cond -{ - /** The real condition */ - native_cond_t m_cond; - /** - The instrumentation hook. - Note that this hook is not conditionally defined, - for binary compatibility of the @c mysql_cond_t interface. - */ - struct PSI_cond *m_psi; -}; - -/** - Type of an instrumented condition. - @c mysql_cond_t is a drop-in replacement for @c native_cond_t. - @sa mysql_cond_init - @sa mysql_cond_wait - @sa mysql_cond_timedwait - @sa mysql_cond_signal - @sa mysql_cond_broadcast - @sa mysql_cond_destroy -*/ -typedef struct st_mysql_cond mysql_cond_t; - -/* - Consider the following code: - static inline void foo() { bar(); } - when foo() is never called. - - With gcc, foo() is a local static function, so the dependencies - are optimized away at compile time, and there is no dependency on bar(). - With other compilers (HP, Sun Studio), the function foo() implementation - is compiled, and bar() needs to be present to link. - - Due to the existing header dependencies in MySQL code, this header file - is sometime used when it is not needed, which in turn cause link failures - on some platforms. - The proper fix would be to cut these extra dependencies in the calling code. - DISABLE_MYSQL_THREAD_H is a work around to limit dependencies. - DISABLE_MYSQL_PRLOCK_H is similar, and is used to disable specifically - the prlock wrappers. -*/ -#ifndef DISABLE_MYSQL_THREAD_H - -/** - @def mysql_mutex_assert_owner(M) - Wrapper, to use safe_mutex_assert_owner with instrumented mutexes. - @c mysql_mutex_assert_owner is a drop-in replacement - for @c safe_mutex_assert_owner. -*/ -#ifdef SAFE_MUTEX -#define mysql_mutex_assert_owner(M) \ - safe_mutex_assert_owner(&(M)->m_mutex); -#else -#define mysql_mutex_assert_owner(M) { } -#endif - -/** - @def mysql_mutex_assert_not_owner(M) - Wrapper, to use safe_mutex_assert_not_owner with instrumented mutexes. - @c mysql_mutex_assert_not_owner is a drop-in replacement - for @c safe_mutex_assert_not_owner. -*/ -#ifdef SAFE_MUTEX -#define mysql_mutex_assert_not_owner(M) \ - safe_mutex_assert_not_owner(&(M)->m_mutex); -#else -#define mysql_mutex_assert_not_owner(M) { } -#endif - -/** - @def mysql_prlock_assert_write_owner(M) - Drop-in replacement - for @c rw_pr_lock_assert_write_owner. -*/ -#define mysql_prlock_assert_write_owner(M) \ - rw_pr_lock_assert_write_owner(&(M)->m_prlock) - -/** - @def mysql_prlock_assert_not_write_owner(M) - Drop-in replacement - for @c rw_pr_lock_assert_not_write_owner. -*/ -#define mysql_prlock_assert_not_write_owner(M) \ - rw_pr_lock_assert_not_write_owner(&(M)->m_prlock) - -/** - @def mysql_mutex_register(P1, P2, P3) - Mutex registration. -*/ -#define mysql_mutex_register(P1, P2, P3) \ - inline_mysql_mutex_register(P1, P2, P3) - -/** - @def mysql_mutex_init(K, M, A) - Instrumented mutex_init. - @c mysql_mutex_init is a replacement for @c pthread_mutex_init. - @param K The PSI_mutex_key for this instrumented mutex - @param M The mutex to initialize - @param A Mutex attributes -*/ - -#ifdef HAVE_PSI_MUTEX_INTERFACE - #ifdef SAFE_MUTEX - #define mysql_mutex_init(K, M, A) \ - inline_mysql_mutex_init(K, M, A, __FILE__, __LINE__) - #else - #define mysql_mutex_init(K, M, A) \ - inline_mysql_mutex_init(K, M, A) - #endif -#else - #ifdef SAFE_MUTEX - #define mysql_mutex_init(K, M, A) \ - inline_mysql_mutex_init(M, A, __FILE__, __LINE__) - #else - #define mysql_mutex_init(K, M, A) \ - inline_mysql_mutex_init(M, A) - #endif -#endif - -/** - @def mysql_mutex_destroy(M) - Instrumented mutex_destroy. - @c mysql_mutex_destroy is a drop-in replacement - for @c pthread_mutex_destroy. -*/ -#ifdef SAFE_MUTEX - #define mysql_mutex_destroy(M) \ - inline_mysql_mutex_destroy(M, __FILE__, __LINE__) -#else - #define mysql_mutex_destroy(M) \ - inline_mysql_mutex_destroy(M) -#endif - -/** - @def mysql_mutex_lock(M) - Instrumented mutex_lock. - @c mysql_mutex_lock is a drop-in replacement for @c pthread_mutex_lock. - @param M The mutex to lock -*/ - -#if defined(SAFE_MUTEX) || defined (HAVE_PSI_MUTEX_INTERFACE) - #define mysql_mutex_lock(M) \ - inline_mysql_mutex_lock(M, __FILE__, __LINE__) -#else - #define mysql_mutex_lock(M) \ - inline_mysql_mutex_lock(M) -#endif - -/** - @def mysql_mutex_trylock(M) - Instrumented mutex_lock. - @c mysql_mutex_trylock is a drop-in replacement - for @c my_mutex_trylock. -*/ - -#if defined(SAFE_MUTEX) || defined (HAVE_PSI_MUTEX_INTERFACE) - #define mysql_mutex_trylock(M) \ - inline_mysql_mutex_trylock(M, __FILE__, __LINE__) -#else - #define mysql_mutex_trylock(M) \ - inline_mysql_mutex_trylock(M) -#endif - -/** - @def mysql_mutex_unlock(M) - Instrumented mutex_unlock. - @c mysql_mutex_unlock is a drop-in replacement for @c pthread_mutex_unlock. -*/ -#ifdef SAFE_MUTEX - #define mysql_mutex_unlock(M) \ - inline_mysql_mutex_unlock(M, __FILE__, __LINE__) -#else - #define mysql_mutex_unlock(M) \ - inline_mysql_mutex_unlock(M) -#endif - -/** - @def mysql_rwlock_register(P1, P2, P3) - Rwlock registration. -*/ -#define mysql_rwlock_register(P1, P2, P3) \ - inline_mysql_rwlock_register(P1, P2, P3) - -/** - @def mysql_rwlock_init(K, RW) - Instrumented rwlock_init. - @c mysql_rwlock_init is a replacement for @c pthread_rwlock_init. - Note that pthread_rwlockattr_t is not supported in MySQL. - @param K The PSI_rwlock_key for this instrumented rwlock - @param RW The rwlock to initialize -*/ -#ifdef HAVE_PSI_RWLOCK_INTERFACE - #define mysql_rwlock_init(K, RW) inline_mysql_rwlock_init(K, RW) -#else - #define mysql_rwlock_init(K, RW) inline_mysql_rwlock_init(RW) -#endif - -/** - @def mysql_prlock_init(K, RW) - Instrumented rw_pr_init. - @c mysql_prlock_init is a replacement for @c rw_pr_init. - @param K The PSI_rwlock_key for this instrumented prlock - @param RW The prlock to initialize -*/ -#ifdef HAVE_PSI_RWLOCK_INTERFACE - #define mysql_prlock_init(K, RW) inline_mysql_prlock_init(K, RW) -#else - #define mysql_prlock_init(K, RW) inline_mysql_prlock_init(RW) -#endif - -/** - @def mysql_rwlock_destroy(RW) - Instrumented rwlock_destroy. - @c mysql_rwlock_destroy is a drop-in replacement - for @c pthread_rwlock_destroy. -*/ -#define mysql_rwlock_destroy(RW) inline_mysql_rwlock_destroy(RW) - -/** - @def mysql_prlock_destroy(RW) - Instrumented rw_pr_destroy. - @c mysql_prlock_destroy is a drop-in replacement - for @c rw_pr_destroy. -*/ -#define mysql_prlock_destroy(RW) inline_mysql_prlock_destroy(RW) - -/** - @def mysql_rwlock_rdlock(RW) - Instrumented rwlock_rdlock. - @c mysql_rwlock_rdlock is a drop-in replacement - for @c pthread_rwlock_rdlock. -*/ -#ifdef HAVE_PSI_RWLOCK_INTERFACE - #define mysql_rwlock_rdlock(RW) \ - inline_mysql_rwlock_rdlock(RW, __FILE__, __LINE__) -#else - #define mysql_rwlock_rdlock(RW) \ - inline_mysql_rwlock_rdlock(RW) -#endif - -/** - @def mysql_prlock_rdlock(RW) - Instrumented rw_pr_rdlock. - @c mysql_prlock_rdlock is a drop-in replacement - for @c rw_pr_rdlock. -*/ -#ifdef HAVE_PSI_RWLOCK_INTERFACE - #define mysql_prlock_rdlock(RW) \ - inline_mysql_prlock_rdlock(RW, __FILE__, __LINE__) -#else - #define mysql_prlock_rdlock(RW) \ - inline_mysql_prlock_rdlock(RW) -#endif - -/** - @def mysql_rwlock_wrlock(RW) - Instrumented rwlock_wrlock. - @c mysql_rwlock_wrlock is a drop-in replacement - for @c pthread_rwlock_wrlock. -*/ -#ifdef HAVE_PSI_RWLOCK_INTERFACE - #define mysql_rwlock_wrlock(RW) \ - inline_mysql_rwlock_wrlock(RW, __FILE__, __LINE__) -#else - #define mysql_rwlock_wrlock(RW) \ - inline_mysql_rwlock_wrlock(RW) -#endif - -/** - @def mysql_prlock_wrlock(RW) - Instrumented rw_pr_wrlock. - @c mysql_prlock_wrlock is a drop-in replacement - for @c rw_pr_wrlock. -*/ -#ifdef HAVE_PSI_RWLOCK_INTERFACE - #define mysql_prlock_wrlock(RW) \ - inline_mysql_prlock_wrlock(RW, __FILE__, __LINE__) -#else - #define mysql_prlock_wrlock(RW) \ - inline_mysql_prlock_wrlock(RW) -#endif - -/** - @def mysql_rwlock_tryrdlock(RW) - Instrumented rwlock_tryrdlock. - @c mysql_rwlock_tryrdlock is a drop-in replacement - for @c pthread_rwlock_tryrdlock. -*/ -#ifdef HAVE_PSI_RWLOCK_INTERFACE - #define mysql_rwlock_tryrdlock(RW) \ - inline_mysql_rwlock_tryrdlock(RW, __FILE__, __LINE__) -#else - #define mysql_rwlock_tryrdlock(RW) \ - inline_mysql_rwlock_tryrdlock(RW) -#endif - -/** - @def mysql_rwlock_trywrlock(RW) - Instrumented rwlock_trywrlock. - @c mysql_rwlock_trywrlock is a drop-in replacement - for @c pthread_rwlock_trywrlock. -*/ -#ifdef HAVE_PSI_RWLOCK_INTERFACE - #define mysql_rwlock_trywrlock(RW) \ - inline_mysql_rwlock_trywrlock(RW, __FILE__, __LINE__) -#else - #define mysql_rwlock_trywrlock(RW) \ - inline_mysql_rwlock_trywrlock(RW) -#endif - -/** - @def mysql_rwlock_unlock(RW) - Instrumented rwlock_unlock. - @c mysql_rwlock_unlock is a drop-in replacement - for @c pthread_rwlock_unlock. -*/ -#define mysql_rwlock_unlock(RW) inline_mysql_rwlock_unlock(RW) - -/** - @def mysql_prlock_unlock(RW) - Instrumented rw_pr_unlock. - @c mysql_prlock_unlock is a drop-in replacement - for @c rw_pr_unlock. -*/ -#define mysql_prlock_unlock(RW) inline_mysql_prlock_unlock(RW) - -/** - @def mysql_cond_register(P1, P2, P3) - Cond registration. -*/ -#define mysql_cond_register(P1, P2, P3) \ - inline_mysql_cond_register(P1, P2, P3) - -/** - @def mysql_cond_init(K, C) - Instrumented cond_init. - @c mysql_cond_init is a replacement for @c pthread_cond_init. - Note that pthread_condattr_t is not supported in MySQL. - @param C The cond to initialize - @param K The PSI_cond_key for this instrumented cond - -*/ -#ifdef HAVE_PSI_COND_INTERFACE - #define mysql_cond_init(K, C) inline_mysql_cond_init(K, C) -#else - #define mysql_cond_init(K, C) inline_mysql_cond_init(C) -#endif - -/** - @def mysql_cond_destroy(C) - Instrumented cond_destroy. - @c mysql_cond_destroy is a drop-in replacement for @c pthread_cond_destroy. -*/ -#define mysql_cond_destroy(C) inline_mysql_cond_destroy(C) - -/** - @def mysql_cond_wait(C) - Instrumented cond_wait. - @c mysql_cond_wait is a drop-in replacement for @c native_cond_wait. -*/ -#if defined(SAFE_MUTEX) || defined(HAVE_PSI_COND_INTERFACE) - #define mysql_cond_wait(C, M) \ - inline_mysql_cond_wait(C, M, __FILE__, __LINE__) -#else - #define mysql_cond_wait(C, M) \ - inline_mysql_cond_wait(C, M) -#endif - -/** - @def mysql_cond_timedwait(C, M, W) - Instrumented cond_timedwait. - @c mysql_cond_timedwait is a drop-in replacement - for @c native_cond_timedwait. -*/ -#if defined(SAFE_MUTEX) || defined(HAVE_PSI_COND_INTERFACE) - #define mysql_cond_timedwait(C, M, W) \ - inline_mysql_cond_timedwait(C, M, W, __FILE__, __LINE__) -#else - #define mysql_cond_timedwait(C, M, W) \ - inline_mysql_cond_timedwait(C, M, W) -#endif - -/** - @def mysql_cond_signal(C) - Instrumented cond_signal. - @c mysql_cond_signal is a drop-in replacement for @c pthread_cond_signal. -*/ -#define mysql_cond_signal(C) inline_mysql_cond_signal(C) - -/** - @def mysql_cond_broadcast(C) - Instrumented cond_broadcast. - @c mysql_cond_broadcast is a drop-in replacement - for @c pthread_cond_broadcast. -*/ -#define mysql_cond_broadcast(C) inline_mysql_cond_broadcast(C) - -/** - @def mysql_thread_register(P1, P2, P3) - Thread registration. -*/ -#define mysql_thread_register(P1, P2, P3) \ - inline_mysql_thread_register(P1, P2, P3) - -/** - @def mysql_thread_create(K, P1, P2, P3, P4) - Instrumented my_thread_create. - This function creates both the thread instrumentation and a thread. - @c mysql_thread_create is a replacement for @c my_thread_create. - The parameter P4 (or, if it is NULL, P1) will be used as the - instrumented thread "indentity". - Providing a P1 / P4 parameter with a different value for each call - will on average improve performances, since this thread identity value - is used internally to randomize access to data and prevent contention. - This is optional, and the improvement is not guaranteed, only statistical. - @param K The PSI_thread_key for this instrumented thread - @param P1 my_thread_create parameter 1 - @param P2 my_thread_create parameter 2 - @param P3 my_thread_create parameter 3 - @param P4 my_thread_create parameter 4 -*/ -#ifdef HAVE_PSI_THREAD_INTERFACE - #define mysql_thread_create(K, P1, P2, P3, P4) \ - inline_mysql_thread_create(K, P1, P2, P3, P4) -#else - #define mysql_thread_create(K, P1, P2, P3, P4) \ - my_thread_create(P1, P2, P3, P4) -#endif - -/** - @def mysql_thread_set_psi_id(I) - Set the thread identifier for the instrumentation. - @param I The thread identifier -*/ -#ifdef HAVE_PSI_THREAD_INTERFACE - #define mysql_thread_set_psi_id(I) inline_mysql_thread_set_psi_id(I) -#else - #define mysql_thread_set_psi_id(I) do {} while (0) -#endif - -/** - @def mysql_thread_set_psi_THD(T) - Set the thread sql session for the instrumentation. - @param I The thread identifier -*/ -#ifdef HAVE_PSI_THREAD_INTERFACE - #define mysql_thread_set_psi_THD(T) inline_mysql_thread_set_psi_THD(T) -#else - #define mysql_thread_set_psi_THD(T) do {} while (0) -#endif - -static inline void inline_mysql_mutex_register( -#ifdef HAVE_PSI_MUTEX_INTERFACE - const char *category, - PSI_mutex_info *info, - int count -#else - const char *category MY_ATTRIBUTE ((unused)), - void *info MY_ATTRIBUTE ((unused)), - int count MY_ATTRIBUTE ((unused)) -#endif -) -{ -#ifdef HAVE_PSI_MUTEX_INTERFACE - PSI_MUTEX_CALL(register_mutex)(category, info, count); -#endif -} - -static inline int inline_mysql_mutex_init( -#ifdef HAVE_PSI_MUTEX_INTERFACE - PSI_mutex_key key, -#endif - mysql_mutex_t *that, - const native_mutexattr_t *attr -#ifdef SAFE_MUTEX - , const char *src_file, uint src_line -#endif - ) -{ -#ifdef HAVE_PSI_MUTEX_INTERFACE - that->m_psi= PSI_MUTEX_CALL(init_mutex)(key, &that->m_mutex); -#else - that->m_psi= NULL; -#endif - return my_mutex_init(&that->m_mutex, attr -#ifdef SAFE_MUTEX - , src_file, src_line -#endif - ); -} - -static inline int inline_mysql_mutex_destroy( - mysql_mutex_t *that -#ifdef SAFE_MUTEX - , const char *src_file, uint src_line -#endif - ) -{ -#ifdef HAVE_PSI_MUTEX_INTERFACE - if (that->m_psi != NULL) - { - PSI_MUTEX_CALL(destroy_mutex)(that->m_psi); - that->m_psi= NULL; - } -#endif - return my_mutex_destroy(&that->m_mutex -#ifdef SAFE_MUTEX - , src_file, src_line -#endif - ); -} - -static inline int inline_mysql_mutex_lock( - mysql_mutex_t *that -#if defined(SAFE_MUTEX) || defined (HAVE_PSI_MUTEX_INTERFACE) - , const char *src_file, uint src_line -#endif - ) -{ - int result; - -#ifdef HAVE_PSI_MUTEX_INTERFACE - if (that->m_psi != NULL) - { - /* Instrumentation start */ - PSI_mutex_locker *locker; - PSI_mutex_locker_state state; - locker= PSI_MUTEX_CALL(start_mutex_wait)(&state, that->m_psi, - PSI_MUTEX_LOCK, src_file, src_line); - - /* Instrumented code */ - result= my_mutex_lock(&that->m_mutex -#ifdef SAFE_MUTEX - , src_file, src_line -#endif - ); - - /* Instrumentation end */ - if (locker != NULL) - PSI_MUTEX_CALL(end_mutex_wait)(locker, result); - - return result; - } -#endif - - /* Non instrumented code */ - result= my_mutex_lock(&that->m_mutex -#ifdef SAFE_MUTEX - , src_file, src_line -#endif - ); - - return result; -} - -static inline int inline_mysql_mutex_trylock( - mysql_mutex_t *that -#if defined(SAFE_MUTEX) || defined (HAVE_PSI_MUTEX_INTERFACE) - , const char *src_file, uint src_line -#endif - ) -{ - int result; - -#ifdef HAVE_PSI_MUTEX_INTERFACE - if (that->m_psi != NULL) - { - /* Instrumentation start */ - PSI_mutex_locker *locker; - PSI_mutex_locker_state state; - locker= PSI_MUTEX_CALL(start_mutex_wait)(&state, that->m_psi, - PSI_MUTEX_TRYLOCK, src_file, src_line); - - /* Instrumented code */ - result= my_mutex_trylock(&that->m_mutex -#ifdef SAFE_MUTEX - , src_file, src_line -#endif - ); - - /* Instrumentation end */ - if (locker != NULL) - PSI_MUTEX_CALL(end_mutex_wait)(locker, result); - - return result; - } -#endif - - /* Non instrumented code */ - result= my_mutex_trylock(&that->m_mutex -#ifdef SAFE_MUTEX - , src_file, src_line -#endif - ); - - return result; -} - -static inline int inline_mysql_mutex_unlock( - mysql_mutex_t *that -#ifdef SAFE_MUTEX - , const char *src_file, uint src_line -#endif - ) -{ - int result; - -#ifdef HAVE_PSI_MUTEX_INTERFACE - if (that->m_psi != NULL) - PSI_MUTEX_CALL(unlock_mutex)(that->m_psi); -#endif - - result= my_mutex_unlock(&that->m_mutex -#ifdef SAFE_MUTEX - , src_file, src_line -#endif - ); - - return result; -} - -static inline void inline_mysql_rwlock_register( -#ifdef HAVE_PSI_RWLOCK_INTERFACE - const char *category, - PSI_rwlock_info *info, - int count -#else - const char *category MY_ATTRIBUTE ((unused)), - void *info MY_ATTRIBUTE ((unused)), - int count MY_ATTRIBUTE ((unused)) -#endif -) -{ -#ifdef HAVE_PSI_RWLOCK_INTERFACE - PSI_RWLOCK_CALL(register_rwlock)(category, info, count); -#endif -} - -static inline int inline_mysql_rwlock_init( -#ifdef HAVE_PSI_RWLOCK_INTERFACE - PSI_rwlock_key key, -#endif - mysql_rwlock_t *that) -{ -#ifdef HAVE_PSI_RWLOCK_INTERFACE - that->m_psi= PSI_RWLOCK_CALL(init_rwlock)(key, &that->m_rwlock); -#else - that->m_psi= NULL; -#endif - return native_rw_init(&that->m_rwlock); -} - -#ifndef DISABLE_MYSQL_PRLOCK_H -static inline int inline_mysql_prlock_init( -#ifdef HAVE_PSI_RWLOCK_INTERFACE - PSI_rwlock_key key, -#endif - mysql_prlock_t *that) -{ -#ifdef HAVE_PSI_RWLOCK_INTERFACE - that->m_psi= PSI_RWLOCK_CALL(init_rwlock)(key, &that->m_prlock); -#else - that->m_psi= NULL; -#endif - return rw_pr_init(&that->m_prlock); -} -#endif - -static inline int inline_mysql_rwlock_destroy( - mysql_rwlock_t *that) -{ -#ifdef HAVE_PSI_RWLOCK_INTERFACE - if (that->m_psi != NULL) - { - PSI_RWLOCK_CALL(destroy_rwlock)(that->m_psi); - that->m_psi= NULL; - } -#endif - return native_rw_destroy(&that->m_rwlock); -} - -#ifndef DISABLE_MYSQL_PRLOCK_H -static inline int inline_mysql_prlock_destroy( - mysql_prlock_t *that) -{ -#ifdef HAVE_PSI_RWLOCK_INTERFACE - if (that->m_psi != NULL) - { - PSI_RWLOCK_CALL(destroy_rwlock)(that->m_psi); - that->m_psi= NULL; - } -#endif - return rw_pr_destroy(&that->m_prlock); -} -#endif - -static inline int inline_mysql_rwlock_rdlock( - mysql_rwlock_t *that -#ifdef HAVE_PSI_RWLOCK_INTERFACE - , const char *src_file, uint src_line -#endif - ) -{ - int result; - -#ifdef HAVE_PSI_RWLOCK_INTERFACE - if (that->m_psi != NULL) - { - /* Instrumentation start */ - PSI_rwlock_locker *locker; - PSI_rwlock_locker_state state; - locker= PSI_RWLOCK_CALL(start_rwlock_rdwait)(&state, that->m_psi, - PSI_RWLOCK_READLOCK, src_file, src_line); - - /* Instrumented code */ - result= native_rw_rdlock(&that->m_rwlock); - - /* Instrumentation end */ - if (locker != NULL) - PSI_RWLOCK_CALL(end_rwlock_rdwait)(locker, result); - - return result; - } -#endif - - /* Non instrumented code */ - result= native_rw_rdlock(&that->m_rwlock); - - return result; -} - -#ifndef DISABLE_MYSQL_PRLOCK_H -static inline int inline_mysql_prlock_rdlock( - mysql_prlock_t *that -#ifdef HAVE_PSI_RWLOCK_INTERFACE - , const char *src_file, uint src_line -#endif - ) -{ - int result; - -#ifdef HAVE_PSI_RWLOCK_INTERFACE - if (that->m_psi != NULL) - { - /* Instrumentation start */ - PSI_rwlock_locker *locker; - PSI_rwlock_locker_state state; - locker= PSI_RWLOCK_CALL(start_rwlock_rdwait)(&state, that->m_psi, - PSI_RWLOCK_READLOCK, src_file, src_line); - - /* Instrumented code */ - result= rw_pr_rdlock(&that->m_prlock); - - /* Instrumentation end */ - if (locker != NULL) - PSI_RWLOCK_CALL(end_rwlock_rdwait)(locker, result); - - return result; - } -#endif - - /* Non instrumented code */ - result= rw_pr_rdlock(&that->m_prlock); - - return result; -} -#endif - -static inline int inline_mysql_rwlock_wrlock( - mysql_rwlock_t *that -#ifdef HAVE_PSI_RWLOCK_INTERFACE - , const char *src_file, uint src_line -#endif - ) -{ - int result; - -#ifdef HAVE_PSI_RWLOCK_INTERFACE - if (that->m_psi != NULL) - { - /* Instrumentation start */ - PSI_rwlock_locker *locker; - PSI_rwlock_locker_state state; - locker= PSI_RWLOCK_CALL(start_rwlock_wrwait)(&state, that->m_psi, - PSI_RWLOCK_WRITELOCK, src_file, src_line); - - /* Instrumented code */ - result= native_rw_wrlock(&that->m_rwlock); - - /* Instrumentation end */ - if (locker != NULL) - PSI_RWLOCK_CALL(end_rwlock_wrwait)(locker, result); - - return result; - } -#endif - - /* Non instrumented code */ - result= native_rw_wrlock(&that->m_rwlock); - - return result; -} - -#ifndef DISABLE_MYSQL_PRLOCK_H -static inline int inline_mysql_prlock_wrlock( - mysql_prlock_t *that -#ifdef HAVE_PSI_RWLOCK_INTERFACE - , const char *src_file, uint src_line -#endif - ) -{ - int result; - -#ifdef HAVE_PSI_RWLOCK_INTERFACE - if (that->m_psi != NULL) - { - /* Instrumentation start */ - PSI_rwlock_locker *locker; - PSI_rwlock_locker_state state; - locker= PSI_RWLOCK_CALL(start_rwlock_wrwait)(&state, that->m_psi, - PSI_RWLOCK_WRITELOCK, src_file, src_line); - - /* Instrumented code */ - result= rw_pr_wrlock(&that->m_prlock); - - /* Instrumentation end */ - if (locker != NULL) - PSI_RWLOCK_CALL(end_rwlock_wrwait)(locker, result); - - return result; - } -#endif - - /* Non instrumented code */ - result= rw_pr_wrlock(&that->m_prlock); - - return result; -} -#endif - -static inline int inline_mysql_rwlock_tryrdlock( - mysql_rwlock_t *that -#ifdef HAVE_PSI_RWLOCK_INTERFACE - , const char *src_file, uint src_line -#endif - ) -{ - int result; - -#ifdef HAVE_PSI_RWLOCK_INTERFACE - if (that->m_psi != NULL) - { - /* Instrumentation start */ - PSI_rwlock_locker *locker; - PSI_rwlock_locker_state state; - locker= PSI_RWLOCK_CALL(start_rwlock_rdwait)(&state, that->m_psi, - PSI_RWLOCK_TRYREADLOCK, src_file, src_line); - - /* Instrumented code */ - result= native_rw_tryrdlock(&that->m_rwlock); - - /* Instrumentation end */ - if (locker != NULL) - PSI_RWLOCK_CALL(end_rwlock_rdwait)(locker, result); - - return result; - } -#endif - - /* Non instrumented code */ - result= native_rw_tryrdlock(&that->m_rwlock); - - return result; -} - -static inline int inline_mysql_rwlock_trywrlock( - mysql_rwlock_t *that -#ifdef HAVE_PSI_RWLOCK_INTERFACE - , const char *src_file, uint src_line -#endif - ) -{ - int result; - -#ifdef HAVE_PSI_RWLOCK_INTERFACE - if (that->m_psi != NULL) - { - /* Instrumentation start */ - PSI_rwlock_locker *locker; - PSI_rwlock_locker_state state; - locker= PSI_RWLOCK_CALL(start_rwlock_wrwait)(&state, that->m_psi, - PSI_RWLOCK_TRYWRITELOCK, src_file, src_line); - - /* Instrumented code */ - result= native_rw_trywrlock(&that->m_rwlock); - - /* Instrumentation end */ - if (locker != NULL) - PSI_RWLOCK_CALL(end_rwlock_wrwait)(locker, result); - - return result; - } -#endif - - /* Non instrumented code */ - result= native_rw_trywrlock(&that->m_rwlock); - - return result; -} - -static inline int inline_mysql_rwlock_unlock( - mysql_rwlock_t *that) -{ - int result; -#ifdef HAVE_PSI_RWLOCK_INTERFACE - if (that->m_psi != NULL) - PSI_RWLOCK_CALL(unlock_rwlock)(that->m_psi); -#endif - result= native_rw_unlock(&that->m_rwlock); - return result; -} - -#ifndef DISABLE_MYSQL_PRLOCK_H -static inline int inline_mysql_prlock_unlock( - mysql_prlock_t *that) -{ - int result; -#ifdef HAVE_PSI_RWLOCK_INTERFACE - if (that->m_psi != NULL) - PSI_RWLOCK_CALL(unlock_rwlock)(that->m_psi); -#endif - result= rw_pr_unlock(&that->m_prlock); - return result; -} -#endif - -static inline void inline_mysql_cond_register( -#ifdef HAVE_PSI_COND_INTERFACE - const char *category, - PSI_cond_info *info, - int count -#else - const char *category MY_ATTRIBUTE ((unused)), - void *info MY_ATTRIBUTE ((unused)), - int count MY_ATTRIBUTE ((unused)) -#endif -) -{ -#ifdef HAVE_PSI_COND_INTERFACE - PSI_COND_CALL(register_cond)(category, info, count); -#endif -} - -static inline int inline_mysql_cond_init( -#ifdef HAVE_PSI_COND_INTERFACE - PSI_cond_key key, -#endif - mysql_cond_t *that) -{ -#ifdef HAVE_PSI_COND_INTERFACE - that->m_psi= PSI_COND_CALL(init_cond)(key, &that->m_cond); -#else - that->m_psi= NULL; -#endif - return native_cond_init(&that->m_cond); -} - -static inline int inline_mysql_cond_destroy( - mysql_cond_t *that) -{ -#ifdef HAVE_PSI_COND_INTERFACE - if (that->m_psi != NULL) - { - PSI_COND_CALL(destroy_cond)(that->m_psi); - that->m_psi= NULL; - } -#endif - return native_cond_destroy(&that->m_cond); -} - -static inline int inline_mysql_cond_wait( - mysql_cond_t *that, - mysql_mutex_t *mutex -#if defined(SAFE_MUTEX) || defined(HAVE_PSI_COND_INTERFACE) - , const char *src_file, uint src_line -#endif - ) -{ - int result; - -#ifdef HAVE_PSI_COND_INTERFACE - if (that->m_psi != NULL) - { - /* Instrumentation start */ - PSI_cond_locker *locker; - PSI_cond_locker_state state; - locker= PSI_COND_CALL(start_cond_wait)(&state, that->m_psi, mutex->m_psi, - PSI_COND_WAIT, src_file, src_line); - - /* Instrumented code */ - result= my_cond_wait(&that->m_cond, &mutex->m_mutex -#ifdef SAFE_MUTEX - , src_file, src_line -#endif - ); - - /* Instrumentation end */ - if (locker != NULL) - PSI_COND_CALL(end_cond_wait)(locker, result); - - return result; - } -#endif - - /* Non instrumented code */ - result= my_cond_wait(&that->m_cond, &mutex->m_mutex -#ifdef SAFE_MUTEX - , src_file, src_line -#endif - ); - - return result; -} - -static inline int inline_mysql_cond_timedwait( - mysql_cond_t *that, - mysql_mutex_t *mutex, - const struct timespec *abstime -#if defined(SAFE_MUTEX) || defined(HAVE_PSI_COND_INTERFACE) - , const char *src_file, uint src_line -#endif - ) -{ - int result; - -#ifdef HAVE_PSI_COND_INTERFACE - if (that->m_psi != NULL) - { - /* Instrumentation start */ - PSI_cond_locker *locker; - PSI_cond_locker_state state; - locker= PSI_COND_CALL(start_cond_wait)(&state, that->m_psi, mutex->m_psi, - PSI_COND_TIMEDWAIT, src_file, src_line); - - /* Instrumented code */ - result= my_cond_timedwait(&that->m_cond, &mutex->m_mutex, abstime -#ifdef SAFE_MUTEX - , src_file, src_line -#endif - ); - - /* Instrumentation end */ - if (locker != NULL) - PSI_COND_CALL(end_cond_wait)(locker, result); - - return result; - } -#endif - - /* Non instrumented code */ - result= my_cond_timedwait(&that->m_cond, &mutex->m_mutex, abstime -#ifdef SAFE_MUTEX - , src_file, src_line -#endif - ); - - return result; -} - -static inline int inline_mysql_cond_signal( - mysql_cond_t *that) -{ - int result; -#ifdef HAVE_PSI_COND_INTERFACE - if (that->m_psi != NULL) - PSI_COND_CALL(signal_cond)(that->m_psi); -#endif - result= native_cond_signal(&that->m_cond); - return result; -} - -static inline int inline_mysql_cond_broadcast( - mysql_cond_t *that) -{ - int result; -#ifdef HAVE_PSI_COND_INTERFACE - if (that->m_psi != NULL) - PSI_COND_CALL(broadcast_cond)(that->m_psi); -#endif - result= native_cond_broadcast(&that->m_cond); - return result; -} - -static inline void inline_mysql_thread_register( -#ifdef HAVE_PSI_THREAD_INTERFACE - const char *category, - PSI_thread_info *info, - int count -#else - const char *category MY_ATTRIBUTE ((unused)), - void *info MY_ATTRIBUTE ((unused)), - int count MY_ATTRIBUTE ((unused)) -#endif -) -{ -#ifdef HAVE_PSI_THREAD_INTERFACE - PSI_THREAD_CALL(register_thread)(category, info, count); -#endif -} - -#ifdef HAVE_PSI_THREAD_INTERFACE -static inline int inline_mysql_thread_create( - PSI_thread_key key, - my_thread_handle *thread, const my_thread_attr_t *attr, - my_start_routine start_routine, void *arg) -{ - int result; - result= PSI_THREAD_CALL(spawn_thread)(key, thread, attr, start_routine, arg); - return result; -} - -static inline void inline_mysql_thread_set_psi_id(my_thread_id id) -{ - struct PSI_thread *psi= PSI_THREAD_CALL(get_thread)(); - PSI_THREAD_CALL(set_thread_id)(psi, id); -} - -#ifdef __cplusplus -class THD; -static inline void inline_mysql_thread_set_psi_THD(THD *thd) -{ - struct PSI_thread *psi= PSI_THREAD_CALL(get_thread)(); - PSI_THREAD_CALL(set_thread_THD)(psi, thd); -} -#endif /* __cplusplus */ - -#endif - -#endif /* DISABLE_MYSQL_THREAD_H */ - -/** @} (end of group Thread_instrumentation) */ - -#endif - diff --git a/vendor/mysql/include/mysql/psi/mysql_transaction.h b/vendor/mysql/include/mysql/psi/mysql_transaction.h deleted file mode 100644 index c80abf4622..0000000000 --- a/vendor/mysql/include/mysql/psi/mysql_transaction.h +++ /dev/null @@ -1,213 +0,0 @@ -/* Copyright (c) 2013, Oracle and/or its affiliates. All rights reserved. - - This program is free software; you can redistribute it and/or modify - it under the terms of the GNU General Public License as published by - the Free Software Foundation; version 2 of the License. - - This program is distributed in the hope that it will be useful, - but WITHOUT ANY WARRANTY; without even the implied warranty of - MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - GNU General Public License for more details. - - You should have received a copy of the GNU General Public License - along with this program; if not, write to the Free Software - Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA */ - -#ifndef MYSQL_TRANSACTION_H -#define MYSQL_TRANSACTION_H - -/** - @file mysql/psi/mysql_transaction.h - Instrumentation helpers for transactions. -*/ - -#include "mysql/psi/psi.h" - -#ifndef PSI_TRANSACTION_CALL -#define PSI_TRANSACTION_CALL(M) PSI_DYNAMIC_CALL(M) -#endif - -/** - @defgroup Transaction_instrumentation Transaction Instrumentation - @ingroup Instrumentation_interface - @{ -*/ - -#ifdef HAVE_PSI_TRANSACTION_INTERFACE - #define MYSQL_START_TRANSACTION(STATE, XID, TRXID, ISO, RO, AC) \ - inline_mysql_start_transaction(STATE, XID, TRXID, ISO, RO, AC, __FILE__, __LINE__) -#else - #define MYSQL_START_TRANSACTION(STATE, XID, TRXID, ISO, RO, AC) \ - do {} while (0) -#endif - -#ifdef HAVE_PSI_TRANSACTION_INTERFACE - #define MYSQL_SET_TRANSACTION_GTID(LOCKER, P1, P2) \ - inline_mysql_set_transaction_gtid(LOCKER, P1, P2) -#else - #define MYSQL_SET_TRANSACTION_GTID(LOCKER, P1, P2) \ - do {} while (0) -#endif - -#ifdef HAVE_PSI_TRANSACTION_INTERFACE - #define MYSQL_SET_TRANSACTION_XID(LOCKER, P1, P2) \ - inline_mysql_set_transaction_xid(LOCKER, P1, P2) -#else - #define MYSQL_SET_TRANSACTION_XID(LOCKER, P1, P2) \ - do {} while (0) -#endif - -#ifdef HAVE_PSI_TRANSACTION_INTERFACE - #define MYSQL_SET_TRANSACTION_XA_STATE(LOCKER, P1) \ - inline_mysql_set_transaction_xa_state(LOCKER, P1) -#else - #define MYSQL_SET_TRANSACTION_XA_STATE(LOCKER, P1) \ - do {} while (0) -#endif - -#ifdef HAVE_PSI_TRANSACTION_INTERFACE - #define MYSQL_SET_TRANSACTION_TRXID(LOCKER, P1) \ - inline_mysql_set_transaction_trxid(LOCKER, P1) -#else - #define MYSQL_SET_TRANSACTION_TRXID(LOCKER, P1) \ - do {} while (0) -#endif - -#ifdef HAVE_PSI_TRANSACTION_INTERFACE - #define MYSQL_INC_TRANSACTION_SAVEPOINTS(LOCKER, P1) \ - inline_mysql_inc_transaction_savepoints(LOCKER, P1) -#else - #define MYSQL_INC_TRANSACTION_SAVEPOINTS(LOCKER, P1) \ - do {} while (0) -#endif - -#ifdef HAVE_PSI_TRANSACTION_INTERFACE - #define MYSQL_INC_TRANSACTION_ROLLBACK_TO_SAVEPOINT(LOCKER, P1) \ - inline_mysql_inc_transaction_rollback_to_savepoint(LOCKER, P1) -#else - #define MYSQL_INC_TRANSACTION_ROLLBACK_TO_SAVEPOINT(LOCKER, P1) \ - do {} while (0) -#endif - -#ifdef HAVE_PSI_TRANSACTION_INTERFACE - #define MYSQL_INC_TRANSACTION_RELEASE_SAVEPOINT(LOCKER, P1) \ - inline_mysql_inc_transaction_release_savepoint(LOCKER, P1) -#else - #define MYSQL_INC_TRANSACTION_RELEASE_SAVEPOINT(LOCKER, P1) \ - do {} while (0) -#endif - -#ifdef HAVE_PSI_TRANSACTION_INTERFACE - #define MYSQL_ROLLBACK_TRANSACTION(LOCKER) \ - inline_mysql_rollback_transaction(LOCKER) -#else - #define MYSQL_ROLLBACK_TRANSACTION(LOCKER) \ - NULL -#endif - -#ifdef HAVE_PSI_TRANSACTION_INTERFACE - #define MYSQL_COMMIT_TRANSACTION(LOCKER) \ - inline_mysql_commit_transaction(LOCKER) -#else - #define MYSQL_COMMIT_TRANSACTION(LOCKER) \ - NULL -#endif - -#ifdef HAVE_PSI_TRANSACTION_INTERFACE -static inline struct PSI_transaction_locker * -inline_mysql_start_transaction(PSI_transaction_locker_state *state, - const void *xid, - const ulonglong *trxid, - int isolation_level, - my_bool read_only, - my_bool autocommit, - const char *src_file, int src_line) -{ - PSI_transaction_locker *locker; - locker= PSI_TRANSACTION_CALL(get_thread_transaction_locker)(state, - xid, trxid, - isolation_level, - read_only, - autocommit); - if (likely(locker != NULL)) - PSI_TRANSACTION_CALL(start_transaction)(locker, src_file, src_line); - return locker; -} - -static inline void -inline_mysql_set_transaction_gtid(PSI_transaction_locker *locker, - const void *sid, - const void *gtid_spec) -{ - if (likely(locker != NULL)) - PSI_TRANSACTION_CALL(set_transaction_gtid)(locker, sid, gtid_spec); -} - -static inline void -inline_mysql_set_transaction_xid(PSI_transaction_locker *locker, - const void *xid, - int xa_state) -{ - if (likely(locker != NULL)) - PSI_TRANSACTION_CALL(set_transaction_xid)(locker, xid, xa_state); -} - -static inline void -inline_mysql_set_transaction_xa_state(PSI_transaction_locker *locker, - int xa_state) -{ - if (likely(locker != NULL)) - PSI_TRANSACTION_CALL(set_transaction_xa_state)(locker, xa_state); -} - -static inline void -inline_mysql_set_transaction_trxid(PSI_transaction_locker *locker, - const ulonglong *trxid) -{ - if (likely(locker != NULL)) - PSI_TRANSACTION_CALL(set_transaction_trxid)(locker, trxid); -} - -static inline void -inline_mysql_inc_transaction_savepoints(PSI_transaction_locker *locker, - ulong count) -{ - if (likely(locker != NULL)) - PSI_TRANSACTION_CALL(inc_transaction_savepoints)(locker, count); -} - -static inline void -inline_mysql_inc_transaction_rollback_to_savepoint(PSI_transaction_locker *locker, - ulong count) -{ - if (likely(locker != NULL)) - PSI_TRANSACTION_CALL(inc_transaction_rollback_to_savepoint)(locker, count); -} - -static inline void -inline_mysql_inc_transaction_release_savepoint(PSI_transaction_locker *locker, - ulong count) -{ - if (likely(locker != NULL)) - PSI_TRANSACTION_CALL(inc_transaction_release_savepoint)(locker, count); -} - -static inline void -inline_mysql_rollback_transaction(struct PSI_transaction_locker *locker) -{ - if (likely(locker != NULL)) - PSI_TRANSACTION_CALL(end_transaction)(locker, false); -} - -static inline void -inline_mysql_commit_transaction(struct PSI_transaction_locker *locker) -{ - if (likely(locker != NULL)) - PSI_TRANSACTION_CALL(end_transaction)(locker, true); -} -#endif - -/** @} (end of group Transaction_instrumentation) */ - -#endif - diff --git a/vendor/mysql/include/mysql/psi/psi.h b/vendor/mysql/include/mysql/psi/psi.h deleted file mode 100644 index 9fb62868e3..0000000000 --- a/vendor/mysql/include/mysql/psi/psi.h +++ /dev/null @@ -1,2980 +0,0 @@ -/* Copyright (c) 2008, 2015, Oracle and/or its affiliates. All rights reserved. - - This program is free software; you can redistribute it and/or modify - it under the terms of the GNU General Public License as published by - the Free Software Foundation; version 2 of the License. - - This program is distributed in the hope that it will be useful, - but WITHOUT ANY WARRANTY; without even the implied warranty of - MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - GNU General Public License for more details. - - You should have received a copy of the GNU General Public License - along with this program; if not, write to the Free Software Foundation, - 51 Franklin Street, Suite 500, Boston, MA 02110-1335 USA */ - -#ifndef MYSQL_PERFORMANCE_SCHEMA_INTERFACE_H -#define MYSQL_PERFORMANCE_SCHEMA_INTERFACE_H - -#ifdef EMBEDDED_LIBRARY -#define DISABLE_ALL_PSI -#endif /* EMBEDDED_LIBRARY */ - -#ifndef MY_GLOBAL_INCLUDED -/* - Make sure a .c or .cc file contains an include to my_global.h first. - When this include is missing, all the #ifdef HAVE_XXX have no effect, - and the resulting binary won't build, or won't link, - or will crash at runtime - since various structures will have different binary definitions. -*/ -#error "You must include my_global.h in the code for the build to be correct." -#endif - -#include "psi_base.h" -#include "psi_memory.h" - -/* - MAINTAINER: - The following pattern: - typedef struct XYZ XYZ; - is not needed in C++, but required for C. -*/ - -C_MODE_START - -/** @sa MDL_key. */ -struct MDL_key; -typedef struct MDL_key MDL_key; - -/** @sa enum_mdl_type. */ -typedef int opaque_mdl_type; - -/** @sa enum_mdl_duration. */ -typedef int opaque_mdl_duration; - -/** @sa MDL_wait::enum_wait_status. */ -typedef int opaque_mdl_status; - -/** @sa enum_vio_type. */ -typedef int opaque_vio_type; - -struct TABLE_SHARE; - -struct sql_digest_storage; - -#ifdef __cplusplus - class THD; -#else - /* - Phony declaration when compiling C code. - This is ok, because the C code will never have a THD anyway. - */ - struct opaque_THD - { - int dummy; - }; - typedef struct opaque_THD THD; -#endif - -/** - @file mysql/psi/psi.h - Performance schema instrumentation interface. - - @defgroup Instrumentation_interface Instrumentation Interface - @ingroup Performance_schema - @{ -*/ - -/** - Interface for an instrumented mutex. - This is an opaque structure. -*/ -struct PSI_mutex; -typedef struct PSI_mutex PSI_mutex; - -/** - Interface for an instrumented rwlock. - This is an opaque structure. -*/ -struct PSI_rwlock; -typedef struct PSI_rwlock PSI_rwlock; - -/** - Interface for an instrumented condition. - This is an opaque structure. -*/ -struct PSI_cond; -typedef struct PSI_cond PSI_cond; - -/** - Interface for an instrumented table share. - This is an opaque structure. -*/ -struct PSI_table_share; -typedef struct PSI_table_share PSI_table_share; - -/** - Interface for an instrumented table handle. - This is an opaque structure. -*/ -struct PSI_table; -typedef struct PSI_table PSI_table; - -/** - Interface for an instrumented thread. - This is an opaque structure. -*/ -struct PSI_thread; -typedef struct PSI_thread PSI_thread; - -/** - Interface for an instrumented file handle. - This is an opaque structure. -*/ -struct PSI_file; -typedef struct PSI_file PSI_file; - -/** - Interface for an instrumented socket descriptor. - This is an opaque structure. -*/ -struct PSI_socket; -typedef struct PSI_socket PSI_socket; - -/** - Interface for an instrumented prepared statement. - This is an opaque structure. -*/ -struct PSI_prepared_stmt; -typedef struct PSI_prepared_stmt PSI_prepared_stmt; - -/** - Interface for an instrumented table operation. - This is an opaque structure. -*/ -struct PSI_table_locker; -typedef struct PSI_table_locker PSI_table_locker; - -/** - Interface for an instrumented statement. - This is an opaque structure. -*/ -struct PSI_statement_locker; -typedef struct PSI_statement_locker PSI_statement_locker; - -/** - Interface for an instrumented transaction. - This is an opaque structure. -*/ -struct PSI_transaction_locker; -typedef struct PSI_transaction_locker PSI_transaction_locker; - -/** - Interface for an instrumented idle operation. - This is an opaque structure. -*/ -struct PSI_idle_locker; -typedef struct PSI_idle_locker PSI_idle_locker; - -/** - Interface for an instrumented statement digest operation. - This is an opaque structure. -*/ -struct PSI_digest_locker; -typedef struct PSI_digest_locker PSI_digest_locker; - -/** - Interface for an instrumented stored procedure share. - This is an opaque structure. -*/ -struct PSI_sp_share; -typedef struct PSI_sp_share PSI_sp_share; - -/** - Interface for an instrumented stored program. - This is an opaque structure. -*/ -struct PSI_sp_locker; -typedef struct PSI_sp_locker PSI_sp_locker; - -/** - Interface for an instrumented metadata lock. - This is an opaque structure. -*/ -struct PSI_metadata_lock; -typedef struct PSI_metadata_lock PSI_metadata_lock; - -/** - Interface for an instrumented stage progress. - This is a public structure, for efficiency. -*/ -struct PSI_stage_progress -{ - ulonglong m_work_completed; - ulonglong m_work_estimated; -}; -typedef struct PSI_stage_progress PSI_stage_progress; - -/** IO operation performed on an instrumented table. */ -enum PSI_table_io_operation -{ - /** Row fetch. */ - PSI_TABLE_FETCH_ROW= 0, - /** Row write. */ - PSI_TABLE_WRITE_ROW= 1, - /** Row update. */ - PSI_TABLE_UPDATE_ROW= 2, - /** Row delete. */ - PSI_TABLE_DELETE_ROW= 3 -}; -typedef enum PSI_table_io_operation PSI_table_io_operation; - -/** - State data storage for @c start_table_io_wait_v1_t, - @c start_table_lock_wait_v1_t. - This structure provide temporary storage to a table locker. - The content of this structure is considered opaque, - the fields are only hints of what an implementation - of the psi interface can use. - This memory is provided by the instrumented code for performance reasons. - @sa start_table_io_wait_v1_t - @sa start_table_lock_wait_v1_t -*/ -struct PSI_table_locker_state -{ - /** Internal state. */ - uint m_flags; - /** Current io operation. */ - enum PSI_table_io_operation m_io_operation; - /** Current table handle. */ - struct PSI_table *m_table; - /** Current table share. */ - struct PSI_table_share *m_table_share; - /** Current thread. */ - struct PSI_thread *m_thread; - /** Timer start. */ - ulonglong m_timer_start; - /** Timer function. */ - ulonglong (*m_timer)(void); - /** Internal data. */ - void *m_wait; - /** - Implementation specific. - For table io, the table io index. - For table lock, the lock type. - */ - uint m_index; -}; -typedef struct PSI_table_locker_state PSI_table_locker_state; - -/** Entry point for the performance schema interface. */ -struct PSI_bootstrap -{ - /** - ABI interface finder. - Calling this method with an interface version number returns either - an instance of the ABI for this version, or NULL. - @param version the interface version number to find - @return a versioned interface (PSI_v1, PSI_v2 or PSI) - @sa PSI_VERSION_1 - @sa PSI_v1 - @sa PSI_VERSION_2 - @sa PSI_v2 - @sa PSI_CURRENT_VERSION - @sa PSI - */ - void* (*get_interface)(int version); -}; -typedef struct PSI_bootstrap PSI_bootstrap; - -#ifdef HAVE_PSI_INTERFACE - -#ifdef DISABLE_ALL_PSI - -#ifndef DISABLE_PSI_THREAD -#define DISABLE_PSI_THREAD -#endif - -#ifndef DISABLE_PSI_MUTEX -#define DISABLE_PSI_MUTEX -#endif - -#ifndef DISABLE_PSI_RWLOCK -#define DISABLE_PSI_RWLOCK -#endif - -#ifndef DISABLE_PSI_COND -#define DISABLE_PSI_COND -#endif - -#ifndef DISABLE_PSI_FILE -#define DISABLE_PSI_FILE -#endif - -#ifndef DISABLE_PSI_TABLE -#define DISABLE_PSI_TABLE -#endif - -#ifndef DISABLE_PSI_SOCKET -#define DISABLE_PSI_SOCKET -#endif - -#ifndef DISABLE_PSI_STAGE -#define DISABLE_PSI_STAGE -#endif - -#ifndef DISABLE_PSI_STATEMENT -#define DISABLE_PSI_STATEMENT -#endif - -#ifndef DISABLE_PSI_SP -#define DISABLE_PSI_SP -#endif - -#ifndef DISABLE_PSI_IDLE -#define DISABLE_PSI_IDLE -#endif - -#ifndef DISABLE_PSI_STATEMENT_DIGEST -#define DISABLE_PSI_STATEMENT_DIGEST -#endif - -#ifndef DISABLE_PSI_METADATA -#define DISABLE_PSI_METADATA -#endif - -#ifndef DISABLE_PSI_MEMORY -#define DISABLE_PSI_MEMORY -#endif - -#ifndef DISABLE_PSI_TRANSACTION -#define DISABLE_PSI_TRANSACTION -#endif - -#ifndef DISABLE_PSI_SP -#define DISABLE_PSI_SP -#endif - -#ifndef DISABLE_PSI_PS -#define DISABLE_PSI_PS -#endif - -#endif - -/** - @def DISABLE_PSI_MUTEX - Compiling option to disable the mutex instrumentation. - This option is mostly intended to be used during development, - when doing special builds with only a subset of the performance schema instrumentation, - for code analysis / profiling / performance tuning of a specific instrumentation alone. - @sa DISABLE_PSI_RWLOCK - @sa DISABLE_PSI_COND - @sa DISABLE_PSI_FILE - @sa DISABLE_PSI_THREAD - @sa DISABLE_PSI_TABLE - @sa DISABLE_PSI_STAGE - @sa DISABLE_PSI_STATEMENT - @sa DISABLE_PSI_SP - @sa DISABLE_PSI_STATEMENT_DIGEST - @sa DISABLE_PSI_SOCKET - @sa DISABLE_PSI_MEMORY - @sa DISABLE_PSI_IDLE - @sa DISABLE_PSI_METADATA - @sa DISABLE PSI_TRANSACTION -*/ - -#ifndef DISABLE_PSI_MUTEX -#define HAVE_PSI_MUTEX_INTERFACE -#endif - -/** - @def DISABLE_PSI_RWLOCK - Compiling option to disable the rwlock instrumentation. - @sa DISABLE_PSI_MUTEX -*/ - -#ifndef DISABLE_PSI_RWLOCK -#define HAVE_PSI_RWLOCK_INTERFACE -#endif - -/** - @def DISABLE_PSI_COND - Compiling option to disable the cond instrumentation. - @sa DISABLE_PSI_MUTEX -*/ - -#ifndef DISABLE_PSI_COND -#define HAVE_PSI_COND_INTERFACE -#endif - -/** - @def DISABLE_PSI_FILE - Compiling option to disable the file instrumentation. - @sa DISABLE_PSI_MUTEX -*/ - -#ifndef DISABLE_PSI_FILE -#define HAVE_PSI_FILE_INTERFACE -#endif - -/** - @def DISABLE_PSI_THREAD - Compiling option to disable the thread instrumentation. - @sa DISABLE_PSI_MUTEX -*/ -#ifndef DISABLE_PSI_THREAD -#define HAVE_PSI_THREAD_INTERFACE -#endif - -/** - @def DISABLE_PSI_TABLE - Compiling option to disable the table instrumentation. - @sa DISABLE_PSI_MUTEX -*/ - -#ifndef DISABLE_PSI_TABLE -#define HAVE_PSI_TABLE_INTERFACE -#endif - -/** - @def DISABLE_PSI_STAGE - Compiling option to disable the stage instrumentation. - @sa DISABLE_PSI_MUTEX -*/ - -#ifndef DISABLE_PSI_STAGE -#define HAVE_PSI_STAGE_INTERFACE -#endif - -/** - @def DISABLE_PSI_STATEMENT - Compiling option to disable the statement instrumentation. - @sa DISABLE_PSI_MUTEX -*/ - -#ifndef DISABLE_PSI_STATEMENT -#define HAVE_PSI_STATEMENT_INTERFACE -#endif - -/** - @def DISABLE_PSI_SP - Compiling option to disable the stored program instrumentation. - @sa DISABLE_PSI_MUTEX -*/ -#ifndef DISABLE_PSI_SP -#define HAVE_PSI_SP_INTERFACE -#endif - -/** - @def DISABLE_PSI_PS - Compiling option to disable the prepared statement instrumentation. - @sa DISABLE_PSI_MUTEX -*/ -#ifndef DISABLE_PSI_STATEMENT -#ifndef DISABLE_PSI_PS -#define HAVE_PSI_PS_INTERFACE -#endif -#endif - -/** - @def DISABLE_PSI_STATEMENT_DIGEST - Compiling option to disable the statement digest instrumentation. -*/ - -#ifndef DISABLE_PSI_STATEMENT -#ifndef DISABLE_PSI_STATEMENT_DIGEST -#define HAVE_PSI_STATEMENT_DIGEST_INTERFACE -#endif -#endif - -/** - @def DISABLE_PSI_TRANSACTION - Compiling option to disable the transaction instrumentation. - @sa DISABLE_PSI_MUTEX -*/ - -#ifndef DISABLE_PSI_TRANSACTION -#define HAVE_PSI_TRANSACTION_INTERFACE -#endif - -/** - @def DISABLE_PSI_SOCKET - Compiling option to disable the statement instrumentation. - @sa DISABLE_PSI_MUTEX -*/ - -#ifndef DISABLE_PSI_SOCKET -#define HAVE_PSI_SOCKET_INTERFACE -#endif - -/** - @def DISABLE_PSI_MEMORY - Compiling option to disable the memory instrumentation. - @sa DISABLE_PSI_MUTEX -*/ - -#ifndef DISABLE_PSI_MEMORY -#define HAVE_PSI_MEMORY_INTERFACE -#endif - -/** - @def DISABLE_PSI_IDLE - Compiling option to disable the idle instrumentation. - @sa DISABLE_PSI_MUTEX -*/ - -#ifndef DISABLE_PSI_IDLE -#define HAVE_PSI_IDLE_INTERFACE -#endif - -/** - @def DISABLE_PSI_METADATA - Compiling option to disable the metadata instrumentation. - @sa DISABLE_PSI_MUTEX -*/ - -#ifndef DISABLE_PSI_METADATA -#define HAVE_PSI_METADATA_INTERFACE -#endif - -/** - @def PSI_VERSION_1 - Performance Schema Interface number for version 1. - This version is supported. -*/ -#define PSI_VERSION_1 1 - -/** - @def PSI_VERSION_2 - Performance Schema Interface number for version 2. - This version is not implemented, it's a placeholder. -*/ -#define PSI_VERSION_2 2 - -/** - @def PSI_CURRENT_VERSION - Performance Schema Interface number for the most recent version. - The most current version is @c PSI_VERSION_1 -*/ -#define PSI_CURRENT_VERSION 1 - -#ifndef USE_PSI_2 -#ifndef USE_PSI_1 -#define USE_PSI_1 -#endif -#endif - -/** - Interface for an instrumented mutex operation. - This is an opaque structure. -*/ -struct PSI_mutex_locker; -typedef struct PSI_mutex_locker PSI_mutex_locker; - -/** - Interface for an instrumented rwlock operation. - This is an opaque structure. -*/ -struct PSI_rwlock_locker; -typedef struct PSI_rwlock_locker PSI_rwlock_locker; - -/** - Interface for an instrumented condition operation. - This is an opaque structure. -*/ -struct PSI_cond_locker; -typedef struct PSI_cond_locker PSI_cond_locker; - -/** - Interface for an instrumented file operation. - This is an opaque structure. -*/ -struct PSI_file_locker; -typedef struct PSI_file_locker PSI_file_locker; - -/** - Interface for an instrumented socket operation. - This is an opaque structure. -*/ -struct PSI_socket_locker; -typedef struct PSI_socket_locker PSI_socket_locker; - -/** - Interface for an instrumented MDL operation. - This is an opaque structure. -*/ -struct PSI_metadata_locker; -typedef struct PSI_metadata_locker PSI_metadata_locker; - -/** Operation performed on an instrumented mutex. */ -enum PSI_mutex_operation -{ - /** Lock. */ - PSI_MUTEX_LOCK= 0, - /** Lock attempt. */ - PSI_MUTEX_TRYLOCK= 1 -}; -typedef enum PSI_mutex_operation PSI_mutex_operation; - -/** - Operation performed on an instrumented rwlock. - For basic READ / WRITE lock, - operations are "READ" or "WRITE". - For SX-locks, operations are "SHARED", "SHARED-EXCLUSIVE" or "EXCLUSIVE". -*/ -enum PSI_rwlock_operation -{ - /** Read lock. */ - PSI_RWLOCK_READLOCK= 0, - /** Write lock. */ - PSI_RWLOCK_WRITELOCK= 1, - /** Read lock attempt. */ - PSI_RWLOCK_TRYREADLOCK= 2, - /** Write lock attempt. */ - PSI_RWLOCK_TRYWRITELOCK= 3, - - /** Shared lock. */ - PSI_RWLOCK_SHAREDLOCK= 4, - /** Shared Exclusive lock. */ - PSI_RWLOCK_SHAREDEXCLUSIVELOCK= 5, - /** Exclusive lock. */ - PSI_RWLOCK_EXCLUSIVELOCK= 6, - /** Shared lock attempt. */ - PSI_RWLOCK_TRYSHAREDLOCK= 7, - /** Shared Exclusive lock attempt. */ - PSI_RWLOCK_TRYSHAREDEXCLUSIVELOCK= 8, - /** Exclusive lock attempt. */ - PSI_RWLOCK_TRYEXCLUSIVELOCK= 9 - -}; -typedef enum PSI_rwlock_operation PSI_rwlock_operation; - -/** Operation performed on an instrumented condition. */ -enum PSI_cond_operation -{ - /** Wait. */ - PSI_COND_WAIT= 0, - /** Wait, with timeout. */ - PSI_COND_TIMEDWAIT= 1 -}; -typedef enum PSI_cond_operation PSI_cond_operation; - -/** Operation performed on an instrumented file. */ -enum PSI_file_operation -{ - /** File creation, as in @c create(). */ - PSI_FILE_CREATE= 0, - /** Temporary file creation, as in @c create_temp_file(). */ - PSI_FILE_CREATE_TMP= 1, - /** File open, as in @c open(). */ - PSI_FILE_OPEN= 2, - /** File open, as in @c fopen(). */ - PSI_FILE_STREAM_OPEN= 3, - /** File close, as in @c close(). */ - PSI_FILE_CLOSE= 4, - /** File close, as in @c fclose(). */ - PSI_FILE_STREAM_CLOSE= 5, - /** - Generic file read, such as @c fgets(), @c fgetc(), @c fread(), @c read(), - @c pread(). - */ - PSI_FILE_READ= 6, - /** - Generic file write, such as @c fputs(), @c fputc(), @c fprintf(), - @c vfprintf(), @c fwrite(), @c write(), @c pwrite(). - */ - PSI_FILE_WRITE= 7, - /** Generic file seek, such as @c fseek() or @c seek(). */ - PSI_FILE_SEEK= 8, - /** Generic file tell, such as @c ftell() or @c tell(). */ - PSI_FILE_TELL= 9, - /** File flush, as in @c fflush(). */ - PSI_FILE_FLUSH= 10, - /** File stat, as in @c stat(). */ - PSI_FILE_STAT= 11, - /** File stat, as in @c fstat(). */ - PSI_FILE_FSTAT= 12, - /** File chsize, as in @c my_chsize(). */ - PSI_FILE_CHSIZE= 13, - /** File delete, such as @c my_delete() or @c my_delete_with_symlink(). */ - PSI_FILE_DELETE= 14, - /** File rename, such as @c my_rename() or @c my_rename_with_symlink(). */ - PSI_FILE_RENAME= 15, - /** File sync, as in @c fsync() or @c my_sync(). */ - PSI_FILE_SYNC= 16 -}; -typedef enum PSI_file_operation PSI_file_operation; - -/** Lock operation performed on an instrumented table. */ -enum PSI_table_lock_operation -{ - /** Table lock, in the server layer. */ - PSI_TABLE_LOCK= 0, - /** Table lock, in the storage engine layer. */ - PSI_TABLE_EXTERNAL_LOCK= 1 -}; -typedef enum PSI_table_lock_operation PSI_table_lock_operation; - -/** State of an instrumented socket. */ -enum PSI_socket_state -{ - /** Idle, waiting for the next command. */ - PSI_SOCKET_STATE_IDLE= 1, - /** Active, executing a command. */ - PSI_SOCKET_STATE_ACTIVE= 2 -}; -typedef enum PSI_socket_state PSI_socket_state; - -/** Operation performed on an instrumented socket. */ -enum PSI_socket_operation -{ - /** Socket creation, as in @c socket() or @c socketpair(). */ - PSI_SOCKET_CREATE= 0, - /** Socket connection, as in @c connect(), @c listen() and @c accept(). */ - PSI_SOCKET_CONNECT= 1, - /** Socket bind, as in @c bind(), @c getsockname() and @c getpeername(). */ - PSI_SOCKET_BIND= 2, - /** Socket close, as in @c shutdown(). */ - PSI_SOCKET_CLOSE= 3, - /** Socket send, @c send(). */ - PSI_SOCKET_SEND= 4, - /** Socket receive, @c recv(). */ - PSI_SOCKET_RECV= 5, - /** Socket send, @c sendto(). */ - PSI_SOCKET_SENDTO= 6, - /** Socket receive, @c recvfrom). */ - PSI_SOCKET_RECVFROM= 7, - /** Socket send, @c sendmsg(). */ - PSI_SOCKET_SENDMSG= 8, - /** Socket receive, @c recvmsg(). */ - PSI_SOCKET_RECVMSG= 9, - /** Socket seek, such as @c fseek() or @c seek(). */ - PSI_SOCKET_SEEK= 10, - /** Socket options, as in @c getsockopt() and @c setsockopt(). */ - PSI_SOCKET_OPT= 11, - /** Socket status, as in @c sockatmark() and @c isfdtype(). */ - PSI_SOCKET_STAT= 12, - /** Socket shutdown, as in @c shutdown(). */ - PSI_SOCKET_SHUTDOWN= 13, - /** Socket select, as in @c select() and @c poll(). */ - PSI_SOCKET_SELECT= 14 -}; -typedef enum PSI_socket_operation PSI_socket_operation; - -/** - Instrumented mutex key. - To instrument a mutex, a mutex key must be obtained using @c register_mutex. - Using a zero key always disable the instrumentation. -*/ -typedef unsigned int PSI_mutex_key; - -/** - Instrumented rwlock key. - To instrument a rwlock, a rwlock key must be obtained - using @c register_rwlock. - Using a zero key always disable the instrumentation. -*/ -typedef unsigned int PSI_rwlock_key; - -/** - Instrumented cond key. - To instrument a condition, a condition key must be obtained - using @c register_cond. - Using a zero key always disable the instrumentation. -*/ -typedef unsigned int PSI_cond_key; - -/** - Instrumented thread key. - To instrument a thread, a thread key must be obtained - using @c register_thread. - Using a zero key always disable the instrumentation. -*/ -typedef unsigned int PSI_thread_key; - -/** - Instrumented file key. - To instrument a file, a file key must be obtained using @c register_file. - Using a zero key always disable the instrumentation. -*/ -#ifndef PSI_FILE_KEY_DEFINED -typedef unsigned int PSI_file_key; -#define PSI_FILE_KEY_DEFINED -#endif - -/** - Instrumented stage key. - To instrument a stage, a stage key must be obtained using @c register_stage. - Using a zero key always disable the instrumentation. -*/ -typedef unsigned int PSI_stage_key; - -/** - Instrumented statement key. - To instrument a statement, a statement key must be obtained using @c register_statement. - Using a zero key always disable the instrumentation. -*/ -typedef unsigned int PSI_statement_key; - -/** - Instrumented socket key. - To instrument a socket, a socket key must be obtained using @c register_socket. - Using a zero key always disable the instrumentation. -*/ -typedef unsigned int PSI_socket_key; - -#ifdef HAVE_PSI_1 - -/** - @defgroup Group_PSI_v1 Application Binary Interface, version 1 - @ingroup Instrumentation_interface - @{ -*/ - -/** - Mutex information. - @since PSI_VERSION_1 - This structure is used to register an instrumented mutex. -*/ -struct PSI_mutex_info_v1 -{ - /** - Pointer to the key assigned to the registered mutex. - */ - PSI_mutex_key *m_key; - /** - The name of the mutex to register. - */ - const char *m_name; - /** - The flags of the mutex to register. - @sa PSI_FLAG_GLOBAL - */ - int m_flags; -}; -typedef struct PSI_mutex_info_v1 PSI_mutex_info_v1; - -/** - Rwlock information. - @since PSI_VERSION_1 - This structure is used to register an instrumented rwlock. -*/ -struct PSI_rwlock_info_v1 -{ - /** - Pointer to the key assigned to the registered rwlock. - */ - PSI_rwlock_key *m_key; - /** - The name of the rwlock to register. - */ - const char *m_name; - /** - The flags of the rwlock to register. - @sa PSI_FLAG_GLOBAL - */ - int m_flags; -}; -typedef struct PSI_rwlock_info_v1 PSI_rwlock_info_v1; - -/** - Condition information. - @since PSI_VERSION_1 - This structure is used to register an instrumented cond. -*/ -struct PSI_cond_info_v1 -{ - /** - Pointer to the key assigned to the registered cond. - */ - PSI_cond_key *m_key; - /** - The name of the cond to register. - */ - const char *m_name; - /** - The flags of the cond to register. - @sa PSI_FLAG_GLOBAL - */ - int m_flags; -}; -typedef struct PSI_cond_info_v1 PSI_cond_info_v1; - -/** - Thread instrument information. - @since PSI_VERSION_1 - This structure is used to register an instrumented thread. -*/ -struct PSI_thread_info_v1 -{ - /** - Pointer to the key assigned to the registered thread. - */ - PSI_thread_key *m_key; - /** - The name of the thread instrument to register. - */ - const char *m_name; - /** - The flags of the thread to register. - @sa PSI_FLAG_GLOBAL - */ - int m_flags; -}; -typedef struct PSI_thread_info_v1 PSI_thread_info_v1; - -/** - File instrument information. - @since PSI_VERSION_1 - This structure is used to register an instrumented file. -*/ -struct PSI_file_info_v1 -{ - /** - Pointer to the key assigned to the registered file. - */ - PSI_file_key *m_key; - /** - The name of the file instrument to register. - */ - const char *m_name; - /** - The flags of the file instrument to register. - @sa PSI_FLAG_GLOBAL - */ - int m_flags; -}; -typedef struct PSI_file_info_v1 PSI_file_info_v1; - -/** - Stage instrument information. - @since PSI_VERSION_1 - This structure is used to register an instrumented stage. -*/ -struct PSI_stage_info_v1 -{ - /** The registered stage key. */ - PSI_stage_key m_key; - /** The name of the stage instrument to register. */ - const char *m_name; - /** The flags of the stage instrument to register. */ - int m_flags; -}; -typedef struct PSI_stage_info_v1 PSI_stage_info_v1; - -/** - Statement instrument information. - @since PSI_VERSION_1 - This structure is used to register an instrumented statement. -*/ -struct PSI_statement_info_v1 -{ - /** The registered statement key. */ - PSI_statement_key m_key; - /** The name of the statement instrument to register. */ - const char *m_name; - /** The flags of the statement instrument to register. */ - int m_flags; -}; -typedef struct PSI_statement_info_v1 PSI_statement_info_v1; - -/** - Socket instrument information. - @since PSI_VERSION_1 - This structure is used to register an instrumented socket. -*/ -struct PSI_socket_info_v1 -{ - /** - Pointer to the key assigned to the registered socket. - */ - PSI_socket_key *m_key; - /** - The name of the socket instrument to register. - */ - const char *m_name; - /** - The flags of the socket instrument to register. - @sa PSI_FLAG_GLOBAL - */ - int m_flags; -}; -typedef struct PSI_socket_info_v1 PSI_socket_info_v1; - -/** - State data storage for @c start_idle_wait_v1_t. - This structure provide temporary storage to an idle locker. - The content of this structure is considered opaque, - the fields are only hints of what an implementation - of the psi interface can use. - This memory is provided by the instrumented code for performance reasons. - @sa start_idle_wait_v1_t. -*/ -struct PSI_idle_locker_state_v1 -{ - /** Internal state. */ - uint m_flags; - /** Current thread. */ - struct PSI_thread *m_thread; - /** Timer start. */ - ulonglong m_timer_start; - /** Timer function. */ - ulonglong (*m_timer)(void); - /** Internal data. */ - void *m_wait; -}; -typedef struct PSI_idle_locker_state_v1 PSI_idle_locker_state_v1; - -/** - State data storage for @c start_mutex_wait_v1_t. - This structure provide temporary storage to a mutex locker. - The content of this structure is considered opaque, - the fields are only hints of what an implementation - of the psi interface can use. - This memory is provided by the instrumented code for performance reasons. - @sa start_mutex_wait_v1_t -*/ -struct PSI_mutex_locker_state_v1 -{ - /** Internal state. */ - uint m_flags; - /** Current operation. */ - enum PSI_mutex_operation m_operation; - /** Current mutex. */ - struct PSI_mutex *m_mutex; - /** Current thread. */ - struct PSI_thread *m_thread; - /** Timer start. */ - ulonglong m_timer_start; - /** Timer function. */ - ulonglong (*m_timer)(void); - /** Internal data. */ - void *m_wait; -}; -typedef struct PSI_mutex_locker_state_v1 PSI_mutex_locker_state_v1; - -/** - State data storage for @c start_rwlock_rdwait_v1_t, @c start_rwlock_wrwait_v1_t. - This structure provide temporary storage to a rwlock locker. - The content of this structure is considered opaque, - the fields are only hints of what an implementation - of the psi interface can use. - This memory is provided by the instrumented code for performance reasons. - @sa start_rwlock_rdwait_v1_t - @sa start_rwlock_wrwait_v1_t -*/ -struct PSI_rwlock_locker_state_v1 -{ - /** Internal state. */ - uint m_flags; - /** Current operation. */ - enum PSI_rwlock_operation m_operation; - /** Current rwlock. */ - struct PSI_rwlock *m_rwlock; - /** Current thread. */ - struct PSI_thread *m_thread; - /** Timer start. */ - ulonglong m_timer_start; - /** Timer function. */ - ulonglong (*m_timer)(void); - /** Internal data. */ - void *m_wait; -}; -typedef struct PSI_rwlock_locker_state_v1 PSI_rwlock_locker_state_v1; - -/** - State data storage for @c start_cond_wait_v1_t. - This structure provide temporary storage to a condition locker. - The content of this structure is considered opaque, - the fields are only hints of what an implementation - of the psi interface can use. - This memory is provided by the instrumented code for performance reasons. - @sa start_cond_wait_v1_t -*/ -struct PSI_cond_locker_state_v1 -{ - /** Internal state. */ - uint m_flags; - /** Current operation. */ - enum PSI_cond_operation m_operation; - /** Current condition. */ - struct PSI_cond *m_cond; - /** Current mutex. */ - struct PSI_mutex *m_mutex; - /** Current thread. */ - struct PSI_thread *m_thread; - /** Timer start. */ - ulonglong m_timer_start; - /** Timer function. */ - ulonglong (*m_timer)(void); - /** Internal data. */ - void *m_wait; -}; -typedef struct PSI_cond_locker_state_v1 PSI_cond_locker_state_v1; - -/** - State data storage for @c get_thread_file_name_locker_v1_t. - This structure provide temporary storage to a file locker. - The content of this structure is considered opaque, - the fields are only hints of what an implementation - of the psi interface can use. - This memory is provided by the instrumented code for performance reasons. - @sa get_thread_file_name_locker_v1_t - @sa get_thread_file_stream_locker_v1_t - @sa get_thread_file_descriptor_locker_v1_t -*/ -struct PSI_file_locker_state_v1 -{ - /** Internal state. */ - uint m_flags; - /** Current operation. */ - enum PSI_file_operation m_operation; - /** Current file. */ - struct PSI_file *m_file; - /** Current file name. */ - const char *m_name; - /** Current file class. */ - void *m_class; - /** Current thread. */ - struct PSI_thread *m_thread; - /** Operation number of bytes. */ - size_t m_number_of_bytes; - /** Timer start. */ - ulonglong m_timer_start; - /** Timer function. */ - ulonglong (*m_timer)(void); - /** Internal data. */ - void *m_wait; -}; -typedef struct PSI_file_locker_state_v1 PSI_file_locker_state_v1; - -/** - State data storage for @c start_metadata_wait_v1_t. - This structure provide temporary storage to a metadata locker. - The content of this structure is considered opaque, - the fields are only hints of what an implementation - of the psi interface can use. - This memory is provided by the instrumented code for performance reasons. - @sa start_metadata_wait_v1_t -*/ -struct PSI_metadata_locker_state_v1 -{ - /** Internal state. */ - uint m_flags; - /** Current metadata lock. */ - struct PSI_metadata_lock *m_metadata_lock; - /** Current thread. */ - struct PSI_thread *m_thread; - /** Timer start. */ - ulonglong m_timer_start; - /** Timer function. */ - ulonglong (*m_timer)(void); - /** Internal data. */ - void *m_wait; -}; -typedef struct PSI_metadata_locker_state_v1 PSI_metadata_locker_state_v1; - -/* Duplicate of NAME_LEN, to avoid dependency on mysql_com.h */ -#define PSI_SCHEMA_NAME_LEN (64 * 3) - -/** - State data storage for @c get_thread_statement_locker_v1_t, - @c get_thread_statement_locker_v1_t. - This structure provide temporary storage to a statement locker. - The content of this structure is considered opaque, - the fields are only hints of what an implementation - of the psi interface can use. - This memory is provided by the instrumented code for performance reasons. - @sa get_thread_statement_locker_v1_t -*/ -struct PSI_statement_locker_state_v1 -{ - /** Discarded flag. */ - my_bool m_discarded; - /** In prepare flag. */ - my_bool m_in_prepare; - /** Metric, no index used flag. */ - uchar m_no_index_used; - /** Metric, no good index used flag. */ - uchar m_no_good_index_used; - /** Internal state. */ - uint m_flags; - /** Instrumentation class. */ - void *m_class; - /** Current thread. */ - struct PSI_thread *m_thread; - /** Timer start. */ - ulonglong m_timer_start; - /** Timer function. */ - ulonglong (*m_timer)(void); - /** Internal data. */ - void *m_statement; - /** Locked time. */ - ulonglong m_lock_time; - /** Rows sent. */ - ulonglong m_rows_sent; - /** Rows examined. */ - ulonglong m_rows_examined; - /** Metric, temporary tables created on disk. */ - ulong m_created_tmp_disk_tables; - /** Metric, temporary tables created. */ - ulong m_created_tmp_tables; - /** Metric, number of select full join. */ - ulong m_select_full_join; - /** Metric, number of select full range join. */ - ulong m_select_full_range_join; - /** Metric, number of select range. */ - ulong m_select_range; - /** Metric, number of select range check. */ - ulong m_select_range_check; - /** Metric, number of select scan. */ - ulong m_select_scan; - /** Metric, number of sort merge passes. */ - ulong m_sort_merge_passes; - /** Metric, number of sort merge. */ - ulong m_sort_range; - /** Metric, number of sort rows. */ - ulong m_sort_rows; - /** Metric, number of sort scans. */ - ulong m_sort_scan; - /** Statement digest. */ - const struct sql_digest_storage *m_digest; - /** Current schema name. */ - char m_schema_name[PSI_SCHEMA_NAME_LEN]; - /** Length in bytes of @c m_schema_name. */ - uint m_schema_name_length; - /** Statement character set number. */ - uint m_cs_number; - PSI_sp_share *m_parent_sp_share; - PSI_prepared_stmt *m_parent_prepared_stmt; -}; -typedef struct PSI_statement_locker_state_v1 PSI_statement_locker_state_v1; - -/** - State data storage for @c get_thread_transaction_locker_v1_t, - @c get_thread_transaction_locker_v1_t. - This structure provide temporary storage to a transaction locker. - The content of this structure is considered opaque, - the fields are only hints of what an implementation - of the psi interface can use. - This memory is provided by the instrumented code for performance reasons. - @sa get_thread_transaction_locker_v1_t -*/ -struct PSI_transaction_locker_state_v1 -{ - /** Internal state. */ - uint m_flags; - /** Instrumentation class. */ - void *m_class; - /** Current thread. */ - struct PSI_thread *m_thread; - /** Timer start. */ - ulonglong m_timer_start; - /** Timer function. */ - ulonglong (*m_timer)(void); - /** Internal data. */ - void *m_transaction; - /** True if read-only transaction, false if read-write. */ - my_bool m_read_only; - /** True if transaction is autocommit. */ - my_bool m_autocommit; - /** Number of statements. */ - ulong m_statement_count; - /** Total number of savepoints. */ - ulong m_savepoint_count; - /** Number of rollback_to_savepoint. */ - ulong m_rollback_to_savepoint_count; - /** Number of release_savepoint. */ - ulong m_release_savepoint_count; -}; - -typedef struct PSI_transaction_locker_state_v1 PSI_transaction_locker_state_v1; - -/** - State data storage for @c start_socket_wait_v1_t. - This structure provide temporary storage to a socket locker. - The content of this structure is considered opaque, - the fields are only hints of what an implementation - of the psi interface can use. - This memory is provided by the instrumented code for performance reasons. - @sa start_socket_wait_v1_t -*/ -struct PSI_socket_locker_state_v1 -{ - /** Internal state. */ - uint m_flags; - /** Current socket. */ - struct PSI_socket *m_socket; - /** Current thread. */ - struct PSI_thread *m_thread; - /** Operation number of bytes. */ - size_t m_number_of_bytes; - /** Timer start. */ - ulonglong m_timer_start; - /** Timer function. */ - ulonglong (*m_timer)(void); - /** Current operation. */ - enum PSI_socket_operation m_operation; - /** Source file. */ - const char* m_src_file; - /** Source line number. */ - int m_src_line; - /** Internal data. */ - void *m_wait; -}; -typedef struct PSI_socket_locker_state_v1 PSI_socket_locker_state_v1; - -struct PSI_sp_locker_state_v1 -{ - /** Internal state. */ - uint m_flags; - /** Current thread. */ - struct PSI_thread *m_thread; - /** Timer start. */ - ulonglong m_timer_start; - /** Timer function. */ - ulonglong (*m_timer)(void); - /** Stored Procedure share. */ - PSI_sp_share* m_sp_share; -}; -typedef struct PSI_sp_locker_state_v1 PSI_sp_locker_state_v1; - -/* Using typedef to make reuse between PSI_v1 and PSI_v2 easier later. */ - -/** - Mutex registration API. - @param category a category name (typically a plugin name) - @param info an array of mutex info to register - @param count the size of the info array -*/ -typedef void (*register_mutex_v1_t) - (const char *category, struct PSI_mutex_info_v1 *info, int count); - -/** - Rwlock registration API. - @param category a category name (typically a plugin name) - @param info an array of rwlock info to register - @param count the size of the info array -*/ -typedef void (*register_rwlock_v1_t) - (const char *category, struct PSI_rwlock_info_v1 *info, int count); - -/** - Cond registration API. - @param category a category name (typically a plugin name) - @param info an array of cond info to register - @param count the size of the info array -*/ -typedef void (*register_cond_v1_t) - (const char *category, struct PSI_cond_info_v1 *info, int count); - -/** - Thread registration API. - @param category a category name (typically a plugin name) - @param info an array of thread info to register - @param count the size of the info array -*/ -typedef void (*register_thread_v1_t) - (const char *category, struct PSI_thread_info_v1 *info, int count); - -/** - File registration API. - @param category a category name (typically a plugin name) - @param info an array of file info to register - @param count the size of the info array -*/ -typedef void (*register_file_v1_t) - (const char *category, struct PSI_file_info_v1 *info, int count); - -/** - Stage registration API. - @param category a category name - @param info an array of stage info to register - @param count the size of the info array -*/ -typedef void (*register_stage_v1_t) - (const char *category, struct PSI_stage_info_v1 **info, int count); - -/** - Statement registration API. - @param category a category name - @param info an array of stage info to register - @param count the size of the info array -*/ -typedef void (*register_statement_v1_t) - (const char *category, struct PSI_statement_info_v1 *info, int count); - -/** - Socket registration API. - @param category a category name (typically a plugin name) - @param info an array of socket info to register - @param count the size of the info array -*/ -typedef void (*register_socket_v1_t) - (const char *category, struct PSI_socket_info_v1 *info, int count); - -/** - Mutex instrumentation initialisation API. - @param key the registered mutex key - @param identity the address of the mutex itself - @return an instrumented mutex -*/ -typedef struct PSI_mutex* (*init_mutex_v1_t) - (PSI_mutex_key key, const void *identity); - -/** - Mutex instrumentation destruction API. - @param mutex the mutex to destroy -*/ -typedef void (*destroy_mutex_v1_t)(struct PSI_mutex *mutex); - -/** - Rwlock instrumentation initialisation API. - @param key the registered rwlock key - @param identity the address of the rwlock itself - @return an instrumented rwlock -*/ -typedef struct PSI_rwlock* (*init_rwlock_v1_t) - (PSI_rwlock_key key, const void *identity); - -/** - Rwlock instrumentation destruction API. - @param rwlock the rwlock to destroy -*/ -typedef void (*destroy_rwlock_v1_t)(struct PSI_rwlock *rwlock); - -/** - Cond instrumentation initialisation API. - @param key the registered key - @param identity the address of the rwlock itself - @return an instrumented cond -*/ -typedef struct PSI_cond* (*init_cond_v1_t) - (PSI_cond_key key, const void *identity); - -/** - Cond instrumentation destruction API. - @param cond the rcond to destroy -*/ -typedef void (*destroy_cond_v1_t)(struct PSI_cond *cond); - -/** - Socket instrumentation initialisation API. - @param key the registered mutex key - @param socket descriptor - @param addr the socket ip address - @param addr_len length of socket ip address - @return an instrumented socket -*/ -typedef struct PSI_socket* (*init_socket_v1_t) - (PSI_socket_key key, const my_socket *fd, - const struct sockaddr *addr, socklen_t addr_len); - -/** - socket instrumentation destruction API. - @param socket the socket to destroy -*/ -typedef void (*destroy_socket_v1_t)(struct PSI_socket *socket); - -/** - Acquire a table share instrumentation. - @param temporary True for temporary tables - @param share The SQL layer table share - @return a table share instrumentation, or NULL -*/ -typedef struct PSI_table_share* (*get_table_share_v1_t) - (my_bool temporary, struct TABLE_SHARE *share); - -/** - Release a table share. - @param info the table share to release -*/ -typedef void (*release_table_share_v1_t)(struct PSI_table_share *share); - -/** - Drop a table share. - @param temporary True for temporary tables - @param schema_name the table schema name - @param schema_name_length the table schema name length - @param table_name the table name - @param table_name_length the table name length -*/ -typedef void (*drop_table_share_v1_t) - (my_bool temporary, const char *schema_name, int schema_name_length, - const char *table_name, int table_name_length); - -/** - Open an instrumentation table handle. - @param share the table to open - @param identity table handle identity - @return a table handle, or NULL -*/ -typedef struct PSI_table* (*open_table_v1_t) - (struct PSI_table_share *share, const void *identity); - -/** - Unbind a table handle from the current thread. - This operation happens when an opened table is added to the open table cache. - @param table the table to unbind -*/ -typedef void (*unbind_table_v1_t) - (struct PSI_table *table); - -/** - Rebind a table handle to the current thread. - This operation happens when a table from the open table cache - is reused for a thread. - @param table the table to unbind -*/ -typedef PSI_table* (*rebind_table_v1_t) - (PSI_table_share *share, const void *identity, PSI_table *table); - -/** - Close an instrumentation table handle. - Note that the table handle is invalid after this call. - @param table the table handle to close -*/ -typedef void (*close_table_v1_t)(struct TABLE_SHARE *server_share, - struct PSI_table *table); - -/** - Create a file instrumentation for a created file. - This method does not create the file itself, but is used to notify the - instrumentation interface that a file was just created. - @param key the file instrumentation key for this file - @param name the file name - @param file the file handle -*/ -typedef void (*create_file_v1_t)(PSI_file_key key, const char *name, - File file); - -/** - Spawn a thread. - This method creates a new thread, with instrumentation. - @param key the instrumentation key for this thread - @param thread the resulting thread - @param attr the thread attributes - @param start_routine the thread start routine - @param arg the thread start routine argument -*/ -typedef int (*spawn_thread_v1_t)(PSI_thread_key key, - my_thread_handle *thread, - const my_thread_attr_t *attr, - void *(*start_routine)(void*), void *arg); - -/** - Create instrumentation for a thread. - @param key the registered key - @param identity an address typical of the thread - @return an instrumented thread -*/ -typedef struct PSI_thread* (*new_thread_v1_t) - (PSI_thread_key key, const void *identity, ulonglong thread_id); - -/** - Assign a THD to an instrumented thread. - @param thread the instrumented thread - @param THD the sql layer THD to assign -*/ -typedef void (*set_thread_THD_v1_t)(struct PSI_thread *thread, - THD *thd); - -/** - Assign an id to an instrumented thread. - @param thread the instrumented thread - @param id the id to assign -*/ -typedef void (*set_thread_id_v1_t)(struct PSI_thread *thread, - ulonglong id); - -/** - Assign the current operating system thread id to an instrumented thread. - The operating system task id is obtained from @c gettid() - @param thread the instrumented thread -*/ -typedef void (*set_thread_os_id_v1_t)(struct PSI_thread *thread); - -/** - Get the instrumentation for the running thread. - For this function to return a result, - the thread instrumentation must have been attached to the - running thread using @c set_thread() - @return the instrumentation for the running thread -*/ -typedef struct PSI_thread* (*get_thread_v1_t)(void); - -/** - Assign a user name to the instrumented thread. - @param user the user name - @param user_len the user name length -*/ -typedef void (*set_thread_user_v1_t)(const char *user, int user_len); - -/** - Assign a user name and host name to the instrumented thread. - @param user the user name - @param user_len the user name length - @param host the host name - @param host_len the host name length -*/ -typedef void (*set_thread_account_v1_t)(const char *user, int user_len, - const char *host, int host_len); - -/** - Assign a current database to the instrumented thread. - @param db the database name - @param db_len the database name length -*/ -typedef void (*set_thread_db_v1_t)(const char* db, int db_len); - -/** - Assign a current command to the instrumented thread. - @param command the current command -*/ -typedef void (*set_thread_command_v1_t)(int command); - -/** - Assign a connection type to the instrumented thread. - @param conn_type the connection type -*/ -typedef void (*set_connection_type_v1_t)(opaque_vio_type conn_type); - - -/** - Assign a start time to the instrumented thread. - @param start_time the thread start time -*/ -typedef void (*set_thread_start_time_v1_t)(time_t start_time); - -/** - Assign a state to the instrumented thread. - @param state the thread state -*/ -typedef void (*set_thread_state_v1_t)(const char* state); - -/** - Assign a process info to the instrumented thread. - @param info the process into string - @param info_len the process into string length -*/ -typedef void (*set_thread_info_v1_t)(const char* info, uint info_len); - -/** - Attach a thread instrumentation to the running thread. - In case of thread pools, this method should be called when - a worker thread picks a work item and runs it. - Also, this method should be called if the instrumented code does not - keep the pointer returned by @c new_thread() and relies on @c get_thread() - instead. - @param thread the thread instrumentation -*/ -typedef void (*set_thread_v1_t)(struct PSI_thread *thread); - -/** Delete the current thread instrumentation. */ -typedef void (*delete_current_thread_v1_t)(void); - -/** Delete a thread instrumentation. */ -typedef void (*delete_thread_v1_t)(struct PSI_thread *thread); - -/** - Get a file instrumentation locker, for opening or creating a file. - @param state data storage for the locker - @param key the file instrumentation key - @param op the operation to perform - @param name the file name - @param identity a pointer representative of this file. - @return a file locker, or NULL -*/ -typedef struct PSI_file_locker* (*get_thread_file_name_locker_v1_t) - (struct PSI_file_locker_state_v1 *state, - PSI_file_key key, enum PSI_file_operation op, const char *name, - const void *identity); - -/** - Get a file stream instrumentation locker. - @param state data storage for the locker - @param file the file stream to access - @param op the operation to perform - @return a file locker, or NULL -*/ -typedef struct PSI_file_locker* (*get_thread_file_stream_locker_v1_t) - (struct PSI_file_locker_state_v1 *state, - struct PSI_file *file, enum PSI_file_operation op); - -/** - Get a file instrumentation locker. - @param state data storage for the locker - @param file the file descriptor to access - @param op the operation to perform - @return a file locker, or NULL -*/ -typedef struct PSI_file_locker* (*get_thread_file_descriptor_locker_v1_t) - (struct PSI_file_locker_state_v1 *state, - File file, enum PSI_file_operation op); - -/** - Record a mutex instrumentation unlock event. - @param mutex the mutex instrumentation -*/ -typedef void (*unlock_mutex_v1_t) - (struct PSI_mutex *mutex); - -/** - Record a rwlock instrumentation unlock event. - @param rwlock the rwlock instrumentation -*/ -typedef void (*unlock_rwlock_v1_t) - (struct PSI_rwlock *rwlock); - -/** - Record a condition instrumentation signal event. - @param cond the cond instrumentation -*/ -typedef void (*signal_cond_v1_t) - (struct PSI_cond *cond); - -/** - Record a condition instrumentation broadcast event. - @param cond the cond instrumentation -*/ -typedef void (*broadcast_cond_v1_t) - (struct PSI_cond *cond); - -/** - Record an idle instrumentation wait start event. - @param state data storage for the locker - @param file the source file name - @param line the source line number - @return an idle locker, or NULL -*/ -typedef struct PSI_idle_locker* (*start_idle_wait_v1_t) - (struct PSI_idle_locker_state_v1 *state, const char *src_file, uint src_line); - -/** - Record an idle instrumentation wait end event. - @param locker a thread locker for the running thread -*/ -typedef void (*end_idle_wait_v1_t) - (struct PSI_idle_locker *locker); - -/** - Record a mutex instrumentation wait start event. - @param state data storage for the locker - @param mutex the instrumented mutex to lock - @param op the operation to perform - @param file the source file name - @param line the source line number - @return a mutex locker, or NULL -*/ -typedef struct PSI_mutex_locker* (*start_mutex_wait_v1_t) - (struct PSI_mutex_locker_state_v1 *state, - struct PSI_mutex *mutex, - enum PSI_mutex_operation op, - const char *src_file, uint src_line); - -/** - Record a mutex instrumentation wait end event. - @param locker a thread locker for the running thread - @param rc the wait operation return code -*/ -typedef void (*end_mutex_wait_v1_t) - (struct PSI_mutex_locker *locker, int rc); - -/** - Record a rwlock instrumentation read wait start event. - @param locker a thread locker for the running thread - @param must must block: 1 for lock, 0 for trylock -*/ -typedef struct PSI_rwlock_locker* (*start_rwlock_rdwait_v1_t) - (struct PSI_rwlock_locker_state_v1 *state, - struct PSI_rwlock *rwlock, - enum PSI_rwlock_operation op, - const char *src_file, uint src_line); - -/** - Record a rwlock instrumentation read wait end event. - @param locker a thread locker for the running thread - @param rc the wait operation return code -*/ -typedef void (*end_rwlock_rdwait_v1_t) - (struct PSI_rwlock_locker *locker, int rc); - -/** - Record a rwlock instrumentation write wait start event. - @param locker a thread locker for the running thread - @param must must block: 1 for lock, 0 for trylock -*/ -typedef struct PSI_rwlock_locker* (*start_rwlock_wrwait_v1_t) - (struct PSI_rwlock_locker_state_v1 *state, - struct PSI_rwlock *rwlock, - enum PSI_rwlock_operation op, - const char *src_file, uint src_line); - -/** - Record a rwlock instrumentation write wait end event. - @param locker a thread locker for the running thread - @param rc the wait operation return code -*/ -typedef void (*end_rwlock_wrwait_v1_t) - (struct PSI_rwlock_locker *locker, int rc); - -/** - Record a condition instrumentation wait start event. - @param locker a thread locker for the running thread - @param must must block: 1 for wait, 0 for timedwait -*/ -typedef struct PSI_cond_locker* (*start_cond_wait_v1_t) - (struct PSI_cond_locker_state_v1 *state, - struct PSI_cond *cond, - struct PSI_mutex *mutex, - enum PSI_cond_operation op, - const char *src_file, uint src_line); - -/** - Record a condition instrumentation wait end event. - @param locker a thread locker for the running thread - @param rc the wait operation return code -*/ -typedef void (*end_cond_wait_v1_t) - (struct PSI_cond_locker *locker, int rc); - -/** - Record a table instrumentation io wait start event. - @param locker a table locker for the running thread - @param file the source file name - @param line the source line number -*/ -typedef struct PSI_table_locker* (*start_table_io_wait_v1_t) - (struct PSI_table_locker_state *state, - struct PSI_table *table, - enum PSI_table_io_operation op, - uint index, - const char *src_file, uint src_line); - -/** - Record a table instrumentation io wait end event. - @param locker a table locker for the running thread - @param numrows the number of rows involved in io -*/ -typedef void (*end_table_io_wait_v1_t) - (struct PSI_table_locker *locker, - ulonglong numrows); - -/** - Record a table instrumentation lock wait start event. - @param locker a table locker for the running thread - @param file the source file name - @param line the source line number -*/ -typedef struct PSI_table_locker* (*start_table_lock_wait_v1_t) - (struct PSI_table_locker_state *state, - struct PSI_table *table, - enum PSI_table_lock_operation op, - ulong flags, - const char *src_file, uint src_line); - -/** - Record a table instrumentation lock wait end event. - @param locker a table locker for the running thread -*/ -typedef void (*end_table_lock_wait_v1_t)(struct PSI_table_locker *locker); - -typedef void (*unlock_table_v1_t)(struct PSI_table *table); - -/** - Start a file instrumentation open operation. - @param locker the file locker - @param op the operation to perform - @param src_file the source file name - @param src_line the source line number -*/ -typedef void (*start_file_open_wait_v1_t) - (struct PSI_file_locker *locker, const char *src_file, uint src_line); - -/** - End a file instrumentation open operation, for file streams. - @param locker the file locker. - @param result the opened file (NULL indicates failure, non NULL success). - @return an instrumented file handle -*/ -typedef struct PSI_file* (*end_file_open_wait_v1_t) - (struct PSI_file_locker *locker, void *result); - -/** - End a file instrumentation open operation, for non stream files. - @param locker the file locker. - @param file the file number assigned by open() or create() for this file. -*/ -typedef void (*end_file_open_wait_and_bind_to_descriptor_v1_t) - (struct PSI_file_locker *locker, File file); - -/** - End a file instrumentation open operation, for non stream temporary files. - @param locker the file locker. - @param file the file number assigned by open() or create() for this file. - @param filename the file name generated during temporary file creation. -*/ -typedef void (*end_temp_file_open_wait_and_bind_to_descriptor_v1_t) - (struct PSI_file_locker *locker, File file, const char *filename); - -/** - Record a file instrumentation start event. - @param locker a file locker for the running thread - @param op file operation to be performed - @param count the number of bytes requested, or 0 if not applicable - @param src_file the source file name - @param src_line the source line number -*/ -typedef void (*start_file_wait_v1_t) - (struct PSI_file_locker *locker, size_t count, - const char *src_file, uint src_line); - -/** - Record a file instrumentation end event. - Note that for file close operations, the instrumented file handle - associated with the file (which was provided to obtain a locker) - is invalid after this call. - @param locker a file locker for the running thread - @param count the number of bytes actually used in the operation, - or 0 if not applicable, or -1 if the operation failed - @sa get_thread_file_name_locker - @sa get_thread_file_stream_locker - @sa get_thread_file_descriptor_locker -*/ -typedef void (*end_file_wait_v1_t) - (struct PSI_file_locker *locker, size_t count); - -/** - Start a file instrumentation close operation. - @param locker the file locker - @param op the operation to perform - @param src_file the source file name - @param src_line the source line number -*/ -typedef void (*start_file_close_wait_v1_t) - (struct PSI_file_locker *locker, const char *src_file, uint src_line); - -/** - End a file instrumentation close operation. - @param locker the file locker. - @param rc the close operation return code (0 for success). - @return an instrumented file handle -*/ -typedef void (*end_file_close_wait_v1_t) - (struct PSI_file_locker *locker, int rc); - -/** - Start a new stage, and implicitly end the previous stage. - @param key the key of the new stage - @param src_file the source file name - @param src_line the source line number - @return the new stage progress -*/ -typedef PSI_stage_progress* (*start_stage_v1_t) - (PSI_stage_key key, const char *src_file, int src_line); - -typedef PSI_stage_progress* (*get_current_stage_progress_v1_t)(void); - -/** End the current stage. */ -typedef void (*end_stage_v1_t) (void); - -/** - Get a statement instrumentation locker. - @param state data storage for the locker - @param key the statement instrumentation key - @param charset client character set - @return a statement locker, or NULL -*/ -typedef struct PSI_statement_locker* (*get_thread_statement_locker_v1_t) - (struct PSI_statement_locker_state_v1 *state, - PSI_statement_key key, const void *charset, PSI_sp_share *sp_share); - -/** - Refine a statement locker to a more specific key. - Note that only events declared mutable can be refined. - @param the statement locker for the current event - @param key the new key for the event - @sa PSI_FLAG_MUTABLE -*/ -typedef struct PSI_statement_locker* (*refine_statement_v1_t) - (struct PSI_statement_locker *locker, - PSI_statement_key key); - -/** - Start a new statement event. - @param locker the statement locker for this event - @param db the active database name for this statement - @param db_length the active database name length for this statement - @param src_file source file name - @param src_line source line number -*/ -typedef void (*start_statement_v1_t) - (struct PSI_statement_locker *locker, - const char *db, uint db_length, - const char *src_file, uint src_line); - -/** - Set the statement text for a statement event. - @param locker the current statement locker - @param text the statement text - @param text_len the statement text length -*/ -typedef void (*set_statement_text_v1_t) - (struct PSI_statement_locker *locker, - const char *text, uint text_len); - -/** - Set a statement event lock time. - @param locker the statement locker - @param lock_time the locked time, in microseconds -*/ -typedef void (*set_statement_lock_time_t) - (struct PSI_statement_locker *locker, ulonglong lock_time); - -/** - Set a statement event rows sent metric. - @param locker the statement locker - @param count the number of rows sent -*/ -typedef void (*set_statement_rows_sent_t) - (struct PSI_statement_locker *locker, ulonglong count); - -/** - Set a statement event rows examined metric. - @param locker the statement locker - @param count the number of rows examined -*/ -typedef void (*set_statement_rows_examined_t) - (struct PSI_statement_locker *locker, ulonglong count); - -/** - Increment a statement event "created tmp disk tables" metric. - @param locker the statement locker - @param count the metric increment value -*/ -typedef void (*inc_statement_created_tmp_disk_tables_t) - (struct PSI_statement_locker *locker, ulong count); - -/** - Increment a statement event "created tmp tables" metric. - @param locker the statement locker - @param count the metric increment value -*/ -typedef void (*inc_statement_created_tmp_tables_t) - (struct PSI_statement_locker *locker, ulong count); - -/** - Increment a statement event "select full join" metric. - @param locker the statement locker - @param count the metric increment value -*/ -typedef void (*inc_statement_select_full_join_t) - (struct PSI_statement_locker *locker, ulong count); - -/** - Increment a statement event "select full range join" metric. - @param locker the statement locker - @param count the metric increment value -*/ -typedef void (*inc_statement_select_full_range_join_t) - (struct PSI_statement_locker *locker, ulong count); - -/** - Increment a statement event "select range join" metric. - @param locker the statement locker - @param count the metric increment value -*/ -typedef void (*inc_statement_select_range_t) - (struct PSI_statement_locker *locker, ulong count); - -/** - Increment a statement event "select range check" metric. - @param locker the statement locker - @param count the metric increment value -*/ -typedef void (*inc_statement_select_range_check_t) - (struct PSI_statement_locker *locker, ulong count); - -/** - Increment a statement event "select scan" metric. - @param locker the statement locker - @param count the metric increment value -*/ -typedef void (*inc_statement_select_scan_t) - (struct PSI_statement_locker *locker, ulong count); - -/** - Increment a statement event "sort merge passes" metric. - @param locker the statement locker - @param count the metric increment value -*/ -typedef void (*inc_statement_sort_merge_passes_t) - (struct PSI_statement_locker *locker, ulong count); - -/** - Increment a statement event "sort range" metric. - @param locker the statement locker - @param count the metric increment value -*/ -typedef void (*inc_statement_sort_range_t) - (struct PSI_statement_locker *locker, ulong count); - -/** - Increment a statement event "sort rows" metric. - @param locker the statement locker - @param count the metric increment value -*/ -typedef void (*inc_statement_sort_rows_t) - (struct PSI_statement_locker *locker, ulong count); - -/** - Increment a statement event "sort scan" metric. - @param locker the statement locker - @param count the metric increment value -*/ -typedef void (*inc_statement_sort_scan_t) - (struct PSI_statement_locker *locker, ulong count); - -/** - Set a statement event "no index used" metric. - @param locker the statement locker - @param count the metric value -*/ -typedef void (*set_statement_no_index_used_t) - (struct PSI_statement_locker *locker); - -/** - Set a statement event "no good index used" metric. - @param locker the statement locker - @param count the metric value -*/ -typedef void (*set_statement_no_good_index_used_t) - (struct PSI_statement_locker *locker); - -/** - End a statement event. - @param locker the statement locker - @param stmt_da the statement diagnostics area. - @sa Diagnostics_area -*/ -typedef void (*end_statement_v1_t) - (struct PSI_statement_locker *locker, void *stmt_da); - -/** - Get a transaction instrumentation locker. - @param state data storage for the locker - @param xid the xid for this transaction - @param trxid the InnoDB transaction id - @param iso_level isolation level for this transaction - @param read_only true if transaction access mode is read-only - @param autocommit true if transaction is autocommit - @return a transaction locker, or NULL -*/ -typedef struct PSI_transaction_locker* (*get_thread_transaction_locker_v1_t) - (struct PSI_transaction_locker_state_v1 *state, const void *xid, - const ulonglong *trxid, int isolation_level, my_bool read_only, - my_bool autocommit); - -/** - Start a new transaction event. - @param locker the transaction locker for this event - @param src_file source file name - @param src_line source line number -*/ -typedef void (*start_transaction_v1_t) - (struct PSI_transaction_locker *locker, - const char *src_file, uint src_line); - -/** - Set the transaction xid. - @param locker the transaction locker for this event - @param xid the id of the XA transaction - #param xa_state is the state of the XA transaction -*/ -typedef void (*set_transaction_xid_v1_t) - (struct PSI_transaction_locker *locker, - const void *xid, int xa_state); - -/** - Set the state of the XA transaction. - @param locker the transaction locker for this event - @param xa_state the new state of the xa transaction -*/ -typedef void (*set_transaction_xa_state_v1_t) - (struct PSI_transaction_locker *locker, - int xa_state); - -/** - Set the transaction gtid. - @param locker the transaction locker for this event - @param sid the source id for the transaction, mapped from sidno - @param gtid_spec the gtid specifier for the transaction -*/ -typedef void (*set_transaction_gtid_v1_t) - (struct PSI_transaction_locker *locker, - const void *sid, const void *gtid_spec); - -/** - Set the transaction trx_id. - @param locker the transaction locker for this event - @param trxid the storage engine transaction ID -*/ -typedef void (*set_transaction_trxid_v1_t) - (struct PSI_transaction_locker *locker, - const ulonglong *trxid); - -/** - Increment a transaction event savepoint count. - @param locker the transaction locker - @param count the increment value -*/ -typedef void (*inc_transaction_savepoints_v1_t) - (struct PSI_transaction_locker *locker, ulong count); - -/** - Increment a transaction event rollback to savepoint count. - @param locker the transaction locker - @param count the increment value -*/ -typedef void (*inc_transaction_rollback_to_savepoint_v1_t) - (struct PSI_transaction_locker *locker, ulong count); - -/** - Increment a transaction event release savepoint count. - @param locker the transaction locker - @param count the increment value -*/ -typedef void (*inc_transaction_release_savepoint_v1_t) - (struct PSI_transaction_locker *locker, ulong count); - -/** - Commit or rollback the transaction. - @param locker the transaction locker for this event - @param commit true if transaction was committed, false if rolled back -*/ -typedef void (*end_transaction_v1_t) - (struct PSI_transaction_locker *locker, - my_bool commit); - -/** - Record a socket instrumentation start event. - @param locker a socket locker for the running thread - @param op socket operation to be performed - @param count the number of bytes requested, or 0 if not applicable - @param src_file the source file name - @param src_line the source line number -*/ -typedef struct PSI_socket_locker* (*start_socket_wait_v1_t) - (struct PSI_socket_locker_state_v1 *state, - struct PSI_socket *socket, - enum PSI_socket_operation op, - size_t count, - const char *src_file, uint src_line); - -/** - Record a socket instrumentation end event. - Note that for socket close operations, the instrumented socket handle - associated with the socket (which was provided to obtain a locker) - is invalid after this call. - @param locker a socket locker for the running thread - @param count the number of bytes actually used in the operation, - or 0 if not applicable, or -1 if the operation failed - @sa get_thread_socket_locker -*/ -typedef void (*end_socket_wait_v1_t) - (struct PSI_socket_locker *locker, size_t count); - -/** - Set the socket state for an instrumented socket. - @param socket the instrumented socket - @param state socket state - */ -typedef void (*set_socket_state_v1_t)(struct PSI_socket *socket, - enum PSI_socket_state state); - -/** - Set the socket info for an instrumented socket. - @param socket the instrumented socket - @param fd the socket descriptor - @param addr the socket ip address - @param addr_len length of socket ip address - @param thread_id associated thread id -*/ -typedef void (*set_socket_info_v1_t)(struct PSI_socket *socket, - const my_socket *fd, - const struct sockaddr *addr, - socklen_t addr_len); - -/** - Bind a socket to the thread that owns it. - @param socket instrumented socket -*/ -typedef void (*set_socket_thread_owner_v1_t)(struct PSI_socket *socket); - -/** - Get a prepare statement. - @param locker a statement locker for the running thread. -*/ -typedef PSI_prepared_stmt* (*create_prepared_stmt_v1_t) - (void *identity, uint stmt_id, PSI_statement_locker *locker, - const char *stmt_name, size_t stmt_name_length, - const char *name, size_t length); - -/** - destroy a prepare statement. - @param prepared_stmt prepared statement. -*/ -typedef void (*destroy_prepared_stmt_v1_t) - (PSI_prepared_stmt *prepared_stmt); - -/** - repreare a prepare statement. - @param prepared_stmt prepared statement. -*/ -typedef void (*reprepare_prepared_stmt_v1_t) - (PSI_prepared_stmt *prepared_stmt); - -/** - Record a prepare statement instrumentation execute event. - @param locker a statement locker for the running thread. - @param prepared_stmt prepared statement. -*/ -typedef void (*execute_prepared_stmt_v1_t) - (PSI_statement_locker *locker, PSI_prepared_stmt* prepared_stmt); - -/** - Get a digest locker for the current statement. - @param locker a statement locker for the running thread -*/ -typedef struct PSI_digest_locker * (*digest_start_v1_t) - (struct PSI_statement_locker *locker); - -/** - Add a token to the current digest instrumentation. - @param locker a digest locker for the current statement - @param token the lexical token to add - @param yylval the lexical token attributes -*/ -typedef void (*digest_end_v1_t) - (struct PSI_digest_locker *locker, const struct sql_digest_storage *digest); - -typedef PSI_sp_locker* (*start_sp_v1_t) - (struct PSI_sp_locker_state_v1 *state, struct PSI_sp_share* sp_share); - -typedef void (*end_sp_v1_t) - (struct PSI_sp_locker *locker); - -typedef void (*drop_sp_v1_t) - (uint object_type, - const char *schema_name, uint schema_name_length, - const char *object_name, uint object_name_length); - -/** - Acquire a sp share instrumentation. - @param type of stored program - @param schema name of stored program - @param name of stored program - @return a stored program share instrumentation, or NULL -*/ -typedef struct PSI_sp_share* (*get_sp_share_v1_t) - (uint object_type, - const char *schema_name, uint schema_name_length, - const char *object_name, uint object_name_length); - -/** - Release a stored program share. - @param info the stored program share to release -*/ -typedef void (*release_sp_share_v1_t)(struct PSI_sp_share *share); - -typedef PSI_metadata_lock* (*create_metadata_lock_v1_t) - (void *identity, - const MDL_key *key, - opaque_mdl_type mdl_type, - opaque_mdl_duration mdl_duration, - opaque_mdl_status mdl_status, - const char *src_file, - uint src_line); - -typedef void (*set_metadata_lock_status_v1_t)(PSI_metadata_lock *lock, - opaque_mdl_status mdl_status); - -typedef void (*destroy_metadata_lock_v1_t)(PSI_metadata_lock *lock); - -typedef struct PSI_metadata_locker* (*start_metadata_wait_v1_t) - (struct PSI_metadata_locker_state_v1 *state, - struct PSI_metadata_lock *mdl, - const char *src_file, uint src_line); - -typedef void (*end_metadata_wait_v1_t) - (struct PSI_metadata_locker *locker, int rc); - -/** - Stores an array of connection attributes - @param buffer char array of length encoded connection attributes - in network format - @param length length of the data in buffer - @param from_cs charset in which @c buffer is encoded - @return state - @retval non_0 attributes truncated - @retval 0 stored the attribute -*/ -typedef int (*set_thread_connect_attrs_v1_t)(const char *buffer, uint length, - const void *from_cs); - -/** - Performance Schema Interface, version 1. - @since PSI_VERSION_1 -*/ -struct PSI_v1 -{ - /** @sa register_mutex_v1_t. */ - register_mutex_v1_t register_mutex; - /** @sa register_rwlock_v1_t. */ - register_rwlock_v1_t register_rwlock; - /** @sa register_cond_v1_t. */ - register_cond_v1_t register_cond; - /** @sa register_thread_v1_t. */ - register_thread_v1_t register_thread; - /** @sa register_file_v1_t. */ - register_file_v1_t register_file; - /** @sa register_stage_v1_t. */ - register_stage_v1_t register_stage; - /** @sa register_statement_v1_t. */ - register_statement_v1_t register_statement; - /** @sa register_socket_v1_t. */ - register_socket_v1_t register_socket; - /** @sa init_mutex_v1_t. */ - init_mutex_v1_t init_mutex; - /** @sa destroy_mutex_v1_t. */ - destroy_mutex_v1_t destroy_mutex; - /** @sa init_rwlock_v1_t. */ - init_rwlock_v1_t init_rwlock; - /** @sa destroy_rwlock_v1_t. */ - destroy_rwlock_v1_t destroy_rwlock; - /** @sa init_cond_v1_t. */ - init_cond_v1_t init_cond; - /** @sa destroy_cond_v1_t. */ - destroy_cond_v1_t destroy_cond; - /** @sa init_socket_v1_t. */ - init_socket_v1_t init_socket; - /** @sa destroy_socket_v1_t. */ - destroy_socket_v1_t destroy_socket; - - /** @sa get_table_share_v1_t. */ - get_table_share_v1_t get_table_share; - /** @sa release_table_share_v1_t. */ - release_table_share_v1_t release_table_share; - /** @sa drop_table_share_v1_t. */ - drop_table_share_v1_t drop_table_share; - /** @sa open_table_v1_t. */ - open_table_v1_t open_table; - /** @sa unbind_table_v1_t. */ - unbind_table_v1_t unbind_table; - /** @sa rebind_table_v1_t. */ - rebind_table_v1_t rebind_table; - /** @sa close_table_v1_t. */ - close_table_v1_t close_table; - /** @sa create_file_v1_t. */ - create_file_v1_t create_file; - /** @sa spawn_thread_v1_t. */ - spawn_thread_v1_t spawn_thread; - /** @sa new_thread_v1_t. */ - new_thread_v1_t new_thread; - /** @sa set_thread_id_v1_t. */ - set_thread_id_v1_t set_thread_id; - /** @sa set_thread_THD_v1_t. */ - set_thread_THD_v1_t set_thread_THD; - /** @sa set_thread_os_id_v1_t. */ - set_thread_os_id_v1_t set_thread_os_id; - /** @sa get_thread_v1_t. */ - get_thread_v1_t get_thread; - /** @sa set_thread_user_v1_t. */ - set_thread_user_v1_t set_thread_user; - /** @sa set_thread_account_v1_t. */ - set_thread_account_v1_t set_thread_account; - /** @sa set_thread_db_v1_t. */ - set_thread_db_v1_t set_thread_db; - /** @sa set_thread_command_v1_t. */ - set_thread_command_v1_t set_thread_command; - /** @sa set_connection_type_v1_t. */ - set_connection_type_v1_t set_connection_type; - /** @sa set_thread_start_time_v1_t. */ - set_thread_start_time_v1_t set_thread_start_time; - /** @sa set_thread_state_v1_t. */ - set_thread_state_v1_t set_thread_state; - /** @sa set_thread_info_v1_t. */ - set_thread_info_v1_t set_thread_info; - /** @sa set_thread_v1_t. */ - set_thread_v1_t set_thread; - /** @sa delete_current_thread_v1_t. */ - delete_current_thread_v1_t delete_current_thread; - /** @sa delete_thread_v1_t. */ - delete_thread_v1_t delete_thread; - /** @sa get_thread_file_name_locker_v1_t. */ - get_thread_file_name_locker_v1_t get_thread_file_name_locker; - /** @sa get_thread_file_stream_locker_v1_t. */ - get_thread_file_stream_locker_v1_t get_thread_file_stream_locker; - /** @sa get_thread_file_descriptor_locker_v1_t. */ - get_thread_file_descriptor_locker_v1_t get_thread_file_descriptor_locker; - /** @sa unlock_mutex_v1_t. */ - unlock_mutex_v1_t unlock_mutex; - /** @sa unlock_rwlock_v1_t. */ - unlock_rwlock_v1_t unlock_rwlock; - /** @sa signal_cond_v1_t. */ - signal_cond_v1_t signal_cond; - /** @sa broadcast_cond_v1_t. */ - broadcast_cond_v1_t broadcast_cond; - /** @sa start_idle_wait_v1_t. */ - start_idle_wait_v1_t start_idle_wait; - /** @sa end_idle_wait_v1_t. */ - end_idle_wait_v1_t end_idle_wait; - /** @sa start_mutex_wait_v1_t. */ - start_mutex_wait_v1_t start_mutex_wait; - /** @sa end_mutex_wait_v1_t. */ - end_mutex_wait_v1_t end_mutex_wait; - /** @sa start_rwlock_rdwait_v1_t. */ - start_rwlock_rdwait_v1_t start_rwlock_rdwait; - /** @sa end_rwlock_rdwait_v1_t. */ - end_rwlock_rdwait_v1_t end_rwlock_rdwait; - /** @sa start_rwlock_wrwait_v1_t. */ - start_rwlock_wrwait_v1_t start_rwlock_wrwait; - /** @sa end_rwlock_wrwait_v1_t. */ - end_rwlock_wrwait_v1_t end_rwlock_wrwait; - /** @sa start_cond_wait_v1_t. */ - start_cond_wait_v1_t start_cond_wait; - /** @sa end_cond_wait_v1_t. */ - end_cond_wait_v1_t end_cond_wait; - /** @sa start_table_io_wait_v1_t. */ - start_table_io_wait_v1_t start_table_io_wait; - /** @sa end_table_io_wait_v1_t. */ - end_table_io_wait_v1_t end_table_io_wait; - /** @sa start_table_lock_wait_v1_t. */ - start_table_lock_wait_v1_t start_table_lock_wait; - /** @sa end_table_lock_wait_v1_t. */ - end_table_lock_wait_v1_t end_table_lock_wait; - /** @sa start_file_open_wait_v1_t. */ - start_file_open_wait_v1_t start_file_open_wait; - /** @sa end_file_open_wait_v1_t. */ - end_file_open_wait_v1_t end_file_open_wait; - /** @sa end_file_open_wait_and_bind_to_descriptor_v1_t. */ - end_file_open_wait_and_bind_to_descriptor_v1_t - end_file_open_wait_and_bind_to_descriptor; - /** @sa end_temp_file_open_wait_and_bind_to_descriptor_v1_t. */ - end_temp_file_open_wait_and_bind_to_descriptor_v1_t - end_temp_file_open_wait_and_bind_to_descriptor; - /** @sa start_file_wait_v1_t. */ - start_file_wait_v1_t start_file_wait; - /** @sa end_file_wait_v1_t. */ - end_file_wait_v1_t end_file_wait; - /** @sa start_file_close_wait_v1_t. */ - start_file_close_wait_v1_t start_file_close_wait; - /** @sa end_file_close_wait_v1_t. */ - end_file_close_wait_v1_t end_file_close_wait; - /** @sa start_stage_v1_t. */ - start_stage_v1_t start_stage; - /** @sa get_current_stage_progress_v1_t. */ - get_current_stage_progress_v1_t get_current_stage_progress; - /** @sa end_stage_v1_t. */ - end_stage_v1_t end_stage; - /** @sa get_thread_statement_locker_v1_t. */ - get_thread_statement_locker_v1_t get_thread_statement_locker; - /** @sa refine_statement_v1_t. */ - refine_statement_v1_t refine_statement; - /** @sa start_statement_v1_t. */ - start_statement_v1_t start_statement; - /** @sa set_statement_text_v1_t. */ - set_statement_text_v1_t set_statement_text; - /** @sa set_statement_lock_time_t. */ - set_statement_lock_time_t set_statement_lock_time; - /** @sa set_statement_rows_sent_t. */ - set_statement_rows_sent_t set_statement_rows_sent; - /** @sa set_statement_rows_examined_t. */ - set_statement_rows_examined_t set_statement_rows_examined; - /** @sa inc_statement_created_tmp_disk_tables. */ - inc_statement_created_tmp_disk_tables_t inc_statement_created_tmp_disk_tables; - /** @sa inc_statement_created_tmp_tables. */ - inc_statement_created_tmp_tables_t inc_statement_created_tmp_tables; - /** @sa inc_statement_select_full_join. */ - inc_statement_select_full_join_t inc_statement_select_full_join; - /** @sa inc_statement_select_full_range_join. */ - inc_statement_select_full_range_join_t inc_statement_select_full_range_join; - /** @sa inc_statement_select_range. */ - inc_statement_select_range_t inc_statement_select_range; - /** @sa inc_statement_select_range_check. */ - inc_statement_select_range_check_t inc_statement_select_range_check; - /** @sa inc_statement_select_scan. */ - inc_statement_select_scan_t inc_statement_select_scan; - /** @sa inc_statement_sort_merge_passes. */ - inc_statement_sort_merge_passes_t inc_statement_sort_merge_passes; - /** @sa inc_statement_sort_range. */ - inc_statement_sort_range_t inc_statement_sort_range; - /** @sa inc_statement_sort_rows. */ - inc_statement_sort_rows_t inc_statement_sort_rows; - /** @sa inc_statement_sort_scan. */ - inc_statement_sort_scan_t inc_statement_sort_scan; - /** @sa set_statement_no_index_used. */ - set_statement_no_index_used_t set_statement_no_index_used; - /** @sa set_statement_no_good_index_used. */ - set_statement_no_good_index_used_t set_statement_no_good_index_used; - /** @sa end_statement_v1_t. */ - end_statement_v1_t end_statement; - /** @sa get_thread_transaction_locker_v1_t. */ - get_thread_transaction_locker_v1_t get_thread_transaction_locker; - /** @sa start_transaction_v1_t. */ - start_transaction_v1_t start_transaction; - /** @sa set_transaction_xid_v1_t. */ - set_transaction_xid_v1_t set_transaction_xid; - /** @sa set_transaction_xa_state_v1_t. */ - set_transaction_xa_state_v1_t set_transaction_xa_state; - /** @sa set_transaction_gtid_v1_t. */ - set_transaction_gtid_v1_t set_transaction_gtid; - /** @sa set_transaction_trxid_v1_t. */ - set_transaction_trxid_v1_t set_transaction_trxid; - /** @sa inc_transaction_savepoints_v1_t. */ - inc_transaction_savepoints_v1_t inc_transaction_savepoints; - /** @sa inc_transaction_rollback_to_savepoint_v1_t. */ - inc_transaction_rollback_to_savepoint_v1_t inc_transaction_rollback_to_savepoint; - /** @sa inc_transaction_release_savepoint_v1_t. */ - inc_transaction_release_savepoint_v1_t inc_transaction_release_savepoint; - /** @sa end_transaction_v1_t. */ - end_transaction_v1_t end_transaction; - /** @sa start_socket_wait_v1_t. */ - start_socket_wait_v1_t start_socket_wait; - /** @sa end_socket_wait_v1_t. */ - end_socket_wait_v1_t end_socket_wait; - /** @sa set_socket_state_v1_t. */ - set_socket_state_v1_t set_socket_state; - /** @sa set_socket_info_v1_t. */ - set_socket_info_v1_t set_socket_info; - /** @sa set_socket_thread_owner_v1_t. */ - set_socket_thread_owner_v1_t set_socket_thread_owner; - /** @sa create_prepared_stmt_v1_t. */ - create_prepared_stmt_v1_t create_prepared_stmt; - /** @sa destroy_prepared_stmt_v1_t. */ - destroy_prepared_stmt_v1_t destroy_prepared_stmt; - /** @sa reprepare_prepared_stmt_v1_t. */ - reprepare_prepared_stmt_v1_t reprepare_prepared_stmt; - /** @sa execute_prepared_stmt_v1_t. */ - execute_prepared_stmt_v1_t execute_prepared_stmt; - /** @sa digest_start_v1_t. */ - digest_start_v1_t digest_start; - /** @sa digest_end_v1_t. */ - digest_end_v1_t digest_end; - /** @sa set_thread_connect_attrs_v1_t. */ - set_thread_connect_attrs_v1_t set_thread_connect_attrs; - /** @sa start_sp_v1_t. */ - start_sp_v1_t start_sp; - /** @sa start_sp_v1_t. */ - end_sp_v1_t end_sp; - /** @sa drop_sp_v1_t. */ - drop_sp_v1_t drop_sp; - /** @sa get_sp_share_v1_t. */ - get_sp_share_v1_t get_sp_share; - /** @sa release_sp_share_v1_t. */ - release_sp_share_v1_t release_sp_share; - /** @sa register_memory_v1_t. */ - register_memory_v1_t register_memory; - /** @sa memory_alloc_v1_t. */ - memory_alloc_v1_t memory_alloc; - /** @sa memory_realloc_v1_t. */ - memory_realloc_v1_t memory_realloc; - /** @sa memory_claim_v1_t. */ - memory_claim_v1_t memory_claim; - /** @sa memory_free_v1_t. */ - memory_free_v1_t memory_free; - - unlock_table_v1_t unlock_table; - - create_metadata_lock_v1_t create_metadata_lock; - set_metadata_lock_status_v1_t set_metadata_lock_status; - destroy_metadata_lock_v1_t destroy_metadata_lock; - - start_metadata_wait_v1_t start_metadata_wait; - end_metadata_wait_v1_t end_metadata_wait; -}; - -/** @} (end of group Group_PSI_v1) */ - -#endif /* HAVE_PSI_1 */ - -#ifdef USE_PSI_2 -#define HAVE_PSI_2 -#endif - -#ifdef HAVE_PSI_2 - -/** - @defgroup Group_PSI_v2 Application Binary Interface, version 2 - @ingroup Instrumentation_interface - @{ -*/ - -/** - Performance Schema Interface, version 2. - This is a placeholder, this interface is not defined yet. - @since PSI_VERSION_2 -*/ -struct PSI_v2 -{ - /** Placeholder */ - int placeholder; - /* ... extended interface ... */ -}; - -/** Placeholder */ -struct PSI_mutex_info_v2 -{ - /** Placeholder */ - int placeholder; -}; - -/** Placeholder */ -struct PSI_rwlock_info_v2 -{ - /** Placeholder */ - int placeholder; -}; - -/** Placeholder */ -struct PSI_cond_info_v2 -{ - /** Placeholder */ - int placeholder; -}; - -/** Placeholder */ -struct PSI_thread_info_v2 -{ - /** Placeholder */ - int placeholder; -}; - -/** Placeholder */ -struct PSI_file_info_v2 -{ - /** Placeholder */ - int placeholder; -}; - -/** Placeholder */ -struct PSI_stage_info_v2 -{ - /** Placeholder */ - int placeholder; -}; - -/** Placeholder */ -struct PSI_statement_info_v2 -{ - /** Placeholder */ - int placeholder; -}; - -/** Placeholder */ -struct PSI_transaction_info_v2 -{ - /** Placeholder */ - int placeholder; -}; - -/** Placeholder */ -struct PSI_idle_locker_state_v2 -{ - /** Placeholder */ - int placeholder; -}; - -/** Placeholder */ -struct PSI_mutex_locker_state_v2 -{ - /** Placeholder */ - int placeholder; -}; - -/** Placeholder */ -struct PSI_rwlock_locker_state_v2 -{ - /** Placeholder */ - int placeholder; -}; - -/** Placeholder */ -struct PSI_cond_locker_state_v2 -{ - /** Placeholder */ - int placeholder; -}; - -/** Placeholder */ -struct PSI_file_locker_state_v2 -{ - /** Placeholder */ - int placeholder; -}; - -/** Placeholder */ -struct PSI_statement_locker_state_v2 -{ - /** Placeholder */ - int placeholder; -}; - -/** Placeholder */ -struct PSI_transaction_locker_state_v2 -{ - /** Placeholder */ - int placeholder; -}; - -/** Placeholder */ -struct PSI_socket_locker_state_v2 -{ - /** Placeholder */ - int placeholder; -}; - -struct PSI_metadata_locker_state_v2 -{ - int placeholder; -}; - -/** @} (end of group Group_PSI_v2) */ - -#endif /* HAVE_PSI_2 */ - -/** - @typedef PSI - The instrumentation interface for the current version. - @sa PSI_CURRENT_VERSION -*/ - -/** - @typedef PSI_mutex_info - The mutex information structure for the current version. -*/ - -/** - @typedef PSI_rwlock_info - The rwlock information structure for the current version. -*/ - -/** - @typedef PSI_cond_info - The cond information structure for the current version. -*/ - -/** - @typedef PSI_thread_info - The thread information structure for the current version. -*/ - -/** - @typedef PSI_file_info - The file information structure for the current version. -*/ - -/* Export the required version */ -#ifdef USE_PSI_1 -typedef struct PSI_v1 PSI; -typedef struct PSI_mutex_info_v1 PSI_mutex_info; -typedef struct PSI_rwlock_info_v1 PSI_rwlock_info; -typedef struct PSI_cond_info_v1 PSI_cond_info; -typedef struct PSI_thread_info_v1 PSI_thread_info; -typedef struct PSI_file_info_v1 PSI_file_info; -typedef struct PSI_stage_info_v1 PSI_stage_info; -typedef struct PSI_statement_info_v1 PSI_statement_info; -typedef struct PSI_transaction_info_v1 PSI_transaction_info; -typedef struct PSI_socket_info_v1 PSI_socket_info; -typedef struct PSI_idle_locker_state_v1 PSI_idle_locker_state; -typedef struct PSI_mutex_locker_state_v1 PSI_mutex_locker_state; -typedef struct PSI_rwlock_locker_state_v1 PSI_rwlock_locker_state; -typedef struct PSI_cond_locker_state_v1 PSI_cond_locker_state; -typedef struct PSI_file_locker_state_v1 PSI_file_locker_state; -typedef struct PSI_statement_locker_state_v1 PSI_statement_locker_state; -typedef struct PSI_transaction_locker_state_v1 PSI_transaction_locker_state; -typedef struct PSI_socket_locker_state_v1 PSI_socket_locker_state; -typedef struct PSI_sp_locker_state_v1 PSI_sp_locker_state; -typedef struct PSI_metadata_locker_state_v1 PSI_metadata_locker_state; -#endif - -#ifdef USE_PSI_2 -typedef struct PSI_v2 PSI; -typedef struct PSI_mutex_info_v2 PSI_mutex_info; -typedef struct PSI_rwlock_info_v2 PSI_rwlock_info; -typedef struct PSI_cond_info_v2 PSI_cond_info; -typedef struct PSI_thread_info_v2 PSI_thread_info; -typedef struct PSI_file_info_v2 PSI_file_info; -typedef struct PSI_stage_info_v2 PSI_stage_info; -typedef struct PSI_statement_info_v2 PSI_statement_info; -typedef struct PSI_transaction_info_v2 PSI_transaction_info; -typedef struct PSI_socket_info_v2 PSI_socket_info; -typedef struct PSI_idle_locker_state_v2 PSI_idle_locker_state; -typedef struct PSI_mutex_locker_state_v2 PSI_mutex_locker_state; -typedef struct PSI_rwlock_locker_state_v2 PSI_rwlock_locker_state; -typedef struct PSI_cond_locker_state_v2 PSI_cond_locker_state; -typedef struct PSI_file_locker_state_v2 PSI_file_locker_state; -typedef struct PSI_statement_locker_state_v2 PSI_statement_locker_state; -typedef struct PSI_transaction_locker_state_v2 PSI_transaction_locker_state; -typedef struct PSI_socket_locker_state_v2 PSI_socket_locker_state; -typedef struct PSI_sp_locker_state_v2 PSI_sp_locker_state; -typedef struct PSI_metadata_locker_state_v2 PSI_metadata_locker_state; -#endif - -#else /* HAVE_PSI_INTERFACE */ - -/** - Dummy structure, used to declare PSI_server when no instrumentation - is available. - The content does not matter, since PSI_server will be NULL. -*/ -struct PSI_none -{ - int opaque; -}; -typedef struct PSI_none PSI; - -/** - Stage instrument information. - @since PSI_VERSION_1 - This structure is used to register an instrumented stage. -*/ -struct PSI_stage_info_none -{ - /** Unused stage key. */ - unsigned int m_key; - /** The name of the stage instrument. */ - const char *m_name; - /** Unused stage flags. */ - int m_flags; -}; - -/** - The stage instrumentation has to co exist with the legacy - THD::set_proc_info instrumentation. - To avoid duplication of the instrumentation in the server, - the common PSI_stage_info structure is used, - so we export it here, even when not building - with HAVE_PSI_INTERFACE. -*/ -typedef struct PSI_stage_info_none PSI_stage_info; - -#endif /* HAVE_PSI_INTERFACE */ - -extern MYSQL_PLUGIN_IMPORT PSI *PSI_server; - -/* - Allow to override PSI_XXX_CALL at compile time - with more efficient implementations, if available. - If nothing better is available, - make a dynamic call using the PSI_server function pointer. -*/ - -#define PSI_DYNAMIC_CALL(M) PSI_server->M - -/** @} */ - -C_MODE_END -#endif /* MYSQL_PERFORMANCE_SCHEMA_INTERFACE_H */ - diff --git a/vendor/mysql/include/mysql/psi/psi_base.h b/vendor/mysql/include/mysql/psi/psi_base.h deleted file mode 100644 index 94cb5c9f51..0000000000 --- a/vendor/mysql/include/mysql/psi/psi_base.h +++ /dev/null @@ -1,155 +0,0 @@ -/* Copyright (c) 2008, 2016, Oracle and/or its affiliates. All rights reserved. - - This program is free software; you can redistribute it and/or modify - it under the terms of the GNU General Public License as published by - the Free Software Foundation; version 2 of the License. - - This program is distributed in the hope that it will be useful, - but WITHOUT ANY WARRANTY; without even the implied warranty of - MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - GNU General Public License for more details. - - You should have received a copy of the GNU General Public License - along with this program; if not, write to the Free Software Foundation, - 51 Franklin Street, Suite 500, Boston, MA 02110-1335 USA */ - -#ifndef MYSQL_PSI_BASE_H -#define MYSQL_PSI_BASE_H - -#ifdef __cplusplus -extern "C" { -#endif - -/** - @file mysql/psi/psi_base.h - Performance schema instrumentation interface. - - @defgroup Instrumentation_interface Instrumentation Interface - @ingroup Performance_schema - @{ -*/ - -#define PSI_INSTRUMENT_ME 0 - -#define PSI_NOT_INSTRUMENTED 0 - -/** - Global flag. - This flag indicate that an instrumentation point is a global variable, - or a singleton. -*/ -#define PSI_FLAG_GLOBAL (1 << 0) - -/** - Mutable flag. - This flag indicate that an instrumentation point is a general placeholder, - that can mutate into a more specific instrumentation point. -*/ -#define PSI_FLAG_MUTABLE (1 << 1) - -#define PSI_FLAG_THREAD (1 << 2) - -/** - Stage progress flag. - This flag apply to the stage instruments only. - It indicates the instrumentation provides progress data. -*/ -#define PSI_FLAG_STAGE_PROGRESS (1 << 3) - -/** - Shared Exclusive flag. - Indicates that rwlock support the shared exclusive state. -*/ -#define PSI_RWLOCK_FLAG_SX (1 << 4) - -/** - Transferable flag. - This flag indicate that an instrumented object can - be created by a thread and destroyed by another thread. -*/ -#define PSI_FLAG_TRANSFER (1 << 5) - -/** - Volatility flag. - This flag indicate that an instrumented object - has a volatility (life cycle) comparable - to the volatility of a session. -*/ -#define PSI_FLAG_VOLATILITY_SESSION (1 << 6) - -#ifdef HAVE_PSI_INTERFACE - -/** - @def PSI_VERSION_1 - Performance Schema Interface number for version 1. - This version is supported. -*/ -#define PSI_VERSION_1 1 - -/** - @def PSI_VERSION_2 - Performance Schema Interface number for version 2. - This version is not implemented, it's a placeholder. -*/ -#define PSI_VERSION_2 2 - -/** - @def PSI_CURRENT_VERSION - Performance Schema Interface number for the most recent version. - The most current version is @c PSI_VERSION_1 -*/ -#define PSI_CURRENT_VERSION 1 - -/** - @def USE_PSI_1 - Define USE_PSI_1 to use the interface version 1. -*/ - -/** - @def USE_PSI_2 - Define USE_PSI_2 to use the interface version 2. -*/ - -/** - @def HAVE_PSI_1 - Define HAVE_PSI_1 if the interface version 1 needs to be compiled in. -*/ - -/** - @def HAVE_PSI_2 - Define HAVE_PSI_2 if the interface version 2 needs to be compiled in. -*/ - -#ifndef USE_PSI_2 -#ifndef USE_PSI_1 -#define USE_PSI_1 -#endif -#endif - -#ifdef USE_PSI_1 -#define HAVE_PSI_1 -#endif - -#ifdef USE_PSI_2 -#define HAVE_PSI_2 -#endif - -/* - Allow to override PSI_XXX_CALL at compile time - with more efficient implementations, if available. - If nothing better is available, - make a dynamic call using the PSI_server function pointer. -*/ - -#define PSI_DYNAMIC_CALL(M) PSI_server->M - -#endif /* HAVE_PSI_INTERFACE */ - -/** @} */ - -#ifdef __cplusplus -} -#endif - -#endif /* MYSQL_PSI_BASE_H */ - diff --git a/vendor/mysql/include/mysql/psi/psi_memory.h b/vendor/mysql/include/mysql/psi/psi_memory.h deleted file mode 100644 index 725b3ed77d..0000000000 --- a/vendor/mysql/include/mysql/psi/psi_memory.h +++ /dev/null @@ -1,155 +0,0 @@ -/* Copyright (c) 2013, 2015, Oracle and/or its affiliates. All rights reserved. - - This program is free software; you can redistribute it and/or modify - it under the terms of the GNU General Public License as published by - the Free Software Foundation; version 2 of the License. - - This program is distributed in the hope that it will be useful, - but WITHOUT ANY WARRANTY; without even the implied warranty of - MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - GNU General Public License for more details. - - You should have received a copy of the GNU General Public License - along with this program; if not, write to the Free Software Foundation, - 51 Franklin Street, Suite 500, Boston, MA 02110-1335 USA */ - -#ifndef MYSQL_PSI_MEMORY_H -#define MYSQL_PSI_MEMORY_H - -#include "psi_base.h" - -#ifdef __cplusplus -extern "C" { -#endif - -/** - @file mysql/psi/psi_memory.h - Performance schema instrumentation interface. - - @defgroup Instrumentation_interface Instrumentation Interface - @ingroup Performance_schema - @{ -*/ - -#ifdef HAVE_PSI_INTERFACE -#ifndef DISABLE_ALL_PSI -#ifndef DISABLE_PSI_MEMORY -#define HAVE_PSI_MEMORY_INTERFACE -#endif /* DISABLE_PSI_MEMORY */ -#endif /* DISABLE_ALL_PSI */ -#endif /* HAVE_PSI_INTERFACE */ - -struct PSI_thread; - -/** - Instrumented memory key. - To instrument memory, a memory key must be obtained using @c register_memory. - Using a zero key always disable the instrumentation. -*/ -typedef unsigned int PSI_memory_key; - -#ifdef HAVE_PSI_1 - -/** - @defgroup Group_PSI_v1 Application Binary Interface, version 1 - @ingroup Instrumentation_interface - @{ -*/ - -/** - Memory instrument information. - @since PSI_VERSION_1 - This structure is used to register instrumented memory. -*/ -struct PSI_memory_info_v1 -{ - /** Pointer to the key assigned to the registered memory. */ - PSI_memory_key *m_key; - /** The name of the memory instrument to register. */ - const char *m_name; - /** - The flags of the socket instrument to register. - @sa PSI_FLAG_GLOBAL - */ - int m_flags; -}; -typedef struct PSI_memory_info_v1 PSI_memory_info_v1; - -/** - Memory registration API. - @param category a category name (typically a plugin name) - @param info an array of memory info to register - @param count the size of the info array -*/ -typedef void (*register_memory_v1_t) - (const char *category, struct PSI_memory_info_v1 *info, int count); - -/** - Instrument memory allocation. - @param key the memory instrument key - @param size the size of memory allocated - @param[out] owner the memory owner - @return the effective memory instrument key -*/ -typedef PSI_memory_key (*memory_alloc_v1_t) - (PSI_memory_key key, size_t size, struct PSI_thread ** owner); - -/** - Instrument memory re allocation. - @param key the memory instrument key - @param old_size the size of memory previously allocated - @param new_size the size of memory re allocated - @param[in, out] owner the memory owner - @return the effective memory instrument key -*/ -typedef PSI_memory_key (*memory_realloc_v1_t) - (PSI_memory_key key, size_t old_size, size_t new_size, struct PSI_thread ** owner); - -/** - Instrument memory claim. - @param key the memory instrument key - @param size the size of memory allocated - @param[in, out] owner the memory owner - @return the effective memory instrument key -*/ -typedef PSI_memory_key (*memory_claim_v1_t) - (PSI_memory_key key, size_t size, struct PSI_thread ** owner); - -/** - Instrument memory free. - @param key the memory instrument key - @param size the size of memory allocated - @param owner the memory owner -*/ -typedef void (*memory_free_v1_t) - (PSI_memory_key key, size_t size, struct PSI_thread * owner); - -/** @} (end of group Group_PSI_v1) */ - -#endif /* HAVE_PSI_1 */ - -#ifdef HAVE_PSI_2 -struct PSI_memory_info_v2 -{ - int placeholder; -}; - -#endif /* HAVE_PSI_2 */ - -#ifdef USE_PSI_1 -typedef struct PSI_memory_info_v1 PSI_memory_info; -#endif - -#ifdef USE_PSI_2 -typedef struct PSI_memory_info_v2 PSI_memory_info; -#endif - -/** @} (end of group Instrumentation_interface) */ - -#ifdef __cplusplus -} -#endif - - -#endif /* MYSQL_PSI_MEMORY_H */ - diff --git a/vendor/mysql/include/mysql/service_my_snprintf.h b/vendor/mysql/include/mysql/service_my_snprintf.h deleted file mode 100644 index d734ae155e..0000000000 --- a/vendor/mysql/include/mysql/service_my_snprintf.h +++ /dev/null @@ -1,101 +0,0 @@ -#ifndef MYSQL_SERVICE_MY_SNPRINTF_INCLUDED -#define MYSQL_SERVICE_MY_SNPRINTF_INCLUDED -/* Copyright (c) 2009, 2015, Oracle and/or its affiliates. All rights reserved. - - This program is free software; you can redistribute it and/or modify - it under the terms of the GNU General Public License as published by - the Free Software Foundation; version 2 of the License. - - This program is distributed in the hope that it will be useful, - but WITHOUT ANY WARRANTY; without even the implied warranty of - MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - GNU General Public License for more details. - - You should have received a copy of the GNU General Public License - along with this program; if not, write to the Free Software - Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA */ - -/** - @file - my_snprintf service - - Portable and limited vsnprintf() implementation. - - This is a portable, limited vsnprintf() implementation, with some - extra features. "Portable" means that it'll produce identical result - on all platforms (for example, on Windows and Linux system printf %e - formats the exponent differently, on different systems %p either - prints leading 0x or not, %s may accept null pointer or crash on - it). "Limited" means that it does not support all the C89 features. - But it supports few extensions, not in any standard. - - my_vsnprintf(to, n, fmt, ap) - - @param[out] to A buffer to store the result in - @param[in] n Store up to n-1 characters, followed by an end 0 - @param[in] fmt printf-like format string - @param[in] ap Arguments - - @return a number of bytes written to a buffer *excluding* terminating '\0' - - @post - The syntax of a format string is generally the same: - % - where everithing but the format is optional. - - Three one-character flags are recognized: - '0' has the standard zero-padding semantics; - '-' is parsed, but silently ignored; - '`' (backtick) is only supported for strings (%s) and means that the - string will be quoted according to MySQL identifier quoting rules. - - Both and can be specified as numbers or '*'. - If an asterisk is used, an argument of type int is consumed. - - can be 'l', 'll', or 'z'. - - Supported formats are 's' (null pointer is accepted, printed as - "(null)"), 'b' (extension, see below), 'c', 'd', 'i', 'u', 'x', 'o', - 'X', 'p' (works as 0x%x). - - Standard syntax for positional arguments $n is supported. - - Extensions: - - Flag '`' (backtick): see above. - - Format 'b': binary buffer, prints exactly bytes from the - argument, without stopping at '\0'. -*/ - -#ifdef __cplusplus -extern "C" { -#endif - -#ifndef MYSQL_ABI_CHECK -#include -#include -#endif - -extern struct my_snprintf_service_st { - size_t (*my_snprintf_type)(char*, size_t, const char*, ...); - size_t (*my_vsnprintf_type)(char *, size_t, const char*, va_list); -} *my_snprintf_service; - -#ifdef MYSQL_DYNAMIC_PLUGIN - -#define my_vsnprintf my_snprintf_service->my_vsnprintf_type -#define my_snprintf my_snprintf_service->my_snprintf_type - -#else - -size_t my_snprintf(char* to, size_t n, const char* fmt, ...); -size_t my_vsnprintf(char *to, size_t n, const char* fmt, va_list ap); - -#endif - -#ifdef __cplusplus -} -#endif - -#endif /* #define MYSQL_SERVICE_MY_SNPRINTF_INCLUDED */ diff --git a/vendor/mysql/include/mysql/service_mysql_alloc.h b/vendor/mysql/include/mysql/service_mysql_alloc.h deleted file mode 100644 index a43a169daf..0000000000 --- a/vendor/mysql/include/mysql/service_mysql_alloc.h +++ /dev/null @@ -1,81 +0,0 @@ -/* Copyright (c) 2012, 2015, Oracle and/or its affiliates. All rights reserved. - - This program is free software; you can redistribute it and/or modify - it under the terms of the GNU General Public License as published by - the Free Software Foundation; version 2 of the License. - - This program is distributed in the hope that it will be useful, - but WITHOUT ANY WARRANTY; without even the implied warranty of - MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - GNU General Public License for more details. - - You should have received a copy of the GNU General Public License - along with this program; if not, write to the Free Software - Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA */ - -#ifndef MYSQL_SERVICE_MYSQL_ALLOC_INCLUDED -#define MYSQL_SERVICE_MYSQL_ALLOC_INCLUDED - -#ifndef MYSQL_ABI_CHECK -#include -#endif - -/* PSI_memory_key */ -#include "mysql/psi/psi_memory.h" - -#ifdef __cplusplus -extern "C" { -#endif - -/* myf */ -typedef int myf_t; - -typedef void * (*mysql_malloc_t)(PSI_memory_key key, size_t size, myf_t flags); -typedef void * (*mysql_realloc_t)(PSI_memory_key key, void *ptr, size_t size, myf_t flags); -typedef void (*mysql_claim_t)(void *ptr); -typedef void (*mysql_free_t)(void *ptr); -typedef void * (*my_memdup_t)(PSI_memory_key key, const void *from, size_t length, myf_t flags); -typedef char * (*my_strdup_t)(PSI_memory_key key, const char *from, myf_t flags); -typedef char * (*my_strndup_t)(PSI_memory_key key, const char *from, size_t length, myf_t flags); - -struct mysql_malloc_service_st -{ - mysql_malloc_t mysql_malloc; - mysql_realloc_t mysql_realloc; - mysql_claim_t mysql_claim; - mysql_free_t mysql_free; - my_memdup_t my_memdup; - my_strdup_t my_strdup; - my_strndup_t my_strndup; -}; - -extern struct mysql_malloc_service_st *mysql_malloc_service; - -#ifdef MYSQL_DYNAMIC_PLUGIN - -#define my_malloc mysql_malloc_service->mysql_malloc -#define my_realloc mysql_malloc_service->mysql_realloc -#define my_claim mysql_malloc_service->mysql_claim -#define my_free mysql_malloc_service->mysql_free -#define my_memdup mysql_malloc_service->my_memdup -#define my_strdup mysql_malloc_service->my_strdup -#define my_strndup mysql_malloc_service->my_strndup - -#else - -extern void * my_malloc(PSI_memory_key key, size_t size, myf_t flags); -extern void * my_realloc(PSI_memory_key key, void *ptr, size_t size, myf_t flags); -extern void my_claim(void *ptr); -extern void my_free(void *ptr); -extern void * my_memdup(PSI_memory_key key, const void *from, size_t length, myf_t flags); -extern char * my_strdup(PSI_memory_key key, const char *from, myf_t flags); -extern char * my_strndup(PSI_memory_key key, const char *from, size_t length, myf_t flags); - -#endif - -#ifdef __cplusplus -} -#endif - -#endif - diff --git a/vendor/mysql/include/mysql/udf_registration_types.h b/vendor/mysql/include/mysql/udf_registration_types.h new file mode 100644 index 0000000000..5ab1425de7 --- /dev/null +++ b/vendor/mysql/include/mysql/udf_registration_types.h @@ -0,0 +1,91 @@ +/* Copyright (c) 2017, 2024, Oracle and/or its affiliates. + +This program is free software; you can redistribute it and/or modify +it under the terms of the GNU General Public License, version 2.0, +as published by the Free Software Foundation. + +This program is designed to work with certain software (including +but not limited to OpenSSL) that is licensed under separate terms, +as designated in a particular file or component or in included license +documentation. The authors of MySQL hereby grant you an additional +permission to link the program and your derivative works with the +separately licensed software that they have either included with +the program or referenced in the documentation. + +Without limiting anything contained in the foregoing, this file, +which is part of C Driver for MySQL (Connector/C), is also subject to the +Universal FOSS Exception, version 1.0, a copy of which can be found at +http://oss.oracle.com/licenses/universal-foss-exception. + +This program is distributed in the hope that it will be useful, +but WITHOUT ANY WARRANTY; without even the implied warranty of +MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +GNU General Public License, version 2.0, for more details. + +You should have received a copy of the GNU General Public License +along with this program; if not, write to the Free Software +Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA */ + +#ifndef UDF_REGISTRATION_TYPES_H +#define UDF_REGISTRATION_TYPES_H + +#ifndef MYSQL_ABI_CHECK +#include +#endif + +/** +Type of the user defined function return slot and arguments +*/ +enum Item_result { + INVALID_RESULT = -1, /** not valid for UDFs */ + STRING_RESULT = 0, /** char * */ + REAL_RESULT, /** double */ + INT_RESULT, /** long long */ + ROW_RESULT, /** not valid for UDFs */ + DECIMAL_RESULT /** char *, to be converted to/from a decimal */ +}; + +typedef struct UDF_ARGS { + unsigned int arg_count; /**< Number of arguments */ + enum Item_result *arg_type; /**< Pointer to item_results */ + char **args; /**< Pointer to argument */ + unsigned long *lengths; /**< Length of string arguments */ + char *maybe_null; /**< Set to 1 for all maybe_null args */ + char **attributes; /**< Pointer to attribute name */ + unsigned long *attribute_lengths; /**< Length of attribute arguments */ + void *extension; +} UDF_ARGS; + +/** +Information about the result of a user defined function + +@todo add a notion for determinism of the UDF. + +@sa Item_udf_func::update_used_tables() +*/ +typedef struct UDF_INIT { + bool maybe_null; /** 1 if function can return NULL */ + unsigned int decimals; /** for real functions */ + unsigned long max_length; /** For string functions */ + char *ptr; /** free pointer for function data */ + bool const_item; /** 1 if function always returns the same value */ + void *extension; +} UDF_INIT; + +enum Item_udftype { UDFTYPE_FUNCTION = 1, UDFTYPE_AGGREGATE }; + +typedef void (*Udf_func_clear)(UDF_INIT *, unsigned char *, unsigned char *); +typedef void (*Udf_func_add)(UDF_INIT *, UDF_ARGS *, unsigned char *, + unsigned char *); +typedef void (*Udf_func_deinit)(UDF_INIT *); +typedef bool (*Udf_func_init)(UDF_INIT *, UDF_ARGS *, char *); +typedef void (*Udf_func_any)(void); +typedef double (*Udf_func_double)(UDF_INIT *, UDF_ARGS *, unsigned char *, + unsigned char *); +typedef long long (*Udf_func_longlong)(UDF_INIT *, UDF_ARGS *, unsigned char *, + unsigned char *); +typedef char *(*Udf_func_string)(UDF_INIT *, UDF_ARGS *, char *, + unsigned long *, unsigned char *, + unsigned char *); + +#endif /* UDF_REGISTRATION_TYPES_H */ diff --git a/vendor/mysql/include/mysql_com.h b/vendor/mysql/include/mysql_com.h index fd30b8439e..505da5ffb9 100644 --- a/vendor/mysql/include/mysql_com.h +++ b/vendor/mysql/include/mysql_com.h @@ -1,36 +1,73 @@ -/* Copyright (c) 2000, 2015, Oracle and/or its affiliates. All rights reserved. +/* Copyright (c) 2000, 2024, Oracle and/or its affiliates. This program is free software; you can redistribute it and/or modify - it under the terms of the GNU General Public License as published by - the Free Software Foundation; version 2 of the License. + it under the terms of the GNU General Public License, version 2.0, + as published by the Free Software Foundation. + + This program is designed to work with certain software (including + but not limited to OpenSSL) that is licensed under separate terms, + as designated in a particular file or component or in included license + documentation. The authors of MySQL hereby grant you an additional + permission to link the program and your derivative works with the + separately licensed software that they have either included with + the program or referenced in the documentation. + + Without limiting anything contained in the foregoing, this file, + which is part of C Driver for MySQL (Connector/C), is also subject to the + Universal FOSS Exception, version 1.0, a copy of which can be found at + http://oss.oracle.com/licenses/universal-foss-exception. This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - GNU General Public License for more details. + GNU General Public License, version 2.0, for more details. You should have received a copy of the GNU General Public License along with this program; if not, write to the Free Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA */ -/* -** Common definition between mysql server & client +/** + @file include/mysql_com.h + Common definition between mysql server & client. */ #ifndef _mysql_com_h #define _mysql_com_h -#include "binary_log_types.h" + +#ifndef MYSQL_ABI_CHECK +#include +#include +#endif + #include "my_command.h" -#define HOSTNAME_LENGTH 60 +#include "my_compress.h" + +/* + We need a definition for my_socket. On the client, already provides + it, but on the server side, we need to get it from a header. +*/ +#ifndef my_socket_defined +#include "my_io.h" +#include "mysql/components/services/bits/my_io_bits.h" +#endif + +#ifndef MYSQL_ABI_CHECK +#include +#endif + #define SYSTEM_CHARSET_MBMAXLEN 3 #define FILENAME_CHARSET_MBMAXLEN 5 -#define NAME_CHAR_LEN 64 /* Field/table name length */ +#define NAME_CHAR_LEN 64 /**< Field/table name length */ +#define PARTITION_EXPR_CHAR_LEN \ + 2048 /**< Maximum expression length in chars \ + */ #define USERNAME_CHAR_LENGTH 32 #define USERNAME_CHAR_LENGTH_STR "32" #ifndef NAME_LEN -#define NAME_LEN (NAME_CHAR_LEN*SYSTEM_CHARSET_MBMAXLEN) +#define NAME_LEN (NAME_CHAR_LEN * SYSTEM_CHARSET_MBMAXLEN) #endif -#define USERNAME_LENGTH (USERNAME_CHAR_LENGTH*SYSTEM_CHARSET_MBMAXLEN) +#define USERNAME_LENGTH (USERNAME_CHAR_LENGTH * SYSTEM_CHARSET_MBMAXLEN) +#define CONNECT_STRING_MAXLEN 1024 #define MYSQL_AUTODETECT_CHARSET_NAME "auto" @@ -38,333 +75,867 @@ #define SQLSTATE_LENGTH 5 /* + In FIDO terminology, relying party is the server where required services are + running. Relying party ID is unique name given to server. +*/ +#define RELYING_PARTY_ID_LENGTH 255 + +/* Length of random salt sent during fido registration */ +#define CHALLENGE_LENGTH 32 + +/* Maximum authentication factors server supports */ +#define MAX_AUTH_FACTORS 3 +/** Maximum length of comments + + pre 5.6: 60 characters */ -#define TABLE_COMMENT_INLINE_MAXLEN 180 /* pre 6.0: 60 characters */ +#define TABLE_COMMENT_INLINE_MAXLEN 180 #define TABLE_COMMENT_MAXLEN 2048 #define COLUMN_COMMENT_MAXLEN 1024 #define INDEX_COMMENT_MAXLEN 1024 #define TABLE_PARTITION_COMMENT_MAXLEN 1024 +#define TABLESPACE_COMMENT_MAXLEN 2048 -/* +/** Maximum length of protocol packet. - OK packet length limit also restricted to this value as any length greater - than this value will have first byte of OK packet to be 254 thus does not - provide a means to identify if this is OK or EOF packet. + @ref page_protocol_basic_ok_packet length limit also restricted to this value + as any length greater than this value will have first byte of + @ref page_protocol_basic_ok_packet to be 254 thus does not + provide a means to identify if this is @ref page_protocol_basic_ok_packet or + @ref page_protocol_basic_eof_packet. */ -#define MAX_PACKET_LENGTH (256L*256L*256L-1) +#define MAX_PACKET_LENGTH (256L * 256L * 256L - 1) -/* - USER_HOST_BUFF_SIZE -- length of string buffer, that is enough to contain - username and hostname parts of the user identifier with trailing zero in - MySQL standard format: - user_name_part@host_name_part\0 -*/ -#define USER_HOST_BUFF_SIZE HOSTNAME_LENGTH + USERNAME_LENGTH + 2 - -#define LOCAL_HOST "localhost" +#define LOCAL_HOST "localhost" #define LOCAL_HOST_NAMEDPIPE "." - #if defined(_WIN32) #define MYSQL_NAMEDPIPE "MySQL" #define MYSQL_SERVICENAME "MySQL" #endif /* _WIN32 */ -/* The length of the header part for each generated column in the .frm file. */ +/** The length of the header part for each generated column in the .frm file.*/ #define FRM_GCOL_HEADER_SIZE 4 -/* +/** Maximum length of the expression statement defined for generated columns. */ #define GENERATED_COLUMN_EXPRESSION_MAXLEN 65535 - FRM_GCOL_HEADER_SIZE -/* +/** Length of random string sent by server on handshake; this is also length of obfuscated password, received from client */ #define SCRAMBLE_LENGTH 20 #define AUTH_PLUGIN_DATA_PART_1_LENGTH 8 -/* length of password stored in the db: new passwords are preceeded with '*' */ -#define SCRAMBLED_PASSWORD_CHAR_LENGTH (SCRAMBLE_LENGTH*2+1) +/** length of password stored in the db: new passwords are preceded with '*'*/ +#define SCRAMBLED_PASSWORD_CHAR_LENGTH (SCRAMBLE_LENGTH * 2 + 1) + +/** + @defgroup group_cs_column_definition_flags Column Definition Flags + @ingroup group_cs + @brief Values for the flags bitmask used by ::Send_field:flags -#define NOT_NULL_FLAG 1 /* Field can't be NULL */ -#define PRI_KEY_FLAG 2 /* Field is part of a primary key */ -#define UNIQUE_KEY_FLAG 4 /* Field is part of a unique key */ -#define MULTIPLE_KEY_FLAG 8 /* Field is part of a key */ -#define BLOB_FLAG 16 /* Field is a blob */ -#define UNSIGNED_FLAG 32 /* Field is unsigned */ -#define ZEROFILL_FLAG 64 /* Field is zerofill */ -#define BINARY_FLAG 128 /* Field is binary */ + Currently need to fit into 32 bits. + + Each bit represents an optional feature of the protocol. + + Both the client and the server are sending these. + + The intersection of the two determines what optional parts of the + protocol will be used. +*/ + +/** + @addtogroup group_cs_column_definition_flags + @{ +*/ + +#define NOT_NULL_FLAG 1 /**< Field can't be NULL */ +#define PRI_KEY_FLAG 2 /**< Field is part of a primary key */ +#define UNIQUE_KEY_FLAG 4 /**< Field is part of a unique key */ +#define MULTIPLE_KEY_FLAG 8 /**< Field is part of a key */ +#define BLOB_FLAG 16 /**< Field is a blob */ +#define UNSIGNED_FLAG 32 /**< Field is unsigned */ +#define ZEROFILL_FLAG 64 /**< Field is zerofill */ +#define BINARY_FLAG 128 /**< Field is binary */ /* The following are only sent to new clients */ -#define ENUM_FLAG 256 /* field is an enum */ -#define AUTO_INCREMENT_FLAG 512 /* field is a autoincrement field */ -#define TIMESTAMP_FLAG 1024 /* Field is a timestamp */ -#define SET_FLAG 2048 /* field is a set */ -#define NO_DEFAULT_VALUE_FLAG 4096 /* Field doesn't have default value */ -#define ON_UPDATE_NOW_FLAG 8192 /* Field is set to NOW on UPDATE */ -#define NUM_FLAG 32768 /* Field is num (for clients) */ -#define PART_KEY_FLAG 16384 /* Intern; Part of some key */ -#define GROUP_FLAG 32768 /* Intern: Group field */ -#define UNIQUE_FLAG 65536 /* Intern: Used by sql_yacc */ -#define BINCMP_FLAG 131072 /* Intern: Used by sql_yacc */ -#define GET_FIXED_FIELDS_FLAG (1 << 18) /* Used to get fields in item tree */ -#define FIELD_IN_PART_FUNC_FLAG (1 << 19)/* Field part of partition func */ +#define ENUM_FLAG 256 /**< field is an enum */ +#define AUTO_INCREMENT_FLAG 512 /**< field is a autoincrement field */ +#define TIMESTAMP_FLAG 1024 /**< Field is a timestamp */ +#define SET_FLAG 2048 /**< field is a set */ +#define NO_DEFAULT_VALUE_FLAG 4096 /**< Field doesn't have default value */ +#define ON_UPDATE_NOW_FLAG 8192 /**< Field is set to NOW on UPDATE */ +#define NUM_FLAG 32768 /**< Field is num (for clients) */ +#define PART_KEY_FLAG 16384 /**< Intern; Part of some key */ +#define GROUP_FLAG 32768 /**< Intern: Group field */ +#define UNIQUE_FLAG 65536 /**< Intern: Used by sql_yacc */ +#define BINCMP_FLAG 131072 /**< Intern: Used by sql_yacc */ +#define GET_FIXED_FIELDS_FLAG \ + (1 << 18) /**< Used to get fields in item tree \ + */ +#define FIELD_IN_PART_FUNC_FLAG (1 << 19) /**< Field part of partition func */ /** Intern: Field in TABLE object for new version of altered table, which participates in a newly added index. */ #define FIELD_IN_ADD_INDEX (1 << 20) -#define FIELD_IS_RENAMED (1<< 21) /* Intern: Field is being renamed */ -#define FIELD_FLAGS_STORAGE_MEDIA 22 /* Field storage media, bit 22-23 */ +#define FIELD_IS_RENAMED (1 << 21) /**< Intern: Field is being renamed */ +#define FIELD_FLAGS_STORAGE_MEDIA 22 /**< Field storage media, bit 22-23 */ #define FIELD_FLAGS_STORAGE_MEDIA_MASK (3 << FIELD_FLAGS_STORAGE_MEDIA) -#define FIELD_FLAGS_COLUMN_FORMAT 24 /* Field column format, bit 24-25 */ +#define FIELD_FLAGS_COLUMN_FORMAT 24 /**< Field column format, bit 24-25 */ #define FIELD_FLAGS_COLUMN_FORMAT_MASK (3 << FIELD_FLAGS_COLUMN_FORMAT) -#define FIELD_IS_DROPPED (1<< 26) /* Intern: Field is being dropped */ -#define EXPLICIT_NULL_FLAG (1<< 27) /* Field is explicitly specified as - NULL by the user */ - -#define REFRESH_GRANT 1 /* Refresh grant tables */ -#define REFRESH_LOG 2 /* Start on new log file */ -#define REFRESH_TABLES 4 /* close all tables */ -#define REFRESH_HOSTS 8 /* Flush host cache */ -#define REFRESH_STATUS 16 /* Flush status variables */ -#define REFRESH_THREADS 32 /* Flush thread cache */ -#define REFRESH_SLAVE 64 /* Reset master info and restart slave - thread */ -#define REFRESH_MASTER 128 /* Remove all bin logs in the index - and truncate the index */ -#define REFRESH_ERROR_LOG 256 /* Rotate only the erorr log */ -#define REFRESH_ENGINE_LOG 512 /* Flush all storage engine logs */ -#define REFRESH_BINARY_LOG 1024 /* Flush the binary log */ -#define REFRESH_RELAY_LOG 2048 /* Flush the relay log */ -#define REFRESH_GENERAL_LOG 4096 /* Flush the general log */ -#define REFRESH_SLOW_LOG 8192 /* Flush the slow query log */ - -/* The following can't be set with mysql_refresh() */ -#define REFRESH_READ_LOCK 16384 /* Lock tables for read */ -#define REFRESH_FAST 32768 /* Intern flag */ - -/* RESET (remove all queries) from query cache */ -#define REFRESH_QUERY_CACHE 65536 -#define REFRESH_QUERY_CACHE_FREE 0x20000L /* pack query cache */ -#define REFRESH_DES_KEY_FILE 0x40000L -#define REFRESH_USER_RESOURCES 0x80000L -#define REFRESH_FOR_EXPORT 0x100000L /* FLUSH TABLES ... FOR EXPORT */ -#define REFRESH_OPTIMIZER_COSTS 0x200000L /* FLUSH OPTIMIZER_COSTS */ - -#define CLIENT_LONG_PASSWORD 1 /* new more secure passwords */ -#define CLIENT_FOUND_ROWS 2 /* Found instead of affected rows */ -#define CLIENT_LONG_FLAG 4 /* Get all column flags */ -#define CLIENT_CONNECT_WITH_DB 8 /* One can specify db on connect */ -#define CLIENT_NO_SCHEMA 16 /* Don't allow database.table.column */ -#define CLIENT_COMPRESS 32 /* Can use compression protocol */ -#define CLIENT_ODBC 64 /* Odbc client */ -#define CLIENT_LOCAL_FILES 128 /* Can use LOAD DATA LOCAL */ -#define CLIENT_IGNORE_SPACE 256 /* Ignore spaces before '(' */ -#define CLIENT_PROTOCOL_41 512 /* New 4.1 protocol */ -#define CLIENT_INTERACTIVE 1024 /* This is an interactive client */ -#define CLIENT_SSL 2048 /* Switch to SSL after handshake */ -#define CLIENT_IGNORE_SIGPIPE 4096 /* IGNORE sigpipes */ -#define CLIENT_TRANSACTIONS 8192 /* Client knows about transactions */ -#define CLIENT_RESERVED 16384 /* Old flag for 4.1 protocol */ -#define CLIENT_RESERVED2 32768 /* Old flag for 4.1 authentication */ -#define CLIENT_MULTI_STATEMENTS (1UL << 16) /* Enable/disable multi-stmt support */ -#define CLIENT_MULTI_RESULTS (1UL << 17) /* Enable/disable multi-results */ -#define CLIENT_PS_MULTI_RESULTS (1UL << 18) /* Multi-results in PS-protocol */ - -#define CLIENT_PLUGIN_AUTH (1UL << 19) /* Client supports plugin authentication */ -#define CLIENT_CONNECT_ATTRS (1UL << 20) /* Client supports connection attributes */ - -/* Enable authentication response packet to be larger than 255 bytes. */ +#define FIELD_IS_DROPPED (1 << 26) /**< Intern: Field is being dropped */ +#define EXPLICIT_NULL_FLAG \ + (1 << 27) /**< Field is explicitly specified as \ + NULL by the user */ +/* 1 << 28 is unused. */ + +/** Field will not be loaded in secondary engine. */ +#define NOT_SECONDARY_FLAG (1 << 29) +/** Field is explicitly marked as invisible by the user. */ +#define FIELD_IS_INVISIBLE (1 << 30) + +/** @}*/ + +/** + @defgroup group_cs_com_refresh_flags COM_REFRESH Flags + @ingroup group_cs + + @brief Values for the `sub_command` in ::COM_REFRESH + + Currently the protocol carries only 8 bits of these flags. + + The rest (8-end) are used only internally in the server. +*/ + +/** + @addtogroup group_cs_com_refresh_flags + @{ +*/ + +#define REFRESH_GRANT 1 /**< Refresh grant tables, FLUSH PRIVILEGES */ +#define REFRESH_LOG 2 /**< Start on new log file, FLUSH LOGS */ +#define REFRESH_TABLES 4 /**< close all tables, FLUSH TABLES */ +#define UNUSED_8 \ + 8 /**< Previously REFRESH_HOSTS but not used anymore. Use TRUNCATE TABLE \ + performance_schema.host_cache instead */ +#define REFRESH_STATUS 16 /**< Flush status variables, FLUSH STATUS */ +#define UNUSED_32 32 /**< Removed. Used to be flush thread cache */ +#define REFRESH_REPLICA \ + 64 /**< Reset source info and restart replica \ + thread, RESET REPLICA */ + +#define REFRESH_SOURCE \ + 128 /**< Remove all bin logs in the index \ + and truncate the index. Also resets \ + GTID information. Command: \ + RESET BINARY LOGS AND GTIDS */ + +#define REFRESH_ERROR_LOG 256 /**< Rotate only the error log */ +#define REFRESH_ENGINE_LOG 512 /**< Flush all storage engine logs */ +#define REFRESH_BINARY_LOG 1024 /**< Flush the binary log */ +#define REFRESH_RELAY_LOG 2048 /**< Flush the relay log */ +#define REFRESH_GENERAL_LOG 4096 /**< Flush the general log */ +#define REFRESH_SLOW_LOG 8192 /**< Flush the slow query log */ +#define REFRESH_READ_LOCK 16384 /**< Lock tables for read. */ +/** + Wait for an impending flush before closing the tables. + + @sa REFRESH_READ_LOCK, handle_reload_request, close_cached_tables +*/ +#define REFRESH_FAST 32768 +#define REFRESH_USER_RESOURCES \ + 0x80000L /** FLUSH RESOURCES. @sa ::reset_mqh \ + */ +#define REFRESH_FOR_EXPORT 0x100000L /** FLUSH TABLES ... FOR EXPORT */ +#define REFRESH_OPTIMIZER_COSTS 0x200000L /** FLUSH OPTIMIZER_COSTS */ +#define REFRESH_PERSIST 0x400000L /** RESET PERSIST */ + +/** @}*/ + +/** + @defgroup group_cs_capabilities_flags Capabilities Flags + @ingroup group_cs + + @brief Values for the capabilities flag bitmask used by the MySQL protocol + + Currently need to fit into 32 bits. + + Each bit represents an optional feature of the protocol. + + Both the client and the server are sending these. + + The intersection of the two determines whast optional parts of the + protocol will be used. +*/ + +/** + @addtogroup group_cs_capabilities_flags + @{ +*/ + +/** + Use the improved version of Old Password Authentication. + + Not used. + + @note Assumed to be set since 4.1.1. +*/ +#define CLIENT_LONG_PASSWORD 1 +/** + Send found rows instead of affected rows in @ref + page_protocol_basic_eof_packet +*/ +#define CLIENT_FOUND_ROWS 2 +/** + @brief Get all column flags + + Longer flags in Protocol::ColumnDefinition320. + + @todo Reference Protocol::ColumnDefinition320 + + Server + ------ + + Supports longer flags. + + Client + ------ + + Expects longer flags. +*/ +#define CLIENT_LONG_FLAG 4 +/** + Database (schema) name can be specified on connect in Handshake Response + Packet. + + @todo Reference Handshake Response Packet. + + Server + ------ + + Supports schema-name in Handshake Response Packet. + + Client + ------ + + Handshake Response Packet contains a schema-name. + + @sa send_client_reply_packet() +*/ +#define CLIENT_CONNECT_WITH_DB 8 +#define CLIENT_NO_SCHEMA \ + 16 /**< DEPRECATED: Don't allow database.table.column */ +/** + Compression protocol supported. + + @todo Reference Compression + + Server + ------ + + Supports compression. + + Client + ------ + + Switches to Compression compressed protocol after successful authentication. +*/ +#define CLIENT_COMPRESS 32 +/** + Special handling of ODBC behavior. + + @note No special behavior since 3.22. +*/ +#define CLIENT_ODBC 64 +/** + Can use LOAD DATA LOCAL. + + Server + ------ + + Enables the LOCAL INFILE request of LOAD DATA|XML. + + Client + ------ + + Will handle LOCAL INFILE request. +*/ +#define CLIENT_LOCAL_FILES 128 +/** + Ignore spaces before '(' + + Server + ------ + + Parser can ignore spaces before '('. + + Client + ------ + + Let the parser ignore spaces before '('. +*/ +#define CLIENT_IGNORE_SPACE 256 +/** + New 4.1 protocol + + @todo Reference the new 4.1 protocol + + Server + ------ + + Supports the 4.1 protocol. + + Client + ------ + + Uses the 4.1 protocol. + + @note this value was CLIENT_CHANGE_USER in 3.22, unused in 4.0 +*/ +#define CLIENT_PROTOCOL_41 512 +/** + This is an interactive client + + Use @ref System_variables::net_wait_timeout + versus @ref System_variables::net_interactive_timeout. + + Server + ------ + + Supports interactive and noninteractive clients. + + Client + ------ + + Client is interactive. + + @sa mysql_real_connect() +*/ +#define CLIENT_INTERACTIVE 1024 +/** + Use SSL encryption for the session + + @todo Reference SSL + + Server + ------ + + Supports SSL + + Client + ------ + + Switch to SSL after sending the capability-flags. +*/ +#define CLIENT_SSL 2048 +/** + Client only flag. Not used. + + Client + ------ + + Do not issue SIGPIPE if network failures occur (libmysqlclient only). + + @sa mysql_real_connect() +*/ +#define CLIENT_IGNORE_SIGPIPE 4096 +/** + Client knows about transactions + + Server + ------ + + Can send status flags in @ref page_protocol_basic_ok_packet / + @ref page_protocol_basic_eof_packet. + + Client + ------ + + Expects status flags in @ref page_protocol_basic_ok_packet / + @ref page_protocol_basic_eof_packet. + + @note This flag is optional in 3.23, but always set by the server since 4.0. + @sa send_server_handshake_packet(), parse_client_handshake_packet(), + net_send_ok(), net_send_eof() +*/ +#define CLIENT_TRANSACTIONS 8192 +#define CLIENT_RESERVED 16384 /**< DEPRECATED: Old flag for 4.1 protocol */ +#define CLIENT_RESERVED2 \ + 32768 /**< DEPRECATED: Old flag for 4.1 authentication \ + CLIENT_SECURE_CONNECTION */ +/** + Enable/disable multi-stmt support + + Also sets @ref CLIENT_MULTI_RESULTS. Currently not checked anywhere. + + Server + ------ + + Can handle multiple statements per COM_QUERY and COM_STMT_PREPARE. + + Client + ------- + + May send multiple statements per COM_QUERY and COM_STMT_PREPARE. + + @note Was named ::CLIENT_MULTI_QUERIES in 4.1.0, renamed later. + + Requires + -------- + + ::CLIENT_PROTOCOL_41 + + @todo Reference COM_QUERY and COM_STMT_PREPARE +*/ +#define CLIENT_MULTI_STATEMENTS (1UL << 16) +/** + Enable/disable multi-results + + Server + ------ + + Can send multiple resultsets for COM_QUERY. + Error if the server needs to send them and client + does not support them. + + Client + ------- + + Can handle multiple resultsets for COM_QUERY. + + Requires + -------- + + ::CLIENT_PROTOCOL_41 + + @sa mysql_execute_command(), sp_head::MULTI_RESULTS +*/ +#define CLIENT_MULTI_RESULTS (1UL << 17) +/** + Multi-results and OUT parameters in PS-protocol. + + Server + ------ + + Can send multiple resultsets for COM_STMT_EXECUTE. + + Client + ------ + + Can handle multiple resultsets for COM_STMT_EXECUTE. + + Requires + -------- + + ::CLIENT_PROTOCOL_41 + + @todo Reference COM_STMT_EXECUTE and PS-protocol + + @sa Protocol_binary::send_out_parameters +*/ +#define CLIENT_PS_MULTI_RESULTS (1UL << 18) + +/** + Client supports plugin authentication + + Server + ------ + + Sends extra data in Initial Handshake Packet and supports the pluggable + authentication protocol. + + Client + ------ + + Supports authentication plugins. + + Requires + -------- + + ::CLIENT_PROTOCOL_41 + + @todo Reference plugin authentication, Initial Handshake Packet, + Authentication plugins + + @sa send_change_user_packet(), send_client_reply_packet(), run_plugin_auth(), + parse_com_change_user_packet(), parse_client_handshake_packet() +*/ +#define CLIENT_PLUGIN_AUTH (1UL << 19) +/** + Client supports connection attributes + + Server + ------ + + Permits connection attributes in Protocol::HandshakeResponse41. + + Client + ------ + + Sends connection attributes in Protocol::HandshakeResponse41. + + @todo Reference Protocol::HandshakeResponse41 + + @sa send_client_connect_attrs(), read_client_connect_attrs() +*/ +#define CLIENT_CONNECT_ATTRS (1UL << 20) + +/** + Enable authentication response packet to be larger than 255 bytes. + + When the ability to change default plugin require that the initial password + field in the Protocol::HandshakeResponse41 paclet can be of arbitrary size. + However, the 4.1 client-server protocol limits the length of the + auth-data-field sent from client to server to 255 bytes. + The solution is to change the type of the field to a true length encoded + string and indicate the protocol change + with this client capability flag. + + Server + ------ + + Understands length-encoded integer for auth response data in + Protocol::HandshakeResponse41. + + Client + ------ + + Length of auth response data in Protocol::HandshakeResponse41 + is a length-encoded integer. + + @todo Reference Protocol::HandshakeResponse41 + + @note The flag was introduced in 5.6.6, but had the wrong value. + + @sa send_client_reply_packet(), parse_client_handshake_packet(), + get_56_lenc_string(), get_41_lenc_string() +*/ #define CLIENT_PLUGIN_AUTH_LENENC_CLIENT_DATA (1UL << 21) -/* Don't close the connection for a connection with expired password. */ +/** + Don't close the connection for a user account with expired password. + + Server + ------ + + Announces support for expired password extension. + + Client + ------ + + Can handle expired passwords. + + @todo Reference expired password + + @sa MYSQL_OPT_CAN_HANDLE_EXPIRED_PASSWORDS, disconnect_on_expired_password + ACL_USER::password_expired, check_password_lifetime(), acl_authenticate() +*/ #define CLIENT_CAN_HANDLE_EXPIRED_PASSWORDS (1UL << 22) /** Capable of handling server state change information. Its a hint to the - server to include the state change information in Ok packet. + server to include the state change information in + @ref page_protocol_basic_ok_packet. + + Server + ------ + Can set ::SERVER_SESSION_STATE_CHANGED in the ::SERVER_STATUS_flags_enum + and send @ref sect_protocol_basic_ok_packet_sessinfo in a + @ref page_protocol_basic_ok_packet. + + Client + ------ + + Expects the server to send @ref sect_protocol_basic_ok_packet_sessinfo in + a @ref page_protocol_basic_ok_packet. + + @sa enum_session_state_type, read_ok_ex(), net_send_ok(), Session_tracker, + State_tracker */ #define CLIENT_SESSION_TRACK (1UL << 23) -/* Client no longer needs EOF packet */ -#define CLIENT_DEPRECATE_EOF (1UL << 24) +/** + Client no longer needs @ref page_protocol_basic_eof_packet and will + use @ref page_protocol_basic_ok_packet instead. + @sa net_send_ok() -#define CLIENT_SSL_VERIFY_SERVER_CERT (1UL << 30) -#define CLIENT_REMEMBER_OPTIONS (1UL << 31) + Server + ------ -#ifdef HAVE_COMPRESS -#define CAN_CLIENT_COMPRESS CLIENT_COMPRESS -#else -#define CAN_CLIENT_COMPRESS 0 -#endif + Can send OK after a Text Resultset. -/* Gather all possible capabilites (flags) supported by the server */ -#define CLIENT_ALL_FLAGS (CLIENT_LONG_PASSWORD \ - | CLIENT_FOUND_ROWS \ - | CLIENT_LONG_FLAG \ - | CLIENT_CONNECT_WITH_DB \ - | CLIENT_NO_SCHEMA \ - | CLIENT_COMPRESS \ - | CLIENT_ODBC \ - | CLIENT_LOCAL_FILES \ - | CLIENT_IGNORE_SPACE \ - | CLIENT_PROTOCOL_41 \ - | CLIENT_INTERACTIVE \ - | CLIENT_SSL \ - | CLIENT_IGNORE_SIGPIPE \ - | CLIENT_TRANSACTIONS \ - | CLIENT_RESERVED \ - | CLIENT_RESERVED2 \ - | CLIENT_MULTI_STATEMENTS \ - | CLIENT_MULTI_RESULTS \ - | CLIENT_PS_MULTI_RESULTS \ - | CLIENT_SSL_VERIFY_SERVER_CERT \ - | CLIENT_REMEMBER_OPTIONS \ - | CLIENT_PLUGIN_AUTH \ - | CLIENT_CONNECT_ATTRS \ - | CLIENT_PLUGIN_AUTH_LENENC_CLIENT_DATA \ - | CLIENT_CAN_HANDLE_EXPIRED_PASSWORDS \ - | CLIENT_SESSION_TRACK \ - | CLIENT_DEPRECATE_EOF \ -) + Client + ------ -/* - Switch off the flags that are optional and depending on build flags - If any of the optional flags is supported by the build it will be switched - on before sending to the client during the connection handshake. + Expects an @ref page_protocol_basic_ok_packet (instead of + @ref page_protocol_basic_eof_packet) after the resultset rows of a + Text Resultset. + + Background + ---------- + + To support ::CLIENT_SESSION_TRACK, additional information must be sent after + all successful commands. Although the @ref page_protocol_basic_ok_packet is + extensible, the @ref page_protocol_basic_eof_packet is not due to the overlap + of its bytes with the content of the Text Resultset Row. + + Therefore, the @ref page_protocol_basic_eof_packet in the + Text Resultset is replaced with an @ref page_protocol_basic_ok_packet. + @ref page_protocol_basic_eof_packet is deprecated as of MySQL 5.7.5. + + @todo Reference Text Resultset + + @sa cli_safe_read_with_ok(), read_ok_ex(), net_send_ok(), net_send_eof() */ -#define CLIENT_BASIC_FLAGS (((CLIENT_ALL_FLAGS & ~CLIENT_SSL) \ - & ~CLIENT_COMPRESS) \ - & ~CLIENT_SSL_VERIFY_SERVER_CERT) +#define CLIENT_DEPRECATE_EOF (1UL << 24) /** - Is raised when a multi-statement transaction - has been started, either explicitly, by means - of BEGIN or COMMIT AND CHAIN, or - implicitly, by the first transactional - statement, when autocommit=off. + The client can handle optional metadata information in the resultset. */ -#define SERVER_STATUS_IN_TRANS 1 -#define SERVER_STATUS_AUTOCOMMIT 2 /* Server in auto_commit mode */ -#define SERVER_MORE_RESULTS_EXISTS 8 /* Multi query - next query exists */ -#define SERVER_QUERY_NO_GOOD_INDEX_USED 16 -#define SERVER_QUERY_NO_INDEX_USED 32 +#define CLIENT_OPTIONAL_RESULTSET_METADATA (1UL << 25) + /** - The server was able to fulfill the clients request and opened a - read-only non-scrollable cursor for a query. This flag comes - in reply to COM_STMT_EXECUTE and COM_STMT_FETCH commands. + Compression protocol extended to support zstd compression method + + This capability flag is used to send zstd compression level between + client and server provided both client and server are enabled with + this flag. + + Server + ------ + Server sets this flag when global variable protocol-compression-algorithms + has zstd in its list of supported values. + + Client + ------ + Client sets this flag when it is configured to use zstd compression method. + */ -#define SERVER_STATUS_CURSOR_EXISTS 64 +#define CLIENT_ZSTD_COMPRESSION_ALGORITHM (1UL << 26) + /** - This flag is sent when a read-only cursor is exhausted, in reply to - COM_STMT_FETCH command. + Support optional extension for query parameters into the @ref + page_protocol_com_query and @ref page_protocol_com_stmt_execute packets. + + Server + ------ + + Expects an optional part containing the query parameter set(s). Executes the + query for each set of parameters or returns an error if more than 1 set of + parameters is sent and the server can't execute it. + + Client + ------ + + Can send the optional part containing the query parameter set(s). */ -#define SERVER_STATUS_LAST_ROW_SENT 128 -#define SERVER_STATUS_DB_DROPPED 256 /* A database was dropped */ -#define SERVER_STATUS_NO_BACKSLASH_ESCAPES 512 +#define CLIENT_QUERY_ATTRIBUTES (1UL << 27) + /** - Sent to the client if after a prepared statement reprepare - we discovered that the new statement returns a different - number of result set columns. + Support Multi factor authentication. + + Server + ------ + Server sends AuthNextFactor packet after every nth factor authentication + method succeeds, except the last factor authentication. + + Client + ------ + Client reads AuthNextFactor packet sent by server and initiates next factor + authentication method. */ -#define SERVER_STATUS_METADATA_CHANGED 1024 -#define SERVER_QUERY_WAS_SLOW 2048 +#define MULTI_FACTOR_AUTHENTICATION (1UL << 28) /** - To mark ResultSet containing output parameter values. + This flag will be reserved to extend the 32bit capabilities structure to + 64bits. */ -#define SERVER_PS_OUT_PARAMS 4096 +#define CLIENT_CAPABILITY_EXTENSION (1UL << 29) /** - Set at the same time as SERVER_STATUS_IN_TRANS if the started - multi-statement transaction is a read-only transaction. Cleared - when the transaction commits or aborts. Since this flag is sent - to clients in OK and EOF packets, the flag indicates the - transaction status at the end of command execution. + Verify server certificate. + + Client only flag. + + @deprecated in favor of --ssl-mode. */ -#define SERVER_STATUS_IN_TRANS_READONLY 8192 +#define CLIENT_SSL_VERIFY_SERVER_CERT (1UL << 30) /** - This status flag, when on, implies that one of the state information has - changed on the server because of the execution of the last statement. + Don't reset the options after an unsuccessful connect + + Client only flag. + + Typically passed via ::mysql_real_connect() 's client_flag parameter. + + @sa mysql_real_connect() */ -#define SERVER_SESSION_STATE_CHANGED (1UL << 14) +#define CLIENT_REMEMBER_OPTIONS (1UL << 31) +/** @}*/ + +/** a compatibility alias for CLIENT_COMPRESS */ +#define CAN_CLIENT_COMPRESS CLIENT_COMPRESS + +/** Gather all possible capabilities (flags) supported by the server */ +#define CLIENT_ALL_FLAGS \ + (CLIENT_LONG_PASSWORD | CLIENT_FOUND_ROWS | CLIENT_LONG_FLAG | \ + CLIENT_CONNECT_WITH_DB | CLIENT_NO_SCHEMA | CLIENT_COMPRESS | CLIENT_ODBC | \ + CLIENT_LOCAL_FILES | CLIENT_IGNORE_SPACE | CLIENT_PROTOCOL_41 | \ + CLIENT_INTERACTIVE | CLIENT_SSL | CLIENT_IGNORE_SIGPIPE | \ + CLIENT_TRANSACTIONS | CLIENT_RESERVED | CLIENT_RESERVED2 | \ + CLIENT_MULTI_STATEMENTS | CLIENT_MULTI_RESULTS | CLIENT_PS_MULTI_RESULTS | \ + CLIENT_SSL_VERIFY_SERVER_CERT | CLIENT_REMEMBER_OPTIONS | \ + CLIENT_PLUGIN_AUTH | CLIENT_CONNECT_ATTRS | \ + CLIENT_PLUGIN_AUTH_LENENC_CLIENT_DATA | \ + CLIENT_CAN_HANDLE_EXPIRED_PASSWORDS | CLIENT_SESSION_TRACK | \ + CLIENT_DEPRECATE_EOF | CLIENT_OPTIONAL_RESULTSET_METADATA | \ + CLIENT_ZSTD_COMPRESSION_ALGORITHM | CLIENT_QUERY_ATTRIBUTES | \ + MULTI_FACTOR_AUTHENTICATION) + +/** + Switch off from ::CLIENT_ALL_FLAGS the flags that are optional and + depending on build flags. + If any of the optional flags is supported by the build it will be switched + on before sending to the client during the connection handshake. +*/ +#define CLIENT_BASIC_FLAGS \ + (CLIENT_ALL_FLAGS & \ + ~(CLIENT_SSL | CLIENT_COMPRESS | CLIENT_SSL_VERIFY_SERVER_CERT | \ + CLIENT_ZSTD_COMPRESSION_ALGORITHM)) + +/** The status flags are a bit-field */ +enum SERVER_STATUS_flags_enum { + /** + Is raised when a multi-statement transaction + has been started, either explicitly, by means + of BEGIN or COMMIT AND CHAIN, or + implicitly, by the first transactional + statement, when autocommit=off. + */ + SERVER_STATUS_IN_TRANS = 1, + SERVER_STATUS_AUTOCOMMIT = 2, /**< Server in auto_commit mode */ + SERVER_MORE_RESULTS_EXISTS = 8, /**< Multi query - next query exists */ + SERVER_QUERY_NO_GOOD_INDEX_USED = 16, + SERVER_QUERY_NO_INDEX_USED = 32, + /** + The server was able to fulfill the clients request and opened a + read-only non-scrollable cursor for a query. This flag comes + in reply to COM_STMT_EXECUTE and COM_STMT_FETCH commands. + Used by Binary Protocol Resultset to signal that COM_STMT_FETCH + must be used to fetch the row-data. + @todo Refify "Binary Protocol Resultset" and "COM_STMT_FETCH". + */ + SERVER_STATUS_CURSOR_EXISTS = 64, + /** + This flag is sent when a read-only cursor is exhausted, in reply to + COM_STMT_FETCH command. + */ + SERVER_STATUS_LAST_ROW_SENT = 128, + SERVER_STATUS_DB_DROPPED = 256, /**< A database was dropped */ + SERVER_STATUS_NO_BACKSLASH_ESCAPES = 512, + /** + Sent to the client if after a prepared statement reprepare + we discovered that the new statement returns a different + number of result set columns. + */ + SERVER_STATUS_METADATA_CHANGED = 1024, + SERVER_QUERY_WAS_SLOW = 2048, + /** + To mark ResultSet containing output parameter values. + */ + SERVER_PS_OUT_PARAMS = 4096, + + /** + Set at the same time as SERVER_STATUS_IN_TRANS if the started + multi-statement transaction is a read-only transaction. Cleared + when the transaction commits or aborts. Since this flag is sent + to clients in OK and EOF packets, the flag indicates the + transaction status at the end of command execution. + */ + SERVER_STATUS_IN_TRANS_READONLY = 8192, + + /** + This status flag, when on, implies that one of the state information has + changed on the server because of the execution of the last statement. + */ + SERVER_SESSION_STATE_CHANGED = (1UL << 14) +}; /** Server status flags that must be cleared when starting execution of a new SQL statement. Flags from this set are only added to the - current server status by the execution engine, but - never removed -- the execution engine expects them + current server status by the execution engine, but + never removed -- the execution engine expects them to disappear automagically by the next command. */ -#define SERVER_STATUS_CLEAR_SET (SERVER_QUERY_NO_GOOD_INDEX_USED| \ - SERVER_QUERY_NO_INDEX_USED|\ - SERVER_MORE_RESULTS_EXISTS|\ - SERVER_STATUS_METADATA_CHANGED |\ - SERVER_QUERY_WAS_SLOW |\ - SERVER_STATUS_DB_DROPPED |\ - SERVER_STATUS_CURSOR_EXISTS|\ - SERVER_STATUS_LAST_ROW_SENT|\ - SERVER_SESSION_STATE_CHANGED) - -#define MYSQL_ERRMSG_SIZE 512 -#define NET_READ_TIMEOUT 30 /* Timeout on read */ -#define NET_WRITE_TIMEOUT 60 /* Timeout on write */ -#define NET_WAIT_TIMEOUT 8*60*60 /* Wait for new query */ - -#define ONLY_KILL_QUERY 1 - - -struct st_vio; /* Only C */ -typedef struct st_vio Vio; - -#define MAX_TINYINT_WIDTH 3 /* Max width for a TINY w.o. sign */ -#define MAX_SMALLINT_WIDTH 5 /* Max width for a SHORT w.o. sign */ -#define MAX_MEDIUMINT_WIDTH 8 /* Max width for a INT24 w.o. sign */ -#define MAX_INT_WIDTH 10 /* Max width for a LONG w.o. sign */ -#define MAX_BIGINT_WIDTH 20 /* Max width for a LONGLONG */ -#define MAX_CHAR_WIDTH 255 /* Max length for a CHAR colum */ -#define MAX_BLOB_WIDTH 16777216 /* Default width for blob */ - -typedef struct st_net { - Vio *vio; - unsigned char *buff,*buff_end,*write_pos,*read_pos; - my_socket fd; /* For Perl DBI/dbd */ - /* - The following variable is set if we are doing several queries in one +#define SERVER_STATUS_CLEAR_SET \ + (SERVER_QUERY_NO_GOOD_INDEX_USED | SERVER_QUERY_NO_INDEX_USED | \ + SERVER_MORE_RESULTS_EXISTS | SERVER_STATUS_METADATA_CHANGED | \ + SERVER_QUERY_WAS_SLOW | SERVER_STATUS_DB_DROPPED | \ + SERVER_STATUS_CURSOR_EXISTS | SERVER_STATUS_LAST_ROW_SENT | \ + SERVER_SESSION_STATE_CHANGED) + +/** Max length of a error message. Should be kept in sync with ::ERRMSGSIZE. */ +#define MYSQL_ERRMSG_SIZE 512 +#define NET_READ_TIMEOUT 30 /**< Timeout on read */ +#define NET_WRITE_TIMEOUT 60 /**< Timeout on write */ +#define NET_WAIT_TIMEOUT 8 * 60 * 60 /**< Wait for new query */ + +/** + Flag used by the parser. Kill only the query and not the connection. + + @sa SQLCOM_KILL, sql_kill(), LEX::type +*/ +#define ONLY_KILL_QUERY 1 + +#ifndef MYSQL_VIO +struct Vio; +#define MYSQL_VIO struct Vio * +#endif + +#define MAX_TINYINT_WIDTH 3 /**< Max width for a TINY w.o. sign */ +#define MAX_SMALLINT_WIDTH 5 /**< Max width for a SHORT w.o. sign */ +#define MAX_MEDIUMINT_WIDTH 8 /**< Max width for a INT24 w.o. sign */ +#define MAX_INT_WIDTH 10 /**< Max width for a LONG w.o. sign */ +#define MAX_BIGINT_WIDTH 20 /**< Max width for a LONGLONG */ +/// Max width for a CHAR column, in number of characters +#define MAX_CHAR_WIDTH 255 +/// Default width for blob in bytes @todo - align this with sizes from field.h +#define MAX_BLOB_WIDTH 16777216 + +#define NET_ERROR_UNSET 0 /**< No error has occurred yet */ +#define NET_ERROR_SOCKET_RECOVERABLE 1 /**< Socket still usable */ +#define NET_ERROR_SOCKET_UNUSABLE 2 /**< Do not use the socket */ +#define NET_ERROR_SOCKET_NOT_READABLE 3 /**< Try write and close socket */ +#define NET_ERROR_SOCKET_NOT_WRITABLE 4 /**< Try read and close socket */ + +typedef struct NET { + MYSQL_VIO vio; + unsigned char *buff, *buff_end, *write_pos, *read_pos; + my_socket fd; /* For Perl DBI/dbd */ + /** + Set if we are doing several queries in one command ( as in LOAD TABLE ... FROM MASTER ), and do not want to confuse the client with OK at the wrong time */ - unsigned long remain_in_buf,length, buf_length, where_b; - unsigned long max_packet,max_packet_size; - unsigned int pkt_nr,compress_pkt_nr; + unsigned long remain_in_buf, length, buf_length, where_b; + unsigned long max_packet, max_packet_size; + unsigned int pkt_nr, compress_pkt_nr; unsigned int write_timeout, read_timeout, retry_count; int fcntl; unsigned int *return_status; unsigned char reading_or_writing; - char save_char; - my_bool unused1; /* Please remove with the next incompatible ABI change */ - my_bool unused2; /* Please remove with the next incompatible ABI change */ - my_bool compress; - my_bool unused3; /* Please remove with the next incompatible ABI change. */ - /* - Pointer to query object in query cache, do not equal NULL (0) for - queries in cache that have not stored its results yet - */ - /* - Unused, please remove with the next incompatible ABI change. - */ - unsigned char *unused; + unsigned char save_char; + bool compress; unsigned int last_errno; - unsigned char error; - my_bool unused4; /* Please remove with the next incompatible ABI change. */ - my_bool unused5; /* Please remove with the next incompatible ABI change. */ + unsigned char error; /** Client library error message buffer. Actually belongs to struct MYSQL. */ char last_error[MYSQL_ERRMSG_SIZE]; /** Client library sqlstate buffer. Set along with the error message. */ - char sqlstate[SQLSTATE_LENGTH+1]; + char sqlstate[SQLSTATE_LENGTH + 1]; /** Extension pointer, for the caller private use. Any program linking with the networking library can use this pointer, @@ -376,238 +947,359 @@ typedef struct st_net { void *extension; } NET; +#define packet_error (~(unsigned long)0) -#define packet_error (~(unsigned long) 0) -/* For backward compatibility */ -#define CLIENT_MULTI_QUERIES CLIENT_MULTI_STATEMENTS -#define FIELD_TYPE_DECIMAL MYSQL_TYPE_DECIMAL -#define FIELD_TYPE_NEWDECIMAL MYSQL_TYPE_NEWDECIMAL -#define FIELD_TYPE_TINY MYSQL_TYPE_TINY -#define FIELD_TYPE_SHORT MYSQL_TYPE_SHORT -#define FIELD_TYPE_LONG MYSQL_TYPE_LONG -#define FIELD_TYPE_FLOAT MYSQL_TYPE_FLOAT -#define FIELD_TYPE_DOUBLE MYSQL_TYPE_DOUBLE -#define FIELD_TYPE_NULL MYSQL_TYPE_NULL -#define FIELD_TYPE_TIMESTAMP MYSQL_TYPE_TIMESTAMP -#define FIELD_TYPE_LONGLONG MYSQL_TYPE_LONGLONG -#define FIELD_TYPE_INT24 MYSQL_TYPE_INT24 -#define FIELD_TYPE_DATE MYSQL_TYPE_DATE -#define FIELD_TYPE_TIME MYSQL_TYPE_TIME -#define FIELD_TYPE_DATETIME MYSQL_TYPE_DATETIME -#define FIELD_TYPE_YEAR MYSQL_TYPE_YEAR -#define FIELD_TYPE_NEWDATE MYSQL_TYPE_NEWDATE -#define FIELD_TYPE_ENUM MYSQL_TYPE_ENUM -#define FIELD_TYPE_SET MYSQL_TYPE_SET -#define FIELD_TYPE_TINY_BLOB MYSQL_TYPE_TINY_BLOB +/** + @addtogroup group_cs_backward_compatibility Backward compatibility + @ingroup group_cs + @{ +*/ +#define CLIENT_MULTI_QUERIES CLIENT_MULTI_STATEMENTS +#define FIELD_TYPE_DECIMAL MYSQL_TYPE_DECIMAL +#define FIELD_TYPE_NEWDECIMAL MYSQL_TYPE_NEWDECIMAL +#define FIELD_TYPE_TINY MYSQL_TYPE_TINY +#define FIELD_TYPE_SHORT MYSQL_TYPE_SHORT +#define FIELD_TYPE_LONG MYSQL_TYPE_LONG +#define FIELD_TYPE_FLOAT MYSQL_TYPE_FLOAT +#define FIELD_TYPE_DOUBLE MYSQL_TYPE_DOUBLE +#define FIELD_TYPE_NULL MYSQL_TYPE_NULL +#define FIELD_TYPE_TIMESTAMP MYSQL_TYPE_TIMESTAMP +#define FIELD_TYPE_LONGLONG MYSQL_TYPE_LONGLONG +#define FIELD_TYPE_INT24 MYSQL_TYPE_INT24 +#define FIELD_TYPE_DATE MYSQL_TYPE_DATE +#define FIELD_TYPE_TIME MYSQL_TYPE_TIME +#define FIELD_TYPE_DATETIME MYSQL_TYPE_DATETIME +#define FIELD_TYPE_YEAR MYSQL_TYPE_YEAR +#define FIELD_TYPE_NEWDATE MYSQL_TYPE_NEWDATE +#define FIELD_TYPE_ENUM MYSQL_TYPE_ENUM +#define FIELD_TYPE_SET MYSQL_TYPE_SET +#define FIELD_TYPE_TINY_BLOB MYSQL_TYPE_TINY_BLOB #define FIELD_TYPE_MEDIUM_BLOB MYSQL_TYPE_MEDIUM_BLOB -#define FIELD_TYPE_LONG_BLOB MYSQL_TYPE_LONG_BLOB -#define FIELD_TYPE_BLOB MYSQL_TYPE_BLOB -#define FIELD_TYPE_VAR_STRING MYSQL_TYPE_VAR_STRING -#define FIELD_TYPE_STRING MYSQL_TYPE_STRING -#define FIELD_TYPE_CHAR MYSQL_TYPE_TINY -#define FIELD_TYPE_INTERVAL MYSQL_TYPE_ENUM -#define FIELD_TYPE_GEOMETRY MYSQL_TYPE_GEOMETRY -#define FIELD_TYPE_BIT MYSQL_TYPE_BIT +#define FIELD_TYPE_LONG_BLOB MYSQL_TYPE_LONG_BLOB +#define FIELD_TYPE_BLOB MYSQL_TYPE_BLOB +#define FIELD_TYPE_VAR_STRING MYSQL_TYPE_VAR_STRING +#define FIELD_TYPE_STRING MYSQL_TYPE_STRING +#define FIELD_TYPE_CHAR MYSQL_TYPE_TINY +#define FIELD_TYPE_INTERVAL MYSQL_TYPE_ENUM +#define FIELD_TYPE_GEOMETRY MYSQL_TYPE_GEOMETRY +#define FIELD_TYPE_BIT MYSQL_TYPE_BIT +/** @}*/ +/** + @addtogroup group_cs_shutdown_kill_constants Shutdown/kill enums and constants + @ingroup group_cs -/* Shutdown/kill enums and constants */ - -/* Bits for THD::killable. */ -#define MYSQL_SHUTDOWN_KILLABLE_CONNECT (unsigned char)(1 << 0) -#define MYSQL_SHUTDOWN_KILLABLE_TRANS (unsigned char)(1 << 1) + @sa THD::is_killable + @{ +*/ +#define MYSQL_SHUTDOWN_KILLABLE_CONNECT (unsigned char)(1 << 0) +#define MYSQL_SHUTDOWN_KILLABLE_TRANS (unsigned char)(1 << 1) #define MYSQL_SHUTDOWN_KILLABLE_LOCK_TABLE (unsigned char)(1 << 2) -#define MYSQL_SHUTDOWN_KILLABLE_UPDATE (unsigned char)(1 << 3) +#define MYSQL_SHUTDOWN_KILLABLE_UPDATE (unsigned char)(1 << 3) +/** + We want levels to be in growing order of hardness (because we use number + comparisons). + + @note ::SHUTDOWN_DEFAULT does not respect the growing property, but it's ok. +*/ enum mysql_enum_shutdown_level { - /* - We want levels to be in growing order of hardness (because we use number - comparisons). Note that DEFAULT does not respect the growing property, but - it's ok. - */ SHUTDOWN_DEFAULT = 0, - /* wait for existing connections to finish */ - SHUTDOWN_WAIT_CONNECTIONS= MYSQL_SHUTDOWN_KILLABLE_CONNECT, - /* wait for existing trans to finish */ - SHUTDOWN_WAIT_TRANSACTIONS= MYSQL_SHUTDOWN_KILLABLE_TRANS, - /* wait for existing updates to finish (=> no partial MyISAM update) */ - SHUTDOWN_WAIT_UPDATES= MYSQL_SHUTDOWN_KILLABLE_UPDATE, - /* flush InnoDB buffers and other storage engines' buffers*/ - SHUTDOWN_WAIT_ALL_BUFFERS= (MYSQL_SHUTDOWN_KILLABLE_UPDATE << 1), - /* don't flush InnoDB buffers, flush other storage engines' buffers*/ - SHUTDOWN_WAIT_CRITICAL_BUFFERS= (MYSQL_SHUTDOWN_KILLABLE_UPDATE << 1) + 1, - /* Now the 2 levels of the KILL command */ - KILL_QUERY= 254, - KILL_CONNECTION= 255 + /** Wait for existing connections to finish */ + SHUTDOWN_WAIT_CONNECTIONS = MYSQL_SHUTDOWN_KILLABLE_CONNECT, + /** Wait for existing transactons to finish */ + SHUTDOWN_WAIT_TRANSACTIONS = MYSQL_SHUTDOWN_KILLABLE_TRANS, + /** Wait for existing updates to finish (=> no partial MyISAM update) */ + SHUTDOWN_WAIT_UPDATES = MYSQL_SHUTDOWN_KILLABLE_UPDATE, + /** Flush InnoDB buffers and other storage engines' buffers*/ + SHUTDOWN_WAIT_ALL_BUFFERS = (MYSQL_SHUTDOWN_KILLABLE_UPDATE << 1), + /** Don't flush InnoDB buffers, flush other storage engines' buffers*/ + SHUTDOWN_WAIT_CRITICAL_BUFFERS = (MYSQL_SHUTDOWN_KILLABLE_UPDATE << 1) + 1, + /** Query level of the KILL command */ + KILL_QUERY = 254, + /** Connection level of the KILL command */ + KILL_CONNECTION = 255 }; +/** @}*/ - -enum enum_cursor_type -{ - CURSOR_TYPE_NO_CURSOR= 0, - CURSOR_TYPE_READ_ONLY= 1, - CURSOR_TYPE_FOR_UPDATE= 2, - CURSOR_TYPE_SCROLLABLE= 4 +enum enum_resultset_metadata { + /** No metadata will be sent. */ + RESULTSET_METADATA_NONE = 0, + /** The server will send all metadata. */ + RESULTSET_METADATA_FULL = 1 }; +#if defined(__clang__) +// disable -Wdocumentation to workaround +// https://bugs.llvm.org/show_bug.cgi?id=38905 +#pragma clang diagnostic push +#pragma clang diagnostic ignored "-Wdocumentation" +#endif +/** + The flags used in COM_STMT_EXECUTE. + @sa @ref Protocol_classic::parse_packet, @ref mysql_int_serialize_param_data +*/ +#if defined(__clang__) +#pragma clang diagnostic pop +#endif +enum enum_cursor_type { + CURSOR_TYPE_NO_CURSOR = 0, + CURSOR_TYPE_READ_ONLY = 1, + CURSOR_TYPE_FOR_UPDATE = 2, + CURSOR_TYPE_SCROLLABLE = 4, + /** + On when the client will send the parameter count + even for 0 parameters. + */ + PARAMETER_COUNT_AVAILABLE = 8 +}; -/* options for mysql_set_option */ -enum enum_mysql_set_option -{ +/** options for ::mysql_options() */ +enum enum_mysql_set_option { MYSQL_OPTION_MULTI_STATEMENTS_ON, MYSQL_OPTION_MULTI_STATEMENTS_OFF }; -/* +/** Type of state change information that the server can include in the Ok packet. - Note : 1) session_state_type shouldn't go past 255 (i.e. 1-byte boundary). - 2) Modify the definition of SESSION_TRACK_END when a new member is - added. -*/ -enum enum_session_state_type -{ - SESSION_TRACK_SYSTEM_VARIABLES, /* Session system variables */ - SESSION_TRACK_SCHEMA, /* Current schema */ - SESSION_TRACK_STATE_CHANGE, /* track session state changes */ - SESSION_TRACK_GTIDS, - SESSION_TRACK_TRANSACTION_CHARACTERISTICS, /* Transaction chistics */ - SESSION_TRACK_TRANSACTION_STATE /* Transaction state */ + + @note + - session_state_type shouldn't go past 255 (i.e. 1-byte boundary). + - Modify the definition of ::SESSION_TRACK_END when a new member is added. +*/ +enum enum_session_state_type { + SESSION_TRACK_SYSTEM_VARIABLES, /**< Session system variables */ + SESSION_TRACK_SCHEMA, /**< Current schema */ + SESSION_TRACK_STATE_CHANGE, /**< track session state changes */ + SESSION_TRACK_GTIDS, /**< See also: session_track_gtids */ + SESSION_TRACK_TRANSACTION_CHARACTERISTICS, /**< Transaction chistics */ + SESSION_TRACK_TRANSACTION_STATE /**< Transaction state */ }; +/** start of ::enum_session_state_type */ #define SESSION_TRACK_BEGIN SESSION_TRACK_SYSTEM_VARIABLES +/** End of ::enum_session_state_type */ #define SESSION_TRACK_END SESSION_TRACK_TRANSACTION_STATE +/** is T a valid session state type */ #define IS_SESSION_STATE_TYPE(T) \ (((int)(T) >= SESSION_TRACK_BEGIN) && ((T) <= SESSION_TRACK_END)) -#define net_new_transaction(net) ((net)->pkt_nr=0) - -#ifdef __cplusplus -extern "C" { -#endif - -my_bool my_net_init(NET *net, Vio* vio); -void my_net_local_init(NET *net); -void net_end(NET *net); -void net_clear(NET *net, my_bool check_buffer); -void net_claim_memory_ownership(NET *net); -my_bool net_realloc(NET *net, size_t length); -my_bool net_flush(NET *net); -my_bool my_net_write(NET *net,const unsigned char *packet, size_t len); -my_bool net_write_command(NET *net,unsigned char command, - const unsigned char *header, size_t head_len, - const unsigned char *packet, size_t len); -my_bool net_write_packet(NET *net, const unsigned char *packet, size_t length); -unsigned long my_net_read(NET *net); - -#ifdef MY_GLOBAL_INCLUDED -void my_net_set_write_timeout(NET *net, uint timeout); -void my_net_set_read_timeout(NET *net, uint timeout); -#endif +#define net_new_transaction(net) ((net)->pkt_nr = 0) + +bool my_net_init(struct NET *net, MYSQL_VIO vio); +void my_net_local_init(struct NET *net); +void net_end(struct NET *net); +void net_clear(struct NET *net, bool check_buffer); +void net_claim_memory_ownership(struct NET *net, bool claim); +bool net_realloc(struct NET *net, size_t length); +bool net_flush(struct NET *net); +bool my_net_write(struct NET *net, const unsigned char *packet, size_t len); +bool net_write_command(struct NET *net, unsigned char command, + const unsigned char *header, size_t head_len, + const unsigned char *packet, size_t len); +bool net_write_packet(struct NET *net, const unsigned char *packet, + size_t length); +unsigned long my_net_read(struct NET *net); +void my_net_set_write_timeout(struct NET *net, unsigned int timeout); +void my_net_set_read_timeout(struct NET *net, unsigned int timeout); +void my_net_set_retry_count(struct NET *net, unsigned int retry_count); struct rand_struct { - unsigned long seed1,seed2,max_value; + unsigned long seed1, seed2, max_value; double max_value_dbl; }; -#ifdef __cplusplus -} -#endif - - /* The following is for user defined functions */ +/* Include the types here so existing UDFs can keep compiling */ +#include "mysql/udf_registration_types.h" -enum Item_result {STRING_RESULT=0, REAL_RESULT, INT_RESULT, ROW_RESULT, - DECIMAL_RESULT}; - -typedef struct st_udf_args -{ - unsigned int arg_count; /* Number of arguments */ - enum Item_result *arg_type; /* Pointer to item_results */ - char **args; /* Pointer to argument */ - unsigned long *lengths; /* Length of string arguments */ - char *maybe_null; /* Set to 1 for all maybe_null args */ - char **attributes; /* Pointer to attribute name */ - unsigned long *attribute_lengths; /* Length of attribute arguments */ - void *extension; -} UDF_ARGS; +/** + @addtogroup group_cs_compresson_constants Constants when using compression + @ingroup group_cs + @{ +*/ +#define NET_HEADER_SIZE 4 /**< standard header size */ +#define COMP_HEADER_SIZE 3 /**< compression header extra size */ +/** @}*/ - /* This holds information about the result */ +/* Prototypes to password functions */ -typedef struct st_udf_init -{ - my_bool maybe_null; /* 1 if function can return NULL */ - unsigned int decimals; /* for real functions */ - unsigned long max_length; /* For string functions */ - char *ptr; /* free pointer for function data */ - my_bool const_item; /* 1 if function always returns the same value */ - void *extension; -} UDF_INIT; -/* - TODO: add a notion for determinism of the UDF. - See Item_udf_func::update_used_tables () -*/ +/* used in both client and server */ +char *octet2hex(char *to, const char *str, unsigned int len); - /* Constants when using compression */ -#define NET_HEADER_SIZE 4 /* standard header size */ -#define COMP_HEADER_SIZE 3 /* compression header extra size */ +/* end of password.c */ - /* Prototypes to password functions */ +bool generate_sha256_scramble(unsigned char *dst, size_t dst_size, + const char *src, size_t src_size, const char *rnd, + size_t rnd_size); +// extern "C" since it is an (undocumented) part of the libmysql ABI. #ifdef __cplusplus extern "C" { #endif - -/* - These functions are used for authentication by client and server and - implemented in sql/password.c -*/ - -void randominit(struct rand_struct *, unsigned long seed1, - unsigned long seed2); -double my_rnd(struct rand_struct *); -void create_random_string(char *to, unsigned int length, struct rand_struct *rand_st); - -void hash_password(unsigned long *to, const char *password, unsigned int password_len); -void make_scrambled_password_323(char *to, const char *password); -void scramble_323(char *to, const char *message, const char *password); -my_bool check_scramble_323(const unsigned char *reply, const char *message, - unsigned long *salt); -void get_salt_from_password_323(unsigned long *res, const char *password); -void make_password_from_salt_323(char *to, const unsigned long *salt); - -void make_scrambled_password(char *to, const char *password); -void scramble(char *to, const char *message, const char *password); -my_bool check_scramble(const unsigned char *reply, const char *message, - const unsigned char *hash_stage2); -void get_salt_from_password(unsigned char *res, const char *password); -void make_password_from_salt(char *to, const unsigned char *hash_stage2); -char *octet2hex(char *to, const char *str, unsigned int len); - -/* end of password.c */ - char *get_tty_password(const char *opt_message); +#ifdef __cplusplus +} +#endif + const char *mysql_errno_to_sqlstate(unsigned int mysql_errno); /* Some other useful functions */ -my_bool my_thread_init(void); +bool my_thread_init(void); void my_thread_end(void); -#ifdef MY_GLOBAL_INCLUDED -ulong STDCALL net_field_length(uchar **packet); -my_ulonglong net_field_length_ll(uchar **packet); -uchar *net_store_length(uchar *pkg, ulonglong length); -unsigned int net_length_size(ulonglong num); +#ifdef STDCALL +unsigned long STDCALL net_field_length(unsigned char **packet); +unsigned long STDCALL net_field_length_checked(unsigned char **packet, + unsigned long max_length); #endif +uint64_t net_field_length_ll(unsigned char **packet); +unsigned char *net_store_length(unsigned char *pkg, unsigned long long length); +unsigned int net_length_size(unsigned long long num); +unsigned int net_field_length_size(const unsigned char *pos); +uint64_t net_length_size_including_self(uint64_t length_without_self); -#ifdef __cplusplus -} -#endif +#define NULL_LENGTH ((unsigned long)~0) /**< For ::net_store_length() */ +#define MYSQL_STMT_HEADER 4 +#define MYSQL_LONG_DATA_HEADER 6 + +/* clang-format off */ +/** + Describes the current state of Asynchronous connection phase state machine + + @startuml + [*] --> CONNECT_STAGE_INVALID + [*] --> CONNECT_STAGE_NOT_STARTED + + CONNECT_STAGE_NOT_STARTED --> CONNECT_STAGE_NET_BEGIN_CONNECT + CONNECT_STAGE_NOT_STARTED --> CONNECT_STAGE_COMPLETE -#define NULL_LENGTH ((unsigned long) ~0) /* For net_store_length */ -#define MYSQL_STMT_HEADER 4 -#define MYSQL_LONG_DATA_HEADER 6 + CONNECT_STAGE_NET_BEGIN_CONNECT --> CONNECT_STAGE_NET_WAIT_CONNECT + CONNECT_STAGE_NET_BEGIN_CONNECT --> CONNECT_STAGE_NET_COMPLETE_CONNECT + CONNECT_STAGE_NET_BEGIN_CONNECT --> STATE_MACHINE_FAILED -#define NOT_FIXED_DEC 31 + CONNECT_STAGE_NET_WAIT_CONNECT --> CONNECT_STAGE_NET_COMPLETE_CONNECT + CONNECT_STAGE_NET_WAIT_CONNECT --> STATE_MACHINE_FAILED + + CONNECT_STAGE_NET_COMPLETE_CONNECT --> STATE_MACHINE_FAILED + CONNECT_STAGE_NET_COMPLETE_CONNECT --> CONNECT_STAGE_READ_GREETING + + CONNECT_STAGE_READ_GREETING --> STATE_MACHINE_FAILED + CONNECT_STAGE_READ_GREETING --> CONNECT_STAGE_PARSE_HANDSHAKE + + CONNECT_STAGE_PARSE_HANDSHAKE --> STATE_MACHINE_FAILED + CONNECT_STAGE_PARSE_HANDSHAKE --> CONNECT_STAGE_ESTABLISH_SSL + + CONNECT_STAGE_ESTABLISH_SSL --> STATE_MACHINE_FAILED + CONNECT_STAGE_ESTABLISH_SSL --> CONNECT_STAGE_AUTHENTICATE + + CONNECT_STAGE_AUTHENTICATE --> STATE_MACHINE_FAILED + CONNECT_STAGE_AUTHENTICATE --> CONNECT_STAGE_AUTH_BEGIN + + CONNECT_STAGE_AUTH_BEGIN --> STATE_MACHINE_FAILED + CONNECT_STAGE_AUTH_BEGIN --> CONNECT_STAGE_AUTH_RUN_FIRST_AUTHENTICATE_USER + + CONNECT_STAGE_AUTH_RUN_FIRST_AUTHENTICATE_USER --> CONNECT_STAGE_AUTH_HANDLE_FIRST_AUTHENTICATE_USER + + CONNECT_STAGE_AUTH_HANDLE_FIRST_AUTHENTICATE_USER --> STATE_MACHINE_FAILED + CONNECT_STAGE_AUTH_HANDLE_FIRST_AUTHENTICATE_USER --> CONNECT_STAGE_AUTH_READ_CHANGE_USER_RESULT + + CONNECT_STAGE_AUTH_READ_CHANGE_USER_RESULT --> CONNECT_STAGE_AUTH_HANDLE_CHANGE_USER_REQUEST + + CONNECT_STAGE_AUTH_HANDLE_CHANGE_USER_REQUEST --> STATE_MACHINE_FAILED + CONNECT_STAGE_AUTH_HANDLE_CHANGE_USER_REQUEST --> CONNECT_STAGE_AUTH_RUN_SECOND_AUTHENTICATE_USER + CONNECT_STAGE_AUTH_HANDLE_CHANGE_USER_REQUEST --> CONNECT_STAGE_AUTH_INIT_MULTI_AUTH + CONNECT_STAGE_AUTH_HANDLE_CHANGE_USER_REQUEST --> CONNECT_STAGE_AUTH_FINISH_AUTH + + CONNECT_STAGE_AUTH_RUN_SECOND_AUTHENTICATE_USER --> STATE_MACHINE_FAILED + CONNECT_STAGE_AUTH_RUN_SECOND_AUTHENTICATE_USER --> CONNECT_STAGE_AUTH_HANDLE_SECOND_AUTHENTICATE_USER + + CONNECT_STAGE_AUTH_HANDLE_SECOND_AUTHENTICATE_USER --> STATE_MACHINE_FAILED + CONNECT_STAGE_AUTH_HANDLE_SECOND_AUTHENTICATE_USER --> CONNECT_STAGE_AUTH_INIT_MULTI_AUTH + CONNECT_STAGE_AUTH_HANDLE_SECOND_AUTHENTICATE_USER --> CONNECT_STAGE_AUTH_FINISH_AUTH + + CONNECT_STAGE_AUTH_INIT_MULTI_AUTH --> STATE_MACHINE_FAILED + CONNECT_STAGE_AUTH_INIT_MULTI_AUTH --> CONNECT_STAGE_AUTH_DO_MULTI_PLUGIN_AUTH + + CONNECT_STAGE_AUTH_DO_MULTI_PLUGIN_AUTH --> STATE_MACHINE_FAILED + CONNECT_STAGE_AUTH_DO_MULTI_PLUGIN_AUTH --> CONNECT_STAGE_AUTH_HANDLE_MULTI_AUTH_RESPONSE + + CONNECT_STAGE_AUTH_HANDLE_MULTI_AUTH_RESPONSE --> STATE_MACHINE_FAILED + CONNECT_STAGE_AUTH_HANDLE_MULTI_AUTH_RESPONSE --> CONNECT_STAGE_AUTH_INIT_MULTI_AUTH + CONNECT_STAGE_AUTH_HANDLE_MULTI_AUTH_RESPONSE --> CONNECT_STAGE_AUTH_FINISH_AUTH + + CONNECT_STAGE_AUTH_FINISH_AUTH --> STATE_MACHINE_FAILED + CONNECT_STAGE_AUTH_FINISH_AUTH --> CONNECT_STAGE_PREP_SELECT_DATABASE + + CONNECT_STAGE_PREP_SELECT_DATABASE --> CONNECT_STAGE_COMPLETE + CONNECT_STAGE_PREP_SELECT_DATABASE --> CONNECT_STAGE_PREP_INIT_COMMANDS + + CONNECT_STAGE_PREP_INIT_COMMANDS --> CONNECT_STAGE_COMPLETE + CONNECT_STAGE_PREP_INIT_COMMANDS --> CONNECT_STAGE_SEND_ONE_INIT_COMMAND + + CONNECT_STAGE_SEND_ONE_INIT_COMMAND --> CONNECT_STAGE_SEND_ONE_INIT_COMMAND + CONNECT_STAGE_SEND_ONE_INIT_COMMAND --> STATE_MACHINE_FAILED + CONNECT_STAGE_SEND_ONE_INIT_COMMAND --> CONNECT_STAGE_COMPLETE + + STATE_MACHINE_FAILED --> [*] + CONNECT_STAGE_COMPLETE --> [*] + CONNECT_STAGE_INVALID --> [*] + @enduml +*/ +/* clang-format on */ +enum connect_stage { + /** MYSQL not valid or an unknown state */ + CONNECT_STAGE_INVALID = 0, + /** not connected */ + CONNECT_STAGE_NOT_STARTED, + /** begin connection to the server */ + CONNECT_STAGE_NET_BEGIN_CONNECT, + /** wait for connection to be established */ + CONNECT_STAGE_NET_WAIT_CONNECT, + /** init the local data structures post connect */ + CONNECT_STAGE_NET_COMPLETE_CONNECT, + /** read the first packet */ + CONNECT_STAGE_READ_GREETING, + /** parse the first packet */ + CONNECT_STAGE_PARSE_HANDSHAKE, + /** tls establishment */ + CONNECT_STAGE_ESTABLISH_SSL, + /** authentication phase */ + CONNECT_STAGE_AUTHENTICATE, + /** determine the plugin to use */ + CONNECT_STAGE_AUTH_BEGIN, + /** run first auth plugin */ + CONNECT_STAGE_AUTH_RUN_FIRST_AUTHENTICATE_USER, + /** handle the result of the first auth plugin run */ + CONNECT_STAGE_AUTH_HANDLE_FIRST_AUTHENTICATE_USER, + /** read the implied changed user auth, if any */ + CONNECT_STAGE_AUTH_READ_CHANGE_USER_RESULT, + /** Check if server asked to use a different authentication plugin */ + CONNECT_STAGE_AUTH_HANDLE_CHANGE_USER_REQUEST, + /** Start the authentication process again with the plugin which + server asked for */ + CONNECT_STAGE_AUTH_RUN_SECOND_AUTHENTICATE_USER, + /** Start multi factor authentication */ + CONNECT_STAGE_AUTH_INIT_MULTI_AUTH, + /** Final cleanup */ + CONNECT_STAGE_AUTH_FINISH_AUTH, + /** Now read the results of the second plugin run */ + CONNECT_STAGE_AUTH_HANDLE_SECOND_AUTHENTICATE_USER, + /** Invoke client plugins multi-auth authentication method */ + CONNECT_STAGE_AUTH_DO_MULTI_PLUGIN_AUTH, + /** Handle response from client plugins authentication method */ + CONNECT_STAGE_AUTH_HANDLE_MULTI_AUTH_RESPONSE, + /** Authenticated, set initial database if specified */ + CONNECT_STAGE_PREP_SELECT_DATABASE, + /** Prepare to send a sequence of init commands. */ + CONNECT_STAGE_PREP_INIT_COMMANDS, + /** Send an init command. This is called once per init command until + they've all been run (or a failure occurs) */ + CONNECT_STAGE_SEND_ONE_INIT_COMMAND, + /** Connected or no async connect in progress */ + CONNECT_STAGE_COMPLETE +}; #endif diff --git a/vendor/mysql/include/mysql_com_server.h b/vendor/mysql/include/mysql_com_server.h deleted file mode 100644 index 1ea040207d..0000000000 --- a/vendor/mysql/include/mysql_com_server.h +++ /dev/null @@ -1,41 +0,0 @@ -/* Copyright (c) 2011, Oracle and/or its affiliates. All rights reserved. - - This program is free software; you can redistribute it and/or modify - it under the terms of the GNU General Public License as published by - the Free Software Foundation; version 2 of the License. - - This program is distributed in the hope that it will be useful, - but WITHOUT ANY WARRANTY; without even the implied warranty of - MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - GNU General Public License for more details. - - You should have received a copy of the GNU General Public License - along with this program; if not, write to the Free Software - Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA */ - -/* - Definitions private to the server, - used in the networking layer to notify specific events. -*/ - -#ifndef _mysql_com_server_h -#define _mysql_com_server_h - -struct st_net_server; - -typedef void (*before_header_callback_fn) - (struct st_net *net, void *user_data, size_t count); - -typedef void (*after_header_callback_fn) - (struct st_net *net, void *user_data, size_t count, my_bool rc); - -struct st_net_server -{ - before_header_callback_fn m_before_header; - after_header_callback_fn m_after_header; - void *m_user_data; -}; - -typedef struct st_net_server NET_SERVER; - -#endif diff --git a/vendor/mysql/include/mysql_embed.h b/vendor/mysql/include/mysql_embed.h deleted file mode 100644 index cdee3a98a8..0000000000 --- a/vendor/mysql/include/mysql_embed.h +++ /dev/null @@ -1,29 +0,0 @@ -#ifndef MYSQL_EMBED_INCLUDED -#define MYSQL_EMBED_INCLUDED - -/* Copyright (c) 2000, 2013, Oracle and/or its affiliates. All rights reserved. - - This program is free software; you can redistribute it and/or modify - it under the terms of the GNU General Public License as published by - the Free Software Foundation; version 2 of the License. - - This program is distributed in the hope that it will be useful, - but WITHOUT ANY WARRANTY; without even the implied warranty of - MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - GNU General Public License for more details. - - You should have received a copy of the GNU General Public License - along with this program; if not, write to the Free Software - Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA */ - -/* Defines that are unique to the embedded version of MySQL */ - -#ifdef EMBEDDED_LIBRARY - -/* Things we don't need in the embedded version of MySQL */ -/* TODO HF add #undef HAVE_VIO if we don't want client in embedded library */ - -#undef HAVE_DLOPEN /* No udf functions */ - -#endif /* EMBEDDED_LIBRARY */ -#endif /* MYSQL_EMBED_INCLUDED */ diff --git a/vendor/mysql/include/mysql_time.h b/vendor/mysql/include/mysql_time.h index ac9719c68c..e4892d472b 100644 --- a/vendor/mysql/include/mysql_time.h +++ b/vendor/mysql/include/mysql_time.h @@ -1,22 +1,36 @@ -/* Copyright (c) 2004, 2011, Oracle and/or its affiliates. All rights reserved. +/* Copyright (c) 2004, 2024, Oracle and/or its affiliates. This program is free software; you can redistribute it and/or modify - it under the terms of the GNU General Public License as published by - the Free Software Foundation; version 2 of the License. + it under the terms of the GNU General Public License, version 2.0, + as published by the Free Software Foundation. + + This program is designed to work with certain software (including + but not limited to OpenSSL) that is licensed under separate terms, + as designated in a particular file or component or in included license + documentation. The authors of MySQL hereby grant you an additional + permission to link the program and your derivative works with the + separately licensed software that they have either included with + the program or referenced in the documentation. + + Without limiting anything contained in the foregoing, this file, + which is part of C Driver for MySQL (Connector/C), is also subject to the + Universal FOSS Exception, version 1.0, a copy of which can be found at + http://oss.oracle.com/licenses/universal-foss-exception. This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - GNU General Public License for more details. + GNU General Public License, version 2.0, for more details. You should have received a copy of the GNU General Public License along with this program; if not, write to the Free Software - Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA */ + Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA */ #ifndef _mysql_time_h_ #define _mysql_time_h_ -/* +/** + @file include/mysql_time.h Time declarations shared between the server and client API: you should not add anything to this header unless it's used (and hence should be visible) in mysql.h. @@ -25,12 +39,33 @@ and Time Values" chapter in documentation. */ -enum enum_mysql_timestamp_type -{ - MYSQL_TIMESTAMP_NONE= -2, MYSQL_TIMESTAMP_ERROR= -1, - MYSQL_TIMESTAMP_DATE= 0, MYSQL_TIMESTAMP_DATETIME= 1, MYSQL_TIMESTAMP_TIME= 2 -}; +// Do not not pull in the server header "my_inttypes.h" from client code. +// IWYU pragma: no_include "my_inttypes.h" + +enum enum_mysql_timestamp_type { + MYSQL_TIMESTAMP_NONE = -2, + MYSQL_TIMESTAMP_ERROR = -1, + /// Stores year, month and day components. + MYSQL_TIMESTAMP_DATE = 0, + + /** + Stores all date and time components. + Value is in UTC for `TIMESTAMP` type. + Value is in local time zone for `DATETIME` type. + */ + MYSQL_TIMESTAMP_DATETIME = 1, + + /// Stores hour, minute, second and microsecond. + MYSQL_TIMESTAMP_TIME = 2, + + /** + A temporary type for `DATETIME` or `TIMESTAMP` types equipped with time + zone information. After the time zone information is reconciled, the type is + converted to MYSQL_TIMESTAMP_DATETIME. + */ + MYSQL_TIMESTAMP_DATETIME_TZ = 3 +}; /* Structure which is used to represent datetime values inside MySQL. @@ -44,12 +79,13 @@ enum enum_mysql_timestamp_type value (time_type == MYSQL_TIMESTAMP_TIME) days and hour member can hold bigger values. */ -typedef struct st_mysql_time -{ - unsigned int year, month, day, hour, minute, second; - unsigned long second_part; /**< microseconds */ - my_bool neg; +typedef struct MYSQL_TIME { + unsigned int year, month, day, hour, minute, second; + unsigned long second_part; /**< microseconds */ + bool neg; enum enum_mysql_timestamp_type time_type; + /// The time zone displacement, specified in seconds. + int time_zone_displacement; } MYSQL_TIME; #endif /* _mysql_time_h_ */ diff --git a/vendor/mysql/include/mysql_version.h b/vendor/mysql/include/mysql_version.h index 061dff72ba..ee79b583c6 100644 --- a/vendor/mysql/include/mysql_version.h +++ b/vendor/mysql/include/mysql_version.h @@ -7,22 +7,23 @@ #ifndef _mysql_version_h #define _mysql_version_h -#ifdef _CUSTOMCONFIG_ -#include -#else + #define PROTOCOL_VERSION 10 -#define MYSQL_SERVER_VERSION "5.7.16" -#define MYSQL_VERSION_ID 50716 +#define MYSQL_SERVER_VERSION "8.4.0" +#define MYSQL_BASE_VERSION "mysqld-8.4" +#define MYSQL_SERVER_SUFFIX_DEF "" +#define MYSQL_VERSION_ID 80400 +#define MYSQL_VERSION_MATURITY "LTS" #define MYSQL_PORT 3306 +#define MYSQL_ADMIN_PORT 33062 #define MYSQL_PORT_DEFAULT 0 #define MYSQL_UNIX_ADDR "/tmp/mysql.sock" #define MYSQL_CONFIG_NAME "my" -#define MYSQL_COMPILATION_COMMENT "MySQL Connector/C (GPL)" -#define LIBMYSQL_VERSION "6.1.11" -#define LIBMYSQL_VERSION_ID 60111 - -/* mysqld compile time options */ -#endif /* _CUSTOMCONFIG_ */ +#define MYSQL_PERSIST_CONFIG_NAME "mysqld-auto" +#define MYSQL_COMPILATION_COMMENT "Source distribution" +#define MYSQL_COMPILATION_COMMENT_SERVER "Source distribution" +#define LIBMYSQL_VERSION "8.4.0" +#define LIBMYSQL_VERSION_ID 80400 #ifndef LICENSE #define LICENSE GPL diff --git a/vendor/mysql/include/mysqld_ername.h b/vendor/mysql/include/mysqld_ername.h deleted file mode 100644 index 50d6531cf2..0000000000 --- a/vendor/mysql/include/mysqld_ername.h +++ /dev/null @@ -1,1082 +0,0 @@ -/* Autogenerated file, please don't edit */ - -{ "ER_HASHCHK", 1000, "hashchk" }, -{ "ER_NISAMCHK", 1001, "isamchk" }, -{ "ER_NO", 1002, "NO" }, -{ "ER_YES", 1003, "YES" }, -{ "ER_CANT_CREATE_FILE", 1004, "Can\'t create file \'%-.200s\' (errno: %d - %s)" }, -{ "ER_CANT_CREATE_TABLE", 1005, "Can\'t create table \'%-.200s\' (errno: %d)" }, -{ "ER_CANT_CREATE_DB", 1006, "Can\'t create database \'%-.192s\' (errno: %d)" }, -{ "ER_DB_CREATE_EXISTS", 1007, "Can\'t create database \'%-.192s\'; database exists" }, -{ "ER_DB_DROP_EXISTS", 1008, "Can\'t drop database \'%-.192s\'; database doesn\'t exist" }, -{ "ER_DB_DROP_DELETE", 1009, "Error dropping database (can\'t delete \'%-.192s\', errno: %d)" }, -{ "ER_DB_DROP_RMDIR", 1010, "Error dropping database (can\'t rmdir \'%-.192s\', errno: %d)" }, -{ "ER_CANT_DELETE_FILE", 1011, "Error on delete of \'%-.192s\' (errno: %d - %s)" }, -{ "ER_CANT_FIND_SYSTEM_REC", 1012, "Can\'t read record in system table" }, -{ "ER_CANT_GET_STAT", 1013, "Can\'t get status of \'%-.200s\' (errno: %d - %s)" }, -{ "ER_CANT_GET_WD", 1014, "Can\'t get working directory (errno: %d - %s)" }, -{ "ER_CANT_LOCK", 1015, "Can\'t lock file (errno: %d - %s)" }, -{ "ER_CANT_OPEN_FILE", 1016, "Can\'t open file: \'%-.200s\' (errno: %d - %s)" }, -{ "ER_FILE_NOT_FOUND", 1017, "Can\'t find file: \'%-.200s\' (errno: %d - %s)" }, -{ "ER_CANT_READ_DIR", 1018, "Can\'t read dir of \'%-.192s\' (errno: %d - %s)" }, -{ "ER_CANT_SET_WD", 1019, "Can\'t change dir to \'%-.192s\' (errno: %d - %s)" }, -{ "ER_CHECKREAD", 1020, "Record has changed since last read in table \'%-.192s\'" }, -{ "ER_DISK_FULL", 1021, "Disk full (%s); waiting for someone to free some space... (errno: %d - %s)" }, -{ "ER_DUP_KEY", 1022, "Can\'t write; duplicate key in table \'%-.192s\'" }, -{ "ER_ERROR_ON_CLOSE", 1023, "Error on close of \'%-.192s\' (errno: %d - %s)" }, -{ "ER_ERROR_ON_READ", 1024, "Error reading file \'%-.200s\' (errno: %d - %s)" }, -{ "ER_ERROR_ON_RENAME", 1025, "Error on rename of \'%-.210s\' to \'%-.210s\' (errno: %d - %s)" }, -{ "ER_ERROR_ON_WRITE", 1026, "Error writing file \'%-.200s\' (errno: %d - %s)" }, -{ "ER_FILE_USED", 1027, "\'%-.192s\' is locked against change" }, -{ "ER_FILSORT_ABORT", 1028, "Sort aborted" }, -{ "ER_FORM_NOT_FOUND", 1029, "View \'%-.192s\' doesn\'t exist for \'%-.192s\'" }, -{ "ER_GET_ERRNO", 1030, "Got error %d from storage engine" }, -{ "ER_ILLEGAL_HA", 1031, "Table storage engine for \'%-.192s\' doesn\'t have this option" }, -{ "ER_KEY_NOT_FOUND", 1032, "Can\'t find record in \'%-.192s\'" }, -{ "ER_NOT_FORM_FILE", 1033, "Incorrect information in file: \'%-.200s\'" }, -{ "ER_NOT_KEYFILE", 1034, "Incorrect key file for table \'%-.200s\'; try to repair it" }, -{ "ER_OLD_KEYFILE", 1035, "Old key file for table \'%-.192s\'; repair it!" }, -{ "ER_OPEN_AS_READONLY", 1036, "Table \'%-.192s\' is read only" }, -{ "ER_OUTOFMEMORY", 1037, "Out of memory; restart server and try again (needed %d bytes)" }, -{ "ER_OUT_OF_SORTMEMORY", 1038, "Out of sort memory, consider increasing server sort buffer size" }, -{ "ER_UNEXPECTED_EOF", 1039, "Unexpected EOF found when reading file \'%-.192s\' (errno: %d - %s)" }, -{ "ER_CON_COUNT_ERROR", 1040, "Too many connections" }, -{ "ER_OUT_OF_RESOURCES", 1041, "Out of memory; check if mysqld or some other process uses all available memory; if not, you may have to use \'ulimit\' to allow mysqld to use more memory or you can add more swap space" }, -{ "ER_BAD_HOST_ERROR", 1042, "Can\'t get hostname for your address" }, -{ "ER_HANDSHAKE_ERROR", 1043, "Bad handshake" }, -{ "ER_DBACCESS_DENIED_ERROR", 1044, "Access denied for user \'%-.48s\'@\'%-.64s\' to database \'%-.192s\'" }, -{ "ER_ACCESS_DENIED_ERROR", 1045, "Access denied for user \'%-.48s\'@\'%-.64s\' (using password: %s)" }, -{ "ER_NO_DB_ERROR", 1046, "No database selected" }, -{ "ER_UNKNOWN_COM_ERROR", 1047, "Unknown command" }, -{ "ER_BAD_NULL_ERROR", 1048, "Column \'%-.192s\' cannot be null" }, -{ "ER_BAD_DB_ERROR", 1049, "Unknown database \'%-.192s\'" }, -{ "ER_TABLE_EXISTS_ERROR", 1050, "Table \'%-.192s\' already exists" }, -{ "ER_BAD_TABLE_ERROR", 1051, "Unknown table \'%-.100s\'" }, -{ "ER_NON_UNIQ_ERROR", 1052, "Column \'%-.192s\' in %-.192s is ambiguous" }, -{ "ER_SERVER_SHUTDOWN", 1053, "Server shutdown in progress" }, -{ "ER_BAD_FIELD_ERROR", 1054, "Unknown column \'%-.192s\' in \'%-.192s\'" }, -{ "ER_WRONG_FIELD_WITH_GROUP", 1055, "\'%-.192s\' isn\'t in GROUP BY" }, -{ "ER_WRONG_GROUP_FIELD", 1056, "Can\'t group on \'%-.192s\'" }, -{ "ER_WRONG_SUM_SELECT", 1057, "Statement has sum functions and columns in same statement" }, -{ "ER_WRONG_VALUE_COUNT", 1058, "Column count doesn\'t match value count" }, -{ "ER_TOO_LONG_IDENT", 1059, "Identifier name \'%-.100s\' is too long" }, -{ "ER_DUP_FIELDNAME", 1060, "Duplicate column name \'%-.192s\'" }, -{ "ER_DUP_KEYNAME", 1061, "Duplicate key name \'%-.192s\'" }, -{ "ER_DUP_ENTRY", 1062, "Duplicate entry \'%-.192s\' for key %d" }, -{ "ER_WRONG_FIELD_SPEC", 1063, "Incorrect column specifier for column \'%-.192s\'" }, -{ "ER_PARSE_ERROR", 1064, "%s near \'%-.80s\' at line %d" }, -{ "ER_EMPTY_QUERY", 1065, "Query was empty" }, -{ "ER_NONUNIQ_TABLE", 1066, "Not unique table/alias: \'%-.192s\'" }, -{ "ER_INVALID_DEFAULT", 1067, "Invalid default value for \'%-.192s\'" }, -{ "ER_MULTIPLE_PRI_KEY", 1068, "Multiple primary key defined" }, -{ "ER_TOO_MANY_KEYS", 1069, "Too many keys specified; max %d keys allowed" }, -{ "ER_TOO_MANY_KEY_PARTS", 1070, "Too many key parts specified; max %d parts allowed" }, -{ "ER_TOO_LONG_KEY", 1071, "Specified key was too long; max key length is %d bytes" }, -{ "ER_KEY_COLUMN_DOES_NOT_EXITS", 1072, "Key column \'%-.192s\' doesn\'t exist in table" }, -{ "ER_BLOB_USED_AS_KEY", 1073, "BLOB column \'%-.192s\' can\'t be used in key specification with the used table type" }, -{ "ER_TOO_BIG_FIELDLENGTH", 1074, "Column length too big for column \'%-.192s\' (max = %lu); use BLOB or TEXT instead" }, -{ "ER_WRONG_AUTO_KEY", 1075, "Incorrect table definition; there can be only one auto column and it must be defined as a key" }, -{ "ER_READY", 1076, "%s: ready for connections.\nVersion: \'%s\' socket: \'%s\' port: %d" }, -{ "ER_NORMAL_SHUTDOWN", 1077, "%s: Normal shutdown\n" }, -{ "ER_GOT_SIGNAL", 1078, "%s: Got signal %d. Aborting!\n" }, -{ "ER_SHUTDOWN_COMPLETE", 1079, "%s: Shutdown complete\n" }, -{ "ER_FORCING_CLOSE", 1080, "%s: Forcing close of thread %ld user: \'%-.48s\'\n" }, -{ "ER_IPSOCK_ERROR", 1081, "Can\'t create IP socket" }, -{ "ER_NO_SUCH_INDEX", 1082, "Table \'%-.192s\' has no index like the one used in CREATE INDEX; recreate the table" }, -{ "ER_WRONG_FIELD_TERMINATORS", 1083, "Field separator argument is not what is expected; check the manual" }, -{ "ER_BLOBS_AND_NO_TERMINATED", 1084, "You can\'t use fixed rowlength with BLOBs; please use \'fields terminated by\'" }, -{ "ER_TEXTFILE_NOT_READABLE", 1085, "The file \'%-.128s\' must be in the database directory or be readable by all" }, -{ "ER_FILE_EXISTS_ERROR", 1086, "File \'%-.200s\' already exists" }, -{ "ER_LOAD_INFO", 1087, "Records: %ld Deleted: %ld Skipped: %ld Warnings: %ld" }, -{ "ER_ALTER_INFO", 1088, "Records: %ld Duplicates: %ld" }, -{ "ER_WRONG_SUB_KEY", 1089, "Incorrect prefix key; the used key part isn\'t a string, the used length is longer than the key part, or the storage engine doesn\'t support unique prefix keys" }, -{ "ER_CANT_REMOVE_ALL_FIELDS", 1090, "You can\'t delete all columns with ALTER TABLE; use DROP TABLE instead" }, -{ "ER_CANT_DROP_FIELD_OR_KEY", 1091, "Can\'t DROP \'%-.192s\'; check that column/key exists" }, -{ "ER_INSERT_INFO", 1092, "Records: %ld Duplicates: %ld Warnings: %ld" }, -{ "ER_UPDATE_TABLE_USED", 1093, "You can\'t specify target table \'%-.192s\' for update in FROM clause" }, -{ "ER_NO_SUCH_THREAD", 1094, "Unknown thread id: %lu" }, -{ "ER_KILL_DENIED_ERROR", 1095, "You are not owner of thread %lu" }, -{ "ER_NO_TABLES_USED", 1096, "No tables used" }, -{ "ER_TOO_BIG_SET", 1097, "Too many strings for column %-.192s and SET" }, -{ "ER_NO_UNIQUE_LOGFILE", 1098, "Can\'t generate a unique log-filename %-.200s.(1-999)\n" }, -{ "ER_TABLE_NOT_LOCKED_FOR_WRITE", 1099, "Table \'%-.192s\' was locked with a READ lock and can\'t be updated" }, -{ "ER_TABLE_NOT_LOCKED", 1100, "Table \'%-.192s\' was not locked with LOCK TABLES" }, -{ "ER_BLOB_CANT_HAVE_DEFAULT", 1101, "BLOB, TEXT, GEOMETRY or JSON column \'%-.192s\' can\'t have a default value" }, -{ "ER_WRONG_DB_NAME", 1102, "Incorrect database name \'%-.100s\'" }, -{ "ER_WRONG_TABLE_NAME", 1103, "Incorrect table name \'%-.100s\'" }, -{ "ER_TOO_BIG_SELECT", 1104, "The SELECT would examine more than MAX_JOIN_SIZE rows; check your WHERE and use SET SQL_BIG_SELECTS=1 or SET MAX_JOIN_SIZE=# if the SELECT is okay" }, -{ "ER_UNKNOWN_ERROR", 1105, "Unknown error" }, -{ "ER_UNKNOWN_PROCEDURE", 1106, "Unknown procedure \'%-.192s\'" }, -{ "ER_WRONG_PARAMCOUNT_TO_PROCEDURE", 1107, "Incorrect parameter count to procedure \'%-.192s\'" }, -{ "ER_WRONG_PARAMETERS_TO_PROCEDURE", 1108, "Incorrect parameters to procedure \'%-.192s\'" }, -{ "ER_UNKNOWN_TABLE", 1109, "Unknown table \'%-.192s\' in %-.32s" }, -{ "ER_FIELD_SPECIFIED_TWICE", 1110, "Column \'%-.192s\' specified twice" }, -{ "ER_INVALID_GROUP_FUNC_USE", 1111, "Invalid use of group function" }, -{ "ER_UNSUPPORTED_EXTENSION", 1112, "Table \'%-.192s\' uses an extension that doesn\'t exist in this MySQL version" }, -{ "ER_TABLE_MUST_HAVE_COLUMNS", 1113, "A table must have at least 1 column" }, -{ "ER_RECORD_FILE_FULL", 1114, "The table \'%-.192s\' is full" }, -{ "ER_UNKNOWN_CHARACTER_SET", 1115, "Unknown character set: \'%-.64s\'" }, -{ "ER_TOO_MANY_TABLES", 1116, "Too many tables; MySQL can only use %d tables in a join" }, -{ "ER_TOO_MANY_FIELDS", 1117, "Too many columns" }, -{ "ER_TOO_BIG_ROWSIZE", 1118, "Row size too large. The maximum row size for the used table type, not counting BLOBs, is %ld. This includes storage overhead, check the manual. You have to change some columns to TEXT or BLOBs" }, -{ "ER_STACK_OVERRUN", 1119, "Thread stack overrun: Used: %ld of a %ld stack. Use \'mysqld --thread_stack=#\' to specify a bigger stack if needed" }, -{ "ER_WRONG_OUTER_JOIN", 1120, "Cross dependency found in OUTER JOIN; examine your ON conditions" }, -{ "ER_NULL_COLUMN_IN_INDEX", 1121, "Table handler doesn\'t support NULL in given index. Please change column \'%-.192s\' to be NOT NULL or use another handler" }, -{ "ER_CANT_FIND_UDF", 1122, "Can\'t load function \'%-.192s\'" }, -{ "ER_CANT_INITIALIZE_UDF", 1123, "Can\'t initialize function \'%-.192s\'; %-.80s" }, -{ "ER_UDF_NO_PATHS", 1124, "No paths allowed for shared library" }, -{ "ER_UDF_EXISTS", 1125, "Function \'%-.192s\' already exists" }, -{ "ER_CANT_OPEN_LIBRARY", 1126, "Can\'t open shared library \'%-.192s\' (errno: %d %-.128s)" }, -{ "ER_CANT_FIND_DL_ENTRY", 1127, "Can\'t find symbol \'%-.128s\' in library" }, -{ "ER_FUNCTION_NOT_DEFINED", 1128, "Function \'%-.192s\' is not defined" }, -{ "ER_HOST_IS_BLOCKED", 1129, "Host \'%-.64s\' is blocked because of many connection errors; unblock with \'mysqladmin flush-hosts\'" }, -{ "ER_HOST_NOT_PRIVILEGED", 1130, "Host \'%-.64s\' is not allowed to connect to this MySQL server" }, -{ "ER_PASSWORD_ANONYMOUS_USER", 1131, "You are using MySQL as an anonymous user and anonymous users are not allowed to change passwords" }, -{ "ER_PASSWORD_NOT_ALLOWED", 1132, "You must have privileges to update tables in the mysql database to be able to change passwords for others" }, -{ "ER_PASSWORD_NO_MATCH", 1133, "Can\'t find any matching row in the user table" }, -{ "ER_UPDATE_INFO", 1134, "Rows matched: %ld Changed: %ld Warnings: %ld" }, -{ "ER_CANT_CREATE_THREAD", 1135, "Can\'t create a new thread (errno %d); if you are not out of available memory, you can consult the manual for a possible OS-dependent bug" }, -{ "ER_WRONG_VALUE_COUNT_ON_ROW", 1136, "Column count doesn\'t match value count at row %ld" }, -{ "ER_CANT_REOPEN_TABLE", 1137, "Can\'t reopen table: \'%-.192s\'" }, -{ "ER_INVALID_USE_OF_NULL", 1138, "Invalid use of NULL value" }, -{ "ER_REGEXP_ERROR", 1139, "Got error \'%-.64s\' from regexp" }, -{ "ER_MIX_OF_GROUP_FUNC_AND_FIELDS", 1140, "Mixing of GROUP columns (MIN(),MAX(),COUNT(),...) with no GROUP columns is illegal if there is no GROUP BY clause" }, -{ "ER_NONEXISTING_GRANT", 1141, "There is no such grant defined for user \'%-.48s\' on host \'%-.64s\'" }, -{ "ER_TABLEACCESS_DENIED_ERROR", 1142, "%-.128s command denied to user \'%-.48s\'@\'%-.64s\' for table \'%-.64s\'" }, -{ "ER_COLUMNACCESS_DENIED_ERROR", 1143, "%-.16s command denied to user \'%-.48s\'@\'%-.64s\' for column \'%-.192s\' in table \'%-.192s\'" }, -{ "ER_ILLEGAL_GRANT_FOR_TABLE", 1144, "Illegal GRANT/REVOKE command; please consult the manual to see which privileges can be used" }, -{ "ER_GRANT_WRONG_HOST_OR_USER", 1145, "The host or user argument to GRANT is too long" }, -{ "ER_NO_SUCH_TABLE", 1146, "Table \'%-.192s.%-.192s\' doesn\'t exist" }, -{ "ER_NONEXISTING_TABLE_GRANT", 1147, "There is no such grant defined for user \'%-.48s\' on host \'%-.64s\' on table \'%-.192s\'" }, -{ "ER_NOT_ALLOWED_COMMAND", 1148, "The used command is not allowed with this MySQL version" }, -{ "ER_SYNTAX_ERROR", 1149, "You have an error in your SQL syntax; check the manual that corresponds to your MySQL server version for the right syntax to use" }, -{ "ER_UNUSED1", 1150, "Delayed insert thread couldn\'t get requested lock for table %-.192s" }, -{ "ER_UNUSED2", 1151, "Too many delayed threads in use" }, -{ "ER_ABORTING_CONNECTION", 1152, "Aborted connection %ld to db: \'%-.192s\' user: \'%-.48s\' (%-.64s)" }, -{ "ER_NET_PACKET_TOO_LARGE", 1153, "Got a packet bigger than \'max_allowed_packet\' bytes" }, -{ "ER_NET_READ_ERROR_FROM_PIPE", 1154, "Got a read error from the connection pipe" }, -{ "ER_NET_FCNTL_ERROR", 1155, "Got an error from fcntl()" }, -{ "ER_NET_PACKETS_OUT_OF_ORDER", 1156, "Got packets out of order" }, -{ "ER_NET_UNCOMPRESS_ERROR", 1157, "Couldn\'t uncompress communication packet" }, -{ "ER_NET_READ_ERROR", 1158, "Got an error reading communication packets" }, -{ "ER_NET_READ_INTERRUPTED", 1159, "Got timeout reading communication packets" }, -{ "ER_NET_ERROR_ON_WRITE", 1160, "Got an error writing communication packets" }, -{ "ER_NET_WRITE_INTERRUPTED", 1161, "Got timeout writing communication packets" }, -{ "ER_TOO_LONG_STRING", 1162, "Result string is longer than \'max_allowed_packet\' bytes" }, -{ "ER_TABLE_CANT_HANDLE_BLOB", 1163, "The used table type doesn\'t support BLOB/TEXT columns" }, -{ "ER_TABLE_CANT_HANDLE_AUTO_INCREMENT", 1164, "The used table type doesn\'t support AUTO_INCREMENT columns" }, -{ "ER_UNUSED3", 1165, "INSERT DELAYED can\'t be used with table \'%-.192s\' because it is locked with LOCK TABLES" }, -{ "ER_WRONG_COLUMN_NAME", 1166, "Incorrect column name \'%-.100s\'" }, -{ "ER_WRONG_KEY_COLUMN", 1167, "The used storage engine can\'t index column \'%-.192s\'" }, -{ "ER_WRONG_MRG_TABLE", 1168, "Unable to open underlying table which is differently defined or of non-MyISAM type or doesn\'t exist" }, -{ "ER_DUP_UNIQUE", 1169, "Can\'t write, because of unique constraint, to table \'%-.192s\'" }, -{ "ER_BLOB_KEY_WITHOUT_LENGTH", 1170, "BLOB/TEXT column \'%-.192s\' used in key specification without a key length" }, -{ "ER_PRIMARY_CANT_HAVE_NULL", 1171, "All parts of a PRIMARY KEY must be NOT NULL; if you need NULL in a key, use UNIQUE instead" }, -{ "ER_TOO_MANY_ROWS", 1172, "Result consisted of more than one row" }, -{ "ER_REQUIRES_PRIMARY_KEY", 1173, "This table type requires a primary key" }, -{ "ER_NO_RAID_COMPILED", 1174, "This version of MySQL is not compiled with RAID support" }, -{ "ER_UPDATE_WITHOUT_KEY_IN_SAFE_MODE", 1175, "You are using safe update mode and you tried to update a table without a WHERE that uses a KEY column" }, -{ "ER_KEY_DOES_NOT_EXITS", 1176, "Key \'%-.192s\' doesn\'t exist in table \'%-.192s\'" }, -{ "ER_CHECK_NO_SUCH_TABLE", 1177, "Can\'t open table" }, -{ "ER_CHECK_NOT_IMPLEMENTED", 1178, "The storage engine for the table doesn\'t support %s" }, -{ "ER_CANT_DO_THIS_DURING_AN_TRANSACTION", 1179, "You are not allowed to execute this command in a transaction" }, -{ "ER_ERROR_DURING_COMMIT", 1180, "Got error %d during COMMIT" }, -{ "ER_ERROR_DURING_ROLLBACK", 1181, "Got error %d during ROLLBACK" }, -{ "ER_ERROR_DURING_FLUSH_LOGS", 1182, "Got error %d during FLUSH_LOGS" }, -{ "ER_ERROR_DURING_CHECKPOINT", 1183, "Got error %d during CHECKPOINT" }, -{ "ER_NEW_ABORTING_CONNECTION", 1184, "Aborted connection %u to db: \'%-.192s\' user: \'%-.48s\' host: \'%-.64s\' (%-.64s)" }, -{ "ER_DUMP_NOT_IMPLEMENTED", 1185, "The storage engine for the table does not support binary table dump" }, -{ "ER_FLUSH_MASTER_BINLOG_CLOSED", 1186, "Binlog closed, cannot RESET MASTER" }, -{ "ER_INDEX_REBUILD", 1187, "Failed rebuilding the index of dumped table \'%-.192s\'" }, -{ "ER_MASTER", 1188, "Error from master: \'%-.64s\'" }, -{ "ER_MASTER_NET_READ", 1189, "Net error reading from master" }, -{ "ER_MASTER_NET_WRITE", 1190, "Net error writing to master" }, -{ "ER_FT_MATCHING_KEY_NOT_FOUND", 1191, "Can\'t find FULLTEXT index matching the column list" }, -{ "ER_LOCK_OR_ACTIVE_TRANSACTION", 1192, "Can\'t execute the given command because you have active locked tables or an active transaction" }, -{ "ER_UNKNOWN_SYSTEM_VARIABLE", 1193, "Unknown system variable \'%-.64s\'" }, -{ "ER_CRASHED_ON_USAGE", 1194, "Table \'%-.192s\' is marked as crashed and should be repaired" }, -{ "ER_CRASHED_ON_REPAIR", 1195, "Table \'%-.192s\' is marked as crashed and last (automatic?) repair failed" }, -{ "ER_WARNING_NOT_COMPLETE_ROLLBACK", 1196, "Some non-transactional changed tables couldn\'t be rolled back" }, -{ "ER_TRANS_CACHE_FULL", 1197, "Multi-statement transaction required more than \'max_binlog_cache_size\' bytes of storage; increase this mysqld variable and try again" }, -{ "ER_SLAVE_MUST_STOP", 1198, "This operation cannot be performed with a running slave; run STOP SLAVE first" }, -{ "ER_SLAVE_NOT_RUNNING", 1199, "This operation requires a running slave; configure slave and do START SLAVE" }, -{ "ER_BAD_SLAVE", 1200, "The server is not configured as slave; fix in config file or with CHANGE MASTER TO" }, -{ "ER_MASTER_INFO", 1201, "Could not initialize master info structure; more error messages can be found in the MySQL error log" }, -{ "ER_SLAVE_THREAD", 1202, "Could not create slave thread; check system resources" }, -{ "ER_TOO_MANY_USER_CONNECTIONS", 1203, "User %-.64s already has more than \'max_user_connections\' active connections" }, -{ "ER_SET_CONSTANTS_ONLY", 1204, "You may only use constant expressions with SET" }, -{ "ER_LOCK_WAIT_TIMEOUT", 1205, "Lock wait timeout exceeded; try restarting transaction" }, -{ "ER_LOCK_TABLE_FULL", 1206, "The total number of locks exceeds the lock table size" }, -{ "ER_READ_ONLY_TRANSACTION", 1207, "Update locks cannot be acquired during a READ UNCOMMITTED transaction" }, -{ "ER_DROP_DB_WITH_READ_LOCK", 1208, "DROP DATABASE not allowed while thread is holding global read lock" }, -{ "ER_CREATE_DB_WITH_READ_LOCK", 1209, "CREATE DATABASE not allowed while thread is holding global read lock" }, -{ "ER_WRONG_ARGUMENTS", 1210, "Incorrect arguments to %s" }, -{ "ER_NO_PERMISSION_TO_CREATE_USER", 1211, "\'%-.48s\'@\'%-.64s\' is not allowed to create new users" }, -{ "ER_UNION_TABLES_IN_DIFFERENT_DIR", 1212, "Incorrect table definition; all MERGE tables must be in the same database" }, -{ "ER_LOCK_DEADLOCK", 1213, "Deadlock found when trying to get lock; try restarting transaction" }, -{ "ER_TABLE_CANT_HANDLE_FT", 1214, "The used table type doesn\'t support FULLTEXT indexes" }, -{ "ER_CANNOT_ADD_FOREIGN", 1215, "Cannot add foreign key constraint" }, -{ "ER_NO_REFERENCED_ROW", 1216, "Cannot add or update a child row: a foreign key constraint fails" }, -{ "ER_ROW_IS_REFERENCED", 1217, "Cannot delete or update a parent row: a foreign key constraint fails" }, -{ "ER_CONNECT_TO_MASTER", 1218, "Error connecting to master: %-.128s" }, -{ "ER_QUERY_ON_MASTER", 1219, "Error running query on master: %-.128s" }, -{ "ER_ERROR_WHEN_EXECUTING_COMMAND", 1220, "Error when executing command %s: %-.128s" }, -{ "ER_WRONG_USAGE", 1221, "Incorrect usage of %s and %s" }, -{ "ER_WRONG_NUMBER_OF_COLUMNS_IN_SELECT", 1222, "The used SELECT statements have a different number of columns" }, -{ "ER_CANT_UPDATE_WITH_READLOCK", 1223, "Can\'t execute the query because you have a conflicting read lock" }, -{ "ER_MIXING_NOT_ALLOWED", 1224, "Mixing of transactional and non-transactional tables is disabled" }, -{ "ER_DUP_ARGUMENT", 1225, "Option \'%s\' used twice in statement" }, -{ "ER_USER_LIMIT_REACHED", 1226, "User \'%-.64s\' has exceeded the \'%s\' resource (current value: %ld)" }, -{ "ER_SPECIFIC_ACCESS_DENIED_ERROR", 1227, "Access denied; you need (at least one of) the %-.128s privilege(s) for this operation" }, -{ "ER_LOCAL_VARIABLE", 1228, "Variable \'%-.64s\' is a SESSION variable and can\'t be used with SET GLOBAL" }, -{ "ER_GLOBAL_VARIABLE", 1229, "Variable \'%-.64s\' is a GLOBAL variable and should be set with SET GLOBAL" }, -{ "ER_NO_DEFAULT", 1230, "Variable \'%-.64s\' doesn\'t have a default value" }, -{ "ER_WRONG_VALUE_FOR_VAR", 1231, "Variable \'%-.64s\' can\'t be set to the value of \'%-.200s\'" }, -{ "ER_WRONG_TYPE_FOR_VAR", 1232, "Incorrect argument type to variable \'%-.64s\'" }, -{ "ER_VAR_CANT_BE_READ", 1233, "Variable \'%-.64s\' can only be set, not read" }, -{ "ER_CANT_USE_OPTION_HERE", 1234, "Incorrect usage/placement of \'%s\'" }, -{ "ER_NOT_SUPPORTED_YET", 1235, "This version of MySQL doesn\'t yet support \'%s\'" }, -{ "ER_MASTER_FATAL_ERROR_READING_BINLOG", 1236, "Got fatal error %d from master when reading data from binary log: \'%-.320s\'" }, -{ "ER_SLAVE_IGNORED_TABLE", 1237, "Slave SQL thread ignored the query because of replicate-*-table rules" }, -{ "ER_INCORRECT_GLOBAL_LOCAL_VAR", 1238, "Variable \'%-.192s\' is a %s variable" }, -{ "ER_WRONG_FK_DEF", 1239, "Incorrect foreign key definition for \'%-.192s\': %s" }, -{ "ER_KEY_REF_DO_NOT_MATCH_TABLE_REF", 1240, "Key reference and table reference don\'t match" }, -{ "ER_OPERAND_COLUMNS", 1241, "Operand should contain %d column(s)" }, -{ "ER_SUBQUERY_NO_1_ROW", 1242, "Subquery returns more than 1 row" }, -{ "ER_UNKNOWN_STMT_HANDLER", 1243, "Unknown prepared statement handler (%.*s) given to %s" }, -{ "ER_CORRUPT_HELP_DB", 1244, "Help database is corrupt or does not exist" }, -{ "ER_CYCLIC_REFERENCE", 1245, "Cyclic reference on subqueries" }, -{ "ER_AUTO_CONVERT", 1246, "Converting column \'%s\' from %s to %s" }, -{ "ER_ILLEGAL_REFERENCE", 1247, "Reference \'%-.64s\' not supported (%s)" }, -{ "ER_DERIVED_MUST_HAVE_ALIAS", 1248, "Every derived table must have its own alias" }, -{ "ER_SELECT_REDUCED", 1249, "Select %u was reduced during optimization" }, -{ "ER_TABLENAME_NOT_ALLOWED_HERE", 1250, "Table \'%-.192s\' from one of the SELECTs cannot be used in %-.32s" }, -{ "ER_NOT_SUPPORTED_AUTH_MODE", 1251, "Client does not support authentication protocol requested by server; consider upgrading MySQL client" }, -{ "ER_SPATIAL_CANT_HAVE_NULL", 1252, "All parts of a SPATIAL index must be NOT NULL" }, -{ "ER_COLLATION_CHARSET_MISMATCH", 1253, "COLLATION \'%s\' is not valid for CHARACTER SET \'%s\'" }, -{ "ER_SLAVE_WAS_RUNNING", 1254, "Slave is already running" }, -{ "ER_SLAVE_WAS_NOT_RUNNING", 1255, "Slave already has been stopped" }, -{ "ER_TOO_BIG_FOR_UNCOMPRESS", 1256, "Uncompressed data size too large; the maximum size is %d (probably, length of uncompressed data was corrupted)" }, -{ "ER_ZLIB_Z_MEM_ERROR", 1257, "ZLIB: Not enough memory" }, -{ "ER_ZLIB_Z_BUF_ERROR", 1258, "ZLIB: Not enough room in the output buffer (probably, length of uncompressed data was corrupted)" }, -{ "ER_ZLIB_Z_DATA_ERROR", 1259, "ZLIB: Input data corrupted" }, -{ "ER_CUT_VALUE_GROUP_CONCAT", 1260, "Row %u was cut by GROUP_CONCAT()" }, -{ "ER_WARN_TOO_FEW_RECORDS", 1261, "Row %ld doesn\'t contain data for all columns" }, -{ "ER_WARN_TOO_MANY_RECORDS", 1262, "Row %ld was truncated; it contained more data than there were input columns" }, -{ "ER_WARN_NULL_TO_NOTNULL", 1263, "Column set to default value; NULL supplied to NOT NULL column \'%s\' at row %ld" }, -{ "ER_WARN_DATA_OUT_OF_RANGE", 1264, "Out of range value for column \'%s\' at row %ld" }, -{ "WARN_DATA_TRUNCATED", 1265, "Data truncated for column \'%s\' at row %ld" }, -{ "ER_WARN_USING_OTHER_HANDLER", 1266, "Using storage engine %s for table \'%s\'" }, -{ "ER_CANT_AGGREGATE_2COLLATIONS", 1267, "Illegal mix of collations (%s,%s) and (%s,%s) for operation \'%s\'" }, -{ "ER_DROP_USER", 1268, "Cannot drop one or more of the requested users" }, -{ "ER_REVOKE_GRANTS", 1269, "Can\'t revoke all privileges for one or more of the requested users" }, -{ "ER_CANT_AGGREGATE_3COLLATIONS", 1270, "Illegal mix of collations (%s,%s), (%s,%s), (%s,%s) for operation \'%s\'" }, -{ "ER_CANT_AGGREGATE_NCOLLATIONS", 1271, "Illegal mix of collations for operation \'%s\'" }, -{ "ER_VARIABLE_IS_NOT_STRUCT", 1272, "Variable \'%-.64s\' is not a variable component (can\'t be used as XXXX.variable_name)" }, -{ "ER_UNKNOWN_COLLATION", 1273, "Unknown collation: \'%-.64s\'" }, -{ "ER_SLAVE_IGNORED_SSL_PARAMS", 1274, "SSL parameters in CHANGE MASTER are ignored because this MySQL slave was compiled without SSL support; they can be used later if MySQL slave with SSL is started" }, -{ "ER_SERVER_IS_IN_SECURE_AUTH_MODE", 1275, "Server is running in --secure-auth mode, but \'%s\'@\'%s\' has a password in the old format; please change the password to the new format" }, -{ "ER_WARN_FIELD_RESOLVED", 1276, "Field or reference \'%-.192s%s%-.192s%s%-.192s\' of SELECT #%d was resolved in SELECT #%d" }, -{ "ER_BAD_SLAVE_UNTIL_COND", 1277, "Incorrect parameter or combination of parameters for START SLAVE UNTIL" }, -{ "ER_MISSING_SKIP_SLAVE", 1278, "It is recommended to use --skip-slave-start when doing step-by-step replication with START SLAVE UNTIL; otherwise, you will get problems if you get an unexpected slave\'s mysqld restart" }, -{ "ER_UNTIL_COND_IGNORED", 1279, "SQL thread is not to be started so UNTIL options are ignored" }, -{ "ER_WRONG_NAME_FOR_INDEX", 1280, "Incorrect index name \'%-.100s\'" }, -{ "ER_WRONG_NAME_FOR_CATALOG", 1281, "Incorrect catalog name \'%-.100s\'" }, -{ "ER_WARN_QC_RESIZE", 1282, "Query cache failed to set size %lu; new query cache size is %lu" }, -{ "ER_BAD_FT_COLUMN", 1283, "Column \'%-.192s\' cannot be part of FULLTEXT index" }, -{ "ER_UNKNOWN_KEY_CACHE", 1284, "Unknown key cache \'%-.100s\'" }, -{ "ER_WARN_HOSTNAME_WONT_WORK", 1285, "MySQL is started in --skip-name-resolve mode; you must restart it without this switch for this grant to work" }, -{ "ER_UNKNOWN_STORAGE_ENGINE", 1286, "Unknown storage engine \'%s\'" }, -{ "ER_WARN_DEPRECATED_SYNTAX", 1287, "\'%s\' is deprecated and will be removed in a future release. Please use %s instead" }, -{ "ER_NON_UPDATABLE_TABLE", 1288, "The target table %-.100s of the %s is not updatable" }, -{ "ER_FEATURE_DISABLED", 1289, "The \'%s\' feature is disabled; you need MySQL built with \'%s\' to have it working" }, -{ "ER_OPTION_PREVENTS_STATEMENT", 1290, "The MySQL server is running with the %s option so it cannot execute this statement" }, -{ "ER_DUPLICATED_VALUE_IN_TYPE", 1291, "Column \'%-.100s\' has duplicated value \'%-.64s\' in %s" }, -{ "ER_TRUNCATED_WRONG_VALUE", 1292, "Truncated incorrect %-.32s value: \'%-.128s\'" }, -{ "ER_TOO_MUCH_AUTO_TIMESTAMP_COLS", 1293, "Incorrect table definition; there can be only one TIMESTAMP column with CURRENT_TIMESTAMP in DEFAULT or ON UPDATE clause" }, -{ "ER_INVALID_ON_UPDATE", 1294, "Invalid ON UPDATE clause for \'%-.192s\' column" }, -{ "ER_UNSUPPORTED_PS", 1295, "This command is not supported in the prepared statement protocol yet" }, -{ "ER_GET_ERRMSG", 1296, "Got error %d \'%-.100s\' from %s" }, -{ "ER_GET_TEMPORARY_ERRMSG", 1297, "Got temporary error %d \'%-.100s\' from %s" }, -{ "ER_UNKNOWN_TIME_ZONE", 1298, "Unknown or incorrect time zone: \'%-.64s\'" }, -{ "ER_WARN_INVALID_TIMESTAMP", 1299, "Invalid TIMESTAMP value in column \'%s\' at row %ld" }, -{ "ER_INVALID_CHARACTER_STRING", 1300, "Invalid %s character string: \'%.64s\'" }, -{ "ER_WARN_ALLOWED_PACKET_OVERFLOWED", 1301, "Result of %s() was larger than max_allowed_packet (%ld) - truncated" }, -{ "ER_CONFLICTING_DECLARATIONS", 1302, "Conflicting declarations: \'%s%s\' and \'%s%s\'" }, -{ "ER_SP_NO_RECURSIVE_CREATE", 1303, "Can\'t create a %s from within another stored routine" }, -{ "ER_SP_ALREADY_EXISTS", 1304, "%s %s already exists" }, -{ "ER_SP_DOES_NOT_EXIST", 1305, "%s %s does not exist" }, -{ "ER_SP_DROP_FAILED", 1306, "Failed to DROP %s %s" }, -{ "ER_SP_STORE_FAILED", 1307, "Failed to CREATE %s %s" }, -{ "ER_SP_LILABEL_MISMATCH", 1308, "%s with no matching label: %s" }, -{ "ER_SP_LABEL_REDEFINE", 1309, "Redefining label %s" }, -{ "ER_SP_LABEL_MISMATCH", 1310, "End-label %s without match" }, -{ "ER_SP_UNINIT_VAR", 1311, "Referring to uninitialized variable %s" }, -{ "ER_SP_BADSELECT", 1312, "PROCEDURE %s can\'t return a result set in the given context" }, -{ "ER_SP_BADRETURN", 1313, "RETURN is only allowed in a FUNCTION" }, -{ "ER_SP_BADSTATEMENT", 1314, "%s is not allowed in stored procedures" }, -{ "ER_UPDATE_LOG_DEPRECATED_IGNORED", 1315, "The update log is deprecated and replaced by the binary log; SET SQL_LOG_UPDATE has been ignored." }, -{ "ER_UPDATE_LOG_DEPRECATED_TRANSLATED", 1316, "The update log is deprecated and replaced by the binary log; SET SQL_LOG_UPDATE has been translated to SET SQL_LOG_BIN." }, -{ "ER_QUERY_INTERRUPTED", 1317, "Query execution was interrupted" }, -{ "ER_SP_WRONG_NO_OF_ARGS", 1318, "Incorrect number of arguments for %s %s; expected %u, got %u" }, -{ "ER_SP_COND_MISMATCH", 1319, "Undefined CONDITION: %s" }, -{ "ER_SP_NORETURN", 1320, "No RETURN found in FUNCTION %s" }, -{ "ER_SP_NORETURNEND", 1321, "FUNCTION %s ended without RETURN" }, -{ "ER_SP_BAD_CURSOR_QUERY", 1322, "Cursor statement must be a SELECT" }, -{ "ER_SP_BAD_CURSOR_SELECT", 1323, "Cursor SELECT must not have INTO" }, -{ "ER_SP_CURSOR_MISMATCH", 1324, "Undefined CURSOR: %s" }, -{ "ER_SP_CURSOR_ALREADY_OPEN", 1325, "Cursor is already open" }, -{ "ER_SP_CURSOR_NOT_OPEN", 1326, "Cursor is not open" }, -{ "ER_SP_UNDECLARED_VAR", 1327, "Undeclared variable: %s" }, -{ "ER_SP_WRONG_NO_OF_FETCH_ARGS", 1328, "Incorrect number of FETCH variables" }, -{ "ER_SP_FETCH_NO_DATA", 1329, "No data - zero rows fetched, selected, or processed" }, -{ "ER_SP_DUP_PARAM", 1330, "Duplicate parameter: %s" }, -{ "ER_SP_DUP_VAR", 1331, "Duplicate variable: %s" }, -{ "ER_SP_DUP_COND", 1332, "Duplicate condition: %s" }, -{ "ER_SP_DUP_CURS", 1333, "Duplicate cursor: %s" }, -{ "ER_SP_CANT_ALTER", 1334, "Failed to ALTER %s %s" }, -{ "ER_SP_SUBSELECT_NYI", 1335, "Subquery value not supported" }, -{ "ER_STMT_NOT_ALLOWED_IN_SF_OR_TRG", 1336, "%s is not allowed in stored function or trigger" }, -{ "ER_SP_VARCOND_AFTER_CURSHNDLR", 1337, "Variable or condition declaration after cursor or handler declaration" }, -{ "ER_SP_CURSOR_AFTER_HANDLER", 1338, "Cursor declaration after handler declaration" }, -{ "ER_SP_CASE_NOT_FOUND", 1339, "Case not found for CASE statement" }, -{ "ER_FPARSER_TOO_BIG_FILE", 1340, "Configuration file \'%-.192s\' is too big" }, -{ "ER_FPARSER_BAD_HEADER", 1341, "Malformed file type header in file \'%-.192s\'" }, -{ "ER_FPARSER_EOF_IN_COMMENT", 1342, "Unexpected end of file while parsing comment \'%-.200s\'" }, -{ "ER_FPARSER_ERROR_IN_PARAMETER", 1343, "Error while parsing parameter \'%-.192s\' (line: \'%-.192s\')" }, -{ "ER_FPARSER_EOF_IN_UNKNOWN_PARAMETER", 1344, "Unexpected end of file while skipping unknown parameter \'%-.192s\'" }, -{ "ER_VIEW_NO_EXPLAIN", 1345, "EXPLAIN/SHOW can not be issued; lacking privileges for underlying table" }, -{ "ER_FRM_UNKNOWN_TYPE", 1346, "File \'%-.192s\' has unknown type \'%-.64s\' in its header" }, -{ "ER_WRONG_OBJECT", 1347, "\'%-.192s.%-.192s\' is not %s" }, -{ "ER_NONUPDATEABLE_COLUMN", 1348, "Column \'%-.192s\' is not updatable" }, -{ "ER_VIEW_SELECT_DERIVED_UNUSED", 1349, "View\'s SELECT contains a subquery in the FROM clause" }, -{ "ER_VIEW_SELECT_CLAUSE", 1350, "View\'s SELECT contains a \'%s\' clause" }, -{ "ER_VIEW_SELECT_VARIABLE", 1351, "View\'s SELECT contains a variable or parameter" }, -{ "ER_VIEW_SELECT_TMPTABLE", 1352, "View\'s SELECT refers to a temporary table \'%-.192s\'" }, -{ "ER_VIEW_WRONG_LIST", 1353, "View\'s SELECT and view\'s field list have different column counts" }, -{ "ER_WARN_VIEW_MERGE", 1354, "View merge algorithm can\'t be used here for now (assumed undefined algorithm)" }, -{ "ER_WARN_VIEW_WITHOUT_KEY", 1355, "View being updated does not have complete key of underlying table in it" }, -{ "ER_VIEW_INVALID", 1356, "View \'%-.192s.%-.192s\' references invalid table(s) or column(s) or function(s) or definer/invoker of view lack rights to use them" }, -{ "ER_SP_NO_DROP_SP", 1357, "Can\'t drop or alter a %s from within another stored routine" }, -{ "ER_SP_GOTO_IN_HNDLR", 1358, "GOTO is not allowed in a stored procedure handler" }, -{ "ER_TRG_ALREADY_EXISTS", 1359, "Trigger already exists" }, -{ "ER_TRG_DOES_NOT_EXIST", 1360, "Trigger does not exist" }, -{ "ER_TRG_ON_VIEW_OR_TEMP_TABLE", 1361, "Trigger\'s \'%-.192s\' is view or temporary table" }, -{ "ER_TRG_CANT_CHANGE_ROW", 1362, "Updating of %s row is not allowed in %strigger" }, -{ "ER_TRG_NO_SUCH_ROW_IN_TRG", 1363, "There is no %s row in %s trigger" }, -{ "ER_NO_DEFAULT_FOR_FIELD", 1364, "Field \'%-.192s\' doesn\'t have a default value" }, -{ "ER_DIVISION_BY_ZERO", 1365, "Division by 0" }, -{ "ER_TRUNCATED_WRONG_VALUE_FOR_FIELD", 1366, "Incorrect %-.32s value: \'%-.128s\' for column \'%.192s\' at row %ld" }, -{ "ER_ILLEGAL_VALUE_FOR_TYPE", 1367, "Illegal %s \'%-.192s\' value found during parsing" }, -{ "ER_VIEW_NONUPD_CHECK", 1368, "CHECK OPTION on non-updatable view \'%-.192s.%-.192s\'" }, -{ "ER_VIEW_CHECK_FAILED", 1369, "CHECK OPTION failed \'%-.192s.%-.192s\'" }, -{ "ER_PROCACCESS_DENIED_ERROR", 1370, "%-.16s command denied to user \'%-.48s\'@\'%-.64s\' for routine \'%-.192s\'" }, -{ "ER_RELAY_LOG_FAIL", 1371, "Failed purging old relay logs: %s" }, -{ "ER_PASSWD_LENGTH", 1372, "Password hash should be a %d-digit hexadecimal number" }, -{ "ER_UNKNOWN_TARGET_BINLOG", 1373, "Target log not found in binlog index" }, -{ "ER_IO_ERR_LOG_INDEX_READ", 1374, "I/O error reading log index file" }, -{ "ER_BINLOG_PURGE_PROHIBITED", 1375, "Server configuration does not permit binlog purge" }, -{ "ER_FSEEK_FAIL", 1376, "Failed on fseek()" }, -{ "ER_BINLOG_PURGE_FATAL_ERR", 1377, "Fatal error during log purge" }, -{ "ER_LOG_IN_USE", 1378, "A purgeable log is in use, will not purge" }, -{ "ER_LOG_PURGE_UNKNOWN_ERR", 1379, "Unknown error during log purge" }, -{ "ER_RELAY_LOG_INIT", 1380, "Failed initializing relay log position: %s" }, -{ "ER_NO_BINARY_LOGGING", 1381, "You are not using binary logging" }, -{ "ER_RESERVED_SYNTAX", 1382, "The \'%-.64s\' syntax is reserved for purposes internal to the MySQL server" }, -{ "ER_WSAS_FAILED", 1383, "WSAStartup Failed" }, -{ "ER_DIFF_GROUPS_PROC", 1384, "Can\'t handle procedures with different groups yet" }, -{ "ER_NO_GROUP_FOR_PROC", 1385, "Select must have a group with this procedure" }, -{ "ER_ORDER_WITH_PROC", 1386, "Can\'t use ORDER clause with this procedure" }, -{ "ER_LOGGING_PROHIBIT_CHANGING_OF", 1387, "Binary logging and replication forbid changing the global server %s" }, -{ "ER_NO_FILE_MAPPING", 1388, "Can\'t map file: %-.200s, errno: %d" }, -{ "ER_WRONG_MAGIC", 1389, "Wrong magic in %-.64s" }, -{ "ER_PS_MANY_PARAM", 1390, "Prepared statement contains too many placeholders" }, -{ "ER_KEY_PART_0", 1391, "Key part \'%-.192s\' length cannot be 0" }, -{ "ER_VIEW_CHECKSUM", 1392, "View text checksum failed" }, -{ "ER_VIEW_MULTIUPDATE", 1393, "Can not modify more than one base table through a join view \'%-.192s.%-.192s\'" }, -{ "ER_VIEW_NO_INSERT_FIELD_LIST", 1394, "Can not insert into join view \'%-.192s.%-.192s\' without fields list" }, -{ "ER_VIEW_DELETE_MERGE_VIEW", 1395, "Can not delete from join view \'%-.192s.%-.192s\'" }, -{ "ER_CANNOT_USER", 1396, "Operation %s failed for %.256s" }, -{ "ER_XAER_NOTA", 1397, "XAER_NOTA: Unknown XID" }, -{ "ER_XAER_INVAL", 1398, "XAER_INVAL: Invalid arguments (or unsupported command)" }, -{ "ER_XAER_RMFAIL", 1399, "XAER_RMFAIL: The command cannot be executed when global transaction is in the %.64s state" }, -{ "ER_XAER_OUTSIDE", 1400, "XAER_OUTSIDE: Some work is done outside global transaction" }, -{ "ER_XAER_RMERR", 1401, "XAER_RMERR: Fatal error occurred in the transaction branch - check your data for consistency" }, -{ "ER_XA_RBROLLBACK", 1402, "XA_RBROLLBACK: Transaction branch was rolled back" }, -{ "ER_NONEXISTING_PROC_GRANT", 1403, "There is no such grant defined for user \'%-.48s\' on host \'%-.64s\' on routine \'%-.192s\'" }, -{ "ER_PROC_AUTO_GRANT_FAIL", 1404, "Failed to grant EXECUTE and ALTER ROUTINE privileges" }, -{ "ER_PROC_AUTO_REVOKE_FAIL", 1405, "Failed to revoke all privileges to dropped routine" }, -{ "ER_DATA_TOO_LONG", 1406, "Data too long for column \'%s\' at row %ld" }, -{ "ER_SP_BAD_SQLSTATE", 1407, "Bad SQLSTATE: \'%s\'" }, -{ "ER_STARTUP", 1408, "%s: ready for connections.\nVersion: \'%s\' socket: \'%s\' port: %d %s" }, -{ "ER_LOAD_FROM_FIXED_SIZE_ROWS_TO_VAR", 1409, "Can\'t load value from file with fixed size rows to variable" }, -{ "ER_CANT_CREATE_USER_WITH_GRANT", 1410, "You are not allowed to create a user with GRANT" }, -{ "ER_WRONG_VALUE_FOR_TYPE", 1411, "Incorrect %-.32s value: \'%-.128s\' for function %-.32s" }, -{ "ER_TABLE_DEF_CHANGED", 1412, "Table definition has changed, please retry transaction" }, -{ "ER_SP_DUP_HANDLER", 1413, "Duplicate handler declared in the same block" }, -{ "ER_SP_NOT_VAR_ARG", 1414, "OUT or INOUT argument %d for routine %s is not a variable or NEW pseudo-variable in BEFORE trigger" }, -{ "ER_SP_NO_RETSET", 1415, "Not allowed to return a result set from a %s" }, -{ "ER_CANT_CREATE_GEOMETRY_OBJECT", 1416, "Cannot get geometry object from data you send to the GEOMETRY field" }, -{ "ER_FAILED_ROUTINE_BREAK_BINLOG", 1417, "A routine failed and has neither NO SQL nor READS SQL DATA in its declaration and binary logging is enabled; if non-transactional tables were updated, the binary log will miss their changes" }, -{ "ER_BINLOG_UNSAFE_ROUTINE", 1418, "This function has none of DETERMINISTIC, NO SQL, or READS SQL DATA in its declaration and binary logging is enabled (you *might* want to use the less safe log_bin_trust_function_creators variable)" }, -{ "ER_BINLOG_CREATE_ROUTINE_NEED_SUPER", 1419, "You do not have the SUPER privilege and binary logging is enabled (you *might* want to use the less safe log_bin_trust_function_creators variable)" }, -{ "ER_EXEC_STMT_WITH_OPEN_CURSOR", 1420, "You can\'t execute a prepared statement which has an open cursor associated with it. Reset the statement to re-execute it." }, -{ "ER_STMT_HAS_NO_OPEN_CURSOR", 1421, "The statement (%lu) has no open cursor." }, -{ "ER_COMMIT_NOT_ALLOWED_IN_SF_OR_TRG", 1422, "Explicit or implicit commit is not allowed in stored function or trigger." }, -{ "ER_NO_DEFAULT_FOR_VIEW_FIELD", 1423, "Field of view \'%-.192s.%-.192s\' underlying table doesn\'t have a default value" }, -{ "ER_SP_NO_RECURSION", 1424, "Recursive stored functions and triggers are not allowed." }, -{ "ER_TOO_BIG_SCALE", 1425, "Too big scale %d specified for column \'%-.192s\'. Maximum is %lu." }, -{ "ER_TOO_BIG_PRECISION", 1426, "Too-big precision %d specified for \'%-.192s\'. Maximum is %lu." }, -{ "ER_M_BIGGER_THAN_D", 1427, "For float(M,D), double(M,D) or decimal(M,D), M must be >= D (column \'%-.192s\')." }, -{ "ER_WRONG_LOCK_OF_SYSTEM_TABLE", 1428, "You can\'t combine write-locking of system tables with other tables or lock types" }, -{ "ER_CONNECT_TO_FOREIGN_DATA_SOURCE", 1429, "Unable to connect to foreign data source: %.64s" }, -{ "ER_QUERY_ON_FOREIGN_DATA_SOURCE", 1430, "There was a problem processing the query on the foreign data source. Data source error: %-.64s" }, -{ "ER_FOREIGN_DATA_SOURCE_DOESNT_EXIST", 1431, "The foreign data source you are trying to reference does not exist. Data source error: %-.64s" }, -{ "ER_FOREIGN_DATA_STRING_INVALID_CANT_CREATE", 1432, "Can\'t create federated table. The data source connection string \'%-.64s\' is not in the correct format" }, -{ "ER_FOREIGN_DATA_STRING_INVALID", 1433, "The data source connection string \'%-.64s\' is not in the correct format" }, -{ "ER_CANT_CREATE_FEDERATED_TABLE", 1434, "Can\'t create federated table. Foreign data src error: %-.64s" }, -{ "ER_TRG_IN_WRONG_SCHEMA", 1435, "Trigger in wrong schema" }, -{ "ER_STACK_OVERRUN_NEED_MORE", 1436, "Thread stack overrun: %ld bytes used of a %ld byte stack, and %ld bytes needed. Use \'mysqld --thread_stack=#\' to specify a bigger stack." }, -{ "ER_TOO_LONG_BODY", 1437, "Routine body for \'%-.100s\' is too long" }, -{ "ER_WARN_CANT_DROP_DEFAULT_KEYCACHE", 1438, "Cannot drop default keycache" }, -{ "ER_TOO_BIG_DISPLAYWIDTH", 1439, "Display width out of range for column \'%-.192s\' (max = %lu)" }, -{ "ER_XAER_DUPID", 1440, "XAER_DUPID: The XID already exists" }, -{ "ER_DATETIME_FUNCTION_OVERFLOW", 1441, "Datetime function: %-.32s field overflow" }, -{ "ER_CANT_UPDATE_USED_TABLE_IN_SF_OR_TRG", 1442, "Can\'t update table \'%-.192s\' in stored function/trigger because it is already used by statement which invoked this stored function/trigger." }, -{ "ER_VIEW_PREVENT_UPDATE", 1443, "The definition of table \'%-.192s\' prevents operation %.192s on table \'%-.192s\'." }, -{ "ER_PS_NO_RECURSION", 1444, "The prepared statement contains a stored routine call that refers to that same statement. It\'s not allowed to execute a prepared statement in such a recursive manner" }, -{ "ER_SP_CANT_SET_AUTOCOMMIT", 1445, "Not allowed to set autocommit from a stored function or trigger" }, -{ "ER_MALFORMED_DEFINER", 1446, "Definer is not fully qualified" }, -{ "ER_VIEW_FRM_NO_USER", 1447, "View \'%-.192s\'.\'%-.192s\' has no definer information (old table format). Current user is used as definer. Please recreate the view!" }, -{ "ER_VIEW_OTHER_USER", 1448, "You need the SUPER privilege for creation view with \'%-.192s\'@\'%-.192s\' definer" }, -{ "ER_NO_SUCH_USER", 1449, "The user specified as a definer (\'%-.64s\'@\'%-.64s\') does not exist" }, -{ "ER_FORBID_SCHEMA_CHANGE", 1450, "Changing schema from \'%-.192s\' to \'%-.192s\' is not allowed." }, -{ "ER_ROW_IS_REFERENCED_2", 1451, "Cannot delete or update a parent row: a foreign key constraint fails (%.192s)" }, -{ "ER_NO_REFERENCED_ROW_2", 1452, "Cannot add or update a child row: a foreign key constraint fails (%.192s)" }, -{ "ER_SP_BAD_VAR_SHADOW", 1453, "Variable \'%-.64s\' must be quoted with `...`, or renamed" }, -{ "ER_TRG_NO_DEFINER", 1454, "No definer attribute for trigger \'%-.192s\'.\'%-.192s\'. The trigger will be activated under the authorization of the invoker, which may have insufficient privileges. Please recreate the trigger." }, -{ "ER_OLD_FILE_FORMAT", 1455, "\'%-.192s\' has an old format, you should re-create the \'%s\' object(s)" }, -{ "ER_SP_RECURSION_LIMIT", 1456, "Recursive limit %d (as set by the max_sp_recursion_depth variable) was exceeded for routine %.192s" }, -{ "ER_SP_PROC_TABLE_CORRUPT", 1457, "Failed to load routine %-.192s. The table mysql.proc is missing, corrupt, or contains bad data (internal code %d)" }, -{ "ER_SP_WRONG_NAME", 1458, "Incorrect routine name \'%-.192s\'" }, -{ "ER_TABLE_NEEDS_UPGRADE", 1459, "Table upgrade required. Please do \"REPAIR TABLE `%-.64s`\" or dump/reload to fix it!" }, -{ "ER_SP_NO_AGGREGATE", 1460, "AGGREGATE is not supported for stored functions" }, -{ "ER_MAX_PREPARED_STMT_COUNT_REACHED", 1461, "Can\'t create more than max_prepared_stmt_count statements (current value: %lu)" }, -{ "ER_VIEW_RECURSIVE", 1462, "`%-.192s`.`%-.192s` contains view recursion" }, -{ "ER_NON_GROUPING_FIELD_USED", 1463, "Non-grouping field \'%-.192s\' is used in %-.64s clause" }, -{ "ER_TABLE_CANT_HANDLE_SPKEYS", 1464, "The used table type doesn\'t support SPATIAL indexes" }, -{ "ER_NO_TRIGGERS_ON_SYSTEM_SCHEMA", 1465, "Triggers can not be created on system tables" }, -{ "ER_REMOVED_SPACES", 1466, "Leading spaces are removed from name \'%s\'" }, -{ "ER_AUTOINC_READ_FAILED", 1467, "Failed to read auto-increment value from storage engine" }, -{ "ER_USERNAME", 1468, "user name" }, -{ "ER_HOSTNAME", 1469, "host name" }, -{ "ER_WRONG_STRING_LENGTH", 1470, "String \'%-.70s\' is too long for %s (should be no longer than %d)" }, -{ "ER_NON_INSERTABLE_TABLE", 1471, "The target table %-.100s of the %s is not insertable-into" }, -{ "ER_ADMIN_WRONG_MRG_TABLE", 1472, "Table \'%-.64s\' is differently defined or of non-MyISAM type or doesn\'t exist" }, -{ "ER_TOO_HIGH_LEVEL_OF_NESTING_FOR_SELECT", 1473, "Too high level of nesting for select" }, -{ "ER_NAME_BECOMES_EMPTY", 1474, "Name \'%-.64s\' has become \'\'" }, -{ "ER_AMBIGUOUS_FIELD_TERM", 1475, "First character of the FIELDS TERMINATED string is ambiguous; please use non-optional and non-empty FIELDS ENCLOSED BY" }, -{ "ER_FOREIGN_SERVER_EXISTS", 1476, "The foreign server, %s, you are trying to create already exists." }, -{ "ER_FOREIGN_SERVER_DOESNT_EXIST", 1477, "The foreign server name you are trying to reference does not exist. Data source error: %-.64s" }, -{ "ER_ILLEGAL_HA_CREATE_OPTION", 1478, "Table storage engine \'%-.64s\' does not support the create option \'%.64s\'" }, -{ "ER_PARTITION_REQUIRES_VALUES_ERROR", 1479, "Syntax error: %-.64s PARTITIONING requires definition of VALUES %-.64s for each partition" }, -{ "ER_PARTITION_WRONG_VALUES_ERROR", 1480, "Only %-.64s PARTITIONING can use VALUES %-.64s in partition definition" }, -{ "ER_PARTITION_MAXVALUE_ERROR", 1481, "MAXVALUE can only be used in last partition definition" }, -{ "ER_PARTITION_SUBPARTITION_ERROR", 1482, "Subpartitions can only be hash partitions and by key" }, -{ "ER_PARTITION_SUBPART_MIX_ERROR", 1483, "Must define subpartitions on all partitions if on one partition" }, -{ "ER_PARTITION_WRONG_NO_PART_ERROR", 1484, "Wrong number of partitions defined, mismatch with previous setting" }, -{ "ER_PARTITION_WRONG_NO_SUBPART_ERROR", 1485, "Wrong number of subpartitions defined, mismatch with previous setting" }, -{ "ER_WRONG_EXPR_IN_PARTITION_FUNC_ERROR", 1486, "Constant, random or timezone-dependent expressions in (sub)partitioning function are not allowed" }, -{ "ER_NO_CONST_EXPR_IN_RANGE_OR_LIST_ERROR", 1487, "Expression in RANGE/LIST VALUES must be constant" }, -{ "ER_FIELD_NOT_FOUND_PART_ERROR", 1488, "Field in list of fields for partition function not found in table" }, -{ "ER_LIST_OF_FIELDS_ONLY_IN_HASH_ERROR", 1489, "List of fields is only allowed in KEY partitions" }, -{ "ER_INCONSISTENT_PARTITION_INFO_ERROR", 1490, "The partition info in the frm file is not consistent with what can be written into the frm file" }, -{ "ER_PARTITION_FUNC_NOT_ALLOWED_ERROR", 1491, "The %-.192s function returns the wrong type" }, -{ "ER_PARTITIONS_MUST_BE_DEFINED_ERROR", 1492, "For %-.64s partitions each partition must be defined" }, -{ "ER_RANGE_NOT_INCREASING_ERROR", 1493, "VALUES LESS THAN value must be strictly increasing for each partition" }, -{ "ER_INCONSISTENT_TYPE_OF_FUNCTIONS_ERROR", 1494, "VALUES value must be of same type as partition function" }, -{ "ER_MULTIPLE_DEF_CONST_IN_LIST_PART_ERROR", 1495, "Multiple definition of same constant in list partitioning" }, -{ "ER_PARTITION_ENTRY_ERROR", 1496, "Partitioning can not be used stand-alone in query" }, -{ "ER_MIX_HANDLER_ERROR", 1497, "The mix of handlers in the partitions is not allowed in this version of MySQL" }, -{ "ER_PARTITION_NOT_DEFINED_ERROR", 1498, "For the partitioned engine it is necessary to define all %-.64s" }, -{ "ER_TOO_MANY_PARTITIONS_ERROR", 1499, "Too many partitions (including subpartitions) were defined" }, -{ "ER_SUBPARTITION_ERROR", 1500, "It is only possible to mix RANGE/LIST partitioning with HASH/KEY partitioning for subpartitioning" }, -{ "ER_CANT_CREATE_HANDLER_FILE", 1501, "Failed to create specific handler file" }, -{ "ER_BLOB_FIELD_IN_PART_FUNC_ERROR", 1502, "A BLOB field is not allowed in partition function" }, -{ "ER_UNIQUE_KEY_NEED_ALL_FIELDS_IN_PF", 1503, "A %-.192s must include all columns in the table\'s partitioning function" }, -{ "ER_NO_PARTS_ERROR", 1504, "Number of %-.64s = 0 is not an allowed value" }, -{ "ER_PARTITION_MGMT_ON_NONPARTITIONED", 1505, "Partition management on a not partitioned table is not possible" }, -{ "ER_FOREIGN_KEY_ON_PARTITIONED", 1506, "Foreign keys are not yet supported in conjunction with partitioning" }, -{ "ER_DROP_PARTITION_NON_EXISTENT", 1507, "Error in list of partitions to %-.64s" }, -{ "ER_DROP_LAST_PARTITION", 1508, "Cannot remove all partitions, use DROP TABLE instead" }, -{ "ER_COALESCE_ONLY_ON_HASH_PARTITION", 1509, "COALESCE PARTITION can only be used on HASH/KEY partitions" }, -{ "ER_REORG_HASH_ONLY_ON_SAME_NO", 1510, "REORGANIZE PARTITION can only be used to reorganize partitions not to change their numbers" }, -{ "ER_REORG_NO_PARAM_ERROR", 1511, "REORGANIZE PARTITION without parameters can only be used on auto-partitioned tables using HASH PARTITIONs" }, -{ "ER_ONLY_ON_RANGE_LIST_PARTITION", 1512, "%-.64s PARTITION can only be used on RANGE/LIST partitions" }, -{ "ER_ADD_PARTITION_SUBPART_ERROR", 1513, "Trying to Add partition(s) with wrong number of subpartitions" }, -{ "ER_ADD_PARTITION_NO_NEW_PARTITION", 1514, "At least one partition must be added" }, -{ "ER_COALESCE_PARTITION_NO_PARTITION", 1515, "At least one partition must be coalesced" }, -{ "ER_REORG_PARTITION_NOT_EXIST", 1516, "More partitions to reorganize than there are partitions" }, -{ "ER_SAME_NAME_PARTITION", 1517, "Duplicate partition name %-.192s" }, -{ "ER_NO_BINLOG_ERROR", 1518, "It is not allowed to shut off binlog on this command" }, -{ "ER_CONSECUTIVE_REORG_PARTITIONS", 1519, "When reorganizing a set of partitions they must be in consecutive order" }, -{ "ER_REORG_OUTSIDE_RANGE", 1520, "Reorganize of range partitions cannot change total ranges except for last partition where it can extend the range" }, -{ "ER_PARTITION_FUNCTION_FAILURE", 1521, "Partition function not supported in this version for this handler" }, -{ "ER_PART_STATE_ERROR", 1522, "Partition state cannot be defined from CREATE/ALTER TABLE" }, -{ "ER_LIMITED_PART_RANGE", 1523, "The %-.64s handler only supports 32 bit integers in VALUES" }, -{ "ER_PLUGIN_IS_NOT_LOADED", 1524, "Plugin \'%-.192s\' is not loaded" }, -{ "ER_WRONG_VALUE", 1525, "Incorrect %-.32s value: \'%-.128s\'" }, -{ "ER_NO_PARTITION_FOR_GIVEN_VALUE", 1526, "Table has no partition for value %-.64s" }, -{ "ER_FILEGROUP_OPTION_ONLY_ONCE", 1527, "It is not allowed to specify %s more than once" }, -{ "ER_CREATE_FILEGROUP_FAILED", 1528, "Failed to create %s" }, -{ "ER_DROP_FILEGROUP_FAILED", 1529, "Failed to drop %s" }, -{ "ER_TABLESPACE_AUTO_EXTEND_ERROR", 1530, "The handler doesn\'t support autoextend of tablespaces" }, -{ "ER_WRONG_SIZE_NUMBER", 1531, "A size parameter was incorrectly specified, either number or on the form 10M" }, -{ "ER_SIZE_OVERFLOW_ERROR", 1532, "The size number was correct but we don\'t allow the digit part to be more than 2 billion" }, -{ "ER_ALTER_FILEGROUP_FAILED", 1533, "Failed to alter: %s" }, -{ "ER_BINLOG_ROW_LOGGING_FAILED", 1534, "Writing one row to the row-based binary log failed" }, -{ "ER_BINLOG_ROW_WRONG_TABLE_DEF", 1535, "Table definition on master and slave does not match: %s" }, -{ "ER_BINLOG_ROW_RBR_TO_SBR", 1536, "Slave running with --log-slave-updates must use row-based binary logging to be able to replicate row-based binary log events" }, -{ "ER_EVENT_ALREADY_EXISTS", 1537, "Event \'%-.192s\' already exists" }, -{ "ER_EVENT_STORE_FAILED", 1538, "Failed to store event %s. Error code %d from storage engine." }, -{ "ER_EVENT_DOES_NOT_EXIST", 1539, "Unknown event \'%-.192s\'" }, -{ "ER_EVENT_CANT_ALTER", 1540, "Failed to alter event \'%-.192s\'" }, -{ "ER_EVENT_DROP_FAILED", 1541, "Failed to drop %s" }, -{ "ER_EVENT_INTERVAL_NOT_POSITIVE_OR_TOO_BIG", 1542, "INTERVAL is either not positive or too big" }, -{ "ER_EVENT_ENDS_BEFORE_STARTS", 1543, "ENDS is either invalid or before STARTS" }, -{ "ER_EVENT_EXEC_TIME_IN_THE_PAST", 1544, "Event execution time is in the past. Event has been disabled" }, -{ "ER_EVENT_OPEN_TABLE_FAILED", 1545, "Failed to open mysql.event" }, -{ "ER_EVENT_NEITHER_M_EXPR_NOR_M_AT", 1546, "No datetime expression provided" }, -{ "ER_OBSOLETE_COL_COUNT_DOESNT_MATCH_CORRUPTED", 1547, "Column count of mysql.%s is wrong. Expected %d, found %d. The table is probably corrupted" }, -{ "ER_OBSOLETE_CANNOT_LOAD_FROM_TABLE", 1548, "Cannot load from mysql.%s. The table is probably corrupted" }, -{ "ER_EVENT_CANNOT_DELETE", 1549, "Failed to delete the event from mysql.event" }, -{ "ER_EVENT_COMPILE_ERROR", 1550, "Error during compilation of event\'s body" }, -{ "ER_EVENT_SAME_NAME", 1551, "Same old and new event name" }, -{ "ER_EVENT_DATA_TOO_LONG", 1552, "Data for column \'%s\' too long" }, -{ "ER_DROP_INDEX_FK", 1553, "Cannot drop index \'%-.192s\': needed in a foreign key constraint" }, -{ "ER_WARN_DEPRECATED_SYNTAX_WITH_VER", 1554, "The syntax \'%s\' is deprecated and will be removed in MySQL %s. Please use %s instead" }, -{ "ER_CANT_WRITE_LOCK_LOG_TABLE", 1555, "You can\'t write-lock a log table. Only read access is possible" }, -{ "ER_CANT_LOCK_LOG_TABLE", 1556, "You can\'t use locks with log tables." }, -{ "ER_FOREIGN_DUPLICATE_KEY_OLD_UNUSED", 1557, "Upholding foreign key constraints for table \'%.192s\', entry \'%-.192s\', key %d would lead to a duplicate entry" }, -{ "ER_COL_COUNT_DOESNT_MATCH_PLEASE_UPDATE", 1558, "Column count of mysql.%s is wrong. Expected %d, found %d. Created with MySQL %d, now running %d. Please use mysql_upgrade to fix this error." }, -{ "ER_TEMP_TABLE_PREVENTS_SWITCH_OUT_OF_RBR", 1559, "Cannot switch out of the row-based binary log format when the session has open temporary tables" }, -{ "ER_STORED_FUNCTION_PREVENTS_SWITCH_BINLOG_FORMAT", 1560, "Cannot change the binary logging format inside a stored function or trigger" }, -{ "ER_NDB_CANT_SWITCH_BINLOG_FORMAT", 1561, "The NDB cluster engine does not support changing the binlog format on the fly yet" }, -{ "ER_PARTITION_NO_TEMPORARY", 1562, "Cannot create temporary table with partitions" }, -{ "ER_PARTITION_CONST_DOMAIN_ERROR", 1563, "Partition constant is out of partition function domain" }, -{ "ER_PARTITION_FUNCTION_IS_NOT_ALLOWED", 1564, "This partition function is not allowed" }, -{ "ER_DDL_LOG_ERROR", 1565, "Error in DDL log" }, -{ "ER_NULL_IN_VALUES_LESS_THAN", 1566, "Not allowed to use NULL value in VALUES LESS THAN" }, -{ "ER_WRONG_PARTITION_NAME", 1567, "Incorrect partition name" }, -{ "ER_CANT_CHANGE_TX_CHARACTERISTICS", 1568, "Transaction characteristics can\'t be changed while a transaction is in progress" }, -{ "ER_DUP_ENTRY_AUTOINCREMENT_CASE", 1569, "ALTER TABLE causes auto_increment resequencing, resulting in duplicate entry \'%-.192s\' for key \'%-.192s\'" }, -{ "ER_EVENT_MODIFY_QUEUE_ERROR", 1570, "Internal scheduler error %d" }, -{ "ER_EVENT_SET_VAR_ERROR", 1571, "Error during starting/stopping of the scheduler. Error code %u" }, -{ "ER_PARTITION_MERGE_ERROR", 1572, "Engine cannot be used in partitioned tables" }, -{ "ER_CANT_ACTIVATE_LOG", 1573, "Cannot activate \'%-.64s\' log" }, -{ "ER_RBR_NOT_AVAILABLE", 1574, "The server was not built with row-based replication" }, -{ "ER_BASE64_DECODE_ERROR", 1575, "Decoding of base64 string failed" }, -{ "ER_EVENT_RECURSION_FORBIDDEN", 1576, "Recursion of EVENT DDL statements is forbidden when body is present" }, -{ "ER_EVENTS_DB_ERROR", 1577, "Cannot proceed because system tables used by Event Scheduler were found damaged at server start" }, -{ "ER_ONLY_INTEGERS_ALLOWED", 1578, "Only integers allowed as number here" }, -{ "ER_UNSUPORTED_LOG_ENGINE", 1579, "This storage engine cannot be used for log tables\"" }, -{ "ER_BAD_LOG_STATEMENT", 1580, "You cannot \'%s\' a log table if logging is enabled" }, -{ "ER_CANT_RENAME_LOG_TABLE", 1581, "Cannot rename \'%s\'. When logging enabled, rename to/from log table must rename two tables: the log table to an archive table and another table back to \'%s\'" }, -{ "ER_WRONG_PARAMCOUNT_TO_NATIVE_FCT", 1582, "Incorrect parameter count in the call to native function \'%-.192s\'" }, -{ "ER_WRONG_PARAMETERS_TO_NATIVE_FCT", 1583, "Incorrect parameters in the call to native function \'%-.192s\'" }, -{ "ER_WRONG_PARAMETERS_TO_STORED_FCT", 1584, "Incorrect parameters in the call to stored function %-.192s" }, -{ "ER_NATIVE_FCT_NAME_COLLISION", 1585, "This function \'%-.192s\' has the same name as a native function" }, -{ "ER_DUP_ENTRY_WITH_KEY_NAME", 1586, "Duplicate entry \'%-.64s\' for key \'%-.192s\'" }, -{ "ER_BINLOG_PURGE_EMFILE", 1587, "Too many files opened, please execute the command again" }, -{ "ER_EVENT_CANNOT_CREATE_IN_THE_PAST", 1588, "Event execution time is in the past and ON COMPLETION NOT PRESERVE is set. The event was dropped immediately after creation." }, -{ "ER_EVENT_CANNOT_ALTER_IN_THE_PAST", 1589, "Event execution time is in the past and ON COMPLETION NOT PRESERVE is set. The event was not changed. Specify a time in the future." }, -{ "ER_SLAVE_INCIDENT", 1590, "The incident %s occured on the master. Message: %s" }, -{ "ER_NO_PARTITION_FOR_GIVEN_VALUE_SILENT", 1591, "Table has no partition for some existing values" }, -{ "ER_BINLOG_UNSAFE_STATEMENT", 1592, "Unsafe statement written to the binary log using statement format since BINLOG_FORMAT = STATEMENT. %s" }, -{ "ER_SLAVE_FATAL_ERROR", 1593, "Fatal error: %s" }, -{ "ER_SLAVE_RELAY_LOG_READ_FAILURE", 1594, "Relay log read failure: %s" }, -{ "ER_SLAVE_RELAY_LOG_WRITE_FAILURE", 1595, "Relay log write failure: %s" }, -{ "ER_SLAVE_CREATE_EVENT_FAILURE", 1596, "Failed to create %s" }, -{ "ER_SLAVE_MASTER_COM_FAILURE", 1597, "Master command %s failed: %s" }, -{ "ER_BINLOG_LOGGING_IMPOSSIBLE", 1598, "Binary logging not possible. Message: %s" }, -{ "ER_VIEW_NO_CREATION_CTX", 1599, "View `%-.64s`.`%-.64s` has no creation context" }, -{ "ER_VIEW_INVALID_CREATION_CTX", 1600, "Creation context of view `%-.64s`.`%-.64s\' is invalid" }, -{ "ER_SR_INVALID_CREATION_CTX", 1601, "Creation context of stored routine `%-.64s`.`%-.64s` is invalid" }, -{ "ER_TRG_CORRUPTED_FILE", 1602, "Corrupted TRG file for table `%-.64s`.`%-.64s`" }, -{ "ER_TRG_NO_CREATION_CTX", 1603, "Triggers for table `%-.64s`.`%-.64s` have no creation context" }, -{ "ER_TRG_INVALID_CREATION_CTX", 1604, "Trigger creation context of table `%-.64s`.`%-.64s` is invalid" }, -{ "ER_EVENT_INVALID_CREATION_CTX", 1605, "Creation context of event `%-.64s`.`%-.64s` is invalid" }, -{ "ER_TRG_CANT_OPEN_TABLE", 1606, "Cannot open table for trigger `%-.64s`.`%-.64s`" }, -{ "ER_CANT_CREATE_SROUTINE", 1607, "Cannot create stored routine `%-.64s`. Check warnings" }, -{ "ER_NEVER_USED", 1608, "Ambiguous slave modes combination. %s" }, -{ "ER_NO_FORMAT_DESCRIPTION_EVENT_BEFORE_BINLOG_STATEMENT", 1609, "The BINLOG statement of type `%s` was not preceded by a format description BINLOG statement." }, -{ "ER_SLAVE_CORRUPT_EVENT", 1610, "Corrupted replication event was detected" }, -{ "ER_LOAD_DATA_INVALID_COLUMN_UNUSED", 1611, "Invalid column reference (%-.64s) in LOAD DATA" }, -{ "ER_LOG_PURGE_NO_FILE", 1612, "Being purged log %s was not found" }, -{ "ER_XA_RBTIMEOUT", 1613, "XA_RBTIMEOUT: Transaction branch was rolled back: took too long" }, -{ "ER_XA_RBDEADLOCK", 1614, "XA_RBDEADLOCK: Transaction branch was rolled back: deadlock was detected" }, -{ "ER_NEED_REPREPARE", 1615, "Prepared statement needs to be re-prepared" }, -{ "ER_DELAYED_NOT_SUPPORTED", 1616, "DELAYED option not supported for table \'%-.192s\'" }, -{ "WARN_NO_MASTER_INFO", 1617, "The master info structure does not exist" }, -{ "WARN_OPTION_IGNORED", 1618, "<%-.64s> option ignored" }, -{ "ER_PLUGIN_DELETE_BUILTIN", 1619, "Built-in plugins cannot be deleted" }, -{ "WARN_PLUGIN_BUSY", 1620, "Plugin is busy and will be uninstalled on shutdown" }, -{ "ER_VARIABLE_IS_READONLY", 1621, "%s variable \'%s\' is read-only. Use SET %s to assign the value" }, -{ "ER_WARN_ENGINE_TRANSACTION_ROLLBACK", 1622, "Storage engine %s does not support rollback for this statement. Transaction rolled back and must be restarted" }, -{ "ER_SLAVE_HEARTBEAT_FAILURE", 1623, "Unexpected master\'s heartbeat data: %s" }, -{ "ER_SLAVE_HEARTBEAT_VALUE_OUT_OF_RANGE", 1624, "The requested value for the heartbeat period is either negative or exceeds the maximum allowed (%s seconds)." }, -{ "ER_NDB_REPLICATION_SCHEMA_ERROR", 1625, "Bad schema for mysql.ndb_replication table. Message: %-.64s" }, -{ "ER_CONFLICT_FN_PARSE_ERROR", 1626, "Error in parsing conflict function. Message: %-.64s" }, -{ "ER_EXCEPTIONS_WRITE_ERROR", 1627, "Write to exceptions table failed. Message: %-.128s\"" }, -{ "ER_TOO_LONG_TABLE_COMMENT", 1628, "Comment for table \'%-.64s\' is too long (max = %lu)" }, -{ "ER_TOO_LONG_FIELD_COMMENT", 1629, "Comment for field \'%-.64s\' is too long (max = %lu)" }, -{ "ER_FUNC_INEXISTENT_NAME_COLLISION", 1630, "FUNCTION %s does not exist. Check the \'Function Name Parsing and Resolution\' section in the Reference Manual" }, -{ "ER_DATABASE_NAME", 1631, "Database" }, -{ "ER_TABLE_NAME", 1632, "Table" }, -{ "ER_PARTITION_NAME", 1633, "Partition" }, -{ "ER_SUBPARTITION_NAME", 1634, "Subpartition" }, -{ "ER_TEMPORARY_NAME", 1635, "Temporary" }, -{ "ER_RENAMED_NAME", 1636, "Renamed" }, -{ "ER_TOO_MANY_CONCURRENT_TRXS", 1637, "Too many active concurrent transactions" }, -{ "WARN_NON_ASCII_SEPARATOR_NOT_IMPLEMENTED", 1638, "Non-ASCII separator arguments are not fully supported" }, -{ "ER_DEBUG_SYNC_TIMEOUT", 1639, "debug sync point wait timed out" }, -{ "ER_DEBUG_SYNC_HIT_LIMIT", 1640, "debug sync point hit limit reached" }, -{ "ER_DUP_SIGNAL_SET", 1641, "Duplicate condition information item \'%s\'" }, -{ "ER_SIGNAL_WARN", 1642, "Unhandled user-defined warning condition" }, -{ "ER_SIGNAL_NOT_FOUND", 1643, "Unhandled user-defined not found condition" }, -{ "ER_SIGNAL_EXCEPTION", 1644, "Unhandled user-defined exception condition" }, -{ "ER_RESIGNAL_WITHOUT_ACTIVE_HANDLER", 1645, "RESIGNAL when handler not active" }, -{ "ER_SIGNAL_BAD_CONDITION_TYPE", 1646, "SIGNAL/RESIGNAL can only use a CONDITION defined with SQLSTATE" }, -{ "WARN_COND_ITEM_TRUNCATED", 1647, "Data truncated for condition item \'%s\'" }, -{ "ER_COND_ITEM_TOO_LONG", 1648, "Data too long for condition item \'%s\'" }, -{ "ER_UNKNOWN_LOCALE", 1649, "Unknown locale: \'%-.64s\'" }, -{ "ER_SLAVE_IGNORE_SERVER_IDS", 1650, "The requested server id %d clashes with the slave startup option --replicate-same-server-id" }, -{ "ER_QUERY_CACHE_DISABLED", 1651, "Query cache is disabled; restart the server with query_cache_type=1 to enable it" }, -{ "ER_SAME_NAME_PARTITION_FIELD", 1652, "Duplicate partition field name \'%-.192s\'" }, -{ "ER_PARTITION_COLUMN_LIST_ERROR", 1653, "Inconsistency in usage of column lists for partitioning" }, -{ "ER_WRONG_TYPE_COLUMN_VALUE_ERROR", 1654, "Partition column values of incorrect type" }, -{ "ER_TOO_MANY_PARTITION_FUNC_FIELDS_ERROR", 1655, "Too many fields in \'%-.192s\'" }, -{ "ER_MAXVALUE_IN_VALUES_IN", 1656, "Cannot use MAXVALUE as value in VALUES IN" }, -{ "ER_TOO_MANY_VALUES_ERROR", 1657, "Cannot have more than one value for this type of %-.64s partitioning" }, -{ "ER_ROW_SINGLE_PARTITION_FIELD_ERROR", 1658, "Row expressions in VALUES IN only allowed for multi-field column partitioning" }, -{ "ER_FIELD_TYPE_NOT_ALLOWED_AS_PARTITION_FIELD", 1659, "Field \'%-.192s\' is of a not allowed type for this type of partitioning" }, -{ "ER_PARTITION_FIELDS_TOO_LONG", 1660, "The total length of the partitioning fields is too large" }, -{ "ER_BINLOG_ROW_ENGINE_AND_STMT_ENGINE", 1661, "Cannot execute statement: impossible to write to binary log since both row-incapable engines and statement-incapable engines are involved." }, -{ "ER_BINLOG_ROW_MODE_AND_STMT_ENGINE", 1662, "Cannot execute statement: impossible to write to binary log since BINLOG_FORMAT = ROW and at least one table uses a storage engine limited to statement-based logging." }, -{ "ER_BINLOG_UNSAFE_AND_STMT_ENGINE", 1663, "Cannot execute statement: impossible to write to binary log since statement is unsafe, storage engine is limited to statement-based logging, and BINLOG_FORMAT = MIXED. %s" }, -{ "ER_BINLOG_ROW_INJECTION_AND_STMT_ENGINE", 1664, "Cannot execute statement: impossible to write to binary log since statement is in row format and at least one table uses a storage engine limited to statement-based logging." }, -{ "ER_BINLOG_STMT_MODE_AND_ROW_ENGINE", 1665, "Cannot execute statement: impossible to write to binary log since BINLOG_FORMAT = STATEMENT and at least one table uses a storage engine limited to row-based logging.%s" }, -{ "ER_BINLOG_ROW_INJECTION_AND_STMT_MODE", 1666, "Cannot execute statement: impossible to write to binary log since statement is in row format and BINLOG_FORMAT = STATEMENT." }, -{ "ER_BINLOG_MULTIPLE_ENGINES_AND_SELF_LOGGING_ENGINE", 1667, "Cannot execute statement: impossible to write to binary log since more than one engine is involved and at least one engine is self-logging." }, -{ "ER_BINLOG_UNSAFE_LIMIT", 1668, "The statement is unsafe because it uses a LIMIT clause. This is unsafe because the set of rows included cannot be predicted." }, -{ "ER_UNUSED4", 1669, "The statement is unsafe because it uses INSERT DELAYED. This is unsafe because the times when rows are inserted cannot be predicted." }, -{ "ER_BINLOG_UNSAFE_SYSTEM_TABLE", 1670, "The statement is unsafe because it uses the general log, slow query log, or performance_schema table(s). This is unsafe because system tables may differ on slaves." }, -{ "ER_BINLOG_UNSAFE_AUTOINC_COLUMNS", 1671, "Statement is unsafe because it invokes a trigger or a stored function that inserts into an AUTO_INCREMENT column. Inserted values cannot be logged correctly." }, -{ "ER_BINLOG_UNSAFE_UDF", 1672, "Statement is unsafe because it uses a UDF which may not return the same value on the slave." }, -{ "ER_BINLOG_UNSAFE_SYSTEM_VARIABLE", 1673, "Statement is unsafe because it uses a system variable that may have a different value on the slave." }, -{ "ER_BINLOG_UNSAFE_SYSTEM_FUNCTION", 1674, "Statement is unsafe because it uses a system function that may return a different value on the slave." }, -{ "ER_BINLOG_UNSAFE_NONTRANS_AFTER_TRANS", 1675, "Statement is unsafe because it accesses a non-transactional table after accessing a transactional table within the same transaction." }, -{ "ER_MESSAGE_AND_STATEMENT", 1676, "%s Statement: %s" }, -{ "ER_SLAVE_CONVERSION_FAILED", 1677, "Column %d of table \'%-.192s.%-.192s\' cannot be converted from type \'%-.32s\' to type \'%-.32s\'" }, -{ "ER_SLAVE_CANT_CREATE_CONVERSION", 1678, "Can\'t create conversion table for table \'%-.192s.%-.192s\'" }, -{ "ER_INSIDE_TRANSACTION_PREVENTS_SWITCH_BINLOG_FORMAT", 1679, "Cannot modify @@session.binlog_format inside a transaction" }, -{ "ER_PATH_LENGTH", 1680, "The path specified for %.64s is too long." }, -{ "ER_WARN_DEPRECATED_SYNTAX_NO_REPLACEMENT", 1681, "\'%s\' is deprecated and will be removed in a future release." }, -{ "ER_WRONG_NATIVE_TABLE_STRUCTURE", 1682, "Native table \'%-.64s\'.\'%-.64s\' has the wrong structure" }, -{ "ER_WRONG_PERFSCHEMA_USAGE", 1683, "Invalid performance_schema usage." }, -{ "ER_WARN_I_S_SKIPPED_TABLE", 1684, "Table \'%s\'.\'%s\' was skipped since its definition is being modified by concurrent DDL statement" }, -{ "ER_INSIDE_TRANSACTION_PREVENTS_SWITCH_BINLOG_DIRECT", 1685, "Cannot modify @@session.binlog_direct_non_transactional_updates inside a transaction" }, -{ "ER_STORED_FUNCTION_PREVENTS_SWITCH_BINLOG_DIRECT", 1686, "Cannot change the binlog direct flag inside a stored function or trigger" }, -{ "ER_SPATIAL_MUST_HAVE_GEOM_COL", 1687, "A SPATIAL index may only contain a geometrical type column" }, -{ "ER_TOO_LONG_INDEX_COMMENT", 1688, "Comment for index \'%-.64s\' is too long (max = %lu)" }, -{ "ER_LOCK_ABORTED", 1689, "Wait on a lock was aborted due to a pending exclusive lock" }, -{ "ER_DATA_OUT_OF_RANGE", 1690, "%s value is out of range in \'%s\'" }, -{ "ER_WRONG_SPVAR_TYPE_IN_LIMIT", 1691, "A variable of a non-integer based type in LIMIT clause" }, -{ "ER_BINLOG_UNSAFE_MULTIPLE_ENGINES_AND_SELF_LOGGING_ENGINE", 1692, "Mixing self-logging and non-self-logging engines in a statement is unsafe." }, -{ "ER_BINLOG_UNSAFE_MIXED_STATEMENT", 1693, "Statement accesses nontransactional table as well as transactional or temporary table, and writes to any of them." }, -{ "ER_INSIDE_TRANSACTION_PREVENTS_SWITCH_SQL_LOG_BIN", 1694, "Cannot modify @@session.sql_log_bin inside a transaction" }, -{ "ER_STORED_FUNCTION_PREVENTS_SWITCH_SQL_LOG_BIN", 1695, "Cannot change the sql_log_bin inside a stored function or trigger" }, -{ "ER_FAILED_READ_FROM_PAR_FILE", 1696, "Failed to read from the .par file" }, -{ "ER_VALUES_IS_NOT_INT_TYPE_ERROR", 1697, "VALUES value for partition \'%-.64s\' must have type INT" }, -{ "ER_ACCESS_DENIED_NO_PASSWORD_ERROR", 1698, "Access denied for user \'%-.48s\'@\'%-.64s\'" }, -{ "ER_SET_PASSWORD_AUTH_PLUGIN", 1699, "SET PASSWORD has no significance for users authenticating via plugins" }, -{ "ER_GRANT_PLUGIN_USER_EXISTS", 1700, "GRANT with IDENTIFIED WITH is illegal because the user %-.*s already exists" }, -{ "ER_TRUNCATE_ILLEGAL_FK", 1701, "Cannot truncate a table referenced in a foreign key constraint (%.192s)" }, -{ "ER_PLUGIN_IS_PERMANENT", 1702, "Plugin \'%s\' is force_plus_permanent and can not be unloaded" }, -{ "ER_SLAVE_HEARTBEAT_VALUE_OUT_OF_RANGE_MIN", 1703, "The requested value for the heartbeat period is less than 1 millisecond. The value is reset to 0, meaning that heartbeating will effectively be disabled." }, -{ "ER_SLAVE_HEARTBEAT_VALUE_OUT_OF_RANGE_MAX", 1704, "The requested value for the heartbeat period exceeds the value of `slave_net_timeout\' seconds. A sensible value for the period should be less than the timeout." }, -{ "ER_STMT_CACHE_FULL", 1705, "Multi-row statements required more than \'max_binlog_stmt_cache_size\' bytes of storage; increase this mysqld variable and try again" }, -{ "ER_MULTI_UPDATE_KEY_CONFLICT", 1706, "Primary key/partition key update is not allowed since the table is updated both as \'%-.192s\' and \'%-.192s\'." }, -{ "ER_TABLE_NEEDS_REBUILD", 1707, "Table rebuild required. Please do \"ALTER TABLE `%-.64s` FORCE\" or dump/reload to fix it!" }, -{ "WARN_OPTION_BELOW_LIMIT", 1708, "The value of \'%s\' should be no less than the value of \'%s\'" }, -{ "ER_INDEX_COLUMN_TOO_LONG", 1709, "Index column size too large. The maximum column size is %lu bytes." }, -{ "ER_ERROR_IN_TRIGGER_BODY", 1710, "Trigger \'%-.64s\' has an error in its body: \'%-.256s\'" }, -{ "ER_ERROR_IN_UNKNOWN_TRIGGER_BODY", 1711, "Unknown trigger has an error in its body: \'%-.256s\'" }, -{ "ER_INDEX_CORRUPT", 1712, "Index %s is corrupted" }, -{ "ER_UNDO_RECORD_TOO_BIG", 1713, "Undo log record is too big." }, -{ "ER_BINLOG_UNSAFE_INSERT_IGNORE_SELECT", 1714, "INSERT IGNORE... SELECT is unsafe because the order in which rows are retrieved by the SELECT determines which (if any) rows are ignored. This order cannot be predicted and may differ on master and the slave." }, -{ "ER_BINLOG_UNSAFE_INSERT_SELECT_UPDATE", 1715, "INSERT... SELECT... ON DUPLICATE KEY UPDATE is unsafe because the order in which rows are retrieved by the SELECT determines which (if any) rows are updated. This order cannot be predicted and may differ on master and the slave." }, -{ "ER_BINLOG_UNSAFE_REPLACE_SELECT", 1716, "REPLACE... SELECT is unsafe because the order in which rows are retrieved by the SELECT determines which (if any) rows are replaced. This order cannot be predicted and may differ on master and the slave." }, -{ "ER_BINLOG_UNSAFE_CREATE_IGNORE_SELECT", 1717, "CREATE... IGNORE SELECT is unsafe because the order in which rows are retrieved by the SELECT determines which (if any) rows are ignored. This order cannot be predicted and may differ on master and the slave." }, -{ "ER_BINLOG_UNSAFE_CREATE_REPLACE_SELECT", 1718, "CREATE... REPLACE SELECT is unsafe because the order in which rows are retrieved by the SELECT determines which (if any) rows are replaced. This order cannot be predicted and may differ on master and the slave." }, -{ "ER_BINLOG_UNSAFE_UPDATE_IGNORE", 1719, "UPDATE IGNORE is unsafe because the order in which rows are updated determines which (if any) rows are ignored. This order cannot be predicted and may differ on master and the slave." }, -{ "ER_PLUGIN_NO_UNINSTALL", 1720, "Plugin \'%s\' is marked as not dynamically uninstallable. You have to stop the server to uninstall it." }, -{ "ER_PLUGIN_NO_INSTALL", 1721, "Plugin \'%s\' is marked as not dynamically installable. You have to stop the server to install it." }, -{ "ER_BINLOG_UNSAFE_WRITE_AUTOINC_SELECT", 1722, "Statements writing to a table with an auto-increment column after selecting from another table are unsafe because the order in which rows are retrieved determines what (if any) rows will be written. This order cannot be predicted and may differ on master and the slave." }, -{ "ER_BINLOG_UNSAFE_CREATE_SELECT_AUTOINC", 1723, "CREATE TABLE... SELECT... on a table with an auto-increment column is unsafe because the order in which rows are retrieved by the SELECT determines which (if any) rows are inserted. This order cannot be predicted and may differ on master and the slave." }, -{ "ER_BINLOG_UNSAFE_INSERT_TWO_KEYS", 1724, "INSERT... ON DUPLICATE KEY UPDATE on a table with more than one UNIQUE KEY is unsafe" }, -{ "ER_TABLE_IN_FK_CHECK", 1725, "Table is being used in foreign key check." }, -{ "ER_UNSUPPORTED_ENGINE", 1726, "Storage engine \'%s\' does not support system tables. [%s.%s]" }, -{ "ER_BINLOG_UNSAFE_AUTOINC_NOT_FIRST", 1727, "INSERT into autoincrement field which is not the first part in the composed primary key is unsafe." }, -{ "ER_CANNOT_LOAD_FROM_TABLE_V2", 1728, "Cannot load from %s.%s. The table is probably corrupted" }, -{ "ER_MASTER_DELAY_VALUE_OUT_OF_RANGE", 1729, "The requested value %s for the master delay exceeds the maximum %u" }, -{ "ER_ONLY_FD_AND_RBR_EVENTS_ALLOWED_IN_BINLOG_STATEMENT", 1730, "Only Format_description_log_event and row events are allowed in BINLOG statements (but %s was provided)" }, -{ "ER_PARTITION_EXCHANGE_DIFFERENT_OPTION", 1731, "Non matching attribute \'%-.64s\' between partition and table" }, -{ "ER_PARTITION_EXCHANGE_PART_TABLE", 1732, "Table to exchange with partition is partitioned: \'%-.64s\'" }, -{ "ER_PARTITION_EXCHANGE_TEMP_TABLE", 1733, "Table to exchange with partition is temporary: \'%-.64s\'" }, -{ "ER_PARTITION_INSTEAD_OF_SUBPARTITION", 1734, "Subpartitioned table, use subpartition instead of partition" }, -{ "ER_UNKNOWN_PARTITION", 1735, "Unknown partition \'%-.64s\' in table \'%-.64s\'" }, -{ "ER_TABLES_DIFFERENT_METADATA", 1736, "Tables have different definitions" }, -{ "ER_ROW_DOES_NOT_MATCH_PARTITION", 1737, "Found a row that does not match the partition" }, -{ "ER_BINLOG_CACHE_SIZE_GREATER_THAN_MAX", 1738, "Option binlog_cache_size (%lu) is greater than max_binlog_cache_size (%lu); setting binlog_cache_size equal to max_binlog_cache_size." }, -{ "ER_WARN_INDEX_NOT_APPLICABLE", 1739, "Cannot use %-.64s access on index \'%-.64s\' due to type or collation conversion on field \'%-.64s\'" }, -{ "ER_PARTITION_EXCHANGE_FOREIGN_KEY", 1740, "Table to exchange with partition has foreign key references: \'%-.64s\'" }, -{ "ER_NO_SUCH_KEY_VALUE", 1741, "Key value \'%-.192s\' was not found in table \'%-.192s.%-.192s\'" }, -{ "ER_RPL_INFO_DATA_TOO_LONG", 1742, "Data for column \'%s\' too long" }, -{ "ER_NETWORK_READ_EVENT_CHECKSUM_FAILURE", 1743, "Replication event checksum verification failed while reading from network." }, -{ "ER_BINLOG_READ_EVENT_CHECKSUM_FAILURE", 1744, "Replication event checksum verification failed while reading from a log file." }, -{ "ER_BINLOG_STMT_CACHE_SIZE_GREATER_THAN_MAX", 1745, "Option binlog_stmt_cache_size (%lu) is greater than max_binlog_stmt_cache_size (%lu); setting binlog_stmt_cache_size equal to max_binlog_stmt_cache_size." }, -{ "ER_CANT_UPDATE_TABLE_IN_CREATE_TABLE_SELECT", 1746, "Can\'t update table \'%-.192s\' while \'%-.192s\' is being created." }, -{ "ER_PARTITION_CLAUSE_ON_NONPARTITIONED", 1747, "PARTITION () clause on non partitioned table" }, -{ "ER_ROW_DOES_NOT_MATCH_GIVEN_PARTITION_SET", 1748, "Found a row not matching the given partition set" }, -{ "ER_NO_SUCH_PARTITION__UNUSED", 1749, "partition \'%-.64s\' doesn\'t exist" }, -{ "ER_CHANGE_RPL_INFO_REPOSITORY_FAILURE", 1750, "Failure while changing the type of replication repository: %s." }, -{ "ER_WARNING_NOT_COMPLETE_ROLLBACK_WITH_CREATED_TEMP_TABLE", 1751, "The creation of some temporary tables could not be rolled back." }, -{ "ER_WARNING_NOT_COMPLETE_ROLLBACK_WITH_DROPPED_TEMP_TABLE", 1752, "Some temporary tables were dropped, but these operations could not be rolled back." }, -{ "ER_MTS_FEATURE_IS_NOT_SUPPORTED", 1753, "%s is not supported in multi-threaded slave mode. %s" }, -{ "ER_MTS_UPDATED_DBS_GREATER_MAX", 1754, "The number of modified databases exceeds the maximum %d; the database names will not be included in the replication event metadata." }, -{ "ER_MTS_CANT_PARALLEL", 1755, "Cannot execute the current event group in the parallel mode. Encountered event %s, relay-log name %s, position %s which prevents execution of this event group in parallel mode. Reason: %s." }, -{ "ER_MTS_INCONSISTENT_DATA", 1756, "%s" }, -{ "ER_FULLTEXT_NOT_SUPPORTED_WITH_PARTITIONING", 1757, "FULLTEXT index is not supported for partitioned tables." }, -{ "ER_DA_INVALID_CONDITION_NUMBER", 1758, "Invalid condition number" }, -{ "ER_INSECURE_PLAIN_TEXT", 1759, "Sending passwords in plain text without SSL/TLS is extremely insecure." }, -{ "ER_INSECURE_CHANGE_MASTER", 1760, "Storing MySQL user name or password information in the master info repository is not secure and is therefore not recommended. Please consider using the USER and PASSWORD connection options for START SLAVE; see the \'START SLAVE Syntax\' in the MySQL Manual for more information." }, -{ "ER_FOREIGN_DUPLICATE_KEY_WITH_CHILD_INFO", 1761, "Foreign key constraint for table \'%.192s\', record \'%-.192s\' would lead to a duplicate entry in table \'%.192s\', key \'%.192s\'" }, -{ "ER_FOREIGN_DUPLICATE_KEY_WITHOUT_CHILD_INFO", 1762, "Foreign key constraint for table \'%.192s\', record \'%-.192s\' would lead to a duplicate entry in a child table" }, -{ "ER_SQLTHREAD_WITH_SECURE_SLAVE", 1763, "Setting authentication options is not possible when only the Slave SQL Thread is being started." }, -{ "ER_TABLE_HAS_NO_FT", 1764, "The table does not have FULLTEXT index to support this query" }, -{ "ER_VARIABLE_NOT_SETTABLE_IN_SF_OR_TRIGGER", 1765, "The system variable %.200s cannot be set in stored functions or triggers." }, -{ "ER_VARIABLE_NOT_SETTABLE_IN_TRANSACTION", 1766, "The system variable %.200s cannot be set when there is an ongoing transaction." }, -{ "ER_GTID_NEXT_IS_NOT_IN_GTID_NEXT_LIST", 1767, "The system variable @@SESSION.GTID_NEXT has the value %.200s, which is not listed in @@SESSION.GTID_NEXT_LIST." }, -{ "ER_CANT_CHANGE_GTID_NEXT_IN_TRANSACTION", 1768, "The system variable @@SESSION.GTID_NEXT cannot change inside a transaction." }, -{ "ER_SET_STATEMENT_CANNOT_INVOKE_FUNCTION", 1769, "The statement \'SET %.200s\' cannot invoke a stored function." }, -{ "ER_GTID_NEXT_CANT_BE_AUTOMATIC_IF_GTID_NEXT_LIST_IS_NON_NULL", 1770, "The system variable @@SESSION.GTID_NEXT cannot be \'AUTOMATIC\' when @@SESSION.GTID_NEXT_LIST is non-NULL." }, -{ "ER_SKIPPING_LOGGED_TRANSACTION", 1771, "Skipping transaction %.200s because it has already been executed and logged." }, -{ "ER_MALFORMED_GTID_SET_SPECIFICATION", 1772, "Malformed GTID set specification \'%.200s\'." }, -{ "ER_MALFORMED_GTID_SET_ENCODING", 1773, "Malformed GTID set encoding." }, -{ "ER_MALFORMED_GTID_SPECIFICATION", 1774, "Malformed GTID specification \'%.200s\'." }, -{ "ER_GNO_EXHAUSTED", 1775, "Impossible to generate Global Transaction Identifier: the integer component reached the maximal value. Restart the server with a new server_uuid." }, -{ "ER_BAD_SLAVE_AUTO_POSITION", 1776, "Parameters MASTER_LOG_FILE, MASTER_LOG_POS, RELAY_LOG_FILE and RELAY_LOG_POS cannot be set when MASTER_AUTO_POSITION is active." }, -{ "ER_AUTO_POSITION_REQUIRES_GTID_MODE_NOT_OFF", 1777, "CHANGE MASTER TO MASTER_AUTO_POSITION = 1 cannot be executed because @@GLOBAL.GTID_MODE = OFF." }, -{ "ER_CANT_DO_IMPLICIT_COMMIT_IN_TRX_WHEN_GTID_NEXT_IS_SET", 1778, "Cannot execute statements with implicit commit inside a transaction when @@SESSION.GTID_NEXT == \'UUID:NUMBER\'." }, -{ "ER_GTID_MODE_ON_REQUIRES_ENFORCE_GTID_CONSISTENCY_ON", 1779, "GTID_MODE = ON requires ENFORCE_GTID_CONSISTENCY = ON." }, -{ "ER_GTID_MODE_REQUIRES_BINLOG", 1780, "@@GLOBAL.GTID_MODE = ON or ON_PERMISSIVE or OFF_PERMISSIVE requires --log-bin and --log-slave-updates." }, -{ "ER_CANT_SET_GTID_NEXT_TO_GTID_WHEN_GTID_MODE_IS_OFF", 1781, "@@SESSION.GTID_NEXT cannot be set to UUID:NUMBER when @@GLOBAL.GTID_MODE = OFF." }, -{ "ER_CANT_SET_GTID_NEXT_TO_ANONYMOUS_WHEN_GTID_MODE_IS_ON", 1782, "@@SESSION.GTID_NEXT cannot be set to ANONYMOUS when @@GLOBAL.GTID_MODE = ON." }, -{ "ER_CANT_SET_GTID_NEXT_LIST_TO_NON_NULL_WHEN_GTID_MODE_IS_OFF", 1783, "@@SESSION.GTID_NEXT_LIST cannot be set to a non-NULL value when @@GLOBAL.GTID_MODE = OFF." }, -{ "ER_FOUND_GTID_EVENT_WHEN_GTID_MODE_IS_OFF__UNUSED", 1784, "Found a Gtid_log_event when @@GLOBAL.GTID_MODE = OFF." }, -{ "ER_GTID_UNSAFE_NON_TRANSACTIONAL_TABLE", 1785, "Statement violates GTID consistency: Updates to non-transactional tables can only be done in either autocommitted statements or single-statement transactions, and never in the same statement as updates to transactional tables." }, -{ "ER_GTID_UNSAFE_CREATE_SELECT", 1786, "Statement violates GTID consistency: CREATE TABLE ... SELECT." }, -{ "ER_GTID_UNSAFE_CREATE_DROP_TEMPORARY_TABLE_IN_TRANSACTION", 1787, "Statement violates GTID consistency: CREATE TEMPORARY TABLE and DROP TEMPORARY TABLE can only be executed outside transactional context. These statements are also not allowed in a function or trigger because functions and triggers are also considered to be multi-statement transactions." }, -{ "ER_GTID_MODE_CAN_ONLY_CHANGE_ONE_STEP_AT_A_TIME", 1788, "The value of @@GLOBAL.GTID_MODE can only be changed one step at a time: OFF <-> OFF_PERMISSIVE <-> ON_PERMISSIVE <-> ON. Also note that this value must be stepped up or down simultaneously on all servers. See the Manual for instructions." }, -{ "ER_MASTER_HAS_PURGED_REQUIRED_GTIDS", 1789, "The slave is connecting using CHANGE MASTER TO MASTER_AUTO_POSITION = 1, but the master has purged binary logs containing GTIDs that the slave requires." }, -{ "ER_CANT_SET_GTID_NEXT_WHEN_OWNING_GTID", 1790, "@@SESSION.GTID_NEXT cannot be changed by a client that owns a GTID. The client owns %s. Ownership is released on COMMIT or ROLLBACK." }, -{ "ER_UNKNOWN_EXPLAIN_FORMAT", 1791, "Unknown EXPLAIN format name: \'%s\'" }, -{ "ER_CANT_EXECUTE_IN_READ_ONLY_TRANSACTION", 1792, "Cannot execute statement in a READ ONLY transaction." }, -{ "ER_TOO_LONG_TABLE_PARTITION_COMMENT", 1793, "Comment for table partition \'%-.64s\' is too long (max = %lu)" }, -{ "ER_SLAVE_CONFIGURATION", 1794, "Slave is not configured or failed to initialize properly. You must at least set --server-id to enable either a master or a slave. Additional error messages can be found in the MySQL error log." }, -{ "ER_INNODB_FT_LIMIT", 1795, "InnoDB presently supports one FULLTEXT index creation at a time" }, -{ "ER_INNODB_NO_FT_TEMP_TABLE", 1796, "Cannot create FULLTEXT index on temporary InnoDB table" }, -{ "ER_INNODB_FT_WRONG_DOCID_COLUMN", 1797, "Column \'%-.192s\' is of wrong type for an InnoDB FULLTEXT index" }, -{ "ER_INNODB_FT_WRONG_DOCID_INDEX", 1798, "Index \'%-.192s\' is of wrong type for an InnoDB FULLTEXT index" }, -{ "ER_INNODB_ONLINE_LOG_TOO_BIG", 1799, "Creating index \'%-.192s\' required more than \'innodb_online_alter_log_max_size\' bytes of modification log. Please try again." }, -{ "ER_UNKNOWN_ALTER_ALGORITHM", 1800, "Unknown ALGORITHM \'%s\'" }, -{ "ER_UNKNOWN_ALTER_LOCK", 1801, "Unknown LOCK type \'%s\'" }, -{ "ER_MTS_CHANGE_MASTER_CANT_RUN_WITH_GAPS", 1802, "CHANGE MASTER cannot be executed when the slave was stopped with an error or killed in MTS mode. Consider using RESET SLAVE or START SLAVE UNTIL." }, -{ "ER_MTS_RECOVERY_FAILURE", 1803, "Cannot recover after SLAVE errored out in parallel execution mode. Additional error messages can be found in the MySQL error log." }, -{ "ER_MTS_RESET_WORKERS", 1804, "Cannot clean up worker info tables. Additional error messages can be found in the MySQL error log." }, -{ "ER_COL_COUNT_DOESNT_MATCH_CORRUPTED_V2", 1805, "Column count of %s.%s is wrong. Expected %d, found %d. The table is probably corrupted" }, -{ "ER_SLAVE_SILENT_RETRY_TRANSACTION", 1806, "Slave must silently retry current transaction" }, -{ "ER_DISCARD_FK_CHECKS_RUNNING", 1807, "There is a foreign key check running on table \'%-.192s\'. Cannot discard the table." }, -{ "ER_TABLE_SCHEMA_MISMATCH", 1808, "Schema mismatch (%s)" }, -{ "ER_TABLE_IN_SYSTEM_TABLESPACE", 1809, "Table \'%-.192s\' in system tablespace" }, -{ "ER_IO_READ_ERROR", 1810, "IO Read error: (%lu, %s) %s" }, -{ "ER_IO_WRITE_ERROR", 1811, "IO Write error: (%lu, %s) %s" }, -{ "ER_TABLESPACE_MISSING", 1812, "Tablespace is missing for table %s." }, -{ "ER_TABLESPACE_EXISTS", 1813, "Tablespace \'%-.192s\' exists." }, -{ "ER_TABLESPACE_DISCARDED", 1814, "Tablespace has been discarded for table \'%-.192s\'" }, -{ "ER_INTERNAL_ERROR", 1815, "Internal error: %s" }, -{ "ER_INNODB_IMPORT_ERROR", 1816, "ALTER TABLE %-.192s IMPORT TABLESPACE failed with error %lu : \'%s\'" }, -{ "ER_INNODB_INDEX_CORRUPT", 1817, "Index corrupt: %s" }, -{ "ER_INVALID_YEAR_COLUMN_LENGTH", 1818, "Supports only YEAR or YEAR(4) column." }, -{ "ER_NOT_VALID_PASSWORD", 1819, "Your password does not satisfy the current policy requirements" }, -{ "ER_MUST_CHANGE_PASSWORD", 1820, "You must reset your password using ALTER USER statement before executing this statement." }, -{ "ER_FK_NO_INDEX_CHILD", 1821, "Failed to add the foreign key constaint. Missing index for constraint \'%s\' in the foreign table \'%s\'" }, -{ "ER_FK_NO_INDEX_PARENT", 1822, "Failed to add the foreign key constaint. Missing index for constraint \'%s\' in the referenced table \'%s\'" }, -{ "ER_FK_FAIL_ADD_SYSTEM", 1823, "Failed to add the foreign key constraint \'%s\' to system tables" }, -{ "ER_FK_CANNOT_OPEN_PARENT", 1824, "Failed to open the referenced table \'%s\'" }, -{ "ER_FK_INCORRECT_OPTION", 1825, "Failed to add the foreign key constraint on table \'%s\'. Incorrect options in FOREIGN KEY constraint \'%s\'" }, -{ "ER_FK_DUP_NAME", 1826, "Duplicate foreign key constraint name \'%s\'" }, -{ "ER_PASSWORD_FORMAT", 1827, "The password hash doesn\'t have the expected format. Check if the correct password algorithm is being used with the PASSWORD() function." }, -{ "ER_FK_COLUMN_CANNOT_DROP", 1828, "Cannot drop column \'%-.192s\': needed in a foreign key constraint \'%-.192s\'" }, -{ "ER_FK_COLUMN_CANNOT_DROP_CHILD", 1829, "Cannot drop column \'%-.192s\': needed in a foreign key constraint \'%-.192s\' of table \'%-.192s\'" }, -{ "ER_FK_COLUMN_NOT_NULL", 1830, "Column \'%-.192s\' cannot be NOT NULL: needed in a foreign key constraint \'%-.192s\' SET NULL" }, -{ "ER_DUP_INDEX", 1831, "Duplicate index \'%-.64s\' defined on the table \'%-.64s.%-.64s\'. This is deprecated and will be disallowed in a future release." }, -{ "ER_FK_COLUMN_CANNOT_CHANGE", 1832, "Cannot change column \'%-.192s\': used in a foreign key constraint \'%-.192s\'" }, -{ "ER_FK_COLUMN_CANNOT_CHANGE_CHILD", 1833, "Cannot change column \'%-.192s\': used in a foreign key constraint \'%-.192s\' of table \'%-.192s\'" }, -{ "ER_UNUSED5", 1834, "Cannot delete rows from table which is parent in a foreign key constraint \'%-.192s\' of table \'%-.192s\'" }, -{ "ER_MALFORMED_PACKET", 1835, "Malformed communication packet." }, -{ "ER_READ_ONLY_MODE", 1836, "Running in read-only mode" }, -{ "ER_GTID_NEXT_TYPE_UNDEFINED_GROUP", 1837, "When @@SESSION.GTID_NEXT is set to a GTID, you must explicitly set it to a different value after a COMMIT or ROLLBACK. Please check GTID_NEXT variable manual page for detailed explanation. Current @@SESSION.GTID_NEXT is \'%s\'." }, -{ "ER_VARIABLE_NOT_SETTABLE_IN_SP", 1838, "The system variable %.200s cannot be set in stored procedures." }, -{ "ER_CANT_SET_GTID_PURGED_WHEN_GTID_MODE_IS_OFF", 1839, "@@GLOBAL.GTID_PURGED can only be set when @@GLOBAL.GTID_MODE = ON." }, -{ "ER_CANT_SET_GTID_PURGED_WHEN_GTID_EXECUTED_IS_NOT_EMPTY", 1840, "@@GLOBAL.GTID_PURGED can only be set when @@GLOBAL.GTID_EXECUTED is empty." }, -{ "ER_CANT_SET_GTID_PURGED_WHEN_OWNED_GTIDS_IS_NOT_EMPTY", 1841, "@@GLOBAL.GTID_PURGED can only be set when there are no ongoing transactions (not even in other clients)." }, -{ "ER_GTID_PURGED_WAS_CHANGED", 1842, "@@GLOBAL.GTID_PURGED was changed from \'%s\' to \'%s\'." }, -{ "ER_GTID_EXECUTED_WAS_CHANGED", 1843, "@@GLOBAL.GTID_EXECUTED was changed from \'%s\' to \'%s\'." }, -{ "ER_BINLOG_STMT_MODE_AND_NO_REPL_TABLES", 1844, "Cannot execute statement: impossible to write to binary log since BINLOG_FORMAT = STATEMENT, and both replicated and non replicated tables are written to." }, -{ "ER_ALTER_OPERATION_NOT_SUPPORTED", 1845, "%s is not supported for this operation. Try %s." }, -{ "ER_ALTER_OPERATION_NOT_SUPPORTED_REASON", 1846, "%s is not supported. Reason: %s. Try %s." }, -{ "ER_ALTER_OPERATION_NOT_SUPPORTED_REASON_COPY", 1847, "COPY algorithm requires a lock" }, -{ "ER_ALTER_OPERATION_NOT_SUPPORTED_REASON_PARTITION", 1848, "Partition specific operations do not yet support LOCK/ALGORITHM" }, -{ "ER_ALTER_OPERATION_NOT_SUPPORTED_REASON_FK_RENAME", 1849, "Columns participating in a foreign key are renamed" }, -{ "ER_ALTER_OPERATION_NOT_SUPPORTED_REASON_COLUMN_TYPE", 1850, "Cannot change column type INPLACE" }, -{ "ER_ALTER_OPERATION_NOT_SUPPORTED_REASON_FK_CHECK", 1851, "Adding foreign keys needs foreign_key_checks=OFF" }, -{ "ER_UNUSED6", 1852, "Creating unique indexes with IGNORE requires COPY algorithm to remove duplicate rows" }, -{ "ER_ALTER_OPERATION_NOT_SUPPORTED_REASON_NOPK", 1853, "Dropping a primary key is not allowed without also adding a new primary key" }, -{ "ER_ALTER_OPERATION_NOT_SUPPORTED_REASON_AUTOINC", 1854, "Adding an auto-increment column requires a lock" }, -{ "ER_ALTER_OPERATION_NOT_SUPPORTED_REASON_HIDDEN_FTS", 1855, "Cannot replace hidden FTS_DOC_ID with a user-visible one" }, -{ "ER_ALTER_OPERATION_NOT_SUPPORTED_REASON_CHANGE_FTS", 1856, "Cannot drop or rename FTS_DOC_ID" }, -{ "ER_ALTER_OPERATION_NOT_SUPPORTED_REASON_FTS", 1857, "Fulltext index creation requires a lock" }, -{ "ER_SQL_SLAVE_SKIP_COUNTER_NOT_SETTABLE_IN_GTID_MODE", 1858, "sql_slave_skip_counter can not be set when the server is running with @@GLOBAL.GTID_MODE = ON. Instead, for each transaction that you want to skip, generate an empty transaction with the same GTID as the transaction" }, -{ "ER_DUP_UNKNOWN_IN_INDEX", 1859, "Duplicate entry for key \'%-.192s\'" }, -{ "ER_IDENT_CAUSES_TOO_LONG_PATH", 1860, "Long database name and identifier for object resulted in path length exceeding %d characters. Path: \'%s\'." }, -{ "ER_ALTER_OPERATION_NOT_SUPPORTED_REASON_NOT_NULL", 1861, "cannot silently convert NULL values, as required in this SQL_MODE" }, -{ "ER_MUST_CHANGE_PASSWORD_LOGIN", 1862, "Your password has expired. To log in you must change it using a client that supports expired passwords." }, -{ "ER_ROW_IN_WRONG_PARTITION", 1863, "Found a row in wrong partition %s" }, -{ "ER_MTS_EVENT_BIGGER_PENDING_JOBS_SIZE_MAX", 1864, "Cannot schedule event %s, relay-log name %s, position %s to Worker thread because its size %lu exceeds %lu of slave_pending_jobs_size_max." }, -{ "ER_INNODB_NO_FT_USES_PARSER", 1865, "Cannot CREATE FULLTEXT INDEX WITH PARSER on InnoDB table" }, -{ "ER_BINLOG_LOGICAL_CORRUPTION", 1866, "The binary log file \'%s\' is logically corrupted: %s" }, -{ "ER_WARN_PURGE_LOG_IN_USE", 1867, "file %s was not purged because it was being read by %d thread(s), purged only %d out of %d files." }, -{ "ER_WARN_PURGE_LOG_IS_ACTIVE", 1868, "file %s was not purged because it is the active log file." }, -{ "ER_AUTO_INCREMENT_CONFLICT", 1869, "Auto-increment value in UPDATE conflicts with internally generated values" }, -{ "WARN_ON_BLOCKHOLE_IN_RBR", 1870, "Row events are not logged for %s statements that modify BLACKHOLE tables in row format. Table(s): \'%-.192s\'" }, -{ "ER_SLAVE_MI_INIT_REPOSITORY", 1871, "Slave failed to initialize master info structure from the repository" }, -{ "ER_SLAVE_RLI_INIT_REPOSITORY", 1872, "Slave failed to initialize relay log info structure from the repository" }, -{ "ER_ACCESS_DENIED_CHANGE_USER_ERROR", 1873, "Access denied trying to change to user \'%-.48s\'@\'%-.64s\' (using password: %s). Disconnecting." }, -{ "ER_INNODB_READ_ONLY", 1874, "InnoDB is in read only mode." }, -{ "ER_STOP_SLAVE_SQL_THREAD_TIMEOUT", 1875, "STOP SLAVE command execution is incomplete: Slave SQL thread got the stop signal, thread is busy, SQL thread will stop once the current task is complete." }, -{ "ER_STOP_SLAVE_IO_THREAD_TIMEOUT", 1876, "STOP SLAVE command execution is incomplete: Slave IO thread got the stop signal, thread is busy, IO thread will stop once the current task is complete." }, -{ "ER_TABLE_CORRUPT", 1877, "Operation cannot be performed. The table \'%-.64s.%-.64s\' is missing, corrupt or contains bad data." }, -{ "ER_TEMP_FILE_WRITE_FAILURE", 1878, "Temporary file write failure." }, -{ "ER_INNODB_FT_AUX_NOT_HEX_ID", 1879, "Upgrade index name failed, please use create index(alter table) algorithm copy to rebuild index." }, -{ "ER_OLD_TEMPORALS_UPGRADED", 1880, "TIME/TIMESTAMP/DATETIME columns of old format have been upgraded to the new format." }, -{ "ER_INNODB_FORCED_RECOVERY", 1881, "Operation not allowed when innodb_forced_recovery > 0." }, -{ "ER_AES_INVALID_IV", 1882, "The initialization vector supplied to %s is too short. Must be at least %d bytes long" }, -{ "ER_PLUGIN_CANNOT_BE_UNINSTALLED", 1883, "Plugin \'%s\' cannot be uninstalled now. %s" }, -{ "ER_GTID_UNSAFE_BINLOG_SPLITTABLE_STATEMENT_AND_GTID_GROUP", 1884, "Cannot execute statement because it needs to be written to the binary log as multiple statements, and this is not allowed when @@SESSION.GTID_NEXT == \'UUID:NUMBER\'." }, -{ "ER_SLAVE_HAS_MORE_GTIDS_THAN_MASTER", 1885, "Slave has more GTIDs than the master has, using the master\'s SERVER_UUID. This may indicate that the end of the binary log was truncated or that the last binary log file was lost, e.g., after a power or disk failure when sync_binlog != 1. The master may or may not have rolled back transactions that were already replicated to the slave. Suggest to replicate any transactions that master has rolled back from slave to master, and/or commit empty transactions on master to account for transactions that have been committed on master but are not included in GTID_EXECUTED." }, -{ "ER_FILE_CORRUPT", 3000, "File %s is corrupted" }, -{ "ER_ERROR_ON_MASTER", 3001, "Query partially completed on the master (error on master: %d) and was aborted. There is a chance that your master is inconsistent at this point. If you are sure that your master is ok, run this query manually on the slave and then restart the slave with SET GLOBAL SQL_SLAVE_SKIP_COUNTER=1; START SLAVE;. Query:\'%s\'" }, -{ "ER_INCONSISTENT_ERROR", 3002, "Query caused different errors on master and slave. Error on master: message (format)=\'%s\' error code=%d; Error on slave:actual message=\'%s\', error code=%d. Default database:\'%s\'. Query:\'%s\'" }, -{ "ER_STORAGE_ENGINE_NOT_LOADED", 3003, "Storage engine for table \'%s\'.\'%s\' is not loaded." }, -{ "ER_GET_STACKED_DA_WITHOUT_ACTIVE_HANDLER", 3004, "GET STACKED DIAGNOSTICS when handler not active" }, -{ "ER_WARN_LEGACY_SYNTAX_CONVERTED", 3005, "%s is no longer supported. The statement was converted to %s." }, -{ "ER_BINLOG_UNSAFE_FULLTEXT_PLUGIN", 3006, "Statement is unsafe because it uses a fulltext parser plugin which may not return the same value on the slave." }, -{ "ER_CANNOT_DISCARD_TEMPORARY_TABLE", 3007, "Cannot DISCARD/IMPORT tablespace associated with temporary table" }, -{ "ER_FK_DEPTH_EXCEEDED", 3008, "Foreign key cascade delete/update exceeds max depth of %d." }, -{ "ER_COL_COUNT_DOESNT_MATCH_PLEASE_UPDATE_V2", 3009, "Column count of %s.%s is wrong. Expected %d, found %d. Created with MySQL %d, now running %d. Please use mysql_upgrade to fix this error." }, -{ "ER_WARN_TRIGGER_DOESNT_HAVE_CREATED", 3010, "Trigger %s.%s.%s does not have CREATED attribute." }, -{ "ER_REFERENCED_TRG_DOES_NOT_EXIST", 3011, "Referenced trigger \'%s\' for the given action time and event type does not exist." }, -{ "ER_EXPLAIN_NOT_SUPPORTED", 3012, "EXPLAIN FOR CONNECTION command is supported only for SELECT/UPDATE/INSERT/DELETE/REPLACE" }, -{ "ER_INVALID_FIELD_SIZE", 3013, "Invalid size for column \'%-.192s\'." }, -{ "ER_MISSING_HA_CREATE_OPTION", 3014, "Table storage engine \'%-.64s\' found required create option missing" }, -{ "ER_ENGINE_OUT_OF_MEMORY", 3015, "Out of memory in storage engine \'%-.64s\'." }, -{ "ER_PASSWORD_EXPIRE_ANONYMOUS_USER", 3016, "The password for anonymous user cannot be expired." }, -{ "ER_SLAVE_SQL_THREAD_MUST_STOP", 3017, "This operation cannot be performed with a running slave sql thread; run STOP SLAVE SQL_THREAD first" }, -{ "ER_NO_FT_MATERIALIZED_SUBQUERY", 3018, "Cannot create FULLTEXT index on materialized subquery" }, -{ "ER_INNODB_UNDO_LOG_FULL", 3019, "Undo Log error: %s" }, -{ "ER_INVALID_ARGUMENT_FOR_LOGARITHM", 3020, "Invalid argument for logarithm" }, -{ "ER_SLAVE_CHANNEL_IO_THREAD_MUST_STOP", 3021, "This operation cannot be performed with a running slave io thread; run STOP SLAVE IO_THREAD FOR CHANNEL \'%s\' first." }, -{ "ER_WARN_OPEN_TEMP_TABLES_MUST_BE_ZERO", 3022, "This operation may not be safe when the slave has temporary tables. The tables will be kept open until the server restarts or until the tables are deleted by any replicated DROP statement. Suggest to wait until slave_open_temp_tables = 0." }, -{ "ER_WARN_ONLY_MASTER_LOG_FILE_NO_POS", 3023, "CHANGE MASTER TO with a MASTER_LOG_FILE clause but no MASTER_LOG_POS clause may not be safe. The old position value may not be valid for the new binary log file." }, -{ "ER_QUERY_TIMEOUT", 3024, "Query execution was interrupted, maximum statement execution time exceeded" }, -{ "ER_NON_RO_SELECT_DISABLE_TIMER", 3025, "Select is not a read only statement, disabling timer" }, -{ "ER_DUP_LIST_ENTRY", 3026, "Duplicate entry \'%-.192s\'." }, -{ "ER_SQL_MODE_NO_EFFECT", 3027, "\'%s\' mode no longer has any effect. Use STRICT_ALL_TABLES or STRICT_TRANS_TABLES instead." }, -{ "ER_AGGREGATE_ORDER_FOR_UNION", 3028, "Expression #%u of ORDER BY contains aggregate function and applies to a UNION" }, -{ "ER_AGGREGATE_ORDER_NON_AGG_QUERY", 3029, "Expression #%u of ORDER BY contains aggregate function and applies to the result of a non-aggregated query" }, -{ "ER_SLAVE_WORKER_STOPPED_PREVIOUS_THD_ERROR", 3030, "Slave worker has stopped after at least one previous worker encountered an error when slave-preserve-commit-order was enabled. To preserve commit order, the last transaction executed by this thread has not been committed. When restarting the slave after fixing any failed threads, you should fix this worker as well." }, -{ "ER_DONT_SUPPORT_SLAVE_PRESERVE_COMMIT_ORDER", 3031, "slave_preserve_commit_order is not supported %s." }, -{ "ER_SERVER_OFFLINE_MODE", 3032, "The server is currently in offline mode" }, -{ "ER_GIS_DIFFERENT_SRIDS", 3033, "Binary geometry function %s given two geometries of different srids: %u and %u, which should have been identical." }, -{ "ER_GIS_UNSUPPORTED_ARGUMENT", 3034, "Calling geometry function %s with unsupported types of arguments." }, -{ "ER_GIS_UNKNOWN_ERROR", 3035, "Unknown GIS error occured in function %s." }, -{ "ER_GIS_UNKNOWN_EXCEPTION", 3036, "Unknown exception caught in GIS function %s." }, -{ "ER_GIS_INVALID_DATA", 3037, "Invalid GIS data provided to function %s." }, -{ "ER_BOOST_GEOMETRY_EMPTY_INPUT_EXCEPTION", 3038, "The geometry has no data in function %s." }, -{ "ER_BOOST_GEOMETRY_CENTROID_EXCEPTION", 3039, "Unable to calculate centroid because geometry is empty in function %s." }, -{ "ER_BOOST_GEOMETRY_OVERLAY_INVALID_INPUT_EXCEPTION", 3040, "Geometry overlay calculation error: geometry data is invalid in function %s." }, -{ "ER_BOOST_GEOMETRY_TURN_INFO_EXCEPTION", 3041, "Geometry turn info calculation error: geometry data is invalid in function %s." }, -{ "ER_BOOST_GEOMETRY_SELF_INTERSECTION_POINT_EXCEPTION", 3042, "Analysis procedures of intersection points interrupted unexpectedly in function %s." }, -{ "ER_BOOST_GEOMETRY_UNKNOWN_EXCEPTION", 3043, "Unknown exception thrown in function %s." }, -{ "ER_STD_BAD_ALLOC_ERROR", 3044, "Memory allocation error: %-.256s in function %s." }, -{ "ER_STD_DOMAIN_ERROR", 3045, "Domain error: %-.256s in function %s." }, -{ "ER_STD_LENGTH_ERROR", 3046, "Length error: %-.256s in function %s." }, -{ "ER_STD_INVALID_ARGUMENT", 3047, "Invalid argument error: %-.256s in function %s." }, -{ "ER_STD_OUT_OF_RANGE_ERROR", 3048, "Out of range error: %-.256s in function %s." }, -{ "ER_STD_OVERFLOW_ERROR", 3049, "Overflow error error: %-.256s in function %s." }, -{ "ER_STD_RANGE_ERROR", 3050, "Range error: %-.256s in function %s." }, -{ "ER_STD_UNDERFLOW_ERROR", 3051, "Underflow error: %-.256s in function %s." }, -{ "ER_STD_LOGIC_ERROR", 3052, "Logic error: %-.256s in function %s." }, -{ "ER_STD_RUNTIME_ERROR", 3053, "Runtime error: %-.256s in function %s." }, -{ "ER_STD_UNKNOWN_EXCEPTION", 3054, "Unknown exception: %-.384s in function %s." }, -{ "ER_GIS_DATA_WRONG_ENDIANESS", 3055, "Geometry byte string must be little endian." }, -{ "ER_CHANGE_MASTER_PASSWORD_LENGTH", 3056, "The password provided for the replication user exceeds the maximum length of 32 characters" }, -{ "ER_USER_LOCK_WRONG_NAME", 3057, "Incorrect user-level lock name \'%-.192s\'." }, -{ "ER_USER_LOCK_DEADLOCK", 3058, "Deadlock found when trying to get user-level lock; try rolling back transaction/releasing locks and restarting lock acquisition." }, -{ "ER_REPLACE_INACCESSIBLE_ROWS", 3059, "REPLACE cannot be executed as it requires deleting rows that are not in the view" }, -{ "ER_ALTER_OPERATION_NOT_SUPPORTED_REASON_GIS", 3060, "Do not support online operation on table with GIS index" }, -{ "ER_ILLEGAL_USER_VAR", 3061, "User variable name \'%-.100s\' is illegal" }, -{ "ER_GTID_MODE_OFF", 3062, "Cannot %s when GTID_MODE = OFF." }, -{ "ER_UNSUPPORTED_BY_REPLICATION_THREAD", 3063, "Cannot %s from a replication slave thread." }, -{ "ER_INCORRECT_TYPE", 3064, "Incorrect type for argument %s in function %s." }, -{ "ER_FIELD_IN_ORDER_NOT_SELECT", 3065, "Expression #%u of ORDER BY clause is not in SELECT list, references column \'%-.192s\' which is not in SELECT list; this is incompatible with %s" }, -{ "ER_AGGREGATE_IN_ORDER_NOT_SELECT", 3066, "Expression #%u of ORDER BY clause is not in SELECT list, contains aggregate function; this is incompatible with %s" }, -{ "ER_INVALID_RPL_WILD_TABLE_FILTER_PATTERN", 3067, "Supplied filter list contains a value which is not in the required format \'db_pattern.table_pattern\'" }, -{ "ER_NET_OK_PACKET_TOO_LARGE", 3068, "OK packet too large" }, -{ "ER_INVALID_JSON_DATA", 3069, "Invalid JSON data provided to function %s: %s" }, -{ "ER_INVALID_GEOJSON_MISSING_MEMBER", 3070, "Invalid GeoJSON data provided to function %s: Missing required member \'%s\'" }, -{ "ER_INVALID_GEOJSON_WRONG_TYPE", 3071, "Invalid GeoJSON data provided to function %s: Member \'%s\' must be of type \'%s\'" }, -{ "ER_INVALID_GEOJSON_UNSPECIFIED", 3072, "Invalid GeoJSON data provided to function %s" }, -{ "ER_DIMENSION_UNSUPPORTED", 3073, "Unsupported number of coordinate dimensions in function %s: Found %u, expected %u" }, -{ "ER_SLAVE_CHANNEL_DOES_NOT_EXIST", 3074, "Slave channel \'%s\' does not exist." }, -{ "ER_SLAVE_MULTIPLE_CHANNELS_HOST_PORT", 3075, "A slave channel \'%s\' already exists for the given host and port combination." }, -{ "ER_SLAVE_CHANNEL_NAME_INVALID_OR_TOO_LONG", 3076, "Couldn\'t create channel: Channel name is either invalid or too long." }, -{ "ER_SLAVE_NEW_CHANNEL_WRONG_REPOSITORY", 3077, "To have multiple channels, repository cannot be of type FILE; Please check the repository configuration and convert them to TABLE." }, -{ "ER_SLAVE_CHANNEL_DELETE", 3078, "Cannot delete slave info objects for channel \'%s\'." }, -{ "ER_SLAVE_MULTIPLE_CHANNELS_CMD", 3079, "Multiple channels exist on the slave. Please provide channel name as an argument." }, -{ "ER_SLAVE_MAX_CHANNELS_EXCEEDED", 3080, "Maximum number of replication channels allowed exceeded." }, -{ "ER_SLAVE_CHANNEL_MUST_STOP", 3081, "This operation cannot be performed with running replication threads; run STOP SLAVE FOR CHANNEL \'%s\' first" }, -{ "ER_SLAVE_CHANNEL_NOT_RUNNING", 3082, "This operation requires running replication threads; configure slave and run START SLAVE FOR CHANNEL \'%s\'" }, -{ "ER_SLAVE_CHANNEL_WAS_RUNNING", 3083, "Replication thread(s) for channel \'%s\' are already runnning." }, -{ "ER_SLAVE_CHANNEL_WAS_NOT_RUNNING", 3084, "Replication thread(s) for channel \'%s\' are already stopped." }, -{ "ER_SLAVE_CHANNEL_SQL_THREAD_MUST_STOP", 3085, "This operation cannot be performed with a running slave sql thread; run STOP SLAVE SQL_THREAD FOR CHANNEL \'%s\' first." }, -{ "ER_SLAVE_CHANNEL_SQL_SKIP_COUNTER", 3086, "When sql_slave_skip_counter > 0, it is not allowed to start more than one SQL thread by using \'START SLAVE [SQL_THREAD]\'. Value of sql_slave_skip_counter can only be used by one SQL thread at a time. Please use \'START SLAVE [SQL_THREAD] FOR CHANNEL\' to start the SQL thread which will use the value of sql_slave_skip_counter." }, -{ "ER_WRONG_FIELD_WITH_GROUP_V2", 3087, "Expression #%u of %s is not in GROUP BY clause and contains nonaggregated column \'%-.192s\' which is not functionally dependent on columns in GROUP BY clause; this is incompatible with sql_mode=only_full_group_by" }, -{ "ER_MIX_OF_GROUP_FUNC_AND_FIELDS_V2", 3088, "In aggregated query without GROUP BY, expression #%u of %s contains nonaggregated column \'%-.192s\'; this is incompatible with sql_mode=only_full_group_by" }, -{ "ER_WARN_DEPRECATED_SYSVAR_UPDATE", 3089, "Updating \'%s\' is deprecated. It will be made read-only in a future release." }, -{ "ER_WARN_DEPRECATED_SQLMODE", 3090, "Changing sql mode \'%s\' is deprecated. It will be removed in a future release." }, -{ "ER_CANNOT_LOG_PARTIAL_DROP_DATABASE_WITH_GTID", 3091, "DROP DATABASE failed; some tables may have been dropped but the database directory remains. The GTID has not been added to GTID_EXECUTED and the statement was not written to the binary log. Fix this as follows: (1) remove all files from the database directory %-.192s; (2) SET GTID_NEXT=\'%-.192s\'; (3) DROP DATABASE `%-.192s`." }, -{ "ER_GROUP_REPLICATION_CONFIGURATION", 3092, "The server is not configured properly to be an active member of the group. Please see more details on error log." }, -{ "ER_GROUP_REPLICATION_RUNNING", 3093, "The START GROUP_REPLICATION command failed since the group is already running." }, -{ "ER_GROUP_REPLICATION_APPLIER_INIT_ERROR", 3094, "The START GROUP_REPLICATION command failed as the applier module failed to start." }, -{ "ER_GROUP_REPLICATION_STOP_APPLIER_THREAD_TIMEOUT", 3095, "The STOP GROUP_REPLICATION command execution is incomplete: The applier thread got the stop signal while it was busy. The applier thread will stop once the current task is complete." }, -{ "ER_GROUP_REPLICATION_COMMUNICATION_LAYER_SESSION_ERROR", 3096, "The START GROUP_REPLICATION command failed as there was an error when initializing the group communication layer." }, -{ "ER_GROUP_REPLICATION_COMMUNICATION_LAYER_JOIN_ERROR", 3097, "The START GROUP_REPLICATION command failed as there was an error when joining the communication group." }, -{ "ER_BEFORE_DML_VALIDATION_ERROR", 3098, "The table does not comply with the requirements by an external plugin." }, -{ "ER_PREVENTS_VARIABLE_WITHOUT_RBR", 3099, "Cannot change the value of variable %s without binary log format as ROW." }, -{ "ER_RUN_HOOK_ERROR", 3100, "Error on observer while running replication hook \'%s\'." }, -{ "ER_TRANSACTION_ROLLBACK_DURING_COMMIT", 3101, "Plugin instructed the server to rollback the current transaction." }, -{ "ER_GENERATED_COLUMN_FUNCTION_IS_NOT_ALLOWED", 3102, "Expression of generated column \'%s\' contains a disallowed function." }, -{ "ER_UNSUPPORTED_ALTER_INPLACE_ON_VIRTUAL_COLUMN", 3103, "INPLACE ADD or DROP of virtual columns cannot be combined with other ALTER TABLE actions" }, -{ "ER_WRONG_FK_OPTION_FOR_GENERATED_COLUMN", 3104, "Cannot define foreign key with %s clause on a generated column." }, -{ "ER_NON_DEFAULT_VALUE_FOR_GENERATED_COLUMN", 3105, "The value specified for generated column \'%s\' in table \'%s\' is not allowed." }, -{ "ER_UNSUPPORTED_ACTION_ON_GENERATED_COLUMN", 3106, "\'%s\' is not supported for generated columns." }, -{ "ER_GENERATED_COLUMN_NON_PRIOR", 3107, "Generated column can refer only to generated columns defined prior to it." }, -{ "ER_DEPENDENT_BY_GENERATED_COLUMN", 3108, "Column \'%s\' has a generated column dependency." }, -{ "ER_GENERATED_COLUMN_REF_AUTO_INC", 3109, "Generated column \'%s\' cannot refer to auto-increment column." }, -{ "ER_FEATURE_NOT_AVAILABLE", 3110, "The \'%-.64s\' feature is not available; you need to remove \'%-.64s\' or use MySQL built with \'%-.64s\'" }, -{ "ER_CANT_SET_GTID_MODE", 3111, "SET @@GLOBAL.GTID_MODE = %-.64s is not allowed because %-.384s." }, -{ "ER_CANT_USE_AUTO_POSITION_WITH_GTID_MODE_OFF", 3112, "The replication receiver thread%-.192s cannot start in AUTO_POSITION mode: this server uses @@GLOBAL.GTID_MODE = OFF." }, -{ "ER_CANT_REPLICATE_ANONYMOUS_WITH_AUTO_POSITION", 3113, "Cannot replicate anonymous transaction when AUTO_POSITION = 1, at file %.512s, position %lld." }, -{ "ER_CANT_REPLICATE_ANONYMOUS_WITH_GTID_MODE_ON", 3114, "Cannot replicate anonymous transaction when @@GLOBAL.GTID_MODE = ON, at file %.512s, position %lld." }, -{ "ER_CANT_REPLICATE_GTID_WITH_GTID_MODE_OFF", 3115, "Cannot replicate GTID-transaction when @@GLOBAL.GTID_MODE = OFF, at file %.512s, position %lld." }, -{ "ER_CANT_SET_ENFORCE_GTID_CONSISTENCY_ON_WITH_ONGOING_GTID_VIOLATING_TRANSACTIONS", 3116, "Cannot set ENFORCE_GTID_CONSISTENCY = ON because there are ongoing transactions that violate GTID consistency." }, -{ "ER_SET_ENFORCE_GTID_CONSISTENCY_WARN_WITH_ONGOING_GTID_VIOLATING_TRANSACTIONS", 3117, "There are ongoing transactions that violate GTID consistency." }, -{ "ER_ACCOUNT_HAS_BEEN_LOCKED", 3118, "Access denied for user \'%-.48s\'@\'%-.64s\'. Account is locked." }, -{ "ER_WRONG_TABLESPACE_NAME", 3119, "Incorrect tablespace name `%-.192s`" }, -{ "ER_TABLESPACE_IS_NOT_EMPTY", 3120, "Tablespace `%-.192s` is not empty." }, -{ "ER_WRONG_FILE_NAME", 3121, "Incorrect File Name \'%s\'." }, -{ "ER_BOOST_GEOMETRY_INCONSISTENT_TURNS_EXCEPTION", 3122, "Inconsistent intersection points." }, -{ "ER_WARN_OPTIMIZER_HINT_SYNTAX_ERROR", 3123, "Optimizer hint syntax error" }, -{ "ER_WARN_BAD_MAX_EXECUTION_TIME", 3124, "Unsupported MAX_EXECUTION_TIME" }, -{ "ER_WARN_UNSUPPORTED_MAX_EXECUTION_TIME", 3125, "MAX_EXECUTION_TIME hint is supported by top-level standalone SELECT statements only" }, -{ "ER_WARN_CONFLICTING_HINT", 3126, "Hint %s is ignored as conflicting/duplicated" }, -{ "ER_WARN_UNKNOWN_QB_NAME", 3127, "Query block name %s is not found for %s hint" }, -{ "ER_UNRESOLVED_HINT_NAME", 3128, "Unresolved name %s for %s hint" }, -{ "ER_WARN_ON_MODIFYING_GTID_EXECUTED_TABLE", 3129, "Please do not modify the %s table. This is a mysql internal system table to store GTIDs for committed transactions. Modifying it can lead to an inconsistent GTID state." }, -{ "ER_PLUGGABLE_PROTOCOL_COMMAND_NOT_SUPPORTED", 3130, "Command not supported by pluggable protocols" }, -{ "ER_LOCKING_SERVICE_WRONG_NAME", 3131, "Incorrect locking service lock name \'%-.192s\'." }, -{ "ER_LOCKING_SERVICE_DEADLOCK", 3132, "Deadlock found when trying to get locking service lock; try releasing locks and restarting lock acquisition." }, -{ "ER_LOCKING_SERVICE_TIMEOUT", 3133, "Service lock wait timeout exceeded." }, -{ "ER_GIS_MAX_POINTS_IN_GEOMETRY_OVERFLOWED", 3134, "Parameter %s exceeds the maximum number of points in a geometry (%lu) in function %s." }, -{ "ER_SQL_MODE_MERGED", 3135, "\'NO_ZERO_DATE\', \'NO_ZERO_IN_DATE\' and \'ERROR_FOR_DIVISION_BY_ZERO\' sql modes should be used with strict mode. They will be merged with strict mode in a future release." }, -{ "ER_VTOKEN_PLUGIN_TOKEN_MISMATCH", 3136, "Version token mismatch for %.*s. Correct value %.*s" }, -{ "ER_VTOKEN_PLUGIN_TOKEN_NOT_FOUND", 3137, "Version token %.*s not found." }, -{ "ER_CANT_SET_VARIABLE_WHEN_OWNING_GTID", 3138, "Variable %-.192s cannot be changed by a client that owns a GTID. The client owns %s. Ownership is released on COMMIT or ROLLBACK." }, -{ "ER_SLAVE_CHANNEL_OPERATION_NOT_ALLOWED", 3139, "%-.192s cannot be performed on channel \'%-.192s\'." }, -{ "ER_INVALID_JSON_TEXT", 3140, "Invalid JSON text: \"%s\" at position %u in value for column \'%-.200s\'." }, -{ "ER_INVALID_JSON_TEXT_IN_PARAM", 3141, "Invalid JSON text in argument %u to function %s: \"%s\" at position %u.%-.0s" }, -{ "ER_INVALID_JSON_BINARY_DATA", 3142, "The JSON binary value contains invalid data." }, -{ "ER_INVALID_JSON_PATH", 3143, "Invalid JSON path expression. The error is around character position %u.%-.200s" }, -{ "ER_INVALID_JSON_CHARSET", 3144, "Cannot create a JSON value from a string with CHARACTER SET \'%s\'." }, -{ "ER_INVALID_JSON_CHARSET_IN_FUNCTION", 3145, "Invalid JSON character data provided to function %s: \'%s\'; utf8 is required." }, -{ "ER_INVALID_TYPE_FOR_JSON", 3146, "Invalid data type for JSON data in argument %u to function %s; a JSON string or JSON type is required." }, -{ "ER_INVALID_CAST_TO_JSON", 3147, "Cannot CAST value to JSON." }, -{ "ER_INVALID_JSON_PATH_CHARSET", 3148, "A path expression must be encoded in the utf8 character set. The path expression \'%-.200s\' is encoded in character set \'%-.200s\'." }, -{ "ER_INVALID_JSON_PATH_WILDCARD", 3149, "In this situation, path expressions may not contain the * and ** tokens." }, -{ "ER_JSON_VALUE_TOO_BIG", 3150, "The JSON value is too big to be stored in a JSON column." }, -{ "ER_JSON_KEY_TOO_BIG", 3151, "The JSON object contains a key name that is too long." }, -{ "ER_JSON_USED_AS_KEY", 3152, "JSON column \'%-.192s\' cannot be used in key specification." }, -{ "ER_JSON_VACUOUS_PATH", 3153, "The path expression \'$\' is not allowed in this context." }, -{ "ER_JSON_BAD_ONE_OR_ALL_ARG", 3154, "The oneOrAll argument to %s may take these values: \'one\' or \'all\'." }, -{ "ER_NUMERIC_JSON_VALUE_OUT_OF_RANGE", 3155, "Out of range JSON value for CAST to %s%-.0s from column %s at row %ld" }, -{ "ER_INVALID_JSON_VALUE_FOR_CAST", 3156, "Invalid JSON value for CAST to %s%-.0s from column %s at row %ld" }, -{ "ER_JSON_DOCUMENT_TOO_DEEP", 3157, "The JSON document exceeds the maximum depth." }, -{ "ER_JSON_DOCUMENT_NULL_KEY", 3158, "JSON documents may not contain NULL member names." }, -{ "ER_SECURE_TRANSPORT_REQUIRED", 3159, "Connections using insecure transport are prohibited while --require_secure_transport=ON." }, -{ "ER_NO_SECURE_TRANSPORTS_CONFIGURED", 3160, "No secure transports (SSL or Shared Memory) are configured, unable to set --require_secure_transport=ON." }, -{ "ER_DISABLED_STORAGE_ENGINE", 3161, "Storage engine %s is disabled (Table creation is disallowed)." }, -{ "ER_USER_DOES_NOT_EXIST", 3162, "User %s does not exist." }, -{ "ER_USER_ALREADY_EXISTS", 3163, "User %s already exists." }, -{ "ER_AUDIT_API_ABORT", 3164, "Aborted by Audit API (\'%-.48s\';%d)." }, -{ "ER_INVALID_JSON_PATH_ARRAY_CELL", 3165, "A path expression is not a path to a cell in an array." }, -{ "ER_BUFPOOL_RESIZE_INPROGRESS", 3166, "Another buffer pool resize is already in progress." }, -{ "ER_FEATURE_DISABLED_SEE_DOC", 3167, "The \'%s\' feature is disabled; see the documentation for \'%s\'" }, -{ "ER_SERVER_ISNT_AVAILABLE", 3168, "Server isn\'t available" }, -{ "ER_SESSION_WAS_KILLED", 3169, "Session was killed" }, -{ "ER_CAPACITY_EXCEEDED", 3170, "Memory capacity of %llu bytes for \'%s\' exceeded. %s" }, -{ "ER_CAPACITY_EXCEEDED_IN_RANGE_OPTIMIZER", 3171, "Range optimization was not done for this query." }, -{ "ER_TABLE_NEEDS_UPG_PART", 3172, "Partitioning upgrade required. Please dump/reload to fix it or do: ALTER TABLE `%-.192s`.`%-.192s` UPGRADE PARTITIONING" }, -{ "ER_CANT_WAIT_FOR_EXECUTED_GTID_SET_WHILE_OWNING_A_GTID", 3173, "The client holds ownership of the GTID %s. Therefore, WAIT_FOR_EXECUTED_GTID_SET cannot wait for this GTID." }, -{ "ER_CANNOT_ADD_FOREIGN_BASE_COL_VIRTUAL", 3174, "Cannot add foreign key on the base column of indexed virtual column." }, -{ "ER_CANNOT_CREATE_VIRTUAL_INDEX_CONSTRAINT", 3175, "Cannot create index on virtual column whose base column has foreign constraint." }, -{ "ER_ERROR_ON_MODIFYING_GTID_EXECUTED_TABLE", 3176, "Please do not modify the %s table with an XA transaction. This is an internal system table used to store GTIDs for committed transactions. Although modifying it can lead to an inconsistent GTID state, if neccessary you can modify it with a non-XA transaction." }, -{ "ER_LOCK_REFUSED_BY_ENGINE", 3177, "Lock acquisition refused by storage engine." }, -{ "ER_UNSUPPORTED_ALTER_ONLINE_ON_VIRTUAL_COLUMN", 3178, "ADD COLUMN col...VIRTUAL, ADD INDEX(col)" }, -{ "ER_MASTER_KEY_ROTATION_NOT_SUPPORTED_BY_SE", 3179, "Master key rotation is not supported by storage engine." }, -{ "ER_MASTER_KEY_ROTATION_ERROR_BY_SE", 3180, "Encryption key rotation error reported by SE: %s" }, -{ "ER_MASTER_KEY_ROTATION_BINLOG_FAILED", 3181, "Write to binlog failed. However, master key rotation has been completed successfully." }, -{ "ER_MASTER_KEY_ROTATION_SE_UNAVAILABLE", 3182, "Storage engine is not available." }, -{ "ER_TABLESPACE_CANNOT_ENCRYPT", 3183, "This tablespace can\'t be encrypted." }, -{ "ER_INVALID_ENCRYPTION_OPTION", 3184, "Invalid encryption option." }, -{ "ER_CANNOT_FIND_KEY_IN_KEYRING", 3185, "Can\'t find master key from keyring, please check keyring plugin is loaded." }, -{ "ER_CAPACITY_EXCEEDED_IN_PARSER", 3186, "Parser bailed out for this query." }, -{ "ER_UNSUPPORTED_ALTER_ENCRYPTION_INPLACE", 3187, "Cannot alter encryption attribute by inplace algorithm." }, -{ "ER_KEYRING_UDF_KEYRING_SERVICE_ERROR", 3188, "Function \'%s\' failed because underlying keyring service returned an error. Please check if a keyring plugin is installed and that provided arguments are valid for the keyring you are using." }, -{ "ER_USER_COLUMN_OLD_LENGTH", 3189, "It seems that your db schema is old. The %s column is 77 characters long and should be 93 characters long. Please run mysql_upgrade." }, -{ "ER_CANT_RESET_MASTER", 3190, "RESET MASTER is not allowed because %-.384s." }, -{ "ER_GROUP_REPLICATION_MAX_GROUP_SIZE", 3191, "The START GROUP_REPLICATION command failed since the group already has 9 members." }, -{ "ER_CANNOT_ADD_FOREIGN_BASE_COL_STORED", 3192, "Cannot add foreign key on the base column of stored column. " }, -{ "ER_TABLE_REFERENCED", 3193, "Cannot complete the operation because table is referenced by another connection." }, diff --git a/vendor/mysql/include/mysqld_error.h b/vendor/mysql/include/mysqld_error.h index 99d0a1ec27..46b9522b43 100644 --- a/vendor/mysql/include/mysqld_error.h +++ b/vendor/mysql/include/mysqld_error.h @@ -1,13 +1,37 @@ +/* Copyright (c) 2000, 2024, Oracle and/or its affiliates. + + This program is free software; you can redistribute it and/or modify + it under the terms of the GNU General Public License, version 2.0, + as published by the Free Software Foundation. + + This program is designed to work with certain software (including + but not limited to OpenSSL) that is licensed under separate terms, + as designated in a particular file or component or in included license + documentation. The authors of MySQL hereby grant you an additional + permission to link the program and your derivative works with the + separately licensed software that they have either included with + the program or referenced in the documentation. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License, version 2.0, for more details. + + You should have received a copy of the GNU General Public License + along with this program; if not, write to the Free Software + Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA */ /* Autogenerated file, please don't edit */ #ifndef MYSQLD_ERROR_INCLUDED #define MYSQLD_ERROR_INCLUDED -static const int errmsg_section_start[] = { 1000, 3000 }; -static const int errmsg_section_size[] = { 886, 194 }; +static const int errmsg_section_start[] = { 1000, 3000, 3500, 6000, 10000, 15000 }; +static const int errmsg_section_size[] = { 888, 239, 667, 140, 4073, 141 }; + +static const int total_error_count = 6148; -#define ER_HASHCHK 1000 -#define ER_NISAMCHK 1001 +//#define OBSOLETE_ER_HASHCHK 1000 +//#define OBSOLETE_ER_NISAMCHK 1001 #define ER_NO 1002 #define ER_YES 1003 #define ER_CANT_CREATE_FILE 1004 @@ -15,27 +39,27 @@ static const int errmsg_section_size[] = { 886, 194 }; #define ER_CANT_CREATE_DB 1006 #define ER_DB_CREATE_EXISTS 1007 #define ER_DB_DROP_EXISTS 1008 -#define ER_DB_DROP_DELETE 1009 +//#define OBSOLETE_ER_DB_DROP_DELETE 1009 #define ER_DB_DROP_RMDIR 1010 -#define ER_CANT_DELETE_FILE 1011 +//#define OBSOLETE_ER_CANT_DELETE_FILE 1011 #define ER_CANT_FIND_SYSTEM_REC 1012 #define ER_CANT_GET_STAT 1013 -#define ER_CANT_GET_WD 1014 +//#define OBSOLETE_ER_CANT_GET_WD 1014 #define ER_CANT_LOCK 1015 #define ER_CANT_OPEN_FILE 1016 #define ER_FILE_NOT_FOUND 1017 #define ER_CANT_READ_DIR 1018 -#define ER_CANT_SET_WD 1019 +//#define OBSOLETE_ER_CANT_SET_WD 1019 #define ER_CHECKREAD 1020 -#define ER_DISK_FULL 1021 +//#define OBSOLETE_ER_DISK_FULL 1021 #define ER_DUP_KEY 1022 -#define ER_ERROR_ON_CLOSE 1023 +//#define OBSOLETE_ER_ERROR_ON_CLOSE 1023 #define ER_ERROR_ON_READ 1024 #define ER_ERROR_ON_RENAME 1025 #define ER_ERROR_ON_WRITE 1026 #define ER_FILE_USED 1027 -#define ER_FILSORT_ABORT 1028 -#define ER_FORM_NOT_FOUND 1029 +//#define OBSOLETE_ER_FILSORT_ABORT 1028 +//#define OBSOLETE_ER_FORM_NOT_FOUND 1029 #define ER_GET_ERRNO 1030 #define ER_ILLEGAL_HA 1031 #define ER_KEY_NOT_FOUND 1032 @@ -45,7 +69,7 @@ static const int errmsg_section_size[] = { 886, 194 }; #define ER_OPEN_AS_READONLY 1036 #define ER_OUTOFMEMORY 1037 #define ER_OUT_OF_SORTMEMORY 1038 -#define ER_UNEXPECTED_EOF 1039 +//#define OBSOLETE_ER_UNEXPECTED_EOF 1039 #define ER_CON_COUNT_ERROR 1040 #define ER_OUT_OF_RESOURCES 1041 #define ER_BAD_HOST_ERROR 1042 @@ -83,8 +107,8 @@ static const int errmsg_section_size[] = { 886, 194 }; #define ER_TOO_BIG_FIELDLENGTH 1074 #define ER_WRONG_AUTO_KEY 1075 #define ER_READY 1076 -#define ER_NORMAL_SHUTDOWN 1077 -#define ER_GOT_SIGNAL 1078 +//#define OBSOLETE_ER_NORMAL_SHUTDOWN 1077 +//#define OBSOLETE_ER_GOT_SIGNAL 1078 #define ER_SHUTDOWN_COMPLETE 1079 #define ER_FORCING_CLOSE 1080 #define ER_IPSOCK_ERROR 1081 @@ -126,7 +150,7 @@ static const int errmsg_section_size[] = { 886, 194 }; #define ER_TOO_MANY_FIELDS 1117 #define ER_TOO_BIG_ROWSIZE 1118 #define ER_STACK_OVERRUN 1119 -#define ER_WRONG_OUTER_JOIN 1120 +#define ER_WRONG_OUTER_JOIN_UNUSED 1120 #define ER_NULL_COLUMN_IN_INDEX 1121 #define ER_CANT_FIND_UDF 1122 #define ER_CANT_INITIALIZE_UDF 1123 @@ -156,8 +180,8 @@ static const int errmsg_section_size[] = { 886, 194 }; #define ER_NONEXISTING_TABLE_GRANT 1147 #define ER_NOT_ALLOWED_COMMAND 1148 #define ER_SYNTAX_ERROR 1149 -#define ER_UNUSED1 1150 -#define ER_UNUSED2 1151 +//#define OBSOLETE_ER_UNUSED1 1150 +//#define OBSOLETE_ER_UNUSED2 1151 #define ER_ABORTING_CONNECTION 1152 #define ER_NET_PACKET_TOO_LARGE 1153 #define ER_NET_READ_ERROR_FROM_PIPE 1154 @@ -171,7 +195,7 @@ static const int errmsg_section_size[] = { 886, 194 }; #define ER_TOO_LONG_STRING 1162 #define ER_TABLE_CANT_HANDLE_BLOB 1163 #define ER_TABLE_CANT_HANDLE_AUTO_INCREMENT 1164 -#define ER_UNUSED3 1165 +//#define OBSOLETE_ER_UNUSED3 1165 #define ER_WRONG_COLUMN_NAME 1166 #define ER_WRONG_KEY_COLUMN 1167 #define ER_WRONG_MRG_TABLE 1168 @@ -180,7 +204,7 @@ static const int errmsg_section_size[] = { 886, 194 }; #define ER_PRIMARY_CANT_HAVE_NULL 1171 #define ER_TOO_MANY_ROWS 1172 #define ER_REQUIRES_PRIMARY_KEY 1173 -#define ER_NO_RAID_COMPILED 1174 +//#define OBSOLETE_ER_NO_RAID_COMPILED 1174 #define ER_UPDATE_WITHOUT_KEY_IN_SAFE_MODE 1175 #define ER_KEY_DOES_NOT_EXITS 1176 #define ER_CHECK_NO_SUCH_TABLE 1177 @@ -189,14 +213,14 @@ static const int errmsg_section_size[] = { 886, 194 }; #define ER_ERROR_DURING_COMMIT 1180 #define ER_ERROR_DURING_ROLLBACK 1181 #define ER_ERROR_DURING_FLUSH_LOGS 1182 -#define ER_ERROR_DURING_CHECKPOINT 1183 +//#define OBSOLETE_ER_ERROR_DURING_CHECKPOINT 1183 #define ER_NEW_ABORTING_CONNECTION 1184 -#define ER_DUMP_NOT_IMPLEMENTED 1185 -#define ER_FLUSH_MASTER_BINLOG_CLOSED 1186 -#define ER_INDEX_REBUILD 1187 -#define ER_MASTER 1188 -#define ER_MASTER_NET_READ 1189 -#define ER_MASTER_NET_WRITE 1190 +//#define OBSOLETE_ER_DUMP_NOT_IMPLEMENTED 1185 +//#define OBSOLETE_ER_FLUSH_MASTER_BINLOG_CLOSED 1186 +//#define OBSOLETE_ER_INDEX_REBUILD 1187 +#define ER_SOURCE 1188 +#define ER_SOURCE_NET_READ 1189 +#define ER_SOURCE_NET_WRITE 1190 #define ER_FT_MATCHING_KEY_NOT_FOUND 1191 #define ER_LOCK_OR_ACTIVE_TRANSACTION 1192 #define ER_UNKNOWN_SYSTEM_VARIABLE 1193 @@ -204,28 +228,28 @@ static const int errmsg_section_size[] = { 886, 194 }; #define ER_CRASHED_ON_REPAIR 1195 #define ER_WARNING_NOT_COMPLETE_ROLLBACK 1196 #define ER_TRANS_CACHE_FULL 1197 -#define ER_SLAVE_MUST_STOP 1198 -#define ER_SLAVE_NOT_RUNNING 1199 -#define ER_BAD_SLAVE 1200 -#define ER_MASTER_INFO 1201 -#define ER_SLAVE_THREAD 1202 +//#define OBSOLETE_ER_SLAVE_MUST_STOP 1198 +#define ER_REPLICA_NOT_RUNNING 1199 +#define ER_BAD_REPLICA 1200 +#define ER_CONNECTION_METADATA 1201 +#define ER_REPLICA_THREAD 1202 #define ER_TOO_MANY_USER_CONNECTIONS 1203 #define ER_SET_CONSTANTS_ONLY 1204 #define ER_LOCK_WAIT_TIMEOUT 1205 #define ER_LOCK_TABLE_FULL 1206 #define ER_READ_ONLY_TRANSACTION 1207 -#define ER_DROP_DB_WITH_READ_LOCK 1208 -#define ER_CREATE_DB_WITH_READ_LOCK 1209 +//#define OBSOLETE_ER_DROP_DB_WITH_READ_LOCK 1208 +//#define OBSOLETE_ER_CREATE_DB_WITH_READ_LOCK 1209 #define ER_WRONG_ARGUMENTS 1210 #define ER_NO_PERMISSION_TO_CREATE_USER 1211 -#define ER_UNION_TABLES_IN_DIFFERENT_DIR 1212 +//#define OBSOLETE_ER_UNION_TABLES_IN_DIFFERENT_DIR 1212 #define ER_LOCK_DEADLOCK 1213 #define ER_TABLE_CANT_HANDLE_FT 1214 #define ER_CANNOT_ADD_FOREIGN 1215 #define ER_NO_REFERENCED_ROW 1216 #define ER_ROW_IS_REFERENCED 1217 -#define ER_CONNECT_TO_MASTER 1218 -#define ER_QUERY_ON_MASTER 1219 +#define ER_CONNECT_TO_SOURCE 1218 +//#define OBSOLETE_ER_QUERY_ON_MASTER 1219 #define ER_ERROR_WHEN_EXECUTING_COMMAND 1220 #define ER_WRONG_USAGE 1221 #define ER_WRONG_NUMBER_OF_COLUMNS_IN_SELECT 1222 @@ -242,8 +266,8 @@ static const int errmsg_section_size[] = { 886, 194 }; #define ER_VAR_CANT_BE_READ 1233 #define ER_CANT_USE_OPTION_HERE 1234 #define ER_NOT_SUPPORTED_YET 1235 -#define ER_MASTER_FATAL_ERROR_READING_BINLOG 1236 -#define ER_SLAVE_IGNORED_TABLE 1237 +#define ER_SOURCE_FATAL_ERROR_READING_BINLOG 1236 +#define ER_REPLICA_IGNORED_TABLE 1237 #define ER_INCORRECT_GLOBAL_LOCAL_VAR 1238 #define ER_WRONG_FK_DEF 1239 #define ER_KEY_REF_DO_NOT_MATCH_TABLE_REF 1240 @@ -251,7 +275,7 @@ static const int errmsg_section_size[] = { 886, 194 }; #define ER_SUBQUERY_NO_1_ROW 1242 #define ER_UNKNOWN_STMT_HANDLER 1243 #define ER_CORRUPT_HELP_DB 1244 -#define ER_CYCLIC_REFERENCE 1245 +//#define OBSOLETE_ER_CYCLIC_REFERENCE 1245 #define ER_AUTO_CONVERT 1246 #define ER_ILLEGAL_REFERENCE 1247 #define ER_DERIVED_MUST_HAVE_ALIAS 1248 @@ -260,8 +284,8 @@ static const int errmsg_section_size[] = { 886, 194 }; #define ER_NOT_SUPPORTED_AUTH_MODE 1251 #define ER_SPATIAL_CANT_HAVE_NULL 1252 #define ER_COLLATION_CHARSET_MISMATCH 1253 -#define ER_SLAVE_WAS_RUNNING 1254 -#define ER_SLAVE_WAS_NOT_RUNNING 1255 +//#define OBSOLETE_ER_SLAVE_WAS_RUNNING 1254 +//#define OBSOLETE_ER_SLAVE_WAS_NOT_RUNNING 1255 #define ER_TOO_BIG_FOR_UNCOMPRESS 1256 #define ER_ZLIB_Z_MEM_ERROR 1257 #define ER_ZLIB_Z_BUF_ERROR 1258 @@ -274,21 +298,21 @@ static const int errmsg_section_size[] = { 886, 194 }; #define WARN_DATA_TRUNCATED 1265 #define ER_WARN_USING_OTHER_HANDLER 1266 #define ER_CANT_AGGREGATE_2COLLATIONS 1267 -#define ER_DROP_USER 1268 +//#define OBSOLETE_ER_DROP_USER 1268 #define ER_REVOKE_GRANTS 1269 #define ER_CANT_AGGREGATE_3COLLATIONS 1270 #define ER_CANT_AGGREGATE_NCOLLATIONS 1271 #define ER_VARIABLE_IS_NOT_STRUCT 1272 #define ER_UNKNOWN_COLLATION 1273 -#define ER_SLAVE_IGNORED_SSL_PARAMS 1274 -#define ER_SERVER_IS_IN_SECURE_AUTH_MODE 1275 +#define ER_REPLICA_IGNORED_SSL_PARAMS 1274 +//#define OBSOLETE_ER_SERVER_IS_IN_SECURE_AUTH_MODE 1275 #define ER_WARN_FIELD_RESOLVED 1276 -#define ER_BAD_SLAVE_UNTIL_COND 1277 -#define ER_MISSING_SKIP_SLAVE 1278 +#define ER_BAD_REPLICA_UNTIL_COND 1277 +#define ER_MISSING_SKIP_REPLICA 1278 #define ER_UNTIL_COND_IGNORED 1279 #define ER_WRONG_NAME_FOR_INDEX 1280 #define ER_WRONG_NAME_FOR_CATALOG 1281 -#define ER_WARN_QC_RESIZE 1282 +//#define OBSOLETE_ER_WARN_QC_RESIZE 1282 #define ER_BAD_FT_COLUMN 1283 #define ER_UNKNOWN_KEY_CACHE 1284 #define ER_WARN_HOSTNAME_WONT_WORK 1285 @@ -299,7 +323,7 @@ static const int errmsg_section_size[] = { 886, 194 }; #define ER_OPTION_PREVENTS_STATEMENT 1290 #define ER_DUPLICATED_VALUE_IN_TYPE 1291 #define ER_TRUNCATED_WRONG_VALUE 1292 -#define ER_TOO_MUCH_AUTO_TIMESTAMP_COLS 1293 +//#define OBSOLETE_ER_TOO_MUCH_AUTO_TIMESTAMP_COLS 1293 #define ER_INVALID_ON_UPDATE 1294 #define ER_UNSUPPORTED_PS 1295 #define ER_GET_ERRMSG 1296 @@ -352,10 +376,10 @@ static const int errmsg_section_size[] = { 886, 194 }; #define ER_FPARSER_ERROR_IN_PARAMETER 1343 #define ER_FPARSER_EOF_IN_UNKNOWN_PARAMETER 1344 #define ER_VIEW_NO_EXPLAIN 1345 -#define ER_FRM_UNKNOWN_TYPE 1346 +//#define OBSOLETE_ER_FRM_UNKNOWN_TYPE 1346 #define ER_WRONG_OBJECT 1347 #define ER_NONUPDATEABLE_COLUMN 1348 -#define ER_VIEW_SELECT_DERIVED_UNUSED 1349 +//#define OBSOLETE_ER_VIEW_SELECT_DERIVED_UNUSED 1349 #define ER_VIEW_SELECT_CLAUSE 1350 #define ER_VIEW_SELECT_VARIABLE 1351 #define ER_VIEW_SELECT_TMPTABLE 1352 @@ -364,7 +388,7 @@ static const int errmsg_section_size[] = { 886, 194 }; #define ER_WARN_VIEW_WITHOUT_KEY 1355 #define ER_VIEW_INVALID 1356 #define ER_SP_NO_DROP_SP 1357 -#define ER_SP_GOTO_IN_HNDLR 1358 +//#define OBSOLETE_ER_SP_GOTO_IN_HNDLR 1358 #define ER_TRG_ALREADY_EXISTS 1359 #define ER_TRG_DOES_NOT_EXIST 1360 #define ER_TRG_ON_VIEW_OR_TEMP_TABLE 1361 @@ -378,7 +402,7 @@ static const int errmsg_section_size[] = { 886, 194 }; #define ER_VIEW_CHECK_FAILED 1369 #define ER_PROCACCESS_DENIED_ERROR 1370 #define ER_RELAY_LOG_FAIL 1371 -#define ER_PASSWD_LENGTH 1372 +//#define OBSOLETE_ER_PASSWD_LENGTH 1372 #define ER_UNKNOWN_TARGET_BINLOG 1373 #define ER_IO_ERR_LOG_INDEX_READ 1374 #define ER_BINLOG_PURGE_PROHIBITED 1375 @@ -389,13 +413,13 @@ static const int errmsg_section_size[] = { 886, 194 }; #define ER_RELAY_LOG_INIT 1380 #define ER_NO_BINARY_LOGGING 1381 #define ER_RESERVED_SYNTAX 1382 -#define ER_WSAS_FAILED 1383 -#define ER_DIFF_GROUPS_PROC 1384 -#define ER_NO_GROUP_FOR_PROC 1385 -#define ER_ORDER_WITH_PROC 1386 -#define ER_LOGGING_PROHIBIT_CHANGING_OF 1387 -#define ER_NO_FILE_MAPPING 1388 -#define ER_WRONG_MAGIC 1389 +//#define OBSOLETE_ER_WSAS_FAILED 1383 +//#define OBSOLETE_ER_DIFF_GROUPS_PROC 1384 +//#define OBSOLETE_ER_NO_GROUP_FOR_PROC 1385 +//#define OBSOLETE_ER_ORDER_WITH_PROC 1386 +//#define OBSOLETE_ER_LOGGING_PROHIBIT_CHANGING_OF 1387 +//#define OBSOLETE_ER_NO_FILE_MAPPING 1388 +//#define OBSOLETE_ER_WRONG_MAGIC 1389 #define ER_PS_MANY_PARAM 1390 #define ER_KEY_PART_0 1391 #define ER_VIEW_CHECKSUM 1392 @@ -423,10 +447,10 @@ static const int errmsg_section_size[] = { 886, 194 }; #define ER_SP_NOT_VAR_ARG 1414 #define ER_SP_NO_RETSET 1415 #define ER_CANT_CREATE_GEOMETRY_OBJECT 1416 -#define ER_FAILED_ROUTINE_BREAK_BINLOG 1417 +//#define OBSOLETE_ER_FAILED_ROUTINE_BREAK_BINLOG 1417 #define ER_BINLOG_UNSAFE_ROUTINE 1418 #define ER_BINLOG_CREATE_ROUTINE_NEED_SUPER 1419 -#define ER_EXEC_STMT_WITH_OPEN_CURSOR 1420 +//#define OBSOLETE_ER_EXEC_STMT_WITH_OPEN_CURSOR 1420 #define ER_STMT_HAS_NO_OPEN_CURSOR 1421 #define ER_COMMIT_NOT_ALLOWED_IN_SF_OR_TRG 1422 #define ER_NO_DEFAULT_FOR_VIEW_FIELD 1423 @@ -440,7 +464,7 @@ static const int errmsg_section_size[] = { 886, 194 }; #define ER_FOREIGN_DATA_SOURCE_DOESNT_EXIST 1431 #define ER_FOREIGN_DATA_STRING_INVALID_CANT_CREATE 1432 #define ER_FOREIGN_DATA_STRING_INVALID 1433 -#define ER_CANT_CREATE_FEDERATED_TABLE 1434 +//#define OBSOLETE_ER_CANT_CREATE_FEDERATED_TABLE 1434 #define ER_TRG_IN_WRONG_SCHEMA 1435 #define ER_STACK_OVERRUN_NEED_MORE 1436 #define ER_TOO_LONG_BODY 1437 @@ -452,7 +476,7 @@ static const int errmsg_section_size[] = { 886, 194 }; #define ER_VIEW_PREVENT_UPDATE 1443 #define ER_PS_NO_RECURSION 1444 #define ER_SP_CANT_SET_AUTOCOMMIT 1445 -#define ER_MALFORMED_DEFINER 1446 +//#define OBSOLETE_ER_MALFORMED_DEFINER 1446 #define ER_VIEW_FRM_NO_USER 1447 #define ER_VIEW_OTHER_USER 1448 #define ER_NO_SUCH_USER 1449 @@ -463,7 +487,7 @@ static const int errmsg_section_size[] = { 886, 194 }; #define ER_TRG_NO_DEFINER 1454 #define ER_OLD_FILE_FORMAT 1455 #define ER_SP_RECURSION_LIMIT 1456 -#define ER_SP_PROC_TABLE_CORRUPT 1457 +//#define OBSOLETE_ER_SP_PROC_TABLE_CORRUPT 1457 #define ER_SP_WRONG_NAME 1458 #define ER_TABLE_NEEDS_UPGRADE 1459 #define ER_SP_NO_AGGREGATE 1460 @@ -488,14 +512,14 @@ static const int errmsg_section_size[] = { 886, 194 }; #define ER_PARTITION_REQUIRES_VALUES_ERROR 1479 #define ER_PARTITION_WRONG_VALUES_ERROR 1480 #define ER_PARTITION_MAXVALUE_ERROR 1481 -#define ER_PARTITION_SUBPARTITION_ERROR 1482 -#define ER_PARTITION_SUBPART_MIX_ERROR 1483 +//#define OBSOLETE_ER_PARTITION_SUBPARTITION_ERROR 1482 +//#define OBSOLETE_ER_PARTITION_SUBPART_MIX_ERROR 1483 #define ER_PARTITION_WRONG_NO_PART_ERROR 1484 #define ER_PARTITION_WRONG_NO_SUBPART_ERROR 1485 #define ER_WRONG_EXPR_IN_PARTITION_FUNC_ERROR 1486 -#define ER_NO_CONST_EXPR_IN_RANGE_OR_LIST_ERROR 1487 +//#define OBSOLETE_ER_NO_CONST_EXPR_IN_RANGE_OR_LIST_ERROR 1487 #define ER_FIELD_NOT_FOUND_PART_ERROR 1488 -#define ER_LIST_OF_FIELDS_ONLY_IN_HASH_ERROR 1489 +//#define OBSOLETE_ER_LIST_OF_FIELDS_ONLY_IN_HASH_ERROR 1489 #define ER_INCONSISTENT_PARTITION_INFO_ERROR 1490 #define ER_PARTITION_FUNC_NOT_ALLOWED_ERROR 1491 #define ER_PARTITIONS_MUST_BE_DEFINED_ERROR 1492 @@ -528,7 +552,7 @@ static const int errmsg_section_size[] = { 886, 194 }; #define ER_CONSECUTIVE_REORG_PARTITIONS 1519 #define ER_REORG_OUTSIDE_RANGE 1520 #define ER_PARTITION_FUNCTION_FAILURE 1521 -#define ER_PART_STATE_ERROR 1522 +//#define OBSOLETE_ER_PART_STATE_ERROR 1522 #define ER_LIMITED_PART_RANGE 1523 #define ER_PLUGIN_IS_NOT_LOADED 1524 #define ER_WRONG_VALUE 1525 @@ -541,49 +565,49 @@ static const int errmsg_section_size[] = { 886, 194 }; #define ER_SIZE_OVERFLOW_ERROR 1532 #define ER_ALTER_FILEGROUP_FAILED 1533 #define ER_BINLOG_ROW_LOGGING_FAILED 1534 -#define ER_BINLOG_ROW_WRONG_TABLE_DEF 1535 -#define ER_BINLOG_ROW_RBR_TO_SBR 1536 +//#define OBSOLETE_ER_BINLOG_ROW_WRONG_TABLE_DEF 1535 +//#define OBSOLETE_ER_BINLOG_ROW_RBR_TO_SBR 1536 #define ER_EVENT_ALREADY_EXISTS 1537 -#define ER_EVENT_STORE_FAILED 1538 +//#define OBSOLETE_ER_EVENT_STORE_FAILED 1538 #define ER_EVENT_DOES_NOT_EXIST 1539 -#define ER_EVENT_CANT_ALTER 1540 -#define ER_EVENT_DROP_FAILED 1541 +//#define OBSOLETE_ER_EVENT_CANT_ALTER 1540 +//#define OBSOLETE_ER_EVENT_DROP_FAILED 1541 #define ER_EVENT_INTERVAL_NOT_POSITIVE_OR_TOO_BIG 1542 #define ER_EVENT_ENDS_BEFORE_STARTS 1543 #define ER_EVENT_EXEC_TIME_IN_THE_PAST 1544 -#define ER_EVENT_OPEN_TABLE_FAILED 1545 -#define ER_EVENT_NEITHER_M_EXPR_NOR_M_AT 1546 -#define ER_OBSOLETE_COL_COUNT_DOESNT_MATCH_CORRUPTED 1547 -#define ER_OBSOLETE_CANNOT_LOAD_FROM_TABLE 1548 -#define ER_EVENT_CANNOT_DELETE 1549 -#define ER_EVENT_COMPILE_ERROR 1550 +//#define OBSOLETE_ER_EVENT_OPEN_TABLE_FAILED 1545 +//#define OBSOLETE_ER_EVENT_NEITHER_M_EXPR_NOR_M_AT 1546 +//#define OBSOLETE_ER_COL_COUNT_DOESNT_MATCH_CORRUPTED 1547 +//#define OBSOLETE_ER_CANNOT_LOAD_FROM_TABLE 1548 +//#define OBSOLETE_ER_EVENT_CANNOT_DELETE 1549 +//#define OBSOLETE_ER_EVENT_COMPILE_ERROR 1550 #define ER_EVENT_SAME_NAME 1551 -#define ER_EVENT_DATA_TOO_LONG 1552 +//#define OBSOLETE_ER_EVENT_DATA_TOO_LONG 1552 #define ER_DROP_INDEX_FK 1553 #define ER_WARN_DEPRECATED_SYNTAX_WITH_VER 1554 -#define ER_CANT_WRITE_LOCK_LOG_TABLE 1555 +//#define OBSOLETE_ER_CANT_WRITE_LOCK_LOG_TABLE 1555 #define ER_CANT_LOCK_LOG_TABLE 1556 #define ER_FOREIGN_DUPLICATE_KEY_OLD_UNUSED 1557 #define ER_COL_COUNT_DOESNT_MATCH_PLEASE_UPDATE 1558 -#define ER_TEMP_TABLE_PREVENTS_SWITCH_OUT_OF_RBR 1559 +//#define OBSOLETE_ER_TEMP_TABLE_PREVENTS_SWITCH_OUT_OF_RBR 1559 #define ER_STORED_FUNCTION_PREVENTS_SWITCH_BINLOG_FORMAT 1560 -#define ER_NDB_CANT_SWITCH_BINLOG_FORMAT 1561 +//#define OBSOLETE_ER_NDB_CANT_SWITCH_BINLOG_FORMAT 1561 #define ER_PARTITION_NO_TEMPORARY 1562 #define ER_PARTITION_CONST_DOMAIN_ERROR 1563 #define ER_PARTITION_FUNCTION_IS_NOT_ALLOWED 1564 -#define ER_DDL_LOG_ERROR 1565 +//#define OBSOLETE_ER_DDL_LOG_ERROR_UNUSED 1565 #define ER_NULL_IN_VALUES_LESS_THAN 1566 #define ER_WRONG_PARTITION_NAME 1567 #define ER_CANT_CHANGE_TX_CHARACTERISTICS 1568 #define ER_DUP_ENTRY_AUTOINCREMENT_CASE 1569 -#define ER_EVENT_MODIFY_QUEUE_ERROR 1570 +//#define OBSOLETE_ER_EVENT_MODIFY_QUEUE_ERROR 1570 #define ER_EVENT_SET_VAR_ERROR 1571 #define ER_PARTITION_MERGE_ERROR 1572 -#define ER_CANT_ACTIVATE_LOG 1573 -#define ER_RBR_NOT_AVAILABLE 1574 +//#define OBSOLETE_ER_CANT_ACTIVATE_LOG 1573 +//#define OBSOLETE_ER_RBR_NOT_AVAILABLE 1574 #define ER_BASE64_DECODE_ERROR 1575 #define ER_EVENT_RECURSION_FORBIDDEN 1576 -#define ER_EVENTS_DB_ERROR 1577 +//#define OBSOLETE_ER_EVENTS_DB_ERROR 1577 #define ER_ONLY_INTEGERS_ALLOWED 1578 #define ER_UNSUPORTED_LOG_ENGINE 1579 #define ER_BAD_LOG_STATEMENT 1580 @@ -596,41 +620,41 @@ static const int errmsg_section_size[] = { 886, 194 }; #define ER_BINLOG_PURGE_EMFILE 1587 #define ER_EVENT_CANNOT_CREATE_IN_THE_PAST 1588 #define ER_EVENT_CANNOT_ALTER_IN_THE_PAST 1589 -#define ER_SLAVE_INCIDENT 1590 +//#define OBSOLETE_ER_SLAVE_INCIDENT 1590 #define ER_NO_PARTITION_FOR_GIVEN_VALUE_SILENT 1591 #define ER_BINLOG_UNSAFE_STATEMENT 1592 -#define ER_SLAVE_FATAL_ERROR 1593 -#define ER_SLAVE_RELAY_LOG_READ_FAILURE 1594 -#define ER_SLAVE_RELAY_LOG_WRITE_FAILURE 1595 -#define ER_SLAVE_CREATE_EVENT_FAILURE 1596 -#define ER_SLAVE_MASTER_COM_FAILURE 1597 +#define ER_BINLOG_FATAL_ERROR 1593 +//#define OBSOLETE_ER_SLAVE_RELAY_LOG_READ_FAILURE 1594 +//#define OBSOLETE_ER_SLAVE_RELAY_LOG_WRITE_FAILURE 1595 +//#define OBSOLETE_ER_SLAVE_CREATE_EVENT_FAILURE 1596 +//#define OBSOLETE_ER_SLAVE_MASTER_COM_FAILURE 1597 #define ER_BINLOG_LOGGING_IMPOSSIBLE 1598 #define ER_VIEW_NO_CREATION_CTX 1599 #define ER_VIEW_INVALID_CREATION_CTX 1600 -#define ER_SR_INVALID_CREATION_CTX 1601 +//#define OBSOLETE_ER_SR_INVALID_CREATION_CTX 1601 #define ER_TRG_CORRUPTED_FILE 1602 #define ER_TRG_NO_CREATION_CTX 1603 #define ER_TRG_INVALID_CREATION_CTX 1604 #define ER_EVENT_INVALID_CREATION_CTX 1605 #define ER_TRG_CANT_OPEN_TABLE 1606 -#define ER_CANT_CREATE_SROUTINE 1607 -#define ER_NEVER_USED 1608 +//#define OBSOLETE_ER_CANT_CREATE_SROUTINE 1607 +//#define OBSOLETE_ER_NEVER_USED 1608 #define ER_NO_FORMAT_DESCRIPTION_EVENT_BEFORE_BINLOG_STATEMENT 1609 -#define ER_SLAVE_CORRUPT_EVENT 1610 -#define ER_LOAD_DATA_INVALID_COLUMN_UNUSED 1611 +#define ER_REPLICA_CORRUPT_EVENT 1610 +//#define OBSOLETE_ER_LOAD_DATA_INVALID_COLUMN_UNUSED 1611 #define ER_LOG_PURGE_NO_FILE 1612 #define ER_XA_RBTIMEOUT 1613 #define ER_XA_RBDEADLOCK 1614 #define ER_NEED_REPREPARE 1615 -#define ER_DELAYED_NOT_SUPPORTED 1616 -#define WARN_NO_MASTER_INFO 1617 +//#define OBSOLETE_ER_DELAYED_NOT_SUPPORTED 1616 +#define WARN_NO_CONNECTION_METADATA 1617 #define WARN_OPTION_IGNORED 1618 #define ER_PLUGIN_DELETE_BUILTIN 1619 #define WARN_PLUGIN_BUSY 1620 #define ER_VARIABLE_IS_READONLY 1621 #define ER_WARN_ENGINE_TRANSACTION_ROLLBACK 1622 -#define ER_SLAVE_HEARTBEAT_FAILURE 1623 -#define ER_SLAVE_HEARTBEAT_VALUE_OUT_OF_RANGE 1624 +//#define OBSOLETE_ER_SLAVE_HEARTBEAT_FAILURE 1623 +#define ER_REPLICA_HEARTBEAT_VALUE_OUT_OF_RANGE 1624 #define ER_NDB_REPLICATION_SCHEMA_ERROR 1625 #define ER_CONFLICT_FN_PARSE_ERROR 1626 #define ER_EXCEPTIONS_WRITE_ERROR 1627 @@ -656,8 +680,8 @@ static const int errmsg_section_size[] = { 886, 194 }; #define WARN_COND_ITEM_TRUNCATED 1647 #define ER_COND_ITEM_TOO_LONG 1648 #define ER_UNKNOWN_LOCALE 1649 -#define ER_SLAVE_IGNORE_SERVER_IDS 1650 -#define ER_QUERY_CACHE_DISABLED 1651 +#define ER_REPLICA_IGNORE_SERVER_IDS 1650 +//#define OBSOLETE_ER_QUERY_CACHE_DISABLED 1651 #define ER_SAME_NAME_PARTITION_FIELD 1652 #define ER_PARTITION_COLUMN_LIST_ERROR 1653 #define ER_WRONG_TYPE_COLUMN_VALUE_ERROR 1654 @@ -675,7 +699,7 @@ static const int errmsg_section_size[] = { 886, 194 }; #define ER_BINLOG_ROW_INJECTION_AND_STMT_MODE 1666 #define ER_BINLOG_MULTIPLE_ENGINES_AND_SELF_LOGGING_ENGINE 1667 #define ER_BINLOG_UNSAFE_LIMIT 1668 -#define ER_UNUSED4 1669 +//#define OBSOLETE_ER_UNUSED4 1669 #define ER_BINLOG_UNSAFE_SYSTEM_TABLE 1670 #define ER_BINLOG_UNSAFE_AUTOINC_COLUMNS 1671 #define ER_BINLOG_UNSAFE_UDF 1672 @@ -683,8 +707,8 @@ static const int errmsg_section_size[] = { 886, 194 }; #define ER_BINLOG_UNSAFE_SYSTEM_FUNCTION 1674 #define ER_BINLOG_UNSAFE_NONTRANS_AFTER_TRANS 1675 #define ER_MESSAGE_AND_STATEMENT 1676 -#define ER_SLAVE_CONVERSION_FAILED 1677 -#define ER_SLAVE_CANT_CREATE_CONVERSION 1678 +//#define OBSOLETE_ER_SLAVE_CONVERSION_FAILED 1677 +#define ER_REPLICA_CANT_CREATE_CONVERSION 1678 #define ER_INSIDE_TRANSACTION_PREVENTS_SWITCH_BINLOG_FORMAT 1679 #define ER_PATH_LENGTH 1680 #define ER_WARN_DEPRECATED_SYNTAX_NO_REPLACEMENT 1681 @@ -697,7 +721,7 @@ static const int errmsg_section_size[] = { 886, 194 }; #define ER_TOO_LONG_INDEX_COMMENT 1688 #define ER_LOCK_ABORTED 1689 #define ER_DATA_OUT_OF_RANGE 1690 -#define ER_WRONG_SPVAR_TYPE_IN_LIMIT 1691 +//#define OBSOLETE_ER_WRONG_SPVAR_TYPE_IN_LIMIT 1691 #define ER_BINLOG_UNSAFE_MULTIPLE_ENGINES_AND_SELF_LOGGING_ENGINE 1692 #define ER_BINLOG_UNSAFE_MIXED_STATEMENT 1693 #define ER_INSIDE_TRANSACTION_PREVENTS_SWITCH_SQL_LOG_BIN 1694 @@ -705,12 +729,12 @@ static const int errmsg_section_size[] = { 886, 194 }; #define ER_FAILED_READ_FROM_PAR_FILE 1696 #define ER_VALUES_IS_NOT_INT_TYPE_ERROR 1697 #define ER_ACCESS_DENIED_NO_PASSWORD_ERROR 1698 -#define ER_SET_PASSWORD_AUTH_PLUGIN 1699 -#define ER_GRANT_PLUGIN_USER_EXISTS 1700 +//#define OBSOLETE_ER_SET_PASSWORD_AUTH_PLUGIN 1699 +//#define OBSOLETE_ER_GRANT_PLUGIN_USER_EXISTS 1700 #define ER_TRUNCATE_ILLEGAL_FK 1701 #define ER_PLUGIN_IS_PERMANENT 1702 -#define ER_SLAVE_HEARTBEAT_VALUE_OUT_OF_RANGE_MIN 1703 -#define ER_SLAVE_HEARTBEAT_VALUE_OUT_OF_RANGE_MAX 1704 +#define ER_REPLICA_HEARTBEAT_VALUE_OUT_OF_RANGE_MIN 1703 +#define ER_REPLICA_HEARTBEAT_VALUE_OUT_OF_RANGE_MAX 1704 #define ER_STMT_CACHE_FULL 1705 #define ER_MULTI_UPDATE_KEY_CONFLICT 1706 #define ER_TABLE_NEEDS_REBUILD 1707 @@ -735,7 +759,7 @@ static const int errmsg_section_size[] = { 886, 194 }; #define ER_UNSUPPORTED_ENGINE 1726 #define ER_BINLOG_UNSAFE_AUTOINC_NOT_FIRST 1727 #define ER_CANNOT_LOAD_FROM_TABLE_V2 1728 -#define ER_MASTER_DELAY_VALUE_OUT_OF_RANGE 1729 +#define ER_SOURCE_DELAY_VALUE_OUT_OF_RANGE 1729 #define ER_ONLY_FD_AND_RBR_EVENTS_ALLOWED_IN_BINLOG_STATEMENT 1730 #define ER_PARTITION_EXCHANGE_DIFFERENT_OPTION 1731 #define ER_PARTITION_EXCHANGE_PART_TABLE 1732 @@ -747,60 +771,60 @@ static const int errmsg_section_size[] = { 886, 194 }; #define ER_BINLOG_CACHE_SIZE_GREATER_THAN_MAX 1738 #define ER_WARN_INDEX_NOT_APPLICABLE 1739 #define ER_PARTITION_EXCHANGE_FOREIGN_KEY 1740 -#define ER_NO_SUCH_KEY_VALUE 1741 +//#define OBSOLETE_ER_NO_SUCH_KEY_VALUE 1741 #define ER_RPL_INFO_DATA_TOO_LONG 1742 -#define ER_NETWORK_READ_EVENT_CHECKSUM_FAILURE 1743 -#define ER_BINLOG_READ_EVENT_CHECKSUM_FAILURE 1744 +//#define OBSOLETE_ER_NETWORK_READ_EVENT_CHECKSUM_FAILURE 1743 +//#define OBSOLETE_ER_BINLOG_READ_EVENT_CHECKSUM_FAILURE 1744 #define ER_BINLOG_STMT_CACHE_SIZE_GREATER_THAN_MAX 1745 #define ER_CANT_UPDATE_TABLE_IN_CREATE_TABLE_SELECT 1746 #define ER_PARTITION_CLAUSE_ON_NONPARTITIONED 1747 #define ER_ROW_DOES_NOT_MATCH_GIVEN_PARTITION_SET 1748 -#define ER_NO_SUCH_PARTITION__UNUSED 1749 +//#define OBSOLETE_ER_NO_SUCH_PARTITION__UNUSED 1749 #define ER_CHANGE_RPL_INFO_REPOSITORY_FAILURE 1750 #define ER_WARNING_NOT_COMPLETE_ROLLBACK_WITH_CREATED_TEMP_TABLE 1751 #define ER_WARNING_NOT_COMPLETE_ROLLBACK_WITH_DROPPED_TEMP_TABLE 1752 -#define ER_MTS_FEATURE_IS_NOT_SUPPORTED 1753 -#define ER_MTS_UPDATED_DBS_GREATER_MAX 1754 -#define ER_MTS_CANT_PARALLEL 1755 -#define ER_MTS_INCONSISTENT_DATA 1756 +#define ER_MTA_FEATURE_IS_NOT_SUPPORTED 1753 +#define ER_MTA_UPDATED_DBS_GREATER_MAX 1754 +#define ER_MTA_CANT_PARALLEL 1755 +#define ER_MTA_INCONSISTENT_DATA 1756 #define ER_FULLTEXT_NOT_SUPPORTED_WITH_PARTITIONING 1757 #define ER_DA_INVALID_CONDITION_NUMBER 1758 #define ER_INSECURE_PLAIN_TEXT 1759 -#define ER_INSECURE_CHANGE_MASTER 1760 +#define ER_INSECURE_CHANGE_SOURCE 1760 #define ER_FOREIGN_DUPLICATE_KEY_WITH_CHILD_INFO 1761 #define ER_FOREIGN_DUPLICATE_KEY_WITHOUT_CHILD_INFO 1762 -#define ER_SQLTHREAD_WITH_SECURE_SLAVE 1763 +#define ER_SQLTHREAD_WITH_SECURE_REPLICA 1763 #define ER_TABLE_HAS_NO_FT 1764 #define ER_VARIABLE_NOT_SETTABLE_IN_SF_OR_TRIGGER 1765 #define ER_VARIABLE_NOT_SETTABLE_IN_TRANSACTION 1766 -#define ER_GTID_NEXT_IS_NOT_IN_GTID_NEXT_LIST 1767 -#define ER_CANT_CHANGE_GTID_NEXT_IN_TRANSACTION 1768 +//#define OBSOLETE_ER_GTID_NEXT_IS_NOT_IN_GTID_NEXT_LIST 1767 +//#define OBSOLETE_ER_CANT_CHANGE_GTID_NEXT_IN_TRANSACTION 1768 #define ER_SET_STATEMENT_CANNOT_INVOKE_FUNCTION 1769 #define ER_GTID_NEXT_CANT_BE_AUTOMATIC_IF_GTID_NEXT_LIST_IS_NON_NULL 1770 -#define ER_SKIPPING_LOGGED_TRANSACTION 1771 +//#define OBSOLETE_ER_SKIPPING_LOGGED_TRANSACTION 1771 #define ER_MALFORMED_GTID_SET_SPECIFICATION 1772 #define ER_MALFORMED_GTID_SET_ENCODING 1773 #define ER_MALFORMED_GTID_SPECIFICATION 1774 #define ER_GNO_EXHAUSTED 1775 -#define ER_BAD_SLAVE_AUTO_POSITION 1776 +#define ER_BAD_REPLICA_AUTO_POSITION 1776 #define ER_AUTO_POSITION_REQUIRES_GTID_MODE_NOT_OFF 1777 #define ER_CANT_DO_IMPLICIT_COMMIT_IN_TRX_WHEN_GTID_NEXT_IS_SET 1778 #define ER_GTID_MODE_ON_REQUIRES_ENFORCE_GTID_CONSISTENCY_ON 1779 -#define ER_GTID_MODE_REQUIRES_BINLOG 1780 +//#define OBSOLETE_ER_GTID_MODE_REQUIRES_BINLOG 1780 #define ER_CANT_SET_GTID_NEXT_TO_GTID_WHEN_GTID_MODE_IS_OFF 1781 #define ER_CANT_SET_GTID_NEXT_TO_ANONYMOUS_WHEN_GTID_MODE_IS_ON 1782 #define ER_CANT_SET_GTID_NEXT_LIST_TO_NON_NULL_WHEN_GTID_MODE_IS_OFF 1783 -#define ER_FOUND_GTID_EVENT_WHEN_GTID_MODE_IS_OFF__UNUSED 1784 +//#define OBSOLETE_ER_FOUND_GTID_EVENT_WHEN_GTID_MODE_IS_OFF__UNUSED 1784 #define ER_GTID_UNSAFE_NON_TRANSACTIONAL_TABLE 1785 #define ER_GTID_UNSAFE_CREATE_SELECT 1786 -#define ER_GTID_UNSAFE_CREATE_DROP_TEMPORARY_TABLE_IN_TRANSACTION 1787 +//#define OBSOLETE_ER_GTID_UNSAFE_CREATE_DROP_TEMP_TABLE_IN_TRANSACTION 1787 #define ER_GTID_MODE_CAN_ONLY_CHANGE_ONE_STEP_AT_A_TIME 1788 -#define ER_MASTER_HAS_PURGED_REQUIRED_GTIDS 1789 +#define ER_SOURCE_HAS_PURGED_REQUIRED_GTIDS 1789 #define ER_CANT_SET_GTID_NEXT_WHEN_OWNING_GTID 1790 #define ER_UNKNOWN_EXPLAIN_FORMAT 1791 #define ER_CANT_EXECUTE_IN_READ_ONLY_TRANSACTION 1792 #define ER_TOO_LONG_TABLE_PARTITION_COMMENT 1793 -#define ER_SLAVE_CONFIGURATION 1794 +#define ER_REPLICA_CONFIGURATION 1794 #define ER_INNODB_FT_LIMIT 1795 #define ER_INNODB_NO_FT_TEMP_TABLE 1796 #define ER_INNODB_FT_WRONG_DOCID_COLUMN 1797 @@ -808,11 +832,11 @@ static const int errmsg_section_size[] = { 886, 194 }; #define ER_INNODB_ONLINE_LOG_TOO_BIG 1799 #define ER_UNKNOWN_ALTER_ALGORITHM 1800 #define ER_UNKNOWN_ALTER_LOCK 1801 -#define ER_MTS_CHANGE_MASTER_CANT_RUN_WITH_GAPS 1802 -#define ER_MTS_RECOVERY_FAILURE 1803 -#define ER_MTS_RESET_WORKERS 1804 +#define ER_MTA_CHANGE_SOURCE_CANT_RUN_WITH_GAPS 1802 +#define ER_MTA_RECOVERY_FAILURE 1803 +#define ER_MTA_RESET_WORKERS 1804 #define ER_COL_COUNT_DOESNT_MATCH_CORRUPTED_V2 1805 -#define ER_SLAVE_SILENT_RETRY_TRANSACTION 1806 +#define ER_REPLICA_SILENT_RETRY_TRANSACTION 1806 #define ER_DISCARD_FK_CHECKS_RUNNING 1807 #define ER_TABLE_SCHEMA_MISMATCH 1808 #define ER_TABLE_IN_SYSTEM_TABLESPACE 1809 @@ -840,12 +864,12 @@ static const int errmsg_section_size[] = { 886, 194 }; #define ER_DUP_INDEX 1831 #define ER_FK_COLUMN_CANNOT_CHANGE 1832 #define ER_FK_COLUMN_CANNOT_CHANGE_CHILD 1833 -#define ER_UNUSED5 1834 +//#define OBSOLETE_ER_UNUSED5 1834 #define ER_MALFORMED_PACKET 1835 #define ER_READ_ONLY_MODE 1836 -#define ER_GTID_NEXT_TYPE_UNDEFINED_GROUP 1837 +#define ER_GTID_NEXT_TYPE_UNDEFINED_GTID 1837 #define ER_VARIABLE_NOT_SETTABLE_IN_SP 1838 -#define ER_CANT_SET_GTID_PURGED_WHEN_GTID_MODE_IS_OFF 1839 +//#define OBSOLETE_ER_CANT_SET_GTID_PURGED_WHEN_GTID_MODE_IS_OFF 1839 #define ER_CANT_SET_GTID_PURGED_WHEN_GTID_EXECUTED_IS_NOT_EMPTY 1840 #define ER_CANT_SET_GTID_PURGED_WHEN_OWNED_GTIDS_IS_NOT_EMPTY 1841 #define ER_GTID_PURGED_WAS_CHANGED 1842 @@ -858,31 +882,31 @@ static const int errmsg_section_size[] = { 886, 194 }; #define ER_ALTER_OPERATION_NOT_SUPPORTED_REASON_FK_RENAME 1849 #define ER_ALTER_OPERATION_NOT_SUPPORTED_REASON_COLUMN_TYPE 1850 #define ER_ALTER_OPERATION_NOT_SUPPORTED_REASON_FK_CHECK 1851 -#define ER_UNUSED6 1852 +//#define OBSOLETE_ER_UNUSED6 1852 #define ER_ALTER_OPERATION_NOT_SUPPORTED_REASON_NOPK 1853 #define ER_ALTER_OPERATION_NOT_SUPPORTED_REASON_AUTOINC 1854 #define ER_ALTER_OPERATION_NOT_SUPPORTED_REASON_HIDDEN_FTS 1855 #define ER_ALTER_OPERATION_NOT_SUPPORTED_REASON_CHANGE_FTS 1856 #define ER_ALTER_OPERATION_NOT_SUPPORTED_REASON_FTS 1857 -#define ER_SQL_SLAVE_SKIP_COUNTER_NOT_SETTABLE_IN_GTID_MODE 1858 +//#define OBSOLETE_ER_SQL_REPLICA_SKIP_COUNTER_NOT_SETTABLE_IN_GTID_MODE 1858 #define ER_DUP_UNKNOWN_IN_INDEX 1859 #define ER_IDENT_CAUSES_TOO_LONG_PATH 1860 #define ER_ALTER_OPERATION_NOT_SUPPORTED_REASON_NOT_NULL 1861 #define ER_MUST_CHANGE_PASSWORD_LOGIN 1862 #define ER_ROW_IN_WRONG_PARTITION 1863 -#define ER_MTS_EVENT_BIGGER_PENDING_JOBS_SIZE_MAX 1864 -#define ER_INNODB_NO_FT_USES_PARSER 1865 +#define ER_MTA_EVENT_BIGGER_PENDING_JOBS_SIZE_MAX 1864 +//#define OBSOLETE_ER_INNODB_NO_FT_USES_PARSER 1865 #define ER_BINLOG_LOGICAL_CORRUPTION 1866 #define ER_WARN_PURGE_LOG_IN_USE 1867 #define ER_WARN_PURGE_LOG_IS_ACTIVE 1868 #define ER_AUTO_INCREMENT_CONFLICT 1869 #define WARN_ON_BLOCKHOLE_IN_RBR 1870 -#define ER_SLAVE_MI_INIT_REPOSITORY 1871 -#define ER_SLAVE_RLI_INIT_REPOSITORY 1872 +#define ER_REPLICA_CM_INIT_REPOSITORY 1871 +#define ER_REPLICA_AM_INIT_REPOSITORY 1872 #define ER_ACCESS_DENIED_CHANGE_USER_ERROR 1873 #define ER_INNODB_READ_ONLY 1874 -#define ER_STOP_SLAVE_SQL_THREAD_TIMEOUT 1875 -#define ER_STOP_SLAVE_IO_THREAD_TIMEOUT 1876 +#define ER_STOP_REPLICA_SQL_THREAD_TIMEOUT 1875 +#define ER_STOP_REPLICA_IO_THREAD_TIMEOUT 1876 #define ER_TABLE_CORRUPT 1877 #define ER_TEMP_FILE_WRITE_FAILURE 1878 #define ER_INNODB_FT_AUX_NOT_HEX_ID 1879 @@ -890,11 +914,13 @@ static const int errmsg_section_size[] = { 886, 194 }; #define ER_INNODB_FORCED_RECOVERY 1881 #define ER_AES_INVALID_IV 1882 #define ER_PLUGIN_CANNOT_BE_UNINSTALLED 1883 -#define ER_GTID_UNSAFE_BINLOG_SPLITTABLE_STATEMENT_AND_GTID_GROUP 1884 -#define ER_SLAVE_HAS_MORE_GTIDS_THAN_MASTER 1885 +#define ER_GTID_UNSAFE_BINLOG_SPLITTABLE_STATEMENT_AND_ASSIGNED_GTID 1884 +#define ER_REPLICA_HAS_MORE_GTIDS_THAN_SOURCE 1885 +#define ER_MISSING_KEY 1886 +#define WARN_NAMED_PIPE_ACCESS_EVERYONE 1887 #define ER_FILE_CORRUPT 3000 -#define ER_ERROR_ON_MASTER 3001 -#define ER_INCONSISTENT_ERROR 3002 +#define ER_ERROR_ON_SOURCE 3001 +//#define OBSOLETE_ER_INCONSISTENT_ERROR 3002 #define ER_STORAGE_ENGINE_NOT_LOADED 3003 #define ER_GET_STACKED_DA_WITHOUT_ACTIVE_HANDLER 3004 #define ER_WARN_LEGACY_SYNTAX_CONVERTED 3005 @@ -909,21 +935,21 @@ static const int errmsg_section_size[] = { 886, 194 }; #define ER_MISSING_HA_CREATE_OPTION 3014 #define ER_ENGINE_OUT_OF_MEMORY 3015 #define ER_PASSWORD_EXPIRE_ANONYMOUS_USER 3016 -#define ER_SLAVE_SQL_THREAD_MUST_STOP 3017 +#define ER_REPLICA_SQL_THREAD_MUST_STOP 3017 #define ER_NO_FT_MATERIALIZED_SUBQUERY 3018 #define ER_INNODB_UNDO_LOG_FULL 3019 #define ER_INVALID_ARGUMENT_FOR_LOGARITHM 3020 -#define ER_SLAVE_CHANNEL_IO_THREAD_MUST_STOP 3021 +#define ER_REPLICA_CHANNEL_IO_THREAD_MUST_STOP 3021 #define ER_WARN_OPEN_TEMP_TABLES_MUST_BE_ZERO 3022 -#define ER_WARN_ONLY_MASTER_LOG_FILE_NO_POS 3023 +#define ER_WARN_ONLY_SOURCE_LOG_FILE_NO_POS 3023 #define ER_QUERY_TIMEOUT 3024 #define ER_NON_RO_SELECT_DISABLE_TIMER 3025 #define ER_DUP_LIST_ENTRY 3026 -#define ER_SQL_MODE_NO_EFFECT 3027 +//#define OBSOLETE_ER_SQL_MODE_NO_EFFECT 3027 #define ER_AGGREGATE_ORDER_FOR_UNION 3028 #define ER_AGGREGATE_ORDER_NON_AGG_QUERY 3029 -#define ER_SLAVE_WORKER_STOPPED_PREVIOUS_THD_ERROR 3030 -#define ER_DONT_SUPPORT_SLAVE_PRESERVE_COMMIT_ORDER 3031 +#define ER_REPLICA_WORKER_STOPPED_PREVIOUS_THD_ERROR 3030 +#define ER_DONT_SUPPORT_REPLICA_PRESERVE_COMMIT_ORDER 3031 #define ER_SERVER_OFFLINE_MODE 3032 #define ER_GIS_DIFFERENT_SRIDS 3033 #define ER_GIS_UNSUPPORTED_ARGUMENT 3034 @@ -948,14 +974,14 @@ static const int errmsg_section_size[] = { 886, 194 }; #define ER_STD_RUNTIME_ERROR 3053 #define ER_STD_UNKNOWN_EXCEPTION 3054 #define ER_GIS_DATA_WRONG_ENDIANESS 3055 -#define ER_CHANGE_MASTER_PASSWORD_LENGTH 3056 +#define ER_CHANGE_SOURCE_PASSWORD_LENGTH 3056 #define ER_USER_LOCK_WRONG_NAME 3057 #define ER_USER_LOCK_DEADLOCK 3058 #define ER_REPLACE_INACCESSIBLE_ROWS 3059 #define ER_ALTER_OPERATION_NOT_SUPPORTED_REASON_GIS 3060 #define ER_ILLEGAL_USER_VAR 3061 #define ER_GTID_MODE_OFF 3062 -#define ER_UNSUPPORTED_BY_REPLICATION_THREAD 3063 +//#define OBSOLETE_ER_UNSUPPORTED_BY_REPLICATION_THREAD 3063 #define ER_INCORRECT_TYPE 3064 #define ER_FIELD_IN_ORDER_NOT_SELECT 3065 #define ER_AGGREGATE_IN_ORDER_NOT_SELECT 3066 @@ -966,19 +992,19 @@ static const int errmsg_section_size[] = { 886, 194 }; #define ER_INVALID_GEOJSON_WRONG_TYPE 3071 #define ER_INVALID_GEOJSON_UNSPECIFIED 3072 #define ER_DIMENSION_UNSUPPORTED 3073 -#define ER_SLAVE_CHANNEL_DOES_NOT_EXIST 3074 -#define ER_SLAVE_MULTIPLE_CHANNELS_HOST_PORT 3075 -#define ER_SLAVE_CHANNEL_NAME_INVALID_OR_TOO_LONG 3076 -#define ER_SLAVE_NEW_CHANNEL_WRONG_REPOSITORY 3077 -#define ER_SLAVE_CHANNEL_DELETE 3078 -#define ER_SLAVE_MULTIPLE_CHANNELS_CMD 3079 -#define ER_SLAVE_MAX_CHANNELS_EXCEEDED 3080 -#define ER_SLAVE_CHANNEL_MUST_STOP 3081 -#define ER_SLAVE_CHANNEL_NOT_RUNNING 3082 -#define ER_SLAVE_CHANNEL_WAS_RUNNING 3083 -#define ER_SLAVE_CHANNEL_WAS_NOT_RUNNING 3084 -#define ER_SLAVE_CHANNEL_SQL_THREAD_MUST_STOP 3085 -#define ER_SLAVE_CHANNEL_SQL_SKIP_COUNTER 3086 +#define ER_REPLICA_CHANNEL_DOES_NOT_EXIST 3074 +//#define OBSOLETE_ER_SLAVE_MULTIPLE_CHANNELS_HOST_PORT 3075 +#define ER_REPLICA_CHANNEL_NAME_INVALID_OR_TOO_LONG 3076 +#define ER_REPLICA_NEW_CHANNEL_WRONG_REPOSITORY 3077 +//#define OBSOLETE_ER_SLAVE_CHANNEL_DELETE 3078 +#define ER_REPLICA_MULTIPLE_CHANNELS_CMD 3079 +#define ER_REPLICA_MAX_CHANNELS_EXCEEDED 3080 +#define ER_REPLICA_CHANNEL_MUST_STOP 3081 +#define ER_REPLICA_CHANNEL_NOT_RUNNING 3082 +#define ER_REPLICA_CHANNEL_WAS_RUNNING 3083 +#define ER_REPLICA_CHANNEL_WAS_NOT_RUNNING 3084 +#define ER_REPLICA_CHANNEL_SQL_THREAD_MUST_STOP 3085 +#define ER_REPLICA_CHANNEL_SQL_SKIP_COUNTER 3086 #define ER_WRONG_FIELD_WITH_GROUP_V2 3087 #define ER_MIX_OF_GROUP_FUNC_AND_FIELDS_V2 3088 #define ER_WARN_DEPRECATED_SYSVAR_UPDATE 3089 @@ -1005,11 +1031,11 @@ static const int errmsg_section_size[] = { 886, 194 }; #define ER_FEATURE_NOT_AVAILABLE 3110 #define ER_CANT_SET_GTID_MODE 3111 #define ER_CANT_USE_AUTO_POSITION_WITH_GTID_MODE_OFF 3112 -#define ER_CANT_REPLICATE_ANONYMOUS_WITH_AUTO_POSITION 3113 -#define ER_CANT_REPLICATE_ANONYMOUS_WITH_GTID_MODE_ON 3114 -#define ER_CANT_REPLICATE_GTID_WITH_GTID_MODE_OFF 3115 -#define ER_CANT_SET_ENFORCE_GTID_CONSISTENCY_ON_WITH_ONGOING_GTID_VIOLATING_TRANSACTIONS 3116 -#define ER_SET_ENFORCE_GTID_CONSISTENCY_WARN_WITH_ONGOING_GTID_VIOLATING_TRANSACTIONS 3117 +//#define OBSOLETE_ER_CANT_REPLICATE_ANONYMOUS_WITH_AUTO_POSITION 3113 +//#define OBSOLETE_ER_CANT_REPLICATE_ANONYMOUS_WITH_GTID_MODE_ON 3114 +//#define OBSOLETE_ER_CANT_REPLICATE_GTID_WITH_GTID_MODE_OFF 3115 +#define ER_CANT_ENFORCE_GTID_CONSISTENCY_WITH_ONGOING_GTID_VIOLATING_TX 3116 +#define ER_ENFORCE_GTID_CONSISTENCY_WARN_WITH_ONGOING_GTID_VIOLATING_TX 3117 #define ER_ACCOUNT_HAS_BEEN_LOCKED 3118 #define ER_WRONG_TABLESPACE_NAME 3119 #define ER_TABLESPACE_IS_NOT_EMPTY 3120 @@ -1031,7 +1057,7 @@ static const int errmsg_section_size[] = { 886, 194 }; #define ER_VTOKEN_PLUGIN_TOKEN_MISMATCH 3136 #define ER_VTOKEN_PLUGIN_TOKEN_NOT_FOUND 3137 #define ER_CANT_SET_VARIABLE_WHEN_OWNING_GTID 3138 -#define ER_SLAVE_CHANNEL_OPERATION_NOT_ALLOWED 3139 +#define ER_REPLICA_CHANNEL_OPERATION_NOT_ALLOWED 3139 #define ER_INVALID_JSON_TEXT 3140 #define ER_INVALID_JSON_TEXT_IN_PARAM 3141 #define ER_INVALID_JSON_BINARY_DATA 3142 @@ -1064,7 +1090,7 @@ static const int errmsg_section_size[] = { 886, 194 }; #define ER_SESSION_WAS_KILLED 3169 #define ER_CAPACITY_EXCEEDED 3170 #define ER_CAPACITY_EXCEEDED_IN_RANGE_OPTIMIZER 3171 -#define ER_TABLE_NEEDS_UPG_PART 3172 +//#define OBSOLETE_ER_TABLE_NEEDS_UPG_PART 3172 #define ER_CANT_WAIT_FOR_EXECUTED_GTID_SET_WHILE_OWNING_A_GTID 3173 #define ER_CANNOT_ADD_FOREIGN_BASE_COL_VIRTUAL 3174 #define ER_CANNOT_CREATE_VIRTUAL_INDEX_CONSTRAINT 3175 @@ -1072,7 +1098,7 @@ static const int errmsg_section_size[] = { 886, 194 }; #define ER_LOCK_REFUSED_BY_ENGINE 3177 #define ER_UNSUPPORTED_ALTER_ONLINE_ON_VIRTUAL_COLUMN 3178 #define ER_MASTER_KEY_ROTATION_NOT_SUPPORTED_BY_SE 3179 -#define ER_MASTER_KEY_ROTATION_ERROR_BY_SE 3180 +//#define OBSOLETE_ER_MASTER_KEY_ROTATION_ERROR_BY_SE 3180 #define ER_MASTER_KEY_ROTATION_BINLOG_FAILED 3181 #define ER_MASTER_KEY_ROTATION_SE_UNAVAILABLE 3182 #define ER_TABLESPACE_CANNOT_ENCRYPT 3183 @@ -1082,8 +1108,5082 @@ static const int errmsg_section_size[] = { 886, 194 }; #define ER_UNSUPPORTED_ALTER_ENCRYPTION_INPLACE 3187 #define ER_KEYRING_UDF_KEYRING_SERVICE_ERROR 3188 #define ER_USER_COLUMN_OLD_LENGTH 3189 -#define ER_CANT_RESET_MASTER 3190 +#define ER_CANT_RESET_SOURCE 3190 #define ER_GROUP_REPLICATION_MAX_GROUP_SIZE 3191 #define ER_CANNOT_ADD_FOREIGN_BASE_COL_STORED 3192 #define ER_TABLE_REFERENCED 3193 +//#define OBSOLETE_ER_PARTITION_ENGINE_DEPRECATED_FOR_TABLE 3194 +//#define OBSOLETE_ER_WARN_USING_GEOMFROMWKB_TO_SET_SRID_ZERO 3195 +//#define OBSOLETE_ER_WARN_USING_GEOMFROMWKB_TO_SET_SRID 3196 +#define ER_XA_RETRY 3197 +#define ER_KEYRING_AWS_UDF_AWS_KMS_ERROR 3198 +#define ER_BINLOG_UNSAFE_XA 3199 +#define ER_UDF_ERROR 3200 +#define ER_KEYRING_MIGRATION_FAILURE 3201 +#define ER_KEYRING_ACCESS_DENIED_ERROR 3202 +#define ER_KEYRING_MIGRATION_STATUS 3203 +//#define OBSOLETE_ER_PLUGIN_FAILED_TO_OPEN_TABLES 3204 +//#define OBSOLETE_ER_PLUGIN_FAILED_TO_OPEN_TABLE 3205 +//#define OBSOLETE_ER_AUDIT_LOG_NO_KEYRING_PLUGIN_INSTALLED 3206 +//#define OBSOLETE_ER_AUDIT_LOG_ENCRYPTION_PASSWORD_HAS_NOT_BEEN_SET 3207 +//#define OBSOLETE_ER_AUDIT_LOG_COULD_NOT_CREATE_AES_KEY 3208 +//#define OBSOLETE_ER_AUDIT_LOG_ENCRYPTION_PASSWORD_CANNOT_BE_FETCHED 3209 +//#define OBSOLETE_ER_AUDIT_LOG_JSON_FILTERING_NOT_ENABLED 3210 +//#define OBSOLETE_ER_AUDIT_LOG_UDF_INSUFFICIENT_PRIVILEGE 3211 +//#define OBSOLETE_ER_AUDIT_LOG_SUPER_PRIVILEGE_REQUIRED 3212 +//#define OBSOLETE_ER_COULD_NOT_REINITIALIZE_AUDIT_LOG_FILTERS 3213 +//#define OBSOLETE_ER_AUDIT_LOG_UDF_INVALID_ARGUMENT_TYPE 3214 +//#define OBSOLETE_ER_AUDIT_LOG_UDF_INVALID_ARGUMENT_COUNT 3215 +//#define OBSOLETE_ER_AUDIT_LOG_HAS_NOT_BEEN_INSTALLED 3216 +//#define OBSOLETE_ER_AUDIT_LOG_UDF_READ_INVALID_MAX_ARRAY_LENGTH_ARG_TYPE 3217 +#define ER_AUDIT_LOG_UDF_READ_INVALID_MAX_ARRAY_LENGTH_ARG_VALUE 3218 +//#define OBSOLETE_ER_AUDIT_LOG_JSON_FILTER_PARSING_ERROR 3219 +//#define OBSOLETE_ER_AUDIT_LOG_JSON_FILTER_NAME_CANNOT_BE_EMPTY 3220 +//#define OBSOLETE_ER_AUDIT_LOG_JSON_USER_NAME_CANNOT_BE_EMPTY 3221 +//#define OBSOLETE_ER_AUDIT_LOG_JSON_FILTER_DOES_NOT_EXISTS 3222 +//#define OBSOLETE_ER_AUDIT_LOG_USER_FIRST_CHARACTER_MUST_BE_ALPHANUMERIC 3223 +//#define OBSOLETE_ER_AUDIT_LOG_USER_NAME_INVALID_CHARACTER 3224 +//#define OBSOLETE_ER_AUDIT_LOG_HOST_NAME_INVALID_CHARACTER 3225 +#define OBSOLETE_WARN_DEPRECATED_MAXDB_SQL_MODE_FOR_TIMESTAMP 3226 +//#define OBSOLETE_ER_XA_REPLICATION_FILTERS 3227 +//#define OBSOLETE_ER_CANT_OPEN_ERROR_LOG 3228 +//#define OBSOLETE_ER_GROUPING_ON_TIMESTAMP_IN_DST 3229 +//#define OBSOLETE_ER_CANT_START_SERVER_NAMED_PIPE 3230 +#define ER_WRITE_SET_EXCEEDS_LIMIT 3231 +//#define OBSOLETE_ER_DEPRECATED_TLS_VERSION_SESSION_57 3232 +//#define OBSOLETE_ER_WARN_DEPRECATED_TLS_VERSION_57 3233 +//#define OBSOLETE_ER_WARN_WRONG_NATIVE_TABLE_STRUCTURE 3234 +#define ER_AES_INVALID_KDF_NAME 3235 +#define ER_AES_INVALID_KDF_ITERATIONS 3236 +#define WARN_AES_KEY_SIZE 3237 +#define ER_AES_INVALID_KDF_OPTION_SIZE 3238 +#define ER_UNSUPPORT_COMPRESSED_TEMPORARY_TABLE 3500 +#define ER_ACL_OPERATION_FAILED 3501 +#define ER_UNSUPPORTED_INDEX_ALGORITHM 3502 +#define ER_NO_SUCH_DB 3503 +#define ER_TOO_BIG_ENUM 3504 +#define ER_TOO_LONG_SET_ENUM_VALUE 3505 +#define ER_INVALID_DD_OBJECT 3506 +#define ER_UPDATING_DD_TABLE 3507 +#define ER_INVALID_DD_OBJECT_ID 3508 +#define ER_INVALID_DD_OBJECT_NAME 3509 +#define ER_TABLESPACE_MISSING_WITH_NAME 3510 +#define ER_TOO_LONG_ROUTINE_COMMENT 3511 +#define ER_SP_LOAD_FAILED 3512 +#define ER_INVALID_BITWISE_OPERANDS_SIZE 3513 +#define ER_INVALID_BITWISE_AGGREGATE_OPERANDS_SIZE 3514 +#define ER_WARN_UNSUPPORTED_HINT 3515 +#define ER_UNEXPECTED_GEOMETRY_TYPE 3516 +#define ER_SRS_PARSE_ERROR 3517 +#define ER_SRS_PROJ_PARAMETER_MISSING 3518 +#define ER_WARN_SRS_NOT_FOUND 3519 +#define ER_SRS_NOT_CARTESIAN 3520 +#define ER_SRS_NOT_CARTESIAN_UNDEFINED 3521 +#define ER_PK_INDEX_CANT_BE_INVISIBLE 3522 +#define ER_UNKNOWN_AUTHID 3523 +#define ER_FAILED_ROLE_GRANT 3524 +#define ER_OPEN_ROLE_TABLES 3525 +#define ER_FAILED_DEFAULT_ROLES 3526 +#define ER_COMPONENTS_NO_SCHEME 3527 +#define ER_COMPONENTS_NO_SCHEME_SERVICE 3528 +#define ER_COMPONENTS_CANT_LOAD 3529 +#define ER_ROLE_NOT_GRANTED 3530 +#define ER_FAILED_REVOKE_ROLE 3531 +#define ER_RENAME_ROLE 3532 +#define ER_COMPONENTS_CANT_ACQUIRE_SERVICE_IMPLEMENTATION 3533 +#define ER_COMPONENTS_CANT_SATISFY_DEPENDENCY 3534 +#define ER_COMPONENTS_LOAD_CANT_REGISTER_SERVICE_IMPLEMENTATION 3535 +#define ER_COMPONENTS_LOAD_CANT_INITIALIZE 3536 +#define ER_COMPONENTS_UNLOAD_NOT_LOADED 3537 +#define ER_COMPONENTS_UNLOAD_CANT_DEINITIALIZE 3538 +#define ER_COMPONENTS_CANT_RELEASE_SERVICE 3539 +#define ER_COMPONENTS_UNLOAD_CANT_UNREGISTER_SERVICE 3540 +#define ER_COMPONENTS_CANT_UNLOAD 3541 +#define ER_WARN_UNLOAD_THE_NOT_PERSISTED 3542 +#define ER_COMPONENT_TABLE_INCORRECT 3543 +#define ER_COMPONENT_MANIPULATE_ROW_FAILED 3544 +#define ER_COMPONENTS_UNLOAD_DUPLICATE_IN_GROUP 3545 +#define ER_CANT_SET_GTID_PURGED_DUE_SETS_CONSTRAINTS 3546 +#define ER_CANNOT_LOCK_USER_MANAGEMENT_CACHES 3547 +#define ER_SRS_NOT_FOUND 3548 +#define ER_VARIABLE_NOT_PERSISTED 3549 +#define ER_IS_QUERY_INVALID_CLAUSE 3550 +#define ER_UNABLE_TO_STORE_STATISTICS 3551 +#define ER_NO_SYSTEM_SCHEMA_ACCESS 3552 +#define ER_NO_SYSTEM_TABLESPACE_ACCESS 3553 +#define ER_NO_SYSTEM_TABLE_ACCESS 3554 +#define ER_NO_SYSTEM_TABLE_ACCESS_FOR_DICTIONARY_TABLE 3555 +#define ER_NO_SYSTEM_TABLE_ACCESS_FOR_SYSTEM_TABLE 3556 +#define ER_NO_SYSTEM_TABLE_ACCESS_FOR_TABLE 3557 +#define ER_INVALID_OPTION_KEY 3558 +#define ER_INVALID_OPTION_VALUE 3559 +#define ER_INVALID_OPTION_KEY_VALUE_PAIR 3560 +#define ER_INVALID_OPTION_START_CHARACTER 3561 +#define ER_INVALID_OPTION_END_CHARACTER 3562 +#define ER_INVALID_OPTION_CHARACTERS 3563 +#define ER_DUPLICATE_OPTION_KEY 3564 +#define ER_WARN_SRS_NOT_FOUND_AXIS_ORDER 3565 +#define ER_NO_ACCESS_TO_NATIVE_FCT 3566 +#define ER_RESET_SOURCE_TO_VALUE_OUT_OF_RANGE 3567 +#define ER_UNRESOLVED_TABLE_LOCK 3568 +#define ER_DUPLICATE_TABLE_LOCK 3569 +#define ER_BINLOG_UNSAFE_SKIP_LOCKED 3570 +#define ER_BINLOG_UNSAFE_NOWAIT 3571 +#define ER_LOCK_NOWAIT 3572 +#define ER_CTE_RECURSIVE_REQUIRES_UNION 3573 +#define ER_CTE_RECURSIVE_REQUIRES_NONRECURSIVE_FIRST 3574 +#define ER_CTE_RECURSIVE_FORBIDS_AGGREGATION 3575 +#define ER_CTE_RECURSIVE_FORBIDDEN_JOIN_ORDER 3576 +#define ER_CTE_RECURSIVE_REQUIRES_SINGLE_REFERENCE 3577 +#define ER_SWITCH_TMP_ENGINE 3578 +#define ER_WINDOW_NO_SUCH_WINDOW 3579 +#define ER_WINDOW_CIRCULARITY_IN_WINDOW_GRAPH 3580 +#define ER_WINDOW_NO_CHILD_PARTITIONING 3581 +#define ER_WINDOW_NO_INHERIT_FRAME 3582 +#define ER_WINDOW_NO_REDEFINE_ORDER_BY 3583 +#define ER_WINDOW_FRAME_START_ILLEGAL 3584 +#define ER_WINDOW_FRAME_END_ILLEGAL 3585 +#define ER_WINDOW_FRAME_ILLEGAL 3586 +#define ER_WINDOW_RANGE_FRAME_ORDER_TYPE 3587 +#define ER_WINDOW_RANGE_FRAME_TEMPORAL_TYPE 3588 +#define ER_WINDOW_RANGE_FRAME_NUMERIC_TYPE 3589 +#define ER_WINDOW_RANGE_BOUND_NOT_CONSTANT 3590 +#define ER_WINDOW_DUPLICATE_NAME 3591 +#define ER_WINDOW_ILLEGAL_ORDER_BY 3592 +#define ER_WINDOW_INVALID_WINDOW_FUNC_USE 3593 +#define ER_WINDOW_INVALID_WINDOW_FUNC_ALIAS_USE 3594 +#define ER_WINDOW_NESTED_WINDOW_FUNC_USE_IN_WINDOW_SPEC 3595 +#define ER_WINDOW_ROWS_INTERVAL_USE 3596 +#define ER_WINDOW_NO_GROUP_ORDER_UNUSED 3597 +#define ER_WINDOW_EXPLAIN_JSON 3598 +#define ER_WINDOW_FUNCTION_IGNORES_FRAME 3599 +#define ER_WL9236_NOW_UNUSED 3600 +#define ER_INVALID_NO_OF_ARGS 3601 +#define ER_FIELD_IN_GROUPING_NOT_GROUP_BY 3602 +#define ER_TOO_LONG_TABLESPACE_COMMENT 3603 +#define ER_ENGINE_CANT_DROP_TABLE 3604 +#define ER_ENGINE_CANT_DROP_MISSING_TABLE 3605 +#define ER_TABLESPACE_DUP_FILENAME 3606 +#define ER_DB_DROP_RMDIR2 3607 +#define ER_IMP_NO_FILES_MATCHED 3608 +#define ER_IMP_SCHEMA_DOES_NOT_EXIST 3609 +#define ER_IMP_TABLE_ALREADY_EXISTS 3610 +#define ER_IMP_INCOMPATIBLE_MYSQLD_VERSION 3611 +#define ER_IMP_INCOMPATIBLE_DD_VERSION 3612 +#define ER_IMP_INCOMPATIBLE_SDI_VERSION 3613 +#define ER_WARN_INVALID_HINT 3614 +#define ER_VAR_DOES_NOT_EXIST 3615 +#define ER_LONGITUDE_OUT_OF_RANGE 3616 +#define ER_LATITUDE_OUT_OF_RANGE 3617 +#define ER_NOT_IMPLEMENTED_FOR_GEOGRAPHIC_SRS 3618 +#define ER_ILLEGAL_PRIVILEGE_LEVEL 3619 +#define ER_NO_SYSTEM_VIEW_ACCESS 3620 +#define ER_COMPONENT_FILTER_FLABBERGASTED 3621 +#define ER_PART_EXPR_TOO_LONG 3622 +#define ER_UDF_DROP_DYNAMICALLY_REGISTERED 3623 +#define ER_UNABLE_TO_STORE_COLUMN_STATISTICS 3624 +#define ER_UNABLE_TO_UPDATE_COLUMN_STATISTICS 3625 +#define ER_UNABLE_TO_DROP_COLUMN_STATISTICS 3626 +#define ER_UNABLE_TO_BUILD_HISTOGRAM 3627 +#define ER_MANDATORY_ROLE 3628 +#define ER_MISSING_TABLESPACE_FILE 3629 +#define ER_PERSIST_ONLY_ACCESS_DENIED_ERROR 3630 +#define ER_CMD_NEED_SUPER 3631 +#define ER_PATH_IN_DATADIR 3632 +#define ER_CLONE_DDL_IN_PROGRESS 3633 +#define ER_CLONE_TOO_MANY_CONCURRENT_CLONES 3634 +#define ER_APPLIER_LOG_EVENT_VALIDATION_ERROR 3635 +#define ER_CTE_MAX_RECURSION_DEPTH 3636 +#define ER_NOT_HINT_UPDATABLE_VARIABLE 3637 +#define ER_CREDENTIALS_CONTRADICT_TO_HISTORY 3638 +#define ER_WARNING_PASSWORD_HISTORY_CLAUSES_VOID 3639 +#define ER_CLIENT_DOES_NOT_SUPPORT 3640 +#define ER_I_S_SKIPPED_TABLESPACE 3641 +#define ER_TABLESPACE_ENGINE_MISMATCH 3642 +#define ER_WRONG_SRID_FOR_COLUMN 3643 +#define ER_CANNOT_ALTER_SRID_DUE_TO_INDEX 3644 +#define ER_WARN_BINLOG_PARTIAL_UPDATES_DISABLED 3645 +//#define OBSOLETE_ER_WARN_BINLOG_V1_ROW_EVENTS_DISABLED 3646 +#define ER_WARN_BINLOG_PARTIAL_UPDATES_SUGGESTS_PARTIAL_IMAGES 3647 +#define ER_COULD_NOT_APPLY_JSON_DIFF 3648 +#define ER_CORRUPTED_JSON_DIFF 3649 +#define ER_RESOURCE_GROUP_EXISTS 3650 +#define ER_RESOURCE_GROUP_NOT_EXISTS 3651 +#define ER_INVALID_VCPU_ID 3652 +#define ER_INVALID_VCPU_RANGE 3653 +#define ER_INVALID_THREAD_PRIORITY 3654 +#define ER_DISALLOWED_OPERATION 3655 +#define ER_RESOURCE_GROUP_BUSY 3656 +#define ER_RESOURCE_GROUP_DISABLED 3657 +#define ER_FEATURE_UNSUPPORTED 3658 +#define ER_ATTRIBUTE_IGNORED 3659 +#define ER_INVALID_THREAD_ID 3660 +#define ER_RESOURCE_GROUP_BIND_FAILED 3661 +#define ER_INVALID_USE_OF_FORCE_OPTION 3662 +#define ER_GROUP_REPLICATION_COMMAND_FAILURE 3663 +#define ER_SDI_OPERATION_FAILED 3664 +#define ER_MISSING_JSON_TABLE_VALUE 3665 +#define ER_WRONG_JSON_TABLE_VALUE 3666 +#define ER_TF_MUST_HAVE_ALIAS 3667 +#define ER_TF_FORBIDDEN_JOIN_TYPE 3668 +#define ER_JT_VALUE_OUT_OF_RANGE 3669 +#define ER_JT_MAX_NESTED_PATH 3670 +#define ER_PASSWORD_EXPIRATION_NOT_SUPPORTED_BY_AUTH_METHOD 3671 +#define ER_INVALID_GEOJSON_CRS_NOT_TOP_LEVEL 3672 +#define ER_BAD_NULL_ERROR_NOT_IGNORED 3673 +#define WARN_USELESS_SPATIAL_INDEX 3674 +#define ER_DISK_FULL_NOWAIT 3675 +#define ER_PARSE_ERROR_IN_DIGEST_FN 3676 +#define ER_UNDISCLOSED_PARSE_ERROR_IN_DIGEST_FN 3677 +#define ER_SCHEMA_DIR_EXISTS 3678 +#define ER_SCHEMA_DIR_MISSING 3679 +#define ER_SCHEMA_DIR_CREATE_FAILED 3680 +#define ER_SCHEMA_DIR_UNKNOWN 3681 +#define ER_ONLY_IMPLEMENTED_FOR_SRID_0_AND_4326 3682 +//#define OBSOLETE_ER_BINLOG_EXPIRE_LOG_DAYS_AND_SECS_USED_TOGETHER 3683 +#define ER_REGEXP_BUFFER_OVERFLOW 3684 +#define ER_REGEXP_ILLEGAL_ARGUMENT 3685 +#define ER_REGEXP_INDEX_OUTOFBOUNDS_ERROR 3686 +#define ER_REGEXP_INTERNAL_ERROR 3687 +#define ER_REGEXP_RULE_SYNTAX 3688 +#define ER_REGEXP_BAD_ESCAPE_SEQUENCE 3689 +#define ER_REGEXP_UNIMPLEMENTED 3690 +#define ER_REGEXP_MISMATCHED_PAREN 3691 +#define ER_REGEXP_BAD_INTERVAL 3692 +#define ER_REGEXP_MAX_LT_MIN 3693 +#define ER_REGEXP_INVALID_BACK_REF 3694 +#define ER_REGEXP_LOOK_BEHIND_LIMIT 3695 +#define ER_REGEXP_MISSING_CLOSE_BRACKET 3696 +#define ER_REGEXP_INVALID_RANGE 3697 +#define ER_REGEXP_STACK_OVERFLOW 3698 +#define ER_REGEXP_TIME_OUT 3699 +#define ER_REGEXP_PATTERN_TOO_BIG 3700 +#define ER_CANT_SET_ERROR_LOG_SERVICE 3701 +#define ER_EMPTY_PIPELINE_FOR_ERROR_LOG_SERVICE 3702 +#define ER_COMPONENT_FILTER_DIAGNOSTICS 3703 +#define ER_NOT_IMPLEMENTED_FOR_CARTESIAN_SRS 3704 +#define ER_NOT_IMPLEMENTED_FOR_PROJECTED_SRS 3705 +#define ER_NONPOSITIVE_RADIUS 3706 +#define ER_RESTART_SERVER_FAILED 3707 +#define ER_SRS_MISSING_MANDATORY_ATTRIBUTE 3708 +#define ER_SRS_MULTIPLE_ATTRIBUTE_DEFINITIONS 3709 +#define ER_SRS_NAME_CANT_BE_EMPTY_OR_WHITESPACE 3710 +#define ER_SRS_ORGANIZATION_CANT_BE_EMPTY_OR_WHITESPACE 3711 +#define ER_SRS_ID_ALREADY_EXISTS 3712 +#define ER_WARN_SRS_ID_ALREADY_EXISTS 3713 +#define ER_CANT_MODIFY_SRID_0 3714 +#define ER_WARN_RESERVED_SRID_RANGE 3715 +#define ER_CANT_MODIFY_SRS_USED_BY_COLUMN 3716 +#define ER_SRS_INVALID_CHARACTER_IN_ATTRIBUTE 3717 +#define ER_SRS_ATTRIBUTE_STRING_TOO_LONG 3718 +#define ER_DEPRECATED_UTF8_ALIAS 3719 +#define ER_DEPRECATED_NATIONAL 3720 +#define ER_INVALID_DEFAULT_UTF8MB4_COLLATION 3721 +#define ER_UNABLE_TO_COLLECT_LOG_STATUS 3722 +#define ER_RESERVED_TABLESPACE_NAME 3723 +#define ER_UNABLE_TO_SET_OPTION 3724 +#define ER_REPLICA_POSSIBLY_DIVERGED_AFTER_DDL 3725 +#define ER_SRS_NOT_GEOGRAPHIC 3726 +#define ER_POLYGON_TOO_LARGE 3727 +#define ER_SPATIAL_UNIQUE_INDEX 3728 +#define ER_INDEX_TYPE_NOT_SUPPORTED_FOR_SPATIAL_INDEX 3729 +#define ER_FK_CANNOT_DROP_PARENT 3730 +#define ER_GEOMETRY_PARAM_LONGITUDE_OUT_OF_RANGE 3731 +#define ER_GEOMETRY_PARAM_LATITUDE_OUT_OF_RANGE 3732 +#define ER_FK_CANNOT_USE_VIRTUAL_COLUMN 3733 +#define ER_FK_NO_COLUMN_PARENT 3734 +#define ER_CANT_SET_ERROR_SUPPRESSION_LIST 3735 +#define ER_SRS_GEOGCS_INVALID_AXES 3736 +#define ER_SRS_INVALID_SEMI_MAJOR_AXIS 3737 +#define ER_SRS_INVALID_INVERSE_FLATTENING 3738 +#define ER_SRS_INVALID_ANGULAR_UNIT 3739 +#define ER_SRS_INVALID_PRIME_MERIDIAN 3740 +#define ER_TRANSFORM_SOURCE_SRS_NOT_SUPPORTED 3741 +#define ER_TRANSFORM_TARGET_SRS_NOT_SUPPORTED 3742 +#define ER_TRANSFORM_SOURCE_SRS_MISSING_TOWGS84 3743 +#define ER_TRANSFORM_TARGET_SRS_MISSING_TOWGS84 3744 +#define ER_TEMP_TABLE_PREVENTS_SWITCH_SESSION_BINLOG_FORMAT 3745 +#define ER_TEMP_TABLE_PREVENTS_SWITCH_GLOBAL_BINLOG_FORMAT 3746 +#define ER_RUNNING_APPLIER_PREVENTS_SWITCH_GLOBAL_BINLOG_FORMAT 3747 +#define ER_CLIENT_GTID_UNSAFE_CREATE_DROP_TEMP_TABLE_IN_TRX_IN_SBR 3748 +//#define OBSOLETE_ER_XA_CANT_CREATE_MDL_BACKUP 3749 +#define ER_TABLE_WITHOUT_PK 3750 +#define ER_WARN_DATA_TRUNCATED_FUNCTIONAL_INDEX 3751 +#define ER_WARN_DATA_OUT_OF_RANGE_FUNCTIONAL_INDEX 3752 +#define ER_FUNCTIONAL_INDEX_ON_JSON_OR_GEOMETRY_FUNCTION 3753 +#define ER_FUNCTIONAL_INDEX_REF_AUTO_INCREMENT 3754 +#define ER_CANNOT_DROP_COLUMN_FUNCTIONAL_INDEX 3755 +#define ER_FUNCTIONAL_INDEX_PRIMARY_KEY 3756 +#define ER_FUNCTIONAL_INDEX_ON_LOB 3757 +#define ER_FUNCTIONAL_INDEX_FUNCTION_IS_NOT_ALLOWED 3758 +#define ER_FULLTEXT_FUNCTIONAL_INDEX 3759 +#define ER_SPATIAL_FUNCTIONAL_INDEX 3760 +#define ER_WRONG_KEY_COLUMN_FUNCTIONAL_INDEX 3761 +#define ER_FUNCTIONAL_INDEX_ON_FIELD 3762 +#define ER_GENERATED_COLUMN_NAMED_FUNCTION_IS_NOT_ALLOWED 3763 +#define ER_GENERATED_COLUMN_ROW_VALUE 3764 +#define ER_GENERATED_COLUMN_VARIABLES 3765 +#define ER_DEPENDENT_BY_DEFAULT_GENERATED_VALUE 3766 +#define ER_DEFAULT_VAL_GENERATED_NON_PRIOR 3767 +#define ER_DEFAULT_VAL_GENERATED_REF_AUTO_INC 3768 +#define ER_DEFAULT_VAL_GENERATED_FUNCTION_IS_NOT_ALLOWED 3769 +#define ER_DEFAULT_VAL_GENERATED_NAMED_FUNCTION_IS_NOT_ALLOWED 3770 +#define ER_DEFAULT_VAL_GENERATED_ROW_VALUE 3771 +#define ER_DEFAULT_VAL_GENERATED_VARIABLES 3772 +#define ER_DEFAULT_AS_VAL_GENERATED 3773 +#define ER_UNSUPPORTED_ACTION_ON_DEFAULT_VAL_GENERATED 3774 +#define ER_GTID_UNSAFE_ALTER_ADD_COL_WITH_DEFAULT_EXPRESSION 3775 +#define ER_FK_CANNOT_CHANGE_ENGINE 3776 +#define ER_WARN_DEPRECATED_USER_SET_EXPR 3777 +#define ER_WARN_DEPRECATED_UTF8MB3_COLLATION 3778 +#define ER_WARN_DEPRECATED_NESTED_COMMENT_SYNTAX 3779 +#define ER_FK_INCOMPATIBLE_COLUMNS 3780 +#define ER_GR_HOLD_WAIT_TIMEOUT 3781 +#define ER_GR_HOLD_KILLED 3782 +#define ER_GR_HOLD_MEMBER_STATUS_ERROR 3783 +#define ER_RPL_ENCRYPTION_FAILED_TO_FETCH_KEY 3784 +#define ER_RPL_ENCRYPTION_KEY_NOT_FOUND 3785 +#define ER_RPL_ENCRYPTION_KEYRING_INVALID_KEY 3786 +#define ER_RPL_ENCRYPTION_HEADER_ERROR 3787 +#define ER_RPL_ENCRYPTION_FAILED_TO_ROTATE_LOGS 3788 +#define ER_RPL_ENCRYPTION_KEY_EXISTS_UNEXPECTED 3789 +#define ER_RPL_ENCRYPTION_FAILED_TO_GENERATE_KEY 3790 +#define ER_RPL_ENCRYPTION_FAILED_TO_STORE_KEY 3791 +#define ER_RPL_ENCRYPTION_FAILED_TO_REMOVE_KEY 3792 +#define ER_RPL_ENCRYPTION_UNABLE_TO_CHANGE_OPTION 3793 +#define ER_RPL_ENCRYPTION_MASTER_KEY_RECOVERY_FAILED 3794 +#define ER_SLOW_LOG_MODE_IGNORED_WHEN_NOT_LOGGING_TO_FILE 3795 +#define ER_GRP_TRX_CONSISTENCY_NOT_ALLOWED 3796 +#define ER_GRP_TRX_CONSISTENCY_BEFORE 3797 +#define ER_GRP_TRX_CONSISTENCY_AFTER_ON_TRX_BEGIN 3798 +#define ER_GRP_TRX_CONSISTENCY_BEGIN_NOT_ALLOWED 3799 +#define ER_FUNCTIONAL_INDEX_ROW_VALUE_IS_NOT_ALLOWED 3800 +#define ER_RPL_ENCRYPTION_FAILED_TO_ENCRYPT 3801 +#define ER_PAGE_TRACKING_NOT_STARTED 3802 +#define ER_PAGE_TRACKING_RANGE_NOT_TRACKED 3803 +#define ER_PAGE_TRACKING_CANNOT_PURGE 3804 +#define ER_RPL_ENCRYPTION_CANNOT_ROTATE_BINLOG_MASTER_KEY 3805 +#define ER_BINLOG_MASTER_KEY_RECOVERY_OUT_OF_COMBINATION 3806 +#define ER_BINLOG_MASTER_KEY_ROTATION_FAIL_TO_OPERATE_KEY 3807 +#define ER_BINLOG_MASTER_KEY_ROTATION_FAIL_TO_ROTATE_LOGS 3808 +#define ER_BINLOG_MASTER_KEY_ROTATION_FAIL_TO_REENCRYPT_LOG 3809 +#define ER_BINLOG_MASTER_KEY_ROTATION_FAIL_TO_CLEANUP_UNUSED_KEYS 3810 +#define ER_BINLOG_MASTER_KEY_ROTATION_FAIL_TO_CLEANUP_AUX_KEY 3811 +#define ER_NON_BOOLEAN_EXPR_FOR_CHECK_CONSTRAINT 3812 +#define ER_COLUMN_CHECK_CONSTRAINT_REFERENCES_OTHER_COLUMN 3813 +#define ER_CHECK_CONSTRAINT_NAMED_FUNCTION_IS_NOT_ALLOWED 3814 +#define ER_CHECK_CONSTRAINT_FUNCTION_IS_NOT_ALLOWED 3815 +#define ER_CHECK_CONSTRAINT_VARIABLES 3816 +#define ER_CHECK_CONSTRAINT_ROW_VALUE 3817 +#define ER_CHECK_CONSTRAINT_REFERS_AUTO_INCREMENT_COLUMN 3818 +#define ER_CHECK_CONSTRAINT_VIOLATED 3819 +#define ER_CHECK_CONSTRAINT_REFERS_UNKNOWN_COLUMN 3820 +#define ER_CHECK_CONSTRAINT_NOT_FOUND 3821 +#define ER_CHECK_CONSTRAINT_DUP_NAME 3822 +#define ER_CHECK_CONSTRAINT_CLAUSE_USING_FK_REFER_ACTION_COLUMN 3823 +#define WARN_UNENCRYPTED_TABLE_IN_ENCRYPTED_DB 3824 +#define ER_INVALID_ENCRYPTION_REQUEST 3825 +#define ER_CANNOT_SET_TABLE_ENCRYPTION 3826 +#define ER_CANNOT_SET_DATABASE_ENCRYPTION 3827 +#define ER_CANNOT_SET_TABLESPACE_ENCRYPTION 3828 +#define ER_TABLESPACE_CANNOT_BE_ENCRYPTED 3829 +#define ER_TABLESPACE_CANNOT_BE_DECRYPTED 3830 +#define ER_TABLESPACE_TYPE_UNKNOWN 3831 +#define ER_TARGET_TABLESPACE_UNENCRYPTED 3832 +#define ER_CANNOT_USE_ENCRYPTION_CLAUSE 3833 +#define ER_INVALID_MULTIPLE_CLAUSES 3834 +#define ER_UNSUPPORTED_USE_OF_GRANT_AS 3835 +#define ER_UKNOWN_AUTH_ID_OR_ACCESS_DENIED_FOR_GRANT_AS 3836 +#define ER_DEPENDENT_BY_FUNCTIONAL_INDEX 3837 +#define ER_PLUGIN_NOT_EARLY 3838 +#define ER_INNODB_REDO_LOG_ARCHIVE_START_SUBDIR_PATH 3839 +#define ER_INNODB_REDO_LOG_ARCHIVE_START_TIMEOUT 3840 +#define ER_INNODB_REDO_LOG_ARCHIVE_DIRS_INVALID 3841 +#define ER_INNODB_REDO_LOG_ARCHIVE_LABEL_NOT_FOUND 3842 +#define ER_INNODB_REDO_LOG_ARCHIVE_DIR_EMPTY 3843 +#define ER_INNODB_REDO_LOG_ARCHIVE_NO_SUCH_DIR 3844 +#define ER_INNODB_REDO_LOG_ARCHIVE_DIR_CLASH 3845 +#define ER_INNODB_REDO_LOG_ARCHIVE_DIR_PERMISSIONS 3846 +#define ER_INNODB_REDO_LOG_ARCHIVE_FILE_CREATE 3847 +#define ER_INNODB_REDO_LOG_ARCHIVE_ACTIVE 3848 +#define ER_INNODB_REDO_LOG_ARCHIVE_INACTIVE 3849 +#define ER_INNODB_REDO_LOG_ARCHIVE_FAILED 3850 +#define ER_INNODB_REDO_LOG_ARCHIVE_SESSION 3851 +#define ER_STD_REGEX_ERROR 3852 +#define ER_INVALID_JSON_TYPE 3853 +#define ER_CANNOT_CONVERT_STRING 3854 +#define ER_DEPENDENT_BY_PARTITION_FUNC 3855 +#define ER_WARN_DEPRECATED_FLOAT_AUTO_INCREMENT 3856 +#define ER_RPL_CANT_STOP_REPLICA_WHILE_LOCKED_BACKUP 3857 +#define ER_WARN_DEPRECATED_FLOAT_DIGITS 3858 +#define ER_WARN_DEPRECATED_FLOAT_UNSIGNED 3859 +#define ER_WARN_DEPRECATED_INTEGER_DISPLAY_WIDTH 3860 +#define ER_WARN_DEPRECATED_ZEROFILL 3861 +#define ER_CLONE_DONOR 3862 +#define ER_CLONE_PROTOCOL 3863 +#define ER_CLONE_DONOR_VERSION 3864 +#define ER_CLONE_OS 3865 +#define ER_CLONE_PLATFORM 3866 +#define ER_CLONE_CHARSET 3867 +#define ER_CLONE_CONFIG 3868 +#define ER_CLONE_SYS_CONFIG 3869 +#define ER_CLONE_PLUGIN_MATCH 3870 +#define ER_CLONE_LOOPBACK 3871 +#define ER_CLONE_ENCRYPTION 3872 +#define ER_CLONE_DISK_SPACE 3873 +#define ER_CLONE_IN_PROGRESS 3874 +#define ER_CLONE_DISALLOWED 3875 +#define ER_CANNOT_GRANT_ROLES_TO_ANONYMOUS_USER 3876 +#define ER_SECONDARY_ENGINE_PLUGIN 3877 +#define ER_SECOND_PASSWORD_CANNOT_BE_EMPTY 3878 +#define ER_DB_ACCESS_DENIED 3879 +#define ER_DA_AUTH_ID_WITH_SYSTEM_USER_PRIV_IN_MANDATORY_ROLES 3880 +#define ER_DA_RPL_GTID_TABLE_CANNOT_OPEN 3881 +#define ER_GEOMETRY_IN_UNKNOWN_LENGTH_UNIT 3882 +#define ER_DA_PLUGIN_INSTALL_ERROR 3883 +#define ER_NO_SESSION_TEMP 3884 +#define ER_DA_UNKNOWN_ERROR_NUMBER 3885 +#define ER_COLUMN_CHANGE_SIZE 3886 +#define ER_REGEXP_INVALID_CAPTURE_GROUP_NAME 3887 +#define ER_DA_SSL_LIBRARY_ERROR 3888 +#define ER_SECONDARY_ENGINE 3889 +#define ER_SECONDARY_ENGINE_DDL 3890 +#define ER_INCORRECT_CURRENT_PASSWORD 3891 +#define ER_MISSING_CURRENT_PASSWORD 3892 +#define ER_CURRENT_PASSWORD_NOT_REQUIRED 3893 +#define ER_PASSWORD_CANNOT_BE_RETAINED_ON_PLUGIN_CHANGE 3894 +#define ER_CURRENT_PASSWORD_CANNOT_BE_RETAINED 3895 +#define ER_PARTIAL_REVOKES_EXIST 3896 +#define ER_CANNOT_GRANT_SYSTEM_PRIV_TO_MANDATORY_ROLE 3897 +#define ER_XA_REPLICATION_FILTERS 3898 +#define ER_UNSUPPORTED_SQL_MODE 3899 +#define ER_REGEXP_INVALID_FLAG 3900 +#define ER_PARTIAL_REVOKE_AND_DB_GRANT_BOTH_EXISTS 3901 +#define ER_UNIT_NOT_FOUND 3902 +#define ER_INVALID_JSON_VALUE_FOR_FUNC_INDEX 3903 +#define ER_JSON_VALUE_OUT_OF_RANGE_FOR_FUNC_INDEX 3904 +#define ER_EXCEEDED_MV_KEYS_NUM 3905 +#define ER_EXCEEDED_MV_KEYS_SPACE 3906 +#define ER_FUNCTIONAL_INDEX_DATA_IS_TOO_LONG 3907 +#define ER_WRONG_MVI_VALUE 3908 +#define ER_WARN_FUNC_INDEX_NOT_APPLICABLE 3909 +#define ER_GRP_RPL_UDF_ERROR 3910 +#define ER_UPDATE_GTID_PURGED_WITH_GR 3911 +#define ER_GROUPING_ON_TIMESTAMP_IN_DST 3912 +#define ER_TABLE_NAME_CAUSES_TOO_LONG_PATH 3913 +#define ER_AUDIT_LOG_INSUFFICIENT_PRIVILEGE 3914 +//#define OBSOLETE_ER_AUDIT_LOG_PASSWORD_HAS_BEEN_COPIED 3915 +#define ER_DA_GRP_RPL_STARTED_AUTO_REJOIN 3916 +#define ER_SYSVAR_CHANGE_DURING_QUERY 3917 +#define ER_GLOBSTAT_CHANGE_DURING_QUERY 3918 +#define ER_GRP_RPL_MESSAGE_SERVICE_INIT_FAILURE 3919 +#define ER_CHANGE_SOURCE_WRONG_COMPRESSION_ALGORITHM_CLIENT 3920 +#define ER_CHANGE_SOURCE_WRONG_COMPRESSION_LEVEL_CLIENT 3921 +#define ER_WRONG_COMPRESSION_ALGORITHM_CLIENT 3922 +#define ER_WRONG_COMPRESSION_LEVEL_CLIENT 3923 +#define ER_CHANGE_SOURCE_WRONG_COMPRESSION_ALGORITHM_LIST_CLIENT 3924 +#define ER_CLIENT_PRIVILEGE_CHECKS_USER_CANNOT_BE_ANONYMOUS 3925 +#define ER_CLIENT_PRIVILEGE_CHECKS_USER_DOES_NOT_EXIST 3926 +#define ER_CLIENT_PRIVILEGE_CHECKS_USER_CORRUPT 3927 +#define ER_CLIENT_PRIVILEGE_CHECKS_USER_NEEDS_RPL_APPLIER_PRIV 3928 +#define ER_WARN_DA_PRIVILEGE_NOT_REGISTERED 3929 +#define ER_CLIENT_KEYRING_UDF_KEY_INVALID 3930 +#define ER_CLIENT_KEYRING_UDF_KEY_TYPE_INVALID 3931 +#define ER_CLIENT_KEYRING_UDF_KEY_TOO_LONG 3932 +#define ER_CLIENT_KEYRING_UDF_KEY_TYPE_TOO_LONG 3933 +#define ER_JSON_SCHEMA_VALIDATION_ERROR_WITH_DETAILED_REPORT 3934 +#define ER_DA_UDF_INVALID_CHARSET_SPECIFIED 3935 +#define ER_DA_UDF_INVALID_CHARSET 3936 +#define ER_DA_UDF_INVALID_COLLATION 3937 +#define ER_DA_UDF_INVALID_EXTENSION_ARGUMENT_TYPE 3938 +#define ER_MULTIPLE_CONSTRAINTS_WITH_SAME_NAME 3939 +#define ER_CONSTRAINT_NOT_FOUND 3940 +#define ER_ALTER_CONSTRAINT_ENFORCEMENT_NOT_SUPPORTED 3941 +#define ER_TABLE_VALUE_CONSTRUCTOR_MUST_HAVE_COLUMNS 3942 +#define ER_TABLE_VALUE_CONSTRUCTOR_CANNOT_HAVE_DEFAULT 3943 +#define ER_CLIENT_QUERY_FAILURE_INVALID_NON_ROW_FORMAT 3944 +#define ER_REQUIRE_ROW_FORMAT_INVALID_VALUE 3945 +#define ER_FAILED_TO_DETERMINE_IF_ROLE_IS_MANDATORY 3946 +#define ER_FAILED_TO_FETCH_MANDATORY_ROLE_LIST 3947 +#define ER_CLIENT_LOCAL_FILES_DISABLED 3948 +#define ER_IMP_INCOMPATIBLE_CFG_VERSION 3949 +#define ER_DA_OOM 3950 +#define ER_DA_UDF_INVALID_ARGUMENT_TO_SET_CHARSET 3951 +#define ER_DA_UDF_INVALID_RETURN_TYPE_TO_SET_CHARSET 3952 +#define ER_MULTIPLE_INTO_CLAUSES 3953 +#define ER_MISPLACED_INTO 3954 +#define ER_USER_ACCESS_DENIED_FOR_USER_ACCOUNT_BLOCKED_BY_PASSWORD_LOCK 3955 +#define ER_WARN_DEPRECATED_YEAR_UNSIGNED 3956 +#define ER_CLONE_NETWORK_PACKET 3957 +#define ER_SDI_OPERATION_FAILED_MISSING_RECORD 3958 +#define ER_DEPENDENT_BY_CHECK_CONSTRAINT 3959 +#define ER_GRP_OPERATION_NOT_ALLOWED_GR_MUST_STOP 3960 +#define ER_WARN_DEPRECATED_JSON_TABLE_ON_ERROR_ON_EMPTY 3961 +#define ER_WARN_DEPRECATED_INNER_INTO 3962 +#define ER_WARN_DEPRECATED_VALUES_FUNCTION_ALWAYS_NULL 3963 +#define ER_WARN_DEPRECATED_SQL_CALC_FOUND_ROWS 3964 +#define ER_WARN_DEPRECATED_FOUND_ROWS 3965 +#define ER_MISSING_JSON_VALUE 3966 +#define ER_MULTIPLE_JSON_VALUES 3967 +#define ER_HOSTNAME_TOO_LONG 3968 +//#define OBSOLETE_ER_WARN_CLIENT_DEPRECATED_PARTITION_PREFIX_KEY 3969 +#define ER_GROUP_REPLICATION_USER_EMPTY_MSG 3970 +#define ER_GROUP_REPLICATION_USER_MANDATORY_MSG 3971 +#define ER_GROUP_REPLICATION_PASSWORD_LENGTH 3972 +#define ER_SUBQUERY_TRANSFORM_REJECTED 3973 +#define ER_DA_GRP_RPL_RECOVERY_ENDPOINT_FORMAT 3974 +#define ER_DA_GRP_RPL_RECOVERY_ENDPOINT_INVALID 3975 +#define ER_WRONG_VALUE_FOR_VAR_PLUS_ACTIONABLE_PART 3976 +#define ER_STATEMENT_NOT_ALLOWED_AFTER_START_TRANSACTION 3977 +#define ER_FOREIGN_KEY_WITH_ATOMIC_CREATE_SELECT 3978 +#define ER_NOT_ALLOWED_WITH_START_TRANSACTION 3979 +#define ER_INVALID_JSON_ATTRIBUTE 3980 +#define ER_ENGINE_ATTRIBUTE_NOT_SUPPORTED 3981 +#define ER_INVALID_USER_ATTRIBUTE_JSON 3982 +#define ER_INNODB_REDO_DISABLED 3983 +#define ER_INNODB_REDO_ARCHIVING_ENABLED 3984 +#define ER_MDL_OUT_OF_RESOURCES 3985 +#define ER_IMPLICIT_COMPARISON_FOR_JSON 3986 +#define ER_FUNCTION_DOES_NOT_SUPPORT_CHARACTER_SET 3987 +#define ER_IMPOSSIBLE_STRING_CONVERSION 3988 +#define ER_SCHEMA_READ_ONLY 3989 +#define ER_RPL_ASYNC_RECONNECT_GTID_MODE_OFF 3990 +#define ER_RPL_ASYNC_RECONNECT_AUTO_POSITION_OFF 3991 +#define ER_DISABLE_GTID_MODE_REQUIRES_ASYNC_RECONNECT_OFF 3992 +#define ER_DISABLE_AUTO_POSITION_REQUIRES_ASYNC_RECONNECT_OFF 3993 +#define ER_INVALID_PARAMETER_USE 3994 +#define ER_CHARACTER_SET_MISMATCH 3995 +#define ER_WARN_VAR_VALUE_CHANGE_NOT_SUPPORTED 3996 +#define ER_INVALID_TIME_ZONE_INTERVAL 3997 +#define ER_INVALID_CAST 3998 +#define ER_HYPERGRAPH_NOT_SUPPORTED_YET 3999 +#define ER_WARN_HYPERGRAPH_EXPERIMENTAL 4000 +#define ER_DA_NO_ERROR_LOG_PARSER_CONFIGURED 4001 +#define ER_DA_ERROR_LOG_TABLE_DISABLED 4002 +#define ER_DA_ERROR_LOG_MULTIPLE_FILTERS 4003 +#define ER_DA_CANT_OPEN_ERROR_LOG 4004 +#define ER_USER_REFERENCED_AS_DEFINER 4005 +#define ER_CANNOT_USER_REFERENCED_AS_DEFINER 4006 +#define ER_REGEX_NUMBER_TOO_BIG 4007 +#define ER_SPVAR_NONINTEGER_TYPE 4008 +#define WARN_UNSUPPORTED_ACL_TABLES_READ 4009 +#define ER_BINLOG_UNSAFE_ACL_TABLE_READ_IN_DML_DDL 4010 +#define ER_STOP_REPLICA_MONITOR_IO_THREAD_TIMEOUT 4011 +#define ER_STARTING_REPLICA_MONITOR_IO_THREAD 4012 +#define ER_CANT_USE_ANONYMOUS_TO_GTID_WITH_GTID_MODE_NOT_ON 4013 +#define ER_CANT_COMBINE_ANONYMOUS_TO_GTID_AND_AUTOPOSITION 4014 +#define ER_ASSIGN_GTIDS_TO_ANONYMOUS_TRANSACTIONS_REQUIRES_GTID_MODE_ON 4015 +#define ER_SQL_REPLICA_SKIP_COUNTER_USED_WITH_GTID_MODE_ON 4016 +#define ER_USING_ASSIGN_GTIDS_TO_ANONYMOUS_TRANSACTIONS_AS_LOCAL_OR_UUID 4017 +//#define OBSOLETE_ER_SET_GTID_TO_ANON_AND_WAIT_UNTIL_SQL_THD_AFTER_GTIDS 4018 +#define ER_CANT_SET_SQL_AFTER_OR_BEFORE_GTIDS_WITH_ANONYMOUS_TO_GTID 4019 +#define ER_ANONYMOUS_TO_GTID_UUID_SAME_AS_GROUP_NAME 4020 +#define ER_CANT_USE_SAME_UUID_AS_GROUP_NAME 4021 +#define ER_GRP_RPL_RECOVERY_CHANNEL_STILL_RUNNING 4022 +#define ER_INNODB_INVALID_AUTOEXTEND_SIZE_VALUE 4023 +#define ER_INNODB_INCOMPATIBLE_WITH_TABLESPACE 4024 +#define ER_INNODB_AUTOEXTEND_SIZE_OUT_OF_RANGE 4025 +#define ER_CANNOT_USE_AUTOEXTEND_SIZE_CLAUSE 4026 +#define ER_ROLE_GRANTED_TO_ITSELF 4027 +#define ER_TABLE_MUST_HAVE_A_VISIBLE_COLUMN 4028 +#define ER_INNODB_COMPRESSION_FAILURE 4029 +#define ER_WARN_ASYNC_CONN_FAILOVER_NETWORK_NAMESPACE 4030 +#define ER_CLIENT_INTERACTION_TIMEOUT 4031 +#define ER_INVALID_CAST_TO_GEOMETRY 4032 +#define ER_INVALID_CAST_POLYGON_RING_DIRECTION 4033 +#define ER_GIS_DIFFERENT_SRIDS_AGGREGATION 4034 +#define ER_RELOAD_KEYRING_FAILURE 4035 +#define ER_SDI_GET_KEYS_INVALID_TABLESPACE 4036 +#define ER_CHANGE_RPL_SRC_WRONG_COMPRESSION_ALGORITHM_SIZE 4037 +//#define OBSOLETE_ER_WARN_DEPRECATED_TLS_VERSION_FOR_CHANNEL_CLI 4038 +#define ER_CANT_USE_SAME_UUID_AS_VIEW_CHANGE_UUID 4039 +#define ER_ANONYMOUS_TO_GTID_UUID_SAME_AS_VIEW_CHANGE_UUID 4040 +#define ER_GRP_RPL_VIEW_CHANGE_UUID_FAIL_GET_VARIABLE 4041 +#define ER_WARN_ADUIT_LOG_MAX_SIZE_AND_PRUNE_SECONDS 4042 +#define ER_WARN_ADUIT_LOG_MAX_SIZE_CLOSE_TO_ROTATE_ON_SIZE 4043 +#define ER_KERBEROS_CREATE_USER 4044 +#define ER_INSTALL_PLUGIN_CONFLICT_CLIENT 4045 +#define ER_DA_ERROR_LOG_COMPONENT_FLUSH_FAILED 4046 +#define ER_WARN_SQL_AFTER_MTS_GAPS_GAP_NOT_CALCULATED 4047 +#define ER_INVALID_ASSIGNMENT_TARGET 4048 +#define ER_OPERATION_NOT_ALLOWED_ON_GR_SECONDARY 4049 +#define ER_GRP_RPL_FAILOVER_CHANNEL_STATUS_PROPAGATION 4050 +#define ER_WARN_AUDIT_LOG_FORMAT_UNIX_TIMESTAMP_ONLY_WHEN_JSON 4051 +#define ER_INVALID_MFA_PLUGIN_SPECIFIED 4052 +#define ER_IDENTIFIED_BY_UNSUPPORTED 4053 +#define ER_INVALID_PLUGIN_FOR_REGISTRATION 4054 +#define ER_PLUGIN_REQUIRES_REGISTRATION 4055 +#define ER_MFA_METHOD_EXISTS 4056 +#define ER_MFA_METHOD_NOT_EXISTS 4057 +#define ER_AUTHENTICATION_POLICY_MISMATCH 4058 +#define ER_PLUGIN_REGISTRATION_DONE 4059 +#define ER_INVALID_USER_FOR_REGISTRATION 4060 +#define ER_USER_REGISTRATION_FAILED 4061 +#define ER_MFA_METHODS_INVALID_ORDER 4062 +#define ER_MFA_METHODS_IDENTICAL 4063 +#define ER_INVALID_MFA_OPERATIONS_FOR_PASSWORDLESS_USER 4064 +#define ER_CHANGE_REPLICATION_SOURCE_NO_OPTIONS_FOR_GTID_ONLY 4065 +#define ER_CHANGE_REP_SOURCE_CANT_DISABLE_REQ_ROW_FORMAT_WITH_GTID_ONLY 4066 +#define ER_CHANGE_REP_SOURCE_CANT_DISABLE_AUTO_POSITION_WITH_GTID_ONLY 4067 +#define ER_CHANGE_REP_SOURCE_CANT_DISABLE_GTID_ONLY_WITHOUT_POSITIONS 4068 +#define ER_CHANGE_REP_SOURCE_CANT_DISABLE_AUTO_POS_WITHOUT_POSITIONS 4069 +#define ER_CHANGE_REP_SOURCE_GR_CHANNEL_WITH_GTID_MODE_NOT_ON 4070 +#define ER_CANT_USE_GTID_ONLY_WITH_GTID_MODE_NOT_ON 4071 +#define ER_WARN_C_DISABLE_GTID_ONLY_WITH_SOURCE_AUTO_POS_INVALID_POS 4072 +#define ER_DA_SSL_FIPS_MODE_ERROR 4073 +#define ER_VALUE_OUT_OF_RANGE 4074 +#define ER_FULLTEXT_WITH_ROLLUP 4075 +#define ER_REGEXP_MISSING_RESOURCE 4076 +#define ER_WARN_REGEXP_USING_DEFAULT 4077 +#define ER_REGEXP_MISSING_FILE 4078 +#define ER_WARN_DEPRECATED_COLLATION 4079 +#define ER_CONCURRENT_PROCEDURE_USAGE 4080 +#define ER_DA_GLOBAL_CONN_LIMIT 4081 +#define ER_DA_CONN_LIMIT 4082 +#define ER_ALTER_OPERATION_NOT_SUPPORTED_REASON_COLUMN_TYPE_INSTANT 4083 +#define ER_WARN_SF_UDF_NAME_COLLISION 4084 +#define ER_CANNOT_PURGE_BINLOG_WITH_BACKUP_LOCK 4085 +#define ER_TOO_MANY_WINDOWS 4086 +#define ER_MYSQLBACKUP_CLIENT_MSG 4087 +#define ER_COMMENT_CONTAINS_INVALID_STRING 4088 +#define ER_DEFINITION_CONTAINS_INVALID_STRING 4089 +#define ER_CANT_EXECUTE_COMMAND_WITH_ASSIGNED_GTID_NEXT 4090 +#define ER_XA_TEMP_TABLE 4091 +#define ER_INNODB_MAX_ROW_VERSION 4092 +//#define OBSOLETE_ER_INNODB_INSTANT_ADD_NOT_SUPPORTED_MAX_SIZE 4093 +#define ER_OPERATION_NOT_ALLOWED_WHILE_PRIMARY_CHANGE_IS_RUNNING 4094 +#define ER_WARN_DEPRECATED_DATETIME_DELIMITER 4095 +#define ER_WARN_DEPRECATED_SUPERFLUOUS_DELIMITER 4096 +#define ER_CANNOT_PERSIST_SENSITIVE_VARIABLES 4097 +#define ER_WARN_CANNOT_SECURELY_PERSIST_SENSITIVE_VARIABLES 4098 +#define ER_WARN_TRG_ALREADY_EXISTS 4099 +#define ER_IF_NOT_EXISTS_UNSUPPORTED_TRG_EXISTS_ON_DIFFERENT_TABLE 4100 +#define ER_IF_NOT_EXISTS_UNSUPPORTED_UDF_NATIVE_FCT_NAME_COLLISION 4101 +#define ER_SET_PASSWORD_AUTH_PLUGIN_ERROR 4102 +//#define OBSOLETE_ER_REDUCED_DBLWR_FILE_CORRUPTED 4103 +//#define OBSOLETE_ER_REDUCED_DBLWR_PAGE_FOUND 4104 +#define ER_SRS_INVALID_LATITUDE_OF_ORIGIN 4105 +#define ER_SRS_INVALID_LONGITUDE_OF_ORIGIN 4106 +#define ER_SRS_UNUSED_PROJ_PARAMETER_PRESENT 4107 +#define ER_GIPK_COLUMN_EXISTS 4108 +#define ER_GIPK_FAILED_AUTOINC_COLUMN_EXISTS 4109 +#define ER_GIPK_COLUMN_ALTER_NOT_ALLOWED 4110 +#define ER_DROP_PK_COLUMN_TO_DROP_GIPK 4111 +#define ER_CREATE_SELECT_WITH_GIPK_DISALLOWED_IN_SBR 4112 +//#define OBSOLETE_ER_DA_EXPIRE_LOGS_DAYS_IGNORED 4113 +#define ER_CTE_RECURSIVE_NOT_UNION 4114 +#define ER_COMMAND_BACKEND_FAILED_TO_FETCH_SECURITY_CTX 4115 +#define ER_COMMAND_SERVICE_BACKEND_FAILED 4116 +#define ER_CLIENT_FILE_PRIVILEGE_FOR_REPLICATION_CHECKS 4117 +#define ER_GROUP_REPLICATION_FORCE_MEMBERS_COMMAND_FAILURE 4118 +#define ER_WARN_DEPRECATED_IDENT 4119 +#define ER_INTERSECT_ALL_MAX_DUPLICATES_EXCEEDED 4120 +#define ER_TP_QUERY_THRS_PER_GRP_EXCEEDS_TXN_THR_LIMIT 4121 +#define ER_BAD_TIMESTAMP_FORMAT 4122 +#define ER_SHAPE_PRIDICTION_UDF 4123 +#define ER_SRS_INVALID_HEIGHT 4124 +#define ER_SRS_INVALID_SCALING 4125 +#define ER_SRS_INVALID_ZONE_WIDTH 4126 +#define ER_SRS_INVALID_LATITUDE_POLAR_STERE_VAR_A 4127 +#define ER_WARN_DEPRECATED_CLIENT_NO_SCHEMA_OPTION 4128 +#define ER_TABLE_NOT_EMPTY 4129 +#define ER_TABLE_NO_PRIMARY_KEY 4130 +#define ER_TABLE_IN_SHARED_TABLESPACE 4131 +#define ER_INDEX_OTHER_THAN_PK 4132 +#define ER_LOAD_BULK_DATA_UNSORTED 4133 +#define ER_BULK_EXECUTOR_ERROR 4134 +#define ER_BULK_READER_LIBCURL_INIT_FAILED 4135 +#define ER_BULK_READER_LIBCURL_ERROR 4136 +#define ER_BULK_READER_SERVER_ERROR 4137 +#define ER_BULK_READER_COMMUNICATION_ERROR 4138 +#define ER_BULK_LOAD_DATA_FAILED 4139 +#define ER_BULK_LOADER_COLUMN_TOO_BIG_FOR_LEFTOVER_BUFFER 4140 +#define ER_BULK_LOADER_COMPONENT_ERROR 4141 +#define ER_BULK_LOADER_FILE_CONTAINS_LESS_LINES_THAN_IGNORE_CLAUSE 4142 +#define ER_BULK_PARSER_MISSING_ENCLOSED_BY 4143 +#define ER_BULK_PARSER_ROW_BUFFER_MAX_TOTAL_COLS_EXCEEDED 4144 +#define ER_BULK_PARSER_COPY_BUFFER_SIZE_EXCEEDED 4145 +#define ER_BULK_PARSER_UNEXPECTED_END_OF_INPUT 4146 +#define ER_BULK_PARSER_UNEXPECTED_ROW_TERMINATOR 4147 +#define ER_BULK_PARSER_UNEXPECTED_CHAR_AFTER_ENDING_ENCLOSED_BY 4148 +#define ER_BULK_PARSER_UNEXPECTED_CHAR_AFTER_NULL_ESCAPE 4149 +#define ER_BULK_PARSER_UNEXPECTED_CHAR_AFTER_COLUMN_TERMINATOR 4150 +#define ER_BULK_PARSER_INCOMPLETE_ESCAPE_SEQUENCE 4151 +#define ER_LOAD_BULK_DATA_FAILED 4152 +#define ER_LOAD_BULK_DATA_WRONG_VALUE_FOR_FIELD 4153 +#define ER_LOAD_BULK_DATA_WARN_NULL_TO_NOTNULL 4154 +#define ER_REQUIRE_TABLE_PRIMARY_KEY_CHECK_GENERATE_WITH_GR 4155 +#define ER_CANT_CHANGE_SYS_VAR_IN_READ_ONLY_MODE 4156 +#define ER_INNODB_INSTANT_ADD_DROP_NOT_SUPPORTED_MAX_SIZE 4157 +#define ER_INNODB_INSTANT_ADD_NOT_SUPPORTED_MAX_FIELDS 4158 +#define ER_CANT_SET_PERSISTED 4159 +#define ER_INSTALL_COMPONENT_SET_NULL_VALUE 4160 +#define ER_INSTALL_COMPONENT_SET_UNUSED_VALUE 4161 +#define ER_WARN_DEPRECATED_USER_DEFINED_COLLATIONS 4162 +#define ER_USER_LOCK_OVERLONG_NAME 4163 +#define ER_WARN_NO_SPACE_VERSION_COMMENT 4164 +#define ER_VALIDATE_PASSWORD_INSUFFICIENT_CHANGED_CHARACTERS 4165 +#define ER_WARN_DEPRECATED_WITH_NOTE 4166 +#define ER_LANGUAGE_COMPONENT 6000 +#define ER_LANGUAGE_COMPONENT_NOT_AVAILABLE 6001 +#define ER_LANGUAGE_COMPONENT_UNSUPPORTED_LANGUAGE 6002 +#define ER_LANGUAGE_COMPONENT_CANNOT_UNINSTALL 6003 +#define ER_SP_NO_ALTER_LANGUAGE 6004 +#define ER_EXPLAIN_INTO_ANALYZE_NOT_SUPPORTED 6005 +#define ER_EXPLAIN_INTO_IMPLICIT_FORMAT_NOT_SUPPORTED 6006 +#define ER_EXPLAIN_INTO_FORMAT_NOT_SUPPORTED 6007 +#define ER_NULL_CANT_BE_PERSISTED_FOR_READONLY 6008 +#define ER_EXPLAIN_INTO_FOR_CONNECTION_NOT_SUPPORTED 6009 +#define ER_INNODB_IMPORT_WRONG_DROPPED_ENUM_LENGTH 6010 +#define ER_INNODB_IMPORT_WRONG_NUMBER_OF_INDEXES_ZERO 6011 +#define ER_INNODB_IMPORT_WRONG_NUMBER_OF_INDEXES_TOO_HIGH 6012 +#define ER_INNODB_IMPORT_DROP_COL_METADATA_MISMATCH 6013 +#define ER_INNODB_IMPORT_ENUM_NULL_TERMINATOR_MISSING 6014 +#define ER_SIMULATED_INJECTION_ERROR 6015 +#define ER_WARN_DEPRECATED_DYNAMIC_PRIV_IN_GRANT 6016 +#define ER_BULK_MULTI_READER_OPEN_FILE_FAILED 6017 +#define ER_BULK_MULTI_READER_READ_FILE_FAILED 6018 +#define ER_BULK_MERGE_INVALID_CHUNK 6019 +#define ER_BULK_MERGE_NOT_ALL_CHUNKS_CONSUMED 6020 +#define ER_BULK_WRITER_LIBCURL_INIT_FAILED 6021 +#define ER_BULK_WRITER_LIBCURL_ERROR 6022 +#define ER_BULK_SORTING_LOADER_WRITE 6023 +#define ER_BULK_SORTING_LOADER_WAIT 6024 +#define ER_BULK_READER_OPEN_FILE_FAILED 6025 +#define ER_BULK_LOAD_TABLE_HAS_INSTANT_COLS 6026 +#define ER_BULK_LOAD_RESOURCE 6027 +#define ER_BULK_LOAD_SECONDARY_ENGINE 6028 +#define ER_BULK_READER_ERROR 6029 +#define ER_BULK_READER_FILE_DOESNT_EXIST 6030 +#define ER_BULK_READER_COULDNT_RESOLVE_HOST 6031 +#define ER_START_REPLICA_CHANNEL_INVALID_CONFIGURATION 6032 +#define ER_CANNOT_EXECUTE_IN_PRIMARY 6033 +#define ER_TOO_MANY_GROUP_BY_MODIFIER_BRANCHES 6034 +#define ER_WARN_DEPRECATED_ENGINE_SYNTAX_NO_REPLACEMENT 6035 +#define ER_QUALIFY_WITHOUT_WINDOW_FUNCTION 6036 +#define ER_SUPPORTED_ONLY_WITH_HYPERGRAPH 6037 +#define ER_SPECIFIC_ACCESS_DENIED 6038 +#define ER_CANT_SET_GTID_NEXT_TO_AUTOMATIC_TAGGED_WHEN_GTID_MODE_IS_OFF 6039 +#define ER_GTID_NEXT_TAG_GTID_MODE_OFF 6040 +#define ER_LH_COL_NOT_NULLABLE 6041 +#define ER_LH_WARN_COL_MISSING_NOT_NULLABLE 6042 +#define ER_LH_COL_IS_EMPTY 6043 +#define ER_LH_COL_IS_EMPTY_WARN 6044 +#define ER_LH_BAD_VALUE 6045 +#define ER_LH_DECIMAL_UNKNOWN_ERR 6046 +#define ER_LH_DECIMAL_OOM_ERR 6047 +#define ER_LH_WARN_DECIMAL_ROUNDING 6048 +#define ER_LH_DECIMAL_PRECISION_EXCEEDS_SCHEMA 6049 +#define ER_LH_EXCEEDS_MIN 6050 +#define ER_LH_EXCEEDS_MAX 6051 +#define ER_LH_WARN_EXCEEDS_MIN_TRUNCATING 6052 +#define ER_LH_WARN_EXCEEDS_MAX_TRUNCATING 6053 +#define ER_LH_REAL_IS_NAN 6054 +#define ER_LH_OUT_OF_RANGE 6055 +#define ER_LH_DATETIME_FORMAT 6056 +#define ER_LH_WARN_TRUNCATED 6057 +#define ER_LH_CANNOT_CONVERT_STRING 6058 +#define ER_LH_RESOURCE_PRINCIPAL_ERR 6059 +#define ER_LH_AWS_AUTH_ERR 6060 +#define ER_LH_CSV_PARSING_ERR 6061 +#define ER_LH_COLUMN_MISMATCH_ERR 6062 +#define ER_LH_COLUMN_MAX_ERR 6063 +#define ER_LH_CHARSET_UNSUPPORTED 6064 +#define ER_LH_PARQUET_DECIMAL_CONVERSION_ERR 6065 +#define ER_LH_STRING_TOO_LONG 6066 +#define ER_LH_RESOURCE_PRINCIPAL_BUCKET_ERR 6067 +#define ER_LH_NO_FILES_FOUND 6068 +#define ER_LH_EMPTY_FILE 6069 +#define ER_LH_DUPLICATE_FILE 6070 +#define ER_LH_AVRO_SCHEMA_DEPTH_EXCEEDS_MAX 6071 +#define ER_LH_AVRO_HEADER_MISMATCH 6072 +#define ER_LH_AVRO_ENUM_CANNOT_CONVERT_CHARSET 6073 +#define ER_LH_AVRO_ENUM_MISMATCH 6074 +#define ER_LH_AVRO_TYPE_CANNOT_CONVERT 6075 +#define ER_LH_AVRO_FILE_ENDS_UNEXPECTEDLY 6076 +#define ER_LH_AVRO_FILE_DATA_CORRUPT 6077 +#define ER_LH_AVRO_INVALID_UNION 6078 +#define ER_LH_AVRO_INVALID_BLOCK_SIZE 6079 +#define ER_LH_AVRO_INVALID_BLOCK_RECORD_COUNT 6080 +#define ER_LH_FORMAT_HEADER_NO_MAGIC_BYTES 6081 +#define ER_LH_AVRO_HEADER_METADATA_ERR 6082 +#define ER_LH_AVRO_HEADER_NO_SCHEMA 6083 +#define ER_LH_AVRO_NO_CODEC_IN_HEADER 6084 +#define ER_LH_AVRO_INVALID_NAME_IN_SCHEMA 6085 +#define ER_LH_AVRO_DECODING_ERR 6086 +#define ER_LH_PARQUET_NON_UTF8_FILE_ENC 6087 +#define ER_LH_PARQUET_SCHEMA_MISMATCH 6088 +#define ER_LH_PARQUET_ROW_GROUP_SIZE_EXCEEDS_MAX 6089 +#define ER_LH_PARQUET_CANNOT_LOCATE_OFFSET 6090 +#define ER_LH_PARQUET_TYPE_CANNOT_CONVERT 6091 +#define ER_LH_PARQUET_CANNOT_LOCATE_SCHEMA 6092 +#define ER_LH_INFER_SCHEMA_MISMATCH 6093 +#define ER_LH_OOM 6094 +#define ER_LH_WARN_INFER_SKIPPED_LINES 6095 +#define ER_LH_WARN_INFER_SKIPPED_FILES 6096 +#define ER_LH_INFER_FILE_HAS_NO_DATA 6097 +#define ER_LH_INFER_NO_DATA 6098 +#define ER_LH_INFER_NO_FILES 6099 +#define ER_LH_WARN_INFER_USE_DEFAULT_COL_NAMES 6100 +#define ER_LH_PARQUET_CANNOT_READ_HEADER 6101 +#define ER_LH_INFER_WARN_GOT_EXCEPTION 6102 +#define ER_LH_AVRO_CANNOT_PARSE_HEADER 6103 +#define ER_LH_PARQUET_CANT_OPEN_FILE 6104 +#define ER_LH_TOO_LARGE_VALUE_ERR 6105 +#define ER_LH_TOO_LARGE_ROW_ERR 6106 +#define ER_TABLESAMPLE_PERCENTAGE 6107 +#define ER_TABLESAMPLE_ONLY_ON_BASE_TABLES 6108 +//#define OBSOLETE_ER_PARAMETER_INDEX_OUT_OF_RANGE 6109 +#define ER_RESULT_SIZE_LIMIT_EXCEEDED 6110 +#define ER_LANGUAGE_COMPONENT_INTERNAL 6111 +#define ER_LANGUAGE_COMPONENT_CONCURRENCY_LIMIT 6112 +#define ER_LANGUAGE_COMPONENT_RUNTIME 6113 +#define ER_LANGUAGE_COMPONENT_TIMEZONE 6114 +#define ER_LANGUAGE_COMPONENT_KEYWORD 6115 +#define ER_LANGUAGE_COMPONENT_SET_SYSTEM_VARIABLE 6116 +#define ER_LANGUAGE_COMPONENT_UNSUPPORTED_TYPE 6117 +#define ER_LANGUAGE_COMPONENT_CONVERSION 6118 +#define ER_WARN_SP_STATEMENT_PARTIALLY_EXECUTED 6119 +#define ER_STMT_EXECUTION_NOT_ALLOWED_WITHIN_SP_OR_TRG_OR_UDF 6120 +#define ER_LH_JSON_PARSING 6121 +#define ER_ENGINE_CANNOT_BE_DEFAULT 6122 +#define ER_PARTITION_PREFIX_KEY_NOT_SUPPORTED 6123 +#define ER_WARN_DEPRECATED_NON_STANDARD_KEY 6124 +#define ER_FK_NO_UNIQUE_INDEX_PARENT 6125 +#define ER_ACCESS_DENIED_NO_PROXY_GRANT 6126 +#define ER_ACCESS_DENIED_NO_PROXY 6127 +#define ER_LH_USER_DATA_ACCESS_FAILED 6128 +#define ER_BULK_READER_ZSTD_ERROR 6129 +#define ER_BULK_PARSER_ERROR 6130 +#define ER_LH_INVALID_JSON_FILE_FORMAT_SCHEMA 6131 +#define ER_LH_INFER_JSON_INVALID_SCHEMA 6132 +#define ER_LH_JSON_FILE_FORMAT_WARN_INFER_SCHEMA 6133 +#define ER_NON_SCALAR_USED_AS_KEY 6134 +#define ER_INCOMPATIBLE_TYPE_AGG 6135 +#define ER_DATA_INCOMPATIBLE_WITH_VECTOR 6136 +#define ER_EXCEEDS_VECTOR_MAX_DIMENSIONS 6137 +#define ER_TO_VECTOR_CONVERSION 6138 +#define ER_EXTERNAL_UNSUPPORTED_INDEX_ALGORITHM 6139 +#define ER_PARSER_TRACE 10000 +#define ER_BOOTSTRAP_CANT_THREAD 10001 +#define ER_TRIGGER_INVALID_VALUE 10002 +#define ER_OPT_WRONG_TREE 10003 +#define ER_DD_FAILSAFE 10004 +#define ER_DD_NO_WRITES_NO_REPOPULATION 10005 +#define ER_DD_VERSION_FOUND 10006 +#define ER_DD_VERSION_INSTALLED 10007 +#define ER_DD_VERSION_UNSUPPORTED 10008 +//#define OBSOLETE_ER_LOG_SYSLOG_FACILITY_FAIL 10009 +#define ER_LOG_SYSLOG_CANNOT_OPEN 10010 +#define ER_LOG_SLOW_CANNOT_OPEN 10011 +#define ER_LOG_GENERAL_CANNOT_OPEN 10012 +#define ER_LOG_CANNOT_WRITE 10013 +#define ER_RPL_ZOMBIE_ENCOUNTERED 10014 +#define ER_RPL_GTID_TABLE_CANNOT_OPEN 10015 +#define ER_SYSTEM_SCHEMA_NOT_FOUND 10016 +#define ER_DD_INIT_UPGRADE_FAILED 10017 +#define ER_VIEW_UNKNOWN_CHARSET_OR_COLLATION 10018 +#define ER_DD_VIEW_CANT_ALLOC_CHARSET 10019 +#define ER_DD_INIT_FAILED 10020 +#define ER_DD_UPDATING_PLUGIN_MD_FAILED 10021 +//#define OBSOLETE_ER_DD_POPULATING_TABLES_FAILED 10022 +#define ER_DD_VIEW_CANT_CREATE 10023 +#define ER_DD_METADATA_NOT_FOUND 10024 +#define ER_DD_CACHE_NOT_EMPTY_AT_SHUTDOWN 10025 +#define ER_DD_OBJECT_REMAINS 10026 +#define ER_DD_OBJECT_REMAINS_IN_RELEASER 10027 +#define ER_DD_OBJECT_RELEASER_REMAINS 10028 +#define ER_DD_CANT_GET_OBJECT_KEY 10029 +#define ER_DD_CANT_CREATE_OBJECT_KEY 10030 +#define ER_CANT_CREATE_HANDLE_MGR_THREAD 10031 +#define ER_RPL_REPO_HAS_GAPS 10032 +#define ER_INVALID_VALUE_FOR_ENFORCE_GTID_CONSISTENCY 10033 +#define ER_CHANGED_ENFORCE_GTID_CONSISTENCY 10034 +#define ER_CHANGED_GTID_MODE 10035 +#define ER_DISABLED_STORAGE_ENGINE_AS_DEFAULT 10036 +#define ER_DEBUG_SYNC_HIT 10037 +#define ER_DEBUG_SYNC_EXECUTED 10038 +#define ER_DEBUG_SYNC_THREAD_MAX 10039 +#define ER_DEBUG_SYNC_OOM 10040 +#define ER_CANT_INIT_TC_LOG 10041 +#define ER_EVENT_CANT_INIT_QUEUE 10042 +#define ER_EVENT_PURGING_QUEUE 10043 +#define ER_EVENT_LAST_EXECUTION 10044 +#define ER_EVENT_MESSAGE_STACK 10045 +#define ER_EVENT_EXECUTION_FAILED 10046 +#define ER_CANT_INIT_SCHEDULER_THREAD 10047 +#define ER_SCHEDULER_STOPPED 10048 +#define ER_CANT_CREATE_SCHEDULER_THREAD 10049 +#define ER_SCHEDULER_WAITING 10050 +#define ER_SCHEDULER_STARTED 10051 +#define ER_SCHEDULER_STOPPING_FAILED_TO_GET_EVENT 10052 +#define ER_SCHEDULER_STOPPING_FAILED_TO_CREATE_WORKER 10053 +#define ER_SCHEDULER_KILLING 10054 +#define ER_UNABLE_TO_RESOLVE_IP 10055 +#define ER_UNABLE_TO_RESOLVE_HOSTNAME 10056 +#define ER_HOSTNAME_RESEMBLES_IPV4 10057 +#define ER_HOSTNAME_DOESNT_RESOLVE_TO 10058 +#define ER_ADDRESSES_FOR_HOSTNAME_HEADER 10059 +#define ER_ADDRESSES_FOR_HOSTNAME_LIST_ITEM 10060 +#define ER_TRG_WITHOUT_DEFINER 10061 +#define ER_TRG_NO_CLIENT_CHARSET 10062 +#define ER_PARSING_VIEW 10063 +#define ER_COMPONENTS_INFRASTRUCTURE_BOOTSTRAP 10064 +#define ER_COMPONENTS_INFRASTRUCTURE_SHUTDOWN 10065 +#define ER_COMPONENTS_PERSIST_LOADER_BOOTSTRAP 10066 +#define ER_DEPART_WITH_GRACE 10067 +#define ER_CA_SELF_SIGNED 10068 +#define ER_SSL_LIBRARY_ERROR 10069 +#define ER_NO_THD_NO_UUID 10070 +#define ER_UUID_SALT 10071 +#define ER_UUID_IS 10072 +#define ER_UUID_INVALID 10073 +#define ER_UUID_SCRUB 10074 +#define ER_CREATING_NEW_UUID 10075 +#define ER_CANT_CREATE_UUID 10076 +#define ER_UNKNOWN_UNSUPPORTED_STORAGE_ENGINE 10077 +#define ER_SECURE_AUTH_VALUE_UNSUPPORTED 10078 +#define ER_INVALID_INSTRUMENT 10079 +#define ER_INNODB_MANDATORY 10080 +//#define OBSOLETE_ER_INNODB_CANNOT_BE_IGNORED 10081 +//#define OBSOLETE_ER_OLD_PASSWORDS_NO_MIDDLE_GROUND 10082 +#define ER_VERBOSE_REQUIRES_HELP 10083 +#define ER_POINTLESS_WITHOUT_SLOWLOG 10084 +#define ER_WASTEFUL_NET_BUFFER_SIZE 10085 +#define ER_DEPRECATED_TIMESTAMP_IMPLICIT_DEFAULTS 10086 +#define ER_FT_BOOL_SYNTAX_INVALID 10087 +#define ER_CREDENTIALLESS_AUTO_USER_BAD 10088 +#define ER_CONNECTION_HANDLING_OOM 10089 +#define ER_THREAD_HANDLING_OOM 10090 +#define ER_CANT_CREATE_TEST_FILE 10091 +#define ER_CANT_CREATE_PID_FILE 10092 +#define ER_CANT_REMOVE_PID_FILE 10093 +#define ER_CANT_CREATE_SHUTDOWN_THREAD 10094 +#define ER_SEC_FILE_PRIV_CANT_ACCESS_DIR 10095 +#define ER_SEC_FILE_PRIV_IGNORED 10096 +#define ER_SEC_FILE_PRIV_EMPTY 10097 +#define ER_SEC_FILE_PRIV_NULL 10098 +#define ER_SEC_FILE_PRIV_DIRECTORY_INSECURE 10099 +#define ER_SEC_FILE_PRIV_CANT_STAT 10100 +#define ER_SEC_FILE_PRIV_DIRECTORY_PERMISSIONS 10101 +#define ER_SEC_FILE_PRIV_ARGUMENT_TOO_LONG 10102 +#define ER_CANT_CREATE_NAMED_PIPES_THREAD 10103 +#define ER_CANT_CREATE_TCPIP_THREAD 10104 +#define ER_CANT_CREATE_SHM_THREAD 10105 +#define ER_CANT_CREATE_INTERRUPT_THREAD 10106 +#define ER_WRITABLE_CONFIG_REMOVED 10107 +#define ER_CORE_VALUES 10108 +#define ER_WRONG_DATETIME_SPEC 10109 +#define ER_RPL_BINLOG_FILTERS_OOM 10110 +#define ER_KEYCACHE_OOM 10111 +#define ER_CONFIRMING_THE_FUTURE 10112 +#define ER_BACK_IN_TIME 10113 +#define ER_FUTURE_DATE 10114 +#define ER_UNSUPPORTED_DATE 10115 +#define ER_STARTING_AS 10116 +#define ER_SHUTTING_DOWN_REPLICA_THREADS 10117 +#define ER_DISCONNECTING_REMAINING_CLIENTS 10118 +#define ER_ABORTING 10119 +#define ER_BINLOG_END 10120 +#define ER_CALL_ME_LOCALHOST 10121 +#define ER_USER_REQUIRES_ROOT 10122 +#define ER_REALLY_RUN_AS_ROOT 10123 +#define ER_USER_WHAT_USER 10124 +#define ER_TRANSPORTS_WHAT_TRANSPORTS 10125 +#define ER_FAIL_SETGID 10126 +#define ER_FAIL_SETUID 10127 +#define ER_FAIL_SETREGID 10128 +#define ER_FAIL_SETREUID 10129 +#define ER_FAIL_CHROOT 10130 +#define ER_WIN_LISTEN_BUT_HOW 10131 +#define ER_NOT_RIGHT_NOW 10132 +#define ER_FIXING_CLIENT_CHARSET 10133 +#define ER_OOM 10134 +#define ER_FAILED_TO_LOCK_MEM 10135 +#define ER_MYINIT_FAILED 10136 +#define ER_BEG_INITFILE 10137 +#define ER_END_INITFILE 10138 +#define ER_CHANGED_MAX_OPEN_FILES 10139 +#define ER_CANT_INCREASE_MAX_OPEN_FILES 10140 +#define ER_CHANGED_MAX_CONNECTIONS 10141 +#define ER_CHANGED_TABLE_OPEN_CACHE 10142 +#define ER_THE_USER_ABIDES 10143 +#define ER_RPL_CANT_ADD_DO_TABLE 10144 +#define ER_RPL_CANT_ADD_IGNORE_TABLE 10145 +#define ER_TRACK_VARIABLES_BOGUS 10146 +#define ER_EXCESS_ARGUMENTS 10147 +#define ER_VERBOSE_HINT 10148 +#define ER_CANT_READ_ERRMSGS 10149 +#define ER_CANT_INIT_DBS 10150 +#define ER_LOG_OUTPUT_CONTRADICTORY 10151 +#define ER_NO_CSV_NO_LOG_TABLES 10152 +#define ER_RPL_REWRITEDB_MISSING_ARROW 10153 +#define ER_RPL_REWRITEDB_EMPTY_FROM 10154 +#define ER_RPL_REWRITEDB_EMPTY_TO 10155 +#define ER_LOG_FILES_GIVEN_LOG_OUTPUT_IS_TABLE 10156 +#define ER_LOG_FILE_INVALID 10157 +#define ER_LOWER_CASE_TABLE_NAMES_CS_DD_ON_CI_FS_UNSUPPORTED 10158 +#define ER_LOWER_CASE_TABLE_NAMES_USING_2 10159 +#define ER_LOWER_CASE_TABLE_NAMES_USING_0 10160 +#define ER_NEED_LOG_BIN 10161 +#define ER_NEED_FILE_INSTEAD_OF_DIR 10162 +#define ER_LOG_BIN_BETTER_WITH_NAME 10163 +#define ER_BINLOG_NEEDS_SERVERID 10164 +#define ER_RPL_CANT_MAKE_PATHS 10165 +#define ER_CANT_INITIALIZE_GTID 10166 +#define ER_CANT_INITIALIZE_EARLY_PLUGINS 10167 +#define ER_CANT_INITIALIZE_BUILTIN_PLUGINS 10168 +#define ER_CANT_INITIALIZE_DYNAMIC_PLUGINS 10169 +#define ER_PERFSCHEMA_INIT_FAILED 10170 +#define ER_STACKSIZE_UNEXPECTED 10171 +//#define OBSOLETE_ER_CANT_SET_DATADIR 10172 +#define ER_CANT_STAT_DATADIR 10173 +#define ER_CANT_CHOWN_DATADIR 10174 +#define ER_CANT_SET_UP_PERSISTED_VALUES 10175 +#define ER_CANT_SAVE_GTIDS 10176 +//#define OBSOLETE_ER_AUTH_CANT_SET_DEFAULT_PLUGIN 10177 +#define ER_CANT_JOIN_SHUTDOWN_THREAD 10178 +#define ER_CANT_HASH_DO_AND_IGNORE_RULES 10179 +#define ER_CANT_OPEN_CA 10180 +#define ER_CANT_ACCESS_CAPATH 10181 +#define ER_SSL_TRYING_DATADIR_DEFAULTS 10182 +#define ER_AUTO_OPTIONS_FAILED 10183 +#define ER_CANT_INIT_TIMER 10184 +#define ER_SERVERID_TOO_LARGE 10185 +#define ER_DEFAULT_SE_UNAVAILABLE 10186 +#define ER_CANT_OPEN_ERROR_LOG 10187 +#define ER_INVALID_ERROR_LOG_NAME 10188 +#define ER_RPL_INFINITY_DENIED 10189 +#define ER_RPL_INFINITY_IGNORED 10190 +//#define OBSOLETE_ER_NDB_TABLES_NOT_READY 10191 +#define ER_TABLE_CHECK_INTACT 10192 +#define ER_DD_TABLESPACE_NOT_FOUND 10193 +#define ER_DD_TRG_CONNECTION_COLLATION_MISSING 10194 +#define ER_DD_TRG_DB_COLLATION_MISSING 10195 +#define ER_DD_TRG_DEFINER_OOM 10196 +#define ER_DD_TRG_FILE_UNREADABLE 10197 +#define ER_TRG_CANT_PARSE 10198 +#define ER_DD_TRG_CANT_ADD 10199 +#define ER_DD_CANT_RESOLVE_VIEW 10200 +#define ER_DD_VIEW_WITHOUT_DEFINER 10201 +#define ER_PLUGIN_INIT_FAILED 10202 +#define ER_RPL_TRX_DELEGATES_INIT_FAILED 10203 +#define ER_RPL_BINLOG_STORAGE_DELEGATES_INIT_FAILED 10204 +#define ER_RPL_BINLOG_TRANSMIT_DELEGATES_INIT_FAILED 10205 +#define ER_RPL_BINLOG_RELAY_DELEGATES_INIT_FAILED 10206 +#define ER_RPL_PLUGIN_FUNCTION_FAILED 10207 +#define ER_SQL_HA_READ_FAILED 10208 +#define ER_SR_BOGUS_VALUE 10209 +#define ER_SR_INVALID_CONTEXT 10210 +#define ER_READING_TABLE_FAILED 10211 +#define ER_DES_FILE_WRONG_KEY 10212 +//#define OBSOLETE_ER_CANT_SET_PERSISTED 10213 +#define ER_JSON_PARSE_ERROR 10214 +#define ER_CONFIG_OPTION_WITHOUT_GROUP 10215 +#define ER_VALGRIND_DO_QUICK_LEAK_CHECK 10216 +#define ER_VALGRIND_COUNT_LEAKS 10217 +#define ER_LOAD_DATA_INFILE_FAILED_IN_UNEXPECTED_WAY 10218 +#define ER_UNKNOWN_ERROR_NUMBER 10219 +#define ER_UDF_CANT_ALLOC_FOR_STRUCTURES 10220 +#define ER_UDF_CANT_ALLOC_FOR_FUNCTION 10221 +#define ER_UDF_INVALID_ROW_IN_FUNCTION_TABLE 10222 +#define ER_UDF_CANT_OPEN_FUNCTION_TABLE 10223 +#define ER_XA_RECOVER_FOUND_TRX_IN_SE 10224 +#define ER_XA_RECOVER_FOUND_XA_TRX 10225 +//#define OBSOLETE_ER_XA_IGNORING_XID 10226 +//#define OBSOLETE_ER_XA_COMMITTING_XID 10227 +//#define OBSOLETE_ER_XA_ROLLING_BACK_XID 10228 +#define ER_XA_STARTING_RECOVERY 10229 +#define ER_XA_NO_MULTI_2PC_HEURISTIC_RECOVER 10230 +#define ER_XA_RECOVER_EXPLANATION 10231 +#define ER_XA_RECOVERY_DONE 10232 +#define ER_TRX_GTID_COLLECT_REJECT 10233 +#define ER_SQL_AUTHOR_DEFAULT_ROLES_FAIL 10234 +#define ER_SQL_USER_TABLE_CREATE_WARNING 10235 +#define ER_SQL_USER_TABLE_ALTER_WARNING 10236 +#define ER_ROW_IN_WRONG_PARTITION_PLEASE_REPAIR 10237 +#define ER_MYISAM_CRASHED_ERROR_IN_THREAD 10238 +#define ER_MYISAM_CRASHED_ERROR_IN 10239 +#define ER_TOO_MANY_STORAGE_ENGINES 10240 +#define ER_SE_TYPECODE_CONFLICT 10241 +#define ER_TRX_WRITE_SET_OOM 10242 +#define ER_HANDLERTON_OOM 10243 +#define ER_CONN_SHM_LISTENER 10244 +#define ER_CONN_SHM_CANT_CREATE_SERVICE 10245 +#define ER_CONN_SHM_CANT_CREATE_CONNECTION 10246 +#define ER_CONN_PIP_CANT_CREATE_EVENT 10247 +#define ER_CONN_PIP_CANT_CREATE_PIPE 10248 +#define ER_CONN_PER_THREAD_NO_THREAD 10249 +#define ER_CONN_TCP_NO_SOCKET 10250 +#define ER_CONN_TCP_CREATED 10251 +#define ER_CONN_TCP_ADDRESS 10252 +#define ER_CONN_TCP_IPV6_AVAILABLE 10253 +#define ER_CONN_TCP_IPV6_UNAVAILABLE 10254 +#define ER_CONN_TCP_ERROR_WITH_STRERROR 10255 +#define ER_CONN_TCP_CANT_RESOLVE_HOSTNAME 10256 +#define ER_CONN_TCP_IS_THERE_ANOTHER_USING_PORT 10257 +#define ER_CONN_UNIX_IS_THERE_ANOTHER_USING_SOCKET 10258 +#define ER_CONN_UNIX_PID_CLAIMED_SOCKET_FILE 10259 +#define ER_CONN_TCP_CANT_RESET_V6ONLY 10260 +#define ER_CONN_TCP_BIND_RETRY 10261 +#define ER_CONN_TCP_BIND_FAIL 10262 +#define ER_CONN_TCP_IP_NOT_LOGGED 10263 +#define ER_CONN_TCP_RESOLVE_INFO 10264 +#define ER_CONN_TCP_START_FAIL 10265 +#define ER_CONN_TCP_LISTEN_FAIL 10266 +#define ER_CONN_UNIX_PATH_TOO_LONG 10267 +#define ER_CONN_UNIX_LOCK_FILE_FAIL 10268 +#define ER_CONN_UNIX_NO_FD 10269 +#define ER_CONN_UNIX_NO_BIND_NO_START 10270 +#define ER_CONN_UNIX_LISTEN_FAILED 10271 +#define ER_CONN_UNIX_LOCK_FILE_GIVING_UP 10272 +#define ER_CONN_UNIX_LOCK_FILE_CANT_CREATE 10273 +#define ER_CONN_UNIX_LOCK_FILE_CANT_OPEN 10274 +#define ER_CONN_UNIX_LOCK_FILE_CANT_READ 10275 +#define ER_CONN_UNIX_LOCK_FILE_EMPTY 10276 +#define ER_CONN_UNIX_LOCK_FILE_PIDLESS 10277 +#define ER_CONN_UNIX_LOCK_FILE_CANT_WRITE 10278 +#define ER_CONN_UNIX_LOCK_FILE_CANT_DELETE 10279 +#define ER_CONN_UNIX_LOCK_FILE_CANT_SYNC 10280 +#define ER_CONN_UNIX_LOCK_FILE_CANT_CLOSE 10281 +#define ER_CONN_SOCKET_SELECT_FAILED 10282 +#define ER_CONN_SOCKET_ACCEPT_FAILED 10283 +#define ER_AUTH_RSA_CANT_FIND 10284 +#define ER_AUTH_RSA_CANT_PARSE 10285 +#define ER_AUTH_RSA_CANT_READ 10286 +#define ER_AUTH_RSA_FILES_NOT_FOUND 10287 +#define ER_CONN_ATTR_TRUNCATED 10288 +#define ER_X509_CIPHERS_MISMATCH 10289 +#define ER_X509_ISSUER_MISMATCH 10290 +#define ER_X509_SUBJECT_MISMATCH 10291 +#define ER_AUTH_CANT_ACTIVATE_ROLE 10292 +#define ER_X509_NEEDS_RSA_PRIVKEY 10293 +#define ER_X509_CANT_WRITE_KEY 10294 +#define ER_X509_CANT_CHMOD_KEY 10295 +#define ER_X509_CANT_READ_CA_KEY 10296 +#define ER_X509_CANT_READ_CA_CERT 10297 +#define ER_X509_CANT_CREATE_CERT 10298 +#define ER_X509_CANT_WRITE_CERT 10299 +#define ER_AUTH_CANT_CREATE_RSA_PAIR 10300 +#define ER_AUTH_CANT_WRITE_PRIVKEY 10301 +#define ER_AUTH_CANT_WRITE_PUBKEY 10302 +#define ER_AUTH_SSL_CONF_PREVENTS_CERT_GENERATION 10303 +#define ER_AUTH_USING_EXISTING_CERTS 10304 +#define ER_AUTH_CERTS_SAVED_TO_DATADIR 10305 +#define ER_AUTH_CERT_GENERATION_DISABLED 10306 +#define ER_AUTH_RSA_CONF_PREVENTS_KEY_GENERATION 10307 +#define ER_AUTH_KEY_GENERATION_SKIPPED_PAIR_PRESENT 10308 +#define ER_AUTH_KEYS_SAVED_TO_DATADIR 10309 +#define ER_AUTH_KEY_GENERATION_DISABLED 10310 +#define ER_AUTHCACHE_PROXIES_PRIV_SKIPPED_NEEDS_RESOLVE 10311 +#define ER_AUTHCACHE_PLUGIN_MISSING 10312 +#define ER_AUTHCACHE_PLUGIN_CONFIG 10313 +//#define OBSOLETE_ER_AUTHCACHE_ROLE_TABLES_DODGY 10314 +#define ER_AUTHCACHE_USER_SKIPPED_NEEDS_RESOLVE 10315 +#define ER_AUTHCACHE_USER_TABLE_DODGY 10316 +#define ER_AUTHCACHE_USER_IGNORED_DEPRECATED_PASSWORD 10317 +#define ER_AUTHCACHE_USER_IGNORED_NEEDS_PLUGIN 10318 +#define ER_AUTHCACHE_USER_IGNORED_INVALID_PASSWORD 10319 +#define ER_AUTHCACHE_EXPIRED_PASSWORD_UNSUPPORTED 10320 +#define ER_NO_SUPER_WITHOUT_USER_PLUGIN 10321 +#define ER_AUTHCACHE_DB_IGNORED_EMPTY_NAME 10322 +#define ER_AUTHCACHE_DB_SKIPPED_NEEDS_RESOLVE 10323 +#define ER_AUTHCACHE_DB_ENTRY_LOWERCASED_REVOKE_WILL_FAIL 10324 +#define ER_AUTHCACHE_TABLE_PROXIES_PRIV_MISSING 10325 +#define ER_AUTHCACHE_CANT_OPEN_AND_LOCK_PRIVILEGE_TABLES 10326 +#define ER_AUTHCACHE_CANT_INIT_GRANT_SUBSYSTEM 10327 +#define ER_AUTHCACHE_PROCS_PRIV_SKIPPED_NEEDS_RESOLVE 10328 +#define ER_AUTHCACHE_PROCS_PRIV_ENTRY_IGNORED_BAD_ROUTINE_TYPE 10329 +#define ER_AUTHCACHE_TABLES_PRIV_SKIPPED_NEEDS_RESOLVE 10330 +#define ER_USER_NOT_IN_EXTRA_USERS_BINLOG_POSSIBLY_INCOMPLETE 10331 +#define ER_DD_SCHEMA_NOT_FOUND 10332 +#define ER_DD_TABLE_NOT_FOUND 10333 +#define ER_DD_SE_INIT_FAILED 10334 +#define ER_DD_ABORTING_PARTIAL_UPGRADE 10335 +#define ER_DD_FRM_EXISTS_FOR_TABLE 10336 +#define ER_DD_CREATED_FOR_UPGRADE 10337 +#define ER_ERRMSG_CANT_FIND_FILE 10338 +//#define OBSOLETE_ER_ERRMSG_LOADING_55_STYLE 10339 +#define ER_ERRMSG_MISSING_IN_FILE 10340 +#define ER_ERRMSG_OOM 10341 +#define ER_ERRMSG_CANT_READ 10342 +#define ER_TABLE_INCOMPATIBLE_DECIMAL_FIELD 10343 +#define ER_TABLE_INCOMPATIBLE_YEAR_FIELD 10344 +#define ER_INVALID_CHARSET_AND_DEFAULT_IS_MB 10345 +#define ER_TABLE_WRONG_KEY_DEFINITION 10346 +#define ER_CANT_OPEN_FRM_FILE 10347 +#define ER_CANT_READ_FRM_FILE 10348 +#define ER_TABLE_CREATED_WITH_DIFFERENT_VERSION 10349 +#define ER_VIEW_UNPARSABLE 10350 +#define ER_FILE_TYPE_UNKNOWN 10351 +#define ER_INVALID_INFO_IN_FRM 10352 +#define ER_CANT_OPEN_AND_LOCK_PRIVILEGE_TABLES 10353 +#define ER_AUDIT_PLUGIN_DOES_NOT_SUPPORT_AUDIT_AUTH_EVENTS 10354 +#define ER_AUDIT_PLUGIN_HAS_INVALID_DATA 10355 +#define ER_TZ_OOM_INITIALIZING_TIME_ZONES 10356 +#define ER_TZ_CANT_OPEN_AND_LOCK_TIME_ZONE_TABLE 10357 +#define ER_TZ_OOM_LOADING_LEAP_SECOND_TABLE 10358 +#define ER_TZ_TOO_MANY_LEAPS_IN_LEAP_SECOND_TABLE 10359 +#define ER_TZ_ERROR_LOADING_LEAP_SECOND_TABLE 10360 +#define ER_TZ_UNKNOWN_OR_ILLEGAL_DEFAULT_TIME_ZONE 10361 +#define ER_TZ_CANT_FIND_DESCRIPTION_FOR_TIME_ZONE 10362 +#define ER_TZ_CANT_FIND_DESCRIPTION_FOR_TIME_ZONE_ID 10363 +#define ER_TZ_TRANSITION_TYPE_TABLE_TYPE_TOO_LARGE 10364 +#define ER_TZ_TRANSITION_TYPE_TABLE_ABBREVIATIONS_EXCEED_SPACE 10365 +#define ER_TZ_TRANSITION_TYPE_TABLE_LOAD_ERROR 10366 +#define ER_TZ_TRANSITION_TABLE_TOO_MANY_TRANSITIONS 10367 +#define ER_TZ_TRANSITION_TABLE_BAD_TRANSITION_TYPE 10368 +#define ER_TZ_TRANSITION_TABLE_LOAD_ERROR 10369 +#define ER_TZ_NO_TRANSITION_TYPES_IN_TIME_ZONE 10370 +#define ER_TZ_OOM_LOADING_TIME_ZONE_DESCRIPTION 10371 +#define ER_TZ_CANT_BUILD_MKTIME_MAP 10372 +#define ER_TZ_OOM_WHILE_LOADING_TIME_ZONE 10373 +#define ER_TZ_OOM_WHILE_SETTING_TIME_ZONE 10374 +#define ER_REPLICA_SQL_THREAD_STOPPED_UNTIL_CONDITION_BAD 10375 +#define ER_REPLICA_SQL_THREAD_STOPPED_UNTIL_POSITION_REACHED 10376 +#define ER_REPLICA_SQL_THREAD_STOPPED_BEFORE_GTIDS_ALREADY_APPLIED 10377 +#define ER_REPLICA_SQL_THREAD_STOPPED_BEFORE_GTIDS_REACHED 10378 +#define ER_REPLICA_SQL_THREAD_STOPPED_AFTER_GTIDS_REACHED 10379 +#define ER_REPLICA_SQL_THREAD_STOPPED_GAP_TRX_PROCESSED 10380 +#define ER_GROUP_REPLICATION_PLUGIN_NOT_INSTALLED 10381 +#define ER_GTID_ALREADY_ADDED_BY_USER 10382 +#define ER_FAILED_TO_DELETE_FROM_GTID_EXECUTED_TABLE 10383 +#define ER_FAILED_TO_COMPRESS_GTID_EXECUTED_TABLE 10384 +#define ER_FAILED_TO_COMPRESS_GTID_EXECUTED_TABLE_OOM 10385 +#define ER_FAILED_TO_INIT_THREAD_ATTR_FOR_GTID_TABLE_COMPRESSION 10386 +#define ER_FAILED_TO_CREATE_GTID_TABLE_COMPRESSION_THREAD 10387 +#define ER_FAILED_TO_JOIN_GTID_TABLE_COMPRESSION_THREAD 10388 +#define ER_NPIPE_FAILED_TO_INIT_SECURITY_DESCRIPTOR 10389 +#define ER_NPIPE_FAILED_TO_SET_SECURITY_DESCRIPTOR 10390 +#define ER_NPIPE_PIPE_ALREADY_IN_USE 10391 +//#define OBSOLETE_ER_NDB_SLAVE_SAW_EPOCH_LOWER_THAN_PREVIOUS_ON_START 10392 +//#define OBSOLETE_ER_NDB_SLAVE_SAW_EPOCH_LOWER_THAN_PREVIOUS 10393 +//#define OBSOLETE_ER_NDB_SLAVE_SAW_ALREADY_COMMITTED_EPOCH 10394 +//#define OBSOLETE_ER_NDB_SLAVE_PREVIOUS_EPOCH_NOT_COMMITTED 10395 +//#define OBSOLETE_ER_NDB_SLAVE_MISSING_DATA_FOR_TIMESTAMP_COLUMN 10396 +//#define OBSOLETE_ER_NDB_SLAVE_LOGGING_EXCEPTIONS_TO 10397 +//#define OBSOLETE_ER_NDB_SLAVE_LOW_EPOCH_RESOLUTION 10398 +//#define OBSOLETE_ER_NDB_INFO_FOUND_UNEXPECTED_FIELD_TYPE 10399 +//#define OBSOLETE_ER_NDB_INFO_FAILED_TO_CREATE_NDBINFO 10400 +//#define OBSOLETE_ER_NDB_INFO_FAILED_TO_INIT_NDBINFO 10401 +//#define OBSOLETE_ER_NDB_CLUSTER_WRONG_NUMBER_OF_FUNCTION_ARGUMENTS 10402 +//#define OBSOLETE_ER_NDB_CLUSTER_SCHEMA_INFO 10403 +//#define OBSOLETE_ER_NDB_CLUSTER_GENERIC_MESSAGE 10404 +#define ER_RPL_CANT_OPEN_INFO_TABLE 10405 +#define ER_RPL_CANT_SCAN_INFO_TABLE 10406 +#define ER_RPL_CORRUPTED_INFO_TABLE 10407 +#define ER_RPL_CORRUPTED_KEYS_IN_INFO_TABLE 10408 +#define ER_RPL_WORKER_ID_IS 10409 +#define ER_RPL_INCONSISTENT_TIMESTAMPS_IN_TRX 10410 +#define ER_RPL_INCONSISTENT_SEQUENCE_NO_IN_TRX 10411 +//#define OBSOLETE_ER_RPL_CHANNELS_REQUIRE_TABLES_AS_INFO_REPOSITORIES 10412 +#define ER_RPL_CHANNELS_REQUIRE_NON_ZERO_SERVER_ID 10413 +//#define OBSOLETE_ER_RPL_REPO_SHOULD_BE_TABLE 10414 +#define ER_RPL_ERROR_CREATING_CONNECTION_METADATA 10415 +//#define OBSOLETE_ER_RPL_ERROR_CHANGING_CONNECTION_METADATA_REPO_TYPE 10416 +//#define OBSOLETE_ER_RPL_CHANGING_AM_TYPE_FAILED_DUE_TO_GAPS 10417 +#define ER_RPL_ERROR_CREATING_APPLIER_METADATA 10418 +//#define OBSOLETE_ER_RPL_ERROR_CHANGING_APPLIER_METADATA_REPO_TYPE 10419 +#define ER_RPL_FAILED_TO_DELETE_FROM_REPLICA_WORKERS_INFO_REPOSITORY 10420 +#define ER_RPL_FAILED_TO_RESET_STATE_IN_REPLICA_INFO_REPOSITORY 10421 +//#define OBSOLETE_ER_RPL_ERROR_CHECKING_REPOSITORY 10422 +#define ER_RPL_REPLICA_GENERIC_MESSAGE 10423 +#define ER_RPL_REPLICA_COULD_NOT_CREATE_CHANNEL_LIST 10424 +#define ER_RPL_MULTISOURCE_REQUIRES_TABLE_TYPE_REPOSITORIES 10425 +#define ER_RPL_REPLICA_FAILED_TO_INIT_A_CONNECTION_METADATA_STRUCTURE 10426 +#define ER_RPL_REPLICA_FAILED_TO_INIT_CONNECTION_METADATA_STRUCTURE 10427 +#define ER_RPL_REPLICA_FAILED_TO_CREATE_CHANNEL_FROM_CONNECTION_METADATA 10428 +#define ER_RPL_FAILED_TO_CREATE_NEW_INFO_FILE 10429 +#define ER_RPL_FAILED_TO_CREATE_CACHE_FOR_INFO_FILE 10430 +#define ER_RPL_FAILED_TO_OPEN_INFO_FILE 10431 +#define ER_RPL_GTID_MEMORY_FINALLY_AVAILABLE 10432 +#define ER_SERVER_COST_UNKNOWN_COST_CONSTANT 10433 +#define ER_SERVER_COST_INVALID_COST_CONSTANT 10434 +#define ER_ENGINE_COST_UNKNOWN_COST_CONSTANT 10435 +#define ER_ENGINE_COST_UNKNOWN_STORAGE_ENGINE 10436 +#define ER_ENGINE_COST_INVALID_DEVICE_TYPE_FOR_SE 10437 +#define ER_ENGINE_COST_INVALID_CONST_CONSTANT_FOR_SE_AND_DEVICE 10438 +#define ER_SERVER_COST_FAILED_TO_READ 10439 +#define ER_ENGINE_COST_FAILED_TO_READ 10440 +#define ER_FAILED_TO_OPEN_COST_CONSTANT_TABLES 10441 +#define ER_RPL_UNSUPPORTED_UNIGNORABLE_EVENT_IN_STREAM 10442 +#define ER_RPL_GTID_LOG_EVENT_IN_STREAM 10443 +#define ER_RPL_UNEXPECTED_BEGIN_IN_STREAM 10444 +#define ER_RPL_UNEXPECTED_COMMIT_ROLLBACK_OR_XID_LOG_EVENT_IN_STREAM 10445 +#define ER_RPL_UNEXPECTED_XA_ROLLBACK_IN_STREAM 10446 +#define ER_EVENT_EXECUTION_FAILED_CANT_AUTHENTICATE_USER 10447 +#define ER_EVENT_EXECUTION_FAILED_USER_LOST_EVEN_PRIVILEGE 10448 +#define ER_EVENT_ERROR_DURING_COMPILATION 10449 +#define ER_EVENT_DROPPING 10450 +//#define OBSOLETE_ER_NDB_SCHEMA_GENERIC_MESSAGE 10451 +#define ER_RPL_INCOMPATIBLE_DECIMAL_IN_RBR 10452 +#define ER_INIT_ROOT_WITHOUT_PASSWORD 10453 +#define ER_INIT_GENERATING_TEMP_PASSWORD_FOR_ROOT 10454 +#define ER_INIT_CANT_OPEN_BOOTSTRAP_FILE 10455 +#define ER_INIT_BOOTSTRAP_COMPLETE 10456 +#define ER_INIT_DATADIR_NOT_EMPTY_WONT_INITIALIZE 10457 +#define ER_INIT_DATADIR_EXISTS_WONT_INITIALIZE 10458 +#define ER_INIT_DATADIR_EXISTS_AND_PATH_TOO_LONG_WONT_INITIALIZE 10459 +#define ER_INIT_DATADIR_EXISTS_AND_NOT_WRITABLE_WONT_INITIALIZE 10460 +#define ER_INIT_CREATING_DD 10461 +#define ER_RPL_BINLOG_STARTING_DUMP 10462 +#define ER_RPL_BINLOG_SOURCE_SENDS_HEARTBEAT 10463 +#define ER_RPL_BINLOG_SKIPPING_REMAINING_HEARTBEAT_INFO 10464 +#define ER_RPL_BINLOG_SOURCE_USES_CHECKSUM_AND_REPLICA_CANT 10465 +//#define OBSOLETE_ER_NDB_QUERY_FAILED 10466 +#define ER_KILLING_THREAD 10467 +#define ER_DETACHING_SESSION_LEFT_BY_PLUGIN 10468 +#define ER_CANT_DETACH_SESSION_LEFT_BY_PLUGIN 10469 +#define ER_DETACHED_SESSIONS_LEFT_BY_PLUGIN 10470 +#define ER_FAILED_TO_DECREMENT_NUMBER_OF_THREADS 10471 +#define ER_PLUGIN_DID_NOT_DEINITIALIZE_THREADS 10472 +#define ER_KILLED_THREADS_OF_PLUGIN 10473 +//#define OBSOLETE_ER_NDB_SLAVE_MAX_REPLICATED_EPOCH_UNKNOWN 10474 +//#define OBSOLETE_ER_NDB_SLAVE_MAX_REPLICATED_EPOCH_SET_TO 10475 +//#define OBSOLETE_ER_NDB_NODE_ID_AND_MANAGEMENT_SERVER_INFO 10476 +//#define OBSOLETE_ER_NDB_DISCONNECT_INFO 10477 +//#define OBSOLETE_ER_NDB_COLUMN_DEFAULTS_DIFFER 10478 +//#define OBSOLETE_ER_NDB_COLUMN_SHOULD_NOT_HAVE_NATIVE_DEFAULT 10479 +//#define OBSOLETE_ER_NDB_FIELD_INFO 10480 +//#define OBSOLETE_ER_NDB_COLUMN_INFO 10481 +//#define OBSOLETE_ER_NDB_OOM_IN_FIX_UNIQUE_INDEX_ATTR_ORDER 10482 +//#define OBSOLETE_ER_NDB_SLAVE_MALFORMED_EVENT_RECEIVED_ON_TABLE 10483 +//#define OBSOLETE_ER_NDB_SLAVE_CONFLICT_FUNCTION_REQUIRES_ROLE 10484 +//#define OBSOLETE_ER_NDB_SLAVE_CONFLICT_TRANSACTION_IDS 10485 +//#define OBSOLETE_ER_NDB_SLAVE_BINLOG_MISSING_INFO_FOR_CONFLICT_DETECTION 10486 +//#define OBSOLETE_ER_NDB_ERROR_IN_READAUTOINCREMENTVALUE 10487 +//#define OBSOLETE_ER_NDB_FOUND_UNCOMMITTED_AUTOCOMMIT 10488 +//#define OBSOLETE_ER_NDB_SLAVE_TOO_MANY_RETRIES 10489 +//#define OBSOLETE_ER_NDB_SLAVE_ERROR_IN_UPDATE_CREATE_INFO 10490 +//#define OBSOLETE_ER_NDB_SLAVE_CANT_ALLOCATE_TABLE_SHARE 10491 +//#define OBSOLETE_ER_NDB_BINLOG_ERROR_INFO_FROM_DA 10492 +//#define OBSOLETE_ER_NDB_BINLOG_CREATE_TABLE_EVENT 10493 +//#define OBSOLETE_ER_NDB_BINLOG_FAILED_CREATE_TABLE_EVENT_OPERATIONS 10494 +//#define OBSOLETE_ER_NDB_BINLOG_RENAME_EVENT 10495 +//#define OBSOLETE_ER_NDB_BINLOG_FAILED_CREATE_DURING_RENAME 10496 +//#define OBSOLETE_ER_NDB_UNEXPECTED_RENAME_TYPE 10497 +//#define OBSOLETE_ER_NDB_ERROR_IN_GET_AUTO_INCREMENT 10498 +//#define OBSOLETE_ER_NDB_CREATING_SHARE_IN_OPEN 10499 +//#define OBSOLETE_ER_NDB_TABLE_OPENED_READ_ONLY 10500 +//#define OBSOLETE_ER_NDB_INITIALIZE_GIVEN_CLUSTER_PLUGIN_DISABLED 10501 +//#define OBSOLETE_ER_NDB_BINLOG_FORMAT_CHANGED_FROM_STMT_TO_MIXED 10502 +//#define OBSOLETE_ER_NDB_TRAILING_SHARE_RELEASED_BY_CLOSE_CACHED_TABLES 10503 +//#define OBSOLETE_ER_NDB_SHARE_ALREADY_EXISTS 10504 +//#define OBSOLETE_ER_NDB_HANDLE_TRAILING_SHARE_INFO 10505 +//#define OBSOLETE_ER_NDB_CLUSTER_GET_SHARE_INFO 10506 +//#define OBSOLETE_ER_NDB_CLUSTER_REAL_FREE_SHARE_INFO 10507 +//#define OBSOLETE_ER_NDB_CLUSTER_REAL_FREE_SHARE_DROP_FAILED 10508 +//#define OBSOLETE_ER_NDB_CLUSTER_FREE_SHARE_INFO 10509 +//#define OBSOLETE_ER_NDB_CLUSTER_MARK_SHARE_DROPPED_INFO 10510 +//#define OBSOLETE_ER_NDB_CLUSTER_MARK_SHARE_DROPPED_DESTROYING_SHARE 10511 +//#define OBSOLETE_ER_NDB_CLUSTER_OOM_THD_NDB 10512 +//#define OBSOLETE_ER_NDB_BINLOG_NDB_TABLES_INITIALLY_READ_ONLY 10513 +//#define OBSOLETE_ER_NDB_UTIL_THREAD_OOM 10514 +//#define OBSOLETE_ER_NDB_ILLEGAL_VALUE_FOR_NDB_RECV_THREAD_CPU_MASK 10515 +//#define OBSOLETE_ER_NDB_TOO_MANY_CPUS_IN_NDB_RECV_THREAD_CPU_MASK 10516 +#define ER_DBUG_CHECK_SHARES_OPEN 10517 +#define ER_DBUG_CHECK_SHARES_INFO 10518 +#define ER_DBUG_CHECK_SHARES_DROPPED 10519 +#define ER_INVALID_OR_OLD_TABLE_OR_DB_NAME 10520 +#define ER_TC_RECOVERING_AFTER_CRASH_USING 10521 +#define ER_TC_CANT_AUTO_RECOVER_WITH_TC_HEURISTIC_RECOVER 10522 +#define ER_TC_BAD_MAGIC_IN_TC_LOG 10523 +#define ER_TC_NEED_N_SE_SUPPORTING_2PC_FOR_RECOVERY 10524 +#define ER_TC_RECOVERY_FAILED_THESE_ARE_YOUR_OPTIONS 10525 +#define ER_TC_HEURISTIC_RECOVERY_MODE 10526 +#define ER_TC_HEURISTIC_RECOVERY_FAILED 10527 +#define ER_TC_RESTART_WITHOUT_TC_HEURISTIC_RECOVER 10528 +#define ER_RPL_REPLICA_FAILED_TO_CREATE_OR_RECOVER_INFO_REPOSITORIES 10529 +#define ER_RPL_REPLICA_AUTO_POSITION_IS_1_AND_GTID_MODE_IS_OFF 10530 +#define ER_RPL_REPLICA_CANT_START_REPLICA_FOR_CHANNEL 10531 +#define ER_RPL_REPLICA_CANT_STOP_REPLICA_FOR_CHANNEL 10532 +#define ER_RPL_RECOVERY_NO_ROTATE_EVENT_FROM_SOURCE 10533 +#define ER_RPL_RECOVERY_ERROR_READ_RELAY_LOG 10534 +//#define OBSOLETE_ER_RPL_RECOVERY_ERROR_FREEING_IO_CACHE 10535 +#define ER_RPL_RECOVERY_SKIPPED_GROUP_REPLICATION_CHANNEL 10536 +#define ER_RPL_RECOVERY_ERROR 10537 +#define ER_RPL_RECOVERY_IO_ERROR_READING_RELAY_LOG_INDEX 10538 +#define ER_RPL_RECOVERY_FILE_SOURCE_POS_INFO 10539 +#define ER_RPL_RECOVERY_REPLICATE_SAME_SERVER_ID_REQUIRES_POSITION 10540 +#define ER_RPL_MTA_RECOVERY_STARTING_COORDINATOR 10541 +#define ER_RPL_MTA_RECOVERY_FAILED_TO_START_COORDINATOR 10542 +#define ER_RPL_MTA_AUTOMATIC_RECOVERY_FAILED 10543 +#define ER_RPL_MTA_RECOVERY_CANT_OPEN_RELAY_LOG 10544 +#define ER_RPL_MTA_RECOVERY_SUCCESSFUL 10545 +#define ER_RPL_SERVER_ID_MISSING 10546 +#define ER_RPL_CANT_CREATE_REPLICA_THREAD 10547 +#define ER_RPL_REPLICA_IO_THREAD_WAS_KILLED 10548 +//#define OBSOLETE_ER_RPL_REPLICA_SOURCE_UUID_HAS_CHANGED 10549 +#define ER_RPL_REPLICA_USES_CHECKSUM_AND_SOURCE_PRE_50 10550 +#define ER_RPL_REPLICA_SECONDS_BEHIND_SOURCE_DUBIOUS 10551 +#define ER_RPL_REPLICA_CANT_FLUSH_CONNECTION_METADATA_REPOS 10552 +#define ER_RPL_REPLICA_REPORT_HOST_TOO_LONG 10553 +#define ER_RPL_REPLICA_REPORT_USER_TOO_LONG 10554 +#define ER_RPL_REPLICA_REPORT_PASSWORD_TOO_LONG 10555 +#define ER_RPL_REPLICA_ERROR_RETRYING 10556 +#define ER_RPL_REPLICA_ERROR_READING_FROM_SERVER 10557 +#define ER_RPL_REPLICA_DUMP_THREAD_KILLED_BY_SOURCE 10558 +#define ER_RPL_MTA_STATISTICS 10559 +#define ER_RPL_MTA_RECOVERY_COMPLETE 10560 +#define ER_RPL_REPLICA_CANT_INIT_RELAY_LOG_POSITION 10561 +//#define OBSOLETE_ER_RPL_REPLICA_CONNECTED_TO_SOURCE_REPLICATION_STARTED 10562 +#define ER_RPL_REPLICA_IO_THREAD_KILLED 10563 +#define ER_RPL_REPLICA_IO_THREAD_CANT_REGISTER_ON_SOURCE 10564 +#define ER_RPL_REPLICA_FORCING_TO_RECONNECT_IO_THREAD 10565 +#define ER_RPL_REPLICA_ERROR_REQUESTING_BINLOG_DUMP 10566 +#define ER_RPL_LOG_ENTRY_EXCEEDS_REPLICA_MAX_ALLOWED_PACKET 10567 +#define ER_RPL_REPLICA_STOPPING_AS_SOURCE_OOM 10568 +#define ER_RPL_REPLICA_IO_THREAD_ABORTED_WAITING_FOR_RELAY_LOG_SPACE 10569 +#define ER_RPL_REPLICA_IO_THREAD_EXITING 10570 +#define ER_RPL_REPLICA_CANT_INITIALIZE_REPLICA_WORKER 10571 +#define ER_RPL_MTA_GROUP_RECOVERY_APPLIER_METADATA_FOR_WORKER 10572 +#define ER_RPL_ERROR_LOOKING_FOR_LOG 10573 +#define ER_RPL_MTA_GROUP_RECOVERY_APPLIER_METADATA 10574 +#define ER_RPL_CANT_FIND_FOLLOWUP_FILE 10575 +#define ER_RPL_MTA_CHECKPOINT_PERIOD_DIFFERS_FROM_CNT 10576 +#define ER_RPL_REPLICA_WORKER_THREAD_CREATION_FAILED 10577 +#define ER_RPL_REPLICA_WORKER_THREAD_CREATION_FAILED_WITH_ERRNO 10578 +#define ER_RPL_REPLICA_FAILED_TO_INIT_PARTITIONS_HASH 10579 +//#define OBSOLETE_ER_RPL_SLAVE_NDB_TABLES_NOT_AVAILABLE 10580 +#define ER_RPL_REPLICA_SQL_THREAD_STARTING 10581 +#define ER_RPL_REPLICA_SKIP_COUNTER_EXECUTED 10582 +#define ER_RPL_REPLICA_ADDITIONAL_ERROR_INFO_FROM_DA 10583 +#define ER_RPL_REPLICA_ERROR_INFO_FROM_DA 10584 +#define ER_RPL_REPLICA_ERROR_LOADING_USER_DEFINED_LIBRARY 10585 +#define ER_RPL_REPLICA_ERROR_RUNNING_QUERY 10586 +#define ER_RPL_REPLICA_SQL_THREAD_EXITING 10587 +#define ER_RPL_REPLICA_READ_INVALID_EVENT_FROM_SOURCE 10588 +#define ER_RPL_REPLICA_QUEUE_EVENT_FAILED_INVALID_CONFIGURATION 10589 +#define ER_RPL_REPLICA_IO_THREAD_DETECTED_UNEXPECTED_EVENT_SEQUENCE 10590 +#define ER_RPL_REPLICA_CANT_USE_CHARSET 10591 +#define ER_RPL_REPLICA_CONNECTED_TO_SOURCE_REPLICATION_RESUMED 10592 +#define ER_RPL_REPLICA_NEXT_LOG_IS_ACTIVE 10593 +#define ER_RPL_REPLICA_NEXT_LOG_IS_INACTIVE 10594 +#define ER_RPL_REPLICA_SQL_THREAD_IO_ERROR_READING_EVENT 10595 +#define ER_RPL_REPLICA_ERROR_READING_RELAY_LOG_EVENTS 10596 +#define ER_REPLICA_CHANGE_SOURCE_TO_EXECUTED 10597 +#define ER_RPL_REPLICA_NEW_C_M_NEEDS_REPOS_TYPE_OTHER_THAN_FILE 10598 +#define ER_RPL_FAILED_TO_STAT_LOG_IN_INDEX 10599 +#define ER_RPL_LOG_NOT_FOUND_WHILE_COUNTING_RELAY_LOG_SPACE 10600 +#define ER_REPLICA_CANT_USE_TEMPDIR 10601 +#define ER_RPL_RELAY_LOG_NEEDS_FILE_NOT_DIRECTORY 10602 +#define ER_RPL_RELAY_LOG_INDEX_NEEDS_FILE_NOT_DIRECTORY 10603 +#define ER_RPL_PLEASE_USE_OPTION_RELAY_LOG 10604 +#define ER_RPL_OPEN_INDEX_FILE_FAILED 10605 +#define ER_RPL_CANT_INITIALIZE_GTID_SETS_IN_AM_INIT_INFO 10606 +#define ER_RPL_CANT_OPEN_LOG_IN_AM_INIT_INFO 10607 +#define ER_RPL_ERROR_WRITING_RELAY_LOG_CONFIGURATION 10608 +//#define OBSOLETE_ER_NDB_OOM_GET_NDB_BLOBS_VALUE 10609 +//#define OBSOLETE_ER_NDB_THREAD_TIMED_OUT 10610 +//#define OBSOLETE_ER_NDB_TABLE_IS_NOT_DISTRIBUTED 10611 +//#define OBSOLETE_ER_NDB_CREATING_TABLE 10612 +//#define OBSOLETE_ER_NDB_FLUSHING_TABLE_INFO 10613 +//#define OBSOLETE_ER_NDB_CLEANING_STRAY_TABLES 10614 +//#define OBSOLETE_ER_NDB_DISCOVERED_MISSING_DB 10615 +//#define OBSOLETE_ER_NDB_DISCOVERED_REMAINING_DB 10616 +//#define OBSOLETE_ER_NDB_CLUSTER_FIND_ALL_DBS_RETRY 10617 +//#define OBSOLETE_ER_NDB_CLUSTER_FIND_ALL_DBS_FAIL 10618 +//#define OBSOLETE_ER_NDB_SKIPPING_SETUP_TABLE 10619 +//#define OBSOLETE_ER_NDB_FAILED_TO_SET_UP_TABLE 10620 +//#define OBSOLETE_ER_NDB_MISSING_FRM_DISCOVERING 10621 +//#define OBSOLETE_ER_NDB_MISMATCH_IN_FRM_DISCOVERING 10622 +//#define OBSOLETE_ER_NDB_BINLOG_CLEANING_UP_SETUP_LEFTOVERS 10623 +//#define OBSOLETE_ER_NDB_WAITING_INFO 10624 +//#define OBSOLETE_ER_NDB_WAITING_INFO_WITH_MAP 10625 +//#define OBSOLETE_ER_NDB_TIMEOUT_WHILE_DISTRIBUTING 10626 +//#define OBSOLETE_ER_NDB_NOT_WAITING_FOR_DISTRIBUTING 10627 +//#define OBSOLETE_ER_NDB_DISTRIBUTED_INFO 10628 +//#define OBSOLETE_ER_NDB_DISTRIBUTION_COMPLETE 10629 +//#define OBSOLETE_ER_NDB_SCHEMA_DISTRIBUTION_FAILED 10630 +//#define OBSOLETE_ER_NDB_SCHEMA_DISTRIBUTION_REPORTS_SUBSCRIBE 10631 +//#define OBSOLETE_ER_NDB_SCHEMA_DISTRIBUTION_REPORTS_UNSUBSCRIBE 10632 +//#define OBSOLETE_ER_NDB_BINLOG_CANT_DISCOVER_TABLE_FROM_SCHEMA_EVENT 10633 +//#define OBSOLETE_ER_NDB_BINLOG_SIGNALLING_UNKNOWN_VALUE 10634 +//#define OBSOLETE_ER_NDB_BINLOG_REPLY_TO 10635 +//#define OBSOLETE_ER_NDB_BINLOG_CANT_RELEASE_SLOCK 10636 +//#define OBSOLETE_ER_NDB_CANT_FIND_TABLE 10637 +//#define OBSOLETE_ER_NDB_DISCARDING_EVENT_NO_OBJ 10638 +//#define OBSOLETE_ER_NDB_DISCARDING_EVENT_ID_VERSION_MISMATCH 10639 +//#define OBSOLETE_ER_NDB_CLEAR_SLOCK_INFO 10640 +//#define OBSOLETE_ER_NDB_BINLOG_SKIPPING_LOCAL_TABLE 10641 +//#define OBSOLETE_ER_NDB_BINLOG_ONLINE_ALTER_RENAME 10642 +//#define OBSOLETE_ER_NDB_BINLOG_CANT_REOPEN_SHADOW_TABLE 10643 +//#define OBSOLETE_ER_NDB_BINLOG_ONLINE_ALTER_RENAME_COMPLETE 10644 +//#define OBSOLETE_ER_NDB_BINLOG_SKIPPING_DROP_OF_LOCAL_TABLE 10645 +//#define OBSOLETE_ER_NDB_BINLOG_SKIPPING_RENAME_OF_LOCAL_TABLE 10646 +//#define OBSOLETE_ER_NDB_BINLOG_SKIPPING_DROP_OF_TABLES 10647 +//#define OBSOLETE_ER_NDB_BINLOG_GOT_DIST_PRIV_EVENT_FLUSHING_PRIVILEGES 10648 +//#define OBSOLETE_ER_NDB_BINLOG_GOT_SCHEMA_EVENT 10649 +//#define OBSOLETE_ER_NDB_BINLOG_SKIPPING_OLD_SCHEMA_OPERATION 10650 +//#define OBSOLETE_ER_NDB_CLUSTER_FAILURE 10651 +//#define OBSOLETE_ER_NDB_TABLES_INITIALLY_READ_ONLY_ON_RECONNECT 10652 +//#define OBSOLETE_ER_NDB_IGNORING_UNKNOWN_EVENT 10653 +//#define OBSOLETE_ER_NDB_BINLOG_OPENING_INDEX 10654 +//#define OBSOLETE_ER_NDB_BINLOG_CANT_LOCK_NDB_BINLOG_INDEX 10655 +//#define OBSOLETE_ER_NDB_BINLOG_INJECTING_RANDOM_WRITE_FAILURE 10656 +//#define OBSOLETE_ER_NDB_BINLOG_CANT_WRITE_TO_NDB_BINLOG_INDEX 10657 +//#define OBSOLETE_ER_NDB_BINLOG_WRITING_TO_NDB_BINLOG_INDEX 10658 +//#define OBSOLETE_ER_NDB_BINLOG_CANT_COMMIT_TO_NDB_BINLOG_INDEX 10659 +//#define OBSOLETE_ER_NDB_BINLOG_WRITE_INDEX_FAILED_AFTER_KILL 10660 +//#define OBSOLETE_ER_NDB_BINLOG_USING_SERVER_ID_0_SLAVES_WILL_NOT 10661 +//#define OBSOLETE_ER_NDB_SERVER_ID_RESERVED_OR_TOO_LARGE 10662 +//#define OBSOLETE_ER_NDB_BINLOG_REQUIRES_V2_ROW_EVENTS 10663 +//#define OBSOLETE_ER_NDB_BINLOG_STATUS_FORCING_FULL_USE_WRITE 10664 +//#define OBSOLETE_ER_NDB_BINLOG_GENERIC_MESSAGE 10665 +//#define OBSOLETE_ER_NDB_CONFLICT_GENERIC_MESSAGE 10666 +//#define OBSOLETE_ER_NDB_TRANS_DEPENDENCY_TRACKER_ERROR 10667 +//#define OBSOLETE_ER_NDB_CONFLICT_FN_PARSE_ERROR 10668 +//#define OBSOLETE_ER_NDB_CONFLICT_FN_SETUP_ERROR 10669 +//#define OBSOLETE_ER_NDB_BINLOG_FAILED_TO_GET_TABLE 10670 +//#define OBSOLETE_ER_NDB_BINLOG_NOT_LOGGING 10671 +//#define OBSOLETE_ER_NDB_BINLOG_CREATE_TABLE_EVENT_FAILED 10672 +//#define OBSOLETE_ER_NDB_BINLOG_CREATE_TABLE_EVENT_INFO 10673 +//#define OBSOLETE_ER_NDB_BINLOG_DISCOVER_TABLE_EVENT_INFO 10674 +//#define OBSOLETE_ER_NDB_BINLOG_BLOB_REQUIRES_PK 10675 +//#define OBSOLETE_ER_NDB_BINLOG_CANT_CREATE_EVENT_IN_DB 10676 +//#define OBSOLETE_ER_NDB_BINLOG_CANT_CREATE_EVENT_IN_DB_AND_CANT_DROP 10677 +//#define OBSOLETE_ER_NDB_BINLOG_CANT_CREATE_EVENT_IN_DB_DROPPED 10678 +//#define OBSOLETE_ER_NDB_BINLOG_DISCOVER_REUSING_OLD_EVENT_OPS 10679 +//#define OBSOLETE_ER_NDB_BINLOG_CREATING_NDBEVENTOPERATION_FAILED 10680 +//#define OBSOLETE_ER_NDB_BINLOG_CANT_CREATE_BLOB 10681 +//#define OBSOLETE_ER_NDB_BINLOG_NDBEVENT_EXECUTE_FAILED 10682 +//#define OBSOLETE_ER_NDB_CREATE_EVENT_OPS_LOGGING_INFO 10683 +//#define OBSOLETE_ER_NDB_BINLOG_CANT_DROP_EVENT_FROM_DB 10684 +//#define OBSOLETE_ER_NDB_TIMED_OUT_IN_DROP_TABLE 10685 +//#define OBSOLETE_ER_NDB_BINLOG_UNHANDLED_ERROR_FOR_TABLE 10686 +//#define OBSOLETE_ER_NDB_BINLOG_CLUSTER_FAILURE 10687 +//#define OBSOLETE_ER_NDB_BINLOG_UNKNOWN_NON_DATA_EVENT 10688 +//#define OBSOLETE_ER_NDB_BINLOG_INJECTOR_DISCARDING_ROW_EVENT_METADATA 10689 +//#define OBSOLETE_ER_NDB_REMAINING_OPEN_TABLES 10690 +//#define OBSOLETE_ER_NDB_REMAINING_OPEN_TABLE_INFO 10691 +//#define OBSOLETE_ER_NDB_COULD_NOT_GET_APPLY_STATUS_SHARE 10692 +//#define OBSOLETE_ER_NDB_BINLOG_SERVER_SHUTDOWN_DURING_NDB_CLUSTER_START 10693 +//#define OBSOLETE_ER_NDB_BINLOG_CLUSTER_RESTARTED_RESET_MASTER_SUGGESTED 10694 +//#define OBSOLETE_ER_NDB_BINLOG_CLUSTER_HAS_RECONNECTED 10695 +//#define OBSOLETE_ER_NDB_BINLOG_STARTING_LOG_AT_EPOCH 10696 +//#define OBSOLETE_ER_NDB_BINLOG_NDB_TABLES_WRITABLE 10697 +//#define OBSOLETE_ER_NDB_BINLOG_SHUTDOWN_DETECTED 10698 +//#define OBSOLETE_ER_NDB_BINLOG_LOST_SCHEMA_CONNECTION_WAITING 10699 +//#define OBSOLETE_ER_NDB_BINLOG_LOST_SCHEMA_CONNECTION_CONTINUING 10700 +//#define OBSOLETE_ER_NDB_BINLOG_ERROR_HANDLING_SCHEMA_EVENT 10701 +//#define OBSOLETE_ER_NDB_BINLOG_CANT_INJECT_APPLY_STATUS_WRITE_ROW 10702 +//#define OBSOLETE_ER_NDB_BINLOG_ERROR_DURING_GCI_ROLLBACK 10703 +//#define OBSOLETE_ER_NDB_BINLOG_ERROR_DURING_GCI_COMMIT 10704 +//#define OBSOLETE_ER_NDB_BINLOG_LATEST_TRX_IN_EPOCH_NOT_IN_BINLOG 10705 +//#define OBSOLETE_ER_NDB_BINLOG_RELEASING_EXTRA_SHARE_REFERENCES 10706 +//#define OBSOLETE_ER_NDB_BINLOG_REMAINING_OPEN_TABLES 10707 +//#define OBSOLETE_ER_NDB_BINLOG_REMAINING_OPEN_TABLE_INFO 10708 +#define ER_TREE_CORRUPT_PARENT_SHOULD_POINT_AT_PARENT 10709 +#define ER_TREE_CORRUPT_ROOT_SHOULD_BE_BLACK 10710 +#define ER_TREE_CORRUPT_2_CONSECUTIVE_REDS 10711 +#define ER_TREE_CORRUPT_RIGHT_IS_LEFT 10712 +#define ER_TREE_CORRUPT_INCORRECT_BLACK_COUNT 10713 +#define ER_WRONG_COUNT_FOR_ORIGIN 10714 +#define ER_WRONG_COUNT_FOR_KEY 10715 +#define ER_WRONG_COUNT_OF_ELEMENTS 10716 +#define ER_RPL_ERROR_READING_REPLICA_WORKER_CONFIGURATION 10717 +//#define OBSOLETE_ER_RPL_ERROR_WRITING_SLAVE_WORKER_CONFIGURATION 10718 +#define ER_RPL_FAILED_TO_OPEN_RELAY_LOG 10719 +#define ER_RPL_WORKER_CANT_READ_RELAY_LOG 10720 +#define ER_RPL_WORKER_CANT_FIND_NEXT_RELAY_LOG 10721 +#define ER_RPL_MTA_REPLICA_COORDINATOR_HAS_WAITED 10722 +#define ER_BINLOG_FAILED_TO_WRITE_DROP_FOR_TEMP_TABLES 10723 +#define ER_BINLOG_OOM_WRITING_DELETE_WHILE_OPENING_HEAP_TABLE 10724 +#define ER_FAILED_TO_REPAIR_TABLE 10725 +#define ER_FAILED_TO_REMOVE_TEMP_TABLE 10726 +#define ER_SYSTEM_TABLE_NOT_TRANSACTIONAL 10727 +#define ER_RPL_ERROR_WRITING_SOURCE_CONFIGURATION 10728 +#define ER_RPL_ERROR_READING_SOURCE_CONFIGURATION 10729 +#define ER_RPL_SSL_INFO_IN_CONNECTION_METADATA_IGNORED 10730 +#define ER_PLUGIN_FAILED_DEINITIALIZATION 10731 +#define ER_PLUGIN_HAS_NONZERO_REFCOUNT_AFTER_DEINITIALIZATION 10732 +#define ER_PLUGIN_SHUTTING_DOWN_PLUGIN 10733 +#define ER_PLUGIN_REGISTRATION_FAILED 10734 +#define ER_PLUGIN_CANT_OPEN_PLUGIN_TABLE 10735 +#define ER_PLUGIN_CANT_LOAD 10736 +#define ER_PLUGIN_LOAD_PARAMETER_TOO_LONG 10737 +#define ER_PLUGIN_FORCING_SHUTDOWN 10738 +#define ER_PLUGIN_HAS_NONZERO_REFCOUNT_AFTER_SHUTDOWN 10739 +#define ER_PLUGIN_UNKNOWN_VARIABLE_TYPE 10740 +#define ER_PLUGIN_VARIABLE_SET_READ_ONLY 10741 +#define ER_PLUGIN_VARIABLE_MISSING_NAME 10742 +#define ER_PLUGIN_VARIABLE_NOT_ALLOCATED_THREAD_LOCAL 10743 +#define ER_PLUGIN_OOM 10744 +#define ER_PLUGIN_BAD_OPTIONS 10745 +#define ER_PLUGIN_PARSING_OPTIONS_FAILED 10746 +#define ER_PLUGIN_DISABLED 10747 +#define ER_PLUGIN_HAS_CONFLICTING_SYSTEM_VARIABLES 10748 +#define ER_PLUGIN_CANT_SET_PERSISTENT_OPTIONS 10749 +#define ER_MY_NET_WRITE_FAILED_FALLING_BACK_ON_STDERR 10750 +#define ER_RETRYING_REPAIR_WITHOUT_QUICK 10751 +#define ER_RETRYING_REPAIR_WITH_KEYCACHE 10752 +#define ER_FOUND_ROWS_WHILE_REPAIRING 10753 +#define ER_ERROR_DURING_OPTIMIZE_TABLE 10754 +#define ER_ERROR_ENABLING_KEYS 10755 +#define ER_CHECKING_TABLE 10756 +#define ER_RECOVERING_TABLE 10757 +#define ER_CANT_CREATE_TABLE_SHARE_FROM_FRM 10758 +#define ER_CANT_LOCK_TABLE 10759 +#define ER_CANT_ALLOC_TABLE_OBJECT 10760 +#define ER_CANT_CREATE_HANDLER_OBJECT_FOR_TABLE 10761 +#define ER_CANT_SET_HANDLER_REFERENCE_FOR_TABLE 10762 +#define ER_CANT_LOCK_TABLESPACE 10763 +#define ER_CANT_UPGRADE_GENERATED_COLUMNS_TO_DD 10764 +#define ER_DD_ERROR_CREATING_ENTRY 10765 +#define ER_DD_CANT_FETCH_TABLE_DATA 10766 +#define ER_DD_CANT_FIX_SE_DATA 10767 +#define ER_DD_CANT_CREATE_SP 10768 +#define ER_CANT_OPEN_DB_OPT_USING_DEFAULT_CHARSET 10769 +#define ER_CANT_CREATE_CACHE_FOR_DB_OPT 10770 +#define ER_CANT_IDENTIFY_CHARSET_USING_DEFAULT 10771 +#define ER_DB_OPT_NOT_FOUND_USING_DEFAULT_CHARSET 10772 +#define ER_EVENT_CANT_GET_TIMEZONE_FROM_FIELD 10773 +#define ER_EVENT_CANT_FIND_TIMEZONE 10774 +#define ER_EVENT_CANT_GET_CHARSET 10775 +#define ER_EVENT_CANT_GET_COLLATION 10776 +#define ER_EVENT_CANT_OPEN_TABLE_MYSQL_EVENT 10777 +#define ER_CANT_PARSE_STORED_ROUTINE_BODY 10778 +#define ER_CANT_OPEN_TABLE_MYSQL_PROC 10779 +#define ER_CANT_READ_TABLE_MYSQL_PROC 10780 +#define ER_FILE_EXISTS_DURING_UPGRADE 10781 +#define ER_CANT_OPEN_DATADIR_AFTER_UPGRADE_FAILURE 10782 +#define ER_CANT_SET_PATH_FOR 10783 +#define ER_CANT_OPEN_DIR 10784 +//#define OBSOLETE_ER_NDB_CLUSTER_CONNECTION_POOL_NODEIDS 10785 +//#define OBSOLETE_ER_NDB_CANT_PARSE_NDB_CLUSTER_CONNECTION_POOL_NODEIDS 10786 +//#define OBSOLETE_ER_NDB_INVALID_CLUSTER_CONNECTION_POOL_NODEIDS 10787 +//#define OBSOLETE_ER_NDB_DUPLICATE_CLUSTER_CONNECTION_POOL_NODEIDS 10788 +//#define OBSOLETE_ER_NDB_POOL_SIZE_CLUSTER_CONNECTION_POOL_NODEIDS 10789 +//#define OBSOLETE_ER_NDB_NODEID_NOT_FIRST_CONNECTION_POOL_NODEIDS 10790 +//#define OBSOLETE_ER_NDB_USING_NODEID 10791 +//#define OBSOLETE_ER_NDB_CANT_ALLOC_GLOBAL_NDB_CLUSTER_CONNECTION 10792 +//#define OBSOLETE_ER_NDB_CANT_ALLOC_GLOBAL_NDB_OBJECT 10793 +//#define OBSOLETE_ER_NDB_USING_NODEID_LIST 10794 +//#define OBSOLETE_ER_NDB_CANT_ALLOC_NDB_CLUSTER_CONNECTION 10795 +//#define OBSOLETE_ER_NDB_STARTING_CONNECT_THREAD 10796 +//#define OBSOLETE_ER_NDB_NODE_INFO 10797 +//#define OBSOLETE_ER_NDB_CANT_START_CONNECT_THREAD 10798 +//#define OBSOLETE_ER_NDB_GENERIC_ERROR 10799 +//#define OBSOLETE_ER_NDB_CPU_MASK_TOO_SHORT 10800 +#define ER_EVENT_ERROR_CREATING_QUERY_TO_WRITE_TO_BINLOG 10801 +#define ER_EVENT_SCHEDULER_ERROR_LOADING_FROM_DB 10802 +#define ER_EVENT_SCHEDULER_ERROR_GETTING_EVENT_OBJECT 10803 +#define ER_EVENT_SCHEDULER_GOT_BAD_DATA_FROM_TABLE 10804 +#define ER_EVENT_CANT_GET_LOCK_FOR_DROPPING_EVENT 10805 +#define ER_EVENT_UNABLE_TO_DROP_EVENT 10806 +//#define OBSOLETE_ER_BINLOG_ATTACHING_THREAD_MEMORY_FINALLY_AVAILABLE 10807 +#define ER_BINLOG_CANT_RESIZE_CACHE 10808 +#define ER_BINLOG_FILE_BEING_READ_NOT_PURGED 10809 +#define ER_BINLOG_IO_ERROR_READING_HEADER 10810 +//#define OBSOLETE_ER_BINLOG_CANT_OPEN_LOG 10811 +//#define OBSOLETE_ER_BINLOG_CANT_CREATE_CACHE_FOR_LOG 10812 +#define ER_BINLOG_FILE_EXTENSION_NUMBER_EXHAUSTED 10813 +#define ER_BINLOG_FILE_NAME_TOO_LONG 10814 +#define ER_BINLOG_FILE_EXTENSION_NUMBER_RUNNING_LOW 10815 +#define ER_BINLOG_CANT_OPEN_FOR_LOGGING 10816 +#define ER_BINLOG_FAILED_TO_SYNC_INDEX_FILE 10817 +#define ER_BINLOG_ERROR_READING_GTIDS_FROM_RELAY_LOG 10818 +#define ER_BINLOG_EVENTS_READ_FROM_APPLIER_METADATA 10819 +#define ER_BINLOG_ERROR_READING_GTIDS_FROM_BINARY_LOG 10820 +#define ER_BINLOG_EVENTS_READ_FROM_BINLOG_INFO 10821 +#define ER_BINLOG_CANT_GENERATE_NEW_FILE_NAME 10822 +#define ER_BINLOG_FAILED_TO_SYNC_INDEX_FILE_IN_OPEN 10823 +#define ER_BINLOG_CANT_USE_FOR_LOGGING 10824 +#define ER_BINLOG_FAILED_TO_CLOSE_INDEX_FILE_WHILE_REBUILDING 10825 +#define ER_BINLOG_FAILED_TO_DELETE_INDEX_FILE_WHILE_REBUILDING 10826 +#define ER_BINLOG_FAILED_TO_RENAME_INDEX_FILE_WHILE_REBUILDING 10827 +#define ER_BINLOG_FAILED_TO_OPEN_INDEX_FILE_AFTER_REBUILDING 10828 +#define ER_BINLOG_CANT_APPEND_LOG_TO_TMP_INDEX 10829 +#define ER_BINLOG_CANT_LOCATE_OLD_BINLOG_OR_RELAY_LOG_FILES 10830 +#define ER_BINLOG_CANT_DELETE_FILE 10831 +#define ER_BINLOG_CANT_SET_TMP_INDEX_NAME 10832 +#define ER_BINLOG_FAILED_TO_OPEN_TEMPORARY_INDEX_FILE 10833 +//#define OBSOLETE_ER_BINLOG_ERROR_GETTING_NEXT_LOG_FROM_INDEX 10834 +#define ER_BINLOG_CANT_OPEN_TMP_INDEX 10835 +#define ER_BINLOG_CANT_COPY_INDEX_TO_TMP 10836 +#define ER_BINLOG_CANT_CLOSE_TMP_INDEX 10837 +#define ER_BINLOG_CANT_MOVE_TMP_TO_INDEX 10838 +#define ER_BINLOG_PURGE_LOGS_CALLED_WITH_FILE_NOT_IN_INDEX 10839 +#define ER_BINLOG_PURGE_LOGS_CANT_SYNC_INDEX_FILE 10840 +#define ER_BINLOG_PURGE_LOGS_CANT_COPY_TO_REGISTER_FILE 10841 +#define ER_BINLOG_PURGE_LOGS_CANT_FLUSH_REGISTER_FILE 10842 +#define ER_BINLOG_PURGE_LOGS_CANT_UPDATE_INDEX_FILE 10843 +#define ER_BINLOG_PURGE_LOGS_FAILED_TO_PURGE_LOG 10844 +#define ER_BINLOG_FAILED_TO_SET_PURGE_INDEX_FILE_NAME 10845 +#define ER_BINLOG_FAILED_TO_OPEN_REGISTER_FILE 10846 +#define ER_BINLOG_FAILED_TO_REINIT_REGISTER_FILE 10847 +#define ER_BINLOG_FAILED_TO_READ_REGISTER_FILE 10848 +#define ER_CANT_STAT_FILE 10849 +#define ER_BINLOG_CANT_DELETE_LOG_FILE_DOES_INDEX_MATCH_FILES 10850 +#define ER_BINLOG_CANT_DELETE_FILE_AND_READ_BINLOG_INDEX 10851 +#define ER_BINLOG_FAILED_TO_DELETE_LOG_FILE 10852 +#define ER_BINLOG_LOGGING_INCIDENT_TO_STOP_REPLICAS 10853 +#define ER_BINLOG_CANT_FIND_LOG_IN_INDEX 10854 +#define ER_BINLOG_RECOVERING_AFTER_CRASH_USING 10855 +#define ER_BINLOG_CANT_OPEN_CRASHED_BINLOG 10856 +#define ER_BINLOG_CANT_TRIM_CRASHED_BINLOG 10857 +#define ER_BINLOG_CRASHED_BINLOG_TRIMMED 10858 +#define ER_BINLOG_CANT_CLEAR_IN_USE_FLAG_FOR_CRASHED_BINLOG 10859 +#define ER_BINLOG_FAILED_TO_RUN_AFTER_SYNC_HOOK 10860 +#define ER_TURNING_LOGGING_OFF_FOR_THE_DURATION 10861 +#define ER_BINLOG_FAILED_TO_RUN_AFTER_FLUSH_HOOK 10862 +//#define OBSOLETE_ER_BINLOG_CRASH_RECOVERY_FAILED 10863 +#define ER_BINLOG_WARNING_SUPPRESSED 10864 +#define ER_NDB_LOG_ENTRY 10865 +#define ER_NDB_LOG_ENTRY_WITH_PREFIX 10866 +//#define OBSOLETE_ER_NDB_BINLOG_CANT_CREATE_PURGE_THD 10867 +#define ER_INNODB_UNKNOWN_COLLATION 10868 +#define ER_INNODB_INVALID_LOG_GROUP_HOME_DIR 10869 +#define ER_INNODB_INVALID_INNODB_UNDO_DIRECTORY 10870 +#define ER_INNODB_ILLEGAL_COLON_IN_POOL 10871 +#define ER_INNODB_INVALID_PAGE_SIZE 10872 +#define ER_INNODB_DIRTY_WATER_MARK_NOT_LOW 10873 +#define ER_INNODB_IO_CAPACITY_EXCEEDS_MAX 10874 +#define ER_INNODB_FILES_SAME 10875 +#define ER_INNODB_UNREGISTERED_TRX_ACTIVE 10876 +#define ER_INNODB_CLOSING_CONNECTION_ROLLS_BACK 10877 +#define ER_INNODB_TRX_XLATION_TABLE_OOM 10878 +#define ER_INNODB_CANT_FIND_INDEX_IN_INNODB_DD 10879 +#define ER_INNODB_INDEX_COLUMN_INFO_UNLIKE_MYSQLS 10880 +//#define OBSOLETE_ER_INNODB_CANT_OPEN_TABLE 10881 +#define ER_INNODB_CANT_BUILD_INDEX_XLATION_TABLE_FOR 10882 +#define ER_INNODB_PK_NOT_IN_MYSQL 10883 +#define ER_INNODB_PK_ONLY_IN_MYSQL 10884 +#define ER_INNODB_CLUSTERED_INDEX_PRIVATE 10885 +//#define OBSOLETE_ER_INNODB_PARTITION_TABLE_LOWERCASED 10886 +#define ER_ERRMSG_REPLACEMENT_DODGY 10887 +#define ER_ERRMSG_REPLACEMENTS_FAILED 10888 +#define ER_NPIPE_CANT_CREATE 10889 +#define ER_PARTITION_MOVE_CREATED_DUPLICATE_ROW_PLEASE_FIX 10890 +#define ER_AUDIT_CANT_ABORT_COMMAND 10891 +#define ER_AUDIT_CANT_ABORT_EVENT 10892 +#define ER_AUDIT_WARNING 10893 +//#define OBSOLETE_ER_NDB_NUMBER_OF_CHANNELS 10894 +//#define OBSOLETE_ER_NDB_REPLICA_PARALLEL_WORKERS 10895 +//#define OBSOLETE_ER_NDB_DISTRIBUTING_ERR 10896 +#define ER_RPL_REPLICA_INSECURE_CHANGE_SOURCE 10897 +//#define OBSOLETE_ER_RPL_SLAVE_FLUSH_RELAY_LOGS_NOT_ALLOWED 10898 +#define ER_RPL_REPLICA_INCORRECT_CHANNEL 10899 +#define ER_FAILED_TO_FIND_DL_ENTRY 10900 +#define ER_FAILED_TO_OPEN_SHARED_LIBRARY 10901 +#define ER_THREAD_PRIORITY_IGNORED 10902 +#define ER_BINLOG_CACHE_SIZE_TOO_LARGE 10903 +#define ER_BINLOG_STMT_CACHE_SIZE_TOO_LARGE 10904 +#define ER_FAILED_TO_GENERATE_UNIQUE_LOGFILE 10905 +#define ER_FAILED_TO_READ_FILE 10906 +#define ER_FAILED_TO_WRITE_TO_FILE 10907 +#define ER_BINLOG_UNSAFE_MESSAGE_AND_STATEMENT 10908 +#define ER_FORCE_CLOSE_THREAD 10909 +#define ER_SERVER_SHUTDOWN_COMPLETE 10910 +#define ER_RPL_CANT_HAVE_SAME_BASENAME 10911 +#define ER_RPL_GTID_MODE_REQUIRES_ENFORCE_GTID_CONSISTENCY_ON 10912 +#define ER_WARN_NO_SERVERID_SPECIFIED 10913 +#define ER_ABORTING_USER_CONNECTION 10914 +#define ER_SQL_MODE_MERGED_WITH_STRICT_MODE 10915 +#define ER_GTID_PURGED_WAS_UPDATED 10916 +#define ER_GTID_EXECUTED_WAS_UPDATED 10917 +#define ER_DEPRECATE_MSG_WITH_REPLACEMENT 10918 +#define ER_TRG_CREATION_CTX_NOT_SET 10919 +#define ER_FILE_HAS_OLD_FORMAT 10920 +#define ER_VIEW_CREATION_CTX_NOT_SET 10921 +//#define OBSOLETE_ER_TABLE_NAME_CAUSES_TOO_LONG_PATH 10922 +#define ER_TABLE_UPGRADE_REQUIRED 10923 +#define ER_GET_ERRNO_FROM_STORAGE_ENGINE 10924 +#define ER_ACCESS_DENIED_ERROR_WITHOUT_PASSWORD 10925 +#define ER_ACCESS_DENIED_ERROR_WITH_PASSWORD 10926 +#define ER_ACCESS_DENIED_FOR_USER_ACCOUNT_LOCKED 10927 +//#define OBSOLETE_ER_MUST_CHANGE_EXPIRED_PASSWORD 10928 +#define ER_SYSTEM_TABLES_NOT_SUPPORTED_BY_STORAGE_ENGINE 10929 +//#define OBSOLETE_ER_FILESORT_TERMINATED 10930 +#define ER_SERVER_STARTUP_MSG 10931 +#define ER_FAILED_TO_FIND_LOCALE_NAME 10932 +#define ER_FAILED_TO_FIND_COLLATION_NAME 10933 +#define ER_SERVER_OUT_OF_RESOURCES 10934 +#define ER_SERVER_OUTOFMEMORY 10935 +#define ER_INVALID_COLLATION_FOR_CHARSET 10936 +#define ER_CANT_START_ERROR_LOG_SERVICE 10937 +#define ER_CREATING_NEW_UUID_FIRST_START 10938 +#define ER_FAILED_TO_GET_ABSOLUTE_PATH 10939 +#define ER_PERFSCHEMA_COMPONENTS_INFRASTRUCTURE_BOOTSTRAP 10940 +#define ER_PERFSCHEMA_COMPONENTS_INFRASTRUCTURE_SHUTDOWN 10941 +#define ER_DUP_FD_OPEN_FAILED 10942 +#define ER_SYSTEM_VIEW_INIT_FAILED 10943 +#define ER_RESOURCE_GROUP_POST_INIT_FAILED 10944 +#define ER_RESOURCE_GROUP_SUBSYSTEM_INIT_FAILED 10945 +#define ER_FAILED_START_MYSQLD_DAEMON 10946 +#define ER_CANNOT_CHANGE_TO_ROOT_DIR 10947 +#define ER_PERSISTENT_PRIVILEGES_BOOTSTRAP 10948 +#define ER_BASEDIR_SET_TO 10949 +#define ER_RPL_FILTER_ADD_WILD_DO_TABLE_FAILED 10950 +#define ER_RPL_FILTER_ADD_WILD_IGNORE_TABLE_FAILED 10951 +#define ER_PRIVILEGE_SYSTEM_INIT_FAILED 10952 +#define ER_CANNOT_SET_LOG_ERROR_SERVICES 10953 +#define ER_PERFSCHEMA_TABLES_INIT_FAILED 10954 +//#define OBSOLETE_ER_TX_EXTRACTION_ALGORITHM_FOR_BINLOG_TX_DEPEDENCY 10955 +//#define OBSOLETE_ER_INVALID_REPLICATION_TIMESTAMPS 10956 +//#define OBSOLETE_ER_RPL_TIMESTAMPS_RETURNED_TO_NORMAL 10957 +#define ER_BINLOG_FILE_OPEN_FAILED 10958 +#define ER_BINLOG_EVENT_WRITE_TO_STMT_CACHE_FAILED 10959 +#define ER_REPLICA_RELAY_LOG_TRUNCATE_INFO 10960 +#define ER_REPLICA_RELAY_LOG_PURGE_FAILED 10961 +#define ER_RPL_REPLICA_FILTER_CREATE_FAILED 10962 +#define ER_RPL_REPLICA_GLOBAL_FILTERS_COPY_FAILED 10963 +#define ER_RPL_REPLICA_RESET_FILTER_OPTIONS 10964 +#define ER_MISSING_GRANT_SYSTEM_TABLE 10965 +#define ER_MISSING_ACL_SYSTEM_TABLE 10966 +#define ER_ANONYMOUS_AUTH_ID_NOT_ALLOWED_IN_MANDATORY_ROLES 10967 +#define ER_UNKNOWN_AUTH_ID_IN_MANDATORY_ROLE 10968 +#define ER_WRITE_ROW_TO_PARTITION_FAILED 10969 +#define ER_RESOURCE_GROUP_METADATA_UPDATE_SKIPPED 10970 +#define ER_FAILED_TO_PERSIST_RESOURCE_GROUP_METADATA 10971 +#define ER_FAILED_TO_DESERIALIZE_RESOURCE_GROUP 10972 +#define ER_FAILED_TO_UPDATE_RESOURCE_GROUP 10973 +#define ER_RESOURCE_GROUP_VALIDATION_FAILED 10974 +#define ER_FAILED_TO_ALLOCATE_MEMORY_FOR_RESOURCE_GROUP 10975 +#define ER_FAILED_TO_ALLOCATE_MEMORY_FOR_RESOURCE_GROUP_HASH 10976 +#define ER_FAILED_TO_ADD_RESOURCE_GROUP_TO_MAP 10977 +#define ER_RESOURCE_GROUP_IS_DISABLED 10978 +#define ER_FAILED_TO_APPLY_RESOURCE_GROUP_CONTROLLER 10979 +#define ER_FAILED_TO_ACQUIRE_LOCK_ON_RESOURCE_GROUP 10980 +#define ER_PFS_NOTIFICATION_FUNCTION_REGISTER_FAILED 10981 +#define ER_RES_GRP_SET_THR_AFFINITY_FAILED 10982 +#define ER_RES_GRP_SET_THR_AFFINITY_TO_CPUS_FAILED 10983 +#define ER_RES_GRP_THD_UNBIND_FROM_CPU_FAILED 10984 +#define ER_RES_GRP_SET_THREAD_PRIORITY_FAILED 10985 +#define ER_RES_GRP_FAILED_TO_DETERMINE_NICE_CAPABILITY 10986 +#define ER_RES_GRP_FAILED_TO_GET_THREAD_HANDLE 10987 +#define ER_RES_GRP_GET_THREAD_PRIO_NOT_SUPPORTED 10988 +#define ER_RES_GRP_FAILED_DETERMINE_CPU_COUNT 10989 +#define ER_RES_GRP_FEATURE_NOT_AVAILABLE 10990 +#define ER_RES_GRP_INVALID_THREAD_PRIORITY 10991 +#define ER_RES_GRP_SOLARIS_PROCESSOR_BIND_TO_CPUID_FAILED 10992 +#define ER_RES_GRP_SOLARIS_PROCESSOR_BIND_TO_THREAD_FAILED 10993 +#define ER_RES_GRP_SOLARIS_PROCESSOR_AFFINITY_FAILED 10994 +#define ER_DD_UPGRADE_RENAME_IDX_STATS_FILE_FAILED 10995 +#define ER_DD_UPGRADE_DD_OPEN_FAILED 10996 +#define ER_DD_UPGRADE_FAILED_TO_FETCH_TABLESPACES 10997 +#define ER_DD_UPGRADE_FAILED_TO_ACQUIRE_TABLESPACE 10998 +#define ER_DD_UPGRADE_FAILED_TO_RESOLVE_TABLESPACE_ENGINE 10999 +#define ER_FAILED_TO_CREATE_SDI_FOR_TABLESPACE 11000 +#define ER_FAILED_TO_STORE_SDI_FOR_TABLESPACE 11001 +#define ER_DD_UPGRADE_FAILED_TO_FETCH_TABLES 11002 +#define ER_DD_UPGRADE_DD_POPULATED 11003 +#define ER_DD_UPGRADE_INFO_FILE_OPEN_FAILED 11004 +#define ER_DD_UPGRADE_INFO_FILE_CLOSE_FAILED 11005 +#define ER_DD_UPGRADE_TABLESPACE_MIGRATION_FAILED 11006 +#define ER_DD_UPGRADE_FAILED_TO_CREATE_TABLE_STATS 11007 +#define ER_DD_UPGRADE_TABLE_STATS_MIGRATE_COMPLETED 11008 +#define ER_DD_UPGRADE_FAILED_TO_CREATE_INDEX_STATS 11009 +#define ER_DD_UPGRADE_INDEX_STATS_MIGRATE_COMPLETED 11010 +#define ER_DD_UPGRADE_FAILED_FIND_VALID_DATA_DIR 11011 +#define ER_DD_UPGRADE_START 11012 +#define ER_DD_UPGRADE_FAILED_INIT_DD_SE 11013 +#define ER_DD_UPGRADE_FOUND_PARTIALLY_UPGRADED_DD_ABORT 11014 +#define ER_DD_UPGRADE_FOUND_PARTIALLY_UPGRADED_DD_CONTINUE 11015 +#define ER_DD_UPGRADE_SE_LOGS_FAILED 11016 +#define ER_DD_UPGRADE_SDI_INFO_UPDATE_FAILED 11017 +#define ER_SKIP_UPDATING_METADATA_IN_SE_RO_MODE 11018 +#define ER_CREATED_SYSTEM_WITH_VERSION 11019 +#define ER_UNKNOWN_ERROR_DETECTED_IN_SE 11020 +#define ER_READ_LOG_EVENT_FAILED 11021 +#define ER_ROW_DATA_TOO_BIG_TO_WRITE_IN_BINLOG 11022 +#define ER_FAILED_TO_CONSTRUCT_DROP_EVENT_QUERY 11023 +#define ER_FAILED_TO_BINLOG_DROP_EVENT 11024 +#define ER_FAILED_TO_START_REPLICA_THREAD 11025 +#define ER_RPL_IO_THREAD_KILLED 11026 +#define ER_REPLICA_RECONNECT_FAILED 11027 +#define ER_REPLICA_KILLED_AFTER_RECONNECT 11028 +#define ER_REPLICA_NOT_STARTED_ON_SOME_CHANNELS 11029 +#define ER_FAILED_TO_ADD_RPL_FILTER 11030 +#define ER_PER_CHANNEL_RPL_FILTER_CONF_FOR_GRP_RPL 11031 +#define ER_RPL_FILTERS_NOT_ATTACHED_TO_CHANNEL 11032 +#define ER_FAILED_TO_BUILD_DO_AND_IGNORE_TABLE_HASHES 11033 +#define ER_CLONE_PLUGIN_NOT_LOADED_TRACE 11034 +#define ER_CLONE_HANDLER_EXIST_TRACE 11035 +#define ER_CLONE_CREATE_HANDLER_FAIL_TRACE 11036 +#define ER_CYCLE_TIMER_IS_NOT_AVAILABLE 11037 +#define ER_NANOSECOND_TIMER_IS_NOT_AVAILABLE 11038 +#define ER_MICROSECOND_TIMER_IS_NOT_AVAILABLE 11039 +#define ER_PFS_MALLOC_ARRAY_OVERFLOW 11040 +#define ER_PFS_MALLOC_ARRAY_OOM 11041 +#define ER_INNODB_FAILED_TO_FIND_IDX_WITH_KEY_NO 11042 +#define ER_INNODB_FAILED_TO_FIND_IDX 11043 +#define ER_INNODB_FAILED_TO_FIND_IDX_FROM_DICT_CACHE 11044 +#define ER_INNODB_ACTIVE_INDEX_CHANGE_FAILED 11045 +#define ER_INNODB_DIFF_IN_REF_LEN 11046 +#define ER_WRONG_TYPE_FOR_COLUMN_PREFIX_IDX_FLD 11047 +#define ER_INNODB_CANNOT_CREATE_TABLE 11048 +#define ER_INNODB_INTERNAL_INDEX 11049 +#define ER_INNODB_IDX_CNT_MORE_THAN_DEFINED_IN_MYSQL 11050 +#define ER_INNODB_IDX_CNT_FEWER_THAN_DEFINED_IN_MYSQL 11051 +#define ER_INNODB_IDX_COLUMN_CNT_DIFF 11052 +#define ER_INNODB_USE_MONITOR_GROUP_NAME 11053 +#define ER_INNODB_MONITOR_DEFAULT_VALUE_NOT_DEFINED 11054 +#define ER_INNODB_MONITOR_IS_ENABLED 11055 +#define ER_INNODB_INVALID_MONITOR_COUNTER_NAME 11056 +#define ER_WIN_LOAD_LIBRARY_FAILED 11057 +#define ER_PARTITION_HANDLER_ADMIN_MSG 11058 +#define ER_RPL_AM_INIT_INFO_MSG 11059 +#define ER_DD_UPGRADE_TABLE_INTACT_ERROR 11060 +#define ER_SERVER_INIT_COMPILED_IN_COMMANDS 11061 +#define ER_MYISAM_CHECK_METHOD_ERROR 11062 +#define ER_MYISAM_CRASHED_ERROR 11063 +#define ER_WAITPID_FAILED 11064 +#define ER_FAILED_TO_FIND_MYSQLD_STATUS 11065 +#define ER_INNODB_ERROR_LOGGER_MSG 11066 +#define ER_INNODB_ERROR_LOGGER_FATAL_MSG 11067 +#define ER_DEPRECATED_SYNTAX_WITH_REPLACEMENT 11068 +#define ER_DEPRECATED_SYNTAX_NO_REPLACEMENT 11069 +#define ER_DEPRECATE_MSG_NO_REPLACEMENT 11070 +#define ER_LOG_PRINTF_MSG 11071 +#define ER_BINLOG_LOGGING_NOT_POSSIBLE 11072 +#define ER_FAILED_TO_SET_PERSISTED_OPTIONS 11073 +#define ER_COMPONENTS_FAILED_TO_ACQUIRE_SERVICE_IMPLEMENTATION 11074 +#define ER_RES_GRP_INVALID_VCPU_RANGE 11075 +#define ER_RES_GRP_INVALID_VCPU_ID 11076 +#define ER_ERROR_DURING_FLUSH_LOG_COMMIT_PHASE 11077 +#define ER_DROP_DATABASE_FAILED_RMDIR_MANUALLY 11078 +//#define OBSOLETE_ER_EXPIRE_LOGS_DAYS_IGNORED 11079 +#define ER_BINLOG_MALFORMED_OR_OLD_RELAY_LOG 11080 +#define ER_DD_UPGRADE_VIEW_COLUMN_NAME_TOO_LONG 11081 +#define ER_TABLE_NEEDS_DUMP_UPGRADE 11082 +#define ER_DD_UPGRADE_FAILED_TO_UPDATE_VER_NO_IN_TABLESPACE 11083 +#define ER_KEYRING_MIGRATION_FAILED 11084 +#define ER_KEYRING_MIGRATION_SUCCESSFUL 11085 +#define ER_RESTART_RECEIVED_INFO 11086 +#define ER_LCTN_CHANGED 11087 +#define ER_DD_INITIALIZE 11088 +#define ER_DD_RESTART 11089 +#define ER_DD_UPGRADE 11090 +#define ER_DD_UPGRADE_OFF 11091 +#define ER_DD_UPGRADE_VERSION_NOT_SUPPORTED 11092 +#define ER_DD_UPGRADE_SCHEMA_UNAVAILABLE 11093 +#define ER_DD_MINOR_DOWNGRADE 11094 +#define ER_DD_MINOR_DOWNGRADE_VERSION_NOT_SUPPORTED 11095 +#define ER_DD_NO_VERSION_FOUND 11096 +#define ER_THREAD_POOL_NOT_SUPPORTED_ON_PLATFORM 11097 +#define ER_THREAD_POOL_SIZE_TOO_LOW 11098 +#define ER_THREAD_POOL_SIZE_TOO_HIGH 11099 +#define ER_THREAD_POOL_ALGORITHM_INVALID 11100 +#define ER_THREAD_POOL_INVALID_STALL_LIMIT 11101 +#define ER_THREAD_POOL_INVALID_PRIO_KICKUP_TIMER 11102 +#define ER_THREAD_POOL_MAX_UNUSED_THREADS_INVALID 11103 +#define ER_THREAD_POOL_CON_HANDLER_INIT_FAILED 11104 +#define ER_THREAD_POOL_INIT_FAILED 11105 +//#define OBSOLETE_ER_THREAD_POOL_PLUGIN_STARTED 11106 +#define ER_THREAD_POOL_CANNOT_SET_THREAD_SPECIFIC_DATA 11107 +#define ER_THREAD_POOL_FAILED_TO_CREATE_CONNECT_HANDLER_THD 11108 +#define ER_THREAD_POOL_FAILED_TO_CREATE_THD_AND_AUTH_CONN 11109 +#define ER_THREAD_POOL_FAILED_PROCESS_CONNECT_EVENT 11110 +#define ER_THREAD_POOL_FAILED_TO_CREATE_POOL 11111 +#define ER_THREAD_POOL_RATE_LIMITED_ERROR_MSGS 11112 +#define ER_TRHEAD_POOL_LOW_LEVEL_INIT_FAILED 11113 +#define ER_THREAD_POOL_LOW_LEVEL_REARM_FAILED 11114 +#define ER_THREAD_POOL_BUFFER_TOO_SMALL 11115 +#define ER_MECAB_NOT_SUPPORTED 11116 +#define ER_MECAB_NOT_VERIFIED 11117 +#define ER_MECAB_CREATING_MODEL 11118 +#define ER_MECAB_FAILED_TO_CREATE_MODEL 11119 +#define ER_MECAB_FAILED_TO_CREATE_TRIGGER 11120 +#define ER_MECAB_UNSUPPORTED_CHARSET 11121 +#define ER_MECAB_CHARSET_LOADED 11122 +#define ER_MECAB_PARSE_FAILED 11123 +#define ER_MECAB_OOM_WHILE_PARSING_TEXT 11124 +#define ER_MECAB_CREATE_LATTICE_FAILED 11125 +#define ER_SEMISYNC_TRACE_ENTER_FUNC 11126 +#define ER_SEMISYNC_TRACE_EXIT_WITH_INT_EXIT_CODE 11127 +#define ER_SEMISYNC_TRACE_EXIT_WITH_BOOL_EXIT_CODE 11128 +#define ER_SEMISYNC_TRACE_EXIT 11129 +#define ER_SEMISYNC_RPL_INIT_FOR_TRX 11130 +#define ER_SEMISYNC_FAILED_TO_ALLOCATE_TRX_NODE 11131 +#define ER_SEMISYNC_BINLOG_WRITE_OUT_OF_ORDER 11132 +#define ER_SEMISYNC_INSERT_LOG_INFO_IN_ENTRY 11133 +#define ER_SEMISYNC_PROBE_LOG_INFO_IN_ENTRY 11134 +#define ER_SEMISYNC_CLEARED_ALL_ACTIVE_TRANSACTION_NODES 11135 +#define ER_SEMISYNC_CLEARED_ACTIVE_TRANSACTION_TILL_POS 11136 +#define ER_SEMISYNC_REPLY_MAGIC_NO_ERROR 11137 +#define ER_SEMISYNC_REPLY_PKT_LENGTH_TOO_SMALL 11138 +#define ER_SEMISYNC_REPLY_BINLOG_FILE_TOO_LARGE 11139 +#define ER_SEMISYNC_SERVER_REPLY 11140 +#define ER_SEMISYNC_FUNCTION_CALLED_TWICE 11141 +#define ER_SEMISYNC_RPL_ENABLED_ON_SOURCE 11142 +#define ER_SEMISYNC_SOURCE_OOM 11143 +#define ER_SEMISYNC_DISABLED_ON_SOURCE 11144 +#define ER_SEMISYNC_FORCED_SHUTDOWN 11145 +#define ER_SEMISYNC_SOURCE_GOT_REPLY_AT_POS 11146 +#define ER_SEMISYNC_SOURCE_SIGNAL_ALL_WAITING_THREADS 11147 +#define ER_SEMISYNC_SOURCE_TRX_WAIT_POS 11148 +#define ER_SEMISYNC_BINLOG_REPLY_IS_AHEAD 11149 +#define ER_SEMISYNC_MOVE_BACK_WAIT_POS 11150 +#define ER_SEMISYNC_INIT_WAIT_POS 11151 +#define ER_SEMISYNC_WAIT_TIME_FOR_BINLOG_SENT 11152 +#define ER_SEMISYNC_WAIT_FOR_BINLOG_TIMEDOUT 11153 +#define ER_SEMISYNC_WAIT_TIME_ASSESSMENT_FOR_COMMIT_TRX_FAILED 11154 +#define ER_SEMISYNC_RPL_SWITCHED_OFF 11155 +#define ER_SEMISYNC_RPL_SWITCHED_ON 11156 +#define ER_SEMISYNC_NO_SPACE_IN_THE_PKT 11157 +#define ER_SEMISYNC_SYNC_HEADER_UPDATE_INFO 11158 +#define ER_SEMISYNC_FAILED_TO_INSERT_TRX_NODE 11159 +#define ER_SEMISYNC_TRX_SKIPPED_AT_POS 11160 +#define ER_SEMISYNC_SOURCE_FAILED_ON_NET_FLUSH 11161 +#define ER_SEMISYNC_RECEIVED_ACK_IS_SMALLER 11162 +#define ER_SEMISYNC_ADD_ACK_TO_SLOT 11163 +#define ER_SEMISYNC_UPDATE_EXISTING_REPLICA_ACK 11164 +#define ER_SEMISYNC_FAILED_TO_START_ACK_RECEIVER_THD 11165 +#define ER_SEMISYNC_STARTING_ACK_RECEIVER_THD 11166 +#define ER_SEMISYNC_FAILED_TO_WAIT_ON_DUMP_SOCKET 11167 +#define ER_SEMISYNC_STOPPING_ACK_RECEIVER_THREAD 11168 +#define ER_SEMISYNC_FAILED_REGISTER_REPLICA_TO_RECEIVER 11169 +#define ER_SEMISYNC_START_BINLOG_DUMP_TO_REPLICA 11170 +#define ER_SEMISYNC_STOP_BINLOG_DUMP_TO_REPLICA 11171 +#define ER_SEMISYNC_UNREGISTER_TRX_OBSERVER_FAILED 11172 +#define ER_SEMISYNC_UNREGISTER_BINLOG_STORAGE_OBSERVER_FAILED 11173 +#define ER_SEMISYNC_UNREGISTER_BINLOG_TRANSMIT_OBSERVER_FAILED 11174 +#define ER_SEMISYNC_UNREGISTERED_REPLICATOR 11175 +#define ER_SEMISYNC_SOCKET_FD_TOO_LARGE 11176 +#define ER_SEMISYNC_REPLICA_REPLY 11177 +#define ER_SEMISYNC_MISSING_MAGIC_NO_FOR_SEMISYNC_PKT 11178 +#define ER_SEMISYNC_REPLICA_START 11179 +#define ER_SEMISYNC_REPLICA_REPLY_WITH_BINLOG_INFO 11180 +#define ER_SEMISYNC_REPLICA_NET_FLUSH_REPLY_FAILED 11181 +#define ER_SEMISYNC_REPLICA_SEND_REPLY_FAILED 11182 +#define ER_SEMISYNC_EXECUTION_FAILED_ON_SOURCE 11183 +#define ER_SEMISYNC_NOT_SUPPORTED_BY_SOURCE 11184 +#define ER_SEMISYNC_REPLICA_SET_FAILED 11185 +#define ER_SEMISYNC_FAILED_TO_STOP_ACK_RECEIVER_THD 11186 +#define ER_FIREWALL_FAILED_TO_READ_FIREWALL_TABLES 11187 +#define ER_FIREWALL_FAILED_TO_REG_DYNAMIC_PRIVILEGES 11188 +#define ER_FIREWALL_RECORDING_STMT_WAS_TRUNCATED 11189 +#define ER_FIREWALL_RECORDING_STMT_WITHOUT_TEXT 11190 +#define ER_FIREWALL_SUSPICIOUS_STMT 11191 +#define ER_FIREWALL_ACCESS_DENIED 11192 +#define ER_FIREWALL_SKIPPED_UNKNOWN_USER_MODE 11193 +#define ER_FIREWALL_RELOADING_CACHE 11194 +#define ER_FIREWALL_RESET_FOR_USER 11195 +#define ER_FIREWALL_STATUS_FLUSHED 11196 +#define ER_KEYRING_LOGGER_ERROR_MSG 11197 +#define ER_AUDIT_LOG_FILTER_IS_NOT_INSTALLED 11198 +#define ER_AUDIT_LOG_SWITCHING_TO_INCLUDE_LIST 11199 +#define ER_AUDIT_LOG_CANNOT_SET_LOG_POLICY_WITH_OTHER_POLICIES 11200 +#define ER_AUDIT_LOG_ONLY_INCLUDE_LIST_USED 11201 +#define ER_AUDIT_LOG_INDEX_MAP_CANNOT_ACCESS_DIR 11202 +#define ER_AUDIT_LOG_WRITER_RENAME_FILE_FAILED 11203 +#define ER_AUDIT_LOG_WRITER_DEST_FILE_ALREADY_EXISTS 11204 +#define ER_AUDIT_LOG_WRITER_RENAME_FILE_FAILED_REMOVE_FILE_MANUALLY 11205 +#define ER_AUDIT_LOG_WRITER_INCOMPLETE_FILE_RENAMED 11206 +#define ER_AUDIT_LOG_WRITER_FAILED_TO_WRITE_TO_FILE 11207 +#define ER_AUDIT_LOG_EC_WRITER_FAILED_TO_INIT_ENCRYPTION 11208 +#define ER_AUDIT_LOG_EC_WRITER_FAILED_TO_INIT_COMPRESSION 11209 +#define ER_AUDIT_LOG_EC_WRITER_FAILED_TO_CREATE_FILE 11210 +#define ER_AUDIT_LOG_RENAME_LOG_FILE_BEFORE_FLUSH 11211 +#define ER_AUDIT_LOG_FILTER_RESULT_MSG 11212 +#define ER_AUDIT_LOG_JSON_READER_FAILED_TO_PARSE 11213 +#define ER_AUDIT_LOG_JSON_READER_BUF_TOO_SMALL 11214 +#define ER_AUDIT_LOG_JSON_READER_FAILED_TO_OPEN_FILE 11215 +#define ER_AUDIT_LOG_JSON_READER_FILE_PARSING_ERROR 11216 +//#define OBSOLETE_ER_AUDIT_LOG_FILTER_INVALID_COLUMN_COUNT 11217 +//#define OBSOLETE_ER_AUDIT_LOG_FILTER_INVALID_COLUMN_DEFINITION 11218 +#define ER_AUDIT_LOG_FILTER_FAILED_TO_STORE_TABLE_FLDS 11219 +#define ER_AUDIT_LOG_FILTER_FAILED_TO_UPDATE_TABLE 11220 +#define ER_AUDIT_LOG_FILTER_FAILED_TO_INSERT_INTO_TABLE 11221 +#define ER_AUDIT_LOG_FILTER_FAILED_TO_DELETE_FROM_TABLE 11222 +#define ER_AUDIT_LOG_FILTER_FAILED_TO_INIT_TABLE_FOR_READ 11223 +#define ER_AUDIT_LOG_FILTER_FAILED_TO_READ_TABLE 11224 +#define ER_AUDIT_LOG_FILTER_FAILED_TO_CLOSE_TABLE_AFTER_READING 11225 +#define ER_AUDIT_LOG_FILTER_USER_AND_HOST_CANNOT_BE_EMPTY 11226 +#define ER_AUDIT_LOG_FILTER_FLD_FILTERNAME_CANNOT_BE_EMPTY 11227 +#define ER_VALIDATE_PWD_DICT_FILE_NOT_SPECIFIED 11228 +#define ER_VALIDATE_PWD_DICT_FILE_NOT_LOADED 11229 +#define ER_VALIDATE_PWD_DICT_FILE_TOO_BIG 11230 +#define ER_VALIDATE_PWD_FAILED_TO_READ_DICT_FILE 11231 +#define ER_VALIDATE_PWD_FAILED_TO_GET_FLD_FROM_SECURITY_CTX 11232 +#define ER_VALIDATE_PWD_FAILED_TO_GET_SECURITY_CTX 11233 +#define ER_VALIDATE_PWD_LENGTH_CHANGED 11234 +#define ER_REWRITER_QUERY_ERROR_MSG 11235 +#define ER_REWRITER_QUERY_FAILED 11236 +#define ER_XPLUGIN_STARTUP_FAILED 11237 +//#define OBSOLETE_ER_XPLUGIN_SERVER_EXITING 11238 +//#define OBSOLETE_ER_XPLUGIN_SERVER_EXITED 11239 +#define ER_XPLUGIN_USING_SSL_CONF_FROM_SERVER 11240 +#define ER_XPLUGIN_USING_SSL_CONF_FROM_MYSQLX 11241 +#define ER_XPLUGIN_FAILED_TO_USE_SSL_CONF 11242 +#define ER_XPLUGIN_USING_SSL_FOR_TLS_CONNECTION 11243 +#define ER_XPLUGIN_REFERENCE_TO_SECURE_CONN_WITH_XPLUGIN 11244 +#define ER_XPLUGIN_ERROR_MSG 11245 +#define ER_SHA_PWD_FAILED_TO_PARSE_AUTH_STRING 11246 +#define ER_SHA_PWD_FAILED_TO_GENERATE_MULTI_ROUND_HASH 11247 +#define ER_SHA_PWD_AUTH_REQUIRES_RSA_OR_SSL 11248 +#define ER_SHA_PWD_RSA_KEY_TOO_LONG 11249 +#define ER_PLUGIN_COMMON_FAILED_TO_OPEN_FILTER_TABLES 11250 +#define ER_PLUGIN_COMMON_FAILED_TO_OPEN_TABLE 11251 +#define ER_AUTH_LDAP_ERROR_LOGGER_ERROR_MSG 11252 +#define ER_CONN_CONTROL_ERROR_MSG 11253 +#define ER_GRP_RPL_ERROR_MSG 11254 +#define ER_SHA_PWD_SALT_FOR_USER_CORRUPT 11255 +#define ER_SYS_VAR_COMPONENT_OOM 11256 +#define ER_SYS_VAR_COMPONENT_VARIABLE_SET_READ_ONLY 11257 +#define ER_SYS_VAR_COMPONENT_UNKNOWN_VARIABLE_TYPE 11258 +#define ER_SYS_VAR_COMPONENT_FAILED_TO_PARSE_VARIABLE_OPTIONS 11259 +#define ER_SYS_VAR_COMPONENT_FAILED_TO_MAKE_VARIABLE_PERSISTENT 11260 +#define ER_COMPONENT_FILTER_CONFUSED 11261 +#define ER_STOP_REPLICA_IO_THREAD_DISK_SPACE 11262 +#define ER_LOG_FILE_CANNOT_OPEN 11263 +//#define OBSOLETE_ER_UNABLE_TO_COLLECT_LOG_STATUS 11264 +//#define OBSOLETE_ER_DEPRECATED_UTF8_ALIAS 11265 +//#define OBSOLETE_ER_DEPRECATED_NATIONAL 11266 +//#define OBSOLETE_ER_SLAVE_POSSIBLY_DIVERGED_AFTER_DDL 11267 +#define ER_PERSIST_OPTION_STATUS 11268 +#define ER_NOT_IMPLEMENTED_GET_TABLESPACE_STATISTICS 11269 +//#define OBSOLETE_ER_UNABLE_TO_SET_OPTION 11270 +//#define OBSOLETE_ER_RESERVED_TABLESPACE_NAME 11271 +#define ER_SSL_FIPS_MODE_ERROR 11272 +#define ER_CONN_INIT_CONNECT_IGNORED 11273 +//#define OBSOLETE_ER_UNSUPPORTED_SQL_MODE 11274 +#define ER_REWRITER_OOM 11275 +#define ER_REWRITER_TABLE_MALFORMED_ERROR 11276 +#define ER_REWRITER_LOAD_FAILED 11277 +#define ER_REWRITER_READ_FAILED 11278 +#define ER_CONN_CONTROL_EVENT_COORDINATOR_INIT_FAILED 11279 +#define ER_CONN_CONTROL_STAT_CONN_DELAY_TRIGGERED_UPDATE_FAILED 11280 +#define ER_CONN_CONTROL_STAT_CONN_DELAY_TRIGGERED_RESET_FAILED 11281 +#define ER_CONN_CONTROL_INVALID_CONN_DELAY_TYPE 11282 +#define ER_CONN_CONTROL_DELAY_ACTION_INIT_FAILED 11283 +#define ER_CONN_CONTROL_FAILED_TO_SET_CONN_DELAY 11284 +#define ER_CONN_CONTROL_FAILED_TO_UPDATE_CONN_DELAY_HASH 11285 +#define ER_XPLUGIN_FORCE_STOP_CLIENT 11286 +#define ER_XPLUGIN_MAX_AUTH_ATTEMPTS_REACHED 11287 +#define ER_XPLUGIN_BUFFER_PAGE_ALLOC_FAILED 11288 +#define ER_XPLUGIN_DETECTED_HANGING_CLIENTS 11289 +#define ER_XPLUGIN_FAILED_TO_ACCEPT_CLIENT 11290 +#define ER_XPLUGIN_FAILED_TO_SCHEDULE_CLIENT 11291 +#define ER_XPLUGIN_FAILED_TO_PREPARE_IO_INTERFACES 11292 +#define ER_XPLUGIN_SRV_SESSION_INIT_THREAD_FAILED 11293 +#define ER_XPLUGIN_UNABLE_TO_USE_USER_SESSION_ACCOUNT 11294 +#define ER_XPLUGIN_REFERENCE_TO_USER_ACCOUNT_DOC_SECTION 11295 +#define ER_XPLUGIN_UNEXPECTED_EXCEPTION_DISPATCHING_CMD 11296 +#define ER_XPLUGIN_EXCEPTION_IN_TASK_SCHEDULER 11297 +#define ER_XPLUGIN_TASK_SCHEDULING_FAILED 11298 +#define ER_XPLUGIN_EXCEPTION_IN_EVENT_LOOP 11299 +#define ER_XPLUGIN_LISTENER_SETUP_FAILED 11300 +#define ER_XPLUING_NET_STARTUP_FAILED 11301 +#define ER_XPLUGIN_FAILED_AT_SSL_CONF 11302 +//#define OBSOLETE_ER_XPLUGIN_CLIENT_SSL_HANDSHAKE_FAILED 11303 +//#define OBSOLETE_ER_XPLUGIN_SSL_HANDSHAKE_WITH_SERVER_FAILED 11304 +#define ER_XPLUGIN_FAILED_TO_CREATE_SESSION_FOR_CONN 11305 +#define ER_XPLUGIN_FAILED_TO_INITIALIZE_SESSION 11306 +#define ER_XPLUGIN_MESSAGE_TOO_LONG 11307 +#define ER_XPLUGIN_UNINITIALIZED_MESSAGE 11308 +#define ER_XPLUGIN_FAILED_TO_SET_MIN_NUMBER_OF_WORKERS 11309 +#define ER_XPLUGIN_UNABLE_TO_ACCEPT_CONNECTION 11310 +#define ER_XPLUGIN_ALL_IO_INTERFACES_DISABLED 11311 +//#define OBSOLETE_ER_XPLUGIN_INVALID_MSG_DURING_CLIENT_INIT 11312 +//#define OBSOLETE_ER_XPLUGIN_CLOSING_CLIENTS_ON_SHUTDOWN 11313 +#define ER_XPLUGIN_ERROR_READING_SOCKET 11314 +#define ER_XPLUGIN_PEER_DISCONNECTED_WHILE_READING_MSG_BODY 11315 +#define ER_XPLUGIN_READ_FAILED_CLOSING_CONNECTION 11316 +//#define OBSOLETE_ER_XPLUGIN_INVALID_AUTH_METHOD 11317 +//#define OBSOLETE_ER_XPLUGIN_UNEXPECTED_MSG_DURING_AUTHENTICATION 11318 +//#define OBSOLETE_ER_XPLUGIN_ERROR_WRITING_TO_CLIENT 11319 +//#define OBSOLETE_ER_XPLUGIN_SCHEDULER_STARTED 11320 +//#define OBSOLETE_ER_XPLUGIN_SCHEDULER_STOPPED 11321 +#define ER_XPLUGIN_LISTENER_SYS_VARIABLE_ERROR 11322 +#define ER_XPLUGIN_LISTENER_STATUS_MSG 11323 +#define ER_XPLUGIN_RETRYING_BIND_ON_PORT 11324 +//#define OBSOLETE_ER_XPLUGIN_SHUTDOWN_TRIGGERED 11325 +//#define OBSOLETE_ER_XPLUGIN_USER_ACCOUNT_WITH_ALL_PERMISSIONS 11326 +#define ER_XPLUGIN_EXISTING_USER_ACCOUNT_WITH_INCOMPLETE_GRANTS 11327 +//#define OBSOLETE_ER_XPLUGIN_SERVER_STARTS_HANDLING_CONNECTIONS 11328 +//#define OBSOLETE_ER_XPLUGIN_SERVER_STOPPED_HANDLING_CONNECTIONS 11329 +//#define OBSOLETE_ER_XPLUGIN_FAILED_TO_INTERRUPT_SESSION 11330 +//#define OBSOLETE_ER_XPLUGIN_CLIENT_RELEASE_TRIGGERED 11331 +#define ER_XPLUGIN_IPv6_AVAILABLE 11332 +//#define OBSOLETE_ER_XPLUGIN_UNIX_SOCKET_NOT_CONFIGURED 11333 +#define ER_XPLUGIN_CLIENT_KILL_MSG 11334 +#define ER_XPLUGIN_FAILED_TO_GET_SECURITY_CTX 11335 +//#define OBSOLETE_ER_XPLUGIN_FAILED_TO_SWITCH_SECURITY_CTX_TO_ROOT 11336 +#define ER_XPLUGIN_FAILED_TO_CLOSE_SQL_SESSION 11337 +#define ER_XPLUGIN_FAILED_TO_EXECUTE_ADMIN_CMD 11338 +#define ER_XPLUGIN_EMPTY_ADMIN_CMD 11339 +#define ER_XPLUGIN_FAILED_TO_GET_SYS_VAR 11340 +#define ER_XPLUGIN_FAILED_TO_GET_CREATION_STMT 11341 +#define ER_XPLUGIN_FAILED_TO_GET_ENGINE_INFO 11342 +//#define OBSOLETE_ER_XPLUGIN_FAIL_TO_GET_RESULT_DATA 11343 +//#define OBSOLETE_ER_XPLUGIN_CAPABILITY_EXPIRED_PASSWORD 11344 +#define ER_XPLUGIN_FAILED_TO_SET_SO_REUSEADDR_FLAG 11345 +#define ER_XPLUGIN_FAILED_TO_OPEN_INTERNAL_SESSION 11346 +#define ER_XPLUGIN_FAILED_TO_SWITCH_CONTEXT 11347 +#define ER_XPLUGIN_FAILED_TO_UNREGISTER_UDF 11348 +//#define OBSOLETE_ER_XPLUGIN_GET_PEER_ADDRESS_FAILED 11349 +//#define OBSOLETE_ER_XPLUGIN_CAPABILITY_CLIENT_INTERACTIVE_FAILED 11350 +#define ER_XPLUGIN_FAILED_TO_RESET_IPV6_V6ONLY_FLAG 11351 +#define ER_KEYRING_INVALID_KEY_TYPE 11352 +#define ER_KEYRING_INVALID_KEY_LENGTH 11353 +//#define OBSOLETE_ER_KEYRING_FAILED_TO_CREATE_KEYRING_DIR 11354 +//#define OBSOLETE_ER_KEYRING_FILE_INIT_FAILED 11355 +//#define OBSOLETE_ER_KEYRING_INTERNAL_EXCEPTION_FAILED_FILE_INIT 11356 +//#define OBSOLETE_ER_KEYRING_FAILED_TO_GENERATE_KEY 11357 +#define ER_KEYRING_CHECK_KEY_FAILED_DUE_TO_INVALID_KEY 11358 +#define ER_KEYRING_CHECK_KEY_FAILED_DUE_TO_EMPTY_KEY_ID 11359 +#define ER_KEYRING_OPERATION_FAILED_DUE_TO_INTERNAL_ERROR 11360 +#define ER_KEYRING_INCORRECT_FILE 11361 +#define ER_KEYRING_FOUND_MALFORMED_BACKUP_FILE 11362 +#define ER_KEYRING_FAILED_TO_RESTORE_FROM_BACKUP_FILE 11363 +#define ER_KEYRING_FAILED_TO_FLUSH_KEYRING_TO_FILE 11364 +#define ER_KEYRING_FAILED_TO_GET_FILE_STAT 11365 +#define ER_KEYRING_FAILED_TO_REMOVE_FILE 11366 +#define ER_KEYRING_FAILED_TO_TRUNCATE_FILE 11367 +#define ER_KEYRING_UNKNOWN_ERROR 11368 +//#define OBSOLETE_ER_KEYRING_FAILED_TO_SET_KEYRING_FILE_DATA 11369 +#define ER_KEYRING_FILE_IO_ERROR 11370 +#define ER_KEYRING_FAILED_TO_LOAD_KEYRING_CONTENT 11371 +#define ER_KEYRING_FAILED_TO_FLUSH_KEYS_TO_KEYRING 11372 +#define ER_KEYRING_FAILED_TO_FLUSH_KEYS_TO_KEYRING_BACKUP 11373 +#define ER_KEYRING_KEY_FETCH_FAILED_DUE_TO_EMPTY_KEY_ID 11374 +#define ER_KEYRING_FAILED_TO_REMOVE_KEY_DUE_TO_EMPTY_ID 11375 +#define ER_KEYRING_OKV_INCORRECT_KEY_VAULT_CONFIGURED 11376 +#define ER_KEYRING_OKV_INIT_FAILED_DUE_TO_INCORRECT_CONF 11377 +#define ER_KEYRING_OKV_INIT_FAILED_DUE_TO_INTERNAL_ERROR 11378 +#define ER_KEYRING_OKV_INVALID_KEY_TYPE 11379 +#define ER_KEYRING_OKV_INVALID_KEY_LENGTH_FOR_CIPHER 11380 +#define ER_KEYRING_OKV_FAILED_TO_GENERATE_KEY_DUE_TO_INTERNAL_ERROR 11381 +#define ER_KEYRING_OKV_FAILED_TO_FIND_SERVER_ENTRY 11382 +#define ER_KEYRING_OKV_FAILED_TO_FIND_STANDBY_SERVER_ENTRY 11383 +#define ER_KEYRING_OKV_FAILED_TO_PARSE_CONF_FILE 11384 +#define ER_KEYRING_OKV_FAILED_TO_LOAD_KEY_UID 11385 +#define ER_KEYRING_OKV_FAILED_TO_INIT_SSL_LAYER 11386 +#define ER_KEYRING_OKV_FAILED_TO_INIT_CLIENT 11387 +#define ER_KEYRING_OKV_CONNECTION_TO_SERVER_FAILED 11388 +#define ER_KEYRING_OKV_FAILED_TO_REMOVE_KEY 11389 +#define ER_KEYRING_OKV_FAILED_TO_ADD_ATTRIBUTE 11390 +#define ER_KEYRING_OKV_FAILED_TO_GENERATE_KEY 11391 +#define ER_KEYRING_OKV_FAILED_TO_STORE_KEY 11392 +#define ER_KEYRING_OKV_FAILED_TO_ACTIVATE_KEYS 11393 +#define ER_KEYRING_OKV_FAILED_TO_FETCH_KEY 11394 +#define ER_KEYRING_OKV_FAILED_TO_STORE_OR_GENERATE_KEY 11395 +#define ER_KEYRING_OKV_FAILED_TO_RETRIEVE_KEY_SIGNATURE 11396 +#define ER_KEYRING_OKV_FAILED_TO_RETRIEVE_KEY 11397 +#define ER_KEYRING_OKV_FAILED_TO_LOAD_SSL_TRUST_STORE 11398 +#define ER_KEYRING_OKV_FAILED_TO_SET_CERTIFICATE_FILE 11399 +#define ER_KEYRING_OKV_FAILED_TO_SET_KEY_FILE 11400 +#define ER_KEYRING_OKV_KEY_MISMATCH 11401 +//#define OBSOLETE_ER_KEYRING_ENCRYPTED_FILE_INCORRECT_KEYRING_FILE 11402 +//#define OBSOLETE_ER_KEYRING_ENCRYPTED_FILE_DECRYPTION_FAILED 11403 +//#define OBSOLETE_ER_KEYRING_ENCRYPTED_FILE_FOUND_MALFORMED_BACKUP_FILE 11404 +//#define OBSOLETE_ER_KEYRING_ENCRYPTED_FILE_FAILED_TO_RESTORE_KEYRING 11405 +//#define OBSOLETE_ER_KEYRING_ENCRYPTED_FILE_FAILED_TO_FLUSH_KEYRING 11406 +//#define OBSOLETE_ER_KEYRING_ENCRYPTED_FILE_ENCRYPTION_FAILED 11407 +//#define OBSOLETE_ER_KEYRING_ENCRYPTED_FILE_INVALID_KEYRING_DIR 11408 +//#define OBSOLETE_ER_KEYRING_ENCRYPTED_FILE_FAILED_TO_CREATE_KEYRING_DIR 11409 +//#define OBSOLETE_ER_KEYRING_ENCRYPTED_FILE_PASSWORD_IS_INVALID 11410 +//#define OBSOLETE_ER_KEYRING_ENCRYPTED_FILE_PASSWORD_IS_TOO_LONG 11411 +//#define OBSOLETE_ER_KEYRING_ENCRYPTED_FILE_INIT_FAILURE 11412 +//#define OBSOLETE_ER_KEYRING_ENCRYPTED_FILE_INIT_FAILED_INTERNAL_ERROR 11413 +//#define OBSOLETE_ER_KEYRING_ENCRYPTED_FILE_GEN_KEY_FAILED_INTERNAL_ERROR 11414 +#define ER_KEYRING_AWS_FAILED_TO_SET_CMK_ID 11415 +#define ER_KEYRING_AWS_FAILED_TO_SET_REGION 11416 +#define ER_KEYRING_AWS_FAILED_TO_OPEN_CONF_FILE 11417 +#define ER_KEYRING_AWS_FAILED_TO_ACCESS_KEY_ID_FROM_CONF_FILE 11418 +#define ER_KEYRING_AWS_FAILED_TO_ACCESS_KEY_FROM_CONF_FILE 11419 +#define ER_KEYRING_AWS_INVALID_CONF_FILE_PATH 11420 +#define ER_KEYRING_AWS_INVALID_DATA_FILE_PATH 11421 +#define ER_KEYRING_AWS_FAILED_TO_ACCESS_OR_CREATE_KEYRING_DIR 11422 +#define ER_KEYRING_AWS_FAILED_TO_ACCESS_OR_CREATE_KEYRING_DATA_FILE 11423 +#define ER_KEYRING_AWS_FAILED_TO_INIT_DUE_TO_INTERNAL_ERROR 11424 +#define ER_KEYRING_AWS_FAILED_TO_ACCESS_DATA_FILE 11425 +#define ER_KEYRING_AWS_CMK_ID_NOT_SET 11426 +#define ER_KEYRING_AWS_FAILED_TO_GET_KMS_CREDENTIAL_FROM_CONF_FILE 11427 +#define ER_KEYRING_AWS_INIT_FAILURE 11428 +#define ER_KEYRING_AWS_FAILED_TO_INIT_DUE_TO_PLUGIN_INTERNAL_ERROR 11429 +#define ER_KEYRING_AWS_INVALID_KEY_LENGTH_FOR_CIPHER 11430 +#define ER_KEYRING_AWS_FAILED_TO_GENERATE_KEY_DUE_TO_INTERNAL_ERROR 11431 +#define ER_KEYRING_AWS_INCORRECT_FILE 11432 +#define ER_KEYRING_AWS_FOUND_MALFORMED_BACKUP_FILE 11433 +#define ER_KEYRING_AWS_FAILED_TO_RESTORE_FROM_BACKUP_FILE 11434 +#define ER_KEYRING_AWS_FAILED_TO_FLUSH_KEYRING_TO_FILE 11435 +#define ER_KEYRING_AWS_INCORRECT_REGION 11436 +#define ER_KEYRING_AWS_FAILED_TO_CONNECT_KMS 11437 +#define ER_KEYRING_AWS_FAILED_TO_GENERATE_NEW_KEY 11438 +#define ER_KEYRING_AWS_FAILED_TO_ENCRYPT_KEY 11439 +#define ER_KEYRING_AWS_FAILED_TO_RE_ENCRYPT_KEY 11440 +#define ER_KEYRING_AWS_FAILED_TO_DECRYPT_KEY 11441 +#define ER_KEYRING_AWS_FAILED_TO_ROTATE_CMK 11442 +#define ER_GRP_RPL_GTID_ALREADY_USED 11443 +#define ER_GRP_RPL_APPLIER_THD_KILLED 11444 +#define ER_GRP_RPL_EVENT_HANDLING_ERROR 11445 +#define ER_GRP_RPL_ERROR_GTID_EXECUTION_INFO 11446 +//#define OBSOLETE_ER_GRP_RPL_CERTIFICATE_SIZE_ERROR 11447 +#define ER_GRP_RPL_CREATE_APPLIER_CACHE_ERROR 11448 +#define ER_GRP_RPL_UNBLOCK_WAITING_THD 11449 +#define ER_GRP_RPL_APPLIER_PIPELINE_NOT_DISPOSED 11450 +#define ER_GRP_RPL_APPLIER_THD_EXECUTION_ABORTED 11451 +#define ER_GRP_RPL_APPLIER_EXECUTION_FATAL_ERROR 11452 +#define ER_GRP_RPL_ERROR_STOPPING_CHANNELS 11453 +#define ER_GRP_RPL_ERROR_SENDING_SINGLE_PRIMARY_MSSG 11454 +//#define OBSOLETE_ER_GRP_RPL_UPDATE_TRANS_SNAPSHOT_VER_ERROR 11455 +//#define OBSOLETE_ER_GRP_RPL_SIDNO_FETCH_ERROR 11456 +#define ER_GRP_RPL_BROADCAST_COMMIT_TRANS_MSSG_FAILED 11457 +#define ER_GRP_RPL_GROUP_NAME_PARSE_ERROR 11458 +#define ER_GRP_RPL_ADD_GRPSID_TO_GRPGTIDSID_MAP_ERROR 11459 +#define ER_GRP_RPL_UPDATE_GRPGTID_EXECUTED_ERROR 11460 +#define ER_GRP_RPL_DONOR_TRANS_INFO_ERROR 11461 +#define ER_GRP_RPL_SERVER_CONN_ERROR 11462 +#define ER_GRP_RPL_ERROR_FETCHING_GTID_EXECUTED_SET 11463 +#define ER_GRP_RPL_ADD_GTID_TO_GRPGTID_EXECUTED_ERROR 11464 +#define ER_GRP_RPL_ERROR_FETCHING_GTID_SET 11465 +#define ER_GRP_RPL_ADD_RETRIEVED_SET_TO_GRP_GTID_EXECUTED_ERROR 11466 +#define ER_GRP_RPL_CERTIFICATION_INITIALIZATION_FAILURE 11467 +#define ER_GRP_RPL_UPDATE_LAST_CONFLICT_FREE_TRANS_ERROR 11468 +#define ER_GRP_RPL_UPDATE_TRANS_SNAPSHOT_REF_VER_ERROR 11469 +//#define OBSOLETE_ER_GRP_RPL_FETCH_TRANS_SIDNO_ERROR 11470 +//#define OBSOLETE_ER_GRP_RPL_ERROR_VERIFYING_SIDNO 11471 +#define ER_GRP_RPL_CANT_GENERATE_GTID 11472 +#define ER_GRP_RPL_INVALID_GTID_SET 11473 +#define ER_GRP_RPL_UPDATE_GTID_SET_ERROR 11474 +#define ER_GRP_RPL_RECEIVED_SET_MISSING_GTIDS 11475 +//#define OBSOLETE_ER_GRP_RPL_SKIP_COMPUTATION_TRANS_COMMITTED 11476 +#define ER_GRP_RPL_NULL_PACKET 11477 +#define ER_GRP_RPL_CANT_READ_GTID 11478 +#define ER_GRP_RPL_PROCESS_GTID_SET_ERROR 11479 +#define ER_GRP_RPL_PROCESS_INTERSECTION_GTID_SET_ERROR 11480 +#define ER_GRP_RPL_SET_STABLE_TRANS_ERROR 11481 +#define ER_GRP_RPL_CANT_READ_GRP_GTID_EXTRACTED 11482 +#define ER_GRP_RPL_CANT_READ_WRITE_SET_ITEM 11483 +#define ER_GRP_RPL_INIT_CERTIFICATION_INFO_FAILURE 11484 +#define ER_GRP_RPL_CONFLICT_DETECTION_DISABLED 11485 +#define ER_GRP_RPL_MSG_DISCARDED 11486 +#define ER_GRP_RPL_MISSING_GRP_RPL_APPLIER 11487 +#define ER_GRP_RPL_CERTIFIER_MSSG_PROCESS_ERROR 11488 +#define ER_GRP_RPL_SRV_NOT_ONLINE 11489 +#define ER_GRP_RPL_SRV_ONLINE 11490 +#define ER_GRP_RPL_DISABLE_SRV_READ_MODE_RESTRICTED 11491 +#define ER_GRP_RPL_MEM_ONLINE 11492 +#define ER_GRP_RPL_MEM_UNREACHABLE 11493 +#define ER_GRP_RPL_MEM_REACHABLE 11494 +#define ER_GRP_RPL_SRV_BLOCKED 11495 +#define ER_GRP_RPL_SRV_BLOCKED_FOR_SECS 11496 +#define ER_GRP_RPL_CHANGE_GRP_MEM_NOT_PROCESSED 11497 +#define ER_GRP_RPL_MEMBER_CONTACT_RESTORED 11498 +#define ER_GRP_RPL_MEMBER_REMOVED 11499 +#define ER_GRP_RPL_PRIMARY_MEMBER_LEFT_GRP 11500 +#define ER_GRP_RPL_MEMBER_ADDED 11501 +#define ER_GRP_RPL_MEMBER_EXIT_PLUGIN_ERROR 11502 +#define ER_GRP_RPL_MEMBER_CHANGE 11503 +#define ER_GRP_RPL_MEMBER_LEFT_GRP 11504 +#define ER_GRP_RPL_MEMBER_EXPELLED 11505 +#define ER_GRP_RPL_SESSION_OPEN_FAILED 11506 +#define ER_GRP_RPL_NEW_PRIMARY_ELECTED 11507 +#define ER_GRP_RPL_DISABLE_READ_ONLY_FAILED 11508 +#define ER_GRP_RPL_ENABLE_READ_ONLY_FAILED 11509 +#define ER_GRP_RPL_SRV_PRIMARY_MEM 11510 +#define ER_GRP_RPL_SRV_SECONDARY_MEM 11511 +#define ER_GRP_RPL_NO_SUITABLE_PRIMARY_MEM 11512 +#define ER_GRP_RPL_SUPER_READ_ONLY_ACTIVATE_ERROR 11513 +#define ER_GRP_RPL_EXCEEDS_AUTO_INC_VALUE 11514 +#define ER_GRP_RPL_DATA_NOT_PROVIDED_BY_MEM 11515 +#define ER_GRP_RPL_MEMBER_ALREADY_EXISTS 11516 +//#define OBSOLETE_ER_GRP_RPL_GRP_CHANGE_INFO_EXTRACT_ERROR 11517 +#define ER_GRP_RPL_GTID_EXECUTED_EXTRACT_ERROR 11518 +#define ER_GRP_RPL_GTID_SET_EXTRACT_ERROR 11519 +#define ER_GRP_RPL_START_FAILED 11520 +#define ER_GRP_RPL_MEMBER_VER_INCOMPATIBLE 11521 +#define ER_GRP_RPL_TRANS_NOT_PRESENT_IN_GRP 11522 +#define ER_GRP_RPL_TRANS_GREATER_THAN_GRP 11523 +#define ER_GRP_RPL_MEMBER_VERSION_LOWER_THAN_GRP 11524 +#define ER_GRP_RPL_LOCAL_GTID_SETS_PROCESS_ERROR 11525 +#define ER_GRP_RPL_MEMBER_TRANS_GREATER_THAN_GRP 11526 +#define ER_GRP_RPL_BLOCK_SIZE_DIFF_FROM_GRP 11527 +#define ER_GRP_RPL_TRANS_WRITE_SET_EXTRACT_DIFF_FROM_GRP 11528 +#define ER_GRP_RPL_MEMBER_CFG_INCOMPATIBLE_WITH_GRP_CFG 11529 +#define ER_GRP_RPL_MEMBER_STOP_RPL_CHANNELS_ERROR 11530 +#define ER_GRP_RPL_PURGE_APPLIER_LOGS 11531 +#define ER_GRP_RPL_RESET_APPLIER_MODULE_LOGS_ERROR 11532 +#define ER_GRP_RPL_APPLIER_THD_SETUP_ERROR 11533 +#define ER_GRP_RPL_APPLIER_THD_START_ERROR 11534 +#define ER_GRP_RPL_APPLIER_THD_STOP_ERROR 11535 +#define ER_GRP_RPL_FETCH_TRANS_DATA_FAILED 11536 +#define ER_GRP_RPL_REPLICA_IO_THD_PRIMARY_UNKNOWN 11537 +#define ER_GRP_RPL_SALVE_IO_THD_ON_SECONDARY_MEMBER 11538 +#define ER_GRP_RPL_REPLICA_SQL_THD_PRIMARY_UNKNOWN 11539 +#define ER_GRP_RPL_REPLICA_SQL_THD_ON_SECONDARY_MEMBER 11540 +#define ER_GRP_RPL_NEEDS_INNODB_TABLE 11541 +#define ER_GRP_RPL_PRIMARY_KEY_NOT_DEFINED 11542 +#define ER_GRP_RPL_FK_WITH_CASCADE_UNSUPPORTED 11543 +#define ER_GRP_RPL_AUTO_INC_RESET 11544 +#define ER_GRP_RPL_AUTO_INC_OFFSET_RESET 11545 +#define ER_GRP_RPL_AUTO_INC_SET 11546 +#define ER_GRP_RPL_AUTO_INC_OFFSET_SET 11547 +#define ER_GRP_RPL_FETCH_TRANS_CONTEXT_FAILED 11548 +#define ER_GRP_RPL_FETCH_FORMAT_DESC_LOG_EVENT_FAILED 11549 +#define ER_GRP_RPL_FETCH_TRANS_CONTEXT_LOG_EVENT_FAILED 11550 +#define ER_GRP_RPL_FETCH_SNAPSHOT_VERSION_FAILED 11551 +#define ER_GRP_RPL_FETCH_GTID_LOG_EVENT_FAILED 11552 +#define ER_GRP_RPL_UPDATE_SERV_CERTIFICATE_FAILED 11553 +#define ER_GRP_RPL_ADD_GTID_INFO_WITH_LOCAL_GTID_FAILED 11554 +#define ER_GRP_RPL_ADD_GTID_INFO_WITHOUT_LOCAL_GTID_FAILED 11555 +#define ER_GRP_RPL_NOTIFY_CERTIFICATION_OUTCOME_FAILED 11556 +#define ER_GRP_RPL_ADD_GTID_INFO_WITH_REMOTE_GTID_FAILED 11557 +#define ER_GRP_RPL_ADD_GTID_INFO_WITHOUT_REMOTE_GTID_FAILED 11558 +#define ER_GRP_RPL_FETCH_VIEW_CHANGE_LOG_EVENT_FAILED 11559 +//#define OBSOLETE_ER_GRP_RPL_CONTACT_WITH_SRV_FAILED 11560 +//#define OBSOLETE_ER_GRP_RPL_SRV_WAIT_TIME_OUT 11561 +#define ER_GRP_RPL_FETCH_LOG_EVENT_FAILED 11562 +#define ER_GRP_RPL_START_GRP_RPL_FAILED 11563 +#define ER_GRP_RPL_CONN_INTERNAL_PLUGIN_FAIL 11564 +#define ER_GRP_RPL_SUPER_READ_ON 11565 +#define ER_GRP_RPL_SUPER_READ_OFF 11566 +#define ER_GRP_RPL_KILLED_SESSION_ID 11567 +#define ER_GRP_RPL_KILLED_FAILED_ID 11568 +#define ER_GRP_RPL_INTERNAL_QUERY 11569 +#define ER_GRP_RPL_COPY_FROM_EMPTY_STRING 11570 +#define ER_GRP_RPL_QUERY_FAIL 11571 +#define ER_GRP_RPL_CREATE_SESSION_UNABLE 11572 +#define ER_GRP_RPL_MEMBER_NOT_FOUND 11573 +#define ER_GRP_RPL_MAXIMUM_CONNECTION_RETRIES_REACHED 11574 +#define ER_GRP_RPL_ALL_DONORS_LEFT_ABORT_RECOVERY 11575 +#define ER_GRP_RPL_ESTABLISH_RECOVERY_WITH_DONOR 11576 +#define ER_GRP_RPL_ESTABLISH_RECOVERY_WITH_ANOTHER_DONOR 11577 +#define ER_GRP_RPL_NO_VALID_DONOR 11578 +#define ER_GRP_RPL_CONFIG_RECOVERY 11579 +#define ER_GRP_RPL_ESTABLISHING_CONN_GRP_REC_DONOR 11580 +#define ER_GRP_RPL_CREATE_GRP_RPL_REC_CHANNEL 11581 +#define ER_GRP_RPL_DONOR_SERVER_CONN 11582 +#define ER_GRP_RPL_CHECK_STATUS_TABLE 11583 +#define ER_GRP_RPL_STARTING_GRP_REC 11584 +#define ER_GRP_RPL_DONOR_CONN_TERMINATION 11585 +#define ER_GRP_RPL_STOPPING_GRP_REC 11586 +#define ER_GRP_RPL_PURGE_REC 11587 +#define ER_GRP_RPL_UNABLE_TO_KILL_CONN_REC_DONOR_APPLIER 11588 +#define ER_GRP_RPL_UNABLE_TO_KILL_CONN_REC_DONOR_FAILOVER 11589 +#define ER_GRP_RPL_FAILED_TO_NOTIFY_GRP_MEMBERSHIP_EVENT 11590 +#define ER_GRP_RPL_FAILED_TO_BROADCAST_GRP_MEMBERSHIP_NOTIFICATION 11591 +#define ER_GRP_RPL_FAILED_TO_BROADCAST_MEMBER_STATUS_NOTIFICATION 11592 +#define ER_GRP_RPL_OOM_FAILED_TO_GENERATE_IDENTIFICATION_HASH 11593 +#define ER_GRP_RPL_WRITE_IDENT_HASH_BASE64_ENCODING_FAILED 11594 +#define ER_GRP_RPL_INVALID_BINLOG_FORMAT 11595 +//#define OBSOLETE_ER_GRP_RPL_BINLOG_CHECKSUM_SET 11596 +//#define OBSOLETE_ER_GRP_RPL_TRANS_WRITE_SET_EXTRACTION_NOT_SET 11597 +#define ER_GRP_RPL_UNSUPPORTED_TRANS_ISOLATION 11598 +#define ER_GRP_RPL_CANNOT_EXECUTE_TRANS_WHILE_STOPPING 11599 +#define ER_GRP_RPL_CANNOT_EXECUTE_TRANS_WHILE_RECOVERING 11600 +#define ER_GRP_RPL_CANNOT_EXECUTE_TRANS_IN_ERROR_STATE 11601 +#define ER_GRP_RPL_CANNOT_EXECUTE_TRANS_IN_OFFLINE_MODE 11602 +#define ER_GRP_RPL_MULTIPLE_CACHE_TYPE_NOT_SUPPORTED_FOR_SESSION 11603 +#define ER_GRP_RPL_FAILED_TO_REINIT_BINLOG_CACHE_FOR_READ 11604 +#define ER_GRP_RPL_FAILED_TO_CREATE_TRANS_CONTEXT 11605 +#define ER_GRP_RPL_FAILED_TO_EXTRACT_TRANS_WRITE_SET 11606 +#define ER_GRP_RPL_FAILED_TO_GATHER_TRANS_WRITE_SET 11607 +#define ER_GRP_RPL_TRANS_SIZE_EXCEEDS_LIMIT 11608 +//#define OBSOLETE_ER_GRP_RPL_REINIT_OF_INTERNAL_CACHE_FOR_READ_FAILED 11609 +//#define OBSOLETE_ER_GRP_RPL_APPENDING_DATA_TO_INTERNAL_CACHE_FAILED 11610 +#define ER_GRP_RPL_WRITE_TO_TRANSACTION_MESSAGE_FAILED 11611 +#define ER_GRP_RPL_FAILED_TO_REGISTER_TRANS_OUTCOME_NOTIFICTION 11612 +#define ER_GRP_RPL_MSG_TOO_LONG_BROADCASTING_TRANS_FAILED 11613 +#define ER_GRP_RPL_BROADCASTING_TRANS_TO_GRP_FAILED 11614 +#define ER_GRP_RPL_ERROR_WHILE_WAITING_FOR_CONFLICT_DETECTION 11615 +//#define OBSOLETE_ER_GRP_RPL_REINIT_OF_INTERNAL_CACHE_FOR_WRITE_FAILED 11616 +//#define OBSOLETE_ER_GRP_RPL_FAILED_TO_CREATE_COMMIT_CACHE 11617 +//#define OBSOLETE_ER_GRP_RPL_REINIT_OF_COMMIT_CACHE_FOR_WRITE_FAILED 11618 +//#define OBSOLETE_ER_GRP_RPL_PREV_REC_SESSION_RUNNING 11619 +#define ER_GRP_RPL_FATAL_REC_PROCESS 11620 +//#define OBSOLETE_ER_GRP_RPL_WHILE_STOPPING_REP_CHANNEL 11621 +#define ER_GRP_RPL_UNABLE_TO_EVALUATE_APPLIER_STATUS 11622 +#define ER_GRP_RPL_ONLY_ONE_SERVER_ALIVE 11623 +#define ER_GRP_RPL_CERTIFICATION_REC_PROCESS 11624 +#define ER_GRP_RPL_UNABLE_TO_ENSURE_EXECUTION_REC 11625 +#define ER_GRP_RPL_WHILE_SENDING_MSG_REC 11626 +//#define OBSOLETE_ER_GRP_RPL_READ_UNABLE_FOR_SUPER_READ_ONLY 11627 +#define ER_GRP_RPL_READ_UNABLE_FOR_READ_ONLY_SUPER_READ_ONLY 11628 +#define ER_GRP_RPL_UNABLE_TO_RESET_SERVER_READ_MODE 11629 +#define ER_GRP_RPL_UNABLE_TO_CERTIFY_PLUGIN_TRANS 11630 +#define ER_GRP_RPL_UNBLOCK_CERTIFIED_TRANS 11631 +//#define OBSOLETE_ER_GRP_RPL_SERVER_WORKING_AS_SECONDARY 11632 +#define ER_GRP_RPL_FAILED_TO_START_WITH_INVALID_SERVER_ID 11633 +#define ER_GRP_RPL_FORCE_MEMBERS_MUST_BE_EMPTY 11634 +#define ER_GRP_RPL_PLUGIN_STRUCT_INIT_NOT_POSSIBLE_ON_SERVER_START 11635 +#define ER_GRP_RPL_FAILED_TO_ENABLE_SUPER_READ_ONLY_MODE 11636 +#define ER_GRP_RPL_FAILED_TO_INIT_COMMUNICATION_ENGINE 11637 +#define ER_GRP_RPL_FAILED_TO_START_ON_SECONDARY_WITH_ASYNC_CHANNELS 11638 +#define ER_GRP_RPL_FAILED_TO_START_COMMUNICATION_ENGINE 11639 +#define ER_GRP_RPL_TIMEOUT_ON_VIEW_AFTER_JOINING_GRP 11640 +#define ER_GRP_RPL_FAILED_TO_CALL_GRP_COMMUNICATION_INTERFACE 11641 +#define ER_GRP_RPL_MEMBER_SERVER_UUID_IS_INCOMPATIBLE_WITH_GRP 11642 +#define ER_GRP_RPL_MEMBER_CONF_INFO 11643 +#define ER_GRP_RPL_FAILED_TO_CONFIRM_IF_SERVER_LEFT_GRP 11644 +#define ER_GRP_RPL_SERVER_IS_ALREADY_LEAVING 11645 +#define ER_GRP_RPL_SERVER_ALREADY_LEFT 11646 +#define ER_GRP_RPL_WAITING_FOR_VIEW_UPDATE 11647 +#define ER_GRP_RPL_TIMEOUT_RECEIVING_VIEW_CHANGE_ON_SHUTDOWN 11648 +#define ER_GRP_RPL_REQUESTING_NON_MEMBER_SERVER_TO_LEAVE 11649 +#define ER_GRP_RPL_IS_STOPPING 11650 +#define ER_GRP_RPL_IS_STOPPED 11651 +#define ER_GRP_RPL_FAILED_TO_ENABLE_READ_ONLY_MODE_ON_SHUTDOWN 11652 +#define ER_GRP_RPL_RECOVERY_MODULE_TERMINATION_TIMED_OUT_ON_SHUTDOWN 11653 +#define ER_GRP_RPL_APPLIER_TERMINATION_TIMED_OUT_ON_SHUTDOWN 11654 +#define ER_GRP_RPL_FAILED_TO_SHUTDOWN_REGISTRY_MODULE 11655 +#define ER_GRP_RPL_FAILED_TO_INIT_HANDLER 11656 +#define ER_GRP_RPL_FAILED_TO_REGISTER_SERVER_STATE_OBSERVER 11657 +#define ER_GRP_RPL_FAILED_TO_REGISTER_TRANS_STATE_OBSERVER 11658 +#define ER_GRP_RPL_FAILED_TO_REGISTER_BINLOG_STATE_OBSERVER 11659 +#define ER_GRP_RPL_FAILED_TO_START_ON_BOOT 11660 +#define ER_GRP_RPL_FAILED_TO_STOP_ON_PLUGIN_UNINSTALL 11661 +#define ER_GRP_RPL_FAILED_TO_UNREGISTER_SERVER_STATE_OBSERVER 11662 +#define ER_GRP_RPL_FAILED_TO_UNREGISTER_TRANS_STATE_OBSERVER 11663 +#define ER_GRP_RPL_FAILED_TO_UNREGISTER_BINLOG_STATE_OBSERVER 11664 +#define ER_GRP_RPL_ALL_OBSERVERS_UNREGISTERED 11665 +#define ER_GRP_RPL_FAILED_TO_PARSE_THE_GRP_NAME 11666 +#define ER_GRP_RPL_FAILED_TO_GENERATE_SIDNO_FOR_GRP 11667 +#define ER_GRP_RPL_APPLIER_NOT_STARTED_DUE_TO_RUNNING_PREV_SHUTDOWN 11668 +#define ER_GRP_RPL_FAILED_TO_INIT_APPLIER_MODULE 11669 +#define ER_GRP_RPL_APPLIER_INITIALIZED 11670 +#define ER_GRP_RPL_COMMUNICATION_SSL_CONF_INFO 11671 +#define ER_GRP_RPL_ABORTS_AS_SSL_NOT_SUPPORTED_BY_MYSQLD 11672 +#define ER_GRP_RPL_SSL_DISABLED 11673 +#define ER_GRP_RPL_UNABLE_TO_INIT_COMMUNICATION_ENGINE 11674 +#define ER_GRP_RPL_BINLOG_DISABLED 11675 +#define ER_GRP_RPL_GTID_MODE_OFF 11676 +#define ER_GRP_RPL_LOG_REPLICA_UPDATES_NOT_SET 11677 +//#define OBSOLETE_ER_GRP_RPL_INVALID_TRANS_WRITE_SET_EXTRACTION_VALUE 11678 +#define ER_GRP_RPL_APPLIER_METADATA_REPO_MUST_BE_TABLE 11679 +#define ER_GRP_RPL_CONNECTION_METADATA_REPO_MUST_BE_TABLE 11680 +#define ER_GRP_RPL_INCORRECT_TYPE_SET_FOR_PARALLEL_APPLIER 11681 +#define ER_GRP_RPL_REPLICA_PRESERVE_COMMIT_ORDER_NOT_SET 11682 +#define ER_GRP_RPL_SINGLE_PRIM_MODE_NOT_ALLOWED_WITH_UPDATE_EVERYWHERE 11683 +#define ER_GRP_RPL_MODULE_TERMINATE_ERROR 11684 +#define ER_GRP_RPL_GRP_NAME_OPTION_MANDATORY 11685 +#define ER_GRP_RPL_GRP_NAME_IS_TOO_LONG 11686 +#define ER_GRP_RPL_GRP_NAME_IS_NOT_VALID_UUID 11687 +#define ER_GRP_RPL_FLOW_CTRL_MIN_QUOTA_GREATER_THAN_MAX_QUOTA 11688 +#define ER_GRP_RPL_FLOW_CTRL_MIN_RECOVERY_QUOTA_GREATER_THAN_MAX_QUOTA 11689 +#define ER_GRP_RPL_FLOW_CTRL_MAX_QUOTA_SMALLER_THAN_MIN_QUOTAS 11690 +#define ER_GRP_RPL_INVALID_SSL_RECOVERY_STRING 11691 +//#define OBSOLETE_ER_GRP_RPL_SUPPORTS_ONLY_ONE_FORCE_MEMBERS_SET 11692 +//#define OBSOLETE_ER_GRP_RPL_FORCE_MEMBERS_SET_UPDATE_NOT_ALLOWED 11693 +#define ER_GRP_RPL_GRP_COMMUNICATION_INIT_WITH_CONF 11694 +#define ER_GRP_RPL_UNKNOWN_GRP_RPL_APPLIER_PIPELINE_REQUESTED 11695 +#define ER_GRP_RPL_FAILED_TO_BOOTSTRAP_EVENT_HANDLING_INFRASTRUCTURE 11696 +#define ER_GRP_RPL_APPLIER_HANDLER_NOT_INITIALIZED 11697 +#define ER_GRP_RPL_APPLIER_HANDLER_IS_IN_USE 11698 +#define ER_GRP_RPL_APPLIER_HANDLER_ROLE_IS_IN_USE 11699 +#define ER_GRP_RPL_FAILED_TO_INIT_APPLIER_HANDLER 11700 +#define ER_GRP_RPL_SQL_SERVICE_FAILED_TO_INIT_SESSION_THREAD 11701 +#define ER_GRP_RPL_SQL_SERVICE_COMM_SESSION_NOT_INITIALIZED 11702 +#define ER_GRP_RPL_SQL_SERVICE_SERVER_SESSION_KILLED 11703 +#define ER_GRP_RPL_SQL_SERVICE_FAILED_TO_RUN_SQL_QUERY 11704 +#define ER_GRP_RPL_SQL_SERVICE_SERVER_INTERNAL_FAILURE 11705 +#define ER_GRP_RPL_SQL_SERVICE_RETRIES_EXCEEDED_ON_SESSION_STATE 11706 +#define ER_GRP_RPL_SQL_SERVICE_FAILED_TO_FETCH_SECURITY_CTX 11707 +#define ER_GRP_RPL_SQL_SERVICE_SERVER_ACCESS_DENIED_FOR_USER 11708 +#define ER_GRP_RPL_SQL_SERVICE_MAX_CONN_ERROR_FROM_SERVER 11709 +#define ER_GRP_RPL_SQL_SERVICE_SERVER_ERROR_ON_CONN 11710 +#define ER_GRP_RPL_UNREACHABLE_MAJORITY_TIMEOUT_FOR_MEMBER 11711 +#define ER_GRP_RPL_SERVER_SET_TO_READ_ONLY_DUE_TO_ERRORS 11712 +#define ER_GRP_RPL_GMS_LISTENER_FAILED_TO_LOG_NOTIFICATION 11713 +#define ER_GRP_RPL_GRP_COMMUNICATION_ENG_INIT_FAILED 11714 +#define ER_GRP_RPL_SET_GRP_COMMUNICATION_ENG_LOGGER_FAILED 11715 +#define ER_GRP_RPL_DEBUG_OPTIONS 11716 +#define ER_GRP_RPL_INVALID_DEBUG_OPTIONS 11717 +#define ER_GRP_RPL_EXIT_GRP_GCS_ERROR 11718 +#define ER_GRP_RPL_GRP_MEMBER_OFFLINE 11719 +#define ER_GRP_RPL_GCS_INTERFACE_ERROR 11720 +#define ER_GRP_RPL_FORCE_MEMBER_VALUE_SET_ERROR 11721 +#define ER_GRP_RPL_FORCE_MEMBER_VALUE_SET 11722 +#define ER_GRP_RPL_FORCE_MEMBER_VALUE_TIME_OUT 11723 +#define ER_GRP_RPL_BROADCAST_COMMIT_MSSG_TOO_BIG 11724 +#define ER_GRP_RPL_SEND_STATS_ERROR 11725 +#define ER_GRP_RPL_MEMBER_STATS_INFO 11726 +#define ER_GRP_RPL_FLOW_CONTROL_STATS 11727 +#define ER_GRP_RPL_UNABLE_TO_CONVERT_PACKET_TO_EVENT 11728 +#define ER_GRP_RPL_PIPELINE_CREATE_FAILED 11729 +#define ER_GRP_RPL_PIPELINE_REINIT_FAILED_WRITE 11730 +#define ER_GRP_RPL_UNABLE_TO_CONVERT_EVENT_TO_PACKET 11731 +#define ER_GRP_RPL_PIPELINE_FLUSH_FAIL 11732 +#define ER_GRP_RPL_PIPELINE_REINIT_FAILED_READ 11733 +//#define OBSOLETE_ER_GRP_RPL_STOP_REP_CHANNEL 11734 +#define ER_GRP_RPL_GCS_GR_ERROR_MSG 11735 +#define ER_GRP_RPL_REPLICA_IO_THREAD_UNBLOCKED 11736 +#define ER_GRP_RPL_REPLICA_IO_THREAD_ERROR_OUT 11737 +#define ER_GRP_RPL_REPLICA_APPLIER_THREAD_UNBLOCKED 11738 +#define ER_GRP_RPL_REPLICA_APPLIER_THREAD_ERROR_OUT 11739 +#define ER_LDAP_AUTH_FAILED_TO_CREATE_OR_GET_CONNECTION 11740 +#define ER_LDAP_AUTH_DEINIT_FAILED 11741 +#define ER_LDAP_AUTH_SKIPPING_USER_GROUP_SEARCH 11742 +#define ER_LDAP_AUTH_POOL_DISABLE_MAX_SIZE_ZERO 11743 +#define ER_LDAP_AUTH_FAILED_TO_CREATE_LDAP_OBJECT_CREATOR 11744 +#define ER_LDAP_AUTH_FAILED_TO_CREATE_LDAP_OBJECT 11745 +#define ER_LDAP_AUTH_TLS_CONF 11746 +#define ER_LDAP_AUTH_TLS_CONNECTION 11747 +#define ER_LDAP_AUTH_CONN_POOL_NOT_CREATED 11748 +#define ER_LDAP_AUTH_CONN_POOL_INITIALIZING 11749 +#define ER_LDAP_AUTH_CONN_POOL_DEINITIALIZING 11750 +#define ER_LDAP_AUTH_ZERO_MAX_POOL_SIZE_UNCHANGED 11751 +#define ER_LDAP_AUTH_POOL_REINITIALIZING 11752 +#define ER_LDAP_AUTH_FAILED_TO_WRITE_PACKET 11753 +#define ER_LDAP_AUTH_SETTING_USERNAME 11754 +#define ER_LDAP_AUTH_USER_AUTH_DATA 11755 +#define ER_LDAP_AUTH_INFO_FOR_USER 11756 +#define ER_LDAP_AUTH_USER_GROUP_SEARCH_INFO 11757 +#define ER_LDAP_AUTH_GRP_SEARCH_SPECIAL_HDL 11758 +#define ER_LDAP_AUTH_GRP_IS_FULL_DN 11759 +#define ER_LDAP_AUTH_USER_NOT_FOUND_IN_ANY_GRP 11760 +#define ER_LDAP_AUTH_USER_FOUND_IN_MANY_GRPS 11761 +#define ER_LDAP_AUTH_USER_HAS_MULTIPLE_GRP_NAMES 11762 +#define ER_LDAP_AUTH_SEARCHED_USER_GRP_NAME 11763 +#define ER_LDAP_AUTH_OBJECT_CREATE_TIMESTAMP 11764 +#define ER_LDAP_AUTH_CERTIFICATE_NAME 11765 +#define ER_LDAP_AUTH_FAILED_TO_POOL_DEINIT 11766 +#define ER_LDAP_AUTH_FAILED_TO_INITIALIZE_POOL_IN_RECONSTRUCTING 11767 +#define ER_LDAP_AUTH_FAILED_TO_INITIALIZE_POOL_IN_INIT_STATE 11768 +#define ER_LDAP_AUTH_FAILED_TO_INITIALIZE_POOL_IN_DEINIT_STATE 11769 +#define ER_LDAP_AUTH_FAILED_TO_DEINITIALIZE_POOL_IN_RECONSTRUCT_STATE 11770 +#define ER_LDAP_AUTH_FAILED_TO_DEINITIALIZE_NOT_READY_POOL 11771 +#define ER_LDAP_AUTH_FAILED_TO_GET_CONNECTION_AS_PLUGIN_NOT_READY 11772 +#define ER_LDAP_AUTH_CONNECTION_POOL_INIT_FAILED 11773 +#define ER_LDAP_AUTH_MAX_ALLOWED_CONNECTION_LIMIT_HIT 11774 +#define ER_LDAP_AUTH_MAX_POOL_SIZE_SET_FAILED 11775 +#define ER_LDAP_AUTH_PLUGIN_FAILED_TO_READ_PACKET 11776 +#define ER_LDAP_AUTH_CREATING_LDAP_CONNECTION 11777 +#define ER_LDAP_AUTH_GETTING_CONNECTION_FROM_POOL 11778 +#define ER_LDAP_AUTH_RETURNING_CONNECTION_TO_POOL 11779 +#define ER_LDAP_AUTH_SEARCH_USER_GROUP_ATTR_NOT_FOUND 11780 +#define ER_LDAP_AUTH_LDAP_INFO_NULL 11781 +#define ER_LDAP_AUTH_FREEING_CONNECTION 11782 +#define ER_LDAP_AUTH_CONNECTION_PUSHED_TO_POOL 11783 +#define ER_LDAP_AUTH_CONNECTION_CREATOR_ENTER 11784 +#define ER_LDAP_AUTH_STARTING_TLS 11785 +#define ER_LDAP_AUTH_CONNECTION_GET_LDAP_INFO_NULL 11786 +#define ER_LDAP_AUTH_DELETING_CONNECTION_KEY 11787 +#define ER_LDAP_AUTH_POOLED_CONNECTION_KEY 11788 +#define ER_LDAP_AUTH_CREATE_CONNECTION_KEY 11789 +#define ER_LDAP_AUTH_COMMUNICATION_HOST_INFO 11790 +#define ER_LDAP_AUTH_METHOD_TO_CLIENT 11791 +#define ER_LDAP_AUTH_SASL_REQUEST_FROM_CLIENT 11792 +#define ER_LDAP_AUTH_SASL_PROCESS_SASL 11793 +#define ER_LDAP_AUTH_SASL_BIND_SUCCESS_INFO 11794 +#define ER_LDAP_AUTH_STARTED_FOR_USER 11795 +#define ER_LDAP_AUTH_DISTINGUISHED_NAME 11796 +#define ER_LDAP_AUTH_INIT_FAILED 11797 +#define ER_LDAP_AUTH_OR_GROUP_RETRIEVAL_FAILED 11798 +#define ER_LDAP_AUTH_USER_GROUP_SEARCH_FAILED 11799 +#define ER_LDAP_AUTH_USER_BIND_FAILED 11800 +#define ER_LDAP_AUTH_POOL_GET_FAILED_TO_CREATE_CONNECTION 11801 +#define ER_LDAP_AUTH_FAILED_TO_CREATE_LDAP_CONNECTION 11802 +#define ER_LDAP_AUTH_FAILED_TO_ESTABLISH_TLS_CONNECTION 11803 +#define ER_LDAP_AUTH_FAILED_TO_SEARCH_DN 11804 +#define ER_LDAP_AUTH_CONNECTION_POOL_REINIT_ENTER 11805 +#define ER_SYSTEMD_NOTIFY_PATH_TOO_LONG 11806 +#define ER_SYSTEMD_NOTIFY_CONNECT_FAILED 11807 +#define ER_SYSTEMD_NOTIFY_WRITE_FAILED 11808 +#define ER_FOUND_MISSING_GTIDS 11809 +#define ER_PID_FILE_PRIV_DIRECTORY_INSECURE 11810 +#define ER_CANT_CHECK_PID_PATH 11811 +#define ER_VALIDATE_PWD_STATUS_VAR_REGISTRATION_FAILED 11812 +#define ER_VALIDATE_PWD_STATUS_VAR_UNREGISTRATION_FAILED 11813 +#define ER_VALIDATE_PWD_DICT_FILE_OPEN_FAILED 11814 +#define ER_VALIDATE_PWD_COULD_BE_NULL 11815 +#define ER_VALIDATE_PWD_STRING_CONV_TO_LOWERCASE_FAILED 11816 +#define ER_VALIDATE_PWD_STRING_CONV_TO_BUFFER_FAILED 11817 +#define ER_VALIDATE_PWD_STRING_HANDLER_MEM_ALLOCATION_FAILED 11818 +#define ER_VALIDATE_PWD_STRONG_POLICY_DICT_FILE_UNSPECIFIED 11819 +#define ER_VALIDATE_PWD_CONVERT_TO_BUFFER_FAILED 11820 +#define ER_VALIDATE_PWD_VARIABLE_REGISTRATION_FAILED 11821 +#define ER_VALIDATE_PWD_VARIABLE_UNREGISTRATION_FAILED 11822 +#define ER_KEYRING_MIGRATION_EXTRA_OPTIONS 11823 +//#define OBSOLETE_ER_INVALID_DEFAULT_UTF8MB4_COLLATION 11824 +#define ER_IB_MSG_0 11825 +#define ER_IB_MSG_1 11826 +#define ER_IB_MSG_2 11827 +#define ER_IB_MSG_3 11828 +#define ER_IB_MSG_4 11829 +#define ER_IB_MSG_5 11830 +#define ER_IB_MSG_6 11831 +#define ER_IB_MSG_7 11832 +#define ER_IB_MSG_8 11833 +#define ER_IB_MSG_9 11834 +#define ER_IB_MSG_10 11835 +#define ER_IB_MSG_11 11836 +#define ER_IB_MSG_12 11837 +#define ER_IB_MSG_13 11838 +#define ER_IB_MSG_14 11839 +#define ER_IB_MSG_15 11840 +#define ER_IB_MSG_16 11841 +#define ER_IB_MSG_17 11842 +#define ER_IB_MSG_18 11843 +#define ER_IB_MSG_19 11844 +#define ER_IB_MSG_20 11845 +#define ER_IB_MSG_21 11846 +#define ER_IB_MSG_22 11847 +#define ER_IB_MSG_23 11848 +#define ER_IB_MSG_24 11849 +#define ER_IB_MSG_25 11850 +#define ER_IB_MSG_26 11851 +#define ER_IB_MSG_27 11852 +#define ER_IB_MSG_28 11853 +#define ER_IB_MSG_29 11854 +#define ER_IB_MSG_30 11855 +//#define OBSOLETE_ER_IB_MSG_31 11856 +#define ER_IB_MSG_32 11857 +#define ER_IB_MSG_33 11858 +#define ER_IB_MSG_34 11859 +#define ER_IB_MSG_35 11860 +#define ER_IB_MSG_36 11861 +#define ER_IB_MSG_37 11862 +#define ER_IB_MSG_38 11863 +#define ER_IB_MSG_39 11864 +#define ER_IB_MSG_40 11865 +#define ER_IB_MSG_41 11866 +#define ER_IB_MSG_42 11867 +#define ER_IB_MSG_43 11868 +#define ER_IB_MSG_44 11869 +#define ER_IB_MSG_45 11870 +#define ER_IB_MSG_46 11871 +#define ER_IB_MSG_47 11872 +#define ER_IB_MSG_48 11873 +#define ER_IB_MSG_49 11874 +#define ER_IB_MSG_50 11875 +#define ER_IB_MSG_51 11876 +#define ER_IB_MSG_52 11877 +#define ER_IB_MSG_53 11878 +#define ER_IB_MSG_54 11879 +#define ER_IB_MSG_55 11880 +#define ER_IB_MSG_56 11881 +#define ER_IB_MSG_57 11882 +#define ER_IB_MSG_58 11883 +#define ER_IB_MSG_59 11884 +#define ER_IB_MSG_60 11885 +#define ER_IB_MSG_61 11886 +#define ER_IB_MSG_62 11887 +#define ER_IB_MSG_63 11888 +#define ER_IB_MSG_64 11889 +#define ER_IB_MSG_65 11890 +#define ER_IB_MSG_66 11891 +#define ER_IB_MSG_67 11892 +#define ER_IB_MSG_68 11893 +#define ER_IB_MSG_69 11894 +#define ER_IB_MSG_70 11895 +#define ER_IB_MSG_71 11896 +#define ER_IB_MSG_72 11897 +#define ER_IB_MSG_73 11898 +#define ER_IB_MSG_74 11899 +#define ER_IB_MSG_75 11900 +#define ER_IB_MSG_76 11901 +#define ER_IB_MSG_77 11902 +#define ER_IB_MSG_78 11903 +#define ER_IB_MSG_79 11904 +#define ER_IB_MSG_80 11905 +#define ER_IB_MSG_81 11906 +#define ER_IB_MSG_82 11907 +#define ER_IB_MSG_83 11908 +#define ER_IB_MSG_84 11909 +#define ER_IB_MSG_85 11910 +#define ER_IB_MSG_86 11911 +//#define OBSOLETE_ER_IB_MSG_87 11912 +//#define OBSOLETE_ER_IB_MSG_88 11913 +//#define OBSOLETE_ER_IB_MSG_89 11914 +//#define OBSOLETE_ER_IB_MSG_90 11915 +//#define OBSOLETE_ER_IB_MSG_91 11916 +//#define OBSOLETE_ER_IB_MSG_92 11917 +//#define OBSOLETE_ER_IB_MSG_93 11918 +//#define OBSOLETE_ER_IB_MSG_94 11919 +#define ER_IB_MSG_95 11920 +#define ER_IB_MSG_96 11921 +#define ER_IB_MSG_97 11922 +#define ER_IB_MSG_98 11923 +#define ER_IB_MSG_99 11924 +#define ER_IB_MSG_100 11925 +#define ER_IB_MSG_101 11926 +#define ER_IB_MSG_102 11927 +#define ER_IB_MSG_103 11928 +#define ER_IB_MSG_104 11929 +#define ER_IB_MSG_105 11930 +#define ER_IB_MSG_106 11931 +#define ER_IB_MSG_107 11932 +#define ER_IB_MSG_108 11933 +#define ER_IB_MSG_109 11934 +#define ER_IB_MSG_110 11935 +#define ER_IB_MSG_111 11936 +#define ER_IB_MSG_112 11937 +//#define OBSOLETE_ER_IB_MSG_113 11938 +//#define OBSOLETE_ER_IB_MSG_114 11939 +//#define OBSOLETE_ER_IB_MSG_115 11940 +//#define OBSOLETE_ER_IB_MSG_116 11941 +//#define OBSOLETE_ER_IB_MSG_117 11942 +//#define OBSOLETE_ER_IB_MSG_118 11943 +#define ER_IB_MSG_119 11944 +#define ER_IB_MSG_120 11945 +#define ER_IB_MSG_121 11946 +#define ER_IB_MSG_122 11947 +#define ER_IB_MSG_123 11948 +#define ER_IB_MSG_124 11949 +#define ER_IB_MSG_125 11950 +#define ER_IB_MSG_126 11951 +#define ER_IB_MSG_127 11952 +#define ER_IB_MSG_128 11953 +#define ER_IB_MSG_129 11954 +#define ER_IB_MSG_130 11955 +#define ER_IB_MSG_131 11956 +#define ER_IB_MSG_132 11957 +#define ER_IB_MSG_133 11958 +#define ER_IB_MSG_134 11959 +#define ER_IB_MSG_135 11960 +#define ER_IB_MSG_136 11961 +#define ER_IB_MSG_137 11962 +#define ER_IB_MSG_138 11963 +#define ER_IB_MSG_139 11964 +#define ER_IB_MSG_140 11965 +#define ER_IB_MSG_141 11966 +#define ER_IB_MSG_142 11967 +#define ER_IB_MSG_143 11968 +#define ER_IB_MSG_144 11969 +#define ER_IB_MSG_145 11970 +#define ER_IB_MSG_146 11971 +#define ER_IB_MSG_147 11972 +#define ER_IB_MSG_148 11973 +#define ER_IB_CLONE_INTERNAL 11974 +#define ER_IB_CLONE_TIMEOUT 11975 +#define ER_IB_CLONE_STATUS_FILE 11976 +#define ER_IB_CLONE_SQL 11977 +#define ER_IB_CLONE_VALIDATE 11978 +#define ER_IB_CLONE_PUNCH_HOLE 11979 +#define ER_IB_CLONE_GTID_PERSIST 11980 +#define ER_IB_MSG_156 11981 +#define ER_IB_MSG_157 11982 +#define ER_IB_MSG_158 11983 +#define ER_IB_MSG_159 11984 +#define ER_IB_MSG_160 11985 +#define ER_IB_MSG_161 11986 +#define ER_IB_MSG_162 11987 +#define ER_IB_MSG_163 11988 +#define ER_IB_MSG_164 11989 +#define ER_IB_MSG_165 11990 +#define ER_IB_MSG_166 11991 +#define ER_IB_MSG_167 11992 +#define ER_IB_MSG_168 11993 +#define ER_IB_MSG_169 11994 +#define ER_IB_MSG_170 11995 +#define ER_IB_MSG_171 11996 +#define ER_IB_MSG_172 11997 +#define ER_IB_MSG_173 11998 +#define ER_IB_MSG_174 11999 +#define ER_IB_MSG_175 12000 +#define ER_IB_MSG_176 12001 +#define ER_IB_MSG_177 12002 +#define ER_IB_MSG_178 12003 +#define ER_IB_MSG_179 12004 +#define ER_IB_MSG_180 12005 +#define ER_IB_LONG_AHI_DISABLE_WAIT 12006 +#define ER_IB_MSG_182 12007 +#define ER_IB_MSG_183 12008 +#define ER_IB_MSG_184 12009 +//#define OBSOLETE_ER_IB_MSG_185 12010 +//#define OBSOLETE_ER_IB_MSG_186 12011 +#define ER_IB_MSG_187 12012 +#define ER_IB_MSG_188 12013 +#define ER_IB_MSG_189 12014 +#define ER_IB_MSG_190 12015 +#define ER_IB_MSG_191 12016 +#define ER_IB_MSG_192 12017 +#define ER_IB_MSG_193 12018 +#define ER_IB_MSG_194 12019 +#define ER_IB_MSG_195 12020 +#define ER_IB_MSG_196 12021 +#define ER_IB_MSG_197 12022 +#define ER_IB_MSG_198 12023 +#define ER_IB_MSG_199 12024 +#define ER_IB_MSG_200 12025 +#define ER_IB_MSG_201 12026 +#define ER_IB_MSG_202 12027 +#define ER_IB_MSG_203 12028 +#define ER_IB_MSG_204 12029 +#define ER_IB_MSG_205 12030 +#define ER_IB_MSG_206 12031 +#define ER_IB_MSG_207 12032 +#define ER_IB_MSG_208 12033 +#define ER_IB_MSG_209 12034 +#define ER_IB_MSG_210 12035 +#define ER_IB_MSG_211 12036 +#define ER_IB_MSG_212 12037 +#define ER_IB_MSG_213 12038 +#define ER_IB_MSG_214 12039 +#define ER_IB_MSG_215 12040 +#define ER_IB_MSG_216 12041 +#define ER_IB_MSG_217 12042 +#define ER_IB_MSG_218 12043 +#define ER_IB_MSG_219 12044 +#define ER_IB_MSG_220 12045 +#define ER_IB_MSG_221 12046 +#define ER_IB_MSG_222 12047 +#define ER_IB_MSG_223 12048 +#define ER_IB_MSG_224 12049 +#define ER_IB_MSG_225 12050 +#define ER_IB_MSG_226 12051 +//#define OBSOLETE_ER_IB_MSG_227 12052 +//#define OBSOLETE_ER_IB_MSG_228 12053 +#define ER_IB_MSG_229 12054 +#define ER_IB_MSG_230 12055 +#define ER_IB_MSG_231 12056 +#define ER_IB_MSG_232 12057 +#define ER_IB_MSG_233 12058 +#define ER_IB_MSG_234 12059 +#define ER_IB_MSG_235 12060 +#define ER_IB_MSG_236 12061 +#define ER_IB_MSG_237 12062 +#define ER_IB_MSG_238 12063 +#define ER_IB_MSG_239 12064 +#define ER_IB_MSG_240 12065 +#define ER_IB_MSG_241 12066 +#define ER_IB_MSG_242 12067 +#define ER_IB_MSG_243 12068 +#define ER_IB_MSG_244 12069 +#define ER_IB_MSG_245 12070 +#define ER_IB_MSG_246 12071 +#define ER_IB_MSG_247 12072 +#define ER_IB_MSG_248 12073 +#define ER_IB_MSG_249 12074 +#define ER_IB_MSG_250 12075 +#define ER_IB_MSG_251 12076 +#define ER_IB_MSG_252 12077 +#define ER_IB_MSG_253 12078 +#define ER_IB_MSG_254 12079 +#define ER_IB_MSG_255 12080 +#define ER_IB_MSG_256 12081 +#define ER_IB_MSG_257 12082 +#define ER_IB_MSG_258 12083 +#define ER_IB_MSG_259 12084 +#define ER_IB_MSG_260 12085 +#define ER_IB_MSG_261 12086 +#define ER_IB_MSG_262 12087 +#define ER_IB_MSG_263 12088 +#define ER_IB_MSG_264 12089 +#define ER_IB_MSG_265 12090 +#define ER_IB_MSG_266 12091 +#define ER_IB_MSG_267 12092 +#define ER_IB_MSG_268 12093 +#define ER_IB_MSG_269 12094 +#define ER_IB_MSG_270 12095 +#define ER_IB_MSG_271 12096 +#define ER_IB_MSG_272 12097 +#define ER_IB_MSG_273 12098 +//#define OBSOLETE_ER_IB_MSG_274 12099 +//#define OBSOLETE_ER_IB_MSG_275 12100 +//#define OBSOLETE_ER_IB_MSG_276 12101 +//#define OBSOLETE_ER_IB_MSG_277 12102 +#define ER_IB_MSG_278 12103 +//#define OBSOLETE_ER_IB_MSG_279 12104 +#define ER_IB_MSG_280 12105 +#define ER_IB_MSG_281 12106 +#define ER_IB_MSG_282 12107 +#define ER_IB_MSG_283 12108 +#define ER_IB_MSG_284 12109 +#define ER_IB_MSG_285 12110 +#define ER_IB_WARN_ACCESSING_NONEXISTINC_SPACE 12111 +#define ER_IB_MSG_287 12112 +#define ER_IB_MSG_288 12113 +#define ER_IB_MSG_289 12114 +//#define OBSOLETE_ER_IB_MSG_290 12115 +#define ER_IB_MSG_291 12116 +#define ER_IB_MSG_292 12117 +#define ER_IB_MSG_293 12118 +#define ER_IB_MSG_294 12119 +#define ER_IB_MSG_295 12120 +#define ER_IB_MSG_296 12121 +#define ER_IB_MSG_297 12122 +#define ER_IB_MSG_298 12123 +#define ER_IB_MSG_299 12124 +#define ER_IB_MSG_300 12125 +#define ER_IB_MSG_301 12126 +#define ER_IB_MSG_UNEXPECTED_FILE_EXISTS 12127 +#define ER_IB_MSG_303 12128 +#define ER_IB_MSG_304 12129 +#define ER_IB_MSG_305 12130 +#define ER_IB_MSG_306 12131 +#define ER_IB_MSG_307 12132 +#define ER_IB_MSG_308 12133 +#define ER_IB_MSG_309 12134 +#define ER_IB_MSG_310 12135 +#define ER_IB_MSG_311 12136 +#define ER_IB_MSG_312 12137 +#define ER_IB_MSG_313 12138 +#define ER_IB_MSG_314 12139 +#define ER_IB_MSG_315 12140 +#define ER_IB_MSG_316 12141 +#define ER_IB_MSG_317 12142 +#define ER_IB_MSG_318 12143 +#define ER_IB_MSG_319 12144 +#define ER_IB_MSG_320 12145 +#define ER_IB_MSG_321 12146 +#define ER_IB_MSG_322 12147 +#define ER_IB_MSG_323 12148 +#define ER_IB_MSG_324 12149 +#define ER_IB_MSG_325 12150 +#define ER_IB_MSG_326 12151 +//#define OBSOLETE_ER_IB_MSG_327 12152 +#define ER_IB_MSG_328 12153 +#define ER_IB_MSG_329 12154 +#define ER_IB_MSG_330 12155 +#define ER_IB_MSG_331 12156 +#define ER_IB_MSG_332 12157 +#define ER_IB_MSG_333 12158 +#define ER_IB_MSG_334 12159 +#define ER_IB_MSG_335 12160 +#define ER_IB_MSG_336 12161 +#define ER_IB_MSG_337 12162 +#define ER_IB_MSG_338 12163 +#define ER_IB_MSG_339 12164 +#define ER_IB_MSG_340 12165 +#define ER_IB_MSG_341 12166 +#define ER_IB_MSG_342 12167 +#define ER_IB_MSG_343 12168 +#define ER_IB_MSG_344 12169 +#define ER_IB_MSG_345 12170 +#define ER_IB_MSG_346 12171 +#define ER_IB_MSG_347 12172 +#define ER_IB_MSG_348 12173 +#define ER_IB_MSG_349 12174 +#define ER_IB_MSG_350 12175 +//#define OBSOLETE_ER_IB_MSG_351 12176 +#define ER_IB_MSG_UNPROTECTED_LOCATION_ALLOWED 12177 +//#define OBSOLETE_ER_IB_MSG_353 12178 +#define ER_IB_MSG_354 12179 +#define ER_IB_MSG_355 12180 +#define ER_IB_MSG_356 12181 +#define ER_IB_MSG_357 12182 +#define ER_IB_MSG_358 12183 +#define ER_IB_MSG_359 12184 +#define ER_IB_MSG_360 12185 +#define ER_IB_MSG_361 12186 +#define ER_IB_MSG_362 12187 +//#define OBSOLETE_ER_IB_MSG_363 12188 +#define ER_IB_MSG_364 12189 +#define ER_IB_MSG_365 12190 +#define ER_IB_MSG_IGNORE_SCAN_PATH 12191 +#define ER_IB_MSG_367 12192 +#define ER_IB_MSG_368 12193 +#define ER_IB_MSG_369 12194 +#define ER_IB_MSG_370 12195 +#define ER_IB_MSG_371 12196 +#define ER_IB_MSG_372 12197 +#define ER_IB_MSG_373 12198 +#define ER_IB_MSG_374 12199 +#define ER_IB_MSG_375 12200 +#define ER_IB_MSG_376 12201 +#define ER_IB_MSG_377 12202 +#define ER_IB_MSG_378 12203 +#define ER_IB_MSG_379 12204 +#define ER_IB_MSG_380 12205 +#define ER_IB_MSG_381 12206 +#define ER_IB_MSG_382 12207 +#define ER_IB_MSG_383 12208 +#define ER_IB_MSG_384 12209 +#define ER_IB_MSG_385 12210 +#define ER_IB_MSG_386 12211 +#define ER_IB_MSG_387 12212 +#define ER_IB_MSG_GENERAL_TABLESPACE_UNDER_DATADIR 12213 +#define ER_IB_MSG_IMPLICIT_TABLESPACE_IN_DATADIR 12214 +#define ER_IB_MSG_390 12215 +#define ER_IB_MSG_391 12216 +#define ER_IB_MSG_392 12217 +#define ER_IB_MSG_393 12218 +#define ER_IB_MSG_394 12219 +#define ER_IB_MSG_395 12220 +#define ER_IB_MSG_396 12221 +#define ER_IB_MSG_397 12222 +#define ER_IB_MSG_398 12223 +#define ER_IB_MSG_399 12224 +//#define OBSOLETE_ER_IB_MSG_400 12225 +#define ER_IB_MSG_401 12226 +#define ER_IB_MSG_402 12227 +#define ER_IB_MSG_403 12228 +#define ER_IB_MSG_404 12229 +#define ER_IB_MSG_405 12230 +#define ER_IB_MSG_406 12231 +#define ER_IB_MSG_407 12232 +#define ER_IB_MSG_408 12233 +#define ER_IB_MSG_409 12234 +#define ER_IB_MSG_410 12235 +#define ER_IB_MSG_411 12236 +#define ER_IB_MSG_412 12237 +#define ER_IB_MSG_413 12238 +#define ER_IB_MSG_414 12239 +#define ER_IB_MSG_415 12240 +#define ER_IB_MSG_416 12241 +#define ER_IB_MSG_417 12242 +#define ER_IB_MSG_418 12243 +#define ER_IB_MSG_419 12244 +#define ER_IB_MSG_420 12245 +#define ER_IB_MSG_421 12246 +#define ER_IB_MSG_422 12247 +#define ER_IB_MSG_423 12248 +#define ER_IB_MSG_424 12249 +#define ER_IB_MSG_425 12250 +#define ER_IB_MSG_426 12251 +#define ER_IB_MSG_427 12252 +#define ER_IB_MSG_428 12253 +#define ER_IB_MSG_429 12254 +#define ER_IB_MSG_430 12255 +#define ER_IB_MSG_431 12256 +#define ER_IB_MSG_432 12257 +#define ER_IB_MSG_433 12258 +#define ER_IB_MSG_434 12259 +#define ER_IB_MSG_435 12260 +#define ER_IB_MSG_436 12261 +#define ER_IB_MSG_437 12262 +#define ER_IB_MSG_438 12263 +#define ER_IB_MSG_439 12264 +#define ER_IB_MSG_440 12265 +#define ER_IB_MSG_441 12266 +#define ER_IB_MSG_442 12267 +#define ER_IB_MSG_443 12268 +//#define OBSOLETE_ER_IB_MSG_444 12269 +#define ER_IB_MSG_445 12270 +#define ER_IB_MSG_446 12271 +#define ER_IB_MSG_447 12272 +#define ER_IB_MSG_448 12273 +#define ER_IB_MSG_449 12274 +#define ER_IB_MSG_450 12275 +#define ER_IB_MSG_451 12276 +#define ER_IB_MSG_452 12277 +#define ER_IB_MSG_453 12278 +#define ER_IB_MSG_454 12279 +#define ER_IB_MSG_455 12280 +#define ER_IB_MSG_456 12281 +#define ER_IB_MSG_457 12282 +#define ER_IB_MSG_458 12283 +#define ER_IB_MSG_459 12284 +#define ER_IB_MSG_460 12285 +#define ER_IB_MSG_461 12286 +#define ER_IB_MSG_462 12287 +#define ER_IB_MSG_463 12288 +#define ER_IB_MSG_464 12289 +#define ER_IB_MSG_465 12290 +#define ER_IB_MSG_466 12291 +#define ER_IB_MSG_467 12292 +#define ER_IB_MSG_468 12293 +#define ER_IB_MSG_469 12294 +#define ER_IB_MSG_470 12295 +#define ER_IB_MSG_471 12296 +#define ER_IB_MSG_472 12297 +#define ER_IB_MSG_473 12298 +#define ER_IB_MSG_474 12299 +#define ER_IB_MSG_475 12300 +#define ER_IB_MSG_476 12301 +#define ER_IB_MSG_477 12302 +#define ER_IB_MSG_478 12303 +#define ER_IB_MSG_479 12304 +#define ER_IB_MSG_480 12305 +#define ER_IB_MSG_481 12306 +#define ER_IB_MSG_482 12307 +#define ER_IB_MSG_483 12308 +#define ER_IB_MSG_484 12309 +#define ER_IB_MSG_485 12310 +#define ER_IB_MSG_486 12311 +#define ER_IB_MSG_487 12312 +#define ER_IB_MSG_488 12313 +#define ER_IB_MSG_489 12314 +#define ER_IB_MSG_490 12315 +#define ER_IB_MSG_491 12316 +#define ER_IB_MSG_492 12317 +#define ER_IB_MSG_493 12318 +#define ER_IB_MSG_494 12319 +#define ER_IB_MSG_495 12320 +#define ER_IB_MSG_496 12321 +#define ER_IB_MSG_497 12322 +#define ER_IB_MSG_498 12323 +#define ER_IB_MSG_499 12324 +#define ER_IB_MSG_500 12325 +#define ER_IB_MSG_501 12326 +#define ER_IB_MSG_502 12327 +#define ER_IB_MSG_503 12328 +#define ER_IB_MSG_504 12329 +#define ER_IB_MSG_505 12330 +#define ER_IB_MSG_506 12331 +#define ER_IB_MSG_507 12332 +#define ER_IB_MSG_508 12333 +#define ER_IB_MSG_509 12334 +#define ER_IB_MSG_510 12335 +#define ER_IB_MSG_511 12336 +#define ER_IB_MSG_512 12337 +#define ER_IB_MSG_513 12338 +#define ER_IB_MSG_514 12339 +#define ER_IB_MSG_515 12340 +#define ER_IB_MSG_516 12341 +#define ER_IB_MSG_517 12342 +#define ER_IB_MSG_518 12343 +#define ER_IB_MSG_519 12344 +#define ER_IB_MSG_520 12345 +#define ER_IB_MSG_521 12346 +#define ER_IB_MSG_522 12347 +#define ER_IB_MSG_523 12348 +#define ER_IB_MSG_524 12349 +#define ER_IB_MSG_525 12350 +#define ER_IB_MSG_526 12351 +#define ER_IB_MSG_527 12352 +//#define OBSOLETE_ER_IB_MSG_528 12353 +//#define OBSOLETE_ER_IB_MSG_529 12354 +#define ER_IB_MSG_530 12355 +#define ER_IB_MSG_531 12356 +#define ER_IB_MSG_532 12357 +#define ER_IB_MSG_533 12358 +#define ER_IB_MSG_534 12359 +//#define OBSOLETE_ER_IB_MSG_535 12360 +//#define OBSOLETE_ER_IB_MSG_536 12361 +#define ER_IB_MSG_537 12362 +#define ER_IB_MSG_538 12363 +#define ER_IB_MSG_539 12364 +#define ER_IB_MSG_540 12365 +#define ER_IB_MSG_541 12366 +//#define OBSOLETE_ER_IB_MSG_542 12367 +#define ER_IB_MSG_543 12368 +#define ER_IB_MSG_544 12369 +#define ER_IB_MSG_545 12370 +#define ER_IB_MSG_546 12371 +#define ER_IB_MSG_547 12372 +#define ER_IB_MSG_548 12373 +#define ER_IB_MSG_549 12374 +#define ER_IB_MSG_550 12375 +#define ER_IB_MSG_551 12376 +#define ER_IB_MSG_552 12377 +#define ER_IB_MSG_553 12378 +#define ER_IB_MSG_554 12379 +#define ER_IB_MSG_555 12380 +#define ER_IB_MSG_556 12381 +#define ER_IB_MSG_557 12382 +#define ER_IB_MSG_558 12383 +#define ER_IB_MSG_559 12384 +#define ER_IB_MSG_560 12385 +#define ER_IB_MSG_561 12386 +#define ER_IB_MSG_562 12387 +#define ER_IB_MSG_563 12388 +#define ER_IB_MSG_564 12389 +#define ER_IB_MSG_INVALID_LOCATION_FOR_TABLE 12390 +#define ER_IB_MSG_566 12391 +#define ER_IB_MSG_567 12392 +#define ER_IB_MSG_568 12393 +#define ER_IB_MSG_569 12394 +#define ER_IB_MSG_570 12395 +#define ER_IB_MSG_571 12396 +//#define OBSOLETE_ER_IB_MSG_572 12397 +#define ER_IB_MSG_573 12398 +#define ER_IB_MSG_574 12399 +//#define OBSOLETE_ER_IB_MSG_575 12400 +//#define OBSOLETE_ER_IB_MSG_576 12401 +//#define OBSOLETE_ER_IB_MSG_577 12402 +#define ER_IB_MSG_578 12403 +#define ER_IB_MSG_579 12404 +#define ER_IB_MSG_580 12405 +#define ER_IB_MSG_581 12406 +#define ER_IB_MSG_582 12407 +#define ER_IB_MSG_583 12408 +#define ER_IB_MSG_584 12409 +#define ER_IB_MSG_585 12410 +#define ER_IB_MSG_586 12411 +#define ER_IB_MSG_587 12412 +#define ER_IB_MSG_588 12413 +#define ER_IB_MSG_589 12414 +#define ER_IB_MSG_590 12415 +#define ER_IB_MSG_591 12416 +#define ER_IB_MSG_592 12417 +#define ER_IB_MSG_593 12418 +#define ER_IB_MSG_594 12419 +#define ER_IB_MSG_595 12420 +#define ER_IB_MSG_596 12421 +#define ER_IB_MSG_597 12422 +#define ER_IB_MSG_598 12423 +#define ER_IB_MSG_599 12424 +#define ER_IB_MSG_600 12425 +#define ER_IB_MSG_601 12426 +#define ER_IB_MSG_602 12427 +#define ER_IB_MSG_603 12428 +#define ER_IB_MSG_604 12429 +#define ER_IB_MSG_605 12430 +#define ER_IB_MSG_606 12431 +#define ER_IB_MSG_607 12432 +#define ER_IB_MSG_608 12433 +#define ER_IB_MSG_609 12434 +//#define OBSOLETE_ER_IB_MSG_610 12435 +#define ER_IB_MSG_611 12436 +#define ER_IB_MSG_612 12437 +#define ER_IB_MSG_613 12438 +#define ER_IB_MSG_614 12439 +#define ER_IB_MSG_615 12440 +#define ER_IB_MSG_616 12441 +#define ER_IB_MSG_617 12442 +//#define OBSOLETE_ER_IB_MSG_618 12443 +#define ER_IB_MSG_619 12444 +#define ER_IB_MSG_IBUF_CURSOR_RESTORATION_FAILED 12445 +//#define OBSOLETE_ER_IB_MSG_621 12446 +#define ER_IB_MSG_IBUF_FAILED_TO_RESTORE_POSITION 12447 +#define ER_IB_MSG_623 12448 +#define ER_IB_MSG_624 12449 +//#define OBSOLETE_ER_IB_MSG_625 12450 +#define ER_IB_MSG_626 12451 +#define ER_IB_MSG_627 12452 +#define ER_IB_MSG_628 12453 +#define ER_IB_MSG_629 12454 +#define ER_IB_MSG_630 12455 +#define ER_IB_MSG_631 12456 +#define ER_IB_MSG_632 12457 +#define ER_IB_MSG_633 12458 +#define ER_IB_MSG_634 12459 +#define ER_IB_MSG_635 12460 +#define ER_IB_MSG_636 12461 +#define ER_IB_MSG_637 12462 +#define ER_IB_MSG_638 12463 +#define ER_IB_MSG_639 12464 +//#define OBSOLETE_ER_IB_MSG_640 12465 +//#define OBSOLETE_ER_IB_MSG_641 12466 +#define ER_IB_MSG_642 12467 +#define ER_IB_MSG_643 12468 +#define ER_IB_MSG_644 12469 +#define ER_IB_MSG_645 12470 +#define ER_IB_MSG_646 12471 +#define ER_IB_MSG_647 12472 +#define ER_IB_MSG_648 12473 +#define ER_IB_MSG_649 12474 +#define ER_IB_MSG_650 12475 +#define ER_IB_MSG_651 12476 +#define ER_IB_MSG_652 12477 +#define ER_IB_MSG_DDL_LOG_DELETE_BY_ID_OK 12478 +#define ER_IB_MSG_654 12479 +#define ER_IB_MSG_655 12480 +#define ER_IB_MSG_656 12481 +#define ER_IB_MSG_657 12482 +#define ER_IB_MSG_658 12483 +#define ER_IB_MSG_659 12484 +#define ER_IB_MSG_660 12485 +#define ER_IB_MSG_661 12486 +#define ER_IB_MSG_662 12487 +#define ER_IB_MSG_663 12488 +//#define OBSOLETE_ER_IB_MSG_664 12489 +//#define OBSOLETE_ER_IB_MSG_665 12490 +//#define OBSOLETE_ER_IB_MSG_666 12491 +//#define OBSOLETE_ER_IB_MSG_667 12492 +//#define OBSOLETE_ER_IB_MSG_668 12493 +//#define OBSOLETE_ER_IB_MSG_669 12494 +//#define OBSOLETE_ER_IB_MSG_670 12495 +//#define OBSOLETE_ER_IB_MSG_671 12496 +//#define OBSOLETE_ER_IB_MSG_672 12497 +//#define OBSOLETE_ER_IB_MSG_673 12498 +//#define OBSOLETE_ER_IB_MSG_674 12499 +//#define OBSOLETE_ER_IB_MSG_675 12500 +//#define OBSOLETE_ER_IB_MSG_676 12501 +//#define OBSOLETE_ER_IB_MSG_677 12502 +//#define OBSOLETE_ER_IB_MSG_678 12503 +//#define OBSOLETE_ER_IB_MSG_679 12504 +//#define OBSOLETE_ER_IB_MSG_680 12505 +//#define OBSOLETE_ER_IB_MSG_681 12506 +//#define OBSOLETE_ER_IB_MSG_682 12507 +//#define OBSOLETE_ER_IB_MSG_683 12508 +//#define OBSOLETE_ER_IB_MSG_684 12509 +//#define OBSOLETE_ER_IB_MSG_685 12510 +//#define OBSOLETE_ER_IB_MSG_686 12511 +//#define OBSOLETE_ER_IB_MSG_687 12512 +//#define OBSOLETE_ER_IB_MSG_688 12513 +//#define OBSOLETE_ER_IB_MSG_689 12514 +//#define OBSOLETE_ER_IB_MSG_690 12515 +//#define OBSOLETE_ER_IB_MSG_691 12516 +//#define OBSOLETE_ER_IB_MSG_692 12517 +//#define OBSOLETE_ER_IB_MSG_693 12518 +#define ER_IB_MSG_694 12519 +#define ER_IB_MSG_695 12520 +#define ER_IB_MSG_696 12521 +#define ER_IB_MSG_697 12522 +#define ER_IB_MSG_LOG_CORRUPT 12523 +#define ER_IB_MSG_699 12524 +#define ER_IB_MSG_LOG_FORMAT_OLD_AND_LOG_CORRUPTED 12525 +#define ER_IB_MSG_LOG_FORMAT_OLD_AND_NO_CLEAN_SHUTDOWN 12526 +//#define OBSOLETE_ER_IB_MSG_702 12527 +//#define OBSOLETE_ER_IB_MSG_703 12528 +#define ER_IB_MSG_LOG_FORMAT_BEFORE_8_0_30 12529 +#define ER_IB_MSG_LOG_FILE_FORMAT_UNKNOWN 12530 +#define ER_IB_MSG_RECOVERY_CHECKPOINT_NOT_FOUND 12531 +#define ER_IB_MSG_707 12532 +#define ER_IB_MSG_708 12533 +#define ER_IB_MSG_709 12534 +#define ER_IB_MSG_710 12535 +#define ER_IB_MSG_711 12536 +#define ER_IB_MSG_712 12537 +#define ER_IB_MSG_713 12538 +#define ER_IB_MSG_714 12539 +#define ER_IB_MSG_715 12540 +#define ER_IB_MSG_716 12541 +//#define OBSOLETE_ER_IB_MSG_717 12542 +#define ER_IB_MSG_718 12543 +#define ER_IB_MSG_719 12544 +#define ER_IB_MSG_720 12545 +#define ER_IB_MSG_RECOVERY_SKIPPED_IN_READ_ONLY_MODE 12546 +#define ER_IB_MSG_722 12547 +#define ER_IB_MSG_723 12548 +#define ER_IB_MSG_724 12549 +#define ER_IB_MSG_725 12550 +#define ER_IB_MSG_726 12551 +#define ER_IB_MSG_727 12552 +#define ER_IB_MSG_728 12553 +#define ER_IB_MSG_LOG_FILES_CREATED_BY_MEB_AND_READ_ONLY_MODE 12554 +#define ER_IB_MSG_LOG_FILES_CREATED_BY_MEB 12555 +#define ER_IB_MSG_LOG_FILES_CREATED_BY_CLONE 12556 +#define ER_IB_MSG_LOG_FORMAT_OLD 12557 +//#define OBSOLETE_ER_IB_MSG_LOG_FORMAT_NOT_SUPPORTED 12558 +#define ER_IB_MSG_RECOVERY_CHECKPOINT_FROM_BEFORE_CLEAN_SHUTDOWN 12559 +#define ER_IB_MSG_RECOVERY_IS_NEEDED 12560 +#define ER_IB_MSG_RECOVERY_IN_READ_ONLY 12561 +#define ER_IB_MSG_737 12562 +#define ER_IB_MSG_738 12563 +#define ER_IB_MSG_739 12564 +#define ER_IB_MSG_740 12565 +#define ER_IB_MSG_741 12566 +#define ER_IB_MSG_742 12567 +#define ER_IB_MSG_743 12568 +#define ER_IB_MSG_744 12569 +#define ER_IB_MSG_745 12570 +#define ER_IB_MSG_746 12571 +#define ER_IB_MSG_747 12572 +#define ER_IB_MSG_748 12573 +#define ER_IB_MSG_749 12574 +#define ER_IB_MSG_750 12575 +#define ER_IB_MSG_751 12576 +#define ER_IB_MSG_752 12577 +#define ER_IB_MSG_753 12578 +#define ER_IB_MSG_754 12579 +#define ER_IB_MSG_755 12580 +#define ER_IB_MSG_756 12581 +#define ER_IB_MSG_757 12582 +#define ER_IB_MSG_758 12583 +#define ER_IB_MSG_759 12584 +#define ER_IB_MSG_760 12585 +#define ER_IB_MSG_761 12586 +#define ER_IB_MSG_762 12587 +#define ER_IB_MSG_763 12588 +#define ER_IB_MSG_764 12589 +#define ER_IB_MSG_765 12590 +#define ER_IB_MSG_766 12591 +#define ER_IB_MSG_767 12592 +#define ER_IB_MSG_768 12593 +#define ER_IB_MSG_769 12594 +#define ER_IB_MSG_770 12595 +#define ER_IB_MSG_771 12596 +#define ER_IB_MSG_772 12597 +#define ER_IB_MSG_773 12598 +#define ER_IB_MSG_774 12599 +#define ER_IB_MSG_775 12600 +#define ER_IB_MSG_776 12601 +#define ER_IB_MSG_777 12602 +#define ER_IB_MSG_778 12603 +#define ER_IB_MSG_779 12604 +#define ER_IB_MSG_780 12605 +#define ER_IB_MSG_781 12606 +#define ER_IB_MSG_782 12607 +#define ER_IB_MSG_783 12608 +#define ER_IB_MSG_784 12609 +#define ER_IB_MSG_785 12610 +#define ER_IB_MSG_786 12611 +#define ER_IB_MSG_787 12612 +#define ER_IB_MSG_788 12613 +#define ER_IB_MSG_789 12614 +#define ER_IB_MSG_790 12615 +#define ER_IB_MSG_791 12616 +#define ER_IB_MSG_792 12617 +#define ER_IB_MSG_793 12618 +#define ER_IB_MSG_794 12619 +#define ER_IB_MSG_795 12620 +#define ER_IB_MSG_796 12621 +#define ER_IB_MSG_797 12622 +#define ER_IB_MSG_798 12623 +#define ER_IB_MSG_799 12624 +#define ER_IB_MSG_800 12625 +#define ER_IB_MSG_801 12626 +#define ER_IB_MSG_802 12627 +#define ER_IB_MSG_803 12628 +#define ER_IB_MSG_804 12629 +#define ER_IB_MSG_805 12630 +#define ER_IB_MSG_806 12631 +#define ER_IB_MSG_807 12632 +#define ER_IB_MSG_808 12633 +#define ER_IB_MSG_809 12634 +#define ER_IB_MSG_810 12635 +#define ER_IB_MSG_811 12636 +#define ER_IB_MSG_812 12637 +#define ER_IB_MSG_813 12638 +#define ER_IB_MSG_814 12639 +#define ER_IB_MSG_815 12640 +#define ER_IB_MSG_816 12641 +#define ER_IB_MSG_817 12642 +#define ER_IB_MSG_818 12643 +#define ER_IB_MSG_819 12644 +#define ER_IB_MSG_820 12645 +#define ER_IB_MSG_821 12646 +#define ER_IB_MSG_822 12647 +#define ER_IB_MSG_823 12648 +#define ER_IB_MSG_824 12649 +#define ER_IB_MSG_825 12650 +#define ER_IB_MSG_826 12651 +#define ER_IB_MSG_827 12652 +#define ER_IB_MSG_828 12653 +#define ER_IB_MSG_829 12654 +#define ER_IB_MSG_830 12655 +#define ER_IB_MSG_831 12656 +#define ER_IB_MSG_832 12657 +#define ER_IB_MSG_833 12658 +#define ER_IB_MSG_834 12659 +#define ER_IB_MSG_835 12660 +#define ER_IB_MSG_836 12661 +#define ER_IB_MSG_837 12662 +#define ER_IB_MSG_838 12663 +#define ER_IB_MSG_839 12664 +#define ER_IB_MSG_840 12665 +#define ER_IB_MSG_841 12666 +#define ER_IB_MSG_842 12667 +#define ER_IB_MSG_CANT_ENCRYPT_REDO_LOG_DATA 12668 +#define ER_IB_MSG_844 12669 +#define ER_IB_MSG_845 12670 +#define ER_IB_MSG_CANT_DECRYPT_REDO_LOG 12671 +#define ER_IB_MSG_847 12672 +#define ER_IB_MSG_848 12673 +#define ER_IB_MSG_849 12674 +#define ER_IB_MSG_850 12675 +#define ER_IB_MSG_851 12676 +#define ER_IB_MSG_852 12677 +#define ER_IB_MSG_853 12678 +#define ER_IB_MSG_854 12679 +#define ER_IB_MSG_855 12680 +#define ER_IB_MSG_856 12681 +#define ER_IB_MSG_857 12682 +#define ER_IB_MSG_858 12683 +#define ER_IB_MSG_859 12684 +#define ER_IB_MSG_860 12685 +#define ER_IB_MSG_861 12686 +#define ER_IB_MSG_862 12687 +#define ER_IB_MSG_863 12688 +#define ER_IB_MSG_864 12689 +#define ER_IB_MSG_865 12690 +#define ER_IB_MSG_866 12691 +#define ER_IB_MSG_867 12692 +#define ER_IB_MSG_868 12693 +#define ER_IB_MSG_869 12694 +#define ER_IB_MSG_870 12695 +#define ER_IB_MSG_871 12696 +#define ER_IB_MSG_872 12697 +#define ER_IB_MSG_873 12698 +#define ER_IB_MSG_874 12699 +#define ER_IB_MSG_875 12700 +#define ER_IB_MSG_876 12701 +#define ER_IB_MSG_877 12702 +#define ER_IB_MSG_878 12703 +#define ER_IB_MSG_879 12704 +#define ER_IB_MSG_880 12705 +#define ER_IB_MSG_881 12706 +#define ER_IB_MSG_882 12707 +#define ER_IB_MSG_883 12708 +#define ER_IB_MSG_884 12709 +#define ER_IB_MSG_885 12710 +#define ER_IB_MSG_886 12711 +#define ER_IB_MSG_887 12712 +#define ER_IB_MSG_888 12713 +#define ER_IB_MSG_889 12714 +#define ER_IB_MSG_890 12715 +#define ER_IB_MSG_891 12716 +#define ER_IB_MSG_892 12717 +#define ER_IB_MSG_893 12718 +#define ER_IB_MSG_894 12719 +#define ER_IB_MSG_895 12720 +#define ER_IB_MSG_896 12721 +#define ER_IB_MSG_897 12722 +#define ER_IB_MSG_898 12723 +#define ER_IB_MSG_899 12724 +#define ER_IB_MSG_900 12725 +#define ER_IB_MSG_901 12726 +#define ER_IB_MSG_902 12727 +#define ER_IB_MSG_903 12728 +#define ER_IB_MSG_904 12729 +#define ER_IB_MSG_905 12730 +#define ER_IB_MSG_906 12731 +#define ER_IB_MSG_907 12732 +#define ER_IB_MSG_908 12733 +#define ER_IB_MSG_909 12734 +#define ER_IB_MSG_910 12735 +#define ER_IB_MSG_911 12736 +#define ER_IB_MSG_912 12737 +#define ER_IB_MSG_913 12738 +#define ER_IB_MSG_914 12739 +#define ER_IB_MSG_915 12740 +#define ER_IB_MSG_916 12741 +#define ER_IB_MSG_917 12742 +#define ER_IB_MSG_918 12743 +#define ER_IB_MSG_919 12744 +#define ER_IB_MSG_920 12745 +#define ER_IB_MSG_921 12746 +#define ER_IB_MSG_922 12747 +#define ER_IB_MSG_923 12748 +#define ER_IB_MSG_924 12749 +#define ER_IB_MSG_925 12750 +#define ER_IB_MSG_926 12751 +#define ER_IB_MSG_927 12752 +#define ER_IB_MSG_928 12753 +#define ER_IB_MSG_929 12754 +#define ER_IB_MSG_930 12755 +#define ER_IB_MSG_931 12756 +#define ER_IB_MSG_932 12757 +#define ER_IB_MSG_933 12758 +#define ER_IB_MSG_934 12759 +#define ER_IB_MSG_935 12760 +#define ER_IB_MSG_936 12761 +#define ER_IB_MSG_937 12762 +#define ER_IB_MSG_938 12763 +#define ER_IB_MSG_939 12764 +#define ER_IB_MSG_940 12765 +#define ER_IB_MSG_941 12766 +#define ER_IB_MSG_942 12767 +#define ER_IB_MSG_943 12768 +#define ER_IB_MSG_944 12769 +#define ER_IB_MSG_945 12770 +#define ER_IB_MSG_946 12771 +#define ER_IB_IMPORT_INDEX_METADATA_READ_FAILED 12772 +#define ER_IB_MSG_948 12773 +#define ER_IB_MSG_949 12774 +#define ER_IB_MSG_950 12775 +#define ER_IB_MSG_951 12776 +#define ER_IB_MSG_952 12777 +#define ER_IB_MSG_953 12778 +#define ER_IB_MSG_954 12779 +#define ER_IB_MSG_955 12780 +#define ER_IB_MSG_956 12781 +#define ER_IB_MSG_957 12782 +#define ER_IB_MSG_958 12783 +#define ER_IB_MSG_959 12784 +#define ER_IB_MSG_960 12785 +#define ER_IB_MSG_961 12786 +#define ER_IB_MSG_962 12787 +#define ER_IB_MSG_963 12788 +#define ER_IB_MSG_964 12789 +#define ER_IB_MSG_965 12790 +#define ER_IB_MSG_966 12791 +#define ER_IB_MSG_967 12792 +#define ER_IB_MSG_968 12793 +#define ER_IB_MSG_969 12794 +#define ER_IB_MSG_970 12795 +#define ER_IB_MSG_971 12796 +#define ER_IB_MSG_972 12797 +#define ER_IB_MSG_973 12798 +#define ER_IB_MSG_974 12799 +#define ER_IB_MSG_975 12800 +#define ER_IB_MSG_976 12801 +#define ER_IB_MSG_977 12802 +#define ER_IB_MSG_978 12803 +#define ER_IB_MSG_979 12804 +#define ER_IB_MSG_980 12805 +#define ER_IB_MSG_981 12806 +#define ER_IB_MSG_982 12807 +#define ER_IB_MSG_983 12808 +#define ER_IB_MSG_984 12809 +#define ER_IB_MSG_985 12810 +#define ER_IB_MSG_986 12811 +#define ER_IB_MSG_987 12812 +#define ER_IB_MSG_988 12813 +#define ER_IB_MSG_989 12814 +#define ER_IB_MSG_990 12815 +#define ER_IB_MSG_991 12816 +#define ER_IB_MSG_992 12817 +#define ER_IB_MSG_993 12818 +#define ER_IB_MSG_994 12819 +#define ER_IB_MSG_995 12820 +#define ER_IB_MSG_996 12821 +#define ER_IB_MSG_997 12822 +#define ER_IB_MSG_998 12823 +#define ER_IB_MSG_999 12824 +#define ER_IB_MSG_1000 12825 +#define ER_IB_MSG_1001 12826 +#define ER_IB_MSG_1002 12827 +#define ER_IB_MSG_1003 12828 +#define ER_IB_MSG_1004 12829 +#define ER_IB_MSG_1005 12830 +#define ER_IB_MSG_1006 12831 +#define ER_IB_MSG_1007 12832 +#define ER_IB_MSG_1008 12833 +#define ER_IB_MSG_1009 12834 +#define ER_IB_MSG_1010 12835 +#define ER_IB_MSG_1011 12836 +#define ER_IB_MSG_1012 12837 +#define ER_IB_MSG_1013 12838 +#define ER_IB_IMPORT_START_CFG_NAME 12839 +#define ER_IB_MSG_1015 12840 +#define ER_IB_MSG_1016 12841 +#define ER_IB_MSG_1017 12842 +#define ER_IB_MSG_1018 12843 +#define ER_IB_MSG_1019 12844 +#define ER_IB_MSG_1020 12845 +#define ER_IB_MSG_1021 12846 +#define ER_IB_MSG_1022 12847 +#define ER_IB_MSG_1023 12848 +#define ER_IB_MSG_1024 12849 +#define ER_IB_MSG_1025 12850 +#define ER_IB_MSG_1026 12851 +#define ER_IB_MSG_1027 12852 +#define ER_IB_MSG_1028 12853 +#define ER_IB_MSG_1029 12854 +#define ER_IB_MSG_1030 12855 +#define ER_IB_MSG_1031 12856 +#define ER_IB_MSG_1032 12857 +#define ER_IB_MSG_1033 12858 +#define ER_IB_MSG_1034 12859 +#define ER_IB_MSG_1035 12860 +#define ER_IB_MSG_1036 12861 +#define ER_IB_MSG_1037 12862 +#define ER_IB_MSG_1038 12863 +#define ER_IB_MSG_1039 12864 +#define ER_IB_MSG_1040 12865 +#define ER_IB_MSG_1041 12866 +#define ER_IB_MSG_1042 12867 +#define ER_IB_MSG_1043 12868 +#define ER_IB_MSG_1044 12869 +#define ER_IB_MSG_1045 12870 +#define ER_IB_MSG_1046 12871 +#define ER_IB_MSG_1047 12872 +#define ER_IB_MSG_1048 12873 +#define ER_IB_MSG_1049 12874 +//#define OBSOLETE_ER_IB_MSG_1050 12875 +#define ER_IB_MSG_1051 12876 +#define ER_IB_MSG_1052 12877 +#define ER_IB_MSG_1053 12878 +#define ER_IB_MSG_1054 12879 +#define ER_IB_MSG_1055 12880 +#define ER_IB_MSG_1056 12881 +#define ER_IB_MSG_1057 12882 +#define ER_IB_MSG_1058 12883 +#define ER_IB_MSG_1059 12884 +#define ER_IB_MSG_1060 12885 +#define ER_IB_MSG_LOG_FILE_OS_CREATE_FAILED 12886 +#define ER_IB_MSG_FILE_RESIZE 12887 +#define ER_IB_MSG_LOG_FILE_RESIZE_FAILED 12888 +#define ER_IB_MSG_LOG_FILES_CREATE_AND_READ_ONLY_MODE 12889 +#define ER_IB_MSG_1065 12890 +#define ER_IB_MSG_LOG_FILE_PREPARE_ON_CREATE_FAILED 12891 +//#define OBSOLETE_ER_IB_MSG_1067 12892 +#define ER_IB_MSG_LOG_FILES_INITIALIZED 12893 +#define ER_IB_MSG_LOG_FILE_OPEN_FAILED 12894 +#define ER_IB_MSG_1070 12895 +#define ER_IB_MSG_1071 12896 +#define ER_IB_MSG_1072 12897 +#define ER_IB_MSG_1073 12898 +#define ER_IB_MSG_1074 12899 +#define ER_IB_MSG_1075 12900 +#define ER_IB_MSG_1076 12901 +#define ER_IB_MSG_1077 12902 +#define ER_IB_MSG_1078 12903 +#define ER_IB_MSG_1079 12904 +#define ER_IB_MSG_1080 12905 +#define ER_IB_MSG_1081 12906 +#define ER_IB_MSG_1082 12907 +#define ER_IB_MSG_1083 12908 +#define ER_IB_MSG_CANNOT_OPEN_57_UNDO 12909 +#define ER_IB_MSG_1085 12910 +#define ER_IB_MSG_1086 12911 +#define ER_IB_MSG_1087 12912 +#define ER_IB_MSG_1088 12913 +#define ER_IB_MSG_1089 12914 +#define ER_IB_MSG_1090 12915 +#define ER_IB_MSG_1091 12916 +#define ER_IB_MSG_1092 12917 +#define ER_IB_MSG_1093 12918 +#define ER_IB_MSG_1094 12919 +#define ER_IB_MSG_1095 12920 +#define ER_IB_MSG_1096 12921 +#define ER_IB_MSG_1097 12922 +#define ER_IB_MSG_1098 12923 +#define ER_IB_MSG_1099 12924 +#define ER_IB_MSG_1100 12925 +#define ER_IB_MSG_1101 12926 +#define ER_IB_MSG_1102 12927 +#define ER_IB_MSG_1103 12928 +#define ER_IB_MSG_1104 12929 +#define ER_IB_MSG_1105 12930 +#define ER_IB_MSG_BUF_PENDING_IO 12931 +#define ER_IB_MSG_1107 12932 +#define ER_IB_MSG_1108 12933 +#define ER_IB_MSG_1109 12934 +#define ER_IB_MSG_1110 12935 +#define ER_IB_MSG_1111 12936 +#define ER_IB_MSG_1112 12937 +#define ER_IB_MSG_1113 12938 +#define ER_IB_MSG_1114 12939 +#define ER_IB_MSG_1115 12940 +#define ER_IB_MSG_1116 12941 +#define ER_IB_MSG_1117 12942 +//#define OBSOLETE_ER_IB_MSG_1118 12943 +#define ER_IB_MSG_1119 12944 +#define ER_IB_MSG_1120 12945 +#define ER_IB_MSG_1121 12946 +#define ER_IB_MSG_1122 12947 +#define ER_IB_MSG_1123 12948 +#define ER_IB_MSG_1124 12949 +#define ER_IB_MSG_1125 12950 +#define ER_IB_MSG_1126 12951 +#define ER_IB_MSG_1127 12952 +#define ER_IB_MSG_1128 12953 +#define ER_IB_MSG_1129 12954 +#define ER_IB_MSG_1130 12955 +#define ER_IB_MSG_1131 12956 +#define ER_IB_MSG_1132 12957 +#define ER_IB_MSG_1133 12958 +#define ER_IB_MSG_1134 12959 +#define ER_IB_MSG_DATA_DIRECTORY_NOT_INITIALIZED_OR_CORRUPTED 12960 +#define ER_IB_MSG_LOG_FILES_INVALID_SET 12961 +#define ER_IB_MSG_LOG_FILE_SIZE_INVALID 12962 +#define ER_IB_MSG_LOG_FILES_DIFFERENT_SIZES 12963 +#define ER_IB_MSG_1139 12964 +#define ER_IB_MSG_RECOVERY_CORRUPT 12965 +//#define OBSOLETE_ER_IB_MSG_LOG_FILES_RESIZE_ON_START_IN_READ_ONLY_MODE 12966 +#define ER_IB_MSG_1142 12967 +#define ER_IB_MSG_LOG_FILES_REWRITING 12968 +#define ER_IB_MSG_1144 12969 +#define ER_IB_MSG_1145 12970 +#define ER_IB_MSG_1146 12971 +#define ER_IB_MSG_1147 12972 +#define ER_IB_MSG_1148 12973 +#define ER_IB_MSG_1149 12974 +#define ER_IB_MSG_1150 12975 +#define ER_IB_MSG_1151 12976 +#define ER_IB_MSG_1152 12977 +//#define OBSOLETE_ER_IB_MSG_1153 12978 +#define ER_IB_MSG_1154 12979 +#define ER_IB_MSG_1155 12980 +#define ER_IB_MSG_1156 12981 +#define ER_IB_MSG_1157 12982 +#define ER_IB_MSG_1158 12983 +#define ER_IB_MSG_1159 12984 +#define ER_IB_MSG_1160 12985 +#define ER_IB_MSG_1161 12986 +#define ER_IB_MSG_1162 12987 +#define ER_IB_MSG_1163 12988 +#define ER_IB_MSG_1164 12989 +#define ER_IB_MSG_1165 12990 +#define ER_IB_MSG_UNDO_TRUNCATE_FAIL_TO_READ_LOG_FILE 12991 +#define ER_IB_MSG_UNDO_MARKED_FOR_TRUNCATE 12992 +//#define OBSOLETE_ER_IB_MSG_UNDO_INJECT_BEFORE_MDL 12993 +#define ER_IB_MSG_UNDO_TRUNCATE_START 12994 +//#define OBSOLETE_ER_IB_MSG_UNDO_INJECT_BEFORE_DDL_LOG_START 12995 +#define ER_IB_MSG_UNDO_TRUNCATE_DELAY_BY_LOG_CREATE 12996 +//#define OBSOLETE_ER_IB_MSG_UNDO_INJECT_BEFORE_TRUNCATE 12997 +#define ER_IB_MSG_UNDO_TRUNCATE_DELAY_BY_FAILURE 12998 +//#define OBSOLETE_ER_IB_MSG_UNDO_INJECT_BEFORE_STATE_UPDATE 12999 +#define ER_IB_MSG_UNDO_TRUNCATE_COMPLETE 13000 +//#define OBSOLETE_ER_IB_MSG_UNDO_INJECT_TRUNCATE_DONE 13001 +#define ER_IB_MSG_1177 13002 +#define ER_IB_MSG_1178 13003 +#define ER_IB_MSG_1179 13004 +#define ER_IB_MSG_1180 13005 +#define ER_IB_MSG_1181 13006 +#define ER_IB_MSG_1182 13007 +#define ER_IB_MSG_1183 13008 +#define ER_IB_ERR_ACCESSING_OUT_OF_BOUND_FIELD_IN_INDEX 13009 +#define ER_IB_MSG_1185 13010 +#define ER_IB_MSG_1186 13011 +#define ER_IB_MSG_1187 13012 +#define ER_IB_MSG_1188 13013 +#define ER_IB_MSG_1189 13014 +#define ER_IB_MSG_TRX_RECOVERY_ROLLBACK_COMPLETED 13015 +#define ER_IB_MSG_1191 13016 +#define ER_IB_MSG_1192 13017 +#define ER_IB_MSG_1193 13018 +#define ER_IB_MSG_1194 13019 +#define ER_IB_MSG_1195 13020 +#define ER_IB_MSG_1196 13021 +#define ER_IB_MSG_1197 13022 +#define ER_IB_MSG_1198 13023 +#define ER_IB_MSG_1199 13024 +#define ER_IB_MSG_1200 13025 +#define ER_IB_MSG_1201 13026 +#define ER_IB_MSG_1202 13027 +#define ER_IB_MSG_1203 13028 +#define ER_IB_MSG_1204 13029 +#define ER_IB_MSG_1205 13030 +#define ER_IB_MSG_1206 13031 +#define ER_IB_MSG_1207 13032 +#define ER_IB_MSG_1208 13033 +#define ER_IB_MSG_1209 13034 +#define ER_IB_MSG_1210 13035 +#define ER_IB_MSG_1211 13036 +#define ER_IB_MSG_1212 13037 +#define ER_IB_MSG_1213 13038 +#define ER_IB_MSG_1214 13039 +#define ER_IB_MSG_1215 13040 +#define ER_IB_MSG_LOG_FILES_RESIZE_ON_START 13041 +#define ER_IB_MSG_1217 13042 +#define ER_IB_MSG_1218 13043 +#define ER_IB_MSG_1219 13044 +#define ER_IB_MSG_1220 13045 +#define ER_IB_MSG_1221 13046 +#define ER_IB_MSG_1222 13047 +#define ER_IB_MSG_1223 13048 +#define ER_IB_MSG_1224 13049 +#define ER_IB_MSG_1225 13050 +#define ER_IB_MSG_1226 13051 +#define ER_IB_MSG_1227 13052 +#define ER_IB_MSG_1228 13053 +#define ER_IB_MSG_1229 13054 +//#define OBSOLETE_ER_IB_MSG_1230 13055 +#define ER_IB_MSG_1231 13056 +//#define OBSOLETE_ER_IB_MSG_1232 13057 +#define ER_IB_MSG_1233 13058 +#define ER_IB_MSG_LOG_WRITER_OUT_OF_SPACE 13059 +#define ER_IB_MSG_1235 13060 +#define ER_IB_MSG_LOG_WRITER_ABORTS_LOG_ARCHIVER 13061 +#define ER_IB_MSG_LOG_WRITER_WAITING_FOR_ARCHIVER 13062 +#define ER_IB_MSG_1238 13063 +#define ER_IB_MSG_1239 13064 +//#define OBSOLETE_ER_IB_MSG_1240 13065 +#define ER_IB_MSG_1241 13066 +#define ER_IB_MSG_LOG_FILES_CANNOT_ENCRYPT_IN_READ_ONLY 13067 +#define ER_IB_MSG_LOG_FILES_ENCRYPTION_INIT_FAILED 13068 +//#define OBSOLETE_ER_IB_MSG_1244 13069 +#define ER_IB_MSG_1245 13070 +#define ER_IB_MSG_1246 13071 +#define ER_IB_MSG_1247 13072 +#define ER_IB_MSG_1248 13073 +#define ER_IB_MSG_1249 13074 +#define ER_IB_MSG_1250 13075 +#define ER_IB_MSG_1251 13076 +#define ER_IB_MSG_BUF_PENDING_IO_ON_SHUTDOWN 13077 +#define ER_IB_MSG_1253 13078 +//#define OBSOLETE_ER_IB_MSG_1254 13079 +#define ER_IB_MSG_1255 13080 +#define ER_IB_MSG_1256 13081 +#define ER_IB_MSG_1257 13082 +#define ER_IB_MSG_1258 13083 +#define ER_IB_MSG_1259 13084 +#define ER_IB_MSG_1260 13085 +#define ER_IB_MSG_1261 13086 +#define ER_IB_MSG_1262 13087 +#define ER_IB_MSG_1263 13088 +#define ER_IB_MSG_LOG_FILE_HEADER_INVALID_CHECKSUM 13089 +#define ER_IB_MSG_LOG_FORMAT_BEFORE_5_7_9 13090 +#define ER_IB_MSG_1266 13091 +#define ER_IB_MSG_LOG_PARAMS_CONCURRENCY_MARGIN_UNSAFE 13092 +#define ER_IB_MSG_1268 13093 +#define ER_IB_MSG_1269 13094 +#define ER_IB_MSG_THREAD_CONCURRENCY_CHANGED 13095 +#define ER_RPL_REPLICA_SQL_THREAD_STOP_CMD_EXEC_TIMEOUT 13096 +#define ER_RPL_REPLICA_IO_THREAD_STOP_CMD_EXEC_TIMEOUT 13097 +#define ER_RPL_GTID_UNSAFE_STMT_ON_NON_TRANS_TABLE 13098 +#define ER_RPL_GTID_UNSAFE_STMT_CREATE_SELECT 13099 +//#define OBSOLETE_ER_RPL_GTID_UNSAFE_STMT_ON_TEMPORARY_TABLE 13100 +#define ER_BINLOG_ROW_VALUE_OPTION_IGNORED 13101 +//#define OBSOLETE_ER_BINLOG_USE_V1_ROW_EVENTS_IGNORED 13102 +#define ER_BINLOG_ROW_VALUE_OPTION_USED_ONLY_FOR_AFTER_IMAGES 13103 +#define ER_CONNECTION_ABORTED 13104 +#define ER_NORMAL_SERVER_SHUTDOWN 13105 +#define ER_KEYRING_MIGRATE_FAILED 13106 +#define ER_GRP_RPL_LOWER_CASE_TABLE_NAMES_DIFF_FROM_GRP 13107 +#define ER_OOM_SAVE_GTIDS 13108 +#define ER_LCTN_NOT_FOUND 13109 +//#define OBSOLETE_ER_REGEXP_INVALID_CAPTURE_GROUP_NAME 13110 +#define ER_COMPONENT_FILTER_WRONG_VALUE 13111 +#define ER_XPLUGIN_FAILED_TO_STOP_SERVICES 13112 +#define ER_INCONSISTENT_ERROR 13113 +#define ER_SERVER_SOURCE_FATAL_ERROR_READING_BINLOG 13114 +#define ER_NETWORK_READ_EVENT_CHECKSUM_FAILURE 13115 +#define ER_REPLICA_CREATE_EVENT_FAILURE 13116 +#define ER_REPLICA_FATAL_ERROR 13117 +#define ER_REPLICA_HEARTBEAT_FAILURE 13118 +#define ER_REPLICA_INCIDENT 13119 +#define ER_REPLICA_SOURCE_COM_FAILURE 13120 +#define ER_REPLICA_RELAY_LOG_READ_FAILURE 13121 +#define ER_REPLICA_RELAY_LOG_WRITE_FAILURE 13122 +#define ER_SERVER_REPLICA_CM_INIT_REPOSITORY 13123 +#define ER_SERVER_REPLICA_AM_INIT_REPOSITORY 13124 +#define ER_SERVER_NET_PACKET_TOO_LARGE 13125 +#define ER_SERVER_NO_SYSTEM_TABLE_ACCESS 13126 +//#define OBSOLETE_ER_SERVER_UNKNOWN_ERROR 13127 +#define ER_SERVER_UNKNOWN_SYSTEM_VARIABLE 13128 +#define ER_SERVER_NO_SESSION_TO_SEND_TO 13129 +#define ER_SERVER_NEW_ABORTING_CONNECTION 13130 +#define ER_SERVER_OUT_OF_SORTMEMORY 13131 +#define ER_SERVER_RECORD_FILE_FULL 13132 +#define ER_SERVER_DISK_FULL_NOWAIT 13133 +#define ER_SERVER_HANDLER_ERROR 13134 +#define ER_SERVER_NOT_FORM_FILE 13135 +#define ER_SERVER_CANT_OPEN_FILE 13136 +#define ER_SERVER_FILE_NOT_FOUND 13137 +#define ER_SERVER_FILE_USED 13138 +#define ER_SERVER_CANNOT_LOAD_FROM_TABLE_V2 13139 +#define ER_ERROR_INFO_FROM_DA 13140 +#define ER_SERVER_TABLE_CHECK_FAILED 13141 +#define ER_SERVER_COL_COUNT_DOESNT_MATCH_PLEASE_UPDATE_V2 13142 +#define ER_SERVER_COL_COUNT_DOESNT_MATCH_CORRUPTED_V2 13143 +#define ER_SERVER_ACL_TABLE_ERROR 13144 +#define ER_SERVER_REPLICA_INIT_QUERY_FAILED 13145 +#define ER_SERVER_REPLICA_CONVERSION_FAILED 13146 +#define ER_SERVER_REPLICA_IGNORED_TABLE 13147 +#define ER_CANT_REPLICATE_ANONYMOUS_WITH_AUTO_POSITION 13148 +#define ER_CANT_REPLICATE_ANONYMOUS_WITH_GTID_MODE_ON 13149 +#define ER_CANT_REPLICATE_GTID_WITH_GTID_MODE_OFF 13150 +#define ER_SERVER_TEST_MESSAGE 13151 +#define ER_AUDIT_LOG_JSON_FILTER_PARSING_ERROR 13152 +#define ER_AUDIT_LOG_JSON_FILTERING_NOT_ENABLED 13153 +#define ER_PLUGIN_FAILED_TO_OPEN_TABLES 13154 +#define ER_PLUGIN_FAILED_TO_OPEN_TABLE 13155 +#define ER_AUDIT_LOG_JSON_FILTER_NAME_CANNOT_BE_EMPTY 13156 +#define ER_AUDIT_LOG_USER_NAME_INVALID_CHARACTER 13157 +#define ER_AUDIT_LOG_UDF_INSUFFICIENT_PRIVILEGE 13158 +#define ER_AUDIT_LOG_NO_KEYRING_PLUGIN_INSTALLED 13159 +#define ER_AUDIT_LOG_HOST_NAME_INVALID_CHARACTER 13160 +#define ER_AUDIT_LOG_ENCRYPTION_PASSWORD_HAS_NOT_BEEN_SET 13161 +#define ER_AUDIT_LOG_COULD_NOT_CREATE_AES_KEY 13162 +#define ER_AUDIT_LOG_ENCRYPTION_PASSWORD_CANNOT_BE_FETCHED 13163 +#define ER_COULD_NOT_REINITIALIZE_AUDIT_LOG_FILTERS 13164 +#define ER_AUDIT_LOG_JSON_USER_NAME_CANNOT_BE_EMPTY 13165 +#define ER_AUDIT_LOG_USER_FIRST_CHARACTER_MUST_BE_ALPHANUMERIC 13166 +#define ER_AUDIT_LOG_JSON_FILTER_DOES_NOT_EXIST 13167 +//#define OBSOLETE_ER_IB_MSG_1271 13168 +#define ER_STARTING_INIT 13169 +#define ER_ENDING_INIT 13170 +#define ER_IB_MSG_1272 13171 +#define ER_SERVER_SHUTDOWN_INFO 13172 +#define ER_GRP_RPL_PLUGIN_ABORT 13173 +//#define OBSOLETE_ER_REGEXP_INVALID_FLAG 13174 +//#define OBSOLETE_ER_XA_REPLICATION_FILTERS 13175 +//#define OBSOLETE_ER_UPDATE_GTID_PURGED_WITH_GR 13176 +#define ER_AUDIT_LOG_TABLE_DEFINITION_NOT_UPDATED 13177 +#define ER_DD_INITIALIZE_SQL_ERROR 13178 +#define ER_NO_PATH_FOR_SHARED_LIBRARY 13179 +#define ER_UDF_ALREADY_EXISTS 13180 +#define ER_SET_EVENT_FAILED 13181 +#define ER_FAILED_TO_ALLOCATE_SSL_BIO 13182 +#define ER_IB_MSG_1273 13183 +#define ER_PID_FILEPATH_LOCATIONS_INACCESSIBLE 13184 +#define ER_UNKNOWN_VARIABLE_IN_PERSISTED_CONFIG_FILE 13185 +#define ER_FAILED_TO_HANDLE_DEFAULTS_FILE 13186 +#define ER_DUPLICATE_SYS_VAR 13187 +#define ER_FAILED_TO_INIT_SYS_VAR 13188 +#define ER_SYS_VAR_NOT_FOUND 13189 +#define ER_IB_MSG_1274 13190 +#define ER_IB_MSG_1275 13191 +//#define OBSOLETE_ER_TARGET_TS_UNENCRYPTED 13192 +#define ER_IB_MSG_WAIT_FOR_ENCRYPT_THREAD 13193 +#define ER_IB_MSG_1277 13194 +#define ER_IB_MSG_NO_ENCRYPT_PROGRESS_FOUND 13195 +#define ER_IB_MSG_RESUME_OP_FOR_SPACE 13196 +#define ER_IB_MSG_1280 13197 +#define ER_IB_MSG_1281 13198 +#define ER_IB_MSG_1282 13199 +#define ER_IB_MSG_1283 13200 +#define ER_IB_MSG_1284 13201 +#define ER_CANT_SET_ERROR_SUPPRESSION_LIST_FROM_COMMAND_LINE 13202 +#define ER_INVALID_VALUE_OF_BIND_ADDRESSES 13203 +#define ER_RELAY_LOG_SPACE_LIMIT_DISABLED 13204 +#define ER_GRP_RPL_ERROR_GTID_SET_EXTRACTION 13205 +#define ER_GRP_RPL_MISSING_GRP_RPL_ACTION_COORDINATOR 13206 +#define ER_GRP_RPL_JOIN_WHEN_GROUP_ACTION_RUNNING 13207 +#define ER_GRP_RPL_JOINER_EXIT_WHEN_GROUP_ACTION_RUNNING 13208 +#define ER_GRP_RPL_CHANNEL_THREAD_WHEN_GROUP_ACTION_RUNNING 13209 +#define ER_GRP_RPL_APPOINTED_PRIMARY_NOT_PRESENT 13210 +#define ER_GRP_RPL_ERROR_ON_MESSAGE_SENDING 13211 +#define ER_GRP_RPL_CONFIGURATION_ACTION_ERROR 13212 +#define ER_GRP_RPL_CONFIGURATION_ACTION_LOCAL_TERMINATION 13213 +#define ER_GRP_RPL_CONFIGURATION_ACTION_START 13214 +#define ER_GRP_RPL_CONFIGURATION_ACTION_END 13215 +#define ER_GRP_RPL_CONFIGURATION_ACTION_KILLED_ERROR 13216 +#define ER_GRP_RPL_PRIMARY_ELECTION_PROCESS_ERROR 13217 +#define ER_GRP_RPL_PRIMARY_ELECTION_STOP_ERROR 13218 +#define ER_GRP_RPL_NO_STAGE_SERVICE 13219 +#define ER_GRP_RPL_UDF_REGISTER_ERROR 13220 +#define ER_GRP_RPL_UDF_UNREGISTER_ERROR 13221 +#define ER_GRP_RPL_UDF_REGISTER_SERVICE_ERROR 13222 +#define ER_GRP_RPL_SERVER_UDF_ERROR 13223 +//#define OBSOLETE_ER_CURRENT_PASSWORD_NOT_REQUIRED 13224 +//#define OBSOLETE_ER_INCORRECT_CURRENT_PASSWORD 13225 +//#define OBSOLETE_ER_MISSING_CURRENT_PASSWORD 13226 +#define ER_SERVER_WRONG_VALUE_FOR_VAR 13227 +#define ER_COULD_NOT_CREATE_WINDOWS_REGISTRY_KEY 13228 +#define ER_SERVER_GTID_UNSAFE_CREATE_DROP_TEMP_TABLE_IN_TRX_IN_SBR 13229 +//#define OBSOLETE_ER_SECONDARY_ENGINE 13230 +//#define OBSOLETE_ER_SECONDARY_ENGINE_DDL 13231 +//#define OBSOLETE_ER_NO_SESSION_TEMP 13232 +#define ER_XPLUGIN_FAILED_TO_SWITCH_SECURITY_CTX 13233 +#define ER_RPL_GTID_UNSAFE_ALTER_ADD_COL_WITH_DEFAULT_EXPRESSION 13234 +#define ER_UPGRADE_PARSE_ERROR 13235 +#define ER_DATA_DIRECTORY_UNUSABLE 13236 +#define ER_LDAP_AUTH_USER_GROUP_SEARCH_ROOT_BIND 13237 +#define ER_PLUGIN_INSTALL_ERROR 13238 +#define ER_PLUGIN_UNINSTALL_ERROR 13239 +#define ER_SHARED_TABLESPACE_USED_BY_PARTITIONED_TABLE 13240 +#define ER_UNKNOWN_TABLESPACE_TYPE 13241 +#define ER_WARN_DEPRECATED_UTF8_ALIAS_OPTION 13242 +#define ER_WARN_DEPRECATED_UTF8MB3_CHARSET_OPTION 13243 +#define ER_WARN_DEPRECATED_UTF8MB3_COLLATION_OPTION 13244 +#define ER_SSL_MEMORY_INSTRUMENTATION_INIT_FAILED 13245 +#define ER_IB_MSG_MADV_DONTDUMP_UNSUPPORTED 13246 +#define ER_IB_MSG_MADVISE_FAILED 13247 +//#define OBSOLETE_ER_COLUMN_CHANGE_SIZE 13248 +#define ER_WARN_REMOVED_SQL_MODE 13249 +#define ER_IB_MSG_FAILED_TO_ALLOCATE_WAIT 13250 +//#define OBSOLETE_ER_IB_MSG_NUM_POOLS 13251 +#define ER_IB_MSG_USING_UNDO_SPACE 13252 +#define ER_IB_MSG_FAIL_TO_SAVE_SPACE_STATE 13253 +#define ER_IB_MSG_MAX_UNDO_SPACES_REACHED 13254 +#define ER_IB_MSG_ERROR_OPENING_NEW_UNDO_SPACE 13255 +#define ER_IB_MSG_FAILED_SDI_Z_BUF_ERROR 13256 +#define ER_IB_MSG_FAILED_SDI_Z_MEM_ERROR 13257 +#define ER_IB_MSG_SDI_Z_STREAM_ERROR 13258 +#define ER_IB_MSG_SDI_Z_UNKNOWN_ERROR 13259 +#define ER_IB_MSG_FOUND_WRONG_UNDO_SPACE 13260 +#define ER_IB_MSG_NOT_END_WITH_IBU 13261 +//#define OBSOLETE_ER_IB_MSG_UNDO_TRUNCATE_EMPTY_FILE 13262 +//#define OBSOLETE_ER_IB_MSG_UNDO_INJECT_BEFORE_DD_UPDATE 13263 +//#define OBSOLETE_ER_IB_MSG_UNDO_INJECT_BEFORE_UNDO_LOGGING 13264 +//#define OBSOLETE_ER_IB_MSG_UNDO_INJECT_BEFORE_RSEG 13265 +#define ER_IB_MSG_FAILED_TO_FINISH_TRUNCATE 13266 +#define ER_IB_MSG_DEPRECATED_INNODB_UNDO_TABLESPACES 13267 +#define ER_IB_MSG_WRONG_TABLESPACE_DIR 13268 +#define ER_IB_MSG_LOCK_FREE_HASH_USAGE_STATS 13269 +#define ER_CLONE_DONOR_TRACE 13270 +#define ER_CLONE_PROTOCOL_TRACE 13271 +#define ER_CLONE_CLIENT_TRACE 13272 +#define ER_CLONE_SERVER_TRACE 13273 +#define ER_THREAD_POOL_PFS_TABLES_INIT_FAILED 13274 +#define ER_THREAD_POOL_PFS_TABLES_ADD_FAILED 13275 +#define ER_CANT_SET_DATA_DIR 13276 +#define ER_INNODB_INVALID_INNODB_UNDO_DIRECTORY_LOCATION 13277 +#define ER_SERVER_RPL_ENCRYPTION_FAILED_TO_FETCH_KEY 13278 +#define ER_SERVER_RPL_ENCRYPTION_KEY_NOT_FOUND 13279 +#define ER_SERVER_RPL_ENCRYPTION_KEYRING_INVALID_KEY 13280 +#define ER_SERVER_RPL_ENCRYPTION_HEADER_ERROR 13281 +#define ER_SERVER_RPL_ENCRYPTION_FAILED_TO_ROTATE_LOGS 13282 +#define ER_SERVER_RPL_ENCRYPTION_KEY_EXISTS_UNEXPECTED 13283 +#define ER_SERVER_RPL_ENCRYPTION_FAILED_TO_GENERATE_KEY 13284 +#define ER_SERVER_RPL_ENCRYPTION_FAILED_TO_STORE_KEY 13285 +#define ER_SERVER_RPL_ENCRYPTION_FAILED_TO_REMOVE_KEY 13286 +#define ER_SERVER_RPL_ENCRYPTION_MASTER_KEY_RECOVERY_FAILED 13287 +#define ER_SERVER_RPL_ENCRYPTION_UNABLE_TO_INITIALIZE 13288 +#define ER_SERVER_RPL_ENCRYPTION_UNABLE_TO_ROTATE_MASTER_KEY_AT_STARTUP 13289 +#define ER_SERVER_RPL_ENCRYPTION_IGNORE_ROTATE_MASTER_KEY_AT_STARTUP 13290 +#define ER_INVALID_ADMIN_ADDRESS 13291 +#define ER_SERVER_STARTUP_ADMIN_INTERFACE 13292 +#define ER_CANT_CREATE_ADMIN_THREAD 13293 +#define ER_WARNING_RETAIN_CURRENT_PASSWORD_CLAUSE_VOID 13294 +#define ER_WARNING_DISCARD_OLD_PASSWORD_CLAUSE_VOID 13295 +//#define OBSOLETE_ER_SECOND_PASSWORD_CANNOT_BE_EMPTY 13296 +//#define OBSOLETE_ER_PASSWORD_CANNOT_BE_RETAINED_ON_PLUGIN_CHANGE 13297 +//#define OBSOLETE_ER_CURRENT_PASSWORD_CANNOT_BE_RETAINED 13298 +#define ER_WARNING_AUTHCACHE_INVALID_USER_ATTRIBUTES 13299 +#define ER_MYSQL_NATIVE_PASSWORD_SECOND_PASSWORD_USED_INFORMATION 13300 +#define ER_SHA256_PASSWORD_SECOND_PASSWORD_USED_INFORMATION 13301 +#define ER_CACHING_SHA2_PASSWORD_SECOND_PASSWORD_USED_INFORMATION 13302 +#define ER_GRP_RPL_SEND_TRX_PREPARED_MESSAGE_FAILED 13303 +#define ER_GRP_RPL_RELEASE_COMMIT_AFTER_GROUP_PREPARE_FAILED 13304 +#define ER_GRP_RPL_TRX_ALREADY_EXISTS_ON_TCM_ON_AFTER_CERTIFICATION 13305 +#define ER_GRP_RPL_FAILED_TO_INSERT_TRX_ON_TCM_ON_AFTER_CERTIFICATION 13306 +#define ER_GRP_RPL_REGISTER_TRX_TO_WAIT_FOR_GROUP_PREPARE_FAILED 13307 +#define ER_GRP_RPL_TRX_WAIT_FOR_GROUP_PREPARE_FAILED 13308 +#define ER_GRP_RPL_TRX_DOES_NOT_EXIST_ON_TCM_ON_HANDLE_REMOTE_PREPARE 13309 +#define ER_GRP_RPL_RELEASE_BEGIN_TRX_AFTER_DEPENDENCIES_COMMIT_FAILED 13310 +#define ER_GRP_RPL_REGISTER_TRX_TO_WAIT_FOR_DEPENDENCIES_FAILED 13311 +#define ER_GRP_RPL_WAIT_FOR_DEPENDENCIES_FAILED 13312 +#define ER_GRP_RPL_REGISTER_TRX_TO_WAIT_FOR_SYNC_BEFORE_EXECUTION_FAILED 13313 +#define ER_GRP_RPL_SEND_TRX_SYNC_BEFORE_EXECUTION_FAILED 13314 +#define ER_GRP_RPL_TRX_WAIT_FOR_SYNC_BEFORE_EXECUTION_FAILED 13315 +#define ER_GRP_RPL_RELEASE_BEGIN_TRX_AFTER_WAIT_FOR_SYNC_BEFORE_EXEC 13316 +#define ER_GRP_RPL_TRX_WAIT_FOR_GROUP_GTID_EXECUTED 13317 +//#define OBSOLETE_ER_UNIT_NOT_FOUND 13318 +//#define OBSOLETE_ER_GEOMETRY_IN_UNKNOWN_LENGTH_UNIT 13319 +#define ER_WARN_PROPERTY_STRING_PARSE_FAILED 13320 +#define ER_INVALID_PROPERTY_KEY 13321 +#define ER_GRP_RPL_GTID_SET_EXTRACT_ERROR_DURING_RECOVERY 13322 +#define ER_SERVER_RPL_ENCRYPTION_FAILED_TO_ENCRYPT 13323 +#define ER_CANNOT_GET_SERVER_VERSION_FROM_TABLESPACE_HEADER 13324 +#define ER_CANNOT_SET_SERVER_VERSION_IN_TABLESPACE_HEADER 13325 +#define ER_SERVER_UPGRADE_VERSION_NOT_SUPPORTED 13326 +#define ER_SERVER_UPGRADE_FROM_VERSION 13327 +#define ER_GRP_RPL_ERROR_ON_CERT_DB_INSTALL 13328 +#define ER_GRP_RPL_FORCE_MEMBERS_WHEN_LEAVING 13329 +#define ER_TRG_WRONG_ORDER 13330 +//#define OBSOLETE_ER_SECONDARY_ENGINE_PLUGIN 13331 +#define ER_LDAP_AUTH_GRP_SEARCH_NOT_SPECIAL_HDL 13332 +#define ER_LDAP_AUTH_GRP_USER_OBJECT_HAS_GROUP_INFO 13333 +#define ER_LDAP_AUTH_GRP_INFO_FOUND_IN_MANY_OBJECTS 13334 +#define ER_LDAP_AUTH_GRP_INCORRECT_ATTRIBUTE 13335 +#define ER_LDAP_AUTH_GRP_NULL_ATTRIBUTE_VALUE 13336 +#define ER_LDAP_AUTH_GRP_DN_PARSING_FAILED 13337 +#define ER_LDAP_AUTH_GRP_OBJECT_HAS_USER_INFO 13338 +#define ER_LDAP_AUTH_LDAPS 13339 +#define ER_LDAP_MAPPING_GET_USER_PROXY 13340 +#define ER_LDAP_MAPPING_USER_DONT_BELONG_GROUP 13341 +#define ER_LDAP_MAPPING_INFO 13342 +#define ER_LDAP_MAPPING_EMPTY_MAPPING 13343 +#define ER_LDAP_MAPPING_PROCESS_MAPPING 13344 +#define ER_LDAP_MAPPING_CHECK_DELIMI_QUOTE 13345 +#define ER_LDAP_MAPPING_PROCESS_DELIMITER 13346 +#define ER_LDAP_MAPPING_PROCESS_DELIMITER_EQUAL_NOT_FOUND 13347 +#define ER_LDAP_MAPPING_PROCESS_DELIMITER_TRY_COMMA 13348 +#define ER_LDAP_MAPPING_PROCESS_DELIMITER_COMMA_NOT_FOUND 13349 +#define ER_LDAP_MAPPING_NO_SEPEARATOR_END_OF_GROUP 13350 +#define ER_LDAP_MAPPING_GETTING_NEXT_MAPPING 13351 +#define ER_LDAP_MAPPING_PARSING_CURRENT_STATE 13352 +#define ER_LDAP_MAPPING_PARSING_MAPPING_INFO 13353 +#define ER_LDAP_MAPPING_PARSING_ERROR 13354 +#define ER_LDAP_MAPPING_TRIMMING_SPACES 13355 +#define ER_LDAP_MAPPING_IS_QUOTE 13356 +#define ER_LDAP_MAPPING_NON_DESIRED_STATE 13357 +#define ER_INVALID_NAMED_PIPE_FULL_ACCESS_GROUP 13358 +#define ER_PREPARE_FOR_SECONDARY_ENGINE 13359 +#define ER_SERVER_WARN_DEPRECATED 13360 +#define ER_AUTH_ID_WITH_SYSTEM_USER_PRIV_IN_MANDATORY_ROLES 13361 +#define ER_SERVER_BINLOG_MASTER_KEY_RECOVERY_OUT_OF_COMBINATION 13362 +#define ER_SERVER_BINLOG_MASTER_KEY_ROTATION_FAIL_TO_CLEANUP_AUX_KEY 13363 +//#define OBSOLETE_ER_CANNOT_GRANT_SYSTEM_PRIV_TO_MANDATORY_ROLE 13364 +//#define OBSOLETE_ER_PARTIAL_REVOKE_AND_DB_GRANT_BOTH_EXISTS 13365 +//#define OBSOLETE_ER_DB_ACCESS_DENIED 13366 +//#define OBSOLETE_ER_PARTIAL_REVOKES_EXIST 13367 +#define ER_TURNING_ON_PARTIAL_REVOKES 13368 +#define ER_WARN_PARTIAL_REVOKE_AND_DB_GRANT 13369 +#define ER_WARN_INCORRECT_PRIVILEGE_FOR_DB_RESTRICTIONS 13370 +#define ER_WARN_INVALID_DB_RESTRICTIONS 13371 +#define ER_GRP_RPL_INVALID_COMMUNICATION_PROTOCOL 13372 +#define ER_GRP_RPL_STARTED_AUTO_REJOIN 13373 +#define ER_GRP_RPL_TIMEOUT_RECEIVED_VC_ON_REJOIN 13374 +#define ER_GRP_RPL_FINISHED_AUTO_REJOIN 13375 +#define ER_GRP_RPL_DEFAULT_TABLE_ENCRYPTION_DIFF_FROM_GRP 13376 +#define ER_SERVER_UPGRADE_OFF 13377 +#define ER_SERVER_UPGRADE_SKIP 13378 +#define ER_SERVER_UPGRADE_PENDING 13379 +#define ER_SERVER_UPGRADE_FAILED 13380 +#define ER_SERVER_UPGRADE_STATUS 13381 +#define ER_SERVER_UPGRADE_REPAIR_REQUIRED 13382 +#define ER_SERVER_UPGRADE_REPAIR_STATUS 13383 +#define ER_SERVER_UPGRADE_INFO_FILE 13384 +#define ER_SERVER_UPGRADE_SYS_SCHEMA 13385 +#define ER_SERVER_UPGRADE_MYSQL_TABLES 13386 +#define ER_SERVER_UPGRADE_SYSTEM_TABLES 13387 +#define ER_SERVER_UPGRADE_EMPTY_SYS 13388 +#define ER_SERVER_UPGRADE_NO_SYS_VERSION 13389 +#define ER_SERVER_UPGRADE_SYS_VERSION_EMPTY 13390 +#define ER_SERVER_UPGRADE_SYS_SCHEMA_OUTDATED 13391 +#define ER_SERVER_UPGRADE_SYS_SCHEMA_UP_TO_DATE 13392 +#define ER_SERVER_UPGRADE_SYS_SCHEMA_OBJECT_COUNT 13393 +#define ER_SERVER_UPGRADE_CHECKING_DB 13394 +#define ER_IB_MSG_DDL_LOG_DELETE_BY_ID_TMCT 13395 +#define ER_IB_MSG_POST_RECOVER_DDL_LOG_RECOVER 13396 +#define ER_IB_MSG_POST_RECOVER_POST_TS_ENCRYPT 13397 +#define ER_IB_MSG_DDL_LOG_FAIL_POST_DDL 13398 +#define ER_SERVER_BINLOG_UNSAFE_SYSTEM_FUNCTION 13399 +#define ER_SERVER_UPGRADE_HELP_TABLE_STATUS 13400 +//#define OBSOLETE_ER_GRP_RPL_SRV_GTID_WAIT_ERROR 13401 +//#define OBSOLETE_ER_GRP_DELAYED_VCLE_LOGGING 13402 +//#define OBSOLETE_ER_CANNOT_GRANT_ROLES_TO_ANONYMOUS_USER 13403 +#define ER_BINLOG_UNABLE_TO_ROTATE_GTID_TABLE_READONLY 13404 +#define ER_NETWORK_NAMESPACES_NOT_SUPPORTED 13405 +#define ER_UNKNOWN_NETWORK_NAMESPACE 13406 +#define ER_NETWORK_NAMESPACE_NOT_ALLOWED_FOR_WILDCARD_ADDRESS 13407 +#define ER_SETNS_FAILED 13408 +#define ER_WILDCARD_NOT_ALLOWED_FOR_MULTIADDRESS_BIND 13409 +#define ER_NETWORK_NAMESPACE_FILE_PATH_TOO_LONG 13410 +#define ER_IB_MSG_TOO_LONG_PATH 13411 +#define ER_IB_RECV_FIRST_REC_GROUP_INVALID 13412 +#define ER_DD_UPGRADE_COMPLETED 13413 +//#define OBSOLETE_ER_SSL_SERVER_CERT_VERIFY_FAILED 13414 +#define ER_PERSIST_OPTION_USER_TRUNCATED 13415 +#define ER_PERSIST_OPTION_HOST_TRUNCATED 13416 +#define ER_NET_WAIT_ERROR 13417 +#define ER_IB_MSG_1285 13418 +#define ER_IB_MSG_CLOCK_MONOTONIC_UNSUPPORTED 13419 +#define ER_IB_MSG_CLOCK_GETTIME_FAILED 13420 +#define ER_PLUGIN_NOT_EARLY_DUP 13421 +#define ER_PLUGIN_NO_INSTALL_DUP 13422 +//#define OBSOLETE_ER_WARN_DEPRECATED_SQL_CALC_FOUND_ROWS 13423 +//#define OBSOLETE_ER_WARN_DEPRECATED_FOUND_ROWS 13424 +#define ER_BINLOG_UNSAFE_DEFAULT_EXPRESSION_IN_SUBSTATEMENT 13425 +#define ER_GRP_RPL_MEMBER_VER_READ_COMPATIBLE 13426 +#define ER_LOCK_ORDER_INIT_FAILED 13427 +#define ER_AUDIT_LOG_KEYRING_ID_TIMESTAMP_VALUE_IS_INVALID 13428 +#define ER_AUDIT_LOG_FILE_NAME_TIMESTAMP_VALUE_IS_MISSING_OR_INVALID 13429 +#define ER_AUDIT_LOG_FILE_NAME_DOES_NOT_HAVE_REQUIRED_FORMAT 13430 +#define ER_AUDIT_LOG_FILE_NAME_KEYRING_ID_VALUE_IS_MISSING 13431 +#define ER_AUDIT_LOG_FILE_HAS_BEEN_SUCCESSFULLY_PROCESSED 13432 +#define ER_AUDIT_LOG_COULD_NOT_OPEN_FILE_FOR_READING 13433 +#define ER_AUDIT_LOG_INVALID_FILE_CONTENT 13434 +#define ER_AUDIT_LOG_CANNOT_READ_PASSWORD 13435 +#define ER_AUDIT_LOG_CANNOT_STORE_PASSWORD 13436 +#define ER_AUDIT_LOG_CANNOT_REMOVE_PASSWORD 13437 +#define ER_AUDIT_LOG_PASSWORD_HAS_BEEN_COPIED 13438 +//#define OBSOLETE_ER_AUDIT_LOG_INSUFFICIENT_PRIVILEGE 13439 +//#define OBSOLETE_ER_WRONG_MVI_VALUE 13440 +//#define OBSOLETE_ER_WARN_FUNC_INDEX_NOT_APPLICABLE 13441 +//#define OBSOLETE_ER_EXCEEDED_MV_KEYS_NUM 13442 +//#define OBSOLETE_ER_EXCEEDED_MV_KEYS_SPACE 13443 +//#define OBSOLETE_ER_FUNCTIONAL_INDEX_DATA_IS_TOO_LONG 13444 +//#define OBSOLETE_ER_INVALID_JSON_VALUE_FOR_FUNC_INDEX 13445 +//#define OBSOLETE_ER_JSON_VALUE_OUT_OF_RANGE_FOR_FUNC_INDEX 13446 +#define ER_LDAP_EMPTY_USERDN_PASSWORD 13447 +//#define OBSOLETE_ER_GROUPING_ON_TIMESTAMP_IN_DST 13448 +#define ER_ACL_WRONG_OR_MISSING_ACL_TABLES_LOG 13449 +#define ER_LOCK_ORDER_FAILED_WRITE_FILE 13450 +#define ER_LOCK_ORDER_FAILED_READ_FILE 13451 +#define ER_LOCK_ORDER_MESSAGE 13452 +#define ER_LOCK_ORDER_DEPENDENCIES_SYNTAX 13453 +#define ER_LOCK_ORDER_SCANNER_SYNTAX 13454 +#define ER_DATA_DIRECTORY_UNUSABLE_DELETABLE 13455 +#define ER_IB_MSG_BTREE_LEVEL_LIMIT_EXCEEDED 13456 +#define ER_IB_CLONE_START_STOP 13457 +#define ER_IB_CLONE_OPERATION 13458 +#define ER_IB_CLONE_RESTART 13459 +#define ER_IB_CLONE_USER_DATA 13460 +#define ER_IB_CLONE_NON_INNODB_TABLE 13461 +#define ER_CLONE_SHUTDOWN_TRACE 13462 +#define ER_GRP_RPL_GTID_PURGED_EXTRACT_ERROR 13463 +#define ER_GRP_RPL_CLONE_PROCESS_PREPARE_ERROR 13464 +#define ER_GRP_RPL_CLONE_PROCESS_EXEC_ERROR 13465 +#define ER_GRP_RPL_RECOVERY_EVAL_ERROR 13466 +#define ER_GRP_RPL_NO_POSSIBLE_RECOVERY 13467 +#define ER_GRP_RPL_CANT_KILL_THREAD 13468 +#define ER_GRP_RPL_RECOVERY_STRAT_CLONE_THRESHOLD 13469 +#define ER_GRP_RPL_RECOVERY_STRAT_CLONE_PURGED 13470 +#define ER_GRP_RPL_RECOVERY_STRAT_CHOICE 13471 +#define ER_GRP_RPL_RECOVERY_STRAT_FALLBACK 13472 +#define ER_GRP_RPL_RECOVERY_STRAT_NO_FALLBACK 13473 +#define ER_GRP_RPL_REPLICA_THREAD_ERROR_ON_CLONE 13474 +#define ER_UNKNOWN_TABLE_IN_UPGRADE 13475 +#define ER_IDENT_CAUSES_TOO_LONG_PATH_IN_UPGRADE 13476 +#define ER_XA_CANT_CREATE_MDL_BACKUP 13477 +#define ER_AUDIT_LOG_SUPER_PRIVILEGE_REQUIRED 13478 +#define ER_AUDIT_LOG_UDF_INVALID_ARGUMENT_TYPE 13479 +#define ER_AUDIT_LOG_UDF_INVALID_ARGUMENT_COUNT 13480 +#define ER_AUDIT_LOG_HAS_NOT_BEEN_INSTALLED 13481 +#define ER_AUDIT_LOG_UDF_READ_INVALID_MAX_ARRAY_LENGTH_ARG_TYPE 13482 +#define ER_LOG_CANNOT_WRITE_EXTENDED 13483 +//#define OBSOLETE_ER_UPGRADE_WITH_PARTITIONED_TABLES_REJECTED 13484 +#define ER_KEYRING_AWS_INCORRECT_PROXY 13485 +#define ER_GRP_RPL_SERVER_SET_TO_OFFLINE_MODE_DUE_TO_ERRORS 13486 +#define ER_GRP_RPL_MESSAGE_SERVICE_FATAL_ERROR 13487 +#define ER_WARN_WRONG_COMPRESSION_ALGORITHM_LOG 13488 +#define ER_WARN_WRONG_COMPRESSION_LEVEL_LOG 13489 +#define ER_PROTOCOL_COMPRESSION_RESET_LOG 13490 +#define ER_XPLUGIN_COMPRESSION_ERROR 13491 +#define ER_MYSQLBACKUP_MSG 13492 +#define ER_WARN_UNKNOWN_KEYRING_AWS_REGION 13493 +#define ER_WARN_LOG_PRIVILEGE_CHECKS_USER_DOES_NOT_EXIST 13494 +#define ER_WARN_LOG_PRIVILEGE_CHECKS_USER_CORRUPT 13495 +#define ER_WARN_LOG_PRIVILEGE_CHECKS_USER_NEEDS_RPL_APPLIER_PRIV 13496 +#define ER_OBSOLETE_FILE_PRIVILEGE_FOR_REPLICATION_CHECKS 13497 +#define ER_RPL_REPLICA_SQL_THREAD_STARTING_WITH_PRIVILEGE_CHECKS 13498 +#define ER_AUDIT_LOG_CANNOT_GENERATE_PASSWORD 13499 +#define ER_INIT_FAILED_TO_GENERATE_ROOT_PASSWORD 13500 +#define ER_PLUGIN_LOAD_OPTIONS_IGNORED 13501 +#define ER_WARN_AUTH_ID_WITH_SYSTEM_USER_PRIV_IN_MANDATORY_ROLES 13502 +#define ER_IB_MSG_SKIP_HIDDEN_DIR 13503 +#define ER_WARN_RPL_RECOVERY_NO_ROTATE_EVENT_FROM_SOURCE_EOF 13504 +#define ER_IB_LOB_ROLLBACK_INDEX_LEN 13505 +#define ER_CANT_PROCESS_EXPRESSION_FOR_GENERATED_COLUMN_TO_DD 13506 +#define ER_RPL_REPLICA_QUEUE_EVENT_FAILED_INVALID_NON_ROW_FORMAT 13507 +#define ER_OBSOLETE_REQUIRE_ROW_FORMAT_VIOLATION 13508 +#define ER_LOG_PRIV_CHECKS_REQUIRE_ROW_FORMAT_NOT_SET 13509 +#define ER_RPL_REPLICA_SQL_THREAD_DETECTED_UNEXPECTED_EVENT_SEQUENCE 13510 +#define ER_IB_MSG_UPGRADE_PARTITION_FILE 13511 +#define ER_IB_MSG_DOWNGRADE_PARTITION_FILE 13512 +#define ER_IB_MSG_UPGRADE_PARTITION_FILE_IMPORT 13513 +#define ER_IB_WARN_OPEN_PARTITION_FILE 13514 +#define ER_IB_MSG_FIL_STATE_MOVED_CORRECTED 13515 +#define ER_IB_MSG_FIL_STATE_MOVED_CHANGED_PATH 13516 +#define ER_IB_MSG_FIL_STATE_MOVED_CHANGED_NAME 13517 +#define ER_IB_MSG_FIL_STATE_MOVED_TOO_MANY 13518 +#define ER_GR_ELECTED_PRIMARY_GTID_INFORMATION 13519 +#define ER_SCHEMA_NAME_IN_UPPER_CASE_NOT_ALLOWED 13520 +#define ER_TABLE_NAME_IN_UPPER_CASE_NOT_ALLOWED 13521 +#define ER_SCHEMA_NAME_IN_UPPER_CASE_NOT_ALLOWED_FOR_FK 13522 +#define ER_TABLE_NAME_IN_UPPER_CASE_NOT_ALLOWED_FOR_FK 13523 +#define ER_IB_MSG_DICT_PARTITION_NOT_FOUND 13524 +#define ER_ACCESS_DENIED_FOR_USER_ACCOUNT_BLOCKED_BY_PASSWORD_LOCK 13525 +#define ER_INNODB_OUT_OF_RESOURCES 13526 +//#define OBSOLETE_ER_DD_UPGRADE_FOUND_PREPARED_XA_TRANSACTION 13527 +#define ER_MIGRATE_TABLE_TO_DD_OOM 13528 +#define ER_RPL_RELAY_LOG_RECOVERY_INFO_AFTER_CLONE 13529 +#define ER_IB_MSG_57_UNDO_SPACE_DELETE_FAIL 13530 +#define ER_IB_MSG_DBLWR_1285 13531 +#define ER_IB_MSG_DBLWR_1286 13532 +#define ER_IB_MSG_DBLWR_1287 13533 +#define ER_IB_MSG_DBLWR_1288 13534 +#define ER_IB_MSG_DBLWR_1290 13535 +#define ER_IB_MSG_BAD_DBLWR_FILE_NAME 13536 +//#define OBSOLETE_ER_IB_MSG_DBLWR_1292 13537 +#define ER_IB_MSG_DBLWR_1293 13538 +#define ER_IB_MSG_DBLWR_1294 13539 +#define ER_IB_MSG_DBLWR_1295 13540 +#define ER_IB_MSG_DBLWR_1296 13541 +#define ER_IB_MSG_DBLWR_1297 13542 +#define ER_IB_MSG_DBLWR_1298 13543 +#define ER_IB_MSG_DBLWR_1300 13544 +#define ER_IB_MSG_DBLWR_1301 13545 +#define ER_IB_MSG_DBLWR_1304 13546 +#define ER_IB_MSG_DBLWR_1305 13547 +#define ER_IB_MSG_DBLWR_1306 13548 +#define ER_IB_MSG_DBLWR_1307 13549 +#define ER_IB_MSG_DBLWR_1308 13550 +#define ER_IB_MSG_DBLWR_1309 13551 +#define ER_IB_MSG_DBLWR_1310 13552 +#define ER_IB_MSG_DBLWR_1311 13553 +#define ER_IB_MSG_DBLWR_1312 13554 +#define ER_IB_MSG_DBLWR_1313 13555 +#define ER_IB_MSG_DBLWR_1314 13556 +#define ER_IB_MSG_DBLWR_1315 13557 +#define ER_IB_MSG_DBLWR_1316 13558 +#define ER_IB_MSG_DBLWR_1317 13559 +#define ER_IB_MSG_DBLWR_1318 13560 +#define ER_IB_MSG_DBLWR_LOAD_WRONG_SIZE 13561 +#define ER_IB_MSG_DBLWR_1320 13562 +#define ER_IB_MSG_DBLWR_1321 13563 +#define ER_IB_MSG_DBLWR_OPEN_OR_CREATE_WRONG_SIZE 13564 +#define ER_IB_MSG_DBLWR_1323 13565 +#define ER_IB_MSG_DBLWR_1324 13566 +#define ER_IB_MSG_DBLWR_1325 13567 +#define ER_IB_MSG_DBLWR_1326 13568 +#define ER_IB_MSG_DBLWR_1327 13569 +#define ER_IB_MSG_GTID_FLUSH_AT_SHUTDOWN 13570 +#define ER_IB_MSG_57_STAT_SPACE_DELETE_FAIL 13571 +#define ER_NDBINFO_UPGRADING_SCHEMA 13572 +#define ER_NDBINFO_NOT_UPGRADING_SCHEMA 13573 +#define ER_NDBINFO_UPGRADING_SCHEMA_FAIL 13574 +//#define OBSOLETE_ER_IB_MSG_CREATE_LOG_FILE 13575 +#define ER_IB_MSG_INNODB_START_INITIALIZE 13576 +#define ER_IB_MSG_INNODB_END_INITIALIZE 13577 +#define ER_IB_MSG_PAGE_ARCH_NO_RESET_POINTS 13578 +#define ER_IB_WRN_PAGE_ARCH_FLUSH_DATA 13579 +#define ER_IB_ERR_PAGE_ARCH_INVALID_DOUBLE_WRITE_BUF 13580 +#define ER_IB_ERR_PAGE_ARCH_RECOVERY_FAILED 13581 +#define ER_IB_ERR_PAGE_ARCH_INVALID_FORMAT 13582 +#define ER_INVALID_XPLUGIN_SOCKET_SAME_AS_SERVER 13583 +#define ER_INNODB_UNABLE_TO_ACQUIRE_DD_OBJECT 13584 +//#define OBSOLETE_ER_WARN_LOG_DEPRECATED_PARTITION_PREFIX_KEY 13585 +#define ER_IB_MSG_UNDO_TRUNCATE_TOO_OFTEN 13586 +#define ER_GRP_RPL_IS_STARTING 13587 +#define ER_IB_MSG_INVALID_LOCATION_FOR_TABLESPACE 13588 +#define ER_IB_MSG_INVALID_LOCATION_WRONG_DB 13589 +#define ER_IB_MSG_CANNOT_FIND_DD_UNDO_SPACE 13590 +#define ER_GRP_RPL_RECOVERY_ENDPOINT_FORMAT 13591 +#define ER_GRP_RPL_RECOVERY_ENDPOINT_INVALID 13592 +#define ER_GRP_RPL_RECOVERY_ENDPOINT_INVALID_DONOR_ENDPOINT 13593 +#define ER_GRP_RPL_RECOVERY_ENDPOINT_INTERFACES_IPS 13594 +#define ER_WARN_TLS_CHANNEL_INITIALIZATION_ERROR 13595 +#define ER_XPLUGIN_FAILED_TO_VALIDATE_ADDRESS 13596 +#define ER_XPLUGIN_FAILED_TO_BIND_INTERFACE_ADDRESS 13597 +#define ER_IB_ERR_RECOVERY_REDO_DISABLED 13598 +#define ER_IB_WRN_FAST_SHUTDOWN_REDO_DISABLED 13599 +#define ER_IB_WRN_REDO_DISABLED 13600 +#define ER_IB_WRN_REDO_ENABLED 13601 +#define ER_TLS_CONFIGURED_FOR_CHANNEL 13602 +#define ER_TLS_CONFIGURATION_REUSED 13603 +#define ER_IB_TABLESPACE_PATH_VALIDATION_SKIPPED 13604 +#define ER_IB_CANNOT_UPGRADE_WITH_DISCARDED_TABLESPACES 13605 +#define ER_USERNAME_TRUNKATED 13606 +#define ER_HOSTNAME_TRUNKATED 13607 +#define ER_IB_MSG_TRX_RECOVERY_ROLLBACK_NOT_COMPLETED 13608 +#define ER_AUTHCACHE_ROLE_EDGES_IGNORED_EMPTY_NAME 13609 +#define ER_AUTHCACHE_ROLE_EDGES_UNKNOWN_AUTHORIZATION_ID 13610 +#define ER_AUTHCACHE_DEFAULT_ROLES_IGNORED_EMPTY_NAME 13611 +#define ER_AUTHCACHE_DEFAULT_ROLES_UNKNOWN_AUTHORIZATION_ID 13612 +#define ER_IB_ERR_DDL_LOG_INSERT_FAILURE 13613 +#define ER_IB_LOCK_VALIDATE_LATCH_ORDER_VIOLATION 13614 +#define ER_IB_RELOCK_LATCH_ORDER_VIOLATION 13615 +//#define OBSOLETE_ER_IB_MSG_1352 13616 +//#define OBSOLETE_ER_IB_MSG_1353 13617 +//#define OBSOLETE_ER_IB_MSG_1354 13618 +//#define OBSOLETE_ER_IB_MSG_1355 13619 +//#define OBSOLETE_ER_IB_MSG_1356 13620 +#define ER_IB_MSG_1357 13621 +#define ER_IB_MSG_1358 13622 +#define ER_IB_MSG_1359 13623 +#define ER_IB_FAILED_TO_DELETE_TABLESPACE_FILE 13624 +#define ER_IB_UNABLE_TO_EXPAND_TEMPORARY_TABLESPACE_POOL 13625 +#define ER_IB_TMP_TABLESPACE_CANNOT_CREATE_DIRECTORY 13626 +#define ER_IB_MSG_SCANNING_TEMP_TABLESPACE_DIR 13627 +#define ER_IB_ERR_TEMP_TABLESPACE_DIR_DOESNT_EXIST 13628 +#define ER_IB_ERR_TEMP_TABLESPACE_DIR_EMPTY 13629 +#define ER_IB_ERR_TEMP_TABLESPACE_DIR_CONTAINS_SEMICOLON 13630 +#define ER_IB_ERR_TEMP_TABLESPACE_DIR_SUBDIR_OF_DATADIR 13631 +#define ER_IB_ERR_SCHED_SETAFFNINITY_FAILED 13632 +#define ER_IB_ERR_UNKNOWN_PAGE_FETCH_MODE 13633 +#define ER_IB_ERR_LOG_PARSING_BUFFER_OVERFLOW 13634 +#define ER_IB_ERR_NOT_ENOUGH_MEMORY_FOR_PARSE_BUFFER 13635 +#define ER_IB_MSG_1372 13636 +#define ER_IB_MSG_1373 13637 +#define ER_IB_MSG_1374 13638 +#define ER_IB_MSG_1375 13639 +#define ER_IB_ERR_ZLIB_UNCOMPRESS_FAILED 13640 +#define ER_IB_ERR_ZLIB_BUF_ERROR 13641 +#define ER_IB_ERR_ZLIB_MEM_ERROR 13642 +#define ER_IB_ERR_ZLIB_DATA_ERROR 13643 +#define ER_IB_ERR_ZLIB_UNKNOWN_ERROR 13644 +#define ER_IB_MSG_1381 13645 +#define ER_IB_ERR_INDEX_RECORDS_WRONG_ORDER 13646 +#define ER_IB_ERR_INDEX_DUPLICATE_KEY 13647 +#define ER_IB_ERR_FOUND_N_DUPLICATE_KEYS 13648 +#define ER_IB_ERR_FOUND_N_RECORDS_WRONG_ORDER 13649 +#define ER_IB_ERR_PARALLEL_READ_OOM 13650 +#define ER_IB_MSG_UNDO_MARKED_ACTIVE 13651 +#define ER_IB_MSG_UNDO_ALTERED_ACTIVE 13652 +#define ER_IB_MSG_UNDO_ALTERED_INACTIVE 13653 +#define ER_IB_MSG_UNDO_MARKED_EMPTY 13654 +#define ER_IB_MSG_UNDO_TRUNCATE_DELAY_BY_CLONE 13655 +#define ER_IB_MSG_UNDO_TRUNCATE_DELAY_BY_MDL 13656 +#define ER_IB_MSG_INJECT_CRASH 13657 +#define ER_IB_MSG_INJECT_FAILURE 13658 +#define ER_GRP_RPL_TIMEOUT_RECEIVED_VC_LEAVE_ON_REJOIN 13659 +#define ER_RPL_ASYNC_RECONNECT_FAIL_NO_SOURCE 13660 +#define ER_UDF_REGISTER_SERVICE_ERROR 13661 +#define ER_UDF_REGISTER_ERROR 13662 +#define ER_UDF_UNREGISTER_ERROR 13663 +#define ER_EMPTY_PRIVILEGE_NAME_IGNORED 13664 +#define ER_IB_MSG_INCORRECT_SIZE 13665 +#define ER_TMPDIR_PATH_TOO_LONG 13666 +#define ER_ERROR_LOG_DESTINATION_NOT_A_FILE 13667 +#define ER_NO_ERROR_LOG_PARSER_CONFIGURED 13668 +#define ER_UPGRADE_NONEXISTENT_SCHEMA 13669 +#define ER_IB_MSG_CREATED_UNDO_SPACE 13670 +#define ER_IB_MSG_DROPPED_UNDO_SPACE 13671 +#define ER_IB_MSG_MASTER_KEY_ROTATED 13672 +#define ER_IB_DBLWR_DECOMPRESS_FAILED 13673 +#define ER_IB_DBLWR_DECRYPT_FAILED 13674 +#define ER_IB_DBLWR_KEY_MISSING 13675 +#define ER_INNODB_IO_WRITE_ERROR_RETRYING 13676 +#define ER_INNODB_IO_WRITE_FAILED 13677 +#define ER_LOG_COMPONENT_CANNOT_INIT 13678 +#define ER_RPL_ASYNC_CHANNEL_CANT_CONNECT 13679 +#define ER_RPL_ASYNC_SENDER_ADDED 13680 +#define ER_RPL_ASYNC_SENDER_REMOVED 13681 +#define ER_RPL_ASYNC_CHANNEL_STOPPED_QUORUM_LOST 13682 +#define ER_RPL_ASYNC_CHANNEL_CANT_CONNECT_NO_QUORUM 13683 +//#define OBSOLETE_ER_RPL_ASYNC_EXECUTING_QUERY 13684 +#define ER_RPL_REPLICA_MONITOR_IO_THREAD_EXITING 13685 +#define ER_RPL_ASYNC_MANAGED_NAME_REMOVED 13686 +#define ER_RPL_ASYNC_MANAGED_NAME_ADDED 13687 +#define ER_RPL_ASYNC_READ_FAILOVER_TABLE 13688 +#define ER_RPL_REPLICA_MONITOR_IO_THREAD_RECONNECT_CHANNEL 13689 +#define ER_REPLICA_ANON_TO_GTID_IS_LOCAL_OR_UUID_AND_GTID_MODE_NOT_ON 13690 +#define ER_REPLICA_ANONYMOUS_TO_GTID_UUID_SAME_AS_GROUP_NAME 13691 +#define ER_GRP_RPL_GRP_NAME_IS_SAME_AS_ANONYMOUS_TO_GTID_UUID 13692 +#define ER_WARN_GTID_THRESHOLD_BREACH 13693 +#define ER_HEALTH_INFO 13694 +#define ER_HEALTH_WARNING 13695 +#define ER_HEALTH_ERROR 13696 +#define ER_HEALTH_WARNING_DISK_USAGE_LEVEL_1 13697 +#define ER_HEALTH_WARNING_DISK_USAGE_LEVEL_2 13698 +#define ER_HEALTH_WARNING_DISK_USAGE_LEVEL_3 13699 +#define ER_IB_INNODB_TBSP_OUT_OF_SPACE 13700 +#define ER_GRP_RPL_APPLIER_CHANNEL_STILL_RUNNING 13701 +#define ER_RPL_ASYNC_RECONNECT_GTID_MODE_OFF_CHANNEL 13702 +#define ER_FIREWALL_SERVICES_NOT_ACQUIRED 13703 +#define ER_FIREWALL_UDF_REGISTER_FAILED 13704 +#define ER_FIREWALL_PFS_TABLE_REGISTER_FAILED 13705 +#define ER_IB_MSG_STATS_SAMPLING_TOO_LARGE 13706 +#define ER_AUDIT_LOG_FILE_PRUNE_FAILED 13707 +#define ER_AUDIT_LOG_FILE_AUTO_PRUNED 13708 +#define ER_COMPONENTS_INFRASTRUCTURE_MANIFEST_INIT 13709 +#define ER_COMPONENTS_INFRASTRUCTURE_MANIFEST_DEINIT 13710 +#define ER_WARN_COMPONENTS_INFRASTRUCTURE_MANIFEST_NOT_RO 13711 +#define ER_WARN_NO_KEYRING_COMPONENT_SERVICE_FOUND 13712 +#define ER_NOTE_KEYRING_COMPONENT_INITIALIZED 13713 +#define ER_KEYRING_COMPONENT_NOT_INITIALIZED 13714 +#define ER_KEYRING_COMPONENT_EXCEPTION 13715 +#define ER_KEYRING_COMPONENT_MEMORY_ALLOCATION_ERROR 13716 +#define ER_NOTE_KEYRING_COMPONENT_AES_INVALID_MODE_BLOCK_SIZE 13717 +#define ER_NOTE_KEYRING_COMPONENT_AES_DATA_IDENTIFIER_EMPTY 13718 +#define ER_NOTE_KEYRING_COMPONENT_AES_INVALID_KEY 13719 +#define ER_NOTE_KEYRING_COMPONENT_AES_OPERATION_ERROR 13720 +#define ER_NOTE_KEYRING_COMPONENT_READ_DATA_NOT_FOUND 13721 +#define ER_NOTE_KEYRING_COMPONENT_WRITE_MAXIMUM_DATA_LENGTH 13722 +#define ER_NOTE_KEYRING_COMPONENT_STORE_FAILED 13723 +#define ER_NOTE_KEYRING_COMPONENT_REMOVE_FAILED 13724 +#define ER_NOTE_KEYRING_COMPONENT_GENERATE_FAILED 13725 +#define ER_NOTE_KEYRING_COMPONENT_KEYS_METADATA_ITERATOR_FETCH_FAILED 13726 +#define ER_NOTE_KEYRING_COMPONENT_METADATA_ITERATOR_INVALID_OUT_PARAM 13727 +#define ER_IB_WRN_FAILED_TO_ACQUIRE_SERVICE 13728 +#define ER_IB_WRN_OLD_GEOMETRY_TYPE 13729 +#define ER_NET_WAIT_ERROR2 13730 +#define ER_GRP_RPL_MEMBER_ACTION_TRIGGERED 13731 +#define ER_GRP_RPL_MEMBER_ACTION_FAILURE_IGNORE 13732 +#define ER_GRP_RPL_MEMBER_ACTION_FAILURE 13733 +#define ER_GRP_RPL_MEMBER_ACTION_PARSE_ON_RECEIVE 13734 +#define ER_GRP_RPL_MEMBER_ACTION_UPDATE_ACTIONS 13735 +#define ER_GRP_RPL_MEMBER_ACTION_GET_EXCHANGEABLE_DATA 13736 +#define ER_GRP_RPL_MEMBER_ACTION_DEFAULT_CONFIGURATION 13737 +#define ER_GRP_RPL_MEMBER_ACTION_UNABLE_TO_SET_DEFAULT_CONFIGURATION 13738 +#define ER_GRP_RPL_MEMBER_ACTION_PARSE_ON_MEMBER_JOIN 13739 +#define ER_GRP_RPL_MEMBER_ACTION_UPDATE_ACTIONS_ON_MEMBER_JOIN 13740 +#define ER_GRP_RPL_MEMBER_ACTION_INVALID_ACTIONS_ON_MEMBER_JOIN 13741 +#define ER_GRP_RPL_MEMBER_ACTION_ENABLED 13742 +#define ER_GRP_RPL_MEMBER_ACTION_DISABLED 13743 +#define ER_GRP_RPL_MEMBER_ACTIONS_RESET 13744 +//#define OBSOLETE_ER_DEPRECATED_TLS_VERSION_SESSION 13745 +//#define OBSOLETE_ER_WARN_DEPRECATED_TLS_VERSION_FOR_CHANNEL 13746 +#define ER_FIREWALL_DEPRECATED_USER_PROFILE 13747 +#define ER_GRP_RPL_VIEW_CHANGE_UUID_INVALID 13748 +#define ER_GRP_RPL_VIEW_CHANGE_UUID_SAME_AS_GROUP_NAME 13749 +#define ER_GRP_RPL_GROUP_NAME_SAME_AS_VIEW_CHANGE_UUID 13750 +#define ER_GRP_RPL_VIEW_CHANGE_UUID_IS_SAME_AS_ANONYMOUS_TO_GTID_UUID 13751 +#define ER_GRP_RPL_GRP_VIEW_CHANGE_UUID_IS_INCOMPATIBLE_WITH_SERVER_UUID 13752 +#define ER_GRP_RPL_VIEW_CHANGE_UUID_DIFF_FROM_GRP 13753 +#define ER_WARN_REPLICA_ANONYMOUS_TO_GTID_UUID_SAME_AS_VIEW_CHANGE_UUID 13754 +#define ER_GRP_RPL_FAILED_TO_PARSE_THE_VIEW_CHANGE_UUID 13755 +#define ER_GRP_RPL_FAILED_TO_GENERATE_SIDNO_FOR_VIEW_CHANGE_UUID 13756 +#define ER_GRP_RPL_VIEW_CHANGE_UUID_PARSE_ERROR 13757 +#define ER_GRP_RPL_UPDATE_GRPGTID_VIEW_CHANGE_UUID_EXECUTED_ERROR 13758 +#define ER_GRP_RPL_ADD_VIEW_CHANGE_UUID_TO_GRP_SID_MAP_ERROR 13759 +#define ER_GRP_RPL_DONOR_VIEW_CHANGE_UUID_TRANS_INFO_ERROR 13760 +#define ER_WARN_GRP_RPL_VIEW_CHANGE_UUID_FAIL_GET_VARIABLE 13761 +#define ER_WARN_ADUIT_LOG_MAX_SIZE_AND_PRUNE_SECONDS_LOG 13762 +#define ER_WARN_ADUIT_LOG_MAX_SIZE_CLOSE_TO_ROTATE_ON_SIZE_LOG 13763 +#define ER_PLUGIN_INVALID_TABLE_DEFINITION 13764 +#define ER_AUTH_KERBEROS_LOGGER_GENERIC_MSG 13765 +#define ER_INSTALL_PLUGIN_CONFLICT_LOG 13766 +#define ER_DEPRECATED_PERSISTED_VARIABLE_WITH_ALIAS 13767 +#define ER_LOG_COMPONENT_FLUSH_FAILED 13768 +#define ER_IB_MSG_REENCRYPTED_TABLESPACE_KEY 13769 +#define ER_IB_MSG_REENCRYPTED_GENERAL_TABLESPACE_KEY 13770 +#define ER_IB_ERR_PAGE_ARCH_DBLWR_INIT_FAILED 13771 +#define ER_IB_MSG_RECOVERY_NO_SPACE_IN_REDO_LOG__SKIP_IBUF_MERGES 13772 +#define ER_IB_MSG_RECOVERY_NO_SPACE_IN_REDO_LOG__UNEXPECTED 13773 +#define ER_WARN_AUDIT_LOG_FORMAT_UNIX_TIMESTAMP_ONLY_WHEN_JSON_LOG 13774 +#define ER_PREPARE_FOR_PRIMARY_ENGINE 13775 +#define ER_IB_MSG_PAR_RSEG_INIT_COMPLETE_MSG 13776 +#define ER_IB_MSG_PAR_RSEG_INIT_TIME_MSG 13777 +#define ER_DDL_MSG_1 13778 +#define ER_MTR_MSG_1 13779 +#define ER_GRP_RPL_MYSQL_NETWORK_PROVIDER_CLIENT_ERROR_CONN_ERR 13780 +#define ER_GRP_RPL_MYSQL_NETWORK_PROVIDER_CLIENT_ERROR_COMMAND_ERR 13781 +#define ER_GRP_RPL_FAILOVER_CONF_GET_EXCHANGEABLE_DATA 13782 +#define ER_GRP_RPL_FAILOVER_CONF_DEFAULT_CONFIGURATION 13783 +#define ER_GRP_RPL_FAILOVER_CONF_UNABLE_TO_SET_DEFAULT_CONFIGURATION 13784 +#define ER_GRP_RPL_FAILOVER_CONF_PARSE_ON_MEMBER_JOIN 13785 +#define ER_GRP_RPL_FAILOVER_CONF_CHANNEL_DOES_NOT_EXIST 13786 +#define ER_GRP_RPL_FAILOVER_REGISTER_MESSAGE_LISTENER_SERVICE 13787 +#define ER_GRP_RPL_FAILOVER_PRIMARY_WITHOUT_MAJORITY 13788 +#define ER_GRP_RPL_FAILOVER_PRIMARY_BACK_TO_MAJORITY 13789 +#define ER_RPL_INCREMENTING_MEMBER_ACTION_VERSION 13790 +#define ER_GRP_RPL_REPLICA_THREAD_ERROR_ON_SECONDARY_MEMBER 13791 +#define ER_IB_MSG_CLONE_DDL_NTFN 13792 +#define ER_IB_MSG_CLONE_DDL_APPLY 13793 +#define ER_IB_MSG_CLONE_DDL_INVALIDATE 13794 +#define ER_IB_MSG_UNDO_ENCRYPTION_INFO_LOADED 13795 +#define ER_IB_WRN_ENCRYPTION_INFO_SIZE_MISMATCH 13796 +#define ER_INVALID_AUTHENTICATION_POLICY 13797 +#define ER_AUTHENTICATION_PLUGIN_REGISTRATION_FAILED 13798 +#define ER_AUTHENTICATION_PLUGIN_REGISTRATION_INSUFFICIENT_BUFFER 13799 +#define ER_AUTHENTICATION_PLUGIN_AUTH_DATA_CORRUPT 13800 +#define ER_AUTHENTICATION_PLUGIN_SIGNATURE_CORRUPT 13801 +#define ER_AUTHENTICATION_PLUGIN_VERIFY_SIGNATURE_FAILED 13802 +#define ER_AUTHENTICATION_PLUGIN_OOM 13803 +#define ER_AUTHENTICATION_PLUGIN_LOG 13804 +#define ER_WARN_REPLICA_GTID_ONLY_AND_GTID_MODE_NOT_ON 13805 +#define ER_WARN_L_DISABLE_GTID_ONLY_WITH_SOURCE_AUTO_POS_INVALID_POS 13806 +#define ER_RPL_CANNOT_OPEN_RELAY_LOG 13807 +#define ER_AUTHENTICATION_OCI_PLUGIN_NOT_INITIALIZED 13808 +#define ER_AUTHENTICATION_OCI_PRIVATE_KEY_ERROR 13809 +#define ER_AUTHENTICATION_OCI_DOWNLOAD_PUBLIC_KEY 13810 +#define ER_AUTHENTICATION_OCI_IMDS 13811 +#define ER_AUTHENTICATION_OCI_IAM 13812 +#define ER_AUTHENTICATION_OCI_INVALID_AUTHENTICATION_STRING 13813 +#define ER_AUTHENTICATION_OCI_NO_MATCHING_GROUPS 13814 +#define ER_AUTHENTICATION_OCI_NO_GROUPS_FOUND 13815 +#define ER_AUTHENTICATION_OCI_NONCE 13816 +#define ER_HEALTH_WARNING_MEMORY_USAGE_LEVEL_1 13817 +#define ER_HEALTH_WARNING_MEMORY_USAGE_LEVEL_2 13818 +#define ER_HEALTH_WARNING_MEMORY_USAGE_LEVEL_3 13819 +#define ER_GRP_RPL_SET_SINGLE_CONSENSUS_LEADER 13820 +#define ER_GRP_RPL_ERROR_SET_SINGLE_CONSENSUS_LEADER 13821 +#define ER_GRP_RPL_SET_MULTI_CONSENSUS_LEADER 13822 +#define ER_GRP_RPL_ERROR_SET_MULTI_CONSENSUS_LEADER 13823 +#define ER_GRP_RPL_PAXOS_SINGLE_LEADER_DIFF_FROM_GRP 13824 +#define ER_MFA_USER_ATTRIBUTES_CORRUPT 13825 +#define ER_MFA_PLUGIN_NOT_LOADED 13826 +#define ER_WARN_DEPRECATED_CHARSET_OPTION 13827 +#define ER_WARN_DEPRECATED_COLLATION_OPTION 13828 +#define ER_REGEXP_MISSING_ICU_DATADIR 13829 +#define ER_IB_WARN_MANY_NON_LRU_FILES_OPENED 13830 +#define ER_IB_MSG_TRYING_TO_OPEN_FILE_FOR_LONG_TIME 13831 +#define ER_GLOBAL_CONN_LIMIT 13832 +#define ER_CONN_LIMIT 13833 +#define ER_WARN_AUDIT_LOG_DISABLED 13834 +#define ER_INVALID_TLS_VERSION 13835 +#define ER_RPL_RELAY_LOG_RECOVERY_GTID_ONLY 13836 +#define ER_KEYRING_OKV_STANDBY_SERVER_COUNT_EXCEEDED 13837 +#define ER_WARN_MIGRATION_EMPTY_SOURCE_KEYRING 13838 +#define ER_WARN_CANNOT_PERSIST_SENSITIVE_VARIABLES 13839 +#define ER_CANNOT_INTERPRET_PERSISTED_SENSITIVE_VARIABLES 13840 +#define ER_PERSISTED_VARIABLES_KEYRING_SUPPORT_REQUIRED 13841 +#define ER_PERSISTED_VARIABLES_MASTER_KEY_NOT_FOUND 13842 +#define ER_PERSISTED_VARIABLES_MASTER_KEY_CANNOT_BE_GENERATED 13843 +#define ER_PERSISTED_VARIABLES_ENCRYPTION_FAILED 13844 +#define ER_PERSISTED_VARIABLES_DECRYPTION_FAILED 13845 +#define ER_PERSISTED_VARIABLES_LACK_KEYRING_SUPPORT 13846 +#define ER_MY_MALLOC_USING_JEMALLOC 13847 +#define ER_MY_MALLOC_USING_STD_MALLOC 13848 +#define ER_MY_MALLOC_LOADLIBRARY_FAILED 13849 +#define ER_MY_MALLOC_GETPROCADDRESS_FAILED 13850 +#define ER_ACCOUNT_WITH_EXPIRED_PASSWORD 13851 +#define ER_THREAD_POOL_PLUGIN_STARTED 13852 +#define ER_THREAD_POOL_DEDICATED_LISTENERS_INVALID 13853 +#define ER_IB_DBLWR_BYTES_INFO 13854 +#define ER_IB_RDBLWR_BYTES_INFO 13855 +#define ER_IB_MSG_LOG_FILE_IS_EMPTY 13856 +#define ER_IB_MSG_LOG_FILE_TOO_SMALL 13857 +#define ER_IB_MSG_LOG_FILE_TOO_BIG 13858 +#define ER_IB_MSG_LOG_FILE_HEADER_READ_FAILED 13859 +#define ER_IB_MSG_LOG_INIT_DIR_NOT_EMPTY_WONT_INITIALIZE 13860 +#define ER_IB_MSG_LOG_INIT_DIR_LIST_FAILED 13861 +#define ER_IB_MSG_LOG_INIT_DIR_MISSING_SUBDIR 13862 +#define ER_IB_MSG_LOG_FILES_CREATED_BY_CLONE_AND_READ_ONLY_MODE 13863 +#define ER_IB_MSG_LOG_WRITER_WRITE_FAILED 13864 +#define ER_IB_MSG_LOG_WRITER_WAIT_ON_NEW_LOG_FILE 13865 +#define ER_IB_MSG_RECOVERY_CHECKPOINT_OUTSIDE_LOG_FILE 13866 +#define ER_IB_MSG_LOG_WRITER_ENTERED_EXTRA_MARGIN 13867 +#define ER_IB_MSG_LOG_WRITER_EXITED_EXTRA_MARGIN 13868 +#define ER_IB_MSG_LOG_PARAMS_FILE_SIZE_UNUSED 13869 +#define ER_IB_MSG_LOG_PARAMS_N_FILES_UNUSED 13870 +#define ER_IB_MSG_LOG_UPGRADE_FORCED_RECV 13871 +#define ER_IB_MSG_LOG_UPGRADE_IN_READ_ONLY_MODE 13872 +#define ER_IB_MSG_LOG_UPGRADE_CLONED_DB 13873 +#define ER_IB_MSG_LOG_UPGRADE_UNINITIALIZED_FILES 13874 +#define ER_IB_MSG_LOG_UPGRADE_CORRUPTION__UNEXPECTED 13875 +//#define OBSOLETE_ER_IB_MSG_LOG_UPGRADE_NON_PERSISTED_DD_METADATA 13876 +//#define OBSOLETE_ER_IB_MSG_LOG_UPGRADE_FLUSH_FAILED__UNEXPECTED 13877 +//#define OBSOLETE_ER_IB_MSG_LOG_FILES_RESIZE_ON_START_FAILED__UNEXPECTED 13878 +#define ER_IB_MSG_LOG_FILE_FOREIGN_UUID 13879 +#define ER_IB_MSG_LOG_FILE_INVALID_START_LSN 13880 +#define ER_IB_MSG_LOG_FILE_INVALID_LSN_RANGES 13881 +#define ER_IB_MSG_LOG_FILE_MISSING_FOR_ID 13882 +#define ER_IB_MSG_LOG_CHECKPOINT_FOUND 13883 +#define ER_IB_MSG_LOG_FILES_CAPACITY_CHANGED 13884 +#define ER_IB_MSG_LOG_FILES_RESIZE_REQUESTED 13885 +#define ER_IB_MSG_LOG_FILES_RESIZE_CANCELLED 13886 +#define ER_IB_MSG_LOG_FILES_RESIZE_FINISHED 13887 +#define ER_IB_MSG_LOG_FILES_UPGRADE 13888 +#define ER_IB_MSG_LOG_FILE_MARK_CURRENT_AS_INCOMPLETE 13889 +#define ER_IB_MSG_LOG_FILE_REMOVE_FAILED 13890 +#define ER_IB_MSG_LOG_FILE_RENAME_ON_CREATE_FAILED 13891 +#define ER_IB_MSG_LOG_FILES_CREATED_BY_UNKNOWN_CREATOR 13892 +#define ER_IB_MSG_LOG_FILES_FOUND_MISSING 13893 +#define ER_IB_MSG_LOG_FILE_FORMAT_TOO_NEW 13894 +#define ER_IB_MSG_LOG_FILE_FORMAT_TOO_OLD 13895 +#define ER_IB_MSG_LOG_FILE_DIFFERENT_FORMATS 13896 +#define ER_IB_MSG_LOG_PRE_8_0_30_MISSING_FILE0 13897 +#define ER_IB_MSG_LOG_PFS_ACQUIRE_SERVICES_FAILED 13898 +#define ER_IB_MSG_LOG_PFS_CREATE_TABLES_FAILED 13899 +#define ER_IB_MSG_LOG_FILE_TRUNCATE 13900 +#define ER_IB_MSG_LOG_FILE_UNUSED_RESIZE_FAILED 13901 +#define ER_IB_MSG_LOG_FILE_UNUSED_REMOVE_FAILED 13902 +#define ER_IB_MSG_LOG_FILE_UNUSED_RENAME_FAILED 13903 +#define ER_IB_MSG_LOG_FILE_UNUSED_MARK_AS_IN_USE_FAILED 13904 +#define ER_IB_MSG_LOG_FILE_MARK_AS_UNUSED_FAILED 13905 +#define ER_IB_MSG_LOG_PARAMS_DEDICATED_SERVER_IGNORED 13906 +#define ER_IB_MSG_LOG_PARAMS_LEGACY_USAGE 13907 +#define ER_GRP_RPL_FAILED_TO_LOG_VIEW_CHANGE 13908 +#define ER_BINLOG_CRASH_RECOVERY_MALFORMED_LOG 13909 +#define ER_BINLOG_CRASH_RECOVERY_ERROR_RETURNED_SE 13910 +#define ER_BINLOG_CRASH_RECOVERY_ENGINE_RESULTS 13911 +#define ER_BINLOG_CRASH_RECOVERY_COMMIT_FAILED 13912 +#define ER_BINLOG_CRASH_RECOVERY_ROLLBACK_FAILED 13913 +#define ER_BINLOG_CRASH_RECOVERY_PREPARE_FAILED 13914 +#define ER_COMPONENT_EE_SYS_VAR_REGISTRATION_FAILURE 13915 +#define ER_COMPONENT_EE_SYS_VAR_DEREGISTRATION_FAILURE 13916 +#define ER_COMPONENT_EE_FUNCTION_REGISTRATION_FAILURE 13917 +#define ER_COMPONENT_EE_FUNCTION_DEREGISTRATION_FAILURE 13918 +#define ER_COMPONENT_EE_FUNCTION_INVALID_ARGUMENTS 13919 +#define ER_COMPONENT_EE_FUNCTION_INVALID_ALGORITHM 13920 +#define ER_COMPONENT_EE_FUNCTION_KEY_LENGTH_OUT_OF_RANGE 13921 +#define ER_COMPONENT_EE_FUNCTION_PRIVATE_KEY_GENERATION_FAILURE 13922 +#define ER_COMPONENT_EE_FUNCTION_PUBLIC_KEY_GENERATION_FAILURE 13923 +#define ER_COMPONENT_EE_DATA_LENGTH_OUT_OF_RAGE 13924 +#define ER_COMPONENT_EE_DATA_ENCRYPTION_ERROR 13925 +#define ER_COMPONENT_EE_DATA_DECRYPTION_ERROR 13926 +#define ER_COMPONENT_EE_DATA_SIGN_ERROR 13927 +#define ER_COMPONENT_EE_OPENSSL_ERROR 13928 +#define ER_COMPONENT_EE_INSUFFICIENT_LENGTH 13929 +#define ER_SYSTEMD_NOTIFY_DEBUG 13930 +#define ER_TMP_SESSION_FOR_VAR 13931 +#define ER_BUILD_ID 13932 +#define ER_THREAD_POOL_CANNOT_REGISTER_DYNAMIC_PRIVILEGE 13933 +#define ER_IB_MSG_LOG_WRITER_WAIT_ON_CONSUMER 13934 +#define ER_CONDITIONAL_DEBUG 13935 +#define ER_IB_MSG_PARSE_OLD_REDO_INDEX_VERSION 13936 +//#define OBSOLETE_ER_RES_GRP_FAILED_TO_SWITCH_RESOURCE_GROUP 13937 +//#define OBSOLETE_ER_RES_GRP_SWITCH_FAILED_COULD_NOT_ACQUIRE_GLOBAL_LOCK 13938 +//#define OBSOLETE_ER_RES_GRP_SWITCH_FAILED_COULD_NOT_ACQUIRE_LOCK 13939 +//#define OBSOLETE_ER_RES_GRP_SWITCH_FAILED_UNABLE_TO_APPLY_RES_GRP 13940 +#define ER_IB_MSG_CLEAR_INSTANT_DROP_COLUMN_METADATA 13941 +#define ER_COMPONENT_KEYRING_OCI_OPEN_KEY_FILE 13942 +#define ER_COMPONENT_KEYRING_OCI_CREATE_PRIVATE_KEY 13943 +#define ER_COMPONENT_KEYRING_OCI_READ_KEY_FILE 13944 +#define ER_NOTE_COMPONENT_KEYRING_OCI_MISSING_NAME_OR_TYPE 13945 +#define ER_WARN_COMPONENT_KEYRING_OCI_DUPLICATE_KEY 13946 +#define ER_KEYRING_OCI_PARSE_JSON 13947 +#define ER_KEYRING_OCI_INVALID_JSON 13948 +#define ER_KEYRING_OCI_HTTP_REQUEST 13949 +#define ER_THREAD_POOL_SYSVAR_CHANGE 13950 +#define ER_STACK_BACKTRACE 13951 +#define ER_IB_MSG_BUF_POOL_RESIZE_COMPLETE_CUR_CODE 13952 +#define ER_IB_MSG_BUF_POOL_RESIZE_PROGRESS_UPDATE 13953 +#define ER_IB_MSG_BUF_POOL_RESIZE_CODE_STATUS 13954 +#define ER_THREAD_POOL_QUERY_THREADS_PER_GROUP_INVALID 13955 +#define ER_THREAD_POOL_QUERY_THRS_PER_GRP_EXCEEDS_TXN_THR_LIMIT 13956 +#define ER_IB_MSG_INVALID_PAGE_TYPE 13957 +#define ER_IB_PARALLEL_READER_WORKER_INFO 13958 +#define ER_IB_BULK_LOAD_SUBTREE_INFO 13959 +#define ER_IB_BULK_FLUSHER_INFO 13960 +#define ER_IB_BUFFER_POOL_OVERUSE 13961 +#define ER_IB_BUFFER_POOL_FULL 13962 +#define ER_IB_DUPLICATE_KEY 13963 +#define ER_REPLICATION_INCOMPATIBLE_TABLE_WITH_GIPK 13964 +#define ER_BULK_EXECUTOR_INFO 13965 +#define ER_BULK_LOADER_INFO 13966 +#define ER_BULK_LOADER_FILE_CONTAINS_LESS_LINES_THAN_IGNORE_CLAUSE_LOG 13967 +#define ER_BULK_READER_INFO 13968 +#define ER_BULK_READER_LIBCURL_INIT_FAILED_LOG 13969 +#define ER_BULK_READER_LIBCURL_ERROR_LOG 13970 +#define ER_BULK_READER_SERVER_ERROR_LOG 13971 +#define ER_BULK_READER_COMMUNICATION_ERROR_LOG 13972 +#define ER_BULK_PARSER_MISSING_ENCLOSED_BY_LOG 13973 +#define ER_BULK_PARSER_ROW_BUFFER_MAX_TOTAL_COLS_EXCEEDED_LOG 13974 +#define ER_BULK_PARSER_COPY_BUFFER_SIZE_EXCEEDED_LOG 13975 +#define ER_BULK_PARSER_UNEXPECTED_END_OF_INPUT_LOG 13976 +#define ER_BULK_PARSER_UNEXPECTED_ROW_TERMINATOR_LOG 13977 +#define ER_BULK_PARSER_UNEXPECTED_CHAR_AFTER_ENDING_ENCLOSED_BY_LOG 13978 +#define ER_BULK_PARSER_UNEXPECTED_CHAR_AFTER_NULL_ESCAPE_LOG 13979 +#define ER_BULK_PARSER_UNEXPECTED_CHAR_AFTER_COLUMN_TERMINATOR_LOG 13980 +#define ER_BULK_PARSER_INCOMPLETE_ESCAPE_SEQUENCE_LOG 13981 +#define ER_LOAD_BULK_DATA_WRONG_VALUE_FOR_FIELD_LOG 13982 +#define ER_LOAD_BULK_DATA_WARN_NULL_TO_NOTNULL_LOG 13983 +#define ER_IB_BULK_LOAD_THREAD_FAIL 13984 +#define ER_IB_BULK_LOAD_MERGE_FAIL 13985 +#define ER_IB_LOAD_BULK_CONCURRENCY_REDUCED 13986 +#define ER_PLUGIN_EXCEPTION_OPERATION_FAILED 13987 +#define ER_REQUIRE_TABLE_PRIMARY_KEY_CHECK_GENERATE_WITH_GR_IN_REPO 13988 +#define ER_CHECK_TABLE_INSTANT_VERSION_BIT_SET 13989 +#define ER_GRP_RPL_PAXOS_SINGLE_LEADER_DIFF_FROM_OLD_GRP 13990 +#define ER_IB_WRN_IGNORE_REDO_LOG_CAPACITY 13991 +#define ER_IB_PRIMARY_KEY_IS_INSTANT 13992 +#define ER_THREAD_POOL_IDLE_CONNECTION_CLOSED 13993 +#define ER_IB_HIDDEN_NAME_CONFLICT 13994 +#define ER_IB_DICT_INVALID_COLUMN_POSITION 13995 +#define ER_IB_DICT_LOG_TABLE_INFO 13996 +#define ER_RPL_ASYNC_NEXT_FAILOVER_CHANNEL_SELECTED 13997 +#define ER_RPL_REPLICA_SOURCE_UUID_HAS_NOT_CHANGED 13998 +#define ER_RPL_REPLICA_SOURCE_UUID_HAS_CHANGED_HOST_PORT_UNCHANGED 13999 +#define ER_RPL_REPLICA_SOURCE_UUID_HOST_PORT_HAS_CHANGED 14000 +#define ER_RPL_REPLICA_CONNECTED_TO_SOURCE_RPL_STARTED_FILE_BASED 14001 +#define ER_RPL_REPLICA_CONNECTED_TO_SOURCE_RPL_STARTED_GTID_BASED 14002 +#define ER_IB_INDEX_LOADER_DONE 14003 +#define ER_IB_INDEX_BUILDER_DONE 14004 +#define ER_WARN_DEPRECATED_USER_DEFINED_COLLATIONS_OPTION 14005 +#define ER_IB_INDEX_BUILDER_INIT 14006 +#define ER_IB_SELECT_COUNT_STAR 14007 +#define ER_IB_INDEX_LOG_VERSION_MISMATCH 14008 +#define ER_WARN_COMPONENTS_INFRASTRUCTURE_MANIFEST_MULTIPLE_KEYRING 14009 +#define ER_GRP_RPL_HAS_STARTED 14010 +#define ER_CHECK_TABLE_MIN_REC_FLAG_SET 14011 +#define ER_CHECK_TABLE_MIN_REC_FLAG_NOT_SET 14012 +#define ER_NOTE_COMPONENT_SLOT_REGISTRATION_SUCCESS 14013 +#define ER_NOTE_COMPONENT_SLOT_DEREGISTRATION_SUCCESS 14014 +#define ER_WARN_CANNOT_FREE_COMPONENT_DATA_DEALLOCATION_FAILED 14015 +#define ER_IB_RESURRECT_TRX_INSERT 14016 +#define ER_IB_RESURRECT_TRX_UPDATE 14017 +#define ER_IB_RESURRECT_IDENTIFY_TABLE_TO_LOCK 14018 +#define ER_IB_RESURRECT_ACQUIRE_TABLE_LOCK 14019 +#define ER_IB_RESURRECT_RECORD_PROGRESS 14020 +#define ER_IB_RESURRECT_RECORD_COMPLETE 14021 +#define ER_IB_RESURRECT_TRX_INSERT_COMPLETE 14022 +#define ER_IB_RESURRECT_TRX_UPDATE_COMPLETE 14023 +#define ER_AUTHENTICATION_OCI_INVALID_TOKEN 14024 +#define ER_AUTHENTICATION_OCI_TOKEN_DETAILS_MISMATCH 14025 +#define ER_AUTHENTICATION_OCI_TOKEN_NOT_VERIFIED 14026 +#define ER_AUTHENTICATION_OCI_DOWNLOAD_IDDP_PUBLIC_KEY 14027 +//#define OBSOLETE_ER_AUTHENTICATION_OCI_NO_MATCHING_GROUPS_IN_TOKEN 14028 +#define ER_SYS_VAR_REGISTRATION 14029 +#define ER_SYS_VAR_DEREGISTRATION 14030 +#define ER_UDF_REGISTRATION 14031 +#define ER_UDF_DEREGISTRATION 14032 +#define ER_PRIVILEGE_REGISTRATION 14033 +#define ER_PRIVILEGE_DEREGISTRATION 14034 +#define ER_UDF_EXEC_FAILURE 14035 +#define ER_UDF_EXEC_FAILURE_REASON 14036 +#define ER_COMPONENT_SERVICE_CALL 14037 +#define ER_COMPONENT_SERVICE_CALL_RESULT 14038 +#define ER_COMPONENT_LOCK 14039 +#define ER_COMPONENT_UNLOCK 14040 +#define ER_COMPONENT_MASKING_OTHER_ERROR 14041 +#define ER_COMPONENT_MASKING_ABI 14042 +#define ER_COMPONENT_MASKING_ABI_REASON 14043 +#define ER_COMPONENT_MASKING_RANDOM_CREATE 14044 +#define ER_COMPONENT_MASKING_RANDOM_CREATE_REASON 14045 +#define ER_COMPONENT_MASKING_CANNOT_ACCESS_TABLE 14046 +#define ER_REDUCED_DBLWR_FILE_CORRUPTED 14047 +#define ER_REDUCED_DBLWR_PAGE_FOUND 14048 +#define ER_CONN_INIT_CONNECT_IGNORED_MFA 14049 +#define ER_SECONDARY_ENGINE_DDL_FAILED 14050 +#define ER_THREAD_POOL_CONNECTION_REPORT 14051 +#define ER_WARN_SCHEDULED_TASK_RUN_FAILED 14052 +#define ER_AUDIT_LOG_INVALID_FLUSH_INTERVAL_VALUE 14053 +#define ER_LOG_CANNOT_PURGE_BINLOG_WITH_BACKUP_LOCK 14054 +#define ER_CONVERT_MULTI_VALUE 14055 +#define ER_IB_DDL_CONVERT_HEAP_NOT_FOUND 14056 +#define ER_SERVER_DOWNGRADE_FROM_VERSION 14057 +#define ER_BEYOND_SERVER_DOWNGRADE_THRESHOLD 14058 +#define ER_BEYOND_SERVER_UPGRADE_THRESHOLD 14059 +#define ER_INVALID_SERVER_UPGRADE_NOT_LTS 14060 +#define ER_INVALID_SERVER_DOWNGRADE_NOT_PATCH 14061 +#define ER_FAILED_GET_DD_PROPERTY 14062 +#define ER_FAILED_SET_DD_PROPERTY 14063 +#define ER_SERVER_DOWNGRADE_STATUS 14064 +#define ER_INFORMATION_SCHEMA_VERSION_CHANGE 14065 +#define ER_PERFORMANCE_SCHEMA_VERSION_CHANGE 14066 +#define ER_WARN_DEPRECATED_OR_BLOCKED_CIPHER 14067 +#define ER_IB_MSG_DDL_FAIL_NO_BUILDER 14068 +#define ER_GRP_RPL_MEMBER_INFO_DOES_NOT_EXIST 14069 +#define ER_USAGE_DEPRECATION_COUNTER 14070 +#define ER_WAITING_FOR_NO_CONNECTIONS 14071 +#define ER_WAITING_FOR_NO_THDS 14072 +#define ER_LANGUAGE_COMPONENT_INFO 15000 +#define ER_LANGUAGE_COMPONENT_WARNING 15001 +#define ER_LANGUAGE_COMPONENT_ERROR 15002 +#define ER_IB_BULK_FLUSHER_PUNCH_HOLE 15003 +#define ER_GRP_RPL_CONN_KILLED 15004 +#define ER_WARN_CANT_OPEN_CERTIFICATE 15005 +#define ER_FAILED_TO_VALIDATE_CERTIFICATES_SERVER_EXIT 15006 +#define ER_WARN_CA_CERT_VERIFY_FAILED 15007 +#define ER_WARN_FAILED_TO_SETUP_TLS 15008 +#define ER_TLS_LIBRARY_ERROR_INTERNAL 15009 +#define ER_SERVER_CERT_VERIFY_FAILED 15010 +#define ER_WARN_CERTIFICATE_ERROR_STRING 15011 +#define ER_TELEMETRY_INFO 15012 +#define ER_TELEMETRY_WARNING 15013 +#define ER_TELEMETRY_ERROR 15014 +#define ER_SRV_START 15015 +#define ER_SRV_END 15016 +#define ER_SRV_INIT_START 15017 +#define ER_SRV_INIT_END 15018 +#define ER_PLUGINS_SHUTDOWN_START 15019 +#define ER_PLUGINS_SHUTDOWN_END 15020 +#define ER_COMPONENTS_INFRASTRUCTURE_SHUTDOWN_START 15021 +#define ER_COMPONENTS_INFRASTRUCTURE_SHUTDOWN_END 15022 +#define ER_CONNECTIONS_SHUTDOWN_START 15023 +#define ER_CONNECTIONS_SHUTDOWN_END 15024 +#define ER_THREAD_STILL_ALIVE 15025 +#define ER_NUM_THREADS_STILL_ALIVE 15026 +#define ER_GRP_RPL_MYSQL_NETWORK_PROVIDER_SERVER_ERROR_COMMAND_ERR 15027 +#define ER_COMPONENT_KEYRING_OCI_INVALID_CONFIG_VAR 15028 +#define ER_WARN_OPTION_RESET_AND_IGNORED_DURING_INITIALIZE 15029 +#define ER_FIREWALL_SCHEDULER_REGISTER_FAILED 15030 +#define ER_FIREWALL_INVALID_RELOAD_INTERVAL_VALUE 15031 +#define ER_WARN_DEPRECATED_DYNAMIC_PRIV_FOR_USER 15032 +#define ER_BULK_MULTI_READER_INFO 15033 +#define ER_BULK_MERGE_LOADER_INFO 15034 +#define ER_BULK_SORTING_LOADER_INFO 15035 +#define ER_BULK_WRITER_INFO 15036 +#define ER_BULK_WRITER_LIBCURL_INIT_FAILED_LOG 15037 +#define ER_BULK_WRITER_LIBCURL_ERROR_LOG 15038 +#define ER_IB_WRONG_PAGE_ID 15039 +#define ER_IB_FIXED_PAGE_ID 15040 +#define ER_IB_WRONG_PAGEID_AFTER_SYNC_READ 15041 +#define ER_IB_SYNC_READ_FAILED 15042 +#define ER_START_REPLICA_CHANNEL_INVALID_CONFIGURATION_LOG 15043 +#define ER_GROUP_REPLICATION_CERTIFIER_MESSAGE_LARGE 15044 +#define ER_GROUP_REPLICATION_METADATA_SENDER_IS_REMOTE 15045 +#define ER_GROUP_REPLICATION_METADATA_SENDER 15046 +#define ER_GROUP_REPLICATION_ERROR_COMPRESS_INITIALIZE 15047 +#define ER_GROUP_REPLICATION_COMPRESS_PROCESS 15048 +#define ER_GROUP_REPLICATION_UNKOWN_COMPRESSION_TYPE 15049 +#define ER_GROUP_REPLICATION_COMPRESS_EXCEEDS_MAX_SIZE 15050 +#define ER_GROUP_REPLICATION_COMPRESS_OUT_OF_MEMORY 15051 +#define ER_GROUP_REPLICATION_ERROR_DECOMPRESS_INITIALIZE 15052 +#define ER_GROUP_REPLICATION_DECOMPRESS_EXCEEDS_MAX_SIZE 15053 +#define ER_GROUP_REPLICATION_DECOMPRESS_OUT_OF_MEMORY 15054 +#define ER_GROUP_REPLICATION_DECOMPRESS_TRUNCATED 15055 +#define ER_GROUP_REPLICATION_DECOMPRESS_CORRUPTED 15056 +#define ER_GROUP_REPLICATION_DECOMPRESS_END 15057 +#define ER_GROUP_REPLICATION_DECOMPRESS_PROCESS 15058 +#define ER_GRP_RPL_VCLE_NOT_BEING_LOGGED 15059 +#define ER_GROUP_REPLICATION_METADATA_PROTOBUF_PARSING 15060 +#define ER_GROUP_REPLICATION_PROTOBUF_SERIALIZING_ERROR 15061 +#define ER_GROUP_REPLICATION_ERROR_RECEIVED_WAITING_METADATA 15062 +#define ER_GROUP_REPLICATION_TIMEOUT_ERROR_FETCHING_METADATA 15063 +#define ER_GROUP_REPLICATION_METADATA_PAYLOAD_EMPTY 15064 +#define ER_GROUP_REPLICATION_METADATA_MESSAGE_PAYLOAD_EMPTY 15065 +#define ER_GROUP_REPLICATION_METADATA_READ_GTID_EXECUTED 15066 +#define ER_GROUP_REPLICATION_METADATA_PAYLOAD_DECODING 15067 +#define ER_GROUP_REPLICATION_METADATA_SEND_ERROR 15068 +#define ER_GROUP_REPLICATION_METADATA_SAVE_RECOVERY_COPY 15069 +#define ER_GROUP_REPLICATION_METADATA_CERT_INFO_ERROR_PROCESSING 15070 +#define ER_GROUP_REPLICATION_METADATA_CERT_INFO_PACKET_EMPTY 15071 +#define ER_GROUP_REPLICATION_METADATA_ERROR_ON_SEND_ERROR_MESSAGE 15072 +#define ER_GROUP_REPLICATION_METADATA_SET_IN_RECOVERY_FAILED 15073 +#define ER_GROUP_REPLICATION_CERTIFICATION_MODULE_FAILURE 15074 +#define ER_GROUP_REPLICATION_METADATA_INITIALIZATION_FAILURE 15075 +#define ER_GROUP_REPLICATION_METADATA_MEMORY_ALLOC 15076 +#define ER_GROUP_REPLICATION_RECOVERY_SKIPPED_GTID_PRESENT 15077 +#define ER_GROUP_REPLICATION_RECOVERY_FETCHING_GTID_EXECUTED_SET 15078 +#define ER_GROUP_REPLICATION_RECOVERY_ERROR_ADD_GTID_EXECUTED 15079 +#define ER_GROUP_REPLICATION_RECOVERY_METADATA_SENDER_NOT_FOUND 15080 +#define ER_GROUP_REPLICATION_METADATA_CERT_INFO_PACKET_COUNT_ERROR 15081 +#define ER_GROUP_REPLICATION_METADATA_CERT_INFO_ENCODING_ERROR 15082 +#define ER_GROUP_REPLICATION_METADATA_NO_VALID_DONOR 15083 +#define ER_GROUP_REPLICATION_NO_CERTIFICATION_DONOR_AVAILABLE 15084 +#define ER_GROUP_REPLICATION_RECOVERY_STOPPED_GTID_PRESENT 15085 +#define ER_RPL_ASYNC_CHECK_CONNECTION_ERROR 15086 +#define ER_RPL_ASYNC_MONITOR_IO_THD_FETCH_GROUP_MAJORITY_ERROR 15087 +#define ER_RPL_ASYNC_REPLICA_IO_THD_FETCH_GROUP_MAJORITY_ERROR 15088 +#define ER_RPL_ASYNC_GET_GROUP_MEMBERSHIP_DETAILS_ERROR 15089 +#define ER_IB_ERR_CORRUPT_TABLESPACE_UNRECOVERABLE 15090 +#define ER_IB_BULK_LOAD_STATS_WARN 15091 +#define ER_COMPONENT_MASKING_INVALID_FLUSH_INTERVAL_VALUE 15092 +#define ER_COMPONENT_MASKING_VAR_REGISTRATION_FAILURE 15093 +#define ER_COMPONENT_MASKING_NOTIFICATION_REGISTRATION_FAILURE 15094 +#define ER_GRP_RPL_MSG_DECODING_FAILED 15095 +#define ER_GRP_RPL_APPLIER_ERROR_PACKET_RECEIVED 15096 +#define ER_LANGUAGE_COMPONENT_INSTALL_ERROR 15097 +#define ER_WARN_LANGUAGE_COMPONENT_CANNOT_UNINSTALL 15098 +#define ER_LANGUAGE_COMPONENT_SERVER_ERROR 15099 +#define ER_LANGUAGE_COMPONENT_INTERNAL_ERROR 15100 +#define ER_LANGUAGE_COMPONENT_VM_API_FUNCTION_ERROR 15101 +#define ER_LANGUAGE_COMPONENT_VM_INTERNAL_ERROR 15102 +#define ER_WARN_LANGUAGE_COMPONENT_RESOURCE_LIMIT 15103 +#define ER_BLOCKED_CIPHER 15104 +#define ER_KEYRING_COMPONENT_KEYRING_FILE_NAME_EMPTY 15105 +#define ER_KEYRING_COMPONENT_KEYRING_FILE_READ_FAILED 15106 +#define ER_KEYRING_COMPONENT_KEYRING_FILE_DECRYPT_FAILED 15107 +#define ER_KEYRING_COMPONENT_KEYRING_FILE_INVALID_FORMAT 15108 +#define ER_KEYRING_COMPONENT_KEYRING_FILE_JSON_EXTRACT_FAILED 15109 +#define ER_KEYRING_COMPONENT_KEYRING_FILE_KEY_EXTRACT_FAILED 15110 +#define ER_NOTE_KEYRING_COMPONENT_NOT_INITIALIZED 15111 +#define ER_NOTE_KEYRING_COMPONENT_EMPTY_DATA_ID 15112 +#define ER_NOTE_KEYRING_COMPONENT_KEYS_METADATA_ITERATOR_INIT_FAILED 15113 +#define ER_NOTE_KEYRING_COMPONENT_KEY_READ_ITERATOR_INIT_FAILED 15114 +#define ER_NOTE_KEYRING_COMPONENT_KEY_READ_ITERATOR_FETCH_FAILED 15115 +#define ER_BACKGROUND_HISTOGRAM_UPDATE 15116 +#define ER_IB_MSG_SUBMIT_DETAILED_BUG_REPORT 15117 +#define ER_AUTO_INCREMENT_NOT_SUPPORTED_FOR_FLOAT_DOUBLE 15118 +#define ER_SERVER_DOWNGRADE_SYS_SCHEMA 15119 +#define ER_SERVER_DOWNGRADE_HELP_TABLE_STATUS 15120 +#define ER_KEYRING_MIGRATE_SKIPPED_KEY 15121 +#define ER_KEYRING_MIGRATE_MEMORY_DEALLOCATION_FAILED 15122 +#define ER_LOG_CLIENT_INTERACTION_TIMEOUT 15123 +#define ER_GRP_RPL_PREEMPTIVE_GARBAGE_COLLECTION_DIFF_FROM_GRP 15124 +#define ER_IB_LONG_ROLLBACK_FULL 15125 +#define ER_IB_LONG_ROLLBACK 15126 +#define ER_INVALID_FILE_FORMAT 15127 +#define ER_LOG_SANITIZATION 15128 +#define ER_WARN_LOG_DEPRECATED_NON_STANDARD_KEY 15129 +#define ER_THREAD_POOL_MTL_DISABLE 15130 +#define ER_THREAD_POOL_MTL_REENABLE 15131 +#define ER_LOG_PARTITION_PREFIX_KEY_NOT_SUPPORTED 15132 +#define ER_LDAP_AUTH_INFO_USER_MAP 15133 +#define ER_ACCESS_DENIED_NO_PROXY_GRANT_WITH_NAME 15134 +#define ER_ACCESS_DENIED_NO_PROXY_WITH_NAME 15135 +#define ER_GRP_RPL_RECOVERY_WAIT_APPLIER_BACKLOG_START 15136 +#define ER_GRP_RPL_RECOVERY_WAIT_APPLIER_BACKLOG_FINISH 15137 +#define ER_BULK_READER_ZSTD_ERROR_LOG 15138 +#define ER_SECONDARY_ENGINE_DDL_TRACK_PROGRESS 15139 +#define ER_IB_MSG_INNODB_FLUSH_METHOD 15140 +static const int obsolete_error_count = 614; + +static const int pfs_no_error_stat_count = 2; + +static const int pfs_session_error_stat_count = 1773; + +static const int pfs_global_error_stat_count = 3759; + #endif diff --git a/vendor/mysql/include/openssl/applink.c b/vendor/mysql/include/openssl/applink.c new file mode 100644 index 0000000000..601d016633 --- /dev/null +++ b/vendor/mysql/include/openssl/applink.c @@ -0,0 +1,153 @@ +/* + * Copyright 2004-2023 The OpenSSL Project Authors. All Rights Reserved. + * + * Licensed under the Apache License 2.0 (the "License"). You may not use + * this file except in compliance with the License. You can obtain a copy + * in the file LICENSE in the source distribution or at + * https://www.openssl.org/source/license.html + */ + +#define APPLINK_STDIN 1 +#define APPLINK_STDOUT 2 +#define APPLINK_STDERR 3 +#define APPLINK_FPRINTF 4 +#define APPLINK_FGETS 5 +#define APPLINK_FREAD 6 +#define APPLINK_FWRITE 7 +#define APPLINK_FSETMOD 8 +#define APPLINK_FEOF 9 +#define APPLINK_FCLOSE 10 /* should not be used */ + +#define APPLINK_FOPEN 11 /* solely for completeness */ +#define APPLINK_FSEEK 12 +#define APPLINK_FTELL 13 +#define APPLINK_FFLUSH 14 +#define APPLINK_FERROR 15 +#define APPLINK_CLEARERR 16 +#define APPLINK_FILENO 17 /* to be used with below */ + +#define APPLINK_OPEN 18 /* formally can't be used, as flags can vary */ +#define APPLINK_READ 19 +#define APPLINK_WRITE 20 +#define APPLINK_LSEEK 21 +#define APPLINK_CLOSE 22 +#define APPLINK_MAX 22 /* always same as last macro */ + +#ifndef APPMACROS_ONLY + +/* + * Normally, do not define APPLINK_NO_INCLUDES. Define it if you are using + * symbol preprocessing and do not want the preprocessing to affect the + * following included header files. You will need to put these + * include lines somewhere in the file that is including applink.c. + */ +# ifndef APPLINK_NO_INCLUDES +# include +# include +# include +# endif + +# ifdef __BORLANDC__ + /* _lseek in is a function-like macro so we can't take its address */ +# undef _lseek +# define _lseek lseek +# endif + +static void *app_stdin(void) +{ + return stdin; +} + +static void *app_stdout(void) +{ + return stdout; +} + +static void *app_stderr(void) +{ + return stderr; +} + +static int app_feof(FILE *fp) +{ + return feof(fp); +} + +static int app_ferror(FILE *fp) +{ + return ferror(fp); +} + +static void app_clearerr(FILE *fp) +{ + clearerr(fp); +} + +static int app_fileno(FILE *fp) +{ + return _fileno(fp); +} + +static int app_fsetmod(FILE *fp, char mod) +{ + return _setmode(_fileno(fp), mod == 'b' ? _O_BINARY : _O_TEXT); +} + +#ifdef __cplusplus +extern "C" { +#endif + +__declspec(dllexport) +void ** +# if defined(__BORLANDC__) +/* + * __stdcall appears to be the only way to get the name + * decoration right with Borland C. Otherwise it works + * purely incidentally, as we pass no parameters. + */ +__stdcall +# else +__cdecl +# endif +OPENSSL_Applink(void) +{ + static int once = 1; + static void *OPENSSL_ApplinkTable[APPLINK_MAX + 1] = + { (void *)APPLINK_MAX }; + + if (once) { + OPENSSL_ApplinkTable[APPLINK_STDIN] = app_stdin; + OPENSSL_ApplinkTable[APPLINK_STDOUT] = app_stdout; + OPENSSL_ApplinkTable[APPLINK_STDERR] = app_stderr; + OPENSSL_ApplinkTable[APPLINK_FPRINTF] = fprintf; + OPENSSL_ApplinkTable[APPLINK_FGETS] = fgets; + OPENSSL_ApplinkTable[APPLINK_FREAD] = fread; + OPENSSL_ApplinkTable[APPLINK_FWRITE] = fwrite; + OPENSSL_ApplinkTable[APPLINK_FSETMOD] = app_fsetmod; + OPENSSL_ApplinkTable[APPLINK_FEOF] = app_feof; + OPENSSL_ApplinkTable[APPLINK_FCLOSE] = fclose; + + OPENSSL_ApplinkTable[APPLINK_FOPEN] = fopen; + OPENSSL_ApplinkTable[APPLINK_FSEEK] = fseek; + OPENSSL_ApplinkTable[APPLINK_FTELL] = ftell; + OPENSSL_ApplinkTable[APPLINK_FFLUSH] = fflush; + OPENSSL_ApplinkTable[APPLINK_FERROR] = app_ferror; + OPENSSL_ApplinkTable[APPLINK_CLEARERR] = app_clearerr; + OPENSSL_ApplinkTable[APPLINK_FILENO] = app_fileno; + + OPENSSL_ApplinkTable[APPLINK_OPEN] = _open; + OPENSSL_ApplinkTable[APPLINK_READ] = _read; + OPENSSL_ApplinkTable[APPLINK_WRITE] = _write; + OPENSSL_ApplinkTable[APPLINK_LSEEK] = _lseek; + OPENSSL_ApplinkTable[APPLINK_CLOSE] = _close; + + once = 0; + } + + return OPENSSL_ApplinkTable; +} + +#ifdef __cplusplus +} +#endif +#endif diff --git a/vendor/mysql/include/sql_common.h b/vendor/mysql/include/sql_common.h deleted file mode 100644 index 8d5768c2e0..0000000000 --- a/vendor/mysql/include/sql_common.h +++ /dev/null @@ -1,206 +0,0 @@ -#ifndef SQL_COMMON_INCLUDED -#define SQL_COMMON_INCLUDED - -/* Copyright (c) 2003, 2016, Oracle and/or its affiliates. All rights reserved. - - This program is free software; you can redistribute it and/or modify - it under the terms of the GNU General Public License as published by - the Free Software Foundation; version 2 of the License. - - This program is distributed in the hope that it will be useful, - but WITHOUT ANY WARRANTY; without even the implied warranty of - MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - GNU General Public License for more details. - - You should have received a copy of the GNU General Public License - along with this program; if not, write to the Free Software - Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA */ - -#define SQL_COMMON_INCLUDED - -#ifdef __cplusplus -extern "C" { -#endif - -#include -#include - -extern const char *unknown_sqlstate; -extern const char *cant_connect_sqlstate; -extern const char *not_error_sqlstate; - - -/* - Free all memory allocated in MYSQL handle except the - current options. -*/ -void mysql_close_free(MYSQL *mysql); - -/* - Clear connection options stored in MYSQL handle and - free memory used by them. -*/ -void mysql_close_free_options(MYSQL *mysql); - - -/** - The structure is used to hold the state change information - received from the server. LIST functions are used for manipulation - of the members of the structure. -*/ -typedef struct st_session_track_info_node { - /** head_node->data is a LEX_STRING which contains the variable name. */ - LIST *head_node; - LIST *current_node; -} STATE_INFO_NODE; - -/** - Store the change info received from the server in an array of linked lists - with STATE_INFO_NODE elements (one per state type). -*/ -typedef struct st_session_track_info { - /** Array of STATE_NODE_INFO elements (one per state type). */ - struct st_session_track_info_node info_list[SESSION_TRACK_END + 1]; -} STATE_INFO; - -/* - Access to MYSQL::extension member. - - Note: functions mysql_extension_{init,free}() are defined - in client.c. -*/ - -struct st_mysql_trace_info; - -typedef struct st_mysql_extension { - struct st_mysql_trace_info *trace_data; - struct st_session_track_info state_change; -} MYSQL_EXTENSION; - -/* "Constructor/destructor" for MYSQL extension structure. */ -struct st_mysql_extension* mysql_extension_init(struct st_mysql*); -void mysql_extension_free(struct st_mysql_extension*); - -/* - Note: Allocated extension structure is freed in mysql_close_free() - called by mysql_close(). -*/ -#define MYSQL_EXTENSION_PTR(H) \ -( \ - (struct st_mysql_extension*) \ - ( (H)->extension ? \ - (H)->extension : ((H)->extension= mysql_extension_init(H)) \ - ) \ -) - - -struct st_mysql_options_extention { - char *plugin_dir; - char *default_auth; - char *ssl_crl; /* PEM CRL file */ - char *ssl_crlpath; /* PEM directory of CRL-s? */ - HASH connection_attributes; - char *server_public_key_path; - size_t connection_attributes_length; - my_bool enable_cleartext_plugin; - my_bool unused0; /* Former ssl_enforce */ - char *tls_version; /* TLS version option */ - long ssl_ctx_flags; /* SSL ctx options flag */ - unsigned int ssl_mode; -}; - -typedef struct st_mysql_methods -{ - my_bool (*read_query_result)(MYSQL *mysql); - my_bool (*advanced_command)(MYSQL *mysql, - enum enum_server_command command, - const unsigned char *header, - size_t header_length, - const unsigned char *arg, - size_t arg_length, - my_bool skip_check, - MYSQL_STMT *stmt); - MYSQL_DATA *(*read_rows)(MYSQL *mysql,MYSQL_FIELD *mysql_fields, - unsigned int fields); - MYSQL_RES * (*use_result)(MYSQL *mysql); - void (*fetch_lengths)(unsigned long *to, - MYSQL_ROW column, unsigned int field_count); - void (*flush_use_result)(MYSQL *mysql, my_bool flush_all_results); - int (*read_change_user_result)(MYSQL *mysql); -#if !defined(MYSQL_SERVER) || defined(EMBEDDED_LIBRARY) - MYSQL_FIELD * (*list_fields)(MYSQL *mysql); - my_bool (*read_prepare_result)(MYSQL *mysql, MYSQL_STMT *stmt); - int (*stmt_execute)(MYSQL_STMT *stmt); - int (*read_binary_rows)(MYSQL_STMT *stmt); - int (*unbuffered_fetch)(MYSQL *mysql, char **row); - void (*free_embedded_thd)(MYSQL *mysql); - const char *(*read_statistics)(MYSQL *mysql); - my_bool (*next_result)(MYSQL *mysql); - int (*read_rows_from_cursor)(MYSQL_STMT *stmt); - void (*free_rows)(MYSQL_DATA *cur); -#endif -} MYSQL_METHODS; - -#define simple_command(mysql, command, arg, length, skip_check) \ - ((mysql)->methods \ - ? (*(mysql)->methods->advanced_command)(mysql, command, 0, \ - 0, arg, length, skip_check, NULL) \ - : (set_mysql_error(mysql, CR_COMMANDS_OUT_OF_SYNC, unknown_sqlstate), 1)) -#define stmt_command(mysql, command, arg, length, stmt) \ - ((mysql)->methods \ - ? (*(mysql)->methods->advanced_command)(mysql, command, 0, \ - 0, arg, length, 1, stmt) \ - : (set_mysql_error(mysql, CR_COMMANDS_OUT_OF_SYNC, unknown_sqlstate), 1)) - -extern CHARSET_INFO *default_client_charset_info; -MYSQL_FIELD *unpack_fields(MYSQL *mysql, MYSQL_ROWS *data,MEM_ROOT *alloc, - uint fields, my_bool default_value, - uint server_capabilities); -MYSQL_FIELD * cli_read_metadata_ex(MYSQL *mysql, MEM_ROOT *alloc, - unsigned long field_count, - unsigned int fields); -MYSQL_FIELD * cli_read_metadata(MYSQL *mysql, unsigned long field_count, - unsigned int fields); -void free_rows(MYSQL_DATA *cur); -void free_old_query(MYSQL *mysql); -void end_server(MYSQL *mysql); -my_bool mysql_reconnect(MYSQL *mysql); -void mysql_read_default_options(struct st_mysql_options *options, - const char *filename,const char *group); -my_bool -cli_advanced_command(MYSQL *mysql, enum enum_server_command command, - const unsigned char *header, size_t header_length, - const unsigned char *arg, size_t arg_length, - my_bool skip_check, MYSQL_STMT *stmt); -unsigned long cli_safe_read(MYSQL *mysql, my_bool *is_data_packet); -unsigned long cli_safe_read_with_ok(MYSQL *mysql, my_bool parse_ok, - my_bool *is_data_packet); -void net_clear_error(NET *net); -void set_stmt_errmsg(MYSQL_STMT *stmt, NET *net); -void set_stmt_error(MYSQL_STMT *stmt, int errcode, const char *sqlstate, - const char *err); -void set_mysql_error(MYSQL *mysql, int errcode, const char *sqlstate); -void set_mysql_extended_error(MYSQL *mysql, int errcode, const char *sqlstate, - const char *format, ...); - -/* client side of the pluggable authentication */ -struct st_plugin_vio_info; -void mpvio_info(Vio *vio, struct st_plugin_vio_info *info); -int run_plugin_auth(MYSQL *mysql, char *data, uint data_len, - const char *data_plugin, const char *db); -int mysql_client_plugin_init(); -void mysql_client_plugin_deinit(); - -struct st_mysql_client_plugin; -extern struct st_mysql_client_plugin *mysql_client_builtins[]; -uchar * send_client_connect_attrs(MYSQL *mysql, uchar *buf); -extern my_bool libmysql_cleartext_plugin_enabled; -void read_ok_ex(MYSQL *mysql, unsigned long len); - -#ifdef __cplusplus -} -#endif - -#define protocol_41(A) ((A)->server_capabilities & CLIENT_PROTOCOL_41) - -#endif /* SQL_COMMON_INCLUDED */ diff --git a/vendor/mysql/include/sql_state.h b/vendor/mysql/include/sql_state.h deleted file mode 100644 index 9295cabae1..0000000000 --- a/vendor/mysql/include/sql_state.h +++ /dev/null @@ -1,255 +0,0 @@ -/* Autogenerated file, please don't edit */ - -{ ER_DUP_KEY ,"23000", "" }, -{ ER_OUTOFMEMORY ,"HY001", "S1001" }, -{ ER_OUT_OF_SORTMEMORY ,"HY001", "S1001" }, -{ ER_CON_COUNT_ERROR ,"08004", "" }, -{ ER_BAD_HOST_ERROR ,"08S01", "" }, -{ ER_HANDSHAKE_ERROR ,"08S01", "" }, -{ ER_DBACCESS_DENIED_ERROR ,"42000", "" }, -{ ER_ACCESS_DENIED_ERROR ,"28000", "" }, -{ ER_NO_DB_ERROR ,"3D000", "" }, -{ ER_UNKNOWN_COM_ERROR ,"08S01", "" }, -{ ER_BAD_NULL_ERROR ,"23000", "" }, -{ ER_BAD_DB_ERROR ,"42000", "" }, -{ ER_TABLE_EXISTS_ERROR ,"42S01", "" }, -{ ER_BAD_TABLE_ERROR ,"42S02", "" }, -{ ER_NON_UNIQ_ERROR ,"23000", "" }, -{ ER_SERVER_SHUTDOWN ,"08S01", "" }, -{ ER_BAD_FIELD_ERROR ,"42S22", "S0022" }, -{ ER_WRONG_FIELD_WITH_GROUP ,"42000", "S1009" }, -{ ER_WRONG_GROUP_FIELD ,"42000", "S1009" }, -{ ER_WRONG_SUM_SELECT ,"42000", "S1009" }, -{ ER_WRONG_VALUE_COUNT ,"21S01", "" }, -{ ER_TOO_LONG_IDENT ,"42000", "S1009" }, -{ ER_DUP_FIELDNAME ,"42S21", "S1009" }, -{ ER_DUP_KEYNAME ,"42000", "S1009" }, -{ ER_DUP_ENTRY ,"23000", "S1009" }, -{ ER_WRONG_FIELD_SPEC ,"42000", "S1009" }, -{ ER_PARSE_ERROR ,"42000", "s1009" }, -{ ER_EMPTY_QUERY ,"42000", "" }, -{ ER_NONUNIQ_TABLE ,"42000", "S1009" }, -{ ER_INVALID_DEFAULT ,"42000", "S1009" }, -{ ER_MULTIPLE_PRI_KEY ,"42000", "S1009" }, -{ ER_TOO_MANY_KEYS ,"42000", "S1009" }, -{ ER_TOO_MANY_KEY_PARTS ,"42000", "S1009" }, -{ ER_TOO_LONG_KEY ,"42000", "S1009" }, -{ ER_KEY_COLUMN_DOES_NOT_EXITS ,"42000", "S1009" }, -{ ER_BLOB_USED_AS_KEY ,"42000", "S1009" }, -{ ER_TOO_BIG_FIELDLENGTH ,"42000", "S1009" }, -{ ER_WRONG_AUTO_KEY ,"42000", "S1009" }, -{ ER_FORCING_CLOSE ,"08S01", "" }, -{ ER_IPSOCK_ERROR ,"08S01", "" }, -{ ER_NO_SUCH_INDEX ,"42S12", "S1009" }, -{ ER_WRONG_FIELD_TERMINATORS ,"42000", "S1009" }, -{ ER_BLOBS_AND_NO_TERMINATED ,"42000", "S1009" }, -{ ER_CANT_REMOVE_ALL_FIELDS ,"42000", "" }, -{ ER_CANT_DROP_FIELD_OR_KEY ,"42000", "" }, -{ ER_BLOB_CANT_HAVE_DEFAULT ,"42000", "" }, -{ ER_WRONG_DB_NAME ,"42000", "" }, -{ ER_WRONG_TABLE_NAME ,"42000", "" }, -{ ER_TOO_BIG_SELECT ,"42000", "" }, -{ ER_UNKNOWN_PROCEDURE ,"42000", "" }, -{ ER_WRONG_PARAMCOUNT_TO_PROCEDURE ,"42000", "" }, -{ ER_UNKNOWN_TABLE ,"42S02", "" }, -{ ER_FIELD_SPECIFIED_TWICE ,"42000", "" }, -{ ER_UNSUPPORTED_EXTENSION ,"42000", "" }, -{ ER_TABLE_MUST_HAVE_COLUMNS ,"42000", "" }, -{ ER_UNKNOWN_CHARACTER_SET ,"42000", "" }, -{ ER_TOO_BIG_ROWSIZE ,"42000", "" }, -{ ER_WRONG_OUTER_JOIN ,"42000", "" }, -{ ER_NULL_COLUMN_IN_INDEX ,"42000", "" }, -{ ER_PASSWORD_ANONYMOUS_USER ,"42000", "" }, -{ ER_PASSWORD_NOT_ALLOWED ,"42000", "" }, -{ ER_PASSWORD_NO_MATCH ,"42000", "" }, -{ ER_WRONG_VALUE_COUNT_ON_ROW ,"21S01", "" }, -{ ER_INVALID_USE_OF_NULL ,"22004", "" }, -{ ER_REGEXP_ERROR ,"42000", "" }, -{ ER_MIX_OF_GROUP_FUNC_AND_FIELDS ,"42000", "" }, -{ ER_NONEXISTING_GRANT ,"42000", "" }, -{ ER_TABLEACCESS_DENIED_ERROR ,"42000", "" }, -{ ER_COLUMNACCESS_DENIED_ERROR ,"42000", "" }, -{ ER_ILLEGAL_GRANT_FOR_TABLE ,"42000", "" }, -{ ER_GRANT_WRONG_HOST_OR_USER ,"42000", "" }, -{ ER_NO_SUCH_TABLE ,"42S02", "" }, -{ ER_NONEXISTING_TABLE_GRANT ,"42000", "" }, -{ ER_NOT_ALLOWED_COMMAND ,"42000", "" }, -{ ER_SYNTAX_ERROR ,"42000", "" }, -{ ER_ABORTING_CONNECTION ,"08S01", "" }, -{ ER_NET_PACKET_TOO_LARGE ,"08S01", "" }, -{ ER_NET_READ_ERROR_FROM_PIPE ,"08S01", "" }, -{ ER_NET_FCNTL_ERROR ,"08S01", "" }, -{ ER_NET_PACKETS_OUT_OF_ORDER ,"08S01", "" }, -{ ER_NET_UNCOMPRESS_ERROR ,"08S01", "" }, -{ ER_NET_READ_ERROR ,"08S01", "" }, -{ ER_NET_READ_INTERRUPTED ,"08S01", "" }, -{ ER_NET_ERROR_ON_WRITE ,"08S01", "" }, -{ ER_NET_WRITE_INTERRUPTED ,"08S01", "" }, -{ ER_TOO_LONG_STRING ,"42000", "" }, -{ ER_TABLE_CANT_HANDLE_BLOB ,"42000", "" }, -{ ER_TABLE_CANT_HANDLE_AUTO_INCREMENT ,"42000", "" }, -{ ER_WRONG_COLUMN_NAME ,"42000", "" }, -{ ER_WRONG_KEY_COLUMN ,"42000", "" }, -{ ER_DUP_UNIQUE ,"23000", "" }, -{ ER_BLOB_KEY_WITHOUT_LENGTH ,"42000", "" }, -{ ER_PRIMARY_CANT_HAVE_NULL ,"42000", "" }, -{ ER_TOO_MANY_ROWS ,"42000", "" }, -{ ER_REQUIRES_PRIMARY_KEY ,"42000", "" }, -{ ER_KEY_DOES_NOT_EXITS ,"42000", "S1009" }, -{ ER_CHECK_NO_SUCH_TABLE ,"42000", "" }, -{ ER_CHECK_NOT_IMPLEMENTED ,"42000", "" }, -{ ER_CANT_DO_THIS_DURING_AN_TRANSACTION ,"25000", "" }, -{ ER_NEW_ABORTING_CONNECTION ,"08S01", "" }, -{ ER_MASTER_NET_READ ,"08S01", "" }, -{ ER_MASTER_NET_WRITE ,"08S01", "" }, -{ ER_TOO_MANY_USER_CONNECTIONS ,"42000", "" }, -{ ER_READ_ONLY_TRANSACTION ,"25000", "" }, -{ ER_NO_PERMISSION_TO_CREATE_USER ,"42000", "" }, -{ ER_LOCK_DEADLOCK ,"40001", "" }, -{ ER_NO_REFERENCED_ROW ,"23000", "" }, -{ ER_ROW_IS_REFERENCED ,"23000", "" }, -{ ER_CONNECT_TO_MASTER ,"08S01", "" }, -{ ER_WRONG_NUMBER_OF_COLUMNS_IN_SELECT ,"21000", "" }, -{ ER_USER_LIMIT_REACHED ,"42000", "" }, -{ ER_SPECIFIC_ACCESS_DENIED_ERROR ,"42000", "" }, -{ ER_NO_DEFAULT ,"42000", "" }, -{ ER_WRONG_VALUE_FOR_VAR ,"42000", "" }, -{ ER_WRONG_TYPE_FOR_VAR ,"42000", "" }, -{ ER_CANT_USE_OPTION_HERE ,"42000", "" }, -{ ER_NOT_SUPPORTED_YET ,"42000", "" }, -{ ER_WRONG_FK_DEF ,"42000", "" }, -{ ER_OPERAND_COLUMNS ,"21000", "" }, -{ ER_SUBQUERY_NO_1_ROW ,"21000", "" }, -{ ER_ILLEGAL_REFERENCE ,"42S22", "" }, -{ ER_DERIVED_MUST_HAVE_ALIAS ,"42000", "" }, -{ ER_SELECT_REDUCED ,"01000", "" }, -{ ER_TABLENAME_NOT_ALLOWED_HERE ,"42000", "" }, -{ ER_NOT_SUPPORTED_AUTH_MODE ,"08004", "" }, -{ ER_SPATIAL_CANT_HAVE_NULL ,"42000", "" }, -{ ER_COLLATION_CHARSET_MISMATCH ,"42000", "" }, -{ ER_WARN_TOO_FEW_RECORDS ,"01000", "" }, -{ ER_WARN_TOO_MANY_RECORDS ,"01000", "" }, -{ ER_WARN_NULL_TO_NOTNULL ,"22004", "" }, -{ ER_WARN_DATA_OUT_OF_RANGE ,"22003", "" }, -{ WARN_DATA_TRUNCATED ,"01000", "" }, -{ ER_WRONG_NAME_FOR_INDEX ,"42000", "" }, -{ ER_WRONG_NAME_FOR_CATALOG ,"42000", "" }, -{ ER_UNKNOWN_STORAGE_ENGINE ,"42000", "" }, -{ ER_TRUNCATED_WRONG_VALUE ,"22007", "" }, -{ ER_SP_NO_RECURSIVE_CREATE ,"2F003", "" }, -{ ER_SP_ALREADY_EXISTS ,"42000", "" }, -{ ER_SP_DOES_NOT_EXIST ,"42000", "" }, -{ ER_SP_LILABEL_MISMATCH ,"42000", "" }, -{ ER_SP_LABEL_REDEFINE ,"42000", "" }, -{ ER_SP_LABEL_MISMATCH ,"42000", "" }, -{ ER_SP_UNINIT_VAR ,"01000", "" }, -{ ER_SP_BADSELECT ,"0A000", "" }, -{ ER_SP_BADRETURN ,"42000", "" }, -{ ER_SP_BADSTATEMENT ,"0A000", "" }, -{ ER_UPDATE_LOG_DEPRECATED_IGNORED ,"42000", "" }, -{ ER_UPDATE_LOG_DEPRECATED_TRANSLATED ,"42000", "" }, -{ ER_QUERY_INTERRUPTED ,"70100", "" }, -{ ER_SP_WRONG_NO_OF_ARGS ,"42000", "" }, -{ ER_SP_COND_MISMATCH ,"42000", "" }, -{ ER_SP_NORETURN ,"42000", "" }, -{ ER_SP_NORETURNEND ,"2F005", "" }, -{ ER_SP_BAD_CURSOR_QUERY ,"42000", "" }, -{ ER_SP_BAD_CURSOR_SELECT ,"42000", "" }, -{ ER_SP_CURSOR_MISMATCH ,"42000", "" }, -{ ER_SP_CURSOR_ALREADY_OPEN ,"24000", "" }, -{ ER_SP_CURSOR_NOT_OPEN ,"24000", "" }, -{ ER_SP_UNDECLARED_VAR ,"42000", "" }, -{ ER_SP_FETCH_NO_DATA ,"02000", "" }, -{ ER_SP_DUP_PARAM ,"42000", "" }, -{ ER_SP_DUP_VAR ,"42000", "" }, -{ ER_SP_DUP_COND ,"42000", "" }, -{ ER_SP_DUP_CURS ,"42000", "" }, -{ ER_SP_SUBSELECT_NYI ,"0A000", "" }, -{ ER_STMT_NOT_ALLOWED_IN_SF_OR_TRG ,"0A000", "" }, -{ ER_SP_VARCOND_AFTER_CURSHNDLR ,"42000", "" }, -{ ER_SP_CURSOR_AFTER_HANDLER ,"42000", "" }, -{ ER_SP_CASE_NOT_FOUND ,"20000", "" }, -{ ER_DIVISION_BY_ZERO ,"22012", "" }, -{ ER_ILLEGAL_VALUE_FOR_TYPE ,"22007", "" }, -{ ER_PROCACCESS_DENIED_ERROR ,"42000", "" }, -{ ER_XAER_NOTA ,"XAE04", "" }, -{ ER_XAER_INVAL ,"XAE05", "" }, -{ ER_XAER_RMFAIL ,"XAE07", "" }, -{ ER_XAER_OUTSIDE ,"XAE09", "" }, -{ ER_XAER_RMERR ,"XAE03", "" }, -{ ER_XA_RBROLLBACK ,"XA100", "" }, -{ ER_NONEXISTING_PROC_GRANT ,"42000", "" }, -{ ER_DATA_TOO_LONG ,"22001", "" }, -{ ER_SP_BAD_SQLSTATE ,"42000", "" }, -{ ER_CANT_CREATE_USER_WITH_GRANT ,"42000", "" }, -{ ER_SP_DUP_HANDLER ,"42000", "" }, -{ ER_SP_NOT_VAR_ARG ,"42000", "" }, -{ ER_SP_NO_RETSET ,"0A000", "" }, -{ ER_CANT_CREATE_GEOMETRY_OBJECT ,"22003", "" }, -{ ER_TOO_BIG_SCALE ,"42000", "S1009" }, -{ ER_TOO_BIG_PRECISION ,"42000", "S1009" }, -{ ER_M_BIGGER_THAN_D ,"42000", "S1009" }, -{ ER_TOO_LONG_BODY ,"42000", "S1009" }, -{ ER_TOO_BIG_DISPLAYWIDTH ,"42000", "S1009" }, -{ ER_XAER_DUPID ,"XAE08", "" }, -{ ER_DATETIME_FUNCTION_OVERFLOW ,"22008", "" }, -{ ER_ROW_IS_REFERENCED_2 ,"23000", "" }, -{ ER_NO_REFERENCED_ROW_2 ,"23000", "" }, -{ ER_SP_BAD_VAR_SHADOW ,"42000", "" }, -{ ER_SP_WRONG_NAME ,"42000", "" }, -{ ER_SP_NO_AGGREGATE ,"42000", "" }, -{ ER_MAX_PREPARED_STMT_COUNT_REACHED ,"42000", "" }, -{ ER_NON_GROUPING_FIELD_USED ,"42000", "" }, -{ ER_FOREIGN_DUPLICATE_KEY_OLD_UNUSED ,"23000", "S1009" }, -{ ER_CANT_CHANGE_TX_CHARACTERISTICS ,"25001", "" }, -{ ER_WRONG_PARAMCOUNT_TO_NATIVE_FCT ,"42000", "" }, -{ ER_WRONG_PARAMETERS_TO_NATIVE_FCT ,"42000", "" }, -{ ER_WRONG_PARAMETERS_TO_STORED_FCT ,"42000", "" }, -{ ER_DUP_ENTRY_WITH_KEY_NAME ,"23000", "S1009" }, -{ ER_XA_RBTIMEOUT ,"XA106", "" }, -{ ER_XA_RBDEADLOCK ,"XA102", "" }, -{ ER_FUNC_INEXISTENT_NAME_COLLISION ,"42000", "" }, -{ ER_DUP_SIGNAL_SET ,"42000", "" }, -{ ER_SIGNAL_WARN ,"01000", "" }, -{ ER_SIGNAL_NOT_FOUND ,"02000", "" }, -{ ER_SIGNAL_EXCEPTION ,"HY000", "" }, -{ ER_RESIGNAL_WITHOUT_ACTIVE_HANDLER ,"0K000", "" }, -{ ER_SPATIAL_MUST_HAVE_GEOM_COL ,"42000", "" }, -{ ER_DATA_OUT_OF_RANGE ,"22003", "" }, -{ ER_ACCESS_DENIED_NO_PASSWORD_ERROR ,"28000", "" }, -{ ER_TRUNCATE_ILLEGAL_FK ,"42000", "" }, -{ ER_DA_INVALID_CONDITION_NUMBER ,"35000", "" }, -{ ER_FOREIGN_DUPLICATE_KEY_WITH_CHILD_INFO,"23000", "S1009" }, -{ ER_FOREIGN_DUPLICATE_KEY_WITHOUT_CHILD_INFO,"23000", "S1009" }, -{ ER_CANT_EXECUTE_IN_READ_ONLY_TRANSACTION,"25006", "" }, -{ ER_ALTER_OPERATION_NOT_SUPPORTED ,"0A000", "" }, -{ ER_ALTER_OPERATION_NOT_SUPPORTED_REASON ,"0A000", "" }, -{ ER_DUP_UNKNOWN_IN_INDEX ,"23000", "" }, -{ ER_ACCESS_DENIED_CHANGE_USER_ERROR ,"28000", "" }, -{ ER_GET_STACKED_DA_WITHOUT_ACTIVE_HANDLER,"0Z002", "" }, -{ ER_INVALID_ARGUMENT_FOR_LOGARITHM ,"2201E", "" }, -{ ER_GIS_INVALID_DATA ,"22023", "" }, -{ ER_USER_LOCK_WRONG_NAME ,"42000", "" }, -{ ER_ILLEGAL_USER_VAR ,"42000", "S1009" }, -{ ER_NET_OK_PACKET_TOO_LARGE ,"08S01", "" }, -{ ER_WRONG_TABLESPACE_NAME ,"42000", "" }, -{ ER_LOCKING_SERVICE_WRONG_NAME ,"42000", "" }, -{ ER_INVALID_JSON_TEXT ,"22032", "" }, -{ ER_INVALID_JSON_TEXT_IN_PARAM ,"22032", "" }, -{ ER_INVALID_JSON_PATH ,"42000", "" }, -{ ER_INVALID_JSON_CHARSET ,"22032", "" }, -{ ER_INVALID_JSON_CHARSET_IN_FUNCTION ,"22032", "" }, -{ ER_INVALID_TYPE_FOR_JSON ,"22032", "" }, -{ ER_INVALID_CAST_TO_JSON ,"22032", "" }, -{ ER_INVALID_JSON_PATH_CHARSET ,"42000", "" }, -{ ER_INVALID_JSON_PATH_WILDCARD ,"42000", "" }, -{ ER_JSON_VALUE_TOO_BIG ,"22032", "" }, -{ ER_JSON_KEY_TOO_BIG ,"22032", "" }, -{ ER_JSON_USED_AS_KEY ,"42000", "" }, -{ ER_JSON_VACUOUS_PATH ,"42000", "" }, -{ ER_JSON_BAD_ONE_OR_ALL_ARG ,"42000", "" }, -{ ER_NUMERIC_JSON_VALUE_OUT_OF_RANGE ,"22003", "" }, -{ ER_INVALID_JSON_VALUE_FOR_CAST ,"22018", "" }, -{ ER_JSON_DOCUMENT_TOO_DEEP ,"22032", "" }, -{ ER_JSON_DOCUMENT_NULL_KEY ,"22032", "" }, -{ ER_INVALID_JSON_PATH_ARRAY_CELL ,"42000", "" }, diff --git a/vendor/mysql/include/sslopt-case.h b/vendor/mysql/include/sslopt-case.h deleted file mode 100644 index 745196a9c9..0000000000 --- a/vendor/mysql/include/sslopt-case.h +++ /dev/null @@ -1,63 +0,0 @@ -/* Copyright (c) 2000, 2016, Oracle and/or its affiliates. All rights reserved. - - This program is free software; you can redistribute it and/or modify - it under the terms of the GNU General Public License as published by - the Free Software Foundation; version 2 of the License. - - This program is distributed in the hope that it will be useful, - but WITHOUT ANY WARRANTY; without even the implied warranty of - MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - GNU General Public License for more details. - - You should have received a copy of the GNU General Public License - along with this program; if not, write to the Free Software - Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA */ - -#if defined(HAVE_OPENSSL) && !defined(EMBEDDED_LIBRARY) - -#ifndef MYSQL_CLIENT -#error This header is supposed to be used only in the client -#endif - - case OPT_SSL_MODE: - opt_ssl_mode= find_type_or_exit(argument, &ssl_mode_typelib, - opt->name); - ssl_mode_set_explicitly= TRUE; - break; - case OPT_SSL_SSL: - CLIENT_WARN_DEPRECATED("--ssl", "--ssl-mode"); - if (!opt_use_ssl_arg) - opt_ssl_mode= SSL_MODE_DISABLED; - else if (opt_ssl_mode < SSL_MODE_REQUIRED) - opt_ssl_mode= SSL_MODE_REQUIRED; - break; - case OPT_SSL_VERIFY_SERVER_CERT: - CLIENT_WARN_DEPRECATED("--ssl-verify-server-cert", - "--ssl-mode=VERIFY_IDENTITY"); - if (!opt_ssl_verify_server_cert_arg) - { - if (opt_ssl_mode >= SSL_MODE_VERIFY_IDENTITY) - opt_ssl_mode= SSL_MODE_VERIFY_CA; - } - else - opt_ssl_mode= SSL_MODE_VERIFY_IDENTITY; - break; - case OPT_SSL_CA: - case OPT_SSL_CAPATH: - /* Don't change ssl-mode if set explicitly. */ - if (!ssl_mode_set_explicitly) - opt_ssl_mode= SSL_MODE_VERIFY_CA; - break; - case OPT_SSL_KEY: - case OPT_SSL_CERT: - case OPT_SSL_CIPHER: - case OPT_SSL_CRL: - case OPT_SSL_CRLPATH: - case OPT_TLS_VERSION: -#ifdef HAVE_YASSL - /* crl has no effect in yaSSL. */ - opt_ssl_crl= NULL; - opt_ssl_crlpath= NULL; -#endif /* HAVE_YASSL */ - break; -#endif /* HAVE_OPENSSL */ diff --git a/vendor/mysql/include/sslopt-longopts.h b/vendor/mysql/include/sslopt-longopts.h deleted file mode 100644 index 416cea7376..0000000000 --- a/vendor/mysql/include/sslopt-longopts.h +++ /dev/null @@ -1,67 +0,0 @@ -/* Copyright (c) 2000, 2016, Oracle and/or its affiliates. All rights reserved. - - This program is free software; you can redistribute it and/or modify - it under the terms of the GNU General Public License as published by - the Free Software Foundation; version 2 of the License. - - This program is distributed in the hope that it will be useful, - but WITHOUT ANY WARRANTY; without even the implied warranty of - MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - GNU General Public License for more details. - - You should have received a copy of the GNU General Public License - along with this program; if not, write to the Free Software - Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA */ - -#if defined(HAVE_OPENSSL) && !defined(EMBEDDED_LIBRARY) -#ifdef MYSQL_CLIENT - {"ssl-mode", OPT_SSL_MODE, - "SSL connection mode.", - 0, 0, 0, GET_STR, REQUIRED_ARG, 0, 0, 0, 0, 0, 0}, - {"ssl", OPT_SSL_SSL, - "Deprecated. Use --ssl-mode instead.", - &opt_use_ssl_arg, &opt_use_ssl_arg, 0, GET_BOOL, OPT_ARG, 1, 0, 0, 0, 0, 0}, - {"ssl-verify-server-cert", OPT_SSL_VERIFY_SERVER_CERT, - "Deprecated. Use --ssl-mode=VERIFY_IDENTITY instead.", - &opt_ssl_verify_server_cert_arg, &opt_ssl_verify_server_cert_arg, - 0, GET_BOOL, OPT_ARG, 0, 0, 0, 0, 0, 0}, -#else - {"ssl", OPT_SSL_SSL, - "If set to ON, this option enforces that SSL is established before client " - "attempts to authenticate to the server. To disable client SSL capabilities " - "use --ssl=OFF.", - &opt_use_ssl, &opt_use_ssl, 0, GET_BOOL, OPT_ARG, 1, 0, 0, 0, 0, 0}, -#endif - {"ssl-ca", OPT_SSL_CA, - "CA file in PEM format.", - &opt_ssl_ca, &opt_ssl_ca, 0, GET_STR, REQUIRED_ARG, - 0, 0, 0, 0, 0, 0}, - {"ssl-capath", OPT_SSL_CAPATH, - "CA directory.", - &opt_ssl_capath, &opt_ssl_capath, 0, GET_STR, REQUIRED_ARG, - 0, 0, 0, 0, 0, 0}, - {"ssl-cert", OPT_SSL_CERT, "X509 cert in PEM format.", - &opt_ssl_cert, &opt_ssl_cert, 0, GET_STR, REQUIRED_ARG, - 0, 0, 0, 0, 0, 0}, - {"ssl-cipher", OPT_SSL_CIPHER, "SSL cipher to use.", - &opt_ssl_cipher, &opt_ssl_cipher, 0, GET_STR, REQUIRED_ARG, - 0, 0, 0, 0, 0, 0}, - {"ssl-key", OPT_SSL_KEY, "X509 key in PEM format.", - &opt_ssl_key, &opt_ssl_key, 0, GET_STR, REQUIRED_ARG, - 0, 0, 0, 0, 0, 0}, - {"ssl-crl", OPT_SSL_CRL, "Certificate revocation list.", - &opt_ssl_crl, &opt_ssl_crl, 0, GET_STR, REQUIRED_ARG, - 0, 0, 0, 0, 0, 0}, - {"ssl-crlpath", OPT_SSL_CRLPATH, - "Certificate revocation list path.", - &opt_ssl_crlpath, &opt_ssl_crlpath, 0, GET_STR, REQUIRED_ARG, - 0, 0, 0, 0, 0, 0}, - {"tls-version", OPT_TLS_VERSION, "TLS version to use, " -#ifndef HAVE_YASSL - "permitted values are: TLSv1, TLSv1.1, TLSv1.2", -#else - "permitted values are: TLSv1, TLSv1.1", -#endif - &opt_tls_version, &opt_tls_version, 0, GET_STR, REQUIRED_ARG, - 0, 0, 0, 0, 0, 0}, -#endif /* HAVE_OPENSSL */ diff --git a/vendor/mysql/include/sslopt-vars.h b/vendor/mysql/include/sslopt-vars.h deleted file mode 100644 index aef761668a..0000000000 --- a/vendor/mysql/include/sslopt-vars.h +++ /dev/null @@ -1,75 +0,0 @@ -/* Copyright (c) 2000, 2016, Oracle and/or its affiliates. All rights reserved. - - This program is free software; you can redistribute it and/or modify - it under the terms of the GNU General Public License as published by - the Free Software Foundation; version 2 of the License. - - This program is distributed in the hope that it will be useful, - but WITHOUT ANY WARRANTY; without even the implied warranty of - MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - GNU General Public License for more details. - - You should have received a copy of the GNU General Public License - along with this program; if not, write to the Free Software - Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA */ - -#ifndef SSLOPT_VARS_INCLUDED -#define SSLOPT_VARS_INCLUDED - -#if defined(HAVE_OPENSSL) && !defined(EMBEDDED_LIBRARY) - -#ifndef MYSQL_CLIENT -#error This header is supposed to be used only in the client -#endif - -const char *ssl_mode_names_lib[] = - {"DISABLED", "PREFERRED", "REQUIRED", "VERIFY_CA", "VERIFY_IDENTITY", - NullS }; -TYPELIB ssl_mode_typelib = {array_elements(ssl_mode_names_lib) - 1, "", - ssl_mode_names_lib, NULL}; - -static uint opt_ssl_mode = SSL_MODE_PREFERRED; -static char *opt_ssl_ca = 0; -static char *opt_ssl_capath = 0; -static char *opt_ssl_cert = 0; -static char *opt_ssl_cipher = 0; -static char *opt_ssl_key = 0; -static char *opt_ssl_crl = 0; -static char *opt_ssl_crlpath = 0; -static char *opt_tls_version = 0; -static my_bool ssl_mode_set_explicitly= FALSE; -static my_bool opt_use_ssl_arg= TRUE; -static my_bool opt_ssl_verify_server_cert_arg= FALSE; - -static void set_client_ssl_options(MYSQL *mysql) -{ - /* - Print a warning if explicitly defined combination of --ssl-mode other than - VERIFY_CA or VERIFY_IDENTITY with explicit --ssl-ca or --ssl-capath values. - */ - if (ssl_mode_set_explicitly && - opt_ssl_mode < SSL_MODE_VERIFY_CA && - (opt_ssl_ca || opt_ssl_capath)) - { - printf("WARNING: no verification of server certificate will be done. " - "Use --ssl-mode=VERIFY_CA or VERIFY_IDENTITY.\n"); - } - - /* Set SSL parameters: key, cert, ca, capath, cipher, clr, clrpath. */ - if (opt_ssl_mode >= SSL_MODE_VERIFY_CA) - mysql_ssl_set(mysql, opt_ssl_key, opt_ssl_cert, opt_ssl_ca, - opt_ssl_capath, opt_ssl_cipher); - else - mysql_ssl_set(mysql, opt_ssl_key, opt_ssl_cert, NULL, - NULL, opt_ssl_cipher); - mysql_options(mysql, MYSQL_OPT_SSL_CRL, opt_ssl_crl); - mysql_options(mysql, MYSQL_OPT_SSL_CRLPATH, opt_ssl_crlpath); - mysql_options(mysql, MYSQL_OPT_TLS_VERSION, opt_tls_version); - mysql_options(mysql, MYSQL_OPT_SSL_MODE, &opt_ssl_mode); -} - -#define SSL_SET_OPTIONS(mysql) set_client_ssl_options(mysql); -#else -#define SSL_SET_OPTIONS(mysql) do { } while(0) -#endif -#endif /* SSLOPT_VARS_INCLUDED */ diff --git a/vendor/mysql/include/thr_cond.h b/vendor/mysql/include/thr_cond.h deleted file mode 100644 index 95df29d11c..0000000000 --- a/vendor/mysql/include/thr_cond.h +++ /dev/null @@ -1,201 +0,0 @@ -#ifndef THR_COND_INCLUDED -#define THR_COND_INCLUDED - -/* Copyright (c) 2014, 2016, Oracle and/or its affiliates. All rights reserved. - - This program is free software; you can redistribute it and/or modify - it under the terms of the GNU General Public License as published by - the Free Software Foundation; version 2 of the License. - - This program is distributed in the hope that it will be useful, - but WITHOUT ANY WARRANTY; without even the implied warranty of - MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - GNU General Public License for more details. - - You should have received a copy of the GNU General Public License - along with this program; if not, write to the Free Software - Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA */ - -/** - MySQL condition variable implementation. - - There are three "layers": - 1) native_cond_*() - Functions that map directly down to OS primitives. - Windows - ConditionVariable - Other OSes - pthread - 2) my_cond_*() - Functions that use SAFE_MUTEX (default for debug). - Otherwise native_cond_*() is used. - 3) mysql_cond*() - Functions that include Performance Schema instrumentation. - See include/mysql/psi/mysql_thread.h -*/ - -#include "my_thread.h" -#include "thr_mutex.h" - -C_MODE_START - -#ifdef _WIN32 -typedef CONDITION_VARIABLE native_cond_t; -#else -typedef pthread_cond_t native_cond_t; -#endif - -#ifdef _WIN32 -/** - Convert abstime to milliseconds -*/ - -static DWORD get_milliseconds(const struct timespec *abstime) -{ -#ifndef HAVE_STRUCT_TIMESPEC - long long millis; - union ft64 now; - - if (abstime == NULL) - return INFINITE; - - GetSystemTimeAsFileTime(&now.ft); - - /* - Calculate time left to abstime - - subtract start time from current time(values are in 100ns units) - - convert to millisec by dividing with 10000 - */ - millis= (abstime->tv.i64 - now.i64) / 10000; - - /* Don't allow the timeout to be negative */ - if (millis < 0) - return 0; - - /* - Make sure the calculated timeout does not exceed original timeout - value which could cause "wait for ever" if system time changes - */ - if (millis > abstime->max_timeout_msec) - millis= abstime->max_timeout_msec; - - if (millis > UINT_MAX) - millis= UINT_MAX; - - return (DWORD)millis; -#else - /* - Convert timespec to millis and subtract current time. - my_getsystime() returns time in 100 ns units. - */ - ulonglong future= abstime->tv_sec * 1000 + abstime->tv_nsec / 1000000; - ulonglong now= my_getsystime() / 10000; - /* Don't allow the timeout to be negative. */ - if (future < now) - return 0; - return (DWORD)(future - now); -#endif -} -#endif /* _WIN32 */ - -static inline int native_cond_init(native_cond_t *cond) -{ -#ifdef _WIN32 - InitializeConditionVariable(cond); - return 0; -#else - /* pthread_condattr_t is not used in MySQL */ - return pthread_cond_init(cond, NULL); -#endif -} - -static inline int native_cond_destroy(native_cond_t *cond) -{ -#ifdef _WIN32 - return 0; /* no destroy function */ -#else - return pthread_cond_destroy(cond); -#endif -} - -static inline int native_cond_timedwait(native_cond_t *cond, - native_mutex_t *mutex, - const struct timespec *abstime) -{ -#ifdef _WIN32 - DWORD timeout= get_milliseconds(abstime); - if (!SleepConditionVariableCS(cond, mutex, timeout)) - return ETIMEDOUT; - return 0; -#else - return pthread_cond_timedwait(cond, mutex, abstime); -#endif -} - -static inline int native_cond_wait(native_cond_t *cond, native_mutex_t *mutex) -{ -#ifdef _WIN32 - if (!SleepConditionVariableCS(cond, mutex, INFINITE)) - return ETIMEDOUT; - return 0; -#else - return pthread_cond_wait(cond, mutex); -#endif -} - -static inline int native_cond_signal(native_cond_t *cond) -{ -#ifdef _WIN32 - WakeConditionVariable(cond); - return 0; -#else - return pthread_cond_signal(cond); -#endif -} - -static inline int native_cond_broadcast(native_cond_t *cond) -{ -#ifdef _WIN32 - WakeAllConditionVariable(cond); - return 0; -#else - return pthread_cond_broadcast(cond); -#endif -} - -#ifdef SAFE_MUTEX -int safe_cond_wait(native_cond_t *cond, my_mutex_t *mp, - const char *file, uint line); -int safe_cond_timedwait(native_cond_t *cond, my_mutex_t *mp, - const struct timespec *abstime, - const char *file, uint line); -#endif - -static inline int my_cond_timedwait(native_cond_t *cond, my_mutex_t *mp, - const struct timespec *abstime -#ifdef SAFE_MUTEX - , const char *file, uint line -#endif - ) -{ -#ifdef SAFE_MUTEX - return safe_cond_timedwait(cond, mp, abstime, file, line); -#else - return native_cond_timedwait(cond, mp, abstime); -#endif -} - -static inline int my_cond_wait(native_cond_t *cond, my_mutex_t *mp -#ifdef SAFE_MUTEX - , const char *file, uint line -#endif - ) -{ -#ifdef SAFE_MUTEX - return safe_cond_wait(cond, mp, file, line); -#else - return native_cond_wait(cond, mp); -#endif -} - -C_MODE_END - -#endif /* THR_COND_INCLUDED */ diff --git a/vendor/mysql/include/thr_mutex.h b/vendor/mysql/include/thr_mutex.h deleted file mode 100644 index 1b8c9d879d..0000000000 --- a/vendor/mysql/include/thr_mutex.h +++ /dev/null @@ -1,227 +0,0 @@ -#ifndef THR_MUTEX_INCLUDED -#define THR_MUTEX_INCLUDED - -/* Copyright (c) 2014, 2015, Oracle and/or its affiliates. All rights reserved. - - This program is free software; you can redistribute it and/or modify - it under the terms of the GNU General Public License as published by - the Free Software Foundation; version 2 of the License. - - This program is distributed in the hope that it will be useful, - but WITHOUT ANY WARRANTY; without even the implied warranty of - MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - GNU General Public License for more details. - - You should have received a copy of the GNU General Public License - along with this program; if not, write to the Free Software - Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA */ - -/** - MySQL mutex implementation. - - There are three "layers": - 1) native_mutex_*() - Functions that map directly down to OS primitives. - Windows - CriticalSection - Other OSes - pthread - 2) my_mutex_*() - Functions that implement SAFE_MUTEX (default for debug), - Otherwise native_mutex_*() is used. - 3) mysql_mutex_*() - Functions that include Performance Schema instrumentation. - See include/mysql/psi/mysql_thread.h -*/ - -#include -#include "my_thread.h" - -C_MODE_START - -#ifdef _WIN32 -typedef CRITICAL_SECTION native_mutex_t; -typedef int native_mutexattr_t; -#else -typedef pthread_mutex_t native_mutex_t; -typedef pthread_mutexattr_t native_mutexattr_t; -#endif - -/* Define mutex types, see my_thr_init.c */ -#define MY_MUTEX_INIT_SLOW NULL - -/* Can be set in /usr/include/pthread.h */ -#ifdef PTHREAD_ADAPTIVE_MUTEX_INITIALIZER_NP -extern native_mutexattr_t my_fast_mutexattr; -#define MY_MUTEX_INIT_FAST &my_fast_mutexattr -#else -#define MY_MUTEX_INIT_FAST NULL -#endif - -/* Can be set in /usr/include/pthread.h */ -#ifdef PTHREAD_ERRORCHECK_MUTEX_INITIALIZER_NP -extern native_mutexattr_t my_errorcheck_mutexattr; -#define MY_MUTEX_INIT_ERRCHK &my_errorcheck_mutexattr -#else -#define MY_MUTEX_INIT_ERRCHK NULL -#endif - -static inline int native_mutex_init(native_mutex_t *mutex, - const native_mutexattr_t *attr) -{ -#ifdef _WIN32 - InitializeCriticalSection(mutex); - return 0; -#else - return pthread_mutex_init(mutex, attr); -#endif -} - -static inline int native_mutex_lock(native_mutex_t *mutex) -{ -#ifdef _WIN32 - EnterCriticalSection(mutex); - return 0; -#else - return pthread_mutex_lock(mutex); -#endif -} - -static inline int native_mutex_trylock(native_mutex_t *mutex) -{ -#ifdef _WIN32 - if (TryEnterCriticalSection(mutex)) - { - /* Don't allow recursive lock */ - if (mutex->RecursionCount > 1){ - LeaveCriticalSection(mutex); - return EBUSY; - } - return 0; - } - return EBUSY; -#else - return pthread_mutex_trylock(mutex); -#endif -} - -static inline int native_mutex_unlock(native_mutex_t *mutex) -{ -#ifdef _WIN32 - LeaveCriticalSection(mutex); - return 0; -#else - return pthread_mutex_unlock(mutex); -#endif -} - -static inline int native_mutex_destroy(native_mutex_t *mutex) -{ -#ifdef _WIN32 - DeleteCriticalSection(mutex); - return 0; -#else - return pthread_mutex_destroy(mutex); -#endif -} - - -#ifdef SAFE_MUTEX -/* safe_mutex adds checking to mutex for easier debugging */ -typedef struct st_safe_mutex_t -{ - native_mutex_t global, mutex; - const char *file; - uint line, count; - my_thread_t thread; -} my_mutex_t; - -void safe_mutex_global_init(); -int safe_mutex_init(my_mutex_t *mp, const native_mutexattr_t *attr, - const char *file, uint line); -int safe_mutex_lock(my_mutex_t *mp, my_bool try_lock, const char *file, uint line); -int safe_mutex_unlock(my_mutex_t *mp, const char *file, uint line); -int safe_mutex_destroy(my_mutex_t *mp, const char *file, uint line); - -static inline void safe_mutex_assert_owner(const my_mutex_t *mp) -{ - DBUG_ASSERT(mp->count > 0 && - my_thread_equal(my_thread_self(), mp->thread)); -} - -static inline void safe_mutex_assert_not_owner(const my_mutex_t *mp) -{ - DBUG_ASSERT(!mp->count || - !my_thread_equal(my_thread_self(), mp->thread)); -} - -#else -typedef native_mutex_t my_mutex_t; -#endif - -static inline int my_mutex_init(my_mutex_t *mp, const native_mutexattr_t *attr -#ifdef SAFE_MUTEX - , const char *file, uint line -#endif - ) -{ -#ifdef SAFE_MUTEX - return safe_mutex_init(mp, attr, file, line); -#else - return native_mutex_init(mp, attr); -#endif -} - -static inline int my_mutex_lock(my_mutex_t *mp -#ifdef SAFE_MUTEX - , const char *file, uint line -#endif - ) -{ -#ifdef SAFE_MUTEX - return safe_mutex_lock(mp, FALSE, file, line); -#else - return native_mutex_lock(mp); -#endif -} - -static inline int my_mutex_trylock(my_mutex_t *mp -#ifdef SAFE_MUTEX - , const char *file, uint line -#endif - ) -{ -#ifdef SAFE_MUTEX - return safe_mutex_lock(mp, TRUE, file, line); -#else - return native_mutex_trylock(mp); -#endif -} - -static inline int my_mutex_unlock(my_mutex_t *mp -#ifdef SAFE_MUTEX - , const char *file, uint line -#endif - ) -{ -#ifdef SAFE_MUTEX - return safe_mutex_unlock(mp, file, line); -#else - return native_mutex_unlock(mp); -#endif -} - -static inline int my_mutex_destroy(my_mutex_t *mp -#ifdef SAFE_MUTEX - , const char *file, uint line -#endif - ) -{ -#ifdef SAFE_MUTEX - return safe_mutex_destroy(mp, file, line); -#else - return native_mutex_destroy(mp); -#endif -} - -C_MODE_END - -#endif /* THR_MUTEX_INCLUDED */ diff --git a/vendor/mysql/include/thr_rwlock.h b/vendor/mysql/include/thr_rwlock.h deleted file mode 100644 index c177e29e3d..0000000000 --- a/vendor/mysql/include/thr_rwlock.h +++ /dev/null @@ -1,214 +0,0 @@ -#ifndef THR_RWLOCK_INCLUDED -#define THR_RWLOCK_INCLUDED - -/* Copyright (c) 2014, 2016, Oracle and/or its affiliates. All rights reserved. - - This program is free software; you can redistribute it and/or modify - it under the terms of the GNU General Public License as published by - the Free Software Foundation; version 2 of the License. - - This program is distributed in the hope that it will be useful, - but WITHOUT ANY WARRANTY; without even the implied warranty of - MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - GNU General Public License for more details. - - You should have received a copy of the GNU General Public License - along with this program; if not, write to the Free Software - Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA */ - -/** - MySQL rwlock implementation. - - There are two "layers": - 1) native_rw_*() - Functions that map directly down to OS primitives. - Windows - SRWLock - Other OSes - pthread - 2) mysql_rw*() - Functions that include Performance Schema instrumentation. - See include/mysql/psi/mysql_thread.h - - This file also includes rw_pr_*(), which implements a special - version of rwlocks that prefer readers. The P_S version of these - are mysql_prlock_*() - see include/mysql/psi/mysql_thread.h -*/ - -#include "my_global.h" -#include "my_thread.h" -#include "thr_cond.h" - -C_MODE_START - -#ifdef _WIN32 -typedef struct st_my_rw_lock_t -{ - SRWLOCK srwlock; /* native reader writer lock */ - BOOL have_exclusive_srwlock; /* used for unlock */ -} native_rw_lock_t; -#else -typedef pthread_rwlock_t native_rw_lock_t; -#endif - -static inline int native_rw_init(native_rw_lock_t *rwp) -{ -#ifdef _WIN32 - InitializeSRWLock(&rwp->srwlock); - rwp->have_exclusive_srwlock = FALSE; - return 0; -#else - /* pthread_rwlockattr_t is not used in MySQL */ - return pthread_rwlock_init(rwp, NULL); -#endif -} - -static inline int native_rw_destroy(native_rw_lock_t *rwp) -{ -#ifdef _WIN32 - return 0; /* no destroy function */ -#else - return pthread_rwlock_destroy(rwp); -#endif -} - -static inline int native_rw_rdlock(native_rw_lock_t *rwp) -{ -#ifdef _WIN32 - AcquireSRWLockShared(&rwp->srwlock); - return 0; -#else - return pthread_rwlock_rdlock(rwp); -#endif -} - -static inline int native_rw_tryrdlock(native_rw_lock_t *rwp) -{ -#ifdef _WIN32 - if (!TryAcquireSRWLockShared(&rwp->srwlock)) - return EBUSY; - return 0; -#else - return pthread_rwlock_tryrdlock(rwp); -#endif -} - -static inline int native_rw_wrlock(native_rw_lock_t *rwp) -{ -#ifdef _WIN32 - AcquireSRWLockExclusive(&rwp->srwlock); - rwp->have_exclusive_srwlock= TRUE; - return 0; -#else - return pthread_rwlock_wrlock(rwp); -#endif -} - -static inline int native_rw_trywrlock(native_rw_lock_t *rwp) -{ -#ifdef _WIN32 - if (!TryAcquireSRWLockExclusive(&rwp->srwlock)) - return EBUSY; - rwp->have_exclusive_srwlock= TRUE; - return 0; -#else - return pthread_rwlock_trywrlock(rwp); -#endif -} - -static inline int native_rw_unlock(native_rw_lock_t *rwp) -{ -#ifdef _WIN32 - if (rwp->have_exclusive_srwlock) - { - rwp->have_exclusive_srwlock= FALSE; - ReleaseSRWLockExclusive(&rwp->srwlock); - } - else - ReleaseSRWLockShared(&rwp->srwlock); - return 0; -#else - return pthread_rwlock_unlock(rwp); -#endif -} - - -/** - Portable implementation of special type of read-write locks. - - These locks have two properties which are unusual for rwlocks: - 1) They "prefer readers" in the sense that they do not allow - situations in which rwlock is rd-locked and there is a - pending rd-lock which is blocked (e.g. due to pending - request for wr-lock). - This is a stronger guarantee than one which is provided for - PTHREAD_RWLOCK_PREFER_READER_NP rwlocks in Linux. - MDL subsystem deadlock detector relies on this property for - its correctness. - 2) They are optimized for uncontended wr-lock/unlock case. - This is scenario in which they are most oftenly used - within MDL subsystem. Optimizing for it gives significant - performance improvements in some of tests involving many - connections. - - Another important requirement imposed on this type of rwlock - by the MDL subsystem is that it should be OK to destroy rwlock - object which is in unlocked state even though some threads might - have not yet fully left unlock operation for it (of course there - is an external guarantee that no thread will try to lock rwlock - which is destroyed). - Putting it another way the unlock operation should not access - rwlock data after changing its state to unlocked. - - TODO/FIXME: We should consider alleviating this requirement as - it blocks us from doing certain performance optimizations. -*/ - -typedef struct st_rw_pr_lock_t { - /** - Lock which protects the structure. - Also held for the duration of wr-lock. - */ - native_mutex_t lock; - /** - Condition variable which is used to wake-up - writers waiting for readers to go away. - */ - native_cond_t no_active_readers; - /** Number of active readers. */ - uint active_readers; - /** Number of writers waiting for readers to go away. */ - uint writers_waiting_readers; - /** Indicates whether there is an active writer. */ - my_bool active_writer; -#ifdef SAFE_MUTEX - /** Thread holding wr-lock (for debug purposes only). */ - my_thread_t writer_thread; -#endif -} rw_pr_lock_t; - -extern int rw_pr_init(rw_pr_lock_t *); -extern int rw_pr_rdlock(rw_pr_lock_t *); -extern int rw_pr_wrlock(rw_pr_lock_t *); -extern int rw_pr_unlock(rw_pr_lock_t *); -extern int rw_pr_destroy(rw_pr_lock_t *); - -static inline void -rw_pr_lock_assert_write_owner(const rw_pr_lock_t *rwlock MY_ATTRIBUTE((unused))) -{ -#ifdef SAFE_MUTEX - DBUG_ASSERT(rwlock->active_writer && - my_thread_equal(my_thread_self(), rwlock->writer_thread)); -#endif -} - -static inline void -rw_pr_lock_assert_not_write_owner(const rw_pr_lock_t *rwlock MY_ATTRIBUTE((unused))) -{ -#ifdef SAFE_MUTEX - DBUG_ASSERT(!rwlock->active_writer || - !my_thread_equal(my_thread_self(), rwlock->writer_thread)); -#endif -} - -C_MODE_END - -#endif /* THR_RWLOCK_INCLUDED */ diff --git a/vendor/mysql/include/typelib.h b/vendor/mysql/include/typelib.h deleted file mode 100644 index 919dd69d6d..0000000000 --- a/vendor/mysql/include/typelib.h +++ /dev/null @@ -1,54 +0,0 @@ -/* Copyright (c) 2000, 2011, Oracle and/or its affiliates. All rights reserved. - - This program is free software; you can redistribute it and/or modify - it under the terms of the GNU General Public License as published by - the Free Software Foundation; version 2 of the License. - - This program is distributed in the hope that it will be useful, - but WITHOUT ANY WARRANTY; without even the implied warranty of - MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - GNU General Public License for more details. - - You should have received a copy of the GNU General Public License - along with this program; if not, write to the Free Software - Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA */ - - -#ifndef _typelib_h -#define _typelib_h - -#include "my_alloc.h" - -typedef struct st_typelib { /* Different types saved here */ - unsigned int count; /* How many types */ - const char *name; /* Name of typelib */ - const char **type_names; - unsigned int *type_lengths; -} TYPELIB; - -extern my_ulonglong find_typeset(char *x, TYPELIB *typelib,int *error_position); -extern int find_type_or_exit(const char *x, TYPELIB *typelib, - const char *option); -#define FIND_TYPE_BASIC 0 -/** makes @c find_type() require the whole name, no prefix */ -#define FIND_TYPE_NO_PREFIX (1 << 0) -/** always implicitely on, so unused, but old code may pass it */ -#define FIND_TYPE_NO_OVERWRITE (1 << 1) -/** makes @c find_type() accept a number */ -#define FIND_TYPE_ALLOW_NUMBER (1 << 2) -/** makes @c find_type() treat ',' as terminator */ -#define FIND_TYPE_COMMA_TERM (1 << 3) - -extern int find_type(const char *x, const TYPELIB *typelib, unsigned int flags); -extern void make_type(char *to,unsigned int nr,TYPELIB *typelib); -extern const char *get_type(TYPELIB *typelib,unsigned int nr); -extern TYPELIB *copy_typelib(MEM_ROOT *root, TYPELIB *from); - -extern TYPELIB sql_protocol_typelib; - -my_ulonglong find_set_from_flags(const TYPELIB *lib, unsigned int default_name, - my_ulonglong cur_set, my_ulonglong default_set, - const char *str, unsigned int length, - char **err_pos, unsigned int *err_len); - -#endif /* _typelib_h */ diff --git a/vendor/mysql/lib/.gitignore b/vendor/mysql/lib/.gitignore deleted file mode 100644 index 84eea69f75..0000000000 --- a/vendor/mysql/lib/.gitignore +++ /dev/null @@ -1,2 +0,0 @@ -!*.dll -!*.lib diff --git a/vendor/mysql/lib/arm/libmysql.dll b/vendor/mysql/lib/arm/libmysql.dll deleted file mode 100644 index 1ee0083699..0000000000 Binary files a/vendor/mysql/lib/arm/libmysql.dll and /dev/null differ diff --git a/vendor/mysql/lib/arm/libmysql.lib b/vendor/mysql/lib/arm/libmysql.lib deleted file mode 100644 index c2aacf2e69..0000000000 Binary files a/vendor/mysql/lib/arm/libmysql.lib and /dev/null differ diff --git a/vendor/mysql/lib/arm64/libmysql.dll b/vendor/mysql/lib/arm64/libmysql.dll deleted file mode 100644 index d0f08d9fe1..0000000000 Binary files a/vendor/mysql/lib/arm64/libmysql.dll and /dev/null differ diff --git a/vendor/mysql/lib/arm64/libmysql.lib b/vendor/mysql/lib/arm64/libmysql.lib index 5937bdb152..fba8d2c0c1 100644 Binary files a/vendor/mysql/lib/arm64/libmysql.lib and b/vendor/mysql/lib/arm64/libmysql.lib differ diff --git a/vendor/mysql/lib/x64/libmysql.dll b/vendor/mysql/lib/x64/libmysql.dll deleted file mode 100644 index 9adf4c5cc6..0000000000 Binary files a/vendor/mysql/lib/x64/libmysql.dll and /dev/null differ diff --git a/vendor/mysql/lib/x64/libmysql.lib b/vendor/mysql/lib/x64/libmysql.lib index d2dcf9705c..2cabe714f6 100644 Binary files a/vendor/mysql/lib/x64/libmysql.lib and b/vendor/mysql/lib/x64/libmysql.lib differ diff --git a/vendor/mysql/lib/x86/libmysql.dll b/vendor/mysql/lib/x86/libmysql.dll deleted file mode 100644 index eea53cb928..0000000000 Binary files a/vendor/mysql/lib/x86/libmysql.dll and /dev/null differ diff --git a/vendor/mysql/lib/x86/libmysql.lib b/vendor/mysql/lib/x86/libmysql.lib index 08685c71b6..451b18a37d 100644 Binary files a/vendor/mysql/lib/x86/libmysql.lib and b/vendor/mysql/lib/x86/libmysql.lib differ diff --git a/vendor/mysql/mysql-server.diff b/vendor/mysql/mysql-server.diff new file mode 100644 index 0000000000..0f97cd5297 --- /dev/null +++ b/vendor/mysql/mysql-server.diff @@ -0,0 +1,338 @@ +diff --git a/CMakeLists.txt b/CMakeLists.txt +index 8cd3633b877..21b9f946b2a 100644 +--- a/CMakeLists.txt ++++ b/CMakeLists.txt +@@ -54,6 +54,11 @@ IF(WIN32) + CMAKE_MINIMUM_REQUIRED(VERSION 3.15.3) + ENDIF() + ENDIF() ++ cmake_policy(SET CMP0091 NEW) ++ set(CMAKE_MSVC_RUNTIME_LIBRARY "MultiThreaded$<$:Debug>") ++ SET(WITHOUT_SERVER ON CACHE BOOL "" FORCE) ++ SET(WITH_UNIT_TESTS OFF CACHE BOOL "" FORCE) ++ SET(LINK_STATIC_RUNTIME_LIBRARIES ON CACHE BOOL "" FORCE) + ELSEIF(APPLE) + # Version 3.12.4 is needed because the new build system of Xcode is not + # supported by cmake. 3.12.4 will force using the legacy build system. +@@ -661,7 +666,7 @@ MESSAGE(STATUS "SIZEOF_VOIDP ${SIZEOF_VOIDP}") + # even if we have configured for 64bit build.... + SET(CMAKE_SIZEOF_VOID_P ${SIZEOF_VOIDP}) + IF(NOT SIZEOF_VOIDP EQUAL 8) +- MESSAGE(FATAL_ERROR "MySQL supports only 64-bit platforms.") ++# MESSAGE(FATAL_ERROR "MySQL supports only 64-bit platforms.") + ENDIF() + + INCLUDE(compile_flags) +diff --git a/cmake/os/Windows.cmake b/cmake/os/Windows.cmake +index f13bbdf5fff..fee48b56d28 100644 +--- a/cmake/os/Windows.cmake ++++ b/cmake/os/Windows.cmake +@@ -62,6 +62,8 @@ IF(CMAKE_SIZEOF_VOID_P MATCHES 8) + ELSE() + IF(WITHOUT_SERVER) + MESSAGE(WARNING "32bit is experimental!!") ++ SET(SYSTEM_TYPE "Win32") ++ SET(MYSQL_MACHINE_TYPE "x86") + ELSE() + MESSAGE(FATAL_ERROR "32 bit Windows builds are not supported. " + "Clean the build dir and rebuild using -G \"${CMAKE_GENERATOR} Win64\"") +diff --git a/cmake/ssl.cmake b/cmake/ssl.cmake +index 932659d030f..c2e47fc260d 100644 +--- a/cmake/ssl.cmake ++++ b/cmake/ssl.cmake +@@ -197,7 +197,7 @@ FUNCTION(FIND_OPENSSL_EXECUTABLE) + FIND_PROGRAM(OPENSSL_EXECUTABLE openssl) + ENDIF() + +- IF(OPENSSL_EXECUTABLE) ++ IF(OFF) #OPENSSL_EXECUTABLE) + SET(OPENSSL_EXECUTABLE_HAS_ZLIB 0) + EXECUTE_PROCESS( + COMMAND ${OPENSSL_EXECUTABLE} "list-cipher-commands" +@@ -807,6 +807,13 @@ MACRO(MYSQL_CHECK_SSL_DLLS) + SET(SSL_MSVC_VERSION_SUFFIX "-3") + SET(SSL_MSVC_ARCH_SUFFIX "-x64") + ENDIF() ++ IF("${CMAKE_GENERATOR_PLATFORM}" STREQUAL "Win32") ++ SET(SSL_MSVC_ARCH_SUFFIX "") ++ ELSEIF("${CMAKE_GENERATOR_PLATFORM}" STREQUAL "x64") ++ SET(SSL_MSVC_ARCH_SUFFIX "-x64") ++ ELSEIF("${CMAKE_GENERATOR_PLATFORM}" STREQUAL "ARM64") ++ SET(SSL_MSVC_ARCH_SUFFIX "-arm64") ++ ENDIF() + + FIND_FILE(HAVE_CRYPTO_DLL + NAMES +diff --git a/extra/libcno/CMakeLists.txt b/extra/libcno/CMakeLists.txt +index 2cc3a795f59..e1da34163a7 100644 +--- a/extra/libcno/CMakeLists.txt ++++ b/extra/libcno/CMakeLists.txt +@@ -32,9 +32,14 @@ MYSQL_ADD_EXECUTABLE( + SKIP_INSTALL + EXCLUDE_FROM_ALL + ) ++IF(WIN32 AND "${CMAKE_GENERATOR_PLATFORM}" STREQUAL "ARM64") ++ SET(cno_huffman_generator_CMD "${CMAKE_BINARY_DIR}/../build-x64/runtime_output_directory/RelWithDebInfo/cno_huffman_generator.exe") ++ELSE() ++ SET(cno_huffman_generator_CMD cno_huffman_generator) ++ENDIF() + ADD_CUSTOM_COMMAND( + OUTPUT "${LIBCNO_GENERATE_DIR}/hpack-data.h" +- COMMAND cno_huffman_generator ++ COMMAND ${cno_huffman_generator_CMD} + ARGS "${LIBCNO_GENERATE_DIR}/hpack-data.h" + DEPENDS + cno_huffman_generator +diff --git a/scripts/CMakeLists.txt b/scripts/CMakeLists.txt +index 9ebe10bdb51..4ea0fa5496a 100644 +--- a/scripts/CMakeLists.txt ++++ b/scripts/CMakeLists.txt +@@ -54,11 +54,17 @@ ELSE() + MESSAGE(FATAL_ERROR "Cannot concatenate files") + ENDIF() + ++IF(WIN32 AND "${CMAKE_GENERATOR_PLATFORM}" STREQUAL "ARM64") ++ SET(comp_sql_CMD "${CMAKE_BINARY_DIR}/../build-x64/runtime_output_directory/RelWithDebInfo/comp_sql.exe") ++ELSE() ++ SET(comp_sql_CMD comp_sql) ++ENDIF() ++ + # Build mysql_fix_privilege_tables.h + ADD_CUSTOM_COMMAND( + OUTPUT ${CMAKE_CURRENT_BINARY_DIR}/mysql_fix_privilege_tables_sql.h + ${CAT_COMMAND} +- COMMAND comp_sql ++ COMMAND ${comp_sql_CMD} + mysql_fix_privilege_tables + mysql_fix_privilege_tables.sql + mysql_fix_privilege_tables_sql.h +@@ -76,7 +82,7 @@ MY_ADD_CUSTOM_TARGET(GenFixPrivs + + ADD_CUSTOM_COMMAND( + OUTPUT ${CMAKE_CURRENT_BINARY_DIR}/sql_commands_system_data.h +- COMMAND comp_sql ++ COMMAND ${comp_sql_CMD} + mysql_system_data + ${CMAKE_CURRENT_SOURCE_DIR}/mysql_system_tables_data.sql + sql_commands_system_data.h +@@ -87,7 +93,7 @@ ADD_CUSTOM_COMMAND( + + ADD_CUSTOM_COMMAND( + OUTPUT ${CMAKE_CURRENT_BINARY_DIR}/sql_commands_system_tables_data_fix.h +- COMMAND comp_sql ++ COMMAND ${comp_sql_CMD} + mysql_system_tables_data_fix + ${CMAKE_CURRENT_SOURCE_DIR}/mysql_system_tables_data_fix.sql + sql_commands_system_tables_data_fix.h +@@ -98,7 +104,7 @@ ADD_CUSTOM_COMMAND( + + ADD_CUSTOM_COMMAND( + OUTPUT ${CMAKE_CURRENT_BINARY_DIR}/sql_commands_system_tables.h +- COMMAND comp_sql ++ COMMAND ${comp_sql_CMD} + mysql_system_tables + ${CMAKE_CURRENT_SOURCE_DIR}/mysql_system_tables.sql + sql_commands_system_tables.h +@@ -109,7 +115,7 @@ ADD_CUSTOM_COMMAND( + + ADD_CUSTOM_COMMAND( + OUTPUT ${CMAKE_CURRENT_BINARY_DIR}/sql_commands_system_users.h +- COMMAND comp_sql ++ COMMAND ${comp_sql_CMD} + mysql_system_users + ${CMAKE_CURRENT_SOURCE_DIR}/mysql_system_users.sql + sql_commands_system_users.h +@@ -120,7 +126,7 @@ ADD_CUSTOM_COMMAND( + + ADD_CUSTOM_COMMAND( + OUTPUT ${CMAKE_CURRENT_BINARY_DIR}/sql_commands_help_data.h +- COMMAND comp_sql ++ COMMAND ${comp_sql_CMD} + fill_help_tables + ${CMAKE_CURRENT_SOURCE_DIR}/fill_help_tables.sql + sql_commands_help_data.h +@@ -131,7 +137,7 @@ ADD_CUSTOM_COMMAND( + + ADD_CUSTOM_COMMAND( + OUTPUT ${CMAKE_CURRENT_BINARY_DIR}/sql_firewall_sp_set_firewall_mode.h +- COMMAND comp_sql ++ COMMAND ${comp_sql_CMD} + firewall_sp_set_firewall_mode + ${CMAKE_CURRENT_SOURCE_DIR}/firewall/firewall_sp_set_firewall_mode.sql + sql_firewall_sp_set_firewall_mode.h +@@ -142,7 +148,7 @@ ADD_CUSTOM_COMMAND( + + ADD_CUSTOM_COMMAND( + OUTPUT ${CMAKE_CURRENT_BINARY_DIR}/sql_firewall_sp_reload_firewall_rules.h +- COMMAND comp_sql ++ COMMAND ${comp_sql_CMD} + firewall_sp_reload_firewall_rules + ${CMAKE_CURRENT_SOURCE_DIR}/firewall/firewall_sp_reload_firewall_rules.sql + sql_firewall_sp_reload_firewall_rules.h +@@ -153,7 +159,7 @@ ADD_CUSTOM_COMMAND( + + ADD_CUSTOM_COMMAND( + OUTPUT ${CMAKE_CURRENT_BINARY_DIR}/sql_firewall_sp_set_firewall_group_mode.h +- COMMAND comp_sql ++ COMMAND ${comp_sql_CMD} + firewall_sp_set_firewall_group_mode + ${CMAKE_CURRENT_SOURCE_DIR}/firewall/firewall_sp_set_firewall_group_mode.sql + sql_firewall_sp_set_firewall_group_mode.h +@@ -164,7 +170,7 @@ ADD_CUSTOM_COMMAND( + + ADD_CUSTOM_COMMAND( + OUTPUT ${CMAKE_CURRENT_BINARY_DIR}/sql_firewall_sp_set_firewall_group_mode_and_user.h +- COMMAND comp_sql ++ COMMAND ${comp_sql_CMD} + firewall_sp_set_firewall_group_mode_and_user + ${CMAKE_CURRENT_SOURCE_DIR}/firewall/firewall_sp_set_firewall_group_mode_and_user.sql + sql_firewall_sp_set_firewall_group_mode_and_user.h +@@ -175,7 +181,7 @@ ADD_CUSTOM_COMMAND( + + ADD_CUSTOM_COMMAND( + OUTPUT ${CMAKE_CURRENT_BINARY_DIR}/sql_firewall_sp_reload_firewall_group_rules.h +- COMMAND comp_sql ++ COMMAND ${comp_sql_CMD} + firewall_sp_reload_firewall_group_rules + ${CMAKE_CURRENT_SOURCE_DIR}/firewall/firewall_sp_reload_firewall_group_rules.sql + sql_firewall_sp_reload_firewall_group_rules.h +@@ -186,7 +192,7 @@ ADD_CUSTOM_COMMAND( + + ADD_CUSTOM_COMMAND( + OUTPUT ${CMAKE_CURRENT_BINARY_DIR}/sql_firewall_sp_firewall_group_enlist.h +- COMMAND comp_sql ++ COMMAND ${comp_sql_CMD} + firewall_sp_firewall_group_enlist + ${CMAKE_CURRENT_SOURCE_DIR}/firewall/firewall_sp_firewall_group_enlist.sql + sql_firewall_sp_firewall_group_enlist.h +@@ -197,7 +203,7 @@ ADD_CUSTOM_COMMAND( + + ADD_CUSTOM_COMMAND( + OUTPUT ${CMAKE_CURRENT_BINARY_DIR}/sql_firewall_sp_firewall_group_delist.h +- COMMAND comp_sql ++ COMMAND ${comp_sql_CMD} + firewall_sp_firewall_group_delist + ${CMAKE_CURRENT_SOURCE_DIR}/firewall/firewall_sp_firewall_group_delist.sql + sql_firewall_sp_firewall_group_delist.h +diff --git a/scripts/sys_schema/CMakeLists.txt b/scripts/sys_schema/CMakeLists.txt +index 1d3295e8d4f..08327e3026c 100644 +--- a/scripts/sys_schema/CMakeLists.txt ++++ b/scripts/sys_schema/CMakeLists.txt +@@ -205,10 +205,16 @@ ADD_CUSTOM_COMMAND( + MY_ADD_CUSTOM_TARGET(all_sys_schema + DEPENDS ALL_SYS_SCHEMA.sql) + ++IF(WIN32 AND "${CMAKE_GENERATOR_PLATFORM}" STREQUAL "ARM64") ++ SET(comp_sql_CMD "${CMAKE_BINARY_DIR}/../build-x64/runtime_output_directory/RelWithDebInfo/comp_sql.exe") ++ELSE() ++ SET(comp_sql_CMD comp_sql) ++ENDIF() ++ + + ADD_CUSTOM_COMMAND( + OUTPUT ${CMAKE_CURRENT_BINARY_DIR}/sql_commands.h +- COMMAND comp_sql ++ COMMAND ${comp_sql_CMD} + mysql_sys_schema + ${CMAKE_CURRENT_BINARY_DIR}/ALL_SYS_SCHEMA.sql + sql_commands.h +diff --git a/sql-common/client.cc b/sql-common/client.cc +index 891a29a897c..43b9a74c250 100644 +--- a/sql-common/client.cc ++++ b/sql-common/client.cc +@@ -8600,9 +8600,9 @@ int STDCALL mysql_options(MYSQL *mysql, enum mysql_option option, + mysql->options.report_data_truncation = *static_cast(arg); + break; + case MYSQL_OPT_RECONNECT: +- fprintf(stderr, +- "WARNING: MYSQL_OPT_RECONNECT is deprecated and will be " +- "removed in a future version.\n"); ++ // fprintf(stderr, ++ // "WARNING: MYSQL_OPT_RECONNECT is deprecated and will be " ++ // "removed in a future version.\n"); + mysql->reconnect = *static_cast(arg); + break; + case MYSQL_OPT_BIND: +@@ -8930,9 +8930,9 @@ int STDCALL mysql_get_option(MYSQL *mysql, enum mysql_option option, + mysql->options.report_data_truncation; + break; + case MYSQL_OPT_RECONNECT: +- fprintf(stderr, +- "WARNING: MYSQL_OPT_RECONNECT is deprecated and will be " +- "removed in a future version.\n"); ++ // fprintf(stderr, ++ // "WARNING: MYSQL_OPT_RECONNECT is deprecated and will be " ++ // "removed in a future version.\n"); + *(const_cast(static_cast(arg))) = mysql->reconnect; + break; + case MYSQL_OPT_BIND: +diff --git a/strings/CMakeLists.txt b/strings/CMakeLists.txt +index ee363b78bd5..61cfd5890ad 100644 +--- a/strings/CMakeLists.txt ++++ b/strings/CMakeLists.txt +@@ -69,9 +69,15 @@ SET(ZH_HANS_DST_FILE ${CMAKE_BINARY_DIR}/strings/uca900_zh_tbls.cc) + SET(JA_HANS_SRC_FILE ${CMAKE_SOURCE_DIR}/strings/lang_data/ja_hans.txt) + SET(JA_HANS_DST_FILE ${CMAKE_BINARY_DIR}/strings/uca900_ja_tbls.cc) + ++IF(WIN32 AND "${CMAKE_GENERATOR_PLATFORM}" STREQUAL "ARM64") ++ SET(uca9dump_CMD "${CMAKE_BINARY_DIR}/../build-x64/runtime_output_directory/RelWithDebInfo/uca9dump.exe") ++ELSE() ++ SET(uca9dump_CMD uca9dump) ++ENDIF() ++ + ADD_CUSTOM_COMMAND( + OUTPUT ${JA_HANS_DST_FILE} +- COMMAND uca9dump ja ++ COMMAND ${uca9dump_CMD} ja + --in_file=${JA_HANS_SRC_FILE} + --out_file=${JA_HANS_DST_FILE} + DEPENDS uca9dump ${JA_HANS_SRC_FILE} +@@ -80,7 +86,7 @@ ADD_CUSTOM_TARGET(strings_ja_hans DEPENDS ${JA_HANS_DST_FILE}) + + ADD_CUSTOM_COMMAND( + OUTPUT ${ZH_HANS_DST_FILE} +- COMMAND uca9dump zh ++ COMMAND ${uca9dump_CMD} zh + --in_file=${ZH_HANS_SRC_FILE} + --out_file=${ZH_HANS_DST_FILE} + DEPENDS uca9dump ${ZH_HANS_SRC_FILE} +diff --git a/utilities/CMakeLists.txt b/utilities/CMakeLists.txt +index d38157e00a4..dfb166e47a8 100644 +--- a/utilities/CMakeLists.txt ++++ b/utilities/CMakeLists.txt +@@ -45,8 +45,14 @@ MYSQL_ADD_EXECUTABLE(comp_client_err + SKIP_INSTALL + ) + ++IF(WIN32 AND "${CMAKE_GENERATOR_PLATFORM}" STREQUAL "ARM64") ++ SET(comp_client_err_CMD "${CMAKE_BINARY_DIR}/../build-x64/runtime_output_directory/RelWithDebInfo/comp_client_err.exe") ++ELSE() ++ SET(comp_client_err_CMD comp_client_err) ++ENDIF() ++ + ADD_CUSTOM_COMMAND(OUTPUT ${PROJECT_BINARY_DIR}/include/mysqlclient_ername.h +- COMMAND comp_client_err ++ COMMAND ${comp_client_err_CMD} + --in_file=${PROJECT_SOURCE_DIR}/include/errmsg.h + --out_file=${PROJECT_BINARY_DIR}/include/mysqlclient_ername.h + DEPENDS ${CMAKE_CURRENT_SOURCE_DIR}/comp_client_err.cc) +@@ -70,12 +76,18 @@ FILE(MAKE_DIRECTORY ${PROJECT_BINARY_DIR}/${INSTALL_MYSQLSHAREDIR}) + # + # Please see errmsg_readme.txt in the same directory for more information. + # ++IF(WIN32 AND "${CMAKE_GENERATOR_PLATFORM}" STREQUAL "ARM64") ++ SET(comp_err_CMD "${CMAKE_BINARY_DIR}/../build-x64/runtime_output_directory/RelWithDebInfo/comp_err.exe") ++ELSE() ++ SET(comp_err_CMD comp_err) ++ENDIF() ++ + ADD_CUSTOM_COMMAND(OUTPUT + ${PROJECT_BINARY_DIR}/include/mysqld_error.h + ${PROJECT_BINARY_DIR}/include/mysqld_ername.h + ${PROJECT_BINARY_DIR}/include/mysqld_errmsg.h + ${PROJECT_BINARY_DIR}/${INSTALL_MYSQLSHAREDIR}/english/errmsg.sys +- COMMAND comp_err ++ COMMAND ${comp_err_CMD} + --charset=${PROJECT_SOURCE_DIR}/share/charsets + --out-dir=${PROJECT_BINARY_DIR}/${INSTALL_MYSQLSHAREDIR}/ + --header_file=${PROJECT_BINARY_DIR}/include/mysqld_error.h diff --git a/vendor/nvapi/NvApiDriverSettings.c b/vendor/nvapi/NvApiDriverSettings.c index 2fb52dd755..b4eb350104 100644 --- a/vendor/nvapi/NvApiDriverSettings.c +++ b/vendor/nvapi/NvApiDriverSettings.c @@ -148,13 +148,6 @@ EValues_OGL_SINGLE_BACKDEPTH_BUFFER g_valuesOGL_SINGLE_BACKDEPTH_BUFFER[OGL_SING OGL_SINGLE_BACKDEPTH_BUFFER_USE_HW_DEFAULT, }; -EValues_OGL_SLI_CFR_MODE g_valuesOGL_SLI_CFR_MODE[OGL_SLI_CFR_MODE_NUM_VALUES] = -{ - OGL_SLI_CFR_MODE_DISABLE, - OGL_SLI_CFR_MODE_ENABLE, - OGL_SLI_CFR_MODE_CLASSIC_SFR, -}; - EValues_OGL_SLI_MULTICAST g_valuesOGL_SLI_MULTICAST[OGL_SLI_MULTICAST_NUM_VALUES] = { OGL_SLI_MULTICAST_DISABLE, @@ -695,13 +688,6 @@ EValues_WKS_API_STEREO_MODE g_valuesWKS_API_STEREO_MODE[WKS_API_STEREO_MODE_NUM_ WKS_API_STEREO_MODE_DEFAULT_GL, }; -EValues_WKS_MEMORY_ALLOCATION_POLICY g_valuesWKS_MEMORY_ALLOCATION_POLICY[WKS_MEMORY_ALLOCATION_POLICY_NUM_VALUES] = -{ - WKS_MEMORY_ALLOCATION_POLICY_AS_NEEDED, - WKS_MEMORY_ALLOCATION_POLICY_MODERATE_PRE_ALLOCATION, - WKS_MEMORY_ALLOCATION_POLICY_AGGRESSIVE_PRE_ALLOCATION, -}; - EValues_WKS_STEREO_DONGLE_SUPPORT g_valuesWKS_STEREO_DONGLE_SUPPORT[WKS_STEREO_DONGLE_SUPPORT_NUM_VALUES] = { WKS_STEREO_DONGLE_SUPPORT_OFF, @@ -878,7 +864,6 @@ SettingDWORDNameString mapSettingDWORD[TOTAL_DWORD_SETTING_NUM] = {OGL_OVERLAY_SUPPORT_ID, OGL_OVERLAY_SUPPORT_STRING, 3, (NvU32 *)g_valuesOGL_OVERLAY_SUPPORT, OGL_OVERLAY_SUPPORT_OFF}, {OGL_QUALITY_ENHANCEMENTS_ID, OGL_QUALITY_ENHANCEMENTS_STRING, 4, (NvU32 *)g_valuesOGL_QUALITY_ENHANCEMENTS, OGL_QUALITY_ENHANCEMENTS_QUAL}, {OGL_SINGLE_BACKDEPTH_BUFFER_ID, OGL_SINGLE_BACKDEPTH_BUFFER_STRING, 3, (NvU32 *)g_valuesOGL_SINGLE_BACKDEPTH_BUFFER, OGL_SINGLE_BACKDEPTH_BUFFER_DISABLE}, - {OGL_SLI_CFR_MODE_ID, OGL_SLI_CFR_MODE_STRING, 3, (NvU32 *)g_valuesOGL_SLI_CFR_MODE, OGL_SLI_CFR_MODE_DISABLE}, {OGL_SLI_MULTICAST_ID, OGL_SLI_MULTICAST_STRING, 4, (NvU32 *)g_valuesOGL_SLI_MULTICAST, OGL_SLI_MULTICAST_DISABLE}, {OGL_THREAD_CONTROL_ID, OGL_THREAD_CONTROL_STRING, 2, (NvU32 *)g_valuesOGL_THREAD_CONTROL, 0x00000000}, {OGL_TMON_LEVEL_ID, OGL_TMON_LEVEL_STRING, 6, (NvU32 *)g_valuesOGL_TMON_LEVEL, OGL_TMON_LEVEL_MOST}, @@ -895,6 +880,8 @@ SettingDWORDNameString mapSettingDWORD[TOTAL_DWORD_SETTING_NUM] = {ANSEL_ALLOW_ID, ANSEL_ALLOW_STRING, 2, (NvU32 *)g_valuesANSEL_ALLOW, ANSEL_ALLOW_ALLOWED}, {ANSEL_ALLOWLISTED_ID, ANSEL_ALLOWLISTED_STRING, 2, (NvU32 *)g_valuesANSEL_ALLOWLISTED, ANSEL_ALLOWLISTED_DISALLOWED}, {ANSEL_ENABLE_ID, ANSEL_ENABLE_STRING, 2, (NvU32 *)g_valuesANSEL_ENABLE, ANSEL_ENABLE_ON}, + {APPIDLE_DYNAMIC_FRL_FPS_ID, APPIDLE_DYNAMIC_FRL_FPS_STRING, 0, NULL, 0x00000000}, + {APPIDLE_DYNAMIC_FRL_THRESHOLD_TIME_ID, APPIDLE_DYNAMIC_FRL_THRESHOLD_TIME_STRING, 0, NULL, 0x00000000}, {APPLICATION_PROFILE_NOTIFICATION_TIMEOUT_ID, APPLICATION_PROFILE_NOTIFICATION_TIMEOUT_STRING, 6, (NvU32 *)g_valuesAPPLICATION_PROFILE_NOTIFICATION_TIMEOUT, APPLICATION_PROFILE_NOTIFICATION_TIMEOUT_DISABLED}, {APPLICATION_STEAM_ID_ID, APPLICATION_STEAM_ID_STRING, 0, NULL, 0x00000000}, {BATTERY_BOOST_APP_FPS_ID, BATTERY_BOOST_APP_FPS_STRING, 3, (NvU32 *)g_valuesBATTERY_BOOST_APP_FPS, BATTERY_BOOST_APP_FPS_NO_OVERRIDE}, @@ -934,7 +921,6 @@ SettingDWORDNameString mapSettingDWORD[TOTAL_DWORD_SETTING_NUM] = {VSYNC_BEHAVIOR_FLAGS_ID, VSYNC_BEHAVIOR_FLAGS_STRING, 3, (NvU32 *)g_valuesVSYNC_BEHAVIOR_FLAGS, VSYNC_BEHAVIOR_FLAGS_DEFAULT}, {WKS_API_STEREO_EYES_EXCHANGE_ID, WKS_API_STEREO_EYES_EXCHANGE_STRING, 2, (NvU32 *)g_valuesWKS_API_STEREO_EYES_EXCHANGE, WKS_API_STEREO_EYES_EXCHANGE_OFF}, {WKS_API_STEREO_MODE_ID, WKS_API_STEREO_MODE_STRING, 25, (NvU32 *)g_valuesWKS_API_STEREO_MODE, WKS_API_STEREO_MODE_SHUTTER_GLASSES}, - {WKS_MEMORY_ALLOCATION_POLICY_ID, WKS_MEMORY_ALLOCATION_POLICY_STRING, 3, (NvU32 *)g_valuesWKS_MEMORY_ALLOCATION_POLICY, WKS_MEMORY_ALLOCATION_POLICY_AS_NEEDED}, {WKS_STEREO_DONGLE_SUPPORT_ID, WKS_STEREO_DONGLE_SUPPORT_STRING, 3, (NvU32 *)g_valuesWKS_STEREO_DONGLE_SUPPORT, WKS_STEREO_DONGLE_SUPPORT_DAC}, {WKS_STEREO_SUPPORT_ID, WKS_STEREO_SUPPORT_STRING, 2, (NvU32 *)g_valuesWKS_STEREO_SUPPORT, WKS_STEREO_SUPPORT_OFF}, {WKS_STEREO_SWAP_MODE_ID, WKS_STEREO_SWAP_MODE_STRING, 5, (NvU32 *)g_valuesWKS_STEREO_SWAP_MODE, WKS_STEREO_SWAP_MODE_APPLICATION_CONTROL}, @@ -966,5 +952,6 @@ SettingWSTRINGNameString mapSettingWSTRING[TOTAL_WSTRING_SETTING_NUM] = {CUDA_EXCLUDED_GPUS_ID, CUDA_EXCLUDED_GPUS_STRING, 1, (const wchar_t **)g_valuesCUDA_EXCLUDED_GPUS, L"none"}, {D3DOGL_GPU_MAX_POWER_ID, D3DOGL_GPU_MAX_POWER_STRING, 1, (const wchar_t **)g_valuesD3DOGL_GPU_MAX_POWER, L"0"}, {ICAFE_LOGO_CONFIG_ID, ICAFE_LOGO_CONFIG_STRING, 0, NULL, L""}, + {PS_SHADERDISKCACHE_DLL_PATH_WCHAR_ID, PS_SHADERDISKCACHE_DLL_PATH_WCHAR_STRING, 0, NULL, L""}, }; diff --git a/vendor/nvapi/NvApiDriverSettings.h b/vendor/nvapi/NvApiDriverSettings.h index 100f9c8faa..df1d48ac22 100644 --- a/vendor/nvapi/NvApiDriverSettings.h +++ b/vendor/nvapi/NvApiDriverSettings.h @@ -57,7 +57,6 @@ #define OGL_OVERLAY_SUPPORT_STRING L"Enable overlay" #define OGL_QUALITY_ENHANCEMENTS_STRING L"High level control of the rendering quality on OpenGL" #define OGL_SINGLE_BACKDEPTH_BUFFER_STRING L"Unified back/depth buffer" -#define OGL_SLI_CFR_MODE_STRING L"Set CFR mode" #define OGL_SLI_MULTICAST_STRING L"Enable NV_gpu_multicast extension" #define OGL_THREAD_CONTROL_STRING L"Threaded optimization" #define OGL_TMON_LEVEL_STRING L"Event Log Tmon Severity Threshold" @@ -74,6 +73,8 @@ #define ANSEL_ALLOW_STRING L"NVIDIA Predefined Ansel Usage" #define ANSEL_ALLOWLISTED_STRING L"Ansel flags for enabled applications" #define ANSEL_ENABLE_STRING L"Enable Ansel" +#define APPIDLE_DYNAMIC_FRL_FPS_STRING L"Idle Application Max FPS Limit" +#define APPIDLE_DYNAMIC_FRL_THRESHOLD_TIME_STRING L"Idle Application Threshold Time out in seconds" #define APPLICATION_PROFILE_NOTIFICATION_TIMEOUT_STRING L"Application Profile Notification Popup Timeout" #define APPLICATION_STEAM_ID_STRING L"Steam Application ID" #define BATTERY_BOOST_APP_FPS_STRING L"Battery Boost Application FPS" @@ -115,7 +116,6 @@ #define VSYNC_BEHAVIOR_FLAGS_STRING L"Vsync - Behavior Flags" #define WKS_API_STEREO_EYES_EXCHANGE_STRING L"Stereo - Swap eyes" #define WKS_API_STEREO_MODE_STRING L"Stereo - Display mode" -#define WKS_MEMORY_ALLOCATION_POLICY_STRING L"Memory Allocation Policy" #define WKS_STEREO_DONGLE_SUPPORT_STRING L"Stereo - Dongle Support" #define WKS_STEREO_SUPPORT_STRING L"Stereo - Enable" #define WKS_STEREO_SWAP_MODE_STRING L"Stereo - swap mode" @@ -128,6 +128,7 @@ #define MAXWELL_B_SAMPLE_INTERLEAVE_STRING L"Enable sample interleaving (MFAA)" #define PRERENDERLIMIT_STRING L"Maximum pre-rendered frames" #define PS_SHADERDISKCACHE_STRING L"Shader Cache" +#define PS_SHADERDISKCACHE_DLL_PATH_WCHAR_STRING L"shader cache path to dll" #define PS_SHADERDISKCACHE_MAX_SIZE_STRING L"Shader disk cache maximum size" #define PS_TEXFILTER_ANISO_OPTS2_STRING L"Texture filtering - Anisotropic sample optimization" #define PS_TEXFILTER_BILINEAR_IN_ANISO_STRING L"Texture filtering - Anisotropic filter optimization" @@ -159,7 +160,6 @@ enum ESetting { OGL_OVERLAY_SUPPORT_ID = 0x206C28C4, OGL_QUALITY_ENHANCEMENTS_ID = 0x20797D6C, OGL_SINGLE_BACKDEPTH_BUFFER_ID = 0x20A29055, - OGL_SLI_CFR_MODE_ID = 0x20343843, OGL_SLI_MULTICAST_ID = 0x2092D3BE, OGL_THREAD_CONTROL_ID = 0x20C1221E, OGL_TMON_LEVEL_ID = 0x202888C1, @@ -176,6 +176,8 @@ enum ESetting { ANSEL_ALLOW_ID = 0x1035DB89, ANSEL_ALLOWLISTED_ID = 0x1085DA8A, ANSEL_ENABLE_ID = 0x1075D972, + APPIDLE_DYNAMIC_FRL_FPS_ID = 0x10835016, + APPIDLE_DYNAMIC_FRL_THRESHOLD_TIME_ID = 0x10835017, APPLICATION_PROFILE_NOTIFICATION_TIMEOUT_ID = 0x104554B6, APPLICATION_STEAM_ID_ID = 0x107CDDBC, BATTERY_BOOST_APP_FPS_ID = 0x10115C8C, @@ -217,7 +219,6 @@ enum ESetting { VSYNC_BEHAVIOR_FLAGS_ID = 0x10FDEC23, WKS_API_STEREO_EYES_EXCHANGE_ID = 0x11AE435C, WKS_API_STEREO_MODE_ID = 0x11E91A61, - WKS_MEMORY_ALLOCATION_POLICY_ID = 0x11112233, WKS_STEREO_DONGLE_SUPPORT_ID = 0x112493BD, WKS_STEREO_SUPPORT_ID = 0x11AA9E99, WKS_STEREO_SWAP_MODE_ID = 0x11333333, @@ -230,6 +231,7 @@ enum ESetting { MAXWELL_B_SAMPLE_INTERLEAVE_ID = 0x0098C1AC, PRERENDERLIMIT_ID = 0x007BA09E, PS_SHADERDISKCACHE_ID = 0x00198FFF, + PS_SHADERDISKCACHE_DLL_PATH_WCHAR_ID = 0x0019A002, PS_SHADERDISKCACHE_MAX_SIZE_ID = 0x00AC8497, PS_TEXFILTER_ANISO_OPTS2_ID = 0x00E73211, PS_TEXFILTER_BILINEAR_IN_ANISO_ID = 0x0084CD70, @@ -243,8 +245,8 @@ enum ESetting { VSYNCMODE_ID = 0x00A879CF, VSYNCTEARCONTROL_ID = 0x005A375C, TOTAL_DWORD_SETTING_NUM = 96, - TOTAL_WSTRING_SETTING_NUM = 4, - TOTAL_SETTING_NUM = 100, + TOTAL_WSTRING_SETTING_NUM = 5, + TOTAL_SETTING_NUM = 101, INVALID_SETTING_ID = 0xFFFFFFFF }; @@ -371,14 +373,6 @@ enum EValues_OGL_SINGLE_BACKDEPTH_BUFFER { OGL_SINGLE_BACKDEPTH_BUFFER_DEFAULT = OGL_SINGLE_BACKDEPTH_BUFFER_DISABLE }; -enum EValues_OGL_SLI_CFR_MODE { - OGL_SLI_CFR_MODE_DISABLE = 0x00, - OGL_SLI_CFR_MODE_ENABLE = 0x01, - OGL_SLI_CFR_MODE_CLASSIC_SFR = 0x02, - OGL_SLI_CFR_MODE_NUM_VALUES = 3, - OGL_SLI_CFR_MODE_DEFAULT = OGL_SLI_CFR_MODE_DISABLE -}; - enum EValues_OGL_SLI_MULTICAST { OGL_SLI_MULTICAST_DISABLE = 0x00, OGL_SLI_MULTICAST_ENABLE = 0x01, @@ -964,14 +958,6 @@ enum EValues_WKS_API_STEREO_MODE { WKS_API_STEREO_MODE_DEFAULT = WKS_API_STEREO_MODE_SHUTTER_GLASSES }; -enum EValues_WKS_MEMORY_ALLOCATION_POLICY { - WKS_MEMORY_ALLOCATION_POLICY_AS_NEEDED = 0x0, - WKS_MEMORY_ALLOCATION_POLICY_MODERATE_PRE_ALLOCATION = 0x1, - WKS_MEMORY_ALLOCATION_POLICY_AGGRESSIVE_PRE_ALLOCATION = 0x2, - WKS_MEMORY_ALLOCATION_POLICY_NUM_VALUES = 3, - WKS_MEMORY_ALLOCATION_POLICY_DEFAULT = WKS_MEMORY_ALLOCATION_POLICY_AS_NEEDED -}; - enum EValues_WKS_STEREO_DONGLE_SUPPORT { WKS_STEREO_DONGLE_SUPPORT_OFF = 0, WKS_STEREO_DONGLE_SUPPORT_DAC = 1, diff --git a/vendor/nvapi/amd64/nvapi64.lib b/vendor/nvapi/amd64/nvapi64.lib index 9f3729abad..9e22c10f72 100644 Binary files a/vendor/nvapi/amd64/nvapi64.lib and b/vendor/nvapi/amd64/nvapi64.lib differ diff --git a/vendor/nvapi/nvHLSLExtns.h b/vendor/nvapi/nvHLSLExtns.h index 9394036dad..3b5d3a0a0c 100644 --- a/vendor/nvapi/nvHLSLExtns.h +++ b/vendor/nvapi/nvHLSLExtns.h @@ -1625,6 +1625,123 @@ uint4 NvWaveMultiPrefixExclusiveXOr(uint4 val, uint mask) return NvWaveMultiPrefixInclusiveXOr(val, mask); } + +//----------------------------------------------------------------------------// +//------------------------- DXR Micro-map Extension --------------------------// +//----------------------------------------------------------------------------// + +float3x3 NvRtTriangleObjectPositions() +{ + uint index = g_NvidiaExt.IncrementCounter(); + g_NvidiaExt[index].opcode = NV_EXTN_OP_RT_TRIANGLE_OBJECT_POSITIONS; + + float3x3 ret; + ret[0][0] = asfloat(g_NvidiaExt.IncrementCounter()); + ret[0][1] = asfloat(g_NvidiaExt.IncrementCounter()); + ret[0][2] = asfloat(g_NvidiaExt.IncrementCounter()); + ret[1][0] = asfloat(g_NvidiaExt.IncrementCounter()); + ret[1][1] = asfloat(g_NvidiaExt.IncrementCounter()); + ret[1][2] = asfloat(g_NvidiaExt.IncrementCounter()); + ret[2][0] = asfloat(g_NvidiaExt.IncrementCounter()); + ret[2][1] = asfloat(g_NvidiaExt.IncrementCounter()); + ret[2][2] = asfloat(g_NvidiaExt.IncrementCounter()); + return ret; +} + +float3x3 NvRtMicroTriangleObjectPositions() +{ + uint index = g_NvidiaExt.IncrementCounter(); + g_NvidiaExt[index].opcode = NV_EXTN_OP_RT_MICRO_TRIANGLE_OBJECT_POSITIONS; + + float3x3 ret; + ret[0][0] = asfloat(g_NvidiaExt.IncrementCounter()); + ret[0][1] = asfloat(g_NvidiaExt.IncrementCounter()); + ret[0][2] = asfloat(g_NvidiaExt.IncrementCounter()); + ret[1][0] = asfloat(g_NvidiaExt.IncrementCounter()); + ret[1][1] = asfloat(g_NvidiaExt.IncrementCounter()); + ret[1][2] = asfloat(g_NvidiaExt.IncrementCounter()); + ret[2][0] = asfloat(g_NvidiaExt.IncrementCounter()); + ret[2][1] = asfloat(g_NvidiaExt.IncrementCounter()); + ret[2][2] = asfloat(g_NvidiaExt.IncrementCounter()); + return ret; +} + +float3x2 NvRtMicroTriangleBarycentrics() +{ + uint index = g_NvidiaExt.IncrementCounter(); + g_NvidiaExt[index].opcode = NV_EXTN_OP_RT_MICRO_TRIANGLE_BARYCENTRICS; + + float3x2 ret; + ret[0][0] = asfloat(g_NvidiaExt.IncrementCounter()); + ret[0][1] = asfloat(g_NvidiaExt.IncrementCounter()); + ret[1][0] = asfloat(g_NvidiaExt.IncrementCounter()); + ret[1][1] = asfloat(g_NvidiaExt.IncrementCounter()); + ret[2][0] = asfloat(g_NvidiaExt.IncrementCounter()); + ret[2][1] = asfloat(g_NvidiaExt.IncrementCounter()); + return ret; +} + +bool NvRtIsMicroTriangleHit() +{ + uint index = g_NvidiaExt.IncrementCounter(); + g_NvidiaExt[index].opcode = NV_EXTN_OP_RT_IS_MICRO_TRIANGLE_HIT; + uint ret = g_NvidiaExt.IncrementCounter(); + return ret != 0; +} + +bool NvRtIsBackFacing() +{ + uint index = g_NvidiaExt.IncrementCounter(); + g_NvidiaExt[index].opcode = NV_EXTN_OP_RT_IS_BACK_FACING; + uint ret = g_NvidiaExt.IncrementCounter(); + return ret != 0; +} + +#if __SHADER_TARGET_MAJOR > 6 || (__SHADER_TARGET_MAJOR == 6 && __SHADER_TARGET_MINOR >= 5) + +float3 NvRtMicroVertexObjectPosition(RaytracingAccelerationStructure AccelerationStructure, uint InstanceIndex, uint GeometryIndex, uint PrimitiveIndex, uint2 UV) +{ + uint index = g_NvidiaExt.IncrementCounter(); + g_NvidiaExt[index].opcode = NV_EXTN_OP_RT_MICRO_VERTEX_OBJECT_POSITION; + g_NvidiaExt[index].src0u.x = InstanceIndex; + g_NvidiaExt[index].src0u.y = GeometryIndex; + g_NvidiaExt[index].src0u.z = PrimitiveIndex; + g_NvidiaExt[index].src0u.w = UV.x; + g_NvidiaExt[index].src1u.x = UV.y; + uint handle = g_NvidiaExt.IncrementCounter(); + float3 ret; + ret.x = asfloat(g_NvidiaExt.IncrementCounter()); + ret.y = asfloat(g_NvidiaExt.IncrementCounter()); + ret.z = asfloat(g_NvidiaExt.IncrementCounter()); + + RayQuery<0> rq; + rq.TraceRayInline(AccelerationStructure, 0, handle, (RayDesc)0); + + return ret; +} + +float2 NvRtMicroVertexBarycentrics(RaytracingAccelerationStructure AccelerationStructure, uint InstanceIndex, uint GeometryIndex, uint PrimitiveIndex, uint2 UV) +{ + uint index = g_NvidiaExt.IncrementCounter(); + g_NvidiaExt[index].opcode = NV_EXTN_OP_RT_MICRO_VERTEX_BARYCENTRICS; + g_NvidiaExt[index].src0u.x = InstanceIndex; + g_NvidiaExt[index].src0u.y = GeometryIndex; + g_NvidiaExt[index].src0u.z = PrimitiveIndex; + g_NvidiaExt[index].src0u.w = UV.x; + g_NvidiaExt[index].src1u.x = UV.y; + uint handle = g_NvidiaExt.IncrementCounter(); + float2 ret; + ret.x = asfloat(g_NvidiaExt.IncrementCounter()); + ret.y = asfloat(g_NvidiaExt.IncrementCounter()); + + RayQuery<0> rq; + rq.TraceRayInline(AccelerationStructure, 0, handle, (RayDesc)0); + + return ret; +} + +#endif + //----------------------------------------------------------------------------// //------------------------- DXR HitObject Extension --------------------------// //----------------------------------------------------------------------------// diff --git a/vendor/nvapi/nvShaderExtnEnums.h b/vendor/nvapi/nvShaderExtnEnums.h index cfa918b3e7..0913884176 100644 --- a/vendor/nvapi/nvShaderExtnEnums.h +++ b/vendor/nvapi/nvShaderExtnEnums.h @@ -114,6 +114,15 @@ #define NV_EXTN_OP_HIT_OBJECT_IS_NOP 84 #define NV_EXTN_OP_HIT_OBJECT_MAKE_NOP 85 +// Micro-map API +#define NV_EXTN_OP_RT_TRIANGLE_OBJECT_POSITIONS 86 +#define NV_EXTN_OP_RT_MICRO_TRIANGLE_OBJECT_POSITIONS 87 +#define NV_EXTN_OP_RT_MICRO_TRIANGLE_BARYCENTRICS 88 +#define NV_EXTN_OP_RT_IS_MICRO_TRIANGLE_HIT 89 +#define NV_EXTN_OP_RT_IS_BACK_FACING 90 +#define NV_EXTN_OP_RT_MICRO_VERTEX_OBJECT_POSITION 91 +#define NV_EXTN_OP_RT_MICRO_VERTEX_BARYCENTRICS 92 + //----------------------------------------------------------------------------// //-------------------- GET_SPECIAL subOpCode constants -----------------------// //----------------------------------------------------------------------------// diff --git a/vendor/nvapi/nvapi.h b/vendor/nvapi/nvapi.h index 9b4733b1b7..ef5edfcf5f 100644 --- a/vendor/nvapi/nvapi.h +++ b/vendor/nvapi/nvapi.h @@ -41,7 +41,7 @@ /////////////////////////////////////////////////////////////////////////////// // -// Date: Apr 4, 2023 +// Date: May 30, 2024 // File: nvapi.h // // NvAPI provides an interface to NVIDIA devices. This file contains the @@ -338,6 +338,23 @@ typedef NV_EDID_V3 NV_EDID; //! \ingroup gpu NVAPI_INTERFACE NvAPI_GPU_GetEDID(NvPhysicalGpuHandle hPhysicalGpu, NvU32 displayOutputId, NV_EDID *pEDID); +//! \ingroup gpu + +//! Used in NvAPI_DISP_GetEdidData + +#define NV_EDID_DATA_SIZE_MAX 1024 //!< This is the current size supported by Nvidia Display Driver and may change in future. + +typedef enum +{ + NV_EDID_FLAG_DEFAULT = 0, //!< the EDID which is actively used by the driver, it could be _RAW/_COOKED/_FORCED/_INF. + NV_EDID_FLAG_RAW = 1, //!< the EDID which is not modified by the driver. If there's no _FORCED edid engaged, it + //!< will be the unmodified monitor EDID from the I2C bus. Otherwise it is original _FORCED edid. + NV_EDID_FLAG_COOKED = 2, //!< the EDID has been modified by the driver for compatibility + NV_EDID_FLAG_FORCED = 3, //!< the EDID is forced by the end-user over s/w interface, + NV_EDID_FLAG_INF = 4, //!< the EDID is from monitor INF + NV_EDID_FLAG_HW = 5, //!< the EDID is from the monitor over I2C bus without any modification. +} NV_EDID_FLAG; + //! \ingroup gpu //! Used in NV_GPU_CONNECTOR_DATA typedef enum _NV_GPU_CONNECTOR_TYPE @@ -1724,6 +1741,8 @@ NVAPI_INTERFACE NvAPI_GetPhysicalGPUsFromLogicalGPU(NvLogicalGpuHandle hLogicalG //! //! TCC_SUPPORTED //! +//! MCDM_SUPPORTED +//! //! \since Release: 80 //! //! \retval NVAPI_INVALID_ARGUMENT gpuId is zero or pPhysicalGPU is NULL @@ -1744,6 +1763,8 @@ NVAPI_INTERFACE NvAPI_GetPhysicalGPUFromGPUID(NvU32 gpuId, NvPhysicalGpuHandle * //! //! TCC_SUPPORTED //! +//! MCDM_SUPPORTED +//! //! \since Release: 95 //! //! \retval NVAPI_INVALID_ARGUMENT hPhysicalGpu is NULL or invalid. Re-enumerate the GPU handles. @@ -1765,6 +1786,8 @@ NVAPI_INTERFACE NvAPI_GetGPUIDfromPhysicalGPU(NvPhysicalGpuHandle hPhysicalGpu, //! //! TCC_SUPPORTED //! +//! MCDM_SUPPORTED +//! //! \since Release: 170 //! //! \retval NVAPI_INVALID_ARGUMENT: pCount is NULL @@ -1789,6 +1812,8 @@ NVAPI_INTERFACE NvAPI_GPU_GetShaderSubPipeCount(NvPhysicalGpuHandle hPhysicalGpu //! //! TCC_SUPPORTED //! +//! MCDM_SUPPORTED +//! //! \retval ::NVAPI_INVALID_ARGUMENT pCount is NULL //! \retval ::NVAPI_OK *pCount is set //! \retval ::NVAPI_NVIDIA_DEVICE_NOT_FOUND no NVIDIA GPU driving a display was found @@ -2075,6 +2100,8 @@ NVAPI_INTERFACE NvAPI_GPU_GetConnectedSLIOutputsWithLidState(NvPhysicalGpuHandle //! //! TCC_SUPPORTED //! +//! MCDM_SUPPORTED +//! //! \since Release: 95 //! //! \retval NVAPI_INVALID_ARGUMENT hPhysicalGpu or pOutputsMask is NULL @@ -2231,6 +2258,8 @@ NVAPI_INTERFACE NvAPI_GPU_ValidateOutputCombination(NvPhysicalGpuHandle hPhysica //! //! TCC_SUPPORTED //! +//! MCDM_SUPPORTED +//! //! \since Release: 90 //! //! \return NVAPI_ERROR or NVAPI_OK @@ -2249,6 +2278,8 @@ NVAPI_INTERFACE NvAPI_GPU_GetFullName(NvPhysicalGpuHandle hPhysicalGpu, NvAPI_Sh //! //! TCC_SUPPORTED //! +//! MCDM_SUPPORTED +//! //! \since Release: 90 //! //! \param DeviceId The internal PCI device identifier for the GPU. @@ -2289,6 +2320,8 @@ typedef enum _NV_GPU_TYPE //! //! TCC_SUPPORTED //! +//! MCDM_SUPPORTED +//! //! \since Release: 173 //! //! \retval NVAPI_INVALID_ARGUMENT hPhysicalGpu @@ -2325,6 +2358,8 @@ typedef enum _NV_GPU_BUS_TYPE //! //! TCC_SUPPORTED //! +//! MCDM_SUPPORTED +//! //! \since Release: 90 //! //! \return This API can return any of the error codes enumerated in #NvAPI_Status. If there are return error codes with @@ -2347,6 +2382,8 @@ NVAPI_INTERFACE NvAPI_GPU_GetBusType(NvPhysicalGpuHandle hPhysicalGpu,NV_GPU_BUS //! //! TCC_SUPPORTED //! +//! MCDM_SUPPORTED +//! //! \since Release: 167 //! //! \retval NVAPI_INVALID_ARGUMENT hPhysicalGpu or pBusId is NULL. @@ -2369,6 +2406,8 @@ NVAPI_INTERFACE NvAPI_GPU_GetBusId(NvPhysicalGpuHandle hPhysicalGpu, NvU32 *pBus //! //! TCC_SUPPORTED //! +//! MCDM_SUPPORTED +//! //! \since Release: 167 //! //! \retval NVAPI_INVALID_ARGUMENT hPhysicalGpu or pBusSlotId is NULL. @@ -2393,6 +2432,8 @@ NVAPI_INTERFACE NvAPI_GPU_GetBusSlotId(NvPhysicalGpuHandle hPhysicalGpu, NvU32 * //! //! TCC_SUPPORTED //! +//! MCDM_SUPPORTED +//! //! \since Release: 90 //! //! \retval NVAPI_INVALID_ARGUMENT hPhysicalGpu or pIRQ is NULL. @@ -2414,6 +2455,8 @@ NVAPI_INTERFACE NvAPI_GPU_GetIRQ(NvPhysicalGpuHandle hPhysicalGpu,NvU32 *pIRQ); //! //! TCC_SUPPORTED //! +//! MCDM_SUPPORTED +//! //! \since Release: 90 //! //! \retval NVAPI_INVALID_ARGUMENT hPhysicalGpu or pBiosRevision is NULL. @@ -2435,6 +2478,8 @@ NVAPI_INTERFACE NvAPI_GPU_GetVbiosRevision(NvPhysicalGpuHandle hPhysicalGpu,NvU3 //! //! TCC_SUPPORTED //! +//! MCDM_SUPPORTED +//! //! \since Release: 90 //! //! \retval NVAPI_INVALID_ARGUMENT hPhysicalGpu or pBiosRevision is NULL @@ -2458,6 +2503,8 @@ NVAPI_INTERFACE NvAPI_GPU_GetVbiosOEMRevision(NvPhysicalGpuHandle hPhysicalGpu,N //! //! TCC_SUPPORTED //! +//! MCDM_SUPPORTED +//! //! \since Release: 90 //! //! \retval NVAPI_INVALID_ARGUMENT hPhysicalGpu is NULL. @@ -2521,6 +2568,8 @@ NVAPI_INTERFACE NvAPI_GPU_GetCurrentAGPRate(NvPhysicalGpuHandle hPhysicalGpu,NvU //! //! TCC_SUPPORTED //! +//! MCDM_SUPPORTED +//! //! \since Release: 90 //! //! \retval NVAPI_INVALID_ARGUMENT pWidth is NULL. @@ -2545,6 +2594,8 @@ NVAPI_INTERFACE NvAPI_GPU_GetCurrentPCIEDownstreamWidth(NvPhysicalGpuHandle hPhy //! //! TCC_SUPPORTED //! +//! MCDM_SUPPORTED +//! //! \since Release: 90 //! //! \retval NVAPI_INVALID_ARGUMENT pSize is NULL @@ -2567,6 +2618,8 @@ NVAPI_INTERFACE NvAPI_GPU_GetPhysicalFrameBufferSize(NvPhysicalGpuHandle hPhysic //! //! TCC_SUPPORTED //! +//! MCDM_SUPPORTED +//! //! \since Release: 90 //! //! \retval NVAPI_INVALID_ARGUMENT pSize is NULL. @@ -2631,6 +2684,8 @@ typedef NV_BOARD_INFO_V1 NV_BOARD_INFO; //! //! TCC_SUPPORTED //! +//! MCDM_SUPPORTED +//! //! \retval ::NVAPI_OK completed request //! \retval ::NVAPI_ERROR miscellaneous error occurred //! \retval ::NVAPI_EXPECTED_PHYSICAL_GPU_HANDLE handle passed is not a physical GPU handle @@ -2656,6 +2711,8 @@ NVAPI_INTERFACE NvAPI_GPU_GetBoardInfo(NvPhysicalGpuHandle hPhysicalGpu, NV_BOAR //! //! TCC_SUPPORTED //! +//! MCDM_SUPPORTED +//! //! \since Release: 100 //! //! \return NVAPI_ERROR or NVAPI_OK @@ -2861,6 +2918,8 @@ typedef NV_GPU_ARCH_INFO_V2 NV_GPU_ARCH_INFO; //! //! //! TCC_SUPPORTED +//! +//! MCDM_SUPPORTED //! \since Release: 85 //! //! \return This API can return any of the error codes enumerated in @@ -3124,6 +3183,8 @@ NVAPI_INTERFACE NvAPI_GPU_WorkstationFeatureQuery(__in NvPhysicalGpuHandle hPhys //! //! TCC_SUPPORTED //! +//! MCDM_SUPPORTED +//! //! \since Release: 175 //! //! \retval ::NVAPI_OK @@ -3291,6 +3352,8 @@ NVAPI_INTERFACE NvAPI_GPU_CudaEnumComputeCapableGpus(__inout NV_COMPUTE_GPU_TOPO //! //! TCC_SUPPORTED //! +//! MCDM_SUPPORTED +//! //! \param [in] hPhysicalGpu GPU selection. //! \param [out] pValue Pointer to a variable to get the tachometer reading //! @@ -3322,6 +3385,8 @@ NVAPI_INTERFACE NvAPI_GPU_GetTachReading(NvPhysicalGpuHandle hPhysicalGPU, NvU32 //! //! TCC_SUPPORTED //! +//! MCDM_SUPPORTED +//! //! \param [in] hPhysicalGpu A handle identifying the physical GPU for which ECC //! status information is to be retrieved. //! \param [out] pECCStatusInfo A pointer to an ECC status structure. @@ -3399,6 +3464,8 @@ typedef struct //! //! TCC_SUPPORTED //! +//! MCDM_SUPPORTED +//! //! \param [in] hPhysicalGpu A handle identifying the physical GPU for //! which ECC error information is to be //! retrieved. @@ -3432,6 +3499,8 @@ NVAPI_INTERFACE NvAPI_GPU_GetECCErrorInfo(NvPhysicalGpuHandle hPhysicalGpu, //! //! TCC_SUPPORTED //! +//! MCDM_SUPPORTED +//! //! \requires Administrator privileges since release 430.39 //! //! \param [in] hPhysicalGpu A handle identifying the physical GPU for @@ -3464,6 +3533,8 @@ NVAPI_INTERFACE NvAPI_GPU_ResetECCErrorInfo(NvPhysicalGpuHandle hPhysicalGpu, Nv //! //! TCC_SUPPORTED //! +//! MCDM_SUPPORTED +//! //! \param [in] hPhysicalGpu A handle identifying the physical GPU for //! which ECC configuration information //! is to be retrieved. @@ -3510,6 +3581,8 @@ NVAPI_INTERFACE NvAPI_GPU_GetECCConfigurationInfo(NvPhysicalGpuHandle hPhysicalG //! //! TCC_SUPPORTED //! +//! MCDM_SUPPORTED +//! //! \requires Administrator privileges since release 430.39 //! //! \param [in] hPhysicalGpu A handle identifying the physical GPU for @@ -3991,6 +4064,8 @@ typedef NV_GPU_VIRTUALIZATION_INFO_V1 NV_GPU_VIRTUALIZATION_INFO; //! //! TCC_SUPPORTED //! +//! MCDM_SUPPORTED +//! //! \since Release: 367 //! //! \param [in,out] pVirtualizationInfo Pointer to NV_GPU_VIRTUALIZATION_INFO structure. @@ -4207,6 +4282,8 @@ typedef NV_LICENSABLE_FEATURES_V4 NV_LICENSABLE_FEATURES; //! //! TCC_SUPPORTED //! +//! MCDM_SUPPORTED +//! //! \param [in] hPhysicalGpu GPU selection //! \param [in,out] pLicensableFeatures Licensable features information. //! @@ -4218,6 +4295,331 @@ typedef NV_LICENSABLE_FEATURES_V4 NV_LICENSABLE_FEATURES; NVAPI_INTERFACE NvAPI_GPU_GetLicensableFeatures(__in NvPhysicalGpuHandle hPhysicalGpu, __inout NV_LICENSABLE_FEATURES *pLicensableFeatures); +#define NVAPI_NVLINK_COUNTER_MAX_TYPES 32 +#define NVAPI_NVLINK_MAX_LINKS 32 + +//! \ingroup nvlink +//! @{ +//! Used in NvAPI_GPU_NVLINK_GetCaps() + +/* caps format is byte_index:bit_mask */ +#define NVAPI_NVLINK_CAPS_SUPPORTED 0x00000001 //!< Set if NVLink is present and supported on this GPU.This field is used for *global* caps only and NOT for per-link caps +#define NVAPI_NVLINK_CAPS_P2P_SUPPORTED 0x00000002 //!< Set if P2P over NVLink is supported on this GPU. +#define NVAPI_NVLINK_CAPS_SYSMEM_ACCESS 0x00000004 //!< Set if sysmem can be accessed over NVLink on this GPU. +#define NVAPI_NVLINK_CAPS_P2P_ATOMICS 0x00000008 //!< Set if P2P atomics are supported over NVLink on this GPU. +#define NVAPI_NVLINK_CAPS_SYSMEM_ATOMICS 0x00000010 //!< Set if sysmem atomic transcations are supported over NVLink on this GPU. +#define NVAPI_NVLINK_CAPS_PEX_TUNNELING 0x00000020 //!< Set if PEX tunneling over NVLink is supported on this GPU. +#define NVAPI_NVLINK_CAPS_SLI_BRIDGE 0x00000040 //!< Set if SLI over NVLink is supported on this GPU. +#define NVAPI_NVLINK_CAPS_SLI_BRIDGE_SENSABLE 0x00000080 //!< This bit is set if capable of sensing SLI bridges. +#define NVAPI_NVLINK_CAPS_POWER_STATE_L0 0x00000100 //!< This bit is set if L0 is a supported power state on this GPU. +#define NVAPI_NVLINK_CAPS_POWER_STATE_L1 0x00000200 //!< This bit is set if L1 is a supported power state on this GPU. +#define NVAPI_NVLINK_CAPS_POWER_STATE_L2 0x00000400 //!< This bit is set if L2 is a supported power state on this GPU. +#define NVAPI_NVLINK_CAPS_POWER_STATE_L3 0x00000800 //!< This bit is set if L3 is a supported power state on this GPU. + +#define NVAPI_NVLINK_CAPS_VALID 0x00001000 //!< Set if this link is supported on this GPU.This field is used for *per-link* caps only and NOT for global caps. + +#define NVAPI_NVLINK_CAPS_NVLINK_VERSION_INVALID (0x00000000) +#define NVAPI_NVLINK_CAPS_NVLINK_VERSION_1_0 (0x00000001) +#define NVAPI_NVLINK_CAPS_NVLINK_VERSION_2_0 (0x00000002) + +#define NVAPI_NVLINK_CAPS_NCI_VERSION_INVALID (0x00000000) +#define NVAPI_NVLINK_CAPS_NCI_VERSION_1_0 (0x00000001) +#define NVAPI_NVLINK_CAPS_NCI_VERSION_2_0 (0x00000002) + +typedef struct +{ + NvU32 version; //!< Version of this structure. Must always be first element in this structure. + NvU32 capsTbl; //!< This is bit field for getting different global caps.The individual bitfields are specified by NVAPI_NVLINK_CAPS_* + NvU8 lowestNvlinkVersion; //!< This field specifies the lowest supported NVLink version for this GPU. + NvU8 highestNvlinkVersion; //!< This field specifies the highest supported NVLink version for this GPU. + NvU8 lowestNciVersion; //!< This field specifies the lowest supported NCI version for this GPU. + NvU8 highestNciVersion; //!< This field specifies the highest supported NCI version for this GPU. + NvU32 linkMask; //!< This field provides a bitfield mask of NVLink links enabled on this GPU. +}NVLINK_GET_CAPS_V1; + +typedef NVLINK_GET_CAPS_V1 NVLINK_GET_CAPS; +#define NVLINK_GET_CAPS_VER1 MAKE_NVAPI_VERSION(NVLINK_GET_CAPS_V1, 1) + +#define NVLINK_GET_CAPS_VER NVLINK_GET_CAPS_VER1 +//! @} +/////////////////////////////////////////////////////////////////////////////// +// +// FUNCTION NAME: NvAPI_GPU_NVLINK_GetCaps +// +//! DESCRIPTION: This function returns the NVLink capabilities supported by the GPU. +//! SUPPORTED OS: Windows 7 and higher +//! +//! +//! \since Release: 361 +//! +//! \param [in] hPhysicalGpu GPU selection +//! +//! \param [in,out] NVLINK_GET_CAPS This structure contains the output parameters. +//! Also need to specify the version. +//! +//! \retval ::NVAPI_INVALID_USER_PRIVILEGE - The caller does not have administrative privileges +//! +//! \return This API can return any of the error codes enumerated in +//! #NvAPI_Status. If there are return error codes with specific +//! meaning for this API, they are listed below. +//! +//! \ingroup nvlink +/////////////////////////////////////////////////////////////////////////////// +NVAPI_INTERFACE NvAPI_GPU_NVLINK_GetCaps(__in NvPhysicalGpuHandle hPhysicalGpu, __inout NVLINK_GET_CAPS *capsParams); + + +//! \ingroup nvlink +//! @{ +//! Used in NvAPI_GPU_NVLINK_GetStatus() + +#define NVAPI_NVLINK_DEVICE_INFO_DEVICE_ID_FLAGS_NONE (0x00000000) +#define NVAPI_NVLINK_DEVICE_INFO_DEVICE_ID_FLAGS_PCI (0x00000001) +#define NVAPI_NVLINK_DEVICE_INFO_DEVICE_ID_FLAGS_UUID (0x00000002) + +typedef enum _NVAPI_NVLINK_DEVICE_INFO_DEVICE_TYPE +{ + NVAPI_NVLINK_DEVICE_INFO_DEVICE_TYPE_EBRIDGE, + NVAPI_NVLINK_DEVICE_INFO_DEVICE_TYPE_NPU, + NVAPI_NVLINK_DEVICE_INFO_DEVICE_TYPE_GPU, + NVAPI_NVLINK_DEVICE_INFO_DEVICE_TYPE_SWITCH, + NVAPI_NVLINK_DEVICE_INFO_DEVICE_TYPE_TEGRA, + NVAPI_NVLINK_DEVICE_INFO_DEVICE_TYPE_NONE, + NVAPI_NVLINK_DEVICE_INFO_DEVICE_UUID_INVALID, +} NVAPI_NVLINK_DEVICE_INFO_DEVICE_TYPE; + +typedef struct +{ + NvU32 deviceIdFlags; //!< ID Flags, Bitmask that specifies which IDs are valid for the GPU. Refer NVAPI_NVLINK_DEVICE_INFO_DEVICE_ID_FLAGS_* for possible values. + //!< If NVAPI_NVLINK_DEVICE_INFO_DEVICE_ID_FLAGS_PCI is set, PCI information is valid. + //!< If NVAPI_NVLINK_DEVICE_INFO_DEVICE_ID_FLAGS_UUID is set, UUID is valid. + NvU16 domain; //!< domain, bus, device, function, pciDeviceId : PCI information for the GPU. + NvU16 bus; + NvU16 device; + NvU16 function; + NvU32 pciDeviceId; + NvU64 deviceType; //!< GPU Type. See NVAPI_NVLINK_DEVICE_INFO_DEVICE_TYPE_* for possible values. + NvU8 deviceUUID[16]; //!< GPU UUID +}NVLINK_DEVICE_INFO_V1; + +typedef enum _NVAPI_NVLINK_STATUS_LINK_STATE +{ + NVAPI_NVLINK_STATUS_LINK_STATE_UNKNOWN, + NVAPI_NVLINK_STATUS_LINK_STATE_INIT, + NVAPI_NVLINK_STATUS_LINK_STATE_HWCFG, + NVAPI_NVLINK_STATUS_LINK_STATE_SWCFG, + NVAPI_NVLINK_STATUS_LINK_STATE_ACTIVE, + NVAPI_NVLINK_STATUS_LINK_STATE_FAULT, + NVAPI_NVLINK_STATUS_LINK_STATE_RECOVERY, + NVAPI_NVLINK_STATUS_LINK_STATE_RECOVERY_AC, + NVAPI_NVLINK_STATUS_LINK_STATE_RECOVERY_AX, + NVAPI_NVLINK_STATUS_LINK_STATE_INVALID = 0xFFFFFFFF, +}NVAPI_NVLINK_STATUS_LINK_STATE; + +typedef enum _NVAPI_NVLINK_STATUS_SUBLINK_RX_STATE +{ + NVAPI_NVLINK_STATUS_SUBLINK_RX_STATE_UNKNOWN, + NVAPI_NVLINK_STATUS_SUBLINK_RX_STATE_HIGH_SPEED_1, + NVAPI_NVLINK_STATUS_SUBLINK_RX_STATE_LOW_POWER, + NVAPI_NVLINK_STATUS_SUBLINK_RX_STATE_TRAINING, + NVAPI_NVLINK_STATUS_SUBLINK_RX_STATE_SAFE_MODE, + NVAPI_NVLINK_STATUS_SUBLINK_RX_STATE_OFF, + NVAPI_NVLINK_STATUS_SUBLINK_RX_STATE_TEST, + NVAPI_NVLINK_STATUS_SUBLINK_RX_STATE_FAULT, + NVAPI_NVLINK_STATUS_SUBLINK_RX_STATE_INVALID = 0xFF, +}NVAPI_NVLINK_STATUS_SUBLINK_RX_STATE; + +typedef enum _NVAPI_NVLINK_STATUS_SUBLINK_TX_STATE +{ + NVAPI_NVLINK_STATUS_SUBLINK_TX_STATE_UNKNOWN, + NVAPI_NVLINK_STATUS_SUBLINK_TX_STATE_HIGH_SPEED_1, + NVAPI_NVLINK_STATUS_SUBLINK_TX_STATE_LOW_POWER, + NVAPI_NVLINK_STATUS_SUBLINK_TX_STATE_TRAINING, + NVAPI_NVLINK_STATUS_SUBLINK_TX_STATE_SAFE_MODE, + NVAPI_NVLINK_STATUS_SUBLINK_TX_STATE_OFF, + NVAPI_NVLINK_STATUS_SUBLINK_TX_STATE_TEST, + NVAPI_NVLINK_STATUS_SUBLINK_TX_STATE_FAULT, + + NVAPI_NVLINK_STATUS_SUBLINK_TX_STATE_INVALID= 0xFF, +} NVAPI_NVLINK_STATUS_SUBLINK_TX_STATE; + + +#define NVAPI_NVLINK_STATUS_PHY_NVHS (0x00000001) +#define NVAPI_NVLINK_STATUS_PHY_GRS (0x00000002) +#define NVAPI_NVLINK_STATUS_PHY_INVALID (0x000000FF) + +#define NVAPI_NVLINK_STATUS_NVLINK_VERSION_1_0 (0x00000001) +#define NVAPI_NVLINK_STATUS_NVLINK_VERSION_2_0 (0x00000002) +#define NVAPI_NVLINK_STATUS_NVLINK_VERSION_INVALID (0x000000FF) + +#define NVAPI_NVLINK_STATUS_NCI_VERSION_1_0 (0x00000001) +#define NVAPI_NVLINK_STATUS_NCI_VERSION_2_0 (0x00000002) +#define NVAPI_NVLINK_STATUS_NCI_VERSION_INVALID (0x000000FF) + +#define NVAPI_NVLINK_STATUS_NVHS_VERSION_1_0 (0x00000001) +#define NVAPI_NVLINK_STATUS_NVHS_VERSION_INVALID (0x000000FF) + +#define NVAPI_NVLINK_STATUS_GRS_VERSION_1_0 (0x00000001) +#define NVAPI_NVLINK_STATUS_GRS_VERSION_INVALID (0x000000FF) + +#define NVAPI_NVLINK_STATUS_CONNECTED_TRUE (0x00000001) +#define NVAPI_NVLINK_STATUS_CONNECTED_FALSE (0x00000000) + +#define NVAPI_NVLINK_STATUS_LOOP_PROPERTY_LOOPBACK (0x00000001) +#define NVAPI_NVLINK_STATUS_LOOP_PROPERTY_LOOPOUT (0x00000002) +#define NVAPI_NVLINK_STATUS_LOOP_PROPERTY_NONE (0x00000000) + +#define NVAPI_NVLINK_STATUS_REMOTE_LINK_NUMBER_INVALID (0x000000FF) + +#define NVAPI_NVLINK_REFCLK_TYPE_INVALID (0x00) +#define NVAPI_NVLINK_REFCLK_TYPE_NVHS (0x01) +#define NVAPI_NVLINK_REFCLK_TYPE_PEX (0x02) + + +typedef struct +{ + NvU32 capsTbl; //!< This is bit field for getting different global caps.The individual bitfields are specified by NVAPI_NVLINK_CAPS_*. + NvU8 phyType; //!< This field specifies the type of PHY (NVHS or GRS) being used for this link. + NvU8 subLinkWidth; //!< This field specifies the no. of lanes per sublink. + NvU32 linkState; //!< This field specifies the current state of the link.See NVAPI_NVLINK_GET_NVLINK_STATUS_LINK_STATE_* for possible values. + NvU8 rxSublinkStatus; //!< This field specifies the current state of RX sublink.See NVAPI_NVLINK_GET_NVLINK_STATUS_SUBLINK_RX_STATE_* for possible values. + NvU8 txSublinkStatus; //!< This field specifies the current state of TX sublink.See NVAPI_NVLINK_GET_NVLINK_STATUS_SUBLINK_TX_STATE_* for possible values. + NvU8 nvlinkVersion; //!< This field specifies the NVLink version supported by the link. + NvU8 nciVersion; //!< This field specifies the NCI version supported by the link. + NvU8 phyVersion; //!< This field specifies the version of PHY being used by the link. + NvU32 nvlinkCommonClockSpeedMhz; //!< This field gives the value of nvlink common clock in MHz. + NvU32 nvlinkRefClkSpeedMhz; //!< This field gives the value of nvlink refclk clock in MHz. + NvU8 nvlinkRefClkType; //!< This field specifies whether refclk is taken from NVHS reflck or PEX refclk for the current GPU.See NVAPI_NVLINK_REFCLK_TYPE_INVALID* for possible values. + NvU32 nvlinkLinkClockMhz; //!< This field gives the actual clock/speed at which links is running in MHz. + NvU32 connected:1 ; //!< This field specifies if any device is connected on the other end of the link. + NvU32 reserved:31; //!< Reserved for future use. + NvU8 loopProperty; //!< This field specifies if the link is a loopback/loopout link. See NVAPI_NVLINK_STATUS_LOOP_PROPERTY_* for possible values. + NvU8 remoteDeviceLinkNumber; //!< This field specifies the link number on the remote end of the link. + NVLINK_DEVICE_INFO_V1 remoteDeviceInfo; //!< This field stores the GPU information for the remote end of the link +}NVLINK_LINK_STATUS_INFO_V1; + +typedef struct +{ + NvU32 capsTbl; //!< This is bit field for getting different global caps.The individual bitfields are specified by NVAPI_NVLINK_CAPS_*. + NvU8 phyType; //!< This field specifies the type of PHY (NVHS or GRS) being used for this link. + NvU8 subLinkWidth; //!< This field specifies the no. of lanes per sublink. + NvU32 linkState; //!< This field specifies the current state of the link.See NVAPI_NVLINK_GET_NVLINK_STATUS_LINK_STATE_* for possible values. + NvU8 rxSublinkStatus; //!< This field specifies the current state of RX sublink.See NVAPI_NVLINK_GET_NVLINK_STATUS_SUBLINK_RX_STATE_* for possible values. + NvU8 txSublinkStatus; //!< This field specifies the current state of TX sublink.See NVAPI_NVLINK_GET_NVLINK_STATUS_SUBLINK_TX_STATE_* for possible values. + NvU8 nvlinkVersion; //!< This field specifies the NVLink version supported by the link. + NvU8 nciVersion; //!< This field specifies the NCI version supported by the link. + NvU8 phyVersion; //!< This field specifies the version of PHY being used by the link. + NvU32 nvlinkCommonClockSpeedMhz; //!< This field gives the value of nvlink common clock in MHz. + NvU32 nvlinkRefClkSpeedMhz; //!< This field gives the value of nvlink refclk clock in MHz. + NvU8 nvlinkRefClkType; //!< This field specifies whether refclk is taken from NVHS reflck or PEX refclk for the current GPU.See NVAPI_NVLINK_REFCLK_TYPE_INVALID* for possible values. + NvU32 nvlinkLinkClockMhz; //!< This field gives the actual clock/speed at which links is running in MHz. + NvU32 connected:1 ; //!< This field specifies if any device is connected on the other end of the link. + NvU32 reserved:31; //!< Reserved for future use. + NvU8 loopProperty; //!< This field specifies if the link is a loopback/loopout link. See NVAPI_NVLINK_STATUS_LOOP_PROPERTY_* for possible values. + NvU8 remoteDeviceLinkNumber; //!< This field specifies the link number on the remote end of the link. + NVLINK_DEVICE_INFO_V1 remoteDeviceInfo; //!< This field stores the device information for the remote end of the link + NvU8 localDeviceLinkNumber; //!< This field specifies the link number on the local end of the link. + NVLINK_DEVICE_INFO_V1 localDeviceInfo; //!< This field stores the device information for the local end of the link. + NvU32 nvlinkLineRateMbps; //!< Bit rate at which bits toggle on wires in megabits per second. + NvU32 reservedEx[8]; //!< Reserved for future use to avoid versioning. +}NVLINK_LINK_STATUS_INFO_V2; + +typedef struct +{ + NvU32 version; //!< Version of this structure. Must always be first element in this structure. + NvU32 linkMask; //!< This parameter specifies for which links we want the status. + NVLINK_LINK_STATUS_INFO_V1 linkInfo[NVAPI_NVLINK_MAX_LINKS]; //!< This structure stores the per-link status of different NVLink parameters. The link is identified by the index. +}NVLINK_GET_STATUS_V1; + +typedef struct +{ + NvU32 version; //!< Version of this structure. Must always be first element in this structure. + NvU32 linkMask; //!< This parameter specifies for which links we want the status. + NVLINK_LINK_STATUS_INFO_V2 linkInfo[NVAPI_NVLINK_MAX_LINKS]; //!< This structure stores the per-link status of different NVLink parameters. The link is identified by the index. +}NVLINK_GET_STATUS_V2; + + +typedef NVLINK_GET_STATUS_V2 NVLINK_GET_STATUS; +#define NVLINK_GET_STATUS_VER1 MAKE_NVAPI_VERSION(NVLINK_GET_STATUS_V1, 1) +#define NVLINK_GET_STATUS_VER2 MAKE_NVAPI_VERSION(NVLINK_GET_STATUS_V2, 2) + +#define NVLINK_GET_STATUS_VER NVLINK_GET_STATUS_VER2 +//! @} +/////////////////////////////////////////////////////////////////////////////// +// +// FUNCTION NAME: NvAPI_GPU_NVLINK_GetStatus +// +//! DESCRIPTION: This function returns the NVLink status. +//! SUPPORTED OS: Windows 7 and higher +//! +//! +//! \since Release: 361 +//! +//! \param [in] hPhysicalGpu GPU selection +//! +//! \param [in,out] NVLINK_GET_STATUS This structure contains the input and output parameters. +//! linkMask is the input param while others are output parameters. +//! Also need to specify the version. +//! +//! \retval ::NVAPI_INVALID_USER_PRIVILEGE - The caller does not have administrative privileges +//! +//! \return This API can return any of the error codes enumerated in +//! #NvAPI_Status. If there are return error codes with specific +//! meaning for this API, they are listed below. +//! +//! \ingroup nvlink +/////////////////////////////////////////////////////////////////////////////// +NVAPI_INTERFACE NvAPI_GPU_NVLINK_GetStatus(__in NvPhysicalGpuHandle hPhysicalGpu, __inout NVLINK_GET_STATUS* statusParams); + + +typedef struct _NV_GPU_INFO_V1 +{ + NvU32 version; //!< Structure Version. + NvU32 bIsExternalGpu:1; //!< This flag is set for external GPU. + NvU32 reserved:31; //!< Reserved for future use +} NV_GPU_INFO_V1; + +typedef struct _NV_GPU_INFO_V2 +{ + NvU32 version; //!< Structure Version. + NvU32 bIsExternalGpu:1; //!< This flag is set for external GPU. + NvU32 reserved0:31; //!< Reserved for future use + NvU64 reserved1; //!< Reserved for future use + NvU32 rayTracingCores; //!< Number of "Ray Tracing Cores" supported by the GPU. + NvU32 tensorCores; //!< Number of "Tensor Cores" supported by the GPU. + NvU32 reserved2[14]; //!< Reserved for future use. +} NV_GPU_INFO_V2; + +#define NV_GPU_INFO_VER1 MAKE_NVAPI_VERSION(NV_GPU_INFO_V1, 1) +#define NV_GPU_INFO_VER2 MAKE_NVAPI_VERSION(NV_GPU_INFO_V2, 2) +#define NV_GPU_INFO_VER NV_GPU_INFO_VER2 +typedef NV_GPU_INFO_V2 NV_GPU_INFO; + +/////////////////////////////////////////////////////////////////////////////// +// +// FUNCTION NAME: NvAPI_GPU_GetGPUInfo +// +//! DESCRIPTION: This API will return NVIDIA GPU related information. +//! +//! SUPPORTED OS: Windows 7 and higher +//! +//! +//! TCC_SUPPORTED +//! +//! MCDM_SUPPORTED +//! +//! \since Release: 400 +//! +//! \param [in,out] pGpuInfo - This structure will be filled with required information. +//! +//! \return This API can return any of the error codes enumerated in +//! #NvAPI_Status. If there are return error codes with specific +//! meaning for this API, they are listed below. +//! +//! \ingroup gpu +/////////////////////////////////////////////////////////////////////////////// +NVAPI_INTERFACE NvAPI_GPU_GetGPUInfo(__in NvPhysicalGpuHandle hPhysicalGpu, __inout NV_GPU_INFO *pGpuInfo); + + typedef struct _NV_GPU_VR_READY_V1 { @@ -4241,6 +4643,8 @@ typedef NV_GPU_VR_READY_V1 NV_GPU_VR_READY; //! //! TCC_SUPPORTED //! +//! MCDM_SUPPORTED +//! //! \since Release: 465 //! //! \param [in,out] pGpuVrReadyData - This structure will be filled with required information. @@ -4253,6 +4657,65 @@ typedef NV_GPU_VR_READY_V1 NV_GPU_VR_READY; /////////////////////////////////////////////////////////////////////////////// NVAPI_INTERFACE NvAPI_GPU_GetVRReadyData(__in NvPhysicalGpuHandle hPhysicalGpu, __inout NV_GPU_VR_READY *pGpuVrReadyData); + +typedef enum _NV_ADAPTER_TYPE +{ + NV_ADAPTER_TYPE_UNKNOWN = 0x0, + NV_ADAPTER_TYPE_WDDM = NV_BIT(0), //pEDID set to NULL, +//! to get the size of the EDID buffer in pEdidParams->sizeOfEDID. +//! Second Pass: Allocate memory for the EDID buffer of the size - pEdidParams->sizeOfEDID, +//! and call the API again to get the EDID buffer populated. +//! +//! +//! \param [in] displayId - NVIDIA Display ID +//! \param [inout] pEdidParams - Pointer to the structure that contains - pointer to EDID buffer and its size +//! \param [inout] pFlag - The type of EDID to be retrieved (IN). +//! To only retrieve the EDID type, the user should send pEdidParams->pEDID as NULL and +//! pEdidParams->sizeOfEDID as 0. +//! +//! SUPPORTED OS: Windows 7 and higher +//! +//! +//! \since Release: 400 +//! +//! \return This API can return any of the error codes enumerated in #NvAPI_Status. +//! If there are return error codes with specific meaning for this API, they are listed below. +//! NVAPI_INSUFFICIENT_BUFFER: Reallocate buffer with pEdidParams->sizeOfEDID and call again to get complete data. +//! In this case pEdidParams->pEDID contains undefined data. +//! This error occurs only when pEdidParams->pEDID is present. +//! \endcode +//! \ingroup dispcontrol +/////////////////////////////////////////////////////////////////////////////// +NVAPI_INTERFACE NvAPI_DISP_GetEdidData(__in NvU32 displayId, __inout NV_EDID_DATA *pEdidParams, __inout NV_EDID_FLAG *pFlag); +//! @} + typedef struct _NV_GET_ADAPTIVE_SYNC_DATA_V1 { NvU32 version ; //!< [in] structure version @@ -8518,6 +9067,89 @@ NVAPI_INTERFACE NvAPI_DISP_AcquireDedicatedDisplay(__in NvU32 displayId, __inout NVAPI_INTERFACE NvAPI_DISP_ReleaseDedicatedDisplay(__in NvU32 displayId); #endif // defined(__cplusplus) +//! SUPPORTED OS: Windows 11 and higher +//! +#if defined(__cplusplus) + +typedef struct _NV_MANAGED_DEDICATED_DISPLAY_METADATA +{ + NvU32 version; //!< [in] Version of this structure. + NvU32 displayId; //!< [in] DisplayId to identify the display connector the metadata operation is requested for. + NvU32 bSetPosition : 1; //!< [in] Set call: 1 in case the information in variables/fields "positionX" and "positionY" should be stored as metadata. 0 otherwise. + NvU32 bRemovePosition : 1; //!< [in] Set call: 1 in case the stored positionX and positionY metadata should be set to 'not defined', N/A. 0 otherwise. + NvU32 bPositionIsAvailable : 1; //!< [out] Query call: 1 in case the information in variables/fields "positionX" and "positionY" is valid (has been set before). 0 otherwise. + NvU32 bSetName : 1; //!< [in] Set call: 1 in case the information in variable/field "name" should be stored as metadata. 0 otherwise. + NvU32 bRemoveName : 1; //!< [in] Set call: 1 in case the stored name metadata should be set to 'not defined',N/A. 0 otherwise. + NvU32 bNameIsAvailable : 1; //!< [out] Query call: 1 in case the information in variable/field "name" is valid (has been set before). 0 otherwise. + NvU32 reserved : 26; //!< [in][out] Reserved for future use without adding versioning. + NvS32 positionX; //!< [in][out] Metadata for the virtual horizontal position for the display connector specified by displayId. + NvS32 positionY; //!< [in][out] Metadata for the virtual vertical position for the display connector specified by displayId. + NvAPI_ShortString name; //!< [in][out] Metadata for the virtual name of for the display connector specified by displayId. + //!< Valid characters are in the range of 32 ' ' (space) to 126 '~' (both included). +} NV_MANAGED_DEDICATED_DISPLAY_METADATA_V1; + +#define NV_MANAGED_DEDICATED_DISPLAY_METADATA_VER1 MAKE_NVAPI_VERSION(NV_MANAGED_DEDICATED_DISPLAY_METADATA_V1,1) +#define NV_MANAGED_DEDICATED_DISPLAY_METADATA_VER NV_MANAGED_DEDICATED_DISPLAY_METADATA_VER1 + +typedef NV_MANAGED_DEDICATED_DISPLAY_METADATA_V1 NV_MANAGED_DEDICATED_DISPLAY_METADATA; + +/////////////////////////////////////////////////////////////////////////////// +// +// FUNCTION NAME: NvAPI_DISP_GetNvManagedDedicatedDisplayMetadata +// +//! DESCRIPTION: This API returns metadata which has been set for the display connector in question. +//! Main use case would be to query the data for an Nvidia managed dedicated display. +//! The function will work for any valid displayId though. +//! +//! \since Release: 550 +//! +//! \param [in/out] pDedicatedDisplayMetadata Data structure containing input and output data. +//! +//! \retval ::NVAPI_OK The call succeeded. +//! \retval ::NVAPI_ERROR The call failed. +//! \retval ::NVAPI_NO_IMPLEMENTATION The API is not implemented in current driver. +//! \retval ::NVAPI_NOT_SUPPORTED The API is not supported on the current operating system or gpu. +//! \retval ::NVAPI_OUT_OF_MEMORY There wasn't sufficient memory to complete the call. +//! \retval ::NVAPI_INVALID_POINTER An invalid pointer was passed as an argument. +//! \retval ::NVAPI_API_NOT_INITIALIZED NvAPI was not initialized. +//! \retval ::NVAPI_INCOMPATIBLE_STRUCT_VERSION The version of the NV_MANAGED_DEDICATED_DISPLAY_METADATA structure is invalid. +//! +//! \ingroup gpu +/////////////////////////////////////////////////////////////////////////////// +NVAPI_INTERFACE NvAPI_DISP_GetNvManagedDedicatedDisplayMetadata(__inout NV_MANAGED_DEDICATED_DISPLAY_METADATA* pDedicatedDisplayMetadata); +#endif // defined(__cplusplus) + +//! SUPPORTED OS: Windows 11 and higher +//! +#if defined(__cplusplus) +/////////////////////////////////////////////////////////////////////////////// +// +// FUNCTION NAME: NvAPI_DISP_SetNvManagedDedicatedDisplayMetadata +// +//! DESCRIPTION: This API allows to set metadata for the display connector in question. +//! Main use case would be to set the data for an Nvidia managed dedicated display. +//! The function will work for any valid displayId though. +//! +//! \since Release: 550 +//! +//! \param [in/out] pDedicatedDisplayMetadata Data structure containing input and output data. +//! +//! \retval ::NVAPI_OK The call succeeded. +//! \retval ::NVAPI_ERROR The call failed. +//! \retval ::NVAPI_NO_IMPLEMENTATION The API is not implemented in current driver. +//! \retval ::NVAPI_NOT_SUPPORTED The API is not supported on the current operating system or gpu. +//! \retval ::NVAPI_OUT_OF_MEMORY There wasn't sufficient memory to complete the call. +//! \retval ::NVAPI_INVALID_POINTER An invalid pointer was passed as an argument. +//! \retval ::NVAPI_API_NOT_INITIALIZED NvAPI was not initialized. +//! \retval ::NVAPI_INCOMPATIBLE_STRUCT_VERSION The version of the NV_MANAGED_DEDICATED_DISPLAY_METADATA structure is invalid. +//! \retval ::NVAPI_INVALID_USER_PRIVILEGE The caller doesn't have the required administrator privileges to access this API. +//! \retval ::NVAPI_INVALID_ARGUMENT Characters in pDedicatedDisplayMetadata->name are out of the allowed range. +//! +//! \ingroup gpu +/////////////////////////////////////////////////////////////////////////////// +NVAPI_INTERFACE NvAPI_DISP_SetNvManagedDedicatedDisplayMetadata(__inout NV_MANAGED_DEDICATED_DISPLAY_METADATA* pDedicatedDisplayMetadata); +#endif // defined(__cplusplus) + #if defined (_WINNT_) @@ -9885,6 +10517,8 @@ NVAPI_INTERFACE NvAPI_GSync_GetTopology(__in NvGSyncDeviceHandle hNvGSyncDevice, //! \retval ::NVAPI_INVALID_SYNC_TOPOLOGY 1.If any mosaic grid is partial. //! 2.If timing(HVisible/VVisible/refreshRate) applied of any display is different. //! 3.If There is a across GPU mosaic grid in system and that is not a part of pGsyncDisplays. +//! \retval ::NVAPI_INVALID_USER_PRIVILEGE The application will require Administrator privileges to access this API. +//! The application can be elevated to a higher permission level by selecting "Run as Administrator". //! //! \ingroup gsyncapi /////////////////////////////////////////////////////////////////////////////// @@ -10022,7 +10656,8 @@ NVAPI_INTERFACE NvAPI_GSync_GetControlParameters(__in NvGSyncDeviceHandle hNvGSy //! If there are return error codes with specific meaning for this API, they are listed below. //! \retval ::NVAPI_INVALID_ARGUMENT hNvGSyncDevice is NULL. //! \retval ::NVAPI_NVIDIA_DEVICE_NOT_FOUND The queried Graphics system does not have any Sync Device. -//! \retval ::NVAPI_SYNC_MASTER_NOT_FOUND Control Parameters can only be set if there is a Sync Master enabled on the Gsync card. +//! \retval ::NVAPI_INVALID_USER_PRIVILEGE The application will require Administrator privileges to access this API. +//! The application can be elevated to a higher permission level by selecting "Run as Administrator". //! //! \ingroup gsyncapi /////////////////////////////////////////////////////////////////////////////// @@ -15681,6 +16316,35 @@ NVAPI_INTERFACE NvAPI_D3D_ImplicitSLIControl(__in IMPLICIT_SLI_CONTROL implicitS #endif //defined (__cplusplus) && ( defined(_D3D9_H_) || defined(__d3d10_h__) || defined(__d3d10_1_h__) ||defined(__d3d11_h__) ) + +#if defined (__cplusplus) && defined(__d3d12_h__) +/////////////////////////////////////////////////////////////////////////////// +// +// FUNCTION NAME: NvAPI_D3D12_GetNeedsAppFPBlendClamping +// +//! \code +//! DESCRIPTION: This function returns whether the application needs to do FP blend clamping itself +//! +//! \param [in] pDevice Current d3d device +//! \param [out] pAppClampNeeded If true, app needs to clamp. If false, HW does the clamping +//! +//! \return This API can return any of the error codes enumerated in +//! #NvAPI_Status. If there are return error codes with specific +//! meaning for this API, they are listed below. +//! +//! \since Release: 375 +//! +//! SUPPORTED OS: Windows 10 +//! +//! \endcode +//! \ingroup dx +/////////////////////////////////////////////////////////////////////////////// + +NVAPI_INTERFACE NvAPI_D3D12_GetNeedsAppFPBlendClamping(__in ID3D12Device *pDevice, + __out bool *pAppClampNeeded); + +#endif //defined(__cplusplus) && defined(__d3d12_h__) + //! SUPPORTED OS: Windows 10 //! @@ -17074,7 +17738,8 @@ typedef NV_GET_SLEEP_STATUS_PARAMS_V1 NV_GET_SLEEP_STATUS_PARAMS; //! Note that it may not always reflect the previously requested sleep mode, //! as the feature may not be available on the platform, or the setting has //! been overridden by the control panel, for example. -//! bFsVrr indicates fullscreen GSYNC or GSYNC Compatible mode. +//! bFsVrr indicates fullscreen GSYNC or GSYNC Compatible mode. It is valid +//! only when the application is in the foreground. //! bCplVsyncOn indicates Control Panel VSYNC ON override. //! //! \since Release: 455 @@ -17311,7 +17976,8 @@ typedef struct _NV_LATENCY_MARKER_PARAMS NvU32 version; //!< (IN) Structure version NvU64 frameID; NV_LATENCY_MARKER_TYPE markerType; - NvU8 rsvd[64]; + NvU64 rsvd0; + NvU8 rsvd[56]; } NV_LATENCY_MARKER_PARAMS_V1; typedef NV_LATENCY_MARKER_PARAMS_V1 NV_LATENCY_MARKER_PARAMS; @@ -17351,14 +18017,24 @@ typedef NV_LATENCY_MARKER_PARAMS_V1 NV_LATENCY_MARKER_PARAMS; NVAPI_INTERFACE NvAPI_D3D_SetLatencyMarker(__in IUnknown *pDev, __in NV_LATENCY_MARKER_PARAMS* pSetLatencyMarkerParams); #endif //defined(__cplusplus) && (defined(_D3D9_H_) || defined(__d3d10_h__) || defined(__d3d10_1_h__) || defined(__d3d11_h__) || defined(__d3d12_h__)) +//! SUPPORTED OS: Windows 10 and higher +//! //! Used in NvAPI_D3D12_SetAsyncFrameMarker //! \ingroup dx -typedef NV_LATENCY_MARKER_PARAMS_V1 NV_ASYNC_FRAME_MARKER_PARAMS_V1; -typedef NV_ASYNC_FRAME_MARKER_PARAMS_V1 NV_ASYNC_FRAME_MARKER_PARAMS; -#define NV_ASYNC_FRAME_MARKER_PARAMS_VER1 NV_LATENCY_MARKER_PARAMS_VER1 -#define NV_ASYNC_FRAME_MARKER_PARAMS_VER NV_LATENCY_MARKER_PARAMS_VER1 - -#if defined(__cplusplus) && (defined(__d3d12_h__)) +typedef struct _NV_ASYNC_FRAME_MARKER_PARAMS_V1 +{ + NvU32 version; //!< (IN) Structure version + NvU64 frameID; + NV_LATENCY_MARKER_TYPE markerType; + NvU64 presentFrameID; + NvU8 rsvd[56]; +} NV_ASYNC_FRAME_MARKER_PARAMS_V1; + +typedef NV_ASYNC_FRAME_MARKER_PARAMS_V1 NV_ASYNC_FRAME_MARKER_PARAMS; +#define NV_ASYNC_FRAME_MARKER_PARAMS_VER1 MAKE_NVAPI_VERSION(NV_ASYNC_FRAME_MARKER_PARAMS_V1, 1) +#define NV_ASYNC_FRAME_MARKER_PARAMS_VER NV_ASYNC_FRAME_MARKER_PARAMS_VER1 + +#if defined(__cplusplus) && (defined(__d3d12_h__)) /////////////////////////////////////////////////////////////////////////////// // // FUNCTION NAME: NvAPI_D3D12_SetAsyncFrameMarker @@ -17387,6 +18063,7 @@ typedef enum { OUT_OF_BAND_RENDER = 0, OUT_OF_BAND_PRESENT = 1, + OUT_OF_BAND_IGNORE = 2, } NV_OUT_OF_BAND_CQ_TYPE; #if defined(__cplusplus) && defined(__d3d12_h__) @@ -17412,6 +18089,26 @@ NVAPI_INTERFACE NvAPI_D3D12_NotifyOutOfBandCommandQueue(__in ID3D12CommandQueue #endif //defined(__cplusplus) && defined(__d3d12_h__)) +#if defined(__cplusplus) && defined(__d3d12_h__) +/////////////////////////////////////////////////////////////////////////////// +// +// FUNCTION NAME: NvAPI_D3D12_SetCreateCommandQueueLowLatencyHint +// +//! DESCRIPTION: Reserved call. +//! +//! \since Release: 530 +//! \param [in] pDevice The creating device +//! SUPPORTED OS: Windows 10 and higher +//! +//! +//! \return This API can return any of the error codes enumerated in #NvAPI_Status. +//! If there are return error codes with specific meaning for this API, they are listed below. +//! +//! \ingroup dx +/////////////////////////////////////////////////////////////////////////////// +NVAPI_INTERFACE NvAPI_D3D12_SetCreateCommandQueueLowLatencyHint(__in ID3D12Device *pDevice); +#endif //defined(__cplusplus) && defined(__d3d12_h__)) + #if defined (__cplusplus) && defined(__d3d12_h__) // Experimental API for internal use. DO NOT USE! @@ -17467,6 +18164,9 @@ NVAPI_INTERFACE NvAPI_D3D12_LaunchCubinShader(__in ID3D12GraphicsCommandList* NVAPI_INTERFACE NvAPI_D3D12_DestroyCubinComputeShader(__in ID3D12Device* pDevice, __in NVDX_ObjectHandle hShader); +#endif //defined(__cplusplus) && defined(__d3d12_h__) + +#if defined(__d3d12_h__) // Experimental API for internal use. DO NOT USE! //! SUPPORTED OS: Windows 10 and higher //! @@ -17537,6 +18237,28 @@ NVAPI_INTERFACE NvAPI_D3D12_LaunchCuKernelChain(__in ID3D12GraphicsCommandList* __in const NVAPI_CU_KERNEL_LAUNCH_PARAMS* pKernels, __in NvU32 numKernels); +// Experimental API for internal use. DO NOT USE! +//! SUPPORTED OS: Windows 10 and higher +//! + +typedef struct _NVAPI_CU_KERNEL_LAUNCH_PARAMS_EX +{ + NVDX_ObjectHandle hFunction; + NVAPI_DIM3 gridDim; + NVAPI_DIM3 blockDim; + NvU32 dynSharedMemBytes; + + // either pParams/paramsSize is used or kernelParams is used + void const * pParams; + NvU32 paramSize; + void **kernelParams; +} NVAPI_CU_KERNEL_LAUNCH_PARAMS_EX; + +NVAPI_INTERFACE NvAPI_D3D12_LaunchCuKernelChainEx(__in ID3D12GraphicsCommandList* pCommandList, + __in const NVAPI_CU_KERNEL_LAUNCH_PARAMS_EX* pKernels, + __in NvU32 numKernels); + + // Experimental API for internal use. DO NOT USE! //! SUPPORTED OS: Windows 10 and higher //! @@ -17682,6 +18404,17 @@ typedef enum _NVAPI_D3D12_RAYTRACING_OPACITY_MICROMAP_CAPS NVAPI_D3D12_RAYTRACING_OPACITY_MICROMAP_CAP_STANDARD = NV_BIT(0) //!< Standard Opacity Micromap support is available } NVAPI_D3D12_RAYTRACING_OPACITY_MICROMAP_CAPS; +//! Flags specifying raytracing Displacement Micromap support. +//! Additional flags will be added as support becomes available. +//! +//! \ingroup dx +typedef enum _NVAPI_D3D12_RAYTRACING_DISPLACEMENT_MICROMAP_CAPS +{ + NVAPI_D3D12_RAYTRACING_DISPLACEMENT_MICROMAP_CAP_NONE = 0x0, //!< Displacement Micromap support is not available. + //!< The application must not attempt to use any DMM entrypoints or flags. + NVAPI_D3D12_RAYTRACING_DISPLACEMENT_MICROMAP_CAP_STANDARD = NV_BIT(0) //!< Standard Displacement Micromap support is available +} NVAPI_D3D12_RAYTRACING_DISPLACEMENT_MICROMAP_CAPS; + //! List of Raytracing CAPS types that can be queried. //! //! \ingroup dx @@ -17689,6 +18422,7 @@ typedef enum _NVAPI_D3D12_RAYTRACING_CAPS_TYPE { NVAPI_D3D12_RAYTRACING_CAPS_TYPE_THREAD_REORDERING = 0, NVAPI_D3D12_RAYTRACING_CAPS_TYPE_OPACITY_MICROMAP = 1, + NVAPI_D3D12_RAYTRACING_CAPS_TYPE_DISPLACEMENT_MICROMAP = 2, NVAPI_D3D12_RAYTRACING_CAPS_TYPE_INVALID = -1 } NVAPI_D3D12_RAYTRACING_CAPS_TYPE; @@ -17724,6 +18458,283 @@ NVAPI_INTERFACE NvAPI_D3D12_GetRaytracingCaps( __in size_t dataSize); #endif // defined(__cplusplus) && defined(__d3d12_h__) +#if defined(__cplusplus) && defined(__d3d12_h__) && defined(__ID3D12Device5_INTERFACE_DEFINED__) && defined(__ID3D12GraphicsCommandList4_INTERFACE_DEFINED__) + +//! Flags specifying validation behaviour for raytracing operations. +//! \ingroup dx +//! See NvAPI_D3D12_EnableRaytracingValidation +typedef enum _NVAPI_D3D12_RAYTRACING_VALIDATION_FLAGS +{ + NVAPI_D3D12_RAYTRACING_VALIDATION_FLAG_NONE = 0x0, //!< No validation flags. +} NVAPI_D3D12_RAYTRACING_VALIDATION_FLAGS; + +/////////////////////////////////////////////////////////////////////////////// +// +// FUNCTION NAME: NvAPI_D3D12_EnableRaytracingValidation +// +//! DESCRIPTION: Enable raytracing validation for a device. +//! This function must be called before any other raytracing-related function +//! is invoked on the device. Raytracing validation can only be enabled when +//! the NV_ALLOW_RAYTRACING_VALIDATION envvar is set to 1. +//! +//! SUPPORTED OS: Windows 10 and higher +//! +//! +//! \since Release: 545 +//! +//! \param [in] pDevice Pointer to the device on which raytracing validation should be enabled. +//! \param [in] flags Raytracing validation flags. +//! +//! \return This API can return any of the error codes enumerated in #NvAPI_Status. +//! If there are return error codes with specific meaning for this API, they are listed below. +//! +//! \retval ::NVAPI_OK Completed request +//! \retval ::NVAPI_INVALID_POINTER A null pointer was passed as device argument +//! \retval ::NVAPI_INVALID_ARGUMENT An unsupported flag was specified +//! \retval ::NVAPI_INVALID_CALL The call was made too late (other raytracing-related calls have already been made) +//! \retval ::NVAPI_ACCESS_DENIED Validation is not allowed by envvar +//! \ingroup dx +/////////////////////////////////////////////////////////////////////////////// +NVAPI_INTERFACE NvAPI_D3D12_EnableRaytracingValidation( + __in ID3D12Device5* pDevice, + __in NVAPI_D3D12_RAYTRACING_VALIDATION_FLAGS flags); + + + +//! Severity classification of validation messages. +//! \ingroup dx +//! See NVAPI_D3D12_RAYTRACING_VALIDATION_MESSAGE_CALLBACK +typedef enum _NVAPI_D3D12_RAYTRACING_VALIDATION_MESSAGE_SEVERITY +{ + NVAPI_D3D12_RAYTRACING_VALIDATION_MESSAGE_SEVERITY_ERROR = 0x0, //!< Error message (indicates likely bug) + NVAPI_D3D12_RAYTRACING_VALIDATION_MESSAGE_SEVERITY_WARNING = 0x1 //!< Warning message (indicates inadvisable usage or possible bug) +} NVAPI_D3D12_RAYTRACING_VALIDATION_MESSAGE_SEVERITY; + +//! Callback for raytracing validation messages. +//! \param [in] pUserData User data pointer as provided to callback registration. +//! \param [in] severity Severity of message. +//! \param [in] messageCode Type of reported validation message. +//! \param [in] message Human-readable description of what the message code means. +//! \param [in] messageDetails Additional human-readable context for validation message. May contain newlines. +//! \ingroup dx +//! See NvAPI_D3D12_RegisterRaytracingValidationMessageCallback +typedef void(__stdcall *NVAPI_D3D12_RAYTRACING_VALIDATION_MESSAGE_CALLBACK)(void* pUserData, NVAPI_D3D12_RAYTRACING_VALIDATION_MESSAGE_SEVERITY severity, const char* messageCode, const char* message, const char* messageDetails); + +/////////////////////////////////////////////////////////////////////////////// +// +// FUNCTION NAME: NvAPI_D3D12_RegisterRaytracingValidationMessageCallback +// +//! DESCRIPTION: Register a message callback for raytracing validation messages. +//! The provided callback may be invoked by the driver using any thread at any time until the callback is unregistered. +//! It is invalid to register/unregister callbacks from within the callback. +//! It is invalid to create or destroy objects for the device or record commands onto command lists from within the callback. +//! +//! SUPPORTED OS: Windows 10 and higher +//! +//! +//! \since Release: 545 +//! +//! \param [in] pDevice Pointer to the device from which to obtain raytracing validation messages. +//! \param [in] pfnMessageCallback Callback used to report validation messages. +//! \param [in] pUserData [optional] User data to pass as argument to message callback. +//! \param [out] pHandle Handle that may be used to unregister the callback. +//! +//! \return This API can return any of the error codes enumerated in #NvAPI_Status. +//! If there are return error codes with specific meaning for this API, they are listed below. +//! +//! \retval ::NVAPI_OK Completed request +//! \retval ::NVAPI_INVALID_POINTER A null pointer was passed as an argument +//! \ingroup dx +/////////////////////////////////////////////////////////////////////////////// +NVAPI_INTERFACE NvAPI_D3D12_RegisterRaytracingValidationMessageCallback( + __in ID3D12Device5* pDevice, + __in NVAPI_D3D12_RAYTRACING_VALIDATION_MESSAGE_CALLBACK pfnMessageCallback, + __in_opt void* pUserData, + __out void** pHandle); + + + +/////////////////////////////////////////////////////////////////////////////// +// +// FUNCTION NAME: NvAPI_D3D12_UnregisterRaytracingValidationMessageCallback +// +//! DESCRIPTION: Unregister a previously registered message callback for raytracing validation messages. +//! The provided callback will not be invoked once the unregister call has returned. +//! +//! SUPPORTED OS: Windows 10 and higher +//! +//! +//! \since Release: 545 +//! +//! \param [in] pDevice Pointer to the device from which to stop obtaining raytracing validation messages. +//! \param [in] handle Handle to which callback should be unregistered, obtained at registration. +//! +//! \return This API can return any of the error codes enumerated in #NvAPI_Status. +//! If there are return error codes with specific meaning for this API, they are listed below. +//! +//! \retval ::NVAPI_OK Completed request +//! \retval ::NVAPI_INVALID_POINTER A null pointer was passed as device argument +//! \retval ::NVAPI_INVALID_ARGUMENT Callback handle not recognized +//! \ingroup dx +/////////////////////////////////////////////////////////////////////////////// +NVAPI_INTERFACE NvAPI_D3D12_UnregisterRaytracingValidationMessageCallback( + __in ID3D12Device5* pDevice, + __in void* handle); + + + +/////////////////////////////////////////////////////////////////////////////// +// +// FUNCTION NAME: NvAPI_D3D12_FlushRaytracingValidationMessages +// +//! DESCRIPTION: Flush any validation messages that have not yet been reported. +//! This guarantees that any validation messages for work which is known to be complete on the GPU +//! at the time of the call are reported to registered callbacks. +//! This operation is lightweight if the flushed device does not have raytracing validation enabled. +//! +//! SUPPORTED OS: Windows 10 and higher +//! +//! +//! \since Release: 545 +//! +//! \param [in] pDevice Pointer to the device on which raytracing validation messages should be flushed. +//! +//! \return This API can return any of the error codes enumerated in #NvAPI_Status. +//! If there are return error codes with specific meaning for this API, they are listed below. +//! +//! \retval ::NVAPI_OK Completed request +//! \retval ::NVAPI_INVALID_POINTER A null pointer was passed as device argument +//! \ingroup dx +/////////////////////////////////////////////////////////////////////////////// +NVAPI_INTERFACE NvAPI_D3D12_FlushRaytracingValidationMessages( + __in ID3D12Device5* pDevice); + +#endif // defined(__cplusplus) && defined(__d3d12_h__) && defined(__ID3D12Device5_INTERFACE_DEFINED__) && defined(__ID3D12GraphicsCommandList4_INTERFACE_DEFINED__) + +//! SUPPORTED OS: Windows 10 and higher +//! +#if defined(__cplusplus) && defined(__d3d12_h__) && (defined(__ID3D12Device5_INTERFACE_DEFINED__) || defined(__ID3D12GraphicsCommandList4_INTERFACE_DEFINED__)) + +// Types used by both device and command list functions. + +//! Flags specifying building instructions and hints when constructing a DMM Array. +//! +//! \ingroup dx +typedef enum _NVAPI_D3D12_RAYTRACING_DISPLACEMENT_MICROMAP_ARRAY_BUILD_FLAGS +{ + NVAPI_D3D12_RAYTRACING_DISPLACEMENT_MICROMAP_ARRAY_BUILD_FLAG_NONE = 0x0, //!< No options specified for the DMM Array build. + NVAPI_D3D12_RAYTRACING_DISPLACEMENT_MICROMAP_ARRAY_BUILD_FLAG_PREFER_FAST_TRACE = NV_BIT(0), //!< Allow the DMM Array build to take a little longer in order to optimize for traversal performance. + //!< This flag is incompatible with #NVAPI_D3D12_RAYTRACING_DISPLACEMENT_MICROMAP_ARRAY_BUILD_FLAG_PREFER_FAST_BUILD. + NVAPI_D3D12_RAYTRACING_DISPLACEMENT_MICROMAP_ARRAY_BUILD_FLAG_PREFER_FAST_BUILD = NV_BIT(1) //!< Spend as little time as possible on the DMM Array build with some potential loss to traversal performance. + //!< This flag is incompatible with #NVAPI_D3D12_RAYTRACING_DISPLACEMENT_MICROMAP_ARRAY_BUILD_FLAG_PREFER_FAST_TRACE. +} NVAPI_D3D12_RAYTRACING_DISPLACEMENT_MICROMAP_ARRAY_BUILD_FLAGS; + +//! Specifies the input Displacement Micromap formats. +//! The DC1 (Displacement Compression 1) format follows the space-filling curve in barycentric space over the uniformly tessellated micro-triangles. +//! +//! \note This is a 16-bit value when used in #NVAPI_D3D12_RAYTRACING_DISPLACEMENT_MICROMAP_DESC +//! +//! \ingroup dx +typedef enum _NVAPI_D3D12_RAYTRACING_DISPLACEMENT_MICROMAP_FORMAT +{ + NVAPI_D3D12_RAYTRACING_DISPLACEMENT_MICROMAP_FORMAT_DC1_64_TRIS_64_BYTES = 0x1, //!< 64 micro-triangles packed into 64 bytes + NVAPI_D3D12_RAYTRACING_DISPLACEMENT_MICROMAP_FORMAT_DC1_256_TRIS_128_BYTES = 0x2, //!< 256 micro-triangles packed into 128 bytes + NVAPI_D3D12_RAYTRACING_DISPLACEMENT_MICROMAP_FORMAT_DC1_1024_TRIS_128_BYTES = 0x3, //!< 1024 micro-triangles packed into 128 bytes + +} NVAPI_D3D12_RAYTRACING_DISPLACEMENT_MICROMAP_FORMAT; + +//! Number of DMMs of a specific configuration in a DMM Array or BLAS build. +//! Used to compute conservative buffer size estimates for DMM Array and BLAS builds. +//! +//! \ingroup dx +typedef struct _NVAPI_D3D12_RAYTRACING_DISPLACEMENT_MICROMAP_USAGE_COUNT +{ + NvU32 count; //!< For DMM Array builds: total number of DMMs in the DMM Array with the particular \p subdivisionLevel and \p format specified in this descriptor. + //!< For BLAS builds: total number of DMMs with the \p subdivisionLevel and \p format combination that is referenced from the BLAS. + NvU32 subdivisionLevel; //!< Number of subdivisions for the DMM; valid inputs are [0, 5] (#NVAPI_D3D12_RAYTRACING_DISPLACEMENT_MICROMAP_DC1_MAX_SUBDIVISION_LEVEL). + //!< The total number of micro-triangles is 4subdivisionLevel. + NVAPI_D3D12_RAYTRACING_DISPLACEMENT_MICROMAP_FORMAT format; //!< Displacement Micromap format. +} NVAPI_D3D12_RAYTRACING_DISPLACEMENT_MICROMAP_USAGE_COUNT; + +//! Describes one Displacement Micromap. +//! +//! \ingroup dx +typedef struct _NVAPI_D3D12_RAYTRACING_DISPLACEMENT_MICROMAP_DESC +{ + NvU32 byteOffset; //!< Byte offset from the \c inputBuffer, specified in the input structure #NVAPI_D3D12_BUILD_RAYTRACING_DISPLACEMENT_MICROMAP_ARRAY_INPUTS, to where the input DMM data is located. + NvU16 subdivisionLevel; //!< Number of subdivisions for the DMM; valid inputs are [0, 5] (#NVAPI_D3D12_RAYTRACING_DISPLACEMENT_MICROMAP_DC1_MAX_SUBDIVISION_LEVEL). + //!< The total number of micro-triangles is 4subdivisionLevel. + NvU16 format; //!< Format of the DMM of type #NVAPI_D3D12_RAYTRACING_DISPLACEMENT_MICROMAP_FORMAT. +} NVAPI_D3D12_RAYTRACING_DISPLACEMENT_MICROMAP_DESC; + +//! Input structure to DMM Array construction. +//! Individual DMMs are accessed via indices when used in bottom-level acceleration structure (BLAS) construction. +//! +//! \ingroup dx +typedef struct _NVAPI_D3D12_BUILD_RAYTRACING_DISPLACEMENT_MICROMAP_ARRAY_INPUTS +{ + NVAPI_D3D12_RAYTRACING_DISPLACEMENT_MICROMAP_ARRAY_BUILD_FLAGS flags; //!< Flags which apply to all DMMs in the array. + NvU32 numDMMUsageCounts; //!< Number of DMM usage count entries in the \p pDMMUsageCounts array. + const NVAPI_D3D12_RAYTRACING_DISPLACEMENT_MICROMAP_USAGE_COUNT* pDMMUsageCounts; //!< Usage counts for each subdivision level and format combination across all the DMM entries in the build. + D3D12_GPU_VIRTUAL_ADDRESS inputBuffer; //!< Address for raw DMM input data; it must be 256-byte aligned (#NVAPI_D3D12_RAYTRACING_DISPLACEMENT_MICROMAP_ARRAY_BYTE_ALIGNMENT) + //!< It is recommended to try to organize DMMs together in memory that are expected to be used close together spatially. + D3D12_GPU_VIRTUAL_ADDRESS_AND_STRIDE perDMMDescs; //!< GPU array with one #NVAPI_D3D12_RAYTRACING_DISPLACEMENT_MICROMAP_DESC entry per DMM. +} NVAPI_D3D12_BUILD_RAYTRACING_DISPLACEMENT_MICROMAP_ARRAY_INPUTS; + +#endif // defined(__cplusplus) && defined(__d3d12_h__) && (defined(__ID3D12Device5_INTERFACE_DEFINED__) || defined(__ID3D12GraphicsCommandList4_INTERFACE_DEFINED__)) + +#if defined(__cplusplus) && defined(__d3d12_h__) && defined(__ID3D12Device5_INTERFACE_DEFINED__) + +//! Conservative memory requirements for building a DMM Array. +//! +//! \ingroup dx +typedef struct _NVAPI_D3D12_RAYTRACING_DISPLACEMENT_MICROMAP_ARRAY_PREBUILD_INFO +{ + NvU64 resultDataMaxSizeInBytes; //!< Size required to hold the result of a DMM Array build based on the specified inputs. + NvU64 scratchDataSizeInBytes; //!< Scratch storage on GPU required during DMM Array build based on the specified inputs. +} NVAPI_D3D12_RAYTRACING_DISPLACEMENT_MICROMAP_ARRAY_PREBUILD_INFO; + +//! Parameters given to NvAPI_D3D12_GetRaytracingDisplacementMicromapArrayPrebuildInfo(). +//! +//! \ingroup dx +typedef struct _NVAPI_GET_RAYTRACING_DISPLACEMENT_MICROMAP_ARRAY_PREBUILD_INFO_PARAMS_V1 +{ + NvU32 version; //!< [in] Structure version; it should be set to #NVAPI_GET_RAYTRACING_DISPLACEMENT_MICROMAP_ARRAY_PREBUILD_INFO_PARAMS_VER. + const NVAPI_D3D12_BUILD_RAYTRACING_DISPLACEMENT_MICROMAP_ARRAY_INPUTS* pDesc; //!< [in] Description of the DMM Array build. + NVAPI_D3D12_RAYTRACING_DISPLACEMENT_MICROMAP_ARRAY_PREBUILD_INFO* pInfo; //!< [out] Result of the query. +} NVAPI_GET_RAYTRACING_DISPLACEMENT_MICROMAP_ARRAY_PREBUILD_INFO_PARAMS_V1; +#define NVAPI_GET_RAYTRACING_DISPLACEMENT_MICROMAP_ARRAY_PREBUILD_INFO_PARAMS_VER1 MAKE_NVAPI_VERSION(NVAPI_GET_RAYTRACING_DISPLACEMENT_MICROMAP_ARRAY_PREBUILD_INFO_PARAMS_V1, 1) +typedef NVAPI_GET_RAYTRACING_DISPLACEMENT_MICROMAP_ARRAY_PREBUILD_INFO_PARAMS_V1 NVAPI_GET_RAYTRACING_DISPLACEMENT_MICROMAP_ARRAY_PREBUILD_INFO_PARAMS; +#define NVAPI_GET_RAYTRACING_DISPLACEMENT_MICROMAP_ARRAY_PREBUILD_INFO_PARAMS_VER NVAPI_GET_RAYTRACING_DISPLACEMENT_MICROMAP_ARRAY_PREBUILD_INFO_PARAMS_VER1 + +/////////////////////////////////////////////////////////////////////////////// +// +// FUNCTION NAME: NvAPI_D3D12_GetRaytracingDisplacementMicromapArrayPrebuildInfo +// +//! DESCRIPTION: Query conservative memory requirements for building a DMM (Displacement Micromap) Array. +//! The returned size is conservative for DMM Array builds containing +//! a lower or equal number of entries for each resolution and format combination. +//! +//! +//! SUPPORTED OS: Windows 10 and higher +//! +//! +//! \since Release: 525 +//! +//! \param [in] pDevice Device on which the DMM Array will be built. +//! \param [in,out] pParams Wrapper around the inputs and outputs of the function. +//! +//! \return This API can return any of the error codes enumerated in #NvAPI_Status. +//! If there are return error codes with specific meaning for this API, they are listed below. +//! +//! \ingroup dx +/////////////////////////////////////////////////////////////////////////////// +NVAPI_INTERFACE NvAPI_D3D12_GetRaytracingDisplacementMicromapArrayPrebuildInfo( + __in ID3D12Device5* pDevice, + __inout NVAPI_GET_RAYTRACING_DISPLACEMENT_MICROMAP_ARRAY_PREBUILD_INFO_PARAMS* pParams); + +#endif // defined(__cplusplus) && defined(__d3d12_h__) && defined(__ID3D12Device5_INTERFACE_DEFINED__) + //! SUPPORTED OS: Windows 10 and higher //! #if defined(__cplusplus) && defined(__d3d12_h__) && (defined(__ID3D12Device5_INTERFACE_DEFINED__) || defined(__ID3D12GraphicsCommandList4_INTERFACE_DEFINED__)) @@ -17856,6 +18867,9 @@ typedef enum _NVAPI_D3D12_PIPELINE_CREATION_STATE_FLAGS NVAPI_D3D12_PIPELINE_CREATION_STATE_FLAGS_ENABLE_OMM_SUPPORT = NV_BIT(0), //!< [in] Change whether raytracing pipelines are created with support for Opacity Micromaps. //!< If a triangle with an OMM is encountered during traversal and the pipeline was not created with support for them, behavior is undefined. //!< Support should only be enabled if there are OMMs present, since it may incur a small penalty on traversal performance overall. + NVAPI_D3D12_PIPELINE_CREATION_STATE_FLAGS_ENABLE_DMM_SUPPORT = NV_BIT(1), //!< [in] Change whether raytracing pipelines are created with support for Displacement Micromaps. + //!< If a triangle with a DMM is encountered during traversal and the pipeline was not created with support for them, behavior is undefined. + //!< Support should only be enabled if there are DMMs present, since it may incur a small penalty on traversal performance overall. } NVAPI_D3D12_PIPELINE_CREATION_STATE_FLAGS; //! State used when creating new pipelines. @@ -17914,6 +18928,8 @@ typedef enum _NVAPI_D3D12_SERIALIZED_DATA_TYPE_EX // NVAPI_D3D12_SERIALIZED_DATA_TYPE_EX specific flags NVAPI_D3D12_SERIALIZED_DATA_RAYTRACING_OPACITY_MICROMAP_ARRAY_EX = 0x1, //!< Data blob contains an OMM Array. //!< Starting from offset 0, the first bytes of the OMM Array can be reinterpreted as \c D3D12_SERIALIZED_DATA_DRIVER_MATCHING_IDENTIFIER. + NVAPI_D3D12_SERIALIZED_DATA_RAYTRACING_DISPLACEMENT_MICROMAP_ARRAY_EX = 0x2, //!< Data blob contains a DMM Array. + //!< Starting from offset 0, the first bytes of the DMM Array can be reinterpreted as \c D3D12_SERIALIZED_DATA_DRIVER_MATCHING_IDENTIFIER. } NVAPI_D3D12_SERIALIZED_DATA_TYPE_EX; @@ -17982,6 +18998,7 @@ typedef enum _NVAPI_D3D12_RAYTRACING_ACCELERATION_STRUCTURE_BUILD_FLAGS_EX //!< Specifying this build flag may result in some reductions in traversal performance. NVAPI_D3D12_RAYTRACING_ACCELERATION_STRUCTURE_BUILD_FLAG_ALLOW_OMM_OPACITY_STATES_UPDATE_EX = NV_BIT(8), //!< The acceleration structure (AS) supports updating OMM data (encoded opacity values). //!< Specifying this flag may reduce traversal performance. + NVAPI_D3D12_RAYTRACING_ACCELERATION_STRUCTURE_BUILD_FLAG_ALLOW_DATA_ACCESS_EX = NV_BIT(9), //!< Allows triangle and micro-triangle data to be accessed through the BLAS via shader intrinsics. } NVAPI_D3D12_RAYTRACING_ACCELERATION_STRUCTURE_BUILD_FLAGS_EX; @@ -17998,7 +19015,8 @@ typedef enum _NVAPI_D3D12_RAYTRACING_GEOMETRY_TYPE_EX // NVAPI_D3D12_RAYTRACING_GEOMETRY_TYPE_EX specific flags NVAPI_D3D12_RAYTRACING_GEOMETRY_TYPE_OMM_TRIANGLES_EX = 0x2, //!< Shares most fields with the basic triangle geometry type, but allows an OMM Array to be attached to the geometry. //!< The basic triangle type and this OMM-enabled type geometries may be mixed in the same BLAS build. - + NVAPI_D3D12_RAYTRACING_GEOMETRY_TYPE_DMM_TRIANGLES_EX = 0x3, //!< Triangle geometry with attached DMM data. + //!< This geometry cannot be mixed with other geometry types in the same BLAS. } NVAPI_D3D12_RAYTRACING_GEOMETRY_TYPE_EX; @@ -18032,6 +19050,53 @@ typedef struct _NVAPI_D3D12_RAYTRACING_GEOMETRY_OMM_ATTACHMENT_DESC } NVAPI_D3D12_RAYTRACING_GEOMETRY_OMM_ATTACHMENT_DESC; +//! The edge vA..vB is decimated: after subdivision the number of micro-triangles on that edge is halved. +//! (i.e. the neighboring primitive can have a lower subdivision level without introducing cracks) +//! +//! \ingroup dx +typedef enum _NVAPI_D3D12_RAYTRACING_DISPLACEMENT_MICROMAP_PRIMITIVE_FLAGS +{ + NVAPI_D3D12_RAYTRACING_DISPLACEMENT_MICROMAP_PRIMITIVE_FLAG_DECIMATE_01 = NV_BIT(0), + NVAPI_D3D12_RAYTRACING_DISPLACEMENT_MICROMAP_PRIMITIVE_FLAG_DECIMATE_12 = NV_BIT(1), + NVAPI_D3D12_RAYTRACING_DISPLACEMENT_MICROMAP_PRIMITIVE_FLAG_DECIMATE_20 = NV_BIT(2), + +} NVAPI_D3D12_RAYTRACING_DISPLACEMENT_MICROMAP_PRIMITIVE_FLAGS; + +//! Geometry descriptor attachment with Displacement Micromaps. +//! +//! \ingroup dx +typedef struct _NVAPI_D3D12_RAYTRACING_GEOMETRY_DMM_ATTACHMENT_DESC +{ + D3D12_GPU_VIRTUAL_ADDRESS_AND_STRIDE triangleMicromapIndexBuffer; //!< Optional buffer specifying which DMM index to use for each triangle; if \c NULL, there is a 1:1 mapping between input triangles and DMM Array entries. + //!< For BLAS updates, this input buffer must match that of the original build. + DXGI_FORMAT triangleMicromapIndexFormat; //!< Format of \c displacementMicromapIndexBuffer, either \c DXGI_FORMAT_R32_UINT or \c DXGI_FORMAT_R16_UINT. + NvU32 triangleMicromapBaseLocation; //!< Constant added to all DMM indices in \p displacementMicromapIndexBuffer. + + D3D12_GPU_VIRTUAL_ADDRESS_AND_STRIDE trianglePrimitiveFlagsBuffer; //!< Optional, per-triangle UINT8 mode flags (#NVAPI_D3D12_RAYTRACING_DISPLACEMENT_MICROMAP_PRIMITIVE_FLAGS) + + D3D12_GPU_VIRTUAL_ADDRESS_AND_STRIDE vertexBiasAndScaleBuffer; //!< Optional displacement base vertex bias and displacement vector scale buffer. If not supplied, bias defaults to 0 and scale to 1. + DXGI_FORMAT vertexBiasAndScaleFormat; //!< Format of \c displacementBiasAndScaleBuffer. Supported formats are \c DXGI_FORMAT_R16G16_FLOAT and \c DXGI_FORMAT_R32G32_FLOAT + + D3D12_GPU_VIRTUAL_ADDRESS_AND_STRIDE vertexDisplacementVectorBuffer; //!< Per-vertex displacement vector buffer. This buffer is indexed using the index buffer from the base triangle geometry. + DXGI_FORMAT vertexDisplacementVectorFormat; //!< Format of \c displacementVectorBuffer. Supported formats are \c DXGI_FORMAT_R32G32B32_FLOAT, \c DXGI_FORMAT_R32G32B32A32_FLOAT, and \c DXGI_FORMAT_R16G16B16A16_FLOAT (The Alpha channel is ignored, and stride can be set accordingly). + + D3D12_GPU_VIRTUAL_ADDRESS displacementMicromapArray; //!< Pointer to a DMM Array used by this geometry. + //!< Unlike vertex, index, and transform buffers, this resource is dereferenced during raytracing. + + NvU32 numDMMUsageCounts; //!< Number of DMM usage count entries in the \p pDMMUsageCounts array. + const NVAPI_D3D12_RAYTRACING_DISPLACEMENT_MICROMAP_USAGE_COUNT* pDMMUsageCounts; //!< Usage counts for each subdivision level and format combination across all the DMM entries referred-to by the DMM index buffer specified by this geometry. + +} NVAPI_D3D12_RAYTRACING_GEOMETRY_DMM_ATTACHMENT_DESC; + +//! Geometry triangle descriptor with attached augmented Displacement Micromaps. +//! +//! \ingroup dx +typedef struct _NVAPI_D3D12_RAYTRACING_GEOMETRY_DMM_TRIANGLES_DESC +{ + D3D12_RAYTRACING_GEOMETRY_TRIANGLES_DESC triangles; //!< Triangle mesh descriptor. + NVAPI_D3D12_RAYTRACING_GEOMETRY_DMM_ATTACHMENT_DESC dmmAttachment; //!< Displacement Micromap attachment descriptor. +} NVAPI_D3D12_RAYTRACING_GEOMETRY_DMM_TRIANGLES_DESC; + //! Geometry triangle descriptor with attached augmented Opacity Micromaps. //! //! \ingroup dx @@ -18057,6 +19122,8 @@ typedef struct _NVAPI_D3D12_RAYTRACING_GEOMETRY_DESC_EX //!< Otherwise, this parameter is unused (space repurposed in a union). NVAPI_D3D12_RAYTRACING_GEOMETRY_OMM_TRIANGLES_DESC ommTriangles; //!< Describes triangle geometry which may optionally use Opacity Micromaps, if \c type is #NVAPI_D3D12_RAYTRACING_GEOMETRY_TYPE_OMM_TRIANGLES_EX. //!< Otherwise, this parameter is unused (space repurposed in a union). + NVAPI_D3D12_RAYTRACING_GEOMETRY_DMM_TRIANGLES_DESC dmmTriangles; //!< Describes micro-triangle geometry, if \c type is #NVAPI_D3D12_RAYTRACING_GEOMETRY_TYPE_DMM_TRIANGLES_EX. + //!< Otherwise, this parameter is unused (space repurposed in a union). }; } NVAPI_D3D12_RAYTRACING_GEOMETRY_DESC_EX; @@ -18284,6 +19351,182 @@ NVAPI_INTERFACE NvAPI_D3D12_RelocateRaytracingOpacityMicromapArray( #if defined(__cplusplus) && defined(__d3d12_h__) && defined(__ID3D12GraphicsCommandList4_INTERFACE_DEFINED__) +//! Description of the inputs and memory areas used during the building of DMM Arrays. +//! +//! \ingroup dx +typedef struct _NVAPI_D3D12_BUILD_RAYTRACING_DISPLACEMENT_MICROMAP_ARRAY_DESC +{ + D3D12_GPU_VIRTUAL_ADDRESS destDisplacementMicromapArrayData; //!< Output location for the DMM Array build. + //!< NvAPI_D3D12_GetRaytracingDisplacementMicromapArrayPrebuildInfo() reports the amount of memory required for the result given a set of input parameters. + //!< The address must be aligned to 256 bytes (#NVAPI_D3D12_RAYTRACING_DISPLACEMENT_MICROMAP_ARRAY_BYTE_ALIGNMENT). + NVAPI_D3D12_BUILD_RAYTRACING_DISPLACEMENT_MICROMAP_ARRAY_INPUTS inputs; //!< Description of the input data for the DMM Array build. + D3D12_GPU_VIRTUAL_ADDRESS scratchDisplacementMicromapArrayData; //!< Location where the build will store temporary data. + //!< NvAPI_D3D12_GetRaytracingDisplacementMicromapArrayPrebuildInfo() reports the amount of scratch memory the implementation will need for a given set of input parameters. + //!< The address must be aligned to 256 bytes (#NVAPI_D3D12_RAYTRACING_DISPLACEMENT_MICROMAP_ARRAY_BYTE_ALIGNMENT). + //!< Contents of this memory going into a build on the GPU timeline are irrelevant and will not be preserved. + //!< After the build is complete on the GPU timeline, the memory is left with whatever undefined contents the build finished with. + //!< The memory pointed to must be in state \c D3D12_RESOURCE_STATE_UNORDERED_ACCESS. +} NVAPI_D3D12_BUILD_RAYTRACING_DISPLACEMENT_MICROMAP_ARRAY_DESC; + +//! Structure emitted by NvAPI_D3D12_EmitRaytracingDisplacementMicromapArrayPostbuildInfo(), and optionally NvAPI_D3D12_BuildRaytracingDisplacementMicromapArray(), when \c type equals #NVAPI_D3D12_RAYTRACING_DISPLACEMENT_MICROMAP_ARRAY_POSTBUILD_INFO_CURRENT_SIZE. +//! +//! \ingroup dx +typedef struct _NVAPI_D3D12_RAYTRACING_DISPLACEMENT_MICROMAP_ARRAY_POSTBUILD_INFO_CURRENT_SIZE_DESC +{ + NvU64 currentSizeInBytes; //!< Size of the DMM Array buffer. + //!< The queried size may be smaller than the size reported by NvAPI_D3D12_GetRaytracingDisplacementMicromapArrayPrebuildInfo(). + //!< This allows the application to move and relocate the DMM Array to a smaller buffer to reclaim any unused memory after the DMM Array build is complete. +} NVAPI_D3D12_RAYTRACING_DISPLACEMENT_MICROMAP_ARRAY_POSTBUILD_INFO_CURRENT_SIZE_DESC; + +//! Type of postbuild info to emit after a DMM Array build. +//! +//! \ingroup dx +typedef enum _NVAPI_D3D12_RAYTRACING_DISPLACEMENT_MICROMAP_ARRAY_POSTBUILD_INFO_TYPE +{ + NVAPI_D3D12_RAYTRACING_DISPLACEMENT_MICROMAP_ARRAY_POSTBUILD_INFO_CURRENT_SIZE = 0x0, //!< Size of the current DMM Array. May be smaller than reported by the NvAPI_D3D12_GetRaytracingDisplacementMicromapArrayPrebuildInfo() call. + //!< Unused memory can be reclaimed by copying the DMM Array into a new resource; see #NVAPI_D3D12_RAYTRACING_DISPLACEMENT_MICROMAP_ARRAY_POSTBUILD_INFO_CURRENT_SIZE_DESC. +} NVAPI_D3D12_RAYTRACING_DISPLACEMENT_MICROMAP_ARRAY_POSTBUILD_INFO_TYPE; + +//! Description of the postbuild information to generate from a DMM Array. +//! +//! \ingroup dx +typedef struct _NVAPI_D3D12_RAYTRACING_DISPLACEMENT_MICROMAP_ARRAY_POSTBUILD_INFO_DESC +{ + D3D12_GPU_VIRTUAL_ADDRESS destBuffer; //!< Result storage. + //!< Size required and the layout of the contents written by the system depend on \p infoType. + //!< The memory pointed to must be in state \c D3D12_RESOURCE_STATE_UNORDERED_ACCESS. + //!< The memory must be aligned to the natural alignment for the members of the particular output structure being generated (e.g. 8 bytes for a struct with the largest member being \c NvU64). + NVAPI_D3D12_RAYTRACING_DISPLACEMENT_MICROMAP_ARRAY_POSTBUILD_INFO_TYPE infoType; //!< Type of postbuild information to retrieve. +} NVAPI_D3D12_RAYTRACING_DISPLACEMENT_MICROMAP_ARRAY_POSTBUILD_INFO_DESC; + +//! Parameters given to NvAPI_D3D12_BuildRaytracingDisplacementMicromapArray(). +//! +//! \ingroup dx +typedef struct _NVAPI_BUILD_RAYTRACING_DISPLACEMENT_MICROMAP_ARRAY_PARAMS_V1 +{ + NvU32 version; //!< [in] Structure version; it should be set to #NVAPI_BUILD_RAYTRACING_DISPLACEMENT_MICROMAP_ARRAY_PARAMS_VER. + const NVAPI_D3D12_BUILD_RAYTRACING_DISPLACEMENT_MICROMAP_ARRAY_DESC* pDesc; //!< [in] Description of the DMM Array build. + NvU32 numPostbuildInfoDescs; //!< [in] Size of postbuild info desc array. Set to 0 if none are needed. + const NVAPI_D3D12_RAYTRACING_DISPLACEMENT_MICROMAP_ARRAY_POSTBUILD_INFO_DESC* pPostbuildInfoDescs; //!< [in] Optional array of descriptions for postbuild info to generate describing properties of the acceleration structure that was built. + //!< [in] Any given postbuild info type, \c D3D12_RAYTRACING_ACCEELRATION_STRUCTURE_POSTBUILD_INFO_TYPE, can only be selected for output by at most one array entry. +} NVAPI_BUILD_RAYTRACING_DISPLACEMENT_MICROMAP_ARRAY_PARAMS_V1; +#define NVAPI_BUILD_RAYTRACING_DISPLACEMENT_MICROMAP_ARRAY_PARAMS_VER1 MAKE_NVAPI_VERSION(NVAPI_BUILD_RAYTRACING_DISPLACEMENT_MICROMAP_ARRAY_PARAMS_V1, 1) +typedef NVAPI_BUILD_RAYTRACING_DISPLACEMENT_MICROMAP_ARRAY_PARAMS_V1 NVAPI_BUILD_RAYTRACING_DISPLACEMENT_MICROMAP_ARRAY_PARAMS; +#define NVAPI_BUILD_RAYTRACING_DISPLACEMENT_MICROMAP_ARRAY_PARAMS_VER NVAPI_BUILD_RAYTRACING_DISPLACEMENT_MICROMAP_ARRAY_PARAMS_VER1 + +/////////////////////////////////////////////////////////////////////////////// +// +// FUNCTION NAME: NvAPI_D3D12_BuildRaytracingDisplacementMicromapArray +// +//! DESCRIPTION: Construct DMM Array for a collection of DMMs on the GPU. +//! The CPU-side input buffers are not referenced after this call. +//! The GPU-side input resources are not referenced after the build has concluded after ExecuteCommandList(). +//! Additionally, the application may optionally output postbuild information immediately after the build. +//! +//! SUPPORTED OS: Windows 10 and higher +//! +//! +//! \since Release: 525 +//! +//! \param [in] pCommandList Command list on which the command will execute. +//! \param [in] pParams Wrapper around the inputs of the function. +//! +//! \return This API can return any of the error codes enumerated in #NvAPI_Status. +//! If there are return error codes with specific meaning for this API, they are listed below. +//! +//! \retval NVAPI_INVALID_COMBINATION pParams->pPostbuildInfoDescs was set to \c NULL while pParams->numPostbuildInfoDescs is non zero. +//! +//! \ingroup dx +/////////////////////////////////////////////////////////////////////////////// +NVAPI_INTERFACE NvAPI_D3D12_BuildRaytracingDisplacementMicromapArray( + __in ID3D12GraphicsCommandList4* pCommandList, + __in NVAPI_BUILD_RAYTRACING_DISPLACEMENT_MICROMAP_ARRAY_PARAMS* pParams); + +#endif // defined(__cplusplus) && defined(__d3d12_h__) && defined(__ID3D12GraphicsCommandList4_INTERFACE_DEFINED__) + +#if defined(__cplusplus) && defined(__d3d12_h__) && defined(__ID3D12GraphicsCommandList4_INTERFACE_DEFINED__) + +//! Parameters given to NvAPI_D3D12_RelocateRaytracingDisplacementMicromapArray(). +//! +//! \ingroup dx +typedef struct _NVAPI_RELOCATE_RAYTRACING_DISPLACEMENT_MICROMAP_ARRAY_PARAMS_V1 +{ + NvU32 version; //!< [in] Structure version; it should be set to #NVAPI_RELOCATE_RAYTRACING_DISPLACEMENT_MICROMAP_ARRAY_PARAMS_VER. + D3D12_GPU_VIRTUAL_ADDRESS displacementMicromapArray; //!< [in] DMM Array current memory address; it must be 256-byte aligned (#NVAPI_D3D12_RAYTRACING_DISPLACEMENT_MICROMAP_ARRAY_BYTE_ALIGNMENT). +} NVAPI_RELOCATE_RAYTRACING_DISPLACEMENT_MICROMAP_ARRAY_PARAMS_V1; +#define NVAPI_RELOCATE_RAYTRACING_DISPLACEMENT_MICROMAP_ARRAY_PARAMS_VER1 MAKE_NVAPI_VERSION(NVAPI_RELOCATE_RAYTRACING_DISPLACEMENT_MICROMAP_ARRAY_PARAMS_V1, 1) +typedef NVAPI_RELOCATE_RAYTRACING_DISPLACEMENT_MICROMAP_ARRAY_PARAMS_V1 NVAPI_RELOCATE_RAYTRACING_DISPLACEMENT_MICROMAP_ARRAY_PARAMS; +#define NVAPI_RELOCATE_RAYTRACING_DISPLACEMENT_MICROMAP_ARRAY_PARAMS_VER NVAPI_RELOCATE_RAYTRACING_DISPLACEMENT_MICROMAP_ARRAY_PARAMS_VER1 + +/////////////////////////////////////////////////////////////////////////////// +// +// FUNCTION NAME: NvAPI_D3D12_RelocateRaytracingDisplacementMicromapArray +// +//! DESCRIPTION: Makes the DMM Array usable at its current location in memory. +//! A DMM Array that has been copied to a new location must be relocated using this function before it may be attached to any BLAS. +//! +//! SUPPORTED OS: Windows 10 and higher +//! +//! +//! \since Release: 525 +//! +//! \param [in] pCommandList Command list on which the command will execute. +//! \param [in] pParams Wrapper around the inputs of the function. +//! +//! \return This API can return any of the error codes enumerated in #NvAPI_Status. +//! If there are return error codes with specific meaning for this API, they are listed below. +//! +//! \ingroup dx +/////////////////////////////////////////////////////////////////////////////// +NVAPI_INTERFACE NvAPI_D3D12_RelocateRaytracingDisplacementMicromapArray( + __in ID3D12GraphicsCommandList4* pCommandList, + __in const NVAPI_RELOCATE_RAYTRACING_DISPLACEMENT_MICROMAP_ARRAY_PARAMS* pParams); + +#endif // defined(__cplusplus) && defined(__d3d12_h__) && defined(__ID3D12GraphicsCommandList4_INTERFACE_DEFINED__) + +#if defined(__cplusplus) && defined(__d3d12_h__) && defined(__ID3D12GraphicsCommandList4_INTERFACE_DEFINED__) + +//! Parameters given to NvAPI_D3D12_EmitRaytracingDisplacementMicromapArrayPostbuildInfo(). +//! +//! \ingroup dx +typedef struct _NVAPI_EMIT_RAYTRACING_DISPLACEMENT_MICROMAP_ARRAY_POSTBUILD_INFO_PARAMS_V1 +{ + NvU32 version; //!< [in] Structure version; it should be set to #NVAPI_EMIT_RAYTRACING_DISPLACEMENT_MICROMAP_ARRAY_POSTBUILD_INFO_PARAMS_VER. + const NVAPI_D3D12_RAYTRACING_DISPLACEMENT_MICROMAP_ARRAY_POSTBUILD_INFO_DESC* pDesc; //!< [in] Description of which postbuild info to emit. + NvU32 numSources; //!< [in] Number of DMM Arrays in \p pSources. + const D3D12_GPU_VIRTUAL_ADDRESS* pSources; //!< [in] List of DMM Arrays for which postbuild info should be emitted. +} NVAPI_EMIT_RAYTRACING_DISPLACEMENT_MICROMAP_ARRAY_POSTBUILD_INFO_PARAMS_V1; +#define NVAPI_EMIT_RAYTRACING_DISPLACEMENT_MICROMAP_ARRAY_POSTBUILD_INFO_PARAMS_VER1 MAKE_NVAPI_VERSION(NVAPI_EMIT_RAYTRACING_DISPLACEMENT_MICROMAP_ARRAY_POSTBUILD_INFO_PARAMS_V1, 1) +typedef NVAPI_EMIT_RAYTRACING_DISPLACEMENT_MICROMAP_ARRAY_POSTBUILD_INFO_PARAMS_V1 NVAPI_EMIT_RAYTRACING_DISPLACEMENT_MICROMAP_ARRAY_POSTBUILD_INFO_PARAMS; +#define NVAPI_EMIT_RAYTRACING_DISPLACEMENT_MICROMAP_ARRAY_POSTBUILD_INFO_PARAMS_VER NVAPI_EMIT_RAYTRACING_DISPLACEMENT_MICROMAP_ARRAY_POSTBUILD_INFO_PARAMS_VER1 + +/////////////////////////////////////////////////////////////////////////////// +// +// FUNCTION NAME: NvAPI_D3D12_EmitRaytracingDisplacementMicromapArrayPostbuildInfo +// +//! DESCRIPTION: Emits information about one or more DMM Arrays, only available after the DMM Array constructions have finished. +//! +//! SUPPORTED OS: Windows 10 and higher +//! +//! +//! \since Release: 525 +//! +//! \param [in] pCommandList Command list on which the command will execute. +//! \param [in] pParams Wrapper around the inputs of the function. +//! +//! \return This API can return any of the error codes enumerated in #NvAPI_Status. +//! If there are return error codes with specific meaning for this API, they are listed below. +//! +//! \ingroup dx +/////////////////////////////////////////////////////////////////////////////// +NVAPI_INTERFACE NvAPI_D3D12_EmitRaytracingDisplacementMicromapArrayPostbuildInfo( + __in ID3D12GraphicsCommandList4* pCommandList, + __in const NVAPI_EMIT_RAYTRACING_DISPLACEMENT_MICROMAP_ARRAY_POSTBUILD_INFO_PARAMS* pParams); + +#endif // defined(__cplusplus) && defined(__d3d12_h__) && defined(__ID3D12GraphicsCommandList4_INTERFACE_DEFINED__) + +#if defined(__cplusplus) && defined(__d3d12_h__) && defined(__ID3D12GraphicsCommandList4_INTERFACE_DEFINED__) + //! Parameters given to NvAPI_D3D12_EmitRaytracingOpacityMicromapArrayPostbuildInfo(). //! //! \ingroup dx @@ -18443,6 +19686,16 @@ typedef enum _NVAPI_RAY_FLAGS_EX //!< If an instance is flagged with #NVAPI_D3D12_RAYTRACING_INSTANCE_FLAG_DISABLE_OMMS_EX, that takes precedence over this flag. } NVAPI_RAY_FLAG_EX; +//! Mandatory alignment for the address of a DMM Array. +//! +//! \ingroup dx +#define NVAPI_D3D12_RAYTRACING_DISPLACEMENT_MICROMAP_ARRAY_BYTE_ALIGNMENT 256 + +//! Highest subdivision-level allowed with DC1. +//! +//! \ingroup dx +#define NVAPI_D3D12_RAYTRACING_DISPLACEMENT_MICROMAP_DC1_MAX_SUBDIVISION_LEVEL 5 + #endif // defined(__cplusplus) && defined(__d3d12_h__) && defined(__ID3D12GraphicsCommandList4_INTERFACE_DEFINED__) @@ -18544,6 +19797,7 @@ NVAPI_INTERFACE NvAPI_D3D12_CreateCommittedRDMABuffer( __out void **ppRDMAAddress); #endif //defined(__cplusplus) && defined(__d3d12_h__) + //! SUPPORTED OS: Windows 10 and higher //! #if defined(__cplusplus) && defined(__d3d12_h__) @@ -21969,6 +23223,98 @@ typedef NV_DISPLAY_DRIVER_INFO_V2 NV_DISPLAY_DRIVER_INFO; NVAPI_INTERFACE NvAPI_SYS_GetDisplayDriverInfo(__inout NV_DISPLAY_DRIVER_INFO *pDriverInfo); +typedef struct _NV_PHYSICAL_GPU_HANDLE_DATA +{ + NvPhysicalGpuHandle hPhysicalGpu; // The application must not modify the SQL statement text passed into ** the 2nd parameter of sqlite3_exec() while sqlite3_exec() is running. +**
  • The application must not dereference the arrays or string pointers +** passed as the 3rd and 4th callback parameters after it returns. ** */ SQLITE_API int sqlite3_exec( @@ -1075,11 +1077,11 @@ struct sqlite3_file { ** ** xLock() upgrades the database file lock. In other words, xLock() moves the ** database file lock in the direction NONE toward EXCLUSIVE. The argument to -** xLock() is always on of SHARED, RESERVED, PENDING, or EXCLUSIVE, never +** xLock() is always one of SHARED, RESERVED, PENDING, or EXCLUSIVE, never ** SQLITE_LOCK_NONE. If the database file lock is already at or above the ** requested lock, then the call to xLock() is a no-op. ** xUnlock() downgrades the database file lock to either SHARED or NONE. -* If the lock is already at or below the requested lock state, then the call +** If the lock is already at or below the requested lock state, then the call ** to xUnlock() is a no-op. ** The xCheckReservedLock() method checks whether any database connection, ** either in this process or in some other process, is holding a RESERVED, @@ -2440,7 +2442,7 @@ struct sqlite3_mem_methods { ** is stored in each sorted record and the required column values loaded ** from the database as records are returned in sorted order. The default ** value for this option is to never use this optimization. Specifying a -** negative value for this option restores the default behaviour. +** negative value for this option restores the default behavior. ** This option is only available if SQLite is compiled with the ** [SQLITE_ENABLE_SORTER_REFERENCES] compile-time option. ** @@ -2454,6 +2456,22 @@ struct sqlite3_mem_methods { ** configuration setting is never used, then the default maximum is determined ** by the [SQLITE_MEMDB_DEFAULT_MAXSIZE] compile-time option. If that ** compile-time option is not set, then the default maximum is 1073741824. +** +** [[SQLITE_CONFIG_ROWID_IN_VIEW]] +**
    SQLITE_CONFIG_ROWID_IN_VIEW +**
    The SQLITE_CONFIG_ROWID_IN_VIEW option enables or disables the ability +** for VIEWs to have a ROWID. The capability can only be enabled if SQLite is +** compiled with -DSQLITE_ALLOW_ROWID_IN_VIEW, in which case the capability +** defaults to on. This configuration option queries the current setting or +** changes the setting to off or on. The argument is a pointer to an integer. +** If that integer initially holds a value of 1, then the ability for VIEWs to +** have ROWIDs is activated. If the integer initially holds zero, then the +** ability is deactivated. Any other initial value for the integer leaves the +** setting unchanged. After changes, if any, the integer is written with +** a 1 or 0, if the ability for VIEWs to have ROWIDs is on or off. If SQLite +** is compiled without -DSQLITE_ALLOW_ROWID_IN_VIEW (which is the usual and +** recommended case) then the integer is always filled with zero, regardless +** if its initial value. ** */ #define SQLITE_CONFIG_SINGLETHREAD 1 /* nil */ @@ -2485,6 +2503,7 @@ struct sqlite3_mem_methods { #define SQLITE_CONFIG_SMALL_MALLOC 27 /* boolean */ #define SQLITE_CONFIG_SORTERREF_SIZE 28 /* int nByte */ #define SQLITE_CONFIG_MEMDB_MAXSIZE 29 /* sqlite3_int64 */ +#define SQLITE_CONFIG_ROWID_IN_VIEW 30 /* int* */ /* ** CAPI3REF: Database Connection Configuration Options @@ -2615,7 +2634,7 @@ struct sqlite3_mem_methods { ** database handle, SQLite checks if this will mean that there are now no ** connections at all to the database. If so, it performs a checkpoint ** operation before closing the connection. This option may be used to -** override this behaviour. The first parameter passed to this operation +** override this behavior. The first parameter passed to this operation ** is an integer - positive to disable checkpoints-on-close, or zero (the ** default) to enable them, and negative to leave the setting unchanged. ** The second parameter is a pointer to an integer @@ -3599,8 +3618,8 @@ SQLITE_API int sqlite3_set_authorizer( #define SQLITE_RECURSIVE 33 /* NULL NULL */ /* -** CAPI3REF: Tracing And Profiling Functions -** METHOD: sqlite3 +** CAPI3REF: Deprecated Tracing And Profiling Functions +** DEPRECATED ** ** These routines are deprecated. Use the [sqlite3_trace_v2()] interface ** instead of the routines described here. @@ -4267,14 +4286,17 @@ SQLITE_API void sqlite3_free_filename(sqlite3_filename); ** ** ** ^The sqlite3_errmsg() and sqlite3_errmsg16() return English-language -** text that describes the error, as either UTF-8 or UTF-16 respectively. +** text that describes the error, as either UTF-8 or UTF-16 respectively, +** or NULL if no error message is available. +** (See how SQLite handles [invalid UTF] for exceptions to this rule.) ** ^(Memory to hold the error message string is managed internally. ** The application does not need to worry about freeing the result. ** However, the error string might be overwritten or deallocated by ** subsequent calls to other SQLite interface functions.)^ ** -** ^The sqlite3_errstr() interface returns the English-language text -** that describes the [result code], as UTF-8. +** ^The sqlite3_errstr(E) interface returns the English-language text +** that describes the [result code] E, as UTF-8, or NULL if E is not an +** result code for which a text error message is available. ** ^(Memory to hold the error message string is managed internally ** and must not be freed by the application)^. ** @@ -5638,6 +5660,7 @@ SQLITE_API int sqlite3_finalize(sqlite3_stmt *pStmt); */ SQLITE_API int sqlite3_reset(sqlite3_stmt *pStmt); + /* ** CAPI3REF: Create Or Redefine SQL Functions ** KEYWORDS: {function creation routines} @@ -5884,13 +5907,27 @@ SQLITE_API int sqlite3_create_window_function( **
    ** ** [[SQLITE_SUBTYPE]]
    SQLITE_SUBTYPE
    -** The SQLITE_SUBTYPE flag indicates to SQLite that a function may call +** The SQLITE_SUBTYPE flag indicates to SQLite that a function might call ** [sqlite3_value_subtype()] to inspect the sub-types of its arguments. -** Specifying this flag makes no difference for scalar or aggregate user -** functions. However, if it is not specified for a user-defined window -** function, then any sub-types belonging to arguments passed to the window -** function may be discarded before the window function is called (i.e. -** sqlite3_value_subtype() will always return 0). +** This flag instructs SQLite to omit some corner-case optimizations that +** might disrupt the operation of the [sqlite3_value_subtype()] function, +** causing it to return zero rather than the correct subtype(). +** SQL functions that invokes [sqlite3_value_subtype()] should have this +** property. If the SQLITE_SUBTYPE property is omitted, then the return +** value from [sqlite3_value_subtype()] might sometimes be zero even though +** a non-zero subtype was specified by the function argument expression. +** +** [[SQLITE_RESULT_SUBTYPE]]
    SQLITE_RESULT_SUBTYPE
    +** The SQLITE_RESULT_SUBTYPE flag indicates to SQLite that a function might call +** [sqlite3_result_subtype()] to cause a sub-type to be associated with its +** result. +** Every function that invokes [sqlite3_result_subtype()] should have this +** property. If it does not, then the call to [sqlite3_result_subtype()] +** might become a no-op if the function is used as term in an +** [expression index]. On the other hand, SQL functions that never invoke +** [sqlite3_result_subtype()] should avoid setting this property, as the +** purpose of this property is to disable certain optimizations that are +** incompatible with subtypes. **
    ** */ @@ -5898,6 +5935,7 @@ SQLITE_API int sqlite3_create_window_function( #define SQLITE_DIRECTONLY 0x000080000 #define SQLITE_SUBTYPE 0x000100000 #define SQLITE_INNOCUOUS 0x000200000 +#define SQLITE_RESULT_SUBTYPE 0x001000000 /* ** CAPI3REF: Deprecated Functions @@ -6094,6 +6132,12 @@ SQLITE_API int sqlite3_value_encoding(sqlite3_value*); ** information can be used to pass a limited amount of context from ** one SQL function to another. Use the [sqlite3_result_subtype()] ** routine to set the subtype for the return value of an SQL function. +** +** Every [application-defined SQL function] that invoke this interface +** should include the [SQLITE_SUBTYPE] property in the text +** encoding argument when the function is [sqlite3_create_function|registered]. +** If the [SQLITE_SUBTYPE] property is omitted, then sqlite3_value_subtype() +** might return zero instead of the upstream subtype in some corner cases. */ SQLITE_API unsigned int sqlite3_value_subtype(sqlite3_value*); @@ -6192,48 +6236,56 @@ SQLITE_API sqlite3 *sqlite3_context_db_handle(sqlite3_context*); ** METHOD: sqlite3_context ** ** These functions may be used by (non-aggregate) SQL functions to -** associate metadata with argument values. If the same value is passed to -** multiple invocations of the same SQL function during query execution, under -** some circumstances the associated metadata may be preserved. An example -** of where this might be useful is in a regular-expression matching -** function. The compiled version of the regular expression can be stored as -** metadata associated with the pattern string. +** associate auxiliary data with argument values. If the same argument +** value is passed to multiple invocations of the same SQL function during +** query execution, under some circumstances the associated auxiliary data +** might be preserved. An example of where this might be useful is in a +** regular-expression matching function. The compiled version of the regular +** expression can be stored as auxiliary data associated with the pattern string. ** Then as long as the pattern string remains the same, ** the compiled regular expression can be reused on multiple ** invocations of the same function. ** -** ^The sqlite3_get_auxdata(C,N) interface returns a pointer to the metadata +** ^The sqlite3_get_auxdata(C,N) interface returns a pointer to the auxiliary data ** associated by the sqlite3_set_auxdata(C,N,P,X) function with the Nth argument ** value to the application-defined function. ^N is zero for the left-most -** function argument. ^If there is no metadata +** function argument. ^If there is no auxiliary data ** associated with the function argument, the sqlite3_get_auxdata(C,N) interface ** returns a NULL pointer. ** -** ^The sqlite3_set_auxdata(C,N,P,X) interface saves P as metadata for the N-th -** argument of the application-defined function. ^Subsequent +** ^The sqlite3_set_auxdata(C,N,P,X) interface saves P as auxiliary data for the +** N-th argument of the application-defined function. ^Subsequent ** calls to sqlite3_get_auxdata(C,N) return P from the most recent -** sqlite3_set_auxdata(C,N,P,X) call if the metadata is still valid or -** NULL if the metadata has been discarded. +** sqlite3_set_auxdata(C,N,P,X) call if the auxiliary data is still valid or +** NULL if the auxiliary data has been discarded. ** ^After each call to sqlite3_set_auxdata(C,N,P,X) where X is not NULL, ** SQLite will invoke the destructor function X with parameter P exactly -** once, when the metadata is discarded. -** SQLite is free to discard the metadata at any time, including:
      +** once, when the auxiliary data is discarded. +** SQLite is free to discard the auxiliary data at any time, including:
        **
      • ^(when the corresponding function parameter changes)^, or **
      • ^(when [sqlite3_reset()] or [sqlite3_finalize()] is called for the ** SQL statement)^, or **
      • ^(when sqlite3_set_auxdata() is invoked again on the same ** parameter)^, or **
      • ^(during the original sqlite3_set_auxdata() call when a memory -** allocation error occurs.)^
      +** allocation error occurs.)^ +**
    • ^(during the original sqlite3_set_auxdata() call if the function +** is evaluated during query planning instead of during query execution, +** as sometimes happens with [SQLITE_ENABLE_STAT4].)^
    ** -** Note the last bullet in particular. The destructor X in +** Note the last two bullets in particular. The destructor X in ** sqlite3_set_auxdata(C,N,P,X) might be called immediately, before the ** sqlite3_set_auxdata() interface even returns. Hence sqlite3_set_auxdata() ** should be called near the end of the function implementation and the ** function implementation should not make any use of P after -** sqlite3_set_auxdata() has been called. -** -** ^(In practice, metadata is preserved between function calls for +** sqlite3_set_auxdata() has been called. Furthermore, a call to +** sqlite3_get_auxdata() that occurs immediately after a corresponding call +** to sqlite3_set_auxdata() might still return NULL if an out-of-memory +** condition occurred during the sqlite3_set_auxdata() call or if the +** function is being evaluated during query planning rather than during +** query execution. +** +** ^(In practice, auxiliary data is preserved between function calls for ** function parameters that are compile-time constants, including literal ** values and [parameters] and expressions composed from the same.)^ ** @@ -6243,10 +6295,67 @@ SQLITE_API sqlite3 *sqlite3_context_db_handle(sqlite3_context*); ** ** These routines must be called from the same thread in which ** the SQL function is running. +** +** See also: [sqlite3_get_clientdata()] and [sqlite3_set_clientdata()]. */ SQLITE_API void *sqlite3_get_auxdata(sqlite3_context*, int N); SQLITE_API void sqlite3_set_auxdata(sqlite3_context*, int N, void*, void (*)(void*)); +/* +** CAPI3REF: Database Connection Client Data +** METHOD: sqlite3 +** +** These functions are used to associate one or more named pointers +** with a [database connection]. +** A call to sqlite3_set_clientdata(D,N,P,X) causes the pointer P +** to be attached to [database connection] D using name N. Subsequent +** calls to sqlite3_get_clientdata(D,N) will return a copy of pointer P +** or a NULL pointer if there were no prior calls to +** sqlite3_set_clientdata() with the same values of D and N. +** Names are compared using strcmp() and are thus case sensitive. +** +** If P and X are both non-NULL, then the destructor X is invoked with +** argument P on the first of the following occurrences: +**
      +**
    • An out-of-memory error occurs during the call to +** sqlite3_set_clientdata() which attempts to register pointer P. +**
    • A subsequent call to sqlite3_set_clientdata(D,N,P,X) is made +** with the same D and N parameters. +**
    • The database connection closes. SQLite does not make any guarantees +** about the order in which destructors are called, only that all +** destructors will be called exactly once at some point during the +** database connection closing process. +**
    +** +** SQLite does not do anything with client data other than invoke +** destructors on the client data at the appropriate time. The intended +** use for client data is to provide a mechanism for wrapper libraries +** to store additional information about an SQLite database connection. +** +** There is no limit (other than available memory) on the number of different +** client data pointers (with different names) that can be attached to a +** single database connection. However, the implementation is optimized +** for the case of having only one or two different client data names. +** Applications and wrapper libraries are discouraged from using more than +** one client data name each. +** +** There is no way to enumerate the client data pointers +** associated with a database connection. The N parameter can be thought +** of as a secret key such that only code that knows the secret key is able +** to access the associated data. +** +** Security Warning: These interfaces should not be exposed in scripting +** languages or in other circumstances where it might be possible for an +** an attacker to invoke them. Any agent that can invoke these interfaces +** can probably also take control of the process. +** +** Database connection client data is only available for SQLite +** version 3.44.0 ([dateof:3.44.0]) and later. +** +** See also: [sqlite3_set_auxdata()] and [sqlite3_get_auxdata()]. +*/ +SQLITE_API void *sqlite3_get_clientdata(sqlite3*,const char*); +SQLITE_API int sqlite3_set_clientdata(sqlite3*, const char*, void*, void(*)(void*)); /* ** CAPI3REF: Constants Defining Special Destructor Behavior @@ -6448,6 +6557,20 @@ SQLITE_API int sqlite3_result_zeroblob64(sqlite3_context*, sqlite3_uint64 n); ** higher order bits are discarded. ** The number of subtype bytes preserved by SQLite might increase ** in future releases of SQLite. +** +** Every [application-defined SQL function] that invokes this interface +** should include the [SQLITE_RESULT_SUBTYPE] property in its +** text encoding argument when the SQL function is +** [sqlite3_create_function|registered]. If the [SQLITE_RESULT_SUBTYPE] +** property is omitted from the function that invokes sqlite3_result_subtype(), +** then in some cases the sqlite3_result_subtype() might fail to set +** the result subtype. +** +** If SQLite is compiled with -DSQLITE_STRICT_SUBTYPE=1, then any +** SQL function that invokes the sqlite3_result_subtype() interface +** and that does not have the SQLITE_RESULT_SUBTYPE property will raise +** an error. Future versions of SQLite might enable -DSQLITE_STRICT_SUBTYPE=1 +** by default. */ SQLITE_API void sqlite3_result_subtype(sqlite3_context*,unsigned int); @@ -6879,7 +7002,7 @@ SQLITE_API int sqlite3_db_readonly(sqlite3 *db, const char *zDbName); SQLITE_API int sqlite3_txn_state(sqlite3*,const char *zSchema); /* -** CAPI3REF: Allowed return values from [sqlite3_txn_state()] +** CAPI3REF: Allowed return values from sqlite3_txn_state() ** KEYWORDS: {transaction state} ** ** These constants define the current transaction state of a database file. @@ -7011,7 +7134,7 @@ SQLITE_API void *sqlite3_rollback_hook(sqlite3*, void(*)(void *), void*); ** ^Each call to the sqlite3_autovacuum_pages() interface overrides all ** previous invocations for that database connection. ^If the callback ** argument (C) to sqlite3_autovacuum_pages(D,C,P,X) is a NULL pointer, -** then the autovacuum steps callback is cancelled. The return value +** then the autovacuum steps callback is canceled. The return value ** from sqlite3_autovacuum_pages() is normally SQLITE_OK, but might ** be some other error code if something goes wrong. The current ** implementation will only return SQLITE_OK or SQLITE_MISUSE, but other @@ -7077,6 +7200,12 @@ SQLITE_API int sqlite3_autovacuum_pages( ** The exceptions defined in this paragraph might change in a future ** release of SQLite. ** +** Whether the update hook is invoked before or after the +** corresponding change is currently unspecified and may differ +** depending on the type of change. Do not rely on the order of the +** hook call with regards to the final result of the operation which +** triggers the hook. +** ** The update hook implementation must not do anything that will modify ** the database connection that invoked the update hook. Any actions ** to modify the database connection must be deferred until after the @@ -7530,6 +7659,10 @@ struct sqlite3_module { /* The methods above are in versions 1 and 2 of the sqlite_module object. ** Those below are for version 3 and greater. */ int (*xShadowName)(const char*); + /* The methods above are in versions 1 through 3 of the sqlite_module object. + ** Those below are for version 4 and greater. */ + int (*xIntegrity)(sqlite3_vtab *pVTab, const char *zSchema, + const char *zTabName, int mFlags, char **pzErr); }; /* @@ -8017,7 +8150,7 @@ SQLITE_API int sqlite3_blob_reopen(sqlite3_blob *, sqlite3_int64); ** code is returned and the transaction rolled back. ** ** Calling this function with an argument that is not a NULL pointer or an -** open blob handle results in undefined behaviour. ^Calling this routine +** open blob handle results in undefined behavior. ^Calling this routine ** with a null pointer (such as would be returned by a failed call to ** [sqlite3_blob_open()]) is a harmless no-op. ^Otherwise, if this function ** is passed a valid open blob handle, the values returned by the @@ -8244,9 +8377,11 @@ SQLITE_API int sqlite3_vfs_unregister(sqlite3_vfs*); ** ** ^(Some systems (for example, Windows 95) do not support the operation ** implemented by sqlite3_mutex_try(). On those systems, sqlite3_mutex_try() -** will always return SQLITE_BUSY. The SQLite core only ever uses -** sqlite3_mutex_try() as an optimization so this is acceptable -** behavior.)^ +** will always return SQLITE_BUSY. In most cases the SQLite core only uses +** sqlite3_mutex_try() as an optimization, so this is acceptable +** behavior. The exceptions are unix builds that set the +** SQLITE_ENABLE_SETLK_TIMEOUT build option. In that case a working +** sqlite3_mutex_try() is required.)^ ** ** ^The sqlite3_mutex_leave() routine exits a mutex that was ** previously entered by the same thread. The behavior @@ -8497,6 +8632,7 @@ SQLITE_API int sqlite3_test_control(int op, ...); #define SQLITE_TESTCTRL_PRNG_SAVE 5 #define SQLITE_TESTCTRL_PRNG_RESTORE 6 #define SQLITE_TESTCTRL_PRNG_RESET 7 /* NOT USED */ +#define SQLITE_TESTCTRL_FK_NO_ACTION 7 #define SQLITE_TESTCTRL_BITVEC_TEST 8 #define SQLITE_TESTCTRL_FAULT_INSTALL 9 #define SQLITE_TESTCTRL_BENIGN_MALLOC_HOOKS 10 @@ -8504,6 +8640,7 @@ SQLITE_API int sqlite3_test_control(int op, ...); #define SQLITE_TESTCTRL_ASSERT 12 #define SQLITE_TESTCTRL_ALWAYS 13 #define SQLITE_TESTCTRL_RESERVE 14 /* NOT USED */ +#define SQLITE_TESTCTRL_JSON_SELFCHECK 14 #define SQLITE_TESTCTRL_OPTIMIZATIONS 15 #define SQLITE_TESTCTRL_ISKEYWORD 16 /* NOT USED */ #define SQLITE_TESTCTRL_SCRATCHMALLOC 17 /* NOT USED */ @@ -8539,7 +8676,7 @@ SQLITE_API int sqlite3_test_control(int op, ...); ** The sqlite3_keyword_count() interface returns the number of distinct ** keywords understood by SQLite. ** -** The sqlite3_keyword_name(N,Z,L) interface finds the N-th keyword and +** The sqlite3_keyword_name(N,Z,L) interface finds the 0-based N-th keyword and ** makes *Z point to that keyword expressed as UTF8 and writes the number ** of bytes in the keyword into *L. The string that *Z points to is not ** zero-terminated. The sqlite3_keyword_name(N,Z,L) routine returns @@ -9558,8 +9695,8 @@ SQLITE_API int sqlite3_backup_pagecount(sqlite3_backup *p); ** blocked connection already has a registered unlock-notify callback, ** then the new callback replaces the old.)^ ^If sqlite3_unlock_notify() is ** called with a NULL pointer as its second argument, then any existing -** unlock-notify callback is cancelled. ^The blocked connections -** unlock-notify callback may also be cancelled by closing the blocked +** unlock-notify callback is canceled. ^The blocked connections +** unlock-notify callback may also be canceled by closing the blocked ** connection using [sqlite3_close()]. ** ** The unlock-notify callback is not reentrant. If an application invokes @@ -10118,24 +10255,45 @@ SQLITE_API const char *sqlite3_vtab_collation(sqlite3_index_info*,int); **
  • ** ^(If the sqlite3_vtab_distinct() interface returns 2, that means ** that the query planner does not need the rows returned in any particular -** order, as long as rows with the same values in all "aOrderBy" columns -** are adjacent.)^ ^(Furthermore, only a single row for each particular -** combination of values in the columns identified by the "aOrderBy" field -** needs to be returned.)^ ^It is always ok for two or more rows with the same -** values in all "aOrderBy" columns to be returned, as long as all such rows -** are adjacent. ^The virtual table may, if it chooses, omit extra rows -** that have the same value for all columns identified by "aOrderBy". -** ^However omitting the extra rows is optional. +** order, as long as rows with the same values in all columns identified +** by "aOrderBy" are adjacent.)^ ^(Furthermore, when two or more rows +** contain the same values for all columns identified by "colUsed", all but +** one such row may optionally be omitted from the result.)^ +** The virtual table is not required to omit rows that are duplicates +** over the "colUsed" columns, but if the virtual table can do that without +** too much extra effort, it could potentially help the query to run faster. ** This mode is used for a DISTINCT query. **

  • -** ^(If the sqlite3_vtab_distinct() interface returns 3, that means -** that the query planner needs only distinct rows but it does need the -** rows to be sorted.)^ ^The virtual table implementation is free to omit -** rows that are identical in all aOrderBy columns, if it wants to, but -** it is not required to omit any rows. This mode is used for queries +** ^(If the sqlite3_vtab_distinct() interface returns 3, that means the +** virtual table must return rows in the order defined by "aOrderBy" as +** if the sqlite3_vtab_distinct() interface had returned 0. However if +** two or more rows in the result have the same values for all columns +** identified by "colUsed", then all but one such row may optionally be +** omitted.)^ Like when the return value is 2, the virtual table +** is not required to omit rows that are duplicates over the "colUsed" +** columns, but if the virtual table can do that without +** too much extra effort, it could potentially help the query to run faster. +** This mode is used for queries ** that have both DISTINCT and ORDER BY clauses. ** ** +**

    The following table summarizes the conditions under which the +** virtual table is allowed to set the "orderByConsumed" flag based on +** the value returned by sqlite3_vtab_distinct(). This table is a +** restatement of the previous four paragraphs: +** +** +** +**
    sqlite3_vtab_distinct() return value +** Rows are returned in aOrderBy order +** Rows with the same value in all aOrderBy columns are adjacent +** Duplicates over all colUsed columns may be omitted +**
    0yesyesno +**
    1noyesno +**
    2noyesyes +**
    3yesyesyes +**
    +** ** ^For the purposes of comparing virtual table output values to see if the ** values are same value for sorting purposes, two NULL values are considered ** to be the same. In other words, the comparison operator is "IS" @@ -10862,6 +11020,13 @@ SQLITE_API SQLITE_EXPERIMENTAL int sqlite3_snapshot_recover(sqlite3 *db, const c ** SQLITE_SERIALIZE_NOCOPY bit is set but no contiguous copy ** of the database exists. ** +** After the call, if the SQLITE_SERIALIZE_NOCOPY bit had been set, +** the returned buffer content will remain accessible and unchanged +** until either the next write operation on the connection or when +** the connection is closed, and applications must not modify the +** buffer. If the bit had been clear, the returned buffer will not +** be accessed by SQLite after the call. +** ** A call to sqlite3_serialize(D,S,P,F) might return NULL even if the ** SQLITE_SERIALIZE_NOCOPY bit is omitted from argument F if a memory ** allocation error occurs. @@ -10910,6 +11075,9 @@ SQLITE_API unsigned char *sqlite3_serialize( ** SQLite will try to increase the buffer size using sqlite3_realloc64() ** if writes on the database cause it to grow larger than M bytes. ** +** Applications must not modify the buffer P or invalidate it before +** the database connection D is closed. +** ** The sqlite3_deserialize() interface will fail with SQLITE_BUSY if the ** database is currently in a read transaction or is involved in a backup ** operation. @@ -10918,6 +11086,13 @@ SQLITE_API unsigned char *sqlite3_serialize( ** S argument to sqlite3_deserialize(D,S,P,N,M,F) is "temp" then the ** function returns SQLITE_ERROR. ** +** The deserialized database should not be in [WAL mode]. If the database +** is in WAL mode, then any attempt to use the database file will result +** in an [SQLITE_CANTOPEN] error. The application can set the +** [file format version numbers] (bytes 18 and 19) of the input database P +** to 0x01 prior to invoking sqlite3_deserialize(D,S,P,N,M,F) to force the +** database file into rollback mode and work around this limitation. +** ** If sqlite3_deserialize(D,S,P,N,M,F) fails for any reason and if the ** SQLITE_DESERIALIZE_FREEONCLOSE bit is set in argument F, then ** [sqlite3_free()] is invoked on argument P prior to returning. @@ -11990,6 +12165,18 @@ SQLITE_API int sqlite3changeset_concat( ); +/* +** CAPI3REF: Upgrade the Schema of a Changeset/Patchset +*/ +SQLITE_API int sqlite3changeset_upgrade( + sqlite3 *db, + const char *zDb, + int nIn, const void *pIn, /* Input changeset */ + int *pnOut, void **ppOut /* OUT: Inverse of input */ +); + + + /* ** CAPI3REF: Changegroup Handle ** @@ -12036,6 +12223,38 @@ typedef struct sqlite3_changegroup sqlite3_changegroup; */ SQLITE_API int sqlite3changegroup_new(sqlite3_changegroup **pp); +/* +** CAPI3REF: Add a Schema to a Changegroup +** METHOD: sqlite3_changegroup_schema +** +** This method may be used to optionally enforce the rule that the changesets +** added to the changegroup handle must match the schema of database zDb +** ("main", "temp", or the name of an attached database). If +** sqlite3changegroup_add() is called to add a changeset that is not compatible +** with the configured schema, SQLITE_SCHEMA is returned and the changegroup +** object is left in an undefined state. +** +** A changeset schema is considered compatible with the database schema in +** the same way as for sqlite3changeset_apply(). Specifically, for each +** table in the changeset, there exists a database table with: +** +**

      +**
    • The name identified by the changeset, and +**
    • at least as many columns as recorded in the changeset, and +**
    • the primary key columns in the same position as recorded in +** the changeset. +**
    +** +** The output of the changegroup object always has the same schema as the +** database nominated using this function. In cases where changesets passed +** to sqlite3changegroup_add() have fewer columns than the corresponding table +** in the database schema, these are filled in using the default column +** values from the database schema. This makes it possible to combined +** changesets that have different numbers of columns for a single table +** within a changegroup, provided that they are otherwise compatible. +*/ +SQLITE_API int sqlite3changegroup_schema(sqlite3_changegroup*, sqlite3*, const char *zDb); + /* ** CAPI3REF: Add A Changeset To A Changegroup ** METHOD: sqlite3_changegroup @@ -12104,16 +12323,45 @@ SQLITE_API int sqlite3changegroup_new(sqlite3_changegroup **pp); ** If the new changeset contains changes to a table that is already present ** in the changegroup, then the number of columns and the position of the ** primary key columns for the table must be consistent. If this is not the -** case, this function fails with SQLITE_SCHEMA. If the input changeset -** appears to be corrupt and the corruption is detected, SQLITE_CORRUPT is -** returned. Or, if an out-of-memory condition occurs during processing, this -** function returns SQLITE_NOMEM. In all cases, if an error occurs the state -** of the final contents of the changegroup is undefined. +** case, this function fails with SQLITE_SCHEMA. Except, if the changegroup +** object has been configured with a database schema using the +** sqlite3changegroup_schema() API, then it is possible to combine changesets +** with different numbers of columns for a single table, provided that +** they are otherwise compatible. ** -** If no error occurs, SQLITE_OK is returned. +** If the input changeset appears to be corrupt and the corruption is +** detected, SQLITE_CORRUPT is returned. Or, if an out-of-memory condition +** occurs during processing, this function returns SQLITE_NOMEM. +** +** In all cases, if an error occurs the state of the final contents of the +** changegroup is undefined. If no error occurs, SQLITE_OK is returned. */ SQLITE_API int sqlite3changegroup_add(sqlite3_changegroup*, int nData, void *pData); +/* +** CAPI3REF: Add A Single Change To A Changegroup +** METHOD: sqlite3_changegroup +** +** This function adds the single change currently indicated by the iterator +** passed as the second argument to the changegroup object. The rules for +** adding the change are just as described for [sqlite3changegroup_add()]. +** +** If the change is successfully added to the changegroup, SQLITE_OK is +** returned. Otherwise, an SQLite error code is returned. +** +** The iterator must point to a valid entry when this function is called. +** If it does not, SQLITE_ERROR is returned and no change is added to the +** changegroup. Additionally, the iterator must not have been opened with +** the SQLITE_CHANGESETAPPLY_INVERT flag. In this case SQLITE_ERROR is also +** returned. +*/ +SQLITE_API int sqlite3changegroup_add_change( + sqlite3_changegroup*, + sqlite3_changeset_iter* +); + + + /* ** CAPI3REF: Obtain A Composite Changeset From A Changegroup ** METHOD: sqlite3_changegroup @@ -12375,10 +12623,17 @@ SQLITE_API int sqlite3changeset_apply_v2( **
  • an insert change if all fields of the conflicting row match ** the row being inserted. ** +** +**
    SQLITE_CHANGESETAPPLY_FKNOACTION
    +** If this flag it set, then all foreign key constraints in the target +** database behave as if they were declared with "ON UPDATE NO ACTION ON +** DELETE NO ACTION", even if they are actually CASCADE, RESTRICT, SET NULL +** or SET DEFAULT. */ #define SQLITE_CHANGESETAPPLY_NOSAVEPOINT 0x0001 #define SQLITE_CHANGESETAPPLY_INVERT 0x0002 #define SQLITE_CHANGESETAPPLY_IGNORENOOP 0x0004 +#define SQLITE_CHANGESETAPPLY_FKNOACTION 0x0008 /* ** CAPI3REF: Constants Passed To The Conflict Handler @@ -12911,8 +13166,8 @@ struct Fts5PhraseIter { ** EXTENSION API FUNCTIONS ** ** xUserData(pFts): -** Return a copy of the context pointer the extension function was -** registered with. +** Return a copy of the pUserData pointer passed to the xCreateFunction() +** API when the extension function was registered. ** ** xColumnTotalSize(pFts, iCol, pnToken): ** If parameter iCol is less than zero, set output variable *pnToken @@ -12944,8 +13199,11 @@ struct Fts5PhraseIter { ** created with the "columnsize=0" option. ** ** xColumnText: -** This function attempts to retrieve the text of column iCol of the -** current document. If successful, (*pz) is set to point to a buffer +** If parameter iCol is less than zero, or greater than or equal to the +** number of columns in the table, SQLITE_RANGE is returned. +** +** Otherwise, this function attempts to retrieve the text of column iCol of +** the current document. If successful, (*pz) is set to point to a buffer ** containing the text in utf-8 encoding, (*pn) is set to the size in bytes ** (not characters) of the buffer and SQLITE_OK is returned. Otherwise, ** if an error occurs, an SQLite error code is returned and the final values @@ -12955,8 +13213,10 @@ struct Fts5PhraseIter { ** Returns the number of phrases in the current query expression. ** ** xPhraseSize: -** Returns the number of tokens in phrase iPhrase of the query. Phrases -** are numbered starting from zero. +** If parameter iCol is less than zero, or greater than or equal to the +** number of phrases in the current query, as returned by xPhraseCount, +** 0 is returned. Otherwise, this function returns the number of tokens in +** phrase iPhrase of the query. Phrases are numbered starting from zero. ** ** xInstCount: ** Set *pnInst to the total number of occurrences of all phrases within @@ -12972,12 +13232,13 @@ struct Fts5PhraseIter { ** Query for the details of phrase match iIdx within the current row. ** Phrase matches are numbered starting from zero, so the iIdx argument ** should be greater than or equal to zero and smaller than the value -** output by xInstCount(). +** output by xInstCount(). If iIdx is less than zero or greater than +** or equal to the value returned by xInstCount(), SQLITE_RANGE is returned. ** -** Usually, output parameter *piPhrase is set to the phrase number, *piCol +** Otherwise, output parameter *piPhrase is set to the phrase number, *piCol ** to the column in which it occurs and *piOff the token offset of the -** first token of the phrase. Returns SQLITE_OK if successful, or an error -** code (i.e. SQLITE_NOMEM) if an error occurs. +** first token of the phrase. SQLITE_OK is returned if successful, or an +** error code (i.e. SQLITE_NOMEM) if an error occurs. ** ** This API can be quite slow if used with an FTS5 table created with the ** "detail=none" or "detail=column" option. @@ -13003,6 +13264,10 @@ struct Fts5PhraseIter { ** Invoking Api.xUserData() returns a copy of the pointer passed as ** the third argument to pUserData. ** +** If parameter iPhrase is less than zero, or greater than or equal to +** the number of phrases in the query, as returned by xPhraseCount(), +** this function returns SQLITE_RANGE. +** ** If the callback function returns any value other than SQLITE_OK, the ** query is abandoned and the xQueryPhrase function returns immediately. ** If the returned value is SQLITE_DONE, xQueryPhrase returns SQLITE_OK. @@ -13117,9 +13382,42 @@ struct Fts5PhraseIter { ** ** xPhraseNextColumn() ** See xPhraseFirstColumn above. +** +** xQueryToken(pFts5, iPhrase, iToken, ppToken, pnToken) +** This is used to access token iToken of phrase iPhrase of the current +** query. Before returning, output parameter *ppToken is set to point +** to a buffer containing the requested token, and *pnToken to the +** size of this buffer in bytes. +** +** If iPhrase or iToken are less than zero, or if iPhrase is greater than +** or equal to the number of phrases in the query as reported by +** xPhraseCount(), or if iToken is equal to or greater than the number of +** tokens in the phrase, SQLITE_RANGE is returned and *ppToken and *pnToken + are both zeroed. +** +** The output text is not a copy of the query text that specified the +** token. It is the output of the tokenizer module. For tokendata=1 +** tables, this includes any embedded 0x00 and trailing data. +** +** xInstToken(pFts5, iIdx, iToken, ppToken, pnToken) +** This is used to access token iToken of phrase hit iIdx within the +** current row. If iIdx is less than zero or greater than or equal to the +** value returned by xInstCount(), SQLITE_RANGE is returned. Otherwise, +** output variable (*ppToken) is set to point to a buffer containing the +** matching document token, and (*pnToken) to the size of that buffer in +** bytes. This API is not available if the specified token matches a +** prefix query term. In that case both output variables are always set +** to 0. +** +** The output text is not a copy of the document text that was tokenized. +** It is the output of the tokenizer module. For tokendata=1 tables, this +** includes any embedded 0x00 and trailing data. +** +** This API can be quite slow if used with an FTS5 table created with the +** "detail=none" or "detail=column" option. */ struct Fts5ExtensionApi { - int iVersion; /* Currently always set to 2 */ + int iVersion; /* Currently always set to 3 */ void *(*xUserData)(Fts5Context*); @@ -13154,6 +13452,13 @@ struct Fts5ExtensionApi { int (*xPhraseFirstColumn)(Fts5Context*, int iPhrase, Fts5PhraseIter*, int*); void (*xPhraseNextColumn)(Fts5Context*, Fts5PhraseIter*, int *piCol); + + /* Below this point are iVersion>=3 only */ + int (*xQueryToken)(Fts5Context*, + int iPhrase, int iToken, + const char **ppToken, int *pnToken + ); + int (*xInstToken)(Fts5Context*, int iIdx, int iToken, const char**, int*); }; /* @@ -13640,7 +13945,7 @@ struct fts5_api { ** max_page_count macro. */ #ifndef SQLITE_MAX_PAGE_COUNT -# define SQLITE_MAX_PAGE_COUNT 1073741823 +# define SQLITE_MAX_PAGE_COUNT 0xfffffffe /* 4294967294 */ #endif /* @@ -13769,6 +14074,29 @@ struct fts5_api { # endif #endif +/* +** Enable SQLITE_USE_SEH by default on MSVC builds. Only omit +** SEH support if the -DSQLITE_OMIT_SEH option is given. +*/ +#if defined(_MSC_VER) && !defined(SQLITE_OMIT_SEH) +# define SQLITE_USE_SEH 1 +#else +# undef SQLITE_USE_SEH +#endif + +/* +** Enable SQLITE_DIRECT_OVERFLOW_READ, unless the build explicitly +** disables it using -DSQLITE_DIRECT_OVERFLOW_READ=0 +*/ +#if defined(SQLITE_DIRECT_OVERFLOW_READ) && SQLITE_DIRECT_OVERFLOW_READ+1==1 + /* Disable if -DSQLITE_DIRECT_OVERFLOW_READ=0 */ +# undef SQLITE_DIRECT_OVERFLOW_READ +#else + /* In all other cases, enable */ +# define SQLITE_DIRECT_OVERFLOW_READ 1 +#endif + + /* ** The SQLITE_THREADSAFE macro must be defined as 0, 1, or 2. ** 0 means mutexes are permanently disable and the library is never @@ -14037,6 +14365,8 @@ struct fts5_api { # define SQLITE_OMIT_ALTERTABLE #endif +#define SQLITE_DIGIT_SEPARATOR '_' + /* ** Return true (non-zero) if the input is an integer that is too large ** to fit in 32-bits. This macro is used inside of various testcase() @@ -14329,8 +14659,8 @@ SQLITE_PRIVATE void sqlite3HashClear(Hash*); #define TK_TRUEFALSE 170 #define TK_ISNOT 171 #define TK_FUNCTION 172 -#define TK_UMINUS 173 -#define TK_UPLUS 174 +#define TK_UPLUS 173 +#define TK_UMINUS 174 #define TK_TRUTH 175 #define TK_REGISTER 176 #define TK_VECTOR 177 @@ -14339,8 +14669,9 @@ SQLITE_PRIVATE void sqlite3HashClear(Hash*); #define TK_ASTERISK 180 #define TK_SPAN 181 #define TK_ERROR 182 -#define TK_SPACE 183 -#define TK_ILLEGAL 184 +#define TK_QNUMBER 183 +#define TK_SPACE 184 +#define TK_ILLEGAL 185 /************** End of parse.h ***********************************************/ /************** Continuing where we left off in sqliteInt.h ******************/ @@ -14602,7 +14933,7 @@ typedef INT16_TYPE LogEst; # define SQLITE_PTRSIZE __SIZEOF_POINTER__ # elif defined(i386) || defined(__i386__) || defined(_M_IX86) || \ defined(_M_ARM) || defined(__arm__) || defined(__x86) || \ - (defined(__APPLE__) && defined(__POWERPC__)) || \ + (defined(__APPLE__) && defined(__ppc__)) || \ (defined(__TOS_AIX__) && !defined(__64BIT__)) # define SQLITE_PTRSIZE 4 # else @@ -14662,16 +14993,33 @@ typedef INT16_TYPE LogEst; ** using C-preprocessor macros. If that is unsuccessful, or if ** -DSQLITE_BYTEORDER=0 is set, then byte-order is determined ** at run-time. +** +** If you are building SQLite on some obscure platform for which the +** following ifdef magic does not work, you can always include either: +** +** -DSQLITE_BYTEORDER=1234 +** +** or +** +** -DSQLITE_BYTEORDER=4321 +** +** to cause the build to work for little-endian or big-endian processors, +** respectively. */ -#ifndef SQLITE_BYTEORDER -# if defined(i386) || defined(__i386__) || defined(_M_IX86) || \ +#ifndef SQLITE_BYTEORDER /* Replicate changes at tag-20230904a */ +# if defined(__BYTE_ORDER__) && __BYTE_ORDER__==__ORDER_BIG_ENDIAN__ +# define SQLITE_BYTEORDER 4321 +# elif defined(__BYTE_ORDER__) && __BYTE_ORDER__==__ORDER_LITTLE_ENDIAN__ +# define SQLITE_BYTEORDER 1234 +# elif defined(__BIG_ENDIAN__) && __BIG_ENDIAN__==1 +# define SQLITE_BYTEORDER 4321 +# elif defined(i386) || defined(__i386__) || defined(_M_IX86) || \ defined(__x86_64) || defined(__x86_64__) || defined(_M_X64) || \ defined(_M_AMD64) || defined(_M_ARM) || defined(__x86) || \ defined(__ARMEL__) || defined(__AARCH64EL__) || defined(_M_ARM64) -# define SQLITE_BYTEORDER 1234 -# elif defined(sparc) || defined(__ppc__) || \ - defined(__ARMEB__) || defined(__AARCH64EB__) -# define SQLITE_BYTEORDER 4321 +# define SQLITE_BYTEORDER 1234 +# elif defined(sparc) || defined(__ARMEB__) || defined(__AARCH64EB__) +# define SQLITE_BYTEORDER 4321 # else # define SQLITE_BYTEORDER 0 # endif @@ -14822,6 +15170,7 @@ SQLITE_PRIVATE u32 sqlite3TreeTrace; ** 0x00010000 Beginning of DELETE/INSERT/UPDATE processing ** 0x00020000 Transform DISTINCT into GROUP BY ** 0x00040000 SELECT tree dump after all code has been generated +** 0x00080000 NOT NULL strength reduction */ /* @@ -14852,7 +15201,7 @@ SQLITE_PRIVATE u32 sqlite3WhereTrace; ** 0x00000010 Display sqlite3_index_info xBestIndex calls ** 0x00000020 Range an equality scan metrics ** 0x00000040 IN operator decisions -** 0x00000080 WhereLoop cost adjustements +** 0x00000080 WhereLoop cost adjustments ** 0x00000100 ** 0x00000200 Covering index decisions ** 0x00000400 OR optimization @@ -14995,6 +15344,7 @@ typedef struct Column Column; typedef struct Cte Cte; typedef struct CteUse CteUse; typedef struct Db Db; +typedef struct DbClientData DbClientData; typedef struct DbFixer DbFixer; typedef struct Schema Schema; typedef struct Expr Expr; @@ -15633,7 +15983,7 @@ SQLITE_PRIVATE sqlite3_file *sqlite3PagerJrnlFile(Pager*); SQLITE_PRIVATE const char *sqlite3PagerJournalname(Pager*); SQLITE_PRIVATE void *sqlite3PagerTempSpace(Pager*); SQLITE_PRIVATE int sqlite3PagerIsMemdb(Pager*); -SQLITE_PRIVATE void sqlite3PagerCacheStat(Pager *, int, int, int *); +SQLITE_PRIVATE void sqlite3PagerCacheStat(Pager *, int, int, u64*); SQLITE_PRIVATE void sqlite3PagerClearCache(Pager*); SQLITE_PRIVATE int sqlite3SectorSize(sqlite3_file *); @@ -16000,6 +16350,7 @@ SQLITE_PRIVATE int sqlite3BtreeIntegrityCheck( sqlite3 *db, /* Database connection that is running the check */ Btree *p, /* The btree to be checked */ Pgno *aRoot, /* An array of root pages numbers for individual trees */ + sqlite3_value *aCnt, /* OUT: entry counts for each btree in aRoot[] */ int nRoot, /* Number of entries in aRoot[] */ int mxErr, /* Stop reporting errors after this many */ int *pnErr, /* OUT: Write number of errors seen to this variable */ @@ -16220,6 +16571,7 @@ typedef struct VdbeOpList VdbeOpList; #define P4_INT64 (-13) /* P4 is a 64-bit signed integer */ #define P4_INTARRAY (-14) /* P4 is a vector of 32-bit integers */ #define P4_FUNCCTX (-15) /* P4 is a pointer to an sqlite3_context object */ +#define P4_TABLEREF (-16) /* Like P4_TABLE, but reference counted */ /* Error message codes for OP_Halt */ #define P5_ConstraintNotNull 1 @@ -16269,12 +16621,12 @@ typedef struct VdbeOpList VdbeOpList; #define OP_Vacuum 5 #define OP_VFilter 6 /* jump, synopsis: iplan=r[P3] zplan='P4' */ #define OP_VUpdate 7 /* synopsis: data=r[P3@P2] */ -#define OP_Init 8 /* jump, synopsis: Start at P2 */ +#define OP_Init 8 /* jump0, synopsis: Start at P2 */ #define OP_Goto 9 /* jump */ #define OP_Gosub 10 /* jump */ -#define OP_InitCoroutine 11 /* jump */ -#define OP_Yield 12 /* jump */ -#define OP_MustBeInt 13 /* jump */ +#define OP_InitCoroutine 11 /* jump0 */ +#define OP_Yield 12 /* jump0 */ +#define OP_MustBeInt 13 /* jump0 */ #define OP_Jump 14 /* jump */ #define OP_Once 15 /* jump */ #define OP_If 16 /* jump */ @@ -16282,22 +16634,22 @@ typedef struct VdbeOpList VdbeOpList; #define OP_IsType 18 /* jump, synopsis: if typeof(P1.P3) in P5 goto P2 */ #define OP_Not 19 /* same as TK_NOT, synopsis: r[P2]= !r[P1] */ #define OP_IfNullRow 20 /* jump, synopsis: if P1.nullRow then r[P3]=NULL, goto P2 */ -#define OP_SeekLT 21 /* jump, synopsis: key=r[P3@P4] */ -#define OP_SeekLE 22 /* jump, synopsis: key=r[P3@P4] */ -#define OP_SeekGE 23 /* jump, synopsis: key=r[P3@P4] */ -#define OP_SeekGT 24 /* jump, synopsis: key=r[P3@P4] */ +#define OP_SeekLT 21 /* jump0, synopsis: key=r[P3@P4] */ +#define OP_SeekLE 22 /* jump0, synopsis: key=r[P3@P4] */ +#define OP_SeekGE 23 /* jump0, synopsis: key=r[P3@P4] */ +#define OP_SeekGT 24 /* jump0, synopsis: key=r[P3@P4] */ #define OP_IfNotOpen 25 /* jump, synopsis: if( !csr[P1] ) goto P2 */ #define OP_IfNoHope 26 /* jump, synopsis: key=r[P3@P4] */ #define OP_NoConflict 27 /* jump, synopsis: key=r[P3@P4] */ #define OP_NotFound 28 /* jump, synopsis: key=r[P3@P4] */ #define OP_Found 29 /* jump, synopsis: key=r[P3@P4] */ -#define OP_SeekRowid 30 /* jump, synopsis: intkey=r[P3] */ +#define OP_SeekRowid 30 /* jump0, synopsis: intkey=r[P3] */ #define OP_NotExists 31 /* jump, synopsis: intkey=r[P3] */ -#define OP_Last 32 /* jump */ -#define OP_IfSmaller 33 /* jump */ +#define OP_Last 32 /* jump0 */ +#define OP_IfSizeBetween 33 /* jump */ #define OP_SorterSort 34 /* jump */ #define OP_Sort 35 /* jump */ -#define OP_Rewind 36 /* jump */ +#define OP_Rewind 36 /* jump0 */ #define OP_SorterNext 37 /* jump */ #define OP_Prev 38 /* jump */ #define OP_Next 39 /* jump */ @@ -16309,7 +16661,7 @@ typedef struct VdbeOpList VdbeOpList; #define OP_IdxGE 45 /* jump, synopsis: key=r[P3@P4] */ #define OP_RowSetRead 46 /* jump, synopsis: r[P3]=rowset(P1) */ #define OP_RowSetTest 47 /* jump, synopsis: if r[P3] in rowset(P1) goto P2 */ -#define OP_Program 48 /* jump */ +#define OP_Program 48 /* jump0 */ #define OP_FkIfZero 49 /* jump, synopsis: if fkctr[P1]==0 goto P2 */ #define OP_IsNull 50 /* jump, same as TK_ISNULL, synopsis: if r[P1]==NULL goto P2 */ #define OP_NotNull 51 /* jump, same as TK_NOTNULL, synopsis: if r[P1]!=NULL goto P2 */ @@ -16339,7 +16691,7 @@ typedef struct VdbeOpList VdbeOpList; #define OP_Null 75 /* synopsis: r[P2..P3]=NULL */ #define OP_SoftNull 76 /* synopsis: r[P1]=NULL */ #define OP_Blob 77 /* synopsis: r[P2]=P4 (len=P1) */ -#define OP_Variable 78 /* synopsis: r[P2]=parameter(P1,P4) */ +#define OP_Variable 78 /* synopsis: r[P2]=parameter(P1) */ #define OP_Move 79 /* synopsis: r[P2@P3]=r[P1@P3] */ #define OP_Copy 80 /* synopsis: r[P2@P3+1]=r[P1@P3+1] */ #define OP_SCopy 81 /* synopsis: r[P2]=r[P1] */ @@ -16435,19 +16787,22 @@ typedef struct VdbeOpList VdbeOpList; #define OP_VCreate 171 #define OP_VDestroy 172 #define OP_VOpen 173 -#define OP_VInitIn 174 /* synopsis: r[P2]=ValueList(P1,P3) */ -#define OP_VColumn 175 /* synopsis: r[P3]=vcolumn(P2) */ -#define OP_VRename 176 -#define OP_Pagecount 177 -#define OP_MaxPgcnt 178 -#define OP_ClrSubtype 179 /* synopsis: r[P1].subtype = 0 */ -#define OP_FilterAdd 180 /* synopsis: filter(P1) += key(P3@P4) */ -#define OP_Trace 181 -#define OP_CursorHint 182 -#define OP_ReleaseReg 183 /* synopsis: release r[P1@P2] mask P3 */ -#define OP_Noop 184 -#define OP_Explain 185 -#define OP_Abortable 186 +#define OP_VCheck 174 +#define OP_VInitIn 175 /* synopsis: r[P2]=ValueList(P1,P3) */ +#define OP_VColumn 176 /* synopsis: r[P3]=vcolumn(P2) */ +#define OP_VRename 177 +#define OP_Pagecount 178 +#define OP_MaxPgcnt 179 +#define OP_ClrSubtype 180 /* synopsis: r[P1].subtype = 0 */ +#define OP_GetSubtype 181 /* synopsis: r[P2] = r[P1].subtype */ +#define OP_SetSubtype 182 /* synopsis: r[P2].subtype = r[P1] */ +#define OP_FilterAdd 183 /* synopsis: filter(P1) += key(P3@P4) */ +#define OP_Trace 184 +#define OP_CursorHint 185 +#define OP_ReleaseReg 186 /* synopsis: release r[P1@P2] mask P3 */ +#define OP_Noop 187 +#define OP_Explain 188 +#define OP_Abortable 189 /* Properties such as "out2" or "jump" that are specified in ** comments following the "case" for each opcode in the vdbe.c @@ -16460,14 +16815,15 @@ typedef struct VdbeOpList VdbeOpList; #define OPFLG_OUT2 0x10 /* out2: P2 is an output */ #define OPFLG_OUT3 0x20 /* out3: P3 is an output */ #define OPFLG_NCYCLE 0x40 /* ncycle:Cycles count against P1 */ +#define OPFLG_JUMP0 0x80 /* jump0: P2 might be zero */ #define OPFLG_INITIALIZER {\ /* 0 */ 0x00, 0x00, 0x00, 0x00, 0x10, 0x00, 0x41, 0x00,\ -/* 8 */ 0x01, 0x01, 0x01, 0x01, 0x03, 0x03, 0x01, 0x01,\ -/* 16 */ 0x03, 0x03, 0x01, 0x12, 0x01, 0x49, 0x49, 0x49,\ -/* 24 */ 0x49, 0x01, 0x49, 0x49, 0x49, 0x49, 0x49, 0x49,\ -/* 32 */ 0x41, 0x01, 0x41, 0x41, 0x41, 0x01, 0x41, 0x41,\ +/* 8 */ 0x81, 0x01, 0x01, 0x81, 0x83, 0x83, 0x01, 0x01,\ +/* 16 */ 0x03, 0x03, 0x01, 0x12, 0x01, 0xc9, 0xc9, 0xc9,\ +/* 24 */ 0xc9, 0x01, 0x49, 0x49, 0x49, 0x49, 0xc9, 0x49,\ +/* 32 */ 0xc1, 0x01, 0x41, 0x41, 0xc1, 0x01, 0x41, 0x41,\ /* 40 */ 0x41, 0x41, 0x41, 0x26, 0x26, 0x41, 0x23, 0x0b,\ -/* 48 */ 0x01, 0x01, 0x03, 0x03, 0x0b, 0x0b, 0x0b, 0x0b,\ +/* 48 */ 0x81, 0x01, 0x03, 0x03, 0x0b, 0x0b, 0x0b, 0x0b,\ /* 56 */ 0x0b, 0x0b, 0x01, 0x03, 0x03, 0x03, 0x01, 0x41,\ /* 64 */ 0x01, 0x00, 0x00, 0x02, 0x02, 0x08, 0x00, 0x10,\ /* 72 */ 0x10, 0x10, 0x00, 0x10, 0x00, 0x10, 0x10, 0x00,\ @@ -16482,9 +16838,9 @@ typedef struct VdbeOpList VdbeOpList; /* 144 */ 0x10, 0x00, 0x00, 0x10, 0x00, 0x00, 0x00, 0x00,\ /* 152 */ 0x00, 0x10, 0x00, 0x00, 0x06, 0x10, 0x00, 0x04,\ /* 160 */ 0x1a, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,\ -/* 168 */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x40, 0x50, 0x40,\ -/* 176 */ 0x00, 0x10, 0x10, 0x02, 0x00, 0x00, 0x00, 0x00,\ -/* 184 */ 0x00, 0x00, 0x00,} +/* 168 */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x40, 0x10, 0x50,\ +/* 176 */ 0x40, 0x00, 0x10, 0x10, 0x02, 0x12, 0x12, 0x00,\ +/* 184 */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,} /* The resolve3P2Values() routine is able to run faster if it knows ** the value of the largest JUMP opcode. The smaller the maximum @@ -16627,6 +16983,8 @@ SQLITE_PRIVATE RecordCompare sqlite3VdbeFindCompare(UnpackedRecord*); SQLITE_PRIVATE void sqlite3VdbeLinkSubProgram(Vdbe *, SubProgram *); SQLITE_PRIVATE int sqlite3VdbeHasSubProgram(Vdbe*); +SQLITE_PRIVATE void sqlite3MemSetArrayInt64(sqlite3_value *aMem, int iIdx, i64 val); + SQLITE_PRIVATE int sqlite3NotPureFunc(sqlite3_context*); #ifdef SQLITE_ENABLE_BYTECODE_VTAB SQLITE_PRIVATE int sqlite3VdbeBytecodeVtabInit(sqlite3*); @@ -17214,6 +17572,10 @@ struct FuncDefHash { }; #define SQLITE_FUNC_HASH(C,L) (((C)+(L))%SQLITE_FUNC_HASH_SZ) +#if defined(SQLITE_USER_AUTHENTICATION) +# warning "The SQLITE_USER_AUTHENTICATION extension is deprecated. \ + See ext/userauth/user-auth.txt for details." +#endif #ifdef SQLITE_USER_AUTHENTICATION /* ** Information held in the "sqlite3" database connection object and used @@ -17393,6 +17755,7 @@ struct sqlite3 { i64 nDeferredCons; /* Net deferred constraints this transaction. */ i64 nDeferredImmCons; /* Net deferred immediate constraints */ int *pnBytesFreed; /* If not NULL, increment this in DbFree() */ + DbClientData *pDbData; /* sqlite3_set_clientdata() content */ #ifdef SQLITE_ENABLE_UNLOCK_NOTIFY /* The following variables are all protected by the STATIC_MAIN ** mutex, not by sqlite3.mutex. They are used by code in notify.c. @@ -17475,6 +17838,7 @@ struct sqlite3 { /* the count using a callback. */ #define SQLITE_CorruptRdOnly HI(0x00002) /* Prohibit writes due to error */ #define SQLITE_ReadUncommit HI(0x00004) /* READ UNCOMMITTED in shared-cache */ +#define SQLITE_FkNoAction HI(0x00008) /* Treat all FK as NO ACTION */ /* Flags used only if debugging */ #ifdef SQLITE_DEBUG @@ -17515,7 +17879,7 @@ struct sqlite3 { #define SQLITE_CursorHints 0x00000400 /* Add OP_CursorHint opcodes */ #define SQLITE_Stat4 0x00000800 /* Use STAT4 data */ /* TH3 expects this value ^^^^^^^^^^ to be 0x0000800. Don't change it */ -#define SQLITE_PushDown 0x00001000 /* The push-down optimization */ +#define SQLITE_PushDown 0x00001000 /* WHERE-clause push-down opt */ #define SQLITE_SimplifyJoin 0x00002000 /* Convert LEFT JOIN to JOIN */ #define SQLITE_SkipScan 0x00004000 /* Skip-scans */ #define SQLITE_PropagateConst 0x00008000 /* The constant propagation opt */ @@ -17643,14 +18007,15 @@ struct FuncDestructor { #define SQLITE_FUNC_SLOCHNG 0x2000 /* "Slow Change". Value constant during a ** single query - might change over time */ #define SQLITE_FUNC_TEST 0x4000 /* Built-in testing functions */ -/* 0x8000 -- available for reuse */ +#define SQLITE_FUNC_RUNONLY 0x8000 /* Cannot be used by valueFromFunction */ #define SQLITE_FUNC_WINDOW 0x00010000 /* Built-in window-only function */ #define SQLITE_FUNC_INTERNAL 0x00040000 /* For use by NestedParse() only */ #define SQLITE_FUNC_DIRECT 0x00080000 /* Not for use in TRIGGERs or VIEWs */ -#define SQLITE_FUNC_SUBTYPE 0x00100000 /* Result likely to have sub-type */ +/* SQLITE_SUBTYPE 0x00100000 // Consumer of subtypes */ #define SQLITE_FUNC_UNSAFE 0x00200000 /* Function has side effects */ #define SQLITE_FUNC_INLINE 0x00400000 /* Functions implemented in-line */ #define SQLITE_FUNC_BUILTIN 0x00800000 /* This is a built-in function */ +/* SQLITE_RESULT_SUBTYPE 0x01000000 // Generator of subtypes */ #define SQLITE_FUNC_ANYORDER 0x08000000 /* count/min/max aggregate */ /* Identifier numbers for each in-line function */ @@ -17742,10 +18107,11 @@ struct FuncDestructor { #define MFUNCTION(zName, nArg, xPtr, xFunc) \ {nArg, SQLITE_FUNC_BUILTIN|SQLITE_FUNC_CONSTANT|SQLITE_UTF8, \ xPtr, 0, xFunc, 0, 0, 0, #zName, {0} } -#define JFUNCTION(zName, nArg, iArg, xFunc) \ - {nArg, SQLITE_FUNC_BUILTIN|SQLITE_DETERMINISTIC|\ - SQLITE_FUNC_CONSTANT|SQLITE_UTF8, \ - SQLITE_INT_TO_PTR(iArg), 0, xFunc, 0, 0, 0, #zName, {0} } +#define JFUNCTION(zName, nArg, bUseCache, bWS, bRS, bJsonB, iArg, xFunc) \ + {nArg, SQLITE_FUNC_BUILTIN|SQLITE_DETERMINISTIC|SQLITE_FUNC_CONSTANT|\ + SQLITE_UTF8|((bUseCache)*SQLITE_FUNC_RUNONLY)|\ + ((bRS)*SQLITE_SUBTYPE)|((bWS)*SQLITE_RESULT_SUBTYPE), \ + SQLITE_INT_TO_PTR(iArg|((bJsonB)*JSON_BLOB)),0,xFunc,0, 0, 0, #zName, {0} } #define INLINE_FUNC(zName, nArg, iArg, mFlags) \ {nArg, SQLITE_FUNC_BUILTIN|\ SQLITE_UTF8|SQLITE_FUNC_INLINE|SQLITE_FUNC_CONSTANT|(mFlags), \ @@ -18086,8 +18452,7 @@ struct Table { #define TF_HasStored 0x00000040 /* Has one or more STORED columns */ #define TF_HasGenerated 0x00000060 /* Combo: HasVirtual + HasStored */ #define TF_WithoutRowid 0x00000080 /* No rowid. PRIMARY KEY is the key */ -#define TF_StatsUsed 0x00000100 /* Query planner decisions affected by - ** Index.aiRowLogEst[] values */ +#define TF_MaybeReanalyze 0x00000100 /* Maybe run ANALYZE on this table */ #define TF_NoVisibleRowid 0x00000200 /* No user-visible "rowid" column */ #define TF_OOOHidden 0x00000400 /* Out-of-Order hidden columns */ #define TF_HasNotNull 0x00000800 /* Contains NOT NULL constraints */ @@ -18143,6 +18508,15 @@ struct Table { #define HasRowid(X) (((X)->tabFlags & TF_WithoutRowid)==0) #define VisibleRowid(X) (((X)->tabFlags & TF_NoVisibleRowid)==0) +/* Macro is true if the SQLITE_ALLOW_ROWID_IN_VIEW (mis-)feature is +** available. By default, this macro is false +*/ +#ifndef SQLITE_ALLOW_ROWID_IN_VIEW +# define ViewCanHaveRowid 0 +#else +# define ViewCanHaveRowid (sqlite3Config.mNoVisibleRowid==0) +#endif + /* ** Each foreign key constraint is an instance of the following structure. ** @@ -18380,6 +18754,7 @@ struct Index { unsigned isCovering:1; /* True if this is a covering index */ unsigned noSkipScan:1; /* Do not try to use skip-scan if true */ unsigned hasStat1:1; /* aiRowLogEst values come from sqlite_stat1 */ + unsigned bLowQual:1; /* sqlite_stat1 says this is a low-quality index */ unsigned bNoQuery:1; /* Do not use this index to optimize queries */ unsigned bAscKeyBug:1; /* True if the bba7b69f9849b5bf bug applies */ unsigned bHasVCol:1; /* Index references one or more VIRTUAL columns */ @@ -18490,6 +18865,10 @@ struct AggInfo { FuncDef *pFunc; /* The aggregate function implementation */ int iDistinct; /* Ephemeral table used to enforce DISTINCT */ int iDistAddr; /* Address of OP_OpenEphemeral */ + int iOBTab; /* Ephemeral table to implement ORDER BY */ + u8 bOBPayload; /* iOBTab has payload columns separate from key */ + u8 bOBUnique; /* Enforce uniqueness on iOBTab keys */ + u8 bUseSubtype; /* Transfer subtype info through sorter */ } *aFunc; int nFunc; /* Number of entries in aFunc[] */ u32 selId; /* Select to which this AggInfo belongs */ @@ -18674,7 +19053,7 @@ struct Expr { #define EP_Reduced 0x004000 /* Expr struct EXPR_REDUCEDSIZE bytes only */ #define EP_Win 0x008000 /* Contains window functions */ #define EP_TokenOnly 0x010000 /* Expr struct EXPR_TOKENONLYSIZE bytes only */ - /* 0x020000 // Available for reuse */ +#define EP_FullSize 0x020000 /* Expr structure must remain full sized */ #define EP_IfNullRow 0x040000 /* The TK_IF_NULL_ROW opcode */ #define EP_Unlikely 0x080000 /* unlikely() or likelihood() function */ #define EP_ConstFunc 0x100000 /* A SQLITE_FUNC_CONSTANT or _SLOCHNG function */ @@ -18704,6 +19083,7 @@ struct Expr { #define ExprClearProperty(E,P) (E)->flags&=~(P) #define ExprAlwaysTrue(E) (((E)->flags&(EP_OuterON|EP_IsTrue))==EP_IsTrue) #define ExprAlwaysFalse(E) (((E)->flags&(EP_OuterON|EP_IsFalse))==EP_IsFalse) +#define ExprIsFullSize(E) (((E)->flags&(EP_Reduced|EP_TokenOnly))==0) /* Macros used to ensure that the correct members of unions are accessed ** in Expr. @@ -18821,6 +19201,7 @@ struct ExprList { #define ENAME_NAME 0 /* The AS clause of a result set */ #define ENAME_SPAN 1 /* Complete text of the result set expression */ #define ENAME_TAB 2 /* "DB.TABLE.NAME" for the result set */ +#define ENAME_ROWID 3 /* "DB.TABLE._rowid_" for * expansion of rowid */ /* ** An instance of this structure can hold a simple list of identifiers, @@ -18871,10 +19252,12 @@ struct IdList { ** ** Union member validity: ** -** u1.zIndexedBy fg.isIndexedBy && !fg.isTabFunc -** u1.pFuncArg fg.isTabFunc && !fg.isIndexedBy -** u2.pIBIndex fg.isIndexedBy && !fg.isCte -** u2.pCteUse fg.isCte && !fg.isIndexedBy +** u1.zIndexedBy fg.isIndexedBy && !fg.isTabFunc +** u1.pFuncArg fg.isTabFunc && !fg.isIndexedBy +** u1.nRow !fg.isTabFunc && !fg.isIndexedBy +** +** u2.pIBIndex fg.isIndexedBy && !fg.isCte +** u2.pCteUse fg.isCte && !fg.isIndexedBy */ struct SrcItem { Schema *pSchema; /* Schema to which this item is fixed */ @@ -18902,6 +19285,7 @@ struct SrcItem { unsigned isOn :1; /* u3.pOn was once valid and non-NULL */ unsigned isSynthUsing :1; /* u3.pUsing is synthesized from NATURAL */ unsigned isNestedFrom :1; /* pSelect is a SF_NestedFrom subquery */ + unsigned rowidUsed :1; /* The ROWID of this table is referenced */ } fg; int iCursor; /* The VDBE cursor number used to access this table */ union { @@ -18912,6 +19296,7 @@ struct SrcItem { union { char *zIndexedBy; /* Identifier from "INDEXED BY " clause */ ExprList *pFuncArg; /* Arguments to table-valued-function */ + u32 nRow; /* Number of rows in a VALUES clause */ } u1; union { Index *pIBIndex; /* Index structure corresponding to u1.zIndexedBy */ @@ -19021,6 +19406,7 @@ struct NameContext { int nRef; /* Number of names resolved by this context */ int nNcErr; /* Number of errors encountered while resolving names */ int ncFlags; /* Zero or more NC_* flags defined below */ + u32 nNestedSelect; /* Number of nested selects using this NC */ Select *pWinSelect; /* SELECT statement for any window functions */ }; @@ -19054,6 +19440,7 @@ struct NameContext { #define NC_InAggFunc 0x020000 /* True if analyzing arguments to an agg func */ #define NC_FromDDL 0x040000 /* SQL text comes from sqlite_schema */ #define NC_NoSelect 0x080000 /* Do not descend into sub-selects */ +#define NC_Where 0x100000 /* Processing WHERE clause of a SELECT */ #define NC_OrderAgg 0x8000000 /* Has an aggregate other than count/min/max */ /* @@ -19077,6 +19464,7 @@ struct Upsert { Expr *pUpsertWhere; /* WHERE clause for the ON CONFLICT UPDATE */ Upsert *pNextUpsert; /* Next ON CONFLICT clause in the list */ u8 isDoUpdate; /* True for DO UPDATE. False for DO NOTHING */ + u8 isDup; /* True if 2nd or later with same pUpsertIdx */ /* Above this point is the parse tree for the ON CONFLICT clauses. ** The next group of fields stores intermediate data. */ void *pToFree; /* Free memory when deleting the Upsert object */ @@ -19166,11 +19554,12 @@ struct Select { #define SF_View 0x0200000 /* SELECT statement is a view */ #define SF_NoopOrderBy 0x0400000 /* ORDER BY is ignored for this query */ #define SF_UFSrcCheck 0x0800000 /* Check pSrc as required by UPDATE...FROM */ -#define SF_PushDown 0x1000000 /* SELECT has be modified by push-down opt */ +#define SF_PushDown 0x1000000 /* Modified by WHERE-clause push-down opt */ #define SF_MultiPart 0x2000000 /* Has multiple incompatible PARTITIONs */ #define SF_CopyCte 0x4000000 /* SELECT statement is a copy of a CTE */ #define SF_OrderByReqd 0x8000000 /* The ORDER BY clause may not be omitted */ #define SF_UpdateFrom 0x10000000 /* Query originates with UPDATE FROM */ +#define SF_Correlated 0x20000000 /* True if references the outer context */ /* True if S exists and has SF_NestedFrom */ #define IsNestedFrom(S) ((S)!=0 && ((S)->selFlags&SF_NestedFrom)!=0) @@ -19410,6 +19799,7 @@ struct Parse { u8 disableLookaside; /* Number of times lookaside has been disabled */ u8 prepFlags; /* SQLITE_PREPARE_* flags */ u8 withinRJSubrtn; /* Nesting level for RIGHT JOIN body subroutines */ + u8 bHasWith; /* True if statement contains WITH */ #if defined(SQLITE_DEBUG) || defined(SQLITE_COVERAGE_TEST) u8 earlyCleanup; /* OOM inside sqlite3ParserAddCleanup() */ #endif @@ -19429,6 +19819,7 @@ struct Parse { int *aLabel; /* Space to hold the labels */ ExprList *pConstExpr;/* Constant expressions */ IndexedExpr *pIdxEpr;/* List of expressions used by active indexes */ + IndexedExpr *pIdxPartExpr; /* Exprs constrained by index WHERE clauses */ Token constraintName;/* Name of the constraint currently being parsed */ yDbMask writeMask; /* Start a write transaction on these databases */ yDbMask cookieMask; /* Bitmask of schema verified databases */ @@ -19700,6 +20091,7 @@ struct Returning { int iRetCur; /* Transient table holding RETURNING results */ int nRetCol; /* Number of in pReturnEL after expansion */ int iRetReg; /* Register array for holding a row of RETURNING */ + char zName[40]; /* Name of trigger: "sqlite_returning_%p" */ }; /* @@ -19735,6 +20127,9 @@ struct sqlite3_str { ** ** 3. Make a (read-only) copy of a read-only RCStr string using ** sqlite3RCStrRef(). +** +** "String" is in the name, but an RCStr object can also be used to hold +** binary data. */ struct RCStr { u64 nRCRef; /* Number of references */ @@ -19793,6 +20188,9 @@ struct Sqlite3Config { u8 bSmallMalloc; /* Avoid large memory allocations if true */ u8 bExtraSchemaChecks; /* Verify type,name,tbl_name in schema */ u8 bUseLongDouble; /* Make use of long double */ +#ifdef SQLITE_DEBUG + u8 bJsonSelfcheck; /* Double-check JSON parsing */ +#endif int mxStrlen; /* Maximum string length */ int neverCorrupt; /* Database is always well-formed */ int szLookaside; /* Default lookaside buffer size */ @@ -19839,6 +20237,11 @@ struct Sqlite3Config { #endif #ifndef SQLITE_UNTESTABLE int (*xTestCallback)(int); /* Invoked by sqlite3FaultSim() */ +#endif +#ifdef SQLITE_ALLOW_ROWID_IN_VIEW + u32 mNoVisibleRowid; /* TF_NoVisibleRowid if the ROWID_IN_VIEW + ** feature is disabled. 0 if rowids can + ** occur in views. */ #endif int bLocaltimeFault; /* True to fail localtime() calls */ int (*xAltLocaltime)(const void*,void*); /* Alternative localtime() routine */ @@ -20000,6 +20403,16 @@ struct CteUse { }; +/* Client data associated with sqlite3_set_clientdata() and +** sqlite3_get_clientdata(). +*/ +struct DbClientData { + DbClientData *pNext; /* Next in a linked list */ + void *pData; /* The data */ + void (*xDestructor)(void*); /* Destructor. Might be NULL */ + char zName[1]; /* Name of this client data. MUST BE LAST */ +}; + #ifdef SQLITE_DEBUG /* ** An instance of the TreeView object is used for printing the content of @@ -20066,6 +20479,9 @@ struct Window { ** due to the SQLITE_SUBTYPE flag */ }; +SQLITE_PRIVATE Select *sqlite3MultiValues(Parse *pParse, Select *pLeft, ExprList *pRow); +SQLITE_PRIVATE void sqlite3MultiValuesEnd(Parse *pParse, Select *pVal); + #ifndef SQLITE_OMIT_WINDOWFUNC SQLITE_PRIVATE void sqlite3WindowDelete(sqlite3*, Window*); SQLITE_PRIVATE void sqlite3WindowUnlinkFromSelect(Window*); @@ -20285,10 +20701,13 @@ SQLITE_PRIVATE void sqlite3MutexWarnOnContention(sqlite3_mutex*); # define EXP754 (((u64)0x7ff)<<52) # define MAN754 ((((u64)1)<<52)-1) # define IsNaN(X) (((X)&EXP754)==EXP754 && ((X)&MAN754)!=0) +# define IsOvfl(X) (((X)&EXP754)==EXP754) SQLITE_PRIVATE int sqlite3IsNaN(double); +SQLITE_PRIVATE int sqlite3IsOverflow(double); #else -# define IsNaN(X) 0 -# define sqlite3IsNaN(X) 0 +# define IsNaN(X) 0 +# define sqlite3IsNaN(X) 0 +# define sqlite3IsOVerflow(X) 0 #endif /* @@ -20380,6 +20799,7 @@ SQLITE_PRIVATE int sqlite3ErrorToParser(sqlite3*,int); SQLITE_PRIVATE void sqlite3Dequote(char*); SQLITE_PRIVATE void sqlite3DequoteExpr(Expr*); SQLITE_PRIVATE void sqlite3DequoteToken(Token*); +SQLITE_PRIVATE void sqlite3DequoteNumber(Parse*, Expr*); SQLITE_PRIVATE void sqlite3TokenInit(Token*,char*); SQLITE_PRIVATE int sqlite3KeywordCode(const unsigned char*, int); SQLITE_PRIVATE int sqlite3RunParser(Parse*, const char*); @@ -20404,10 +20824,13 @@ SQLITE_PRIVATE void sqlite3PExprAddSelect(Parse*, Expr*, Select*); SQLITE_PRIVATE Expr *sqlite3ExprAnd(Parse*,Expr*, Expr*); SQLITE_PRIVATE Expr *sqlite3ExprSimplifiedAndOr(Expr*); SQLITE_PRIVATE Expr *sqlite3ExprFunction(Parse*,ExprList*, const Token*, int); +SQLITE_PRIVATE void sqlite3ExprAddFunctionOrderBy(Parse*,Expr*,ExprList*); +SQLITE_PRIVATE void sqlite3ExprOrderByAggregateError(Parse*,Expr*); SQLITE_PRIVATE void sqlite3ExprFunctionUsable(Parse*,const Expr*,const FuncDef*); SQLITE_PRIVATE void sqlite3ExprAssignVarNumber(Parse*, Expr*, u32); SQLITE_PRIVATE void sqlite3ExprDelete(sqlite3*, Expr*); -SQLITE_PRIVATE void sqlite3ExprDeferredDelete(Parse*, Expr*); +SQLITE_PRIVATE void sqlite3ExprDeleteGeneric(sqlite3*,void*); +SQLITE_PRIVATE int sqlite3ExprDeferredDelete(Parse*, Expr*); SQLITE_PRIVATE void sqlite3ExprUnmapAndDelete(Parse*, Expr*); SQLITE_PRIVATE ExprList *sqlite3ExprListAppend(Parse*,ExprList*,Expr*); SQLITE_PRIVATE ExprList *sqlite3ExprListAppendVector(Parse*,ExprList*,IdList*,Expr*); @@ -20416,6 +20839,7 @@ SQLITE_PRIVATE void sqlite3ExprListSetSortOrder(ExprList*,int,int); SQLITE_PRIVATE void sqlite3ExprListSetName(Parse*,ExprList*,const Token*,int); SQLITE_PRIVATE void sqlite3ExprListSetSpan(Parse*,ExprList*,const char*,const char*); SQLITE_PRIVATE void sqlite3ExprListDelete(sqlite3*, ExprList*); +SQLITE_PRIVATE void sqlite3ExprListDeleteGeneric(sqlite3*,void*); SQLITE_PRIVATE u32 sqlite3ExprListFlags(const ExprList*); SQLITE_PRIVATE int sqlite3IndexHasDuplicateRootPage(Index*); SQLITE_PRIVATE int sqlite3Init(sqlite3*, char**); @@ -20506,6 +20930,7 @@ SQLITE_PRIVATE int sqlite3DbMaskAllZero(yDbMask); SQLITE_PRIVATE void sqlite3DropTable(Parse*, SrcList*, int, int); SQLITE_PRIVATE void sqlite3CodeDropTable(Parse*, Table*, int, int); SQLITE_PRIVATE void sqlite3DeleteTable(sqlite3*, Table*); +SQLITE_PRIVATE void sqlite3DeleteTableGeneric(sqlite3*, void*); SQLITE_PRIVATE void sqlite3FreeIndex(sqlite3*, Index*); #ifndef SQLITE_OMIT_AUTOINCREMENT SQLITE_PRIVATE void sqlite3AutoincrementBegin(Parse *pParse); @@ -20542,6 +20967,7 @@ SQLITE_PRIVATE int sqlite3Select(Parse*, Select*, SelectDest*); SQLITE_PRIVATE Select *sqlite3SelectNew(Parse*,ExprList*,SrcList*,Expr*,ExprList*, Expr*,ExprList*,u32,Expr*); SQLITE_PRIVATE void sqlite3SelectDelete(sqlite3*, Select*); +SQLITE_PRIVATE void sqlite3SelectDeleteGeneric(sqlite3*,void*); SQLITE_PRIVATE Table *sqlite3SrcListLookup(Parse*, SrcList*); SQLITE_PRIVATE int sqlite3IsReadOnly(Parse*, Table*, Trigger*); SQLITE_PRIVATE void sqlite3OpenTable(Parse*, int iCur, int iDb, Table*, int); @@ -20627,12 +21053,10 @@ SQLITE_PRIVATE void sqlite3LeaveMutexAndCloseZombie(sqlite3*); SQLITE_PRIVATE u32 sqlite3IsTrueOrFalse(const char*); SQLITE_PRIVATE int sqlite3ExprIdToTrueFalse(Expr*); SQLITE_PRIVATE int sqlite3ExprTruthValue(const Expr*); -SQLITE_PRIVATE int sqlite3ExprIsConstant(Expr*); -SQLITE_PRIVATE int sqlite3ExprIsConstantNotJoin(Expr*); +SQLITE_PRIVATE int sqlite3ExprIsConstant(Parse*,Expr*); SQLITE_PRIVATE int sqlite3ExprIsConstantOrFunction(Expr*, u8); SQLITE_PRIVATE int sqlite3ExprIsConstantOrGroupBy(Parse*, Expr*, ExprList*); -SQLITE_PRIVATE int sqlite3ExprIsTableConstant(Expr*,int); -SQLITE_PRIVATE int sqlite3ExprIsSingleTableConstraint(Expr*,const SrcList*,int); +SQLITE_PRIVATE int sqlite3ExprIsSingleTableConstraint(Expr*,const SrcList*,int,int); #ifdef SQLITE_ENABLE_CURSOR_HINTS SQLITE_PRIVATE int sqlite3ExprContainsSubquery(Expr*); #endif @@ -20640,6 +21064,7 @@ SQLITE_PRIVATE int sqlite3ExprIsInteger(const Expr*, int*); SQLITE_PRIVATE int sqlite3ExprCanBeNull(const Expr*); SQLITE_PRIVATE int sqlite3ExprNeedsNoAffinityChange(const Expr*, char); SQLITE_PRIVATE int sqlite3IsRowid(const char*); +SQLITE_PRIVATE const char *sqlite3RowidAlias(Table *pTab); SQLITE_PRIVATE void sqlite3GenerateRowDelete( Parse*,Table*,Trigger*,int,int,int,i16,u8,u8,u8,int); SQLITE_PRIVATE void sqlite3GenerateRowIndexDelete(Parse*, Table*, int, int, int*, int); @@ -20767,6 +21192,7 @@ SQLITE_PRIVATE int sqlite3Utf16ByteLen(const void *pData, int nChar); #endif SQLITE_PRIVATE int sqlite3Utf8CharLen(const char *pData, int nByte); SQLITE_PRIVATE u32 sqlite3Utf8Read(const u8**); +SQLITE_PRIVATE int sqlite3Utf8ReadLimited(const u8*, int, u32*); SQLITE_PRIVATE LogEst sqlite3LogEst(u64); SQLITE_PRIVATE LogEst sqlite3LogEstAdd(LogEst,LogEst); SQLITE_PRIVATE LogEst sqlite3LogEstFromDouble(double); @@ -20815,7 +21241,9 @@ SQLITE_PRIVATE void sqlite3ErrorWithMsg(sqlite3*, int, const char*,...); SQLITE_PRIVATE void sqlite3Error(sqlite3*,int); SQLITE_PRIVATE void sqlite3ErrorClear(sqlite3*); SQLITE_PRIVATE void sqlite3SystemError(sqlite3*,int); +#if !defined(SQLITE_OMIT_BLOB_LITERAL) SQLITE_PRIVATE void *sqlite3HexToBlob(sqlite3*, const char *z, int n); +#endif SQLITE_PRIVATE u8 sqlite3HexToInt(int h); SQLITE_PRIVATE int sqlite3TwoPartName(Parse *, Token *, Token *, Token **); @@ -20911,7 +21339,8 @@ SQLITE_PRIVATE int sqlite3MatchEName( const struct ExprList_item*, const char*, const char*, - const char* + const char*, + int* ); SQLITE_PRIVATE Bitmask sqlite3ExprColUsed(Expr*); SQLITE_PRIVATE u8 sqlite3StrIHash(const char*); @@ -20968,7 +21397,7 @@ SQLITE_PRIVATE int sqlite3ApiExit(sqlite3 *db, int); SQLITE_PRIVATE int sqlite3OpenTempDatabase(Parse *); SQLITE_PRIVATE char *sqlite3RCStrRef(char*); -SQLITE_PRIVATE void sqlite3RCStrUnref(char*); +SQLITE_PRIVATE void sqlite3RCStrUnref(void*); SQLITE_PRIVATE char *sqlite3RCStrNew(u64); SQLITE_PRIVATE char *sqlite3RCStrResize(char*,u64); @@ -21112,6 +21541,7 @@ SQLITE_PRIVATE Cte *sqlite3CteNew(Parse*,Token*,ExprList*,Select*,u8); SQLITE_PRIVATE void sqlite3CteDelete(sqlite3*,Cte*); SQLITE_PRIVATE With *sqlite3WithAdd(Parse*,With*,Cte*); SQLITE_PRIVATE void sqlite3WithDelete(sqlite3*,With*); +SQLITE_PRIVATE void sqlite3WithDeleteGeneric(sqlite3*,void*); SQLITE_PRIVATE With *sqlite3WithPush(Parse*, With*, u8); #else # define sqlite3CteNew(P,T,E,S) ((void*)0) @@ -21124,7 +21554,7 @@ SQLITE_PRIVATE With *sqlite3WithPush(Parse*, With*, u8); SQLITE_PRIVATE Upsert *sqlite3UpsertNew(sqlite3*,ExprList*,Expr*,ExprList*,Expr*,Upsert*); SQLITE_PRIVATE void sqlite3UpsertDelete(sqlite3*,Upsert*); SQLITE_PRIVATE Upsert *sqlite3UpsertDup(sqlite3*,Upsert*); -SQLITE_PRIVATE int sqlite3UpsertAnalyzeTarget(Parse*,SrcList*,Upsert*); +SQLITE_PRIVATE int sqlite3UpsertAnalyzeTarget(Parse*,SrcList*,Upsert*,Upsert*); SQLITE_PRIVATE void sqlite3UpsertDoUpdate(Parse*,Upsert*,Table*,Index*,int); SQLITE_PRIVATE Upsert *sqlite3UpsertOfIndex(Upsert*,Index*); SQLITE_PRIVATE int sqlite3UpsertNextIsIPK(Upsert*); @@ -21514,6 +21944,9 @@ static const char * const sqlite3azCompileOpt[] = { "ALLOW_COVERING_INDEX_SCAN=" CTIMEOPT_VAL(SQLITE_ALLOW_COVERING_INDEX_SCAN), # endif #endif +#ifdef SQLITE_ALLOW_ROWID_IN_VIEW + "ALLOW_ROWID_IN_VIEW", +#endif #ifdef SQLITE_ALLOW_URI_AUTHORITY "ALLOW_URI_AUTHORITY", #endif @@ -21804,6 +22237,9 @@ static const char * const sqlite3azCompileOpt[] = { #ifdef SQLITE_EXPLAIN_ESTIMATED_ROWS "EXPLAIN_ESTIMATED_ROWS", #endif +#ifdef SQLITE_EXTRA_AUTOEXT + "EXTRA_AUTOEXT=" CTIMEOPT_VAL(SQLITE_EXTRA_AUTOEXT), +#endif #ifdef SQLITE_EXTRA_IFNULLROW "EXTRA_IFNULLROW", #endif @@ -22085,6 +22521,9 @@ static const char * const sqlite3azCompileOpt[] = { #ifdef SQLITE_OMIT_SCHEMA_VERSION_PRAGMAS "OMIT_SCHEMA_VERSION_PRAGMAS", #endif +#ifdef SQLITE_OMIT_SEH + "OMIT_SEH", +#endif #ifdef SQLITE_OMIT_SHARED_CACHE "OMIT_SHARED_CACHE", #endif @@ -22483,6 +22922,9 @@ SQLITE_PRIVATE SQLITE_WSD struct Sqlite3Config sqlite3Config = { 0, /* bSmallMalloc */ 1, /* bExtraSchemaChecks */ sizeof(LONGDOUBLE_TYPE)>8, /* bUseLongDouble */ +#ifdef SQLITE_DEBUG + 0, /* bJsonSelfcheck */ +#endif 0x7ffffffe, /* mxStrlen */ 0, /* neverCorrupt */ SQLITE_DEFAULT_LOOKASIDE, /* szLookaside, nLookaside */ @@ -22524,6 +22966,9 @@ SQLITE_PRIVATE SQLITE_WSD struct Sqlite3Config sqlite3Config = { #endif #ifndef SQLITE_UNTESTABLE 0, /* xTestCallback */ +#endif +#ifdef SQLITE_ALLOW_ROWID_IN_VIEW + 0, /* mNoVisibleRowid. 0 == allow rowid-in-view */ #endif 0, /* bLocaltimeFault */ 0, /* xAltLocaltime */ @@ -23735,7 +24180,7 @@ SQLITE_API int sqlite3_db_status( case SQLITE_DBSTATUS_CACHE_MISS: case SQLITE_DBSTATUS_CACHE_WRITE:{ int i; - int nRet = 0; + u64 nRet = 0; assert( SQLITE_DBSTATUS_CACHE_MISS==SQLITE_DBSTATUS_CACHE_HIT+1 ); assert( SQLITE_DBSTATUS_CACHE_WRITE==SQLITE_DBSTATUS_CACHE_HIT+2 ); @@ -23748,7 +24193,7 @@ SQLITE_API int sqlite3_db_status( *pHighwater = 0; /* IMP: R-42420-56072 */ /* IMP: R-54100-20147 */ /* IMP: R-29431-39229 */ - *pCurrent = nRet; + *pCurrent = (int)nRet & 0x7fffffff; break; } @@ -23845,13 +24290,14 @@ struct DateTime { int tz; /* Timezone offset in minutes */ double s; /* Seconds */ char validJD; /* True (1) if iJD is valid */ - char rawS; /* Raw numeric value stored in s */ char validYMD; /* True (1) if Y,M,D are valid */ char validHMS; /* True (1) if h,m,s are valid */ - char validTZ; /* True (1) if tz is valid */ - char tzSet; /* Timezone was set explicitly */ - char isError; /* An overflow has occurred */ - char useSubsec; /* Display subsecond precision */ + char nFloor; /* Days to implement "floor" */ + unsigned rawS : 1; /* Raw numeric value stored in s */ + unsigned isError : 1; /* An overflow has occurred */ + unsigned useSubsec : 1; /* Display subsecond precision */ + unsigned isUtc : 1; /* Time is known to be UTC */ + unsigned isLocal : 1; /* Time is known to be localtime */ }; @@ -23949,6 +24395,8 @@ static int parseTimezone(const char *zDate, DateTime *p){ sgn = +1; }else if( c=='Z' || c=='z' ){ zDate++; + p->isLocal = 0; + p->isUtc = 1; goto zulu_time; }else{ return c!=0; @@ -23961,7 +24409,6 @@ static int parseTimezone(const char *zDate, DateTime *p){ p->tz = sgn*(nMn + nHr*60); zulu_time: while( sqlite3Isspace(*zDate) ){ zDate++; } - p->tzSet = 1; return *zDate!=0; } @@ -24005,7 +24452,6 @@ static int parseHhMmSs(const char *zDate, DateTime *p){ p->m = m; p->s = s + ms; if( parseTimezone(zDate, p) ) return 1; - p->validTZ = (p->tz!=0)?1:0; return 0; } @@ -24052,15 +24498,40 @@ static void computeJD(DateTime *p){ p->validJD = 1; if( p->validHMS ){ p->iJD += p->h*3600000 + p->m*60000 + (sqlite3_int64)(p->s*1000 + 0.5); - if( p->validTZ ){ + if( p->tz ){ p->iJD -= p->tz*60000; p->validYMD = 0; p->validHMS = 0; - p->validTZ = 0; + p->tz = 0; + p->isUtc = 1; + p->isLocal = 0; } } } +/* +** Given the YYYY-MM-DD information current in p, determine if there +** is day-of-month overflow and set nFloor to the number of days that +** would need to be subtracted from the date in order to bring the +** date back to the end of the month. +*/ +static void computeFloor(DateTime *p){ + assert( p->validYMD || p->isError ); + assert( p->D>=0 && p->D<=31 ); + assert( p->M>=0 && p->M<=12 ); + if( p->D<=28 ){ + p->nFloor = 0; + }else if( (1<M) & 0x15aa ){ + p->nFloor = 0; + }else if( p->M!=2 ){ + p->nFloor = (p->D==31); + }else if( p->Y%4!=0 || (p->Y%100==0 && p->Y%400!=0) ){ + p->nFloor = p->D - 28; + }else{ + p->nFloor = p->D - 29; + } +} + /* ** Parse dates of the form ** @@ -24099,12 +24570,16 @@ static int parseYyyyMmDd(const char *zDate, DateTime *p){ p->Y = neg ? -Y : Y; p->M = M; p->D = D; - if( p->validTZ ){ + computeFloor(p); + if( p->tz ){ computeJD(p); } return 0; } + +static void clearYMD_HMS_TZ(DateTime *p); /* Forward declaration */ + /* ** Set the time to the current time reported by the VFS. ** @@ -24114,6 +24589,9 @@ static int setDateTimeToCurrent(sqlite3_context *context, DateTime *p){ p->iJD = sqlite3StmtCurrentTime(context); if( p->iJD>0 ){ p->validJD = 1; + p->isUtc = 1; + p->isLocal = 0; + clearYMD_HMS_TZ(p); return 0; }else{ return 1; @@ -24252,7 +24730,7 @@ static void computeYMD_HMS(DateTime *p){ static void clearYMD_HMS_TZ(DateTime *p){ p->validYMD = 0; p->validHMS = 0; - p->validTZ = 0; + p->tz = 0; } #ifndef SQLITE_OMIT_LOCALTIME @@ -24384,7 +24862,7 @@ static int toLocaltime( p->validHMS = 1; p->validJD = 0; p->rawS = 0; - p->validTZ = 0; + p->tz = 0; p->isError = 0; return SQLITE_OK; } @@ -24404,12 +24882,12 @@ static const struct { float rLimit; /* Maximum NNN value for this transform */ float rXform; /* Constant used for this transform */ } aXformType[] = { - { 6, "second", 4.6427e+14, 1.0 }, - { 6, "minute", 7.7379e+12, 60.0 }, - { 4, "hour", 1.2897e+11, 3600.0 }, - { 3, "day", 5373485.0, 86400.0 }, - { 5, "month", 176546.0, 2592000.0 }, - { 4, "year", 14713.0, 31536000.0 }, + /* 0 */ { 6, "second", 4.6427e+14, 1.0 }, + /* 1 */ { 6, "minute", 7.7379e+12, 60.0 }, + /* 2 */ { 4, "hour", 1.2897e+11, 3600.0 }, + /* 3 */ { 3, "day", 5373485.0, 86400.0 }, + /* 4 */ { 5, "month", 176546.0, 30.0*86400.0 }, + /* 5 */ { 4, "year", 14713.0, 365.0*86400.0 }, }; /* @@ -24441,14 +24919,20 @@ static void autoAdjustDate(DateTime *p){ ** NNN.NNNN seconds ** NNN months ** NNN years +** +/-YYYY-MM-DD HH:MM:SS.SSS +** ceiling +** floor ** start of month ** start of year ** start of week ** start of day ** weekday N ** unixepoch +** auto ** localtime ** utc +** subsec +** subsecond ** ** Return 0 on success and 1 if there is any kind of error. If the error ** is in a system call (i.e. localtime()), then an error message is written @@ -24479,6 +24963,37 @@ static int parseModifier( } break; } + case 'c': { + /* + ** ceiling + ** + ** Resolve day-of-month overflow by rolling forward into the next + ** month. As this is the default action, this modifier is really + ** a no-op that is only included for symmetry. See "floor". + */ + if( sqlite3_stricmp(z, "ceiling")==0 ){ + computeJD(p); + clearYMD_HMS_TZ(p); + rc = 0; + p->nFloor = 0; + } + break; + } + case 'f': { + /* + ** floor + ** + ** Resolve day-of-month overflow by rolling back to the end of the + ** previous month. + */ + if( sqlite3_stricmp(z, "floor")==0 ){ + computeJD(p); + p->iJD -= p->nFloor*86400000; + clearYMD_HMS_TZ(p); + rc = 0; + } + break; + } case 'j': { /* ** julianday @@ -24505,7 +25020,9 @@ static int parseModifier( ** show local time. */ if( sqlite3_stricmp(z, "localtime")==0 && sqlite3NotPureFunc(pCtx) ){ - rc = toLocaltime(p, pCtx); + rc = p->isLocal ? SQLITE_OK : toLocaltime(p, pCtx); + p->isUtc = 0; + p->isLocal = 1; } break; } @@ -24530,7 +25047,7 @@ static int parseModifier( } #ifndef SQLITE_OMIT_LOCALTIME else if( sqlite3_stricmp(z, "utc")==0 && sqlite3NotPureFunc(pCtx) ){ - if( p->tzSet==0 ){ + if( p->isUtc==0 ){ i64 iOrigJD; /* Original localtime */ i64 iGuess; /* Guess at the corresponding utc time */ int cnt = 0; /* Safety to prevent infinite loop */ @@ -24553,7 +25070,8 @@ static int parseModifier( memset(p, 0, sizeof(*p)); p->iJD = iGuess; p->validJD = 1; - p->tzSet = 1; + p->isUtc = 1; + p->isLocal = 0; } rc = SQLITE_OK; } @@ -24573,7 +25091,7 @@ static int parseModifier( && r>=0.0 && r<7.0 && (n=(int)r)==r ){ sqlite3_int64 Z; computeYMD_HMS(p); - p->validTZ = 0; + p->tz = 0; p->validJD = 0; computeJD(p); Z = ((p->iJD + 129600000)/86400000) % 7; @@ -24613,7 +25131,7 @@ static int parseModifier( p->h = p->m = 0; p->s = 0.0; p->rawS = 0; - p->validTZ = 0; + p->tz = 0; p->validJD = 0; if( sqlite3_stricmp(z,"month")==0 ){ p->D = 1; @@ -24684,6 +25202,7 @@ static int parseModifier( x = p->M>0 ? (p->M-1)/12 : (p->M-12)/12; p->Y += x; p->M -= x*12; + computeFloor(p); computeJD(p); p->validHMS = 0; p->validYMD = 0; @@ -24730,11 +25249,12 @@ static int parseModifier( z += n; while( sqlite3Isspace(*z) ) z++; n = sqlite3Strlen30(z); - if( n>10 || n<3 ) break; + if( n<3 || n>10 ) break; if( sqlite3UpperToLower[(u8)z[n-1]]=='s' ) n--; computeJD(p); assert( rc==1 ); rRounder = r<0 ? -0.5 : +0.5; + p->nFloor = 0; for(i=0; iM += (int)r; x = p->M>0 ? (p->M-1)/12 : (p->M-12)/12; p->Y += x; p->M -= x*12; + computeFloor(p); p->validJD = 0; r -= (int)r; break; } case 5: { /* Special processing to add years */ int y = (int)r; - assert( strcmp(aXformType[i].zName,"year")==0 ); + assert( strcmp(aXformType[5].zName,"year")==0 ); computeYMD_HMS(p); + assert( p->M>=0 && p->M<=12 ); p->Y += y; + computeFloor(p); p->validJD = 0; r -= (int)r; break; @@ -24817,6 +25340,12 @@ static int isDate( } computeJD(p); if( p->isError || !validJulianDay(p->iJD) ) return 1; + if( argc==1 && p->validYMD && p->D>28 ){ + /* Make sure a YYYY-MM-DD is normalized. + ** Example: 2023-02-31 -> 2023-03-03 */ + assert( p->validJD ); + p->validYMD = 0; + } return 0; } @@ -25004,22 +25533,83 @@ static void dateFunc( } } +/* +** Compute the number of days after the most recent January 1. +** +** In other words, compute the zero-based day number for the +** current year: +** +** Jan01 = 0, Jan02 = 1, ..., Jan31 = 30, Feb01 = 31, ... +** Dec31 = 364 or 365. +*/ +static int daysAfterJan01(DateTime *pDate){ + DateTime jan01 = *pDate; + assert( jan01.validYMD ); + assert( jan01.validHMS ); + assert( pDate->validJD ); + jan01.validJD = 0; + jan01.M = 1; + jan01.D = 1; + computeJD(&jan01); + return (int)((pDate->iJD-jan01.iJD+43200000)/86400000); +} + +/* +** Return the number of days after the most recent Monday. +** +** In other words, return the day of the week according +** to this code: +** +** 0=Monday, 1=Tuesday, 2=Wednesday, ..., 6=Sunday. +*/ +static int daysAfterMonday(DateTime *pDate){ + assert( pDate->validJD ); + return (int)((pDate->iJD+43200000)/86400000) % 7; +} + +/* +** Return the number of days after the most recent Sunday. +** +** In other words, return the day of the week according +** to this code: +** +** 0=Sunday, 1=Monday, 2=Tues, ..., 6=Saturday +*/ +static int daysAfterSunday(DateTime *pDate){ + assert( pDate->validJD ); + return (int)((pDate->iJD+129600000)/86400000) % 7; +} + /* ** strftime( FORMAT, TIMESTRING, MOD, MOD, ...) ** ** Return a string described by FORMAT. Conversions as follows: ** -** %d day of month +** %d day of month 01-31 +** %e day of month 1-31 ** %f ** fractional seconds SS.SSS +** %F ISO date. YYYY-MM-DD +** %G ISO year corresponding to %V 0000-9999. +** %g 2-digit ISO year corresponding to %V 00-99 ** %H hour 00-24 -** %j day of year 000-366 +** %k hour 0-24 (leading zero converted to space) +** %I hour 01-12 +** %j day of year 001-366 ** %J ** julian day number +** %l hour 1-12 (leading zero converted to space) ** %m month 01-12 ** %M minute 00-59 +** %p "am" or "pm" +** %P "AM" or "PM" +** %R time as HH:MM ** %s seconds since 1970-01-01 ** %S seconds 00-59 -** %w day of week 0-6 Sunday==0 -** %W week of year 00-53 +** %T time as HH:MM:SS +** %u day of week 1-7 Monday==1, Sunday==7 +** %w day of week 0-6 Sunday==0, Monday==1 +** %U week of year 00-53 (First Sunday is start of week 01) +** %V week of year 01-53 (First week containing Thursday is week 01) +** %W week of year 00-53 (First Monday is start of week 01) ** %Y year 0000-9999 ** %% % */ @@ -25044,44 +25634,61 @@ static void strftimeFunc( computeJD(&x); computeYMD_HMS(&x); for(i=j=0; zFmt[i]; i++){ + char cf; if( zFmt[i]!='%' ) continue; if( j59.999 ) s = 59.999; sqlite3_str_appendf(&sRes, "%06.3f", s); break; } - case 'H': { - sqlite3_str_appendf(&sRes, "%02d", x.h); + case 'F': { + sqlite3_str_appendf(&sRes, "%04d-%02d-%02d", x.Y, x.M, x.D); break; } - case 'W': /* Fall thru */ - case 'j': { - int nDay; /* Number of days since 1st day of year */ + case 'G': /* Fall thru */ + case 'g': { DateTime y = x; - y.validJD = 0; - y.M = 1; - y.D = 1; - computeJD(&y); - nDay = (int)((x.iJD-y.iJD+43200000)/86400000); - if( zFmt[i]=='W' ){ - int wd; /* 0=Monday, 1=Tuesday, ... 6=Sunday */ - wd = (int)(((x.iJD+43200000)/86400000)%7); - sqlite3_str_appendf(&sRes,"%02d",(nDay+7-wd)/7); + assert( y.validJD ); + /* Move y so that it is the Thursday in the same week as x */ + y.iJD += (3 - daysAfterMonday(&x))*86400000; + y.validYMD = 0; + computeYMD(&y); + if( cf=='g' ){ + sqlite3_str_appendf(&sRes, "%02d", y.Y%100); }else{ - sqlite3_str_appendf(&sRes,"%03d",nDay+1); + sqlite3_str_appendf(&sRes, "%04d", y.Y); } break; } - case 'J': { + case 'H': + case 'k': { + sqlite3_str_appendf(&sRes, cf=='H' ? "%02d" : "%2d", x.h); + break; + } + case 'I': /* Fall thru */ + case 'l': { + int h = x.h; + if( h>12 ) h -= 12; + if( h==0 ) h = 12; + sqlite3_str_appendf(&sRes, cf=='I' ? "%02d" : "%2d", h); + break; + } + case 'j': { /* Day of year. Jan01==1, Jan02==2, and so forth */ + sqlite3_str_appendf(&sRes,"%03d",daysAfterJan01(&x)+1); + break; + } + case 'J': { /* Julian day number. (Non-standard) */ sqlite3_str_appendf(&sRes,"%.16g",x.iJD/86400000.0); break; } @@ -25093,6 +25700,19 @@ static void strftimeFunc( sqlite3_str_appendf(&sRes,"%02d",x.m); break; } + case 'p': /* Fall thru */ + case 'P': { + if( x.h>=12 ){ + sqlite3_str_append(&sRes, cf=='p' ? "PM" : "pm", 2); + }else{ + sqlite3_str_append(&sRes, cf=='p' ? "AM" : "am", 2); + } + break; + } + case 'R': { + sqlite3_str_appendf(&sRes, "%02d:%02d", x.h, x.m); + break; + } case 's': { if( x.useSubsec ){ sqlite3_str_appendf(&sRes,"%.3f", @@ -25107,9 +25727,35 @@ static void strftimeFunc( sqlite3_str_appendf(&sRes,"%02d",(int)x.s); break; } - case 'w': { - sqlite3_str_appendchar(&sRes, 1, - (char)(((x.iJD+129600000)/86400000) % 7) + '0'); + case 'T': { + sqlite3_str_appendf(&sRes,"%02d:%02d:%02d", x.h, x.m, (int)x.s); + break; + } + case 'u': /* Day of week. 1 to 7. Monday==1, Sunday==7 */ + case 'w': { /* Day of week. 0 to 6. Sunday==0, Monday==1 */ + char c = (char)daysAfterSunday(&x) + '0'; + if( c=='0' && cf=='u' ) c = '7'; + sqlite3_str_appendchar(&sRes, 1, c); + break; + } + case 'U': { /* Week num. 00-53. First Sun of the year is week 01 */ + sqlite3_str_appendf(&sRes,"%02d", + (daysAfterJan01(&x)-daysAfterSunday(&x)+7)/7); + break; + } + case 'V': { /* Week num. 01-53. First week with a Thur is week 01 */ + DateTime y = x; + /* Adjust y so that is the Thursday in the same week as x */ + assert( y.validJD ); + y.iJD += (3 - daysAfterMonday(&x))*86400000; + y.validYMD = 0; + computeYMD(&y); + sqlite3_str_appendf(&sRes,"%02d", daysAfterJan01(&y)/7+1); + break; + } + case 'W': { /* Week num. 00-53. First Mon of the year is week 01 */ + sqlite3_str_appendf(&sRes,"%02d", + (daysAfterJan01(&x)-daysAfterMonday(&x)+7)/7); break; } case 'Y': { @@ -25258,9 +25904,7 @@ static void timediffFunc( d1.iJD = d2.iJD - d1.iJD; d1.iJD += (u64)1486995408 * (u64)100000; } - d1.validYMD = 0; - d1.validHMS = 0; - d1.validTZ = 0; + clearYMD_HMS_TZ(&d1); computeYMD_HMS(&d1); sqlite3StrAccumInit(&sRes, 0, 0, 0, 100); sqlite3_str_appendf(&sRes, "%c%04d-%02d-%02d %02d:%02d:%06.3f", @@ -25329,6 +25973,36 @@ static void currentTimeFunc( } #endif +#if !defined(SQLITE_OMIT_DATETIME_FUNCS) && defined(SQLITE_DEBUG) +/* +** datedebug(...) +** +** This routine returns JSON that describes the internal DateTime object. +** Used for debugging and testing only. Subject to change. +*/ +static void datedebugFunc( + sqlite3_context *context, + int argc, + sqlite3_value **argv +){ + DateTime x; + if( isDate(context, argc, argv, &x)==0 ){ + char *zJson; + zJson = sqlite3_mprintf( + "{iJD:%lld,Y:%d,M:%d,D:%d,h:%d,m:%d,tz:%d," + "s:%.3f,validJD:%d,validYMS:%d,validHMS:%d," + "nFloor:%d,rawS:%d,isError:%d,useSubsec:%d," + "isUtc:%d,isLocal:%d}", + x.iJD, x.Y, x.M, x.D, x.h, x.m, x.tz, + x.s, x.validJD, x.validYMD, x.validHMS, + x.nFloor, x.rawS, x.isError, x.useSubsec, + x.isUtc, x.isLocal); + sqlite3_result_text(context, zJson, -1, sqlite3_free); + } +} +#endif /* !SQLITE_OMIT_DATETIME_FUNCS && SQLITE_DEBUG */ + + /* ** This function registered all of the above C functions as SQL ** functions. This should be the only routine in this file with @@ -25344,6 +26018,9 @@ SQLITE_PRIVATE void sqlite3RegisterDateTimeFunctions(void){ PURE_DATE(datetime, -1, 0, 0, datetimeFunc ), PURE_DATE(strftime, -1, 0, 0, strftimeFunc ), PURE_DATE(timediff, 2, 0, 0, timediffFunc ), +#ifdef SQLITE_DEBUG + PURE_DATE(datedebug, -1, 0, 0, datedebugFunc ), +#endif DFUNCTION(current_time, 0, 0, 0, ctimeFunc ), DFUNCTION(current_timestamp, 0, 0, 0, ctimestampFunc), DFUNCTION(current_date, 0, 0, 0, cdateFunc ), @@ -28198,7 +28875,7 @@ static void checkMutexFree(sqlite3_mutex *p){ assert( SQLITE_MUTEX_FAST<2 ); assert( SQLITE_MUTEX_WARNONCONTENTION<2 ); -#if SQLITE_ENABLE_API_ARMOR +#ifdef SQLITE_ENABLE_API_ARMOR if( ((CheckMutex*)p)->iType<2 ) #endif { @@ -28870,7 +29547,7 @@ static sqlite3_mutex *pthreadMutexAlloc(int iType){ */ static void pthreadMutexFree(sqlite3_mutex *p){ assert( p->nRef==0 ); -#if SQLITE_ENABLE_API_ARMOR +#ifdef SQLITE_ENABLE_API_ARMOR if( p->id==SQLITE_MUTEX_FAST || p->id==SQLITE_MUTEX_RECURSIVE ) #endif { @@ -29223,7 +29900,7 @@ SQLITE_PRIVATE void sqlite3MemoryBarrier(void){ SQLITE_MEMORY_BARRIER; #elif defined(__GNUC__) __sync_synchronize(); -#elif MSVC_VERSION>=1300 +#elif MSVC_VERSION>=1400 _ReadWriteBarrier(); #elif defined(MemoryBarrier) MemoryBarrier(); @@ -29759,6 +30436,24 @@ static void sqlite3MallocAlarm(int nByte){ sqlite3_mutex_enter(mem0.mutex); } +#ifdef SQLITE_DEBUG +/* +** This routine is called whenever an out-of-memory condition is seen, +** It's only purpose to to serve as a breakpoint for gdb or similar +** code debuggers when working on out-of-memory conditions, for example +** caused by PRAGMA hard_heap_limit=N. +*/ +static SQLITE_NOINLINE void test_oom_breakpoint(u64 n){ + static u64 nOomFault = 0; + nOomFault += n; + /* The assert() is never reached in a human lifetime. It is here mostly + ** to prevent code optimizers from optimizing out this function. */ + assert( (nOomFault>>32) < 0xffffffff ); +} +#else +# define test_oom_breakpoint(X) /* No-op for production builds */ +#endif + /* ** Do a memory allocation with statistics and alarms. Assume the ** lock is already held. @@ -29785,6 +30480,7 @@ static void mallocWithAlarm(int n, void **pp){ if( mem0.hardLimit ){ nUsed = sqlite3StatusValue(SQLITE_STATUS_MEMORY_USED); if( nUsed >= mem0.hardLimit - nFull ){ + test_oom_breakpoint(1); *pp = 0; return; } @@ -30073,6 +30769,7 @@ SQLITE_PRIVATE void *sqlite3Realloc(void *pOld, u64 nBytes){ sqlite3MallocAlarm(nDiff); if( mem0.hardLimit>0 && nUsed >= mem0.hardLimit - nDiff ){ sqlite3_mutex_leave(mem0.mutex); + test_oom_breakpoint(1); return 0; } } @@ -30434,7 +31131,7 @@ SQLITE_PRIVATE int sqlite3ApiExit(sqlite3* db, int rc){ if( db->mallocFailed || rc ){ return apiHandleError(db, rc); } - return rc & db->errMask; + return 0; } /************** End of malloc.c **********************************************/ @@ -30939,6 +31636,7 @@ SQLITE_API void sqlite3_str_vappendf( if( xtype==etFLOAT ){ iRound = -precision; }else if( xtype==etGENERIC ){ + if( precision==0 ) precision = 1; iRound = precision; }else{ iRound = precision+1; @@ -30974,13 +31672,14 @@ SQLITE_API void sqlite3_str_vappendf( } exp = s.iDP-1; - if( xtype==etGENERIC && precision>0 ) precision--; /* ** If the field type is etGENERIC, then convert to either etEXP ** or etFLOAT, as appropriate. */ if( xtype==etGENERIC ){ + assert( precision>0 ); + precision--; flag_rtz = !flag_alternateform; if( exp<-4 || exp>precision ){ xtype = etEXP; @@ -31296,9 +31995,13 @@ SQLITE_API void sqlite3_str_vappendf( sqlite3_str_appendall(pAccum, pItem->zAlias); }else{ Select *pSel = pItem->pSelect; - assert( pSel!=0 ); + assert( pSel!=0 ); /* Because of tag-20240424-1 */ if( pSel->selFlags & SF_NestedFrom ){ sqlite3_str_appendf(pAccum, "(join-%u)", pSel->selId); + }else if( pSel->selFlags & SF_MultiValue ){ + assert( !pItem->fg.isTabFunc && !pItem->fg.isIndexedBy ); + sqlite3_str_appendf(pAccum, "%u-ROW VALUES CLAUSE", + pItem->u1.nRow); }else{ sqlite3_str_appendf(pAccum, "(subquery-%u)", pSel->selId); } @@ -31810,7 +32513,7 @@ SQLITE_API void sqlite3_str_appendf(StrAccum *p, const char *zFormat, ...){ /***************************************************************************** -** Reference counted string storage +** Reference counted string/blob storage *****************************************************************************/ /* @@ -31830,7 +32533,7 @@ SQLITE_PRIVATE char *sqlite3RCStrRef(char *z){ ** Decrease the reference count by one. Free the string when the ** reference count reaches zero. */ -SQLITE_PRIVATE void sqlite3RCStrUnref(char *z){ +SQLITE_PRIVATE void sqlite3RCStrUnref(void *z){ RCStr *p = (RCStr*)z; assert( p!=0 ); p--; @@ -32075,8 +32778,10 @@ SQLITE_PRIVATE void sqlite3TreeViewSrcList(TreeView *pView, const SrcList *pSrc) x.printfFlags |= SQLITE_PRINTF_INTERNAL; sqlite3_str_appendf(&x, "{%d:*} %!S", pItem->iCursor, pItem); if( pItem->pTab ){ - sqlite3_str_appendf(&x, " tab=%Q nCol=%d ptr=%p used=%llx", - pItem->pTab->zName, pItem->pTab->nCol, pItem->pTab, pItem->colUsed); + sqlite3_str_appendf(&x, " tab=%Q nCol=%d ptr=%p used=%llx%s", + pItem->pTab->zName, pItem->pTab->nCol, pItem->pTab, + pItem->colUsed, + pItem->fg.rowidUsed ? "+rowid" : ""); } if( (pItem->fg.jointype & (JT_LEFT|JT_RIGHT))==(JT_LEFT|JT_RIGHT) ){ sqlite3_str_appendf(&x, " FULL-OUTER-JOIN"); @@ -32116,12 +32821,14 @@ SQLITE_PRIVATE void sqlite3TreeViewSrcList(TreeView *pView, const SrcList *pSrc) sqlite3TreeViewIdList(pView, pItem->u3.pUsing, (--n)>0, "USING"); } if( pItem->pSelect ){ + sqlite3TreeViewPush(&pView, i+1nSrc); if( pItem->pTab ){ Table *pTab = pItem->pTab; sqlite3TreeViewColumnList(pView, pTab->aCol, pTab->nCol, 1); } assert( (int)pItem->fg.isNestedFrom == IsNestedFrom(pItem->pSelect) ); sqlite3TreeViewSelect(pView, pItem->pSelect, (--n)>0); + sqlite3TreeViewPop(&pView); } if( pItem->fg.isTabFunc ){ sqlite3TreeViewExprList(pView, pItem->u1.pFuncArg, 0, "func-args:"); @@ -32225,7 +32932,7 @@ SQLITE_PRIVATE void sqlite3TreeViewSelect(TreeView *pView, const Select *p, u8 m sqlite3TreeViewItem(pView, "LIMIT", (n--)>0); sqlite3TreeViewExpr(pView, p->pLimit->pLeft, p->pLimit->pRight!=0); if( p->pLimit->pRight ){ - sqlite3TreeViewItem(pView, "OFFSET", (n--)>0); + sqlite3TreeViewItem(pView, "OFFSET", 0); sqlite3TreeViewExpr(pView, p->pLimit->pRight, 0); sqlite3TreeViewPop(&pView); } @@ -32293,6 +33000,7 @@ SQLITE_PRIVATE void sqlite3TreeViewWindow(TreeView *pView, const Window *pWin, u sqlite3TreeViewItem(pView, "FILTER", 1); sqlite3TreeViewExpr(pView, pWin->pFilter, 0); sqlite3TreeViewPop(&pView); + if( pWin->eFrmType==TK_FILTER ) return; } sqlite3TreeViewPush(&pView, more); if( pWin->zName ){ @@ -32302,7 +33010,7 @@ SQLITE_PRIVATE void sqlite3TreeViewWindow(TreeView *pView, const Window *pWin, u } if( pWin->zBase ) nElement++; if( pWin->pOrderBy ) nElement++; - if( pWin->eFrmType ) nElement++; + if( pWin->eFrmType!=0 && pWin->eFrmType!=TK_FILTER ) nElement++; if( pWin->eExclude ) nElement++; if( pWin->zBase ){ sqlite3TreeViewPush(&pView, (--nElement)>0); @@ -32315,7 +33023,7 @@ SQLITE_PRIVATE void sqlite3TreeViewWindow(TreeView *pView, const Window *pWin, u if( pWin->pOrderBy ){ sqlite3TreeViewExprList(pView, pWin->pOrderBy, (--nElement)>0, "ORDER-BY"); } - if( pWin->eFrmType ){ + if( pWin->eFrmType!=0 && pWin->eFrmType!=TK_FILTER ){ char zBuf[30]; const char *zFrmType = "ROWS"; if( pWin->eFrmType==TK_RANGE ) zFrmType = "RANGE"; @@ -32563,7 +33271,7 @@ SQLITE_PRIVATE void sqlite3TreeViewExpr(TreeView *pView, const Expr *pExpr, u8 m assert( ExprUseXList(pExpr) ); pFarg = pExpr->x.pList; #ifndef SQLITE_OMIT_WINDOWFUNC - pWin = ExprHasProperty(pExpr, EP_WinFunc) ? pExpr->y.pWin : 0; + pWin = IsWindowFunc(pExpr) ? pExpr->y.pWin : 0; #else pWin = 0; #endif @@ -32589,7 +33297,13 @@ SQLITE_PRIVATE void sqlite3TreeViewExpr(TreeView *pView, const Expr *pExpr, u8 m sqlite3TreeViewLine(pView, "FUNCTION %Q%s", pExpr->u.zToken, zFlgs); } if( pFarg ){ - sqlite3TreeViewExprList(pView, pFarg, pWin!=0, 0); + sqlite3TreeViewExprList(pView, pFarg, pWin!=0 || pExpr->pLeft, 0); + if( pExpr->pLeft ){ + Expr *pOB = pExpr->pLeft; + assert( pOB->op==TK_ORDER ); + assert( ExprUseXList(pOB) ); + sqlite3TreeViewExprList(pView, pOB->x.pList, pWin!=0, "ORDERBY"); + } } #ifndef SQLITE_OMIT_WINDOWFUNC if( pWin ){ @@ -32598,6 +33312,10 @@ SQLITE_PRIVATE void sqlite3TreeViewExpr(TreeView *pView, const Expr *pExpr, u8 m #endif break; } + case TK_ORDER: { + sqlite3TreeViewExprList(pView, pExpr->x.pList, 0, "ORDERBY"); + break; + } #ifndef SQLITE_OMIT_SUBQUERY case TK_EXISTS: { assert( ExprUseXSelect(pExpr) ); @@ -32651,7 +33369,7 @@ SQLITE_PRIVATE void sqlite3TreeViewExpr(TreeView *pView, const Expr *pExpr, u8 m assert( pExpr->x.pList->nExpr==2 ); pY = pExpr->x.pList->a[0].pExpr; pZ = pExpr->x.pList->a[1].pExpr; - sqlite3TreeViewLine(pView, "BETWEEN"); + sqlite3TreeViewLine(pView, "BETWEEN%s", zFlgs); sqlite3TreeViewExpr(pView, pX, 1); sqlite3TreeViewExpr(pView, pY, 1); sqlite3TreeViewExpr(pView, pZ, 0); @@ -33786,7 +34504,38 @@ SQLITE_PRIVATE u32 sqlite3Utf8Read( return c; } - +/* +** Read a single UTF8 character out of buffer z[], but reading no +** more than n characters from the buffer. z[] is not zero-terminated. +** +** Return the number of bytes used to construct the character. +** +** Invalid UTF8 might generate a strange result. No effort is made +** to detect invalid UTF8. +** +** At most 4 bytes will be read out of z[]. The return value will always +** be between 1 and 4. +*/ +SQLITE_PRIVATE int sqlite3Utf8ReadLimited( + const u8 *z, + int n, + u32 *piOut +){ + u32 c; + int i = 1; + assert( n>0 ); + c = z[0]; + if( c>=0xc0 ){ + c = sqlite3Utf8Trans1[c-0xc0]; + if( n>4 ) n = 4; + while( irc = SQLITE_INTERRUPT; } #ifndef SQLITE_OMIT_PROGRESS_CALLBACK - if( db->xProgress && (++p->nProgressSteps)>=db->nProgressOps ){ - if( db->xProgress(db->pProgressArg) ){ - p->nErr++; - p->rc = SQLITE_INTERRUPT; + if( db->xProgress ){ + if( p->rc==SQLITE_INTERRUPT ){ + p->nProgressSteps = 0; + }else if( (++p->nProgressSteps)>=db->nProgressOps ){ + if( db->xProgress(db->pProgressArg) ){ + p->nErr++; + p->rc = SQLITE_INTERRUPT; + } + p->nProgressSteps = 0; } - p->nProgressSteps = 0; } #endif } @@ -34467,6 +35233,44 @@ SQLITE_PRIVATE void sqlite3DequoteExpr(Expr *p){ sqlite3Dequote(p->u.zToken); } +/* +** Expression p is a QNUMBER (quoted number). Dequote the value in p->u.zToken +** and set the type to INTEGER or FLOAT. "Quoted" integers or floats are those +** that contain '_' characters that must be removed before further processing. +*/ +SQLITE_PRIVATE void sqlite3DequoteNumber(Parse *pParse, Expr *p){ + assert( p!=0 || pParse->db->mallocFailed ); + if( p ){ + const char *pIn = p->u.zToken; + char *pOut = p->u.zToken; + int bHex = (pIn[0]=='0' && (pIn[1]=='x' || pIn[1]=='X')); + int iValue; + assert( p->op==TK_QNUMBER ); + p->op = TK_INTEGER; + do { + if( *pIn!=SQLITE_DIGIT_SEPARATOR ){ + *pOut++ = *pIn; + if( *pIn=='e' || *pIn=='E' || *pIn=='.' ) p->op = TK_FLOAT; + }else{ + if( (bHex==0 && (!sqlite3Isdigit(pIn[-1]) || !sqlite3Isdigit(pIn[1]))) + || (bHex==1 && (!sqlite3Isxdigit(pIn[-1]) || !sqlite3Isxdigit(pIn[1]))) + ){ + sqlite3ErrorMsg(pParse, "unrecognized token: \"%s\"", p->u.zToken); + } + } + }while( *pIn++ ); + if( bHex ) p->op = TK_INTEGER; + + /* tag-20240227-a: If after dequoting, the number is an integer that + ** fits in 32 bits, then it must be converted into EP_IntValue. Other + ** parts of the code expect this. See also tag-20240227-b. */ + if( p->op==TK_INTEGER && sqlite3GetInt32(p->u.zToken, &iValue) ){ + p->u.iValue = iValue; + p->flags |= EP_IntValue; + } + } +} + /* ** If the input token p is quoted, try to adjust the token to remove ** the quotes. This is not always possible: @@ -34783,6 +35587,9 @@ SQLITE_PRIVATE int sqlite3AtoF(const char *z, double *pResult, int length, u8 en u64 s2; rr[0] = (double)s; s2 = (u64)rr[0]; +#if defined(_MSC_VER) && _MSC_VER<1700 + if( s2==0x8000000000000000LL ){ s2 = 2*(u64)(0.5*rr[0]); } +#endif rr[1] = s>=s2 ? (double)(s - s2) : -(double)(s2 - s); if( e>0 ){ while( e>=100 ){ @@ -35185,29 +35992,29 @@ SQLITE_PRIVATE void sqlite3FpDecode(FpDecode *p, double r, int iRound, int mxRou double rr[2]; rr[0] = r; rr[1] = 0.0; - if( rr[0]>1.84e+19 ){ - while( rr[0]>1.84e+119 ){ + if( rr[0]>9.223372036854774784e+18 ){ + while( rr[0]>9.223372036854774784e+118 ){ exp += 100; dekkerMul2(rr, 1.0e-100, -1.99918998026028836196e-117); } - while( rr[0]>1.84e+29 ){ + while( rr[0]>9.223372036854774784e+28 ){ exp += 10; dekkerMul2(rr, 1.0e-10, -3.6432197315497741579e-27); } - while( rr[0]>1.84e+19 ){ + while( rr[0]>9.223372036854774784e+18 ){ exp += 1; dekkerMul2(rr, 1.0e-01, -5.5511151231257827021e-18); } }else{ - while( rr[0]<1.84e-82 ){ + while( rr[0]<9.223372036854774784e-83 ){ exp -= 100; dekkerMul2(rr, 1.0e+100, -1.5902891109759918046e+83); } - while( rr[0]<1.84e+08 ){ + while( rr[0]<9.223372036854774784e+07 ){ exp -= 10; dekkerMul2(rr, 1.0e+10, 0.0); } - while( rr[0]<1.84e+18 ){ + while( rr[0]<9.22337203685477478e+17 ){ exp -= 1; dekkerMul2(rr, 1.0e+01, 0.0); } @@ -35225,7 +36032,7 @@ SQLITE_PRIVATE void sqlite3FpDecode(FpDecode *p, double r, int iRound, int mxRou assert( p->n>0 ); assert( p->nzBuf) ); p->iDP = p->n + exp; - if( iRound<0 ){ + if( iRound<=0 ){ iRound = p->iDP - iRound; if( iRound==0 && p->zBuf[i+1]>='5' ){ iRound = 1; @@ -35523,121 +36330,32 @@ SQLITE_PRIVATE u8 sqlite3GetVarint(const unsigned char *p, u64 *v){ ** this function assumes the single-byte case has already been handled. */ SQLITE_PRIVATE u8 sqlite3GetVarint32(const unsigned char *p, u32 *v){ - u32 a,b; + u64 v64; + u8 n; - /* The 1-byte case. Overwhelmingly the most common. Handled inline - ** by the getVarin32() macro */ - a = *p; - /* a: p0 (unmasked) */ -#ifndef getVarint32 - if (!(a&0x80)) - { - /* Values between 0 and 127 */ - *v = a; - return 1; - } -#endif + /* Assume that the single-byte case has already been handled by + ** the getVarint32() macro */ + assert( (p[0] & 0x80)!=0 ); - /* The 2-byte case */ - p++; - b = *p; - /* b: p1 (unmasked) */ - if (!(b&0x80)) - { - /* Values between 128 and 16383 */ - a &= 0x7f; - a = a<<7; - *v = a | b; + if( (p[1] & 0x80)==0 ){ + /* This is the two-byte case */ + *v = ((p[0]&0x7f)<<7) | p[1]; return 2; } - - /* The 3-byte case */ - p++; - a = a<<14; - a |= *p; - /* a: p0<<14 | p2 (unmasked) */ - if (!(a&0x80)) - { - /* Values between 16384 and 2097151 */ - a &= (0x7f<<14)|(0x7f); - b &= 0x7f; - b = b<<7; - *v = a | b; + if( (p[2] & 0x80)==0 ){ + /* This is the three-byte case */ + *v = ((p[0]&0x7f)<<14) | ((p[1]&0x7f)<<7) | p[2]; return 3; } - - /* A 32-bit varint is used to store size information in btrees. - ** Objects are rarely larger than 2MiB limit of a 3-byte varint. - ** A 3-byte varint is sufficient, for example, to record the size - ** of a 1048569-byte BLOB or string. - ** - ** We only unroll the first 1-, 2-, and 3- byte cases. The very - ** rare larger cases can be handled by the slower 64-bit varint - ** routine. - */ -#if 1 - { - u64 v64; - u8 n; - - n = sqlite3GetVarint(p-2, &v64); - assert( n>3 && n<=9 ); - if( (v64 & SQLITE_MAX_U32)!=v64 ){ - *v = 0xffffffff; - }else{ - *v = (u32)v64; - } - return n; - } - -#else - /* For following code (kept for historical record only) shows an - ** unrolling for the 3- and 4-byte varint cases. This code is - ** slightly faster, but it is also larger and much harder to test. - */ - p++; - b = b<<14; - b |= *p; - /* b: p1<<14 | p3 (unmasked) */ - if (!(b&0x80)) - { - /* Values between 2097152 and 268435455 */ - b &= (0x7f<<14)|(0x7f); - a &= (0x7f<<14)|(0x7f); - a = a<<7; - *v = a | b; - return 4; - } - - p++; - a = a<<14; - a |= *p; - /* a: p0<<28 | p2<<14 | p4 (unmasked) */ - if (!(a&0x80)) - { - /* Values between 268435456 and 34359738367 */ - a &= SLOT_4_2_0; - b &= SLOT_4_2_0; - b = b<<7; - *v = a | b; - return 5; - } - - /* We can only reach this point when reading a corrupt database - ** file. In that case we are not in any hurry. Use the (relatively - ** slow) general-purpose sqlite3GetVarint() routine to extract the - ** value. */ - { - u64 v64; - u8 n; - - p -= 4; - n = sqlite3GetVarint(p, &v64); - assert( n>5 && n<=9 ); + /* four or more bytes */ + n = sqlite3GetVarint(p, &v64); + assert( n>3 && n<=9 ); + if( (v64 & SQLITE_MAX_U32)!=v64 ){ + *v = 0xffffffff; + }else{ *v = (u32)v64; - return n; } -#endif + return n; } /* @@ -36492,7 +37210,7 @@ SQLITE_PRIVATE const char *sqlite3OpcodeName(int i){ /* 30 */ "SeekRowid" OpHelp("intkey=r[P3]"), /* 31 */ "NotExists" OpHelp("intkey=r[P3]"), /* 32 */ "Last" OpHelp(""), - /* 33 */ "IfSmaller" OpHelp(""), + /* 33 */ "IfSizeBetween" OpHelp(""), /* 34 */ "SorterSort" OpHelp(""), /* 35 */ "Sort" OpHelp(""), /* 36 */ "Rewind" OpHelp(""), @@ -36537,7 +37255,7 @@ SQLITE_PRIVATE const char *sqlite3OpcodeName(int i){ /* 75 */ "Null" OpHelp("r[P2..P3]=NULL"), /* 76 */ "SoftNull" OpHelp("r[P1]=NULL"), /* 77 */ "Blob" OpHelp("r[P2]=P4 (len=P1)"), - /* 78 */ "Variable" OpHelp("r[P2]=parameter(P1,P4)"), + /* 78 */ "Variable" OpHelp("r[P2]=parameter(P1)"), /* 79 */ "Move" OpHelp("r[P2@P3]=r[P1@P3]"), /* 80 */ "Copy" OpHelp("r[P2@P3+1]=r[P1@P3+1]"), /* 81 */ "SCopy" OpHelp("r[P2]=r[P1]"), @@ -36633,19 +37351,22 @@ SQLITE_PRIVATE const char *sqlite3OpcodeName(int i){ /* 171 */ "VCreate" OpHelp(""), /* 172 */ "VDestroy" OpHelp(""), /* 173 */ "VOpen" OpHelp(""), - /* 174 */ "VInitIn" OpHelp("r[P2]=ValueList(P1,P3)"), - /* 175 */ "VColumn" OpHelp("r[P3]=vcolumn(P2)"), - /* 176 */ "VRename" OpHelp(""), - /* 177 */ "Pagecount" OpHelp(""), - /* 178 */ "MaxPgcnt" OpHelp(""), - /* 179 */ "ClrSubtype" OpHelp("r[P1].subtype = 0"), - /* 180 */ "FilterAdd" OpHelp("filter(P1) += key(P3@P4)"), - /* 181 */ "Trace" OpHelp(""), - /* 182 */ "CursorHint" OpHelp(""), - /* 183 */ "ReleaseReg" OpHelp("release r[P1@P2] mask P3"), - /* 184 */ "Noop" OpHelp(""), - /* 185 */ "Explain" OpHelp(""), - /* 186 */ "Abortable" OpHelp(""), + /* 174 */ "VCheck" OpHelp(""), + /* 175 */ "VInitIn" OpHelp("r[P2]=ValueList(P1,P3)"), + /* 176 */ "VColumn" OpHelp("r[P3]=vcolumn(P2)"), + /* 177 */ "VRename" OpHelp(""), + /* 178 */ "Pagecount" OpHelp(""), + /* 179 */ "MaxPgcnt" OpHelp(""), + /* 180 */ "ClrSubtype" OpHelp("r[P1].subtype = 0"), + /* 181 */ "GetSubtype" OpHelp("r[P2] = r[P1].subtype"), + /* 182 */ "SetSubtype" OpHelp("r[P2].subtype = r[P1]"), + /* 183 */ "FilterAdd" OpHelp("filter(P1) += key(P3@P4)"), + /* 184 */ "Trace" OpHelp(""), + /* 185 */ "CursorHint" OpHelp(""), + /* 186 */ "ReleaseReg" OpHelp("release r[P1@P2] mask P3"), + /* 187 */ "Noop" OpHelp(""), + /* 188 */ "Explain" OpHelp(""), + /* 189 */ "Abortable" OpHelp(""), }; return azName[i]; } @@ -38932,8 +39653,12 @@ static int unixLogErrorAtLine( ** available, the error message will often be an empty string. Not a ** huge problem. Incorrectly concluding that the GNU version is available ** could lead to a segfault though. + ** + ** Forum post 3f13857fa4062301 reports that the Android SDK may use + ** int-type return, depending on its version. */ -#if defined(STRERROR_R_CHAR_P) || defined(__USE_GNU) +#if (defined(STRERROR_R_CHAR_P) || defined(__USE_GNU)) \ + && !defined(ANDROID) && !defined(__ANDROID__) zErr = # endif strerror_r(iErrno, aErr, sizeof(aErr)-1); @@ -40787,9 +41512,6 @@ static int afpUnlock(sqlite3_file *id, int eFileLock) { unixInodeInfo *pInode; afpLockingContext *context = (afpLockingContext *) pFile->lockingContext; int skipShared = 0; -#ifdef SQLITE_TEST - int h = pFile->h; -#endif assert( pFile ); OSTRACE(("UNLOCK %d %d was %d(%d,%d) pid=%d (afp)\n", pFile->h, eFileLock, @@ -40805,9 +41527,6 @@ static int afpUnlock(sqlite3_file *id, int eFileLock) { assert( pInode->nShared!=0 ); if( pFile->eFileLock>SHARED_LOCK ){ assert( pInode->eFileLock==pFile->eFileLock ); - SimulateIOErrorBenign(1); - SimulateIOError( h=(-1) ) - SimulateIOErrorBenign(0); #ifdef SQLITE_DEBUG /* When reducing a lock such that other processes can start @@ -40856,9 +41575,6 @@ static int afpUnlock(sqlite3_file *id, int eFileLock) { unsigned long long sharedLockByte = SHARED_FIRST+pInode->sharedByte; pInode->nShared--; if( pInode->nShared==0 ){ - SimulateIOErrorBenign(1); - SimulateIOError( h=(-1) ) - SimulateIOErrorBenign(0); if( !skipShared ){ rc = afpSetLock(context->dbPath, pFile, sharedLockByte, 1, 0); } @@ -41700,7 +42416,13 @@ static int unixFileControl(sqlite3_file *id, int op, void *pArg){ #ifdef SQLITE_ENABLE_SETLK_TIMEOUT case SQLITE_FCNTL_LOCK_TIMEOUT: { int iOld = pFile->iBusyTimeout; +#if SQLITE_ENABLE_SETLK_TIMEOUT==1 pFile->iBusyTimeout = *(int*)pArg; +#elif SQLITE_ENABLE_SETLK_TIMEOUT==2 + pFile->iBusyTimeout = !!(*(int*)pArg); +#else +# error "SQLITE_ENABLE_SETLK_TIMEOUT must be set to 1 or 2" +#endif *(int*)pArg = iOld; return SQLITE_OK; } @@ -41953,6 +42675,25 @@ static int unixGetpagesize(void){ ** Either unixShmNode.pShmMutex must be held or unixShmNode.nRef==0 and ** unixMutexHeld() is true when reading or writing any other field ** in this structure. +** +** aLock[SQLITE_SHM_NLOCK]: +** This array records the various locks held by clients on each of the +** SQLITE_SHM_NLOCK slots. If the aLock[] entry is set to 0, then no +** locks are held by the process on this slot. If it is set to -1, then +** some client holds an EXCLUSIVE lock on the locking slot. If the aLock[] +** value is set to a positive value, then it is the number of shared +** locks currently held on the slot. +** +** aMutex[SQLITE_SHM_NLOCK]: +** Normally, when SQLITE_ENABLE_SETLK_TIMEOUT is not defined, mutex +** pShmMutex is used to protect the aLock[] array and the right to +** call fcntl() on unixShmNode.hShm to obtain or release locks. +** +** If SQLITE_ENABLE_SETLK_TIMEOUT is defined though, we use an array +** of mutexes - one for each locking slot. To read or write locking +** slot aLock[iSlot], the caller must hold the corresponding mutex +** aMutex[iSlot]. Similarly, to call fcntl() to obtain or release a +** lock corresponding to slot iSlot, mutex aMutex[iSlot] must be held. */ struct unixShmNode { unixInodeInfo *pInode; /* unixInodeInfo that owns this SHM node */ @@ -41966,10 +42707,11 @@ struct unixShmNode { char **apRegion; /* Array of mapped shared-memory regions */ int nRef; /* Number of unixShm objects pointing to this */ unixShm *pFirst; /* All unixShm objects pointing to this */ +#ifdef SQLITE_ENABLE_SETLK_TIMEOUT + sqlite3_mutex *aMutex[SQLITE_SHM_NLOCK]; +#endif int aLock[SQLITE_SHM_NLOCK]; /* # shared locks on slot, -1==excl lock */ #ifdef SQLITE_DEBUG - u8 exclMask; /* Mask of exclusive locks held */ - u8 sharedMask; /* Mask of shared locks held */ u8 nextShmId; /* Next available unixShm.id value */ #endif }; @@ -42052,16 +42794,35 @@ static int unixShmSystemLock( struct flock f; /* The posix advisory locking structure */ int rc = SQLITE_OK; /* Result code form fcntl() */ - /* Access to the unixShmNode object is serialized by the caller */ pShmNode = pFile->pInode->pShmNode; - assert( pShmNode->nRef==0 || sqlite3_mutex_held(pShmNode->pShmMutex) ); - assert( pShmNode->nRef>0 || unixMutexHeld() ); + + /* Assert that the parameters are within expected range and that the + ** correct mutex or mutexes are held. */ + assert( pShmNode->nRef>=0 ); + assert( (ofst==UNIX_SHM_DMS && n==1) + || (ofst>=UNIX_SHM_BASE && ofst+n<=(UNIX_SHM_BASE+SQLITE_SHM_NLOCK)) + ); + if( ofst==UNIX_SHM_DMS ){ + assert( pShmNode->nRef>0 || unixMutexHeld() ); + assert( pShmNode->nRef==0 || sqlite3_mutex_held(pShmNode->pShmMutex) ); + }else{ +#ifdef SQLITE_ENABLE_SETLK_TIMEOUT + int ii; + for(ii=ofst-UNIX_SHM_BASE; iiaMutex[ii]) ); + } +#else + assert( sqlite3_mutex_held(pShmNode->pShmMutex) ); + assert( pShmNode->nRef>0 ); +#endif + } /* Shared locks never span more than one byte */ assert( n==1 || lockType!=F_RDLCK ); /* Locks are within range */ assert( n>=1 && n<=SQLITE_SHM_NLOCK ); + assert( ofst>=UNIX_SHM_BASE && ofst<=(UNIX_SHM_DMS+SQLITE_SHM_NLOCK) ); if( pShmNode->hShm>=0 ){ int res; @@ -42072,7 +42833,7 @@ static int unixShmSystemLock( f.l_len = n; res = osSetPosixAdvisoryLock(pShmNode->hShm, &f, pFile); if( res==-1 ){ -#ifdef SQLITE_ENABLE_SETLK_TIMEOUT +#if defined(SQLITE_ENABLE_SETLK_TIMEOUT) && SQLITE_ENABLE_SETLK_TIMEOUT==1 rc = (pFile->iBusyTimeout ? SQLITE_BUSY_TIMEOUT : SQLITE_BUSY); #else rc = SQLITE_BUSY; @@ -42080,39 +42841,28 @@ static int unixShmSystemLock( } } - /* Update the global lock state and do debug tracing */ + /* Do debug tracing */ #ifdef SQLITE_DEBUG - { u16 mask; OSTRACE(("SHM-LOCK ")); - mask = ofst>31 ? 0xffff : (1<<(ofst+n)) - (1<exclMask &= ~mask; - pShmNode->sharedMask &= ~mask; + OSTRACE(("unlock %d..%d ok\n", ofst, ofst+n-1)); }else if( lockType==F_RDLCK ){ - OSTRACE(("read-lock %d ok", ofst)); - pShmNode->exclMask &= ~mask; - pShmNode->sharedMask |= mask; + OSTRACE(("read-lock %d..%d ok\n", ofst, ofst+n-1)); }else{ assert( lockType==F_WRLCK ); - OSTRACE(("write-lock %d ok", ofst)); - pShmNode->exclMask |= mask; - pShmNode->sharedMask &= ~mask; + OSTRACE(("write-lock %d..%d ok\n", ofst, ofst+n-1)); } }else{ if( lockType==F_UNLCK ){ - OSTRACE(("unlock %d failed", ofst)); + OSTRACE(("unlock %d..%d failed\n", ofst, ofst+n-1)); }else if( lockType==F_RDLCK ){ - OSTRACE(("read-lock failed")); + OSTRACE(("read-lock %d..%d failed\n", ofst, ofst+n-1)); }else{ assert( lockType==F_WRLCK ); - OSTRACE(("write-lock %d failed", ofst)); + OSTRACE(("write-lock %d..%d failed\n", ofst, ofst+n-1)); } } - OSTRACE((" - afterwards %03x,%03x\n", - pShmNode->sharedMask, pShmNode->exclMask)); - } #endif return rc; @@ -42149,6 +42899,11 @@ static void unixShmPurge(unixFile *pFd){ int i; assert( p->pInode==pFd->pInode ); sqlite3_mutex_free(p->pShmMutex); +#ifdef SQLITE_ENABLE_SETLK_TIMEOUT + for(i=0; iaMutex[i]); + } +#endif for(i=0; inRegion; i+=nShmPerMap){ if( p->hShm>=0 ){ osMunmap(p->apRegion[i], p->szRegion); @@ -42208,7 +42963,20 @@ static int unixLockSharedMemory(unixFile *pDbFd, unixShmNode *pShmNode){ pShmNode->isUnlocked = 1; rc = SQLITE_READONLY_CANTINIT; }else{ +#ifdef SQLITE_ENABLE_SETLK_TIMEOUT + /* Do not use a blocking lock here. If the lock cannot be obtained + ** immediately, it means some other connection is truncating the + ** *-shm file. And after it has done so, it will not release its + ** lock, but only downgrade it to a shared lock. So no point in + ** blocking here. The call below to obtain the shared DMS lock may + ** use a blocking lock. */ + int iSaveTimeout = pDbFd->iBusyTimeout; + pDbFd->iBusyTimeout = 0; +#endif rc = unixShmSystemLock(pDbFd, F_WRLCK, UNIX_SHM_DMS, 1); +#ifdef SQLITE_ENABLE_SETLK_TIMEOUT + pDbFd->iBusyTimeout = iSaveTimeout; +#endif /* The first connection to attach must truncate the -shm file. We ** truncate to 3 bytes (an arbitrary small number, less than the ** -shm header size) rather than 0 as a system debugging aid, to @@ -42329,6 +43097,18 @@ static int unixOpenSharedMemory(unixFile *pDbFd){ rc = SQLITE_NOMEM_BKPT; goto shm_open_err; } +#ifdef SQLITE_ENABLE_SETLK_TIMEOUT + { + int ii; + for(ii=0; iiaMutex[ii] = sqlite3_mutex_alloc(SQLITE_MUTEX_FAST); + if( pShmNode->aMutex[ii]==0 ){ + rc = SQLITE_NOMEM_BKPT; + goto shm_open_err; + } + } + } +#endif } if( pInode->bProcessLock==0 ){ @@ -42550,9 +43330,11 @@ static int unixShmMap( */ #ifdef SQLITE_DEBUG static int assertLockingArrayOk(unixShmNode *pShmNode){ +#ifdef SQLITE_ENABLE_SETLK_TIMEOUT + return 1; +#else unixShm *pX; int aLock[SQLITE_SHM_NLOCK]; - assert( sqlite3_mutex_held(pShmNode->pShmMutex) ); memset(aLock, 0, sizeof(aLock)); for(pX=pShmNode->pFirst; pX; pX=pX->pNext){ @@ -42570,13 +43352,14 @@ static int assertLockingArrayOk(unixShmNode *pShmNode){ assert( 0==memcmp(pShmNode->aLock, aLock, sizeof(aLock)) ); return (memcmp(pShmNode->aLock, aLock, sizeof(aLock))==0); +#endif } #endif /* ** Change the lock state for a shared-memory segment. ** -** Note that the relationship between SHAREd and EXCLUSIVE locks is a little +** Note that the relationship between SHARED and EXCLUSIVE locks is a little ** different here than in posix. In xShmLock(), one can go from unlocked ** to shared and back or from unlocked to exclusive and back. But one may ** not go from shared to exclusive or from exclusive to shared. @@ -42591,7 +43374,7 @@ static int unixShmLock( unixShm *p; /* The shared memory being locked */ unixShmNode *pShmNode; /* The underlying file iNode */ int rc = SQLITE_OK; /* Result code */ - u16 mask; /* Mask of locks to take or release */ + u16 mask = (1<<(ofst+n)) - (1<pShm; @@ -42626,88 +43409,151 @@ static int unixShmLock( ** It is not permitted to block on the RECOVER lock. */ #ifdef SQLITE_ENABLE_SETLK_TIMEOUT - assert( (flags & SQLITE_SHM_UNLOCK) || pDbFd->iBusyTimeout==0 || ( - (ofst!=2) /* not RECOVER */ - && (ofst!=1 || (p->exclMask|p->sharedMask)==0) - && (ofst!=0 || (p->exclMask|p->sharedMask)<3) - && (ofst<3 || (p->exclMask|p->sharedMask)<(1<exclMask|p->sharedMask); + assert( (flags & SQLITE_SHM_UNLOCK) || pDbFd->iBusyTimeout==0 || ( + (ofst!=2) /* not RECOVER */ + && (ofst!=1 || lockMask==0 || lockMask==2) + && (ofst!=0 || lockMask<3) + && (ofst<3 || lockMask<(1<1 || mask==(1<pShmMutex); - assert( assertLockingArrayOk(pShmNode) ); - if( flags & SQLITE_SHM_UNLOCK ){ - if( (p->exclMask|p->sharedMask) & mask ){ - int ii; - int bUnlock = 1; + /* Check if there is any work to do. There are three cases: + ** + ** a) An unlock operation where there are locks to unlock, + ** b) An shared lock where the requested lock is not already held + ** c) An exclusive lock where the requested lock is not already held + ** + ** The SQLite core never requests an exclusive lock that it already holds. + ** This is assert()ed below. + */ + assert( flags!=(SQLITE_SHM_EXCLUSIVE|SQLITE_SHM_LOCK) + || 0==(p->exclMask & mask) + ); + if( ((flags & SQLITE_SHM_UNLOCK) && ((p->exclMask|p->sharedMask) & mask)) + || (flags==(SQLITE_SHM_SHARED|SQLITE_SHM_LOCK) && 0==(p->sharedMask & mask)) + || (flags==(SQLITE_SHM_EXCLUSIVE|SQLITE_SHM_LOCK)) + ){ - for(ii=ofst; ii((p->sharedMask & (1<aMutex[iMutex]); + if( rc!=SQLITE_OK ) goto leave_shmnode_mutexes; + }else{ + sqlite3_mutex_enter(pShmNode->aMutex[iMutex]); } + } +#else + sqlite3_mutex_enter(pShmNode->pShmMutex); +#endif - if( bUnlock ){ - rc = unixShmSystemLock(pDbFd, F_UNLCK, ofst+UNIX_SHM_BASE, n); - if( rc==SQLITE_OK ){ - memset(&aLock[ofst], 0, sizeof(int)*n); + if( ALWAYS(rc==SQLITE_OK) ){ + if( flags & SQLITE_SHM_UNLOCK ){ + /* Case (a) - unlock. */ + int bUnlock = 1; + assert( (p->exclMask & p->sharedMask)==0 ); + assert( !(flags & SQLITE_SHM_EXCLUSIVE) || (p->exclMask & mask)==mask ); + assert( !(flags & SQLITE_SHM_SHARED) || (p->sharedMask & mask)==mask ); + + /* If this is a SHARED lock being unlocked, it is possible that other + ** clients within this process are holding the same SHARED lock. In + ** this case, set bUnlock to 0 so that the posix lock is not removed + ** from the file-descriptor below. */ + if( flags & SQLITE_SHM_SHARED ){ + assert( n==1 ); + assert( aLock[ofst]>=1 ); + if( aLock[ofst]>1 ){ + bUnlock = 0; + aLock[ofst]--; + p->sharedMask &= ~mask; + } } - }else if( ALWAYS(p->sharedMask & (1<1 ); - aLock[ofst]--; - } - /* Undo the local locks */ - if( rc==SQLITE_OK ){ - p->exclMask &= ~mask; - p->sharedMask &= ~mask; - } - } - }else if( flags & SQLITE_SHM_SHARED ){ - assert( n==1 ); - assert( (p->exclMask & (1<sharedMask & mask)==0 ){ - if( aLock[ofst]<0 ){ - rc = SQLITE_BUSY; - }else if( aLock[ofst]==0 ){ - rc = unixShmSystemLock(pDbFd, F_RDLCK, ofst+UNIX_SHM_BASE, n); - } + if( bUnlock ){ + rc = unixShmSystemLock(pDbFd, F_UNLCK, ofst+UNIX_SHM_BASE, n); + if( rc==SQLITE_OK ){ + memset(&aLock[ofst], 0, sizeof(int)*n); + p->sharedMask &= ~mask; + p->exclMask &= ~mask; + } + } + }else if( flags & SQLITE_SHM_SHARED ){ + /* Case (b) - a shared lock. */ - /* Get the local shared locks */ - if( rc==SQLITE_OK ){ - p->sharedMask |= mask; - aLock[ofst]++; - } - } - }else{ - /* Make sure no sibling connections hold locks that will block this - ** lock. If any do, return SQLITE_BUSY right away. */ - int ii; - for(ii=ofst; iisharedMask & mask)==0 ); - if( ALWAYS((p->exclMask & (1<sharedMask |= mask; + aLock[ofst]++; + } + }else{ + /* Case (c) - an exclusive lock. */ + int ii; + + assert( flags==(SQLITE_SHM_LOCK|SQLITE_SHM_EXCLUSIVE) ); assert( (p->sharedMask & mask)==0 ); - p->exclMask |= mask; + assert( (p->exclMask & mask)==0 ); + + /* Make sure no sibling connections hold locks that will block this + ** lock. If any do, return SQLITE_BUSY right away. */ for(ii=ofst; iiexclMask |= mask; + for(ii=ofst; ii=ofst; iMutex--){ + sqlite3_mutex_leave(pShmNode->aMutex[iMutex]); + } +#else + sqlite3_mutex_leave(pShmNode->pShmMutex); +#endif } - assert( assertLockingArrayOk(pShmNode) ); - sqlite3_mutex_leave(pShmNode->pShmMutex); + OSTRACE(("SHM-LOCK shmid-%d, pid-%d got %03x,%03x\n", p->id, osGetpid(0), p->sharedMask, p->exclMask)); return rc; @@ -42957,11 +43803,16 @@ static int unixFetch(sqlite3_file *fd, i64 iOff, int nAmt, void **pp){ #if SQLITE_MAX_MMAP_SIZE>0 if( pFd->mmapSizeMax>0 ){ + /* Ensure that there is always at least a 256 byte buffer of addressable + ** memory following the returned page. If the database is corrupt, + ** SQLite may overread the page slightly (in practice only a few bytes, + ** but 256 is safe, round, number). */ + const int nEofBuffer = 256; if( pFd->pMapRegion==0 ){ int rc = unixMapfile(pFd, -1); if( rc!=SQLITE_OK ) return rc; } - if( pFd->mmapSize >= iOff+nAmt ){ + if( pFd->mmapSize >= (iOff+nAmt+nEofBuffer) ){ *pp = &((u8 *)pFd->pMapRegion)[iOff]; pFd->nFetchOut++; } @@ -43905,12 +44756,19 @@ static int unixOpen( rc = SQLITE_READONLY_DIRECTORY; }else if( errno!=EISDIR && isReadWrite ){ /* Failed to open the file for read/write access. Try read-only. */ + UnixUnusedFd *pReadonly = 0; flags &= ~(SQLITE_OPEN_READWRITE|SQLITE_OPEN_CREATE); openFlags &= ~(O_RDWR|O_CREAT); flags |= SQLITE_OPEN_READONLY; openFlags |= O_RDONLY; isReadonly = 1; - fd = robust_open(zName, openFlags, openMode); + pReadonly = findReusableFd(zName, flags); + if( pReadonly ){ + fd = pReadonly->fd; + sqlite3_free(pReadonly); + }else{ + fd = robust_open(zName, openFlags, openMode); + } } } if( fd<0 ){ @@ -50314,6 +51172,11 @@ static int winFetch(sqlite3_file *fd, i64 iOff, int nAmt, void **pp){ #if SQLITE_MAX_MMAP_SIZE>0 if( pFd->mmapSizeMax>0 ){ + /* Ensure that there is always at least a 256 byte buffer of addressable + ** memory following the returned page. If the database is corrupt, + ** SQLite may overread the page slightly (in practice only a few bytes, + ** but 256 is safe, round, number). */ + const int nEofBuffer = 256; if( pFd->pMapRegion==0 ){ int rc = winMapfile(pFd, -1); if( rc!=SQLITE_OK ){ @@ -50322,7 +51185,7 @@ static int winFetch(sqlite3_file *fd, i64 iOff, int nAmt, void **pp){ return rc; } } - if( pFd->mmapSize >= iOff+nAmt ){ + if( pFd->mmapSize >= (iOff+nAmt+nEofBuffer) ){ assert( pFd->pMapRegion!=0 ); *pp = &((u8 *)pFd->pMapRegion)[iOff]; pFd->nFetchOut++; @@ -52801,6 +53664,14 @@ SQLITE_API unsigned char *sqlite3_serialize( pOut = 0; }else{ sz = sqlite3_column_int64(pStmt, 0)*szPage; + if( sz==0 ){ + sqlite3_reset(pStmt); + sqlite3_exec(db, "BEGIN IMMEDIATE; COMMIT;", 0, 0, 0); + rc = sqlite3_step(pStmt); + if( rc==SQLITE_ROW ){ + sz = sqlite3_column_int64(pStmt, 0)*szPage; + } + } if( piSize ) *piSize = sz; if( mFlags & SQLITE_SERIALIZE_NOCOPY ){ pOut = 0; @@ -56925,7 +57796,7 @@ struct Pager { char *zJournal; /* Name of the journal file */ int (*xBusyHandler)(void*); /* Function to call when busy */ void *pBusyHandlerArg; /* Context argument for xBusyHandler */ - int aStat[4]; /* Total cache hits, misses, writes, spills */ + u32 aStat[4]; /* Total cache hits, misses, writes, spills */ #ifdef SQLITE_TEST int nRead; /* Database pages read */ #endif @@ -57055,9 +57926,8 @@ SQLITE_PRIVATE int sqlite3PagerDirectReadOk(Pager *pPager, Pgno pgno){ #ifndef SQLITE_OMIT_WAL if( pPager->pWal ){ u32 iRead = 0; - int rc; - rc = sqlite3WalFindFrame(pPager->pWal, pgno, &iRead); - return (rc==SQLITE_OK && iRead==0); + (void)sqlite3WalFindFrame(pPager->pWal, pgno, &iRead); + return iRead==0; } #endif return 1; @@ -57729,9 +58599,32 @@ static int writeJournalHdr(Pager *pPager){ memset(zHeader, 0, sizeof(aJournalMagic)+4); } + + /* The random check-hash initializer */ - sqlite3_randomness(sizeof(pPager->cksumInit), &pPager->cksumInit); + if( pPager->journalMode!=PAGER_JOURNALMODE_MEMORY ){ + sqlite3_randomness(sizeof(pPager->cksumInit), &pPager->cksumInit); + } +#ifdef SQLITE_DEBUG + else{ + /* The Pager.cksumInit variable is usually randomized above to protect + ** against there being existing records in the journal file. This is + ** dangerous, as following a crash they may be mistaken for records + ** written by the current transaction and rolled back into the database + ** file, causing corruption. The following assert statements verify + ** that this is not required in "journal_mode=memory" mode, as in that + ** case the journal file is always 0 bytes in size at this point. + ** It is advantageous to avoid the sqlite3_randomness() call if possible + ** as it takes the global PRNG mutex. */ + i64 sz = 0; + sqlite3OsFileSize(pPager->jfd, &sz); + assert( sz==0 ); + assert( pPager->journalOff==journalHdrOffset(pPager) ); + assert( sqlite3JournalIsInMemory(pPager->jfd) ); + } +#endif put32bits(&zHeader[sizeof(aJournalMagic)+4], pPager->cksumInit); + /* The initial database size */ put32bits(&zHeader[sizeof(aJournalMagic)+8], pPager->dbOrigSize); /* The assumed sector size for this process */ @@ -58375,6 +59268,9 @@ static int pager_end_transaction(Pager *pPager, int hasSuper, int bCommit){ return (rc==SQLITE_OK?rc2:rc); } +/* Forward reference */ +static int pager_playback(Pager *pPager, int isHot); + /* ** Execute a rollback if a transaction is active and unlock the ** database file. @@ -58403,6 +59299,21 @@ static void pagerUnlockAndRollback(Pager *pPager){ assert( pPager->eState==PAGER_READER ); pager_end_transaction(pPager, 0, 0); } + }else if( pPager->eState==PAGER_ERROR + && pPager->journalMode==PAGER_JOURNALMODE_MEMORY + && isOpen(pPager->jfd) + ){ + /* Special case for a ROLLBACK due to I/O error with an in-memory + ** journal: We have to rollback immediately, before the journal is + ** closed, because once it is closed, all content is forgotten. */ + int errCode = pPager->errCode; + u8 eLock = pPager->eLock; + pPager->eState = PAGER_OPEN; + pPager->errCode = SQLITE_OK; + pPager->eLock = EXCLUSIVE_LOCK; + pager_playback(pPager, 1); + pPager->errCode = errCode; + pPager->eLock = eLock; } pager_unlock(pPager); } @@ -61258,10 +62169,13 @@ SQLITE_PRIVATE int sqlite3PagerOpen( */ SQLITE_API sqlite3_file *sqlite3_database_file_object(const char *zName){ Pager *pPager; + const char *p; while( zName[-1]!=0 || zName[-2]!=0 || zName[-3]!=0 || zName[-4]!=0 ){ zName--; } - pPager = *(Pager**)(zName - 4 - sizeof(Pager*)); + p = zName - 4 - sizeof(Pager*); + assert( EIGHT_BYTE_ALIGNMENT(p) ); + pPager = *(Pager**)p; return pPager->fd; } @@ -61895,8 +62809,20 @@ SQLITE_PRIVATE int sqlite3PagerGet( DbPage **ppPage, /* Write a pointer to the page here */ int flags /* PAGER_GET_XXX flags */ ){ - /* printf("PAGE %u\n", pgno); fflush(stdout); */ +#if 0 /* Trace page fetch by setting to 1 */ + int rc; + printf("PAGE %u\n", pgno); + fflush(stdout); + rc = pPager->xGet(pPager, pgno, ppPage, flags); + if( rc ){ + printf("PAGE %u failed with 0x%02x\n", pgno, rc); + fflush(stdout); + } + return rc; +#else + /* Normal, high-speed version of sqlite3PagerGet() */ return pPager->xGet(pPager, pgno, ppPage, flags); +#endif } /* @@ -62772,6 +63698,13 @@ SQLITE_PRIVATE int sqlite3PagerCommitPhaseOne( rc = sqlite3OsFileControl(fd, SQLITE_FCNTL_BEGIN_ATOMIC_WRITE, 0); if( rc==SQLITE_OK ){ rc = pager_write_pagelist(pPager, pList); + if( rc==SQLITE_OK && pPager->dbSize>pPager->dbFileSize ){ + char *pTmp = pPager->pTmpSpace; + int szPage = (int)pPager->pageSize; + memset(pTmp, 0, szPage); + rc = sqlite3OsWrite(pPager->fd, pTmp, szPage, + ((i64)pPager->dbSize*pPager->pageSize)-szPage); + } if( rc==SQLITE_OK ){ rc = sqlite3OsFileControl(fd, SQLITE_FCNTL_COMMIT_ATOMIC_WRITE, 0); } @@ -63006,11 +63939,11 @@ SQLITE_PRIVATE int *sqlite3PagerStats(Pager *pPager){ a[3] = pPager->eState==PAGER_OPEN ? -1 : (int) pPager->dbSize; a[4] = pPager->eState; a[5] = pPager->errCode; - a[6] = pPager->aStat[PAGER_STAT_HIT]; - a[7] = pPager->aStat[PAGER_STAT_MISS]; + a[6] = (int)pPager->aStat[PAGER_STAT_HIT] & 0x7fffffff; + a[7] = (int)pPager->aStat[PAGER_STAT_MISS] & 0x7fffffff; a[8] = 0; /* Used to be pPager->nOvfl */ a[9] = pPager->nRead; - a[10] = pPager->aStat[PAGER_STAT_WRITE]; + a[10] = (int)pPager->aStat[PAGER_STAT_WRITE] & 0x7fffffff; return a; } #endif @@ -63026,7 +63959,7 @@ SQLITE_PRIVATE int *sqlite3PagerStats(Pager *pPager){ ** reset parameter is non-zero, the cache hit or miss count is zeroed before ** returning. */ -SQLITE_PRIVATE void sqlite3PagerCacheStat(Pager *pPager, int eStat, int reset, int *pnVal){ +SQLITE_PRIVATE void sqlite3PagerCacheStat(Pager *pPager, int eStat, int reset, u64 *pnVal){ assert( eStat==SQLITE_DBSTATUS_CACHE_HIT || eStat==SQLITE_DBSTATUS_CACHE_MISS @@ -63262,7 +64195,7 @@ SQLITE_PRIVATE sqlite3_file *sqlite3PagerFile(Pager *pPager){ ** This will be either the rollback journal or the WAL file. */ SQLITE_PRIVATE sqlite3_file *sqlite3PagerJrnlFile(Pager *pPager){ -#if SQLITE_OMIT_WAL +#ifdef SQLITE_OMIT_WAL return pPager->jfd; #else return pPager->pWal ? sqlite3WalFile(pPager->pWal) : pPager->jfd; @@ -63583,7 +64516,7 @@ SQLITE_PRIVATE int sqlite3PagerSetJournalMode(Pager *pPager, int eMode){ } assert( state==pPager->eState ); } - }else if( eMode==PAGER_JOURNALMODE_OFF ){ + }else if( eMode==PAGER_JOURNALMODE_OFF || eMode==PAGER_JOURNALMODE_MEMORY ){ sqlite3OsClose(pPager->jfd); } } @@ -63966,7 +64899,7 @@ SQLITE_PRIVATE int sqlite3PagerWalFramesize(Pager *pPager){ } #endif -#ifdef SQLITE_USE_SEH +#if defined(SQLITE_USE_SEH) && !defined(SQLITE_OMIT_WAL) SQLITE_PRIVATE int sqlite3PagerWalSystemErrno(Pager *pPager){ return sqlite3WalSystemErrno(pPager->pWal); } @@ -65982,6 +66915,19 @@ static int walIteratorInit(Wal *pWal, u32 nBackfill, WalIterator **pp){ } #ifdef SQLITE_ENABLE_SETLK_TIMEOUT + + +/* +** Attempt to enable blocking locks that block for nMs ms. Return 1 if +** blocking locks are successfully enabled, or 0 otherwise. +*/ +static int walEnableBlockingMs(Wal *pWal, int nMs){ + int rc = sqlite3OsFileControl( + pWal->pDbFd, SQLITE_FCNTL_LOCK_TIMEOUT, (void*)&nMs + ); + return (rc==SQLITE_OK); +} + /* ** Attempt to enable blocking locks. Blocking locks are enabled only if (a) ** they are supported by the VFS, and (b) the database handle is configured @@ -65993,11 +66939,7 @@ static int walEnableBlocking(Wal *pWal){ if( pWal->db ){ int tmout = pWal->db->busyTimeout; if( tmout ){ - int rc; - rc = sqlite3OsFileControl( - pWal->pDbFd, SQLITE_FCNTL_LOCK_TIMEOUT, (void*)&tmout - ); - res = (rc==SQLITE_OK); + res = walEnableBlockingMs(pWal, tmout); } } return res; @@ -66046,20 +66988,10 @@ SQLITE_PRIVATE void sqlite3WalDb(Wal *pWal, sqlite3 *db){ pWal->db = db; } -/* -** Take an exclusive WRITE lock. Blocking if so configured. -*/ -static int walLockWriter(Wal *pWal){ - int rc; - walEnableBlocking(pWal); - rc = walLockExclusive(pWal, WAL_WRITE_LOCK, 1); - walDisableBlocking(pWal); - return rc; -} #else # define walEnableBlocking(x) 0 # define walDisableBlocking(x) -# define walLockWriter(pWal) walLockExclusive((pWal), WAL_WRITE_LOCK, 1) +# define walEnableBlockingMs(pWal, ms) 0 # define sqlite3WalDb(pWal, db) #endif /* ifdef SQLITE_ENABLE_SETLK_TIMEOUT */ @@ -66660,7 +67592,9 @@ static int walIndexReadHdr(Wal *pWal, int *pChanged){ } }else{ int bWriteLock = pWal->writeLock; - if( bWriteLock || SQLITE_OK==(rc = walLockWriter(pWal)) ){ + if( bWriteLock + || SQLITE_OK==(rc = walLockExclusive(pWal, WAL_WRITE_LOCK, 1)) + ){ pWal->writeLock = 1; if( SQLITE_OK==(rc = walIndexPage(pWal, 0, &page0)) ){ badHdr = walIndexTryHdr(pWal, pChanged); @@ -66668,7 +67602,8 @@ static int walIndexReadHdr(Wal *pWal, int *pChanged){ /* If the wal-index header is still malformed even while holding ** a WRITE lock, it can only mean that the header is corrupted and ** needs to be reconstructed. So run recovery to do exactly that. - */ + ** Disable blocking locks first. */ + walDisableBlocking(pWal); rc = walIndexRecover(pWal); *pChanged = 1; } @@ -66878,6 +67813,37 @@ static int walBeginShmUnreliable(Wal *pWal, int *pChanged){ return rc; } +/* +** The final argument passed to walTryBeginRead() is of type (int*). The +** caller should invoke walTryBeginRead as follows: +** +** int cnt = 0; +** do { +** rc = walTryBeginRead(..., &cnt); +** }while( rc==WAL_RETRY ); +** +** The final value of "cnt" is of no use to the caller. It is used by +** the implementation of walTryBeginRead() as follows: +** +** + Each time walTryBeginRead() is called, it is incremented. Once +** it reaches WAL_RETRY_PROTOCOL_LIMIT - indicating that walTryBeginRead() +** has many times been invoked and failed with WAL_RETRY - walTryBeginRead() +** returns SQLITE_PROTOCOL. +** +** + If SQLITE_ENABLE_SETLK_TIMEOUT is defined and walTryBeginRead() failed +** because a blocking lock timed out (SQLITE_BUSY_TIMEOUT from the OS +** layer), the WAL_RETRY_BLOCKED_MASK bit is set in "cnt". In this case +** the next invocation of walTryBeginRead() may omit an expected call to +** sqlite3OsSleep(). There has already been a delay when the previous call +** waited on a lock. +*/ +#define WAL_RETRY_PROTOCOL_LIMIT 100 +#ifdef SQLITE_ENABLE_SETLK_TIMEOUT +# define WAL_RETRY_BLOCKED_MASK 0x10000000 +#else +# define WAL_RETRY_BLOCKED_MASK 0 +#endif + /* ** Attempt to start a read transaction. This might fail due to a race or ** other transient condition. When that happens, it returns WAL_RETRY to @@ -66928,13 +67894,16 @@ static int walBeginShmUnreliable(Wal *pWal, int *pChanged){ ** so it takes care to hold an exclusive lock on the corresponding ** WAL_READ_LOCK() while changing values. */ -static int walTryBeginRead(Wal *pWal, int *pChanged, int useWal, int cnt){ +static int walTryBeginRead(Wal *pWal, int *pChanged, int useWal, int *pCnt){ volatile WalCkptInfo *pInfo; /* Checkpoint information in wal-index */ u32 mxReadMark; /* Largest aReadMark[] value */ int mxI; /* Index of largest aReadMark[] value */ int i; /* Loop counter */ int rc = SQLITE_OK; /* Return code */ u32 mxFrame; /* Wal frame to lock to */ +#ifdef SQLITE_ENABLE_SETLK_TIMEOUT + int nBlockTmout = 0; +#endif assert( pWal->readLock<0 ); /* Not currently locked */ @@ -66958,14 +67927,34 @@ static int walTryBeginRead(Wal *pWal, int *pChanged, int useWal, int cnt){ ** so that on the 100th (and last) RETRY we delay for 323 milliseconds. ** The total delay time before giving up is less than 10 seconds. */ - if( cnt>5 ){ + (*pCnt)++; + if( *pCnt>5 ){ int nDelay = 1; /* Pause time in microseconds */ - if( cnt>100 ){ + int cnt = (*pCnt & ~WAL_RETRY_BLOCKED_MASK); + if( cnt>WAL_RETRY_PROTOCOL_LIMIT ){ VVA_ONLY( pWal->lockError = 1; ) return SQLITE_PROTOCOL; } - if( cnt>=10 ) nDelay = (cnt-9)*(cnt-9)*39; + if( *pCnt>=10 ) nDelay = (cnt-9)*(cnt-9)*39; +#ifdef SQLITE_ENABLE_SETLK_TIMEOUT + /* In SQLITE_ENABLE_SETLK_TIMEOUT builds, configure the file-descriptor + ** to block for locks for approximately nDelay us. This affects three + ** locks: (a) the shared lock taken on the DMS slot in os_unix.c (if + ** using os_unix.c), (b) the WRITER lock taken in walIndexReadHdr() if the + ** first attempted read fails, and (c) the shared lock taken on the + ** read-mark. + ** + ** If the previous call failed due to an SQLITE_BUSY_TIMEOUT error, + ** then sleep for the minimum of 1us. The previous call already provided + ** an extra delay while it was blocking on the lock. + */ + nBlockTmout = (nDelay+998) / 1000; + if( !useWal && walEnableBlockingMs(pWal, nBlockTmout) ){ + if( *pCnt & WAL_RETRY_BLOCKED_MASK ) nDelay = 1; + } +#endif sqlite3OsSleep(pWal->pVfs, nDelay); + *pCnt &= ~WAL_RETRY_BLOCKED_MASK; } if( !useWal ){ @@ -66973,6 +67962,13 @@ static int walTryBeginRead(Wal *pWal, int *pChanged, int useWal, int cnt){ if( pWal->bShmUnreliable==0 ){ rc = walIndexReadHdr(pWal, pChanged); } +#ifdef SQLITE_ENABLE_SETLK_TIMEOUT + walDisableBlocking(pWal); + if( rc==SQLITE_BUSY_TIMEOUT ){ + rc = SQLITE_BUSY; + *pCnt |= WAL_RETRY_BLOCKED_MASK; + } +#endif if( rc==SQLITE_BUSY ){ /* If there is not a recovery running in another thread or process ** then convert BUSY errors to WAL_RETRY. If recovery is known to @@ -67087,9 +68083,19 @@ static int walTryBeginRead(Wal *pWal, int *pChanged, int useWal, int cnt){ return rc==SQLITE_BUSY ? WAL_RETRY : SQLITE_READONLY_CANTINIT; } + (void)walEnableBlockingMs(pWal, nBlockTmout); rc = walLockShared(pWal, WAL_READ_LOCK(mxI)); + walDisableBlocking(pWal); if( rc ){ - return rc==SQLITE_BUSY ? WAL_RETRY : rc; +#ifdef SQLITE_ENABLE_SETLK_TIMEOUT + if( rc==SQLITE_BUSY_TIMEOUT ){ + *pCnt |= WAL_RETRY_BLOCKED_MASK; + } +#else + assert( rc!=SQLITE_BUSY_TIMEOUT ); +#endif + assert( (rc&0xFF)!=SQLITE_BUSY||rc==SQLITE_BUSY||rc==SQLITE_BUSY_TIMEOUT ); + return (rc&0xFF)==SQLITE_BUSY ? WAL_RETRY : rc; } /* Now that the read-lock has been obtained, check that neither the ** value in the aReadMark[] array or the contents of the wal-index @@ -67277,7 +68283,7 @@ static int walBeginReadTransaction(Wal *pWal, int *pChanged){ #endif do{ - rc = walTryBeginRead(pWal, pChanged, 0, ++cnt); + rc = walTryBeginRead(pWal, pChanged, 0, &cnt); }while( rc==WAL_RETRY ); testcase( (rc&0xff)==SQLITE_BUSY ); testcase( (rc&0xff)==SQLITE_IOERR ); @@ -67458,6 +68464,7 @@ static int walFindFrame( iRead = iFrame; } if( (nCollide--)==0 ){ + *piRead = 0; return SQLITE_CORRUPT_BKPT; } iKey = walNextHash(iKey); @@ -67761,7 +68768,7 @@ static int walRestartLog(Wal *pWal){ cnt = 0; do{ int notUsed; - rc = walTryBeginRead(pWal, ¬Used, 1, ++cnt); + rc = walTryBeginRead(pWal, ¬Used, 1, &cnt); }while( rc==WAL_RETRY ); assert( (rc&0xff)!=SQLITE_BUSY ); /* BUSY not possible when useWal==1 */ testcase( (rc&0xff)==SQLITE_IOERR ); @@ -68182,10 +69189,9 @@ SQLITE_PRIVATE int sqlite3WalCheckpoint( if( pWal->readOnly ) return SQLITE_READONLY; WALTRACE(("WAL%p: checkpoint begins\n", pWal)); - /* Enable blocking locks, if possible. If blocking locks are successfully - ** enabled, set xBusy2=0 so that the busy-handler is never invoked. */ + /* Enable blocking locks, if possible. */ sqlite3WalDb(pWal, db); - (void)walEnableBlocking(pWal); + if( xBusy2 ) (void)walEnableBlocking(pWal); /* IMPLEMENTATION-OF: R-62028-47212 All calls obtain an exclusive ** "checkpoint" lock on the database file. @@ -68226,9 +69232,14 @@ SQLITE_PRIVATE int sqlite3WalCheckpoint( /* Read the wal-index header. */ SEH_TRY { if( rc==SQLITE_OK ){ + /* For a passive checkpoint, do not re-enable blocking locks after + ** reading the wal-index header. A passive checkpoint should not block + ** or invoke the busy handler. The only lock such a checkpoint may + ** attempt to obtain is a lock on a read-slot, and it should give up + ** immediately and do a partial checkpoint if it cannot obtain it. */ walDisableBlocking(pWal); rc = walIndexReadHdr(pWal, &isChanged); - (void)walEnableBlocking(pWal); + if( eMode2!=SQLITE_CHECKPOINT_PASSIVE ) (void)walEnableBlocking(pWal); if( isChanged && pWal->pDbFd->pMethods->iVersion>=3 ){ sqlite3OsUnfetch(pWal->pDbFd, 0, 0); } @@ -68565,7 +69576,7 @@ SQLITE_PRIVATE sqlite3_file *sqlite3WalFile(Wal *pWal){ ** 22 1 Min embedded payload fraction (must be 32) ** 23 1 Min leaf payload fraction (must be 32) ** 24 4 File change counter -** 28 4 Reserved for future use +** 28 4 The size of the database in pages ** 32 4 First freelist page ** 36 4 Number of freelist pages in the file ** 40 60 15 4-byte meta values passed to higher layers @@ -69196,7 +70207,7 @@ struct IntegrityCk { BtShared *pBt; /* The tree being checked out */ Pager *pPager; /* The associated pager. Also accessible by pBt->pPager */ u8 *aPgRef; /* 1 bit per page in the db (see above) */ - Pgno nPage; /* Number of pages in the database */ + Pgno nCkPage; /* Pages in the database. 0 for partial check */ int mxErr; /* Stop accumulating errors when this reaches zero */ int nErr; /* Number of messages written to zErrMsg so far */ int rc; /* SQLITE_OK, SQLITE_NOMEM, or SQLITE_INTERRUPT */ @@ -69208,6 +70219,7 @@ struct IntegrityCk { StrAccum errMsg; /* Accumulate the error message text here */ u32 *heap; /* Min-heap used for analyzing cell coverage */ sqlite3 *db; /* Database connection running the check */ + i64 nRow; /* Number of rows visited in current tree */ }; /* @@ -69529,7 +70541,6 @@ SQLITE_PRIVATE void sqlite3BtreeLeaveCursor(BtCursor *pCur){ /************** End of btmutex.c *********************************************/ /************** Begin file btree.c *******************************************/ - /* ** 2004 April 6 ** @@ -69683,8 +70694,47 @@ int corruptPageError(int lineno, MemPage *p){ # define SQLITE_CORRUPT_PAGE(pMemPage) SQLITE_CORRUPT_PGNO(pMemPage->pgno) #endif +/* Default value for SHARED_LOCK_TRACE macro if shared-cache is disabled +** or if the lock tracking is disabled. This is always the value for +** release builds. +*/ +#define SHARED_LOCK_TRACE(X,MSG,TAB,TYPE) /*no-op*/ + #ifndef SQLITE_OMIT_SHARED_CACHE +#if 0 +/* ^---- Change to 1 and recompile to enable shared-lock tracing +** for debugging purposes. +** +** Print all shared-cache locks on a BtShared. Debugging use only. +*/ +static void sharedLockTrace( + BtShared *pBt, + const char *zMsg, + int iRoot, + int eLockType +){ + BtLock *pLock; + if( iRoot>0 ){ + printf("%s-%p %u%s:", zMsg, pBt, iRoot, eLockType==READ_LOCK?"R":"W"); + }else{ + printf("%s-%p:", zMsg, pBt); + } + for(pLock=pBt->pLock; pLock; pLock=pLock->pNext){ + printf(" %p/%u%s", pLock->pBtree, pLock->iTable, + pLock->eLock==READ_LOCK ? "R" : "W"); + while( pLock->pNext && pLock->pBtree==pLock->pNext->pBtree ){ + pLock = pLock->pNext; + printf(",%u%s", pLock->iTable, pLock->eLock==READ_LOCK ? "R" : "W"); + } + } + printf("\n"); + fflush(stdout); +} +#undef SHARED_LOCK_TRACE +#define SHARED_LOCK_TRACE(X,MSG,TAB,TYPE) sharedLockTrace(X,MSG,TAB,TYPE) +#endif /* Shared-lock tracing */ + #ifdef SQLITE_DEBUG /* **** This function is only used as part of an assert() statement. *** @@ -69761,6 +70811,8 @@ static int hasSharedCacheTableLock( iTab = iRoot; } + SHARED_LOCK_TRACE(pBtree->pBt,"hasLock",iRoot,eLockType); + /* Search for the required lock. Either a write-lock on root-page iTab, a ** write-lock on the schema table, or (if the client is reading) a ** read-lock on iTab will suffice. Return 1 if any of these are found. */ @@ -69894,6 +70946,8 @@ static int setSharedCacheTableLock(Btree *p, Pgno iTable, u8 eLock){ BtLock *pLock = 0; BtLock *pIter; + SHARED_LOCK_TRACE(pBt,"setLock", iTable, eLock); + assert( sqlite3BtreeHoldsMutex(p) ); assert( eLock==READ_LOCK || eLock==WRITE_LOCK ); assert( p->db!=0 ); @@ -69961,6 +71015,8 @@ static void clearAllSharedCacheTableLocks(Btree *p){ assert( p->sharable || 0==*ppIter ); assert( p->inTrans>0 ); + SHARED_LOCK_TRACE(pBt, "clearAllLocks", 0, 0); + while( *ppIter ){ BtLock *pLock = *ppIter; assert( (pBt->btsFlags & BTS_EXCLUSIVE)==0 || pBt->pWriter==pLock->pBtree ); @@ -69999,6 +71055,9 @@ static void clearAllSharedCacheTableLocks(Btree *p){ */ static void downgradeAllSharedCacheTableLocks(Btree *p){ BtShared *pBt = p->pBt; + + SHARED_LOCK_TRACE(pBt, "downgradeLocks", 0, 0); + if( pBt->pWriter==p ){ BtLock *pLock; pBt->pWriter = 0; @@ -74612,9 +75671,12 @@ static int accessPayload( if( pCur->aOverflow==0 || nOvfl*(int)sizeof(Pgno) > sqlite3MallocSize(pCur->aOverflow) ){ - Pgno *aNew = (Pgno*)sqlite3Realloc( - pCur->aOverflow, nOvfl*2*sizeof(Pgno) - ); + Pgno *aNew; + if( sqlite3FaultSim(413) ){ + aNew = 0; + }else{ + aNew = (Pgno*)sqlite3Realloc(pCur->aOverflow, nOvfl*2*sizeof(Pgno)); + } if( aNew==0 ){ return SQLITE_NOMEM_BKPT; }else{ @@ -74624,6 +75686,12 @@ static int accessPayload( memset(pCur->aOverflow, 0, nOvfl*sizeof(Pgno)); pCur->curFlags |= BTCF_ValidOvfl; }else{ + /* Sanity check the validity of the overflow page cache */ + assert( pCur->aOverflow[0]==nextPage + || pCur->aOverflow[0]==0 + || CORRUPT_DB ); + assert( pCur->aOverflow[0]!=0 || pCur->aOverflow[offset/ovflSize]==0 ); + /* If the overflow page-list cache has been allocated and the ** entry for the first required overflow page is valid, skip ** directly to it. @@ -74693,7 +75761,6 @@ static int accessPayload( assert( aWrite>=pBufStart ); /* due to (6) */ memcpy(aSave, aWrite, 4); rc = sqlite3OsRead(fd, aWrite, a+4, (i64)pBt->pageSize*(nextPage-1)); - if( rc && nextPage>pBt->nPage ) rc = SQLITE_CORRUPT_BKPT; nextPage = get4byte(aWrite); memcpy(aWrite, aSave, 4); }else @@ -75106,6 +76173,23 @@ SQLITE_PRIVATE int sqlite3BtreeFirst(BtCursor *pCur, int *pRes){ return rc; } +#ifdef SQLITE_DEBUG +/* The cursors is CURSOR_VALID and has BTCF_AtLast set. Verify that +** this flags are true for a consistent database. +** +** This routine is is called from within assert() statements only. +** It is an internal verification routine and does not appear in production +** builds. +*/ +static int cursorIsAtLastEntry(BtCursor *pCur){ + int ii; + for(ii=0; iiiPage; ii++){ + if( pCur->aiIdx[ii]!=pCur->apPage[ii]->nCell ) return 0; + } + return pCur->ix==pCur->pPage->nCell-1 && pCur->pPage->leaf!=0; +} +#endif + /* Move the cursor to the last entry in the table. Return SQLITE_OK ** on success. Set *pRes to 0 if the cursor actually points to something ** or set *pRes to 1 if the table is empty. @@ -75134,18 +76218,7 @@ SQLITE_PRIVATE int sqlite3BtreeLast(BtCursor *pCur, int *pRes){ /* If the cursor already points to the last entry, this is a no-op. */ if( CURSOR_VALID==pCur->eState && (pCur->curFlags & BTCF_AtLast)!=0 ){ -#ifdef SQLITE_DEBUG - /* This block serves to assert() that the cursor really does point - ** to the last entry in the b-tree. */ - int ii; - for(ii=0; iiiPage; ii++){ - assert( pCur->aiIdx[ii]==pCur->apPage[ii]->nCell ); - } - assert( pCur->ix==pCur->pPage->nCell-1 || CORRUPT_DB ); - testcase( pCur->ix!=pCur->pPage->nCell-1 ); - /* ^-- dbsqlfuzz b92b72e4de80b5140c30ab71372ca719b8feb618 */ - assert( pCur->pPage->leaf ); -#endif + assert( cursorIsAtLastEntry(pCur) || CORRUPT_DB ); *pRes = 0; return SQLITE_OK; } @@ -75198,6 +76271,7 @@ SQLITE_PRIVATE int sqlite3BtreeTableMoveto( } if( pCur->info.nKeycurFlags & BTCF_AtLast)!=0 ){ + assert( cursorIsAtLastEntry(pCur) || CORRUPT_DB ); *pRes = -1; return SQLITE_OK; } @@ -75664,10 +76738,10 @@ SQLITE_PRIVATE i64 sqlite3BtreeRowCountEst(BtCursor *pCur){ assert( cursorOwnsBtShared(pCur) ); assert( sqlite3_mutex_held(pCur->pBtree->db->mutex) ); - /* Currently this interface is only called by the OP_IfSmaller - ** opcode, and it that case the cursor will always be valid and - ** will always point to a leaf node. */ - if( NEVER(pCur->eState!=CURSOR_VALID) ) return -1; + /* Currently this interface is only called by the OP_IfSizeBetween + ** opcode and the OP_Count opcode with P3=1. In either case, + ** the cursor will always be valid unless the btree is empty. */ + if( pCur->eState!=CURSOR_VALID ) return 0; if( NEVER(pCur->pPage->leaf==0) ) return -1; n = pCur->pPage->nCell; @@ -75813,7 +76887,10 @@ static SQLITE_NOINLINE int btreePrevious(BtCursor *pCur){ } pPage = pCur->pPage; - assert( pPage->isInit ); + if( sqlite3FaultSim(412) ) pPage->isInit = 0; + if( !pPage->isInit ){ + return SQLITE_CORRUPT_BKPT; + } if( !pPage->leaf ){ int idx = pCur->ix; rc = moveToChild(pCur, get4byte(findCell(pPage, idx))); @@ -76486,7 +77563,10 @@ static int fillInCell( n = nHeader + nPayload; testcase( n==3 ); testcase( n==4 ); - if( n<4 ) n = 4; + if( n<4 ){ + n = 4; + pPayload[nPayload] = 0; + } *pnSize = n; assert( nSrc<=nPayload ); testcase( nSrcapEnd[] */ u8 *pSrcEnd; /* Current pCArray->apEnd[k] value */ + assert( nCell>0 ); assert( i(u32)usableSize) ){ j = 0; } + if( j>(u32)usableSize ){ j = 0; } memcpy(&pTmp[j], &aData[j], usableSize - j); for(k=0; ALWAYS(kixNx[k]<=i; k++){} @@ -77330,6 +78411,7 @@ static int editPage( return SQLITE_OK; editpage_fail: /* Unable to edit this page. Rebuild it from scratch instead. */ + if( nNew<1 ) return SQLITE_CORRUPT_BKPT; populateCellCache(pCArray, iNew, nNew); return rebuildPage(pCArray, iNew, nNew, pPg); } @@ -77790,7 +78872,7 @@ static int balance_nonroot( ** table-interior, index-leaf, or index-interior). */ if( pOld->aData[0]!=apOld[0]->aData[0] ){ - rc = SQLITE_CORRUPT_BKPT; + rc = SQLITE_CORRUPT_PAGE(pOld); goto balance_cleanup; } @@ -77814,7 +78896,7 @@ static int balance_nonroot( memset(&b.szCell[b.nCell], 0, sizeof(b.szCell[0])*(limit+pOld->nOverflow)); if( pOld->nOverflow>0 ){ if( NEVER(limitaiOvfl[0]) ){ - rc = SQLITE_CORRUPT_BKPT; + rc = SQLITE_CORRUPT_PAGE(pOld); goto balance_cleanup; } limit = pOld->aiOvfl[0]; @@ -78457,7 +79539,7 @@ static int anotherValidCursor(BtCursor *pCur){ && pOther->eState==CURSOR_VALID && pOther->pPage==pCur->pPage ){ - return SQLITE_CORRUPT_BKPT; + return SQLITE_CORRUPT_PAGE(pCur->pPage); } } return SQLITE_OK; @@ -78517,7 +79599,7 @@ static int balance(BtCursor *pCur){ /* The page being written is not a root page, and there is currently ** more than one reference to it. This only happens if the page is one ** of its own ancestor pages. Corruption. */ - rc = SQLITE_CORRUPT_BKPT; + rc = SQLITE_CORRUPT_PAGE(pPage); }else{ MemPage * const pParent = pCur->apPage[iPage-1]; int const iIdx = pCur->aiIdx[iPage-1]; @@ -78681,7 +79763,7 @@ static SQLITE_NOINLINE int btreeOverwriteOverflowCell( rc = btreeGetPage(pBt, ovflPgno, &pPage, 0); if( rc ) return rc; if( sqlite3PagerPageRefcount(pPage->pDbPage)!=1 || pPage->isInit ){ - rc = SQLITE_CORRUPT_BKPT; + rc = SQLITE_CORRUPT_PAGE(pPage); }else{ if( iOffset+ovflPageSize<(u32)nTotal ){ ovflPgno = get4byte(pPage->aData); @@ -78709,7 +79791,7 @@ static int btreeOverwriteCell(BtCursor *pCur, const BtreePayload *pX){ if( pCur->info.pPayload + pCur->info.nLocal > pPage->aDataEnd || pCur->info.pPayload < pPage->aData + pPage->cellOffset ){ - return SQLITE_CORRUPT_BKPT; + return SQLITE_CORRUPT_PAGE(pPage); } if( pCur->info.nLocal==nTotal ){ /* The entire cell is local */ @@ -78790,7 +79872,7 @@ SQLITE_PRIVATE int sqlite3BtreeInsert( ** Which can only happen if the SQLITE_NoSchemaError flag was set when ** the schema was loaded. This cannot be asserted though, as a user might ** set the flag, load the schema, and then unset the flag. */ - return SQLITE_CORRUPT_BKPT; + return SQLITE_CORRUPT_PGNO(pCur->pgnoRoot); } } @@ -78913,7 +79995,7 @@ SQLITE_PRIVATE int sqlite3BtreeInsert( if( pPage->nFree<0 ){ if( NEVER(pCur->eState>CURSOR_INVALID) ){ /* ^^^^^--- due to the moveToRoot() call above */ - rc = SQLITE_CORRUPT_BKPT; + rc = SQLITE_CORRUPT_PAGE(pPage); }else{ rc = btreeComputeFreeSpace(pPage); } @@ -78930,7 +80012,10 @@ SQLITE_PRIVATE int sqlite3BtreeInsert( if( flags & BTREE_PREFORMAT ){ rc = SQLITE_OK; szNew = p->pBt->nPreformatSize; - if( szNew<4 ) szNew = 4; + if( szNew<4 ){ + szNew = 4; + newCell[3] = 0; + } if( ISAUTOVACUUM(p->pBt) && szNew>pPage->maxLocal ){ CellInfo info; pPage->xParseCell(pPage, newCell, &info); @@ -78952,7 +80037,7 @@ SQLITE_PRIVATE int sqlite3BtreeInsert( CellInfo info; assert( idx>=0 ); if( idx>=pPage->nCell ){ - return SQLITE_CORRUPT_BKPT; + return SQLITE_CORRUPT_PAGE(pPage); } rc = sqlite3PagerWrite(pPage->pDbPage); if( rc ){ @@ -78979,10 +80064,10 @@ SQLITE_PRIVATE int sqlite3BtreeInsert( ** necessary to add the PTRMAP_OVERFLOW1 pointer-map entry. */ assert( rc==SQLITE_OK ); /* clearCell never fails when nLocal==nPayload */ if( oldCell < pPage->aData+pPage->hdrOffset+10 ){ - return SQLITE_CORRUPT_BKPT; + return SQLITE_CORRUPT_PAGE(pPage); } if( oldCell+szNew > pPage->aDataEnd ){ - return SQLITE_CORRUPT_BKPT; + return SQLITE_CORRUPT_PAGE(pPage); } memcpy(oldCell, newCell, szNew); return SQLITE_OK; @@ -78992,7 +80077,7 @@ SQLITE_PRIVATE int sqlite3BtreeInsert( }else if( loc<0 && pPage->nCell>0 ){ assert( pPage->leaf ); idx = ++pCur->ix; - pCur->curFlags &= ~BTCF_ValidNKey; + pCur->curFlags &= ~(BTCF_ValidNKey|BTCF_ValidOvfl); }else{ assert( pPage->leaf ); } @@ -79022,7 +80107,7 @@ SQLITE_PRIVATE int sqlite3BtreeInsert( */ if( pPage->nOverflow ){ assert( rc==SQLITE_OK ); - pCur->curFlags &= ~(BTCF_ValidNKey); + pCur->curFlags &= ~(BTCF_ValidNKey|BTCF_ValidOvfl); rc = balance(pCur); /* Must make sure nOverflow is reset to zero even if the balance() @@ -79084,7 +80169,7 @@ SQLITE_PRIVATE int sqlite3BtreeTransferRow(BtCursor *pDest, BtCursor *pSrc, i64 nIn = pSrc->info.nLocal; aIn = pSrc->info.pPayload; if( aIn+nIn>pSrc->pPage->aDataEnd ){ - return SQLITE_CORRUPT_BKPT; + return SQLITE_CORRUPT_PAGE(pSrc->pPage); } nRem = pSrc->info.nPayload; if( nIn==nRem && nInpPage->maxLocal ){ @@ -79109,7 +80194,7 @@ SQLITE_PRIVATE int sqlite3BtreeTransferRow(BtCursor *pDest, BtCursor *pSrc, i64 if( nRem>nIn ){ if( aIn+nIn+4>pSrc->pPage->aDataEnd ){ - return SQLITE_CORRUPT_BKPT; + return SQLITE_CORRUPT_PAGE(pSrc->pPage); } ovflIn = get4byte(&pSrc->info.pPayload[nIn]); } @@ -79205,7 +80290,7 @@ SQLITE_PRIVATE int sqlite3BtreeDelete(BtCursor *pCur, u8 flags){ assert( rc!=SQLITE_OK || CORRUPT_DB || pCur->eState==CURSOR_VALID ); if( rc || pCur->eState!=CURSOR_VALID ) return rc; }else{ - return SQLITE_CORRUPT_BKPT; + return SQLITE_CORRUPT_PGNO(pCur->pgnoRoot); } } assert( pCur->eState==CURSOR_VALID ); @@ -79214,14 +80299,14 @@ SQLITE_PRIVATE int sqlite3BtreeDelete(BtCursor *pCur, u8 flags){ iCellIdx = pCur->ix; pPage = pCur->pPage; if( pPage->nCell<=iCellIdx ){ - return SQLITE_CORRUPT_BKPT; + return SQLITE_CORRUPT_PAGE(pPage); } pCell = findCell(pPage, iCellIdx); if( pPage->nFree<0 && btreeComputeFreeSpace(pPage) ){ - return SQLITE_CORRUPT_BKPT; + return SQLITE_CORRUPT_PAGE(pPage); } if( pCell<&pPage->aCellIdx[pPage->nCell] ){ - return SQLITE_CORRUPT_BKPT; + return SQLITE_CORRUPT_PAGE(pPage); } /* If the BTREE_SAVEPOSITION bit is on, then the cursor position must @@ -79312,7 +80397,7 @@ SQLITE_PRIVATE int sqlite3BtreeDelete(BtCursor *pCur, u8 flags){ n = pCur->pPage->pgno; } pCell = findCell(pLeaf, pLeaf->nCell-1); - if( pCell<&pLeaf->aData[4] ) return SQLITE_CORRUPT_BKPT; + if( pCell<&pLeaf->aData[4] ) return SQLITE_CORRUPT_PAGE(pLeaf); nCell = pLeaf->xCellSize(pLeaf, pCell); assert( MX_CELL_SIZE(pBt) >= nCell ); pTmp = pBt->pTmpSpace; @@ -79428,7 +80513,7 @@ static int btreeCreateTable(Btree *p, Pgno *piTable, int createTabFlags){ */ sqlite3BtreeGetMeta(p, BTREE_LARGEST_ROOT_PAGE, &pgnoRoot); if( pgnoRoot>btreePagecount(pBt) ){ - return SQLITE_CORRUPT_BKPT; + return SQLITE_CORRUPT_PGNO(pgnoRoot); } pgnoRoot++; @@ -79476,7 +80561,7 @@ static int btreeCreateTable(Btree *p, Pgno *piTable, int createTabFlags){ } rc = ptrmapGet(pBt, pgnoRoot, &eType, &iPtrPage); if( eType==PTRMAP_ROOTPAGE || eType==PTRMAP_FREEPAGE ){ - rc = SQLITE_CORRUPT_BKPT; + rc = SQLITE_CORRUPT_PGNO(pgnoRoot); } if( rc!=SQLITE_OK ){ releasePage(pRoot); @@ -79566,14 +80651,14 @@ static int clearDatabasePage( assert( sqlite3_mutex_held(pBt->mutex) ); if( pgno>btreePagecount(pBt) ){ - return SQLITE_CORRUPT_BKPT; + return SQLITE_CORRUPT_PGNO(pgno); } rc = getAndInitPage(pBt, pgno, &pPage, 0); if( rc ) return rc; if( (pBt->openFlags & BTREE_SINGLE)==0 && sqlite3PagerPageRefcount(pPage->pDbPage) != (1 + (pgno==1)) ){ - rc = SQLITE_CORRUPT_BKPT; + rc = SQLITE_CORRUPT_PAGE(pPage); goto cleardatabasepage_out; } hdr = pPage->hdrOffset; @@ -79677,7 +80762,7 @@ static int btreeDropTable(Btree *p, Pgno iTable, int *piMoved){ assert( p->inTrans==TRANS_WRITE ); assert( iTable>=2 ); if( iTable>btreePagecount(pBt) ){ - return SQLITE_CORRUPT_BKPT; + return SQLITE_CORRUPT_PGNO(iTable); } rc = sqlite3BtreeClearTable(p, iTable, 0); @@ -79989,7 +81074,8 @@ static void checkAppendMsg( ** corresponds to page iPg is already set. */ static int getPageReferenced(IntegrityCk *pCheck, Pgno iPg){ - assert( iPg<=pCheck->nPage && sizeof(pCheck->aPgRef[0])==1 ); + assert( pCheck->aPgRef!=0 ); + assert( iPg<=pCheck->nCkPage && sizeof(pCheck->aPgRef[0])==1 ); return (pCheck->aPgRef[iPg/8] & (1 << (iPg & 0x07))); } @@ -79997,7 +81083,8 @@ static int getPageReferenced(IntegrityCk *pCheck, Pgno iPg){ ** Set the bit in the IntegrityCk.aPgRef[] array that corresponds to page iPg. */ static void setPageReferenced(IntegrityCk *pCheck, Pgno iPg){ - assert( iPg<=pCheck->nPage && sizeof(pCheck->aPgRef[0])==1 ); + assert( pCheck->aPgRef!=0 ); + assert( iPg<=pCheck->nCkPage && sizeof(pCheck->aPgRef[0])==1 ); pCheck->aPgRef[iPg/8] |= (1 << (iPg & 0x07)); } @@ -80011,7 +81098,7 @@ static void setPageReferenced(IntegrityCk *pCheck, Pgno iPg){ ** Also check that the page number is in bounds. */ static int checkRef(IntegrityCk *pCheck, Pgno iPage){ - if( iPage>pCheck->nPage || iPage==0 ){ + if( iPage>pCheck->nCkPage || iPage==0 ){ checkAppendMsg(pCheck, "invalid page number %u", iPage); return 1; } @@ -80238,6 +81325,7 @@ static int checkTreePage( if( (rc = btreeGetPage(pBt, iPage, &pPage, 0))!=0 ){ checkAppendMsg(pCheck, "unable to get the page. error code=%d", rc); + if( rc==SQLITE_IOERR_NOMEM ) pCheck->rc = SQLITE_NOMEM; goto end_of_check; } @@ -80268,6 +81356,9 @@ static int checkTreePage( ** number of cells on the page. */ nCell = get2byte(&data[hdr+3]); assert( pPage->nCell==nCell ); + if( pPage->leaf || pPage->intKey==0 ){ + pCheck->nRow += nCell; + } /* EVIDENCE-OF: R-23882-45353 The cell pointer array of a b-tree page ** immediately follows the b-tree page header. */ @@ -80379,6 +81470,7 @@ static int checkTreePage( btreeHeapInsert(heap, (pc<<16)|(pc+size-1)); } } + assert( heap!=0 ); /* Add the freeblocks to the min-heap ** ** EVIDENCE-OF: R-20690-50594 The second field of the b-tree page header @@ -80478,6 +81570,7 @@ SQLITE_PRIVATE int sqlite3BtreeIntegrityCheck( sqlite3 *db, /* Database connection that is running the check */ Btree *p, /* The btree to be checked */ Pgno *aRoot, /* An array of root pages numbers for individual trees */ + Mem *aCnt, /* Memory cells to write counts for each tree to */ int nRoot, /* Number of entries in aRoot[] */ int mxErr, /* Stop reporting errors after this many */ int *pnErr, /* OUT: Write number of errors seen to this variable */ @@ -80491,7 +81584,9 @@ SQLITE_PRIVATE int sqlite3BtreeIntegrityCheck( int bPartial = 0; /* True if not checking all btrees */ int bCkFreelist = 1; /* True to scan the freelist */ VVA_ONLY( int nRef ); + assert( nRoot>0 ); + assert( aCnt!=0 ); /* aRoot[0]==0 means this is a partial check */ if( aRoot[0]==0 ){ @@ -80508,15 +81603,15 @@ SQLITE_PRIVATE int sqlite3BtreeIntegrityCheck( sCheck.db = db; sCheck.pBt = pBt; sCheck.pPager = pBt->pPager; - sCheck.nPage = btreePagecount(sCheck.pBt); + sCheck.nCkPage = btreePagecount(sCheck.pBt); sCheck.mxErr = mxErr; sqlite3StrAccumInit(&sCheck.errMsg, 0, zErr, sizeof(zErr), SQLITE_MAX_LENGTH); sCheck.errMsg.printfFlags = SQLITE_PRINTF_INTERNAL; - if( sCheck.nPage==0 ){ + if( sCheck.nCkPage==0 ){ goto integrity_ck_cleanup; } - sCheck.aPgRef = sqlite3MallocZero((sCheck.nPage / 8)+ 1); + sCheck.aPgRef = sqlite3MallocZero((sCheck.nCkPage / 8)+ 1); if( !sCheck.aPgRef ){ checkOom(&sCheck); goto integrity_ck_cleanup; @@ -80528,7 +81623,7 @@ SQLITE_PRIVATE int sqlite3BtreeIntegrityCheck( } i = PENDING_BYTE_PAGE(pBt); - if( i<=sCheck.nPage ) setPageReferenced(&sCheck, i); + if( i<=sCheck.nCkPage ) setPageReferenced(&sCheck, i); /* Check the integrity of the freelist */ @@ -80564,22 +81659,25 @@ SQLITE_PRIVATE int sqlite3BtreeIntegrityCheck( testcase( pBt->db->flags & SQLITE_CellSizeCk ); pBt->db->flags &= ~(u64)SQLITE_CellSizeCk; for(i=0; (int)iautoVacuum && aRoot[i]>1 && !bPartial ){ - checkPtrmap(&sCheck, aRoot[i], PTRMAP_ROOTPAGE, 0); - } + if( pBt->autoVacuum && aRoot[i]>1 && !bPartial ){ + checkPtrmap(&sCheck, aRoot[i], PTRMAP_ROOTPAGE, 0); + } #endif - sCheck.v0 = aRoot[i]; - checkTreePage(&sCheck, aRoot[i], ¬Used, LARGEST_INT64); + sCheck.v0 = aRoot[i]; + checkTreePage(&sCheck, aRoot[i], ¬Used, LARGEST_INT64); + } + sqlite3MemSetArrayInt64(aCnt, i, sCheck.nRow); } pBt->db->flags = savedDbFlags; /* Make sure every page in the file is referenced */ if( !bPartial ){ - for(i=1; i<=sCheck.nPage && sCheck.mxErr; i++){ + for(i=1; i<=sCheck.nCkPage && sCheck.mxErr; i++){ #ifdef SQLITE_OMIT_AUTOVACUUM if( getPageReferenced(&sCheck, i)==0 ){ checkAppendMsg(&sCheck, "Page %u: never used", i); @@ -82020,7 +83118,7 @@ SQLITE_PRIVATE void sqlite3VdbeMemZeroTerminateIfAble(Mem *pMem){ pMem->flags |= MEM_Term; return; } - if( pMem->xDel==(void(*)(void*))sqlite3RCStrUnref ){ + if( pMem->xDel==sqlite3RCStrUnref ){ /* Blindly assume that all RCStr objects are zero-terminated */ pMem->flags |= MEM_Term; return; @@ -82627,6 +83725,13 @@ SQLITE_PRIVATE void sqlite3VdbeMemSetInt64(Mem *pMem, i64 val){ } } +/* +** Set the iIdx'th entry of array aMem[] to contain integer value val. +*/ +SQLITE_PRIVATE void sqlite3MemSetArrayInt64(sqlite3_value *aMem, int iIdx, i64 val){ + sqlite3VdbeMemSetInt64(&aMem[iIdx], val); +} + /* A no-op destructor */ SQLITE_PRIVATE void sqlite3NoopDestructor(void *p){ UNUSED_PARAMETER(p); } @@ -83199,7 +84304,7 @@ static int valueFromFunction( #endif assert( pFunc ); if( (pFunc->funcFlags & (SQLITE_FUNC_CONSTANT|SQLITE_FUNC_SLOCHNG))==0 - || (pFunc->funcFlags & SQLITE_FUNC_NEEDCOLL) + || (pFunc->funcFlags & (SQLITE_FUNC_NEEDCOLL|SQLITE_FUNC_RUNONLY))!=0 ){ return SQLITE_OK; } @@ -83315,14 +84420,20 @@ static int valueFromExpr( } /* Handle negative integers in a single step. This is needed in the - ** case when the value is -9223372036854775808. - */ - if( op==TK_UMINUS - && (pExpr->pLeft->op==TK_INTEGER || pExpr->pLeft->op==TK_FLOAT) ){ - pExpr = pExpr->pLeft; - op = pExpr->op; - negInt = -1; - zNeg = "-"; + ** case when the value is -9223372036854775808. Except - do not do this + ** for hexadecimal literals. */ + if( op==TK_UMINUS ){ + Expr *pLeft = pExpr->pLeft; + if( (pLeft->op==TK_INTEGER || pLeft->op==TK_FLOAT) ){ + if( ExprHasProperty(pLeft, EP_IntValue) + || pLeft->u.zToken[0]!='0' || (pLeft->u.zToken[1] & ~0x20)!='X' + ){ + pExpr = pLeft; + op = pExpr->op; + negInt = -1; + zNeg = "-"; + } + } } if( op==TK_STRING || op==TK_FLOAT || op==TK_INTEGER ){ @@ -83331,12 +84442,26 @@ static int valueFromExpr( if( ExprHasProperty(pExpr, EP_IntValue) ){ sqlite3VdbeMemSetInt64(pVal, (i64)pExpr->u.iValue*negInt); }else{ - zVal = sqlite3MPrintf(db, "%s%s", zNeg, pExpr->u.zToken); - if( zVal==0 ) goto no_mem; - sqlite3ValueSetStr(pVal, -1, zVal, SQLITE_UTF8, SQLITE_DYNAMIC); + i64 iVal; + if( op==TK_INTEGER && 0==sqlite3DecOrHexToI64(pExpr->u.zToken, &iVal) ){ + sqlite3VdbeMemSetInt64(pVal, iVal*negInt); + }else{ + zVal = sqlite3MPrintf(db, "%s%s", zNeg, pExpr->u.zToken); + if( zVal==0 ) goto no_mem; + sqlite3ValueSetStr(pVal, -1, zVal, SQLITE_UTF8, SQLITE_DYNAMIC); + } } - if( (op==TK_INTEGER || op==TK_FLOAT ) && affinity==SQLITE_AFF_BLOB ){ - sqlite3ValueApplyAffinity(pVal, SQLITE_AFF_NUMERIC, SQLITE_UTF8); + if( affinity==SQLITE_AFF_BLOB ){ + if( op==TK_FLOAT ){ + assert( pVal && pVal->z && pVal->flags==(MEM_Str|MEM_Term) ); + sqlite3AtoF(pVal->z, &pVal->u.r, pVal->n, SQLITE_UTF8); + pVal->flags = MEM_Real; + }else if( op==TK_INTEGER ){ + /* This case is required by -9223372036854775808 and other strings + ** that look like integers but cannot be handled by the + ** sqlite3DecOrHexToI64() call above. */ + sqlite3ValueApplyAffinity(pVal, SQLITE_AFF_NUMERIC, SQLITE_UTF8); + } }else{ sqlite3ValueApplyAffinity(pVal, affinity, SQLITE_UTF8); } @@ -83400,6 +84525,7 @@ static int valueFromExpr( if( pVal ){ pVal->flags = MEM_Int; pVal->u.i = pExpr->u.zToken[4]==0; + sqlite3ValueApplyAffinity(pVal, affinity, enc); } } @@ -83605,17 +84731,17 @@ SQLITE_PRIVATE int sqlite3Stat4Column( sqlite3_value **ppVal /* OUT: Extracted value */ ){ u32 t = 0; /* a column type code */ - int nHdr; /* Size of the header in the record */ - int iHdr; /* Next unread header byte */ - int iField; /* Next unread data byte */ - int szField = 0; /* Size of the current data field */ + u32 nHdr; /* Size of the header in the record */ + u32 iHdr; /* Next unread header byte */ + i64 iField; /* Next unread data byte */ + u32 szField = 0; /* Size of the current data field */ int i; /* Column index */ u8 *a = (u8*)pRec; /* Typecast byte array */ Mem *pMem = *ppVal; /* Write result into this Mem object */ assert( iCol>0 ); iHdr = getVarint32(a, nHdr); - if( nHdr>nRec || iHdr>=nHdr ) return SQLITE_CORRUPT_BKPT; + if( nHdr>(u32)nRec || iHdr>=nHdr ) return SQLITE_CORRUPT_BKPT; iField = nHdr; for(i=0; i<=iCol; i++){ iHdr += getVarint32(&a[iHdr], t); @@ -83922,10 +85048,11 @@ static int growOpArray(Vdbe *v, int nOp){ ** sqlite3CantopenError(lineno) */ static void test_addop_breakpoint(int pc, Op *pOp){ - static int n = 0; + static u64 n = 0; (void)pc; (void)pOp; n++; + if( n==LARGEST_UINT64 ) abort(); /* so that n is used, preventing a warning */ } #endif @@ -84649,6 +85776,15 @@ static void resolveP2Values(Vdbe *p, int *pMaxFuncArgs){ assert( aLabel!=0 ); /* True because of tag-20230419-1 */ pOp->p2 = aLabel[ADDR(pOp->p2)]; } + + /* OPFLG_JUMP opcodes never have P2==0, though OPFLG_JUMP0 opcodes + ** might */ + assert( pOp->p2>0 + || (sqlite3OpcodeProperty[pOp->opcode] & OPFLG_JUMP0)!=0 ); + + /* Jumps never go off the end of the bytecode array */ + assert( pOp->p2nOp + || (sqlite3OpcodeProperty[pOp->opcode] & OPFLG_JUMP)==0 ); break; } } @@ -84713,6 +85849,10 @@ SQLITE_PRIVATE void sqlite3VdbeNoJumpsOutsideSubrtn( int iDest = pOp->p2; /* Jump destination */ if( iDest==0 ) continue; if( pOp->opcode==OP_Gosub ) continue; + if( pOp->p3==20230325 && pOp->opcode==OP_NotNull ){ + /* This is a deliberately taken illegal branch. tag-20230325-2 */ + continue; + } if( iDest<0 ){ int j = ADDR(iDest); assert( j>=0 ); @@ -85106,6 +86246,10 @@ static void freeP4(sqlite3 *db, int p4type, void *p4){ if( db->pnBytesFreed==0 ) sqlite3VtabUnlock((VTable *)p4); break; } + case P4_TABLEREF: { + if( db->pnBytesFreed==0 ) sqlite3DeleteTable(db, (Table*)p4); + break; + } } } @@ -85233,7 +86377,7 @@ static void SQLITE_NOINLINE vdbeChangeP4Full( int n ){ if( pOp->p4type ){ - freeP4(p->db, pOp->p4type, pOp->p4.p); + assert( pOp->p4type > P4_FREE_IF_LE ); pOp->p4type = 0; pOp->p4.p = 0; } @@ -87048,7 +88192,7 @@ SQLITE_PRIVATE int sqlite3VdbeHalt(Vdbe *p){ /* Check for immediate foreign key violations. */ if( p->rc==SQLITE_OK || (p->errorAction==OE_Fail && !isSpecialError) ){ - sqlite3VdbeCheckFk(p, 0); + (void)sqlite3VdbeCheckFk(p, 0); } /* If the auto-commit flag is set and this is the only active writer @@ -87762,6 +88906,23 @@ static void serialGet( pMem->flags = IsNaN(x) ? MEM_Null : MEM_Real; } } +static int serialGet7( + const unsigned char *buf, /* Buffer to deserialize from */ + Mem *pMem /* Memory cell to write value into */ +){ + u64 x = FOUR_BYTE_UINT(buf); + u32 y = FOUR_BYTE_UINT(buf+4); + x = (x<<32) + y; + assert( sizeof(x)==8 && sizeof(pMem->u.r)==8 ); + swapMixedEndianFloat(x); + memcpy(&pMem->u.r, &x, sizeof(x)); + if( IsNaN(x) ){ + pMem->flags = MEM_Null; + return 1; + } + pMem->flags = MEM_Real; + return 0; +} SQLITE_PRIVATE void sqlite3VdbeSerialGet( const unsigned char *buf, /* Buffer to deserialize from */ u32 serial_type, /* Serial type to deserialize */ @@ -88172,32 +89333,44 @@ SQLITE_PRIVATE SQLITE_NOINLINE int sqlite3BlobCompare(const Mem *pB1, const Mem return n1 - n2; } +/* The following two functions are used only within testcase() to prove +** test coverage. These functions do no exist for production builds. +** We must use separate SQLITE_NOINLINE functions here, since otherwise +** optimizer code movement causes gcov to become very confused. +*/ +#if defined(SQLITE_COVERAGE_TEST) || defined(SQLITE_DEBUG) +static int SQLITE_NOINLINE doubleLt(double a, double b){ return a8 ){ + if( sqlite3IsNaN(r) ){ + /* SQLite considers NaN to be a NULL. And all integer values are greater + ** than NULL */ + return 1; + } + if( sqlite3Config.bUseLongDouble ){ LONGDOUBLE_TYPE x = (LONGDOUBLE_TYPE)i; testcase( xr ); testcase( x==r ); - if( xr ) return +1; /*NO_TEST*/ /* work around bugs in gcov */ - return 0; /*NO_TEST*/ /* work around bugs in gcov */ + return (xr); }else{ i64 y; - double s; if( r<-9223372036854775808.0 ) return +1; if( r>=9223372036854775808.0 ) return -1; y = (i64)r; if( iy ) return +1; - s = (double)i; - if( sr ) return +1; - return 0; + testcase( doubleLt(((double)i),r) ); + testcase( doubleLt(r,((double)i)) ); + testcase( doubleEq(r,((double)i)) ); + return (((double)i)r); } } @@ -88427,7 +89600,7 @@ SQLITE_PRIVATE int sqlite3VdbeRecordCompareWithSkip( }else if( serial_type==0 ){ rc = -1; }else if( serial_type==7 ){ - sqlite3VdbeSerialGet(&aKey1[d1], serial_type, &mem1); + serialGet7(&aKey1[d1], &mem1); rc = -sqlite3IntFloatCompare(pRhs->u.i, mem1.u.r); }else{ i64 lhs = vdbeRecordDecodeInt(serial_type, &aKey1[d1]); @@ -88452,14 +89625,18 @@ SQLITE_PRIVATE int sqlite3VdbeRecordCompareWithSkip( }else if( serial_type==0 ){ rc = -1; }else{ - sqlite3VdbeSerialGet(&aKey1[d1], serial_type, &mem1); if( serial_type==7 ){ - if( mem1.u.ru.r ){ + if( serialGet7(&aKey1[d1], &mem1) ){ + rc = -1; /* mem1 is a NaN */ + }else if( mem1.u.ru.r ){ rc = -1; }else if( mem1.u.r>pRhs->u.r ){ rc = +1; + }else{ + assert( rc==0 ); } }else{ + sqlite3VdbeSerialGet(&aKey1[d1], serial_type, &mem1); rc = sqlite3IntFloatCompare(mem1.u.i, pRhs->u.r); } } @@ -88529,7 +89706,14 @@ SQLITE_PRIVATE int sqlite3VdbeRecordCompareWithSkip( /* RHS is null */ else{ serial_type = aKey1[idx1]; - rc = (serial_type!=0 && serial_type!=10); + if( serial_type==0 + || serial_type==10 + || (serial_type==7 && serialGet7(&aKey1[d1], &mem1)!=0) + ){ + assert( rc==0 ); + }else{ + rc = 1; + } } if( rc!=0 ){ @@ -89342,7 +90526,15 @@ SQLITE_API int sqlite3_clear_bindings(sqlite3_stmt *pStmt){ int rc = SQLITE_OK; Vdbe *p = (Vdbe*)pStmt; #if SQLITE_THREADSAFE - sqlite3_mutex *mutex = ((Vdbe*)pStmt)->db->mutex; + sqlite3_mutex *mutex; +#endif +#ifdef SQLITE_ENABLE_API_ARMOR + if( pStmt==0 ){ + return SQLITE_MISUSE_BKPT; + } +#endif +#if SQLITE_THREADSAFE + mutex = p->db->mutex; #endif sqlite3_mutex_enter(mutex); for(i=0; inVar; i++){ @@ -89565,7 +90757,7 @@ SQLITE_API void sqlite3_value_free(sqlite3_value *pOld){ ** is too big or if an OOM occurs. ** ** The invokeValueDestructor(P,X) routine invokes destructor function X() -** on value P is not going to be used and need to be destroyed. +** on value P if P is not going to be used and need to be destroyed. */ static void setResultStrOrError( sqlite3_context *pCtx, /* Function context */ @@ -89595,7 +90787,7 @@ static void setResultStrOrError( static int invokeValueDestructor( const void *p, /* Value to destroy */ void (*xDel)(void*), /* The destructor */ - sqlite3_context *pCtx /* Set a SQLITE_TOOBIG error if no NULL */ + sqlite3_context *pCtx /* Set a SQLITE_TOOBIG error if not NULL */ ){ assert( xDel!=SQLITE_DYNAMIC ); if( xDel==0 ){ @@ -89605,7 +90797,14 @@ static int invokeValueDestructor( }else{ xDel((void*)p); } +#ifdef SQLITE_ENABLE_API_ARMOR + if( pCtx!=0 ){ + sqlite3_result_error_toobig(pCtx); + } +#else + assert( pCtx!=0 ); sqlite3_result_error_toobig(pCtx); +#endif return SQLITE_TOOBIG; } SQLITE_API void sqlite3_result_blob( @@ -89614,6 +90813,12 @@ SQLITE_API void sqlite3_result_blob( int n, void (*xDel)(void *) ){ +#ifdef SQLITE_ENABLE_API_ARMOR + if( pCtx==0 || n<0 ){ + invokeValueDestructor(z, xDel, pCtx); + return; + } +#endif assert( n>=0 ); assert( sqlite3_mutex_held(pCtx->pOut->db->mutex) ); setResultStrOrError(pCtx, z, n, 0, xDel); @@ -89624,8 +90829,14 @@ SQLITE_API void sqlite3_result_blob64( sqlite3_uint64 n, void (*xDel)(void *) ){ - assert( sqlite3_mutex_held(pCtx->pOut->db->mutex) ); assert( xDel!=SQLITE_DYNAMIC ); +#ifdef SQLITE_ENABLE_API_ARMOR + if( pCtx==0 ){ + invokeValueDestructor(z, xDel, 0); + return; + } +#endif + assert( sqlite3_mutex_held(pCtx->pOut->db->mutex) ); if( n>0x7fffffff ){ (void)invokeValueDestructor(z, xDel, pCtx); }else{ @@ -89633,30 +90844,48 @@ SQLITE_API void sqlite3_result_blob64( } } SQLITE_API void sqlite3_result_double(sqlite3_context *pCtx, double rVal){ +#ifdef SQLITE_ENABLE_API_ARMOR + if( pCtx==0 ) return; +#endif assert( sqlite3_mutex_held(pCtx->pOut->db->mutex) ); sqlite3VdbeMemSetDouble(pCtx->pOut, rVal); } SQLITE_API void sqlite3_result_error(sqlite3_context *pCtx, const char *z, int n){ +#ifdef SQLITE_ENABLE_API_ARMOR + if( pCtx==0 ) return; +#endif assert( sqlite3_mutex_held(pCtx->pOut->db->mutex) ); pCtx->isError = SQLITE_ERROR; sqlite3VdbeMemSetStr(pCtx->pOut, z, n, SQLITE_UTF8, SQLITE_TRANSIENT); } #ifndef SQLITE_OMIT_UTF16 SQLITE_API void sqlite3_result_error16(sqlite3_context *pCtx, const void *z, int n){ +#ifdef SQLITE_ENABLE_API_ARMOR + if( pCtx==0 ) return; +#endif assert( sqlite3_mutex_held(pCtx->pOut->db->mutex) ); pCtx->isError = SQLITE_ERROR; sqlite3VdbeMemSetStr(pCtx->pOut, z, n, SQLITE_UTF16NATIVE, SQLITE_TRANSIENT); } #endif SQLITE_API void sqlite3_result_int(sqlite3_context *pCtx, int iVal){ +#ifdef SQLITE_ENABLE_API_ARMOR + if( pCtx==0 ) return; +#endif assert( sqlite3_mutex_held(pCtx->pOut->db->mutex) ); sqlite3VdbeMemSetInt64(pCtx->pOut, (i64)iVal); } SQLITE_API void sqlite3_result_int64(sqlite3_context *pCtx, i64 iVal){ +#ifdef SQLITE_ENABLE_API_ARMOR + if( pCtx==0 ) return; +#endif assert( sqlite3_mutex_held(pCtx->pOut->db->mutex) ); sqlite3VdbeMemSetInt64(pCtx->pOut, iVal); } SQLITE_API void sqlite3_result_null(sqlite3_context *pCtx){ +#ifdef SQLITE_ENABLE_API_ARMOR + if( pCtx==0 ) return; +#endif assert( sqlite3_mutex_held(pCtx->pOut->db->mutex) ); sqlite3VdbeMemSetNull(pCtx->pOut); } @@ -89666,14 +90895,37 @@ SQLITE_API void sqlite3_result_pointer( const char *zPType, void (*xDestructor)(void*) ){ - Mem *pOut = pCtx->pOut; + Mem *pOut; +#ifdef SQLITE_ENABLE_API_ARMOR + if( pCtx==0 ){ + invokeValueDestructor(pPtr, xDestructor, 0); + return; + } +#endif + pOut = pCtx->pOut; assert( sqlite3_mutex_held(pOut->db->mutex) ); sqlite3VdbeMemRelease(pOut); pOut->flags = MEM_Null; sqlite3VdbeMemSetPointer(pOut, pPtr, zPType, xDestructor); } SQLITE_API void sqlite3_result_subtype(sqlite3_context *pCtx, unsigned int eSubtype){ - Mem *pOut = pCtx->pOut; + Mem *pOut; +#ifdef SQLITE_ENABLE_API_ARMOR + if( pCtx==0 ) return; +#endif +#if defined(SQLITE_STRICT_SUBTYPE) && SQLITE_STRICT_SUBTYPE+0!=0 + if( pCtx->pFunc!=0 + && (pCtx->pFunc->funcFlags & SQLITE_RESULT_SUBTYPE)==0 + ){ + char zErr[200]; + sqlite3_snprintf(sizeof(zErr), zErr, + "misuse of sqlite3_result_subtype() by %s()", + pCtx->pFunc->zName); + sqlite3_result_error(pCtx, zErr, -1); + return; + } +#endif /* SQLITE_STRICT_SUBTYPE */ + pOut = pCtx->pOut; assert( sqlite3_mutex_held(pOut->db->mutex) ); pOut->eSubtype = eSubtype & 0xff; pOut->flags |= MEM_Subtype; @@ -89684,6 +90936,12 @@ SQLITE_API void sqlite3_result_text( int n, void (*xDel)(void *) ){ +#ifdef SQLITE_ENABLE_API_ARMOR + if( pCtx==0 ){ + invokeValueDestructor(z, xDel, 0); + return; + } +#endif assert( sqlite3_mutex_held(pCtx->pOut->db->mutex) ); setResultStrOrError(pCtx, z, n, SQLITE_UTF8, xDel); } @@ -89694,6 +90952,12 @@ SQLITE_API void sqlite3_result_text64( void (*xDel)(void *), unsigned char enc ){ +#ifdef SQLITE_ENABLE_API_ARMOR + if( pCtx==0 ){ + invokeValueDestructor(z, xDel, 0); + return; + } +#endif assert( sqlite3_mutex_held(pCtx->pOut->db->mutex) ); assert( xDel!=SQLITE_DYNAMIC ); if( enc!=SQLITE_UTF8 ){ @@ -89737,7 +91001,16 @@ SQLITE_API void sqlite3_result_text16le( } #endif /* SQLITE_OMIT_UTF16 */ SQLITE_API void sqlite3_result_value(sqlite3_context *pCtx, sqlite3_value *pValue){ - Mem *pOut = pCtx->pOut; + Mem *pOut; + +#ifdef SQLITE_ENABLE_API_ARMOR + if( pCtx==0 ) return; + if( pValue==0 ){ + sqlite3_result_null(pCtx); + return; + } +#endif + pOut = pCtx->pOut; assert( sqlite3_mutex_held(pCtx->pOut->db->mutex) ); sqlite3VdbeMemCopy(pOut, pValue); sqlite3VdbeChangeEncoding(pOut, pCtx->enc); @@ -89749,7 +91022,12 @@ SQLITE_API void sqlite3_result_zeroblob(sqlite3_context *pCtx, int n){ sqlite3_result_zeroblob64(pCtx, n>0 ? n : 0); } SQLITE_API int sqlite3_result_zeroblob64(sqlite3_context *pCtx, u64 n){ - Mem *pOut = pCtx->pOut; + Mem *pOut; + +#ifdef SQLITE_ENABLE_API_ARMOR + if( pCtx==0 ) return SQLITE_MISUSE_BKPT; +#endif + pOut = pCtx->pOut; assert( sqlite3_mutex_held(pOut->db->mutex) ); if( n>(u64)pOut->db->aLimit[SQLITE_LIMIT_LENGTH] ){ sqlite3_result_error_toobig(pCtx); @@ -89763,6 +91041,9 @@ SQLITE_API int sqlite3_result_zeroblob64(sqlite3_context *pCtx, u64 n){ #endif } SQLITE_API void sqlite3_result_error_code(sqlite3_context *pCtx, int errCode){ +#ifdef SQLITE_ENABLE_API_ARMOR + if( pCtx==0 ) return; +#endif pCtx->isError = errCode ? errCode : -1; #ifdef SQLITE_DEBUG if( pCtx->pVdbe ) pCtx->pVdbe->rcApp = errCode; @@ -89775,6 +91056,9 @@ SQLITE_API void sqlite3_result_error_code(sqlite3_context *pCtx, int errCode){ /* Force an SQLITE_TOOBIG error. */ SQLITE_API void sqlite3_result_error_toobig(sqlite3_context *pCtx){ +#ifdef SQLITE_ENABLE_API_ARMOR + if( pCtx==0 ) return; +#endif assert( sqlite3_mutex_held(pCtx->pOut->db->mutex) ); pCtx->isError = SQLITE_TOOBIG; sqlite3VdbeMemSetStr(pCtx->pOut, "string or blob too big", -1, @@ -89783,6 +91067,9 @@ SQLITE_API void sqlite3_result_error_toobig(sqlite3_context *pCtx){ /* An SQLITE_NOMEM error. */ SQLITE_API void sqlite3_result_error_nomem(sqlite3_context *pCtx){ +#ifdef SQLITE_ENABLE_API_ARMOR + if( pCtx==0 ) return; +#endif assert( sqlite3_mutex_held(pCtx->pOut->db->mutex) ); sqlite3VdbeMemSetNull(pCtx->pOut); pCtx->isError = SQLITE_NOMEM_BKPT; @@ -90035,6 +91322,9 @@ SQLITE_API int sqlite3_step(sqlite3_stmt *pStmt){ ** pointer to it. */ SQLITE_API void *sqlite3_user_data(sqlite3_context *p){ +#ifdef SQLITE_ENABLE_API_ARMOR + if( p==0 ) return 0; +#endif assert( p && p->pFunc ); return p->pFunc->pUserData; } @@ -90050,7 +91340,11 @@ SQLITE_API void *sqlite3_user_data(sqlite3_context *p){ ** application defined function. */ SQLITE_API sqlite3 *sqlite3_context_db_handle(sqlite3_context *p){ +#ifdef SQLITE_ENABLE_API_ARMOR + if( p==0 ) return 0; +#else assert( p && p->pOut ); +#endif return p->pOut->db; } @@ -90069,7 +91363,11 @@ SQLITE_API sqlite3 *sqlite3_context_db_handle(sqlite3_context *p){ ** value, as a signal to the xUpdate routine that the column is unchanged. */ SQLITE_API int sqlite3_vtab_nochange(sqlite3_context *p){ +#ifdef SQLITE_ENABLE_API_ARMOR + if( p==0 ) return 0; +#else assert( p ); +#endif return sqlite3_value_nochange(p->pOut); } @@ -90097,7 +91395,7 @@ static int valueFromValueList( ValueList *pRhs; *ppOut = 0; - if( pVal==0 ) return SQLITE_MISUSE; + if( pVal==0 ) return SQLITE_MISUSE_BKPT; if( (pVal->flags & MEM_Dyn)==0 || pVal->xDel!=sqlite3VdbeValueListFree ){ return SQLITE_ERROR; }else{ @@ -90228,6 +91526,9 @@ SQLITE_API void *sqlite3_aggregate_context(sqlite3_context *p, int nByte){ SQLITE_API void *sqlite3_get_auxdata(sqlite3_context *pCtx, int iArg){ AuxData *pAuxData; +#ifdef SQLITE_ENABLE_API_ARMOR + if( pCtx==0 ) return 0; +#endif assert( sqlite3_mutex_held(pCtx->pOut->db->mutex) ); #if SQLITE_ENABLE_STAT4 if( pCtx->pVdbe==0 ) return 0; @@ -90260,8 +91561,12 @@ SQLITE_API void sqlite3_set_auxdata( void (*xDelete)(void*) ){ AuxData *pAuxData; - Vdbe *pVdbe = pCtx->pVdbe; + Vdbe *pVdbe; +#ifdef SQLITE_ENABLE_API_ARMOR + if( pCtx==0 ) return; +#endif + pVdbe= pCtx->pVdbe; assert( sqlite3_mutex_held(pCtx->pOut->db->mutex) ); #ifdef SQLITE_ENABLE_STAT4 if( pVdbe==0 ) goto failed; @@ -90698,7 +92003,7 @@ static int vdbeUnbind(Vdbe *p, unsigned int i){ } sqlite3_mutex_enter(p->db->mutex); if( p->eVdbeState!=VDBE_READY_STATE ){ - sqlite3Error(p->db, SQLITE_MISUSE); + sqlite3Error(p->db, SQLITE_MISUSE_BKPT); sqlite3_mutex_leave(p->db->mutex); sqlite3_log(SQLITE_MISUSE, "bind on a busy prepared statement: [%s]", p->zSql); @@ -90927,6 +92232,9 @@ SQLITE_API int sqlite3_bind_zeroblob(sqlite3_stmt *pStmt, int i, int n){ SQLITE_API int sqlite3_bind_zeroblob64(sqlite3_stmt *pStmt, int i, sqlite3_uint64 n){ int rc; Vdbe *p = (Vdbe *)pStmt; +#ifdef SQLITE_ENABLE_API_ARMOR + if( p==0 ) return SQLITE_MISUSE_BKPT; +#endif sqlite3_mutex_enter(p->db->mutex); if( n>(u64)p->db->aLimit[SQLITE_LIMIT_LENGTH] ){ rc = SQLITE_TOOBIG; @@ -91053,6 +92361,9 @@ SQLITE_API int sqlite3_stmt_isexplain(sqlite3_stmt *pStmt){ SQLITE_API int sqlite3_stmt_explain(sqlite3_stmt *pStmt, int eMode){ Vdbe *v = (Vdbe*)pStmt; int rc; +#ifdef SQLITE_ENABLE_API_ARMOR + if( pStmt==0 ) return SQLITE_MISUSE_BKPT; +#endif sqlite3_mutex_enter(v->db->mutex); if( ((int)v->explain)==eMode ){ rc = SQLITE_OK; @@ -91219,10 +92530,16 @@ static UnpackedRecord *vdbeUnpackRecord( ** a field of the row currently being updated or deleted. */ SQLITE_API int sqlite3_preupdate_old(sqlite3 *db, int iIdx, sqlite3_value **ppValue){ - PreUpdate *p = db->pPreUpdate; + PreUpdate *p; Mem *pMem; int rc = SQLITE_OK; +#ifdef SQLITE_ENABLE_API_ARMOR + if( db==0 || ppValue==0 ){ + return SQLITE_MISUSE_BKPT; + } +#endif + p = db->pPreUpdate; /* Test that this call is being made from within an SQLITE_DELETE or ** SQLITE_UPDATE pre-update callback, and that iIdx is within range. */ if( !p || p->op==SQLITE_INSERT ){ @@ -91283,7 +92600,12 @@ SQLITE_API int sqlite3_preupdate_old(sqlite3 *db, int iIdx, sqlite3_value **ppVa ** the number of columns in the row being updated, deleted or inserted. */ SQLITE_API int sqlite3_preupdate_count(sqlite3 *db){ - PreUpdate *p = db->pPreUpdate; + PreUpdate *p; +#ifdef SQLITE_ENABLE_API_ARMOR + p = db!=0 ? db->pPreUpdate : 0; +#else + p = db->pPreUpdate; +#endif return (p ? p->keyinfo.nKeyField : 0); } #endif /* SQLITE_ENABLE_PREUPDATE_HOOK */ @@ -91301,7 +92623,12 @@ SQLITE_API int sqlite3_preupdate_count(sqlite3 *db){ ** or SET DEFAULT action is considered a trigger. */ SQLITE_API int sqlite3_preupdate_depth(sqlite3 *db){ - PreUpdate *p = db->pPreUpdate; + PreUpdate *p; +#ifdef SQLITE_ENABLE_API_ARMOR + p = db!=0 ? db->pPreUpdate : 0; +#else + p = db->pPreUpdate; +#endif return (p ? p->v->nFrame : 0); } #endif /* SQLITE_ENABLE_PREUPDATE_HOOK */ @@ -91312,7 +92639,12 @@ SQLITE_API int sqlite3_preupdate_depth(sqlite3 *db){ ** only. */ SQLITE_API int sqlite3_preupdate_blobwrite(sqlite3 *db){ - PreUpdate *p = db->pPreUpdate; + PreUpdate *p; +#ifdef SQLITE_ENABLE_API_ARMOR + p = db!=0 ? db->pPreUpdate : 0; +#else + p = db->pPreUpdate; +#endif return (p ? p->iBlobWrite : -1); } #endif @@ -91323,10 +92655,16 @@ SQLITE_API int sqlite3_preupdate_blobwrite(sqlite3 *db){ ** a field of the row currently being updated or inserted. */ SQLITE_API int sqlite3_preupdate_new(sqlite3 *db, int iIdx, sqlite3_value **ppValue){ - PreUpdate *p = db->pPreUpdate; + PreUpdate *p; int rc = SQLITE_OK; Mem *pMem; +#ifdef SQLITE_ENABLE_API_ARMOR + if( db==0 || ppValue==0 ){ + return SQLITE_MISUSE_BKPT; + } +#endif + p = db->pPreUpdate; if( !p || p->op==SQLITE_DELETE ){ rc = SQLITE_MISUSE_BKPT; goto preupdate_new_out; @@ -91405,11 +92743,20 @@ SQLITE_API int sqlite3_stmt_scanstatus_v2( void *pOut /* OUT: Write the answer here */ ){ Vdbe *p = (Vdbe*)pStmt; - VdbeOp *aOp = p->aOp; - int nOp = p->nOp; + VdbeOp *aOp; + int nOp; ScanStatus *pScan = 0; int idx; +#ifdef SQLITE_ENABLE_API_ARMOR + if( p==0 || pOut==0 + || iScanStatusOpSQLITE_SCANSTAT_NCYCLE ){ + return 1; + } +#endif + aOp = p->aOp; + nOp = p->nOp; if( p->pFrame ){ VdbeFrame *pFrame; for(pFrame=p->pFrame; pFrame->pParent; pFrame=pFrame->pParent); @@ -91431,7 +92778,6 @@ SQLITE_API int sqlite3_stmt_scanstatus_v2( } if( flags & SQLITE_SCANSTAT_COMPLEX ){ idx = iScan; - pScan = &p->aScan[idx]; }else{ /* If the COMPLEX flag is clear, then this function must ignore any ** ScanStatus structures with ScanStatus.addrLoop set to 0. */ @@ -91444,6 +92790,8 @@ SQLITE_API int sqlite3_stmt_scanstatus_v2( } } if( idx>=p->nScan ) return 1; + assert( pScan==0 || pScan==&p->aScan[idx] ); + pScan = &p->aScan[idx]; switch( iScanStatusOp ){ case SQLITE_SCANSTAT_NLOOP: { @@ -91556,7 +92904,7 @@ SQLITE_API int sqlite3_stmt_scanstatus( SQLITE_API void sqlite3_stmt_scanstatus_reset(sqlite3_stmt *pStmt){ Vdbe *p = (Vdbe*)pStmt; int ii; - for(ii=0; iinOp; ii++){ + for(ii=0; p!=0 && iinOp; ii++){ Op *pOp = &p->aOp[ii]; pOp->nExec = 0; pOp->nCycle = 0; @@ -91895,11 +93243,12 @@ SQLITE_API int sqlite3_found_count = 0; ** sqlite3CantopenError(lineno) */ static void test_trace_breakpoint(int pc, Op *pOp, Vdbe *v){ - static int n = 0; + static u64 n = 0; (void)pc; (void)pOp; (void)v; n++; + if( n==LARGEST_UINT64 ) abort(); /* So that n is used, preventing a warning */ } #endif @@ -92525,11 +93874,11 @@ static SQLITE_NOINLINE int vdbeColumnFromOverflow( sqlite3RCStrRef(pBuf); if( t&1 ){ rc = sqlite3VdbeMemSetStr(pDest, pBuf, len, encoding, - (void(*)(void*))sqlite3RCStrUnref); + sqlite3RCStrUnref); pDest->flags |= MEM_Term; }else{ rc = sqlite3VdbeMemSetStr(pDest, pBuf, len, 0, - (void(*)(void*))sqlite3RCStrUnref); + sqlite3RCStrUnref); } }else{ rc = sqlite3VdbeMemFromBtree(pC->uc.pCursor, iOffset, len, pDest); @@ -92891,7 +94240,7 @@ case OP_Return: { /* in1 */ ** ** See also: EndCoroutine */ -case OP_InitCoroutine: { /* jump */ +case OP_InitCoroutine: { /* jump0 */ assert( pOp->p1>0 && pOp->p1<=(p->nMem+1 - p->nCursor) ); assert( pOp->p2>=0 && pOp->p2nOp ); assert( pOp->p3>=0 && pOp->p3nOp ); @@ -92914,7 +94263,9 @@ case OP_InitCoroutine: { /* jump */ ** ** The instruction at the address in register P1 is a Yield. ** Jump to the P2 parameter of that Yield. -** After the jump, register P1 becomes undefined. +** After the jump, the value register P1 is left with a value +** such that subsequent OP_Yields go back to the this same +** OP_EndCoroutine instruction. ** ** See also: InitCoroutine */ @@ -92926,8 +94277,8 @@ case OP_EndCoroutine: { /* in1 */ pCaller = &aOp[pIn1->u.i]; assert( pCaller->opcode==OP_Yield ); assert( pCaller->p2>=0 && pCaller->p2nOp ); + pIn1->u.i = (int)(pOp - p->aOp) - 1; pOp = &aOp[pCaller->p2 - 1]; - pIn1->flags = MEM_Undefined; break; } @@ -92944,7 +94295,7 @@ case OP_EndCoroutine: { /* in1 */ ** ** See also: InitCoroutine */ -case OP_Yield: { /* in1, jump */ +case OP_Yield: { /* in1, jump0 */ int pcDest; pIn1 = &aMem[pOp->p1]; assert( VdbeMemDynamic(pIn1)==0 ); @@ -93274,19 +94625,15 @@ case OP_Blob: { /* out2 */ break; } -/* Opcode: Variable P1 P2 * P4 * -** Synopsis: r[P2]=parameter(P1,P4) +/* Opcode: Variable P1 P2 * * * +** Synopsis: r[P2]=parameter(P1) ** ** Transfer the values of bound parameter P1 into register P2 -** -** If the parameter is named, then its name appears in P4. -** The P4 value is used by sqlite3_bind_parameter_name(). */ case OP_Variable: { /* out2 */ Mem *pVar; /* Value being transferred */ assert( pOp->p1>0 && pOp->p1<=p->nVar ); - assert( pOp->p4.z==0 || pOp->p4.z==sqlite3VListNumToName(p->pVList,pOp->p1) ); pVar = &p->aVar[pOp->p1 - 1]; if( sqlite3VdbeMemTooBig(pVar) ){ goto too_big; @@ -93796,7 +95143,7 @@ case OP_AddImm: { /* in1 */ pIn1 = &aMem[pOp->p1]; memAboutToChange(p, pIn1); sqlite3VdbeMemIntegerify(pIn1); - pIn1->u.i += pOp->p2; + *(u64*)&pIn1->u.i += (u64)pOp->p2; break; } @@ -93807,7 +95154,7 @@ case OP_AddImm: { /* in1 */ ** without data loss, then jump immediately to P2, or if P2==0 ** raise an SQLITE_MISMATCH exception. */ -case OP_MustBeInt: { /* jump, in1 */ +case OP_MustBeInt: { /* jump0, in1 */ pIn1 = &aMem[pOp->p1]; if( (pIn1->flags & MEM_Int)==0 ){ applyAffinity(pIn1, SQLITE_AFF_NUMERIC, encoding); @@ -93848,7 +95195,7 @@ case OP_RealAffinity: { /* in1 */ } #endif -#ifndef SQLITE_OMIT_CAST +#if !defined(SQLITE_OMIT_CAST) && !defined(SQLITE_OMIT_ANALYZE) /* Opcode: Cast P1 P2 * * * ** Synopsis: affinity(r[P1]) ** @@ -94063,7 +95410,9 @@ case OP_Ge: { /* same as TK_GE, jump, in1, in3 */ } } }else if( affinity==SQLITE_AFF_TEXT && ((flags1 | flags3) & MEM_Str)!=0 ){ - if( (flags1 & MEM_Str)==0 && (flags1&(MEM_Int|MEM_Real|MEM_IntReal))!=0 ){ + if( (flags1 & MEM_Str)!=0 ){ + pIn1->flags &= ~(MEM_Int|MEM_Real|MEM_IntReal); + }else if( (flags1&(MEM_Int|MEM_Real|MEM_IntReal))!=0 ){ testcase( pIn1->flags & MEM_Int ); testcase( pIn1->flags & MEM_Real ); testcase( pIn1->flags & MEM_IntReal ); @@ -94072,7 +95421,9 @@ case OP_Ge: { /* same as TK_GE, jump, in1, in3 */ flags1 = (pIn1->flags & ~MEM_TypeMask) | (flags1 & MEM_TypeMask); if( NEVER(pIn1==pIn3) ) flags3 = flags1 | MEM_Str; } - if( (flags3 & MEM_Str)==0 && (flags3&(MEM_Int|MEM_Real|MEM_IntReal))!=0 ){ + if( (flags3 & MEM_Str)!=0 ){ + pIn3->flags &= ~(MEM_Int|MEM_Real|MEM_IntReal); + }else if( (flags3&(MEM_Int|MEM_Real|MEM_IntReal))!=0 ){ testcase( pIn3->flags & MEM_Int ); testcase( pIn3->flags & MEM_Real ); testcase( pIn3->flags & MEM_IntReal ); @@ -95404,7 +96755,6 @@ case OP_MakeRecord: { /* NULL value. No change in zPayload */ }else{ u64 v; - u32 i; if( serial_type==7 ){ assert( sizeof(v)==sizeof(pRec->u.r) ); memcpy(&v, &pRec->u.r, sizeof(v)); @@ -95412,12 +96762,22 @@ case OP_MakeRecord: { }else{ v = pRec->u.i; } - len = i = sqlite3SmallTypeSizes[serial_type]; - assert( i>0 ); - while( 1 /*exit-by-break*/ ){ - zPayload[--i] = (u8)(v&0xFF); - if( i==0 ) break; - v >>= 8; + len = sqlite3SmallTypeSizes[serial_type]; + assert( len>=1 && len<=8 && len!=5 && len!=7 ); + switch( len ){ + default: zPayload[7] = (u8)(v&0xff); v >>= 8; + zPayload[6] = (u8)(v&0xff); v >>= 8; + /* no break */ deliberate_fall_through + case 6: zPayload[5] = (u8)(v&0xff); v >>= 8; + zPayload[4] = (u8)(v&0xff); v >>= 8; + /* no break */ deliberate_fall_through + case 4: zPayload[3] = (u8)(v&0xff); v >>= 8; + /* no break */ deliberate_fall_through + case 3: zPayload[2] = (u8)(v&0xff); v >>= 8; + /* no break */ deliberate_fall_through + case 2: zPayload[1] = (u8)(v&0xff); v >>= 8; + /* no break */ deliberate_fall_through + case 1: zPayload[0] = (u8)(v&0xff); } zPayload += len; } @@ -96335,7 +97695,8 @@ case OP_SequenceTest: { ** is the only cursor opcode that works with a pseudo-table. ** ** P3 is the number of fields in the records that will be stored by -** the pseudo-table. +** the pseudo-table. If P2 is 0 or negative then the pseudo-cursor +** will return NULL for every column. */ case OP_OpenPseudo: { VdbeCursor *pCx; @@ -96478,10 +97839,10 @@ case OP_ColumnsUsed: { ** ** See also: Found, NotFound, SeekGt, SeekGe, SeekLt */ -case OP_SeekLT: /* jump, in3, group, ncycle */ -case OP_SeekLE: /* jump, in3, group, ncycle */ -case OP_SeekGE: /* jump, in3, group, ncycle */ -case OP_SeekGT: { /* jump, in3, group, ncycle */ +case OP_SeekLT: /* jump0, in3, group, ncycle */ +case OP_SeekLE: /* jump0, in3, group, ncycle */ +case OP_SeekGE: /* jump0, in3, group, ncycle */ +case OP_SeekGT: { /* jump0, in3, group, ncycle */ int res; /* Comparison result */ int oc; /* Opcode */ VdbeCursor *pC; /* The cursor to seek */ @@ -97148,7 +98509,7 @@ case OP_Found: { /* jump, in3, ncycle */ ** ** See also: Found, NotFound, NoConflict, SeekRowid */ -case OP_SeekRowid: { /* jump, in3, ncycle */ +case OP_SeekRowid: { /* jump0, in3, ncycle */ VdbeCursor *pC; BtCursor *pCrsr; int res; @@ -97534,8 +98895,13 @@ case OP_RowCell: { ** the "primary" delete. The others are all on OPFLAG_FORDELETE ** cursors or else are marked with the AUXDELETE flag. ** -** If the OPFLAG_NCHANGE flag of P2 (NB: P2 not P5) is set, then the row -** change count is incremented (otherwise not). +** If the OPFLAG_NCHANGE (0x01) flag of P2 (NB: P2 not P5) is set, then +** the row change count is incremented (otherwise not). +** +** If the OPFLAG_ISNOOP (0x40) flag of P2 (not P5!) is set, then the +** pre-update-hook for deletes is run, but the btree is otherwise unchanged. +** This happens when the OP_Delete is to be shortly followed by an OP_Insert +** with the same key, causing the btree entry to be overwritten. ** ** P1 must not be pseudo-table. It has to be a real table with ** multiple rows. @@ -97902,7 +99268,7 @@ case OP_NullRow: { ** configured to use Prev, not Next. */ case OP_SeekEnd: /* ncycle */ -case OP_Last: { /* jump, ncycle */ +case OP_Last: { /* jump0, ncycle */ VdbeCursor *pC; BtCursor *pCrsr; int res; @@ -97936,28 +99302,38 @@ case OP_Last: { /* jump, ncycle */ break; } -/* Opcode: IfSmaller P1 P2 P3 * * +/* Opcode: IfSizeBetween P1 P2 P3 P4 * ** -** Estimate the number of rows in the table P1. Jump to P2 if that -** estimate is less than approximately 2**(0.1*P3). +** Let N be the approximate number of rows in the table or index +** with cursor P1 and let X be 10*log2(N) if N is positive or -1 +** if N is zero. +** +** Jump to P2 if X is in between P3 and P4, inclusive. */ -case OP_IfSmaller: { /* jump */ +case OP_IfSizeBetween: { /* jump */ VdbeCursor *pC; BtCursor *pCrsr; int res; i64 sz; assert( pOp->p1>=0 && pOp->p1nCursor ); + assert( pOp->p4type==P4_INT32 ); + assert( pOp->p3>=-1 && pOp->p3<=640*2 ); + assert( pOp->p4.i>=-1 && pOp->p4.i<=640*2 ); pC = p->apCsr[pOp->p1]; assert( pC!=0 ); pCrsr = pC->uc.pCursor; assert( pCrsr ); rc = sqlite3BtreeFirst(pCrsr, &res); if( rc ) goto abort_due_to_error; - if( res==0 ){ + if( res!=0 ){ + sz = -1; /* -Infinity encoding */ + }else{ sz = sqlite3BtreeRowCountEst(pCrsr); - if( ALWAYS(sz>=0) && sqlite3LogEst((u64)sz)p3 ) res = 1; + assert( sz>0 ); + sz = sqlite3LogEst((u64)sz); } + res = sz>=pOp->p3 && sz<=pOp->p4.i; VdbeBranchTaken(res!=0,2); if( res ) goto jump_to_p2; break; @@ -98010,7 +99386,7 @@ case OP_Sort: { /* jump ncycle */ ** from the beginning toward the end. In other words, the cursor is ** configured to use Next, not Prev. */ -case OP_Rewind: { /* jump, ncycle */ +case OP_Rewind: { /* jump0, ncycle */ VdbeCursor *pC; BtCursor *pCrsr; int res; @@ -98657,16 +100033,57 @@ case OP_CreateBtree: { /* out2 */ break; } -/* Opcode: SqlExec * * * P4 * +/* Opcode: SqlExec P1 P2 * P4 * ** ** Run the SQL statement or statements specified in the P4 string. +** +** The P1 parameter is a bitmask of options: +** +** 0x0001 Disable Auth and Trace callbacks while the statements +** in P4 are running. +** +** 0x0002 Set db->nAnalysisLimit to P2 while the statements in +** P4 are running. +** */ case OP_SqlExec: { + char *zErr; +#ifndef SQLITE_OMIT_AUTHORIZATION + sqlite3_xauth xAuth; +#endif + u8 mTrace; + int savedAnalysisLimit; + sqlite3VdbeIncrWriteCounter(p, 0); db->nSqlExec++; - rc = sqlite3_exec(db, pOp->p4.z, 0, 0, 0); + zErr = 0; +#ifndef SQLITE_OMIT_AUTHORIZATION + xAuth = db->xAuth; +#endif + mTrace = db->mTrace; + savedAnalysisLimit = db->nAnalysisLimit; + if( pOp->p1 & 0x0001 ){ +#ifndef SQLITE_OMIT_AUTHORIZATION + db->xAuth = 0; +#endif + db->mTrace = 0; + } + if( pOp->p1 & 0x0002 ){ + db->nAnalysisLimit = pOp->p2; + } + rc = sqlite3_exec(db, pOp->p4.z, 0, 0, &zErr); db->nSqlExec--; - if( rc ) goto abort_due_to_error; +#ifndef SQLITE_OMIT_AUTHORIZATION + db->xAuth = xAuth; +#endif + db->mTrace = mTrace; + db->nAnalysisLimit = savedAnalysisLimit; + if( zErr || rc ){ + sqlite3VdbeError(p, "%s", zErr); + sqlite3_free(zErr); + if( rc==SQLITE_NOMEM ) goto no_mem; + goto abort_due_to_error; + } break; } @@ -98812,11 +100229,11 @@ case OP_DropTrigger: { /* Opcode: IntegrityCk P1 P2 P3 P4 P5 ** ** Do an analysis of the currently open database. Store in -** register P1 the text of an error message describing any problems. -** If no problems are found, store a NULL in register P1. +** register (P1+1) the text of an error message describing any problems. +** If no problems are found, store a NULL in register (P1+1). ** -** The register P3 contains one less than the maximum number of allowed errors. -** At most reg(P3) errors will be reported. +** The register (P1) contains one less than the maximum number of allowed +** errors. At most reg(P1) errors will be reported. ** In other words, the analysis stops as soon as reg(P1) errors are ** seen. Reg(P1) is updated with the number of errors remaining. ** @@ -98836,19 +100253,21 @@ case OP_IntegrityCk: { Mem *pnErr; /* Register keeping track of errors remaining */ assert( p->bIsReader ); + assert( pOp->p4type==P4_INTARRAY ); nRoot = pOp->p2; aRoot = pOp->p4.ai; assert( nRoot>0 ); + assert( aRoot!=0 ); assert( aRoot[0]==(Pgno)nRoot ); - assert( pOp->p3>0 && pOp->p3<=(p->nMem+1 - p->nCursor) ); - pnErr = &aMem[pOp->p3]; + assert( pOp->p1>0 && (pOp->p1+1)<=(p->nMem+1 - p->nCursor) ); + pnErr = &aMem[pOp->p1]; assert( (pnErr->flags & MEM_Int)!=0 ); assert( (pnErr->flags & (MEM_Str|MEM_Blob))==0 ); - pIn1 = &aMem[pOp->p1]; + pIn1 = &aMem[pOp->p1+1]; assert( pOp->p5nDb ); assert( DbMaskTest(p->btreeMask, pOp->p5) ); - rc = sqlite3BtreeIntegrityCheck(db, db->aDb[pOp->p5].pBt, &aRoot[1], nRoot, - (int)pnErr->u.i+1, &nErr, &z); + rc = sqlite3BtreeIntegrityCheck(db, db->aDb[pOp->p5].pBt, &aRoot[1], + &aMem[pOp->p3], nRoot, (int)pnErr->u.i+1, &nErr, &z); sqlite3VdbeMemSetNull(pIn1); if( nErr==0 ){ assert( z==0 ); @@ -98975,7 +100394,9 @@ case OP_RowSetTest: { /* jump, in1, in3 */ ** P1 contains the address of the memory cell that contains the first memory ** cell in an array of values used as arguments to the sub-program. P2 ** contains the address to jump to if the sub-program throws an IGNORE -** exception using the RAISE() function. Register P3 contains the address +** exception using the RAISE() function. P2 might be zero, if there is +** no possibility that an IGNORE exception will be raised. +** Register P3 contains the address ** of a memory cell in this (the parent) VM that is used to allocate the ** memory required by the sub-vdbe at runtime. ** @@ -98983,7 +100404,7 @@ case OP_RowSetTest: { /* jump, in1, in3 */ ** ** If P5 is non-zero, then recursive program invocation is enabled. */ -case OP_Program: { /* jump */ +case OP_Program: { /* jump0 */ int nMem; /* Number of memory registers for sub-program */ int nByte; /* Bytes of runtime space required for sub-program */ Mem *pRt; /* Register to allocate runtime space */ @@ -99887,6 +101308,52 @@ case OP_VOpen: { /* ncycle */ } #endif /* SQLITE_OMIT_VIRTUALTABLE */ +#ifndef SQLITE_OMIT_VIRTUALTABLE +/* Opcode: VCheck P1 P2 P3 P4 * +** +** P4 is a pointer to a Table object that is a virtual table in schema P1 +** that supports the xIntegrity() method. This opcode runs the xIntegrity() +** method for that virtual table, using P3 as the integer argument. If +** an error is reported back, the table name is prepended to the error +** message and that message is stored in P2. If no errors are seen, +** register P2 is set to NULL. +*/ +case OP_VCheck: { /* out2 */ + Table *pTab; + sqlite3_vtab *pVtab; + const sqlite3_module *pModule; + char *zErr = 0; + + pOut = &aMem[pOp->p2]; + sqlite3VdbeMemSetNull(pOut); /* Innocent until proven guilty */ + assert( pOp->p4type==P4_TABLEREF ); + pTab = pOp->p4.pTab; + assert( pTab!=0 ); + assert( pTab->nTabRef>0 ); + assert( IsVirtual(pTab) ); + if( pTab->u.vtab.p==0 ) break; + pVtab = pTab->u.vtab.p->pVtab; + assert( pVtab!=0 ); + pModule = pVtab->pModule; + assert( pModule!=0 ); + assert( pModule->iVersion>=4 ); + assert( pModule->xIntegrity!=0 ); + sqlite3VtabLock(pTab->u.vtab.p); + assert( pOp->p1>=0 && pOp->p1nDb ); + rc = pModule->xIntegrity(pVtab, db->aDb[pOp->p1].zDbSName, pTab->zName, + pOp->p3, &zErr); + sqlite3VtabUnlock(pTab->u.vtab.p); + if( rc ){ + sqlite3_free(zErr); + goto abort_due_to_error; + } + if( zErr ){ + sqlite3VdbeMemSetStr(pOut, zErr, -1, SQLITE_UTF8, sqlite3_free); + } + break; +} +#endif /* SQLITE_OMIT_VIRTUALTABLE */ + #ifndef SQLITE_OMIT_VIRTUALTABLE /* Opcode: VInitIn P1 P2 P3 * * ** Synopsis: r[P2]=ValueList(P1,P3) @@ -100000,6 +101467,7 @@ case OP_VColumn: { /* ncycle */ const sqlite3_module *pModule; Mem *pDest; sqlite3_context sContext; + FuncDef nullFunc; VdbeCursor *pCur = p->apCsr[pOp->p1]; assert( pCur!=0 ); @@ -100017,6 +101485,9 @@ case OP_VColumn: { /* ncycle */ memset(&sContext, 0, sizeof(sContext)); sContext.pOut = pDest; sContext.enc = encoding; + nullFunc.pUserData = 0; + nullFunc.funcFlags = SQLITE_RESULT_SUBTYPE; + sContext.pFunc = &nullFunc; assert( pOp->p5==OPFLAG_NOCHNG || pOp->p5==0 ); if( pOp->p5 & OPFLAG_NOCHNG ){ sqlite3VdbeMemSetNull(pDest); @@ -100349,6 +101820,42 @@ case OP_ClrSubtype: { /* in1 */ break; } +/* Opcode: GetSubtype P1 P2 * * * +** Synopsis: r[P2] = r[P1].subtype +** +** Extract the subtype value from register P1 and write that subtype +** into register P2. If P1 has no subtype, then P1 gets a NULL. +*/ +case OP_GetSubtype: { /* in1 out2 */ + pIn1 = &aMem[pOp->p1]; + pOut = &aMem[pOp->p2]; + if( pIn1->flags & MEM_Subtype ){ + sqlite3VdbeMemSetInt64(pOut, pIn1->eSubtype); + }else{ + sqlite3VdbeMemSetNull(pOut); + } + break; +} + +/* Opcode: SetSubtype P1 P2 * * * +** Synopsis: r[P2].subtype = r[P1] +** +** Set the subtype value of register P2 to the integer from register P1. +** If P1 is NULL, clear the subtype from p2. +*/ +case OP_SetSubtype: { /* in1 out2 */ + pIn1 = &aMem[pOp->p1]; + pOut = &aMem[pOp->p2]; + if( pIn1->flags & MEM_Null ){ + pOut->flags &= ~MEM_Subtype; + }else{ + assert( pIn1->flags & MEM_Int ); + pOut->flags |= MEM_Subtype; + pOut->eSubtype = (u8)(pIn1->u.i & 0xff); + } + break; +} + /* Opcode: FilterAdd P1 * P3 P4 * ** Synopsis: filter(P1) += key(P3@P4) ** @@ -100446,7 +101953,7 @@ case OP_Filter: { /* jump */ ** error is encountered. */ case OP_Trace: -case OP_Init: { /* jump */ +case OP_Init: { /* jump0 */ int i; #ifndef SQLITE_OMIT_TRACE char *zTrace; @@ -100833,8 +102340,7 @@ static int blobSeekToRow(Incrblob *p, sqlite3_int64 iRow, char **pzErr){ /* Set the value of register r[1] in the SQL statement to integer iRow. ** This is done directly as a performance optimization */ - v->aMem[1].flags = MEM_Int; - v->aMem[1].u.i = iRow; + sqlite3VdbeMemSetInt64(&v->aMem[1], iRow); /* If the statement has been run before (and is paused at the OP_ResultRow) ** then back it up to the point where it does the OP_NotExists. This could @@ -100917,7 +102423,7 @@ SQLITE_API int sqlite3_blob_open( #endif *ppBlob = 0; #ifdef SQLITE_ENABLE_API_ARMOR - if( !sqlite3SafetyCheckOk(db) || zTable==0 ){ + if( !sqlite3SafetyCheckOk(db) || zTable==0 || zColumn==0 ){ return SQLITE_MISUSE_BKPT; } #endif @@ -101479,7 +102985,7 @@ struct SorterFile { struct SorterList { SorterRecord *pList; /* Linked list of records */ u8 *aMemory; /* If non-NULL, bulk memory to hold pList */ - int szPMA; /* Size of pList as PMA in bytes */ + i64 szPMA; /* Size of pList as PMA in bytes */ }; /* @@ -101588,10 +103094,10 @@ typedef int (*SorterCompare)(SortSubtask*,int*,const void*,int,const void*,int); struct SortSubtask { SQLiteThread *pThread; /* Background thread, if any */ int bDone; /* Set if thread is finished but not joined */ + int nPMA; /* Number of PMAs currently in file */ VdbeSorter *pSorter; /* Sorter that owns this sub-task */ UnpackedRecord *pUnpacked; /* Space to unpack a record */ SorterList list; /* List for thread to write to a PMA */ - int nPMA; /* Number of PMAs currently in file */ SorterCompare xCompare; /* Compare function to use */ SorterFile file; /* Temp file for level-0 PMAs */ SorterFile file2; /* Space for other PMAs */ @@ -103065,8 +104571,8 @@ SQLITE_PRIVATE int sqlite3VdbeSorterWrite( int rc = SQLITE_OK; /* Return Code */ SorterRecord *pNew; /* New list element */ int bFlush; /* True to flush contents of memory to PMA */ - int nReq; /* Bytes of memory required */ - int nPMA; /* Bytes of PMA space required */ + i64 nReq; /* Bytes of memory required */ + i64 nPMA; /* Bytes of PMA space required */ int t; /* serial type of first record field */ assert( pCsr->eCurType==CURTYPE_SORTER ); @@ -104348,10 +105854,10 @@ static int bytecodevtabColumn( #ifdef SQLITE_ENABLE_STMT_SCANSTATUS case 9: /* nexec */ - sqlite3_result_int(ctx, pOp->nExec); + sqlite3_result_int64(ctx, pOp->nExec); break; case 10: /* ncycle */ - sqlite3_result_int(ctx, pOp->nCycle); + sqlite3_result_int64(ctx, pOp->nCycle); break; #else case 9: /* nexec */ @@ -104490,7 +105996,8 @@ static sqlite3_module bytecodevtabModule = { /* xSavepoint */ 0, /* xRelease */ 0, /* xRollbackTo */ 0, - /* xShadowName */ 0 + /* xShadowName */ 0, + /* xIntegrity */ 0 }; @@ -105294,6 +106801,8 @@ static void resolveAlias( assert( iCol>=0 && iColnExpr ); pOrig = pEList->a[iCol].pExpr; assert( pOrig!=0 ); + assert( !ExprHasProperty(pExpr, EP_Reduced|EP_TokenOnly) ); + if( pExpr->pAggInfo ) return; db = pParse->db; pDup = sqlite3ExprDup(db, pOrig, 0); if( db->mallocFailed ){ @@ -105319,21 +106828,36 @@ static void resolveAlias( } /* -** Subqueries stores the original database, table and column names for their -** result sets in ExprList.a[].zSpan, in the form "DATABASE.TABLE.COLUMN". -** Check to see if the zSpan given to this routine matches the zDb, zTab, -** and zCol. If any of zDb, zTab, and zCol are NULL then those fields will -** match anything. +** Subqueries store the original database, table and column names for their +** result sets in ExprList.a[].zSpan, in the form "DATABASE.TABLE.COLUMN", +** and mark the expression-list item by setting ExprList.a[].fg.eEName +** to ENAME_TAB. +** +** Check to see if the zSpan/eEName of the expression-list item passed to this +** routine matches the zDb, zTab, and zCol. If any of zDb, zTab, and zCol are +** NULL then those fields will match anything. Return true if there is a match, +** or false otherwise. +** +** SF_NestedFrom subqueries also store an entry for the implicit rowid (or +** _rowid_, or oid) column by setting ExprList.a[].fg.eEName to ENAME_ROWID, +** and setting zSpan to "DATABASE.TABLE.". This type of pItem +** argument matches if zCol is a rowid alias. If it is not NULL, (*pbRowid) +** is set to 1 if there is this kind of match. */ SQLITE_PRIVATE int sqlite3MatchEName( const struct ExprList_item *pItem, const char *zCol, const char *zTab, - const char *zDb + const char *zDb, + int *pbRowid ){ int n; const char *zSpan; - if( pItem->fg.eEName!=ENAME_TAB ) return 0; + int eEName = pItem->fg.eEName; + if( eEName!=ENAME_TAB && (eEName!=ENAME_ROWID || NEVER(pbRowid==0)) ){ + return 0; + } + assert( pbRowid==0 || *pbRowid==0 ); zSpan = pItem->zEName; for(n=0; ALWAYS(zSpan[n]) && zSpan[n]!='.'; n++){} if( zDb && (sqlite3StrNICmp(zSpan, zDb, n)!=0 || zDb[n]!=0) ){ @@ -105345,9 +106869,11 @@ SQLITE_PRIVATE int sqlite3MatchEName( return 0; } zSpan += n+1; - if( zCol && sqlite3StrICmp(zSpan, zCol)!=0 ){ - return 0; + if( zCol ){ + if( eEName==ENAME_TAB && sqlite3StrICmp(zSpan, zCol)!=0 ) return 0; + if( eEName==ENAME_ROWID && sqlite3IsRowid(zCol)==0 ) return 0; } + if( eEName==ENAME_ROWID ) *pbRowid = 1; return 1; } @@ -105380,6 +106906,7 @@ SQLITE_PRIVATE Bitmask sqlite3ExprColUsed(Expr *pExpr){ assert( ExprUseYTab(pExpr) ); pExTab = pExpr->y.pTab; assert( pExTab!=0 ); + assert( n < pExTab->nCol ); if( (pExTab->tabFlags & TF_HasGenerated)!=0 && (pExTab->aCol[n].colFlags & COLFLAG_GENERATED)!=0 ){ @@ -105474,13 +107001,13 @@ static int lookupName( Parse *pParse, /* The parsing context */ const char *zDb, /* Name of the database containing table, or NULL */ const char *zTab, /* Name of table containing column, or NULL */ - const char *zCol, /* Name of the column. */ + const Expr *pRight, /* Name of the column. */ NameContext *pNC, /* The name context used to resolve the name */ Expr *pExpr /* Make this EXPR node point to the selected column */ ){ int i, j; /* Loop counters */ int cnt = 0; /* Number of matching column names */ - int cntTab = 0; /* Number of matching table names */ + int cntTab = 0; /* Number of potential "rowid" matches */ int nSubquery = 0; /* How many levels of subquery */ sqlite3 *db = pParse->db; /* The database connection */ SrcItem *pItem; /* Use for looping over pSrcList items */ @@ -105491,6 +107018,7 @@ static int lookupName( Table *pTab = 0; /* Table holding the row */ Column *pCol; /* A column of pTab */ ExprList *pFJMatch = 0; /* Matches for FULL JOIN .. USING */ + const char *zCol = pRight->u.zToken; assert( pNC ); /* the name context cannot be NULL. */ assert( zCol ); /* The Z in X.Y.Z cannot be NULL */ @@ -105557,39 +107085,49 @@ static int lookupName( assert( pEList!=0 ); assert( pEList->nExpr==pTab->nCol ); for(j=0; jnExpr; j++){ - if( !sqlite3MatchEName(&pEList->a[j], zCol, zTab, zDb) ){ + int bRowid = 0; /* True if possible rowid match */ + if( !sqlite3MatchEName(&pEList->a[j], zCol, zTab, zDb, &bRowid) ){ continue; } - if( cnt>0 ){ - if( pItem->fg.isUsing==0 - || sqlite3IdListIndex(pItem->u3.pUsing, zCol)<0 - ){ - /* Two or more tables have the same column name which is - ** not joined by USING. This is an error. Signal as much - ** by clearing pFJMatch and letting cnt go above 1. */ - sqlite3ExprListDelete(db, pFJMatch); - pFJMatch = 0; - }else - if( (pItem->fg.jointype & JT_RIGHT)==0 ){ - /* An INNER or LEFT JOIN. Use the left-most table */ - continue; - }else - if( (pItem->fg.jointype & JT_LEFT)==0 ){ - /* A RIGHT JOIN. Use the right-most table */ - cnt = 0; - sqlite3ExprListDelete(db, pFJMatch); - pFJMatch = 0; - }else{ - /* For a FULL JOIN, we must construct a coalesce() func */ - extendFJMatch(pParse, &pFJMatch, pMatch, pExpr->iColumn); + if( bRowid==0 ){ + if( cnt>0 ){ + if( pItem->fg.isUsing==0 + || sqlite3IdListIndex(pItem->u3.pUsing, zCol)<0 + ){ + /* Two or more tables have the same column name which is + ** not joined by USING. This is an error. Signal as much + ** by clearing pFJMatch and letting cnt go above 1. */ + sqlite3ExprListDelete(db, pFJMatch); + pFJMatch = 0; + }else + if( (pItem->fg.jointype & JT_RIGHT)==0 ){ + /* An INNER or LEFT JOIN. Use the left-most table */ + continue; + }else + if( (pItem->fg.jointype & JT_LEFT)==0 ){ + /* A RIGHT JOIN. Use the right-most table */ + cnt = 0; + sqlite3ExprListDelete(db, pFJMatch); + pFJMatch = 0; + }else{ + /* For a FULL JOIN, we must construct a coalesce() func */ + extendFJMatch(pParse, &pFJMatch, pMatch, pExpr->iColumn); + } } + cnt++; + hit = 1; + }else if( cnt>0 ){ + /* This is a potential rowid match, but there has already been + ** a real match found. So this can be ignored. */ + continue; } - cnt++; - cntTab = 2; + cntTab++; pMatch = pItem; pExpr->iColumn = j; pEList->a[j].fg.bUsed = 1; - hit = 1; + + /* rowid cannot be part of a USING clause - assert() this. */ + assert( bRowid==0 || pEList->a[j].fg.bUsingTerm==0 ); if( pEList->a[j].fg.bUsingTerm ) break; } if( hit || zTab==0 ) continue; @@ -105653,8 +107191,37 @@ static int lookupName( } } if( 0==cnt && VisibleRowid(pTab) ){ + /* pTab is a potential ROWID match. Keep track of it and match + ** the ROWID later if that seems appropriate. (Search for "cntTab" + ** to find related code.) Only allow a ROWID match if there is + ** a single ROWID match candidate. + */ +#ifdef SQLITE_ALLOW_ROWID_IN_VIEW + /* In SQLITE_ALLOW_ROWID_IN_VIEW mode, allow a ROWID match + ** if there is a single VIEW candidate or if there is a single + ** non-VIEW candidate plus multiple VIEW candidates. In other + ** words non-VIEW candidate terms take precedence over VIEWs. + */ + if( cntTab==0 + || (cntTab==1 + && ALWAYS(pMatch!=0) + && ALWAYS(pMatch->pTab!=0) + && (pMatch->pTab->tabFlags & TF_Ephemeral)!=0 + && (pTab->tabFlags & TF_Ephemeral)==0) + ){ + cntTab = 1; + pMatch = pItem; + }else{ + cntTab++; + } +#else + /* The (much more common) non-SQLITE_ALLOW_ROWID_IN_VIEW case is + ** simpler since we require exactly one candidate, which will + ** always be a non-VIEW + */ cntTab++; pMatch = pItem; +#endif } } if( pMatch ){ @@ -105683,7 +107250,8 @@ static int lookupName( if( pParse->bReturning ){ if( (pNC->ncFlags & NC_UBaseReg)!=0 && ALWAYS(zTab==0 - || sqlite3StrICmp(zTab,pParse->pTriggerTab->zName)==0) + || sqlite3StrICmp(zTab,pParse->pTriggerTab->zName)==0 + || isValidSchemaTableName(zTab, pParse->pTriggerTab, 0)) ){ pExpr->iTable = op!=TK_DELETE; pTab = pParse->pTriggerTab; @@ -105780,14 +107348,19 @@ static int lookupName( ** Perhaps the name is a reference to the ROWID */ if( cnt==0 - && cntTab==1 + && cntTab>=1 && pMatch && (pNC->ncFlags & (NC_IdxExpr|NC_GenCol))==0 && sqlite3IsRowid(zCol) - && ALWAYS(VisibleRowid(pMatch->pTab)) + && ALWAYS(VisibleRowid(pMatch->pTab) || pMatch->fg.isNestedFrom) ){ - cnt = 1; - pExpr->iColumn = -1; + cnt = cntTab; +#if SQLITE_ALLOW_ROWID_IN_VIEW+0==2 + if( pMatch->pTab!=0 && IsView(pMatch->pTab) ){ + eNewExprOp = TK_NULL; + } +#endif + if( pMatch->fg.isNestedFrom==0 ) pExpr->iColumn = -1; pExpr->affExpr = SQLITE_AFF_INTEGER; } @@ -105940,12 +107513,17 @@ static int lookupName( sqlite3ErrorMsg(pParse, "%s: %s.%s.%s", zErr, zDb, zTab, zCol); }else if( zTab ){ sqlite3ErrorMsg(pParse, "%s: %s.%s", zErr, zTab, zCol); + }else if( cnt==0 && ExprHasProperty(pRight,EP_DblQuoted) ){ + sqlite3ErrorMsg(pParse, "%s: \"%s\" - should this be a" + " string literal in single-quotes?", + zErr, zCol); }else{ sqlite3ErrorMsg(pParse, "%s: %s", zErr, zCol); } sqlite3RecordErrorOffsetOfExpr(pParse->db, pExpr); pParse->checkSchema = 1; pTopNC->nNcErr++; + eNewExprOp = TK_NULL; } assert( pFJMatch==0 ); @@ -105972,8 +107550,12 @@ static int lookupName( ** If a generated column is referenced, set bits for every column ** of the table. */ - if( pExpr->iColumn>=0 && pMatch!=0 ){ - pMatch->colUsed |= sqlite3ExprColUsed(pExpr); + if( pMatch ){ + if( pExpr->iColumn>=0 ){ + pMatch->colUsed |= sqlite3ExprColUsed(pExpr); + }else{ + pMatch->fg.rowidUsed = 1; + } } pExpr->op = eNewExprOp; @@ -106150,6 +107732,19 @@ static int resolveExprStep(Walker *pWalker, Expr *pExpr){ ** resolved. This prevents "column" from being counted as having been ** referenced, which might prevent a SELECT from being erroneously ** marked as correlated. + ** + ** 2024-03-28: Beware of aggregates. A bare column of aggregated table + ** can still evaluate to NULL even though it is marked as NOT NULL. + ** Example: + ** + ** CREATE TABLE t1(a INT NOT NULL); + ** SELECT a, a IS NULL, a IS NOT NULL, count(*) FROM t1; + ** + ** The "a IS NULL" and "a IS NOT NULL" expressions cannot be optimized + ** here because at the time this case is hit, we do not yet know whether + ** or not t1 is being aggregated. We have to assume the worst and omit + ** the optimization. The only time it is safe to apply this optimization + ** is within the WHERE clause. */ case TK_NOTNULL: case TK_ISNULL: { @@ -106160,19 +107755,36 @@ static int resolveExprStep(Walker *pWalker, Expr *pExpr){ anRef[i] = p->nRef; } sqlite3WalkExpr(pWalker, pExpr->pLeft); - if( 0==sqlite3ExprCanBeNull(pExpr->pLeft) && !IN_RENAME_OBJECT ){ - testcase( ExprHasProperty(pExpr, EP_OuterON) ); - assert( !ExprHasProperty(pExpr, EP_IntValue) ); - pExpr->u.iValue = (pExpr->op==TK_NOTNULL); - pExpr->flags |= EP_IntValue; - pExpr->op = TK_INTEGER; + if( IN_RENAME_OBJECT ) return WRC_Prune; + if( sqlite3ExprCanBeNull(pExpr->pLeft) ){ + /* The expression can be NULL. So the optimization does not apply */ + return WRC_Prune; + } - for(i=0, p=pNC; p && ipNext, i++){ - p->nRef = anRef[i]; + for(i=0, p=pNC; p; p=p->pNext, i++){ + if( (p->ncFlags & NC_Where)==0 ){ + return WRC_Prune; /* Not in a WHERE clause. Unsafe to optimize. */ } - sqlite3ExprDelete(pParse->db, pExpr->pLeft); - pExpr->pLeft = 0; } + testcase( ExprHasProperty(pExpr, EP_OuterON) ); + assert( !ExprHasProperty(pExpr, EP_IntValue) ); +#if TREETRACE_ENABLED + if( sqlite3TreeTrace & 0x80000 ){ + sqlite3DebugPrintf( + "NOT NULL strength reduction converts the following to %d:\n", + pExpr->op==TK_NOTNULL + ); + sqlite3ShowExpr(pExpr); + } +#endif /* TREETRACE_ENABLED */ + pExpr->u.iValue = (pExpr->op==TK_NOTNULL); + pExpr->flags |= EP_IntValue; + pExpr->op = TK_INTEGER; + for(i=0, p=pNC; p && ipNext, i++){ + p->nRef = anRef[i]; + } + sqlite3ExprDelete(pParse->db, pExpr->pLeft); + pExpr->pLeft = 0; return WRC_Prune; } @@ -106186,7 +107798,6 @@ static int resolveExprStep(Walker *pWalker, Expr *pExpr){ */ case TK_ID: case TK_DOT: { - const char *zColumn; const char *zTable; const char *zDb; Expr *pRight; @@ -106195,7 +107806,7 @@ static int resolveExprStep(Walker *pWalker, Expr *pExpr){ zDb = 0; zTable = 0; assert( !ExprHasProperty(pExpr, EP_IntValue) ); - zColumn = pExpr->u.zToken; + pRight = pExpr; }else{ Expr *pLeft = pExpr->pLeft; testcase( pNC->ncFlags & NC_IdxExpr ); @@ -106214,14 +107825,13 @@ static int resolveExprStep(Walker *pWalker, Expr *pExpr){ } assert( ExprUseUToken(pLeft) && ExprUseUToken(pRight) ); zTable = pLeft->u.zToken; - zColumn = pRight->u.zToken; assert( ExprUseYTab(pExpr) ); if( IN_RENAME_OBJECT ){ sqlite3RenameTokenRemap(pParse, (void*)pExpr, (void*)pRight); sqlite3RenameTokenRemap(pParse, (void*)&pExpr->y.pTab, (void*)pLeft); } } - return lookupName(pParse, zDb, zTable, zColumn, pNC, pExpr); + return lookupName(pParse, zDb, zTable, pRight, pNC, pExpr); } /* Resolve function names @@ -106240,6 +107850,7 @@ static int resolveExprStep(Walker *pWalker, Expr *pExpr){ Window *pWin = (IsWindowFunc(pExpr) ? pExpr->y.pWin : 0); #endif assert( !ExprHasProperty(pExpr, EP_xIsSelect|EP_IntValue) ); + assert( pExpr->pLeft==0 || pExpr->pLeft->op==TK_ORDER ); zId = pExpr->u.zToken; pDef = sqlite3FindFunction(pParse->db, zId, n, enc, 0); if( pDef==0 ){ @@ -106381,6 +107992,10 @@ static int resolveExprStep(Walker *pWalker, Expr *pExpr){ pNC->nNcErr++; } #endif + else if( is_agg==0 && pExpr->pLeft ){ + sqlite3ExprOrderByAggregateError(pParse, pExpr); + pNC->nNcErr++; + } if( is_agg ){ /* Window functions may not be arguments of aggregate functions. ** Or arguments of other window functions. But aggregate functions @@ -106392,13 +108007,16 @@ static int resolveExprStep(Walker *pWalker, Expr *pExpr){ #endif } } -#ifndef SQLITE_OMIT_WINDOWFUNC - else if( ExprHasProperty(pExpr, EP_WinFunc) ){ + else if( ExprHasProperty(pExpr, EP_WinFunc) || pExpr->pLeft ){ is_agg = 1; } -#endif sqlite3WalkExprList(pWalker, pList); if( is_agg ){ + if( pExpr->pLeft ){ + assert( pExpr->pLeft->op==TK_ORDER ); + assert( ExprUseXList(pExpr->pLeft) ); + sqlite3WalkExprList(pWalker, pExpr->pLeft->x.pList); + } #ifndef SQLITE_OMIT_WINDOWFUNC if( pWin ){ Select *pSel = pNC->pWinSelect; @@ -106427,11 +108045,12 @@ static int resolveExprStep(Walker *pWalker, Expr *pExpr){ while( pNC2 && sqlite3ReferencesSrcList(pParse, pExpr, pNC2->pSrcList)==0 ){ - pExpr->op2++; + pExpr->op2 += (1 + pNC2->nNestedSelect); pNC2 = pNC2->pNext; } assert( pDef!=0 || IN_RENAME_OBJECT ); if( pNC2 && pDef ){ + pExpr->op2 += pNC2->nNestedSelect; assert( SQLITE_FUNC_MINMAX==NC_MinMaxAgg ); assert( SQLITE_FUNC_ANYORDER==NC_OrderAgg ); testcase( (pDef->funcFlags & SQLITE_FUNC_MINMAX)!=0 ); @@ -106460,6 +108079,7 @@ static int resolveExprStep(Walker *pWalker, Expr *pExpr){ testcase( pNC->ncFlags & NC_PartIdx ); testcase( pNC->ncFlags & NC_IdxExpr ); testcase( pNC->ncFlags & NC_GenCol ); + assert( pExpr->x.pSelect ); if( pNC->ncFlags & NC_SelfRef ){ notValidImpl(pParse, pNC, "subqueries", pExpr, pExpr); }else{ @@ -106468,6 +108088,7 @@ static int resolveExprStep(Walker *pWalker, Expr *pExpr){ assert( pNC->nRef>=nRef ); if( nRef!=pNC->nRef ){ ExprSetProperty(pExpr, EP_VarSelect); + pExpr->x.pSelect->selFlags |= SF_Correlated; } pNC->ncFlags |= NC_Subquery; } @@ -106962,10 +108583,8 @@ static int resolveSelectStep(Walker *pWalker, Select *p){ while( p ){ assert( (p->selFlags & SF_Expanded)!=0 ); assert( (p->selFlags & SF_Resolved)==0 ); - assert( db->suppressErr==0 ); /* SF_Resolved not set if errors suppressed */ p->selFlags |= SF_Resolved; - /* Resolve the expressions in the LIMIT and OFFSET clauses. These ** are not allowed to refer to any names, so pass an empty NameContext. */ @@ -106992,8 +108611,10 @@ static int resolveSelectStep(Walker *pWalker, Select *p){ /* Recursively resolve names in all subqueries in the FROM clause */ + if( pOuterNC ) pOuterNC->nNestedSelect++; for(i=0; ipSrc->nSrc; i++){ SrcItem *pItem = &p->pSrc->a[i]; + assert( pItem->zName!=0 || pItem->pSelect!=0 );/* Test of tag-20240424-1*/ if( pItem->pSelect && (pItem->pSelect->selFlags & SF_Resolved)==0 ){ int nRef = pOuterNC ? pOuterNC->nRef : 0; const char *zSavedContext = pParse->zAuthContext; @@ -107016,6 +108637,9 @@ static int resolveSelectStep(Walker *pWalker, Select *p){ } } } + if( pOuterNC && ALWAYS(pOuterNC->nNestedSelect>0) ){ + pOuterNC->nNestedSelect--; + } /* Set up the local name-context to pass to sqlite3ResolveExprNames() to ** resolve the result-set expression list. @@ -107059,7 +108683,9 @@ static int resolveSelectStep(Walker *pWalker, Select *p){ } if( sqlite3ResolveExprNames(&sNC, p->pHaving) ) return WRC_Abort; } + sNC.ncFlags |= NC_Where; if( sqlite3ResolveExprNames(&sNC, p->pWhere) ) return WRC_Abort; + sNC.ncFlags &= ~NC_Where; /* Resolve names in table-valued-function arguments */ for(i=0; ipSrc->nSrc; i++){ @@ -107598,9 +109224,10 @@ SQLITE_PRIVATE Expr *sqlite3ExprSkipCollateAndLikely(Expr *pExpr){ assert( pExpr->x.pList->nExpr>0 ); assert( pExpr->op==TK_FUNCTION ); pExpr = pExpr->x.pList->a[0].pExpr; - }else{ - assert( pExpr->op==TK_COLLATE ); + }else if( pExpr->op==TK_COLLATE ){ pExpr = pExpr->pLeft; + }else{ + break; } } return pExpr; @@ -107971,6 +109598,7 @@ SQLITE_PRIVATE Expr *sqlite3ExprForVectorField( */ pRet = sqlite3PExpr(pParse, TK_SELECT_COLUMN, 0, 0); if( pRet ){ + ExprSetProperty(pRet, EP_FullSize); pRet->iTable = nField; pRet->iColumn = iField; pRet->pLeft = pVector; @@ -108293,11 +109921,12 @@ SQLITE_PRIVATE void sqlite3ExprSetErrorOffset(Expr *pExpr, int iOfst){ ** appear to be quoted. If the quotes were of the form "..." (double-quotes) ** then the EP_DblQuoted flag is set on the expression node. ** -** Special case: If op==TK_INTEGER and pToken points to a string that -** can be translated into a 32-bit integer, then the token is not -** stored in u.zToken. Instead, the integer values is written -** into u.iValue and the EP_IntValue flag is set. No extra storage +** Special case (tag-20240227-a): If op==TK_INTEGER and pToken points to +** a string that can be translated into a 32-bit integer, then the token is +** not stored in u.zToken. Instead, the integer values is written +** into u.iValue and the EP_IntValue flag is set. No extra storage ** is allocated to hold the integer text and the dequote flag is ignored. +** See also tag-20240227-b. */ SQLITE_PRIVATE Expr *sqlite3ExprAlloc( sqlite3 *db, /* Handle for sqlite3DbMallocRawNN() */ @@ -108313,7 +109942,7 @@ SQLITE_PRIVATE Expr *sqlite3ExprAlloc( if( pToken ){ if( op!=TK_INTEGER || pToken->z==0 || sqlite3GetInt32(pToken->z, &iValue)==0 ){ - nExtra = pToken->n+1; + nExtra = pToken->n+1; /* tag-20240227-a */ assert( iValue>=0 ); } } @@ -108561,6 +110190,67 @@ SQLITE_PRIVATE Expr *sqlite3ExprFunction( return pNew; } +/* +** Report an error when attempting to use an ORDER BY clause within +** the arguments of a non-aggregate function. +*/ +SQLITE_PRIVATE void sqlite3ExprOrderByAggregateError(Parse *pParse, Expr *p){ + sqlite3ErrorMsg(pParse, + "ORDER BY may not be used with non-aggregate %#T()", p + ); +} + +/* +** Attach an ORDER BY clause to a function call. +** +** functionname( arguments ORDER BY sortlist ) +** \_____________________/ \______/ +** pExpr pOrderBy +** +** The ORDER BY clause is inserted into a new Expr node of type TK_ORDER +** and added to the Expr.pLeft field of the parent TK_FUNCTION node. +*/ +SQLITE_PRIVATE void sqlite3ExprAddFunctionOrderBy( + Parse *pParse, /* Parsing context */ + Expr *pExpr, /* The function call to which ORDER BY is to be added */ + ExprList *pOrderBy /* The ORDER BY clause to add */ +){ + Expr *pOB; + sqlite3 *db = pParse->db; + if( NEVER(pOrderBy==0) ){ + assert( db->mallocFailed ); + return; + } + if( pExpr==0 ){ + assert( db->mallocFailed ); + sqlite3ExprListDelete(db, pOrderBy); + return; + } + assert( pExpr->op==TK_FUNCTION ); + assert( pExpr->pLeft==0 ); + assert( ExprUseXList(pExpr) ); + if( pExpr->x.pList==0 || NEVER(pExpr->x.pList->nExpr==0) ){ + /* Ignore ORDER BY on zero-argument aggregates */ + sqlite3ParserAddCleanup(pParse, sqlite3ExprListDeleteGeneric, pOrderBy); + return; + } + if( IsWindowFunc(pExpr) ){ + sqlite3ExprOrderByAggregateError(pParse, pExpr); + sqlite3ExprListDelete(db, pOrderBy); + return; + } + + pOB = sqlite3ExprAlloc(db, TK_ORDER, 0, 0); + if( pOB==0 ){ + sqlite3ExprListDelete(db, pOrderBy); + return; + } + pOB->x.pList = pOrderBy; + assert( ExprUseXList(pOB) ); + pExpr->pLeft = pOB; + ExprSetProperty(pOB, EP_FullSize); +} + /* ** Check to see if a function is usable according to current access ** rules: @@ -108684,6 +110374,7 @@ SQLITE_PRIVATE void sqlite3ExprAssignVarNumber(Parse *pParse, Expr *pExpr, u32 n static SQLITE_NOINLINE void sqlite3ExprDeleteNN(sqlite3 *db, Expr *p){ assert( p!=0 ); assert( db!=0 ); +exprDeleteRestart: assert( !ExprUseUValue(p) || p->u.iValue>=0 ); assert( !ExprUseYWin(p) || !ExprUseYSub(p) ); assert( !ExprUseYWin(p) || p->y.pWin!=0 || db->mallocFailed ); @@ -108699,7 +110390,6 @@ static SQLITE_NOINLINE void sqlite3ExprDeleteNN(sqlite3 *db, Expr *p){ if( !ExprHasProperty(p, (EP_TokenOnly|EP_Leaf)) ){ /* The Expr.x union is never used at the same time as Expr.pRight */ assert( (ExprUseXList(p) && p->x.pList==0) || p->pRight==0 ); - if( p->pLeft && p->op!=TK_SELECT_COLUMN ) sqlite3ExprDeleteNN(db, p->pLeft); if( p->pRight ){ assert( !ExprHasProperty(p, EP_WinFunc) ); sqlite3ExprDeleteNN(db, p->pRight); @@ -108714,6 +110404,19 @@ static SQLITE_NOINLINE void sqlite3ExprDeleteNN(sqlite3 *db, Expr *p){ } #endif } + if( p->pLeft && p->op!=TK_SELECT_COLUMN ){ + Expr *pLeft = p->pLeft; + if( !ExprHasProperty(p, EP_Static) + && !ExprHasProperty(pLeft, EP_Static) + ){ + /* Avoid unnecessary recursion on unary operators */ + sqlite3DbNNFreeNN(db, p); + p = pLeft; + goto exprDeleteRestart; + }else{ + sqlite3ExprDeleteNN(db, pLeft); + } + } } if( !ExprHasProperty(p, EP_Static) ){ sqlite3DbNNFreeNN(db, p); @@ -108722,6 +110425,9 @@ static SQLITE_NOINLINE void sqlite3ExprDeleteNN(sqlite3 *db, Expr *p){ SQLITE_PRIVATE void sqlite3ExprDelete(sqlite3 *db, Expr *p){ if( p ) sqlite3ExprDeleteNN(db, p); } +SQLITE_PRIVATE void sqlite3ExprDeleteGeneric(sqlite3 *db, void *p){ + if( ALWAYS(p) ) sqlite3ExprDeleteNN(db, (Expr*)p); +} /* ** Clear both elements of an OnOrUsing object @@ -108743,13 +110449,11 @@ SQLITE_PRIVATE void sqlite3ClearOnOrUsing(sqlite3 *db, OnOrUsing *p){ ** ** The pExpr might be deleted immediately on an OOM error. ** -** The deferred delete is (currently) implemented by adding the -** pExpr to the pParse->pConstExpr list with a register number of 0. +** Return 0 if the delete was successfully deferred. Return non-zero +** if the delete happened immediately because of an OOM. */ -SQLITE_PRIVATE void sqlite3ExprDeferredDelete(Parse *pParse, Expr *pExpr){ - sqlite3ParserAddCleanup(pParse, - (void(*)(sqlite3*,void*))sqlite3ExprDelete, - pExpr); +SQLITE_PRIVATE int sqlite3ExprDeferredDelete(Parse *pParse, Expr *pExpr){ + return 0==sqlite3ParserAddCleanup(pParse, sqlite3ExprDeleteGeneric, pExpr); } /* Invoke sqlite3RenameExprUnmap() and sqlite3ExprDelete() on the @@ -108814,11 +110518,7 @@ static int dupedExprStructSize(const Expr *p, int flags){ assert( flags==EXPRDUP_REDUCE || flags==0 ); /* Only one flag value allowed */ assert( EXPR_FULLSIZE<=0xfff ); assert( (0xfff & (EP_Reduced|EP_TokenOnly))==0 ); - if( 0==flags || p->op==TK_SELECT_COLUMN -#ifndef SQLITE_OMIT_WINDOWFUNC - || ExprHasProperty(p, EP_WinFunc) -#endif - ){ + if( 0==flags || ExprHasProperty(p, EP_FullSize) ){ nSize = EXPR_FULLSIZE; }else{ assert( !ExprHasProperty(p, EP_TokenOnly|EP_Reduced) ); @@ -108849,56 +110549,93 @@ static int dupedExprNodeSize(const Expr *p, int flags){ /* ** Return the number of bytes required to create a duplicate of the -** expression passed as the first argument. The second argument is a -** mask containing EXPRDUP_XXX flags. +** expression passed as the first argument. ** ** The value returned includes space to create a copy of the Expr struct ** itself and the buffer referred to by Expr.u.zToken, if any. ** -** If the EXPRDUP_REDUCE flag is set, then the return value includes -** space to duplicate all Expr nodes in the tree formed by Expr.pLeft -** and Expr.pRight variables (but not for any structures pointed to or -** descended from the Expr.x.pList or Expr.x.pSelect variables). +** The return value includes space to duplicate all Expr nodes in the +** tree formed by Expr.pLeft and Expr.pRight, but not any other +** substructure such as Expr.x.pList, Expr.x.pSelect, and Expr.y.pWin. */ -static int dupedExprSize(const Expr *p, int flags){ - int nByte = 0; - if( p ){ - nByte = dupedExprNodeSize(p, flags); - if( flags&EXPRDUP_REDUCE ){ - nByte += dupedExprSize(p->pLeft, flags) + dupedExprSize(p->pRight, flags); - } - } +static int dupedExprSize(const Expr *p){ + int nByte; + assert( p!=0 ); + nByte = dupedExprNodeSize(p, EXPRDUP_REDUCE); + if( p->pLeft ) nByte += dupedExprSize(p->pLeft); + if( p->pRight ) nByte += dupedExprSize(p->pRight); + assert( nByte==ROUND8(nByte) ); return nByte; } /* -** This function is similar to sqlite3ExprDup(), except that if pzBuffer -** is not NULL then *pzBuffer is assumed to point to a buffer large enough -** to store the copy of expression p, the copies of p->u.zToken -** (if applicable), and the copies of the p->pLeft and p->pRight expressions, -** if any. Before returning, *pzBuffer is set to the first byte past the -** portion of the buffer copied into by this function. +** An EdupBuf is a memory allocation used to stored multiple Expr objects +** together with their Expr.zToken content. This is used to help implement +** compression while doing sqlite3ExprDup(). The top-level Expr does the +** allocation for itself and many of its decendents, then passes an instance +** of the structure down into exprDup() so that they decendents can have +** access to that memory. */ -static Expr *exprDup(sqlite3 *db, const Expr *p, int dupFlags, u8 **pzBuffer){ +typedef struct EdupBuf EdupBuf; +struct EdupBuf { + u8 *zAlloc; /* Memory space available for storage */ +#ifdef SQLITE_DEBUG + u8 *zEnd; /* First byte past the end of memory */ +#endif +}; + +/* +** This function is similar to sqlite3ExprDup(), except that if pEdupBuf +** is not NULL then it points to memory that can be used to store a copy +** of the input Expr p together with its p->u.zToken (if any). pEdupBuf +** is updated with the new buffer tail prior to returning. +*/ +static Expr *exprDup( + sqlite3 *db, /* Database connection (for memory allocation) */ + const Expr *p, /* Expr tree to be duplicated */ + int dupFlags, /* EXPRDUP_REDUCE for compression. 0 if not */ + EdupBuf *pEdupBuf /* Preallocated storage space, or NULL */ +){ Expr *pNew; /* Value to return */ - u8 *zAlloc; /* Memory space from which to build Expr object */ + EdupBuf sEdupBuf; /* Memory space from which to build Expr object */ u32 staticFlag; /* EP_Static if space not obtained from malloc */ + int nToken = -1; /* Space needed for p->u.zToken. -1 means unknown */ assert( db!=0 ); assert( p ); assert( dupFlags==0 || dupFlags==EXPRDUP_REDUCE ); - assert( pzBuffer==0 || dupFlags==EXPRDUP_REDUCE ); + assert( pEdupBuf==0 || dupFlags==EXPRDUP_REDUCE ); /* Figure out where to write the new Expr structure. */ - if( pzBuffer ){ - zAlloc = *pzBuffer; + if( pEdupBuf ){ + sEdupBuf.zAlloc = pEdupBuf->zAlloc; +#ifdef SQLITE_DEBUG + sEdupBuf.zEnd = pEdupBuf->zEnd; +#endif staticFlag = EP_Static; - assert( zAlloc!=0 ); + assert( sEdupBuf.zAlloc!=0 ); + assert( dupFlags==EXPRDUP_REDUCE ); }else{ - zAlloc = sqlite3DbMallocRawNN(db, dupedExprSize(p, dupFlags)); + int nAlloc; + if( dupFlags ){ + nAlloc = dupedExprSize(p); + }else if( !ExprHasProperty(p, EP_IntValue) && p->u.zToken ){ + nToken = sqlite3Strlen30NN(p->u.zToken)+1; + nAlloc = ROUND8(EXPR_FULLSIZE + nToken); + }else{ + nToken = 0; + nAlloc = ROUND8(EXPR_FULLSIZE); + } + assert( nAlloc==ROUND8(nAlloc) ); + sEdupBuf.zAlloc = sqlite3DbMallocRawNN(db, nAlloc); +#ifdef SQLITE_DEBUG + sEdupBuf.zEnd = sEdupBuf.zAlloc ? sEdupBuf.zAlloc+nAlloc : 0; +#endif + staticFlag = 0; } - pNew = (Expr *)zAlloc; + pNew = (Expr *)sEdupBuf.zAlloc; + assert( EIGHT_BYTE_ALIGNMENT(pNew) ); if( pNew ){ /* Set nNewSize to the size allocated for the structure pointed to @@ -108907,22 +110644,27 @@ static Expr *exprDup(sqlite3 *db, const Expr *p, int dupFlags, u8 **pzBuffer){ ** by the copy of the p->u.zToken string (if any). */ const unsigned nStructSize = dupedExprStructSize(p, dupFlags); - const int nNewSize = nStructSize & 0xfff; - int nToken; - if( !ExprHasProperty(p, EP_IntValue) && p->u.zToken ){ - nToken = sqlite3Strlen30(p->u.zToken) + 1; - }else{ - nToken = 0; + int nNewSize = nStructSize & 0xfff; + if( nToken<0 ){ + if( !ExprHasProperty(p, EP_IntValue) && p->u.zToken ){ + nToken = sqlite3Strlen30(p->u.zToken) + 1; + }else{ + nToken = 0; + } } if( dupFlags ){ + assert( (int)(sEdupBuf.zEnd - sEdupBuf.zAlloc) >= nNewSize+nToken ); assert( ExprHasProperty(p, EP_Reduced)==0 ); - memcpy(zAlloc, p, nNewSize); + memcpy(sEdupBuf.zAlloc, p, nNewSize); }else{ u32 nSize = (u32)exprStructSize(p); - memcpy(zAlloc, p, nSize); + assert( (int)(sEdupBuf.zEnd - sEdupBuf.zAlloc) >= + (int)EXPR_FULLSIZE+nToken ); + memcpy(sEdupBuf.zAlloc, p, nSize); if( nSizeu.zToken string, if any. */ - if( nToken ){ - char *zToken = pNew->u.zToken = (char*)&zAlloc[nNewSize]; + assert( nToken>=0 ); + if( nToken>0 ){ + char *zToken = pNew->u.zToken = (char*)&sEdupBuf.zAlloc[nNewSize]; memcpy(zToken, p->u.zToken, nToken); + nNewSize += nToken; } + sEdupBuf.zAlloc += ROUND8(nNewSize); + + if( ((p->flags|pNew->flags)&(EP_TokenOnly|EP_Leaf))==0 ){ - if( 0==((p->flags|pNew->flags) & (EP_TokenOnly|EP_Leaf)) ){ /* Fill in the pNew->x.pSelect or pNew->x.pList member. */ if( ExprUseXSelect(p) ){ pNew->x.pSelect = sqlite3SelectDup(db, p->x.pSelect, dupFlags); }else{ - pNew->x.pList = sqlite3ExprListDup(db, p->x.pList, dupFlags); + pNew->x.pList = sqlite3ExprListDup(db, p->x.pList, + p->op!=TK_ORDER ? dupFlags : 0); } - } - /* Fill in pNew->pLeft and pNew->pRight. */ - if( ExprHasProperty(pNew, EP_Reduced|EP_TokenOnly|EP_WinFunc) ){ - zAlloc += dupedExprNodeSize(p, dupFlags); - if( !ExprHasProperty(pNew, EP_TokenOnly|EP_Leaf) ){ - pNew->pLeft = p->pLeft ? - exprDup(db, p->pLeft, EXPRDUP_REDUCE, &zAlloc) : 0; - pNew->pRight = p->pRight ? - exprDup(db, p->pRight, EXPRDUP_REDUCE, &zAlloc) : 0; - } #ifndef SQLITE_OMIT_WINDOWFUNC if( ExprHasProperty(p, EP_WinFunc) ){ pNew->y.pWin = sqlite3WindowDup(db, pNew, p->y.pWin); assert( ExprHasProperty(pNew, EP_WinFunc) ); } #endif /* SQLITE_OMIT_WINDOWFUNC */ - if( pzBuffer ){ - *pzBuffer = zAlloc; - } - }else{ - if( !ExprHasProperty(p, EP_TokenOnly|EP_Leaf) ){ - if( pNew->op==TK_SELECT_COLUMN ){ + + /* Fill in pNew->pLeft and pNew->pRight. */ + if( dupFlags ){ + if( p->op==TK_SELECT_COLUMN ){ + pNew->pLeft = p->pLeft; + assert( p->pRight==0 + || p->pRight==p->pLeft + || ExprHasProperty(p->pLeft, EP_Subquery) ); + }else{ + pNew->pLeft = p->pLeft ? + exprDup(db, p->pLeft, EXPRDUP_REDUCE, &sEdupBuf) : 0; + } + pNew->pRight = p->pRight ? + exprDup(db, p->pRight, EXPRDUP_REDUCE, &sEdupBuf) : 0; + }else{ + if( p->op==TK_SELECT_COLUMN ){ pNew->pLeft = p->pLeft; - assert( p->pRight==0 || p->pRight==p->pLeft - || ExprHasProperty(p->pLeft, EP_Subquery) ); + assert( p->pRight==0 + || p->pRight==p->pLeft + || ExprHasProperty(p->pLeft, EP_Subquery) ); }else{ pNew->pLeft = sqlite3ExprDup(db, p->pLeft, 0); } @@ -108980,6 +110728,8 @@ static Expr *exprDup(sqlite3 *db, const Expr *p, int dupFlags, u8 **pzBuffer){ } } } + if( pEdupBuf ) memcpy(pEdupBuf, &sEdupBuf, sizeof(sEdupBuf)); + assert( sEdupBuf.zAlloc <= sEdupBuf.zEnd ); return pNew; } @@ -109139,17 +110889,19 @@ SQLITE_PRIVATE SrcList *sqlite3SrcListDup(sqlite3 *db, const SrcList *p, int fla pNewItem->iCursor = pOldItem->iCursor; pNewItem->addrFillSub = pOldItem->addrFillSub; pNewItem->regReturn = pOldItem->regReturn; + pNewItem->regResult = pOldItem->regResult; if( pNewItem->fg.isIndexedBy ){ pNewItem->u1.zIndexedBy = sqlite3DbStrDup(db, pOldItem->u1.zIndexedBy); + }else if( pNewItem->fg.isTabFunc ){ + pNewItem->u1.pFuncArg = + sqlite3ExprListDup(db, pOldItem->u1.pFuncArg, flags); + }else{ + pNewItem->u1.nRow = pOldItem->u1.nRow; } pNewItem->u2 = pOldItem->u2; if( pNewItem->fg.isCte ){ pNewItem->u2.pCteUse->nUse++; } - if( pNewItem->fg.isTabFunc ){ - pNewItem->u1.pFuncArg = - sqlite3ExprListDup(db, pOldItem->u1.pFuncArg, flags); - } pTab = pNewItem->pTab = pOldItem->pTab; if( pTab ){ pTab->nTabRef++; @@ -109244,11 +110996,7 @@ SQLITE_PRIVATE Select *sqlite3SelectDup(sqlite3 *db, const Select *p, int flags) ** initially NULL, then create a new expression list. ** ** The pList argument must be either NULL or a pointer to an ExprList -** obtained from a prior call to sqlite3ExprListAppend(). This routine -** may not be used with an ExprList obtained from sqlite3ExprListDup(). -** Reason: This routine assumes that the number of slots in pList->a[] -** is a power of two. That is true for sqlite3ExprListAppend() returns -** but is not necessarily true from the return value of sqlite3ExprListDup(). +** obtained from a prior call to sqlite3ExprListAppend(). ** ** If a memory allocation error occurs, the entire list is freed and ** NULL is returned. If non-NULL is returned, then it is guaranteed @@ -109513,6 +111261,9 @@ static SQLITE_NOINLINE void exprListDeleteNN(sqlite3 *db, ExprList *pList){ SQLITE_PRIVATE void sqlite3ExprListDelete(sqlite3 *db, ExprList *pList){ if( pList ) exprListDeleteNN(db, pList); } +SQLITE_PRIVATE void sqlite3ExprListDeleteGeneric(sqlite3 *db, void *pList){ + if( ALWAYS(pList) ) exprListDeleteNN(db, (ExprList*)pList); +} /* ** Return the bitwise-OR of all Expr.flags fields in the given @@ -109616,6 +111367,54 @@ SQLITE_PRIVATE Expr *sqlite3ExprSimplifiedAndOr(Expr *pExpr){ return pExpr; } +/* +** pExpr is a TK_FUNCTION node. Try to determine whether or not the +** function is a constant function. A function is constant if all of +** the following are true: +** +** (1) It is a scalar function (not an aggregate or window function) +** (2) It has either the SQLITE_FUNC_CONSTANT or SQLITE_FUNC_SLOCHNG +** property. +** (3) All of its arguments are constants +** +** This routine sets pWalker->eCode to 0 if pExpr is not a constant. +** It makes no changes to pWalker->eCode if pExpr is constant. In +** every case, it returns WRC_Abort. +** +** Called as a service subroutine from exprNodeIsConstant(). +*/ +static SQLITE_NOINLINE int exprNodeIsConstantFunction( + Walker *pWalker, + Expr *pExpr +){ + int n; /* Number of arguments */ + ExprList *pList; /* List of arguments */ + FuncDef *pDef; /* The function */ + sqlite3 *db; /* The database */ + + assert( pExpr->op==TK_FUNCTION ); + if( ExprHasProperty(pExpr, EP_TokenOnly) + || (pList = pExpr->x.pList)==0 + ){; + n = 0; + }else{ + n = pList->nExpr; + sqlite3WalkExprList(pWalker, pList); + if( pWalker->eCode==0 ) return WRC_Abort; + } + db = pWalker->pParse->db; + pDef = sqlite3FindFunction(db, pExpr->u.zToken, n, ENC(db), 0); + if( pDef==0 + || pDef->xFinalize!=0 + || (pDef->funcFlags & (SQLITE_FUNC_CONSTANT|SQLITE_FUNC_SLOCHNG))==0 + || ExprHasProperty(pExpr, EP_WinFunc) + ){ + pWalker->eCode = 0; + return WRC_Abort; + } + return WRC_Prune; +} + /* ** These routines are Walker callbacks used to check expressions to @@ -109644,6 +111443,7 @@ SQLITE_PRIVATE Expr *sqlite3ExprSimplifiedAndOr(Expr *pExpr){ ** malformed schema error. */ static int exprNodeIsConstant(Walker *pWalker, Expr *pExpr){ + assert( pWalker->eCode>0 ); /* If pWalker->eCode is 2 then any term of the expression that comes from ** the ON or USING clauses of an outer join disqualifies the expression @@ -109663,6 +111463,8 @@ static int exprNodeIsConstant(Walker *pWalker, Expr *pExpr){ ){ if( pWalker->eCode==5 ) ExprSetProperty(pExpr, EP_FromDDL); return WRC_Continue; + }else if( pWalker->pParse ){ + return exprNodeIsConstantFunction(pWalker, pExpr); }else{ pWalker->eCode = 0; return WRC_Abort; @@ -109691,9 +111493,11 @@ static int exprNodeIsConstant(Walker *pWalker, Expr *pExpr){ case TK_IF_NULL_ROW: case TK_REGISTER: case TK_DOT: + case TK_RAISE: testcase( pExpr->op==TK_REGISTER ); testcase( pExpr->op==TK_IF_NULL_ROW ); testcase( pExpr->op==TK_DOT ); + testcase( pExpr->op==TK_RAISE ); pWalker->eCode = 0; return WRC_Abort; case TK_VARIABLE: @@ -109715,15 +111519,15 @@ static int exprNodeIsConstant(Walker *pWalker, Expr *pExpr){ return WRC_Continue; } } -static int exprIsConst(Expr *p, int initFlag, int iCur){ +static int exprIsConst(Parse *pParse, Expr *p, int initFlag){ Walker w; w.eCode = initFlag; + w.pParse = pParse; w.xExprCallback = exprNodeIsConstant; w.xSelectCallback = sqlite3SelectWalkFail; #ifdef SQLITE_DEBUG w.xSelectCallback2 = sqlite3SelectWalkAssert2; #endif - w.u.iCur = iCur; sqlite3WalkExpr(&w, p); return w.eCode; } @@ -109735,9 +111539,15 @@ static int exprIsConst(Expr *p, int initFlag, int iCur){ ** For the purposes of this function, a double-quoted string (ex: "abc") ** is considered a variable but a single-quoted string (ex: 'abc') is ** a constant. +** +** The pParse parameter may be NULL. But if it is NULL, there is no way +** to determine if function calls are constant or not, and hence all +** function calls will be considered to be non-constant. If pParse is +** not NULL, then a function call might be constant, depending on the +** function and on its parameters. */ -SQLITE_PRIVATE int sqlite3ExprIsConstant(Expr *p){ - return exprIsConst(p, 1, 0); +SQLITE_PRIVATE int sqlite3ExprIsConstant(Parse *pParse, Expr *p){ + return exprIsConst(pParse, p, 1); } /* @@ -109753,8 +111563,24 @@ SQLITE_PRIVATE int sqlite3ExprIsConstant(Expr *p){ ** can be added to the pParse->pConstExpr list and evaluated once when ** the prepared statement starts up. See sqlite3ExprCodeRunJustOnce(). */ -SQLITE_PRIVATE int sqlite3ExprIsConstantNotJoin(Expr *p){ - return exprIsConst(p, 2, 0); +static int sqlite3ExprIsConstantNotJoin(Parse *pParse, Expr *p){ + return exprIsConst(pParse, p, 2); +} + +/* +** This routine examines sub-SELECT statements as an expression is being +** walked as part of sqlite3ExprIsTableConstant(). Sub-SELECTs are considered +** constant as long as they are uncorrelated - meaning that they do not +** contain any terms from outer contexts. +*/ +static int exprSelectWalkTableConstant(Walker *pWalker, Select *pSelect){ + assert( pSelect!=0 ); + assert( pWalker->eCode==3 || pWalker->eCode==0 ); + if( (pSelect->selFlags & SF_Correlated)!=0 ){ + pWalker->eCode = 0; + return WRC_Abort; + } + return WRC_Prune; } /* @@ -109762,9 +111588,26 @@ SQLITE_PRIVATE int sqlite3ExprIsConstantNotJoin(Expr *p){ ** for any single row of the table with cursor iCur. In other words, the ** expression must not refer to any non-deterministic function nor any ** table other than iCur. +** +** Consider uncorrelated subqueries to be constants if the bAllowSubq +** parameter is true. */ -SQLITE_PRIVATE int sqlite3ExprIsTableConstant(Expr *p, int iCur){ - return exprIsConst(p, 3, iCur); +static int sqlite3ExprIsTableConstant(Expr *p, int iCur, int bAllowSubq){ + Walker w; + w.eCode = 3; + w.pParse = 0; + w.xExprCallback = exprNodeIsConstant; + if( bAllowSubq ){ + w.xSelectCallback = exprSelectWalkTableConstant; + }else{ + w.xSelectCallback = sqlite3SelectWalkFail; +#ifdef SQLITE_DEBUG + w.xSelectCallback2 = sqlite3SelectWalkAssert2; +#endif + } + w.u.iCur = iCur; + sqlite3WalkExpr(&w, p); + return w.eCode; } /* @@ -109782,7 +111625,10 @@ SQLITE_PRIVATE int sqlite3ExprIsTableConstant(Expr *p, int iCur){ ** ** (1) pExpr cannot refer to any table other than pSrc->iCursor. ** -** (2) pExpr cannot use subqueries or non-deterministic functions. +** (2a) pExpr cannot use subqueries unless the bAllowSubq parameter is +** true and the subquery is non-correlated +** +** (2b) pExpr cannot use non-deterministic functions. ** ** (3) pSrc cannot be part of the left operand for a RIGHT JOIN. ** (Is there some way to relax this constraint?) @@ -109811,7 +111657,8 @@ SQLITE_PRIVATE int sqlite3ExprIsTableConstant(Expr *p, int iCur){ SQLITE_PRIVATE int sqlite3ExprIsSingleTableConstraint( Expr *pExpr, /* The constraint */ const SrcList *pSrcList, /* Complete FROM clause */ - int iSrc /* Which element of pSrcList to use */ + int iSrc, /* Which element of pSrcList to use */ + int bAllowSubq /* Allow non-correlated subqueries */ ){ const SrcItem *pSrc = &pSrcList->a[iSrc]; if( pSrc->fg.jointype & JT_LTORJ ){ @@ -109836,7 +111683,8 @@ SQLITE_PRIVATE int sqlite3ExprIsSingleTableConstraint( } } } - return sqlite3ExprIsTableConstant(pExpr, pSrc->iCursor); /* rules (1), (2) */ + /* Rules (1), (2a), and (2b) handled by the following: */ + return sqlite3ExprIsTableConstant(pExpr, pSrc->iCursor, bAllowSubq); } @@ -109921,7 +111769,7 @@ SQLITE_PRIVATE int sqlite3ExprIsConstantOrGroupBy(Parse *pParse, Expr *p, ExprLi */ SQLITE_PRIVATE int sqlite3ExprIsConstantOrFunction(Expr *p, u8 isInit){ assert( isInit==0 || isInit==1 ); - return exprIsConst(p, 4+isInit, 0); + return exprIsConst(0, p, 4+isInit); } #ifdef SQLITE_ENABLE_CURSOR_HINTS @@ -110011,10 +111859,14 @@ SQLITE_PRIVATE int sqlite3ExprCanBeNull(const Expr *p){ return 0; case TK_COLUMN: assert( ExprUseYTab(p) ); - return ExprHasProperty(p, EP_CanBeNull) || - p->y.pTab==0 || /* Reference to column of index on expression */ - (p->iColumn>=0 + return ExprHasProperty(p, EP_CanBeNull) + || NEVER(p->y.pTab==0) /* Reference to column of index on expr */ +#ifdef SQLITE_ALLOW_ROWID_IN_VIEW + || (p->iColumn==XN_ROWID && IsView(p->y.pTab)) +#endif + || (p->iColumn>=0 && p->y.pTab->aCol!=0 /* Possible due to prior error */ + && ALWAYS(p->iColumny.pTab->nCol) && p->y.pTab->aCol[p->iColumn].notNull==0); default: return 1; @@ -110074,6 +111926,27 @@ SQLITE_PRIVATE int sqlite3IsRowid(const char *z){ return 0; } +/* +** Return a pointer to a buffer containing a usable rowid alias for table +** pTab. An alias is usable if there is not an explicit user-defined column +** of the same name. +*/ +SQLITE_PRIVATE const char *sqlite3RowidAlias(Table *pTab){ + const char *azOpt[] = {"_ROWID_", "ROWID", "OID"}; + int ii; + assert( VisibleRowid(pTab) ); + for(ii=0; iinCol; iCol++){ + if( sqlite3_stricmp(azOpt[ii], pTab->aCol[iCol].zCnName)==0 ) break; + } + if( iCol==pTab->nCol ){ + return azOpt[ii]; + } + } + return 0; +} + /* ** pX is the RHS of an IN operator. If pX is a SELECT statement ** that can be simplified to a direct table access, then return @@ -110144,13 +112017,13 @@ static void sqlite3SetHasNullFlag(Vdbe *v, int iCur, int regHasNull){ ** The argument is an IN operator with a list (not a subquery) on the ** right-hand side. Return TRUE if that list is constant. */ -static int sqlite3InRhsIsConstant(Expr *pIn){ +static int sqlite3InRhsIsConstant(Parse *pParse, Expr *pIn){ Expr *pLHS; int res; assert( !ExprHasProperty(pIn, EP_xIsSelect) ); pLHS = pIn->pLeft; pIn->pLeft = 0; - res = sqlite3ExprIsConstant(pIn); + res = sqlite3ExprIsConstant(pParse, pIn); pIn->pLeft = pLHS; return res; } @@ -110419,7 +112292,7 @@ SQLITE_PRIVATE int sqlite3FindInIndex( if( eType==0 && (inFlags & IN_INDEX_NOOP_OK) && ExprUseXList(pX) - && (!sqlite3InRhsIsConstant(pX) || pX->x.pList->nExpr<=2) + && (!sqlite3InRhsIsConstant(pParse,pX) || pX->x.pList->nExpr<=2) ){ pParse->nTab--; /* Back out the allocation of the unused cursor */ iTab = -1; /* Cursor is not allocated */ @@ -110702,7 +112575,7 @@ SQLITE_PRIVATE void sqlite3CodeRhsOfIN( ** this code only executes once. Because for a non-constant ** expression we need to rerun this code each time. */ - if( addrOnce && !sqlite3ExprIsConstant(pE2) ){ + if( addrOnce && !sqlite3ExprIsConstant(pParse, pE2) ){ sqlite3VdbeChangeToNoop(v, addrOnce-1); sqlite3VdbeChangeToNoop(v, addrOnce); ExprClearProperty(pExpr, EP_Subrtn); @@ -111611,6 +113484,41 @@ static SQLITE_NOINLINE int sqlite3IndexedExprLookup( } +/* +** Expresion pExpr is guaranteed to be a TK_COLUMN or equivalent. This +** function checks the Parse.pIdxPartExpr list to see if this column +** can be replaced with a constant value. If so, it generates code to +** put the constant value in a register (ideally, but not necessarily, +** register iTarget) and returns the register number. +** +** Or, if the TK_COLUMN cannot be replaced by a constant, zero is +** returned. +*/ +static int exprPartidxExprLookup(Parse *pParse, Expr *pExpr, int iTarget){ + IndexedExpr *p; + for(p=pParse->pIdxPartExpr; p; p=p->pIENext){ + if( pExpr->iColumn==p->iIdxCol && pExpr->iTable==p->iDataCur ){ + Vdbe *v = pParse->pVdbe; + int addr = 0; + int ret; + + if( p->bMaybeNullRow ){ + addr = sqlite3VdbeAddOp1(v, OP_IfNullRow, p->iIdxCur); + } + ret = sqlite3ExprCodeTarget(pParse, p->pExpr, iTarget); + sqlite3VdbeAddOp4(pParse->pVdbe, OP_Affinity, ret, 1, 0, + (const char*)&p->aff, 1); + if( addr ){ + sqlite3VdbeJumpHere(v, addr); + sqlite3VdbeChangeP3(v, addr, ret); + } + return ret; + } + } + return 0; +} + + /* ** Generate code into the current Vdbe to evaluate the given ** expression. Attempt to store the results in register "target". @@ -111647,6 +113555,7 @@ SQLITE_PRIVATE int sqlite3ExprCodeTarget(Parse *pParse, Expr *pExpr, int target) assert( !ExprHasVVAProperty(pExpr,EP_Immutable) ); op = pExpr->op; } + assert( op!=TK_ORDER ); switch( op ){ case TK_AGG_COLUMN: { AggInfo *pAggInfo = pExpr->pAggInfo; @@ -111660,7 +113569,7 @@ SQLITE_PRIVATE int sqlite3ExprCodeTarget(Parse *pParse, Expr *pExpr, int target) #ifdef SQLITE_VDBE_COVERAGE /* Verify that the OP_Null above is exercised by tests ** tag-20230325-2 */ - sqlite3VdbeAddOp2(v, OP_NotNull, target, 1); + sqlite3VdbeAddOp3(v, OP_NotNull, target, 1, 20230325); VdbeCoverageNeverTaken(v); #endif break; @@ -111768,6 +113677,11 @@ SQLITE_PRIVATE int sqlite3ExprCodeTarget(Parse *pParse, Expr *pExpr, int target) iTab = pParse->iSelfTab - 1; } } + else if( pParse->pIdxPartExpr + && 0!=(r1 = exprPartidxExprLookup(pParse, pExpr, target)) + ){ + return r1; + } assert( ExprUseYTab(pExpr) ); assert( pExpr->y.pTab!=0 ); iReg = sqlite3ExprCodeGetColumn(pParse, pExpr->y.pTab, @@ -111825,12 +113739,6 @@ SQLITE_PRIVATE int sqlite3ExprCodeTarget(Parse *pParse, Expr *pExpr, int target) assert( pExpr->u.zToken!=0 ); assert( pExpr->u.zToken[0]!=0 ); sqlite3VdbeAddOp2(v, OP_Variable, pExpr->iColumn, target); - if( pExpr->u.zToken[1]!=0 ){ - const char *z = sqlite3VListNumToName(pParse->pVList, pExpr->iColumn); - assert( pExpr->u.zToken[0]=='?' || (z && !strcmp(pExpr->u.zToken, z)) ); - pParse->pVList[0] = 0; /* Indicate VList may no longer be enlarged */ - sqlite3VdbeAppendP4(v, (char*)z, P4_STATIC); - } return target; } case TK_REGISTER: { @@ -112004,7 +113912,9 @@ SQLITE_PRIVATE int sqlite3ExprCodeTarget(Parse *pParse, Expr *pExpr, int target) } #endif - if( ConstFactorOk(pParse) && sqlite3ExprIsConstantNotJoin(pExpr) ){ + if( ConstFactorOk(pParse) + && sqlite3ExprIsConstantNotJoin(pParse,pExpr) + ){ /* SQL functions can be expensive. So try to avoid running them ** multiple times if we know they always give the same result */ return sqlite3ExprCodeRunJustOnce(pParse, pExpr, -1); @@ -112035,7 +113945,7 @@ SQLITE_PRIVATE int sqlite3ExprCodeTarget(Parse *pParse, Expr *pExpr, int target) } for(i=0; ia[i].pExpr) ){ + if( i<32 && sqlite3ExprIsConstant(pParse, pFarg->a[i].pExpr) ){ testcase( i==31 ); constMask |= MASKBIT32(i); } @@ -112177,8 +114087,9 @@ SQLITE_PRIVATE int sqlite3ExprCodeTarget(Parse *pParse, Expr *pExpr, int target) if( !ExprHasProperty(pExpr, EP_Collate) ){ /* A TK_COLLATE Expr node without the EP_Collate tag is a so-called ** "SOFT-COLLATE" that is added to constraints that are pushed down - ** from outer queries into sub-queries by the push-down optimization. - ** Clear subtypes as subtypes may not cross a subquery boundary. + ** from outer queries into sub-queries by the WHERE-clause push-down + ** optimization. Clear subtypes as subtypes may not cross a subquery + ** boundary. */ assert( pExpr->pLeft ); sqlite3ExprCode(pParse, pExpr->pLeft, target); @@ -112428,7 +114339,7 @@ SQLITE_PRIVATE int sqlite3ExprCodeTarget(Parse *pParse, Expr *pExpr, int target) ** once. If no functions are involved, then factor the code out and put it at ** the end of the prepared statement in the initialization section. ** -** If regDest>=0 then the result is always stored in that register and the +** If regDest>0 then the result is always stored in that register and the ** result is not reusable. If regDest<0 then this routine is free to ** store the value wherever it wants. The register where the expression ** is stored is returned. When regDest<0, two identical expressions might @@ -112443,6 +114354,7 @@ SQLITE_PRIVATE int sqlite3ExprCodeRunJustOnce( ){ ExprList *p; assert( ConstFactorOk(pParse) ); + assert( regDest!=0 ); p = pParse->pConstExpr; if( regDest<0 && p ){ struct ExprList_item *pItem; @@ -112501,7 +114413,7 @@ SQLITE_PRIVATE int sqlite3ExprCodeTemp(Parse *pParse, Expr *pExpr, int *pReg){ if( ConstFactorOk(pParse) && ALWAYS(pExpr!=0) && pExpr->op!=TK_REGISTER - && sqlite3ExprIsConstantNotJoin(pExpr) + && sqlite3ExprIsConstantNotJoin(pParse, pExpr) ){ *pReg = 0; r2 = sqlite3ExprCodeRunJustOnce(pParse, pExpr, -1); @@ -112533,8 +114445,10 @@ SQLITE_PRIVATE void sqlite3ExprCode(Parse *pParse, Expr *pExpr, int target){ inReg = sqlite3ExprCodeTarget(pParse, pExpr, target); if( inReg!=target ){ u8 op; - if( ALWAYS(pExpr) - && (ExprHasProperty(pExpr,EP_Subquery) || pExpr->op==TK_REGISTER) + Expr *pX = sqlite3ExprSkipCollateAndLikely(pExpr); + testcase( pX!=pExpr ); + if( ALWAYS(pX) + && (ExprHasProperty(pX,EP_Subquery) || pX->op==TK_REGISTER) ){ op = OP_Copy; }else{ @@ -112563,7 +114477,7 @@ SQLITE_PRIVATE void sqlite3ExprCodeCopy(Parse *pParse, Expr *pExpr, int target){ ** might choose to code the expression at initialization time. */ SQLITE_PRIVATE void sqlite3ExprCodeFactorable(Parse *pParse, Expr *pExpr, int target){ - if( pParse->okConstFactor && sqlite3ExprIsConstantNotJoin(pExpr) ){ + if( pParse->okConstFactor && sqlite3ExprIsConstantNotJoin(pParse,pExpr) ){ sqlite3ExprCodeRunJustOnce(pParse, pExpr, target); }else{ sqlite3ExprCodeCopy(pParse, pExpr, target); @@ -112622,7 +114536,7 @@ SQLITE_PRIVATE int sqlite3ExprCodeExprList( sqlite3VdbeAddOp2(v, copyOp, j+srcReg-1, target+i); } }else if( (flags & SQLITE_ECEL_FACTOR)!=0 - && sqlite3ExprIsConstantNotJoin(pExpr) + && sqlite3ExprIsConstantNotJoin(pParse,pExpr) ){ sqlite3ExprCodeRunJustOnce(pParse, pExpr, target+i); }else{ @@ -113254,8 +115168,8 @@ SQLITE_PRIVATE int sqlite3ExprListCompare(const ExprList *pA, const ExprList *pB */ SQLITE_PRIVATE int sqlite3ExprCompareSkip(Expr *pA,Expr *pB, int iTab){ return sqlite3ExprCompare(0, - sqlite3ExprSkipCollateAndLikely(pA), - sqlite3ExprSkipCollateAndLikely(pB), + sqlite3ExprSkipCollate(pA), + sqlite3ExprSkipCollate(pB), iTab); } @@ -113727,6 +115641,12 @@ SQLITE_PRIVATE int sqlite3ReferencesSrcList(Parse *pParse, Expr *pExpr, SrcList assert( pExpr->op==TK_AGG_FUNCTION ); assert( ExprUseXList(pExpr) ); sqlite3WalkExprList(&w, pExpr->x.pList); + if( pExpr->pLeft ){ + assert( pExpr->pLeft->op==TK_ORDER ); + assert( ExprUseXList(pExpr->pLeft) ); + assert( pExpr->pLeft->x.pList!=0 ); + sqlite3WalkExprList(&w, pExpr->pLeft->x.pList); + } #ifndef SQLITE_OMIT_WINDOWFUNC if( ExprHasProperty(pExpr, EP_WinFunc) ){ sqlite3WalkExpr(&w, pExpr->y.pWin->pFilter); @@ -113767,9 +115687,8 @@ static int agginfoPersistExprCb(Walker *pWalker, Expr *pExpr){ && pAggInfo->aCol[iAgg].pCExpr==pExpr ){ pExpr = sqlite3ExprDup(db, pExpr, 0); - if( pExpr ){ + if( pExpr && !sqlite3ExprDeferredDelete(pParse, pExpr) ){ pAggInfo->aCol[iAgg].pCExpr = pExpr; - sqlite3ExprDeferredDelete(pParse, pExpr); } } }else{ @@ -113778,9 +115697,8 @@ static int agginfoPersistExprCb(Walker *pWalker, Expr *pExpr){ && pAggInfo->aFunc[iAgg].pFExpr==pExpr ){ pExpr = sqlite3ExprDup(db, pExpr, 0); - if( pExpr ){ + if( pExpr && !sqlite3ExprDeferredDelete(pParse, pExpr) ){ pAggInfo->aFunc[iAgg].pFExpr = pExpr; - sqlite3ExprDeferredDelete(pParse, pExpr); } } } @@ -113974,13 +115892,14 @@ static int analyzeAggregate(Walker *pWalker, Expr *pExpr){ case TK_AGG_FUNCTION: { if( (pNC->ncFlags & NC_InAggFunc)==0 && pWalker->walkerDepth==pExpr->op2 + && pExpr->pAggInfo==0 ){ /* Check to see if pExpr is a duplicate of another aggregate ** function that is already in the pAggInfo structure */ struct AggInfo_func *pItem = pAggInfo->aFunc; for(i=0; inFunc; i++, pItem++){ - if( pItem->pFExpr==pExpr ) break; + if( NEVER(pItem->pFExpr==pExpr) ) break; if( sqlite3ExprCompare(0, pItem->pFExpr, pExpr, -1)==0 ){ break; } @@ -113991,14 +115910,44 @@ static int analyzeAggregate(Walker *pWalker, Expr *pExpr){ u8 enc = ENC(pParse->db); i = addAggInfoFunc(pParse->db, pAggInfo); if( i>=0 ){ + int nArg; assert( !ExprHasProperty(pExpr, EP_xIsSelect) ); pItem = &pAggInfo->aFunc[i]; pItem->pFExpr = pExpr; assert( ExprUseUToken(pExpr) ); + nArg = pExpr->x.pList ? pExpr->x.pList->nExpr : 0; pItem->pFunc = sqlite3FindFunction(pParse->db, - pExpr->u.zToken, - pExpr->x.pList ? pExpr->x.pList->nExpr : 0, enc, 0); - if( pExpr->flags & EP_Distinct ){ + pExpr->u.zToken, nArg, enc, 0); + assert( pItem->bOBUnique==0 ); + if( pExpr->pLeft + && (pItem->pFunc->funcFlags & SQLITE_FUNC_NEEDCOLL)==0 + ){ + /* The NEEDCOLL test above causes any ORDER BY clause on + ** aggregate min() or max() to be ignored. */ + ExprList *pOBList; + assert( nArg>0 ); + assert( pExpr->pLeft->op==TK_ORDER ); + assert( ExprUseXList(pExpr->pLeft) ); + pItem->iOBTab = pParse->nTab++; + pOBList = pExpr->pLeft->x.pList; + assert( pOBList->nExpr>0 ); + assert( pItem->bOBUnique==0 ); + if( pOBList->nExpr==1 + && nArg==1 + && sqlite3ExprCompare(0,pOBList->a[0].pExpr, + pExpr->x.pList->a[0].pExpr,0)==0 + ){ + pItem->bOBPayload = 0; + pItem->bOBUnique = ExprHasProperty(pExpr, EP_Distinct); + }else{ + pItem->bOBPayload = 1; + } + pItem->bUseSubtype = + (pItem->pFunc->funcFlags & SQLITE_SUBTYPE)!=0; + }else{ + pItem->iOBTab = -1; + } + if( ExprHasProperty(pExpr, EP_Distinct) && !pItem->bOBUnique ){ pItem->iDistinct = pParse->nTab++; }else{ pItem->iDistinct = -1; @@ -114634,14 +116583,19 @@ SQLITE_PRIVATE void sqlite3AlterFinishAddColumn(Parse *pParse, Token *pColDef){ /* Verify that constraints are still satisfied */ if( pNew->pCheck!=0 || (pCol->notNull && (pCol->colFlags & COLFLAG_GENERATED)!=0) + || (pTab->tabFlags & TF_Strict)!=0 ){ sqlite3NestedParse(pParse, "SELECT CASE WHEN quick_check GLOB 'CHECK*'" " THEN raise(ABORT,'CHECK constraint failed')" + " WHEN quick_check GLOB 'non-* value in*'" + " THEN raise(ABORT,'type mismatch on DEFAULT')" " ELSE raise(ABORT,'NOT NULL constraint failed')" " END" " FROM pragma_quick_check(%Q,%Q)" - " WHERE quick_check GLOB 'CHECK*' OR quick_check GLOB 'NULL*'", + " WHERE quick_check GLOB 'CHECK*'" + " OR quick_check GLOB 'NULL*'" + " OR quick_check GLOB 'non-* value in*'", zTab, zDb ); } @@ -116445,7 +118399,12 @@ SQLITE_PRIVATE void sqlite3AlterDropColumn(Parse *pParse, SrcList *pSrc, const T if( i==pTab->iPKey ){ sqlite3VdbeAddOp2(v, OP_Null, 0, regOut); }else{ + char aff = pTab->aCol[i].affinity; + if( aff==SQLITE_AFF_REAL ){ + pTab->aCol[i].affinity = SQLITE_AFF_NUMERIC; + } sqlite3ExprCodeGetColumnOfTable(v, pTab, iCur, i, regOut); + pTab->aCol[i].affinity = aff; } nField++; } @@ -116756,9 +118715,9 @@ static void openStatTable( typedef struct StatAccum StatAccum; typedef struct StatSample StatSample; struct StatSample { - tRowcnt *anEq; /* sqlite_stat4.nEq */ tRowcnt *anDLt; /* sqlite_stat4.nDLt */ #ifdef SQLITE_ENABLE_STAT4 + tRowcnt *anEq; /* sqlite_stat4.nEq */ tRowcnt *anLt; /* sqlite_stat4.nLt */ union { i64 iRowid; /* Rowid in main table of the key */ @@ -116916,9 +118875,9 @@ static void statInit( /* Allocate the space required for the StatAccum object */ n = sizeof(*p) - + sizeof(tRowcnt)*nColUp /* StatAccum.anEq */ - + sizeof(tRowcnt)*nColUp; /* StatAccum.anDLt */ + + sizeof(tRowcnt)*nColUp; /* StatAccum.anDLt */ #ifdef SQLITE_ENABLE_STAT4 + n += sizeof(tRowcnt)*nColUp; /* StatAccum.anEq */ if( mxSample ){ n += sizeof(tRowcnt)*nColUp /* StatAccum.anLt */ + sizeof(StatSample)*(nCol+mxSample) /* StatAccum.aBest[], a[] */ @@ -116939,9 +118898,9 @@ static void statInit( p->nKeyCol = nKeyCol; p->nSkipAhead = 0; p->current.anDLt = (tRowcnt*)&p[1]; - p->current.anEq = &p->current.anDLt[nColUp]; #ifdef SQLITE_ENABLE_STAT4 + p->current.anEq = &p->current.anDLt[nColUp]; p->mxSample = p->nLimit==0 ? mxSample : 0; if( mxSample ){ u8 *pSpace; /* Allocated space not yet assigned */ @@ -117208,7 +119167,9 @@ static void statPush( if( p->nRow==0 ){ /* This is the first call to this function. Do initialization. */ +#ifdef SQLITE_ENABLE_STAT4 for(i=0; inCol; i++) p->current.anEq[i] = 1; +#endif }else{ /* Second and subsequent calls get processed here */ #ifdef SQLITE_ENABLE_STAT4 @@ -117217,15 +119178,17 @@ static void statPush( /* Update anDLt[], anLt[] and anEq[] to reflect the values that apply ** to the current row of the index. */ +#ifdef SQLITE_ENABLE_STAT4 for(i=0; icurrent.anEq[i]++; } +#endif for(i=iChng; inCol; i++){ p->current.anDLt[i]++; #ifdef SQLITE_ENABLE_STAT4 if( p->mxSample ) p->current.anLt[i] += p->current.anEq[i]; -#endif p->current.anEq[i] = 1; +#endif } } @@ -117359,7 +119322,9 @@ static void statGet( u64 iVal = (p->nRow + nDistinct - 1) / nDistinct; if( iVal==2 && p->nRow*10 <= nDistinct*11 ) iVal = 1; sqlite3_str_appendf(&sStat, " %llu", iVal); - assert( p->current.anEq[i] ); +#ifdef SQLITE_ENABLE_STAT4 + assert( p->current.anEq[i] || p->nRow==0 ); +#endif } sqlite3ResultStrAccum(context, &sStat); } @@ -117543,7 +119508,7 @@ static void analyzeOneTable( for(pIdx=pTab->pIndex; pIdx; pIdx=pIdx->pNext){ int nCol; /* Number of columns in pIdx. "N" */ - int addrRewind; /* Address of "OP_Rewind iIdxCur" */ + int addrGotoEnd; /* Address of "OP_Rewind iIdxCur" */ int addrNextRow; /* Address of "next_row:" */ const char *zIdxName; /* Name of the index */ int nColTest; /* Number of columns to test for changes */ @@ -117567,9 +119532,14 @@ static void analyzeOneTable( /* ** Pseudo-code for loop that calls stat_push(): ** - ** Rewind csr - ** if eof(csr) goto end_of_scan; ** regChng = 0 + ** Rewind csr + ** if eof(csr){ + ** stat_init() with count = 0; + ** goto end_of_scan; + ** } + ** count() + ** stat_init() ** goto chng_addr_0; ** ** next_row: @@ -117608,41 +119578,36 @@ static void analyzeOneTable( sqlite3VdbeSetP4KeyInfo(pParse, pIdx); VdbeComment((v, "%s", pIdx->zName)); - /* Invoke the stat_init() function. The arguments are: + /* Implementation of the following: ** + ** regChng = 0 + ** Rewind csr + ** if eof(csr){ + ** stat_init() with count = 0; + ** goto end_of_scan; + ** } + ** count() + ** stat_init() + ** goto chng_addr_0; + */ + assert( regTemp2==regStat+4 ); + sqlite3VdbeAddOp2(v, OP_Integer, db->nAnalysisLimit, regTemp2); + + /* Arguments to stat_init(): ** (1) the number of columns in the index including the rowid ** (or for a WITHOUT ROWID table, the number of PK columns), ** (2) the number of columns in the key without the rowid/pk - ** (3) estimated number of rows in the index, - */ + ** (3) estimated number of rows in the index. */ sqlite3VdbeAddOp2(v, OP_Integer, nCol, regStat+1); assert( regRowid==regStat+2 ); sqlite3VdbeAddOp2(v, OP_Integer, pIdx->nKeyCol, regRowid); -#ifdef SQLITE_ENABLE_STAT4 - if( OptimizationEnabled(db, SQLITE_Stat4) ){ - sqlite3VdbeAddOp2(v, OP_Count, iIdxCur, regTemp); - addrRewind = sqlite3VdbeAddOp1(v, OP_Rewind, iIdxCur); - VdbeCoverage(v); - }else -#endif - { - addrRewind = sqlite3VdbeAddOp1(v, OP_Rewind, iIdxCur); - VdbeCoverage(v); - sqlite3VdbeAddOp3(v, OP_Count, iIdxCur, regTemp, 1); - } - assert( regTemp2==regStat+4 ); - sqlite3VdbeAddOp2(v, OP_Integer, db->nAnalysisLimit, regTemp2); + sqlite3VdbeAddOp3(v, OP_Count, iIdxCur, regTemp, + OptimizationDisabled(db, SQLITE_Stat4)); sqlite3VdbeAddFunctionCall(pParse, 0, regStat+1, regStat, 4, &statInitFuncdef, 0); + addrGotoEnd = sqlite3VdbeAddOp1(v, OP_Rewind, iIdxCur); + VdbeCoverage(v); - /* Implementation of the following: - ** - ** Rewind csr - ** if eof(csr) goto end_of_scan; - ** regChng = 0 - ** goto next_push_0; - ** - */ sqlite3VdbeAddOp2(v, OP_Integer, 0, regChng); addrNextRow = sqlite3VdbeCurrentAddr(v); @@ -117749,6 +119714,12 @@ static void analyzeOneTable( } /* Add the entry to the stat1 table. */ + if( pIdx->pPartIdxWhere ){ + /* Partial indexes might get a zero-entry in sqlite_stat1. But + ** an empty table is omitted from sqlite_stat1. */ + sqlite3VdbeJumpHere(v, addrGotoEnd); + addrGotoEnd = 0; + } callStatGet(pParse, regStat, STAT_GET_STAT1, regStat1); assert( "BBB"[0]==SQLITE_AFF_TEXT ); sqlite3VdbeAddOp4(v, OP_MakeRecord, regTabname, 3, regTemp, "BBB", 0); @@ -117772,6 +119743,13 @@ static void analyzeOneTable( int addrIsNull; u8 seekOp = HasRowid(pTab) ? OP_NotExists : OP_NotFound; + /* No STAT4 data is generated if the number of rows is zero */ + if( addrGotoEnd==0 ){ + sqlite3VdbeAddOp2(v, OP_Cast, regStat1, SQLITE_AFF_INTEGER); + addrGotoEnd = sqlite3VdbeAddOp1(v, OP_IfNot, regStat1); + VdbeCoverage(v); + } + if( doOnce ){ int mxCol = nCol; Index *pX; @@ -117824,7 +119802,7 @@ static void analyzeOneTable( #endif /* SQLITE_ENABLE_STAT4 */ /* End of analysis */ - sqlite3VdbeJumpHere(v, addrRewind); + if( addrGotoEnd ) sqlite3VdbeJumpHere(v, addrGotoEnd); } @@ -118048,6 +120026,16 @@ static void decodeIntArray( while( z[0]!=0 && z[0]!=' ' ) z++; while( z[0]==' ' ) z++; } + + /* Set the bLowQual flag if the peak number of rows obtained + ** from a full equality match is so large that a full table scan + ** seems likely to be faster than using the index. + */ + if( aLog[0] > 66 /* Index has more than 100 rows */ + && aLog[0] <= aLog[nOut-1] /* And only a single value seen */ + ){ + pIndex->bLowQual = 1; + } } } @@ -119563,7 +121551,7 @@ SQLITE_PRIVATE void sqlite3FinishCoding(Parse *pParse){ } sqlite3VdbeAddOp0(v, OP_Halt); -#if SQLITE_USER_AUTHENTICATION +#if SQLITE_USER_AUTHENTICATION && !defined(SQLITE_OMIT_SHARED_CACHE) if( pParse->nTableLock>0 && db->init.busy==0 ){ sqlite3UserAuthInit(db); if( db->auth.authLevelpAinc ) sqlite3AutoincrementBegin(pParse); - /* Code constant expressions that where factored out of inner loops. - ** - ** The pConstExpr list might also contain expressions that we simply - ** want to keep around until the Parse object is deleted. Such - ** expressions have iConstExprReg==0. Do not generate code for - ** those expressions, of course. + /* Code constant expressions that were factored out of inner loops. */ if( pParse->pConstExpr ){ ExprList *pEL = pParse->pConstExpr; pParse->okConstFactor = 0; for(i=0; inExpr; i++){ - int iReg = pEL->a[i].u.iConstExprReg; - sqlite3ExprCode(pParse, pEL->a[i].pExpr, iReg); + assert( pEL->a[i].u.iConstExprReg>0 ); + sqlite3ExprCode(pParse, pEL->a[i].pExpr, pEL->a[i].u.iConstExprReg); } } @@ -120099,7 +122082,7 @@ SQLITE_PRIVATE void sqlite3ColumnSetExpr( */ SQLITE_PRIVATE Expr *sqlite3ColumnExpr(Table *pTab, Column *pCol){ if( pCol->iDflt==0 ) return 0; - if( NEVER(!IsOrdinaryTable(pTab)) ) return 0; + if( !IsOrdinaryTable(pTab) ) return 0; if( NEVER(pTab->u.tab.pDfltList==0) ) return 0; if( NEVER(pTab->u.tab.pDfltList->nExpriDflt) ) return 0; return pTab->u.tab.pDfltList->a[pCol->iDflt-1].pExpr; @@ -120252,6 +122235,9 @@ SQLITE_PRIVATE void sqlite3DeleteTable(sqlite3 *db, Table *pTable){ if( db->pnBytesFreed==0 && (--pTable->nTabRef)>0 ) return; deleteTable(db, pTable); } +SQLITE_PRIVATE void sqlite3DeleteTableGeneric(sqlite3 *db, void *pTable){ + sqlite3DeleteTable(db, (Table*)pTable); +} /* @@ -120786,20 +122772,14 @@ SQLITE_PRIVATE void sqlite3ColumnPropertiesFromName(Table *pTab, Column *pCol){ } #endif -/* -** Name of the special TEMP trigger used to implement RETURNING. The -** name begins with "sqlite_" so that it is guaranteed not to collide -** with any application-generated triggers. -*/ -#define RETURNING_TRIGGER_NAME "sqlite_returning" - /* ** Clean up the data structures associated with the RETURNING clause. */ -static void sqlite3DeleteReturning(sqlite3 *db, Returning *pRet){ +static void sqlite3DeleteReturning(sqlite3 *db, void *pArg){ + Returning *pRet = (Returning*)pArg; Hash *pHash; pHash = &(db->aDb[1].pSchema->trigHash); - sqlite3HashInsert(pHash, RETURNING_TRIGGER_NAME, 0); + sqlite3HashInsert(pHash, pRet->zName, 0); sqlite3ExprListDelete(db, pRet->pReturnEL); sqlite3DbFree(db, pRet); } @@ -120838,11 +122818,12 @@ SQLITE_PRIVATE void sqlite3AddReturning(Parse *pParse, ExprList *pList){ pParse->u1.pReturning = pRet; pRet->pParse = pParse; pRet->pReturnEL = pList; - sqlite3ParserAddCleanup(pParse, - (void(*)(sqlite3*,void*))sqlite3DeleteReturning, pRet); + sqlite3ParserAddCleanup(pParse, sqlite3DeleteReturning, pRet); testcase( pParse->earlyCleanup ); if( db->mallocFailed ) return; - pRet->retTrig.zName = RETURNING_TRIGGER_NAME; + sqlite3_snprintf(sizeof(pRet->zName), pRet->zName, + "sqlite_returning_%p", pParse); + pRet->retTrig.zName = pRet->zName; pRet->retTrig.op = TK_RETURNING; pRet->retTrig.tr_tm = TRIGGER_AFTER; pRet->retTrig.bReturning = 1; @@ -120853,9 +122834,9 @@ SQLITE_PRIVATE void sqlite3AddReturning(Parse *pParse, ExprList *pList){ pRet->retTStep.pTrig = &pRet->retTrig; pRet->retTStep.pExprList = pList; pHash = &(db->aDb[1].pSchema->trigHash); - assert( sqlite3HashFind(pHash, RETURNING_TRIGGER_NAME)==0 + assert( sqlite3HashFind(pHash, pRet->zName)==0 || pParse->nErr || pParse->ifNotExists ); - if( sqlite3HashInsert(pHash, RETURNING_TRIGGER_NAME, &pRet->retTrig) + if( sqlite3HashInsert(pHash, pRet->zName, &pRet->retTrig) ==&pRet->retTrig ){ sqlite3OomFault(db); } @@ -121036,7 +123017,8 @@ SQLITE_PRIVATE char sqlite3AffinityType(const char *zIn, Column *pCol){ assert( zIn!=0 ); while( zIn[0] ){ - h = (h<<8) + sqlite3UpperToLower[(*zIn)&0xff]; + u8 x = *(u8*)zIn; + h = (h<<8) + sqlite3UpperToLower[x]; zIn++; if( h==(('c'<<24)+('h'<<16)+('a'<<8)+'r') ){ /* CHAR */ aff = SQLITE_AFF_TEXT; @@ -122208,20 +124190,20 @@ SQLITE_PRIVATE void sqlite3EndTable( int regRowid; /* Rowid of the next row to insert */ int addrInsLoop; /* Top of the loop for inserting rows */ Table *pSelTab; /* A table that describes the SELECT results */ + int iCsr; /* Write cursor on the new table */ if( IN_SPECIAL_PARSE ){ pParse->rc = SQLITE_ERROR; pParse->nErr++; return; } + iCsr = pParse->nTab++; regYield = ++pParse->nMem; regRec = ++pParse->nMem; regRowid = ++pParse->nMem; - assert(pParse->nTab==1); sqlite3MayAbort(pParse); - sqlite3VdbeAddOp3(v, OP_OpenWrite, 1, pParse->regRoot, iDb); + sqlite3VdbeAddOp3(v, OP_OpenWrite, iCsr, pParse->regRoot, iDb); sqlite3VdbeChangeP5(v, OPFLAG_P2ISREG); - pParse->nTab = 2; addrTop = sqlite3VdbeCurrentAddr(v) + 1; sqlite3VdbeAddOp3(v, OP_InitCoroutine, regYield, 0, addrTop); if( pParse->nErr ) return; @@ -122242,11 +124224,11 @@ SQLITE_PRIVATE void sqlite3EndTable( VdbeCoverage(v); sqlite3VdbeAddOp3(v, OP_MakeRecord, dest.iSdst, dest.nSdst, regRec); sqlite3TableAffinity(v, p, 0); - sqlite3VdbeAddOp2(v, OP_NewRowid, 1, regRowid); - sqlite3VdbeAddOp3(v, OP_Insert, 1, regRec, regRowid); + sqlite3VdbeAddOp2(v, OP_NewRowid, iCsr, regRowid); + sqlite3VdbeAddOp3(v, OP_Insert, iCsr, regRec, regRowid); sqlite3VdbeGoto(v, addrInsLoop); sqlite3VdbeJumpHere(v, addrInsLoop); - sqlite3VdbeAddOp1(v, OP_Close, 1); + sqlite3VdbeAddOp1(v, OP_Close, iCsr); } /* Compute the complete text of the CREATE statement */ @@ -122299,6 +124281,14 @@ SQLITE_PRIVATE void sqlite3EndTable( /* Reparse everything to update our internal data structures */ sqlite3VdbeAddParseSchemaOp(v, iDb, sqlite3MPrintf(db, "tbl_name='%q' AND type!='trigger'", p->zName),0); + + /* Test for cycles in generated columns and illegal expressions + ** in CHECK constraints and in DEFAULT clauses. */ + if( p->tabFlags & TF_HasGenerated ){ + sqlite3VdbeAddOp4(v, OP_SqlExec, 0x0001, 0, 0, + sqlite3MPrintf(db, "SELECT*FROM\"%w\".\"%w\"", + db->aDb[iDb].zDbSName, p->zName), P4_DYNAMIC); + } } /* Add the table to the in-memory representation of the database. @@ -122375,9 +124365,12 @@ SQLITE_PRIVATE void sqlite3CreateView( ** on a view, even though views do not have rowids. The following flag ** setting fixes this problem. But the fix can be disabled by compiling ** with -DSQLITE_ALLOW_ROWID_IN_VIEW in case there are legacy apps that - ** depend upon the old buggy behavior. */ -#ifndef SQLITE_ALLOW_ROWID_IN_VIEW - p->tabFlags |= TF_NoVisibleRowid; + ** depend upon the old buggy behavior. The ability can also be toggled + ** using sqlite3_config(SQLITE_CONFIG_ROWID_IN_VIEW,...) */ +#ifdef SQLITE_ALLOW_ROWID_IN_VIEW + p->tabFlags |= sqlite3Config.mNoVisibleRowid; /* Optional. Allow by default */ +#else + p->tabFlags |= TF_NoVisibleRowid; /* Never allow rowid in view */ #endif sqlite3TwoPartName(pParse, pName1, pName2, &pName); @@ -124890,7 +126883,7 @@ SQLITE_PRIVATE void sqlite3Reindex(Parse *pParse, Token *pName1, Token *pName2){ if( iDb<0 ) return; z = sqlite3NameFromToken(db, pObjName); if( z==0 ) return; - zDb = db->aDb[iDb].zDbSName; + zDb = pName2->n ? db->aDb[iDb].zDbSName : 0; pTab = sqlite3FindTable(db, z, zDb); if( pTab ){ reindexTable(pParse, pTab, 0); @@ -124900,6 +126893,7 @@ SQLITE_PRIVATE void sqlite3Reindex(Parse *pParse, Token *pName1, Token *pName2){ pIndex = sqlite3FindIndex(db, z, zDb); sqlite3DbFree(db, z); if( pIndex ){ + iDb = sqlite3SchemaToIndex(db, pIndex->pTable->pSchema); sqlite3BeginWriteOperation(pParse, 0, iDb); sqlite3RefillIndex(pParse, pIndex, -1); return; @@ -125065,6 +127059,9 @@ SQLITE_PRIVATE void sqlite3WithDelete(sqlite3 *db, With *pWith){ sqlite3DbFree(db, pWith); } } +SQLITE_PRIVATE void sqlite3WithDeleteGeneric(sqlite3 *db, void *pWith){ + sqlite3WithDelete(db, (With*)pWith); +} #endif /* !defined(SQLITE_OMIT_CTE) */ /************** End of build.c ***********************************************/ @@ -127746,13 +129743,13 @@ SQLITE_PRIVATE void sqlite3QuoteValue(StrAccum *pStr, sqlite3_value *pValue){ double r1, r2; const char *zVal; r1 = sqlite3_value_double(pValue); - sqlite3_str_appendf(pStr, "%!.15g", r1); + sqlite3_str_appendf(pStr, "%!0.15g", r1); zVal = sqlite3_str_value(pStr); if( zVal ){ sqlite3AtoF(zVal, &r2, pStr->nChar, SQLITE_UTF8); if( r1!=r2 ){ sqlite3_str_reset(pStr); - sqlite3_str_appendf(pStr, "%!.20e", r1); + sqlite3_str_appendf(pStr, "%!0.20e", r1); } } break; @@ -127901,7 +129898,8 @@ static void hexFunc( *(z++) = hexdigits[c&0xf]; } *z = 0; - sqlite3_result_text(context, zHex, n*2, sqlite3_free); + sqlite3_result_text64(context, zHex, (u64)(z-zHex), + sqlite3_free, SQLITE_UTF8); } } @@ -128053,7 +130051,7 @@ static void replaceFunc( } if( zPattern[0]==0 ){ assert( sqlite3_value_type(argv[1])!=SQLITE_NULL ); - sqlite3_result_value(context, argv[0]); + sqlite3_result_text(context, (const char*)zStr, nStr, SQLITE_TRANSIENT); return; } nPattern = sqlite3_value_bytes(argv[1]); @@ -128195,6 +130193,81 @@ static void trimFunc( sqlite3_result_text(context, (char*)zIn, nIn, SQLITE_TRANSIENT); } +/* The core implementation of the CONCAT(...) and CONCAT_WS(SEP,...) +** functions. +** +** Return a string value that is the concatenation of all non-null +** entries in argv[]. Use zSep as the separator. +*/ +static void concatFuncCore( + sqlite3_context *context, + int argc, + sqlite3_value **argv, + int nSep, + const char *zSep +){ + i64 j, k, n = 0; + int i; + char *z; + for(i=0; i0 ){ + const char *v = (const char*)sqlite3_value_text(argv[i]); + if( v!=0 ){ + if( j>0 && nSep>0 ){ + memcpy(&z[j], zSep, nSep); + j += nSep; + } + memcpy(&z[j], v, k); + j += k; + } + } + } + z[j] = 0; + assert( j<=n ); + sqlite3_result_text64(context, z, j, sqlite3_free, SQLITE_UTF8); +} + +/* +** The CONCAT(...) function. Generate a string result that is the +** concatentation of all non-null arguments. +*/ +static void concatFunc( + sqlite3_context *context, + int argc, + sqlite3_value **argv +){ + concatFuncCore(context, argc, argv, 0, ""); +} + +/* +** The CONCAT_WS(separator, ...) function. +** +** Generate a string that is the concatenation of 2nd through the Nth +** argument. Use the first argument (which must be non-NULL) as the +** separator. +*/ +static void concatwsFunc( + sqlite3_context *context, + int argc, + sqlite3_value **argv +){ + int nSep = sqlite3_value_bytes(argv[0]); + const char *zSep = (const char*)sqlite3_value_text(argv[0]); + if( zSep==0 ) return; + concatFuncCore(context, argc-1, argv+1, nSep, zSep); +} + #ifdef SQLITE_ENABLE_UNKNOWN_SQL_FUNCTION /* @@ -128461,7 +130534,7 @@ static void sumFinalize(sqlite3_context *context){ if( p->approx ){ if( p->ovrfl ){ sqlite3_result_error(context,"integer overflow",-1); - }else if( !sqlite3IsNaN(p->rErr) ){ + }else if( !sqlite3IsOverflow(p->rErr) ){ sqlite3_result_double(context, p->rSum+p->rErr); }else{ sqlite3_result_double(context, p->rSum); @@ -128478,7 +130551,7 @@ static void avgFinalize(sqlite3_context *context){ double r; if( p->approx ){ r = p->rSum; - if( !sqlite3IsNaN(p->rErr) ) r += p->rErr; + if( !sqlite3IsOverflow(p->rErr) ) r += p->rErr; }else{ r = (double)(p->iSum); } @@ -128492,7 +130565,7 @@ static void totalFinalize(sqlite3_context *context){ if( p ){ if( p->approx ){ r = p->rSum; - if( !sqlite3IsNaN(p->rErr) ) r += p->rErr; + if( !sqlite3IsOverflow(p->rErr) ) r += p->rErr; }else{ r = (double)(p->iSum); } @@ -128616,6 +130689,7 @@ static void minMaxFinalize(sqlite3_context *context){ /* ** group_concat(EXPR, ?SEPARATOR?) +** string_agg(EXPR, SEPARATOR) ** ** The SEPARATOR goes before the EXPR string. This is tragic. The ** groupConcatInverse() implementation would have been easier if the @@ -129206,6 +131280,11 @@ SQLITE_PRIVATE void sqlite3RegisterBuiltinFunctions(void){ FUNCTION(hex, 1, 0, 0, hexFunc ), FUNCTION(unhex, 1, 0, 0, unhexFunc ), FUNCTION(unhex, 2, 0, 0, unhexFunc ), + FUNCTION(concat, -1, 0, 0, concatFunc ), + FUNCTION(concat, 0, 0, 0, 0 ), + FUNCTION(concat_ws, -1, 0, 0, concatwsFunc ), + FUNCTION(concat_ws, 0, 0, 0, 0 ), + FUNCTION(concat_ws, 1, 0, 0, 0 ), INLINE_FUNC(ifnull, 2, INLINEFUNC_coalesce, 0 ), VFUNCTION(random, 0, 0, 0, randomFunc ), VFUNCTION(randomblob, 1, 0, 0, randomBlob ), @@ -129235,6 +131314,8 @@ SQLITE_PRIVATE void sqlite3RegisterBuiltinFunctions(void){ groupConcatFinalize, groupConcatValue, groupConcatInverse, 0), WAGGREGATE(group_concat, 2, 0, 0, groupConcatStep, groupConcatFinalize, groupConcatValue, groupConcatInverse, 0), + WAGGREGATE(string_agg, 2, 0, 0, groupConcatStep, + groupConcatFinalize, groupConcatValue, groupConcatInverse, 0), LIKEFUNC(glob, 2, &globInfo, SQLITE_FUNC_LIKE|SQLITE_FUNC_CASE), #ifdef SQLITE_CASE_SENSITIVE_LIKE @@ -130177,6 +132258,7 @@ static int isSetNullAction(Parse *pParse, FKey *pFKey){ if( (p==pFKey->apTrigger[0] && pFKey->aAction[0]==OE_SetNull) || (p==pFKey->apTrigger[1] && pFKey->aAction[1]==OE_SetNull) ){ + assert( (pTop->db->flags & SQLITE_FkNoAction)==0 ); return 1; } } @@ -130371,6 +132453,8 @@ SQLITE_PRIVATE void sqlite3FkCheck( } if( regOld!=0 ){ int eAction = pFKey->aAction[aChange!=0]; + if( (db->flags & SQLITE_FkNoAction) ) eAction = OE_None; + fkScanChildren(pParse, pSrc, pTab, pIdx, pFKey, aiCol, regOld, 1); /* If this is a deferred FK constraint, or a CASCADE or SET NULL ** action applies, then any foreign key violations caused by @@ -130486,7 +132570,11 @@ SQLITE_PRIVATE int sqlite3FkRequired( /* Check if any parent key columns are being modified. */ for(p=sqlite3FkReferences(pTab); p; p=p->pNextTo){ if( fkParentIsModified(pTab, p, aChange, chngRowid) ){ - if( p->aAction[1]!=OE_None ) return 2; + if( (pParse->db->flags & SQLITE_FkNoAction)==0 + && p->aAction[1]!=OE_None + ){ + return 2; + } bHaveFK = 1; } } @@ -130536,6 +132624,7 @@ static Trigger *fkActionTrigger( int iAction = (pChanges!=0); /* 1 for UPDATE, 0 for DELETE */ action = pFKey->aAction[iAction]; + if( (db->flags & SQLITE_FkNoAction) ) action = OE_None; if( action==OE_Restrict && (db->flags & SQLITE_DeferFKs) ){ return 0; } @@ -131373,6 +133462,195 @@ SQLITE_PRIVATE void sqlite3AutoincrementEnd(Parse *pParse){ # define autoIncStep(A,B,C) #endif /* SQLITE_OMIT_AUTOINCREMENT */ +/* +** If argument pVal is a Select object returned by an sqlite3MultiValues() +** that was able to use the co-routine optimization, finish coding the +** co-routine. +*/ +SQLITE_PRIVATE void sqlite3MultiValuesEnd(Parse *pParse, Select *pVal){ + if( ALWAYS(pVal) && pVal->pSrc->nSrc>0 ){ + SrcItem *pItem = &pVal->pSrc->a[0]; + sqlite3VdbeEndCoroutine(pParse->pVdbe, pItem->regReturn); + sqlite3VdbeJumpHere(pParse->pVdbe, pItem->addrFillSub - 1); + } +} + +/* +** Return true if all expressions in the expression-list passed as the +** only argument are constant. +*/ +static int exprListIsConstant(Parse *pParse, ExprList *pRow){ + int ii; + for(ii=0; iinExpr; ii++){ + if( 0==sqlite3ExprIsConstant(pParse, pRow->a[ii].pExpr) ) return 0; + } + return 1; +} + +/* +** Return true if all expressions in the expression-list passed as the +** only argument are both constant and have no affinity. +*/ +static int exprListIsNoAffinity(Parse *pParse, ExprList *pRow){ + int ii; + if( exprListIsConstant(pParse,pRow)==0 ) return 0; + for(ii=0; iinExpr; ii++){ + Expr *pExpr = pRow->a[ii].pExpr; + assert( pExpr->op!=TK_RAISE ); + assert( pExpr->affExpr==0 ); + if( 0!=sqlite3ExprAffinity(pExpr) ) return 0; + } + return 1; + +} + +/* +** This function is called by the parser for the second and subsequent +** rows of a multi-row VALUES clause. Argument pLeft is the part of +** the VALUES clause already parsed, argument pRow is the vector of values +** for the new row. The Select object returned represents the complete +** VALUES clause, including the new row. +** +** There are two ways in which this may be achieved - by incremental +** coding of a co-routine (the "co-routine" method) or by returning a +** Select object equivalent to the following (the "UNION ALL" method): +** +** "pLeft UNION ALL SELECT pRow" +** +** If the VALUES clause contains a lot of rows, this compound Select +** object may consume a lot of memory. +** +** When the co-routine method is used, each row that will be returned +** by the VALUES clause is coded into part of a co-routine as it is +** passed to this function. The returned Select object is equivalent to: +** +** SELECT * FROM ( +** Select object to read co-routine +** ) +** +** The co-routine method is used in most cases. Exceptions are: +** +** a) If the current statement has a WITH clause. This is to avoid +** statements like: +** +** WITH cte AS ( VALUES('x'), ('y') ... ) +** SELECT * FROM cte AS a, cte AS b; +** +** This will not work, as the co-routine uses a hard-coded register +** for its OP_Yield instructions, and so it is not possible for two +** cursors to iterate through it concurrently. +** +** b) The schema is currently being parsed (i.e. the VALUES clause is part +** of a schema item like a VIEW or TRIGGER). In this case there is no VM +** being generated when parsing is taking place, and so generating +** a co-routine is not possible. +** +** c) There are non-constant expressions in the VALUES clause (e.g. +** the VALUES clause is part of a correlated sub-query). +** +** d) One or more of the values in the first row of the VALUES clause +** has an affinity (i.e. is a CAST expression). This causes problems +** because the complex rules SQLite uses (see function +** sqlite3SubqueryColumnTypes() in select.c) to determine the effective +** affinity of such a column for all rows require access to all values in +** the column simultaneously. +*/ +SQLITE_PRIVATE Select *sqlite3MultiValues(Parse *pParse, Select *pLeft, ExprList *pRow){ + + if( pParse->bHasWith /* condition (a) above */ + || pParse->db->init.busy /* condition (b) above */ + || exprListIsConstant(pParse,pRow)==0 /* condition (c) above */ + || (pLeft->pSrc->nSrc==0 && + exprListIsNoAffinity(pParse,pLeft->pEList)==0) /* condition (d) above */ + || IN_SPECIAL_PARSE + ){ + /* The co-routine method cannot be used. Fall back to UNION ALL. */ + Select *pSelect = 0; + int f = SF_Values | SF_MultiValue; + if( pLeft->pSrc->nSrc ){ + sqlite3MultiValuesEnd(pParse, pLeft); + f = SF_Values; + }else if( pLeft->pPrior ){ + /* In this case set the SF_MultiValue flag only if it was set on pLeft */ + f = (f & pLeft->selFlags); + } + pSelect = sqlite3SelectNew(pParse, pRow, 0, 0, 0, 0, 0, f, 0); + pLeft->selFlags &= ~SF_MultiValue; + if( pSelect ){ + pSelect->op = TK_ALL; + pSelect->pPrior = pLeft; + pLeft = pSelect; + } + }else{ + SrcItem *p = 0; /* SrcItem that reads from co-routine */ + + if( pLeft->pSrc->nSrc==0 ){ + /* Co-routine has not yet been started and the special Select object + ** that accesses the co-routine has not yet been created. This block + ** does both those things. */ + Vdbe *v = sqlite3GetVdbe(pParse); + Select *pRet = sqlite3SelectNew(pParse, 0, 0, 0, 0, 0, 0, 0, 0); + + /* Ensure the database schema has been read. This is to ensure we have + ** the correct text encoding. */ + if( (pParse->db->mDbFlags & DBFLAG_SchemaKnownOk)==0 ){ + sqlite3ReadSchema(pParse); + } + + if( pRet ){ + SelectDest dest; + pRet->pSrc->nSrc = 1; + pRet->pPrior = pLeft->pPrior; + pRet->op = pLeft->op; + pLeft->pPrior = 0; + pLeft->op = TK_SELECT; + assert( pLeft->pNext==0 ); + assert( pRet->pNext==0 ); + p = &pRet->pSrc->a[0]; + p->pSelect = pLeft; + p->fg.viaCoroutine = 1; + p->addrFillSub = sqlite3VdbeCurrentAddr(v) + 1; + p->regReturn = ++pParse->nMem; + p->iCursor = -1; + p->u1.nRow = 2; + sqlite3VdbeAddOp3(v,OP_InitCoroutine,p->regReturn,0,p->addrFillSub); + sqlite3SelectDestInit(&dest, SRT_Coroutine, p->regReturn); + + /* Allocate registers for the output of the co-routine. Do so so + ** that there are two unused registers immediately before those + ** used by the co-routine. This allows the code in sqlite3Insert() + ** to use these registers directly, instead of copying the output + ** of the co-routine to a separate array for processing. */ + dest.iSdst = pParse->nMem + 3; + dest.nSdst = pLeft->pEList->nExpr; + pParse->nMem += 2 + dest.nSdst; + + pLeft->selFlags |= SF_MultiValue; + sqlite3Select(pParse, pLeft, &dest); + p->regResult = dest.iSdst; + assert( pParse->nErr || dest.iSdst>0 ); + pLeft = pRet; + } + }else{ + p = &pLeft->pSrc->a[0]; + assert( !p->fg.isTabFunc && !p->fg.isIndexedBy ); + p->u1.nRow++; + } + + if( pParse->nErr==0 ){ + assert( p!=0 ); + if( p->pSelect->pEList->nExpr!=pRow->nExpr ){ + sqlite3SelectWrongNumTermsError(pParse, p->pSelect); + }else{ + sqlite3ExprCodeExprList(pParse, pRow, p->regResult, 0, 0); + sqlite3VdbeAddOp1(pParse->pVdbe, OP_Yield, p->regReturn); + } + } + sqlite3ExprListDelete(pParse->db, pRow); + } + + return pLeft; +} /* Forward declaration */ static int xferOptimization( @@ -131709,25 +133987,40 @@ SQLITE_PRIVATE void sqlite3Insert( if( pSelect ){ /* Data is coming from a SELECT or from a multi-row VALUES clause. ** Generate a co-routine to run the SELECT. */ - int regYield; /* Register holding co-routine entry-point */ - int addrTop; /* Top of the co-routine */ int rc; /* Result code */ - regYield = ++pParse->nMem; - addrTop = sqlite3VdbeCurrentAddr(v) + 1; - sqlite3VdbeAddOp3(v, OP_InitCoroutine, regYield, 0, addrTop); - sqlite3SelectDestInit(&dest, SRT_Coroutine, regYield); - dest.iSdst = bIdListInOrder ? regData : 0; - dest.nSdst = pTab->nCol; - rc = sqlite3Select(pParse, pSelect, &dest); - regFromSelect = dest.iSdst; - assert( db->pParse==pParse ); - if( rc || pParse->nErr ) goto insert_cleanup; - assert( db->mallocFailed==0 ); - sqlite3VdbeEndCoroutine(v, regYield); - sqlite3VdbeJumpHere(v, addrTop - 1); /* label B: */ - assert( pSelect->pEList ); - nColumn = pSelect->pEList->nExpr; + if( pSelect->pSrc->nSrc==1 + && pSelect->pSrc->a[0].fg.viaCoroutine + && pSelect->pPrior==0 + ){ + SrcItem *pItem = &pSelect->pSrc->a[0]; + dest.iSDParm = pItem->regReturn; + regFromSelect = pItem->regResult; + nColumn = pItem->pSelect->pEList->nExpr; + ExplainQueryPlan((pParse, 0, "SCAN %S", pItem)); + if( bIdListInOrder && nColumn==pTab->nCol ){ + regData = regFromSelect; + regRowid = regData - 1; + regIns = regRowid - (IsVirtual(pTab) ? 1 : 0); + } + }else{ + int addrTop; /* Top of the co-routine */ + int regYield = ++pParse->nMem; + addrTop = sqlite3VdbeCurrentAddr(v) + 1; + sqlite3VdbeAddOp3(v, OP_InitCoroutine, regYield, 0, addrTop); + sqlite3SelectDestInit(&dest, SRT_Coroutine, regYield); + dest.iSdst = bIdListInOrder ? regData : 0; + dest.nSdst = pTab->nCol; + rc = sqlite3Select(pParse, pSelect, &dest); + regFromSelect = dest.iSdst; + assert( db->pParse==pParse ); + if( rc || pParse->nErr ) goto insert_cleanup; + assert( db->mallocFailed==0 ); + sqlite3VdbeEndCoroutine(v, regYield); + sqlite3VdbeJumpHere(v, addrTop - 1); /* label B: */ + assert( pSelect->pEList ); + nColumn = pSelect->pEList->nExpr; + } /* Set useTempTable to TRUE if the result of the SELECT statement ** should be written into a temporary table (template 4). Set to @@ -131882,7 +134175,7 @@ SQLITE_PRIVATE void sqlite3Insert( pNx->iDataCur = iDataCur; pNx->iIdxCur = iIdxCur; if( pNx->pUpsertTarget ){ - if( sqlite3UpsertAnalyzeTarget(pParse, pTabList, pNx) ){ + if( sqlite3UpsertAnalyzeTarget(pParse, pTabList, pNx, pUpsert) ){ goto insert_cleanup; } } @@ -133774,7 +136067,10 @@ static int xferOptimization( } } #ifndef SQLITE_OMIT_CHECK - if( pDest->pCheck && sqlite3ExprListCompare(pSrc->pCheck,pDest->pCheck,-1) ){ + if( pDest->pCheck + && (db->mDbFlags & DBFLAG_Vacuum)==0 + && sqlite3ExprListCompare(pSrc->pCheck,pDest->pCheck,-1) + ){ return 0; /* Tables have different CHECK constraints. Ticket #2252 */ } #endif @@ -134491,6 +136787,9 @@ struct sqlite3_api_routines { int (*is_interrupted)(sqlite3*); /* Version 3.43.0 and later */ int (*stmt_explain)(sqlite3_stmt*,int); + /* Version 3.44.0 and later */ + void *(*get_clientdata)(sqlite3*,const char*); + int (*set_clientdata)(sqlite3*, const char*, void*, void(*)(void*)); }; /* @@ -134821,6 +137120,9 @@ typedef int (*sqlite3_loadext_entry)( #define sqlite3_is_interrupted sqlite3_api->is_interrupted /* Version 3.43.0 and later */ #define sqlite3_stmt_explain sqlite3_api->stmt_explain +/* Version 3.44.0 and later */ +#define sqlite3_get_clientdata sqlite3_api->get_clientdata +#define sqlite3_set_clientdata sqlite3_api->set_clientdata #endif /* !defined(SQLITE_CORE) && !defined(SQLITE_OMIT_LOAD_EXTENSION) */ #if !defined(SQLITE_CORE) && !defined(SQLITE_OMIT_LOAD_EXTENSION) @@ -135339,7 +137641,10 @@ static const sqlite3_api_routines sqlite3Apis = { /* Version 3.41.0 and later */ sqlite3_is_interrupted, /* Version 3.43.0 and later */ - sqlite3_stmt_explain + sqlite3_stmt_explain, + /* Version 3.44.0 and later */ + sqlite3_get_clientdata, + sqlite3_set_clientdata }; /* True if x is the directory separator character @@ -135555,6 +137860,9 @@ SQLITE_PRIVATE void sqlite3CloseExtensions(sqlite3 *db){ ** default so as not to open security holes in older applications. */ SQLITE_API int sqlite3_enable_load_extension(sqlite3 *db, int onoff){ +#ifdef SQLITE_ENABLE_API_ARMOR + if( !sqlite3SafetyCheckOk(db) ) return SQLITE_MISUSE_BKPT; +#endif sqlite3_mutex_enter(db->mutex); if( onoff ){ db->flags |= SQLITE_LoadExtension|SQLITE_LoadExtFunc; @@ -135604,6 +137912,9 @@ SQLITE_API int sqlite3_auto_extension( void (*xInit)(void) ){ int rc = SQLITE_OK; +#ifdef SQLITE_ENABLE_API_ARMOR + if( xInit==0 ) return SQLITE_MISUSE_BKPT; +#endif #ifndef SQLITE_OMIT_AUTOINIT rc = sqlite3_initialize(); if( rc ){ @@ -135656,6 +137967,9 @@ SQLITE_API int sqlite3_cancel_auto_extension( int i; int n = 0; wsdAutoextInit; +#ifdef SQLITE_ENABLE_API_ARMOR + if( xInit==0 ) return 0; +#endif sqlite3_mutex_enter(mutex); for(i=(int)wsdAutoext.nExt-1; i>=0; i--){ if( wsdAutoext.aExt[i]==xInit ){ @@ -136431,6 +138745,34 @@ static const PragmaName aPragmaName[] = { /************** End of pragma.h **********************************************/ /************** Continuing where we left off in pragma.c *********************/ +/* +** When the 0x10 bit of PRAGMA optimize is set, any ANALYZE commands +** will be run with an analysis_limit set to the lessor of the value of +** the following macro or to the actual analysis_limit if it is non-zero, +** in order to prevent PRAGMA optimize from running for too long. +** +** The value of 2000 is chosen emperically so that the worst-case run-time +** for PRAGMA optimize does not exceed 100 milliseconds against a variety +** of test databases on a RaspberryPI-4 compiled using -Os and without +** -DSQLITE_DEBUG. Of course, your mileage may vary. For the purpose of +** this paragraph, "worst-case" means that ANALYZE ends up being +** run on every table in the database. The worst case typically only +** happens if PRAGMA optimize is run on a database file for which ANALYZE +** has not been previously run and the 0x10000 flag is included so that +** all tables are analyzed. The usual case for PRAGMA optimize is that +** no ANALYZE commands will be run at all, or if any ANALYZE happens it +** will be against a single table, so that expected timing for PRAGMA +** optimize on a PI-4 is more like 1 millisecond or less with the 0x10000 +** flag or less than 100 microseconds without the 0x10000 flag. +** +** An analysis limit of 2000 is almost always sufficient for the query +** planner to fully characterize an index. The additional accuracy from +** a larger analysis is not usually helpful. +*/ +#ifndef SQLITE_DEFAULT_OPTIMIZE_LIMIT +# define SQLITE_DEFAULT_OPTIMIZE_LIMIT 2000 +#endif + /* ** Interpret the given string as a safety level. Return 0 for OFF, ** 1 for ON or NORMAL, 2 for FULL, and 3 for EXTRA. Return 1 for an empty or @@ -137525,7 +139867,11 @@ SQLITE_PRIVATE void sqlite3Pragma( #endif if( sqlite3GetBoolean(zRight, 0) ){ - db->flags |= mask; + if( (mask & SQLITE_WriteSchema)==0 + || (db->flags & SQLITE_Defensive)==0 + ){ + db->flags |= mask; + } }else{ db->flags &= ~mask; if( mask==SQLITE_DeferFKs ) db->nDeferredImmCons = 0; @@ -138072,7 +140418,7 @@ SQLITE_PRIVATE void sqlite3Pragma( /* Set the maximum error count */ mxErr = SQLITE_INTEGRITY_CHECK_ERROR_MAX; if( zRight ){ - if( sqlite3GetInt32(zRight, &mxErr) ){ + if( sqlite3GetInt32(pValue->z, &mxErr) ){ if( mxErr<=0 ){ mxErr = SQLITE_INTEGRITY_CHECK_ERROR_MAX; } @@ -138089,7 +140435,6 @@ SQLITE_PRIVATE void sqlite3Pragma( Hash *pTbls; /* Set of all tables in the schema */ int *aRoot; /* Array of root page numbers of all btrees */ int cnt = 0; /* Number of entries in aRoot[] */ - int mxIdx = 0; /* Maximum number of indexes for any table */ if( OMIT_TEMPDB && i==1 ) continue; if( iDb>=0 && i!=iDb ) continue; @@ -138111,7 +140456,6 @@ SQLITE_PRIVATE void sqlite3Pragma( if( pObjTab && pObjTab!=pTab ) continue; if( HasRowid(pTab) ) cnt++; for(nIdx=0, pIdx=pTab->pIndex; pIdx; pIdx=pIdx->pNext, nIdx++){ cnt++; } - if( nIdx>mxIdx ) mxIdx = nIdx; } if( cnt==0 ) continue; if( pObjTab ) cnt++; @@ -138131,11 +140475,11 @@ SQLITE_PRIVATE void sqlite3Pragma( aRoot[0] = cnt; /* Make sure sufficient number of registers have been allocated */ - sqlite3TouchRegister(pParse, 8+mxIdx); + sqlite3TouchRegister(pParse, 8+cnt); sqlite3ClearTempRegCache(pParse); /* Do the b-tree integrity checks */ - sqlite3VdbeAddOp4(v, OP_IntegrityCk, 2, cnt, 1, (char*)aRoot,P4_INTARRAY); + sqlite3VdbeAddOp4(v, OP_IntegrityCk, 1, cnt, 8, (char*)aRoot,P4_INTARRAY); sqlite3VdbeChangeP5(v, (u8)i); addr = sqlite3VdbeAddOp1(v, OP_IsNull, 2); VdbeCoverage(v); sqlite3VdbeAddOp4(v, OP_String8, 0, 3, 0, @@ -138145,6 +140489,36 @@ SQLITE_PRIVATE void sqlite3Pragma( integrityCheckResultRow(v); sqlite3VdbeJumpHere(v, addr); + /* Check that the indexes all have the right number of rows */ + cnt = pObjTab ? 1 : 0; + sqlite3VdbeLoadString(v, 2, "wrong # of entries in index "); + for(x=sqliteHashFirst(pTbls); x; x=sqliteHashNext(x)){ + int iTab = 0; + Table *pTab = sqliteHashData(x); + Index *pIdx; + if( pObjTab && pObjTab!=pTab ) continue; + if( HasRowid(pTab) ){ + iTab = cnt++; + }else{ + iTab = cnt; + for(pIdx=pTab->pIndex; ALWAYS(pIdx); pIdx=pIdx->pNext){ + if( IsPrimaryKeyIndex(pIdx) ) break; + iTab++; + } + } + for(pIdx=pTab->pIndex; pIdx; pIdx=pIdx->pNext){ + if( pIdx->pPartIdxWhere==0 ){ + addr = sqlite3VdbeAddOp3(v, OP_Eq, 8+cnt, 0, 8+iTab); + VdbeCoverageNeverNull(v); + sqlite3VdbeLoadString(v, 4, pIdx->zName); + sqlite3VdbeAddOp3(v, OP_Concat, 4, 2, 3); + integrityCheckResultRow(v); + sqlite3VdbeJumpHere(v, addr); + } + cnt++; + } + } + /* Make sure all the indices are constructed correctly. */ for(x=sqliteHashFirst(pTbls); x; x=sqliteHashNext(x)){ @@ -138158,8 +140532,8 @@ SQLITE_PRIVATE void sqlite3Pragma( int r2; /* Previous key for WITHOUT ROWID tables */ int mxCol; /* Maximum non-virtual column number */ - if( !IsOrdinaryTable(pTab) ) continue; if( pObjTab && pObjTab!=pTab ) continue; + if( !IsOrdinaryTable(pTab) ) continue; if( isQuick || HasRowid(pTab) ){ pPk = 0; r2 = 0; @@ -138294,6 +140668,7 @@ SQLITE_PRIVATE void sqlite3Pragma( ** is REAL, we have to load the actual data using OP_Column ** to reliably determine if the value is a NULL. */ sqlite3VdbeAddOp3(v, OP_Column, p1, p3, 3); + sqlite3ColumnDefault(v, pTab, j, 3); jmp3 = sqlite3VdbeAddOp2(v, OP_NotNull, 3, labelOk); VdbeCoverage(v); } @@ -138467,23 +140842,43 @@ SQLITE_PRIVATE void sqlite3Pragma( } sqlite3VdbeAddOp2(v, OP_Next, iDataCur, loopTop); VdbeCoverage(v); sqlite3VdbeJumpHere(v, loopTop-1); - if( !isQuick ){ - sqlite3VdbeLoadString(v, 2, "wrong # of entries in index "); - for(j=0, pIdx=pTab->pIndex; pIdx; pIdx=pIdx->pNext, j++){ - if( pPk==pIdx ) continue; - sqlite3VdbeAddOp2(v, OP_Count, iIdxCur+j, 3); - addr = sqlite3VdbeAddOp3(v, OP_Eq, 8+j, 0, 3); VdbeCoverage(v); - sqlite3VdbeChangeP5(v, SQLITE_NOTNULL); - sqlite3VdbeLoadString(v, 4, pIdx->zName); - sqlite3VdbeAddOp3(v, OP_Concat, 4, 2, 3); - integrityCheckResultRow(v); - sqlite3VdbeJumpHere(v, addr); - } - if( pPk ){ - sqlite3ReleaseTempRange(pParse, r2, pPk->nKeyCol); - } + if( pPk ){ + assert( !isQuick ); + sqlite3ReleaseTempRange(pParse, r2, pPk->nKeyCol); } } + +#ifndef SQLITE_OMIT_VIRTUALTABLE + /* Second pass to invoke the xIntegrity method on all virtual + ** tables. + */ + for(x=sqliteHashFirst(pTbls); x; x=sqliteHashNext(x)){ + Table *pTab = sqliteHashData(x); + sqlite3_vtab *pVTab; + int a1; + if( pObjTab && pObjTab!=pTab ) continue; + if( IsOrdinaryTable(pTab) ) continue; + if( !IsVirtual(pTab) ) continue; + if( pTab->nCol<=0 ){ + const char *zMod = pTab->u.vtab.azArg[0]; + if( sqlite3HashFind(&db->aModule, zMod)==0 ) continue; + } + sqlite3ViewGetColumnNames(pParse, pTab); + if( pTab->u.vtab.p==0 ) continue; + pVTab = pTab->u.vtab.p->pVtab; + if( NEVER(pVTab==0) ) continue; + if( NEVER(pVTab->pModule==0) ) continue; + if( pVTab->pModule->iVersion<4 ) continue; + if( pVTab->pModule->xIntegrity==0 ) continue; + sqlite3VdbeAddOp3(v, OP_VCheck, i, 3, isQuick); + pTab->nTabRef++; + sqlite3VdbeAppendP4(v, pTab, P4_TABLEREF); + a1 = sqlite3VdbeAddOp1(v, OP_IsNull, 3); VdbeCoverage(v); + integrityCheckResultRow(v); + sqlite3VdbeJumpHere(v, a1); + continue; + } +#endif } { static const int iLn = VDBE_OFFSET_LINENO(2); @@ -138747,44 +141142,63 @@ SQLITE_PRIVATE void sqlite3Pragma( ** ** The optional argument is a bitmask of optimizations to perform: ** - ** 0x0001 Debugging mode. Do not actually perform any optimizations - ** but instead return one line of text for each optimization - ** that would have been done. Off by default. + ** 0x00001 Debugging mode. Do not actually perform any optimizations + ** but instead return one line of text for each optimization + ** that would have been done. Off by default. ** - ** 0x0002 Run ANALYZE on tables that might benefit. On by default. - ** See below for additional information. + ** 0x00002 Run ANALYZE on tables that might benefit. On by default. + ** See below for additional information. ** - ** 0x0004 (Not yet implemented) Record usage and performance - ** information from the current session in the - ** database file so that it will be available to "optimize" - ** pragmas run by future database connections. + ** 0x00010 Run all ANALYZE operations using an analysis_limit that + ** is the lessor of the current analysis_limit and the + ** SQLITE_DEFAULT_OPTIMIZE_LIMIT compile-time option. + ** The default value of SQLITE_DEFAULT_OPTIMIZE_LIMIT is + ** currently (2024-02-19) set to 2000, which is such that + ** the worst case run-time for PRAGMA optimize on a 100MB + ** database will usually be less than 100 milliseconds on + ** a RaspberryPI-4 class machine. On by default. ** - ** 0x0008 (Not yet implemented) Create indexes that might have - ** been helpful to recent queries + ** 0x10000 Look at tables to see if they need to be reanalyzed + ** due to growth or shrinkage even if they have not been + ** queried during the current connection. Off by default. ** - ** The default MASK is and always shall be 0xfffe. 0xfffe means perform all - ** of the optimizations listed above except Debug Mode, including new - ** optimizations that have not yet been invented. If new optimizations are - ** ever added that should be off by default, those off-by-default - ** optimizations will have bitmasks of 0x10000 or larger. + ** The default MASK is and always shall be 0x0fffe. In the current + ** implementation, the default mask only covers the 0x00002 optimization, + ** though additional optimizations that are covered by 0x0fffe might be + ** added in the future. Optimizations that are off by default and must + ** be explicitly requested have masks of 0x10000 or greater. ** ** DETERMINATION OF WHEN TO RUN ANALYZE ** ** In the current implementation, a table is analyzed if only if all of ** the following are true: ** - ** (1) MASK bit 0x02 is set. + ** (1) MASK bit 0x00002 is set. + ** + ** (2) The table is an ordinary table, not a virtual table or view. ** - ** (2) The query planner used sqlite_stat1-style statistics for one or - ** more indexes of the table at some point during the lifetime of - ** the current connection. + ** (3) The table name does not begin with "sqlite_". ** - ** (3) One or more indexes of the table are currently unanalyzed OR - ** the number of rows in the table has increased by 25 times or more - ** since the last time ANALYZE was run. + ** (4) One or more of the following is true: + ** (4a) The 0x10000 MASK bit is set. + ** (4b) One or more indexes on the table lacks an entry + ** in the sqlite_stat1 table. + ** (4c) The query planner used sqlite_stat1-style statistics for one + ** or more indexes of the table at some point during the lifetime + ** of the current connection. + ** + ** (5) One or more of the following is true: + ** (5a) One or more indexes on the table lacks an entry + ** in the sqlite_stat1 table. (Same as 4a) + ** (5b) The number of rows in the table has increased or decreased by + ** 10-fold. In other words, the current size of the table is + ** 10 times larger than the size in sqlite_stat1 or else the + ** current size is less than 1/10th the size in sqlite_stat1. ** ** The rules for when tables are analyzed are likely to change in - ** future releases. + ** future releases. Future versions of SQLite might accept a string + ** literal argument to this pragma that contains a mnemonic description + ** of the options rather than a bitmap. */ case PragTyp_OPTIMIZE: { int iDbLast; /* Loop termination point for the schema loop */ @@ -138796,6 +141210,10 @@ SQLITE_PRIVATE void sqlite3Pragma( LogEst szThreshold; /* Size threshold above which reanalysis needed */ char *zSubSql; /* SQL statement for the OP_SqlExec opcode */ u32 opMask; /* Mask of operations to perform */ + int nLimit; /* Analysis limit to use */ + int nCheck = 0; /* Number of tables to be optimized */ + int nBtree = 0; /* Number of btrees to scan */ + int nIndex; /* Number of indexes on the current table */ if( zRight ){ opMask = (u32)sqlite3Atoi(zRight); @@ -138803,6 +141221,14 @@ SQLITE_PRIVATE void sqlite3Pragma( }else{ opMask = 0xfffe; } + if( (opMask & 0x10)==0 ){ + nLimit = 0; + }else if( db->nAnalysisLimit>0 + && db->nAnalysisLimitnTab++; for(iDbLast = zDb?iDb:db->nDb-1; iDb<=iDbLast; iDb++){ if( iDb==1 ) continue; @@ -138811,23 +141237,61 @@ SQLITE_PRIVATE void sqlite3Pragma( for(k=sqliteHashFirst(&pSchema->tblHash); k; k=sqliteHashNext(k)){ pTab = (Table*)sqliteHashData(k); - /* If table pTab has not been used in a way that would benefit from - ** having analysis statistics during the current session, then skip it. - ** This also has the effect of skipping virtual tables and views */ - if( (pTab->tabFlags & TF_StatsUsed)==0 ) continue; + /* This only works for ordinary tables */ + if( !IsOrdinaryTable(pTab) ) continue; + + /* Do not scan system tables */ + if( 0==sqlite3StrNICmp(pTab->zName, "sqlite_", 7) ) continue; - /* Reanalyze if the table is 25 times larger than the last analysis */ - szThreshold = pTab->nRowLogEst + 46; assert( sqlite3LogEst(25)==46 ); + /* Find the size of the table as last recorded in sqlite_stat1. + ** If any index is unanalyzed, then the threshold is -1 to + ** indicate a new, unanalyzed index + */ + szThreshold = pTab->nRowLogEst; + nIndex = 0; for(pIdx=pTab->pIndex; pIdx; pIdx=pIdx->pNext){ + nIndex++; if( !pIdx->hasStat1 ){ - szThreshold = 0; /* Always analyze if any index lacks statistics */ - break; + szThreshold = -1; /* Always analyze if any index lacks statistics */ } } - if( szThreshold ){ - sqlite3OpenTable(pParse, iTabCur, iDb, pTab, OP_OpenRead); - sqlite3VdbeAddOp3(v, OP_IfSmaller, iTabCur, - sqlite3VdbeCurrentAddr(v)+2+(opMask&1), szThreshold); + + /* If table pTab has not been used in a way that would benefit from + ** having analysis statistics during the current session, then skip it, + ** unless the 0x10000 MASK bit is set. */ + if( (pTab->tabFlags & TF_MaybeReanalyze)!=0 ){ + /* Check for size change if stat1 has been used for a query */ + }else if( opMask & 0x10000 ){ + /* Check for size change if 0x10000 is set */ + }else if( pTab->pIndex!=0 && szThreshold<0 ){ + /* Do analysis if unanalyzed indexes exists */ + }else{ + /* Otherwise, we can skip this table */ + continue; + } + + nCheck++; + if( nCheck==2 ){ + /* If ANALYZE might be invoked two or more times, hold a write + ** transaction for efficiency */ + sqlite3BeginWriteOperation(pParse, 0, iDb); + } + nBtree += nIndex+1; + + /* Reanalyze if the table is 10 times larger or smaller than + ** the last analysis. Unconditional reanalysis if there are + ** unanalyzed indexes. */ + sqlite3OpenTable(pParse, iTabCur, iDb, pTab, OP_OpenRead); + if( szThreshold>=0 ){ + const LogEst iRange = 33; /* 10x size change */ + sqlite3VdbeAddOp4Int(v, OP_IfSizeBetween, iTabCur, + sqlite3VdbeCurrentAddr(v)+2+(opMask&1), + szThreshold>=iRange ? szThreshold-iRange : -1, + szThreshold+iRange); + VdbeCoverage(v); + }else{ + sqlite3VdbeAddOp2(v, OP_Rewind, iTabCur, + sqlite3VdbeCurrentAddr(v)+2+(opMask&1)); VdbeCoverage(v); } zSubSql = sqlite3MPrintf(db, "ANALYZE \"%w\".\"%w\"", @@ -138837,11 +141301,27 @@ SQLITE_PRIVATE void sqlite3Pragma( sqlite3VdbeAddOp4(v, OP_String8, 0, r1, 0, zSubSql, P4_DYNAMIC); sqlite3VdbeAddOp2(v, OP_ResultRow, r1, 1); }else{ - sqlite3VdbeAddOp4(v, OP_SqlExec, 0, 0, 0, zSubSql, P4_DYNAMIC); + sqlite3VdbeAddOp4(v, OP_SqlExec, nLimit ? 0x02 : 00, nLimit, 0, + zSubSql, P4_DYNAMIC); } } } sqlite3VdbeAddOp0(v, OP_Expire); + + /* In a schema with a large number of tables and indexes, scale back + ** the analysis_limit to avoid excess run-time in the worst case. + */ + if( !db->mallocFailed && nLimit>0 && nBtree>100 ){ + int iAddr, iEnd; + VdbeOp *aOp; + nLimit = 100*nLimit/nBtree; + if( nLimit<100 ) nLimit = 100; + aOp = sqlite3VdbeGetOp(v, 0); + iEnd = sqlite3VdbeCurrentAddr(v); + for(iAddr=0; iAddrnConstraint; i++, pConstraint++){ - if( pConstraint->usable==0 ) continue; - if( pConstraint->op!=SQLITE_INDEX_CONSTRAINT_EQ ) continue; if( pConstraint->iColumn < pTab->iHidden ) continue; + if( pConstraint->op!=SQLITE_INDEX_CONSTRAINT_EQ ) continue; + if( pConstraint->usable==0 ) return SQLITE_CONSTRAINT; j = pConstraint->iColumn - pTab->iHidden; assert( j < 2 ); seen[j] = i+1; @@ -139120,12 +141600,13 @@ static int pragmaVtabBestIndex(sqlite3_vtab *tab, sqlite3_index_info *pIdxInfo){ j = seen[0]-1; pIdxInfo->aConstraintUsage[j].argvIndex = 1; pIdxInfo->aConstraintUsage[j].omit = 1; - if( seen[1]==0 ) return SQLITE_OK; pIdxInfo->estimatedCost = (double)20; pIdxInfo->estimatedRows = 20; - j = seen[1]-1; - pIdxInfo->aConstraintUsage[j].argvIndex = 2; - pIdxInfo->aConstraintUsage[j].omit = 1; + if( seen[1] ){ + j = seen[1]-1; + pIdxInfo->aConstraintUsage[j].argvIndex = 2; + pIdxInfo->aConstraintUsage[j].omit = 1; + } return SQLITE_OK; } @@ -139145,6 +141626,7 @@ static void pragmaVtabCursorClear(PragmaVtabCursor *pCsr){ int i; sqlite3_finalize(pCsr->pPragma); pCsr->pPragma = 0; + pCsr->iRowid = 0; for(i=0; iazArg); i++){ sqlite3_free(pCsr->azArg[i]); pCsr->azArg[i] = 0; @@ -139285,7 +141767,8 @@ static const sqlite3_module pragmaVtabModule = { 0, /* xSavepoint */ 0, /* xRelease */ 0, /* xRollbackTo */ - 0 /* xShadowName */ + 0, /* xShadowName */ + 0 /* xIntegrity */ }; /* @@ -139909,8 +142392,6 @@ SQLITE_PRIVATE void sqlite3ParseObjectReset(Parse *pParse){ db->lookaside.sz = db->lookaside.bDisable ? 0 : db->lookaside.szTrue; assert( pParse->db->pParse==pParse ); db->pParse = pParse->pOuterParse; - pParse->db = 0; - pParse->disableLookaside = 0; } /* @@ -139946,7 +142427,13 @@ SQLITE_PRIVATE void *sqlite3ParserAddCleanup( void (*xCleanup)(sqlite3*,void*), /* The cleanup routine */ void *pPtr /* Pointer to object to be cleaned up */ ){ - ParseCleanup *pCleanup = sqlite3DbMallocRaw(pParse->db, sizeof(*pCleanup)); + ParseCleanup *pCleanup; + if( sqlite3FaultSim(300) ){ + pCleanup = 0; + sqlite3OomFault(pParse->db); + }else{ + pCleanup = sqlite3DbMallocRaw(pParse->db, sizeof(*pCleanup)); + } if( pCleanup ){ pCleanup->pNext = pParse->pCleanup; pParse->pCleanup = pCleanup; @@ -140181,6 +142668,7 @@ static int sqlite3LockAndPrepare( assert( (rc&db->errMask)==rc ); db->busyHandler.nBusy = 0; sqlite3_mutex_leave(db->mutex); + assert( rc==SQLITE_OK || (*ppStmt)==0 ); return rc; } @@ -140578,6 +143066,9 @@ SQLITE_PRIVATE Select *sqlite3SelectNew( SQLITE_PRIVATE void sqlite3SelectDelete(sqlite3 *db, Select *p){ if( OK_IF_ALWAYS_TRUE(p) ) clearSelect(db, p, 1); } +SQLITE_PRIVATE void sqlite3SelectDeleteGeneric(sqlite3 *db, void *p){ + if( ALWAYS(p) ) clearSelect(db, (Select*)p, 1); +} /* ** Return a pointer to the right-most SELECT statement in a compound. @@ -140848,6 +143339,7 @@ static void unsetJoinExpr(Expr *p, int iTable, int nullable){ } if( p->op==TK_FUNCTION ){ assert( ExprUseXList(p) ); + assert( p->pLeft==0 ); if( p->x.pList ){ int i; for(i=0; ix.pList->nExpr; i++){ @@ -142063,9 +144555,16 @@ static void generateSortTail( int addrExplain; /* Address of OP_Explain instruction */ #endif - ExplainQueryPlan2(addrExplain, (pParse, 0, - "USE TEMP B-TREE FOR %sORDER BY", pSort->nOBSat>0?"RIGHT PART OF ":"") - ); + nKey = pOrderBy->nExpr - pSort->nOBSat; + if( pSort->nOBSat==0 || nKey==1 ){ + ExplainQueryPlan2(addrExplain, (pParse, 0, + "USE TEMP B-TREE FOR %sORDER BY", pSort->nOBSat?"LAST TERM OF ":"" + )); + }else{ + ExplainQueryPlan2(addrExplain, (pParse, 0, + "USE TEMP B-TREE FOR LAST %d TERMS OF ORDER BY", nKey + )); + } sqlite3VdbeScanStatusRange(v, addrExplain,pSort->addrPush,pSort->addrPushEnd); sqlite3VdbeScanStatusCounters(v, addrExplain, addrExplain, pSort->addrPush); @@ -142103,7 +144602,6 @@ static void generateSortTail( regRow = sqlite3GetTempRange(pParse, nColumn); } } - nKey = pOrderBy->nExpr - pSort->nOBSat; if( pSort->sortFlags & SORTFLAG_UseSorter ){ int regSortOut = ++pParse->nMem; iSortTab = pParse->nTab++; @@ -142343,11 +144841,7 @@ static const char *columnTypeImpl( ** data for the result-set column of the sub-select. */ if( iColpEList->nExpr -#ifdef SQLITE_ALLOW_ROWID_IN_VIEW - && iCol>=0 -#else - && ALWAYS(iCol>=0) -#endif + && (!ViewCanHaveRowid || iCol>=0) ){ /* If iCol is less than zero, then the expression requests the ** rowid of the sub-select or view. This expression is legal (see @@ -142723,17 +145217,22 @@ SQLITE_PRIVATE void sqlite3SubqueryColumnTypes( for(i=0, pCol=pTab->aCol; inCol; i++, pCol++){ const char *zType; i64 n; + int m = 0; + Select *pS2 = pSelect; pTab->tabFlags |= (pCol->colFlags & COLFLAG_NOINSERT); p = a[i].pExpr; /* pCol->szEst = ... // Column size est for SELECT tables never used */ pCol->affinity = sqlite3ExprAffinity(p); + while( pCol->affinity<=SQLITE_AFF_NONE && pS2->pNext!=0 ){ + m |= sqlite3ExprDataType(pS2->pEList->a[i].pExpr); + pS2 = pS2->pNext; + pCol->affinity = sqlite3ExprAffinity(pS2->pEList->a[i].pExpr); + } if( pCol->affinity<=SQLITE_AFF_NONE ){ pCol->affinity = aff; } - if( pCol->affinity>=SQLITE_AFF_TEXT && pSelect->pNext ){ - int m = 0; - Select *pS2; - for(m=0, pS2=pSelect->pNext; pS2; pS2=pS2->pNext){ + if( pCol->affinity>=SQLITE_AFF_TEXT && (pS2->pNext || pS2!=pSelect) ){ + for(pS2=pS2->pNext; pS2; pS2=pS2->pNext){ m |= sqlite3ExprDataType(pS2->pEList->a[i].pExpr); } if( pCol->affinity==SQLITE_AFF_TEXT && (m&0x01)!=0 ){ @@ -142763,12 +145262,12 @@ SQLITE_PRIVATE void sqlite3SubqueryColumnTypes( } } if( zType ){ - i64 m = sqlite3Strlen30(zType); + const i64 k = sqlite3Strlen30(zType); n = sqlite3Strlen30(pCol->zCnName); - pCol->zCnName = sqlite3DbReallocOrFree(db, pCol->zCnName, n+m+2); + pCol->zCnName = sqlite3DbReallocOrFree(db, pCol->zCnName, n+k+2); pCol->colFlags &= ~(COLFLAG_HASTYPE|COLFLAG_HASCOLL); if( pCol->zCnName ){ - memcpy(&pCol->zCnName[n+1], zType, m+1); + memcpy(&pCol->zCnName[n+1], zType, k+1); pCol->colFlags |= COLFLAG_HASTYPE; } } @@ -143596,9 +146095,7 @@ static int multiSelect( pDest->iSdst = dest.iSdst; pDest->nSdst = dest.nSdst; if( pDelete ){ - sqlite3ParserAddCleanup(pParse, - (void(*)(sqlite3*,void*))sqlite3SelectDelete, - pDelete); + sqlite3ParserAddCleanup(pParse, sqlite3SelectDeleteGeneric, pDelete); } return rc; } @@ -144149,8 +146646,7 @@ static int multiSelectOrderBy( /* Make arrangements to free the 2nd and subsequent arms of the compound ** after the parse has finished */ if( pSplit->pPrior ){ - sqlite3ParserAddCleanup(pParse, - (void(*)(sqlite3*,void*))sqlite3SelectDelete, pSplit->pPrior); + sqlite3ParserAddCleanup(pParse, sqlite3SelectDeleteGeneric, pSplit->pPrior); } pSplit->pPrior = pPrior; pPrior->pNext = pSplit; @@ -144971,9 +147467,7 @@ static int flattenSubquery( Table *pTabToDel = pSubitem->pTab; if( pTabToDel->nTabRef==1 ){ Parse *pToplevel = sqlite3ParseToplevel(pParse); - sqlite3ParserAddCleanup(pToplevel, - (void(*)(sqlite3*,void*))sqlite3DeleteTable, - pTabToDel); + sqlite3ParserAddCleanup(pToplevel, sqlite3DeleteTableGeneric, pTabToDel); testcase( pToplevel->earlyCleanup ); }else{ pTabToDel->nTabRef--; @@ -145170,7 +147664,7 @@ static void constInsert( ){ int i; assert( pColumn->op==TK_COLUMN ); - assert( sqlite3ExprIsConstant(pValue) ); + assert( sqlite3ExprIsConstant(pConst->pParse, pValue) ); if( ExprHasProperty(pColumn, EP_FixedCol) ) return; if( sqlite3ExprAffinity(pValue)!=0 ) return; @@ -145228,10 +147722,10 @@ static void findConstInWhere(WhereConst *pConst, Expr *pExpr){ pLeft = pExpr->pLeft; assert( pRight!=0 ); assert( pLeft!=0 ); - if( pRight->op==TK_COLUMN && sqlite3ExprIsConstant(pLeft) ){ + if( pRight->op==TK_COLUMN && sqlite3ExprIsConstant(pConst->pParse, pLeft) ){ constInsert(pConst,pRight,pLeft,pExpr); } - if( pLeft->op==TK_COLUMN && sqlite3ExprIsConstant(pRight) ){ + if( pLeft->op==TK_COLUMN && sqlite3ExprIsConstant(pConst->pParse, pRight) ){ constInsert(pConst,pLeft,pRight,pExpr); } } @@ -145452,6 +147946,18 @@ static int pushDownWindowCheck(Parse *pParse, Select *pSubq, Expr *pExpr){ ** The hope is that the terms added to the inner query will make it more ** efficient. ** +** NAME AMBIGUITY +** +** This optimization is called the "WHERE-clause push-down optimization". +** +** Do not confuse this optimization with another unrelated optimization +** with a similar name: The "MySQL push-down optimization" causes WHERE +** clause terms that can be evaluated using only the index and without +** reference to the table are run first, so that if they are false, +** unnecessary table seeks are avoided. +** +** RULES +** ** Do not attempt this optimization if: ** ** (1) (** This restriction was removed on 2017-09-29. We used to @@ -145517,15 +148023,19 @@ static int pushDownWindowCheck(Parse *pParse, Select *pSubq, Expr *pExpr){ ** (9c) There is a RIGHT JOIN (or FULL JOIN) in between the ON/USING ** clause and the subquery. ** -** Without this restriction, the push-down optimization might move -** the ON/USING filter expression from the left side of a RIGHT JOIN -** over to the right side, which leads to incorrect answers. See -** also restriction (6) in sqlite3ExprIsSingleTableConstraint(). +** Without this restriction, the WHERE-clause push-down optimization +** might move the ON/USING filter expression from the left side of a +** RIGHT JOIN over to the right side, which leads to incorrect answers. +** See also restriction (6) in sqlite3ExprIsSingleTableConstraint(). ** ** (10) The inner query is not the right-hand table of a RIGHT JOIN. ** ** (11) The subquery is not a VALUES clause ** +** (12) The WHERE clause is not "rowid ISNULL" or the equivalent. This +** case only comes up if SQLite is compiled using +** SQLITE_ALLOW_ROWID_IN_VIEW. +** ** Return 0 if no changes are made and non-zero if one or more WHERE clause ** terms are duplicated into the subquery. */ @@ -145636,7 +148146,19 @@ static int pushDownWhereTerms( } #endif - if( sqlite3ExprIsSingleTableConstraint(pWhere, pSrcList, iSrc) ){ +#ifdef SQLITE_ALLOW_ROWID_IN_VIEW + if( ViewCanHaveRowid && (pWhere->op==TK_ISNULL || pWhere->op==TK_NOTNULL) ){ + Expr *pLeft = pWhere->pLeft; + if( ALWAYS(pLeft) + && pLeft->op==TK_COLUMN + && pLeft->iColumn < 0 + ){ + return 0; /* Restriction (12) */ + } + } +#endif + + if( sqlite3ExprIsSingleTableConstraint(pWhere, pSrcList, iSrc, 1) ){ nChng++; pSubq->selFlags |= SF_PushDown; while( pSubq ){ @@ -146020,8 +148542,7 @@ static struct Cte *searchWith( SQLITE_PRIVATE With *sqlite3WithPush(Parse *pParse, With *pWith, u8 bFree){ if( pWith ){ if( bFree ){ - pWith = (With*)sqlite3ParserAddCleanup(pParse, - (void(*)(sqlite3*,void*))sqlite3WithDelete, + pWith = (With*)sqlite3ParserAddCleanup(pParse, sqlite3WithDeleteGeneric, pWith); if( pWith==0 ) return 0; } @@ -146264,12 +148785,14 @@ SQLITE_PRIVATE int sqlite3ExpandSubquery(Parse *pParse, SrcItem *pFrom){ while( pSel->pPrior ){ pSel = pSel->pPrior; } sqlite3ColumnsFromExprList(pParse, pSel->pEList,&pTab->nCol,&pTab->aCol); pTab->iPKey = -1; + pTab->eTabType = TABTYP_VIEW; pTab->nRowLogEst = 200; assert( 200==sqlite3LogEst(1048576) ); #ifndef SQLITE_ALLOW_ROWID_IN_VIEW /* The usual case - do not allow ROWID on a subquery */ pTab->tabFlags |= TF_Ephemeral | TF_NoVisibleRowid; #else - pTab->tabFlags |= TF_Ephemeral; /* Legacy compatibility mode */ + /* Legacy compatibility mode */ + pTab->tabFlags |= TF_Ephemeral | sqlite3Config.mNoVisibleRowid; #endif return pParse->nErr ? SQLITE_ERROR : SQLITE_OK; } @@ -146508,6 +149031,7 @@ static int selectExpander(Walker *pWalker, Select *p){ char *zTName = 0; /* text of name of TABLE */ int iErrOfst; if( pE->op==TK_DOT ){ + assert( (selFlags & SF_NestedFrom)==0 ); assert( pE->pLeft!=0 ); assert( !ExprHasProperty(pE->pLeft, EP_IntValue) ); zTName = pE->pLeft->u.zToken; @@ -146518,6 +149042,7 @@ static int selectExpander(Walker *pWalker, Select *p){ iErrOfst = pE->w.iOfst; } for(i=0, pFrom=pTabList->a; inSrc; i++, pFrom++){ + int nAdd; /* Number of cols including rowid */ Table *pTab = pFrom->pTab; /* Table for this data source */ ExprList *pNestedFrom; /* Result-set of a nested FROM clause */ char *zTabName; /* AS name for this data source */ @@ -146535,6 +149060,7 @@ static int selectExpander(Walker *pWalker, Select *p){ pNestedFrom = pFrom->pSelect->pEList; assert( pNestedFrom!=0 ); assert( pNestedFrom->nExpr==pTab->nCol ); + assert( VisibleRowid(pTab)==0 || ViewCanHaveRowid ); }else{ if( zTName && sqlite3StrICmp(zTName, zTabName)!=0 ){ continue; @@ -146565,33 +149091,49 @@ static int selectExpander(Walker *pWalker, Select *p){ }else{ pUsing = 0; } - for(j=0; jnCol; j++){ - char *zName = pTab->aCol[j].zCnName; + + nAdd = pTab->nCol; + if( VisibleRowid(pTab) && (selFlags & SF_NestedFrom)!=0 ) nAdd++; + for(j=0; ja[j], 0, zTName, 0)==0 - ){ - continue; - } + if( j==pTab->nCol ){ + zName = sqlite3RowidAlias(pTab); + if( zName==0 ) continue; + }else{ + zName = pTab->aCol[j].zCnName; - /* If a column is marked as 'hidden', omit it from the expanded - ** result-set list unless the SELECT has the SF_IncludeHidden - ** bit set. - */ - if( (p->selFlags & SF_IncludeHidden)==0 - && IsHiddenColumn(&pTab->aCol[j]) - ){ - continue; - } - if( (pTab->aCol[j].colFlags & COLFLAG_NOEXPAND)!=0 - && zTName==0 - && (selFlags & (SF_NestedFrom))==0 - ){ - continue; + /* If pTab is actually an SF_NestedFrom sub-select, do not + ** expand any ENAME_ROWID columns. */ + if( pNestedFrom && pNestedFrom->a[j].fg.eEName==ENAME_ROWID ){ + continue; + } + + if( zTName + && pNestedFrom + && sqlite3MatchEName(&pNestedFrom->a[j], 0, zTName, 0, 0)==0 + ){ + continue; + } + + /* If a column is marked as 'hidden', omit it from the expanded + ** result-set list unless the SELECT has the SF_IncludeHidden + ** bit set. + */ + if( (p->selFlags & SF_IncludeHidden)==0 + && IsHiddenColumn(&pTab->aCol[j]) + ){ + continue; + } + if( (pTab->aCol[j].colFlags & COLFLAG_NOEXPAND)!=0 + && zTName==0 + && (selFlags & (SF_NestedFrom))==0 + ){ + continue; + } } + assert( zName ); tableSeen = 1; if( i>0 && zTName==0 && (selFlags & SF_NestedFrom)==0 ){ @@ -146633,7 +149175,8 @@ static int selectExpander(Walker *pWalker, Select *p){ pX = &pNew->a[pNew->nExpr-1]; assert( pX->zEName==0 ); if( (selFlags & SF_NestedFrom)!=0 && !IN_RENAME_OBJECT ){ - if( pNestedFrom ){ + if( pNestedFrom && (!ViewCanHaveRowid || jnExpr) ){ + assert( jnExpr ); pX->zEName = sqlite3DbStrDup(db, pNestedFrom->a[j].zEName); testcase( pX->zEName==0 ); }else{ @@ -146641,11 +149184,11 @@ static int selectExpander(Walker *pWalker, Select *p){ zSchemaName, zTabName, zName); testcase( pX->zEName==0 ); } - pX->fg.eEName = ENAME_TAB; + pX->fg.eEName = (j==pTab->nCol ? ENAME_ROWID : ENAME_TAB); if( (pFrom->fg.isUsing && sqlite3IdListIndex(pFrom->u3.pUsing, zName)>=0) || (pUsing && sqlite3IdListIndex(pUsing, zName)>=0) - || (pTab->aCol[j].colFlags & COLFLAG_NOEXPAND)!=0 + || (jnCol && (pTab->aCol[j].colFlags & COLFLAG_NOEXPAND)) ){ pX->fg.bNoExpand = 1; } @@ -146747,10 +149290,10 @@ static void selectAddSubqueryTypeInfo(Walker *pWalker, Select *p){ SrcList *pTabList; SrcItem *pFrom; - assert( p->selFlags & SF_Resolved ); if( p->selFlags & SF_HasTypeInfo ) return; p->selFlags |= SF_HasTypeInfo; pParse = pWalker->pParse; + assert( (p->selFlags & SF_Resolved) ); pTabList = p->pSrc; for(i=0, pFrom=pTabList->a; inSrc; i++, pFrom++){ Table *pTab = pFrom->pTab; @@ -146820,6 +149363,8 @@ SQLITE_PRIVATE void sqlite3SelectPrep( */ static void printAggInfo(AggInfo *pAggInfo){ int ii; + sqlite3DebugPrintf("AggInfo %d/%p:\n", + pAggInfo->selId, pAggInfo); for(ii=0; iinColumn; ii++){ struct AggInfo_col *pCol = &pAggInfo->aCol[ii]; sqlite3DebugPrintf( @@ -146866,8 +149411,14 @@ static void analyzeAggFuncArgs( pNC->ncFlags |= NC_InAggFunc; for(i=0; inFunc; i++){ Expr *pExpr = pAggInfo->aFunc[i].pFExpr; + assert( pExpr->op==TK_FUNCTION || pExpr->op==TK_AGG_FUNCTION ); assert( ExprUseXList(pExpr) ); sqlite3ExprAnalyzeAggList(pNC, pExpr->x.pList); + if( pExpr->pLeft ){ + assert( pExpr->pLeft->op==TK_ORDER ); + assert( ExprUseXList(pExpr->pLeft) ); + sqlite3ExprAnalyzeAggList(pNC, pExpr->pLeft->x.pList); + } #ifndef SQLITE_OMIT_WINDOWFUNC assert( !IsWindowFunc(pExpr) ); if( ExprHasProperty(pExpr, EP_WinFunc) ){ @@ -147022,6 +149573,36 @@ static void resetAccumulator(Parse *pParse, AggInfo *pAggInfo){ pFunc->pFunc->zName)); } } + if( pFunc->iOBTab>=0 ){ + ExprList *pOBList; + KeyInfo *pKeyInfo; + int nExtra = 0; + assert( pFunc->pFExpr->pLeft!=0 ); + assert( pFunc->pFExpr->pLeft->op==TK_ORDER ); + assert( ExprUseXList(pFunc->pFExpr->pLeft) ); + assert( pFunc->pFunc!=0 ); + pOBList = pFunc->pFExpr->pLeft->x.pList; + if( !pFunc->bOBUnique ){ + nExtra++; /* One extra column for the OP_Sequence */ + } + if( pFunc->bOBPayload ){ + /* extra columns for the function arguments */ + assert( ExprUseXList(pFunc->pFExpr) ); + nExtra += pFunc->pFExpr->x.pList->nExpr; + } + if( pFunc->bUseSubtype ){ + nExtra += pFunc->pFExpr->x.pList->nExpr; + } + pKeyInfo = sqlite3KeyInfoFromExprList(pParse, pOBList, 0, nExtra); + if( !pFunc->bOBUnique && pParse->nErr==0 ){ + pKeyInfo->nKeyField++; + } + sqlite3VdbeAddOp4(v, OP_OpenEphemeral, + pFunc->iOBTab, pOBList->nExpr+nExtra, 0, + (char*)pKeyInfo, P4_KEYINFO); + ExplainQueryPlan((pParse, 0, "USE TEMP B-TREE FOR %s(ORDER BY)", + pFunc->pFunc->zName)); + } } } @@ -147037,13 +149618,56 @@ static void finalizeAggFunctions(Parse *pParse, AggInfo *pAggInfo){ ExprList *pList; assert( ExprUseXList(pF->pFExpr) ); pList = pF->pFExpr->x.pList; + if( pF->iOBTab>=0 ){ + /* For an ORDER BY aggregate, calls to OP_AggStep were deferred. Inputs + ** were stored in emphermal table pF->iOBTab. Here, we extract those + ** inputs (in ORDER BY order) and make all calls to OP_AggStep + ** before doing the OP_AggFinal call. */ + int iTop; /* Start of loop for extracting columns */ + int nArg; /* Number of columns to extract */ + int nKey; /* Key columns to be skipped */ + int regAgg; /* Extract into this array */ + int j; /* Loop counter */ + + assert( pF->pFunc!=0 ); + nArg = pList->nExpr; + regAgg = sqlite3GetTempRange(pParse, nArg); + + if( pF->bOBPayload==0 ){ + nKey = 0; + }else{ + assert( pF->pFExpr->pLeft!=0 ); + assert( ExprUseXList(pF->pFExpr->pLeft) ); + assert( pF->pFExpr->pLeft->x.pList!=0 ); + nKey = pF->pFExpr->pLeft->x.pList->nExpr; + if( ALWAYS(!pF->bOBUnique) ) nKey++; + } + iTop = sqlite3VdbeAddOp1(v, OP_Rewind, pF->iOBTab); VdbeCoverage(v); + for(j=nArg-1; j>=0; j--){ + sqlite3VdbeAddOp3(v, OP_Column, pF->iOBTab, nKey+j, regAgg+j); + } + if( pF->bUseSubtype ){ + int regSubtype = sqlite3GetTempReg(pParse); + int iBaseCol = nKey + nArg + (pF->bOBPayload==0 && pF->bOBUnique==0); + for(j=nArg-1; j>=0; j--){ + sqlite3VdbeAddOp3(v, OP_Column, pF->iOBTab, iBaseCol+j, regSubtype); + sqlite3VdbeAddOp2(v, OP_SetSubtype, regSubtype, regAgg+j); + } + sqlite3ReleaseTempReg(pParse, regSubtype); + } + sqlite3VdbeAddOp3(v, OP_AggStep, 0, regAgg, AggInfoFuncReg(pAggInfo,i)); + sqlite3VdbeAppendP4(v, pF->pFunc, P4_FUNCDEF); + sqlite3VdbeChangeP5(v, (u8)nArg); + sqlite3VdbeAddOp2(v, OP_Next, pF->iOBTab, iTop+1); VdbeCoverage(v); + sqlite3VdbeJumpHere(v, iTop); + sqlite3ReleaseTempRange(pParse, regAgg, nArg); + } sqlite3VdbeAddOp2(v, OP_AggFinal, AggInfoFuncReg(pAggInfo,i), pList ? pList->nExpr : 0); sqlite3VdbeAppendP4(v, pF->pFunc, P4_FUNCDEF); } } - /* ** Generate code that will update the accumulator memory cells for an ** aggregate based on the current cursor position. @@ -147052,6 +149676,13 @@ static void finalizeAggFunctions(Parse *pParse, AggInfo *pAggInfo){ ** in pAggInfo, then only populate the pAggInfo->nAccumulator accumulator ** registers if register regAcc contains 0. The caller will take care ** of setting and clearing regAcc. +** +** For an ORDER BY aggregate, the actual accumulator memory cell update +** is deferred until after all input rows have been received, so that they +** can be run in the requested order. In that case, instead of invoking +** OP_AggStep to update the accumulator, just add the arguments that would +** have been passed into OP_AggStep into the sorting ephemeral table +** (along with the appropriate sort key). */ static void updateAccumulator( Parse *pParse, @@ -147073,9 +149704,12 @@ static void updateAccumulator( int nArg; int addrNext = 0; int regAgg; + int regAggSz = 0; + int regDistinct = 0; ExprList *pList; assert( ExprUseXList(pF->pFExpr) ); assert( !IsWindowFunc(pF->pFExpr) ); + assert( pF->pFunc!=0 ); pList = pF->pFExpr->x.pList; if( ExprHasProperty(pF->pFExpr, EP_WinFunc) ){ Expr *pFilter = pF->pFExpr->y.pWin->pFilter; @@ -147099,9 +149733,55 @@ static void updateAccumulator( addrNext = sqlite3VdbeMakeLabel(pParse); sqlite3ExprIfFalse(pParse, pFilter, addrNext, SQLITE_JUMPIFNULL); } - if( pList ){ + if( pF->iOBTab>=0 ){ + /* Instead of invoking AggStep, we must push the arguments that would + ** have been passed to AggStep onto the sorting table. */ + int jj; /* Registered used so far in building the record */ + ExprList *pOBList; /* The ORDER BY clause */ + assert( pList!=0 ); + nArg = pList->nExpr; + assert( nArg>0 ); + assert( pF->pFExpr->pLeft!=0 ); + assert( pF->pFExpr->pLeft->op==TK_ORDER ); + assert( ExprUseXList(pF->pFExpr->pLeft) ); + pOBList = pF->pFExpr->pLeft->x.pList; + assert( pOBList!=0 ); + assert( pOBList->nExpr>0 ); + regAggSz = pOBList->nExpr; + if( !pF->bOBUnique ){ + regAggSz++; /* One register for OP_Sequence */ + } + if( pF->bOBPayload ){ + regAggSz += nArg; + } + if( pF->bUseSubtype ){ + regAggSz += nArg; + } + regAggSz++; /* One extra register to hold result of MakeRecord */ + regAgg = sqlite3GetTempRange(pParse, regAggSz); + regDistinct = regAgg; + sqlite3ExprCodeExprList(pParse, pOBList, regAgg, 0, SQLITE_ECEL_DUP); + jj = pOBList->nExpr; + if( !pF->bOBUnique ){ + sqlite3VdbeAddOp2(v, OP_Sequence, pF->iOBTab, regAgg+jj); + jj++; + } + if( pF->bOBPayload ){ + regDistinct = regAgg+jj; + sqlite3ExprCodeExprList(pParse, pList, regDistinct, 0, SQLITE_ECEL_DUP); + jj += nArg; + } + if( pF->bUseSubtype ){ + int kk; + int regBase = pF->bOBPayload ? regDistinct : regAgg; + for(kk=0; kknExpr; regAgg = sqlite3GetTempRange(pParse, nArg); + regDistinct = regAgg; sqlite3ExprCodeExprList(pParse, pList, regAgg, 0, SQLITE_ECEL_DUP); }else{ nArg = 0; @@ -147112,26 +149792,37 @@ static void updateAccumulator( addrNext = sqlite3VdbeMakeLabel(pParse); } pF->iDistinct = codeDistinct(pParse, eDistinctType, - pF->iDistinct, addrNext, pList, regAgg); - } - if( pF->pFunc->funcFlags & SQLITE_FUNC_NEEDCOLL ){ - CollSeq *pColl = 0; - struct ExprList_item *pItem; - int j; - assert( pList!=0 ); /* pList!=0 if pF->pFunc has NEEDCOLL */ - for(j=0, pItem=pList->a; !pColl && jpExpr); - } - if( !pColl ){ - pColl = pParse->db->pDfltColl; + pF->iDistinct, addrNext, pList, regDistinct); + } + if( pF->iOBTab>=0 ){ + /* Insert a new record into the ORDER BY table */ + sqlite3VdbeAddOp3(v, OP_MakeRecord, regAgg, regAggSz-1, + regAgg+regAggSz-1); + sqlite3VdbeAddOp4Int(v, OP_IdxInsert, pF->iOBTab, regAgg+regAggSz-1, + regAgg, regAggSz-1); + sqlite3ReleaseTempRange(pParse, regAgg, regAggSz); + }else{ + /* Invoke the AggStep function */ + if( pF->pFunc->funcFlags & SQLITE_FUNC_NEEDCOLL ){ + CollSeq *pColl = 0; + struct ExprList_item *pItem; + int j; + assert( pList!=0 ); /* pList!=0 if pF->pFunc has NEEDCOLL */ + for(j=0, pItem=pList->a; !pColl && jpExpr); + } + if( !pColl ){ + pColl = pParse->db->pDfltColl; + } + if( regHit==0 && pAggInfo->nAccumulator ) regHit = ++pParse->nMem; + sqlite3VdbeAddOp4(v, OP_CollSeq, regHit, 0, 0, + (char *)pColl, P4_COLLSEQ); } - if( regHit==0 && pAggInfo->nAccumulator ) regHit = ++pParse->nMem; - sqlite3VdbeAddOp4(v, OP_CollSeq, regHit, 0, 0, (char *)pColl, P4_COLLSEQ); + sqlite3VdbeAddOp3(v, OP_AggStep, 0, regAgg, AggInfoFuncReg(pAggInfo,i)); + sqlite3VdbeAppendP4(v, pF->pFunc, P4_FUNCDEF); + sqlite3VdbeChangeP5(v, (u8)nArg); + sqlite3ReleaseTempRange(pParse, regAgg, nArg); } - sqlite3VdbeAddOp3(v, OP_AggStep, 0, regAgg, AggInfoFuncReg(pAggInfo,i)); - sqlite3VdbeAppendP4(v, pF->pFunc, P4_FUNCDEF); - sqlite3VdbeChangeP5(v, (u8)nArg); - sqlite3ReleaseTempRange(pParse, regAgg, nArg); if( addrNext ){ sqlite3VdbeResolveLabel(v, addrNext); } @@ -147290,7 +149981,8 @@ static SrcItem *isSelfJoinView( /* ** Deallocate a single AggInfo object */ -static void agginfoFree(sqlite3 *db, AggInfo *p){ +static void agginfoFree(sqlite3 *db, void *pArg){ + AggInfo *p = (AggInfo*)pArg; sqlite3DbFree(db, p->aCol); sqlite3DbFree(db, p->aFunc); sqlite3DbFreeNN(db, p); @@ -147364,7 +150056,7 @@ static int countOfViewOptimization(Parse *pParse, Select *p){ pSub->selFlags |= SF_Aggregate; pSub->selFlags &= ~SF_Compound; pSub->nSelectRow = 0; - sqlite3ExprListDelete(db, pSub->pEList); + sqlite3ParserAddCleanup(pParse, sqlite3ExprListDeleteGeneric, pSub->pEList); pTerm = pPrior ? sqlite3ExprDup(db, pCount, 0) : pCount; pSub->pEList = sqlite3ExprListAppend(pParse, 0, pTerm); pTerm = sqlite3PExpr(pParse, TK_SELECT, 0, 0); @@ -147544,9 +150236,8 @@ SQLITE_PRIVATE int sqlite3Select( sqlite3TreeViewExprList(0, p->pOrderBy, 0, "ORDERBY"); } #endif - sqlite3ParserAddCleanup(pParse, - (void(*)(sqlite3*,void*))sqlite3ExprListDelete, - p->pOrderBy); + sqlite3ParserAddCleanup(pParse, sqlite3ExprListDeleteGeneric, + p->pOrderBy); testcase( pParse->earlyCleanup ); p->pOrderBy = 0; } @@ -147652,6 +150343,7 @@ SQLITE_PRIVATE int sqlite3Select( TREETRACE(0x1000,pParse,p, ("LEFT-JOIN simplifies to JOIN on term %d\n",i)); pItem->fg.jointype &= ~(JT_LEFT|JT_OUTER); + unsetJoinExpr(p->pWhere, pItem->iCursor, 0); } } if( pItem->fg.jointype & JT_LTORJ ){ @@ -147666,17 +150358,15 @@ SQLITE_PRIVATE int sqlite3Select( TREETRACE(0x1000,pParse,p, ("RIGHT-JOIN simplifies to JOIN on term %d\n",j)); pI2->fg.jointype &= ~(JT_RIGHT|JT_OUTER); + unsetJoinExpr(p->pWhere, pI2->iCursor, 1); } } } - for(j=pTabList->nSrc-1; j>=i; j--){ + for(j=pTabList->nSrc-1; j>=0; j--){ pTabList->a[j].fg.jointype &= ~JT_LTORJ; if( pTabList->a[j].fg.jointype & JT_RIGHT ) break; } } - assert( pItem->iCursor>=0 ); - unsetJoinExpr(p->pWhere, pItem->iCursor, - pTabList->a[0].fg.jointype & JT_LTORJ); } /* No further action if this term of the FROM clause is not a subquery */ @@ -147739,9 +150429,8 @@ SQLITE_PRIVATE int sqlite3Select( ){ TREETRACE(0x800,pParse,p, ("omit superfluous ORDER BY on %r FROM-clause subquery\n",i+1)); - sqlite3ParserAddCleanup(pParse, - (void(*)(sqlite3*,void*))sqlite3ExprListDelete, - pSub->pOrderBy); + sqlite3ParserAddCleanup(pParse, sqlite3ExprListDeleteGeneric, + pSub->pOrderBy); pSub->pOrderBy = 0; } @@ -147866,7 +150555,7 @@ SQLITE_PRIVATE int sqlite3Select( /* Generate code for all sub-queries in the FROM clause */ pSub = pItem->pSelect; - if( pSub==0 ) continue; + if( pSub==0 || pItem->addrFillSub!=0 ) continue; /* The code for a subquery should only be generated once. */ assert( pItem->addrFillSub==0 ); @@ -147897,7 +150586,7 @@ SQLITE_PRIVATE int sqlite3Select( #endif assert( pItem->pSelect && (pItem->pSelect->selFlags & SF_PushDown)!=0 ); }else{ - TREETRACE(0x4000,pParse,p,("Push-down not possible\n")); + TREETRACE(0x4000,pParse,p,("WHERE-lcause push-down not possible\n")); } /* Convert unused result columns of the subquery into simple NULL @@ -148270,8 +150959,7 @@ SQLITE_PRIVATE int sqlite3Select( */ pAggInfo = sqlite3DbMallocZero(db, sizeof(*pAggInfo) ); if( pAggInfo ){ - sqlite3ParserAddCleanup(pParse, - (void(*)(sqlite3*,void*))agginfoFree, pAggInfo); + sqlite3ParserAddCleanup(pParse, agginfoFree, pAggInfo); testcase( pParse->earlyCleanup ); } if( db->mallocFailed ){ @@ -148779,6 +151467,12 @@ SQLITE_PRIVATE int sqlite3Select( sqlite3ExprListDelete(db, pMinMaxOrderBy); #ifdef SQLITE_DEBUG if( pAggInfo && !db->mallocFailed ){ +#if TREETRACE_ENABLED + if( sqlite3TreeTrace & 0x20 ){ + TREETRACE(0x20,pParse,p,("Finished with AggInfo\n")); + printAggInfo(pAggInfo); + } +#endif for(i=0; inColumn; i++){ Expr *pExpr = pAggInfo->aCol[i].pCExpr; if( pExpr==0 ) continue; @@ -149192,6 +151886,10 @@ SQLITE_PRIVATE void sqlite3BeginTrigger( sqlite3ErrorMsg(pParse, "cannot create triggers on virtual tables"); goto trigger_orphan_error; } + if( (pTab->tabFlags & TF_Shadow)!=0 && sqlite3ReadOnlyShadowTables(db) ){ + sqlite3ErrorMsg(pParse, "cannot create triggers on shadow tables"); + goto trigger_orphan_error; + } /* Check that the trigger name is not reserved and that no trigger of the ** specified name exists */ @@ -149956,6 +152654,72 @@ static ExprList *sqlite3ExpandReturning( return pNew; } +/* If the Expr node is a subquery or an EXISTS operator or an IN operator that +** uses a subquery, and if the subquery is SF_Correlated, then mark the +** expression as EP_VarSelect. +*/ +static int sqlite3ReturningSubqueryVarSelect(Walker *NotUsed, Expr *pExpr){ + UNUSED_PARAMETER(NotUsed); + if( ExprUseXSelect(pExpr) + && (pExpr->x.pSelect->selFlags & SF_Correlated)!=0 + ){ + testcase( ExprHasProperty(pExpr, EP_VarSelect) ); + ExprSetProperty(pExpr, EP_VarSelect); + } + return WRC_Continue; +} + + +/* +** If the SELECT references the table pWalker->u.pTab, then do two things: +** +** (1) Mark the SELECT as as SF_Correlated. +** (2) Set pWalker->eCode to non-zero so that the caller will know +** that (1) has happened. +*/ +static int sqlite3ReturningSubqueryCorrelated(Walker *pWalker, Select *pSelect){ + int i; + SrcList *pSrc; + assert( pSelect!=0 ); + pSrc = pSelect->pSrc; + assert( pSrc!=0 ); + for(i=0; inSrc; i++){ + if( pSrc->a[i].pTab==pWalker->u.pTab ){ + testcase( pSelect->selFlags & SF_Correlated ); + pSelect->selFlags |= SF_Correlated; + pWalker->eCode = 1; + break; + } + } + return WRC_Continue; +} + +/* +** Scan the expression list that is the argument to RETURNING looking +** for subqueries that depend on the table which is being modified in the +** statement that is hosting the RETURNING clause (pTab). Mark all such +** subqueries as SF_Correlated. If the subqueries are part of an +** expression, mark the expression as EP_VarSelect. +** +** https://sqlite.org/forum/forumpost/2c83569ce8945d39 +*/ +static void sqlite3ProcessReturningSubqueries( + ExprList *pEList, + Table *pTab +){ + Walker w; + memset(&w, 0, sizeof(w)); + w.xExprCallback = sqlite3ExprWalkNoop; + w.xSelectCallback = sqlite3ReturningSubqueryCorrelated; + w.u.pTab = pTab; + sqlite3WalkExprList(&w, pEList); + if( w.eCode ){ + w.xExprCallback = sqlite3ReturningSubqueryVarSelect; + w.xSelectCallback = sqlite3SelectWalkNoop; + sqlite3WalkExprList(&w, pEList); + } +} + /* ** Generate code for the RETURNING trigger. Unlike other triggers ** that invoke a subprogram in the bytecode, the code for RETURNING @@ -149975,16 +152739,24 @@ static void codeReturningTrigger( SrcList sFrom; assert( v!=0 ); - assert( pParse->bReturning ); + if( !pParse->bReturning ){ + /* This RETURNING trigger must be for a different statement as + ** this statement lacks a RETURNING clause. */ + return; + } assert( db->pParse==pParse ); pReturning = pParse->u1.pReturning; - assert( pTrigger == &(pReturning->retTrig) ); + if( pTrigger != &(pReturning->retTrig) ){ + /* This RETURNING trigger is for a different statement */ + return; + } memset(&sSelect, 0, sizeof(sSelect)); memset(&sFrom, 0, sizeof(sFrom)); sSelect.pEList = sqlite3ExprListDup(db, pReturning->pReturnEL, 0); sSelect.pSrc = &sFrom; sFrom.nSrc = 1; sFrom.a[0].pTab = pTab; + sFrom.a[0].zName = pTab->zName; /* tag-20240424-1 */ sFrom.a[0].iCursor = -1; sqlite3SelectPrep(pParse, &sSelect, 0); if( pParse->nErr==0 ){ @@ -150011,6 +152783,7 @@ static void codeReturningTrigger( int i; int nCol = pNew->nExpr; int reg = pParse->nMem+1; + sqlite3ProcessReturningSubqueries(pNew, pTab); pParse->nMem += nCol+2; pReturning->iRetReg = reg; for(i=0; ipUpsertIdx = pIdx; + if( sqlite3UpsertOfIndex(pAll,pIdx)!=pUpsert ){ + /* Really this should be an error. The isDup ON CONFLICT clause will + ** never fire. But this problem was not discovered until three years + ** after multi-CONFLICT upsert was added, and so we silently ignore + ** the problem to prevent breaking applications that might actually + ** have redundant ON CONFLICT clauses. */ + pUpsert->isDup = 1; + } break; } if( pUpsert->pUpsertIdx==0 ){ @@ -152078,9 +154863,13 @@ SQLITE_PRIVATE int sqlite3UpsertNextIsIPK(Upsert *pUpsert){ Upsert *pNext; if( NEVER(pUpsert==0) ) return 0; pNext = pUpsert->pNextUpsert; - if( pNext==0 ) return 1; - if( pNext->pUpsertTarget==0 ) return 1; - if( pNext->pUpsertIdx==0 ) return 1; + while( 1 /*exit-by-return*/ ){ + if( pNext==0 ) return 1; + if( pNext->pUpsertTarget==0 ) return 1; + if( pNext->pUpsertIdx==0 ) return 1; + if( !pNext->isDup ) return 0; + pNext = pNext->pNextUpsert; + } return 0; } @@ -152909,7 +155698,6 @@ SQLITE_PRIVATE void sqlite3VtabUnlockList(sqlite3 *db){ if( p ){ db->pDisconnect = 0; - sqlite3ExpirePreparedStatements(db, 0); do { VTable *pNext = p->pNext; sqlite3VtabUnlock(p); @@ -153206,6 +155994,8 @@ static int vtabCallConstructor( db->pVtabCtx = &sCtx; pTab->nTabRef++; rc = xConstruct(db, pMod->pAux, nArg, azArg, &pVTable->pVtab, &zErr); + assert( pTab!=0 ); + assert( pTab->nTabRef>1 || rc!=SQLITE_OK ); sqlite3DeleteTable(db, pTab); db->pVtabCtx = sCtx.pPrior; if( rc==SQLITE_NOMEM ) sqlite3OomFault(db); @@ -153228,7 +156018,7 @@ static int vtabCallConstructor( pVTable->nRef = 1; if( sCtx.bDeclared==0 ){ const char *zFormat = "vtable constructor did not declare schema: %s"; - *pzErr = sqlite3MPrintf(db, zFormat, pTab->zName); + *pzErr = sqlite3MPrintf(db, zFormat, zModuleName); sqlite3VtabUnlock(pVTable); rc = SQLITE_ERROR; }else{ @@ -153406,19 +156196,38 @@ SQLITE_API int sqlite3_declare_vtab(sqlite3 *db, const char *zCreateTable){ Table *pTab; Parse sParse; int initBusy; + int i; + const unsigned char *z; + static const u8 aKeyword[] = { TK_CREATE, TK_TABLE, 0 }; #ifdef SQLITE_ENABLE_API_ARMOR if( !sqlite3SafetyCheckOk(db) || zCreateTable==0 ){ return SQLITE_MISUSE_BKPT; } #endif + + /* Verify that the first two keywords in the CREATE TABLE statement + ** really are "CREATE" and "TABLE". If this is not the case, then + ** sqlite3_declare_vtab() is being misused. + */ + z = (const unsigned char*)zCreateTable; + for(i=0; aKeyword[i]; i++){ + int tokenType = 0; + do{ z += sqlite3GetToken(z, &tokenType); }while( tokenType==TK_SPACE ); + if( tokenType!=aKeyword[i] ){ + sqlite3ErrorWithMsg(db, SQLITE_ERROR, "syntax error"); + return SQLITE_ERROR; + } + } + sqlite3_mutex_enter(db->mutex); pCtx = db->pVtabCtx; if( !pCtx || pCtx->bDeclared ){ - sqlite3Error(db, SQLITE_MISUSE); + sqlite3Error(db, SQLITE_MISUSE_BKPT); sqlite3_mutex_leave(db->mutex); return SQLITE_MISUSE_BKPT; } + pTab = pCtx->pTab; assert( IsVirtual(pTab) ); @@ -153432,11 +156241,10 @@ SQLITE_API int sqlite3_declare_vtab(sqlite3 *db, const char *zCreateTable){ initBusy = db->init.busy; db->init.busy = 0; sParse.nQueryLoop = 1; - if( SQLITE_OK==sqlite3RunParser(&sParse, zCreateTable) - && ALWAYS(sParse.pNewTable!=0) - && ALWAYS(!db->mallocFailed) - && IsOrdinaryTable(sParse.pNewTable) - ){ + if( SQLITE_OK==sqlite3RunParser(&sParse, zCreateTable) ){ + assert( sParse.pNewTable!=0 ); + assert( !db->mallocFailed ); + assert( IsOrdinaryTable(sParse.pNewTable) ); assert( sParse.zErrMsg==0 ); if( !pTab->aCol ){ Table *pNew = sParse.pNewTable; @@ -154475,7 +157283,7 @@ SQLITE_PRIVATE Bitmask sqlite3WhereGetMask(WhereMaskSet*,int); #ifdef WHERETRACE_ENABLED SQLITE_PRIVATE void sqlite3WhereClausePrint(WhereClause *pWC); SQLITE_PRIVATE void sqlite3WhereTermPrint(WhereTerm *pTerm, int iTerm); -SQLITE_PRIVATE void sqlite3WhereLoopPrint(WhereLoop *p, WhereClause *pWC); +SQLITE_PRIVATE void sqlite3WhereLoopPrint(const WhereLoop *p, const WhereClause *pWC); #endif SQLITE_PRIVATE WhereTerm *sqlite3WhereFindTerm( WhereClause *pWC, /* The WHERE clause to be searched */ @@ -154606,7 +157414,7 @@ SQLITE_PRIVATE void sqlite3WhereTabFuncArgs(Parse*, SrcItem*, WhereClause*); #define WHERE_BLOOMFILTER 0x00400000 /* Consider using a Bloom-filter */ #define WHERE_SELFCULL 0x00800000 /* nOut reduced by extra WHERE terms */ #define WHERE_OMIT_OFFSET 0x01000000 /* Set offset counter to zero */ -#define WHERE_VIEWSCAN 0x02000000 /* A full-scan of a VIEW or subquery */ + /* 0x02000000 -- available for reuse */ #define WHERE_EXPRIDX 0x04000000 /* Uses an index-on-expressions */ #endif /* !defined(SQLITE_WHEREINT_H) */ @@ -155931,6 +158739,27 @@ static SQLITE_NOINLINE void filterPullDown( } } +/* +** Loop pLoop is a WHERE_INDEXED level that uses at least one IN(...) +** operator. Return true if level pLoop is guaranteed to visit only one +** row for each key generated for the index. +*/ +static int whereLoopIsOneRow(WhereLoop *pLoop){ + if( pLoop->u.btree.pIndex->onError + && pLoop->nSkip==0 + && pLoop->u.btree.nEq==pLoop->u.btree.pIndex->nKeyCol + ){ + int ii; + for(ii=0; iiu.btree.nEq; ii++){ + if( pLoop->aLTerm[ii]->eOperator & (WO_IS|WO_ISNULL) ){ + return 0; + } + } + return 1; + } + return 0; +} + /* ** Generate code for the start of the iLevel-th loop in the WHERE clause ** implementation described by pWInfo. @@ -156009,7 +158838,7 @@ SQLITE_PRIVATE Bitmask sqlite3WhereCodeOneLoopStart( if( pLevel->iFrom>0 && (pTabItem[0].fg.jointype & JT_LEFT)!=0 ){ pLevel->iLeftJoin = ++pParse->nMem; sqlite3VdbeAddOp2(v, OP_Integer, 0, pLevel->iLeftJoin); - VdbeComment((v, "init LEFT JOIN no-match flag")); + VdbeComment((v, "init LEFT JOIN match flag")); } /* Compute a safe address to jump to if we discover that the table for @@ -156678,7 +159507,9 @@ SQLITE_PRIVATE Bitmask sqlite3WhereCodeOneLoopStart( } /* Record the instruction used to terminate the loop. */ - if( pLoop->wsFlags & WHERE_ONEROW ){ + if( (pLoop->wsFlags & WHERE_ONEROW) + || (pLevel->u.in.nIn && regBignull==0 && whereLoopIsOneRow(pLoop)) + ){ pLevel->op = OP_Noop; }else if( bRev ){ pLevel->op = OP_Prev; @@ -157068,6 +159899,12 @@ SQLITE_PRIVATE Bitmask sqlite3WhereCodeOneLoopStart( ** iLoop==3: Code all remaining expressions. ** ** An effort is made to skip unnecessary iterations of the loop. + ** + ** This optimization of causing simple query restrictions to occur before + ** more complex one is call the "push-down" optimization in MySQL. Here + ** in SQLite, the name is "MySQL push-down", since there is also another + ** totally unrelated optimization called "WHERE-clause push-down". + ** Sometimes the qualifier is omitted, resulting in an ambiguity, so beware. */ iLoop = (pIdx ? 1 : 2); do{ @@ -157318,7 +160155,16 @@ SQLITE_PRIVATE SQLITE_NOINLINE void sqlite3WhereRightJoinLoop( pRJ->regReturn); for(k=0; ka[k].pWLoop->iTab == pWInfo->a[k].iFrom ); + pRight = &pWInfo->pTabList->a[pWInfo->a[k].iFrom]; mAll |= pWInfo->a[k].pWLoop->maskSelf; + if( pRight->fg.viaCoroutine ){ + sqlite3VdbeAddOp3( + v, OP_Null, 0, pRight->regResult, + pRight->regResult + pRight->pSelect->pEList->nExpr-1 + ); + } sqlite3VdbeAddOp1(v, OP_NullRow, pWInfo->a[k].iTabCur); iIdxCur = pWInfo->a[k].iIdxCur; if( iIdxCur ){ @@ -158375,7 +161221,7 @@ static SQLITE_NOINLINE int exprMightBeIndexed2( if( pIdx->aiColumn[i]!=XN_EXPR ) continue; assert( pIdx->bHasExpr ); if( sqlite3ExprCompareSkip(pExpr,pIdx->aColExpr->a[i].pExpr,iCur)==0 - && pExpr->op!=TK_STRING + && !sqlite3ExprIsConstant(0,pIdx->aColExpr->a[i].pExpr) ){ aiCurCol[0] = iCur; aiCurCol[1] = XN_EXPR; @@ -159024,6 +161870,7 @@ SQLITE_PRIVATE void SQLITE_NOINLINE sqlite3WhereAddLimit(WhereClause *pWC, Selec continue; } if( pWC->a[ii].leftCursor!=iCsr ) return; + if( pWC->a[ii].prereqRight!=0 ) return; } /* Check condition (5). Return early if it is not met. */ @@ -159038,12 +161885,14 @@ SQLITE_PRIVATE void SQLITE_NOINLINE sqlite3WhereAddLimit(WhereClause *pWC, Selec /* All conditions are met. Add the terms to the where-clause object. */ assert( p->pLimit->op==TK_LIMIT ); - whereAddLimitExpr(pWC, p->iLimit, p->pLimit->pLeft, - iCsr, SQLITE_INDEX_CONSTRAINT_LIMIT); - if( p->iOffset>0 ){ + if( p->iOffset!=0 && (p->selFlags & SF_Compound)==0 ){ whereAddLimitExpr(pWC, p->iOffset, p->pLimit->pRight, iCsr, SQLITE_INDEX_CONSTRAINT_OFFSET); } + if( p->iOffset==0 || (p->selFlags & SF_Compound)==0 ){ + whereAddLimitExpr(pWC, p->iLimit, p->pLimit->pLeft, + iCsr, SQLITE_INDEX_CONSTRAINT_LIMIT); + } } } @@ -159561,6 +162410,42 @@ static Expr *whereRightSubexprIsColumn(Expr *p){ return 0; } +/* +** Term pTerm is guaranteed to be a WO_IN term. It may be a component term +** of a vector IN expression of the form "(x, y, ...) IN (SELECT ...)". +** This function checks to see if the term is compatible with an index +** column with affinity idxaff (one of the SQLITE_AFF_XYZ values). If so, +** it returns a pointer to the name of the collation sequence (e.g. "BINARY" +** or "NOCASE") used by the comparison in pTerm. If it is not compatible +** with affinity idxaff, NULL is returned. +*/ +static SQLITE_NOINLINE const char *indexInAffinityOk( + Parse *pParse, + WhereTerm *pTerm, + u8 idxaff +){ + Expr *pX = pTerm->pExpr; + Expr inexpr; + + assert( pTerm->eOperator & WO_IN ); + + if( sqlite3ExprIsVector(pX->pLeft) ){ + int iField = pTerm->u.x.iField - 1; + inexpr.flags = 0; + inexpr.op = TK_EQ; + inexpr.pLeft = pX->pLeft->x.pList->a[iField].pExpr; + assert( ExprUseXSelect(pX) ); + inexpr.pRight = pX->x.pSelect->pEList->a[iField].pExpr; + pX = &inexpr; + } + + if( sqlite3IndexAffinityOk(pX, idxaff) ){ + CollSeq *pRet = sqlite3ExprCompareCollSeq(pParse, pX); + return pRet ? pRet->zName : sqlite3StrBINARY; + } + return 0; +} + /* ** Advance to the next WhereTerm that matches according to the criteria ** established when the pScan object was initialized by whereScanInit(). @@ -159611,16 +162496,24 @@ static WhereTerm *whereScanNext(WhereScan *pScan){ if( (pTerm->eOperator & pScan->opMask)!=0 ){ /* Verify the affinity and collating sequence match */ if( pScan->zCollName && (pTerm->eOperator & WO_ISNULL)==0 ){ - CollSeq *pColl; + const char *zCollName; Parse *pParse = pWC->pWInfo->pParse; pX = pTerm->pExpr; - if( !sqlite3IndexAffinityOk(pX, pScan->idxaff) ){ - continue; + + if( (pTerm->eOperator & WO_IN) ){ + zCollName = indexInAffinityOk(pParse, pTerm, pScan->idxaff); + if( !zCollName ) continue; + }else{ + CollSeq *pColl; + if( !sqlite3IndexAffinityOk(pX, pScan->idxaff) ){ + continue; + } + assert(pX->pLeft); + pColl = sqlite3ExprCompareCollSeq(pParse, pX); + zCollName = pColl ? pColl->zName : sqlite3StrBINARY; } - assert(pX->pLeft); - pColl = sqlite3ExprCompareCollSeq(pParse, pX); - if( pColl==0 ) pColl = pParse->db->pDfltColl; - if( sqlite3StrICmp(pColl->zName, pScan->zCollName) ){ + + if( sqlite3StrICmp(zCollName, pScan->zCollName) ){ continue; } } @@ -159937,12 +162830,22 @@ static void translateColumnToCopy( for(; iStartp1!=iTabCur ) continue; if( pOp->opcode==OP_Column ){ +#ifdef SQLITE_DEBUG + if( pParse->db->flags & SQLITE_VdbeAddopTrace ){ + printf("TRANSLATE OP_Column to OP_Copy at %d\n", iStart); + } +#endif pOp->opcode = OP_Copy; pOp->p1 = pOp->p2 + iRegister; pOp->p2 = pOp->p3; pOp->p3 = 0; pOp->p5 = 2; /* Cause the MEM_Subtype flag to be cleared */ }else if( pOp->opcode==OP_Rowid ){ +#ifdef SQLITE_DEBUG + if( pParse->db->flags & SQLITE_VdbeAddopTrace ){ + printf("TRANSLATE OP_Rowid to OP_Sequence at %d\n", iStart); + } +#endif pOp->opcode = OP_Sequence; pOp->p1 = iAutoidxCur; #ifdef SQLITE_ALLOW_ROWID_IN_VIEW @@ -159962,9 +162865,13 @@ static void translateColumnToCopy( ** are no-ops. */ #if !defined(SQLITE_OMIT_VIRTUALTABLE) && defined(WHERETRACE_ENABLED) -static void whereTraceIndexInfoInputs(sqlite3_index_info *p){ +static void whereTraceIndexInfoInputs( + sqlite3_index_info *p, /* The IndexInfo object */ + Table *pTab /* The TABLE that is the virtual table */ +){ int i; if( (sqlite3WhereTrace & 0x10)==0 ) return; + sqlite3DebugPrintf("sqlite3_index_info inputs for %s:\n", pTab->zName); for(i=0; inConstraint; i++){ sqlite3DebugPrintf( " constraint[%d]: col=%d termid=%d op=%d usabled=%d collseq=%s\n", @@ -159982,9 +162889,13 @@ static void whereTraceIndexInfoInputs(sqlite3_index_info *p){ p->aOrderBy[i].desc); } } -static void whereTraceIndexInfoOutputs(sqlite3_index_info *p){ +static void whereTraceIndexInfoOutputs( + sqlite3_index_info *p, /* The IndexInfo object */ + Table *pTab /* The TABLE that is the virtual table */ +){ int i; if( (sqlite3WhereTrace & 0x10)==0 ) return; + sqlite3DebugPrintf("sqlite3_index_info outputs for %s:\n", pTab->zName); for(i=0; inConstraint; i++){ sqlite3DebugPrintf(" usage[%d]: argvIdx=%d omit=%d\n", i, @@ -159998,8 +162909,8 @@ static void whereTraceIndexInfoOutputs(sqlite3_index_info *p){ sqlite3DebugPrintf(" estimatedRows=%lld\n", p->estimatedRows); } #else -#define whereTraceIndexInfoInputs(A) -#define whereTraceIndexInfoOutputs(A) +#define whereTraceIndexInfoInputs(A,B) +#define whereTraceIndexInfoOutputs(A,B) #endif /* @@ -160183,7 +163094,7 @@ static SQLITE_NOINLINE void constructAutomaticIndex( ** WHERE clause (or the ON clause of a LEFT join) that constrain which ** rows of the target table (pSrc) that can be used. */ if( (pTerm->wtFlags & TERM_VIRTUAL)==0 - && sqlite3ExprIsSingleTableConstraint(pExpr, pTabList, pLevel->iFrom) + && sqlite3ExprIsSingleTableConstraint(pExpr, pTabList, pLevel->iFrom, 0) ){ pPartial = sqlite3ExprAnd(pParse, pPartial, sqlite3ExprDup(pParse->db, pExpr, 0)); @@ -160225,7 +163136,7 @@ static SQLITE_NOINLINE void constructAutomaticIndex( ** if they go out of sync. */ if( IsView(pTable) ){ - extraCols = ALLBITS; + extraCols = ALLBITS & ~idxCols; }else{ extraCols = pSrc->colUsed & (~idxCols | MASKBIT(BMS-1)); } @@ -160401,13 +163312,17 @@ static SQLITE_NOINLINE void sqlite3ConstructBloomFilter( WhereLoop *pLoop = pLevel->pWLoop; /* The loop being coded */ int iCur; /* Cursor for table getting the filter */ IndexedExpr *saved_pIdxEpr; /* saved copy of Parse.pIdxEpr */ + IndexedExpr *saved_pIdxPartExpr; /* saved copy of Parse.pIdxPartExpr */ saved_pIdxEpr = pParse->pIdxEpr; + saved_pIdxPartExpr = pParse->pIdxPartExpr; pParse->pIdxEpr = 0; + pParse->pIdxPartExpr = 0; assert( pLoop!=0 ); assert( v!=0 ); assert( pLoop->wsFlags & WHERE_BLOOMFILTER ); + assert( (pLoop->wsFlags & WHERE_IDX_ONLY)==0 ); addrOnce = sqlite3VdbeAddOp0(v, OP_Once); VdbeCoverage(v); do{ @@ -160448,7 +163363,7 @@ static SQLITE_NOINLINE void sqlite3ConstructBloomFilter( for(pTerm=pWInfo->sWC.a; pTermpExpr; if( (pTerm->wtFlags & TERM_VIRTUAL)==0 - && sqlite3ExprIsSingleTableConstraint(pExpr, pTabList, iSrc) + && sqlite3ExprIsSingleTableConstraint(pExpr, pTabList, iSrc, 0) ){ sqlite3ExprIfFalse(pParse, pTerm->pExpr, addrCont, SQLITE_JUMPIFNULL); } @@ -160497,6 +163412,7 @@ static SQLITE_NOINLINE void sqlite3ConstructBloomFilter( }while( iLevel < pWInfo->nLevel ); sqlite3VdbeJumpHere(v, addrOnce); pParse->pIdxEpr = saved_pIdxEpr; + pParse->pIdxPartExpr = saved_pIdxPartExpr; } @@ -160573,7 +163489,7 @@ static sqlite3_index_info *allocateIndexInfo( Expr *pE2; /* Skip over constant terms in the ORDER BY clause */ - if( sqlite3ExprIsConstant(pExpr) ){ + if( sqlite3ExprIsConstant(0, pExpr) ){ continue; } @@ -160608,7 +163524,7 @@ static sqlite3_index_info *allocateIndexInfo( } if( i==n ){ nOrderBy = n; - if( (pWInfo->wctrlFlags & WHERE_DISTINCTBY) ){ + if( (pWInfo->wctrlFlags & WHERE_DISTINCTBY) && !pSrc->fg.rowidUsed ){ eDistinct = 2 + ((pWInfo->wctrlFlags & WHERE_SORTBYGROUP)!=0); }else if( pWInfo->wctrlFlags & WHERE_GROUPBY ){ eDistinct = 1; @@ -160685,7 +163601,7 @@ static sqlite3_index_info *allocateIndexInfo( pIdxInfo->nConstraint = j; for(i=j=0; ia[i].pExpr; - if( sqlite3ExprIsConstant(pExpr) ) continue; + if( sqlite3ExprIsConstant(0, pExpr) ) continue; assert( pExpr->op==TK_COLUMN || (pExpr->op==TK_COLLATE && pExpr->pLeft->op==TK_COLUMN && pExpr->iColumn==pExpr->pLeft->iColumn) ); @@ -160737,11 +163653,11 @@ static int vtabBestIndex(Parse *pParse, Table *pTab, sqlite3_index_info *p){ sqlite3_vtab *pVtab = sqlite3GetVTable(pParse->db, pTab)->pVtab; int rc; - whereTraceIndexInfoInputs(p); + whereTraceIndexInfoInputs(p, pTab); pParse->db->nSchemaLock++; rc = pVtab->pModule->xBestIndex(pVtab, p); pParse->db->nSchemaLock--; - whereTraceIndexInfoOutputs(p); + whereTraceIndexInfoOutputs(p, pTab); if( rc!=SQLITE_OK && rc!=SQLITE_CONSTRAINT ){ if( rc==SQLITE_NOMEM ){ @@ -161264,7 +164180,8 @@ static int whereRangeScanEst( ** sample, then assume they are 4x more selective. This brings ** the estimated selectivity more in line with what it would be ** if estimated without the use of STAT4 tables. */ - if( iLwrIdx==iUprIdx ) nNew -= 20; assert( 20==sqlite3LogEst(4) ); + if( iLwrIdx==iUprIdx ){ nNew -= 20; } + assert( 20==sqlite3LogEst(4) ); }else{ nNew = 10; assert( 10==sqlite3LogEst(2) ); } @@ -161488,17 +164405,34 @@ SQLITE_PRIVATE void sqlite3WhereClausePrint(WhereClause *pWC){ #ifdef WHERETRACE_ENABLED /* ** Print a WhereLoop object for debugging purposes -*/ -SQLITE_PRIVATE void sqlite3WhereLoopPrint(WhereLoop *p, WhereClause *pWC){ - WhereInfo *pWInfo = pWC->pWInfo; - int nb = 1+(pWInfo->pTabList->nSrc+3)/4; - SrcItem *pItem = pWInfo->pTabList->a + p->iTab; - Table *pTab = pItem->pTab; - Bitmask mAll = (((Bitmask)1)<<(nb*4)) - 1; - sqlite3DebugPrintf("%c%2d.%0*llx.%0*llx", p->cId, - p->iTab, nb, p->maskSelf, nb, p->prereq & mAll); - sqlite3DebugPrintf(" %12s", - pItem->zAlias ? pItem->zAlias : pTab->zName); +** +** Format example: +** +** .--- Position in WHERE clause rSetup, rRun, nOut ---. +** | | +** | .--- selfMask nTerm ------. | +** | | | | +** | | .-- prereq Idx wsFlags----. | | +** | | | Name | | | +** | | | __|__ nEq ---. ___|__ | __|__ +** | / \ / \ / \ | / \ / \ / \ +** 1.002.001 t2.t2xy 2 f 010241 N 2 cost 0,56,31 +*/ +SQLITE_PRIVATE void sqlite3WhereLoopPrint(const WhereLoop *p, const WhereClause *pWC){ + if( pWC ){ + WhereInfo *pWInfo = pWC->pWInfo; + int nb = 1+(pWInfo->pTabList->nSrc+3)/4; + SrcItem *pItem = pWInfo->pTabList->a + p->iTab; + Table *pTab = pItem->pTab; + Bitmask mAll = (((Bitmask)1)<<(nb*4)) - 1; + sqlite3DebugPrintf("%c%2d.%0*llx.%0*llx", p->cId, + p->iTab, nb, p->maskSelf, nb, p->prereq & mAll); + sqlite3DebugPrintf(" %12s", + pItem->zAlias ? pItem->zAlias : pTab->zName); + }else{ + sqlite3DebugPrintf("%c%2d.%03llx.%03llx %c%d", + p->cId, p->iTab, p->maskSelf, p->prereq & 0xfff, p->cId, p->iTab); + } if( (p->wsFlags & WHERE_VIRTUALTABLE)==0 ){ const char *zName; if( p->u.btree.pIndex && (zName = p->u.btree.pIndex->zName)!=0 ){ @@ -161535,6 +164469,15 @@ SQLITE_PRIVATE void sqlite3WhereLoopPrint(WhereLoop *p, WhereClause *pWC){ } } } +SQLITE_PRIVATE void sqlite3ShowWhereLoop(const WhereLoop *p){ + if( p ) sqlite3WhereLoopPrint(p, 0); +} +SQLITE_PRIVATE void sqlite3ShowWhereLoopList(const WhereLoop *p){ + while( p ){ + sqlite3ShowWhereLoop(p); + p = p->pNextLoop; + } +} #endif /* @@ -161647,46 +164590,60 @@ static void whereInfoFree(sqlite3 *db, WhereInfo *pWInfo){ } /* -** Return TRUE if all of the following are true: +** Return TRUE if X is a proper subset of Y but is of equal or less cost. +** In other words, return true if all constraints of X are also part of Y +** and Y has additional constraints that might speed the search that X lacks +** but the cost of running X is not more than the cost of running Y. +** +** In other words, return true if the cost relationwship between X and Y +** is inverted and needs to be adjusted. +** +** Case 1: ** -** (1) X has the same or lower cost, or returns the same or fewer rows, -** than Y. -** (2) X uses fewer WHERE clause terms than Y -** (3) Every WHERE clause term used by X is also used by Y -** (4) X skips at least as many columns as Y -** (5) If X is a covering index, than Y is too +** (1a) X and Y use the same index. +** (1b) X has fewer == terms than Y +** (1c) Neither X nor Y use skip-scan +** (1d) X does not have a a greater cost than Y ** -** Conditions (2) and (3) mean that X is a "proper subset" of Y. -** If X is a proper subset of Y then Y is a better choice and ought -** to have a lower cost. This routine returns TRUE when that cost -** relationship is inverted and needs to be adjusted. Constraint (4) -** was added because if X uses skip-scan less than Y it still might -** deserve a lower cost even if it is a proper subset of Y. Constraint (5) -** was added because a covering index probably deserves to have a lower cost -** than a non-covering index even if it is a proper subset. +** Case 2: +** +** (2a) X has the same or lower cost, or returns the same or fewer rows, +** than Y. +** (2b) X uses fewer WHERE clause terms than Y +** (2c) Every WHERE clause term used by X is also used by Y +** (2d) X skips at least as many columns as Y +** (2e) If X is a covering index, than Y is too */ static int whereLoopCheaperProperSubset( const WhereLoop *pX, /* First WhereLoop to compare */ const WhereLoop *pY /* Compare against this WhereLoop */ ){ int i, j; + if( pX->rRun>pY->rRun && pX->nOut>pY->nOut ) return 0; /* (1d) and (2a) */ + assert( (pX->wsFlags & WHERE_VIRTUALTABLE)==0 ); + assert( (pY->wsFlags & WHERE_VIRTUALTABLE)==0 ); + if( pX->u.btree.nEq < pY->u.btree.nEq /* (1b) */ + && pX->u.btree.pIndex==pY->u.btree.pIndex /* (1a) */ + && pX->nSkip==0 && pY->nSkip==0 /* (1c) */ + ){ + return 1; /* Case 1 is true */ + } if( pX->nLTerm-pX->nSkip >= pY->nLTerm-pY->nSkip ){ - return 0; /* X is not a subset of Y */ + return 0; /* (2b) */ } - if( pX->rRun>pY->rRun && pX->nOut>pY->nOut ) return 0; - if( pY->nSkip > pX->nSkip ) return 0; + if( pY->nSkip > pX->nSkip ) return 0; /* (2d) */ for(i=pX->nLTerm-1; i>=0; i--){ if( pX->aLTerm[i]==0 ) continue; for(j=pY->nLTerm-1; j>=0; j--){ if( pY->aLTerm[j]==pX->aLTerm[i] ) break; } - if( j<0 ) return 0; /* X not a subset of Y since term X[i] not used by Y */ + if( j<0 ) return 0; /* (2c) */ } if( (pX->wsFlags&WHERE_IDX_ONLY)!=0 && (pY->wsFlags&WHERE_IDX_ONLY)==0 ){ - return 0; /* Constraint (5) */ + return 0; /* (2e) */ } - return 1; /* All conditions meet */ + return 1; /* Case 2 is true */ } /* @@ -162176,7 +165133,12 @@ static int whereLoopAddBtreeIndex( assert( pNew->u.btree.nBtm==0 ); opMask = WO_EQ|WO_IN|WO_GT|WO_GE|WO_LT|WO_LE|WO_ISNULL|WO_IS; } - if( pProbe->bUnordered ) opMask &= ~(WO_GT|WO_GE|WO_LT|WO_LE); + if( pProbe->bUnordered || pProbe->bLowQual ){ + if( pProbe->bUnordered ) opMask &= ~(WO_GT|WO_GE|WO_LT|WO_LE); + if( pProbe->bLowQual && pSrc->fg.isIndexedBy==0 ){ + opMask &= ~(WO_EQ|WO_IN|WO_IS); + } + } assert( pNew->u.btree.nEqnColumn ); assert( pNew->u.btree.nEqnKeyCol @@ -162442,10 +165404,13 @@ static int whereLoopAddBtreeIndex( } } - /* Set rCostIdx to the cost of visiting selected rows in index. Add - ** it to pNew->rRun, which is currently set to the cost of the index - ** seek only. Then, if this is a non-covering index, add the cost of - ** visiting the rows in the main table. */ + /* Set rCostIdx to the estimated cost of visiting selected rows in the + ** index. The estimate is the sum of two values: + ** 1. The cost of doing one search-by-key to find the first matching + ** entry + ** 2. Stepping forward in the index pNew->nOut times to find all + ** additional matching entries. + */ assert( pSrc->pTab->szTabRow>0 ); if( pProbe->idxType==SQLITE_IDXTYPE_IPK ){ /* The pProbe->szIdxRow is low for an IPK table since the interior @@ -162456,7 +165421,15 @@ static int whereLoopAddBtreeIndex( }else{ rCostIdx = pNew->nOut + 1 + (15*pProbe->szIdxRow)/pSrc->pTab->szTabRow; } - pNew->rRun = sqlite3LogEstAdd(rLogSize, rCostIdx); + rCostIdx = sqlite3LogEstAdd(rLogSize, rCostIdx); + + /* Estimate the cost of running the loop. If all data is coming + ** from the index, then this is just the cost of doing the index + ** lookup and scan. But if some data is coming out of the main table, + ** we also have to add in the cost of doing pNew->nOut searches to + ** locate the row in the main table that corresponds to the index entry. + */ + pNew->rRun = rCostIdx; if( (pNew->wsFlags & (WHERE_IDX_ONLY|WHERE_IPK|WHERE_EXPRIDX))==0 ){ pNew->rRun = sqlite3LogEstAdd(pNew->rRun, pNew->nOut + 16); } @@ -162562,7 +165535,9 @@ static int indexMightHelpWithOrderBy( for(ii=0; iinExpr; ii++){ Expr *pExpr = sqlite3ExprSkipCollateAndLikely(pOB->a[ii].pExpr); if( NEVER(pExpr==0) ) continue; - if( pExpr->op==TK_COLUMN && pExpr->iTable==iCursor ){ + if( (pExpr->op==TK_COLUMN || pExpr->op==TK_AGG_COLUMN) + && pExpr->iTable==iCursor + ){ if( pExpr->iColumn<0 ) return 1; for(jj=0; jjnKeyCol; jj++){ if( pExpr->iColumn==pIndex->aiColumn[jj] ) return 1; @@ -162756,6 +165731,100 @@ static SQLITE_NOINLINE u32 whereIsCoveringIndex( return rc; } +/* +** This is an sqlite3ParserAddCleanup() callback that is invoked to +** free the Parse->pIdxEpr list when the Parse object is destroyed. +*/ +static void whereIndexedExprCleanup(sqlite3 *db, void *pObject){ + IndexedExpr **pp = (IndexedExpr**)pObject; + while( *pp!=0 ){ + IndexedExpr *p = *pp; + *pp = p->pIENext; + sqlite3ExprDelete(db, p->pExpr); + sqlite3DbFreeNN(db, p); + } +} + +/* +** This function is called for a partial index - one with a WHERE clause - in +** two scenarios. In both cases, it determines whether or not the WHERE +** clause on the index implies that a column of the table may be safely +** replaced by a constant expression. For example, in the following +** SELECT: +** +** CREATE INDEX i1 ON t1(b, c) WHERE a=; +** SELECT a, b, c FROM t1 WHERE a= AND b=?; +** +** The "a" in the select-list may be replaced by , iff: +** +** (a) is a constant expression, and +** (b) The (a=) comparison uses the BINARY collation sequence, and +** (c) Column "a" has an affinity other than NONE or BLOB. +** +** If argument pItem is NULL, then pMask must not be NULL. In this case this +** function is being called as part of determining whether or not pIdx +** is a covering index. This function clears any bits in (*pMask) +** corresponding to columns that may be replaced by constants as described +** above. +** +** Otherwise, if pItem is not NULL, then this function is being called +** as part of coding a loop that uses index pIdx. In this case, add entries +** to the Parse.pIdxPartExpr list for each column that can be replaced +** by a constant. +*/ +static void wherePartIdxExpr( + Parse *pParse, /* Parse context */ + Index *pIdx, /* Partial index being processed */ + Expr *pPart, /* WHERE clause being processed */ + Bitmask *pMask, /* Mask to clear bits in */ + int iIdxCur, /* Cursor number for index */ + SrcItem *pItem /* The FROM clause entry for the table */ +){ + assert( pItem==0 || (pItem->fg.jointype & JT_RIGHT)==0 ); + assert( (pItem==0 || pMask==0) && (pMask!=0 || pItem!=0) ); + + if( pPart->op==TK_AND ){ + wherePartIdxExpr(pParse, pIdx, pPart->pRight, pMask, iIdxCur, pItem); + pPart = pPart->pLeft; + } + + if( (pPart->op==TK_EQ || pPart->op==TK_IS) ){ + Expr *pLeft = pPart->pLeft; + Expr *pRight = pPart->pRight; + u8 aff; + + if( pLeft->op!=TK_COLUMN ) return; + if( !sqlite3ExprIsConstant(0, pRight) ) return; + if( !sqlite3IsBinary(sqlite3ExprCompareCollSeq(pParse, pPart)) ) return; + if( pLeft->iColumn<0 ) return; + aff = pIdx->pTable->aCol[pLeft->iColumn].affinity; + if( aff>=SQLITE_AFF_TEXT ){ + if( pItem ){ + sqlite3 *db = pParse->db; + IndexedExpr *p = (IndexedExpr*)sqlite3DbMallocRaw(db, sizeof(*p)); + if( p ){ + int bNullRow = (pItem->fg.jointype&(JT_LEFT|JT_LTORJ))!=0; + p->pExpr = sqlite3ExprDup(db, pRight, 0); + p->iDataCur = pItem->iCursor; + p->iIdxCur = iIdxCur; + p->iIdxCol = pLeft->iColumn; + p->bMaybeNullRow = bNullRow; + p->pIENext = pParse->pIdxPartExpr; + p->aff = aff; + pParse->pIdxPartExpr = p; + if( p->pIENext==0 ){ + void *pArg = (void*)&pParse->pIdxPartExpr; + sqlite3ParserAddCleanup(pParse, whereIndexedExprCleanup, pArg); + } + } + }else if( pLeft->iColumn<(BMS-1) ){ + *pMask &= ~((Bitmask)1 << pLeft->iColumn); + } + } + } +} + + /* ** Add all WhereLoop objects for a single table of the join where the table ** is identified by pBuilder->pNew->iTab. That table is guaranteed to be @@ -162959,9 +166028,6 @@ static int whereLoopAddBtree( #else pNew->rRun = rSize + 16; #endif - if( IsView(pTab) || (pTab->tabFlags & TF_Ephemeral)!=0 ){ - pNew->wsFlags |= WHERE_VIEWSCAN; - } ApplyCostMultiplier(pNew->rRun, pTab->costMult); whereLoopOutputAdjust(pWC, pNew, rSize); rc = whereLoopInsert(pBuilder, pNew); @@ -162974,6 +166040,11 @@ static int whereLoopAddBtree( pNew->wsFlags = WHERE_IDX_ONLY | WHERE_INDEXED; }else{ m = pSrc->colUsed & pProbe->colNotIdxed; + if( pProbe->pPartIdxWhere ){ + wherePartIdxExpr( + pWInfo->pParse, pProbe, pProbe->pPartIdxWhere, &m, 0, 0 + ); + } pNew->wsFlags = WHERE_INDEXED; if( m==TOPBIT || (pProbe->bHasExpr && !pProbe->bHasVCol && m!=0) ){ u32 isCov = whereIsCoveringIndex(pWInfo, pProbe, pSrc->iCursor); @@ -163072,7 +166143,7 @@ static int whereLoopAddBtree( ** unique index is used (making the index functionally non-unique) ** then the sqlite_stat1 data becomes important for scoring the ** plan */ - pTab->tabFlags |= TF_StatsUsed; + pTab->tabFlags |= TF_MaybeReanalyze; } #ifdef SQLITE_ENABLE_STAT4 sqlite3Stat4ProbeFree(pBuilder->pRec); @@ -163094,6 +166165,21 @@ static int isLimitTerm(WhereTerm *pTerm){ && pTerm->eMatchOp<=SQLITE_INDEX_CONSTRAINT_OFFSET; } +/* +** Return true if the first nCons constraints in the pUsage array are +** marked as in-use (have argvIndex>0). False otherwise. +*/ +static int allConstraintsUsed( + struct sqlite3_index_constraint_usage *aUsage, + int nCons +){ + int ii; + for(ii=0; iipNew->iTab. This @@ -163234,13 +166320,20 @@ static int whereLoopAddVirtualOne( *pbIn = 1; assert( (mExclude & WO_IN)==0 ); } + /* Unless pbRetryLimit is non-NULL, there should be no LIMIT/OFFSET + ** terms. And if there are any, they should follow all other terms. */ assert( pbRetryLimit || !isLimitTerm(pTerm) ); - if( isLimitTerm(pTerm) && *pbIn ){ + assert( !isLimitTerm(pTerm) || i>=nConstraint-2 ); + assert( !isLimitTerm(pTerm) || i==nConstraint-1 || isLimitTerm(pTerm+1) ); + + if( isLimitTerm(pTerm) && (*pbIn || !allConstraintsUsed(pUsage, i)) ){ /* If there is an IN(...) term handled as an == (separate call to ** xFilter for each value on the RHS of the IN) and a LIMIT or - ** OFFSET term handled as well, the plan is unusable. Set output - ** variable *pbRetryLimit to true to tell the caller to retry with - ** LIMIT and OFFSET disabled. */ + ** OFFSET term handled as well, the plan is unusable. Similarly, + ** if there is a LIMIT/OFFSET and there are other unused terms, + ** the plan cannot be used. In these cases set variable *pbRetryLimit + ** to true to tell the caller to retry with LIMIT and OFFSET + ** disabled. */ if( pIdxInfo->needToFreeIdxStr ){ sqlite3_free(pIdxInfo->idxStr); pIdxInfo->idxStr = 0; @@ -163356,7 +166449,7 @@ SQLITE_API int sqlite3_vtab_rhs_value( sqlite3_value *pVal = 0; int rc = SQLITE_OK; if( iCons<0 || iCons>=pIdxInfo->nConstraint ){ - rc = SQLITE_MISUSE; /* EV: R-30545-25046 */ + rc = SQLITE_MISUSE_BKPT; /* EV: R-30545-25046 */ }else{ if( pH->aRhs[iCons]==0 ){ WhereTerm *pTerm = &pH->pWC->a[pIdxInfo->aConstraint[iCons].iTermOffset]; @@ -164097,7 +167190,7 @@ static i8 wherePathSatisfiesOrderBy( if( MASKBIT(i) & obSat ) continue; p = pOrderBy->a[i].pExpr; mTerm = sqlite3WhereExprUsage(&pWInfo->sMaskSet,p); - if( mTerm==0 && !sqlite3ExprIsConstant(p) ) continue; + if( mTerm==0 && !sqlite3ExprIsConstant(0,p) ) continue; if( (mTerm&~orderDistinctMask)==0 ){ obSat |= MASKBIT(i); } @@ -164380,14 +167473,6 @@ static int wherePathSolver(WhereInfo *pWInfo, LogEst nRowEst){ rUnsorted -= 2; /* TUNING: Slight bias in favor of no-sort plans */ } - /* TUNING: A full-scan of a VIEW or subquery in the outer loop - ** is not so bad. */ - if( iLoop==0 && (pWLoop->wsFlags & WHERE_VIEWSCAN)!=0 && nLoop>1 ){ - rCost += -10; - nOut += -30; - WHERETRACE(0x80,("VIEWSCAN cost reduction for %c\n",pWLoop->cId)); - } - /* Check to see if pWLoop should be added to the set of ** mxChoice best-so-far paths. ** @@ -164574,10 +167659,9 @@ static int wherePathSolver(WhereInfo *pWInfo, LogEst nRowEst){ if( pFrom->isOrdered==pWInfo->pOrderBy->nExpr ){ pWInfo->eDistinct = WHERE_DISTINCT_ORDERED; } - if( pWInfo->pSelect->pOrderBy - && pWInfo->nOBSat > pWInfo->pSelect->pOrderBy->nExpr ){ - pWInfo->nOBSat = pWInfo->pSelect->pOrderBy->nExpr; - } + /* vvv--- See check-in [12ad822d9b827777] on 2023-03-16 ---vvv */ + assert( pWInfo->pSelect->pOrderBy==0 + || pWInfo->nOBSat <= pWInfo->pSelect->pOrderBy->nExpr ); }else{ pWInfo->revMask = pFrom->revLoop; if( pWInfo->nOBSat<=0 ){ @@ -164620,7 +167704,6 @@ static int wherePathSolver(WhereInfo *pWInfo, LogEst nRowEst){ } } - pWInfo->nRowOut = pFrom->nRow; /* Free temporary memory and return success */ @@ -164628,6 +167711,83 @@ static int wherePathSolver(WhereInfo *pWInfo, LogEst nRowEst){ return SQLITE_OK; } +/* +** This routine implements a heuristic designed to improve query planning. +** This routine is called in between the first and second call to +** wherePathSolver(). Hence the name "Interstage" "Heuristic". +** +** The first call to wherePathSolver() (hereafter just "solver()") computes +** the best path without regard to the order of the outputs. The second call +** to the solver() builds upon the first call to try to find an alternative +** path that satisfies the ORDER BY clause. +** +** This routine looks at the results of the first solver() run, and for +** every FROM clause term in the resulting query plan that uses an equality +** constraint against an index, disable other WhereLoops for that same +** FROM clause term that would try to do a full-table scan. This prevents +** an index search from being converted into a full-table scan in order to +** satisfy an ORDER BY clause, since even though we might get slightly better +** performance using the full-scan without sorting if the output size +** estimates are very precise, we might also get severe performance +** degradation using the full-scan if the output size estimate is too large. +** It is better to err on the side of caution. +** +** Except, if the first solver() call generated a full-table scan in an outer +** loop then stop this analysis at the first full-scan, since the second +** solver() run might try to swap that full-scan for another in order to +** get the output into the correct order. In other words, we allow a +** rewrite like this: +** +** First Solver() Second Solver() +** |-- SCAN t1 |-- SCAN t2 +** |-- SEARCH t2 `-- SEARCH t1 +** `-- SORT USING B-TREE +** +** The purpose of this routine is to disallow rewrites such as: +** +** First Solver() Second Solver() +** |-- SEARCH t1 |-- SCAN t2 <--- bad! +** |-- SEARCH t2 `-- SEARCH t1 +** `-- SORT USING B-TREE +** +** See test cases in test/whereN.test for the real-world query that +** originally provoked this heuristic. +*/ +static SQLITE_NOINLINE void whereInterstageHeuristic(WhereInfo *pWInfo){ + int i; +#ifdef WHERETRACE_ENABLED + int once = 0; +#endif + for(i=0; inLevel; i++){ + WhereLoop *p = pWInfo->a[i].pWLoop; + if( p==0 ) break; + if( (p->wsFlags & WHERE_VIRTUALTABLE)!=0 ) continue; + if( (p->wsFlags & (WHERE_COLUMN_EQ|WHERE_COLUMN_NULL|WHERE_COLUMN_IN))!=0 ){ + u8 iTab = p->iTab; + WhereLoop *pLoop; + for(pLoop=pWInfo->pLoops; pLoop; pLoop=pLoop->pNextLoop){ + if( pLoop->iTab!=iTab ) continue; + if( (pLoop->wsFlags & (WHERE_CONSTRAINT|WHERE_AUTO_INDEX))!=0 ){ + /* Auto-index and index-constrained loops allowed to remain */ + continue; + } +#ifdef WHERETRACE_ENABLED + if( sqlite3WhereTrace & 0x80 ){ + if( once==0 ){ + sqlite3DebugPrintf("Loops disabled by interstage heuristic:\n"); + once = 1; + } + sqlite3WhereLoopPrint(pLoop, &pWInfo->sWC); + } +#endif /* WHERETRACE_ENABLED */ + pLoop->prereq = ALLBITS; /* Prevent 2nd solver() from using this one */ + } + }else{ + break; + } + } +} + /* ** Most queries use only a single table (they are not joins) and have ** simple == constraints against indexed fields. This routine attempts @@ -164916,7 +168076,7 @@ static SQLITE_NOINLINE void whereCheckIfBloomFilterIsUseful( SrcItem *pItem = &pWInfo->pTabList->a[pLoop->iTab]; Table *pTab = pItem->pTab; if( (pTab->tabFlags & TF_HasStat1)==0 ) break; - pTab->tabFlags |= TF_StatsUsed; + pTab->tabFlags |= TF_MaybeReanalyze; if( i>=1 && (pLoop->wsFlags & reqFlags)==reqFlags /* vvvvvv--- Always the case if WHERE_COLUMN_EQ is defined */ @@ -164938,17 +168098,55 @@ static SQLITE_NOINLINE void whereCheckIfBloomFilterIsUseful( } /* -** This is an sqlite3ParserAddCleanup() callback that is invoked to -** free the Parse->pIdxEpr list when the Parse object is destroyed. +** Expression Node callback for sqlite3ExprCanReturnSubtype(). +** +** Only a function call is able to return a subtype. So if the node +** is not a function call, return WRC_Prune immediately. +** +** A function call is able to return a subtype if it has the +** SQLITE_RESULT_SUBTYPE property. +** +** Assume that every function is able to pass-through a subtype from +** one of its argument (using sqlite3_result_value()). Most functions +** are not this way, but we don't have a mechanism to distinguish those +** that are from those that are not, so assume they all work this way. +** That means that if one of its arguments is another function and that +** other function is able to return a subtype, then this function is +** able to return a subtype. */ -static void whereIndexedExprCleanup(sqlite3 *db, void *pObject){ - Parse *pParse = (Parse*)pObject; - while( pParse->pIdxEpr!=0 ){ - IndexedExpr *p = pParse->pIdxEpr; - pParse->pIdxEpr = p->pIENext; - sqlite3ExprDelete(db, p->pExpr); - sqlite3DbFreeNN(db, p); +static int exprNodeCanReturnSubtype(Walker *pWalker, Expr *pExpr){ + int n; + FuncDef *pDef; + sqlite3 *db; + if( pExpr->op!=TK_FUNCTION ){ + return WRC_Prune; } + assert( ExprUseXList(pExpr) ); + db = pWalker->pParse->db; + n = pExpr->x.pList ? pExpr->x.pList->nExpr : 0; + pDef = sqlite3FindFunction(db, pExpr->u.zToken, n, ENC(db), 0); + if( pDef==0 || (pDef->funcFlags & SQLITE_RESULT_SUBTYPE)!=0 ){ + pWalker->eCode = 1; + return WRC_Prune; + } + return WRC_Continue; +} + +/* +** Return TRUE if expression pExpr is able to return a subtype. +** +** A TRUE return does not guarantee that a subtype will be returned. +** It only indicates that a subtype return is possible. False positives +** are acceptable as they only disable an optimization. False negatives, +** on the other hand, can lead to incorrect answers. +*/ +static int sqlite3ExprCanReturnSubtype(Parse *pParse, Expr *pExpr){ + Walker w; + memset(&w, 0, sizeof(w)); + w.pParse = pParse; + w.xExprCallback = exprNodeCanReturnSubtype; + sqlite3WalkExpr(&w, pExpr); + return w.eCode; } /* @@ -164976,20 +168174,20 @@ static SQLITE_NOINLINE void whereAddIndexedExpr( for(i=0; inColumn; i++){ Expr *pExpr; int j = pIdx->aiColumn[i]; - int bMaybeNullRow; if( j==XN_EXPR ){ pExpr = pIdx->aColExpr->a[i].pExpr; - testcase( pTabItem->fg.jointype & JT_LEFT ); - testcase( pTabItem->fg.jointype & JT_RIGHT ); - testcase( pTabItem->fg.jointype & JT_LTORJ ); - bMaybeNullRow = (pTabItem->fg.jointype & (JT_LEFT|JT_LTORJ|JT_RIGHT))!=0; }else if( j>=0 && (pTab->aCol[j].colFlags & COLFLAG_VIRTUAL)!=0 ){ pExpr = sqlite3ColumnExpr(pTab, &pTab->aCol[j]); - bMaybeNullRow = 0; }else{ continue; } - if( sqlite3ExprIsConstant(pExpr) ) continue; + if( sqlite3ExprIsConstant(0,pExpr) ) continue; + if( pExpr->op==TK_FUNCTION && sqlite3ExprCanReturnSubtype(pParse,pExpr) ){ + /* Functions that might set a subtype should not be replaced by the + ** value taken from an expression index since the index omits the + ** subtype. https://sqlite.org/forum/forumpost/68d284c86b082c3e */ + continue; + } p = sqlite3DbMallocRaw(pParse->db, sizeof(IndexedExpr)); if( p==0 ) break; p->pIENext = pParse->pIdxEpr; @@ -165003,7 +168201,7 @@ static SQLITE_NOINLINE void whereAddIndexedExpr( p->iDataCur = pTabItem->iCursor; p->iIdxCur = iIdxCur; p->iIdxCol = i; - p->bMaybeNullRow = bMaybeNullRow; + p->bMaybeNullRow = (pTabItem->fg.jointype & (JT_LEFT|JT_LTORJ|JT_RIGHT))!=0; if( sqlite3IndexAffinityStr(pParse->db, pIdx) ){ p->aff = pIdx->zColAff[i]; } @@ -165012,7 +168210,8 @@ static SQLITE_NOINLINE void whereAddIndexedExpr( #endif pParse->pIdxEpr = p; if( p->pIENext==0 ){ - sqlite3ParserAddCleanup(pParse, whereIndexedExprCleanup, pParse); + void *pArg = (void*)&pParse->pIdxEpr; + sqlite3ParserAddCleanup(pParse, whereIndexedExprCleanup, pArg); } } } @@ -165167,7 +168366,10 @@ SQLITE_PRIVATE WhereInfo *sqlite3WhereBegin( /* An ORDER/GROUP BY clause of more than 63 terms cannot be optimized */ testcase( pOrderBy && pOrderBy->nExpr==BMS-1 ); - if( pOrderBy && pOrderBy->nExpr>=BMS ) pOrderBy = 0; + if( pOrderBy && pOrderBy->nExpr>=BMS ){ + pOrderBy = 0; + wctrlFlags &= ~WHERE_WANT_DISTINCT; + } /* The number of tables in the FROM clause is limited by the number of ** bits in a Bitmask @@ -165192,7 +168394,10 @@ SQLITE_PRIVATE WhereInfo *sqlite3WhereBegin( ** field (type Bitmask) it must be aligned on an 8-byte boundary on ** some architectures. Hence the ROUND8() below. */ - nByteWInfo = ROUND8P(sizeof(WhereInfo)+(nTabList-1)*sizeof(WhereLevel)); + nByteWInfo = ROUND8P(sizeof(WhereInfo)); + if( nTabList>1 ){ + nByteWInfo = ROUND8P(nByteWInfo + (nTabList-1)*sizeof(WhereLevel)); + } pWInfo = sqlite3DbMallocRawNN(db, nByteWInfo + sizeof(WhereLoop)); if( db->mallocFailed ){ sqlite3DbFree(db, pWInfo); @@ -165246,7 +168451,11 @@ SQLITE_PRIVATE WhereInfo *sqlite3WhereBegin( ){ pWInfo->eDistinct = WHERE_DISTINCT_UNIQUE; } - ExplainQueryPlan((pParse, 0, "SCAN CONSTANT ROW")); + if( ALWAYS(pWInfo->pSelect) + && (pWInfo->pSelect->selFlags & SF_MultiValue)==0 + ){ + ExplainQueryPlan((pParse, 0, "SCAN CONSTANT ROW")); + } }else{ /* Assign a bit from the bitmask to every term in the FROM clause. ** @@ -165399,9 +168608,20 @@ SQLITE_PRIVATE WhereInfo *sqlite3WhereBegin( wherePathSolver(pWInfo, 0); if( db->mallocFailed ) goto whereBeginError; if( pWInfo->pOrderBy ){ + whereInterstageHeuristic(pWInfo); wherePathSolver(pWInfo, pWInfo->nRowOut+1); if( db->mallocFailed ) goto whereBeginError; } + + /* TUNING: Assume that a DISTINCT clause on a subquery reduces + ** the output size by a factor of 8 (LogEst -30). + */ + if( (pWInfo->wctrlFlags & WHERE_WANT_DISTINCT)!=0 ){ + WHERETRACE(0x0080,("nRowOut reduced from %d to %d due to DISTINCT\n", + pWInfo->nRowOut, pWInfo->nRowOut-30)); + pWInfo->nRowOut -= 30; + } + } assert( pWInfo->pTabList!=0 ); if( pWInfo->pOrderBy==0 && (db->flags & SQLITE_ReverseOrder)!=0 ){ @@ -165614,6 +168834,11 @@ SQLITE_PRIVATE WhereInfo *sqlite3WhereBegin( if( pIx->bHasExpr && OptimizationEnabled(db, SQLITE_IndexedExpr) ){ whereAddIndexedExpr(pParse, pIx, iIndexCur, pTabItem); } + if( pIx->pPartIdxWhere && (pTabItem->fg.jointype & JT_RIGHT)==0 ){ + wherePartIdxExpr( + pParse, pIx, pIx->pPartIdxWhere, 0, iIndexCur, pTabItem + ); + } } pLevel->iIdxCur = iIndexCur; assert( pIx!=0 ); @@ -165739,6 +168964,11 @@ SQLITE_PRIVATE WhereInfo *sqlite3WhereBegin( pParse->nQueryLoop = pWInfo->savedNQueryLoop; whereInfoFree(db, pWInfo); } +#ifdef WHERETRACE_ENABLED + /* Prevent harmless compiler warnings about debugging routines + ** being declared but never used */ + sqlite3ShowWhereLoopList(0); +#endif /* WHERETRACE_ENABLED */ return 0; } @@ -165928,7 +169158,15 @@ SQLITE_PRIVATE void sqlite3WhereEnd(WhereInfo *pWInfo){ addr = sqlite3VdbeAddOp1(v, OP_IfPos, pLevel->iLeftJoin); VdbeCoverage(v); assert( (ws & WHERE_IDX_ONLY)==0 || (ws & WHERE_INDEXED)!=0 ); if( (ws & WHERE_IDX_ONLY)==0 ){ - assert( pLevel->iTabCur==pTabList->a[pLevel->iFrom].iCursor ); + SrcItem *pSrc = &pTabList->a[pLevel->iFrom]; + assert( pLevel->iTabCur==pSrc->iCursor ); + if( pSrc->fg.viaCoroutine ){ + int m, n; + n = pSrc->regResult; + assert( pSrc->pTab!=0 ); + m = pSrc->pTab->nCol; + sqlite3VdbeAddOp3(v, OP_Null, 0, n, n+m-1); + } sqlite3VdbeAddOp1(v, OP_NullRow, pLevel->iTabCur); } if( (ws & WHERE_INDEXED) @@ -165978,6 +169216,7 @@ SQLITE_PRIVATE void sqlite3WhereEnd(WhereInfo *pWInfo){ */ if( pTabItem->fg.viaCoroutine ){ testcase( pParse->db->mallocFailed ); + assert( pTabItem->regResult>=0 ); translateColumnToCopy(pParse, pLevel->addrBody, pLevel->iTabCur, pTabItem->regResult, 0); continue; @@ -167156,7 +170395,7 @@ SQLITE_PRIVATE int sqlite3WindowRewrite(Parse *pParse, Select *p){ assert( ExprUseXList(pWin->pOwner) ); assert( pWin->pWFunc!=0 ); pArgs = pWin->pOwner->x.pList; - if( pWin->pWFunc->funcFlags & SQLITE_FUNC_SUBTYPE ){ + if( pWin->pWFunc->funcFlags & SQLITE_SUBTYPE ){ selectWindowRewriteEList(pParse, pMWin, pSrc, pArgs, pTab, &pSublist); pWin->iArgCol = (pSublist ? pSublist->nExpr : 0); pWin->bExprArgs = 1; @@ -167282,7 +170521,7 @@ SQLITE_PRIVATE void sqlite3WindowListDelete(sqlite3 *db, Window *p){ ** variable values in the expression tree. */ static Expr *sqlite3WindowOffsetExpr(Parse *pParse, Expr *pExpr){ - if( 0==sqlite3ExprIsConstant(pExpr) ){ + if( 0==sqlite3ExprIsConstant(0,pExpr) ){ if( IN_RENAME_OBJECT ) sqlite3RenameExprUnmap(pParse, pExpr); sqlite3ExprDelete(pParse->db, pExpr); pExpr = sqlite3ExprAlloc(pParse->db, TK_NULL, 0, 0); @@ -167430,8 +170669,9 @@ SQLITE_PRIVATE void sqlite3WindowAttach(Parse *pParse, Expr *p, Window *pWin){ if( p ){ assert( p->op==TK_FUNCTION ); assert( pWin ); + assert( ExprIsFullSize(p) ); p->y.pWin = pWin; - ExprSetProperty(p, EP_WinFunc); + ExprSetProperty(p, EP_WinFunc|EP_FullSize); pWin->pOwner = p; if( (p->flags & EP_Distinct) && pWin->eFrmType!=TK_FILTER ){ sqlite3ErrorMsg(pParse, @@ -169373,6 +172613,14 @@ static void updateDeleteLimitError( return pSelect; } + /* Memory allocator for parser stack resizing. This is a thin wrapper around + ** sqlite3_realloc() that includes a call to sqlite3FaultSim() to facilitate + ** testing. + */ + static void *parserStackRealloc(void *pOld, sqlite3_uint64 newSize){ + return sqlite3FaultSim(700) ? 0 : sqlite3_realloc(pOld, newSize); + } + /* Construct a new Expr object from a single token */ static Expr *tokenExpr(Parse *pParse, int op, Token t){ @@ -169622,8 +172870,8 @@ static void updateDeleteLimitError( #define TK_TRUEFALSE 170 #define TK_ISNOT 171 #define TK_FUNCTION 172 -#define TK_UMINUS 173 -#define TK_UPLUS 174 +#define TK_UPLUS 173 +#define TK_UMINUS 174 #define TK_TRUTH 175 #define TK_REGISTER 176 #define TK_VECTOR 177 @@ -169632,8 +172880,9 @@ static void updateDeleteLimitError( #define TK_ASTERISK 180 #define TK_SPAN 181 #define TK_ERROR 182 -#define TK_SPACE 183 -#define TK_ILLEGAL 184 +#define TK_QNUMBER 183 +#define TK_SPACE 184 +#define TK_ILLEGAL 185 #endif /**************** End token definitions ***************************************/ @@ -169674,6 +172923,9 @@ static void updateDeleteLimitError( ** sqlite3ParserARG_STORE Code to store %extra_argument into yypParser ** sqlite3ParserARG_FETCH Code to extract %extra_argument from yypParser ** sqlite3ParserCTX_* As sqlite3ParserARG_ except for %extra_context +** YYREALLOC Name of the realloc() function to use +** YYFREE Name of the free() function to use +** YYDYNSTACK True if stack space should be extended on heap ** YYERRORSYMBOL is the code number of the error symbol. If not ** defined, then do no error processing. ** YYNSTATE the combined number of states. @@ -169687,37 +172939,39 @@ static void updateDeleteLimitError( ** YY_NO_ACTION The yy_action[] code for no-op ** YY_MIN_REDUCE Minimum value for reduce actions ** YY_MAX_REDUCE Maximum value for reduce actions +** YY_MIN_DSTRCTR Minimum symbol value that has a destructor +** YY_MAX_DSTRCTR Maximum symbol value that has a destructor */ #ifndef INTERFACE # define INTERFACE 1 #endif /************* Begin control #defines *****************************************/ #define YYCODETYPE unsigned short int -#define YYNOCODE 319 +#define YYNOCODE 322 #define YYACTIONTYPE unsigned short int #define YYWILDCARD 101 #define sqlite3ParserTOKENTYPE Token typedef union { int yyinit; sqlite3ParserTOKENTYPE yy0; - TriggerStep* yy33; - Window* yy41; - Select* yy47; - SrcList* yy131; - struct TrigEvent yy180; - struct {int value; int mask;} yy231; - IdList* yy254; - u32 yy285; - ExprList* yy322; - Cte* yy385; - int yy394; - Upsert* yy444; - u8 yy516; - With* yy521; - const char* yy522; - Expr* yy528; - OnOrUsing yy561; - struct FrameBound yy595; + ExprList* yy14; + With* yy59; + Cte* yy67; + Upsert* yy122; + IdList* yy132; + int yy144; + const char* yy168; + SrcList* yy203; + Window* yy211; + OnOrUsing yy269; + struct TrigEvent yy286; + struct {int value; int mask;} yy383; + u32 yy391; + TriggerStep* yy427; + Expr* yy454; + u8 yy462; + struct FrameBound yy509; + Select* yy555; } YYMINORTYPE; #ifndef YYSTACKDEPTH #define YYSTACKDEPTH 100 @@ -169727,24 +172981,29 @@ typedef union { #define sqlite3ParserARG_PARAM #define sqlite3ParserARG_FETCH #define sqlite3ParserARG_STORE +#define YYREALLOC parserStackRealloc +#define YYFREE sqlite3_free +#define YYDYNSTACK 1 #define sqlite3ParserCTX_SDECL Parse *pParse; #define sqlite3ParserCTX_PDECL ,Parse *pParse #define sqlite3ParserCTX_PARAM ,pParse #define sqlite3ParserCTX_FETCH Parse *pParse=yypParser->pParse; #define sqlite3ParserCTX_STORE yypParser->pParse=pParse; #define YYFALLBACK 1 -#define YYNSTATE 575 -#define YYNRULE 403 -#define YYNRULE_WITH_ACTION 338 -#define YYNTOKEN 185 -#define YY_MAX_SHIFT 574 -#define YY_MIN_SHIFTREDUCE 833 -#define YY_MAX_SHIFTREDUCE 1235 -#define YY_ERROR_ACTION 1236 -#define YY_ACCEPT_ACTION 1237 -#define YY_NO_ACTION 1238 -#define YY_MIN_REDUCE 1239 -#define YY_MAX_REDUCE 1641 +#define YYNSTATE 583 +#define YYNRULE 409 +#define YYNRULE_WITH_ACTION 344 +#define YYNTOKEN 186 +#define YY_MAX_SHIFT 582 +#define YY_MIN_SHIFTREDUCE 845 +#define YY_MAX_SHIFTREDUCE 1253 +#define YY_ERROR_ACTION 1254 +#define YY_ACCEPT_ACTION 1255 +#define YY_NO_ACTION 1256 +#define YY_MIN_REDUCE 1257 +#define YY_MAX_REDUCE 1665 +#define YY_MIN_DSTRCTR 205 +#define YY_MAX_DSTRCTR 319 /************* End control #defines *******************************************/ #define YY_NLOOKAHEAD ((int)(sizeof(yy_lookahead)/sizeof(yy_lookahead[0]))) @@ -169760,6 +173019,22 @@ typedef union { # define yytestcase(X) #endif +/* Macro to determine if stack space has the ability to grow using +** heap memory. +*/ +#if YYSTACKDEPTH<=0 || YYDYNSTACK +# define YYGROWABLESTACK 1 +#else +# define YYGROWABLESTACK 0 +#endif + +/* Guarantee a minimum number of initial stack slots. +*/ +#if YYSTACKDEPTH<=0 +# undef YYSTACKDEPTH +# define YYSTACKDEPTH 2 /* Need a minimum stack size */ +#endif + /* Next are the tables used to determine what action to take based on the ** current state and lookahead token. These tables are used to implement @@ -169811,618 +173086,630 @@ typedef union { ** yy_default[] Default action for each state. ** *********** Begin parsing tables **********************************************/ -#define YY_ACTTAB_COUNT (2096) +#define YY_ACTTAB_COUNT (2142) static const YYACTIONTYPE yy_action[] = { - /* 0 */ 568, 208, 568, 118, 115, 229, 568, 118, 115, 229, - /* 10 */ 568, 1310, 377, 1289, 408, 562, 562, 562, 568, 409, - /* 20 */ 378, 1310, 1272, 41, 41, 41, 41, 208, 1520, 71, - /* 30 */ 71, 969, 419, 41, 41, 491, 303, 279, 303, 970, - /* 40 */ 397, 71, 71, 125, 126, 80, 1210, 1210, 1047, 1050, - /* 50 */ 1037, 1037, 123, 123, 124, 124, 124, 124, 476, 409, - /* 60 */ 1237, 1, 1, 574, 2, 1241, 550, 118, 115, 229, - /* 70 */ 317, 480, 146, 480, 524, 118, 115, 229, 529, 1323, - /* 80 */ 417, 523, 142, 125, 126, 80, 1210, 1210, 1047, 1050, - /* 90 */ 1037, 1037, 123, 123, 124, 124, 124, 124, 118, 115, - /* 100 */ 229, 327, 122, 122, 122, 122, 121, 121, 120, 120, - /* 110 */ 120, 119, 116, 444, 284, 284, 284, 284, 442, 442, - /* 120 */ 442, 1559, 376, 1561, 1186, 375, 1157, 565, 1157, 565, - /* 130 */ 409, 1559, 537, 259, 226, 444, 101, 145, 449, 316, - /* 140 */ 559, 240, 122, 122, 122, 122, 121, 121, 120, 120, - /* 150 */ 120, 119, 116, 444, 125, 126, 80, 1210, 1210, 1047, - /* 160 */ 1050, 1037, 1037, 123, 123, 124, 124, 124, 124, 142, - /* 170 */ 294, 1186, 339, 448, 120, 120, 120, 119, 116, 444, - /* 180 */ 127, 1186, 1187, 1186, 148, 441, 440, 568, 119, 116, - /* 190 */ 444, 124, 124, 124, 124, 117, 122, 122, 122, 122, - /* 200 */ 121, 121, 120, 120, 120, 119, 116, 444, 454, 113, - /* 210 */ 13, 13, 546, 122, 122, 122, 122, 121, 121, 120, - /* 220 */ 120, 120, 119, 116, 444, 422, 316, 559, 1186, 1187, - /* 230 */ 1186, 149, 1218, 409, 1218, 124, 124, 124, 124, 122, - /* 240 */ 122, 122, 122, 121, 121, 120, 120, 120, 119, 116, - /* 250 */ 444, 465, 342, 1034, 1034, 1048, 1051, 125, 126, 80, - /* 260 */ 1210, 1210, 1047, 1050, 1037, 1037, 123, 123, 124, 124, - /* 270 */ 124, 124, 1275, 522, 222, 1186, 568, 409, 224, 514, - /* 280 */ 175, 82, 83, 122, 122, 122, 122, 121, 121, 120, - /* 290 */ 120, 120, 119, 116, 444, 1005, 16, 16, 1186, 133, - /* 300 */ 133, 125, 126, 80, 1210, 1210, 1047, 1050, 1037, 1037, - /* 310 */ 123, 123, 124, 124, 124, 124, 122, 122, 122, 122, - /* 320 */ 121, 121, 120, 120, 120, 119, 116, 444, 1038, 546, - /* 330 */ 1186, 373, 1186, 1187, 1186, 252, 1429, 399, 504, 501, - /* 340 */ 500, 111, 560, 566, 4, 924, 924, 433, 499, 340, - /* 350 */ 460, 328, 360, 394, 1231, 1186, 1187, 1186, 563, 568, - /* 360 */ 122, 122, 122, 122, 121, 121, 120, 120, 120, 119, - /* 370 */ 116, 444, 284, 284, 369, 1572, 1598, 441, 440, 154, - /* 380 */ 409, 445, 71, 71, 1282, 565, 1215, 1186, 1187, 1186, - /* 390 */ 85, 1217, 271, 557, 543, 515, 515, 568, 98, 1216, - /* 400 */ 6, 1274, 472, 142, 125, 126, 80, 1210, 1210, 1047, - /* 410 */ 1050, 1037, 1037, 123, 123, 124, 124, 124, 124, 550, - /* 420 */ 13, 13, 1024, 507, 1218, 1186, 1218, 549, 109, 109, - /* 430 */ 222, 568, 1232, 175, 568, 427, 110, 197, 445, 569, - /* 440 */ 445, 430, 1546, 1014, 325, 551, 1186, 270, 287, 368, - /* 450 */ 510, 363, 509, 257, 71, 71, 543, 71, 71, 359, - /* 460 */ 316, 559, 1604, 122, 122, 122, 122, 121, 121, 120, - /* 470 */ 120, 120, 119, 116, 444, 1014, 1014, 1016, 1017, 27, - /* 480 */ 284, 284, 1186, 1187, 1186, 1152, 568, 1603, 409, 899, - /* 490 */ 190, 550, 356, 565, 550, 935, 533, 517, 1152, 516, - /* 500 */ 413, 1152, 552, 1186, 1187, 1186, 568, 544, 544, 51, - /* 510 */ 51, 214, 125, 126, 80, 1210, 1210, 1047, 1050, 1037, - /* 520 */ 1037, 123, 123, 124, 124, 124, 124, 1186, 474, 135, - /* 530 */ 135, 409, 284, 284, 1484, 505, 121, 121, 120, 120, - /* 540 */ 120, 119, 116, 444, 1005, 565, 518, 217, 541, 541, - /* 550 */ 316, 559, 142, 6, 532, 125, 126, 80, 1210, 1210, - /* 560 */ 1047, 1050, 1037, 1037, 123, 123, 124, 124, 124, 124, - /* 570 */ 1548, 122, 122, 122, 122, 121, 121, 120, 120, 120, - /* 580 */ 119, 116, 444, 485, 1186, 1187, 1186, 482, 281, 1263, - /* 590 */ 955, 252, 1186, 373, 504, 501, 500, 1186, 340, 570, - /* 600 */ 1186, 570, 409, 292, 499, 955, 874, 191, 480, 316, - /* 610 */ 559, 384, 290, 380, 122, 122, 122, 122, 121, 121, - /* 620 */ 120, 120, 120, 119, 116, 444, 125, 126, 80, 1210, - /* 630 */ 1210, 1047, 1050, 1037, 1037, 123, 123, 124, 124, 124, - /* 640 */ 124, 409, 394, 1132, 1186, 867, 100, 284, 284, 1186, - /* 650 */ 1187, 1186, 373, 1089, 1186, 1187, 1186, 1186, 1187, 1186, - /* 660 */ 565, 455, 32, 373, 233, 125, 126, 80, 1210, 1210, - /* 670 */ 1047, 1050, 1037, 1037, 123, 123, 124, 124, 124, 124, - /* 680 */ 1428, 957, 568, 228, 956, 122, 122, 122, 122, 121, - /* 690 */ 121, 120, 120, 120, 119, 116, 444, 1152, 228, 1186, - /* 700 */ 157, 1186, 1187, 1186, 1547, 13, 13, 301, 955, 1226, - /* 710 */ 1152, 153, 409, 1152, 373, 1575, 1170, 5, 369, 1572, - /* 720 */ 429, 1232, 3, 955, 122, 122, 122, 122, 121, 121, - /* 730 */ 120, 120, 120, 119, 116, 444, 125, 126, 80, 1210, - /* 740 */ 1210, 1047, 1050, 1037, 1037, 123, 123, 124, 124, 124, - /* 750 */ 124, 409, 208, 567, 1186, 1025, 1186, 1187, 1186, 1186, - /* 760 */ 388, 850, 155, 1546, 286, 402, 1094, 1094, 488, 568, - /* 770 */ 465, 342, 1315, 1315, 1546, 125, 126, 80, 1210, 1210, - /* 780 */ 1047, 1050, 1037, 1037, 123, 123, 124, 124, 124, 124, - /* 790 */ 129, 568, 13, 13, 374, 122, 122, 122, 122, 121, - /* 800 */ 121, 120, 120, 120, 119, 116, 444, 302, 568, 453, - /* 810 */ 528, 1186, 1187, 1186, 13, 13, 1186, 1187, 1186, 1293, - /* 820 */ 463, 1263, 409, 1313, 1313, 1546, 1010, 453, 452, 200, - /* 830 */ 299, 71, 71, 1261, 122, 122, 122, 122, 121, 121, - /* 840 */ 120, 120, 120, 119, 116, 444, 125, 126, 80, 1210, - /* 850 */ 1210, 1047, 1050, 1037, 1037, 123, 123, 124, 124, 124, - /* 860 */ 124, 409, 227, 1069, 1152, 284, 284, 419, 312, 278, - /* 870 */ 278, 285, 285, 1415, 406, 405, 382, 1152, 565, 568, - /* 880 */ 1152, 1189, 565, 1592, 565, 125, 126, 80, 1210, 1210, - /* 890 */ 1047, 1050, 1037, 1037, 123, 123, 124, 124, 124, 124, - /* 900 */ 453, 1476, 13, 13, 1530, 122, 122, 122, 122, 121, - /* 910 */ 121, 120, 120, 120, 119, 116, 444, 201, 568, 354, - /* 920 */ 1578, 574, 2, 1241, 838, 839, 840, 1554, 317, 1205, - /* 930 */ 146, 6, 409, 255, 254, 253, 206, 1323, 9, 1189, - /* 940 */ 262, 71, 71, 424, 122, 122, 122, 122, 121, 121, - /* 950 */ 120, 120, 120, 119, 116, 444, 125, 126, 80, 1210, - /* 960 */ 1210, 1047, 1050, 1037, 1037, 123, 123, 124, 124, 124, - /* 970 */ 124, 568, 284, 284, 568, 1206, 409, 573, 313, 1241, - /* 980 */ 349, 1292, 352, 419, 317, 565, 146, 491, 525, 1635, - /* 990 */ 395, 371, 491, 1323, 70, 70, 1291, 71, 71, 240, - /* 1000 */ 1321, 104, 80, 1210, 1210, 1047, 1050, 1037, 1037, 123, - /* 1010 */ 123, 124, 124, 124, 124, 122, 122, 122, 122, 121, - /* 1020 */ 121, 120, 120, 120, 119, 116, 444, 1110, 284, 284, - /* 1030 */ 428, 448, 1519, 1206, 439, 284, 284, 1483, 1348, 311, - /* 1040 */ 474, 565, 1111, 969, 491, 491, 217, 1259, 565, 1532, - /* 1050 */ 568, 970, 207, 568, 1024, 240, 383, 1112, 519, 122, - /* 1060 */ 122, 122, 122, 121, 121, 120, 120, 120, 119, 116, - /* 1070 */ 444, 1015, 107, 71, 71, 1014, 13, 13, 910, 568, - /* 1080 */ 1489, 568, 284, 284, 97, 526, 491, 448, 911, 1322, - /* 1090 */ 1318, 545, 409, 284, 284, 565, 151, 209, 1489, 1491, - /* 1100 */ 262, 450, 55, 55, 56, 56, 565, 1014, 1014, 1016, - /* 1110 */ 443, 332, 409, 527, 12, 295, 125, 126, 80, 1210, - /* 1120 */ 1210, 1047, 1050, 1037, 1037, 123, 123, 124, 124, 124, - /* 1130 */ 124, 347, 409, 862, 1528, 1206, 125, 126, 80, 1210, - /* 1140 */ 1210, 1047, 1050, 1037, 1037, 123, 123, 124, 124, 124, - /* 1150 */ 124, 1133, 1633, 474, 1633, 371, 125, 114, 80, 1210, - /* 1160 */ 1210, 1047, 1050, 1037, 1037, 123, 123, 124, 124, 124, - /* 1170 */ 124, 1489, 329, 474, 331, 122, 122, 122, 122, 121, - /* 1180 */ 121, 120, 120, 120, 119, 116, 444, 203, 1415, 568, - /* 1190 */ 1290, 862, 464, 1206, 436, 122, 122, 122, 122, 121, - /* 1200 */ 121, 120, 120, 120, 119, 116, 444, 553, 1133, 1634, - /* 1210 */ 539, 1634, 15, 15, 890, 122, 122, 122, 122, 121, - /* 1220 */ 121, 120, 120, 120, 119, 116, 444, 568, 298, 538, - /* 1230 */ 1131, 1415, 1552, 1553, 1327, 409, 6, 6, 1163, 1264, - /* 1240 */ 415, 320, 284, 284, 1415, 508, 565, 525, 300, 457, - /* 1250 */ 43, 43, 568, 891, 12, 565, 330, 478, 425, 407, - /* 1260 */ 126, 80, 1210, 1210, 1047, 1050, 1037, 1037, 123, 123, - /* 1270 */ 124, 124, 124, 124, 568, 57, 57, 288, 1186, 1415, - /* 1280 */ 496, 458, 392, 392, 391, 273, 389, 1131, 1551, 847, - /* 1290 */ 1163, 407, 6, 568, 321, 1152, 470, 44, 44, 1550, - /* 1300 */ 1110, 426, 234, 6, 323, 256, 540, 256, 1152, 431, - /* 1310 */ 568, 1152, 322, 17, 487, 1111, 58, 58, 122, 122, - /* 1320 */ 122, 122, 121, 121, 120, 120, 120, 119, 116, 444, - /* 1330 */ 1112, 216, 481, 59, 59, 1186, 1187, 1186, 111, 560, - /* 1340 */ 324, 4, 236, 456, 526, 568, 237, 456, 568, 437, - /* 1350 */ 168, 556, 420, 141, 479, 563, 568, 293, 568, 1091, - /* 1360 */ 568, 293, 568, 1091, 531, 568, 870, 8, 60, 60, - /* 1370 */ 235, 61, 61, 568, 414, 568, 414, 568, 445, 62, - /* 1380 */ 62, 45, 45, 46, 46, 47, 47, 199, 49, 49, - /* 1390 */ 557, 568, 359, 568, 100, 486, 50, 50, 63, 63, - /* 1400 */ 64, 64, 561, 415, 535, 410, 568, 1024, 568, 534, - /* 1410 */ 316, 559, 316, 559, 65, 65, 14, 14, 568, 1024, - /* 1420 */ 568, 512, 930, 870, 1015, 109, 109, 929, 1014, 66, - /* 1430 */ 66, 131, 131, 110, 451, 445, 569, 445, 416, 177, - /* 1440 */ 1014, 132, 132, 67, 67, 568, 467, 568, 930, 471, - /* 1450 */ 1360, 283, 226, 929, 315, 1359, 407, 568, 459, 407, - /* 1460 */ 1014, 1014, 1016, 239, 407, 86, 213, 1346, 52, 52, - /* 1470 */ 68, 68, 1014, 1014, 1016, 1017, 27, 1577, 1174, 447, - /* 1480 */ 69, 69, 288, 97, 108, 1535, 106, 392, 392, 391, - /* 1490 */ 273, 389, 568, 877, 847, 881, 568, 111, 560, 466, - /* 1500 */ 4, 568, 152, 30, 38, 568, 1128, 234, 396, 323, - /* 1510 */ 111, 560, 527, 4, 563, 53, 53, 322, 568, 163, - /* 1520 */ 163, 568, 337, 468, 164, 164, 333, 563, 76, 76, - /* 1530 */ 568, 289, 1508, 568, 31, 1507, 568, 445, 338, 483, - /* 1540 */ 100, 54, 54, 344, 72, 72, 296, 236, 1076, 557, - /* 1550 */ 445, 877, 1356, 134, 134, 168, 73, 73, 141, 161, - /* 1560 */ 161, 1566, 557, 535, 568, 319, 568, 348, 536, 1007, - /* 1570 */ 473, 261, 261, 889, 888, 235, 535, 568, 1024, 568, - /* 1580 */ 475, 534, 261, 367, 109, 109, 521, 136, 136, 130, - /* 1590 */ 130, 1024, 110, 366, 445, 569, 445, 109, 109, 1014, - /* 1600 */ 162, 162, 156, 156, 568, 110, 1076, 445, 569, 445, - /* 1610 */ 410, 351, 1014, 568, 353, 316, 559, 568, 343, 568, - /* 1620 */ 100, 497, 357, 258, 100, 896, 897, 140, 140, 355, - /* 1630 */ 1306, 1014, 1014, 1016, 1017, 27, 139, 139, 362, 451, - /* 1640 */ 137, 137, 138, 138, 1014, 1014, 1016, 1017, 27, 1174, - /* 1650 */ 447, 568, 372, 288, 111, 560, 1018, 4, 392, 392, - /* 1660 */ 391, 273, 389, 568, 1137, 847, 568, 1072, 568, 258, - /* 1670 */ 492, 563, 568, 211, 75, 75, 555, 960, 234, 261, - /* 1680 */ 323, 111, 560, 927, 4, 113, 77, 77, 322, 74, - /* 1690 */ 74, 42, 42, 1369, 445, 48, 48, 1414, 563, 972, - /* 1700 */ 973, 1088, 1087, 1088, 1087, 860, 557, 150, 928, 1342, - /* 1710 */ 113, 1354, 554, 1419, 1018, 1271, 1262, 1250, 236, 1249, - /* 1720 */ 1251, 445, 1585, 1339, 308, 276, 168, 309, 11, 141, - /* 1730 */ 393, 310, 232, 557, 1401, 1024, 335, 291, 1396, 219, - /* 1740 */ 336, 109, 109, 934, 297, 1406, 235, 341, 477, 110, - /* 1750 */ 502, 445, 569, 445, 1389, 1405, 1014, 400, 1289, 365, - /* 1760 */ 223, 1480, 1024, 1479, 1351, 1352, 1350, 1349, 109, 109, - /* 1770 */ 204, 1588, 1226, 558, 265, 218, 110, 205, 445, 569, - /* 1780 */ 445, 410, 387, 1014, 1527, 179, 316, 559, 1014, 1014, - /* 1790 */ 1016, 1017, 27, 230, 1525, 1223, 79, 560, 85, 4, - /* 1800 */ 418, 215, 548, 81, 84, 188, 1402, 173, 181, 461, - /* 1810 */ 451, 35, 462, 563, 183, 1014, 1014, 1016, 1017, 27, - /* 1820 */ 184, 1485, 185, 186, 495, 242, 98, 398, 1408, 36, - /* 1830 */ 1407, 484, 91, 469, 401, 1410, 445, 192, 1474, 246, - /* 1840 */ 1496, 490, 346, 277, 248, 196, 493, 511, 557, 350, - /* 1850 */ 1252, 249, 250, 403, 1309, 1308, 111, 560, 432, 4, - /* 1860 */ 1307, 1300, 93, 1602, 881, 1601, 224, 404, 434, 520, - /* 1870 */ 263, 435, 1571, 563, 1279, 1278, 364, 1024, 306, 1277, - /* 1880 */ 264, 1600, 1557, 109, 109, 370, 1299, 307, 1556, 438, - /* 1890 */ 128, 110, 1374, 445, 569, 445, 445, 546, 1014, 10, - /* 1900 */ 1461, 105, 381, 1373, 34, 571, 99, 1332, 557, 314, - /* 1910 */ 1180, 530, 272, 274, 379, 210, 1331, 547, 385, 386, - /* 1920 */ 275, 572, 1247, 1242, 411, 412, 1512, 165, 178, 1513, - /* 1930 */ 1014, 1014, 1016, 1017, 27, 1511, 1510, 1024, 78, 147, - /* 1940 */ 166, 220, 221, 109, 109, 834, 304, 167, 446, 212, - /* 1950 */ 318, 110, 231, 445, 569, 445, 144, 1086, 1014, 1084, - /* 1960 */ 326, 180, 169, 1205, 182, 334, 238, 913, 241, 1100, - /* 1970 */ 187, 170, 171, 421, 87, 88, 423, 189, 89, 90, - /* 1980 */ 172, 1103, 243, 1099, 244, 158, 18, 245, 345, 247, - /* 1990 */ 1014, 1014, 1016, 1017, 27, 261, 1092, 193, 1220, 489, - /* 2000 */ 194, 37, 366, 849, 494, 251, 195, 506, 92, 19, - /* 2010 */ 498, 358, 20, 503, 879, 361, 94, 892, 305, 159, - /* 2020 */ 513, 39, 95, 1168, 160, 1053, 964, 1139, 96, 174, - /* 2030 */ 1138, 225, 280, 282, 198, 958, 113, 1158, 1154, 260, - /* 2040 */ 21, 22, 23, 1156, 1162, 1161, 1143, 24, 33, 25, - /* 2050 */ 202, 542, 26, 100, 1067, 102, 1054, 103, 7, 1052, - /* 2060 */ 1056, 1109, 1057, 1108, 266, 267, 28, 40, 390, 1019, - /* 2070 */ 861, 112, 29, 564, 1176, 1175, 268, 176, 143, 923, - /* 2080 */ 1238, 1238, 1238, 1238, 1238, 1238, 1238, 1238, 1238, 1238, - /* 2090 */ 1238, 1238, 1238, 1238, 269, 1593, + /* 0 */ 576, 128, 125, 232, 1622, 549, 576, 1290, 1281, 576, + /* 10 */ 328, 576, 1300, 212, 576, 128, 125, 232, 578, 412, + /* 20 */ 578, 391, 1542, 51, 51, 523, 405, 1293, 529, 51, + /* 30 */ 51, 983, 51, 51, 81, 81, 1107, 61, 61, 984, + /* 40 */ 1107, 1292, 380, 135, 136, 90, 1228, 1228, 1063, 1066, + /* 50 */ 1053, 1053, 133, 133, 134, 134, 134, 134, 1577, 412, + /* 60 */ 287, 287, 7, 287, 287, 422, 1050, 1050, 1064, 1067, + /* 70 */ 289, 556, 492, 573, 524, 561, 573, 497, 561, 482, + /* 80 */ 530, 262, 229, 135, 136, 90, 1228, 1228, 1063, 1066, + /* 90 */ 1053, 1053, 133, 133, 134, 134, 134, 134, 128, 125, + /* 100 */ 232, 1506, 132, 132, 132, 132, 131, 131, 130, 130, + /* 110 */ 130, 129, 126, 450, 1204, 1255, 1, 1, 582, 2, + /* 120 */ 1259, 1571, 420, 1582, 379, 320, 1174, 153, 1174, 1584, + /* 130 */ 412, 378, 1582, 543, 1341, 330, 111, 570, 570, 570, + /* 140 */ 293, 1054, 132, 132, 132, 132, 131, 131, 130, 130, + /* 150 */ 130, 129, 126, 450, 135, 136, 90, 1228, 1228, 1063, + /* 160 */ 1066, 1053, 1053, 133, 133, 134, 134, 134, 134, 287, + /* 170 */ 287, 1204, 1205, 1204, 255, 287, 287, 510, 507, 506, + /* 180 */ 137, 455, 573, 212, 561, 447, 446, 505, 573, 1616, + /* 190 */ 561, 134, 134, 134, 134, 127, 400, 243, 132, 132, + /* 200 */ 132, 132, 131, 131, 130, 130, 130, 129, 126, 450, + /* 210 */ 282, 471, 345, 132, 132, 132, 132, 131, 131, 130, + /* 220 */ 130, 130, 129, 126, 450, 574, 155, 936, 936, 454, + /* 230 */ 227, 521, 1236, 412, 1236, 134, 134, 134, 134, 132, + /* 240 */ 132, 132, 132, 131, 131, 130, 130, 130, 129, 126, + /* 250 */ 450, 130, 130, 130, 129, 126, 450, 135, 136, 90, + /* 260 */ 1228, 1228, 1063, 1066, 1053, 1053, 133, 133, 134, 134, + /* 270 */ 134, 134, 128, 125, 232, 450, 576, 412, 397, 1249, + /* 280 */ 180, 92, 93, 132, 132, 132, 132, 131, 131, 130, + /* 290 */ 130, 130, 129, 126, 450, 381, 387, 1204, 383, 81, + /* 300 */ 81, 135, 136, 90, 1228, 1228, 1063, 1066, 1053, 1053, + /* 310 */ 133, 133, 134, 134, 134, 134, 132, 132, 132, 132, + /* 320 */ 131, 131, 130, 130, 130, 129, 126, 450, 131, 131, + /* 330 */ 130, 130, 130, 129, 126, 450, 556, 1204, 302, 319, + /* 340 */ 567, 121, 568, 480, 4, 555, 1149, 1657, 1628, 1657, + /* 350 */ 45, 128, 125, 232, 1204, 1205, 1204, 1250, 571, 1169, + /* 360 */ 132, 132, 132, 132, 131, 131, 130, 130, 130, 129, + /* 370 */ 126, 450, 1169, 287, 287, 1169, 1019, 576, 422, 1019, + /* 380 */ 412, 451, 1602, 582, 2, 1259, 573, 44, 561, 95, + /* 390 */ 320, 110, 153, 565, 1204, 1205, 1204, 522, 522, 1341, + /* 400 */ 81, 81, 7, 44, 135, 136, 90, 1228, 1228, 1063, + /* 410 */ 1066, 1053, 1053, 133, 133, 134, 134, 134, 134, 295, + /* 420 */ 1149, 1658, 1040, 1658, 1204, 1147, 319, 567, 119, 119, + /* 430 */ 343, 466, 331, 343, 287, 287, 120, 556, 451, 577, + /* 440 */ 451, 1169, 1169, 1028, 319, 567, 438, 573, 210, 561, + /* 450 */ 1339, 1451, 546, 531, 1169, 1169, 1598, 1169, 1169, 416, + /* 460 */ 319, 567, 243, 132, 132, 132, 132, 131, 131, 130, + /* 470 */ 130, 130, 129, 126, 450, 1028, 1028, 1030, 1031, 35, + /* 480 */ 44, 1204, 1205, 1204, 472, 287, 287, 1328, 412, 1307, + /* 490 */ 372, 1595, 359, 225, 454, 1204, 195, 1328, 573, 1147, + /* 500 */ 561, 1333, 1333, 274, 576, 1188, 576, 340, 46, 196, + /* 510 */ 537, 217, 135, 136, 90, 1228, 1228, 1063, 1066, 1053, + /* 520 */ 1053, 133, 133, 134, 134, 134, 134, 19, 19, 19, + /* 530 */ 19, 412, 581, 1204, 1259, 511, 1204, 319, 567, 320, + /* 540 */ 944, 153, 425, 491, 430, 943, 1204, 488, 1341, 1450, + /* 550 */ 532, 1277, 1204, 1205, 1204, 135, 136, 90, 1228, 1228, + /* 560 */ 1063, 1066, 1053, 1053, 133, 133, 134, 134, 134, 134, + /* 570 */ 575, 132, 132, 132, 132, 131, 131, 130, 130, 130, + /* 580 */ 129, 126, 450, 287, 287, 528, 287, 287, 372, 1595, + /* 590 */ 1204, 1205, 1204, 1204, 1205, 1204, 573, 486, 561, 573, + /* 600 */ 889, 561, 412, 1204, 1205, 1204, 886, 40, 22, 22, + /* 610 */ 220, 243, 525, 1449, 132, 132, 132, 132, 131, 131, + /* 620 */ 130, 130, 130, 129, 126, 450, 135, 136, 90, 1228, + /* 630 */ 1228, 1063, 1066, 1053, 1053, 133, 133, 134, 134, 134, + /* 640 */ 134, 412, 180, 454, 1204, 879, 255, 287, 287, 510, + /* 650 */ 507, 506, 372, 1595, 1568, 1331, 1331, 576, 889, 505, + /* 660 */ 573, 44, 561, 559, 1207, 135, 136, 90, 1228, 1228, + /* 670 */ 1063, 1066, 1053, 1053, 133, 133, 134, 134, 134, 134, + /* 680 */ 81, 81, 422, 576, 377, 132, 132, 132, 132, 131, + /* 690 */ 131, 130, 130, 130, 129, 126, 450, 297, 287, 287, + /* 700 */ 460, 1204, 1205, 1204, 1204, 534, 19, 19, 448, 448, + /* 710 */ 448, 573, 412, 561, 230, 436, 1187, 535, 319, 567, + /* 720 */ 363, 432, 1207, 1435, 132, 132, 132, 132, 131, 131, + /* 730 */ 130, 130, 130, 129, 126, 450, 135, 136, 90, 1228, + /* 740 */ 1228, 1063, 1066, 1053, 1053, 133, 133, 134, 134, 134, + /* 750 */ 134, 412, 211, 949, 1169, 1041, 1110, 1110, 494, 547, + /* 760 */ 547, 1204, 1205, 1204, 7, 539, 1570, 1169, 376, 576, + /* 770 */ 1169, 5, 1204, 486, 3, 135, 136, 90, 1228, 1228, + /* 780 */ 1063, 1066, 1053, 1053, 133, 133, 134, 134, 134, 134, + /* 790 */ 576, 513, 19, 19, 427, 132, 132, 132, 132, 131, + /* 800 */ 131, 130, 130, 130, 129, 126, 450, 305, 1204, 433, + /* 810 */ 225, 1204, 385, 19, 19, 273, 290, 371, 516, 366, + /* 820 */ 515, 260, 412, 538, 1568, 549, 1024, 362, 437, 1204, + /* 830 */ 1205, 1204, 902, 1552, 132, 132, 132, 132, 131, 131, + /* 840 */ 130, 130, 130, 129, 126, 450, 135, 136, 90, 1228, + /* 850 */ 1228, 1063, 1066, 1053, 1053, 133, 133, 134, 134, 134, + /* 860 */ 134, 412, 1435, 514, 1281, 1204, 1205, 1204, 1204, 1205, + /* 870 */ 1204, 903, 48, 342, 1568, 1568, 1279, 1627, 1568, 911, + /* 880 */ 576, 129, 126, 450, 110, 135, 136, 90, 1228, 1228, + /* 890 */ 1063, 1066, 1053, 1053, 133, 133, 134, 134, 134, 134, + /* 900 */ 265, 576, 459, 19, 19, 132, 132, 132, 132, 131, + /* 910 */ 131, 130, 130, 130, 129, 126, 450, 1345, 204, 576, + /* 920 */ 459, 458, 50, 47, 19, 19, 49, 434, 1105, 573, + /* 930 */ 497, 561, 412, 428, 108, 1224, 1569, 1554, 376, 205, + /* 940 */ 550, 550, 81, 81, 132, 132, 132, 132, 131, 131, + /* 950 */ 130, 130, 130, 129, 126, 450, 135, 136, 90, 1228, + /* 960 */ 1228, 1063, 1066, 1053, 1053, 133, 133, 134, 134, 134, + /* 970 */ 134, 480, 576, 1204, 576, 1541, 412, 1435, 969, 315, + /* 980 */ 1659, 398, 284, 497, 969, 893, 1569, 1569, 376, 376, + /* 990 */ 1569, 461, 376, 1224, 459, 80, 80, 81, 81, 497, + /* 1000 */ 374, 114, 90, 1228, 1228, 1063, 1066, 1053, 1053, 133, + /* 1010 */ 133, 134, 134, 134, 134, 132, 132, 132, 132, 131, + /* 1020 */ 131, 130, 130, 130, 129, 126, 450, 1204, 1505, 576, + /* 1030 */ 1204, 1205, 1204, 1366, 316, 486, 281, 281, 497, 431, + /* 1040 */ 557, 288, 288, 402, 1340, 471, 345, 298, 429, 573, + /* 1050 */ 576, 561, 81, 81, 573, 374, 561, 971, 386, 132, + /* 1060 */ 132, 132, 132, 131, 131, 130, 130, 130, 129, 126, + /* 1070 */ 450, 231, 117, 81, 81, 287, 287, 231, 287, 287, + /* 1080 */ 576, 1511, 576, 1336, 1204, 1205, 1204, 139, 573, 556, + /* 1090 */ 561, 573, 412, 561, 441, 456, 969, 213, 558, 1511, + /* 1100 */ 1513, 1550, 969, 143, 143, 145, 145, 1368, 314, 478, + /* 1110 */ 444, 970, 412, 850, 851, 852, 135, 136, 90, 1228, + /* 1120 */ 1228, 1063, 1066, 1053, 1053, 133, 133, 134, 134, 134, + /* 1130 */ 134, 357, 412, 397, 1148, 304, 135, 136, 90, 1228, + /* 1140 */ 1228, 1063, 1066, 1053, 1053, 133, 133, 134, 134, 134, + /* 1150 */ 134, 1575, 323, 6, 862, 7, 135, 124, 90, 1228, + /* 1160 */ 1228, 1063, 1066, 1053, 1053, 133, 133, 134, 134, 134, + /* 1170 */ 134, 409, 408, 1511, 212, 132, 132, 132, 132, 131, + /* 1180 */ 131, 130, 130, 130, 129, 126, 450, 411, 118, 1204, + /* 1190 */ 116, 10, 352, 265, 355, 132, 132, 132, 132, 131, + /* 1200 */ 131, 130, 130, 130, 129, 126, 450, 576, 324, 306, + /* 1210 */ 576, 306, 1250, 469, 158, 132, 132, 132, 132, 131, + /* 1220 */ 131, 130, 130, 130, 129, 126, 450, 207, 1224, 1126, + /* 1230 */ 65, 65, 470, 66, 66, 412, 447, 446, 882, 531, + /* 1240 */ 335, 258, 257, 256, 1127, 1233, 1204, 1205, 1204, 327, + /* 1250 */ 1235, 874, 159, 576, 16, 480, 1085, 1040, 1234, 1128, + /* 1260 */ 136, 90, 1228, 1228, 1063, 1066, 1053, 1053, 133, 133, + /* 1270 */ 134, 134, 134, 134, 1029, 576, 81, 81, 1028, 1040, + /* 1280 */ 922, 576, 463, 1236, 576, 1236, 1224, 502, 107, 1435, + /* 1290 */ 923, 6, 576, 410, 1498, 882, 1029, 480, 21, 21, + /* 1300 */ 1028, 332, 1380, 334, 53, 53, 497, 81, 81, 874, + /* 1310 */ 1028, 1028, 1030, 445, 259, 19, 19, 533, 132, 132, + /* 1320 */ 132, 132, 131, 131, 130, 130, 130, 129, 126, 450, + /* 1330 */ 551, 301, 1028, 1028, 1030, 107, 532, 545, 121, 568, + /* 1340 */ 1188, 4, 1126, 1576, 449, 576, 462, 7, 1282, 418, + /* 1350 */ 462, 350, 1435, 576, 518, 571, 544, 1127, 121, 568, + /* 1360 */ 442, 4, 1188, 464, 533, 1180, 1223, 9, 67, 67, + /* 1370 */ 487, 576, 1128, 303, 410, 571, 54, 54, 451, 576, + /* 1380 */ 123, 944, 576, 417, 576, 333, 943, 1379, 576, 236, + /* 1390 */ 565, 576, 1574, 564, 68, 68, 7, 576, 451, 362, + /* 1400 */ 419, 182, 69, 69, 541, 70, 70, 71, 71, 540, + /* 1410 */ 565, 72, 72, 484, 55, 55, 473, 1180, 296, 1040, + /* 1420 */ 56, 56, 296, 493, 541, 119, 119, 410, 1573, 542, + /* 1430 */ 569, 418, 7, 120, 1244, 451, 577, 451, 465, 1040, + /* 1440 */ 1028, 576, 1557, 552, 476, 119, 119, 527, 259, 121, + /* 1450 */ 568, 240, 4, 120, 576, 451, 577, 451, 576, 477, + /* 1460 */ 1028, 576, 156, 576, 57, 57, 571, 576, 286, 229, + /* 1470 */ 410, 336, 1028, 1028, 1030, 1031, 35, 59, 59, 219, + /* 1480 */ 983, 60, 60, 220, 73, 73, 74, 74, 984, 451, + /* 1490 */ 75, 75, 1028, 1028, 1030, 1031, 35, 96, 216, 291, + /* 1500 */ 552, 565, 1188, 318, 395, 395, 394, 276, 392, 576, + /* 1510 */ 485, 859, 474, 1311, 410, 541, 576, 417, 1530, 1144, + /* 1520 */ 540, 399, 1188, 292, 237, 1153, 326, 38, 23, 576, + /* 1530 */ 1040, 576, 20, 20, 325, 299, 119, 119, 164, 76, + /* 1540 */ 76, 1529, 121, 568, 120, 4, 451, 577, 451, 203, + /* 1550 */ 576, 1028, 141, 141, 142, 142, 576, 322, 39, 571, + /* 1560 */ 341, 1021, 110, 264, 239, 901, 900, 423, 242, 908, + /* 1570 */ 909, 370, 173, 77, 77, 43, 479, 1310, 264, 62, + /* 1580 */ 62, 369, 451, 1028, 1028, 1030, 1031, 35, 1601, 1192, + /* 1590 */ 453, 1092, 238, 291, 565, 163, 1309, 110, 395, 395, + /* 1600 */ 394, 276, 392, 986, 987, 859, 481, 346, 264, 110, + /* 1610 */ 1032, 489, 576, 1188, 503, 1088, 261, 261, 237, 576, + /* 1620 */ 326, 121, 568, 1040, 4, 347, 1376, 413, 325, 119, + /* 1630 */ 119, 948, 319, 567, 351, 78, 78, 120, 571, 451, + /* 1640 */ 577, 451, 79, 79, 1028, 354, 356, 576, 360, 1092, + /* 1650 */ 110, 576, 974, 942, 264, 123, 457, 358, 239, 576, + /* 1660 */ 519, 451, 939, 1104, 123, 1104, 173, 576, 1032, 43, + /* 1670 */ 63, 63, 1324, 565, 168, 168, 1028, 1028, 1030, 1031, + /* 1680 */ 35, 576, 169, 169, 1308, 872, 238, 157, 1589, 576, + /* 1690 */ 86, 86, 365, 89, 568, 375, 4, 1103, 941, 1103, + /* 1700 */ 123, 576, 1040, 1389, 64, 64, 1188, 1434, 119, 119, + /* 1710 */ 571, 576, 82, 82, 563, 576, 120, 165, 451, 577, + /* 1720 */ 451, 413, 1362, 1028, 144, 144, 319, 567, 576, 1374, + /* 1730 */ 562, 498, 279, 451, 83, 83, 1439, 576, 166, 166, + /* 1740 */ 576, 1289, 554, 576, 1280, 565, 576, 12, 576, 1268, + /* 1750 */ 457, 146, 146, 1267, 576, 1028, 1028, 1030, 1031, 35, + /* 1760 */ 140, 140, 1269, 167, 167, 1609, 160, 160, 1359, 150, + /* 1770 */ 150, 149, 149, 311, 1040, 576, 312, 147, 147, 313, + /* 1780 */ 119, 119, 222, 235, 576, 1188, 396, 576, 120, 576, + /* 1790 */ 451, 577, 451, 1192, 453, 1028, 508, 291, 148, 148, + /* 1800 */ 1421, 1612, 395, 395, 394, 276, 392, 85, 85, 859, + /* 1810 */ 87, 87, 84, 84, 553, 576, 294, 576, 1426, 338, + /* 1820 */ 339, 1425, 237, 300, 326, 1416, 1409, 1028, 1028, 1030, + /* 1830 */ 1031, 35, 325, 344, 403, 483, 226, 1307, 52, 52, + /* 1840 */ 58, 58, 368, 1371, 1502, 566, 1501, 121, 568, 221, + /* 1850 */ 4, 208, 268, 209, 390, 1244, 1549, 1188, 1372, 1370, + /* 1860 */ 1369, 1547, 239, 184, 571, 233, 421, 1241, 95, 218, + /* 1870 */ 173, 1507, 193, 43, 91, 94, 178, 186, 467, 188, + /* 1880 */ 468, 1422, 13, 189, 190, 191, 501, 451, 245, 108, + /* 1890 */ 238, 401, 1428, 1427, 1430, 475, 404, 1496, 197, 565, + /* 1900 */ 14, 490, 249, 101, 1518, 496, 349, 280, 251, 201, + /* 1910 */ 353, 499, 252, 406, 1270, 253, 517, 1327, 1326, 435, + /* 1920 */ 1325, 1318, 103, 893, 1296, 413, 227, 407, 1040, 1626, + /* 1930 */ 319, 567, 1625, 1297, 119, 119, 439, 367, 1317, 1295, + /* 1940 */ 1624, 526, 120, 440, 451, 577, 451, 1594, 309, 1028, + /* 1950 */ 310, 373, 266, 267, 457, 1580, 1579, 443, 138, 1394, + /* 1960 */ 552, 1393, 11, 1483, 384, 115, 317, 1350, 109, 536, + /* 1970 */ 42, 579, 382, 214, 1349, 388, 1198, 389, 275, 277, + /* 1980 */ 278, 1028, 1028, 1030, 1031, 35, 580, 1265, 414, 1260, + /* 1990 */ 170, 415, 183, 1534, 1535, 1533, 171, 154, 307, 1532, + /* 2000 */ 846, 223, 224, 88, 452, 215, 172, 321, 234, 1102, + /* 2010 */ 152, 1188, 1100, 329, 185, 174, 1223, 925, 187, 241, + /* 2020 */ 337, 244, 1116, 192, 175, 176, 424, 426, 97, 194, + /* 2030 */ 98, 99, 100, 177, 1119, 1115, 246, 247, 161, 24, + /* 2040 */ 248, 348, 1238, 264, 1108, 250, 495, 199, 198, 15, + /* 2050 */ 861, 500, 369, 254, 504, 509, 512, 200, 102, 25, + /* 2060 */ 179, 361, 26, 364, 104, 891, 308, 162, 105, 904, + /* 2070 */ 520, 106, 1185, 1069, 1155, 17, 228, 27, 1154, 283, + /* 2080 */ 285, 263, 978, 202, 972, 123, 28, 1175, 29, 30, + /* 2090 */ 1179, 1171, 31, 1173, 1160, 41, 32, 206, 548, 33, + /* 2100 */ 110, 1178, 1083, 8, 112, 1070, 113, 1068, 1072, 34, + /* 2110 */ 1073, 560, 1125, 269, 1124, 270, 36, 18, 1194, 1033, + /* 2120 */ 873, 151, 122, 37, 393, 271, 272, 572, 181, 1193, + /* 2130 */ 1256, 1256, 1256, 935, 1256, 1256, 1256, 1256, 1256, 1256, + /* 2140 */ 1256, 1617, }; static const YYCODETYPE yy_lookahead[] = { - /* 0 */ 193, 193, 193, 274, 275, 276, 193, 274, 275, 276, - /* 10 */ 193, 223, 219, 225, 206, 210, 211, 212, 193, 19, - /* 20 */ 219, 233, 216, 216, 217, 216, 217, 193, 295, 216, - /* 30 */ 217, 31, 193, 216, 217, 193, 228, 213, 230, 39, - /* 40 */ 206, 216, 217, 43, 44, 45, 46, 47, 48, 49, - /* 50 */ 50, 51, 52, 53, 54, 55, 56, 57, 193, 19, - /* 60 */ 185, 186, 187, 188, 189, 190, 253, 274, 275, 276, - /* 70 */ 195, 193, 197, 193, 261, 274, 275, 276, 253, 204, - /* 80 */ 238, 204, 81, 43, 44, 45, 46, 47, 48, 49, - /* 90 */ 50, 51, 52, 53, 54, 55, 56, 57, 274, 275, - /* 100 */ 276, 262, 102, 103, 104, 105, 106, 107, 108, 109, - /* 110 */ 110, 111, 112, 113, 239, 240, 239, 240, 210, 211, - /* 120 */ 212, 314, 315, 314, 59, 316, 86, 252, 88, 252, - /* 130 */ 19, 314, 315, 256, 257, 113, 25, 72, 296, 138, - /* 140 */ 139, 266, 102, 103, 104, 105, 106, 107, 108, 109, + /* 0 */ 194, 276, 277, 278, 216, 194, 194, 217, 194, 194, + /* 10 */ 194, 194, 224, 194, 194, 276, 277, 278, 204, 19, + /* 20 */ 206, 202, 297, 217, 218, 205, 207, 217, 205, 217, + /* 30 */ 218, 31, 217, 218, 217, 218, 29, 217, 218, 39, + /* 40 */ 33, 217, 220, 43, 44, 45, 46, 47, 48, 49, + /* 50 */ 50, 51, 52, 53, 54, 55, 56, 57, 312, 19, + /* 60 */ 240, 241, 316, 240, 241, 194, 46, 47, 48, 49, + /* 70 */ 22, 254, 65, 253, 254, 255, 253, 194, 255, 194, + /* 80 */ 263, 258, 259, 43, 44, 45, 46, 47, 48, 49, + /* 90 */ 50, 51, 52, 53, 54, 55, 56, 57, 276, 277, + /* 100 */ 278, 285, 102, 103, 104, 105, 106, 107, 108, 109, + /* 110 */ 110, 111, 112, 113, 59, 186, 187, 188, 189, 190, + /* 120 */ 191, 310, 239, 317, 318, 196, 86, 198, 88, 317, + /* 130 */ 19, 319, 317, 318, 205, 264, 25, 211, 212, 213, + /* 140 */ 205, 121, 102, 103, 104, 105, 106, 107, 108, 109, /* 150 */ 110, 111, 112, 113, 43, 44, 45, 46, 47, 48, - /* 160 */ 49, 50, 51, 52, 53, 54, 55, 56, 57, 81, - /* 170 */ 292, 59, 292, 298, 108, 109, 110, 111, 112, 113, - /* 180 */ 69, 116, 117, 118, 72, 106, 107, 193, 111, 112, - /* 190 */ 113, 54, 55, 56, 57, 58, 102, 103, 104, 105, - /* 200 */ 106, 107, 108, 109, 110, 111, 112, 113, 120, 25, - /* 210 */ 216, 217, 145, 102, 103, 104, 105, 106, 107, 108, - /* 220 */ 109, 110, 111, 112, 113, 231, 138, 139, 116, 117, - /* 230 */ 118, 164, 153, 19, 155, 54, 55, 56, 57, 102, + /* 160 */ 49, 50, 51, 52, 53, 54, 55, 56, 57, 240, + /* 170 */ 241, 116, 117, 118, 119, 240, 241, 122, 123, 124, + /* 180 */ 69, 298, 253, 194, 255, 106, 107, 132, 253, 141, + /* 190 */ 255, 54, 55, 56, 57, 58, 207, 268, 102, 103, + /* 200 */ 104, 105, 106, 107, 108, 109, 110, 111, 112, 113, + /* 210 */ 214, 128, 129, 102, 103, 104, 105, 106, 107, 108, + /* 220 */ 109, 110, 111, 112, 113, 134, 25, 136, 137, 300, + /* 230 */ 165, 166, 153, 19, 155, 54, 55, 56, 57, 102, /* 240 */ 103, 104, 105, 106, 107, 108, 109, 110, 111, 112, - /* 250 */ 113, 128, 129, 46, 47, 48, 49, 43, 44, 45, + /* 250 */ 113, 108, 109, 110, 111, 112, 113, 43, 44, 45, /* 260 */ 46, 47, 48, 49, 50, 51, 52, 53, 54, 55, - /* 270 */ 56, 57, 216, 193, 25, 59, 193, 19, 165, 166, - /* 280 */ 193, 67, 24, 102, 103, 104, 105, 106, 107, 108, - /* 290 */ 109, 110, 111, 112, 113, 73, 216, 217, 59, 216, - /* 300 */ 217, 43, 44, 45, 46, 47, 48, 49, 50, 51, + /* 270 */ 56, 57, 276, 277, 278, 113, 194, 19, 22, 23, + /* 280 */ 194, 67, 24, 102, 103, 104, 105, 106, 107, 108, + /* 290 */ 109, 110, 111, 112, 113, 220, 250, 59, 252, 217, + /* 300 */ 218, 43, 44, 45, 46, 47, 48, 49, 50, 51, /* 310 */ 52, 53, 54, 55, 56, 57, 102, 103, 104, 105, - /* 320 */ 106, 107, 108, 109, 110, 111, 112, 113, 121, 145, - /* 330 */ 59, 193, 116, 117, 118, 119, 273, 204, 122, 123, - /* 340 */ 124, 19, 20, 134, 22, 136, 137, 19, 132, 127, - /* 350 */ 128, 129, 24, 22, 23, 116, 117, 118, 36, 193, + /* 320 */ 106, 107, 108, 109, 110, 111, 112, 113, 106, 107, + /* 330 */ 108, 109, 110, 111, 112, 113, 254, 59, 205, 138, + /* 340 */ 139, 19, 20, 194, 22, 263, 22, 23, 231, 25, + /* 350 */ 72, 276, 277, 278, 116, 117, 118, 101, 36, 76, /* 360 */ 102, 103, 104, 105, 106, 107, 108, 109, 110, 111, - /* 370 */ 112, 113, 239, 240, 311, 312, 215, 106, 107, 241, - /* 380 */ 19, 59, 216, 217, 223, 252, 115, 116, 117, 118, - /* 390 */ 151, 120, 26, 71, 193, 308, 309, 193, 149, 128, - /* 400 */ 313, 216, 269, 81, 43, 44, 45, 46, 47, 48, - /* 410 */ 49, 50, 51, 52, 53, 54, 55, 56, 57, 253, - /* 420 */ 216, 217, 100, 95, 153, 59, 155, 261, 106, 107, - /* 430 */ 25, 193, 101, 193, 193, 231, 114, 25, 116, 117, - /* 440 */ 118, 113, 304, 121, 193, 204, 59, 119, 120, 121, - /* 450 */ 122, 123, 124, 125, 216, 217, 193, 216, 217, 131, - /* 460 */ 138, 139, 230, 102, 103, 104, 105, 106, 107, 108, + /* 370 */ 112, 113, 89, 240, 241, 92, 73, 194, 194, 73, + /* 380 */ 19, 59, 188, 189, 190, 191, 253, 81, 255, 151, + /* 390 */ 196, 25, 198, 71, 116, 117, 118, 311, 312, 205, + /* 400 */ 217, 218, 316, 81, 43, 44, 45, 46, 47, 48, + /* 410 */ 49, 50, 51, 52, 53, 54, 55, 56, 57, 270, + /* 420 */ 22, 23, 100, 25, 59, 101, 138, 139, 106, 107, + /* 430 */ 127, 128, 129, 127, 240, 241, 114, 254, 116, 117, + /* 440 */ 118, 76, 76, 121, 138, 139, 263, 253, 264, 255, + /* 450 */ 205, 275, 87, 19, 89, 89, 194, 92, 92, 199, + /* 460 */ 138, 139, 268, 102, 103, 104, 105, 106, 107, 108, /* 470 */ 109, 110, 111, 112, 113, 153, 154, 155, 156, 157, - /* 480 */ 239, 240, 116, 117, 118, 76, 193, 23, 19, 25, - /* 490 */ 22, 253, 23, 252, 253, 108, 87, 204, 89, 261, - /* 500 */ 198, 92, 261, 116, 117, 118, 193, 306, 307, 216, - /* 510 */ 217, 150, 43, 44, 45, 46, 47, 48, 49, 50, - /* 520 */ 51, 52, 53, 54, 55, 56, 57, 59, 193, 216, - /* 530 */ 217, 19, 239, 240, 283, 23, 106, 107, 108, 109, - /* 540 */ 110, 111, 112, 113, 73, 252, 253, 142, 308, 309, - /* 550 */ 138, 139, 81, 313, 145, 43, 44, 45, 46, 47, + /* 480 */ 81, 116, 117, 118, 129, 240, 241, 224, 19, 226, + /* 490 */ 314, 315, 23, 25, 300, 59, 22, 234, 253, 101, + /* 500 */ 255, 236, 237, 26, 194, 183, 194, 152, 72, 22, + /* 510 */ 145, 150, 43, 44, 45, 46, 47, 48, 49, 50, + /* 520 */ 51, 52, 53, 54, 55, 56, 57, 217, 218, 217, + /* 530 */ 218, 19, 189, 59, 191, 23, 59, 138, 139, 196, + /* 540 */ 135, 198, 232, 283, 232, 140, 59, 287, 205, 275, + /* 550 */ 116, 205, 116, 117, 118, 43, 44, 45, 46, 47, /* 560 */ 48, 49, 50, 51, 52, 53, 54, 55, 56, 57, - /* 570 */ 307, 102, 103, 104, 105, 106, 107, 108, 109, 110, - /* 580 */ 111, 112, 113, 281, 116, 117, 118, 285, 23, 193, - /* 590 */ 25, 119, 59, 193, 122, 123, 124, 59, 127, 203, - /* 600 */ 59, 205, 19, 268, 132, 25, 23, 22, 193, 138, - /* 610 */ 139, 249, 204, 251, 102, 103, 104, 105, 106, 107, + /* 570 */ 194, 102, 103, 104, 105, 106, 107, 108, 109, 110, + /* 580 */ 111, 112, 113, 240, 241, 194, 240, 241, 314, 315, + /* 590 */ 116, 117, 118, 116, 117, 118, 253, 194, 255, 253, + /* 600 */ 59, 255, 19, 116, 117, 118, 23, 22, 217, 218, + /* 610 */ 142, 268, 205, 275, 102, 103, 104, 105, 106, 107, /* 620 */ 108, 109, 110, 111, 112, 113, 43, 44, 45, 46, /* 630 */ 47, 48, 49, 50, 51, 52, 53, 54, 55, 56, - /* 640 */ 57, 19, 22, 23, 59, 23, 25, 239, 240, 116, - /* 650 */ 117, 118, 193, 11, 116, 117, 118, 116, 117, 118, - /* 660 */ 252, 269, 22, 193, 15, 43, 44, 45, 46, 47, + /* 640 */ 57, 19, 194, 300, 59, 23, 119, 240, 241, 122, + /* 650 */ 123, 124, 314, 315, 194, 236, 237, 194, 117, 132, + /* 660 */ 253, 81, 255, 205, 59, 43, 44, 45, 46, 47, /* 670 */ 48, 49, 50, 51, 52, 53, 54, 55, 56, 57, - /* 680 */ 273, 143, 193, 118, 143, 102, 103, 104, 105, 106, - /* 690 */ 107, 108, 109, 110, 111, 112, 113, 76, 118, 59, - /* 700 */ 241, 116, 117, 118, 304, 216, 217, 292, 143, 60, - /* 710 */ 89, 241, 19, 92, 193, 193, 23, 22, 311, 312, - /* 720 */ 231, 101, 22, 143, 102, 103, 104, 105, 106, 107, + /* 680 */ 217, 218, 194, 194, 194, 102, 103, 104, 105, 106, + /* 690 */ 107, 108, 109, 110, 111, 112, 113, 294, 240, 241, + /* 700 */ 120, 116, 117, 118, 59, 194, 217, 218, 211, 212, + /* 710 */ 213, 253, 19, 255, 194, 19, 23, 254, 138, 139, + /* 720 */ 24, 232, 117, 194, 102, 103, 104, 105, 106, 107, /* 730 */ 108, 109, 110, 111, 112, 113, 43, 44, 45, 46, /* 740 */ 47, 48, 49, 50, 51, 52, 53, 54, 55, 56, - /* 750 */ 57, 19, 193, 193, 59, 23, 116, 117, 118, 59, - /* 760 */ 201, 21, 241, 304, 22, 206, 127, 128, 129, 193, - /* 770 */ 128, 129, 235, 236, 304, 43, 44, 45, 46, 47, + /* 750 */ 57, 19, 264, 108, 76, 23, 127, 128, 129, 311, + /* 760 */ 312, 116, 117, 118, 316, 87, 306, 89, 308, 194, + /* 770 */ 92, 22, 59, 194, 22, 43, 44, 45, 46, 47, /* 780 */ 48, 49, 50, 51, 52, 53, 54, 55, 56, 57, - /* 790 */ 22, 193, 216, 217, 193, 102, 103, 104, 105, 106, - /* 800 */ 107, 108, 109, 110, 111, 112, 113, 231, 193, 193, - /* 810 */ 193, 116, 117, 118, 216, 217, 116, 117, 118, 226, - /* 820 */ 80, 193, 19, 235, 236, 304, 23, 211, 212, 231, - /* 830 */ 204, 216, 217, 205, 102, 103, 104, 105, 106, 107, + /* 790 */ 194, 95, 217, 218, 265, 102, 103, 104, 105, 106, + /* 800 */ 107, 108, 109, 110, 111, 112, 113, 232, 59, 113, + /* 810 */ 25, 59, 194, 217, 218, 119, 120, 121, 122, 123, + /* 820 */ 124, 125, 19, 145, 194, 194, 23, 131, 232, 116, + /* 830 */ 117, 118, 35, 194, 102, 103, 104, 105, 106, 107, /* 840 */ 108, 109, 110, 111, 112, 113, 43, 44, 45, 46, /* 850 */ 47, 48, 49, 50, 51, 52, 53, 54, 55, 56, - /* 860 */ 57, 19, 193, 123, 76, 239, 240, 193, 253, 239, - /* 870 */ 240, 239, 240, 193, 106, 107, 193, 89, 252, 193, - /* 880 */ 92, 59, 252, 141, 252, 43, 44, 45, 46, 47, + /* 860 */ 57, 19, 194, 66, 194, 116, 117, 118, 116, 117, + /* 870 */ 118, 74, 242, 294, 194, 194, 206, 23, 194, 25, + /* 880 */ 194, 111, 112, 113, 25, 43, 44, 45, 46, 47, /* 890 */ 48, 49, 50, 51, 52, 53, 54, 55, 56, 57, - /* 900 */ 284, 161, 216, 217, 193, 102, 103, 104, 105, 106, - /* 910 */ 107, 108, 109, 110, 111, 112, 113, 231, 193, 16, - /* 920 */ 187, 188, 189, 190, 7, 8, 9, 309, 195, 25, - /* 930 */ 197, 313, 19, 127, 128, 129, 262, 204, 22, 117, - /* 940 */ 24, 216, 217, 263, 102, 103, 104, 105, 106, 107, + /* 900 */ 24, 194, 194, 217, 218, 102, 103, 104, 105, 106, + /* 910 */ 107, 108, 109, 110, 111, 112, 113, 241, 232, 194, + /* 920 */ 212, 213, 242, 242, 217, 218, 242, 130, 11, 253, + /* 930 */ 194, 255, 19, 265, 149, 59, 306, 194, 308, 232, + /* 940 */ 309, 310, 217, 218, 102, 103, 104, 105, 106, 107, /* 950 */ 108, 109, 110, 111, 112, 113, 43, 44, 45, 46, /* 960 */ 47, 48, 49, 50, 51, 52, 53, 54, 55, 56, - /* 970 */ 57, 193, 239, 240, 193, 59, 19, 188, 253, 190, - /* 980 */ 77, 226, 79, 193, 195, 252, 197, 193, 19, 301, - /* 990 */ 302, 193, 193, 204, 216, 217, 226, 216, 217, 266, - /* 1000 */ 204, 159, 45, 46, 47, 48, 49, 50, 51, 52, + /* 970 */ 57, 194, 194, 59, 194, 239, 19, 194, 25, 254, + /* 980 */ 303, 304, 23, 194, 25, 126, 306, 306, 308, 308, + /* 990 */ 306, 271, 308, 117, 286, 217, 218, 217, 218, 194, + /* 1000 */ 194, 159, 45, 46, 47, 48, 49, 50, 51, 52, /* 1010 */ 53, 54, 55, 56, 57, 102, 103, 104, 105, 106, - /* 1020 */ 107, 108, 109, 110, 111, 112, 113, 12, 239, 240, - /* 1030 */ 232, 298, 238, 117, 253, 239, 240, 238, 259, 260, - /* 1040 */ 193, 252, 27, 31, 193, 193, 142, 204, 252, 193, - /* 1050 */ 193, 39, 262, 193, 100, 266, 278, 42, 204, 102, + /* 1020 */ 107, 108, 109, 110, 111, 112, 113, 59, 239, 194, + /* 1030 */ 116, 117, 118, 260, 254, 194, 240, 241, 194, 233, + /* 1040 */ 205, 240, 241, 205, 239, 128, 129, 270, 265, 253, + /* 1050 */ 194, 255, 217, 218, 253, 194, 255, 143, 280, 102, /* 1060 */ 103, 104, 105, 106, 107, 108, 109, 110, 111, 112, - /* 1070 */ 113, 117, 159, 216, 217, 121, 216, 217, 63, 193, - /* 1080 */ 193, 193, 239, 240, 115, 116, 193, 298, 73, 238, - /* 1090 */ 238, 231, 19, 239, 240, 252, 22, 24, 211, 212, - /* 1100 */ 24, 193, 216, 217, 216, 217, 252, 153, 154, 155, - /* 1110 */ 253, 16, 19, 144, 213, 268, 43, 44, 45, 46, + /* 1070 */ 113, 118, 159, 217, 218, 240, 241, 118, 240, 241, + /* 1080 */ 194, 194, 194, 239, 116, 117, 118, 22, 253, 254, + /* 1090 */ 255, 253, 19, 255, 233, 194, 143, 24, 263, 212, + /* 1100 */ 213, 194, 143, 217, 218, 217, 218, 261, 262, 271, + /* 1110 */ 254, 143, 19, 7, 8, 9, 43, 44, 45, 46, /* 1120 */ 47, 48, 49, 50, 51, 52, 53, 54, 55, 56, - /* 1130 */ 57, 238, 19, 59, 193, 59, 43, 44, 45, 46, + /* 1130 */ 57, 16, 19, 22, 23, 294, 43, 44, 45, 46, /* 1140 */ 47, 48, 49, 50, 51, 52, 53, 54, 55, 56, - /* 1150 */ 57, 22, 23, 193, 25, 193, 43, 44, 45, 46, + /* 1150 */ 57, 312, 194, 214, 21, 316, 43, 44, 45, 46, /* 1160 */ 47, 48, 49, 50, 51, 52, 53, 54, 55, 56, - /* 1170 */ 57, 284, 77, 193, 79, 102, 103, 104, 105, 106, - /* 1180 */ 107, 108, 109, 110, 111, 112, 113, 286, 193, 193, - /* 1190 */ 193, 117, 291, 117, 232, 102, 103, 104, 105, 106, - /* 1200 */ 107, 108, 109, 110, 111, 112, 113, 204, 22, 23, - /* 1210 */ 66, 25, 216, 217, 35, 102, 103, 104, 105, 106, - /* 1220 */ 107, 108, 109, 110, 111, 112, 113, 193, 268, 85, - /* 1230 */ 101, 193, 309, 309, 240, 19, 313, 313, 94, 208, - /* 1240 */ 209, 193, 239, 240, 193, 66, 252, 19, 268, 244, - /* 1250 */ 216, 217, 193, 74, 213, 252, 161, 19, 263, 254, + /* 1170 */ 57, 106, 107, 286, 194, 102, 103, 104, 105, 106, + /* 1180 */ 107, 108, 109, 110, 111, 112, 113, 207, 158, 59, + /* 1190 */ 160, 22, 77, 24, 79, 102, 103, 104, 105, 106, + /* 1200 */ 107, 108, 109, 110, 111, 112, 113, 194, 194, 229, + /* 1210 */ 194, 231, 101, 80, 22, 102, 103, 104, 105, 106, + /* 1220 */ 107, 108, 109, 110, 111, 112, 113, 288, 59, 12, + /* 1230 */ 217, 218, 293, 217, 218, 19, 106, 107, 59, 19, + /* 1240 */ 16, 127, 128, 129, 27, 115, 116, 117, 118, 194, + /* 1250 */ 120, 59, 22, 194, 24, 194, 123, 100, 128, 42, /* 1260 */ 44, 45, 46, 47, 48, 49, 50, 51, 52, 53, - /* 1270 */ 54, 55, 56, 57, 193, 216, 217, 5, 59, 193, - /* 1280 */ 19, 244, 10, 11, 12, 13, 14, 101, 309, 17, - /* 1290 */ 146, 254, 313, 193, 193, 76, 115, 216, 217, 309, - /* 1300 */ 12, 263, 30, 313, 32, 46, 87, 46, 89, 130, - /* 1310 */ 193, 92, 40, 22, 263, 27, 216, 217, 102, 103, + /* 1270 */ 54, 55, 56, 57, 117, 194, 217, 218, 121, 100, + /* 1280 */ 63, 194, 245, 153, 194, 155, 117, 19, 115, 194, + /* 1290 */ 73, 214, 194, 256, 161, 116, 117, 194, 217, 218, + /* 1300 */ 121, 77, 194, 79, 217, 218, 194, 217, 218, 117, + /* 1310 */ 153, 154, 155, 254, 46, 217, 218, 144, 102, 103, /* 1320 */ 104, 105, 106, 107, 108, 109, 110, 111, 112, 113, - /* 1330 */ 42, 150, 291, 216, 217, 116, 117, 118, 19, 20, - /* 1340 */ 193, 22, 70, 260, 116, 193, 24, 264, 193, 263, - /* 1350 */ 78, 63, 61, 81, 116, 36, 193, 260, 193, 29, - /* 1360 */ 193, 264, 193, 33, 145, 193, 59, 48, 216, 217, - /* 1370 */ 98, 216, 217, 193, 115, 193, 115, 193, 59, 216, - /* 1380 */ 217, 216, 217, 216, 217, 216, 217, 255, 216, 217, - /* 1390 */ 71, 193, 131, 193, 25, 65, 216, 217, 216, 217, - /* 1400 */ 216, 217, 208, 209, 85, 133, 193, 100, 193, 90, - /* 1410 */ 138, 139, 138, 139, 216, 217, 216, 217, 193, 100, - /* 1420 */ 193, 108, 135, 116, 117, 106, 107, 140, 121, 216, - /* 1430 */ 217, 216, 217, 114, 162, 116, 117, 118, 299, 300, - /* 1440 */ 121, 216, 217, 216, 217, 193, 244, 193, 135, 244, - /* 1450 */ 193, 256, 257, 140, 244, 193, 254, 193, 193, 254, - /* 1460 */ 153, 154, 155, 141, 254, 149, 150, 258, 216, 217, - /* 1470 */ 216, 217, 153, 154, 155, 156, 157, 0, 1, 2, - /* 1480 */ 216, 217, 5, 115, 158, 193, 160, 10, 11, 12, - /* 1490 */ 13, 14, 193, 59, 17, 126, 193, 19, 20, 129, - /* 1500 */ 22, 193, 22, 22, 24, 193, 23, 30, 25, 32, - /* 1510 */ 19, 20, 144, 22, 36, 216, 217, 40, 193, 216, - /* 1520 */ 217, 193, 152, 129, 216, 217, 193, 36, 216, 217, - /* 1530 */ 193, 99, 193, 193, 53, 193, 193, 59, 23, 193, - /* 1540 */ 25, 216, 217, 193, 216, 217, 152, 70, 59, 71, - /* 1550 */ 59, 117, 193, 216, 217, 78, 216, 217, 81, 216, - /* 1560 */ 217, 318, 71, 85, 193, 133, 193, 193, 90, 23, - /* 1570 */ 23, 25, 25, 120, 121, 98, 85, 193, 100, 193, - /* 1580 */ 23, 90, 25, 121, 106, 107, 19, 216, 217, 216, - /* 1590 */ 217, 100, 114, 131, 116, 117, 118, 106, 107, 121, - /* 1600 */ 216, 217, 216, 217, 193, 114, 117, 116, 117, 118, - /* 1610 */ 133, 193, 121, 193, 193, 138, 139, 193, 23, 193, - /* 1620 */ 25, 23, 23, 25, 25, 7, 8, 216, 217, 193, - /* 1630 */ 193, 153, 154, 155, 156, 157, 216, 217, 193, 162, - /* 1640 */ 216, 217, 216, 217, 153, 154, 155, 156, 157, 1, - /* 1650 */ 2, 193, 193, 5, 19, 20, 59, 22, 10, 11, - /* 1660 */ 12, 13, 14, 193, 97, 17, 193, 23, 193, 25, - /* 1670 */ 288, 36, 193, 242, 216, 217, 236, 23, 30, 25, - /* 1680 */ 32, 19, 20, 23, 22, 25, 216, 217, 40, 216, - /* 1690 */ 217, 216, 217, 193, 59, 216, 217, 193, 36, 83, - /* 1700 */ 84, 153, 153, 155, 155, 23, 71, 25, 23, 193, - /* 1710 */ 25, 193, 193, 193, 117, 193, 193, 193, 70, 193, - /* 1720 */ 193, 59, 193, 255, 255, 287, 78, 255, 243, 81, - /* 1730 */ 191, 255, 297, 71, 271, 100, 293, 245, 267, 214, - /* 1740 */ 246, 106, 107, 108, 246, 271, 98, 245, 293, 114, - /* 1750 */ 220, 116, 117, 118, 267, 271, 121, 271, 225, 219, - /* 1760 */ 229, 219, 100, 219, 259, 259, 259, 259, 106, 107, - /* 1770 */ 249, 196, 60, 280, 141, 243, 114, 249, 116, 117, - /* 1780 */ 118, 133, 245, 121, 200, 297, 138, 139, 153, 154, - /* 1790 */ 155, 156, 157, 297, 200, 38, 19, 20, 151, 22, - /* 1800 */ 200, 150, 140, 294, 294, 22, 272, 43, 234, 18, - /* 1810 */ 162, 270, 200, 36, 237, 153, 154, 155, 156, 157, - /* 1820 */ 237, 283, 237, 237, 18, 199, 149, 246, 272, 270, - /* 1830 */ 272, 200, 158, 246, 246, 234, 59, 234, 246, 199, - /* 1840 */ 290, 62, 289, 200, 199, 22, 221, 115, 71, 200, - /* 1850 */ 200, 199, 199, 221, 218, 218, 19, 20, 64, 22, - /* 1860 */ 218, 227, 22, 224, 126, 224, 165, 221, 24, 305, - /* 1870 */ 200, 113, 312, 36, 218, 220, 218, 100, 282, 218, - /* 1880 */ 91, 218, 317, 106, 107, 221, 227, 282, 317, 82, - /* 1890 */ 148, 114, 265, 116, 117, 118, 59, 145, 121, 22, - /* 1900 */ 277, 158, 200, 265, 25, 202, 147, 250, 71, 279, - /* 1910 */ 13, 146, 194, 194, 249, 248, 250, 140, 247, 246, - /* 1920 */ 6, 192, 192, 192, 303, 303, 213, 207, 300, 213, - /* 1930 */ 153, 154, 155, 156, 157, 213, 213, 100, 213, 222, - /* 1940 */ 207, 214, 214, 106, 107, 4, 222, 207, 3, 22, - /* 1950 */ 163, 114, 15, 116, 117, 118, 16, 23, 121, 23, - /* 1960 */ 139, 151, 130, 25, 142, 16, 24, 20, 144, 1, - /* 1970 */ 142, 130, 130, 61, 53, 53, 37, 151, 53, 53, - /* 1980 */ 130, 116, 34, 1, 141, 5, 22, 115, 161, 141, - /* 1990 */ 153, 154, 155, 156, 157, 25, 68, 68, 75, 41, - /* 2000 */ 115, 24, 131, 20, 19, 125, 22, 96, 22, 22, - /* 2010 */ 67, 23, 22, 67, 59, 24, 22, 28, 67, 23, - /* 2020 */ 22, 22, 149, 23, 23, 23, 116, 23, 25, 37, - /* 2030 */ 97, 141, 23, 23, 22, 143, 25, 75, 88, 34, - /* 2040 */ 34, 34, 34, 86, 75, 93, 23, 34, 22, 34, - /* 2050 */ 25, 24, 34, 25, 23, 142, 23, 142, 44, 23, - /* 2060 */ 23, 23, 11, 23, 25, 22, 22, 22, 15, 23, - /* 2070 */ 23, 22, 22, 25, 1, 1, 141, 25, 23, 135, - /* 2080 */ 319, 319, 319, 319, 319, 319, 319, 319, 319, 319, - /* 2090 */ 319, 319, 319, 319, 141, 141, 319, 319, 319, 319, - /* 2100 */ 319, 319, 319, 319, 319, 319, 319, 319, 319, 319, - /* 2110 */ 319, 319, 319, 319, 319, 319, 319, 319, 319, 319, - /* 2120 */ 319, 319, 319, 319, 319, 319, 319, 319, 319, 319, - /* 2130 */ 319, 319, 319, 319, 319, 319, 319, 319, 319, 319, - /* 2140 */ 319, 319, 319, 319, 319, 319, 319, 319, 319, 319, - /* 2150 */ 319, 319, 319, 319, 319, 319, 319, 319, 319, 319, - /* 2160 */ 319, 319, 319, 319, 319, 319, 319, 319, 319, 319, - /* 2170 */ 319, 319, 319, 319, 319, 319, 319, 319, 319, 319, - /* 2180 */ 319, 319, 319, 319, 319, 319, 319, 319, 319, 319, - /* 2190 */ 319, 319, 319, 319, 319, 319, 319, 319, 319, 319, - /* 2200 */ 319, 319, 319, 319, 319, 319, 319, 319, 319, 319, - /* 2210 */ 319, 319, 319, 319, 319, 319, 319, 319, 319, 319, - /* 2220 */ 319, 319, 319, 319, 319, 319, 319, 319, 319, 319, - /* 2230 */ 319, 319, 319, 319, 319, 319, 319, 319, 319, 319, - /* 2240 */ 319, 319, 319, 319, 319, 319, 319, 319, 319, 319, - /* 2250 */ 319, 319, 319, 319, 319, 319, 319, 319, 319, 319, - /* 2260 */ 319, 319, 319, 319, 319, 319, 319, 319, 319, 319, - /* 2270 */ 319, 319, 319, 319, 319, 319, 319, 319, 319, 319, - /* 2280 */ 319, + /* 1330 */ 232, 270, 153, 154, 155, 115, 116, 66, 19, 20, + /* 1340 */ 183, 22, 12, 312, 254, 194, 262, 316, 209, 210, + /* 1350 */ 266, 239, 194, 194, 108, 36, 85, 27, 19, 20, + /* 1360 */ 265, 22, 183, 245, 144, 94, 25, 48, 217, 218, + /* 1370 */ 293, 194, 42, 270, 256, 36, 217, 218, 59, 194, + /* 1380 */ 25, 135, 194, 115, 194, 161, 140, 194, 194, 15, + /* 1390 */ 71, 194, 312, 63, 217, 218, 316, 194, 59, 131, + /* 1400 */ 301, 302, 217, 218, 85, 217, 218, 217, 218, 90, + /* 1410 */ 71, 217, 218, 19, 217, 218, 245, 146, 262, 100, + /* 1420 */ 217, 218, 266, 265, 85, 106, 107, 256, 312, 90, + /* 1430 */ 209, 210, 316, 114, 60, 116, 117, 118, 194, 100, + /* 1440 */ 121, 194, 194, 145, 115, 106, 107, 19, 46, 19, + /* 1450 */ 20, 24, 22, 114, 194, 116, 117, 118, 194, 245, + /* 1460 */ 121, 194, 164, 194, 217, 218, 36, 194, 258, 259, + /* 1470 */ 256, 194, 153, 154, 155, 156, 157, 217, 218, 150, + /* 1480 */ 31, 217, 218, 142, 217, 218, 217, 218, 39, 59, + /* 1490 */ 217, 218, 153, 154, 155, 156, 157, 149, 150, 5, + /* 1500 */ 145, 71, 183, 245, 10, 11, 12, 13, 14, 194, + /* 1510 */ 116, 17, 129, 227, 256, 85, 194, 115, 194, 23, + /* 1520 */ 90, 25, 183, 99, 30, 97, 32, 22, 22, 194, + /* 1530 */ 100, 194, 217, 218, 40, 152, 106, 107, 23, 217, + /* 1540 */ 218, 194, 19, 20, 114, 22, 116, 117, 118, 257, + /* 1550 */ 194, 121, 217, 218, 217, 218, 194, 133, 53, 36, + /* 1560 */ 23, 23, 25, 25, 70, 120, 121, 61, 141, 7, + /* 1570 */ 8, 121, 78, 217, 218, 81, 23, 227, 25, 217, + /* 1580 */ 218, 131, 59, 153, 154, 155, 156, 157, 0, 1, + /* 1590 */ 2, 59, 98, 5, 71, 23, 227, 25, 10, 11, + /* 1600 */ 12, 13, 14, 83, 84, 17, 23, 23, 25, 25, + /* 1610 */ 59, 194, 194, 183, 23, 23, 25, 25, 30, 194, + /* 1620 */ 32, 19, 20, 100, 22, 194, 194, 133, 40, 106, + /* 1630 */ 107, 108, 138, 139, 194, 217, 218, 114, 36, 116, + /* 1640 */ 117, 118, 217, 218, 121, 194, 194, 194, 23, 117, + /* 1650 */ 25, 194, 23, 23, 25, 25, 162, 194, 70, 194, + /* 1660 */ 145, 59, 23, 153, 25, 155, 78, 194, 117, 81, + /* 1670 */ 217, 218, 194, 71, 217, 218, 153, 154, 155, 156, + /* 1680 */ 157, 194, 217, 218, 194, 23, 98, 25, 321, 194, + /* 1690 */ 217, 218, 194, 19, 20, 194, 22, 153, 23, 155, + /* 1700 */ 25, 194, 100, 194, 217, 218, 183, 194, 106, 107, + /* 1710 */ 36, 194, 217, 218, 237, 194, 114, 243, 116, 117, + /* 1720 */ 118, 133, 194, 121, 217, 218, 138, 139, 194, 194, + /* 1730 */ 194, 290, 289, 59, 217, 218, 194, 194, 217, 218, + /* 1740 */ 194, 194, 140, 194, 194, 71, 194, 244, 194, 194, + /* 1750 */ 162, 217, 218, 194, 194, 153, 154, 155, 156, 157, + /* 1760 */ 217, 218, 194, 217, 218, 194, 217, 218, 257, 217, + /* 1770 */ 218, 217, 218, 257, 100, 194, 257, 217, 218, 257, + /* 1780 */ 106, 107, 215, 299, 194, 183, 192, 194, 114, 194, + /* 1790 */ 116, 117, 118, 1, 2, 121, 221, 5, 217, 218, + /* 1800 */ 273, 197, 10, 11, 12, 13, 14, 217, 218, 17, + /* 1810 */ 217, 218, 217, 218, 140, 194, 246, 194, 273, 295, + /* 1820 */ 247, 273, 30, 247, 32, 269, 269, 153, 154, 155, + /* 1830 */ 156, 157, 40, 246, 273, 295, 230, 226, 217, 218, + /* 1840 */ 217, 218, 220, 261, 220, 282, 220, 19, 20, 244, + /* 1850 */ 22, 250, 141, 250, 246, 60, 201, 183, 261, 261, + /* 1860 */ 261, 201, 70, 299, 36, 299, 201, 38, 151, 150, + /* 1870 */ 78, 285, 22, 81, 296, 296, 43, 235, 18, 238, + /* 1880 */ 201, 274, 272, 238, 238, 238, 18, 59, 200, 149, + /* 1890 */ 98, 247, 274, 274, 235, 247, 247, 247, 235, 71, + /* 1900 */ 272, 201, 200, 158, 292, 62, 291, 201, 200, 22, + /* 1910 */ 201, 222, 200, 222, 201, 200, 115, 219, 219, 64, + /* 1920 */ 219, 228, 22, 126, 221, 133, 165, 222, 100, 225, + /* 1930 */ 138, 139, 225, 219, 106, 107, 24, 219, 228, 219, + /* 1940 */ 219, 307, 114, 113, 116, 117, 118, 315, 284, 121, + /* 1950 */ 284, 222, 201, 91, 162, 320, 320, 82, 148, 267, + /* 1960 */ 145, 267, 22, 279, 201, 158, 281, 251, 147, 146, + /* 1970 */ 25, 203, 250, 249, 251, 248, 13, 247, 195, 195, + /* 1980 */ 6, 153, 154, 155, 156, 157, 193, 193, 305, 193, + /* 1990 */ 208, 305, 302, 214, 214, 214, 208, 223, 223, 214, + /* 2000 */ 4, 215, 215, 214, 3, 22, 208, 163, 15, 23, + /* 2010 */ 16, 183, 23, 139, 151, 130, 25, 20, 142, 24, + /* 2020 */ 16, 144, 1, 142, 130, 130, 61, 37, 53, 151, + /* 2030 */ 53, 53, 53, 130, 116, 1, 34, 141, 5, 22, + /* 2040 */ 115, 161, 75, 25, 68, 141, 41, 115, 68, 24, + /* 2050 */ 20, 19, 131, 125, 67, 67, 96, 22, 22, 22, + /* 2060 */ 37, 23, 22, 24, 22, 59, 67, 23, 149, 28, + /* 2070 */ 22, 25, 23, 23, 23, 22, 141, 34, 97, 23, + /* 2080 */ 23, 34, 116, 22, 143, 25, 34, 75, 34, 34, + /* 2090 */ 75, 88, 34, 86, 23, 22, 34, 25, 24, 34, + /* 2100 */ 25, 93, 23, 44, 142, 23, 142, 23, 23, 22, + /* 2110 */ 11, 25, 23, 25, 23, 22, 22, 22, 1, 23, + /* 2120 */ 23, 23, 22, 22, 15, 141, 141, 25, 25, 1, + /* 2130 */ 322, 322, 322, 135, 322, 322, 322, 322, 322, 322, + /* 2140 */ 322, 141, 322, 322, 322, 322, 322, 322, 322, 322, + /* 2150 */ 322, 322, 322, 322, 322, 322, 322, 322, 322, 322, + /* 2160 */ 322, 322, 322, 322, 322, 322, 322, 322, 322, 322, + /* 2170 */ 322, 322, 322, 322, 322, 322, 322, 322, 322, 322, + /* 2180 */ 322, 322, 322, 322, 322, 322, 322, 322, 322, 322, + /* 2190 */ 322, 322, 322, 322, 322, 322, 322, 322, 322, 322, + /* 2200 */ 322, 322, 322, 322, 322, 322, 322, 322, 322, 322, + /* 2210 */ 322, 322, 322, 322, 322, 322, 322, 322, 322, 322, + /* 2220 */ 322, 322, 322, 322, 322, 322, 322, 322, 322, 322, + /* 2230 */ 322, 322, 322, 322, 322, 322, 322, 322, 322, 322, + /* 2240 */ 322, 322, 322, 322, 322, 322, 322, 322, 322, 322, + /* 2250 */ 322, 322, 322, 322, 322, 322, 322, 322, 322, 322, + /* 2260 */ 322, 322, 322, 322, 322, 322, 322, 322, 322, 322, + /* 2270 */ 322, 322, 322, 322, 322, 322, 322, 322, 322, 322, + /* 2280 */ 322, 322, 322, 322, 322, 322, 322, 322, 322, 322, + /* 2290 */ 322, 322, 322, 322, 322, 322, 322, 322, 322, 322, + /* 2300 */ 322, 322, 322, 322, 322, 322, 322, 322, 322, 322, + /* 2310 */ 322, 322, 322, 322, 322, 322, 322, 322, 322, 322, + /* 2320 */ 322, 322, 322, 322, 322, 322, 322, 322, }; -#define YY_SHIFT_COUNT (574) +#define YY_SHIFT_COUNT (582) #define YY_SHIFT_MIN (0) -#define YY_SHIFT_MAX (2074) +#define YY_SHIFT_MAX (2128) static const unsigned short int yy_shift_ofst[] = { - /* 0 */ 1648, 1477, 1272, 322, 322, 1, 1319, 1478, 1491, 1837, - /* 10 */ 1837, 1837, 471, 0, 0, 214, 1093, 1837, 1837, 1837, - /* 20 */ 1837, 1837, 1837, 1837, 1837, 1837, 1837, 1837, 1837, 1837, - /* 30 */ 271, 271, 1219, 1219, 216, 88, 1, 1, 1, 1, - /* 40 */ 1, 40, 111, 258, 361, 469, 512, 583, 622, 693, - /* 50 */ 732, 803, 842, 913, 1073, 1093, 1093, 1093, 1093, 1093, - /* 60 */ 1093, 1093, 1093, 1093, 1093, 1093, 1093, 1093, 1093, 1093, - /* 70 */ 1093, 1093, 1093, 1113, 1093, 1216, 957, 957, 1635, 1662, - /* 80 */ 1777, 1837, 1837, 1837, 1837, 1837, 1837, 1837, 1837, 1837, - /* 90 */ 1837, 1837, 1837, 1837, 1837, 1837, 1837, 1837, 1837, 1837, - /* 100 */ 1837, 1837, 1837, 1837, 1837, 1837, 1837, 1837, 1837, 1837, - /* 110 */ 1837, 1837, 1837, 1837, 1837, 1837, 1837, 1837, 1837, 1837, - /* 120 */ 1837, 1837, 1837, 1837, 1837, 1837, 1837, 1837, 1837, 1837, - /* 130 */ 137, 181, 181, 181, 181, 181, 181, 181, 94, 430, - /* 140 */ 66, 65, 112, 366, 533, 533, 740, 1261, 533, 533, - /* 150 */ 79, 79, 533, 412, 412, 412, 77, 412, 123, 113, - /* 160 */ 113, 22, 22, 2096, 2096, 328, 328, 328, 239, 468, - /* 170 */ 468, 468, 468, 1015, 1015, 409, 366, 1129, 1186, 533, - /* 180 */ 533, 533, 533, 533, 533, 533, 533, 533, 533, 533, - /* 190 */ 533, 533, 533, 533, 533, 533, 533, 533, 533, 969, - /* 200 */ 621, 621, 533, 642, 788, 788, 1228, 1228, 822, 822, - /* 210 */ 67, 1274, 2096, 2096, 2096, 2096, 2096, 2096, 2096, 1307, - /* 220 */ 954, 954, 585, 472, 640, 387, 695, 538, 541, 700, - /* 230 */ 533, 533, 533, 533, 533, 533, 533, 533, 533, 533, - /* 240 */ 222, 533, 533, 533, 533, 533, 533, 533, 533, 533, - /* 250 */ 533, 533, 533, 1179, 1179, 1179, 533, 533, 533, 565, - /* 260 */ 533, 533, 533, 916, 1144, 533, 533, 1288, 533, 533, - /* 270 */ 533, 533, 533, 533, 533, 533, 639, 1330, 209, 1076, - /* 280 */ 1076, 1076, 1076, 580, 209, 209, 1313, 768, 917, 649, - /* 290 */ 1181, 1316, 405, 1316, 1238, 249, 1181, 1181, 249, 1181, - /* 300 */ 405, 1238, 1369, 464, 1259, 1012, 1012, 1012, 1368, 1368, - /* 310 */ 1368, 1368, 184, 184, 1326, 904, 1287, 1480, 1712, 1712, - /* 320 */ 1633, 1633, 1757, 1757, 1633, 1647, 1651, 1783, 1764, 1791, - /* 330 */ 1791, 1791, 1791, 1633, 1806, 1677, 1651, 1651, 1677, 1783, - /* 340 */ 1764, 1677, 1764, 1677, 1633, 1806, 1674, 1779, 1633, 1806, - /* 350 */ 1823, 1633, 1806, 1633, 1806, 1823, 1732, 1732, 1732, 1794, - /* 360 */ 1840, 1840, 1823, 1732, 1738, 1732, 1794, 1732, 1732, 1701, - /* 370 */ 1844, 1758, 1758, 1823, 1633, 1789, 1789, 1807, 1807, 1742, - /* 380 */ 1752, 1877, 1633, 1743, 1742, 1759, 1765, 1677, 1879, 1897, - /* 390 */ 1897, 1914, 1914, 1914, 2096, 2096, 2096, 2096, 2096, 2096, - /* 400 */ 2096, 2096, 2096, 2096, 2096, 2096, 2096, 2096, 2096, 207, - /* 410 */ 1095, 331, 620, 903, 806, 1074, 1483, 1432, 1481, 1322, - /* 420 */ 1370, 1394, 1515, 1291, 1546, 1547, 1557, 1595, 1598, 1599, - /* 430 */ 1434, 1453, 1618, 1462, 1567, 1489, 1644, 1654, 1616, 1660, - /* 440 */ 1548, 1549, 1682, 1685, 1597, 742, 1941, 1945, 1927, 1787, - /* 450 */ 1937, 1940, 1934, 1936, 1821, 1810, 1832, 1938, 1938, 1942, - /* 460 */ 1822, 1947, 1824, 1949, 1968, 1828, 1841, 1938, 1842, 1912, - /* 470 */ 1939, 1938, 1826, 1921, 1922, 1925, 1926, 1850, 1865, 1948, - /* 480 */ 1843, 1982, 1980, 1964, 1872, 1827, 1928, 1970, 1929, 1923, - /* 490 */ 1958, 1848, 1885, 1977, 1983, 1985, 1871, 1880, 1984, 1943, - /* 500 */ 1986, 1987, 1988, 1990, 1946, 1955, 1991, 1911, 1989, 1994, - /* 510 */ 1951, 1992, 1996, 1873, 1998, 2000, 2001, 2002, 2003, 2004, - /* 520 */ 1999, 1933, 1890, 2009, 2010, 1910, 2005, 2012, 1892, 2011, - /* 530 */ 2006, 2007, 2008, 2013, 1950, 1962, 1957, 2014, 1969, 1952, - /* 540 */ 2015, 2023, 2026, 2027, 2025, 2028, 2018, 1913, 1915, 2031, - /* 550 */ 2011, 2033, 2036, 2037, 2038, 2039, 2040, 2043, 2051, 2044, - /* 560 */ 2045, 2046, 2047, 2049, 2050, 2048, 1944, 1935, 1953, 1954, - /* 570 */ 2052, 2055, 2053, 2073, 2074, + /* 0 */ 1792, 1588, 1494, 322, 322, 399, 306, 1319, 1339, 1430, + /* 10 */ 1828, 1828, 1828, 580, 399, 399, 399, 399, 399, 0, + /* 20 */ 0, 214, 1093, 1828, 1828, 1828, 1828, 1828, 1828, 1828, + /* 30 */ 1828, 1828, 1828, 1828, 1828, 1828, 1828, 1828, 1130, 1130, + /* 40 */ 365, 365, 55, 278, 436, 713, 713, 201, 201, 201, + /* 50 */ 201, 40, 111, 258, 361, 469, 512, 583, 622, 693, + /* 60 */ 732, 803, 842, 913, 1073, 1093, 1093, 1093, 1093, 1093, + /* 70 */ 1093, 1093, 1093, 1093, 1093, 1093, 1093, 1093, 1093, 1093, + /* 80 */ 1093, 1093, 1093, 1113, 1093, 1216, 957, 957, 1523, 1602, + /* 90 */ 1674, 1828, 1828, 1828, 1828, 1828, 1828, 1828, 1828, 1828, + /* 100 */ 1828, 1828, 1828, 1828, 1828, 1828, 1828, 1828, 1828, 1828, + /* 110 */ 1828, 1828, 1828, 1828, 1828, 1828, 1828, 1828, 1828, 1828, + /* 120 */ 1828, 1828, 1828, 1828, 1828, 1828, 1828, 1828, 1828, 1828, + /* 130 */ 1828, 1828, 1828, 1828, 1828, 1828, 1828, 1828, 1828, 1828, + /* 140 */ 137, 181, 181, 181, 181, 181, 181, 181, 96, 222, + /* 150 */ 143, 477, 713, 1133, 1268, 713, 713, 79, 79, 713, + /* 160 */ 770, 83, 65, 65, 65, 288, 162, 162, 2142, 2142, + /* 170 */ 696, 696, 696, 238, 474, 474, 474, 474, 1217, 1217, + /* 180 */ 678, 477, 324, 398, 713, 713, 713, 713, 713, 713, + /* 190 */ 713, 713, 713, 713, 713, 713, 713, 713, 713, 713, + /* 200 */ 713, 713, 713, 1220, 366, 366, 713, 917, 283, 283, + /* 210 */ 434, 434, 605, 605, 1298, 2142, 2142, 2142, 2142, 2142, + /* 220 */ 2142, 2142, 1179, 1157, 1157, 487, 527, 585, 645, 749, + /* 230 */ 914, 968, 752, 713, 713, 713, 713, 713, 713, 713, + /* 240 */ 713, 713, 713, 303, 713, 713, 713, 713, 713, 713, + /* 250 */ 713, 713, 713, 713, 713, 713, 797, 797, 797, 713, + /* 260 */ 713, 713, 959, 713, 713, 713, 1169, 1271, 713, 713, + /* 270 */ 1330, 713, 713, 713, 713, 713, 713, 713, 713, 629, + /* 280 */ 7, 91, 876, 876, 876, 876, 953, 91, 91, 1246, + /* 290 */ 1065, 1106, 1374, 1329, 1348, 468, 1348, 1394, 785, 1329, + /* 300 */ 1329, 785, 1329, 468, 1394, 859, 854, 1402, 1449, 1449, + /* 310 */ 1449, 1173, 1173, 1173, 1173, 1355, 1355, 1030, 1341, 405, + /* 320 */ 1230, 1795, 1795, 1711, 1711, 1829, 1829, 1711, 1717, 1719, + /* 330 */ 1850, 1833, 1860, 1860, 1860, 1860, 1711, 1868, 1740, 1719, + /* 340 */ 1719, 1740, 1850, 1833, 1740, 1833, 1740, 1711, 1868, 1745, + /* 350 */ 1843, 1711, 1868, 1887, 1711, 1868, 1711, 1868, 1887, 1801, + /* 360 */ 1801, 1801, 1855, 1900, 1900, 1887, 1801, 1797, 1801, 1855, + /* 370 */ 1801, 1801, 1761, 1912, 1830, 1830, 1887, 1711, 1862, 1862, + /* 380 */ 1875, 1875, 1810, 1815, 1940, 1711, 1807, 1810, 1821, 1823, + /* 390 */ 1740, 1945, 1963, 1963, 1974, 1974, 1974, 2142, 2142, 2142, + /* 400 */ 2142, 2142, 2142, 2142, 2142, 2142, 2142, 2142, 2142, 2142, + /* 410 */ 2142, 2142, 20, 1224, 256, 1111, 1115, 1114, 1192, 1496, + /* 420 */ 1424, 1505, 1427, 355, 1383, 1537, 1506, 1538, 1553, 1583, + /* 430 */ 1584, 1591, 1625, 541, 1445, 1562, 1450, 1572, 1515, 1428, + /* 440 */ 1532, 1592, 1629, 1520, 1630, 1639, 1510, 1544, 1662, 1675, + /* 450 */ 1551, 48, 1996, 2001, 1983, 1844, 1993, 1994, 1986, 1989, + /* 460 */ 1874, 1863, 1885, 1991, 1991, 1995, 1876, 1997, 1877, 2004, + /* 470 */ 2021, 1881, 1894, 1991, 1895, 1965, 1990, 1991, 1878, 1975, + /* 480 */ 1977, 1978, 1979, 1903, 1918, 2002, 1896, 2034, 2033, 2017, + /* 490 */ 1925, 1880, 1976, 2018, 1980, 1967, 2005, 1904, 1932, 2025, + /* 500 */ 2030, 2032, 1921, 1928, 2035, 1987, 2036, 2037, 2038, 2040, + /* 510 */ 1988, 2006, 2039, 1960, 2041, 2042, 1999, 2023, 2044, 2043, + /* 520 */ 1919, 2048, 2049, 2050, 2046, 2051, 2053, 1981, 1935, 2056, + /* 530 */ 2057, 1966, 2047, 2061, 1941, 2060, 2052, 2054, 2055, 2058, + /* 540 */ 2003, 2012, 2007, 2059, 2015, 2008, 2062, 2071, 2073, 2074, + /* 550 */ 2072, 2075, 2065, 1962, 1964, 2079, 2060, 2082, 2084, 2085, + /* 560 */ 2087, 2086, 2089, 2088, 2091, 2093, 2099, 2094, 2095, 2096, + /* 570 */ 2097, 2100, 2101, 2102, 1998, 1984, 1985, 2000, 2103, 2098, + /* 580 */ 2109, 2117, 2128, }; -#define YY_REDUCE_COUNT (408) -#define YY_REDUCE_MIN (-271) -#define YY_REDUCE_MAX (1740) +#define YY_REDUCE_COUNT (411) +#define YY_REDUCE_MIN (-275) +#define YY_REDUCE_MAX (1798) static const short yy_reduce_ofst[] = { - /* 0 */ -125, 733, 789, 241, 293, -123, -193, -191, -183, -187, - /* 10 */ 166, 238, 133, -207, -199, -267, -176, -6, 204, 489, - /* 20 */ 576, -175, 598, 686, 615, 725, 860, 778, 781, 857, - /* 30 */ 616, 887, 87, 240, -192, 408, 626, 796, 843, 854, - /* 40 */ 1003, -271, -271, -271, -271, -271, -271, -271, -271, -271, - /* 50 */ -271, -271, -271, -271, -271, -271, -271, -271, -271, -271, - /* 60 */ -271, -271, -271, -271, -271, -271, -271, -271, -271, -271, - /* 70 */ -271, -271, -271, -271, -271, -271, -271, -271, 80, 83, - /* 80 */ 313, 886, 888, 996, 1034, 1059, 1081, 1100, 1117, 1152, - /* 90 */ 1155, 1163, 1165, 1167, 1169, 1172, 1180, 1182, 1184, 1198, - /* 100 */ 1200, 1213, 1215, 1225, 1227, 1252, 1254, 1264, 1299, 1303, - /* 110 */ 1308, 1312, 1325, 1328, 1337, 1340, 1343, 1371, 1373, 1384, - /* 120 */ 1386, 1411, 1420, 1424, 1426, 1458, 1470, 1473, 1475, 1479, - /* 130 */ -271, -271, -271, -271, -271, -271, -271, -271, -271, -271, - /* 140 */ -271, 138, 459, 396, -158, 470, 302, -212, 521, 201, - /* 150 */ -195, -92, 559, 630, 632, 630, -271, 632, 901, 63, - /* 160 */ 407, -271, -271, -271, -271, 161, 161, 161, 251, 335, - /* 170 */ 847, 960, 980, 537, 588, 618, 628, 688, 688, -166, - /* 180 */ -161, 674, 790, 794, 799, 851, 852, -122, 680, -120, - /* 190 */ 995, 1038, 415, 1051, 893, 798, 962, 400, 1086, 779, - /* 200 */ 923, 924, 263, 1041, 979, 990, 1083, 1097, 1031, 1194, - /* 210 */ 362, 994, 1139, 1005, 1037, 1202, 1205, 1195, 1210, -194, - /* 220 */ 56, 185, -135, 232, 522, 560, 601, 617, 669, 683, - /* 230 */ 711, 856, 908, 941, 1048, 1101, 1147, 1257, 1262, 1265, - /* 240 */ 392, 1292, 1333, 1339, 1342, 1346, 1350, 1359, 1374, 1418, - /* 250 */ 1421, 1436, 1437, 593, 755, 770, 997, 1445, 1459, 1209, - /* 260 */ 1500, 1504, 1516, 1132, 1243, 1518, 1519, 1440, 1520, 560, - /* 270 */ 1522, 1523, 1524, 1526, 1527, 1529, 1382, 1438, 1431, 1468, - /* 280 */ 1469, 1472, 1476, 1209, 1431, 1431, 1485, 1525, 1539, 1435, - /* 290 */ 1463, 1471, 1492, 1487, 1443, 1494, 1474, 1484, 1498, 1486, - /* 300 */ 1502, 1455, 1530, 1531, 1533, 1540, 1542, 1544, 1505, 1506, - /* 310 */ 1507, 1508, 1521, 1528, 1493, 1537, 1532, 1575, 1488, 1496, - /* 320 */ 1584, 1594, 1509, 1510, 1600, 1538, 1534, 1541, 1574, 1577, - /* 330 */ 1583, 1585, 1586, 1612, 1626, 1581, 1556, 1558, 1587, 1559, - /* 340 */ 1601, 1588, 1603, 1592, 1631, 1640, 1550, 1553, 1643, 1645, - /* 350 */ 1625, 1649, 1652, 1650, 1653, 1632, 1636, 1637, 1642, 1634, - /* 360 */ 1639, 1641, 1646, 1656, 1655, 1658, 1659, 1661, 1663, 1560, - /* 370 */ 1564, 1596, 1605, 1664, 1670, 1565, 1571, 1627, 1638, 1657, - /* 380 */ 1665, 1623, 1702, 1630, 1666, 1667, 1671, 1673, 1703, 1718, - /* 390 */ 1719, 1729, 1730, 1731, 1621, 1622, 1628, 1720, 1713, 1716, - /* 400 */ 1722, 1723, 1733, 1717, 1724, 1727, 1728, 1725, 1740, + /* 0 */ -71, 194, 343, 835, -180, -177, 838, -194, -188, -185, + /* 10 */ -183, 82, 183, -65, 133, 245, 346, 407, 458, -178, + /* 20 */ 75, -275, -4, 310, 312, 489, 575, 596, 463, 686, + /* 30 */ 707, 725, 780, 1098, 856, 778, 1059, 1090, 708, 887, + /* 40 */ 86, 448, 980, 630, 680, 681, 684, 796, 801, 796, + /* 50 */ 801, -261, -261, -261, -261, -261, -261, -261, -261, -261, + /* 60 */ -261, -261, -261, -261, -261, -261, -261, -261, -261, -261, + /* 70 */ -261, -261, -261, -261, -261, -261, -261, -261, -261, -261, + /* 80 */ -261, -261, -261, -261, -261, -261, -261, -261, 391, 886, + /* 90 */ 888, 1013, 1016, 1081, 1087, 1151, 1159, 1177, 1185, 1188, + /* 100 */ 1190, 1194, 1197, 1203, 1247, 1260, 1264, 1267, 1269, 1273, + /* 110 */ 1315, 1322, 1335, 1337, 1356, 1362, 1418, 1425, 1453, 1457, + /* 120 */ 1465, 1473, 1487, 1495, 1507, 1517, 1521, 1534, 1543, 1546, + /* 130 */ 1549, 1552, 1554, 1560, 1581, 1590, 1593, 1595, 1621, 1623, + /* 140 */ -261, -261, -261, -261, -261, -261, -261, -261, -261, -261, + /* 150 */ -261, -186, -117, 260, 263, 460, 631, -74, 497, -181, + /* 160 */ -261, 939, 176, 274, 338, 676, -261, -261, -261, -261, + /* 170 */ -212, -212, -212, -184, 149, 777, 1061, 1103, 265, 419, + /* 180 */ -254, 670, 677, 677, -11, -129, 184, 488, 736, 789, + /* 190 */ 805, 844, 403, 529, 579, 668, 783, 841, 1158, 1112, + /* 200 */ 806, 861, 1095, 846, 839, 1031, -189, 1077, 1080, 1116, + /* 210 */ 1084, 1156, 1139, 1221, 46, 1099, 1037, 1118, 1171, 1214, + /* 220 */ 1210, 1258, -210, -190, -176, -115, 117, 262, 376, 490, + /* 230 */ 511, 520, 618, 639, 743, 901, 907, 958, 1014, 1055, + /* 240 */ 1108, 1193, 1244, 720, 1248, 1277, 1324, 1347, 1417, 1431, + /* 250 */ 1432, 1440, 1451, 1452, 1463, 1478, 1286, 1350, 1369, 1490, + /* 260 */ 1498, 1501, 773, 1509, 1513, 1528, 1292, 1367, 1535, 1536, + /* 270 */ 1477, 1542, 376, 1547, 1550, 1555, 1559, 1568, 1571, 1441, + /* 280 */ 1443, 1474, 1511, 1516, 1519, 1522, 773, 1474, 1474, 1503, + /* 290 */ 1567, 1594, 1484, 1527, 1556, 1570, 1557, 1524, 1573, 1545, + /* 300 */ 1548, 1576, 1561, 1587, 1540, 1575, 1606, 1611, 1622, 1624, + /* 310 */ 1626, 1582, 1597, 1598, 1599, 1601, 1603, 1563, 1608, 1605, + /* 320 */ 1604, 1564, 1566, 1655, 1660, 1578, 1579, 1665, 1586, 1607, + /* 330 */ 1610, 1642, 1641, 1645, 1646, 1647, 1679, 1688, 1644, 1618, + /* 340 */ 1619, 1648, 1628, 1659, 1649, 1663, 1650, 1700, 1702, 1612, + /* 350 */ 1615, 1706, 1708, 1689, 1709, 1712, 1713, 1715, 1691, 1698, + /* 360 */ 1699, 1701, 1693, 1704, 1707, 1705, 1714, 1703, 1718, 1710, + /* 370 */ 1720, 1721, 1632, 1634, 1664, 1666, 1729, 1751, 1635, 1636, + /* 380 */ 1692, 1694, 1716, 1722, 1684, 1763, 1685, 1723, 1724, 1727, + /* 390 */ 1730, 1768, 1783, 1784, 1793, 1794, 1796, 1683, 1686, 1690, + /* 400 */ 1782, 1779, 1780, 1781, 1785, 1788, 1774, 1775, 1786, 1787, + /* 410 */ 1789, 1798, }; static const YYACTIONTYPE yy_default[] = { - /* 0 */ 1639, 1639, 1639, 1469, 1236, 1347, 1236, 1236, 1236, 1469, - /* 10 */ 1469, 1469, 1236, 1377, 1377, 1522, 1269, 1236, 1236, 1236, - /* 20 */ 1236, 1236, 1236, 1236, 1236, 1236, 1236, 1468, 1236, 1236, - /* 30 */ 1236, 1236, 1555, 1555, 1236, 1236, 1236, 1236, 1236, 1236, - /* 40 */ 1236, 1236, 1386, 1236, 1393, 1236, 1236, 1236, 1236, 1236, - /* 50 */ 1470, 1471, 1236, 1236, 1236, 1521, 1523, 1486, 1400, 1399, - /* 60 */ 1398, 1397, 1504, 1365, 1391, 1384, 1388, 1465, 1466, 1464, - /* 70 */ 1617, 1471, 1470, 1236, 1387, 1433, 1449, 1432, 1236, 1236, - /* 80 */ 1236, 1236, 1236, 1236, 1236, 1236, 1236, 1236, 1236, 1236, - /* 90 */ 1236, 1236, 1236, 1236, 1236, 1236, 1236, 1236, 1236, 1236, - /* 100 */ 1236, 1236, 1236, 1236, 1236, 1236, 1236, 1236, 1236, 1236, - /* 110 */ 1236, 1236, 1236, 1236, 1236, 1236, 1236, 1236, 1236, 1236, - /* 120 */ 1236, 1236, 1236, 1236, 1236, 1236, 1236, 1236, 1236, 1236, - /* 130 */ 1441, 1448, 1447, 1446, 1455, 1445, 1442, 1435, 1434, 1436, - /* 140 */ 1437, 1236, 1236, 1260, 1236, 1236, 1257, 1311, 1236, 1236, - /* 150 */ 1236, 1236, 1236, 1541, 1540, 1236, 1438, 1236, 1269, 1427, - /* 160 */ 1426, 1452, 1439, 1451, 1450, 1529, 1591, 1590, 1487, 1236, - /* 170 */ 1236, 1236, 1236, 1236, 1236, 1555, 1236, 1236, 1236, 1236, - /* 180 */ 1236, 1236, 1236, 1236, 1236, 1236, 1236, 1236, 1236, 1236, - /* 190 */ 1236, 1236, 1236, 1236, 1236, 1236, 1236, 1236, 1236, 1367, - /* 200 */ 1555, 1555, 1236, 1269, 1555, 1555, 1368, 1368, 1265, 1265, - /* 210 */ 1371, 1236, 1536, 1338, 1338, 1338, 1338, 1347, 1338, 1236, - /* 220 */ 1236, 1236, 1236, 1236, 1236, 1236, 1236, 1236, 1236, 1236, - /* 230 */ 1236, 1236, 1236, 1236, 1526, 1524, 1236, 1236, 1236, 1236, - /* 240 */ 1236, 1236, 1236, 1236, 1236, 1236, 1236, 1236, 1236, 1236, - /* 250 */ 1236, 1236, 1236, 1236, 1236, 1236, 1236, 1236, 1236, 1236, - /* 260 */ 1236, 1236, 1236, 1343, 1236, 1236, 1236, 1236, 1236, 1236, - /* 270 */ 1236, 1236, 1236, 1236, 1236, 1584, 1236, 1499, 1325, 1343, - /* 280 */ 1343, 1343, 1343, 1345, 1326, 1324, 1337, 1270, 1243, 1631, - /* 290 */ 1403, 1392, 1344, 1392, 1628, 1390, 1403, 1403, 1390, 1403, - /* 300 */ 1344, 1628, 1286, 1606, 1281, 1377, 1377, 1377, 1367, 1367, - /* 310 */ 1367, 1367, 1371, 1371, 1467, 1344, 1337, 1236, 1631, 1631, - /* 320 */ 1353, 1353, 1630, 1630, 1353, 1487, 1614, 1412, 1314, 1320, - /* 330 */ 1320, 1320, 1320, 1353, 1254, 1390, 1614, 1614, 1390, 1412, - /* 340 */ 1314, 1390, 1314, 1390, 1353, 1254, 1503, 1625, 1353, 1254, - /* 350 */ 1477, 1353, 1254, 1353, 1254, 1477, 1312, 1312, 1312, 1301, - /* 360 */ 1236, 1236, 1477, 1312, 1286, 1312, 1301, 1312, 1312, 1573, - /* 370 */ 1236, 1481, 1481, 1477, 1353, 1565, 1565, 1380, 1380, 1385, - /* 380 */ 1371, 1472, 1353, 1236, 1385, 1383, 1381, 1390, 1304, 1587, - /* 390 */ 1587, 1583, 1583, 1583, 1636, 1636, 1536, 1599, 1269, 1269, - /* 400 */ 1269, 1269, 1599, 1288, 1288, 1270, 1270, 1269, 1599, 1236, - /* 410 */ 1236, 1236, 1236, 1236, 1236, 1594, 1236, 1531, 1488, 1357, - /* 420 */ 1236, 1236, 1236, 1236, 1236, 1236, 1236, 1236, 1236, 1236, - /* 430 */ 1236, 1236, 1236, 1236, 1542, 1236, 1236, 1236, 1236, 1236, - /* 440 */ 1236, 1236, 1236, 1236, 1236, 1417, 1236, 1239, 1533, 1236, - /* 450 */ 1236, 1236, 1236, 1236, 1236, 1236, 1236, 1394, 1395, 1358, - /* 460 */ 1236, 1236, 1236, 1236, 1236, 1236, 1236, 1409, 1236, 1236, - /* 470 */ 1236, 1404, 1236, 1236, 1236, 1236, 1236, 1236, 1236, 1236, - /* 480 */ 1627, 1236, 1236, 1236, 1236, 1236, 1236, 1502, 1501, 1236, - /* 490 */ 1236, 1355, 1236, 1236, 1236, 1236, 1236, 1236, 1236, 1236, - /* 500 */ 1236, 1236, 1236, 1236, 1236, 1284, 1236, 1236, 1236, 1236, - /* 510 */ 1236, 1236, 1236, 1236, 1236, 1236, 1236, 1236, 1236, 1236, - /* 520 */ 1236, 1236, 1236, 1236, 1236, 1236, 1236, 1236, 1236, 1382, - /* 530 */ 1236, 1236, 1236, 1236, 1236, 1236, 1236, 1236, 1236, 1236, - /* 540 */ 1236, 1236, 1236, 1236, 1570, 1372, 1236, 1236, 1236, 1236, - /* 550 */ 1618, 1236, 1236, 1236, 1236, 1236, 1236, 1236, 1236, 1236, - /* 560 */ 1236, 1236, 1236, 1236, 1236, 1610, 1328, 1418, 1236, 1421, - /* 570 */ 1258, 1236, 1248, 1236, 1236, + /* 0 */ 1663, 1663, 1663, 1491, 1254, 1367, 1254, 1254, 1254, 1254, + /* 10 */ 1491, 1491, 1491, 1254, 1254, 1254, 1254, 1254, 1254, 1397, + /* 20 */ 1397, 1544, 1287, 1254, 1254, 1254, 1254, 1254, 1254, 1254, + /* 30 */ 1254, 1254, 1254, 1254, 1254, 1490, 1254, 1254, 1254, 1254, + /* 40 */ 1578, 1578, 1254, 1254, 1254, 1254, 1254, 1563, 1562, 1254, + /* 50 */ 1254, 1254, 1406, 1254, 1413, 1254, 1254, 1254, 1254, 1254, + /* 60 */ 1492, 1493, 1254, 1254, 1254, 1543, 1545, 1508, 1420, 1419, + /* 70 */ 1418, 1417, 1526, 1385, 1411, 1404, 1408, 1487, 1488, 1486, + /* 80 */ 1641, 1493, 1492, 1254, 1407, 1455, 1471, 1454, 1254, 1254, + /* 90 */ 1254, 1254, 1254, 1254, 1254, 1254, 1254, 1254, 1254, 1254, + /* 100 */ 1254, 1254, 1254, 1254, 1254, 1254, 1254, 1254, 1254, 1254, + /* 110 */ 1254, 1254, 1254, 1254, 1254, 1254, 1254, 1254, 1254, 1254, + /* 120 */ 1254, 1254, 1254, 1254, 1254, 1254, 1254, 1254, 1254, 1254, + /* 130 */ 1254, 1254, 1254, 1254, 1254, 1254, 1254, 1254, 1254, 1254, + /* 140 */ 1463, 1470, 1469, 1468, 1477, 1467, 1464, 1457, 1456, 1458, + /* 150 */ 1459, 1278, 1254, 1275, 1329, 1254, 1254, 1254, 1254, 1254, + /* 160 */ 1460, 1287, 1448, 1447, 1446, 1254, 1474, 1461, 1473, 1472, + /* 170 */ 1551, 1615, 1614, 1509, 1254, 1254, 1254, 1254, 1254, 1254, + /* 180 */ 1578, 1254, 1254, 1254, 1254, 1254, 1254, 1254, 1254, 1254, + /* 190 */ 1254, 1254, 1254, 1254, 1254, 1254, 1254, 1254, 1254, 1254, + /* 200 */ 1254, 1254, 1254, 1387, 1578, 1578, 1254, 1287, 1578, 1578, + /* 210 */ 1388, 1388, 1283, 1283, 1391, 1558, 1358, 1358, 1358, 1358, + /* 220 */ 1367, 1358, 1254, 1254, 1254, 1254, 1254, 1254, 1254, 1254, + /* 230 */ 1254, 1254, 1254, 1254, 1254, 1254, 1254, 1548, 1546, 1254, + /* 240 */ 1254, 1254, 1254, 1254, 1254, 1254, 1254, 1254, 1254, 1254, + /* 250 */ 1254, 1254, 1254, 1254, 1254, 1254, 1254, 1254, 1254, 1254, + /* 260 */ 1254, 1254, 1254, 1254, 1254, 1254, 1363, 1254, 1254, 1254, + /* 270 */ 1254, 1254, 1254, 1254, 1254, 1254, 1254, 1254, 1608, 1254, + /* 280 */ 1521, 1343, 1363, 1363, 1363, 1363, 1365, 1344, 1342, 1357, + /* 290 */ 1288, 1261, 1655, 1423, 1412, 1364, 1412, 1652, 1410, 1423, + /* 300 */ 1423, 1410, 1423, 1364, 1652, 1304, 1630, 1299, 1397, 1397, + /* 310 */ 1397, 1387, 1387, 1387, 1387, 1391, 1391, 1489, 1364, 1357, + /* 320 */ 1254, 1655, 1655, 1373, 1373, 1654, 1654, 1373, 1509, 1638, + /* 330 */ 1432, 1332, 1338, 1338, 1338, 1338, 1373, 1272, 1410, 1638, + /* 340 */ 1638, 1410, 1432, 1332, 1410, 1332, 1410, 1373, 1272, 1525, + /* 350 */ 1649, 1373, 1272, 1499, 1373, 1272, 1373, 1272, 1499, 1330, + /* 360 */ 1330, 1330, 1319, 1254, 1254, 1499, 1330, 1304, 1330, 1319, + /* 370 */ 1330, 1330, 1596, 1254, 1503, 1503, 1499, 1373, 1588, 1588, + /* 380 */ 1400, 1400, 1405, 1391, 1494, 1373, 1254, 1405, 1403, 1401, + /* 390 */ 1410, 1322, 1611, 1611, 1607, 1607, 1607, 1660, 1660, 1558, + /* 400 */ 1623, 1287, 1287, 1287, 1287, 1623, 1306, 1306, 1288, 1288, + /* 410 */ 1287, 1623, 1254, 1254, 1254, 1254, 1254, 1254, 1618, 1254, + /* 420 */ 1553, 1510, 1377, 1254, 1254, 1254, 1254, 1254, 1254, 1254, + /* 430 */ 1254, 1254, 1254, 1254, 1254, 1254, 1254, 1254, 1254, 1564, + /* 440 */ 1254, 1254, 1254, 1254, 1254, 1254, 1254, 1254, 1254, 1254, + /* 450 */ 1254, 1437, 1254, 1257, 1555, 1254, 1254, 1254, 1254, 1254, + /* 460 */ 1254, 1254, 1254, 1414, 1415, 1378, 1254, 1254, 1254, 1254, + /* 470 */ 1254, 1254, 1254, 1429, 1254, 1254, 1254, 1424, 1254, 1254, + /* 480 */ 1254, 1254, 1254, 1254, 1254, 1254, 1651, 1254, 1254, 1254, + /* 490 */ 1254, 1254, 1254, 1524, 1523, 1254, 1254, 1375, 1254, 1254, + /* 500 */ 1254, 1254, 1254, 1254, 1254, 1254, 1254, 1254, 1254, 1254, + /* 510 */ 1254, 1302, 1254, 1254, 1254, 1254, 1254, 1254, 1254, 1254, + /* 520 */ 1254, 1254, 1254, 1254, 1254, 1254, 1254, 1254, 1254, 1254, + /* 530 */ 1254, 1254, 1254, 1254, 1254, 1402, 1254, 1254, 1254, 1254, + /* 540 */ 1254, 1254, 1254, 1254, 1254, 1254, 1254, 1254, 1254, 1254, + /* 550 */ 1593, 1392, 1254, 1254, 1254, 1254, 1642, 1254, 1254, 1254, + /* 560 */ 1254, 1352, 1254, 1254, 1254, 1254, 1254, 1254, 1254, 1254, + /* 570 */ 1254, 1254, 1254, 1634, 1346, 1438, 1254, 1441, 1276, 1254, + /* 580 */ 1266, 1254, 1254, }; /********** End of lemon-generated parsing tables *****************************/ @@ -170615,8 +173902,8 @@ static const YYCODETYPE yyFallback[] = { 0, /* TRUEFALSE => nothing */ 0, /* ISNOT => nothing */ 0, /* FUNCTION => nothing */ - 0, /* UMINUS => nothing */ 0, /* UPLUS => nothing */ + 0, /* UMINUS => nothing */ 0, /* TRUTH => nothing */ 0, /* REGISTER => nothing */ 0, /* VECTOR => nothing */ @@ -170625,6 +173912,7 @@ static const YYCODETYPE yyFallback[] = { 0, /* ASTERISK => nothing */ 0, /* SPAN => nothing */ 0, /* ERROR => nothing */ + 0, /* QNUMBER => nothing */ 0, /* SPACE => nothing */ 0, /* ILLEGAL => nothing */ }; @@ -170667,14 +173955,9 @@ struct yyParser { #endif sqlite3ParserARG_SDECL /* A place to hold %extra_argument */ sqlite3ParserCTX_SDECL /* A place to hold %extra_context */ -#if YYSTACKDEPTH<=0 - int yystksz; /* Current side of the stack */ - yyStackEntry *yystack; /* The parser's stack */ - yyStackEntry yystk0; /* First stack entry */ -#else - yyStackEntry yystack[YYSTACKDEPTH]; /* The parser's stack */ - yyStackEntry *yystackEnd; /* Last entry in the stack */ -#endif + yyStackEntry *yystackEnd; /* Last entry in the stack */ + yyStackEntry *yystack; /* The parser stack */ + yyStackEntry yystk0[YYSTACKDEPTH]; /* Initial stack space */ }; typedef struct yyParser yyParser; @@ -170888,8 +174171,8 @@ static const char *const yyTokenName[] = { /* 170 */ "TRUEFALSE", /* 171 */ "ISNOT", /* 172 */ "FUNCTION", - /* 173 */ "UMINUS", - /* 174 */ "UPLUS", + /* 173 */ "UPLUS", + /* 174 */ "UMINUS", /* 175 */ "TRUTH", /* 176 */ "REGISTER", /* 177 */ "VECTOR", @@ -170898,142 +174181,145 @@ static const char *const yyTokenName[] = { /* 180 */ "ASTERISK", /* 181 */ "SPAN", /* 182 */ "ERROR", - /* 183 */ "SPACE", - /* 184 */ "ILLEGAL", - /* 185 */ "input", - /* 186 */ "cmdlist", - /* 187 */ "ecmd", - /* 188 */ "cmdx", - /* 189 */ "explain", - /* 190 */ "cmd", - /* 191 */ "transtype", - /* 192 */ "trans_opt", - /* 193 */ "nm", - /* 194 */ "savepoint_opt", - /* 195 */ "create_table", - /* 196 */ "create_table_args", - /* 197 */ "createkw", - /* 198 */ "temp", - /* 199 */ "ifnotexists", - /* 200 */ "dbnm", - /* 201 */ "columnlist", - /* 202 */ "conslist_opt", - /* 203 */ "table_option_set", - /* 204 */ "select", - /* 205 */ "table_option", - /* 206 */ "columnname", - /* 207 */ "carglist", - /* 208 */ "typetoken", - /* 209 */ "typename", - /* 210 */ "signed", - /* 211 */ "plus_num", - /* 212 */ "minus_num", - /* 213 */ "scanpt", - /* 214 */ "scantok", - /* 215 */ "ccons", - /* 216 */ "term", - /* 217 */ "expr", - /* 218 */ "onconf", - /* 219 */ "sortorder", - /* 220 */ "autoinc", - /* 221 */ "eidlist_opt", - /* 222 */ "refargs", - /* 223 */ "defer_subclause", - /* 224 */ "generated", - /* 225 */ "refarg", - /* 226 */ "refact", - /* 227 */ "init_deferred_pred_opt", - /* 228 */ "conslist", - /* 229 */ "tconscomma", - /* 230 */ "tcons", - /* 231 */ "sortlist", - /* 232 */ "eidlist", - /* 233 */ "defer_subclause_opt", - /* 234 */ "orconf", - /* 235 */ "resolvetype", - /* 236 */ "raisetype", - /* 237 */ "ifexists", - /* 238 */ "fullname", - /* 239 */ "selectnowith", - /* 240 */ "oneselect", - /* 241 */ "wqlist", - /* 242 */ "multiselect_op", - /* 243 */ "distinct", - /* 244 */ "selcollist", - /* 245 */ "from", - /* 246 */ "where_opt", - /* 247 */ "groupby_opt", - /* 248 */ "having_opt", - /* 249 */ "orderby_opt", - /* 250 */ "limit_opt", - /* 251 */ "window_clause", - /* 252 */ "values", - /* 253 */ "nexprlist", - /* 254 */ "sclp", - /* 255 */ "as", - /* 256 */ "seltablist", - /* 257 */ "stl_prefix", - /* 258 */ "joinop", - /* 259 */ "on_using", - /* 260 */ "indexed_by", - /* 261 */ "exprlist", - /* 262 */ "xfullname", - /* 263 */ "idlist", - /* 264 */ "indexed_opt", - /* 265 */ "nulls", - /* 266 */ "with", - /* 267 */ "where_opt_ret", - /* 268 */ "setlist", - /* 269 */ "insert_cmd", - /* 270 */ "idlist_opt", - /* 271 */ "upsert", - /* 272 */ "returning", - /* 273 */ "filter_over", - /* 274 */ "likeop", - /* 275 */ "between_op", - /* 276 */ "in_op", - /* 277 */ "paren_exprlist", - /* 278 */ "case_operand", - /* 279 */ "case_exprlist", - /* 280 */ "case_else", - /* 281 */ "uniqueflag", - /* 282 */ "collate", - /* 283 */ "vinto", - /* 284 */ "nmnum", - /* 285 */ "trigger_decl", - /* 286 */ "trigger_cmd_list", - /* 287 */ "trigger_time", - /* 288 */ "trigger_event", - /* 289 */ "foreach_clause", - /* 290 */ "when_clause", - /* 291 */ "trigger_cmd", - /* 292 */ "trnm", - /* 293 */ "tridxby", - /* 294 */ "database_kw_opt", - /* 295 */ "key_opt", - /* 296 */ "add_column_fullname", - /* 297 */ "kwcolumn_opt", - /* 298 */ "create_vtab", - /* 299 */ "vtabarglist", - /* 300 */ "vtabarg", - /* 301 */ "vtabargtoken", - /* 302 */ "lp", - /* 303 */ "anylist", - /* 304 */ "wqitem", - /* 305 */ "wqas", - /* 306 */ "windowdefn_list", - /* 307 */ "windowdefn", - /* 308 */ "window", - /* 309 */ "frame_opt", - /* 310 */ "part_opt", - /* 311 */ "filter_clause", - /* 312 */ "over_clause", - /* 313 */ "range_or_rows", - /* 314 */ "frame_bound", - /* 315 */ "frame_bound_s", - /* 316 */ "frame_bound_e", - /* 317 */ "frame_exclude_opt", - /* 318 */ "frame_exclude", + /* 183 */ "QNUMBER", + /* 184 */ "SPACE", + /* 185 */ "ILLEGAL", + /* 186 */ "input", + /* 187 */ "cmdlist", + /* 188 */ "ecmd", + /* 189 */ "cmdx", + /* 190 */ "explain", + /* 191 */ "cmd", + /* 192 */ "transtype", + /* 193 */ "trans_opt", + /* 194 */ "nm", + /* 195 */ "savepoint_opt", + /* 196 */ "create_table", + /* 197 */ "create_table_args", + /* 198 */ "createkw", + /* 199 */ "temp", + /* 200 */ "ifnotexists", + /* 201 */ "dbnm", + /* 202 */ "columnlist", + /* 203 */ "conslist_opt", + /* 204 */ "table_option_set", + /* 205 */ "select", + /* 206 */ "table_option", + /* 207 */ "columnname", + /* 208 */ "carglist", + /* 209 */ "typetoken", + /* 210 */ "typename", + /* 211 */ "signed", + /* 212 */ "plus_num", + /* 213 */ "minus_num", + /* 214 */ "scanpt", + /* 215 */ "scantok", + /* 216 */ "ccons", + /* 217 */ "term", + /* 218 */ "expr", + /* 219 */ "onconf", + /* 220 */ "sortorder", + /* 221 */ "autoinc", + /* 222 */ "eidlist_opt", + /* 223 */ "refargs", + /* 224 */ "defer_subclause", + /* 225 */ "generated", + /* 226 */ "refarg", + /* 227 */ "refact", + /* 228 */ "init_deferred_pred_opt", + /* 229 */ "conslist", + /* 230 */ "tconscomma", + /* 231 */ "tcons", + /* 232 */ "sortlist", + /* 233 */ "eidlist", + /* 234 */ "defer_subclause_opt", + /* 235 */ "orconf", + /* 236 */ "resolvetype", + /* 237 */ "raisetype", + /* 238 */ "ifexists", + /* 239 */ "fullname", + /* 240 */ "selectnowith", + /* 241 */ "oneselect", + /* 242 */ "wqlist", + /* 243 */ "multiselect_op", + /* 244 */ "distinct", + /* 245 */ "selcollist", + /* 246 */ "from", + /* 247 */ "where_opt", + /* 248 */ "groupby_opt", + /* 249 */ "having_opt", + /* 250 */ "orderby_opt", + /* 251 */ "limit_opt", + /* 252 */ "window_clause", + /* 253 */ "values", + /* 254 */ "nexprlist", + /* 255 */ "mvalues", + /* 256 */ "sclp", + /* 257 */ "as", + /* 258 */ "seltablist", + /* 259 */ "stl_prefix", + /* 260 */ "joinop", + /* 261 */ "on_using", + /* 262 */ "indexed_by", + /* 263 */ "exprlist", + /* 264 */ "xfullname", + /* 265 */ "idlist", + /* 266 */ "indexed_opt", + /* 267 */ "nulls", + /* 268 */ "with", + /* 269 */ "where_opt_ret", + /* 270 */ "setlist", + /* 271 */ "insert_cmd", + /* 272 */ "idlist_opt", + /* 273 */ "upsert", + /* 274 */ "returning", + /* 275 */ "filter_over", + /* 276 */ "likeop", + /* 277 */ "between_op", + /* 278 */ "in_op", + /* 279 */ "paren_exprlist", + /* 280 */ "case_operand", + /* 281 */ "case_exprlist", + /* 282 */ "case_else", + /* 283 */ "uniqueflag", + /* 284 */ "collate", + /* 285 */ "vinto", + /* 286 */ "nmnum", + /* 287 */ "trigger_decl", + /* 288 */ "trigger_cmd_list", + /* 289 */ "trigger_time", + /* 290 */ "trigger_event", + /* 291 */ "foreach_clause", + /* 292 */ "when_clause", + /* 293 */ "trigger_cmd", + /* 294 */ "trnm", + /* 295 */ "tridxby", + /* 296 */ "database_kw_opt", + /* 297 */ "key_opt", + /* 298 */ "add_column_fullname", + /* 299 */ "kwcolumn_opt", + /* 300 */ "create_vtab", + /* 301 */ "vtabarglist", + /* 302 */ "vtabarg", + /* 303 */ "vtabargtoken", + /* 304 */ "lp", + /* 305 */ "anylist", + /* 306 */ "wqitem", + /* 307 */ "wqas", + /* 308 */ "withnm", + /* 309 */ "windowdefn_list", + /* 310 */ "windowdefn", + /* 311 */ "window", + /* 312 */ "frame_opt", + /* 313 */ "part_opt", + /* 314 */ "filter_clause", + /* 315 */ "over_clause", + /* 316 */ "range_or_rows", + /* 317 */ "frame_bound", + /* 318 */ "frame_bound_s", + /* 319 */ "frame_bound_e", + /* 320 */ "frame_exclude_opt", + /* 321 */ "frame_exclude", }; #endif /* defined(YYCOVERAGE) || !defined(NDEBUG) */ @@ -171136,349 +174422,363 @@ static const char *const yyRuleName[] = { /* 92 */ "oneselect ::= SELECT distinct selcollist from where_opt groupby_opt having_opt orderby_opt limit_opt", /* 93 */ "oneselect ::= SELECT distinct selcollist from where_opt groupby_opt having_opt window_clause orderby_opt limit_opt", /* 94 */ "values ::= VALUES LP nexprlist RP", - /* 95 */ "values ::= values COMMA LP nexprlist RP", - /* 96 */ "distinct ::= DISTINCT", - /* 97 */ "distinct ::= ALL", - /* 98 */ "distinct ::=", - /* 99 */ "sclp ::=", - /* 100 */ "selcollist ::= sclp scanpt expr scanpt as", - /* 101 */ "selcollist ::= sclp scanpt STAR", - /* 102 */ "selcollist ::= sclp scanpt nm DOT STAR", - /* 103 */ "as ::= AS nm", - /* 104 */ "as ::=", - /* 105 */ "from ::=", - /* 106 */ "from ::= FROM seltablist", - /* 107 */ "stl_prefix ::= seltablist joinop", - /* 108 */ "stl_prefix ::=", - /* 109 */ "seltablist ::= stl_prefix nm dbnm as on_using", - /* 110 */ "seltablist ::= stl_prefix nm dbnm as indexed_by on_using", - /* 111 */ "seltablist ::= stl_prefix nm dbnm LP exprlist RP as on_using", - /* 112 */ "seltablist ::= stl_prefix LP select RP as on_using", - /* 113 */ "seltablist ::= stl_prefix LP seltablist RP as on_using", - /* 114 */ "dbnm ::=", - /* 115 */ "dbnm ::= DOT nm", - /* 116 */ "fullname ::= nm", - /* 117 */ "fullname ::= nm DOT nm", - /* 118 */ "xfullname ::= nm", - /* 119 */ "xfullname ::= nm DOT nm", - /* 120 */ "xfullname ::= nm DOT nm AS nm", - /* 121 */ "xfullname ::= nm AS nm", - /* 122 */ "joinop ::= COMMA|JOIN", - /* 123 */ "joinop ::= JOIN_KW JOIN", - /* 124 */ "joinop ::= JOIN_KW nm JOIN", - /* 125 */ "joinop ::= JOIN_KW nm nm JOIN", - /* 126 */ "on_using ::= ON expr", - /* 127 */ "on_using ::= USING LP idlist RP", - /* 128 */ "on_using ::=", - /* 129 */ "indexed_opt ::=", - /* 130 */ "indexed_by ::= INDEXED BY nm", - /* 131 */ "indexed_by ::= NOT INDEXED", - /* 132 */ "orderby_opt ::=", - /* 133 */ "orderby_opt ::= ORDER BY sortlist", - /* 134 */ "sortlist ::= sortlist COMMA expr sortorder nulls", - /* 135 */ "sortlist ::= expr sortorder nulls", - /* 136 */ "sortorder ::= ASC", - /* 137 */ "sortorder ::= DESC", - /* 138 */ "sortorder ::=", - /* 139 */ "nulls ::= NULLS FIRST", - /* 140 */ "nulls ::= NULLS LAST", - /* 141 */ "nulls ::=", - /* 142 */ "groupby_opt ::=", - /* 143 */ "groupby_opt ::= GROUP BY nexprlist", - /* 144 */ "having_opt ::=", - /* 145 */ "having_opt ::= HAVING expr", - /* 146 */ "limit_opt ::=", - /* 147 */ "limit_opt ::= LIMIT expr", - /* 148 */ "limit_opt ::= LIMIT expr OFFSET expr", - /* 149 */ "limit_opt ::= LIMIT expr COMMA expr", - /* 150 */ "cmd ::= with DELETE FROM xfullname indexed_opt where_opt_ret", - /* 151 */ "where_opt ::=", - /* 152 */ "where_opt ::= WHERE expr", - /* 153 */ "where_opt_ret ::=", - /* 154 */ "where_opt_ret ::= WHERE expr", - /* 155 */ "where_opt_ret ::= RETURNING selcollist", - /* 156 */ "where_opt_ret ::= WHERE expr RETURNING selcollist", - /* 157 */ "cmd ::= with UPDATE orconf xfullname indexed_opt SET setlist from where_opt_ret", - /* 158 */ "setlist ::= setlist COMMA nm EQ expr", - /* 159 */ "setlist ::= setlist COMMA LP idlist RP EQ expr", - /* 160 */ "setlist ::= nm EQ expr", - /* 161 */ "setlist ::= LP idlist RP EQ expr", - /* 162 */ "cmd ::= with insert_cmd INTO xfullname idlist_opt select upsert", - /* 163 */ "cmd ::= with insert_cmd INTO xfullname idlist_opt DEFAULT VALUES returning", - /* 164 */ "upsert ::=", - /* 165 */ "upsert ::= RETURNING selcollist", - /* 166 */ "upsert ::= ON CONFLICT LP sortlist RP where_opt DO UPDATE SET setlist where_opt upsert", - /* 167 */ "upsert ::= ON CONFLICT LP sortlist RP where_opt DO NOTHING upsert", - /* 168 */ "upsert ::= ON CONFLICT DO NOTHING returning", - /* 169 */ "upsert ::= ON CONFLICT DO UPDATE SET setlist where_opt returning", - /* 170 */ "returning ::= RETURNING selcollist", - /* 171 */ "insert_cmd ::= INSERT orconf", - /* 172 */ "insert_cmd ::= REPLACE", - /* 173 */ "idlist_opt ::=", - /* 174 */ "idlist_opt ::= LP idlist RP", - /* 175 */ "idlist ::= idlist COMMA nm", - /* 176 */ "idlist ::= nm", - /* 177 */ "expr ::= LP expr RP", - /* 178 */ "expr ::= ID|INDEXED|JOIN_KW", - /* 179 */ "expr ::= nm DOT nm", - /* 180 */ "expr ::= nm DOT nm DOT nm", - /* 181 */ "term ::= NULL|FLOAT|BLOB", - /* 182 */ "term ::= STRING", - /* 183 */ "term ::= INTEGER", - /* 184 */ "expr ::= VARIABLE", - /* 185 */ "expr ::= expr COLLATE ID|STRING", - /* 186 */ "expr ::= CAST LP expr AS typetoken RP", - /* 187 */ "expr ::= ID|INDEXED|JOIN_KW LP distinct exprlist RP", - /* 188 */ "expr ::= ID|INDEXED|JOIN_KW LP STAR RP", - /* 189 */ "expr ::= ID|INDEXED|JOIN_KW LP distinct exprlist RP filter_over", - /* 190 */ "expr ::= ID|INDEXED|JOIN_KW LP STAR RP filter_over", - /* 191 */ "term ::= CTIME_KW", - /* 192 */ "expr ::= LP nexprlist COMMA expr RP", - /* 193 */ "expr ::= expr AND expr", - /* 194 */ "expr ::= expr OR expr", - /* 195 */ "expr ::= expr LT|GT|GE|LE expr", - /* 196 */ "expr ::= expr EQ|NE expr", - /* 197 */ "expr ::= expr BITAND|BITOR|LSHIFT|RSHIFT expr", - /* 198 */ "expr ::= expr PLUS|MINUS expr", - /* 199 */ "expr ::= expr STAR|SLASH|REM expr", - /* 200 */ "expr ::= expr CONCAT expr", - /* 201 */ "likeop ::= NOT LIKE_KW|MATCH", - /* 202 */ "expr ::= expr likeop expr", - /* 203 */ "expr ::= expr likeop expr ESCAPE expr", - /* 204 */ "expr ::= expr ISNULL|NOTNULL", - /* 205 */ "expr ::= expr NOT NULL", - /* 206 */ "expr ::= expr IS expr", - /* 207 */ "expr ::= expr IS NOT expr", - /* 208 */ "expr ::= expr IS NOT DISTINCT FROM expr", - /* 209 */ "expr ::= expr IS DISTINCT FROM expr", - /* 210 */ "expr ::= NOT expr", - /* 211 */ "expr ::= BITNOT expr", - /* 212 */ "expr ::= PLUS|MINUS expr", - /* 213 */ "expr ::= expr PTR expr", - /* 214 */ "between_op ::= BETWEEN", - /* 215 */ "between_op ::= NOT BETWEEN", - /* 216 */ "expr ::= expr between_op expr AND expr", - /* 217 */ "in_op ::= IN", - /* 218 */ "in_op ::= NOT IN", - /* 219 */ "expr ::= expr in_op LP exprlist RP", - /* 220 */ "expr ::= LP select RP", - /* 221 */ "expr ::= expr in_op LP select RP", - /* 222 */ "expr ::= expr in_op nm dbnm paren_exprlist", - /* 223 */ "expr ::= EXISTS LP select RP", - /* 224 */ "expr ::= CASE case_operand case_exprlist case_else END", - /* 225 */ "case_exprlist ::= case_exprlist WHEN expr THEN expr", - /* 226 */ "case_exprlist ::= WHEN expr THEN expr", - /* 227 */ "case_else ::= ELSE expr", - /* 228 */ "case_else ::=", - /* 229 */ "case_operand ::=", - /* 230 */ "exprlist ::=", - /* 231 */ "nexprlist ::= nexprlist COMMA expr", - /* 232 */ "nexprlist ::= expr", - /* 233 */ "paren_exprlist ::=", - /* 234 */ "paren_exprlist ::= LP exprlist RP", - /* 235 */ "cmd ::= createkw uniqueflag INDEX ifnotexists nm dbnm ON nm LP sortlist RP where_opt", - /* 236 */ "uniqueflag ::= UNIQUE", - /* 237 */ "uniqueflag ::=", - /* 238 */ "eidlist_opt ::=", - /* 239 */ "eidlist_opt ::= LP eidlist RP", - /* 240 */ "eidlist ::= eidlist COMMA nm collate sortorder", - /* 241 */ "eidlist ::= nm collate sortorder", - /* 242 */ "collate ::=", - /* 243 */ "collate ::= COLLATE ID|STRING", - /* 244 */ "cmd ::= DROP INDEX ifexists fullname", - /* 245 */ "cmd ::= VACUUM vinto", - /* 246 */ "cmd ::= VACUUM nm vinto", - /* 247 */ "vinto ::= INTO expr", - /* 248 */ "vinto ::=", - /* 249 */ "cmd ::= PRAGMA nm dbnm", - /* 250 */ "cmd ::= PRAGMA nm dbnm EQ nmnum", - /* 251 */ "cmd ::= PRAGMA nm dbnm LP nmnum RP", - /* 252 */ "cmd ::= PRAGMA nm dbnm EQ minus_num", - /* 253 */ "cmd ::= PRAGMA nm dbnm LP minus_num RP", - /* 254 */ "plus_num ::= PLUS INTEGER|FLOAT", - /* 255 */ "minus_num ::= MINUS INTEGER|FLOAT", - /* 256 */ "cmd ::= createkw trigger_decl BEGIN trigger_cmd_list END", - /* 257 */ "trigger_decl ::= temp TRIGGER ifnotexists nm dbnm trigger_time trigger_event ON fullname foreach_clause when_clause", - /* 258 */ "trigger_time ::= BEFORE|AFTER", - /* 259 */ "trigger_time ::= INSTEAD OF", - /* 260 */ "trigger_time ::=", - /* 261 */ "trigger_event ::= DELETE|INSERT", - /* 262 */ "trigger_event ::= UPDATE", - /* 263 */ "trigger_event ::= UPDATE OF idlist", - /* 264 */ "when_clause ::=", - /* 265 */ "when_clause ::= WHEN expr", - /* 266 */ "trigger_cmd_list ::= trigger_cmd_list trigger_cmd SEMI", - /* 267 */ "trigger_cmd_list ::= trigger_cmd SEMI", - /* 268 */ "trnm ::= nm DOT nm", - /* 269 */ "tridxby ::= INDEXED BY nm", - /* 270 */ "tridxby ::= NOT INDEXED", - /* 271 */ "trigger_cmd ::= UPDATE orconf trnm tridxby SET setlist from where_opt scanpt", - /* 272 */ "trigger_cmd ::= scanpt insert_cmd INTO trnm idlist_opt select upsert scanpt", - /* 273 */ "trigger_cmd ::= DELETE FROM trnm tridxby where_opt scanpt", - /* 274 */ "trigger_cmd ::= scanpt select scanpt", - /* 275 */ "expr ::= RAISE LP IGNORE RP", - /* 276 */ "expr ::= RAISE LP raisetype COMMA nm RP", - /* 277 */ "raisetype ::= ROLLBACK", - /* 278 */ "raisetype ::= ABORT", - /* 279 */ "raisetype ::= FAIL", - /* 280 */ "cmd ::= DROP TRIGGER ifexists fullname", - /* 281 */ "cmd ::= ATTACH database_kw_opt expr AS expr key_opt", - /* 282 */ "cmd ::= DETACH database_kw_opt expr", - /* 283 */ "key_opt ::=", - /* 284 */ "key_opt ::= KEY expr", - /* 285 */ "cmd ::= REINDEX", - /* 286 */ "cmd ::= REINDEX nm dbnm", - /* 287 */ "cmd ::= ANALYZE", - /* 288 */ "cmd ::= ANALYZE nm dbnm", - /* 289 */ "cmd ::= ALTER TABLE fullname RENAME TO nm", - /* 290 */ "cmd ::= ALTER TABLE add_column_fullname ADD kwcolumn_opt columnname carglist", - /* 291 */ "cmd ::= ALTER TABLE fullname DROP kwcolumn_opt nm", - /* 292 */ "add_column_fullname ::= fullname", - /* 293 */ "cmd ::= ALTER TABLE fullname RENAME kwcolumn_opt nm TO nm", - /* 294 */ "cmd ::= create_vtab", - /* 295 */ "cmd ::= create_vtab LP vtabarglist RP", - /* 296 */ "create_vtab ::= createkw VIRTUAL TABLE ifnotexists nm dbnm USING nm", - /* 297 */ "vtabarg ::=", - /* 298 */ "vtabargtoken ::= ANY", - /* 299 */ "vtabargtoken ::= lp anylist RP", - /* 300 */ "lp ::= LP", - /* 301 */ "with ::= WITH wqlist", - /* 302 */ "with ::= WITH RECURSIVE wqlist", - /* 303 */ "wqas ::= AS", - /* 304 */ "wqas ::= AS MATERIALIZED", - /* 305 */ "wqas ::= AS NOT MATERIALIZED", - /* 306 */ "wqitem ::= nm eidlist_opt wqas LP select RP", - /* 307 */ "wqlist ::= wqitem", - /* 308 */ "wqlist ::= wqlist COMMA wqitem", - /* 309 */ "windowdefn_list ::= windowdefn_list COMMA windowdefn", - /* 310 */ "windowdefn ::= nm AS LP window RP", - /* 311 */ "window ::= PARTITION BY nexprlist orderby_opt frame_opt", - /* 312 */ "window ::= nm PARTITION BY nexprlist orderby_opt frame_opt", - /* 313 */ "window ::= ORDER BY sortlist frame_opt", - /* 314 */ "window ::= nm ORDER BY sortlist frame_opt", - /* 315 */ "window ::= nm frame_opt", - /* 316 */ "frame_opt ::=", - /* 317 */ "frame_opt ::= range_or_rows frame_bound_s frame_exclude_opt", - /* 318 */ "frame_opt ::= range_or_rows BETWEEN frame_bound_s AND frame_bound_e frame_exclude_opt", - /* 319 */ "range_or_rows ::= RANGE|ROWS|GROUPS", - /* 320 */ "frame_bound_s ::= frame_bound", - /* 321 */ "frame_bound_s ::= UNBOUNDED PRECEDING", - /* 322 */ "frame_bound_e ::= frame_bound", - /* 323 */ "frame_bound_e ::= UNBOUNDED FOLLOWING", - /* 324 */ "frame_bound ::= expr PRECEDING|FOLLOWING", - /* 325 */ "frame_bound ::= CURRENT ROW", - /* 326 */ "frame_exclude_opt ::=", - /* 327 */ "frame_exclude_opt ::= EXCLUDE frame_exclude", - /* 328 */ "frame_exclude ::= NO OTHERS", - /* 329 */ "frame_exclude ::= CURRENT ROW", - /* 330 */ "frame_exclude ::= GROUP|TIES", - /* 331 */ "window_clause ::= WINDOW windowdefn_list", - /* 332 */ "filter_over ::= filter_clause over_clause", - /* 333 */ "filter_over ::= over_clause", - /* 334 */ "filter_over ::= filter_clause", - /* 335 */ "over_clause ::= OVER LP window RP", - /* 336 */ "over_clause ::= OVER nm", - /* 337 */ "filter_clause ::= FILTER LP WHERE expr RP", - /* 338 */ "input ::= cmdlist", - /* 339 */ "cmdlist ::= cmdlist ecmd", - /* 340 */ "cmdlist ::= ecmd", - /* 341 */ "ecmd ::= SEMI", - /* 342 */ "ecmd ::= cmdx SEMI", - /* 343 */ "ecmd ::= explain cmdx SEMI", - /* 344 */ "trans_opt ::=", - /* 345 */ "trans_opt ::= TRANSACTION", - /* 346 */ "trans_opt ::= TRANSACTION nm", - /* 347 */ "savepoint_opt ::= SAVEPOINT", - /* 348 */ "savepoint_opt ::=", - /* 349 */ "cmd ::= create_table create_table_args", - /* 350 */ "table_option_set ::= table_option", - /* 351 */ "columnlist ::= columnlist COMMA columnname carglist", - /* 352 */ "columnlist ::= columnname carglist", - /* 353 */ "nm ::= ID|INDEXED|JOIN_KW", - /* 354 */ "nm ::= STRING", - /* 355 */ "typetoken ::= typename", - /* 356 */ "typename ::= ID|STRING", - /* 357 */ "signed ::= plus_num", - /* 358 */ "signed ::= minus_num", - /* 359 */ "carglist ::= carglist ccons", - /* 360 */ "carglist ::=", - /* 361 */ "ccons ::= NULL onconf", - /* 362 */ "ccons ::= GENERATED ALWAYS AS generated", - /* 363 */ "ccons ::= AS generated", - /* 364 */ "conslist_opt ::= COMMA conslist", - /* 365 */ "conslist ::= conslist tconscomma tcons", - /* 366 */ "conslist ::= tcons", - /* 367 */ "tconscomma ::=", - /* 368 */ "defer_subclause_opt ::= defer_subclause", - /* 369 */ "resolvetype ::= raisetype", - /* 370 */ "selectnowith ::= oneselect", - /* 371 */ "oneselect ::= values", - /* 372 */ "sclp ::= selcollist COMMA", - /* 373 */ "as ::= ID|STRING", - /* 374 */ "indexed_opt ::= indexed_by", - /* 375 */ "returning ::=", - /* 376 */ "expr ::= term", - /* 377 */ "likeop ::= LIKE_KW|MATCH", - /* 378 */ "case_operand ::= expr", - /* 379 */ "exprlist ::= nexprlist", - /* 380 */ "nmnum ::= plus_num", - /* 381 */ "nmnum ::= nm", - /* 382 */ "nmnum ::= ON", - /* 383 */ "nmnum ::= DELETE", - /* 384 */ "nmnum ::= DEFAULT", - /* 385 */ "plus_num ::= INTEGER|FLOAT", - /* 386 */ "foreach_clause ::=", - /* 387 */ "foreach_clause ::= FOR EACH ROW", - /* 388 */ "trnm ::= nm", - /* 389 */ "tridxby ::=", - /* 390 */ "database_kw_opt ::= DATABASE", - /* 391 */ "database_kw_opt ::=", - /* 392 */ "kwcolumn_opt ::=", - /* 393 */ "kwcolumn_opt ::= COLUMNKW", - /* 394 */ "vtabarglist ::= vtabarg", - /* 395 */ "vtabarglist ::= vtabarglist COMMA vtabarg", - /* 396 */ "vtabarg ::= vtabarg vtabargtoken", - /* 397 */ "anylist ::=", - /* 398 */ "anylist ::= anylist LP anylist RP", - /* 399 */ "anylist ::= anylist ANY", - /* 400 */ "with ::=", - /* 401 */ "windowdefn_list ::= windowdefn", - /* 402 */ "window ::= frame_opt", + /* 95 */ "oneselect ::= mvalues", + /* 96 */ "mvalues ::= values COMMA LP nexprlist RP", + /* 97 */ "mvalues ::= mvalues COMMA LP nexprlist RP", + /* 98 */ "distinct ::= DISTINCT", + /* 99 */ "distinct ::= ALL", + /* 100 */ "distinct ::=", + /* 101 */ "sclp ::=", + /* 102 */ "selcollist ::= sclp scanpt expr scanpt as", + /* 103 */ "selcollist ::= sclp scanpt STAR", + /* 104 */ "selcollist ::= sclp scanpt nm DOT STAR", + /* 105 */ "as ::= AS nm", + /* 106 */ "as ::=", + /* 107 */ "from ::=", + /* 108 */ "from ::= FROM seltablist", + /* 109 */ "stl_prefix ::= seltablist joinop", + /* 110 */ "stl_prefix ::=", + /* 111 */ "seltablist ::= stl_prefix nm dbnm as on_using", + /* 112 */ "seltablist ::= stl_prefix nm dbnm as indexed_by on_using", + /* 113 */ "seltablist ::= stl_prefix nm dbnm LP exprlist RP as on_using", + /* 114 */ "seltablist ::= stl_prefix LP select RP as on_using", + /* 115 */ "seltablist ::= stl_prefix LP seltablist RP as on_using", + /* 116 */ "dbnm ::=", + /* 117 */ "dbnm ::= DOT nm", + /* 118 */ "fullname ::= nm", + /* 119 */ "fullname ::= nm DOT nm", + /* 120 */ "xfullname ::= nm", + /* 121 */ "xfullname ::= nm DOT nm", + /* 122 */ "xfullname ::= nm DOT nm AS nm", + /* 123 */ "xfullname ::= nm AS nm", + /* 124 */ "joinop ::= COMMA|JOIN", + /* 125 */ "joinop ::= JOIN_KW JOIN", + /* 126 */ "joinop ::= JOIN_KW nm JOIN", + /* 127 */ "joinop ::= JOIN_KW nm nm JOIN", + /* 128 */ "on_using ::= ON expr", + /* 129 */ "on_using ::= USING LP idlist RP", + /* 130 */ "on_using ::=", + /* 131 */ "indexed_opt ::=", + /* 132 */ "indexed_by ::= INDEXED BY nm", + /* 133 */ "indexed_by ::= NOT INDEXED", + /* 134 */ "orderby_opt ::=", + /* 135 */ "orderby_opt ::= ORDER BY sortlist", + /* 136 */ "sortlist ::= sortlist COMMA expr sortorder nulls", + /* 137 */ "sortlist ::= expr sortorder nulls", + /* 138 */ "sortorder ::= ASC", + /* 139 */ "sortorder ::= DESC", + /* 140 */ "sortorder ::=", + /* 141 */ "nulls ::= NULLS FIRST", + /* 142 */ "nulls ::= NULLS LAST", + /* 143 */ "nulls ::=", + /* 144 */ "groupby_opt ::=", + /* 145 */ "groupby_opt ::= GROUP BY nexprlist", + /* 146 */ "having_opt ::=", + /* 147 */ "having_opt ::= HAVING expr", + /* 148 */ "limit_opt ::=", + /* 149 */ "limit_opt ::= LIMIT expr", + /* 150 */ "limit_opt ::= LIMIT expr OFFSET expr", + /* 151 */ "limit_opt ::= LIMIT expr COMMA expr", + /* 152 */ "cmd ::= with DELETE FROM xfullname indexed_opt where_opt_ret", + /* 153 */ "where_opt ::=", + /* 154 */ "where_opt ::= WHERE expr", + /* 155 */ "where_opt_ret ::=", + /* 156 */ "where_opt_ret ::= WHERE expr", + /* 157 */ "where_opt_ret ::= RETURNING selcollist", + /* 158 */ "where_opt_ret ::= WHERE expr RETURNING selcollist", + /* 159 */ "cmd ::= with UPDATE orconf xfullname indexed_opt SET setlist from where_opt_ret", + /* 160 */ "setlist ::= setlist COMMA nm EQ expr", + /* 161 */ "setlist ::= setlist COMMA LP idlist RP EQ expr", + /* 162 */ "setlist ::= nm EQ expr", + /* 163 */ "setlist ::= LP idlist RP EQ expr", + /* 164 */ "cmd ::= with insert_cmd INTO xfullname idlist_opt select upsert", + /* 165 */ "cmd ::= with insert_cmd INTO xfullname idlist_opt DEFAULT VALUES returning", + /* 166 */ "upsert ::=", + /* 167 */ "upsert ::= RETURNING selcollist", + /* 168 */ "upsert ::= ON CONFLICT LP sortlist RP where_opt DO UPDATE SET setlist where_opt upsert", + /* 169 */ "upsert ::= ON CONFLICT LP sortlist RP where_opt DO NOTHING upsert", + /* 170 */ "upsert ::= ON CONFLICT DO NOTHING returning", + /* 171 */ "upsert ::= ON CONFLICT DO UPDATE SET setlist where_opt returning", + /* 172 */ "returning ::= RETURNING selcollist", + /* 173 */ "insert_cmd ::= INSERT orconf", + /* 174 */ "insert_cmd ::= REPLACE", + /* 175 */ "idlist_opt ::=", + /* 176 */ "idlist_opt ::= LP idlist RP", + /* 177 */ "idlist ::= idlist COMMA nm", + /* 178 */ "idlist ::= nm", + /* 179 */ "expr ::= LP expr RP", + /* 180 */ "expr ::= ID|INDEXED|JOIN_KW", + /* 181 */ "expr ::= nm DOT nm", + /* 182 */ "expr ::= nm DOT nm DOT nm", + /* 183 */ "term ::= NULL|FLOAT|BLOB", + /* 184 */ "term ::= STRING", + /* 185 */ "term ::= INTEGER", + /* 186 */ "expr ::= VARIABLE", + /* 187 */ "expr ::= expr COLLATE ID|STRING", + /* 188 */ "expr ::= CAST LP expr AS typetoken RP", + /* 189 */ "expr ::= ID|INDEXED|JOIN_KW LP distinct exprlist RP", + /* 190 */ "expr ::= ID|INDEXED|JOIN_KW LP distinct exprlist ORDER BY sortlist RP", + /* 191 */ "expr ::= ID|INDEXED|JOIN_KW LP STAR RP", + /* 192 */ "expr ::= ID|INDEXED|JOIN_KW LP distinct exprlist RP filter_over", + /* 193 */ "expr ::= ID|INDEXED|JOIN_KW LP distinct exprlist ORDER BY sortlist RP filter_over", + /* 194 */ "expr ::= ID|INDEXED|JOIN_KW LP STAR RP filter_over", + /* 195 */ "term ::= CTIME_KW", + /* 196 */ "expr ::= LP nexprlist COMMA expr RP", + /* 197 */ "expr ::= expr AND expr", + /* 198 */ "expr ::= expr OR expr", + /* 199 */ "expr ::= expr LT|GT|GE|LE expr", + /* 200 */ "expr ::= expr EQ|NE expr", + /* 201 */ "expr ::= expr BITAND|BITOR|LSHIFT|RSHIFT expr", + /* 202 */ "expr ::= expr PLUS|MINUS expr", + /* 203 */ "expr ::= expr STAR|SLASH|REM expr", + /* 204 */ "expr ::= expr CONCAT expr", + /* 205 */ "likeop ::= NOT LIKE_KW|MATCH", + /* 206 */ "expr ::= expr likeop expr", + /* 207 */ "expr ::= expr likeop expr ESCAPE expr", + /* 208 */ "expr ::= expr ISNULL|NOTNULL", + /* 209 */ "expr ::= expr NOT NULL", + /* 210 */ "expr ::= expr IS expr", + /* 211 */ "expr ::= expr IS NOT expr", + /* 212 */ "expr ::= expr IS NOT DISTINCT FROM expr", + /* 213 */ "expr ::= expr IS DISTINCT FROM expr", + /* 214 */ "expr ::= NOT expr", + /* 215 */ "expr ::= BITNOT expr", + /* 216 */ "expr ::= PLUS|MINUS expr", + /* 217 */ "expr ::= expr PTR expr", + /* 218 */ "between_op ::= BETWEEN", + /* 219 */ "between_op ::= NOT BETWEEN", + /* 220 */ "expr ::= expr between_op expr AND expr", + /* 221 */ "in_op ::= IN", + /* 222 */ "in_op ::= NOT IN", + /* 223 */ "expr ::= expr in_op LP exprlist RP", + /* 224 */ "expr ::= LP select RP", + /* 225 */ "expr ::= expr in_op LP select RP", + /* 226 */ "expr ::= expr in_op nm dbnm paren_exprlist", + /* 227 */ "expr ::= EXISTS LP select RP", + /* 228 */ "expr ::= CASE case_operand case_exprlist case_else END", + /* 229 */ "case_exprlist ::= case_exprlist WHEN expr THEN expr", + /* 230 */ "case_exprlist ::= WHEN expr THEN expr", + /* 231 */ "case_else ::= ELSE expr", + /* 232 */ "case_else ::=", + /* 233 */ "case_operand ::=", + /* 234 */ "exprlist ::=", + /* 235 */ "nexprlist ::= nexprlist COMMA expr", + /* 236 */ "nexprlist ::= expr", + /* 237 */ "paren_exprlist ::=", + /* 238 */ "paren_exprlist ::= LP exprlist RP", + /* 239 */ "cmd ::= createkw uniqueflag INDEX ifnotexists nm dbnm ON nm LP sortlist RP where_opt", + /* 240 */ "uniqueflag ::= UNIQUE", + /* 241 */ "uniqueflag ::=", + /* 242 */ "eidlist_opt ::=", + /* 243 */ "eidlist_opt ::= LP eidlist RP", + /* 244 */ "eidlist ::= eidlist COMMA nm collate sortorder", + /* 245 */ "eidlist ::= nm collate sortorder", + /* 246 */ "collate ::=", + /* 247 */ "collate ::= COLLATE ID|STRING", + /* 248 */ "cmd ::= DROP INDEX ifexists fullname", + /* 249 */ "cmd ::= VACUUM vinto", + /* 250 */ "cmd ::= VACUUM nm vinto", + /* 251 */ "vinto ::= INTO expr", + /* 252 */ "vinto ::=", + /* 253 */ "cmd ::= PRAGMA nm dbnm", + /* 254 */ "cmd ::= PRAGMA nm dbnm EQ nmnum", + /* 255 */ "cmd ::= PRAGMA nm dbnm LP nmnum RP", + /* 256 */ "cmd ::= PRAGMA nm dbnm EQ minus_num", + /* 257 */ "cmd ::= PRAGMA nm dbnm LP minus_num RP", + /* 258 */ "plus_num ::= PLUS INTEGER|FLOAT", + /* 259 */ "minus_num ::= MINUS INTEGER|FLOAT", + /* 260 */ "cmd ::= createkw trigger_decl BEGIN trigger_cmd_list END", + /* 261 */ "trigger_decl ::= temp TRIGGER ifnotexists nm dbnm trigger_time trigger_event ON fullname foreach_clause when_clause", + /* 262 */ "trigger_time ::= BEFORE|AFTER", + /* 263 */ "trigger_time ::= INSTEAD OF", + /* 264 */ "trigger_time ::=", + /* 265 */ "trigger_event ::= DELETE|INSERT", + /* 266 */ "trigger_event ::= UPDATE", + /* 267 */ "trigger_event ::= UPDATE OF idlist", + /* 268 */ "when_clause ::=", + /* 269 */ "when_clause ::= WHEN expr", + /* 270 */ "trigger_cmd_list ::= trigger_cmd_list trigger_cmd SEMI", + /* 271 */ "trigger_cmd_list ::= trigger_cmd SEMI", + /* 272 */ "trnm ::= nm DOT nm", + /* 273 */ "tridxby ::= INDEXED BY nm", + /* 274 */ "tridxby ::= NOT INDEXED", + /* 275 */ "trigger_cmd ::= UPDATE orconf trnm tridxby SET setlist from where_opt scanpt", + /* 276 */ "trigger_cmd ::= scanpt insert_cmd INTO trnm idlist_opt select upsert scanpt", + /* 277 */ "trigger_cmd ::= DELETE FROM trnm tridxby where_opt scanpt", + /* 278 */ "trigger_cmd ::= scanpt select scanpt", + /* 279 */ "expr ::= RAISE LP IGNORE RP", + /* 280 */ "expr ::= RAISE LP raisetype COMMA nm RP", + /* 281 */ "raisetype ::= ROLLBACK", + /* 282 */ "raisetype ::= ABORT", + /* 283 */ "raisetype ::= FAIL", + /* 284 */ "cmd ::= DROP TRIGGER ifexists fullname", + /* 285 */ "cmd ::= ATTACH database_kw_opt expr AS expr key_opt", + /* 286 */ "cmd ::= DETACH database_kw_opt expr", + /* 287 */ "key_opt ::=", + /* 288 */ "key_opt ::= KEY expr", + /* 289 */ "cmd ::= REINDEX", + /* 290 */ "cmd ::= REINDEX nm dbnm", + /* 291 */ "cmd ::= ANALYZE", + /* 292 */ "cmd ::= ANALYZE nm dbnm", + /* 293 */ "cmd ::= ALTER TABLE fullname RENAME TO nm", + /* 294 */ "cmd ::= ALTER TABLE add_column_fullname ADD kwcolumn_opt columnname carglist", + /* 295 */ "cmd ::= ALTER TABLE fullname DROP kwcolumn_opt nm", + /* 296 */ "add_column_fullname ::= fullname", + /* 297 */ "cmd ::= ALTER TABLE fullname RENAME kwcolumn_opt nm TO nm", + /* 298 */ "cmd ::= create_vtab", + /* 299 */ "cmd ::= create_vtab LP vtabarglist RP", + /* 300 */ "create_vtab ::= createkw VIRTUAL TABLE ifnotexists nm dbnm USING nm", + /* 301 */ "vtabarg ::=", + /* 302 */ "vtabargtoken ::= ANY", + /* 303 */ "vtabargtoken ::= lp anylist RP", + /* 304 */ "lp ::= LP", + /* 305 */ "with ::= WITH wqlist", + /* 306 */ "with ::= WITH RECURSIVE wqlist", + /* 307 */ "wqas ::= AS", + /* 308 */ "wqas ::= AS MATERIALIZED", + /* 309 */ "wqas ::= AS NOT MATERIALIZED", + /* 310 */ "wqitem ::= withnm eidlist_opt wqas LP select RP", + /* 311 */ "withnm ::= nm", + /* 312 */ "wqlist ::= wqitem", + /* 313 */ "wqlist ::= wqlist COMMA wqitem", + /* 314 */ "windowdefn_list ::= windowdefn_list COMMA windowdefn", + /* 315 */ "windowdefn ::= nm AS LP window RP", + /* 316 */ "window ::= PARTITION BY nexprlist orderby_opt frame_opt", + /* 317 */ "window ::= nm PARTITION BY nexprlist orderby_opt frame_opt", + /* 318 */ "window ::= ORDER BY sortlist frame_opt", + /* 319 */ "window ::= nm ORDER BY sortlist frame_opt", + /* 320 */ "window ::= nm frame_opt", + /* 321 */ "frame_opt ::=", + /* 322 */ "frame_opt ::= range_or_rows frame_bound_s frame_exclude_opt", + /* 323 */ "frame_opt ::= range_or_rows BETWEEN frame_bound_s AND frame_bound_e frame_exclude_opt", + /* 324 */ "range_or_rows ::= RANGE|ROWS|GROUPS", + /* 325 */ "frame_bound_s ::= frame_bound", + /* 326 */ "frame_bound_s ::= UNBOUNDED PRECEDING", + /* 327 */ "frame_bound_e ::= frame_bound", + /* 328 */ "frame_bound_e ::= UNBOUNDED FOLLOWING", + /* 329 */ "frame_bound ::= expr PRECEDING|FOLLOWING", + /* 330 */ "frame_bound ::= CURRENT ROW", + /* 331 */ "frame_exclude_opt ::=", + /* 332 */ "frame_exclude_opt ::= EXCLUDE frame_exclude", + /* 333 */ "frame_exclude ::= NO OTHERS", + /* 334 */ "frame_exclude ::= CURRENT ROW", + /* 335 */ "frame_exclude ::= GROUP|TIES", + /* 336 */ "window_clause ::= WINDOW windowdefn_list", + /* 337 */ "filter_over ::= filter_clause over_clause", + /* 338 */ "filter_over ::= over_clause", + /* 339 */ "filter_over ::= filter_clause", + /* 340 */ "over_clause ::= OVER LP window RP", + /* 341 */ "over_clause ::= OVER nm", + /* 342 */ "filter_clause ::= FILTER LP WHERE expr RP", + /* 343 */ "term ::= QNUMBER", + /* 344 */ "input ::= cmdlist", + /* 345 */ "cmdlist ::= cmdlist ecmd", + /* 346 */ "cmdlist ::= ecmd", + /* 347 */ "ecmd ::= SEMI", + /* 348 */ "ecmd ::= cmdx SEMI", + /* 349 */ "ecmd ::= explain cmdx SEMI", + /* 350 */ "trans_opt ::=", + /* 351 */ "trans_opt ::= TRANSACTION", + /* 352 */ "trans_opt ::= TRANSACTION nm", + /* 353 */ "savepoint_opt ::= SAVEPOINT", + /* 354 */ "savepoint_opt ::=", + /* 355 */ "cmd ::= create_table create_table_args", + /* 356 */ "table_option_set ::= table_option", + /* 357 */ "columnlist ::= columnlist COMMA columnname carglist", + /* 358 */ "columnlist ::= columnname carglist", + /* 359 */ "nm ::= ID|INDEXED|JOIN_KW", + /* 360 */ "nm ::= STRING", + /* 361 */ "typetoken ::= typename", + /* 362 */ "typename ::= ID|STRING", + /* 363 */ "signed ::= plus_num", + /* 364 */ "signed ::= minus_num", + /* 365 */ "carglist ::= carglist ccons", + /* 366 */ "carglist ::=", + /* 367 */ "ccons ::= NULL onconf", + /* 368 */ "ccons ::= GENERATED ALWAYS AS generated", + /* 369 */ "ccons ::= AS generated", + /* 370 */ "conslist_opt ::= COMMA conslist", + /* 371 */ "conslist ::= conslist tconscomma tcons", + /* 372 */ "conslist ::= tcons", + /* 373 */ "tconscomma ::=", + /* 374 */ "defer_subclause_opt ::= defer_subclause", + /* 375 */ "resolvetype ::= raisetype", + /* 376 */ "selectnowith ::= oneselect", + /* 377 */ "oneselect ::= values", + /* 378 */ "sclp ::= selcollist COMMA", + /* 379 */ "as ::= ID|STRING", + /* 380 */ "indexed_opt ::= indexed_by", + /* 381 */ "returning ::=", + /* 382 */ "expr ::= term", + /* 383 */ "likeop ::= LIKE_KW|MATCH", + /* 384 */ "case_operand ::= expr", + /* 385 */ "exprlist ::= nexprlist", + /* 386 */ "nmnum ::= plus_num", + /* 387 */ "nmnum ::= nm", + /* 388 */ "nmnum ::= ON", + /* 389 */ "nmnum ::= DELETE", + /* 390 */ "nmnum ::= DEFAULT", + /* 391 */ "plus_num ::= INTEGER|FLOAT", + /* 392 */ "foreach_clause ::=", + /* 393 */ "foreach_clause ::= FOR EACH ROW", + /* 394 */ "trnm ::= nm", + /* 395 */ "tridxby ::=", + /* 396 */ "database_kw_opt ::= DATABASE", + /* 397 */ "database_kw_opt ::=", + /* 398 */ "kwcolumn_opt ::=", + /* 399 */ "kwcolumn_opt ::= COLUMNKW", + /* 400 */ "vtabarglist ::= vtabarg", + /* 401 */ "vtabarglist ::= vtabarglist COMMA vtabarg", + /* 402 */ "vtabarg ::= vtabarg vtabargtoken", + /* 403 */ "anylist ::=", + /* 404 */ "anylist ::= anylist LP anylist RP", + /* 405 */ "anylist ::= anylist ANY", + /* 406 */ "with ::=", + /* 407 */ "windowdefn_list ::= windowdefn", + /* 408 */ "window ::= frame_opt", }; #endif /* NDEBUG */ -#if YYSTACKDEPTH<=0 +#if YYGROWABLESTACK /* ** Try to increase the size of the parser stack. Return the number ** of errors. Return 0 on success. */ static int yyGrowStack(yyParser *p){ + int oldSize = 1 + (int)(p->yystackEnd - p->yystack); int newSize; int idx; yyStackEntry *pNew; - newSize = p->yystksz*2 + 100; - idx = p->yytos ? (int)(p->yytos - p->yystack) : 0; - if( p->yystack==&p->yystk0 ){ - pNew = malloc(newSize*sizeof(pNew[0])); - if( pNew ) pNew[0] = p->yystk0; + newSize = oldSize*2 + 100; + idx = (int)(p->yytos - p->yystack); + if( p->yystack==p->yystk0 ){ + pNew = YYREALLOC(0, newSize*sizeof(pNew[0])); + if( pNew==0 ) return 1; + memcpy(pNew, p->yystack, oldSize*sizeof(pNew[0])); }else{ - pNew = realloc(p->yystack, newSize*sizeof(pNew[0])); + pNew = YYREALLOC(p->yystack, newSize*sizeof(pNew[0])); + if( pNew==0 ) return 1; } - if( pNew ){ - p->yystack = pNew; - p->yytos = &p->yystack[idx]; + p->yystack = pNew; + p->yytos = &p->yystack[idx]; #ifndef NDEBUG - if( yyTraceFILE ){ - fprintf(yyTraceFILE,"%sStack grows from %d to %d entries.\n", - yyTracePrompt, p->yystksz, newSize); - } -#endif - p->yystksz = newSize; + if( yyTraceFILE ){ + fprintf(yyTraceFILE,"%sStack grows from %d to %d entries.\n", + yyTracePrompt, oldSize, newSize); } - return pNew==0; +#endif + p->yystackEnd = &p->yystack[newSize-1]; + return 0; } +#endif /* YYGROWABLESTACK */ + +#if !YYGROWABLESTACK +/* For builds that do no have a growable stack, yyGrowStack always +** returns an error. +*/ +# define yyGrowStack(X) 1 #endif /* Datatype of the argument to the memory allocated passed as the @@ -171498,24 +174798,14 @@ SQLITE_PRIVATE void sqlite3ParserInit(void *yypRawParser sqlite3ParserCTX_PDECL) #ifdef YYTRACKMAXSTACKDEPTH yypParser->yyhwm = 0; #endif -#if YYSTACKDEPTH<=0 - yypParser->yytos = NULL; - yypParser->yystack = NULL; - yypParser->yystksz = 0; - if( yyGrowStack(yypParser) ){ - yypParser->yystack = &yypParser->yystk0; - yypParser->yystksz = 1; - } -#endif + yypParser->yystack = yypParser->yystk0; + yypParser->yystackEnd = &yypParser->yystack[YYSTACKDEPTH-1]; #ifndef YYNOERRORRECOVERY yypParser->yyerrcnt = -1; #endif yypParser->yytos = yypParser->yystack; yypParser->yystack[0].stateno = 0; yypParser->yystack[0].major = 0; -#if YYSTACKDEPTH>0 - yypParser->yystackEnd = &yypParser->yystack[YYSTACKDEPTH-1]; -#endif } #ifndef sqlite3Parser_ENGINEALWAYSONSTACK @@ -171569,97 +174859,98 @@ static void yy_destructor( ** inside the C code. */ /********* Begin destructor definitions ***************************************/ - case 204: /* select */ - case 239: /* selectnowith */ - case 240: /* oneselect */ - case 252: /* values */ + case 205: /* select */ + case 240: /* selectnowith */ + case 241: /* oneselect */ + case 253: /* values */ + case 255: /* mvalues */ { -sqlite3SelectDelete(pParse->db, (yypminor->yy47)); -} - break; - case 216: /* term */ - case 217: /* expr */ - case 246: /* where_opt */ - case 248: /* having_opt */ - case 267: /* where_opt_ret */ - case 278: /* case_operand */ - case 280: /* case_else */ - case 283: /* vinto */ - case 290: /* when_clause */ - case 295: /* key_opt */ - case 311: /* filter_clause */ +sqlite3SelectDelete(pParse->db, (yypminor->yy555)); +} + break; + case 217: /* term */ + case 218: /* expr */ + case 247: /* where_opt */ + case 249: /* having_opt */ + case 269: /* where_opt_ret */ + case 280: /* case_operand */ + case 282: /* case_else */ + case 285: /* vinto */ + case 292: /* when_clause */ + case 297: /* key_opt */ + case 314: /* filter_clause */ { -sqlite3ExprDelete(pParse->db, (yypminor->yy528)); -} - break; - case 221: /* eidlist_opt */ - case 231: /* sortlist */ - case 232: /* eidlist */ - case 244: /* selcollist */ - case 247: /* groupby_opt */ - case 249: /* orderby_opt */ - case 253: /* nexprlist */ - case 254: /* sclp */ - case 261: /* exprlist */ - case 268: /* setlist */ - case 277: /* paren_exprlist */ - case 279: /* case_exprlist */ - case 310: /* part_opt */ +sqlite3ExprDelete(pParse->db, (yypminor->yy454)); +} + break; + case 222: /* eidlist_opt */ + case 232: /* sortlist */ + case 233: /* eidlist */ + case 245: /* selcollist */ + case 248: /* groupby_opt */ + case 250: /* orderby_opt */ + case 254: /* nexprlist */ + case 256: /* sclp */ + case 263: /* exprlist */ + case 270: /* setlist */ + case 279: /* paren_exprlist */ + case 281: /* case_exprlist */ + case 313: /* part_opt */ { -sqlite3ExprListDelete(pParse->db, (yypminor->yy322)); +sqlite3ExprListDelete(pParse->db, (yypminor->yy14)); } break; - case 238: /* fullname */ - case 245: /* from */ - case 256: /* seltablist */ - case 257: /* stl_prefix */ - case 262: /* xfullname */ + case 239: /* fullname */ + case 246: /* from */ + case 258: /* seltablist */ + case 259: /* stl_prefix */ + case 264: /* xfullname */ { -sqlite3SrcListDelete(pParse->db, (yypminor->yy131)); +sqlite3SrcListDelete(pParse->db, (yypminor->yy203)); } break; - case 241: /* wqlist */ + case 242: /* wqlist */ { -sqlite3WithDelete(pParse->db, (yypminor->yy521)); +sqlite3WithDelete(pParse->db, (yypminor->yy59)); } break; - case 251: /* window_clause */ - case 306: /* windowdefn_list */ + case 252: /* window_clause */ + case 309: /* windowdefn_list */ { -sqlite3WindowListDelete(pParse->db, (yypminor->yy41)); +sqlite3WindowListDelete(pParse->db, (yypminor->yy211)); } break; - case 263: /* idlist */ - case 270: /* idlist_opt */ + case 265: /* idlist */ + case 272: /* idlist_opt */ { -sqlite3IdListDelete(pParse->db, (yypminor->yy254)); +sqlite3IdListDelete(pParse->db, (yypminor->yy132)); } break; - case 273: /* filter_over */ - case 307: /* windowdefn */ - case 308: /* window */ - case 309: /* frame_opt */ - case 312: /* over_clause */ + case 275: /* filter_over */ + case 310: /* windowdefn */ + case 311: /* window */ + case 312: /* frame_opt */ + case 315: /* over_clause */ { -sqlite3WindowDelete(pParse->db, (yypminor->yy41)); +sqlite3WindowDelete(pParse->db, (yypminor->yy211)); } break; - case 286: /* trigger_cmd_list */ - case 291: /* trigger_cmd */ + case 288: /* trigger_cmd_list */ + case 293: /* trigger_cmd */ { -sqlite3DeleteTriggerStep(pParse->db, (yypminor->yy33)); +sqlite3DeleteTriggerStep(pParse->db, (yypminor->yy427)); } break; - case 288: /* trigger_event */ + case 290: /* trigger_event */ { -sqlite3IdListDelete(pParse->db, (yypminor->yy180).b); +sqlite3IdListDelete(pParse->db, (yypminor->yy286).b); } break; - case 314: /* frame_bound */ - case 315: /* frame_bound_s */ - case 316: /* frame_bound_e */ + case 317: /* frame_bound */ + case 318: /* frame_bound_s */ + case 319: /* frame_bound_e */ { -sqlite3ExprDelete(pParse->db, (yypminor->yy595).pExpr); +sqlite3ExprDelete(pParse->db, (yypminor->yy509).pExpr); } break; /********* End destructor definitions *****************************************/ @@ -171693,9 +174984,26 @@ static void yy_pop_parser_stack(yyParser *pParser){ */ SQLITE_PRIVATE void sqlite3ParserFinalize(void *p){ yyParser *pParser = (yyParser*)p; - while( pParser->yytos>pParser->yystack ) yy_pop_parser_stack(pParser); -#if YYSTACKDEPTH<=0 - if( pParser->yystack!=&pParser->yystk0 ) free(pParser->yystack); + + /* In-lined version of calling yy_pop_parser_stack() for each + ** element left in the stack */ + yyStackEntry *yytos = pParser->yytos; + while( yytos>pParser->yystack ){ +#ifndef NDEBUG + if( yyTraceFILE ){ + fprintf(yyTraceFILE,"%sPopping %s\n", + yyTracePrompt, + yyTokenName[yytos->major]); + } +#endif + if( yytos->major>=YY_MIN_DSTRCTR ){ + yy_destructor(pParser, yytos->major, &yytos->minor); + } + yytos--; + } + +#if YYGROWABLESTACK + if( pParser->yystack!=pParser->yystk0 ) YYFREE(pParser->yystack); #endif } @@ -171878,7 +175186,7 @@ static void yyStackOverflow(yyParser *yypParser){ ** stack every overflows */ /******** Begin %stack_overflow code ******************************************/ - sqlite3ErrorMsg(pParse, "parser stack overflow"); + sqlite3OomFault(pParse->db); /******** End %stack_overflow code ********************************************/ sqlite3ParserARG_STORE /* Suppress warning about unused %extra_argument var */ sqlite3ParserCTX_STORE @@ -171922,25 +175230,19 @@ static void yy_shift( assert( yypParser->yyhwm == (int)(yypParser->yytos - yypParser->yystack) ); } #endif -#if YYSTACKDEPTH>0 - if( yypParser->yytos>yypParser->yystackEnd ){ - yypParser->yytos--; - yyStackOverflow(yypParser); - return; - } -#else - if( yypParser->yytos>=&yypParser->yystack[yypParser->yystksz] ){ + yytos = yypParser->yytos; + if( yytos>yypParser->yystackEnd ){ if( yyGrowStack(yypParser) ){ yypParser->yytos--; yyStackOverflow(yypParser); return; } + yytos = yypParser->yytos; + assert( yytos <= yypParser->yystackEnd ); } -#endif if( yyNewState > YY_MAX_SHIFT ){ yyNewState += YY_MIN_REDUCE - YY_MIN_SHIFTREDUCE; } - yytos = yypParser->yytos; yytos->stateno = yyNewState; yytos->major = yyMajor; yytos->minor.yy0 = yyMinor; @@ -171950,409 +175252,415 @@ static void yy_shift( /* For rule J, yyRuleInfoLhs[J] contains the symbol on the left-hand side ** of that rule */ static const YYCODETYPE yyRuleInfoLhs[] = { - 189, /* (0) explain ::= EXPLAIN */ - 189, /* (1) explain ::= EXPLAIN QUERY PLAN */ - 188, /* (2) cmdx ::= cmd */ - 190, /* (3) cmd ::= BEGIN transtype trans_opt */ - 191, /* (4) transtype ::= */ - 191, /* (5) transtype ::= DEFERRED */ - 191, /* (6) transtype ::= IMMEDIATE */ - 191, /* (7) transtype ::= EXCLUSIVE */ - 190, /* (8) cmd ::= COMMIT|END trans_opt */ - 190, /* (9) cmd ::= ROLLBACK trans_opt */ - 190, /* (10) cmd ::= SAVEPOINT nm */ - 190, /* (11) cmd ::= RELEASE savepoint_opt nm */ - 190, /* (12) cmd ::= ROLLBACK trans_opt TO savepoint_opt nm */ - 195, /* (13) create_table ::= createkw temp TABLE ifnotexists nm dbnm */ - 197, /* (14) createkw ::= CREATE */ - 199, /* (15) ifnotexists ::= */ - 199, /* (16) ifnotexists ::= IF NOT EXISTS */ - 198, /* (17) temp ::= TEMP */ - 198, /* (18) temp ::= */ - 196, /* (19) create_table_args ::= LP columnlist conslist_opt RP table_option_set */ - 196, /* (20) create_table_args ::= AS select */ - 203, /* (21) table_option_set ::= */ - 203, /* (22) table_option_set ::= table_option_set COMMA table_option */ - 205, /* (23) table_option ::= WITHOUT nm */ - 205, /* (24) table_option ::= nm */ - 206, /* (25) columnname ::= nm typetoken */ - 208, /* (26) typetoken ::= */ - 208, /* (27) typetoken ::= typename LP signed RP */ - 208, /* (28) typetoken ::= typename LP signed COMMA signed RP */ - 209, /* (29) typename ::= typename ID|STRING */ - 213, /* (30) scanpt ::= */ - 214, /* (31) scantok ::= */ - 215, /* (32) ccons ::= CONSTRAINT nm */ - 215, /* (33) ccons ::= DEFAULT scantok term */ - 215, /* (34) ccons ::= DEFAULT LP expr RP */ - 215, /* (35) ccons ::= DEFAULT PLUS scantok term */ - 215, /* (36) ccons ::= DEFAULT MINUS scantok term */ - 215, /* (37) ccons ::= DEFAULT scantok ID|INDEXED */ - 215, /* (38) ccons ::= NOT NULL onconf */ - 215, /* (39) ccons ::= PRIMARY KEY sortorder onconf autoinc */ - 215, /* (40) ccons ::= UNIQUE onconf */ - 215, /* (41) ccons ::= CHECK LP expr RP */ - 215, /* (42) ccons ::= REFERENCES nm eidlist_opt refargs */ - 215, /* (43) ccons ::= defer_subclause */ - 215, /* (44) ccons ::= COLLATE ID|STRING */ - 224, /* (45) generated ::= LP expr RP */ - 224, /* (46) generated ::= LP expr RP ID */ - 220, /* (47) autoinc ::= */ - 220, /* (48) autoinc ::= AUTOINCR */ - 222, /* (49) refargs ::= */ - 222, /* (50) refargs ::= refargs refarg */ - 225, /* (51) refarg ::= MATCH nm */ - 225, /* (52) refarg ::= ON INSERT refact */ - 225, /* (53) refarg ::= ON DELETE refact */ - 225, /* (54) refarg ::= ON UPDATE refact */ - 226, /* (55) refact ::= SET NULL */ - 226, /* (56) refact ::= SET DEFAULT */ - 226, /* (57) refact ::= CASCADE */ - 226, /* (58) refact ::= RESTRICT */ - 226, /* (59) refact ::= NO ACTION */ - 223, /* (60) defer_subclause ::= NOT DEFERRABLE init_deferred_pred_opt */ - 223, /* (61) defer_subclause ::= DEFERRABLE init_deferred_pred_opt */ - 227, /* (62) init_deferred_pred_opt ::= */ - 227, /* (63) init_deferred_pred_opt ::= INITIALLY DEFERRED */ - 227, /* (64) init_deferred_pred_opt ::= INITIALLY IMMEDIATE */ - 202, /* (65) conslist_opt ::= */ - 229, /* (66) tconscomma ::= COMMA */ - 230, /* (67) tcons ::= CONSTRAINT nm */ - 230, /* (68) tcons ::= PRIMARY KEY LP sortlist autoinc RP onconf */ - 230, /* (69) tcons ::= UNIQUE LP sortlist RP onconf */ - 230, /* (70) tcons ::= CHECK LP expr RP onconf */ - 230, /* (71) tcons ::= FOREIGN KEY LP eidlist RP REFERENCES nm eidlist_opt refargs defer_subclause_opt */ - 233, /* (72) defer_subclause_opt ::= */ - 218, /* (73) onconf ::= */ - 218, /* (74) onconf ::= ON CONFLICT resolvetype */ - 234, /* (75) orconf ::= */ - 234, /* (76) orconf ::= OR resolvetype */ - 235, /* (77) resolvetype ::= IGNORE */ - 235, /* (78) resolvetype ::= REPLACE */ - 190, /* (79) cmd ::= DROP TABLE ifexists fullname */ - 237, /* (80) ifexists ::= IF EXISTS */ - 237, /* (81) ifexists ::= */ - 190, /* (82) cmd ::= createkw temp VIEW ifnotexists nm dbnm eidlist_opt AS select */ - 190, /* (83) cmd ::= DROP VIEW ifexists fullname */ - 190, /* (84) cmd ::= select */ - 204, /* (85) select ::= WITH wqlist selectnowith */ - 204, /* (86) select ::= WITH RECURSIVE wqlist selectnowith */ - 204, /* (87) select ::= selectnowith */ - 239, /* (88) selectnowith ::= selectnowith multiselect_op oneselect */ - 242, /* (89) multiselect_op ::= UNION */ - 242, /* (90) multiselect_op ::= UNION ALL */ - 242, /* (91) multiselect_op ::= EXCEPT|INTERSECT */ - 240, /* (92) oneselect ::= SELECT distinct selcollist from where_opt groupby_opt having_opt orderby_opt limit_opt */ - 240, /* (93) oneselect ::= SELECT distinct selcollist from where_opt groupby_opt having_opt window_clause orderby_opt limit_opt */ - 252, /* (94) values ::= VALUES LP nexprlist RP */ - 252, /* (95) values ::= values COMMA LP nexprlist RP */ - 243, /* (96) distinct ::= DISTINCT */ - 243, /* (97) distinct ::= ALL */ - 243, /* (98) distinct ::= */ - 254, /* (99) sclp ::= */ - 244, /* (100) selcollist ::= sclp scanpt expr scanpt as */ - 244, /* (101) selcollist ::= sclp scanpt STAR */ - 244, /* (102) selcollist ::= sclp scanpt nm DOT STAR */ - 255, /* (103) as ::= AS nm */ - 255, /* (104) as ::= */ - 245, /* (105) from ::= */ - 245, /* (106) from ::= FROM seltablist */ - 257, /* (107) stl_prefix ::= seltablist joinop */ - 257, /* (108) stl_prefix ::= */ - 256, /* (109) seltablist ::= stl_prefix nm dbnm as on_using */ - 256, /* (110) seltablist ::= stl_prefix nm dbnm as indexed_by on_using */ - 256, /* (111) seltablist ::= stl_prefix nm dbnm LP exprlist RP as on_using */ - 256, /* (112) seltablist ::= stl_prefix LP select RP as on_using */ - 256, /* (113) seltablist ::= stl_prefix LP seltablist RP as on_using */ - 200, /* (114) dbnm ::= */ - 200, /* (115) dbnm ::= DOT nm */ - 238, /* (116) fullname ::= nm */ - 238, /* (117) fullname ::= nm DOT nm */ - 262, /* (118) xfullname ::= nm */ - 262, /* (119) xfullname ::= nm DOT nm */ - 262, /* (120) xfullname ::= nm DOT nm AS nm */ - 262, /* (121) xfullname ::= nm AS nm */ - 258, /* (122) joinop ::= COMMA|JOIN */ - 258, /* (123) joinop ::= JOIN_KW JOIN */ - 258, /* (124) joinop ::= JOIN_KW nm JOIN */ - 258, /* (125) joinop ::= JOIN_KW nm nm JOIN */ - 259, /* (126) on_using ::= ON expr */ - 259, /* (127) on_using ::= USING LP idlist RP */ - 259, /* (128) on_using ::= */ - 264, /* (129) indexed_opt ::= */ - 260, /* (130) indexed_by ::= INDEXED BY nm */ - 260, /* (131) indexed_by ::= NOT INDEXED */ - 249, /* (132) orderby_opt ::= */ - 249, /* (133) orderby_opt ::= ORDER BY sortlist */ - 231, /* (134) sortlist ::= sortlist COMMA expr sortorder nulls */ - 231, /* (135) sortlist ::= expr sortorder nulls */ - 219, /* (136) sortorder ::= ASC */ - 219, /* (137) sortorder ::= DESC */ - 219, /* (138) sortorder ::= */ - 265, /* (139) nulls ::= NULLS FIRST */ - 265, /* (140) nulls ::= NULLS LAST */ - 265, /* (141) nulls ::= */ - 247, /* (142) groupby_opt ::= */ - 247, /* (143) groupby_opt ::= GROUP BY nexprlist */ - 248, /* (144) having_opt ::= */ - 248, /* (145) having_opt ::= HAVING expr */ - 250, /* (146) limit_opt ::= */ - 250, /* (147) limit_opt ::= LIMIT expr */ - 250, /* (148) limit_opt ::= LIMIT expr OFFSET expr */ - 250, /* (149) limit_opt ::= LIMIT expr COMMA expr */ - 190, /* (150) cmd ::= with DELETE FROM xfullname indexed_opt where_opt_ret */ - 246, /* (151) where_opt ::= */ - 246, /* (152) where_opt ::= WHERE expr */ - 267, /* (153) where_opt_ret ::= */ - 267, /* (154) where_opt_ret ::= WHERE expr */ - 267, /* (155) where_opt_ret ::= RETURNING selcollist */ - 267, /* (156) where_opt_ret ::= WHERE expr RETURNING selcollist */ - 190, /* (157) cmd ::= with UPDATE orconf xfullname indexed_opt SET setlist from where_opt_ret */ - 268, /* (158) setlist ::= setlist COMMA nm EQ expr */ - 268, /* (159) setlist ::= setlist COMMA LP idlist RP EQ expr */ - 268, /* (160) setlist ::= nm EQ expr */ - 268, /* (161) setlist ::= LP idlist RP EQ expr */ - 190, /* (162) cmd ::= with insert_cmd INTO xfullname idlist_opt select upsert */ - 190, /* (163) cmd ::= with insert_cmd INTO xfullname idlist_opt DEFAULT VALUES returning */ - 271, /* (164) upsert ::= */ - 271, /* (165) upsert ::= RETURNING selcollist */ - 271, /* (166) upsert ::= ON CONFLICT LP sortlist RP where_opt DO UPDATE SET setlist where_opt upsert */ - 271, /* (167) upsert ::= ON CONFLICT LP sortlist RP where_opt DO NOTHING upsert */ - 271, /* (168) upsert ::= ON CONFLICT DO NOTHING returning */ - 271, /* (169) upsert ::= ON CONFLICT DO UPDATE SET setlist where_opt returning */ - 272, /* (170) returning ::= RETURNING selcollist */ - 269, /* (171) insert_cmd ::= INSERT orconf */ - 269, /* (172) insert_cmd ::= REPLACE */ - 270, /* (173) idlist_opt ::= */ - 270, /* (174) idlist_opt ::= LP idlist RP */ - 263, /* (175) idlist ::= idlist COMMA nm */ - 263, /* (176) idlist ::= nm */ - 217, /* (177) expr ::= LP expr RP */ - 217, /* (178) expr ::= ID|INDEXED|JOIN_KW */ - 217, /* (179) expr ::= nm DOT nm */ - 217, /* (180) expr ::= nm DOT nm DOT nm */ - 216, /* (181) term ::= NULL|FLOAT|BLOB */ - 216, /* (182) term ::= STRING */ - 216, /* (183) term ::= INTEGER */ - 217, /* (184) expr ::= VARIABLE */ - 217, /* (185) expr ::= expr COLLATE ID|STRING */ - 217, /* (186) expr ::= CAST LP expr AS typetoken RP */ - 217, /* (187) expr ::= ID|INDEXED|JOIN_KW LP distinct exprlist RP */ - 217, /* (188) expr ::= ID|INDEXED|JOIN_KW LP STAR RP */ - 217, /* (189) expr ::= ID|INDEXED|JOIN_KW LP distinct exprlist RP filter_over */ - 217, /* (190) expr ::= ID|INDEXED|JOIN_KW LP STAR RP filter_over */ - 216, /* (191) term ::= CTIME_KW */ - 217, /* (192) expr ::= LP nexprlist COMMA expr RP */ - 217, /* (193) expr ::= expr AND expr */ - 217, /* (194) expr ::= expr OR expr */ - 217, /* (195) expr ::= expr LT|GT|GE|LE expr */ - 217, /* (196) expr ::= expr EQ|NE expr */ - 217, /* (197) expr ::= expr BITAND|BITOR|LSHIFT|RSHIFT expr */ - 217, /* (198) expr ::= expr PLUS|MINUS expr */ - 217, /* (199) expr ::= expr STAR|SLASH|REM expr */ - 217, /* (200) expr ::= expr CONCAT expr */ - 274, /* (201) likeop ::= NOT LIKE_KW|MATCH */ - 217, /* (202) expr ::= expr likeop expr */ - 217, /* (203) expr ::= expr likeop expr ESCAPE expr */ - 217, /* (204) expr ::= expr ISNULL|NOTNULL */ - 217, /* (205) expr ::= expr NOT NULL */ - 217, /* (206) expr ::= expr IS expr */ - 217, /* (207) expr ::= expr IS NOT expr */ - 217, /* (208) expr ::= expr IS NOT DISTINCT FROM expr */ - 217, /* (209) expr ::= expr IS DISTINCT FROM expr */ - 217, /* (210) expr ::= NOT expr */ - 217, /* (211) expr ::= BITNOT expr */ - 217, /* (212) expr ::= PLUS|MINUS expr */ - 217, /* (213) expr ::= expr PTR expr */ - 275, /* (214) between_op ::= BETWEEN */ - 275, /* (215) between_op ::= NOT BETWEEN */ - 217, /* (216) expr ::= expr between_op expr AND expr */ - 276, /* (217) in_op ::= IN */ - 276, /* (218) in_op ::= NOT IN */ - 217, /* (219) expr ::= expr in_op LP exprlist RP */ - 217, /* (220) expr ::= LP select RP */ - 217, /* (221) expr ::= expr in_op LP select RP */ - 217, /* (222) expr ::= expr in_op nm dbnm paren_exprlist */ - 217, /* (223) expr ::= EXISTS LP select RP */ - 217, /* (224) expr ::= CASE case_operand case_exprlist case_else END */ - 279, /* (225) case_exprlist ::= case_exprlist WHEN expr THEN expr */ - 279, /* (226) case_exprlist ::= WHEN expr THEN expr */ - 280, /* (227) case_else ::= ELSE expr */ - 280, /* (228) case_else ::= */ - 278, /* (229) case_operand ::= */ - 261, /* (230) exprlist ::= */ - 253, /* (231) nexprlist ::= nexprlist COMMA expr */ - 253, /* (232) nexprlist ::= expr */ - 277, /* (233) paren_exprlist ::= */ - 277, /* (234) paren_exprlist ::= LP exprlist RP */ - 190, /* (235) cmd ::= createkw uniqueflag INDEX ifnotexists nm dbnm ON nm LP sortlist RP where_opt */ - 281, /* (236) uniqueflag ::= UNIQUE */ - 281, /* (237) uniqueflag ::= */ - 221, /* (238) eidlist_opt ::= */ - 221, /* (239) eidlist_opt ::= LP eidlist RP */ - 232, /* (240) eidlist ::= eidlist COMMA nm collate sortorder */ - 232, /* (241) eidlist ::= nm collate sortorder */ - 282, /* (242) collate ::= */ - 282, /* (243) collate ::= COLLATE ID|STRING */ - 190, /* (244) cmd ::= DROP INDEX ifexists fullname */ - 190, /* (245) cmd ::= VACUUM vinto */ - 190, /* (246) cmd ::= VACUUM nm vinto */ - 283, /* (247) vinto ::= INTO expr */ - 283, /* (248) vinto ::= */ - 190, /* (249) cmd ::= PRAGMA nm dbnm */ - 190, /* (250) cmd ::= PRAGMA nm dbnm EQ nmnum */ - 190, /* (251) cmd ::= PRAGMA nm dbnm LP nmnum RP */ - 190, /* (252) cmd ::= PRAGMA nm dbnm EQ minus_num */ - 190, /* (253) cmd ::= PRAGMA nm dbnm LP minus_num RP */ - 211, /* (254) plus_num ::= PLUS INTEGER|FLOAT */ - 212, /* (255) minus_num ::= MINUS INTEGER|FLOAT */ - 190, /* (256) cmd ::= createkw trigger_decl BEGIN trigger_cmd_list END */ - 285, /* (257) trigger_decl ::= temp TRIGGER ifnotexists nm dbnm trigger_time trigger_event ON fullname foreach_clause when_clause */ - 287, /* (258) trigger_time ::= BEFORE|AFTER */ - 287, /* (259) trigger_time ::= INSTEAD OF */ - 287, /* (260) trigger_time ::= */ - 288, /* (261) trigger_event ::= DELETE|INSERT */ - 288, /* (262) trigger_event ::= UPDATE */ - 288, /* (263) trigger_event ::= UPDATE OF idlist */ - 290, /* (264) when_clause ::= */ - 290, /* (265) when_clause ::= WHEN expr */ - 286, /* (266) trigger_cmd_list ::= trigger_cmd_list trigger_cmd SEMI */ - 286, /* (267) trigger_cmd_list ::= trigger_cmd SEMI */ - 292, /* (268) trnm ::= nm DOT nm */ - 293, /* (269) tridxby ::= INDEXED BY nm */ - 293, /* (270) tridxby ::= NOT INDEXED */ - 291, /* (271) trigger_cmd ::= UPDATE orconf trnm tridxby SET setlist from where_opt scanpt */ - 291, /* (272) trigger_cmd ::= scanpt insert_cmd INTO trnm idlist_opt select upsert scanpt */ - 291, /* (273) trigger_cmd ::= DELETE FROM trnm tridxby where_opt scanpt */ - 291, /* (274) trigger_cmd ::= scanpt select scanpt */ - 217, /* (275) expr ::= RAISE LP IGNORE RP */ - 217, /* (276) expr ::= RAISE LP raisetype COMMA nm RP */ - 236, /* (277) raisetype ::= ROLLBACK */ - 236, /* (278) raisetype ::= ABORT */ - 236, /* (279) raisetype ::= FAIL */ - 190, /* (280) cmd ::= DROP TRIGGER ifexists fullname */ - 190, /* (281) cmd ::= ATTACH database_kw_opt expr AS expr key_opt */ - 190, /* (282) cmd ::= DETACH database_kw_opt expr */ - 295, /* (283) key_opt ::= */ - 295, /* (284) key_opt ::= KEY expr */ - 190, /* (285) cmd ::= REINDEX */ - 190, /* (286) cmd ::= REINDEX nm dbnm */ - 190, /* (287) cmd ::= ANALYZE */ - 190, /* (288) cmd ::= ANALYZE nm dbnm */ - 190, /* (289) cmd ::= ALTER TABLE fullname RENAME TO nm */ - 190, /* (290) cmd ::= ALTER TABLE add_column_fullname ADD kwcolumn_opt columnname carglist */ - 190, /* (291) cmd ::= ALTER TABLE fullname DROP kwcolumn_opt nm */ - 296, /* (292) add_column_fullname ::= fullname */ - 190, /* (293) cmd ::= ALTER TABLE fullname RENAME kwcolumn_opt nm TO nm */ - 190, /* (294) cmd ::= create_vtab */ - 190, /* (295) cmd ::= create_vtab LP vtabarglist RP */ - 298, /* (296) create_vtab ::= createkw VIRTUAL TABLE ifnotexists nm dbnm USING nm */ - 300, /* (297) vtabarg ::= */ - 301, /* (298) vtabargtoken ::= ANY */ - 301, /* (299) vtabargtoken ::= lp anylist RP */ - 302, /* (300) lp ::= LP */ - 266, /* (301) with ::= WITH wqlist */ - 266, /* (302) with ::= WITH RECURSIVE wqlist */ - 305, /* (303) wqas ::= AS */ - 305, /* (304) wqas ::= AS MATERIALIZED */ - 305, /* (305) wqas ::= AS NOT MATERIALIZED */ - 304, /* (306) wqitem ::= nm eidlist_opt wqas LP select RP */ - 241, /* (307) wqlist ::= wqitem */ - 241, /* (308) wqlist ::= wqlist COMMA wqitem */ - 306, /* (309) windowdefn_list ::= windowdefn_list COMMA windowdefn */ - 307, /* (310) windowdefn ::= nm AS LP window RP */ - 308, /* (311) window ::= PARTITION BY nexprlist orderby_opt frame_opt */ - 308, /* (312) window ::= nm PARTITION BY nexprlist orderby_opt frame_opt */ - 308, /* (313) window ::= ORDER BY sortlist frame_opt */ - 308, /* (314) window ::= nm ORDER BY sortlist frame_opt */ - 308, /* (315) window ::= nm frame_opt */ - 309, /* (316) frame_opt ::= */ - 309, /* (317) frame_opt ::= range_or_rows frame_bound_s frame_exclude_opt */ - 309, /* (318) frame_opt ::= range_or_rows BETWEEN frame_bound_s AND frame_bound_e frame_exclude_opt */ - 313, /* (319) range_or_rows ::= RANGE|ROWS|GROUPS */ - 315, /* (320) frame_bound_s ::= frame_bound */ - 315, /* (321) frame_bound_s ::= UNBOUNDED PRECEDING */ - 316, /* (322) frame_bound_e ::= frame_bound */ - 316, /* (323) frame_bound_e ::= UNBOUNDED FOLLOWING */ - 314, /* (324) frame_bound ::= expr PRECEDING|FOLLOWING */ - 314, /* (325) frame_bound ::= CURRENT ROW */ - 317, /* (326) frame_exclude_opt ::= */ - 317, /* (327) frame_exclude_opt ::= EXCLUDE frame_exclude */ - 318, /* (328) frame_exclude ::= NO OTHERS */ - 318, /* (329) frame_exclude ::= CURRENT ROW */ - 318, /* (330) frame_exclude ::= GROUP|TIES */ - 251, /* (331) window_clause ::= WINDOW windowdefn_list */ - 273, /* (332) filter_over ::= filter_clause over_clause */ - 273, /* (333) filter_over ::= over_clause */ - 273, /* (334) filter_over ::= filter_clause */ - 312, /* (335) over_clause ::= OVER LP window RP */ - 312, /* (336) over_clause ::= OVER nm */ - 311, /* (337) filter_clause ::= FILTER LP WHERE expr RP */ - 185, /* (338) input ::= cmdlist */ - 186, /* (339) cmdlist ::= cmdlist ecmd */ - 186, /* (340) cmdlist ::= ecmd */ - 187, /* (341) ecmd ::= SEMI */ - 187, /* (342) ecmd ::= cmdx SEMI */ - 187, /* (343) ecmd ::= explain cmdx SEMI */ - 192, /* (344) trans_opt ::= */ - 192, /* (345) trans_opt ::= TRANSACTION */ - 192, /* (346) trans_opt ::= TRANSACTION nm */ - 194, /* (347) savepoint_opt ::= SAVEPOINT */ - 194, /* (348) savepoint_opt ::= */ - 190, /* (349) cmd ::= create_table create_table_args */ - 203, /* (350) table_option_set ::= table_option */ - 201, /* (351) columnlist ::= columnlist COMMA columnname carglist */ - 201, /* (352) columnlist ::= columnname carglist */ - 193, /* (353) nm ::= ID|INDEXED|JOIN_KW */ - 193, /* (354) nm ::= STRING */ - 208, /* (355) typetoken ::= typename */ - 209, /* (356) typename ::= ID|STRING */ - 210, /* (357) signed ::= plus_num */ - 210, /* (358) signed ::= minus_num */ - 207, /* (359) carglist ::= carglist ccons */ - 207, /* (360) carglist ::= */ - 215, /* (361) ccons ::= NULL onconf */ - 215, /* (362) ccons ::= GENERATED ALWAYS AS generated */ - 215, /* (363) ccons ::= AS generated */ - 202, /* (364) conslist_opt ::= COMMA conslist */ - 228, /* (365) conslist ::= conslist tconscomma tcons */ - 228, /* (366) conslist ::= tcons */ - 229, /* (367) tconscomma ::= */ - 233, /* (368) defer_subclause_opt ::= defer_subclause */ - 235, /* (369) resolvetype ::= raisetype */ - 239, /* (370) selectnowith ::= oneselect */ - 240, /* (371) oneselect ::= values */ - 254, /* (372) sclp ::= selcollist COMMA */ - 255, /* (373) as ::= ID|STRING */ - 264, /* (374) indexed_opt ::= indexed_by */ - 272, /* (375) returning ::= */ - 217, /* (376) expr ::= term */ - 274, /* (377) likeop ::= LIKE_KW|MATCH */ - 278, /* (378) case_operand ::= expr */ - 261, /* (379) exprlist ::= nexprlist */ - 284, /* (380) nmnum ::= plus_num */ - 284, /* (381) nmnum ::= nm */ - 284, /* (382) nmnum ::= ON */ - 284, /* (383) nmnum ::= DELETE */ - 284, /* (384) nmnum ::= DEFAULT */ - 211, /* (385) plus_num ::= INTEGER|FLOAT */ - 289, /* (386) foreach_clause ::= */ - 289, /* (387) foreach_clause ::= FOR EACH ROW */ - 292, /* (388) trnm ::= nm */ - 293, /* (389) tridxby ::= */ - 294, /* (390) database_kw_opt ::= DATABASE */ - 294, /* (391) database_kw_opt ::= */ - 297, /* (392) kwcolumn_opt ::= */ - 297, /* (393) kwcolumn_opt ::= COLUMNKW */ - 299, /* (394) vtabarglist ::= vtabarg */ - 299, /* (395) vtabarglist ::= vtabarglist COMMA vtabarg */ - 300, /* (396) vtabarg ::= vtabarg vtabargtoken */ - 303, /* (397) anylist ::= */ - 303, /* (398) anylist ::= anylist LP anylist RP */ - 303, /* (399) anylist ::= anylist ANY */ - 266, /* (400) with ::= */ - 306, /* (401) windowdefn_list ::= windowdefn */ - 308, /* (402) window ::= frame_opt */ + 190, /* (0) explain ::= EXPLAIN */ + 190, /* (1) explain ::= EXPLAIN QUERY PLAN */ + 189, /* (2) cmdx ::= cmd */ + 191, /* (3) cmd ::= BEGIN transtype trans_opt */ + 192, /* (4) transtype ::= */ + 192, /* (5) transtype ::= DEFERRED */ + 192, /* (6) transtype ::= IMMEDIATE */ + 192, /* (7) transtype ::= EXCLUSIVE */ + 191, /* (8) cmd ::= COMMIT|END trans_opt */ + 191, /* (9) cmd ::= ROLLBACK trans_opt */ + 191, /* (10) cmd ::= SAVEPOINT nm */ + 191, /* (11) cmd ::= RELEASE savepoint_opt nm */ + 191, /* (12) cmd ::= ROLLBACK trans_opt TO savepoint_opt nm */ + 196, /* (13) create_table ::= createkw temp TABLE ifnotexists nm dbnm */ + 198, /* (14) createkw ::= CREATE */ + 200, /* (15) ifnotexists ::= */ + 200, /* (16) ifnotexists ::= IF NOT EXISTS */ + 199, /* (17) temp ::= TEMP */ + 199, /* (18) temp ::= */ + 197, /* (19) create_table_args ::= LP columnlist conslist_opt RP table_option_set */ + 197, /* (20) create_table_args ::= AS select */ + 204, /* (21) table_option_set ::= */ + 204, /* (22) table_option_set ::= table_option_set COMMA table_option */ + 206, /* (23) table_option ::= WITHOUT nm */ + 206, /* (24) table_option ::= nm */ + 207, /* (25) columnname ::= nm typetoken */ + 209, /* (26) typetoken ::= */ + 209, /* (27) typetoken ::= typename LP signed RP */ + 209, /* (28) typetoken ::= typename LP signed COMMA signed RP */ + 210, /* (29) typename ::= typename ID|STRING */ + 214, /* (30) scanpt ::= */ + 215, /* (31) scantok ::= */ + 216, /* (32) ccons ::= CONSTRAINT nm */ + 216, /* (33) ccons ::= DEFAULT scantok term */ + 216, /* (34) ccons ::= DEFAULT LP expr RP */ + 216, /* (35) ccons ::= DEFAULT PLUS scantok term */ + 216, /* (36) ccons ::= DEFAULT MINUS scantok term */ + 216, /* (37) ccons ::= DEFAULT scantok ID|INDEXED */ + 216, /* (38) ccons ::= NOT NULL onconf */ + 216, /* (39) ccons ::= PRIMARY KEY sortorder onconf autoinc */ + 216, /* (40) ccons ::= UNIQUE onconf */ + 216, /* (41) ccons ::= CHECK LP expr RP */ + 216, /* (42) ccons ::= REFERENCES nm eidlist_opt refargs */ + 216, /* (43) ccons ::= defer_subclause */ + 216, /* (44) ccons ::= COLLATE ID|STRING */ + 225, /* (45) generated ::= LP expr RP */ + 225, /* (46) generated ::= LP expr RP ID */ + 221, /* (47) autoinc ::= */ + 221, /* (48) autoinc ::= AUTOINCR */ + 223, /* (49) refargs ::= */ + 223, /* (50) refargs ::= refargs refarg */ + 226, /* (51) refarg ::= MATCH nm */ + 226, /* (52) refarg ::= ON INSERT refact */ + 226, /* (53) refarg ::= ON DELETE refact */ + 226, /* (54) refarg ::= ON UPDATE refact */ + 227, /* (55) refact ::= SET NULL */ + 227, /* (56) refact ::= SET DEFAULT */ + 227, /* (57) refact ::= CASCADE */ + 227, /* (58) refact ::= RESTRICT */ + 227, /* (59) refact ::= NO ACTION */ + 224, /* (60) defer_subclause ::= NOT DEFERRABLE init_deferred_pred_opt */ + 224, /* (61) defer_subclause ::= DEFERRABLE init_deferred_pred_opt */ + 228, /* (62) init_deferred_pred_opt ::= */ + 228, /* (63) init_deferred_pred_opt ::= INITIALLY DEFERRED */ + 228, /* (64) init_deferred_pred_opt ::= INITIALLY IMMEDIATE */ + 203, /* (65) conslist_opt ::= */ + 230, /* (66) tconscomma ::= COMMA */ + 231, /* (67) tcons ::= CONSTRAINT nm */ + 231, /* (68) tcons ::= PRIMARY KEY LP sortlist autoinc RP onconf */ + 231, /* (69) tcons ::= UNIQUE LP sortlist RP onconf */ + 231, /* (70) tcons ::= CHECK LP expr RP onconf */ + 231, /* (71) tcons ::= FOREIGN KEY LP eidlist RP REFERENCES nm eidlist_opt refargs defer_subclause_opt */ + 234, /* (72) defer_subclause_opt ::= */ + 219, /* (73) onconf ::= */ + 219, /* (74) onconf ::= ON CONFLICT resolvetype */ + 235, /* (75) orconf ::= */ + 235, /* (76) orconf ::= OR resolvetype */ + 236, /* (77) resolvetype ::= IGNORE */ + 236, /* (78) resolvetype ::= REPLACE */ + 191, /* (79) cmd ::= DROP TABLE ifexists fullname */ + 238, /* (80) ifexists ::= IF EXISTS */ + 238, /* (81) ifexists ::= */ + 191, /* (82) cmd ::= createkw temp VIEW ifnotexists nm dbnm eidlist_opt AS select */ + 191, /* (83) cmd ::= DROP VIEW ifexists fullname */ + 191, /* (84) cmd ::= select */ + 205, /* (85) select ::= WITH wqlist selectnowith */ + 205, /* (86) select ::= WITH RECURSIVE wqlist selectnowith */ + 205, /* (87) select ::= selectnowith */ + 240, /* (88) selectnowith ::= selectnowith multiselect_op oneselect */ + 243, /* (89) multiselect_op ::= UNION */ + 243, /* (90) multiselect_op ::= UNION ALL */ + 243, /* (91) multiselect_op ::= EXCEPT|INTERSECT */ + 241, /* (92) oneselect ::= SELECT distinct selcollist from where_opt groupby_opt having_opt orderby_opt limit_opt */ + 241, /* (93) oneselect ::= SELECT distinct selcollist from where_opt groupby_opt having_opt window_clause orderby_opt limit_opt */ + 253, /* (94) values ::= VALUES LP nexprlist RP */ + 241, /* (95) oneselect ::= mvalues */ + 255, /* (96) mvalues ::= values COMMA LP nexprlist RP */ + 255, /* (97) mvalues ::= mvalues COMMA LP nexprlist RP */ + 244, /* (98) distinct ::= DISTINCT */ + 244, /* (99) distinct ::= ALL */ + 244, /* (100) distinct ::= */ + 256, /* (101) sclp ::= */ + 245, /* (102) selcollist ::= sclp scanpt expr scanpt as */ + 245, /* (103) selcollist ::= sclp scanpt STAR */ + 245, /* (104) selcollist ::= sclp scanpt nm DOT STAR */ + 257, /* (105) as ::= AS nm */ + 257, /* (106) as ::= */ + 246, /* (107) from ::= */ + 246, /* (108) from ::= FROM seltablist */ + 259, /* (109) stl_prefix ::= seltablist joinop */ + 259, /* (110) stl_prefix ::= */ + 258, /* (111) seltablist ::= stl_prefix nm dbnm as on_using */ + 258, /* (112) seltablist ::= stl_prefix nm dbnm as indexed_by on_using */ + 258, /* (113) seltablist ::= stl_prefix nm dbnm LP exprlist RP as on_using */ + 258, /* (114) seltablist ::= stl_prefix LP select RP as on_using */ + 258, /* (115) seltablist ::= stl_prefix LP seltablist RP as on_using */ + 201, /* (116) dbnm ::= */ + 201, /* (117) dbnm ::= DOT nm */ + 239, /* (118) fullname ::= nm */ + 239, /* (119) fullname ::= nm DOT nm */ + 264, /* (120) xfullname ::= nm */ + 264, /* (121) xfullname ::= nm DOT nm */ + 264, /* (122) xfullname ::= nm DOT nm AS nm */ + 264, /* (123) xfullname ::= nm AS nm */ + 260, /* (124) joinop ::= COMMA|JOIN */ + 260, /* (125) joinop ::= JOIN_KW JOIN */ + 260, /* (126) joinop ::= JOIN_KW nm JOIN */ + 260, /* (127) joinop ::= JOIN_KW nm nm JOIN */ + 261, /* (128) on_using ::= ON expr */ + 261, /* (129) on_using ::= USING LP idlist RP */ + 261, /* (130) on_using ::= */ + 266, /* (131) indexed_opt ::= */ + 262, /* (132) indexed_by ::= INDEXED BY nm */ + 262, /* (133) indexed_by ::= NOT INDEXED */ + 250, /* (134) orderby_opt ::= */ + 250, /* (135) orderby_opt ::= ORDER BY sortlist */ + 232, /* (136) sortlist ::= sortlist COMMA expr sortorder nulls */ + 232, /* (137) sortlist ::= expr sortorder nulls */ + 220, /* (138) sortorder ::= ASC */ + 220, /* (139) sortorder ::= DESC */ + 220, /* (140) sortorder ::= */ + 267, /* (141) nulls ::= NULLS FIRST */ + 267, /* (142) nulls ::= NULLS LAST */ + 267, /* (143) nulls ::= */ + 248, /* (144) groupby_opt ::= */ + 248, /* (145) groupby_opt ::= GROUP BY nexprlist */ + 249, /* (146) having_opt ::= */ + 249, /* (147) having_opt ::= HAVING expr */ + 251, /* (148) limit_opt ::= */ + 251, /* (149) limit_opt ::= LIMIT expr */ + 251, /* (150) limit_opt ::= LIMIT expr OFFSET expr */ + 251, /* (151) limit_opt ::= LIMIT expr COMMA expr */ + 191, /* (152) cmd ::= with DELETE FROM xfullname indexed_opt where_opt_ret */ + 247, /* (153) where_opt ::= */ + 247, /* (154) where_opt ::= WHERE expr */ + 269, /* (155) where_opt_ret ::= */ + 269, /* (156) where_opt_ret ::= WHERE expr */ + 269, /* (157) where_opt_ret ::= RETURNING selcollist */ + 269, /* (158) where_opt_ret ::= WHERE expr RETURNING selcollist */ + 191, /* (159) cmd ::= with UPDATE orconf xfullname indexed_opt SET setlist from where_opt_ret */ + 270, /* (160) setlist ::= setlist COMMA nm EQ expr */ + 270, /* (161) setlist ::= setlist COMMA LP idlist RP EQ expr */ + 270, /* (162) setlist ::= nm EQ expr */ + 270, /* (163) setlist ::= LP idlist RP EQ expr */ + 191, /* (164) cmd ::= with insert_cmd INTO xfullname idlist_opt select upsert */ + 191, /* (165) cmd ::= with insert_cmd INTO xfullname idlist_opt DEFAULT VALUES returning */ + 273, /* (166) upsert ::= */ + 273, /* (167) upsert ::= RETURNING selcollist */ + 273, /* (168) upsert ::= ON CONFLICT LP sortlist RP where_opt DO UPDATE SET setlist where_opt upsert */ + 273, /* (169) upsert ::= ON CONFLICT LP sortlist RP where_opt DO NOTHING upsert */ + 273, /* (170) upsert ::= ON CONFLICT DO NOTHING returning */ + 273, /* (171) upsert ::= ON CONFLICT DO UPDATE SET setlist where_opt returning */ + 274, /* (172) returning ::= RETURNING selcollist */ + 271, /* (173) insert_cmd ::= INSERT orconf */ + 271, /* (174) insert_cmd ::= REPLACE */ + 272, /* (175) idlist_opt ::= */ + 272, /* (176) idlist_opt ::= LP idlist RP */ + 265, /* (177) idlist ::= idlist COMMA nm */ + 265, /* (178) idlist ::= nm */ + 218, /* (179) expr ::= LP expr RP */ + 218, /* (180) expr ::= ID|INDEXED|JOIN_KW */ + 218, /* (181) expr ::= nm DOT nm */ + 218, /* (182) expr ::= nm DOT nm DOT nm */ + 217, /* (183) term ::= NULL|FLOAT|BLOB */ + 217, /* (184) term ::= STRING */ + 217, /* (185) term ::= INTEGER */ + 218, /* (186) expr ::= VARIABLE */ + 218, /* (187) expr ::= expr COLLATE ID|STRING */ + 218, /* (188) expr ::= CAST LP expr AS typetoken RP */ + 218, /* (189) expr ::= ID|INDEXED|JOIN_KW LP distinct exprlist RP */ + 218, /* (190) expr ::= ID|INDEXED|JOIN_KW LP distinct exprlist ORDER BY sortlist RP */ + 218, /* (191) expr ::= ID|INDEXED|JOIN_KW LP STAR RP */ + 218, /* (192) expr ::= ID|INDEXED|JOIN_KW LP distinct exprlist RP filter_over */ + 218, /* (193) expr ::= ID|INDEXED|JOIN_KW LP distinct exprlist ORDER BY sortlist RP filter_over */ + 218, /* (194) expr ::= ID|INDEXED|JOIN_KW LP STAR RP filter_over */ + 217, /* (195) term ::= CTIME_KW */ + 218, /* (196) expr ::= LP nexprlist COMMA expr RP */ + 218, /* (197) expr ::= expr AND expr */ + 218, /* (198) expr ::= expr OR expr */ + 218, /* (199) expr ::= expr LT|GT|GE|LE expr */ + 218, /* (200) expr ::= expr EQ|NE expr */ + 218, /* (201) expr ::= expr BITAND|BITOR|LSHIFT|RSHIFT expr */ + 218, /* (202) expr ::= expr PLUS|MINUS expr */ + 218, /* (203) expr ::= expr STAR|SLASH|REM expr */ + 218, /* (204) expr ::= expr CONCAT expr */ + 276, /* (205) likeop ::= NOT LIKE_KW|MATCH */ + 218, /* (206) expr ::= expr likeop expr */ + 218, /* (207) expr ::= expr likeop expr ESCAPE expr */ + 218, /* (208) expr ::= expr ISNULL|NOTNULL */ + 218, /* (209) expr ::= expr NOT NULL */ + 218, /* (210) expr ::= expr IS expr */ + 218, /* (211) expr ::= expr IS NOT expr */ + 218, /* (212) expr ::= expr IS NOT DISTINCT FROM expr */ + 218, /* (213) expr ::= expr IS DISTINCT FROM expr */ + 218, /* (214) expr ::= NOT expr */ + 218, /* (215) expr ::= BITNOT expr */ + 218, /* (216) expr ::= PLUS|MINUS expr */ + 218, /* (217) expr ::= expr PTR expr */ + 277, /* (218) between_op ::= BETWEEN */ + 277, /* (219) between_op ::= NOT BETWEEN */ + 218, /* (220) expr ::= expr between_op expr AND expr */ + 278, /* (221) in_op ::= IN */ + 278, /* (222) in_op ::= NOT IN */ + 218, /* (223) expr ::= expr in_op LP exprlist RP */ + 218, /* (224) expr ::= LP select RP */ + 218, /* (225) expr ::= expr in_op LP select RP */ + 218, /* (226) expr ::= expr in_op nm dbnm paren_exprlist */ + 218, /* (227) expr ::= EXISTS LP select RP */ + 218, /* (228) expr ::= CASE case_operand case_exprlist case_else END */ + 281, /* (229) case_exprlist ::= case_exprlist WHEN expr THEN expr */ + 281, /* (230) case_exprlist ::= WHEN expr THEN expr */ + 282, /* (231) case_else ::= ELSE expr */ + 282, /* (232) case_else ::= */ + 280, /* (233) case_operand ::= */ + 263, /* (234) exprlist ::= */ + 254, /* (235) nexprlist ::= nexprlist COMMA expr */ + 254, /* (236) nexprlist ::= expr */ + 279, /* (237) paren_exprlist ::= */ + 279, /* (238) paren_exprlist ::= LP exprlist RP */ + 191, /* (239) cmd ::= createkw uniqueflag INDEX ifnotexists nm dbnm ON nm LP sortlist RP where_opt */ + 283, /* (240) uniqueflag ::= UNIQUE */ + 283, /* (241) uniqueflag ::= */ + 222, /* (242) eidlist_opt ::= */ + 222, /* (243) eidlist_opt ::= LP eidlist RP */ + 233, /* (244) eidlist ::= eidlist COMMA nm collate sortorder */ + 233, /* (245) eidlist ::= nm collate sortorder */ + 284, /* (246) collate ::= */ + 284, /* (247) collate ::= COLLATE ID|STRING */ + 191, /* (248) cmd ::= DROP INDEX ifexists fullname */ + 191, /* (249) cmd ::= VACUUM vinto */ + 191, /* (250) cmd ::= VACUUM nm vinto */ + 285, /* (251) vinto ::= INTO expr */ + 285, /* (252) vinto ::= */ + 191, /* (253) cmd ::= PRAGMA nm dbnm */ + 191, /* (254) cmd ::= PRAGMA nm dbnm EQ nmnum */ + 191, /* (255) cmd ::= PRAGMA nm dbnm LP nmnum RP */ + 191, /* (256) cmd ::= PRAGMA nm dbnm EQ minus_num */ + 191, /* (257) cmd ::= PRAGMA nm dbnm LP minus_num RP */ + 212, /* (258) plus_num ::= PLUS INTEGER|FLOAT */ + 213, /* (259) minus_num ::= MINUS INTEGER|FLOAT */ + 191, /* (260) cmd ::= createkw trigger_decl BEGIN trigger_cmd_list END */ + 287, /* (261) trigger_decl ::= temp TRIGGER ifnotexists nm dbnm trigger_time trigger_event ON fullname foreach_clause when_clause */ + 289, /* (262) trigger_time ::= BEFORE|AFTER */ + 289, /* (263) trigger_time ::= INSTEAD OF */ + 289, /* (264) trigger_time ::= */ + 290, /* (265) trigger_event ::= DELETE|INSERT */ + 290, /* (266) trigger_event ::= UPDATE */ + 290, /* (267) trigger_event ::= UPDATE OF idlist */ + 292, /* (268) when_clause ::= */ + 292, /* (269) when_clause ::= WHEN expr */ + 288, /* (270) trigger_cmd_list ::= trigger_cmd_list trigger_cmd SEMI */ + 288, /* (271) trigger_cmd_list ::= trigger_cmd SEMI */ + 294, /* (272) trnm ::= nm DOT nm */ + 295, /* (273) tridxby ::= INDEXED BY nm */ + 295, /* (274) tridxby ::= NOT INDEXED */ + 293, /* (275) trigger_cmd ::= UPDATE orconf trnm tridxby SET setlist from where_opt scanpt */ + 293, /* (276) trigger_cmd ::= scanpt insert_cmd INTO trnm idlist_opt select upsert scanpt */ + 293, /* (277) trigger_cmd ::= DELETE FROM trnm tridxby where_opt scanpt */ + 293, /* (278) trigger_cmd ::= scanpt select scanpt */ + 218, /* (279) expr ::= RAISE LP IGNORE RP */ + 218, /* (280) expr ::= RAISE LP raisetype COMMA nm RP */ + 237, /* (281) raisetype ::= ROLLBACK */ + 237, /* (282) raisetype ::= ABORT */ + 237, /* (283) raisetype ::= FAIL */ + 191, /* (284) cmd ::= DROP TRIGGER ifexists fullname */ + 191, /* (285) cmd ::= ATTACH database_kw_opt expr AS expr key_opt */ + 191, /* (286) cmd ::= DETACH database_kw_opt expr */ + 297, /* (287) key_opt ::= */ + 297, /* (288) key_opt ::= KEY expr */ + 191, /* (289) cmd ::= REINDEX */ + 191, /* (290) cmd ::= REINDEX nm dbnm */ + 191, /* (291) cmd ::= ANALYZE */ + 191, /* (292) cmd ::= ANALYZE nm dbnm */ + 191, /* (293) cmd ::= ALTER TABLE fullname RENAME TO nm */ + 191, /* (294) cmd ::= ALTER TABLE add_column_fullname ADD kwcolumn_opt columnname carglist */ + 191, /* (295) cmd ::= ALTER TABLE fullname DROP kwcolumn_opt nm */ + 298, /* (296) add_column_fullname ::= fullname */ + 191, /* (297) cmd ::= ALTER TABLE fullname RENAME kwcolumn_opt nm TO nm */ + 191, /* (298) cmd ::= create_vtab */ + 191, /* (299) cmd ::= create_vtab LP vtabarglist RP */ + 300, /* (300) create_vtab ::= createkw VIRTUAL TABLE ifnotexists nm dbnm USING nm */ + 302, /* (301) vtabarg ::= */ + 303, /* (302) vtabargtoken ::= ANY */ + 303, /* (303) vtabargtoken ::= lp anylist RP */ + 304, /* (304) lp ::= LP */ + 268, /* (305) with ::= WITH wqlist */ + 268, /* (306) with ::= WITH RECURSIVE wqlist */ + 307, /* (307) wqas ::= AS */ + 307, /* (308) wqas ::= AS MATERIALIZED */ + 307, /* (309) wqas ::= AS NOT MATERIALIZED */ + 306, /* (310) wqitem ::= withnm eidlist_opt wqas LP select RP */ + 308, /* (311) withnm ::= nm */ + 242, /* (312) wqlist ::= wqitem */ + 242, /* (313) wqlist ::= wqlist COMMA wqitem */ + 309, /* (314) windowdefn_list ::= windowdefn_list COMMA windowdefn */ + 310, /* (315) windowdefn ::= nm AS LP window RP */ + 311, /* (316) window ::= PARTITION BY nexprlist orderby_opt frame_opt */ + 311, /* (317) window ::= nm PARTITION BY nexprlist orderby_opt frame_opt */ + 311, /* (318) window ::= ORDER BY sortlist frame_opt */ + 311, /* (319) window ::= nm ORDER BY sortlist frame_opt */ + 311, /* (320) window ::= nm frame_opt */ + 312, /* (321) frame_opt ::= */ + 312, /* (322) frame_opt ::= range_or_rows frame_bound_s frame_exclude_opt */ + 312, /* (323) frame_opt ::= range_or_rows BETWEEN frame_bound_s AND frame_bound_e frame_exclude_opt */ + 316, /* (324) range_or_rows ::= RANGE|ROWS|GROUPS */ + 318, /* (325) frame_bound_s ::= frame_bound */ + 318, /* (326) frame_bound_s ::= UNBOUNDED PRECEDING */ + 319, /* (327) frame_bound_e ::= frame_bound */ + 319, /* (328) frame_bound_e ::= UNBOUNDED FOLLOWING */ + 317, /* (329) frame_bound ::= expr PRECEDING|FOLLOWING */ + 317, /* (330) frame_bound ::= CURRENT ROW */ + 320, /* (331) frame_exclude_opt ::= */ + 320, /* (332) frame_exclude_opt ::= EXCLUDE frame_exclude */ + 321, /* (333) frame_exclude ::= NO OTHERS */ + 321, /* (334) frame_exclude ::= CURRENT ROW */ + 321, /* (335) frame_exclude ::= GROUP|TIES */ + 252, /* (336) window_clause ::= WINDOW windowdefn_list */ + 275, /* (337) filter_over ::= filter_clause over_clause */ + 275, /* (338) filter_over ::= over_clause */ + 275, /* (339) filter_over ::= filter_clause */ + 315, /* (340) over_clause ::= OVER LP window RP */ + 315, /* (341) over_clause ::= OVER nm */ + 314, /* (342) filter_clause ::= FILTER LP WHERE expr RP */ + 217, /* (343) term ::= QNUMBER */ + 186, /* (344) input ::= cmdlist */ + 187, /* (345) cmdlist ::= cmdlist ecmd */ + 187, /* (346) cmdlist ::= ecmd */ + 188, /* (347) ecmd ::= SEMI */ + 188, /* (348) ecmd ::= cmdx SEMI */ + 188, /* (349) ecmd ::= explain cmdx SEMI */ + 193, /* (350) trans_opt ::= */ + 193, /* (351) trans_opt ::= TRANSACTION */ + 193, /* (352) trans_opt ::= TRANSACTION nm */ + 195, /* (353) savepoint_opt ::= SAVEPOINT */ + 195, /* (354) savepoint_opt ::= */ + 191, /* (355) cmd ::= create_table create_table_args */ + 204, /* (356) table_option_set ::= table_option */ + 202, /* (357) columnlist ::= columnlist COMMA columnname carglist */ + 202, /* (358) columnlist ::= columnname carglist */ + 194, /* (359) nm ::= ID|INDEXED|JOIN_KW */ + 194, /* (360) nm ::= STRING */ + 209, /* (361) typetoken ::= typename */ + 210, /* (362) typename ::= ID|STRING */ + 211, /* (363) signed ::= plus_num */ + 211, /* (364) signed ::= minus_num */ + 208, /* (365) carglist ::= carglist ccons */ + 208, /* (366) carglist ::= */ + 216, /* (367) ccons ::= NULL onconf */ + 216, /* (368) ccons ::= GENERATED ALWAYS AS generated */ + 216, /* (369) ccons ::= AS generated */ + 203, /* (370) conslist_opt ::= COMMA conslist */ + 229, /* (371) conslist ::= conslist tconscomma tcons */ + 229, /* (372) conslist ::= tcons */ + 230, /* (373) tconscomma ::= */ + 234, /* (374) defer_subclause_opt ::= defer_subclause */ + 236, /* (375) resolvetype ::= raisetype */ + 240, /* (376) selectnowith ::= oneselect */ + 241, /* (377) oneselect ::= values */ + 256, /* (378) sclp ::= selcollist COMMA */ + 257, /* (379) as ::= ID|STRING */ + 266, /* (380) indexed_opt ::= indexed_by */ + 274, /* (381) returning ::= */ + 218, /* (382) expr ::= term */ + 276, /* (383) likeop ::= LIKE_KW|MATCH */ + 280, /* (384) case_operand ::= expr */ + 263, /* (385) exprlist ::= nexprlist */ + 286, /* (386) nmnum ::= plus_num */ + 286, /* (387) nmnum ::= nm */ + 286, /* (388) nmnum ::= ON */ + 286, /* (389) nmnum ::= DELETE */ + 286, /* (390) nmnum ::= DEFAULT */ + 212, /* (391) plus_num ::= INTEGER|FLOAT */ + 291, /* (392) foreach_clause ::= */ + 291, /* (393) foreach_clause ::= FOR EACH ROW */ + 294, /* (394) trnm ::= nm */ + 295, /* (395) tridxby ::= */ + 296, /* (396) database_kw_opt ::= DATABASE */ + 296, /* (397) database_kw_opt ::= */ + 299, /* (398) kwcolumn_opt ::= */ + 299, /* (399) kwcolumn_opt ::= COLUMNKW */ + 301, /* (400) vtabarglist ::= vtabarg */ + 301, /* (401) vtabarglist ::= vtabarglist COMMA vtabarg */ + 302, /* (402) vtabarg ::= vtabarg vtabargtoken */ + 305, /* (403) anylist ::= */ + 305, /* (404) anylist ::= anylist LP anylist RP */ + 305, /* (405) anylist ::= anylist ANY */ + 268, /* (406) with ::= */ + 309, /* (407) windowdefn_list ::= windowdefn */ + 311, /* (408) window ::= frame_opt */ }; /* For rule J, yyRuleInfoNRhs[J] contains the negative of the number @@ -172453,314 +175761,320 @@ static const signed char yyRuleInfoNRhs[] = { -9, /* (92) oneselect ::= SELECT distinct selcollist from where_opt groupby_opt having_opt orderby_opt limit_opt */ -10, /* (93) oneselect ::= SELECT distinct selcollist from where_opt groupby_opt having_opt window_clause orderby_opt limit_opt */ -4, /* (94) values ::= VALUES LP nexprlist RP */ - -5, /* (95) values ::= values COMMA LP nexprlist RP */ - -1, /* (96) distinct ::= DISTINCT */ - -1, /* (97) distinct ::= ALL */ - 0, /* (98) distinct ::= */ - 0, /* (99) sclp ::= */ - -5, /* (100) selcollist ::= sclp scanpt expr scanpt as */ - -3, /* (101) selcollist ::= sclp scanpt STAR */ - -5, /* (102) selcollist ::= sclp scanpt nm DOT STAR */ - -2, /* (103) as ::= AS nm */ - 0, /* (104) as ::= */ - 0, /* (105) from ::= */ - -2, /* (106) from ::= FROM seltablist */ - -2, /* (107) stl_prefix ::= seltablist joinop */ - 0, /* (108) stl_prefix ::= */ - -5, /* (109) seltablist ::= stl_prefix nm dbnm as on_using */ - -6, /* (110) seltablist ::= stl_prefix nm dbnm as indexed_by on_using */ - -8, /* (111) seltablist ::= stl_prefix nm dbnm LP exprlist RP as on_using */ - -6, /* (112) seltablist ::= stl_prefix LP select RP as on_using */ - -6, /* (113) seltablist ::= stl_prefix LP seltablist RP as on_using */ - 0, /* (114) dbnm ::= */ - -2, /* (115) dbnm ::= DOT nm */ - -1, /* (116) fullname ::= nm */ - -3, /* (117) fullname ::= nm DOT nm */ - -1, /* (118) xfullname ::= nm */ - -3, /* (119) xfullname ::= nm DOT nm */ - -5, /* (120) xfullname ::= nm DOT nm AS nm */ - -3, /* (121) xfullname ::= nm AS nm */ - -1, /* (122) joinop ::= COMMA|JOIN */ - -2, /* (123) joinop ::= JOIN_KW JOIN */ - -3, /* (124) joinop ::= JOIN_KW nm JOIN */ - -4, /* (125) joinop ::= JOIN_KW nm nm JOIN */ - -2, /* (126) on_using ::= ON expr */ - -4, /* (127) on_using ::= USING LP idlist RP */ - 0, /* (128) on_using ::= */ - 0, /* (129) indexed_opt ::= */ - -3, /* (130) indexed_by ::= INDEXED BY nm */ - -2, /* (131) indexed_by ::= NOT INDEXED */ - 0, /* (132) orderby_opt ::= */ - -3, /* (133) orderby_opt ::= ORDER BY sortlist */ - -5, /* (134) sortlist ::= sortlist COMMA expr sortorder nulls */ - -3, /* (135) sortlist ::= expr sortorder nulls */ - -1, /* (136) sortorder ::= ASC */ - -1, /* (137) sortorder ::= DESC */ - 0, /* (138) sortorder ::= */ - -2, /* (139) nulls ::= NULLS FIRST */ - -2, /* (140) nulls ::= NULLS LAST */ - 0, /* (141) nulls ::= */ - 0, /* (142) groupby_opt ::= */ - -3, /* (143) groupby_opt ::= GROUP BY nexprlist */ - 0, /* (144) having_opt ::= */ - -2, /* (145) having_opt ::= HAVING expr */ - 0, /* (146) limit_opt ::= */ - -2, /* (147) limit_opt ::= LIMIT expr */ - -4, /* (148) limit_opt ::= LIMIT expr OFFSET expr */ - -4, /* (149) limit_opt ::= LIMIT expr COMMA expr */ - -6, /* (150) cmd ::= with DELETE FROM xfullname indexed_opt where_opt_ret */ - 0, /* (151) where_opt ::= */ - -2, /* (152) where_opt ::= WHERE expr */ - 0, /* (153) where_opt_ret ::= */ - -2, /* (154) where_opt_ret ::= WHERE expr */ - -2, /* (155) where_opt_ret ::= RETURNING selcollist */ - -4, /* (156) where_opt_ret ::= WHERE expr RETURNING selcollist */ - -9, /* (157) cmd ::= with UPDATE orconf xfullname indexed_opt SET setlist from where_opt_ret */ - -5, /* (158) setlist ::= setlist COMMA nm EQ expr */ - -7, /* (159) setlist ::= setlist COMMA LP idlist RP EQ expr */ - -3, /* (160) setlist ::= nm EQ expr */ - -5, /* (161) setlist ::= LP idlist RP EQ expr */ - -7, /* (162) cmd ::= with insert_cmd INTO xfullname idlist_opt select upsert */ - -8, /* (163) cmd ::= with insert_cmd INTO xfullname idlist_opt DEFAULT VALUES returning */ - 0, /* (164) upsert ::= */ - -2, /* (165) upsert ::= RETURNING selcollist */ - -12, /* (166) upsert ::= ON CONFLICT LP sortlist RP where_opt DO UPDATE SET setlist where_opt upsert */ - -9, /* (167) upsert ::= ON CONFLICT LP sortlist RP where_opt DO NOTHING upsert */ - -5, /* (168) upsert ::= ON CONFLICT DO NOTHING returning */ - -8, /* (169) upsert ::= ON CONFLICT DO UPDATE SET setlist where_opt returning */ - -2, /* (170) returning ::= RETURNING selcollist */ - -2, /* (171) insert_cmd ::= INSERT orconf */ - -1, /* (172) insert_cmd ::= REPLACE */ - 0, /* (173) idlist_opt ::= */ - -3, /* (174) idlist_opt ::= LP idlist RP */ - -3, /* (175) idlist ::= idlist COMMA nm */ - -1, /* (176) idlist ::= nm */ - -3, /* (177) expr ::= LP expr RP */ - -1, /* (178) expr ::= ID|INDEXED|JOIN_KW */ - -3, /* (179) expr ::= nm DOT nm */ - -5, /* (180) expr ::= nm DOT nm DOT nm */ - -1, /* (181) term ::= NULL|FLOAT|BLOB */ - -1, /* (182) term ::= STRING */ - -1, /* (183) term ::= INTEGER */ - -1, /* (184) expr ::= VARIABLE */ - -3, /* (185) expr ::= expr COLLATE ID|STRING */ - -6, /* (186) expr ::= CAST LP expr AS typetoken RP */ - -5, /* (187) expr ::= ID|INDEXED|JOIN_KW LP distinct exprlist RP */ - -4, /* (188) expr ::= ID|INDEXED|JOIN_KW LP STAR RP */ - -6, /* (189) expr ::= ID|INDEXED|JOIN_KW LP distinct exprlist RP filter_over */ - -5, /* (190) expr ::= ID|INDEXED|JOIN_KW LP STAR RP filter_over */ - -1, /* (191) term ::= CTIME_KW */ - -5, /* (192) expr ::= LP nexprlist COMMA expr RP */ - -3, /* (193) expr ::= expr AND expr */ - -3, /* (194) expr ::= expr OR expr */ - -3, /* (195) expr ::= expr LT|GT|GE|LE expr */ - -3, /* (196) expr ::= expr EQ|NE expr */ - -3, /* (197) expr ::= expr BITAND|BITOR|LSHIFT|RSHIFT expr */ - -3, /* (198) expr ::= expr PLUS|MINUS expr */ - -3, /* (199) expr ::= expr STAR|SLASH|REM expr */ - -3, /* (200) expr ::= expr CONCAT expr */ - -2, /* (201) likeop ::= NOT LIKE_KW|MATCH */ - -3, /* (202) expr ::= expr likeop expr */ - -5, /* (203) expr ::= expr likeop expr ESCAPE expr */ - -2, /* (204) expr ::= expr ISNULL|NOTNULL */ - -3, /* (205) expr ::= expr NOT NULL */ - -3, /* (206) expr ::= expr IS expr */ - -4, /* (207) expr ::= expr IS NOT expr */ - -6, /* (208) expr ::= expr IS NOT DISTINCT FROM expr */ - -5, /* (209) expr ::= expr IS DISTINCT FROM expr */ - -2, /* (210) expr ::= NOT expr */ - -2, /* (211) expr ::= BITNOT expr */ - -2, /* (212) expr ::= PLUS|MINUS expr */ - -3, /* (213) expr ::= expr PTR expr */ - -1, /* (214) between_op ::= BETWEEN */ - -2, /* (215) between_op ::= NOT BETWEEN */ - -5, /* (216) expr ::= expr between_op expr AND expr */ - -1, /* (217) in_op ::= IN */ - -2, /* (218) in_op ::= NOT IN */ - -5, /* (219) expr ::= expr in_op LP exprlist RP */ - -3, /* (220) expr ::= LP select RP */ - -5, /* (221) expr ::= expr in_op LP select RP */ - -5, /* (222) expr ::= expr in_op nm dbnm paren_exprlist */ - -4, /* (223) expr ::= EXISTS LP select RP */ - -5, /* (224) expr ::= CASE case_operand case_exprlist case_else END */ - -5, /* (225) case_exprlist ::= case_exprlist WHEN expr THEN expr */ - -4, /* (226) case_exprlist ::= WHEN expr THEN expr */ - -2, /* (227) case_else ::= ELSE expr */ - 0, /* (228) case_else ::= */ - 0, /* (229) case_operand ::= */ - 0, /* (230) exprlist ::= */ - -3, /* (231) nexprlist ::= nexprlist COMMA expr */ - -1, /* (232) nexprlist ::= expr */ - 0, /* (233) paren_exprlist ::= */ - -3, /* (234) paren_exprlist ::= LP exprlist RP */ - -12, /* (235) cmd ::= createkw uniqueflag INDEX ifnotexists nm dbnm ON nm LP sortlist RP where_opt */ - -1, /* (236) uniqueflag ::= UNIQUE */ - 0, /* (237) uniqueflag ::= */ - 0, /* (238) eidlist_opt ::= */ - -3, /* (239) eidlist_opt ::= LP eidlist RP */ - -5, /* (240) eidlist ::= eidlist COMMA nm collate sortorder */ - -3, /* (241) eidlist ::= nm collate sortorder */ - 0, /* (242) collate ::= */ - -2, /* (243) collate ::= COLLATE ID|STRING */ - -4, /* (244) cmd ::= DROP INDEX ifexists fullname */ - -2, /* (245) cmd ::= VACUUM vinto */ - -3, /* (246) cmd ::= VACUUM nm vinto */ - -2, /* (247) vinto ::= INTO expr */ - 0, /* (248) vinto ::= */ - -3, /* (249) cmd ::= PRAGMA nm dbnm */ - -5, /* (250) cmd ::= PRAGMA nm dbnm EQ nmnum */ - -6, /* (251) cmd ::= PRAGMA nm dbnm LP nmnum RP */ - -5, /* (252) cmd ::= PRAGMA nm dbnm EQ minus_num */ - -6, /* (253) cmd ::= PRAGMA nm dbnm LP minus_num RP */ - -2, /* (254) plus_num ::= PLUS INTEGER|FLOAT */ - -2, /* (255) minus_num ::= MINUS INTEGER|FLOAT */ - -5, /* (256) cmd ::= createkw trigger_decl BEGIN trigger_cmd_list END */ - -11, /* (257) trigger_decl ::= temp TRIGGER ifnotexists nm dbnm trigger_time trigger_event ON fullname foreach_clause when_clause */ - -1, /* (258) trigger_time ::= BEFORE|AFTER */ - -2, /* (259) trigger_time ::= INSTEAD OF */ - 0, /* (260) trigger_time ::= */ - -1, /* (261) trigger_event ::= DELETE|INSERT */ - -1, /* (262) trigger_event ::= UPDATE */ - -3, /* (263) trigger_event ::= UPDATE OF idlist */ - 0, /* (264) when_clause ::= */ - -2, /* (265) when_clause ::= WHEN expr */ - -3, /* (266) trigger_cmd_list ::= trigger_cmd_list trigger_cmd SEMI */ - -2, /* (267) trigger_cmd_list ::= trigger_cmd SEMI */ - -3, /* (268) trnm ::= nm DOT nm */ - -3, /* (269) tridxby ::= INDEXED BY nm */ - -2, /* (270) tridxby ::= NOT INDEXED */ - -9, /* (271) trigger_cmd ::= UPDATE orconf trnm tridxby SET setlist from where_opt scanpt */ - -8, /* (272) trigger_cmd ::= scanpt insert_cmd INTO trnm idlist_opt select upsert scanpt */ - -6, /* (273) trigger_cmd ::= DELETE FROM trnm tridxby where_opt scanpt */ - -3, /* (274) trigger_cmd ::= scanpt select scanpt */ - -4, /* (275) expr ::= RAISE LP IGNORE RP */ - -6, /* (276) expr ::= RAISE LP raisetype COMMA nm RP */ - -1, /* (277) raisetype ::= ROLLBACK */ - -1, /* (278) raisetype ::= ABORT */ - -1, /* (279) raisetype ::= FAIL */ - -4, /* (280) cmd ::= DROP TRIGGER ifexists fullname */ - -6, /* (281) cmd ::= ATTACH database_kw_opt expr AS expr key_opt */ - -3, /* (282) cmd ::= DETACH database_kw_opt expr */ - 0, /* (283) key_opt ::= */ - -2, /* (284) key_opt ::= KEY expr */ - -1, /* (285) cmd ::= REINDEX */ - -3, /* (286) cmd ::= REINDEX nm dbnm */ - -1, /* (287) cmd ::= ANALYZE */ - -3, /* (288) cmd ::= ANALYZE nm dbnm */ - -6, /* (289) cmd ::= ALTER TABLE fullname RENAME TO nm */ - -7, /* (290) cmd ::= ALTER TABLE add_column_fullname ADD kwcolumn_opt columnname carglist */ - -6, /* (291) cmd ::= ALTER TABLE fullname DROP kwcolumn_opt nm */ - -1, /* (292) add_column_fullname ::= fullname */ - -8, /* (293) cmd ::= ALTER TABLE fullname RENAME kwcolumn_opt nm TO nm */ - -1, /* (294) cmd ::= create_vtab */ - -4, /* (295) cmd ::= create_vtab LP vtabarglist RP */ - -8, /* (296) create_vtab ::= createkw VIRTUAL TABLE ifnotexists nm dbnm USING nm */ - 0, /* (297) vtabarg ::= */ - -1, /* (298) vtabargtoken ::= ANY */ - -3, /* (299) vtabargtoken ::= lp anylist RP */ - -1, /* (300) lp ::= LP */ - -2, /* (301) with ::= WITH wqlist */ - -3, /* (302) with ::= WITH RECURSIVE wqlist */ - -1, /* (303) wqas ::= AS */ - -2, /* (304) wqas ::= AS MATERIALIZED */ - -3, /* (305) wqas ::= AS NOT MATERIALIZED */ - -6, /* (306) wqitem ::= nm eidlist_opt wqas LP select RP */ - -1, /* (307) wqlist ::= wqitem */ - -3, /* (308) wqlist ::= wqlist COMMA wqitem */ - -3, /* (309) windowdefn_list ::= windowdefn_list COMMA windowdefn */ - -5, /* (310) windowdefn ::= nm AS LP window RP */ - -5, /* (311) window ::= PARTITION BY nexprlist orderby_opt frame_opt */ - -6, /* (312) window ::= nm PARTITION BY nexprlist orderby_opt frame_opt */ - -4, /* (313) window ::= ORDER BY sortlist frame_opt */ - -5, /* (314) window ::= nm ORDER BY sortlist frame_opt */ - -2, /* (315) window ::= nm frame_opt */ - 0, /* (316) frame_opt ::= */ - -3, /* (317) frame_opt ::= range_or_rows frame_bound_s frame_exclude_opt */ - -6, /* (318) frame_opt ::= range_or_rows BETWEEN frame_bound_s AND frame_bound_e frame_exclude_opt */ - -1, /* (319) range_or_rows ::= RANGE|ROWS|GROUPS */ - -1, /* (320) frame_bound_s ::= frame_bound */ - -2, /* (321) frame_bound_s ::= UNBOUNDED PRECEDING */ - -1, /* (322) frame_bound_e ::= frame_bound */ - -2, /* (323) frame_bound_e ::= UNBOUNDED FOLLOWING */ - -2, /* (324) frame_bound ::= expr PRECEDING|FOLLOWING */ - -2, /* (325) frame_bound ::= CURRENT ROW */ - 0, /* (326) frame_exclude_opt ::= */ - -2, /* (327) frame_exclude_opt ::= EXCLUDE frame_exclude */ - -2, /* (328) frame_exclude ::= NO OTHERS */ - -2, /* (329) frame_exclude ::= CURRENT ROW */ - -1, /* (330) frame_exclude ::= GROUP|TIES */ - -2, /* (331) window_clause ::= WINDOW windowdefn_list */ - -2, /* (332) filter_over ::= filter_clause over_clause */ - -1, /* (333) filter_over ::= over_clause */ - -1, /* (334) filter_over ::= filter_clause */ - -4, /* (335) over_clause ::= OVER LP window RP */ - -2, /* (336) over_clause ::= OVER nm */ - -5, /* (337) filter_clause ::= FILTER LP WHERE expr RP */ - -1, /* (338) input ::= cmdlist */ - -2, /* (339) cmdlist ::= cmdlist ecmd */ - -1, /* (340) cmdlist ::= ecmd */ - -1, /* (341) ecmd ::= SEMI */ - -2, /* (342) ecmd ::= cmdx SEMI */ - -3, /* (343) ecmd ::= explain cmdx SEMI */ - 0, /* (344) trans_opt ::= */ - -1, /* (345) trans_opt ::= TRANSACTION */ - -2, /* (346) trans_opt ::= TRANSACTION nm */ - -1, /* (347) savepoint_opt ::= SAVEPOINT */ - 0, /* (348) savepoint_opt ::= */ - -2, /* (349) cmd ::= create_table create_table_args */ - -1, /* (350) table_option_set ::= table_option */ - -4, /* (351) columnlist ::= columnlist COMMA columnname carglist */ - -2, /* (352) columnlist ::= columnname carglist */ - -1, /* (353) nm ::= ID|INDEXED|JOIN_KW */ - -1, /* (354) nm ::= STRING */ - -1, /* (355) typetoken ::= typename */ - -1, /* (356) typename ::= ID|STRING */ - -1, /* (357) signed ::= plus_num */ - -1, /* (358) signed ::= minus_num */ - -2, /* (359) carglist ::= carglist ccons */ - 0, /* (360) carglist ::= */ - -2, /* (361) ccons ::= NULL onconf */ - -4, /* (362) ccons ::= GENERATED ALWAYS AS generated */ - -2, /* (363) ccons ::= AS generated */ - -2, /* (364) conslist_opt ::= COMMA conslist */ - -3, /* (365) conslist ::= conslist tconscomma tcons */ - -1, /* (366) conslist ::= tcons */ - 0, /* (367) tconscomma ::= */ - -1, /* (368) defer_subclause_opt ::= defer_subclause */ - -1, /* (369) resolvetype ::= raisetype */ - -1, /* (370) selectnowith ::= oneselect */ - -1, /* (371) oneselect ::= values */ - -2, /* (372) sclp ::= selcollist COMMA */ - -1, /* (373) as ::= ID|STRING */ - -1, /* (374) indexed_opt ::= indexed_by */ - 0, /* (375) returning ::= */ - -1, /* (376) expr ::= term */ - -1, /* (377) likeop ::= LIKE_KW|MATCH */ - -1, /* (378) case_operand ::= expr */ - -1, /* (379) exprlist ::= nexprlist */ - -1, /* (380) nmnum ::= plus_num */ - -1, /* (381) nmnum ::= nm */ - -1, /* (382) nmnum ::= ON */ - -1, /* (383) nmnum ::= DELETE */ - -1, /* (384) nmnum ::= DEFAULT */ - -1, /* (385) plus_num ::= INTEGER|FLOAT */ - 0, /* (386) foreach_clause ::= */ - -3, /* (387) foreach_clause ::= FOR EACH ROW */ - -1, /* (388) trnm ::= nm */ - 0, /* (389) tridxby ::= */ - -1, /* (390) database_kw_opt ::= DATABASE */ - 0, /* (391) database_kw_opt ::= */ - 0, /* (392) kwcolumn_opt ::= */ - -1, /* (393) kwcolumn_opt ::= COLUMNKW */ - -1, /* (394) vtabarglist ::= vtabarg */ - -3, /* (395) vtabarglist ::= vtabarglist COMMA vtabarg */ - -2, /* (396) vtabarg ::= vtabarg vtabargtoken */ - 0, /* (397) anylist ::= */ - -4, /* (398) anylist ::= anylist LP anylist RP */ - -2, /* (399) anylist ::= anylist ANY */ - 0, /* (400) with ::= */ - -1, /* (401) windowdefn_list ::= windowdefn */ - -1, /* (402) window ::= frame_opt */ + -1, /* (95) oneselect ::= mvalues */ + -5, /* (96) mvalues ::= values COMMA LP nexprlist RP */ + -5, /* (97) mvalues ::= mvalues COMMA LP nexprlist RP */ + -1, /* (98) distinct ::= DISTINCT */ + -1, /* (99) distinct ::= ALL */ + 0, /* (100) distinct ::= */ + 0, /* (101) sclp ::= */ + -5, /* (102) selcollist ::= sclp scanpt expr scanpt as */ + -3, /* (103) selcollist ::= sclp scanpt STAR */ + -5, /* (104) selcollist ::= sclp scanpt nm DOT STAR */ + -2, /* (105) as ::= AS nm */ + 0, /* (106) as ::= */ + 0, /* (107) from ::= */ + -2, /* (108) from ::= FROM seltablist */ + -2, /* (109) stl_prefix ::= seltablist joinop */ + 0, /* (110) stl_prefix ::= */ + -5, /* (111) seltablist ::= stl_prefix nm dbnm as on_using */ + -6, /* (112) seltablist ::= stl_prefix nm dbnm as indexed_by on_using */ + -8, /* (113) seltablist ::= stl_prefix nm dbnm LP exprlist RP as on_using */ + -6, /* (114) seltablist ::= stl_prefix LP select RP as on_using */ + -6, /* (115) seltablist ::= stl_prefix LP seltablist RP as on_using */ + 0, /* (116) dbnm ::= */ + -2, /* (117) dbnm ::= DOT nm */ + -1, /* (118) fullname ::= nm */ + -3, /* (119) fullname ::= nm DOT nm */ + -1, /* (120) xfullname ::= nm */ + -3, /* (121) xfullname ::= nm DOT nm */ + -5, /* (122) xfullname ::= nm DOT nm AS nm */ + -3, /* (123) xfullname ::= nm AS nm */ + -1, /* (124) joinop ::= COMMA|JOIN */ + -2, /* (125) joinop ::= JOIN_KW JOIN */ + -3, /* (126) joinop ::= JOIN_KW nm JOIN */ + -4, /* (127) joinop ::= JOIN_KW nm nm JOIN */ + -2, /* (128) on_using ::= ON expr */ + -4, /* (129) on_using ::= USING LP idlist RP */ + 0, /* (130) on_using ::= */ + 0, /* (131) indexed_opt ::= */ + -3, /* (132) indexed_by ::= INDEXED BY nm */ + -2, /* (133) indexed_by ::= NOT INDEXED */ + 0, /* (134) orderby_opt ::= */ + -3, /* (135) orderby_opt ::= ORDER BY sortlist */ + -5, /* (136) sortlist ::= sortlist COMMA expr sortorder nulls */ + -3, /* (137) sortlist ::= expr sortorder nulls */ + -1, /* (138) sortorder ::= ASC */ + -1, /* (139) sortorder ::= DESC */ + 0, /* (140) sortorder ::= */ + -2, /* (141) nulls ::= NULLS FIRST */ + -2, /* (142) nulls ::= NULLS LAST */ + 0, /* (143) nulls ::= */ + 0, /* (144) groupby_opt ::= */ + -3, /* (145) groupby_opt ::= GROUP BY nexprlist */ + 0, /* (146) having_opt ::= */ + -2, /* (147) having_opt ::= HAVING expr */ + 0, /* (148) limit_opt ::= */ + -2, /* (149) limit_opt ::= LIMIT expr */ + -4, /* (150) limit_opt ::= LIMIT expr OFFSET expr */ + -4, /* (151) limit_opt ::= LIMIT expr COMMA expr */ + -6, /* (152) cmd ::= with DELETE FROM xfullname indexed_opt where_opt_ret */ + 0, /* (153) where_opt ::= */ + -2, /* (154) where_opt ::= WHERE expr */ + 0, /* (155) where_opt_ret ::= */ + -2, /* (156) where_opt_ret ::= WHERE expr */ + -2, /* (157) where_opt_ret ::= RETURNING selcollist */ + -4, /* (158) where_opt_ret ::= WHERE expr RETURNING selcollist */ + -9, /* (159) cmd ::= with UPDATE orconf xfullname indexed_opt SET setlist from where_opt_ret */ + -5, /* (160) setlist ::= setlist COMMA nm EQ expr */ + -7, /* (161) setlist ::= setlist COMMA LP idlist RP EQ expr */ + -3, /* (162) setlist ::= nm EQ expr */ + -5, /* (163) setlist ::= LP idlist RP EQ expr */ + -7, /* (164) cmd ::= with insert_cmd INTO xfullname idlist_opt select upsert */ + -8, /* (165) cmd ::= with insert_cmd INTO xfullname idlist_opt DEFAULT VALUES returning */ + 0, /* (166) upsert ::= */ + -2, /* (167) upsert ::= RETURNING selcollist */ + -12, /* (168) upsert ::= ON CONFLICT LP sortlist RP where_opt DO UPDATE SET setlist where_opt upsert */ + -9, /* (169) upsert ::= ON CONFLICT LP sortlist RP where_opt DO NOTHING upsert */ + -5, /* (170) upsert ::= ON CONFLICT DO NOTHING returning */ + -8, /* (171) upsert ::= ON CONFLICT DO UPDATE SET setlist where_opt returning */ + -2, /* (172) returning ::= RETURNING selcollist */ + -2, /* (173) insert_cmd ::= INSERT orconf */ + -1, /* (174) insert_cmd ::= REPLACE */ + 0, /* (175) idlist_opt ::= */ + -3, /* (176) idlist_opt ::= LP idlist RP */ + -3, /* (177) idlist ::= idlist COMMA nm */ + -1, /* (178) idlist ::= nm */ + -3, /* (179) expr ::= LP expr RP */ + -1, /* (180) expr ::= ID|INDEXED|JOIN_KW */ + -3, /* (181) expr ::= nm DOT nm */ + -5, /* (182) expr ::= nm DOT nm DOT nm */ + -1, /* (183) term ::= NULL|FLOAT|BLOB */ + -1, /* (184) term ::= STRING */ + -1, /* (185) term ::= INTEGER */ + -1, /* (186) expr ::= VARIABLE */ + -3, /* (187) expr ::= expr COLLATE ID|STRING */ + -6, /* (188) expr ::= CAST LP expr AS typetoken RP */ + -5, /* (189) expr ::= ID|INDEXED|JOIN_KW LP distinct exprlist RP */ + -8, /* (190) expr ::= ID|INDEXED|JOIN_KW LP distinct exprlist ORDER BY sortlist RP */ + -4, /* (191) expr ::= ID|INDEXED|JOIN_KW LP STAR RP */ + -6, /* (192) expr ::= ID|INDEXED|JOIN_KW LP distinct exprlist RP filter_over */ + -9, /* (193) expr ::= ID|INDEXED|JOIN_KW LP distinct exprlist ORDER BY sortlist RP filter_over */ + -5, /* (194) expr ::= ID|INDEXED|JOIN_KW LP STAR RP filter_over */ + -1, /* (195) term ::= CTIME_KW */ + -5, /* (196) expr ::= LP nexprlist COMMA expr RP */ + -3, /* (197) expr ::= expr AND expr */ + -3, /* (198) expr ::= expr OR expr */ + -3, /* (199) expr ::= expr LT|GT|GE|LE expr */ + -3, /* (200) expr ::= expr EQ|NE expr */ + -3, /* (201) expr ::= expr BITAND|BITOR|LSHIFT|RSHIFT expr */ + -3, /* (202) expr ::= expr PLUS|MINUS expr */ + -3, /* (203) expr ::= expr STAR|SLASH|REM expr */ + -3, /* (204) expr ::= expr CONCAT expr */ + -2, /* (205) likeop ::= NOT LIKE_KW|MATCH */ + -3, /* (206) expr ::= expr likeop expr */ + -5, /* (207) expr ::= expr likeop expr ESCAPE expr */ + -2, /* (208) expr ::= expr ISNULL|NOTNULL */ + -3, /* (209) expr ::= expr NOT NULL */ + -3, /* (210) expr ::= expr IS expr */ + -4, /* (211) expr ::= expr IS NOT expr */ + -6, /* (212) expr ::= expr IS NOT DISTINCT FROM expr */ + -5, /* (213) expr ::= expr IS DISTINCT FROM expr */ + -2, /* (214) expr ::= NOT expr */ + -2, /* (215) expr ::= BITNOT expr */ + -2, /* (216) expr ::= PLUS|MINUS expr */ + -3, /* (217) expr ::= expr PTR expr */ + -1, /* (218) between_op ::= BETWEEN */ + -2, /* (219) between_op ::= NOT BETWEEN */ + -5, /* (220) expr ::= expr between_op expr AND expr */ + -1, /* (221) in_op ::= IN */ + -2, /* (222) in_op ::= NOT IN */ + -5, /* (223) expr ::= expr in_op LP exprlist RP */ + -3, /* (224) expr ::= LP select RP */ + -5, /* (225) expr ::= expr in_op LP select RP */ + -5, /* (226) expr ::= expr in_op nm dbnm paren_exprlist */ + -4, /* (227) expr ::= EXISTS LP select RP */ + -5, /* (228) expr ::= CASE case_operand case_exprlist case_else END */ + -5, /* (229) case_exprlist ::= case_exprlist WHEN expr THEN expr */ + -4, /* (230) case_exprlist ::= WHEN expr THEN expr */ + -2, /* (231) case_else ::= ELSE expr */ + 0, /* (232) case_else ::= */ + 0, /* (233) case_operand ::= */ + 0, /* (234) exprlist ::= */ + -3, /* (235) nexprlist ::= nexprlist COMMA expr */ + -1, /* (236) nexprlist ::= expr */ + 0, /* (237) paren_exprlist ::= */ + -3, /* (238) paren_exprlist ::= LP exprlist RP */ + -12, /* (239) cmd ::= createkw uniqueflag INDEX ifnotexists nm dbnm ON nm LP sortlist RP where_opt */ + -1, /* (240) uniqueflag ::= UNIQUE */ + 0, /* (241) uniqueflag ::= */ + 0, /* (242) eidlist_opt ::= */ + -3, /* (243) eidlist_opt ::= LP eidlist RP */ + -5, /* (244) eidlist ::= eidlist COMMA nm collate sortorder */ + -3, /* (245) eidlist ::= nm collate sortorder */ + 0, /* (246) collate ::= */ + -2, /* (247) collate ::= COLLATE ID|STRING */ + -4, /* (248) cmd ::= DROP INDEX ifexists fullname */ + -2, /* (249) cmd ::= VACUUM vinto */ + -3, /* (250) cmd ::= VACUUM nm vinto */ + -2, /* (251) vinto ::= INTO expr */ + 0, /* (252) vinto ::= */ + -3, /* (253) cmd ::= PRAGMA nm dbnm */ + -5, /* (254) cmd ::= PRAGMA nm dbnm EQ nmnum */ + -6, /* (255) cmd ::= PRAGMA nm dbnm LP nmnum RP */ + -5, /* (256) cmd ::= PRAGMA nm dbnm EQ minus_num */ + -6, /* (257) cmd ::= PRAGMA nm dbnm LP minus_num RP */ + -2, /* (258) plus_num ::= PLUS INTEGER|FLOAT */ + -2, /* (259) minus_num ::= MINUS INTEGER|FLOAT */ + -5, /* (260) cmd ::= createkw trigger_decl BEGIN trigger_cmd_list END */ + -11, /* (261) trigger_decl ::= temp TRIGGER ifnotexists nm dbnm trigger_time trigger_event ON fullname foreach_clause when_clause */ + -1, /* (262) trigger_time ::= BEFORE|AFTER */ + -2, /* (263) trigger_time ::= INSTEAD OF */ + 0, /* (264) trigger_time ::= */ + -1, /* (265) trigger_event ::= DELETE|INSERT */ + -1, /* (266) trigger_event ::= UPDATE */ + -3, /* (267) trigger_event ::= UPDATE OF idlist */ + 0, /* (268) when_clause ::= */ + -2, /* (269) when_clause ::= WHEN expr */ + -3, /* (270) trigger_cmd_list ::= trigger_cmd_list trigger_cmd SEMI */ + -2, /* (271) trigger_cmd_list ::= trigger_cmd SEMI */ + -3, /* (272) trnm ::= nm DOT nm */ + -3, /* (273) tridxby ::= INDEXED BY nm */ + -2, /* (274) tridxby ::= NOT INDEXED */ + -9, /* (275) trigger_cmd ::= UPDATE orconf trnm tridxby SET setlist from where_opt scanpt */ + -8, /* (276) trigger_cmd ::= scanpt insert_cmd INTO trnm idlist_opt select upsert scanpt */ + -6, /* (277) trigger_cmd ::= DELETE FROM trnm tridxby where_opt scanpt */ + -3, /* (278) trigger_cmd ::= scanpt select scanpt */ + -4, /* (279) expr ::= RAISE LP IGNORE RP */ + -6, /* (280) expr ::= RAISE LP raisetype COMMA nm RP */ + -1, /* (281) raisetype ::= ROLLBACK */ + -1, /* (282) raisetype ::= ABORT */ + -1, /* (283) raisetype ::= FAIL */ + -4, /* (284) cmd ::= DROP TRIGGER ifexists fullname */ + -6, /* (285) cmd ::= ATTACH database_kw_opt expr AS expr key_opt */ + -3, /* (286) cmd ::= DETACH database_kw_opt expr */ + 0, /* (287) key_opt ::= */ + -2, /* (288) key_opt ::= KEY expr */ + -1, /* (289) cmd ::= REINDEX */ + -3, /* (290) cmd ::= REINDEX nm dbnm */ + -1, /* (291) cmd ::= ANALYZE */ + -3, /* (292) cmd ::= ANALYZE nm dbnm */ + -6, /* (293) cmd ::= ALTER TABLE fullname RENAME TO nm */ + -7, /* (294) cmd ::= ALTER TABLE add_column_fullname ADD kwcolumn_opt columnname carglist */ + -6, /* (295) cmd ::= ALTER TABLE fullname DROP kwcolumn_opt nm */ + -1, /* (296) add_column_fullname ::= fullname */ + -8, /* (297) cmd ::= ALTER TABLE fullname RENAME kwcolumn_opt nm TO nm */ + -1, /* (298) cmd ::= create_vtab */ + -4, /* (299) cmd ::= create_vtab LP vtabarglist RP */ + -8, /* (300) create_vtab ::= createkw VIRTUAL TABLE ifnotexists nm dbnm USING nm */ + 0, /* (301) vtabarg ::= */ + -1, /* (302) vtabargtoken ::= ANY */ + -3, /* (303) vtabargtoken ::= lp anylist RP */ + -1, /* (304) lp ::= LP */ + -2, /* (305) with ::= WITH wqlist */ + -3, /* (306) with ::= WITH RECURSIVE wqlist */ + -1, /* (307) wqas ::= AS */ + -2, /* (308) wqas ::= AS MATERIALIZED */ + -3, /* (309) wqas ::= AS NOT MATERIALIZED */ + -6, /* (310) wqitem ::= withnm eidlist_opt wqas LP select RP */ + -1, /* (311) withnm ::= nm */ + -1, /* (312) wqlist ::= wqitem */ + -3, /* (313) wqlist ::= wqlist COMMA wqitem */ + -3, /* (314) windowdefn_list ::= windowdefn_list COMMA windowdefn */ + -5, /* (315) windowdefn ::= nm AS LP window RP */ + -5, /* (316) window ::= PARTITION BY nexprlist orderby_opt frame_opt */ + -6, /* (317) window ::= nm PARTITION BY nexprlist orderby_opt frame_opt */ + -4, /* (318) window ::= ORDER BY sortlist frame_opt */ + -5, /* (319) window ::= nm ORDER BY sortlist frame_opt */ + -2, /* (320) window ::= nm frame_opt */ + 0, /* (321) frame_opt ::= */ + -3, /* (322) frame_opt ::= range_or_rows frame_bound_s frame_exclude_opt */ + -6, /* (323) frame_opt ::= range_or_rows BETWEEN frame_bound_s AND frame_bound_e frame_exclude_opt */ + -1, /* (324) range_or_rows ::= RANGE|ROWS|GROUPS */ + -1, /* (325) frame_bound_s ::= frame_bound */ + -2, /* (326) frame_bound_s ::= UNBOUNDED PRECEDING */ + -1, /* (327) frame_bound_e ::= frame_bound */ + -2, /* (328) frame_bound_e ::= UNBOUNDED FOLLOWING */ + -2, /* (329) frame_bound ::= expr PRECEDING|FOLLOWING */ + -2, /* (330) frame_bound ::= CURRENT ROW */ + 0, /* (331) frame_exclude_opt ::= */ + -2, /* (332) frame_exclude_opt ::= EXCLUDE frame_exclude */ + -2, /* (333) frame_exclude ::= NO OTHERS */ + -2, /* (334) frame_exclude ::= CURRENT ROW */ + -1, /* (335) frame_exclude ::= GROUP|TIES */ + -2, /* (336) window_clause ::= WINDOW windowdefn_list */ + -2, /* (337) filter_over ::= filter_clause over_clause */ + -1, /* (338) filter_over ::= over_clause */ + -1, /* (339) filter_over ::= filter_clause */ + -4, /* (340) over_clause ::= OVER LP window RP */ + -2, /* (341) over_clause ::= OVER nm */ + -5, /* (342) filter_clause ::= FILTER LP WHERE expr RP */ + -1, /* (343) term ::= QNUMBER */ + -1, /* (344) input ::= cmdlist */ + -2, /* (345) cmdlist ::= cmdlist ecmd */ + -1, /* (346) cmdlist ::= ecmd */ + -1, /* (347) ecmd ::= SEMI */ + -2, /* (348) ecmd ::= cmdx SEMI */ + -3, /* (349) ecmd ::= explain cmdx SEMI */ + 0, /* (350) trans_opt ::= */ + -1, /* (351) trans_opt ::= TRANSACTION */ + -2, /* (352) trans_opt ::= TRANSACTION nm */ + -1, /* (353) savepoint_opt ::= SAVEPOINT */ + 0, /* (354) savepoint_opt ::= */ + -2, /* (355) cmd ::= create_table create_table_args */ + -1, /* (356) table_option_set ::= table_option */ + -4, /* (357) columnlist ::= columnlist COMMA columnname carglist */ + -2, /* (358) columnlist ::= columnname carglist */ + -1, /* (359) nm ::= ID|INDEXED|JOIN_KW */ + -1, /* (360) nm ::= STRING */ + -1, /* (361) typetoken ::= typename */ + -1, /* (362) typename ::= ID|STRING */ + -1, /* (363) signed ::= plus_num */ + -1, /* (364) signed ::= minus_num */ + -2, /* (365) carglist ::= carglist ccons */ + 0, /* (366) carglist ::= */ + -2, /* (367) ccons ::= NULL onconf */ + -4, /* (368) ccons ::= GENERATED ALWAYS AS generated */ + -2, /* (369) ccons ::= AS generated */ + -2, /* (370) conslist_opt ::= COMMA conslist */ + -3, /* (371) conslist ::= conslist tconscomma tcons */ + -1, /* (372) conslist ::= tcons */ + 0, /* (373) tconscomma ::= */ + -1, /* (374) defer_subclause_opt ::= defer_subclause */ + -1, /* (375) resolvetype ::= raisetype */ + -1, /* (376) selectnowith ::= oneselect */ + -1, /* (377) oneselect ::= values */ + -2, /* (378) sclp ::= selcollist COMMA */ + -1, /* (379) as ::= ID|STRING */ + -1, /* (380) indexed_opt ::= indexed_by */ + 0, /* (381) returning ::= */ + -1, /* (382) expr ::= term */ + -1, /* (383) likeop ::= LIKE_KW|MATCH */ + -1, /* (384) case_operand ::= expr */ + -1, /* (385) exprlist ::= nexprlist */ + -1, /* (386) nmnum ::= plus_num */ + -1, /* (387) nmnum ::= nm */ + -1, /* (388) nmnum ::= ON */ + -1, /* (389) nmnum ::= DELETE */ + -1, /* (390) nmnum ::= DEFAULT */ + -1, /* (391) plus_num ::= INTEGER|FLOAT */ + 0, /* (392) foreach_clause ::= */ + -3, /* (393) foreach_clause ::= FOR EACH ROW */ + -1, /* (394) trnm ::= nm */ + 0, /* (395) tridxby ::= */ + -1, /* (396) database_kw_opt ::= DATABASE */ + 0, /* (397) database_kw_opt ::= */ + 0, /* (398) kwcolumn_opt ::= */ + -1, /* (399) kwcolumn_opt ::= COLUMNKW */ + -1, /* (400) vtabarglist ::= vtabarg */ + -3, /* (401) vtabarglist ::= vtabarglist COMMA vtabarg */ + -2, /* (402) vtabarg ::= vtabarg vtabargtoken */ + 0, /* (403) anylist ::= */ + -4, /* (404) anylist ::= anylist LP anylist RP */ + -2, /* (405) anylist ::= anylist ANY */ + 0, /* (406) with ::= */ + -1, /* (407) windowdefn_list ::= windowdefn */ + -1, /* (408) window ::= frame_opt */ }; static void yy_accept(yyParser*); /* Forward Declaration */ @@ -172812,16 +176126,16 @@ static YYACTIONTYPE yy_reduce( { sqlite3FinishCoding(pParse); } break; case 3: /* cmd ::= BEGIN transtype trans_opt */ -{sqlite3BeginTransaction(pParse, yymsp[-1].minor.yy394);} +{sqlite3BeginTransaction(pParse, yymsp[-1].minor.yy144);} break; case 4: /* transtype ::= */ -{yymsp[1].minor.yy394 = TK_DEFERRED;} +{yymsp[1].minor.yy144 = TK_DEFERRED;} break; case 5: /* transtype ::= DEFERRED */ case 6: /* transtype ::= IMMEDIATE */ yytestcase(yyruleno==6); case 7: /* transtype ::= EXCLUSIVE */ yytestcase(yyruleno==7); - case 319: /* range_or_rows ::= RANGE|ROWS|GROUPS */ yytestcase(yyruleno==319); -{yymsp[0].minor.yy394 = yymsp[0].major; /*A-overwrites-X*/} + case 324: /* range_or_rows ::= RANGE|ROWS|GROUPS */ yytestcase(yyruleno==324); +{yymsp[0].minor.yy144 = yymsp[0].major; /*A-overwrites-X*/} break; case 8: /* cmd ::= COMMIT|END trans_opt */ case 9: /* cmd ::= ROLLBACK trans_opt */ yytestcase(yyruleno==9); @@ -172844,7 +176158,7 @@ static YYACTIONTYPE yy_reduce( break; case 13: /* create_table ::= createkw temp TABLE ifnotexists nm dbnm */ { - sqlite3StartTable(pParse,&yymsp[-1].minor.yy0,&yymsp[0].minor.yy0,yymsp[-4].minor.yy394,0,0,yymsp[-2].minor.yy394); + sqlite3StartTable(pParse,&yymsp[-1].minor.yy0,&yymsp[0].minor.yy0,yymsp[-4].minor.yy144,0,0,yymsp[-2].minor.yy144); } break; case 14: /* createkw ::= CREATE */ @@ -172856,40 +176170,40 @@ static YYACTIONTYPE yy_reduce( case 62: /* init_deferred_pred_opt ::= */ yytestcase(yyruleno==62); case 72: /* defer_subclause_opt ::= */ yytestcase(yyruleno==72); case 81: /* ifexists ::= */ yytestcase(yyruleno==81); - case 98: /* distinct ::= */ yytestcase(yyruleno==98); - case 242: /* collate ::= */ yytestcase(yyruleno==242); -{yymsp[1].minor.yy394 = 0;} + case 100: /* distinct ::= */ yytestcase(yyruleno==100); + case 246: /* collate ::= */ yytestcase(yyruleno==246); +{yymsp[1].minor.yy144 = 0;} break; case 16: /* ifnotexists ::= IF NOT EXISTS */ -{yymsp[-2].minor.yy394 = 1;} +{yymsp[-2].minor.yy144 = 1;} break; case 17: /* temp ::= TEMP */ -{yymsp[0].minor.yy394 = pParse->db->init.busy==0;} +{yymsp[0].minor.yy144 = pParse->db->init.busy==0;} break; case 19: /* create_table_args ::= LP columnlist conslist_opt RP table_option_set */ { - sqlite3EndTable(pParse,&yymsp[-2].minor.yy0,&yymsp[-1].minor.yy0,yymsp[0].minor.yy285,0); + sqlite3EndTable(pParse,&yymsp[-2].minor.yy0,&yymsp[-1].minor.yy0,yymsp[0].minor.yy391,0); } break; case 20: /* create_table_args ::= AS select */ { - sqlite3EndTable(pParse,0,0,0,yymsp[0].minor.yy47); - sqlite3SelectDelete(pParse->db, yymsp[0].minor.yy47); + sqlite3EndTable(pParse,0,0,0,yymsp[0].minor.yy555); + sqlite3SelectDelete(pParse->db, yymsp[0].minor.yy555); } break; case 21: /* table_option_set ::= */ -{yymsp[1].minor.yy285 = 0;} +{yymsp[1].minor.yy391 = 0;} break; case 22: /* table_option_set ::= table_option_set COMMA table_option */ -{yylhsminor.yy285 = yymsp[-2].minor.yy285|yymsp[0].minor.yy285;} - yymsp[-2].minor.yy285 = yylhsminor.yy285; +{yylhsminor.yy391 = yymsp[-2].minor.yy391|yymsp[0].minor.yy391;} + yymsp[-2].minor.yy391 = yylhsminor.yy391; break; case 23: /* table_option ::= WITHOUT nm */ { if( yymsp[0].minor.yy0.n==5 && sqlite3_strnicmp(yymsp[0].minor.yy0.z,"rowid",5)==0 ){ - yymsp[-1].minor.yy285 = TF_WithoutRowid | TF_NoVisibleRowid; + yymsp[-1].minor.yy391 = TF_WithoutRowid | TF_NoVisibleRowid; }else{ - yymsp[-1].minor.yy285 = 0; + yymsp[-1].minor.yy391 = 0; sqlite3ErrorMsg(pParse, "unknown table option: %.*s", yymsp[0].minor.yy0.n, yymsp[0].minor.yy0.z); } } @@ -172897,20 +176211,20 @@ static YYACTIONTYPE yy_reduce( case 24: /* table_option ::= nm */ { if( yymsp[0].minor.yy0.n==6 && sqlite3_strnicmp(yymsp[0].minor.yy0.z,"strict",6)==0 ){ - yylhsminor.yy285 = TF_Strict; + yylhsminor.yy391 = TF_Strict; }else{ - yylhsminor.yy285 = 0; + yylhsminor.yy391 = 0; sqlite3ErrorMsg(pParse, "unknown table option: %.*s", yymsp[0].minor.yy0.n, yymsp[0].minor.yy0.z); } } - yymsp[0].minor.yy285 = yylhsminor.yy285; + yymsp[0].minor.yy391 = yylhsminor.yy391; break; case 25: /* columnname ::= nm typetoken */ {sqlite3AddColumn(pParse,yymsp[-1].minor.yy0,yymsp[0].minor.yy0);} break; case 26: /* typetoken ::= */ case 65: /* conslist_opt ::= */ yytestcase(yyruleno==65); - case 104: /* as ::= */ yytestcase(yyruleno==104); + case 106: /* as ::= */ yytestcase(yyruleno==106); {yymsp[1].minor.yy0.n = 0; yymsp[1].minor.yy0.z = 0;} break; case 27: /* typetoken ::= typename LP signed RP */ @@ -172929,7 +176243,7 @@ static YYACTIONTYPE yy_reduce( case 30: /* scanpt ::= */ { assert( yyLookahead!=YYNOCODE ); - yymsp[1].minor.yy522 = yyLookaheadToken.z; + yymsp[1].minor.yy168 = yyLookaheadToken.z; } break; case 31: /* scantok ::= */ @@ -172943,17 +176257,17 @@ static YYACTIONTYPE yy_reduce( {pParse->constraintName = yymsp[0].minor.yy0;} break; case 33: /* ccons ::= DEFAULT scantok term */ -{sqlite3AddDefaultValue(pParse,yymsp[0].minor.yy528,yymsp[-1].minor.yy0.z,&yymsp[-1].minor.yy0.z[yymsp[-1].minor.yy0.n]);} +{sqlite3AddDefaultValue(pParse,yymsp[0].minor.yy454,yymsp[-1].minor.yy0.z,&yymsp[-1].minor.yy0.z[yymsp[-1].minor.yy0.n]);} break; case 34: /* ccons ::= DEFAULT LP expr RP */ -{sqlite3AddDefaultValue(pParse,yymsp[-1].minor.yy528,yymsp[-2].minor.yy0.z+1,yymsp[0].minor.yy0.z);} +{sqlite3AddDefaultValue(pParse,yymsp[-1].minor.yy454,yymsp[-2].minor.yy0.z+1,yymsp[0].minor.yy0.z);} break; case 35: /* ccons ::= DEFAULT PLUS scantok term */ -{sqlite3AddDefaultValue(pParse,yymsp[0].minor.yy528,yymsp[-2].minor.yy0.z,&yymsp[-1].minor.yy0.z[yymsp[-1].minor.yy0.n]);} +{sqlite3AddDefaultValue(pParse,yymsp[0].minor.yy454,yymsp[-2].minor.yy0.z,&yymsp[-1].minor.yy0.z[yymsp[-1].minor.yy0.n]);} break; case 36: /* ccons ::= DEFAULT MINUS scantok term */ { - Expr *p = sqlite3PExpr(pParse, TK_UMINUS, yymsp[0].minor.yy528, 0); + Expr *p = sqlite3PExpr(pParse, TK_UMINUS, yymsp[0].minor.yy454, 0); sqlite3AddDefaultValue(pParse,p,yymsp[-2].minor.yy0.z,&yymsp[-1].minor.yy0.z[yymsp[-1].minor.yy0.n]); } break; @@ -172968,151 +176282,151 @@ static YYACTIONTYPE yy_reduce( } break; case 38: /* ccons ::= NOT NULL onconf */ -{sqlite3AddNotNull(pParse, yymsp[0].minor.yy394);} +{sqlite3AddNotNull(pParse, yymsp[0].minor.yy144);} break; case 39: /* ccons ::= PRIMARY KEY sortorder onconf autoinc */ -{sqlite3AddPrimaryKey(pParse,0,yymsp[-1].minor.yy394,yymsp[0].minor.yy394,yymsp[-2].minor.yy394);} +{sqlite3AddPrimaryKey(pParse,0,yymsp[-1].minor.yy144,yymsp[0].minor.yy144,yymsp[-2].minor.yy144);} break; case 40: /* ccons ::= UNIQUE onconf */ -{sqlite3CreateIndex(pParse,0,0,0,0,yymsp[0].minor.yy394,0,0,0,0, +{sqlite3CreateIndex(pParse,0,0,0,0,yymsp[0].minor.yy144,0,0,0,0, SQLITE_IDXTYPE_UNIQUE);} break; case 41: /* ccons ::= CHECK LP expr RP */ -{sqlite3AddCheckConstraint(pParse,yymsp[-1].minor.yy528,yymsp[-2].minor.yy0.z,yymsp[0].minor.yy0.z);} +{sqlite3AddCheckConstraint(pParse,yymsp[-1].minor.yy454,yymsp[-2].minor.yy0.z,yymsp[0].minor.yy0.z);} break; case 42: /* ccons ::= REFERENCES nm eidlist_opt refargs */ -{sqlite3CreateForeignKey(pParse,0,&yymsp[-2].minor.yy0,yymsp[-1].minor.yy322,yymsp[0].minor.yy394);} +{sqlite3CreateForeignKey(pParse,0,&yymsp[-2].minor.yy0,yymsp[-1].minor.yy14,yymsp[0].minor.yy144);} break; case 43: /* ccons ::= defer_subclause */ -{sqlite3DeferForeignKey(pParse,yymsp[0].minor.yy394);} +{sqlite3DeferForeignKey(pParse,yymsp[0].minor.yy144);} break; case 44: /* ccons ::= COLLATE ID|STRING */ {sqlite3AddCollateType(pParse, &yymsp[0].minor.yy0);} break; case 45: /* generated ::= LP expr RP */ -{sqlite3AddGenerated(pParse,yymsp[-1].minor.yy528,0);} +{sqlite3AddGenerated(pParse,yymsp[-1].minor.yy454,0);} break; case 46: /* generated ::= LP expr RP ID */ -{sqlite3AddGenerated(pParse,yymsp[-2].minor.yy528,&yymsp[0].minor.yy0);} +{sqlite3AddGenerated(pParse,yymsp[-2].minor.yy454,&yymsp[0].minor.yy0);} break; case 48: /* autoinc ::= AUTOINCR */ -{yymsp[0].minor.yy394 = 1;} +{yymsp[0].minor.yy144 = 1;} break; case 49: /* refargs ::= */ -{ yymsp[1].minor.yy394 = OE_None*0x0101; /* EV: R-19803-45884 */} +{ yymsp[1].minor.yy144 = OE_None*0x0101; /* EV: R-19803-45884 */} break; case 50: /* refargs ::= refargs refarg */ -{ yymsp[-1].minor.yy394 = (yymsp[-1].minor.yy394 & ~yymsp[0].minor.yy231.mask) | yymsp[0].minor.yy231.value; } +{ yymsp[-1].minor.yy144 = (yymsp[-1].minor.yy144 & ~yymsp[0].minor.yy383.mask) | yymsp[0].minor.yy383.value; } break; case 51: /* refarg ::= MATCH nm */ -{ yymsp[-1].minor.yy231.value = 0; yymsp[-1].minor.yy231.mask = 0x000000; } +{ yymsp[-1].minor.yy383.value = 0; yymsp[-1].minor.yy383.mask = 0x000000; } break; case 52: /* refarg ::= ON INSERT refact */ -{ yymsp[-2].minor.yy231.value = 0; yymsp[-2].minor.yy231.mask = 0x000000; } +{ yymsp[-2].minor.yy383.value = 0; yymsp[-2].minor.yy383.mask = 0x000000; } break; case 53: /* refarg ::= ON DELETE refact */ -{ yymsp[-2].minor.yy231.value = yymsp[0].minor.yy394; yymsp[-2].minor.yy231.mask = 0x0000ff; } +{ yymsp[-2].minor.yy383.value = yymsp[0].minor.yy144; yymsp[-2].minor.yy383.mask = 0x0000ff; } break; case 54: /* refarg ::= ON UPDATE refact */ -{ yymsp[-2].minor.yy231.value = yymsp[0].minor.yy394<<8; yymsp[-2].minor.yy231.mask = 0x00ff00; } +{ yymsp[-2].minor.yy383.value = yymsp[0].minor.yy144<<8; yymsp[-2].minor.yy383.mask = 0x00ff00; } break; case 55: /* refact ::= SET NULL */ -{ yymsp[-1].minor.yy394 = OE_SetNull; /* EV: R-33326-45252 */} +{ yymsp[-1].minor.yy144 = OE_SetNull; /* EV: R-33326-45252 */} break; case 56: /* refact ::= SET DEFAULT */ -{ yymsp[-1].minor.yy394 = OE_SetDflt; /* EV: R-33326-45252 */} +{ yymsp[-1].minor.yy144 = OE_SetDflt; /* EV: R-33326-45252 */} break; case 57: /* refact ::= CASCADE */ -{ yymsp[0].minor.yy394 = OE_Cascade; /* EV: R-33326-45252 */} +{ yymsp[0].minor.yy144 = OE_Cascade; /* EV: R-33326-45252 */} break; case 58: /* refact ::= RESTRICT */ -{ yymsp[0].minor.yy394 = OE_Restrict; /* EV: R-33326-45252 */} +{ yymsp[0].minor.yy144 = OE_Restrict; /* EV: R-33326-45252 */} break; case 59: /* refact ::= NO ACTION */ -{ yymsp[-1].minor.yy394 = OE_None; /* EV: R-33326-45252 */} +{ yymsp[-1].minor.yy144 = OE_None; /* EV: R-33326-45252 */} break; case 60: /* defer_subclause ::= NOT DEFERRABLE init_deferred_pred_opt */ -{yymsp[-2].minor.yy394 = 0;} +{yymsp[-2].minor.yy144 = 0;} break; case 61: /* defer_subclause ::= DEFERRABLE init_deferred_pred_opt */ case 76: /* orconf ::= OR resolvetype */ yytestcase(yyruleno==76); - case 171: /* insert_cmd ::= INSERT orconf */ yytestcase(yyruleno==171); -{yymsp[-1].minor.yy394 = yymsp[0].minor.yy394;} + case 173: /* insert_cmd ::= INSERT orconf */ yytestcase(yyruleno==173); +{yymsp[-1].minor.yy144 = yymsp[0].minor.yy144;} break; case 63: /* init_deferred_pred_opt ::= INITIALLY DEFERRED */ case 80: /* ifexists ::= IF EXISTS */ yytestcase(yyruleno==80); - case 215: /* between_op ::= NOT BETWEEN */ yytestcase(yyruleno==215); - case 218: /* in_op ::= NOT IN */ yytestcase(yyruleno==218); - case 243: /* collate ::= COLLATE ID|STRING */ yytestcase(yyruleno==243); -{yymsp[-1].minor.yy394 = 1;} + case 219: /* between_op ::= NOT BETWEEN */ yytestcase(yyruleno==219); + case 222: /* in_op ::= NOT IN */ yytestcase(yyruleno==222); + case 247: /* collate ::= COLLATE ID|STRING */ yytestcase(yyruleno==247); +{yymsp[-1].minor.yy144 = 1;} break; case 64: /* init_deferred_pred_opt ::= INITIALLY IMMEDIATE */ -{yymsp[-1].minor.yy394 = 0;} +{yymsp[-1].minor.yy144 = 0;} break; case 66: /* tconscomma ::= COMMA */ {pParse->constraintName.n = 0;} break; case 68: /* tcons ::= PRIMARY KEY LP sortlist autoinc RP onconf */ -{sqlite3AddPrimaryKey(pParse,yymsp[-3].minor.yy322,yymsp[0].minor.yy394,yymsp[-2].minor.yy394,0);} +{sqlite3AddPrimaryKey(pParse,yymsp[-3].minor.yy14,yymsp[0].minor.yy144,yymsp[-2].minor.yy144,0);} break; case 69: /* tcons ::= UNIQUE LP sortlist RP onconf */ -{sqlite3CreateIndex(pParse,0,0,0,yymsp[-2].minor.yy322,yymsp[0].minor.yy394,0,0,0,0, +{sqlite3CreateIndex(pParse,0,0,0,yymsp[-2].minor.yy14,yymsp[0].minor.yy144,0,0,0,0, SQLITE_IDXTYPE_UNIQUE);} break; case 70: /* tcons ::= CHECK LP expr RP onconf */ -{sqlite3AddCheckConstraint(pParse,yymsp[-2].minor.yy528,yymsp[-3].minor.yy0.z,yymsp[-1].minor.yy0.z);} +{sqlite3AddCheckConstraint(pParse,yymsp[-2].minor.yy454,yymsp[-3].minor.yy0.z,yymsp[-1].minor.yy0.z);} break; case 71: /* tcons ::= FOREIGN KEY LP eidlist RP REFERENCES nm eidlist_opt refargs defer_subclause_opt */ { - sqlite3CreateForeignKey(pParse, yymsp[-6].minor.yy322, &yymsp[-3].minor.yy0, yymsp[-2].minor.yy322, yymsp[-1].minor.yy394); - sqlite3DeferForeignKey(pParse, yymsp[0].minor.yy394); + sqlite3CreateForeignKey(pParse, yymsp[-6].minor.yy14, &yymsp[-3].minor.yy0, yymsp[-2].minor.yy14, yymsp[-1].minor.yy144); + sqlite3DeferForeignKey(pParse, yymsp[0].minor.yy144); } break; case 73: /* onconf ::= */ case 75: /* orconf ::= */ yytestcase(yyruleno==75); -{yymsp[1].minor.yy394 = OE_Default;} +{yymsp[1].minor.yy144 = OE_Default;} break; case 74: /* onconf ::= ON CONFLICT resolvetype */ -{yymsp[-2].minor.yy394 = yymsp[0].minor.yy394;} +{yymsp[-2].minor.yy144 = yymsp[0].minor.yy144;} break; case 77: /* resolvetype ::= IGNORE */ -{yymsp[0].minor.yy394 = OE_Ignore;} +{yymsp[0].minor.yy144 = OE_Ignore;} break; case 78: /* resolvetype ::= REPLACE */ - case 172: /* insert_cmd ::= REPLACE */ yytestcase(yyruleno==172); -{yymsp[0].minor.yy394 = OE_Replace;} + case 174: /* insert_cmd ::= REPLACE */ yytestcase(yyruleno==174); +{yymsp[0].minor.yy144 = OE_Replace;} break; case 79: /* cmd ::= DROP TABLE ifexists fullname */ { - sqlite3DropTable(pParse, yymsp[0].minor.yy131, 0, yymsp[-1].minor.yy394); + sqlite3DropTable(pParse, yymsp[0].minor.yy203, 0, yymsp[-1].minor.yy144); } break; case 82: /* cmd ::= createkw temp VIEW ifnotexists nm dbnm eidlist_opt AS select */ { - sqlite3CreateView(pParse, &yymsp[-8].minor.yy0, &yymsp[-4].minor.yy0, &yymsp[-3].minor.yy0, yymsp[-2].minor.yy322, yymsp[0].minor.yy47, yymsp[-7].minor.yy394, yymsp[-5].minor.yy394); + sqlite3CreateView(pParse, &yymsp[-8].minor.yy0, &yymsp[-4].minor.yy0, &yymsp[-3].minor.yy0, yymsp[-2].minor.yy14, yymsp[0].minor.yy555, yymsp[-7].minor.yy144, yymsp[-5].minor.yy144); } break; case 83: /* cmd ::= DROP VIEW ifexists fullname */ { - sqlite3DropTable(pParse, yymsp[0].minor.yy131, 1, yymsp[-1].minor.yy394); + sqlite3DropTable(pParse, yymsp[0].minor.yy203, 1, yymsp[-1].minor.yy144); } break; case 84: /* cmd ::= select */ { SelectDest dest = {SRT_Output, 0, 0, 0, 0, 0, 0}; - sqlite3Select(pParse, yymsp[0].minor.yy47, &dest); - sqlite3SelectDelete(pParse->db, yymsp[0].minor.yy47); + sqlite3Select(pParse, yymsp[0].minor.yy555, &dest); + sqlite3SelectDelete(pParse->db, yymsp[0].minor.yy555); } break; case 85: /* select ::= WITH wqlist selectnowith */ -{yymsp[-2].minor.yy47 = attachWithToSelect(pParse,yymsp[0].minor.yy47,yymsp[-1].minor.yy521);} +{yymsp[-2].minor.yy555 = attachWithToSelect(pParse,yymsp[0].minor.yy555,yymsp[-1].minor.yy59);} break; case 86: /* select ::= WITH RECURSIVE wqlist selectnowith */ -{yymsp[-3].minor.yy47 = attachWithToSelect(pParse,yymsp[0].minor.yy47,yymsp[-1].minor.yy521);} +{yymsp[-3].minor.yy555 = attachWithToSelect(pParse,yymsp[0].minor.yy555,yymsp[-1].minor.yy59);} break; case 87: /* select ::= selectnowith */ { - Select *p = yymsp[0].minor.yy47; + Select *p = yymsp[0].minor.yy555; if( p ){ parserDoubleLinkSelect(pParse, p); } @@ -173120,8 +176434,8 @@ static YYACTIONTYPE yy_reduce( break; case 88: /* selectnowith ::= selectnowith multiselect_op oneselect */ { - Select *pRhs = yymsp[0].minor.yy47; - Select *pLhs = yymsp[-2].minor.yy47; + Select *pRhs = yymsp[0].minor.yy555; + Select *pLhs = yymsp[-2].minor.yy555; if( pRhs && pRhs->pPrior ){ SrcList *pFrom; Token x; @@ -173131,148 +176445,145 @@ static YYACTIONTYPE yy_reduce( pRhs = sqlite3SelectNew(pParse,0,pFrom,0,0,0,0,0,0); } if( pRhs ){ - pRhs->op = (u8)yymsp[-1].minor.yy394; + pRhs->op = (u8)yymsp[-1].minor.yy144; pRhs->pPrior = pLhs; if( ALWAYS(pLhs) ) pLhs->selFlags &= ~SF_MultiValue; pRhs->selFlags &= ~SF_MultiValue; - if( yymsp[-1].minor.yy394!=TK_ALL ) pParse->hasCompound = 1; + if( yymsp[-1].minor.yy144!=TK_ALL ) pParse->hasCompound = 1; }else{ sqlite3SelectDelete(pParse->db, pLhs); } - yymsp[-2].minor.yy47 = pRhs; + yymsp[-2].minor.yy555 = pRhs; } break; case 89: /* multiselect_op ::= UNION */ case 91: /* multiselect_op ::= EXCEPT|INTERSECT */ yytestcase(yyruleno==91); -{yymsp[0].minor.yy394 = yymsp[0].major; /*A-overwrites-OP*/} +{yymsp[0].minor.yy144 = yymsp[0].major; /*A-overwrites-OP*/} break; case 90: /* multiselect_op ::= UNION ALL */ -{yymsp[-1].minor.yy394 = TK_ALL;} +{yymsp[-1].minor.yy144 = TK_ALL;} break; case 92: /* oneselect ::= SELECT distinct selcollist from where_opt groupby_opt having_opt orderby_opt limit_opt */ { - yymsp[-8].minor.yy47 = sqlite3SelectNew(pParse,yymsp[-6].minor.yy322,yymsp[-5].minor.yy131,yymsp[-4].minor.yy528,yymsp[-3].minor.yy322,yymsp[-2].minor.yy528,yymsp[-1].minor.yy322,yymsp[-7].minor.yy394,yymsp[0].minor.yy528); + yymsp[-8].minor.yy555 = sqlite3SelectNew(pParse,yymsp[-6].minor.yy14,yymsp[-5].minor.yy203,yymsp[-4].minor.yy454,yymsp[-3].minor.yy14,yymsp[-2].minor.yy454,yymsp[-1].minor.yy14,yymsp[-7].minor.yy144,yymsp[0].minor.yy454); } break; case 93: /* oneselect ::= SELECT distinct selcollist from where_opt groupby_opt having_opt window_clause orderby_opt limit_opt */ { - yymsp[-9].minor.yy47 = sqlite3SelectNew(pParse,yymsp[-7].minor.yy322,yymsp[-6].minor.yy131,yymsp[-5].minor.yy528,yymsp[-4].minor.yy322,yymsp[-3].minor.yy528,yymsp[-1].minor.yy322,yymsp[-8].minor.yy394,yymsp[0].minor.yy528); - if( yymsp[-9].minor.yy47 ){ - yymsp[-9].minor.yy47->pWinDefn = yymsp[-2].minor.yy41; + yymsp[-9].minor.yy555 = sqlite3SelectNew(pParse,yymsp[-7].minor.yy14,yymsp[-6].minor.yy203,yymsp[-5].minor.yy454,yymsp[-4].minor.yy14,yymsp[-3].minor.yy454,yymsp[-1].minor.yy14,yymsp[-8].minor.yy144,yymsp[0].minor.yy454); + if( yymsp[-9].minor.yy555 ){ + yymsp[-9].minor.yy555->pWinDefn = yymsp[-2].minor.yy211; }else{ - sqlite3WindowListDelete(pParse->db, yymsp[-2].minor.yy41); + sqlite3WindowListDelete(pParse->db, yymsp[-2].minor.yy211); } } break; case 94: /* values ::= VALUES LP nexprlist RP */ { - yymsp[-3].minor.yy47 = sqlite3SelectNew(pParse,yymsp[-1].minor.yy322,0,0,0,0,0,SF_Values,0); + yymsp[-3].minor.yy555 = sqlite3SelectNew(pParse,yymsp[-1].minor.yy14,0,0,0,0,0,SF_Values,0); } break; - case 95: /* values ::= values COMMA LP nexprlist RP */ + case 95: /* oneselect ::= mvalues */ { - Select *pRight, *pLeft = yymsp[-4].minor.yy47; - pRight = sqlite3SelectNew(pParse,yymsp[-1].minor.yy322,0,0,0,0,0,SF_Values|SF_MultiValue,0); - if( ALWAYS(pLeft) ) pLeft->selFlags &= ~SF_MultiValue; - if( pRight ){ - pRight->op = TK_ALL; - pRight->pPrior = pLeft; - yymsp[-4].minor.yy47 = pRight; - }else{ - yymsp[-4].minor.yy47 = pLeft; - } + sqlite3MultiValuesEnd(pParse, yymsp[0].minor.yy555); +} + break; + case 96: /* mvalues ::= values COMMA LP nexprlist RP */ + case 97: /* mvalues ::= mvalues COMMA LP nexprlist RP */ yytestcase(yyruleno==97); +{ + yymsp[-4].minor.yy555 = sqlite3MultiValues(pParse, yymsp[-4].minor.yy555, yymsp[-1].minor.yy14); } break; - case 96: /* distinct ::= DISTINCT */ -{yymsp[0].minor.yy394 = SF_Distinct;} + case 98: /* distinct ::= DISTINCT */ +{yymsp[0].minor.yy144 = SF_Distinct;} break; - case 97: /* distinct ::= ALL */ -{yymsp[0].minor.yy394 = SF_All;} + case 99: /* distinct ::= ALL */ +{yymsp[0].minor.yy144 = SF_All;} break; - case 99: /* sclp ::= */ - case 132: /* orderby_opt ::= */ yytestcase(yyruleno==132); - case 142: /* groupby_opt ::= */ yytestcase(yyruleno==142); - case 230: /* exprlist ::= */ yytestcase(yyruleno==230); - case 233: /* paren_exprlist ::= */ yytestcase(yyruleno==233); - case 238: /* eidlist_opt ::= */ yytestcase(yyruleno==238); -{yymsp[1].minor.yy322 = 0;} + case 101: /* sclp ::= */ + case 134: /* orderby_opt ::= */ yytestcase(yyruleno==134); + case 144: /* groupby_opt ::= */ yytestcase(yyruleno==144); + case 234: /* exprlist ::= */ yytestcase(yyruleno==234); + case 237: /* paren_exprlist ::= */ yytestcase(yyruleno==237); + case 242: /* eidlist_opt ::= */ yytestcase(yyruleno==242); +{yymsp[1].minor.yy14 = 0;} break; - case 100: /* selcollist ::= sclp scanpt expr scanpt as */ + case 102: /* selcollist ::= sclp scanpt expr scanpt as */ { - yymsp[-4].minor.yy322 = sqlite3ExprListAppend(pParse, yymsp[-4].minor.yy322, yymsp[-2].minor.yy528); - if( yymsp[0].minor.yy0.n>0 ) sqlite3ExprListSetName(pParse, yymsp[-4].minor.yy322, &yymsp[0].minor.yy0, 1); - sqlite3ExprListSetSpan(pParse,yymsp[-4].minor.yy322,yymsp[-3].minor.yy522,yymsp[-1].minor.yy522); + yymsp[-4].minor.yy14 = sqlite3ExprListAppend(pParse, yymsp[-4].minor.yy14, yymsp[-2].minor.yy454); + if( yymsp[0].minor.yy0.n>0 ) sqlite3ExprListSetName(pParse, yymsp[-4].minor.yy14, &yymsp[0].minor.yy0, 1); + sqlite3ExprListSetSpan(pParse,yymsp[-4].minor.yy14,yymsp[-3].minor.yy168,yymsp[-1].minor.yy168); } break; - case 101: /* selcollist ::= sclp scanpt STAR */ + case 103: /* selcollist ::= sclp scanpt STAR */ { Expr *p = sqlite3Expr(pParse->db, TK_ASTERISK, 0); sqlite3ExprSetErrorOffset(p, (int)(yymsp[0].minor.yy0.z - pParse->zTail)); - yymsp[-2].minor.yy322 = sqlite3ExprListAppend(pParse, yymsp[-2].minor.yy322, p); + yymsp[-2].minor.yy14 = sqlite3ExprListAppend(pParse, yymsp[-2].minor.yy14, p); } break; - case 102: /* selcollist ::= sclp scanpt nm DOT STAR */ + case 104: /* selcollist ::= sclp scanpt nm DOT STAR */ { Expr *pRight, *pLeft, *pDot; pRight = sqlite3PExpr(pParse, TK_ASTERISK, 0, 0); sqlite3ExprSetErrorOffset(pRight, (int)(yymsp[0].minor.yy0.z - pParse->zTail)); pLeft = tokenExpr(pParse, TK_ID, yymsp[-2].minor.yy0); pDot = sqlite3PExpr(pParse, TK_DOT, pLeft, pRight); - yymsp[-4].minor.yy322 = sqlite3ExprListAppend(pParse,yymsp[-4].minor.yy322, pDot); + yymsp[-4].minor.yy14 = sqlite3ExprListAppend(pParse,yymsp[-4].minor.yy14, pDot); } break; - case 103: /* as ::= AS nm */ - case 115: /* dbnm ::= DOT nm */ yytestcase(yyruleno==115); - case 254: /* plus_num ::= PLUS INTEGER|FLOAT */ yytestcase(yyruleno==254); - case 255: /* minus_num ::= MINUS INTEGER|FLOAT */ yytestcase(yyruleno==255); + case 105: /* as ::= AS nm */ + case 117: /* dbnm ::= DOT nm */ yytestcase(yyruleno==117); + case 258: /* plus_num ::= PLUS INTEGER|FLOAT */ yytestcase(yyruleno==258); + case 259: /* minus_num ::= MINUS INTEGER|FLOAT */ yytestcase(yyruleno==259); {yymsp[-1].minor.yy0 = yymsp[0].minor.yy0;} break; - case 105: /* from ::= */ - case 108: /* stl_prefix ::= */ yytestcase(yyruleno==108); -{yymsp[1].minor.yy131 = 0;} + case 107: /* from ::= */ + case 110: /* stl_prefix ::= */ yytestcase(yyruleno==110); +{yymsp[1].minor.yy203 = 0;} break; - case 106: /* from ::= FROM seltablist */ + case 108: /* from ::= FROM seltablist */ { - yymsp[-1].minor.yy131 = yymsp[0].minor.yy131; - sqlite3SrcListShiftJoinType(pParse,yymsp[-1].minor.yy131); + yymsp[-1].minor.yy203 = yymsp[0].minor.yy203; + sqlite3SrcListShiftJoinType(pParse,yymsp[-1].minor.yy203); } break; - case 107: /* stl_prefix ::= seltablist joinop */ + case 109: /* stl_prefix ::= seltablist joinop */ { - if( ALWAYS(yymsp[-1].minor.yy131 && yymsp[-1].minor.yy131->nSrc>0) ) yymsp[-1].minor.yy131->a[yymsp[-1].minor.yy131->nSrc-1].fg.jointype = (u8)yymsp[0].minor.yy394; + if( ALWAYS(yymsp[-1].minor.yy203 && yymsp[-1].minor.yy203->nSrc>0) ) yymsp[-1].minor.yy203->a[yymsp[-1].minor.yy203->nSrc-1].fg.jointype = (u8)yymsp[0].minor.yy144; } break; - case 109: /* seltablist ::= stl_prefix nm dbnm as on_using */ + case 111: /* seltablist ::= stl_prefix nm dbnm as on_using */ { - yymsp[-4].minor.yy131 = sqlite3SrcListAppendFromTerm(pParse,yymsp[-4].minor.yy131,&yymsp[-3].minor.yy0,&yymsp[-2].minor.yy0,&yymsp[-1].minor.yy0,0,&yymsp[0].minor.yy561); + yymsp[-4].minor.yy203 = sqlite3SrcListAppendFromTerm(pParse,yymsp[-4].minor.yy203,&yymsp[-3].minor.yy0,&yymsp[-2].minor.yy0,&yymsp[-1].minor.yy0,0,&yymsp[0].minor.yy269); } break; - case 110: /* seltablist ::= stl_prefix nm dbnm as indexed_by on_using */ + case 112: /* seltablist ::= stl_prefix nm dbnm as indexed_by on_using */ { - yymsp[-5].minor.yy131 = sqlite3SrcListAppendFromTerm(pParse,yymsp[-5].minor.yy131,&yymsp[-4].minor.yy0,&yymsp[-3].minor.yy0,&yymsp[-2].minor.yy0,0,&yymsp[0].minor.yy561); - sqlite3SrcListIndexedBy(pParse, yymsp[-5].minor.yy131, &yymsp[-1].minor.yy0); + yymsp[-5].minor.yy203 = sqlite3SrcListAppendFromTerm(pParse,yymsp[-5].minor.yy203,&yymsp[-4].minor.yy0,&yymsp[-3].minor.yy0,&yymsp[-2].minor.yy0,0,&yymsp[0].minor.yy269); + sqlite3SrcListIndexedBy(pParse, yymsp[-5].minor.yy203, &yymsp[-1].minor.yy0); } break; - case 111: /* seltablist ::= stl_prefix nm dbnm LP exprlist RP as on_using */ + case 113: /* seltablist ::= stl_prefix nm dbnm LP exprlist RP as on_using */ { - yymsp[-7].minor.yy131 = sqlite3SrcListAppendFromTerm(pParse,yymsp[-7].minor.yy131,&yymsp[-6].minor.yy0,&yymsp[-5].minor.yy0,&yymsp[-1].minor.yy0,0,&yymsp[0].minor.yy561); - sqlite3SrcListFuncArgs(pParse, yymsp[-7].minor.yy131, yymsp[-3].minor.yy322); + yymsp[-7].minor.yy203 = sqlite3SrcListAppendFromTerm(pParse,yymsp[-7].minor.yy203,&yymsp[-6].minor.yy0,&yymsp[-5].minor.yy0,&yymsp[-1].minor.yy0,0,&yymsp[0].minor.yy269); + sqlite3SrcListFuncArgs(pParse, yymsp[-7].minor.yy203, yymsp[-3].minor.yy14); } break; - case 112: /* seltablist ::= stl_prefix LP select RP as on_using */ + case 114: /* seltablist ::= stl_prefix LP select RP as on_using */ { - yymsp[-5].minor.yy131 = sqlite3SrcListAppendFromTerm(pParse,yymsp[-5].minor.yy131,0,0,&yymsp[-1].minor.yy0,yymsp[-3].minor.yy47,&yymsp[0].minor.yy561); + yymsp[-5].minor.yy203 = sqlite3SrcListAppendFromTerm(pParse,yymsp[-5].minor.yy203,0,0,&yymsp[-1].minor.yy0,yymsp[-3].minor.yy555,&yymsp[0].minor.yy269); } break; - case 113: /* seltablist ::= stl_prefix LP seltablist RP as on_using */ + case 115: /* seltablist ::= stl_prefix LP seltablist RP as on_using */ { - if( yymsp[-5].minor.yy131==0 && yymsp[-1].minor.yy0.n==0 && yymsp[0].minor.yy561.pOn==0 && yymsp[0].minor.yy561.pUsing==0 ){ - yymsp[-5].minor.yy131 = yymsp[-3].minor.yy131; - }else if( ALWAYS(yymsp[-3].minor.yy131!=0) && yymsp[-3].minor.yy131->nSrc==1 ){ - yymsp[-5].minor.yy131 = sqlite3SrcListAppendFromTerm(pParse,yymsp[-5].minor.yy131,0,0,&yymsp[-1].minor.yy0,0,&yymsp[0].minor.yy561); - if( yymsp[-5].minor.yy131 ){ - SrcItem *pNew = &yymsp[-5].minor.yy131->a[yymsp[-5].minor.yy131->nSrc-1]; - SrcItem *pOld = yymsp[-3].minor.yy131->a; + if( yymsp[-5].minor.yy203==0 && yymsp[-1].minor.yy0.n==0 && yymsp[0].minor.yy269.pOn==0 && yymsp[0].minor.yy269.pUsing==0 ){ + yymsp[-5].minor.yy203 = yymsp[-3].minor.yy203; + }else if( ALWAYS(yymsp[-3].minor.yy203!=0) && yymsp[-3].minor.yy203->nSrc==1 ){ + yymsp[-5].minor.yy203 = sqlite3SrcListAppendFromTerm(pParse,yymsp[-5].minor.yy203,0,0,&yymsp[-1].minor.yy0,0,&yymsp[0].minor.yy269); + if( yymsp[-5].minor.yy203 ){ + SrcItem *pNew = &yymsp[-5].minor.yy203->a[yymsp[-5].minor.yy203->nSrc-1]; + SrcItem *pOld = yymsp[-3].minor.yy203->a; pNew->zName = pOld->zName; pNew->zDatabase = pOld->zDatabase; pNew->pSelect = pOld->pSelect; @@ -173288,153 +176599,153 @@ static YYACTIONTYPE yy_reduce( pOld->zName = pOld->zDatabase = 0; pOld->pSelect = 0; } - sqlite3SrcListDelete(pParse->db, yymsp[-3].minor.yy131); + sqlite3SrcListDelete(pParse->db, yymsp[-3].minor.yy203); }else{ Select *pSubquery; - sqlite3SrcListShiftJoinType(pParse,yymsp[-3].minor.yy131); - pSubquery = sqlite3SelectNew(pParse,0,yymsp[-3].minor.yy131,0,0,0,0,SF_NestedFrom,0); - yymsp[-5].minor.yy131 = sqlite3SrcListAppendFromTerm(pParse,yymsp[-5].minor.yy131,0,0,&yymsp[-1].minor.yy0,pSubquery,&yymsp[0].minor.yy561); + sqlite3SrcListShiftJoinType(pParse,yymsp[-3].minor.yy203); + pSubquery = sqlite3SelectNew(pParse,0,yymsp[-3].minor.yy203,0,0,0,0,SF_NestedFrom,0); + yymsp[-5].minor.yy203 = sqlite3SrcListAppendFromTerm(pParse,yymsp[-5].minor.yy203,0,0,&yymsp[-1].minor.yy0,pSubquery,&yymsp[0].minor.yy269); } } break; - case 114: /* dbnm ::= */ - case 129: /* indexed_opt ::= */ yytestcase(yyruleno==129); + case 116: /* dbnm ::= */ + case 131: /* indexed_opt ::= */ yytestcase(yyruleno==131); {yymsp[1].minor.yy0.z=0; yymsp[1].minor.yy0.n=0;} break; - case 116: /* fullname ::= nm */ + case 118: /* fullname ::= nm */ { - yylhsminor.yy131 = sqlite3SrcListAppend(pParse,0,&yymsp[0].minor.yy0,0); - if( IN_RENAME_OBJECT && yylhsminor.yy131 ) sqlite3RenameTokenMap(pParse, yylhsminor.yy131->a[0].zName, &yymsp[0].minor.yy0); + yylhsminor.yy203 = sqlite3SrcListAppend(pParse,0,&yymsp[0].minor.yy0,0); + if( IN_RENAME_OBJECT && yylhsminor.yy203 ) sqlite3RenameTokenMap(pParse, yylhsminor.yy203->a[0].zName, &yymsp[0].minor.yy0); } - yymsp[0].minor.yy131 = yylhsminor.yy131; + yymsp[0].minor.yy203 = yylhsminor.yy203; break; - case 117: /* fullname ::= nm DOT nm */ + case 119: /* fullname ::= nm DOT nm */ { - yylhsminor.yy131 = sqlite3SrcListAppend(pParse,0,&yymsp[-2].minor.yy0,&yymsp[0].minor.yy0); - if( IN_RENAME_OBJECT && yylhsminor.yy131 ) sqlite3RenameTokenMap(pParse, yylhsminor.yy131->a[0].zName, &yymsp[0].minor.yy0); + yylhsminor.yy203 = sqlite3SrcListAppend(pParse,0,&yymsp[-2].minor.yy0,&yymsp[0].minor.yy0); + if( IN_RENAME_OBJECT && yylhsminor.yy203 ) sqlite3RenameTokenMap(pParse, yylhsminor.yy203->a[0].zName, &yymsp[0].minor.yy0); } - yymsp[-2].minor.yy131 = yylhsminor.yy131; + yymsp[-2].minor.yy203 = yylhsminor.yy203; break; - case 118: /* xfullname ::= nm */ -{yymsp[0].minor.yy131 = sqlite3SrcListAppend(pParse,0,&yymsp[0].minor.yy0,0); /*A-overwrites-X*/} + case 120: /* xfullname ::= nm */ +{yymsp[0].minor.yy203 = sqlite3SrcListAppend(pParse,0,&yymsp[0].minor.yy0,0); /*A-overwrites-X*/} break; - case 119: /* xfullname ::= nm DOT nm */ -{yymsp[-2].minor.yy131 = sqlite3SrcListAppend(pParse,0,&yymsp[-2].minor.yy0,&yymsp[0].minor.yy0); /*A-overwrites-X*/} + case 121: /* xfullname ::= nm DOT nm */ +{yymsp[-2].minor.yy203 = sqlite3SrcListAppend(pParse,0,&yymsp[-2].minor.yy0,&yymsp[0].minor.yy0); /*A-overwrites-X*/} break; - case 120: /* xfullname ::= nm DOT nm AS nm */ + case 122: /* xfullname ::= nm DOT nm AS nm */ { - yymsp[-4].minor.yy131 = sqlite3SrcListAppend(pParse,0,&yymsp[-4].minor.yy0,&yymsp[-2].minor.yy0); /*A-overwrites-X*/ - if( yymsp[-4].minor.yy131 ) yymsp[-4].minor.yy131->a[0].zAlias = sqlite3NameFromToken(pParse->db, &yymsp[0].minor.yy0); + yymsp[-4].minor.yy203 = sqlite3SrcListAppend(pParse,0,&yymsp[-4].minor.yy0,&yymsp[-2].minor.yy0); /*A-overwrites-X*/ + if( yymsp[-4].minor.yy203 ) yymsp[-4].minor.yy203->a[0].zAlias = sqlite3NameFromToken(pParse->db, &yymsp[0].minor.yy0); } break; - case 121: /* xfullname ::= nm AS nm */ + case 123: /* xfullname ::= nm AS nm */ { - yymsp[-2].minor.yy131 = sqlite3SrcListAppend(pParse,0,&yymsp[-2].minor.yy0,0); /*A-overwrites-X*/ - if( yymsp[-2].minor.yy131 ) yymsp[-2].minor.yy131->a[0].zAlias = sqlite3NameFromToken(pParse->db, &yymsp[0].minor.yy0); + yymsp[-2].minor.yy203 = sqlite3SrcListAppend(pParse,0,&yymsp[-2].minor.yy0,0); /*A-overwrites-X*/ + if( yymsp[-2].minor.yy203 ) yymsp[-2].minor.yy203->a[0].zAlias = sqlite3NameFromToken(pParse->db, &yymsp[0].minor.yy0); } break; - case 122: /* joinop ::= COMMA|JOIN */ -{ yymsp[0].minor.yy394 = JT_INNER; } + case 124: /* joinop ::= COMMA|JOIN */ +{ yymsp[0].minor.yy144 = JT_INNER; } break; - case 123: /* joinop ::= JOIN_KW JOIN */ -{yymsp[-1].minor.yy394 = sqlite3JoinType(pParse,&yymsp[-1].minor.yy0,0,0); /*X-overwrites-A*/} + case 125: /* joinop ::= JOIN_KW JOIN */ +{yymsp[-1].minor.yy144 = sqlite3JoinType(pParse,&yymsp[-1].minor.yy0,0,0); /*X-overwrites-A*/} break; - case 124: /* joinop ::= JOIN_KW nm JOIN */ -{yymsp[-2].minor.yy394 = sqlite3JoinType(pParse,&yymsp[-2].minor.yy0,&yymsp[-1].minor.yy0,0); /*X-overwrites-A*/} + case 126: /* joinop ::= JOIN_KW nm JOIN */ +{yymsp[-2].minor.yy144 = sqlite3JoinType(pParse,&yymsp[-2].minor.yy0,&yymsp[-1].minor.yy0,0); /*X-overwrites-A*/} break; - case 125: /* joinop ::= JOIN_KW nm nm JOIN */ -{yymsp[-3].minor.yy394 = sqlite3JoinType(pParse,&yymsp[-3].minor.yy0,&yymsp[-2].minor.yy0,&yymsp[-1].minor.yy0);/*X-overwrites-A*/} + case 127: /* joinop ::= JOIN_KW nm nm JOIN */ +{yymsp[-3].minor.yy144 = sqlite3JoinType(pParse,&yymsp[-3].minor.yy0,&yymsp[-2].minor.yy0,&yymsp[-1].minor.yy0);/*X-overwrites-A*/} break; - case 126: /* on_using ::= ON expr */ -{yymsp[-1].minor.yy561.pOn = yymsp[0].minor.yy528; yymsp[-1].minor.yy561.pUsing = 0;} + case 128: /* on_using ::= ON expr */ +{yymsp[-1].minor.yy269.pOn = yymsp[0].minor.yy454; yymsp[-1].minor.yy269.pUsing = 0;} break; - case 127: /* on_using ::= USING LP idlist RP */ -{yymsp[-3].minor.yy561.pOn = 0; yymsp[-3].minor.yy561.pUsing = yymsp[-1].minor.yy254;} + case 129: /* on_using ::= USING LP idlist RP */ +{yymsp[-3].minor.yy269.pOn = 0; yymsp[-3].minor.yy269.pUsing = yymsp[-1].minor.yy132;} break; - case 128: /* on_using ::= */ -{yymsp[1].minor.yy561.pOn = 0; yymsp[1].minor.yy561.pUsing = 0;} + case 130: /* on_using ::= */ +{yymsp[1].minor.yy269.pOn = 0; yymsp[1].minor.yy269.pUsing = 0;} break; - case 130: /* indexed_by ::= INDEXED BY nm */ + case 132: /* indexed_by ::= INDEXED BY nm */ {yymsp[-2].minor.yy0 = yymsp[0].minor.yy0;} break; - case 131: /* indexed_by ::= NOT INDEXED */ + case 133: /* indexed_by ::= NOT INDEXED */ {yymsp[-1].minor.yy0.z=0; yymsp[-1].minor.yy0.n=1;} break; - case 133: /* orderby_opt ::= ORDER BY sortlist */ - case 143: /* groupby_opt ::= GROUP BY nexprlist */ yytestcase(yyruleno==143); -{yymsp[-2].minor.yy322 = yymsp[0].minor.yy322;} + case 135: /* orderby_opt ::= ORDER BY sortlist */ + case 145: /* groupby_opt ::= GROUP BY nexprlist */ yytestcase(yyruleno==145); +{yymsp[-2].minor.yy14 = yymsp[0].minor.yy14;} break; - case 134: /* sortlist ::= sortlist COMMA expr sortorder nulls */ + case 136: /* sortlist ::= sortlist COMMA expr sortorder nulls */ { - yymsp[-4].minor.yy322 = sqlite3ExprListAppend(pParse,yymsp[-4].minor.yy322,yymsp[-2].minor.yy528); - sqlite3ExprListSetSortOrder(yymsp[-4].minor.yy322,yymsp[-1].minor.yy394,yymsp[0].minor.yy394); + yymsp[-4].minor.yy14 = sqlite3ExprListAppend(pParse,yymsp[-4].minor.yy14,yymsp[-2].minor.yy454); + sqlite3ExprListSetSortOrder(yymsp[-4].minor.yy14,yymsp[-1].minor.yy144,yymsp[0].minor.yy144); } break; - case 135: /* sortlist ::= expr sortorder nulls */ + case 137: /* sortlist ::= expr sortorder nulls */ { - yymsp[-2].minor.yy322 = sqlite3ExprListAppend(pParse,0,yymsp[-2].minor.yy528); /*A-overwrites-Y*/ - sqlite3ExprListSetSortOrder(yymsp[-2].minor.yy322,yymsp[-1].minor.yy394,yymsp[0].minor.yy394); + yymsp[-2].minor.yy14 = sqlite3ExprListAppend(pParse,0,yymsp[-2].minor.yy454); /*A-overwrites-Y*/ + sqlite3ExprListSetSortOrder(yymsp[-2].minor.yy14,yymsp[-1].minor.yy144,yymsp[0].minor.yy144); } break; - case 136: /* sortorder ::= ASC */ -{yymsp[0].minor.yy394 = SQLITE_SO_ASC;} + case 138: /* sortorder ::= ASC */ +{yymsp[0].minor.yy144 = SQLITE_SO_ASC;} break; - case 137: /* sortorder ::= DESC */ -{yymsp[0].minor.yy394 = SQLITE_SO_DESC;} + case 139: /* sortorder ::= DESC */ +{yymsp[0].minor.yy144 = SQLITE_SO_DESC;} break; - case 138: /* sortorder ::= */ - case 141: /* nulls ::= */ yytestcase(yyruleno==141); -{yymsp[1].minor.yy394 = SQLITE_SO_UNDEFINED;} + case 140: /* sortorder ::= */ + case 143: /* nulls ::= */ yytestcase(yyruleno==143); +{yymsp[1].minor.yy144 = SQLITE_SO_UNDEFINED;} break; - case 139: /* nulls ::= NULLS FIRST */ -{yymsp[-1].minor.yy394 = SQLITE_SO_ASC;} + case 141: /* nulls ::= NULLS FIRST */ +{yymsp[-1].minor.yy144 = SQLITE_SO_ASC;} break; - case 140: /* nulls ::= NULLS LAST */ -{yymsp[-1].minor.yy394 = SQLITE_SO_DESC;} + case 142: /* nulls ::= NULLS LAST */ +{yymsp[-1].minor.yy144 = SQLITE_SO_DESC;} break; - case 144: /* having_opt ::= */ - case 146: /* limit_opt ::= */ yytestcase(yyruleno==146); - case 151: /* where_opt ::= */ yytestcase(yyruleno==151); - case 153: /* where_opt_ret ::= */ yytestcase(yyruleno==153); - case 228: /* case_else ::= */ yytestcase(yyruleno==228); - case 229: /* case_operand ::= */ yytestcase(yyruleno==229); - case 248: /* vinto ::= */ yytestcase(yyruleno==248); -{yymsp[1].minor.yy528 = 0;} + case 146: /* having_opt ::= */ + case 148: /* limit_opt ::= */ yytestcase(yyruleno==148); + case 153: /* where_opt ::= */ yytestcase(yyruleno==153); + case 155: /* where_opt_ret ::= */ yytestcase(yyruleno==155); + case 232: /* case_else ::= */ yytestcase(yyruleno==232); + case 233: /* case_operand ::= */ yytestcase(yyruleno==233); + case 252: /* vinto ::= */ yytestcase(yyruleno==252); +{yymsp[1].minor.yy454 = 0;} break; - case 145: /* having_opt ::= HAVING expr */ - case 152: /* where_opt ::= WHERE expr */ yytestcase(yyruleno==152); - case 154: /* where_opt_ret ::= WHERE expr */ yytestcase(yyruleno==154); - case 227: /* case_else ::= ELSE expr */ yytestcase(yyruleno==227); - case 247: /* vinto ::= INTO expr */ yytestcase(yyruleno==247); -{yymsp[-1].minor.yy528 = yymsp[0].minor.yy528;} + case 147: /* having_opt ::= HAVING expr */ + case 154: /* where_opt ::= WHERE expr */ yytestcase(yyruleno==154); + case 156: /* where_opt_ret ::= WHERE expr */ yytestcase(yyruleno==156); + case 231: /* case_else ::= ELSE expr */ yytestcase(yyruleno==231); + case 251: /* vinto ::= INTO expr */ yytestcase(yyruleno==251); +{yymsp[-1].minor.yy454 = yymsp[0].minor.yy454;} break; - case 147: /* limit_opt ::= LIMIT expr */ -{yymsp[-1].minor.yy528 = sqlite3PExpr(pParse,TK_LIMIT,yymsp[0].minor.yy528,0);} + case 149: /* limit_opt ::= LIMIT expr */ +{yymsp[-1].minor.yy454 = sqlite3PExpr(pParse,TK_LIMIT,yymsp[0].minor.yy454,0);} break; - case 148: /* limit_opt ::= LIMIT expr OFFSET expr */ -{yymsp[-3].minor.yy528 = sqlite3PExpr(pParse,TK_LIMIT,yymsp[-2].minor.yy528,yymsp[0].minor.yy528);} + case 150: /* limit_opt ::= LIMIT expr OFFSET expr */ +{yymsp[-3].minor.yy454 = sqlite3PExpr(pParse,TK_LIMIT,yymsp[-2].minor.yy454,yymsp[0].minor.yy454);} break; - case 149: /* limit_opt ::= LIMIT expr COMMA expr */ -{yymsp[-3].minor.yy528 = sqlite3PExpr(pParse,TK_LIMIT,yymsp[0].minor.yy528,yymsp[-2].minor.yy528);} + case 151: /* limit_opt ::= LIMIT expr COMMA expr */ +{yymsp[-3].minor.yy454 = sqlite3PExpr(pParse,TK_LIMIT,yymsp[0].minor.yy454,yymsp[-2].minor.yy454);} break; - case 150: /* cmd ::= with DELETE FROM xfullname indexed_opt where_opt_ret */ + case 152: /* cmd ::= with DELETE FROM xfullname indexed_opt where_opt_ret */ { - sqlite3SrcListIndexedBy(pParse, yymsp[-2].minor.yy131, &yymsp[-1].minor.yy0); - sqlite3DeleteFrom(pParse,yymsp[-2].minor.yy131,yymsp[0].minor.yy528,0,0); + sqlite3SrcListIndexedBy(pParse, yymsp[-2].minor.yy203, &yymsp[-1].minor.yy0); + sqlite3DeleteFrom(pParse,yymsp[-2].minor.yy203,yymsp[0].minor.yy454,0,0); } break; - case 155: /* where_opt_ret ::= RETURNING selcollist */ -{sqlite3AddReturning(pParse,yymsp[0].minor.yy322); yymsp[-1].minor.yy528 = 0;} + case 157: /* where_opt_ret ::= RETURNING selcollist */ +{sqlite3AddReturning(pParse,yymsp[0].minor.yy14); yymsp[-1].minor.yy454 = 0;} break; - case 156: /* where_opt_ret ::= WHERE expr RETURNING selcollist */ -{sqlite3AddReturning(pParse,yymsp[0].minor.yy322); yymsp[-3].minor.yy528 = yymsp[-2].minor.yy528;} + case 158: /* where_opt_ret ::= WHERE expr RETURNING selcollist */ +{sqlite3AddReturning(pParse,yymsp[0].minor.yy14); yymsp[-3].minor.yy454 = yymsp[-2].minor.yy454;} break; - case 157: /* cmd ::= with UPDATE orconf xfullname indexed_opt SET setlist from where_opt_ret */ + case 159: /* cmd ::= with UPDATE orconf xfullname indexed_opt SET setlist from where_opt_ret */ { - sqlite3SrcListIndexedBy(pParse, yymsp[-5].minor.yy131, &yymsp[-4].minor.yy0); - sqlite3ExprListCheckLength(pParse,yymsp[-2].minor.yy322,"set list"); - if( yymsp[-1].minor.yy131 ){ - SrcList *pFromClause = yymsp[-1].minor.yy131; + sqlite3SrcListIndexedBy(pParse, yymsp[-5].minor.yy203, &yymsp[-4].minor.yy0); + sqlite3ExprListCheckLength(pParse,yymsp[-2].minor.yy14,"set list"); + if( yymsp[-1].minor.yy203 ){ + SrcList *pFromClause = yymsp[-1].minor.yy203; if( pFromClause->nSrc>1 ){ Select *pSubquery; Token as; @@ -173443,92 +176754,92 @@ static YYACTIONTYPE yy_reduce( as.z = 0; pFromClause = sqlite3SrcListAppendFromTerm(pParse,0,0,0,&as,pSubquery,0); } - yymsp[-5].minor.yy131 = sqlite3SrcListAppendList(pParse, yymsp[-5].minor.yy131, pFromClause); + yymsp[-5].minor.yy203 = sqlite3SrcListAppendList(pParse, yymsp[-5].minor.yy203, pFromClause); } - sqlite3Update(pParse,yymsp[-5].minor.yy131,yymsp[-2].minor.yy322,yymsp[0].minor.yy528,yymsp[-6].minor.yy394,0,0,0); + sqlite3Update(pParse,yymsp[-5].minor.yy203,yymsp[-2].minor.yy14,yymsp[0].minor.yy454,yymsp[-6].minor.yy144,0,0,0); } break; - case 158: /* setlist ::= setlist COMMA nm EQ expr */ + case 160: /* setlist ::= setlist COMMA nm EQ expr */ { - yymsp[-4].minor.yy322 = sqlite3ExprListAppend(pParse, yymsp[-4].minor.yy322, yymsp[0].minor.yy528); - sqlite3ExprListSetName(pParse, yymsp[-4].minor.yy322, &yymsp[-2].minor.yy0, 1); + yymsp[-4].minor.yy14 = sqlite3ExprListAppend(pParse, yymsp[-4].minor.yy14, yymsp[0].minor.yy454); + sqlite3ExprListSetName(pParse, yymsp[-4].minor.yy14, &yymsp[-2].minor.yy0, 1); } break; - case 159: /* setlist ::= setlist COMMA LP idlist RP EQ expr */ + case 161: /* setlist ::= setlist COMMA LP idlist RP EQ expr */ { - yymsp[-6].minor.yy322 = sqlite3ExprListAppendVector(pParse, yymsp[-6].minor.yy322, yymsp[-3].minor.yy254, yymsp[0].minor.yy528); + yymsp[-6].minor.yy14 = sqlite3ExprListAppendVector(pParse, yymsp[-6].minor.yy14, yymsp[-3].minor.yy132, yymsp[0].minor.yy454); } break; - case 160: /* setlist ::= nm EQ expr */ + case 162: /* setlist ::= nm EQ expr */ { - yylhsminor.yy322 = sqlite3ExprListAppend(pParse, 0, yymsp[0].minor.yy528); - sqlite3ExprListSetName(pParse, yylhsminor.yy322, &yymsp[-2].minor.yy0, 1); + yylhsminor.yy14 = sqlite3ExprListAppend(pParse, 0, yymsp[0].minor.yy454); + sqlite3ExprListSetName(pParse, yylhsminor.yy14, &yymsp[-2].minor.yy0, 1); } - yymsp[-2].minor.yy322 = yylhsminor.yy322; + yymsp[-2].minor.yy14 = yylhsminor.yy14; break; - case 161: /* setlist ::= LP idlist RP EQ expr */ + case 163: /* setlist ::= LP idlist RP EQ expr */ { - yymsp[-4].minor.yy322 = sqlite3ExprListAppendVector(pParse, 0, yymsp[-3].minor.yy254, yymsp[0].minor.yy528); + yymsp[-4].minor.yy14 = sqlite3ExprListAppendVector(pParse, 0, yymsp[-3].minor.yy132, yymsp[0].minor.yy454); } break; - case 162: /* cmd ::= with insert_cmd INTO xfullname idlist_opt select upsert */ + case 164: /* cmd ::= with insert_cmd INTO xfullname idlist_opt select upsert */ { - sqlite3Insert(pParse, yymsp[-3].minor.yy131, yymsp[-1].minor.yy47, yymsp[-2].minor.yy254, yymsp[-5].minor.yy394, yymsp[0].minor.yy444); + sqlite3Insert(pParse, yymsp[-3].minor.yy203, yymsp[-1].minor.yy555, yymsp[-2].minor.yy132, yymsp[-5].minor.yy144, yymsp[0].minor.yy122); } break; - case 163: /* cmd ::= with insert_cmd INTO xfullname idlist_opt DEFAULT VALUES returning */ + case 165: /* cmd ::= with insert_cmd INTO xfullname idlist_opt DEFAULT VALUES returning */ { - sqlite3Insert(pParse, yymsp[-4].minor.yy131, 0, yymsp[-3].minor.yy254, yymsp[-6].minor.yy394, 0); + sqlite3Insert(pParse, yymsp[-4].minor.yy203, 0, yymsp[-3].minor.yy132, yymsp[-6].minor.yy144, 0); } break; - case 164: /* upsert ::= */ -{ yymsp[1].minor.yy444 = 0; } + case 166: /* upsert ::= */ +{ yymsp[1].minor.yy122 = 0; } break; - case 165: /* upsert ::= RETURNING selcollist */ -{ yymsp[-1].minor.yy444 = 0; sqlite3AddReturning(pParse,yymsp[0].minor.yy322); } + case 167: /* upsert ::= RETURNING selcollist */ +{ yymsp[-1].minor.yy122 = 0; sqlite3AddReturning(pParse,yymsp[0].minor.yy14); } break; - case 166: /* upsert ::= ON CONFLICT LP sortlist RP where_opt DO UPDATE SET setlist where_opt upsert */ -{ yymsp[-11].minor.yy444 = sqlite3UpsertNew(pParse->db,yymsp[-8].minor.yy322,yymsp[-6].minor.yy528,yymsp[-2].minor.yy322,yymsp[-1].minor.yy528,yymsp[0].minor.yy444);} + case 168: /* upsert ::= ON CONFLICT LP sortlist RP where_opt DO UPDATE SET setlist where_opt upsert */ +{ yymsp[-11].minor.yy122 = sqlite3UpsertNew(pParse->db,yymsp[-8].minor.yy14,yymsp[-6].minor.yy454,yymsp[-2].minor.yy14,yymsp[-1].minor.yy454,yymsp[0].minor.yy122);} break; - case 167: /* upsert ::= ON CONFLICT LP sortlist RP where_opt DO NOTHING upsert */ -{ yymsp[-8].minor.yy444 = sqlite3UpsertNew(pParse->db,yymsp[-5].minor.yy322,yymsp[-3].minor.yy528,0,0,yymsp[0].minor.yy444); } + case 169: /* upsert ::= ON CONFLICT LP sortlist RP where_opt DO NOTHING upsert */ +{ yymsp[-8].minor.yy122 = sqlite3UpsertNew(pParse->db,yymsp[-5].minor.yy14,yymsp[-3].minor.yy454,0,0,yymsp[0].minor.yy122); } break; - case 168: /* upsert ::= ON CONFLICT DO NOTHING returning */ -{ yymsp[-4].minor.yy444 = sqlite3UpsertNew(pParse->db,0,0,0,0,0); } + case 170: /* upsert ::= ON CONFLICT DO NOTHING returning */ +{ yymsp[-4].minor.yy122 = sqlite3UpsertNew(pParse->db,0,0,0,0,0); } break; - case 169: /* upsert ::= ON CONFLICT DO UPDATE SET setlist where_opt returning */ -{ yymsp[-7].minor.yy444 = sqlite3UpsertNew(pParse->db,0,0,yymsp[-2].minor.yy322,yymsp[-1].minor.yy528,0);} + case 171: /* upsert ::= ON CONFLICT DO UPDATE SET setlist where_opt returning */ +{ yymsp[-7].minor.yy122 = sqlite3UpsertNew(pParse->db,0,0,yymsp[-2].minor.yy14,yymsp[-1].minor.yy454,0);} break; - case 170: /* returning ::= RETURNING selcollist */ -{sqlite3AddReturning(pParse,yymsp[0].minor.yy322);} + case 172: /* returning ::= RETURNING selcollist */ +{sqlite3AddReturning(pParse,yymsp[0].minor.yy14);} break; - case 173: /* idlist_opt ::= */ -{yymsp[1].minor.yy254 = 0;} + case 175: /* idlist_opt ::= */ +{yymsp[1].minor.yy132 = 0;} break; - case 174: /* idlist_opt ::= LP idlist RP */ -{yymsp[-2].minor.yy254 = yymsp[-1].minor.yy254;} + case 176: /* idlist_opt ::= LP idlist RP */ +{yymsp[-2].minor.yy132 = yymsp[-1].minor.yy132;} break; - case 175: /* idlist ::= idlist COMMA nm */ -{yymsp[-2].minor.yy254 = sqlite3IdListAppend(pParse,yymsp[-2].minor.yy254,&yymsp[0].minor.yy0);} + case 177: /* idlist ::= idlist COMMA nm */ +{yymsp[-2].minor.yy132 = sqlite3IdListAppend(pParse,yymsp[-2].minor.yy132,&yymsp[0].minor.yy0);} break; - case 176: /* idlist ::= nm */ -{yymsp[0].minor.yy254 = sqlite3IdListAppend(pParse,0,&yymsp[0].minor.yy0); /*A-overwrites-Y*/} + case 178: /* idlist ::= nm */ +{yymsp[0].minor.yy132 = sqlite3IdListAppend(pParse,0,&yymsp[0].minor.yy0); /*A-overwrites-Y*/} break; - case 177: /* expr ::= LP expr RP */ -{yymsp[-2].minor.yy528 = yymsp[-1].minor.yy528;} + case 179: /* expr ::= LP expr RP */ +{yymsp[-2].minor.yy454 = yymsp[-1].minor.yy454;} break; - case 178: /* expr ::= ID|INDEXED|JOIN_KW */ -{yymsp[0].minor.yy528=tokenExpr(pParse,TK_ID,yymsp[0].minor.yy0); /*A-overwrites-X*/} + case 180: /* expr ::= ID|INDEXED|JOIN_KW */ +{yymsp[0].minor.yy454=tokenExpr(pParse,TK_ID,yymsp[0].minor.yy0); /*A-overwrites-X*/} break; - case 179: /* expr ::= nm DOT nm */ + case 181: /* expr ::= nm DOT nm */ { Expr *temp1 = tokenExpr(pParse,TK_ID,yymsp[-2].minor.yy0); Expr *temp2 = tokenExpr(pParse,TK_ID,yymsp[0].minor.yy0); - yylhsminor.yy528 = sqlite3PExpr(pParse, TK_DOT, temp1, temp2); + yylhsminor.yy454 = sqlite3PExpr(pParse, TK_DOT, temp1, temp2); } - yymsp[-2].minor.yy528 = yylhsminor.yy528; + yymsp[-2].minor.yy454 = yylhsminor.yy454; break; - case 180: /* expr ::= nm DOT nm DOT nm */ + case 182: /* expr ::= nm DOT nm DOT nm */ { Expr *temp1 = tokenExpr(pParse,TK_ID,yymsp[-4].minor.yy0); Expr *temp2 = tokenExpr(pParse,TK_ID,yymsp[-2].minor.yy0); @@ -173537,27 +176848,27 @@ static YYACTIONTYPE yy_reduce( if( IN_RENAME_OBJECT ){ sqlite3RenameTokenRemap(pParse, 0, temp1); } - yylhsminor.yy528 = sqlite3PExpr(pParse, TK_DOT, temp1, temp4); + yylhsminor.yy454 = sqlite3PExpr(pParse, TK_DOT, temp1, temp4); } - yymsp[-4].minor.yy528 = yylhsminor.yy528; + yymsp[-4].minor.yy454 = yylhsminor.yy454; break; - case 181: /* term ::= NULL|FLOAT|BLOB */ - case 182: /* term ::= STRING */ yytestcase(yyruleno==182); -{yymsp[0].minor.yy528=tokenExpr(pParse,yymsp[0].major,yymsp[0].minor.yy0); /*A-overwrites-X*/} + case 183: /* term ::= NULL|FLOAT|BLOB */ + case 184: /* term ::= STRING */ yytestcase(yyruleno==184); +{yymsp[0].minor.yy454=tokenExpr(pParse,yymsp[0].major,yymsp[0].minor.yy0); /*A-overwrites-X*/} break; - case 183: /* term ::= INTEGER */ + case 185: /* term ::= INTEGER */ { - yylhsminor.yy528 = sqlite3ExprAlloc(pParse->db, TK_INTEGER, &yymsp[0].minor.yy0, 1); - if( yylhsminor.yy528 ) yylhsminor.yy528->w.iOfst = (int)(yymsp[0].minor.yy0.z - pParse->zTail); + yylhsminor.yy454 = sqlite3ExprAlloc(pParse->db, TK_INTEGER, &yymsp[0].minor.yy0, 1); + if( yylhsminor.yy454 ) yylhsminor.yy454->w.iOfst = (int)(yymsp[0].minor.yy0.z - pParse->zTail); } - yymsp[0].minor.yy528 = yylhsminor.yy528; + yymsp[0].minor.yy454 = yylhsminor.yy454; break; - case 184: /* expr ::= VARIABLE */ + case 186: /* expr ::= VARIABLE */ { if( !(yymsp[0].minor.yy0.z[0]=='#' && sqlite3Isdigit(yymsp[0].minor.yy0.z[1])) ){ u32 n = yymsp[0].minor.yy0.n; - yymsp[0].minor.yy528 = tokenExpr(pParse, TK_VARIABLE, yymsp[0].minor.yy0); - sqlite3ExprAssignVarNumber(pParse, yymsp[0].minor.yy528, n); + yymsp[0].minor.yy454 = tokenExpr(pParse, TK_VARIABLE, yymsp[0].minor.yy0); + sqlite3ExprAssignVarNumber(pParse, yymsp[0].minor.yy454, n); }else{ /* When doing a nested parse, one can include terms in an expression ** that look like this: #1 #2 ... These terms refer to registers @@ -173566,179 +176877,203 @@ static YYACTIONTYPE yy_reduce( assert( t.n>=2 ); if( pParse->nested==0 ){ sqlite3ErrorMsg(pParse, "near \"%T\": syntax error", &t); - yymsp[0].minor.yy528 = 0; + yymsp[0].minor.yy454 = 0; }else{ - yymsp[0].minor.yy528 = sqlite3PExpr(pParse, TK_REGISTER, 0, 0); - if( yymsp[0].minor.yy528 ) sqlite3GetInt32(&t.z[1], &yymsp[0].minor.yy528->iTable); + yymsp[0].minor.yy454 = sqlite3PExpr(pParse, TK_REGISTER, 0, 0); + if( yymsp[0].minor.yy454 ) sqlite3GetInt32(&t.z[1], &yymsp[0].minor.yy454->iTable); } } } break; - case 185: /* expr ::= expr COLLATE ID|STRING */ + case 187: /* expr ::= expr COLLATE ID|STRING */ { - yymsp[-2].minor.yy528 = sqlite3ExprAddCollateToken(pParse, yymsp[-2].minor.yy528, &yymsp[0].minor.yy0, 1); + yymsp[-2].minor.yy454 = sqlite3ExprAddCollateToken(pParse, yymsp[-2].minor.yy454, &yymsp[0].minor.yy0, 1); } break; - case 186: /* expr ::= CAST LP expr AS typetoken RP */ + case 188: /* expr ::= CAST LP expr AS typetoken RP */ { - yymsp[-5].minor.yy528 = sqlite3ExprAlloc(pParse->db, TK_CAST, &yymsp[-1].minor.yy0, 1); - sqlite3ExprAttachSubtrees(pParse->db, yymsp[-5].minor.yy528, yymsp[-3].minor.yy528, 0); + yymsp[-5].minor.yy454 = sqlite3ExprAlloc(pParse->db, TK_CAST, &yymsp[-1].minor.yy0, 1); + sqlite3ExprAttachSubtrees(pParse->db, yymsp[-5].minor.yy454, yymsp[-3].minor.yy454, 0); } break; - case 187: /* expr ::= ID|INDEXED|JOIN_KW LP distinct exprlist RP */ + case 189: /* expr ::= ID|INDEXED|JOIN_KW LP distinct exprlist RP */ { - yylhsminor.yy528 = sqlite3ExprFunction(pParse, yymsp[-1].minor.yy322, &yymsp[-4].minor.yy0, yymsp[-2].minor.yy394); + yylhsminor.yy454 = sqlite3ExprFunction(pParse, yymsp[-1].minor.yy14, &yymsp[-4].minor.yy0, yymsp[-2].minor.yy144); } - yymsp[-4].minor.yy528 = yylhsminor.yy528; + yymsp[-4].minor.yy454 = yylhsminor.yy454; break; - case 188: /* expr ::= ID|INDEXED|JOIN_KW LP STAR RP */ + case 190: /* expr ::= ID|INDEXED|JOIN_KW LP distinct exprlist ORDER BY sortlist RP */ { - yylhsminor.yy528 = sqlite3ExprFunction(pParse, 0, &yymsp[-3].minor.yy0, 0); + yylhsminor.yy454 = sqlite3ExprFunction(pParse, yymsp[-4].minor.yy14, &yymsp[-7].minor.yy0, yymsp[-5].minor.yy144); + sqlite3ExprAddFunctionOrderBy(pParse, yylhsminor.yy454, yymsp[-1].minor.yy14); } - yymsp[-3].minor.yy528 = yylhsminor.yy528; + yymsp[-7].minor.yy454 = yylhsminor.yy454; break; - case 189: /* expr ::= ID|INDEXED|JOIN_KW LP distinct exprlist RP filter_over */ + case 191: /* expr ::= ID|INDEXED|JOIN_KW LP STAR RP */ { - yylhsminor.yy528 = sqlite3ExprFunction(pParse, yymsp[-2].minor.yy322, &yymsp[-5].minor.yy0, yymsp[-3].minor.yy394); - sqlite3WindowAttach(pParse, yylhsminor.yy528, yymsp[0].minor.yy41); + yylhsminor.yy454 = sqlite3ExprFunction(pParse, 0, &yymsp[-3].minor.yy0, 0); } - yymsp[-5].minor.yy528 = yylhsminor.yy528; + yymsp[-3].minor.yy454 = yylhsminor.yy454; break; - case 190: /* expr ::= ID|INDEXED|JOIN_KW LP STAR RP filter_over */ + case 192: /* expr ::= ID|INDEXED|JOIN_KW LP distinct exprlist RP filter_over */ { - yylhsminor.yy528 = sqlite3ExprFunction(pParse, 0, &yymsp[-4].minor.yy0, 0); - sqlite3WindowAttach(pParse, yylhsminor.yy528, yymsp[0].minor.yy41); + yylhsminor.yy454 = sqlite3ExprFunction(pParse, yymsp[-2].minor.yy14, &yymsp[-5].minor.yy0, yymsp[-3].minor.yy144); + sqlite3WindowAttach(pParse, yylhsminor.yy454, yymsp[0].minor.yy211); } - yymsp[-4].minor.yy528 = yylhsminor.yy528; + yymsp[-5].minor.yy454 = yylhsminor.yy454; break; - case 191: /* term ::= CTIME_KW */ + case 193: /* expr ::= ID|INDEXED|JOIN_KW LP distinct exprlist ORDER BY sortlist RP filter_over */ { - yylhsminor.yy528 = sqlite3ExprFunction(pParse, 0, &yymsp[0].minor.yy0, 0); + yylhsminor.yy454 = sqlite3ExprFunction(pParse, yymsp[-5].minor.yy14, &yymsp[-8].minor.yy0, yymsp[-6].minor.yy144); + sqlite3WindowAttach(pParse, yylhsminor.yy454, yymsp[0].minor.yy211); + sqlite3ExprAddFunctionOrderBy(pParse, yylhsminor.yy454, yymsp[-2].minor.yy14); } - yymsp[0].minor.yy528 = yylhsminor.yy528; + yymsp[-8].minor.yy454 = yylhsminor.yy454; break; - case 192: /* expr ::= LP nexprlist COMMA expr RP */ + case 194: /* expr ::= ID|INDEXED|JOIN_KW LP STAR RP filter_over */ { - ExprList *pList = sqlite3ExprListAppend(pParse, yymsp[-3].minor.yy322, yymsp[-1].minor.yy528); - yymsp[-4].minor.yy528 = sqlite3PExpr(pParse, TK_VECTOR, 0, 0); - if( yymsp[-4].minor.yy528 ){ - yymsp[-4].minor.yy528->x.pList = pList; + yylhsminor.yy454 = sqlite3ExprFunction(pParse, 0, &yymsp[-4].minor.yy0, 0); + sqlite3WindowAttach(pParse, yylhsminor.yy454, yymsp[0].minor.yy211); +} + yymsp[-4].minor.yy454 = yylhsminor.yy454; + break; + case 195: /* term ::= CTIME_KW */ +{ + yylhsminor.yy454 = sqlite3ExprFunction(pParse, 0, &yymsp[0].minor.yy0, 0); +} + yymsp[0].minor.yy454 = yylhsminor.yy454; + break; + case 196: /* expr ::= LP nexprlist COMMA expr RP */ +{ + ExprList *pList = sqlite3ExprListAppend(pParse, yymsp[-3].minor.yy14, yymsp[-1].minor.yy454); + yymsp[-4].minor.yy454 = sqlite3PExpr(pParse, TK_VECTOR, 0, 0); + if( yymsp[-4].minor.yy454 ){ + yymsp[-4].minor.yy454->x.pList = pList; if( ALWAYS(pList->nExpr) ){ - yymsp[-4].minor.yy528->flags |= pList->a[0].pExpr->flags & EP_Propagate; + yymsp[-4].minor.yy454->flags |= pList->a[0].pExpr->flags & EP_Propagate; } }else{ sqlite3ExprListDelete(pParse->db, pList); } } break; - case 193: /* expr ::= expr AND expr */ -{yymsp[-2].minor.yy528=sqlite3ExprAnd(pParse,yymsp[-2].minor.yy528,yymsp[0].minor.yy528);} + case 197: /* expr ::= expr AND expr */ +{yymsp[-2].minor.yy454=sqlite3ExprAnd(pParse,yymsp[-2].minor.yy454,yymsp[0].minor.yy454);} break; - case 194: /* expr ::= expr OR expr */ - case 195: /* expr ::= expr LT|GT|GE|LE expr */ yytestcase(yyruleno==195); - case 196: /* expr ::= expr EQ|NE expr */ yytestcase(yyruleno==196); - case 197: /* expr ::= expr BITAND|BITOR|LSHIFT|RSHIFT expr */ yytestcase(yyruleno==197); - case 198: /* expr ::= expr PLUS|MINUS expr */ yytestcase(yyruleno==198); - case 199: /* expr ::= expr STAR|SLASH|REM expr */ yytestcase(yyruleno==199); - case 200: /* expr ::= expr CONCAT expr */ yytestcase(yyruleno==200); -{yymsp[-2].minor.yy528=sqlite3PExpr(pParse,yymsp[-1].major,yymsp[-2].minor.yy528,yymsp[0].minor.yy528);} + case 198: /* expr ::= expr OR expr */ + case 199: /* expr ::= expr LT|GT|GE|LE expr */ yytestcase(yyruleno==199); + case 200: /* expr ::= expr EQ|NE expr */ yytestcase(yyruleno==200); + case 201: /* expr ::= expr BITAND|BITOR|LSHIFT|RSHIFT expr */ yytestcase(yyruleno==201); + case 202: /* expr ::= expr PLUS|MINUS expr */ yytestcase(yyruleno==202); + case 203: /* expr ::= expr STAR|SLASH|REM expr */ yytestcase(yyruleno==203); + case 204: /* expr ::= expr CONCAT expr */ yytestcase(yyruleno==204); +{yymsp[-2].minor.yy454=sqlite3PExpr(pParse,yymsp[-1].major,yymsp[-2].minor.yy454,yymsp[0].minor.yy454);} break; - case 201: /* likeop ::= NOT LIKE_KW|MATCH */ + case 205: /* likeop ::= NOT LIKE_KW|MATCH */ {yymsp[-1].minor.yy0=yymsp[0].minor.yy0; yymsp[-1].minor.yy0.n|=0x80000000; /*yymsp[-1].minor.yy0-overwrite-yymsp[0].minor.yy0*/} break; - case 202: /* expr ::= expr likeop expr */ + case 206: /* expr ::= expr likeop expr */ { ExprList *pList; int bNot = yymsp[-1].minor.yy0.n & 0x80000000; yymsp[-1].minor.yy0.n &= 0x7fffffff; - pList = sqlite3ExprListAppend(pParse,0, yymsp[0].minor.yy528); - pList = sqlite3ExprListAppend(pParse,pList, yymsp[-2].minor.yy528); - yymsp[-2].minor.yy528 = sqlite3ExprFunction(pParse, pList, &yymsp[-1].minor.yy0, 0); - if( bNot ) yymsp[-2].minor.yy528 = sqlite3PExpr(pParse, TK_NOT, yymsp[-2].minor.yy528, 0); - if( yymsp[-2].minor.yy528 ) yymsp[-2].minor.yy528->flags |= EP_InfixFunc; + pList = sqlite3ExprListAppend(pParse,0, yymsp[0].minor.yy454); + pList = sqlite3ExprListAppend(pParse,pList, yymsp[-2].minor.yy454); + yymsp[-2].minor.yy454 = sqlite3ExprFunction(pParse, pList, &yymsp[-1].minor.yy0, 0); + if( bNot ) yymsp[-2].minor.yy454 = sqlite3PExpr(pParse, TK_NOT, yymsp[-2].minor.yy454, 0); + if( yymsp[-2].minor.yy454 ) yymsp[-2].minor.yy454->flags |= EP_InfixFunc; } break; - case 203: /* expr ::= expr likeop expr ESCAPE expr */ + case 207: /* expr ::= expr likeop expr ESCAPE expr */ { ExprList *pList; int bNot = yymsp[-3].minor.yy0.n & 0x80000000; yymsp[-3].minor.yy0.n &= 0x7fffffff; - pList = sqlite3ExprListAppend(pParse,0, yymsp[-2].minor.yy528); - pList = sqlite3ExprListAppend(pParse,pList, yymsp[-4].minor.yy528); - pList = sqlite3ExprListAppend(pParse,pList, yymsp[0].minor.yy528); - yymsp[-4].minor.yy528 = sqlite3ExprFunction(pParse, pList, &yymsp[-3].minor.yy0, 0); - if( bNot ) yymsp[-4].minor.yy528 = sqlite3PExpr(pParse, TK_NOT, yymsp[-4].minor.yy528, 0); - if( yymsp[-4].minor.yy528 ) yymsp[-4].minor.yy528->flags |= EP_InfixFunc; + pList = sqlite3ExprListAppend(pParse,0, yymsp[-2].minor.yy454); + pList = sqlite3ExprListAppend(pParse,pList, yymsp[-4].minor.yy454); + pList = sqlite3ExprListAppend(pParse,pList, yymsp[0].minor.yy454); + yymsp[-4].minor.yy454 = sqlite3ExprFunction(pParse, pList, &yymsp[-3].minor.yy0, 0); + if( bNot ) yymsp[-4].minor.yy454 = sqlite3PExpr(pParse, TK_NOT, yymsp[-4].minor.yy454, 0); + if( yymsp[-4].minor.yy454 ) yymsp[-4].minor.yy454->flags |= EP_InfixFunc; } break; - case 204: /* expr ::= expr ISNULL|NOTNULL */ -{yymsp[-1].minor.yy528 = sqlite3PExpr(pParse,yymsp[0].major,yymsp[-1].minor.yy528,0);} + case 208: /* expr ::= expr ISNULL|NOTNULL */ +{yymsp[-1].minor.yy454 = sqlite3PExpr(pParse,yymsp[0].major,yymsp[-1].minor.yy454,0);} break; - case 205: /* expr ::= expr NOT NULL */ -{yymsp[-2].minor.yy528 = sqlite3PExpr(pParse,TK_NOTNULL,yymsp[-2].minor.yy528,0);} + case 209: /* expr ::= expr NOT NULL */ +{yymsp[-2].minor.yy454 = sqlite3PExpr(pParse,TK_NOTNULL,yymsp[-2].minor.yy454,0);} break; - case 206: /* expr ::= expr IS expr */ + case 210: /* expr ::= expr IS expr */ { - yymsp[-2].minor.yy528 = sqlite3PExpr(pParse,TK_IS,yymsp[-2].minor.yy528,yymsp[0].minor.yy528); - binaryToUnaryIfNull(pParse, yymsp[0].minor.yy528, yymsp[-2].minor.yy528, TK_ISNULL); + yymsp[-2].minor.yy454 = sqlite3PExpr(pParse,TK_IS,yymsp[-2].minor.yy454,yymsp[0].minor.yy454); + binaryToUnaryIfNull(pParse, yymsp[0].minor.yy454, yymsp[-2].minor.yy454, TK_ISNULL); } break; - case 207: /* expr ::= expr IS NOT expr */ + case 211: /* expr ::= expr IS NOT expr */ { - yymsp[-3].minor.yy528 = sqlite3PExpr(pParse,TK_ISNOT,yymsp[-3].minor.yy528,yymsp[0].minor.yy528); - binaryToUnaryIfNull(pParse, yymsp[0].minor.yy528, yymsp[-3].minor.yy528, TK_NOTNULL); + yymsp[-3].minor.yy454 = sqlite3PExpr(pParse,TK_ISNOT,yymsp[-3].minor.yy454,yymsp[0].minor.yy454); + binaryToUnaryIfNull(pParse, yymsp[0].minor.yy454, yymsp[-3].minor.yy454, TK_NOTNULL); } break; - case 208: /* expr ::= expr IS NOT DISTINCT FROM expr */ + case 212: /* expr ::= expr IS NOT DISTINCT FROM expr */ { - yymsp[-5].minor.yy528 = sqlite3PExpr(pParse,TK_IS,yymsp[-5].minor.yy528,yymsp[0].minor.yy528); - binaryToUnaryIfNull(pParse, yymsp[0].minor.yy528, yymsp[-5].minor.yy528, TK_ISNULL); + yymsp[-5].minor.yy454 = sqlite3PExpr(pParse,TK_IS,yymsp[-5].minor.yy454,yymsp[0].minor.yy454); + binaryToUnaryIfNull(pParse, yymsp[0].minor.yy454, yymsp[-5].minor.yy454, TK_ISNULL); } break; - case 209: /* expr ::= expr IS DISTINCT FROM expr */ + case 213: /* expr ::= expr IS DISTINCT FROM expr */ { - yymsp[-4].minor.yy528 = sqlite3PExpr(pParse,TK_ISNOT,yymsp[-4].minor.yy528,yymsp[0].minor.yy528); - binaryToUnaryIfNull(pParse, yymsp[0].minor.yy528, yymsp[-4].minor.yy528, TK_NOTNULL); + yymsp[-4].minor.yy454 = sqlite3PExpr(pParse,TK_ISNOT,yymsp[-4].minor.yy454,yymsp[0].minor.yy454); + binaryToUnaryIfNull(pParse, yymsp[0].minor.yy454, yymsp[-4].minor.yy454, TK_NOTNULL); } break; - case 210: /* expr ::= NOT expr */ - case 211: /* expr ::= BITNOT expr */ yytestcase(yyruleno==211); -{yymsp[-1].minor.yy528 = sqlite3PExpr(pParse, yymsp[-1].major, yymsp[0].minor.yy528, 0);/*A-overwrites-B*/} + case 214: /* expr ::= NOT expr */ + case 215: /* expr ::= BITNOT expr */ yytestcase(yyruleno==215); +{yymsp[-1].minor.yy454 = sqlite3PExpr(pParse, yymsp[-1].major, yymsp[0].minor.yy454, 0);/*A-overwrites-B*/} break; - case 212: /* expr ::= PLUS|MINUS expr */ + case 216: /* expr ::= PLUS|MINUS expr */ { - yymsp[-1].minor.yy528 = sqlite3PExpr(pParse, yymsp[-1].major==TK_PLUS ? TK_UPLUS : TK_UMINUS, yymsp[0].minor.yy528, 0); - /*A-overwrites-B*/ + Expr *p = yymsp[0].minor.yy454; + u8 op = yymsp[-1].major + (TK_UPLUS-TK_PLUS); + assert( TK_UPLUS>TK_PLUS ); + assert( TK_UMINUS == TK_MINUS + (TK_UPLUS - TK_PLUS) ); + if( p && p->op==TK_UPLUS ){ + p->op = op; + yymsp[-1].minor.yy454 = p; + }else{ + yymsp[-1].minor.yy454 = sqlite3PExpr(pParse, op, p, 0); + /*A-overwrites-B*/ + } } break; - case 213: /* expr ::= expr PTR expr */ + case 217: /* expr ::= expr PTR expr */ { - ExprList *pList = sqlite3ExprListAppend(pParse, 0, yymsp[-2].minor.yy528); - pList = sqlite3ExprListAppend(pParse, pList, yymsp[0].minor.yy528); - yylhsminor.yy528 = sqlite3ExprFunction(pParse, pList, &yymsp[-1].minor.yy0, 0); + ExprList *pList = sqlite3ExprListAppend(pParse, 0, yymsp[-2].minor.yy454); + pList = sqlite3ExprListAppend(pParse, pList, yymsp[0].minor.yy454); + yylhsminor.yy454 = sqlite3ExprFunction(pParse, pList, &yymsp[-1].minor.yy0, 0); } - yymsp[-2].minor.yy528 = yylhsminor.yy528; + yymsp[-2].minor.yy454 = yylhsminor.yy454; break; - case 214: /* between_op ::= BETWEEN */ - case 217: /* in_op ::= IN */ yytestcase(yyruleno==217); -{yymsp[0].minor.yy394 = 0;} + case 218: /* between_op ::= BETWEEN */ + case 221: /* in_op ::= IN */ yytestcase(yyruleno==221); +{yymsp[0].minor.yy144 = 0;} break; - case 216: /* expr ::= expr between_op expr AND expr */ + case 220: /* expr ::= expr between_op expr AND expr */ { - ExprList *pList = sqlite3ExprListAppend(pParse,0, yymsp[-2].minor.yy528); - pList = sqlite3ExprListAppend(pParse,pList, yymsp[0].minor.yy528); - yymsp[-4].minor.yy528 = sqlite3PExpr(pParse, TK_BETWEEN, yymsp[-4].minor.yy528, 0); - if( yymsp[-4].minor.yy528 ){ - yymsp[-4].minor.yy528->x.pList = pList; + ExprList *pList = sqlite3ExprListAppend(pParse,0, yymsp[-2].minor.yy454); + pList = sqlite3ExprListAppend(pParse,pList, yymsp[0].minor.yy454); + yymsp[-4].minor.yy454 = sqlite3PExpr(pParse, TK_BETWEEN, yymsp[-4].minor.yy454, 0); + if( yymsp[-4].minor.yy454 ){ + yymsp[-4].minor.yy454->x.pList = pList; }else{ sqlite3ExprListDelete(pParse->db, pList); } - if( yymsp[-3].minor.yy394 ) yymsp[-4].minor.yy528 = sqlite3PExpr(pParse, TK_NOT, yymsp[-4].minor.yy528, 0); + if( yymsp[-3].minor.yy144 ) yymsp[-4].minor.yy454 = sqlite3PExpr(pParse, TK_NOT, yymsp[-4].minor.yy454, 0); } break; - case 219: /* expr ::= expr in_op LP exprlist RP */ + case 223: /* expr ::= expr in_op LP exprlist RP */ { - if( yymsp[-1].minor.yy322==0 ){ + if( yymsp[-1].minor.yy14==0 ){ /* Expressions of the form ** ** expr1 IN () @@ -173747,208 +177082,208 @@ static YYACTIONTYPE yy_reduce( ** simplify to constants 0 (false) and 1 (true), respectively, ** regardless of the value of expr1. */ - sqlite3ExprUnmapAndDelete(pParse, yymsp[-4].minor.yy528); - yymsp[-4].minor.yy528 = sqlite3Expr(pParse->db, TK_STRING, yymsp[-3].minor.yy394 ? "true" : "false"); - if( yymsp[-4].minor.yy528 ) sqlite3ExprIdToTrueFalse(yymsp[-4].minor.yy528); - }else{ - Expr *pRHS = yymsp[-1].minor.yy322->a[0].pExpr; - if( yymsp[-1].minor.yy322->nExpr==1 && sqlite3ExprIsConstant(pRHS) && yymsp[-4].minor.yy528->op!=TK_VECTOR ){ - yymsp[-1].minor.yy322->a[0].pExpr = 0; - sqlite3ExprListDelete(pParse->db, yymsp[-1].minor.yy322); + sqlite3ExprUnmapAndDelete(pParse, yymsp[-4].minor.yy454); + yymsp[-4].minor.yy454 = sqlite3Expr(pParse->db, TK_STRING, yymsp[-3].minor.yy144 ? "true" : "false"); + if( yymsp[-4].minor.yy454 ) sqlite3ExprIdToTrueFalse(yymsp[-4].minor.yy454); + }else{ + Expr *pRHS = yymsp[-1].minor.yy14->a[0].pExpr; + if( yymsp[-1].minor.yy14->nExpr==1 && sqlite3ExprIsConstant(pParse,pRHS) && yymsp[-4].minor.yy454->op!=TK_VECTOR ){ + yymsp[-1].minor.yy14->a[0].pExpr = 0; + sqlite3ExprListDelete(pParse->db, yymsp[-1].minor.yy14); pRHS = sqlite3PExpr(pParse, TK_UPLUS, pRHS, 0); - yymsp[-4].minor.yy528 = sqlite3PExpr(pParse, TK_EQ, yymsp[-4].minor.yy528, pRHS); - }else if( yymsp[-1].minor.yy322->nExpr==1 && pRHS->op==TK_SELECT ){ - yymsp[-4].minor.yy528 = sqlite3PExpr(pParse, TK_IN, yymsp[-4].minor.yy528, 0); - sqlite3PExprAddSelect(pParse, yymsp[-4].minor.yy528, pRHS->x.pSelect); + yymsp[-4].minor.yy454 = sqlite3PExpr(pParse, TK_EQ, yymsp[-4].minor.yy454, pRHS); + }else if( yymsp[-1].minor.yy14->nExpr==1 && pRHS->op==TK_SELECT ){ + yymsp[-4].minor.yy454 = sqlite3PExpr(pParse, TK_IN, yymsp[-4].minor.yy454, 0); + sqlite3PExprAddSelect(pParse, yymsp[-4].minor.yy454, pRHS->x.pSelect); pRHS->x.pSelect = 0; - sqlite3ExprListDelete(pParse->db, yymsp[-1].minor.yy322); - }else{ - yymsp[-4].minor.yy528 = sqlite3PExpr(pParse, TK_IN, yymsp[-4].minor.yy528, 0); - if( yymsp[-4].minor.yy528==0 ){ - sqlite3ExprListDelete(pParse->db, yymsp[-1].minor.yy322); - }else if( yymsp[-4].minor.yy528->pLeft->op==TK_VECTOR ){ - int nExpr = yymsp[-4].minor.yy528->pLeft->x.pList->nExpr; - Select *pSelectRHS = sqlite3ExprListToValues(pParse, nExpr, yymsp[-1].minor.yy322); + sqlite3ExprListDelete(pParse->db, yymsp[-1].minor.yy14); + }else{ + yymsp[-4].minor.yy454 = sqlite3PExpr(pParse, TK_IN, yymsp[-4].minor.yy454, 0); + if( yymsp[-4].minor.yy454==0 ){ + sqlite3ExprListDelete(pParse->db, yymsp[-1].minor.yy14); + }else if( yymsp[-4].minor.yy454->pLeft->op==TK_VECTOR ){ + int nExpr = yymsp[-4].minor.yy454->pLeft->x.pList->nExpr; + Select *pSelectRHS = sqlite3ExprListToValues(pParse, nExpr, yymsp[-1].minor.yy14); if( pSelectRHS ){ parserDoubleLinkSelect(pParse, pSelectRHS); - sqlite3PExprAddSelect(pParse, yymsp[-4].minor.yy528, pSelectRHS); + sqlite3PExprAddSelect(pParse, yymsp[-4].minor.yy454, pSelectRHS); } }else{ - yymsp[-4].minor.yy528->x.pList = yymsp[-1].minor.yy322; - sqlite3ExprSetHeightAndFlags(pParse, yymsp[-4].minor.yy528); + yymsp[-4].minor.yy454->x.pList = yymsp[-1].minor.yy14; + sqlite3ExprSetHeightAndFlags(pParse, yymsp[-4].minor.yy454); } } - if( yymsp[-3].minor.yy394 ) yymsp[-4].minor.yy528 = sqlite3PExpr(pParse, TK_NOT, yymsp[-4].minor.yy528, 0); + if( yymsp[-3].minor.yy144 ) yymsp[-4].minor.yy454 = sqlite3PExpr(pParse, TK_NOT, yymsp[-4].minor.yy454, 0); } } break; - case 220: /* expr ::= LP select RP */ + case 224: /* expr ::= LP select RP */ { - yymsp[-2].minor.yy528 = sqlite3PExpr(pParse, TK_SELECT, 0, 0); - sqlite3PExprAddSelect(pParse, yymsp[-2].minor.yy528, yymsp[-1].minor.yy47); + yymsp[-2].minor.yy454 = sqlite3PExpr(pParse, TK_SELECT, 0, 0); + sqlite3PExprAddSelect(pParse, yymsp[-2].minor.yy454, yymsp[-1].minor.yy555); } break; - case 221: /* expr ::= expr in_op LP select RP */ + case 225: /* expr ::= expr in_op LP select RP */ { - yymsp[-4].minor.yy528 = sqlite3PExpr(pParse, TK_IN, yymsp[-4].minor.yy528, 0); - sqlite3PExprAddSelect(pParse, yymsp[-4].minor.yy528, yymsp[-1].minor.yy47); - if( yymsp[-3].minor.yy394 ) yymsp[-4].minor.yy528 = sqlite3PExpr(pParse, TK_NOT, yymsp[-4].minor.yy528, 0); + yymsp[-4].minor.yy454 = sqlite3PExpr(pParse, TK_IN, yymsp[-4].minor.yy454, 0); + sqlite3PExprAddSelect(pParse, yymsp[-4].minor.yy454, yymsp[-1].minor.yy555); + if( yymsp[-3].minor.yy144 ) yymsp[-4].minor.yy454 = sqlite3PExpr(pParse, TK_NOT, yymsp[-4].minor.yy454, 0); } break; - case 222: /* expr ::= expr in_op nm dbnm paren_exprlist */ + case 226: /* expr ::= expr in_op nm dbnm paren_exprlist */ { SrcList *pSrc = sqlite3SrcListAppend(pParse, 0,&yymsp[-2].minor.yy0,&yymsp[-1].minor.yy0); Select *pSelect = sqlite3SelectNew(pParse, 0,pSrc,0,0,0,0,0,0); - if( yymsp[0].minor.yy322 ) sqlite3SrcListFuncArgs(pParse, pSelect ? pSrc : 0, yymsp[0].minor.yy322); - yymsp[-4].minor.yy528 = sqlite3PExpr(pParse, TK_IN, yymsp[-4].minor.yy528, 0); - sqlite3PExprAddSelect(pParse, yymsp[-4].minor.yy528, pSelect); - if( yymsp[-3].minor.yy394 ) yymsp[-4].minor.yy528 = sqlite3PExpr(pParse, TK_NOT, yymsp[-4].minor.yy528, 0); + if( yymsp[0].minor.yy14 ) sqlite3SrcListFuncArgs(pParse, pSelect ? pSrc : 0, yymsp[0].minor.yy14); + yymsp[-4].minor.yy454 = sqlite3PExpr(pParse, TK_IN, yymsp[-4].minor.yy454, 0); + sqlite3PExprAddSelect(pParse, yymsp[-4].minor.yy454, pSelect); + if( yymsp[-3].minor.yy144 ) yymsp[-4].minor.yy454 = sqlite3PExpr(pParse, TK_NOT, yymsp[-4].minor.yy454, 0); } break; - case 223: /* expr ::= EXISTS LP select RP */ + case 227: /* expr ::= EXISTS LP select RP */ { Expr *p; - p = yymsp[-3].minor.yy528 = sqlite3PExpr(pParse, TK_EXISTS, 0, 0); - sqlite3PExprAddSelect(pParse, p, yymsp[-1].minor.yy47); + p = yymsp[-3].minor.yy454 = sqlite3PExpr(pParse, TK_EXISTS, 0, 0); + sqlite3PExprAddSelect(pParse, p, yymsp[-1].minor.yy555); } break; - case 224: /* expr ::= CASE case_operand case_exprlist case_else END */ + case 228: /* expr ::= CASE case_operand case_exprlist case_else END */ { - yymsp[-4].minor.yy528 = sqlite3PExpr(pParse, TK_CASE, yymsp[-3].minor.yy528, 0); - if( yymsp[-4].minor.yy528 ){ - yymsp[-4].minor.yy528->x.pList = yymsp[-1].minor.yy528 ? sqlite3ExprListAppend(pParse,yymsp[-2].minor.yy322,yymsp[-1].minor.yy528) : yymsp[-2].minor.yy322; - sqlite3ExprSetHeightAndFlags(pParse, yymsp[-4].minor.yy528); + yymsp[-4].minor.yy454 = sqlite3PExpr(pParse, TK_CASE, yymsp[-3].minor.yy454, 0); + if( yymsp[-4].minor.yy454 ){ + yymsp[-4].minor.yy454->x.pList = yymsp[-1].minor.yy454 ? sqlite3ExprListAppend(pParse,yymsp[-2].minor.yy14,yymsp[-1].minor.yy454) : yymsp[-2].minor.yy14; + sqlite3ExprSetHeightAndFlags(pParse, yymsp[-4].minor.yy454); }else{ - sqlite3ExprListDelete(pParse->db, yymsp[-2].minor.yy322); - sqlite3ExprDelete(pParse->db, yymsp[-1].minor.yy528); + sqlite3ExprListDelete(pParse->db, yymsp[-2].minor.yy14); + sqlite3ExprDelete(pParse->db, yymsp[-1].minor.yy454); } } break; - case 225: /* case_exprlist ::= case_exprlist WHEN expr THEN expr */ + case 229: /* case_exprlist ::= case_exprlist WHEN expr THEN expr */ { - yymsp[-4].minor.yy322 = sqlite3ExprListAppend(pParse,yymsp[-4].minor.yy322, yymsp[-2].minor.yy528); - yymsp[-4].minor.yy322 = sqlite3ExprListAppend(pParse,yymsp[-4].minor.yy322, yymsp[0].minor.yy528); + yymsp[-4].minor.yy14 = sqlite3ExprListAppend(pParse,yymsp[-4].minor.yy14, yymsp[-2].minor.yy454); + yymsp[-4].minor.yy14 = sqlite3ExprListAppend(pParse,yymsp[-4].minor.yy14, yymsp[0].minor.yy454); } break; - case 226: /* case_exprlist ::= WHEN expr THEN expr */ + case 230: /* case_exprlist ::= WHEN expr THEN expr */ { - yymsp[-3].minor.yy322 = sqlite3ExprListAppend(pParse,0, yymsp[-2].minor.yy528); - yymsp[-3].minor.yy322 = sqlite3ExprListAppend(pParse,yymsp[-3].minor.yy322, yymsp[0].minor.yy528); + yymsp[-3].minor.yy14 = sqlite3ExprListAppend(pParse,0, yymsp[-2].minor.yy454); + yymsp[-3].minor.yy14 = sqlite3ExprListAppend(pParse,yymsp[-3].minor.yy14, yymsp[0].minor.yy454); } break; - case 231: /* nexprlist ::= nexprlist COMMA expr */ -{yymsp[-2].minor.yy322 = sqlite3ExprListAppend(pParse,yymsp[-2].minor.yy322,yymsp[0].minor.yy528);} + case 235: /* nexprlist ::= nexprlist COMMA expr */ +{yymsp[-2].minor.yy14 = sqlite3ExprListAppend(pParse,yymsp[-2].minor.yy14,yymsp[0].minor.yy454);} break; - case 232: /* nexprlist ::= expr */ -{yymsp[0].minor.yy322 = sqlite3ExprListAppend(pParse,0,yymsp[0].minor.yy528); /*A-overwrites-Y*/} + case 236: /* nexprlist ::= expr */ +{yymsp[0].minor.yy14 = sqlite3ExprListAppend(pParse,0,yymsp[0].minor.yy454); /*A-overwrites-Y*/} break; - case 234: /* paren_exprlist ::= LP exprlist RP */ - case 239: /* eidlist_opt ::= LP eidlist RP */ yytestcase(yyruleno==239); -{yymsp[-2].minor.yy322 = yymsp[-1].minor.yy322;} + case 238: /* paren_exprlist ::= LP exprlist RP */ + case 243: /* eidlist_opt ::= LP eidlist RP */ yytestcase(yyruleno==243); +{yymsp[-2].minor.yy14 = yymsp[-1].minor.yy14;} break; - case 235: /* cmd ::= createkw uniqueflag INDEX ifnotexists nm dbnm ON nm LP sortlist RP where_opt */ + case 239: /* cmd ::= createkw uniqueflag INDEX ifnotexists nm dbnm ON nm LP sortlist RP where_opt */ { sqlite3CreateIndex(pParse, &yymsp[-7].minor.yy0, &yymsp[-6].minor.yy0, - sqlite3SrcListAppend(pParse,0,&yymsp[-4].minor.yy0,0), yymsp[-2].minor.yy322, yymsp[-10].minor.yy394, - &yymsp[-11].minor.yy0, yymsp[0].minor.yy528, SQLITE_SO_ASC, yymsp[-8].minor.yy394, SQLITE_IDXTYPE_APPDEF); + sqlite3SrcListAppend(pParse,0,&yymsp[-4].minor.yy0,0), yymsp[-2].minor.yy14, yymsp[-10].minor.yy144, + &yymsp[-11].minor.yy0, yymsp[0].minor.yy454, SQLITE_SO_ASC, yymsp[-8].minor.yy144, SQLITE_IDXTYPE_APPDEF); if( IN_RENAME_OBJECT && pParse->pNewIndex ){ sqlite3RenameTokenMap(pParse, pParse->pNewIndex->zName, &yymsp[-4].minor.yy0); } } break; - case 236: /* uniqueflag ::= UNIQUE */ - case 278: /* raisetype ::= ABORT */ yytestcase(yyruleno==278); -{yymsp[0].minor.yy394 = OE_Abort;} + case 240: /* uniqueflag ::= UNIQUE */ + case 282: /* raisetype ::= ABORT */ yytestcase(yyruleno==282); +{yymsp[0].minor.yy144 = OE_Abort;} break; - case 237: /* uniqueflag ::= */ -{yymsp[1].minor.yy394 = OE_None;} + case 241: /* uniqueflag ::= */ +{yymsp[1].minor.yy144 = OE_None;} break; - case 240: /* eidlist ::= eidlist COMMA nm collate sortorder */ + case 244: /* eidlist ::= eidlist COMMA nm collate sortorder */ { - yymsp[-4].minor.yy322 = parserAddExprIdListTerm(pParse, yymsp[-4].minor.yy322, &yymsp[-2].minor.yy0, yymsp[-1].minor.yy394, yymsp[0].minor.yy394); + yymsp[-4].minor.yy14 = parserAddExprIdListTerm(pParse, yymsp[-4].minor.yy14, &yymsp[-2].minor.yy0, yymsp[-1].minor.yy144, yymsp[0].minor.yy144); } break; - case 241: /* eidlist ::= nm collate sortorder */ + case 245: /* eidlist ::= nm collate sortorder */ { - yymsp[-2].minor.yy322 = parserAddExprIdListTerm(pParse, 0, &yymsp[-2].minor.yy0, yymsp[-1].minor.yy394, yymsp[0].minor.yy394); /*A-overwrites-Y*/ + yymsp[-2].minor.yy14 = parserAddExprIdListTerm(pParse, 0, &yymsp[-2].minor.yy0, yymsp[-1].minor.yy144, yymsp[0].minor.yy144); /*A-overwrites-Y*/ } break; - case 244: /* cmd ::= DROP INDEX ifexists fullname */ -{sqlite3DropIndex(pParse, yymsp[0].minor.yy131, yymsp[-1].minor.yy394);} + case 248: /* cmd ::= DROP INDEX ifexists fullname */ +{sqlite3DropIndex(pParse, yymsp[0].minor.yy203, yymsp[-1].minor.yy144);} break; - case 245: /* cmd ::= VACUUM vinto */ -{sqlite3Vacuum(pParse,0,yymsp[0].minor.yy528);} + case 249: /* cmd ::= VACUUM vinto */ +{sqlite3Vacuum(pParse,0,yymsp[0].minor.yy454);} break; - case 246: /* cmd ::= VACUUM nm vinto */ -{sqlite3Vacuum(pParse,&yymsp[-1].minor.yy0,yymsp[0].minor.yy528);} + case 250: /* cmd ::= VACUUM nm vinto */ +{sqlite3Vacuum(pParse,&yymsp[-1].minor.yy0,yymsp[0].minor.yy454);} break; - case 249: /* cmd ::= PRAGMA nm dbnm */ + case 253: /* cmd ::= PRAGMA nm dbnm */ {sqlite3Pragma(pParse,&yymsp[-1].minor.yy0,&yymsp[0].minor.yy0,0,0);} break; - case 250: /* cmd ::= PRAGMA nm dbnm EQ nmnum */ + case 254: /* cmd ::= PRAGMA nm dbnm EQ nmnum */ {sqlite3Pragma(pParse,&yymsp[-3].minor.yy0,&yymsp[-2].minor.yy0,&yymsp[0].minor.yy0,0);} break; - case 251: /* cmd ::= PRAGMA nm dbnm LP nmnum RP */ + case 255: /* cmd ::= PRAGMA nm dbnm LP nmnum RP */ {sqlite3Pragma(pParse,&yymsp[-4].minor.yy0,&yymsp[-3].minor.yy0,&yymsp[-1].minor.yy0,0);} break; - case 252: /* cmd ::= PRAGMA nm dbnm EQ minus_num */ + case 256: /* cmd ::= PRAGMA nm dbnm EQ minus_num */ {sqlite3Pragma(pParse,&yymsp[-3].minor.yy0,&yymsp[-2].minor.yy0,&yymsp[0].minor.yy0,1);} break; - case 253: /* cmd ::= PRAGMA nm dbnm LP minus_num RP */ + case 257: /* cmd ::= PRAGMA nm dbnm LP minus_num RP */ {sqlite3Pragma(pParse,&yymsp[-4].minor.yy0,&yymsp[-3].minor.yy0,&yymsp[-1].minor.yy0,1);} break; - case 256: /* cmd ::= createkw trigger_decl BEGIN trigger_cmd_list END */ + case 260: /* cmd ::= createkw trigger_decl BEGIN trigger_cmd_list END */ { Token all; all.z = yymsp[-3].minor.yy0.z; all.n = (int)(yymsp[0].minor.yy0.z - yymsp[-3].minor.yy0.z) + yymsp[0].minor.yy0.n; - sqlite3FinishTrigger(pParse, yymsp[-1].minor.yy33, &all); + sqlite3FinishTrigger(pParse, yymsp[-1].minor.yy427, &all); } break; - case 257: /* trigger_decl ::= temp TRIGGER ifnotexists nm dbnm trigger_time trigger_event ON fullname foreach_clause when_clause */ + case 261: /* trigger_decl ::= temp TRIGGER ifnotexists nm dbnm trigger_time trigger_event ON fullname foreach_clause when_clause */ { - sqlite3BeginTrigger(pParse, &yymsp[-7].minor.yy0, &yymsp[-6].minor.yy0, yymsp[-5].minor.yy394, yymsp[-4].minor.yy180.a, yymsp[-4].minor.yy180.b, yymsp[-2].minor.yy131, yymsp[0].minor.yy528, yymsp[-10].minor.yy394, yymsp[-8].minor.yy394); + sqlite3BeginTrigger(pParse, &yymsp[-7].minor.yy0, &yymsp[-6].minor.yy0, yymsp[-5].minor.yy144, yymsp[-4].minor.yy286.a, yymsp[-4].minor.yy286.b, yymsp[-2].minor.yy203, yymsp[0].minor.yy454, yymsp[-10].minor.yy144, yymsp[-8].minor.yy144); yymsp[-10].minor.yy0 = (yymsp[-6].minor.yy0.n==0?yymsp[-7].minor.yy0:yymsp[-6].minor.yy0); /*A-overwrites-T*/ } break; - case 258: /* trigger_time ::= BEFORE|AFTER */ -{ yymsp[0].minor.yy394 = yymsp[0].major; /*A-overwrites-X*/ } + case 262: /* trigger_time ::= BEFORE|AFTER */ +{ yymsp[0].minor.yy144 = yymsp[0].major; /*A-overwrites-X*/ } break; - case 259: /* trigger_time ::= INSTEAD OF */ -{ yymsp[-1].minor.yy394 = TK_INSTEAD;} + case 263: /* trigger_time ::= INSTEAD OF */ +{ yymsp[-1].minor.yy144 = TK_INSTEAD;} break; - case 260: /* trigger_time ::= */ -{ yymsp[1].minor.yy394 = TK_BEFORE; } + case 264: /* trigger_time ::= */ +{ yymsp[1].minor.yy144 = TK_BEFORE; } break; - case 261: /* trigger_event ::= DELETE|INSERT */ - case 262: /* trigger_event ::= UPDATE */ yytestcase(yyruleno==262); -{yymsp[0].minor.yy180.a = yymsp[0].major; /*A-overwrites-X*/ yymsp[0].minor.yy180.b = 0;} + case 265: /* trigger_event ::= DELETE|INSERT */ + case 266: /* trigger_event ::= UPDATE */ yytestcase(yyruleno==266); +{yymsp[0].minor.yy286.a = yymsp[0].major; /*A-overwrites-X*/ yymsp[0].minor.yy286.b = 0;} break; - case 263: /* trigger_event ::= UPDATE OF idlist */ -{yymsp[-2].minor.yy180.a = TK_UPDATE; yymsp[-2].minor.yy180.b = yymsp[0].minor.yy254;} + case 267: /* trigger_event ::= UPDATE OF idlist */ +{yymsp[-2].minor.yy286.a = TK_UPDATE; yymsp[-2].minor.yy286.b = yymsp[0].minor.yy132;} break; - case 264: /* when_clause ::= */ - case 283: /* key_opt ::= */ yytestcase(yyruleno==283); -{ yymsp[1].minor.yy528 = 0; } + case 268: /* when_clause ::= */ + case 287: /* key_opt ::= */ yytestcase(yyruleno==287); +{ yymsp[1].minor.yy454 = 0; } break; - case 265: /* when_clause ::= WHEN expr */ - case 284: /* key_opt ::= KEY expr */ yytestcase(yyruleno==284); -{ yymsp[-1].minor.yy528 = yymsp[0].minor.yy528; } + case 269: /* when_clause ::= WHEN expr */ + case 288: /* key_opt ::= KEY expr */ yytestcase(yyruleno==288); +{ yymsp[-1].minor.yy454 = yymsp[0].minor.yy454; } break; - case 266: /* trigger_cmd_list ::= trigger_cmd_list trigger_cmd SEMI */ + case 270: /* trigger_cmd_list ::= trigger_cmd_list trigger_cmd SEMI */ { - assert( yymsp[-2].minor.yy33!=0 ); - yymsp[-2].minor.yy33->pLast->pNext = yymsp[-1].minor.yy33; - yymsp[-2].minor.yy33->pLast = yymsp[-1].minor.yy33; + assert( yymsp[-2].minor.yy427!=0 ); + yymsp[-2].minor.yy427->pLast->pNext = yymsp[-1].minor.yy427; + yymsp[-2].minor.yy427->pLast = yymsp[-1].minor.yy427; } break; - case 267: /* trigger_cmd_list ::= trigger_cmd SEMI */ + case 271: /* trigger_cmd_list ::= trigger_cmd SEMI */ { - assert( yymsp[-1].minor.yy33!=0 ); - yymsp[-1].minor.yy33->pLast = yymsp[-1].minor.yy33; + assert( yymsp[-1].minor.yy427!=0 ); + yymsp[-1].minor.yy427->pLast = yymsp[-1].minor.yy427; } break; - case 268: /* trnm ::= nm DOT nm */ + case 272: /* trnm ::= nm DOT nm */ { yymsp[-2].minor.yy0 = yymsp[0].minor.yy0; sqlite3ErrorMsg(pParse, @@ -173956,367 +177291,377 @@ static YYACTIONTYPE yy_reduce( "statements within triggers"); } break; - case 269: /* tridxby ::= INDEXED BY nm */ + case 273: /* tridxby ::= INDEXED BY nm */ { sqlite3ErrorMsg(pParse, "the INDEXED BY clause is not allowed on UPDATE or DELETE statements " "within triggers"); } break; - case 270: /* tridxby ::= NOT INDEXED */ + case 274: /* tridxby ::= NOT INDEXED */ { sqlite3ErrorMsg(pParse, "the NOT INDEXED clause is not allowed on UPDATE or DELETE statements " "within triggers"); } break; - case 271: /* trigger_cmd ::= UPDATE orconf trnm tridxby SET setlist from where_opt scanpt */ -{yylhsminor.yy33 = sqlite3TriggerUpdateStep(pParse, &yymsp[-6].minor.yy0, yymsp[-2].minor.yy131, yymsp[-3].minor.yy322, yymsp[-1].minor.yy528, yymsp[-7].minor.yy394, yymsp[-8].minor.yy0.z, yymsp[0].minor.yy522);} - yymsp[-8].minor.yy33 = yylhsminor.yy33; + case 275: /* trigger_cmd ::= UPDATE orconf trnm tridxby SET setlist from where_opt scanpt */ +{yylhsminor.yy427 = sqlite3TriggerUpdateStep(pParse, &yymsp[-6].minor.yy0, yymsp[-2].minor.yy203, yymsp[-3].minor.yy14, yymsp[-1].minor.yy454, yymsp[-7].minor.yy144, yymsp[-8].minor.yy0.z, yymsp[0].minor.yy168);} + yymsp[-8].minor.yy427 = yylhsminor.yy427; break; - case 272: /* trigger_cmd ::= scanpt insert_cmd INTO trnm idlist_opt select upsert scanpt */ + case 276: /* trigger_cmd ::= scanpt insert_cmd INTO trnm idlist_opt select upsert scanpt */ { - yylhsminor.yy33 = sqlite3TriggerInsertStep(pParse,&yymsp[-4].minor.yy0,yymsp[-3].minor.yy254,yymsp[-2].minor.yy47,yymsp[-6].minor.yy394,yymsp[-1].minor.yy444,yymsp[-7].minor.yy522,yymsp[0].minor.yy522);/*yylhsminor.yy33-overwrites-yymsp[-6].minor.yy394*/ + yylhsminor.yy427 = sqlite3TriggerInsertStep(pParse,&yymsp[-4].minor.yy0,yymsp[-3].minor.yy132,yymsp[-2].minor.yy555,yymsp[-6].minor.yy144,yymsp[-1].minor.yy122,yymsp[-7].minor.yy168,yymsp[0].minor.yy168);/*yylhsminor.yy427-overwrites-yymsp[-6].minor.yy144*/ } - yymsp[-7].minor.yy33 = yylhsminor.yy33; + yymsp[-7].minor.yy427 = yylhsminor.yy427; break; - case 273: /* trigger_cmd ::= DELETE FROM trnm tridxby where_opt scanpt */ -{yylhsminor.yy33 = sqlite3TriggerDeleteStep(pParse, &yymsp[-3].minor.yy0, yymsp[-1].minor.yy528, yymsp[-5].minor.yy0.z, yymsp[0].minor.yy522);} - yymsp[-5].minor.yy33 = yylhsminor.yy33; + case 277: /* trigger_cmd ::= DELETE FROM trnm tridxby where_opt scanpt */ +{yylhsminor.yy427 = sqlite3TriggerDeleteStep(pParse, &yymsp[-3].minor.yy0, yymsp[-1].minor.yy454, yymsp[-5].minor.yy0.z, yymsp[0].minor.yy168);} + yymsp[-5].minor.yy427 = yylhsminor.yy427; break; - case 274: /* trigger_cmd ::= scanpt select scanpt */ -{yylhsminor.yy33 = sqlite3TriggerSelectStep(pParse->db, yymsp[-1].minor.yy47, yymsp[-2].minor.yy522, yymsp[0].minor.yy522); /*yylhsminor.yy33-overwrites-yymsp[-1].minor.yy47*/} - yymsp[-2].minor.yy33 = yylhsminor.yy33; + case 278: /* trigger_cmd ::= scanpt select scanpt */ +{yylhsminor.yy427 = sqlite3TriggerSelectStep(pParse->db, yymsp[-1].minor.yy555, yymsp[-2].minor.yy168, yymsp[0].minor.yy168); /*yylhsminor.yy427-overwrites-yymsp[-1].minor.yy555*/} + yymsp[-2].minor.yy427 = yylhsminor.yy427; break; - case 275: /* expr ::= RAISE LP IGNORE RP */ + case 279: /* expr ::= RAISE LP IGNORE RP */ { - yymsp[-3].minor.yy528 = sqlite3PExpr(pParse, TK_RAISE, 0, 0); - if( yymsp[-3].minor.yy528 ){ - yymsp[-3].minor.yy528->affExpr = OE_Ignore; + yymsp[-3].minor.yy454 = sqlite3PExpr(pParse, TK_RAISE, 0, 0); + if( yymsp[-3].minor.yy454 ){ + yymsp[-3].minor.yy454->affExpr = OE_Ignore; } } break; - case 276: /* expr ::= RAISE LP raisetype COMMA nm RP */ + case 280: /* expr ::= RAISE LP raisetype COMMA nm RP */ { - yymsp[-5].minor.yy528 = sqlite3ExprAlloc(pParse->db, TK_RAISE, &yymsp[-1].minor.yy0, 1); - if( yymsp[-5].minor.yy528 ) { - yymsp[-5].minor.yy528->affExpr = (char)yymsp[-3].minor.yy394; + yymsp[-5].minor.yy454 = sqlite3ExprAlloc(pParse->db, TK_RAISE, &yymsp[-1].minor.yy0, 1); + if( yymsp[-5].minor.yy454 ) { + yymsp[-5].minor.yy454->affExpr = (char)yymsp[-3].minor.yy144; } } break; - case 277: /* raisetype ::= ROLLBACK */ -{yymsp[0].minor.yy394 = OE_Rollback;} + case 281: /* raisetype ::= ROLLBACK */ +{yymsp[0].minor.yy144 = OE_Rollback;} break; - case 279: /* raisetype ::= FAIL */ -{yymsp[0].minor.yy394 = OE_Fail;} + case 283: /* raisetype ::= FAIL */ +{yymsp[0].minor.yy144 = OE_Fail;} break; - case 280: /* cmd ::= DROP TRIGGER ifexists fullname */ + case 284: /* cmd ::= DROP TRIGGER ifexists fullname */ { - sqlite3DropTrigger(pParse,yymsp[0].minor.yy131,yymsp[-1].minor.yy394); + sqlite3DropTrigger(pParse,yymsp[0].minor.yy203,yymsp[-1].minor.yy144); } break; - case 281: /* cmd ::= ATTACH database_kw_opt expr AS expr key_opt */ + case 285: /* cmd ::= ATTACH database_kw_opt expr AS expr key_opt */ { - sqlite3Attach(pParse, yymsp[-3].minor.yy528, yymsp[-1].minor.yy528, yymsp[0].minor.yy528); + sqlite3Attach(pParse, yymsp[-3].minor.yy454, yymsp[-1].minor.yy454, yymsp[0].minor.yy454); } break; - case 282: /* cmd ::= DETACH database_kw_opt expr */ + case 286: /* cmd ::= DETACH database_kw_opt expr */ { - sqlite3Detach(pParse, yymsp[0].minor.yy528); + sqlite3Detach(pParse, yymsp[0].minor.yy454); } break; - case 285: /* cmd ::= REINDEX */ + case 289: /* cmd ::= REINDEX */ {sqlite3Reindex(pParse, 0, 0);} break; - case 286: /* cmd ::= REINDEX nm dbnm */ + case 290: /* cmd ::= REINDEX nm dbnm */ {sqlite3Reindex(pParse, &yymsp[-1].minor.yy0, &yymsp[0].minor.yy0);} break; - case 287: /* cmd ::= ANALYZE */ + case 291: /* cmd ::= ANALYZE */ {sqlite3Analyze(pParse, 0, 0);} break; - case 288: /* cmd ::= ANALYZE nm dbnm */ + case 292: /* cmd ::= ANALYZE nm dbnm */ {sqlite3Analyze(pParse, &yymsp[-1].minor.yy0, &yymsp[0].minor.yy0);} break; - case 289: /* cmd ::= ALTER TABLE fullname RENAME TO nm */ + case 293: /* cmd ::= ALTER TABLE fullname RENAME TO nm */ { - sqlite3AlterRenameTable(pParse,yymsp[-3].minor.yy131,&yymsp[0].minor.yy0); + sqlite3AlterRenameTable(pParse,yymsp[-3].minor.yy203,&yymsp[0].minor.yy0); } break; - case 290: /* cmd ::= ALTER TABLE add_column_fullname ADD kwcolumn_opt columnname carglist */ + case 294: /* cmd ::= ALTER TABLE add_column_fullname ADD kwcolumn_opt columnname carglist */ { yymsp[-1].minor.yy0.n = (int)(pParse->sLastToken.z-yymsp[-1].minor.yy0.z) + pParse->sLastToken.n; sqlite3AlterFinishAddColumn(pParse, &yymsp[-1].minor.yy0); } break; - case 291: /* cmd ::= ALTER TABLE fullname DROP kwcolumn_opt nm */ + case 295: /* cmd ::= ALTER TABLE fullname DROP kwcolumn_opt nm */ { - sqlite3AlterDropColumn(pParse, yymsp[-3].minor.yy131, &yymsp[0].minor.yy0); + sqlite3AlterDropColumn(pParse, yymsp[-3].minor.yy203, &yymsp[0].minor.yy0); } break; - case 292: /* add_column_fullname ::= fullname */ + case 296: /* add_column_fullname ::= fullname */ { disableLookaside(pParse); - sqlite3AlterBeginAddColumn(pParse, yymsp[0].minor.yy131); + sqlite3AlterBeginAddColumn(pParse, yymsp[0].minor.yy203); } break; - case 293: /* cmd ::= ALTER TABLE fullname RENAME kwcolumn_opt nm TO nm */ + case 297: /* cmd ::= ALTER TABLE fullname RENAME kwcolumn_opt nm TO nm */ { - sqlite3AlterRenameColumn(pParse, yymsp[-5].minor.yy131, &yymsp[-2].minor.yy0, &yymsp[0].minor.yy0); + sqlite3AlterRenameColumn(pParse, yymsp[-5].minor.yy203, &yymsp[-2].minor.yy0, &yymsp[0].minor.yy0); } break; - case 294: /* cmd ::= create_vtab */ + case 298: /* cmd ::= create_vtab */ {sqlite3VtabFinishParse(pParse,0);} break; - case 295: /* cmd ::= create_vtab LP vtabarglist RP */ + case 299: /* cmd ::= create_vtab LP vtabarglist RP */ {sqlite3VtabFinishParse(pParse,&yymsp[0].minor.yy0);} break; - case 296: /* create_vtab ::= createkw VIRTUAL TABLE ifnotexists nm dbnm USING nm */ + case 300: /* create_vtab ::= createkw VIRTUAL TABLE ifnotexists nm dbnm USING nm */ { - sqlite3VtabBeginParse(pParse, &yymsp[-3].minor.yy0, &yymsp[-2].minor.yy0, &yymsp[0].minor.yy0, yymsp[-4].minor.yy394); + sqlite3VtabBeginParse(pParse, &yymsp[-3].minor.yy0, &yymsp[-2].minor.yy0, &yymsp[0].minor.yy0, yymsp[-4].minor.yy144); } break; - case 297: /* vtabarg ::= */ + case 301: /* vtabarg ::= */ {sqlite3VtabArgInit(pParse);} break; - case 298: /* vtabargtoken ::= ANY */ - case 299: /* vtabargtoken ::= lp anylist RP */ yytestcase(yyruleno==299); - case 300: /* lp ::= LP */ yytestcase(yyruleno==300); + case 302: /* vtabargtoken ::= ANY */ + case 303: /* vtabargtoken ::= lp anylist RP */ yytestcase(yyruleno==303); + case 304: /* lp ::= LP */ yytestcase(yyruleno==304); {sqlite3VtabArgExtend(pParse,&yymsp[0].minor.yy0);} break; - case 301: /* with ::= WITH wqlist */ - case 302: /* with ::= WITH RECURSIVE wqlist */ yytestcase(yyruleno==302); -{ sqlite3WithPush(pParse, yymsp[0].minor.yy521, 1); } + case 305: /* with ::= WITH wqlist */ + case 306: /* with ::= WITH RECURSIVE wqlist */ yytestcase(yyruleno==306); +{ sqlite3WithPush(pParse, yymsp[0].minor.yy59, 1); } break; - case 303: /* wqas ::= AS */ -{yymsp[0].minor.yy516 = M10d_Any;} + case 307: /* wqas ::= AS */ +{yymsp[0].minor.yy462 = M10d_Any;} break; - case 304: /* wqas ::= AS MATERIALIZED */ -{yymsp[-1].minor.yy516 = M10d_Yes;} + case 308: /* wqas ::= AS MATERIALIZED */ +{yymsp[-1].minor.yy462 = M10d_Yes;} break; - case 305: /* wqas ::= AS NOT MATERIALIZED */ -{yymsp[-2].minor.yy516 = M10d_No;} + case 309: /* wqas ::= AS NOT MATERIALIZED */ +{yymsp[-2].minor.yy462 = M10d_No;} break; - case 306: /* wqitem ::= nm eidlist_opt wqas LP select RP */ + case 310: /* wqitem ::= withnm eidlist_opt wqas LP select RP */ { - yymsp[-5].minor.yy385 = sqlite3CteNew(pParse, &yymsp[-5].minor.yy0, yymsp[-4].minor.yy322, yymsp[-1].minor.yy47, yymsp[-3].minor.yy516); /*A-overwrites-X*/ + yymsp[-5].minor.yy67 = sqlite3CteNew(pParse, &yymsp[-5].minor.yy0, yymsp[-4].minor.yy14, yymsp[-1].minor.yy555, yymsp[-3].minor.yy462); /*A-overwrites-X*/ } break; - case 307: /* wqlist ::= wqitem */ + case 311: /* withnm ::= nm */ +{pParse->bHasWith = 1;} + break; + case 312: /* wqlist ::= wqitem */ { - yymsp[0].minor.yy521 = sqlite3WithAdd(pParse, 0, yymsp[0].minor.yy385); /*A-overwrites-X*/ + yymsp[0].minor.yy59 = sqlite3WithAdd(pParse, 0, yymsp[0].minor.yy67); /*A-overwrites-X*/ } break; - case 308: /* wqlist ::= wqlist COMMA wqitem */ + case 313: /* wqlist ::= wqlist COMMA wqitem */ { - yymsp[-2].minor.yy521 = sqlite3WithAdd(pParse, yymsp[-2].minor.yy521, yymsp[0].minor.yy385); + yymsp[-2].minor.yy59 = sqlite3WithAdd(pParse, yymsp[-2].minor.yy59, yymsp[0].minor.yy67); } break; - case 309: /* windowdefn_list ::= windowdefn_list COMMA windowdefn */ + case 314: /* windowdefn_list ::= windowdefn_list COMMA windowdefn */ { - assert( yymsp[0].minor.yy41!=0 ); - sqlite3WindowChain(pParse, yymsp[0].minor.yy41, yymsp[-2].minor.yy41); - yymsp[0].minor.yy41->pNextWin = yymsp[-2].minor.yy41; - yylhsminor.yy41 = yymsp[0].minor.yy41; + assert( yymsp[0].minor.yy211!=0 ); + sqlite3WindowChain(pParse, yymsp[0].minor.yy211, yymsp[-2].minor.yy211); + yymsp[0].minor.yy211->pNextWin = yymsp[-2].minor.yy211; + yylhsminor.yy211 = yymsp[0].minor.yy211; } - yymsp[-2].minor.yy41 = yylhsminor.yy41; + yymsp[-2].minor.yy211 = yylhsminor.yy211; break; - case 310: /* windowdefn ::= nm AS LP window RP */ + case 315: /* windowdefn ::= nm AS LP window RP */ { - if( ALWAYS(yymsp[-1].minor.yy41) ){ - yymsp[-1].minor.yy41->zName = sqlite3DbStrNDup(pParse->db, yymsp[-4].minor.yy0.z, yymsp[-4].minor.yy0.n); + if( ALWAYS(yymsp[-1].minor.yy211) ){ + yymsp[-1].minor.yy211->zName = sqlite3DbStrNDup(pParse->db, yymsp[-4].minor.yy0.z, yymsp[-4].minor.yy0.n); } - yylhsminor.yy41 = yymsp[-1].minor.yy41; + yylhsminor.yy211 = yymsp[-1].minor.yy211; } - yymsp[-4].minor.yy41 = yylhsminor.yy41; + yymsp[-4].minor.yy211 = yylhsminor.yy211; break; - case 311: /* window ::= PARTITION BY nexprlist orderby_opt frame_opt */ + case 316: /* window ::= PARTITION BY nexprlist orderby_opt frame_opt */ { - yymsp[-4].minor.yy41 = sqlite3WindowAssemble(pParse, yymsp[0].minor.yy41, yymsp[-2].minor.yy322, yymsp[-1].minor.yy322, 0); + yymsp[-4].minor.yy211 = sqlite3WindowAssemble(pParse, yymsp[0].minor.yy211, yymsp[-2].minor.yy14, yymsp[-1].minor.yy14, 0); } break; - case 312: /* window ::= nm PARTITION BY nexprlist orderby_opt frame_opt */ + case 317: /* window ::= nm PARTITION BY nexprlist orderby_opt frame_opt */ { - yylhsminor.yy41 = sqlite3WindowAssemble(pParse, yymsp[0].minor.yy41, yymsp[-2].minor.yy322, yymsp[-1].minor.yy322, &yymsp[-5].minor.yy0); + yylhsminor.yy211 = sqlite3WindowAssemble(pParse, yymsp[0].minor.yy211, yymsp[-2].minor.yy14, yymsp[-1].minor.yy14, &yymsp[-5].minor.yy0); } - yymsp[-5].minor.yy41 = yylhsminor.yy41; + yymsp[-5].minor.yy211 = yylhsminor.yy211; break; - case 313: /* window ::= ORDER BY sortlist frame_opt */ + case 318: /* window ::= ORDER BY sortlist frame_opt */ { - yymsp[-3].minor.yy41 = sqlite3WindowAssemble(pParse, yymsp[0].minor.yy41, 0, yymsp[-1].minor.yy322, 0); + yymsp[-3].minor.yy211 = sqlite3WindowAssemble(pParse, yymsp[0].minor.yy211, 0, yymsp[-1].minor.yy14, 0); } break; - case 314: /* window ::= nm ORDER BY sortlist frame_opt */ + case 319: /* window ::= nm ORDER BY sortlist frame_opt */ { - yylhsminor.yy41 = sqlite3WindowAssemble(pParse, yymsp[0].minor.yy41, 0, yymsp[-1].minor.yy322, &yymsp[-4].minor.yy0); + yylhsminor.yy211 = sqlite3WindowAssemble(pParse, yymsp[0].minor.yy211, 0, yymsp[-1].minor.yy14, &yymsp[-4].minor.yy0); } - yymsp[-4].minor.yy41 = yylhsminor.yy41; + yymsp[-4].minor.yy211 = yylhsminor.yy211; break; - case 315: /* window ::= nm frame_opt */ + case 320: /* window ::= nm frame_opt */ { - yylhsminor.yy41 = sqlite3WindowAssemble(pParse, yymsp[0].minor.yy41, 0, 0, &yymsp[-1].minor.yy0); + yylhsminor.yy211 = sqlite3WindowAssemble(pParse, yymsp[0].minor.yy211, 0, 0, &yymsp[-1].minor.yy0); } - yymsp[-1].minor.yy41 = yylhsminor.yy41; + yymsp[-1].minor.yy211 = yylhsminor.yy211; break; - case 316: /* frame_opt ::= */ + case 321: /* frame_opt ::= */ { - yymsp[1].minor.yy41 = sqlite3WindowAlloc(pParse, 0, TK_UNBOUNDED, 0, TK_CURRENT, 0, 0); + yymsp[1].minor.yy211 = sqlite3WindowAlloc(pParse, 0, TK_UNBOUNDED, 0, TK_CURRENT, 0, 0); } break; - case 317: /* frame_opt ::= range_or_rows frame_bound_s frame_exclude_opt */ + case 322: /* frame_opt ::= range_or_rows frame_bound_s frame_exclude_opt */ { - yylhsminor.yy41 = sqlite3WindowAlloc(pParse, yymsp[-2].minor.yy394, yymsp[-1].minor.yy595.eType, yymsp[-1].minor.yy595.pExpr, TK_CURRENT, 0, yymsp[0].minor.yy516); + yylhsminor.yy211 = sqlite3WindowAlloc(pParse, yymsp[-2].minor.yy144, yymsp[-1].minor.yy509.eType, yymsp[-1].minor.yy509.pExpr, TK_CURRENT, 0, yymsp[0].minor.yy462); } - yymsp[-2].minor.yy41 = yylhsminor.yy41; + yymsp[-2].minor.yy211 = yylhsminor.yy211; break; - case 318: /* frame_opt ::= range_or_rows BETWEEN frame_bound_s AND frame_bound_e frame_exclude_opt */ + case 323: /* frame_opt ::= range_or_rows BETWEEN frame_bound_s AND frame_bound_e frame_exclude_opt */ { - yylhsminor.yy41 = sqlite3WindowAlloc(pParse, yymsp[-5].minor.yy394, yymsp[-3].minor.yy595.eType, yymsp[-3].minor.yy595.pExpr, yymsp[-1].minor.yy595.eType, yymsp[-1].minor.yy595.pExpr, yymsp[0].minor.yy516); + yylhsminor.yy211 = sqlite3WindowAlloc(pParse, yymsp[-5].minor.yy144, yymsp[-3].minor.yy509.eType, yymsp[-3].minor.yy509.pExpr, yymsp[-1].minor.yy509.eType, yymsp[-1].minor.yy509.pExpr, yymsp[0].minor.yy462); } - yymsp[-5].minor.yy41 = yylhsminor.yy41; + yymsp[-5].minor.yy211 = yylhsminor.yy211; break; - case 320: /* frame_bound_s ::= frame_bound */ - case 322: /* frame_bound_e ::= frame_bound */ yytestcase(yyruleno==322); -{yylhsminor.yy595 = yymsp[0].minor.yy595;} - yymsp[0].minor.yy595 = yylhsminor.yy595; + case 325: /* frame_bound_s ::= frame_bound */ + case 327: /* frame_bound_e ::= frame_bound */ yytestcase(yyruleno==327); +{yylhsminor.yy509 = yymsp[0].minor.yy509;} + yymsp[0].minor.yy509 = yylhsminor.yy509; break; - case 321: /* frame_bound_s ::= UNBOUNDED PRECEDING */ - case 323: /* frame_bound_e ::= UNBOUNDED FOLLOWING */ yytestcase(yyruleno==323); - case 325: /* frame_bound ::= CURRENT ROW */ yytestcase(yyruleno==325); -{yylhsminor.yy595.eType = yymsp[-1].major; yylhsminor.yy595.pExpr = 0;} - yymsp[-1].minor.yy595 = yylhsminor.yy595; + case 326: /* frame_bound_s ::= UNBOUNDED PRECEDING */ + case 328: /* frame_bound_e ::= UNBOUNDED FOLLOWING */ yytestcase(yyruleno==328); + case 330: /* frame_bound ::= CURRENT ROW */ yytestcase(yyruleno==330); +{yylhsminor.yy509.eType = yymsp[-1].major; yylhsminor.yy509.pExpr = 0;} + yymsp[-1].minor.yy509 = yylhsminor.yy509; break; - case 324: /* frame_bound ::= expr PRECEDING|FOLLOWING */ -{yylhsminor.yy595.eType = yymsp[0].major; yylhsminor.yy595.pExpr = yymsp[-1].minor.yy528;} - yymsp[-1].minor.yy595 = yylhsminor.yy595; + case 329: /* frame_bound ::= expr PRECEDING|FOLLOWING */ +{yylhsminor.yy509.eType = yymsp[0].major; yylhsminor.yy509.pExpr = yymsp[-1].minor.yy454;} + yymsp[-1].minor.yy509 = yylhsminor.yy509; break; - case 326: /* frame_exclude_opt ::= */ -{yymsp[1].minor.yy516 = 0;} + case 331: /* frame_exclude_opt ::= */ +{yymsp[1].minor.yy462 = 0;} break; - case 327: /* frame_exclude_opt ::= EXCLUDE frame_exclude */ -{yymsp[-1].minor.yy516 = yymsp[0].minor.yy516;} + case 332: /* frame_exclude_opt ::= EXCLUDE frame_exclude */ +{yymsp[-1].minor.yy462 = yymsp[0].minor.yy462;} break; - case 328: /* frame_exclude ::= NO OTHERS */ - case 329: /* frame_exclude ::= CURRENT ROW */ yytestcase(yyruleno==329); -{yymsp[-1].minor.yy516 = yymsp[-1].major; /*A-overwrites-X*/} + case 333: /* frame_exclude ::= NO OTHERS */ + case 334: /* frame_exclude ::= CURRENT ROW */ yytestcase(yyruleno==334); +{yymsp[-1].minor.yy462 = yymsp[-1].major; /*A-overwrites-X*/} break; - case 330: /* frame_exclude ::= GROUP|TIES */ -{yymsp[0].minor.yy516 = yymsp[0].major; /*A-overwrites-X*/} + case 335: /* frame_exclude ::= GROUP|TIES */ +{yymsp[0].minor.yy462 = yymsp[0].major; /*A-overwrites-X*/} break; - case 331: /* window_clause ::= WINDOW windowdefn_list */ -{ yymsp[-1].minor.yy41 = yymsp[0].minor.yy41; } + case 336: /* window_clause ::= WINDOW windowdefn_list */ +{ yymsp[-1].minor.yy211 = yymsp[0].minor.yy211; } break; - case 332: /* filter_over ::= filter_clause over_clause */ + case 337: /* filter_over ::= filter_clause over_clause */ { - if( yymsp[0].minor.yy41 ){ - yymsp[0].minor.yy41->pFilter = yymsp[-1].minor.yy528; + if( yymsp[0].minor.yy211 ){ + yymsp[0].minor.yy211->pFilter = yymsp[-1].minor.yy454; }else{ - sqlite3ExprDelete(pParse->db, yymsp[-1].minor.yy528); + sqlite3ExprDelete(pParse->db, yymsp[-1].minor.yy454); } - yylhsminor.yy41 = yymsp[0].minor.yy41; + yylhsminor.yy211 = yymsp[0].minor.yy211; } - yymsp[-1].minor.yy41 = yylhsminor.yy41; + yymsp[-1].minor.yy211 = yylhsminor.yy211; break; - case 333: /* filter_over ::= over_clause */ + case 338: /* filter_over ::= over_clause */ { - yylhsminor.yy41 = yymsp[0].minor.yy41; + yylhsminor.yy211 = yymsp[0].minor.yy211; } - yymsp[0].minor.yy41 = yylhsminor.yy41; + yymsp[0].minor.yy211 = yylhsminor.yy211; break; - case 334: /* filter_over ::= filter_clause */ + case 339: /* filter_over ::= filter_clause */ { - yylhsminor.yy41 = (Window*)sqlite3DbMallocZero(pParse->db, sizeof(Window)); - if( yylhsminor.yy41 ){ - yylhsminor.yy41->eFrmType = TK_FILTER; - yylhsminor.yy41->pFilter = yymsp[0].minor.yy528; + yylhsminor.yy211 = (Window*)sqlite3DbMallocZero(pParse->db, sizeof(Window)); + if( yylhsminor.yy211 ){ + yylhsminor.yy211->eFrmType = TK_FILTER; + yylhsminor.yy211->pFilter = yymsp[0].minor.yy454; }else{ - sqlite3ExprDelete(pParse->db, yymsp[0].minor.yy528); + sqlite3ExprDelete(pParse->db, yymsp[0].minor.yy454); } } - yymsp[0].minor.yy41 = yylhsminor.yy41; + yymsp[0].minor.yy211 = yylhsminor.yy211; break; - case 335: /* over_clause ::= OVER LP window RP */ + case 340: /* over_clause ::= OVER LP window RP */ { - yymsp[-3].minor.yy41 = yymsp[-1].minor.yy41; - assert( yymsp[-3].minor.yy41!=0 ); + yymsp[-3].minor.yy211 = yymsp[-1].minor.yy211; + assert( yymsp[-3].minor.yy211!=0 ); } break; - case 336: /* over_clause ::= OVER nm */ + case 341: /* over_clause ::= OVER nm */ { - yymsp[-1].minor.yy41 = (Window*)sqlite3DbMallocZero(pParse->db, sizeof(Window)); - if( yymsp[-1].minor.yy41 ){ - yymsp[-1].minor.yy41->zName = sqlite3DbStrNDup(pParse->db, yymsp[0].minor.yy0.z, yymsp[0].minor.yy0.n); + yymsp[-1].minor.yy211 = (Window*)sqlite3DbMallocZero(pParse->db, sizeof(Window)); + if( yymsp[-1].minor.yy211 ){ + yymsp[-1].minor.yy211->zName = sqlite3DbStrNDup(pParse->db, yymsp[0].minor.yy0.z, yymsp[0].minor.yy0.n); } } break; - case 337: /* filter_clause ::= FILTER LP WHERE expr RP */ -{ yymsp[-4].minor.yy528 = yymsp[-1].minor.yy528; } + case 342: /* filter_clause ::= FILTER LP WHERE expr RP */ +{ yymsp[-4].minor.yy454 = yymsp[-1].minor.yy454; } + break; + case 343: /* term ::= QNUMBER */ +{ + yylhsminor.yy454=tokenExpr(pParse,yymsp[0].major,yymsp[0].minor.yy0); + sqlite3DequoteNumber(pParse, yylhsminor.yy454); +} + yymsp[0].minor.yy454 = yylhsminor.yy454; break; default: - /* (338) input ::= cmdlist */ yytestcase(yyruleno==338); - /* (339) cmdlist ::= cmdlist ecmd */ yytestcase(yyruleno==339); - /* (340) cmdlist ::= ecmd (OPTIMIZED OUT) */ assert(yyruleno!=340); - /* (341) ecmd ::= SEMI */ yytestcase(yyruleno==341); - /* (342) ecmd ::= cmdx SEMI */ yytestcase(yyruleno==342); - /* (343) ecmd ::= explain cmdx SEMI (NEVER REDUCES) */ assert(yyruleno!=343); - /* (344) trans_opt ::= */ yytestcase(yyruleno==344); - /* (345) trans_opt ::= TRANSACTION */ yytestcase(yyruleno==345); - /* (346) trans_opt ::= TRANSACTION nm */ yytestcase(yyruleno==346); - /* (347) savepoint_opt ::= SAVEPOINT */ yytestcase(yyruleno==347); - /* (348) savepoint_opt ::= */ yytestcase(yyruleno==348); - /* (349) cmd ::= create_table create_table_args */ yytestcase(yyruleno==349); - /* (350) table_option_set ::= table_option (OPTIMIZED OUT) */ assert(yyruleno!=350); - /* (351) columnlist ::= columnlist COMMA columnname carglist */ yytestcase(yyruleno==351); - /* (352) columnlist ::= columnname carglist */ yytestcase(yyruleno==352); - /* (353) nm ::= ID|INDEXED|JOIN_KW */ yytestcase(yyruleno==353); - /* (354) nm ::= STRING */ yytestcase(yyruleno==354); - /* (355) typetoken ::= typename */ yytestcase(yyruleno==355); - /* (356) typename ::= ID|STRING */ yytestcase(yyruleno==356); - /* (357) signed ::= plus_num (OPTIMIZED OUT) */ assert(yyruleno!=357); - /* (358) signed ::= minus_num (OPTIMIZED OUT) */ assert(yyruleno!=358); - /* (359) carglist ::= carglist ccons */ yytestcase(yyruleno==359); - /* (360) carglist ::= */ yytestcase(yyruleno==360); - /* (361) ccons ::= NULL onconf */ yytestcase(yyruleno==361); - /* (362) ccons ::= GENERATED ALWAYS AS generated */ yytestcase(yyruleno==362); - /* (363) ccons ::= AS generated */ yytestcase(yyruleno==363); - /* (364) conslist_opt ::= COMMA conslist */ yytestcase(yyruleno==364); - /* (365) conslist ::= conslist tconscomma tcons */ yytestcase(yyruleno==365); - /* (366) conslist ::= tcons (OPTIMIZED OUT) */ assert(yyruleno!=366); - /* (367) tconscomma ::= */ yytestcase(yyruleno==367); - /* (368) defer_subclause_opt ::= defer_subclause (OPTIMIZED OUT) */ assert(yyruleno!=368); - /* (369) resolvetype ::= raisetype (OPTIMIZED OUT) */ assert(yyruleno!=369); - /* (370) selectnowith ::= oneselect (OPTIMIZED OUT) */ assert(yyruleno!=370); - /* (371) oneselect ::= values */ yytestcase(yyruleno==371); - /* (372) sclp ::= selcollist COMMA */ yytestcase(yyruleno==372); - /* (373) as ::= ID|STRING */ yytestcase(yyruleno==373); - /* (374) indexed_opt ::= indexed_by (OPTIMIZED OUT) */ assert(yyruleno!=374); - /* (375) returning ::= */ yytestcase(yyruleno==375); - /* (376) expr ::= term (OPTIMIZED OUT) */ assert(yyruleno!=376); - /* (377) likeop ::= LIKE_KW|MATCH */ yytestcase(yyruleno==377); - /* (378) case_operand ::= expr */ yytestcase(yyruleno==378); - /* (379) exprlist ::= nexprlist */ yytestcase(yyruleno==379); - /* (380) nmnum ::= plus_num (OPTIMIZED OUT) */ assert(yyruleno!=380); - /* (381) nmnum ::= nm (OPTIMIZED OUT) */ assert(yyruleno!=381); - /* (382) nmnum ::= ON */ yytestcase(yyruleno==382); - /* (383) nmnum ::= DELETE */ yytestcase(yyruleno==383); - /* (384) nmnum ::= DEFAULT */ yytestcase(yyruleno==384); - /* (385) plus_num ::= INTEGER|FLOAT */ yytestcase(yyruleno==385); - /* (386) foreach_clause ::= */ yytestcase(yyruleno==386); - /* (387) foreach_clause ::= FOR EACH ROW */ yytestcase(yyruleno==387); - /* (388) trnm ::= nm */ yytestcase(yyruleno==388); - /* (389) tridxby ::= */ yytestcase(yyruleno==389); - /* (390) database_kw_opt ::= DATABASE */ yytestcase(yyruleno==390); - /* (391) database_kw_opt ::= */ yytestcase(yyruleno==391); - /* (392) kwcolumn_opt ::= */ yytestcase(yyruleno==392); - /* (393) kwcolumn_opt ::= COLUMNKW */ yytestcase(yyruleno==393); - /* (394) vtabarglist ::= vtabarg */ yytestcase(yyruleno==394); - /* (395) vtabarglist ::= vtabarglist COMMA vtabarg */ yytestcase(yyruleno==395); - /* (396) vtabarg ::= vtabarg vtabargtoken */ yytestcase(yyruleno==396); - /* (397) anylist ::= */ yytestcase(yyruleno==397); - /* (398) anylist ::= anylist LP anylist RP */ yytestcase(yyruleno==398); - /* (399) anylist ::= anylist ANY */ yytestcase(yyruleno==399); - /* (400) with ::= */ yytestcase(yyruleno==400); - /* (401) windowdefn_list ::= windowdefn (OPTIMIZED OUT) */ assert(yyruleno!=401); - /* (402) window ::= frame_opt (OPTIMIZED OUT) */ assert(yyruleno!=402); + /* (344) input ::= cmdlist */ yytestcase(yyruleno==344); + /* (345) cmdlist ::= cmdlist ecmd */ yytestcase(yyruleno==345); + /* (346) cmdlist ::= ecmd (OPTIMIZED OUT) */ assert(yyruleno!=346); + /* (347) ecmd ::= SEMI */ yytestcase(yyruleno==347); + /* (348) ecmd ::= cmdx SEMI */ yytestcase(yyruleno==348); + /* (349) ecmd ::= explain cmdx SEMI (NEVER REDUCES) */ assert(yyruleno!=349); + /* (350) trans_opt ::= */ yytestcase(yyruleno==350); + /* (351) trans_opt ::= TRANSACTION */ yytestcase(yyruleno==351); + /* (352) trans_opt ::= TRANSACTION nm */ yytestcase(yyruleno==352); + /* (353) savepoint_opt ::= SAVEPOINT */ yytestcase(yyruleno==353); + /* (354) savepoint_opt ::= */ yytestcase(yyruleno==354); + /* (355) cmd ::= create_table create_table_args */ yytestcase(yyruleno==355); + /* (356) table_option_set ::= table_option (OPTIMIZED OUT) */ assert(yyruleno!=356); + /* (357) columnlist ::= columnlist COMMA columnname carglist */ yytestcase(yyruleno==357); + /* (358) columnlist ::= columnname carglist */ yytestcase(yyruleno==358); + /* (359) nm ::= ID|INDEXED|JOIN_KW */ yytestcase(yyruleno==359); + /* (360) nm ::= STRING */ yytestcase(yyruleno==360); + /* (361) typetoken ::= typename */ yytestcase(yyruleno==361); + /* (362) typename ::= ID|STRING */ yytestcase(yyruleno==362); + /* (363) signed ::= plus_num (OPTIMIZED OUT) */ assert(yyruleno!=363); + /* (364) signed ::= minus_num (OPTIMIZED OUT) */ assert(yyruleno!=364); + /* (365) carglist ::= carglist ccons */ yytestcase(yyruleno==365); + /* (366) carglist ::= */ yytestcase(yyruleno==366); + /* (367) ccons ::= NULL onconf */ yytestcase(yyruleno==367); + /* (368) ccons ::= GENERATED ALWAYS AS generated */ yytestcase(yyruleno==368); + /* (369) ccons ::= AS generated */ yytestcase(yyruleno==369); + /* (370) conslist_opt ::= COMMA conslist */ yytestcase(yyruleno==370); + /* (371) conslist ::= conslist tconscomma tcons */ yytestcase(yyruleno==371); + /* (372) conslist ::= tcons (OPTIMIZED OUT) */ assert(yyruleno!=372); + /* (373) tconscomma ::= */ yytestcase(yyruleno==373); + /* (374) defer_subclause_opt ::= defer_subclause (OPTIMIZED OUT) */ assert(yyruleno!=374); + /* (375) resolvetype ::= raisetype (OPTIMIZED OUT) */ assert(yyruleno!=375); + /* (376) selectnowith ::= oneselect (OPTIMIZED OUT) */ assert(yyruleno!=376); + /* (377) oneselect ::= values */ yytestcase(yyruleno==377); + /* (378) sclp ::= selcollist COMMA */ yytestcase(yyruleno==378); + /* (379) as ::= ID|STRING */ yytestcase(yyruleno==379); + /* (380) indexed_opt ::= indexed_by (OPTIMIZED OUT) */ assert(yyruleno!=380); + /* (381) returning ::= */ yytestcase(yyruleno==381); + /* (382) expr ::= term (OPTIMIZED OUT) */ assert(yyruleno!=382); + /* (383) likeop ::= LIKE_KW|MATCH */ yytestcase(yyruleno==383); + /* (384) case_operand ::= expr */ yytestcase(yyruleno==384); + /* (385) exprlist ::= nexprlist */ yytestcase(yyruleno==385); + /* (386) nmnum ::= plus_num (OPTIMIZED OUT) */ assert(yyruleno!=386); + /* (387) nmnum ::= nm (OPTIMIZED OUT) */ assert(yyruleno!=387); + /* (388) nmnum ::= ON */ yytestcase(yyruleno==388); + /* (389) nmnum ::= DELETE */ yytestcase(yyruleno==389); + /* (390) nmnum ::= DEFAULT */ yytestcase(yyruleno==390); + /* (391) plus_num ::= INTEGER|FLOAT */ yytestcase(yyruleno==391); + /* (392) foreach_clause ::= */ yytestcase(yyruleno==392); + /* (393) foreach_clause ::= FOR EACH ROW */ yytestcase(yyruleno==393); + /* (394) trnm ::= nm */ yytestcase(yyruleno==394); + /* (395) tridxby ::= */ yytestcase(yyruleno==395); + /* (396) database_kw_opt ::= DATABASE */ yytestcase(yyruleno==396); + /* (397) database_kw_opt ::= */ yytestcase(yyruleno==397); + /* (398) kwcolumn_opt ::= */ yytestcase(yyruleno==398); + /* (399) kwcolumn_opt ::= COLUMNKW */ yytestcase(yyruleno==399); + /* (400) vtabarglist ::= vtabarg */ yytestcase(yyruleno==400); + /* (401) vtabarglist ::= vtabarglist COMMA vtabarg */ yytestcase(yyruleno==401); + /* (402) vtabarg ::= vtabarg vtabargtoken */ yytestcase(yyruleno==402); + /* (403) anylist ::= */ yytestcase(yyruleno==403); + /* (404) anylist ::= anylist LP anylist RP */ yytestcase(yyruleno==404); + /* (405) anylist ::= anylist ANY */ yytestcase(yyruleno==405); + /* (406) with ::= */ yytestcase(yyruleno==406); + /* (407) windowdefn_list ::= windowdefn (OPTIMIZED OUT) */ assert(yyruleno!=407); + /* (408) window ::= frame_opt (OPTIMIZED OUT) */ assert(yyruleno!=408); break; /********** End reduce actions ************************************************/ }; @@ -174503,19 +177848,12 @@ SQLITE_PRIVATE void sqlite3Parser( (int)(yypParser->yytos - yypParser->yystack)); } #endif -#if YYSTACKDEPTH>0 if( yypParser->yytos>=yypParser->yystackEnd ){ - yyStackOverflow(yypParser); - break; - } -#else - if( yypParser->yytos>=&yypParser->yystack[yypParser->yystksz-1] ){ if( yyGrowStack(yypParser) ){ yyStackOverflow(yypParser); break; } } -#endif } yyact = yy_reduce(yypParser,yyruleno,yymajor,yyminor sqlite3ParserCTX_PARAM); }else if( yyact <= YY_MAX_SHIFTREDUCE ){ @@ -175586,27 +178924,58 @@ SQLITE_PRIVATE int sqlite3GetToken(const unsigned char *z, int *tokenType){ *tokenType = TK_INTEGER; #ifndef SQLITE_OMIT_HEX_INTEGER if( z[0]=='0' && (z[1]=='x' || z[1]=='X') && sqlite3Isxdigit(z[2]) ){ - for(i=3; sqlite3Isxdigit(z[i]); i++){} - return i; - } + for(i=3; 1; i++){ + if( sqlite3Isxdigit(z[i])==0 ){ + if( z[i]==SQLITE_DIGIT_SEPARATOR ){ + *tokenType = TK_QNUMBER; + }else{ + break; + } + } + } + }else #endif - for(i=0; sqlite3Isdigit(z[i]); i++){} + { + for(i=0; 1; i++){ + if( sqlite3Isdigit(z[i])==0 ){ + if( z[i]==SQLITE_DIGIT_SEPARATOR ){ + *tokenType = TK_QNUMBER; + }else{ + break; + } + } + } #ifndef SQLITE_OMIT_FLOATING_POINT - if( z[i]=='.' ){ - i++; - while( sqlite3Isdigit(z[i]) ){ i++; } - *tokenType = TK_FLOAT; - } - if( (z[i]=='e' || z[i]=='E') && - ( sqlite3Isdigit(z[i+1]) - || ((z[i+1]=='+' || z[i+1]=='-') && sqlite3Isdigit(z[i+2])) - ) - ){ - i += 2; - while( sqlite3Isdigit(z[i]) ){ i++; } - *tokenType = TK_FLOAT; - } + if( z[i]=='.' ){ + if( *tokenType==TK_INTEGER ) *tokenType = TK_FLOAT; + for(i++; 1; i++){ + if( sqlite3Isdigit(z[i])==0 ){ + if( z[i]==SQLITE_DIGIT_SEPARATOR ){ + *tokenType = TK_QNUMBER; + }else{ + break; + } + } + } + } + if( (z[i]=='e' || z[i]=='E') && + ( sqlite3Isdigit(z[i+1]) + || ((z[i+1]=='+' || z[i+1]=='-') && sqlite3Isdigit(z[i+2])) + ) + ){ + if( *tokenType==TK_INTEGER ) *tokenType = TK_FLOAT; + for(i+=2; 1; i++){ + if( sqlite3Isdigit(z[i])==0 ){ + if( z[i]==SQLITE_DIGIT_SEPARATOR ){ + *tokenType = TK_QNUMBER; + }else{ + break; + } + } + } + } #endif + } while( IdChar(z[i]) ){ *tokenType = TK_ILLEGAL; i++; @@ -175771,10 +179140,13 @@ SQLITE_PRIVATE int sqlite3RunParser(Parse *pParse, const char *zSql){ if( tokenType>=TK_WINDOW ){ assert( tokenType==TK_SPACE || tokenType==TK_OVER || tokenType==TK_FILTER || tokenType==TK_ILLEGAL || tokenType==TK_WINDOW + || tokenType==TK_QNUMBER ); #else if( tokenType>=TK_SPACE ){ - assert( tokenType==TK_SPACE || tokenType==TK_ILLEGAL ); + assert( tokenType==TK_SPACE || tokenType==TK_ILLEGAL + || tokenType==TK_QNUMBER + ); #endif /* SQLITE_OMIT_WINDOWFUNC */ if( AtomicLoad(&db->u1.isInterrupted) ){ pParse->rc = SQLITE_INTERRUPT; @@ -175807,7 +179179,7 @@ SQLITE_PRIVATE int sqlite3RunParser(Parse *pParse, const char *zSql){ assert( n==6 ); tokenType = analyzeFilterKeyword((const u8*)&zSql[6], lastTokenParsed); #endif /* SQLITE_OMIT_WINDOWFUNC */ - }else{ + }else if( tokenType!=TK_QNUMBER ){ Token x; x.z = zSql; x.n = n; @@ -176440,7 +179812,9 @@ SQLITE_PRIVATE int sqlite3Fts5Init(sqlite3*); #ifdef SQLITE_ENABLE_STMTVTAB SQLITE_PRIVATE int sqlite3StmtVtabInit(sqlite3*); #endif - +#ifdef SQLITE_EXTRA_AUTOEXT +int SQLITE_EXTRA_AUTOEXT(sqlite3*); +#endif /* ** An array of pointers to extension initializer functions for ** built-in extensions. @@ -176474,6 +179848,9 @@ static int (*const sqlite3BuiltinExtensions[])(sqlite3*) = { #ifdef SQLITE_ENABLE_BYTECODE_VTAB sqlite3VdbeBytecodeVtabInit, #endif +#ifdef SQLITE_EXTRA_AUTOEXT + SQLITE_EXTRA_AUTOEXT, +#endif }; #ifndef SQLITE_AMALGAMATION @@ -176547,6 +179924,32 @@ SQLITE_API char *sqlite3_temp_directory = 0; */ SQLITE_API char *sqlite3_data_directory = 0; +/* +** Determine whether or not high-precision (long double) floating point +** math works correctly on CPU currently running. +*/ +static SQLITE_NOINLINE int hasHighPrecisionDouble(int rc){ + if( sizeof(LONGDOUBLE_TYPE)<=8 ){ + /* If the size of "long double" is not more than 8, then + ** high-precision math is not possible. */ + return 0; + }else{ + /* Just because sizeof(long double)>8 does not mean that the underlying + ** hardware actually supports high-precision floating point. For example, + ** clearing the 0x100 bit in the floating-point control word on Intel + ** processors will make long double work like double, even though long + ** double takes up more space. The only way to determine if long double + ** actually works is to run an experiment. */ + LONGDOUBLE_TYPE a, b, c; + rc++; + a = 1.0+rc*0.1; + b = 1.0e+18+rc*25.0; + c = a+b; + return b!=c; + } +} + + /* ** Initialize SQLite. ** @@ -176742,6 +180145,12 @@ SQLITE_API int sqlite3_initialize(void){ } #endif + /* Experimentally determine if high-precision floating point is + ** available. */ +#ifndef SQLITE_OMIT_WSD + sqlite3Config.bUseLongDouble = hasHighPrecisionDouble(rc); +#endif + return rc; } @@ -177121,6 +180530,18 @@ SQLITE_API int sqlite3_config(int op, ...){ } #endif /* SQLITE_OMIT_DESERIALIZE */ + case SQLITE_CONFIG_ROWID_IN_VIEW: { + int *pVal = va_arg(ap,int*); +#ifdef SQLITE_ALLOW_ROWID_IN_VIEW + if( 0==*pVal ) sqlite3GlobalConfig.mNoVisibleRowid = TF_NoVisibleRowid; + if( 1==*pVal ) sqlite3GlobalConfig.mNoVisibleRowid = 0; + *pVal = (sqlite3GlobalConfig.mNoVisibleRowid==0); +#else + *pVal = 0; +#endif + break; + } + default: { rc = SQLITE_ERROR; break; @@ -177312,6 +180733,10 @@ SQLITE_API int sqlite3_db_cacheflush(sqlite3 *db){ SQLITE_API int sqlite3_db_config(sqlite3 *db, int op, ...){ va_list ap; int rc; + +#ifdef SQLITE_ENABLE_API_ARMOR + if( !sqlite3SafetyCheckOk(db) ) return SQLITE_MISUSE_BKPT; +#endif sqlite3_mutex_enter(db->mutex); va_start(ap, op); switch( op ){ @@ -177641,6 +181066,14 @@ static int sqlite3Close(sqlite3 *db, int forceZombie){ } #endif + while( db->pDbData ){ + DbClientData *p = db->pDbData; + db->pDbData = p->pNext; + assert( p->pData!=0 ); + if( p->xDestructor ) p->xDestructor(p->pData); + sqlite3_free(p); + } + /* Convert the connection into a zombie and then close it. */ db->eOpenState = SQLITE_STATE_ZOMBIE; @@ -178258,7 +181691,7 @@ SQLITE_PRIVATE int sqlite3CreateFunc( assert( SQLITE_FUNC_CONSTANT==SQLITE_DETERMINISTIC ); assert( SQLITE_FUNC_DIRECT==SQLITE_DIRECTONLY ); extraFlags = enc & (SQLITE_DETERMINISTIC|SQLITE_DIRECTONLY| - SQLITE_SUBTYPE|SQLITE_INNOCUOUS); + SQLITE_SUBTYPE|SQLITE_INNOCUOUS|SQLITE_RESULT_SUBTYPE); enc &= (SQLITE_FUNC_ENCMASK|SQLITE_ANY); /* The SQLITE_INNOCUOUS flag is the same bit as SQLITE_FUNC_UNSAFE. But @@ -178715,6 +182148,12 @@ SQLITE_API void *sqlite3_preupdate_hook( void *pArg /* First callback argument */ ){ void *pRet; + +#ifdef SQLITE_ENABLE_API_ARMOR + if( db==0 ){ + return 0; + } +#endif sqlite3_mutex_enter(db->mutex); pRet = db->pPreUpdateArg; db->xPreUpdateCallback = xCallback; @@ -178861,7 +182300,7 @@ SQLITE_API int sqlite3_wal_checkpoint_v2( if( eModeSQLITE_CHECKPOINT_TRUNCATE ){ /* EVIDENCE-OF: R-03996-12088 The M parameter must be a valid checkpoint ** mode: */ - return SQLITE_MISUSE; + return SQLITE_MISUSE_BKPT; } sqlite3_mutex_enter(db->mutex); @@ -180098,6 +183537,69 @@ SQLITE_API int sqlite3_collation_needed16( } #endif /* SQLITE_OMIT_UTF16 */ +/* +** Find existing client data. +*/ +SQLITE_API void *sqlite3_get_clientdata(sqlite3 *db, const char *zName){ + DbClientData *p; + sqlite3_mutex_enter(db->mutex); + for(p=db->pDbData; p; p=p->pNext){ + if( strcmp(p->zName, zName)==0 ){ + void *pResult = p->pData; + sqlite3_mutex_leave(db->mutex); + return pResult; + } + } + sqlite3_mutex_leave(db->mutex); + return 0; +} + +/* +** Add new client data to a database connection. +*/ +SQLITE_API int sqlite3_set_clientdata( + sqlite3 *db, /* Attach client data to this connection */ + const char *zName, /* Name of the client data */ + void *pData, /* The client data itself */ + void (*xDestructor)(void*) /* Destructor */ +){ + DbClientData *p, **pp; + sqlite3_mutex_enter(db->mutex); + pp = &db->pDbData; + for(p=db->pDbData; p && strcmp(p->zName,zName); p=p->pNext){ + pp = &p->pNext; + } + if( p ){ + assert( p->pData!=0 ); + if( p->xDestructor ) p->xDestructor(p->pData); + if( pData==0 ){ + *pp = p->pNext; + sqlite3_free(p); + sqlite3_mutex_leave(db->mutex); + return SQLITE_OK; + } + }else if( pData==0 ){ + sqlite3_mutex_leave(db->mutex); + return SQLITE_OK; + }else{ + size_t n = strlen(zName); + p = sqlite3_malloc64( sizeof(DbClientData)+n+1 ); + if( p==0 ){ + if( xDestructor ) xDestructor(pData); + sqlite3_mutex_leave(db->mutex); + return SQLITE_NOMEM; + } + memcpy(p->zName, zName, n+1); + p->pNext = db->pDbData; + db->pDbData = p; + } + p->pData = pData; + p->xDestructor = xDestructor; + sqlite3_mutex_leave(db->mutex); + return SQLITE_OK; +} + + #ifndef SQLITE_OMIT_DEPRECATED /* ** This function is now an anachronism. It used to be used to recover from a @@ -180447,6 +183949,28 @@ SQLITE_API int sqlite3_test_control(int op, ...){ } #endif + /* sqlite3_test_control(SQLITE_TESTCTRL_FK_NO_ACTION, sqlite3 *db, int b); + ** + ** If b is true, then activate the SQLITE_FkNoAction setting. If b is + ** false then clearn that setting. If the SQLITE_FkNoAction setting is + ** abled, all foreign key ON DELETE and ON UPDATE actions behave as if + ** they were NO ACTION, regardless of how they are defined. + ** + ** NB: One must usually run "PRAGMA writable_schema=RESET" after + ** using this test-control, before it will take full effect. failing + ** to reset the schema can result in some unexpected behavior. + */ + case SQLITE_TESTCTRL_FK_NO_ACTION: { + sqlite3 *db = va_arg(ap, sqlite3*); + int b = va_arg(ap, int); + if( b ){ + db->flags |= SQLITE_FkNoAction; + }else{ + db->flags &= ~SQLITE_FkNoAction; + } + break; + } + /* ** sqlite3_test_control(BITVEC_TEST, size, program) ** @@ -180871,11 +184395,11 @@ SQLITE_API int sqlite3_test_control(int op, ...){ ** X<0 Make no changes to the bUseLongDouble. Just report value. ** X==0 Disable bUseLongDouble ** X==1 Enable bUseLongDouble - ** X==2 Set bUseLongDouble to its default value for this platform + ** X>=2 Set bUseLongDouble to its default value for this platform */ case SQLITE_TESTCTRL_USELONGDOUBLE: { int b = va_arg(ap, int); - if( b==2 ) b = sizeof(LONGDOUBLE_TYPE)>8; + if( b>=2 ) b = hasHighPrecisionDouble(b); if( b>=0 ) sqlite3Config.bUseLongDouble = b>0; rc = sqlite3Config.bUseLongDouble!=0; break; @@ -180912,6 +184436,28 @@ SQLITE_API int sqlite3_test_control(int op, ...){ break; } #endif + + /* sqlite3_test_control(SQLITE_TESTCTRL_JSON_SELFCHECK, &onOff); + ** + ** Activate or deactivate validation of JSONB that is generated from + ** text. Off by default, as the validation is slow. Validation is + ** only available if compiled using SQLITE_DEBUG. + ** + ** If onOff is initially 1, then turn it on. If onOff is initially + ** off, turn it off. If onOff is initially -1, then change onOff + ** to be the current setting. + */ + case SQLITE_TESTCTRL_JSON_SELFCHECK: { +#if defined(SQLITE_DEBUG) && !defined(SQLITE_OMIT_WSD) + int *pOnOff = va_arg(ap, int*); + if( *pOnOff<0 ){ + *pOnOff = sqlite3Config.bJsonSelfcheck; + }else{ + sqlite3Config.bJsonSelfcheck = (u8)((*pOnOff)&0xff); + } +#endif + break; + } } va_end(ap); #endif /* SQLITE_UNTESTABLE */ @@ -181289,7 +184835,7 @@ SQLITE_API int sqlite3_compileoption_used(const char *zOptName){ int nOpt; const char **azCompileOpt; -#if SQLITE_ENABLE_API_ARMOR +#ifdef SQLITE_ENABLE_API_ARMOR if( zOptName==0 ){ (void)SQLITE_MISUSE_BKPT; return 0; @@ -181484,6 +185030,9 @@ SQLITE_API int sqlite3_unlock_notify( ){ int rc = SQLITE_OK; +#ifdef SQLITE_ENABLE_API_ARMOR + if( !sqlite3SafetyCheckOk(db) ) return SQLITE_MISUSE_BKPT; +#endif sqlite3_mutex_enter(db->mutex); enterMutex(); @@ -182505,6 +186054,7 @@ struct Fts3Table { int nPgsz; /* Page size for host database */ char *zSegmentsTbl; /* Name of %_segments table */ sqlite3_blob *pSegments; /* Blob handle open on %_segments table */ + int iSavepoint; /* ** The following array of hash tables is used to buffer pending index @@ -182892,6 +186442,8 @@ SQLITE_PRIVATE int sqlite3FtsUnicodeIsdiacritic(int); SQLITE_PRIVATE int sqlite3Fts3ExprIterate(Fts3Expr*, int (*x)(Fts3Expr*,int,void*), void*); +SQLITE_PRIVATE int sqlite3Fts3IntegrityCheck(Fts3Table *p, int *pbOk); + #endif /* !SQLITE_CORE || SQLITE_ENABLE_FTS3 */ #endif /* _FTSINT_H */ @@ -183248,6 +186800,7 @@ static void fts3DeclareVtab(int *pRc, Fts3Table *p){ zLanguageid = (p->zLanguageid ? p->zLanguageid : "__langid"); sqlite3_vtab_config(p->db, SQLITE_VTAB_CONSTRAINT_SUPPORT, 1); + sqlite3_vtab_config(p->db, SQLITE_VTAB_INNOCUOUS); /* Create a list of user columns for the virtual table */ zCols = sqlite3_mprintf("%Q, ", p->azColumn[0]); @@ -186497,6 +190050,8 @@ static int fts3RenameMethod( rc = sqlite3Fts3PendingTermsFlush(p); } + p->bIgnoreSavepoint = 1; + if( p->zContentTbl==0 ){ fts3DbExec(&rc, db, "ALTER TABLE %Q.'%q_content' RENAME TO '%q_content';", @@ -186524,6 +190079,8 @@ static int fts3RenameMethod( "ALTER TABLE %Q.'%q_segdir' RENAME TO '%q_segdir';", p->zDb, p->zName, zName ); + + p->bIgnoreSavepoint = 0; return rc; } @@ -186534,12 +190091,28 @@ static int fts3RenameMethod( */ static int fts3SavepointMethod(sqlite3_vtab *pVtab, int iSavepoint){ int rc = SQLITE_OK; - UNUSED_PARAMETER(iSavepoint); - assert( ((Fts3Table *)pVtab)->inTransaction ); - assert( ((Fts3Table *)pVtab)->mxSavepoint <= iSavepoint ); - TESTONLY( ((Fts3Table *)pVtab)->mxSavepoint = iSavepoint ); - if( ((Fts3Table *)pVtab)->bIgnoreSavepoint==0 ){ - rc = fts3SyncMethod(pVtab); + Fts3Table *pTab = (Fts3Table*)pVtab; + assert( pTab->inTransaction ); + assert( pTab->mxSavepoint<=iSavepoint ); + TESTONLY( pTab->mxSavepoint = iSavepoint ); + + if( pTab->bIgnoreSavepoint==0 ){ + if( fts3HashCount(&pTab->aIndex[0].hPending)>0 ){ + char *zSql = sqlite3_mprintf("INSERT INTO %Q.%Q(%Q) VALUES('flush')", + pTab->zDb, pTab->zName, pTab->zName + ); + if( zSql ){ + pTab->bIgnoreSavepoint = 1; + rc = sqlite3_exec(pTab->db, zSql, 0, 0, 0); + pTab->bIgnoreSavepoint = 0; + sqlite3_free(zSql); + }else{ + rc = SQLITE_NOMEM; + } + } + if( rc==SQLITE_OK ){ + pTab->iSavepoint = iSavepoint+1; + } } return rc; } @@ -186550,12 +190123,11 @@ static int fts3SavepointMethod(sqlite3_vtab *pVtab, int iSavepoint){ ** This is a no-op. */ static int fts3ReleaseMethod(sqlite3_vtab *pVtab, int iSavepoint){ - TESTONLY( Fts3Table *p = (Fts3Table*)pVtab ); - UNUSED_PARAMETER(iSavepoint); - UNUSED_PARAMETER(pVtab); - assert( p->inTransaction ); - assert( p->mxSavepoint >= iSavepoint ); - TESTONLY( p->mxSavepoint = iSavepoint-1 ); + Fts3Table *pTab = (Fts3Table*)pVtab; + assert( pTab->inTransaction ); + assert( pTab->mxSavepoint >= iSavepoint ); + TESTONLY( pTab->mxSavepoint = iSavepoint-1 ); + pTab->iSavepoint = iSavepoint; return SQLITE_OK; } @@ -186565,11 +190137,13 @@ static int fts3ReleaseMethod(sqlite3_vtab *pVtab, int iSavepoint){ ** Discard the contents of the pending terms table. */ static int fts3RollbackToMethod(sqlite3_vtab *pVtab, int iSavepoint){ - Fts3Table *p = (Fts3Table*)pVtab; + Fts3Table *pTab = (Fts3Table*)pVtab; UNUSED_PARAMETER(iSavepoint); - assert( p->inTransaction ); - TESTONLY( p->mxSavepoint = iSavepoint ); - sqlite3Fts3PendingTermsClear(p); + assert( pTab->inTransaction ); + TESTONLY( pTab->mxSavepoint = iSavepoint ); + if( (iSavepoint+1)<=pTab->iSavepoint ){ + sqlite3Fts3PendingTermsClear(pTab); + } return SQLITE_OK; } @@ -186588,8 +190162,42 @@ static int fts3ShadowName(const char *zName){ return 0; } +/* +** Implementation of the xIntegrity() method on the FTS3/FTS4 virtual +** table. +*/ +static int fts3IntegrityMethod( + sqlite3_vtab *pVtab, /* The virtual table to be checked */ + const char *zSchema, /* Name of schema in which pVtab lives */ + const char *zTabname, /* Name of the pVTab table */ + int isQuick, /* True if this is a quick_check */ + char **pzErr /* Write error message here */ +){ + Fts3Table *p = (Fts3Table*)pVtab; + int rc = SQLITE_OK; + int bOk = 0; + + UNUSED_PARAMETER(isQuick); + rc = sqlite3Fts3IntegrityCheck(p, &bOk); + assert( rc!=SQLITE_CORRUPT_VTAB ); + if( rc==SQLITE_ERROR || (rc&0xFF)==SQLITE_CORRUPT ){ + *pzErr = sqlite3_mprintf("unable to validate the inverted index for" + " FTS%d table %s.%s: %s", + p->bFts4 ? 4 : 3, zSchema, zTabname, sqlite3_errstr(rc)); + if( *pzErr ) rc = SQLITE_OK; + }else if( rc==SQLITE_OK && bOk==0 ){ + *pzErr = sqlite3_mprintf("malformed inverted index for FTS%d table %s.%s", + p->bFts4 ? 4 : 3, zSchema, zTabname); + if( *pzErr==0 ) rc = SQLITE_NOMEM; + } + sqlite3Fts3SegmentsClose(p); + return rc; +} + + + static const sqlite3_module fts3Module = { - /* iVersion */ 3, + /* iVersion */ 4, /* xCreate */ fts3CreateMethod, /* xConnect */ fts3ConnectMethod, /* xBestIndex */ fts3BestIndexMethod, @@ -186613,6 +190221,7 @@ static const sqlite3_module fts3Module = { /* xRelease */ fts3ReleaseMethod, /* xRollbackTo */ fts3RollbackToMethod, /* xShadowName */ fts3ShadowName, + /* xIntegrity */ fts3IntegrityMethod, }; /* @@ -189288,7 +192897,8 @@ SQLITE_PRIVATE int sqlite3Fts3InitAux(sqlite3 *db){ 0, /* xSavepoint */ 0, /* xRelease */ 0, /* xRollbackTo */ - 0 /* xShadowName */ + 0, /* xShadowName */ + 0 /* xIntegrity */ }; int rc; /* Return code */ @@ -192854,7 +196464,8 @@ SQLITE_PRIVATE int sqlite3Fts3InitTok(sqlite3 *db, Fts3Hash *pHash, void(*xDestr 0, /* xSavepoint */ 0, /* xRelease */ 0, /* xRollbackTo */ - 0 /* xShadowName */ + 0, /* xShadowName */ + 0 /* xIntegrity */ }; int rc; /* Return code */ @@ -196195,7 +199806,6 @@ SQLITE_PRIVATE int sqlite3Fts3PendingTermsFlush(Fts3Table *p){ rc = fts3SegmentMerge(p, p->iPrevLangid, i, FTS3_SEGCURSOR_PENDING); if( rc==SQLITE_DONE ) rc = SQLITE_OK; } - sqlite3Fts3PendingTermsClear(p); /* Determine the auto-incr-merge setting if unknown. If enabled, ** estimate the number of leaf blocks of content to be written @@ -196217,6 +199827,10 @@ SQLITE_PRIVATE int sqlite3Fts3PendingTermsFlush(Fts3Table *p){ rc = sqlite3_reset(pStmt); } } + + if( rc==SQLITE_OK ){ + sqlite3Fts3PendingTermsClear(p); + } return rc; } @@ -196848,6 +200462,8 @@ static int fts3AppendToNode( blobGrowBuffer(pPrev, nTerm, &rc); if( rc!=SQLITE_OK ) return rc; + assert( pPrev!=0 ); + assert( pPrev->a!=0 ); nPrefix = fts3PrefixCompress(pPrev->a, pPrev->n, zTerm, nTerm); nSuffix = nTerm - nPrefix; @@ -196904,9 +200520,13 @@ static int fts3IncrmergeAppend( nSpace += sqlite3Fts3VarintLen(nDoclist) + nDoclist; /* If the current block is not empty, and if adding this term/doclist - ** to the current block would make it larger than Fts3Table.nNodeSize - ** bytes, write this block out to the database. */ - if( pLeaf->block.n>0 && (pLeaf->block.n + nSpace)>p->nNodeSize ){ + ** to the current block would make it larger than Fts3Table.nNodeSize bytes, + ** and if there is still room for another leaf page, write this block out to + ** the database. */ + if( pLeaf->block.n>0 + && (pLeaf->block.n + nSpace)>p->nNodeSize + && pLeaf->iBlock < (pWriter->iStart + pWriter->nLeafEst) + ){ rc = fts3WriteSegment(p, pLeaf->iBlock, pLeaf->block.a, pLeaf->block.n); pWriter->nWork++; @@ -197238,7 +200858,7 @@ static int fts3IncrmergeLoad( rc = sqlite3Fts3ReadBlock(p, reader.iChild, &aBlock, &nBlock,0); blobGrowBuffer(&pNode->block, MAX(nBlock, p->nNodeSize)+FTS3_NODE_PADDING, &rc - ); + ); if( rc==SQLITE_OK ){ memcpy(pNode->block.a, aBlock, nBlock); pNode->block.n = nBlock; @@ -198155,7 +201775,7 @@ static u64 fts3ChecksumIndex( ** If an error occurs (e.g. an OOM or IO error), return an SQLite error ** code. The final value of *pbOk is undefined in this case. */ -static int fts3IntegrityCheck(Fts3Table *p, int *pbOk){ +SQLITE_PRIVATE int sqlite3Fts3IntegrityCheck(Fts3Table *p, int *pbOk){ int rc = SQLITE_OK; /* Return code */ u64 cksum1 = 0; /* Checksum based on FTS index contents */ u64 cksum2 = 0; /* Checksum based on %_content contents */ @@ -198233,7 +201853,12 @@ static int fts3IntegrityCheck(Fts3Table *p, int *pbOk){ sqlite3_finalize(pStmt); } - *pbOk = (cksum1==cksum2); + if( rc==SQLITE_CORRUPT_VTAB ){ + rc = SQLITE_OK; + *pbOk = 0; + }else{ + *pbOk = (rc==SQLITE_OK && cksum1==cksum2); + } return rc; } @@ -198273,7 +201898,7 @@ static int fts3DoIntegrityCheck( ){ int rc; int bOk = 0; - rc = fts3IntegrityCheck(p, &bOk); + rc = sqlite3Fts3IntegrityCheck(p, &bOk); if( rc==SQLITE_OK && bOk==0 ) rc = FTS_CORRUPT_VTAB; return rc; } @@ -198303,8 +201928,11 @@ static int fts3SpecialInsert(Fts3Table *p, sqlite3_value *pVal){ rc = fts3DoIncrmerge(p, &zVal[6]); }else if( nVal>10 && 0==sqlite3_strnicmp(zVal, "automerge=", 10) ){ rc = fts3DoAutoincrmerge(p, &zVal[10]); + }else if( nVal==5 && 0==sqlite3_strnicmp(zVal, "flush", 5) ){ + rc = sqlite3Fts3PendingTermsFlush(p); + } #if defined(SQLITE_DEBUG) || defined(SQLITE_TEST) - }else{ + else{ int v; if( nVal>9 && 0==sqlite3_strnicmp(zVal, "nodesize=", 9) ){ v = atoi(&zVal[9]); @@ -198322,8 +201950,8 @@ static int fts3SpecialInsert(Fts3Table *p, sqlite3_value *pVal){ if( v>=4 && v<=FTS3_MERGE_COUNT && (v&1)==0 ) p->nMergeCount = v; rc = SQLITE_OK; } -#endif } +#endif return rc; } @@ -199136,7 +202764,7 @@ static void fts3SnippetDetails( } mCover |= mPhrase; - for(j=0; jnToken; j++){ + for(j=0; jnToken && jnSnippet; j++){ mHighlight |= (mPos>>j); } @@ -201244,24 +204872,145 @@ SQLITE_PRIVATE int sqlite3FtsUnicodeFold(int c, int eRemoveDiacritic){ ** ****************************************************************************** ** -** This SQLite JSON functions. +** SQLite JSON functions. ** ** This file began as an extension in ext/misc/json1.c in 2015. That ** extension proved so useful that it has now been moved into the core. ** -** For the time being, all JSON is stored as pure text. (We might add -** a JSONB type in the future which stores a binary encoding of JSON in -** a BLOB, but there is no support for JSONB in the current implementation. -** This implementation parses JSON text at 250 MB/s, so it is hard to see -** how JSONB might improve on that.) +** The original design stored all JSON as pure text, canonical RFC-8259. +** Support for JSON-5 extensions was added with version 3.42.0 (2023-05-16). +** All generated JSON text still conforms strictly to RFC-8259, but text +** with JSON-5 extensions is accepted as input. +** +** Beginning with version 3.45.0 (circa 2024-01-01), these routines also +** accept BLOB values that have JSON encoded using a binary representation +** called "JSONB". The name JSONB comes from PostgreSQL, however the on-disk +** format SQLite JSONB is completely different and incompatible with +** PostgreSQL JSONB. +** +** Decoding and interpreting JSONB is still O(N) where N is the size of +** the input, the same as text JSON. However, the constant of proportionality +** for JSONB is much smaller due to faster parsing. The size of each +** element in JSONB is encoded in its header, so there is no need to search +** for delimiters using persnickety syntax rules. JSONB seems to be about +** 3x faster than text JSON as a result. JSONB is also tends to be slightly +** smaller than text JSON, by 5% or 10%, but there are corner cases where +** JSONB can be slightly larger. So you are not far mistaken to say that +** a JSONB blob is the same size as the equivalent RFC-8259 text. +** +** +** THE JSONB ENCODING: +** +** Every JSON element is encoded in JSONB as a header and a payload. +** The header is between 1 and 9 bytes in size. The payload is zero +** or more bytes. +** +** The lower 4 bits of the first byte of the header determines the +** element type: +** +** 0: NULL +** 1: TRUE +** 2: FALSE +** 3: INT -- RFC-8259 integer literal +** 4: INT5 -- JSON5 integer literal +** 5: FLOAT -- RFC-8259 floating point literal +** 6: FLOAT5 -- JSON5 floating point literal +** 7: TEXT -- Text literal acceptable to both SQL and JSON +** 8: TEXTJ -- Text containing RFC-8259 escapes +** 9: TEXT5 -- Text containing JSON5 and/or RFC-8259 escapes +** 10: TEXTRAW -- Text containing unescaped syntax characters +** 11: ARRAY +** 12: OBJECT +** +** The other three possible values (13-15) are reserved for future +** enhancements. +** +** The upper 4 bits of the first byte determine the size of the header +** and sometimes also the size of the payload. If X is the first byte +** of the element and if X>>4 is between 0 and 11, then the payload +** will be that many bytes in size and the header is exactly one byte +** in size. Other four values for X>>4 (12-15) indicate that the header +** is more than one byte in size and that the payload size is determined +** by the remainder of the header, interpreted as a unsigned big-endian +** integer. +** +** Value of X>>4 Size integer Total header size +** ------------- -------------------- ----------------- +** 12 1 byte (0-255) 2 +** 13 2 byte (0-65535) 3 +** 14 4 byte (0-4294967295) 5 +** 15 8 byte (0-1.8e19) 9 +** +** The payload size need not be expressed in its minimal form. For example, +** if the payload size is 10, the size can be expressed in any of 5 different +** ways: (1) (X>>4)==10, (2) (X>>4)==12 following by on 0x0a byte, +** (3) (X>>4)==13 followed by 0x00 and 0x0a, (4) (X>>4)==14 followed by +** 0x00 0x00 0x00 0x0a, or (5) (X>>4)==15 followed by 7 bytes of 0x00 and +** a single byte of 0x0a. The shorter forms are preferred, of course, but +** sometimes when generating JSONB, the payload size is not known in advance +** and it is convenient to reserve sufficient header space to cover the +** largest possible payload size and then come back later and patch up +** the size when it becomes known, resulting in a non-minimal encoding. +** +** The value (X>>4)==15 is not actually used in the current implementation +** (as SQLite is currently unable handle BLOBs larger than about 2GB) +** but is included in the design to allow for future enhancements. +** +** The payload follows the header. NULL, TRUE, and FALSE have no payload and +** their payload size must always be zero. The payload for INT, INT5, +** FLOAT, FLOAT5, TEXT, TEXTJ, TEXT5, and TEXTROW is text. Note that the +** "..." or '...' delimiters are omitted from the various text encodings. +** The payload for ARRAY and OBJECT is a list of additional elements that +** are the content for the array or object. The payload for an OBJECT +** must be an even number of elements. The first element of each pair is +** the label and must be of type TEXT, TEXTJ, TEXT5, or TEXTRAW. +** +** A valid JSONB blob consists of a single element, as described above. +** Usually this will be an ARRAY or OBJECT element which has many more +** elements as its content. But the overall blob is just a single element. +** +** Input validation for JSONB blobs simply checks that the element type +** code is between 0 and 12 and that the total size of the element +** (header plus payload) is the same as the size of the BLOB. If those +** checks are true, the BLOB is assumed to be JSONB and processing continues. +** Errors are only raised if some other miscoding is discovered during +** processing. +** +** Additional information can be found in the doc/jsonb.md file of the +** canonical SQLite source tree. */ #ifndef SQLITE_OMIT_JSON /* #include "sqliteInt.h" */ +/* JSONB element types +*/ +#define JSONB_NULL 0 /* "null" */ +#define JSONB_TRUE 1 /* "true" */ +#define JSONB_FALSE 2 /* "false" */ +#define JSONB_INT 3 /* integer acceptable to JSON and SQL */ +#define JSONB_INT5 4 /* integer in 0x000 notation */ +#define JSONB_FLOAT 5 /* float acceptable to JSON and SQL */ +#define JSONB_FLOAT5 6 /* float with JSON5 extensions */ +#define JSONB_TEXT 7 /* Text compatible with both JSON and SQL */ +#define JSONB_TEXTJ 8 /* Text with JSON escapes */ +#define JSONB_TEXT5 9 /* Text with JSON-5 escape */ +#define JSONB_TEXTRAW 10 /* SQL text that needs escaping for JSON */ +#define JSONB_ARRAY 11 /* An array */ +#define JSONB_OBJECT 12 /* An object */ + +/* Human-readable names for the JSONB values. The index for each +** string must correspond to the JSONB_* integer above. +*/ +static const char * const jsonbType[] = { + "null", "true", "false", "integer", "integer", + "real", "real", "text", "text", "text", + "text", "array", "object", "", "", "", "" +}; + /* ** Growing our own isspace() routine this way is twice as fast as ** the library isspace() function, resulting in a 7% overall performance -** increase for the parser. (Ubuntu14.10 gcc 4.8.4 x64 with -Os). +** increase for the text-JSON parser. (Ubuntu14.10 gcc 4.8.4 x64 with -Os). */ static const char jsonIsSpace[] = { 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 1, 0, 0, 1, 0, 0, @@ -201282,11 +205031,19 @@ static const char jsonIsSpace[] = { 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, }; -#define fast_isspace(x) (jsonIsSpace[(unsigned char)x]) +#define jsonIsspace(x) (jsonIsSpace[(unsigned char)x]) + +/* +** The set of all space characters recognized by jsonIsspace(). +** Useful as the second argument to strspn(). +*/ +static const char jsonSpaces[] = "\011\012\015\040"; /* -** Characters that are special to JSON. Control charaters, -** '"' and '\\'. +** Characters that are special to JSON. Control characters, +** '"' and '\\' and '\''. Actually, '\'' is not special to +** canonical JSON, but it is special in JSON-5, so we include +** it in the set of special characters. */ static const char jsonIsOk[256] = { 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, @@ -201308,22 +205065,49 @@ static const char jsonIsOk[256] = { 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1 }; - -#if !defined(SQLITE_DEBUG) && !defined(SQLITE_COVERAGE_TEST) -# define VVA(X) -#else -# define VVA(X) X -#endif - /* Objects */ +typedef struct JsonCache JsonCache; typedef struct JsonString JsonString; -typedef struct JsonNode JsonNode; typedef struct JsonParse JsonParse; -typedef struct JsonCleanup JsonCleanup; + +/* +** Magic number used for the JSON parse cache in sqlite3_get_auxdata() +*/ +#define JSON_CACHE_ID (-429938) /* Cache entry */ +#define JSON_CACHE_SIZE 4 /* Max number of cache entries */ + +/* +** jsonUnescapeOneChar() returns this invalid code point if it encounters +** a syntax error. +*/ +#define JSON_INVALID_CHAR 0x99999 + +/* A cache mapping JSON text into JSONB blobs. +** +** Each cache entry is a JsonParse object with the following restrictions: +** +** * The bReadOnly flag must be set +** +** * The aBlob[] array must be owned by the JsonParse object. In other +** words, nBlobAlloc must be non-zero. +** +** * eEdit and delta must be zero. +** +** * zJson must be an RCStr. In other words bJsonIsRCStr must be true. +*/ +struct JsonCache { + sqlite3 *db; /* Database connection */ + int nUsed; /* Number of active entries in the cache */ + JsonParse *a[JSON_CACHE_SIZE]; /* One line for each cache entry */ +}; /* An instance of this object represents a JSON string ** under construction. Really, this is a generic string accumulator ** that can be and is used to create strings other than JSON. +** +** If the generated string is longer than will fit into the zSpace[] buffer, +** then it will be an RCStr string. This aids with caching of large +** JSON strings. */ struct JsonString { sqlite3_context *pCtx; /* Function context - put error messages here */ @@ -201331,121 +205115,75 @@ struct JsonString { u64 nAlloc; /* Bytes of storage available in zBuf[] */ u64 nUsed; /* Bytes of zBuf[] currently used */ u8 bStatic; /* True if zBuf is static space */ - u8 bErr; /* True if an error has been encountered */ + u8 eErr; /* True if an error has been encountered */ char zSpace[100]; /* Initial static space */ }; -/* A deferred cleanup task. A list of JsonCleanup objects might be -** run when the JsonParse object is destroyed. -*/ -struct JsonCleanup { - JsonCleanup *pJCNext; /* Next in a list */ - void (*xOp)(void*); /* Routine to run */ - void *pArg; /* Argument to xOp() */ -}; +/* Allowed values for JsonString.eErr */ +#define JSTRING_OOM 0x01 /* Out of memory */ +#define JSTRING_MALFORMED 0x02 /* Malformed JSONB */ +#define JSTRING_ERR 0x04 /* Error already sent to sqlite3_result */ -/* JSON type values +/* The "subtype" set for text JSON values passed through using +** sqlite3_result_subtype() and sqlite3_value_subtype(). */ -#define JSON_SUBST 0 /* Special edit node. Uses u.iPrev */ -#define JSON_NULL 1 -#define JSON_TRUE 2 -#define JSON_FALSE 3 -#define JSON_INT 4 -#define JSON_REAL 5 -#define JSON_STRING 6 -#define JSON_ARRAY 7 -#define JSON_OBJECT 8 - -/* The "subtype" set for JSON values */ #define JSON_SUBTYPE 74 /* Ascii for "J" */ /* -** Names of the various JSON types: -*/ -static const char * const jsonType[] = { - "subst", - "null", "true", "false", "integer", "real", "text", "array", "object" -}; - -/* Bit values for the JsonNode.jnFlag field -*/ -#define JNODE_RAW 0x01 /* Content is raw, not JSON encoded */ -#define JNODE_ESCAPE 0x02 /* Content is text with \ escapes */ -#define JNODE_REMOVE 0x04 /* Do not output */ -#define JNODE_REPLACE 0x08 /* Target of a JSON_SUBST node */ -#define JNODE_APPEND 0x10 /* More ARRAY/OBJECT entries at u.iAppend */ -#define JNODE_LABEL 0x20 /* Is a label of an object */ -#define JNODE_JSON5 0x40 /* Node contains JSON5 enhancements */ - - -/* A single node of parsed JSON. An array of these nodes describes -** a parse of JSON + edits. -** -** Use the json_parse() SQL function (available when compiled with -** -DSQLITE_DEBUG) to see a dump of complete JsonParse objects, including -** a complete listing and decoding of the array of JsonNodes. +** Bit values for the flags passed into various SQL function implementations +** via the sqlite3_user_data() value. */ -struct JsonNode { - u8 eType; /* One of the JSON_ type values */ - u8 jnFlags; /* JNODE flags */ - u8 eU; /* Which union element to use */ - u32 n; /* Bytes of content for INT, REAL or STRING - ** Number of sub-nodes for ARRAY and OBJECT - ** Node that SUBST applies to */ - union { - const char *zJContent; /* 1: Content for INT, REAL, and STRING */ - u32 iAppend; /* 2: More terms for ARRAY and OBJECT */ - u32 iKey; /* 3: Key for ARRAY objects in json_tree() */ - u32 iPrev; /* 4: Previous SUBST node, or 0 */ - } u; -}; +#define JSON_JSON 0x01 /* Result is always JSON */ +#define JSON_SQL 0x02 /* Result is always SQL */ +#define JSON_ABPATH 0x03 /* Allow abbreviated JSON path specs */ +#define JSON_ISSET 0x04 /* json_set(), not json_insert() */ +#define JSON_BLOB 0x08 /* Use the BLOB output format */ -/* A parsed and possibly edited JSON string. Lifecycle: +/* A parsed JSON value. Lifecycle: ** -** 1. JSON comes in and is parsed into an array aNode[]. The original -** JSON text is stored in zJson. +** 1. JSON comes in and is parsed into a JSONB value in aBlob. The +** original text is stored in zJson. This step is skipped if the +** input is JSONB instead of text JSON. ** -** 2. Zero or more changes are made (via json_remove() or json_replace() -** or similar) to the aNode[] array. +** 2. The aBlob[] array is searched using the JSON path notation, if needed. ** -** 3. A new, edited and mimified JSON string is generated from aNode -** and stored in zAlt. The JsonParse object always owns zAlt. +** 3. Zero or more changes are made to aBlob[] (via json_remove() or +** json_replace() or json_patch() or similar). ** -** Step 1 always happens. Step 2 and 3 may or may not happen, depending -** on the operation. -** -** aNode[].u.zJContent entries typically point into zJson. Hence zJson -** must remain valid for the lifespan of the parse. For edits, -** aNode[].u.zJContent might point to malloced space other than zJson. -** Entries in pClup are responsible for freeing that extra malloced space. -** -** When walking the parse tree in aNode[], edits are ignored if useMod is -** false. +** 4. New JSON text is generated from the aBlob[] for output. This step +** is skipped if the function is one of the jsonb_* functions that +** returns JSONB instead of text JSON. */ struct JsonParse { - u32 nNode; /* Number of slots of aNode[] used */ - u32 nAlloc; /* Number of slots of aNode[] allocated */ - JsonNode *aNode; /* Array of nodes containing the parse */ - char *zJson; /* Original JSON string (before edits) */ - char *zAlt; /* Revised and/or mimified JSON */ - u32 *aUp; /* Index of parent of each node */ - JsonCleanup *pClup;/* Cleanup operations prior to freeing this object */ + u8 *aBlob; /* JSONB representation of JSON value */ + u32 nBlob; /* Bytes of aBlob[] actually used */ + u32 nBlobAlloc; /* Bytes allocated to aBlob[]. 0 if aBlob is external */ + char *zJson; /* Json text used for parsing */ + sqlite3 *db; /* The database connection to which this object belongs */ + int nJson; /* Length of the zJson string in bytes */ + u32 nJPRef; /* Number of references to this object */ + u32 iErr; /* Error location in zJson[] */ u16 iDepth; /* Nesting depth */ u8 nErr; /* Number of errors seen */ u8 oom; /* Set to true if out of memory */ u8 bJsonIsRCStr; /* True if zJson is an RCStr */ u8 hasNonstd; /* True if input uses non-standard features like JSON5 */ - u8 useMod; /* Actually use the edits contain inside aNode */ - u8 hasMod; /* aNode contains edits from the original zJson */ - u32 nJPRef; /* Number of references to this object */ - int nJson; /* Length of the zJson string in bytes */ - int nAlt; /* Length of alternative JSON string zAlt, in bytes */ - u32 iErr; /* Error location in zJson[] */ - u32 iSubst; /* Last JSON_SUBST entry in aNode[] */ - u32 iHold; /* Age of this entry in the cache for LRU replacement */ + u8 bReadOnly; /* Do not modify. */ + /* Search and edit information. See jsonLookupStep() */ + u8 eEdit; /* Edit operation to apply */ + int delta; /* Size change due to the edit */ + u32 nIns; /* Number of bytes to insert */ + u32 iLabel; /* Location of label if search landed on an object value */ + u8 *aIns; /* Content to be inserted */ }; +/* Allowed values for JsonParse.eEdit */ +#define JEDIT_DEL 1 /* Delete if exists */ +#define JEDIT_REPL 2 /* Overwrite if exists */ +#define JEDIT_INS 3 /* Insert if not exists */ +#define JEDIT_SET 4 /* Insert or overwrite */ + /* ** Maximum nesting depth of JSON for this implementation. ** @@ -201453,15 +205191,151 @@ struct JsonParse { ** descent parser. A depth of 1000 is far deeper than any sane JSON ** should go. Historical note: This limit was 2000 prior to version 3.42.0 */ -#define JSON_MAX_DEPTH 1000 +#ifndef SQLITE_JSON_MAX_DEPTH +# define JSON_MAX_DEPTH 1000 +#else +# define JSON_MAX_DEPTH SQLITE_JSON_MAX_DEPTH +#endif + +/* +** Allowed values for the flgs argument to jsonParseFuncArg(); +*/ +#define JSON_EDITABLE 0x01 /* Generate a writable JsonParse object */ +#define JSON_KEEPERROR 0x02 /* Return non-NULL even if there is an error */ + +/************************************************************************** +** Forward references +**************************************************************************/ +static void jsonReturnStringAsBlob(JsonString*); +static int jsonFuncArgMightBeBinary(sqlite3_value *pJson); +static u32 jsonTranslateBlobToText(const JsonParse*,u32,JsonString*); +static void jsonReturnParse(sqlite3_context*,JsonParse*); +static JsonParse *jsonParseFuncArg(sqlite3_context*,sqlite3_value*,u32); +static void jsonParseFree(JsonParse*); +static u32 jsonbPayloadSize(const JsonParse*, u32, u32*); +static u32 jsonUnescapeOneChar(const char*, u32, u32*); + +/************************************************************************** +** Utility routines for dealing with JsonCache objects +**************************************************************************/ + +/* +** Free a JsonCache object. +*/ +static void jsonCacheDelete(JsonCache *p){ + int i; + for(i=0; inUsed; i++){ + jsonParseFree(p->a[i]); + } + sqlite3DbFree(p->db, p); +} +static void jsonCacheDeleteGeneric(void *p){ + jsonCacheDelete((JsonCache*)p); +} + +/* +** Insert a new entry into the cache. If the cache is full, expel +** the least recently used entry. Return SQLITE_OK on success or a +** result code otherwise. +** +** Cache entries are stored in age order, oldest first. +*/ +static int jsonCacheInsert( + sqlite3_context *ctx, /* The SQL statement context holding the cache */ + JsonParse *pParse /* The parse object to be added to the cache */ +){ + JsonCache *p; + + assert( pParse->zJson!=0 ); + assert( pParse->bJsonIsRCStr ); + assert( pParse->delta==0 ); + p = sqlite3_get_auxdata(ctx, JSON_CACHE_ID); + if( p==0 ){ + sqlite3 *db = sqlite3_context_db_handle(ctx); + p = sqlite3DbMallocZero(db, sizeof(*p)); + if( p==0 ) return SQLITE_NOMEM; + p->db = db; + sqlite3_set_auxdata(ctx, JSON_CACHE_ID, p, jsonCacheDeleteGeneric); + p = sqlite3_get_auxdata(ctx, JSON_CACHE_ID); + if( p==0 ) return SQLITE_NOMEM; + } + if( p->nUsed >= JSON_CACHE_SIZE ){ + jsonParseFree(p->a[0]); + memmove(p->a, &p->a[1], (JSON_CACHE_SIZE-1)*sizeof(p->a[0])); + p->nUsed = JSON_CACHE_SIZE-1; + } + assert( pParse->nBlobAlloc>0 ); + pParse->eEdit = 0; + pParse->nJPRef++; + pParse->bReadOnly = 1; + p->a[p->nUsed] = pParse; + p->nUsed++; + return SQLITE_OK; +} + +/* +** Search for a cached translation the json text supplied by pArg. Return +** the JsonParse object if found. Return NULL if not found. +** +** When a match if found, the matching entry is moved to become the +** most-recently used entry if it isn't so already. +** +** The JsonParse object returned still belongs to the Cache and might +** be deleted at any moment. If the caller whants the JsonParse to +** linger, it needs to increment the nPJRef reference counter. +*/ +static JsonParse *jsonCacheSearch( + sqlite3_context *ctx, /* The SQL statement context holding the cache */ + sqlite3_value *pArg /* Function argument containing SQL text */ +){ + JsonCache *p; + int i; + const char *zJson; + int nJson; + + if( sqlite3_value_type(pArg)!=SQLITE_TEXT ){ + return 0; + } + zJson = (const char*)sqlite3_value_text(pArg); + if( zJson==0 ) return 0; + nJson = sqlite3_value_bytes(pArg); + + p = sqlite3_get_auxdata(ctx, JSON_CACHE_ID); + if( p==0 ){ + return 0; + } + for(i=0; inUsed; i++){ + if( p->a[i]->zJson==zJson ) break; + } + if( i>=p->nUsed ){ + for(i=0; inUsed; i++){ + if( p->a[i]->nJson!=nJson ) continue; + if( memcmp(p->a[i]->zJson, zJson, nJson)==0 ) break; + } + } + if( inUsed ){ + if( inUsed-1 ){ + /* Make the matching entry the most recently used entry */ + JsonParse *tmp = p->a[i]; + memmove(&p->a[i], &p->a[i+1], (p->nUsed-i-1)*sizeof(tmp)); + p->a[p->nUsed-1] = tmp; + i = p->nUsed - 1; + } + assert( p->a[i]->delta==0 ); + return p->a[i]; + }else{ + return 0; + } +} /************************************************************************** ** Utility routines for dealing with JsonString objects **************************************************************************/ -/* Set the JsonString object to an empty string +/* Turn uninitialized bulk memory into a valid JsonString object +** holding a zero-length string. */ -static void jsonZero(JsonString *p){ +static void jsonStringZero(JsonString *p){ p->zBuf = p->zSpace; p->nAlloc = sizeof(p->zSpace); p->nUsed = 0; @@ -201470,39 +205344,39 @@ static void jsonZero(JsonString *p){ /* Initialize the JsonString object */ -static void jsonInit(JsonString *p, sqlite3_context *pCtx){ +static void jsonStringInit(JsonString *p, sqlite3_context *pCtx){ p->pCtx = pCtx; - p->bErr = 0; - jsonZero(p); + p->eErr = 0; + jsonStringZero(p); } /* Free all allocated memory and reset the JsonString object back to its ** initial state. */ -static void jsonReset(JsonString *p){ +static void jsonStringReset(JsonString *p){ if( !p->bStatic ) sqlite3RCStrUnref(p->zBuf); - jsonZero(p); + jsonStringZero(p); } /* Report an out-of-memory (OOM) condition */ -static void jsonOom(JsonString *p){ - p->bErr = 1; - sqlite3_result_error_nomem(p->pCtx); - jsonReset(p); +static void jsonStringOom(JsonString *p){ + p->eErr |= JSTRING_OOM; + if( p->pCtx ) sqlite3_result_error_nomem(p->pCtx); + jsonStringReset(p); } /* Enlarge pJson->zBuf so that it can hold at least N more bytes. ** Return zero on success. Return non-zero on an OOM error */ -static int jsonGrow(JsonString *p, u32 N){ +static int jsonStringGrow(JsonString *p, u32 N){ u64 nTotal = NnAlloc ? p->nAlloc*2 : p->nAlloc+N+10; char *zNew; if( p->bStatic ){ - if( p->bErr ) return 1; + if( p->eErr ) return 1; zNew = sqlite3RCStrNew(nTotal); if( zNew==0 ){ - jsonOom(p); + jsonStringOom(p); return SQLITE_NOMEM; } memcpy(zNew, p->zBuf, (size_t)p->nUsed); @@ -201511,8 +205385,8 @@ static int jsonGrow(JsonString *p, u32 N){ }else{ p->zBuf = sqlite3RCStrResize(p->zBuf, nTotal); if( p->zBuf==0 ){ - p->bErr = 1; - jsonZero(p); + p->eErr |= JSTRING_OOM; + jsonStringZero(p); return SQLITE_NOMEM; } } @@ -201522,20 +205396,20 @@ static int jsonGrow(JsonString *p, u32 N){ /* Append N bytes from zIn onto the end of the JsonString string. */ -static SQLITE_NOINLINE void jsonAppendExpand( +static SQLITE_NOINLINE void jsonStringExpandAndAppend( JsonString *p, const char *zIn, u32 N ){ assert( N>0 ); - if( jsonGrow(p,N) ) return; + if( jsonStringGrow(p,N) ) return; memcpy(p->zBuf+p->nUsed, zIn, N); p->nUsed += N; } static void jsonAppendRaw(JsonString *p, const char *zIn, u32 N){ if( N==0 ) return; if( N+p->nUsed >= p->nAlloc ){ - jsonAppendExpand(p,zIn,N); + jsonStringExpandAndAppend(p,zIn,N); }else{ memcpy(p->zBuf+p->nUsed, zIn, N); p->nUsed += N; @@ -201544,19 +205418,18 @@ static void jsonAppendRaw(JsonString *p, const char *zIn, u32 N){ static void jsonAppendRawNZ(JsonString *p, const char *zIn, u32 N){ assert( N>0 ); if( N+p->nUsed >= p->nAlloc ){ - jsonAppendExpand(p,zIn,N); + jsonStringExpandAndAppend(p,zIn,N); }else{ memcpy(p->zBuf+p->nUsed, zIn, N); p->nUsed += N; } } - /* Append formatted text (not to exceed N bytes) to the JsonString. */ static void jsonPrintf(int N, JsonString *p, const char *zFormat, ...){ va_list ap; - if( (p->nUsed + N >= p->nAlloc) && jsonGrow(p, N) ) return; + if( (p->nUsed + N >= p->nAlloc) && jsonStringGrow(p, N) ) return; va_start(ap, zFormat); sqlite3_vsnprintf(N, p->zBuf+p->nUsed, zFormat, ap); va_end(ap); @@ -201566,7 +205439,7 @@ static void jsonPrintf(int N, JsonString *p, const char *zFormat, ...){ /* Append a single character */ static SQLITE_NOINLINE void jsonAppendCharExpand(JsonString *p, char c){ - if( jsonGrow(p,1) ) return; + if( jsonStringGrow(p,1) ) return; p->zBuf[p->nUsed++] = c; } static void jsonAppendChar(JsonString *p, char c){ @@ -201577,24 +205450,27 @@ static void jsonAppendChar(JsonString *p, char c){ } } -/* Try to force the string to be a zero-terminated RCStr string. +/* Remove a single character from the end of the string +*/ +static void jsonStringTrimOneChar(JsonString *p){ + if( p->eErr==0 ){ + assert( p->nUsed>0 ); + p->nUsed--; + } +} + + +/* Make sure there is a zero terminator on p->zBuf[] ** ** Return true on success. Return false if an OOM prevents this ** from happening. */ -static int jsonForceRCStr(JsonString *p){ +static int jsonStringTerminate(JsonString *p){ jsonAppendChar(p, 0); - if( p->bErr ) return 0; - p->nUsed--; - if( p->bStatic==0 ) return 1; - p->nAlloc = 0; - p->nUsed++; - jsonGrow(p, p->nUsed); - p->nUsed--; - return p->bStatic==0; + jsonStringTrimOneChar(p); + return p->eErr==0; } - /* Append a comma separator to the output buffer, if the previous ** character is not '[' or '{'. */ @@ -201606,184 +205482,120 @@ static void jsonAppendSeparator(JsonString *p){ jsonAppendChar(p, ','); } -/* Append the N-byte string in zIn to the end of the JsonString string -** under construction. Enclose the string in "..." and escape -** any double-quotes or backslash characters contained within the -** string. +/* c is a control character. Append the canonical JSON representation +** of that control character to p. +** +** This routine assumes that the output buffer has already been enlarged +** sufficiently to hold the worst-case encoding plus a nul terminator. */ -static void jsonAppendString(JsonString *p, const char *zIn, u32 N){ - u32 i; - if( zIn==0 || ((N+p->nUsed+2 >= p->nAlloc) && jsonGrow(p,N+2)!=0) ) return; - p->zBuf[p->nUsed++] = '"'; - for(i=0; izBuf[p->nUsed++] = c; - }else if( c=='"' || c=='\\' ){ - json_simple_escape: - if( (p->nUsed+N+3-i > p->nAlloc) && jsonGrow(p,N+3-i)!=0 ) return; - p->zBuf[p->nUsed++] = '\\'; - p->zBuf[p->nUsed++] = c; - }else if( c=='\'' ){ - p->zBuf[p->nUsed++] = c; - }else{ - static const char aSpecial[] = { - 0, 0, 0, 0, 0, 0, 0, 0, 'b', 't', 'n', 0, 'f', 'r', 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 - }; - assert( sizeof(aSpecial)==32 ); - assert( aSpecial['\b']=='b' ); - assert( aSpecial['\f']=='f' ); - assert( aSpecial['\n']=='n' ); - assert( aSpecial['\r']=='r' ); - assert( aSpecial['\t']=='t' ); - assert( c>=0 && cnUsed+N+7+i > p->nAlloc) && jsonGrow(p,N+7-i)!=0 ) return; - p->zBuf[p->nUsed++] = '\\'; - p->zBuf[p->nUsed++] = 'u'; - p->zBuf[p->nUsed++] = '0'; - p->zBuf[p->nUsed++] = '0'; - p->zBuf[p->nUsed++] = "0123456789abcdef"[c>>4]; - p->zBuf[p->nUsed++] = "0123456789abcdef"[c&0xf]; - } +static void jsonAppendControlChar(JsonString *p, u8 c){ + static const char aSpecial[] = { + 0, 0, 0, 0, 0, 0, 0, 0, 'b', 't', 'n', 0, 'f', 'r', 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 + }; + assert( sizeof(aSpecial)==32 ); + assert( aSpecial['\b']=='b' ); + assert( aSpecial['\f']=='f' ); + assert( aSpecial['\n']=='n' ); + assert( aSpecial['\r']=='r' ); + assert( aSpecial['\t']=='t' ); + assert( c>=0 && cnUsed+7 <= p->nAlloc ); + if( aSpecial[c] ){ + p->zBuf[p->nUsed] = '\\'; + p->zBuf[p->nUsed+1] = aSpecial[c]; + p->nUsed += 2; + }else{ + p->zBuf[p->nUsed] = '\\'; + p->zBuf[p->nUsed+1] = 'u'; + p->zBuf[p->nUsed+2] = '0'; + p->zBuf[p->nUsed+3] = '0'; + p->zBuf[p->nUsed+4] = "0123456789abcdef"[c>>4]; + p->zBuf[p->nUsed+5] = "0123456789abcdef"[c&0xf]; + p->nUsed += 6; } - p->zBuf[p->nUsed++] = '"'; - assert( p->nUsednAlloc ); } -/* -** The zIn[0..N] string is a JSON5 string literal. Append to p a translation -** of the string literal that standard JSON and that omits all JSON5 -** features. +/* Append the N-byte string in zIn to the end of the JsonString string +** under construction. Enclose the string in double-quotes ("...") and +** escape any double-quotes or backslash characters contained within the +** string. +** +** This routine is a high-runner. There is a measurable performance +** increase associated with unwinding the jsonIsOk[] loop. */ -static void jsonAppendNormalizedString(JsonString *p, const char *zIn, u32 N){ - u32 i; - jsonAppendChar(p, '"'); - zIn++; - N -= 2; - while( N>0 ){ - for(i=0; i0 ){ - jsonAppendRawNZ(p, zIn, i); - zIn += i; - N -= i; - if( N==0 ) break; - } - assert( zIn[0]=='\\' ); - switch( (u8)zIn[1] ){ - case '\'': - jsonAppendChar(p, '\''); - break; - case 'v': - jsonAppendRawNZ(p, "\\u0009", 6); - break; - case 'x': - jsonAppendRawNZ(p, "\\u00", 4); - jsonAppendRawNZ(p, &zIn[2], 2); - zIn += 2; - N -= 2; - break; - case '0': - jsonAppendRawNZ(p, "\\u0000", 6); +static void jsonAppendString(JsonString *p, const char *zIn, u32 N){ + u32 k; + u8 c; + const u8 *z = (const u8*)zIn; + if( z==0 ) return; + if( (N+p->nUsed+2 >= p->nAlloc) && jsonStringGrow(p,N+2)!=0 ) return; + p->zBuf[p->nUsed++] = '"'; + while( 1 /*exit-by-break*/ ){ + k = 0; + /* The following while() is the 4-way unwound equivalent of + ** + ** while( k=N ){ + while( k=4 ); - assert( 0x80==(u8)zIn[2] ); - assert( 0xa8==(u8)zIn[3] || 0xa9==(u8)zIn[3] ); - zIn += 2; - N -= 2; + } + if( !jsonIsOk[z[k+2]] ){ + k += 2; break; - default: - jsonAppendRawNZ(p, zIn, 2); + } + if( !jsonIsOk[z[k+3]] ){ + k += 3; break; + }else{ + k += 4; + } } - zIn += 2; - N -= 2; - } - jsonAppendChar(p, '"'); -} - -/* -** The zIn[0..N] string is a JSON5 integer literal. Append to p a translation -** of the string literal that standard JSON and that omits all JSON5 -** features. -*/ -static void jsonAppendNormalizedInt(JsonString *p, const char *zIn, u32 N){ - if( zIn[0]=='+' ){ - zIn++; - N--; - }else if( zIn[0]=='-' ){ - jsonAppendChar(p, '-'); - zIn++; - N--; - } - if( zIn[0]=='0' && (zIn[1]=='x' || zIn[1]=='X') ){ - sqlite3_int64 i = 0; - int rc = sqlite3DecOrHexToI64(zIn, &i); - if( rc<=1 ){ - jsonPrintf(100,p,"%lld",i); + if( k>=N ){ + if( k>0 ){ + memcpy(&p->zBuf[p->nUsed], z, k); + p->nUsed += k; + } + break; + } + if( k>0 ){ + memcpy(&p->zBuf[p->nUsed], z, k); + p->nUsed += k; + z += k; + N -= k; + } + c = z[0]; + if( c=='"' || c=='\\' ){ + if( (p->nUsed+N+3 > p->nAlloc) && jsonStringGrow(p,N+3)!=0 ) return; + p->zBuf[p->nUsed++] = '\\'; + p->zBuf[p->nUsed++] = c; + }else if( c=='\'' ){ + p->zBuf[p->nUsed++] = c; }else{ - assert( rc==2 ); - jsonAppendRawNZ(p, "9.0e999", 7); + if( (p->nUsed+N+7 > p->nAlloc) && jsonStringGrow(p,N+7)!=0 ) return; + jsonAppendControlChar(p, c); } - return; - } - assert( N>0 ); - jsonAppendRawNZ(p, zIn, N); -} - -/* -** The zIn[0..N] string is a JSON5 real literal. Append to p a translation -** of the string literal that standard JSON and that omits all JSON5 -** features. -*/ -static void jsonAppendNormalizedReal(JsonString *p, const char *zIn, u32 N){ - u32 i; - if( zIn[0]=='+' ){ - zIn++; - N--; - }else if( zIn[0]=='-' ){ - jsonAppendChar(p, '-'); - zIn++; + z++; N--; } - if( zIn[0]=='.' ){ - jsonAppendChar(p, '0'); - } - for(i=0; i0 ){ - jsonAppendRawNZ(p, zIn, N); - } + p->zBuf[p->nUsed++] = '"'; + assert( p->nUsednAlloc ); } - - /* -** Append a function parameter value to the JSON string under -** construction. +** Append an sqlite3_value (such as a function parameter) to the JSON +** string under construction in p. */ -static void jsonAppendValue( +static void jsonAppendSqlValue( JsonString *p, /* Append to this JSON string */ sqlite3_value *pValue /* Value to append */ ){ @@ -201813,290 +205625,127 @@ static void jsonAppendValue( break; } default: { - if( p->bErr==0 ){ + if( jsonFuncArgMightBeBinary(pValue) ){ + JsonParse px; + memset(&px, 0, sizeof(px)); + px.aBlob = (u8*)sqlite3_value_blob(pValue); + px.nBlob = sqlite3_value_bytes(pValue); + jsonTranslateBlobToText(&px, 0, p); + }else if( p->eErr==0 ){ sqlite3_result_error(p->pCtx, "JSON cannot hold BLOB values", -1); - p->bErr = 2; - jsonReset(p); + p->eErr = JSTRING_ERR; + jsonStringReset(p); } break; } } } - -/* Make the JSON in p the result of the SQL function. +/* Make the text in p (which is probably a generated JSON text string) +** the result of the SQL function. +** +** The JsonString is reset. ** -** The JSON string is reset. +** If pParse and ctx are both non-NULL, then the SQL string in p is +** loaded into the zJson field of the pParse object as a RCStr and the +** pParse is added to the cache. */ -static void jsonResult(JsonString *p){ - if( p->bErr==0 ){ - if( p->bStatic ){ +static void jsonReturnString( + JsonString *p, /* String to return */ + JsonParse *pParse, /* JSONB source or NULL */ + sqlite3_context *ctx /* Where to cache */ +){ + assert( (pParse!=0)==(ctx!=0) ); + assert( ctx==0 || ctx==p->pCtx ); + if( p->eErr==0 ){ + int flags = SQLITE_PTR_TO_INT(sqlite3_user_data(p->pCtx)); + if( flags & JSON_BLOB ){ + jsonReturnStringAsBlob(p); + }else if( p->bStatic ){ sqlite3_result_text64(p->pCtx, p->zBuf, p->nUsed, SQLITE_TRANSIENT, SQLITE_UTF8); - }else if( jsonForceRCStr(p) ){ - sqlite3RCStrRef(p->zBuf); - sqlite3_result_text64(p->pCtx, p->zBuf, p->nUsed, - (void(*)(void*))sqlite3RCStrUnref, + }else if( jsonStringTerminate(p) ){ + if( pParse && pParse->bJsonIsRCStr==0 && pParse->nBlobAlloc>0 ){ + int rc; + pParse->zJson = sqlite3RCStrRef(p->zBuf); + pParse->nJson = p->nUsed; + pParse->bJsonIsRCStr = 1; + rc = jsonCacheInsert(ctx, pParse); + if( rc==SQLITE_NOMEM ){ + sqlite3_result_error_nomem(ctx); + jsonStringReset(p); + return; + } + } + sqlite3_result_text64(p->pCtx, sqlite3RCStrRef(p->zBuf), p->nUsed, + sqlite3RCStrUnref, SQLITE_UTF8); + }else{ + sqlite3_result_error_nomem(p->pCtx); } - } - if( p->bErr==1 ){ + }else if( p->eErr & JSTRING_OOM ){ sqlite3_result_error_nomem(p->pCtx); + }else if( p->eErr & JSTRING_MALFORMED ){ + sqlite3_result_error(p->pCtx, "malformed JSON", -1); } - jsonReset(p); + jsonStringReset(p); } /************************************************************************** -** Utility routines for dealing with JsonNode and JsonParse objects +** Utility routines for dealing with JsonParse objects **************************************************************************/ -/* -** Return the number of consecutive JsonNode slots need to represent -** the parsed JSON at pNode. The minimum answer is 1. For ARRAY and -** OBJECT types, the number might be larger. -** -** Appended elements are not counted. The value returned is the number -** by which the JsonNode counter should increment in order to go to the -** next peer value. -*/ -static u32 jsonNodeSize(JsonNode *pNode){ - return pNode->eType>=JSON_ARRAY ? pNode->n+1 : 1; -} - /* ** Reclaim all memory allocated by a JsonParse object. But do not ** delete the JsonParse object itself. */ static void jsonParseReset(JsonParse *pParse){ - while( pParse->pClup ){ - JsonCleanup *pTask = pParse->pClup; - pParse->pClup = pTask->pJCNext; - pTask->xOp(pTask->pArg); - sqlite3_free(pTask); - } assert( pParse->nJPRef<=1 ); - if( pParse->aNode ){ - sqlite3_free(pParse->aNode); - pParse->aNode = 0; - } - pParse->nNode = 0; - pParse->nAlloc = 0; - if( pParse->aUp ){ - sqlite3_free(pParse->aUp); - pParse->aUp = 0; - } if( pParse->bJsonIsRCStr ){ sqlite3RCStrUnref(pParse->zJson); pParse->zJson = 0; + pParse->nJson = 0; pParse->bJsonIsRCStr = 0; } - if( pParse->zAlt ){ - sqlite3RCStrUnref(pParse->zAlt); - pParse->zAlt = 0; + if( pParse->nBlobAlloc ){ + sqlite3DbFree(pParse->db, pParse->aBlob); + pParse->aBlob = 0; + pParse->nBlob = 0; + pParse->nBlobAlloc = 0; } } /* -** Free a JsonParse object that was obtained from sqlite3_malloc(). -** -** Note that destroying JsonParse might call sqlite3RCStrUnref() to -** destroy the zJson value. The RCStr object might recursively invoke -** JsonParse to destroy this pParse object again. Take care to ensure -** that this recursive destructor sequence terminates harmlessly. +** Decrement the reference count on the JsonParse object. When the +** count reaches zero, free the object. */ static void jsonParseFree(JsonParse *pParse){ - if( pParse->nJPRef>1 ){ - pParse->nJPRef--; - }else{ - jsonParseReset(pParse); - sqlite3_free(pParse); - } -} - -/* -** Add a cleanup task to the JsonParse object. -** -** If an OOM occurs, the cleanup operation happens immediately -** and this function returns SQLITE_NOMEM. -*/ -static int jsonParseAddCleanup( - JsonParse *pParse, /* Add the cleanup task to this parser */ - void(*xOp)(void*), /* The cleanup task */ - void *pArg /* Argument to the cleanup */ -){ - JsonCleanup *pTask = sqlite3_malloc64( sizeof(*pTask) ); - if( pTask==0 ){ - pParse->oom = 1; - xOp(pArg); - return SQLITE_ERROR; - } - pTask->pJCNext = pParse->pClup; - pParse->pClup = pTask; - pTask->xOp = xOp; - pTask->pArg = pArg; - return SQLITE_OK; -} - -/* -** Convert the JsonNode pNode into a pure JSON string and -** append to pOut. Subsubstructure is also included. Return -** the number of JsonNode objects that are encoded. -*/ -static void jsonRenderNode( - JsonParse *pParse, /* the complete parse of the JSON */ - JsonNode *pNode, /* The node to render */ - JsonString *pOut /* Write JSON here */ -){ - assert( pNode!=0 ); - while( (pNode->jnFlags & JNODE_REPLACE)!=0 && pParse->useMod ){ - u32 idx = (u32)(pNode - pParse->aNode); - u32 i = pParse->iSubst; - while( 1 /*exit-by-break*/ ){ - assert( inNode ); - assert( pParse->aNode[i].eType==JSON_SUBST ); - assert( pParse->aNode[i].eU==4 ); - assert( pParse->aNode[i].u.iPrevaNode[i].n==idx ){ - pNode = &pParse->aNode[i+1]; - break; - } - i = pParse->aNode[i].u.iPrev; - } - } - switch( pNode->eType ){ - default: { - assert( pNode->eType==JSON_NULL ); - jsonAppendRawNZ(pOut, "null", 4); - break; - } - case JSON_TRUE: { - jsonAppendRawNZ(pOut, "true", 4); - break; - } - case JSON_FALSE: { - jsonAppendRawNZ(pOut, "false", 5); - break; - } - case JSON_STRING: { - assert( pNode->eU==1 ); - if( pNode->jnFlags & JNODE_RAW ){ - if( pNode->jnFlags & JNODE_LABEL ){ - jsonAppendChar(pOut, '"'); - jsonAppendRaw(pOut, pNode->u.zJContent, pNode->n); - jsonAppendChar(pOut, '"'); - }else{ - jsonAppendString(pOut, pNode->u.zJContent, pNode->n); - } - }else if( pNode->jnFlags & JNODE_JSON5 ){ - jsonAppendNormalizedString(pOut, pNode->u.zJContent, pNode->n); - }else{ - assert( pNode->n>0 ); - jsonAppendRawNZ(pOut, pNode->u.zJContent, pNode->n); - } - break; - } - case JSON_REAL: { - assert( pNode->eU==1 ); - if( pNode->jnFlags & JNODE_JSON5 ){ - jsonAppendNormalizedReal(pOut, pNode->u.zJContent, pNode->n); - }else{ - assert( pNode->n>0 ); - jsonAppendRawNZ(pOut, pNode->u.zJContent, pNode->n); - } - break; - } - case JSON_INT: { - assert( pNode->eU==1 ); - if( pNode->jnFlags & JNODE_JSON5 ){ - jsonAppendNormalizedInt(pOut, pNode->u.zJContent, pNode->n); - }else{ - assert( pNode->n>0 ); - jsonAppendRawNZ(pOut, pNode->u.zJContent, pNode->n); - } - break; - } - case JSON_ARRAY: { - u32 j = 1; - jsonAppendChar(pOut, '['); - for(;;){ - while( j<=pNode->n ){ - if( (pNode[j].jnFlags & JNODE_REMOVE)==0 || pParse->useMod==0 ){ - jsonAppendSeparator(pOut); - jsonRenderNode(pParse, &pNode[j], pOut); - } - j += jsonNodeSize(&pNode[j]); - } - if( (pNode->jnFlags & JNODE_APPEND)==0 ) break; - if( pParse->useMod==0 ) break; - assert( pNode->eU==2 ); - pNode = &pParse->aNode[pNode->u.iAppend]; - j = 1; - } - jsonAppendChar(pOut, ']'); - break; - } - case JSON_OBJECT: { - u32 j = 1; - jsonAppendChar(pOut, '{'); - for(;;){ - while( j<=pNode->n ){ - if( (pNode[j+1].jnFlags & JNODE_REMOVE)==0 || pParse->useMod==0 ){ - jsonAppendSeparator(pOut); - jsonRenderNode(pParse, &pNode[j], pOut); - jsonAppendChar(pOut, ':'); - jsonRenderNode(pParse, &pNode[j+1], pOut); - } - j += 1 + jsonNodeSize(&pNode[j+1]); - } - if( (pNode->jnFlags & JNODE_APPEND)==0 ) break; - if( pParse->useMod==0 ) break; - assert( pNode->eU==2 ); - pNode = &pParse->aNode[pNode->u.iAppend]; - j = 1; - } - jsonAppendChar(pOut, '}'); - break; + if( pParse ){ + if( pParse->nJPRef>1 ){ + pParse->nJPRef--; + }else{ + jsonParseReset(pParse); + sqlite3DbFree(pParse->db, pParse); } } } -/* -** Return a JsonNode and all its descendants as a JSON string. -*/ -static void jsonReturnJson( - JsonParse *pParse, /* The complete JSON */ - JsonNode *pNode, /* Node to return */ - sqlite3_context *pCtx, /* Return value for this function */ - int bGenerateAlt /* Also store the rendered text in zAlt */ -){ - JsonString s; - if( pParse->oom ){ - sqlite3_result_error_nomem(pCtx); - return; - } - if( pParse->nErr==0 ){ - jsonInit(&s, pCtx); - jsonRenderNode(pParse, pNode, &s); - if( bGenerateAlt && pParse->zAlt==0 && jsonForceRCStr(&s) ){ - pParse->zAlt = sqlite3RCStrRef(s.zBuf); - pParse->nAlt = s.nUsed; - } - jsonResult(&s); - sqlite3_result_subtype(pCtx, JSON_SUBTYPE); - } -} +/************************************************************************** +** Utility routines for the JSON text parser +**************************************************************************/ /* ** Translate a single byte of Hex into an integer. -** This routine only works if h really is a valid hexadecimal -** character: 0..9a..fA..F +** This routine only gives a correct answer if h really is a valid hexadecimal +** character: 0..9a..fA..F. But unlike sqlite3HexToInt(), it does not +** assert() if the digit is not hex. */ static u8 jsonHexToInt(int h){ - assert( (h>='0' && h<='9') || (h>='a' && h<='f') || (h>='A' && h<='F') ); +#ifdef SQLITE_ASCII + h += 9*(1&(h>>6)); +#endif #ifdef SQLITE_EBCDIC h += 9*(1&~(h>>4)); -#else - h += 9*(1&(h>>6)); #endif return (u8)(h & 0xf); } @@ -202106,10 +205755,6 @@ static u8 jsonHexToInt(int h){ */ static u32 jsonHexToInt4(const char *z){ u32 v; - assert( sqlite3Isxdigit(z[0]) ); - assert( sqlite3Isxdigit(z[1]) ); - assert( sqlite3Isxdigit(z[2]) ); - assert( sqlite3Isxdigit(z[3]) ); v = (jsonHexToInt(z[0])<<12) + (jsonHexToInt(z[1])<<8) + (jsonHexToInt(z[2])<<4) @@ -202117,281 +205762,6 @@ static u32 jsonHexToInt4(const char *z){ return v; } -/* -** Make the JsonNode the return value of the function. -*/ -static void jsonReturn( - JsonParse *pParse, /* Complete JSON parse tree */ - JsonNode *pNode, /* Node to return */ - sqlite3_context *pCtx /* Return value for this function */ -){ - switch( pNode->eType ){ - default: { - assert( pNode->eType==JSON_NULL ); - sqlite3_result_null(pCtx); - break; - } - case JSON_TRUE: { - sqlite3_result_int(pCtx, 1); - break; - } - case JSON_FALSE: { - sqlite3_result_int(pCtx, 0); - break; - } - case JSON_INT: { - sqlite3_int64 i = 0; - int rc; - int bNeg = 0; - const char *z; - - assert( pNode->eU==1 ); - z = pNode->u.zJContent; - if( z[0]=='-' ){ z++; bNeg = 1; } - else if( z[0]=='+' ){ z++; } - rc = sqlite3DecOrHexToI64(z, &i); - if( rc<=1 ){ - sqlite3_result_int64(pCtx, bNeg ? -i : i); - }else if( rc==3 && bNeg ){ - sqlite3_result_int64(pCtx, SMALLEST_INT64); - }else{ - goto to_double; - } - break; - } - case JSON_REAL: { - double r; - const char *z; - assert( pNode->eU==1 ); - to_double: - z = pNode->u.zJContent; - sqlite3AtoF(z, &r, sqlite3Strlen30(z), SQLITE_UTF8); - sqlite3_result_double(pCtx, r); - break; - } - case JSON_STRING: { - if( pNode->jnFlags & JNODE_RAW ){ - assert( pNode->eU==1 ); - sqlite3_result_text(pCtx, pNode->u.zJContent, pNode->n, - SQLITE_TRANSIENT); - }else if( (pNode->jnFlags & JNODE_ESCAPE)==0 ){ - /* JSON formatted without any backslash-escapes */ - assert( pNode->eU==1 ); - sqlite3_result_text(pCtx, pNode->u.zJContent+1, pNode->n-2, - SQLITE_TRANSIENT); - }else{ - /* Translate JSON formatted string into raw text */ - u32 i; - u32 n = pNode->n; - const char *z; - char *zOut; - u32 j; - u32 nOut = n; - assert( pNode->eU==1 ); - z = pNode->u.zJContent; - zOut = sqlite3_malloc( nOut+1 ); - if( zOut==0 ){ - sqlite3_result_error_nomem(pCtx); - break; - } - for(i=1, j=0; i>6)); - zOut[j++] = 0x80 | (v&0x3f); - }else{ - u32 vlo; - if( (v&0xfc00)==0xd800 - && i>18); - zOut[j++] = 0x80 | ((v>>12)&0x3f); - zOut[j++] = 0x80 | ((v>>6)&0x3f); - zOut[j++] = 0x80 | (v&0x3f); - }else{ - zOut[j++] = 0xe0 | (v>>12); - zOut[j++] = 0x80 | ((v>>6)&0x3f); - zOut[j++] = 0x80 | (v&0x3f); - } - } - continue; - }else if( c=='b' ){ - c = '\b'; - }else if( c=='f' ){ - c = '\f'; - }else if( c=='n' ){ - c = '\n'; - }else if( c=='r' ){ - c = '\r'; - }else if( c=='t' ){ - c = '\t'; - }else if( c=='v' ){ - c = '\v'; - }else if( c=='\'' || c=='"' || c=='/' || c=='\\' ){ - /* pass through unchanged */ - }else if( c=='0' ){ - c = 0; - }else if( c=='x' ){ - c = (jsonHexToInt(z[i+1])<<4) | jsonHexToInt(z[i+2]); - i += 2; - }else if( c=='\r' && z[i+1]=='\n' ){ - i++; - continue; - }else if( 0xe2==(u8)c ){ - assert( 0x80==(u8)z[i+1] ); - assert( 0xa8==(u8)z[i+2] || 0xa9==(u8)z[i+2] ); - i += 2; - continue; - }else{ - continue; - } - } /* end if( c=='\\' ) */ - zOut[j++] = c; - } /* end for() */ - zOut[j] = 0; - sqlite3_result_text(pCtx, zOut, j, sqlite3_free); - } - break; - } - case JSON_ARRAY: - case JSON_OBJECT: { - jsonReturnJson(pParse, pNode, pCtx, 0); - break; - } - } -} - -/* Forward reference */ -static int jsonParseAddNode(JsonParse*,u32,u32,const char*); - -/* -** A macro to hint to the compiler that a function should not be -** inlined. -*/ -#if defined(__GNUC__) -# define JSON_NOINLINE __attribute__((noinline)) -#elif defined(_MSC_VER) && _MSC_VER>=1310 -# define JSON_NOINLINE __declspec(noinline) -#else -# define JSON_NOINLINE -#endif - - -/* -** Add a single node to pParse->aNode after first expanding the -** size of the aNode array. Return the index of the new node. -** -** If an OOM error occurs, set pParse->oom and return -1. -*/ -static JSON_NOINLINE int jsonParseAddNodeExpand( - JsonParse *pParse, /* Append the node to this object */ - u32 eType, /* Node type */ - u32 n, /* Content size or sub-node count */ - const char *zContent /* Content */ -){ - u32 nNew; - JsonNode *pNew; - assert( pParse->nNode>=pParse->nAlloc ); - if( pParse->oom ) return -1; - nNew = pParse->nAlloc*2 + 10; - pNew = sqlite3_realloc64(pParse->aNode, sizeof(JsonNode)*nNew); - if( pNew==0 ){ - pParse->oom = 1; - return -1; - } - pParse->nAlloc = sqlite3_msize(pNew)/sizeof(JsonNode); - pParse->aNode = pNew; - assert( pParse->nNodenAlloc ); - return jsonParseAddNode(pParse, eType, n, zContent); -} - -/* -** Create a new JsonNode instance based on the arguments and append that -** instance to the JsonParse. Return the index in pParse->aNode[] of the -** new node, or -1 if a memory allocation fails. -*/ -static int jsonParseAddNode( - JsonParse *pParse, /* Append the node to this object */ - u32 eType, /* Node type */ - u32 n, /* Content size or sub-node count */ - const char *zContent /* Content */ -){ - JsonNode *p; - assert( pParse->aNode!=0 || pParse->nNode>=pParse->nAlloc ); - if( pParse->nNode>=pParse->nAlloc ){ - return jsonParseAddNodeExpand(pParse, eType, n, zContent); - } - assert( pParse->aNode!=0 ); - p = &pParse->aNode[pParse->nNode]; - assert( p!=0 ); - p->eType = (u8)(eType & 0xff); - p->jnFlags = (u8)(eType >> 8); - VVA( p->eU = zContent ? 1 : 0 ); - p->n = n; - p->u.zJContent = zContent; - return pParse->nNode++; -} - -/* -** Add an array of new nodes to the current pParse->aNode array. -** Return the index of the first node added. -** -** If an OOM error occurs, set pParse->oom. -*/ -static void jsonParseAddNodeArray( - JsonParse *pParse, /* Append the node to this object */ - JsonNode *aNode, /* Array of nodes to add */ - u32 nNode /* Number of elements in aNew */ -){ - assert( aNode!=0 ); - assert( nNode>=1 ); - if( pParse->nNode + nNode > pParse->nAlloc ){ - u32 nNew = pParse->nNode + nNode; - JsonNode *aNew = sqlite3_realloc64(pParse->aNode, nNew*sizeof(JsonNode)); - if( aNew==0 ){ - pParse->oom = 1; - return; - } - pParse->nAlloc = sqlite3_msize(aNew)/sizeof(JsonNode); - pParse->aNode = aNew; - } - memcpy(&pParse->aNode[pParse->nNode], aNode, nNode*sizeof(JsonNode)); - pParse->nNode += nNode; -} - -/* -** Add a new JSON_SUBST node. The node immediately following -** this new node will be the substitute content for iNode. -*/ -static int jsonParseAddSubstNode( - JsonParse *pParse, /* Add the JSON_SUBST here */ - u32 iNode /* References this node */ -){ - int idx = jsonParseAddNode(pParse, JSON_SUBST, iNode, 0); - if( pParse->oom ) return -1; - pParse->aNode[iNode].jnFlags |= JNODE_REPLACE; - pParse->aNode[idx].eU = 4; - pParse->aNode[idx].u.iPrev = pParse->iSubst; - pParse->iSubst = idx; - pParse->hasMod = 1; - pParse->useMod = 1; - return idx; -} - /* ** Return true if z[] begins with 2 (or more) hexadecimal digits */ @@ -202545,63 +205915,503 @@ static const struct NanInfName { char *zMatch; char *zRepl; } aNanInfName[] = { - { 'i', 'I', 3, JSON_REAL, 7, "inf", "9.0e999" }, - { 'i', 'I', 8, JSON_REAL, 7, "infinity", "9.0e999" }, - { 'n', 'N', 3, JSON_NULL, 4, "NaN", "null" }, - { 'q', 'Q', 4, JSON_NULL, 4, "QNaN", "null" }, - { 's', 'S', 4, JSON_NULL, 4, "SNaN", "null" }, + { 'i', 'I', 3, JSONB_FLOAT, 7, "inf", "9.0e999" }, + { 'i', 'I', 8, JSONB_FLOAT, 7, "infinity", "9.0e999" }, + { 'n', 'N', 3, JSONB_NULL, 4, "NaN", "null" }, + { 'q', 'Q', 4, JSONB_NULL, 4, "QNaN", "null" }, + { 's', 'S', 4, JSONB_NULL, 4, "SNaN", "null" }, }; + /* -** Parse a single JSON value which begins at pParse->zJson[i]. Return the -** index of the first character past the end of the value parsed. +** Report the wrong number of arguments for json_insert(), json_replace() +** or json_set(). +*/ +static void jsonWrongNumArgs( + sqlite3_context *pCtx, + const char *zFuncName +){ + char *zMsg = sqlite3_mprintf("json_%s() needs an odd number of arguments", + zFuncName); + sqlite3_result_error(pCtx, zMsg, -1); + sqlite3_free(zMsg); +} + +/**************************************************************************** +** Utility routines for dealing with the binary BLOB representation of JSON +****************************************************************************/ + +/* +** Expand pParse->aBlob so that it holds at least N bytes. ** -** Special return values: +** Return the number of errors. +*/ +static int jsonBlobExpand(JsonParse *pParse, u32 N){ + u8 *aNew; + u32 t; + assert( N>pParse->nBlobAlloc ); + if( pParse->nBlobAlloc==0 ){ + t = 100; + }else{ + t = pParse->nBlobAlloc*2; + } + if( tdb, pParse->aBlob, t); + if( aNew==0 ){ pParse->oom = 1; return 1; } + pParse->aBlob = aNew; + pParse->nBlobAlloc = t; + return 0; +} + +/* +** If pParse->aBlob is not previously editable (because it is taken +** from sqlite3_value_blob(), as indicated by the fact that +** pParse->nBlobAlloc==0 and pParse->nBlob>0) then make it editable +** by making a copy into space obtained from malloc. +** +** Return true on success. Return false on OOM. +*/ +static int jsonBlobMakeEditable(JsonParse *pParse, u32 nExtra){ + u8 *aOld; + u32 nSize; + assert( !pParse->bReadOnly ); + if( pParse->oom ) return 0; + if( pParse->nBlobAlloc>0 ) return 1; + aOld = pParse->aBlob; + nSize = pParse->nBlob + nExtra; + pParse->aBlob = 0; + if( jsonBlobExpand(pParse, nSize) ){ + return 0; + } + assert( pParse->nBlobAlloc >= pParse->nBlob + nExtra ); + memcpy(pParse->aBlob, aOld, pParse->nBlob); + return 1; +} + +/* Expand pParse->aBlob and append one bytes. +*/ +static SQLITE_NOINLINE void jsonBlobExpandAndAppendOneByte( + JsonParse *pParse, + u8 c +){ + jsonBlobExpand(pParse, pParse->nBlob+1); + if( pParse->oom==0 ){ + assert( pParse->nBlob+1<=pParse->nBlobAlloc ); + pParse->aBlob[pParse->nBlob++] = c; + } +} + +/* Append a single character. +*/ +static void jsonBlobAppendOneByte(JsonParse *pParse, u8 c){ + if( pParse->nBlob >= pParse->nBlobAlloc ){ + jsonBlobExpandAndAppendOneByte(pParse, c); + }else{ + pParse->aBlob[pParse->nBlob++] = c; + } +} + +/* Slow version of jsonBlobAppendNode() that first resizes the +** pParse->aBlob structure. +*/ +static void jsonBlobAppendNode(JsonParse*,u8,u32,const void*); +static SQLITE_NOINLINE void jsonBlobExpandAndAppendNode( + JsonParse *pParse, + u8 eType, + u32 szPayload, + const void *aPayload +){ + if( jsonBlobExpand(pParse, pParse->nBlob+szPayload+9) ) return; + jsonBlobAppendNode(pParse, eType, szPayload, aPayload); +} + + +/* Append an node type byte together with the payload size and +** possibly also the payload. +** +** If aPayload is not NULL, then it is a pointer to the payload which +** is also appended. If aPayload is NULL, the pParse->aBlob[] array +** is resized (if necessary) so that it is big enough to hold the +** payload, but the payload is not appended and pParse->nBlob is left +** pointing to where the first byte of payload will eventually be. +*/ +static void jsonBlobAppendNode( + JsonParse *pParse, /* The JsonParse object under construction */ + u8 eType, /* Node type. One of JSONB_* */ + u32 szPayload, /* Number of bytes of payload */ + const void *aPayload /* The payload. Might be NULL */ +){ + u8 *a; + if( pParse->nBlob+szPayload+9 > pParse->nBlobAlloc ){ + jsonBlobExpandAndAppendNode(pParse,eType,szPayload,aPayload); + return; + } + assert( pParse->aBlob!=0 ); + a = &pParse->aBlob[pParse->nBlob]; + if( szPayload<=11 ){ + a[0] = eType | (szPayload<<4); + pParse->nBlob += 1; + }else if( szPayload<=0xff ){ + a[0] = eType | 0xc0; + a[1] = szPayload & 0xff; + pParse->nBlob += 2; + }else if( szPayload<=0xffff ){ + a[0] = eType | 0xd0; + a[1] = (szPayload >> 8) & 0xff; + a[2] = szPayload & 0xff; + pParse->nBlob += 3; + }else{ + a[0] = eType | 0xe0; + a[1] = (szPayload >> 24) & 0xff; + a[2] = (szPayload >> 16) & 0xff; + a[3] = (szPayload >> 8) & 0xff; + a[4] = szPayload & 0xff; + pParse->nBlob += 5; + } + if( aPayload ){ + pParse->nBlob += szPayload; + memcpy(&pParse->aBlob[pParse->nBlob-szPayload], aPayload, szPayload); + } +} + +/* Change the payload size for the node at index i to be szPayload. +*/ +static int jsonBlobChangePayloadSize( + JsonParse *pParse, + u32 i, + u32 szPayload +){ + u8 *a; + u8 szType; + u8 nExtra; + u8 nNeeded; + int delta; + if( pParse->oom ) return 0; + a = &pParse->aBlob[i]; + szType = a[0]>>4; + if( szType<=11 ){ + nExtra = 0; + }else if( szType==12 ){ + nExtra = 1; + }else if( szType==13 ){ + nExtra = 2; + }else{ + nExtra = 4; + } + if( szPayload<=11 ){ + nNeeded = 0; + }else if( szPayload<=0xff ){ + nNeeded = 1; + }else if( szPayload<=0xffff ){ + nNeeded = 2; + }else{ + nNeeded = 4; + } + delta = nNeeded - nExtra; + if( delta ){ + u32 newSize = pParse->nBlob + delta; + if( delta>0 ){ + if( newSize>pParse->nBlobAlloc && jsonBlobExpand(pParse, newSize) ){ + return 0; /* OOM error. Error state recorded in pParse->oom. */ + } + a = &pParse->aBlob[i]; + memmove(&a[1+delta], &a[1], pParse->nBlob - (i+1)); + }else{ + memmove(&a[1], &a[1-delta], pParse->nBlob - (i+1-delta)); + } + pParse->nBlob = newSize; + } + if( nNeeded==0 ){ + a[0] = (a[0] & 0x0f) | (szPayload<<4); + }else if( nNeeded==1 ){ + a[0] = (a[0] & 0x0f) | 0xc0; + a[1] = szPayload & 0xff; + }else if( nNeeded==2 ){ + a[0] = (a[0] & 0x0f) | 0xd0; + a[1] = (szPayload >> 8) & 0xff; + a[2] = szPayload & 0xff; + }else{ + a[0] = (a[0] & 0x0f) | 0xe0; + a[1] = (szPayload >> 24) & 0xff; + a[2] = (szPayload >> 16) & 0xff; + a[3] = (szPayload >> 8) & 0xff; + a[4] = szPayload & 0xff; + } + return delta; +} + +/* +** If z[0] is 'u' and is followed by exactly 4 hexadecimal character, +** then set *pOp to JSONB_TEXTJ and return true. If not, do not make +** any changes to *pOp and return false. +*/ +static int jsonIs4HexB(const char *z, int *pOp){ + if( z[0]!='u' ) return 0; + if( !jsonIs4Hex(&z[1]) ) return 0; + *pOp = JSONB_TEXTJ; + return 1; +} + +/* +** Check a single element of the JSONB in pParse for validity. +** +** The element to be checked starts at offset i and must end at on the +** last byte before iEnd. +** +** Return 0 if everything is correct. Return the 1-based byte offset of the +** error if a problem is detected. (In other words, if the error is at offset +** 0, return 1). +*/ +static u32 jsonbValidityCheck( + const JsonParse *pParse, /* Input JSONB. Only aBlob and nBlob are used */ + u32 i, /* Start of element as pParse->aBlob[i] */ + u32 iEnd, /* One more than the last byte of the element */ + u32 iDepth /* Current nesting depth */ +){ + u32 n, sz, j, k; + const u8 *z; + u8 x; + if( iDepth>JSON_MAX_DEPTH ) return i+1; + sz = 0; + n = jsonbPayloadSize(pParse, i, &sz); + if( NEVER(n==0) ) return i+1; /* Checked by caller */ + if( NEVER(i+n+sz!=iEnd) ) return i+1; /* Checked by caller */ + z = pParse->aBlob; + x = z[i] & 0x0f; + switch( x ){ + case JSONB_NULL: + case JSONB_TRUE: + case JSONB_FALSE: { + return n+sz==1 ? 0 : i+1; + } + case JSONB_INT: { + if( sz<1 ) return i+1; + j = i+n; + if( z[j]=='-' ){ + j++; + if( sz<2 ) return i+1; + } + k = i+n+sz; + while( jk ) return j+1; + if( z[j+1]!='.' && z[j+1]!='e' && z[j+1]!='E' ) return j+1; + j++; + } + for(; j0 ) return j+1; + if( x==JSONB_FLOAT && (j==k-1 || !sqlite3Isdigit(z[j+1])) ){ + return j+1; + } + seen = 1; + continue; + } + if( z[j]=='e' || z[j]=='E' ){ + if( seen==2 ) return j+1; + if( j==k-1 ) return j+1; + if( z[j+1]=='+' || z[j+1]=='-' ){ + j++; + if( j==k-1 ) return j+1; + } + seen = 2; + continue; + } + return j+1; + } + if( seen==0 ) return i+1; + return 0; + } + case JSONB_TEXT: { + j = i+n; + k = j+sz; + while( j=k ){ + return j+1; + }else if( strchr("\"\\/bfnrt",z[j+1])!=0 ){ + j++; + }else if( z[j+1]=='u' ){ + if( j+5>=k ) return j+1; + if( !jsonIs4Hex((const char*)&z[j+2]) ) return j+1; + j++; + }else if( x!=JSONB_TEXT5 ){ + return j+1; + }else{ + u32 c = 0; + u32 szC = jsonUnescapeOneChar((const char*)&z[j], k-j, &c); + if( c==JSON_INVALID_CHAR ) return j+1; + j += szC - 1; + } + } + j++; + } + return 0; + } + case JSONB_TEXTRAW: { + return 0; + } + case JSONB_ARRAY: { + u32 sub; + j = i+n; + k = j+sz; + while( jk ) return j+1; + sub = jsonbValidityCheck(pParse, j, j+n+sz, iDepth+1); + if( sub ) return sub; + j += n + sz; + } + assert( j==k ); + return 0; + } + case JSONB_OBJECT: { + u32 cnt = 0; + u32 sub; + j = i+n; + k = j+sz; + while( jk ) return j+1; + if( (cnt & 1)==0 ){ + x = z[j] & 0x0f; + if( xJSONB_TEXTRAW ) return j+1; + } + sub = jsonbValidityCheck(pParse, j, j+n+sz, iDepth+1); + if( sub ) return sub; + cnt++; + j += n + sz; + } + assert( j==k ); + if( (cnt & 1)!=0 ) return j+1; + return 0; + } + default: { + return i+1; + } + } +} + +/* +** Translate a single element of JSON text at pParse->zJson[i] into +** its equivalent binary JSONB representation. Append the translation into +** pParse->aBlob[] beginning at pParse->nBlob. The size of +** pParse->aBlob[] is increased as necessary. +** +** Return the index of the first character past the end of the element parsed, +** or one of the following special result codes: ** ** 0 End of input -** -1 Syntax error -** -2 '}' seen -** -3 ']' seen -** -4 ',' seen -** -5 ':' seen +** -1 Syntax error or OOM +** -2 '}' seen \ +** -3 ']' seen \___ For these returns, pParse->iErr is set to +** -4 ',' seen / the index in zJson[] of the seen character +** -5 ':' seen / */ -static int jsonParseValue(JsonParse *pParse, u32 i){ +static int jsonTranslateTextToBlob(JsonParse *pParse, u32 i){ char c; u32 j; - int iThis; + u32 iThis, iStart; int x; - JsonNode *pNode; + u8 t; const char *z = pParse->zJson; json_parse_restart: switch( (u8)z[i] ){ case '{': { /* Parse object */ - iThis = jsonParseAddNode(pParse, JSON_OBJECT, 0, 0); - if( iThis<0 ) return -1; + iThis = pParse->nBlob; + jsonBlobAppendNode(pParse, JSONB_OBJECT, pParse->nJson-i, 0); if( ++pParse->iDepth > JSON_MAX_DEPTH ){ pParse->iErr = i; return -1; } + iStart = pParse->nBlob; for(j=i+1;;j++){ - u32 nNode = pParse->nNode; - x = jsonParseValue(pParse, j); + u32 iBlob = pParse->nBlob; + x = jsonTranslateTextToBlob(pParse, j); if( x<=0 ){ + int op; if( x==(-2) ){ j = pParse->iErr; - if( pParse->nNode!=(u32)iThis+1 ) pParse->hasNonstd = 1; + if( pParse->nBlob!=(u32)iStart ) pParse->hasNonstd = 1; break; } j += json5Whitespace(&z[j]); + op = JSONB_TEXT; if( sqlite3JsonId1(z[j]) - || (z[j]=='\\' && z[j+1]=='u' && jsonIs4Hex(&z[j+2])) + || (z[j]=='\\' && jsonIs4HexB(&z[j+1], &op)) ){ int k = j+1; while( (sqlite3JsonId2(z[k]) && json5Whitespace(&z[k])==0) - || (z[k]=='\\' && z[k+1]=='u' && jsonIs4Hex(&z[k+2])) + || (z[k]=='\\' && jsonIs4HexB(&z[k+1], &op)) ){ k++; } - jsonParseAddNode(pParse, JSON_STRING | (JNODE_RAW<<8), k-j, &z[j]); + assert( iBlob==pParse->nBlob ); + jsonBlobAppendNode(pParse, op, k-j, &z[j]); pParse->hasNonstd = 1; x = k; }else{ @@ -202610,24 +206420,24 @@ static int jsonParseValue(JsonParse *pParse, u32 i){ } } if( pParse->oom ) return -1; - pNode = &pParse->aNode[nNode]; - if( pNode->eType!=JSON_STRING ){ + t = pParse->aBlob[iBlob] & 0x0f; + if( tJSONB_TEXTRAW ){ pParse->iErr = j; return -1; } - pNode->jnFlags |= JNODE_LABEL; j = x; if( z[j]==':' ){ j++; }else{ - if( fast_isspace(z[j]) ){ - do{ j++; }while( fast_isspace(z[j]) ); + if( jsonIsspace(z[j]) ){ + /* strspn() is not helpful here */ + do{ j++; }while( jsonIsspace(z[j]) ); if( z[j]==':' ){ j++; goto parse_object_value; } } - x = jsonParseValue(pParse, j); + x = jsonTranslateTextToBlob(pParse, j); if( x!=(-5) ){ if( x!=(-1) ) pParse->iErr = j; return -1; @@ -202635,7 +206445,7 @@ static int jsonParseValue(JsonParse *pParse, u32 i){ j = pParse->iErr+1; } parse_object_value: - x = jsonParseValue(pParse, j); + x = jsonTranslateTextToBlob(pParse, j); if( x<=0 ){ if( x!=(-1) ) pParse->iErr = j; return -1; @@ -202646,15 +206456,15 @@ static int jsonParseValue(JsonParse *pParse, u32 i){ }else if( z[j]=='}' ){ break; }else{ - if( fast_isspace(z[j]) ){ - do{ j++; }while( fast_isspace(z[j]) ); + if( jsonIsspace(z[j]) ){ + j += 1 + (u32)strspn(&z[j+1], jsonSpaces); if( z[j]==',' ){ continue; }else if( z[j]=='}' ){ break; } } - x = jsonParseValue(pParse, j); + x = jsonTranslateTextToBlob(pParse, j); if( x==(-4) ){ j = pParse->iErr; continue; @@ -202667,25 +206477,27 @@ static int jsonParseValue(JsonParse *pParse, u32 i){ pParse->iErr = j; return -1; } - pParse->aNode[iThis].n = pParse->nNode - (u32)iThis - 1; + jsonBlobChangePayloadSize(pParse, iThis, pParse->nBlob - iStart); pParse->iDepth--; return j+1; } case '[': { /* Parse array */ - iThis = jsonParseAddNode(pParse, JSON_ARRAY, 0, 0); - if( iThis<0 ) return -1; + iThis = pParse->nBlob; + assert( i<=(u32)pParse->nJson ); + jsonBlobAppendNode(pParse, JSONB_ARRAY, pParse->nJson - i, 0); + iStart = pParse->nBlob; + if( pParse->oom ) return -1; if( ++pParse->iDepth > JSON_MAX_DEPTH ){ pParse->iErr = i; return -1; } - memset(&pParse->aNode[iThis].u, 0, sizeof(pParse->aNode[iThis].u)); for(j=i+1;;j++){ - x = jsonParseValue(pParse, j); + x = jsonTranslateTextToBlob(pParse, j); if( x<=0 ){ if( x==(-3) ){ j = pParse->iErr; - if( pParse->nNode!=(u32)iThis+1 ) pParse->hasNonstd = 1; + if( pParse->nBlob!=iStart ) pParse->hasNonstd = 1; break; } if( x!=(-1) ) pParse->iErr = j; @@ -202697,15 +206509,15 @@ static int jsonParseValue(JsonParse *pParse, u32 i){ }else if( z[j]==']' ){ break; }else{ - if( fast_isspace(z[j]) ){ - do{ j++; }while( fast_isspace(z[j]) ); + if( jsonIsspace(z[j]) ){ + j += 1 + (u32)strspn(&z[j+1], jsonSpaces); if( z[j]==',' ){ continue; }else if( z[j]==']' ){ break; } } - x = jsonParseValue(pParse, j); + x = jsonTranslateTextToBlob(pParse, j); if( x==(-4) ){ j = pParse->iErr; continue; @@ -202718,23 +206530,33 @@ static int jsonParseValue(JsonParse *pParse, u32 i){ pParse->iErr = j; return -1; } - pParse->aNode[iThis].n = pParse->nNode - (u32)iThis - 1; + jsonBlobChangePayloadSize(pParse, iThis, pParse->nBlob - iStart); pParse->iDepth--; return j+1; } case '\'': { - u8 jnFlags; + u8 opcode; char cDelim; pParse->hasNonstd = 1; - jnFlags = JNODE_JSON5; + opcode = JSONB_TEXT; goto parse_string; case '"': /* Parse string */ - jnFlags = 0; + opcode = JSONB_TEXT; parse_string: cDelim = z[i]; - for(j=i+1; 1; j++){ - if( jsonIsOk[(unsigned char)z[j]] ) continue; + j = i+1; + while( 1 /*exit-by-break*/ ){ + if( jsonIsOk[(u8)z[j]] ){ + if( !jsonIsOk[(u8)z[j+1]] ){ + j += 1; + }else if( !jsonIsOk[(u8)z[j+2]] ){ + j += 2; + }else{ + j += 3; + continue; + } + } c = z[j]; if( c==cDelim ){ break; @@ -202743,33 +206565,41 @@ static int jsonParseValue(JsonParse *pParse, u32 i){ if( c=='"' || c=='\\' || c=='/' || c=='b' || c=='f' || c=='n' || c=='r' || c=='t' || (c=='u' && jsonIs4Hex(&z[j+1])) ){ - jnFlags |= JNODE_ESCAPE; + if( opcode==JSONB_TEXT ) opcode = JSONB_TEXTJ; }else if( c=='\'' || c=='0' || c=='v' || c=='\n' || (0xe2==(u8)c && 0x80==(u8)z[j+1] && (0xa8==(u8)z[j+2] || 0xa9==(u8)z[j+2])) || (c=='x' && jsonIs2Hex(&z[j+1])) ){ - jnFlags |= (JNODE_ESCAPE|JNODE_JSON5); + opcode = JSONB_TEXT5; pParse->hasNonstd = 1; }else if( c=='\r' ){ if( z[j+1]=='\n' ) j++; - jnFlags |= (JNODE_ESCAPE|JNODE_JSON5); + opcode = JSONB_TEXT5; pParse->hasNonstd = 1; }else{ pParse->iErr = j; return -1; } }else if( c<=0x1f ){ - /* Control characters are not allowed in strings */ - pParse->iErr = j; - return -1; + if( c==0 ){ + pParse->iErr = j; + return -1; + } + /* Control characters are not allowed in canonical JSON string + ** literals, but are allowed in JSON5 string literals. */ + opcode = JSONB_TEXT5; + pParse->hasNonstd = 1; + }else if( c=='"' ){ + opcode = JSONB_TEXT5; } + j++; } - jsonParseAddNode(pParse, JSON_STRING | (jnFlags<<8), j+1-i, &z[i]); + jsonBlobAppendNode(pParse, opcode, j-1-i, &z[i+1]); return j+1; } case 't': { if( strncmp(z+i,"true",4)==0 && !sqlite3Isalnum(z[i+4]) ){ - jsonParseAddNode(pParse, JSON_TRUE, 0, 0); + jsonBlobAppendOneByte(pParse, JSONB_TRUE); return i+4; } pParse->iErr = i; @@ -202777,23 +206607,22 @@ static int jsonParseValue(JsonParse *pParse, u32 i){ } case 'f': { if( strncmp(z+i,"false",5)==0 && !sqlite3Isalnum(z[i+5]) ){ - jsonParseAddNode(pParse, JSON_FALSE, 0, 0); + jsonBlobAppendOneByte(pParse, JSONB_FALSE); return i+5; } pParse->iErr = i; return -1; } case '+': { - u8 seenDP, seenE, jnFlags; + u8 seenE; pParse->hasNonstd = 1; - jnFlags = JNODE_JSON5; + t = 0x00; /* Bit 0x01: JSON5. Bit 0x02: FLOAT */ goto parse_number; case '.': if( sqlite3Isdigit(z[i+1]) ){ pParse->hasNonstd = 1; - jnFlags = JNODE_JSON5; + t = 0x03; /* Bit 0x01: JSON5. Bit 0x02: FLOAT */ seenE = 0; - seenDP = JSON_REAL; goto parse_number_2; } pParse->iErr = i; @@ -202810,9 +206639,8 @@ static int jsonParseValue(JsonParse *pParse, u32 i){ case '8': case '9': /* Parse number */ - jnFlags = 0; + t = 0x00; /* Bit 0x01: JSON5. Bit 0x02: FLOAT */ parse_number: - seenDP = JSON_INT; seenE = 0; assert( '-' < '0' ); assert( '+' < '0' ); @@ -202822,9 +206650,9 @@ static int jsonParseValue(JsonParse *pParse, u32 i){ if( c<='0' ){ if( c=='0' ){ if( (z[i+1]=='x' || z[i+1]=='X') && sqlite3Isxdigit(z[i+2]) ){ - assert( seenDP==JSON_INT ); + assert( t==0x00 ); pParse->hasNonstd = 1; - jnFlags |= JNODE_JSON5; + t = 0x01; for(j=i+3; sqlite3Isxdigit(z[j]); j++){} goto parse_number_finish; }else if( sqlite3Isdigit(z[i+1]) ){ @@ -202841,15 +206669,15 @@ static int jsonParseValue(JsonParse *pParse, u32 i){ ){ pParse->hasNonstd = 1; if( z[i]=='-' ){ - jsonParseAddNode(pParse, JSON_REAL, 8, "-9.0e999"); + jsonBlobAppendNode(pParse, JSONB_FLOAT, 6, "-9e999"); }else{ - jsonParseAddNode(pParse, JSON_REAL, 7, "9.0e999"); + jsonBlobAppendNode(pParse, JSONB_FLOAT, 5, "9e999"); } return i + (sqlite3StrNICmp(&z[i+4],"inity",5)==0 ? 9 : 4); } if( z[i+1]=='.' ){ pParse->hasNonstd = 1; - jnFlags |= JNODE_JSON5; + t |= 0x01; goto parse_number_2; } pParse->iErr = i; @@ -202861,30 +206689,31 @@ static int jsonParseValue(JsonParse *pParse, u32 i){ return -1; }else if( (z[i+2]=='x' || z[i+2]=='X') && sqlite3Isxdigit(z[i+3]) ){ pParse->hasNonstd = 1; - jnFlags |= JNODE_JSON5; + t |= 0x01; for(j=i+4; sqlite3Isxdigit(z[j]); j++){} goto parse_number_finish; } } } } + parse_number_2: for(j=i+1;; j++){ c = z[j]; if( sqlite3Isdigit(c) ) continue; if( c=='.' ){ - if( seenDP==JSON_REAL ){ + if( (t & 0x02)!=0 ){ pParse->iErr = j; return -1; } - seenDP = JSON_REAL; + t |= 0x02; continue; } if( c=='e' || c=='E' ){ if( z[j-1]<'0' ){ if( ALWAYS(z[j-1]=='.') && ALWAYS(j-2>=i) && sqlite3Isdigit(z[j-2]) ){ pParse->hasNonstd = 1; - jnFlags |= JNODE_JSON5; + t |= 0x01; }else{ pParse->iErr = j; return -1; @@ -202894,7 +206723,7 @@ static int jsonParseValue(JsonParse *pParse, u32 i){ pParse->iErr = j; return -1; } - seenDP = JSON_REAL; + t |= 0x02; seenE = 1; c = z[j+1]; if( c=='+' || c=='-' ){ @@ -202912,14 +206741,18 @@ static int jsonParseValue(JsonParse *pParse, u32 i){ if( z[j-1]<'0' ){ if( ALWAYS(z[j-1]=='.') && ALWAYS(j-2>=i) && sqlite3Isdigit(z[j-2]) ){ pParse->hasNonstd = 1; - jnFlags |= JNODE_JSON5; + t |= 0x01; }else{ pParse->iErr = j; return -1; } } parse_number_finish: - jsonParseAddNode(pParse, seenDP | (jnFlags<<8), j - i, &z[i]); + assert( JSONB_INT+0x01==JSONB_INT5 ); + assert( JSONB_FLOAT+0x01==JSONB_FLOAT5 ); + assert( JSONB_INT+0x02==JSONB_FLOAT ); + if( z[i]=='+' ) i++; + jsonBlobAppendNode(pParse, JSONB_INT+t, j-i, &z[i]); return j; } case '}': { @@ -202945,9 +206778,7 @@ static int jsonParseValue(JsonParse *pParse, u32 i){ case 0x0a: case 0x0d: case 0x20: { - do{ - i++; - }while( fast_isspace(z[i]) ); + i += 1 + (u32)strspn(&z[i+1], jsonSpaces); goto json_parse_restart; } case 0x0b: @@ -202969,10 +206800,11 @@ static int jsonParseValue(JsonParse *pParse, u32 i){ } case 'n': { if( strncmp(z+i,"null",4)==0 && !sqlite3Isalnum(z[i+4]) ){ - jsonParseAddNode(pParse, JSON_NULL, 0, 0); + jsonBlobAppendOneByte(pParse, JSONB_NULL); return i+4; } /* fall-through into the default case that checks for NaN */ + /* no break */ deliberate_fall_through } default: { u32 k; @@ -202985,8 +206817,11 @@ static int jsonParseValue(JsonParse *pParse, u32 i){ continue; } if( sqlite3Isalnum(z[i+nn]) ) continue; - jsonParseAddNode(pParse, aNanInfName[k].eType, - aNanInfName[k].nRepl, aNanInfName[k].zRepl); + if( aNanInfName[k].eType==JSONB_FLOAT ){ + jsonBlobAppendNode(pParse, JSONB_FLOAT, 5, "9e999"); + }else{ + jsonBlobAppendOneByte(pParse, JSONB_NULL); + } pParse->hasNonstd = 1; return i + nn; } @@ -202996,6 +206831,7 @@ static int jsonParseValue(JsonParse *pParse, u32 i){ } /* End switch(z[i]) */ } + /* ** Parse a complete JSON string. Return 0 on success or non-zero if there ** are any errors. If an error occurs, free all memory held by pParse, @@ -203004,20 +206840,26 @@ static int jsonParseValue(JsonParse *pParse, u32 i){ ** pParse must be initialized to an empty parse object prior to calling ** this routine. */ -static int jsonParse( +static int jsonConvertTextToBlob( JsonParse *pParse, /* Initialize and fill this JsonParse object */ sqlite3_context *pCtx /* Report errors here */ ){ int i; const char *zJson = pParse->zJson; - i = jsonParseValue(pParse, 0); + i = jsonTranslateTextToBlob(pParse, 0); if( pParse->oom ) i = -1; if( i>0 ){ +#ifdef SQLITE_DEBUG assert( pParse->iDepth==0 ); - while( fast_isspace(zJson[i]) ) i++; + if( sqlite3Config.bJsonSelfcheck ){ + assert( jsonbValidityCheck(pParse, 0, pParse->nBlob, 0)==0 ); + } +#endif + while( jsonIsspace(zJson[i]) ) i++; if( zJson[i] ){ i += json5Whitespace(&zJson[i]); if( zJson[i] ){ + if( pCtx ) sqlite3_result_error(pCtx, "malformed JSON", -1); jsonParseReset(pParse); return 1; } @@ -203038,248 +206880,832 @@ static int jsonParse( return 0; } +/* +** The input string pStr is a well-formed JSON text string. Convert +** this into the JSONB format and make it the return value of the +** SQL function. +*/ +static void jsonReturnStringAsBlob(JsonString *pStr){ + JsonParse px; + memset(&px, 0, sizeof(px)); + jsonStringTerminate(pStr); + if( pStr->eErr ){ + sqlite3_result_error_nomem(pStr->pCtx); + return; + } + px.zJson = pStr->zBuf; + px.nJson = pStr->nUsed; + px.db = sqlite3_context_db_handle(pStr->pCtx); + (void)jsonTranslateTextToBlob(&px, 0); + if( px.oom ){ + sqlite3DbFree(px.db, px.aBlob); + sqlite3_result_error_nomem(pStr->pCtx); + }else{ + assert( px.nBlobAlloc>0 ); + assert( !px.bReadOnly ); + sqlite3_result_blob(pStr->pCtx, px.aBlob, px.nBlob, SQLITE_DYNAMIC); + } +} -/* Mark node i of pParse as being a child of iParent. Call recursively -** to fill in all the descendants of node i. +/* The byte at index i is a node type-code. This routine +** determines the payload size for that node and writes that +** payload size in to *pSz. It returns the offset from i to the +** beginning of the payload. Return 0 on error. */ -static void jsonParseFillInParentage(JsonParse *pParse, u32 i, u32 iParent){ - JsonNode *pNode = &pParse->aNode[i]; - u32 j; - pParse->aUp[i] = iParent; - switch( pNode->eType ){ - case JSON_ARRAY: { - for(j=1; j<=pNode->n; j += jsonNodeSize(pNode+j)){ - jsonParseFillInParentage(pParse, i+j, i); +static u32 jsonbPayloadSize(const JsonParse *pParse, u32 i, u32 *pSz){ + u8 x; + u32 sz; + u32 n; + if( NEVER(i>pParse->nBlob) ){ + *pSz = 0; + return 0; + } + x = pParse->aBlob[i]>>4; + if( x<=11 ){ + sz = x; + n = 1; + }else if( x==12 ){ + if( i+1>=pParse->nBlob ){ + *pSz = 0; + return 0; + } + sz = pParse->aBlob[i+1]; + n = 2; + }else if( x==13 ){ + if( i+2>=pParse->nBlob ){ + *pSz = 0; + return 0; + } + sz = (pParse->aBlob[i+1]<<8) + pParse->aBlob[i+2]; + n = 3; + }else if( x==14 ){ + if( i+4>=pParse->nBlob ){ + *pSz = 0; + return 0; + } + sz = ((u32)pParse->aBlob[i+1]<<24) + (pParse->aBlob[i+2]<<16) + + (pParse->aBlob[i+3]<<8) + pParse->aBlob[i+4]; + n = 5; + }else{ + if( i+8>=pParse->nBlob + || pParse->aBlob[i+1]!=0 + || pParse->aBlob[i+2]!=0 + || pParse->aBlob[i+3]!=0 + || pParse->aBlob[i+4]!=0 + ){ + *pSz = 0; + return 0; + } + sz = (pParse->aBlob[i+5]<<24) + (pParse->aBlob[i+6]<<16) + + (pParse->aBlob[i+7]<<8) + pParse->aBlob[i+8]; + n = 9; + } + if( (i64)i+sz+n > pParse->nBlob + && (i64)i+sz+n > pParse->nBlob-pParse->delta + ){ + sz = 0; + n = 0; + } + *pSz = sz; + return n; +} + + +/* +** Translate the binary JSONB representation of JSON beginning at +** pParse->aBlob[i] into a JSON text string. Append the JSON +** text onto the end of pOut. Return the index in pParse->aBlob[] +** of the first byte past the end of the element that is translated. +** +** If an error is detected in the BLOB input, the pOut->eErr flag +** might get set to JSTRING_MALFORMED. But not all BLOB input errors +** are detected. So a malformed JSONB input might either result +** in an error, or in incorrect JSON. +** +** The pOut->eErr JSTRING_OOM flag is set on a OOM. +*/ +static u32 jsonTranslateBlobToText( + const JsonParse *pParse, /* the complete parse of the JSON */ + u32 i, /* Start rendering at this index */ + JsonString *pOut /* Write JSON here */ +){ + u32 sz, n, j, iEnd; + + n = jsonbPayloadSize(pParse, i, &sz); + if( n==0 ){ + pOut->eErr |= JSTRING_MALFORMED; + return pParse->nBlob+1; + } + switch( pParse->aBlob[i] & 0x0f ){ + case JSONB_NULL: { + jsonAppendRawNZ(pOut, "null", 4); + return i+1; + } + case JSONB_TRUE: { + jsonAppendRawNZ(pOut, "true", 4); + return i+1; + } + case JSONB_FALSE: { + jsonAppendRawNZ(pOut, "false", 5); + return i+1; + } + case JSONB_INT: + case JSONB_FLOAT: { + if( sz==0 ) goto malformed_jsonb; + jsonAppendRaw(pOut, (const char*)&pParse->aBlob[i+n], sz); + break; + } + case JSONB_INT5: { /* Integer literal in hexadecimal notation */ + u32 k = 2; + sqlite3_uint64 u = 0; + const char *zIn = (const char*)&pParse->aBlob[i+n]; + int bOverflow = 0; + if( sz==0 ) goto malformed_jsonb; + if( zIn[0]=='-' ){ + jsonAppendChar(pOut, '-'); + k++; + }else if( zIn[0]=='+' ){ + k++; + } + for(; keErr |= JSTRING_MALFORMED; + break; + }else if( (u>>60)!=0 ){ + bOverflow = 1; + }else{ + u = u*16 + sqlite3HexToInt(zIn[k]); + } } + jsonPrintf(100,pOut,bOverflow?"9.0e999":"%llu", u); break; } - case JSON_OBJECT: { - for(j=1; j<=pNode->n; j += jsonNodeSize(pNode+j+1)+1){ - pParse->aUp[i+j] = i; - jsonParseFillInParentage(pParse, i+j+1, i); + case JSONB_FLOAT5: { /* Float literal missing digits beside "." */ + u32 k = 0; + const char *zIn = (const char*)&pParse->aBlob[i+n]; + if( sz==0 ) goto malformed_jsonb; + if( zIn[0]=='-' ){ + jsonAppendChar(pOut, '-'); + k++; + } + if( zIn[k]=='.' ){ + jsonAppendChar(pOut, '0'); + } + for(; kaBlob[i+n], sz); + jsonAppendChar(pOut, '"'); + break; + } + case JSONB_TEXT5: { + const char *zIn; + u32 k; + u32 sz2 = sz; + zIn = (const char*)&pParse->aBlob[i+n]; + jsonAppendChar(pOut, '"'); + while( sz2>0 ){ + for(k=0; k0 ){ + jsonAppendRawNZ(pOut, zIn, k); + if( k>=sz2 ){ + break; + } + zIn += k; + sz2 -= k; + } + if( zIn[0]=='"' ){ + jsonAppendRawNZ(pOut, "\\\"", 2); + zIn++; + sz2--; + continue; + } + if( zIn[0]<=0x1f ){ + if( pOut->nUsed+7>pOut->nAlloc && jsonStringGrow(pOut,7) ) break; + jsonAppendControlChar(pOut, zIn[0]); + zIn++; + sz2--; + continue; + } + assert( zIn[0]=='\\' ); + assert( sz2>=1 ); + if( sz2<2 ){ + pOut->eErr |= JSTRING_MALFORMED; + break; + } + switch( (u8)zIn[1] ){ + case '\'': + jsonAppendChar(pOut, '\''); + break; + case 'v': + jsonAppendRawNZ(pOut, "\\u0009", 6); + break; + case 'x': + if( sz2<4 ){ + pOut->eErr |= JSTRING_MALFORMED; + sz2 = 2; + break; + } + jsonAppendRawNZ(pOut, "\\u00", 4); + jsonAppendRawNZ(pOut, &zIn[2], 2); + zIn += 2; + sz2 -= 2; + break; + case '0': + jsonAppendRawNZ(pOut, "\\u0000", 6); + break; + case '\r': + if( sz2>2 && zIn[2]=='\n' ){ + zIn++; + sz2--; + } + break; + case '\n': + break; + case 0xe2: + /* '\' followed by either U+2028 or U+2029 is ignored as + ** whitespace. Not that in UTF8, U+2028 is 0xe2 0x80 0x29. + ** U+2029 is the same except for the last byte */ + if( sz2<4 + || 0x80!=(u8)zIn[2] + || (0xa8!=(u8)zIn[3] && 0xa9!=(u8)zIn[3]) + ){ + pOut->eErr |= JSTRING_MALFORMED; + sz2 = 2; + break; + } + zIn += 2; + sz2 -= 2; + break; + default: + jsonAppendRawNZ(pOut, zIn, 2); + break; + } + assert( sz2>=2 ); + zIn += 2; + sz2 -= 2; + } + jsonAppendChar(pOut, '"'); + break; + } + case JSONB_TEXTRAW: { + jsonAppendString(pOut, (const char*)&pParse->aBlob[i+n], sz); + break; + } + case JSONB_ARRAY: { + jsonAppendChar(pOut, '['); + j = i+n; + iEnd = j+sz; + while( jeErr==0 ){ + j = jsonTranslateBlobToText(pParse, j, pOut); + jsonAppendChar(pOut, ','); + } + if( j>iEnd ) pOut->eErr |= JSTRING_MALFORMED; + if( sz>0 ) jsonStringTrimOneChar(pOut); + jsonAppendChar(pOut, ']'); + break; + } + case JSONB_OBJECT: { + int x = 0; + jsonAppendChar(pOut, '{'); + j = i+n; + iEnd = j+sz; + while( jeErr==0 ){ + j = jsonTranslateBlobToText(pParse, j, pOut); + jsonAppendChar(pOut, (x++ & 1) ? ',' : ':'); + } + if( (x & 1)!=0 || j>iEnd ) pOut->eErr |= JSTRING_MALFORMED; + if( sz>0 ) jsonStringTrimOneChar(pOut); + jsonAppendChar(pOut, '}'); + break; + } + default: { + malformed_jsonb: + pOut->eErr |= JSTRING_MALFORMED; break; } } + return i+n+sz; +} + +/* Context for recursion of json_pretty() +*/ +typedef struct JsonPretty JsonPretty; +struct JsonPretty { + JsonParse *pParse; /* The BLOB being rendered */ + JsonString *pOut; /* Generate pretty output into this string */ + const char *zIndent; /* Use this text for indentation */ + u32 szIndent; /* Bytes in zIndent[] */ + u32 nIndent; /* Current level of indentation */ +}; + +/* Append indentation to the pretty JSON under construction */ +static void jsonPrettyIndent(JsonPretty *pPretty){ + u32 jj; + for(jj=0; jjnIndent; jj++){ + jsonAppendRaw(pPretty->pOut, pPretty->zIndent, pPretty->szIndent); + } } /* -** Compute the parentage of all nodes in a completed parse. +** Translate the binary JSONB representation of JSON beginning at +** pParse->aBlob[i] into a JSON text string. Append the JSON +** text onto the end of pOut. Return the index in pParse->aBlob[] +** of the first byte past the end of the element that is translated. +** +** This is a variant of jsonTranslateBlobToText() that "pretty-prints" +** the output. Extra whitespace is inserted to make the JSON easier +** for humans to read. +** +** If an error is detected in the BLOB input, the pOut->eErr flag +** might get set to JSTRING_MALFORMED. But not all BLOB input errors +** are detected. So a malformed JSONB input might either result +** in an error, or in incorrect JSON. +** +** The pOut->eErr JSTRING_OOM flag is set on a OOM. */ -static int jsonParseFindParents(JsonParse *pParse){ - u32 *aUp; - assert( pParse->aUp==0 ); - aUp = pParse->aUp = sqlite3_malloc64( sizeof(u32)*pParse->nNode ); - if( aUp==0 ){ - pParse->oom = 1; - return SQLITE_NOMEM; +static u32 jsonTranslateBlobToPrettyText( + JsonPretty *pPretty, /* Pretty-printing context */ + u32 i /* Start rendering at this index */ +){ + u32 sz, n, j, iEnd; + const JsonParse *pParse = pPretty->pParse; + JsonString *pOut = pPretty->pOut; + n = jsonbPayloadSize(pParse, i, &sz); + if( n==0 ){ + pOut->eErr |= JSTRING_MALFORMED; + return pParse->nBlob+1; } - jsonParseFillInParentage(pParse, 0, 0); - return SQLITE_OK; + switch( pParse->aBlob[i] & 0x0f ){ + case JSONB_ARRAY: { + j = i+n; + iEnd = j+sz; + jsonAppendChar(pOut, '['); + if( jnIndent++; + while( pOut->eErr==0 ){ + jsonPrettyIndent(pPretty); + j = jsonTranslateBlobToPrettyText(pPretty, j); + if( j>=iEnd ) break; + jsonAppendRawNZ(pOut, ",\n", 2); + } + jsonAppendChar(pOut, '\n'); + pPretty->nIndent--; + jsonPrettyIndent(pPretty); + } + jsonAppendChar(pOut, ']'); + i = iEnd; + break; + } + case JSONB_OBJECT: { + j = i+n; + iEnd = j+sz; + jsonAppendChar(pOut, '{'); + if( jnIndent++; + while( pOut->eErr==0 ){ + jsonPrettyIndent(pPretty); + j = jsonTranslateBlobToText(pParse, j, pOut); + if( j>iEnd ){ + pOut->eErr |= JSTRING_MALFORMED; + break; + } + jsonAppendRawNZ(pOut, ": ", 2); + j = jsonTranslateBlobToPrettyText(pPretty, j); + if( j>=iEnd ) break; + jsonAppendRawNZ(pOut, ",\n", 2); + } + jsonAppendChar(pOut, '\n'); + pPretty->nIndent--; + jsonPrettyIndent(pPretty); + } + jsonAppendChar(pOut, '}'); + i = iEnd; + break; + } + default: { + i = jsonTranslateBlobToText(pParse, i, pOut); + break; + } + } + return i; +} + + +/* Return true if the input pJson +** +** For performance reasons, this routine does not do a detailed check of the +** input BLOB to ensure that it is well-formed. Hence, false positives are +** possible. False negatives should never occur, however. +*/ +static int jsonFuncArgMightBeBinary(sqlite3_value *pJson){ + u32 sz, n; + const u8 *aBlob; + int nBlob; + JsonParse s; + if( sqlite3_value_type(pJson)!=SQLITE_BLOB ) return 0; + aBlob = sqlite3_value_blob(pJson); + nBlob = sqlite3_value_bytes(pJson); + if( nBlob<1 ) return 0; + if( NEVER(aBlob==0) || (aBlob[0] & 0x0f)>JSONB_OBJECT ) return 0; + memset(&s, 0, sizeof(s)); + s.aBlob = (u8*)aBlob; + s.nBlob = nBlob; + n = jsonbPayloadSize(&s, 0, &sz); + if( n==0 ) return 0; + if( sz+n!=(u32)nBlob ) return 0; + if( (aBlob[0] & 0x0f)<=JSONB_FALSE && sz>0 ) return 0; + return sz+n==(u32)nBlob; } /* -** Magic number used for the JSON parse cache in sqlite3_get_auxdata() +** Given that a JSONB_ARRAY object starts at offset i, return +** the number of entries in that array. */ -#define JSON_CACHE_ID (-429938) /* First cache entry */ -#define JSON_CACHE_SZ 4 /* Max number of cache entries */ +static u32 jsonbArrayCount(JsonParse *pParse, u32 iRoot){ + u32 n, sz, i, iEnd; + u32 k = 0; + n = jsonbPayloadSize(pParse, iRoot, &sz); + iEnd = iRoot+n+sz; + for(i=iRoot+n; n>0 && idelta. +*/ +static void jsonAfterEditSizeAdjust(JsonParse *pParse, u32 iRoot){ + u32 sz = 0; + u32 nBlob; + assert( pParse->delta!=0 ); + assert( pParse->nBlobAlloc >= pParse->nBlob ); + nBlob = pParse->nBlob; + pParse->nBlob = pParse->nBlobAlloc; + (void)jsonbPayloadSize(pParse, iRoot, &sz); + pParse->nBlob = nBlob; + sz += pParse->delta; + pParse->delta += jsonBlobChangePayloadSize(pParse, iRoot, sz); +} + +/* +** Modify the JSONB blob at pParse->aBlob by removing nDel bytes of +** content beginning at iDel, and replacing them with nIns bytes of +** content given by aIns. ** -** Except, if an error occurs and pErrCtx==0 then return the JsonParse -** object with JsonParse.nErr non-zero and the caller will own the JsonParse -** object. In that case, it will be the responsibility of the caller to -** invoke jsonParseFree(). To summarize: +** nDel may be zero, in which case no bytes are removed. But iDel is +** still important as new bytes will be insert beginning at iDel. ** -** pErrCtx!=0 || p->nErr==0 ==> Return value p is owned by the -** cache. Call does not need to -** free it. +** aIns may be zero, in which case space is created to hold nIns bytes +** beginning at iDel, but that space is uninitialized. ** -** pErrCtx==0 && p->nErr!=0 ==> Return value is owned by the caller -** and so the caller must free it. +** Set pParse->oom if an OOM occurs. */ -static JsonParse *jsonParseCached( - sqlite3_context *pCtx, /* Context to use for cache search */ - sqlite3_value *pJson, /* Function param containing JSON text */ - sqlite3_context *pErrCtx, /* Write parse errors here if not NULL */ - int bUnedited /* No prior edits allowed */ +static void jsonBlobEdit( + JsonParse *pParse, /* The JSONB to be modified is in pParse->aBlob */ + u32 iDel, /* First byte to be removed */ + u32 nDel, /* Number of bytes to remove */ + const u8 *aIns, /* Content to insert */ + u32 nIns /* Bytes of content to insert */ ){ - char *zJson = (char*)sqlite3_value_text(pJson); - int nJson = sqlite3_value_bytes(pJson); - JsonParse *p; - JsonParse *pMatch = 0; - int iKey; - int iMinKey = 0; - u32 iMinHold = 0xffffffff; - u32 iMaxHold = 0; - int bJsonRCStr; + i64 d = (i64)nIns - (i64)nDel; + if( d!=0 ){ + if( pParse->nBlob + d > pParse->nBlobAlloc ){ + jsonBlobExpand(pParse, pParse->nBlob+d); + if( pParse->oom ) return; + } + memmove(&pParse->aBlob[iDel+nIns], + &pParse->aBlob[iDel+nDel], + pParse->nBlob - (iDel+nDel)); + pParse->nBlob += d; + pParse->delta += d; + } + if( nIns && aIns ) memcpy(&pParse->aBlob[iDel], aIns, nIns); +} - if( zJson==0 ) return 0; - for(iKey=0; iKeynJson==nJson - && (p->hasMod==0 || bUnedited==0) - && (p->zJson==zJson || memcmp(p->zJson,zJson,nJson)==0) - ){ - p->nErr = 0; - p->useMod = 0; - pMatch = p; - }else - if( pMatch==0 - && p->zAlt!=0 - && bUnedited==0 - && p->nAlt==nJson - && memcmp(p->zAlt, zJson, nJson)==0 - ){ - p->nErr = 0; - p->useMod = 1; - pMatch = p; - }else if( p->iHoldiHold; - iMinKey = iKey; + if( z[i+1]=='\r' ){ + if( i+2iHold>iMaxHold ){ - iMaxHold = p->iHold; + if( 0xe2==(u8)z[i+1] + && i+3nErr = 0; - pMatch->iHold = iMaxHold+1; - assert( pMatch->nJPRef>0 ); /* pMatch is owned by the cache */ - return pMatch; - } + return i; +} - /* The input JSON was not found anywhere in the cache. We will need - ** to parse it ourselves and generate a new JsonParse object. - */ - bJsonRCStr = sqlite3ValueIsOfClass(pJson,(void(*)(void*))sqlite3RCStrUnref); - p = sqlite3_malloc64( sizeof(*p) + (bJsonRCStr ? 0 : nJson+1) ); - if( p==0 ){ - sqlite3_result_error_nomem(pCtx); - return 0; +/* +** Input z[0..n] defines JSON escape sequence including the leading '\\'. +** Decode that escape sequence into a single character. Write that +** character into *piOut. Return the number of bytes in the escape sequence. +** +** If there is a syntax error of some kind (for example too few characters +** after the '\\' to complete the encoding) then *piOut is set to +** JSON_INVALID_CHAR. +*/ +static u32 jsonUnescapeOneChar(const char *z, u32 n, u32 *piOut){ + assert( n>0 ); + assert( z[0]=='\\' ); + if( n<2 ){ + *piOut = JSON_INVALID_CHAR; + return n; } - memset(p, 0, sizeof(*p)); - if( bJsonRCStr ){ - p->zJson = sqlite3RCStrRef(zJson); - p->bJsonIsRCStr = 1; - }else{ - p->zJson = (char*)&p[1]; - memcpy(p->zJson, zJson, nJson+1); + switch( (u8)z[1] ){ + case 'u': { + u32 v, vlo; + if( n<6 ){ + *piOut = JSON_INVALID_CHAR; + return n; + } + v = jsonHexToInt4(&z[2]); + if( (v & 0xfc00)==0xd800 + && n>=12 + && z[6]=='\\' + && z[7]=='u' + && ((vlo = jsonHexToInt4(&z[8]))&0xfc00)==0xdc00 + ){ + *piOut = ((v&0x3ff)<<10) + (vlo&0x3ff) + 0x10000; + return 12; + }else{ + *piOut = v; + return 6; + } + } + case 'b': { *piOut = '\b'; return 2; } + case 'f': { *piOut = '\f'; return 2; } + case 'n': { *piOut = '\n'; return 2; } + case 'r': { *piOut = '\r'; return 2; } + case 't': { *piOut = '\t'; return 2; } + case 'v': { *piOut = '\v'; return 2; } + case '0': { *piOut = 0; return 2; } + case '\'': + case '"': + case '/': + case '\\':{ *piOut = z[1]; return 2; } + case 'x': { + if( n<4 ){ + *piOut = JSON_INVALID_CHAR; + return n; + } + *piOut = (jsonHexToInt(z[2])<<4) | jsonHexToInt(z[3]); + return 4; + } + case 0xe2: + case '\r': + case '\n': { + u32 nSkip = jsonBytesToBypass(z, n); + if( nSkip==0 ){ + *piOut = JSON_INVALID_CHAR; + return n; + }else if( nSkip==n ){ + *piOut = 0; + return n; + }else if( z[nSkip]=='\\' ){ + return nSkip + jsonUnescapeOneChar(&z[nSkip], n-nSkip, piOut); + }else{ + int sz = sqlite3Utf8ReadLimited((u8*)&z[nSkip], n-nSkip, piOut); + return nSkip + sz; + } + } + default: { + *piOut = JSON_INVALID_CHAR; + return 2; + } } - p->nJPRef = 1; - if( jsonParse(p, pErrCtx) ){ - if( pErrCtx==0 ){ - p->nErr = 1; - assert( p->nJPRef==1 ); /* Caller will own the new JsonParse object p */ - return p; +} + + +/* +** Compare two object labels. Return 1 if they are equal and +** 0 if they differ. +** +** In this version, we know that one or the other or both of the +** two comparands contains an escape sequence. +*/ +static SQLITE_NOINLINE int jsonLabelCompareEscaped( + const char *zLeft, /* The left label */ + u32 nLeft, /* Size of the left label in bytes */ + int rawLeft, /* True if zLeft contains no escapes */ + const char *zRight, /* The right label */ + u32 nRight, /* Size of the right label in bytes */ + int rawRight /* True if zRight is escape-free */ +){ + u32 cLeft, cRight; + assert( rawLeft==0 || rawRight==0 ); + while( 1 /*exit-by-return*/ ){ + if( nLeft==0 ){ + cLeft = 0; + }else if( rawLeft || zLeft[0]!='\\' ){ + cLeft = ((u8*)zLeft)[0]; + if( cLeft>=0xc0 ){ + int sz = sqlite3Utf8ReadLimited((u8*)zLeft, nLeft, &cLeft); + zLeft += sz; + nLeft -= sz; + }else{ + zLeft++; + nLeft--; + } + }else{ + u32 n = jsonUnescapeOneChar(zLeft, nLeft, &cLeft); + zLeft += n; + assert( n<=nLeft ); + nLeft -= n; + } + if( nRight==0 ){ + cRight = 0; + }else if( rawRight || zRight[0]!='\\' ){ + cRight = ((u8*)zRight)[0]; + if( cRight>=0xc0 ){ + int sz = sqlite3Utf8ReadLimited((u8*)zRight, nRight, &cRight); + zRight += sz; + nRight -= sz; + }else{ + zRight++; + nRight--; + } + }else{ + u32 n = jsonUnescapeOneChar(zRight, nRight, &cRight); + zRight += n; + assert( n<=nRight ); + nRight -= n; } - jsonParseFree(p); - return 0; + if( cLeft!=cRight ) return 0; + if( cLeft==0 ) return 1; } - p->nJson = nJson; - p->iHold = iMaxHold+1; - /* Transfer ownership of the new JsonParse to the cache */ - sqlite3_set_auxdata(pCtx, JSON_CACHE_ID+iMinKey, p, - (void(*)(void*))jsonParseFree); - return (JsonParse*)sqlite3_get_auxdata(pCtx, JSON_CACHE_ID+iMinKey); } /* -** Compare the OBJECT label at pNode against zKey,nKey. Return true on -** a match. +** Compare two object labels. Return 1 if they are equal and +** 0 if they differ. Return -1 if an OOM occurs. */ -static int jsonLabelCompare(const JsonNode *pNode, const char *zKey, u32 nKey){ - assert( pNode->eU==1 ); - if( pNode->jnFlags & JNODE_RAW ){ - if( pNode->n!=nKey ) return 0; - return strncmp(pNode->u.zJContent, zKey, nKey)==0; +static int jsonLabelCompare( + const char *zLeft, /* The left label */ + u32 nLeft, /* Size of the left label in bytes */ + int rawLeft, /* True if zLeft contains no escapes */ + const char *zRight, /* The right label */ + u32 nRight, /* Size of the right label in bytes */ + int rawRight /* True if zRight is escape-free */ +){ + if( rawLeft && rawRight ){ + /* Simpliest case: Neither label contains escapes. A simple + ** memcmp() is sufficient. */ + if( nLeft!=nRight ) return 0; + return memcmp(zLeft, zRight, nLeft)==0; }else{ - if( pNode->n!=nKey+2 ) return 0; - return strncmp(pNode->u.zJContent+1, zKey, nKey)==0; + return jsonLabelCompareEscaped(zLeft, nLeft, rawLeft, + zRight, nRight, rawRight); } } -static int jsonSameLabel(const JsonNode *p1, const JsonNode *p2){ - if( p1->jnFlags & JNODE_RAW ){ - return jsonLabelCompare(p2, p1->u.zJContent, p1->n); - }else if( p2->jnFlags & JNODE_RAW ){ - return jsonLabelCompare(p1, p2->u.zJContent, p2->n); + +/* +** Error returns from jsonLookupStep() +*/ +#define JSON_LOOKUP_ERROR 0xffffffff +#define JSON_LOOKUP_NOTFOUND 0xfffffffe +#define JSON_LOOKUP_PATHERROR 0xfffffffd +#define JSON_LOOKUP_ISERROR(x) ((x)>=JSON_LOOKUP_PATHERROR) + +/* Forward declaration */ +static u32 jsonLookupStep(JsonParse*,u32,const char*,u32); + + +/* This helper routine for jsonLookupStep() populates pIns with +** binary data that is to be inserted into pParse. +** +** In the common case, pIns just points to pParse->aIns and pParse->nIns. +** But if the zPath of the original edit operation includes path elements +** that go deeper, additional substructure must be created. +** +** For example: +** +** json_insert('{}', '$.a.b.c', 123); +** +** The search stops at '$.a' But additional substructure must be +** created for the ".b.c" part of the patch so that the final result +** is: {"a":{"b":{"c"::123}}}. This routine populates pIns with +** the binary equivalent of {"b":{"c":123}} so that it can be inserted. +** +** The caller is responsible for resetting pIns when it has finished +** using the substructure. +*/ +static u32 jsonCreateEditSubstructure( + JsonParse *pParse, /* The original JSONB that is being edited */ + JsonParse *pIns, /* Populate this with the blob data to insert */ + const char *zTail /* Tail of the path that determins substructure */ +){ + static const u8 emptyObject[] = { JSONB_ARRAY, JSONB_OBJECT }; + int rc; + memset(pIns, 0, sizeof(*pIns)); + pIns->db = pParse->db; + if( zTail[0]==0 ){ + /* No substructure. Just insert what is given in pParse. */ + pIns->aBlob = pParse->aIns; + pIns->nBlob = pParse->nIns; + rc = 0; }else{ - return p1->n==p2->n && strncmp(p1->u.zJContent,p2->u.zJContent,p1->n)==0; + /* Construct the binary substructure */ + pIns->nBlob = 1; + pIns->aBlob = (u8*)&emptyObject[zTail[0]=='.']; + pIns->eEdit = pParse->eEdit; + pIns->nIns = pParse->nIns; + pIns->aIns = pParse->aIns; + rc = jsonLookupStep(pIns, 0, zTail, 0); + pParse->oom |= pIns->oom; } + return rc; /* Error code only */ } -/* forward declaration */ -static JsonNode *jsonLookupAppend(JsonParse*,const char*,int*,const char**); - /* -** Search along zPath to find the node specified. Return a pointer -** to that node, or NULL if zPath is malformed or if there is no such -** node. +** Search along zPath to find the Json element specified. Return an +** index into pParse->aBlob[] for the start of that element's value. ** -** If pApnd!=0, then try to append new nodes to complete zPath if it is -** possible to do so and if no existing node corresponds to zPath. If -** new nodes are appended *pApnd is set to 1. +** If the value found by this routine is the value half of label/value pair +** within an object, then set pPath->iLabel to the start of the corresponding +** label, before returning. +** +** Return one of the JSON_LOOKUP error codes if problems are seen. +** +** This routine will also modify the blob. If pParse->eEdit is one of +** JEDIT_DEL, JEDIT_REPL, JEDIT_INS, or JEDIT_SET, then changes might be +** made to the selected value. If an edit is performed, then the return +** value does not necessarily point to the select element. If an edit +** is performed, the return value is only useful for detecting error +** conditions. */ -static JsonNode *jsonLookupStep( +static u32 jsonLookupStep( JsonParse *pParse, /* The JSON to search */ - u32 iRoot, /* Begin the search at this node */ + u32 iRoot, /* Begin the search at this element of aBlob[] */ const char *zPath, /* The path to search */ - int *pApnd, /* Append nodes to complete path if not NULL */ - const char **pzErr /* Make *pzErr point to any syntax error in zPath */ + u32 iLabel /* Label if iRoot is a value of in an object */ ){ - u32 i, j, nKey; + u32 i, j, k, nKey, sz, n, iEnd, rc; const char *zKey; - JsonNode *pRoot; - if( pParse->oom ) return 0; - pRoot = &pParse->aNode[iRoot]; - if( pRoot->jnFlags & (JNODE_REPLACE|JNODE_REMOVE) && pParse->useMod ){ - while( (pRoot->jnFlags & JNODE_REPLACE)!=0 ){ - u32 idx = (u32)(pRoot - pParse->aNode); - i = pParse->iSubst; - while( 1 /*exit-by-break*/ ){ - assert( inNode ); - assert( pParse->aNode[i].eType==JSON_SUBST ); - assert( pParse->aNode[i].eU==4 ); - assert( pParse->aNode[i].u.iPrevaNode[i].n==idx ){ - pRoot = &pParse->aNode[i+1]; - iRoot = i+1; - break; - } - i = pParse->aNode[i].u.iPrev; + u8 x; + + if( zPath[0]==0 ){ + if( pParse->eEdit && jsonBlobMakeEditable(pParse, pParse->nIns) ){ + n = jsonbPayloadSize(pParse, iRoot, &sz); + sz += n; + if( pParse->eEdit==JEDIT_DEL ){ + if( iLabel>0 ){ + sz += iRoot - iLabel; + iRoot = iLabel; + } + jsonBlobEdit(pParse, iRoot, sz, 0, 0); + }else if( pParse->eEdit==JEDIT_INS ){ + /* Already exists, so json_insert() is a no-op */ + }else{ + /* json_set() or json_replace() */ + jsonBlobEdit(pParse, iRoot, sz, pParse->aIns, pParse->nIns); } } - if( pRoot->jnFlags & JNODE_REMOVE ){ - return 0; - } + pParse->iLabel = iLabel; + return iRoot; } - if( zPath[0]==0 ) return pRoot; if( zPath[0]=='.' ){ - if( pRoot->eType!=JSON_OBJECT ) return 0; + int rawKey = 1; + x = pParse->aBlob[iRoot]; zPath++; if( zPath[0]=='"' ){ zKey = zPath + 1; @@ -203288,250 +207714,705 @@ static JsonNode *jsonLookupStep( if( zPath[i] ){ i++; }else{ - *pzErr = zPath; - return 0; + return JSON_LOOKUP_PATHERROR; } testcase( nKey==0 ); + rawKey = memchr(zKey, '\\', nKey)==0; }else{ zKey = zPath; for(i=0; zPath[i] && zPath[i]!='.' && zPath[i]!='['; i++){} nKey = i; if( nKey==0 ){ - *pzErr = zPath; - return 0; - } - } - j = 1; - for(;;){ - while( j<=pRoot->n ){ - if( jsonLabelCompare(pRoot+j, zKey, nKey) ){ - return jsonLookupStep(pParse, iRoot+j+1, &zPath[i], pApnd, pzErr); - } - j++; - j += jsonNodeSize(&pRoot[j]); + return JSON_LOOKUP_PATHERROR; + } + } + if( (x & 0x0f)!=JSONB_OBJECT ) return JSON_LOOKUP_NOTFOUND; + n = jsonbPayloadSize(pParse, iRoot, &sz); + j = iRoot + n; /* j is the index of a label */ + iEnd = j+sz; + while( jaBlob[j] & 0x0f; + if( xJSONB_TEXTRAW ) return JSON_LOOKUP_ERROR; + n = jsonbPayloadSize(pParse, j, &sz); + if( n==0 ) return JSON_LOOKUP_ERROR; + k = j+n; /* k is the index of the label text */ + if( k+sz>=iEnd ) return JSON_LOOKUP_ERROR; + zLabel = (const char*)&pParse->aBlob[k]; + rawLabel = x==JSONB_TEXT || x==JSONB_TEXTRAW; + if( jsonLabelCompare(zKey, nKey, rawKey, zLabel, sz, rawLabel) ){ + u32 v = k+sz; /* v is the index of the value */ + if( ((pParse->aBlob[v])&0x0f)>JSONB_OBJECT ) return JSON_LOOKUP_ERROR; + n = jsonbPayloadSize(pParse, v, &sz); + if( n==0 || v+n+sz>iEnd ) return JSON_LOOKUP_ERROR; + assert( j>0 ); + rc = jsonLookupStep(pParse, v, &zPath[i], j); + if( pParse->delta ) jsonAfterEditSizeAdjust(pParse, iRoot); + return rc; } - if( (pRoot->jnFlags & JNODE_APPEND)==0 ) break; - if( pParse->useMod==0 ) break; - assert( pRoot->eU==2 ); - iRoot = pRoot->u.iAppend; - pRoot = &pParse->aNode[iRoot]; - j = 1; - } - if( pApnd ){ - u32 iStart, iLabel; - JsonNode *pNode; - assert( pParse->useMod ); - iStart = jsonParseAddNode(pParse, JSON_OBJECT, 2, 0); - iLabel = jsonParseAddNode(pParse, JSON_STRING, nKey, zKey); - zPath += i; - pNode = jsonLookupAppend(pParse, zPath, pApnd, pzErr); - if( pParse->oom ) return 0; - if( pNode ){ - pRoot = &pParse->aNode[iRoot]; - assert( pRoot->eU==0 ); - pRoot->u.iAppend = iStart; - pRoot->jnFlags |= JNODE_APPEND; - VVA( pRoot->eU = 2 ); - pParse->aNode[iLabel].jnFlags |= JNODE_RAW; - } - return pNode; + j = k+sz; + if( ((pParse->aBlob[j])&0x0f)>JSONB_OBJECT ) return JSON_LOOKUP_ERROR; + n = jsonbPayloadSize(pParse, j, &sz); + if( n==0 ) return JSON_LOOKUP_ERROR; + j += n+sz; + } + if( j>iEnd ) return JSON_LOOKUP_ERROR; + if( pParse->eEdit>=JEDIT_INS ){ + u32 nIns; /* Total bytes to insert (label+value) */ + JsonParse v; /* BLOB encoding of the value to be inserted */ + JsonParse ix; /* Header of the label to be inserted */ + testcase( pParse->eEdit==JEDIT_INS ); + testcase( pParse->eEdit==JEDIT_SET ); + memset(&ix, 0, sizeof(ix)); + ix.db = pParse->db; + jsonBlobAppendNode(&ix, rawKey?JSONB_TEXTRAW:JSONB_TEXT5, nKey, 0); + pParse->oom |= ix.oom; + rc = jsonCreateEditSubstructure(pParse, &v, &zPath[i]); + if( !JSON_LOOKUP_ISERROR(rc) + && jsonBlobMakeEditable(pParse, ix.nBlob+nKey+v.nBlob) + ){ + assert( !pParse->oom ); + nIns = ix.nBlob + nKey + v.nBlob; + jsonBlobEdit(pParse, j, 0, 0, nIns); + if( !pParse->oom ){ + assert( pParse->aBlob!=0 ); /* Because pParse->oom!=0 */ + assert( ix.aBlob!=0 ); /* Because pPasre->oom!=0 */ + memcpy(&pParse->aBlob[j], ix.aBlob, ix.nBlob); + k = j + ix.nBlob; + memcpy(&pParse->aBlob[k], zKey, nKey); + k += nKey; + memcpy(&pParse->aBlob[k], v.aBlob, v.nBlob); + if( ALWAYS(pParse->delta) ) jsonAfterEditSizeAdjust(pParse, iRoot); + } + } + jsonParseReset(&v); + jsonParseReset(&ix); + return rc; } }else if( zPath[0]=='[' ){ - i = 0; - j = 1; - while( sqlite3Isdigit(zPath[j]) ){ - i = i*10 + zPath[j] - '0'; - j++; + x = pParse->aBlob[iRoot] & 0x0f; + if( x!=JSONB_ARRAY ) return JSON_LOOKUP_NOTFOUND; + n = jsonbPayloadSize(pParse, iRoot, &sz); + k = 0; + i = 1; + while( sqlite3Isdigit(zPath[i]) ){ + k = k*10 + zPath[i] - '0'; + i++; } - if( j<2 || zPath[j]!=']' ){ + if( i<2 || zPath[i]!=']' ){ if( zPath[1]=='#' ){ - JsonNode *pBase = pRoot; - int iBase = iRoot; - if( pRoot->eType!=JSON_ARRAY ) return 0; - for(;;){ - while( j<=pBase->n ){ - if( (pBase[j].jnFlags & JNODE_REMOVE)==0 || pParse->useMod==0 ) i++; - j += jsonNodeSize(&pBase[j]); - } - if( (pBase->jnFlags & JNODE_APPEND)==0 ) break; - if( pParse->useMod==0 ) break; - assert( pBase->eU==2 ); - iBase = pBase->u.iAppend; - pBase = &pParse->aNode[iBase]; - j = 1; - } - j = 2; + k = jsonbArrayCount(pParse, iRoot); + i = 2; if( zPath[2]=='-' && sqlite3Isdigit(zPath[3]) ){ - unsigned int x = 0; - j = 3; + unsigned int nn = 0; + i = 3; do{ - x = x*10 + zPath[j] - '0'; - j++; - }while( sqlite3Isdigit(zPath[j]) ); - if( x>i ) return 0; - i -= x; + nn = nn*10 + zPath[i] - '0'; + i++; + }while( sqlite3Isdigit(zPath[i]) ); + if( nn>k ) return JSON_LOOKUP_NOTFOUND; + k -= nn; } - if( zPath[j]!=']' ){ - *pzErr = zPath; - return 0; + if( zPath[i]!=']' ){ + return JSON_LOOKUP_PATHERROR; } }else{ - *pzErr = zPath; - return 0; + return JSON_LOOKUP_PATHERROR; } } - if( pRoot->eType!=JSON_ARRAY ) return 0; - zPath += j + 1; - j = 1; - for(;;){ - while( j<=pRoot->n - && (i>0 || ((pRoot[j].jnFlags & JNODE_REMOVE)!=0 && pParse->useMod)) + j = iRoot+n; + iEnd = j+sz; + while( jdelta ) jsonAfterEditSizeAdjust(pParse, iRoot); + return rc; + } + k--; + n = jsonbPayloadSize(pParse, j, &sz); + if( n==0 ) return JSON_LOOKUP_ERROR; + j += n+sz; + } + if( j>iEnd ) return JSON_LOOKUP_ERROR; + if( k>0 ) return JSON_LOOKUP_NOTFOUND; + if( pParse->eEdit>=JEDIT_INS ){ + JsonParse v; + testcase( pParse->eEdit==JEDIT_INS ); + testcase( pParse->eEdit==JEDIT_SET ); + rc = jsonCreateEditSubstructure(pParse, &v, &zPath[i+1]); + if( !JSON_LOOKUP_ISERROR(rc) + && jsonBlobMakeEditable(pParse, v.nBlob) ){ - if( (pRoot[j].jnFlags & JNODE_REMOVE)==0 || pParse->useMod==0 ) i--; - j += jsonNodeSize(&pRoot[j]); - } - if( (pRoot->jnFlags & JNODE_APPEND)==0 ) break; - if( pParse->useMod==0 ) break; - assert( pRoot->eU==2 ); - iRoot = pRoot->u.iAppend; - pRoot = &pParse->aNode[iRoot]; - j = 1; - } - if( j<=pRoot->n ){ - return jsonLookupStep(pParse, iRoot+j, zPath, pApnd, pzErr); - } - if( i==0 && pApnd ){ - u32 iStart; - JsonNode *pNode; - assert( pParse->useMod ); - iStart = jsonParseAddNode(pParse, JSON_ARRAY, 1, 0); - pNode = jsonLookupAppend(pParse, zPath, pApnd, pzErr); - if( pParse->oom ) return 0; - if( pNode ){ - pRoot = &pParse->aNode[iRoot]; - assert( pRoot->eU==0 ); - pRoot->u.iAppend = iStart; - pRoot->jnFlags |= JNODE_APPEND; - VVA( pRoot->eU = 2 ); + assert( !pParse->oom ); + jsonBlobEdit(pParse, j, 0, v.aBlob, v.nBlob); } - return pNode; + jsonParseReset(&v); + if( pParse->delta ) jsonAfterEditSizeAdjust(pParse, iRoot); + return rc; } }else{ - *pzErr = zPath; + return JSON_LOOKUP_PATHERROR; } - return 0; + return JSON_LOOKUP_NOTFOUND; } /* -** Append content to pParse that will complete zPath. Return a pointer -** to the inserted node, or return NULL if the append fails. +** Convert a JSON BLOB into text and make that text the return value +** of an SQL function. */ -static JsonNode *jsonLookupAppend( - JsonParse *pParse, /* Append content to the JSON parse */ - const char *zPath, /* Description of content to append */ - int *pApnd, /* Set this flag to 1 */ - const char **pzErr /* Make this point to any syntax error */ +static void jsonReturnTextJsonFromBlob( + sqlite3_context *ctx, + const u8 *aBlob, + u32 nBlob ){ - *pApnd = 1; - if( zPath[0]==0 ){ - jsonParseAddNode(pParse, JSON_NULL, 0, 0); - return pParse->oom ? 0 : &pParse->aNode[pParse->nNode-1]; - } - if( zPath[0]=='.' ){ - jsonParseAddNode(pParse, JSON_OBJECT, 0, 0); - }else if( strncmp(zPath,"[0]",3)==0 ){ - jsonParseAddNode(pParse, JSON_ARRAY, 0, 0); - }else{ - return 0; - } - if( pParse->oom ) return 0; - return jsonLookupStep(pParse, pParse->nNode-1, zPath, pApnd, pzErr); + JsonParse x; + JsonString s; + + if( NEVER(aBlob==0) ) return; + memset(&x, 0, sizeof(x)); + x.aBlob = (u8*)aBlob; + x.nBlob = nBlob; + jsonStringInit(&s, ctx); + jsonTranslateBlobToText(&x, 0, &s); + jsonReturnString(&s, 0, 0); } + /* -** Return the text of a syntax error message on a JSON path. Space is -** obtained from sqlite3_malloc(). +** Return the value of the BLOB node at index i. +** +** If the value is a primitive, return it as an SQL value. +** If the value is an array or object, return it as either +** JSON text or the BLOB encoding, depending on the JSON_B flag +** on the userdata. */ -static char *jsonPathSyntaxError(const char *zErr){ - return sqlite3_mprintf("JSON path error near '%q'", zErr); +static void jsonReturnFromBlob( + JsonParse *pParse, /* Complete JSON parse tree */ + u32 i, /* Index of the node */ + sqlite3_context *pCtx, /* Return value for this function */ + int textOnly /* return text JSON. Disregard user-data */ +){ + u32 n, sz; + int rc; + sqlite3 *db = sqlite3_context_db_handle(pCtx); + + n = jsonbPayloadSize(pParse, i, &sz); + if( n==0 ){ + sqlite3_result_error(pCtx, "malformed JSON", -1); + return; + } + switch( pParse->aBlob[i] & 0x0f ){ + case JSONB_NULL: { + if( sz ) goto returnfromblob_malformed; + sqlite3_result_null(pCtx); + break; + } + case JSONB_TRUE: { + if( sz ) goto returnfromblob_malformed; + sqlite3_result_int(pCtx, 1); + break; + } + case JSONB_FALSE: { + if( sz ) goto returnfromblob_malformed; + sqlite3_result_int(pCtx, 0); + break; + } + case JSONB_INT5: + case JSONB_INT: { + sqlite3_int64 iRes = 0; + char *z; + int bNeg = 0; + char x; + if( sz==0 ) goto returnfromblob_malformed; + x = (char)pParse->aBlob[i+n]; + if( x=='-' ){ + if( sz<2 ) goto returnfromblob_malformed; + n++; + sz--; + bNeg = 1; + } + z = sqlite3DbStrNDup(db, (const char*)&pParse->aBlob[i+n], (int)sz); + if( z==0 ) goto returnfromblob_oom; + rc = sqlite3DecOrHexToI64(z, &iRes); + sqlite3DbFree(db, z); + if( rc==0 ){ + sqlite3_result_int64(pCtx, bNeg ? -iRes : iRes); + }else if( rc==3 && bNeg ){ + sqlite3_result_int64(pCtx, SMALLEST_INT64); + }else if( rc==1 ){ + goto returnfromblob_malformed; + }else{ + if( bNeg ){ n--; sz++; } + goto to_double; + } + break; + } + case JSONB_FLOAT5: + case JSONB_FLOAT: { + double r; + char *z; + if( sz==0 ) goto returnfromblob_malformed; + to_double: + z = sqlite3DbStrNDup(db, (const char*)&pParse->aBlob[i+n], (int)sz); + if( z==0 ) goto returnfromblob_oom; + rc = sqlite3AtoF(z, &r, sqlite3Strlen30(z), SQLITE_UTF8); + sqlite3DbFree(db, z); + if( rc<=0 ) goto returnfromblob_malformed; + sqlite3_result_double(pCtx, r); + break; + } + case JSONB_TEXTRAW: + case JSONB_TEXT: { + sqlite3_result_text(pCtx, (char*)&pParse->aBlob[i+n], sz, + SQLITE_TRANSIENT); + break; + } + case JSONB_TEXT5: + case JSONB_TEXTJ: { + /* Translate JSON formatted string into raw text */ + u32 iIn, iOut; + const char *z; + char *zOut; + u32 nOut = sz; + z = (const char*)&pParse->aBlob[i+n]; + zOut = sqlite3DbMallocRaw(db, nOut+1); + if( zOut==0 ) goto returnfromblob_oom; + for(iIn=iOut=0; iIn=2 ); + zOut[iOut++] = (char)(0xc0 | (v>>6)); + zOut[iOut++] = 0x80 | (v&0x3f); + }else if( v<0x10000 ){ + assert( szEscape>=3 ); + zOut[iOut++] = 0xe0 | (v>>12); + zOut[iOut++] = 0x80 | ((v>>6)&0x3f); + zOut[iOut++] = 0x80 | (v&0x3f); + }else if( v==JSON_INVALID_CHAR ){ + /* Silently ignore illegal unicode */ + }else{ + assert( szEscape>=4 ); + zOut[iOut++] = 0xf0 | (v>>18); + zOut[iOut++] = 0x80 | ((v>>12)&0x3f); + zOut[iOut++] = 0x80 | ((v>>6)&0x3f); + zOut[iOut++] = 0x80 | (v&0x3f); + } + iIn += szEscape - 1; + }else{ + zOut[iOut++] = c; + } + } /* end for() */ + assert( iOut<=nOut ); + zOut[iOut] = 0; + sqlite3_result_text(pCtx, zOut, iOut, SQLITE_DYNAMIC); + break; + } + case JSONB_ARRAY: + case JSONB_OBJECT: { + int flags = textOnly ? 0 : SQLITE_PTR_TO_INT(sqlite3_user_data(pCtx)); + if( flags & JSON_BLOB ){ + sqlite3_result_blob(pCtx, &pParse->aBlob[i], sz+n, SQLITE_TRANSIENT); + }else{ + jsonReturnTextJsonFromBlob(pCtx, &pParse->aBlob[i], sz+n); + } + break; + } + default: { + goto returnfromblob_malformed; + } + } + return; + +returnfromblob_oom: + sqlite3_result_error_nomem(pCtx); + return; + +returnfromblob_malformed: + sqlite3_result_error(pCtx, "malformed JSON", -1); + return; } /* -** Do a node lookup using zPath. Return a pointer to the node on success. -** Return NULL if not found or if there is an error. +** pArg is a function argument that might be an SQL value or a JSON +** value. Figure out what it is and encode it as a JSONB blob. +** Return the results in pParse. ** -** On an error, write an error message into pCtx and increment the -** pParse->nErr counter. +** pParse is uninitialized upon entry. This routine will handle the +** initialization of pParse. The result will be contained in +** pParse->aBlob and pParse->nBlob. pParse->aBlob might be dynamically +** allocated (if pParse->nBlobAlloc is greater than zero) in which case +** the caller is responsible for freeing the space allocated to pParse->aBlob +** when it has finished with it. Or pParse->aBlob might be a static string +** or a value obtained from sqlite3_value_blob(pArg). ** -** If pApnd!=NULL then try to append missing nodes and set *pApnd = 1 if -** nodes are appended. +** If the argument is a BLOB that is clearly not a JSONB, then this +** function might set an error message in ctx and return non-zero. +** It might also set an error message and return non-zero on an OOM error. */ -static JsonNode *jsonLookup( - JsonParse *pParse, /* The JSON to search */ - const char *zPath, /* The path to search */ - int *pApnd, /* Append nodes to complete path if not NULL */ - sqlite3_context *pCtx /* Report errors here, if not NULL */ -){ - const char *zErr = 0; - JsonNode *pNode = 0; - char *zMsg; - - if( zPath==0 ) return 0; - if( zPath[0]!='$' ){ - zErr = zPath; - goto lookup_err; +static int jsonFunctionArgToBlob( + sqlite3_context *ctx, + sqlite3_value *pArg, + JsonParse *pParse +){ + int eType = sqlite3_value_type(pArg); + static u8 aNull[] = { 0x00 }; + memset(pParse, 0, sizeof(pParse[0])); + pParse->db = sqlite3_context_db_handle(ctx); + switch( eType ){ + default: { + pParse->aBlob = aNull; + pParse->nBlob = 1; + return 0; + } + case SQLITE_BLOB: { + if( jsonFuncArgMightBeBinary(pArg) ){ + pParse->aBlob = (u8*)sqlite3_value_blob(pArg); + pParse->nBlob = sqlite3_value_bytes(pArg); + }else{ + sqlite3_result_error(ctx, "JSON cannot hold BLOB values", -1); + return 1; + } + break; + } + case SQLITE_TEXT: { + const char *zJson = (const char*)sqlite3_value_text(pArg); + int nJson = sqlite3_value_bytes(pArg); + if( zJson==0 ) return 1; + if( sqlite3_value_subtype(pArg)==JSON_SUBTYPE ){ + pParse->zJson = (char*)zJson; + pParse->nJson = nJson; + if( jsonConvertTextToBlob(pParse, ctx) ){ + sqlite3_result_error(ctx, "malformed JSON", -1); + sqlite3DbFree(pParse->db, pParse->aBlob); + memset(pParse, 0, sizeof(pParse[0])); + return 1; + } + }else{ + jsonBlobAppendNode(pParse, JSONB_TEXTRAW, nJson, zJson); + } + break; + } + case SQLITE_FLOAT: { + double r = sqlite3_value_double(pArg); + if( NEVER(sqlite3IsNaN(r)) ){ + jsonBlobAppendNode(pParse, JSONB_NULL, 0, 0); + }else{ + int n = sqlite3_value_bytes(pArg); + const char *z = (const char*)sqlite3_value_text(pArg); + if( z==0 ) return 1; + if( z[0]=='I' ){ + jsonBlobAppendNode(pParse, JSONB_FLOAT, 5, "9e999"); + }else if( z[0]=='-' && z[1]=='I' ){ + jsonBlobAppendNode(pParse, JSONB_FLOAT, 6, "-9e999"); + }else{ + jsonBlobAppendNode(pParse, JSONB_FLOAT, n, z); + } + } + break; + } + case SQLITE_INTEGER: { + int n = sqlite3_value_bytes(pArg); + const char *z = (const char*)sqlite3_value_text(pArg); + if( z==0 ) return 1; + jsonBlobAppendNode(pParse, JSONB_INT, n, z); + break; + } } - zPath++; - pNode = jsonLookupStep(pParse, 0, zPath, pApnd, &zErr); - if( zErr==0 ) return pNode; + if( pParse->oom ){ + sqlite3_result_error_nomem(ctx); + return 1; + }else{ + return 0; + } +} -lookup_err: - pParse->nErr++; - assert( zErr!=0 && pCtx!=0 ); - zMsg = jsonPathSyntaxError(zErr); +/* +** Generate a bad path error. +** +** If ctx is not NULL then push the error message into ctx and return NULL. +** If ctx is NULL, then return the text of the error message. +*/ +static char *jsonBadPathError( + sqlite3_context *ctx, /* The function call containing the error */ + const char *zPath /* The path with the problem */ +){ + char *zMsg = sqlite3_mprintf("bad JSON path: %Q", zPath); + if( ctx==0 ) return zMsg; if( zMsg ){ - sqlite3_result_error(pCtx, zMsg, -1); + sqlite3_result_error(ctx, zMsg, -1); sqlite3_free(zMsg); }else{ - sqlite3_result_error_nomem(pCtx); + sqlite3_result_error_nomem(ctx); } return 0; } +/* argv[0] is a BLOB that seems likely to be a JSONB. Subsequent +** arguments come in parse where each pair contains a JSON path and +** content to insert or set at that patch. Do the updates +** and return the result. +** +** The specific operation is determined by eEdit, which can be one +** of JEDIT_INS, JEDIT_REPL, or JEDIT_SET. +*/ +static void jsonInsertIntoBlob( + sqlite3_context *ctx, + int argc, + sqlite3_value **argv, + int eEdit /* JEDIT_INS, JEDIT_REPL, or JEDIT_SET */ +){ + int i; + u32 rc = 0; + const char *zPath = 0; + int flgs; + JsonParse *p; + JsonParse ax; + + assert( (argc&1)==1 ); + flgs = argc==1 ? 0 : JSON_EDITABLE; + p = jsonParseFuncArg(ctx, argv[0], flgs); + if( p==0 ) return; + for(i=1; inBlob, ax.aBlob, ax.nBlob); + } + rc = 0; + }else{ + p->eEdit = eEdit; + p->nIns = ax.nBlob; + p->aIns = ax.aBlob; + p->delta = 0; + rc = jsonLookupStep(p, 0, zPath+1, 0); + } + jsonParseReset(&ax); + if( rc==JSON_LOOKUP_NOTFOUND ) continue; + if( JSON_LOOKUP_ISERROR(rc) ) goto jsonInsertIntoBlob_patherror; + } + jsonReturnParse(ctx, p); + jsonParseFree(p); + return; + +jsonInsertIntoBlob_patherror: + jsonParseFree(p); + if( rc==JSON_LOOKUP_ERROR ){ + sqlite3_result_error(ctx, "malformed JSON", -1); + }else{ + jsonBadPathError(ctx, zPath); + } + return; +} /* -** Report the wrong number of arguments for json_insert(), json_replace() -** or json_set(). +** If pArg is a blob that seems like a JSONB blob, then initialize +** p to point to that JSONB and return TRUE. If pArg does not seem like +** a JSONB blob, then return FALSE; +** +** This routine is only called if it is already known that pArg is a +** blob. The only open question is whether or not the blob appears +** to be a JSONB blob. */ -static void jsonWrongNumArgs( - sqlite3_context *pCtx, - const char *zFuncName -){ - char *zMsg = sqlite3_mprintf("json_%s() needs an odd number of arguments", - zFuncName); - sqlite3_result_error(pCtx, zMsg, -1); - sqlite3_free(zMsg); +static int jsonArgIsJsonb(sqlite3_value *pArg, JsonParse *p){ + u32 n, sz = 0; + p->aBlob = (u8*)sqlite3_value_blob(pArg); + p->nBlob = (u32)sqlite3_value_bytes(pArg); + if( p->nBlob==0 ){ + p->aBlob = 0; + return 0; + } + if( NEVER(p->aBlob==0) ){ + return 0; + } + if( (p->aBlob[0] & 0x0f)<=JSONB_OBJECT + && (n = jsonbPayloadSize(p, 0, &sz))>0 + && sz+n==p->nBlob + && ((p->aBlob[0] & 0x0f)>JSONB_FALSE || sz==0) + ){ + return 1; + } + p->aBlob = 0; + p->nBlob = 0; + return 0; } /* -** Mark all NULL entries in the Object passed in as JNODE_REMOVE. +** Generate a JsonParse object, containing valid JSONB in aBlob and nBlob, +** from the SQL function argument pArg. Return a pointer to the new +** JsonParse object. +** +** Ownership of the new JsonParse object is passed to the caller. The +** caller should invoke jsonParseFree() on the return value when it +** has finished using it. +** +** If any errors are detected, an appropriate error messages is set +** using sqlite3_result_error() or the equivalent and this routine +** returns NULL. This routine also returns NULL if the pArg argument +** is an SQL NULL value, but no error message is set in that case. This +** is so that SQL functions that are given NULL arguments will return +** a NULL value. */ -static void jsonRemoveAllNulls(JsonNode *pNode){ - int i, n; - assert( pNode->eType==JSON_OBJECT ); - n = pNode->n; - for(i=2; i<=n; i += jsonNodeSize(&pNode[i])+1){ - switch( pNode[i].eType ){ - case JSON_NULL: - pNode[i].jnFlags |= JNODE_REMOVE; - break; - case JSON_OBJECT: - jsonRemoveAllNulls(&pNode[i]); - break; +static JsonParse *jsonParseFuncArg( + sqlite3_context *ctx, + sqlite3_value *pArg, + u32 flgs +){ + int eType; /* Datatype of pArg */ + JsonParse *p = 0; /* Value to be returned */ + JsonParse *pFromCache = 0; /* Value taken from cache */ + sqlite3 *db; /* The database connection */ + + assert( ctx!=0 ); + eType = sqlite3_value_type(pArg); + if( eType==SQLITE_NULL ){ + return 0; + } + pFromCache = jsonCacheSearch(ctx, pArg); + if( pFromCache ){ + pFromCache->nJPRef++; + if( (flgs & JSON_EDITABLE)==0 ){ + return pFromCache; } } + db = sqlite3_context_db_handle(ctx); +rebuild_from_cache: + p = sqlite3DbMallocZero(db, sizeof(*p)); + if( p==0 ) goto json_pfa_oom; + memset(p, 0, sizeof(*p)); + p->db = db; + p->nJPRef = 1; + if( pFromCache!=0 ){ + u32 nBlob = pFromCache->nBlob; + p->aBlob = sqlite3DbMallocRaw(db, nBlob); + if( p->aBlob==0 ) goto json_pfa_oom; + memcpy(p->aBlob, pFromCache->aBlob, nBlob); + p->nBlobAlloc = p->nBlob = nBlob; + p->hasNonstd = pFromCache->hasNonstd; + jsonParseFree(pFromCache); + return p; + } + if( eType==SQLITE_BLOB ){ + if( jsonArgIsJsonb(pArg,p) ){ + if( (flgs & JSON_EDITABLE)!=0 && jsonBlobMakeEditable(p, 0)==0 ){ + goto json_pfa_oom; + } + return p; + } + /* If the blob is not valid JSONB, fall through into trying to cast + ** the blob into text which is then interpreted as JSON. (tag-20240123-a) + ** + ** This goes against all historical documentation about how the SQLite + ** JSON functions were suppose to work. From the beginning, blob was + ** reserved for expansion and a blob value should have raised an error. + ** But it did not, due to a bug. And many applications came to depend + ** upon this buggy behavior, espeically when using the CLI and reading + ** JSON text using readfile(), which returns a blob. For this reason + ** we will continue to support the bug moving forward. + ** See for example https://sqlite.org/forum/forumpost/012136abd5292b8d + */ + } + p->zJson = (char*)sqlite3_value_text(pArg); + p->nJson = sqlite3_value_bytes(pArg); + if( db->mallocFailed ) goto json_pfa_oom; + if( p->nJson==0 ) goto json_pfa_malformed; + assert( p->zJson!=0 ); + if( jsonConvertTextToBlob(p, (flgs & JSON_KEEPERROR) ? 0 : ctx) ){ + if( flgs & JSON_KEEPERROR ){ + p->nErr = 1; + return p; + }else{ + jsonParseFree(p); + return 0; + } + }else{ + int isRCStr = sqlite3ValueIsOfClass(pArg, sqlite3RCStrUnref); + int rc; + if( !isRCStr ){ + char *zNew = sqlite3RCStrNew( p->nJson ); + if( zNew==0 ) goto json_pfa_oom; + memcpy(zNew, p->zJson, p->nJson); + p->zJson = zNew; + p->zJson[p->nJson] = 0; + }else{ + sqlite3RCStrRef(p->zJson); + } + p->bJsonIsRCStr = 1; + rc = jsonCacheInsert(ctx, p); + if( rc==SQLITE_NOMEM ) goto json_pfa_oom; + if( flgs & JSON_EDITABLE ){ + pFromCache = p; + p = 0; + goto rebuild_from_cache; + } + } + return p; + +json_pfa_malformed: + if( flgs & JSON_KEEPERROR ){ + p->nErr = 1; + return p; + }else{ + jsonParseFree(p); + sqlite3_result_error(ctx, "malformed JSON", -1); + return 0; + } + +json_pfa_oom: + jsonParseFree(pFromCache); + jsonParseFree(p); + sqlite3_result_error_nomem(ctx); + return 0; } +/* +** Make the return value of a JSON function either the raw JSONB blob +** or make it JSON text, depending on whether the JSON_BLOB flag is +** set on the function. +*/ +static void jsonReturnParse( + sqlite3_context *ctx, + JsonParse *p +){ + int flgs; + if( p->oom ){ + sqlite3_result_error_nomem(ctx); + return; + } + flgs = SQLITE_PTR_TO_INT(sqlite3_user_data(ctx)); + if( flgs & JSON_BLOB ){ + if( p->nBlobAlloc>0 && !p->bReadOnly ){ + sqlite3_result_blob(ctx, p->aBlob, p->nBlob, SQLITE_DYNAMIC); + p->nBlobAlloc = 0; + }else{ + sqlite3_result_blob(ctx, p->aBlob, p->nBlob, SQLITE_TRANSIENT); + } + }else{ + JsonString s; + jsonStringInit(&s, ctx); + p->delta = 0; + jsonTranslateBlobToText(p, 0, &s); + jsonReturnString(&s, p, ctx); + sqlite3_result_subtype(ctx, JSON_SUBTYPE); + } +} /**************************************************************************** ** SQL functions used for testing and debugging @@ -203539,63 +208420,124 @@ static void jsonRemoveAllNulls(JsonNode *pNode){ #if SQLITE_DEBUG /* -** Print N node entries. -*/ -static void jsonDebugPrintNodeEntries( - JsonNode *aNode, /* First node entry to print */ - int N /* Number of node entries to print */ -){ - int i; - for(i=0; iaBlob[iStart] & 0x0f; + u32 savedNBlob = pParse->nBlob; + sqlite3_str_appendf(pOut, "%5d:%*s", iStart, nIndent, ""); + if( pParse->nBlobAlloc>pParse->nBlob ){ + pParse->nBlob = pParse->nBlobAlloc; + } + nn = n = jsonbPayloadSize(pParse, iStart, &sz); + if( nn==0 ) nn = 1; + if( sz>0 && xaBlob[iStart+i]); + } + if( n==0 ){ + sqlite3_str_appendf(pOut, " ERROR invalid node size\n"); + iStart = n==0 ? iStart+1 : iEnd; + continue; + } + pParse->nBlob = savedNBlob; + if( iStart+n+sz>iEnd ){ + iEnd = iStart+n+sz; + if( iEnd>pParse->nBlob ){ + if( pParse->nBlobAlloc>0 && iEnd>pParse->nBlobAlloc ){ + iEnd = pParse->nBlobAlloc; + }else{ + iEnd = pParse->nBlob; + } + } } - printf("node %4u: %-7s n=%-5d", i, zType, aNode[i].n); - if( (aNode[i].jnFlags & ~JNODE_LABEL)!=0 ){ - u8 f = aNode[i].jnFlags; - if( f & JNODE_RAW ) printf(" RAW"); - if( f & JNODE_ESCAPE ) printf(" ESCAPE"); - if( f & JNODE_REMOVE ) printf(" REMOVE"); - if( f & JNODE_REPLACE ) printf(" REPLACE"); - if( f & JNODE_APPEND ) printf(" APPEND"); - if( f & JNODE_JSON5 ) printf(" JSON5"); + sqlite3_str_appendall(pOut," <-- "); + switch( x ){ + case JSONB_NULL: sqlite3_str_appendall(pOut,"null"); break; + case JSONB_TRUE: sqlite3_str_appendall(pOut,"true"); break; + case JSONB_FALSE: sqlite3_str_appendall(pOut,"false"); break; + case JSONB_INT: sqlite3_str_appendall(pOut,"int"); break; + case JSONB_INT5: sqlite3_str_appendall(pOut,"int5"); break; + case JSONB_FLOAT: sqlite3_str_appendall(pOut,"float"); break; + case JSONB_FLOAT5: sqlite3_str_appendall(pOut,"float5"); break; + case JSONB_TEXT: sqlite3_str_appendall(pOut,"text"); break; + case JSONB_TEXTJ: sqlite3_str_appendall(pOut,"textj"); break; + case JSONB_TEXT5: sqlite3_str_appendall(pOut,"text5"); break; + case JSONB_TEXTRAW: sqlite3_str_appendall(pOut,"textraw"); break; + case JSONB_ARRAY: { + sqlite3_str_appendf(pOut,"array, %u bytes\n", sz); + jsonDebugPrintBlob(pParse, iStart+n, iStart+n+sz, nIndent+2, pOut); + showContent = 0; + break; + } + case JSONB_OBJECT: { + sqlite3_str_appendf(pOut, "object, %u bytes\n", sz); + jsonDebugPrintBlob(pParse, iStart+n, iStart+n+sz, nIndent+2, pOut); + showContent = 0; + break; + } + default: { + sqlite3_str_appendall(pOut, "ERROR: unknown node type\n"); + showContent = 0; + break; + } } - switch( aNode[i].eU ){ - case 1: printf(" zJContent=[%.*s]\n", - aNode[i].n, aNode[i].u.zJContent); break; - case 2: printf(" iAppend=%u\n", aNode[i].u.iAppend); break; - case 3: printf(" iKey=%u\n", aNode[i].u.iKey); break; - case 4: printf(" iPrev=%u\n", aNode[i].u.iPrev); break; - default: printf("\n"); + if( showContent ){ + if( sz==0 && x<=JSONB_FALSE ){ + sqlite3_str_append(pOut, "\n", 1); + }else{ + u32 j; + sqlite3_str_appendall(pOut, ": \""); + for(j=iStart+n; jaBlob[j]; + if( c<0x20 || c>=0x7f ) c = '.'; + sqlite3_str_append(pOut, (char*)&c, 1); + } + sqlite3_str_append(pOut, "\"\n", 2); + } } + iStart += n + sz; } } -#endif /* SQLITE_DEBUG */ - - -#if 0 /* 1 for debugging. 0 normally. Requires -DSQLITE_DEBUG too */ -static void jsonDebugPrintParse(JsonParse *p){ - jsonDebugPrintNodeEntries(p->aNode, p->nNode); -} -static void jsonDebugPrintNode(JsonNode *pNode){ - jsonDebugPrintNodeEntries(pNode, jsonNodeSize(pNode)); +static void jsonShowParse(JsonParse *pParse){ + sqlite3_str out; + char zBuf[1000]; + if( pParse==0 ){ + printf("NULL pointer\n"); + return; + }else{ + printf("nBlobAlloc = %u\n", pParse->nBlobAlloc); + printf("nBlob = %u\n", pParse->nBlob); + printf("delta = %d\n", pParse->delta); + if( pParse->nBlob==0 ) return; + printf("content (bytes 0..%u):\n", pParse->nBlob-1); + } + sqlite3StrAccumInit(&out, 0, zBuf, sizeof(zBuf), 1000000); + jsonDebugPrintBlob(pParse, 0, pParse->nBlob, 0, &out); + printf("%s", sqlite3_str_value(&out)); + sqlite3_str_reset(&out); } -#else - /* The usual case */ -# define jsonDebugPrintNode(X) -# define jsonDebugPrintParse(X) -#endif +#endif /* SQLITE_DEBUG */ #ifdef SQLITE_DEBUG /* ** SQL function: json_parse(JSON) ** -** Parse JSON using jsonParseCached(). Then print a dump of that -** parse on standard output. Return the mimified JSON result, just -** like the json() function. +** Parse JSON using jsonParseFuncArg(). Return text that is a +** human-readable dump of the binary JSONB for the input parameter. */ static void jsonParseFunc( sqlite3_context *ctx, @@ -203603,38 +208545,20 @@ static void jsonParseFunc( sqlite3_value **argv ){ JsonParse *p; /* The parse */ + sqlite3_str out; - assert( argc==1 ); - p = jsonParseCached(ctx, argv[0], ctx, 0); + assert( argc>=1 ); + sqlite3StrAccumInit(&out, 0, 0, 0, 1000000); + p = jsonParseFuncArg(ctx, argv[0], 0); if( p==0 ) return; - printf("nNode = %u\n", p->nNode); - printf("nAlloc = %u\n", p->nAlloc); - printf("nJson = %d\n", p->nJson); - printf("nAlt = %d\n", p->nAlt); - printf("nErr = %u\n", p->nErr); - printf("oom = %u\n", p->oom); - printf("hasNonstd = %u\n", p->hasNonstd); - printf("useMod = %u\n", p->useMod); - printf("hasMod = %u\n", p->hasMod); - printf("nJPRef = %u\n", p->nJPRef); - printf("iSubst = %u\n", p->iSubst); - printf("iHold = %u\n", p->iHold); - jsonDebugPrintNodeEntries(p->aNode, p->nNode); - jsonReturnJson(p, p->aNode, ctx, 1); -} - -/* -** The json_test1(JSON) function return true (1) if the input is JSON -** text generated by another json function. It returns (0) if the input -** is not known to be JSON. -*/ -static void jsonTest1Func( - sqlite3_context *ctx, - int argc, - sqlite3_value **argv -){ - UNUSED_PARAMETER(argc); - sqlite3_result_int(ctx, sqlite3_value_subtype(argv[0])==JSON_SUBTYPE); + if( argc==1 ){ + jsonDebugPrintBlob(p, 0, p->nBlob, 0, &out); + sqlite3_result_text64(ctx,out.zText,out.nChar,SQLITE_TRANSIENT,SQLITE_UTF8); + }else{ + jsonShowParse(p); + } + jsonParseFree(p); + sqlite3_str_reset(&out); } #endif /* SQLITE_DEBUG */ @@ -203643,7 +208567,7 @@ static void jsonTest1Func( ****************************************************************************/ /* -** Implementation of the json_QUOTE(VALUE) function. Return a JSON value +** Implementation of the json_quote(VALUE) function. Return a JSON value ** corresponding to the SQL value input. Mostly this means putting ** double-quotes around strings and returning the unquoted string "null" ** when given a NULL input. @@ -203656,9 +208580,9 @@ static void jsonQuoteFunc( JsonString jx; UNUSED_PARAMETER(argc); - jsonInit(&jx, ctx); - jsonAppendValue(&jx, argv[0]); - jsonResult(&jx); + jsonStringInit(&jx, ctx); + jsonAppendSqlValue(&jx, argv[0]); + jsonReturnString(&jx, 0, 0); sqlite3_result_subtype(ctx, JSON_SUBTYPE); } @@ -203675,18 +208599,17 @@ static void jsonArrayFunc( int i; JsonString jx; - jsonInit(&jx, ctx); + jsonStringInit(&jx, ctx); jsonAppendChar(&jx, '['); for(i=0; inNode ); if( argc==2 ){ const char *zPath = (const char*)sqlite3_value_text(argv[1]); - pNode = jsonLookup(p, zPath, 0, ctx); - }else{ - pNode = p->aNode; - } - if( pNode==0 ){ - return; - } - if( pNode->eType==JSON_ARRAY ){ - while( 1 /*exit-by-break*/ ){ - i = 1; - while( i<=pNode->n ){ - if( (pNode[i].jnFlags & JNODE_REMOVE)==0 ) n++; - i += jsonNodeSize(&pNode[i]); + if( zPath==0 ){ + jsonParseFree(p); + return; + } + i = jsonLookupStep(p, 0, zPath[0]=='$' ? zPath+1 : "@", 0); + if( JSON_LOOKUP_ISERROR(i) ){ + if( i==JSON_LOOKUP_NOTFOUND ){ + /* no-op */ + }else if( i==JSON_LOOKUP_PATHERROR ){ + jsonBadPathError(ctx, zPath); + }else{ + sqlite3_result_error(ctx, "malformed JSON", -1); } - if( (pNode->jnFlags & JNODE_APPEND)==0 ) break; - if( p->useMod==0 ) break; - assert( pNode->eU==2 ); - pNode = &p->aNode[pNode->u.iAppend]; + eErr = 1; + i = 0; } + }else{ + i = 0; + } + if( (p->aBlob[i] & 0x0f)==JSONB_ARRAY ){ + cnt = jsonbArrayCount(p, i); } - sqlite3_result_int64(ctx, n); + if( !eErr ) sqlite3_result_int64(ctx, cnt); + jsonParseFree(p); } -/* -** Bit values for the flags passed into jsonExtractFunc() or -** jsonSetFunc() via the user-data value. -*/ -#define JSON_JSON 0x01 /* Result is always JSON */ -#define JSON_SQL 0x02 /* Result is always SQL */ -#define JSON_ABPATH 0x03 /* Allow abbreviated JSON path specs */ -#define JSON_ISSET 0x04 /* json_set(), not json_insert() */ +/* True if the string is all alphanumerics and underscores */ +static int jsonAllAlphanum(const char *z, int n){ + int i; + for(i=0; i2 ){ + jsonAppendChar(&jx, '['); + } + for(i=1; i and ->> operators accept abbreviated PATH arguments. This - ** is mostly for compatibility with PostgreSQL, but also for - ** convenience. - ** - ** NUMBER ==> $[NUMBER] // PG compatible - ** LABEL ==> $.LABEL // PG compatible - ** [NUMBER] ==> $[NUMBER] // Not PG. Purely for convenience - */ - jsonInit(&jx, ctx); - if( sqlite3Isdigit(zPath[0]) ){ - jsonAppendRawNZ(&jx, "$[", 2); - jsonAppendRaw(&jx, zPath, (int)strlen(zPath)); - jsonAppendRawNZ(&jx, "]", 2); - }else{ - jsonAppendRawNZ(&jx, "$.", 1 + (zPath[0]!='[')); - jsonAppendRaw(&jx, zPath, (int)strlen(zPath)); - jsonAppendChar(&jx, 0); - } - pNode = jx.bErr ? 0 : jsonLookup(p, jx.zBuf, 0, ctx); - jsonReset(&jx); + const char *zPath = (const char*)sqlite3_value_text(argv[i]); + int nPath; + u32 j; + if( zPath==0 ) goto json_extract_error; + nPath = sqlite3Strlen30(zPath); + if( zPath[0]=='$' ){ + j = jsonLookupStep(p, 0, zPath+1, 0); + }else if( (flags & JSON_ABPATH) ){ + /* The -> and ->> operators accept abbreviated PATH arguments. This + ** is mostly for compatibility with PostgreSQL, but also for + ** convenience. + ** + ** NUMBER ==> $[NUMBER] // PG compatible + ** LABEL ==> $.LABEL // PG compatible + ** [NUMBER] ==> $[NUMBER] // Not PG. Purely for convenience + */ + jsonStringInit(&jx, ctx); + if( sqlite3_value_type(argv[i])==SQLITE_INTEGER ){ + jsonAppendRawNZ(&jx, "[", 1); + jsonAppendRaw(&jx, zPath, nPath); + jsonAppendRawNZ(&jx, "]", 2); + }else if( jsonAllAlphanum(zPath, nPath) ){ + jsonAppendRawNZ(&jx, ".", 1); + jsonAppendRaw(&jx, zPath, nPath); + }else if( zPath[0]=='[' && nPath>=3 && zPath[nPath-1]==']' ){ + jsonAppendRaw(&jx, zPath, nPath); }else{ - pNode = jsonLookup(p, zPath, 0, ctx); + jsonAppendRawNZ(&jx, ".\"", 2); + jsonAppendRaw(&jx, zPath, nPath); + jsonAppendRawNZ(&jx, "\"", 1); } - if( pNode ){ + jsonStringTerminate(&jx); + j = jsonLookupStep(p, 0, jx.zBuf, 0); + jsonStringReset(&jx); + }else{ + jsonBadPathError(ctx, zPath); + goto json_extract_error; + } + if( jnBlob ){ + if( argc==2 ){ if( flags & JSON_JSON ){ - jsonReturnJson(p, pNode, ctx, 0); + jsonStringInit(&jx, ctx); + jsonTranslateBlobToText(p, j, &jx); + jsonReturnString(&jx, 0, 0); + jsonStringReset(&jx); + assert( (flags & JSON_BLOB)==0 ); + sqlite3_result_subtype(ctx, JSON_SUBTYPE); }else{ - jsonReturn(p, pNode, ctx); - sqlite3_result_subtype(ctx, 0); + jsonReturnFromBlob(p, j, ctx, 0); + if( (flags & (JSON_SQL|JSON_BLOB))==0 + && (p->aBlob[j]&0x0f)>=JSONB_ARRAY + ){ + sqlite3_result_subtype(ctx, JSON_SUBTYPE); + } } + }else{ + jsonAppendSeparator(&jx); + jsonTranslateBlobToText(p, j, &jx); } - }else{ - pNode = jsonLookup(p, zPath, 0, ctx); - if( p->nErr==0 && pNode ) jsonReturn(p, pNode, ctx); - } - }else{ - /* Two or more PATH arguments results in a JSON array with each - ** element of the array being the value selected by one of the PATHs */ - int i; - jsonInit(&jx, ctx); - jsonAppendChar(&jx, '['); - for(i=1; inErr ) break; - jsonAppendSeparator(&jx); - if( pNode ){ - jsonRenderNode(p, pNode, &jx); + }else if( j==JSON_LOOKUP_NOTFOUND ){ + if( argc==2 ){ + goto json_extract_error; /* Return NULL if not found */ }else{ + jsonAppendSeparator(&jx); jsonAppendRawNZ(&jx, "null", 4); } + }else if( j==JSON_LOOKUP_ERROR ){ + sqlite3_result_error(ctx, "malformed JSON", -1); + goto json_extract_error; + }else{ + jsonBadPathError(ctx, zPath); + goto json_extract_error; } - if( i==argc ){ - jsonAppendChar(&jx, ']'); - jsonResult(&jx); + } + if( argc>2 ){ + jsonAppendChar(&jx, ']'); + jsonReturnString(&jx, 0, 0); + if( (flags & JSON_BLOB)==0 ){ sqlite3_result_subtype(ctx, JSON_SUBTYPE); } - jsonReset(&jx); } +json_extract_error: + jsonStringReset(&jx); + jsonParseFree(p); + return; } -/* This is the RFC 7396 MergePatch algorithm. -*/ -static JsonNode *jsonMergePatch( - JsonParse *pParse, /* The JSON parser that contains the TARGET */ - u32 iTarget, /* Node of the TARGET in pParse */ - JsonNode *pPatch /* The PATCH */ -){ - u32 i, j; - u32 iRoot; - JsonNode *pTarget; - if( pPatch->eType!=JSON_OBJECT ){ - return pPatch; - } - assert( iTargetnNode ); - pTarget = &pParse->aNode[iTarget]; - assert( (pPatch->jnFlags & JNODE_APPEND)==0 ); - if( pTarget->eType!=JSON_OBJECT ){ - jsonRemoveAllNulls(pPatch); - return pPatch; - } - iRoot = iTarget; - for(i=1; in; i += jsonNodeSize(&pPatch[i+1])+1){ - u32 nKey; - const char *zKey; - assert( pPatch[i].eType==JSON_STRING ); - assert( pPatch[i].jnFlags & JNODE_LABEL ); - assert( pPatch[i].eU==1 ); - nKey = pPatch[i].n; - zKey = pPatch[i].u.zJContent; - for(j=1; jn; j += jsonNodeSize(&pTarget[j+1])+1 ){ - assert( pTarget[j].eType==JSON_STRING ); - assert( pTarget[j].jnFlags & JNODE_LABEL ); - if( jsonSameLabel(&pPatch[i], &pTarget[j]) ){ - if( pTarget[j+1].jnFlags & (JNODE_REMOVE|JNODE_REPLACE) ) break; - if( pPatch[i+1].eType==JSON_NULL ){ - pTarget[j+1].jnFlags |= JNODE_REMOVE; - }else{ - JsonNode *pNew = jsonMergePatch(pParse, iTarget+j+1, &pPatch[i+1]); - if( pNew==0 ) return 0; - if( pNew!=&pParse->aNode[iTarget+j+1] ){ - jsonParseAddSubstNode(pParse, iTarget+j+1); - jsonParseAddNodeArray(pParse, pNew, jsonNodeSize(pNew)); - } - pTarget = &pParse->aNode[iTarget]; - } - break; +/* +** Return codes for jsonMergePatch() +*/ +#define JSON_MERGE_OK 0 /* Success */ +#define JSON_MERGE_BADTARGET 1 /* Malformed TARGET blob */ +#define JSON_MERGE_BADPATCH 2 /* Malformed PATCH blob */ +#define JSON_MERGE_OOM 3 /* Out-of-memory condition */ + +/* +** RFC-7396 MergePatch for two JSONB blobs. +** +** pTarget is the target. pPatch is the patch. The target is updated +** in place. The patch is read-only. +** +** The original RFC-7396 algorithm is this: +** +** define MergePatch(Target, Patch): +** if Patch is an Object: +** if Target is not an Object: +** Target = {} # Ignore the contents and set it to an empty Object +** for each Name/Value pair in Patch: +** if Value is null: +** if Name exists in Target: +** remove the Name/Value pair from Target +** else: +** Target[Name] = MergePatch(Target[Name], Value) +** return Target +** else: +** return Patch +** +** Here is an equivalent algorithm restructured to show the actual +** implementation: +** +** 01 define MergePatch(Target, Patch): +** 02 if Patch is not an Object: +** 03 return Patch +** 04 else: // if Patch is an Object +** 05 if Target is not an Object: +** 06 Target = {} +** 07 for each Name/Value pair in Patch: +** 08 if Name exists in Target: +** 09 if Value is null: +** 10 remove the Name/Value pair from Target +** 11 else +** 12 Target[name] = MergePatch(Target[Name], Value) +** 13 else if Value is not NULL: +** 14 if Value is not an Object: +** 15 Target[name] = Value +** 16 else: +** 17 Target[name] = MergePatch('{}',value) +** 18 return Target +** | +** ^---- Line numbers referenced in comments in the implementation +*/ +static int jsonMergePatch( + JsonParse *pTarget, /* The JSON parser that contains the TARGET */ + u32 iTarget, /* Index of TARGET in pTarget->aBlob[] */ + const JsonParse *pPatch, /* The PATCH */ + u32 iPatch /* Index of PATCH in pPatch->aBlob[] */ +){ + u8 x; /* Type of a single node */ + u32 n, sz=0; /* Return values from jsonbPayloadSize() */ + u32 iTCursor; /* Cursor position while scanning the target object */ + u32 iTStart; /* First label in the target object */ + u32 iTEndBE; /* Original first byte past end of target, before edit */ + u32 iTEnd; /* Current first byte past end of target */ + u8 eTLabel; /* Node type of the target label */ + u32 iTLabel = 0; /* Index of the label */ + u32 nTLabel = 0; /* Header size in bytes for the target label */ + u32 szTLabel = 0; /* Size of the target label payload */ + u32 iTValue = 0; /* Index of the target value */ + u32 nTValue = 0; /* Header size of the target value */ + u32 szTValue = 0; /* Payload size for the target value */ + + u32 iPCursor; /* Cursor position while scanning the patch */ + u32 iPEnd; /* First byte past the end of the patch */ + u8 ePLabel; /* Node type of the patch label */ + u32 iPLabel; /* Start of patch label */ + u32 nPLabel; /* Size of header on the patch label */ + u32 szPLabel; /* Payload size of the patch label */ + u32 iPValue; /* Start of patch value */ + u32 nPValue; /* Header size for the patch value */ + u32 szPValue; /* Payload size of the patch value */ + + assert( iTarget>=0 && iTargetnBlob ); + assert( iPatch>=0 && iPatchnBlob ); + x = pPatch->aBlob[iPatch] & 0x0f; + if( x!=JSONB_OBJECT ){ /* Algorithm line 02 */ + u32 szPatch; /* Total size of the patch, header+payload */ + u32 szTarget; /* Total size of the target, header+payload */ + n = jsonbPayloadSize(pPatch, iPatch, &sz); + szPatch = n+sz; + sz = 0; + n = jsonbPayloadSize(pTarget, iTarget, &sz); + szTarget = n+sz; + jsonBlobEdit(pTarget, iTarget, szTarget, pPatch->aBlob+iPatch, szPatch); + return pTarget->oom ? JSON_MERGE_OOM : JSON_MERGE_OK; /* Line 03 */ + } + x = pTarget->aBlob[iTarget] & 0x0f; + if( x!=JSONB_OBJECT ){ /* Algorithm line 05 */ + n = jsonbPayloadSize(pTarget, iTarget, &sz); + jsonBlobEdit(pTarget, iTarget+n, sz, 0, 0); + x = pTarget->aBlob[iTarget]; + pTarget->aBlob[iTarget] = (x & 0xf0) | JSONB_OBJECT; + } + n = jsonbPayloadSize(pPatch, iPatch, &sz); + if( NEVER(n==0) ) return JSON_MERGE_BADPATCH; + iPCursor = iPatch+n; + iPEnd = iPCursor+sz; + n = jsonbPayloadSize(pTarget, iTarget, &sz); + if( NEVER(n==0) ) return JSON_MERGE_BADTARGET; + iTStart = iTarget+n; + iTEndBE = iTStart+sz; + + while( iPCursoraBlob[iPCursor] & 0x0f; + if( ePLabelJSONB_TEXTRAW ){ + return JSON_MERGE_BADPATCH; + } + nPLabel = jsonbPayloadSize(pPatch, iPCursor, &szPLabel); + if( nPLabel==0 ) return JSON_MERGE_BADPATCH; + iPValue = iPCursor + nPLabel + szPLabel; + if( iPValue>=iPEnd ) return JSON_MERGE_BADPATCH; + nPValue = jsonbPayloadSize(pPatch, iPValue, &szPValue); + if( nPValue==0 ) return JSON_MERGE_BADPATCH; + iPCursor = iPValue + nPValue + szPValue; + if( iPCursor>iPEnd ) return JSON_MERGE_BADPATCH; + + iTCursor = iTStart; + iTEnd = iTEndBE + pTarget->delta; + while( iTCursoraBlob[iTCursor] & 0x0f; + if( eTLabelJSONB_TEXTRAW ){ + return JSON_MERGE_BADTARGET; + } + nTLabel = jsonbPayloadSize(pTarget, iTCursor, &szTLabel); + if( nTLabel==0 ) return JSON_MERGE_BADTARGET; + iTValue = iTLabel + nTLabel + szTLabel; + if( iTValue>=iTEnd ) return JSON_MERGE_BADTARGET; + nTValue = jsonbPayloadSize(pTarget, iTValue, &szTValue); + if( nTValue==0 ) return JSON_MERGE_BADTARGET; + if( iTValue + nTValue + szTValue > iTEnd ) return JSON_MERGE_BADTARGET; + isEqual = jsonLabelCompare( + (const char*)&pPatch->aBlob[iPLabel+nPLabel], + szPLabel, + (ePLabel==JSONB_TEXT || ePLabel==JSONB_TEXTRAW), + (const char*)&pTarget->aBlob[iTLabel+nTLabel], + szTLabel, + (eTLabel==JSONB_TEXT || eTLabel==JSONB_TEXTRAW)); + if( isEqual ) break; + iTCursor = iTValue + nTValue + szTValue; + } + x = pPatch->aBlob[iPValue] & 0x0f; + if( iTCursoroom) ) return JSON_MERGE_OOM; + }else{ + /* Algorithm line 12 */ + int rc, savedDelta = pTarget->delta; + pTarget->delta = 0; + rc = jsonMergePatch(pTarget, iTValue, pPatch, iPValue); + if( rc ) return rc; + pTarget->delta += savedDelta; + } + }else if( x>0 ){ /* Algorithm line 13 */ + /* No match and patch value is not NULL */ + u32 szNew = szPLabel+nPLabel; + if( (pPatch->aBlob[iPValue] & 0x0f)!=JSONB_OBJECT ){ /* Line 14 */ + jsonBlobEdit(pTarget, iTEnd, 0, 0, szPValue+nPValue+szNew); + if( pTarget->oom ) return JSON_MERGE_OOM; + memcpy(&pTarget->aBlob[iTEnd], &pPatch->aBlob[iPLabel], szNew); + memcpy(&pTarget->aBlob[iTEnd+szNew], + &pPatch->aBlob[iPValue], szPValue+nPValue); + }else{ + int rc, savedDelta; + jsonBlobEdit(pTarget, iTEnd, 0, 0, szNew+1); + if( pTarget->oom ) return JSON_MERGE_OOM; + memcpy(&pTarget->aBlob[iTEnd], &pPatch->aBlob[iPLabel], szNew); + pTarget->aBlob[iTEnd+szNew] = 0x00; + savedDelta = pTarget->delta; + pTarget->delta = 0; + rc = jsonMergePatch(pTarget, iTEnd+szNew,pPatch,iPValue); + if( rc ) return rc; + pTarget->delta += savedDelta; } } - if( j>=pTarget->n && pPatch[i+1].eType!=JSON_NULL ){ - int iStart; - JsonNode *pApnd; - u32 nApnd; - iStart = jsonParseAddNode(pParse, JSON_OBJECT, 0, 0); - jsonParseAddNode(pParse, JSON_STRING, nKey, zKey); - pApnd = &pPatch[i+1]; - if( pApnd->eType==JSON_OBJECT ) jsonRemoveAllNulls(pApnd); - nApnd = jsonNodeSize(pApnd); - jsonParseAddNodeArray(pParse, pApnd, jsonNodeSize(pApnd)); - if( pParse->oom ) return 0; - pParse->aNode[iStart].n = 1+nApnd; - pParse->aNode[iRoot].jnFlags |= JNODE_APPEND; - pParse->aNode[iRoot].u.iAppend = iStart; - VVA( pParse->aNode[iRoot].eU = 2 ); - iRoot = iStart; - pTarget = &pParse->aNode[iTarget]; - } } - return pTarget; + if( pTarget->delta ) jsonAfterEditSizeAdjust(pTarget, iTarget); + return pTarget->oom ? JSON_MERGE_OOM : JSON_MERGE_OK; } + /* ** Implementation of the json_mergepatch(JSON1,JSON2) function. Return a JSON ** object that is the result of running the RFC 7396 MergePatch() algorithm @@ -203922,28 +209000,27 @@ static void jsonPatchFunc( int argc, sqlite3_value **argv ){ - JsonParse *pX; /* The JSON that is being patched */ - JsonParse *pY; /* The patch */ - JsonNode *pResult; /* The result of the merge */ + JsonParse *pTarget; /* The TARGET */ + JsonParse *pPatch; /* The PATCH */ + int rc; /* Result code */ UNUSED_PARAMETER(argc); - pX = jsonParseCached(ctx, argv[0], ctx, 1); - if( pX==0 ) return; - assert( pX->hasMod==0 ); - pX->hasMod = 1; - pY = jsonParseCached(ctx, argv[1], ctx, 1); - if( pY==0 ) return; - pX->useMod = 1; - pY->useMod = 1; - pResult = jsonMergePatch(pX, 0, pY->aNode); - assert( pResult!=0 || pX->oom ); - if( pResult && pX->oom==0 ){ - jsonDebugPrintParse(pX); - jsonDebugPrintNode(pResult); - jsonReturnJson(pX, pResult, ctx, 0); - }else{ - sqlite3_result_error_nomem(ctx); + assert( argc==2 ); + pTarget = jsonParseFuncArg(ctx, argv[0], JSON_EDITABLE); + if( pTarget==0 ) return; + pPatch = jsonParseFuncArg(ctx, argv[1], 0); + if( pPatch ){ + rc = jsonMergePatch(pTarget, 0, pPatch, 0); + if( rc==JSON_MERGE_OK ){ + jsonReturnParse(ctx, pTarget); + }else if( rc==JSON_MERGE_OOM ){ + sqlite3_result_error_nomem(ctx); + }else{ + sqlite3_result_error(ctx, "malformed JSON", -1); + } + jsonParseFree(pPatch); } + jsonParseFree(pTarget); } @@ -203967,23 +209044,23 @@ static void jsonObjectFunc( "of arguments", -1); return; } - jsonInit(&jx, ctx); + jsonStringInit(&jx, ctx); jsonAppendChar(&jx, '{'); for(i=0; i1); - if( pParse==0 ) return; - for(i=1; i<(u32)argc; i++){ + p = jsonParseFuncArg(ctx, argv[0], argc>1 ? JSON_EDITABLE : 0); + if( p==0 ) return; + for(i=1; inErr ) goto remove_done; - if( pNode ){ - pNode->jnFlags |= JNODE_REMOVE; - pParse->hasMod = 1; - pParse->useMod = 1; + if( zPath==0 ){ + goto json_remove_done; + } + if( zPath[0]!='$' ){ + goto json_remove_patherror; + } + if( zPath[1]==0 ){ + /* json_remove(j,'$') returns NULL */ + goto json_remove_done; + } + p->eEdit = JEDIT_DEL; + p->delta = 0; + rc = jsonLookupStep(p, 0, zPath+1, 0); + if( JSON_LOOKUP_ISERROR(rc) ){ + if( rc==JSON_LOOKUP_NOTFOUND ){ + continue; /* No-op */ + }else if( rc==JSON_LOOKUP_PATHERROR ){ + jsonBadPathError(ctx, zPath); + }else{ + sqlite3_result_error(ctx, "malformed JSON", -1); + } + goto json_remove_done; } } - if( (pParse->aNode[0].jnFlags & JNODE_REMOVE)==0 ){ - jsonReturnJson(pParse, pParse->aNode, ctx, 1); - } -remove_done: - jsonDebugPrintParse(p); -} + jsonReturnParse(ctx, p); + jsonParseFree(p); + return; -/* -** Substitute the value at iNode with the pValue parameter. -*/ -static void jsonReplaceNode( - sqlite3_context *pCtx, - JsonParse *p, - int iNode, - sqlite3_value *pValue -){ - int idx = jsonParseAddSubstNode(p, iNode); - if( idx<=0 ){ - assert( p->oom ); - return; - } - switch( sqlite3_value_type(pValue) ){ - case SQLITE_NULL: { - jsonParseAddNode(p, JSON_NULL, 0, 0); - break; - } - case SQLITE_FLOAT: { - char *z = sqlite3_mprintf("%!0.15g", sqlite3_value_double(pValue)); - int n; - if( z==0 ){ - p->oom = 1; - break; - } - n = sqlite3Strlen30(z); - jsonParseAddNode(p, JSON_REAL, n, z); - jsonParseAddCleanup(p, sqlite3_free, z); - break; - } - case SQLITE_INTEGER: { - char *z = sqlite3_mprintf("%lld", sqlite3_value_int64(pValue)); - int n; - if( z==0 ){ - p->oom = 1; - break; - } - n = sqlite3Strlen30(z); - jsonParseAddNode(p, JSON_INT, n, z); - jsonParseAddCleanup(p, sqlite3_free, z); +json_remove_patherror: + jsonBadPathError(ctx, zPath); - break; - } - case SQLITE_TEXT: { - const char *z = (const char*)sqlite3_value_text(pValue); - u32 n = (u32)sqlite3_value_bytes(pValue); - if( z==0 ){ - p->oom = 1; - break; - } - if( sqlite3_value_subtype(pValue)!=JSON_SUBTYPE ){ - char *zCopy = sqlite3DbStrDup(0, z); - int k; - if( zCopy ){ - jsonParseAddCleanup(p, sqlite3_free, zCopy); - }else{ - p->oom = 1; - sqlite3_result_error_nomem(pCtx); - } - k = jsonParseAddNode(p, JSON_STRING, n, zCopy); - assert( k>0 || p->oom ); - if( p->oom==0 ) p->aNode[k].jnFlags |= JNODE_RAW; - }else{ - JsonParse *pPatch = jsonParseCached(pCtx, pValue, pCtx, 1); - if( pPatch==0 ){ - p->oom = 1; - break; - } - jsonParseAddNodeArray(p, pPatch->aNode, pPatch->nNode); - /* The nodes copied out of pPatch and into p likely contain - ** u.zJContent pointers into pPatch->zJson. So preserve the - ** content of pPatch until p is destroyed. */ - assert( pPatch->nJPRef>=1 ); - pPatch->nJPRef++; - jsonParseAddCleanup(p, (void(*)(void*))jsonParseFree, pPatch); - } - break; - } - default: { - jsonParseAddNode(p, JSON_NULL, 0, 0); - sqlite3_result_error(pCtx, "JSON cannot hold BLOB values", -1); - p->nErr++; - break; - } - } +json_remove_done: + jsonParseFree(p); + return; } /* @@ -204124,30 +209133,12 @@ static void jsonReplaceFunc( int argc, sqlite3_value **argv ){ - JsonParse *pParse; /* The parse */ - JsonNode *pNode; - const char *zPath; - u32 i; - if( argc<1 ) return; if( (argc&1)==0 ) { jsonWrongNumArgs(ctx, "replace"); return; } - pParse = jsonParseCached(ctx, argv[0], ctx, argc>1); - if( pParse==0 ) return; - for(i=1; i<(u32)argc; i+=2){ - zPath = (const char*)sqlite3_value_text(argv[i]); - pParse->useMod = 1; - pNode = jsonLookup(pParse, zPath, 0, ctx); - if( pParse->nErr ) goto replace_err; - if( pNode ){ - jsonReplaceNode(ctx, pParse, (u32)(pNode - pParse->aNode), argv[i+1]); - } - } - jsonReturnJson(pParse, pParse->aNode, ctx, 1); -replace_err: - jsonDebugPrintParse(pParse); + jsonInsertIntoBlob(ctx, argc, argv, JEDIT_REPL); } @@ -204168,39 +209159,16 @@ static void jsonSetFunc( int argc, sqlite3_value **argv ){ - JsonParse *pParse; /* The parse */ - JsonNode *pNode; - const char *zPath; - u32 i; - int bApnd; - int bIsSet = sqlite3_user_data(ctx)!=0; + + int flags = SQLITE_PTR_TO_INT(sqlite3_user_data(ctx)); + int bIsSet = (flags&JSON_ISSET)!=0; if( argc<1 ) return; if( (argc&1)==0 ) { jsonWrongNumArgs(ctx, bIsSet ? "set" : "insert"); return; } - pParse = jsonParseCached(ctx, argv[0], ctx, argc>1); - if( pParse==0 ) return; - for(i=1; i<(u32)argc; i+=2){ - zPath = (const char*)sqlite3_value_text(argv[i]); - bApnd = 0; - pParse->useMod = 1; - pNode = jsonLookup(pParse, zPath, &bApnd, ctx); - if( pParse->oom ){ - sqlite3_result_error_nomem(ctx); - goto jsonSetDone; - }else if( pParse->nErr ){ - goto jsonSetDone; - }else if( pNode && (bApnd || bIsSet) ){ - jsonReplaceNode(ctx, pParse, (u32)(pNode - pParse->aNode), argv[i+1]); - } - } - jsonDebugPrintParse(pParse); - jsonReturnJson(pParse, pParse->aNode, ctx, 1); - -jsonSetDone: - /* no cleanup required */; + jsonInsertIntoBlob(ctx, argc, argv, bIsSet ? JEDIT_SET : JEDIT_INS); } /* @@ -204216,27 +209184,127 @@ static void jsonTypeFunc( sqlite3_value **argv ){ JsonParse *p; /* The parse */ - const char *zPath; - JsonNode *pNode; + const char *zPath = 0; + u32 i; - p = jsonParseCached(ctx, argv[0], ctx, 0); + p = jsonParseFuncArg(ctx, argv[0], 0); if( p==0 ) return; if( argc==2 ){ zPath = (const char*)sqlite3_value_text(argv[1]); - pNode = jsonLookup(p, zPath, 0, ctx); + if( zPath==0 ) goto json_type_done; + if( zPath[0]!='$' ){ + jsonBadPathError(ctx, zPath); + goto json_type_done; + } + i = jsonLookupStep(p, 0, zPath+1, 0); + if( JSON_LOOKUP_ISERROR(i) ){ + if( i==JSON_LOOKUP_NOTFOUND ){ + /* no-op */ + }else if( i==JSON_LOOKUP_PATHERROR ){ + jsonBadPathError(ctx, zPath); + }else{ + sqlite3_result_error(ctx, "malformed JSON", -1); + } + goto json_type_done; + } }else{ - pNode = p->aNode; + i = 0; } - if( pNode ){ - sqlite3_result_text(ctx, jsonType[pNode->eType], -1, SQLITE_STATIC); + sqlite3_result_text(ctx, jsonbType[p->aBlob[i]&0x0f], -1, SQLITE_STATIC); +json_type_done: + jsonParseFree(p); +} + +/* +** json_pretty(JSON) +** json_pretty(JSON, INDENT) +** +** Return text that is a pretty-printed rendering of the input JSON. +** If the argument is not valid JSON, return NULL. +** +** The INDENT argument is text that is used for indentation. If omitted, +** it defaults to four spaces (the same as PostgreSQL). +*/ +static void jsonPrettyFunc( + sqlite3_context *ctx, + int argc, + sqlite3_value **argv +){ + JsonString s; /* The output string */ + JsonPretty x; /* Pretty printing context */ + + memset(&x, 0, sizeof(x)); + x.pParse = jsonParseFuncArg(ctx, argv[0], 0); + if( x.pParse==0 ) return; + x.pOut = &s; + jsonStringInit(&s, ctx); + if( argc==1 || (x.zIndent = (const char*)sqlite3_value_text(argv[1]))==0 ){ + x.zIndent = " "; + x.szIndent = 4; + }else{ + x.szIndent = (u32)strlen(x.zIndent); } + jsonTranslateBlobToPrettyText(&x, 0); + jsonReturnString(&s, 0, 0); + jsonParseFree(x.pParse); } /* ** json_valid(JSON) -** -** Return 1 if JSON is a well-formed canonical JSON string according -** to RFC-7159. Return 0 otherwise. +** json_valid(JSON, FLAGS) +** +** Check the JSON argument to see if it is well-formed. The FLAGS argument +** encodes the various constraints on what is meant by "well-formed": +** +** 0x01 Canonical RFC-8259 JSON text +** 0x02 JSON text with optional JSON-5 extensions +** 0x04 Superficially appears to be JSONB +** 0x08 Strictly well-formed JSONB +** +** If the FLAGS argument is omitted, it defaults to 1. Useful values for +** FLAGS include: +** +** 1 Strict canonical JSON text +** 2 JSON text perhaps with JSON-5 extensions +** 4 Superficially appears to be JSONB +** 5 Canonical JSON text or superficial JSONB +** 6 JSON-5 text or superficial JSONB +** 8 Strict JSONB +** 9 Canonical JSON text or strict JSONB +** 10 JSON-5 text or strict JSONB +** +** Other flag combinations are redundant. For example, every canonical +** JSON text is also well-formed JSON-5 text, so FLAG values 2 and 3 +** are the same. Similarly, any input that passes a strict JSONB validation +** will also pass the superficial validation so 12 through 15 are the same +** as 8 through 11 respectively. +** +** This routine runs in linear time to validate text and when doing strict +** JSONB validation. Superficial JSONB validation is constant time, +** assuming the BLOB is already in memory. The performance advantage +** of superficial JSONB validation is why that option is provided. +** Application developers can choose to do fast superficial validation or +** slower strict validation, according to their specific needs. +** +** Only the lower four bits of the FLAGS argument are currently used. +** Higher bits are reserved for future expansion. To facilitate +** compatibility, the current implementation raises an error if any bit +** in FLAGS is set other than the lower four bits. +** +** The original circa 2015 implementation of the JSON routines in +** SQLite only supported canonical RFC-8259 JSON text and the json_valid() +** function only accepted one argument. That is why the default value +** for the FLAGS argument is 1, since FLAGS=1 causes this routine to only +** recognize canonical RFC-8259 JSON text as valid. The extra FLAGS +** argument was added when the JSON routines were extended to support +** JSON5-like extensions and binary JSONB stored in BLOBs. +** +** Return Values: +** +** * Raise an error if FLAGS is outside the range of 1 to 15. +** * Return NULL if the input is NULL +** * Return 1 if the input is well-formed. +** * Return 0 if the input is not well-formed. */ static void jsonValidFunc( sqlite3_context *ctx, @@ -204244,79 +209312,128 @@ static void jsonValidFunc( sqlite3_value **argv ){ JsonParse *p; /* The parse */ - UNUSED_PARAMETER(argc); - if( sqlite3_value_type(argv[0])==SQLITE_NULL ){ + u8 flags = 1; + u8 res = 0; + if( argc==2 ){ + i64 f = sqlite3_value_int64(argv[1]); + if( f<1 || f>15 ){ + sqlite3_result_error(ctx, "FLAGS parameter to json_valid() must be" + " between 1 and 15", -1); + return; + } + flags = f & 0x0f; + } + switch( sqlite3_value_type(argv[0]) ){ + case SQLITE_NULL: { #ifdef SQLITE_LEGACY_JSON_VALID - /* Incorrect legacy behavior was to return FALSE for a NULL input */ - sqlite3_result_int(ctx, 0); + /* Incorrect legacy behavior was to return FALSE for a NULL input */ + sqlite3_result_int(ctx, 0); #endif - return; - } - p = jsonParseCached(ctx, argv[0], 0, 0); - if( p==0 || p->oom ){ - sqlite3_result_error_nomem(ctx); - sqlite3_free(p); - }else{ - sqlite3_result_int(ctx, p->nErr==0 && (p->hasNonstd==0 || p->useMod)); - if( p->nErr ) jsonParseFree(p); + return; + } + case SQLITE_BLOB: { + if( jsonFuncArgMightBeBinary(argv[0]) ){ + if( flags & 0x04 ){ + /* Superficial checking only - accomplished by the + ** jsonFuncArgMightBeBinary() call above. */ + res = 1; + }else if( flags & 0x08 ){ + /* Strict checking. Check by translating BLOB->TEXT->BLOB. If + ** no errors occur, call that a "strict check". */ + JsonParse px; + u32 iErr; + memset(&px, 0, sizeof(px)); + px.aBlob = (u8*)sqlite3_value_blob(argv[0]); + px.nBlob = sqlite3_value_bytes(argv[0]); + iErr = jsonbValidityCheck(&px, 0, px.nBlob, 1); + res = iErr==0; + } + break; + } + /* Fall through into interpreting the input as text. See note + ** above at tag-20240123-a. */ + /* no break */ deliberate_fall_through + } + default: { + JsonParse px; + if( (flags & 0x3)==0 ) break; + memset(&px, 0, sizeof(px)); + + p = jsonParseFuncArg(ctx, argv[0], JSON_KEEPERROR); + if( p ){ + if( p->oom ){ + sqlite3_result_error_nomem(ctx); + }else if( p->nErr ){ + /* no-op */ + }else if( (flags & 0x02)!=0 || p->hasNonstd==0 ){ + res = 1; + } + jsonParseFree(p); + }else{ + sqlite3_result_error_nomem(ctx); + } + break; + } } + sqlite3_result_int(ctx, res); } /* ** json_error_position(JSON) ** -** If the argument is not an interpretable JSON string, then return the 1-based -** character position at which the parser first recognized that the input -** was in error. The left-most character is 1. If the string is valid -** JSON, then return 0. -** -** Note that json_valid() is only true for strictly conforming canonical JSON. -** But this routine returns zero if the input contains extension. Thus: -** -** (1) If the input X is strictly conforming canonical JSON: -** -** json_valid(X) returns true -** json_error_position(X) returns 0 +** If the argument is NULL, return NULL ** -** (2) If the input X is JSON but it includes extension (such as JSON5) that -** are not part of RFC-8259: +** If the argument is BLOB, do a full validity check and return non-zero +** if the check fails. The return value is the approximate 1-based offset +** to the byte of the element that contains the first error. ** -** json_valid(X) returns false -** json_error_position(X) return 0 -** -** (3) If the input X cannot be interpreted as JSON even taking extensions -** into account: -** -** json_valid(X) return false -** json_error_position(X) returns 1 or more +** Otherwise interpret the argument is TEXT (even if it is numeric) and +** return the 1-based character position for where the parser first recognized +** that the input was not valid JSON, or return 0 if the input text looks +** ok. JSON-5 extensions are accepted. */ static void jsonErrorFunc( sqlite3_context *ctx, int argc, sqlite3_value **argv ){ - JsonParse *p; /* The parse */ + i64 iErrPos = 0; /* Error position to be returned */ + JsonParse s; + + assert( argc==1 ); UNUSED_PARAMETER(argc); - if( sqlite3_value_type(argv[0])==SQLITE_NULL ) return; - p = jsonParseCached(ctx, argv[0], 0, 0); - if( p==0 || p->oom ){ + memset(&s, 0, sizeof(s)); + s.db = sqlite3_context_db_handle(ctx); + if( jsonFuncArgMightBeBinary(argv[0]) ){ + s.aBlob = (u8*)sqlite3_value_blob(argv[0]); + s.nBlob = sqlite3_value_bytes(argv[0]); + iErrPos = (i64)jsonbValidityCheck(&s, 0, s.nBlob, 1); + }else{ + s.zJson = (char*)sqlite3_value_text(argv[0]); + if( s.zJson==0 ) return; /* NULL input or OOM */ + s.nJson = sqlite3_value_bytes(argv[0]); + if( jsonConvertTextToBlob(&s,0) ){ + if( s.oom ){ + iErrPos = -1; + }else{ + /* Convert byte-offset s.iErr into a character offset */ + u32 k; + assert( s.zJson!=0 ); /* Because s.oom is false */ + for(k=0; knErr==0 ){ - sqlite3_result_int(ctx, 0); }else{ - int n = 1; - u32 i; - const char *z = (const char*)sqlite3_value_text(argv[0]); - for(i=0; iiErr && ALWAYS(z[i]); i++){ - if( (z[i]&0xc0)!=0x80 ) n++; - } - sqlite3_result_int(ctx, n); - jsonParseFree(p); + sqlite3_result_int64(ctx, iErrPos); } } - /**************************************************************************** ** Aggregate SQL function implementations ****************************************************************************/ @@ -204335,32 +209452,42 @@ static void jsonArrayStep( pStr = (JsonString*)sqlite3_aggregate_context(ctx, sizeof(*pStr)); if( pStr ){ if( pStr->zBuf==0 ){ - jsonInit(pStr, ctx); + jsonStringInit(pStr, ctx); jsonAppendChar(pStr, '['); }else if( pStr->nUsed>1 ){ jsonAppendChar(pStr, ','); } pStr->pCtx = ctx; - jsonAppendValue(pStr, argv[0]); + jsonAppendSqlValue(pStr, argv[0]); } } static void jsonArrayCompute(sqlite3_context *ctx, int isFinal){ JsonString *pStr; pStr = (JsonString*)sqlite3_aggregate_context(ctx, 0); if( pStr ){ + int flags; pStr->pCtx = ctx; jsonAppendChar(pStr, ']'); - if( pStr->bErr ){ - if( pStr->bErr==1 ) sqlite3_result_error_nomem(ctx); - assert( pStr->bStatic ); + flags = SQLITE_PTR_TO_INT(sqlite3_user_data(ctx)); + if( pStr->eErr ){ + jsonReturnString(pStr, 0, 0); + return; + }else if( flags & JSON_BLOB ){ + jsonReturnStringAsBlob(pStr); + if( isFinal ){ + if( !pStr->bStatic ) sqlite3RCStrUnref(pStr->zBuf); + }else{ + jsonStringTrimOneChar(pStr); + } + return; }else if( isFinal ){ sqlite3_result_text(ctx, pStr->zBuf, (int)pStr->nUsed, pStr->bStatic ? SQLITE_TRANSIENT : - (void(*)(void*))sqlite3RCStrUnref); + sqlite3RCStrUnref); pStr->bStatic = 1; }else{ sqlite3_result_text(ctx, pStr->zBuf, (int)pStr->nUsed, SQLITE_TRANSIENT); - pStr->nUsed--; + jsonStringTrimOneChar(pStr); } }else{ sqlite3_result_text(ctx, "[]", 2, SQLITE_STATIC); @@ -204441,35 +209568,46 @@ static void jsonObjectStep( pStr = (JsonString*)sqlite3_aggregate_context(ctx, sizeof(*pStr)); if( pStr ){ if( pStr->zBuf==0 ){ - jsonInit(pStr, ctx); + jsonStringInit(pStr, ctx); jsonAppendChar(pStr, '{'); }else if( pStr->nUsed>1 ){ jsonAppendChar(pStr, ','); } pStr->pCtx = ctx; z = (const char*)sqlite3_value_text(argv[0]); - n = (u32)sqlite3_value_bytes(argv[0]); + n = sqlite3Strlen30(z); jsonAppendString(pStr, z, n); jsonAppendChar(pStr, ':'); - jsonAppendValue(pStr, argv[1]); + jsonAppendSqlValue(pStr, argv[1]); } } static void jsonObjectCompute(sqlite3_context *ctx, int isFinal){ JsonString *pStr; pStr = (JsonString*)sqlite3_aggregate_context(ctx, 0); if( pStr ){ + int flags; jsonAppendChar(pStr, '}'); - if( pStr->bErr ){ - if( pStr->bErr==1 ) sqlite3_result_error_nomem(ctx); - assert( pStr->bStatic ); + pStr->pCtx = ctx; + flags = SQLITE_PTR_TO_INT(sqlite3_user_data(ctx)); + if( pStr->eErr ){ + jsonReturnString(pStr, 0, 0); + return; + }else if( flags & JSON_BLOB ){ + jsonReturnStringAsBlob(pStr); + if( isFinal ){ + if( !pStr->bStatic ) sqlite3RCStrUnref(pStr->zBuf); + }else{ + jsonStringTrimOneChar(pStr); + } + return; }else if( isFinal ){ sqlite3_result_text(ctx, pStr->zBuf, (int)pStr->nUsed, pStr->bStatic ? SQLITE_TRANSIENT : - (void(*)(void*))sqlite3RCStrUnref); + sqlite3RCStrUnref); pStr->bStatic = 1; }else{ sqlite3_result_text(ctx, pStr->zBuf, (int)pStr->nUsed, SQLITE_TRANSIENT); - pStr->nUsed--; + jsonStringTrimOneChar(pStr); } }else{ sqlite3_result_text(ctx, "{}", 2, SQLITE_STATIC); @@ -204489,19 +209627,37 @@ static void jsonObjectFinal(sqlite3_context *ctx){ /**************************************************************************** ** The json_each virtual table ****************************************************************************/ +typedef struct JsonParent JsonParent; +struct JsonParent { + u32 iHead; /* Start of object or array */ + u32 iValue; /* Start of the value */ + u32 iEnd; /* First byte past the end */ + u32 nPath; /* Length of path */ + i64 iKey; /* Key for JSONB_ARRAY */ +}; + typedef struct JsonEachCursor JsonEachCursor; struct JsonEachCursor { sqlite3_vtab_cursor base; /* Base class - must be first */ u32 iRowid; /* The rowid */ - u32 iBegin; /* The first node of the scan */ - u32 i; /* Index in sParse.aNode[] of current row */ + u32 i; /* Index in sParse.aBlob[] of current row */ u32 iEnd; /* EOF when i equals or exceeds this value */ - u8 eType; /* Type of top-level element */ + u32 nRoot; /* Size of the root path in bytes */ + u8 eType; /* Type of the container for element i */ u8 bRecursive; /* True for json_tree(). False for json_each() */ - char *zJson; /* Input JSON */ - char *zRoot; /* Path by which to filter zJson */ + u32 nParent; /* Current nesting depth */ + u32 nParentAlloc; /* Space allocated for aParent[] */ + JsonParent *aParent; /* Parent elements of i */ + sqlite3 *db; /* Database connection */ + JsonString path; /* Current path */ JsonParse sParse; /* Parse of the input JSON */ }; +typedef struct JsonEachConnection JsonEachConnection; +struct JsonEachConnection { + sqlite3_vtab base; /* Base class - must be first */ + sqlite3 *db; /* Database connection */ +}; + /* Constructor for the json_each virtual table */ static int jsonEachConnect( @@ -204511,7 +209667,7 @@ static int jsonEachConnect( sqlite3_vtab **ppVtab, char **pzErr ){ - sqlite3_vtab *pNew; + JsonEachConnection *pNew; int rc; /* Column numbers */ @@ -204537,28 +209693,32 @@ static int jsonEachConnect( "CREATE TABLE x(key,value,type,atom,id,parent,fullkey,path," "json HIDDEN,root HIDDEN)"); if( rc==SQLITE_OK ){ - pNew = *ppVtab = sqlite3_malloc( sizeof(*pNew) ); + pNew = (JsonEachConnection*)sqlite3DbMallocZero(db, sizeof(*pNew)); + *ppVtab = (sqlite3_vtab*)pNew; if( pNew==0 ) return SQLITE_NOMEM; - memset(pNew, 0, sizeof(*pNew)); sqlite3_vtab_config(db, SQLITE_VTAB_INNOCUOUS); + pNew->db = db; } return rc; } /* destructor for json_each virtual table */ static int jsonEachDisconnect(sqlite3_vtab *pVtab){ - sqlite3_free(pVtab); + JsonEachConnection *p = (JsonEachConnection*)pVtab; + sqlite3DbFree(p->db, pVtab); return SQLITE_OK; } /* constructor for a JsonEachCursor object for json_each(). */ static int jsonEachOpenEach(sqlite3_vtab *p, sqlite3_vtab_cursor **ppCursor){ + JsonEachConnection *pVtab = (JsonEachConnection*)p; JsonEachCursor *pCur; UNUSED_PARAMETER(p); - pCur = sqlite3_malloc( sizeof(*pCur) ); + pCur = sqlite3DbMallocZero(pVtab->db, sizeof(*pCur)); if( pCur==0 ) return SQLITE_NOMEM; - memset(pCur, 0, sizeof(*pCur)); + pCur->db = pVtab->db; + jsonStringZero(&pCur->path); *ppCursor = &pCur->base; return SQLITE_OK; } @@ -204576,21 +209736,24 @@ static int jsonEachOpenTree(sqlite3_vtab *p, sqlite3_vtab_cursor **ppCursor){ /* Reset a JsonEachCursor back to its original state. Free any memory ** held. */ static void jsonEachCursorReset(JsonEachCursor *p){ - sqlite3_free(p->zRoot); jsonParseReset(&p->sParse); + jsonStringReset(&p->path); + sqlite3DbFree(p->db, p->aParent); p->iRowid = 0; p->i = 0; + p->aParent = 0; + p->nParent = 0; + p->nParentAlloc = 0; p->iEnd = 0; p->eType = 0; - p->zJson = 0; - p->zRoot = 0; } /* Destructor for a jsonEachCursor object */ static int jsonEachClose(sqlite3_vtab_cursor *cur){ JsonEachCursor *p = (JsonEachCursor*)cur; jsonEachCursorReset(p); - sqlite3_free(cur); + + sqlite3DbFree(p->db, cur); return SQLITE_OK; } @@ -204601,200 +209764,233 @@ static int jsonEachEof(sqlite3_vtab_cursor *cur){ return p->i >= p->iEnd; } -/* Advance the cursor to the next element for json_tree() */ -static int jsonEachNext(sqlite3_vtab_cursor *cur){ - JsonEachCursor *p = (JsonEachCursor*)cur; - if( p->bRecursive ){ - if( p->sParse.aNode[p->i].jnFlags & JNODE_LABEL ) p->i++; - p->i++; - p->iRowid++; - if( p->iiEnd ){ - u32 iUp = p->sParse.aUp[p->i]; - JsonNode *pUp = &p->sParse.aNode[iUp]; - p->eType = pUp->eType; - if( pUp->eType==JSON_ARRAY ){ - assert( pUp->eU==0 || pUp->eU==3 ); - testcase( pUp->eU==3 ); - VVA( pUp->eU = 3 ); - if( iUp==p->i-1 ){ - pUp->u.iKey = 0; - }else{ - pUp->u.iKey++; +/* +** If the cursor is currently pointing at the label of a object entry, +** then return the index of the value. For all other cases, return the +** current pointer position, which is the value. +*/ +static int jsonSkipLabel(JsonEachCursor *p){ + if( p->eType==JSONB_OBJECT ){ + u32 sz = 0; + u32 n = jsonbPayloadSize(&p->sParse, p->i, &sz); + return p->i + n + sz; + }else{ + return p->i; + } +} + +/* +** Append the path name for the current element. +*/ +static void jsonAppendPathName(JsonEachCursor *p){ + assert( p->nParent>0 ); + assert( p->eType==JSONB_ARRAY || p->eType==JSONB_OBJECT ); + if( p->eType==JSONB_ARRAY ){ + jsonPrintf(30, &p->path, "[%lld]", p->aParent[p->nParent-1].iKey); + }else{ + u32 n, sz = 0, k, i; + const char *z; + int needQuote = 0; + n = jsonbPayloadSize(&p->sParse, p->i, &sz); + k = p->i + n; + z = (const char*)&p->sParse.aBlob[k]; + if( sz==0 || !sqlite3Isalpha(z[0]) ){ + needQuote = 1; + }else{ + for(i=0; ieType ){ - case JSON_ARRAY: { - p->i += jsonNodeSize(&p->sParse.aNode[p->i]); - p->iRowid++; - break; - } - case JSON_OBJECT: { - p->i += 1 + jsonNodeSize(&p->sParse.aNode[p->i+1]); - p->iRowid++; - break; - } - default: { - p->i = p->iEnd; - break; - } + if( needQuote ){ + jsonPrintf(sz+4,&p->path,".\"%.*s\"", sz, z); + }else{ + jsonPrintf(sz+2,&p->path,".%.*s", sz, z); } } - return SQLITE_OK; } -/* Append an object label to the JSON Path being constructed -** in pStr. -*/ -static void jsonAppendObjectPathElement( - JsonString *pStr, - JsonNode *pNode -){ - int jj, nn; - const char *z; - assert( pNode->eType==JSON_STRING ); - assert( pNode->jnFlags & JNODE_LABEL ); - assert( pNode->eU==1 ); - z = pNode->u.zJContent; - nn = pNode->n; - if( (pNode->jnFlags & JNODE_RAW)==0 ){ - assert( nn>=2 ); - assert( z[0]=='"' || z[0]=='\'' ); - assert( z[nn-1]=='"' || z[0]=='\'' ); - if( nn>2 && sqlite3Isalpha(z[1]) ){ - for(jj=2; jjbRecursive ){ + u8 x; + u8 levelChange = 0; + u32 n, sz = 0; + u32 i = jsonSkipLabel(p); + x = p->sParse.aBlob[i] & 0x0f; + n = jsonbPayloadSize(&p->sParse, i, &sz); + if( x==JSONB_OBJECT || x==JSONB_ARRAY ){ + JsonParent *pParent; + if( p->nParent>=p->nParentAlloc ){ + JsonParent *pNew; + u64 nNew; + nNew = p->nParentAlloc*2 + 3; + pNew = sqlite3DbRealloc(p->db, p->aParent, sizeof(JsonParent)*nNew); + if( pNew==0 ) return SQLITE_NOMEM; + p->nParentAlloc = (u32)nNew; + p->aParent = pNew; + } + levelChange = 1; + pParent = &p->aParent[p->nParent]; + pParent->iHead = p->i; + pParent->iValue = i; + pParent->iEnd = i + n + sz; + pParent->iKey = -1; + pParent->nPath = (u32)p->path.nUsed; + if( p->eType && p->nParent ){ + jsonAppendPathName(p); + if( p->path.eErr ) rc = SQLITE_NOMEM; + } + p->nParent++; + p->i = i + n; + }else{ + p->i = i + n + sz; + } + while( p->nParent>0 && p->i >= p->aParent[p->nParent-1].iEnd ){ + p->nParent--; + p->path.nUsed = p->aParent[p->nParent].nPath; + levelChange = 1; + } + if( levelChange ){ + if( p->nParent>0 ){ + JsonParent *pParent = &p->aParent[p->nParent-1]; + u32 iVal = pParent->iValue; + p->eType = p->sParse.aBlob[iVal] & 0x0f; + }else{ + p->eType = 0; } } + }else{ + u32 n, sz = 0; + u32 i = jsonSkipLabel(p); + n = jsonbPayloadSize(&p->sParse, i, &sz); + p->i = i + n + sz; + } + if( p->eType==JSONB_ARRAY && p->nParent ){ + p->aParent[p->nParent-1].iKey++; } - jsonPrintf(nn+2, pStr, ".%.*s", nn, z); + p->iRowid++; + return rc; } -/* Append the name of the path for element i to pStr +/* Length of the path for rowid==0 in bRecursive mode. */ -static void jsonEachComputePath( - JsonEachCursor *p, /* The cursor */ - JsonString *pStr, /* Write the path here */ - u32 i /* Path to this element */ -){ - JsonNode *pNode, *pUp; - u32 iUp; - if( i==0 ){ - jsonAppendChar(pStr, '$'); - return; - } - iUp = p->sParse.aUp[i]; - jsonEachComputePath(p, pStr, iUp); - pNode = &p->sParse.aNode[i]; - pUp = &p->sParse.aNode[iUp]; - if( pUp->eType==JSON_ARRAY ){ - assert( pUp->eU==3 || (pUp->eU==0 && pUp->u.iKey==0) ); - testcase( pUp->eU==0 ); - jsonPrintf(30, pStr, "[%d]", pUp->u.iKey); - }else{ - assert( pUp->eType==JSON_OBJECT ); - if( (pNode->jnFlags & JNODE_LABEL)==0 ) pNode--; - jsonAppendObjectPathElement(pStr, pNode); +static int jsonEachPathLength(JsonEachCursor *p){ + u32 n = p->path.nUsed; + char *z = p->path.zBuf; + if( p->iRowid==0 && p->bRecursive && n>=2 ){ + while( n>1 ){ + n--; + if( z[n]=='[' || z[n]=='.' ){ + u32 x, sz = 0; + char cSaved = z[n]; + z[n] = 0; + assert( p->sParse.eEdit==0 ); + x = jsonLookupStep(&p->sParse, 0, z+1, 0); + z[n] = cSaved; + if( JSON_LOOKUP_ISERROR(x) ) continue; + if( x + jsonbPayloadSize(&p->sParse, x, &sz) == p->i ) break; + } + } } + return n; } /* Return the value of a column */ static int jsonEachColumn( sqlite3_vtab_cursor *cur, /* The cursor */ sqlite3_context *ctx, /* First argument to sqlite3_result_...() */ - int i /* Which column to return */ + int iColumn /* Which column to return */ ){ JsonEachCursor *p = (JsonEachCursor*)cur; - JsonNode *pThis = &p->sParse.aNode[p->i]; - switch( i ){ + switch( iColumn ){ case JEACH_KEY: { - if( p->i==0 ) break; - if( p->eType==JSON_OBJECT ){ - jsonReturn(&p->sParse, pThis, ctx); - }else if( p->eType==JSON_ARRAY ){ - u32 iKey; - if( p->bRecursive ){ - if( p->iRowid==0 ) break; - assert( p->sParse.aNode[p->sParse.aUp[p->i]].eU==3 ); - iKey = p->sParse.aNode[p->sParse.aUp[p->i]].u.iKey; + if( p->nParent==0 ){ + u32 n, j; + if( p->nRoot==1 ) break; + j = jsonEachPathLength(p); + n = p->nRoot - j; + if( n==0 ){ + break; + }else if( p->path.zBuf[j]=='[' ){ + i64 x; + sqlite3Atoi64(&p->path.zBuf[j+1], &x, n-1, SQLITE_UTF8); + sqlite3_result_int64(ctx, x); + }else if( p->path.zBuf[j+1]=='"' ){ + sqlite3_result_text(ctx, &p->path.zBuf[j+2], n-3, SQLITE_TRANSIENT); }else{ - iKey = p->iRowid; + sqlite3_result_text(ctx, &p->path.zBuf[j+1], n-1, SQLITE_TRANSIENT); } - sqlite3_result_int64(ctx, (sqlite3_int64)iKey); + break; + } + if( p->eType==JSONB_OBJECT ){ + jsonReturnFromBlob(&p->sParse, p->i, ctx, 1); + }else{ + assert( p->eType==JSONB_ARRAY ); + sqlite3_result_int64(ctx, p->aParent[p->nParent-1].iKey); } break; } case JEACH_VALUE: { - if( pThis->jnFlags & JNODE_LABEL ) pThis++; - jsonReturn(&p->sParse, pThis, ctx); + u32 i = jsonSkipLabel(p); + jsonReturnFromBlob(&p->sParse, i, ctx, 1); + if( (p->sParse.aBlob[i] & 0x0f)>=JSONB_ARRAY ){ + sqlite3_result_subtype(ctx, JSON_SUBTYPE); + } break; } case JEACH_TYPE: { - if( pThis->jnFlags & JNODE_LABEL ) pThis++; - sqlite3_result_text(ctx, jsonType[pThis->eType], -1, SQLITE_STATIC); + u32 i = jsonSkipLabel(p); + u8 eType = p->sParse.aBlob[i] & 0x0f; + sqlite3_result_text(ctx, jsonbType[eType], -1, SQLITE_STATIC); break; } case JEACH_ATOM: { - if( pThis->jnFlags & JNODE_LABEL ) pThis++; - if( pThis->eType>=JSON_ARRAY ) break; - jsonReturn(&p->sParse, pThis, ctx); + u32 i = jsonSkipLabel(p); + if( (p->sParse.aBlob[i] & 0x0f)sParse, i, ctx, 1); + } break; } case JEACH_ID: { - sqlite3_result_int64(ctx, - (sqlite3_int64)p->i + ((pThis->jnFlags & JNODE_LABEL)!=0)); + sqlite3_result_int64(ctx, (sqlite3_int64)p->i); break; } case JEACH_PARENT: { - if( p->i>p->iBegin && p->bRecursive ){ - sqlite3_result_int64(ctx, (sqlite3_int64)p->sParse.aUp[p->i]); + if( p->nParent>0 && p->bRecursive ){ + sqlite3_result_int64(ctx, p->aParent[p->nParent-1].iHead); } break; } case JEACH_FULLKEY: { - JsonString x; - jsonInit(&x, ctx); - if( p->bRecursive ){ - jsonEachComputePath(p, &x, p->i); - }else{ - if( p->zRoot ){ - jsonAppendRaw(&x, p->zRoot, (int)strlen(p->zRoot)); - }else{ - jsonAppendChar(&x, '$'); - } - if( p->eType==JSON_ARRAY ){ - jsonPrintf(30, &x, "[%d]", p->iRowid); - }else if( p->eType==JSON_OBJECT ){ - jsonAppendObjectPathElement(&x, pThis); - } - } - jsonResult(&x); + u64 nBase = p->path.nUsed; + if( p->nParent ) jsonAppendPathName(p); + sqlite3_result_text64(ctx, p->path.zBuf, p->path.nUsed, + SQLITE_TRANSIENT, SQLITE_UTF8); + p->path.nUsed = nBase; break; } case JEACH_PATH: { - if( p->bRecursive ){ - JsonString x; - jsonInit(&x, ctx); - jsonEachComputePath(p, &x, p->sParse.aUp[p->i]); - jsonResult(&x); - break; - } - /* For json_each() path and root are the same so fall through - ** into the root case */ - /* no break */ deliberate_fall_through + u32 n = jsonEachPathLength(p); + sqlite3_result_text64(ctx, p->path.zBuf, n, + SQLITE_TRANSIENT, SQLITE_UTF8); + break; } default: { - const char *zRoot = p->zRoot; - if( zRoot==0 ) zRoot = "$"; - sqlite3_result_text(ctx, zRoot, -1, SQLITE_STATIC); + sqlite3_result_text(ctx, p->path.zBuf, p->nRoot, SQLITE_STATIC); break; } case JEACH_JSON: { - assert( i==JEACH_JSON ); - sqlite3_result_text(ctx, p->sParse.zJson, -1, SQLITE_STATIC); + if( p->sParse.zJson==0 ){ + sqlite3_result_blob(ctx, p->sParse.aBlob, p->sParse.nBlob, + SQLITE_TRANSIENT); + }else{ + sqlite3_result_text(ctx, p->sParse.zJson, -1, SQLITE_TRANSIENT); + } break; } } @@ -204885,86 +210081,97 @@ static int jsonEachFilter( int argc, sqlite3_value **argv ){ JsonEachCursor *p = (JsonEachCursor*)cur; - const char *z; const char *zRoot = 0; - sqlite3_int64 n; + u32 i, n, sz; UNUSED_PARAMETER(idxStr); UNUSED_PARAMETER(argc); jsonEachCursorReset(p); if( idxNum==0 ) return SQLITE_OK; - z = (const char*)sqlite3_value_text(argv[0]); - if( z==0 ) return SQLITE_OK; memset(&p->sParse, 0, sizeof(p->sParse)); p->sParse.nJPRef = 1; - if( sqlite3ValueIsOfClass(argv[0], (void(*)(void*))sqlite3RCStrUnref) ){ - p->sParse.zJson = sqlite3RCStrRef((char*)z); - }else{ - n = sqlite3_value_bytes(argv[0]); - p->sParse.zJson = sqlite3RCStrNew( n+1 ); - if( p->sParse.zJson==0 ) return SQLITE_NOMEM; - memcpy(p->sParse.zJson, z, (size_t)n+1); - } - p->sParse.bJsonIsRCStr = 1; - p->zJson = p->sParse.zJson; - if( jsonParse(&p->sParse, 0) ){ - int rc = SQLITE_NOMEM; - if( p->sParse.oom==0 ){ - sqlite3_free(cur->pVtab->zErrMsg); - cur->pVtab->zErrMsg = sqlite3_mprintf("malformed JSON"); - if( cur->pVtab->zErrMsg ) rc = SQLITE_ERROR; + p->sParse.db = p->db; + if( jsonFuncArgMightBeBinary(argv[0]) ){ + p->sParse.nBlob = sqlite3_value_bytes(argv[0]); + p->sParse.aBlob = (u8*)sqlite3_value_blob(argv[0]); + }else{ + p->sParse.zJson = (char*)sqlite3_value_text(argv[0]); + p->sParse.nJson = sqlite3_value_bytes(argv[0]); + if( p->sParse.zJson==0 ){ + p->i = p->iEnd = 0; + return SQLITE_OK; } - jsonEachCursorReset(p); - return rc; - }else if( p->bRecursive && jsonParseFindParents(&p->sParse) ){ - jsonEachCursorReset(p); - return SQLITE_NOMEM; - }else{ - JsonNode *pNode = 0; - if( idxNum==3 ){ - const char *zErr = 0; - zRoot = (const char*)sqlite3_value_text(argv[1]); - if( zRoot==0 ) return SQLITE_OK; - n = sqlite3_value_bytes(argv[1]); - p->zRoot = sqlite3_malloc64( n+1 ); - if( p->zRoot==0 ) return SQLITE_NOMEM; - memcpy(p->zRoot, zRoot, (size_t)n+1); - if( zRoot[0]!='$' ){ - zErr = zRoot; - }else{ - pNode = jsonLookupStep(&p->sParse, 0, p->zRoot+1, 0, &zErr); + if( jsonConvertTextToBlob(&p->sParse, 0) ){ + if( p->sParse.oom ){ + return SQLITE_NOMEM; } - if( zErr ){ + goto json_each_malformed_input; + } + } + if( idxNum==3 ){ + zRoot = (const char*)sqlite3_value_text(argv[1]); + if( zRoot==0 ) return SQLITE_OK; + if( zRoot[0]!='$' ){ + sqlite3_free(cur->pVtab->zErrMsg); + cur->pVtab->zErrMsg = jsonBadPathError(0, zRoot); + jsonEachCursorReset(p); + return cur->pVtab->zErrMsg ? SQLITE_ERROR : SQLITE_NOMEM; + } + p->nRoot = sqlite3Strlen30(zRoot); + if( zRoot[1]==0 ){ + i = p->i = 0; + p->eType = 0; + }else{ + i = jsonLookupStep(&p->sParse, 0, zRoot+1, 0); + if( JSON_LOOKUP_ISERROR(i) ){ + if( i==JSON_LOOKUP_NOTFOUND ){ + p->i = 0; + p->eType = 0; + p->iEnd = 0; + return SQLITE_OK; + } sqlite3_free(cur->pVtab->zErrMsg); - cur->pVtab->zErrMsg = jsonPathSyntaxError(zErr); + cur->pVtab->zErrMsg = jsonBadPathError(0, zRoot); jsonEachCursorReset(p); return cur->pVtab->zErrMsg ? SQLITE_ERROR : SQLITE_NOMEM; - }else if( pNode==0 ){ - return SQLITE_OK; } - }else{ - pNode = p->sParse.aNode; - } - p->iBegin = p->i = (int)(pNode - p->sParse.aNode); - p->eType = pNode->eType; - if( p->eType>=JSON_ARRAY ){ - assert( pNode->eU==0 ); - VVA( pNode->eU = 3 ); - pNode->u.iKey = 0; - p->iEnd = p->i + pNode->n + 1; - if( p->bRecursive ){ - p->eType = p->sParse.aNode[p->sParse.aUp[p->i]].eType; - if( p->i>0 && (p->sParse.aNode[p->i-1].jnFlags & JNODE_LABEL)!=0 ){ - p->i--; - } + if( p->sParse.iLabel ){ + p->i = p->sParse.iLabel; + p->eType = JSONB_OBJECT; }else{ - p->i++; - } - }else{ - p->iEnd = p->i+1; - } + p->i = i; + p->eType = JSONB_ARRAY; + } + } + jsonAppendRaw(&p->path, zRoot, p->nRoot); + }else{ + i = p->i = 0; + p->eType = 0; + p->nRoot = 1; + jsonAppendRaw(&p->path, "$", 1); + } + p->nParent = 0; + n = jsonbPayloadSize(&p->sParse, i, &sz); + p->iEnd = i+n+sz; + if( (p->sParse.aBlob[i] & 0x0f)>=JSONB_ARRAY && !p->bRecursive ){ + p->i = i + n; + p->eType = p->sParse.aBlob[i] & 0x0f; + p->aParent = sqlite3DbMallocZero(p->db, sizeof(JsonParent)); + if( p->aParent==0 ) return SQLITE_NOMEM; + p->nParent = 1; + p->nParentAlloc = 1; + p->aParent[0].iKey = 0; + p->aParent[0].iEnd = p->iEnd; + p->aParent[0].iHead = p->i; + p->aParent[0].iValue = i; } return SQLITE_OK; + +json_each_malformed_input: + sqlite3_free(cur->pVtab->zErrMsg); + cur->pVtab->zErrMsg = sqlite3_mprintf("malformed JSON"); + jsonEachCursorReset(p); + return cur->pVtab->zErrMsg ? SQLITE_ERROR : SQLITE_NOMEM; } /* The methods of the json_each virtual table */ @@ -204992,7 +210199,8 @@ static sqlite3_module jsonEachModule = { 0, /* xSavepoint */ 0, /* xRelease */ 0, /* xRollbackTo */ - 0 /* xShadowName */ + 0, /* xShadowName */ + 0 /* xIntegrity */ }; /* The methods of the json_tree virtual table. */ @@ -205020,7 +210228,8 @@ static sqlite3_module jsonTreeModule = { 0, /* xSavepoint */ 0, /* xRelease */ 0, /* xRollbackTo */ - 0 /* xShadowName */ + 0, /* xShadowName */ + 0 /* xIntegrity */ }; #endif /* SQLITE_OMIT_VIRTUALTABLE */ #endif /* !defined(SQLITE_OMIT_JSON) */ @@ -205031,34 +210240,59 @@ static sqlite3_module jsonTreeModule = { SQLITE_PRIVATE void sqlite3RegisterJsonFunctions(void){ #ifndef SQLITE_OMIT_JSON static FuncDef aJsonFunc[] = { - JFUNCTION(json, 1, 0, jsonRemoveFunc), - JFUNCTION(json_array, -1, 0, jsonArrayFunc), - JFUNCTION(json_array_length, 1, 0, jsonArrayLengthFunc), - JFUNCTION(json_array_length, 2, 0, jsonArrayLengthFunc), - JFUNCTION(json_error_position,1, 0, jsonErrorFunc), - JFUNCTION(json_extract, -1, 0, jsonExtractFunc), - JFUNCTION(->, 2, JSON_JSON, jsonExtractFunc), - JFUNCTION(->>, 2, JSON_SQL, jsonExtractFunc), - JFUNCTION(json_insert, -1, 0, jsonSetFunc), - JFUNCTION(json_object, -1, 0, jsonObjectFunc), - JFUNCTION(json_patch, 2, 0, jsonPatchFunc), - JFUNCTION(json_quote, 1, 0, jsonQuoteFunc), - JFUNCTION(json_remove, -1, 0, jsonRemoveFunc), - JFUNCTION(json_replace, -1, 0, jsonReplaceFunc), - JFUNCTION(json_set, -1, JSON_ISSET, jsonSetFunc), - JFUNCTION(json_type, 1, 0, jsonTypeFunc), - JFUNCTION(json_type, 2, 0, jsonTypeFunc), - JFUNCTION(json_valid, 1, 0, jsonValidFunc), + /* sqlite3_result_subtype() ----, ,--- sqlite3_value_subtype() */ + /* | | */ + /* Uses cache ------, | | ,---- Returns JSONB */ + /* | | | | */ + /* Number of arguments ---, | | | | ,--- Flags */ + /* | | | | | | */ + JFUNCTION(json, 1,1,1, 0,0,0, jsonRemoveFunc), + JFUNCTION(jsonb, 1,1,0, 0,1,0, jsonRemoveFunc), + JFUNCTION(json_array, -1,0,1, 1,0,0, jsonArrayFunc), + JFUNCTION(jsonb_array, -1,0,1, 1,1,0, jsonArrayFunc), + JFUNCTION(json_array_length, 1,1,0, 0,0,0, jsonArrayLengthFunc), + JFUNCTION(json_array_length, 2,1,0, 0,0,0, jsonArrayLengthFunc), + JFUNCTION(json_error_position,1,1,0, 0,0,0, jsonErrorFunc), + JFUNCTION(json_extract, -1,1,1, 0,0,0, jsonExtractFunc), + JFUNCTION(jsonb_extract, -1,1,0, 0,1,0, jsonExtractFunc), + JFUNCTION(->, 2,1,1, 0,0,JSON_JSON, jsonExtractFunc), + JFUNCTION(->>, 2,1,0, 0,0,JSON_SQL, jsonExtractFunc), + JFUNCTION(json_insert, -1,1,1, 1,0,0, jsonSetFunc), + JFUNCTION(jsonb_insert, -1,1,0, 1,1,0, jsonSetFunc), + JFUNCTION(json_object, -1,0,1, 1,0,0, jsonObjectFunc), + JFUNCTION(jsonb_object, -1,0,1, 1,1,0, jsonObjectFunc), + JFUNCTION(json_patch, 2,1,1, 0,0,0, jsonPatchFunc), + JFUNCTION(jsonb_patch, 2,1,0, 0,1,0, jsonPatchFunc), + JFUNCTION(json_pretty, 1,1,0, 0,0,0, jsonPrettyFunc), + JFUNCTION(json_pretty, 2,1,0, 0,0,0, jsonPrettyFunc), + JFUNCTION(json_quote, 1,0,1, 1,0,0, jsonQuoteFunc), + JFUNCTION(json_remove, -1,1,1, 0,0,0, jsonRemoveFunc), + JFUNCTION(jsonb_remove, -1,1,0, 0,1,0, jsonRemoveFunc), + JFUNCTION(json_replace, -1,1,1, 1,0,0, jsonReplaceFunc), + JFUNCTION(jsonb_replace, -1,1,0, 1,1,0, jsonReplaceFunc), + JFUNCTION(json_set, -1,1,1, 1,0,JSON_ISSET, jsonSetFunc), + JFUNCTION(jsonb_set, -1,1,0, 1,1,JSON_ISSET, jsonSetFunc), + JFUNCTION(json_type, 1,1,0, 0,0,0, jsonTypeFunc), + JFUNCTION(json_type, 2,1,0, 0,0,0, jsonTypeFunc), + JFUNCTION(json_valid, 1,1,0, 0,0,0, jsonValidFunc), + JFUNCTION(json_valid, 2,1,0, 0,0,0, jsonValidFunc), #if SQLITE_DEBUG - JFUNCTION(json_parse, 1, 0, jsonParseFunc), - JFUNCTION(json_test1, 1, 0, jsonTest1Func), + JFUNCTION(json_parse, 1,1,0, 0,0,0, jsonParseFunc), #endif WAGGREGATE(json_group_array, 1, 0, 0, jsonArrayStep, jsonArrayFinal, jsonArrayValue, jsonGroupInverse, - SQLITE_SUBTYPE|SQLITE_UTF8|SQLITE_DETERMINISTIC), + SQLITE_SUBTYPE|SQLITE_RESULT_SUBTYPE|SQLITE_UTF8| + SQLITE_DETERMINISTIC), + WAGGREGATE(jsonb_group_array, 1, JSON_BLOB, 0, + jsonArrayStep, jsonArrayFinal, jsonArrayValue, jsonGroupInverse, + SQLITE_SUBTYPE|SQLITE_RESULT_SUBTYPE|SQLITE_UTF8|SQLITE_DETERMINISTIC), WAGGREGATE(json_group_object, 2, 0, 0, jsonObjectStep, jsonObjectFinal, jsonObjectValue, jsonGroupInverse, - SQLITE_SUBTYPE|SQLITE_UTF8|SQLITE_DETERMINISTIC) + SQLITE_SUBTYPE|SQLITE_RESULT_SUBTYPE|SQLITE_UTF8|SQLITE_DETERMINISTIC), + WAGGREGATE(jsonb_group_object,2, JSON_BLOB, 0, + jsonObjectStep, jsonObjectFinal, jsonObjectValue, jsonGroupInverse, + SQLITE_SUBTYPE|SQLITE_RESULT_SUBTYPE|SQLITE_UTF8| + SQLITE_DETERMINISTIC) }; sqlite3InsertBuiltinFuncs(aJsonFunc, ArraySize(aJsonFunc)); #endif @@ -205255,6 +210489,7 @@ struct Rtree { int iDepth; /* Current depth of the r-tree structure */ char *zDb; /* Name of database containing r-tree table */ char *zName; /* Name of r-tree table */ + char *zNodeName; /* Name of the %_node table */ u32 nBusy; /* Current number of users of this structure */ i64 nRowEst; /* Estimated number of rows in this table */ u32 nCursor; /* Number of open cursors */ @@ -205267,7 +210502,6 @@ struct Rtree { ** headed by the node (leaf nodes have RtreeNode.iNode==0). */ RtreeNode *pDeleted; - int iReinsertHeight; /* Height of sub-trees Reinsert() has run on */ /* Blob I/O on xxx_node */ sqlite3_blob *pNodeBlob; @@ -205564,15 +210798,20 @@ struct RtreeMatchArg { ** -DSQLITE_RUNTIME_BYTEORDER=1 is set, then byte-order is determined ** at run-time. */ -#ifndef SQLITE_BYTEORDER -# if defined(i386) || defined(__i386__) || defined(_M_IX86) || \ +#ifndef SQLITE_BYTEORDER /* Replicate changes at tag-20230904a */ +# if defined(__BYTE_ORDER__) && __BYTE_ORDER__==__ORDER_BIG_ENDIAN__ +# define SQLITE_BYTEORDER 4321 +# elif defined(__BYTE_ORDER__) && __BYTE_ORDER__==__ORDER_LITTLE_ENDIAN__ +# define SQLITE_BYTEORDER 1234 +# elif defined(__BIG_ENDIAN__) && __BIG_ENDIAN__==1 +# define SQLITE_BYTEORDER 4321 +# elif defined(i386) || defined(__i386__) || defined(_M_IX86) || \ defined(__x86_64) || defined(__x86_64__) || defined(_M_X64) || \ defined(_M_AMD64) || defined(_M_ARM) || defined(__x86) || \ defined(__ARMEL__) || defined(__AARCH64EL__) || defined(_M_ARM64) -# define SQLITE_BYTEORDER 1234 -# elif defined(sparc) || defined(__ppc__) || \ - defined(__ARMEB__) || defined(__AARCH64EB__) -# define SQLITE_BYTEORDER 4321 +# define SQLITE_BYTEORDER 1234 +# elif defined(sparc) || defined(__ARMEB__) || defined(__AARCH64EB__) +# define SQLITE_BYTEORDER 4321 # else # define SQLITE_BYTEORDER 0 # endif @@ -205778,11 +211017,9 @@ static RtreeNode *nodeNew(Rtree *pRtree, RtreeNode *pParent){ ** Clear the Rtree.pNodeBlob object */ static void nodeBlobReset(Rtree *pRtree){ - if( pRtree->pNodeBlob && pRtree->inWrTrans==0 && pRtree->nCursor==0 ){ - sqlite3_blob *pBlob = pRtree->pNodeBlob; - pRtree->pNodeBlob = 0; - sqlite3_blob_close(pBlob); - } + sqlite3_blob *pBlob = pRtree->pNodeBlob; + pRtree->pNodeBlob = 0; + sqlite3_blob_close(pBlob); } /* @@ -205801,7 +211038,7 @@ static int nodeAcquire( ** increase its reference count and return it. */ if( (pNode = nodeHashLookup(pRtree, iNode))!=0 ){ - if( pParent && pParent!=pNode->pParent ){ + if( pParent && ALWAYS(pParent!=pNode->pParent) ){ RTREE_IS_CORRUPT(pRtree); return SQLITE_CORRUPT_VTAB; } @@ -205821,14 +211058,11 @@ static int nodeAcquire( } } if( pRtree->pNodeBlob==0 ){ - char *zTab = sqlite3_mprintf("%s_node", pRtree->zName); - if( zTab==0 ) return SQLITE_NOMEM; - rc = sqlite3_blob_open(pRtree->db, pRtree->zDb, zTab, "data", iNode, 0, + rc = sqlite3_blob_open(pRtree->db, pRtree->zDb, pRtree->zNodeName, + "data", iNode, 0, &pRtree->pNodeBlob); - sqlite3_free(zTab); } if( rc ){ - nodeBlobReset(pRtree); *ppNode = 0; /* If unable to open an sqlite3_blob on the desired row, that can only ** be because the shadow tables hold erroneous data. */ @@ -205888,6 +211122,7 @@ static int nodeAcquire( } *ppNode = pNode; }else{ + nodeBlobReset(pRtree); if( pNode ){ pRtree->nNodeRef--; sqlite3_free(pNode); @@ -206032,6 +211267,7 @@ static void nodeGetCoord( int iCoord, /* Which coordinate to extract */ RtreeCoord *pCoord /* OUT: Space to write result to */ ){ + assert( iCellzData[12 + pRtree->nBytesPerCell*iCell + 4*iCoord], pCoord); } @@ -206221,7 +211457,9 @@ static int rtreeClose(sqlite3_vtab_cursor *cur){ sqlite3_finalize(pCsr->pReadAux); sqlite3_free(pCsr); pRtree->nCursor--; - nodeBlobReset(pRtree); + if( pRtree->nCursor==0 && pRtree->inWrTrans==0 ){ + nodeBlobReset(pRtree); + } return SQLITE_OK; } @@ -206806,7 +212044,11 @@ static int rtreeRowid(sqlite3_vtab_cursor *pVtabCursor, sqlite_int64 *pRowid){ int rc = SQLITE_OK; RtreeNode *pNode = rtreeNodeOfFirstSearchPoint(pCsr, &rc); if( rc==SQLITE_OK && ALWAYS(p) ){ - *pRowid = nodeGetRowid(RTREE_OF_CURSOR(pCsr), pNode, p->iCell); + if( p->iCell>=NCELL(pNode) ){ + rc = SQLITE_ABORT; + }else{ + *pRowid = nodeGetRowid(RTREE_OF_CURSOR(pCsr), pNode, p->iCell); + } } return rc; } @@ -206824,6 +212066,7 @@ static int rtreeColumn(sqlite3_vtab_cursor *cur, sqlite3_context *ctx, int i){ if( rc ) return rc; if( NEVER(p==0) ) return SQLITE_OK; + if( p->iCell>=NCELL(pNode) ) return SQLITE_ABORT; if( i==0 ){ sqlite3_result_int64(ctx, nodeGetRowid(pRtree, pNode, p->iCell)); }else if( i<=pRtree->nDim2 ){ @@ -206921,6 +212164,8 @@ static int deserializeGeometry(sqlite3_value *pValue, RtreeConstraint *pCons){ return SQLITE_OK; } +SQLITE_PRIVATE int sqlite3IntFloatCompare(i64,double); + /* ** Rtree virtual table module xFilter method. */ @@ -206950,7 +212195,8 @@ static int rtreeFilter( i64 iNode = 0; int eType = sqlite3_value_numeric_type(argv[0]); if( eType==SQLITE_INTEGER - || (eType==SQLITE_FLOAT && sqlite3_value_double(argv[0])==iRowid) + || (eType==SQLITE_FLOAT + && 0==sqlite3IntFloatCompare(iRowid,sqlite3_value_double(argv[0]))) ){ rc = findLeafNode(pRtree, iRowid, &pLeaf, &iNode); }else{ @@ -207166,8 +212412,12 @@ static int rtreeBestIndex(sqlite3_vtab *tab, sqlite3_index_info *pIdxInfo){ pIdxInfo->idxNum = 2; pIdxInfo->needToFreeIdxStr = 1; - if( iIdx>0 && 0==(pIdxInfo->idxStr = sqlite3_mprintf("%s", zIdxStr)) ){ - return SQLITE_NOMEM; + if( iIdx>0 ){ + pIdxInfo->idxStr = sqlite3_malloc( iIdx+1 ); + if( pIdxInfo->idxStr==0 ){ + return SQLITE_NOMEM; + } + memcpy(pIdxInfo->idxStr, zIdxStr, iIdx+1); } nRow = pRtree->nRowEst >> (iIdx/2); @@ -207246,31 +212496,22 @@ static void cellUnion(Rtree *pRtree, RtreeCell *p1, RtreeCell *p2){ */ static int cellContains(Rtree *pRtree, RtreeCell *p1, RtreeCell *p2){ int ii; - int isInt = (pRtree->eCoordType==RTREE_COORD_INT32); - for(ii=0; iinDim2; ii+=2){ - RtreeCoord *a1 = &p1->aCoord[ii]; - RtreeCoord *a2 = &p2->aCoord[ii]; - if( (!isInt && (a2[0].fa1[1].f)) - || ( isInt && (a2[0].ia1[1].i)) - ){ - return 0; + if( pRtree->eCoordType==RTREE_COORD_INT32 ){ + for(ii=0; iinDim2; ii+=2){ + RtreeCoord *a1 = &p1->aCoord[ii]; + RtreeCoord *a2 = &p2->aCoord[ii]; + if( a2[0].ia1[1].i ) return 0; + } + }else{ + for(ii=0; iinDim2; ii+=2){ + RtreeCoord *a1 = &p1->aCoord[ii]; + RtreeCoord *a2 = &p2->aCoord[ii]; + if( a2[0].fa1[1].f ) return 0; } } return 1; } -/* -** Return the amount cell p would grow by if it were unioned with pCell. -*/ -static RtreeDValue cellGrowth(Rtree *pRtree, RtreeCell *p, RtreeCell *pCell){ - RtreeDValue area; - RtreeCell cell; - memcpy(&cell, p, sizeof(RtreeCell)); - area = cellArea(pRtree, &cell); - cellUnion(pRtree, &cell, pCell); - return (cellArea(pRtree, &cell)-area); -} - static RtreeDValue cellOverlap( Rtree *pRtree, RtreeCell *p, @@ -207317,38 +212558,52 @@ static int ChooseLeaf( for(ii=0; rc==SQLITE_OK && ii<(pRtree->iDepth-iHeight); ii++){ int iCell; sqlite3_int64 iBest = 0; - + int bFound = 0; RtreeDValue fMinGrowth = RTREE_ZERO; RtreeDValue fMinArea = RTREE_ZERO; - int nCell = NCELL(pNode); - RtreeCell cell; RtreeNode *pChild = 0; - RtreeCell *aCell = 0; - - /* Select the child node which will be enlarged the least if pCell - ** is inserted into it. Resolve ties by choosing the entry with - ** the smallest area. + /* First check to see if there is are any cells in pNode that completely + ** contains pCell. If two or more cells in pNode completely contain pCell + ** then pick the smallest. */ for(iCell=0; iCell1 ){ - int iLeft = 0; - int iRight = 0; - - int nLeft = nIdx/2; - int nRight = nIdx-nLeft; - int *aLeft = aIdx; - int *aRight = &aIdx[nLeft]; - - SortByDistance(aLeft, nLeft, aDistance, aSpare); - SortByDistance(aRight, nRight, aDistance, aSpare); - - memcpy(aSpare, aLeft, sizeof(int)*nLeft); - aLeft = aSpare; - - while( iLeftnDim; iDim++){ - aCenterCoord[iDim] += DCOORD(aCell[ii].aCoord[iDim*2]); - aCenterCoord[iDim] += DCOORD(aCell[ii].aCoord[iDim*2+1]); - } - } - for(iDim=0; iDimnDim; iDim++){ - aCenterCoord[iDim] = (aCenterCoord[iDim]/(nCell*(RtreeDValue)2)); - } - - for(ii=0; iinDim; iDim++){ - RtreeDValue coord = (DCOORD(aCell[ii].aCoord[iDim*2+1]) - - DCOORD(aCell[ii].aCoord[iDim*2])); - aDistance[ii] += (coord-aCenterCoord[iDim])*(coord-aCenterCoord[iDim]); - } - } - - SortByDistance(aOrder, nCell, aDistance, aSpare); - nodeZero(pRtree, pNode); - - for(ii=0; rc==SQLITE_OK && ii<(nCell-(RTREE_MINCELLS(pRtree)+1)); ii++){ - RtreeCell *p = &aCell[aOrder[ii]]; - nodeInsertCell(pRtree, pNode, p); - if( p->iRowid==pCell->iRowid ){ - if( iHeight==0 ){ - rc = rowidWrite(pRtree, p->iRowid, pNode->iNode); - }else{ - rc = parentWrite(pRtree, p->iRowid, pNode->iNode); - } - } - } - if( rc==SQLITE_OK ){ - rc = fixBoundingBox(pRtree, pNode); - } - for(; rc==SQLITE_OK && iiiNode currently contains - ** the height of the sub-tree headed by the cell. - */ - RtreeNode *pInsert; - RtreeCell *p = &aCell[aOrder[ii]]; - rc = ChooseLeaf(pRtree, p, iHeight, &pInsert); - if( rc==SQLITE_OK ){ - int rc2; - rc = rtreeInsertCell(pRtree, pInsert, p, iHeight); - rc2 = nodeRelease(pRtree, pInsert); - if( rc==SQLITE_OK ){ - rc = rc2; - } - } - } - - sqlite3_free(aCell); - return rc; -} - /* ** Insert cell pCell into node pNode. Node pNode is the head of a ** subtree iHeight high (leaf nodes have iHeight==0). @@ -208097,12 +213180,7 @@ static int rtreeInsertCell( } } if( nodeInsertCell(pRtree, pNode, pCell) ){ - if( iHeight<=pRtree->iReinsertHeight || pNode->iNode==1){ - rc = SplitNode(pRtree, pNode, pCell, iHeight); - }else{ - pRtree->iReinsertHeight = iHeight; - rc = Reinsert(pRtree, pNode, pCell, iHeight); - } + rc = SplitNode(pRtree, pNode, pCell, iHeight); }else{ rc = AdjustTree(pRtree, pNode, pCell); if( ALWAYS(rc==SQLITE_OK) ){ @@ -208445,7 +213523,6 @@ static int rtreeUpdate( } if( rc==SQLITE_OK ){ int rc2; - pRtree->iReinsertHeight = -1; rc = rtreeInsertCell(pRtree, pLeaf, &cell, 0); rc2 = nodeRelease(pRtree, pLeaf); if( rc==SQLITE_OK ){ @@ -208475,7 +213552,7 @@ static int rtreeUpdate( static int rtreeBeginTransaction(sqlite3_vtab *pVtab){ Rtree *pRtree = (Rtree *)pVtab; assert( pRtree->inWrTrans==0 ); - pRtree->inWrTrans++; + pRtree->inWrTrans = 1; return SQLITE_OK; } @@ -208489,6 +213566,9 @@ static int rtreeEndTransaction(sqlite3_vtab *pVtab){ nodeBlobReset(pRtree); return SQLITE_OK; } +static int rtreeRollback(sqlite3_vtab *pVtab){ + return rtreeEndTransaction(pVtab); +} /* ** The xRename method for rtree module virtual tables. @@ -208586,8 +213666,11 @@ static int rtreeShadowName(const char *zName){ return 0; } +/* Forward declaration */ +static int rtreeIntegrity(sqlite3_vtab*, const char*, const char*, int, char**); + static sqlite3_module rtreeModule = { - 3, /* iVersion */ + 4, /* iVersion */ rtreeCreate, /* xCreate - create a table */ rtreeConnect, /* xConnect - connect to an existing table */ rtreeBestIndex, /* xBestIndex - Determine search strategy */ @@ -208604,13 +213687,14 @@ static sqlite3_module rtreeModule = { rtreeBeginTransaction, /* xBegin - begin transaction */ rtreeEndTransaction, /* xSync - sync transaction */ rtreeEndTransaction, /* xCommit - commit transaction */ - rtreeEndTransaction, /* xRollback - rollback transaction */ + rtreeRollback, /* xRollback - rollback transaction */ 0, /* xFindFunction - function overloading */ rtreeRename, /* xRename - rename the table */ rtreeSavepoint, /* xSavepoint */ 0, /* xRelease */ 0, /* xRollbackTo */ - rtreeShadowName /* xShadowName */ + rtreeShadowName, /* xShadowName */ + rtreeIntegrity /* xIntegrity */ }; static int rtreeSqlInit( @@ -208703,7 +213787,7 @@ static int rtreeSqlInit( } sqlite3_free(zSql); } - if( pRtree->nAux ){ + if( pRtree->nAux && rc!=SQLITE_NOMEM ){ pRtree->zReadAuxSql = sqlite3_mprintf( "SELECT * FROM \"%w\".\"%w_rowid\" WHERE rowid=?1", zDb, zPrefix); @@ -208866,22 +213950,27 @@ static int rtreeInit( } sqlite3_vtab_config(db, SQLITE_VTAB_CONSTRAINT_SUPPORT, 1); + sqlite3_vtab_config(db, SQLITE_VTAB_INNOCUOUS); + /* Allocate the sqlite3_vtab structure */ nDb = (int)strlen(argv[1]); nName = (int)strlen(argv[2]); - pRtree = (Rtree *)sqlite3_malloc64(sizeof(Rtree)+nDb+nName+2); + pRtree = (Rtree *)sqlite3_malloc64(sizeof(Rtree)+nDb+nName*2+8); if( !pRtree ){ return SQLITE_NOMEM; } - memset(pRtree, 0, sizeof(Rtree)+nDb+nName+2); + memset(pRtree, 0, sizeof(Rtree)+nDb+nName*2+8); pRtree->nBusy = 1; pRtree->base.pModule = &rtreeModule; pRtree->zDb = (char *)&pRtree[1]; pRtree->zName = &pRtree->zDb[nDb+1]; + pRtree->zNodeName = &pRtree->zName[nName+1]; pRtree->eCoordType = (u8)eCoordType; memcpy(pRtree->zDb, argv[1], nDb); memcpy(pRtree->zName, argv[2], nName); + memcpy(pRtree->zNodeName, argv[2], nName); + memcpy(&pRtree->zNodeName[nName], "_node", 6); /* Create/Connect to the underlying relational database schema. If @@ -209378,7 +214467,6 @@ static int rtreeCheckTable( ){ RtreeCheck check; /* Common context for various routines */ sqlite3_stmt *pStmt = 0; /* Used to find column count of rtree table */ - int bEnd = 0; /* True if transaction should be closed */ int nAux = 0; /* Number of extra columns. */ /* Initialize the context object */ @@ -209387,24 +214475,14 @@ static int rtreeCheckTable( check.zDb = zDb; check.zTab = zTab; - /* If there is not already an open transaction, open one now. This is - ** to ensure that the queries run as part of this integrity-check operate - ** on a consistent snapshot. */ - if( sqlite3_get_autocommit(db) ){ - check.rc = sqlite3_exec(db, "BEGIN", 0, 0, 0); - bEnd = 1; - } - /* Find the number of auxiliary columns */ - if( check.rc==SQLITE_OK ){ - pStmt = rtreeCheckPrepare(&check, "SELECT * FROM %Q.'%q_rowid'", zDb, zTab); - if( pStmt ){ - nAux = sqlite3_column_count(pStmt) - 2; - sqlite3_finalize(pStmt); - }else - if( check.rc!=SQLITE_NOMEM ){ - check.rc = SQLITE_OK; - } + pStmt = rtreeCheckPrepare(&check, "SELECT * FROM %Q.'%q_rowid'", zDb, zTab); + if( pStmt ){ + nAux = sqlite3_column_count(pStmt) - 2; + sqlite3_finalize(pStmt); + }else + if( check.rc!=SQLITE_NOMEM ){ + check.rc = SQLITE_OK; } /* Find number of dimensions in the rtree table. */ @@ -209435,15 +214513,35 @@ static int rtreeCheckTable( sqlite3_finalize(check.aCheckMapping[0]); sqlite3_finalize(check.aCheckMapping[1]); - /* If one was opened, close the transaction */ - if( bEnd ){ - int rc = sqlite3_exec(db, "END", 0, 0, 0); - if( check.rc==SQLITE_OK ) check.rc = rc; - } *pzReport = check.zReport; return check.rc; } +/* +** Implementation of the xIntegrity method for Rtree. +*/ +static int rtreeIntegrity( + sqlite3_vtab *pVtab, /* The virtual table to check */ + const char *zSchema, /* Schema in which the virtual table lives */ + const char *zName, /* Name of the virtual table */ + int isQuick, /* True for a quick_check */ + char **pzErr /* Write results here */ +){ + Rtree *pRtree = (Rtree*)pVtab; + int rc; + assert( pzErr!=0 && *pzErr==0 ); + UNUSED_PARAMETER(zSchema); + UNUSED_PARAMETER(zName); + UNUSED_PARAMETER(isQuick); + rc = rtreeCheckTable(pRtree->db, pRtree->zDb, pRtree->zName, pzErr); + if( rc==SQLITE_OK && *pzErr ){ + *pzErr = sqlite3_mprintf("In RTree %s.%s:\n%z", + pRtree->zDb, pRtree->zName, *pzErr); + if( (*pzErr)==0 ) rc = SQLITE_NOMEM; + } + return rc; +} + /* ** Usage: ** @@ -210765,24 +215863,28 @@ static int geopolyInit( (void)pAux; sqlite3_vtab_config(db, SQLITE_VTAB_CONSTRAINT_SUPPORT, 1); + sqlite3_vtab_config(db, SQLITE_VTAB_INNOCUOUS); /* Allocate the sqlite3_vtab structure */ nDb = strlen(argv[1]); nName = strlen(argv[2]); - pRtree = (Rtree *)sqlite3_malloc64(sizeof(Rtree)+nDb+nName+2); + pRtree = (Rtree *)sqlite3_malloc64(sizeof(Rtree)+nDb+nName*2+8); if( !pRtree ){ return SQLITE_NOMEM; } - memset(pRtree, 0, sizeof(Rtree)+nDb+nName+2); + memset(pRtree, 0, sizeof(Rtree)+nDb+nName*2+8); pRtree->nBusy = 1; pRtree->base.pModule = &rtreeModule; pRtree->zDb = (char *)&pRtree[1]; pRtree->zName = &pRtree->zDb[nDb+1]; + pRtree->zNodeName = &pRtree->zName[nName+1]; pRtree->eCoordType = RTREE_COORD_REAL32; pRtree->nDim = 2; pRtree->nDim2 = 4; memcpy(pRtree->zDb, argv[1], nDb); memcpy(pRtree->zName, argv[2], nName); + memcpy(pRtree->zNodeName, argv[2], nName); + memcpy(&pRtree->zNodeName[nName], "_node", 6); /* Create/Connect to the underlying relational database schema. If @@ -211196,7 +216298,6 @@ static int geopolyUpdate( } if( rc==SQLITE_OK ){ int rc2; - pRtree->iReinsertHeight = -1; rc = rtreeInsertCell(pRtree, pLeaf, &cell, 0); rc2 = nodeRelease(pRtree, pLeaf); if( rc==SQLITE_OK ){ @@ -211293,7 +216394,8 @@ static sqlite3_module geopolyModule = { rtreeSavepoint, /* xSavepoint */ 0, /* xRelease */ 0, /* xRollbackTo */ - rtreeShadowName /* xShadowName */ + rtreeShadowName, /* xShadowName */ + rtreeIntegrity /* xIntegrity */ }; static int sqlite3_geopoly_init(sqlite3 *db){ @@ -212004,7 +217106,7 @@ static void icuLoadCollation( UCollator *pUCollator; /* ICU library collation object */ int rc; /* Return code from sqlite3_create_collation_x() */ - assert(nArg==2); + assert(nArg==2 || nArg==3); (void)nArg; /* Unused parameter */ zLocale = (const char *)sqlite3_value_text(apArg[0]); zName = (const char *)sqlite3_value_text(apArg[1]); @@ -212019,7 +217121,39 @@ static void icuLoadCollation( return; } assert(p); - + if(nArg==3){ + const char *zOption = (const char*)sqlite3_value_text(apArg[2]); + static const struct { + const char *zName; + UColAttributeValue val; + } aStrength[] = { + { "PRIMARY", UCOL_PRIMARY }, + { "SECONDARY", UCOL_SECONDARY }, + { "TERTIARY", UCOL_TERTIARY }, + { "DEFAULT", UCOL_DEFAULT_STRENGTH }, + { "QUARTERNARY", UCOL_QUATERNARY }, + { "IDENTICAL", UCOL_IDENTICAL }, + }; + unsigned int i; + for(i=0; i=sizeof(aStrength)/sizeof(aStrength[0]) ){ + sqlite3_str *pStr = sqlite3_str_new(sqlite3_context_db_handle(p)); + sqlite3_str_appendf(pStr, + "unknown collation strength \"%s\" - should be one of:", + zOption); + for(i=0; ipTblIter, &p->zErrmsg); pIter->zTbl = 0; + pIter->zDataTbl = 0; }else{ pIter->zTbl = (const char*)sqlite3_column_text(pIter->pTblIter, 0); pIter->zDataTbl = (const char*)sqlite3_column_text(pIter->pTblIter,1); @@ -215972,7 +221109,7 @@ static i64 rbuShmChecksum(sqlite3rbu *p){ u32 volatile *ptr; p->rc = pDb->pMethods->xShmMap(pDb, 0, 32*1024, 0, (void volatile**)&ptr); if( p->rc==SQLITE_OK ){ - iRet = ((i64)ptr[10] << 32) + ptr[11]; + iRet = (i64)(((u64)ptr[10] << 32) + ptr[11]); } } return iRet; @@ -219307,7 +224444,8 @@ SQLITE_PRIVATE int sqlite3DbstatRegister(sqlite3 *db){ 0, /* xSavepoint */ 0, /* xRelease */ 0, /* xRollbackTo */ - 0 /* xShadowName */ + 0, /* xShadowName */ + 0 /* xIntegrity */ }; return sqlite3_create_module(db, "dbstat", &dbstat_module, 0); } @@ -219744,7 +224882,8 @@ SQLITE_PRIVATE int sqlite3DbpageRegister(sqlite3 *db){ 0, /* xSavepoint */ 0, /* xRelease */ 0, /* xRollbackTo */ - 0 /* xShadowName */ + 0, /* xShadowName */ + 0 /* xIntegrity */ }; return sqlite3_create_module(db, "sqlite_dbpage", &dbpage_module, 0); } @@ -219875,6 +225014,18 @@ struct sqlite3_changeset_iter { ** The data associated with each hash-table entry is a structure containing ** a subset of the initial values that the modified row contained at the ** start of the session. Or no initial values if the row was inserted. +** +** pDfltStmt: +** This is only used by the sqlite3changegroup_xxx() APIs, not by +** regular sqlite3_session objects. It is a SELECT statement that +** selects the default value for each table column. For example, +** if the table is +** +** CREATE TABLE xx(a DEFAULT 1, b, c DEFAULT 'abc') +** +** then this variable is the compiled version of: +** +** SELECT 1, NULL, 'abc' */ struct SessionTable { SessionTable *pNext; @@ -219883,10 +225034,12 @@ struct SessionTable { int bStat1; /* True if this is sqlite_stat1 */ int bRowid; /* True if this table uses rowid for PK */ const char **azCol; /* Column names */ + const char **azDflt; /* Default value expressions */ u8 *abPK; /* Array of primary key flags */ int nEntry; /* Total number of entries in hash table */ int nChange; /* Size of apChange[] array */ SessionChange **apChange; /* Hash table buckets */ + sqlite3_stmt *pDfltStmt; }; /* @@ -220055,6 +225208,7 @@ struct SessionTable { struct SessionChange { u8 op; /* One of UPDATE, DELETE, INSERT */ u8 bIndirect; /* True if this change is "indirect" */ + u16 nRecordField; /* Number of fields in aRecord[] */ int nMaxSize; /* Max size of eventual changeset record */ int nRecord; /* Number of bytes in buffer aRecord[] */ u8 *aRecord; /* Buffer containing old.* record */ @@ -220080,7 +225234,7 @@ static int sessionVarintLen(int iVal){ ** Read a varint value from aBuf[] into *piVal. Return the number of ** bytes read. */ -static int sessionVarintGet(u8 *aBuf, int *piVal){ +static int sessionVarintGet(const u8 *aBuf, int *piVal){ return getVarint32(aBuf, *piVal); } @@ -220343,9 +225497,11 @@ static int sessionPreupdateHash( ** Return the number of bytes of space occupied by the value (including ** the type byte). */ -static int sessionSerialLen(u8 *a){ - int e = *a; +static int sessionSerialLen(const u8 *a){ + int e; int n; + assert( a!=0 ); + e = *a; if( e==0 || e==0xFF ) return 1; if( e==SQLITE_NULL ) return 1; if( e==SQLITE_INTEGER || e==SQLITE_FLOAT ) return 9; @@ -220750,13 +225906,14 @@ static int sessionGrowHash( ** ** For example, if the table is declared as: ** -** CREATE TABLE tbl1(w, x, y, z, PRIMARY KEY(w, z)); +** CREATE TABLE tbl1(w, x DEFAULT 'abc', y, z, PRIMARY KEY(w, z)); ** -** Then the four output variables are populated as follows: +** Then the five output variables are populated as follows: ** ** *pnCol = 4 ** *pzTab = "tbl1" ** *pazCol = {"w", "x", "y", "z"} +** *pazDflt = {NULL, 'abc', NULL, NULL} ** *pabPK = {1, 0, 0, 1} ** ** All returned buffers are part of the same single allocation, which must @@ -220770,6 +225927,7 @@ static int sessionTableInfo( int *pnCol, /* OUT: number of columns */ const char **pzTab, /* OUT: Copy of zThis */ const char ***pazCol, /* OUT: Array of column names for table */ + const char ***pazDflt, /* OUT: Array of default value expressions */ u8 **pabPK, /* OUT: Array of booleans - true for PK col */ int *pbRowid /* OUT: True if only PK is a rowid */ ){ @@ -220782,11 +225940,18 @@ static int sessionTableInfo( int i; u8 *pAlloc = 0; char **azCol = 0; + char **azDflt = 0; u8 *abPK = 0; int bRowid = 0; /* Set to true to use rowid as PK */ assert( pazCol && pabPK ); + *pazCol = 0; + *pabPK = 0; + *pnCol = 0; + if( pzTab ) *pzTab = 0; + if( pazDflt ) *pazDflt = 0; + nThis = sqlite3Strlen30(zThis); if( nThis==12 && 0==sqlite3_stricmp("sqlite_stat1", zThis) ){ rc = sqlite3_table_column_metadata(db, zDb, zThis, 0, 0, 0, 0, 0, 0); @@ -220800,39 +225965,28 @@ static int sessionTableInfo( }else if( rc==SQLITE_ERROR ){ zPragma = sqlite3_mprintf(""); }else{ - *pazCol = 0; - *pabPK = 0; - *pnCol = 0; - if( pzTab ) *pzTab = 0; return rc; } }else{ zPragma = sqlite3_mprintf("PRAGMA '%q'.table_info('%q')", zDb, zThis); } if( !zPragma ){ - *pazCol = 0; - *pabPK = 0; - *pnCol = 0; - if( pzTab ) *pzTab = 0; return SQLITE_NOMEM; } rc = sqlite3_prepare_v2(db, zPragma, -1, &pStmt, 0); sqlite3_free(zPragma); if( rc!=SQLITE_OK ){ - *pazCol = 0; - *pabPK = 0; - *pnCol = 0; - if( pzTab ) *pzTab = 0; return rc; } nByte = nThis + 1; bRowid = (pbRowid!=0); while( SQLITE_ROW==sqlite3_step(pStmt) ){ - nByte += sqlite3_column_bytes(pStmt, 1); + nByte += sqlite3_column_bytes(pStmt, 1); /* name */ + nByte += sqlite3_column_bytes(pStmt, 4); /* dflt_value */ nDbCol++; - if( sqlite3_column_int(pStmt, 5) ) bRowid = 0; + if( sqlite3_column_int(pStmt, 5) ) bRowid = 0; /* pk */ } if( nDbCol==0 ) bRowid = 0; nDbCol += bRowid; @@ -220840,15 +225994,18 @@ static int sessionTableInfo( rc = sqlite3_reset(pStmt); if( rc==SQLITE_OK ){ - nByte += nDbCol * (sizeof(const char *) + sizeof(u8) + 1); + nByte += nDbCol * (sizeof(const char *)*2 + sizeof(u8) + 1 + 1); pAlloc = sessionMalloc64(pSession, nByte); if( pAlloc==0 ){ rc = SQLITE_NOMEM; + }else{ + memset(pAlloc, 0, nByte); } } if( rc==SQLITE_OK ){ azCol = (char **)pAlloc; - pAlloc = (u8 *)&azCol[nDbCol]; + azDflt = (char**)&azCol[nDbCol]; + pAlloc = (u8 *)&azDflt[nDbCol]; abPK = (u8 *)pAlloc; pAlloc = &abPK[nDbCol]; if( pzTab ){ @@ -220868,11 +226025,21 @@ static int sessionTableInfo( } while( SQLITE_ROW==sqlite3_step(pStmt) ){ int nName = sqlite3_column_bytes(pStmt, 1); + int nDflt = sqlite3_column_bytes(pStmt, 4); const unsigned char *zName = sqlite3_column_text(pStmt, 1); + const unsigned char *zDflt = sqlite3_column_text(pStmt, 4); + if( zName==0 ) break; memcpy(pAlloc, zName, nName+1); azCol[i] = (char *)pAlloc; pAlloc += nName+1; + if( zDflt ){ + memcpy(pAlloc, zDflt, nDflt+1); + azDflt[i] = (char *)pAlloc; + pAlloc += nDflt+1; + }else{ + azDflt[i] = 0; + } abPK[i] = sqlite3_column_int(pStmt, 5); i++; } @@ -220883,14 +226050,11 @@ static int sessionTableInfo( ** free any allocation made. An error code will be returned in this case. */ if( rc==SQLITE_OK ){ - *pazCol = (const char **)azCol; + *pazCol = (const char**)azCol; + if( pazDflt ) *pazDflt = (const char**)azDflt; *pabPK = abPK; *pnCol = nDbCol; }else{ - *pazCol = 0; - *pabPK = 0; - *pnCol = 0; - if( pzTab ) *pzTab = 0; sessionFree(pSession, azCol); } if( pbRowid ) *pbRowid = bRowid; @@ -220899,10 +226063,9 @@ static int sessionTableInfo( } /* -** This function is only called from within a pre-update handler for a -** write to table pTab, part of session pSession. If this is the first -** write to this table, initalize the SessionTable.nCol, azCol[] and -** abPK[] arrays accordingly. +** This function is called to initialize the SessionTable.nCol, azCol[] +** abPK[] and azDflt[] members of SessionTable object pTab. If these +** fields are already initilialized, this function is a no-op. ** ** If an error occurs, an error code is stored in sqlite3_session.rc and ** non-zero returned. Or, if no error occurs but the table has no primary @@ -220910,15 +226073,22 @@ static int sessionTableInfo( ** indicate that updates on this table should be ignored. SessionTable.abPK ** is set to NULL in this case. */ -static int sessionInitTable(sqlite3_session *pSession, SessionTable *pTab){ +static int sessionInitTable( + sqlite3_session *pSession, /* Optional session handle */ + SessionTable *pTab, /* Table object to initialize */ + sqlite3 *db, /* Database handle to read schema from */ + const char *zDb /* Name of db - "main", "temp" etc. */ +){ + int rc = SQLITE_OK; + if( pTab->nCol==0 ){ u8 *abPK; assert( pTab->azCol==0 || pTab->abPK==0 ); - pSession->rc = sessionTableInfo(pSession, pSession->db, pSession->zDb, - pTab->zName, &pTab->nCol, 0, &pTab->azCol, &abPK, - (pSession->bImplicitPK ? &pTab->bRowid : 0) + rc = sessionTableInfo(pSession, db, zDb, + pTab->zName, &pTab->nCol, 0, &pTab->azCol, &pTab->azDflt, &abPK, + ((pSession==0 || pSession->bImplicitPK) ? &pTab->bRowid : 0) ); - if( pSession->rc==SQLITE_OK ){ + if( rc==SQLITE_OK ){ int i; for(i=0; inCol; i++){ if( abPK[i] ){ @@ -220930,14 +226100,321 @@ static int sessionInitTable(sqlite3_session *pSession, SessionTable *pTab){ pTab->bStat1 = 1; } - if( pSession->bEnableSize ){ + if( pSession && pSession->bEnableSize ){ pSession->nMaxChangesetSize += ( 1 + sessionVarintLen(pTab->nCol) + pTab->nCol + strlen(pTab->zName)+1 ); } } } - return (pSession->rc || pTab->abPK==0); + + if( pSession ){ + pSession->rc = rc; + return (rc || pTab->abPK==0); + } + return rc; +} + +/* +** Re-initialize table object pTab. +*/ +static int sessionReinitTable(sqlite3_session *pSession, SessionTable *pTab){ + int nCol = 0; + const char **azCol = 0; + const char **azDflt = 0; + u8 *abPK = 0; + int bRowid = 0; + + assert( pSession->rc==SQLITE_OK ); + + pSession->rc = sessionTableInfo(pSession, pSession->db, pSession->zDb, + pTab->zName, &nCol, 0, &azCol, &azDflt, &abPK, + (pSession->bImplicitPK ? &bRowid : 0) + ); + if( pSession->rc==SQLITE_OK ){ + if( pTab->nCol>nCol || pTab->bRowid!=bRowid ){ + pSession->rc = SQLITE_SCHEMA; + }else{ + int ii; + int nOldCol = pTab->nCol; + for(ii=0; iinCol ){ + if( pTab->abPK[ii]!=abPK[ii] ){ + pSession->rc = SQLITE_SCHEMA; + } + }else if( abPK[ii] ){ + pSession->rc = SQLITE_SCHEMA; + } + } + + if( pSession->rc==SQLITE_OK ){ + const char **a = pTab->azCol; + pTab->azCol = azCol; + pTab->nCol = nCol; + pTab->azDflt = azDflt; + pTab->abPK = abPK; + azCol = a; + } + if( pSession->bEnableSize ){ + pSession->nMaxChangesetSize += (nCol - nOldCol); + pSession->nMaxChangesetSize += sessionVarintLen(nCol); + pSession->nMaxChangesetSize -= sessionVarintLen(nOldCol); + } + } + } + + sqlite3_free((char*)azCol); + return pSession->rc; +} + +/* +** Session-change object (*pp) contains an old.* record with fewer than +** nCol fields. This function updates it with the default values for +** the missing fields. +*/ +static void sessionUpdateOneChange( + sqlite3_session *pSession, /* For memory accounting */ + int *pRc, /* IN/OUT: Error code */ + SessionChange **pp, /* IN/OUT: Change object to update */ + int nCol, /* Number of columns now in table */ + sqlite3_stmt *pDflt /* SELECT */ +){ + SessionChange *pOld = *pp; + + while( pOld->nRecordFieldnRecordField; + int eType = sqlite3_column_type(pDflt, iField); + switch( eType ){ + case SQLITE_NULL: + nIncr = 1; + break; + case SQLITE_INTEGER: + case SQLITE_FLOAT: + nIncr = 9; + break; + default: { + int n = sqlite3_column_bytes(pDflt, iField); + nIncr = 1 + sessionVarintLen(n) + n; + assert( eType==SQLITE_TEXT || eType==SQLITE_BLOB ); + break; + } + } + + nByte = nIncr + (sizeof(SessionChange) + pOld->nRecord); + pNew = sessionMalloc64(pSession, nByte); + if( pNew==0 ){ + *pRc = SQLITE_NOMEM; + return; + }else{ + memcpy(pNew, pOld, sizeof(SessionChange)); + pNew->aRecord = (u8*)&pNew[1]; + memcpy(pNew->aRecord, pOld->aRecord, pOld->nRecord); + pNew->aRecord[pNew->nRecord++] = (u8)eType; + switch( eType ){ + case SQLITE_INTEGER: { + i64 iVal = sqlite3_column_int64(pDflt, iField); + sessionPutI64(&pNew->aRecord[pNew->nRecord], iVal); + pNew->nRecord += 8; + break; + } + + case SQLITE_FLOAT: { + double rVal = sqlite3_column_double(pDflt, iField); + i64 iVal = 0; + memcpy(&iVal, &rVal, sizeof(rVal)); + sessionPutI64(&pNew->aRecord[pNew->nRecord], iVal); + pNew->nRecord += 8; + break; + } + + case SQLITE_TEXT: { + int n = sqlite3_column_bytes(pDflt, iField); + const char *z = (const char*)sqlite3_column_text(pDflt, iField); + pNew->nRecord += sessionVarintPut(&pNew->aRecord[pNew->nRecord], n); + memcpy(&pNew->aRecord[pNew->nRecord], z, n); + pNew->nRecord += n; + break; + } + + case SQLITE_BLOB: { + int n = sqlite3_column_bytes(pDflt, iField); + const u8 *z = (const u8*)sqlite3_column_blob(pDflt, iField); + pNew->nRecord += sessionVarintPut(&pNew->aRecord[pNew->nRecord], n); + memcpy(&pNew->aRecord[pNew->nRecord], z, n); + pNew->nRecord += n; + break; + } + + default: + assert( eType==SQLITE_NULL ); + break; + } + + sessionFree(pSession, pOld); + *pp = pOld = pNew; + pNew->nRecordField++; + pNew->nMaxSize += nIncr; + if( pSession ){ + pSession->nMaxChangesetSize += nIncr; + } + } + } +} + +/* +** Ensure that there is room in the buffer to append nByte bytes of data. +** If not, use sqlite3_realloc() to grow the buffer so that there is. +** +** If successful, return zero. Otherwise, if an OOM condition is encountered, +** set *pRc to SQLITE_NOMEM and return non-zero. +*/ +static int sessionBufferGrow(SessionBuffer *p, i64 nByte, int *pRc){ +#define SESSION_MAX_BUFFER_SZ (0x7FFFFF00 - 1) + i64 nReq = p->nBuf + nByte; + if( *pRc==SQLITE_OK && nReq>p->nAlloc ){ + u8 *aNew; + i64 nNew = p->nAlloc ? p->nAlloc : 128; + + do { + nNew = nNew*2; + }while( nNewSESSION_MAX_BUFFER_SZ ){ + nNew = SESSION_MAX_BUFFER_SZ; + if( nNewaBuf, nNew); + if( 0==aNew ){ + *pRc = SQLITE_NOMEM; + }else{ + p->aBuf = aNew; + p->nAlloc = nNew; + } + } + return (*pRc!=SQLITE_OK); +} + + +/* +** This function is a no-op if *pRc is other than SQLITE_OK when it is +** called. Otherwise, append a string to the buffer. All bytes in the string +** up to (but not including) the nul-terminator are written to the buffer. +** +** If an OOM condition is encountered, set *pRc to SQLITE_NOMEM before +** returning. +*/ +static void sessionAppendStr( + SessionBuffer *p, + const char *zStr, + int *pRc +){ + int nStr = sqlite3Strlen30(zStr); + if( 0==sessionBufferGrow(p, nStr+1, pRc) ){ + memcpy(&p->aBuf[p->nBuf], zStr, nStr); + p->nBuf += nStr; + p->aBuf[p->nBuf] = 0x00; + } +} + +/* +** Format a string using printf() style formatting and then append it to the +** buffer using sessionAppendString(). +*/ +static void sessionAppendPrintf( + SessionBuffer *p, /* Buffer to append to */ + int *pRc, + const char *zFmt, + ... +){ + if( *pRc==SQLITE_OK ){ + char *zApp = 0; + va_list ap; + va_start(ap, zFmt); + zApp = sqlite3_vmprintf(zFmt, ap); + if( zApp==0 ){ + *pRc = SQLITE_NOMEM; + }else{ + sessionAppendStr(p, zApp, pRc); + } + va_end(ap); + sqlite3_free(zApp); + } +} + +/* +** Prepare a statement against database handle db that SELECTs a single +** row containing the default values for each column in table pTab. For +** example, if pTab is declared as: +** +** CREATE TABLE pTab(a PRIMARY KEY, b DEFAULT 123, c DEFAULT 'abcd'); +** +** Then this function prepares and returns the SQL statement: +** +** SELECT NULL, 123, 'abcd'; +*/ +static int sessionPrepareDfltStmt( + sqlite3 *db, /* Database handle */ + SessionTable *pTab, /* Table to prepare statement for */ + sqlite3_stmt **ppStmt /* OUT: Statement handle */ +){ + SessionBuffer sql = {0,0,0}; + int rc = SQLITE_OK; + const char *zSep = " "; + int ii = 0; + + *ppStmt = 0; + sessionAppendPrintf(&sql, &rc, "SELECT"); + for(ii=0; iinCol; ii++){ + const char *zDflt = pTab->azDflt[ii] ? pTab->azDflt[ii] : "NULL"; + sessionAppendPrintf(&sql, &rc, "%s%s", zSep, zDflt); + zSep = ", "; + } + if( rc==SQLITE_OK ){ + rc = sqlite3_prepare_v2(db, (const char*)sql.aBuf, -1, ppStmt, 0); + } + sqlite3_free(sql.aBuf); + + return rc; +} + +/* +** Table pTab has one or more existing change-records with old.* records +** with fewer than pTab->nCol columns. This function updates all such +** change-records with the default values for the missing columns. +*/ +static int sessionUpdateChanges(sqlite3_session *pSession, SessionTable *pTab){ + sqlite3_stmt *pStmt = 0; + int rc = pSession->rc; + + rc = sessionPrepareDfltStmt(pSession->db, pTab, &pStmt); + if( rc==SQLITE_OK && SQLITE_ROW==sqlite3_step(pStmt) ){ + int ii = 0; + SessionChange **pp = 0; + for(ii=0; iinChange; ii++){ + for(pp=&pTab->apChange[ii]; *pp; pp=&((*pp)->pNext)){ + if( (*pp)->nRecordField!=pTab->nCol ){ + sessionUpdateOneChange(pSession, &rc, pp, pTab->nCol, pStmt); + } + } + } + } + + pSession->rc = rc; + rc = sqlite3_finalize(pStmt); + if( pSession->rc==SQLITE_OK ) pSession->rc = rc; + return pSession->rc; } /* @@ -221100,16 +226577,22 @@ static void sessionPreupdateOneChange( int iHash; int bNull = 0; int rc = SQLITE_OK; + int nExpect = 0; SessionStat1Ctx stat1 = {{0,0,0,0,0},0}; if( pSession->rc ) return; /* Load table details if required */ - if( sessionInitTable(pSession, pTab) ) return; + if( sessionInitTable(pSession, pTab, pSession->db, pSession->zDb) ) return; /* Check the number of columns in this xPreUpdate call matches the ** number of columns in the table. */ - if( (pTab->nCol-pTab->bRowid)!=pSession->hook.xCount(pSession->hook.pCtx) ){ + nExpect = pSession->hook.xCount(pSession->hook.pCtx); + if( (pTab->nCol-pTab->bRowid)nCol-pTab->bRowid)!=nExpect ){ pSession->rc = SQLITE_SCHEMA; return; } @@ -221186,7 +226669,7 @@ static void sessionPreupdateOneChange( } /* Allocate the change object */ - pC = (SessionChange *)sessionMalloc64(pSession, nByte); + pC = (SessionChange*)sessionMalloc64(pSession, nByte); if( !pC ){ rc = SQLITE_NOMEM; goto error_out; @@ -221219,6 +226702,7 @@ static void sessionPreupdateOneChange( if( pSession->bIndirect || pSession->hook.xDepth(pSession->hook.pCtx) ){ pC->bIndirect = 1; } + pC->nRecordField = pTab->nCol; pC->nRecord = nByte; pC->op = op; pC->pNext = pTab->apChange[iHash]; @@ -221598,7 +227082,7 @@ SQLITE_API int sqlite3session_diff( /* Locate and if necessary initialize the target table object */ rc = sessionFindTable(pSession, zTbl, &pTo); if( pTo==0 ) goto diff_out; - if( sessionInitTable(pSession, pTo) ){ + if( sessionInitTable(pSession, pTo, pSession->db, pSession->zDb) ){ rc = pSession->rc; goto diff_out; } @@ -221611,7 +227095,7 @@ SQLITE_API int sqlite3session_diff( int bRowid = 0; u8 *abPK; const char **azCol = 0; - rc = sessionTableInfo(0, db, zFrom, zTbl, &nCol, 0, &azCol, &abPK, + rc = sessionTableInfo(0, db, zFrom, zTbl, &nCol, 0, &azCol, 0, &abPK, pSession->bImplicitPK ? &bRowid : 0 ); if( rc==SQLITE_OK ){ @@ -221726,6 +227210,7 @@ static void sessionDeleteTable(sqlite3_session *pSession, SessionTable *pList){ sessionFree(pSession, p); } } + sqlite3_finalize(pTab->pDfltStmt); sessionFree(pSession, (char*)pTab->azCol); /* cast works around VC++ bug */ sessionFree(pSession, pTab->apChange); sessionFree(pSession, pTab); @@ -221758,9 +227243,7 @@ SQLITE_API void sqlite3session_delete(sqlite3_session *pSession){ ** associated hash-tables. */ sessionDeleteTable(pSession, pSession->pTable); - /* Assert that all allocations have been freed and then free the - ** session object itself. */ - assert( pSession->nMalloc==0 ); + /* Free the session object. */ sqlite3_free(pSession); } @@ -221831,48 +227314,6 @@ SQLITE_API int sqlite3session_attach( return rc; } -/* -** Ensure that there is room in the buffer to append nByte bytes of data. -** If not, use sqlite3_realloc() to grow the buffer so that there is. -** -** If successful, return zero. Otherwise, if an OOM condition is encountered, -** set *pRc to SQLITE_NOMEM and return non-zero. -*/ -static int sessionBufferGrow(SessionBuffer *p, i64 nByte, int *pRc){ -#define SESSION_MAX_BUFFER_SZ (0x7FFFFF00 - 1) - i64 nReq = p->nBuf + nByte; - if( *pRc==SQLITE_OK && nReq>p->nAlloc ){ - u8 *aNew; - i64 nNew = p->nAlloc ? p->nAlloc : 128; - - do { - nNew = nNew*2; - }while( nNewSESSION_MAX_BUFFER_SZ ){ - nNew = SESSION_MAX_BUFFER_SZ; - if( nNewaBuf, nNew); - if( 0==aNew ){ - *pRc = SQLITE_NOMEM; - }else{ - p->aBuf = aNew; - p->nAlloc = nNew; - } - } - return (*pRc!=SQLITE_OK); -} - /* ** Append the value passed as the second argument to the buffer passed ** as the first. @@ -221941,27 +227382,6 @@ static void sessionAppendBlob( } } -/* -** This function is a no-op if *pRc is other than SQLITE_OK when it is -** called. Otherwise, append a string to the buffer. All bytes in the string -** up to (but not including) the nul-terminator are written to the buffer. -** -** If an OOM condition is encountered, set *pRc to SQLITE_NOMEM before -** returning. -*/ -static void sessionAppendStr( - SessionBuffer *p, - const char *zStr, - int *pRc -){ - int nStr = sqlite3Strlen30(zStr); - if( 0==sessionBufferGrow(p, nStr+1, pRc) ){ - memcpy(&p->aBuf[p->nBuf], zStr, nStr); - p->nBuf += nStr; - p->aBuf[p->nBuf] = 0x00; - } -} - /* ** This function is a no-op if *pRc is other than SQLITE_OK when it is ** called. Otherwise, append the string representation of integer iVal @@ -221980,27 +227400,6 @@ static void sessionAppendInteger( sessionAppendStr(p, aBuf, pRc); } -static void sessionAppendPrintf( - SessionBuffer *p, /* Buffer to append to */ - int *pRc, - const char *zFmt, - ... -){ - if( *pRc==SQLITE_OK ){ - char *zApp = 0; - va_list ap; - va_start(ap, zFmt); - zApp = sqlite3_vmprintf(zFmt, ap); - if( zApp==0 ){ - *pRc = SQLITE_NOMEM; - }else{ - sessionAppendStr(p, zApp, pRc); - } - va_end(ap); - sqlite3_free(zApp); - } -} - /* ** This function is a no-op if *pRc is other than SQLITE_OK when it is ** called. Otherwise, append the string zStr enclosed in quotes (") and @@ -222491,26 +227890,16 @@ static int sessionGenerateChangeset( for(pTab=pSession->pTable; rc==SQLITE_OK && pTab; pTab=pTab->pNext){ if( pTab->nEntry ){ const char *zName = pTab->zName; - int nCol = 0; /* Number of columns in table */ - u8 *abPK = 0; /* Primary key array */ - const char **azCol = 0; /* Table columns */ int i; /* Used to iterate through hash buckets */ sqlite3_stmt *pSel = 0; /* SELECT statement to query table pTab */ int nRewind = buf.nBuf; /* Initial size of write buffer */ int nNoop; /* Size of buffer after writing tbl header */ - int bRowid = 0; + int nOldCol = pTab->nCol; /* Check the table schema is still Ok. */ - rc = sessionTableInfo( - 0, db, pSession->zDb, zName, &nCol, 0, &azCol, &abPK, - (pSession->bImplicitPK ? &bRowid : 0) - ); - if( rc==SQLITE_OK && ( - pTab->nCol!=nCol - || pTab->bRowid!=bRowid - || memcmp(abPK, pTab->abPK, nCol) - )){ - rc = SQLITE_SCHEMA; + rc = sessionReinitTable(pSession, pTab); + if( rc==SQLITE_OK && pTab->nCol!=nOldCol ){ + rc = sessionUpdateChanges(pSession, pTab); } /* Write a table header */ @@ -222518,8 +227907,8 @@ static int sessionGenerateChangeset( /* Build and compile a statement to execute: */ if( rc==SQLITE_OK ){ - rc = sessionSelectStmt( - db, 0, pSession->zDb, zName, bRowid, nCol, azCol, abPK, &pSel + rc = sessionSelectStmt(db, 0, pSession->zDb, + zName, pTab->bRowid, pTab->nCol, pTab->azCol, pTab->abPK, &pSel ); } @@ -222528,22 +227917,22 @@ static int sessionGenerateChangeset( SessionChange *p; /* Used to iterate through changes */ for(p=pTab->apChange[i]; rc==SQLITE_OK && p; p=p->pNext){ - rc = sessionSelectBind(pSel, nCol, abPK, p); + rc = sessionSelectBind(pSel, pTab->nCol, pTab->abPK, p); if( rc!=SQLITE_OK ) continue; if( sqlite3_step(pSel)==SQLITE_ROW ){ if( p->op==SQLITE_INSERT ){ int iCol; sessionAppendByte(&buf, SQLITE_INSERT, &rc); sessionAppendByte(&buf, p->bIndirect, &rc); - for(iCol=0; iColnCol; iCol++){ sessionAppendCol(&buf, pSel, iCol, &rc); } }else{ - assert( abPK!=0 ); /* Because sessionSelectStmt() returned ok */ - rc = sessionAppendUpdate(&buf, bPatchset, pSel, p, abPK); + assert( pTab->abPK!=0 ); + rc = sessionAppendUpdate(&buf, bPatchset, pSel, p, pTab->abPK); } }else if( p->op!=SQLITE_INSERT ){ - rc = sessionAppendDelete(&buf, bPatchset, p, nCol, abPK); + rc = sessionAppendDelete(&buf, bPatchset, p, pTab->nCol,pTab->abPK); } if( rc==SQLITE_OK ){ rc = sqlite3_reset(pSel); @@ -222568,7 +227957,6 @@ static int sessionGenerateChangeset( if( buf.nBuf==nNoop ){ buf.nBuf = nRewind; } - sqlite3_free((char*)azCol); /* cast works around VC++ bug */ } } @@ -223192,14 +228580,14 @@ static int sessionChangesetNextOne( p->rc = sessionInputBuffer(&p->in, 2); if( p->rc!=SQLITE_OK ) return p->rc; + sessionDiscardData(&p->in); + p->in.iCurrent = p->in.iNext; + /* If the iterator is already at the end of the changeset, return DONE. */ if( p->in.iNext>=p->in.nData ){ return SQLITE_DONE; } - sessionDiscardData(&p->in); - p->in.iCurrent = p->in.iNext; - op = p->in.aData[p->in.iNext++]; while( op=='T' || op=='P' ){ if( pbNew ) *pbNew = 1; @@ -224697,7 +230085,7 @@ static int sessionChangesetApply( sqlite3changeset_pk(pIter, &abPK, 0); rc = sessionTableInfo(0, db, "main", zNew, - &sApply.nCol, &zTab, &sApply.azCol, &sApply.abPK, &sApply.bRowid + &sApply.nCol, &zTab, &sApply.azCol, 0, &sApply.abPK, &sApply.bRowid ); if( rc!=SQLITE_OK ) break; for(i=0; iflags & SQLITE_FkNoAction; + + if( flags & SQLITE_CHANGESETAPPLY_FKNOACTION ){ + db->flags |= ((u64)SQLITE_FkNoAction); + db->aDb[0].pSchema->schema_cookie -= 32; + } + if( rc==SQLITE_OK ){ rc = sessionChangesetApply( db, pIter, xFilter, xConflict, pCtx, ppRebase, pnRebase, flags ); } + + if( (flags & SQLITE_CHANGESETAPPLY_FKNOACTION) && savedFlag==0 ){ + assert( db->flags & SQLITE_FkNoAction ); + db->flags &= ~((u64)SQLITE_FkNoAction); + db->aDb[0].pSchema->schema_cookie -= 32; + } return rc; } @@ -224921,6 +230322,10 @@ struct sqlite3_changegroup { int rc; /* Error code */ int bPatch; /* True to accumulate patchsets */ SessionTable *pList; /* List of tables in current patch */ + SessionBuffer rec; + + sqlite3 *db; /* Configured by changegroup_schema() */ + char *zDb; /* Configured by changegroup_schema() */ }; /* @@ -224941,6 +230346,7 @@ static int sessionChangeMerge( ){ SessionChange *pNew = 0; int rc = SQLITE_OK; + assert( aRec!=0 ); if( !pExist ){ pNew = (SessionChange *)sqlite3_malloc64(sizeof(SessionChange) + nRec); @@ -225107,84 +230513,236 @@ static int sessionChangeMerge( } /* -** Add all changes in the changeset traversed by the iterator passed as -** the first argument to the changegroup hash tables. +** Check if a changeset entry with nCol columns and the PK array passed +** as the final argument to this function is compatible with SessionTable +** pTab. If so, return 1. Otherwise, if they are incompatible in some way, +** return 0. */ -static int sessionChangesetToHash( - sqlite3_changeset_iter *pIter, /* Iterator to read from */ - sqlite3_changegroup *pGrp, /* Changegroup object to add changeset to */ - int bRebase /* True if hash table is for rebasing */ +static int sessionChangesetCheckCompat( + SessionTable *pTab, + int nCol, + u8 *abPK ){ - u8 *aRec; - int nRec; - int rc = SQLITE_OK; - SessionTable *pTab = 0; - - while( SQLITE_ROW==sessionChangesetNext(pIter, &aRec, &nRec, 0) ){ - const char *zNew; - int nCol; - int op; - int iHash; - int bIndirect; - SessionChange *pChange; - SessionChange *pExist = 0; - SessionChange **pp; - - if( pGrp->pList==0 ){ - pGrp->bPatch = pIter->bPatchset; - }else if( pIter->bPatchset!=pGrp->bPatch ){ - rc = SQLITE_ERROR; - break; + if( pTab->azCol && nColnCol ){ + int ii; + for(ii=0; iinCol; ii++){ + u8 bPK = (ii < nCol) ? abPK[ii] : 0; + if( pTab->abPK[ii]!=bPK ) return 0; } + return 1; + } + return (pTab->nCol==nCol && 0==memcmp(abPK, pTab->abPK, nCol)); +} - sqlite3changeset_op(pIter, &zNew, &nCol, &op, &bIndirect); - if( !pTab || sqlite3_stricmp(zNew, pTab->zName) ){ - /* Search the list for a matching table */ - int nNew = (int)strlen(zNew); - u8 *abPK; +static int sessionChangesetExtendRecord( + sqlite3_changegroup *pGrp, + SessionTable *pTab, + int nCol, + int op, + const u8 *aRec, + int nRec, + SessionBuffer *pOut +){ + int rc = SQLITE_OK; + int ii = 0; - sqlite3changeset_pk(pIter, &abPK, 0); - for(pTab = pGrp->pList; pTab; pTab=pTab->pNext){ - if( 0==sqlite3_strnicmp(pTab->zName, zNew, nNew+1) ) break; - } - if( !pTab ){ - SessionTable **ppTab; + assert( pTab->azCol ); + assert( nColnCol ); - pTab = sqlite3_malloc64(sizeof(SessionTable) + nCol + nNew+1); - if( !pTab ){ - rc = SQLITE_NOMEM; + pOut->nBuf = 0; + if( op==SQLITE_INSERT || (op==SQLITE_DELETE && pGrp->bPatch==0) ){ + /* Append the missing default column values to the record. */ + sessionAppendBlob(pOut, aRec, nRec, &rc); + if( rc==SQLITE_OK && pTab->pDfltStmt==0 ){ + rc = sessionPrepareDfltStmt(pGrp->db, pTab, &pTab->pDfltStmt); + } + for(ii=nCol; rc==SQLITE_OK && iinCol; ii++){ + int eType = sqlite3_column_type(pTab->pDfltStmt, ii); + sessionAppendByte(pOut, eType, &rc); + switch( eType ){ + case SQLITE_FLOAT: + case SQLITE_INTEGER: { + i64 iVal; + if( eType==SQLITE_INTEGER ){ + iVal = sqlite3_column_int64(pTab->pDfltStmt, ii); + }else{ + double rVal = sqlite3_column_int64(pTab->pDfltStmt, ii); + memcpy(&iVal, &rVal, sizeof(i64)); + } + if( SQLITE_OK==sessionBufferGrow(pOut, 8, &rc) ){ + sessionPutI64(&pOut->aBuf[pOut->nBuf], iVal); + } break; } - memset(pTab, 0, sizeof(SessionTable)); - pTab->nCol = nCol; - pTab->abPK = (u8*)&pTab[1]; - memcpy(pTab->abPK, abPK, nCol); - pTab->zName = (char*)&pTab->abPK[nCol]; - memcpy(pTab->zName, zNew, nNew+1); - - /* The new object must be linked on to the end of the list, not - ** simply added to the start of it. This is to ensure that the - ** tables within the output of sqlite3changegroup_output() are in - ** the right order. */ - for(ppTab=&pGrp->pList; *ppTab; ppTab=&(*ppTab)->pNext); - *ppTab = pTab; - }else if( pTab->nCol!=nCol || memcmp(pTab->abPK, abPK, nCol) ){ - rc = SQLITE_SCHEMA; - break; + + case SQLITE_BLOB: + case SQLITE_TEXT: { + int n = sqlite3_column_bytes(pTab->pDfltStmt, ii); + sessionAppendVarint(pOut, n, &rc); + if( eType==SQLITE_TEXT ){ + const u8 *z = (const u8*)sqlite3_column_text(pTab->pDfltStmt, ii); + sessionAppendBlob(pOut, z, n, &rc); + }else{ + const u8 *z = (const u8*)sqlite3_column_blob(pTab->pDfltStmt, ii); + sessionAppendBlob(pOut, z, n, &rc); + } + break; + } + + default: + assert( eType==SQLITE_NULL ); + break; + } + } + }else if( op==SQLITE_UPDATE ){ + /* Append missing "undefined" entries to the old.* record. And, if this + ** is an UPDATE, to the new.* record as well. */ + int iOff = 0; + if( pGrp->bPatch==0 ){ + for(ii=0; iinCol-nCol); ii++){ + sessionAppendByte(pOut, 0x00, &rc); } } - if( sessionGrowHash(0, pIter->bPatchset, pTab) ){ - rc = SQLITE_NOMEM; - break; + sessionAppendBlob(pOut, &aRec[iOff], nRec-iOff, &rc); + for(ii=0; ii<(pTab->nCol-nCol); ii++){ + sessionAppendByte(pOut, 0x00, &rc); } + }else{ + assert( op==SQLITE_DELETE && pGrp->bPatch ); + sessionAppendBlob(pOut, aRec, nRec, &rc); + } + + return rc; +} + +/* +** Locate or create a SessionTable object that may be used to add the +** change currently pointed to by iterator pIter to changegroup pGrp. +** If successful, set output variable (*ppTab) to point to the table +** object and return SQLITE_OK. Otherwise, if some error occurs, return +** an SQLite error code and leave (*ppTab) set to NULL. +*/ +static int sessionChangesetFindTable( + sqlite3_changegroup *pGrp, + const char *zTab, + sqlite3_changeset_iter *pIter, + SessionTable **ppTab +){ + int rc = SQLITE_OK; + SessionTable *pTab = 0; + int nTab = (int)strlen(zTab); + u8 *abPK = 0; + int nCol = 0; + + *ppTab = 0; + sqlite3changeset_pk(pIter, &abPK, &nCol); + + /* Search the list for an existing table */ + for(pTab = pGrp->pList; pTab; pTab=pTab->pNext){ + if( 0==sqlite3_strnicmp(pTab->zName, zTab, nTab+1) ) break; + } + + /* If one was not found above, create a new table now */ + if( !pTab ){ + SessionTable **ppNew; + + pTab = sqlite3_malloc64(sizeof(SessionTable) + nCol + nTab+1); + if( !pTab ){ + return SQLITE_NOMEM; + } + memset(pTab, 0, sizeof(SessionTable)); + pTab->nCol = nCol; + pTab->abPK = (u8*)&pTab[1]; + memcpy(pTab->abPK, abPK, nCol); + pTab->zName = (char*)&pTab->abPK[nCol]; + memcpy(pTab->zName, zTab, nTab+1); + + if( pGrp->db ){ + pTab->nCol = 0; + rc = sessionInitTable(0, pTab, pGrp->db, pGrp->zDb); + if( rc ){ + assert( pTab->azCol==0 ); + sqlite3_free(pTab); + return rc; + } + } + + /* The new object must be linked on to the end of the list, not + ** simply added to the start of it. This is to ensure that the + ** tables within the output of sqlite3changegroup_output() are in + ** the right order. */ + for(ppNew=&pGrp->pList; *ppNew; ppNew=&(*ppNew)->pNext); + *ppNew = pTab; + } + + /* Check that the table is compatible. */ + if( !sessionChangesetCheckCompat(pTab, nCol, abPK) ){ + rc = SQLITE_SCHEMA; + } + + *ppTab = pTab; + return rc; +} + +/* +** Add the change currently indicated by iterator pIter to the hash table +** belonging to changegroup pGrp. +*/ +static int sessionOneChangeToHash( + sqlite3_changegroup *pGrp, + sqlite3_changeset_iter *pIter, + int bRebase +){ + int rc = SQLITE_OK; + int nCol = 0; + int op = 0; + int iHash = 0; + int bIndirect = 0; + SessionChange *pChange = 0; + SessionChange *pExist = 0; + SessionChange **pp = 0; + SessionTable *pTab = 0; + u8 *aRec = &pIter->in.aData[pIter->in.iCurrent + 2]; + int nRec = (pIter->in.iNext - pIter->in.iCurrent) - 2; + + /* Ensure that only changesets, or only patchsets, but not a mixture + ** of both, are being combined. It is an error to try to combine a + ** changeset and a patchset. */ + if( pGrp->pList==0 ){ + pGrp->bPatch = pIter->bPatchset; + }else if( pIter->bPatchset!=pGrp->bPatch ){ + rc = SQLITE_ERROR; + } + + if( rc==SQLITE_OK ){ + const char *zTab = 0; + sqlite3changeset_op(pIter, &zTab, &nCol, &op, &bIndirect); + rc = sessionChangesetFindTable(pGrp, zTab, pIter, &pTab); + } + + if( rc==SQLITE_OK && nColnCol ){ + SessionBuffer *pBuf = &pGrp->rec; + rc = sessionChangesetExtendRecord(pGrp, pTab, nCol, op, aRec, nRec, pBuf); + aRec = pBuf->aBuf; + nRec = pBuf->nBuf; + assert( pGrp->db ); + } + + if( rc==SQLITE_OK && sessionGrowHash(0, pIter->bPatchset, pTab) ){ + rc = SQLITE_NOMEM; + } + + if( rc==SQLITE_OK ){ + /* Search for existing entry. If found, remove it from the hash table. + ** Code below may link it back in. */ iHash = sessionChangeHash( pTab, (pIter->bPatchset && op==SQLITE_DELETE), aRec, pTab->nChange ); - - /* Search for existing entry. If found, remove it from the hash table. - ** Code below may link it back in. - */ for(pp=&pTab->apChange[iHash]; *pp; pp=&(*pp)->pNext){ int bPkOnly1 = 0; int bPkOnly2 = 0; @@ -225199,16 +230757,39 @@ static int sessionChangesetToHash( break; } } + } + if( rc==SQLITE_OK ){ rc = sessionChangeMerge(pTab, bRebase, pIter->bPatchset, pExist, op, bIndirect, aRec, nRec, &pChange ); - if( rc ) break; - if( pChange ){ - pChange->pNext = pTab->apChange[iHash]; - pTab->apChange[iHash] = pChange; - pTab->nEntry++; - } + } + if( rc==SQLITE_OK && pChange ){ + pChange->pNext = pTab->apChange[iHash]; + pTab->apChange[iHash] = pChange; + pTab->nEntry++; + } + + if( rc==SQLITE_OK ) rc = pIter->rc; + return rc; +} + +/* +** Add all changes in the changeset traversed by the iterator passed as +** the first argument to the changegroup hash tables. +*/ +static int sessionChangesetToHash( + sqlite3_changeset_iter *pIter, /* Iterator to read from */ + sqlite3_changegroup *pGrp, /* Changegroup object to add changeset to */ + int bRebase /* True if hash table is for rebasing */ +){ + u8 *aRec; + int nRec; + int rc = SQLITE_OK; + + while( SQLITE_ROW==(sessionChangesetNext(pIter, &aRec, &nRec, 0)) ){ + rc = sessionOneChangeToHash(pGrp, pIter, bRebase); + if( rc!=SQLITE_OK ) break; } if( rc==SQLITE_OK ) rc = pIter->rc; @@ -225297,6 +230878,31 @@ SQLITE_API int sqlite3changegroup_new(sqlite3_changegroup **pp){ return rc; } +/* +** Provide a database schema to the changegroup object. +*/ +SQLITE_API int sqlite3changegroup_schema( + sqlite3_changegroup *pGrp, + sqlite3 *db, + const char *zDb +){ + int rc = SQLITE_OK; + + if( pGrp->pList || pGrp->db ){ + /* Cannot add a schema after one or more calls to sqlite3changegroup_add(), + ** or after sqlite3changegroup_schema() has already been called. */ + rc = SQLITE_MISUSE; + }else{ + pGrp->zDb = sqlite3_mprintf("%s", zDb); + if( pGrp->zDb==0 ){ + rc = SQLITE_NOMEM; + }else{ + pGrp->db = db; + } + } + return rc; +} + /* ** Add the changeset currently stored in buffer pData, size nData bytes, ** to changeset-group p. @@ -225313,6 +230919,23 @@ SQLITE_API int sqlite3changegroup_add(sqlite3_changegroup *pGrp, int nData, void return rc; } +/* +** Add a single change to a changeset-group. +*/ +SQLITE_API int sqlite3changegroup_add_change( + sqlite3_changegroup *pGrp, + sqlite3_changeset_iter *pIter +){ + if( pIter->in.iCurrent==pIter->in.iNext + || pIter->rc!=SQLITE_OK + || pIter->bInvert + ){ + /* Iterator does not point to any valid entry or is an INVERT iterator. */ + return SQLITE_ERROR; + } + return sessionOneChangeToHash(pGrp, pIter, 0); +} + /* ** Obtain a buffer containing a changeset representing the concatenation ** of all changesets added to the group so far. @@ -225360,7 +230983,9 @@ SQLITE_API int sqlite3changegroup_output_strm( */ SQLITE_API void sqlite3changegroup_delete(sqlite3_changegroup *pGrp){ if( pGrp ){ + sqlite3_free(pGrp->zDb); sessionDeleteTable(0, pGrp->pList); + sqlite3_free(pGrp->rec.aBuf); sqlite3_free(pGrp); } } @@ -225762,6 +231387,7 @@ SQLITE_API int sqlite3rebaser_rebase_strm( SQLITE_API void sqlite3rebaser_delete(sqlite3_rebaser *p){ if( p ){ sessionDeleteTable(0, p->grp.pList); + sqlite3_free(p->grp.rec.aBuf); sqlite3_free(p); } } @@ -225859,8 +231485,8 @@ struct Fts5PhraseIter { ** EXTENSION API FUNCTIONS ** ** xUserData(pFts): -** Return a copy of the context pointer the extension function was -** registered with. +** Return a copy of the pUserData pointer passed to the xCreateFunction() +** API when the extension function was registered. ** ** xColumnTotalSize(pFts, iCol, pnToken): ** If parameter iCol is less than zero, set output variable *pnToken @@ -225892,8 +231518,11 @@ struct Fts5PhraseIter { ** created with the "columnsize=0" option. ** ** xColumnText: -** This function attempts to retrieve the text of column iCol of the -** current document. If successful, (*pz) is set to point to a buffer +** If parameter iCol is less than zero, or greater than or equal to the +** number of columns in the table, SQLITE_RANGE is returned. +** +** Otherwise, this function attempts to retrieve the text of column iCol of +** the current document. If successful, (*pz) is set to point to a buffer ** containing the text in utf-8 encoding, (*pn) is set to the size in bytes ** (not characters) of the buffer and SQLITE_OK is returned. Otherwise, ** if an error occurs, an SQLite error code is returned and the final values @@ -225903,8 +231532,10 @@ struct Fts5PhraseIter { ** Returns the number of phrases in the current query expression. ** ** xPhraseSize: -** Returns the number of tokens in phrase iPhrase of the query. Phrases -** are numbered starting from zero. +** If parameter iCol is less than zero, or greater than or equal to the +** number of phrases in the current query, as returned by xPhraseCount, +** 0 is returned. Otherwise, this function returns the number of tokens in +** phrase iPhrase of the query. Phrases are numbered starting from zero. ** ** xInstCount: ** Set *pnInst to the total number of occurrences of all phrases within @@ -225920,12 +231551,13 @@ struct Fts5PhraseIter { ** Query for the details of phrase match iIdx within the current row. ** Phrase matches are numbered starting from zero, so the iIdx argument ** should be greater than or equal to zero and smaller than the value -** output by xInstCount(). +** output by xInstCount(). If iIdx is less than zero or greater than +** or equal to the value returned by xInstCount(), SQLITE_RANGE is returned. ** -** Usually, output parameter *piPhrase is set to the phrase number, *piCol +** Otherwise, output parameter *piPhrase is set to the phrase number, *piCol ** to the column in which it occurs and *piOff the token offset of the -** first token of the phrase. Returns SQLITE_OK if successful, or an error -** code (i.e. SQLITE_NOMEM) if an error occurs. +** first token of the phrase. SQLITE_OK is returned if successful, or an +** error code (i.e. SQLITE_NOMEM) if an error occurs. ** ** This API can be quite slow if used with an FTS5 table created with the ** "detail=none" or "detail=column" option. @@ -225951,6 +231583,10 @@ struct Fts5PhraseIter { ** Invoking Api.xUserData() returns a copy of the pointer passed as ** the third argument to pUserData. ** +** If parameter iPhrase is less than zero, or greater than or equal to +** the number of phrases in the query, as returned by xPhraseCount(), +** this function returns SQLITE_RANGE. +** ** If the callback function returns any value other than SQLITE_OK, the ** query is abandoned and the xQueryPhrase function returns immediately. ** If the returned value is SQLITE_DONE, xQueryPhrase returns SQLITE_OK. @@ -226065,9 +231701,42 @@ struct Fts5PhraseIter { ** ** xPhraseNextColumn() ** See xPhraseFirstColumn above. +** +** xQueryToken(pFts5, iPhrase, iToken, ppToken, pnToken) +** This is used to access token iToken of phrase iPhrase of the current +** query. Before returning, output parameter *ppToken is set to point +** to a buffer containing the requested token, and *pnToken to the +** size of this buffer in bytes. +** +** If iPhrase or iToken are less than zero, or if iPhrase is greater than +** or equal to the number of phrases in the query as reported by +** xPhraseCount(), or if iToken is equal to or greater than the number of +** tokens in the phrase, SQLITE_RANGE is returned and *ppToken and *pnToken + are both zeroed. +** +** The output text is not a copy of the query text that specified the +** token. It is the output of the tokenizer module. For tokendata=1 +** tables, this includes any embedded 0x00 and trailing data. +** +** xInstToken(pFts5, iIdx, iToken, ppToken, pnToken) +** This is used to access token iToken of phrase hit iIdx within the +** current row. If iIdx is less than zero or greater than or equal to the +** value returned by xInstCount(), SQLITE_RANGE is returned. Otherwise, +** output variable (*ppToken) is set to point to a buffer containing the +** matching document token, and (*pnToken) to the size of that buffer in +** bytes. This API is not available if the specified token matches a +** prefix query term. In that case both output variables are always set +** to 0. +** +** The output text is not a copy of the document text that was tokenized. +** It is the output of the tokenizer module. For tokendata=1 tables, this +** includes any embedded 0x00 and trailing data. +** +** This API can be quite slow if used with an FTS5 table created with the +** "detail=none" or "detail=column" option. */ struct Fts5ExtensionApi { - int iVersion; /* Currently always set to 2 */ + int iVersion; /* Currently always set to 3 */ void *(*xUserData)(Fts5Context*); @@ -226102,6 +231771,13 @@ struct Fts5ExtensionApi { int (*xPhraseFirstColumn)(Fts5Context*, int iPhrase, Fts5PhraseIter*, int*); void (*xPhraseNextColumn)(Fts5Context*, Fts5PhraseIter*, int *piCol); + + /* Below this point are iVersion>=3 only */ + int (*xQueryToken)(Fts5Context*, + int iPhrase, int iToken, + const char **ppToken, int *pnToken + ); + int (*xInstToken)(Fts5Context*, int iIdx, int iToken, const char**, int*); }; /* @@ -226576,6 +232252,7 @@ struct Fts5Config { char *zContent; /* content table */ char *zContentRowid; /* "content_rowid=" option value */ int bColumnsize; /* "columnsize=" option value (dflt==1) */ + int bTokendata; /* "tokendata=" option value (dflt==0) */ int eDetail; /* FTS5_DETAIL_XXX value */ char *zContentExprlist; Fts5Tokenizer *pTok; @@ -226764,17 +232441,19 @@ struct Fts5IndexIter { /* ** Values used as part of the flags argument passed to IndexQuery(). */ -#define FTS5INDEX_QUERY_PREFIX 0x0001 /* Prefix query */ -#define FTS5INDEX_QUERY_DESC 0x0002 /* Docs in descending rowid order */ -#define FTS5INDEX_QUERY_TEST_NOIDX 0x0004 /* Do not use prefix index */ -#define FTS5INDEX_QUERY_SCAN 0x0008 /* Scan query (fts5vocab) */ +#define FTS5INDEX_QUERY_PREFIX 0x0001 /* Prefix query */ +#define FTS5INDEX_QUERY_DESC 0x0002 /* Docs in descending rowid order */ +#define FTS5INDEX_QUERY_TEST_NOIDX 0x0004 /* Do not use prefix index */ +#define FTS5INDEX_QUERY_SCAN 0x0008 /* Scan query (fts5vocab) */ /* The following are used internally by the fts5_index.c module. They are ** defined here only to make it easier to avoid clashes with the flags ** above. */ -#define FTS5INDEX_QUERY_SKIPEMPTY 0x0010 -#define FTS5INDEX_QUERY_NOOUTPUT 0x0020 -#define FTS5INDEX_QUERY_SKIPHASH 0x0040 +#define FTS5INDEX_QUERY_SKIPEMPTY 0x0010 +#define FTS5INDEX_QUERY_NOOUTPUT 0x0020 +#define FTS5INDEX_QUERY_SKIPHASH 0x0040 +#define FTS5INDEX_QUERY_NOTOKENDATA 0x0080 +#define FTS5INDEX_QUERY_SCANONETERM 0x0100 /* ** Create/destroy an Fts5Index object. @@ -226843,6 +232522,10 @@ static void *sqlite3Fts5StructureRef(Fts5Index*); static void sqlite3Fts5StructureRelease(void*); static int sqlite3Fts5StructureTest(Fts5Index*, void*); +/* +** Used by xInstToken(): +*/ +static int sqlite3Fts5IterToken(Fts5IndexIter*, i64, int, int, const char**, int*); /* ** Insert or remove data to or from the index. Each time a document is @@ -226920,6 +232603,13 @@ static int sqlite3Fts5IndexLoadConfig(Fts5Index *p); static int sqlite3Fts5IndexGetOrigin(Fts5Index *p, i64 *piOrigin); static int sqlite3Fts5IndexContentlessDelete(Fts5Index *p, i64 iOrigin, i64 iRowid); +static void sqlite3Fts5IndexIterClearTokendata(Fts5IndexIter*); + +/* Used to populate hash tables for xInstToken in detail=none/column mode. */ +static int sqlite3Fts5IndexIterWriteTokendata( + Fts5IndexIter*, const char*, int, i64 iRowid, int iCol, int iOff +); + /* ** End of interface to code in fts5_index.c. **************************************************************************/ @@ -227025,6 +232715,7 @@ static void sqlite3Fts5HashScanNext(Fts5Hash*); static int sqlite3Fts5HashScanEof(Fts5Hash*); static void sqlite3Fts5HashScanEntry(Fts5Hash *, const char **pzTerm, /* OUT: term (nul-terminated) */ + int *pnTerm, /* OUT: Size of term in bytes */ const u8 **ppDoclist, /* OUT: pointer to doclist */ int *pnDoclist /* OUT: size of doclist in bytes */ ); @@ -227151,6 +232842,10 @@ static int sqlite3Fts5ExprClonePhrase(Fts5Expr*, int, Fts5Expr**); static int sqlite3Fts5ExprPhraseCollist(Fts5Expr *, int, const u8 **, int *); +static int sqlite3Fts5ExprQueryToken(Fts5Expr*, int, int, const char**, int*); +static int sqlite3Fts5ExprInstToken(Fts5Expr*, i64, int, int, int, int, const char**, int*); +static void sqlite3Fts5ExprClearTokens(Fts5Expr*); + /******************************************* ** The fts5_expr.c API above this point is used by the other hand-written ** C code in this module. The interfaces below this point are called by @@ -227387,6 +233082,9 @@ static void sqlite3Fts5UnicodeAscii(u8*, u8*); ** sqlite3Fts5ParserARG_STORE Code to store %extra_argument into fts5yypParser ** sqlite3Fts5ParserARG_FETCH Code to extract %extra_argument from fts5yypParser ** sqlite3Fts5ParserCTX_* As sqlite3Fts5ParserARG_ except for %extra_context +** fts5YYREALLOC Name of the realloc() function to use +** fts5YYFREE Name of the free() function to use +** fts5YYDYNSTACK True if stack space should be extended on heap ** fts5YYERRORSYMBOL is the code number of the error symbol. If not ** defined, then do no error processing. ** fts5YYNSTATE the combined number of states. @@ -227400,6 +233098,8 @@ static void sqlite3Fts5UnicodeAscii(u8*, u8*); ** fts5YY_NO_ACTION The fts5yy_action[] code for no-op ** fts5YY_MIN_REDUCE Minimum value for reduce actions ** fts5YY_MAX_REDUCE Maximum value for reduce actions +** fts5YY_MIN_DSTRCTR Minimum symbol value that has a destructor +** fts5YY_MAX_DSTRCTR Maximum symbol value that has a destructor */ #ifndef INTERFACE # define INTERFACE 1 @@ -227426,6 +233126,9 @@ typedef union { #define sqlite3Fts5ParserARG_PARAM ,pParse #define sqlite3Fts5ParserARG_FETCH Fts5Parse *pParse=fts5yypParser->pParse; #define sqlite3Fts5ParserARG_STORE fts5yypParser->pParse=pParse; +#define fts5YYREALLOC realloc +#define fts5YYFREE free +#define fts5YYDYNSTACK 0 #define sqlite3Fts5ParserCTX_SDECL #define sqlite3Fts5ParserCTX_PDECL #define sqlite3Fts5ParserCTX_PARAM @@ -227443,6 +233146,8 @@ typedef union { #define fts5YY_NO_ACTION 82 #define fts5YY_MIN_REDUCE 83 #define fts5YY_MAX_REDUCE 110 +#define fts5YY_MIN_DSTRCTR 16 +#define fts5YY_MAX_DSTRCTR 24 /************* End control #defines *******************************************/ #define fts5YY_NLOOKAHEAD ((int)(sizeof(fts5yy_lookahead)/sizeof(fts5yy_lookahead[0]))) @@ -227458,6 +233163,22 @@ typedef union { # define fts5yytestcase(X) #endif +/* Macro to determine if stack space has the ability to grow using +** heap memory. +*/ +#if fts5YYSTACKDEPTH<=0 || fts5YYDYNSTACK +# define fts5YYGROWABLESTACK 1 +#else +# define fts5YYGROWABLESTACK 0 +#endif + +/* Guarantee a minimum number of initial stack slots. +*/ +#if fts5YYSTACKDEPTH<=0 +# undef fts5YYSTACKDEPTH +# define fts5YYSTACKDEPTH 2 /* Need a minimum stack size */ +#endif + /* Next are the tables used to determine what action to take based on the ** current state and lookahead token. These tables are used to implement @@ -227618,14 +233339,9 @@ struct fts5yyParser { #endif sqlite3Fts5ParserARG_SDECL /* A place to hold %extra_argument */ sqlite3Fts5ParserCTX_SDECL /* A place to hold %extra_context */ -#if fts5YYSTACKDEPTH<=0 - int fts5yystksz; /* Current side of the stack */ - fts5yyStackEntry *fts5yystack; /* The parser's stack */ - fts5yyStackEntry fts5yystk0; /* First stack entry */ -#else - fts5yyStackEntry fts5yystack[fts5YYSTACKDEPTH]; /* The parser's stack */ - fts5yyStackEntry *fts5yystackEnd; /* Last entry in the stack */ -#endif + fts5yyStackEntry *fts5yystackEnd; /* Last entry in the stack */ + fts5yyStackEntry *fts5yystack; /* The parser stack */ + fts5yyStackEntry fts5yystk0[fts5YYSTACKDEPTH]; /* Initial stack space */ }; typedef struct fts5yyParser fts5yyParser; @@ -227732,37 +233448,45 @@ static const char *const fts5yyRuleName[] = { #endif /* NDEBUG */ -#if fts5YYSTACKDEPTH<=0 +#if fts5YYGROWABLESTACK /* ** Try to increase the size of the parser stack. Return the number ** of errors. Return 0 on success. */ static int fts5yyGrowStack(fts5yyParser *p){ + int oldSize = 1 + (int)(p->fts5yystackEnd - p->fts5yystack); int newSize; int idx; fts5yyStackEntry *pNew; - newSize = p->fts5yystksz*2 + 100; - idx = p->fts5yytos ? (int)(p->fts5yytos - p->fts5yystack) : 0; - if( p->fts5yystack==&p->fts5yystk0 ){ - pNew = malloc(newSize*sizeof(pNew[0])); - if( pNew ) pNew[0] = p->fts5yystk0; + newSize = oldSize*2 + 100; + idx = (int)(p->fts5yytos - p->fts5yystack); + if( p->fts5yystack==p->fts5yystk0 ){ + pNew = fts5YYREALLOC(0, newSize*sizeof(pNew[0])); + if( pNew==0 ) return 1; + memcpy(pNew, p->fts5yystack, oldSize*sizeof(pNew[0])); }else{ - pNew = realloc(p->fts5yystack, newSize*sizeof(pNew[0])); + pNew = fts5YYREALLOC(p->fts5yystack, newSize*sizeof(pNew[0])); + if( pNew==0 ) return 1; } - if( pNew ){ - p->fts5yystack = pNew; - p->fts5yytos = &p->fts5yystack[idx]; + p->fts5yystack = pNew; + p->fts5yytos = &p->fts5yystack[idx]; #ifndef NDEBUG - if( fts5yyTraceFILE ){ - fprintf(fts5yyTraceFILE,"%sStack grows from %d to %d entries.\n", - fts5yyTracePrompt, p->fts5yystksz, newSize); - } -#endif - p->fts5yystksz = newSize; + if( fts5yyTraceFILE ){ + fprintf(fts5yyTraceFILE,"%sStack grows from %d to %d entries.\n", + fts5yyTracePrompt, oldSize, newSize); } - return pNew==0; +#endif + p->fts5yystackEnd = &p->fts5yystack[newSize-1]; + return 0; } +#endif /* fts5YYGROWABLESTACK */ + +#if !fts5YYGROWABLESTACK +/* For builds that do no have a growable stack, fts5yyGrowStack always +** returns an error. +*/ +# define fts5yyGrowStack(X) 1 #endif /* Datatype of the argument to the memory allocated passed as the @@ -227782,24 +233506,14 @@ static void sqlite3Fts5ParserInit(void *fts5yypRawParser sqlite3Fts5ParserCTX_PD #ifdef fts5YYTRACKMAXSTACKDEPTH fts5yypParser->fts5yyhwm = 0; #endif -#if fts5YYSTACKDEPTH<=0 - fts5yypParser->fts5yytos = NULL; - fts5yypParser->fts5yystack = NULL; - fts5yypParser->fts5yystksz = 0; - if( fts5yyGrowStack(fts5yypParser) ){ - fts5yypParser->fts5yystack = &fts5yypParser->fts5yystk0; - fts5yypParser->fts5yystksz = 1; - } -#endif + fts5yypParser->fts5yystack = fts5yypParser->fts5yystk0; + fts5yypParser->fts5yystackEnd = &fts5yypParser->fts5yystack[fts5YYSTACKDEPTH-1]; #ifndef fts5YYNOERRORRECOVERY fts5yypParser->fts5yyerrcnt = -1; #endif fts5yypParser->fts5yytos = fts5yypParser->fts5yystack; fts5yypParser->fts5yystack[0].stateno = 0; fts5yypParser->fts5yystack[0].major = 0; -#if fts5YYSTACKDEPTH>0 - fts5yypParser->fts5yystackEnd = &fts5yypParser->fts5yystack[fts5YYSTACKDEPTH-1]; -#endif } #ifndef sqlite3Fts5Parser_ENGINEALWAYSONSTACK @@ -227913,9 +233627,26 @@ static void fts5yy_pop_parser_stack(fts5yyParser *pParser){ */ static void sqlite3Fts5ParserFinalize(void *p){ fts5yyParser *pParser = (fts5yyParser*)p; - while( pParser->fts5yytos>pParser->fts5yystack ) fts5yy_pop_parser_stack(pParser); -#if fts5YYSTACKDEPTH<=0 - if( pParser->fts5yystack!=&pParser->fts5yystk0 ) free(pParser->fts5yystack); + + /* In-lined version of calling fts5yy_pop_parser_stack() for each + ** element left in the stack */ + fts5yyStackEntry *fts5yytos = pParser->fts5yytos; + while( fts5yytos>pParser->fts5yystack ){ +#ifndef NDEBUG + if( fts5yyTraceFILE ){ + fprintf(fts5yyTraceFILE,"%sPopping %s\n", + fts5yyTracePrompt, + fts5yyTokenName[fts5yytos->major]); + } +#endif + if( fts5yytos->major>=fts5YY_MIN_DSTRCTR ){ + fts5yy_destructor(pParser, fts5yytos->major, &fts5yytos->minor); + } + fts5yytos--; + } + +#if fts5YYGROWABLESTACK + if( pParser->fts5yystack!=pParser->fts5yystk0 ) fts5YYFREE(pParser->fts5yystack); #endif } @@ -228142,25 +233873,19 @@ static void fts5yy_shift( assert( fts5yypParser->fts5yyhwm == (int)(fts5yypParser->fts5yytos - fts5yypParser->fts5yystack) ); } #endif -#if fts5YYSTACKDEPTH>0 - if( fts5yypParser->fts5yytos>fts5yypParser->fts5yystackEnd ){ - fts5yypParser->fts5yytos--; - fts5yyStackOverflow(fts5yypParser); - return; - } -#else - if( fts5yypParser->fts5yytos>=&fts5yypParser->fts5yystack[fts5yypParser->fts5yystksz] ){ + fts5yytos = fts5yypParser->fts5yytos; + if( fts5yytos>fts5yypParser->fts5yystackEnd ){ if( fts5yyGrowStack(fts5yypParser) ){ fts5yypParser->fts5yytos--; fts5yyStackOverflow(fts5yypParser); return; } + fts5yytos = fts5yypParser->fts5yytos; + assert( fts5yytos <= fts5yypParser->fts5yystackEnd ); } -#endif if( fts5yyNewState > fts5YY_MAX_SHIFT ){ fts5yyNewState += fts5YY_MIN_REDUCE - fts5YY_MIN_SHIFTREDUCE; } - fts5yytos = fts5yypParser->fts5yytos; fts5yytos->stateno = fts5yyNewState; fts5yytos->major = fts5yyMajor; fts5yytos->minor.fts5yy0 = fts5yyMinor; @@ -228597,19 +234322,12 @@ static void sqlite3Fts5Parser( (int)(fts5yypParser->fts5yytos - fts5yypParser->fts5yystack)); } #endif -#if fts5YYSTACKDEPTH>0 if( fts5yypParser->fts5yytos>=fts5yypParser->fts5yystackEnd ){ - fts5yyStackOverflow(fts5yypParser); - break; - } -#else - if( fts5yypParser->fts5yytos>=&fts5yypParser->fts5yystack[fts5yypParser->fts5yystksz-1] ){ if( fts5yyGrowStack(fts5yypParser) ){ fts5yyStackOverflow(fts5yypParser); break; } } -#endif } fts5yyact = fts5yy_reduce(fts5yypParser,fts5yyruleno,fts5yymajor,fts5yyminor sqlite3Fts5ParserCTX_PARAM); }else if( fts5yyact <= fts5YY_MAX_SHIFTREDUCE ){ @@ -228865,15 +234583,19 @@ static int fts5CInstIterInit( */ typedef struct HighlightContext HighlightContext; struct HighlightContext { - CInstIter iter; /* Coalesced Instance Iterator */ - int iPos; /* Current token offset in zIn[] */ + /* Constant parameters to fts5HighlightCb() */ int iRangeStart; /* First token to include */ int iRangeEnd; /* If non-zero, last token to include */ const char *zOpen; /* Opening highlight */ const char *zClose; /* Closing highlight */ const char *zIn; /* Input text */ int nIn; /* Size of input text in bytes */ - int iOff; /* Current offset within zIn[] */ + + /* Variables modified by fts5HighlightCb() */ + CInstIter iter; /* Coalesced Instance Iterator */ + int iPos; /* Current token offset in zIn[] */ + int iOff; /* Have copied up to this offset in zIn[] */ + int bOpen; /* True if highlight is open */ char *zOut; /* Output value */ }; @@ -228906,8 +234628,8 @@ static int fts5HighlightCb( int tflags, /* Mask of FTS5_TOKEN_* flags */ const char *pToken, /* Buffer containing token */ int nToken, /* Size of token in bytes */ - int iStartOff, /* Start offset of token */ - int iEndOff /* End offset of token */ + int iStartOff, /* Start byte offset of token */ + int iEndOff /* End byte offset of token */ ){ HighlightContext *p = (HighlightContext*)pContext; int rc = SQLITE_OK; @@ -228923,30 +234645,55 @@ static int fts5HighlightCb( if( p->iRangeStart && iPos==p->iRangeStart ) p->iOff = iStartOff; } - if( iPos==p->iter.iStart ){ + /* If the parenthesis is open, and this token is not part of the current + ** phrase, and the starting byte offset of this token is past the point + ** that has currently been copied into the output buffer, close the + ** parenthesis. */ + if( p->bOpen + && (iPos<=p->iter.iStart || p->iter.iStart<0) + && iStartOff>p->iOff + ){ + fts5HighlightAppend(&rc, p, p->zClose, -1); + p->bOpen = 0; + } + + /* If this is the start of a new phrase, and the highlight is not open: + ** + ** * copy text from the input up to the start of the phrase, and + ** * open the highlight. + */ + if( iPos==p->iter.iStart && p->bOpen==0 ){ fts5HighlightAppend(&rc, p, &p->zIn[p->iOff], iStartOff - p->iOff); fts5HighlightAppend(&rc, p, p->zOpen, -1); p->iOff = iStartOff; + p->bOpen = 1; } if( iPos==p->iter.iEnd ){ - if( p->iRangeEnd>=0 && p->iter.iStartiRangeStart ){ + if( p->bOpen==0 ){ + assert( p->iRangeEnd>=0 ); fts5HighlightAppend(&rc, p, p->zOpen, -1); + p->bOpen = 1; } fts5HighlightAppend(&rc, p, &p->zIn[p->iOff], iEndOff - p->iOff); - fts5HighlightAppend(&rc, p, p->zClose, -1); p->iOff = iEndOff; + if( rc==SQLITE_OK ){ rc = fts5CInstIterNext(&p->iter); } } - if( p->iRangeEnd>=0 && iPos==p->iRangeEnd ){ - fts5HighlightAppend(&rc, p, &p->zIn[p->iOff], iEndOff - p->iOff); - p->iOff = iEndOff; - if( iPos>=p->iter.iStart && iPositer.iEnd ){ + if( iPos==p->iRangeEnd ){ + if( p->bOpen ){ + if( p->iter.iStart>=0 && iPos>=p->iter.iStart ){ + fts5HighlightAppend(&rc, p, &p->zIn[p->iOff], iEndOff - p->iOff); + p->iOff = iEndOff; + } fts5HighlightAppend(&rc, p, p->zClose, -1); + p->bOpen = 0; } + fts5HighlightAppend(&rc, p, &p->zIn[p->iOff], iEndOff - p->iOff); + p->iOff = iEndOff; } return rc; @@ -228978,8 +234725,10 @@ static void fts5HighlightFunction( ctx.zClose = (const char*)sqlite3_value_text(apVal[2]); ctx.iRangeEnd = -1; rc = pApi->xColumnText(pFts, iCol, &ctx.zIn, &ctx.nIn); - - if( ctx.zIn ){ + if( rc==SQLITE_RANGE ){ + sqlite3_result_text(pCtx, "", -1, SQLITE_STATIC); + rc = SQLITE_OK; + }else if( ctx.zIn ){ if( rc==SQLITE_OK ){ rc = fts5CInstIterInit(pApi, pFts, iCol, &ctx.iter); } @@ -228987,6 +234736,9 @@ static void fts5HighlightFunction( if( rc==SQLITE_OK ){ rc = pApi->xTokenize(pFts, ctx.zIn, ctx.nIn, (void*)&ctx,fts5HighlightCb); } + if( ctx.bOpen ){ + fts5HighlightAppend(&rc, &ctx, ctx.zClose, -1); + } fts5HighlightAppend(&rc, &ctx, &ctx.zIn[ctx.iOff], ctx.nIn - ctx.iOff); if( rc==SQLITE_OK ){ @@ -229265,6 +235017,9 @@ static void fts5SnippetFunction( if( rc==SQLITE_OK ){ rc = pApi->xTokenize(pFts, ctx.zIn, ctx.nIn, (void*)&ctx,fts5HighlightCb); } + if( ctx.bOpen ){ + fts5HighlightAppend(&rc, &ctx, ctx.zClose, -1); + } if( ctx.iRangeEnd>=(nColSize-1) ){ fts5HighlightAppend(&rc, &ctx, &ctx.zIn[ctx.iOff], ctx.nIn - ctx.iOff); }else{ @@ -229540,6 +235295,7 @@ static void sqlite3Fts5BufferAppendBlob( ){ if( nData ){ if( fts5BufferGrow(pRc, pBuf, nData) ) return; + assert( pBuf->p!=0 ); memcpy(&pBuf->p[pBuf->n], pData, nData); pBuf->n += nData; } @@ -229641,6 +235397,7 @@ static int sqlite3Fts5PoslistNext64( i64 *piOff /* IN/OUT: Current offset */ ){ int i = *pi; + assert( a!=0 || i==0 ); if( i>=n ){ /* EOF */ *piOff = -1; @@ -229648,6 +235405,7 @@ static int sqlite3Fts5PoslistNext64( }else{ i64 iOff = *piOff; u32 iVal; + assert( a!=0 ); fts5FastGetVarint32(a, i, iVal); if( iVal<=1 ){ if( iVal==0 ){ @@ -230279,6 +236037,16 @@ static int fts5ConfigParseSpecial( return rc; } + if( sqlite3_strnicmp("tokendata", zCmd, nCmd)==0 ){ + if( (zArg[0]!='0' && zArg[0]!='1') || zArg[1]!='\0' ){ + *pzErr = sqlite3_mprintf("malformed tokendata=... directive"); + rc = SQLITE_ERROR; + }else{ + pConfig->bTokendata = (zArg[0]=='1'); + } + return rc; + } + *pzErr = sqlite3_mprintf("unrecognized option: \"%.*s\"", nCmd, zCmd); return SQLITE_ERROR; } @@ -231012,7 +236780,9 @@ struct Fts5ExprNode { struct Fts5ExprTerm { u8 bPrefix; /* True for a prefix term */ u8 bFirst; /* True if token must be first in column */ - char *zTerm; /* nul-terminated term */ + char *pTerm; /* Term data */ + int nQueryTerm; /* Effective size of term in bytes */ + int nFullTerm; /* Size of term in bytes incl. tokendata */ Fts5IndexIter *pIter; /* Iterator for this term */ Fts5ExprTerm *pSynonym; /* Pointer to first in list of synonyms */ }; @@ -231879,7 +237649,7 @@ static int fts5ExprNearInitAll( p->pIter = 0; } rc = sqlite3Fts5IndexQuery( - pExpr->pIndex, p->zTerm, (int)strlen(p->zTerm), + pExpr->pIndex, p->pTerm, p->nQueryTerm, (pTerm->bPrefix ? FTS5INDEX_QUERY_PREFIX : 0) | (pExpr->bDesc ? FTS5INDEX_QUERY_DESC : 0), pNear->pColset, @@ -232516,7 +238286,7 @@ static void fts5ExprPhraseFree(Fts5ExprPhrase *pPhrase){ Fts5ExprTerm *pSyn; Fts5ExprTerm *pNext; Fts5ExprTerm *pTerm = &pPhrase->aTerm[i]; - sqlite3_free(pTerm->zTerm); + sqlite3_free(pTerm->pTerm); sqlite3Fts5IterClose(pTerm->pIter); for(pSyn=pTerm->pSynonym; pSyn; pSyn=pNext){ pNext = pSyn->pSynonym; @@ -232614,6 +238384,7 @@ static Fts5ExprNearset *sqlite3Fts5ParseNearset( typedef struct TokenCtx TokenCtx; struct TokenCtx { Fts5ExprPhrase *pPhrase; + Fts5Config *pConfig; int rc; }; @@ -232647,8 +238418,12 @@ static int fts5ParseTokenize( rc = SQLITE_NOMEM; }else{ memset(pSyn, 0, (size_t)nByte); - pSyn->zTerm = ((char*)pSyn) + sizeof(Fts5ExprTerm) + sizeof(Fts5Buffer); - memcpy(pSyn->zTerm, pToken, nToken); + pSyn->pTerm = ((char*)pSyn) + sizeof(Fts5ExprTerm) + sizeof(Fts5Buffer); + pSyn->nFullTerm = pSyn->nQueryTerm = nToken; + if( pCtx->pConfig->bTokendata ){ + pSyn->nQueryTerm = (int)strlen(pSyn->pTerm); + } + memcpy(pSyn->pTerm, pToken, nToken); pSyn->pSynonym = pPhrase->aTerm[pPhrase->nTerm-1].pSynonym; pPhrase->aTerm[pPhrase->nTerm-1].pSynonym = pSyn; } @@ -232673,7 +238448,11 @@ static int fts5ParseTokenize( if( rc==SQLITE_OK ){ pTerm = &pPhrase->aTerm[pPhrase->nTerm++]; memset(pTerm, 0, sizeof(Fts5ExprTerm)); - pTerm->zTerm = sqlite3Fts5Strndup(&rc, pToken, nToken); + pTerm->pTerm = sqlite3Fts5Strndup(&rc, pToken, nToken); + pTerm->nFullTerm = pTerm->nQueryTerm = nToken; + if( pCtx->pConfig->bTokendata && rc==SQLITE_OK ){ + pTerm->nQueryTerm = (int)strlen(pTerm->pTerm); + } } } @@ -232740,6 +238519,7 @@ static Fts5ExprPhrase *sqlite3Fts5ParseTerm( memset(&sCtx, 0, sizeof(TokenCtx)); sCtx.pPhrase = pAppend; + sCtx.pConfig = pConfig; rc = fts5ParseStringFromToken(pToken, &z); if( rc==SQLITE_OK ){ @@ -232787,12 +238567,15 @@ static int sqlite3Fts5ExprClonePhrase( Fts5Expr **ppNew ){ int rc = SQLITE_OK; /* Return code */ - Fts5ExprPhrase *pOrig; /* The phrase extracted from pExpr */ + Fts5ExprPhrase *pOrig = 0; /* The phrase extracted from pExpr */ Fts5Expr *pNew = 0; /* Expression to return via *ppNew */ - TokenCtx sCtx = {0,0}; /* Context object for fts5ParseTokenize */ - - pOrig = pExpr->apExprPhrase[iPhrase]; - pNew = (Fts5Expr*)sqlite3Fts5MallocZero(&rc, sizeof(Fts5Expr)); + TokenCtx sCtx = {0,0,0}; /* Context object for fts5ParseTokenize */ + if( iPhrase<0 || iPhrase>=pExpr->nPhrase ){ + rc = SQLITE_RANGE; + }else{ + pOrig = pExpr->apExprPhrase[iPhrase]; + pNew = (Fts5Expr*)sqlite3Fts5MallocZero(&rc, sizeof(Fts5Expr)); + } if( rc==SQLITE_OK ){ pNew->apExprPhrase = (Fts5ExprPhrase**)sqlite3Fts5MallocZero(&rc, sizeof(Fts5ExprPhrase*)); @@ -232805,7 +238588,7 @@ static int sqlite3Fts5ExprClonePhrase( pNew->pRoot->pNear = (Fts5ExprNearset*)sqlite3Fts5MallocZero(&rc, sizeof(Fts5ExprNearset) + sizeof(Fts5ExprPhrase*)); } - if( rc==SQLITE_OK ){ + if( rc==SQLITE_OK && ALWAYS(pOrig!=0) ){ Fts5Colset *pColsetOrig = pOrig->pNode->pNear->pColset; if( pColsetOrig ){ sqlite3_int64 nByte; @@ -232819,26 +238602,27 @@ static int sqlite3Fts5ExprClonePhrase( } } - if( pOrig->nTerm ){ - int i; /* Used to iterate through phrase terms */ - for(i=0; rc==SQLITE_OK && inTerm; i++){ - int tflags = 0; - Fts5ExprTerm *p; - for(p=&pOrig->aTerm[i]; p && rc==SQLITE_OK; p=p->pSynonym){ - const char *zTerm = p->zTerm; - rc = fts5ParseTokenize((void*)&sCtx, tflags, zTerm, (int)strlen(zTerm), - 0, 0); - tflags = FTS5_TOKEN_COLOCATED; - } - if( rc==SQLITE_OK ){ - sCtx.pPhrase->aTerm[i].bPrefix = pOrig->aTerm[i].bPrefix; - sCtx.pPhrase->aTerm[i].bFirst = pOrig->aTerm[i].bFirst; + if( rc==SQLITE_OK ){ + if( pOrig->nTerm ){ + int i; /* Used to iterate through phrase terms */ + sCtx.pConfig = pExpr->pConfig; + for(i=0; rc==SQLITE_OK && inTerm; i++){ + int tflags = 0; + Fts5ExprTerm *p; + for(p=&pOrig->aTerm[i]; p && rc==SQLITE_OK; p=p->pSynonym){ + rc = fts5ParseTokenize((void*)&sCtx,tflags,p->pTerm,p->nFullTerm,0,0); + tflags = FTS5_TOKEN_COLOCATED; + } + if( rc==SQLITE_OK ){ + sCtx.pPhrase->aTerm[i].bPrefix = pOrig->aTerm[i].bPrefix; + sCtx.pPhrase->aTerm[i].bFirst = pOrig->aTerm[i].bFirst; + } } + }else{ + /* This happens when parsing a token or quoted phrase that contains + ** no token characters at all. (e.g ... MATCH '""'). */ + sCtx.pPhrase = sqlite3Fts5MallocZero(&rc, sizeof(Fts5ExprPhrase)); } - }else{ - /* This happens when parsing a token or quoted phrase that contains - ** no token characters at all. (e.g ... MATCH '""'). */ - sCtx.pPhrase = sqlite3Fts5MallocZero(&rc, sizeof(Fts5ExprPhrase)); } if( rc==SQLITE_OK && ALWAYS(sCtx.pPhrase) ){ @@ -233208,11 +238992,13 @@ static Fts5ExprNode *fts5ParsePhraseToAnd( if( parseGrowPhraseArray(pParse) ){ fts5ExprPhraseFree(pPhrase); }else{ + Fts5ExprTerm *p = &pNear->apPhrase[0]->aTerm[ii]; + Fts5ExprTerm *pTo = &pPhrase->aTerm[0]; pParse->apPhrase[pParse->nPhrase++] = pPhrase; pPhrase->nTerm = 1; - pPhrase->aTerm[0].zTerm = sqlite3Fts5Strndup( - &pParse->rc, pNear->apPhrase[0]->aTerm[ii].zTerm, -1 - ); + pTo->pTerm = sqlite3Fts5Strndup(&pParse->rc, p->pTerm, p->nFullTerm); + pTo->nQueryTerm = p->nQueryTerm; + pTo->nFullTerm = p->nFullTerm; pRet->apChild[ii] = sqlite3Fts5ParseNode(pParse, FTS5_STRING, 0, 0, sqlite3Fts5ParseNearset(pParse, 0, pPhrase) ); @@ -233397,16 +239183,17 @@ static char *fts5ExprTermPrint(Fts5ExprTerm *pTerm){ /* Determine the maximum amount of space required. */ for(p=pTerm; p; p=p->pSynonym){ - nByte += (int)strlen(pTerm->zTerm) * 2 + 3 + 2; + nByte += pTerm->nQueryTerm * 2 + 3 + 2; } zQuoted = sqlite3_malloc64(nByte); if( zQuoted ){ int i = 0; for(p=pTerm; p; p=p->pSynonym){ - char *zIn = p->zTerm; + char *zIn = p->pTerm; + char *zEnd = &zIn[p->nQueryTerm]; zQuoted[i++] = '"'; - while( *zIn ){ + while( zInnTerm; iTerm++){ - char *zTerm = pPhrase->aTerm[iTerm].zTerm; - zRet = fts5PrintfAppend(zRet, "%s%s", iTerm==0?"":" ", zTerm); + Fts5ExprTerm *p = &pPhrase->aTerm[iTerm]; + zRet = fts5PrintfAppend(zRet, "%s%.*s", iTerm==0?"":" ", + p->nQueryTerm, p->pTerm + ); if( pPhrase->aTerm[iTerm].bPrefix ){ zRet = fts5PrintfAppend(zRet, "*"); } @@ -233886,6 +239675,17 @@ static int fts5ExprColsetTest(Fts5Colset *pColset, int iCol){ return 0; } +/* +** pToken is a buffer nToken bytes in size that may or may not contain +** an embedded 0x00 byte. If it does, return the number of bytes in +** the buffer before the 0x00. If it does not, return nToken. +*/ +static int fts5QueryTerm(const char *pToken, int nToken){ + int ii; + for(ii=0; iipExpr; int i; + int nQuery = nToken; + i64 iRowid = pExpr->pRoot->iRowid; UNUSED_PARAM2(iUnused1, iUnused2); - if( nToken>FTS5_MAX_TOKEN_SIZE ) nToken = FTS5_MAX_TOKEN_SIZE; + if( nQuery>FTS5_MAX_TOKEN_SIZE ) nQuery = FTS5_MAX_TOKEN_SIZE; + if( pExpr->pConfig->bTokendata ){ + nQuery = fts5QueryTerm(pToken, nQuery); + } if( (tflags & FTS5_TOKEN_COLOCATED)==0 ) p->iOff++; for(i=0; inPhrase; i++){ - Fts5ExprTerm *pTerm; + Fts5ExprTerm *pT; if( p->aPopulator[i].bOk==0 ) continue; - for(pTerm=&pExpr->apExprPhrase[i]->aTerm[0]; pTerm; pTerm=pTerm->pSynonym){ - int nTerm = (int)strlen(pTerm->zTerm); - if( (nTerm==nToken || (nTermbPrefix)) - && memcmp(pTerm->zTerm, pToken, nTerm)==0 + for(pT=&pExpr->apExprPhrase[i]->aTerm[0]; pT; pT=pT->pSynonym){ + if( (pT->nQueryTerm==nQuery || (pT->nQueryTermbPrefix)) + && memcmp(pT->pTerm, pToken, pT->nQueryTerm)==0 ){ int rc = sqlite3Fts5PoslistWriterAppend( &pExpr->apExprPhrase[i]->poslist, &p->aPopulator[i].writer, p->iOff ); + if( rc==SQLITE_OK && pExpr->pConfig->bTokendata && !pT->bPrefix ){ + int iCol = p->iOff>>32; + int iTokOff = p->iOff & 0x7FFFFFFF; + rc = sqlite3Fts5IndexIterWriteTokendata( + pT->pIter, pToken, nToken, iRowid, iCol, iTokOff + ); + } if( rc ) return rc; break; } @@ -234048,6 +239859,83 @@ static int sqlite3Fts5ExprPhraseCollist( return rc; } +/* +** Does the work of the fts5_api.xQueryToken() API method. +*/ +static int sqlite3Fts5ExprQueryToken( + Fts5Expr *pExpr, + int iPhrase, + int iToken, + const char **ppOut, + int *pnOut +){ + Fts5ExprPhrase *pPhrase = 0; + + if( iPhrase<0 || iPhrase>=pExpr->nPhrase ){ + return SQLITE_RANGE; + } + pPhrase = pExpr->apExprPhrase[iPhrase]; + if( iToken<0 || iToken>=pPhrase->nTerm ){ + return SQLITE_RANGE; + } + + *ppOut = pPhrase->aTerm[iToken].pTerm; + *pnOut = pPhrase->aTerm[iToken].nFullTerm; + return SQLITE_OK; +} + +/* +** Does the work of the fts5_api.xInstToken() API method. +*/ +static int sqlite3Fts5ExprInstToken( + Fts5Expr *pExpr, + i64 iRowid, + int iPhrase, + int iCol, + int iOff, + int iToken, + const char **ppOut, + int *pnOut +){ + Fts5ExprPhrase *pPhrase = 0; + Fts5ExprTerm *pTerm = 0; + int rc = SQLITE_OK; + + if( iPhrase<0 || iPhrase>=pExpr->nPhrase ){ + return SQLITE_RANGE; + } + pPhrase = pExpr->apExprPhrase[iPhrase]; + if( iToken<0 || iToken>=pPhrase->nTerm ){ + return SQLITE_RANGE; + } + pTerm = &pPhrase->aTerm[iToken]; + if( pTerm->bPrefix==0 ){ + if( pExpr->pConfig->bTokendata ){ + rc = sqlite3Fts5IterToken( + pTerm->pIter, iRowid, iCol, iOff+iToken, ppOut, pnOut + ); + }else{ + *ppOut = pTerm->pTerm; + *pnOut = pTerm->nFullTerm; + } + } + return rc; +} + +/* +** Clear the token mappings for all Fts5IndexIter objects mannaged by +** the expression passed as the only argument. +*/ +static void sqlite3Fts5ExprClearTokens(Fts5Expr *pExpr){ + int ii; + for(ii=0; iinPhrase; ii++){ + Fts5ExprTerm *pT; + for(pT=&pExpr->apExprPhrase[ii]->aTerm[0]; pT; pT=pT->pSynonym){ + sqlite3Fts5IndexIterClearTokendata(pT->pIter); + } + } +} + /* ** 2014 August 11 ** @@ -234086,10 +239974,15 @@ struct Fts5Hash { /* ** Each entry in the hash table is represented by an object of the -** following type. Each object, its key (a nul-terminated string) and -** its current data are stored in a single memory allocation. The -** key immediately follows the object in memory. The position list -** data immediately follows the key data in memory. +** following type. Each object, its key, and its current data are stored +** in a single memory allocation. The key immediately follows the object +** in memory. The position list data immediately follows the key data +** in memory. +** +** The key is Fts5HashEntry.nKey bytes in size. It consists of a single +** byte identifying the index (either the main term index or a prefix-index), +** followed by the term data. For example: "0token". There is no +** nul-terminator - in this case nKey=6. ** ** The data that follows the key is in a similar, but not identical format ** to the doclist data stored in the database. It is: @@ -234224,8 +240117,7 @@ static int fts5HashResize(Fts5Hash *pHash){ unsigned int iHash; Fts5HashEntry *p = apOld[i]; apOld[i] = p->pHashNext; - iHash = fts5HashKey(nNew, (u8*)fts5EntryKey(p), - (int)strlen(fts5EntryKey(p))); + iHash = fts5HashKey(nNew, (u8*)fts5EntryKey(p), p->nKey); p->pHashNext = apNew[iHash]; apNew[iHash] = p; } @@ -234309,7 +240201,7 @@ static int sqlite3Fts5HashWrite( for(p=pHash->aSlot[iHash]; p; p=p->pHashNext){ char *zKey = fts5EntryKey(p); if( zKey[0]==bByte - && p->nKey==nToken + && p->nKey==nToken+1 && memcmp(&zKey[1], pToken, nToken)==0 ){ break; @@ -234339,9 +240231,9 @@ static int sqlite3Fts5HashWrite( zKey[0] = bByte; memcpy(&zKey[1], pToken, nToken); assert( iHash==fts5HashKey(pHash->nSlot, (u8*)zKey, nToken+1) ); - p->nKey = nToken; + p->nKey = nToken+1; zKey[nToken+1] = '\0'; - p->nData = nToken+1 + 1 + sizeof(Fts5HashEntry); + p->nData = nToken+1 + sizeof(Fts5HashEntry); p->pHashNext = pHash->aSlot[iHash]; pHash->aSlot[iHash] = p; pHash->nEntry++; @@ -234458,12 +240350,17 @@ static Fts5HashEntry *fts5HashEntryMerge( *ppOut = p1; p1 = 0; }else{ - int i = 0; char *zKey1 = fts5EntryKey(p1); char *zKey2 = fts5EntryKey(p2); - while( zKey1[i]==zKey2[i] ) i++; + int nMin = MIN(p1->nKey, p2->nKey); + + int cmp = memcmp(zKey1, zKey2, nMin); + if( cmp==0 ){ + cmp = p1->nKey - p2->nKey; + } + assert( cmp!=0 ); - if( ((u8)zKey1[i])>((u8)zKey2[i]) ){ + if( cmp>0 ){ /* p2 is smaller */ *ppOut = p2; ppOut = &p2->pScanNext; @@ -234482,10 +240379,8 @@ static Fts5HashEntry *fts5HashEntryMerge( } /* -** Extract all tokens from hash table iHash and link them into a list -** in sorted order. The hash table is cleared before returning. It is -** the responsibility of the caller to free the elements of the returned -** list. +** Link all tokens from hash table iHash into a list in sorted order. The +** tokens are not removed from the hash table. */ static int fts5HashEntrySort( Fts5Hash *pHash, @@ -234507,7 +240402,7 @@ static int fts5HashEntrySort( Fts5HashEntry *pIter; for(pIter=pHash->aSlot[iSlot]; pIter; pIter=pIter->pHashNext){ if( pTerm==0 - || (pIter->nKey+1>=nTerm && 0==memcmp(fts5EntryKey(pIter), pTerm, nTerm)) + || (pIter->nKey>=nTerm && 0==memcmp(fts5EntryKey(pIter), pTerm, nTerm)) ){ Fts5HashEntry *pEntry = pIter; pEntry->pScanNext = 0; @@ -234546,12 +240441,11 @@ static int sqlite3Fts5HashQuery( for(p=pHash->aSlot[iHash]; p; p=p->pHashNext){ zKey = fts5EntryKey(p); - assert( p->nKey+1==(int)strlen(zKey) ); - if( nTerm==p->nKey+1 && memcmp(zKey, pTerm, nTerm)==0 ) break; + if( nTerm==p->nKey && memcmp(zKey, pTerm, nTerm)==0 ) break; } if( p ){ - int nHashPre = sizeof(Fts5HashEntry) + nTerm + 1; + int nHashPre = sizeof(Fts5HashEntry) + nTerm; int nList = p->nData - nHashPre; u8 *pRet = (u8*)(*ppOut = sqlite3_malloc64(nPre + nList + 10)); if( pRet ){ @@ -234612,19 +240506,22 @@ static int sqlite3Fts5HashScanEof(Fts5Hash *p){ static void sqlite3Fts5HashScanEntry( Fts5Hash *pHash, const char **pzTerm, /* OUT: term (nul-terminated) */ + int *pnTerm, /* OUT: Size of term in bytes */ const u8 **ppDoclist, /* OUT: pointer to doclist */ int *pnDoclist /* OUT: size of doclist in bytes */ ){ Fts5HashEntry *p; if( (p = pHash->pScan) ){ char *zKey = fts5EntryKey(p); - int nTerm = (int)strlen(zKey); + int nTerm = p->nKey; fts5HashAddPoslistSize(pHash, p, 0); *pzTerm = zKey; - *ppDoclist = (const u8*)&zKey[nTerm+1]; - *pnDoclist = p->nData - (sizeof(Fts5HashEntry) + nTerm + 1); + *pnTerm = nTerm; + *ppDoclist = (const u8*)&zKey[nTerm]; + *pnDoclist = p->nData - (sizeof(Fts5HashEntry) + nTerm); }else{ *pzTerm = 0; + *pnTerm = 0; *ppDoclist = 0; *pnDoclist = 0; } @@ -234955,6 +240852,9 @@ typedef struct Fts5SegWriter Fts5SegWriter; typedef struct Fts5Structure Fts5Structure; typedef struct Fts5StructureLevel Fts5StructureLevel; typedef struct Fts5StructureSegment Fts5StructureSegment; +typedef struct Fts5TokenDataIter Fts5TokenDataIter; +typedef struct Fts5TokenDataMap Fts5TokenDataMap; +typedef struct Fts5TombstoneArray Fts5TombstoneArray; struct Fts5Data { u8 *p; /* Pointer to buffer containing record */ @@ -234989,6 +240889,7 @@ struct Fts5Index { /* Error state. */ int rc; /* Current error code */ + int flushRc; /* State used by the fts5DataXXX() functions. */ sqlite3_blob *pReader; /* RO incr-blob open on %_data table */ @@ -234997,6 +240898,7 @@ struct Fts5Index { sqlite3_stmt *pIdxWriter; /* "INSERT ... %_idx VALUES(?,?,?,?)" */ sqlite3_stmt *pIdxDeleter; /* "DELETE FROM %_idx WHERE segid=?" */ sqlite3_stmt *pIdxSelect; + sqlite3_stmt *pIdxNextSelect; int nRead; /* Total number of blocks read */ sqlite3_stmt *pDeleteFromIdx; @@ -235150,8 +241052,7 @@ struct Fts5SegIter { Fts5Data *pLeaf; /* Current leaf data */ Fts5Data *pNextLeaf; /* Leaf page (iLeafPgno+1) */ i64 iLeafOffset; /* Byte offset within current leaf */ - Fts5Data **apTombstone; /* Array of tombstone pages */ - int nTombstone; + Fts5TombstoneArray *pTombArray; /* Array of tombstone pages */ /* Next method */ void (*xNext)(Fts5Index*, Fts5SegIter*, int*); @@ -235178,6 +241079,15 @@ struct Fts5SegIter { u8 bDel; /* True if the delete flag is set */ }; +/* +** Array of tombstone pages. Reference counted. +*/ +struct Fts5TombstoneArray { + int nRef; /* Number of pointers to this object */ + int nTombstone; + Fts5Data *apTombstone[1]; /* Array of tombstone pages */ +}; + /* ** Argument is a pointer to an Fts5Data structure that contains a ** leaf page. @@ -235222,9 +241132,16 @@ struct Fts5SegIter { ** poslist: ** Used by sqlite3Fts5IterPoslist() when the poslist needs to be buffered. ** There is no way to tell if this is populated or not. +** +** pColset: +** If not NULL, points to an object containing a set of column indices. +** Only matches that occur in one of these columns will be returned. +** The Fts5Iter does not own the Fts5Colset object, and so it is not +** freed when the iterator is closed - it is owned by the upper layer. */ struct Fts5Iter { Fts5IndexIter base; /* Base class containing output vars */ + Fts5TokenDataIter *pTokenDataIter; Fts5Index *pIndex; /* Index that owns this iterator */ Fts5Buffer poslist; /* Buffer containing current poslist */ @@ -235242,7 +241159,6 @@ struct Fts5Iter { Fts5SegIter aSeg[1]; /* Array of segment iterators */ }; - /* ** An instance of the following type is used to iterate through the contents ** of a doclist-index record. @@ -236160,9 +242076,9 @@ static int fts5DlidxLvlNext(Fts5DlidxLvl *pLvl){ } if( iOffnn ){ - i64 iVal; + u64 iVal; pLvl->iLeafPgno += (iOff - pLvl->iOff) + 1; - iOff += fts5GetVarint(&pData->p[iOff], (u64*)&iVal); + iOff += fts5GetVarint(&pData->p[iOff], &iVal); pLvl->iRowid += iVal; pLvl->iOff = iOff; }else{ @@ -236541,18 +242457,20 @@ static void fts5SegIterSetNext(Fts5Index *p, Fts5SegIter *pIter){ } /* -** Allocate a tombstone hash page array (pIter->apTombstone) for the -** iterator passed as the second argument. If an OOM error occurs, leave -** an error in the Fts5Index object. +** Allocate a tombstone hash page array object (pIter->pTombArray) for +** the iterator passed as the second argument. If an OOM error occurs, +** leave an error in the Fts5Index object. */ static void fts5SegIterAllocTombstone(Fts5Index *p, Fts5SegIter *pIter){ const int nTomb = pIter->pSeg->nPgTombstone; if( nTomb>0 ){ - Fts5Data **apTomb = 0; - apTomb = (Fts5Data**)sqlite3Fts5MallocZero(&p->rc, sizeof(Fts5Data)*nTomb); - if( apTomb ){ - pIter->apTombstone = apTomb; - pIter->nTombstone = nTomb; + int nByte = nTomb * sizeof(Fts5Data*) + sizeof(Fts5TombstoneArray); + Fts5TombstoneArray *pNew; + pNew = (Fts5TombstoneArray*)sqlite3Fts5MallocZero(&p->rc, nByte); + if( pNew ){ + pNew->nTombstone = nTomb; + pNew->nRef = 1; + pIter->pTombArray = pNew; } } } @@ -236809,15 +242727,16 @@ static void fts5SegIterNext_None( }else{ const u8 *pList = 0; const char *zTerm = 0; + int nTerm = 0; int nList; sqlite3Fts5HashScanNext(p->pHash); - sqlite3Fts5HashScanEntry(p->pHash, &zTerm, &pList, &nList); + sqlite3Fts5HashScanEntry(p->pHash, &zTerm, &nTerm, &pList, &nList); if( pList==0 ) goto next_none_eof; pIter->pLeaf->p = (u8*)pList; pIter->pLeaf->nn = nList; pIter->pLeaf->szLeaf = nList; pIter->iEndofDoclist = nList; - sqlite3Fts5BufferSet(&p->rc,&pIter->term, (int)strlen(zTerm), (u8*)zTerm); + sqlite3Fts5BufferSet(&p->rc,&pIter->term, nTerm, (u8*)zTerm); pIter->iLeafOffset = fts5GetVarint(pList, (u64*)&pIter->iRowid); } @@ -236883,11 +242802,12 @@ static void fts5SegIterNext( }else if( pIter->pSeg==0 ){ const u8 *pList = 0; const char *zTerm = 0; + int nTerm = 0; int nList = 0; assert( (pIter->flags & FTS5_SEGITER_ONETERM) || pbNewTerm ); if( 0==(pIter->flags & FTS5_SEGITER_ONETERM) ){ sqlite3Fts5HashScanNext(p->pHash); - sqlite3Fts5HashScanEntry(p->pHash, &zTerm, &pList, &nList); + sqlite3Fts5HashScanEntry(p->pHash, &zTerm, &nTerm, &pList, &nList); } if( pList==0 ){ fts5DataRelease(pIter->pLeaf); @@ -236897,8 +242817,7 @@ static void fts5SegIterNext( pIter->pLeaf->nn = nList; pIter->pLeaf->szLeaf = nList; pIter->iEndofDoclist = nList+1; - sqlite3Fts5BufferSet(&p->rc, &pIter->term, (int)strlen(zTerm), - (u8*)zTerm); + sqlite3Fts5BufferSet(&p->rc, &pIter->term, nTerm, (u8*)zTerm); pIter->iLeafOffset = fts5GetVarint(pList, (u64*)&pIter->iRowid); *pbNewTerm = 1; } @@ -237284,7 +243203,7 @@ static void fts5SegIterSeekInit( fts5LeafSeek(p, bGe, pIter, pTerm, nTerm); } - if( p->rc==SQLITE_OK && bGe==0 ){ + if( p->rc==SQLITE_OK && (bGe==0 || (flags & FTS5INDEX_QUERY_SCANONETERM)) ){ pIter->flags |= FTS5_SEGITER_ONETERM; if( pIter->pLeaf ){ if( flags & FTS5INDEX_QUERY_DESC ){ @@ -237300,7 +243219,9 @@ static void fts5SegIterSeekInit( } fts5SegIterSetNext(p, pIter); - fts5SegIterAllocTombstone(p, pIter); + if( 0==(flags & FTS5INDEX_QUERY_SCANONETERM) ){ + fts5SegIterAllocTombstone(p, pIter); + } /* Either: ** @@ -237317,6 +243238,79 @@ static void fts5SegIterSeekInit( ); } + +/* +** SQL used by fts5SegIterNextInit() to find the page to open. +*/ +static sqlite3_stmt *fts5IdxNextStmt(Fts5Index *p){ + if( p->pIdxNextSelect==0 ){ + Fts5Config *pConfig = p->pConfig; + fts5IndexPrepareStmt(p, &p->pIdxNextSelect, sqlite3_mprintf( + "SELECT pgno FROM '%q'.'%q_idx' WHERE " + "segid=? AND term>? ORDER BY term ASC LIMIT 1", + pConfig->zDb, pConfig->zName + )); + + } + return p->pIdxNextSelect; +} + +/* +** This is similar to fts5SegIterSeekInit(), except that it initializes +** the segment iterator to point to the first term following the page +** with pToken/nToken on it. +*/ +static void fts5SegIterNextInit( + Fts5Index *p, + const char *pTerm, int nTerm, + Fts5StructureSegment *pSeg, /* Description of segment */ + Fts5SegIter *pIter /* Object to populate */ +){ + int iPg = -1; /* Page of segment to open */ + int bDlidx = 0; + sqlite3_stmt *pSel = 0; /* SELECT to find iPg */ + + pSel = fts5IdxNextStmt(p); + if( pSel ){ + assert( p->rc==SQLITE_OK ); + sqlite3_bind_int(pSel, 1, pSeg->iSegid); + sqlite3_bind_blob(pSel, 2, pTerm, nTerm, SQLITE_STATIC); + + if( sqlite3_step(pSel)==SQLITE_ROW ){ + i64 val = sqlite3_column_int64(pSel, 0); + iPg = (int)(val>>1); + bDlidx = (val & 0x0001); + } + p->rc = sqlite3_reset(pSel); + sqlite3_bind_null(pSel, 2); + if( p->rc ) return; + } + + memset(pIter, 0, sizeof(*pIter)); + pIter->pSeg = pSeg; + pIter->flags |= FTS5_SEGITER_ONETERM; + if( iPg>=0 ){ + pIter->iLeafPgno = iPg - 1; + fts5SegIterNextPage(p, pIter); + fts5SegIterSetNext(p, pIter); + } + if( pIter->pLeaf ){ + const u8 *a = pIter->pLeaf->p; + int iTermOff = 0; + + pIter->iPgidxOff = pIter->pLeaf->szLeaf; + pIter->iPgidxOff += fts5GetVarint32(&a[pIter->iPgidxOff], iTermOff); + pIter->iLeafOffset = iTermOff; + fts5SegIterLoadTerm(p, pIter, 0); + fts5SegIterLoadNPos(p, pIter); + if( bDlidx ) fts5SegIterLoadDlidx(p, pIter); + + assert( p->rc!=SQLITE_OK || + fts5BufferCompareBlob(&pIter->term, (const u8*)pTerm, nTerm)>0 + ); + } +} + /* ** Initialize the object pIter to point to term pTerm/nTerm within the ** in-memory hash table. If there is no such term in the hash-table, the @@ -237343,14 +243337,21 @@ static void fts5SegIterHashInit( const u8 *pList = 0; p->rc = sqlite3Fts5HashScanInit(p->pHash, (const char*)pTerm, nTerm); - sqlite3Fts5HashScanEntry(p->pHash, (const char**)&z, &pList, &nList); - n = (z ? (int)strlen((const char*)z) : 0); + sqlite3Fts5HashScanEntry(p->pHash, (const char**)&z, &n, &pList, &nList); if( pList ){ pLeaf = fts5IdxMalloc(p, sizeof(Fts5Data)); if( pLeaf ){ pLeaf->p = (u8*)pList; } } + + /* The call to sqlite3Fts5HashScanInit() causes the hash table to + ** fill the size field of all existing position lists. This means they + ** can no longer be appended to. Since the only scenario in which they + ** can be appended to is if the previous operation on this table was + ** a DELETE, by clearing the Fts5Index.bDelete flag we can avoid this + ** possibility altogether. */ + p->bDelete = 0; }else{ p->rc = sqlite3Fts5HashQuery(p->pHash, sizeof(Fts5Data), (const char*)pTerm, nTerm, (void**)&pLeaf, &nList @@ -237395,6 +243396,23 @@ static void fts5IndexFreeArray(Fts5Data **ap, int n){ } } +/* +** Decrement the ref-count of the object passed as the only argument. If it +** reaches 0, free it and its contents. +*/ +static void fts5TombstoneArrayDelete(Fts5TombstoneArray *p){ + if( p ){ + p->nRef--; + if( p->nRef<=0 ){ + int ii; + for(ii=0; iinTombstone; ii++){ + fts5DataRelease(p->apTombstone[ii]); + } + sqlite3_free(p); + } + } +} + /* ** Zero the iterator passed as the only argument. */ @@ -237402,7 +243420,7 @@ static void fts5SegIterClear(Fts5SegIter *pIter){ fts5BufferFree(&pIter->term); fts5DataRelease(pIter->pLeaf); fts5DataRelease(pIter->pNextLeaf); - fts5IndexFreeArray(pIter->apTombstone, pIter->nTombstone); + fts5TombstoneArrayDelete(pIter->pTombArray); fts5DlidxIterFree(pIter->pDlidx); sqlite3_free(pIter->aRowidOffset); memset(pIter, 0, sizeof(Fts5SegIter)); @@ -237536,7 +243554,6 @@ static int fts5MultiIterDoCompare(Fts5Iter *pIter, int iOut){ assert_nc( i2!=0 ); pRes->bTermEq = 1; if( p1->iRowid==p2->iRowid ){ - p1->bDel = p2->bDel; return i2; } res = ((p1->iRowid > p2->iRowid)==pIter->bRev) ? -1 : +1; @@ -237648,7 +243665,6 @@ static void fts5SegIterNextFrom( }while( p->rc==SQLITE_OK ); } - /* ** Free the iterator object passed as the second argument. */ @@ -237793,24 +243809,25 @@ static int fts5IndexTombstoneQuery( static int fts5MultiIterIsDeleted(Fts5Iter *pIter){ int iFirst = pIter->aFirst[1].iFirst; Fts5SegIter *pSeg = &pIter->aSeg[iFirst]; + Fts5TombstoneArray *pArray = pSeg->pTombArray; - if( pSeg->pLeaf && pSeg->nTombstone ){ + if( pSeg->pLeaf && pArray ){ /* Figure out which page the rowid might be present on. */ - int iPg = ((u64)pSeg->iRowid) % pSeg->nTombstone; + int iPg = ((u64)pSeg->iRowid) % pArray->nTombstone; assert( iPg>=0 ); /* If tombstone hash page iPg has not yet been loaded from the ** database, load it now. */ - if( pSeg->apTombstone[iPg]==0 ){ - pSeg->apTombstone[iPg] = fts5DataRead(pIter->pIndex, + if( pArray->apTombstone[iPg]==0 ){ + pArray->apTombstone[iPg] = fts5DataRead(pIter->pIndex, FTS5_TOMBSTONE_ROWID(pSeg->pSeg->iSegid, iPg) ); - if( pSeg->apTombstone[iPg]==0 ) return 0; + if( pArray->apTombstone[iPg]==0 ) return 0; } return fts5IndexTombstoneQuery( - pSeg->apTombstone[iPg], - pSeg->nTombstone, + pArray->apTombstone[iPg], + pArray->nTombstone, pSeg->iRowid ); } @@ -237904,7 +243921,7 @@ static Fts5Iter *fts5MultiIterAlloc( int nSeg ){ Fts5Iter *pNew; - int nSlot; /* Power of two >= nSeg */ + i64 nSlot; /* Power of two >= nSeg */ for(nSlot=2; nSlotnSeg-1; iIter>0; iIter--){ + int iEq; + if( (iEq = fts5MultiIterDoCompare(pIter, iIter)) ){ + Fts5SegIter *pSeg = &pIter->aSeg[iEq]; + if( p->rc==SQLITE_OK ) pSeg->xNext(p, pSeg, 0); + fts5MultiIterAdvanced(p, pIter, iEq, iIter); + } + } + fts5MultiIterSetEof(pIter); + fts5AssertMultiIterSetup(p, pIter); + + if( (pIter->bSkipEmpty && fts5MultiIterIsEmpty(p, pIter)) + || fts5MultiIterIsDeleted(pIter) + ){ + fts5MultiIterNext(p, pIter, 0, 0); + }else if( pIter->base.bEof==0 ){ + Fts5SegIter *pSeg = &pIter->aSeg[pIter->aFirst[1].iFirst]; + pIter->xSetOutputs(pIter, pSeg); + } +} /* ** Allocate a new Fts5Iter object. @@ -238430,31 +244473,12 @@ static void fts5MultiIterNew( assert( iIter==nSeg ); } - /* If the above was successful, each component iterators now points + /* If the above was successful, each component iterator now points ** to the first entry in its segment. In this case initialize the ** aFirst[] array. Or, if an error has occurred, free the iterator ** object and set the output variable to NULL. */ if( p->rc==SQLITE_OK ){ - for(iIter=pNew->nSeg-1; iIter>0; iIter--){ - int iEq; - if( (iEq = fts5MultiIterDoCompare(pNew, iIter)) ){ - Fts5SegIter *pSeg = &pNew->aSeg[iEq]; - if( p->rc==SQLITE_OK ) pSeg->xNext(p, pSeg, 0); - fts5MultiIterAdvanced(p, pNew, iEq, iIter); - } - } - fts5MultiIterSetEof(pNew); - fts5AssertMultiIterSetup(p, pNew); - - if( (pNew->bSkipEmpty && fts5MultiIterIsEmpty(p, pNew)) - || fts5MultiIterIsDeleted(pNew) - ){ - fts5MultiIterNext(p, pNew, 0, 0); - }else if( pNew->base.bEof==0 ){ - Fts5SegIter *pSeg = &pNew->aSeg[pNew->aFirst[1].iFirst]; - pNew->xSetOutputs(pNew, pSeg); - } - + fts5MultiIterFinishSetup(p, pNew); }else{ fts5MultiIterFree(pNew); *ppOut = 0; @@ -238479,7 +244503,6 @@ static void fts5MultiIterNew2( pNew = fts5MultiIterAlloc(p, 2); if( pNew ){ Fts5SegIter *pIter = &pNew->aSeg[1]; - pIter->flags = FTS5_SEGITER_ONETERM; if( pData->szLeaf>0 ){ pIter->pLeaf = pData; @@ -238627,6 +244650,7 @@ static void fts5IndexDiscardData(Fts5Index *p){ sqlite3Fts5HashClear(p->pHash); p->nPendingData = 0; p->nPendingRow = 0; + p->flushRc = SQLITE_OK; } p->nContentlessDelete = 0; } @@ -238842,7 +244866,7 @@ static void fts5WriteDlidxAppend( } if( pDlidx->bPrevValid ){ - iVal = iRowid - pDlidx->iPrev; + iVal = (u64)iRowid - (u64)pDlidx->iPrev; }else{ i64 iPgno = (i==0 ? pWriter->writer.pgno : pDlidx[-1].pgno); assert( pDlidx->buf.n==0 ); @@ -239029,7 +245053,7 @@ static void fts5WriteAppendPoslistData( const u8 *a = aData; int n = nData; - assert( p->pConfig->pgsz>0 ); + assert( p->pConfig->pgsz>0 || p->rc!=SQLITE_OK ); while( p->rc==SQLITE_OK && (pPage->buf.n + pPage->pgidx.n + n)>=p->pConfig->pgsz ){ @@ -239680,7 +245704,6 @@ static void fts5DoSecureDelete( int iPgIdx = pSeg->pLeaf->szLeaf; u64 iDelta = 0; - u64 iNextDelta = 0; int iNextOff = 0; int iOff = 0; int nIdx = 0; @@ -239688,8 +245711,6 @@ static void fts5DoSecureDelete( int bLastInDoclist = 0; int iIdx = 0; int iStart = 0; - int iKeyOff = 0; - int iPrevKeyOff = 0; int iDelKeyOff = 0; /* Offset of deleted key, if any */ nIdx = nPg-iPgIdx; @@ -239714,10 +245735,21 @@ static void fts5DoSecureDelete( ** This block sets the following variables: ** ** iStart: + ** The offset of the first byte of the rowid or delta-rowid + ** value for the doclist entry being removed. + ** ** iDelta: + ** The value of the rowid or delta-rowid value for the doclist + ** entry being removed. + ** + ** iNextOff: + ** The offset of the next entry following the position list + ** for the one being removed. If the position list for this + ** entry overflows onto the next leaf page, this value will be + ** greater than pLeaf->szLeaf. */ { - int iSOP; + int iSOP; /* Start-Of-Position-list */ if( pSeg->iLeafPgno==pSeg->iTermLeafPgno ){ iStart = pSeg->iTermLeafOffset; }else{ @@ -239753,47 +245785,81 @@ static void fts5DoSecureDelete( } iOff = iStart; + + /* If the position-list for the entry being removed flows over past + ** the end of this page, delete the portion of the position-list on the + ** next page and beyond. + ** + ** Set variable bLastInDoclist to true if this entry happens + ** to be the last rowid in the doclist for its term. */ if( iNextOff>=iPgIdx ){ int pgno = pSeg->iLeafPgno+1; fts5SecureDeleteOverflow(p, pSeg->pSeg, pgno, &bLastInDoclist); iNextOff = iPgIdx; - }else{ - /* Set bLastInDoclist to true if the entry being removed is the last - ** in its doclist. */ - for(iIdx=0, iKeyOff=0; iIdxbDel==0 ){ + if( iNextOff!=iPgIdx ){ + /* Loop through the page-footer. If iNextOff (offset of the + ** entry following the one we are removing) is equal to the + ** offset of a key on this page, then the entry is the last + ** in its doclist. */ + int iKeyOff = 0; + for(iIdx=0; iIdxbDel ){ + iOff += sqlite3Fts5PutVarint(&aPg[iOff], iDelta); + aPg[iOff++] = 0x01; + }else if( bLastInDoclist==0 ){ if( iNextOff!=iPgIdx ){ + u64 iNextDelta = 0; iNextOff += fts5GetVarint(&aPg[iNextOff], &iNextDelta); iOff += sqlite3Fts5PutVarint(&aPg[iOff], iDelta + iNextDelta); } }else if( - iStart==pSeg->iTermLeafOffset && pSeg->iLeafPgno==pSeg->iTermLeafPgno + pSeg->iLeafPgno==pSeg->iTermLeafPgno + && iStart==pSeg->iTermLeafOffset ){ /* The entry being removed was the only position list in its ** doclist. Therefore the term needs to be removed as well. */ int iKey = 0; - for(iIdx=0, iKeyOff=0; iIdx(u32)iStart ) break; iKeyOff += iVal; } + assert_nc( iKey>=1 ); + /* Set iDelKeyOff to the value of the footer entry to remove from + ** the page. */ iDelKeyOff = iOff = iKeyOff; + if( iNextOff!=iPgIdx ){ + /* This is the only position-list associated with the term, and there + ** is another term following it on this page. So the subsequent term + ** needs to be moved to replace the term associated with the entry + ** being removed. */ int nPrefix = 0; int nSuffix = 0; int nPrefix2 = 0; @@ -239872,6 +245938,15 @@ static void fts5DoSecureDelete( } } + /* Assuming no error has occurred, this block does final edits to the + ** leaf page before writing it back to disk. Input variables are: + ** + ** nPg: Total initial size of leaf page. + ** iPgIdx: Initial offset of page footer. + ** + ** iOff: Offset to move data to + ** iNextOff: Offset to move data from + */ if( p->rc==SQLITE_OK ){ const int nMove = nPg - iNextOff; /* Number of bytes to move */ int nShift = iNextOff - iOff; /* Distance to move them */ @@ -239914,10 +245989,10 @@ static void fts5FlushSecureDelete( Fts5Index *p, Fts5Structure *pStruct, const char *zTerm, + int nTerm, i64 iRowid ){ const int f = FTS5INDEX_QUERY_SKIPHASH; - int nTerm = (int)strlen(zTerm); Fts5Iter *pIter = 0; /* Used to find term instance */ fts5MultiIterNew(p, pStruct, f, 0, (const u8*)zTerm, nTerm, -1, 0, &pIter); @@ -239991,8 +246066,7 @@ static void fts5FlushOneHash(Fts5Index *p){ int nDoclist; /* Size of doclist in bytes */ /* Get the term and doclist for this entry. */ - sqlite3Fts5HashScanEntry(pHash, &zTerm, &pDoclist, &nDoclist); - nTerm = (int)strlen(zTerm); + sqlite3Fts5HashScanEntry(pHash, &zTerm, &nTerm, &pDoclist, &nDoclist); if( bSecureDelete==0 ){ fts5WriteAppendTerm(p, &writer, nTerm, (const u8*)zTerm); if( p->rc!=SQLITE_OK ) break; @@ -240022,7 +246096,7 @@ static void fts5FlushOneHash(Fts5Index *p){ if( bSecureDelete ){ if( eDetail==FTS5_DETAIL_NONE ){ if( iOffrc!=SQLITE_OK || pDoclist[iOff]==0x01 ){ iOff++; continue; @@ -240072,10 +246146,16 @@ static void fts5FlushOneHash(Fts5Index *p){ fts5WriteFlushLeaf(p, &writer); } }else{ - int bDummy; - int nPos; - int nCopy = fts5GetPoslistSize(&pDoclist[iOff], &nPos, &bDummy); - nCopy += nPos; + int bDel = 0; + int nPos = 0; + int nCopy = fts5GetPoslistSize(&pDoclist[iOff], &nPos, &bDel); + if( bDel && bSecureDelete ){ + fts5BufferAppendVarint(&p->rc, pBuf, nPos*2); + iOff += nCopy; + nCopy = nPos; + }else{ + nCopy += nPos; + } if( (pBuf->n + pPgidx->n + nCopy) <= pgsz ){ /* The entire poslist will fit on the current leaf. So copy ** it in one go. */ @@ -240113,7 +246193,6 @@ static void fts5FlushOneHash(Fts5Index *p){ assert( pBuf->n<=pBuf->nSpace ); if( p->rc==SQLITE_OK ) sqlite3Fts5HashScanNext(pHash); } - sqlite3Fts5HashClear(pHash); fts5WriteFinish(p, &writer, &pgnoLast); assert( p->rc!=SQLITE_OK || bSecureDelete || pgnoLast>0 ); @@ -240146,7 +246225,6 @@ static void fts5FlushOneHash(Fts5Index *p){ fts5IndexCrisismerge(p, &pStruct); fts5StructureWrite(p, pStruct); fts5StructureRelease(pStruct); - p->nContentlessDelete = 0; } /* @@ -240154,11 +246232,21 @@ static void fts5FlushOneHash(Fts5Index *p){ */ static void fts5IndexFlush(Fts5Index *p){ /* Unless it is empty, flush the hash table to disk */ + if( p->flushRc ){ + p->rc = p->flushRc; + return; + } if( p->nPendingData || p->nContentlessDelete ){ assert( p->pHash ); fts5FlushOneHash(p); - p->nPendingData = 0; - p->nPendingRow = 0; + if( p->rc==SQLITE_OK ){ + sqlite3Fts5HashClear(p->pHash); + p->nPendingData = 0; + p->nPendingRow = 0; + p->nContentlessDelete = 0; + }else if( p->nPendingData || p->nContentlessDelete ){ + p->flushRc = p->rc; + } } } @@ -240236,8 +246324,9 @@ static int sqlite3Fts5IndexOptimize(Fts5Index *p){ assert( p->rc==SQLITE_OK ); fts5IndexFlush(p); - assert( p->nContentlessDelete==0 ); + assert( p->rc!=SQLITE_OK || p->nContentlessDelete==0 ); pStruct = fts5StructureRead(p); + assert( p->rc!=SQLITE_OK || pStruct!=0 ); fts5StructureInvalidate(p); if( pStruct ){ @@ -240643,7 +246732,7 @@ static void fts5SetupPrefixIter( u8 *pToken, /* Buffer containing prefix to match */ int nToken, /* Size of buffer pToken in bytes */ Fts5Colset *pColset, /* Restrict matches to these columns */ - Fts5Iter **ppIter /* OUT: New iterator */ + Fts5Iter **ppIter /* OUT: New iterator */ ){ Fts5Structure *pStruct; Fts5Buffer *aBuf; @@ -240664,8 +246753,9 @@ static void fts5SetupPrefixIter( aBuf = (Fts5Buffer*)fts5IdxMalloc(p, sizeof(Fts5Buffer)*nBuf); pStruct = fts5StructureRead(p); + assert( p->rc!=SQLITE_OK || (aBuf && pStruct) ); - if( aBuf && pStruct ){ + if( p->rc==SQLITE_OK ){ const int flags = FTS5INDEX_QUERY_SCAN | FTS5INDEX_QUERY_SKIPEMPTY | FTS5INDEX_QUERY_NOOUTPUT; @@ -240677,6 +246767,12 @@ static void fts5SetupPrefixIter( int bNewTerm = 1; memset(&doclist, 0, sizeof(doclist)); + + /* If iIdx is non-zero, then it is the number of a prefix-index for + ** prefixes 1 character longer than the prefix being queried for. That + ** index contains all the doclists required, except for the one + ** corresponding to the prefix itself. That one is extracted from the + ** main term index here. */ if( iIdx!=0 ){ int dummy = 0; const int f2 = FTS5INDEX_QUERY_SKIPEMPTY|FTS5INDEX_QUERY_NOOUTPUT; @@ -240700,6 +246796,7 @@ static void fts5SetupPrefixIter( pToken[0] = FTS5_MAIN_PREFIX + iIdx; fts5MultiIterNew(p, pStruct, flags, pColset, pToken, nToken, -1, 0, &p1); fts5IterSetOutputCb(&p->rc, p1); + for( /* no-op */ ; fts5MultiIterEof(p, p1)==0; fts5MultiIterNext2(p, p1, &bNewTerm) @@ -240715,7 +246812,6 @@ static void fts5SetupPrefixIter( } if( p1->base.nData==0 ) continue; - if( p1->base.iRowid<=iLastRowid && doclist.n>0 ){ for(i=0; p->rc==SQLITE_OK && doclist.n; i++){ int i1 = i*nMerge; @@ -240754,7 +246850,7 @@ static void fts5SetupPrefixIter( } fts5MultiIterFree(p1); - pData = fts5IdxMalloc(p, sizeof(Fts5Data)+doclist.n+FTS5_DATA_ZERO_PADDING); + pData = fts5IdxMalloc(p, sizeof(*pData)+doclist.n+FTS5_DATA_ZERO_PADDING); if( pData ){ pData->p = (u8*)&pData[1]; pData->nn = pData->szLeaf = doclist.n; @@ -240897,6 +246993,7 @@ static int sqlite3Fts5IndexClose(Fts5Index *p){ sqlite3_finalize(p->pIdxWriter); sqlite3_finalize(p->pIdxDeleter); sqlite3_finalize(p->pIdxSelect); + sqlite3_finalize(p->pIdxNextSelect); sqlite3_finalize(p->pDataVersion); sqlite3_finalize(p->pDeleteFromIdx); sqlite3Fts5HashFree(p->pHash); @@ -240992,6 +247089,457 @@ static int sqlite3Fts5IndexWrite( return rc; } +/* +** pToken points to a buffer of size nToken bytes containing a search +** term, including the index number at the start, used on a tokendata=1 +** table. This function returns true if the term in buffer pBuf matches +** token pToken/nToken. +*/ +static int fts5IsTokendataPrefix( + Fts5Buffer *pBuf, + const u8 *pToken, + int nToken +){ + return ( + pBuf->n>=nToken + && 0==memcmp(pBuf->p, pToken, nToken) + && (pBuf->n==nToken || pBuf->p[nToken]==0x00) + ); +} + +/* +** Ensure the segment-iterator passed as the only argument points to EOF. +*/ +static void fts5SegIterSetEOF(Fts5SegIter *pSeg){ + fts5DataRelease(pSeg->pLeaf); + pSeg->pLeaf = 0; +} + +/* +** Usually, a tokendata=1 iterator (struct Fts5TokenDataIter) accumulates an +** array of these for each row it visits. Or, for an iterator used by an +** "ORDER BY rank" query, it accumulates an array of these for the entire +** query. +** +** Each instance in the array indicates the iterator (and therefore term) +** associated with position iPos of rowid iRowid. This is used by the +** xInstToken() API. +*/ +struct Fts5TokenDataMap { + i64 iRowid; /* Row this token is located in */ + i64 iPos; /* Position of token */ + int iIter; /* Iterator token was read from */ +}; + +/* +** An object used to supplement Fts5Iter for tokendata=1 iterators. +*/ +struct Fts5TokenDataIter { + int nIter; + int nIterAlloc; + + int nMap; + int nMapAlloc; + Fts5TokenDataMap *aMap; + + Fts5PoslistReader *aPoslistReader; + int *aPoslistToIter; + Fts5Iter *apIter[1]; +}; + +/* +** This function appends iterator pAppend to Fts5TokenDataIter pIn and +** returns the result. +*/ +static Fts5TokenDataIter *fts5AppendTokendataIter( + Fts5Index *p, /* Index object (for error code) */ + Fts5TokenDataIter *pIn, /* Current Fts5TokenDataIter struct */ + Fts5Iter *pAppend /* Append this iterator */ +){ + Fts5TokenDataIter *pRet = pIn; + + if( p->rc==SQLITE_OK ){ + if( pIn==0 || pIn->nIter==pIn->nIterAlloc ){ + int nAlloc = pIn ? pIn->nIterAlloc*2 : 16; + int nByte = nAlloc * sizeof(Fts5Iter*) + sizeof(Fts5TokenDataIter); + Fts5TokenDataIter *pNew = (Fts5TokenDataIter*)sqlite3_realloc(pIn, nByte); + + if( pNew==0 ){ + p->rc = SQLITE_NOMEM; + }else{ + if( pIn==0 ) memset(pNew, 0, nByte); + pRet = pNew; + pNew->nIterAlloc = nAlloc; + } + } + } + if( p->rc ){ + sqlite3Fts5IterClose((Fts5IndexIter*)pAppend); + }else{ + pRet->apIter[pRet->nIter++] = pAppend; + } + assert( pRet==0 || pRet->nIter<=pRet->nIterAlloc ); + + return pRet; +} + +/* +** Delete an Fts5TokenDataIter structure and its contents. +*/ +static void fts5TokendataIterDelete(Fts5TokenDataIter *pSet){ + if( pSet ){ + int ii; + for(ii=0; iinIter; ii++){ + fts5MultiIterFree(pSet->apIter[ii]); + } + sqlite3_free(pSet->aPoslistReader); + sqlite3_free(pSet->aMap); + sqlite3_free(pSet); + } +} + +/* +** Append a mapping to the token-map belonging to object pT. +*/ +static void fts5TokendataIterAppendMap( + Fts5Index *p, + Fts5TokenDataIter *pT, + int iIter, + i64 iRowid, + i64 iPos +){ + if( p->rc==SQLITE_OK ){ + if( pT->nMap==pT->nMapAlloc ){ + int nNew = pT->nMapAlloc ? pT->nMapAlloc*2 : 64; + int nByte = nNew * sizeof(Fts5TokenDataMap); + Fts5TokenDataMap *aNew; + + aNew = (Fts5TokenDataMap*)sqlite3_realloc(pT->aMap, nByte); + if( aNew==0 ){ + p->rc = SQLITE_NOMEM; + return; + } + + pT->aMap = aNew; + pT->nMapAlloc = nNew; + } + + pT->aMap[pT->nMap].iRowid = iRowid; + pT->aMap[pT->nMap].iPos = iPos; + pT->aMap[pT->nMap].iIter = iIter; + pT->nMap++; + } +} + +/* +** The iterator passed as the only argument must be a tokendata=1 iterator +** (pIter->pTokenDataIter!=0). This function sets the iterator output +** variables (pIter->base.*) according to the contents of the current +** row. +*/ +static void fts5IterSetOutputsTokendata(Fts5Iter *pIter){ + int ii; + int nHit = 0; + i64 iRowid = SMALLEST_INT64; + int iMin = 0; + + Fts5TokenDataIter *pT = pIter->pTokenDataIter; + + pIter->base.nData = 0; + pIter->base.pData = 0; + + for(ii=0; iinIter; ii++){ + Fts5Iter *p = pT->apIter[ii]; + if( p->base.bEof==0 ){ + if( nHit==0 || p->base.iRowidbase.iRowid; + nHit = 1; + pIter->base.pData = p->base.pData; + pIter->base.nData = p->base.nData; + iMin = ii; + }else if( p->base.iRowid==iRowid ){ + nHit++; + } + } + } + + if( nHit==0 ){ + pIter->base.bEof = 1; + }else{ + int eDetail = pIter->pIndex->pConfig->eDetail; + pIter->base.bEof = 0; + pIter->base.iRowid = iRowid; + + if( nHit==1 && eDetail==FTS5_DETAIL_FULL ){ + fts5TokendataIterAppendMap(pIter->pIndex, pT, iMin, iRowid, -1); + }else + if( nHit>1 && eDetail!=FTS5_DETAIL_NONE ){ + int nReader = 0; + int nByte = 0; + i64 iPrev = 0; + + /* Allocate array of iterators if they are not already allocated. */ + if( pT->aPoslistReader==0 ){ + pT->aPoslistReader = (Fts5PoslistReader*)sqlite3Fts5MallocZero( + &pIter->pIndex->rc, + pT->nIter * (sizeof(Fts5PoslistReader) + sizeof(int)) + ); + if( pT->aPoslistReader==0 ) return; + pT->aPoslistToIter = (int*)&pT->aPoslistReader[pT->nIter]; + } + + /* Populate an iterator for each poslist that will be merged */ + for(ii=0; iinIter; ii++){ + Fts5Iter *p = pT->apIter[ii]; + if( iRowid==p->base.iRowid ){ + pT->aPoslistToIter[nReader] = ii; + sqlite3Fts5PoslistReaderInit( + p->base.pData, p->base.nData, &pT->aPoslistReader[nReader++] + ); + nByte += p->base.nData; + } + } + + /* Ensure the output buffer is large enough */ + if( fts5BufferGrow(&pIter->pIndex->rc, &pIter->poslist, nByte+nHit*10) ){ + return; + } + + /* Ensure the token-mapping is large enough */ + if( eDetail==FTS5_DETAIL_FULL && pT->nMapAlloc<(pT->nMap + nByte) ){ + int nNew = (pT->nMapAlloc + nByte) * 2; + Fts5TokenDataMap *aNew = (Fts5TokenDataMap*)sqlite3_realloc( + pT->aMap, nNew*sizeof(Fts5TokenDataMap) + ); + if( aNew==0 ){ + pIter->pIndex->rc = SQLITE_NOMEM; + return; + } + pT->aMap = aNew; + pT->nMapAlloc = nNew; + } + + pIter->poslist.n = 0; + + while( 1 ){ + i64 iMinPos = LARGEST_INT64; + + /* Find smallest position */ + iMin = 0; + for(ii=0; iiaPoslistReader[ii]; + if( pReader->bEof==0 ){ + if( pReader->iPosiPos; + iMin = ii; + } + } + } + + /* If all readers were at EOF, break out of the loop. */ + if( iMinPos==LARGEST_INT64 ) break; + + sqlite3Fts5PoslistSafeAppend(&pIter->poslist, &iPrev, iMinPos); + sqlite3Fts5PoslistReaderNext(&pT->aPoslistReader[iMin]); + + if( eDetail==FTS5_DETAIL_FULL ){ + pT->aMap[pT->nMap].iPos = iMinPos; + pT->aMap[pT->nMap].iIter = pT->aPoslistToIter[iMin]; + pT->aMap[pT->nMap].iRowid = iRowid; + pT->nMap++; + } + } + + pIter->base.pData = pIter->poslist.p; + pIter->base.nData = pIter->poslist.n; + } + } +} + +/* +** The iterator passed as the only argument must be a tokendata=1 iterator +** (pIter->pTokenDataIter!=0). This function advances the iterator. If +** argument bFrom is false, then the iterator is advanced to the next +** entry. Or, if bFrom is true, it is advanced to the first entry with +** a rowid of iFrom or greater. +*/ +static void fts5TokendataIterNext(Fts5Iter *pIter, int bFrom, i64 iFrom){ + int ii; + Fts5TokenDataIter *pT = pIter->pTokenDataIter; + Fts5Index *pIndex = pIter->pIndex; + + for(ii=0; iinIter; ii++){ + Fts5Iter *p = pT->apIter[ii]; + if( p->base.bEof==0 + && (p->base.iRowid==pIter->base.iRowid || (bFrom && p->base.iRowidbase.bEof==0 + && p->base.iRowidrc==SQLITE_OK + ){ + fts5MultiIterNext(pIndex, p, 0, 0); + } + } + } + + if( pIndex->rc==SQLITE_OK ){ + fts5IterSetOutputsTokendata(pIter); + } +} + +/* +** If the segment-iterator passed as the first argument is at EOF, then +** set pIter->term to a copy of buffer pTerm. +*/ +static void fts5TokendataSetTermIfEof(Fts5Iter *pIter, Fts5Buffer *pTerm){ + if( pIter && pIter->aSeg[0].pLeaf==0 ){ + fts5BufferSet(&pIter->pIndex->rc, &pIter->aSeg[0].term, pTerm->n, pTerm->p); + } +} + +/* +** This function sets up an iterator to use for a non-prefix query on a +** tokendata=1 table. +*/ +static Fts5Iter *fts5SetupTokendataIter( + Fts5Index *p, /* FTS index to query */ + const u8 *pToken, /* Buffer containing query term */ + int nToken, /* Size of buffer pToken in bytes */ + Fts5Colset *pColset /* Colset to filter on */ +){ + Fts5Iter *pRet = 0; + Fts5TokenDataIter *pSet = 0; + Fts5Structure *pStruct = 0; + const int flags = FTS5INDEX_QUERY_SCANONETERM | FTS5INDEX_QUERY_SCAN; + + Fts5Buffer bSeek = {0, 0, 0}; + Fts5Buffer *pSmall = 0; + + fts5IndexFlush(p); + pStruct = fts5StructureRead(p); + + while( p->rc==SQLITE_OK ){ + Fts5Iter *pPrev = pSet ? pSet->apIter[pSet->nIter-1] : 0; + Fts5Iter *pNew = 0; + Fts5SegIter *pNewIter = 0; + Fts5SegIter *pPrevIter = 0; + + int iLvl, iSeg, ii; + + pNew = fts5MultiIterAlloc(p, pStruct->nSegment); + if( pSmall ){ + fts5BufferSet(&p->rc, &bSeek, pSmall->n, pSmall->p); + fts5BufferAppendBlob(&p->rc, &bSeek, 1, (const u8*)"\0"); + }else{ + fts5BufferSet(&p->rc, &bSeek, nToken, pToken); + } + if( p->rc ){ + sqlite3Fts5IterClose((Fts5IndexIter*)pNew); + break; + } + + pNewIter = &pNew->aSeg[0]; + pPrevIter = (pPrev ? &pPrev->aSeg[0] : 0); + for(iLvl=0; iLvlnLevel; iLvl++){ + for(iSeg=pStruct->aLevel[iLvl].nSeg-1; iSeg>=0; iSeg--){ + Fts5StructureSegment *pSeg = &pStruct->aLevel[iLvl].aSeg[iSeg]; + int bDone = 0; + + if( pPrevIter ){ + if( fts5BufferCompare(pSmall, &pPrevIter->term) ){ + memcpy(pNewIter, pPrevIter, sizeof(Fts5SegIter)); + memset(pPrevIter, 0, sizeof(Fts5SegIter)); + bDone = 1; + }else if( pPrevIter->iEndofDoclist>pPrevIter->pLeaf->szLeaf ){ + fts5SegIterNextInit(p,(const char*)bSeek.p,bSeek.n-1,pSeg,pNewIter); + bDone = 1; + } + } + + if( bDone==0 ){ + fts5SegIterSeekInit(p, bSeek.p, bSeek.n, flags, pSeg, pNewIter); + } + + if( pPrevIter ){ + if( pPrevIter->pTombArray ){ + pNewIter->pTombArray = pPrevIter->pTombArray; + pNewIter->pTombArray->nRef++; + } + }else{ + fts5SegIterAllocTombstone(p, pNewIter); + } + + pNewIter++; + if( pPrevIter ) pPrevIter++; + if( p->rc ) break; + } + } + fts5TokendataSetTermIfEof(pPrev, pSmall); + + pNew->bSkipEmpty = 1; + pNew->pColset = pColset; + fts5IterSetOutputCb(&p->rc, pNew); + + /* Loop through all segments in the new iterator. Find the smallest + ** term that any segment-iterator points to. Iterator pNew will be + ** used for this term. Also, set any iterator that points to a term that + ** does not match pToken/nToken to point to EOF */ + pSmall = 0; + for(ii=0; iinSeg; ii++){ + Fts5SegIter *pII = &pNew->aSeg[ii]; + if( 0==fts5IsTokendataPrefix(&pII->term, pToken, nToken) ){ + fts5SegIterSetEOF(pII); + } + if( pII->pLeaf && (!pSmall || fts5BufferCompare(pSmall, &pII->term)>0) ){ + pSmall = &pII->term; + } + } + + /* If pSmall is still NULL at this point, then the new iterator does + ** not point to any terms that match the query. So delete it and break + ** out of the loop - all required iterators have been collected. */ + if( pSmall==0 ){ + sqlite3Fts5IterClose((Fts5IndexIter*)pNew); + break; + } + + /* Append this iterator to the set and continue. */ + pSet = fts5AppendTokendataIter(p, pSet, pNew); + } + + if( p->rc==SQLITE_OK && pSet ){ + int ii; + for(ii=0; iinIter; ii++){ + Fts5Iter *pIter = pSet->apIter[ii]; + int iSeg; + for(iSeg=0; iSegnSeg; iSeg++){ + pIter->aSeg[iSeg].flags |= FTS5_SEGITER_ONETERM; + } + fts5MultiIterFinishSetup(p, pIter); + } + } + + if( p->rc==SQLITE_OK ){ + pRet = fts5MultiIterAlloc(p, 0); + } + if( pRet ){ + pRet->pTokenDataIter = pSet; + if( pSet ){ + fts5IterSetOutputsTokendata(pRet); + }else{ + pRet->base.bEof = 1; + } + }else{ + fts5TokendataIterDelete(pSet); + } + + fts5StructureRelease(pStruct); + fts5BufferFree(&bSeek); + return pRet; +} + + /* ** Open a new iterator to iterate though all rowid that match the ** specified token or token prefix. @@ -241013,8 +247561,13 @@ static int sqlite3Fts5IndexQuery( if( sqlite3Fts5BufferSize(&p->rc, &buf, nToken+1)==0 ){ int iIdx = 0; /* Index to search */ int iPrefixIdx = 0; /* +1 prefix index */ + int bTokendata = pConfig->bTokendata; if( nToken>0 ) memcpy(&buf.p[1], pToken, nToken); + if( flags & (FTS5INDEX_QUERY_NOTOKENDATA|FTS5INDEX_QUERY_SCAN) ){ + bTokendata = 0; + } + /* Figure out which index to search and set iIdx accordingly. If this ** is a prefix query for which there is no prefix index, set iIdx to ** greater than pConfig->nPrefix to indicate that the query will be @@ -241040,7 +247593,10 @@ static int sqlite3Fts5IndexQuery( } } - if( iIdx<=pConfig->nPrefix ){ + if( bTokendata && iIdx==0 ){ + buf.p[0] = '0'; + pRet = fts5SetupTokendataIter(p, buf.p, nToken+1, pColset); + }else if( iIdx<=pConfig->nPrefix ){ /* Straight index lookup */ Fts5Structure *pStruct = fts5StructureRead(p); buf.p[0] = (u8)(FTS5_MAIN_PREFIX + iIdx); @@ -241087,7 +247643,11 @@ static int sqlite3Fts5IndexQuery( static int sqlite3Fts5IterNext(Fts5IndexIter *pIndexIter){ Fts5Iter *pIter = (Fts5Iter*)pIndexIter; assert( pIter->pIndex->rc==SQLITE_OK ); - fts5MultiIterNext(pIter->pIndex, pIter, 0, 0); + if( pIter->pTokenDataIter ){ + fts5TokendataIterNext(pIter, 0, 0); + }else{ + fts5MultiIterNext(pIter->pIndex, pIter, 0, 0); + } return fts5IndexReturn(pIter->pIndex); } @@ -241120,7 +247680,11 @@ static int sqlite3Fts5IterNextScan(Fts5IndexIter *pIndexIter){ */ static int sqlite3Fts5IterNextFrom(Fts5IndexIter *pIndexIter, i64 iMatch){ Fts5Iter *pIter = (Fts5Iter*)pIndexIter; - fts5MultiIterNextFrom(pIter->pIndex, pIter, iMatch); + if( pIter->pTokenDataIter ){ + fts5TokendataIterNext(pIter, 1, iMatch); + }else{ + fts5MultiIterNextFrom(pIter->pIndex, pIter, iMatch); + } return fts5IndexReturn(pIter->pIndex); } @@ -241135,6 +247699,99 @@ static const char *sqlite3Fts5IterTerm(Fts5IndexIter *pIndexIter, int *pn){ return (z ? &z[1] : 0); } +/* +** This is used by xInstToken() to access the token at offset iOff, column +** iCol of row iRowid. The token is returned via output variables *ppOut +** and *pnOut. The iterator passed as the first argument must be a tokendata=1 +** iterator (pIter->pTokenDataIter!=0). +*/ +static int sqlite3Fts5IterToken( + Fts5IndexIter *pIndexIter, + i64 iRowid, + int iCol, + int iOff, + const char **ppOut, int *pnOut +){ + Fts5Iter *pIter = (Fts5Iter*)pIndexIter; + Fts5TokenDataIter *pT = pIter->pTokenDataIter; + Fts5TokenDataMap *aMap = pT->aMap; + i64 iPos = (((i64)iCol)<<32) + iOff; + + int i1 = 0; + int i2 = pT->nMap; + int iTest = 0; + + while( i2>i1 ){ + iTest = (i1 + i2) / 2; + + if( aMap[iTest].iRowidiRowid ){ + i2 = iTest; + }else{ + if( aMap[iTest].iPosiPos ){ + i2 = iTest; + }else{ + break; + } + } + } + + if( i2>i1 ){ + Fts5Iter *pMap = pT->apIter[aMap[iTest].iIter]; + *ppOut = (const char*)pMap->aSeg[0].term.p+1; + *pnOut = pMap->aSeg[0].term.n-1; + } + + return SQLITE_OK; +} + +/* +** Clear any existing entries from the token-map associated with the +** iterator passed as the only argument. +*/ +static void sqlite3Fts5IndexIterClearTokendata(Fts5IndexIter *pIndexIter){ + Fts5Iter *pIter = (Fts5Iter*)pIndexIter; + if( pIter && pIter->pTokenDataIter ){ + pIter->pTokenDataIter->nMap = 0; + } +} + +/* +** Set a token-mapping for the iterator passed as the first argument. This +** is used in detail=column or detail=none mode when a token is requested +** using the xInstToken() API. In this case the caller tokenizers the +** current row and configures the token-mapping via multiple calls to this +** function. +*/ +static int sqlite3Fts5IndexIterWriteTokendata( + Fts5IndexIter *pIndexIter, + const char *pToken, int nToken, + i64 iRowid, int iCol, int iOff +){ + Fts5Iter *pIter = (Fts5Iter*)pIndexIter; + Fts5TokenDataIter *pT = pIter->pTokenDataIter; + Fts5Index *p = pIter->pIndex; + int ii; + + assert( p->pConfig->eDetail!=FTS5_DETAIL_FULL ); + assert( pIter->pTokenDataIter ); + + for(ii=0; iinIter; ii++){ + Fts5Buffer *pTerm = &pT->apIter[ii]->aSeg[0].term; + if( nToken==pTerm->n-1 && memcmp(pToken, pTerm->p+1, nToken)==0 ) break; + } + if( iinIter ){ + fts5TokendataIterAppendMap(p, pT, ii, iRowid, (((i64)iCol)<<32) + iOff); + } + return fts5IndexReturn(p); +} + /* ** Close an iterator opened by an earlier call to sqlite3Fts5IndexQuery(). */ @@ -241142,6 +247799,7 @@ static void sqlite3Fts5IterClose(Fts5IndexIter *pIndexIter){ if( pIndexIter ){ Fts5Iter *pIter = (Fts5Iter*)pIndexIter; Fts5Index *pIndex = pIter->pIndex; + fts5TokendataIterDelete(pIter->pTokenDataIter); fts5MultiIterFree(pIter); sqlite3Fts5IndexCloseReader(pIndex); } @@ -241649,7 +248307,9 @@ static int fts5QueryCksum( int eDetail = p->pConfig->eDetail; u64 cksum = *pCksum; Fts5IndexIter *pIter = 0; - int rc = sqlite3Fts5IndexQuery(p, z, n, flags, 0, &pIter); + int rc = sqlite3Fts5IndexQuery( + p, z, n, (flags | FTS5INDEX_QUERY_NOTOKENDATA), 0, &pIter + ); while( rc==SQLITE_OK && ALWAYS(pIter!=0) && 0==sqlite3Fts5IterEof(pIter) ){ i64 rowid = pIter->iRowid; @@ -241816,7 +248476,7 @@ static void fts5IndexIntegrityCheckEmpty( } static void fts5IntegrityCheckPgidx(Fts5Index *p, Fts5Data *pLeaf){ - int iTermOff = 0; + i64 iTermOff = 0; int ii; Fts5Buffer buf1 = {0,0,0}; @@ -241825,7 +248485,7 @@ static void fts5IntegrityCheckPgidx(Fts5Index *p, Fts5Data *pLeaf){ ii = pLeaf->szLeaf; while( iinn && p->rc==SQLITE_OK ){ int res; - int iOff; + i64 iOff; int nIncr; ii += fts5GetVarint32(&pLeaf->p[ii], nIncr); @@ -242347,6 +249007,24 @@ static void fts5DecodeRowidList( } #endif /* SQLITE_TEST || SQLITE_FTS5_DEBUG */ +#if defined(SQLITE_TEST) || defined(SQLITE_FTS5_DEBUG) +static void fts5BufferAppendTerm(int *pRc, Fts5Buffer *pBuf, Fts5Buffer *pTerm){ + int ii; + fts5BufferGrow(pRc, pBuf, pTerm->n*2 + 1); + if( *pRc==SQLITE_OK ){ + for(ii=0; iin; ii++){ + if( pTerm->p[ii]==0x00 ){ + pBuf->p[pBuf->n++] = '\\'; + pBuf->p[pBuf->n++] = '0'; + }else{ + pBuf->p[pBuf->n++] = pTerm->p[ii]; + } + } + pBuf->p[pBuf->n] = 0x00; + } +} +#endif /* SQLITE_TEST || SQLITE_FTS5_DEBUG */ + #if defined(SQLITE_TEST) || defined(SQLITE_FTS5_DEBUG) /* ** The implementation of user-defined scalar function fts5_decode(). @@ -242454,9 +249132,8 @@ static void fts5DecodeFunction( iOff += fts5GetVarint32(&a[iOff], nAppend); term.n = nKeep; fts5BufferAppendBlob(&rc, &term, nAppend, &a[iOff]); - sqlite3Fts5BufferAppendPrintf( - &rc, &s, " term=%.*s", term.n, (const char*)term.p - ); + sqlite3Fts5BufferAppendPrintf(&rc, &s, " term="); + fts5BufferAppendTerm(&rc, &s, &term); iOff += nAppend; /* Figure out where the doclist for this term ends */ @@ -242564,9 +249241,8 @@ static void fts5DecodeFunction( fts5BufferAppendBlob(&rc, &term, nByte, &a[iOff]); iOff += nByte; - sqlite3Fts5BufferAppendPrintf( - &rc, &s, " term=%.*s", term.n, (const char*)term.p - ); + sqlite3Fts5BufferAppendPrintf(&rc, &s, " term="); + fts5BufferAppendTerm(&rc, &s, &term); iOff += fts5DecodeDoclist(&rc, &s, &a[iOff], iEnd-iOff); } @@ -242900,7 +249576,8 @@ static int sqlite3Fts5IndexInit(sqlite3 *db){ 0, /* xSavepoint */ 0, /* xRelease */ 0, /* xRollbackTo */ - 0 /* xShadowName */ + 0, /* xShadowName */ + 0 /* xIntegrity */ }; rc = sqlite3_create_module(db, "fts5_structure", &fts5structure_module, 0); } @@ -243039,6 +249716,8 @@ struct Fts5FullTable { Fts5Storage *pStorage; /* Document store */ Fts5Global *pGlobal; /* Global (connection wide) data */ Fts5Cursor *pSortCsr; /* Sort data from this cursor */ + int iSavepoint; /* Successful xSavepoint()+1 */ + #ifdef SQLITE_DEBUG struct Fts5TransactionState ts; #endif @@ -243327,6 +250006,13 @@ static int fts5InitVtab( pConfig->pzErrmsg = 0; } + if( rc==SQLITE_OK && pConfig->eContent==FTS5_CONTENT_NORMAL ){ + rc = sqlite3_vtab_config(db, SQLITE_VTAB_CONSTRAINT_SUPPORT, (int)1); + } + if( rc==SQLITE_OK ){ + rc = sqlite3_vtab_config(db, SQLITE_VTAB_INNOCUOUS); + } + if( rc!=SQLITE_OK ){ fts5FreeVtab(pTab); pTab = 0; @@ -243569,12 +250255,15 @@ static int fts5BestIndexMethod(sqlite3_vtab *pVTab, sqlite3_index_info *pInfo){ } idxStr[iIdxStr] = '\0'; - /* Set idxFlags flags for the ORDER BY clause */ + /* Set idxFlags flags for the ORDER BY clause + ** + ** Note that tokendata=1 tables cannot currently handle "ORDER BY rowid DESC". + */ if( pInfo->nOrderBy==1 ){ int iSort = pInfo->aOrderBy[0].iColumn; if( iSort==(pConfig->nCol+1) && bSeenMatch ){ idxFlags |= FTS5_BI_ORDER_RANK; - }else if( iSort==-1 ){ + }else if( iSort==-1 && (!pInfo->aOrderBy[0].desc || !pConfig->bTokendata) ){ idxFlags |= FTS5_BI_ORDER_ROWID; } if( BitFlagTest(idxFlags, FTS5_BI_ORDER_RANK|FTS5_BI_ORDER_ROWID) ){ @@ -243826,6 +250515,16 @@ static int fts5NextMethod(sqlite3_vtab_cursor *pCursor){ ); assert( !CsrFlagTest(pCsr, FTS5CSR_EOF) ); + /* If this cursor uses FTS5_PLAN_MATCH and this is a tokendata=1 table, + ** clear any token mappings accumulated at the fts5_index.c level. In + ** other cases, specifically FTS5_PLAN_SOURCE and FTS5_PLAN_SORTED_MATCH, + ** we need to retain the mappings for the entire query. */ + if( pCsr->ePlan==FTS5_PLAN_MATCH + && ((Fts5Table*)pCursor->pVtab)->pConfig->bTokendata + ){ + sqlite3Fts5ExprClearTokens(pCsr->pExpr); + } + if( pCsr->ePlan<3 ){ int bSkip = 0; if( (rc = fts5CursorReseek(pCsr, &bSkip)) || bSkip ) return rc; @@ -244251,6 +250950,9 @@ static int fts5FilterMethod( pCsr->iFirstRowid = fts5GetRowidLimit(pRowidGe, SMALLEST_INT64); } + rc = sqlite3Fts5IndexLoadConfig(pTab->p.pIndex); + if( rc!=SQLITE_OK ) goto filter_out; + if( pTab->pSortCsr ){ /* If pSortCsr is non-NULL, then this call is being made as part of ** processing for a "... MATCH ORDER BY rank" query (ePlan is @@ -244273,6 +250975,7 @@ static int fts5FilterMethod( pCsr->pExpr = pTab->pSortCsr->pExpr; rc = fts5CursorFirst(pTab, pCsr, bDesc); }else if( pCsr->pExpr ){ + assert( rc==SQLITE_OK ); rc = fts5CursorParseRank(pConfig, pCsr, pRank); if( rc==SQLITE_OK ){ if( bOrderByRank ){ @@ -244444,6 +251147,7 @@ static int fts5SpecialInsert( Fts5Config *pConfig = pTab->p.pConfig; int rc = SQLITE_OK; int bError = 0; + int bLoadConfig = 0; if( 0==sqlite3_stricmp("delete-all", zCmd) ){ if( pConfig->eContent==FTS5_CONTENT_NORMAL ){ @@ -244455,6 +251159,7 @@ static int fts5SpecialInsert( }else{ rc = sqlite3Fts5StorageDeleteAll(pTab->pStorage); } + bLoadConfig = 1; }else if( 0==sqlite3_stricmp("rebuild", zCmd) ){ if( pConfig->eContent==FTS5_CONTENT_NONE ){ fts5SetVtabError(pTab, @@ -244464,6 +251169,7 @@ static int fts5SpecialInsert( }else{ rc = sqlite3Fts5StorageRebuild(pTab->pStorage); } + bLoadConfig = 1; }else if( 0==sqlite3_stricmp("optimize", zCmd) ){ rc = sqlite3Fts5StorageOptimize(pTab->pStorage); }else if( 0==sqlite3_stricmp("merge", zCmd) ){ @@ -244476,8 +251182,13 @@ static int fts5SpecialInsert( }else if( 0==sqlite3_stricmp("prefix-index", zCmd) ){ pConfig->bPrefixIndex = sqlite3_value_int(pVal); #endif + }else if( 0==sqlite3_stricmp("flush", zCmd) ){ + rc = sqlite3Fts5FlushToDisk(&pTab->p); }else{ - rc = sqlite3Fts5IndexLoadConfig(pTab->p.pIndex); + rc = sqlite3Fts5FlushToDisk(&pTab->p); + if( rc==SQLITE_OK ){ + rc = sqlite3Fts5IndexLoadConfig(pTab->p.pIndex); + } if( rc==SQLITE_OK ){ rc = sqlite3Fts5ConfigSetValue(pTab->p.pConfig, zCmd, pVal, &bError); } @@ -244489,6 +251200,12 @@ static int fts5SpecialInsert( } } } + + if( rc==SQLITE_OK && bLoadConfig ){ + pTab->p.pConfig->iCookie--; + rc = sqlite3Fts5IndexLoadConfig(pTab->p.pIndex); + } + return rc; } @@ -244607,7 +251324,7 @@ static int fts5UpdateMethod( assert( nArg!=1 || eType0==SQLITE_INTEGER ); /* Filter out attempts to run UPDATE or DELETE on contentless tables. - ** This is not suported. Except - DELETE is supported if the CREATE + ** This is not suported. Except - they are both supported if the CREATE ** VIRTUAL TABLE statement contained "contentless_delete=1". */ if( eType0==SQLITE_INTEGER && pConfig->eContent==FTS5_CONTENT_NONE @@ -244636,7 +251353,8 @@ static int fts5UpdateMethod( } else if( eType0!=SQLITE_INTEGER ){ - /* If this is a REPLACE, first remove the current entry (if any) */ + /* An INSERT statement. If the conflict-mode is REPLACE, first remove + ** the current entry (if any). */ if( eConflict==SQLITE_REPLACE && eType1==SQLITE_INTEGER ){ i64 iNew = sqlite3_value_int64(apVal[1]); /* Rowid to delete */ rc = sqlite3Fts5StorageDelete(pTab->pStorage, iNew, 0); @@ -244795,7 +251513,10 @@ static int fts5ApiColumnText( ){ int rc = SQLITE_OK; Fts5Cursor *pCsr = (Fts5Cursor*)pCtx; - if( fts5IsContentless((Fts5FullTable*)(pCsr->base.pVtab)) + Fts5Table *pTab = (Fts5Table*)(pCsr->base.pVtab); + if( iCol<0 || iCol>=pTab->pConfig->nCol ){ + rc = SQLITE_RANGE; + }else if( fts5IsContentless((Fts5FullTable*)(pCsr->base.pVtab)) || pCsr->ePlan==FTS5_PLAN_SPECIAL ){ *pz = 0; @@ -244820,8 +251541,9 @@ static int fts5CsrPoslist( int rc = SQLITE_OK; int bLive = (pCsr->pSorter==0); - if( CsrFlagTest(pCsr, FTS5CSR_REQUIRE_POSLIST) ){ - + if( iPhrase<0 || iPhrase>=sqlite3Fts5ExprPhraseCount(pCsr->pExpr) ){ + rc = SQLITE_RANGE; + }else if( CsrFlagTest(pCsr, FTS5CSR_REQUIRE_POSLIST) ){ if( pConfig->eDetail!=FTS5_DETAIL_FULL ){ Fts5PoslistPopulator *aPopulator; int i; @@ -244845,15 +251567,21 @@ static int fts5CsrPoslist( CsrFlagClear(pCsr, FTS5CSR_REQUIRE_POSLIST); } - if( pCsr->pSorter && pConfig->eDetail==FTS5_DETAIL_FULL ){ - Fts5Sorter *pSorter = pCsr->pSorter; - int i1 = (iPhrase==0 ? 0 : pSorter->aIdx[iPhrase-1]); - *pn = pSorter->aIdx[iPhrase] - i1; - *pa = &pSorter->aPoslist[i1]; + if( rc==SQLITE_OK ){ + if( pCsr->pSorter && pConfig->eDetail==FTS5_DETAIL_FULL ){ + Fts5Sorter *pSorter = pCsr->pSorter; + int i1 = (iPhrase==0 ? 0 : pSorter->aIdx[iPhrase-1]); + *pn = pSorter->aIdx[iPhrase] - i1; + *pa = &pSorter->aPoslist[i1]; + }else{ + *pn = sqlite3Fts5ExprPoslist(pCsr->pExpr, iPhrase, pa); + } }else{ - *pn = sqlite3Fts5ExprPoslist(pCsr->pExpr, iPhrase, pa); + *pa = 0; + *pn = 0; } + return rc; } @@ -244960,12 +251688,6 @@ static int fts5ApiInst( ){ if( iIdx<0 || iIdx>=pCsr->nInstCount ){ rc = SQLITE_RANGE; -#if 0 - }else if( fts5IsOffsetless((Fts5Table*)pCsr->base.pVtab) ){ - *piPhrase = pCsr->aInst[iIdx*3]; - *piCol = pCsr->aInst[iIdx*3 + 2]; - *piOff = -1; -#endif }else{ *piPhrase = pCsr->aInst[iIdx*3]; *piCol = pCsr->aInst[iIdx*3 + 1]; @@ -245220,13 +251942,56 @@ static int fts5ApiPhraseFirstColumn( return rc; } +/* +** xQueryToken() API implemenetation. +*/ +static int fts5ApiQueryToken( + Fts5Context* pCtx, + int iPhrase, + int iToken, + const char **ppOut, + int *pnOut +){ + Fts5Cursor *pCsr = (Fts5Cursor*)pCtx; + return sqlite3Fts5ExprQueryToken(pCsr->pExpr, iPhrase, iToken, ppOut, pnOut); +} + +/* +** xInstToken() API implemenetation. +*/ +static int fts5ApiInstToken( + Fts5Context *pCtx, + int iIdx, + int iToken, + const char **ppOut, int *pnOut +){ + Fts5Cursor *pCsr = (Fts5Cursor*)pCtx; + int rc = SQLITE_OK; + if( CsrFlagTest(pCsr, FTS5CSR_REQUIRE_INST)==0 + || SQLITE_OK==(rc = fts5CacheInstArray(pCsr)) + ){ + if( iIdx<0 || iIdx>=pCsr->nInstCount ){ + rc = SQLITE_RANGE; + }else{ + int iPhrase = pCsr->aInst[iIdx*3]; + int iCol = pCsr->aInst[iIdx*3 + 1]; + int iOff = pCsr->aInst[iIdx*3 + 2]; + i64 iRowid = fts5CursorRowid(pCsr); + rc = sqlite3Fts5ExprInstToken( + pCsr->pExpr, iRowid, iPhrase, iCol, iOff, iToken, ppOut, pnOut + ); + } + } + return rc; +} + static int fts5ApiQueryPhrase(Fts5Context*, int, void*, int(*)(const Fts5ExtensionApi*, Fts5Context*, void*) ); static const Fts5ExtensionApi sFts5Api = { - 2, /* iVersion */ + 3, /* iVersion */ fts5ApiUserData, fts5ApiColumnCount, fts5ApiRowCount, @@ -245246,6 +252011,8 @@ static const Fts5ExtensionApi sFts5Api = { fts5ApiPhraseNext, fts5ApiPhraseFirstColumn, fts5ApiPhraseNextColumn, + fts5ApiQueryToken, + fts5ApiInstToken }; /* @@ -245510,8 +252277,10 @@ static int fts5RenameMethod( sqlite3_vtab *pVtab, /* Virtual table handle */ const char *zName /* New name of table */ ){ + int rc; Fts5FullTable *pTab = (Fts5FullTable*)pVtab; - return sqlite3Fts5StorageRename(pTab->pStorage, zName); + rc = sqlite3Fts5StorageRename(pTab->pStorage, zName); + return rc; } static int sqlite3Fts5FlushToDisk(Fts5Table *pTab){ @@ -245525,9 +252294,15 @@ static int sqlite3Fts5FlushToDisk(Fts5Table *pTab){ ** Flush the contents of the pending-terms table to disk. */ static int fts5SavepointMethod(sqlite3_vtab *pVtab, int iSavepoint){ - UNUSED_PARAM(iSavepoint); /* Call below is a no-op for NDEBUG builds */ - fts5CheckTransactionState((Fts5FullTable*)pVtab, FTS5_SAVEPOINT, iSavepoint); - return sqlite3Fts5FlushToDisk((Fts5Table*)pVtab); + Fts5FullTable *pTab = (Fts5FullTable*)pVtab; + int rc = SQLITE_OK; + + fts5CheckTransactionState(pTab, FTS5_SAVEPOINT, iSavepoint); + rc = sqlite3Fts5FlushToDisk((Fts5Table*)pVtab); + if( rc==SQLITE_OK ){ + pTab->iSavepoint = iSavepoint+1; + } + return rc; } /* @@ -245536,9 +252311,16 @@ static int fts5SavepointMethod(sqlite3_vtab *pVtab, int iSavepoint){ ** This is a no-op. */ static int fts5ReleaseMethod(sqlite3_vtab *pVtab, int iSavepoint){ - UNUSED_PARAM(iSavepoint); /* Call below is a no-op for NDEBUG builds */ - fts5CheckTransactionState((Fts5FullTable*)pVtab, FTS5_RELEASE, iSavepoint); - return sqlite3Fts5FlushToDisk((Fts5Table*)pVtab); + Fts5FullTable *pTab = (Fts5FullTable*)pVtab; + int rc = SQLITE_OK; + fts5CheckTransactionState(pTab, FTS5_RELEASE, iSavepoint); + if( (iSavepoint+1)iSavepoint ){ + rc = sqlite3Fts5FlushToDisk(&pTab->p); + if( rc==SQLITE_OK ){ + pTab->iSavepoint = iSavepoint; + } + } + return rc; } /* @@ -245548,11 +252330,14 @@ static int fts5ReleaseMethod(sqlite3_vtab *pVtab, int iSavepoint){ */ static int fts5RollbackToMethod(sqlite3_vtab *pVtab, int iSavepoint){ Fts5FullTable *pTab = (Fts5FullTable*)pVtab; - UNUSED_PARAM(iSavepoint); /* Call below is a no-op for NDEBUG builds */ + int rc = SQLITE_OK; fts5CheckTransactionState(pTab, FTS5_ROLLBACKTO, iSavepoint); fts5TripCursors(pTab); - pTab->p.pConfig->pgsz = 0; - return sqlite3Fts5StorageRollback(pTab->pStorage); + if( (iSavepoint+1)<=pTab->iSavepoint ){ + pTab->p.pConfig->pgsz = 0; + rc = sqlite3Fts5StorageRollback(pTab->pStorage); + } + return rc; } /* @@ -245754,7 +252539,7 @@ static void fts5SourceIdFunc( ){ assert( nArg==0 ); UNUSED_PARAM2(nArg, apUnused); - sqlite3_result_text(pCtx, "fts5: 2023-09-11 12:01:27 2d3a40c05c49e1a49264912b1a05bc2143ac0e7c3df588276ce80a4cbc9bd1b0", -1, SQLITE_TRANSIENT); + sqlite3_result_text(pCtx, "fts5: 2024-05-23 13:25:27 96c92aba00c8375bc32fafcdf12429c58bd8aabfcadab6683e35bbb9cdebf19e", -1, SQLITE_TRANSIENT); } /* @@ -245772,9 +252557,41 @@ static int fts5ShadowName(const char *zName){ return 0; } +/* +** Run an integrity check on the FTS5 data structures. Return a string +** if anything is found amiss. Return a NULL pointer if everything is +** OK. +*/ +static int fts5IntegrityMethod( + sqlite3_vtab *pVtab, /* the FTS5 virtual table to check */ + const char *zSchema, /* Name of schema in which this table lives */ + const char *zTabname, /* Name of the table itself */ + int isQuick, /* True if this is a quick-check */ + char **pzErr /* Write error message here */ +){ + Fts5FullTable *pTab = (Fts5FullTable*)pVtab; + int rc; + + assert( pzErr!=0 && *pzErr==0 ); + UNUSED_PARAM(isQuick); + rc = sqlite3Fts5StorageIntegrity(pTab->pStorage, 0); + if( (rc&0xff)==SQLITE_CORRUPT ){ + *pzErr = sqlite3_mprintf("malformed inverted index for FTS5 table %s.%s", + zSchema, zTabname); + rc = (*pzErr) ? SQLITE_OK : SQLITE_NOMEM; + }else if( rc!=SQLITE_OK ){ + *pzErr = sqlite3_mprintf("unable to validate the inverted index for" + " FTS5 table %s.%s: %s", + zSchema, zTabname, sqlite3_errstr(rc)); + } + sqlite3Fts5IndexCloseReader(pTab->p.pIndex); + + return rc; +} + static int fts5Init(sqlite3 *db){ static const sqlite3_module fts5Mod = { - /* iVersion */ 3, + /* iVersion */ 4, /* xCreate */ fts5CreateMethod, /* xConnect */ fts5ConnectMethod, /* xBestIndex */ fts5BestIndexMethod, @@ -245797,7 +252614,8 @@ static int fts5Init(sqlite3 *db){ /* xSavepoint */ fts5SavepointMethod, /* xRelease */ fts5ReleaseMethod, /* xRollbackTo */ fts5RollbackToMethod, - /* xShadowName */ fts5ShadowName + /* xShadowName */ fts5ShadowName, + /* xIntegrity */ fts5IntegrityMethod }; int rc; @@ -246563,7 +253381,7 @@ static int sqlite3Fts5StorageRebuild(Fts5Storage *p){ } if( rc==SQLITE_OK ){ - rc = fts5StorageGetStmt(p, FTS5_STMT_SCAN, &pScan, 0); + rc = fts5StorageGetStmt(p, FTS5_STMT_SCAN, &pScan, pConfig->pzErrmsg); } while( rc==SQLITE_OK && SQLITE_ROW==sqlite3_step(pScan) ){ @@ -247074,7 +253892,9 @@ static int sqlite3Fts5StorageSync(Fts5Storage *p){ i64 iLastRowid = sqlite3_last_insert_rowid(p->pConfig->db); if( p->bTotalsValid ){ rc = fts5StorageSaveTotals(p); - p->bTotalsValid = 0; + if( rc==SQLITE_OK ){ + p->bTotalsValid = 0; + } } if( rc==SQLITE_OK ){ rc = sqlite3Fts5IndexSync(p->pIndex); @@ -247348,6 +254168,12 @@ static const unsigned char sqlite3Utf8Trans1[] = { #endif /* ifndef SQLITE_AMALGAMATION */ +#define FTS5_SKIP_UTF8(zIn) { \ + if( ((unsigned char)(*(zIn++)))>=0xc0 ){ \ + while( (((unsigned char)*zIn) & 0xc0)==0x80 ){ zIn++; } \ + } \ +} + typedef struct Unicode61Tokenizer Unicode61Tokenizer; struct Unicode61Tokenizer { unsigned char aTokenChar[128]; /* ASCII range token characters */ @@ -248383,6 +255209,7 @@ static int fts5PorterTokenize( typedef struct TrigramTokenizer TrigramTokenizer; struct TrigramTokenizer { int bFold; /* True to fold to lower-case */ + int iFoldParam; /* Parameter to pass to Fts5UnicodeFold() */ }; /* @@ -248409,6 +255236,7 @@ static int fts5TriCreate( }else{ int i; pNew->bFold = 1; + pNew->iFoldParam = 0; for(i=0; rc==SQLITE_OK && ibFold = (zArg[0]=='0'); } + }else if( 0==sqlite3_stricmp(azArg[i], "remove_diacritics") ){ + if( (zArg[0]!='0' && zArg[0]!='1' && zArg[0]!='2') || zArg[1] ){ + rc = SQLITE_ERROR; + }else{ + pNew->iFoldParam = (zArg[0]!='0') ? 2 : 0; + } }else{ rc = SQLITE_ERROR; } } + + if( pNew->iFoldParam!=0 && pNew->bFold==0 ){ + rc = SQLITE_ERROR; + } + if( rc!=SQLITE_OK ){ fts5TriDelete((Fts5Tokenizer*)pNew); pNew = 0; @@ -248443,40 +255282,62 @@ static int fts5TriTokenize( TrigramTokenizer *p = (TrigramTokenizer*)pTok; int rc = SQLITE_OK; char aBuf[32]; + char *zOut = aBuf; + int ii; const unsigned char *zIn = (const unsigned char*)pText; const unsigned char *zEof = &zIn[nText]; u32 iCode; + int aStart[3]; /* Input offset of each character in aBuf[] */ UNUSED_PARAM(unusedFlags); - while( 1 ){ - char *zOut = aBuf; - int iStart = zIn - (const unsigned char*)pText; - const unsigned char *zNext; - - READ_UTF8(zIn, zEof, iCode); - if( iCode==0 ) break; - zNext = zIn; - if( zInbFold ) iCode = sqlite3Fts5UnicodeFold(iCode, 0); - WRITE_UTF8(zOut, iCode); + + /* Populate aBuf[] with the characters for the first trigram. */ + for(ii=0; ii<3; ii++){ + do { + aStart[ii] = zIn - (const unsigned char*)pText; READ_UTF8(zIn, zEof, iCode); - if( iCode==0 ) break; - }else{ - break; - } - if( zInbFold ) iCode = sqlite3Fts5UnicodeFold(iCode, 0); - WRITE_UTF8(zOut, iCode); + if( iCode==0 ) return SQLITE_OK; + if( p->bFold ) iCode = sqlite3Fts5UnicodeFold(iCode, p->iFoldParam); + }while( iCode==0 ); + WRITE_UTF8(zOut, iCode); + } + + /* At the start of each iteration of this loop: + ** + ** aBuf: Contains 3 characters. The 3 characters of the next trigram. + ** zOut: Points to the byte following the last character in aBuf. + ** aStart[3]: Contains the byte offset in the input text corresponding + ** to the start of each of the three characters in the buffer. + */ + assert( zIn<=zEof ); + while( 1 ){ + int iNext; /* Start of character following current tri */ + const char *z1; + + /* Read characters from the input up until the first non-diacritic */ + do { + iNext = zIn - (const unsigned char*)pText; READ_UTF8(zIn, zEof, iCode); if( iCode==0 ) break; - if( p->bFold ) iCode = sqlite3Fts5UnicodeFold(iCode, 0); - WRITE_UTF8(zOut, iCode); - }else{ - break; - } - rc = xToken(pCtx, 0, aBuf, zOut-aBuf, iStart, iStart + zOut-aBuf); - if( rc!=SQLITE_OK ) break; - zIn = zNext; + if( p->bFold ) iCode = sqlite3Fts5UnicodeFold(iCode, p->iFoldParam); + }while( iCode==0 ); + + /* Pass the current trigram back to fts5 */ + rc = xToken(pCtx, 0, aBuf, zOut-aBuf, aStart[0], iNext); + if( iCode==0 || rc!=SQLITE_OK ) break; + + /* Remove the first character from buffer aBuf[]. Append the character + ** with codepoint iCode. */ + z1 = aBuf; + FTS5_SKIP_UTF8(z1); + memmove(aBuf, z1, zOut - z1); + zOut -= (z1 - aBuf); + WRITE_UTF8(zOut, iCode); + + /* Update the aStart[] array */ + aStart[0] = aStart[1]; + aStart[1] = aStart[2]; + aStart[2] = iNext; } return rc; @@ -248499,7 +255360,9 @@ static int sqlite3Fts5TokenizerPattern( ){ if( xCreate==fts5TriCreate ){ TrigramTokenizer *p = (TrigramTokenizer*)pTok; - return p->bFold ? FTS5_PATTERN_LIKE : FTS5_PATTERN_GLOB; + if( p->iFoldParam==0 ){ + return p->bFold ? FTS5_PATTERN_LIKE : FTS5_PATTERN_GLOB; + } } return FTS5_PATTERN_NONE; } @@ -250288,7 +257151,7 @@ static int fts5VocabFilterMethod( if( pEq ){ zTerm = (const char *)sqlite3_value_text(pEq); nTerm = sqlite3_value_bytes(pEq); - f = 0; + f = FTS5INDEX_QUERY_NOTOKENDATA; }else{ if( pGe ){ zTerm = (const char *)sqlite3_value_text(pGe); @@ -250442,7 +257305,8 @@ static int sqlite3Fts5VocabInit(Fts5Global *pGlobal, sqlite3 *db){ /* xSavepoint */ 0, /* xRelease */ 0, /* xRollbackTo */ 0, - /* xShadowName */ 0 + /* xShadowName */ 0, + /* xIntegrity */ 0 }; void *p = (void*)pGlobal; @@ -250771,6 +257635,7 @@ static sqlite3_module stmtModule = { 0, /* xRelease */ 0, /* xRollbackTo */ 0, /* xShadowName */ + 0 /* xIntegrity */ }; #endif /* SQLITE_OMIT_VIRTUALTABLE */ diff --git a/vendor/sqlite/sqlite3.h b/vendor/sqlite/sqlite3.h index b9d0692988..57df8dcf20 100644 --- a/vendor/sqlite/sqlite3.h +++ b/vendor/sqlite/sqlite3.h @@ -146,9 +146,9 @@ extern "C" { ** [sqlite3_libversion_number()], [sqlite3_sourceid()], ** [sqlite_version()] and [sqlite_source_id()]. */ -#define SQLITE_VERSION "3.43.1" -#define SQLITE_VERSION_NUMBER 3043001 -#define SQLITE_SOURCE_ID "2023-09-11 12:01:27 2d3a40c05c49e1a49264912b1a05bc2143ac0e7c3df588276ce80a4cbc9bd1b0" +#define SQLITE_VERSION "3.46.0" +#define SQLITE_VERSION_NUMBER 3046000 +#define SQLITE_SOURCE_ID "2024-05-23 13:25:27 96c92aba00c8375bc32fafcdf12429c58bd8aabfcadab6683e35bbb9cdebf19e" /* ** CAPI3REF: Run-Time Library Version Numbers @@ -420,6 +420,8 @@ typedef int (*sqlite3_callback)(void*,int,char**, char**); ** the 1st parameter to sqlite3_exec() while sqlite3_exec() is running. **
  • The application must not modify the SQL statement text passed into ** the 2nd parameter of sqlite3_exec() while sqlite3_exec() is running. +**
  • The application must not dereference the arrays or string pointers +** passed as the 3rd and 4th callback parameters after it returns. ** */ SQLITE_API int sqlite3_exec( @@ -762,11 +764,11 @@ struct sqlite3_file { ** ** xLock() upgrades the database file lock. In other words, xLock() moves the ** database file lock in the direction NONE toward EXCLUSIVE. The argument to -** xLock() is always on of SHARED, RESERVED, PENDING, or EXCLUSIVE, never +** xLock() is always one of SHARED, RESERVED, PENDING, or EXCLUSIVE, never ** SQLITE_LOCK_NONE. If the database file lock is already at or above the ** requested lock, then the call to xLock() is a no-op. ** xUnlock() downgrades the database file lock to either SHARED or NONE. -* If the lock is already at or below the requested lock state, then the call +** If the lock is already at or below the requested lock state, then the call ** to xUnlock() is a no-op. ** The xCheckReservedLock() method checks whether any database connection, ** either in this process or in some other process, is holding a RESERVED, @@ -2127,7 +2129,7 @@ struct sqlite3_mem_methods { ** is stored in each sorted record and the required column values loaded ** from the database as records are returned in sorted order. The default ** value for this option is to never use this optimization. Specifying a -** negative value for this option restores the default behaviour. +** negative value for this option restores the default behavior. ** This option is only available if SQLite is compiled with the ** [SQLITE_ENABLE_SORTER_REFERENCES] compile-time option. ** @@ -2141,6 +2143,22 @@ struct sqlite3_mem_methods { ** configuration setting is never used, then the default maximum is determined ** by the [SQLITE_MEMDB_DEFAULT_MAXSIZE] compile-time option. If that ** compile-time option is not set, then the default maximum is 1073741824. +** +** [[SQLITE_CONFIG_ROWID_IN_VIEW]] +**
    SQLITE_CONFIG_ROWID_IN_VIEW +**
    The SQLITE_CONFIG_ROWID_IN_VIEW option enables or disables the ability +** for VIEWs to have a ROWID. The capability can only be enabled if SQLite is +** compiled with -DSQLITE_ALLOW_ROWID_IN_VIEW, in which case the capability +** defaults to on. This configuration option queries the current setting or +** changes the setting to off or on. The argument is a pointer to an integer. +** If that integer initially holds a value of 1, then the ability for VIEWs to +** have ROWIDs is activated. If the integer initially holds zero, then the +** ability is deactivated. Any other initial value for the integer leaves the +** setting unchanged. After changes, if any, the integer is written with +** a 1 or 0, if the ability for VIEWs to have ROWIDs is on or off. If SQLite +** is compiled without -DSQLITE_ALLOW_ROWID_IN_VIEW (which is the usual and +** recommended case) then the integer is always filled with zero, regardless +** if its initial value. ** */ #define SQLITE_CONFIG_SINGLETHREAD 1 /* nil */ @@ -2172,6 +2190,7 @@ struct sqlite3_mem_methods { #define SQLITE_CONFIG_SMALL_MALLOC 27 /* boolean */ #define SQLITE_CONFIG_SORTERREF_SIZE 28 /* int nByte */ #define SQLITE_CONFIG_MEMDB_MAXSIZE 29 /* sqlite3_int64 */ +#define SQLITE_CONFIG_ROWID_IN_VIEW 30 /* int* */ /* ** CAPI3REF: Database Connection Configuration Options @@ -2302,7 +2321,7 @@ struct sqlite3_mem_methods { ** database handle, SQLite checks if this will mean that there are now no ** connections at all to the database. If so, it performs a checkpoint ** operation before closing the connection. This option may be used to -** override this behaviour. The first parameter passed to this operation +** override this behavior. The first parameter passed to this operation ** is an integer - positive to disable checkpoints-on-close, or zero (the ** default) to enable them, and negative to leave the setting unchanged. ** The second parameter is a pointer to an integer @@ -3286,8 +3305,8 @@ SQLITE_API int sqlite3_set_authorizer( #define SQLITE_RECURSIVE 33 /* NULL NULL */ /* -** CAPI3REF: Tracing And Profiling Functions -** METHOD: sqlite3 +** CAPI3REF: Deprecated Tracing And Profiling Functions +** DEPRECATED ** ** These routines are deprecated. Use the [sqlite3_trace_v2()] interface ** instead of the routines described here. @@ -3954,14 +3973,17 @@ SQLITE_API void sqlite3_free_filename(sqlite3_filename); ** ** ** ^The sqlite3_errmsg() and sqlite3_errmsg16() return English-language -** text that describes the error, as either UTF-8 or UTF-16 respectively. +** text that describes the error, as either UTF-8 or UTF-16 respectively, +** or NULL if no error message is available. +** (See how SQLite handles [invalid UTF] for exceptions to this rule.) ** ^(Memory to hold the error message string is managed internally. ** The application does not need to worry about freeing the result. ** However, the error string might be overwritten or deallocated by ** subsequent calls to other SQLite interface functions.)^ ** -** ^The sqlite3_errstr() interface returns the English-language text -** that describes the [result code], as UTF-8. +** ^The sqlite3_errstr(E) interface returns the English-language text +** that describes the [result code] E, as UTF-8, or NULL if E is not an +** result code for which a text error message is available. ** ^(Memory to hold the error message string is managed internally ** and must not be freed by the application)^. ** @@ -5325,6 +5347,7 @@ SQLITE_API int sqlite3_finalize(sqlite3_stmt *pStmt); */ SQLITE_API int sqlite3_reset(sqlite3_stmt *pStmt); + /* ** CAPI3REF: Create Or Redefine SQL Functions ** KEYWORDS: {function creation routines} @@ -5571,13 +5594,27 @@ SQLITE_API int sqlite3_create_window_function( **
    ** ** [[SQLITE_SUBTYPE]]
    SQLITE_SUBTYPE
    -** The SQLITE_SUBTYPE flag indicates to SQLite that a function may call +** The SQLITE_SUBTYPE flag indicates to SQLite that a function might call ** [sqlite3_value_subtype()] to inspect the sub-types of its arguments. -** Specifying this flag makes no difference for scalar or aggregate user -** functions. However, if it is not specified for a user-defined window -** function, then any sub-types belonging to arguments passed to the window -** function may be discarded before the window function is called (i.e. -** sqlite3_value_subtype() will always return 0). +** This flag instructs SQLite to omit some corner-case optimizations that +** might disrupt the operation of the [sqlite3_value_subtype()] function, +** causing it to return zero rather than the correct subtype(). +** SQL functions that invokes [sqlite3_value_subtype()] should have this +** property. If the SQLITE_SUBTYPE property is omitted, then the return +** value from [sqlite3_value_subtype()] might sometimes be zero even though +** a non-zero subtype was specified by the function argument expression. +** +** [[SQLITE_RESULT_SUBTYPE]]
    SQLITE_RESULT_SUBTYPE
    +** The SQLITE_RESULT_SUBTYPE flag indicates to SQLite that a function might call +** [sqlite3_result_subtype()] to cause a sub-type to be associated with its +** result. +** Every function that invokes [sqlite3_result_subtype()] should have this +** property. If it does not, then the call to [sqlite3_result_subtype()] +** might become a no-op if the function is used as term in an +** [expression index]. On the other hand, SQL functions that never invoke +** [sqlite3_result_subtype()] should avoid setting this property, as the +** purpose of this property is to disable certain optimizations that are +** incompatible with subtypes. **
    ** */ @@ -5585,6 +5622,7 @@ SQLITE_API int sqlite3_create_window_function( #define SQLITE_DIRECTONLY 0x000080000 #define SQLITE_SUBTYPE 0x000100000 #define SQLITE_INNOCUOUS 0x000200000 +#define SQLITE_RESULT_SUBTYPE 0x001000000 /* ** CAPI3REF: Deprecated Functions @@ -5781,6 +5819,12 @@ SQLITE_API int sqlite3_value_encoding(sqlite3_value*); ** information can be used to pass a limited amount of context from ** one SQL function to another. Use the [sqlite3_result_subtype()] ** routine to set the subtype for the return value of an SQL function. +** +** Every [application-defined SQL function] that invoke this interface +** should include the [SQLITE_SUBTYPE] property in the text +** encoding argument when the function is [sqlite3_create_function|registered]. +** If the [SQLITE_SUBTYPE] property is omitted, then sqlite3_value_subtype() +** might return zero instead of the upstream subtype in some corner cases. */ SQLITE_API unsigned int sqlite3_value_subtype(sqlite3_value*); @@ -5879,48 +5923,56 @@ SQLITE_API sqlite3 *sqlite3_context_db_handle(sqlite3_context*); ** METHOD: sqlite3_context ** ** These functions may be used by (non-aggregate) SQL functions to -** associate metadata with argument values. If the same value is passed to -** multiple invocations of the same SQL function during query execution, under -** some circumstances the associated metadata may be preserved. An example -** of where this might be useful is in a regular-expression matching -** function. The compiled version of the regular expression can be stored as -** metadata associated with the pattern string. +** associate auxiliary data with argument values. If the same argument +** value is passed to multiple invocations of the same SQL function during +** query execution, under some circumstances the associated auxiliary data +** might be preserved. An example of where this might be useful is in a +** regular-expression matching function. The compiled version of the regular +** expression can be stored as auxiliary data associated with the pattern string. ** Then as long as the pattern string remains the same, ** the compiled regular expression can be reused on multiple ** invocations of the same function. ** -** ^The sqlite3_get_auxdata(C,N) interface returns a pointer to the metadata +** ^The sqlite3_get_auxdata(C,N) interface returns a pointer to the auxiliary data ** associated by the sqlite3_set_auxdata(C,N,P,X) function with the Nth argument ** value to the application-defined function. ^N is zero for the left-most -** function argument. ^If there is no metadata +** function argument. ^If there is no auxiliary data ** associated with the function argument, the sqlite3_get_auxdata(C,N) interface ** returns a NULL pointer. ** -** ^The sqlite3_set_auxdata(C,N,P,X) interface saves P as metadata for the N-th -** argument of the application-defined function. ^Subsequent +** ^The sqlite3_set_auxdata(C,N,P,X) interface saves P as auxiliary data for the +** N-th argument of the application-defined function. ^Subsequent ** calls to sqlite3_get_auxdata(C,N) return P from the most recent -** sqlite3_set_auxdata(C,N,P,X) call if the metadata is still valid or -** NULL if the metadata has been discarded. +** sqlite3_set_auxdata(C,N,P,X) call if the auxiliary data is still valid or +** NULL if the auxiliary data has been discarded. ** ^After each call to sqlite3_set_auxdata(C,N,P,X) where X is not NULL, ** SQLite will invoke the destructor function X with parameter P exactly -** once, when the metadata is discarded. -** SQLite is free to discard the metadata at any time, including:
      +** once, when the auxiliary data is discarded. +** SQLite is free to discard the auxiliary data at any time, including:
        **
      • ^(when the corresponding function parameter changes)^, or **
      • ^(when [sqlite3_reset()] or [sqlite3_finalize()] is called for the ** SQL statement)^, or **
      • ^(when sqlite3_set_auxdata() is invoked again on the same ** parameter)^, or **
      • ^(during the original sqlite3_set_auxdata() call when a memory -** allocation error occurs.)^
      +** allocation error occurs.)^ +**
    • ^(during the original sqlite3_set_auxdata() call if the function +** is evaluated during query planning instead of during query execution, +** as sometimes happens with [SQLITE_ENABLE_STAT4].)^
    ** -** Note the last bullet in particular. The destructor X in +** Note the last two bullets in particular. The destructor X in ** sqlite3_set_auxdata(C,N,P,X) might be called immediately, before the ** sqlite3_set_auxdata() interface even returns. Hence sqlite3_set_auxdata() ** should be called near the end of the function implementation and the ** function implementation should not make any use of P after -** sqlite3_set_auxdata() has been called. -** -** ^(In practice, metadata is preserved between function calls for +** sqlite3_set_auxdata() has been called. Furthermore, a call to +** sqlite3_get_auxdata() that occurs immediately after a corresponding call +** to sqlite3_set_auxdata() might still return NULL if an out-of-memory +** condition occurred during the sqlite3_set_auxdata() call or if the +** function is being evaluated during query planning rather than during +** query execution. +** +** ^(In practice, auxiliary data is preserved between function calls for ** function parameters that are compile-time constants, including literal ** values and [parameters] and expressions composed from the same.)^ ** @@ -5930,10 +5982,67 @@ SQLITE_API sqlite3 *sqlite3_context_db_handle(sqlite3_context*); ** ** These routines must be called from the same thread in which ** the SQL function is running. +** +** See also: [sqlite3_get_clientdata()] and [sqlite3_set_clientdata()]. */ SQLITE_API void *sqlite3_get_auxdata(sqlite3_context*, int N); SQLITE_API void sqlite3_set_auxdata(sqlite3_context*, int N, void*, void (*)(void*)); +/* +** CAPI3REF: Database Connection Client Data +** METHOD: sqlite3 +** +** These functions are used to associate one or more named pointers +** with a [database connection]. +** A call to sqlite3_set_clientdata(D,N,P,X) causes the pointer P +** to be attached to [database connection] D using name N. Subsequent +** calls to sqlite3_get_clientdata(D,N) will return a copy of pointer P +** or a NULL pointer if there were no prior calls to +** sqlite3_set_clientdata() with the same values of D and N. +** Names are compared using strcmp() and are thus case sensitive. +** +** If P and X are both non-NULL, then the destructor X is invoked with +** argument P on the first of the following occurrences: +**
      +**
    • An out-of-memory error occurs during the call to +** sqlite3_set_clientdata() which attempts to register pointer P. +**
    • A subsequent call to sqlite3_set_clientdata(D,N,P,X) is made +** with the same D and N parameters. +**
    • The database connection closes. SQLite does not make any guarantees +** about the order in which destructors are called, only that all +** destructors will be called exactly once at some point during the +** database connection closing process. +**
    +** +** SQLite does not do anything with client data other than invoke +** destructors on the client data at the appropriate time. The intended +** use for client data is to provide a mechanism for wrapper libraries +** to store additional information about an SQLite database connection. +** +** There is no limit (other than available memory) on the number of different +** client data pointers (with different names) that can be attached to a +** single database connection. However, the implementation is optimized +** for the case of having only one or two different client data names. +** Applications and wrapper libraries are discouraged from using more than +** one client data name each. +** +** There is no way to enumerate the client data pointers +** associated with a database connection. The N parameter can be thought +** of as a secret key such that only code that knows the secret key is able +** to access the associated data. +** +** Security Warning: These interfaces should not be exposed in scripting +** languages or in other circumstances where it might be possible for an +** an attacker to invoke them. Any agent that can invoke these interfaces +** can probably also take control of the process. +** +** Database connection client data is only available for SQLite +** version 3.44.0 ([dateof:3.44.0]) and later. +** +** See also: [sqlite3_set_auxdata()] and [sqlite3_get_auxdata()]. +*/ +SQLITE_API void *sqlite3_get_clientdata(sqlite3*,const char*); +SQLITE_API int sqlite3_set_clientdata(sqlite3*, const char*, void*, void(*)(void*)); /* ** CAPI3REF: Constants Defining Special Destructor Behavior @@ -6135,6 +6244,20 @@ SQLITE_API int sqlite3_result_zeroblob64(sqlite3_context*, sqlite3_uint64 n); ** higher order bits are discarded. ** The number of subtype bytes preserved by SQLite might increase ** in future releases of SQLite. +** +** Every [application-defined SQL function] that invokes this interface +** should include the [SQLITE_RESULT_SUBTYPE] property in its +** text encoding argument when the SQL function is +** [sqlite3_create_function|registered]. If the [SQLITE_RESULT_SUBTYPE] +** property is omitted from the function that invokes sqlite3_result_subtype(), +** then in some cases the sqlite3_result_subtype() might fail to set +** the result subtype. +** +** If SQLite is compiled with -DSQLITE_STRICT_SUBTYPE=1, then any +** SQL function that invokes the sqlite3_result_subtype() interface +** and that does not have the SQLITE_RESULT_SUBTYPE property will raise +** an error. Future versions of SQLite might enable -DSQLITE_STRICT_SUBTYPE=1 +** by default. */ SQLITE_API void sqlite3_result_subtype(sqlite3_context*,unsigned int); @@ -6566,7 +6689,7 @@ SQLITE_API int sqlite3_db_readonly(sqlite3 *db, const char *zDbName); SQLITE_API int sqlite3_txn_state(sqlite3*,const char *zSchema); /* -** CAPI3REF: Allowed return values from [sqlite3_txn_state()] +** CAPI3REF: Allowed return values from sqlite3_txn_state() ** KEYWORDS: {transaction state} ** ** These constants define the current transaction state of a database file. @@ -6698,7 +6821,7 @@ SQLITE_API void *sqlite3_rollback_hook(sqlite3*, void(*)(void *), void*); ** ^Each call to the sqlite3_autovacuum_pages() interface overrides all ** previous invocations for that database connection. ^If the callback ** argument (C) to sqlite3_autovacuum_pages(D,C,P,X) is a NULL pointer, -** then the autovacuum steps callback is cancelled. The return value +** then the autovacuum steps callback is canceled. The return value ** from sqlite3_autovacuum_pages() is normally SQLITE_OK, but might ** be some other error code if something goes wrong. The current ** implementation will only return SQLITE_OK or SQLITE_MISUSE, but other @@ -6764,6 +6887,12 @@ SQLITE_API int sqlite3_autovacuum_pages( ** The exceptions defined in this paragraph might change in a future ** release of SQLite. ** +** Whether the update hook is invoked before or after the +** corresponding change is currently unspecified and may differ +** depending on the type of change. Do not rely on the order of the +** hook call with regards to the final result of the operation which +** triggers the hook. +** ** The update hook implementation must not do anything that will modify ** the database connection that invoked the update hook. Any actions ** to modify the database connection must be deferred until after the @@ -7217,6 +7346,10 @@ struct sqlite3_module { /* The methods above are in versions 1 and 2 of the sqlite_module object. ** Those below are for version 3 and greater. */ int (*xShadowName)(const char*); + /* The methods above are in versions 1 through 3 of the sqlite_module object. + ** Those below are for version 4 and greater. */ + int (*xIntegrity)(sqlite3_vtab *pVTab, const char *zSchema, + const char *zTabName, int mFlags, char **pzErr); }; /* @@ -7704,7 +7837,7 @@ SQLITE_API int sqlite3_blob_reopen(sqlite3_blob *, sqlite3_int64); ** code is returned and the transaction rolled back. ** ** Calling this function with an argument that is not a NULL pointer or an -** open blob handle results in undefined behaviour. ^Calling this routine +** open blob handle results in undefined behavior. ^Calling this routine ** with a null pointer (such as would be returned by a failed call to ** [sqlite3_blob_open()]) is a harmless no-op. ^Otherwise, if this function ** is passed a valid open blob handle, the values returned by the @@ -7931,9 +8064,11 @@ SQLITE_API int sqlite3_vfs_unregister(sqlite3_vfs*); ** ** ^(Some systems (for example, Windows 95) do not support the operation ** implemented by sqlite3_mutex_try(). On those systems, sqlite3_mutex_try() -** will always return SQLITE_BUSY. The SQLite core only ever uses -** sqlite3_mutex_try() as an optimization so this is acceptable -** behavior.)^ +** will always return SQLITE_BUSY. In most cases the SQLite core only uses +** sqlite3_mutex_try() as an optimization, so this is acceptable +** behavior. The exceptions are unix builds that set the +** SQLITE_ENABLE_SETLK_TIMEOUT build option. In that case a working +** sqlite3_mutex_try() is required.)^ ** ** ^The sqlite3_mutex_leave() routine exits a mutex that was ** previously entered by the same thread. The behavior @@ -8184,6 +8319,7 @@ SQLITE_API int sqlite3_test_control(int op, ...); #define SQLITE_TESTCTRL_PRNG_SAVE 5 #define SQLITE_TESTCTRL_PRNG_RESTORE 6 #define SQLITE_TESTCTRL_PRNG_RESET 7 /* NOT USED */ +#define SQLITE_TESTCTRL_FK_NO_ACTION 7 #define SQLITE_TESTCTRL_BITVEC_TEST 8 #define SQLITE_TESTCTRL_FAULT_INSTALL 9 #define SQLITE_TESTCTRL_BENIGN_MALLOC_HOOKS 10 @@ -8191,6 +8327,7 @@ SQLITE_API int sqlite3_test_control(int op, ...); #define SQLITE_TESTCTRL_ASSERT 12 #define SQLITE_TESTCTRL_ALWAYS 13 #define SQLITE_TESTCTRL_RESERVE 14 /* NOT USED */ +#define SQLITE_TESTCTRL_JSON_SELFCHECK 14 #define SQLITE_TESTCTRL_OPTIMIZATIONS 15 #define SQLITE_TESTCTRL_ISKEYWORD 16 /* NOT USED */ #define SQLITE_TESTCTRL_SCRATCHMALLOC 17 /* NOT USED */ @@ -8226,7 +8363,7 @@ SQLITE_API int sqlite3_test_control(int op, ...); ** The sqlite3_keyword_count() interface returns the number of distinct ** keywords understood by SQLite. ** -** The sqlite3_keyword_name(N,Z,L) interface finds the N-th keyword and +** The sqlite3_keyword_name(N,Z,L) interface finds the 0-based N-th keyword and ** makes *Z point to that keyword expressed as UTF8 and writes the number ** of bytes in the keyword into *L. The string that *Z points to is not ** zero-terminated. The sqlite3_keyword_name(N,Z,L) routine returns @@ -9245,8 +9382,8 @@ SQLITE_API int sqlite3_backup_pagecount(sqlite3_backup *p); ** blocked connection already has a registered unlock-notify callback, ** then the new callback replaces the old.)^ ^If sqlite3_unlock_notify() is ** called with a NULL pointer as its second argument, then any existing -** unlock-notify callback is cancelled. ^The blocked connections -** unlock-notify callback may also be cancelled by closing the blocked +** unlock-notify callback is canceled. ^The blocked connections +** unlock-notify callback may also be canceled by closing the blocked ** connection using [sqlite3_close()]. ** ** The unlock-notify callback is not reentrant. If an application invokes @@ -9805,24 +9942,45 @@ SQLITE_API const char *sqlite3_vtab_collation(sqlite3_index_info*,int); **
  • ** ^(If the sqlite3_vtab_distinct() interface returns 2, that means ** that the query planner does not need the rows returned in any particular -** order, as long as rows with the same values in all "aOrderBy" columns -** are adjacent.)^ ^(Furthermore, only a single row for each particular -** combination of values in the columns identified by the "aOrderBy" field -** needs to be returned.)^ ^It is always ok for two or more rows with the same -** values in all "aOrderBy" columns to be returned, as long as all such rows -** are adjacent. ^The virtual table may, if it chooses, omit extra rows -** that have the same value for all columns identified by "aOrderBy". -** ^However omitting the extra rows is optional. +** order, as long as rows with the same values in all columns identified +** by "aOrderBy" are adjacent.)^ ^(Furthermore, when two or more rows +** contain the same values for all columns identified by "colUsed", all but +** one such row may optionally be omitted from the result.)^ +** The virtual table is not required to omit rows that are duplicates +** over the "colUsed" columns, but if the virtual table can do that without +** too much extra effort, it could potentially help the query to run faster. ** This mode is used for a DISTINCT query. **

  • -** ^(If the sqlite3_vtab_distinct() interface returns 3, that means -** that the query planner needs only distinct rows but it does need the -** rows to be sorted.)^ ^The virtual table implementation is free to omit -** rows that are identical in all aOrderBy columns, if it wants to, but -** it is not required to omit any rows. This mode is used for queries +** ^(If the sqlite3_vtab_distinct() interface returns 3, that means the +** virtual table must return rows in the order defined by "aOrderBy" as +** if the sqlite3_vtab_distinct() interface had returned 0. However if +** two or more rows in the result have the same values for all columns +** identified by "colUsed", then all but one such row may optionally be +** omitted.)^ Like when the return value is 2, the virtual table +** is not required to omit rows that are duplicates over the "colUsed" +** columns, but if the virtual table can do that without +** too much extra effort, it could potentially help the query to run faster. +** This mode is used for queries ** that have both DISTINCT and ORDER BY clauses. ** ** +**

    The following table summarizes the conditions under which the +** virtual table is allowed to set the "orderByConsumed" flag based on +** the value returned by sqlite3_vtab_distinct(). This table is a +** restatement of the previous four paragraphs: +** +** +** +**
    sqlite3_vtab_distinct() return value +** Rows are returned in aOrderBy order +** Rows with the same value in all aOrderBy columns are adjacent +** Duplicates over all colUsed columns may be omitted +**
    0yesyesno +**
    1noyesno +**
    2noyesyes +**
    3yesyesyes +**
    +** ** ^For the purposes of comparing virtual table output values to see if the ** values are same value for sorting purposes, two NULL values are considered ** to be the same. In other words, the comparison operator is "IS" @@ -10549,6 +10707,13 @@ SQLITE_API SQLITE_EXPERIMENTAL int sqlite3_snapshot_recover(sqlite3 *db, const c ** SQLITE_SERIALIZE_NOCOPY bit is set but no contiguous copy ** of the database exists. ** +** After the call, if the SQLITE_SERIALIZE_NOCOPY bit had been set, +** the returned buffer content will remain accessible and unchanged +** until either the next write operation on the connection or when +** the connection is closed, and applications must not modify the +** buffer. If the bit had been clear, the returned buffer will not +** be accessed by SQLite after the call. +** ** A call to sqlite3_serialize(D,S,P,F) might return NULL even if the ** SQLITE_SERIALIZE_NOCOPY bit is omitted from argument F if a memory ** allocation error occurs. @@ -10597,6 +10762,9 @@ SQLITE_API unsigned char *sqlite3_serialize( ** SQLite will try to increase the buffer size using sqlite3_realloc64() ** if writes on the database cause it to grow larger than M bytes. ** +** Applications must not modify the buffer P or invalidate it before +** the database connection D is closed. +** ** The sqlite3_deserialize() interface will fail with SQLITE_BUSY if the ** database is currently in a read transaction or is involved in a backup ** operation. @@ -10605,6 +10773,13 @@ SQLITE_API unsigned char *sqlite3_serialize( ** S argument to sqlite3_deserialize(D,S,P,N,M,F) is "temp" then the ** function returns SQLITE_ERROR. ** +** The deserialized database should not be in [WAL mode]. If the database +** is in WAL mode, then any attempt to use the database file will result +** in an [SQLITE_CANTOPEN] error. The application can set the +** [file format version numbers] (bytes 18 and 19) of the input database P +** to 0x01 prior to invoking sqlite3_deserialize(D,S,P,N,M,F) to force the +** database file into rollback mode and work around this limitation. +** ** If sqlite3_deserialize(D,S,P,N,M,F) fails for any reason and if the ** SQLITE_DESERIALIZE_FREEONCLOSE bit is set in argument F, then ** [sqlite3_free()] is invoked on argument P prior to returning. @@ -11677,6 +11852,18 @@ SQLITE_API int sqlite3changeset_concat( ); +/* +** CAPI3REF: Upgrade the Schema of a Changeset/Patchset +*/ +SQLITE_API int sqlite3changeset_upgrade( + sqlite3 *db, + const char *zDb, + int nIn, const void *pIn, /* Input changeset */ + int *pnOut, void **ppOut /* OUT: Inverse of input */ +); + + + /* ** CAPI3REF: Changegroup Handle ** @@ -11723,6 +11910,38 @@ typedef struct sqlite3_changegroup sqlite3_changegroup; */ SQLITE_API int sqlite3changegroup_new(sqlite3_changegroup **pp); +/* +** CAPI3REF: Add a Schema to a Changegroup +** METHOD: sqlite3_changegroup_schema +** +** This method may be used to optionally enforce the rule that the changesets +** added to the changegroup handle must match the schema of database zDb +** ("main", "temp", or the name of an attached database). If +** sqlite3changegroup_add() is called to add a changeset that is not compatible +** with the configured schema, SQLITE_SCHEMA is returned and the changegroup +** object is left in an undefined state. +** +** A changeset schema is considered compatible with the database schema in +** the same way as for sqlite3changeset_apply(). Specifically, for each +** table in the changeset, there exists a database table with: +** +**

      +**
    • The name identified by the changeset, and +**
    • at least as many columns as recorded in the changeset, and +**
    • the primary key columns in the same position as recorded in +** the changeset. +**
    +** +** The output of the changegroup object always has the same schema as the +** database nominated using this function. In cases where changesets passed +** to sqlite3changegroup_add() have fewer columns than the corresponding table +** in the database schema, these are filled in using the default column +** values from the database schema. This makes it possible to combined +** changesets that have different numbers of columns for a single table +** within a changegroup, provided that they are otherwise compatible. +*/ +SQLITE_API int sqlite3changegroup_schema(sqlite3_changegroup*, sqlite3*, const char *zDb); + /* ** CAPI3REF: Add A Changeset To A Changegroup ** METHOD: sqlite3_changegroup @@ -11791,16 +12010,45 @@ SQLITE_API int sqlite3changegroup_new(sqlite3_changegroup **pp); ** If the new changeset contains changes to a table that is already present ** in the changegroup, then the number of columns and the position of the ** primary key columns for the table must be consistent. If this is not the -** case, this function fails with SQLITE_SCHEMA. If the input changeset -** appears to be corrupt and the corruption is detected, SQLITE_CORRUPT is -** returned. Or, if an out-of-memory condition occurs during processing, this -** function returns SQLITE_NOMEM. In all cases, if an error occurs the state -** of the final contents of the changegroup is undefined. +** case, this function fails with SQLITE_SCHEMA. Except, if the changegroup +** object has been configured with a database schema using the +** sqlite3changegroup_schema() API, then it is possible to combine changesets +** with different numbers of columns for a single table, provided that +** they are otherwise compatible. +** +** If the input changeset appears to be corrupt and the corruption is +** detected, SQLITE_CORRUPT is returned. Or, if an out-of-memory condition +** occurs during processing, this function returns SQLITE_NOMEM. ** -** If no error occurs, SQLITE_OK is returned. +** In all cases, if an error occurs the state of the final contents of the +** changegroup is undefined. If no error occurs, SQLITE_OK is returned. */ SQLITE_API int sqlite3changegroup_add(sqlite3_changegroup*, int nData, void *pData); +/* +** CAPI3REF: Add A Single Change To A Changegroup +** METHOD: sqlite3_changegroup +** +** This function adds the single change currently indicated by the iterator +** passed as the second argument to the changegroup object. The rules for +** adding the change are just as described for [sqlite3changegroup_add()]. +** +** If the change is successfully added to the changegroup, SQLITE_OK is +** returned. Otherwise, an SQLite error code is returned. +** +** The iterator must point to a valid entry when this function is called. +** If it does not, SQLITE_ERROR is returned and no change is added to the +** changegroup. Additionally, the iterator must not have been opened with +** the SQLITE_CHANGESETAPPLY_INVERT flag. In this case SQLITE_ERROR is also +** returned. +*/ +SQLITE_API int sqlite3changegroup_add_change( + sqlite3_changegroup*, + sqlite3_changeset_iter* +); + + + /* ** CAPI3REF: Obtain A Composite Changeset From A Changegroup ** METHOD: sqlite3_changegroup @@ -12062,10 +12310,17 @@ SQLITE_API int sqlite3changeset_apply_v2( **
  • an insert change if all fields of the conflicting row match ** the row being inserted. ** +** +**
    SQLITE_CHANGESETAPPLY_FKNOACTION
    +** If this flag it set, then all foreign key constraints in the target +** database behave as if they were declared with "ON UPDATE NO ACTION ON +** DELETE NO ACTION", even if they are actually CASCADE, RESTRICT, SET NULL +** or SET DEFAULT. */ #define SQLITE_CHANGESETAPPLY_NOSAVEPOINT 0x0001 #define SQLITE_CHANGESETAPPLY_INVERT 0x0002 #define SQLITE_CHANGESETAPPLY_IGNORENOOP 0x0004 +#define SQLITE_CHANGESETAPPLY_FKNOACTION 0x0008 /* ** CAPI3REF: Constants Passed To The Conflict Handler @@ -12598,8 +12853,8 @@ struct Fts5PhraseIter { ** EXTENSION API FUNCTIONS ** ** xUserData(pFts): -** Return a copy of the context pointer the extension function was -** registered with. +** Return a copy of the pUserData pointer passed to the xCreateFunction() +** API when the extension function was registered. ** ** xColumnTotalSize(pFts, iCol, pnToken): ** If parameter iCol is less than zero, set output variable *pnToken @@ -12631,8 +12886,11 @@ struct Fts5PhraseIter { ** created with the "columnsize=0" option. ** ** xColumnText: -** This function attempts to retrieve the text of column iCol of the -** current document. If successful, (*pz) is set to point to a buffer +** If parameter iCol is less than zero, or greater than or equal to the +** number of columns in the table, SQLITE_RANGE is returned. +** +** Otherwise, this function attempts to retrieve the text of column iCol of +** the current document. If successful, (*pz) is set to point to a buffer ** containing the text in utf-8 encoding, (*pn) is set to the size in bytes ** (not characters) of the buffer and SQLITE_OK is returned. Otherwise, ** if an error occurs, an SQLite error code is returned and the final values @@ -12642,8 +12900,10 @@ struct Fts5PhraseIter { ** Returns the number of phrases in the current query expression. ** ** xPhraseSize: -** Returns the number of tokens in phrase iPhrase of the query. Phrases -** are numbered starting from zero. +** If parameter iCol is less than zero, or greater than or equal to the +** number of phrases in the current query, as returned by xPhraseCount, +** 0 is returned. Otherwise, this function returns the number of tokens in +** phrase iPhrase of the query. Phrases are numbered starting from zero. ** ** xInstCount: ** Set *pnInst to the total number of occurrences of all phrases within @@ -12659,12 +12919,13 @@ struct Fts5PhraseIter { ** Query for the details of phrase match iIdx within the current row. ** Phrase matches are numbered starting from zero, so the iIdx argument ** should be greater than or equal to zero and smaller than the value -** output by xInstCount(). +** output by xInstCount(). If iIdx is less than zero or greater than +** or equal to the value returned by xInstCount(), SQLITE_RANGE is returned. ** -** Usually, output parameter *piPhrase is set to the phrase number, *piCol +** Otherwise, output parameter *piPhrase is set to the phrase number, *piCol ** to the column in which it occurs and *piOff the token offset of the -** first token of the phrase. Returns SQLITE_OK if successful, or an error -** code (i.e. SQLITE_NOMEM) if an error occurs. +** first token of the phrase. SQLITE_OK is returned if successful, or an +** error code (i.e. SQLITE_NOMEM) if an error occurs. ** ** This API can be quite slow if used with an FTS5 table created with the ** "detail=none" or "detail=column" option. @@ -12690,6 +12951,10 @@ struct Fts5PhraseIter { ** Invoking Api.xUserData() returns a copy of the pointer passed as ** the third argument to pUserData. ** +** If parameter iPhrase is less than zero, or greater than or equal to +** the number of phrases in the query, as returned by xPhraseCount(), +** this function returns SQLITE_RANGE. +** ** If the callback function returns any value other than SQLITE_OK, the ** query is abandoned and the xQueryPhrase function returns immediately. ** If the returned value is SQLITE_DONE, xQueryPhrase returns SQLITE_OK. @@ -12804,9 +13069,42 @@ struct Fts5PhraseIter { ** ** xPhraseNextColumn() ** See xPhraseFirstColumn above. +** +** xQueryToken(pFts5, iPhrase, iToken, ppToken, pnToken) +** This is used to access token iToken of phrase iPhrase of the current +** query. Before returning, output parameter *ppToken is set to point +** to a buffer containing the requested token, and *pnToken to the +** size of this buffer in bytes. +** +** If iPhrase or iToken are less than zero, or if iPhrase is greater than +** or equal to the number of phrases in the query as reported by +** xPhraseCount(), or if iToken is equal to or greater than the number of +** tokens in the phrase, SQLITE_RANGE is returned and *ppToken and *pnToken + are both zeroed. +** +** The output text is not a copy of the query text that specified the +** token. It is the output of the tokenizer module. For tokendata=1 +** tables, this includes any embedded 0x00 and trailing data. +** +** xInstToken(pFts5, iIdx, iToken, ppToken, pnToken) +** This is used to access token iToken of phrase hit iIdx within the +** current row. If iIdx is less than zero or greater than or equal to the +** value returned by xInstCount(), SQLITE_RANGE is returned. Otherwise, +** output variable (*ppToken) is set to point to a buffer containing the +** matching document token, and (*pnToken) to the size of that buffer in +** bytes. This API is not available if the specified token matches a +** prefix query term. In that case both output variables are always set +** to 0. +** +** The output text is not a copy of the document text that was tokenized. +** It is the output of the tokenizer module. For tokendata=1 tables, this +** includes any embedded 0x00 and trailing data. +** +** This API can be quite slow if used with an FTS5 table created with the +** "detail=none" or "detail=column" option. */ struct Fts5ExtensionApi { - int iVersion; /* Currently always set to 2 */ + int iVersion; /* Currently always set to 3 */ void *(*xUserData)(Fts5Context*); @@ -12841,6 +13139,13 @@ struct Fts5ExtensionApi { int (*xPhraseFirstColumn)(Fts5Context*, int iPhrase, Fts5PhraseIter*, int*); void (*xPhraseNextColumn)(Fts5Context*, Fts5PhraseIter*, int *piCol); + + /* Below this point are iVersion>=3 only */ + int (*xQueryToken)(Fts5Context*, + int iPhrase, int iToken, + const char **ppToken, int *pnToken + ); + int (*xInstToken)(Fts5Context*, int iIdx, int iToken, const char**, int*); }; /* diff --git a/vendor/sqlite/sqlite3ext.h b/vendor/sqlite/sqlite3ext.h index 7116380992..ae0949baf7 100644 --- a/vendor/sqlite/sqlite3ext.h +++ b/vendor/sqlite/sqlite3ext.h @@ -363,6 +363,9 @@ struct sqlite3_api_routines { int (*is_interrupted)(sqlite3*); /* Version 3.43.0 and later */ int (*stmt_explain)(sqlite3_stmt*,int); + /* Version 3.44.0 and later */ + void *(*get_clientdata)(sqlite3*,const char*); + int (*set_clientdata)(sqlite3*, const char*, void*, void(*)(void*)); }; /* @@ -693,6 +696,9 @@ typedef int (*sqlite3_loadext_entry)( #define sqlite3_is_interrupted sqlite3_api->is_interrupted /* Version 3.43.0 and later */ #define sqlite3_stmt_explain sqlite3_api->stmt_explain +/* Version 3.44.0 and later */ +#define sqlite3_get_clientdata sqlite3_api->get_clientdata +#define sqlite3_set_clientdata sqlite3_api->set_clientdata #endif /* !defined(SQLITE_CORE) && !defined(SQLITE_OMIT_LOAD_EXTENSION) */ #if !defined(SQLITE_CORE) && !defined(SQLITE_OMIT_LOAD_EXTENSION) diff --git a/vendor/tinygettext/language.cpp b/vendor/tinygettext/language.cpp index d26a9aff1a..b8690eddc6 100644 --- a/vendor/tinygettext/language.cpp +++ b/vendor/tinygettext/language.cpp @@ -193,7 +193,7 @@ LanguageSpec languages[] = {{"aa", 0, 0, "Afar"}, {"my", 0, 0, "Burmese"}, {"my", "MM", 0, "Burmese (Myanmar)"}, {"nb", 0, 0, "Norwegian Bokmal"}, - {"nb", "NO", 0, "Norwegian Bokml (Norway)"}, + {"nb", "NO", 0, "Norwegian Bokmål (Norway)"}, {"ne", 0, 0, "Nepali"}, {"nl", 0, 0, "Dutch"}, {"nl", "BE", 0, "Dutch (Belgium)"}, @@ -296,7 +296,7 @@ resolve_language_alias(const std::string& name) // Aliases taken from /etc/locale.alias language_aliases["bokmal"] = "nb_NO.ISO-8859-1"; - language_aliases["bokml"] = "nb_NO.ISO-8859-1"; + language_aliases["bokmål"] = "nb_NO.ISO-8859-1"; language_aliases["catalan"] = "ca_ES.ISO-8859-1"; language_aliases["croatian"] = "hr_HR.ISO-8859-2"; language_aliases["czech"] = "cs_CZ.ISO-8859-2"; @@ -307,7 +307,7 @@ resolve_language_alias(const std::string& name) language_aliases["eesti"] = "et_EE.ISO-8859-1"; language_aliases["estonian"] = "et_EE.ISO-8859-1"; language_aliases["finnish"] = "fi_FI.ISO-8859-1"; - language_aliases["franais"] = "fr_FR.ISO-8859-1"; + language_aliases["français"] = "fr_FR.ISO-8859-1"; language_aliases["french"] = "fr_FR.ISO-8859-1"; language_aliases["galego"] = "gl_ES.ISO-8859-1"; language_aliases["galician"] = "gl_ES.ISO-8859-1"; diff --git a/vendor/unrar/arccmt.cpp b/vendor/unrar/arccmt.cpp index 8b7e498f4f..f23a7dd70a 100644 --- a/vendor/unrar/arccmt.cpp +++ b/vendor/unrar/arccmt.cpp @@ -1,6 +1,6 @@ static bool IsAnsiEscComment(const wchar *Data,size_t Size); -bool Archive::GetComment(Array *CmtData) +bool Archive::GetComment(std::wstring &CmtData) { if (!MainComment) return false; @@ -11,7 +11,7 @@ bool Archive::GetComment(Array *CmtData) } -bool Archive::DoGetComment(Array *CmtData) +bool Archive::DoGetComment(std::wstring &CmtData) { #ifndef SFX_MODULE uint CmtLength; @@ -101,10 +101,8 @@ bool Archive::DoGetComment(Array *CmtData) // 4x memory for OEM to UTF-8 output here. OemToCharBuffA((char *)UnpData,(char *)UnpData,(DWORD)UnpDataSize); #endif - CmtData->Alloc(UnpDataSize+1); - memset(CmtData->Addr(0),0,CmtData->Size()*sizeof(wchar)); - CharToWide((char *)UnpData,CmtData->Addr(0),CmtData->Size()); - CmtData->Alloc(wcslen(CmtData->Addr(0))); + std::string UnpStr((char*)UnpData,UnpDataSize); + CharToWide(UnpStr,CmtData); } } } @@ -112,12 +110,12 @@ bool Archive::DoGetComment(Array *CmtData) { if (CmtLength==0) return false; - Array CmtRaw(CmtLength); - int ReadSize=Read(&CmtRaw[0],CmtLength); + std::vector CmtRaw(CmtLength); + int ReadSize=Read(CmtRaw.data(),CmtLength); if (ReadSize>=0 && (uint)ReadSize *CmtData) uiMsg(UIERROR_CMTBROKEN,FileName); return false; } - CmtData->Alloc(CmtLength+1); - CmtRaw.Push(0); +// CmtData.resize(CmtLength+1); + CmtRaw.push_back(0); #ifdef _WIN_ALL // If we ever decide to extend it to Android, we'll need to alloc // 4x memory for OEM to UTF-8 output here. - OemToCharA((char *)&CmtRaw[0],(char *)&CmtRaw[0]); + OemToCharA((char *)CmtRaw.data(),(char *)CmtRaw.data()); #endif - CharToWide((char *)&CmtRaw[0],CmtData->Addr(0),CmtData->Size()); - CmtData->Alloc(wcslen(CmtData->Addr(0))); + CharToWide((const char *)CmtRaw.data(),CmtData); +// CmtData->resize(wcslen(CmtData->data())); } #endif - return CmtData->Size() > 0; + return CmtData.size() > 0; } -bool Archive::ReadCommentData(Array *CmtData) +bool Archive::ReadCommentData(std::wstring &CmtData) { - Array CmtRaw; + std::vector CmtRaw; if (!ReadSubData(&CmtRaw,NULL,false)) return false; - size_t CmtSize=CmtRaw.Size(); - CmtRaw.Push(0); - CmtData->Alloc(CmtSize+1); + size_t CmtSize=CmtRaw.size(); + CmtRaw.push_back(0); +// CmtData->resize(CmtSize+1); if (Format==RARFMT50) - UtfToWide((char *)&CmtRaw[0],CmtData->Addr(0),CmtData->Size()); + UtfToWide((char *)CmtRaw.data(),CmtData); else if ((SubHead.SubFlags & SUBHEAD_FLAGS_CMT_UNICODE)!=0) { - RawToWide(&CmtRaw[0],CmtData->Addr(0),CmtSize/2); - (*CmtData)[CmtSize/2]=0; - + CmtData=RawToWide(CmtRaw); } else { - CharToWide((char *)&CmtRaw[0],CmtData->Addr(0),CmtData->Size()); + CharToWide((const char *)CmtRaw.data(),CmtData); } - CmtData->Alloc(wcslen(CmtData->Addr(0))); // Set buffer size to actual comment length. +// CmtData->resize(wcslen(CmtData->data())); // Set buffer size to actual comment length. return true; } @@ -170,15 +166,16 @@ void Archive::ViewComment() { if (Cmd->DisableComment) return; - Array CmtBuf; - if (GetComment(&CmtBuf)) // In GUI too, so "Test" command detects broken comments. + std::wstring CmtBuf; + if (GetComment(CmtBuf)) // In GUI too, so "Test" command detects broken comments. { - size_t CmtSize=CmtBuf.Size(); - wchar *ChPtr=wcschr(&CmtBuf[0],0x1A); - if (ChPtr!=NULL) - CmtSize=ChPtr-&CmtBuf[0]; - mprintf(L"\n"); - OutComment(&CmtBuf[0],CmtSize); + size_t CmtSize=CmtBuf.size(); + auto EndPos=CmtBuf.find(0x1A); + if (EndPos!=std::wstring::npos) + CmtSize=EndPos; + mprintf(St(MArcComment)); + mprintf(L":\n"); + OutComment(CmtBuf); } } diff --git a/vendor/unrar/archive.cpp b/vendor/unrar/archive.cpp index 25f0c3b79d..c2293de7cc 100644 --- a/vendor/unrar/archive.cpp +++ b/vendor/unrar/archive.cpp @@ -39,7 +39,6 @@ Archive::Archive(CommandData *InitCmd) VolWrite=0; AddingFilesSize=0; AddingHeadersSize=0; - *FirstVolumeName=0; Splitting=false; NewArchive=false; @@ -74,7 +73,7 @@ void Archive::CheckArc(bool EnableBroken) #if !defined(SFX_MODULE) -void Archive::CheckOpen(const wchar *Name) +void Archive::CheckOpen(const std::wstring &Name) { TOpen(Name); CheckArc(false); @@ -82,7 +81,7 @@ void Archive::CheckOpen(const wchar *Name) #endif -bool Archive::WCheckOpen(const wchar *Name) +bool Archive::WCheckOpen(const std::wstring &Name) { if (!WOpen(Name)) return false; @@ -148,9 +147,9 @@ bool Archive::IsArchive(bool EnableBroken) } else { - Array Buffer(MAXSFXSIZE); + std::vector Buffer(MAXSFXSIZE); long CurPos=(long)Tell(); - int ReadSize=Read(&Buffer[0],Buffer.Size()-16); + int ReadSize=Read(Buffer.data(),Buffer.size()-16); for (int I=0;I0x10000000000ULL) + return 0; + uint64 Pow2=0x20000; // Power of 2 dictionary size. + for (;2*Pow2<=Size;Pow2*=2) + Flags+=FCI_DICT_BIT0; + if (Size==Pow2) + return Size; // If 'Size' is the power of 2, return it as is. + + // Get the number of Pow2/32 to add to Pow2 for nearest value not exceeding 'Size'. + uint64 Fraction=(Size-Pow2)/(Pow2/32); + Flags+=(uint)Fraction*FCI_DICT_FRACT0; + return Pow2+Fraction*(Pow2/32); +} diff --git a/vendor/unrar/archive.hpp b/vendor/unrar/archive.hpp index c0019aef57..58bdafaa10 100644 --- a/vendor/unrar/archive.hpp +++ b/vendor/unrar/archive.hpp @@ -27,7 +27,7 @@ class Archive:public File { private: void UpdateLatestTime(FileHeader *CurBlock); - void ConvertNameCase(wchar *Name); + void ConvertNameCase(std::wstring &Name); void ConvertFileHeader(FileHeader *hd); size_t ReadHeader14(); size_t ReadHeader15(); @@ -36,9 +36,9 @@ class Archive:public File void RequestArcPassword(RarCheckPassword *SelPwd); void UnexpEndArcMsg(); void BrokenHeaderMsg(); - void UnkEncVerMsg(const wchar *Name,const wchar *Info); - bool DoGetComment(Array *CmtData); - bool ReadCommentData(Array *CmtData); + void UnkEncVerMsg(const std::wstring &Name,const std::wstring &Info); + bool DoGetComment(std::wstring &CmtData); + bool ReadCommentData(std::wstring &CmtData); #if !defined(RAR_NOCRYPT) CryptData HeadersCrypt; @@ -67,9 +67,9 @@ class Archive:public File size_t SearchRR(); size_t ReadHeader(); void CheckArc(bool EnableBroken); - void CheckOpen(const wchar *Name); - bool WCheckOpen(const wchar *Name); - bool GetComment(Array *CmtData); + void CheckOpen(const std::wstring &Name); + bool WCheckOpen(const std::wstring &Name); + bool GetComment(std::wstring &CmtData); void ViewComment(); void SetLatestTime(RarTime *NewTime); void SeekToNext(); @@ -79,23 +79,25 @@ class Archive:public File void VolSubtractHeaderSize(size_t SubSize); uint FullHeaderSize(size_t Size); int64 GetStartPos(); - void AddSubData(byte *SrcData,uint64 DataSize,File *SrcFile, + void AddSubData(const byte *SrcData,uint64 DataSize,File *SrcFile, const wchar *Name,uint Flags); - bool ReadSubData(Array *UnpData,File *DestFile,bool TestMode); + bool ReadSubData(std::vector *UnpData,File *DestFile,bool TestMode); HEADER_TYPE GetHeaderType() {return CurHeaderType;} CommandData* GetCommandData() {return Cmd;} void SetSilentOpen(bool Mode) {SilentOpen=Mode;} -#if 0 - void GetRecoveryInfo(bool Required,int64 *Size,int *Percent); -#endif #ifdef USE_QOPEN - bool Open(const wchar *Name,uint Mode=FMF_READ); - int Read(void *Data,size_t Size); - void Seek(int64 Offset,int Method); - int64 Tell(); + bool Open(const std::wstring &Name,uint Mode=FMF_READ) override; + int Read(void *Data,size_t Size) override; + void Seek(int64 Offset,int Method) override; + int64 Tell() override; void QOpenUnload() {QOpen.Unload();} void SetProhibitQOpen(bool Mode) {ProhibitQOpen=Mode;} #endif + static uint64 GetWinSize(uint64 Size,uint &Flags); + + // Needed to see wstring based Open from File. Otherwise compiler finds + // Open in Archive and doesn't check the base class overloads. + using File::Open; BaseBlock ShortBlock; MarkHeader MarkHead; @@ -135,12 +137,16 @@ class Archive:public File uint VolNumber; int64 VolWrite; + + // Total size of files adding to archive. Might also include the size of + // files repacked in solid archive. uint64 AddingFilesSize; + uint64 AddingHeadersSize; bool NewArchive; - wchar FirstVolumeName[NM]; + std::wstring FirstVolumeName; }; diff --git a/vendor/unrar/arcread.cpp b/vendor/unrar/arcread.cpp index 6b7dd98ee6..825da72663 100644 --- a/vendor/unrar/arcread.cpp +++ b/vendor/unrar/arcread.cpp @@ -119,10 +119,10 @@ void Archive::BrokenHeaderMsg() } -void Archive::UnkEncVerMsg(const wchar *Name,const wchar *Info) +void Archive::UnkEncVerMsg(const std::wstring &Name,const std::wstring &Info) { uiMsg(UIERROR_UNKNOWNENCMETHOD,FileName,Name,Info); - ErrHandler.SetErrorCode(RARX_WARNING); + ErrHandler.SetErrorCode(RARX_FATAL); } @@ -222,7 +222,7 @@ size_t Archive::ReadHeader15() { case HEAD_MAIN: MainHead.Reset(); - *(BaseBlock *)&MainHead=ShortBlock; + MainHead.SetBaseBlock(ShortBlock); MainHead.HighPosAV=Raw.Get2(); MainHead.PosAV=Raw.Get4(); @@ -248,7 +248,7 @@ size_t Archive::ReadHeader15() FileHeader *hd=FileBlock ? &FileHead:&SubHead; hd->Reset(); - *(BaseBlock *)hd=ShortBlock; + hd->SetBaseBlock(ShortBlock); hd->SplitBefore=(hd->Flags & LHD_SPLIT_BEFORE)!=0; hd->SplitAfter=(hd->Flags & LHD_SPLIT_AFTER)!=0; @@ -307,7 +307,7 @@ size_t Archive::ReadHeader15() if (hd->HostOS==HOST_UNIX && (hd->FileAttr & 0xF000)==0xA000) { hd->RedirType=FSREDIR_UNIXSYMLINK; - *hd->RedirName=0; + hd->RedirName.clear(); } hd->Inherited=!FileBlock && (hd->SubFlags & SUBHEAD_FLAGS_INHERITED)!=0; @@ -334,27 +334,26 @@ size_t Archive::ReadHeader15() if (hd->UnknownUnpSize) hd->UnpSize=INT64NDF; - char FileName[NM*4]; - size_t ReadNameSize=Min(NameSize,ASIZE(FileName)-1); - Raw.GetB((byte *)FileName,ReadNameSize); - FileName[ReadNameSize]=0; + size_t ReadNameSize=Min(NameSize,MAXPATHSIZE); + std::string FileName(ReadNameSize,0); + Raw.GetB((byte *)&FileName[0],ReadNameSize); if (FileBlock) { - *hd->FileName=0; + hd->FileName.clear(); if ((hd->Flags & LHD_UNICODE)!=0) { EncodeFileName NameCoder; - size_t Length=strlen(FileName); + size_t Length=strlen(FileName.data()); Length++; if (ReadNameSize>Length) - NameCoder.Decode(FileName,ReadNameSize,(byte *)FileName+Length, - ReadNameSize-Length,hd->FileName, - ASIZE(hd->FileName)); + NameCoder.Decode(FileName.data(),ReadNameSize, + (byte *)&FileName[Length], + ReadNameSize-Length,hd->FileName); } - if (*hd->FileName==0) - ArcCharToWide(FileName,hd->FileName,ASIZE(hd->FileName),ACTW_OEM); + if (hd->FileName.empty()) + ArcCharToWide(FileName.data(),hd->FileName,ACTW_OEM); #ifndef SFX_MODULE ConvertNameCase(hd->FileName); @@ -363,7 +362,7 @@ size_t Archive::ReadHeader15() } else { - CharToWide(FileName,hd->FileName,ASIZE(hd->FileName)); + CharToWide(FileName.data(),hd->FileName); // Calculate the size of optional data. int DataSize=int(hd->HeadSize-NameSize-SIZEOF_FILEHEAD3); @@ -374,14 +373,15 @@ size_t Archive::ReadHeader15() { // Here we read optional additional fields for subheaders. // They are stored after the file name and before salt. - hd->SubData.Alloc(DataSize); - Raw.GetB(&hd->SubData[0],DataSize); + hd->SubData.resize(DataSize); + Raw.GetB(hd->SubData.data(),DataSize); } if (hd->CmpName(SUBHEAD_TYPE_CMT)) MainComment=true; } + if ((hd->Flags & LHD_SALT)!=0) Raw.GetB(hd->Salt,SIZE_SALT30); hd->mtime.SetDos(FileTime); @@ -424,7 +424,7 @@ size_t Archive::ReadHeader15() NextBlockPos=SafeAdd(NextBlockPos,hd->PackSize,0); bool CRCProcessedOnly=hd->CommentInHeader; - ushort HeaderCRC=Raw.GetCRC15(CRCProcessedOnly); + uint HeaderCRC=Raw.GetCRC15(CRCProcessedOnly); if (hd->HeadCRC!=HeaderCRC) { BrokenHeader=true; @@ -441,7 +441,7 @@ size_t Archive::ReadHeader15() } break; case HEAD_ENDARC: - *(BaseBlock *)&EndArcHead=ShortBlock; + EndArcHead.SetBaseBlock(ShortBlock); EndArcHead.NextVolume=(EndArcHead.Flags & EARC_NEXT_VOLUME)!=0; EndArcHead.DataCRC=(EndArcHead.Flags & EARC_DATACRC)!=0; EndArcHead.RevSpace=(EndArcHead.Flags & EARC_REVSPACE)!=0; @@ -453,14 +453,14 @@ size_t Archive::ReadHeader15() break; #ifndef SFX_MODULE case HEAD3_CMT: - *(BaseBlock *)&CommHead=ShortBlock; + CommHead.SetBaseBlock(ShortBlock); CommHead.UnpSize=Raw.Get2(); CommHead.UnpVer=Raw.Get1(); CommHead.Method=Raw.Get1(); CommHead.CommCRC=Raw.Get2(); break; case HEAD3_PROTECT: - *(BaseBlock *)&ProtectHead=ShortBlock; + ProtectHead.SetBaseBlock(ShortBlock); ProtectHead.DataSize=Raw.Get4(); ProtectHead.Version=Raw.Get1(); ProtectHead.RecSectors=Raw.Get2(); @@ -469,7 +469,7 @@ size_t Archive::ReadHeader15() NextBlockPos+=ProtectHead.DataSize; break; case HEAD3_OLDSERVICE: // RAR 2.9 and earlier. - *(BaseBlock *)&SubBlockHead=ShortBlock; + SubBlockHead.SetBaseBlock(ShortBlock); SubBlockHead.DataSize=Raw.Get4(); NextBlockPos+=SubBlockHead.DataSize; SubBlockHead.SubType=Raw.Get2(); @@ -490,10 +490,13 @@ size_t Archive::ReadHeader15() StreamHead.Method=Raw.Get1(); StreamHead.StreamCRC=Raw.Get4(); StreamHead.StreamNameSize=Raw.Get2(); - if (StreamHead.StreamNameSize>=ASIZE(StreamHead.StreamName)) - StreamHead.StreamNameSize=ASIZE(StreamHead.StreamName)-1; - Raw.GetB(StreamHead.StreamName,StreamHead.StreamNameSize); - StreamHead.StreamName[StreamHead.StreamNameSize]=0; + + const size_t MaxStreamName20=260; // Maximum allowed stream name in RAR 2.x format. + if (StreamHead.StreamNameSize>MaxStreamName20) + StreamHead.StreamNameSize=MaxStreamName20; + + StreamHead.StreamName.resize(StreamHead.StreamNameSize); + Raw.GetB(&StreamHead.StreamName[0],StreamHead.StreamNameSize); break; } break; @@ -504,7 +507,7 @@ size_t Archive::ReadHeader15() break; } - ushort HeaderCRC=Raw.GetCRC15(false); + uint HeaderCRC=Raw.GetCRC15(false); // Old AV header does not have header CRC properly set. // Old Unix owners header didn't include string fields into header size, @@ -584,10 +587,10 @@ size_t Archive::ReadHeader50() RequestArcPassword(CheckPwd.IsSet() ? &CheckPwd:NULL); byte PswCheck[SIZE_PSWCHECK]; - HeadersCrypt.SetCryptKeys(false,CRYPT_RAR50,&Cmd->Password,CryptHead.Salt,HeadersInitV,CryptHead.Lg2Count,NULL,PswCheck); + bool EncSet=HeadersCrypt.SetCryptKeys(false,CRYPT_RAR50,&Cmd->Password,CryptHead.Salt,HeadersInitV,CryptHead.Lg2Count,NULL,PswCheck); // Verify password validity. If header is damaged, we cannot rely on // password check value, because it can be damaged too. - if (CryptHead.UsePswCheck && !BrokenHeader && + if (EncSet && CryptHead.UsePswCheck && !BrokenHeader && memcmp(PswCheck,CryptHead.PswCheck,SIZE_PSWCHECK)!=0) { if (GlobalPassword) // For -p or Ctrl+P. @@ -646,7 +649,7 @@ size_t Archive::ReadHeader50() } int SizeToRead=int(BlockSize); - SizeToRead-=FirstReadSize-SizeBytes-4; // Adjust overread size bytes if any. + SizeToRead-=int(FirstReadSize-SizeBytes-4); // Adjust overread size bytes if any. uint HeaderSize=4+SizeBytes+(uint)BlockSize; if (SizeToRead<0 || HeaderSizeCRYPT_VERSION) { - wchar Info[20]; - swprintf(Info,ASIZE(Info),L"h%u",CryptVersion); - UnkEncVerMsg(FileName,Info); + UnkEncVerMsg(FileName,L"h" + std::to_wstring(CryptVersion)); + FailedHeaderDecryption=true; return 0; } uint EncFlags=(uint)Raw.GetV(); @@ -725,9 +727,8 @@ size_t Archive::ReadHeader50() CryptHead.Lg2Count=Raw.Get1(); if (CryptHead.Lg2Count>CRYPT5_KDF_LG2_COUNT_MAX) { - wchar Info[20]; - swprintf(Info,ASIZE(Info),L"hc%u",CryptHead.Lg2Count); - UnkEncVerMsg(FileName,Info); + UnkEncVerMsg(FileName,L"hc" + std::to_wstring(CryptHead.Lg2Count)); + FailedHeaderDecryption=true; return 0; } @@ -739,12 +740,8 @@ size_t Archive::ReadHeader50() byte csum[SIZE_PSWCHECK_CSUM]; Raw.GetB(csum,SIZE_PSWCHECK_CSUM); - sha256_context ctx; - sha256_init(&ctx); - sha256_process(&ctx, CryptHead.PswCheck, SIZE_PSWCHECK); - byte Digest[SHA256_DIGEST_SIZE]; - sha256_done(&ctx, Digest); + sha256_get(CryptHead.PswCheck, SIZE_PSWCHECK, Digest); CryptHead.UsePswCheck=memcmp(csum,Digest,SIZE_PSWCHECK_CSUM)==0; } @@ -754,7 +751,7 @@ size_t Archive::ReadHeader50() case HEAD_MAIN: { MainHead.Reset(); - *(BaseBlock *)&MainHead=ShortBlock; + MainHead.SetBaseBlock(ShortBlock); uint ArcFlags=(uint)Raw.GetV(); Volume=(ArcFlags & MHFL_VOLUME)!=0; @@ -832,9 +829,14 @@ size_t Archive::ReadHeader50() // we may need to use the compression algorithm 15 in the future, // but it was already used in RAR 1.5 and Unpack needs to distinguish // them. - hd->UnpVer=(CompInfo & 0x3f) + 50; - if (hd->UnpVer!=50) // Only 5.0 compression is known now. - hd->UnpVer=VER_UNKNOWN; + uint UnpVer=(CompInfo & 0x3f); + if (UnpVer==0) + hd->UnpVer=VER_PACK5; + else + if (UnpVer==1) + hd->UnpVer=VER_PACK7; + else + hd->UnpVer=VER_UNKNOWN; hd->HostOS=(byte)Raw.GetV(); size_t NameSize=(size_t)Raw.GetV(); @@ -852,14 +854,29 @@ size_t Archive::ReadHeader50() hd->SubBlock=(hd->Flags & HFL_CHILD)!=0; hd->Solid=FileBlock && (CompInfo & FCI_SOLID)!=0; hd->Dir=(hd->FileFlags & FHFL_DIRECTORY)!=0; - hd->WinSize=hd->Dir ? 0:size_t(0x20000)<<((CompInfo>>10)&0xf); + if (hd->Dir || UnpVer>1) + hd->WinSize=0; + else + { + hd->WinSize=0x20000ULL<<((CompInfo>>10)&(UnpVer==0 ? 0x0f:0x1f)); + if (UnpVer==1) + { + hd->WinSize+=hd->WinSize/32*((CompInfo>>15)&0x1f); + + // RAR7 header with RAR5 compression. Needed to append RAR7 files + // to RAR5 solid stream if new dictionary is larger than existing. + if ((CompInfo & FCI_RAR5_COMPAT)!=0) + hd->UnpVer=VER_PACK5; + if (hd->WinSize>UNPACK_MAX_DICT) + hd->UnpVer=VER_UNKNOWN; + } + } - char FileName[NM*4]; - size_t ReadNameSize=Min(NameSize,ASIZE(FileName)-1); - Raw.GetB((byte *)FileName,ReadNameSize); - FileName[ReadNameSize]=0; + size_t ReadNameSize=Min(NameSize,MAXPATHSIZE); + std::string FileName(ReadNameSize,0); + Raw.GetB((byte *)&FileName[0],ReadNameSize); - UtfToWide(FileName,hd->FileName,ASIZE(hd->FileName)); + UtfToWide(FileName.data(),hd->FileName); // Should do it before converting names, because extra fields can // affect name processing, like in case of NTFS streams. @@ -884,7 +901,7 @@ size_t Archive::ReadHeader50() break; case HEAD_ENDARC: { - *(BaseBlock *)&EndArcHead=ShortBlock; + EndArcHead.SetBaseBlock(ShortBlock); uint ArcFlags=(uint)Raw.GetV(); EndArcHead.NextVolume=(ArcFlags & EHFL_NEXTVOLUME)!=0; EndArcHead.StoreVolNumber=false; @@ -916,7 +933,7 @@ void Archive::RequestArcPassword(RarCheckPassword *CheckPwd) *PasswordA=0; if (Cmd->Callback(UCM_NEEDPASSWORD,Cmd->UserData,(LPARAM)PasswordA,ASIZE(PasswordA))==-1) *PasswordA=0; - GetWideName(PasswordA,NULL,PasswordW,ASIZE(PasswordW)); + CharToWide(PasswordA,PasswordW,ASIZE(PasswordW)); cleandata(PasswordA,sizeof(PasswordA)); } Cmd->Password.Set(PasswordW); @@ -991,19 +1008,14 @@ void Archive::ProcessExtra50(RawRead *Raw,size_t ExtraSize,const BaseBlock *bb) if ((Flags & MHEXTRA_METADATA_NAME)!=0) { uint64 NameSize=Raw->GetV(); - if (NameSize>0 && NameSize<0x10000) // Prevent excessive allocation. + if (NameSize>0 && NameSize NameU((size_t)NameSize); // UTF-8 name. + std::string NameU((size_t)NameSize,0); // UTF-8 name. Raw->GetB(&NameU[0],(size_t)NameSize); // If starts from 0, the name was longer than reserved space // when saving this extra field. if (NameU[0]!=0) - { - NameU.push_back(0); - std::vector NameW(NameU.size()*4); - UtfToWide(&NameU[0],&NameW[0],NameW.size()); - hd->OrigName.assign(&NameW[0]); - } + UtfToWide(&NameU[0],hd->OrigName); } } if ((Flags & MHEXTRA_METADATA_CTIME)!=0) @@ -1029,11 +1041,7 @@ void Archive::ProcessExtra50(RawRead *Raw,size_t ExtraSize,const BaseBlock *bb) FileHeader *hd=(FileHeader *)bb; uint EncVersion=(uint)Raw->GetV(); if (EncVersion>CRYPT_VERSION) - { - wchar Info[20]; - swprintf(Info,ASIZE(Info),L"x%u",EncVersion); - UnkEncVerMsg(hd->FileName,Info); - } + UnkEncVerMsg(hd->FileName,L"x" + std::to_wstring(EncVersion)); else { uint Flags=(uint)Raw->GetV(); @@ -1041,44 +1049,39 @@ void Archive::ProcessExtra50(RawRead *Raw,size_t ExtraSize,const BaseBlock *bb) hd->UseHashKey=(Flags & FHEXTRA_CRYPT_HASHMAC)!=0; hd->Lg2Count=Raw->Get1(); if (hd->Lg2Count>CRYPT5_KDF_LG2_COUNT_MAX) + UnkEncVerMsg(hd->FileName,L"xc" + std::to_wstring(hd->Lg2Count)); + else { - wchar Info[20]; - swprintf(Info,ASIZE(Info),L"xc%u",hd->Lg2Count); - UnkEncVerMsg(hd->FileName,Info); - } - Raw->GetB(hd->Salt,SIZE_SALT50); - Raw->GetB(hd->InitV,SIZE_INITV); - if (hd->UsePswCheck) - { - Raw->GetB(hd->PswCheck,SIZE_PSWCHECK); - - // It is important to know if password check data is valid. - // If it is damaged and header CRC32 fails to detect it, - // archiver would refuse to decompress a possibly valid file. - // Since we want to be sure distinguishing a wrong password - // or corrupt file data, we use 64-bit password check data - // and to control its validity we use 32 bits of password - // check data SHA-256 additionally to 32-bit header CRC32. - byte csum[SIZE_PSWCHECK_CSUM]; - Raw->GetB(csum,SIZE_PSWCHECK_CSUM); - - sha256_context ctx; - sha256_init(&ctx); - sha256_process(&ctx, hd->PswCheck, SIZE_PSWCHECK); - - byte Digest[SHA256_DIGEST_SIZE]; - sha256_done(&ctx, Digest); - - hd->UsePswCheck=memcmp(csum,Digest,SIZE_PSWCHECK_CSUM)==0; - - // RAR 5.21 and earlier set PswCheck field in service records to 0 - // even if UsePswCheck was present. - if (bb->HeaderType==HEAD_SERVICE && memcmp(hd->PswCheck,"\0\0\0\0\0\0\0\0",SIZE_PSWCHECK)==0) - hd->UsePswCheck=0; + Raw->GetB(hd->Salt,SIZE_SALT50); + Raw->GetB(hd->InitV,SIZE_INITV); + if (hd->UsePswCheck) + { + Raw->GetB(hd->PswCheck,SIZE_PSWCHECK); + + // It is important to know if password check data is valid. + // If it is damaged and header CRC32 fails to detect it, + // archiver would refuse to decompress a possibly valid file. + // Since we want to be sure distinguishing a wrong password + // or corrupt file data, we use 64-bit password check data + // and to control its validity we use 32 bits of password + // check data SHA-256 additionally to 32-bit header CRC32. + byte csum[SIZE_PSWCHECK_CSUM]; + Raw->GetB(csum,SIZE_PSWCHECK_CSUM); + + byte Digest[SHA256_DIGEST_SIZE]; + sha256_get(hd->PswCheck, SIZE_PSWCHECK, Digest); + + hd->UsePswCheck=memcmp(csum,Digest,SIZE_PSWCHECK_CSUM)==0; + + // RAR 5.21 and earlier set PswCheck field in service records to 0 + // even if UsePswCheck was present. + if (bb->HeaderType==HEAD_SERVICE && memcmp(hd->PswCheck,"\0\0\0\0\0\0\0\0",SIZE_PSWCHECK)==0) + hd->UsePswCheck=0; + } + hd->SaltSet=true; + hd->CryptMethod=CRYPT_RAR50; + hd->Encrypted=true; } - hd->SaltSet=true; - hd->CryptMethod=CRYPT_RAR50; - hd->Encrypted=true; } } break; @@ -1133,31 +1136,27 @@ void Archive::ProcessExtra50(RawRead *Raw,size_t ExtraSize,const BaseBlock *bb) if (Version!=0) { hd->Version=true; - - wchar VerText[20]; - swprintf(VerText,ASIZE(VerText),L";%u",Version); - wcsncatz(hd->FileName,VerText,ASIZE(hd->FileName)); + hd->FileName += L';' + std::to_wstring(Version); } } break; case FHEXTRA_REDIR: { - hd->RedirType=(FILE_SYSTEM_REDIRECT)Raw->GetV(); + FILE_SYSTEM_REDIRECT RedirType=(FILE_SYSTEM_REDIRECT)Raw->GetV(); uint Flags=(uint)Raw->GetV(); - hd->DirTarget=(Flags & FHEXTRA_REDIR_DIR)!=0; size_t NameSize=(size_t)Raw->GetV(); - char UtfName[NM*4]; - *UtfName=0; - if (NameSize0 && NameSizeGetB(UtfName,NameSize); - UtfName[NameSize]=0; - } + std::string UtfName(NameSize,0); + hd->RedirType=RedirType; + hd->DirTarget=(Flags & FHEXTRA_REDIR_DIR)!=0; + Raw->GetB(&UtfName[0],NameSize); + UtfToWide(&UtfName[0],hd->RedirName); #ifdef _WIN_ALL - UnixSlashToDos(UtfName,UtfName,ASIZE(UtfName)); + UnixSlashToDos(hd->RedirName,hd->RedirName); #endif - UtfToWide(UtfName,hd->RedirName,ASIZE(hd->RedirName)); + } } break; case FHEXTRA_UOWNER: @@ -1214,8 +1213,8 @@ void Archive::ProcessExtra50(RawRead *Raw,size_t ExtraSize,const BaseBlock *bb) // We cannot allocate too much memory here, because above // we check FieldSize againt Raw size and we control that Raw size // is sensible when reading headers. - hd->SubData.Alloc((size_t)FieldSize); - Raw->GetB(hd->SubData.Addr(0),(size_t)FieldSize); + hd->SubData.resize((size_t)FieldSize); + Raw->GetB(hd->SubData.data(),(size_t)FieldSize); } break; } @@ -1238,7 +1237,7 @@ size_t Archive::ReadHeader14() Raw.GetB(Mark,4); uint HeadSize=Raw.Get2(); if (HeadSize<7) - return false; + return 0; byte Flags=Raw.Get1(); NextBlockPos=CurBlockPos+HeadSize; CurHeaderType=HEAD_MAIN; @@ -1261,7 +1260,7 @@ size_t Archive::ReadHeader14() FileHead.FileHash.CRC32=Raw.Get2(); FileHead.HeadSize=Raw.Get2(); if (FileHead.HeadSize<21) - return false; + return 0; uint FileTime=Raw.Get4(); FileHead.FileAttr=Raw.Get1(); FileHead.Flags=Raw.Get1()|LONG_BLOCK; @@ -1285,12 +1284,13 @@ size_t Archive::ReadHeader14() Raw.Read(NameSize); - char FileName[NM]; - size_t ReadNameSize=Min(NameSize,ASIZE(FileName)-1); - Raw.GetB((byte *)FileName,ReadNameSize); - FileName[ReadNameSize]=0; - IntToExt(FileName,FileName,ASIZE(FileName)); - CharToWide(FileName,FileHead.FileName,ASIZE(FileHead.FileName)); + // RAR 1.4 name size is stored in a single byte field and it can't + // exceed 255, so additional checks are not needed. + std::string FileName(NameSize,0); + Raw.GetB((byte *)&FileName[0],NameSize); + std::string NameA; + IntToExt(FileName,NameA); + CharToWide(NameA,FileHead.FileName); ConvertNameCase(FileHead.FileName); ConvertFileHeader(&FileHead); @@ -1304,7 +1304,7 @@ size_t Archive::ReadHeader14() #ifndef SFX_MODULE -void Archive::ConvertNameCase(wchar *Name) +void Archive::ConvertNameCase(std::wstring &Name) { if (Cmd->ConvertNames==NAMES_UPPERCASE) wcsupper(Name); @@ -1322,7 +1322,7 @@ bool Archive::IsArcDir() void Archive::ConvertAttributes() { -#if defined(_WIN_ALL) || defined(_EMX) +#ifdef _WIN_ALL if (FileHead.HSType!=HSYS_WINDOWS) FileHead.FileAttr=FileHead.Dir ? 0x10 : 0x20; #endif @@ -1387,19 +1387,23 @@ void Archive::ConvertAttributes() void Archive::ConvertFileHeader(FileHeader *hd) { +/* if (hd->HSType==HSYS_UNKNOWN) if (hd->Dir) hd->FileAttr=0x10; else hd->FileAttr=0x20; +*/ #ifdef _WIN_ALL if (hd->HSType==HSYS_UNIX) // Convert Unix, OS X and Android decomposed chracters to Windows precomposed. - ConvertToPrecomposed(hd->FileName,ASIZE(hd->FileName)); + ConvertToPrecomposed(hd->FileName); #endif - for (wchar *s=hd->FileName;*s!=0;s++) + for (uint I=0;IFileName.size();I++) { + wchar *s=&hd->FileName[I]; + #ifdef _UNIX // Backslash is the invalid character for Windows file headers, // but it can present in Unix file names extracted in Unix. @@ -1407,7 +1411,7 @@ void Archive::ConvertFileHeader(FileHeader *hd) *s='_'; #endif -#if defined(_WIN_ALL) || defined(_EMX) +#ifdef _WIN_ALL // RAR 5.0 archives do not use '\' as path separator, so if we see it, // it means that it is a part of Unix file name, which we cannot // extract in Windows. @@ -1432,6 +1436,9 @@ void Archive::ConvertFileHeader(FileHeader *hd) if (*s=='/' || *s=='\\' && Format!=RARFMT50) *s=CPATHDIVIDER; } + + // Zeroes inside might be possible in broken Unicode names decoded with EncodeFileName::Decode. + TruncateAtZero(hd->FileName); // Ensure there are no zeroes inside of string. } @@ -1446,7 +1453,7 @@ int64 Archive::GetStartPos() } -bool Archive::ReadSubData(Array *UnpData,File *DestFile,bool TestMode) +bool Archive::ReadSubData(std::vector *UnpData,File *DestFile,bool TestMode) { if (BrokenHeader) { @@ -1454,7 +1461,7 @@ bool Archive::ReadSubData(Array *UnpData,File *DestFile,bool TestMode) ErrHandler.SetErrorCode(RARX_CRC); return false; } - if (SubHead.Method>5 || SubHead.UnpVer>(Format==RARFMT50 ? VER_UNPACK5:VER_UNPACK)) + if (SubHead.Method>5 || SubHead.UnpVer>(Format==RARFMT50 ? VER_UNPACK7:VER_UNPACK)) { uiMsg(UIERROR_SUBHEADERUNKNOWN,FileName); return false; @@ -1481,7 +1488,7 @@ bool Archive::ReadSubData(Array *UnpData,File *DestFile,bool TestMode) SubDataIO.SetTestMode(true); else { - UnpData->Alloc((size_t)SubHead.UnpSize); + UnpData->resize((size_t)SubHead.UnpSize); SubDataIO.SetUnpackToMemory(&(*UnpData)[0],(uint)SubHead.UnpSize); } } @@ -1510,7 +1517,7 @@ bool Archive::ReadSubData(Array *UnpData,File *DestFile,bool TestMode) uiMsg(UIERROR_SUBHEADERDATABROKEN,FileName,SubHead.FileName); ErrHandler.SetErrorCode(RARX_CRC); if (UnpData!=NULL) - UnpData->Reset(); + UnpData->clear(); return false; } return true; diff --git a/vendor/unrar/blake2s.cpp b/vendor/unrar/blake2s.cpp index 317603dac4..ae9d4e02a0 100644 --- a/vendor/unrar/blake2s.cpp +++ b/vendor/unrar/blake2s.cpp @@ -2,6 +2,20 @@ #include "rar.hpp" +static const byte blake2s_sigma[10][16] = +{ + { 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15 } , + { 14, 10, 4, 8, 9, 15, 13, 6, 1, 12, 0, 2, 11, 7, 5, 3 } , + { 11, 8, 12, 0, 5, 2, 15, 13, 10, 14, 3, 6, 7, 1, 9, 4 } , + { 7, 9, 3, 1, 13, 12, 11, 14, 2, 6, 5, 10, 4, 0, 15, 8 } , + { 9, 0, 5, 7, 2, 4, 10, 15, 14, 1, 11, 12, 6, 8, 3, 13 } , + { 2, 12, 6, 10, 0, 11, 8, 3, 4, 13, 7, 5, 15, 14, 1, 9 } , + { 12, 5, 1, 15, 14, 13, 4, 10, 0, 7, 6, 3, 9, 2, 8, 11 } , + { 13, 11, 7, 14, 12, 1, 3, 9, 5, 0, 15, 4, 8, 6, 2, 10 } , + { 6, 15, 14, 9, 11, 3, 0, 8, 12, 2, 13, 7, 1, 4, 10, 5 } , + { 10, 2, 8, 4, 7, 6, 1, 5, 15, 11, 9, 14, 3, 12, 13 , 0 } , +}; + #ifdef USE_SSE #include "blake2s_sse.cpp" #endif @@ -18,20 +32,6 @@ static const uint32 blake2s_IV[8] = 0x510E527FUL, 0x9B05688CUL, 0x1F83D9ABUL, 0x5BE0CD19UL }; -static const byte blake2s_sigma[10][16] = -{ - { 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15 } , - { 14, 10, 4, 8, 9, 15, 13, 6, 1, 12, 0, 2, 11, 7, 5, 3 } , - { 11, 8, 12, 0, 5, 2, 15, 13, 10, 14, 3, 6, 7, 1, 9, 4 } , - { 7, 9, 3, 1, 13, 12, 11, 14, 2, 6, 5, 10, 4, 0, 15, 8 } , - { 9, 0, 5, 7, 2, 4, 10, 15, 14, 1, 11, 12, 6, 8, 3, 13 } , - { 2, 12, 6, 10, 0, 11, 8, 3, 4, 13, 7, 5, 15, 14, 1, 9 } , - { 12, 5, 1, 15, 14, 13, 4, 10, 0, 7, 6, 3, 9, 2, 8, 11 } , - { 13, 11, 7, 14, 12, 1, 3, 9, 5, 0, 15, 4, 8, 6, 2, 10 } , - { 6, 15, 14, 9, 11, 3, 0, 8, 12, 2, 13, 7, 1, 4, 10, 5 } , - { 10, 2, 8, 4, 7, 6, 1, 5, 15, 11, 9, 14, 3, 12, 13 , 0 } , -}; - static inline void blake2s_set_lastnode( blake2s_state *S ) { S->f[1] = ~0U; @@ -134,11 +134,7 @@ void blake2s_update( blake2s_state *S, const byte *in, size_t inlen ) blake2s_increment_counter( S, BLAKE2S_BLOCKBYTES ); #ifdef USE_SSE -#ifdef _WIN_32 // We use SSSE3 _mm_shuffle_epi8 only in x64 mode. - if (_SSE_Version>=SSE_SSE2) -#else if (_SSE_Version>=SSE_SSSE3) -#endif blake2s_compress_sse( S, S->buf ); else blake2s_compress( S, S->buf ); // Compress diff --git a/vendor/unrar/blake2s_sse.cpp b/vendor/unrar/blake2s_sse.cpp index 1a02f21066..933fcad8c4 100644 --- a/vendor/unrar/blake2s_sse.cpp +++ b/vendor/unrar/blake2s_sse.cpp @@ -1,15 +1,14 @@ // Based on public domain code written in 2012 by Samuel Neves -extern const byte blake2s_sigma[10][16]; - // Initialization vector. static __m128i blake2s_IV_0_3, blake2s_IV_4_7; -#ifdef _WIN_64 -// Constants for cyclic rotation. Used in 64-bit mode in mm_rotr_epi32 macro. +// Constants for cyclic rotation. static __m128i crotr8, crotr16; -#endif +#ifdef __GNUC__ +__attribute__((target("sse2"))) +#endif static void blake2s_init_sse() { // We cannot initialize these 128 bit variables in place when declaring @@ -24,28 +23,18 @@ static void blake2s_init_sse() blake2s_IV_0_3 = _mm_setr_epi32( 0x6A09E667, 0xBB67AE85, 0x3C6EF372, 0xA54FF53A ); blake2s_IV_4_7 = _mm_setr_epi32( 0x510E527F, 0x9B05688C, 0x1F83D9AB, 0x5BE0CD19 ); -#ifdef _WIN_64 crotr8 = _mm_set_epi8( 12, 15, 14, 13, 8, 11, 10, 9, 4, 7, 6, 5, 0, 3, 2, 1 ); crotr16 = _mm_set_epi8( 13, 12, 15, 14, 9, 8, 11, 10, 5, 4, 7, 6, 1, 0, 3, 2 ); -#endif } #define LOAD(p) _mm_load_si128( (__m128i *)(p) ) #define STORE(p,r) _mm_store_si128((__m128i *)(p), r) -#ifdef _WIN_32 -// 32-bit mode has less SSE2 registers and in MSVC2008 it is more efficient -// to not use _mm_shuffle_epi8 here. -#define mm_rotr_epi32(r, c) ( \ - _mm_xor_si128(_mm_srli_epi32( (r), c ),_mm_slli_epi32( (r), 32-c )) ) -#else #define mm_rotr_epi32(r, c) ( \ c==8 ? _mm_shuffle_epi8(r,crotr8) \ : c==16 ? _mm_shuffle_epi8(r,crotr16) \ : _mm_xor_si128(_mm_srli_epi32( (r), c ),_mm_slli_epi32( (r), 32-c )) ) -#endif - #define G1(row1,row2,row3,row4,buf) \ row1 = _mm_add_epi32( _mm_add_epi32( row1, buf), row2 ); \ @@ -73,14 +62,6 @@ static void blake2s_init_sse() row3 = _mm_shuffle_epi32( row3, _MM_SHUFFLE(1,0,3,2) ); \ row2 = _mm_shuffle_epi32( row2, _MM_SHUFFLE(2,1,0,3) ); -#ifdef _WIN_64 - // MSVC 2008 in x64 mode expands _mm_set_epi32 to store to stack and load - // from stack operations, which are slower than this code. - #define _mm_set_epi32(i3,i2,i1,i0) \ - _mm_unpacklo_epi32(_mm_unpacklo_epi32(_mm_cvtsi32_si128(i0),_mm_cvtsi32_si128(i2)), \ - _mm_unpacklo_epi32(_mm_cvtsi32_si128(i1),_mm_cvtsi32_si128(i3))) -#endif - // Original BLAKE2 SSE4.1 message loading code was a little slower in x86 mode // and about the same in x64 mode in our test. Perhaps depends on compiler. // We also tried _mm_i32gather_epi32 and _mm256_i32gather_epi32 AVX2 gather @@ -101,6 +82,9 @@ static void blake2s_init_sse() } +#ifdef __GNUC__ +__attribute__((target("ssse3"))) +#endif static int blake2s_compress_sse( blake2s_state *S, const byte block[BLAKE2S_BLOCKBYTES] ) { __m128i row[4]; diff --git a/vendor/unrar/blake2sp.cpp b/vendor/unrar/blake2sp.cpp index da645883b5..91dbd14482 100644 --- a/vendor/unrar/blake2sp.cpp +++ b/vendor/unrar/blake2sp.cpp @@ -20,7 +20,7 @@ void blake2sp_init( blake2sp_state *S ) blake2s_init_param( &S->R, 0, 1 ); // Init root. - for( uint i = 0; i < PARALLELISM_DEGREE; ++i ) + for( uint32 i = 0; i < PARALLELISM_DEGREE; ++i ) blake2s_init_param( &S->S[i], i, 0 ); // Init leaf. S->R.last_node = 1; @@ -49,6 +49,8 @@ void Blake2ThreadData::Update() if (_SSE_Version>=SSE_SSE && inlen__ >= 2 * PARALLELISM_DEGREE * BLAKE2S_BLOCKBYTES) _mm_prefetch((char*)(in__ + PARALLELISM_DEGREE * BLAKE2S_BLOCKBYTES), _MM_HINT_T0); #endif + // We tried to _forceinline blake2s_update and blake2s_compress_sse, + // but it didn't improve performance. blake2s_update( S, in__, BLAKE2S_BLOCKBYTES ); in__ += PARALLELISM_DEGREE * BLAKE2S_BLOCKBYTES; inlen__ -= PARALLELISM_DEGREE * BLAKE2S_BLOCKBYTES; diff --git a/vendor/unrar/cmddata.cpp b/vendor/unrar/cmddata.cpp index ffc5ff90db..37bcf5b0fa 100644 --- a/vendor/unrar/cmddata.cpp +++ b/vendor/unrar/cmddata.cpp @@ -13,8 +13,18 @@ void CommandData::Init() { RAROptions::Init(); - *Command=0; - *ArcName=0; + Command.clear(); + ArcName.clear(); + ExtrPath.clear(); + TempPath.clear(); + SFXModule.clear(); + CommentFile.clear(); + ArcPath.clear(); + ExclArcPath.clear(); + LogName.clear(); + EmailTo.clear(); + UseStdin.clear(); + FileLists=false; NoMoreSwitches=false; @@ -30,57 +40,45 @@ void CommandData::Init() StoreArgs.Reset(); Password.Clean(); NextVolSizes.clear(); -} - - -// Return the pointer to next position in the string and store dynamically -// allocated command line parameter in Par. -static const wchar *AllocCmdParam(const wchar *CmdLine,wchar **Par) -{ - const wchar *NextCmd=GetCmdParam(CmdLine,NULL,0); - if (NextCmd==NULL) - return NULL; - size_t ParSize=NextCmd-CmdLine+2; // Parameter size including the trailing zero. - *Par=(wchar *)malloc(ParSize*sizeof(wchar)); - if (*Par==NULL) - return NULL; - return GetCmdParam(CmdLine,*Par,ParSize); +#ifdef RARDLL + DllDestName.clear(); +#endif } #if !defined(SFX_MODULE) void CommandData::ParseCommandLine(bool Preprocess,int argc, char *argv[]) { - *Command=0; + Command.clear(); NoMoreSwitches=false; #ifdef CUSTOM_CMDLINE_PARSER // In Windows we may prefer to implement our own command line parser // to avoid replacing \" by " in standard parser. Such replacing corrupts // destination paths like "dest path\" in extraction commands. - const wchar *CmdLine=GetCommandLine(); + std::wstring CmdLine=GetCommandLine(); + + std::wstring Param; + std::wstring::size_type Pos=0; - wchar *Par; for (bool FirstParam=true;;FirstParam=false) { - if ((CmdLine=AllocCmdParam(CmdLine,&Par))==NULL) + if (!GetCmdParam(CmdLine,Pos,Param)) break; if (!FirstParam) // First parameter is the executable name. if (Preprocess) - PreprocessArg(Par); + PreprocessArg(Param.data()); else - ParseArg(Par); - free(Par); + ParseArg(Param.data()); } #else - Array Arg; for (int I=1;I0 && Arg[L-1]=='.' && (L==1 || L>=2 && (IsPathDiv(Arg[L-2]) || + Arg[L-2]=='.' && (L==2 || L>=3 && IsPathDiv(Arg[L-3]))))) + FolderArg=true; + + wchar CmdChar=toupperw(Command[0]); bool Add=wcschr(L"AFUM",CmdChar)!=NULL; bool Extract=CmdChar=='X' || CmdChar=='E'; bool Repair=CmdChar=='R' && Command[1]==0; - if (EndSeparator && !Add) - wcsncpyz(ExtrPath,Arg,ASIZE(ExtrPath)); + if (FolderArg && !Add) + ExtrPath=Arg; else if ((Add || CmdChar=='T') && (*Arg!='@' || ListMode==RCLM_REJECT_LISTS)) FileArgs.AddString(Arg); @@ -147,10 +158,10 @@ void CommandData::ParseArg(wchar *Arg) } else // We use 'destpath\' when extracting and reparing. - if (Found && FileData.IsDir && (Extract || Repair) && *ExtrPath==0) + if (Found && FileData.IsDir && (Extract || Repair) && ExtrPath.empty()) { - wcsncpyz(ExtrPath,Arg,ASIZE(ExtrPath)); - AddEndSlash(ExtrPath,ASIZE(ExtrPath)); + ExtrPath=Arg; + AddEndSlash(ExtrPath); } else FileArgs.AddString(Arg); @@ -178,12 +189,12 @@ void CommandData::ParseDone() #if !defined(SFX_MODULE) void CommandData::ParseEnvVar() { - char *EnvStr=getenv("RAR"); - if (EnvStr!=NULL) + char *EnvVar=getenv("RAR"); + if (EnvVar!=NULL) { - Array EnvStrW(strlen(EnvStr)+1); - CharToWide(EnvStr,&EnvStrW[0],EnvStrW.Size()); - ProcessSwitchesString(&EnvStrW[0]); + std::wstring EnvStr; + CharToWide(EnvVar,EnvStr); + ProcessSwitchesString(EnvStr); } } #endif @@ -192,7 +203,7 @@ void CommandData::ParseEnvVar() #if !defined(SFX_MODULE) // Preprocess those parameters, which must be processed before the rest of -// command line. Return 'false' to stop further processing. +// command line. void CommandData::PreprocessArg(const wchar *Arg) { if (IsSwitch(Arg[0]) && !NoMoreSwitches) @@ -201,7 +212,7 @@ void CommandData::PreprocessArg(const wchar *Arg) if (Arg[0]=='-' && Arg[1]==0) // Switch "--". NoMoreSwitches=true; if (wcsicomp(Arg,L"cfg-")==0) - ConfigDisabled=true; + ProcessSwitch(Arg); if (wcsnicomp(Arg,L"ilog",4)==0) { // Ensure that correct log file name is already set @@ -213,13 +224,13 @@ void CommandData::PreprocessArg(const wchar *Arg) { // Process -sc before reading any file lists. ProcessSwitch(Arg); - if (*LogName!=0) + if (!LogName.empty()) InitLogOptions(LogName,ErrlogCharset); } } else - if (*Command==0) - wcsncpy(Command,Arg,ASIZE(Command)); // Need for rar.ini. + if (Command.empty()) + Command=Arg; // Need for rar.ini. } #endif @@ -237,10 +248,10 @@ void CommandData::ReadConfig() Str++; if (wcsnicomp(Str,L"switches=",9)==0) ProcessSwitchesString(Str+9); - if (*Command!=0) + if (!Command.empty()) { wchar Cmd[16]; - wcsncpyz(Cmd,Command,ASIZE(Cmd)); + wcsncpyz(Cmd,Command.c_str(),ASIZE(Cmd)); wchar C0=toupperw(Cmd[0]); wchar C1=toupperw(Cmd[1]); if (C0=='I' || C0=='L' || C0=='M' || C0=='S' || C0=='V') @@ -260,14 +271,19 @@ void CommandData::ReadConfig() #if !defined(SFX_MODULE) -void CommandData::ProcessSwitchesString(const wchar *Str) +void CommandData::ProcessSwitchesString(const std::wstring &Str) { - wchar *Par; - while ((Str=AllocCmdParam(Str,&Par))!=NULL) + std::wstring Par; + std::wstring::size_type Pos=0; + while (GetCmdParam(Str,Pos,Par)) { - if (IsSwitch(*Par)) - ProcessSwitch(Par+1); - free(Par); + if (IsSwitch(Par[0])) + ProcessSwitch(&Par[1]); + else + { + mprintf(St(MSwSyntaxError),Par.c_str()); + ErrHandler.Exit(RARX_USERERROR); + } } } #endif @@ -330,13 +346,12 @@ void CommandData::ProcessSwitch(const wchar *Switch) break; } break; - case 'N': // Reserved for archive name. - break; case 'O': AddArcOnly=true; break; case 'P': - wcsncpyz(ArcPath,Switch+2,ASIZE(ArcPath)); + // Convert slashes here than before every comparison. + SlashToNative(Switch+2,ArcPath); break; case 'S': SyncFiles=true; @@ -347,7 +362,14 @@ void CommandData::ProcessSwitch(const wchar *Switch) } break; case 'C': - if (Switch[2]==0) + if (Switch[2]!=0) + { + if (wcsicomp(Switch+1,L"FG-")==0) + ConfigDisabled=true; + else + BadSwitch(Switch); + } + else switch(toupperw(Switch[1])) { case '-': @@ -359,10 +381,15 @@ void CommandData::ProcessSwitch(const wchar *Switch) case 'L': ConvertNames=NAMES_LOWERCASE; break; + default: + BadSwitch(Switch); + break; } break; case 'D': - if (Switch[2]==0) + if (Switch[2]!=0) + BadSwitch(Switch); + else switch(toupperw(Switch[1])) { case 'S': @@ -374,6 +401,9 @@ void CommandData::ProcessSwitch(const wchar *Switch) case 'F': DeleteFiles=true; break; + default: + BadSwitch(Switch); + break; } break; case 'E': @@ -395,7 +425,11 @@ void CommandData::ProcessSwitch(const wchar *Switch) ExclPath=EXCL_ABSPATH; break; case '4': - wcsncpyz(ExclArcPath,Switch+3,ASIZE(ExclArcPath)); + // Convert slashes here than before every comparison. + SlashToNative(Switch+3,ExclArcPath); + break; + default: + BadSwitch(Switch); break; } break; @@ -431,7 +465,7 @@ void CommandData::ProcessSwitch(const wchar *Switch) else if (!Password.IsSet()) { - uiGetPassword(UIPASSWORD_GLOBAL,NULL,&Password,NULL); + uiGetPassword(UIPASSWORD_GLOBAL,L"",&Password,NULL); eprintf(L"\n"); } break; @@ -443,7 +477,7 @@ void CommandData::ProcessSwitch(const wchar *Switch) case 'I': if (wcsnicomp(Switch+1,L"LOG",3)==0) { - wcsncpyz(LogName,Switch[4]!=0 ? Switch+4:DefLogName,ASIZE(LogName)); + LogName=Switch[4]!=0 ? Switch+4:DefLogName; break; } if (wcsnicomp(Switch+1,L"SND",3)==0) @@ -461,7 +495,7 @@ void CommandData::ProcessSwitch(const wchar *Switch) } if (wcsnicomp(Switch+1,L"EML",3)==0) { - wcsncpyz(EmailTo,Switch[4]!=0 ? Switch+4:L"@",ASIZE(EmailTo)); + EmailTo=Switch[4]!=0 ? Switch+4:L"@"; break; } if (wcsicomp(Switch+1,L"M")==0) // For compatibility with pre-WinRAR 6.0 -im syntax. Replaced with -idv. @@ -568,12 +602,14 @@ void CommandData::ProcessSwitch(const wchar *Switch) } switch(toupperw(*(Str++))) { - case 'T': Type=FILTER_PPM; break; +// case 'T': Type=FILTER_TEXT; break; case 'E': Type=FILTER_E8; break; case 'D': Type=FILTER_DELTA; break; - case 'A': Type=FILTER_AUDIO; break; - case 'C': Type=FILTER_RGB; break; - case 'R': Type=FILTER_ARM; break; +// case 'A': Type=FILTER_AUDIO; break; +// case 'C': Type=FILTER_RGB; break; +// case 'R': Type=FILTER_ARM; break; + case 'L': Type=FILTER_LONGRANGE; break; + case 'X': Type=FILTER_EXHAUSTIVE; break; } if (*Str=='+' || *Str=='-') State=*(Str++)=='+' ? FILTER_FORCE:FILTER_DISABLE; @@ -586,6 +622,44 @@ void CommandData::ProcessSwitch(const wchar *Switch) case 'M': break; case 'D': + { + bool SetDictLimit=toupperw(Switch[2])=='X'; + + uint64 Size=atoiw(Switch+(SetDictLimit ? 3 : 2)); + wchar LastChar=toupperw(Switch[wcslen(Switch)-1]); + if (IsDigit(LastChar)) + LastChar=SetDictLimit ? 'G':'M'; // Treat -md128 as -md128m and -mdx32 as -mdx32g. + switch(LastChar) + { + case 'K': + Size*=1024; + break; + case 'M': + Size*=1024*1024; + break; + case 'G': + Size*=1024*1024*1024; + break; + default: + BadSwitch(Switch); + } + + // 2023.07.22: For 4 GB and less we also check that it is power of 2, + // so archives are compatible with RAR 5.0+. + // We allow Size>PACK_MAX_DICT here, so we can use -md[x] to unpack + // archives created by future versions with higher PACK_MAX_DICT + uint Flags; + if ((Size=Archive::GetWinSize(Size,Flags))==0 || + Size<=0x100000000ULL && !IsPow2(Size)) + BadSwitch(Switch); + else + if (SetDictLimit) + WinSizeLimit=Size; + else + { + WinSize=Size; + } + } break; case 'E': if (toupperw(Switch[2])=='S' && Switch[3]==0) @@ -593,25 +667,20 @@ void CommandData::ProcessSwitch(const wchar *Switch) break; case 'S': { - wchar StoreNames[1024]; - wcsncpyz(StoreNames,(Switch[2]==0 ? DefaultStoreList:Switch+2),ASIZE(StoreNames)); - wchar *Names=StoreNames; - while (*Names!=0) + std::wstring StoreNames=(Switch[2]==0 ? DefaultStoreList:Switch+2); + size_t Pos=0; + while (Pos. + std::wstring ExclArcPath; // For -ep4 switch. + std::wstring LogName; + std::wstring EmailTo; + + // Read data from stdin and store in archive under a name specified here + // when archiving. Read an archive from stdin if any non-empty string + // is specified here when extracting. + std::wstring UseStdin; StringList FileArgs; StringList ExclArgs; @@ -69,6 +82,11 @@ class CommandData:public RAROptions SecPassword Password; std::vector NextVolSizes; + + +#ifdef RARDLL + std::wstring DllDestName; +#endif }; #endif diff --git a/vendor/unrar/cmdfilter.cpp b/vendor/unrar/cmdfilter.cpp index e0add14bfa..c20d8d6b98 100644 --- a/vendor/unrar/cmdfilter.cpp +++ b/vendor/unrar/cmdfilter.cpp @@ -1,7 +1,7 @@ // Return 'true' if we need to exclude the file from processing as result // of -x switch. If CheckInclList is true, we also check the file against // the include list created with -n switch. -bool CommandData::ExclCheck(const wchar *CheckName,bool Dir,bool CheckFullPath,bool CheckInclList) +bool CommandData::ExclCheck(const std::wstring &CheckName,bool Dir,bool CheckFullPath,bool CheckInclList) { if (CheckArgs(&ExclArgs,Dir,CheckName,CheckFullPath,MATCH_WILDSUBPATH)) return true; @@ -13,17 +13,15 @@ bool CommandData::ExclCheck(const wchar *CheckName,bool Dir,bool CheckFullPath,b } -bool CommandData::CheckArgs(StringList *Args,bool Dir,const wchar *CheckName,bool CheckFullPath,int MatchMode) +bool CommandData::CheckArgs(StringList *Args,bool Dir,const std::wstring &CheckName,bool CheckFullPath,int MatchMode) { - wchar *Name=ConvertPath(CheckName,NULL,0); - wchar FullName[NM]; - wchar CurMask[NM]; - *FullName=0; + std::wstring Name,FullName,CurMask; + ConvertPath(&CheckName,&Name); Args->Rewind(); - while (Args->GetString(CurMask,ASIZE(CurMask))) + while (Args->GetString(CurMask)) { - wchar *LastMaskChar=PointToLastChar(CurMask); - bool DirMask=IsPathDiv(*LastMaskChar); // Mask for directories only. + wchar LastMaskChar=GetLastChar(CurMask); + bool DirMask=IsPathDiv(LastMaskChar); // Mask for directories only. if (Dir) { @@ -33,16 +31,33 @@ bool CommandData::CheckArgs(StringList *Args,bool Dir,const wchar *CheckName,boo // We process the directory and have the directory exclusion mask. // So let's convert "mask\" to "mask" and process it normally. - *LastMaskChar=0; + CurMask.pop_back(); } else { - // REMOVED, we want -npath\* to match empty folders too. - // If mask has wildcards in name part and does not have the trailing - // '\' character, we cannot use it for directories. - - // if (IsWildcard(PointToName(CurMask))) - // continue; + // This code doesn't allow to apply -n and -x wildcard masks without + // trailing slash to folders unless these masks are * and *.*. + // See the changes history below. + // 2023.03.26: Previously we removed this code completely to let + // 'rar a arc dir -ndir\path\*' include empty folders in 'path' too. + // But then we received an email from user not willing -x*.avi to + // exclude folders like dir.avi with non-avi files. Also rar.txt + // mentions that masks like *.avi exclude only files. Initially + // we wanted masks like -npath\* or -xpath\* to match the entire + // contents of path including empty folders and added the special + // check for "*" and "*.*". But this is not very straightforward, + // when *.* and *.avi are processed differently, especially taking + // into account that we can specify the exact folder name without + // wildcards to process it and masks like 'dir*\' can be used to + // exclude folders. So we decided to skip all usual wildcard masks + // for folders. + // 2023.11.22: We returned the special check for "*" and "*.*", + // because users expected 'rar a arc dir -xdir\*' to exclude + // everything including subfolders in 'dir'. For now we returned it + // both for -n and -x, but we can limit it to -x only if needed. + std::wstring Name=PointToName(CurMask); + if (IsWildcard(Name) && Name!=L"*" && Name!=L"*.*") + continue; } } else @@ -54,7 +69,7 @@ bool CommandData::CheckArgs(StringList *Args,bool Dir,const wchar *CheckName,boo // is excluded from further scanning. if (DirMask) - wcsncatz(CurMask,L"*",ASIZE(CurMask)); + CurMask+=L"*"; } #ifndef SFX_MODULE @@ -66,19 +81,20 @@ bool CommandData::CheckArgs(StringList *Args,bool Dir,const wchar *CheckName,boo // correctly. Moreover, removing "*\" from mask would break // the comparison, because now all names have the path. - if (*FullName==0) - ConvertNameToFull(CheckName,FullName,ASIZE(FullName)); + if (FullName.empty()) + ConvertNameToFull(CheckName,FullName); if (CmpName(CurMask,FullName,MatchMode)) return true; } else #endif { - wchar NewName[NM+2],*CurName=Name; + std::wstring CurName=Name; // Important to convert before "*\" check below, so masks like // d:*\something are processed properly. - wchar *CmpMask=ConvertPath(CurMask,NULL,0); + size_t MaskOffset=ConvertPath(&CurMask,nullptr); + std::wstring CmpMask=CurMask.substr(MaskOffset); if (CmpMask[0]=='*' && IsPathDiv(CmpMask[1])) { @@ -86,10 +102,9 @@ bool CommandData::CheckArgs(StringList *Args,bool Dir,const wchar *CheckName,boo // but also in the current directory. We convert the name // from 'name' to '.\name' to be matched by "*\" part even if it is // in current directory. - NewName[0]='.'; - NewName[1]=CPATHDIVIDER; - wcsncpyz(NewName+2,Name,ASIZE(NewName)-2); - CurName=NewName; + CurName=L'.'; + CurName+=CPATHDIVIDER; + CurName+=Name; } if (CmpName(CmpMask,CurName,MatchMode)) @@ -277,10 +292,10 @@ bool CommandData::SizeCheck(int64 Size) // Return 0 if file must not be processed or a number of matched parameter otherwise. int CommandData::IsProcessFile(FileHeader &FileHead,bool *ExactMatch,int MatchType, - bool Flags,wchar *MatchedArg,uint MatchedArgSize) + bool Flags,std::wstring *MatchedArg) { - if (MatchedArg!=NULL && MatchedArgSize>0) - *MatchedArg=0; + if (MatchedArg!=NULL) + MatchedArg->clear(); bool Dir=FileHead.Dir; if (ExclCheck(FileHead.FileName,Dir,false,true)) return 0; @@ -295,17 +310,22 @@ int CommandData::IsProcessFile(FileHeader &FileHead,bool *ExactMatch,int MatchTy if (!Dir && SizeCheck(FileHead.UnpSize)) return 0; #endif - wchar *ArgName; + std::wstring ArgName; FileArgs.Rewind(); - for (int StringCount=1;(ArgName=FileArgs.GetString())!=NULL;StringCount++) + for (int StringCount=1;FileArgs.GetString(ArgName);StringCount++) + { + // Ensure that both parameters of CmpName are either C++ strings or + // pointers, so we avoid time consuming string construction for one of + // parameters in this expensive loop. if (CmpName(ArgName,FileHead.FileName,MatchType)) { if (ExactMatch!=NULL) *ExactMatch=wcsicompc(ArgName,FileHead.FileName)==0; if (MatchedArg!=NULL) - wcsncpyz(MatchedArg,ArgName,MatchedArgSize); + *MatchedArg=ArgName; return StringCount; } + } return 0; } diff --git a/vendor/unrar/cmdmix.cpp b/vendor/unrar/cmdmix.cpp index 6bd1e1ac0f..e70b7d0011 100644 --- a/vendor/unrar/cmdmix.cpp +++ b/vendor/unrar/cmdmix.cpp @@ -103,7 +103,7 @@ void CommandData::OutHelp(RAR_EXIT ExitCode) if (CmpMSGID(Help[I],MCHelpSwOW)) continue; #endif -#if !defined(_WIN_ALL) && !defined(_EMX) +#ifndef _WIN_ALL if (CmpMSGID(Help[I],MCHelpSwAC)) continue; #endif diff --git a/vendor/unrar/coder.cpp b/vendor/unrar/coder.cpp index 9d971a8ad4..6282371cd8 100644 --- a/vendor/unrar/coder.cpp +++ b/vendor/unrar/coder.cpp @@ -1,8 +1,8 @@ -inline unsigned int RangeCoder::GetChar() +inline byte RangeCoder::GetChar() { - return(UnpackRead->GetChar()); + return UnpackRead->GetChar(); } @@ -11,8 +11,8 @@ void RangeCoder::InitDecoder(Unpack *UnpackRead) RangeCoder::UnpackRead=UnpackRead; low=code=0; - range=uint(-1); - for (int i=0;i < 4;i++) + range=0xffffffff; + for (uint i = 0; i < 4; i++) code=(code << 8) | GetChar(); } diff --git a/vendor/unrar/coder.hpp b/vendor/unrar/coder.hpp index 7b36ff218f..42c3f33845 100644 --- a/vendor/unrar/coder.hpp +++ b/vendor/unrar/coder.hpp @@ -11,7 +11,7 @@ class RangeCoder inline uint GetCurrentShiftCount(uint SHIFT); inline void Decode(); inline void PutChar(unsigned int c); - inline unsigned int GetChar(); + inline byte GetChar(); uint low, code, range; struct SUBRANGE diff --git a/vendor/unrar/compress.hpp b/vendor/unrar/compress.hpp index 4ef8570f4e..018909a01b 100644 --- a/vendor/unrar/compress.hpp +++ b/vendor/unrar/compress.hpp @@ -21,10 +21,12 @@ class PackDef static const uint LOW_DIST_REP_COUNT = 16; static const uint NC = 306; /* alphabet = {0, 1, 2, ..., NC - 1} */ - static const uint DC = 64; + static const uint DCB = 64; // Base distance codes up to 4 GB. + static const uint DCX = 80; // Extended distance codes up to 1 TB. static const uint LDC = 16; static const uint RC = 44; - static const uint HUFF_TABLE_SIZE = NC + DC + RC + LDC; + static const uint HUFF_TABLE_SIZEB = NC + DCB + RC + LDC; + static const uint HUFF_TABLE_SIZEX = NC + DCX + RC + LDC; static const uint BC = 20; static const uint NC30 = 299; /* alphabet = {0, 1, 2, ..., NC - 1} */ @@ -43,10 +45,6 @@ class PackDef // Largest alphabet size among all values listed above. static const uint LARGEST_TABLE_SIZE = 306; - enum { - CODE_HUFFMAN, CODE_LZ, CODE_REPEATLZ, CODE_CACHELZ, CODE_STARTFILE, - CODE_ENDFILE, CODE_FILTER, CODE_FILTERDATA - }; }; @@ -54,7 +52,10 @@ enum FilterType { // These values must not be changed, because we use them directly // in RAR5 compression and decompression code. FILTER_DELTA=0, FILTER_E8, FILTER_E8E9, FILTER_ARM, - FILTER_AUDIO, FILTER_RGB, FILTER_ITANIUM, FILTER_PPM, FILTER_NONE + FILTER_AUDIO, FILTER_RGB, FILTER_ITANIUM, FILTER_TEXT, + + // These values can be changed. + FILTER_LONGRANGE,FILTER_EXHAUSTIVE,FILTER_NONE }; #endif diff --git a/vendor/unrar/consio.cpp b/vendor/unrar/consio.cpp index fa35d6146f..023c3f3c84 100644 --- a/vendor/unrar/consio.cpp +++ b/vendor/unrar/consio.cpp @@ -5,8 +5,6 @@ static MESSAGE_TYPE MsgStream=MSG_STDOUT; static RAR_CHARSET RedirectCharset=RCH_DEFAULT; static bool ProhibitInput=false; -const int MaxMsgSize=2*NM+2048; - static bool StdoutRedirected=false,StderrRedirected=false,StdinRedirected=false; #ifdef _WIN_ALL @@ -71,44 +69,42 @@ void ProhibitConsoleInput() #ifndef SILENT static void cvt_wprintf(FILE *dest,const wchar *fmt,va_list arglist) { - // This buffer is for format string only, not for entire output, - // so it can be short enough. - wchar fmtw[1024]; - PrintfPrepareFmt(fmt,fmtw,ASIZE(fmtw)); + // No need for PrintfPrepareFmt here, vwstrprintf calls it. + std::wstring s=vwstrprintf(fmt,arglist); + + ReplaceEsc(s); + #ifdef _WIN_ALL - safebuf wchar Msg[MaxMsgSize]; if (dest==stdout && StdoutRedirected || dest==stderr && StderrRedirected) { HANDLE hOut=GetStdHandle(dest==stdout ? STD_OUTPUT_HANDLE:STD_ERROR_HANDLE); - vswprintf(Msg,ASIZE(Msg),fmtw,arglist); DWORD Written; if (RedirectCharset==RCH_UNICODE) - WriteFile(hOut,Msg,(DWORD)wcslen(Msg)*sizeof(*Msg),&Written,NULL); + WriteFile(hOut,s.data(),(DWORD)s.size()*sizeof(s[0]),&Written,NULL); else { // Avoid Unicode for redirect in Windows, it does not work with pipes. - safebuf char MsgA[MaxMsgSize]; + std::string MsgA; if (RedirectCharset==RCH_UTF8) - WideToUtf(Msg,MsgA,ASIZE(MsgA)); + WideToUtf(s,MsgA); else - WideToChar(Msg,MsgA,ASIZE(MsgA)); + WideToChar(s,MsgA); if (RedirectCharset==RCH_DEFAULT || RedirectCharset==RCH_OEM) - CharToOemA(MsgA,MsgA); // Console tools like 'more' expect OEM encoding. + CharToOemA(&MsgA[0],&MsgA[0]); // Console tools like 'more' expect OEM encoding. // We already converted \n to \r\n above, so we use WriteFile instead // of C library to avoid unnecessary additional conversion. - WriteFile(hOut,MsgA,(DWORD)strlen(MsgA),&Written,NULL); + WriteFile(hOut,MsgA.data(),(DWORD)MsgA.size(),&Written,NULL); } return; } // MSVC2008 vfwprintf writes every character to console separately // and it is too slow. We use direct WriteConsole call instead. - vswprintf(Msg,ASIZE(Msg),fmtw,arglist); HANDLE hOut=GetStdHandle(dest==stderr ? STD_ERROR_HANDLE:STD_OUTPUT_HANDLE); DWORD Written; - WriteConsole(hOut,Msg,(DWORD)wcslen(Msg),&Written,NULL); + WriteConsole(hOut,s.data(),(DWORD)s.size(),&Written,NULL); #else - vfwprintf(dest,fmtw,arglist); + fputws(s.c_str(),dest); // We do not use setbuf(NULL) in Unix (see comments in InitConsole). fflush(dest); #endif @@ -160,13 +156,11 @@ static void QuitIfInputProhibited() } -static void GetPasswordText(wchar *Str,uint MaxLength) +static void GetPasswordText(std::wstring &Str) { - if (MaxLength==0) - return; QuitIfInputProhibited(); if (StdinRedirected) - getwstr(Str,MaxLength); // Read from pipe or redirected file. + getwstr(Str); // Read from pipe or redirected file. else { #ifdef _WIN_ALL @@ -175,50 +169,47 @@ static void GetPasswordText(wchar *Str,uint MaxLength) GetConsoleMode(hConIn,&ConInMode); SetConsoleMode(hConIn,ENABLE_LINE_INPUT); // Remove ENABLE_ECHO_INPUT. + std::vector Buf(MAXPASSWORD); + // We prefer ReadConsole to ReadFile, so we can read Unicode input. DWORD Read=0; - ReadConsole(hConIn,Str,MaxLength-1,&Read,NULL); - Str[Read]=0; + ReadConsole(hConIn,Buf.data(),(DWORD)Buf.size()-1,&Read,NULL); + Buf[Read]=0; + Str=Buf.data(); + cleandata(Buf.data(),Buf.size()*sizeof(Buf[0])); + SetConsoleMode(hConIn,ConInMode); - // If entered password is longer than MAXPASSWORD and truncated, - // read its unread part anyway, so it isn't read later as the second - // password for -p switch. Low level FlushConsoleInputBuffer doesn't help + // 2023.03.12: Previously we checked for presence of "\n" in entered + // passwords, supposing that truncated strings do not include it. + // We did it to read the rest of excessively long string, so it is not + // read later as the second password for -p switch. But this "\n" check + // doesn't seem to work in Windows 10 anymore and "\r" is present even + // in truncated strings. Also we increased MAXPASSWORD, so it is larger + // than MAXPASSWORD_RAR. Thus we removed this check as not working + // and not that necessary. Low level FlushConsoleInputBuffer doesn't help // for high level ReadConsole, which in line input mode seems to store // the rest of string in its own internal buffer. - if (wcschr(Str,'\r')==NULL) // If '\r' is missing, the password was truncated. - while (true) - { - wchar Trail[64]; - DWORD TrailRead=0; - // Use ASIZE(Trail)-1 to reserve the space for trailing 0. - ReadConsole(hConIn,Trail,ASIZE(Trail)-1,&TrailRead,NULL); - Trail[TrailRead]=0; - if (TrailRead==0 || wcschr(Trail,'\r')!=NULL) - break; - } - #else - char StrA[MAXPASSWORD*4]; // "*4" for multibyte UTF-8 characters. -#if defined(_EMX) || defined (__VMS) - fgets(StrA,ASIZE(StrA)-1,stdin); + std::vector StrA(MAXPASSWORD*4); // "*4" for multibyte UTF-8 characters. +#ifdef __VMS + fgets(StrA.data(),StrA.size()-1,stdin); #elif defined(__sun) - strncpyz(StrA,getpassphrase(""),ASIZE(StrA)); + strncpyz(StrA.data(),getpassphrase(""),StrA.size()); #else - strncpyz(StrA,getpass(""),ASIZE(StrA)); + strncpyz(StrA.data(),getpass(""),StrA.size()); #endif - CharToWide(StrA,Str,MaxLength); - cleandata(StrA,sizeof(StrA)); + CharToWide(StrA.data(),Str); + cleandata(StrA.data(),StrA.size()*sizeof(StrA[0])); #endif } - Str[MaxLength-1]=0; RemoveLF(Str); } #endif #ifndef SILENT -bool GetConsolePassword(UIPASSWORD_TYPE Type,const wchar *FileName,SecPassword *Password) +bool GetConsolePassword(UIPASSWORD_TYPE Type,const std::wstring &FileName,SecPassword *Password) { if (!StdinRedirected) uiAlarm(UIALARM_QUESTION); @@ -229,33 +220,33 @@ bool GetConsolePassword(UIPASSWORD_TYPE Type,const wchar *FileName,SecPassword * if (Type==UIPASSWORD_GLOBAL) eprintf(L"\n%s: ",St(MAskPsw)); else - eprintf(St(MAskPswFor),FileName); + eprintf(St(MAskPswFor),FileName.c_str()); - wchar PlainPsw[MAXPASSWORD+1]; - GetPasswordText(PlainPsw,ASIZE(PlainPsw)); - if (*PlainPsw==0 && Type==UIPASSWORD_GLOBAL) + std::wstring PlainPsw; + GetPasswordText(PlainPsw); + if (PlainPsw.empty() && Type==UIPASSWORD_GLOBAL) return false; - if (wcslen(PlainPsw)>=MAXPASSWORD) + if (PlainPsw.size()>=MAXPASSWORD) { - PlainPsw[MAXPASSWORD-1]=0; + PlainPsw.erase(MAXPASSWORD-1); uiMsg(UIERROR_TRUNCPSW,MAXPASSWORD-1); } if (!StdinRedirected && Type==UIPASSWORD_GLOBAL) { eprintf(St(MReAskPsw)); - wchar CmpStr[MAXPASSWORD]; - GetPasswordText(CmpStr,ASIZE(CmpStr)); - if (*CmpStr==0 || wcscmp(PlainPsw,CmpStr)!=0) + std::wstring CmpStr; + GetPasswordText(CmpStr); + if (CmpStr.empty() || PlainPsw!=CmpStr) { eprintf(St(MNotMatchPsw)); - cleandata(PlainPsw,sizeof(PlainPsw)); - cleandata(CmpStr,sizeof(CmpStr)); + cleandata(&PlainPsw[0],PlainPsw.size()*sizeof(PlainPsw[0])); + cleandata(&CmpStr[0],CmpStr.size()*sizeof(CmpStr[0])); continue; } - cleandata(CmpStr,sizeof(CmpStr)); + cleandata(&CmpStr[0],CmpStr.size()*sizeof(CmpStr[0])); } - Password->Set(PlainPsw); - cleandata(PlainPsw,sizeof(PlainPsw)); + Password->Set(PlainPsw.c_str()); + cleandata(&PlainPsw[0],PlainPsw.size()*sizeof(PlainPsw[0])); break; } return true; @@ -264,14 +255,17 @@ bool GetConsolePassword(UIPASSWORD_TYPE Type,const wchar *FileName,SecPassword * #ifndef SILENT -bool getwstr(wchar *str,size_t n) +bool getwstr(std::wstring &str) { // Print buffered prompt title function before waiting for input. fflush(stderr); QuitIfInputProhibited(); - *str=0; + str.clear(); + + const size_t MaxRead=MAXPATHSIZE; // Large enough to read a file name. + #if defined(_WIN_ALL) // fgetws does not work well with non-English text in Windows, // so we do not use it. @@ -279,11 +273,11 @@ bool getwstr(wchar *str,size_t n) { // fgets does not work well with pipes in Windows in our test. // Let's use files. - Array StrA(n*4); // Up to 4 UTF-8 characters per wchar_t. + std::vector StrA(MaxRead*4); // Up to 4 UTF-8 characters per wchar_t. File SrcFile; SrcFile.SetHandleType(FILE_HANDLESTD); SrcFile.SetLineInputMode(true); - int ReadSize=SrcFile.Read(&StrA[0],StrA.Size()-1); + int ReadSize=SrcFile.Read(&StrA[0],StrA.size()-1); if (ReadSize<=0) { // Looks like stdin is a null device. We can enter to infinite loop @@ -297,19 +291,23 @@ bool getwstr(wchar *str,size_t n) // use "chcp" in console. But we avoid OEM to ANSI conversion, // because we also want to handle ANSI files redirection correctly, // like "rar ... < ansifile.txt". - CharToWide(&StrA[0],str,n); - cleandata(&StrA[0],StrA.Size()); // We can use this function to enter passwords. + CharToWide(&StrA[0],str); + cleandata(&StrA[0],StrA.size()); // We can use this function to enter passwords. } else { + std::vector Buf(MaxRead); // Up to 4 UTF-8 characters per wchar_t. DWORD ReadSize=0; - if (ReadConsole(GetStdHandle(STD_INPUT_HANDLE),str,DWORD(n-1),&ReadSize,NULL)==0) + if (ReadConsole(GetStdHandle(STD_INPUT_HANDLE),&Buf[0],(DWORD)Buf.size()-1,&ReadSize,NULL)==0) return false; - str[ReadSize]=0; + Buf[ReadSize]=0; + str=Buf.data(); } #else - if (fgetws(str,n,stdin)==NULL) + std::vector Buf(MaxRead); // Up to 4 UTF-8 characters per wchar_t. + if (fgetws(&Buf[0],Buf.size(),stdin)==NULL) ErrHandler.Exit(RARX_USERBREAK); // Avoid infinite Ask() loop. + str=Buf.data(); #endif RemoveLF(str); return true; @@ -361,8 +359,8 @@ int Ask(const wchar *AskStr) eprintf(L"[%c]%ls",Item[I][KeyPos],&Item[I][KeyPos+1]); } eprintf(L" "); - wchar Str[50]; - getwstr(Str,ASIZE(Str)); + std::wstring Str; + getwstr(Str); wchar Ch=toupperw(Str[0]); for (int I=0;I[{key};"{string}"p used to redefine // a keyboard key on some terminals. @@ -389,18 +387,16 @@ static bool IsCommentUnsafe(const wchar *Data,size_t Size) } -void OutComment(const wchar *Comment,size_t Size) +void OutComment(const std::wstring &Comment) { - if (IsCommentUnsafe(Comment,Size)) + if (IsCommentUnsafe(Comment)) return; const size_t MaxOutSize=0x400; - for (size_t I=0;I>1)^0xEDB88320 : (C>>1); CRCTab[I]=C; } + +#ifdef USE_NEON_CRC32 + #ifdef _APPLE + // getauxval isn't available in OS X + uint Value=0; + size_t Size=sizeof(Value); + int RetCode=sysctlbyname("hw.optional.armv8_crc32",&Value,&Size,NULL,0); + CRC_Neon=RetCode==0 && Value!=0; + #else + CRC_Neon=(getauxval(AT_HWCAP) & HWCAP_CRC32)!=0; + #endif +#endif + } @@ -47,7 +64,7 @@ static void InitTables() for (uint I=0;I<256;I++) // Build additional lookup tables. { uint C=crc_tables[0][I]; - for (uint J=1;J<8;J++) + for (uint J=1;J<16;J++) { C=crc_tables[0][(byte)C]^(C>>8); crc_tables[J][I]=C; @@ -63,28 +80,66 @@ uint CRC32(uint StartCRC,const void *Addr,size_t Size) { byte *Data=(byte *)Addr; +#ifdef USE_NEON_CRC32 + if (CRC_Neon) + { + for (;Size>=8;Size-=8,Data+=8) +#ifdef __clang__ + StartCRC = __builtin_arm_crc32d(StartCRC, RawGet8(Data)); +#else + StartCRC = __builtin_aarch64_crc32x(StartCRC, RawGet8(Data)); +#endif + for (;Size>0;Size--,Data++) // Process left data. +#ifdef __clang__ + StartCRC = __builtin_arm_crc32b(StartCRC, *Data); +#else + StartCRC = __builtin_aarch64_crc32b(StartCRC, *Data); +#endif + return StartCRC; + } +#endif + #ifdef USE_SLICING - // Align Data to 8 for better performance. - for (;Size>0 && ((size_t)Data & 7);Size--,Data++) + // Align Data to 16 for better performance and to avoid ALLOW_MISALIGNED + // check below. + for (;Size>0 && ((size_t)Data & 15)!=0;Size--,Data++) StartCRC=crc_tables[0][(byte)(StartCRC^Data[0])]^(StartCRC>>8); - for (;Size>=8;Size-=8,Data+=8) + // 2023.12.06: We switched to slicing-by-16, which seems to be faster than + // slicing-by-8 on modern CPUs. Slicing-by-32 would require 32 KB for tables + // and could be limited by L1 cache size on some CPUs. + for (;Size>=16;Size-=16,Data+=16) { #ifdef BIG_ENDIAN - StartCRC ^= Data[0]|(Data[1] << 8)|(Data[2] << 16)|(Data[3] << 24); - uint NextData = Data[4]|(Data[5] << 8)|(Data[6] << 16)|(Data[7] << 24); + StartCRC ^= RawGet4(Data); + uint D1 = RawGet4(Data+4); + uint D2 = RawGet4(Data+8); + uint D3 = RawGet4(Data+12); #else + // We avoid RawGet4 here for performance reason, to access uint32 + // directly even if ALLOW_MISALIGNED isn't defined. We can do it, + // because we aligned 'Data' above. StartCRC ^= *(uint32 *) Data; - uint NextData = *(uint32 *) (Data+4); + uint D1 = *(uint32 *) (Data+4); + uint D2 = *(uint32 *) (Data+8); + uint D3 = *(uint32 *) (Data+12); #endif - StartCRC = crc_tables[7][(byte) StartCRC ] ^ - crc_tables[6][(byte)(StartCRC >> 8) ] ^ - crc_tables[5][(byte)(StartCRC >> 16)] ^ - crc_tables[4][(byte)(StartCRC >> 24)] ^ - crc_tables[3][(byte) NextData ] ^ - crc_tables[2][(byte)(NextData >> 8) ] ^ - crc_tables[1][(byte)(NextData >> 16)] ^ - crc_tables[0][(byte)(NextData >> 24)]; + StartCRC = crc_tables[15][(byte) StartCRC ] ^ + crc_tables[14][(byte)(StartCRC >> 8) ] ^ + crc_tables[13][(byte)(StartCRC >> 16)] ^ + crc_tables[12][(byte)(StartCRC >> 24)] ^ + crc_tables[11][(byte) D1 ] ^ + crc_tables[10][(byte)(D1 >> 8) ] ^ + crc_tables[ 9][(byte)(D1 >> 16)] ^ + crc_tables[ 8][(byte)(D1 >> 24)] ^ + crc_tables[ 7][(byte) D2 ] ^ + crc_tables[ 6][(byte)(D2 >> 8)] ^ + crc_tables[ 5][(byte)(D2 >> 16)] ^ + crc_tables[ 4][(byte)(D2 >> 24)] ^ + crc_tables[ 3][(byte) D3 ] ^ + crc_tables[ 2][(byte)(D3 >> 8)] ^ + crc_tables[ 1][(byte)(D3 >> 16)] ^ + crc_tables[ 0][(byte)(D3 >> 24)]; } #endif @@ -110,74 +165,6 @@ ushort Checksum14(ushort StartCRC,const void *Addr,size_t Size) #endif -#if 0 -static uint64 crc64_tables[8][256]; // Tables for Slicing-by-8 for CRC64. - -void InitCRC64(uint64 *CRCTab) -{ - const uint64 poly=INT32TO64(0xC96C5795, 0xD7870F42); // 0xC96C5795D7870F42; - for (uint I=0;I<256;I++) - { - uint64 C=I; - for (uint J=0;J<8;J++) - C=(C & 1) ? (C>>1)^poly: (C>>1); - CRCTab[I]=C; - } -} - - -static void InitTables64() -{ - InitCRC64(crc64_tables[0]); - - for (uint I=0;I<256;I++) // Build additional lookup tables. - { - uint64 C=crc64_tables[0][I]; - for (uint J=1;J<8;J++) - { - C=crc64_tables[0][(byte)C]^(C>>8); - crc64_tables[J][I]=C; - } - } -} - - -// We cannot place the intialization to CRC64(), because we use this function -// in multithreaded mode and it conflicts with multithreading. -struct CallInitCRC64 {CallInitCRC64() {InitTables64();}} static CallInit64; - -uint64 CRC64(uint64 StartCRC,const void *Addr,size_t Size) -{ - byte *Data=(byte *)Addr; - - // Align Data to 8 for better performance. - for (;Size>0 && ((size_t)Data & 7)!=0;Size--,Data++) - StartCRC=crc64_tables[0][(byte)(StartCRC^Data[0])]^(StartCRC>>8); - - for (byte *DataEnd=Data+Size/8*8; Data> 8 ) ] ^ - crc64_tables[ 5 ] [ ( byte ) (Index >> 16 ) ] ^ - crc64_tables[ 4 ] [ ( byte ) (Index >> 24 ) ] ^ - crc64_tables[ 3 ] [ ( byte ) (Index >> 32 ) ] ^ - crc64_tables[ 2 ] [ ( byte ) (Index >> 40 ) ] ^ - crc64_tables[ 1 ] [ ( byte ) (Index >> 48 ) ] ^ - crc64_tables[ 0 ] [ ( byte ) (Index >> 56 ) ] ; - } - - for (Size%=8;Size>0;Size--,Data++) // Process left data. - StartCRC=crc64_tables[0][(byte)(StartCRC^Data[0])]^(StartCRC>>8); - - return StartCRC; -} #if 0 @@ -186,6 +173,11 @@ struct TestCRCStruct {TestCRCStruct() {TestCRC();exit(0);}} GlobalTesCRC; void TestCRC() { + // This function is invoked from global object and _SSE_Version is global + // and can be initialized after this function. So we explicitly initialize + // it here to enable SSE support in Blake2sp. + _SSE_Version=GetSSEVersion(); + const uint FirstSize=300; byte b[FirstSize]; @@ -251,23 +243,38 @@ void TestCRC() const size_t BufSize=0x100000; byte *Buf=new byte[BufSize]; - memset(Buf,0,BufSize); + GetRnd(Buf,BufSize); clock_t StartTime=clock(); r32=0xffffffff; - const uint BufCount=5000; + const uint64 BufCount=5000; for (uint I=0;I>16); + Key15[3]+=ushort(P+(CRCTab[P]>>16)); } } -void CryptData::SetAV15Encryption() -{ - InitCRC32(CRCTab); - Method=CRYPT_RAR15; - Key15[0]=0x4765; - Key15[1]=0x9021; - Key15[2]=0x7382; - Key15[3]=0x5215; -} - - void CryptData::SetCmt13Encryption() { Method=CRYPT_RAR13; @@ -68,7 +55,7 @@ void CryptData::Crypt15(byte *Data,size_t Count) { Key15[0]+=0x1234; Key15[1]^=CRCTab[(Key15[0] & 0x1fe)>>1]; - Key15[2]-=CRCTab[(Key15[0] & 0x1fe)>>1]>>16; + Key15[2]-=ushort(CRCTab[(Key15[0] & 0x1fe)>>1]>>16); Key15[0]^=Key15[2]; Key15[3]=rotrs(Key15[3]&0xffff,1,16)^Key15[1]; Key15[3]=rotrs(Key15[3]&0xffff,1,16); diff --git a/vendor/unrar/crypt5.cpp b/vendor/unrar/crypt5.cpp index bb9b2bab2c..2183c8f081 100644 --- a/vendor/unrar/crypt5.cpp +++ b/vendor/unrar/crypt5.cpp @@ -128,20 +128,12 @@ void pbkdf2(const byte *Pwd, size_t PwdLength, } -void CryptData::SetKey50(bool Encrypt,SecPassword *Password,const wchar *PwdW, +bool CryptData::SetKey50(bool Encrypt,SecPassword *Password,const wchar *PwdW, const byte *Salt,const byte *InitV,uint Lg2Cnt,byte *HashKey, byte *PswCheck) { if (Lg2Cnt>CRYPT5_KDF_LG2_COUNT_MAX) - { - // Initialize these fields to prevent uninitialized data access warnings - // by analyzing tools when accessing returned data. - if (HashKey!=nullptr) - memset(HashKey,0,SHA256_DIGEST_SIZE); - if (PswCheck!=nullptr) - memset(PswCheck,0,SIZE_PSWCHECK); - return; - } + return false; byte Key[32],PswCheckValue[SHA256_DIGEST_SIZE],HashKeyValue[SHA256_DIGEST_SIZE]; bool Found=false; @@ -194,6 +186,7 @@ void CryptData::SetKey50(bool Encrypt,SecPassword *Password,const wchar *PwdW, rin.Init(Encrypt, Key, 256, InitV); cleandata(Key,sizeof(Key)); + return true; } @@ -208,6 +201,7 @@ void ConvertHashToMAC(HashValue *Value,byte *Key) Value->CRC32=0; for (uint I=0;ICRC32^=Digest[I] << ((I & 3) * 8); + Value->CRC32&=0xffffffff; // In case the variable size is larger than 32-bit. } if (Value->Type==HASH_BLAKE2) { diff --git a/vendor/unrar/dll.cpp b/vendor/unrar/dll.cpp index 31818e4980..de8796dc2d 100644 --- a/vendor/unrar/dll.cpp +++ b/vendor/unrar/dll.cpp @@ -44,22 +44,21 @@ HANDLE PASCAL RAROpenArchiveEx(struct RAROpenArchiveDataEx *r) Data->Cmd.FileArgs.AddString(L"*"); Data->Cmd.KeepBroken=(r->OpFlags&ROADOF_KEEPBROKEN)!=0; - char AnsiArcName[NM]; - *AnsiArcName=0; - if (r->ArcName!=NULL) + std::string AnsiArcName; + if (r->ArcName!=nullptr) { - strncpyz(AnsiArcName,r->ArcName,ASIZE(AnsiArcName)); + AnsiArcName=r->ArcName; #ifdef _WIN_ALL if (!AreFileApisANSI()) - { - OemToCharBuffA(r->ArcName,AnsiArcName,ASIZE(AnsiArcName)); - AnsiArcName[ASIZE(AnsiArcName)-1]=0; - } + IntToExt(r->ArcName,AnsiArcName); #endif } - wchar ArcName[NM]; - GetWideName(AnsiArcName,r->ArcNameW,ArcName,ASIZE(ArcName)); + std::wstring ArcName; + if (r->ArcNameW!=nullptr && *r->ArcNameW!=0) + ArcName=r->ArcNameW; + else + CharToWide(AnsiArcName,ArcName); Data->Cmd.AddArcName(ArcName); Data->Cmd.Overwrite=OVERWRITE_ALL; @@ -113,35 +112,35 @@ HANDLE PASCAL RAROpenArchiveEx(struct RAROpenArchiveDataEx *r) if (Data->Arc.FirstVolume) r->Flags|=ROADF_FIRSTVOLUME; - Array CmtDataW; - if (r->CmtBufSize!=0 && Data->Arc.GetComment(&CmtDataW)) + std::wstring CmtDataW; + if (r->CmtBufSize!=0 && Data->Arc.GetComment(CmtDataW)) { if (r->CmtBufW!=NULL) { - CmtDataW.Push(0); - size_t Size=wcslen(&CmtDataW[0])+1; +// CmtDataW.push_back(0); + size_t Size=wcslen(CmtDataW.data())+1; r->CmtState=Size>r->CmtBufSize ? ERAR_SMALL_BUF:1; r->CmtSize=(uint)Min(Size,r->CmtBufSize); - memcpy(r->CmtBufW,&CmtDataW[0],(r->CmtSize-1)*sizeof(*r->CmtBufW)); + memcpy(r->CmtBufW,CmtDataW.data(),(r->CmtSize-1)*sizeof(*r->CmtBufW)); r->CmtBufW[r->CmtSize-1]=0; } else if (r->CmtBuf!=NULL) { - Array CmtData(CmtDataW.Size()*4+1); - memset(&CmtData[0],0,CmtData.Size()); - WideToChar(&CmtDataW[0],&CmtData[0],CmtData.Size()-1); - size_t Size=strlen(&CmtData[0])+1; + std::vector CmtData(CmtDataW.size()*4+1); + WideToChar(&CmtDataW[0],&CmtData[0],CmtData.size()-1); + size_t Size=strlen(CmtData.data())+1; r->CmtState=Size>r->CmtBufSize ? ERAR_SMALL_BUF:1; r->CmtSize=(uint)Min(Size,r->CmtBufSize); - memcpy(r->CmtBuf,&CmtData[0],r->CmtSize-1); + memcpy(r->CmtBuf,CmtData.data(),r->CmtSize-1); r->CmtBuf[r->CmtSize-1]=0; } } else r->CmtState=r->CmtSize=0; + Data->Extract.ExtractArchiveInit(Data->Arc); return (HANDLE)Data; } @@ -183,8 +182,7 @@ int PASCAL RARCloseArchive(HANDLE hArcData) int PASCAL RARReadHeader(HANDLE hArcData,struct RARHeaderData *D) { - struct RARHeaderDataEx X; - memset(&X,0,sizeof(X)); + struct RARHeaderDataEx X{}; int Code=RARReadHeaderEx(hArcData,&X); @@ -242,14 +240,18 @@ int PASCAL RARReadHeaderEx(HANDLE hArcData,struct RARHeaderDataEx *D) else return Code; } - wcsncpy(D->ArcNameW,Data->Arc.FileName,ASIZE(D->ArcNameW)); + wcsncpyz(D->ArcNameW,Data->Arc.FileName.c_str(),ASIZE(D->ArcNameW)); WideToChar(D->ArcNameW,D->ArcName,ASIZE(D->ArcName)); + if (D->ArcNameEx!=nullptr) + wcsncpyz(D->ArcNameEx,Data->Arc.FileName.c_str(),D->ArcNameExSize); - wcsncpy(D->FileNameW,hd->FileName,ASIZE(D->FileNameW)); + wcsncpyz(D->FileNameW,hd->FileName.c_str(),ASIZE(D->FileNameW)); WideToChar(D->FileNameW,D->FileName,ASIZE(D->FileName)); #ifdef _WIN_ALL CharToOemA(D->FileName,D->FileName); #endif + if (D->FileNameEx!=nullptr) + wcsncpyz(D->FileNameEx,hd->FileName.c_str(),D->FileNameExSize); D->Flags=0; if (hd->SplitBefore) @@ -311,7 +313,7 @@ int PASCAL RARReadHeaderEx(HANDLE hArcData,struct RARHeaderDataEx *D) // this RedirNameSize check sometimes later. if (hd->RedirType!=FSREDIR_NONE && D->RedirName!=NULL && D->RedirNameSize>0 && D->RedirNameSize<100000) - wcsncpyz(D->RedirName,hd->RedirName,D->RedirNameSize); + wcsncpyz(D->RedirName,hd->RedirName.c_str(),D->RedirNameSize); D->DirTarget=hd->DirTarget; } catch (RAR_EXIT ErrCode) @@ -346,50 +348,52 @@ int PASCAL ProcessFile(HANDLE hArcData,int Operation,char *DestPath,char *DestNa { Data->Cmd.DllOpMode=Operation; - *Data->Cmd.ExtrPath=0; - *Data->Cmd.DllDestName=0; + Data->Cmd.ExtrPath.clear(); + Data->Cmd.DllDestName.clear(); if (DestPath!=NULL) { - char ExtrPathA[NM]; - strncpyz(ExtrPathA,DestPath,ASIZE(ExtrPathA)-2); + std::string ExtrPathA=DestPath; #ifdef _WIN_ALL // We must not apply OemToCharBuffA directly to DestPath, // because we do not know DestPath length and OemToCharBuffA // does not stop at 0. - OemToCharA(ExtrPathA,ExtrPathA); + IntToExt(ExtrPathA,ExtrPathA); #endif - CharToWide(ExtrPathA,Data->Cmd.ExtrPath,ASIZE(Data->Cmd.ExtrPath)); - AddEndSlash(Data->Cmd.ExtrPath,ASIZE(Data->Cmd.ExtrPath)); + CharToWide(ExtrPathA,Data->Cmd.ExtrPath); + AddEndSlash(Data->Cmd.ExtrPath); } if (DestName!=NULL) { - char DestNameA[NM]; - strncpyz(DestNameA,DestName,ASIZE(DestNameA)-2); + std::string DestNameA=DestName; #ifdef _WIN_ALL // We must not apply OemToCharBuffA directly to DestName, // because we do not know DestName length and OemToCharBuffA // does not stop at 0. - OemToCharA(DestNameA,DestNameA); + IntToExt(DestNameA,DestNameA); #endif - CharToWide(DestNameA,Data->Cmd.DllDestName,ASIZE(Data->Cmd.DllDestName)); + CharToWide(DestNameA,Data->Cmd.DllDestName); } if (DestPathW!=NULL) { - wcsncpy(Data->Cmd.ExtrPath,DestPathW,ASIZE(Data->Cmd.ExtrPath)); - AddEndSlash(Data->Cmd.ExtrPath,ASIZE(Data->Cmd.ExtrPath)); + Data->Cmd.ExtrPath=DestPathW; + AddEndSlash(Data->Cmd.ExtrPath); } if (DestNameW!=NULL) - wcsncpyz(Data->Cmd.DllDestName,DestNameW,ASIZE(Data->Cmd.DllDestName)); + Data->Cmd.DllDestName=DestNameW; - wcsncpyz(Data->Cmd.Command,Operation==RAR_EXTRACT ? L"X":L"T",ASIZE(Data->Cmd.Command)); + Data->Cmd.Command=Operation==RAR_EXTRACT ? L"X":L"T"; Data->Cmd.Test=Operation!=RAR_EXTRACT; bool Repeat=false; Data->Extract.ExtractCurrentFile(Data->Arc,Data->HeaderSize,Repeat); // Now we process extra file information if any. + // It is important to do it in the same ProcessFile(), because caller + // app can rely on this behavior, for example, to overwrite + // the extracted Mark of the Web with propagated from archive + // immediately after ProcessFile() call. // // Archive can be closed if we process volumes, next volume is missing // and current one is already removed or deleted. So we need to check @@ -456,7 +460,7 @@ void PASCAL RARSetPassword(HANDLE hArcData,char *Password) #ifndef RAR_NOCRYPT DataSet *Data=(DataSet *)hArcData; wchar PasswordW[MAXPASSWORD]; - GetWideName(Password,NULL,PasswordW,ASIZE(PasswordW)); + CharToWide(Password,PasswordW,ASIZE(PasswordW)); Data->Cmd.Password.Set(PasswordW); cleandata(PasswordW,sizeof(PasswordW)); #endif diff --git a/vendor/unrar/dll.hpp b/vendor/unrar/dll.hpp index c785ff188e..ac8d53facd 100644 --- a/vendor/unrar/dll.hpp +++ b/vendor/unrar/dll.hpp @@ -19,6 +19,7 @@ #define ERAR_MISSING_PASSWORD 22 #define ERAR_EREFERENCE 23 #define ERAR_BAD_PASSWORD 24 +#define ERAR_LARGE_DICT 25 #define RAR_OM_LIST 0 #define RAR_OM_EXTRACT 1 @@ -31,7 +32,7 @@ #define RAR_VOL_ASK 0 #define RAR_VOL_NOTIFY 1 -#define RAR_DLL_VERSION 8 +#define RAR_DLL_VERSION 9 #define RAR_HASH_NONE 0 #define RAR_HASH_CRC32 1 @@ -108,7 +109,11 @@ struct RARHeaderDataEx unsigned int CtimeHigh; unsigned int AtimeLow; unsigned int AtimeHigh; - unsigned int Reserved[988]; + wchar_t *ArcNameEx; + unsigned int ArcNameExSize; + wchar_t *FileNameEx; + unsigned int FileNameExSize; + unsigned int Reserved[982]; }; @@ -157,7 +162,7 @@ struct RAROpenArchiveDataEx enum UNRARCALLBACK_MESSAGES { UCM_CHANGEVOLUME,UCM_PROCESSDATA,UCM_NEEDPASSWORD,UCM_CHANGEVOLUMEW, - UCM_NEEDPASSWORDW + UCM_NEEDPASSWORDW,UCM_LARGEDICT }; typedef int (PASCAL *CHANGEVOLPROC)(char *ArcName,int Mode); diff --git a/vendor/unrar/encname.cpp b/vendor/unrar/encname.cpp index e1ba1ed70f..d602090ef7 100644 --- a/vendor/unrar/encname.cpp +++ b/vendor/unrar/encname.cpp @@ -11,12 +11,13 @@ EncodeFileName::EncodeFileName() -void EncodeFileName::Decode(char *Name,size_t NameSize,byte *EncName,size_t EncSize, - wchar *NameW,size_t MaxDecSize) +void EncodeFileName::Decode(const char *Name,size_t NameSize, + const byte *EncName,size_t EncSize, + std::wstring &NameW) { size_t EncPos=0,DecPos=0; byte HighByte=EncPos=EncSize) break; + // We need DecPos also for ASCII "Name", so resize() instead of push_back(). + NameW.resize(DecPos+1); NameW[DecPos++]=EncName[EncPos++]; break; case 1: if (EncPos>=EncSize) break; + NameW.resize(DecPos+1); NameW[DecPos++]=EncName[EncPos++]+(HighByte<<8); break; case 2: if (EncPos+1>=EncSize) break; + NameW.resize(DecPos+1); NameW[DecPos++]=EncName[EncPos]+(EncName[EncPos+1]<<8); EncPos+=2; break; @@ -51,17 +56,22 @@ void EncodeFileName::Decode(char *Name,size_t NameSize,byte *EncName,size_t EncS if (EncPos>=EncSize) break; byte Correction=EncName[EncPos++]; - for (Length=(Length&0x7f)+2;Length>0 && DecPos0 && DecPos0 && DecPos0 && DecPos &EncName); byte Flags; uint FlagBits; @@ -12,8 +12,8 @@ class EncodeFileName size_t DestSize; public: EncodeFileName(); - size_t Encode(char *Name,wchar *NameW,byte *EncName); - void Decode(char *Name,size_t NameSize,byte *EncName,size_t EncSize,wchar *NameW,size_t MaxDecSize); + void Encode(const std::string &Name,const std::wstring &NameW,std::vector &EncName); + void Decode(const char *Name,size_t NameSize,const byte *EncName,size_t EncSize,std::wstring &NameW); }; #endif diff --git a/vendor/unrar/errhnd.cpp b/vendor/unrar/errhnd.cpp index 97193e5ac2..b07e2f6646 100644 --- a/vendor/unrar/errhnd.cpp +++ b/vendor/unrar/errhnd.cpp @@ -26,7 +26,7 @@ void ErrorHandler::MemoryError() } -void ErrorHandler::OpenError(const wchar *FileName) +void ErrorHandler::OpenError(const std::wstring &FileName) { #ifndef SILENT OpenErrorMsg(FileName); @@ -35,7 +35,7 @@ void ErrorHandler::OpenError(const wchar *FileName) } -void ErrorHandler::CloseError(const wchar *FileName) +void ErrorHandler::CloseError(const std::wstring &FileName) { if (!UserBreak) { @@ -51,7 +51,7 @@ void ErrorHandler::CloseError(const wchar *FileName) } -void ErrorHandler::ReadError(const wchar *FileName) +void ErrorHandler::ReadError(const std::wstring &FileName) { #ifndef SILENT ReadErrorMsg(FileName); @@ -62,13 +62,13 @@ void ErrorHandler::ReadError(const wchar *FileName) } -void ErrorHandler::AskRepeatRead(const wchar *FileName,bool &Ignore,bool &Retry,bool &Quit) +void ErrorHandler::AskRepeatRead(const std::wstring &FileName,bool &Ignore,bool &Retry,bool &Quit) { SetErrorCode(RARX_READ); #if !defined(SILENT) && !defined(SFX_MODULE) if (!Silent) { - uiMsg(UIERROR_FILEREAD,UINULL,FileName); + uiMsg(UIERROR_FILEREAD,L"",FileName); SysErrMsg(); if (ReadErrIgnoreAll) Ignore=true; @@ -88,7 +88,7 @@ void ErrorHandler::AskRepeatRead(const wchar *FileName,bool &Ignore,bool &Retry, } -void ErrorHandler::WriteError(const wchar *ArcName,const wchar *FileName) +void ErrorHandler::WriteError(const std::wstring &ArcName,const std::wstring &FileName) { #ifndef SILENT WriteErrorMsg(ArcName,FileName); @@ -100,7 +100,7 @@ void ErrorHandler::WriteError(const wchar *ArcName,const wchar *FileName) #ifdef _WIN_ALL -void ErrorHandler::WriteErrorFAT(const wchar *FileName) +void ErrorHandler::WriteErrorFAT(const std::wstring &FileName) { SysErrMsg(); uiMsg(UIERROR_NTFSREQUIRED,FileName); @@ -111,7 +111,7 @@ void ErrorHandler::WriteErrorFAT(const wchar *FileName) #endif -bool ErrorHandler::AskRepeatWrite(const wchar *FileName,bool DiskFull) +bool ErrorHandler::AskRepeatWrite(const std::wstring &FileName,bool DiskFull) { #ifndef SILENT if (!Silent) @@ -129,7 +129,7 @@ bool ErrorHandler::AskRepeatWrite(const wchar *FileName,bool DiskFull) } -void ErrorHandler::SeekError(const wchar *FileName) +void ErrorHandler::SeekError(const std::wstring &FileName) { if (!UserBreak) { @@ -144,13 +144,16 @@ void ErrorHandler::SeekError(const wchar *FileName) void ErrorHandler::GeneralErrMsg(const wchar *fmt,...) { +#ifndef RARDLL va_list arglist; va_start(arglist,fmt); - wchar Msg[1024]; - vswprintf(Msg,ASIZE(Msg),fmt,arglist); + + std::wstring Msg=vwstrprintf(fmt,arglist); uiMsg(UIERROR_GENERALERRMSG,Msg); SysErrMsg(); + va_end(arglist); +#endif } @@ -161,13 +164,13 @@ void ErrorHandler::MemoryErrorMsg() } -void ErrorHandler::OpenErrorMsg(const wchar *FileName) +void ErrorHandler::OpenErrorMsg(const std::wstring &FileName) { - OpenErrorMsg(NULL,FileName); + OpenErrorMsg(L"",FileName); } -void ErrorHandler::OpenErrorMsg(const wchar *ArcName,const wchar *FileName) +void ErrorHandler::OpenErrorMsg(const std::wstring &ArcName,const std::wstring &FileName) { uiMsg(UIERROR_FILEOPEN,ArcName,FileName); SysErrMsg(); @@ -179,13 +182,13 @@ void ErrorHandler::OpenErrorMsg(const wchar *ArcName,const wchar *FileName) } -void ErrorHandler::CreateErrorMsg(const wchar *FileName) +void ErrorHandler::CreateErrorMsg(const std::wstring &FileName) { - CreateErrorMsg(NULL,FileName); + CreateErrorMsg(L"",FileName); } -void ErrorHandler::CreateErrorMsg(const wchar *ArcName,const wchar *FileName) +void ErrorHandler::CreateErrorMsg(const std::wstring &ArcName,const std::wstring &FileName) { uiMsg(UIERROR_FILECREATE,ArcName,FileName); SysErrMsg(); @@ -193,13 +196,13 @@ void ErrorHandler::CreateErrorMsg(const wchar *ArcName,const wchar *FileName) } -void ErrorHandler::ReadErrorMsg(const wchar *FileName) +void ErrorHandler::ReadErrorMsg(const std::wstring &FileName) { - ReadErrorMsg(NULL,FileName); + ReadErrorMsg(L"",FileName); } -void ErrorHandler::ReadErrorMsg(const wchar *ArcName,const wchar *FileName) +void ErrorHandler::ReadErrorMsg(const std::wstring &ArcName,const std::wstring &FileName) { uiMsg(UIERROR_FILEREAD,ArcName,FileName); SysErrMsg(); @@ -207,7 +210,7 @@ void ErrorHandler::ReadErrorMsg(const wchar *ArcName,const wchar *FileName) } -void ErrorHandler::WriteErrorMsg(const wchar *ArcName,const wchar *FileName) +void ErrorHandler::WriteErrorMsg(const std::wstring &ArcName,const std::wstring &FileName) { uiMsg(UIERROR_FILEWRITE,ArcName,FileName); SysErrMsg(); @@ -215,21 +218,21 @@ void ErrorHandler::WriteErrorMsg(const wchar *ArcName,const wchar *FileName) } -void ErrorHandler::ArcBrokenMsg(const wchar *ArcName) +void ErrorHandler::ArcBrokenMsg(const std::wstring &ArcName) { uiMsg(UIERROR_ARCBROKEN,ArcName); SetErrorCode(RARX_CRC); } -void ErrorHandler::ChecksumFailedMsg(const wchar *ArcName,const wchar *FileName) +void ErrorHandler::ChecksumFailedMsg(const std::wstring &ArcName,const std::wstring &FileName) { uiMsg(UIERROR_CHECKSUM,ArcName,FileName); SetErrorCode(RARX_CRC); } -void ErrorHandler::UnknownMethodMsg(const wchar *ArcName,const wchar *FileName) +void ErrorHandler::UnknownMethodMsg(const std::wstring &ArcName,const std::wstring &FileName) { uiMsg(UIERROR_UNKNOWNMETHOD,ArcName,FileName); ErrHandler.SetErrorCode(RARX_FATAL); @@ -332,33 +335,44 @@ void ErrorHandler::Throw(RAR_EXIT Code) if (Code==RARX_USERBREAK && !EnableBreak) return; #if !defined(SILENT) - // Do not write "aborted" when just displaying online help. - if (Code!=RARX_SUCCESS && Code!=RARX_USERERROR) - mprintf(L"\n%s\n",St(MProgAborted)); + if (Code!=RARX_SUCCESS) + if (Code==RARX_USERERROR) // Do not write "aborted" when just displaying the online help. + mprintf(L"\n"); // For consistency with other errors, which print the final "\n". + else + mprintf(L"\n%s\n",St(MProgAborted)); #endif SetErrorCode(Code); throw Code; } -bool ErrorHandler::GetSysErrMsg(wchar *Msg,size_t Size) +bool ErrorHandler::GetSysErrMsg(std::wstring &Msg) { #ifndef SILENT #ifdef _WIN_ALL int ErrType=GetLastError(); if (ErrType!=0) - return FormatMessage(FORMAT_MESSAGE_FROM_SYSTEM|FORMAT_MESSAGE_IGNORE_INSERTS, - NULL,ErrType,MAKELANGID(LANG_NEUTRAL,SUBLANG_DEFAULT), - Msg,(DWORD)Size,NULL)!=0; + { + wchar *Buf=nullptr; + if (FormatMessage(FORMAT_MESSAGE_FROM_SYSTEM| + FORMAT_MESSAGE_IGNORE_INSERTS|FORMAT_MESSAGE_ALLOCATE_BUFFER, + NULL,ErrType,MAKELANGID(LANG_NEUTRAL,SUBLANG_DEFAULT), + (LPTSTR)&Buf,0,NULL)!=0) + { + Msg=Buf; + LocalFree(Buf); + return true; + } + } #endif -#if defined(_UNIX) || defined(_EMX) +#ifdef _UNIX if (errno!=0) { char *err=strerror(errno); if (err!=NULL) { - CharToWide(err,Msg,Size); + CharToWide(err,Msg); return true; } } @@ -371,31 +385,26 @@ bool ErrorHandler::GetSysErrMsg(wchar *Msg,size_t Size) void ErrorHandler::SysErrMsg() { #ifndef SILENT - wchar Msg[1024]; - if (!GetSysErrMsg(Msg,ASIZE(Msg))) + std::wstring Msg; + if (!GetSysErrMsg(Msg)) return; #ifdef _WIN_ALL - wchar *CurMsg=Msg; - while (CurMsg!=NULL) // Print string with \r\n as several strings to multiple lines. + // Print string with \r\n as several strings to multiple lines. + size_t Pos=0; + while (Pos!=std::wstring::npos) { - while (*CurMsg=='\r' || *CurMsg=='\n') - CurMsg++; - if (*CurMsg==0) + while (Msg[Pos]=='\r' || Msg[Pos]=='\n') + Pos++; + if (Pos==Msg.size()) break; - wchar *EndMsg=wcschr(CurMsg,'\r'); - if (EndMsg==NULL) - EndMsg=wcschr(CurMsg,'\n'); - if (EndMsg!=NULL) - { - *EndMsg=0; - EndMsg++; - } + size_t EndPos=Msg.find_first_of(L"\r\n",Pos); + std::wstring CurMsg=Msg.substr(Pos,EndPos==std::wstring::npos ? EndPos:EndPos-Pos); uiMsg(UIERROR_SYSERRMSG,CurMsg); - CurMsg=EndMsg; + Pos=EndPos; } #endif -#if defined(_UNIX) || defined(_EMX) +#ifdef _UNIX uiMsg(UIERROR_SYSERRMSG,Msg); #endif diff --git a/vendor/unrar/errhnd.hpp b/vendor/unrar/errhnd.hpp index 06f4f616fd..3b558b102a 100644 --- a/vendor/unrar/errhnd.hpp +++ b/vendor/unrar/errhnd.hpp @@ -33,26 +33,26 @@ class ErrorHandler ErrorHandler(); void Clean(); void MemoryError(); - void OpenError(const wchar *FileName); - void CloseError(const wchar *FileName); - void ReadError(const wchar *FileName); - void AskRepeatRead(const wchar *FileName,bool &Ignore,bool &Retry,bool &Quit); - void WriteError(const wchar *ArcName,const wchar *FileName); - void WriteErrorFAT(const wchar *FileName); - bool AskRepeatWrite(const wchar *FileName,bool DiskFull); - void SeekError(const wchar *FileName); + void OpenError(const std::wstring &FileName); + void CloseError(const std::wstring &FileName); + void ReadError(const std::wstring &FileName); + void AskRepeatRead(const std::wstring &FileName,bool &Ignore,bool &Retry,bool &Quit); + void WriteError(const std::wstring &ArcName,const std::wstring &FileName); + void WriteErrorFAT(const std::wstring &FileName); + bool AskRepeatWrite(const std::wstring &FileName,bool DiskFull); + void SeekError(const std::wstring &FileName); void GeneralErrMsg(const wchar *fmt,...); void MemoryErrorMsg(); - void OpenErrorMsg(const wchar *FileName); - void OpenErrorMsg(const wchar *ArcName,const wchar *FileName); - void CreateErrorMsg(const wchar *FileName); - void CreateErrorMsg(const wchar *ArcName,const wchar *FileName); - void ReadErrorMsg(const wchar *FileName); - void ReadErrorMsg(const wchar *ArcName,const wchar *FileName); - void WriteErrorMsg(const wchar *ArcName,const wchar *FileName); - void ArcBrokenMsg(const wchar *ArcName); - void ChecksumFailedMsg(const wchar *ArcName,const wchar *FileName); - void UnknownMethodMsg(const wchar *ArcName,const wchar *FileName); + void OpenErrorMsg(const std::wstring &FileName); + void OpenErrorMsg(const std::wstring &ArcName,const std::wstring &FileName); + void CreateErrorMsg(const std::wstring &FileName); + void CreateErrorMsg(const std::wstring &ArcName,const std::wstring &FileName); + void ReadErrorMsg(const std::wstring &FileName); + void ReadErrorMsg(const std::wstring &ArcName,const std::wstring &FileName); + void WriteErrorMsg(const std::wstring &ArcName,const std::wstring &FileName); + void ArcBrokenMsg(const std::wstring &ArcName); + void ChecksumFailedMsg(const std::wstring &ArcName,const std::wstring &FileName); + void UnknownMethodMsg(const std::wstring &ArcName,const std::wstring &FileName); void Exit(RAR_EXIT ExitCode); void SetErrorCode(RAR_EXIT Code); RAR_EXIT GetErrorCode() {return ExitCode;} @@ -60,7 +60,7 @@ class ErrorHandler void SetSignalHandlers(bool Enable); void Throw(RAR_EXIT Code); void SetSilent(bool Mode) {Silent=Mode;} - bool GetSysErrMsg(wchar *Msg,size_t Size); + bool GetSysErrMsg(std::wstring &Msg); void SysErrMsg(); int GetSystemErrorCode(); void SetSystemErrorCode(int Code); diff --git a/vendor/unrar/extinfo.cpp b/vendor/unrar/extinfo.cpp index 048e3a4412..b3fe7495b8 100644 --- a/vendor/unrar/extinfo.cpp +++ b/vendor/unrar/extinfo.cpp @@ -19,7 +19,7 @@ // RAR2 service header extra records. #ifndef SFX_MODULE -void SetExtraInfo20(CommandData *Cmd,Archive &Arc,wchar *Name) +void SetExtraInfo20(CommandData *Cmd,Archive &Arc,const std::wstring &Name) { #ifdef _WIN_ALL if (Cmd->Test) @@ -40,12 +40,12 @@ void SetExtraInfo20(CommandData *Cmd,Archive &Arc,wchar *Name) // RAR3 and RAR5 service header extra records. -void SetExtraInfo(CommandData *Cmd,Archive &Arc,wchar *Name) +void SetExtraInfo(CommandData *Cmd,Archive &Arc,const std::wstring &Name) { #ifdef _UNIX if (!Cmd->Test && Cmd->ProcessOwners && Arc.Format==RARFMT15 && Arc.SubHead.CmpName(SUBHEAD_TYPE_UOWNER)) - ExtractUnixOwner30(Arc,Name); + ExtractUnixOwner30(Arc,Name.c_str()); #endif #ifdef _WIN_ALL if (!Cmd->Test && Cmd->ProcessOwners && Arc.SubHead.CmpName(SUBHEAD_TYPE_ACL)) @@ -57,7 +57,7 @@ void SetExtraInfo(CommandData *Cmd,Archive &Arc,wchar *Name) // Extra data stored directly in file header. -void SetFileHeaderExtra(CommandData *Cmd,Archive &Arc,wchar *Name) +void SetFileHeaderExtra(CommandData *Cmd,Archive &Arc,const std::wstring &Name) { #ifdef _UNIX if (Cmd->ProcessOwners && Arc.Format==RARFMT50 && Arc.FileHead.UnixOwnerSet) @@ -68,39 +68,34 @@ void SetFileHeaderExtra(CommandData *Cmd,Archive &Arc,wchar *Name) -// Calculate a number of path components except \. and \.. -static int CalcAllowedDepth(const wchar *Name) +// Calculate the number of path components except \. and \.. +static int CalcAllowedDepth(const std::wstring &Name) { int AllowedDepth=0; - while (*Name!=0) - { - if (IsPathDiv(Name[0]) && Name[1]!=0 && !IsPathDiv(Name[1])) + for (size_t I=0;I=ASIZE(Path)) - return true; // It should not be that long, skip. - wcsncpyz(Path,Name,ASIZE(Path)); - for (wchar *s=Path+wcslen(Path)-1;s>Path;s--) - if (IsPathDiv(*s)) + if (Path.empty()) // So we can safely use Path.size()-1 below. + return false; + for (size_t I=Path.size()-1;I>0;I--) + if (IsPathDiv(Path[I])) { - *s=0; + Path.erase(I); FindData FD; if (FindFile::FastFind(Path,&FD,true) && (FD.IsLink || !FD.IsDir)) return true; @@ -109,69 +104,7 @@ static bool LinkInPath(const wchar *Name) } -// Delete symbolic links in file path, if any, and replace them by directories. -// Prevents extracting files outside of destination folder with symlink chains. -bool LinksToDirs(const wchar *SrcName,const wchar *SkipPart,std::wstring &LastChecked) -{ - // Unlike Unix, Windows doesn't expand lnk1 in symlink targets like - // "lnk1/../dir", but converts the path to "dir". In Unix we need to call - // this function to prevent placing unpacked files outside of destination - // folder if previously we unpacked "dir/lnk1" -> "..", - // "dir/lnk2" -> "lnk1/.." and "dir/lnk2/anypath/poc.txt". - // We may still need this function to prevent abusing symlink chains - // in link source path if we remove detection of such chains - // in IsRelativeSymlinkSafe. This function seems to make other symlink - // related safety checks redundant, but for now we prefer to keep them too. - // - // 2022.12.01: the performance impact is minimized after adding the check - // against the previous path and enabling this verification only after - // extracting a symlink with ".." in target. So we enabled it for Windows - // as well for extra safety. -//#ifdef _UNIX - wchar Path[NM]; - if (wcslen(SrcName)>=ASIZE(Path)) - return false; // It should not be that long, skip. - wcsncpyz(Path,SrcName,ASIZE(Path)); - - size_t SkipLength=wcslen(SkipPart); - - if (SkipLength>0 && wcsncmp(Path,SkipPart,SkipLength)!=0) - SkipLength=0; // Parameter validation, not really needed now. - - // Do not check parts already checked in previous path to improve performance. - for (uint I=0;Path[I]!=0 && ISkipLength) - SkipLength=I; - - wchar *Name=Path; - if (SkipLength>0) - { - // Avoid converting symlinks in destination path part specified by user. - Name+=SkipLength; - while (IsPathDiv(*Name)) - Name++; - } - - for (wchar *s=Path+wcslen(Path)-1;s>Name;s--) - if (IsPathDiv(*s)) - { - *s=0; - FindData FD; - if (FindFile::FastFind(Path,&FD,true) && FD.IsLink) -#ifdef _WIN_ALL - if (!DelDir(Path)) -#else - if (!DelFile(Path)) -#endif - return false; // Couldn't delete the symlink to replace it with directory. - } - LastChecked=SrcName; -//#endif - return true; -} - - -bool IsRelativeSymlinkSafe(CommandData *Cmd,const wchar *SrcName,const wchar *PrepSrcName,const wchar *TargetName) +bool IsRelativeSymlinkSafe(CommandData *Cmd,const std::wstring &SrcName,std::wstring PrepSrcName,const std::wstring &TargetName) { // Catch root dir based /path/file paths also as stuff like \\?\. // Do not check PrepSrcName here, it can be root based if destination path @@ -181,14 +114,13 @@ bool IsRelativeSymlinkSafe(CommandData *Cmd,const wchar *SrcName,const wchar *Pr // Number of ".." in link target. int UpLevels=0; - for (int Pos=0;*TargetName!=0;Pos++) + for (uint Pos=0;PosExtrPath); - if (ExtrPathLength>0 && wcsncmp(PrepSrcName,Cmd->ExtrPath,ExtrPathLength)==0) + size_t ExtrPathLength=Cmd->ExtrPath.size(); + if (ExtrPathLength>0 && PrepSrcName.compare(0,ExtrPathLength,Cmd->ExtrPath)==0) { - PrepSrcName+=ExtrPathLength; - while (IsPathDiv(*PrepSrcName)) - PrepSrcName++; + while (IsPathDiv(PrepSrcName[ExtrPathLength])) + ExtrPathLength++; + PrepSrcName.erase(0,ExtrPathLength); } int PrepAllowedDepth=CalcAllowedDepth(PrepSrcName); @@ -223,7 +155,7 @@ bool IsRelativeSymlinkSafe(CommandData *Cmd,const wchar *SrcName,const wchar *Pr } -bool ExtractSymlink(CommandData *Cmd,ComprDataIO &DataIO,Archive &Arc,const wchar *LinkName,bool &UpLink) +bool ExtractSymlink(CommandData *Cmd,ComprDataIO &DataIO,Archive &Arc,const std::wstring &LinkName,bool &UpLink) { // Returning true in Uplink indicates that link target might include ".." // and enables additional checks. It is ok to falsely return true here, @@ -233,20 +165,20 @@ bool ExtractSymlink(CommandData *Cmd,ComprDataIO &DataIO,Archive &Arc,const wcha UpLink=true; // Assume the target might include potentially unsafe "..". #if defined(SAVE_LINKS) && defined(_UNIX) || defined(_WIN_ALL) if (Arc.Format==RARFMT50) // For RAR5 archives we can check RedirName for both Unix and Windows. - UpLink=wcsstr(Arc.FileHead.RedirName,L"..")!=NULL; + UpLink=Arc.FileHead.RedirName.find(L"..")!=std::wstring::npos; #endif #if defined(SAVE_LINKS) && defined(_UNIX) // For RAR 3.x archives we process links even in test mode to skip link data. if (Arc.Format==RARFMT15) - return ExtractUnixLink30(Cmd,DataIO,Arc,LinkName,UpLink); + return ExtractUnixLink30(Cmd,DataIO,Arc,LinkName.c_str(),UpLink); if (Arc.Format==RARFMT50) - return ExtractUnixLink50(Cmd,LinkName,&Arc.FileHead); + return ExtractUnixLink50(Cmd,LinkName.c_str(),&Arc.FileHead); #elif defined(_WIN_ALL) // RAR 5.0 archives store link information in file header, so there is // no need to additionally test it if we do not create a file. if (Arc.Format==RARFMT50) - return CreateReparsePoint(Cmd,LinkName,&Arc.FileHead); + return CreateReparsePoint(Cmd,LinkName.c_str(),&Arc.FileHead); #endif return false; } diff --git a/vendor/unrar/extinfo.hpp b/vendor/unrar/extinfo.hpp index d8551d463d..11b89feff8 100644 --- a/vendor/unrar/extinfo.hpp +++ b/vendor/unrar/extinfo.hpp @@ -1,24 +1,23 @@ #ifndef _RAR_EXTINFO_ #define _RAR_EXTINFO_ -bool LinksToDirs(const wchar *SrcName,const wchar *SkipPart,std::wstring &LastChecked); -bool IsRelativeSymlinkSafe(CommandData *Cmd,const wchar *SrcName,const wchar *PrepSrcName,const wchar *TargetName); -bool ExtractSymlink(CommandData *Cmd,ComprDataIO &DataIO,Archive &Arc,const wchar *LinkName,bool &UpLink); +bool IsRelativeSymlinkSafe(CommandData *Cmd,const std::wstring &SrcName,std::wstring PrepSrcName,const std::wstring &TargetName); +bool ExtractSymlink(CommandData *Cmd,ComprDataIO &DataIO,Archive &Arc,const std::wstring &LinkName,bool &UpLink); #ifdef _UNIX -void SetUnixOwner(Archive &Arc,const wchar *FileName); +void SetUnixOwner(Archive &Arc,const std::wstring &FileName); #endif -bool ExtractHardlink(CommandData *Cmd,wchar *NameNew,wchar *NameExisting,size_t NameExistingSize); +bool ExtractHardlink(CommandData *Cmd,const std::wstring &NameNew,const std::wstring &NameExisting); -void GetStreamNameNTFS(Archive &Arc,wchar *StreamName,size_t MaxSize); +std::wstring GetStreamNameNTFS(Archive &Arc); #ifdef _WIN_ALL bool SetPrivilege(LPCTSTR PrivName); #endif -void SetExtraInfo20(CommandData *Cmd,Archive &Arc,wchar *Name); -void SetExtraInfo(CommandData *Cmd,Archive &Arc,wchar *Name); -void SetFileHeaderExtra(CommandData *Cmd,Archive &Arc,wchar *Name); +void SetExtraInfo20(CommandData *Cmd,Archive &Arc,const std::wstring &Name); +void SetExtraInfo(CommandData *Cmd,Archive &Arc,const std::wstring &Name); +void SetFileHeaderExtra(CommandData *Cmd,Archive &Arc,const std::wstring &Name); #endif diff --git a/vendor/unrar/extract.cpp b/vendor/unrar/extract.cpp index f2eb166572..f799e6a3e0 100644 --- a/vendor/unrar/extract.cpp +++ b/vendor/unrar/extract.cpp @@ -4,12 +4,8 @@ CmdExtract::CmdExtract(CommandData *Cmd) { CmdExtract::Cmd=Cmd; - *ArcName=0; - *DestFileName=0; - ArcAnalyzed=false; - Analyze=new AnalyzeData; - memset(Analyze,0,sizeof(*Analyze)); + Analyze={}; TotalFileCount=0; @@ -36,24 +32,21 @@ CmdExtract::~CmdExtract() { FreeAnalyzeData(); delete Unp; - delete Analyze; } void CmdExtract::FreeAnalyzeData() { - for (size_t I=0;ICommand[0]); - if (*Cmd->UseStdin==0) + if (Cmd->UseStdin.empty()) { FindData FD; - while (Cmd->GetArcName(ArcName,ASIZE(ArcName))) + while (Cmd->GetArcName(ArcName)) if (FindFile::FastFind(ArcName,&FD)) DataIO.TotalArcSize+=FD.Size; } Cmd->ArcNames.Rewind(); - while (Cmd->GetArcName(ArcName,ASIZE(ArcName))) + while (Cmd->GetArcName(ArcName)) { if (Cmd->ManualPassword) Cmd->Password.Clean(); // Clean user entered password before processing next archive. @@ -97,7 +90,7 @@ void CmdExtract::DoExtract() if (TotalFileCount==0 && Cmd->Command[0]!='I' && ErrHandler.GetErrorCode()!=RARX_BADPWD) // Not in case of wrong archive password. { - if (!PasswordCancelled) + if (!SuppressNoFilesMessage) uiMsg(UIERROR_NOFILESTOEXTRACT,ArcName); // Other error codes may explain a reason of "no files extracted" clearer, @@ -146,7 +139,7 @@ void CmdExtract::ExtractArchiveInit(Archive &Arc) EXTRACT_ARC_CODE CmdExtract::ExtractArchive() { Archive Arc(Cmd); - if (*Cmd->UseStdin!=0) + if (!Cmd->UseStdin.empty()) { Arc.SetHandleType(FILE_HANDLESTD); #ifdef USE_QOPEN @@ -155,8 +148,10 @@ EXTRACT_ARC_CODE CmdExtract::ExtractArchive() } else { -#if defined(_WIN_ALL) && !defined(SFX_MODULE) // WinRAR GUI code also resets the cache. - if (*Cmd->Command=='T' || Cmd->Test) + // We commented out "&& !defined(WINRAR)", because WinRAR GUI code resets + // the cache for usual test command, but not for test after archiving. +#if defined(_WIN_ALL) && !defined(SFX_MODULE) + if (Cmd->Command[0]=='T' || Cmd->Test) ResetFileCache(ArcName); // Reset the file cache when testing an archive. #endif if (!Arc.WOpen(ArcName)) @@ -168,8 +163,8 @@ EXTRACT_ARC_CODE CmdExtract::ExtractArchive() #if !defined(SFX_MODULE) && !defined(RARDLL) if (CmpExt(ArcName,L"rev")) { - wchar FirstVolName[NM]; - VolNameToFirstName(ArcName,FirstVolName,ASIZE(FirstVolName),true); + std::wstring FirstVolName; + VolNameToFirstName(ArcName,FirstVolName,true); // If several volume names from same volume set are specified // and current volume is not first in set and first volume is present @@ -183,7 +178,7 @@ EXTRACT_ARC_CODE CmdExtract::ExtractArchive() } #endif - mprintf(St(MNotRAR),ArcName); + mprintf(St(MNotRAR),ArcName.c_str()); #ifndef SFX_MODULE if (CmpExt(ArcName,L"rar")) @@ -198,8 +193,8 @@ EXTRACT_ARC_CODE CmdExtract::ExtractArchive() #ifndef SFX_MODULE if (Arc.Volume && !Arc.FirstVolume && !UseExactVolName) { - wchar FirstVolName[NM]; - VolNameToFirstName(ArcName,FirstVolName,ASIZE(FirstVolName),Arc.NewNumbering); + std::wstring FirstVolName; + VolNameToFirstName(ArcName,FirstVolName,Arc.NewNumbering); // If several volume names from same volume set are specified // and current volume is not first in set and first volume is present @@ -215,7 +210,7 @@ EXTRACT_ARC_CODE CmdExtract::ExtractArchive() int64 VolumeSetSize=0; // Total size of volumes after the current volume. #ifndef SFX_MODULE - if (!ArcAnalyzed && *Cmd->UseStdin==0) + if (!ArcAnalyzed && Cmd->UseStdin.empty()) { AnalyzeArchive(Arc.FileName,Arc.Volume,Arc.NewNumbering); ArcAnalyzed=true; // Avoid repeated analysis on EXTRACT_ARC_REPEAT. @@ -227,10 +222,10 @@ EXTRACT_ARC_CODE CmdExtract::ExtractArchive() #ifndef SFX_MODULE // Try to speed up extraction for independent solid volumes by starting // extraction from non-first volume if we can. - if (*Analyze->StartName!=0) + if (!Analyze.StartName.empty()) { - wcsncpyz(ArcName,Analyze->StartName,ASIZE(ArcName)); - *Analyze->StartName=0; + ArcName=Analyze.StartName; + Analyze.StartName.clear(); UseExactVolName=true; return EXTRACT_ARC_REPEAT; @@ -240,15 +235,14 @@ EXTRACT_ARC_CODE CmdExtract::ExtractArchive() // Calculate the total size of all accessible volumes. // This size is necessary to display the correct total progress indicator. - wchar NextName[NM]; - wcsncpyz(NextName,Arc.FileName,ASIZE(NextName)); + std::wstring NextName=Arc.FileName; while (true) { // First volume is already added to DataIO.TotalArcSize // in initial TotalArcSize calculation in DoExtract. // So we skip it and start from second volume. - NextVolumeName(NextName,ASIZE(NextName),!Arc.NewNumbering); + NextVolumeName(NextName,!Arc.NewNumbering); FindData FD; if (FindFile::FastFind(NextName,&FD)) VolumeSetSize+=FD.Size; @@ -260,11 +254,11 @@ EXTRACT_ARC_CODE CmdExtract::ExtractArchive() ExtractArchiveInit(Arc); - if (*Cmd->Command=='T' || *Cmd->Command=='I') + if (Cmd->Command[0]=='T' || Cmd->Command[0]=='I') Cmd->Test=true; - if (*Cmd->Command=='I') + if (Cmd->Command[0]=='I') { Cmd->DisablePercentage=true; } @@ -272,10 +266,10 @@ EXTRACT_ARC_CODE CmdExtract::ExtractArchive() uiStartArchiveExtract(!Cmd->Test,ArcName); #ifndef SFX_MODULE - if (Analyze->StartPos!=0) + if (Analyze.StartPos!=0) { - Arc.Seek(Analyze->StartPos,SEEK_SET); - Analyze->StartPos=0; + Arc.Seek(Analyze.StartPos,SEEK_SET); + Analyze.StartPos=0; } #endif @@ -336,8 +330,8 @@ bool CmdExtract::ExtractCurrentFile(Archive &Arc,size_t HeaderSize,bool &Repeat) if (HeaderType==HEAD_FILE) { // Unlike Arc.FileName, ArcName might store an old volume name here. - if (Analyze->EndPos!=0 && Analyze->EndPos==Arc.CurBlockPos && - (*Analyze->EndName==0 || wcscmp(Analyze->EndName,Arc.FileName)==0)) + if (Analyze.EndPos!=0 && Analyze.EndPos==Arc.CurBlockPos && + (Analyze.EndName.empty() || Analyze.EndName==Arc.FileName)) return false; } else @@ -376,32 +370,30 @@ bool CmdExtract::ExtractCurrentFile(Archive &Arc,size_t HeaderSize,bool &Repeat) // when reading an archive. But we prefer to do it here, because this // function is called directly in unrar.dll, so we fix bad parameters // passed to dll. Also we want to see real negative sizes in the listing - // of corrupt archive. To prevent uninitialized data access perform + // of corrupt archive. To prevent the uninitialized data access, perform // these checks after rejecting zero length and non-file headers above. if (Arc.FileHead.PackSize<0) Arc.FileHead.PackSize=0; if (Arc.FileHead.UnpSize<0) Arc.FileHead.UnpSize=0; - // 2022.03.20: We might remove this check in the future. - // It duplicates Analyze->EndPos and Analyze->EndName in all cases except - // volumes on removable media. + // This check duplicates Analyze.EndPos and Analyze.EndName + // in all cases except volumes on removable media. if (!Cmd->Recurse && MatchedArgs>=Cmd->FileArgs.ItemsCount() && AllMatchesExact) return false; int MatchType=MATCH_WILDSUBPATH; bool EqualNames=false; - wchar MatchedArg[NM]; - int MatchNumber=Cmd->IsProcessFile(Arc.FileHead,&EqualNames,MatchType,0,MatchedArg,ASIZE(MatchedArg)); - bool MatchFound=MatchNumber!=0; + std::wstring MatchedArg; + bool MatchFound=Cmd->IsProcessFile(Arc.FileHead,&EqualNames,MatchType,0,&MatchedArg)!=0; #ifndef SFX_MODULE if (Cmd->ExclPath==EXCL_BASEPATH) { - wcsncpyz(Cmd->ArcPath,MatchedArg,ASIZE(Cmd->ArcPath)); - *PointToName(Cmd->ArcPath)=0; + Cmd->ArcPath=MatchedArg; + GetPathWithSep(Cmd->ArcPath,Cmd->ArcPath); if (IsWildcard(Cmd->ArcPath)) // Cannot correctly process path*\* masks here. - *Cmd->ArcPath=0; + Cmd->ArcPath.clear(); } #endif if (MatchFound && !EqualNames) @@ -412,13 +404,13 @@ bool CmdExtract::ExtractCurrentFile(Archive &Arc,size_t HeaderSize,bool &Repeat) #if !defined(SFX_MODULE) && !defined(RARDLL) if (Arc.FileHead.SplitBefore && FirstFile && !UseExactVolName) { - wchar CurVolName[NM]; - wcsncpyz(CurVolName,ArcName,ASIZE(CurVolName)); - GetFirstVolIfFullSet(ArcName,Arc.NewNumbering,ArcName,ASIZE(ArcName)); + std::wstring StartVolName; + GetFirstVolIfFullSet(ArcName,Arc.NewNumbering,StartVolName); - if (wcsicomp(ArcName,CurVolName)!=0 && FileExist(ArcName)) + if (StartVolName!=ArcName && FileExist(StartVolName)) { - wcsncpyz(Cmd->ArcName,ArcName,ASIZE(ArcName)); // For GUI "Delete archive after extraction". + ArcName=StartVolName; + Cmd->ArcName=ArcName; // For GUI "Delete archive after extraction". // If first volume name does not match the current name and if such // volume name really exists, let's unpack from this first volume. Repeat=true; @@ -435,12 +427,11 @@ bool CmdExtract::ExtractCurrentFile(Archive &Arc,size_t HeaderSize,bool &Repeat) } } #endif - wcsncpyz(ArcName,CurVolName,ASIZE(ArcName)); } #endif - wchar ArcFileName[NM]; - ConvertPath(Arc.FileHead.FileName,ArcFileName,ASIZE(ArcFileName)); + std::wstring ArcFileName; + ConvertPath(&Arc.FileHead.FileName,&ArcFileName); if (Arc.FileHead.Version) { @@ -486,10 +477,10 @@ bool CmdExtract::ExtractCurrentFile(Archive &Arc,size_t HeaderSize,bool &Repeat) bool RefTarget=false; if (!MatchFound) - for (size_t I=0;ITest) // While harmless, it is useless for 't'. { @@ -500,11 +491,11 @@ bool CmdExtract::ExtractCurrentFile(Archive &Arc,size_t HeaderSize,bool &Repeat) // targets and it is possible that first target isn't unpacked // for some reason. Also targets might have associated service blocks // like ACLs. All this would complicate processing a lot. - wcsncpyz(DestFileName,*Cmd->TempPath!=0 ? Cmd->TempPath:Cmd->ExtrPath,ASIZE(DestFileName)); - AddEndSlash(DestFileName,ASIZE(DestFileName)); - wcsncatz(DestFileName,L"__tmp_reference_source_",ASIZE(DestFileName)); - MkTemp(DestFileName,ASIZE(DestFileName)); - MatchedRef->TmpName=wcsdup(DestFileName); + DestFileName=!Cmd->TempPath.empty() ? Cmd->TempPath:Cmd->ExtrPath; + AddEndSlash(DestFileName); + DestFileName+=L"__tmp_reference_source_"; + MkTemp(DestFileName); + MatchedRef.TmpName=DestFileName; } RefTarget=true; // Need it even for 't' to test the reference source. break; @@ -516,7 +507,7 @@ bool CmdExtract::ExtractCurrentFile(Archive &Arc,size_t HeaderSize,bool &Repeat) else MatchFound=false; // Skip only the current file for non-solid archive. - if (MatchFound || RefTarget || (SkipSolid=Arc.Solid)!=0) + if (MatchFound || RefTarget || (SkipSolid=Arc.Solid)!=false) { // First common call of uiStartFileExtract. It is done before overwrite // prompts, so if SkipSolid state is changed below, we'll need to make @@ -525,10 +516,10 @@ bool CmdExtract::ExtractCurrentFile(Archive &Arc,size_t HeaderSize,bool &Repeat) return false; if (!RefTarget) - ExtrPrepareName(Arc,ArcFileName,DestFileName,ASIZE(DestFileName)); + ExtrPrepareName(Arc,ArcFileName,DestFileName); // DestFileName can be set empty in case of excessive -ap switch. - ExtrFile=!SkipSolid && *DestFileName!=0 && !Arc.FileHead.SplitBefore; + ExtrFile=!SkipSolid && !DestFileName.empty() && !Arc.FileHead.SplitBefore; if ((Cmd->FreshFiles || Cmd->UpdateFiles) && (Command=='E' || Command=='X')) { @@ -580,7 +571,7 @@ bool CmdExtract::ExtractCurrentFile(Archive &Arc,size_t HeaderSize,bool &Repeat) #else if (!ExtrGetPassword(Arc,ArcFileName,CheckPwd.IsSet() ? &CheckPwd:NULL)) { - PasswordCancelled=true; + SuppressNoFilesMessage=true; return false; } #endif @@ -593,14 +584,14 @@ bool CmdExtract::ExtractCurrentFile(Archive &Arc,size_t HeaderSize,bool &Repeat) #endif byte PswCheck[SIZE_PSWCHECK]; - DataIO.SetEncryption(false,Arc.FileHead.CryptMethod,&FilePassword, - Arc.FileHead.SaltSet ? Arc.FileHead.Salt:NULL, + bool EncSet=DataIO.SetEncryption(false,Arc.FileHead.CryptMethod, + &FilePassword,Arc.FileHead.SaltSet ? Arc.FileHead.Salt:nullptr, Arc.FileHead.InitV,Arc.FileHead.Lg2Count, Arc.FileHead.HashKey,PswCheck); // If header is damaged, we cannot rely on password check value, // because it can be damaged too. - if (Arc.FileHead.UsePswCheck && !Arc.BrokenHeader && + if (EncSet && Arc.FileHead.UsePswCheck && !Arc.BrokenHeader && memcmp(Arc.FileHead.PswCheck,PswCheck,SIZE_PSWCHECK)!=0) { if (GlobalPassword) // For -p or Ctrl+P to avoid the infinite loop. @@ -637,13 +628,25 @@ bool CmdExtract::ExtractCurrentFile(Archive &Arc,size_t HeaderSize,bool &Repeat) else DataIO.SetEncryption(false,CRYPT_NONE,NULL,NULL,NULL,0,NULL,NULL); + // Per file symlink conversion flag. Can be turned off in unrar.dll. + bool CurConvertSymlinkPaths=ConvertSymlinkPaths; + #ifdef RARDLL - if (*Cmd->DllDestName!=0) - wcsncpyz(DestFileName,Cmd->DllDestName,ASIZE(DestFileName)); + if (!Cmd->DllDestName.empty()) + { + DestFileName=Cmd->DllDestName; + + // If unrar.dll sets the entire destination pathname, there is no + // destination path and we can't convert symlinks, because we would + // risk converting important user or system symlinks in this case. + // If DllDestName is set, it turns off our path processing and app + // invoking the library cares about everything including safety. + CurConvertSymlinkPaths=false; + } #endif if (ExtrFile && Command!='P' && !Cmd->Test && !Cmd->AbsoluteLinks && - ConvertSymlinkPaths) + CurConvertSymlinkPaths) ExtrFile=LinksToDirs(DestFileName,Cmd->ExtrPath,LastCheckedSymlink); File CurFile; @@ -651,13 +654,17 @@ bool CmdExtract::ExtractCurrentFile(Archive &Arc,size_t HeaderSize,bool &Repeat) bool LinkEntry=Arc.FileHead.RedirType!=FSREDIR_NONE; if (LinkEntry && (Arc.FileHead.RedirType!=FSREDIR_FILECOPY)) { + if (Cmd->SkipSymLinks && (Arc.FileHead.RedirType==FSREDIR_UNIXSYMLINK || + Arc.FileHead.RedirType==FSREDIR_WINSYMLINK || Arc.FileHead.RedirType==FSREDIR_JUNCTION)) + ExtrFile=false; + if (ExtrFile && Command!='P' && !Cmd->Test) { // Overwrite prompt for symbolic and hard links and when we move // a temporary file to the file reference instead of copying it. bool UserReject=false; - if (FileExist(DestFileName) && !UserReject) - FileCreate(Cmd,NULL,DestFileName,ASIZE(DestFileName),&UserReject,Arc.FileHead.UnpSize,&Arc.FileHead.mtime); + if (FileExist(DestFileName)) + FileCreate(Cmd,NULL,DestFileName,&UserReject,Arc.FileHead.UnpSize,&Arc.FileHead.mtime); if (UserReject) ExtrFile=false; } @@ -676,7 +683,13 @@ bool CmdExtract::ExtractCurrentFile(Archive &Arc,size_t HeaderSize,bool &Repeat) } else if (ExtrFile) // Create files and file copies (FSREDIR_FILECOPY). + { + // Check the dictionary size before creating a file and issuing + // any overwrite prompts. + if (!CheckWinLimit(Arc,ArcFileName)) + return false; ExtrFile=ExtrCreateFile(Arc,CurFile); + } if (!ExtrFile && Arc.Solid) { @@ -690,6 +703,9 @@ bool CmdExtract::ExtractCurrentFile(Archive &Arc,size_t HeaderSize,bool &Repeat) // a solid archive. if (!uiStartFileExtract(ArcFileName,false,false,true)) return false; + // Check the dictionary size also for skipping files. + if (!CheckWinLimit(Arc,ArcFileName)) + return false; } if (ExtrFile) { @@ -712,21 +728,21 @@ bool CmdExtract::ExtractCurrentFile(Archive &Arc,size_t HeaderSize,bool &Repeat) FileCount++; if (Command!='I' && !Cmd->DisableNames) if (SkipSolid) - mprintf(St(MExtrSkipFile),ArcFileName); + mprintf(St(MExtrSkipFile),ArcFileName.c_str()); else switch(Cmd->Test ? 'T':Command) // "Test" can be also enabled by -t switch. { case 'T': - mprintf(St(MExtrTestFile),ArcFileName); + mprintf(St(MExtrTestFile),ArcFileName.c_str()); break; #ifndef SFX_MODULE case 'P': - mprintf(St(MExtrPrinting),ArcFileName); + mprintf(St(MExtrPrinting),ArcFileName.c_str()); break; #endif case 'X': case 'E': - mprintf(St(MExtrFile),DestFileName); + mprintf(St(MExtrFile),DestFileName.c_str()); break; } if (!Cmd->DisablePercentage && !Cmd->DisableNames) @@ -774,7 +790,7 @@ bool CmdExtract::ExtractCurrentFile(Archive &Arc,size_t HeaderSize,bool &Repeat) if (Type==FSREDIR_HARDLINK || Type==FSREDIR_FILECOPY) { - wchar RedirName[NM]; + std::wstring RedirName; // 2022.11.15: Might be needed when unpacking WinRAR 5.0 links with // Unix RAR. WinRAR 5.0 used \ path separators here, when beginning @@ -783,17 +799,17 @@ bool CmdExtract::ExtractCurrentFile(Archive &Arc,size_t HeaderSize,bool &Repeat) // We must perform this conversion before ConvertPath call, // so paths mixing different slashes like \dir1/dir2\file are // processed correctly. - SlashToNative(Arc.FileHead.RedirName,RedirName,ASIZE(RedirName)); + SlashToNative(Arc.FileHead.RedirName,RedirName); - ConvertPath(RedirName,RedirName,ASIZE(RedirName)); + ConvertPath(&RedirName,&RedirName); - wchar NameExisting[NM]; - ExtrPrepareName(Arc,RedirName,NameExisting,ASIZE(NameExisting)); - if (FileCreateMode && *NameExisting!=0) // *NameExisting can be 0 in case of excessive -ap switch. + std::wstring NameExisting; + ExtrPrepareName(Arc,RedirName,NameExisting); + if (FileCreateMode && !NameExisting.empty()) // *NameExisting can be empty in case of excessive -ap switch. if (Type==FSREDIR_HARDLINK) - LinkSuccess=ExtractHardlink(Cmd,DestFileName,NameExisting,ASIZE(NameExisting)); + LinkSuccess=ExtractHardlink(Cmd,DestFileName,NameExisting); else - LinkSuccess=ExtractFileCopy(CurFile,Arc.FileName,RedirName,DestFileName,NameExisting,ASIZE(NameExisting),Arc.FileHead.UnpSize); + LinkSuccess=ExtractFileCopy(CurFile,Arc.FileName,RedirName,DestFileName,NameExisting,Arc.FileHead.UnpSize); } else if (Type==FSREDIR_UNIXSYMLINK || Type==FSREDIR_WINSYMLINK || Type==FSREDIR_JUNCTION) @@ -803,10 +819,6 @@ bool CmdExtract::ExtractCurrentFile(Archive &Arc,size_t HeaderSize,bool &Repeat) bool UpLink; LinkSuccess=ExtractSymlink(Cmd,DataIO,Arc,DestFileName,UpLink); - // Unix symlink can have its own owner data. - if (LinkSuccess) - SetFileHeaderExtra(Cmd,Arc,DestFileName); - ConvertSymlinkPaths|=LinkSuccess && UpLink; // We do not actually need to reset the cache here if we cache @@ -844,7 +856,17 @@ bool CmdExtract::ExtractCurrentFile(Archive &Arc,size_t HeaderSize,bool &Repeat) UnstoreFile(DataIO,Arc.FileHead.UnpSize); else { - Unp->Init(Arc.FileHead.WinSize,Arc.FileHead.Solid); + try + { + Unp->Init(Arc.FileHead.WinSize,Arc.FileHead.Solid); + } + catch (std::bad_alloc) + { + if (Arc.FileHead.WinSize>=0x40000000) + uiMsg(UIERROR_EXTRDICTOUTMEM,Arc.FileName,uint(Arc.FileHead.WinSize/0x40000000+(Arc.FileHead.WinSize%0x40000000!=0 ? 1 : 0))); + throw; + } + Unp->SetDestSize(Arc.FileHead.UnpSize); #ifndef SFX_MODULE // RAR 1.3 - 1.5 archives do not set per file solid flag. @@ -912,26 +934,36 @@ bool CmdExtract::ExtractCurrentFile(Archive &Arc,size_t HeaderSize,bool &Repeat) if (SkipSolid) mprintf(L"\b\b\b\b\b "); } - - // If we successfully unpacked a hard link, we wish to set its file - // attributes. Hard link shares file metadata with link target, - // so we do not need to set link time or owner. But when we overwrite - // an existing link, we can call PrepareToDelete(), which affects - // link target attributes as well. So we set link attributes to restore - // both target and link attributes if PrepareToDelete() changed them. - bool SetAttrOnly=LinkEntry && Arc.FileHead.RedirType==FSREDIR_HARDLINK && LinkSuccess; - if (!TestMode && (Command=='X' || Command=='E') && - (!LinkEntry || SetAttrOnly || Arc.FileHead.RedirType==FSREDIR_FILECOPY && LinkSuccess) && - (!BrokenFile || Cmd->KeepBroken)) + (!LinkEntry || LinkSuccess) && (!BrokenFile || Cmd->KeepBroken)) { + // Set everything for usual files and file references. + bool SetAll=!LinkEntry || Arc.FileHead.RedirType==FSREDIR_FILECOPY; + + // Set time and adjust size for usual files and references. + // Symlink time requires the special treatment and it is set directly + // after creating a symlink. + bool SetTimeAndSize=SetAll; + + // Set file attributes for usual files, references and hard links. + // Hard link shares the file metadata with link target, so we do not + // need to set link time or owner. But when we overwrite an existing + // link, we can call PrepareToDelete(), which affects link target + // attributes too. So we set link attributes to restore both target + // and link attributes if PrepareToDelete() has changed them. + bool SetAttr=SetAll || Arc.FileHead.RedirType==FSREDIR_HARDLINK; + + // Call SetFileHeaderExtra to set Unix user and group for usual files, + // references and symlinks. Unix symlink can have its own owner data. + bool SetExtra=SetAll || Arc.FileHead.RedirType==FSREDIR_UNIXSYMLINK; + // Below we use DestFileName instead of CurFile.FileName, // so we can set file attributes also for hard links, which do not // have the open CurFile. These strings are the same for other items. - if (!SetAttrOnly) + if (SetTimeAndSize) { - // We could preallocate more space that really written to broken file + // We could preallocate more space than really written to broken file // or file with crafted header. if (Preallocated>0 && (BrokenFile || DataIO.CurUnpWrite!=Preallocated)) CurFile.Truncate(); @@ -942,28 +974,33 @@ bool CmdExtract::ExtractCurrentFile(Archive &Arc,size_t HeaderSize,bool &Repeat) Cmd->xctime==EXTTIME_NONE ? NULL:&Arc.FileHead.ctime, Cmd->xatime==EXTTIME_NONE ? NULL:&Arc.FileHead.atime); CurFile.Close(); + } + if (SetExtra) SetFileHeaderExtra(Cmd,Arc,DestFileName); + if (SetTimeAndSize) CurFile.SetCloseFileTime( Cmd->xmtime==EXTTIME_NONE ? NULL:&Arc.FileHead.mtime, Cmd->xatime==EXTTIME_NONE ? NULL:&Arc.FileHead.atime); - } + if (SetAttr) + { #if defined(_WIN_ALL) && !defined(SFX_MODULE) - if (Cmd->SetCompressedAttr && - (Arc.FileHead.FileAttr & FILE_ATTRIBUTE_COMPRESSED)!=0) - SetFileCompression(DestFileName,true); - if (Cmd->ClearArc) - Arc.FileHead.FileAttr&=~FILE_ATTRIBUTE_ARCHIVE; + if (Cmd->SetCompressedAttr && + (Arc.FileHead.FileAttr & FILE_ATTRIBUTE_COMPRESSED)!=0) + SetFileCompression(DestFileName,true); + if (Cmd->ClearArc) + Arc.FileHead.FileAttr&=~FILE_ATTRIBUTE_ARCHIVE; #endif - if (!Cmd->IgnoreGeneralAttr && !SetFileAttr(DestFileName,Arc.FileHead.FileAttr)) - { - uiMsg(UIERROR_FILEATTR,Arc.FileName,DestFileName); - // Android cannot set file attributes and while UIERROR_FILEATTR - // above is handled by Android RAR silently, this call would cause - // "Operation not permitted" message for every unpacked file. - ErrHandler.SysErrMsg(); + if (!Cmd->IgnoreGeneralAttr && !SetFileAttr(DestFileName,Arc.FileHead.FileAttr)) + { + uiMsg(UIERROR_FILEATTR,Arc.FileName,DestFileName); + // Android cannot set file attributes and while UIERROR_FILEATTR + // above is handled by Android RAR silently, this call would cause + // "Operation not permitted" message for every unpacked file. + ErrHandler.SysErrMsg(); + } } PrevProcessed=true; @@ -989,42 +1026,44 @@ bool CmdExtract::ExtractCurrentFile(Archive &Arc,size_t HeaderSize,bool &Repeat) void CmdExtract::UnstoreFile(ComprDataIO &DataIO,int64 DestUnpSize) { - Array Buffer(File::CopyBufferSize()); + std::vector Buffer(File::CopyBufferSize()); while (true) { - int ReadSize=DataIO.UnpRead(&Buffer[0],Buffer.Size()); + int ReadSize=DataIO.UnpRead(Buffer.data(),Buffer.size()); if (ReadSize<=0) break; int WriteSize=ReadSize0) { - DataIO.UnpWrite(&Buffer[0],WriteSize); + DataIO.UnpWrite(Buffer.data(),WriteSize); DestUnpSize-=WriteSize; } } } -bool CmdExtract::ExtractFileCopy(File &New,wchar *ArcName,const wchar *RedirName,wchar *NameNew,wchar *NameExisting,size_t NameExistingSize,int64 UnpSize) +bool CmdExtract::ExtractFileCopy(File &New,const std::wstring &ArcName,const std::wstring &RedirName,const std::wstring &NameNew,const std::wstring &NameExisting,int64 UnpSize) { File Existing; if (!Existing.Open(NameExisting)) { + std::wstring TmpExisting=NameExisting; // NameExisting is 'const', so copy it here. + bool OpenFailed=true; // If we couldn't find the existing file, check if match is present // in temporary reference sources list. - for (size_t I=0;IDllError=ERAR_EREFERENCE; @@ -1062,20 +1100,20 @@ bool CmdExtract::ExtractFileCopy(File &New,wchar *ArcName,const wchar *RedirName } } - Array Buffer(0x100000); + std::vector Buffer(0x100000); int64 CopySize=0; while (true) { Wait(); - int ReadSize=Existing.Read(&Buffer[0],Buffer.Size()); + int ReadSize=Existing.Read(Buffer.data(),Buffer.size()); if (ReadSize==0) break; // Update only the current file progress in WinRAR, set the total to 0 // to keep it as is. It looks better for WinRAR. uiExtractProgress(CopySize,UnpSize,0,0); - New.Write(&Buffer[0],ReadSize); + New.Write(Buffer.data(),ReadSize); CopySize+=ReadSize; } @@ -1083,7 +1121,7 @@ bool CmdExtract::ExtractFileCopy(File &New,wchar *ArcName,const wchar *RedirName } -void CmdExtract::ExtrPrepareName(Archive &Arc,const wchar *ArcFileName,wchar *DestName,size_t DestSize) +void CmdExtract::ExtrPrepareName(Archive &Arc,const std::wstring &ArcFileName,std::wstring &DestName) { if (Cmd->Test) { @@ -1091,15 +1129,15 @@ void CmdExtract::ExtrPrepareName(Archive &Arc,const wchar *ArcFileName,wchar *De // This check also allows to avoid issuing "Attempting to correct... // Renaming..." messages in MakeNameCompatible() below for problematic // names like aux.txt when testing an archive. - wcsncpyz(DestName,ArcFileName,DestSize); + DestName=ArcFileName; return; } - wcsncpyz(DestName,Cmd->ExtrPath,DestSize); + DestName=Cmd->ExtrPath; - if (*Cmd->ExtrPath!=0) + if (!Cmd->ExtrPath.empty()) { - wchar LastChar=*PointToLastChar(Cmd->ExtrPath); + wchar LastChar=GetLastChar(Cmd->ExtrPath); // We need IsPathDiv check here to correctly handle Unix forward slash // in the end of destination path in Windows: rar x arc dest/ // so we call IsPathDiv first instead of just calling AddEndSlash, @@ -1108,7 +1146,7 @@ void CmdExtract::ExtrPrepareName(Archive &Arc,const wchar *ArcFileName,wchar *De if (!IsPathDiv(LastChar) && !IsDriveDiv(LastChar)) { // Destination path can be without trailing slash if it come from GUI shell. - AddEndSlash(DestName,DestSize); + AddEndSlash(DestName); } } @@ -1118,38 +1156,40 @@ void CmdExtract::ExtrPrepareName(Archive &Arc,const wchar *ArcFileName,wchar *De switch(Cmd->AppendArcNameToPath) { case APPENDARCNAME_DESTPATH: // To subdir of destination path. - wcsncatz(DestName,PointToName(Arc.FirstVolumeName),DestSize); - SetExt(DestName,NULL,DestSize); + DestName+=PointToName(Arc.FirstVolumeName); + RemoveExt(DestName); break; case APPENDARCNAME_OWNSUBDIR: // To subdir of archive own dir. - wcsncpyz(DestName,Arc.FirstVolumeName,DestSize); - SetExt(DestName,NULL,DestSize); + DestName=Arc.FirstVolumeName; + RemoveExt(DestName); break; case APPENDARCNAME_OWNDIR: // To archive own dir. - wcsncpyz(DestName,Arc.FirstVolumeName,DestSize); + DestName=Arc.FirstVolumeName; RemoveNameFromPath(DestName); break; } - AddEndSlash(DestName,DestSize); + AddEndSlash(DestName); } #endif - + // We need to modify the name below and ArcFileName is const. + std::wstring CurName=ArcFileName; #ifndef SFX_MODULE - wchar *ArcPath=*Cmd->ExclArcPath!=0 ? Cmd->ExclArcPath:Cmd->ArcPath; - size_t ArcPathLength=wcslen(ArcPath); + std::wstring &ArcPath=!Cmd->ExclArcPath.empty() ? Cmd->ExclArcPath:Cmd->ArcPath; + size_t ArcPathLength=ArcPath.size(); if (ArcPathLength>0) { - size_t NameLength=wcslen(ArcFileName); - if (NameLength>=ArcPathLength && wcsnicompc(ArcPath,ArcFileName,ArcPathLength)==0 && + size_t NameLength=CurName.size(); + if (NameLength>=ArcPathLength && wcsnicompc(ArcPath,CurName,ArcPathLength)==0 && (IsPathDiv(ArcPath[ArcPathLength-1]) || - IsPathDiv(ArcFileName[ArcPathLength]) || ArcFileName[ArcPathLength]==0)) + IsPathDiv(CurName[ArcPathLength]) || CurName[ArcPathLength]==0)) { - ArcFileName+=Min(ArcPathLength,NameLength); - while (IsPathDiv(*ArcFileName)) - ArcFileName++; - if (*ArcFileName==0) // Excessive -ap switch. + size_t Pos=Min(ArcPathLength,NameLength); + while (PosExclPath==EXCL_ABSPATH && Command=='X' && IsDriveDiv(':'); - // We do not use any user specified destination paths when extracting - // absolute paths in -ep3 mode. if (AbsPaths) - *DestName=0; + { + // We do not use a user specified destination path when extracting + // absolute paths in -ep3 mode. + wchar DiskLetter=toupperw(CurName[0]); + if (CurName[1]=='_' && IsPathDiv(CurName[2]) && DiskLetter>='A' && DiskLetter<='Z') + DestName=CurName.substr(0,1) + L':' + CurName.substr(2); + else + if (CurName[0]=='_' && CurName[1]=='_') + DestName=std::wstring(2,CPATHDIVIDER) + CurName.substr(2); + else + AbsPaths=false; // Apply the destination path even with -ep3 for not absolute path. + } if (Command=='E' || Cmd->ExclPath==EXCL_SKIPWHOLEPATH) - wcsncatz(DestName,PointToName(ArcFileName),DestSize); - else - wcsncatz(DestName,ArcFileName,DestSize); + CurName=PointToName(CurName); + if (!AbsPaths) + DestName+=CurName; #ifdef _WIN_ALL // Must do after Cmd->ArcPath processing above, so file name and arc path // trailing spaces are in sync. if (!Cmd->AllowIncompatNames) - MakeNameCompatible(DestName,DestSize); + MakeNameCompatible(DestName); #endif - - wchar DiskLetter=toupperw(DestName[0]); - - if (AbsPaths) - { - if (DestName[1]=='_' && IsPathDiv(DestName[2]) && - DiskLetter>='A' && DiskLetter<='Z') - DestName[1]=':'; - else - if (DestName[0]=='_' && DestName[1]=='_') - { - // Convert __server\share to \\server\share. - DestName[0]=CPATHDIVIDER; - DestName[1]=CPATHDIVIDER; - } - } } @@ -1212,7 +1245,7 @@ bool CmdExtract::ExtrDllGetPassword() *PasswordA=0; if (Cmd->Callback(UCM_NEEDPASSWORD,Cmd->UserData,(LPARAM)PasswordA,ASIZE(PasswordA))==-1) *PasswordA=0; - GetWideName(PasswordA,NULL,PasswordW,ASIZE(PasswordW)); + CharToWide(PasswordA,PasswordW,ASIZE(PasswordW)); cleandata(PasswordA,sizeof(PasswordA)); } Cmd->Password.Set(PasswordW); @@ -1228,7 +1261,7 @@ bool CmdExtract::ExtrDllGetPassword() #ifndef RARDLL -bool CmdExtract::ExtrGetPassword(Archive &Arc,const wchar *ArcFileName,RarCheckPassword *CheckPwd) +bool CmdExtract::ExtrGetPassword(Archive &Arc,const std::wstring &ArcFileName,RarCheckPassword *CheckPwd) { if (!Cmd->Password.IsSet()) { @@ -1244,7 +1277,7 @@ bool CmdExtract::ExtrGetPassword(Archive &Arc,const wchar *ArcFileName,RarCheckP else if (!GlobalPassword && !Arc.FileHead.Solid) { - eprintf(St(MUseCurPsw),ArcFileName); + eprintf(St(MUseCurPsw),ArcFileName.c_str()); switch(Cmd->AllYes ? 1 : Ask(St(MYesNoAll))) { case -1: @@ -1285,13 +1318,13 @@ void CmdExtract::ConvertDosPassword(Archive &Arc,SecPassword &DestPwd) #endif -void CmdExtract::ExtrCreateDir(Archive &Arc,const wchar *ArcFileName) +void CmdExtract::ExtrCreateDir(Archive &Arc,const std::wstring &ArcFileName) { if (Cmd->Test) { if (!Cmd->DisableNames) { - mprintf(St(MExtrTestFile),ArcFileName); + mprintf(St(MExtrTestFile),ArcFileName.c_str()); mprintf(L" %s",St(MOk)); } return; @@ -1307,7 +1340,7 @@ void CmdExtract::ExtrCreateDir(Archive &Arc,const wchar *ArcFileName) // File with name same as this directory exists. Propose user // to overwrite it. bool UserReject; - FileCreate(Cmd,NULL,DestFileName,ASIZE(DestFileName),&UserReject,Arc.FileHead.UnpSize,&Arc.FileHead.mtime); + FileCreate(Cmd,NULL,DestFileName,&UserReject,Arc.FileHead.UnpSize,&Arc.FileHead.mtime); DirExist=false; } if (!DirExist) @@ -1317,17 +1350,15 @@ void CmdExtract::ExtrCreateDir(Archive &Arc,const wchar *ArcFileName) if (MDCode!=MKDIR_SUCCESS && !IsNameUsable(DestFileName)) { uiMsg(UIMSG_CORRECTINGNAME,Arc.FileName); - wchar OrigName[ASIZE(DestFileName)]; - wcsncpyz(OrigName,DestFileName,ASIZE(OrigName)); + std::wstring OrigName=DestFileName; MakeNameUsable(DestFileName,true); #ifndef SFX_MODULE uiMsg(UIERROR_RENAMING,Arc.FileName,OrigName,DestFileName); #endif DirExist=FileExist(DestFileName) && IsDir(GetFileAttr(DestFileName)); - if (!DirExist) + if (!DirExist && (Cmd->AbsoluteLinks || !ConvertSymlinkPaths || + LinksToDirs(DestFileName,Cmd->ExtrPath,LastCheckedSymlink))) { - if (!Cmd->AbsoluteLinks && ConvertSymlinkPaths) - LinksToDirs(DestFileName,Cmd->ExtrPath,LastCheckedSymlink); CreatePath(DestFileName,true,Cmd->DisableNames); MDCode=MakeDir(DestFileName,!Cmd->IgnoreGeneralAttr,Arc.FileHead.FileAttr); } @@ -1338,7 +1369,7 @@ void CmdExtract::ExtrCreateDir(Archive &Arc,const wchar *ArcFileName) { if (!Cmd->DisableNames) { - mprintf(St(MCreatDir),DestFileName); + mprintf(St(MCreatDir),DestFileName.c_str()); mprintf(L" %s",St(MOk)); } PrevProcessed=true; @@ -1388,7 +1419,7 @@ bool CmdExtract::ExtrCreateFile(Archive &Arc,File &CurFile) bool UserReject; // Specify "write only" mode to avoid OpenIndiana NAS problems // with SetFileTime and read+write files. - if (!FileCreate(Cmd,&CurFile,DestFileName,ASIZE(DestFileName),&UserReject,Arc.FileHead.UnpSize,&Arc.FileHead.mtime,true)) + if (!FileCreate(Cmd,&CurFile,DestFileName,&UserReject,Arc.FileHead.UnpSize,&Arc.FileHead.mtime,true)) { Success=false; if (!UserReject) @@ -1404,23 +1435,24 @@ bool CmdExtract::ExtrCreateFile(Archive &Arc,File &CurFile) { uiMsg(UIMSG_CORRECTINGNAME,Arc.FileName); - wchar OrigName[ASIZE(DestFileName)]; - wcsncpyz(OrigName,DestFileName,ASIZE(OrigName)); + std::wstring OrigName=DestFileName; MakeNameUsable(DestFileName,true); - if (!Cmd->AbsoluteLinks && ConvertSymlinkPaths) - LinksToDirs(DestFileName,Cmd->ExtrPath,LastCheckedSymlink); - CreatePath(DestFileName,true,Cmd->DisableNames); - if (FileCreate(Cmd,&CurFile,DestFileName,ASIZE(DestFileName),&UserReject,Arc.FileHead.UnpSize,&Arc.FileHead.mtime,true)) + if (Cmd->AbsoluteLinks || !ConvertSymlinkPaths || + LinksToDirs(DestFileName,Cmd->ExtrPath,LastCheckedSymlink)) { + CreatePath(DestFileName,true,Cmd->DisableNames); + if (FileCreate(Cmd,&CurFile,DestFileName,&UserReject,Arc.FileHead.UnpSize,&Arc.FileHead.mtime,true)) + { #ifndef SFX_MODULE - uiMsg(UIERROR_RENAMING,Arc.FileName,OrigName,DestFileName); + uiMsg(UIERROR_RENAMING,Arc.FileName,OrigName,DestFileName); #endif - Success=true; + Success=true; + } + else + ErrHandler.CreateErrorMsg(Arc.FileName,DestFileName); } - else - ErrHandler.CreateErrorMsg(Arc.FileName,DestFileName); } } } @@ -1429,11 +1461,11 @@ bool CmdExtract::ExtrCreateFile(Archive &Arc,File &CurFile) } -bool CmdExtract::CheckUnpVer(Archive &Arc,const wchar *ArcFileName) +bool CmdExtract::CheckUnpVer(Archive &Arc,const std::wstring &ArcFileName) { bool WrongVer; - if (Arc.Format==RARFMT50) // Both SFX and RAR can unpack RAR 5.0 archives. - WrongVer=Arc.FileHead.UnpVer>VER_UNPACK5; + if (Arc.Format==RARFMT50) // Both SFX and RAR can unpack RAR 5.0 and 7.0 archives. + WrongVer=Arc.FileHead.UnpVer>VER_UNPACK7; else { #ifdef SFX_MODULE // SFX can unpack only RAR 2.9 archives. @@ -1466,7 +1498,7 @@ bool CmdExtract::CheckUnpVer(Archive &Arc,const wchar *ArcFileName) // But it would be slower for solid archives than scaning headers // in first pass and extracting everything in second, as implemented now. // -void CmdExtract::AnalyzeArchive(const wchar *ArcName,bool Volume,bool NewNumbering) +void CmdExtract::AnalyzeArchive(const std::wstring &ArcName,bool Volume,bool NewNumbering) { FreeAnalyzeData(); // If processing non-first archive in multiple archives set. @@ -1476,11 +1508,11 @@ void CmdExtract::AnalyzeArchive(const wchar *ArcName,bool Volume,bool NewNumberi return; // No need to check further for * and *.* masks. // Start search from first volume if all volumes preceding current are available. - wchar NextName[NM]; + std::wstring NextName; if (Volume) - GetFirstVolIfFullSet(ArcName,NewNumbering,NextName,ASIZE(NextName)); + GetFirstVolIfFullSet(ArcName,NewNumbering,NextName); else - wcsncpyz(NextName,ArcName,ASIZE(NextName)); + NextName=ArcName; bool MatchFound=false; bool PrevMatched=false; @@ -1489,7 +1521,7 @@ void CmdExtract::AnalyzeArchive(const wchar *ArcName,bool Volume,bool NewNumberi bool FirstVolume=true; // We shall set FirstFile once for all volumes and not for each volume. - // So we do not reuse the outdated Analyze->StartPos from previous volume + // So we do not reuse the outdated Analyze.StartPos from previous volume // if extracted file resides completely in the beginning of current one. bool FirstFile=true; @@ -1503,8 +1535,8 @@ void CmdExtract::AnalyzeArchive(const wchar *ArcName,bool Volume,bool NewNumberi // If we couldn't open trailing volumes, we can't set early exit // parameters. It is possible that some volume are on removable media // and will be provided by user when extracting. - *Analyze->EndName=0; - Analyze->EndPos=0; + Analyze.EndName.clear(); + Analyze.EndPos=0; } break; } @@ -1539,24 +1571,24 @@ void CmdExtract::AnalyzeArchive(const wchar *ArcName,bool Volume,bool NewNumberi // if we set StartName for first volume or StartPos for first // archived file. if (!FirstVolume) - wcsncpyz(Analyze->StartName,NextName,ASIZE(Analyze->StartName)); + Analyze.StartName=NextName; // We shall set FirstFile once for all volumes for this code // to work properly. Alternatively we could append - // "|| Analyze->StartPos!=0" to the condition, so we do not reuse - // the outdated Analyze->StartPos value from previous volume. + // "|| Analyze.StartPos!=0" to the condition, so we do not reuse + // the outdated Analyze.StartPos value from previous volume. if (!FirstFile) - Analyze->StartPos=Arc.CurBlockPos; + Analyze.StartPos=Arc.CurBlockPos; } - if (Cmd->IsProcessFile(Arc.FileHead,NULL,MATCH_WILDSUBPATH,0,NULL,0)!=0) + if (Cmd->IsProcessFile(Arc.FileHead,NULL,MATCH_WILDSUBPATH,0,NULL)!=0) { MatchFound = true; PrevMatched = true; // Reset the previously set early exit position, if any, because // we found a new matched file. - Analyze->EndPos=0; + Analyze.EndPos=0; // Matched file reference pointing at maybe non-matched source file. // Even though we know RedirName, we can't check if source file @@ -1565,8 +1597,8 @@ void CmdExtract::AnalyzeArchive(const wchar *ArcName,bool Volume,bool NewNumberi if (Arc.FileHead.RedirType==FSREDIR_FILECOPY) { bool AlreadyAdded=false; - for (size_t I=0;IEndName,NextName,ASIZE(Analyze->EndName)); - Analyze->EndPos=Arc.CurBlockPos; + Analyze.EndName=NextName; + Analyze.EndPos=Arc.CurBlockPos; } PrevMatched=false; } @@ -1616,7 +1648,7 @@ void CmdExtract::AnalyzeArchive(const wchar *ArcName,bool Volume,bool NewNumberi if (Volume && OpenNext) { - NextVolumeName(NextName,ASIZE(NextName),!Arc.NewNumbering); + NextVolumeName(NextName,!Arc.NewNumbering); FirstVolume=false; // Needed for multivolume archives. Added in case some 'break' @@ -1631,8 +1663,8 @@ void CmdExtract::AnalyzeArchive(const wchar *ArcName,bool Volume,bool NewNumberi // If file references are present, we can't reliably skip in semi-solid // archives, because reference source can be present in skipped data. - if (RefList.Size()!=0) - memset(Analyze,0,sizeof(*Analyze)); + if (RefList.size()!=0) + Analyze={}; } #endif @@ -1640,26 +1672,46 @@ void CmdExtract::AnalyzeArchive(const wchar *ArcName,bool Volume,bool NewNumberi #ifndef SFX_MODULE // Return the first volume name if all volumes preceding the specified // are available. Otherwise return the specified volume name. -void CmdExtract::GetFirstVolIfFullSet(const wchar *SrcName,bool NewNumbering,wchar *DestName,size_t DestSize) +void CmdExtract::GetFirstVolIfFullSet(const std::wstring &SrcName,bool NewNumbering,std::wstring &DestName) { - wchar FirstVolName[NM]; - VolNameToFirstName(SrcName,FirstVolName,ASIZE(FirstVolName),NewNumbering); - wchar NextName[NM]; - wcsncpyz(NextName,FirstVolName,ASIZE(NextName)); - wchar ResultName[NM]; - wcsncpyz(ResultName,SrcName,ASIZE(ResultName)); + std::wstring FirstVolName; + VolNameToFirstName(SrcName,FirstVolName,NewNumbering); + std::wstring NextName=FirstVolName; + std::wstring ResultName=SrcName; while (true) { - if (wcscmp(SrcName,NextName)==0) + if (SrcName==NextName) { - wcsncpyz(ResultName,FirstVolName,DestSize); + ResultName=FirstVolName; // Reached the specified volume starting from the first. break; } if (!FileExist(NextName)) break; - NextVolumeName(NextName,ASIZE(NextName),!NewNumbering); + NextVolumeName(NextName,!NewNumbering); } - wcsncpyz(DestName,ResultName,DestSize); + DestName=ResultName; } +#endif -#endif \ No newline at end of file + +bool CmdExtract::CheckWinLimit(Archive &Arc,std::wstring &ArcFileName) +{ + if (Arc.FileHead.WinSize<=Cmd->WinSizeLimit || Arc.FileHead.WinSize<=Cmd->WinSize) + return true; + if (uiDictLimit(Cmd,ArcFileName,Arc.FileHead.WinSize,Max(Cmd->WinSizeLimit,Cmd->WinSize))) + { + // No more prompts when extracting other files. Important for GUI versions, + // where we might not have [Max]WinSize set permanently when extracting. + Cmd->WinSizeLimit=Arc.FileHead.WinSize; + } + else + { + ErrHandler.SetErrorCode(RARX_FATAL); +#ifdef RARDLL + Cmd->DllError=ERAR_LARGE_DICT; +#endif + Arc.SeekToNext(); + return false; + } + return true; +} diff --git a/vendor/unrar/extract.hpp b/vendor/unrar/extract.hpp index 18396c5b93..4400057aee 100644 --- a/vendor/unrar/extract.hpp +++ b/vendor/unrar/extract.hpp @@ -8,41 +8,42 @@ class CmdExtract private: struct ExtractRef { - wchar *RefName; - wchar *TmpName; + std::wstring RefName; + std::wstring TmpName; uint64 RefCount; }; - Array RefList; + std::vector RefList; struct AnalyzeData { - wchar StartName[NM]; + std::wstring StartName; uint64 StartPos; - wchar EndName[NM]; + std::wstring EndName; uint64 EndPos; - } *Analyze; + } Analyze; bool ArcAnalyzed; void FreeAnalyzeData(); EXTRACT_ARC_CODE ExtractArchive(); - bool ExtractFileCopy(File &New,wchar *ArcName,const wchar *RedirName,wchar *NameNew,wchar *NameExisting,size_t NameExistingSize,int64 UnpSize); - void ExtrPrepareName(Archive &Arc,const wchar *ArcFileName,wchar *DestName,size_t DestSize); + bool ExtractFileCopy(File &New,const std::wstring &ArcName,const std::wstring &RedirName,const std::wstring &NameNew,const std::wstring &NameExisting,int64 UnpSize); + void ExtrPrepareName(Archive &Arc,const std::wstring &ArcFileName,std::wstring &DestName); #ifdef RARDLL bool ExtrDllGetPassword(); #else - bool ExtrGetPassword(Archive &Arc,const wchar *ArcFileName,RarCheckPassword *CheckPwd); + bool ExtrGetPassword(Archive &Arc,const std::wstring &ArcFileName,RarCheckPassword *CheckPwd); #endif #if defined(_WIN_ALL) && !defined(SFX_MODULE) void ConvertDosPassword(Archive &Arc,SecPassword &DestPwd); #endif - void ExtrCreateDir(Archive &Arc,const wchar *ArcFileName); + void ExtrCreateDir(Archive &Arc,const std::wstring &ArcFileName); bool ExtrCreateFile(Archive &Arc,File &CurFile); - bool CheckUnpVer(Archive &Arc,const wchar *ArcFileName); + bool CheckUnpVer(Archive &Arc,const std::wstring &ArcFileName); #ifndef SFX_MODULE - void AnalyzeArchive(const wchar *ArcName,bool Volume,bool NewNumbering); - void GetFirstVolIfFullSet(const wchar *SrcName,bool NewNumbering,wchar *DestName,size_t DestSize); + void AnalyzeArchive(const std::wstring &ArcName,bool Volume,bool NewNumbering); + void GetFirstVolIfFullSet(const std::wstring &SrcName,bool NewNumbering,std::wstring &DestName); #endif + bool CheckWinLimit(Archive &Arc,std::wstring &ArcFileName); RarTime StartTime; // Time when extraction started. @@ -65,12 +66,12 @@ class CmdExtract // any wrong password hints. bool AnySolidDataUnpackedWell; - wchar ArcName[NM]; + std::wstring ArcName; bool GlobalPassword; bool PrevProcessed; // If previous file was successfully extracted or tested. - wchar DestFileName[NM]; - bool PasswordCancelled; + std::wstring DestFileName; + bool SuppressNoFilesMessage; // In Windows it is set to true if at least one symlink with ".." // in target was extracted. diff --git a/vendor/unrar/filcreat.cpp b/vendor/unrar/filcreat.cpp index d58e4f6fe9..6b21aa2606 100644 --- a/vendor/unrar/filcreat.cpp +++ b/vendor/unrar/filcreat.cpp @@ -3,7 +3,7 @@ // If NewFile==NULL, we delete created file after user confirmation. // It is useful if we need to overwrite an existing folder or file, // but need user confirmation for that. -bool FileCreate(CommandData *Cmd,File *NewFile,wchar *Name,size_t MaxNameSize, +bool FileCreate(CommandData *Cmd,File *NewFile,std::wstring &Name, bool *UserReject,int64 FileSize,RarTime *FileTime,bool WriteOnly) { if (UserReject!=NULL) @@ -29,7 +29,7 @@ bool FileCreate(CommandData *Cmd,File *NewFile,wchar *Name,size_t MaxNameSize, // autorename below can change the name, so we need to check it again. ShortNameChanged=false; #endif - UIASKREP_RESULT Choice=uiAskReplaceEx(Cmd,Name,MaxNameSize,FileSize,FileTime,(NewFile==NULL ? UIASKREP_F_NORENAME:0)); + UIASKREP_RESULT Choice=uiAskReplaceEx(Cmd,Name,FileSize,FileTime,(NewFile==NULL ? UIASKREP_F_NORENAME:0)); if (Choice==UIASKREP_R_REPLACE) break; @@ -56,85 +56,70 @@ bool FileCreate(CommandData *Cmd,File *NewFile,wchar *Name,size_t MaxNameSize, } -bool GetAutoRenamedName(wchar *Name,size_t MaxNameSize) -{ - wchar NewName[NM]; - size_t NameLength=wcslen(Name); - wchar *Ext=GetExt(Name); - if (Ext==NULL) - Ext=Name+NameLength; - for (uint FileVer=1;;FileVer++) - { - swprintf(NewName,ASIZE(NewName),L"%.*ls(%u)%ls",uint(Ext-Name),Name,FileVer,Ext); - if (!FileExist(NewName)) - { - wcsncpyz(Name,NewName,MaxNameSize); - break; - } - if (FileVer>=1000000) - return false; - } - return true; -} - - #if defined(_WIN_ALL) // If we find a file, which short name is equal to 'Name', we try to change // its short name, while preserving the long name. It helps when unpacking // an archived file, which long name is equal to short name of already // existing file. Otherwise we would overwrite the already existing file, // even though its long name does not match the name of unpacking file. -bool UpdateExistingShortName(const wchar *Name) +bool UpdateExistingShortName(const std::wstring &Name) { - wchar LongPathName[NM]; - DWORD Res=GetLongPathName(Name,LongPathName,ASIZE(LongPathName)); - if (Res==0 || Res>=ASIZE(LongPathName)) + DWORD Res=GetLongPathName(Name.c_str(),NULL,0); + if (Res==0) return false; - wchar ShortPathName[NM]; - Res=GetShortPathName(Name,ShortPathName,ASIZE(ShortPathName)); - if (Res==0 || Res>=ASIZE(ShortPathName)) + std::vector LongPathBuf(Res); + Res=GetLongPathName(Name.c_str(),LongPathBuf.data(),(DWORD)LongPathBuf.size()); + if (Res==0 || Res>=LongPathBuf.size()) return false; - wchar *LongName=PointToName(LongPathName); - wchar *ShortName=PointToName(ShortPathName); + Res=GetShortPathName(Name.c_str(),NULL,0); + if (Res==0) + return false; + std::vector ShortPathBuf(Res); + Res=GetShortPathName(Name.c_str(),ShortPathBuf.data(),(DWORD)ShortPathBuf.size()); + if (Res==0 || Res>=ShortPathBuf.size()) + return false; + std::wstring LongPathName=LongPathBuf.data(); + std::wstring ShortPathName=ShortPathBuf.data(); + + std::wstring LongName=PointToName(LongPathName); + std::wstring ShortName=PointToName(ShortPathName); // We continue only if file has a short name, which does not match its // long name, and this short name is equal to name of file which we need // to create. - if (*ShortName==0 || wcsicomp(LongName,ShortName)==0 || + if (ShortName.empty() || wcsicomp(LongName,ShortName)==0 || wcsicomp(PointToName(Name),ShortName)!=0) return false; // Generate the temporary new name for existing file. - wchar NewName[NM]; - *NewName=0; - for (int I=0;I<10000 && *NewName==0;I+=123) + std::wstring NewName; + for (uint I=0;I<10000 && NewName.empty();I+=123) { // Here we copy the path part of file to create. We'll make the temporary // file in the same folder. - wcsncpyz(NewName,Name,ASIZE(NewName)); + NewName=Name; // Here we set the random name part. - swprintf(PointToName(NewName),ASIZE(NewName),L"rtmp%d",I); + SetName(NewName,std::wstring(L"rtmp") + std::to_wstring(I)); // If such file is already exist, try next random name. if (FileExist(NewName)) - *NewName=0; + NewName.clear(); } // If we could not generate the name not used by any other file, we return. - if (*NewName==0) + if (NewName.empty()) return false; // FastFind returns the name without path, but we need the fully qualified // name for renaming, so we use the path from file to create and long name // from existing file. - wchar FullName[NM]; - wcsncpyz(FullName,Name,ASIZE(FullName)); - SetName(FullName,LongName,ASIZE(FullName)); + std::wstring FullName=Name; + SetName(FullName,LongName); // Rename the existing file to randomly generated name. Normally it changes // the short name too. - if (!MoveFile(FullName,NewName)) + if (!MoveFile(FullName.c_str(),NewName.c_str())) return false; // Now we need to create the temporary empty file with same name as @@ -149,7 +134,7 @@ bool UpdateExistingShortName(const wchar *Name) // Now we rename the existing file from temporary name to original long name. // Since its previous short name is occupied by another file, it should // get another short name. - MoveFile(NewName,FullName); + MoveFile(NewName.c_str(),FullName.c_str()); if (Created) { @@ -157,9 +142,9 @@ bool UpdateExistingShortName(const wchar *Name) KeepShortFile.Close(); KeepShortFile.Delete(); } - // We successfully changed the short name. Maybe sometimes we'll simplify - // this function by use of SetFileShortName Windows API call. - // But SetFileShortName is not available in older Windows. + // We successfully changed the short name. We do not use the simpler + // SetFileShortName Windows API call, because it requires SE_RESTORE_NAME + // privilege. return true; } #endif diff --git a/vendor/unrar/filcreat.hpp b/vendor/unrar/filcreat.hpp index 456a4a4a13..ad95feef94 100644 --- a/vendor/unrar/filcreat.hpp +++ b/vendor/unrar/filcreat.hpp @@ -1,14 +1,12 @@ #ifndef _RAR_FILECREATE_ #define _RAR_FILECREATE_ -bool FileCreate(CommandData *Cmd,File *NewFile,wchar *Name,size_t MaxNameSize, +bool FileCreate(CommandData *Cmd,File *NewFile,std::wstring &Name, bool *UserReject,int64 FileSize=INT64NDF, RarTime *FileTime=NULL,bool WriteOnly=false); -bool GetAutoRenamedName(wchar *Name,size_t MaxNameSize); - #if defined(_WIN_ALL) -bool UpdateExistingShortName(const wchar *Name); +bool UpdateExistingShortName(const std::wstring &Name); #endif #endif diff --git a/vendor/unrar/file.cpp b/vendor/unrar/file.cpp index 7bf60fd4ef..2d0d785cb2 100644 --- a/vendor/unrar/file.cpp +++ b/vendor/unrar/file.cpp @@ -3,7 +3,6 @@ File::File() { hFile=FILE_BAD_HANDLE; - *FileName=0; NewFile=false; LastWrite=false; HandleType=FILE_HANDLENORMAL; @@ -40,12 +39,12 @@ void File::operator = (File &SrcFile) LastWrite=SrcFile.LastWrite; HandleType=SrcFile.HandleType; TruncatedAfterReadError=SrcFile.TruncatedAfterReadError; - wcsncpyz(FileName,SrcFile.FileName,ASIZE(FileName)); + FileName=SrcFile.FileName; SrcFile.SkipClose=true; } -bool File::Open(const wchar *Name,uint Mode) +bool File::Open(const std::wstring &Name,uint Mode) { ErrorType=FILE_SUCCESS; FileHandle hNewFile; @@ -63,17 +62,17 @@ bool File::Open(const wchar *Name,uint Mode) FindData FD; if (PreserveAtime) Access|=FILE_WRITE_ATTRIBUTES; // Needed to preserve atime. - hNewFile=CreateFile(Name,Access,ShareMode,NULL,OPEN_EXISTING,Flags,NULL); + hNewFile=CreateFile(Name.c_str(),Access,ShareMode,NULL,OPEN_EXISTING,Flags,NULL); DWORD LastError; if (hNewFile==FILE_BAD_HANDLE) { LastError=GetLastError(); - wchar LongName[NM]; - if (GetWinLongPath(Name,LongName,ASIZE(LongName))) + std::wstring LongName; + if (GetWinLongPath(Name,LongName)) { - hNewFile=CreateFile(LongName,Access,ShareMode,NULL,OPEN_EXISTING,Flags,NULL); + hNewFile=CreateFile(LongName.c_str(),Access,ShareMode,NULL,OPEN_EXISTING,Flags,NULL); // For archive names longer than 260 characters first CreateFile // (without \\?\) fails and sets LastError to 3 (access denied). @@ -112,10 +111,10 @@ bool File::Open(const wchar *Name,uint Mode) if (PreserveAtime) flags|=O_NOATIME; #endif - char NameA[NM]; - WideToChar(Name,NameA,ASIZE(NameA)); + std::string NameA; + WideToChar(Name,NameA); - int handle=open(NameA,flags); + int handle=open(NameA.c_str(),flags); #ifdef LOCK_EX #ifdef _OSF_SOURCE @@ -148,7 +147,7 @@ bool File::Open(const wchar *Name,uint Mode) if (Success) { hFile=hNewFile; - wcsncpyz(FileName,Name,ASIZE(FileName)); + FileName=Name; TruncatedAfterReadError=false; } return Success; @@ -156,7 +155,7 @@ bool File::Open(const wchar *Name,uint Mode) #if !defined(SFX_MODULE) -void File::TOpen(const wchar *Name) +void File::TOpen(const std::wstring &Name) { if (!WOpen(Name)) ErrHandler.Exit(RARX_OPEN); @@ -164,7 +163,7 @@ void File::TOpen(const wchar *Name) #endif -bool File::WOpen(const wchar *Name) +bool File::WOpen(const std::wstring &Name) { if (Open(Name)) return true; @@ -173,7 +172,7 @@ bool File::WOpen(const wchar *Name) } -bool File::Create(const wchar *Name,uint Mode) +bool File::Create(const std::wstring &Name,uint Mode) { // OpenIndiana based NAS and CIFS shares fail to set the file time if file // was created in read+write mode and some data was written and not flushed @@ -188,40 +187,40 @@ bool File::Create(const wchar *Name,uint Mode) // Windows automatically removes dots and spaces in the end of file name, // So we detect such names and process them with \\?\ prefix. - wchar *LastChar=PointToLastChar(Name); - bool Special=*LastChar=='.' || *LastChar==' '; + wchar LastChar=GetLastChar(Name); + bool Special=LastChar=='.' || LastChar==' '; if (Special && (Mode & FMF_STANDARDNAMES)==0) hFile=FILE_BAD_HANDLE; else - hFile=CreateFile(Name,Access,ShareMode,NULL,CREATE_ALWAYS,0,NULL); + hFile=CreateFile(Name.c_str(),Access,ShareMode,NULL,CREATE_ALWAYS,0,NULL); if (hFile==FILE_BAD_HANDLE) { - wchar LongName[NM]; - if (GetWinLongPath(Name,LongName,ASIZE(LongName))) - hFile=CreateFile(LongName,Access,ShareMode,NULL,CREATE_ALWAYS,0,NULL); + std::wstring LongName; + if (GetWinLongPath(Name,LongName)) + hFile=CreateFile(LongName.c_str(),Access,ShareMode,NULL,CREATE_ALWAYS,0,NULL); } #else - char NameA[NM]; - WideToChar(Name,NameA,ASIZE(NameA)); #ifdef FILE_USE_OPEN - hFile=open(NameA,(O_CREAT|O_TRUNC) | (WriteMode ? O_WRONLY : O_RDWR),0666); + std::string NameA; + WideToChar(Name,NameA); + hFile=open(NameA.c_str(),(O_CREAT|O_TRUNC) | (WriteMode ? O_WRONLY : O_RDWR),0666); #else - hFile=fopen(NameA,WriteMode ? WRITEBINARY:CREATEBINARY); + hFile=fopen(NameA.c_str(),WriteMode ? WRITEBINARY:CREATEBINARY); #endif #endif NewFile=true; HandleType=FILE_HANDLENORMAL; SkipClose=false; - wcsncpyz(FileName,Name,ASIZE(FileName)); + FileName=Name; return hFile!=FILE_BAD_HANDLE; } #if !defined(SFX_MODULE) -void File::TCreate(const wchar *Name,uint Mode) +void File::TCreate(const std::wstring &Name,uint Mode) { if (!WCreate(Name,Mode)) ErrHandler.Exit(RARX_FATAL); @@ -229,7 +228,7 @@ void File::TCreate(const wchar *Name,uint Mode) #endif -bool File::WCreate(const wchar *Name,uint Mode) +bool File::WCreate(const std::wstring &Name,uint Mode) { if (Create(Name,Mode)) return true; @@ -250,7 +249,7 @@ bool File::Close() // We use the standard system handle for stdout in Windows // and it must not be closed here. if (HandleType==FILE_HANDLENORMAL) - Success=CloseHandle(hFile)==TRUE; + Success=CloseHandle(hFile)!=FALSE; #else #ifdef FILE_USE_OPEN Success=close(hFile)!=-1; @@ -280,16 +279,16 @@ bool File::Delete() } -bool File::Rename(const wchar *NewName) +bool File::Rename(const std::wstring &NewName) { // No need to rename if names are already same. - bool Success=wcscmp(FileName,NewName)==0; + bool Success=(NewName==FileName); if (!Success) Success=RenameFile(FileName,NewName); if (Success) - wcsncpyz(FileName,NewName,ASIZE(FileName)); + FileName=NewName; return Success; } @@ -327,13 +326,13 @@ bool File::Write(const void *Data,size_t Size) const size_t MaxSize=0x4000; for (size_t I=0;IIsSet(); bool seta=fta!=NULL && fta->IsSet(); if (setm || seta) { - char NameA[NM]; - WideToChar(Name,NameA,ASIZE(NameA)); + std::string NameA; + WideToChar(Name,NameA); #ifdef UNIX_TIME_NS timespec times[2]; @@ -720,7 +719,7 @@ void File::SetCloseFileTimeByName(const wchar *Name,RarTime *ftm,RarTime *fta) times[0].tv_nsec=seta ? long(fta->GetUnixNS()%1000000000) : UTIME_NOW; times[1].tv_sec=setm ? ftm->GetUnix() : 0; times[1].tv_nsec=setm ? long(ftm->GetUnixNS()%1000000000) : UTIME_NOW; - utimensat(AT_FDCWD,NameA,times,0); + utimensat(AT_FDCWD,NameA.c_str(),times,0); #else utimbuf ut; if (setm) @@ -731,7 +730,7 @@ void File::SetCloseFileTimeByName(const wchar *Name,RarTime *ftm,RarTime *fta) ut.actime=fta->GetUnix(); else ut.actime=ut.modtime; // Need to set something, cannot left it 0. - utime(NameA,&ut); + utime(NameA.c_str(),&ut); #endif } #endif @@ -802,15 +801,15 @@ bool File::IsDevice() #ifndef SFX_MODULE int64 File::Copy(File &Dest,int64 Length) { - Array Buffer(File::CopyBufferSize()); + std::vector Buffer(File::CopyBufferSize()); int64 CopySize=0; bool CopyAll=(Length==INT64NDF); while (CopyAll || Length>0) { Wait(); - size_t SizeToRead=(!CopyAll && Length<(int64)Buffer.Size()) ? (size_t)Length:Buffer.Size(); - byte *Buf=&Buffer[0]; + size_t SizeToRead=(!CopyAll && Length<(int64)Buffer.size()) ? (size_t)Length:Buffer.size(); + byte *Buf=Buffer.data(); int ReadSize=Read(Buf,SizeToRead); if (ReadSize==0) break; diff --git a/vendor/unrar/file.hpp b/vendor/unrar/file.hpp index 5f55de960e..a95cc398fa 100644 --- a/vendor/unrar/file.hpp +++ b/vendor/unrar/file.hpp @@ -83,12 +83,9 @@ class File protected: bool OpenShared; // Set by 'Archive' class. public: - wchar FileName[NM]; + std::wstring FileName; FILE_ERRORTYPE ErrorType; - - byte *SeekBuf; // To read instead of seek for stdin files. - static const size_t SeekBufSize=0x10000; public: File(); virtual ~File(); @@ -96,15 +93,15 @@ class File // Several functions below are 'virtual', because they are redefined // by Archive for QOpen and by MultiFile for split files in WinRAR. - virtual bool Open(const wchar *Name,uint Mode=FMF_READ); - void TOpen(const wchar *Name); - bool WOpen(const wchar *Name); - bool Create(const wchar *Name,uint Mode=FMF_UPDATE|FMF_SHAREREAD); - void TCreate(const wchar *Name,uint Mode=FMF_UPDATE|FMF_SHAREREAD); - bool WCreate(const wchar *Name,uint Mode=FMF_UPDATE|FMF_SHAREREAD); + virtual bool Open(const std::wstring &Name,uint Mode=FMF_READ); + void TOpen(const std::wstring &Name); + bool WOpen(const std::wstring &Name); + bool Create(const std::wstring &Name,uint Mode=FMF_UPDATE|FMF_SHAREREAD); + void TCreate(const std::wstring &Name,uint Mode=FMF_UPDATE|FMF_SHAREREAD); + bool WCreate(const std::wstring &Name,uint Mode=FMF_UPDATE|FMF_SHAREREAD); virtual bool Close(); // 'virtual' for MultiFile class. bool Delete(); - bool Rename(const wchar *NewName); + bool Rename(const std::wstring &NewName); bool Write(const void *Data,size_t Size); virtual int Read(void *Data,size_t Size); int DirectRead(void *Data,size_t Size); @@ -118,13 +115,13 @@ class File void Flush(); void SetOpenFileTime(RarTime *ftm,RarTime *ftc=NULL,RarTime *fta=NULL); void SetCloseFileTime(RarTime *ftm,RarTime *fta=NULL); - static void SetCloseFileTimeByName(const wchar *Name,RarTime *ftm,RarTime *fta); + static void SetCloseFileTimeByName(const std::wstring &Name,RarTime *ftm,RarTime *fta); #ifdef _UNIX static void StatToRarTime(struct stat &st,RarTime *ftm,RarTime *ftc,RarTime *fta); #endif void GetOpenFileTime(RarTime *ftm,RarTime *ftc=NULL,RarTime *fta=NULL); virtual bool IsOpened() {return hFile!=FILE_BAD_HANDLE;} // 'virtual' for MultiFile class. - int64 FileLength(); + virtual int64 FileLength(); // 'virtual' for MultiFile class. void SetHandleType(FILE_HANDLETYPE Type) {HandleType=Type;} void SetLineInputMode(bool Mode) {LineInput=Mode;} FILE_HANDLETYPE GetHandleType() {return HandleType;} @@ -151,14 +148,9 @@ class File #endif static size_t CopyBufferSize() { -#ifdef _WIN_ALL - // USB flash performance is poor with 64 KB buffer, 256+ KB resolved it. - // For copying from HDD to same HDD the best performance was with 256 KB - // buffer in XP and with 1 MB buffer in Win10. - return WinNT()==WNT_WXP ? 0x40000:0x100000; -#else - return 0x100000; -#endif + // Values in 0x100000 - 0x400000 range are ok, but multithreaded CRC32 + // seems to benefit from 0x400000, especially on ARM CPUs. + return 0x400000; } }; diff --git a/vendor/unrar/filefn.cpp b/vendor/unrar/filefn.cpp index aaef305b8e..3cb2589261 100644 --- a/vendor/unrar/filefn.cpp +++ b/vendor/unrar/filefn.cpp @@ -1,18 +1,18 @@ #include "rar.hpp" -MKDIR_CODE MakeDir(const wchar *Name,bool SetAttr,uint Attr) +MKDIR_CODE MakeDir(const std::wstring &Name,bool SetAttr,uint Attr) { #ifdef _WIN_ALL // Windows automatically removes dots and spaces in the end of directory // name. So we detect such names and process them with \\?\ prefix. - wchar *LastChar=PointToLastChar(Name); - bool Special=*LastChar=='.' || *LastChar==' '; - BOOL RetCode=Special ? FALSE : CreateDirectory(Name,NULL); + wchar LastChar=GetLastChar(Name); + bool Special=LastChar=='.' || LastChar==' '; + BOOL RetCode=Special ? FALSE : CreateDirectory(Name.c_str(),NULL); if (RetCode==0 && !FileExist(Name)) { - wchar LongName[NM]; - if (GetWinLongPath(Name,LongName,ASIZE(LongName))) - RetCode=CreateDirectory(LongName,NULL); + std::wstring LongName; + if (GetWinLongPath(Name,LongName)) + RetCode=CreateDirectory(LongName.c_str(),NULL); } if (RetCode!=0) // Non-zero return code means success for CreateDirectory. { @@ -25,10 +25,10 @@ MKDIR_CODE MakeDir(const wchar *Name,bool SetAttr,uint Attr) return MKDIR_BADPATH; return MKDIR_ERROR; #elif defined(_UNIX) - char NameA[NM]; - WideToChar(Name,NameA,ASIZE(NameA)); + std::string NameA; + WideToChar(Name,NameA); mode_t uattr=SetAttr ? (mode_t)Attr:0777; - int ErrCode=mkdir(NameA,uattr); + int ErrCode=mkdir(NameA.c_str(),uattr); if (ErrCode==-1) return errno==ENOENT ? MKDIR_BADPATH:MKDIR_ERROR; return MKDIR_SUCCESS; @@ -38,12 +38,19 @@ MKDIR_CODE MakeDir(const wchar *Name,bool SetAttr,uint Attr) } -bool CreatePath(const wchar *Path,bool SkipLastName,bool Silent) +// Simplified version of MakeDir(). +bool CreateDir(const std::wstring &Name) { - if (Path==NULL || *Path==0) + return MakeDir(Name,false,0)==MKDIR_SUCCESS; +} + + +bool CreatePath(const std::wstring &Path,bool SkipLastName,bool Silent) +{ + if (Path.empty()) return false; -#if defined(_WIN_ALL) || defined(_EMX) +#ifdef _WIN_ALL uint DirAttr=0; #else uint DirAttr=0777; @@ -51,42 +58,36 @@ bool CreatePath(const wchar *Path,bool SkipLastName,bool Silent) bool Success=true; - for (const wchar *s=Path;*s!=0;s++) + for (size_t I=0;I=ASIZE(DirName)) - break; - // Process all kinds of path separators, so user can enter Unix style - // path in Windows or Windows in Unix. s>Path check avoids attempting + // path in Windows or Windows in Unix. I>0 check avoids attempting // creating an empty directory for paths starting from path separator. - if (IsPathDiv(*s) && s>Path) + if (IsPathDiv(Path[I]) && I>0) { #ifdef _WIN_ALL // We must not attempt to create "D:" directory, because first // CreateDirectory will fail, so we'll use \\?\D:, which forces Wine // to create "D:" directory. - if (s==Path+2 && Path[1]==':') + if (I==2 && Path[1]==':') continue; #endif - wcsncpy(DirName,Path,s-Path); - DirName[s-Path]=0; - + std::wstring DirName=Path.substr(0,I); Success=MakeDir(DirName,true,DirAttr)==MKDIR_SUCCESS; if (Success && !Silent) { - mprintf(St(MCreatDir),DirName); + mprintf(St(MCreatDir),DirName.c_str()); mprintf(L" %s",St(MOk)); } } } - if (!SkipLastName && !IsPathDiv(*PointToLastChar(Path))) + if (!SkipLastName && !IsPathDiv(GetLastChar(Path))) Success=MakeDir(Path,true,DirAttr)==MKDIR_SUCCESS; return Success; } -void SetDirTime(const wchar *Name,RarTime *ftm,RarTime *ftc,RarTime *fta) +void SetDirTime(const std::wstring &Name,RarTime *ftm,RarTime *ftc,RarTime *fta) { #if defined(_WIN_ALL) bool sm=ftm!=NULL && ftm->IsSet(); @@ -98,13 +99,13 @@ void SetDirTime(const wchar *Name,RarTime *ftm,RarTime *ftc,RarTime *fta) if (ResetAttr) SetFileAttr(Name,0); - HANDLE hFile=CreateFile(Name,GENERIC_WRITE,FILE_SHARE_READ|FILE_SHARE_WRITE, + HANDLE hFile=CreateFile(Name.c_str(),GENERIC_WRITE,FILE_SHARE_READ|FILE_SHARE_WRITE, NULL,OPEN_EXISTING,FILE_FLAG_BACKUP_SEMANTICS,NULL); if (hFile==INVALID_HANDLE_VALUE) { - wchar LongName[NM]; - if (GetWinLongPath(Name,LongName,ASIZE(LongName))) - hFile=CreateFile(LongName,GENERIC_WRITE,FILE_SHARE_READ|FILE_SHARE_WRITE, + std::wstring LongName; + if (GetWinLongPath(Name,LongName)) + hFile=CreateFile(LongName.c_str(),GENERIC_WRITE,FILE_SHARE_READ|FILE_SHARE_WRITE, NULL,OPEN_EXISTING,FILE_FLAG_BACKUP_SEMANTICS,NULL); } @@ -122,18 +123,18 @@ void SetDirTime(const wchar *Name,RarTime *ftm,RarTime *ftc,RarTime *fta) if (ResetAttr) SetFileAttr(Name,DirAttr); #endif -#if defined(_UNIX) || defined(_EMX) +#ifdef _UNIX File::SetCloseFileTimeByName(Name,ftm,fta); #endif } -bool IsRemovable(const wchar *Name) +bool IsRemovable(const std::wstring &Name) { #if defined(_WIN_ALL) - wchar Root[NM]; - GetPathRoot(Name,Root,ASIZE(Root)); - int Type=GetDriveType(*Root!=0 ? Root:NULL); + std::wstring Root; + GetPathRoot(Name,Root); + int Type=GetDriveType(Root.empty() ? nullptr : Root.c_str()); return Type==DRIVE_REMOVABLE || Type==DRIVE_CDROM; #else return false; @@ -142,25 +143,25 @@ bool IsRemovable(const wchar *Name) #ifndef SFX_MODULE -int64 GetFreeDisk(const wchar *Name) +int64 GetFreeDisk(const std::wstring &Name) { #ifdef _WIN_ALL - wchar Root[NM]; - GetFilePath(Name,Root,ASIZE(Root)); + std::wstring Root; + GetPathWithSep(Name,Root); ULARGE_INTEGER uiTotalSize,uiTotalFree,uiUserFree; uiUserFree.u.LowPart=uiUserFree.u.HighPart=0; - if (GetDiskFreeSpaceEx(*Root!=0 ? Root:NULL,&uiUserFree,&uiTotalSize,&uiTotalFree) && + if (GetDiskFreeSpaceEx(Root.empty() ? NULL:Root.c_str(),&uiUserFree,&uiTotalSize,&uiTotalFree) && uiUserFree.u.HighPart<=uiTotalFree.u.HighPart) return INT32TO64(uiUserFree.u.HighPart,uiUserFree.u.LowPart); return 0; #elif defined(_UNIX) - wchar Root[NM]; - GetFilePath(Name,Root,ASIZE(Root)); - char RootA[NM]; - WideToChar(Root,RootA,ASIZE(RootA)); + std::wstring Root; + GetPathWithSep(Name,Root); + std::string RootA; + WideToChar(Root,RootA); struct statvfs sfs; - if (statvfs(*RootA!=0 ? RootA:".",&sfs)!=0) + if (statvfs(RootA.empty() ? ".":RootA.c_str(),&sfs)!=0) return 0; int64 FreeSize=sfs.f_bsize; FreeSize=FreeSize*sfs.f_bavail; @@ -175,26 +176,27 @@ int64 GetFreeDisk(const wchar *Name) #if defined(_WIN_ALL) && !defined(SFX_MODULE) && !defined(SILENT) // Return 'true' for FAT and FAT32, so we can adjust the maximum supported // file size to 4 GB for these file systems. -bool IsFAT(const wchar *Name) +bool IsFAT(const std::wstring &Name) { - wchar Root[NM]; - GetPathRoot(Name,Root,ASIZE(Root)); + std::wstring Root; + GetPathRoot(Name,Root); wchar FileSystem[MAX_PATH+1]; - if (GetVolumeInformation(Root,NULL,0,NULL,NULL,NULL,FileSystem,ASIZE(FileSystem))) + // Root can be empty, when we create volumes with -v in the current folder. + if (GetVolumeInformation(Root.empty() ? NULL:Root.c_str(),NULL,0,NULL,NULL,NULL,FileSystem,ASIZE(FileSystem))) return wcscmp(FileSystem,L"FAT")==0 || wcscmp(FileSystem,L"FAT32")==0; return false; } #endif -bool FileExist(const wchar *Name) +bool FileExist(const std::wstring &Name) { #ifdef _WIN_ALL return GetFileAttr(Name)!=0xffffffff; #elif defined(ENABLE_ACCESS) - char NameA[NM]; - WideToChar(Name,NameA,ASIZE(NameA)); - return access(NameA,0)==0; + std::string NameA; + WideToChar(Name,NameA); + return access(NameA.c_str(),0)==0; #else FindData FD; return FindFile::FastFind(Name,&FD); @@ -202,7 +204,7 @@ bool FileExist(const wchar *Name) } -bool WildFileExist(const wchar *Name) +bool WildFileExist(const std::wstring &Name) { if (IsWildcard(Name)) { @@ -230,8 +232,9 @@ bool IsUnreadable(uint Attr) { #if defined(_UNIX) && defined(S_ISFIFO) && defined(S_ISSOCK) && defined(S_ISCHR) return S_ISFIFO(Attr) || S_ISSOCK(Attr) || S_ISCHR(Attr); -#endif +#else return false; +#endif } @@ -261,66 +264,63 @@ bool IsDeleteAllowed(uint FileAttr) } -void PrepareToDelete(const wchar *Name) +void PrepareToDelete(const std::wstring &Name) { -#if defined(_WIN_ALL) || defined(_EMX) +#ifdef _WIN_ALL SetFileAttr(Name,0); #endif #ifdef _UNIX - if (Name!=NULL) - { - char NameA[NM]; - WideToChar(Name,NameA,ASIZE(NameA)); - chmod(NameA,S_IRUSR|S_IWUSR|S_IXUSR); - } + std::string NameA; + WideToChar(Name,NameA); + chmod(NameA.c_str(),S_IRUSR|S_IWUSR|S_IXUSR); #endif } -uint GetFileAttr(const wchar *Name) +uint GetFileAttr(const std::wstring &Name) { #ifdef _WIN_ALL - DWORD Attr=GetFileAttributes(Name); + DWORD Attr=GetFileAttributes(Name.c_str()); if (Attr==0xffffffff) { - wchar LongName[NM]; - if (GetWinLongPath(Name,LongName,ASIZE(LongName))) - Attr=GetFileAttributes(LongName); + std::wstring LongName; + if (GetWinLongPath(Name,LongName)) + Attr=GetFileAttributes(LongName.c_str()); } return Attr; #else - char NameA[NM]; - WideToChar(Name,NameA,ASIZE(NameA)); + std::string NameA; + WideToChar(Name,NameA); struct stat st; - if (stat(NameA,&st)!=0) + if (stat(NameA.c_str(),&st)!=0) return 0; return st.st_mode; #endif } -bool SetFileAttr(const wchar *Name,uint Attr) +bool SetFileAttr(const std::wstring &Name,uint Attr) { #ifdef _WIN_ALL - bool Success=SetFileAttributes(Name,Attr)!=0; + bool Success=SetFileAttributes(Name.c_str(),Attr)!=0; if (!Success) { - wchar LongName[NM]; - if (GetWinLongPath(Name,LongName,ASIZE(LongName))) - Success=SetFileAttributes(LongName,Attr)!=0; + std::wstring LongName; + if (GetWinLongPath(Name,LongName)) + Success=SetFileAttributes(LongName.c_str(),Attr)!=0; } return Success; #elif defined(_UNIX) - char NameA[NM]; - WideToChar(Name,NameA,ASIZE(NameA)); - return chmod(NameA,(mode_t)Attr)==0; + std::string NameA; + WideToChar(Name,NameA); + return chmod(NameA.c_str(),(mode_t)Attr)==0; #else return false; #endif } -wchar *MkTemp(wchar *Name,size_t MaxSize) +wchar* MkTemp(wchar *Name,size_t MaxSize) { size_t Length=wcslen(Name); @@ -344,7 +344,11 @@ wchar *MkTemp(wchar *Name,size_t MaxSize) { uint Ext=Random%50000+Attempt; wchar RndText[50]; - swprintf(RndText,ASIZE(RndText),L"%u.%03u",PID,Ext); + // User asked to specify the single extension for all temporary files, + // so it can be added to server ransomware protection exceptions. + // He wrote, this protection blocks temporary files when adding + // a file to RAR archive with drag and drop. + swprintf(RndText,ASIZE(RndText),L"%u.%03u.rartemp",PID,Ext); if (Length+wcslen(RndText)>=MaxSize || Attempt==1000) return NULL; wcsncpyz(Name+Length,RndText,MaxSize-Length); @@ -355,6 +359,40 @@ wchar *MkTemp(wchar *Name,size_t MaxSize) } +bool MkTemp(std::wstring &Name) +{ + RarTime CurTime; + CurTime.SetCurrentTime(); + + // We cannot use CurTime.GetWin() as is, because its lowest bits can + // have low informational value, like being a zero or few fixed numbers. + uint Random=(uint)(CurTime.GetWin()/100000); + + // Using PID we guarantee that different RAR copies use different temp names + // even if started in exactly the same time. + uint PID=0; +#ifdef _WIN_ALL + PID=(uint)GetCurrentProcessId(); +#elif defined(_UNIX) + PID=(uint)getpid(); +#endif + + for (uint Attempt=0;;Attempt++) + { + uint Ext=Random%50000+Attempt; + if (Attempt==1000) + return false; + std::wstring NewName=Name + std::to_wstring(PID) + L"." + std::to_wstring(Ext) + L".rartemp"; + if (!FileExist(NewName)) + { + Name=NewName; + break; + } + } + return true; +} + + #if !defined(SFX_MODULE) void CalcFileSum(File *SrcFile,uint *CRC32,byte *Blake2,uint Threads,int64 Size,uint Flags) { @@ -370,8 +408,7 @@ void CalcFileSum(File *SrcFile,uint *CRC32,byte *Blake2,uint Threads,int64 Size, SrcFile->Seek(0,SEEK_SET); const size_t BufSize=0x100000; - Array Data(BufSize); - + std::vector Data(BufSize); DataHash HashCRC,HashBlake2; HashCRC.Init(HASH_CRC32,Threads); @@ -386,7 +423,7 @@ void CalcFileSum(File *SrcFile,uint *CRC32,byte *Blake2,uint Threads,int64 Size, SizeToRead=BufSize; // Then always attempt to read the entire buffer. else SizeToRead=(size_t)Min((int64)BufSize,Size); - int ReadSize=SrcFile->Read(&Data[0],SizeToRead); + int ReadSize=SrcFile->Read(Data.data(),SizeToRead); if (ReadSize==0) break; TotalRead+=ReadSize; @@ -410,9 +447,9 @@ void CalcFileSum(File *SrcFile,uint *CRC32,byte *Blake2,uint Threads,int64 Size, } if (CRC32!=NULL) - HashCRC.Update(&Data[0],ReadSize); + HashCRC.Update(Data.data(),ReadSize); if (Blake2!=NULL) - HashBlake2.Update(&Data[0],ReadSize); + HashBlake2.Update(Data.data(),ReadSize); if (Size!=INT64NDF) Size-=ReadSize; @@ -434,79 +471,78 @@ void CalcFileSum(File *SrcFile,uint *CRC32,byte *Blake2,uint Threads,int64 Size, #endif -bool RenameFile(const wchar *SrcName,const wchar *DestName) +bool RenameFile(const std::wstring &SrcName,const std::wstring &DestName) { #ifdef _WIN_ALL - bool Success=MoveFile(SrcName,DestName)!=0; + bool Success=MoveFile(SrcName.c_str(),DestName.c_str())!=0; if (!Success) { - wchar LongName1[NM],LongName2[NM]; - if (GetWinLongPath(SrcName,LongName1,ASIZE(LongName1)) && - GetWinLongPath(DestName,LongName2,ASIZE(LongName2))) - Success=MoveFile(LongName1,LongName2)!=0; + std::wstring LongName1,LongName2; + if (GetWinLongPath(SrcName,LongName1) && GetWinLongPath(DestName,LongName2)) + Success=MoveFile(LongName1.c_str(),LongName2.c_str())!=0; } return Success; #else - char SrcNameA[NM],DestNameA[NM]; - WideToChar(SrcName,SrcNameA,ASIZE(SrcNameA)); - WideToChar(DestName,DestNameA,ASIZE(DestNameA)); - bool Success=rename(SrcNameA,DestNameA)==0; + std::string SrcNameA,DestNameA; + WideToChar(SrcName,SrcNameA); + WideToChar(DestName,DestNameA); + bool Success=rename(SrcNameA.c_str(),DestNameA.c_str())==0; return Success; #endif } -bool DelFile(const wchar *Name) +bool DelFile(const std::wstring &Name) { #ifdef _WIN_ALL - bool Success=DeleteFile(Name)!=0; + bool Success=DeleteFile(Name.c_str())!=0; if (!Success) { - wchar LongName[NM]; - if (GetWinLongPath(Name,LongName,ASIZE(LongName))) - Success=DeleteFile(LongName)!=0; + std::wstring LongName; + if (GetWinLongPath(Name,LongName)) + Success=DeleteFile(LongName.c_str())!=0; } return Success; #else - char NameA[NM]; - WideToChar(Name,NameA,ASIZE(NameA)); - bool Success=remove(NameA)==0; + std::string NameA; + WideToChar(Name,NameA); + bool Success=remove(NameA.c_str())==0; return Success; #endif } -bool DelDir(const wchar *Name) +bool DelDir(const std::wstring &Name) { #ifdef _WIN_ALL - bool Success=RemoveDirectory(Name)!=0; + bool Success=RemoveDirectory(Name.c_str())!=0; if (!Success) { - wchar LongName[NM]; - if (GetWinLongPath(Name,LongName,ASIZE(LongName))) - Success=RemoveDirectory(LongName)!=0; + std::wstring LongName; + if (GetWinLongPath(Name,LongName)) + Success=RemoveDirectory(LongName.c_str())!=0; } return Success; #else - char NameA[NM]; - WideToChar(Name,NameA,ASIZE(NameA)); - bool Success=rmdir(NameA)==0; + std::string NameA; + WideToChar(Name,NameA); + bool Success=rmdir(NameA.c_str())==0; return Success; #endif } #if defined(_WIN_ALL) && !defined(SFX_MODULE) -bool SetFileCompression(const wchar *Name,bool State) +bool SetFileCompression(const std::wstring &Name,bool State) { - HANDLE hFile=CreateFile(Name,FILE_READ_DATA|FILE_WRITE_DATA, + HANDLE hFile=CreateFile(Name.c_str(),FILE_READ_DATA|FILE_WRITE_DATA, FILE_SHARE_READ|FILE_SHARE_WRITE,NULL,OPEN_EXISTING, FILE_FLAG_BACKUP_SEMANTICS|FILE_FLAG_SEQUENTIAL_SCAN,NULL); if (hFile==INVALID_HANDLE_VALUE) { - wchar LongName[NM]; - if (GetWinLongPath(Name,LongName,ASIZE(LongName))) - hFile=CreateFile(LongName,FILE_READ_DATA|FILE_WRITE_DATA, + std::wstring LongName; + if (GetWinLongPath(Name,LongName)) + hFile=CreateFile(LongName.c_str(),FILE_READ_DATA|FILE_WRITE_DATA, FILE_SHARE_READ|FILE_SHARE_WRITE,NULL,OPEN_EXISTING, FILE_FLAG_BACKUP_SEMANTICS|FILE_FLAG_SEQUENTIAL_SCAN,NULL); } @@ -521,11 +557,11 @@ bool SetFileCompression(const wchar *Name,bool State) } -void ResetFileCache(const wchar *Name) +void ResetFileCache(const std::wstring &Name) { // To reset file cache in Windows it is enough to open it with // FILE_FLAG_NO_BUFFERING and then close it. - HANDLE hSrc=CreateFile(Name,GENERIC_READ, + HANDLE hSrc=CreateFile(Name.c_str(),GENERIC_READ, FILE_SHARE_READ|FILE_SHARE_WRITE, NULL,OPEN_EXISTING,FILE_FLAG_NO_BUFFERING,NULL); if (hSrc!=INVALID_HANDLE_VALUE) @@ -542,3 +578,69 @@ void ResetFileCache(const wchar *Name) + + +// Delete symbolic links in file path, if any, and replace them by directories. +// Prevents extracting files outside of destination folder with symlink chains. +bool LinksToDirs(const std::wstring &SrcName,const std::wstring &SkipPart,std::wstring &LastChecked) +{ + // Unlike Unix, Windows doesn't expand lnk1 in symlink targets like + // "lnk1/../dir", but converts the path to "dir". In Unix we need to call + // this function to prevent placing unpacked files outside of destination + // folder if previously we unpacked "dir/lnk1" -> "..", + // "dir/lnk2" -> "lnk1/.." and "dir/lnk2/anypath/poc.txt". + // We may still need this function to prevent abusing symlink chains + // in link source path if we remove detection of such chains + // in IsRelativeSymlinkSafe. This function seems to make other symlink + // related safety checks redundant, but for now we prefer to keep them too. + // + // 2022.12.01: the performance impact is minimized after adding the check + // against the previous path and enabling this verification only after + // extracting a symlink with ".." in target. So we enabled it for Windows + // as well for extra safety. +//#ifdef _UNIX + std::wstring Path=SrcName; + + size_t SkipLength=SkipPart.size(); + + if (SkipLength>0 && Path.rfind(SkipPart,0)!=0) + SkipLength=0; // Parameter validation, not really needed now. + + // Do not check parts already checked in previous path to improve performance. + for (size_t I=0;ISkipLength) + SkipLength=I; + + // Avoid converting symlinks in destination path part specified by user. + while (SkipLength0) + for (size_t I=Path.size()-1;I>SkipLength;I--) + if (IsPathDiv(Path[I])) + { + Path.erase(I); + FindData FD; + if (FindFile::FastFind(Path,&FD,true) && FD.IsLink) + { +#ifdef _WIN_ALL + // Normally Windows symlinks to directory look like a directory + // and are deleted with DelDir(). It is possible to create + // a file-like symlink pointing at directory, which can be deleted + // only with && DelFile, but such symlink isn't really functional. + // Here we prefer to fail deleting such symlink and skip extracting + // a file. + if (!DelDir(Path)) +#else + if (!DelFile(Path)) +#endif + { + ErrHandler.CreateErrorMsg(SrcName); // Extraction command will skip this file or directory. + return false; // Couldn't delete the symlink to replace it with directory. + } + } + } + LastChecked=SrcName; +//#endif + return true; +} diff --git a/vendor/unrar/filefn.hpp b/vendor/unrar/filefn.hpp index 53d86653fe..4e06197391 100644 --- a/vendor/unrar/filefn.hpp +++ b/vendor/unrar/filefn.hpp @@ -3,47 +3,52 @@ enum MKDIR_CODE {MKDIR_SUCCESS,MKDIR_ERROR,MKDIR_BADPATH}; -MKDIR_CODE MakeDir(const wchar *Name,bool SetAttr,uint Attr); -bool CreatePath(const wchar *Path,bool SkipLastName,bool Silent); -void SetDirTime(const wchar *Name,RarTime *ftm,RarTime *ftc,RarTime *fta); -bool IsRemovable(const wchar *Name); +MKDIR_CODE MakeDir(const std::wstring &Name,bool SetAttr,uint Attr); +bool CreateDir(const std::wstring &Name); +bool CreatePath(const std::wstring &Path,bool SkipLastName,bool Silent); +void SetDirTime(const std::wstring &Name,RarTime *ftm,RarTime *ftc,RarTime *fta); +bool IsRemovable(const std::wstring &Name); #ifndef SFX_MODULE -int64 GetFreeDisk(const wchar *Name); +int64 GetFreeDisk(const std::wstring &Name); #endif #if defined(_WIN_ALL) && !defined(SFX_MODULE) && !defined(SILENT) -bool IsFAT(const wchar *Root); +bool IsFAT(const std::wstring &Root); #endif -bool FileExist(const wchar *Name); -bool WildFileExist(const wchar *Name); +bool FileExist(const std::wstring &Name); +bool WildFileExist(const std::wstring &Name); bool IsDir(uint Attr); bool IsUnreadable(uint Attr); bool IsLink(uint Attr); -void SetSFXMode(const wchar *FileName); -void EraseDiskContents(const wchar *FileName); +void SetSFXMode(const std::wstring &FileName); +void EraseDiskContents(const std::wstring &FileName); bool IsDeleteAllowed(uint FileAttr); -void PrepareToDelete(const wchar *Name); -uint GetFileAttr(const wchar *Name); -bool SetFileAttr(const wchar *Name,uint Attr); +void PrepareToDelete(const std::wstring &Name); +uint GetFileAttr(const std::wstring &Name); +bool SetFileAttr(const std::wstring &Name,uint Attr); wchar* MkTemp(wchar *Name,size_t MaxSize); +bool MkTemp(std::wstring &Name); enum CALCFSUM_FLAGS {CALCFSUM_SHOWTEXT=1,CALCFSUM_SHOWPERCENT=2,CALCFSUM_SHOWPROGRESS=4,CALCFSUM_CURPOS=8}; void CalcFileSum(File *SrcFile,uint *CRC32,byte *Blake2,uint Threads,int64 Size=INT64NDF,uint Flags=0); -bool RenameFile(const wchar *SrcName,const wchar *DestName); -bool DelFile(const wchar *Name); -bool DelDir(const wchar *Name); +bool RenameFile(const std::wstring &SrcName,const std::wstring &DestName); +bool DelFile(const std::wstring &Name); +bool DelDir(const std::wstring &Name); #if defined(_WIN_ALL) && !defined(SFX_MODULE) -bool SetFileCompression(const wchar *Name,bool State); -void ResetFileCache(const wchar *Name); +bool SetFileCompression(const std::wstring &Name,bool State); +void ResetFileCache(const std::wstring &Name); #endif +// Keep it here and not in extinfo.cpp, because it is invoked from Zip.SFX too. +bool LinksToDirs(const std::wstring &SrcName,const std::wstring &SkipPart,std::wstring &LastChecked); + #endif diff --git a/vendor/unrar/filestr.cpp b/vendor/unrar/filestr.cpp index a5d29d74bc..ec45654d2d 100644 --- a/vendor/unrar/filestr.cpp +++ b/vendor/unrar/filestr.cpp @@ -1,7 +1,7 @@ #include "rar.hpp" bool ReadTextFile( - const wchar *Name, + const std::wstring &Name, StringList *List, bool Config, bool AbortOnError, @@ -10,17 +10,15 @@ bool ReadTextFile( bool SkipComments, bool ExpandEnvStr) { - wchar FileName[NM]; - *FileName=0; + std::wstring FileName; - if (Name!=NULL) - if (Config) - GetConfigName(Name,FileName,ASIZE(FileName),true,false); - else - wcsncpyz(FileName,Name,ASIZE(FileName)); + if (Config) + GetConfigName(Name,FileName,true,false); + else + FileName=Name; File SrcFile; - if (*FileName!=0) + if (!FileName.empty()) { bool OpenCode=AbortOnError ? SrcFile.WOpen(FileName):SrcFile.Open(FileName,0); @@ -34,36 +32,36 @@ bool ReadTextFile( else SrcFile.SetHandleType(FILE_HANDLESTD); - uint DataSize=0,ReadSize; + size_t DataSize=0,ReadSize; const int ReadBlock=4096; - Array Data(ReadBlock); + std::vector Data(ReadBlock); while ((ReadSize=SrcFile.Read(&Data[DataSize],ReadBlock))!=0) { DataSize+=ReadSize; - Data.Add(ReadSize); // Always have ReadBlock available for next data. + Data.resize(DataSize+ReadBlock); // Always have ReadBlock available for next data. } // Set to really read size, so we can zero terminate it correctly. - Data.Alloc(DataSize); + Data.resize(DataSize); int LittleEndian=DataSize>=2 && Data[0]==255 && Data[1]==254 ? 1:0; int BigEndian=DataSize>=2 && Data[0]==254 && Data[1]==255 ? 1:0; bool Utf8=DataSize>=3 && Data[0]==0xef && Data[1]==0xbb && Data[2]==0xbf; if (SrcCharset==RCH_DEFAULT) - SrcCharset=DetectTextEncoding(&Data[0],DataSize); + SrcCharset=DetectTextEncoding(Data.data(),DataSize); - Array DataW; + std::vector DataW(ReadBlock); if (SrcCharset==RCH_DEFAULT || SrcCharset==RCH_OEM || SrcCharset==RCH_ANSI) { - Data.Push(0); // Zero terminate. + Data.push_back(0); // Zero terminate. #if defined(_WIN_ALL) if (SrcCharset==RCH_OEM) - OemToCharA((char *)&Data[0],(char *)&Data[0]); + OemToCharA((char *)Data.data(),(char *)Data.data()); #endif - DataW.Alloc(Data.Size()); - CharToWide((char *)&Data[0],&DataW[0],DataW.Size()); + DataW.resize(Data.size()); + CharToWide((char *)Data.data(),DataW.data(),DataW.size()); } if (SrcCharset==RCH_UNICODE) @@ -75,8 +73,8 @@ bool ReadTextFile( LittleEndian=1; } - DataW.Alloc(Data.Size()/2+1); - size_t End=Data.Size() & ~1; // We need even bytes number for UTF-16. + DataW.resize(Data.size()/2+1); + size_t End=Data.size() & ~1; // We need even bytes number for UTF-16. for (size_t I=Start;IAddString(ExpName); + Expanded=true; } #endif if (!Expanded && *CurStr!=0) diff --git a/vendor/unrar/filestr.hpp b/vendor/unrar/filestr.hpp index febd0a2925..3c28130495 100644 --- a/vendor/unrar/filestr.hpp +++ b/vendor/unrar/filestr.hpp @@ -2,7 +2,7 @@ #define _RAR_FILESTR_ bool ReadTextFile( - const wchar *Name, + const std::wstring &Name, StringList *List, bool Config, bool AbortOnError=false, diff --git a/vendor/unrar/find.cpp b/vendor/unrar/find.cpp index c9f2c5768c..64d933eb6c 100644 --- a/vendor/unrar/find.cpp +++ b/vendor/unrar/find.cpp @@ -2,7 +2,6 @@ FindFile::FindFile() { - *FindMask=0; FirstCall=true; #ifdef _WIN_ALL hFind=INVALID_HANDLE_VALUE; @@ -24,9 +23,9 @@ FindFile::~FindFile() } -void FindFile::SetMask(const wchar *Mask) +void FindFile::SetMask(const std::wstring &Mask) { - wcsncpyz(FindMask,Mask,ASIZE(FindMask)); + FindMask=Mask; FirstCall=true; } @@ -34,7 +33,7 @@ void FindFile::SetMask(const wchar *Mask) bool FindFile::Next(FindData *fd,bool GetSymLink) { fd->Error=false; - if (*FindMask==0) + if (FindMask.empty()) return false; #ifdef _WIN_ALL if (FirstCall) @@ -48,14 +47,14 @@ bool FindFile::Next(FindData *fd,bool GetSymLink) #else if (FirstCall) { - wchar DirName[NM]; - wcsncpyz(DirName,FindMask,ASIZE(DirName)); + std::wstring DirName; + DirName=FindMask; RemoveNameFromPath(DirName); - if (*DirName==0) - wcsncpyz(DirName,L".",ASIZE(DirName)); - char DirNameA[NM]; - WideToChar(DirName,DirNameA,ASIZE(DirNameA)); - if ((dirp=opendir(DirNameA))==NULL) + if (DirName.empty()) + DirName=L"."; + std::string DirNameA; + WideToChar(DirName,DirNameA); + if ((dirp=opendir(DirNameA.c_str()))==NULL) { fd->Error=(errno!=ENOENT); return false; @@ -63,32 +62,31 @@ bool FindFile::Next(FindData *fd,bool GetSymLink) } while (1) { - wchar Name[NM]; + std::wstring Name; struct dirent *ent=readdir(dirp); if (ent==NULL) return false; if (strcmp(ent->d_name,".")==0 || strcmp(ent->d_name,"..")==0) continue; - if (!CharToWide(ent->d_name,Name,ASIZE(Name))) - uiMsg(UIERROR_INVALIDNAME,UINULL,Name); + if (!CharToWide(std::string(ent->d_name),Name)) + uiMsg(UIERROR_INVALIDNAME,L"",Name); if (CmpName(FindMask,Name,MATCH_NAMES)) { - wchar FullName[NM]; - wcsncpyz(FullName,FindMask,ASIZE(FullName)); - *PointToName(FullName)=0; - if (wcslen(FullName)+wcslen(Name)>=ASIZE(FullName)-1) + std::wstring FullName=FindMask; + FullName.erase(GetNamePos(FullName)); + if (FullName.size()+Name.size()>=MAXPATHSIZE) { uiMsg(UIERROR_PATHTOOLONG,FullName,L"",Name); return false; } - wcsncatz(FullName,Name,ASIZE(FullName)); + FullName+=Name; if (!FastFind(FullName,fd,GetSymLink)) { ErrHandler.OpenErrorMsg(FullName); continue; } - wcsncpyz(fd->Name,FullName,ASIZE(fd->Name)); + fd->Name=FullName; break; } } @@ -98,14 +96,14 @@ bool FindFile::Next(FindData *fd,bool GetSymLink) fd->IsLink=IsLink(fd->FileAttr); FirstCall=false; - wchar *NameOnly=PointToName(fd->Name); - if (wcscmp(NameOnly,L".")==0 || wcscmp(NameOnly,L"..")==0) + std::wstring NameOnly=PointToName(fd->Name); + if (NameOnly==L"." || NameOnly==L"..") return Next(fd); return true; } -bool FindFile::FastFind(const wchar *FindMask,FindData *fd,bool GetSymLink) +bool FindFile::FastFind(const std::wstring &FindMask,FindData *fd,bool GetSymLink) { fd->Error=false; #ifndef _UNIX @@ -118,16 +116,16 @@ bool FindFile::FastFind(const wchar *FindMask,FindData *fd,bool GetSymLink) return false; FindClose(hFind); #elif defined(_UNIX) - char FindMaskA[NM]; - WideToChar(FindMask,FindMaskA,ASIZE(FindMaskA)); + std::string FindMaskA; + WideToChar(FindMask,FindMaskA); struct stat st; if (GetSymLink) { #ifdef SAVE_LINKS - if (lstat(FindMaskA,&st)!=0) + if (lstat(FindMaskA.c_str(),&st)!=0) #else - if (stat(FindMaskA,&st)!=0) + if (stat(FindMaskA.c_str(),&st)!=0) #endif { fd->Error=(errno!=ENOENT); @@ -135,7 +133,7 @@ bool FindFile::FastFind(const wchar *FindMask,FindData *fd,bool GetSymLink) } } else - if (stat(FindMaskA,&st)!=0) + if (stat(FindMaskA.c_str(),&st)!=0) { fd->Error=(errno!=ENOENT); return false; @@ -145,7 +143,7 @@ bool FindFile::FastFind(const wchar *FindMask,FindData *fd,bool GetSymLink) File::StatToRarTime(st,&fd->mtime,&fd->ctime,&fd->atime); - wcsncpyz(fd->Name,FindMask,ASIZE(fd->Name)); + fd->Name=FindMask; #endif fd->Flags=0; fd->IsDir=IsDir(fd->FileAttr); @@ -156,17 +154,17 @@ bool FindFile::FastFind(const wchar *FindMask,FindData *fd,bool GetSymLink) #ifdef _WIN_ALL -HANDLE FindFile::Win32Find(HANDLE hFind,const wchar *Mask,FindData *fd) +HANDLE FindFile::Win32Find(HANDLE hFind,const std::wstring &Mask,FindData *fd) { WIN32_FIND_DATA FindData; if (hFind==INVALID_HANDLE_VALUE) { - hFind=FindFirstFile(Mask,&FindData); + hFind=FindFirstFile(Mask.c_str(),&FindData); if (hFind==INVALID_HANDLE_VALUE) { - wchar LongMask[NM]; - if (GetWinLongPath(Mask,LongMask,ASIZE(LongMask))) - hFind=FindFirstFile(LongMask,&FindData); + std::wstring LongMask; + if (GetWinLongPath(Mask,LongMask)) + hFind=FindFirstFile(LongMask.c_str(),&FindData); } if (hFind==INVALID_HANDLE_VALUE) { @@ -190,8 +188,8 @@ HANDLE FindFile::Win32Find(HANDLE hFind,const wchar *Mask,FindData *fd) if (hFind!=INVALID_HANDLE_VALUE) { - wcsncpyz(fd->Name,Mask,ASIZE(fd->Name)); - SetName(fd->Name,FindData.cFileName,ASIZE(fd->Name)); + fd->Name=Mask; + SetName(fd->Name,FindData.cFileName); fd->Size=INT32TO64(FindData.nFileSizeHigh,FindData.nFileSizeLow); fd->FileAttr=FindData.dwFileAttributes; fd->ftCreationTime=FindData.ftCreationTime; diff --git a/vendor/unrar/find.hpp b/vendor/unrar/find.hpp index 250637f8ac..6812def7e5 100644 --- a/vendor/unrar/find.hpp +++ b/vendor/unrar/find.hpp @@ -7,7 +7,7 @@ enum FINDDATA_FLAGS { struct FindData { - wchar Name[NM]; + std::wstring Name; uint64 Size; uint FileAttr; bool IsDir; @@ -28,10 +28,10 @@ class FindFile { private: #ifdef _WIN_ALL - static HANDLE Win32Find(HANDLE hFind,const wchar *Mask,FindData *fd); + static HANDLE Win32Find(HANDLE hFind,const std::wstring &Mask,FindData *fd); #endif - wchar FindMask[NM]; + std::wstring FindMask; bool FirstCall; #ifdef _WIN_ALL HANDLE hFind; @@ -41,9 +41,9 @@ class FindFile public: FindFile(); ~FindFile(); - void SetMask(const wchar *Mask); + void SetMask(const std::wstring &Mask); bool Next(FindData *fd,bool GetSymLink=false); - static bool FastFind(const wchar *FindMask,FindData *fd,bool GetSymLink=false); + static bool FastFind(const std::wstring &FindMask,FindData *fd,bool GetSymLink=false); }; #endif diff --git a/vendor/unrar/getbits.cpp b/vendor/unrar/getbits.cpp index 5d5ad2bb2c..a5c8c3af4a 100644 --- a/vendor/unrar/getbits.cpp +++ b/vendor/unrar/getbits.cpp @@ -5,11 +5,11 @@ BitInput::BitInput(bool AllocBuffer) ExternalBuffer=false; if (AllocBuffer) { - // getbits*() attempt to read data from InAddr, ... InAddr+4 positions. - // So let's allocate 4 additional bytes for situation, when we need to + // getbits*() attempt to read data from InAddr, ... InAddr+8 positions. + // So let's allocate 8 additional bytes for situation, when we need to // read only 1 byte from the last position of buffer and avoid a crash - // from access to next 4 bytes, which contents we do not need. - size_t BufSize=MAX_SIZE+4; + // from access to next 8 bytes, which contents we do not need. + size_t BufSize=MAX_SIZE+8; InBuf=new byte[BufSize]; // Ensure that we get predictable results when accessing bytes in area @@ -17,7 +17,7 @@ BitInput::BitInput(bool AllocBuffer) memset(InBuf,0,BufSize); } else - InBuf=NULL; + InBuf=nullptr; } @@ -30,14 +30,14 @@ BitInput::~BitInput() void BitInput::faddbits(uint Bits) { - // Function wrapped version of inline addbits to save code size. + // Function wrapped version of inline addbits to reduce the code size. addbits(Bits); } uint BitInput::fgetbits() { - // Function wrapped version of inline getbits to save code size. + // Function wrapped version of inline getbits to reduce the code size. return getbits(); } diff --git a/vendor/unrar/getbits.hpp b/vendor/unrar/getbits.hpp index 00acbea945..65fb25a140 100644 --- a/vendor/unrar/getbits.hpp +++ b/vendor/unrar/getbits.hpp @@ -34,8 +34,7 @@ class BitInput uint getbits() { #if defined(LITTLE_ENDIAN) && defined(ALLOW_MISALIGNED) - uint32 BitField=*(uint32*)(InBuf+InAddr); - BitField=ByteSwap32(BitField); + uint32 BitField=RawGetBE4(InBuf+InAddr); BitField >>= (16-InBit); #else uint BitField=(uint)InBuf[InAddr] << 16; @@ -51,19 +50,21 @@ class BitInput // Bit at (InAddr,InBit) has the highest position in returning data. uint getbits32() { -#if defined(LITTLE_ENDIAN) && defined(ALLOW_MISALIGNED) - uint32 BitField=*(uint32*)(InBuf+InAddr); - BitField=ByteSwap32(BitField); -#else - uint BitField=(uint)InBuf[InAddr] << 24; - BitField|=(uint)InBuf[InAddr+1] << 16; - BitField|=(uint)InBuf[InAddr+2] << 8; - BitField|=(uint)InBuf[InAddr+3]; -#endif + uint BitField=RawGetBE4(InBuf+InAddr); BitField <<= InBit; BitField|=(uint)InBuf[InAddr+4] >> (8-InBit); return BitField & 0xffffffff; } + + // Return 64 bits from current position in the buffer. + // Bit at (InAddr,InBit) has the highest position in returning data. + uint64 getbits64() + { + uint64 BitField=RawGetBE8(InBuf+InAddr); + BitField <<= InBit; + BitField|=(uint)InBuf[InAddr+8] >> (8-InBit); + return BitField; + } void faddbits(uint Bits); uint fgetbits(); diff --git a/vendor/unrar/hardlinks.cpp b/vendor/unrar/hardlinks.cpp index 171b5fa087..5080da056a 100644 --- a/vendor/unrar/hardlinks.cpp +++ b/vendor/unrar/hardlinks.cpp @@ -1,4 +1,4 @@ -bool ExtractHardlink(CommandData *Cmd,wchar *NameNew,wchar *NameExisting,size_t NameExistingSize) +bool ExtractHardlink(CommandData *Cmd,const std::wstring &NameNew,const std::wstring &NameExisting) { if (!FileExist(NameExisting)) { @@ -10,7 +10,7 @@ bool ExtractHardlink(CommandData *Cmd,wchar *NameNew,wchar *NameExisting,size_t CreatePath(NameNew,true,Cmd->DisableNames); #ifdef _WIN_ALL - bool Success=CreateHardLink(NameNew,NameExisting,NULL)!=0; + bool Success=CreateHardLink(NameNew.c_str(),NameExisting.c_str(),NULL)!=0; if (!Success) { uiMsg(UIERROR_HLINKCREATE,NameNew); @@ -19,10 +19,10 @@ bool ExtractHardlink(CommandData *Cmd,wchar *NameNew,wchar *NameExisting,size_t } return Success; #elif defined(_UNIX) - char NameExistingA[NM],NameNewA[NM]; - WideToChar(NameExisting,NameExistingA,ASIZE(NameExistingA)); - WideToChar(NameNew,NameNewA,ASIZE(NameNewA)); - bool Success=link(NameExistingA,NameNewA)==0; + std::string NameExistingA,NameNewA; + WideToChar(NameExisting,NameExistingA); + WideToChar(NameNew,NameNewA); + bool Success=link(NameExistingA.c_str(),NameNewA.c_str())==0; if (!Success) { uiMsg(UIERROR_HLINKCREATE,NameNew); diff --git a/vendor/unrar/hash.cpp b/vendor/unrar/hash.cpp index 106cc60833..cde3db913d 100644 --- a/vendor/unrar/hash.cpp +++ b/vendor/unrar/hash.cpp @@ -76,7 +76,7 @@ void DataHash::Init(HASH_TYPE Type,uint MaxThreads) if (Type==HASH_BLAKE2) blake2sp_init(blake2ctx); #ifdef RAR_SMP - DataHash::MaxThreads=Min(MaxThreads,MaxHashThreads); + DataHash::MaxThreads=Min(MaxThreads,HASH_POOL_THREADS); #endif } @@ -88,13 +88,19 @@ void DataHash::Update(const void *Data,size_t DataSize) CurCRC32=Checksum14((ushort)CurCRC32,Data,DataSize); #endif if (HashType==HASH_CRC32) + { +#ifdef RAR_SMP + UpdateCRC32MT(Data,DataSize); +#else CurCRC32=CRC32(CurCRC32,Data,DataSize); +#endif + } if (HashType==HASH_BLAKE2) { #ifdef RAR_SMP - if (MaxThreads>1 && ThPool==NULL) - ThPool=new ThreadPool(BLAKE2_THREADS_NUMBER); + if (MaxThreads>1 && ThPool==nullptr) + ThPool=new ThreadPool(HASH_POOL_THREADS); blake2ctx->ThPool=ThPool; blake2ctx->MaxThreads=MaxThreads; #endif @@ -103,6 +109,146 @@ void DataHash::Update(const void *Data,size_t DataSize) } +#ifdef RAR_SMP +THREAD_PROC(BuildCRC32Thread) +{ + DataHash::CRC32ThreadData *td=(DataHash::CRC32ThreadData *)Data; + + // Use 0 initial value to simplify combining the result with existing CRC32. + // It doesn't affect the first initial 0xffffffff in the data beginning. + // If we used 0xffffffff here, we would need to shift 0xffffffff left to + // block width and XOR it with block CRC32 to reset its initial value to 0. + td->DataCRC=CRC32(0,td->Data,td->DataSize); +} + + +// CRC is linear and distributive over addition, so CRC(a+b)=CRC(a)+CRC(b). +// Since addition in finite field is XOR, we have CRC(a^b)=CRC(a)^CRC(b). +// So CRC(aaabbb) = CRC(aaa000) ^ CRC(000bbb) = CRC(aaa000) ^ CRC(bbb), +// because CRC ignores leading zeroes. Thus to split CRC calculations +// to "aaa" and "bbb" blocks and then to threads we need to be able to +// find CRC(aaa000) knowing "aaa" quickly. We use Galois finite field to +// calculate the power of 2 to get "1000" and multiply it by "aaa". +void DataHash::UpdateCRC32MT(const void *Data,size_t DataSize) +{ + const size_t MinBlock=0x4000; + if (DataSize<2*MinBlock || MaxThreads<2) + { + CurCRC32=CRC32(CurCRC32,Data,DataSize); + return; + } + + if (ThPool==nullptr) + ThPool=new ThreadPool(HASH_POOL_THREADS); + + size_t Threads=MaxThreads; + size_t BlockSize=DataSize/Threads; + if (BlockSizeAddTask(BuildCRC32Thread,(void*)&td[I]); +#else + BuildCRC32Thread((void*)&td[I]); +#endif + } + +#ifdef USE_THREADS + ThPool->WaitDone(); +#endif // USE_THREADS + + uint StdShift=gfExpCRC(uint(8*td[0].DataSize)); + for (size_t I=0;I>=1) + Reversed|=(N & 1)<<(31-I); + return Reversed; +} + + +// Galois field multiplication modulo POLY. +uint DataHash::gfMulCRC(uint A, uint B) +{ + // For reversed 0xEDB88320 polynomial we bit reverse CRC32 before passing + // to this function, so we must use the normal polynomial here. + // We set the highest polynomial bit 33 for proper multiplication + // in case uint is larger than 32-bit. + const uint POLY=uint(0x104c11db7); + + uint R = 0 ; // Multiplication result. + while (A != 0 && B != 0) // If any of multipliers becomes 0, quit early. + { + // For non-zero lowest B bit, add A to result. + R ^= (B & 1)!=0 ? A : 0; + + // Make A twice larger before the next iteration. + // Subtract POLY to keep it modulo POLY if high bit is set. + A = (A << 1) ^ ((A & 0x80000000)!=0 ? POLY : 0); + + B >>= 1; // Move next B bit to lowest position. + } + return R; +} + + +// Calculate 2 power N with square-and-multiply algorithm. +uint DataHash::gfExpCRC(uint N) +{ + uint S = 2; // Starts from base value and contains the current square. + uint R = 1; // Exponentiation result. + while (N > 1) + { + if ((N & 1)!=0) // If N is odd. + R = gfMulCRC(R, S); + S = gfMulCRC(S, S); // Next square. + N >>= 1; + } + // We could change the loop condition to N > 0 and return R at expense + // of one additional gfMulCRC(S, S). + return gfMulCRC(R, S); +} + + void DataHash::Result(HashValue *Result) { Result->Type=HashType; diff --git a/vendor/unrar/hash.hpp b/vendor/unrar/hash.hpp index 6315680e78..0189113e94 100644 --- a/vendor/unrar/hash.hpp +++ b/vendor/unrar/hash.hpp @@ -32,7 +32,24 @@ class DataHash; class DataHash { + public: + struct CRC32ThreadData + { + void *Data; + size_t DataSize; + uint DataCRC; + }; private: + void UpdateCRC32MT(const void *Data,size_t DataSize); + uint BitReverse32(uint N); + uint gfMulCRC(uint A, uint B); + uint gfExpCRC(uint N); + + // Speed gain seems to vanish above 8 CRC32 threads. + static const uint CRC32_POOL_THREADS=8; + // Thread pool must allow at least BLAKE2_THREADS_NUMBER threads. + static const uint HASH_POOL_THREADS=Max(BLAKE2_THREADS_NUMBER,CRC32_POOL_THREADS); + HASH_TYPE HashType; uint CurCRC32; blake2sp_state *blake2ctx; @@ -41,8 +58,6 @@ class DataHash ThreadPool *ThPool; uint MaxThreads; - // Upper limit for maximum threads to prevent wasting threads in pool. - static const uint MaxHashThreads=8; #endif public: DataHash(); diff --git a/vendor/unrar/headers.cpp b/vendor/unrar/headers.cpp index b441376c56..b2d00d3b9f 100644 --- a/vendor/unrar/headers.cpp +++ b/vendor/unrar/headers.cpp @@ -2,7 +2,7 @@ void FileHeader::Reset(size_t SubDataSize) { - SubData.Alloc(SubDataSize); + SubData.resize(SubDataSize); BaseBlock::Reset(); FileHash.Init(HASH_NONE); mtime.Reset(); @@ -37,6 +37,7 @@ void FileHeader::Reset(size_t SubDataSize) } +/* FileHeader& FileHeader::operator = (FileHeader &hd) { SubData.Reset(); @@ -45,6 +46,7 @@ FileHeader& FileHeader::operator = (FileHeader &hd) SubData=hd.SubData; return *this; } +*/ void MainHeader::Reset() diff --git a/vendor/unrar/headers.hpp b/vendor/unrar/headers.hpp index 5984f99629..8697e3887c 100644 --- a/vendor/unrar/headers.hpp +++ b/vendor/unrar/headers.hpp @@ -15,8 +15,10 @@ #define VER_PACK 29U #define VER_PACK5 50U // It is stored as 0, but we subtract 50 when saving an archive. +#define VER_PACK7 70U // It is stored as 1, but we subtract 70 when saving an archive. #define VER_UNPACK 29U #define VER_UNPACK5 50U // It is stored as 0, but we add 50 when reading an archive. +#define VER_UNPACK7 70U // It is stored as 1, but we add 50 when reading an archive. #define VER_UNKNOWN 9999U // Just some large value. #define MHD_VOLUME 0x0001U @@ -82,7 +84,7 @@ enum HEADER_TYPE { }; -// RAR 2.9 and earlier. +// RAR 2.9 and earlier service haeders, mostly outdated and not supported. enum { EA_HEAD=0x100,UO_HEAD=0x101,MAC_HEAD=0x102,BEEA_HEAD=0x103, NTACL_HEAD=0x104,STREAM_HEAD=0x105 }; @@ -147,6 +149,14 @@ struct BaseBlock { SkipIfUnknown=false; } + + // We use it to assign this block data to inherited blocks. + // Such function seems to be cleaner than '(BaseBlock&)' cast or adding + // 'using BaseBlock::operator=;' to every inherited header. + void SetBaseBlock(BaseBlock &Src) + { + *this=Src; + } }; @@ -184,9 +194,9 @@ struct FileHeader:BlockHeader uint FileAttr; uint SubFlags; }; - wchar FileName[NM]; + std::wstring FileName; - Array SubData; + std::vector SubData; RarTime mtime; RarTime ctime; @@ -226,7 +236,7 @@ struct FileHeader:BlockHeader bool Dir; bool CommentInHeader; // RAR 2.0 file comment. bool Version; // name.ext;ver file name containing the version number. - size_t WinSize; + uint64 WinSize; bool Inherited; // New file inherits a subblock when updating a host file (for subblocks only). // 'true' if file sizes use 8 bytes instead of 4. Not used in RAR 5.0. @@ -239,7 +249,7 @@ struct FileHeader:BlockHeader HOST_SYSTEM_TYPE HSType; FILE_SYSTEM_REDIRECT RedirType; - wchar RedirName[NM]; + std::wstring RedirName; bool DirTarget; bool UnixOwnerSet,UnixOwnerNumeric,UnixGroupNumeric; @@ -256,10 +266,10 @@ struct FileHeader:BlockHeader bool CmpName(const wchar *Name) { - return(wcscmp(FileName,Name)==0); + return FileName==Name; } - FileHeader& operator = (FileHeader &hd); +// FileHeader& operator = (FileHeader &hd); }; @@ -340,7 +350,7 @@ struct StreamHeader:SubBlockHeader byte Method; uint StreamCRC; ushort StreamNameSize; - char StreamName[260]; + std::string StreamName; }; diff --git a/vendor/unrar/headers5.hpp b/vendor/unrar/headers5.hpp index 50f5955d1d..361e554df2 100644 --- a/vendor/unrar/headers5.hpp +++ b/vendor/unrar/headers5.hpp @@ -42,20 +42,27 @@ // RAR 5.0 file compression flags. -#define FCI_ALGO_BIT0 0x0001 // Version of compression algorithm. -#define FCI_ALGO_BIT1 0x0002 // 0 .. 63. -#define FCI_ALGO_BIT2 0x0004 -#define FCI_ALGO_BIT3 0x0008 -#define FCI_ALGO_BIT4 0x0010 -#define FCI_ALGO_BIT5 0x0020 -#define FCI_SOLID 0x0040 // Solid flag. -#define FCI_METHOD_BIT0 0x0080 // Compression method. -#define FCI_METHOD_BIT1 0x0100 // 0 .. 5 (6 and 7 are not used). -#define FCI_METHOD_BIT2 0x0200 -#define FCI_DICT_BIT0 0x0400 // Dictionary size. -#define FCI_DICT_BIT1 0x0800 // 128 KB .. 4 GB. -#define FCI_DICT_BIT2 0x1000 -#define FCI_DICT_BIT3 0x2000 +#define FCI_ALGO_BIT0 0x00000001 // Version of compression algorithm. +#define FCI_ALGO_BIT1 0x00000002 // 0 .. 63. +#define FCI_ALGO_BIT2 0x00000004 +#define FCI_ALGO_BIT3 0x00000008 +#define FCI_ALGO_BIT4 0x00000010 +#define FCI_ALGO_BIT5 0x00000020 +#define FCI_SOLID 0x00000040 // Solid flag. +#define FCI_METHOD_BIT0 0x00000080 // Compression method. +#define FCI_METHOD_BIT1 0x00000100 // 0 .. 5 (6 and 7 are not used). +#define FCI_METHOD_BIT2 0x00000200 +#define FCI_DICT_BIT0 0x00000400 // Dictionary size. +#define FCI_DICT_BIT1 0x00000800 // 128 KB .. 1 TB. +#define FCI_DICT_BIT2 0x00001000 +#define FCI_DICT_BIT3 0x00002000 +#define FCI_DICT_BIT4 0x00004000 +#define FCI_DICT_FRACT0 0x00008000 // Dictionary fraction in 1/32 of size. +#define FCI_DICT_FRACT1 0x00010000 +#define FCI_DICT_FRACT2 0x00020000 +#define FCI_DICT_FRACT3 0x00040000 +#define FCI_DICT_FRACT4 0x00080000 +#define FCI_RAR5_COMPAT 0x00100000 // RAR7 compression flags and RAR5 compression algorithm. // Main header extra field values. #define MHEXTRA_LOCATOR 0x01 // Position of quick list and other blocks. diff --git a/vendor/unrar/isnt.cpp b/vendor/unrar/isnt.cpp index 3cc876b990..b89b2ce54d 100644 --- a/vendor/unrar/isnt.cpp +++ b/vendor/unrar/isnt.cpp @@ -40,7 +40,7 @@ static bool WMI_IsWindows10() IWbemServices *pSvc = NULL; - hres = pLoc->ConnectServer(_bstr_t(L"ROOT\\CIMV2"),NULL,NULL,NULL,NULL,0,0,&pSvc); + hres = pLoc->ConnectServer(_bstr_t(L"ROOT\\CIMV2"),NULL,NULL,NULL,0,NULL,NULL,&pSvc); if (FAILED(hres)) { @@ -62,30 +62,24 @@ static bool WMI_IsWindows10() hres = pSvc->ExecQuery(bstr_t("WQL"), bstr_t("SELECT * FROM Win32_OperatingSystem"), WBEM_FLAG_FORWARD_ONLY | WBEM_FLAG_RETURN_IMMEDIATELY, NULL, &pEnumerator); - if (FAILED(hres)) + if (FAILED(hres) || pEnumerator==NULL) { pSvc->Release(); pLoc->Release(); return false; } + bool Win10=false; + IWbemClassObject *pclsObj = NULL; ULONG uReturn = 0; - - bool Win10=false; - while (pEnumerator!=NULL) + pEnumerator->Next(WBEM_INFINITE, 1, &pclsObj, &uReturn); + if (pclsObj!=NULL && uReturn>0) { - HRESULT hr = pEnumerator->Next(WBEM_INFINITE, 1, &pclsObj, &uReturn); - - if (uReturn==0) - break; - VARIANT vtProp; - - hr = pclsObj->Get(L"Name", 0, &vtProp, 0, 0); + pclsObj->Get(L"Name", 0, &vtProp, 0, 0); Win10|=wcsstr(vtProp.bstrVal,L"Windows 10")!=NULL; VariantClear(&vtProp); - pclsObj->Release(); } diff --git a/vendor/unrar/list.cpp b/vendor/unrar/list.cpp index e4444e13ab..3eae4de651 100644 --- a/vendor/unrar/list.cpp +++ b/vendor/unrar/list.cpp @@ -1,7 +1,6 @@ #include "rar.hpp" static void ListFileHeader(Archive &Arc,FileHeader &hd,bool &TitleShown,bool Verbose,bool Technical,bool Bare,bool DisableNames); -static void ListSymLink(Archive &Arc); static void ListFileAttr(uint A,HOST_SYSTEM_TYPE HostType,wchar *AttrStr,size_t AttrSize); static void ListOldSubHeader(Archive &Arc); static void ListNewSubHeader(CommandData *Cmd,Archive &Arc); @@ -15,8 +14,8 @@ void ListArchive(CommandData *Cmd) bool Bare=(Cmd->Command[1]=='B'); bool Verbose=(Cmd->Command[0]=='V'); - wchar ArcName[NM]; - while (Cmd->GetArcName(ArcName,ASIZE(ArcName))) + std::wstring ArcName; + while (Cmd->GetArcName(ArcName)) { if (Cmd->ManualPassword) Cmd->Password.Clean(); // Clean user entered password before processing next archive. @@ -35,33 +34,31 @@ void ListArchive(CommandData *Cmd) if (!Bare) { Arc.ViewComment(); - mprintf(L"\n%s: %s",St(MListArchive),Arc.FileName); + mprintf(L"\n%s: %s",St(MListArchive),Arc.FileName.c_str()); mprintf(L"\n%s: ",St(MListDetails)); - uint SetCount=0; const wchar *Fmt=Arc.Format==RARFMT14 ? L"RAR 1.4":(Arc.Format==RARFMT15 ? L"RAR 4":L"RAR 5"); - mprintf(L"%s%s", SetCount++ > 0 ? L", ":L"", Fmt); + mprintf(L"%s", Fmt); if (Arc.Solid) - mprintf(L"%s%s", SetCount++ > 0 ? L", ":L"", St(MListSolid)); + mprintf(L", %s", St(MListSolid)); if (Arc.SFXSize>0) - mprintf(L"%s%s", SetCount++ > 0 ? L", ":L"", St(MListSFX)); + mprintf(L", %s", St(MListSFX)); if (Arc.Volume) if (Arc.Format==RARFMT50) { // RAR 5.0 archives store the volume number in main header, // so it is already available now. - if (SetCount++ > 0) - mprintf(L", "); + mprintf(L", "); mprintf(St(MVolumeNumber),Arc.VolNumber+1); } else - mprintf(L"%s%s", SetCount++ > 0 ? L", ":L"", St(MListVolume)); + mprintf(L", %s", St(MListVolume)); if (Arc.Protected) - mprintf(L"%s%s", SetCount++ > 0 ? L", ":L"", St(MListRR)); + mprintf(L", %s", St(MListRR)); if (Arc.Locked) - mprintf(L"%s%s", SetCount++ > 0 ? L", ":L"", St(MListLock)); + mprintf(L", %s", St(MListLock)); if (Arc.Encrypted) - mprintf(L"%s%s", SetCount++ > 0 ? L", ":L"", St(MListEncHead)); + mprintf(L", %s", St(MListEncHead)); if (!Arc.MainHead.OrigName.empty()) mprintf(L"\n%s: %s",St(MOrigName),Arc.MainHead.OrigName.c_str()); @@ -100,7 +97,7 @@ void ListArchive(CommandData *Cmd) switch(HeaderType) { case HEAD_FILE: - FileMatched=Cmd->IsProcessFile(Arc.FileHead,NULL,MATCH_WILDSUBPATH,0,NULL,0)!=0; + FileMatched=Cmd->IsProcessFile(Arc.FileHead,NULL,MATCH_WILDSUBPATH,0,NULL)!=0; if (FileMatched) { ListFileHeader(Arc,Arc.FileHead,TitleShown,Verbose,Technical,Bare,Cmd->DisableNames); @@ -155,7 +152,7 @@ void ListArchive(CommandData *Cmd) ArcCount++; #ifndef NOVOLUME - if (Cmd->VolSize!=0 && (Arc.FileHead.SplitAfter || + if (Cmd->VolSize==VOLSIZE_AUTO && (Arc.FileHead.SplitAfter || Arc.GetHeaderType()==HEAD_ENDARC && Arc.EndArcHead.NextVolume) && MergeArchive(Arc,NULL,false,Cmd->Command[0])) Arc.Seek(0,SEEK_SET); @@ -166,7 +163,7 @@ void ListArchive(CommandData *Cmd) else { if (Cmd->ArcNames.ItemsCount()<2 && !Bare) - mprintf(St(MNotRAR),Arc.FileName); + mprintf(St(MNotRAR),Arc.FileName.c_str()); break; } } @@ -219,7 +216,7 @@ void ListFileHeader(Archive &Arc,FileHeader &hd,bool &TitleShown,bool Verbose,bo if (DisableNames) return; - wchar *Name=hd.FileName; + const wchar *Name=hd.FileName.c_str(); RARFORMAT Format=Arc.Format; if (Bare) @@ -266,9 +263,8 @@ void ListFileHeader(Archive &Arc,FileHeader &hd,bool &TitleShown,bool Verbose,bo if (!FileBlock && Arc.SubHead.CmpName(SUBHEAD_TYPE_STREAM)) { mprintf(L"\n%12ls: %ls",St(MListType),St(MListStream)); - wchar StreamName[NM]; - GetStreamNameNTFS(Arc,StreamName,ASIZE(StreamName)); - mprintf(L"\n%12ls: %ls",St(MListTarget),StreamName); + std::wstring StreamName=GetStreamNameNTFS(Arc); + mprintf(L"\n%12ls: %ls",St(MListTarget),StreamName.c_str()); } else { @@ -292,25 +288,27 @@ void ListFileHeader(Archive &Arc,FileHeader &hd,bool &TitleShown,bool Verbose,bo if (hd.RedirType!=FSREDIR_NONE) if (Format==RARFMT15) { - char LinkTargetA[NM]; + std::string LinkTargetA; if (Arc.FileHead.Encrypted) { // Link data are encrypted. We would need to ask for password // and initialize decryption routine to display the link target. - strncpyz(LinkTargetA,"*<-?->",ASIZE(LinkTargetA)); + LinkTargetA="*<-?->"; } else { - int DataSize=(int)Min(hd.PackSize,ASIZE(LinkTargetA)-1); - Arc.Read(LinkTargetA,DataSize); - LinkTargetA[DataSize > 0 ? DataSize : 0] = 0; + size_t DataSize=(size_t)Min(hd.PackSize,MAXPATHSIZE); + std::vector Buf(DataSize+1); + Arc.Read(Buf.data(),DataSize); + Buf[DataSize] = 0; + LinkTargetA=Buf.data(); } - wchar LinkTarget[NM]; - CharToWide(LinkTargetA,LinkTarget,ASIZE(LinkTarget)); - mprintf(L"\n%12ls: %ls",St(MListTarget),LinkTarget); + std::wstring LinkTarget; + CharToWide(LinkTargetA,LinkTarget); + mprintf(L"\n%12ls: %ls",St(MListTarget),LinkTarget.c_str()); } else - mprintf(L"\n%12ls: %ls",St(MListTarget),hd.RedirName); + mprintf(L"\n%12ls: %ls",St(MListTarget),hd.RedirName.c_str()); } if (!hd.Dir) { @@ -341,11 +339,11 @@ void ListFileHeader(Archive &Arc,FileHeader &hd,bool &TitleShown,bool Verbose,bo hd.FileHash.CRC32); if (hd.FileHash.Type==HASH_BLAKE2) { - wchar BlakeStr[BLAKE2_DIGEST_SIZE*2+1]; - BinToHex(hd.FileHash.Digest,BLAKE2_DIGEST_SIZE,NULL,BlakeStr,ASIZE(BlakeStr)); + std::wstring BlakeStr; + BinToHex(hd.FileHash.Digest,BLAKE2_DIGEST_SIZE,BlakeStr); mprintf(L"\n%12ls: %ls", hd.UseHashKey ? L"BLAKE2 MAC":hd.SplitAfter ? L"Pack-BLAKE2":L"BLAKE2", - BlakeStr); + BlakeStr.c_str()); } const wchar *HostOS=L""; @@ -362,11 +360,22 @@ void ListFileHeader(Archive &Arc,FileHeader &hd,bool &TitleShown,bool Verbose,bo if (*HostOS!=0) mprintf(L"\n%12ls: %ls",St(MListHostOS),HostOS); - mprintf(L"\n%12ls: RAR %ls(v%d) -m%d -md=%d%s",St(MListCompInfo), + std::wstring WinSize; + if (!hd.Dir) + if (hd.WinSize%1073741824==0) + WinSize=L" -md=" + std::to_wstring(hd.WinSize/1073741824) + L"g"; + else + if (hd.WinSize%1048576==0) + WinSize=L" -md=" + std::to_wstring(hd.WinSize/1048576) + L"m"; + else + if (hd.WinSize>=1024) + WinSize=L" -md=" + std::to_wstring(hd.WinSize/1024) + L"k"; + else + WinSize=L" -md=?"; + + mprintf(L"\n%12ls: RAR %ls(v%d) -m%d%s",St(MListCompInfo), Format==RARFMT15 ? L"1.5":L"5.0", - hd.UnpVer==VER_UNKNOWN ? 0 : hd.UnpVer,hd.Method, - hd.WinSize>=0x100000 ? hd.WinSize/0x100000:hd.WinSize/0x400, - hd.WinSize>=0x100000 ? L"M":L"K"); + hd.UnpVer==VER_UNKNOWN ? 0 : hd.UnpVer,hd.Method,WinSize.c_str()); if (hd.Solid || hd.Encrypted) { @@ -379,7 +388,7 @@ void ListFileHeader(Archive &Arc,FileHeader &hd,bool &TitleShown,bool Verbose,bo if (hd.Version) { - uint Version=ParseVersionFileName(Name,false); + uint Version=ParseVersionFileName(hd.FileName,false); if (Version!=0) mprintf(L"\n%12ls: %u",St(MListFileVer),Version); } @@ -388,13 +397,13 @@ void ListFileHeader(Archive &Arc,FileHeader &hd,bool &TitleShown,bool Verbose,bo { mprintf(L"\n%12ls: ",L"Unix owner"); if (*hd.UnixOwnerName!=0) - mprintf(L"%ls",GetWide(hd.UnixOwnerName)); + mprintf(L"%ls",GetWide(hd.UnixOwnerName).c_str()); else if (hd.UnixOwnerNumeric) mprintf(L"#%d",hd.UnixOwnerID); mprintf(L":"); if (*hd.UnixGroupName!=0) - mprintf(L"%ls",GetWide(hd.UnixGroupName)); + mprintf(L"%ls",GetWide(hd.UnixGroupName).c_str()); else if (hd.UnixGroupNumeric) mprintf(L"#%d",hd.UnixGroupID); @@ -422,31 +431,11 @@ void ListFileHeader(Archive &Arc,FileHeader &hd,bool &TitleShown,bool Verbose,bo mprintf(L"%02x%02x..%02x ",S[0],S[1],S[31]); } else - mprintf(L"???????? "); + mprintf(hd.Dir ? L" ":L"???????? "); // Missing checksum is ok for folder, not for file. } mprintf(L"%ls",Name); } -/* -void ListSymLink(Archive &Arc) -{ - if (Arc.FileHead.HSType==HSYS_UNIX && (Arc.FileHead.FileAttr & 0xF000)==0xA000) - if (Arc.FileHead.Encrypted) - { - // Link data are encrypted. We would need to ask for password - // and initialize decryption routine to display the link target. - mprintf(L"\n%22ls %ls",L"-->",L"*<-?->"); - } - else - { - char FileName[NM]; - uint DataSize=(uint)Min(Arc.FileHead.PackSize,sizeof(FileName)-1); - Arc.Read(FileName,DataSize); - FileName[DataSize]=0; - mprintf(L"\n%22ls %ls",L"-->",GetWide(FileName)); - } -} -*/ void ListFileAttr(uint A,HOST_SYSTEM_TYPE HostType,wchar *AttrStr,size_t AttrSize) { diff --git a/vendor/unrar/loclang.hpp b/vendor/unrar/loclang.hpp index 1e23ece76b..df94a8eb25 100644 --- a/vendor/unrar/loclang.hpp +++ b/vendor/unrar/loclang.hpp @@ -45,7 +45,7 @@ #define MCHelpCmdR L"\n r Repair archive" #define MCHelpCmdRC L"\n rc Reconstruct missing volumes" #define MCHelpCmdRN L"\n rn Rename archived files" -#define MCHelpCmdRR L"\n rr[N] Add the data recovery record" +#define MCHelpCmdRR L"\n rr[N] Add data recovery record" #define MCHelpCmdRV L"\n rv[N] Create recovery volumes" #define MCHelpCmdS L"\n s[name|-] Convert archive to or from SFX" #define MCHelpCmdT L"\n t Test archive files" @@ -94,9 +94,8 @@ #define MCHelpSwKB L"\n kb Keep broken extracted files" #define MCHelpSwLog L"\n log[f][=name] Write names to log file" #define MCHelpSwMn L"\n m<0..5> Set compression level (0-store...3-default...5-maximal)" -#define MCHelpSwMA L"\n ma[4|5] Specify a version of archiving format" #define MCHelpSwMC L"\n mc Set advanced compression parameters" -#define MCHelpSwMD L"\n md[k,m,g] Dictionary size in KB, MB or GB" +#define MCHelpSwMD L"\n md[x][kmg] Dictionary size in KB, MB or GB" #define MCHelpSwME L"\n me[par] Set encryption parameters" #define MCHelpSwMS L"\n ms[ext;ext] Specify file types to store" #define MCHelpSwMT L"\n mt Set the number of threads" @@ -107,7 +106,7 @@ #define MCHelpSwOC L"\n oc Set NTFS Compressed attribute" #define MCHelpSwOH L"\n oh Save hard links as the link instead of the file" #define MCHelpSwOI L"\n oi[0-4][:min] Save identical files as references" -#define MCHelpSwOL L"\n ol[a] Process symbolic links as the link [absolute paths]" +#define MCHelpSwOL L"\n ol[a,-] Process symbolic links as the link [absolute paths, skip]" #define MCHelpSwONI L"\n oni Allow potentially incompatible names" #define MCHelpSwOP L"\n op Set the output path for extracted files" #define MCHelpSwOR L"\n or Rename files automatically" @@ -126,8 +125,8 @@ #define MCHelpSwSC L"\n sc[obj] Specify the character set" #define MCHelpSwSFX L"\n sfx[name] Create SFX archive" #define MCHelpSwSI L"\n si[name] Read data from standard input (stdin)" -#define MCHelpSwSL L"\n sl Process files with size less than specified" -#define MCHelpSwSM L"\n sm Process files with size more than specified" +#define MCHelpSwSL L"\n sl[u] Process files with size less than specified" +#define MCHelpSwSM L"\n sm[u] Process files with size more than specified" #define MCHelpSwT L"\n t Test files after archiving" #define MCHelpSwTK L"\n tk Keep original archive time" #define MCHelpSwTL L"\n tl Set archive time to latest file" @@ -139,10 +138,9 @@ #define MCHelpSwU L"\n u Update files" #define MCHelpSwV L"\n v Create volumes with size autodetection or list all volumes" #define MCHelpSwVUnr L"\n v List all volumes" -#define MCHelpSwVn L"\n v[k,b] Create volumes with size=*1000 [*1024, *1]" +#define MCHelpSwVn L"\n v[u] Create volumes with size in [bBkKmMgGtT] units" #define MCHelpSwVD L"\n vd Erase disk contents before creating volume" #define MCHelpSwVER L"\n ver[n] File version control" -#define MCHelpSwVN L"\n vn Use the old style volume naming scheme" #define MCHelpSwVP L"\n vp Pause before each volume" #define MCHelpSwW L"\n w Assign work directory" #define MCHelpSwX L"\n x Exclude specified file" @@ -165,7 +163,7 @@ #define MErrRename L"\nCannot rename %s to %s" #define MAbsNextVol L"\nCannot find volume %s" #define MBreak L"\nUser break\n" -#define MAskCreatVol L"\nCreate next volume ?" +#define MAskCreatVol L"\nCreate next volume?" #define MAskNextDisk L"\nDisk full. Insert next" #define MCreatVol L"\n\nCreating %sarchive %s\n" #define MAskNextVol L"\nInsert disk with %s" @@ -212,7 +210,7 @@ #define MCRCFailed L"\n%-20s - checksum error" #define MExtrTest L"\n\nTesting archive %s\n" #define MExtracting L"\n\nExtracting from %s\n" -#define MUseCurPsw L"\n%s - use current password ?" +#define MUseCurPsw L"\n%s - use current password?" #define MCreatDir L"\nCreating %-56s" #define MExtrSkipFile L"\nSkipping %-56s" #define MExtrTestFile L"\nTesting %-56s" @@ -225,18 +223,17 @@ #define MExtrAllOk L"\nAll OK" #define MExtrTotalErr L"\nTotal errors: %ld" #define MAskReplace L"\n\nWould you like to replace the existing file %s\n%6s bytes, modified on %s\nwith a new one\n%6s bytes, modified on %s\n" -#define MAskOverwrite L"\nOverwrite %s ?" +#define MAskOverwrite L"\nOverwrite %s?" #define MAskNewName L"\nEnter new name: " #define MHeaderBroken L"\nCorrupt header is found" #define MMainHeaderBroken L"\nMain archive header is corrupt" #define MLogFileHead L"\n%s - the file header is corrupt" #define MLogProtectHead L"The data recovery header is corrupt" +#define MArcComment L"\nArchive comment" #define MReadStdinCmt L"\nReading comment from stdin\n" #define MReadCommFrom L"\nReading comment from %s" #define MDelComment L"\nDeleting comment from %s" #define MAddComment L"\nAdding comment to %s" -#define MFCommAdd L"\nAdding file comments" -#define MAskFComm L"\n\nReading comment for %s : %s from stdin\n" #define MLogCommBrk L"\nThe archive comment is corrupt" #define MCommAskCont L"\nPress 'Enter' to continue or 'Q' to quit:" #define MWriteCommTo L"\nWrite comment to %s" @@ -284,11 +281,9 @@ #define MListHostOS L"Host OS" #define MListFileVer L"File version" #define MListService L"Service" -#define MListUOHead L"\n Unix Owner/Group data: %-14s %-14s" #define MListNTACLHead L"\n NTFS security data" #define MListStrmHead L"\n NTFS stream: %s" #define MListUnkHead L"\n Unknown subheader type: 0x%04x" -#define MFileComment L"\nComment: " #define MYes L"Yes" #define MNo L"No" #define MListNoFiles L" 0 files\n" @@ -296,10 +291,10 @@ #define MRprBuild L"\nBuilding %s" #define MRprOldFormat L"\nCannot repair archive with old format" #define MRprFind L"\nFound %s" -#define MRprAskIsSol L"\nThe archive header is corrupt. Mark archive as solid ?" +#define MRprAskIsSol L"\nThe archive header is corrupt. Mark archive as solid?" #define MRprNoFiles L"\nNo files found" #define MLogUnexpEOF L"\nUnexpected end of archive" -#define MRepAskReconst L"\nReconstruct archive structure ?" +#define MRepAskReconst L"\nReconstruct archive structure?" #define MRRSearch L"\nSearching for recovery record" #define MAnalyzeFileData L"\nAnalyzing file data" #define MRecRNotFound L"\nData recovery record not found" @@ -316,7 +311,7 @@ #define MSetOwnersError L"\nWARNING: Cannot set %s owner and group\n" #define MErrLnkRead L"\nWARNING: Cannot read symbolic link %s" #define MSymLinkExists L"\nWARNING: Symbolic link %s already exists" -#define MAskRetryCreate L"\nCannot create %s. Retry ?" +#define MAskRetryCreate L"\nCannot create %s. Retry?" #define MDataBadCRC L"\n%-20s : packed data checksum error in volume %s" #define MFileRO L"\n%s is read-only" #define MACLGetError L"\nWARNING: Cannot get %s security data\n" @@ -330,6 +325,7 @@ #define MCorrectingName L"\nWARNING: Attempting to correct the invalid file or directory name" #define MUnpCannotMerge L"\nWARNING: You need to start extraction from a previous volume to unpack %s" #define MUnknownOption L"\nERROR: Unknown option: %s" +#define MSwSyntaxError L"\nERROR: '-' is expected in the beginning of: %s" #define MSubHeadCorrupt L"\nERROR: Corrupt data header found, ignored" #define MSubHeadUnknown L"\nWARNING: Unknown data header format, ignored" #define MSubHeadDataCRC L"\nERROR: Corrupt %s data block" @@ -386,6 +382,8 @@ #define MNeedAdmin L"\nYou may need to run RAR as administrator" #define MDictOutMem L"\nNot enough memory for %d MB compression dictionary, changed to %d MB." #define MUseSmalllerDict L"\nPlease use a smaller compression dictionary." +#define MExtrDictOutMem L"\nNot enough memory to unpack the archive with %u GB compression dictionary." +#define MSuggest64bit L"\n64-bit RAR version is necessary." #define MOpenErrAtime L"\nYou may need to remove -tsp switch to open this file." #define MErrReadInfo L"\nChoose 'Ignore' to continue with the already read file part only, 'Ignore all' to do it for all read errors, 'Retry' to repeat read and 'Quit' to abort." #define MErrReadTrunc L"\n%s is archived incompletely because of read error.\n" @@ -399,3 +397,8 @@ #define MOrigName L"Original name" #define MOriginalTime L"Original time" #define MFileRenamed L"\n%s is renamed to %s" +#define MDictNotAllowed L"\n%u GB dictionary exceeds %u GB limit and needs more than %u GB memory to unpack." +#define MDictExtrAnyway L"\nUse -md%ug or -mdx%ug switches to extract anyway." +#define MDictComprLimit L"\n%u GB dictionary exceeds %u GB limit and not allowed when compressing data." +#define MNeedSFX64 L"\n64-bit self-extracting module is necessary for %u GB compression dictionary." +#define MSkipUnsafeLink L"\nSkipping the potentially unsafe %s -> %s link. For archives from a trustworthy source use -ola to extract it anyway." diff --git a/vendor/unrar/log.cpp b/vendor/unrar/log.cpp index 8bbe8ee0b5..57f7648ef6 100644 --- a/vendor/unrar/log.cpp +++ b/vendor/unrar/log.cpp @@ -1,13 +1,14 @@ #include "rar.hpp" -static wchar LogName[NM]; -static RAR_CHARSET LogCharset=RCH_DEFAULT; -void InitLogOptions(const wchar *LogFileName,RAR_CHARSET CSet) +void InitLogOptions(const std::wstring &LogFileName,RAR_CHARSET CSet) +{ +} + + +void CloseLogOptions() { - wcsncpyz(LogName,LogFileName,ASIZE(LogName)); - LogCharset=CSet; } @@ -19,17 +20,15 @@ void Log(const wchar *ArcName,const wchar *fmt,...) uiAlarm(UIALARM_ERROR); - // This buffer is for format string only, not for entire output, - // so it can be short enough. - wchar fmtw[1024]; - PrintfPrepareFmt(fmt,fmtw,ASIZE(fmtw)); - - safebuf wchar Msg[2*NM+1024]; va_list arglist; va_start(arglist,fmt); - vswprintf(Msg,ASIZE(Msg),fmtw,arglist); + + std::wstring s=vwstrprintf(fmt,arglist); + + ReplaceEsc(s); + va_end(arglist); - eprintf(L"%ls",Msg); + eprintf(L"%ls",s.c_str()); ErrHandler.SetSystemErrorCode(Code); } #endif diff --git a/vendor/unrar/log.hpp b/vendor/unrar/log.hpp index 008ef11a0c..22eaa8e6eb 100644 --- a/vendor/unrar/log.hpp +++ b/vendor/unrar/log.hpp @@ -1,7 +1,8 @@ #ifndef _RAR_LOG_ #define _RAR_LOG_ -void InitLogOptions(const wchar *LogFileName,RAR_CHARSET CSet); +void InitLogOptions(const std::wstring &LogFileName,RAR_CHARSET CSet); +void CloseLogOptions(); #ifdef SILENT inline void Log(const wchar *ArcName,const wchar *fmt,...) {} diff --git a/vendor/unrar/match.cpp b/vendor/unrar/match.cpp index ec88fa61b3..0a78d8dd7d 100644 --- a/vendor/unrar/match.cpp +++ b/vendor/unrar/match.cpp @@ -3,6 +3,7 @@ static bool match(const wchar *pattern,const wchar *string,bool ForceCase); static int mwcsicompc(const wchar *Str1,const wchar *Str2,bool ForceCase); static int mwcsnicompc(const wchar *Str1,const wchar *Str2,size_t N,bool ForceCase); +static bool IsWildcard(const wchar *Str,size_t CheckSize); inline uint touppercw(uint ch,bool ForceCase) { @@ -16,12 +17,15 @@ inline uint touppercw(uint ch,bool ForceCase) } -bool CmpName(const wchar *Wildcard,const wchar *Name,int CmpMode) +bool CmpName(const wchar *Wildcard,const wchar *Name,uint CmpMode) { bool ForceCase=(CmpMode&MATCH_FORCECASESENSITIVE)!=0; CmpMode&=MATCH_MODEMASK; + wchar *Name1=PointToName(Wildcard); + wchar *Name2=PointToName(Name); + if (CmpMode!=MATCH_NAMES) { size_t WildLength=wcslen(Wildcard); @@ -32,47 +36,48 @@ bool CmpName(const wchar *Wildcard,const wchar *Name,int CmpMode) // "path1" mask must match "path1\path2\filename.ext" and "path1" names. wchar NextCh=Name[WildLength]; if (NextCh==L'\\' || NextCh==L'/' || NextCh==0) - return(true); + return true; } // Nothing more to compare for MATCH_SUBPATHONLY. if (CmpMode==MATCH_SUBPATHONLY) - return(false); - - wchar Path1[NM],Path2[NM]; - GetFilePath(Wildcard,Path1,ASIZE(Path1)); - GetFilePath(Name,Path2,ASIZE(Path2)); - - if ((CmpMode==MATCH_EXACT || CmpMode==MATCH_EXACTPATH) && - mwcsicompc(Path1,Path2,ForceCase)!=0) - return(false); + return false; + + // 2023.08.29: We tried std::wstring Path1 and Path2 here, but performance + // impact for O(n^2) complexity loop in CmdExtract::AnalyzeArchive() + // was rather noticeable, 1.7s instead of 0.9s when extracting ~300 files + // with @listfile from archive with ~7000 files. + // This function can be invoked from other O(n^2) loops. So for now + // we prefer to avoid wstring and use pointers and path sizes here. + // Another option could be using std::wstring_view. + + size_t Path1Size=Name1-Wildcard; + size_t Path2Size=Name2-Name; + + if ((CmpMode==MATCH_EXACT || CmpMode==MATCH_EXACTPATH) && + (Path1Size!=Path2Size || + mwcsnicompc(Wildcard,Name,Path1Size,ForceCase)!=0)) + return false; if (CmpMode==MATCH_ALLWILD) return match(Wildcard,Name,ForceCase); if (CmpMode==MATCH_SUBPATH || CmpMode==MATCH_WILDSUBPATH) - if (IsWildcard(Path1)) - return(match(Wildcard,Name,ForceCase)); + if (IsWildcard(Wildcard,Path1Size)) + return match(Wildcard,Name,ForceCase); else if (CmpMode==MATCH_SUBPATH || IsWildcard(Wildcard)) { - if (*Path1 && mwcsnicompc(Path1,Path2,wcslen(Path1),ForceCase)!=0) - return(false); + if (Path1Size>0 && mwcsnicompc(Wildcard,Name,Path1Size,ForceCase)!=0) + return false; } else - if (mwcsicompc(Path1,Path2,ForceCase)!=0) - return(false); + if (Path1Size!=Path2Size || mwcsnicompc(Wildcard,Name,Path1Size,ForceCase)!=0) + return false; } - wchar *Name1=PointToName(Wildcard); - wchar *Name2=PointToName(Name); - - // Always return false for RAR temporary files to exclude them - // from archiving operations. -// if (mwcsnicompc(L"__rar_",Name2,6,false)==0) -// return(false); if (CmpMode==MATCH_EXACT) - return(mwcsicompc(Name1,Name2,ForceCase)==0); + return mwcsicompc(Name1,Name2,ForceCase)==0; - return(match(Name1,Name2,ForceCase)); + return match(Name1,Name2,ForceCase); } @@ -85,18 +90,18 @@ bool match(const wchar *pattern,const wchar *string,bool ForceCase) switch (patternc) { case 0: - return(stringc==0); + return stringc==0; case '?': if (stringc == 0) - return(false); + return false; break; case '*': if (*pattern==0) - return(true); + return true; if (*pattern=='.') { if (pattern[1]=='*' && pattern[2]==0) - return(true); + return true; const wchar *dot=wcschr(string,'.'); if (pattern[1]==0) return (dot==NULL || dot[1]==0); @@ -104,22 +109,22 @@ bool match(const wchar *pattern,const wchar *string,bool ForceCase) { string=dot; if (wcspbrk(pattern,L"*?")==NULL && wcschr(string+1,'.')==NULL) - return(mwcsicompc(pattern+1,string+1,ForceCase)==0); + return mwcsicompc(pattern+1,string+1,ForceCase)==0; } } while (*string) if (match(pattern,string++,ForceCase)) - return(true); - return(false); + return true; + return false; default: if (patternc != stringc) { // Allow "name." mask match "name" and "name.\" match "name\". if (patternc=='.' && (stringc==0 || stringc=='\\' || stringc=='.')) - return(match(pattern,string,ForceCase)); + return match(pattern,string,ForceCase); else - return(false); + return false; } break; } @@ -145,3 +150,18 @@ int mwcsnicompc(const wchar *Str1,const wchar *Str2,size_t N,bool ForceCase) return wcsnicomp(Str1,Str2,N); #endif } + + +bool IsWildcard(const wchar *Str,size_t CheckSize) +{ + size_t CheckPos=0; +#ifdef _WIN_ALL + // Not treat the special NTFS \\?\d: path prefix as a wildcard. + if (Str[0]=='\\' && Str[1]=='\\' && Str[2]=='?' && Str[3]=='\\') + CheckPos+=4; +#endif + for (size_t I=CheckPos;I= 9*sf)+(cf >= 12*sf)+(cf >= 15*sf); - pc->U.SummFreq += cf; + pc->U.SummFreq += (ushort)cf; } p=pc->U.Stats+ns1; p->Successor=Successor; p->Symbol = fs.Symbol; - p->Freq = cf; - pc->NumStats=++ns1; + p->Freq = (byte)cf; + pc->NumStats=(ushort)++ns1; } MaxContext=MinContext=fs.Successor; return; @@ -542,7 +542,7 @@ inline bool RARPPM_CONTEXT::decodeSymbol2(ModelPPM *Model) Model->CharMask[(*pps)->Symbol]=Model->EscCount; pps++; } while ( --i ); - psee2c->Summ += Model->Coder.SubRange.scale; + psee2c->Summ += (ushort)Model->Coder.SubRange.scale; Model->NumMasked = NumStats; } return true; diff --git a/vendor/unrar/model.hpp b/vendor/unrar/model.hpp index 52abc89b3b..2c9fa404ff 100644 --- a/vendor/unrar/model.hpp +++ b/vendor/unrar/model.hpp @@ -25,7 +25,7 @@ struct RARPPM_SEE2_CONTEXT : RARPPM_DEF } uint getMean() { - uint RetVal=GET_SHORT16(Summ) >> Shift; + short RetVal=GET_SHORT16(Summ) >> Shift; Summ -= RetVal; return RetVal+(RetVal == 0); } diff --git a/vendor/unrar/options.cpp b/vendor/unrar/options.cpp index 22ae27ce21..ab8cff5ebd 100644 --- a/vendor/unrar/options.cpp +++ b/vendor/unrar/options.cpp @@ -10,6 +10,7 @@ void RAROptions::Init() { memset(this,0,sizeof(RAROptions)); WinSize=0x2000000; + WinSizeLimit=0x100000000; Overwrite=OVERWRITE_DEFAULT; Method=3; MsgStream=MSG_STDOUT; diff --git a/vendor/unrar/options.hpp b/vendor/unrar/options.hpp index e249eb599d..1061bd0216 100644 --- a/vendor/unrar/options.hpp +++ b/vendor/unrar/options.hpp @@ -33,7 +33,7 @@ enum RECURSE_MODE RECURSE_NONE=0, // no recurse switches RECURSE_DISABLE, // switch -r- RECURSE_ALWAYS, // switch -r - RECURSE_WILDCARDS, // switch -r0 + RECURSE_WILDCARDS // switch -r0 }; enum OVERWRITE_MODE @@ -57,7 +57,13 @@ enum QOPEN_MODE { QOPEN_NONE, QOPEN_AUTO, QOPEN_ALWAYS }; enum RAR_CHARSET { RCH_DEFAULT=0,RCH_ANSI,RCH_OEM,RCH_UNICODE,RCH_UTF8 }; #define MAX_FILTER_TYPES 16 -enum FilterState {FILTER_DEFAULT=0,FILTER_AUTO,FILTER_FORCE,FILTER_DISABLE}; + +enum FilterState { + FILTER_DEFAULT=0, // No -mc switch. + FILTER_AUTO, // -mc switch is present. + FILTER_FORCE, // -mc+ switch is present. + FILTER_DISABLE // -mc- switch is present. +}; enum SAVECOPY_MODE { @@ -98,6 +104,7 @@ class RAROptions RAROptions(); void Init(); + uint ExclFileAttr; uint InclFileAttr; @@ -107,30 +114,24 @@ class RAROptions bool InclDir; bool InclAttrSet; - size_t WinSize; - wchar TempPath[NM]; - wchar SFXModule[NM]; + uint64 WinSize; + uint64 WinSizeLimit; // Switch -mdx. #ifdef USE_QOPEN QOPEN_MODE QOpenMode; #endif bool ConfigDisabled; // Switch -cfg-. - wchar ExtrPath[NM]; - wchar CommentFile[NM]; RAR_CHARSET CommentCharset; RAR_CHARSET FilelistCharset; RAR_CHARSET ErrlogCharset; RAR_CHARSET RedirectCharset; - wchar ArcPath[NM]; // For -ap. - wchar ExclArcPath[NM]; // For -ep4 switch. bool EncryptHeaders; bool SkipEncrypted; bool ManualPassword; // Password entered manually during operation, might need to clean for next archive. - wchar LogName[NM]; MESSAGE_TYPE MsgStream; SOUND_NOTIFY_MODE Sound; OVERWRITE_MODE Overwrite; @@ -164,6 +165,7 @@ class RAROptions bool SaveSymLinks; bool SaveHardLinks; bool AbsoluteLinks; + bool SkipSymLinks; int Priority; int SleepTime; bool KeepBroken; @@ -195,7 +197,6 @@ class RAROptions bool Test; bool VolumePause; FilterMode FilterModes[MAX_FILTER_TYPES]; - wchar EmailTo[NM]; uint VersionControl; APPENDARCNAME_MODE AppendArcNameToPath; POWER_MODE Shutdown; @@ -204,11 +205,6 @@ class RAROptions EXTTIME_MODE xatime; bool PreserveAtime; - // Read data from stdin and store in archive under a name specified here - // when archiving. Read an archive from stdin if any non-empty string - // is specified here when extracting. - wchar UseStdin[NM]; - uint Threads; // We use it to init hash even if RAR_SMP is not defined. @@ -216,7 +212,6 @@ class RAROptions #ifdef RARDLL - wchar DllDestName[NM]; int DllOpMode; int DllError; LPARAM UserData; @@ -224,5 +219,6 @@ class RAROptions CHANGEVOLPROC ChangeVolProc; PROCESSDATAPROC ProcessDataProc; #endif + }; #endif diff --git a/vendor/unrar/os.hpp b/vendor/unrar/os.hpp index 4b21e49d76..b6718462e0 100644 --- a/vendor/unrar/os.hpp +++ b/vendor/unrar/os.hpp @@ -4,10 +4,6 @@ #define FALSE 0 #define TRUE 1 -#ifdef __EMX__ - #define INCL_BASE -#endif - #if defined(RARDLL) && !defined(SILENT) #define SILENT #endif @@ -15,14 +11,13 @@ #include #include #include +#include +#include // For automatic pointers. -#if defined(_WIN_ALL) || defined(_EMX) +#ifdef _WIN_ALL #define LITTLE_ENDIAN -#define NM 2048 - -#ifdef _WIN_ALL // We got a report that just "#define STRICT" is incompatible with @@ -41,15 +36,8 @@ #define _UNICODE // Set _T() macro to convert from narrow to wide strings. #endif -#if 0 -// 2021.09.05: Allow newer Vista+ APIs like IFileOpenDialog for WinRAR, -// but still keep SFX modules XP compatible. -#define WINVER _WIN32_WINNT_VISTA -#define _WIN32_WINNT _WIN32_WINNT_VISTA -#else #define WINVER _WIN32_WINNT_WINXP #define _WIN32_WINNT _WIN32_WINNT_WINXP -#endif #if !defined(ZIPSFX) #define RAR_SMP @@ -70,28 +58,23 @@ #include #include +// For WMI requests. +#include +#include +#pragma comment(lib, "wbemuuid.lib") -#endif // _WIN_ALL #include #include #include +#include +#include -#if !defined(_EMX) && !defined(_MSC_VER) - #include +// Use SSE only for x86/x64, not ARM Windows. +#if defined(_M_IX86) || defined(_M_X64) + #define USE_SSE + #define SSE_ALIGNMENT 16 #endif -#ifdef _MSC_VER - #include - #include - - // Use SSE only for x86/x64, not ARM Windows. - #if defined(_M_IX86) || defined(_M_X64) - #define USE_SSE - #define SSE_ALIGNMENT 16 - #endif -#else - #include -#endif // _MSC_VER #include #include @@ -113,7 +96,7 @@ #define SPATHDIVIDER L"\\" -#define CPATHDIVIDER '\\' +#define CPATHDIVIDER L'\\' #define MASKALL L"*" #define READBINARY "rb" @@ -123,25 +106,13 @@ #define WRITEBINARY "wb" #define APPENDTEXT "at" -#if defined(_WIN_ALL) - #ifdef _MSC_VER - #define _stdfunction __cdecl - #define _forceinline __forceinline - #else - #define _stdfunction _USERENTRY - #define _forceinline inline - #endif -#else - #define _stdfunction - #define _forceinline inline -#endif +#define _stdfunction __cdecl +#define _forceinline __forceinline -#endif // defined(_WIN_ALL) || defined(_EMX) +#endif // _WIN_ALL #ifdef _UNIX -#define NM 2048 - #include #include #include @@ -149,7 +120,7 @@ #if defined(__QNXNTO__) #include #endif -#if defined(RAR_SMP) && defined(__APPLE__) +#ifdef _APPLE #include #endif #ifndef SFX_MODULE @@ -172,6 +143,28 @@ #include #include +#ifdef __GNUC__ + #if defined(__i386__) || defined(__x86_64__) + #include + + #define USE_SSE + #define SSE_ALIGNMENT 16 + #endif +#endif + +#if defined(__aarch64__) && (defined(__ARM_FEATURE_CRYPTO) || defined(__ARM_FEATURE_CRC32)) +#include +#ifndef _APPLE +#include +#include +#endif +#ifdef __ARM_FEATURE_CRYPTO +#define USE_NEON_AES +#endif +#ifdef __ARM_FEATURE_CRC32 +#define USE_NEON_CRC32 +#endif +#endif #ifdef S_IFLNK #define SAVE_LINKS @@ -189,7 +182,7 @@ #define SPATHDIVIDER L"/" -#define CPATHDIVIDER '/' +#define CPATHDIVIDER L'/' #define MASKALL L"*" #define READBINARY "r" @@ -219,6 +212,10 @@ #endif #endif +#ifdef __VMS +# define LITTLE_ENDIAN +#endif + // Unlike Apple x64, utimensat shall be available in all Apple M1 systems. #if _POSIX_C_SOURCE >= 200809L || defined(__APPLE__) && defined(__arm64__) #define UNIX_TIME_NS // Nanosecond time precision in Unix. @@ -226,19 +223,12 @@ #endif // _UNIX -#if 0 - #define MSGID_INT - typedef int MSGID; -#else typedef const wchar* MSGID; -#endif #ifndef SSE_ALIGNMENT // No SSE use and no special data alignment is required. #define SSE_ALIGNMENT 1 #endif -#define safebuf static - // Solaris defines _LITTLE_ENDIAN or _BIG_ENDIAN. #if defined(_LITTLE_ENDIAN) && !defined(LITTLE_ENDIAN) #define LITTLE_ENDIAN @@ -269,8 +259,8 @@ #endif #endif -#if !defined(BIG_ENDIAN) && defined(_WIN_ALL) || defined(__i386__) || defined(__x86_64__) -// Allow not aligned integer access, increases speed in some operations. +#if !defined(BIG_ENDIAN) && defined(_WIN_ALL) || defined(__i386__) || defined(__x86_64__) || defined(__aarch64__) +// Allow unaligned integer access, increases speed in some operations. #define ALLOW_MISALIGNED #endif diff --git a/vendor/unrar/pathfn.cpp b/vendor/unrar/pathfn.cpp index e959e9d65b..7c0f919632 100644 --- a/vendor/unrar/pathfn.cpp +++ b/vendor/unrar/pathfn.cpp @@ -9,6 +9,21 @@ wchar* PointToName(const wchar *Path) } +std::wstring PointToName(const std::wstring &Path) +{ + return std::wstring(Path.substr(GetNamePos(Path))); +} + + +size_t GetNamePos(const std::wstring &Path) +{ + for (int I=(int)Path.size()-1;I>=0;I--) + if (IsPathDiv(Path[I])) + return I+1; + return IsDriveLetter(Path) ? 2 : 0; +} + + wchar* PointToLastChar(const wchar *Path) { size_t Length=wcslen(Path); @@ -16,94 +31,95 @@ wchar* PointToLastChar(const wchar *Path) } -wchar* ConvertPath(const wchar *SrcPath,wchar *DestPath,size_t DestSize) +wchar GetLastChar(const std::wstring &Path) +{ + return Path.empty() ? 0:Path.back(); +} + + +size_t ConvertPath(const std::wstring *SrcPath,std::wstring *DestPath) { - const wchar *DestPtr=SrcPath; + const std::wstring &S=*SrcPath; // To avoid *SrcPath[] everywhere. + size_t DestPos=0; - // Prevent \..\ in any part of path string. - for (const wchar *s=DestPtr;*s!=0;s++) - if (IsPathDiv(s[0]) && s[1]=='.' && s[2]=='.' && IsPathDiv(s[3])) - DestPtr=s+4; + // Prevent \..\ in any part of path string and \.. at the end of string + for (size_t I=0;I:\ and any sequence of . and \ in the beginning of path string. - while (*DestPtr!=0) + while (DestPos='A' && Letter<='Z' && IsDriveDiv(Path[1]); } -int GetPathDisk(const wchar *Path) +int GetPathDisk(const std::wstring &Path) { if (IsDriveLetter(Path)) - return etoupperw(*Path)-'A'; + return etoupperw(Path[0])-'A'; else return -1; } -void AddEndSlash(wchar *Path,size_t MaxLength) +void AddEndSlash(std::wstring &Path) { - size_t Length=wcslen(Path); - if (Length>0 && Path[Length-1]!=CPATHDIVIDER && Length+12) + AddEndSlash(OutName); + OutName+=Name; + Pathname=OutName; } -// Returns file path including the trailing path separator symbol. -void GetFilePath(const wchar *FullName,wchar *Path,size_t MaxLength) +// Returns the file path including the trailing path separator symbol. +// It is allowed for both parameters to point to the same string. +void GetPathWithSep(const std::wstring &FullName,std::wstring &Path) { - if (MaxLength==0) - return; - size_t PathLength=Min(MaxLength-1,size_t(PointToName(FullName)-FullName)); - wcsncpy(Path,FullName,PathLength); - Path[PathLength]=0; + if (std::addressof(FullName)!=std::addressof(Path)) + Path=FullName; + Path.erase(GetNamePos(FullName)); } -// Removes name and returns file path without the trailing -// path separator symbol. -void RemoveNameFromPath(wchar *Path) +// Removes name and returns file path without the trailing path separator. +// But for names like d:\name return d:\ with trailing path separator. +void RemoveNameFromPath(std::wstring &Path) { - wchar *Name=PointToName(Path); - if (Name>=Path+2 && (!IsDriveDiv(Path[1]) || Name>=Path+4)) - Name--; - *Name=0; + auto NamePos=GetNamePos(Path); + if (NamePos>=2 && (!IsDriveDiv(Path[1]) || NamePos>=4)) + NamePos--; + Path.erase(NamePos); } #if defined(_WIN_ALL) && !defined(SFX_MODULE) -bool GetAppDataPath(wchar *Path,size_t MaxSize,bool Create) +bool GetAppDataPath(std::wstring &Path,bool Create) { LPMALLOC g_pMalloc; SHGetMalloc(&g_pMalloc); LPITEMIDLIST ppidl; - *Path=0; + Path.clear(); bool Success=false; if (SHGetSpecialFolderLocation(NULL,CSIDL_APPDATA,&ppidl)==NOERROR && - SHGetPathFromIDList(ppidl,Path) && *Path!=0) + SHGetPathStrFromIDList(ppidl,Path) && !Path.empty()) { - AddEndSlash(Path,MaxSize); - wcsncatz(Path,L"WinRAR",MaxSize); + AddEndSlash(Path); + Path+=L"WinRAR"; Success=FileExist(Path); if (!Success && Create) - Success=MakeDir(Path,false,0)==MKDIR_SUCCESS; + Success=CreateDir(Path); } g_pMalloc->Free(ppidl); return Success; @@ -243,24 +278,41 @@ bool GetAppDataPath(wchar *Path,size_t MaxSize,bool Create) #endif +#if defined(_WIN_ALL) +bool SHGetPathStrFromIDList(PCIDLIST_ABSOLUTE pidl,std::wstring &Path) +{ + std::vector Buf(MAX_PATH); + bool Success=SHGetPathFromIDList(pidl,Buf.data())!=FALSE; + Path=Buf.data(); + return Success; +} +#endif + + #if defined(_WIN_ALL) && !defined(SFX_MODULE) -void GetRarDataPath(wchar *Path,size_t MaxSize,bool Create) +void GetRarDataPath(std::wstring &Path,bool Create) { - *Path=0; + Path.clear(); HKEY hKey; if (RegOpenKeyEx(HKEY_CURRENT_USER,L"Software\\WinRAR\\Paths",0, KEY_QUERY_VALUE,&hKey)==ERROR_SUCCESS) { - DWORD DataSize=(DWORD)MaxSize,Type; - RegQueryValueEx(hKey,L"AppData",0,&Type,(BYTE *)Path,&DataSize); - RegCloseKey(hKey); + DWORD DataSize; + LSTATUS Code=RegQueryValueEx(hKey,L"AppData",NULL,NULL,NULL,&DataSize); + if (Code==ERROR_SUCCESS) + { + std::vector PathBuf(DataSize/sizeof(wchar)); + RegQueryValueEx(hKey,L"AppData",0,NULL,(BYTE *)PathBuf.data(),&DataSize); + Path=PathBuf.data(); + RegCloseKey(hKey); + } } - if (*Path==0 || !FileExist(Path)) - if (!GetAppDataPath(Path,MaxSize,Create)) + if (Path.empty() || !FileExist(Path)) + if (!GetAppDataPath(Path,Create)) { - GetModuleFileName(NULL,Path,(DWORD)MaxSize); + Path=GetModuleFileStr(); RemoveNameFromPath(Path); } } @@ -268,7 +320,7 @@ void GetRarDataPath(wchar *Path,size_t MaxSize,bool Create) #ifndef SFX_MODULE -bool EnumConfigPaths(uint Number,wchar *Path,size_t MaxSize,bool Create) +bool EnumConfigPaths(uint Number,std::wstring &Path,bool Create) { #ifdef _UNIX static const wchar *ConfPath[]={ @@ -278,24 +330,24 @@ bool EnumConfigPaths(uint Number,wchar *Path,size_t MaxSize,bool Create) { char *EnvStr=getenv("HOME"); if (EnvStr!=NULL) - CharToWide(EnvStr,Path,MaxSize); + CharToWide(EnvStr,Path); else - wcsncpyz(Path,ConfPath[0],MaxSize); + Path=ConfPath[0]; return true; } Number--; if (Number>=ASIZE(ConfPath)) return false; - wcsncpyz(Path,ConfPath[Number], MaxSize); + Path=ConfPath[Number]; return true; #elif defined(_WIN_ALL) if (Number>1) return false; if (Number==0) - GetRarDataPath(Path,MaxSize,Create); + GetRarDataPath(Path,Create); else { - GetModuleFileName(NULL,Path,(DWORD)MaxSize); + Path=GetModuleFileStr(); RemoveNameFromPath(Path); } return true; @@ -307,13 +359,15 @@ bool EnumConfigPaths(uint Number,wchar *Path,size_t MaxSize,bool Create) #ifndef SFX_MODULE -void GetConfigName(const wchar *Name,wchar *FullName,size_t MaxSize,bool CheckExist,bool Create) +void GetConfigName(const std::wstring &Name,std::wstring &FullName,bool CheckExist,bool Create) { - *FullName=0; - for (uint I=0;EnumConfigPaths(I,FullName,MaxSize,Create);I++) + FullName.clear(); + for (uint I=0;;I++) { - AddEndSlash(FullName,MaxSize); - wcsncatz(FullName,Name,MaxSize); + std::wstring ConfPath; + if (!EnumConfigPaths(I,ConfPath,Create)) + break; + MakeName(ConfPath,Name,FullName); if (!CheckExist || WildFileExist(FullName)) break; } @@ -321,112 +375,107 @@ void GetConfigName(const wchar *Name,wchar *FullName,size_t MaxSize,bool CheckEx #endif -// Returns a pointer to rightmost digit of volume number or to beginning +// Returns the position to rightmost digit of volume number or beginning // of file name if numeric part is missing. -wchar* GetVolNumPart(const wchar *ArcName) +size_t GetVolNumPos(const std::wstring &ArcName) { // We do not want to increment any characters in path component. - ArcName=PointToName(ArcName); + size_t NamePos=GetNamePos(ArcName); - if (*ArcName==0) - return (wchar *)ArcName; + if (NamePos==ArcName.size()) + return NamePos; // Pointing to last name character. - const wchar *ChPtr=ArcName+wcslen(ArcName)-1; + size_t Pos=ArcName.size()-1; // Skipping the archive extension. - while (!IsDigit(*ChPtr) && ChPtr>ArcName) - ChPtr--; + while (!IsDigit(ArcName[Pos]) && Pos>NamePos) + Pos--; // Skipping the numeric part of name. - const wchar *NumPtr=ChPtr; - while (IsDigit(*NumPtr) && NumPtr>ArcName) - NumPtr--; + size_t NumPos=Pos; + while (IsDigit(ArcName[NumPos]) && NumPos>NamePos) + NumPos--; // Searching for first numeric part in names like name.part##of##.rar. // Stop search on the first dot. - while (NumPtr>ArcName && *NumPtr!='.') + while (NumPos>NamePos && ArcName[NumPos]!='.') { - if (IsDigit(*NumPtr)) + if (IsDigit(ArcName[NumPos])) { // Validate the first numeric part only if it has a dot somewhere // before it. - const wchar *Dot=wcschr(ArcName,'.'); - if (Dot!=NULL && Dot|\"")==NULL; + return !Name.empty() && Name.find_first_of(L"?*<>|\"")==std::wstring::npos; } - - -void MakeNameUsable(wchar *Name,bool Extended) +void MakeNameUsable(std::wstring &Name,bool Extended) { - for (wchar *s=Name;*s!=0;s++) + for (size_t I=0;I|\"":L"?*",*s)!=NULL || Extended && (uint)*s<32) - *s='_'; + if (wcschr(Extended ? L"?*<>|\"":L"?*",Name[I])!=NULL || + Extended && (uint)Name[I]<32) + Name[I]='_'; #ifdef _UNIX // We were asked to apply Windows-like conversion in Linux in case // files are unpacked to Windows share. This code is invoked only @@ -478,26 +526,24 @@ void MakeNameUsable(wchar *Name,bool Extended) { // Windows shares in Unix do not allow the drive letter, // so unlike Windows version, we check all characters here. - if (*s==':') - *s='_'; + if (Name[I]==':') + Name[I]='_'; // No spaces or dots before the path separator are allowed on Windows // shares. But they are allowed and automatically removed at the end of - // file or folder name, so it is useless to replace them here. + // file or folder name, so we need to replace them only before + // the path separator, but not at the end of file name. // Since such files or folders are created successfully, a supposed - // conversion here would never be invoked. - if ((*s==' ' || *s=='.') && IsPathDiv(s[1])) - *s='_'; + // conversion at the end of file name would never be invoked here. + // While converting dots, we preserve "." and ".." path components, + // such as when specifying ".." in the destination path. + if (IsPathDiv(Name[I+1]) && (Name[I]==' ' || Name[I]=='.' && I>0 && + !IsPathDiv(Name[I-1]) && (Name[I-1]!='.' || I>1 && !IsPathDiv(Name[I-2])))) + Name[I]='_'; } #else - if (s-Name>1 && *s==':') - *s='_'; -#if 0 // We already can create such files. - // Remove ' ' and '.' before path separator, but allow .\ and ..\. - if (IsPathDiv(s[1]) && (*s==' ' || *s=='.' && s>Name && - !IsPathDiv(s[-1]) && (s[-1]!='.' || s>Name+1 && !IsPathDiv(s[-2])))) - *s='_'; -#endif + if (I>1 && Name[I]==':') + Name[I]='_'; #endif } } @@ -512,20 +558,38 @@ void UnixSlashToDos(const char *SrcName,char *DestName,size_t MaxLength) } -void DosSlashToUnix(const char *SrcName,char *DestName,size_t MaxLength) +void UnixSlashToDos(const wchar *SrcName,wchar *DestName,size_t MaxLength) { size_t Copied=0; for (;Copied0) - *Dest=0; + Dest.clear(); return; } #ifdef _WIN_ALL { - wchar FullName[NM],*NamePtr; - DWORD Code=GetFullPathName(Src,ASIZE(FullName),FullName,&NamePtr); - if (Code==0 || Code>ASIZE(FullName)) + DWORD Code=GetFullPathName(Src.c_str(),0,NULL,NULL); // Get the buffer size. + if (Code!=0) { - wchar LongName[NM]; - if (GetWinLongPath(Src,LongName,ASIZE(LongName))) - Code=GetFullPathName(LongName,ASIZE(FullName),FullName,&NamePtr); + std::vector FullName(Code); + Code=GetFullPathName(Src.c_str(),(DWORD)FullName.size(),FullName.data(),NULL); + + if (Code>0 && Code<=FullName.size()) + { + Dest=FullName.data(); + return; + } } - if (Code!=0 && Code FullName(Code); + Code=GetFullPathName(LongName.c_str(),(DWORD)FullName.size(),FullName.data(),NULL); + + if (Code>0 && Code<=FullName.size()) + { + Dest=FullName.data(); + return; + } + } + } + if (Src!=Dest) + Dest=Src; // Copy source to destination in case of failure. } #elif defined(_UNIX) if (IsFullPath(Src)) - *Dest=0; + Dest.clear(); else { - char CurDirA[NM]; - if (getcwd(CurDirA,ASIZE(CurDirA))==NULL) - *CurDirA=0; - CharToWide(CurDirA,Dest,MaxSize); - AddEndSlash(Dest,MaxSize); + std::vector CurDirA(MAXPATHSIZE); + if (getcwd(CurDirA.data(),CurDirA.size())==NULL) + CurDirA[0]=0; + CharToWide(CurDirA.data(),Dest); + AddEndSlash(Dest); } - wcsncatz(Dest,Src,MaxSize); + Dest+=Src; #else - wcsncpyz(Dest,Src,MaxSize); + Dest=Src; #endif } -bool IsFullPath(const wchar *Path) +bool IsFullPath(const std::wstring &Path) { -/* - wchar PathOnly[NM]; - GetFilePath(Path,PathOnly,ASIZE(PathOnly)); - if (IsWildcard(PathOnly)) - return true; -*/ -#if defined(_WIN_ALL) || defined(_EMX) - return Path[0]=='\\' && Path[1]=='\\' || IsDriveLetter(Path) && IsPathDiv(Path[2]); +#ifdef _WIN_ALL + return Path.size()>=2 && Path[0]=='\\' && Path[1]=='\\' || + Path.size()>=3 && IsDriveLetter(Path) && IsPathDiv(Path[2]); #else - return IsPathDiv(Path[0]); + return Path.size()>=1 && IsPathDiv(Path[0]); #endif } -bool IsFullRootPath(const wchar *Path) +bool IsFullRootPath(const std::wstring &Path) { return IsFullPath(Path) || IsPathDiv(Path[0]); } -void GetPathRoot(const wchar *Path,wchar *Root,size_t MaxSize) +// Both source and destination can point to the same string. +void GetPathRoot(const std::wstring &Path,std::wstring &Root) { - *Root=0; if (IsDriveLetter(Path)) - swprintf(Root,MaxSize,L"%c:\\",*Path); + Root=Path.substr(0,2) + L"\\"; else if (Path[0]=='\\' && Path[1]=='\\') { - const wchar *Slash=wcschr(Path+2,'\\'); - if (Slash!=NULL) + size_t Slash=Path.find('\\',2); + if (Slash!=std::wstring::npos) { size_t Length; - if ((Slash=wcschr(Slash+1,'\\'))!=NULL) - Length=Slash-Path+1; + if ((Slash=Path.find('\\',Slash+1))!=std::wstring::npos) + Length=Slash+1; else - Length=wcslen(Path); - if (Length>=MaxSize) - Length=0; - wcsncpy(Root,Path,Length); - Root[Length]=0; + Length=Path.size(); + Root=Path.substr(0,Length); } } + else + Root.clear(); } -int ParseVersionFileName(wchar *Name,bool Truncate) +int ParseVersionFileName(std::wstring &Name,bool Truncate) { int Version=0; - wchar *VerText=wcsrchr(Name,';'); - if (VerText!=NULL) + auto VerPos=Name.rfind(';'); + if (VerPos!=std::wstring::npos && VerPos+1FirstName;ChPtr--) - if (IsDigit(*ChPtr)) + for (size_t Pos=GetVolNumPos(Name);Pos>0;Pos--) + if (IsDigit(Name[Pos])) { - *ChPtr=N; // Set the rightmost digit to '1' and others to '0'. + Name[Pos]=N; // Set the rightmost digit to '1' and others to '0'. N='0'; } else - if (N=='0') + if (N=='0') // If we already set the rightmost '1' before. { - VolNumStart=ChPtr+1; // Store the position of leftmost digit in volume number. + VolNumStart=Pos+1; // Store the position of leftmost digit in volume number. break; } } else { // Old volume numbering scheme. Just set the extension to ".rar". - SetExt(FirstName,L"rar",MaxSize); - VolNumStart=GetExt(FirstName); + SetExt(Name,L"rar"); + VolNumStart=GetExtPos(Name); } - if (!FileExist(FirstName)) + if (!FileExist(Name)) { // If the first volume, which name we just generated, does not exist, // check if volume with same name and any other extension is available. // It can help in case of *.exe or *.sfx first volume. - wchar Mask[NM]; - wcsncpyz(Mask,FirstName,ASIZE(Mask)); - SetExt(Mask,L"*",ASIZE(Mask)); + std::wstring Mask=Name; + SetExt(Mask,L"*"); FindFile Find; Find.SetMask(Mask); FindData FD; @@ -689,32 +782,33 @@ wchar* VolNameToFirstName(const wchar *VolName,wchar *FirstName,size_t MaxSize,b Archive Arc; if (Arc.Open(FD.Name,0) && Arc.IsArchive(true) && Arc.FirstVolume) { - wcsncpyz(FirstName,FD.Name,MaxSize); + Name=FD.Name; break; } } } + FirstName=Name; return VolNumStart; } #endif #ifndef SFX_MODULE -static void GenArcName(wchar *ArcName,size_t MaxSize,const wchar *GenerateMask,uint ArcNumber,bool &ArcNumPresent) +static void GenArcName(std::wstring &ArcName,const std::wstring &GenerateMask,uint ArcNumber,bool &ArcNumPresent) { + size_t Pos=0; bool Prefix=false; - if (*GenerateMask=='+') + if (GenerateMask[0]=='+') { Prefix=true; // Add the time string before the archive name. - GenerateMask++; // Skip '+' in the beginning of time mask. + Pos++; // Skip '+' in the beginning of time mask. } - wchar Mask[MAX_GENERATE_MASK]; - wcsncpyz(Mask,*GenerateMask!=0 ? GenerateMask:L"yyyymmddhhmmss",ASIZE(Mask)); + std::wstring Mask=!GenerateMask.empty() ? GenerateMask.substr(Pos):L"yyyymmddhhmmss"; bool QuoteMode=false; uint MAsMinutes=0; // By default we treat 'M' as months. - for (uint I=0;Mask[I]!=0;I++) + for (uint I=0;I=4) CurWeek++; - char Field[10][11]; + const size_t FieldSize=11; + char Field[10][FieldSize]; - sprintf(Field[0],"%04u",rlt.Year); - sprintf(Field[1],"%02u",rlt.Month); - sprintf(Field[2],"%02u",rlt.Day); - sprintf(Field[3],"%02u",rlt.Hour); - sprintf(Field[4],"%02u",rlt.Minute); - sprintf(Field[5],"%02u",rlt.Second); - sprintf(Field[6],"%02u",(uint)CurWeek); - sprintf(Field[7],"%u",(uint)WeekDay+1); - sprintf(Field[8],"%03u",rlt.yDay+1); - sprintf(Field[9],"%05u",ArcNumber); + snprintf(Field[0],FieldSize,"%04u",rlt.Year); + snprintf(Field[1],FieldSize,"%02u",rlt.Month); + snprintf(Field[2],FieldSize,"%02u",rlt.Day); + snprintf(Field[3],FieldSize,"%02u",rlt.Hour); + snprintf(Field[4],FieldSize,"%02u",rlt.Minute); + snprintf(Field[5],FieldSize,"%02u",rlt.Second); + snprintf(Field[6],FieldSize,"%02u",(uint)CurWeek); + snprintf(Field[7],FieldSize,"%u",(uint)WeekDay+1); + snprintf(Field[8],FieldSize,"%03u",rlt.yDay+1); + snprintf(Field[9],FieldSize,"%05u",ArcNumber); const wchar *MaskChars=L"YMDHISWAEN"; // How many times every modifier character was encountered in the mask. - int CField[sizeof(Field)/sizeof(Field[0])]; + int CField[sizeof(Field)/sizeof(Field[0])]{}; - memset(CField,0,sizeof(CField)); QuoteMode=false; - for (uint I=0;Mask[I]!=0;I++) + for (uint I=0;I0) - DestW[DestSize-1]=0; - - return DestW; -} - - #ifdef _WIN_ALL // We should return 'true' even if resulting path is shorter than MAX_PATH, // because we can also use this function to open files with non-standard // characters, even if their path length is normal. -bool GetWinLongPath(const wchar *Src,wchar *Dest,size_t MaxSize) +bool GetWinLongPath(const std::wstring &Src,std::wstring &Dest) { - if (*Src==0) + if (Src.empty()) return false; - const wchar *Prefix=L"\\\\?\\"; - const size_t PrefixLength=4; - bool FullPath=IsDriveLetter(Src) && IsPathDiv(Src[2]); - size_t SrcLength=wcslen(Src); + const std::wstring Prefix=L"\\\\?\\"; + + bool FullPath=Src.size()>=3 && IsDriveLetter(Src) && IsPathDiv(Src[2]); if (IsFullPath(Src)) // Paths in d:\path\name format. { if (IsDriveLetter(Src)) { - if (MaxSize<=PrefixLength+SrcLength) - return false; - wcsncpyz(Dest,Prefix,MaxSize); - wcsncatz(Dest,Src,MaxSize); // "\\?\D:\very long path". + Dest=Prefix+Src; // "\\?\D:\very long path". return true; } else - if (Src[0]=='\\' && Src[1]=='\\') + if (Src.size()>2 && Src[0]=='\\' && Src[1]=='\\') { - if (MaxSize<=PrefixLength+SrcLength+2) - return false; - wcsncpyz(Dest,Prefix,MaxSize); - wcsncatz(Dest,L"UNC",MaxSize); - wcsncatz(Dest,Src+1,MaxSize); // "\\?\UNC\server\share". + Dest=Prefix+L"UNC"+Src.substr(1); // "\\?\UNC\server\share". return true; } - // We may be here only if we modify IsFullPath in the future. + // We can be here only if modify IsFullPath() in the future. return false; } else { - wchar CurDir[NM]; - DWORD DirCode=GetCurrentDirectory(ASIZE(CurDir)-1,CurDir); - if (DirCode==0 || DirCode>ASIZE(CurDir)-1) + std::wstring CurDir; + if (!GetCurDir(CurDir)) return false; if (IsPathDiv(Src[0])) // Paths in \path\name format. { - if (MaxSize<=PrefixLength+SrcLength+2) - return false; - wcsncpyz(Dest,Prefix,MaxSize); - CurDir[2]=0; - wcsncatz(Dest,CurDir,MaxSize); // Copy drive letter 'd:'. - wcsncatz(Dest,Src,MaxSize); + Dest=Prefix+CurDir[0]+L':'+Src; // Copy drive letter 'd:'. return true; } else // Paths in path\name format. { - AddEndSlash(CurDir,ASIZE(CurDir)); - if (MaxSize<=PrefixLength+wcslen(CurDir)+SrcLength) - return false; - wcsncpyz(Dest,Prefix,MaxSize); - wcsncatz(Dest,CurDir,MaxSize); + Dest=Prefix+CurDir; + AddEndSlash(Dest); + size_t Pos=0; if (Src[0]=='.' && IsPathDiv(Src[1])) // Remove leading .\ in pathname. - Src+=2; + Pos=2; - wcsncatz(Dest,Src,MaxSize); + Dest+=Src.substr(Pos); return true; } } @@ -1008,46 +1061,55 @@ bool GetWinLongPath(const wchar *Src,wchar *Dest,size_t MaxSize) // Convert Unix, OS X and Android decomposed chracters to Windows precomposed. -void ConvertToPrecomposed(wchar *Name,size_t NameSize) +void ConvertToPrecomposed(std::wstring &Name) { - wchar FileName[NM]; - if (WinNT()>=WNT_VISTA && // MAP_PRECOMPOSED is not supported in XP. - FoldString(MAP_PRECOMPOSED,Name,-1,FileName,ASIZE(FileName))!=0) - { - FileName[ASIZE(FileName)-1]=0; - wcsncpyz(Name,FileName,NameSize); - } + if (WinNT() FileName(Size); + if (FoldString(MAP_PRECOMPOSED,Name.c_str(),-1,FileName.data(),(int)FileName.size())!=0) + Name=FileName.data(); } -void MakeNameCompatible(wchar *Name,size_t MaxSize) +void MakeNameCompatible(std::wstring &Name) { // Remove trailing spaces and dots in file name and in dir names in path. - int Src=0,Dest=0; - while (true) - { - if (IsPathDiv(Name[Src]) || Name[Src]==0) - for (int I=Dest-1;I>0 && (Name[I]==' ' || Name[I]=='.');I--) + for (int I=0;I<(int)Name.size();I++) + if (I+1==Name.size() || IsPathDiv(Name[I+1])) + while (I>=0 && (Name[I]=='.' || Name[I]==' ')) { - // Permit path1/./path2 and ../path1 paths. - if (Name[I]=='.' && (IsPathDiv(Name[I-1]) || Name[I-1]=='.' && I==1)) + if (I==0 && Name[I]==' ') + { + // Windows 10 Explorer can't rename or delete " " files and folders. + Name[I]='_'; // Convert " /path" to "_/path". break; - Dest--; + } + if (Name[I]=='.') + { + // 2024.05.01: Permit ./path1, path1/./path2, ../path1, + // path1/../path2 and exotic Win32 d:.\path1, d:..\path1 paths + // requested by user. Leading dots are possible here if specified + // by user in the destination path. + if (I==0 || IsPathDiv(Name[I-1]) || I==2 && IsDriveLetter(Name)) + break; + if (I>=1 && Name[I-1]=='.' && (I==1 || IsPathDiv(Name[I-2]) || + I==3 && IsDriveLetter(Name))) + break; + } + Name.erase(I,1); + I--; } - Name[Dest]=Name[Src]; - if (Name[Src]==0) - break; - Src++; - Dest++; - } // Rename reserved device names, such as aux.txt to _aux.txt. // We check them in path components too, where they are also prohibited. - for (uint I=0;Name[I]!=0;I++) + for (size_t I=0;I0 && IsPathDiv(Name[I-1])) { static const wchar *Devices[]={L"CON",L"PRN",L"AUX",L"NUL",L"COM#",L"LPT#"}; - wchar *s=Name+I; + const wchar *s=&Name[I]; bool MatchFound=false; for (uint J=0;JI+1) // I+1, because we do not move the trailing 0. - memmove(s+1,s,(MaxSize-I-1)*sizeof(*s)); - *s='_'; + std::wstring OrigName=Name; + Name.insert(I,1,'_'); #ifndef SFX_MODULE uiMsg(UIMSG_CORRECTINGNAME,nullptr); uiMsg(UIERROR_RENAMING,nullptr,OrigName,Name); @@ -1084,3 +1143,54 @@ void MakeNameCompatible(wchar *Name,size_t MaxSize) #endif + + +#ifdef _WIN_ALL +std::wstring GetModuleFileStr() +{ + HMODULE hModule=nullptr; + + std::vector Path(256); + while (Path.size()<=MAXPATHSIZE) + { + if (GetModuleFileName(hModule,Path.data(),(DWORD)Path.size()) Buf(BufSize); + DWORD Code=GetCurrentDirectory((DWORD)Buf.size(),Buf.data()); + Dir=Buf.data(); + return Code!=0; +} +#endif + + diff --git a/vendor/unrar/pathfn.hpp b/vendor/unrar/pathfn.hpp index 62cae0ad2c..57dab5a548 100644 --- a/vendor/unrar/pathfn.hpp +++ b/vendor/unrar/pathfn.hpp @@ -2,39 +2,52 @@ #define _RAR_PATHFN_ wchar* PointToName(const wchar *Path); +std::wstring PointToName(const std::wstring &Path); +size_t GetNamePos(const std::wstring &Path); wchar* PointToLastChar(const wchar *Path); -wchar* ConvertPath(const wchar *SrcPath,wchar *DestPath,size_t DestSize); -void SetName(wchar *FullName,const wchar *Name,size_t MaxSize); -void SetExt(wchar *Name,const wchar *NewExt,size_t MaxSize); -void SetSFXExt(wchar *SFXName,size_t MaxSize); +wchar GetLastChar(const std::wstring &Path); +size_t ConvertPath(const std::wstring *SrcPath,std::wstring *DestPath); +void SetName(std::wstring &FullName,const std::wstring &Name); +void SetExt(std::wstring &Name,std::wstring NewExt); +void RemoveExt(std::wstring &Name); +void SetSFXExt(std::wstring &SFXName); wchar *GetExt(const wchar *Name); -bool CmpExt(const wchar *Name,const wchar *Ext); -bool IsWildcard(const wchar *Str); +std::wstring GetExt(const std::wstring &Name); +std::wstring::size_type GetExtPos(const std::wstring &Name); +bool CmpExt(const std::wstring &Name,const std::wstring &Ext); +bool IsWildcard(const std::wstring &Str); bool IsPathDiv(int Ch); bool IsDriveDiv(int Ch); -bool IsDriveLetter(const wchar *Path); -int GetPathDisk(const wchar *Path); -void AddEndSlash(wchar *Path,size_t MaxLength); -void MakeName(const wchar *Path,const wchar *Name,wchar *Pathname,size_t MaxSize); -void GetFilePath(const wchar *FullName,wchar *Path,size_t MaxLength); -void RemoveNameFromPath(wchar *Path); +bool IsDriveLetter(const std::wstring &Path); +int GetPathDisk(const std::wstring &Path); +void AddEndSlash(std::wstring &Path); +void MakeName(const std::wstring &Path,const std::wstring &Name,std::wstring &Pathname); +void GetPathWithSep(const std::wstring &FullName,std::wstring &Path); +void RemoveNameFromPath(std::wstring &Path); #if defined(_WIN_ALL) && !defined(SFX_MODULE) -bool GetAppDataPath(wchar *Path,size_t MaxSize,bool Create); -void GetRarDataPath(wchar *Path,size_t MaxSize,bool Create); +bool GetAppDataPath(std::wstring &Path,bool Create); +void GetRarDataPath(std::wstring &Path,bool Create); +#endif +#ifdef _WIN_ALL +bool SHGetPathStrFromIDList(PCIDLIST_ABSOLUTE pidl,std::wstring &Path); #endif #ifndef SFX_MODULE -bool EnumConfigPaths(uint Number,wchar *Path,size_t MaxSize,bool Create); -void GetConfigName(const wchar *Name,wchar *FullName,size_t MaxSize,bool CheckExist,bool Create); +bool EnumConfigPaths(uint Number,std::wstring &Path,bool Create); +void GetConfigName(const std::wstring &Name,std::wstring &FullName,bool CheckExist,bool Create); #endif -wchar* GetVolNumPart(const wchar *ArcName); -void NextVolumeName(wchar *ArcName,uint MaxLength,bool OldNumbering); -bool IsNameUsable(const wchar *Name); -void MakeNameUsable(wchar *Name,bool Extended); +size_t GetVolNumPos(const std::wstring &ArcName); +void NextVolumeName(std::wstring &ArcName,bool OldNumbering); +bool IsNameUsable(const std::wstring &Name); +void MakeNameUsable(std::wstring &Name,bool Extended); void UnixSlashToDos(const char *SrcName,char *DestName,size_t MaxLength); -void DosSlashToUnix(const char *SrcName,char *DestName,size_t MaxLength); void UnixSlashToDos(const wchar *SrcName,wchar *DestName,size_t MaxLength); +void UnixSlashToDos(const std::string &SrcName,std::string &DestName); +void UnixSlashToDos(const std::wstring &SrcName,std::wstring &DestName); +void DosSlashToUnix(const char *SrcName,char *DestName,size_t MaxLength); void DosSlashToUnix(const wchar *SrcName,wchar *DestName,size_t MaxLength); +void DosSlashToUnix(const std::string &SrcName,std::string &DestName); +void DosSlashToUnix(const std::wstring &SrcName,std::wstring &DestName); inline void SlashToNative(const char *SrcName,char *DestName,size_t MaxLength) { @@ -45,6 +58,15 @@ inline void SlashToNative(const char *SrcName,char *DestName,size_t MaxLength) #endif } +inline void SlashToNative(const std::string &SrcName,std::string &DestName) +{ +#ifdef _WIN_ALL + UnixSlashToDos(SrcName,DestName); +#else + DosSlashToUnix(SrcName,DestName); +#endif +} + inline void SlashToNative(const wchar *SrcName,wchar *DestName,size_t MaxLength) { #ifdef _WIN_ALL @@ -54,22 +76,44 @@ inline void SlashToNative(const wchar *SrcName,wchar *DestName,size_t MaxLength) #endif } -void ConvertNameToFull(const wchar *Src,wchar *Dest,size_t MaxSize); -bool IsFullPath(const wchar *Path); -bool IsFullRootPath(const wchar *Path); -void GetPathRoot(const wchar *Path,wchar *Root,size_t MaxSize); -int ParseVersionFileName(wchar *Name,bool Truncate); -wchar* VolNameToFirstName(const wchar *VolName,wchar *FirstName,size_t MaxSize,bool NewNumbering); -wchar* GetWideName(const char *Name,const wchar *NameW,wchar *DestW,size_t DestSize); +inline void SlashToNative(const std::wstring &SrcName,std::wstring &DestName) +{ +#ifdef _WIN_ALL + UnixSlashToDos(SrcName,DestName); +#else + DosSlashToUnix(SrcName,DestName); +#endif +} + +void ConvertNameToFull(const std::wstring &Src,std::wstring &Dest); +bool IsFullPath(const std::wstring &Path); +bool IsFullRootPath(const std::wstring &Path); +void GetPathRoot(const std::wstring &Path,std::wstring &Root); +int ParseVersionFileName(std::wstring &Name,bool Truncate); +size_t VolNameToFirstName(const std::wstring &VolName,std::wstring &FirstName,bool NewNumbering); #ifndef SFX_MODULE -void GenerateArchiveName(wchar *ArcName,size_t MaxSize,const wchar *GenerateMask,bool Archiving); +void GenerateArchiveName(std::wstring &ArcName,const std::wstring &GenerateMask,bool Archiving); +#endif + +#ifdef _WIN_ALL +bool GetWinLongPath(const std::wstring &Src,std::wstring &Dest); +void ConvertToPrecomposed(std::wstring &Name); +void MakeNameCompatible(std::wstring &Name); +#endif + + +#ifdef _WIN_ALL +std::wstring GetModuleFileStr(); +std::wstring GetProgramFile(const std::wstring &Name); +#endif + +#if defined(_WIN_ALL) +bool SetCurDir(const std::wstring &Dir); #endif #ifdef _WIN_ALL -bool GetWinLongPath(const wchar *Src,wchar *Dest,size_t MaxSize); -void ConvertToPrecomposed(wchar *Name,size_t NameSize); -void MakeNameCompatible(wchar *Name,size_t MaxSize); +bool GetCurDir(std::wstring &Dir); #endif diff --git a/vendor/unrar/qopen.cpp b/vendor/unrar/qopen.cpp index d906d06bd3..e4ae8a9d1e 100644 --- a/vendor/unrar/qopen.cpp +++ b/vendor/unrar/qopen.cpp @@ -114,7 +114,7 @@ void QuickOpen::Load(uint64 BlockPos) RawDataPos=0; ReadBufSize=0; ReadBufPos=0; - LastReadHeader.Reset(); + LastReadHeader.clear(); LastReadHeaderPos=0; ReadBuffer(); @@ -126,7 +126,7 @@ bool QuickOpen::Read(void *Data,size_t Size,size_t &Result) if (!Loaded) return false; // Find next suitable cached block. - while (LastReadHeaderPos+LastReadHeader.Size()<=SeekPos) + while (LastReadHeaderPos+LastReadHeader.size()<=SeekPos) if (!ReadNext()) break; if (!Loaded) @@ -138,9 +138,9 @@ bool QuickOpen::Read(void *Data,size_t Size,size_t &Result) return false; } - if (SeekPos>=LastReadHeaderPos && SeekPos+Size<=LastReadHeaderPos+LastReadHeader.Size()) + if (SeekPos>=LastReadHeaderPos && SeekPos+Size<=LastReadHeaderPos+LastReadHeader.size()) { - memcpy(Data,LastReadHeader+size_t(SeekPos-LastReadHeaderPos),Size); + memcpy(Data,&LastReadHeader[size_t(SeekPos-LastReadHeaderPos)],Size); Result=Size; SeekPos+=Size; UnsyncSeekPos=true; @@ -292,8 +292,8 @@ bool QuickOpen::ReadNext() size_t HeaderSize=(size_t)Raw.GetV(); if (HeaderSize>MAX_HEADER_SIZE_RAR5) return false; - LastReadHeader.Alloc(HeaderSize); - Raw.GetB(&LastReadHeader[0],HeaderSize); + LastReadHeader.resize(HeaderSize); + Raw.GetB(LastReadHeader.data(),HeaderSize); // Calculate the absolute position as offset from quick open service header. LastReadHeaderPos=QOHeaderPos-Offset; return true; diff --git a/vendor/unrar/qopen.hpp b/vendor/unrar/qopen.hpp index d745cea801..7adca4b5e5 100644 --- a/vendor/unrar/qopen.hpp +++ b/vendor/unrar/qopen.hpp @@ -43,7 +43,7 @@ class QuickOpen uint64 RawDataPos; // Current read position in QO data. size_t ReadBufSize; // Size of Buf data currently read from QO. size_t ReadBufPos; // Current read position in Buf data. - Array LastReadHeader; + std::vector LastReadHeader; uint64 LastReadHeaderPos; uint64 SeekPos; bool UnsyncSeekPos; // QOpen SeekPos does not match an actual file pointer. diff --git a/vendor/unrar/rar.cpp b/vendor/unrar/rar.cpp index 34b4b2789b..075e768f46 100644 --- a/vendor/unrar/rar.cpp +++ b/vendor/unrar/rar.cpp @@ -12,11 +12,11 @@ int main(int argc, char *argv[]) ErrHandler.SetSignalHandlers(true); #ifdef SFX_MODULE - wchar ModuleName[NM]; + std::wstring ModuleName; #ifdef _WIN_ALL - GetModuleFileName(NULL,ModuleName,ASIZE(ModuleName)); + ModuleName=GetModuleFileStr(); #else - CharToWide(argv[0],ModuleName,ASIZE(ModuleName)); + CharToWide(argv[0],ModuleName); #endif #endif @@ -35,9 +35,10 @@ int main(int argc, char *argv[]) try { - CommandData *Cmd=new CommandData; + // Use std::unique_ptr to free Cmd in case of exception. + std::unique_ptr Cmd(new CommandData); #ifdef SFX_MODULE - wcsncpyz(Cmd->Command,L"X",ASIZE(Cmd->Command)); + Cmd->Command=L"X"; char *Switch=argc>1 ? argv[1]:NULL; if (Switch!=NULL && Cmd->IsSwitch(Switch[0])) { @@ -68,7 +69,7 @@ int main(int argc, char *argv[]) #if defined(_WIN_ALL) && !defined(SFX_MODULE) ShutdownOnClose=Cmd->Shutdown; - if (ShutdownOnClose) + if (ShutdownOnClose!=POWERMODE_KEEP) ShutdownCheckAnother(true); #endif @@ -78,7 +79,6 @@ int main(int argc, char *argv[]) Cmd->OutTitle(); Cmd->ProcessCommand(); - delete Cmd; } catch (RAR_EXIT ErrCode) { @@ -100,6 +100,7 @@ int main(int argc, char *argv[]) Shutdown(ShutdownOnClose); #endif ErrHandler.MainExit=true; + CloseLogOptions(); return ErrHandler.GetErrorCode(); } #endif diff --git a/vendor/unrar/rar.hpp b/vendor/unrar/rar.hpp index 67edb6735d..38cd74446e 100644 --- a/vendor/unrar/rar.hpp +++ b/vendor/unrar/rar.hpp @@ -16,7 +16,6 @@ #include "unicode.hpp" #include "errhnd.hpp" #include "secpassword.hpp" -#include "array.hpp" #include "strlist.hpp" #include "timefn.hpp" #include "sha1.hpp" @@ -85,9 +84,6 @@ #include "global.hpp" -#if 0 -#include "benchmark.hpp" -#endif diff --git a/vendor/unrar/rardefs.hpp b/vendor/unrar/rardefs.hpp index 6858d39c13..433010f223 100644 --- a/vendor/unrar/rardefs.hpp +++ b/vendor/unrar/rardefs.hpp @@ -17,13 +17,28 @@ #define MAXPASSWORD 512 #define MAXPASSWORD_RAR 128 +// Set some arbitrary sensible limit to maximum path length to prevent +// the excessive memory allocation for dynamically allocated strings. +#define MAXPATHSIZE 0x10000 + #define MAXSFXSIZE 0x200000 #define MAXCMTSIZE 0x40000 +#ifdef _WIN_32 +#define DefSFXName L"default32.sfx" +#else #define DefSFXName L"default.sfx" +#endif #define DefSortListName L"rarfiles.lst" +// Maximum dictionary allowed by compression. Can be less than +// maximum dictionary supported by decompression. +#define PACK_MAX_DICT 0x1000000000ULL // 64 GB. + +// Maximum dictionary allowed by decompression. +#define UNPACK_MAX_DICT 0x1000000000ULL // 64 GB. + #ifndef SFX_MODULE #define USE_QOPEN diff --git a/vendor/unrar/raros.hpp b/vendor/unrar/raros.hpp index 4f4f2ae796..b701637abc 100644 --- a/vendor/unrar/raros.hpp +++ b/vendor/unrar/raros.hpp @@ -1,15 +1,6 @@ #ifndef _RAR_RAROS_ #define _RAR_RAROS_ -#ifdef __EMX__ - #define _EMX -#endif - -#ifdef __DJGPP__ - #define _DJGPP - #define _EMX -#endif - #if defined(__WIN32__) || defined(_WIN32) #define _WIN_ALL // Defined for all Windows platforms, 32 and 64 bit, mobile and desktop. #ifdef _M_X64 @@ -29,7 +20,7 @@ #define _APPLE #endif -#if !defined(_EMX) && !defined(_WIN_ALL) && !defined(_BEOS) && !defined(_APPLE) +#if !defined(_WIN_ALL) && !defined(_UNIX) #define _UNIX #endif diff --git a/vendor/unrar/rartypes.hpp b/vendor/unrar/rartypes.hpp index 3d3111bc38..a612c345dd 100644 --- a/vendor/unrar/rartypes.hpp +++ b/vendor/unrar/rartypes.hpp @@ -5,7 +5,7 @@ typedef uint8_t byte; // Unsigned 8 bits. typedef uint16_t ushort; // Preferably 16 bits, but can be more. -typedef unsigned int uint; // 32 bits or more. +typedef unsigned int uint; // Preferably 32 bits, likely can be more. typedef uint32_t uint32; // 32 bits exactly. typedef int32_t int32; // Signed 32 bits exactly. typedef uint64_t uint64; // 64 bits exactly. diff --git a/vendor/unrar/rarvm.cpp b/vendor/unrar/rarvm.cpp index 8d8675a39b..c44e021014 100644 --- a/vendor/unrar/rarvm.cpp +++ b/vendor/unrar/rarvm.cpp @@ -246,7 +246,7 @@ bool RarVM::ExecuteStandardFilter(VM_StandardFilters FilterType) } else Predicted=PrevByte; - DestData[I]=PrevByte=(byte)(Predicted-*(SrcData++)); + PrevByte=DestData[I]=(byte)(Predicted-*(SrcData++)); } } for (uint I=PosR,Border=DataSize-2;I>16); D[3]=(byte)(Field>>24); #else - *(uint32 *)Data=Field; + *(uint32 *)Data=(uint32)Field; #endif } @@ -87,18 +87,32 @@ inline uint32 RawGetBE4(const byte *m) #elif defined(USE_MEM_BYTESWAP) && (defined(__clang__) || defined(__GNUC__)) return __builtin_bswap32(*(uint32 *)m); #else - return uint32(m[0]<<24) | uint32(m[1]<<16) | uint32(m[2]<<8) | m[3]; + return uint32(m[0])<<24 | uint32(m[1])<<16 | uint32(m[2])<<8 | m[3]; +#endif +} + + +// Load 8 big endian bytes from memory and return uint64. +inline uint64 RawGetBE8(const byte *m) +{ +#if defined(USE_MEM_BYTESWAP) && defined(_MSC_VER) + return _byteswap_uint64(*(uint64 *)m); +#elif defined(USE_MEM_BYTESWAP) && (defined(__clang__) || defined(__GNUC__)) + return __builtin_bswap64(*(uint64 *)m); +#else + return uint64(m[0])<<56 | uint64(m[1])<<48 | uint64(m[2])<<40 | uint64(m[3])<<32 | + uint64(m[4])<<24 | uint64(m[5])<<16 | uint64(m[6])<<8 | m[7]; #endif } // Save integer to memory as big endian. -inline void RawPutBE4(uint32 i,byte *mem) +inline void RawPutBE4(uint i,byte *mem) { #if defined(USE_MEM_BYTESWAP) && defined(_MSC_VER) - *(uint32*)mem = _byteswap_ulong(i); + *(uint32*)mem = _byteswap_ulong((uint32)i); #elif defined(USE_MEM_BYTESWAP) && (defined(__clang__) || defined(__GNUC__)) - *(uint32*)mem = __builtin_bswap32(i); + *(uint32*)mem = __builtin_bswap32((uint32)i); #else mem[0]=byte(i>>24); mem[1]=byte(i>>16); @@ -108,6 +122,26 @@ inline void RawPutBE4(uint32 i,byte *mem) } +// Save integer to memory as big endian. +inline void RawPutBE8(uint64 i,byte *mem) +{ +#if defined(USE_MEM_BYTESWAP) && defined(_MSC_VER) + *(uint64*)mem = _byteswap_uint64(i); +#elif defined(USE_MEM_BYTESWAP) && (defined(__clang__) || defined(__GNUC__)) + *(uint64*)mem = __builtin_bswap64(i); +#else + mem[0]=byte(i>>56); + mem[1]=byte(i>>48); + mem[2]=byte(i>>40); + mem[3]=byte(i>>32); + mem[4]=byte(i>>24); + mem[5]=byte(i>>16); + mem[6]=byte(i>>8); + mem[7]=byte(i); +#endif +} + + inline uint32 ByteSwap32(uint32 i) { #ifdef _MSC_VER @@ -119,4 +153,29 @@ inline uint32 ByteSwap32(uint32 i) #endif } + + + +inline bool IsPow2(uint64 n) // Check if 'n' is power of 2. +{ + return (n & (n-1))==0; +} + + +inline uint64 GetGreaterOrEqualPow2(uint64 n) +{ + uint64 p=1; + while (pRead(&Data[FullSize],AlignedReadSize); Crypt->DecryptBlock(&Data[FullSize],AlignedReadSize); DataSize+=ReadSize==0 ? 0:Size; @@ -55,7 +55,7 @@ size_t RawRead::Read(size_t Size) #endif if (Size!=0) { - Data.Add(Size); + Data.resize(Data.size()+Size); ReadSize=SrcFile->Read(&Data[DataSize],Size); DataSize+=ReadSize; } @@ -67,7 +67,7 @@ void RawRead::Read(byte *SrcData,size_t Size) { if (Size!=0) { - Data.Add(Size); + Data.resize(Data.size()+Size); memcpy(&Data[DataSize],SrcData,Size); DataSize+=Size; } @@ -96,8 +96,7 @@ uint RawRead::Get4() { if (ReadPos+3 Data; + std::vector Data; File *SrcFile; size_t DataSize; size_t ReadPos; @@ -27,7 +27,7 @@ class RawRead uint GetCRC50(); byte* GetDataPtr() {return &Data[0];} size_t Size() {return DataSize;} - size_t PaddedSize() {return Data.Size()-DataSize;} + size_t PaddedSize() {return Data.size()-DataSize;} size_t DataLeft() {return DataSize-ReadPos;} size_t GetPos() {return ReadPos;} void SetPos(size_t Pos) {ReadPos=Pos;} diff --git a/vendor/unrar/rdwrfn.cpp b/vendor/unrar/rdwrfn.cpp index fa71376018..a49a8bcedf 100644 --- a/vendor/unrar/rdwrfn.cpp +++ b/vendor/unrar/rdwrfn.cpp @@ -246,28 +246,28 @@ void ComprDataIO::GetUnpackedData(byte **Data,size_t *Size) } -void ComprDataIO::SetEncryption(bool Encrypt,CRYPT_METHOD Method, +// Return true if encryption or decryption mode is set correctly. +bool ComprDataIO::SetEncryption(bool Encrypt,CRYPT_METHOD Method, SecPassword *Password,const byte *Salt,const byte *InitV, uint Lg2Cnt,byte *HashKey,byte *PswCheck) { -#ifndef RAR_NOCRYPT +#ifdef RAR_NOCRYPT + return false; +#else if (Encrypt) + { Encryption=Crypt->SetCryptKeys(true,Method,Password,Salt,InitV,Lg2Cnt,HashKey,PswCheck); + return Encryption; + } else + { Decryption=Decrypt->SetCryptKeys(false,Method,Password,Salt,InitV,Lg2Cnt,HashKey,PswCheck); + return Decryption; + } #endif } -#if !defined(SFX_MODULE) && !defined(RAR_NOCRYPT) -void ComprDataIO::SetAV15Encryption() -{ - Decryption=true; - Decrypt->SetAV15Encryption(); -} -#endif - - #if !defined(SFX_MODULE) && !defined(RAR_NOCRYPT) void ComprDataIO::SetCmt13Encryption() { @@ -299,11 +299,15 @@ void ComprDataIO::AdjustTotalArcSize(Archive *Arc) // packed size to beginning of these blocks. Earlier we already calculated // the total size based on entire archive sizes. We also set LastArcSize // to start of first trailing block, to add it later to ProcessedArcSize. - int64 ArcLength=Arc->IsSeekable() ? Arc->FileLength() : 0; - if (Arc->MainHead.QOpenOffset!=0) // QO is always preceding RR record. + uint64 ArcLength=Arc->IsSeekable() ? Arc->FileLength() : 0; + // QO is always preceding RR record. + // Also we check QO and RR to be less than archive length to prevent + // negative "ArcLength-LastArcSize" and possible signed integer overflow + // when calculating TotalArcSize. + if (Arc->MainHead.QOpenOffset>0 && Arc->MainHead.QOpenOffsetMainHead.QOpenOffset; else - if (Arc->MainHead.RROffset!=0) + if (Arc->MainHead.RROffset>0 && Arc->MainHead.RROffsetMainHead.RROffset; else { diff --git a/vendor/unrar/rdwrfn.hpp b/vendor/unrar/rdwrfn.hpp index 3060a0ff3f..58685ca363 100644 --- a/vendor/unrar/rdwrfn.hpp +++ b/vendor/unrar/rdwrfn.hpp @@ -6,10 +6,6 @@ class CmdAdd; class Unpack; class ArcFileSearch; -#if 0 -// We use external i/o calls for Benchmark command. -#define COMPRDATAIO_EXTIO -#endif class ComprDataIO { @@ -70,9 +66,8 @@ class ComprDataIO void SetFiles(File *SrcFile,File *DestFile); void SetCommand(CmdAdd *Cmd) {Command=Cmd;} void SetSubHeader(FileHeader *hd,int64 *Pos) {SubHead=hd;SubHeadPos=Pos;} - void SetEncryption(bool Encrypt,CRYPT_METHOD Method,SecPassword *Password, + bool SetEncryption(bool Encrypt,CRYPT_METHOD Method,SecPassword *Password, const byte *Salt,const byte *InitV,uint Lg2Cnt,byte *HashKey,byte *PswCheck); - void SetAV15Encryption(); void SetCmt13Encryption(); void SetUnpackToMemory(byte *Addr,uint Size); void SetCurrentCommand(wchar Cmd) {CurrentCommand=Cmd;} diff --git a/vendor/unrar/recvol.cpp b/vendor/unrar/recvol.cpp index b178207119..426d9ceebe 100644 --- a/vendor/unrar/recvol.cpp +++ b/vendor/unrar/recvol.cpp @@ -1,11 +1,12 @@ #include "rar.hpp" + #include "recvol3.cpp" #include "recvol5.cpp" -bool RecVolumesRestore(CommandData *Cmd,const wchar *Name,bool Silent) +bool RecVolumesRestore(CommandData *Cmd,const std::wstring &Name,bool Silent) { Archive Arc(Cmd); if (!Arc.Open(Name)) @@ -42,24 +43,20 @@ bool RecVolumesRestore(CommandData *Cmd,const wchar *Name,bool Silent) } -void RecVolumesTest(CommandData *Cmd,Archive *Arc,const wchar *Name) +void RecVolumesTest(CommandData *Cmd,Archive *Arc,const std::wstring &Name) { - wchar RevName[NM]; - *RevName=0; - if (Arc!=NULL) + std::wstring RevName; + if (Arc==NULL) + RevName=Name; + else { // We received .rar or .exe volume as a parameter, trying to find // the matching .rev file number 1. bool NewNumbering=Arc->NewNumbering; - wchar ArcName[NM]; - wcsncpyz(ArcName,Name,ASIZE(ArcName)); - - wchar *VolNumStart=VolNameToFirstName(ArcName,ArcName,ASIZE(ArcName),NewNumbering); - wchar RecVolMask[NM]; - wcsncpyz(RecVolMask,ArcName,ASIZE(RecVolMask)); - size_t BaseNamePartLength=VolNumStart-ArcName; - wcsncpyz(RecVolMask+BaseNamePartLength,L"*.rev",ASIZE(RecVolMask)-BaseNamePartLength); + std::wstring RecVolMask; + size_t VolNumStart=VolNameToFirstName(Name,RecVolMask,NewNumbering); + RecVolMask.replace(VolNumStart, std::wstring::npos, L"*.rev"); FindFile Find; Find.SetMask(RecVolMask); @@ -67,31 +64,30 @@ void RecVolumesTest(CommandData *Cmd,Archive *Arc,const wchar *Name) while (Find.Next(&RecData)) { - wchar *Num=GetVolNumPart(RecData.Name); - if (*Num!='1') // Name must have "0...01" numeric part. + size_t NumPos=GetVolNumPos(RecData.Name); + if (RecData.Name[NumPos]!='1') // Name must have "0...01" numeric part. continue; bool FirstVol=true; - while (--Num>=RecData.Name && IsDigit(*Num)) - if (*Num!='0') + while (NumPos>0 && IsDigit(RecData.Name[--NumPos])) + if (RecData.Name[NumPos]!='0') { FirstVol=false; break; } if (FirstVol) { - wcsncpyz(RevName,RecData.Name,ASIZE(RevName)); - Name=RevName; + RevName=RecData.Name; break; } } - if (*RevName==0) // First .rev file not found. + if (RevName.empty()) // First .rev file not found. return; } File RevFile; - if (!RevFile.Open(Name)) + if (!RevFile.Open(RevName)) { - ErrHandler.OpenErrorMsg(Name); // It also sets RARX_OPEN. + ErrHandler.OpenErrorMsg(RevName); // It also sets RARX_OPEN. return; } mprintf(L"\n"); @@ -101,11 +97,11 @@ void RecVolumesTest(CommandData *Cmd,Archive *Arc,const wchar *Name) if (Rev5) { RecVolumes5 RecVol(Cmd,true); - RecVol.Test(Cmd,Name); + RecVol.Test(Cmd,RevName); } else { RecVolumes3 RecVol(Cmd,true); - RecVol.Test(Cmd,Name); + RecVol.Test(Cmd,RevName); } } diff --git a/vendor/unrar/recvol.hpp b/vendor/unrar/recvol.hpp index 4a6d663ffe..159bd1adc8 100644 --- a/vendor/unrar/recvol.hpp +++ b/vendor/unrar/recvol.hpp @@ -8,7 +8,7 @@ class RecVolumes3 { private: File *SrcFile[256]; - Array Buf; + std::vector Buf; #ifdef RAR_SMP ThreadPool *RSThreadPool; @@ -16,16 +16,16 @@ class RecVolumes3 public: RecVolumes3(CommandData *Cmd,bool TestOnly); ~RecVolumes3(); - void Make(CommandData *Cmd,wchar *ArcName); - bool Restore(CommandData *Cmd,const wchar *Name,bool Silent); - void Test(CommandData *Cmd,const wchar *Name); + void Make(CommandData *Cmd,std::wstring ArcName); + bool Restore(CommandData *Cmd,const std::wstring &Name,bool Silent); + void Test(CommandData *Cmd,const std::wstring &Name); }; struct RecVolItem { File *f; - wchar Name[NM]; + std::wstring Name; uint CRC; uint64 FileSize; bool New; // Newly created RAR volume. @@ -52,7 +52,7 @@ class RecVolumes5 void ProcessRS(CommandData *Cmd,uint MaxRead,bool Encode); uint ReadHeader(File *RecFile,bool FirstRev); - Array RecItems; + std::vector RecItems; byte *RealReadBuffer; // Real pointer returned by 'new'. byte *ReadBuffer; // Pointer aligned for SSE instructions. @@ -78,11 +78,11 @@ class RecVolumes5 public: RecVolumes5(CommandData *Cmd,bool TestOnly); ~RecVolumes5(); - bool Restore(CommandData *Cmd,const wchar *Name,bool Silent); - void Test(CommandData *Cmd,const wchar *Name); + bool Restore(CommandData *Cmd,const std::wstring &Name,bool Silent); + void Test(CommandData *Cmd,const std::wstring &Name); }; -bool RecVolumesRestore(CommandData *Cmd,const wchar *Name,bool Silent); -void RecVolumesTest(CommandData *Cmd,Archive *Arc,const wchar *Name); +bool RecVolumesRestore(CommandData *Cmd,const std::wstring &Name,bool Silent); +void RecVolumesTest(CommandData *Cmd,Archive *Arc,const std::wstring &Name); #endif diff --git a/vendor/unrar/recvol3.cpp b/vendor/unrar/recvol3.cpp index 0138d0f3a9..4199deed1b 100644 --- a/vendor/unrar/recvol3.cpp +++ b/vendor/unrar/recvol3.cpp @@ -23,12 +23,6 @@ class RSEncode // Encode or decode data area, one object per one thread. #ifdef RAR_SMP -THREAD_PROC(RSEncodeThread) -{ - RSEncode *rs=(RSEncode *)Data; - rs->EncodeBuf(); -} - THREAD_PROC(RSDecodeThread) { RSEncode *rs=(RSEncode *)Data; @@ -47,8 +41,7 @@ RecVolumes3::RecVolumes3(CommandData *Cmd,bool TestOnly) } else { - Buf.Alloc(TotalBufferSize); - memset(SrcFile,0,sizeof(SrcFile)); + Buf.resize(TotalBufferSize); #ifdef RAR_SMP RSThreadPool=new ThreadPool(Cmd->Threads); #endif @@ -68,30 +61,16 @@ RecVolumes3::~RecVolumes3() -void RSEncode::EncodeBuf() -{ - for (int BufPos=BufStart;BufPosName;Ext--) - if (!IsDigit(*Ext)) - if (*Ext=='_' && IsDigit(*(Ext-1))) + for (ExtPos--;ExtPos>0;ExtPos--) + if (!IsDigit(Name[ExtPos])) + if (Name[ExtPos]=='_' && IsDigit(Name[ExtPos-1])) DigitGroup++; else break; @@ -99,19 +78,19 @@ static bool IsNewStyleRev(const wchar *Name) } -bool RecVolumes3::Restore(CommandData *Cmd,const wchar *Name,bool Silent) +bool RecVolumes3::Restore(CommandData *Cmd,const std::wstring &Name,bool Silent) { - wchar ArcName[NM]; - wcsncpyz(ArcName,Name,ASIZE(ArcName)); - wchar *Ext=GetExt(ArcName); + std::wstring ArcName=Name; bool NewStyle=false; // New style .rev volumes are supported since RAR 3.10. - bool RevName=Ext!=NULL && wcsicomp(Ext,L".rev")==0; + bool RevName=CmpExt(ArcName,L"rev"); if (RevName) { NewStyle=IsNewStyleRev(ArcName); - while (Ext>ArcName+1 && (IsDigit(*(Ext-1)) || *(Ext-1)=='_')) - Ext--; - wcsncpyz(Ext,L"*.*",ASIZE(ArcName)-(Ext-ArcName)); + + size_t ExtPos=GetExtPos(ArcName); + while (ExtPos>1 && (IsDigit(ArcName[ExtPos-1]) || ArcName[ExtPos-1]=='_')) + ExtPos--; + ArcName.replace(ExtPos,std::wstring::npos,L"*.*"); FindFile Find; Find.SetMask(ArcName); @@ -121,7 +100,7 @@ bool RecVolumes3::Restore(CommandData *Cmd,const wchar *Name,bool Silent) Archive Arc(Cmd); if (Arc.WOpen(fd.Name) && Arc.IsArchive(true)) { - wcsncpyz(ArcName,fd.Name,ASIZE(ArcName)); + ArcName=fd.Name; break; } } @@ -138,11 +117,10 @@ bool RecVolumes3::Restore(CommandData *Cmd,const wchar *Name,bool Silent) bool NewNumbering=Arc.NewNumbering; Arc.Close(); - wchar *VolNumStart=VolNameToFirstName(ArcName,ArcName,ASIZE(ArcName),NewNumbering); - wchar RecVolMask[NM]; - wcsncpyz(RecVolMask,ArcName,ASIZE(RecVolMask)); - size_t BaseNamePartLength=VolNumStart-ArcName; - wcsncpyz(RecVolMask+BaseNamePartLength,L"*.rev",ASIZE(RecVolMask)-BaseNamePartLength); + size_t VolNumStart=VolNameToFirstName(ArcName,ArcName,NewNumbering); + std::wstring RecVolMask=ArcName; + RecVolMask.replace(VolNumStart,std::wstring::npos,L"*.rev"); + size_t BaseNamePartLength=VolNumStart; int64 RecFileSize=0; @@ -155,25 +133,25 @@ bool RecVolumes3::Restore(CommandData *Cmd,const wchar *Name,bool Silent) Find.SetMask(RecVolMask); FindData RecData; int FileNumber=0,RecVolNumber=0,FoundRecVolumes=0,MissingVolumes=0; - wchar PrevName[NM]; + std::wstring PrevName; while (Find.Next(&RecData)) { - wchar *CurName=RecData.Name; + std::wstring CurName=RecData.Name; int P[3]; if (!RevName && !NewStyle) { NewStyle=true; - wchar *Dot=GetExt(CurName); - if (Dot!=NULL) + size_t DotPos=GetExtPos(CurName); + if (DotPos!=std::wstring::npos) { - int LineCount=0; - Dot--; - while (Dot>CurName && *Dot!='.') + uint LineCount=0; + DotPos--; + while (DotPos>0 && CurName[DotPos]!='.') { - if (*Dot=='_') + if (CurName[DotPos]=='_') LineCount++; - Dot--; + DotPos--; } if (LineCount==2) NewStyle=false; @@ -209,17 +187,17 @@ bool RecVolumes3::Restore(CommandData *Cmd,const wchar *Name,bool Silent) } else { - wchar *Dot=GetExt(CurName); - if (Dot==NULL) + size_t DotPos=GetExtPos(CurName); + if (DotPos==std::wstring::npos) continue; bool WrongParam=false; for (size_t I=0;I=CurName+BaseNamePartLength); - P[I]=atoiw(Dot+1); + DotPos--; + } while (IsDigit(CurName[DotPos]) && DotPos>=BaseNamePartLength); + P[I]=atoiw(&CurName[DotPos+1]); if (P[I]==0 || P[I]>255) WrongParam=true; } @@ -235,7 +213,7 @@ bool RecVolumes3::Restore(CommandData *Cmd,const wchar *Name,bool Silent) } RecVolNumber=P[1]; FileNumber=P[2]; - wcsncpyz(PrevName,CurName,ASIZE(PrevName)); + PrevName=CurName; File *NewFile=new File; NewFile->TOpen(CurName); @@ -256,11 +234,9 @@ bool RecVolumes3::Restore(CommandData *Cmd,const wchar *Name,bool Silent) if (FoundRecVolumes==0) return false; - bool WriteFlags[256]; - memset(WriteFlags,0,sizeof(WriteFlags)); + bool WriteFlags[256]{}; - wchar LastVolName[NM]; - *LastVolName=0; + std::wstring LastVolName; for (int CurArcNum=0;CurArcNumClose(); - wchar NewName[NM]; - wcsncpyz(NewName,ArcName,ASIZE(NewName)); - wcsncatz(NewName,L".bad",ASIZE(NewName)); + std::wstring NewName=ArcName+L".bad"; uiMsg(UIMSG_BADARCHIVE,ArcName); uiMsg(UIMSG_RENAMING,ArcName,NewName); @@ -329,13 +303,13 @@ bool RecVolumes3::Restore(CommandData *Cmd,const wchar *Name,bool Silent) MissingVolumes++; if (CurArcNum==FileNumber-1) - wcsncpyz(LastVolName,ArcName,ASIZE(LastVolName)); + LastVolName=ArcName; uiMsg(UIMSG_MISSINGVOL,ArcName); uiMsg(UIEVENT_NEWARCHIVE,ArcName); } SrcFile[CurArcNum]=(File*)NewFile; - NextVolumeName(ArcName,ASIZE(ArcName),!NewNumbering); + NextVolumeName(ArcName,!NewNumbering); } uiMsg(UIMSG_RECVOLMISSING,MissingVolumes); @@ -460,7 +434,7 @@ bool RecVolumes3::Restore(CommandData *Cmd,const wchar *Name,bool Silent) CurFile->Close(); SrcFile[I]=NULL; } - if (*LastVolName!=0) + if (!LastVolName.empty()) { // Truncate the last volume to its real size. Archive Arc(Cmd); @@ -504,7 +478,7 @@ void RSEncode::DecodeBuf() } -void RecVolumes3::Test(CommandData *Cmd,const wchar *Name) +void RecVolumes3::Test(CommandData *Cmd,const std::wstring &Name) { if (!IsNewStyleRev(Name)) // RAR 3.0 name#_#_#.rev do not include CRC32. { @@ -512,8 +486,7 @@ void RecVolumes3::Test(CommandData *Cmd,const wchar *Name) return; } - wchar VolName[NM]; - wcsncpyz(VolName,Name,ASIZE(VolName)); + std::wstring VolName=Name; while (FileExist(VolName)) { @@ -525,7 +498,7 @@ void RecVolumes3::Test(CommandData *Cmd,const wchar *Name) } if (!uiStartFileExtract(VolName,false,true,false)) return; - mprintf(St(MExtrTestFile),VolName); + mprintf(St(MExtrTestFile),VolName.c_str()); mprintf(L" "); CurFile.Seek(0,SEEK_END); int64 Length=CurFile.Tell(); @@ -546,6 +519,6 @@ void RecVolumes3::Test(CommandData *Cmd,const wchar *Name) ErrHandler.SetErrorCode(RARX_CRC); } - NextVolumeName(VolName,ASIZE(VolName),false); + NextVolumeName(VolName,false); } } diff --git a/vendor/unrar/recvol5.cpp b/vendor/unrar/recvol5.cpp index 2d9c947110..e094b17119 100644 --- a/vendor/unrar/recvol5.cpp +++ b/vendor/unrar/recvol5.cpp @@ -48,8 +48,8 @@ RecVolumes5::~RecVolumes5() { delete[] RealBuf; delete[] RealReadBuffer; - for (uint I=0;IArcName && IsDigit(*(Num-1))) - Num--; - if (Num<=PointToName(ArcName)) + size_t NumPos=GetVolNumPos(ArcName); + while (NumPos>0 && IsDigit(ArcName[NumPos-1])) + NumPos--; + if (NumPos<=GetNamePos(ArcName)) return false; // Numeric part is missing or entire volume name is numeric, not possible for RAR or REV volume. - wcsncpyz(Num,L"*.*",ASIZE(ArcName)-(Num-ArcName)); + ArcName.replace(NumPos,std::wstring::npos,L"*.*"); - wchar FirstVolName[NM]; - *FirstVolName=0; - - wchar LongestRevName[NM]; - *LongestRevName=0; + std::wstring FirstVolName; + std::wstring LongestRevName; int64 RecFileSize=0; @@ -184,8 +180,8 @@ bool RecVolumes5::Restore(CommandData *Cmd,const wchar *Name,bool Silent) ItemPos=RecNum; FoundRecVolumes++; - if (wcslen(fd.Name)>wcslen(LongestRevName)) - wcsncpyz(LongestRevName,fd.Name,ASIZE(LongestRevName)); + if (fd.Name.size()>LongestRevName.size()) + LongestRevName=fd.Name; } } else @@ -204,35 +200,35 @@ bool RecVolumes5::Restore(CommandData *Cmd,const wchar *Name,bool Silent) // RAR volume found. Get its number, store the handle in appropriate // array slot, clean slots in between if we had to grow the array. - wchar *Num=GetVolNumPart(fd.Name); + size_t NumPos=GetVolNumPos(fd.Name); uint VolNum=0; - for (uint K=1;Num>=fd.Name && IsDigit(*Num);K*=10,Num--) - VolNum+=(*Num-'0')*K; + for (uint K=1;(int)NumPos>=0 && IsDigit(fd.Name[NumPos]);K*=10,NumPos--) + VolNum+=(fd.Name[NumPos]-'0')*K; if (VolNum==0 || VolNum>MaxVolumes) continue; - size_t CurSize=RecItems.Size(); + size_t CurSize=RecItems.size(); if (VolNum>CurSize) { - RecItems.Alloc(VolNum); - for (size_t I=CurSize;If=Vol; Item->New=false; - wcsncpyz(Item->Name,fd.Name,ASIZE(Item->Name)); + Item->Name=fd.Name; } } @@ -244,10 +240,10 @@ bool RecVolumes5::Restore(CommandData *Cmd,const wchar *Name,bool Silent) // If we did not find even a single .rar volume, create .rar volume name // based on the longest .rev file name. Use longest .rev, so we have // enough space for volume number. - if (*FirstVolName==0) + if (FirstVolName.empty()) { - SetExt(LongestRevName,L"rar",ASIZE(LongestRevName)); - VolNameToFirstName(LongestRevName,FirstVolName,ASIZE(FirstVolName),true); + SetExt(LongestRevName,L"rar"); + VolNameToFirstName(LongestRevName,FirstVolName,true); } uiMsg(UIMSG_RECVOLCALCCHECKSUM); @@ -309,9 +305,8 @@ bool RecVolumes5::Restore(CommandData *Cmd,const wchar *Name,bool Silent) { Item->f->Close(); - wchar NewName[NM]; - wcsncpyz(NewName,Item->Name,ASIZE(NewName)); - wcsncatz(NewName,L".bad",ASIZE(NewName)); + std::wstring NewName; + NewName=Item->Name+L".bad"; uiMsg(UIMSG_BADARCHIVE,Item->Name); uiMsg(UIMSG_RENAMING,Item->Name,NewName); @@ -322,12 +317,12 @@ bool RecVolumes5::Restore(CommandData *Cmd,const wchar *Name,bool Silent) if ((Item->New=(Item->f==NULL))==true) { - wcsncpyz(Item->Name,FirstVolName,ASIZE(Item->Name)); + Item->Name=FirstVolName; uiMsg(UIMSG_CREATING,Item->Name); uiMsg(UIEVENT_NEWARCHIVE,Item->Name); File *NewVol=new File; bool UserReject; - if (!FileCreate(Cmd,NewVol,Item->Name,ASIZE(Item->Name),&UserReject)) + if (!FileCreate(Cmd,NewVol,Item->Name,&UserReject)) { if (!UserReject) ErrHandler.CreateErrorMsg(Item->Name); @@ -336,7 +331,7 @@ bool RecVolumes5::Restore(CommandData *Cmd,const wchar *Name,bool Silent) NewVol->Prealloc(Item->FileSize); Item->f=NewVol; } - NextVolumeName(FirstVolName,ASIZE(FirstVolName),false); + NextVolumeName(FirstVolName,false); } @@ -389,7 +384,7 @@ bool RecVolumes5::Restore(CommandData *Cmd,const wchar *Name,bool Silent) J++; VolNum=J++; // Use next valid REV volume data instead of RAR. } - RecVolItem *Item=RecItems+VolNum; + RecVolItem *Item=&RecItems[VolNum]; byte *B=&ReadBuf[0]; int ReadSize=0; @@ -411,7 +406,7 @@ bool RecVolumes5::Restore(CommandData *Cmd,const wchar *Name,bool Silent) for (uint I=0,J=0;IFileSize); Item->f->Write(Buf+(J++)*RecBufferSize,WriteSize); Item->FileSize-=WriteSize; @@ -477,10 +472,10 @@ uint RecVolumes5::ReadHeader(File *RecFile,bool FirstRev) { // If we have read the first valid REV file, init data structures // using information from REV header. - size_t CurSize=RecItems.Size(); - RecItems.Alloc(TotalCount); - for (size_t I=CurSize;I=1) // Check the maximum supported cpuid function. @@ -102,8 +111,24 @@ void Rijndael::Init(bool Encrypt,const byte *key,uint keyLen,const byte * initVe } else AES_NI=false; -#elif defined(USE_NEON) - AES_Neon=(getauxval(AT_HWCAP) & HWCAP_AES)!=0; +#elif defined(__GNUC__) + AES_NI=__builtin_cpu_supports("aes"); +#endif + +#elif defined(USE_NEON_AES) + #ifdef _APPLE + // getauxval isn't available in OS X + uint Value=0; + size_t Size=sizeof(Value); + int RetCode=sysctlbyname("hw.optional.arm.FEAT_AES",&Value,&Size,NULL,0); + + // We treat sysctlbyname failure with -1 return code as AES presence, + // because "hw.optional.arm.FEAT_AES" was missing in OS X 11, but AES + // still was supported by Neon. + AES_Neon=RetCode!=0 || Value!=0; + #else + AES_Neon=(getauxval(AT_HWCAP) & HWCAP_AES)!=0; + #endif #endif // Other developers asked us to initialize it to suppress "may be used @@ -156,7 +181,7 @@ void Rijndael::blockEncrypt(const byte *input,size_t inputLen,byte *outBuffer) blockEncryptSSE(input,numBlocks,outBuffer); return; } -#elif defined(USE_NEON) +#elif defined(USE_NEON_AES) if (AES_Neon) { blockEncryptNeon(input,numBlocks,outBuffer); @@ -249,7 +274,7 @@ void Rijndael::blockEncryptSSE(const byte *input,size_t numBlocks,byte *outBuffe #endif -#ifdef USE_NEON +#ifdef USE_NEON_AES void Rijndael::blockEncryptNeon(const byte *input,size_t numBlocks,byte *outBuffer) { byte *prevBlock = m_initVector; @@ -295,7 +320,7 @@ void Rijndael::blockDecrypt(const byte *input, size_t inputLen, byte *outBuffer) blockDecryptSSE(input,numBlocks,outBuffer); return; } -#elif defined(USE_NEON) +#elif defined(USE_NEON_AES) if (AES_Neon) { blockDecryptNeon(input,numBlocks,outBuffer); @@ -392,7 +417,7 @@ void Rijndael::blockDecryptSSE(const byte *input, size_t numBlocks, byte *outBuf #endif -#ifdef USE_NEON +#ifdef USE_NEON_AES void Rijndael::blockDecryptNeon(const byte *input, size_t numBlocks, byte *outBuffer) { byte iv[16]; @@ -585,16 +610,16 @@ void TestRijndael() for (uint L=0;L<3;L++) { byte Out[16]; - wchar Str[sizeof(Out)*2+1]; + std::wstring Str; uint KeyLength=128+L*64; rij.Init(true,Key[L],KeyLength,IV); for (uint I=0;I>8; - ((byte *)&T1L)[I]=gfMul(I<<4,M); - ((byte *)&T1H)[I]=gfMul(I<<4,M)>>8; - ((byte *)&T2L)[I]=gfMul(I<<8,M); - ((byte *)&T2H)[I]=gfMul(I<<8,M)>>8; - ((byte *)&T3L)[I]=gfMul(I<<12,M); - ((byte *)&T3H)[I]=gfMul(I<<12,M)>>8; + ((byte *)&T0L)[I]=byte(gfMul(I,M)); + ((byte *)&T0H)[I]=byte(gfMul(I,M)>>8); + ((byte *)&T1L)[I]=byte(gfMul(I<<4,M)); + ((byte *)&T1H)[I]=byte(gfMul(I<<4,M)>>8); + ((byte *)&T2L)[I]=byte(gfMul(I<<8,M)); + ((byte *)&T2H)[I]=byte(gfMul(I<<8,M)>>8); + ((byte *)&T3L)[I]=byte(gfMul(I<<12,M)); + ((byte *)&T3H)[I]=byte(gfMul(I<<12,M)>>8); } size_t Pos=0; diff --git a/vendor/unrar/rs16.hpp b/vendor/unrar/rs16.hpp index b67a7ca86e..3833313c56 100644 --- a/vendor/unrar/rs16.hpp +++ b/vendor/unrar/rs16.hpp @@ -17,6 +17,9 @@ class RSCoder16 void InvertDecoderMatrix(); #ifdef USE_SSE +#if defined(USE_SSE) && defined(__GNUC__) + __attribute__((target("ssse3"))) +#endif bool SSE_UpdateECC(uint DataNum, uint ECCNum, const byte *Data, byte *ECC, size_t BlockSize); #endif diff --git a/vendor/unrar/scantree.cpp b/vendor/unrar/scantree.cpp index dbaf1e4273..4313177741 100644 --- a/vendor/unrar/scantree.cpp +++ b/vendor/unrar/scantree.cpp @@ -10,12 +10,11 @@ ScanTree::ScanTree(StringList *FileMasks,RECURSE_MODE Recurse,bool GetLinks,SCAN ScanEntireDisk=false; FolderWildcards=false; + FindStack.push_back(NULL); // We need a single NULL pointer for initial Depth==0. + SetAllMaskDepth=0; - *CurMask=0; - memset(FindStack,0,sizeof(FindStack)); Depth=0; Errors=0; - *ErrArcName=0; Cmd=NULL; ErrDirList=NULL; ErrDirSpecPathLength=NULL; @@ -42,7 +41,7 @@ SCAN_CODE ScanTree::GetNext(FindData *FD) SCAN_CODE FindCode; while (1) { - if (*CurMask==0 && !GetNextMask()) + if (CurMask.empty() && !GetNextMask()) return SCAN_DONE; #ifndef SILENT @@ -79,7 +78,7 @@ bool ScanTree::ExpandFolderMask() { bool WildcardFound=false; uint SlashPos=0; - for (int I=0;CurMask[I]!=0;I++) + for (uint I=0;I0 && ExpandedFolderList.GetString(CurMask,ASIZE(CurMask))) + if (ExpandedFolderList.ItemsCount()>0 && ExpandedFolderList.GetString(CurMask)) return true; FolderWildcards=false; FilterList.Reset(); - if (!FileMasks->GetString(CurMask,ASIZE(CurMask))) + if (!FileMasks->GetString(CurMask)) return false; // Check if folder wildcards present. @@ -144,10 +141,10 @@ bool ScanTree::GetFilteredMask() uint SlashPos=0; uint StartPos=0; #ifdef _WIN_ALL // Not treat the special NTFS \\?\d: path prefix as a wildcard. - if (CurMask[0]=='\\' && CurMask[1]=='\\' && CurMask[2]=='?' && CurMask[3]=='\\') + if (CurMask.rfind(L"\\\\?\\",0)==0) StartPos=4; #endif - for (uint I=StartPos;CurMask[I]!=0;I++) + for (uint I=StartPos;I2 && CurMask[0]=='\\' && CurMask[1]=='\\') { - const wchar *Slash=wcschr(CurMask+2,'\\'); - if (Slash!=NULL) + auto Slash=CurMask.find('\\',2); + if (Slash!=std::wstring::npos) { - Slash=wcschr(Slash+1,'\\'); - ScanEntireDisk=Slash!=NULL && *(Slash+1)==0; + Slash=CurMask.find('\\',Slash+1); + // If backslash is found and it is the last string character. + ScanEntireDisk=Slash!=std::wstring::npos && Slash+1==CurMask.size(); } } else ScanEntireDisk=IsDriveLetter(CurMask) && IsPathDiv(CurMask[2]) && CurMask[3]==0; - wchar *Name=PointToName(CurMask); - if (*Name==0) - wcsncatz(CurMask,MASKALL,ASIZE(CurMask)); - if (Name[0]=='.' && (Name[1]==0 || Name[1]=='.' && Name[2]==0)) + auto NamePos=GetNamePos(CurMask); + std::wstring Name=CurMask.substr(NamePos); + if (Name.empty()) + CurMask+=MASKALL; + if (Name==L"." || Name==L"..") { - AddEndSlash(CurMask,ASIZE(CurMask)); - wcsncatz(CurMask,MASKALL,ASIZE(CurMask)); + AddEndSlash(CurMask); + CurMask+=MASKALL; } - SpecPathLength=Name-CurMask; + SpecPathLength=NamePos; Depth=0; - wcsncpyz(OrigCurMask,CurMask,ASIZE(OrigCurMask)); + OrigCurMask=CurMask; return true; } @@ -250,7 +249,7 @@ bool ScanTree::GetNextMask() SCAN_CODE ScanTree::FindProc(FindData *FD) { - if (*CurMask==0) + if (CurMask.empty()) return SCAN_NEXT; bool FastFindFile=false; @@ -283,10 +282,9 @@ SCAN_CODE ScanTree::FindProc(FindData *FD) // Create the new FindFile object for wildcard based search. FindStack[Depth]=new FindFile; - wchar SearchMask[NM]; - wcsncpyz(SearchMask,CurMask,ASIZE(SearchMask)); + std::wstring SearchMask=CurMask; if (SearchAll) - SetName(SearchMask,MASKALL,ASIZE(SearchMask)); + SetName(SearchMask,MASKALL); FindStack[Depth]->SetMask(SearchMask); } else @@ -325,7 +323,7 @@ SCAN_CODE ScanTree::FindProc(FindData *FD) // It is not necessary for directories, because even in "fast find" // mode, directory recursing will quit by (Depth < 0) condition, // which returns SCAN_DONE to calling function. - *CurMask=0; + CurMask.clear(); return RetCode; } @@ -344,9 +342,6 @@ SCAN_CODE ScanTree::FindProc(FindData *FD) if (Error) ScanError(Error); - wchar DirName[NM]; - *DirName=0; - // Going to at least one directory level higher. delete FindStack[Depth]; FindStack[Depth--]=NULL; @@ -362,29 +357,32 @@ SCAN_CODE ScanTree::FindProc(FindData *FD) return SCAN_DONE; } - wchar *Slash=wcsrchr(CurMask,CPATHDIVIDER); - if (Slash!=NULL) + auto Slash=CurMask.rfind(CPATHDIVIDER); + if (Slash!=std::wstring::npos) { - wchar Mask[NM]; - wcsncpyz(Mask,Slash,ASIZE(Mask)); + std::wstring Mask; + Mask=CurMask.substr(Slash); // Name mask with leading slash like \*.* if (DepthIsDir) + { + FD->Flags|=FDDF_SECONDDIR; + return Error ? SCAN_ERROR:SCAN_SUCCESS; } - } - if (GetDirs==SCAN_GETDIRSTWICE && - FindFile::FastFind(DirName,FD,GetLinks) && FD->IsDir) - { - FD->Flags|=FDDF_SECONDDIR; - return Error ? SCAN_ERROR:SCAN_SUCCESS; } return Error ? SCAN_ERROR:SCAN_NEXT; } @@ -414,22 +412,22 @@ SCAN_CODE ScanTree::FindProc(FindData *FD) return FastFindFile ? SCAN_DONE:SCAN_NEXT; } - wchar Mask[NM]; - - wcsncpyz(Mask,FastFindFile ? MASKALL:PointToName(CurMask),ASIZE(Mask)); - wcsncpyz(CurMask,FD->Name,ASIZE(CurMask)); + std::wstring Mask=FastFindFile ? MASKALL:PointToName(CurMask); + CurMask=FD->Name; - if (wcslen(CurMask)+wcslen(Mask)+1>=NM || Depth>=MAXSCANDEPTH-1) + if (CurMask.size()+Mask.size()+1>=MAXPATHSIZE || Depth>=MAXSCANDEPTH-1) { uiMsg(UIERROR_PATHTOOLONG,CurMask,SPATHDIVIDER,Mask); return SCAN_ERROR; } - AddEndSlash(CurMask,ASIZE(CurMask)); - wcsncatz(CurMask,Mask,ASIZE(CurMask)); + AddEndSlash(CurMask); + CurMask+=Mask; Depth++; + FindStack.resize(Depth+1); + // We need to use OrigCurMask for depths less than SetAllMaskDepth // and "*" for depths equal or larger than SetAllMaskDepth. // It is important when "fast finding" directories at Depth > 0. @@ -470,19 +468,18 @@ void ScanTree::ScanError(bool &Error) // We cannot just check FD->FileAttr here, it can be undefined // if we process "folder\*" mask or if we process "folder" mask, // but "folder" is inaccessible. - wchar *Slash=PointToName(CurMask); - if (Slash>CurMask) + auto Slash=GetNamePos(CurMask); + if (Slash>1) { - *(Slash-1)=0; - DWORD Attr=GetFileAttributes(CurMask); - *(Slash-1)=CPATHDIVIDER; + std::wstring Parent=CurMask.substr(0,Slash-1); + DWORD Attr=GetFileAttr(Parent); if (Attr!=0xffffffff && (Attr & FILE_ATTRIBUTE_REPARSE_POINT)!=0) Error=false; } // Do not display an error if we cannot scan contents of // "System Volume Information" folder. Normally it is not accessible. - if (wcsstr(CurMask,L"System Volume Information\\")!=NULL) + if (CurMask.find(L"System Volume Information\\")!=std::wstring::npos) Error=false; } #endif @@ -495,10 +492,10 @@ void ScanTree::ScanError(bool &Error) if (ErrDirList!=NULL) ErrDirList->AddString(CurMask); if (ErrDirSpecPathLength!=NULL) - ErrDirSpecPathLength->Push((uint)SpecPathLength); - wchar FullName[NM]; + ErrDirSpecPathLength->push_back((uint)SpecPathLength); + std::wstring FullName; // This conversion works for wildcard masks too. - ConvertNameToFull(CurMask,FullName,ASIZE(FullName)); + ConvertNameToFull(CurMask,FullName); uiMsg(UIERROR_DIRSCAN,FullName); ErrHandler.SysErrMsg(); } diff --git a/vendor/unrar/scantree.hpp b/vendor/unrar/scantree.hpp index 7ebe69ad1a..06bf545c61 100644 --- a/vendor/unrar/scantree.hpp +++ b/vendor/unrar/scantree.hpp @@ -11,20 +11,21 @@ enum SCAN_DIRS enum SCAN_CODE { SCAN_SUCCESS,SCAN_DONE,SCAN_ERROR,SCAN_NEXT }; -#define MAXSCANDEPTH (NM/2) - class CommandData; class ScanTree { private: + static constexpr size_t MAXSCANDEPTH = MAXPATHSIZE/2; + bool ExpandFolderMask(); bool GetFilteredMask(); bool GetNextMask(); SCAN_CODE FindProc(FindData *FD); void ScanError(bool &Error); - FindFile *FindStack[MAXSCANDEPTH]; +// FindFile *FindStack[MAXSCANDEPTH]; + std::vector FindStack; int Depth; int SetAllMaskDepth; @@ -33,13 +34,13 @@ class ScanTree RECURSE_MODE Recurse; bool GetLinks; SCAN_DIRS GetDirs; - int Errors; + uint Errors; // Set when processing paths like c:\ (root directory without wildcards). bool ScanEntireDisk; - wchar CurMask[NM]; - wchar OrigCurMask[NM]; + std::wstring CurMask; + std::wstring OrigCurMask; // Store all folder masks generated from folder wildcard mask in non-recursive mode. StringList ExpandedFolderList; @@ -49,7 +50,7 @@ class ScanTree // Save the list of unreadable dirs here. StringList *ErrDirList; - Array *ErrDirSpecPathLength; + std::vector *ErrDirSpecPathLength; // Set if processing a folder wildcard mask. bool FolderWildcards; @@ -57,7 +58,7 @@ class ScanTree bool SearchAllInRoot; size_t SpecPathLength; - wchar ErrArcName[NM]; + std::wstring ErrArcName; CommandData *Cmd; public: @@ -65,10 +66,10 @@ class ScanTree ~ScanTree(); SCAN_CODE GetNext(FindData *FindData); size_t GetSpecPathLength() {return SpecPathLength;} - int GetErrors() {return Errors;}; - void SetErrArcName(const wchar *Name) {wcsncpyz(ErrArcName,Name,ASIZE(ErrArcName));} + uint GetErrors() {return Errors;}; + void SetErrArcName(const std::wstring &Name) {ErrArcName=Name;} void SetCommandData(CommandData *Cmd) {ScanTree::Cmd=Cmd;} - void SetErrDirList(StringList *List,Array *Lengths) + void SetErrDirList(StringList *List,std::vector *Lengths) { ErrDirList=List; ErrDirSpecPathLength=Lengths; diff --git a/vendor/unrar/secpassword.cpp b/vendor/unrar/secpassword.cpp index 08da549721..8d8f298609 100644 --- a/vendor/unrar/secpassword.cpp +++ b/vendor/unrar/secpassword.cpp @@ -69,8 +69,8 @@ SecPassword::~SecPassword() void SecPassword::Clean() { PasswordSet=false; - if (Password.size()>0) - cleandata(&Password[0],Password.size()*sizeof(Password[0])); + if (!Password.empty()) + cleandata(Password.data(),Password.size()*sizeof(Password[0])); } @@ -79,7 +79,7 @@ void SecPassword::Clean() // So we use our own function for this purpose. void cleandata(void *data,size_t size) { - if (data==NULL || size==0) + if (data==nullptr || size==0) return; #if defined(_WIN_ALL) && defined(_MSC_VER) SecureZeroMemory(data,size); @@ -120,6 +120,14 @@ void SecPassword::Get(wchar *Psw,size_t MaxSize) } +void SecPassword::Get(std::wstring &Psw) +{ + wchar PswBuf[MAXPASSWORD]; + Get(PswBuf,ASIZE(PswBuf)); + Psw=PswBuf; +} + + void SecPassword::Set(const wchar *Psw) diff --git a/vendor/unrar/secpassword.hpp b/vendor/unrar/secpassword.hpp index 5284bce124..44e073c97c 100644 --- a/vendor/unrar/secpassword.hpp +++ b/vendor/unrar/secpassword.hpp @@ -15,6 +15,7 @@ class SecPassword ~SecPassword(); void Clean(); void Get(wchar *Psw,size_t MaxSize); + void Get(std::wstring &Psw); void Set(const wchar *Psw); bool IsSet() {return PasswordSet;} size_t Length(); @@ -23,6 +24,7 @@ class SecPassword void cleandata(void *data,size_t size); +inline void cleandata(std::wstring &s) {cleandata(&s[0],s.size()*sizeof(s[0]));} void SecHideData(void *Data,size_t DataSize,bool Encode,bool CrossProcess); #endif diff --git a/vendor/unrar/sha256.cpp b/vendor/unrar/sha256.cpp index f90d2c0954..4c93aba785 100644 --- a/vendor/unrar/sha256.cpp +++ b/vendor/unrar/sha256.cpp @@ -63,7 +63,7 @@ static void sha256_transform(sha256_context *ctx) for (uint I = 0; I < 64; I++) { - uint T1 = v[7] + Sg1(v[4]) + Ch(v[4], v[5], v[6]) + K[I] + W[I]; + uint32 T1 = v[7] + Sg1(v[4]) + Ch(v[4], v[5], v[6]) + K[I] + W[I]; // It is possible to eliminate variable copying if we unroll loop // and rename variables every time. But my test did not show any speed @@ -74,7 +74,7 @@ static void sha256_transform(sha256_context *ctx) v[4] = v[3] + T1; // It works a little faster when moved here from beginning of loop. - uint T2 = Sg0(v[0]) + Maj(v[0], v[1], v[2]); + uint32 T2 = Sg0(v[0]) + Maj(v[0], v[1], v[2]); v[3] = v[2]; v[2] = v[1]; @@ -146,3 +146,13 @@ void sha256_done(sha256_context *ctx, byte *Digest) sha256_init(ctx); } + + +void sha256_get(const void *Data, size_t Size, byte *Digest) +{ + sha256_context ctx; + sha256_init(&ctx); + sha256_process(&ctx, Data, Size); + sha256_done(&ctx, Digest); +} + diff --git a/vendor/unrar/sha256.hpp b/vendor/unrar/sha256.hpp index b6837e7601..186297c073 100644 --- a/vendor/unrar/sha256.hpp +++ b/vendor/unrar/sha256.hpp @@ -13,5 +13,6 @@ typedef struct void sha256_init(sha256_context *ctx); void sha256_process(sha256_context *ctx, const void *Data, size_t Size); void sha256_done(sha256_context *ctx, byte *Digest); +void sha256_get(const void *Data, size_t Size, byte *Digest); #endif diff --git a/vendor/unrar/strfn.cpp b/vendor/unrar/strfn.cpp index 7617f7a599..3fdaca59b1 100644 --- a/vendor/unrar/strfn.cpp +++ b/vendor/unrar/strfn.cpp @@ -2,66 +2,67 @@ const char *NullToEmpty(const char *Str) { - return Str==NULL ? "":Str; + return Str==nullptr ? "":Str; } const wchar *NullToEmpty(const wchar *Str) { - return Str==NULL ? L"":Str; + return Str==nullptr ? L"":Str; } -void IntToExt(const char *Src,char *Dest,size_t DestSize) +void IntToExt(const std::string &Src,std::string &Dest) { #ifdef _WIN_ALL - // OemToCharBuff does not stop at 0, so let's check source length. - size_t SrcLength=strlen(Src)+1; - if (DestSize>SrcLength) - DestSize=SrcLength; - OemToCharBuffA(Src,Dest,(DWORD)DestSize); - Dest[DestSize-1]=0; + if (std::addressof(Src)!=std::addressof(Dest)) + Dest=Src; + // OemToCharA use seems to be discouraged. So we use OemToCharBuffA, + // which doesn't stop at 0 and converts the entire passed length. + OemToCharBuffA(&Dest[0],&Dest[0],(DWORD)Dest.size()); + + std::string::size_type Pos=Dest.find('\0'); // Avoid zeroes inside of Dest. + if (Pos!=std::string::npos) + Dest.erase(Pos); + #else - if (Dest!=Src) - strncpyz(Dest,Src,DestSize); + if (std::addressof(Src)!=std::addressof(Dest)) + Dest=Src; #endif } // Convert archived names and comments to Unicode. // Allows user to select a code page in GUI. -void ArcCharToWide(const char *Src,wchar *Dest,size_t DestSize,ACTW_ENCODING Encoding) +void ArcCharToWide(const char *Src,std::wstring &Dest,ACTW_ENCODING Encoding) { #if defined(_WIN_ALL) // Console Windows RAR. if (Encoding==ACTW_UTF8) - UtfToWide(Src,Dest,DestSize); + UtfToWide(Src,Dest); else { - Array NameA; + std::string NameA; if (Encoding==ACTW_OEM) { - NameA.Alloc(DestSize+1); - IntToExt(Src,&NameA[0],NameA.Size()); - Src=&NameA[0]; + IntToExt(Src,NameA); + Src=NameA.data(); } - CharToWide(Src,Dest,DestSize); + CharToWide(Src,Dest); } #else // RAR for Unix. if (Encoding==ACTW_UTF8) - UtfToWide(Src,Dest,DestSize); + UtfToWide(Src,Dest); else - CharToWide(Src,Dest,DestSize); + CharToWide(Src,Dest); #endif - // Ensure that we return a zero terminate string for security reason. - // While [Jni]CharToWide might already do it, be protected in case of future - // changes in these functions. - if (DestSize>0) - Dest[DestSize-1]=0; + TruncateAtZero(Dest); // Ensure there are no zeroes inside of string. } + + int stricomp(const char *s1,const char *s2) { #ifdef _WIN_ALL @@ -113,6 +114,19 @@ wchar* RemoveEOL(wchar *Str) } +void RemoveEOL(std::wstring &Str) +{ + while (!Str.empty()) + { + wchar c=Str.back(); + if (c=='\r' || c=='\n' || c==' ' || c=='\t') + Str.pop_back(); + else + break; + } +} + + wchar* RemoveLF(wchar *Str) { for (int I=(int)wcslen(Str)-1;I>=0 && (Str[I]=='\r' || Str[I]=='\n');I--) @@ -121,6 +135,13 @@ wchar* RemoveLF(wchar *Str) } +void RemoveLF(std::wstring &Str) +{ + for (int I=(int)Str.size()-1;I>=0 && (Str[I]=='\r' || Str[I]=='\n');I--) + Str.erase(I); +} + + #if defined(SFX_MODULE) // char version of etoupperw. Used in console SFX module only. // Fast toupper for English only input and output. Additionally to speed, @@ -176,30 +197,18 @@ bool IsAlpha(int ch) -void BinToHex(const byte *Bin,size_t BinSize,char *HexA,wchar *HexW,size_t HexSize) +void BinToHex(const byte *Bin,size_t BinSize,std::wstring &Hex) { - uint A=0,W=0; // ASCII and Unicode hex output positions. + Hex.clear(); for (uint I=0;I> 4; uint Low=Bin[I] & 0xf; - uint HighHex=High>9 ? 'a'+High-10:'0'+High; - uint LowHex=Low>9 ? 'a'+Low-10:'0'+Low; - if (HexA!=NULL && A9 ? 'a'+High-10 : '0'+High; + uint LowHex=Low>9 ? 'a'+Low-10 : '0'+Low; + Hex+=HighHex; + Hex+=LowHex; } - if (HexA!=NULL && HexSize>0) - HexA[A]=0; - if (HexW!=NULL && HexSize>0) - HexW[W]=0; } @@ -217,22 +226,25 @@ uint GetDigits(uint Number) #endif -bool LowAscii(const char *Str) +bool LowAscii(const std::string &Str) { - for (size_t I=0;Str[I]!=0;I++) - if (/*(byte)Str[I]<32 || */(byte)Str[I]>127) + for (char Ch : Str) + { + // We convert char to byte in case char is signed. + if (/*(uint)Ch<32 || */(byte)Ch>127) return false; + } return true; } -bool LowAscii(const wchar *Str) +bool LowAscii(const std::wstring &Str) { - for (size_t I=0;Str[I]!=0;I++) + for (wchar Ch : Str) { // We convert wchar_t to uint just in case if some compiler // uses signed wchar_t. - if (/*(uint)Str[I]<32 || */(uint)Str[I]>127) + if (/*(uint)Ch<32 || */(uint)Ch>127) return false; } return true; @@ -249,6 +261,12 @@ int wcsicompc(const wchar *s1,const wchar *s2) // For path comparison. } +int wcsicompc(const std::wstring &s1,const std::wstring &s2) +{ + return wcsicompc(s1.c_str(),s2.c_str()); +} + + int wcsnicompc(const wchar *s1,const wchar *s2,size_t n) { #if defined(_UNIX) @@ -259,6 +277,12 @@ int wcsnicompc(const wchar *s1,const wchar *s2,size_t n) } +int wcsnicompc(const std::wstring &s1,const std::wstring &s2,size_t n) +{ + return wcsnicompc(s1.c_str(),s2.c_str(),n); +} + + // Safe copy: copies maxlen-1 max and for maxlen>0 returns zero terminated dest. void strncpyz(char *dest, const char *src, size_t maxlen) { @@ -383,88 +407,164 @@ void fmtitoa(int64 n,wchar *Str,size_t MaxSize) } -const wchar* GetWide(const char *Src) +std::wstring GetWide(const char *Src) { - const size_t MaxLength=NM; - static wchar StrTable[4][MaxLength]; - static uint StrNum=0; - if (++StrNum >= ASIZE(StrTable)) - StrNum=0; - wchar *Str=StrTable[StrNum]; - CharToWide(Src,Str,MaxLength); - Str[MaxLength-1]=0; + std::wstring Str; + CharToWide(Src,Str); return Str; } // Parse string containing parameters separated with spaces. -// Support quote marks. Param can be NULL to return the pointer to next -// parameter, which can be used to estimate the buffer size for Param. -const wchar* GetCmdParam(const wchar *CmdLine,wchar *Param,size_t MaxSize) +// Support quote marks. Accepts and updates the current position in the string. +// Returns false if there is nothing to parse. +bool GetCmdParam(const std::wstring &CmdLine,std::wstring::size_type &Pos,std::wstring &Param) { - while (IsSpace(*CmdLine)) - CmdLine++; - if (*CmdLine==0) - return NULL; + Param.clear(); + + while (IsSpace(CmdLine[Pos])) + Pos++; + if (Pos==CmdLine.size()) + return false; - size_t ParamSize=0; bool Quote=false; - while (*CmdLine!=0 && (Quote || !IsSpace(*CmdLine))) + while (Pos=0 || Msg.size()>MaxAllocSize) + break; + Msg.resize(Msg.size()*4); + } + std::wstring::size_type ZeroPos=Msg.find(L'\0'); + if (ZeroPos!=std::wstring::npos) + Msg.resize(ZeroPos); // Remove excessive zeroes at the end. + + return Msg; +} +#endif + + +#ifdef _WIN_ALL +bool ExpandEnvironmentStr(std::wstring &Str) +{ + DWORD ExpCode=ExpandEnvironmentStrings(Str.c_str(),nullptr,0); + if (ExpCode==0) + return false; + std::vector Buf(ExpCode); + ExpCode=ExpandEnvironmentStrings(Str.c_str(),Buf.data(),(DWORD)Buf.size()); + if (ExpCode==0 || ExpCode>Buf.size()) + return false; + Str=Buf.data(); + return true; } #endif + + +void TruncateAtZero(std::wstring &Str) +{ + std::wstring::size_type Pos=Str.find(L'\0'); + if (Pos!=std::wstring::npos) + Str.erase(Pos); +} + + +void ReplaceEsc(std::wstring &Str) +{ + std::wstring::size_type Pos=0; + while (true) + { + Pos=Str.find(L'\033',Pos); + if (Pos==std::wstring::npos) + break; + Str[Pos]=L'\''; + Str.insert(Pos+1,L"\\033'"); + Pos+=6; + } +} diff --git a/vendor/unrar/strfn.hpp b/vendor/unrar/strfn.hpp index 2a21feae0b..fd4793c574 100644 --- a/vendor/unrar/strfn.hpp +++ b/vendor/unrar/strfn.hpp @@ -3,16 +3,18 @@ const char* NullToEmpty(const char *Str); const wchar* NullToEmpty(const wchar *Str); -void IntToExt(const char *Src,char *Dest,size_t DestSize); +void IntToExt(const std::string &Src,std::string &Dest); enum ACTW_ENCODING { ACTW_DEFAULT, ACTW_OEM, ACTW_UTF8}; -void ArcCharToWide(const char *Src,wchar *Dest,size_t DestSize,ACTW_ENCODING Encoding); +void ArcCharToWide(const char *Src,std::wstring &Dest,ACTW_ENCODING Encoding); int stricomp(const char *s1,const char *s2); int strnicomp(const char *s1,const char *s2,size_t n); wchar* RemoveEOL(wchar *Str); +void RemoveEOL(std::wstring &Str); wchar* RemoveLF(wchar *Str); +void RemoveLF(std::wstring &Str); void strncpyz(char *dest, const char *src, size_t maxlen); void wcsncpyz(wchar *dest, const wchar *src, size_t maxlen); @@ -28,25 +30,36 @@ bool IsDigit(int ch); bool IsSpace(int ch); bool IsAlpha(int ch); -void BinToHex(const byte *Bin,size_t BinSize,char *Hex,wchar *HexW,size_t HexSize); +void BinToHex(const byte *Bin,size_t BinSize,std::wstring &Hex); #ifndef SFX_MODULE uint GetDigits(uint Number); #endif -bool LowAscii(const char *Str); -bool LowAscii(const wchar *Str); +bool LowAscii(const std::string &Str); +bool LowAscii(const std::wstring &Str); int wcsicompc(const wchar *s1,const wchar *s2); +int wcsicompc(const std::wstring &s1,const std::wstring &s2); int wcsnicompc(const wchar *s1,const wchar *s2,size_t n); +int wcsnicompc(const std::wstring &s1,const std::wstring &s2,size_t n); void itoa(int64 n,char *Str,size_t MaxSize); void itoa(int64 n,wchar *Str,size_t MaxSize); void fmtitoa(int64 n,wchar *Str,size_t MaxSize); -const wchar* GetWide(const char *Src); -const wchar* GetCmdParam(const wchar *CmdLine,wchar *Param,size_t MaxSize); +std::wstring GetWide(const char *Src); +bool GetCmdParam(const std::wstring &CmdLine,std::wstring::size_type &Pos,std::wstring &Param); #ifndef RARDLL -void PrintfPrepareFmt(const wchar *Org,wchar *Cvt,size_t MaxSize); +void PrintfPrepareFmt(const wchar *Org,std::wstring &Cvt); +std::wstring wstrprintf(const wchar *fmt,...); +std::wstring vwstrprintf(const wchar *fmt,va_list arglist); #endif +#ifdef _WIN_ALL +bool ExpandEnvironmentStr(std::wstring &Str); +#endif + +void TruncateAtZero(std::wstring &Str); +void ReplaceEsc(std::wstring &Str); + #endif diff --git a/vendor/unrar/strlist.cpp b/vendor/unrar/strlist.cpp index 50d69c7156..e76654fcd4 100644 --- a/vendor/unrar/strlist.cpp +++ b/vendor/unrar/strlist.cpp @@ -9,18 +9,20 @@ StringList::StringList() void StringList::Reset() { Rewind(); - StringData.Reset(); + StringData.clear(); StringsCount=0; SavePosNumber=0; } +/* void StringList::AddStringA(const char *Str) { - Array StrW(strlen(Str)); - CharToWide(Str,&StrW[0],StrW.Size()); - AddString(&StrW[0]); + std::wstring StrW; + CharToWide(Str,StrW); + AddString(StrW); } +*/ void StringList::AddString(const wchar *Str) @@ -28,22 +30,30 @@ void StringList::AddString(const wchar *Str) if (Str==NULL) Str=L""; - size_t PrevSize=StringData.Size(); - StringData.Add(wcslen(Str)+1); + size_t PrevSize=StringData.size(); + StringData.resize(PrevSize+wcslen(Str)+1); wcscpy(&StringData[PrevSize],Str); StringsCount++; } +void StringList::AddString(const std::wstring &Str) +{ + AddString(Str.c_str()); +} + + +/* bool StringList::GetStringA(char *Str,size_t MaxLength) { - Array StrW(MaxLength); - if (!GetString(&StrW[0],StrW.Size())) + std::wstring StrW; + if (!GetString(StrW)) return false; - WideToChar(&StrW[0],Str,MaxLength); + WideToChar(StrW.c_str(),Str,MaxLength); return true; } +*/ bool StringList::GetString(wchar *Str,size_t MaxLength) @@ -56,6 +66,16 @@ bool StringList::GetString(wchar *Str,size_t MaxLength) } +bool StringList::GetString(std::wstring &Str) +{ + wchar *StrPtr; + if (!GetString(&StrPtr)) + return false; + Str=StrPtr; + return true; +} + + #ifndef SFX_MODULE bool StringList::GetString(wchar *Str,size_t MaxLength,int StringNum) { @@ -71,6 +91,22 @@ bool StringList::GetString(wchar *Str,size_t MaxLength,int StringNum) RestorePosition(); return RetCode; } + + +bool StringList::GetString(std::wstring &Str,int StringNum) +{ + SavePosition(); + Rewind(); + bool RetCode=true; + while (StringNum-- >=0) + if (!GetString(Str)) + { + RetCode=false; + break; + } + RestorePosition(); + return RetCode; +} #endif @@ -84,7 +120,7 @@ wchar* StringList::GetString() bool StringList::GetString(wchar **Str) { - if (CurPos>=StringData.Size()) // No more strings left unprocessed. + if (CurPos>=StringData.size()) // No more strings left unprocessed. { if (Str!=NULL) *Str=NULL; @@ -107,7 +143,7 @@ void StringList::Rewind() #ifndef SFX_MODULE -bool StringList::Search(const wchar *Str,bool CaseSensitive) +bool StringList::Search(const std::wstring &Str,bool CaseSensitive) { SavePosition(); Rewind(); @@ -115,8 +151,8 @@ bool StringList::Search(const wchar *Str,bool CaseSensitive) wchar *CurStr; while (GetString(&CurStr)) { - if (Str!=NULL && CurStr!=NULL) - if ((CaseSensitive ? wcscmp(Str,CurStr):wcsicomp(Str,CurStr))!=0) + if (CurStr!=NULL) + if (CaseSensitive && Str!=CurStr || !CaseSensitive && wcsicomp(Str,CurStr)!=0) continue; Found=true; break; diff --git a/vendor/unrar/strlist.hpp b/vendor/unrar/strlist.hpp index 16a2cbb033..d89ba5c95c 100644 --- a/vendor/unrar/strlist.hpp +++ b/vendor/unrar/strlist.hpp @@ -4,7 +4,7 @@ class StringList { private: - Array StringData; + std::vector StringData; size_t CurPos; size_t StringsCount; @@ -13,17 +13,20 @@ class StringList public: StringList(); void Reset(); - void AddStringA(const char *Str); +// void AddStringA(const char *Str); void AddString(const wchar *Str); - bool GetStringA(char *Str,size_t MaxLength); + void AddString(const std::wstring &Str); +// bool GetStringA(char *Str,size_t MaxLength); bool GetString(wchar *Str,size_t MaxLength); + bool GetString(std::wstring &Str); bool GetString(wchar *Str,size_t MaxLength,int StringNum); + bool GetString(std::wstring &Str,int StringNum); wchar* GetString(); bool GetString(wchar **Str); void Rewind(); size_t ItemsCount() {return StringsCount;}; - size_t GetCharCount() {return StringData.Size();} - bool Search(const wchar *Str,bool CaseSensitive); + size_t GetCharCount() {return StringData.size();} + bool Search(const std::wstring &Str,bool CaseSensitive); void SavePosition(); void RestorePosition(); }; diff --git a/vendor/unrar/system.cpp b/vendor/unrar/system.cpp index 9e5362274f..cf9d1836e4 100644 --- a/vendor/unrar/system.cpp +++ b/vendor/unrar/system.cpp @@ -150,16 +150,18 @@ bool ShutdownCheckAnother(bool Open) + #if defined(_WIN_ALL) // Load library from Windows System32 folder. Use this function to prevent // loading a malicious code from current folder or same folder as exe. HMODULE WINAPI LoadSysLibrary(const wchar *Name) { - wchar SysDir[NM]; - if (GetSystemDirectory(SysDir,ASIZE(SysDir))==0) - return NULL; - MakeName(SysDir,Name,SysDir,ASIZE(SysDir)); - return LoadLibrary(SysDir); + std::vector SysDir(MAX_PATH); + if (GetSystemDirectory(SysDir.data(),(UINT)SysDir.size())==0) + return nullptr; + std::wstring FullName; + MakeName(SysDir.data(),Name,FullName); + return LoadLibrary(FullName.c_str()); } @@ -186,6 +188,7 @@ SSE_VERSION _SSE_Version=GetSSEVersion(); SSE_VERSION GetSSEVersion() { +#ifdef _MSC_VER int CPUInfo[4]; __cpuid(CPUInfo, 0); @@ -210,6 +213,18 @@ SSE_VERSION GetSSEVersion() if ((CPUInfo[3] & 0x2000000)!=0) return SSE_SSE; } +#elif defined(__GNUC__) + if (__builtin_cpu_supports("avx2")) + return SSE_AVX2; + if (__builtin_cpu_supports("sse4.1")) + return SSE_SSE41; + if (__builtin_cpu_supports("ssse3")) + return SSE_SSSE3; + if (__builtin_cpu_supports("sse2")) + return SSE_SSE2; + if (__builtin_cpu_supports("sse")) + return SSE_SSE; +#endif return SSE_NONE; } #endif diff --git a/vendor/unrar/system.hpp b/vendor/unrar/system.hpp index a56d6b7fcc..de4c14a6f6 100644 --- a/vendor/unrar/system.hpp +++ b/vendor/unrar/system.hpp @@ -21,7 +21,7 @@ void InitSystemOptions(int SleepTime); void SetPriority(int Priority); clock_t MonoClock(); void Wait(); -bool EmailFile(const wchar *FileName,const wchar *MailToW); +bool EmailFile(const std::wstring &FileName,std::wstring MailToW); void Shutdown(POWER_MODE Mode); bool ShutdownCheckAnother(bool Open); @@ -30,7 +30,6 @@ HMODULE WINAPI LoadSysLibrary(const wchar *Name); bool IsUserAdmin(); #endif - #ifdef USE_SSE enum SSE_VERSION {SSE_NONE,SSE_SSE,SSE_SSE2,SSE_SSSE3,SSE_SSE41,SSE_AVX2}; SSE_VERSION GetSSEVersion(); diff --git a/vendor/unrar/timefn.cpp b/vendor/unrar/timefn.cpp index 0abf49de97..aa90715da0 100644 --- a/vendor/unrar/timefn.cpp +++ b/vendor/unrar/timefn.cpp @@ -71,12 +71,12 @@ void RarTime::SetLocal(RarLocalTime *lt) { #ifdef _WIN_ALL SYSTEMTIME st; - st.wYear=lt->Year; - st.wMonth=lt->Month; - st.wDay=lt->Day; - st.wHour=lt->Hour; - st.wMinute=lt->Minute; - st.wSecond=lt->Second; + st.wYear=(WORD)lt->Year; + st.wMonth=(WORD)lt->Month; + st.wDay=(WORD)lt->Day; + st.wHour=(WORD)lt->Hour; + st.wMinute=(WORD)lt->Minute; + st.wSecond=(WORD)lt->Second; st.wMilliseconds=0; st.wDayOfWeek=0; FILETIME lft; @@ -183,8 +183,7 @@ void RarTime::SetUnix(time_t ut) // Get the high precision Unix time in nanoseconds since 01-01-1970. uint64 RarTime::GetUnixNS() { - // 11644473600000000000 - number of ns between 01-01-1601 and 01-01-1970. - uint64 ushift=INT32TO64(0xA1997B0B,0x4C6A0000); + const uint64 ushift=11644473600000000000ULL; // ns between 01-01-1601 and 01-01-1970. return itime*(1000000000/TICKS_PER_SECOND)-ushift; } @@ -192,8 +191,7 @@ uint64 RarTime::GetUnixNS() // Set the high precision Unix time in nanoseconds since 01-01-1970. void RarTime::SetUnixNS(uint64 ns) { - // 11644473600000000000 - number of ns between 01-01-1601 and 01-01-1970. - uint64 ushift=INT32TO64(0xA1997B0B,0x4C6A0000); + const uint64 ushift=11644473600000000000ULL; // ns between 01-01-1601 and 01-01-1970. itime=(ns+ushift)/(1000000000/TICKS_PER_SECOND); } @@ -327,14 +325,14 @@ void RarTime::Adjust(int64 ns) #ifndef SFX_MODULE -const wchar *GetMonthName(int Month) +const wchar *GetMonthName(uint Month) { return uiGetMonthName(Month); } #endif -bool IsLeapYear(int Year) +bool IsLeapYear(uint Year) { return (Year&3)==0 && (Year%100!=0 || Year%400==0); } diff --git a/vendor/unrar/timefn.hpp b/vendor/unrar/timefn.hpp index 49b61e85d6..6c265ec02b 100644 --- a/vendor/unrar/timefn.hpp +++ b/vendor/unrar/timefn.hpp @@ -70,7 +70,7 @@ class RarTime void Adjust(int64 ns); }; -const wchar *GetMonthName(int Month); -bool IsLeapYear(int Year); +const wchar *GetMonthName(uint Month); +bool IsLeapYear(uint Year); #endif diff --git a/vendor/unrar/ui.hpp b/vendor/unrar/ui.hpp index 5def26df18..f37001bec9 100644 --- a/vendor/unrar/ui.hpp +++ b/vendor/unrar/ui.hpp @@ -19,8 +19,8 @@ enum UIMESSAGE_CODE { UIERROR_SUBHEADERBROKEN, UIERROR_SUBHEADERUNKNOWN, UIERROR_SUBHEADERDATABROKEN, UIERROR_RRDAMAGED, UIERROR_UNKNOWNMETHOD, UIERROR_UNKNOWNENCMETHOD, UIERROR_RENAMING, UIERROR_NEWERRAR, - UIERROR_NOTSFX, UIERROR_OLDTOSFX, - UIERROR_WRONGSFXVER, UIERROR_HEADENCMISMATCH, UIERROR_DICTOUTMEM, + UIERROR_NOTSFX, UIERROR_OLDTOSFX,UIERROR_WRONGSFXVER, + UIERROR_HEADENCMISMATCH, UIERROR_DICTOUTMEM,UIERROR_EXTRDICTOUTMEM, UIERROR_USESMALLERDICT, UIERROR_MODIFYUNKNOWN, UIERROR_MODIFYOLD, UIERROR_MODIFYLOCKED, UIERROR_MODIFYVOLUME, UIERROR_NOTVOLUME, UIERROR_NOTFIRSTVOLUME, UIERROR_RECVOLLIMIT, UIERROR_RECVOLDIFFSETS, @@ -32,14 +32,15 @@ enum UIMESSAGE_CODE { UIERROR_NOFILESTOADD, UIERROR_NOFILESTODELETE, UIERROR_NOFILESTOEXTRACT, UIERROR_MISSINGVOL, UIERROR_NEEDPREVVOL, UIERROR_UNKNOWNEXTRA, UIERROR_CORRUPTEXTRA, UIERROR_NTFSREQUIRED, UIERROR_ZIPVOLSFX, - UIERROR_FILERO, UIERROR_TOOLARGESFX, UIERROR_NOZIPSFX, UIERROR_EMAIL, - UIERROR_ACLGET, UIERROR_ACLBROKEN, UIERROR_ACLUNKNOWN, UIERROR_ACLSET, - UIERROR_STREAMBROKEN, UIERROR_STREAMUNKNOWN, UIERROR_INCOMPATSWITCH, - UIERROR_PATHTOOLONG, UIERROR_DIRSCAN, UIERROR_UOWNERGET, - UIERROR_UOWNERBROKEN, UIERROR_UOWNERGETOWNERID, UIERROR_UOWNERGETGROUPID, - UIERROR_UOWNERSET, UIERROR_ULINKREAD, UIERROR_ULINKEXIST, - UIERROR_OPENPRESERVEATIME, UIERROR_READERRTRUNCATED, UIERROR_READERRCOUNT, - UIERROR_DIRNAMEEXISTS,UIERROR_TRUNCPSW,UIERROR_ADJUSTVALUE, + UIERROR_FILERO, UIERROR_TOOLARGESFX, UIERROR_NOZIPSFX, UIERROR_NEEEDSFX64, + UIERROR_EMAIL, UIERROR_ACLGET, UIERROR_ACLBROKEN, UIERROR_ACLUNKNOWN, + UIERROR_ACLSET, UIERROR_STREAMBROKEN, UIERROR_STREAMUNKNOWN, + UIERROR_INCOMPATSWITCH, UIERROR_PATHTOOLONG, UIERROR_DIRSCAN, + UIERROR_UOWNERGET, UIERROR_UOWNERBROKEN, UIERROR_UOWNERGETOWNERID, + UIERROR_UOWNERGETGROUPID, UIERROR_UOWNERSET, UIERROR_ULINKREAD, + UIERROR_ULINKEXIST, UIERROR_OPENPRESERVEATIME, UIERROR_READERRTRUNCATED, + UIERROR_READERRCOUNT, UIERROR_DIRNAMEEXISTS,UIERROR_TRUNCPSW, + UIERROR_ADJUSTVALUE, UIERROR_SKIPUNSAFELINK, UIMSG_FIRST, UIMSG_STRING, UIMSG_BUILD, UIMSG_RRSEARCH, UIMSG_ANALYZEFILEDATA, @@ -76,19 +77,25 @@ enum UIASKREP_RESULT { UIASKREP_R_RENAME,UIASKREP_R_RENAMEAUTO,UIASKREP_R_CANCEL,UIASKREP_R_UNUSED }; -UIASKREP_RESULT uiAskReplace(wchar *Name,size_t MaxNameSize,int64 FileSize,RarTime *FileTime,uint Flags); -UIASKREP_RESULT uiAskReplaceEx(CommandData *Cmd,wchar *Name,size_t MaxNameSize,int64 FileSize,RarTime *FileTime,uint Flags); +UIASKREP_RESULT uiAskReplace(std::wstring &Name,int64 FileSize,RarTime *FileTime,uint Flags); +UIASKREP_RESULT uiAskReplaceEx(CommandData *Cmd,std::wstring &Name,int64 FileSize,RarTime *FileTime,uint Flags); void uiInit(SOUND_NOTIFY_MODE Sound); -void uiStartArchiveExtract(bool Extract,const wchar *ArcName); -bool uiStartFileExtract(const wchar *FileName,bool Extract,bool Test,bool Skip); +void uiStartArchiveExtract(bool Extract,const std::wstring &ArcName); +bool uiStartFileExtract(const std::wstring &FileName,bool Extract,bool Test,bool Skip); void uiExtractProgress(int64 CurFileSize,int64 TotalFileSize,int64 CurSize,int64 TotalSize); void uiProcessProgress(const char *Command,int64 CurSize,int64 TotalSize); -enum UIPASSWORD_TYPE {UIPASSWORD_GLOBAL,UIPASSWORD_FILE,UIPASSWORD_ARCHIVE}; -bool uiGetPassword(UIPASSWORD_TYPE Type,const wchar *FileName,SecPassword *Password,CheckPassword *CheckPwd); +enum UIPASSWORD_TYPE +{ + UIPASSWORD_GLOBAL, // For -p, -hp without parameter or Ctrl+P in WinRAR. + UIPASSWORD_FILE, // Extracting an encrypted file. + UIPASSWORD_ARCHIVE, // Extracting or opening an encrypted header archive. +}; + +bool uiGetPassword(UIPASSWORD_TYPE Type,const std::wstring &FileName,SecPassword *Password,CheckPassword *CheckPwd); bool uiIsGlobalPasswordSet(); enum UIALARM_TYPE {UIALARM_ERROR, UIALARM_INFO, UIALARM_QUESTION}; @@ -96,14 +103,16 @@ void uiAlarm(UIALARM_TYPE Type); void uiEolAfterMsg(); -bool uiAskNextVolume(wchar *VolName,size_t MaxSize); +bool uiAskNextVolume(std::wstring &VolName); #if !defined(SILENT) && !defined(SFX_MODULE) -void uiAskRepeatRead(const wchar *FileName,bool &Ignore,bool &All,bool &Retry,bool &Quit); +void uiAskRepeatRead(const std::wstring &FileName,bool &Ignore,bool &All,bool &Retry,bool &Quit); #endif -bool uiAskRepeatWrite(const wchar *FileName,bool DiskFull); +bool uiAskRepeatWrite(const std::wstring &FileName,bool DiskFull); + +bool uiDictLimit(CommandData *Cmd,const std::wstring &FileName,uint64 DictSize,uint64 MaxDictSize); #ifndef SFX_MODULE -const wchar *uiGetMonthName(int Month); +const wchar *uiGetMonthName(uint Month); #endif class uiMsgStore @@ -131,6 +140,12 @@ class uiMsgStore Str[StrSize++]=s; return *this; } + uiMsgStore& operator << (const std::wstring &s) + { + if (StrSizeOverwrite==OVERWRITE_NONE) return UIASKREP_R_SKIP; #if !defined(SFX_MODULE) && !defined(SILENT) // Must be before Cmd->AllYes check or -y switch would override -or. - if (Cmd->Overwrite==OVERWRITE_AUTORENAME && GetAutoRenamedName(Name,MaxNameSize)) + if (Cmd->Overwrite==OVERWRITE_AUTORENAME && GetAutoRenamedName(Name)) return UIASKREP_R_REPLACE; #endif - // This check must be after OVERWRITE_AUTORENAME processing or -y switch - // would override -or. - if (Cmd->AllYes || Cmd->Overwrite==OVERWRITE_ALL) - { - PrepareToDelete(Name); - return UIASKREP_R_REPLACE; - } - - wchar NewName[NM]; - wcsncpyz(NewName,Name,ASIZE(NewName)); - UIASKREP_RESULT Choice=uiAskReplace(NewName,ASIZE(NewName),FileSize,FileTime,Flags); + std::wstring NewName=Name; + UIASKREP_RESULT Choice=Cmd->AllYes || Cmd->Overwrite==OVERWRITE_ALL ? + UIASKREP_R_REPLACE : uiAskReplace(NewName,FileSize,FileTime,Flags); if (Choice==UIASKREP_R_REPLACE || Choice==UIASKREP_R_REPLACEALL) + { PrepareToDelete(Name); + // Overwrite the link itself instead of its target. + // For normal files we prefer to inherit file attributes, permissions + // and hard links. + FindData FD; + if (FindFile::FastFind(Name,&FD,true) && FD.IsLink) + DelFile(Name); + } + if (Choice==UIASKREP_R_REPLACEALL) { Cmd->Overwrite=OVERWRITE_ALL; @@ -46,16 +48,16 @@ UIASKREP_RESULT uiAskReplaceEx(CommandData *Cmd,wchar *Name,size_t MaxNameSize,i } if (Choice==UIASKREP_R_RENAME) { - if (PointToName(NewName)==NewName) - SetName(Name,NewName,MaxNameSize); + if (GetNamePos(NewName)==0) + SetName(Name,NewName); else - wcsncpyz(Name,NewName,MaxNameSize); + Name=NewName; if (FileExist(Name)) - return uiAskReplaceEx(Cmd,Name,MaxNameSize,FileSize,FileTime,Flags); + return uiAskReplaceEx(Cmd,Name,FileSize,FileTime,Flags); return UIASKREP_R_REPLACE; } #if !defined(SFX_MODULE) && !defined(SILENT) - if (Choice==UIASKREP_R_RENAMEAUTO && GetAutoRenamedName(Name,MaxNameSize)) + if (Choice==UIASKREP_R_RENAMEAUTO && GetAutoRenamedName(Name)) { Cmd->Overwrite=OVERWRITE_AUTORENAME; return UIASKREP_R_REPLACE; @@ -63,3 +65,23 @@ UIASKREP_RESULT uiAskReplaceEx(CommandData *Cmd,wchar *Name,size_t MaxNameSize,i #endif return Choice; } + + +bool GetAutoRenamedName(std::wstring &Name) +{ + std::wstring Ext=GetExt(Name); + for (uint FileVer=1;FileVer<1000000;FileVer++) + { + std::wstring NewName=Name; + RemoveExt(NewName); + wchar Ver[10]; + itoa(FileVer,Ver,ASIZE(Ver)); + NewName = NewName + L"(" + Ver + L")" + Ext; + if (!FileExist(NewName)) + { + Name=NewName; + return true; + } + } + return false; +} diff --git a/vendor/unrar/uiconsole.cpp b/vendor/unrar/uiconsole.cpp index b524c25ff4..cc1c72d6db 100644 --- a/vendor/unrar/uiconsole.cpp +++ b/vendor/unrar/uiconsole.cpp @@ -1,12 +1,11 @@ static bool AnyMessageDisplayed=false; // For console -idn switch. // Purely user interface function. Gets and returns user input. -UIASKREP_RESULT uiAskReplace(wchar *Name,size_t MaxNameSize,int64 FileSize,RarTime *FileTime,uint Flags) +UIASKREP_RESULT uiAskReplace(std::wstring &Name,int64 FileSize,RarTime *FileTime,uint Flags) { wchar SizeText1[20],DateStr1[50],SizeText2[20],DateStr2[50]; - FindData ExistingFD; - memset(&ExistingFD,0,sizeof(ExistingFD)); // In case find fails. + FindData ExistingFD={}; // Init in case find fails. FindFile::FastFind(Name,&ExistingFD); itoa(ExistingFD.Size,SizeText1,ASIZE(SizeText1)); ExistingFD.mtime.GetText(DateStr1,ASIZE(DateStr1),false); @@ -14,16 +13,16 @@ UIASKREP_RESULT uiAskReplace(wchar *Name,size_t MaxNameSize,int64 FileSize,RarTi if (FileSize==INT64NDF || FileTime==NULL) { eprintf(L"\n"); - eprintf(St(MAskOverwrite),Name); + eprintf(St(MAskOverwrite),Name.c_str()); } else { itoa(FileSize,SizeText2,ASIZE(SizeText2)); FileTime->GetText(DateStr2,ASIZE(DateStr2),false); if ((Flags & UIASKREP_F_EXCHSRCDEST)==0) - eprintf(St(MAskReplace),Name,SizeText1,DateStr1,SizeText2,DateStr2); + eprintf(St(MAskReplace),Name.c_str(),SizeText1,DateStr1,SizeText2,DateStr2); else - eprintf(St(MAskReplace),Name,SizeText2,DateStr2,SizeText1,DateStr1); + eprintf(St(MAskReplace),Name.c_str(),SizeText2,DateStr2,SizeText1,DateStr1); } bool AllowRename=(Flags & UIASKREP_F_NORENAME)==0; @@ -46,7 +45,7 @@ UIASKREP_RESULT uiAskReplace(wchar *Name,size_t MaxNameSize,int64 FileSize,RarTi if (AllowRename && Choice==5) { mprintf(St(MAskNewName)); - if (getwstr(Name,MaxNameSize)) + if (getwstr(Name)) return UIASKREP_R_RENAME; else return UIASKREP_R_SKIP; // Process fwgets failure as if user answered 'No'. @@ -57,13 +56,13 @@ UIASKREP_RESULT uiAskReplace(wchar *Name,size_t MaxNameSize,int64 FileSize,RarTi -void uiStartArchiveExtract(bool Extract,const wchar *ArcName) +void uiStartArchiveExtract(bool Extract,const std::wstring &ArcName) { - mprintf(St(Extract ? MExtracting : MExtrTest), ArcName); + mprintf(St(Extract ? MExtracting : MExtrTest), ArcName.c_str()); } -bool uiStartFileExtract(const wchar *FileName,bool Extract,bool Test,bool Skip) +bool uiStartFileExtract(const std::wstring &FileName,bool Extract,bool Test,bool Skip) { return true; } @@ -237,6 +236,12 @@ void uiMsgStore::Msg() case UIERROR_RECVOLCANNOTFIX: mprintf(St(MRecVolCannotFix)); break; + case UIERROR_EXTRDICTOUTMEM: + Log(Str[0],St(MExtrDictOutMem),Num[0]); +#ifdef _WIN_32 + Log(Str[0],St(MSuggest64bit)); +#endif + break; case UIERROR_UNEXPEOF: Log(Str[0],St(MLogUnexpEOF)); break; @@ -344,6 +349,9 @@ void uiMsgStore::Msg() case UIERROR_ADJUSTVALUE: Log(NULL,St(MAdjustValue),Str[0],Str[1]); break; + case UIERROR_SKIPUNSAFELINK: + Log(NULL,St(MSkipUnsafeLink),Str[0],Str[1]); + break; #ifndef SFX_MODULE case UIMSG_STRING: @@ -389,7 +397,6 @@ void uiMsgStore::Msg() break; - case UIEVENT_RRTESTINGSTART: mprintf(L"%s ",St(MTestingRR)); break; @@ -397,7 +404,7 @@ void uiMsgStore::Msg() } -bool uiGetPassword(UIPASSWORD_TYPE Type,const wchar *FileName, +bool uiGetPassword(UIPASSWORD_TYPE Type,const std::wstring &FileName, SecPassword *Password,CheckPassword *CheckPwd) { // Unlike GUI we cannot provide Cancel button here, so we use the empty @@ -433,14 +440,14 @@ void uiAlarm(UIALARM_TYPE Type) -bool uiAskNextVolume(wchar *VolName,size_t MaxSize) +bool uiAskNextVolume(std::wstring &VolName) { - eprintf(St(MAskNextVol),VolName); + eprintf(St(MAskNextVol),VolName.c_str()); return Ask(St(MContinueQuit))!=2; } -void uiAskRepeatRead(const wchar *FileName,bool &Ignore,bool &All,bool &Retry,bool &Quit) +void uiAskRepeatRead(const std::wstring &FileName,bool &Ignore,bool &All,bool &Retry,bool &Quit) { eprintf(St(MErrReadInfo)); int Code=Ask(St(MIgnoreAllRetryQuit)); @@ -452,16 +459,37 @@ void uiAskRepeatRead(const wchar *FileName,bool &Ignore,bool &All,bool &Retry,bo } -bool uiAskRepeatWrite(const wchar *FileName,bool DiskFull) +bool uiAskRepeatWrite(const std::wstring &FileName,bool DiskFull) { mprintf(L"\n"); - Log(NULL,St(DiskFull ? MNotEnoughDisk:MErrWrite),FileName); + Log(NULL,St(DiskFull ? MNotEnoughDisk:MErrWrite),FileName.c_str()); return Ask(St(MRetryAbort))==1; } +bool uiDictLimit(CommandData *Cmd,const std::wstring &FileName,uint64 DictSize,uint64 MaxDictSize) +{ + mprintf(L"\n%s",FileName.c_str()); + const uint64 GB=1024*1024*1024; // We display sizes in GB here. + + // Include the reminder for switches like -md6400m. + DictSize=DictSize/GB+(DictSize%GB!=0 ? 1:0); + + // Exclude reminder for in case it is less than archive dictionary size, + // but still more than nearest GB value. Otherwise we could have message + // like "7 GB dictionary exceeds 7 GB limit", where first 7 might be actually + // 6272 MB and second is 6400 MB. + MaxDictSize/=GB; + + mprintf(St(MDictNotAllowed),(uint)DictSize,(uint)MaxDictSize,(uint)DictSize); + mprintf(St(MDictExtrAnyway),(uint)DictSize,(uint)DictSize); + mprintf(L"\n"); + return false; // Stop extracting. +} + + #ifndef SFX_MODULE -const wchar *uiGetMonthName(int Month) +const wchar *uiGetMonthName(uint Month) { static MSGID MonthID[12]={ MMonthJan,MMonthFeb,MMonthMar,MMonthApr,MMonthMay,MMonthJun, diff --git a/vendor/unrar/uisilent.cpp b/vendor/unrar/uisilent.cpp index 8155885746..806e468181 100644 --- a/vendor/unrar/uisilent.cpp +++ b/vendor/unrar/uisilent.cpp @@ -1,5 +1,5 @@ // Purely user interface function. Gets and returns user input. -UIASKREP_RESULT uiAskReplace(wchar *Name,size_t MaxNameSize,int64 FileSize,RarTime *FileTime,uint Flags) +UIASKREP_RESULT uiAskReplace(std::wstring &Name,int64 FileSize,RarTime *FileTime,uint Flags) { return UIASKREP_R_REPLACE; } @@ -7,12 +7,12 @@ UIASKREP_RESULT uiAskReplace(wchar *Name,size_t MaxNameSize,int64 FileSize,RarTi -void uiStartArchiveExtract(bool Extract,const wchar *ArcName) +void uiStartArchiveExtract(bool Extract,const std::wstring &ArcName) { } -bool uiStartFileExtract(const wchar *FileName,bool Extract,bool Test,bool Skip) +bool uiStartFileExtract(const std::wstring &FileName,bool Extract,bool Test,bool Skip) { return true; } @@ -33,7 +33,7 @@ void uiMsgStore::Msg() } -bool uiGetPassword(UIPASSWORD_TYPE Type,const wchar *FileName, +bool uiGetPassword(UIPASSWORD_TYPE Type,const std::wstring &FileName, SecPassword *Password,CheckPassword *CheckPwd) { return false; @@ -62,8 +62,19 @@ void uiGiveTick() } +bool uiDictLimit(CommandData *Cmd,const std::wstring &FileName,uint64 DictSize,uint64 MaxDictSize) +{ +#ifdef RARDLL + if (Cmd->Callback!=nullptr && + Cmd->Callback(UCM_LARGEDICT,Cmd->UserData,(LPARAM)(DictSize/1024),(LPARAM)(MaxDictSize/1024))==1) + return true; // Continue extracting if unrar.dll callback permits it. +#endif + return false; // Stop extracting. +} + + #ifndef SFX_MODULE -const wchar *uiGetMonthName(int Month) +const wchar *uiGetMonthName(uint Month) { return L""; } diff --git a/vendor/unrar/ulinks.cpp b/vendor/unrar/ulinks.cpp index 141a97fecc..ea841557c0 100644 --- a/vendor/unrar/ulinks.cpp +++ b/vendor/unrar/ulinks.cpp @@ -1,6 +1,6 @@ -static bool UnixSymlink(CommandData *Cmd,const char *Target,const wchar *LinkName,RarTime *ftm,RarTime *fta) +static bool UnixSymlink(CommandData *Cmd,const std::string &Target,const wchar *LinkName,RarTime *ftm,RarTime *fta) { CreatePath(LinkName,true,Cmd->DisableNames); @@ -9,15 +9,15 @@ static bool UnixSymlink(CommandData *Cmd,const char *Target,const wchar *LinkNam // called earlier inside of uiAskReplaceEx. DelFile(LinkName); - char LinkNameA[NM]; - WideToChar(LinkName,LinkNameA,ASIZE(LinkNameA)); - if (symlink(Target,LinkNameA)==-1) // Error. + std::string LinkNameA; + WideToChar(LinkName,LinkNameA); + if (symlink(Target.c_str(),LinkNameA.c_str())==-1) // Error. { if (errno==EEXIST) uiMsg(UIERROR_ULINKEXIST,LinkName); else { - uiMsg(UIERROR_SLINKCREATE,UINULL,LinkName); + uiMsg(UIERROR_SLINKCREATE,L"",LinkName); ErrHandler.SetErrorCode(RARX_WARNING); } return false; @@ -29,14 +29,14 @@ static bool UnixSymlink(CommandData *Cmd,const char *Target,const wchar *LinkNam times[0].tv_nsec=fta->IsSet() ? long(fta->GetUnixNS()%1000000000) : UTIME_NOW; times[1].tv_sec=ftm->GetUnix(); times[1].tv_nsec=ftm->IsSet() ? long(ftm->GetUnixNS()%1000000000) : UTIME_NOW; - utimensat(AT_FDCWD,LinkNameA,times,AT_SYMLINK_NOFOLLOW); + utimensat(AT_FDCWD,LinkNameA.c_str(),times,AT_SYMLINK_NOFOLLOW); #else struct timeval tv[2]; tv[0].tv_sec=fta->GetUnix(); tv[0].tv_usec=long(fta->GetUnixNS()%1000000000/1000); tv[1].tv_sec=ftm->GetUnix(); tv[1].tv_usec=long(ftm->GetUnixNS()%1000000000/1000); - lutimes(LinkNameA,tv); + lutimes(LinkNameA.c_str(),tv); #endif #endif @@ -55,9 +55,9 @@ static bool IsFullPath(const char *PathA) // Unix ASCII version. // it didn't affect the number of path related characters we analyze // in IsRelativeSymlinkSafe later. // This check is likely to be excessive, but let's keep it anyway. -static bool SafeCharToWide(const char *Src,wchar *Dest,size_t DestSize) +static bool SafeCharToWide(const std::string &Src,std::wstring &Dest) { - if (!CharToWide(Src,Dest,DestSize) || *Dest==0) + if (!CharToWide(Src,Dest) || Dest.empty()) return false; uint SrcChars=0,DestChars=0; for (uint I=0;Src[I]!=0;I++) @@ -73,18 +73,18 @@ static bool SafeCharToWide(const char *Src,wchar *Dest,size_t DestSize) static bool ExtractUnixLink30(CommandData *Cmd,ComprDataIO &DataIO,Archive &Arc, const wchar *LinkName,bool &UpLink) { - char Target[NM]; if (IsLink(Arc.FileHead.FileAttr)) { size_t DataSize=(size_t)Arc.FileHead.PackSize; - if (DataSize>ASIZE(Target)-1) + if (DataSize>MAXPATHSIZE) return false; - if ((size_t)DataIO.UnpRead((byte *)Target,DataSize)!=DataSize) + std::vector TargetBuf(DataSize+1); + if ((size_t)DataIO.UnpRead((byte*)TargetBuf.data(),DataSize)!=DataSize) return false; - Target[DataSize]=0; + std::string Target(TargetBuf.data(),TargetBuf.size()); DataIO.UnpHash.Init(Arc.FileHead.FileHash.Type,1); - DataIO.UnpHash.Update(Target,strlen(Target)); + DataIO.UnpHash.Update(Target.data(),strlen(Target.data())); DataIO.UnpHash.Result(&Arc.FileHead.FileHash); // Return true in case of bad checksum, so link will be processed further @@ -92,16 +92,21 @@ static bool ExtractUnixLink30(CommandData *Cmd,ComprDataIO &DataIO,Archive &Arc, if (!DataIO.UnpHash.Cmp(&Arc.FileHead.FileHash,Arc.FileHead.UseHashKey ? Arc.FileHead.HashKey:NULL)) return true; - wchar TargetW[NM]; - if (!SafeCharToWide(Target,TargetW,ASIZE(TargetW))) + std::wstring TargetW; + if (!SafeCharToWide(Target.data(),TargetW)) return false; + TruncateAtZero(TargetW); // Use Arc.FileHead.FileName instead of LinkName, since LinkName // can include the destination path as a prefix, which can // confuse IsRelativeSymlinkSafe algorithm. if (!Cmd->AbsoluteLinks && (IsFullPath(TargetW) || - !IsRelativeSymlinkSafe(Cmd,Arc.FileHead.FileName,LinkName,TargetW))) + !IsRelativeSymlinkSafe(Cmd,Arc.FileHead.FileName.c_str(),LinkName,TargetW.c_str()))) + { + uiMsg(UIERROR_SKIPUNSAFELINK,Arc.FileHead.FileName,TargetW); + ErrHandler.SetErrorCode(RARX_WARNING); return false; - UpLink=strstr(Target,"..")!=NULL; + } + UpLink=Target.find("..")!=std::string::npos; return UnixSymlink(Cmd,Target,LinkName,&Arc.FileHead.mtime,&Arc.FileHead.atime); } return false; @@ -110,27 +115,36 @@ static bool ExtractUnixLink30(CommandData *Cmd,ComprDataIO &DataIO,Archive &Arc, static bool ExtractUnixLink50(CommandData *Cmd,const wchar *Name,FileHeader *hd) { - char Target[NM]; - WideToChar(hd->RedirName,Target,ASIZE(Target)); + std::string Target; + WideToChar(hd->RedirName,Target); if (hd->RedirType==FSREDIR_WINSYMLINK || hd->RedirType==FSREDIR_JUNCTION) { // Cannot create Windows absolute path symlinks in Unix. Only relative path // Windows symlinks can be created here. RAR 5.0 used \??\ prefix // for Windows absolute symlinks, since RAR 5.1 /??/ is used. // We escape ? as \? to avoid "trigraph" warning - if (strncmp(Target,"\\??\\",4)==0 || strncmp(Target,"/\?\?/",4)==0) + if (Target.rfind("\\??\\",0)!=std::string::npos || + Target.rfind("/\?\?/",0)!=std::string::npos) + { + uiMsg(UIERROR_SLINKCREATE,nullptr,L"\"" + hd->FileName + L"\" -> \"" + hd->RedirName + L"\""); + ErrHandler.SetErrorCode(RARX_WARNING); return false; - DosSlashToUnix(Target,Target,ASIZE(Target)); + } + DosSlashToUnix(Target,Target); } - wchar TargetW[NM]; - if (!SafeCharToWide(Target,TargetW,ASIZE(TargetW))) + std::wstring TargetW; + if (!SafeCharToWide(Target,TargetW)) return false; // Use hd->FileName instead of LinkName, since LinkName can include // the destination path as a prefix, which can confuse // IsRelativeSymlinkSafe algorithm. if (!Cmd->AbsoluteLinks && (IsFullPath(TargetW) || - !IsRelativeSymlinkSafe(Cmd,hd->FileName,Name,TargetW))) + !IsRelativeSymlinkSafe(Cmd,hd->FileName.c_str(),Name,TargetW.c_str()))) + { + uiMsg(UIERROR_SKIPUNSAFELINK,hd->FileName,TargetW); + ErrHandler.SetErrorCode(RARX_WARNING); return false; + } return UnixSymlink(Cmd,Target,Name,&hd->mtime,&hd->atime); } diff --git a/vendor/unrar/unicode.cpp b/vendor/unrar/unicode.cpp index 73b09bb220..812e35ba88 100644 --- a/vendor/unrar/unicode.cpp +++ b/vendor/unrar/unicode.cpp @@ -128,6 +128,26 @@ bool CharToWide(const char *Src,wchar *Dest,size_t DestSize) } +bool WideToChar(const std::wstring &Src,std::string &Dest) +{ + // We need more than 1 char per wchar_t for DBCS and up to 4 for UTF-8. + std::vector DestA(4*Src.size()+1); // "+1" for terminating zero. + bool Result=WideToChar(Src.c_str(),DestA.data(),DestA.size()); + Dest=DestA.data(); + return Result; +} + + +bool CharToWide(const std::string &Src,std::wstring &Dest) +{ + // 2 wchar_t per char in case char is converted to UTF-16 surrogate pair. + std::vector DestW(2*Src.size()+1); // "+1" for terminating zero. + bool Result=CharToWide(Src.c_str(),DestW.data(),DestW.size()); + Dest=DestW.data(); + return Result; +} + + #if defined(_UNIX) && defined(MBFUNCTIONS) // Convert and restore mapped inconvertible Unicode characters. // We use it for extended ASCII names in Unix. @@ -244,6 +264,19 @@ byte* WideToRaw(const wchar *Src,size_t SrcSize,byte *Dest,size_t DestSize) } +// Store UTF-16 raw byte stream. +void WideToRaw(const std::wstring &Src,std::vector &Dest) +{ + for (wchar C : Src) + { + Dest.push_back((byte)C); + Dest.push_back((byte)(C>>8)); + } + Dest.push_back(0); // 2 bytes of trailing UTF-16 zero. + Dest.push_back(0); +} + + wchar* RawToWide(const byte *Src,wchar *Dest,size_t DestSize) { for (size_t I=0;I &Src) +{ + std::wstring Dest; + for (size_t I=0;I+1>6)); + Dest.push_back(0x80|(c&0x3f)); + } + else + { + if (c>=0xd800 && c<=0xdbff && I=0xdc00 && Src[I]<=0xdfff) // Surrogate pair. + { + c=((c-0xd800)<<10)+(Src[I]-0xdc00)+0x10000; + I++; + } + if (c<0x10000) + { + Dest.push_back(0xe0|(c>>12)); + Dest.push_back(0x80|((c>>6)&0x3f)); + Dest.push_back(0x80|(c&0x3f)); + } + else + if (c < 0x200000) + { + Dest.push_back(0xf0|(c>>18)); + Dest.push_back(0x80|((c>>12)&0x3f)); + Dest.push_back(0x80|((c>>6)&0x3f)); + Dest.push_back(0x80|(c&0x3f)); + } + } + } +} + + + size_t WideToUtfSize(const wchar *Src) { size_t Size=0; @@ -397,6 +484,146 @@ bool UtfToWide(const char *Src,wchar *Dest,size_t DestSize) } +bool UtfToWide(const char *Src,std::wstring &Dest) +{ + bool Success=true; + Dest.clear(); + while (*Src!=0) + { + uint c=byte(*(Src++)),d; + if (c<0x80) + d=c; + else + if ((c>>5)==6) + { + if ((*Src&0xc0)!=0x80) + { + Success=false; + break; + } + d=((c&0x1f)<<6)|(*Src&0x3f); + Src++; + } + else + if ((c>>4)==14) + { + if ((Src[0]&0xc0)!=0x80 || (Src[1]&0xc0)!=0x80) + { + Success=false; + break; + } + d=((c&0xf)<<12)|((Src[0]&0x3f)<<6)|(Src[1]&0x3f); + Src+=2; + } + else + if ((c>>3)==30) + { + if ((Src[0]&0xc0)!=0x80 || (Src[1]&0xc0)!=0x80 || (Src[2]&0xc0)!=0x80) + { + Success=false; + break; + } + d=((c&7)<<18)|((Src[0]&0x3f)<<12)|((Src[1]&0x3f)<<6)|(Src[2]&0x3f); + Src+=3; + } + else + { + Success=false; + break; + } + if (d>0xffff) + { + if (d>0x10ffff) // UTF-8 must end at 0x10ffff according to RFC 3629. + { + Success=false; + continue; + } + if (sizeof(wchar_t)==2) // Use the surrogate pair. + { + Dest.push_back( ((d-0x10000)>>10)+0xd800 ); + Dest.push_back( (d&0x3ff)+0xdc00 ); + } + else + Dest.push_back( d ); + } + else + Dest.push_back( d ); + } + return Success; +} + + +/* +bool UtfToWide(const std::vector &Src,std::wstring &Dest) +{ + bool Success=true; + Dest.clear(); + for (size_t I=0;I>5)==6) + { + if (Src.size()-I<1 || (Src[I]&0xc0)!=0x80) + { + Success=false; + break; + } + d=((c&0x1f)<<6)|(Src[I]&0x3f); + I++; + } + else + if ((c>>4)==14) + { + if (Src.size()-I<2 || (Src[I]&0xc0)!=0x80 || (Src[I+1]&0xc0)!=0x80) + { + Success=false; + break; + } + d=((c&0xf)<<12)|((Src[I]&0x3f)<<6)|(Src[I+1]&0x3f); + I+=2; + } + else + if ((c>>3)==30) + { + if (Src.size()-I<3 || (Src[I]&0xc0)!=0x80 || (Src[I+1]&0xc0)!=0x80 || (Src[I+2]&0xc0)!=0x80) + { + Success=false; + break; + } + d=((c&7)<<18)|((Src[I]&0x3f)<<12)|((Src[I+1]&0x3f)<<6)|(Src[I+2]&0x3f); + I+=3; + } + else + { + Success=false; + break; + } + if (d>0xffff) + { + if (d>0x10ffff) // UTF-8 must end at 0x10ffff according to RFC 3629. + { + Success=false; + continue; + } + if (sizeof(Dest[0])==2) // Use the surrogate pair. + { + Dest.push_back( ((d-0x10000)>>10)+0xd800 ); + Dest.push_back( (d&0x3ff)+0xdc00 ); + } + else + Dest.push_back( d ); + } + else + Dest.push_back( d ); + } + return Success; +} +*/ + + // For zero terminated strings. bool IsTextUtf8(const byte *Src) { @@ -450,8 +677,10 @@ int wcsnicomp(const wchar *s1,const wchar *s2,size_t n) // If we specify 'n' exceeding the actual string length, CompareString goes // beyond the trailing zero and compares garbage. So we need to limit 'n' // to real string length. - size_t l1=Min(wcslen(s1)+1,n); - size_t l2=Min(wcslen(s2)+1,n); + size_t sl1=wcslen(s1); // Pre-compute to not call wcslen() in Min() twice. + size_t l1=Min(sl1+1,n); + size_t sl2=wcslen(s2); // Pre-compute to not call wcslen() in Min() twice. + size_t l2=Min(sl2+1,n); return CompareStringW(LOCALE_USER_DEFAULT,NORM_IGNORECASE|SORT_STRINGSORT,s1,(int)l1,s2,(int)l2)-2; #else if (n==0) @@ -483,7 +712,15 @@ const wchar_t* wcscasestr(const wchar_t *str, const wchar_t *search) if (tolowerw(str[i+j])!=tolowerw(search[j])) break; } - return NULL; + return nullptr; +} + + +// Case insensitive std::wstring substring search. +std::wstring::size_type wcscasestr(const std::wstring &str, const std::wstring &search) +{ + const wchar *Found=wcscasestr(str.c_str(),search.c_str()); + return Found==nullptr ? std::wstring::npos : Found-str.c_str(); } @@ -500,10 +737,14 @@ wchar* wcslower(wchar *s) #endif return s; } -#endif -#ifndef SFX_MODULE +void wcslower(std::wstring &s) +{ + wcslower(&s[0]); +} + + wchar* wcsupper(wchar *s) { #ifdef _WIN_ALL @@ -516,6 +757,12 @@ wchar* wcsupper(wchar *s) #endif return s; } + + +void wcsupper(std::wstring &s) +{ + wcsupper(&s[0]); +} #endif @@ -548,27 +795,28 @@ int tolowerw(int ch) } -int atoiw(const wchar *s) +int atoiw(const std::wstring &s) { return (int)atoilw(s); } -int64 atoilw(const wchar *s) +int64 atoilw(const std::wstring &s) { bool sign=false; - if (*s=='-') // We do use signed integers here, for example, in GUI SFX. + size_t Pos=0; + if (s[Pos]=='-') // We do use signed integers here, for example, in GUI SFX. { - s++; + Pos++; sign=true; } // Use unsigned type here, since long string can overflow the variable // and signed integer overflow is undefined behavior in C++. uint64 n=0; - while (*s>='0' && *s<='9') + while (s[Pos]>='0' && s[Pos]<='9') { - n=n*10+(*s-'0'); - s++; + n=n*10+(s[Pos]-'0'); + Pos++; } // Check int64(n)>=0 to avoid the signed overflow with undefined behavior // when negating 0x8000000000000000. diff --git a/vendor/unrar/unicode.hpp b/vendor/unrar/unicode.hpp index 9bfd9c5dcd..2d867b3aef 100644 --- a/vendor/unrar/unicode.hpp +++ b/vendor/unrar/unicode.hpp @@ -7,25 +7,37 @@ bool WideToChar(const wchar *Src,char *Dest,size_t DestSize); bool CharToWide(const char *Src,wchar *Dest,size_t DestSize); +bool WideToChar(const std::wstring &Src,std::string &Dest); +bool CharToWide(const std::string &Src,std::wstring &Dest); byte* WideToRaw(const wchar *Src,size_t SrcSize,byte *Dest,size_t DestSize); +void WideToRaw(const std::wstring &Src,std::vector &Dest); wchar* RawToWide(const byte *Src,wchar *Dest,size_t DestSize); +std::wstring RawToWide(const std::vector &Src); void WideToUtf(const wchar *Src,char *Dest,size_t DestSize); +void WideToUtf(const std::wstring &Src,std::string &Dest); size_t WideToUtfSize(const wchar *Src); bool UtfToWide(const char *Src,wchar *Dest,size_t DestSize); +bool UtfToWide(const char *Src,std::wstring &Dest); +//bool UtfToWide(const std::vector &Src,std::wstring &Dest); bool IsTextUtf8(const byte *Src); bool IsTextUtf8(const byte *Src,size_t SrcSize); int wcsicomp(const wchar *s1,const wchar *s2); +inline int wcsicomp(const std::wstring &s1,const std::wstring &s2) {return wcsicomp(s1.c_str(),s2.c_str());} int wcsnicomp(const wchar *s1,const wchar *s2,size_t n); +inline int wcsnicomp(const std::wstring &s1,const std::wstring &s2,size_t n) {return wcsnicomp(s1.c_str(),s2.c_str(),n);} const wchar_t* wcscasestr(const wchar_t *str, const wchar_t *search); +std::wstring::size_type wcscasestr(const std::wstring &str, const std::wstring &search); #ifndef SFX_MODULE wchar* wcslower(wchar *s); +void wcslower(std::wstring &s); wchar* wcsupper(wchar *s); +void wcsupper(std::wstring &s); #endif int toupperw(int ch); int tolowerw(int ch); -int atoiw(const wchar *s); -int64 atoilw(const wchar *s); +int atoiw(const std::wstring &s); +int64 atoilw(const std::wstring &s); #ifdef DBCS_SUPPORTED class SupportDBCS diff --git a/vendor/unrar/unpack.cpp b/vendor/unrar/unpack.cpp index 9236e748bc..99c6f15db5 100644 --- a/vendor/unrar/unpack.cpp +++ b/vendor/unrar/unpack.cpp @@ -10,8 +10,8 @@ #ifndef SFX_MODULE #include "unpack15.cpp" #include "unpack20.cpp" -#endif #include "unpack30.cpp" +#endif #include "unpack50.cpp" #include "unpack50frag.cpp" @@ -24,18 +24,20 @@ Unpack::Unpack(ComprDataIO *DataIO) Suspended=false; UnpAllBuf=false; UnpSomeRead=false; + ExtraDist=false; #ifdef RAR_SMP MaxUserThreads=1; UnpThreadPool=NULL; ReadBufMT=NULL; UnpThreadData=NULL; #endif + AllocWinSize=0; MaxWinSize=0; MaxWinMask=0; // Perform initialization, which should be done only once for all files. - // It prevents crash if first DoUnpack call is later made with wrong - // (true) 'Solid' value. + // It prevents crash if first unpacked file has the wrong "true" Solid flag, + // so first DoUnpack call is made with the wrong "true" Solid value later. UnpInitData(false); #ifndef SFX_MODULE // RAR 1.5 decompression initialization @@ -47,10 +49,11 @@ Unpack::Unpack(ComprDataIO *DataIO) Unpack::~Unpack() { +#ifndef SFX_MODULE InitFilters30(false); +#endif - if (Window!=NULL) - free(Window); + free(Window); #ifdef RAR_SMP delete UnpThreadPool; delete[] ReadBufMT; @@ -70,13 +73,11 @@ void Unpack::SetThreads(uint Threads) #endif -void Unpack::Init(size_t WinSize,bool Solid) +// We get 64-bit WinSize, so we still can check and quit for dictionaries +// exceeding a threshold in 32-bit builds. Then we convert WinSize to size_t +// MaxWinSize. +void Unpack::Init(uint64 WinSize,bool Solid) { - // If 32-bit RAR unpacks an archive with 4 GB dictionary, the window size - // will be 0 because of size_t overflow. Let's issue the memory error. - if (WinSize==0) - ErrHandler.MemoryError(); - // Minimum window size must be at least twice more than maximum possible // size of filter block, which is 0x10000 in RAR now. If window size is // smaller, we can have a block with never cleared flt->NextWindow flag @@ -86,39 +87,53 @@ void Unpack::Init(size_t WinSize,bool Solid) if (WinSize>16)>0x10000) // Window size must not exceed 4 GB. + if (WinSize>Min(0x10000000000ULL,UNPACK_MAX_DICT)) // Window size must not exceed 1 TB. + throw std::bad_alloc(); + + // 32-bit build can't unpack dictionaries exceeding 32-bit even in theory. + // Also we've not verified if WrapUp and WrapDown work properly in 32-bit + // version and >2GB dictionary and if 32-bit version can handle >2GB + // distances. Since such version is unlikely to allocate >2GB anyway, + // we prohibit >2GB dictionaries for 32-bit build here. + if (WinSize>0x80000000 && sizeof(size_t)<=4) + throw std::bad_alloc(); + + // Solid block shall use the same window size for all files. + // But if Window isn't initialized when Solid is set, it means that + // first file in solid block doesn't have the solid flag. We initialize + // the window anyway for such malformed archive. + // Non-solid files shall use their specific window sizes, + // so current window size and unpack routine behavior doesn't depend on + // previously unpacked files and their extraction order. + if (!Solid || Window==nullptr) + { + MaxWinSize=(size_t)WinSize; + MaxWinMask=MaxWinSize-1; + } + + // Use the already allocated window when processing non-solid files + // with reducing dictionary sizes. + if (WinSize<=AllocWinSize) return; // Archiving code guarantees that window size does not grow in the same // solid stream. So if we are here, we are either creating a new window // or increasing the size of non-solid window. So we could safely reject - // current window data without copying them to a new window, though being - // extra cautious, we still handle the solid window grow case below. - bool Grow=Solid && (Window!=NULL || Fragmented); - - // We do not handle growth for existing fragmented window. - if (Grow && Fragmented) + // current window data without copying them to a new window. + if (Solid && (Window!=NULL || Fragmented && WinSize>FragWindow.GetWinSize())) throw std::bad_alloc(); - byte *NewWindow=Fragmented ? NULL : (byte *)malloc(WinSize); + free(Window); + + Window=Fragmented ? NULL : (byte *)malloc((size_t)WinSize); - if (NewWindow==NULL) - if (Grow || WinSize<0x1000000) - { - // We do not support growth for new fragmented window. - // Also exclude RAR4 and small dictionaries. - throw std::bad_alloc(); - } + if (Window==NULL) + if (WinSize<0x1000000 || sizeof(size_t)>4) + throw std::bad_alloc(); // Exclude RAR4, small dictionaries and 64-bit. else { - if (Window!=NULL) // If allocated by preceding files. - { - free(Window); - Window=NULL; - } - FragWindow.Init(WinSize); + if (WinSize>FragWindow.GetWinSize()) + FragWindow.Init((size_t)WinSize); Fragmented=true; } @@ -126,23 +141,12 @@ void Unpack::Init(size_t WinSize,bool Solid) { // Clean the window to generate the same output when unpacking corrupt // RAR files, which may access unused areas of sliding dictionary. - memset(NewWindow,0,WinSize); - - // If Window is not NULL, it means that window size has grown. - // In solid streams we need to copy data to a new window in such case. - // RAR archiving code does not allow it in solid streams now, - // but let's implement it anyway just in case we'll change it sometimes. - if (Grow) - for (size_t I=1;I<=MaxWinSize;I++) - NewWindow[(UnpPtr-I)&(WinSize-1)]=Window[(UnpPtr-I)&(MaxWinSize-1)]; - - if (Window!=NULL) - free(Window); - Window=NewWindow; - } + // 2023.10.31: We've added FirstWinDone based unused area access check + // in Unpack::CopyString(), so this memset might be unnecessary now. +// memset(Window,0,(size_t)WinSize); - MaxWinSize=WinSize; - MaxWinMask=MaxWinSize-1; + AllocWinSize=WinSize; + } } @@ -154,21 +158,23 @@ void Unpack::DoUnpack(uint Method,bool Solid) switch(Method) { #ifndef SFX_MODULE - case 15: // rar 1.5 compression + case 15: // RAR 1.5 compression. if (!Fragmented) Unpack15(Solid); break; - case 20: // rar 2.x compression - case 26: // files larger than 2GB + case 20: // RAR 2.x compression. + case 26: // Files larger than 2GB. if (!Fragmented) Unpack20(Solid); break; -#endif - case 29: // rar 3.x compression + case 29: // RAR 3.x compression. if (!Fragmented) Unpack29(Solid); break; - case 50: // RAR 5.0 compression algorithm. +#endif + case VER_PACK5: // 50. RAR 5.0 and 7.0 compression algorithms. + case VER_PACK7: // 70. + ExtraDist=(Method==VER_PACK7); #ifdef RAR_SMP if (MaxUserThreads>1) { @@ -194,13 +200,19 @@ void Unpack::UnpInitData(bool Solid) { if (!Solid) { - memset(OldDist,0,sizeof(OldDist)); + OldDist[0]=OldDist[1]=OldDist[2]=OldDist[3]=(size_t)-1; + OldDistPtr=0; - LastDist=LastLength=0; + + LastDist=(uint)-1; // Initialize it to -1 like LastDist. + LastLength=0; + // memset(Window,0,MaxWinSize); memset(&BlockTables,0,sizeof(BlockTables)); UnpPtr=WrPtr=0; - WriteBorder=Min(MaxWinSize,UNPACK_MAX_WRITE)&MaxWinMask; + PrevPtr=0; + FirstWinDone=false; + WriteBorder=Min(MaxWinSize,UNPACK_MAX_WRITE); } // Filters never share several solid files, so we can safely reset them // even in solid archive. @@ -215,8 +227,8 @@ void Unpack::UnpInitData(bool Solid) BlockHeader.BlockSize=-1; // '-1' means not defined yet. #ifndef SFX_MODULE UnpInitData20(Solid); -#endif UnpInitData30(Solid); +#endif UnpInitData50(Solid); } diff --git a/vendor/unrar/unpack.hpp b/vendor/unrar/unpack.hpp index 737b31c2cc..5ed904a8cf 100644 --- a/vendor/unrar/unpack.hpp +++ b/vendor/unrar/unpack.hpp @@ -2,7 +2,7 @@ #define _RAR_UNPACK_ // Maximum allowed number of compressed bits processed in quick mode. -#define MAX_QUICK_DECODE_BITS 10 +#define MAX_QUICK_DECODE_BITS 9 // Maximum number of filters per entire data block. Must be at least // twice more than MAX_PACK_FILTERS to store filters from two data blocks. @@ -102,7 +102,7 @@ struct UnpackDecodedItem ushort Length; union { - uint Distance; + size_t Distance; byte Literal[8]; // Store up to 8 chars here to speed up extraction. }; }; @@ -143,13 +143,13 @@ struct UnpackThreadData struct UnpackFilter { + // Groop 'byte' and 'bool' together to reduce the actual struct size. byte Type; - uint BlockStart; - uint BlockLength; byte Channels; -// uint Width; -// byte PosR; bool NextWindow; + + size_t BlockStart; + uint BlockLength; }; @@ -188,14 +188,16 @@ class FragmentedWindow void Reset(); byte *Mem[MAX_MEM_BLOCKS]; size_t MemSize[MAX_MEM_BLOCKS]; + size_t LastAllocated; public: FragmentedWindow(); ~FragmentedWindow(); void Init(size_t WinSize); byte& operator [](size_t Item); - void CopyString(uint Length,uint Distance,size_t &UnpPtr,size_t MaxWinMask); + void CopyString(uint Length,size_t Distance,size_t &UnpPtr,bool FirstWinDone,size_t MaxWinSize); void CopyData(byte *Dest,size_t WinPos,size_t Size); size_t GetBlockSize(size_t StartPos,size_t RequiredSize); + size_t GetWinSize() {return LastAllocated;} }; @@ -216,10 +218,9 @@ class Unpack:PackDef bool ReadTables(BitInput &Inp,UnpackBlockHeader &Header,UnpackBlockTables &Tables); void MakeDecodeTables(byte *LengthTable,DecodeTable *Dec,uint Size); _forceinline uint DecodeNumber(BitInput &Inp,DecodeTable *Dec); - void CopyString(); - inline void InsertOldDist(unsigned int Distance); + inline void InsertOldDist(size_t Distance); void UnpInitData(bool Solid); - _forceinline void CopyString(uint Length,uint Distance); + _forceinline void CopyString(uint Length,size_t Distance); uint ReadFilterData(BitInput &Inp); bool ReadFilter(BitInput &Inp,UnpackFilter &Filter); bool AddFilter(UnpackFilter &Filter); @@ -240,20 +241,25 @@ class Unpack:PackDef byte *ReadBufMT; #endif - Array FilterSrcMemory; - Array FilterDstMemory; + std::vector FilterSrcMemory; + std::vector FilterDstMemory; // Filters code, one entry per filter. - Array Filters; + std::vector Filters; - uint OldDist[4],OldDistPtr; + size_t OldDist[4],OldDistPtr; uint LastLength; // LastDist is necessary only for RAR2 and older with circular OldDist // array. In RAR3 last distance is always stored in OldDist[0]. uint LastDist; - size_t UnpPtr,WrPtr; + size_t UnpPtr; // Current position in window. + + size_t PrevPtr; // UnpPtr value for previous loop iteration. + bool FirstWinDone; // At least one dictionary was processed. + + size_t WrPtr; // Last written unpacked data position. // Top border of read packed data. int ReadTop; @@ -266,7 +272,7 @@ class Unpack:PackDef UnpackBlockHeader BlockHeader; UnpackBlockTables BlockTables; - size_t WriteBorder; + size_t WriteBorder; // Perform write when reaching this border. byte *Window; @@ -289,7 +295,7 @@ class Unpack:PackDef void LongLZ(); void HuffDecode(); void GetFlagsBuf(); - void UnpInitData15(int Solid); + void UnpInitData15(bool Solid); void InitHuff(); void CorrHuff(ushort *CharSet,byte *NumToPlace); void CopyString15(uint Distance,uint Length); @@ -359,15 +365,15 @@ class Unpack:PackDef BitInput VMCodeInp; // Filters code, one entry per filter. - Array Filters30; + std::vector Filters30; // Filters stack, several entrances of same filter are possible. - Array PrgStack; + std::vector PrgStack; // Lengths of preceding data blocks, one length of one last block // for every filter. Used to reduce the size required to write // the data block length if lengths are repeating. - Array OldFilterLengths; + std::vector OldFilterLengths; int LastFilter; /***************************** Unpack v 3.0 *********************************/ @@ -375,9 +381,9 @@ class Unpack:PackDef public: Unpack(ComprDataIO *DataIO); ~Unpack(); - void Init(size_t WinSize,bool Solid); + void Init(uint64 WinSize,bool Solid); void DoUnpack(uint Method,bool Solid); - bool IsFileExtracted() {return(FileExtracted);} + bool IsFileExtracted() {return FileExtracted;} void SetDestSize(int64 DestSize) {DestUnpSize=DestSize;FileExtracted=false;} void SetSuspended(bool Suspended) {Unpack::Suspended=Suspended;} @@ -386,10 +392,13 @@ class Unpack:PackDef void UnpackDecode(UnpackThreadData &D); #endif + uint64 AllocWinSize; size_t MaxWinSize; size_t MaxWinMask; - uint GetChar() + bool ExtraDist; // Allow distances up to 1 TB. + + byte GetChar() { if (Inp.InAddr>BitInput::MAX_SIZE-30) { @@ -399,6 +408,30 @@ class Unpack:PackDef } return Inp.InBuf[Inp.InAddr++]; } + + + // If window position crosses the window beginning, wrap it to window end. + // Replaces &MaxWinMask for non-power 2 window sizes. + // We can't use %WinSize everywhere not only for performance reason, + // but also because C++ % is reminder instead of modulo. + // We need additional checks in the code if WinPos distance from 0 + // can exceed MaxWinSize. Alternatively we could add such check here. + inline size_t WrapDown(size_t WinPos) + { + return WinPos >= MaxWinSize ? WinPos + MaxWinSize : WinPos; + } + + // If window position crosses the window end, wrap it to window beginning. + // Replaces &MaxWinMask for non-power 2 window sizes. + // Unlike WrapDown, we can use %WinSize here if there was no size_t + // overflow when calculating WinPos. + // We need additional checks in the code if WinPos distance from MaxWinSize + // can be MaxWinSize or more. Alternatively we could add such check here + // or use %WinSize. + inline size_t WrapUp(size_t WinPos) + { + return WinPos >= MaxWinSize ? WinPos - MaxWinSize : WinPos; + } }; #endif diff --git a/vendor/unrar/unpack15.cpp b/vendor/unrar/unpack15.cpp index 1e7cf76c2d..1019c354a6 100644 --- a/vendor/unrar/unpack15.cpp +++ b/vendor/unrar/unpack15.cpp @@ -1,40 +1,40 @@ #define STARTL1 2 -static unsigned int DecL1[]={0x8000,0xa000,0xc000,0xd000,0xe000,0xea00, +static uint DecL1[]={0x8000,0xa000,0xc000,0xd000,0xe000,0xea00, 0xee00,0xf000,0xf200,0xf200,0xffff}; -static unsigned int PosL1[]={0,0,0,2,3,5,7,11,16,20,24,32,32}; +static uint PosL1[]={0,0,0,2,3,5,7,11,16,20,24,32,32}; #define STARTL2 3 -static unsigned int DecL2[]={0xa000,0xc000,0xd000,0xe000,0xea00,0xee00, +static uint DecL2[]={0xa000,0xc000,0xd000,0xe000,0xea00,0xee00, 0xf000,0xf200,0xf240,0xffff}; -static unsigned int PosL2[]={0,0,0,0,5,7,9,13,18,22,26,34,36}; +static uint PosL2[]={0,0,0,0,5,7,9,13,18,22,26,34,36}; #define STARTHF0 4 -static unsigned int DecHf0[]={0x8000,0xc000,0xe000,0xf200,0xf200,0xf200, +static uint DecHf0[]={0x8000,0xc000,0xe000,0xf200,0xf200,0xf200, 0xf200,0xf200,0xffff}; -static unsigned int PosHf0[]={0,0,0,0,0,8,16,24,33,33,33,33,33}; +static uint PosHf0[]={0,0,0,0,0,8,16,24,33,33,33,33,33}; #define STARTHF1 5 -static unsigned int DecHf1[]={0x2000,0xc000,0xe000,0xf000,0xf200,0xf200, +static uint DecHf1[]={0x2000,0xc000,0xe000,0xf000,0xf200,0xf200, 0xf7e0,0xffff}; -static unsigned int PosHf1[]={0,0,0,0,0,0,4,44,60,76,80,80,127}; +static uint PosHf1[]={0,0,0,0,0,0,4,44,60,76,80,80,127}; #define STARTHF2 5 -static unsigned int DecHf2[]={0x1000,0x2400,0x8000,0xc000,0xfa00,0xffff, +static uint DecHf2[]={0x1000,0x2400,0x8000,0xc000,0xfa00,0xffff, 0xffff,0xffff}; -static unsigned int PosHf2[]={0,0,0,0,0,0,2,7,53,117,233,0,0}; +static uint PosHf2[]={0,0,0,0,0,0,2,7,53,117,233,0,0}; #define STARTHF3 6 -static unsigned int DecHf3[]={0x800,0x2400,0xee00,0xfe80,0xffff,0xffff, +static uint DecHf3[]={0x800,0x2400,0xee00,0xfe80,0xffff,0xffff, 0xffff}; -static unsigned int PosHf3[]={0,0,0,0,0,0,0,2,16,218,251,0,0}; +static uint PosHf3[]={0,0,0,0,0,0,0,2,16,218,251,0,0}; #define STARTHF4 8 -static unsigned int DecHf4[]={0xff00,0xffff,0xffff,0xffff,0xffff,0xffff}; -static unsigned int PosHf4[]={0,0,0,0,0,0,0,0,0,255,0,0,0}; +static uint DecHf4[]={0xff00,0xffff,0xffff,0xffff,0xffff,0xffff}; +static uint PosHf4[]={0,0,0,0,0,0,0,0,0,255,0,0,0}; void Unpack::Unpack15(bool Solid) @@ -60,6 +60,9 @@ void Unpack::Unpack15(bool Solid) { UnpPtr&=MaxWinMask; + FirstWinDone|=(PrevPtr>UnpPtr); + PrevPtr=UnpPtr; + if (Inp.InAddr>ReadTop-30 && !UnpReadBuf()) break; if (((WrPtr-UnpPtr) & MaxWinMask)<270 && WrPtr!=UnpPtr) @@ -116,27 +119,27 @@ void Unpack::Unpack15(bool Solid) void Unpack::ShortLZ() { - static unsigned int ShortLen1[]={1,3,4,4,5,6,7,8,8,4,4,5,6,6,4,0}; - static unsigned int ShortXor1[]={0,0xa0,0xd0,0xe0,0xf0,0xf8,0xfc,0xfe, + static uint ShortLen1[]={1,3,4,4,5,6,7,8,8,4,4,5,6,6,4,0}; + static uint ShortXor1[]={0,0xa0,0xd0,0xe0,0xf0,0xf8,0xfc,0xfe, 0xff,0xc0,0x80,0x90,0x98,0x9c,0xb0}; - static unsigned int ShortLen2[]={2,3,3,3,4,4,5,6,6,4,4,5,6,6,4,0}; - static unsigned int ShortXor2[]={0,0x40,0x60,0xa0,0xd0,0xe0,0xf0,0xf8, + static uint ShortLen2[]={2,3,3,3,4,4,5,6,6,4,4,5,6,6,4,0}; + static uint ShortXor2[]={0,0x40,0x60,0xa0,0xd0,0xe0,0xf0,0xf8, 0xfc,0xc0,0x80,0x90,0x98,0x9c,0xb0}; - unsigned int Length,SaveLength; - unsigned int LastDistance; - unsigned int Distance; + uint Length,SaveLength; + uint LastDistance; + uint Distance; int DistancePlace; NumHuf=0; - unsigned int BitField=Inp.fgetbits(); + uint BitField=Inp.fgetbits(); if (LCount==2) { Inp.faddbits(1); if (BitField >= 0x8000) { - CopyString15((unsigned int)LastDist,LastLength); + CopyString15(LastDist,LastLength); return; } BitField <<= 1; @@ -168,7 +171,7 @@ void Unpack::ShortLZ() if (Length == 9) { LCount++; - CopyString15((unsigned int)LastDist,LastLength); + CopyString15(LastDist,LastLength); return; } if (Length == 14) @@ -185,7 +188,7 @@ void Unpack::ShortLZ() LCount=0; SaveLength=Length; - Distance=OldDist[(OldDistPtr-(Length-9)) & 3]; + Distance=(uint)OldDist[(OldDistPtr-(Length-9)) & 3]; Length=DecodeNum(Inp.fgetbits(),STARTL1,DecL1,PosL1)+2; if (Length==0x101 && SaveLength==10) { @@ -214,8 +217,8 @@ void Unpack::ShortLZ() if (--DistancePlace != -1) { LastDistance=ChSetA[DistancePlace]; - ChSetA[DistancePlace+1]=LastDistance; - ChSetA[DistancePlace]=Distance; + ChSetA[DistancePlace+1]=(ushort)LastDistance; + ChSetA[DistancePlace]=(ushort)Distance; } Length+=2; OldDist[OldDistPtr++] = ++Distance; @@ -228,10 +231,10 @@ void Unpack::ShortLZ() void Unpack::LongLZ() { - unsigned int Length; - unsigned int Distance; - unsigned int DistancePlace,NewDistancePlace; - unsigned int OldAvr2,OldAvr3; + uint Length; + uint Distance; + uint DistancePlace,NewDistancePlace; + uint OldAvr2,OldAvr3; NumHuf=0; Nlzb+=16; @@ -242,7 +245,7 @@ void Unpack::LongLZ() } OldAvr2=AvrLn2; - unsigned int BitField=Inp.fgetbits(); + uint BitField=Inp.fgetbits(); if (AvrLn2 >= 122) Length=DecodeNum(BitField,STARTL2,DecL2,PosL2); else @@ -286,7 +289,7 @@ void Unpack::LongLZ() } ChSetB[DistancePlace & 0xff]=ChSetB[NewDistancePlace]; - ChSetB[NewDistancePlace]=Distance; + ChSetB[NewDistancePlace]=(ushort)Distance; Distance=((Distance & 0xff00) | (Inp.fgetbits() >> 8)) >> 1; Inp.faddbits(7); @@ -320,12 +323,12 @@ void Unpack::LongLZ() void Unpack::HuffDecode() { - unsigned int CurByte,NewBytePlace; - unsigned int Length; - unsigned int Distance; + uint CurByte,NewBytePlace; + uint Length; + uint Distance; int BytePlace; - unsigned int BitField=Inp.fgetbits(); + uint BitField=Inp.fgetbits(); if (AvrPlc > 0x75ff) BytePlace=DecodeNum(BitField,STARTHF4,DecHf4,PosHf4); @@ -392,14 +395,14 @@ void Unpack::HuffDecode() } ChSet[BytePlace]=ChSet[NewBytePlace]; - ChSet[NewBytePlace]=CurByte; + ChSet[NewBytePlace]=(ushort)CurByte; } void Unpack::GetFlagsBuf() { - unsigned int Flags,NewFlagsPlace; - unsigned int FlagsPlace=DecodeNum(Inp.fgetbits(),STARTHF2,DecHf2,PosHf2); + uint Flags,NewFlagsPlace; + uint FlagsPlace=DecodeNum(Inp.fgetbits(),STARTHF2,DecHf2,PosHf2); // Our Huffman table stores 257 items and needs all them in other parts // of code such as when StMode is on, so the first item is control item. @@ -420,11 +423,11 @@ void Unpack::GetFlagsBuf() } ChSetC[FlagsPlace]=ChSetC[NewFlagsPlace]; - ChSetC[NewFlagsPlace]=Flags; + ChSetC[NewFlagsPlace]=(ushort)Flags; } -void Unpack::UnpInitData15(int Solid) +void Unpack::UnpInitData15(bool Solid) { if (!Solid) { @@ -443,7 +446,7 @@ void Unpack::UnpInitData15(int Solid) void Unpack::InitHuff() { - for (unsigned int I=0;I<256;I++) + for (ushort I=0;I<256;I++) { ChSet[I]=ChSetB[I]=I<<8; ChSetA[I]=I; @@ -471,11 +474,19 @@ void Unpack::CorrHuff(ushort *CharSet,byte *NumToPlace) void Unpack::CopyString15(uint Distance,uint Length) { DestUnpSize-=Length; - while (Length--) - { - Window[UnpPtr]=Window[(UnpPtr-Distance) & MaxWinMask]; - UnpPtr=(UnpPtr+1) & MaxWinMask; - } + // 2024.04.18: Distance can be 0 in corrupt RAR 1.5 archives. + if (!FirstWinDone && Distance>UnpPtr || Distance>MaxWinSize || Distance==0) + while (Length-- > 0) + { + Window[UnpPtr]=0; + UnpPtr=(UnpPtr+1) & MaxWinMask; + } + else + while (Length-- > 0) + { + Window[UnpPtr]=Window[(UnpPtr-Distance) & MaxWinMask]; + UnpPtr=(UnpPtr+1) & MaxWinMask; + } } diff --git a/vendor/unrar/unpack20.cpp b/vendor/unrar/unpack20.cpp index 93c8ba05a2..a0e179d6a6 100644 --- a/vendor/unrar/unpack20.cpp +++ b/vendor/unrar/unpack20.cpp @@ -2,7 +2,8 @@ void Unpack::CopyString20(uint Length,uint Distance) { - LastDist=OldDist[OldDistPtr++]=Distance; + LastDist=Distance; + OldDist[OldDistPtr++]=Distance; OldDistPtr = OldDistPtr & 3; // Needed if RAR 1.5 file is called after RAR 2.0. LastLength=Length; DestUnpSize-=Length; @@ -36,6 +37,9 @@ void Unpack::Unpack20(bool Solid) { UnpPtr&=MaxWinMask; + FirstWinDone|=(PrevPtr>UnpPtr); + PrevPtr=UnpPtr; + if (Inp.InAddr>ReadTop-30) if (!UnpReadBuf()) break; @@ -109,7 +113,7 @@ void Unpack::Unpack20(bool Solid) } if (Number<261) { - uint Distance=OldDist[(OldDistPtr-(Number-256)) & 3]; + uint Distance=(uint)OldDist[(OldDistPtr-(Number-256)) & 3]; uint LengthNumber=DecodeNumber(Inp,&BlockTables.RD); uint Length=LDecode[LengthNumber]+2; if ((Bits=LBits[LengthNumber])>0) diff --git a/vendor/unrar/unpack30.cpp b/vendor/unrar/unpack30.cpp index 7c2adfab28..1fb0615a6b 100644 --- a/vendor/unrar/unpack30.cpp +++ b/vendor/unrar/unpack30.cpp @@ -17,8 +17,8 @@ void Unpack::Unpack29(bool Solid) { static unsigned char LDecode[]={0,1,2,3,4,5,6,7,8,10,12,14,16,20,24,28,32,40,48,56,64,80,96,112,128,160,192,224}; static unsigned char LBits[]= {0,0,0,0,0,0,0,0,1, 1, 1, 1, 2, 2, 2, 2, 3, 3, 3, 3, 4, 4, 4, 4, 5, 5, 5, 5}; - static int DDecode[DC]; - static byte DBits[DC]; + static int DDecode[DC30]; + static byte DBits[DC30]; static int DBitLengthCounts[]= {4,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,14,0,12}; static unsigned char SDDecode[]={0,4,8,16,32,64,128,192}; static unsigned char SDBits[]= {2,2,3, 4, 5, 6, 6, 6}; @@ -50,6 +50,9 @@ void Unpack::Unpack29(bool Solid) { UnpPtr&=MaxWinMask; + FirstWinDone|=(PrevPtr>UnpPtr); + PrevPtr=UnpPtr; + if (Inp.InAddr>ReadBorder) { if (!UnpReadBuf30()) @@ -219,7 +222,7 @@ void Unpack::Unpack29(bool Solid) if (Number<263) { uint DistNum=Number-259; - uint Distance=OldDist[DistNum]; + uint Distance=(uint)OldDist[DistNum]; for (uint I=DistNum;I>0;I--) OldDist[I]=OldDist[I-1]; OldDist[0]=Distance; @@ -306,7 +309,7 @@ bool Unpack::ReadVMCode() } if (Length==0) return false; - Array VMCode(Length); + std::vector VMCode(Length); for (uint I=0;I>8; Inp.addbits(8); } - return AddVMCode(FirstByte,&VMCode[0],Length); + return AddVMCode(FirstByte,VMCode.data(),Length); } @@ -346,7 +349,7 @@ bool Unpack::ReadVMCodePPM() } if (Length==0) return false; - Array VMCode(Length); + std::vector VMCode(Length); for (uint I=0;IFilters30.Size() || FiltPos>OldFilterLengths.Size()) + if (FiltPos>Filters30.size() || FiltPos>OldFilterLengths.size()) return false; LastFilter=FiltPos; - bool NewFilter=(FiltPos==Filters30.Size()); + bool NewFilter=(FiltPos==Filters30.size()); UnpackFilter30 *StackFilter=new UnpackFilter30; // New filter for PrgStack. @@ -393,15 +396,15 @@ bool Unpack::AddVMCode(uint FirstByte,byte *Code,uint CodeSize) return false; } - Filters30.Add(1); - Filters30[Filters30.Size()-1]=Filter=new UnpackFilter30; - StackFilter->ParentFilter=(uint)(Filters30.Size()-1); + StackFilter->ParentFilter=(uint)Filters30.size(); + Filter=new UnpackFilter30; + Filters30.push_back(Filter); // Reserve one item to store the data block length of our new filter // entry. We'll set it to real block length below, after reading it. // But we need to initialize it now, because when processing corrupt // data, we can access this item even before we set it to real value. - OldFilterLengths.Push(0); + OldFilterLengths.push_back(0); } else // Filter was used in the past. { @@ -410,7 +413,7 @@ bool Unpack::AddVMCode(uint FirstByte,byte *Code,uint CodeSize) } uint EmptyCount=0; - for (uint I=0;IMAX3_UNPACK_FILTERS) + if (PrgStack.size()>MAX3_UNPACK_FILTERS) { delete StackFilter; return false; } - PrgStack.Add(1); + PrgStack.resize(PrgStack.size()+1); EmptyCount=1; } - size_t StackPos=PrgStack.Size()-EmptyCount; + size_t StackPos=PrgStack.size()-EmptyCount; PrgStack[StackPos]=StackFilter; uint BlockStart=RarVM::ReadData(VMCodeInp); @@ -448,7 +451,7 @@ bool Unpack::AddVMCode(uint FirstByte,byte *Code,uint CodeSize) // for same filter. It is possible for corrupt data to access a new // and not filled yet item of OldFilterLengths array here. This is why // we set new OldFilterLengths items to zero above. - StackFilter->BlockLength=FiltPosBlockLength=FiltPosNextWindow=WrPtr!=UnpPtr && ((WrPtr-UnpPtr)&MaxWinMask)<=BlockStart; @@ -472,7 +475,7 @@ bool Unpack::AddVMCode(uint FirstByte,byte *Code,uint CodeSize) uint VMCodeSize=RarVM::ReadData(VMCodeInp); if (VMCodeSize>=0x10000 || VMCodeSize==0 || VMCodeInp.InAddr+VMCodeSize>CodeSize) return false; - Array VMCode(VMCodeSize); + std::vector VMCode(VMCodeSize); for (uint I=0;I>8; VMCodeInp.faddbits(8); } - VM.Prepare(&VMCode[0],VMCodeSize,&Filter->Prg); + VM.Prepare(VMCode.data(),VMCodeSize,&Filter->Prg); } StackFilter->Prg.Type=Filter->Prg.Type; @@ -520,7 +523,7 @@ void Unpack::UnpWriteBuf30() { uint WrittenBorder=(uint)WrPtr; uint WriteSize=(uint)((UnpPtr-WrittenBorder)&MaxWinMask); - for (size_t I=0;IFilteredDataSize; delete PrgStack[I]; - PrgStack[I]=NULL; - while (I+1FilteredDataSize; I++; delete PrgStack[I]; - PrgStack[I]=NULL; + PrgStack[I]=nullptr; } UnpIO->UnpWrite(FilteredData,FilteredDataSize); UnpSomeRead=true; @@ -601,10 +604,10 @@ void Unpack::UnpWriteBuf30() { // Current filter intersects the window write border, so we adjust // the window border to process this filter next time, not now. - for (size_t J=I;JNextWindow) + if (flt!=nullptr && flt->NextWindow) flt->NextWindow=false; } WrPtr=WrittenBorder; @@ -752,14 +755,14 @@ void Unpack::InitFilters30(bool Solid) { if (!Solid) { - OldFilterLengths.SoftReset(); + OldFilterLengths.clear(); LastFilter=0; - for (size_t I=0;IUnpPtr); + PrevPtr=UnpPtr; if (Inp.InAddr>=ReadBorder) { @@ -42,7 +47,8 @@ void Unpack::Unpack5(bool Solid) break; } - if (((WriteBorder-UnpPtr) & MaxWinMask)<=MAX_INC_LZ_MATCH && WriteBorder!=UnpPtr) + // WriteBorder==UnpPtr means that we have MaxWinSize data ahead. + if (WrapDown(WriteBorder-UnpPtr)<=MAX_INC_LZ_MATCH && WriteBorder!=UnpPtr) { UnpWriteBuf(); if (WrittenFileSize>DestUnpSize) @@ -67,7 +73,8 @@ void Unpack::Unpack5(bool Solid) { uint Length=SlotToLength(Inp,MainSlot-262); - uint DBits,Distance=1,DistSlot=DecodeNumber(Inp,&BlockTables.DD); + size_t Distance=1; + uint DBits,DistSlot=DecodeNumber(Inp,&BlockTables.DD); if (DistSlot<4) { DBits=0; @@ -76,7 +83,7 @@ void Unpack::Unpack5(bool Solid) else { DBits=DistSlot/2 - 1; - Distance+=(2 | (DistSlot & 1)) << DBits; + Distance+=size_t(2 | (DistSlot & 1)) << DBits; } if (DBits>0) @@ -85,11 +92,23 @@ void Unpack::Unpack5(bool Solid) { if (DBits>4) { - Distance+=((Inp.getbits32()>>(36-DBits))<<4); + // It is also possible to always use getbits64() here. + if (DBits>36) + Distance+=( ( size_t(Inp.getbits64() ) >> (68-DBits) ) << 4 ); + else + Distance+=( ( size_t(Inp.getbits32() ) >> (36-DBits) ) << 4 ); Inp.addbits(DBits-4); } uint LowDist=DecodeNumber(Inp,&BlockTables.LDD); Distance+=LowDist; + + // Distance can be 0 for multiples of 4 GB as result of size_t + // overflow in 32-bit build. Its lower 32-bit can also erroneously + // fit into dictionary after truncating upper 32-bits. Replace such + // invalid distances with -1, so CopyString sets 0 data for them. + // DBits>=30 also as DistSlot>=62 indicate distances >=0x80000001. + if (sizeof(Distance)==4 && DBits>=30) + Distance=(size_t)-1; } else { @@ -112,7 +131,7 @@ void Unpack::Unpack5(bool Solid) InsertOldDist(Distance); LastLength=Length; if (Fragmented) - FragWindow.CopyString(Length,Distance,UnpPtr,MaxWinMask); + FragWindow.CopyString(Length,Distance,UnpPtr,FirstWinDone,MaxWinSize); else CopyString(Length,Distance); continue; @@ -128,7 +147,7 @@ void Unpack::Unpack5(bool Solid) { if (LastLength!=0) if (Fragmented) - FragWindow.CopyString(LastLength,OldDist[0],UnpPtr,MaxWinMask); + FragWindow.CopyString(LastLength,OldDist[0],UnpPtr,FirstWinDone,MaxWinSize); else CopyString(LastLength,OldDist[0]); continue; @@ -136,7 +155,7 @@ void Unpack::Unpack5(bool Solid) if (MainSlot<262) { uint DistNum=MainSlot-258; - uint Distance=OldDist[DistNum]; + size_t Distance=OldDist[DistNum]; for (uint I=DistNum;I>0;I--) OldDist[I]=OldDist[I-1]; OldDist[0]=Distance; @@ -145,7 +164,7 @@ void Unpack::Unpack5(bool Solid) uint Length=SlotToLength(Inp,LengthSlot); LastLength=Length; if (Fragmented) - FragWindow.CopyString(Length,Distance,UnpPtr,MaxWinMask); + FragWindow.CopyString(Length,Distance,UnpPtr,FirstWinDone,MaxWinSize); else CopyString(Length,Distance); continue; @@ -196,20 +215,25 @@ bool Unpack::ReadFilter(BitInput &Inp,UnpackFilter &Filter) bool Unpack::AddFilter(UnpackFilter &Filter) { - if (Filters.Size()>=MAX_UNPACK_FILTERS) + if (Filters.size()>=MAX_UNPACK_FILTERS) { UnpWriteBuf(); // Write data, apply and flush filters. - if (Filters.Size()>=MAX_UNPACK_FILTERS) + if (Filters.size()>=MAX_UNPACK_FILTERS) InitFilters(); // Still too many filters, prevent excessive memory use. } // If distance to filter start is that large that due to circular dictionary // mode now it points to old not written yet data, then we set 'NextWindow' // flag and process this filter only after processing that older data. - Filter.NextWindow=WrPtr!=UnpPtr && ((WrPtr-UnpPtr)&MaxWinMask)<=Filter.BlockStart; - - Filter.BlockStart=uint((Filter.BlockStart+UnpPtr)&MaxWinMask); - Filters.Push(Filter); + Filter.NextWindow=WrPtr!=UnpPtr && WrapDown(WrPtr-UnpPtr)<=Filter.BlockStart; + + // In malformed archive Filter.BlockStart can be many times larger + // than window size, so here we must use the reminder instead of + // subtracting the single window size as WrapUp can do. So the result + // is always within the window. Since we add and not subtract here, + // reminder always provides the valid result in valid archives. + Filter.BlockStart=(Filter.BlockStart+UnpPtr)%MaxWinSize; + Filters.push_back(Filter); return true; } @@ -255,10 +279,10 @@ bool Unpack::UnpReadBuf() void Unpack::UnpWriteBuf() { size_t WrittenBorder=WrPtr; - size_t FullWriteSize=(UnpPtr-WrittenBorder)&MaxWinMask; + size_t FullWriteSize=WrapDown(UnpPtr-WrittenBorder); size_t WriteSizeLeft=FullWriteSize; bool NotAllFiltersProcessed=false; - for (size_t I=0;IBlockStart-WrPtr)&MaxWinMask)<=FullWriteSize) + // to next block and no further wrap arounds is possible. + if (WrapDown(flt->BlockStart-WrPtr)<=FullWriteSize) flt->NextWindow=false; continue; } - uint BlockStart=flt->BlockStart; + size_t BlockStart=flt->BlockStart; uint BlockLength=flt->BlockLength; - if (((BlockStart-WrittenBorder)&MaxWinMask)0) // We set it to 0 also for invalid filters. { - uint BlockEnd=(BlockStart+BlockLength)&MaxWinMask; + size_t BlockEnd=WrapUp(BlockStart+BlockLength); - FilterSrcMemory.Alloc(BlockLength); - byte *Mem=&FilterSrcMemory[0]; + FilterSrcMemory.resize(BlockLength); + byte *Mem=FilterSrcMemory.data(); if (BlockStartType!=FILTER_NONE) @@ -365,7 +389,7 @@ void Unpack::UnpWriteBuf() // Remove processed filters from queue. size_t EmptyCount=0; - for (size_t I=0;I0) Filters[I-EmptyCount]=Filters[I]; @@ -373,7 +397,7 @@ void Unpack::UnpWriteBuf() EmptyCount++; } if (EmptyCount>0) - Filters.Alloc(Filters.Size()-EmptyCount); + Filters.resize(Filters.size()-EmptyCount); if (!NotAllFiltersProcessed) // Only if all filters are processed. { @@ -385,12 +409,12 @@ void Unpack::UnpWriteBuf() // We prefer to write data in blocks not exceeding UNPACK_MAX_WRITE // instead of potentially huge MaxWinSize blocks. It also allows us // to keep the size of Filters array reasonable. - WriteBorder=(UnpPtr+Min(MaxWinSize,UNPACK_MAX_WRITE))&MaxWinMask; + WriteBorder=WrapUp(UnpPtr+Min(MaxWinSize,UNPACK_MAX_WRITE)); // Choose the nearest among WriteBorder and WrPtr actual written border. // If border is equal to UnpPtr, it means that we have MaxWinSize data ahead. if (WriteBorder==UnpPtr || - WrPtr!=UnpPtr && ((WrPtr-UnpPtr)&MaxWinMask)<((WriteBorder-UnpPtr)&MaxWinMask)) + WrPtr!=UnpPtr && WrapDown(WrPtr-UnpPtr)Channels,SrcPos=0; - FilterDstMemory.Alloc(DataSize); - byte *DstData=&FilterDstMemory[0]; + FilterDstMemory.resize(DataSize); + byte *DstData=FilterDstMemory.data(); // Bytes from same channels are grouped to continual data blocks, // so we need to place them back to their interleaving positions. @@ -492,13 +516,13 @@ void Unpack::UnpWriteArea(size_t StartPtr,size_t EndPtr) if (Fragmented) { - size_t SizeToWrite=(EndPtr-StartPtr) & MaxWinMask; + size_t SizeToWrite=WrapDown(EndPtr-StartPtr); while (SizeToWrite>0) { size_t BlockSize=FragWindow.GetBlockSize(StartPtr,SizeToWrite); UnpWriteData(&FragWindow[StartPtr],BlockSize); SizeToWrite-=BlockSize; - StartPtr=(StartPtr+BlockSize) & MaxWinMask; + StartPtr=WrapUp(StartPtr+BlockSize); } } else @@ -541,7 +565,7 @@ bool Unpack::ReadBlockHeader(BitInput &Inp,UnpackBlockHeader &Header) return false; Inp.faddbits((8-Inp.InBit)&7); - byte BlockFlags=Inp.fgetbits()>>8; + byte BlockFlags=byte(Inp.fgetbits()>>8); Inp.faddbits(8); uint ByteCount=((BlockFlags>>3)&3)+1; // Block size byte count. @@ -564,14 +588,24 @@ bool Unpack::ReadBlockHeader(BitInput &Inp,UnpackBlockHeader &Header) Header.BlockSize=BlockSize; byte CheckSum=byte(0x5a^BlockFlags^BlockSize^(BlockSize>>8)^(BlockSize>>16)); + + // 2024.01.04: In theory the valid block can have Header.BlockSize == 0 + // and Header.TablePresent == false in case the only block purpose is to + // store Header.LastBlockInFile flag if it didn't fit into previous block. + // So we do not reject Header.BlockSize == 0. Though currently RAR doesn't + // seem to issue such zero length blocks. if (CheckSum!=SavedCheckSum) return false; Header.BlockStart=Inp.InAddr; + + // We called Inp.faddbits(8) above, thus Header.BlockStart can't be 0 here. + // So there is no overflow even if Header.BlockSize is 0. ReadBorder=Min(ReadBorder,Header.BlockStart+Header.BlockSize-1); Header.LastBlockInFile=(BlockFlags & 0x40)!=0; Header.TablePresent=(BlockFlags & 0x80)!=0; + return true; } @@ -610,8 +644,8 @@ bool Unpack::ReadTables(BitInput &Inp,UnpackBlockHeader &Header,UnpackBlockTable MakeDecodeTables(BitLength,&Tables.BD,BC); - byte Table[HUFF_TABLE_SIZE]; - const uint TableSize=HUFF_TABLE_SIZE; + byte Table[HUFF_TABLE_SIZEX]; + const uint TableSize=ExtraDist ? HUFF_TABLE_SIZEX:HUFF_TABLE_SIZEB; for (uint I=0;IReadTop-5) @@ -674,14 +708,15 @@ bool Unpack::ReadTables(BitInput &Inp,UnpackBlockHeader &Header,UnpackBlockTable if (!Inp.ExternalBuffer && Inp.InAddr>ReadTop) return false; MakeDecodeTables(&Table[0],&Tables.LD,NC); - MakeDecodeTables(&Table[NC],&Tables.DD,DC); - MakeDecodeTables(&Table[NC+DC],&Tables.LDD,LDC); - MakeDecodeTables(&Table[NC+DC+LDC],&Tables.RD,RC); + uint DCodes=ExtraDist ? DCX : DCB; + MakeDecodeTables(&Table[NC],&Tables.DD,DCodes); + MakeDecodeTables(&Table[NC+DCodes],&Tables.LDD,LDC); + MakeDecodeTables(&Table[NC+DCodes+LDC],&Tables.RD,RC); return true; } void Unpack::InitFilters() { - Filters.SoftReset(); + Filters.clear(); } diff --git a/vendor/unrar/unpack50frag.cpp b/vendor/unrar/unpack50frag.cpp index 3c008ff245..9208405e04 100644 --- a/vendor/unrar/unpack50frag.cpp +++ b/vendor/unrar/unpack50frag.cpp @@ -2,6 +2,7 @@ FragmentedWindow::FragmentedWindow() { memset(Mem,0,sizeof(Mem)); memset(MemSize,0,sizeof(MemSize)); + LastAllocated=0; } @@ -13,6 +14,7 @@ FragmentedWindow::~FragmentedWindow() void FragmentedWindow::Reset() { + LastAllocated=0; for (uint I=0;IUnpPtr) + { + SrcPtr+=MaxWinSize; + + if (Distance>MaxWinSize || !FirstWinDone) + { + while (Length-- > 0) + { + (*this)[UnpPtr]=0; + if (++UnpPtr>=MaxWinSize) + UnpPtr-=MaxWinSize; + } + return; + } + } + while (Length-- > 0) { - (*this)[UnpPtr]=(*this)[SrcPtr++ & MaxWinMask]; - // We need to have masked UnpPtr after quit from loop, so it must not - // be replaced with '(*this)[UnpPtr++ & MaxWinMask]' - UnpPtr=(UnpPtr+1) & MaxWinMask; + (*this)[UnpPtr]=(*this)[SrcPtr]; + if (++SrcPtr>=MaxWinSize) + SrcPtr-=MaxWinSize; + if (++UnpPtr>=MaxWinSize) + UnpPtr-=MaxWinSize; } } diff --git a/vendor/unrar/unpack50mt.cpp b/vendor/unrar/unpack50mt.cpp index 82c9c4a8ce..3d3fde59c4 100644 --- a/vendor/unrar/unpack50mt.cpp +++ b/vendor/unrar/unpack50mt.cpp @@ -1,3 +1,5 @@ +// 2023.09.09: 0x400000 and 2 are optimal for i9-12900K. +// Further increasing the buffer size reduced the extraction speed. #define UNP_READ_SIZE_MT 0x400000 #define UNP_BLOCKS_PER_THREAD 2 @@ -277,7 +279,7 @@ void Unpack::Unpack5MT(bool Solid) } } } - UnpPtr&=MaxWinMask; // ProcessDecoded and maybe others can leave UnpPtr > MaxWinMask here. + UnpPtr=WrapUp(UnpPtr); // ProcessDecoded and maybe others can leave UnpPtr >= MaxWinSize here. UnpWriteBuf(); BlockHeader=UnpThreadData[LastBlockNum].BlockHeader; @@ -362,7 +364,8 @@ void Unpack::UnpackDecode(UnpackThreadData &D) { uint Length=SlotToLength(D.Inp,MainSlot-262); - uint DBits,Distance=1,DistSlot=DecodeNumber(D.Inp,&D.BlockTables.DD); + size_t Distance=1; + uint DBits,DistSlot=DecodeNumber(D.Inp,&D.BlockTables.DD); if (DistSlot<4) { DBits=0; @@ -371,7 +374,7 @@ void Unpack::UnpackDecode(UnpackThreadData &D) else { DBits=DistSlot/2 - 1; - Distance+=(2 | (DistSlot & 1)) << DBits; + Distance+=size_t(2 | (DistSlot & 1)) << DBits; } if (DBits>0) @@ -380,11 +383,23 @@ void Unpack::UnpackDecode(UnpackThreadData &D) { if (DBits>4) { - Distance+=((D.Inp.getbits32()>>(36-DBits))<<4); + // It is also possible to always use getbits64() here. + if (DBits>36) + Distance+=( ( size_t(D.Inp.getbits64() ) >> (68-DBits) ) << 4 ); + else + Distance+=( ( size_t(D.Inp.getbits32() ) >> (36-DBits) ) << 4 ); D.Inp.addbits(DBits-4); } uint LowDist=DecodeNumber(D.Inp,&D.BlockTables.LDD); Distance+=LowDist; + + // Distance can be 0 for multiples of 4 GB as result of size_t + // overflow in 32-bit build. Its lower 32-bit can also erroneously + // fit into dictionary after truncating upper 32-bits. Replace such + // invalid distances with -1, so CopyString sets 0 data for them. + // DBits>=30 also as DistSlot>=62 indicate distances >=0x80000001. + if (sizeof(Distance)==4 && DBits>=30) + Distance=(size_t)-1; } else { @@ -450,8 +465,12 @@ bool Unpack::ProcessDecoded(UnpackThreadData &D) UnpackDecodedItem *Item=D.Decoded,*Border=D.Decoded+D.DecodedSize; while (ItemUnpPtr); + PrevPtr=UnpPtr; + + if (WrapDown(WriteBorder-UnpPtr)<=MAX_INC_LZ_MATCH && WriteBorder!=UnpPtr) { UnpWriteBuf(); if (WrittenFileSize>DestUnpSize) @@ -469,7 +488,7 @@ bool Unpack::ProcessDecoded(UnpackThreadData &D) else #endif for (uint I=0;I<=Item->Length;I++) - Window[UnpPtr++ & MaxWinMask]=Item->Literal[I]; + Window[WrapUp(UnpPtr++)]=Item->Literal[I]; } else if (Item->Type==UNPDT_MATCH) @@ -481,8 +500,8 @@ bool Unpack::ProcessDecoded(UnpackThreadData &D) else if (Item->Type==UNPDT_REP) { - uint Distance=OldDist[Item->Distance]; - for (uint I=Item->Distance;I>0;I--) + size_t Distance=OldDist[Item->Distance]; + for (size_t I=Item->Distance;I>0;I--) OldDist[I]=OldDist[I-1]; OldDist[0]=Distance; LastLength=Item->Length; @@ -505,7 +524,7 @@ bool Unpack::ProcessDecoded(UnpackThreadData &D) Item++; Filter.Channels=(byte)Item->Length; - Filter.BlockLength=Item->Distance; + Filter.BlockLength=(uint)Item->Distance; AddFilter(Filter); } @@ -543,7 +562,11 @@ bool Unpack::UnpackLargeBlock(UnpackThreadData &D) while (true) { - UnpPtr&=MaxWinMask; + UnpPtr=WrapUp(UnpPtr); + + FirstWinDone|=(PrevPtr>UnpPtr); + PrevPtr=UnpPtr; + if (D.Inp.InAddr>=ReadBorder) { if (D.Inp.InAddr>BlockBorder || D.Inp.InAddr==BlockBorder && @@ -559,7 +582,7 @@ bool Unpack::UnpackLargeBlock(UnpackThreadData &D) break; } } - if (((WriteBorder-UnpPtr) & MaxWinMask)<=MAX_INC_LZ_MATCH && WriteBorder!=UnpPtr) + if (WrapDown(WriteBorder-UnpPtr)<=MAX_INC_LZ_MATCH && WriteBorder!=UnpPtr) { UnpWriteBuf(); if (WrittenFileSize>DestUnpSize) @@ -576,7 +599,8 @@ bool Unpack::UnpackLargeBlock(UnpackThreadData &D) { uint Length=SlotToLength(D.Inp,MainSlot-262); - uint DBits,Distance=1,DistSlot=DecodeNumber(D.Inp,&D.BlockTables.DD); + size_t Distance=1; + uint DBits,DistSlot=DecodeNumber(D.Inp,&D.BlockTables.DD); if (DistSlot<4) { DBits=0; @@ -585,7 +609,7 @@ bool Unpack::UnpackLargeBlock(UnpackThreadData &D) else { DBits=DistSlot/2 - 1; - Distance+=(2 | (DistSlot & 1)) << DBits; + Distance+=size_t(2 | (DistSlot & 1)) << DBits; } if (DBits>0) @@ -594,11 +618,23 @@ bool Unpack::UnpackLargeBlock(UnpackThreadData &D) { if (DBits>4) { - Distance+=((D.Inp.getbits32()>>(36-DBits))<<4); + // It is also possible to always use getbits64() here. + if (DBits>36) + Distance+=( ( size_t(D.Inp.getbits64() ) >> (68-DBits) ) << 4 ); + else + Distance+=( ( size_t(D.Inp.getbits32() ) >> (36-DBits) ) << 4 ); D.Inp.addbits(DBits-4); } uint LowDist=DecodeNumber(D.Inp,&D.BlockTables.LDD); Distance+=LowDist; + + // Distance can be 0 for multiples of 4 GB as result of size_t + // overflow in 32-bit build. Its lower 32-bit can also erroneously + // fit into dictionary after truncating upper 32-bits. Replace such + // invalid distances with -1, so CopyString sets 0 data for them. + // DBits>=30 also as DistSlot>=62 indicate distances >=0x80000001. + if (sizeof(Distance)==4 && DBits>=30) + Distance=(size_t)-1; } else { @@ -639,7 +675,7 @@ bool Unpack::UnpackLargeBlock(UnpackThreadData &D) if (MainSlot<262) { uint DistNum=MainSlot-258; - uint Distance=OldDist[DistNum]; + size_t Distance=OldDist[DistNum]; for (uint I=DistNum;I>0;I--) OldDist[I]=OldDist[I-1]; OldDist[0]=Distance; diff --git a/vendor/unrar/unpackinline.cpp b/vendor/unrar/unpackinline.cpp index 04c3d1f7dc..68aec9170d 100644 --- a/vendor/unrar/unpackinline.cpp +++ b/vendor/unrar/unpackinline.cpp @@ -1,4 +1,4 @@ -_forceinline void Unpack::InsertOldDist(uint Distance) +_forceinline void Unpack::InsertOldDist(size_t Distance) { OldDist[3]=OldDist[2]; OldDist[2]=OldDist[1]; @@ -6,23 +6,58 @@ _forceinline void Unpack::InsertOldDist(uint Distance) OldDist[0]=Distance; } -#ifdef _MSC_VER -#define FAST_MEMCPY +#if defined(LITTLE_ENDIAN) && defined(ALLOW_MISALIGNED) +#define UNPACK_COPY8 // We can copy 8 bytes at any position as uint64. #endif -_forceinline void Unpack::CopyString(uint Length,uint Distance) +_forceinline void Unpack::CopyString(uint Length,size_t Distance) { size_t SrcPtr=UnpPtr-Distance; + + // Perform the correction here instead of "else", so matches crossing + // the window beginning can also be processed by first "if" part. + if (Distance>UnpPtr) // Unlike SrcPtr>=MaxWinSize, it catches invalid distances like 0xfffffff0 in 32-bit build. + { + // Same as WrapDown(SrcPtr), needed because of UnpPtr-Distance above. + // We need the same condition below, so we expanded WrapDown() here. + SrcPtr+=MaxWinSize; + + // About Distance>MaxWinSize check. + // SrcPtr can be >=MaxWinSize if distance exceeds MaxWinSize + // in a malformed archive. Our WrapDown replacement above might not + // correct it, so to prevent out of bound Window read we check it here. + // Unlike SrcPtr>=MaxWinSize check, it allows MaxWinSize>0x80000000 + // in 32-bit build, which could cause overflow in SrcPtr. + // About !FirstWinDone check. + // If first window hasn't filled yet and it points outside of window, + // set data to 0 instead of copying preceding file data, so result doesn't + // depend on previously extracted files in non-solid archive. + if (Distance>MaxWinSize || !FirstWinDone) + { + // Fill area of specified length with 0 instead of returning. + // So if only the distance is broken and rest of packed data is valid, + // it preserves offsets and allows to continue extraction. + // If we set SrcPtr to random offset instead, let's say, 0, + // we still will be copying preceding file data if UnpPtr is also 0. + while (Length-- > 0) + { + Window[UnpPtr]=0; + UnpPtr=WrapUp(UnpPtr+1); + } + return; + } + } + if (SrcPtr=8) @@ -40,7 +75,7 @@ _forceinline void Unpack::CopyString(uint Length,uint Distance) Dest+=8; Length-=8; } -#ifdef FAST_MEMCPY +#ifdef UNPACK_COPY8 else while (Length>=8) { @@ -49,9 +84,7 @@ _forceinline void Unpack::CopyString(uint Length,uint Distance) // But for real RAR archives Distance <= MaxWinSize - MAX_INC_LZ_MATCH // always, so overlap here is impossible. - // This memcpy expanded inline by MSVC. We could also use uint64 - // assignment, which seems to provide about the same speed. - memcpy(Dest,Src,8); + RawPut8(RawGet8(Src),Dest); Src+=8; Dest+=8; @@ -71,10 +104,10 @@ _forceinline void Unpack::CopyString(uint Length,uint Distance) else while (Length-- > 0) // Slow copying with all possible precautions. { - Window[UnpPtr]=Window[SrcPtr++ & MaxWinMask]; + Window[UnpPtr]=Window[WrapUp(SrcPtr++)]; // We need to have masked UnpPtr after quit from loop, so it must not - // be replaced with 'Window[UnpPtr++ & MaxWinMask]' - UnpPtr=(UnpPtr+1) & MaxWinMask; + // be replaced with 'Window[WrapUp(UnpPtr++)]' + UnpPtr=WrapUp(UnpPtr+1); } } diff --git a/vendor/unrar/uowners.cpp b/vendor/unrar/uowners.cpp index 5eb1279027..cbe2f40440 100644 --- a/vendor/unrar/uowners.cpp +++ b/vendor/unrar/uowners.cpp @@ -2,18 +2,16 @@ void ExtractUnixOwner30(Archive &Arc,const wchar *FileName) { - char NameA[NM]; - WideToChar(FileName,NameA,ASIZE(NameA)); - - if (memchr(&Arc.SubHead.SubData[0],0,Arc.SubHead.SubData.Size())==NULL) + // There must be 0 byte between owner and group strings. + // Otherwise strlen call below wouldn't be safe. + if (memchr(Arc.SubHead.SubData.data(),0,Arc.SubHead.SubData.size())==NULL) return; - char *OwnerName=(char *)&Arc.SubHead.SubData[0]; + char *OwnerName=(char *)Arc.SubHead.SubData.data(); int OwnerSize=strlen(OwnerName)+1; - int GroupSize=Arc.SubHead.SubData.Size()-OwnerSize; - char GroupName[NM]; - strncpy(GroupName,(char *)&Arc.SubHead.SubData[OwnerSize],GroupSize); - GroupName[GroupSize]=0; + int GroupSize=Arc.SubHead.SubData.size()-OwnerSize; + char *GroupName=(char *)&Arc.SubHead.SubData[OwnerSize]; + std::string GroupStr(GroupName,GroupName+GroupSize); struct passwd *pw; if ((pw=getpwnam(OwnerName))==NULL) @@ -25,7 +23,7 @@ void ExtractUnixOwner30(Archive &Arc,const wchar *FileName) uid_t OwnerID=pw->pw_uid; struct group *gr; - if ((gr=getgrnam(GroupName))==NULL) + if ((gr=getgrnam(GroupStr.c_str()))==NULL) { uiMsg(UIERROR_UOWNERGETGROUPID,Arc.FileName,GetWide(GroupName)); ErrHandler.SetErrorCode(RARX_WARNING); @@ -33,10 +31,14 @@ void ExtractUnixOwner30(Archive &Arc,const wchar *FileName) } uint Attr=GetFileAttr(FileName); gid_t GroupID=gr->gr_gid; + + std::string NameA; + WideToChar(FileName,NameA); + #if defined(SAVE_LINKS) && !defined(_APPLE) - if (lchown(NameA,OwnerID,GroupID)!=0) + if (lchown(NameA.c_str(),OwnerID,GroupID)!=0) #else - if (chown(NameA,OwnerID,GroupID)!=0) + if (chown(NameA.c_str(),OwnerID,GroupID)!=0) #endif { uiMsg(UIERROR_UOWNERSET,Arc.FileName,FileName); @@ -46,11 +48,8 @@ void ExtractUnixOwner30(Archive &Arc,const wchar *FileName) } -void SetUnixOwner(Archive &Arc,const wchar *FileName) +void SetUnixOwner(Archive &Arc,const std::wstring &FileName) { - char NameA[NM]; - WideToChar(FileName,NameA,ASIZE(NameA)); - // First, we try to resolve symbolic names. If they are missing or cannot // be resolved, we try to use numeric values if any. If numeric values // are missing too, function fails. @@ -85,10 +84,14 @@ void SetUnixOwner(Archive &Arc,const wchar *FileName) else hd.UnixGroupID=gr->gr_gid; } + + std::string NameA; + WideToChar(FileName,NameA); + #if defined(SAVE_LINKS) && !defined(_APPLE) - if (lchown(NameA,hd.UnixOwnerID,hd.UnixGroupID)!=0) + if (lchown(NameA.c_str(),hd.UnixOwnerID,hd.UnixGroupID)!=0) #else - if (chown(NameA,hd.UnixOwnerID,hd.UnixGroupID)!=0) + if (chown(NameA.c_str(),hd.UnixOwnerID,hd.UnixGroupID)!=0) #endif { uiMsg(UIERROR_UOWNERSET,Arc.FileName,FileName); diff --git a/vendor/unrar/version.hpp b/vendor/unrar/version.hpp index e968fcd7b5..6987a9afb7 100644 --- a/vendor/unrar/version.hpp +++ b/vendor/unrar/version.hpp @@ -1,6 +1,6 @@ -#define RARVER_MAJOR 6 -#define RARVER_MINOR 24 -#define RARVER_BETA 1 -#define RARVER_DAY 17 -#define RARVER_MONTH 9 -#define RARVER_YEAR 2023 +#define RARVER_MAJOR 7 +#define RARVER_MINOR 1 +#define RARVER_BETA 0 +#define RARVER_DAY 12 +#define RARVER_MONTH 5 +#define RARVER_YEAR 2024 diff --git a/vendor/unrar/volume.cpp b/vendor/unrar/volume.cpp index 4924d8d0ea..e17151559d 100644 --- a/vendor/unrar/volume.cpp +++ b/vendor/unrar/volume.cpp @@ -1,8 +1,8 @@ #include "rar.hpp" #ifdef RARDLL -static bool DllVolChange(CommandData *Cmd,wchar *NextName,size_t NameSize); -static bool DllVolNotify(CommandData *Cmd,wchar *NextName); +bool DllVolChange(CommandData *Cmd,std::wstring &NextName); +static bool DllVolNotify(CommandData *Cmd,const std::wstring &NextName); #endif @@ -35,9 +35,8 @@ bool MergeArchive(Archive &Arc,ComprDataIO *DataIO,bool ShowFileName,wchar Comma Arc.Close(); - wchar NextName[NM]; - wcsncpyz(NextName,Arc.FileName,ASIZE(NextName)); - NextVolumeName(NextName,ASIZE(NextName),!Arc.NewNumbering); + std::wstring NextName=Arc.FileName; + NextVolumeName(NextName,!Arc.NewNumbering); #if !defined(SFX_MODULE) && !defined(RARDLL) bool RecoveryDone=false; @@ -56,7 +55,7 @@ bool MergeArchive(Archive &Arc,ComprDataIO *DataIO,bool ShowFileName,wchar Comma // the next file might not be fully decoded yet. They write chunks of data // and then close the file again until the next chunk comes in. - if (Cmd->VolumePause && !uiAskNextVolume(NextName,ASIZE(NextName))) + if (Cmd->VolumePause && !uiAskNextVolume(NextName)) FailedOpen=true; #endif @@ -76,18 +75,17 @@ bool MergeArchive(Archive &Arc,ComprDataIO *DataIO,bool ShowFileName,wchar Comma { // Checking for new style volumes renamed by user to old style // name format. Some users did it for unknown reason. - wchar AltNextName[NM]; - wcsncpyz(AltNextName,Arc.FileName,ASIZE(AltNextName)); - NextVolumeName(AltNextName,ASIZE(AltNextName),true); + std::wstring AltNextName=Arc.FileName; + NextVolumeName(AltNextName,true); OldSchemeTested=true; if (Arc.Open(AltNextName,OpenMode)) { - wcsncpyz(NextName,AltNextName,ASIZE(NextName)); + NextName=AltNextName; break; } } #ifdef RARDLL - if (!DllVolChange(Cmd,NextName,ASIZE(NextName))) + if (!DllVolChange(Cmd,NextName)) { FailedOpen=true; break; @@ -109,7 +107,7 @@ bool MergeArchive(Archive &Arc,ComprDataIO *DataIO,bool ShowFileName,wchar Comma break; } #ifndef SILENT - if (Cmd->AllYes || !uiAskNextVolume(NextName,ASIZE(NextName))) + if (Cmd->AllYes || !uiAskNextVolume(NextName)) #endif { FailedOpen=true; @@ -128,7 +126,7 @@ bool MergeArchive(Archive &Arc,ComprDataIO *DataIO,bool ShowFileName,wchar Comma } if (Command=='T' || Command=='X' || Command=='E') - mprintf(St(Command=='T' ? MTestVol:MExtrVol),Arc.FileName); + mprintf(St(Command=='T' ? MTestVol:MExtrVol),Arc.FileName.c_str()); Arc.CheckArc(true); @@ -158,7 +156,7 @@ bool MergeArchive(Archive &Arc,ComprDataIO *DataIO,bool ShowFileName,wchar Comma } if (ShowFileName && !Cmd->DisableNames) { - mprintf(St(MExtrPoints),Arc.FileHead.FileName); + mprintf(St(MExtrPoints),Arc.FileHead.FileName.c_str()); if (!Cmd->DisablePercentage) mprintf(L" "); } @@ -190,45 +188,65 @@ bool MergeArchive(Archive &Arc,ComprDataIO *DataIO,bool ShowFileName,wchar Comma #ifdef RARDLL -bool DllVolChange(CommandData *Cmd,wchar *NextName,size_t NameSize) +bool DllVolChange(CommandData *Cmd,std::wstring &NextName) { bool DllVolChanged=false,DllVolAborted=false; if (Cmd->Callback!=NULL) { - wchar OrgNextName[NM]; - wcsncpyz(OrgNextName,NextName,ASIZE(OrgNextName)); - if (Cmd->Callback(UCM_CHANGEVOLUMEW,Cmd->UserData,(LPARAM)NextName,RAR_VOL_ASK)==-1) + std::wstring OrgNextName=NextName; + + std::vector NameBuf(MAXPATHSIZE); + std::copy(NextName.data(), NextName.data() + NextName.size() + 1, NameBuf.begin()); + + if (Cmd->Callback(UCM_CHANGEVOLUMEW,Cmd->UserData,(LPARAM)NameBuf.data(),RAR_VOL_ASK)==-1) DllVolAborted=true; else - if (wcscmp(OrgNextName,NextName)!=0) + { + NextName=NameBuf.data(); + if (OrgNextName!=NextName) DllVolChanged=true; else { - char NextNameA[NM],OrgNextNameA[NM]; - WideToChar(NextName,NextNameA,ASIZE(NextNameA)); - strncpyz(OrgNextNameA,NextNameA,ASIZE(OrgNextNameA)); - if (Cmd->Callback(UCM_CHANGEVOLUME,Cmd->UserData,(LPARAM)NextNameA,RAR_VOL_ASK)==-1) + std::string NextNameA; + WideToChar(NextName,NextNameA); + std::string OrgNextNameA=NextNameA; + + std::vector NameBufA(MAXPATHSIZE); + std::copy(NextNameA.data(), NextNameA.data() + NextNameA.size() + 1, NameBufA.begin()); + + if (Cmd->Callback(UCM_CHANGEVOLUME,Cmd->UserData,(LPARAM)NameBufA.data(),RAR_VOL_ASK)==-1) DllVolAborted=true; else - if (strcmp(OrgNextNameA,NextNameA)!=0) + { + NextNameA=NameBufA.data(); + if (OrgNextNameA!=NextNameA) { // We can damage some Unicode characters by U->A->U conversion, // so set Unicode name only if we see that ANSI name is changed. - CharToWide(NextNameA,NextName,NameSize); + CharToWide(NextNameA,NextName); DllVolChanged=true; } + } } + } } if (!DllVolChanged && Cmd->ChangeVolProc!=NULL) { - char NextNameA[NM]; - WideToChar(NextName,NextNameA,ASIZE(NextNameA)); - int RetCode=Cmd->ChangeVolProc(NextNameA,RAR_VOL_ASK); + std::string NextNameA; + WideToChar(NextName,NextNameA); + + std::vector NameBufA(MAXPATHSIZE); + std::copy(NextNameA.data(), NextNameA.data() + NextNameA.size() + 1, NameBufA.begin()); + + int RetCode=Cmd->ChangeVolProc(NameBufA.data(),RAR_VOL_ASK); if (RetCode==0) DllVolAborted=true; else - CharToWide(NextNameA,NextName,NameSize); + { + NextNameA=NameBufA.data(); + CharToWide(NextNameA,NextName); + } } // We quit only on 'abort' condition, but not on 'name not changed'. @@ -246,20 +264,21 @@ bool DllVolChange(CommandData *Cmd,wchar *NextName,size_t NameSize) #ifdef RARDLL -bool DllVolNotify(CommandData *Cmd,wchar *NextName) +static bool DllVolNotify(CommandData *Cmd,const std::wstring &NextName) { - char NextNameA[NM]; - WideToChar(NextName,NextNameA,ASIZE(NextNameA)); + std::string NextNameA; + WideToChar(NextName,NextNameA); + if (Cmd->Callback!=NULL) { - if (Cmd->Callback(UCM_CHANGEVOLUMEW,Cmd->UserData,(LPARAM)NextName,RAR_VOL_NOTIFY)==-1) + if (Cmd->Callback(UCM_CHANGEVOLUMEW,Cmd->UserData,(LPARAM)NextName.data(),RAR_VOL_NOTIFY)==-1) return false; - if (Cmd->Callback(UCM_CHANGEVOLUME,Cmd->UserData,(LPARAM)NextNameA,RAR_VOL_NOTIFY)==-1) + if (Cmd->Callback(UCM_CHANGEVOLUME,Cmd->UserData,(LPARAM)NextNameA.data(),RAR_VOL_NOTIFY)==-1) return false; } if (Cmd->ChangeVolProc!=NULL) { - int RetCode=Cmd->ChangeVolProc(NextNameA,RAR_VOL_NOTIFY); + int RetCode=Cmd->ChangeVolProc((char *)NextNameA.data(),RAR_VOL_NOTIFY); if (RetCode==0) return false; } diff --git a/vendor/unrar/win32acl.cpp b/vendor/unrar/win32acl.cpp index d4797bde09..36cb8525ef 100644 --- a/vendor/unrar/win32acl.cpp +++ b/vendor/unrar/win32acl.cpp @@ -5,7 +5,7 @@ static bool ReadSacl=false; #ifndef SFX_MODULE -void ExtractACL20(Archive &Arc,const wchar *FileName) +void ExtractACL20(Archive &Arc,const std::wstring &FileName) { SetACLPrivileges(); @@ -27,7 +27,7 @@ void ExtractACL20(Archive &Arc,const wchar *FileName) Unpack Unpack(&DataIO); Unpack.Init(0x10000,false); - Array UnpData(Arc.EAHead.UnpSize); + std::vector UnpData(Arc.EAHead.UnpSize); DataIO.SetUnpackToMemory(&UnpData[0],Arc.EAHead.UnpSize); DataIO.SetPackedSizeToRead(Arc.EAHead.DataSize); DataIO.EnableShowProgress(false); @@ -49,7 +49,7 @@ void ExtractACL20(Archive &Arc,const wchar *FileName) si|=SACL_SECURITY_INFORMATION; SECURITY_DESCRIPTOR *sd=(SECURITY_DESCRIPTOR *)&UnpData[0]; - int SetCode=SetFileSecurity(FileName,si,sd); + int SetCode=SetFileSecurity(FileName.c_str(),si,sd); if (!SetCode) { @@ -64,9 +64,9 @@ void ExtractACL20(Archive &Arc,const wchar *FileName) #endif -void ExtractACL(Archive &Arc,const wchar *FileName) +void ExtractACL(Archive &Arc,const std::wstring &FileName) { - Array SubData; + std::vector SubData; if (!Arc.ReadSubData(&SubData,NULL,false)) return; @@ -78,12 +78,12 @@ void ExtractACL(Archive &Arc,const wchar *FileName) si|=SACL_SECURITY_INFORMATION; SECURITY_DESCRIPTOR *sd=(SECURITY_DESCRIPTOR *)&SubData[0]; - int SetCode=SetFileSecurity(FileName,si,sd); + int SetCode=SetFileSecurity(FileName.c_str(),si,sd); if (!SetCode) { - wchar LongName[NM]; - if (GetWinLongPath(FileName,LongName,ASIZE(LongName))) - SetCode=SetFileSecurity(LongName,si,sd); + std::wstring LongName; + if (GetWinLongPath(FileName,LongName)) + SetCode=SetFileSecurity(LongName.c_str(),si,sd); } if (!SetCode) diff --git a/vendor/unrar/win32lnk.cpp b/vendor/unrar/win32lnk.cpp index 759c49003f..677c27357c 100644 --- a/vendor/unrar/win32lnk.cpp +++ b/vendor/unrar/win32lnk.cpp @@ -40,26 +40,24 @@ bool CreateReparsePoint(CommandData *Cmd,const wchar *Name,FileHeader *hd) PrivSet=true; } - const DWORD BufSize=sizeof(REPARSE_DATA_BUFFER)+2*NM*sizeof(wchar)+1024; - Array Buf(BufSize); - REPARSE_DATA_BUFFER *rdb=(REPARSE_DATA_BUFFER *)&Buf[0]; - - wchar SubstName[NM]; - wcsncpyz(SubstName,hd->RedirName,ASIZE(SubstName)); - size_t SubstLength=wcslen(SubstName); - - wchar PrintName[NM],*PrintNameSrc=SubstName,*PrintNameDst=PrintName; - bool WinPrefix=wcsncmp(PrintNameSrc,L"\\??\\",4)==0; - if (WinPrefix) - PrintNameSrc+=4; - if (WinPrefix && wcsncmp(PrintNameSrc,L"UNC\\",4)==0) - { - *(PrintNameDst++)='\\'; // Insert second \ in beginning of share name. - PrintNameSrc+=3; - } - wcscpy(PrintNameDst,PrintNameSrc); + const std::wstring &SubstName=hd->RedirName; + size_t SubstLength=SubstName.size(); + + // REPARSE_DATA_BUFFER receives both SubstName and PrintName strings, + // thus "*2" below. PrintName is either shorter or same length as SubstName. + const DWORD BufSize=sizeof(REPARSE_DATA_BUFFER)+((DWORD)SubstLength+1)*2*sizeof(wchar); + + std::vector Buf(BufSize); + REPARSE_DATA_BUFFER *rdb=(REPARSE_DATA_BUFFER *)Buf.data(); - size_t PrintLength=wcslen(PrintName); + // Remove \??\ NTFS junction prefix of present. + bool WinPrefix=SubstName.rfind(L"\\??\\",0)!=std::wstring::npos; + std::wstring PrintName=WinPrefix ? SubstName.substr(4):SubstName; + + if (WinPrefix && PrintName.rfind(L"UNC\\",0)!=std::wstring::npos) + PrintName=L"\\"+PrintName.substr(3); // Convert UNC\server\share to \\server\share. + + size_t PrintLength=PrintName.size(); bool AbsPath=WinPrefix; // IsFullPath is not really needed here, AbsPath check is enough. @@ -69,7 +67,11 @@ bool CreateReparsePoint(CommandData *Cmd,const wchar *Name,FileHeader *hd) // path as a prefix, which can confuse IsRelativeSymlinkSafe algorithm. if (!Cmd->AbsoluteLinks && (AbsPath || IsFullPath(hd->RedirName) || !IsRelativeSymlinkSafe(Cmd,hd->FileName,Name,hd->RedirName))) + { + uiMsg(UIERROR_SKIPUNSAFELINK,hd->FileName,hd->RedirName); + ErrHandler.SetErrorCode(RARX_WARNING); return false; + } CreatePath(Name,true,Cmd->DisableNames); @@ -86,9 +88,9 @@ bool CreateReparsePoint(CommandData *Cmd,const wchar *Name,FileHeader *hd) // Unix symlinks do not have their own 'directory' attribute. if (hd->Dir || hd->DirTarget) { - if (!CreateDirectory(Name,NULL)) + if (!CreateDir(Name)) { - uiMsg(UIERROR_DIRCREATE,UINULL,Name); + uiMsg(UIERROR_DIRCREATE,L"",Name); ErrHandler.SetErrorCode(RARX_CREATE); return false; } @@ -118,11 +120,11 @@ bool CreateReparsePoint(CommandData *Cmd,const wchar *Name,FileHeader *hd) rdb->MountPointReparseBuffer.SubstituteNameOffset=0; rdb->MountPointReparseBuffer.SubstituteNameLength=USHORT(SubstLength*sizeof(WCHAR)); - wcscpy(rdb->MountPointReparseBuffer.PathBuffer,SubstName); + wcscpy(rdb->MountPointReparseBuffer.PathBuffer,SubstName.data()); rdb->MountPointReparseBuffer.PrintNameOffset=USHORT((SubstLength+1)*sizeof(WCHAR)); rdb->MountPointReparseBuffer.PrintNameLength=USHORT(PrintLength*sizeof(WCHAR)); - wcscpy(rdb->MountPointReparseBuffer.PathBuffer+SubstLength+1,PrintName); + wcscpy(rdb->MountPointReparseBuffer.PathBuffer+SubstLength+1,PrintName.data()); } else if (hd->RedirType==FSREDIR_WINSYMLINK || hd->RedirType==FSREDIR_UNIXSYMLINK) @@ -139,11 +141,11 @@ bool CreateReparsePoint(CommandData *Cmd,const wchar *Name,FileHeader *hd) rdb->SymbolicLinkReparseBuffer.SubstituteNameOffset=0; rdb->SymbolicLinkReparseBuffer.SubstituteNameLength=USHORT(SubstLength*sizeof(WCHAR)); - wcscpy(rdb->SymbolicLinkReparseBuffer.PathBuffer,SubstName); + wcscpy(rdb->SymbolicLinkReparseBuffer.PathBuffer,SubstName.data()); rdb->SymbolicLinkReparseBuffer.PrintNameOffset=USHORT((SubstLength+1)*sizeof(WCHAR)); rdb->SymbolicLinkReparseBuffer.PrintNameLength=USHORT(PrintLength*sizeof(WCHAR)); - wcscpy(rdb->SymbolicLinkReparseBuffer.PathBuffer+SubstLength+1,PrintName); + wcscpy(rdb->SymbolicLinkReparseBuffer.PathBuffer+SubstLength+1,PrintName.data()); rdb->SymbolicLinkReparseBuffer.Flags=AbsPath ? 0:SYMLINK_FLAG_RELATIVE; } @@ -166,7 +168,7 @@ bool CreateReparsePoint(CommandData *Cmd,const wchar *Name,FileHeader *hd) rdb->ReparseDataLength,NULL,0,&Returned,NULL)) { CloseHandle(hFile); - uiMsg(UIERROR_SLINKCREATE,UINULL,Name); + uiMsg(UIERROR_SLINKCREATE,L"",Name); DWORD LastError=GetLastError(); if ((LastError==ERROR_ACCESS_DENIED || LastError==ERROR_PRIVILEGE_NOT_HELD) && diff --git a/vendor/unrar/win32stm.cpp b/vendor/unrar/win32stm.cpp index 3b77d2a452..0c9c72a4a3 100644 --- a/vendor/unrar/win32stm.cpp +++ b/vendor/unrar/win32stm.cpp @@ -2,7 +2,7 @@ #ifdef _WIN_ALL // StreamName must include the leading ':'. -static bool IsNtfsReservedStream(const wchar *StreamName) +static bool IsNtfsReservedStream(const std::wstring &StreamName) { const wchar *Reserved[]{ L"::$ATTRIBUTE_LIST",L"::$BITMAP",L"::$DATA",L"::$EA",L"::$EA_INFORMATION", @@ -19,7 +19,7 @@ static bool IsNtfsReservedStream(const wchar *StreamName) #if !defined(SFX_MODULE) && defined(_WIN_ALL) -void ExtractStreams20(Archive &Arc,const wchar *FileName) +void ExtractStreams20(Archive &Arc,const std::wstring &FileName) { if (Arc.BrokenHeader) { @@ -35,39 +35,39 @@ void ExtractStreams20(Archive &Arc,const wchar *FileName) return; } - wchar StreamName[NM+2]; - if (FileName[0]!=0 && FileName[1]==0) + std::wstring StreamName; + if (FileName.size()==1) { // Convert single character names like f:stream to .\f:stream to // resolve the ambiguity with drive letters. - wcsncpyz(StreamName,L".\\",ASIZE(StreamName)); - wcsncatz(StreamName,FileName,ASIZE(StreamName)); + StreamName=L".\\"+FileName; } else - wcsncpyz(StreamName,FileName,ASIZE(StreamName)); - if (wcslen(StreamName)+strlen(Arc.StreamHead.StreamName)>=ASIZE(StreamName) || - Arc.StreamHead.StreamName[0]!=':') + StreamName=FileName; + if (Arc.StreamHead.StreamName[0]!=':') { uiMsg(UIERROR_STREAMBROKEN,Arc.FileName,FileName); ErrHandler.SetErrorCode(RARX_CRC); return; } - wchar StoredName[NM]; - CharToWide(Arc.StreamHead.StreamName,StoredName,ASIZE(StoredName)); - ConvertPath(StoredName+1,StoredName+1,ASIZE(StoredName)-1); + std::wstring StoredName; + // "substr(1)" to exclude ':', so we can use ConvertPath() below. + CharToWide(Arc.StreamHead.StreamName.substr(1),StoredName); + ConvertPath(&StoredName,&StoredName); + StoredName=L":"+StoredName; if (IsNtfsReservedStream(StoredName)) return; - wcsncatz(StreamName,StoredName,ASIZE(StreamName)); + StreamName+=StoredName; - FindData fd; - bool Found=FindFile::FastFind(FileName,&fd); + FindData FD; + bool Found=FindFile::FastFind(FileName,&FD); - if ((fd.FileAttr & FILE_ATTRIBUTE_READONLY)!=0) - SetFileAttr(FileName,fd.FileAttr & ~FILE_ATTRIBUTE_READONLY); + if ((FD.FileAttr & FILE_ATTRIBUTE_READONLY)!=0) + SetFileAttr(FileName,FD.FileAttr & ~FILE_ATTRIBUTE_READONLY); File CurFile; if (CurFile.WCreate(StreamName)) @@ -93,31 +93,29 @@ void ExtractStreams20(Archive &Arc,const wchar *FileName) } File HostFile; if (Found && HostFile.Open(FileName,FMF_OPENSHARED|FMF_UPDATE)) - SetFileTime(HostFile.GetHandle(),&fd.ftCreationTime,&fd.ftLastAccessTime, - &fd.ftLastWriteTime); - if ((fd.FileAttr & FILE_ATTRIBUTE_READONLY)!=0) - SetFileAttr(FileName,fd.FileAttr); + SetFileTime(HostFile.GetHandle(),&FD.ftCreationTime,&FD.ftLastAccessTime, + &FD.ftLastWriteTime); + if ((FD.FileAttr & FILE_ATTRIBUTE_READONLY)!=0) + SetFileAttr(FileName,FD.FileAttr); } #endif #ifdef _WIN_ALL -void ExtractStreams(Archive &Arc,const wchar *FileName,bool TestMode) +void ExtractStreams(Archive &Arc,const std::wstring &FileName,bool TestMode) { - wchar FullName[NM+2]; + std::wstring FullName; if (FileName[0]!=0 && FileName[1]==0) { // Convert single character names like f:stream to .\f:stream to // resolve the ambiguity with drive letters. - wcsncpyz(FullName,L".\\",ASIZE(FullName)); - wcsncatz(FullName,FileName,ASIZE(FullName)); + FullName=L".\\"+FileName; } else - wcsncpyz(FullName,FileName,ASIZE(FullName)); + FullName=FileName; - wchar StreamName[NM]; - GetStreamNameNTFS(Arc,StreamName,ASIZE(StreamName)); - if (*StreamName!=':') + std::wstring StreamName=GetStreamNameNTFS(Arc); + if (StreamName[0]!=':') { uiMsg(UIERROR_STREAMBROKEN,Arc.FileName,FileName); ErrHandler.SetErrorCode(RARX_CRC); @@ -131,17 +129,17 @@ void ExtractStreams(Archive &Arc,const wchar *FileName,bool TestMode) return; } - wcsncatz(FullName,StreamName,ASIZE(FullName)); + FullName+=StreamName; if (IsNtfsReservedStream(StreamName)) return; - FindData fd; - bool HostFound=FindFile::FastFind(FileName,&fd); + FindData FD; + bool HostFound=FindFile::FastFind(FileName,&FD); - if ((fd.FileAttr & FILE_ATTRIBUTE_READONLY)!=0) - SetFileAttr(FileName,fd.FileAttr & ~FILE_ATTRIBUTE_READONLY); + if ((FD.FileAttr & FILE_ATTRIBUTE_READONLY)!=0) + SetFileAttr(FileName,FD.FileAttr & ~FILE_ATTRIBUTE_READONLY); File CurFile; if (CurFile.WCreate(FullName)) @@ -153,32 +151,26 @@ void ExtractStreams(Archive &Arc,const wchar *FileName,bool TestMode) // Restoring original file timestamps. File HostFile; if (HostFound && HostFile.Open(FileName,FMF_OPENSHARED|FMF_UPDATE)) - SetFileTime(HostFile.GetHandle(),&fd.ftCreationTime,&fd.ftLastAccessTime, - &fd.ftLastWriteTime); + SetFileTime(HostFile.GetHandle(),&FD.ftCreationTime,&FD.ftLastAccessTime, + &FD.ftLastWriteTime); // Restoring original file attributes. Important if file was read only // or did not have "Archive" attribute - SetFileAttr(FileName,fd.FileAttr); + SetFileAttr(FileName,FD.FileAttr); } #endif -void GetStreamNameNTFS(Archive &Arc,wchar *StreamName,size_t MaxSize) +std::wstring GetStreamNameNTFS(Archive &Arc) { - byte *Data=&Arc.SubHead.SubData[0]; - size_t DataSize=Arc.SubHead.SubData.Size(); + std::wstring Dest; if (Arc.Format==RARFMT15) - { - size_t DestSize=Min(DataSize/2,MaxSize-1); - RawToWide(Data,StreamName,DestSize); - StreamName[DestSize]=0; - } + Dest=RawToWide(Arc.SubHead.SubData); else { - char UtfString[NM*4]; - size_t DestSize=Min(DataSize,ASIZE(UtfString)-1); - memcpy(UtfString,Data,DestSize); - UtfString[DestSize]=0; - UtfToWide(UtfString,StreamName,MaxSize); + std::vector Src=Arc.SubHead.SubData; + Src.push_back(0); // Needed for our UtfToWide. + UtfToWide((char *)Src.data(),Dest); } + return Dest; } diff --git a/vendor/zip/ioapi.h b/vendor/zip/ioapi.h index c588a18d03..a2d2e6e60d 100644 --- a/vendor/zip/ioapi.h +++ b/vendor/zip/ioapi.h @@ -144,7 +144,7 @@ typedef long (ZCALLBACK *tell_file_func) (voidpf opaque, voidpf stream) typedef long (ZCALLBACK *seek_file_func) (voidpf opaque, voidpf stream, uLong offset, int origin); -/* here is the "old" 32 bits structure structure */ +/* here is the "old" 32 bits structure */ typedef struct zlib_filefunc_def_s { open_file_func zopen_file; diff --git a/vendor/zip/iowin32.c b/vendor/zip/iowin32.c index 08536e94b8..49f5ba1b18 100644 --- a/vendor/zip/iowin32.c +++ b/vendor/zip/iowin32.c @@ -89,7 +89,7 @@ static voidpf win32_build_iowin(HANDLE hFile) { } voidpf ZCALLBACK win32_open64_file_func(voidpf opaque, const void* filename, int mode) { - const char* mode_fopen = NULL; + (void)opaque; DWORD dwDesiredAccess,dwCreationDisposition,dwShareMode,dwFlagsAndAttributes ; HANDLE hFile = NULL; @@ -117,7 +117,7 @@ voidpf ZCALLBACK win32_open64_file_func(voidpf opaque, const void* filename, int voidpf ZCALLBACK win32_open64_file_funcA(voidpf opaque, const void* filename, int mode) { - const char* mode_fopen = NULL; + (void)opaque; DWORD dwDesiredAccess,dwCreationDisposition,dwShareMode,dwFlagsAndAttributes ; HANDLE hFile = NULL; @@ -140,7 +140,7 @@ voidpf ZCALLBACK win32_open64_file_funcA(voidpf opaque, const void* filename, in voidpf ZCALLBACK win32_open64_file_funcW(voidpf opaque, const void* filename, int mode) { - const char* mode_fopen = NULL; + (void)opaque; DWORD dwDesiredAccess,dwCreationDisposition,dwShareMode,dwFlagsAndAttributes ; HANDLE hFile = NULL; @@ -159,7 +159,7 @@ voidpf ZCALLBACK win32_open64_file_funcW(voidpf opaque, const void* filename, in voidpf ZCALLBACK win32_open_file_func(voidpf opaque, const char* filename, int mode) { - const char* mode_fopen = NULL; + (void)opaque; DWORD dwDesiredAccess,dwCreationDisposition,dwShareMode,dwFlagsAndAttributes ; HANDLE hFile = NULL; @@ -187,6 +187,7 @@ voidpf ZCALLBACK win32_open_file_func(voidpf opaque, const char* filename, int m uLong ZCALLBACK win32_read_file_func(voidpf opaque, voidpf stream, void* buf,uLong size) { + (void)opaque; uLong ret=0; HANDLE hFile = NULL; if (stream!=NULL) @@ -208,6 +209,7 @@ uLong ZCALLBACK win32_read_file_func(voidpf opaque, voidpf stream, void* buf,uLo uLong ZCALLBACK win32_write_file_func(voidpf opaque, voidpf stream, const void* buf, uLong size) { + (void)opaque; uLong ret=0; HANDLE hFile = NULL; if (stream!=NULL) @@ -247,6 +249,7 @@ static BOOL MySetFilePointerEx(HANDLE hFile, LARGE_INTEGER pos, LARGE_INTEGER *n } long ZCALLBACK win32_tell_file_func(voidpf opaque, voidpf stream) { + (void)opaque; long ret=-1; HANDLE hFile = NULL; if (stream!=NULL) @@ -269,6 +272,7 @@ long ZCALLBACK win32_tell_file_func(voidpf opaque, voidpf stream) { } ZPOS64_T ZCALLBACK win32_tell64_file_func(voidpf opaque, voidpf stream) { + (void)opaque; ZPOS64_T ret= (ZPOS64_T)-1; HANDLE hFile = NULL; if (stream!=NULL) @@ -293,6 +297,7 @@ ZPOS64_T ZCALLBACK win32_tell64_file_func(voidpf opaque, voidpf stream) { long ZCALLBACK win32_seek_file_func(voidpf opaque, voidpf stream, uLong offset, int origin) { + (void)opaque; DWORD dwMoveMethod=0xFFFFFFFF; HANDLE hFile = NULL; @@ -330,6 +335,7 @@ long ZCALLBACK win32_seek_file_func(voidpf opaque, voidpf stream, uLong offset, } long ZCALLBACK win32_seek64_file_func(voidpf opaque, voidpf stream, ZPOS64_T offset, int origin) { + (void)opaque; DWORD dwMoveMethod=0xFFFFFFFF; HANDLE hFile = NULL; long ret=-1; @@ -368,6 +374,7 @@ long ZCALLBACK win32_seek64_file_func(voidpf opaque, voidpf stream, ZPOS64_T off } int ZCALLBACK win32_close_file_func(voidpf opaque, voidpf stream) { + (void)opaque; int ret=-1; if (stream!=NULL) @@ -385,6 +392,7 @@ int ZCALLBACK win32_close_file_func(voidpf opaque, voidpf stream) { } int ZCALLBACK win32_error_file_func(voidpf opaque, voidpf stream) { + (void)opaque; int ret=-1; if (stream!=NULL) { diff --git a/vendor/zip/mztools.c b/vendor/zip/mztools.c index c8d2375615..f86c1e71b0 100644 --- a/vendor/zip/mztools.c +++ b/vendor/zip/mztools.c @@ -5,6 +5,9 @@ */ /* Code */ +#ifndef _CRT_SECURE_NO_WARNINGS +# define _CRT_SECURE_NO_WARNINGS +#endif #include #include #include @@ -140,28 +143,28 @@ extern int ZEXPORT unzRepair(const char* file, const char* fileOut, const char* /* Central directory entry */ { - char header[46]; + char central[46]; char* comment = ""; int comsize = (int) strlen(comment); - WRITE_32(header, 0x02014b50); - WRITE_16(header + 4, version); - WRITE_16(header + 6, version); - WRITE_16(header + 8, gpflag); - WRITE_16(header + 10, method); - WRITE_16(header + 12, filetime); - WRITE_16(header + 14, filedate); - WRITE_32(header + 16, crc); - WRITE_32(header + 20, cpsize); - WRITE_32(header + 24, uncpsize); - WRITE_16(header + 28, fnsize); - WRITE_16(header + 30, extsize); - WRITE_16(header + 32, comsize); - WRITE_16(header + 34, 0); /* disk # */ - WRITE_16(header + 36, 0); /* int attrb */ - WRITE_32(header + 38, 0); /* ext attrb */ - WRITE_32(header + 42, currentOffset); + WRITE_32(central, 0x02014b50); + WRITE_16(central + 4, version); + WRITE_16(central + 6, version); + WRITE_16(central + 8, gpflag); + WRITE_16(central + 10, method); + WRITE_16(central + 12, filetime); + WRITE_16(central + 14, filedate); + WRITE_32(central + 16, crc); + WRITE_32(central + 20, cpsize); + WRITE_32(central + 24, uncpsize); + WRITE_16(central + 28, fnsize); + WRITE_16(central + 30, extsize); + WRITE_16(central + 32, comsize); + WRITE_16(central + 34, 0); /* disk # */ + WRITE_16(central + 36, 0); /* int attrb */ + WRITE_32(central + 38, 0); /* ext attrb */ + WRITE_32(central + 42, currentOffset); /* Header */ - if (fwrite(header, 1, 46, fpOutCD) == 46) { + if (fwrite(central, 1, 46, fpOutCD) == 46) { offsetCD += 46; /* Filename */ @@ -215,23 +218,23 @@ extern int ZEXPORT unzRepair(const char* file, const char* fileOut, const char* /* Final central directory */ { int entriesZip = entries; - char header[22]; + char end[22]; char* comment = ""; // "ZIP File recovered by zlib/minizip/mztools"; int comsize = (int) strlen(comment); if (entriesZip > 0xffff) { entriesZip = 0xffff; } - WRITE_32(header, 0x06054b50); - WRITE_16(header + 4, 0); /* disk # */ - WRITE_16(header + 6, 0); /* disk # */ - WRITE_16(header + 8, entriesZip); /* hack */ - WRITE_16(header + 10, entriesZip); /* hack */ - WRITE_32(header + 12, offsetCD); /* size of CD */ - WRITE_32(header + 16, offset); /* offset to CD */ - WRITE_16(header + 20, comsize); /* comment */ + WRITE_32(end, 0x06054b50); + WRITE_16(end + 4, 0); /* disk # */ + WRITE_16(end + 6, 0); /* disk # */ + WRITE_16(end + 8, entriesZip); /* hack */ + WRITE_16(end + 10, entriesZip); /* hack */ + WRITE_32(end + 12, offsetCD); /* size of CD */ + WRITE_32(end + 16, offset); /* offset to CD */ + WRITE_16(end + 20, comsize); /* comment */ /* Header */ - if (fwrite(header, 1, 22, fpOutCD) == 22) { + if (fwrite(end, 1, 22, fpOutCD) == 22) { /* Comment field */ if (comsize > 0) { diff --git a/vendor/zip/skipset.h b/vendor/zip/skipset.h new file mode 100644 index 0000000000..381aa13a80 --- /dev/null +++ b/vendor/zip/skipset.h @@ -0,0 +1,360 @@ +// skipset.h -- set operations using a skiplist +// Copyright (C) 2024 Mark Adler +// See MiniZip_info.txt for the license. + +// This implements a skiplist set, i.e. just keys, no data, with ~O(log n) time +// insert and search operations. The application defines the type of a key, and +// provides a function to compare two keys. + +// This header is not definitions of functions found in another source file -- +// it creates the set functions, with the application's key type, right where +// the #include is. Before this header is #included, these must be defined: +// +// 1. A macro or typedef for set_key_t, the type of a key. +// 2. A macro or function set_cmp(a, b) to compare two keys. The return values +// are < 0 for a < b, 0 for a == b, and > 0 for a > b. +// 3. A macro or function set_drop(s, k) to release the key k's resources, if +// any, when doing a set_end() or set_clear(). s is a pointer to the set +// that key is in, for use with set_free() if desired. +// +// Example usage: +// +// typedef int set_key_t; +// #define set_cmp(a, b) ((a) < (b) ? -1 : (a) == (b) ? 0 : 1) +// #define set_drop(s, k) +// #include "skipset.h" +// +// int test(void) { // return 0: good, 1: bad, -1: out of memory +// set_t set; +// if (setjmp(set.env)) +// return -1; +// set_start(&set); +// set_insert(&set, 2); +// set_insert(&set, 1); +// set_insert(&set, 7); +// int bad = !set_found(&set, 2); +// bad = bad || set_found(&set, 5); +// set_end(&set); +// return bad; +// } +// +// Interface summary (see more details below): +// - set_t is the type of the set being operated on (a set_t pointer is passed) +// - set_start() initializes a new, empty set (initialize set.env first) +// - set_insert() inserts a new key into the set, or not if it's already there +// - set_found() determines whether or not a key is in the set +// - set_end() ends the use of the set, freeing all memory +// - set_clear() empties the set, equivalent to set_end() and then set_start() +// - set_ok() checks if set appears to be usable, i.e. started and not ended +// +// Auxiliary functions available to the application: +// - set_alloc() allocates memory with optional tracking (#define SET_TRACK) +// - set_free() deallocates memory allocated by set_alloc() +// - set_rand() returns 32 random bits (seeded by set_start()) + +#ifndef SKIPSET_H +#define SKIPSET_H + +#include // realloc(), free(), NULL, size_t +#include // jmp_buf, longjmp() +#include // ENOMEM +#include // int16_t, uint32_t, uint64_t +#include // time(), clock() +#include // assert.h + +// Structures and functions below noted as "--private--" should not be used by +// the application. set_t is partially private and partially public -- see the +// comments there. + +// There is no POSIX random() in MSVC, and rand() is awful. For portability, we +// cannot rely on a library function for random numbers. Instead we use the +// fast and effective algorithm below, invented by Melissa O'Neill. + +// *Really* minimal PCG32 code / (c) 2014 M.E. O'Neill / www.pcg-random.org +// Licensed under Apache License 2.0 (NO WARRANTY, etc. see website) +// --private-- Random number generator state. +typedef struct { + uint64_t state; // 64-bit generator state + uint64_t inc; // 63-bit sequence id +} set_rand_t; +// --private-- Initialize the state *gen using seed and seq. seed seeds the +// advancing 64-bit state. seq is a sequence selection constant. +void set_seed(set_rand_t *gen, uint64_t seed, uint64_t seq) { + gen->inc = (seq << 1) | 1; + gen->state = (seed + gen->inc) * 6364136223846793005ULL + gen->inc; +} +// Return 32 random bits, advancing the state *gen. +uint32_t set_rand(set_rand_t *gen) { + uint64_t state = gen->state; + gen->state = state * 6364136223846793005ULL + gen->inc; + uint32_t mix = (uint32_t)(((state >> 18) ^ state) >> 27); + int rot = state >> 59; + return (mix >> rot) | (mix << ((-rot) & 31)); +} +// End of PCG32 code. + +// --private-- Linked-list node. +typedef struct set_node_s set_node_t; +struct set_node_s { + set_key_t key; // the key (not used for head or path) + int16_t size; // number of allocated pointers in right[] + int16_t fill; // number of pointers in right[] filled in + set_node_t **right; // pointer for each level, each to the right +}; + +// A set. The application sets env, may use gen with set_rand(), and may read +// allocs and memory. The remaining variables are --private-- . +typedef struct set_s { + set_node_t *head; // skiplist head -- no key, just links + set_node_t *path; // right[] is path to key from set_found() + set_node_t *node; // node under construction, in case of longjmp() + int16_t depth; // maximum depth of the skiplist + uint64_t ran; // a precious trove of random bits + set_rand_t gen; // random number generator state + jmp_buf env; // setjmp() environment for allocation errors +#ifdef SET_TRACK + size_t allocs; // number of allocations + size_t memory; // total amount of allocated memory (>= requests) +#endif +} set_t; + +// Memory allocation and deallocation. set_alloc(set, ptr, size) returns a +// pointer to an allocation of size bytes if ptr is NULL, or the previous +// allocation ptr resized to size bytes. set_alloc() will never return NULL. +// set_free(set, ptr) frees an allocation created by set_alloc(). These may be +// used by the application. e.g. if allocation tracking is desired. +#ifdef SET_TRACK +// Track the number of allocations and the total backing memory size. +# if defined(_WIN32) +# include +# define SET_ALLOC_SIZE(ptr) _msize(ptr) +# elif defined(__MACH__) +# include +# define SET_ALLOC_SIZE(ptr) malloc_size(ptr) +# elif defined(__linux__) +# include +# define SET_ALLOC_SIZE(ptr) malloc_usable_size(ptr) +# elif defined(__FreeBSD__) +# include +# define SET_ALLOC_SIZE(ptr) malloc_usable_size(ptr) +# elif defined(__NetBSD__) +# include +# define SET_ALLOC_SIZE(ptr) malloc_usable_size(ptr) +# else // e.g. OpenBSD +# define SET_ALLOC_SIZE(ptr) 0 +# endif +// With tracking. +void *set_alloc(set_t *set, void *ptr, size_t size) { + size_t had = ptr == NULL ? 0 : SET_ALLOC_SIZE(ptr); + void *mem = realloc(ptr, size); + if (mem == NULL) + longjmp(set->env, ENOMEM); + set->allocs += ptr == NULL; + set->memory += SET_ALLOC_SIZE(mem) - had; + return mem; +} +void set_free(set_t *set, void *ptr) { + if (ptr != NULL) { + set->allocs--; + set->memory -= SET_ALLOC_SIZE(ptr); + free(ptr); + } +} +#else +// Without tracking. +void *set_alloc(set_t *set, void *ptr, size_t size) { + void *mem = realloc(ptr, size); + if (mem == NULL) + longjmp(set->env, ENOMEM); + return mem; +} +void set_free(set_t *set, void *ptr) { + (void)set; + free(ptr); +} +#endif + +// --private-- Grow node's array right[] as needed to be able to hold at least +// want links. If fill is true, assure that the first want links are filled in, +// setting them to set->head if not previously filled in. Otherwise it is +// assumed that the first want links are about to be filled in. +void set_grow(set_t *set, set_node_t *node, int want, int fill) { + if (node->size < want) { + int more = node->size ? node->size : 1; + while (more < want) + more <<= 1; + node->right = set_alloc(set, node->right, more * sizeof(set_node_t *)); + node->size = (int16_t)more; + } + int i; + if (fill) + for (i = node->fill; i < want; i++) + node->right[i] = set->head; + node->fill = (int16_t)want; +} + +// --private-- Return a new node. key is left uninitialized. +set_node_t *set_node(set_t *set) { + set_node_t *node = set_alloc(set, NULL, sizeof(set_node_t)); + node->size = 0; + node->fill = 0; + node->right = NULL; + return node; +} + +// --private-- Free the list linked from head, along with the keys. +void set_sweep(set_t *set) { + set_node_t *step = set->head->right[0]; + while (step != set->head) { + set_node_t *next = step->right[0]; // save link to next node + set_drop(set, step->key); + set_free(set, step->right); + set_free(set, step); + step = next; + } +} + +// Initialize a new set. set->env must be initialized using setjmp() before +// set_start() is called. A longjmp(set->env, ENOMEM) will be used to handle a +// memory allocation failure during any of the operations. (See setjmp.h and +// errno.h.) The set can still be used if this happens, assuming that it didn't +// happen during set_start(). Whether set_start() completed or not, set_end() +// can be used to free the set's memory after a longjmp(). +void set_start(set_t *set) { +#ifdef SET_TRACK + set->allocs = 0; + set->memory = 0; +#endif + set->head = set->path = set->node = NULL; // in case set_node() fails + set->path = set_node(set); + set->head = set_node(set); + set_grow(set, set->head, 1, 1); // one link back to head for an empty set + *(unsigned char *)&set->head->key = 137; // set id + set->depth = 0; + set_seed(&set->gen, ((uint64_t)(uintptr_t)set << 32) ^ + ((uint64_t)time(NULL) << 12) ^ clock(), 0); + set->ran = 1; +} + +// Return true if *set appears to be in a usable state. If *set has been zeroed +// out, then set_ok(set) will be false and set_end(set) will be safe. +int set_ok(set_t *set) { + return set->head != NULL && + set->head->right != NULL && + *(unsigned char *)&set->head->key == 137; +} + +// Empty the set. This frees the memory used for the previous set contents. +// After set_clear(), *set is ready for use, as if after a set_start(). +void set_clear(set_t *set) { + assert(set_ok(set) && "improper use"); + + // Free all the keys and their nodes. + set_sweep(set); + + // Leave the head and path allocations as is. Clear their contents, with + // head pointing to itself and setting depth to zero, for an empty set. + set->head->right[0] = set->head; + set->head->fill = 1; + set->path->fill = 0; + set->depth = 0; +} + +// Done using the set -- free all allocations. The only operation on *set +// permitted after this is set_start(). Though another set_end() would do no +// harm. This can be done at any time after a set_start(), or after a longjmp() +// on any allocation failure, including during a set_start(). +void set_end(set_t *set) { + if (set->head != NULL) { + // Empty the set and free the head node. + if (set->head->right != NULL) { + set_sweep(set); + set_free(set, set->head->right); + } + set_free(set, set->head); + set->head = NULL; + } + if (set->path != NULL) { + // Free the path work area. + set_free(set, set->path->right); + set_free(set, set->path); + set->path = NULL; + } + if (set->node != NULL) { + // Free the node that was under construction when longjmp() hit. + set_drop(set, set->node->key); + set_free(set, set->node->right); + set_free(set, set->node); + set->node = NULL; + } +} + +// Look for key. Return 1 if found or 0 if not. This also puts the path to get +// there in set->path, for use by set_insert(). +int set_found(set_t *set, set_key_t key) { + assert(set_ok(set) && "improper use"); + + // Start at depth and work down and right as determined by key comparisons. + set_node_t *head = set->head, *here = head; + int i = set->depth; + set_grow(set, set->path, i + 1, 0); + do { + while (here->right[i] != head && + set_cmp(here->right[i]->key, key) < 0) + here = here->right[i]; + set->path->right[i] = here; + } while (i--); + + // See if the key matches. + here = here->right[0]; + return here != head && set_cmp(here->key, key) == 0; +} + +// Insert the key key. Return 0 on success, or 1 if key is already in the set. +int set_insert(set_t *set, set_key_t key) { + assert(set_ok(set) && "improper use"); + + if (set_found(set, key)) + // That key is already in the set. + return 1; + + // Randomly generate a new level-- level 0 with probability 1/2, 1 with + // probability 1/4, 2 with probability 1/8, etc. + int level = 0; + for (;;) { + if (set->ran == 1) + // Ran out. Get another 32 random bits. + set->ran = set_rand(&set->gen) | (1ULL << 32); + int bit = set->ran & 1; + set->ran >>= 1; + if (bit) + break; + assert(level < 32767 && + "Overhead, without any fuss, the stars were going out."); + level++; + } + if (level > set->depth) { + // The maximum depth is now deeper. Update the structures. + set_grow(set, set->path, level + 1, 1); + set_grow(set, set->head, level + 1, 1); + set->depth = (int16_t)level; + } + + // Make a new node for the provided key, and insert it in the lists up to + // and including level. + set->node = set_node(set); + set->node->key = key; + set_grow(set, set->node, level + 1, 0); + int i; + for (i = 0; i <= level; i++) { + set->node->right[i] = set->path->right[i]->right[i]; + set->path->right[i]->right[i] = set->node; + } + set->node = NULL; + return 0; +} + +#else +#error ** another skiplist set already created here +// Would need to implement a prefix in order to support multiple sets. +#endif diff --git a/vendor/zip/unzip.c b/vendor/zip/unzip.c index ed763f89f1..a2ee14bdd4 100644 --- a/vendor/zip/unzip.c +++ b/vendor/zip/unzip.c @@ -68,10 +68,6 @@ #include #include -#ifndef NOUNCRYPT - #define NOUNCRYPT -#endif - #include "zlib.h" #include "unzip.h" @@ -92,7 +88,7 @@ #ifndef CASESENSITIVITYDEFAULT_NO -# if !defined(unix) && !defined(CASESENSITIVITYDEFAULT_YES) +# if (!defined(__unix__) && !defined(__unix) || defined(__CYGWIN__)) && !defined(CASESENSITIVITYDEFAULT_YES) # define CASESENSITIVITYDEFAULT_NO # endif #endif @@ -117,7 +113,7 @@ const char unz_copyright[] = " unzip 1.01 Copyright 1998-2004 Gilles Vollant - http://www.winimage.com/zLibDll"; -/* unz_file_info_interntal contain internal info about a file in zipfile*/ +/* unz_file_info64_internal contain internal info about a file in zipfile*/ typedef struct unz_file_info64_internal_s { ZPOS64_T offset_curfile;/* relative offset of local header 8 bytes */ @@ -450,7 +446,7 @@ local ZPOS64_T unz64local_SearchCentralDir64(const zlib_filefunc64_32_def* pzlib if (unz64local_getLong(pzlib_filefunc_def,filestream,&uL)!=UNZ_OK) return CENTRALDIRINVALID; - /* number of the disk with the start of the zip64 end of central directory */ + /* number of the disk with the start of the zip64 end of central directory */ if (unz64local_getLong(pzlib_filefunc_def,filestream,&uL)!=UNZ_OK) return CENTRALDIRINVALID; if (uL != 0) @@ -497,9 +493,9 @@ local unzFile unzOpenInternal(const void *path, ZPOS64_T central_pos; uLong uL; - uLong number_disk; /* number of the current dist, used for + uLong number_disk; /* number of the current disk, used for spanning ZIP, unsupported, always 0*/ - uLong number_disk_with_CD; /* number the the disk with central dir, used + uLong number_disk_with_CD; /* number the disk with central dir, used for spanning ZIP, unsupported, always 0*/ ZPOS64_T number_entry_CD; /* total number of entries in the central dir @@ -1613,7 +1609,7 @@ extern int ZEXPORT unzReadCurrentFile(unzFile file, voidp buf, unsigned len) { uInt i; for(i=0;iread_buffer[i] = - zdecode(s->keys,s->pcrc_32_tab, + (char)zdecode(s->keys,s->pcrc_32_tab, pfile_in_zip_read_info->read_buffer[i]); } # endif diff --git a/vendor/zip/unzip.h b/vendor/zip/unzip.h index 14105840f6..ceb614e783 100644 --- a/vendor/zip/unzip.h +++ b/vendor/zip/unzip.h @@ -306,13 +306,17 @@ extern int ZEXPORT unzGetCurrentFileInfo(unzFile file, Get Info about the current file if pfile_info!=NULL, the *pfile_info structure will contain some info about the current file - if szFileName!=NULL, the filemane string will be copied in szFileName + if szFileName!=NULL, the filename string will be copied in szFileName (fileNameBufferSize is the size of the buffer) if extraField!=NULL, the extra field information will be copied in extraField (extraFieldBufferSize is the size of the buffer). This is the Central-header version of the extra field if szComment!=NULL, the comment string of the file will be copied in szComment (commentBufferSize is the size of the buffer) + The file name and comment will be zero-terminated if there is room in the + provided buffer. Otherwise the buffer will contain as much as will fit. If at + least 65537 bytes of room is provided, then the result will always be + complete and zero-terminated. */ diff --git a/vendor/zip/zip.c b/vendor/zip/zip.c index 0446109b26..cbb250843e 100644 --- a/vendor/zip/zip.c +++ b/vendor/zip/zip.c @@ -123,6 +123,19 @@ typedef struct linkedlist_data_s } linkedlist_data; +// zipAlreadyThere() set functions for a set of zero-terminated strings, and +// a block_t type for reading the central directory datablocks. +typedef char const *set_key_t; +#define set_cmp(a, b) strcmp(a, b) +#define set_drop(s, k) set_free(s, (void *)(intptr_t)(k)) +#include "skipset.h" +typedef struct { + unsigned char *next; // next byte in datablock data + size_t left; // number of bytes left in data (at least) + linkedlist_datablock_internal *node; // current datablock +} block_t; + + typedef struct { z_stream stream; /* zLib stream structure for inflate */ @@ -174,6 +187,10 @@ typedef struct char *globalcomment; #endif + // Support for zipAlreadyThere(). + set_t set; // set for detecting name collisions + block_t block; // block for reading the central directory + } zip64_internal; @@ -264,6 +281,223 @@ local int add_data_in_datablock(linkedlist_data* ll, const void* buf, uLong len) return ZIP_OK; } +// zipAlreadyThere() operations. "set" in the zip internal structure keeps the +// set of names that are in the under-construction central directory so far. A +// skipset provides ~O(log n) time insertion and searching. Central directory +// records, stored in a linked list of allocated memory datablocks, is read +// through "block" in the zip internal structure. + +// The block_*() functions support extracting the central directory file names +// from the datablocks. They are designed to support a growing directory by +// automatically continuing once more data has been appended to the linked +// datablocks. + +// Initialize *block to the head of list. This should only be called once the +// list has at least some data in it, i.e. list->first_block is not NULL. +local void block_init(block_t *block, linkedlist_data *list) { + block->node = list->first_block; + block->next = block->node->data; + block->left = block->node->filled_in_this_block; +} + +// Mark *block as bad, with all subsequent reads returning end, even if more +// data is added to the datablocks. This is invoked if the central directory is +// invalid, so there is no longer any point in attempting to interpret it. +local void block_stop(block_t *block) { + block->left = 0; + block->next = NULL; +} + +// Return true if *block has reached the end of the data in the datablocks. +local int block_end(block_t *block) { + linkedlist_datablock_internal *node = block->node; + if (node == NULL) + // This block was previously terminated with extreme prejudice. + return 1; + if (block->next < node->data + node->filled_in_this_block) + // There are more bytes to read in the current datablock. + return 0; + while (node->next_datablock != NULL) { + if (node->filled_in_this_block != 0) + // There are some bytes in a later datablock. + return 0; + node = node->next_datablock; + } + // Reached the end of the list of datablocks. There's nothing. + return 1; +} + +// Return one byte from *block, or -1 if the end is reached. +local int block_get(block_t *block) { + while (block->left == 0) { + if (block->node == NULL) + // We've been marked bad. Return end. + return -1; + // Update left in case more was filled in since we were last here. + block->left = block->node->filled_in_this_block - + (block->next - block->node->data); + if (block->left != 0) + // There was indeed more data appended in the current datablock. + break; + if (block->node->next_datablock == NULL) + // No more data here, and there is no next datablock. At the end. + return -1; + // Try the next datablock for more data. + block->node = block->node->next_datablock; + block->next = block->node->data; + block->left = block->node->filled_in_this_block; + } + // We have a byte to return. + block->left--; + return *block->next++; +} + +// Return a 16-bit unsigned little-endian value from block, or a negative value +// if the end is reached. +local long block_get2(block_t *block) { + long got = block_get(block); + return got | ((unsigned long)block_get(block) << 8); +} + +// Read up to len bytes from block into buf. Return the number of bytes read. +local size_t block_read(block_t *block, unsigned char *buf, size_t len) { + size_t need = len; + while (need) { + if (block->left == 0) { + // Get a byte to update and step through the linked list as needed. + int got = block_get(block); + if (got == -1) + // Reached the end. + break; + *buf++ = (unsigned char)got; + need--; + continue; + } + size_t take = need > block->left ? block->left : need; + memcpy(buf, block->next, take); + block->next += take; + block->left -= take; + buf += take; + need -= take; + } + return len - need; // return the number of bytes copied +} + +// Skip n bytes in block. Return 0 on success or -1 if there are less than n +// bytes to the end. +local int block_skip(block_t *block, size_t n) { + while (n > block->left) { + n -= block->left; + block->next += block->left; + block->left = 0; + if (block_get(block) == -1) + return -1; + n--; + } + block->next += n; + block->left -= n; + return 0; +} + +// Process the next central directory record at *block. Return the allocated, +// zero-terminated file name, or NULL for end of input or invalid data. If +// invalid, *block is marked bad. This uses *set for the allocation of memory. +local char *block_central_name(block_t *block, set_t *set) { + char *name = NULL; + for (;;) { + if (block_end(block)) + // At the end of the central directory (so far). + return NULL; + + // Check for a central directory record signature. + if (block_get2(block) != (CENTRALHEADERMAGIC & 0xffff) || + block_get2(block) != (CENTRALHEADERMAGIC >> 16)) + // Incorrect signature. + break; + + // Go through the remaining fixed-length portion of the record, + // extracting the lengths of the three variable-length fields. + block_skip(block, 24); + unsigned flen = block_get2(block); // file name length + unsigned xlen = block_get2(block); // extra field length + unsigned clen = block_get2(block); // comment field length + if (block_skip(block, 12) == -1) + // Premature end of the record. + break; + + // Extract the name and skip over the extra and comment fields. + name = set_alloc(set, NULL, flen + 1); + if (block_read(block, (unsigned char *)name, flen) < flen || + block_skip(block, xlen + clen) == -1) + // Premature end of the record. + break; + + // Check for embedded nuls in the name. + if (memchr(name, 0, flen) != NULL) { + // This name can never match the zero-terminated name provided to + // zipAlreadyThere(), so we discard it and go back to get another + // name. (Who the heck is putting nuls inside their zip file entry + // names anyway?) + set_free(set, name); + continue; + } + + // All good. Return the zero-terminated file name. + name[flen] = 0; + return name; + } + + // Invalid signature or premature end of the central directory record. + // Abandon trying to process the central directory. + set_free(set, name); + block_stop(block); + return NULL; +} + +// Return 0 if name is not in the central directory so far, 1 if it is, -1 if +// the central directory is invalid, -2 if out of memory, or ZIP_PARAMERROR if +// file is NULL. +extern int ZEXPORT zipAlreadyThere(zipFile file, char const *name) { + zip64_internal *zip = file; + if (zip == NULL) + return ZIP_PARAMERROR; + if (zip->central_dir.first_block == NULL) + // No central directory yet, so no, name isn't there. + return 0; + if (setjmp(zip->set.env)) { + // Memory allocation failure. + set_end(&zip->set); + return -2; + } + if (!set_ok(&zip->set)) { + // This is the first time here with some central directory content. We + // construct this set of names only on demand. Prepare set and block. + set_start(&zip->set); + block_init(&zip->block, &zip->central_dir); + } + + // Update the set of names from the current central directory contents. + // This reads any new central directory records since the last time we were + // here. + for (;;) { + char *there = block_central_name(&zip->block, &zip->set); + if (there == NULL) { + if (zip->block.next == NULL) + // The central directory is invalid. + return -1; + break; + } + + // Add there to the set. + if (set_insert(&zip->set, there)) + // There's already a duplicate in the central directory! We'll just + // let this be and carry on. + set_free(&zip->set, there); + } + + // Return true if name is in the central directory. + return set_found(&zip->set, name); +} /****************************************************************************/ @@ -551,7 +785,7 @@ local ZPOS64_T zip64local_SearchCentralDir64(const zlib_filefunc64_32_def* pzlib for (i=(int)uReadSize-3; (i--)>0;) { - // Signature "0x07064b50" Zip64 end of central directory locater + // Signature "0x07064b50" Zip64 end of central directory locator if (((*(buf+i))==0x50) && ((*(buf+i+1))==0x4b) && ((*(buf+i+2))==0x06) && ((*(buf+i+3))==0x07)) { uPosFound = uReadPos+(unsigned)i; @@ -575,7 +809,7 @@ local ZPOS64_T zip64local_SearchCentralDir64(const zlib_filefunc64_32_def* pzlib if (zip64local_getLong(pzlib_filefunc_def,filestream,&uL)!=ZIP_OK) return 0; - /* number of the disk with the start of the zip64 end of central directory */ + /* number of the disk with the start of the zip64 end of central directory */ if (zip64local_getLong(pzlib_filefunc_def,filestream,&uL)!=ZIP_OK) return 0; if (uL != 0) @@ -614,9 +848,9 @@ local int LoadCentralDirectoryRecord(zip64_internal* pziinit) { ZPOS64_T central_pos; uLong uL; - uLong number_disk; /* number of the current dist, used for + uLong number_disk; /* number of the current disk, used for spanning ZIP, unsupported, always 0*/ - uLong number_disk_with_CD; /* number the the disk with central dir, used + uLong number_disk_with_CD; /* number of the disk with central dir, used for spanning ZIP, unsupported, always 0*/ ZPOS64_T number_entry; ZPOS64_T number_entry_CD; /* total number of entries in @@ -843,6 +1077,7 @@ extern zipFile ZEXPORT zipOpen3(const void *pathname, int append, zipcharpc* glo ziinit.number_entry = 0; ziinit.add_position_when_writing_offset = 0; init_linkedlist(&(ziinit.central_dir)); + memset(&ziinit.set, 0, sizeof(set_t)); // make sure set appears dormant @@ -1027,7 +1262,6 @@ extern int ZEXPORT zipOpenNewFileInZip4_64(zipFile file, const char* filename, c int err = ZIP_OK; # ifdef NOCRYPT - (crcForCrypting); if (password != NULL) return ZIP_PARAMERROR; # endif @@ -1608,7 +1842,7 @@ extern int ZEXPORT zipCloseFileInZipRaw64(zipFile file, ZPOS64_T uncompressed_si if((uLong)(datasize + 4) > zi->ci.size_centralExtraFree) { - // we can not write more data to the buffer that we have room for. + // we cannot write more data to the buffer that we have room for. return ZIP_BADZIPFILE; } @@ -1871,8 +2105,10 @@ extern int ZEXPORT zipClose(zipFile file, const char* global_comment) { } free_linkedlist(&(zi->central_dir)); + set_end(&zi->set); // set was zeroed, so this is safe + pos = centraldir_pos_inzip - zi->add_position_when_writing_offset; - if(pos >= 0xffffffff || zi->number_entry > 0xFFFF) + if(pos >= 0xffffffff || zi->number_entry >= 0xFFFF) { ZPOS64_T Zip64EOCDpos = ZTELL64(zi->z_filefunc,zi->filestream); Write_Zip64EndOfCentralDirectoryRecord(zi, size_centraldir, centraldir_pos_inzip); diff --git a/vendor/zip/zip.h b/vendor/zip/zip.h index 5fc0841324..1f7f0b263d 100644 --- a/vendor/zip/zip.h +++ b/vendor/zip/zip.h @@ -35,7 +35,7 @@ See header of zip.h -*/ + */ #ifndef _zip12_H #define _zip12_H @@ -127,12 +127,12 @@ extern zipFile ZEXPORT zipOpen64(const void *pathname, int append); If the zipfile cannot be opened, the return value is NULL. Else, the return value is a zipFile Handle, usable with other function of this zip package. -*/ + */ /* Note : there is no delete function into a zipfile. If you want delete file into a zipfile, you must open a zipfile, and create another Of course, you can use RAW reading and writing to copy the file you did not want delete -*/ + */ extern zipFile ZEXPORT zipOpen2(const char *pathname, int append, @@ -177,16 +177,16 @@ extern int ZEXPORT zipOpenNewFileInZip64(zipFile file, filename : the filename in zip (if NULL, '-' without quote will be used *zipfi contain supplemental information if extrafield_local!=NULL and size_extrafield_local>0, extrafield_local - contains the extrafield data the the local header + contains the extrafield data for the local header if extrafield_global!=NULL and size_extrafield_global>0, extrafield_global - contains the extrafield data the the local header + contains the extrafield data for the global header if comment != NULL, comment contain the comment string method contain the compression method (0 for store, Z_DEFLATED for deflate) level contain the level of compression (can be Z_DEFAULT_COMPRESSION) zip64 is set to 1 if a zip64 extended information block should be added to the local file header. this MUST be '1' if the uncompressed size is >= 0xffffffff. -*/ + */ extern int ZEXPORT zipOpenNewFileInZip2(zipFile file, @@ -311,12 +311,12 @@ extern int ZEXPORT zipWriteInFileInZip(zipFile file, unsigned len); /* Write data in the zipfile -*/ + */ extern int ZEXPORT zipCloseFileInZip(zipFile file); /* Close the current file in the zipfile -*/ + */ extern int ZEXPORT zipCloseFileInZipRaw(zipFile file, uLong uncompressed_size, @@ -326,17 +326,23 @@ extern int ZEXPORT zipCloseFileInZipRaw64(zipFile file, ZPOS64_T uncompressed_size, uLong crc32); +extern int ZEXPORT zipAlreadyThere(zipFile file, + char const* name); +/* + See if name is already in file's central directory. + */ + /* Close the current file in the zipfile, for file opened with parameter raw=1 in zipOpenNewFileInZip2 uncompressed_size and crc32 are value for the uncompressed size -*/ + */ extern int ZEXPORT zipClose(zipFile file, const char* global_comment); /* Close the zipfile -*/ + */ extern int ZEXPORT zipRemoveExtraInfoBlock(char* pData, int* dataLen, short sHeader); @@ -355,7 +361,7 @@ extern int ZEXPORT zipRemoveExtraInfoBlock(char* pData, int* dataLen, short sHea Remove ZIP64 Extra information from a Local File Header extra field data zipRemoveExtraInfoBlock(pLocalHeaderExtraFieldData, &nLocalHeaderExtraFieldDataLen, 0x0001); -*/ + */ #ifdef __cplusplus } diff --git a/vendor/zlib/deflate.c b/vendor/zlib/deflate.c index bd01175192..cbdd880bd6 100644 --- a/vendor/zlib/deflate.c +++ b/vendor/zlib/deflate.c @@ -1,5 +1,5 @@ /* deflate.c -- compress data using the deflation algorithm - * Copyright (C) 1995-2023 Jean-loup Gailly and Mark Adler + * Copyright (C) 1995-2024 Jean-loup Gailly and Mark Adler * For conditions of distribution and use, see copyright notice in zlib.h */ @@ -52,7 +52,7 @@ #include "deflate.h" const char deflate_copyright[] = - " deflate 1.3 Copyright 1995-2023 Jean-loup Gailly and Mark Adler "; + " deflate 1.3.1.1 Copyright 1995-2024 Jean-loup Gailly and Mark Adler "; /* If you use the zlib library in a product, an acknowledgment is welcome in the documentation of your product. If for some reason you cannot @@ -493,7 +493,7 @@ int ZEXPORT deflateInit2_(z_streamp strm, int level, int method, * symbols from which it is being constructed. */ - s->pending_buf = (uchf *) ZALLOC(strm, s->lit_bufsize, 4); + s->pending_buf = (uchf *) ZALLOC(strm, s->lit_bufsize, LIT_BUFS); s->pending_buf_size = (ulg)s->lit_bufsize * 4; if (s->window == Z_NULL || s->prev == Z_NULL || s->head == Z_NULL || @@ -503,8 +503,14 @@ int ZEXPORT deflateInit2_(z_streamp strm, int level, int method, deflateEnd (strm); return Z_MEM_ERROR; } +#ifdef LIT_MEM + s->d_buf = (ushf *)(s->pending_buf + (s->lit_bufsize << 1)); + s->l_buf = s->pending_buf + (s->lit_bufsize << 2); + s->sym_end = s->lit_bufsize - 1; +#else s->sym_buf = s->pending_buf + s->lit_bufsize; s->sym_end = (s->lit_bufsize - 1) * 3; +#endif /* We avoid equality with lit_bufsize*3 because of wraparound at 64K * on 16 bit machines and because stored blocks are restricted to * 64K-1 bytes. @@ -720,9 +726,15 @@ int ZEXPORT deflatePrime(z_streamp strm, int bits, int value) { if (deflateStateCheck(strm)) return Z_STREAM_ERROR; s = strm->state; +#ifdef LIT_MEM + if (bits < 0 || bits > 16 || + (uchf *)s->d_buf < s->pending_out + ((Buf_size + 7) >> 3)) + return Z_BUF_ERROR; +#else if (bits < 0 || bits > 16 || s->sym_buf < s->pending_out + ((Buf_size + 7) >> 3)) return Z_BUF_ERROR; +#endif do { put = Buf_size - s->bi_valid; if (put > bits) @@ -834,13 +846,13 @@ uLong ZEXPORT deflateBound(z_streamp strm, uLong sourceLen) { storelen = sourceLen + (sourceLen >> 5) + (sourceLen >> 7) + (sourceLen >> 11) + 7; - /* if can't get parameters, return larger bound plus a zlib wrapper */ + /* if can't get parameters, return larger bound plus a wrapper */ if (deflateStateCheck(strm)) - return (fixedlen > storelen ? fixedlen : storelen) + 6; + return (fixedlen > storelen ? fixedlen : storelen) + 18; /* compute wrapper length */ s = strm->state; - switch (s->wrap) { + switch (s->wrap < 0 ? -s->wrap : s->wrap) { case 0: /* raw deflate */ wraplen = 0; break; @@ -870,7 +882,7 @@ uLong ZEXPORT deflateBound(z_streamp strm, uLong sourceLen) { break; #endif default: /* for compiler happiness */ - wraplen = 6; + wraplen = 18; } /* if not default parameters, return one of the conservative bounds */ @@ -1294,7 +1306,7 @@ int ZEXPORT deflateCopy(z_streamp dest, z_streamp source) { ds->window = (Bytef *) ZALLOC(dest, ds->w_size, 2*sizeof(Byte)); ds->prev = (Posf *) ZALLOC(dest, ds->w_size, sizeof(Pos)); ds->head = (Posf *) ZALLOC(dest, ds->hash_size, sizeof(Pos)); - ds->pending_buf = (uchf *) ZALLOC(dest, ds->lit_bufsize, 4); + ds->pending_buf = (uchf *) ZALLOC(dest, ds->lit_bufsize, LIT_BUFS); if (ds->window == Z_NULL || ds->prev == Z_NULL || ds->head == Z_NULL || ds->pending_buf == Z_NULL) { @@ -1305,10 +1317,15 @@ int ZEXPORT deflateCopy(z_streamp dest, z_streamp source) { zmemcpy(ds->window, ss->window, ds->w_size * 2 * sizeof(Byte)); zmemcpy((voidpf)ds->prev, (voidpf)ss->prev, ds->w_size * sizeof(Pos)); zmemcpy((voidpf)ds->head, (voidpf)ss->head, ds->hash_size * sizeof(Pos)); - zmemcpy(ds->pending_buf, ss->pending_buf, (uInt)ds->pending_buf_size); + zmemcpy(ds->pending_buf, ss->pending_buf, ds->lit_bufsize * LIT_BUFS); ds->pending_out = ds->pending_buf + (ss->pending_out - ss->pending_buf); +#ifdef LIT_MEM + ds->d_buf = (ushf *)(ds->pending_buf + (ds->lit_bufsize << 1)); + ds->l_buf = ds->pending_buf + (ds->lit_bufsize << 2); +#else ds->sym_buf = ds->pending_buf + ds->lit_bufsize; +#endif ds->l_desc.dyn_tree = ds->dyn_ltree; ds->d_desc.dyn_tree = ds->dyn_dtree; @@ -1539,13 +1556,21 @@ local uInt longest_match(deflate_state *s, IPos cur_match) { */ local void check_match(deflate_state *s, IPos start, IPos match, int length) { /* check that the match is indeed a match */ - if (zmemcmp(s->window + match, - s->window + start, length) != EQUAL) { - fprintf(stderr, " start %u, match %u, length %d\n", - start, match, length); + Bytef *back = s->window + (int)match, *here = s->window + start; + IPos len = length; + if (match == (IPos)-1) { + /* match starts one byte before the current window -- just compare the + subsequent length-1 bytes */ + back++; + here++; + len--; + } + if (zmemcmp(back, here, len) != EQUAL) { + fprintf(stderr, " start %u, match %d, length %d\n", + start, (int)match, length); do { - fprintf(stderr, "%c%c", s->window[match++], s->window[start++]); - } while (--length != 0); + fprintf(stderr, "(%02x %02x)", *back++, *here++); + } while (--len != 0); z_error("invalid match"); } if (z_verbose > 1) { @@ -1610,7 +1635,8 @@ local block_state deflate_stored(deflate_state *s, int flush) { * possible. If flushing, copy the remaining available input to next_out as * stored blocks, if there is enough space. */ - unsigned len, left, have, last = 0; + int last = 0; + unsigned len, left, have; unsigned used = s->strm->avail_in; do { /* Set len to the maximum size block that we can copy directly with the @@ -1646,10 +1672,10 @@ local block_state deflate_stored(deflate_state *s, int flush) { _tr_stored_block(s, (char *)0, 0L, last); /* Replace the lengths in the dummy stored block with len. */ - s->pending_buf[s->pending - 4] = len; - s->pending_buf[s->pending - 3] = len >> 8; - s->pending_buf[s->pending - 2] = ~len; - s->pending_buf[s->pending - 1] = ~len >> 8; + s->pending_buf[s->pending - 4] = (Bytef)len; + s->pending_buf[s->pending - 3] = (Bytef)(len >> 8); + s->pending_buf[s->pending - 2] = (Bytef)~len; + s->pending_buf[s->pending - 1] = (Bytef)(~len >> 8); /* Write the stored block header bytes. */ flush_pending(s->strm); diff --git a/vendor/zlib/deflate.h b/vendor/zlib/deflate.h index 8696791429..300c6ada62 100644 --- a/vendor/zlib/deflate.h +++ b/vendor/zlib/deflate.h @@ -1,5 +1,5 @@ /* deflate.h -- internal compression state - * Copyright (C) 1995-2018 Jean-loup Gailly + * Copyright (C) 1995-2024 Jean-loup Gailly * For conditions of distribution and use, see copyright notice in zlib.h */ @@ -23,6 +23,10 @@ # define GZIP #endif +/* define LIT_MEM to slightly increase the speed of deflate (order 1% to 2%) at + the cost of a larger memory footprint */ +/* #define LIT_MEM */ + /* =========================================================================== * Internal compression state. */ @@ -217,7 +221,14 @@ typedef struct internal_state { /* Depth of each subtree used as tie breaker for trees of equal frequency */ +#ifdef LIT_MEM +# define LIT_BUFS 5 + ushf *d_buf; /* buffer for distances */ + uchf *l_buf; /* buffer for literals/lengths */ +#else +# define LIT_BUFS 4 uchf *sym_buf; /* buffer for distances and literals/lengths */ +#endif uInt lit_bufsize; /* Size of match buffer for literals/lengths. There are 4 reasons for @@ -239,7 +250,7 @@ typedef struct internal_state { * - I can't count above 4 */ - uInt sym_next; /* running index in sym_buf */ + uInt sym_next; /* running index in symbol buffer */ uInt sym_end; /* symbol table full when sym_next reaches this */ ulg opt_len; /* bit length of current block with optimal trees */ @@ -318,6 +329,25 @@ void ZLIB_INTERNAL _tr_stored_block(deflate_state *s, charf *buf, extern const uch ZLIB_INTERNAL _dist_code[]; #endif +#ifdef LIT_MEM +# define _tr_tally_lit(s, c, flush) \ + { uch cc = (c); \ + s->d_buf[s->sym_next] = 0; \ + s->l_buf[s->sym_next++] = cc; \ + s->dyn_ltree[cc].Freq++; \ + flush = (s->sym_next == s->sym_end); \ + } +# define _tr_tally_dist(s, distance, length, flush) \ + { uch len = (uch)(length); \ + ush dist = (ush)(distance); \ + s->d_buf[s->sym_next] = dist; \ + s->l_buf[s->sym_next++] = len; \ + dist--; \ + s->dyn_ltree[_length_code[len]+LITERALS+1].Freq++; \ + s->dyn_dtree[d_code(dist)].Freq++; \ + flush = (s->sym_next == s->sym_end); \ + } +#else # define _tr_tally_lit(s, c, flush) \ { uch cc = (c); \ s->sym_buf[s->sym_next++] = 0; \ @@ -337,6 +367,7 @@ void ZLIB_INTERNAL _tr_stored_block(deflate_state *s, charf *buf, s->dyn_dtree[d_code(dist)].Freq++; \ flush = (s->sym_next == s->sym_end); \ } +#endif #else # define _tr_tally_lit(s, c, flush) flush = _tr_tally(s, 0, c) # define _tr_tally_dist(s, distance, length, flush) \ diff --git a/vendor/zlib/gzguts.h b/vendor/zlib/gzguts.h index f9375047e8..71dea740c6 100644 --- a/vendor/zlib/gzguts.h +++ b/vendor/zlib/gzguts.h @@ -1,5 +1,5 @@ /* gzguts.h -- zlib internal header definitions for gz* operations - * Copyright (C) 2004-2019 Mark Adler + * Copyright (C) 2004-2024 Mark Adler * For conditions of distribution and use, see copyright notice in zlib.h */ @@ -17,6 +17,18 @@ # define ZLIB_INTERNAL #endif +#if defined(_WIN32) +# ifndef WIN32_LEAN_AND_MEAN +# define WIN32_LEAN_AND_MEAN +# endif +# ifndef _CRT_SECURE_NO_WARNINGS +# define _CRT_SECURE_NO_WARNINGS +# endif +# ifndef _CRT_NONSTDC_NO_DEPRECATE +# define _CRT_NONSTDC_NO_DEPRECATE +# endif +#endif + #include #include "zlib.h" #ifdef STDC @@ -25,8 +37,8 @@ # include #endif -#ifndef _POSIX_SOURCE -# define _POSIX_SOURCE +#ifndef _POSIX_C_SOURCE +# define _POSIX_C_SOURCE 200112L #endif #include @@ -36,19 +48,13 @@ #if defined(__TURBOC__) || defined(_MSC_VER) || defined(_WIN32) # include +# include #endif -#if defined(_WIN32) +#if defined(_WIN32) && !defined(WIDECHAR) # define WIDECHAR #endif -#ifdef WINAPI_FAMILY -# define open _open -# define read _read -# define write _write -# define close _close -#endif - #ifdef NO_DEFLATE /* for compatibility with old definition */ # define NO_GZCOMPRESS #endif @@ -72,33 +78,28 @@ #endif #ifndef HAVE_VSNPRINTF -# ifdef MSDOS +# if !defined(NO_vsnprintf) && \ + (defined(MSDOS) || defined(__TURBOC__) || defined(__SASC) || \ + defined(VMS) || defined(__OS400) || defined(__MVS__)) /* vsnprintf may exist on some MS-DOS compilers (DJGPP?), but for now we just assume it doesn't. */ # define NO_vsnprintf # endif -# ifdef __TURBOC__ -# define NO_vsnprintf -# endif # ifdef WIN32 /* In Win32, vsnprintf is available as the "non-ANSI" _vsnprintf. */ -# if !defined(vsnprintf) && !defined(NO_vsnprintf) -# if !defined(_MSC_VER) || ( defined(_MSC_VER) && _MSC_VER < 1500 ) -# define vsnprintf _vsnprintf +# if !defined(_MSC_VER) || ( defined(_MSC_VER) && _MSC_VER < 1500 ) +# ifndef vsnprintf +# define vsnprintf _vsnprintf # endif # endif -# endif -# ifdef __SASC -# define NO_vsnprintf -# endif -# ifdef VMS -# define NO_vsnprintf -# endif -# ifdef __OS400__ -# define NO_vsnprintf -# endif -# ifdef __MVS__ -# define NO_vsnprintf +# elif !defined(__STDC_VERSION__) || __STDC_VERSION__-0 < 199901L +/* Otherwise if C89/90, assume no C99 snprintf() or vsnprintf() */ +# ifndef NO_snprintf +# define NO_snprintf +# endif +# ifndef NO_vsnprintf +# define NO_vsnprintf +# endif # endif #endif @@ -210,9 +211,5 @@ char ZLIB_INTERNAL *gz_strwinerror(DWORD error); /* GT_OFF(x), where x is an unsigned value, is true if x > maximum z_off64_t value -- needed when comparing unsigned to z_off64_t, which is signed (possible z_off64_t types off_t, off64_t, and long are all signed) */ -#ifdef INT_MAX -# define GT_OFF(x) (sizeof(int) == sizeof(z_off64_t) && (x) > INT_MAX) -#else unsigned ZLIB_INTERNAL gz_intmax(void); -# define GT_OFF(x) (sizeof(int) == sizeof(z_off64_t) && (x) > gz_intmax()) -#endif +#define GT_OFF(x) (sizeof(int) == sizeof(z_off64_t) && (x) > gz_intmax()) diff --git a/vendor/zlib/gzlib.c b/vendor/zlib/gzlib.c index 29fc4486fb..baa3e79d41 100644 --- a/vendor/zlib/gzlib.c +++ b/vendor/zlib/gzlib.c @@ -1,19 +1,19 @@ /* gzlib.c -- zlib functions common to reading and writing gzip files - * Copyright (C) 2004-2019 Mark Adler + * Copyright (C) 2004-2024 Mark Adler * For conditions of distribution and use, see copyright notice in zlib.h */ #include "gzguts.h" -#if defined(_WIN32) && !defined(__BORLANDC__) +#if defined(__DJGPP__) +# define LSEEK llseek +#elif defined(_WIN32) && !defined(__BORLANDC__) && !defined(UNDER_CE) # define LSEEK _lseeki64 -#else -#if defined(_LARGEFILE64_SOURCE) && _LFS64_LARGEFILE-0 +#elif defined(_LARGEFILE64_SOURCE) && _LFS64_LARGEFILE-0 # define LSEEK lseek64 #else # define LSEEK lseek #endif -#endif #if defined UNDER_CE @@ -52,7 +52,7 @@ char ZLIB_INTERNAL *gz_strwinerror(DWORD error) { msgbuf[chars] = 0; } - wcstombs(buf, msgbuf, chars + 1); + wcstombs(buf, msgbuf, chars + 1); // assumes buf is big enough LocalFree(msgbuf); } else { @@ -179,11 +179,8 @@ local gzFile gz_open(const void *path, int fd, const char *mode) { /* save the path name for error messages */ #ifdef WIDECHAR - if (fd == -2) { + if (fd == -2) len = wcstombs(NULL, path, 0); - if (len == (z_size_t)-1) - len = 0; - } else #endif len = strlen((const char *)path); @@ -193,18 +190,21 @@ local gzFile gz_open(const void *path, int fd, const char *mode) { return NULL; } #ifdef WIDECHAR - if (fd == -2) + if (fd == -2) { if (len) wcstombs(state->path, path, len + 1); else *(state->path) = 0; + } else #endif + { #if !defined(NO_snprintf) && !defined(NO_vsnprintf) (void)snprintf(state->path, len + 1, "%s", (const char *)path); #else strcpy(state->path, path); #endif + } /* compute the flags for open() */ oflag = @@ -228,11 +228,14 @@ local gzFile gz_open(const void *path, int fd, const char *mode) { O_APPEND))); /* open the file with the appropriate flags (or just use fd) */ - state->fd = fd > -1 ? fd : ( + if (fd == -1) + state->fd = open((const char *)path, oflag, 0666); #ifdef WIDECHAR - fd == -2 ? _wopen(path, oflag, 0666) : + else if (fd == -2) + state->fd = _wopen(path, oflag, _S_IREAD | _S_IWRITE); #endif - open((const char *)path, oflag, 0666)); + else + state->fd = fd; if (state->fd == -1) { free(state->path); free(state); @@ -563,20 +566,20 @@ void ZLIB_INTERNAL gz_error(gz_statep state, int err, const char *msg) { #endif } -#ifndef INT_MAX /* portably return maximum value for an int (when limits.h presumed not available) -- we need to do this to cover cases where 2's complement not used, since C standard permits 1's complement and sign-bit representations, otherwise we could just use ((unsigned)-1) >> 1 */ unsigned ZLIB_INTERNAL gz_intmax(void) { - unsigned p, q; - - p = 1; +#ifdef INT_MAX + return INT_MAX; +#else + unsigned p = 1, q; do { q = p; p <<= 1; p++; } while (p > q); return q >> 1; -} #endif +} diff --git a/vendor/zlib/gzread.c b/vendor/zlib/gzread.c index 4168cbc887..2d4ca4290d 100644 --- a/vendor/zlib/gzread.c +++ b/vendor/zlib/gzread.c @@ -374,7 +374,8 @@ int ZEXPORT gzread(gzFile file, voidp buf, unsigned len) { } /* -- see zlib.h -- */ -z_size_t ZEXPORT gzfread(voidp buf, z_size_t size, z_size_t nitems, gzFile file) { +z_size_t ZEXPORT gzfread(voidp buf, z_size_t size, z_size_t nitems, + gzFile file) { z_size_t len; gz_statep state; diff --git a/vendor/zlib/inflate.c b/vendor/zlib/inflate.c index b0757a9b24..94ecff015a 100644 --- a/vendor/zlib/inflate.c +++ b/vendor/zlib/inflate.c @@ -1387,7 +1387,7 @@ int ZEXPORT inflateSync(z_streamp strm) { /* if first time, start search in bit buffer */ if (state->mode != SYNC) { state->mode = SYNC; - state->hold <<= state->bits & 7; + state->hold >>= state->bits & 7; state->bits -= state->bits & 7; len = 0; while (state->bits >= 8) { diff --git a/vendor/zlib/inflate.h b/vendor/zlib/inflate.h index f127b6b1fa..f758e0dcc1 100644 --- a/vendor/zlib/inflate.h +++ b/vendor/zlib/inflate.h @@ -100,7 +100,7 @@ struct inflate_state { unsigned char FAR *window; /* allocated sliding window, if needed */ /* bit accumulator */ unsigned long hold; /* input bit accumulator */ - unsigned bits; /* number of bits in "in" */ + unsigned bits; /* number of bits in hold */ /* for string and stored block copying */ unsigned length; /* literal or length of data to copy */ unsigned offset; /* distance back to copy string from */ diff --git a/vendor/zlib/inftrees.c b/vendor/zlib/inftrees.c index 8a208c2daa..a127e6b8f7 100644 --- a/vendor/zlib/inftrees.c +++ b/vendor/zlib/inftrees.c @@ -1,5 +1,5 @@ /* inftrees.c -- generate Huffman trees for efficient decoding - * Copyright (C) 1995-2023 Mark Adler + * Copyright (C) 1995-2024 Mark Adler * For conditions of distribution and use, see copyright notice in zlib.h */ @@ -9,7 +9,7 @@ #define MAXBITS 15 const char inflate_copyright[] = - " inflate 1.3 Copyright 1995-2023 Mark Adler "; + " inflate 1.3.1.1 Copyright 1995-2024 Mark Adler "; /* If you use the zlib library in a product, an acknowledgment is welcome in the documentation of your product. If for some reason you cannot @@ -57,7 +57,7 @@ int ZLIB_INTERNAL inflate_table(codetype type, unsigned short FAR *lens, 35, 43, 51, 59, 67, 83, 99, 115, 131, 163, 195, 227, 258, 0, 0}; static const unsigned short lext[31] = { /* Length codes 257..285 extra */ 16, 16, 16, 16, 16, 16, 16, 16, 17, 17, 17, 17, 18, 18, 18, 18, - 19, 19, 19, 19, 20, 20, 20, 20, 21, 21, 21, 21, 16, 198, 203}; + 19, 19, 19, 19, 20, 20, 20, 20, 21, 21, 21, 21, 16, 73, 200}; static const unsigned short dbase[32] = { /* Distance codes 0..29 base */ 1, 2, 3, 4, 5, 7, 9, 13, 17, 25, 33, 49, 65, 97, 129, 193, 257, 385, 513, 769, 1025, 1537, 2049, 3073, 4097, 6145, diff --git a/vendor/zlib/inftrees.h b/vendor/zlib/inftrees.h index a10712d8cb..396f74b5da 100644 --- a/vendor/zlib/inftrees.h +++ b/vendor/zlib/inftrees.h @@ -41,8 +41,8 @@ typedef struct { examples/enough.c found in the zlib distribution. The arguments to that program are the number of symbols, the initial root table size, and the maximum bit length of a code. "enough 286 9 15" for literal/length codes - returns returns 852, and "enough 30 6 15" for distance codes returns 592. - The initial root table size (9 or 6) is found in the fifth argument of the + returns 852, and "enough 30 6 15" for distance codes returns 592. The + initial root table size (9 or 6) is found in the fifth argument of the inflate_table() calls in inflate.c and infback.c. If the root table size is changed, then these maximum sizes would be need to be recalculated and updated. */ diff --git a/vendor/zlib/trees.c b/vendor/zlib/trees.c index 8dbdc40bac..979ae4100a 100644 --- a/vendor/zlib/trees.c +++ b/vendor/zlib/trees.c @@ -1,5 +1,5 @@ /* trees.c -- output deflated data using Huffman coding - * Copyright (C) 1995-2021 Jean-loup Gailly + * Copyright (C) 1995-2024 Jean-loup Gailly * detect_data_type() function provided freely by Cosmin Truta, 2006 * For conditions of distribution and use, see copyright notice in zlib.h */ @@ -724,7 +724,7 @@ local void scan_tree(deflate_state *s, ct_data *tree, int max_code) { if (++count < max_count && curlen == nextlen) { continue; } else if (count < min_count) { - s->bl_tree[curlen].Freq += count; + s->bl_tree[curlen].Freq += (ush)count; } else if (curlen != 0) { if (curlen != prevlen) s->bl_tree[curlen].Freq++; s->bl_tree[REP_3_6].Freq++; @@ -899,14 +899,19 @@ local void compress_block(deflate_state *s, const ct_data *ltree, const ct_data *dtree) { unsigned dist; /* distance of matched string */ int lc; /* match length or unmatched char (if dist == 0) */ - unsigned sx = 0; /* running index in sym_buf */ + unsigned sx = 0; /* running index in symbol buffers */ unsigned code; /* the code to send */ int extra; /* number of extra bits to send */ if (s->sym_next != 0) do { +#ifdef LIT_MEM + dist = s->d_buf[sx]; + lc = s->l_buf[sx++]; +#else dist = s->sym_buf[sx++] & 0xff; dist += (unsigned)(s->sym_buf[sx++] & 0xff) << 8; lc = s->sym_buf[sx++]; +#endif if (dist == 0) { send_code(s, lc, ltree); /* send a literal byte */ Tracecv(isgraph(lc), (stderr," '%c' ", lc)); @@ -931,8 +936,12 @@ local void compress_block(deflate_state *s, const ct_data *ltree, } } /* literal or match pair ? */ - /* Check that the overlay between pending_buf and sym_buf is ok: */ + /* Check for no overlay of pending_buf on needed symbols */ +#ifdef LIT_MEM + Assert(s->pending < 2 * (s->lit_bufsize + sx), "pendingBuf overflow"); +#else Assert(s->pending < s->lit_bufsize + sx, "pendingBuf overflow"); +#endif } while (sx < s->sym_next); @@ -1082,9 +1091,14 @@ void ZLIB_INTERNAL _tr_flush_block(deflate_state *s, charf *buf, * the current block must be flushed. */ int ZLIB_INTERNAL _tr_tally(deflate_state *s, unsigned dist, unsigned lc) { +#ifdef LIT_MEM + s->d_buf[s->sym_next] = (ush)dist; + s->l_buf[s->sym_next++] = (uch)lc; +#else s->sym_buf[s->sym_next++] = (uch)dist; s->sym_buf[s->sym_next++] = (uch)(dist >> 8); s->sym_buf[s->sym_next++] = (uch)lc; +#endif if (dist == 0) { /* lc is the unmatched char */ s->dyn_ltree[lc].Freq++; diff --git a/vendor/zlib/zconf.h b/vendor/zlib/zconf.h index fb76ffe312..ea3b6d685e 100644 --- a/vendor/zlib/zconf.h +++ b/vendor/zlib/zconf.h @@ -1,5 +1,5 @@ /* zconf.h -- configuration of the zlib compression library - * Copyright (C) 1995-2016 Jean-loup Gailly, Mark Adler + * Copyright (C) 1995-2024 Jean-loup Gailly, Mark Adler * For conditions of distribution and use, see copyright notice in zlib.h */ @@ -300,14 +300,6 @@ # endif #endif -#ifndef Z_ARG /* function prototypes for stdarg */ -# if defined(STDC) || defined(Z_HAVE_STDARG_H) -# define Z_ARG(args) args -# else -# define Z_ARG(args) () -# endif -#endif - /* The following definitions for FAR are needed only for MSDOS mixed * model programming (small or medium model with some far allocations). * This was tested only with MSC; for other MSDOS compilers you may have @@ -478,12 +470,8 @@ typedef uLong FAR uLongf; #endif #ifndef Z_HAVE_UNISTD_H -# ifdef __WATCOMC__ -# define Z_HAVE_UNISTD_H -# endif -#endif -#ifndef Z_HAVE_UNISTD_H -# if defined(_LARGEFILE64_SOURCE) && !defined(_WIN32) +# if defined(__WATCOMC__) || defined(__GO32__) || \ + (defined(_LARGEFILE64_SOURCE) && !defined(_WIN32)) # define Z_HAVE_UNISTD_H # endif #endif @@ -523,12 +511,14 @@ typedef uLong FAR uLongf; #if !defined(_WIN32) && defined(Z_LARGE64) # define z_off64_t off64_t +#elif defined(__MINGW32__) +# define z_off64_t long long +#elif defined(_WIN32) && !defined(__GNUC__) +# define z_off64_t __int64 +#elif defined(__GO32__) +# define z_off64_t offset_t #else -# if defined(_WIN32) && !defined(__GNUC__) -# define z_off64_t __int64 -# else -# define z_off64_t z_off_t -# endif +# define z_off64_t z_off_t #endif /* MVS linker does not support external names larger than 8 bytes */ diff --git a/vendor/zlib/zlib.h b/vendor/zlib/zlib.h index 6b7244f994..592d453f5f 100644 --- a/vendor/zlib/zlib.h +++ b/vendor/zlib/zlib.h @@ -1,7 +1,7 @@ /* zlib.h -- interface of the 'zlib' general purpose compression library - version 1.3, August 18th, 2023 + version 1.3.1.1, January xxth, 2024 - Copyright (C) 1995-2023 Jean-loup Gailly and Mark Adler + Copyright (C) 1995-2024 Jean-loup Gailly and Mark Adler This software is provided 'as-is', without any express or implied warranty. In no event will the authors be held liable for any damages @@ -37,12 +37,12 @@ extern "C" { #endif -#define ZLIB_VERSION "1.3" -#define ZLIB_VERNUM 0x1300 +#define ZLIB_VERSION "1.3.1.1-motley" +#define ZLIB_VERNUM 0x1311 #define ZLIB_VER_MAJOR 1 #define ZLIB_VER_MINOR 3 -#define ZLIB_VER_REVISION 0 -#define ZLIB_VER_SUBREVISION 0 +#define ZLIB_VER_REVISION 1 +#define ZLIB_VER_SUBREVISION 1 /* The 'zlib' compression library provides in-memory compression and @@ -587,18 +587,21 @@ ZEXTERN int ZEXPORT deflateInit2(z_streamp strm, The strategy parameter is used to tune the compression algorithm. Use the value Z_DEFAULT_STRATEGY for normal data, Z_FILTERED for data produced by a - filter (or predictor), Z_HUFFMAN_ONLY to force Huffman encoding only (no - string match), or Z_RLE to limit match distances to one (run-length - encoding). Filtered data consists mostly of small values with a somewhat - random distribution. In this case, the compression algorithm is tuned to - compress them better. The effect of Z_FILTERED is to force more Huffman - coding and less string matching; it is somewhat intermediate between - Z_DEFAULT_STRATEGY and Z_HUFFMAN_ONLY. Z_RLE is designed to be almost as - fast as Z_HUFFMAN_ONLY, but give better compression for PNG image data. The - strategy parameter only affects the compression ratio but not the - correctness of the compressed output even if it is not set appropriately. - Z_FIXED prevents the use of dynamic Huffman codes, allowing for a simpler - decoder for special applications. + filter (or predictor), Z_RLE to limit match distances to one (run-length + encoding), or Z_HUFFMAN_ONLY to force Huffman encoding only (no string + matching). Filtered data consists mostly of small values with a somewhat + random distribution, as produced by the PNG filters. In this case, the + compression algorithm is tuned to compress them better. The effect of + Z_FILTERED is to force more Huffman coding and less string matching than the + default; it is intermediate between Z_DEFAULT_STRATEGY and Z_HUFFMAN_ONLY. + Z_RLE is almost as fast as Z_HUFFMAN_ONLY, but should give better + compression for PNG image data than Huffman only. The degree of string + matching from most to none is: Z_DEFAULT_STRATEGY, Z_FILTERED, Z_RLE, then + Z_HUFFMAN. The strategy parameter affects the compression ratio but never + the correctness of the compressed output, even if it is not set optimally + for the given data. Z_FIXED uses the default string matching, but prevents + the use of dynamic Huffman codes, allowing for a simpler decoder for special + applications. deflateInit2 returns Z_OK if success, Z_MEM_ERROR if there was not enough memory, Z_STREAM_ERROR if any parameter is invalid (such as an invalid @@ -936,10 +939,10 @@ ZEXTERN int ZEXPORT inflateSync(z_streamp strm); inflateSync returns Z_OK if a possible full flush point has been found, Z_BUF_ERROR if no more input was provided, Z_DATA_ERROR if no flush point has been found, or Z_STREAM_ERROR if the stream structure was inconsistent. - In the success case, the application may save the current current value of - total_in which indicates where valid compressed data was found. In the - error case, the application may repeatedly call inflateSync, providing more - input each time, until success or end of the input data. + In the success case, the application may save the current value of total_in + which indicates where valid compressed data was found. In the error case, + the application may repeatedly call inflateSync, providing more input each + time, until success or end of the input data. */ ZEXTERN int ZEXPORT inflateCopy(z_streamp dest, @@ -1758,14 +1761,14 @@ ZEXTERN uLong ZEXPORT crc32_combine(uLong crc1, uLong crc2, z_off_t len2); seq1 and seq2 with lengths len1 and len2, CRC-32 check values were calculated for each, crc1 and crc2. crc32_combine() returns the CRC-32 check value of seq1 and seq2 concatenated, requiring only crc1, crc2, and - len2. + len2. len2 must be non-negative. */ /* ZEXTERN uLong ZEXPORT crc32_combine_gen(z_off_t len2); Return the operator corresponding to length len2, to be used with - crc32_combine_op(). + crc32_combine_op(). len2 must be non-negative. */ ZEXTERN uLong ZEXPORT crc32_combine_op(uLong crc1, uLong crc2, uLong op); @@ -1888,9 +1891,9 @@ ZEXTERN int ZEXPORT gzgetc_(gzFile file); /* backward compatibility */ ZEXTERN z_off_t ZEXPORT gzseek64(gzFile, z_off_t, int); ZEXTERN z_off_t ZEXPORT gztell64(gzFile); ZEXTERN z_off_t ZEXPORT gzoffset64(gzFile); - ZEXTERN uLong ZEXPORT adler32_combine64(uLong, uLong, z_off_t); - ZEXTERN uLong ZEXPORT crc32_combine64(uLong, uLong, z_off_t); - ZEXTERN uLong ZEXPORT crc32_combine_gen64(z_off_t); + ZEXTERN uLong ZEXPORT adler32_combine64(uLong, uLong, z_off64_t); + ZEXTERN uLong ZEXPORT crc32_combine64(uLong, uLong, z_off64_t); + ZEXTERN uLong ZEXPORT crc32_combine_gen64(z_off64_t); # endif #else ZEXTERN gzFile ZEXPORT gzopen(const char *, const char *); diff --git a/vendor/zlib/zutil.h b/vendor/zlib/zutil.h index 902a304cc2..4f22299a0f 100644 --- a/vendor/zlib/zutil.h +++ b/vendor/zlib/zutil.h @@ -1,5 +1,5 @@ /* zutil.h -- internal interface and configuration of the compression library - * Copyright (C) 1995-2022 Jean-loup Gailly, Mark Adler + * Copyright (C) 1995-2024 Jean-loup Gailly, Mark Adler * For conditions of distribution and use, see copyright notice in zlib.h */ @@ -56,7 +56,7 @@ typedef unsigned long ulg; extern z_const char * const z_errmsg[10]; /* indexed by 2-zlib_error */ /* (size given to avoid silly warnings with Visual C++) */ -#define ERR_MSG(err) z_errmsg[Z_NEED_DICT-(err)] +#define ERR_MSG(err) z_errmsg[(err) < -6 || (err) > 2 ? 9 : 2 - (err)] #define ERR_RETURN(strm,err) \ return (strm->msg = ERR_MSG(err), (err)) @@ -137,20 +137,11 @@ extern z_const char * const z_errmsg[10]; /* indexed by 2-zlib_error */ # endif #endif -#if defined(MACOS) || defined(TARGET_OS_MAC) +#if defined(MACOS) # define OS_CODE 7 -# ifndef Z_SOLO -# if defined(__MWERKS__) && __dest_os != __be_os && __dest_os != __win32_os -# include /* for fdopen */ -# else -# ifndef fdopen -# define fdopen(fd,mode) NULL /* No fdopen() */ -# endif -# endif -# endif #endif -#ifdef __acorn +#if defined(__acorn) || defined(__riscos) # define OS_CODE 13 #endif @@ -170,18 +161,6 @@ extern z_const char * const z_errmsg[10]; /* indexed by 2-zlib_error */ # define OS_CODE 19 #endif -#if defined(_BEOS_) || defined(RISCOS) -# define fdopen(fd,mode) NULL /* No fdopen() */ -#endif - -#if (defined(_MSC_VER) && (_MSC_VER > 600)) && !defined __INTERIX -# if defined(_WIN32_WCE) -# define fdopen(fd,mode) NULL /* No fdopen() */ -# else -# define fdopen(fd,type) _fdopen(fd,type) -# endif -#endif - #if defined(__BORLANDC__) && !defined(MSDOS) #pragma warn -8004 #pragma warn -8008 @@ -189,11 +168,10 @@ extern z_const char * const z_errmsg[10]; /* indexed by 2-zlib_error */ #endif /* provide prototypes for these when building zlib without LFS */ -#if !defined(_WIN32) && \ - (!defined(_LARGEFILE64_SOURCE) || _LFS64_LARGEFILE-0 == 0) - ZEXTERN uLong ZEXPORT adler32_combine64(uLong, uLong, z_off_t); - ZEXTERN uLong ZEXPORT crc32_combine64(uLong, uLong, z_off_t); - ZEXTERN uLong ZEXPORT crc32_combine_gen64(z_off_t); +#ifndef Z_LARGE64 + ZEXTERN uLong ZEXPORT adler32_combine64(uLong, uLong, z_off64_t); + ZEXTERN uLong ZEXPORT crc32_combine64(uLong, uLong, z_off64_t); + ZEXTERN uLong ZEXPORT crc32_combine_gen64(z_off64_t); #endif /* common defaults */